diff --git a/.bazelignore b/.bazelignore new file mode 100644 index 0000000000000..201f851370eb6 --- /dev/null +++ b/.bazelignore @@ -0,0 +1,3 @@ +# These are fetched as external repositories. +third_party/benchmark +third_party/googletest diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000000..83860865a37c5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,37 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + + + +**What version of protobuf and what language are you using?** +Version: master/v3.6.0/v3.5.0 etc. +Language: C++/Java/Python/C#/Ruby/PHP/Objective-C/Javascript + +**What operating system (Linux, Windows, ...) and version?** + +**What runtime / compiler are you using (e.g., python version or gcc version)** + +**What did you do?** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**What did you expect to see** + +**What did you see instead?** + +Make sure you include information that can help us debug (full error message, exception listing, stack trace, logs). + +**Anything else we should know about your project / environment** diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000000..28b9bc97ce81e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,28 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + + + + +**What language does this apply to?** +If it's a proto syntax change, is it for proto2 or proto3? +If it's about generated code change, what programming language? + +**Describe the problem you are trying to solve.** + +**Describe the solution you'd like** + +**Describe alternatives you've considered** + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/mergeable.yml b/.github/mergeable.yml new file mode 100644 index 0000000000000..8577f086ee216 --- /dev/null +++ b/.github/mergeable.yml @@ -0,0 +1,18 @@ +mergeable: + pull_requests: + label: + and: + - must_exclude: + regex: '^disposition/DO NOT MERGE' + message: 'Pull request marked not mergeable' + - or: + - and: + - must_include: + regex: 'release notes: yes' + message: 'Please include release notes: yes' + - must_include: + regex: '^(c#|c\+\+|cleanup|conformance tests|integration|java|javascript|go|objective-c|php|python|ruby|bazel|cmake|protoc)' + message: 'Please include at least a language label (e.g., c++, java, python). Or apply one of the following labels: bazel, cmake, cleanup, conformance tests, integration, protoc.' + - must_include: + regex: 'release notes: no' + message: 'Please include release notes: no' diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml new file mode 100644 index 0000000000000..a138098c94630 --- /dev/null +++ b/.github/workflows/codespell.yml @@ -0,0 +1,16 @@ +# GitHub Action to automate the identification of common misspellings in text files. +# https://github.com/codespell-project/actions-codespell +# https://github.com/codespell-project/codespell +name: codespell +on: [push, pull_request] +jobs: + codespell: + name: Check for spelling errors + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: codespell-project/actions-codespell@master + with: + check_filenames: true + skip: ./.git,./conformance/third_party,*.snk,*.pb,*.pb.cc,*.pb.h,./src/google/protobuf/testdata,./objectivec/Tests,./python/compatibility_tests/v2.5.0/tests/google/protobuf/internal + ignore_words_list: "alow,alse,ba,cleare,copyable,cloneable,dedup,dur,errorprone,files',fo,fundementals,hel,importd,inout,leapyear,nd,nin,ois,ons,parseable,process',te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od" diff --git a/.gitignore b/.gitignore index fdc52bf746421..44ab2d49ef489 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,7 @@ m4/lt~obsolete.m4 autom4te.cache # downloaded files -gmock +/gmock # in-tree configure-generated files Makefile @@ -47,19 +47,17 @@ any_test.pb.* map*unittest.pb.* unittest*.pb.* cpp_test*.pb.* -src/google/protobuf/compiler/js/well_known_types_embed.cc src/google/protobuf/util/**/*.pb.cc src/google/protobuf/util/**/*.pb.h *.pyc *.egg-info *_pb2.py -python/*.egg +python/**/*.egg python/.eggs/ python/.tox python/build/ -python/google/protobuf/compiler/ -python/google/protobuf/util/ +python/docs/_build/ src/js_embed src/protoc @@ -106,7 +104,7 @@ build_msvc # needed to trigger "pod install" to rerun the preinstall commands. Pods/ -# Comformance test output +# Conformance test output conformance/.libs/ conformance/com/ conformance/conformance-cpp @@ -120,6 +118,7 @@ conformance/Conformance.pbobjc.h conformance/Conformance.pbobjc.m conformance/conformance_pb.js conformance/conformance_pb.rb +conformance/core conformance/failing_tests.txt conformance/google/ conformance/google-protobuf/ @@ -138,20 +137,33 @@ conformance/*.class # php test output composer.lock +php/.phpunit.result.cache +php/tests/.phpunit.result.cache php/tests/generated/ php/tests/old_protoc +php/tests/phpunit-9.phar php/tests/protobuf/ +php/tests/core +php/tests/vgcore* +php/tests/multirequest.result +php/tests/nohup.out +php/tests/.phpunit.result.cache +php/tests/phpunit-* php/ext/google/protobuf/.libs/ php/ext/google/protobuf/Makefile.fragments php/ext/google/protobuf/Makefile.global php/ext/google/protobuf/Makefile.objects php/ext/google/protobuf/acinclude.m4 php/ext/google/protobuf/build/ +php/ext/google/protobuf/bundled_php.c php/ext/google/protobuf/config.h +php/ext/google/protobuf/config.h.in~ php/ext/google/protobuf/config.nice +php/ext/google/protobuf/configure.ac php/ext/google/protobuf/configure.in php/ext/google/protobuf/mkinstalldirs php/ext/google/protobuf/run-tests.php +php/ext/google/protobuf/third_party/ vendor/ # JavaScript artifacts @@ -171,3 +183,40 @@ js/testproto_libs2.js # Ignore the bazel symlinks /bazel-* + +# ruby test output +ruby/lib/ +ruby/tests/basic_test_pb.rb +ruby/tests/basic_test_proto2_pb.rb +ruby/tests/generated_code_pb.rb +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/test_import_proto2_pb.rb +ruby/tests/test_ruby_package_proto2_pb.rb +ruby/Gemfile.lock +ruby/compatibility_tests/v3.0.0/protoc +ruby/compatibility_tests/v3.0.0/tests/generated_code_pb.rb +ruby/compatibility_tests/v3.0.0/tests/test_import_pb.rb + +# IntelliJ CLion Config files and build output +cmake/.idea +cmake/cmake-build-debug/ + +# Common build subdirectories. +./.build/ +./_build/ + +# Visual Studio 2017 +.vs + +# Visual Studio Code +/.vscode/ + +# IntelliJ +.idea +*.iml + +# BenchmarkDotNet +BenchmarkDotNet.Artifacts/ diff --git a/.gitmodules b/.gitmodules index 55a47ceafefff..bcd125a49582a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "third_party/benchmark"] path = third_party/benchmark url = https://github.com/google/benchmark.git +[submodule "third_party/googletest"] + path = third_party/googletest + url = https://github.com/google/googletest.git + ignore = dirty diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000000000..88f4c100f36a1 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,22 @@ +# .readthedocs.yml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +sphinx: + configuration: python/docs/conf.py + fail_on_warning: false + +# Setup build requirements for docs. +# Use conda so that we can install the latest libprotobuf package without +# having to build from scratch just for docs builds. +conda: + environment: python/docs/environment.yml + +python: + version: 3.7 + install: + - method: setuptools + path: python diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d49e0a71315e8..0000000000000 --- a/.travis.yml +++ /dev/null @@ -1,91 +0,0 @@ -sudo: required -dist: trusty -# Note: travis currently does not support listing more than one language so -# this cheats and claims to only be cpp. If they add multiple language -# support, this should probably get updated to install steps and/or -# rvm/gemfile/jdk/etc. entries rather than manually doing the work. -language: cpp -os: - - osx -# The Objective C build needs Xcode 7.0 or later. -osx_image: xcode8.1 -script: - - ./tests.sh $CONFIG -env: - - CONFIG=cpp - - CONFIG=cpp_distcheck - - CONFIG=golang - - CONFIG=java_jdk7 - - CONFIG=java_oracle7 - - CONFIG=javanano_jdk7 - - CONFIG=javanano_oracle7 - - CONFIG=javascript - # iOS build log was starting to choke travis UI, so split to cover the - # Xcode Debug and Release Configurations independently. - - CONFIG=objectivec_ios_debug - - CONFIG=objectivec_ios_release - - CONFIG=objectivec_osx - - CONFIG=objectivec_cocoapods_integration - - CONFIG=python - - CONFIG=python_cpp - - CONFIG=ruby21 - - CONFIG=ruby22 - - CONFIG=jruby - - CONFIG=php5.6_mac - - CONFIG=php7.0_mac -matrix: - exclude: - # It's nontrivial to programmatically install a new JDK from the command - # line on OS X, so we rely on testing on Linux for Java code. - - os: osx - env: CONFIG=java_jdk7 - - os: osx - env: CONFIG=java_oracle7 - - os: osx - env: CONFIG=javanano_jdk7 - - os: osx - env: CONFIG=javanano_oracle7 - # Requires installing golang, currently travis.sh is doing that with apt-get - # which doesn't work on OS X. - - os: osx - env: CONFIG=golang - include: - # The dotnet environment requires Ubuntu 14.04 or 16.04. This - # configuration is effectively an "extra" one, outside the - # autogenerated matrix. - - os: linux - env: CONFIG=csharp - language: csharp - dist: trusty - dotnet: 1.0.1 - mono: none - # This test is kept on travis because it doesn't play nicely with other - # tests on jenkins running in parallel. - - os: linux - env: CONFIG=cpp_distcheck - # The Java compatibility test currently only runs on Linux because it will - # fetch pre-built Linux protoc binaries in the test. - - os: linux - env: CONFIG=java_compatibility - # The Python compatibility test currently only runs on Linux because it will - # fetch pre-built Linux protoc binaries in the test. - - os: linux - env: CONFIG=python_compatibility - allow_failures: - # These currently do not work on OS X but are being worked on by @haberman. - - os: osx - env: CONFIG=ruby22 - - os: osx - env: CONFIG=jruby - # https://github.com/google/protobuf/issues/1253 - Started failing when - # we moved to an OS X image that is 10.11. - - os: osx - env: CONFIG=python_cpp - # Mark the iOS test as flakey as xcodebuild some times fails to start the - # iOS Simulator. - - os: osx - env: CONFIG=objectivec_ios_debug - - os: osx - env: CONFIG=objectivec_ios_release -notifications: - email: false diff --git a/BUILD b/BUILD index cacd2375d11f8..1124321602b50 100644 --- a/BUILD +++ b/BUILD @@ -1,116 +1,188 @@ -# Bazel (http://bazel.io/) BUILD file for Protobuf. +# Bazel (https://bazel.build/) BUILD file for Protobuf. + +load("@bazel_skylib//rules:common_settings.bzl", "string_flag") +load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test", "objc_library", native_cc_proto_library = "cc_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain", "proto_library") +load("@rules_python//python:defs.bzl", "py_library") +load(":cc_proto_blacklist_test.bzl", "cc_proto_blacklist_test") licenses(["notice"]) exports_files(["LICENSE"]) +################################################################################ +# build configuration +################################################################################ + +# TODO(yannic): Remove in 3.14.0. +string_flag( + name = "incompatible_use_com_google_googletest", + build_setting_default = "true", + values = ["true", "false"] +) + +config_setting( + name = "use_com_google_googletest", + flag_values = { + "//:incompatible_use_com_google_googletest": "true" + }, +) + +GTEST = select({ + "//:use_com_google_googletest": [ + "@com_google_googletest//:gtest", + ], + "//conditions:default": [ + "//external:gtest", + ], +}) + +GTEST_MAIN = select({ + "//:use_com_google_googletest": [ + "@com_google_googletest//:gtest_main", + ], + "//conditions:default": [ + "//external:gtest_main", + ], +}) + +################################################################################ +# ZLIB configuration +################################################################################ + +ZLIB_DEPS = ["@zlib//:zlib"] + ################################################################################ # Protobuf Runtime Library ################################################################################ -WIN_COPTS = [ +MSVC_COPTS = [ "/DHAVE_PTHREAD", - "/wd4018", # -Wno-sign-compare - "/wd4514", # -Wno-unused-function + "/wd4018", # -Wno-sign-compare + "/wd4065", # switch statement contains 'default' but no 'case' labels + "/wd4146", # unary minus operator applied to unsigned type, result still unsigned + "/wd4244", # 'conversion' conversion from 'type1' to 'type2', possible loss of data + "/wd4251", # 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2' + "/wd4267", # 'var' : conversion from 'size_t' to 'type', possible loss of data + "/wd4305", # 'identifier' : truncation from 'type1' to 'type2' + "/wd4307", # 'operator' : integral constant overflow + "/wd4309", # 'conversion' : truncation of constant value + "/wd4334", # 'operator' : result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?) + "/wd4355", # 'this' : used in base member initializer list + "/wd4506", # no definition for inline function 'function' + "/wd4514", # -Wno-unused-function + "/wd4800", # 'type' : forcing value to bool 'true' or 'false' (performance warning) + "/wd4996", # The compiler encountered a deprecated declaration. ] COPTS = select({ - ":windows" : WIN_COPTS, - ":windows_msvc" : WIN_COPTS, + ":msvc": MSVC_COPTS, "//conditions:default": [ "-DHAVE_PTHREAD", - "-Wall", - "-Wwrite-strings", + "-DHAVE_ZLIB", "-Woverloaded-virtual", "-Wno-sign-compare", "-Wno-unused-function", + # Prevents ISO C++ const string assignment warnings for pyext sources. + "-Wno-write-strings", + "-Wno-deprecated-declarations", ], }) +load(":compiler_config_setting.bzl", "create_compiler_config_setting") + +create_compiler_config_setting( + name = "msvc", + value = "msvc-cl", + visibility = [ + # Public, but Protobuf only visibility. + "//:__subpackages__", + ], +) + config_setting( - name = "windows", - values = { "cpu": "x64_windows" }, + name = "android", + values = { + "crosstool_top": "//external:android/crosstool", + }, + visibility = [ + # Public, but Protobuf only visibility. + "//:__subpackages__", + ], ) config_setting( - name = "windows_msvc", - values = { "cpu": "x64_windows_msvc" }, + name = "android-libcpp", + values = { + "crosstool_top": "@androidndk//:toolchain-libcpp", + }, + visibility = [ + # Public, but Protobuf only visibility. + "//:__subpackages__", + ], ) config_setting( - name = "android", + name = "android-gnu-libstdcpp", values = { - "crosstool_top": "//external:android/crosstool", + "crosstool_top": "@androidndk//:toolchain-gnu-libstdcpp", }, + visibility = [ + # Public, but Protobuf only visibility. + "//:__subpackages__", + ], ) -# Android builds do not need to link in a separate pthread library. +# Android and MSVC builds do not need to link in a separate pthread library. LINK_OPTS = select({ ":android": [], - "//conditions:default": ["-lpthread", "-lm"], + ":android-libcpp": [], + ":android-gnu-libstdcpp": [], + ":msvc": [ + # Suppress linker warnings about files with no symbols defined. + "-ignore:4221", + ], + "//conditions:default": [ + "-lpthread", + "-lm", + ], }) load( ":protobuf.bzl", + "adapt_proto_library", "cc_proto_library", - "py_proto_library", "internal_copied_filegroup", "internal_gen_well_known_protos_java", "internal_protobuf_py_tests", + "py_proto_library", ) -config_setting( - name = "ios_armv7", - values = { - "ios_cpu": "armv7", - }, -) - -config_setting( - name = "ios_armv7s", - values = { - "ios_cpu": "armv7s", - }, -) - -config_setting( - name = "ios_arm64", - values = { - "ios_cpu": "arm64", - }, -) - -IOS_ARM_COPTS = [ - "-DOS_IOS", - "-miphoneos-version-min=7.0", - "-arch armv7", - "-arch armv7s", - "-arch arm64", - "-D__thread=", - "-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.2.sdk/", -] - cc_library( name = "protobuf_lite", srcs = [ # AUTOGEN(protobuf_lite_srcs) + "src/google/protobuf/any_lite.cc", "src/google/protobuf/arena.cc", "src/google/protobuf/arenastring.cc", "src/google/protobuf/extension_set.cc", + "src/google/protobuf/generated_enum_util.cc", "src/google/protobuf/generated_message_table_driven_lite.cc", "src/google/protobuf/generated_message_util.cc", + "src/google/protobuf/implicit_weak_message.cc", "src/google/protobuf/io/coded_stream.cc", + "src/google/protobuf/io/io_win32.cc", + "src/google/protobuf/io/strtod.cc", "src/google/protobuf/io/zero_copy_stream.cc", + "src/google/protobuf/io/zero_copy_stream_impl.cc", "src/google/protobuf/io/zero_copy_stream_impl_lite.cc", + "src/google/protobuf/map.cc", "src/google/protobuf/message_lite.cc", + "src/google/protobuf/parse_context.cc", "src/google/protobuf/repeated_field.cc", - "src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc", - "src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc", "src/google/protobuf/stubs/bytestream.cc", "src/google/protobuf/stubs/common.cc", "src/google/protobuf/stubs/int128.cc", - "src/google/protobuf/stubs/io_win32.cc", - "src/google/protobuf/stubs/once.cc", "src/google/protobuf/stubs/status.cc", "src/google/protobuf/stubs/statusor.cc", "src/google/protobuf/stubs/stringpiece.cc", @@ -120,18 +192,21 @@ cc_library( "src/google/protobuf/stubs/time.cc", "src/google/protobuf/wire_format_lite.cc", ], - hdrs = glob(["src/google/protobuf/**/*.h"]), - copts = select({ - ":ios_armv7": IOS_ARM_COPTS, - ":ios_armv7s": IOS_ARM_COPTS, - ":ios_arm64": IOS_ARM_COPTS, - "//conditions:default": [], - }) + COPTS, + hdrs = glob([ + "src/google/protobuf/**/*.h", + "src/google/protobuf/**/*.inc", + ]), + copts = COPTS, includes = ["src/"], linkopts = LINK_OPTS, visibility = ["//visibility:public"], ) +PROTOBUF_DEPS = select({ + ":msvc": [], + "//conditions:default": ZLIB_DEPS, +}) + cc_library( name = "protobuf", srcs = [ @@ -153,16 +228,13 @@ cc_library( "src/google/protobuf/generated_message_table_driven.cc", "src/google/protobuf/io/gzip_stream.cc", "src/google/protobuf/io/printer.cc", - "src/google/protobuf/io/strtod.cc", "src/google/protobuf/io/tokenizer.cc", - "src/google/protobuf/io/zero_copy_stream_impl.cc", "src/google/protobuf/map_field.cc", "src/google/protobuf/message.cc", "src/google/protobuf/reflection_ops.cc", "src/google/protobuf/service.cc", "src/google/protobuf/source_context.pb.cc", "src/google/protobuf/struct.pb.cc", - "src/google/protobuf/stubs/mathlimits.cc", "src/google/protobuf/stubs/substitute.cc", "src/google/protobuf/text_format.cc", "src/google/protobuf/timestamp.pb.cc", @@ -192,17 +264,15 @@ cc_library( "src/google/protobuf/wire_format.cc", "src/google/protobuf/wrappers.pb.cc", ], - hdrs = glob(["src/**/*.h"]), - copts = select({ - ":ios_armv7": IOS_ARM_COPTS, - ":ios_armv7s": IOS_ARM_COPTS, - ":ios_arm64": IOS_ARM_COPTS, - "//conditions:default": [], - }) + COPTS, + hdrs = glob([ + "src/**/*.h", + "src/**/*.inc", + ]), + copts = COPTS, includes = ["src/"], linkopts = LINK_OPTS, visibility = ["//visibility:public"], - deps = [":protobuf_lite"], + deps = [":protobuf_lite"] + PROTOBUF_DEPS, ) # This provides just the header files for use in projects that need to build @@ -211,36 +281,47 @@ cc_library( # TODO(keveman): Remove this target once the support gets added to Bazel. cc_library( name = "protobuf_headers", - hdrs = glob(["src/**/*.h"]), + hdrs = glob([ + "src/**/*.h", + "src/**/*.inc", + ]), includes = ["src/"], visibility = ["//visibility:public"], ) -objc_library( - name = "protobuf_objc", - hdrs = ["objectivec/GPBProtocolBuffers.h"], - includes = ["objectivec"], - non_arc_srcs = ["objectivec/GPBProtocolBuffers.m"], - visibility = ["//visibility:public"], -) - -RELATIVE_WELL_KNOWN_PROTOS = [ - # AUTOGEN(well_known_protos) - "google/protobuf/any.proto", - "google/protobuf/api.proto", - "google/protobuf/compiler/plugin.proto", - "google/protobuf/descriptor.proto", - "google/protobuf/duration.proto", - "google/protobuf/empty.proto", - "google/protobuf/field_mask.proto", - "google/protobuf/source_context.proto", - "google/protobuf/struct.proto", - "google/protobuf/timestamp.proto", - "google/protobuf/type.proto", - "google/protobuf/wrappers.proto", -] +# Map of all well known protos. +# name => (include path, imports) +WELL_KNOWN_PROTO_MAP = { + "any": ("src/google/protobuf/any.proto", []), + "api": ( + "src/google/protobuf/api.proto", + [ + "source_context", + "type", + ], + ), + "compiler_plugin": ( + "src/google/protobuf/compiler/plugin.proto", + ["descriptor"], + ), + "descriptor": ("src/google/protobuf/descriptor.proto", []), + "duration": ("src/google/protobuf/duration.proto", []), + "empty": ("src/google/protobuf/empty.proto", []), + "field_mask": ("src/google/protobuf/field_mask.proto", []), + "source_context": ("src/google/protobuf/source_context.proto", []), + "struct": ("src/google/protobuf/struct.proto", []), + "timestamp": ("src/google/protobuf/timestamp.proto", []), + "type": ( + "src/google/protobuf/type.proto", + [ + "any", + "source_context", + ], + ), + "wrappers": ("src/google/protobuf/wrappers.proto", []), +} -WELL_KNOWN_PROTOS = ["src/" + s for s in RELATIVE_WELL_KNOWN_PROTOS] +WELL_KNOWN_PROTOS = [value[0] for value in WELL_KNOWN_PROTO_MAP.values()] filegroup( name = "well_known_protos", @@ -248,38 +329,61 @@ filegroup( visibility = ["//visibility:public"], ) -cc_proto_library( +adapt_proto_library( + name = "cc_wkt_protos_genproto", + deps = [proto + "_proto" for proto in WELL_KNOWN_PROTO_MAP.keys()], + visibility = ["//visibility:public"], +) + +cc_library( name = "cc_wkt_protos", - srcs = WELL_KNOWN_PROTOS, - include = "src", - default_runtime = ":protobuf", - internal_bootstrap_hack = 1, - protoc = ":protoc", + deprecation = "Only for backward compatibility. Do not use.", visibility = ["//visibility:public"], ) ################################################################################ -# Protocol Buffers Compiler +# Well Known Types Proto Library Rules +# +# These proto_library rules can be used with one of the language specific proto +# library rules i.e. java_proto_library: +# +# java_proto_library( +# name = "any_java_proto", +# deps = ["@com_google_protobuf//:any_proto], +# ) ################################################################################ -cc_binary( - name = "js_embed", - srcs = ["src/google/protobuf/compiler/js/embed.cc"], +[proto_library( + name = proto[0] + "_proto", + srcs = [proto[1][0]], + strip_import_prefix = "src", visibility = ["//visibility:public"], -) + deps = [dep + "_proto" for dep in proto[1][1]], +) for proto in WELL_KNOWN_PROTO_MAP.items()] -genrule( - name = "generate_js_well_known_types_embed", - srcs = [ - "src/google/protobuf/compiler/js/well_known_types/any.js", - "src/google/protobuf/compiler/js/well_known_types/struct.js", - "src/google/protobuf/compiler/js/well_known_types/timestamp.js", +[native_cc_proto_library( + name = proto + "_cc_proto", + deps = [proto + "_proto"], + visibility = ["//visibility:private"], +) for proto in WELL_KNOWN_PROTO_MAP.keys()] + +cc_proto_blacklist_test( + name = "cc_proto_blacklist_test", + deps = [proto + "_cc_proto" for proto in WELL_KNOWN_PROTO_MAP.keys()], + tags = [ + # Exclude this target from wildcard expansion (//...). Due to + # https://github.com/bazelbuild/bazel/issues/10590, this test has to + # be nominated using the `@com_google_protobuf//` prefix. We do that, + # e.g., in kokoro/linux/bazel/build.sh. + # See also https://github.com/protocolbuffers/protobuf/pull/7096. + "manual", ], - outs = ["src/google/protobuf/compiler/js/well_known_types_embed.cc"], - cmd = "$(location :js_embed) $(SRCS) > $@", - tools = [":js_embed"], ) +################################################################################ +# Protocol Buffers Compiler +################################################################################ + cc_library( name = "protoc_lib", srcs = [ @@ -296,6 +400,7 @@ cc_library( "src/google/protobuf/compiler/cpp/cpp_map_field.cc", "src/google/protobuf/compiler/cpp/cpp_message.cc", "src/google/protobuf/compiler/cpp/cpp_message_field.cc", + "src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc", "src/google/protobuf/compiler/cpp/cpp_primitive_field.cc", "src/google/protobuf/compiler/cpp/cpp_service.cc", "src/google/protobuf/compiler/cpp/cpp_string_field.cc", @@ -328,8 +433,6 @@ cc_library( "src/google/protobuf/compiler/java/java_generator.cc", "src/google/protobuf/compiler/java/java_generator_factory.cc", "src/google/protobuf/compiler/java/java_helpers.cc", - "src/google/protobuf/compiler/java/java_lazy_message_field.cc", - "src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc", "src/google/protobuf/compiler/java/java_map_field.cc", "src/google/protobuf/compiler/java/java_map_field_lite.cc", "src/google/protobuf/compiler/java/java_message.cc", @@ -345,17 +448,6 @@ cc_library( "src/google/protobuf/compiler/java/java_shared_code_generator.cc", "src/google/protobuf/compiler/java/java_string_field.cc", "src/google/protobuf/compiler/java/java_string_field_lite.cc", - "src/google/protobuf/compiler/javanano/javanano_enum.cc", - "src/google/protobuf/compiler/javanano/javanano_enum_field.cc", - "src/google/protobuf/compiler/javanano/javanano_extension.cc", - "src/google/protobuf/compiler/javanano/javanano_field.cc", - "src/google/protobuf/compiler/javanano/javanano_file.cc", - "src/google/protobuf/compiler/javanano/javanano_generator.cc", - "src/google/protobuf/compiler/javanano/javanano_helpers.cc", - "src/google/protobuf/compiler/javanano/javanano_map_field.cc", - "src/google/protobuf/compiler/javanano/javanano_message.cc", - "src/google/protobuf/compiler/javanano/javanano_message_field.cc", - "src/google/protobuf/compiler/javanano/javanano_primitive_field.cc", "src/google/protobuf/compiler/js/js_generator.cc", "src/google/protobuf/compiler/js/well_known_types_embed.cc", "src/google/protobuf/compiler/objectivec/objectivec_enum.cc", @@ -403,7 +495,6 @@ RELATIVE_LITE_TEST_PROTOS = [ "google/protobuf/unittest_import_lite.proto", "google/protobuf/unittest_import_public_lite.proto", "google/protobuf/unittest_lite.proto", - "google/protobuf/unittest_no_arena_lite.proto", ] LITE_TEST_PROTOS = ["src/" + s for s in RELATIVE_LITE_TEST_PROTOS] @@ -430,16 +521,16 @@ RELATIVE_TEST_PROTOS = [ "google/protobuf/unittest_lite_imports_nonlite.proto", "google/protobuf/unittest_mset.proto", "google/protobuf/unittest_mset_wire_format.proto", - "google/protobuf/unittest_no_arena.proto", - "google/protobuf/unittest_no_arena_import.proto", "google/protobuf/unittest_no_field_presence.proto", "google/protobuf/unittest_no_generic_services.proto", "google/protobuf/unittest_optimize_for.proto", "google/protobuf/unittest_preserve_unknown_enum.proto", "google/protobuf/unittest_preserve_unknown_enum2.proto", + "google/protobuf/unittest_proto3.proto", "google/protobuf/unittest_proto3_arena.proto", "google/protobuf/unittest_proto3_arena_lite.proto", "google/protobuf/unittest_proto3_lite.proto", + "google/protobuf/unittest_proto3_optional.proto", "google/protobuf/unittest_well_known_types.proto", "google/protobuf/util/internal/testdata/anys.proto", "google/protobuf/util/internal/testdata/books.proto", @@ -452,6 +543,7 @@ RELATIVE_TEST_PROTOS = [ "google/protobuf/util/internal/testdata/struct.proto", "google/protobuf/util/internal/testdata/timestamp_duration.proto", "google/protobuf/util/internal/testdata/wrappers.proto", + "google/protobuf/util/json_format.proto", "google/protobuf/util/json_format_proto3.proto", "google/protobuf/util/message_differencer_unittest.proto", ] @@ -470,8 +562,9 @@ cc_proto_library( COMMON_TEST_SRCS = [ # AUTOGEN(common_test_srcs) "src/google/protobuf/arena_test_util.cc", - "src/google/protobuf/map_test_util.cc", + "src/google/protobuf/map_test_util.inc", "src/google/protobuf/test_util.cc", + "src/google/protobuf/test_util.inc", "src/google/protobuf/testing/file.cc", "src/google/protobuf/testing/googletest.cc", ] @@ -487,18 +580,19 @@ cc_binary( deps = [ ":protobuf", ":protoc_lib", - "//external:gtest", - ], + ] + GTEST, ) cc_test( name = "win32_test", - srcs = ["src/google/protobuf/stubs/io_win32_unittest.cc"], + srcs = ["src/google/protobuf/io/io_win32_unittest.cc"], + tags = [ + "manual", + "windows", + ], deps = [ ":protobuf_lite", - "//external:gtest_main", - ], - tags = ["manual", "windows"], + ] + GTEST_MAIN, ) cc_test( @@ -508,11 +602,12 @@ cc_test( "src/google/protobuf/any_test.cc", "src/google/protobuf/arena_unittest.cc", "src/google/protobuf/arenastring_unittest.cc", - "src/google/protobuf/compiler/command_line_interface_unittest.cc", + "src/google/protobuf/compiler/annotation_test_util.cc", "src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc", "src/google/protobuf/compiler/cpp/cpp_move_unittest.cc", "src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc", "src/google/protobuf/compiler/cpp/cpp_unittest.cc", + "src/google/protobuf/compiler/cpp/cpp_unittest.inc", "src/google/protobuf/compiler/cpp/metadata_test.cc", "src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc", "src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc", @@ -531,25 +626,26 @@ cc_test( "src/google/protobuf/extension_set_unittest.cc", "src/google/protobuf/generated_message_reflection_unittest.cc", "src/google/protobuf/io/coded_stream_unittest.cc", + "src/google/protobuf/io/io_win32_unittest.cc", "src/google/protobuf/io/printer_unittest.cc", "src/google/protobuf/io/tokenizer_unittest.cc", "src/google/protobuf/io/zero_copy_stream_unittest.cc", "src/google/protobuf/map_field_test.cc", "src/google/protobuf/map_test.cc", "src/google/protobuf/message_unittest.cc", + "src/google/protobuf/message_unittest.inc", "src/google/protobuf/no_field_presence_test.cc", "src/google/protobuf/preserve_unknown_enum_test.cc", "src/google/protobuf/proto3_arena_lite_unittest.cc", "src/google/protobuf/proto3_arena_unittest.cc", "src/google/protobuf/proto3_lite_unittest.cc", + "src/google/protobuf/proto3_lite_unittest.inc", "src/google/protobuf/reflection_ops_unittest.cc", "src/google/protobuf/repeated_field_reflection_unittest.cc", "src/google/protobuf/repeated_field_unittest.cc", "src/google/protobuf/stubs/bytestream_unittest.cc", "src/google/protobuf/stubs/common_unittest.cc", "src/google/protobuf/stubs/int128_unittest.cc", - "src/google/protobuf/stubs/io_win32_unittest.cc", - "src/google/protobuf/stubs/once_unittest.cc", "src/google/protobuf/stubs/status_test.cc", "src/google/protobuf/stubs/statusor_test.cc", "src/google/protobuf/stubs/stringpiece_unittest.cc", @@ -558,7 +654,6 @@ cc_test( "src/google/protobuf/stubs/strutil_unittest.cc", "src/google/protobuf/stubs/template_util_unittest.cc", "src/google/protobuf/stubs/time_test.cc", - "src/google/protobuf/stubs/type_traits_unittest.cc", "src/google/protobuf/text_format_unittest.cc", "src/google/protobuf/unknown_field_set_unittest.cc", "src/google/protobuf/util/delimited_message_util_test.cc", @@ -576,7 +671,13 @@ cc_test( "src/google/protobuf/util/type_resolver_util_test.cc", "src/google/protobuf/well_known_types_unittest.cc", "src/google/protobuf/wire_format_unittest.cc", - ], + ] + select({ + "//conditions:default": [ + # AUTOGEN(non_msvc_test_srcs) + "src/google/protobuf/compiler/command_line_interface_unittest.cc", + ], + ":msvc": [], + }), copts = COPTS, data = [ ":test_plugin", @@ -585,7 +686,6 @@ cc_test( # Files for csharp_bootstrap_unittest.cc. "conformance/**/*", "csharp/src/**/*", - "examples/**/*", ]), includes = [ "src/", @@ -595,40 +695,49 @@ cc_test( ":cc_test_protos", ":protobuf", ":protoc_lib", - "//external:gtest_main", - ], + ] + PROTOBUF_DEPS + GTEST_MAIN, ) ################################################################################ # Java support ################################################################################ + internal_gen_well_known_protos_java( - srcs = WELL_KNOWN_PROTOS, + name = "gen_well_known_protos_java", + deps = [proto + "_proto" for proto in WELL_KNOWN_PROTO_MAP.keys()], + visibility = [ + "//java:__subpackages__", + ], ) -java_library( +alias( name = "protobuf_java", - srcs = glob([ - "java/core/src/main/java/com/google/protobuf/*.java", - ]) + [ - ":gen_well_known_protos_java", - ], - javacopts = ["-source 6", "-target 6"], + actual = "//java/core", visibility = ["//visibility:public"], ) -java_library( +alias( + name = "protobuf_javalite", + actual = "//java/lite", + visibility = ["//visibility:public"], +) + +alias( name = "protobuf_java_util", - srcs = glob([ - "java/util/src/main/java/com/google/protobuf/util/*.java", - ]), - javacopts = ["-source 6", "-target 6"], + actual = "//java/util", + visibility = ["//visibility:public"], +) + +alias( + name = "java_toolchain", + actual = "//java/core:toolchain", + visibility = ["//visibility:public"], +) + +alias( + name = "javalite_toolchain", + actual = "//java/lite:toolchain", visibility = ["//visibility:public"], - deps = [ - "protobuf_java", - "//external:gson", - "//external:guava", - ], ) ################################################################################ @@ -639,12 +748,9 @@ py_library( name = "python_srcs", srcs = glob( [ - "python/google/protobuf/*.py", "python/google/protobuf/**/*.py", ], exclude = [ - "python/google/protobuf/__init__.py", - "python/google/protobuf/**/__init__.py", "python/google/protobuf/internal/*_test.py", "python/google/protobuf/internal/test_util.py", ], @@ -659,6 +765,13 @@ cc_binary( copts = COPTS + [ "-DPYTHON_PROTO2_CPP_IMPL_V2", ], + tags = [ + # Exclude this target from wildcard expansion (//...) because it may + # not even be buildable. It will be built if it is needed according + # to :use_fast_cpp_protos. + # https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes + "manual", + ], linkshared = 1, linkstatic = 1, deps = select({ @@ -683,10 +796,18 @@ cc_binary( "python/", "src/", ], + tags = [ + # Exclude this target from wildcard expansion (//...) because it may + # not even be buildable. It will be built if it is needed according + # to :use_fast_cpp_protos. + # https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes + "manual", + ], linkshared = 1, linkstatic = 1, deps = [ ":protobuf", + ":proto_api", ] + select({ "//conditions:default": [], ":use_fast_cpp_protos": ["//external:python_headers"], @@ -698,6 +819,10 @@ config_setting( values = { "define": "use_fast_cpp_protos=true", }, + visibility = [ + # Public, but Protobuf only visibility. + "//:__subpackages__", + ], ) config_setting( @@ -705,6 +830,10 @@ config_setting( values = { "define": "allow_oversize_protos=true", }, + visibility = [ + # Public, but Protobuf only visibility. + "//:__subpackages__", + ], ) # Copy the builtin proto files from src/google/protobuf to @@ -721,7 +850,7 @@ internal_copied_filegroup( # TODO(dzc): Remove this once py_proto_library can have labels in srcs, in # which case we can simply add :protos_python in srcs. -COPIED_WELL_KNOWN_PROTOS = ["python/" + s for s in RELATIVE_WELL_KNOWN_PROTOS] +COPIED_WELL_KNOWN_PROTOS = ["python/" + s[4:] for s in WELL_KNOWN_PROTOS] py_proto_library( name = "protobuf_python", @@ -738,7 +867,7 @@ py_proto_library( protoc = ":protoc", py_libs = [ ":python_srcs", - "//external:six", + "@six//:six", ], srcs_version = "PY2AND3", visibility = ["//visibility:public"], @@ -828,97 +957,182 @@ internal_protobuf_py_tests( deps = [":python_tests"], ) +cc_library( + name = "proto_api", + hdrs = ["python/google/protobuf/proto_api.h"], + visibility = ["//visibility:public"], + deps = [ + "//external:python_headers", + ], +) + proto_lang_toolchain( name = "cc_toolchain", + blacklisted_protos = [proto + "_proto" for proto in WELL_KNOWN_PROTO_MAP.keys()], command_line = "--cpp_out=$(OUT)", runtime = ":protobuf", visibility = ["//visibility:public"], ) -proto_lang_toolchain( - name = "java_toolchain", - command_line = "--java_out=$(OUT)", - runtime = ":protobuf_java", +alias( + name = "objectivec", + actual = "//objectivec", visibility = ["//visibility:public"], ) -OBJC_HDRS = [ - "objectivec/GPBArray.h", - "objectivec/GPBBootstrap.h", - "objectivec/GPBCodedInputStream.h", - "objectivec/GPBCodedOutputStream.h", - "objectivec/GPBDescriptor.h", - "objectivec/GPBDictionary.h", - "objectivec/GPBExtensionInternals.h", - "objectivec/GPBExtensionRegistry.h", - "objectivec/GPBMessage.h", - "objectivec/GPBProtocolBuffers.h", - "objectivec/GPBProtocolBuffers_RuntimeSupport.h", - "objectivec/GPBRootObject.h", - "objectivec/GPBRuntimeTypes.h", - "objectivec/GPBUnknownField.h", - "objectivec/GPBUnknownFieldSet.h", - "objectivec/GPBUtilities.h", - "objectivec/GPBWellKnownTypes.h", - "objectivec/GPBWireFormat.h", - "objectivec/google/protobuf/Any.pbobjc.h", - "objectivec/google/protobuf/Api.pbobjc.h", - "objectivec/google/protobuf/Duration.pbobjc.h", - "objectivec/google/protobuf/Empty.pbobjc.h", - "objectivec/google/protobuf/FieldMask.pbobjc.h", - "objectivec/google/protobuf/SourceContext.pbobjc.h", - "objectivec/google/protobuf/Struct.pbobjc.h", - "objectivec/google/protobuf/Timestamp.pbobjc.h", - "objectivec/google/protobuf/Type.pbobjc.h", - "objectivec/google/protobuf/Wrappers.pbobjc.h", -] +alias( + name = "protobuf_objc", + actual = "//objectivec", + visibility = ["//visibility:public"], +) -OBJC_PRIVATE_HDRS = [ - "objectivec/GPBArray_PackagePrivate.h", - "objectivec/GPBCodedInputStream_PackagePrivate.h", - "objectivec/GPBCodedOutputStream_PackagePrivate.h", - "objectivec/GPBDescriptor_PackagePrivate.h", - "objectivec/GPBDictionary_PackagePrivate.h", - "objectivec/GPBMessage_PackagePrivate.h", - "objectivec/GPBRootObject_PackagePrivate.h", - "objectivec/GPBUnknownFieldSet_PackagePrivate.h", - "objectivec/GPBUnknownField_PackagePrivate.h", - "objectivec/GPBUtilities_PackagePrivate.h", -] +################################################################################ +# Test generated proto support +################################################################################ -OBJC_SRCS = [ - "objectivec/GPBArray.m", - "objectivec/GPBCodedInputStream.m", - "objectivec/GPBCodedOutputStream.m", - "objectivec/GPBDescriptor.m", - "objectivec/GPBDictionary.m", - "objectivec/GPBExtensionInternals.m", - "objectivec/GPBExtensionRegistry.m", - "objectivec/GPBMessage.m", - "objectivec/GPBRootObject.m", - "objectivec/GPBUnknownField.m", - "objectivec/GPBUnknownFieldSet.m", - "objectivec/GPBUtilities.m", - "objectivec/GPBWellKnownTypes.m", - "objectivec/GPBWireFormat.m", - "objectivec/google/protobuf/Any.pbobjc.m", - "objectivec/google/protobuf/Api.pbobjc.m", - "objectivec/google/protobuf/Duration.pbobjc.m", - "objectivec/google/protobuf/Empty.pbobjc.m", - "objectivec/google/protobuf/FieldMask.pbobjc.m", - "objectivec/google/protobuf/SourceContext.pbobjc.m", - "objectivec/google/protobuf/Struct.pbobjc.m", - "objectivec/google/protobuf/Timestamp.pbobjc.m", - "objectivec/google/protobuf/Type.pbobjc.m", - "objectivec/google/protobuf/Wrappers.pbobjc.m", -] +genrule( + name = "generated_protos", + srcs = ["src/google/protobuf/unittest_import.proto"], + outs = ["unittest_gen.proto"], + cmd = "cat $(SRCS) | sed 's|google/|src/google/|' > $(OUTS)", +) -objc_library( - name = "objectivec", - hdrs = OBJC_HDRS + OBJC_PRIVATE_HDRS, +proto_library( + name = "generated_protos_proto", + srcs = [ + "src/google/protobuf/unittest_import_public.proto", + "unittest_gen.proto", + ], +) + +py_proto_library( + name = "generated_protos_py", + srcs = [ + "src/google/protobuf/unittest_import_public.proto", + "unittest_gen.proto", + ], + default_runtime = "", + protoc = ":protoc", +) + +################################################################################ +# Conformance tests +################################################################################ + +proto_library( + name = "test_messages_proto2_proto", + srcs = ["src/google/protobuf/test_messages_proto2.proto"], + visibility = ["//visibility:public"], +) + +proto_library( + name = "test_messages_proto3_proto", + srcs = ["src/google/protobuf/test_messages_proto3.proto"], + visibility = ["//visibility:public"], + deps = [ + ":any_proto", + ":duration_proto", + ":field_mask_proto", + ":struct_proto", + ":timestamp_proto", + ":wrappers_proto", + ], +) + +cc_proto_library( + name = "test_messages_proto2_proto_cc", + srcs = ["src/google/protobuf/test_messages_proto2.proto"], +) + +cc_proto_library( + name = "test_messages_proto3_proto_cc", + srcs = ["src/google/protobuf/test_messages_proto3.proto"], + deps = [ + ":cc_wkt_protos", + ], +) + +proto_library( + name = "conformance_proto", + srcs = ["conformance/conformance.proto"], + visibility = ["//visibility:public"], +) + +cc_proto_library( + name = "conformance_proto_cc", + srcs = ["conformance/conformance.proto"], +) + +cc_library( + name = "jsoncpp", + srcs = ["conformance/third_party/jsoncpp/jsoncpp.cpp"], + hdrs = ["conformance/third_party/jsoncpp/json.h"], + includes = ["conformance"], +) + +cc_library( + name = "conformance_test", + srcs = [ + "conformance/conformance_test.cc", + "conformance/conformance_test_runner.cc", + ], + hdrs = [ + "conformance/conformance_test.h", + ], includes = [ - "objectivec", + "conformance", + "src", + ], + deps = [":conformance_proto_cc"], +) + +cc_library( + name = "binary_json_conformance_suite", + srcs = ["conformance/binary_json_conformance_suite.cc"], + hdrs = ["conformance/binary_json_conformance_suite.h"], + deps = [ + ":conformance_test", + ":jsoncpp", + ":test_messages_proto2_proto_cc", + ":test_messages_proto3_proto_cc", + ], +) + +cc_library( + name = "text_format_conformance_suite", + srcs = ["conformance/text_format_conformance_suite.cc"], + hdrs = ["conformance/text_format_conformance_suite.h"], + deps = [ + ":conformance_test", + ":test_messages_proto2_proto_cc", + ":test_messages_proto3_proto_cc", ], - non_arc_srcs = OBJC_SRCS, +) + +cc_binary( + name = "conformance_test_runner", + srcs = ["conformance/conformance_test_main.cc"], visibility = ["//visibility:public"], + deps = [ + ":binary_json_conformance_suite", + ":conformance_test", + ":text_format_conformance_suite", + ], +) + +sh_test( + name = "build_files_updated_unittest", + srcs = [ + "build_files_updated_unittest.sh", + ], + data = [ + "BUILD", + "cmake/extract_includes.bat.in", + "cmake/libprotobuf.cmake", + "cmake/libprotobuf-lite.cmake", + "cmake/libprotoc.cmake", + "cmake/tests.cmake", + "src/Makefile.am", + "update_file_lists.sh", + ], ) diff --git a/CHANGES.txt b/CHANGES.txt index 1f1dd6d599a0a..9be4173739b58 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,928 @@ +2021-02-05 version 3.15.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + Protocol Compiler + * Optional fields for proto3 are enabled by default, and no longer require + the --experimental_allow_proto3_optional flag. + + C++ + * MessageDifferencer: fixed bug when using custom ignore with multiple + unknown fields + * Use init_seg in MSVC to push initialization to an earlier phase. + * Runtime no longer triggers -Wsign-compare warnings. + * Fixed -Wtautological-constant-out-of-range-compare warning. + * DynamicCastToGenerated works for nullptr input for even if RTTI is disabled + * Arena is refactored and optimized. + * Clarified/specified that the exact value of Arena::SpaceAllocated() is an + implementation detail users must not rely on. It should not be used in + unit tests. + * Change the signature of Any::PackFrom() to return false on error. + * Add fast reflection getter API for strings. + * Constant initialize the global message instances + * Avoid potential for missed wakeup in UnknownFieldSet + * Now Proto3 Oneof fields have "has" methods for checking their presence in + C++. + * Bugfix for NVCC + * Return early in _InternalSerialize for empty maps. + * Adding functionality for outputting map key values in proto path logging + output (does not affect comparison logic) and stop printing 'value' in the + path. The modified print functionality is in the + MessageDifferencer::StreamReporter. + * Fixed https://github.com/protocolbuffers/protobuf/issues/8129 + * Ensure that null char symbol, package and file names do not result in a + crash. + * Constant initialize the global message instances + * Pretty print 'max' instead of numeric values in reserved ranges. + * Removed remaining instances of std::is_pod, which is deprecated in C++20. + * Changes to reduce code size for unknown field handling by making uncommon + cases out of line. + * Fix std::is_pod deprecated in C++20 (#7180) + * Fix some -Wunused-parameter warnings (#8053) + * Fix detecting file as directory on zOS issue #8051 (#8052) + * Don't include sys/param.h for _BYTE_ORDER (#8106) + * remove CMAKE_THREAD_LIBS_INIT from pkgconfig CFLAGS (#8154) + * Fix TextFormatMapTest.DynamicMessage issue#5136 (#8159) + * Fix for compiler warning issue#8145 (#8160) + * fix: support deprecated enums for GCC < 6 (#8164) + * Fix some warning when compiling with Visual Studio 2019 on x64 target (#8125) + + Python + * Provided an override for the reverse() method that will reverse the internal + collection directly instead of using the other methods of the BaseContainer. + * MessageFactory.CreateProtoype can be overridden to customize class creation. + * Fix PyUnknownFields memory leak (#7928) + * Add macOS big sur compatibility (#8126) + + JavaScript + * Generate `getDescriptor` methods with `*` as their `this` type. + * Enforce `let/const` for generated messages. + * js/binary/utils.js: Fix jspb.utils.joinUnsignedDecimalString to work with negative bitsLow and low but non-zero bitsHigh parameter. (#8170) + + PHP + * Added support for PHP 8. (#8105) + * unregister INI entries and fix invalid read on shutdown (#8042) + * Fix PhpDoc comments for message accessors to include "|null". (#8136) + * fix: convert native PHP floats to single precision (#8187) + * Fixed PHP to support field numbers >=2**28. (#8235) + * feat: add support for deprecated fields to PHP compiler (#8223) + * Protect against stack overflow if the user derives from Message. (#8248) + * Fixed clone for Message, RepeatedField, and MapField. (#8245) + * Updated upb to allow nonzero offset minutes in JSON timestamps. (#8258) + + Ruby + * Added support for Ruby 3. (#8184) + * Rewrote the data storage layer to be based on upb_msg objects from the + upb library. This should lead to much better parsing performance, + particularly for large messages. (#8184). + * Fill out JRuby support (#7923) + * [Ruby] Fix: (SIGSEGV) gRPC-Ruby issue on Windows. memory alloc infinite + recursion/run out of memory (#8195) + * Fix jruby support to handle messages nested more than 1 level deep (#8194) + + Java + * Avoid possible UnsupportedOperationException when using CodedInputSteam + with a direct ByteBuffer. + * Make Durations.comparator() and Timestamps.comparator() Serializable. + * Add more detailed error information for dynamic message field type + validation failure + * Removed declarations of functions declared in java_names.h from + java_helpers.h. + * Now Proto3 Oneof fields have "has" methods for checking their presence in + Java. + * Annotates Java proto generated *_FIELD_NUMBER constants. + * Add -assumevalues to remove JvmMemoryAccessor on Android. + + C# + * Fix parsing negative Int32Value that crosses segment boundary (#8035) + * Change ByteString to use memory and support unsafe create without copy (#7645) + * Optimize MapField serialization by removing MessageAdapter (#8143) + * Allow FileDescriptors to be parsed with extension registries (#8220) + * Optimize writing small strings (#8149) + +2020-11-11 version 3.14.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + Protocol Compiler + * The proto compiler no longer requires a .proto filename when it is not + generating code. + * Added flag `--deterministic_output` to `protoc --encode=...`. + * Fixed deadlock when using google.protobuf.Any embedded in aggregate options. + + C++ + * Arenas are now unconditionally enabled. cc_enable_arenas no longer has + any effect. + * Removed inlined string support, which is incompatible with arenas. + * Fix a memory corruption bug in reflection when mixing optional and + non-optional fields. + * Make SpaceUsed() calculation more thorough for map fields. + * Add stack overflow protection for text format with unknown field values. + * FieldPath::FollowAll() now returns a bool to signal if an out-of-bounds + error was encountered. + * Performance improvements for Map. + * Minor formatting fix when dumping a descriptor to .proto format with + DebugString. + * UBSAN fix in RepeatedField (#2073). + * When running under ASAN, skip a test that makes huge allocations. + * Fixed a crash that could happen when creating more than 256 extensions in + a single message. + * Fix a crash in BuildFile when passing in invalid descriptor proto. + * Parser security fix when operating with CodedInputStream. + * Warn against the use of AllowUnknownExtension. + * Migrated to C++11 for-range loops instead of index-based loops where + possible. This fixes a lot of warnings when compiling with -Wsign-compare. + * Fix segment fault for proto3 optional (#7805) + * Adds a CMake option to build `libprotoc` separately (#7949) + + Java + * Bugfix in mergeFrom() when a oneof has multiple message fields. + * Fix RopeByteString.RopeInputStream.read() returning -1 when told to read + 0 bytes when not at EOF. + * Redefine remove(Object) on primitive repeated field Lists to avoid + autoboxing. + * Support "\u" escapes in textformat string literals. + * Trailing empty spaces are no longer ignored for FieldMask. + * Fix FieldMaskUtil.subtract to recursively remove mask. + * Mark enums with `@java.lang.Deprecated` if the proto enum has option + `deprecated = true;`. + * Adding forgotten duration.proto to the lite library (#7738) + + Python + * Print google.protobuf.NullValue as null instead of "NULL_VALUE" when it is + used outside WKT Value/Struct. + * Fix bug occurring when attempting to deep copy an enum type in python 3. + * Add a setuptools extension for generating Python protobufs (#7783) + * Remove uses of pkg_resources in non-namespace packages. (#7902) + * [bazel/py] Omit google/__init__.py from the Protobuf runtime. (#7908) + * Removed the unnecessary setuptools package dependency for Python package (#7511) + * Fix PyUnknownFields memory leak (#7928) + + PHP + * Added support for "==" to the PHP C extension (#7883) + * Added `==` operators for Map and Array. (#7900) + * Native C well-known types (#7944) + * Optimized away hex2bin() call in generated code (#8006) + * New version of upb, and a new hash function wyhash in third_party. (#8000) + * add missing hasOneof method to check presence of oneof fields (#8003) + + Go: + * Update go_package options to reference google.golang.org/protobuf module. + + C#: + * annotate ByteString.CopyFrom(ReadOnlySpan) as SecuritySafeCritical (#7701) + * Fix C# optional field reflection when there are regular fields too (#7705) + * Fix parsing negative Int32Value that crosses segment boundary (#8035) + + Javascript: + * JS: parse (un)packed fields conditionally (#7379) + +2020-07-14 version 3.13.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + PHP: + * The C extension is completely rewritten. The new C extension has significantly + better parsing performance and fixes a handful of conformance issues. It will + also make it easier to add support for more features like proto2 and proto3 presence. + * The new C extension does not support PHP 5.x. PHP 5.x users can still use pure-PHP. + + C++: + * Removed deprecated unsafe arena string accessors + * Enabled heterogeneous lookup for std::string keys in maps. + * Removed implicit conversion from StringPiece to std::string + * Fix use-after-destroy bug when the Map is allocated in the arena. + * Improved the randomness of map ordering + * Added stack overflow protection for text format with unknown fields + * Use std::hash for proto maps to help with portability. + * Added more Windows macros to proto whitelist. + * Arena constructors for map entry messages are now marked "explicit" + (for regular messages they were already explicit). + * Fix subtle aliasing bug in RepeatedField::Add + * Fix mismatch between MapEntry ByteSize and Serialize with respect to unset + fields. + + Python: + * JSON format conformance fixes: + * Reject lowercase t for Timestamp json format. + * Print full_name directly for extensions (no camelCase). + * Reject boolean values for integer fields. + * Reject NaN, Infinity, -Infinity that is not quoted. + * Base64 fixes for bytes fields: accept URL-safe base64 and missing padding. + * Bugfix for fields/files named "async" or "await". + * Improved the error message when AttributeError is returned from __getattr__ + in EnumTypeWrapper. + + Java: + * Fixed a bug where setting optional proto3 enums with setFooValue() would + not mark the value as present. + * Add Subtract function to FieldMaskUtil. + + C#: + * Dropped support for netstandard1.0 (replaced by support for netstandard1.1). + This was required to modernize the parsing stack to use the `Span` + type internally. (#7351) + * Add `ParseFrom(ReadOnlySequence)` method to enable GC friendly + parsing with reduced allocations and buffer copies. (#7351) + * Add support for serialization directly to a `IBufferWriter` or + to a `Span` to enable GC friendly serialization. + The new API is available as extension methods on the `IMessage` type. (#7576) + * Add `GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE` define to make + generated code compatible with old C# compilers (pre-roslyn compilers + from .NET framework and old versions of mono) that do not support + ref structs. Users that are still on a legacy stack that does + not support C# 7.2 compiler might need to use the new define + in their projects to be able to build the newly generated code. (#7490) + * Due to the major overhaul of parsing and serialization internals (#7351 and #7576), + it is recommended to regenerate your generated code to achieve the best + performance (the legacy generated code will still work, but might incur + a slight performance penalty). + +2020-07-28 version 3.12.4 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + +This release contains no significant changes, but exists because 3.12.3 was +mistakenly tagged at the wrong commit. + +2020-06-01 version 3.12.3 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + Objective-C + * Tweak the union used for Extensions to support old generated code. #7573 + +2020-05-26 version 3.12.2 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + C++ + * Simplified the template export macros to fix the build for mingw32. (#7539) + + Objective-C + * Fix for the :protobuf_objc target in the Bazel BUILD file. (#7538) + +2020-05-20 version 3.12.1 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + Ruby + * Re-add binary gems for Ruby 2.3 and 2.4. These are EOL upstream, however + many people still use them and dropping support will require more + coordination. + +2020-05-12 version 3.12.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + Protocol Compiler + * [experimental] Singular, non-message typed fields in proto3 now support + presence tracking. This is enabled by adding the "optional" field label and + passing the --experimental_allow_proto3_optional flag to protoc. + * For usage info, see docs/field_presence.md. + * During this experimental phase, code generators should update to support + proto3 presence, see docs/implementing_proto3_presence.md for instructions. + * Allow duplicate symbol names when multiple descriptor sets are passed on + the command-line, to match the behavior when multiple .proto files are passed. + * Deterministic `protoc --descriptor_set_out` (#7175) + + C++ + * [experimental] Added proto3 presence support. + * New descriptor APIs to support proto3 presence. + * Enable Arenas by default on all .proto files. + * Documented that users are not allowed to subclass Message or MessageLite. + * Mark generated classes as final; inheriting from protos is strongly discouraged. + * Add stack overflow protection for text format with unknown fields. + * Add accessors for map key and value FieldDescriptors. + * Add FieldMaskUtil::FromFieldNumbers(). + * MessageDifferencer: use ParsePartial() on Any fields so the diff does not + fail when there are missing required fields. + * ReflectionOps::Merge(): lookup messages in the right factory, if it can. + * Added Descriptor::WellKnownTypes enum and Descriptor::well_known_type() + accessor as an easier way of determining if a message is a Well-Known Type. + * Optimized RepeatedField::Add() when it is used in a loop. + * Made proto move/swap more efficient. + * De-virtualize the GetArena() method in MessageLite. + * Improves performance of json_stream_parser.cc by factor 1000 (#7230) + * bug: #7076 undefine Windows OUT and OPTIONAL macros (#7087) + * Fixed a bug in FieldDescriptor::DebugString() that would erroneously print + an "optional" label for a field in a oneof. + * Fix bug in parsing bool extensions that assumed they are always 1 byte. + * Fix off-by-one error in FieldOptions::ByteSize() when extensions are present. + * Clarified the comments to show an example of the difference between + Descriptor::extension and DescriptorPool::FindAllExtensions. + * Add a compiler option 'code_size' to force optimize_for=code_size on all + protos where this is possible. + + Java + * [experimental] Added proto3 presence support. + * Mark java enum _VALUE constants as @Deprecated if the enum field is deprecated + * reduce size for enums with allow_alias set to true. + * Sort map fields alphabetically by the field's key when printing textproto. + * Fixed a bug in map sorting that appeared in -rc1 and -rc2 (#7508). + * TextFormat.merge() handles Any as top level type. + * Throw a descriptive IllegalArgumentException when calling + getValueDescriptor() on enum special value UNRECOGNIZED instead of + ArrayIndexOutOfBoundsException. + * Fixed an issue with JsonFormat.printer() where setting printingEnumsAsInts() + would override the configuration passed into includingDefaultValueFields(). + * Implement overrides of indexOf() and contains() on primitive lists returned + for repeated fields to avoid autoboxing the list contents. + * Add overload to FieldMaskUtil.fromStringList that accepts a descriptor. + * [bazel] Move Java runtime/toolchains into //java (#7190) + + Python + * [experimental] Added proto3 presence support. + * [experimental] fast import protobuf module, only works with cpp generated code linked in. + * Truncate 'float' fields to 4 bytes of precision in setters for pure-Python + implementation (C++ extension was already doing this). + * Fixed a memory leak in C++ bindings. + * Added a deprecation warning when code tries to create Descriptor objects + directly. + * Fix unintended comparison between bytes and string in descriptor.py. + * Avoid printing excess digits for float fields in TextFormat. + * Remove Python 2.5 syntax compatibility from the proto compiler generated _pb2.py module code. + * Drop 3.3, 3.4 and use single version docker images for all python tests (#7396) + + JavaScript + * Fix js message pivot selection (#6813) + + PHP + * Persistent Descriptor Pool (#6899) + * Implement lazy loading of php class for proto messages (#6911) + * Correct @return in Any.unpack docblock (#7089) + * Ignore unknown enum value when ignore_unknown specified (#7455) + + Ruby + * [experimental] Implemented proto3 presence for Ruby. (#7406) + * Stop building binary gems for ruby <2.5 (#7453) + * Fix for wrappers with a zero value (#7195) + * Fix for JSON serialization of 0/empty-valued wrapper types (#7198) + * Call "Class#new" over rb_class_new_instance in decoding (#7352) + * Build extensions for Ruby 2.7 (#7027) + * assigning 'nil' to submessage should clear the field. (#7397) + + C# + * [experimental] Add support for proto3 presence fields in C# (#7382) + * Mark GetOption API as obsolete and expose the "GetOptions()" method on descriptors instead (#7491) + * Remove Has/Clear members for C# message fields in proto2 (#7429) + * Enforce recursion depth checking for unknown fields (#7132) + * Fix conformance test failures for Google.Protobuf (#6910) + * Cleanup various bits of Google.Protobuf (#6674) + * Fix latest ArgumentException for C# extensions (#6938) + * Remove unnecessary branch from ReadTag (#7289) + + Objective-C + * [experimental] ObjC Proto3 optional support (#7421) + * Block subclassing of generated classes (#7124) + * Use references to Obj C classes instead of names in descriptors. (#7026) + * Revisit how the WKTs are bundled with ObjC. (#7173) + + Other + * Add a proto_lang_toolchain for javalite (#6882) + * [bazel] Update gtest and deprecate //external:{gtest,gtest_main} (#7237) + * Add application note for explicit presence tracking. (#7390) + * Howto doc for implementing proto3 presence in a code generator. (#7407) + + +2020-02-14 version 3.11.4 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + C# + * Fix latest ArgumentException for C# extensions (#7188) + * Enforce recursion depth checking for unknown fields (#7210) + + Ruby + * Fix wrappers with a zero value (#7195) + * Fix JSON serialization of 0/empty-valued wrapper types (#7198) + +2020-01-31 version 3.11.3 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + C++ + * Add OUT and OPTIONAL to windows portability files (#7087) + + PHP + * Refactored ulong to zend_ulong for php7.4 compatibility (#7147) + * Call register_class before getClass from desc to fix segfault (#7077) + + +2019-12-10 version 3.11.2 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + PHP + * Make c extension portable for php 7.4 (#6968) + + +2019-12-02 version 3.11.1 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + PHP + * Extern declare protobuf_globals (#6946) + + +2019-11-19 version 3.11.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + C++ + * Make serialization method naming consistent + * Make proto runtime + generated code free of deprecation warnings + * Moved ShutdownProtobufLibrary() to message_lite.h. For backward compatibility a declaration is still available in stubs/common.h, but users should prefer message_lite.h + * Removed non-namespace macro EXPECT_OK() + * Removed mathlimits.h from stubs in favor of using std::numeric_limits from C++11 + * Fixed bug in parser when ending on a group tag + * Add a helper function to UnknownFieldSet to deal with the changing return value of message::unknown_fields() + * Fix incorrect use of string_view iterators + * Support direct pickling of nested messages + * Skip extension tag validation for MessageSet if unknown dependencies are allowed + * Updated deprecation macros to annotate deprecated code (#6612) + * Remove conversion warning in MapEntryFuncs::ByteSizeLong (#6766) + * Revert "Make shared libraries be able to link to MSVC static runtime libraries, so that VC runtime is not required." (#6914) + + Java + * Remove the usage of MethodHandle, so that Android users prior to API version 26 can use protobuf-java + * Publish ProGuard config for javalite + * Fix for StrictMode disk read violation in ExtensionRegistryLite + * Include part of the ByteString's content in its toString(). + * Include unknown fields when merging proto3 messages in Java lite builders + + Python + * Add float_precision option in json format printer + * Optionally print bytes fields as messages in unknown fields, if possible + * FieldPath: fix testing IsSet on root path '' + * Experimental code gen (fast import protobuf module) which only work with cpp generated code linked in + + JavaScript + * Remove guard for Symbol iterator for jspb.Map + + PHP + * Avoid too much overhead in layout_init (#6716) + * Lazily Create Singular Wrapper Message (#6833) + * Implement lazy loading of php class for proto messages (#6911) + + Ruby + * Ruby lazy wrappers optimization (#6797) + + C# + * (RepeatedField): Capacity property to resize the internal array (#6530) + * Experimental proto2 support is now officially available (#4642, #5183, #5350, #5936) + * Getting started doc: https://github.com/protocolbuffers/protobuf/blob/master/docs/csharp/proto2.md + * Add length checks to ExtensionCollection (#6759) + * Optimize parsing of some primitive and wrapper types (#6843) + * Use 3 parameter Encoding.GetString for default string values (#6828) + * Change _Extensions property to normal body rather than expression (#6856) + + Objective C + * Fixed unaligned reads for 32bit arm with newer Xcode versions (#6678) + + +2019-09-03 version 3.10.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + C++ + * Switch the proto parser to the faster MOMI parser. + * Properly escape Struct keys in the proto3 JSON serializer. + * Fix crash on uninitialized map entries. + * Informed the compiler of has-bit invariant to produce better code + * Unused imports of files defining descriptor extensions will now be reported + * Add proto2::util::RemoveSubranges to remove multiple subranges in linear time. + * Added BaseTextGenerator::GetCurrentIndentationSize() + * Made implicit weak fields compatible with the Apple linker + * Support 32 bit values for ProtoStreamObjectWriter to Struct. + * Removed the internal-only header coded_stream_inl.h and the internal-only methods defined there. + * Enforced no SWIG wrapping of descriptor_database.h (other headers already had this restriction). + * Implementation of the equivalent of the MOMI parser for serialization. This removes one of the two serialization routines, by making the fast array serialization routine completely general. SerializeToCodedStream can now be implemented in terms of the much much faster array serialization. The array serialization regresses slightly, but when array serialization is not possible this wins big. + * Do not convert unknown field name to snake case to accurately report error. + * Fix a UBSAN warnings. (#6333) + * Add podspec for C++ (#6404) + * protoc: fix source code info location for missing label (#6436) + * C++ Add move constructor for Reflection's SetString (#6477) + + Java + * Call loadDescriptor outside of synchronized block to remove one possible source of deadlock. + * Have oneof enums implement a separate interface (other than EnumLite) for clarity. + * Opensource Android Memory Accessors + * Update TextFormat to make use of the new TypeRegistry. + * Support getFieldBuilder and getRepeatedFieldBuilder in ExtendableBuilder + * Update JsonFormat to make use of the new TypeRegistry. + * Add proguard config generator for GmmBenchmarkSuiteLite. + * Change ProtobufArrayList to use Object[] instead of ArrayList for 5-10% faster parsing + * Implement ProtobufArrayList.add(E) for 20% (5%-40%) faster overall protolite2 parsing + * Make a copy of JsonFormat.TypeRegistry at the protobuf top level package. This will eventually replace JsonFormat.TypeRegistry. + * Fix javadoc warnings in generated files (#6231) + * Java: Add Automatic-Module-Name entries to the Manifest (#6568) + + Python + * Add descriptor methods in descriptor_pool are deprecated. + * Uses explicit imports to prevent multithread test failures in py3. + * Added __delitem__ for Python extension dict + * Update six version to 1.12.0 and fix legacy_create_init issue (#6391) + + JavaScript + * Remove deprecated boolean option to getResultBase64String(). + * Fix sint64 zig-zag encoding. + * Simplify hash64 string conversion to avoid DIGIT array. Should reduce overhead if these functions aren't used, and be more efficient by avoiding linear array searches. + * Change the parameter types of binaryReaderFn in ExtensionFieldBinaryInfo to (number, ?, ?). + * Create dates.ts and time_of_days.ts to mirror Java versions. This is a near-identical conversion of c.g.type.util.{Dates,TimeOfDays} respectively. + * Migrate moneys to TypeScript. + + PHP + * Fix incorrect leap day for Timestamp (#6696) + * Initialize well known type values (#6713) + + Ruby + * Fix scope resolution for Google namespace (#5878) + * Support hashes for struct initializers (#5716) + * Optimized away the creation of empty string objects. (#6502) + * Roll forward Ruby upb changes now that protobuf Ruby build is fixed (#5866) + * Optimized layout_mark() for Ruby (#6521) + * Optimization for layout_init() (#6547) + * Fix for GC of Ruby map frames. (#6533) + * Fixed leap year handling by reworking upb_mktime() -> upb_timegm(). (#6695) + + Objective C + * Remove OSReadLittle* due to alignment requirements (#6678) + * Don't use unions and instead use memcpy for the type swaps. (#6672) + + Other + * Override CocoaPods module to lowercase (#6464) + + +2019-06-28 version 3.9.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + C++ + * Optimize and simplify implementation of RepeatedPtrFieldBase + * Don't create unnecessary unknown field sets. + * Remove branch from accessors to repeated field element array. + * Added delimited parse and serialize util. + * Reduce size by not emitting constants for fieldnumbers + * Fix a bug when comparing finite and infinite field values with explicit tolerances. + * TextFormat::Parser should use a custom Finder to look up extensions by number if one is provided. + * Add MessageLite::Utf8DebugString() to make MessageLite more compatible with Message. + * Fail fast for better performance in DescriptorPool::FindExtensionByNumber() if descriptor has no defined extensions. + * Adding the file name to help debug colliding extensions + * Added FieldDescriptor::PrintableNameForExtension() and DescriptorPool::FindExtensionByPrintableName(). + The latter will replace Reflection::FindKnownExtensionByName(). + * Replace NULL with nullptr + * Created a new Add method in repeated field that allows adding a range of elements all at once. + * Enabled enum name-to-value mapping functions for C++ lite + * Avoid dynamic initialization in descriptor.proto generated code + * Move stream functions to MessageLite from Message. + * Move all zero_copy_stream functionality to io_lite. + * Do not create array of matched fields for simple repeated fields + * Enabling silent mode by default to reduce make compilation noise. (#6237) + + Java + * Expose TextFormat.Printer and make it configurable. Deprecate the static methods. + * Library for constructing google.protobuf.Struct and google.protobuf.Value + * Make OneofDescriptor extend GenericDescriptor. + * Expose streamingness of service methods from MethodDescriptor. + * Fix a bug where TextFormat fails to parse Any filed with > 1 embedded message sub-fields. + * Establish consistent JsonFormat behavior for nulls in oneofs, regardless of order. + * Update GSON version to 3.8.5. (#6268) + * Add `protobuf_java_lite` Bazel target. (#6177) + + Python + * Change implementation of Name() for enums that allow aliases in proto2 in Python + to be in line with claims in C++ implementation (to return first value). + * Explicitly say what field cannot be set when the new value fails a type check. + * Duplicate register in descriptor pool will raise errors + * Add __slots__ to all well_known_types classes, custom attributes are not allowed anymore. + * text_format only present 8 valid digits for float fields by default + + JavaScript + * Add Oneof enum to the list of goog.provide + + PHP + * Make php message class final to avoid mocking. (#6277) + * Rename get/setXXXValue to get/setXXXWrapper. (#6295) + + Ruby + * Remove to_hash methods. (#6166) + + +2019-04-29 version 3.8.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + C++ + * Use std::atomic in case of myriad2 platform + * Always declare enums to be int-sized + * Added DebugString() and ShortDebugString() methods on MessageLite + * Specialized different parse loop control flows + * Make hasbits potentially in register. The or's start forming an obstacle because it's a read modify store on the same mem address on each iteration. + * Move to an internal MACRO for parser validity checks. + * Improve map parsing performance. + * Make MergePartialFromCodedStream non virtual. This allows direct calls, potential inlining and is also a code health improvement + * Add an overall limit to parse_context to prevent reading past it. This allows to remove a annoying level of indirection. + * Fix a mistake, we shouldn't verify map key/value strings for utf8 in opt mode for proto2. + * Further improvements to cut binary size. + * Prepare to make MergePartialFromCodedStream non-virtual. + * A report on some interesting behavior change in python (caused by b/27494216) made me realize there is a check that needs to be done in case the parse ended on a end group tag. + * Add a note of caution to the comments around skip in CodedOutputStream. + * Simplify end check. + * Add overload for ParseMessage for MessageLite/Message types. If the explicit type is not known inlining won't help de-virtualizing the virtual call. + * Reduce linker input. It turns out that ParseMessage is not inlined, producing template instantiations that are used only once and save nothing but cost more. + * Improve the parser. + * [c++17] Changed proto2::RepeatedPtrField iterators to no longer derive from the deprecated std::iterator class. + * Change the default value of case_insensitive_enum_parsing to false for JsonStringToMessage. + * Add a warning if a field name doesn't match the style guide. + * Fix TextFormat not round-trip correctly when float value is max float. + * Added locationed info for some errors at compiler + * Python reserved keywords are now working with getattr()/setattr() for most descriptors. + * Added AllowUnknownField() in text_format + * Append '_' to C++ reserved keywords for message, enum, extension + * Fix MSVC warning C4244 in protobuf's parse_context.h. + * Updating Iterators to be compatible with C++17 in MSVC. + * Use capability annotation in mutex.h + * Fix "UndefinedBehaviorSanitizer: cfi-bad-type" + * CriticalSectionLock class as a lightweight replacement for std::mutex on Windows platforms. + * Removed vestigial wire_format_lite_inl.h + + C# + * Added System.Memory dependency. + + Java + * Make Java protoc code generator ignore optimize_for LITE_RUNTIME. Users should instead use the Java lite protoc plugin. + * Change Extension getMessageDefaultInstance() to return Message instead of MessageLite. + * Prevent malicious input streams from leaking buffers for ByteString or ByteBuffer parsing. + * Release new Javalite runtime. + * Show warning in case potential file name conflict. + * Allow Java reserved keywords to be used in extensions. + * Added setAllowUnknownFields() in text format + * Add memoization to ExtensionRegistryLite.getEmptyRegistry() + * Improve performance of CodedOutputStream.writeUInt32NoTag + * Add an optimized mismatch-finding algorithm to UnsafeUtil. + * When serializing uint32 varints, check that we have MAX_VARINT32_SIZE bytes left, not just MAX_VARINT_SIZE. + * Minor optimization to RopeByteString.PieceIterator + + JavaScript + * Simplify generated toObject code when the default value is used. + + Python + * Changes implementation of Name() for enums that allow aliases in proto2 in Python to be in line with claims in C++ implementation (to return first value). + * Added double_format option in text format printer. + * Added iter and __contains__ to extension dict + * Added allow_unknown_field option in python text format parser + * Fixed Timestamp.ToDatetime() loses precision issue + * Support unknown field in text format printer. + * Float field will be convert to inf if bigger than struct.unpack('f', b'\xff\xff\x7f\x7f')[0] which is about 3.4028234664e+38, + convert to -inf if smaller than -3.4028234664e+38 + * Allowed casting str->bytes in Message.__setstate__ + + Ruby + * Helper methods to get enum name for Ruby. + + +2019-01-24 version 3.7.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + C++ + * Introduced new MOMI (maybe-outside-memory-interval) parser. + * Add an option to json_util to parse enum as case-insensitive. In the future, enum parsing in json_util will become case-sensitive. + * Added conformance test for enum aliases + * Added support for --cpp_out=speed:... + * Added use of C++ override keyword where appropriate + * Many other cleanups and fixes. + + Java + * Fix illegal reflective access warning in JDK 9+ + * Add BOM + + Python + * Added Python 3.7 compatibility. + * Modified ParseFromString to return bytes parsed . + * Introduce Proto C API. + * FindFileContainingSymbol in descriptor pool is now able to find field and enum values. + * reflection.MakeClass() and reflection.ParseMessage() are deprecated. + * Added DescriptorPool.FindMethodByName() method in pure python (c extension already has it) + * Flipped proto3 to preserve unknown fields by default. + * Added support for memoryview in python3 proto message parsing. + * Added MergeFrom for repeated scalar fields in c extension (pure python already has it) + * Surrogates are now rejected at setters in python3. + * Added public unknown field API. + * RecursionLimit is also set to max if allow_oversize_protos is enabled. + * Disallow duplicate scalars in proto3 text_format parse. + * Fix some segment faults for c extension map field. + + PHP + * Most issues for json encoding/decoding in the c extension have been fixed. There are still some edge cases not fixed. For more details, check conformance/failure_list_php_c.txt. + * Supports php 7.3 + * Added helper methods to convert between enum values and names. + * Allow setting/getting wrapper message fields using primitive values. + * Various bug fixes. + + Ruby + * Ruby 2.6 support. + * Drops support for ruby < 2.3. + * Most issues for json encoding/decoding in the c extension have been fixed. There are still some edge cases not fixed. For more details, check conformance/failure_list_ruby.txt. + * Json parsing can specify an option to ignore unknown fields: msg.decode_json(data, {ignore_unknown_fields: true}). + * Added support for proto2 syntax (partially). + * Various bug fixes. + + Csharp + * More support for FieldMask include merge, intersect and more. + * Increasing the default recursion limit to 100. + * Support loading FileDescriptors dynamically. + * Provide access to comments from descriptors. + * Added Any.Is method. + * Compatible with C# 6 + * Added IComparable and comparison operators on Timestamp. + + Objective C + * Add ability to introspect list of enum values (#4678) + * Copy the value when setting message/data fields (#5215) + * Support suppressing the objc package prefix checks on a list of files (#5309) + * More complete keyword and NSObject method (via categories) checks for field names, can result in more fields being rename, but avoids the collisions at runtime (#5289) + * Small fixes to TextFormat generation for extensions (#5362) + * Provide more details/context in deprecation messages (#5412) + * Array/Dictionary enumeration blocks NS_NOESCAPE annotation for Swift (#5421) + * Properly annotate extensions for ARC when their names imply behaviors (#5427) + * Enum alias name collision improvements (#5480) + + +2018-07-27 version 3.6.1 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + C++ + * Introduced workaround for Windows issue with std::atomic and std::once_flag + initialization (#4777, #4773). + + PHP + * Added compatibility with PHP 7.3 (#4898). + + Ruby + * Fixed Ruby crash involving Any encoding (#4718). + +2018-06-01 version 3.6.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + + C++ + * Starting from this release, we now require C++11. For those we cannot yet + upgrade to C++11, we will try to keep the 3.5.x branch updated with + critical bug fixes only. If you have any concerns about this, please + comment on issue #2780. + * Moved to C++11 types like std::atomic and std::unique_ptr and away from our + old custom-built equivalents. + * Added support for repeated message fields in lite protos using implicit + weak fields. This is an experimental feature that allows the linker to + strip out more unused messages than previously was possible. + * Fixed SourceCodeInfo for interpreted options and extension range options. + * Fixed always_print_enums_as_ints option for JSON serialization. + * Added support for ignoring unknown enum values when parsing JSON. + * Create std::string in Arena memory. + * Fixed ValidateDateTime to correctly check the day. + * Fixed bug in ZeroCopyStreamByteSink. + * Various other cleanups and fixes. + + Java + * Dropped support for Java 6. + * Added a UTF-8 decoder that uses Unsafe to directly decode a byte buffer. + * Added deprecation annotations to generated code for deprecated oneof + fields. + * Fixed map field serialization in DynamicMessage. + * Cleanup and documentation for Java Lite runtime. + * Various other fixes and cleanups + * Fixed unboxed arraylists to handle an edge case + * Improved performance for copying between unboxed arraylists + * Fixed lite protobuf to avoid Java compiler warnings + * Improved test coverage for lite runtime + * Performance improvements for lite runtime + + Python + * Fixed bytes/string map key incompatibility between C++ and pure-Python + implementations (issue #4029) + * Added __init__.py files to compiler and util subpackages + * Use /MT for all Windows versions + * Fixed an issue affecting the Python-C++ implementation when used with + Cython (issue #2896) + * Various text format fixes + * Various fixes to resolve behavior differences between the pure-Python and + Python-C++ implementations + + PHP + * Added php_metadata_namespace to control the file path of generated metadata + file. + * Changed generated classes of nested message/enum. E.g., Foo.Bar, which + previously generates Foo_Bar, now generates Foo/Bar + * Added array constructor. When creating a message, users can pass a php + array whose content is field name to value pairs into constructor. The + created message will be initialized according to the array. Note that + message field should use a message value instead of a sub-array. + * Various bug fixes. + + Objective-C + * We removed some helper class methods from GPBDictionary to shrink the size + of the library, the functionary is still there, but you may need to do some + specific +alloc / -init… methods instead. + * Minor improvements in the performance of object field getters/setters by + avoiding some memory management overhead. + * Fix a memory leak during the raising of some errors. + * Make header importing completely order independent. + * Small code improvements for things the undefined behaviors compiler option + was flagging. + + Ruby + * Added ruby_package file option to control the module of generated class. + * Various bug fixes. + + Javascript + * Allow setting string to int64 field. + + Csharp + * Unknown fields are now parsed and then sent back on the wire. They can be + discarded at parse time via a CodedInputStream option. + * Movement towards working with .NET 3.5 and Unity + * Expression trees are no longer used + * AOT generics issues in Unity/il2cpp have a workaround (see this commit for + details) + * Floating point values are now compared bitwise (affects NaN value + comparisons) + * The default size limit when parsing is now 2GB rather than 64MB + * MessageParser now supports parsing from a slice of a byte array + * JSON list parsing now accepts null values where the underlying proto + representation does + +2017-12-20 version 3.5.1 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + Planned Future Changes + * Make C++ implementation C++11 only: we plan to require C++11 to build + protobuf code starting from 3.6.0 release. Please join this github issue: + https://github.com/protocolbuffers/protobuf/issues/2780 to provide your feedback. + + protoc + * Fixed a bug introduced in 3.5.0 and protoc in Windows now accepts non-ascii + characters in paths again. + + C++ + * Removed several usages of C++11 features in the code base. + * Fixed some compiler warnings. + + PHP + * Fixed memory leak in C-extension implementation. + * Added discardUnknokwnFields API. + * Removed duplicated typedef in C-extension headers. + * Avoided calling private php methods (timelib_update_ts). + * Fixed Any.php to use fully-qualified name for DescriptorPool. + + Ruby + * Added Google_Protobuf_discard_unknown for discarding unknown fields in + messages. + + C# + * Unknown fields are now preserved by default. + * Floating point values are now bitwise compared, affecting message equality + check and Contains() API in map and repeated fields. + + +2017-11-13 version 3.5.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) + Planned Future Changes + * Make C++ implementation C++11 only: we plan to require C++11 to build + protobuf code starting from 3.6.0 release. Please join this github issue: + https://github.com/protocolbuffers/protobuf/issues/2780 to provide your feedback. + + General + * Unknown fields are now preserved in proto3 for most of the language + implementations for proto3 by default. See the per-language section for + details. + * reserve keyword are now supported in enums + + C++ + * Proto3 messages are now preserving unknown fields by default. If you rely on + unknowns fields being dropped. Please use DiscardUnknownFields() explicitly. + * Deprecated the unsafe_arena_release_* and unsafe_arena_add_allocated_* + methods for string fields. + * Added move constructor and move assignment to RepeatedField, + RepeatedPtrField and google::protobuf::Any. + * Added perfect forwarding in Arena::CreateMessage + * In-progress experimental support for implicit weak fields with lite protos. + This feature allows the linker to strip out more unused messages and reduce + binary size. + * Various performance optimizations. + + Java + * Proto3 messages are now preserving unknown fields by default. If you’d like + to drop unknown fields, please use the DiscardUnknownFieldsParser API. For + example: + Parser parser = DiscardUnknownFieldsParser.wrap(Foo.parser()); + Foo foo = parser.parseFrom(input); + * Added a new CodedInputStream decoder for Iterable with direct + ByteBuffers. + * TextFormat now prints unknown length-delimited fields as messages if + possible. + * FieldMaskUtil.merge() no longer creates unnecessary empty messages when a + message field is unset in both source message and destination message. + * Various performance optimizations. + + Python + * Proto3 messages are now preserving unknown fields by default. Use + message.DiscardUnknownFields() to drop unknown fields. + * Add FieldDescriptor.file in generated code. + * Add descriptor pool FindOneofByName in pure python. + * Change unknown enum values into unknown field set . + * Add more Python dict/list compatibility for Struct/ListValue. + * Add utf-8 support for text_format.Merge()/Parse(). + * Support numeric unknown enum values for proto3 JSON format. + * Add warning for Unexpected end-group tag in cpp extension. + + PHP + * Proto3 messages are now preserving unknown fields. + * Provide well known type messages in runtime. + * Add prefix ‘PB’ to generated class of reserved names. + * Fixed all conformance tests for encode/decode json in php runtime. C + extension needs more work. + + Objective-C + * Fixed some issues around copying of messages with unknown fields and then + mutating the unknown fields in the copy. + + C# + * Added unknown field support in JsonParser. + * Fixed oneof message field merge. + * Simplify parsing messages from array slices. + + Ruby + * Unknown fields are now preserved by default. + * Fixed several bugs for segment fault. + + Javascript + * Decoder can handle both paced and unpacked data no matter how the proto is + defined. + * Decoder now accept long varint for 32 bit integers. + + 2017-08-14 version 3.4.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) Planned Future Changes * There are some changes that are not included in this release but are planned @@ -13,14 +938,14 @@ For issues and discussions: - https://github.com/google/protobuf/issues/272 + https://github.com/protocolbuffers/protobuf/issues/272 - Make C++ implementation C++11 only: we plan to require C++11 to build protobuf code starting from 3.5.0 or 3.6.0 release, after unknown fields semantic changes are finished. Please join this github issue: - https://github.com/google/protobuf/issues/2780 + https://github.com/protocolbuffers/protobuf/issues/2780 to provide your feedback. @@ -89,6 +1014,9 @@ * Added pretty-print filter to text format. * Services and method descriptors are always printed even if generic_service option is turned off. + * Note: AppEngine 2.5 is deprecated on June 2017 that AppEngine 2.5 will + never update protobuf runtime. Users who depend on AppEngine 2.5 should use + old protoc. PHP * Support PHP generic services. Specify file option php_generic_service=true @@ -137,14 +1065,14 @@ for the timeline and follow up this github issue: - https://github.com/google/protobuf/issues/272 + https://github.com/protocolbuffers/protobuf/issues/272 for discussion. - Make C++ implementation C++11 only: we plan to require C++11 to build protobuf code starting from 3.4.0 or 3.5.0 release. Please join this github issue: - https://github.com/google/protobuf/issues/2780 + https://github.com/protocolbuffers/protobuf/issues/2780 to provide your feedback. @@ -371,7 +1299,7 @@ details about APIs. Objective-C - * Helpers are now provided for working the the Any well known type (see + * Helpers are now provided for working the Any well known type (see GPBWellKnownTypes.h for the api additions). * Some improvements in startup code (especially when extensions aren’t used). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000000..db1ff31cac6c4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,98 @@ +# Contributing to Protocol Buffers + +We welcome your contributions to protocol buffers. This doc describes the +process to contribute patches to protobuf and the general guidelines we +expect contributors to follow. + +## Before You Start + +We accept patches in the form of github pull requests. If you are new to +github, please read [How to create github pull requests](https://help.github.com/articles/about-pull-requests/) +first. + +### Contributor License Agreements + +Contributions to this project must be accompanied by a Contributor License +Agreement. You (or your employer) retain the copyright to your contribution, +this simply gives us permission to use and redistribute your contributions +as part of the project. + +* If you are an individual writing original source code and you're sure you + own the intellectual property, then you'll need to sign an [individual CLA](https://cla.developers.google.com/about/google-individual?csw=1). +* If you work for a company that wants to allow you to contribute your work, + then you'll need to sign a [corporate CLA](https://cla.developers.google.com/about/google-corporate?csw=1). + +### Coding Style + +This project follows [Google’s Coding Style Guides](https://github.com/google/styleguide). +Before sending out your pull request, please familiarize yourself with the +corresponding style guides and make sure the proposed code change is style +conforming. + +## Contributing Process + +Most pull requests should go to the master branch and the change will be +included in the next major/minor version release (e.g., 3.6.0 release). If you +need to include a bug fix in a patch release (e.g., 3.5.2), make sure it’s +already merged to master, and then create a pull request cherry-picking the +commits from master branch to the release branch (e.g., branch 3.5.x). + +For each pull request, a protobuf team member will be assigned to review the +pull request. For minor cleanups, the pull request may be merged right away +after an initial review. For larger changes, you will likely receive multiple +rounds of comments and it may take some time to complete. We will try to keep +our response time within 7-days but if you don’t get any response in a few +days, feel free to comment on the threads to get our attention. We also expect +you to respond to our comments within a reasonable amount of time. If we don’t +hear from you for 2 weeks or longer, we may close the pull request. You can +still send the pull request again once you have time to work on it. + +Once a pull request is merged, we will take care of the rest and get it into +the final release. + +## Pull Request Guidelines + +* If you are a Googler, it is preferable to first create an internal CL and + have it reviewed and submitted. The code propagation process will deliver the + change to GitHub. +* Create small PRs that are narrowly focused on addressing a single concern. + We often receive PRs that are trying to fix several things at a time, but if + only one fix is considered acceptable, nothing gets merged and both author's + & review's time is wasted. Create more PRs to address different concerns and + everyone will be happy. +* For speculative changes, consider opening an issue and discussing it first. + If you are suggesting a behavioral or API change, make sure you get explicit + support from a protobuf team member before sending us the pull request. +* Provide a good PR description as a record of what change is being made and + why it was made. Link to a GitHub issue if it exists. +* Don't fix code style and formatting unless you are already changing that + line to address an issue. PRs with irrelevant changes won't be merged. If + you do want to fix formatting or style, do that in a separate PR. +* Unless your PR is trivial, you should expect there will be reviewer comments + that you'll need to address before merging. We expect you to be reasonably + responsive to those comments, otherwise the PR will be closed after 2-3 weeks + of inactivity. +* Maintain clean commit history and use meaningful commit messages. PRs with + messy commit history are difficult to review and won't be merged. Use rebase + -i upstream/master to curate your commit history and/or to bring in latest + changes from master (but avoid rebasing in the middle of a code review). +* Keep your PR up to date with upstream/master (if there are merge conflicts, + we can't really merge your change). +* All tests need to be passing before your change can be merged. We recommend + you run tests locally before creating your PR to catch breakages early on. + Ultimately, the green signal will be provided by our testing infrastructure. + The reviewer will help you if there are test failures that seem not related + to the change you are making. + +## Reviewer Guidelines + +* Make sure that all tests are passing before approval. +* Apply the "release notes: yes" label if the pull request's description should + be included in the next release (e.g., any new feature / bug fix). + Apply the "release notes: no" label if the pull request's description should + not be included in the next release (e.g., refactoring changes that does not + change behavior, integration from Google internal, updating tests, etc.). +* Apply the appropriate language label (e.g., C++, Java, Python, etc.) to the + pull request. This will make it easier to identify which languages the pull + request affects, allowing us to better identify appropriate reviewer, create + a better release note, and make it easier to identify issues in the future. diff --git a/LICENSE b/LICENSE index f028c82324202..19b305b00060a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,14 +1,4 @@ -This license applies to all parts of Protocol Buffers except the following: - - - Atomicops support for generic gcc, located in - src/google/protobuf/stubs/atomicops_internals_generic_gcc.h. - This file is copyrighted by Red Hat Inc. - - - Atomicops support for AIX/POWER, located in - src/google/protobuf/stubs/atomicops_internals_power.h. - This file is copyrighted by Bloomberg Finance LP. - -Copyright 2014, Google Inc. All rights reserved. +Copyright 2008 Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/Makefile.am b/Makefile.am index 52d7ce9d69e0a..53b259480ab89 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,8 +8,8 @@ AUTOMAKE_OPTIONS = foreign # the right time. SUBDIRS = . src -# Always include gmock in distributions. -DIST_SUBDIRS = $(subdirs) src conformance benchmarks +# Always include third_party directories in distributions. +DIST_SUBDIRS = src conformance benchmarks third_party/googletest # Build gmock before we build protobuf tests. We don't add gmock to SUBDIRS # because then "make check" would also build and run all of gmock's own tests, @@ -18,8 +18,8 @@ DIST_SUBDIRS = $(subdirs) src conformance benchmarks # the installed version of gmock if there is one. check-local: @echo "Making lib/libgmock.a lib/libgmock_main.a in gmock" - @cd gmock && $(MAKE) $(AM_MAKEFLAGS) lib/libgmock.la lib/libgmock_main.la - @cd gmock/gtest && $(MAKE) $(AM_MAKEFLAGS) lib/libgtest.la lib/libgtest_main.la + @cd third_party/googletest/googletest && $(MAKE) $(AM_MAKEFLAGS) lib/libgtest.la lib/libgtest_main.la + @cd third_party/googletest/googlemock && $(MAKE) $(AM_MAKEFLAGS) lib/libgmock.la lib/libgmock_main.la # We would like to clean gmock when "make clean" is invoked. But we have to # be careful because clean-local is also invoked during "make distclean", but @@ -28,9 +28,9 @@ check-local: # cd to the directory again and "make clean" it will fail. So, check that the # Makefile exists before recursing. clean-local: - @if test -e gmock/Makefile; then \ - echo "Making clean in gmock"; \ - cd gmock && $(MAKE) $(AM_MAKEFLAGS) clean; \ + @if test -e third_party/googletest/Makefile; then \ + echo "Making clean in googletest"; \ + cd third_party/googletest && $(MAKE) $(AM_MAKEFLAGS) clean; \ fi; \ if test -e conformance/Makefile; then \ echo "Making clean in conformance"; \ @@ -49,88 +49,154 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = protobuf.pc protobuf-lite.pc csharp_EXTRA_DIST= \ + global.json \ csharp/.gitignore \ csharp/CHANGES.txt \ + csharp/Google.Protobuf.Tools.targets \ csharp/Google.Protobuf.Tools.nuspec \ csharp/README.md \ csharp/build_packages.bat \ csharp/build_tools.sh \ + csharp/buildall.bat \ csharp/buildall.sh \ csharp/generate_protos.sh \ - csharp/global.json \ + csharp/install_dotnet_sdk.ps1 \ csharp/keys/Google.Protobuf.public.snk \ csharp/keys/Google.Protobuf.snk \ csharp/keys/README.md \ + csharp/protos/README.md \ + csharp/protos/map_unittest_proto3.proto \ + csharp/protos/old_extensions1.proto \ + csharp/protos/old_extensions2.proto \ + csharp/protos/unittest_issue6936_a.proto \ + csharp/protos/unittest_issue6936_b.proto \ + csharp/protos/unittest_issue6936_c.proto \ csharp/protos/unittest_custom_options_proto3.proto \ + csharp/protos/unittest_import_public_proto3.proto \ + csharp/protos/unittest_import_public.proto \ + csharp/protos/unittest_import_proto3.proto \ + csharp/protos/unittest_import.proto \ csharp/protos/unittest_issues.proto \ + csharp/protos/unittest_proto3.proto \ + csharp/protos/unittest_selfreferential_options.proto \ + csharp/protos/unittest.proto \ csharp/src/AddressBook/AddPerson.cs \ csharp/src/AddressBook/Addressbook.cs \ csharp/src/AddressBook/AddressBook.csproj \ csharp/src/AddressBook/ListPeople.cs \ csharp/src/AddressBook/Program.cs \ csharp/src/AddressBook/SampleUsage.cs \ + csharp/src/Google.Protobuf.Benchmarks/BenchmarkDatasetConfig.cs \ + csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs \ + csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs \ + csharp/src/Google.Protobuf.Benchmarks/ByteStringBenchmark.cs \ + csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj \ + csharp/src/Google.Protobuf.Benchmarks/GoogleMessageBenchmark.cs \ + csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs \ + csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs \ + csharp/src/Google.Protobuf.Benchmarks/Program.cs \ + csharp/src/Google.Protobuf.Benchmarks/wrapper_benchmark_messages.proto \ + csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs \ + csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs \ + csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs \ csharp/src/Google.Protobuf.Conformance/Conformance.cs \ csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj \ csharp/src/Google.Protobuf.Conformance/Program.cs \ csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj \ csharp/src/Google.Protobuf.JsonDump/Program.cs \ + csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs \ csharp/src/Google.Protobuf.Test/ByteStringTest.cs \ csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs \ csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs \ csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs \ csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs \ + csharp/src/Google.Protobuf.Test/Collections/ProtobufEqualityComparersTest.cs \ csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs \ csharp/src/Google.Protobuf.Test/Compatibility/PropertyInfoExtensionsTest.cs \ csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs \ csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs \ csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs \ csharp/src/Google.Protobuf.Test/EqualityTester.cs \ + csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs \ csharp/src/Google.Protobuf.Test/FieldCodecTest.cs \ + csharp/src/Google.Protobuf.Test/FieldMaskTreeTest.cs \ csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs \ + csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs \ csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj \ csharp/src/Google.Protobuf.Test/IssuesTest.cs \ csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs \ csharp/src/Google.Protobuf.Test/JsonParserTest.cs \ csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs \ - csharp/src/Google.Protobuf.Test/Program.cs \ + csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs \ + csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs \ + csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs \ + csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs \ + csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs \ csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs \ + csharp/src/Google.Protobuf.Test/Reflection/DescriptorDeclarationTest.cs \ csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs \ csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs \ csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs \ csharp/src/Google.Protobuf.Test/SampleEnum.cs \ csharp/src/Google.Protobuf.Test/SampleMessages.cs \ + csharp/src/Google.Protobuf.Test/SampleNaNs.cs \ csharp/src/Google.Protobuf.Test/TestCornerCases.cs \ - csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs \ - csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs \ - csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs \ - csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs \ - csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs \ - csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs \ - csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs \ - csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs \ - csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/Google.Protobuf.Test.TestProtos.csproj \ + csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936A.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/ForeignMessagePartial.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/OldExtensions1.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/OldExtensions2.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs \ csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs \ csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs \ csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs \ csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs \ csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs \ + csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs \ + csharp/src/Google.Protobuf.Test/testprotos.pb \ csharp/src/Google.Protobuf.sln \ csharp/src/Google.Protobuf/ByteArray.cs \ csharp/src/Google.Protobuf/ByteString.cs \ + csharp/src/Google.Protobuf/ByteStringAsync.cs \ csharp/src/Google.Protobuf/CodedInputStream.cs \ csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs \ csharp/src/Google.Protobuf/CodedOutputStream.cs \ + csharp/src/Google.Protobuf/Collections/Lists.cs \ csharp/src/Google.Protobuf/Collections/MapField.cs \ + csharp/src/Google.Protobuf/Collections/ProtobufEqualityComparers.cs \ csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs \ csharp/src/Google.Protobuf/Collections/RepeatedField.cs \ + csharp/src/Google.Protobuf/Compatibility/MethodInfoExtensions.cs \ csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs \ csharp/src/Google.Protobuf/Compatibility/StreamExtensions.cs \ csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs \ + csharp/src/Google.Protobuf/Extension.cs \ + csharp/src/Google.Protobuf/ExtensionRegistry.cs \ + csharp/src/Google.Protobuf/ExtensionSet.cs \ + csharp/src/Google.Protobuf/ExtensionValue.cs \ csharp/src/Google.Protobuf/FieldCodec.cs \ + csharp/src/Google.Protobuf/FieldMaskTree.cs \ csharp/src/Google.Protobuf/FrameworkPortability.cs \ csharp/src/Google.Protobuf/Google.Protobuf.csproj \ + csharp/src/Google.Protobuf/IBufferMessage.cs \ csharp/src/Google.Protobuf/ICustomDiagnosticMessage.cs \ csharp/src/Google.Protobuf/IDeepCloneable.cs \ + csharp/src/Google.Protobuf/IExtendableMessage.cs \ csharp/src/Google.Protobuf/IMessage.cs \ csharp/src/Google.Protobuf/InvalidJsonException.cs \ csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs \ @@ -141,16 +207,26 @@ csharp_EXTRA_DIST= \ csharp/src/Google.Protobuf/LimitedInputStream.cs \ csharp/src/Google.Protobuf/MessageExtensions.cs \ csharp/src/Google.Protobuf/MessageParser.cs \ + csharp/src/Google.Protobuf/ObjectIntPair.cs \ + csharp/src/Google.Protobuf/ParseContext.cs \ + csharp/src/Google.Protobuf/ParserInternalState.cs \ + csharp/src/Google.Protobuf/ParsingPrimitives.cs \ + csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs \ + csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs \ csharp/src/Google.Protobuf/ProtoPreconditions.cs \ + csharp/src/Google.Protobuf/SegmentedBufferHelper.cs \ csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs \ csharp/src/Google.Protobuf/Reflection/CustomOptions.cs \ csharp/src/Google.Protobuf/Reflection/Descriptor.cs \ csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs \ + csharp/src/Google.Protobuf/Reflection/DescriptorDeclaration.cs \ csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs \ csharp/src/Google.Protobuf/Reflection/DescriptorUtil.cs \ csharp/src/Google.Protobuf/Reflection/DescriptorValidationException.cs \ csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs \ csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs \ + csharp/src/Google.Protobuf/Reflection/ExtensionAccessor.cs \ + csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs \ csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs \ csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs \ csharp/src/Google.Protobuf/Reflection/FieldType.cs \ @@ -165,7 +241,6 @@ csharp_EXTRA_DIST= \ csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs \ csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs \ csharp/src/Google.Protobuf/Reflection/PackageDescriptor.cs \ - csharp/src/Google.Protobuf/Reflection/PartialClasses.cs \ csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs \ csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs \ csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs \ @@ -188,10 +263,20 @@ csharp_EXTRA_DIST= \ csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs \ csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs \ csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs \ - csharp/src/Google.Protobuf/WireFormat.cs + csharp/src/Google.Protobuf/WireFormat.cs \ + csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs \ + csharp/src/Google.Protobuf/WritingPrimitives.cs \ + csharp/src/Google.Protobuf/WriterInternalState.cs \ + csharp/src/Google.Protobuf/WriteContext.cs \ + csharp/src/Google.Protobuf/WriteBufferHelper.cs \ + csharp/src/Google.Protobuf/UnknownField.cs \ + csharp/src/Google.Protobuf/UnknownFieldSet.cs \ + csharp/src/Google.Protobuf/UnsafeByteOperations.cs java_EXTRA_DIST= \ java/README.md \ + java/bom/pom.xml \ + java/core/BUILD \ java/core/generate-sources-build.xml \ java/core/generate-test-sources-build.xml \ java/core/pom.xml \ @@ -199,16 +284,25 @@ java_EXTRA_DIST= java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java \ java/core/src/main/java/com/google/protobuf/AbstractParser.java \ java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java \ + java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java \ + java/core/src/main/java/com/google/protobuf/Android.java \ + java/core/src/main/java/com/google/protobuf/ArrayDecoders.java \ + java/core/src/main/java/com/google/protobuf/BinaryReader.java \ + java/core/src/main/java/com/google/protobuf/BinaryWriter.java \ java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java \ java/core/src/main/java/com/google/protobuf/BlockingService.java \ java/core/src/main/java/com/google/protobuf/BooleanArrayList.java \ + java/core/src/main/java/com/google/protobuf/BufferAllocator.java \ java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java \ java/core/src/main/java/com/google/protobuf/ByteOutput.java \ java/core/src/main/java/com/google/protobuf/ByteString.java \ java/core/src/main/java/com/google/protobuf/CodedInputStream.java \ + java/core/src/main/java/com/google/protobuf/CodedInputStreamReader.java \ java/core/src/main/java/com/google/protobuf/CodedOutputStream.java \ - java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java \ + java/core/src/main/java/com/google/protobuf/CodedOutputStreamWriter.java \ + java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java \ java/core/src/main/java/com/google/protobuf/Descriptors.java \ + java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java \ java/core/src/main/java/com/google/protobuf/DoubleArrayList.java \ java/core/src/main/java/com/google/protobuf/DynamicMessage.java \ java/core/src/main/java/com/google/protobuf/ExperimentalApi.java \ @@ -217,36 +311,65 @@ java_EXTRA_DIST= java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java \ java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java \ java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java \ + java/core/src/main/java/com/google/protobuf/ExtensionSchema.java \ + java/core/src/main/java/com/google/protobuf/ExtensionSchemaFull.java \ + java/core/src/main/java/com/google/protobuf/ExtensionSchemaLite.java \ + java/core/src/main/java/com/google/protobuf/ExtensionSchemas.java \ + java/core/src/main/java/com/google/protobuf/FieldInfo.java \ java/core/src/main/java/com/google/protobuf/FieldSet.java \ + java/core/src/main/java/com/google/protobuf/FieldType.java \ java/core/src/main/java/com/google/protobuf/FloatArrayList.java \ java/core/src/main/java/com/google/protobuf/GeneratedMessage.java \ + java/core/src/main/java/com/google/protobuf/GeneratedMessageInfoFactory.java \ java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java \ java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java \ java/core/src/main/java/com/google/protobuf/IntArrayList.java \ java/core/src/main/java/com/google/protobuf/Internal.java \ java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \ + java/core/src/main/java/com/google/protobuf/IterableByteBufferInputStream.java \ + java/core/src/main/java/com/google/protobuf/JavaType.java \ java/core/src/main/java/com/google/protobuf/LazyField.java \ java/core/src/main/java/com/google/protobuf/LazyFieldLite.java \ java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java \ java/core/src/main/java/com/google/protobuf/LazyStringList.java \ + java/core/src/main/java/com/google/protobuf/ListFieldSchema.java \ java/core/src/main/java/com/google/protobuf/LongArrayList.java \ + java/core/src/main/java/com/google/protobuf/ManifestSchemaFactory.java \ java/core/src/main/java/com/google/protobuf/MapEntry.java \ java/core/src/main/java/com/google/protobuf/MapEntryLite.java \ java/core/src/main/java/com/google/protobuf/MapField.java \ java/core/src/main/java/com/google/protobuf/MapFieldLite.java \ + java/core/src/main/java/com/google/protobuf/MapFieldSchema.java \ + java/core/src/main/java/com/google/protobuf/MapFieldSchemaFull.java \ + java/core/src/main/java/com/google/protobuf/MapFieldSchemaLite.java \ + java/core/src/main/java/com/google/protobuf/MapFieldSchemas.java \ java/core/src/main/java/com/google/protobuf/Message.java \ + java/core/src/main/java/com/google/protobuf/MessageInfo.java \ + java/core/src/main/java/com/google/protobuf/MessageInfoFactory.java \ java/core/src/main/java/com/google/protobuf/MessageLite.java \ java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java \ java/core/src/main/java/com/google/protobuf/MessageLiteToString.java \ java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java \ java/core/src/main/java/com/google/protobuf/MessageReflection.java \ + java/core/src/main/java/com/google/protobuf/MessageSchema.java \ + java/core/src/main/java/com/google/protobuf/MessageSetSchema.java \ java/core/src/main/java/com/google/protobuf/MutabilityOracle.java \ + java/core/src/main/java/com/google/protobuf/NewInstanceSchema.java \ + java/core/src/main/java/com/google/protobuf/NewInstanceSchemaFull.java \ + java/core/src/main/java/com/google/protobuf/NewInstanceSchemaLite.java \ + java/core/src/main/java/com/google/protobuf/NewInstanceSchemas.java \ java/core/src/main/java/com/google/protobuf/NioByteString.java \ + java/core/src/main/java/com/google/protobuf/OneofInfo.java \ java/core/src/main/java/com/google/protobuf/Parser.java \ java/core/src/main/java/com/google/protobuf/PrimitiveNonBoxingCollection.java \ + java/core/src/main/java/com/google/protobuf/ProtoSyntax.java \ + java/core/src/main/java/com/google/protobuf/Protobuf.java \ java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java \ + java/core/src/main/java/com/google/protobuf/ProtobufLists.java \ java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java \ java/core/src/main/java/com/google/protobuf/ProtocolStringList.java \ + java/core/src/main/java/com/google/protobuf/RawMessageInfo.java \ + java/core/src/main/java/com/google/protobuf/Reader.java \ java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java \ java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java \ java/core/src/main/java/com/google/protobuf/RopeByteString.java \ @@ -254,38 +377,60 @@ java_EXTRA_DIST= java/core/src/main/java/com/google/protobuf/RpcChannel.java \ java/core/src/main/java/com/google/protobuf/RpcController.java \ java/core/src/main/java/com/google/protobuf/RpcUtil.java \ + java/core/src/main/java/com/google/protobuf/Schema.java \ + java/core/src/main/java/com/google/protobuf/SchemaFactory.java \ + java/core/src/main/java/com/google/protobuf/SchemaUtil.java \ java/core/src/main/java/com/google/protobuf/Service.java \ java/core/src/main/java/com/google/protobuf/ServiceException.java \ java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java \ java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java \ java/core/src/main/java/com/google/protobuf/SmallSortedMap.java \ + java/core/src/main/java/com/google/protobuf/StructuralMessageInfo.java \ java/core/src/main/java/com/google/protobuf/TextFormat.java \ java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java \ java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java \ java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java \ + java/core/src/main/java/com/google/protobuf/TypeRegistry.java \ java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java \ + java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java \ java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java \ java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java \ + java/core/src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java \ + java/core/src/main/java/com/google/protobuf/UnknownFieldSetSchema.java \ java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java \ java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java \ java/core/src/main/java/com/google/protobuf/UnsafeUtil.java \ java/core/src/main/java/com/google/protobuf/Utf8.java \ java/core/src/main/java/com/google/protobuf/WireFormat.java \ + java/core/src/main/java/com/google/protobuf/Writer.java \ java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java \ + java/core/src/test/java/com/google/protobuf/AbstractProto2LiteSchemaTest.java \ + java/core/src/test/java/com/google/protobuf/AbstractProto2SchemaTest.java \ + java/core/src/test/java/com/google/protobuf/AbstractProto3LiteSchemaTest.java \ + java/core/src/test/java/com/google/protobuf/AbstractProto3SchemaTest.java \ + java/core/src/test/java/com/google/protobuf/AbstractSchemaTest.java \ java/core/src/test/java/com/google/protobuf/AnyTest.java \ + java/core/src/test/java/com/google/protobuf/ArrayDecodersTest.java \ + java/core/src/test/java/com/google/protobuf/BinaryProtocolTest.java \ java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java \ java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java \ java/core/src/test/java/com/google/protobuf/ByteBufferWriterTest.java \ java/core/src/test/java/com/google/protobuf/ByteStringTest.java \ + java/core/src/test/java/com/google/protobuf/CachedFieldSizeTest.java \ java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java \ + java/core/src/test/java/com/google/protobuf/CodedAdapterTest.java \ java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java \ java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java \ + java/core/src/test/java/com/google/protobuf/DecodeUtf8Test.java \ java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java \ java/core/src/test/java/com/google/protobuf/DescriptorsTest.java \ java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java \ java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java \ java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java \ java/core/src/test/java/com/google/protobuf/EnumTest.java \ + java/core/src/test/java/com/google/protobuf/ExperimentalMessageFactory.java \ + java/core/src/test/java/com/google/protobuf/ExperimentalSerializationUtil.java \ + java/core/src/test/java/com/google/protobuf/ExperimentalTestDataProvider.java \ java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java \ java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java \ java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java \ @@ -300,17 +445,32 @@ java_EXTRA_DIST= java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java \ java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java \ java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java \ - java/core/src/test/java/com/google/protobuf/LiteTest.java \ java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java \ java/core/src/test/java/com/google/protobuf/LongArrayListTest.java \ java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java \ java/core/src/test/java/com/google/protobuf/MapForProto2Test.java \ + java/core/src/test/java/com/google/protobuf/MapLiteTest.java \ java/core/src/test/java/com/google/protobuf/MapTest.java \ java/core/src/test/java/com/google/protobuf/MessageTest.java \ java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java \ java/core/src/test/java/com/google/protobuf/NioByteStringTest.java \ + java/core/src/test/java/com/google/protobuf/PackedFieldTest.java \ java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java \ + java/core/src/test/java/com/google/protobuf/ParserLiteTest.java \ java/core/src/test/java/com/google/protobuf/ParserTest.java \ + java/core/src/test/java/com/google/protobuf/Proto2ExtensionLookupSchemaTest.java \ + java/core/src/test/java/com/google/protobuf/Proto2LiteSchemaTest.java \ + java/core/src/test/java/com/google/protobuf/Proto2MessageFactory.java \ + java/core/src/test/java/com/google/protobuf/Proto2MessageInfoFactory.java \ + java/core/src/test/java/com/google/protobuf/Proto2MessageLiteFactory.java \ + java/core/src/test/java/com/google/protobuf/Proto2SchemaTest.java \ + java/core/src/test/java/com/google/protobuf/Proto2UnknownEnumValueTest.java \ + java/core/src/test/java/com/google/protobuf/Proto3LiteSchemaTest.java \ + java/core/src/test/java/com/google/protobuf/Proto3MessageFactory.java \ + java/core/src/test/java/com/google/protobuf/Proto3MessageInfoFactory.java \ + java/core/src/test/java/com/google/protobuf/Proto3MessageLiteFactory.java \ + java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java \ + java/core/src/test/java/com/google/protobuf/Proto3SchemaTest.java \ java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java \ java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java \ java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java \ @@ -320,25 +480,36 @@ java_EXTRA_DIST= java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java \ java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java \ java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java \ + java/core/src/test/java/com/google/protobuf/TestSchemas.java \ + java/core/src/test/java/com/google/protobuf/TestSchemasLite.java \ java/core/src/test/java/com/google/protobuf/TestUtil.java \ java/core/src/test/java/com/google/protobuf/TestUtilLite.java \ java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java \ java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java \ java/core/src/test/java/com/google/protobuf/TextFormatTest.java \ + java/core/src/test/java/com/google/protobuf/TypeRegistryTest.java \ java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java \ - java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java \ java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java \ java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java \ + java/core/src/test/java/com/google/protobuf/Utf8Test.java \ + java/core/src/test/java/com/google/protobuf/Utf8Utils.java \ java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java \ + java/core/src/test/java/com/google/protobuf/WireFormatLiteTest.java \ java/core/src/test/java/com/google/protobuf/WireFormatTest.java \ + java/core/src/test/java/com/google/protobuf/WrappersLiteOfMethodTest.java \ + java/core/src/test/java/com/google/protobuf/WrappersOfMethodTest.java \ java/core/src/test/proto/com/google/protobuf/any_test.proto \ + java/core/src/test/proto/com/google/protobuf/cached_field_size_test.proto \ + java/core/src/test/proto/com/google/protobuf/deprecated_file.proto \ java/core/src/test/proto/com/google/protobuf/field_presence_test.proto \ java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto \ java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto \ java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto \ java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto \ java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto \ + java/core/src/test/proto/com/google/protobuf/map_lite_test.proto \ java/core/src/test/proto/com/google/protobuf/map_test.proto \ + java/core/src/test/proto/com/google/protobuf/message_lite_extension_util_test.proto\ java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto \ java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto \ java/core/src/test/proto/com/google/protobuf/nested_extension.proto \ @@ -348,68 +519,49 @@ java_EXTRA_DIST= java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto \ java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto \ java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto \ + java/core/src/test/proto/com/google/protobuf/packed_field_test.proto \ + java/core/src/test/proto/com/google/protobuf/proto2_message.proto \ + java/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto \ + java/core/src/test/proto/com/google/protobuf/proto2_unknown_enum_values.proto \ + java/core/src/test/proto/com/google/protobuf/proto3_message.proto \ + java/core/src/test/proto/com/google/protobuf/proto3_message_lite.proto \ java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto \ java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto \ java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto \ java/core/src/test/proto/com/google/protobuf/test_custom_options.proto \ java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto \ + java/core/src/test/proto/com/google/protobuf/wrappers_test.proto \ + java/lite.md \ + java/lite/BUILD \ java/lite/generate-sources-build.xml \ java/lite/generate-test-sources-build.xml \ + java/lite/lite.awk \ java/lite/pom.xml \ + java/lite/process-lite-sources-build.xml \ + java/lite/src/test/java/com/google/protobuf/LiteTest.java \ + java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java \ java/pom.xml \ + java/util/BUILD \ java/util/pom.xml \ java/util/src/main/java/com/google/protobuf/util/Durations.java \ java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java \ java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java \ java/util/src/main/java/com/google/protobuf/util/JsonFormat.java \ java/util/src/main/java/com/google/protobuf/util/TimeUtil.java \ + java/util/src/main/java/com/google/protobuf/util/Structs.java \ java/util/src/main/java/com/google/protobuf/util/Timestamps.java \ + java/util/src/main/java/com/google/protobuf/util/Values.java \ java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java \ java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java \ java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java \ + java/util/src/test/java/com/google/protobuf/util/StructsTest.java \ java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java \ + java/util/src/test/java/com/google/protobuf/util/ValuesTest.java \ java/util/src/test/proto/com/google/protobuf/util/json_test.proto -javanano_EXTRA_DIST= \ - javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java \ - javanano/src/main/java/com/google/protobuf/nano/FieldData.java \ - javanano/src/main/java/com/google/protobuf/nano/FieldArray.java \ - javanano/src/main/java/com/google/protobuf/nano/WireFormatNano.java \ - javanano/src/main/java/com/google/protobuf/nano/Extension.java \ - javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java \ - javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java \ - javanano/src/main/java/com/google/protobuf/nano/MessageNano.java \ - javanano/src/main/java/com/google/protobuf/nano/InternalNano.java \ - javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java \ - javanano/src/main/java/com/google/protobuf/nano/MapFactories.java \ - javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java \ - javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java \ - javanano/src/test/java/com/google/protobuf/nano/unittest_accessors_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_extension_repeated_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_has_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_single_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/NanoTest.java \ - javanano/src/test/java/com/google/protobuf/nano/unittest_simple_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_import_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_packables_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_extension_singular_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_recursive_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_stringutf8_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_multiple_nano.proto \ - javanano/src/test/java/com/google/protobuf/nano/map_test.proto \ - javanano/README.md \ - javanano/pom.xml - objectivec_EXTRA_DIST= \ + objectivec/.clang-format \ + objectivec/BUILD \ objectivec/DevTools/check_version_stamps.sh \ objectivec/DevTools/compile_testing_protos.sh \ objectivec/DevTools/full_mac_build.sh \ @@ -417,25 +569,19 @@ objectivec_EXTRA_DIST= \ objectivec/DevTools/pddm_tests.py \ objectivec/generate_well_known_types.sh \ objectivec/google/protobuf/Any.pbobjc.h \ - objectivec/google/protobuf/Any.pbobjc.m \ objectivec/google/protobuf/Api.pbobjc.h \ - objectivec/google/protobuf/Api.pbobjc.m \ objectivec/google/protobuf/Duration.pbobjc.h \ - objectivec/google/protobuf/Duration.pbobjc.m \ objectivec/google/protobuf/Empty.pbobjc.h \ - objectivec/google/protobuf/Empty.pbobjc.m \ objectivec/google/protobuf/FieldMask.pbobjc.h \ - objectivec/google/protobuf/FieldMask.pbobjc.m \ objectivec/google/protobuf/SourceContext.pbobjc.h \ - objectivec/google/protobuf/SourceContext.pbobjc.m \ objectivec/google/protobuf/Struct.pbobjc.h \ - objectivec/google/protobuf/Struct.pbobjc.m \ objectivec/google/protobuf/Timestamp.pbobjc.h \ - objectivec/google/protobuf/Timestamp.pbobjc.m \ objectivec/google/protobuf/Type.pbobjc.h \ - objectivec/google/protobuf/Type.pbobjc.m \ objectivec/google/protobuf/Wrappers.pbobjc.h \ - objectivec/google/protobuf/Wrappers.pbobjc.m \ + objectivec/GPBAny.pbobjc.h \ + objectivec/GPBAny.pbobjc.m \ + objectivec/GPBApi.pbobjc.h \ + objectivec/GPBApi.pbobjc.m \ objectivec/GPBArray.h \ objectivec/GPBArray.m \ objectivec/GPBArray_PackagePrivate.h \ @@ -452,10 +598,16 @@ objectivec_EXTRA_DIST= \ objectivec/GPBDictionary.h \ objectivec/GPBDictionary.m \ objectivec/GPBDictionary_PackagePrivate.h \ + objectivec/GPBDuration.pbobjc.h \ + objectivec/GPBDuration.pbobjc.m \ + objectivec/GPBEmpty.pbobjc.h \ + objectivec/GPBEmpty.pbobjc.m \ objectivec/GPBExtensionInternals.h \ objectivec/GPBExtensionInternals.m \ objectivec/GPBExtensionRegistry.h \ objectivec/GPBExtensionRegistry.m \ + objectivec/GPBFieldMask.pbobjc.h \ + objectivec/GPBFieldMask.pbobjc.m \ objectivec/GPBMessage.h \ objectivec/GPBMessage.m \ objectivec/GPBMessage_PackagePrivate.h \ @@ -466,6 +618,14 @@ objectivec_EXTRA_DIST= \ objectivec/GPBRootObject.m \ objectivec/GPBRootObject_PackagePrivate.h \ objectivec/GPBRuntimeTypes.h \ + objectivec/GPBSourceContext.pbobjc.h \ + objectivec/GPBSourceContext.pbobjc.m \ + objectivec/GPBStruct.pbobjc.h \ + objectivec/GPBStruct.pbobjc.m \ + objectivec/GPBTimestamp.pbobjc.h \ + objectivec/GPBTimestamp.pbobjc.m \ + objectivec/GPBType.pbobjc.h \ + objectivec/GPBType.pbobjc.m \ objectivec/GPBUnknownField.h \ objectivec/GPBUnknownField.m \ objectivec/GPBUnknownField_PackagePrivate.h \ @@ -479,16 +639,26 @@ objectivec_EXTRA_DIST= \ objectivec/GPBWellKnownTypes.m \ objectivec/GPBWireFormat.h \ objectivec/GPBWireFormat.m \ + objectivec/GPBWrappers.pbobjc.h \ + objectivec/GPBWrappers.pbobjc.m \ objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj \ objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata \ + objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist \ objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \ objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \ objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \ objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj \ objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/contents.xcworkspacedata \ + objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist \ objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \ objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \ objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \ + objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj \ + objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata \ + objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist \ + objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \ + objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \ + objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \ objectivec/README.md \ objectivec/Tests/CocoaPods/OSXCocoaPodsTester/OSXCocoaPodsTester.xcodeproj/project.pbxproj \ objectivec/Tests/CocoaPods/OSXCocoaPodsTester/OSXCocoaPodsTester.xcodeproj/project.xcworkspace/contents.xcworkspacedata \ @@ -523,6 +693,31 @@ objectivec_EXTRA_DIST= \ objectivec/Tests/GPBArrayTests.m \ objectivec/Tests/GPBCodedInputStreamTests.m \ objectivec/Tests/GPBCodedOuputStreamTests.m \ + objectivec/Tests/GPBCompileTest01.m \ + objectivec/Tests/GPBCompileTest02.m \ + objectivec/Tests/GPBCompileTest03.m \ + objectivec/Tests/GPBCompileTest04.m \ + objectivec/Tests/GPBCompileTest05.m \ + objectivec/Tests/GPBCompileTest06.m \ + objectivec/Tests/GPBCompileTest07.m \ + objectivec/Tests/GPBCompileTest08.m \ + objectivec/Tests/GPBCompileTest09.m \ + objectivec/Tests/GPBCompileTest10.m \ + objectivec/Tests/GPBCompileTest11.m \ + objectivec/Tests/GPBCompileTest12.m \ + objectivec/Tests/GPBCompileTest13.m \ + objectivec/Tests/GPBCompileTest14.m \ + objectivec/Tests/GPBCompileTest15.m \ + objectivec/Tests/GPBCompileTest16.m \ + objectivec/Tests/GPBCompileTest17.m \ + objectivec/Tests/GPBCompileTest18.m \ + objectivec/Tests/GPBCompileTest19.m \ + objectivec/Tests/GPBCompileTest20.m \ + objectivec/Tests/GPBCompileTest21.m \ + objectivec/Tests/GPBCompileTest22.m \ + objectivec/Tests/GPBCompileTest23.m \ + objectivec/Tests/GPBCompileTest24.m \ + objectivec/Tests/GPBCompileTest25.m \ objectivec/Tests/GPBConcurrencyTests.m \ objectivec/Tests/GPBDescriptorTests.m \ objectivec/Tests/GPBDictionaryTests+Bool.m \ @@ -534,6 +729,7 @@ objectivec_EXTRA_DIST= \ objectivec/Tests/GPBDictionaryTests.m \ objectivec/Tests/GPBDictionaryTests.pddm \ objectivec/Tests/GPBExtensionRegistryTest.m \ + objectivec/Tests/GPBMessageTests+ClassNames.m \ objectivec/Tests/GPBMessageTests+Merge.m \ objectivec/Tests/GPBMessageTests+Runtime.m \ objectivec/Tests/GPBMessageTests+Serialization.m \ @@ -549,20 +745,7 @@ objectivec_EXTRA_DIST= \ objectivec/Tests/GPBUtilitiesTests.m \ objectivec/Tests/GPBWellKnownTypesTest.m \ objectivec/Tests/GPBWireFormatTests.m \ - objectivec/Tests/iOSTestHarness/AppDelegate.m \ - objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings \ - objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json \ - objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png \ - objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6_2x.png \ - objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png \ - objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7_2x.png \ - objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png \ - objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6_2x.png \ - objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_2x.png \ - objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_3x.png \ - objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json \ - objectivec/Tests/iOSTestHarness/Info.plist \ - objectivec/Tests/iOSTestHarness/LaunchScreen.xib \ + objectivec/Tests/text_format_extensions_unittest_data.txt \ objectivec/Tests/text_format_map_unittest_data.txt \ objectivec/Tests/text_format_unittest_data.txt \ objectivec/Tests/unittest_cycle.proto \ @@ -576,6 +759,7 @@ objectivec_EXTRA_DIST= \ objectivec/Tests/unittest_extension_chain_f.proto \ objectivec/Tests/unittest_extension_chain_g.proto \ objectivec/Tests/unittest_objc.proto \ + objectivec/Tests/unittest_objc_options.proto \ objectivec/Tests/unittest_objc_startup.proto \ objectivec/Tests/unittest_runtime_proto2.proto \ objectivec/Tests/unittest_runtime_proto3.proto \ @@ -584,124 +768,207 @@ objectivec_EXTRA_DIST= \ Protobuf.podspec php_EXTRA_DIST= \ - php/ext/google/protobuf/utf8.h \ - php/ext/google/protobuf/message.c \ - php/ext/google/protobuf/utf8.c \ - php/ext/google/protobuf/package.xml \ - php/ext/google/protobuf/upb.h \ + composer.json \ + php/README.md \ + php/composer.json \ + php/ext/google/protobuf/arena.c \ + php/ext/google/protobuf/arena.h \ php/ext/google/protobuf/array.c \ - php/ext/google/protobuf/encode_decode.c \ - php/ext/google/protobuf/protobuf.h \ - php/ext/google/protobuf/type_check.c \ + php/ext/google/protobuf/array.h \ + php/ext/google/protobuf/config.m4 \ + php/ext/google/protobuf/convert.c \ + php/ext/google/protobuf/convert.h \ php/ext/google/protobuf/def.c \ - php/ext/google/protobuf/storage.c \ + php/ext/google/protobuf/def.h \ php/ext/google/protobuf/map.c \ - php/ext/google/protobuf/config.m4 \ - php/ext/google/protobuf/upb.c \ + php/ext/google/protobuf/map.h \ + php/ext/google/protobuf/message.c \ + php/ext/google/protobuf/message.h \ + php/ext/google/protobuf/names.c \ + php/ext/google/protobuf/names.h \ + php/ext/google/protobuf/package.xml \ + php/ext/google/protobuf/php-upb.c \ + php/ext/google/protobuf/php-upb.h \ php/ext/google/protobuf/protobuf.c \ - php/src/phpdoc.dist.xml \ + php/ext/google/protobuf/protobuf.h \ + php/ext/google/protobuf/wkt.inc \ + php/generate_descriptor_protos.sh \ + php/phpunit.xml \ + php/prepare_c_extension.sh \ + php/release.sh \ + php/src/GPBMetadata/Google/Protobuf/Any.php \ + php/src/GPBMetadata/Google/Protobuf/Api.php \ + php/src/GPBMetadata/Google/Protobuf/Duration.php \ + php/src/GPBMetadata/Google/Protobuf/FieldMask.php \ + php/src/GPBMetadata/Google/Protobuf/GPBEmpty.php \ + php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php \ + php/src/GPBMetadata/Google/Protobuf/SourceContext.php \ + php/src/GPBMetadata/Google/Protobuf/Struct.php \ + php/src/GPBMetadata/Google/Protobuf/Timestamp.php \ + php/src/GPBMetadata/Google/Protobuf/Type.php \ + php/src/GPBMetadata/Google/Protobuf/Wrappers.php \ + php/src/Google/Protobuf/Any.php \ + php/src/Google/Protobuf/Api.php \ + php/src/Google/Protobuf/BoolValue.php \ + php/src/Google/Protobuf/BytesValue.php \ php/src/Google/Protobuf/Descriptor.php \ php/src/Google/Protobuf/DescriptorPool.php \ + php/src/Google/Protobuf/DoubleValue.php \ + php/src/Google/Protobuf/Duration.php \ + php/src/Google/Protobuf/Enum.php \ php/src/Google/Protobuf/EnumDescriptor.php \ + php/src/Google/Protobuf/EnumValue.php \ php/src/Google/Protobuf/EnumValueDescriptor.php \ + php/src/Google/Protobuf/Field.php \ php/src/Google/Protobuf/FieldDescriptor.php \ - php/src/Google/Protobuf/OneofDescriptor.php \ + php/src/Google/Protobuf/FieldMask.php \ + php/src/Google/Protobuf/Field/Cardinality.php \ + php/src/Google/Protobuf/Field_Cardinality.php \ + php/src/Google/Protobuf/Field/Kind.php \ + php/src/Google/Protobuf/Field_Kind.php \ + php/src/Google/Protobuf/FloatValue.php \ + php/src/Google/Protobuf/GPBEmpty.php \ + php/src/Google/Protobuf/Int32Value.php \ + php/src/Google/Protobuf/Int64Value.php \ + php/src/Google/Protobuf/Internal/AnyBase.php \ php/src/Google/Protobuf/Internal/CodedInputStream.php \ php/src/Google/Protobuf/Internal/CodedOutputStream.php \ + php/src/Google/Protobuf/Internal/Descriptor.php \ php/src/Google/Protobuf/Internal/DescriptorPool.php \ - php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php \ - php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php \ php/src/Google/Protobuf/Internal/DescriptorProto.php \ - php/src/Google/Protobuf/Internal/Descriptor.php \ + php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php \ + php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php \ php/src/Google/Protobuf/Internal/EnumBuilderContext.php \ php/src/Google/Protobuf/Internal/EnumDescriptor.php \ php/src/Google/Protobuf/Internal/EnumDescriptorProto.php \ + php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php \ php/src/Google/Protobuf/Internal/EnumOptions.php \ php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php \ php/src/Google/Protobuf/Internal/EnumValueOptions.php \ - php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php \ + php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php \ php/src/Google/Protobuf/Internal/FieldDescriptorProto.php \ php/src/Google/Protobuf/Internal/FieldDescriptor.php \ - php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php \ - php/src/Google/Protobuf/Internal/FieldOptions_CType.php \ - php/src/Google/Protobuf/Internal/FieldOptions_JSType.php \ + php/src/Google/Protobuf/Internal/FieldDescriptorProto.php \ + php/src/Google/Protobuf/Internal/FieldDescriptorProto/Label.php \ + php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php \ php/src/Google/Protobuf/Internal/FieldOptions.php \ + php/src/Google/Protobuf/Internal/FieldOptions/CType.php \ + php/src/Google/Protobuf/Internal/FieldOptions/JSType.php \ + php/src/Google/Protobuf/Internal/FileDescriptor.php \ php/src/Google/Protobuf/Internal/FileDescriptorProto.php \ php/src/Google/Protobuf/Internal/FileDescriptorSet.php \ - php/src/Google/Protobuf/Internal/FileDescriptor.php \ - php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php \ php/src/Google/Protobuf/Internal/FileOptions.php \ - php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php \ - php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php \ - php/src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php \ + php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php \ php/src/Google/Protobuf/Internal/GPBDecodeException.php \ php/src/Google/Protobuf/Internal/GPBJsonWire.php \ php/src/Google/Protobuf/Internal/GPBLabel.php \ php/src/Google/Protobuf/Internal/GPBType.php \ php/src/Google/Protobuf/Internal/GPBUtil.php \ - php/src/Google/Protobuf/Internal/GPBWireType.php \ php/src/Google/Protobuf/Internal/GPBWire.php \ + php/src/Google/Protobuf/Internal/GPBWireType.php \ + php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php \ + php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php \ + php/src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php \ php/src/Google/Protobuf/Internal/HasPublicDescriptorTrait.php \ php/src/Google/Protobuf/Internal/MapEntry.php \ - php/src/Google/Protobuf/Internal/MapFieldIter.php \ php/src/Google/Protobuf/Internal/MapField.php \ + php/src/Google/Protobuf/Internal/MapFieldIter.php \ + php/src/Google/Protobuf/Internal/Message.php \ php/src/Google/Protobuf/Internal/MessageBuilderContext.php \ php/src/Google/Protobuf/Internal/MessageOptions.php \ - php/src/Google/Protobuf/Internal/Message.php \ php/src/Google/Protobuf/Internal/MethodDescriptorProto.php \ - php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php \ php/src/Google/Protobuf/Internal/MethodOptions.php \ - php/src/Google/Protobuf/Internal/OneofDescriptorProto.php \ + php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php \ php/src/Google/Protobuf/Internal/OneofDescriptor.php \ + php/src/Google/Protobuf/Internal/OneofDescriptorProto.php \ php/src/Google/Protobuf/Internal/OneofField.php \ php/src/Google/Protobuf/Internal/OneofOptions.php \ php/src/Google/Protobuf/Internal/RawInputStream.php \ - php/src/Google/Protobuf/Internal/RepeatedFieldIter.php \ php/src/Google/Protobuf/Internal/RepeatedField.php \ + php/src/Google/Protobuf/Internal/RepeatedFieldIter.php \ php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php \ php/src/Google/Protobuf/Internal/ServiceOptions.php \ - php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php \ php/src/Google/Protobuf/Internal/SourceCodeInfo.php \ - php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php \ + php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php \ + php/src/Google/Protobuf/Internal/TimestampBase.php \ php/src/Google/Protobuf/Internal/UninterpretedOption.php \ - php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php \ - php/tests/array_test.php \ + php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php \ + php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php \ + php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php \ + php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php \ + php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php \ + php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php \ + php/src/Google/Protobuf/Internal/FieldOptions_CType.php \ + php/src/Google/Protobuf/Internal/FieldOptions_JSType.php \ + php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php \ + php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php \ + php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php \ + php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php \ + php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php \ + php/src/Google/Protobuf/ListValue.php \ + php/src/Google/Protobuf/Method.php \ + php/src/Google/Protobuf/Mixin.php \ + php/src/Google/Protobuf/NullValue.php \ + php/src/Google/Protobuf/OneofDescriptor.php \ + php/src/Google/Protobuf/Option.php \ + php/src/Google/Protobuf/SourceContext.php \ + php/src/Google/Protobuf/StringValue.php \ + php/src/Google/Protobuf/Struct.php \ + php/src/Google/Protobuf/Syntax.php \ + php/src/Google/Protobuf/Timestamp.php \ + php/src/Google/Protobuf/Type.php \ + php/src/Google/Protobuf/UInt32Value.php \ + php/src/Google/Protobuf/UInt64Value.php \ + php/src/Google/Protobuf/Value.php \ + php/src/phpdoc.dist.xml \ + php/tests/ArrayTest.php \ php/tests/autoload.php \ + php/tests/bootstrap_phpunit.php \ php/tests/compatibility_test.sh \ - php/tests/descriptors_test.php \ - php/tests/encode_decode_test.php \ + php/tests/compile_extension.sh \ + php/tests/DescriptorsTest.php \ + php/tests/EncodeDecodeTest.php \ php/tests/gdb_test.sh \ - php/tests/generated_class_test.php \ - php/tests/generated_phpdoc_test.php \ - php/tests/generated_service_test.php \ - php/tests/map_field_test.php \ + php/tests/generate_protos.sh \ + php/tests/GeneratedClassTest.php \ + php/tests/GeneratedPhpdocTest.php \ + php/tests/GeneratedServiceTest.php \ + php/tests/MapFieldTest.php \ php/tests/memory_leak_test.php \ - php/tests/php_implementation_test.php \ + php/tests/multirequest.php \ + php/tests/multirequest.sh \ + php/tests/PhpImplementationTest.php \ + php/tests/proto/empty/echo.proto \ + php/tests/proto/test.proto \ php/tests/proto/test_descriptors.proto \ php/tests/proto/test_empty_php_namespace.proto \ php/tests/proto/test_import_descriptor_proto.proto \ php/tests/proto/test_include.proto \ - php/tests/proto/test.proto \ php/tests/proto/test_no_namespace.proto \ php/tests/proto/test_php_namespace.proto \ php/tests/proto/test_prefix.proto \ + php/tests/proto/test_reserved_enum_lower.proto \ + php/tests/proto/test_reserved_enum_upper.proto \ + php/tests/proto/test_reserved_enum_value_lower.proto \ + php/tests/proto/test_reserved_enum_value_upper.proto \ + php/tests/proto/test_reserved_message_lower.proto \ + php/tests/proto/test_reserved_message_upper.proto \ php/tests/proto/test_service.proto \ php/tests/proto/test_service_namespace.proto \ + php/tests/proto/test_wrapper_type_setters.proto \ php/tests/test.sh \ php/tests/test_base.php \ php/tests/test_util.php \ - php/tests/well_known_test.php \ php/tests/undefined_test.php \ - php/README.md \ - php/composer.json \ - php/generate_descriptor_protos.sh \ - php/phpunit.xml \ - composer.json + php/tests/valgrind.supp \ + php/tests/WellKnownTest.php \ + php/tests/WrapperTypeSettersTest.php python_EXTRA_DIST= \ python/MANIFEST.in \ python/google/__init__.py \ python/google/protobuf/__init__.py \ + python/google/protobuf/compiler/__init__.py \ python/google/protobuf/descriptor.py \ python/google/protobuf/descriptor_database.py \ python/google/protobuf/descriptor_pool.py \ @@ -720,6 +987,7 @@ python_EXTRA_DIST= \ python/google/protobuf/internal/descriptor_test.py \ python/google/protobuf/internal/encoder.py \ python/google/protobuf/internal/enum_type_wrapper.py \ + python/google/protobuf/internal/extension_dict.py \ python/google/protobuf/internal/factory_test1.proto \ python/google/protobuf/internal/factory_test2.proto \ python/google/protobuf/internal/file_options_test.proto \ @@ -728,6 +996,7 @@ python_EXTRA_DIST= \ python/google/protobuf/internal/import_test_package/inner.proto \ python/google/protobuf/internal/import_test_package/outer.proto \ python/google/protobuf/internal/json_format_test.py \ + python/google/protobuf/internal/keywords_test.py \ python/google/protobuf/internal/message_factory_test.py \ python/google/protobuf/internal/message_listener.py \ python/google/protobuf/internal/message_set_extensions.proto \ @@ -736,6 +1005,7 @@ python_EXTRA_DIST= \ python/google/protobuf/internal/more_extensions.proto \ python/google/protobuf/internal/more_extensions_dynamic.proto \ python/google/protobuf/internal/more_messages.proto \ + python/google/protobuf/internal/no_package.proto \ python/google/protobuf/internal/packed_field_test.proto \ python/google/protobuf/internal/proto_builder_test.py \ python/google/protobuf/internal/python_message.py \ @@ -744,6 +1014,7 @@ python_EXTRA_DIST= \ python/google/protobuf/internal/service_reflection_test.py \ python/google/protobuf/internal/symbol_database_test.py \ python/google/protobuf/internal/test_bad_identifiers.proto \ + python/google/protobuf/internal/test_proto3_optional.proto \ python/google/protobuf/internal/test_util.py \ python/google/protobuf/internal/testing_refleaks.py \ python/google/protobuf/internal/text_encoding_test.py \ @@ -760,6 +1031,7 @@ python_EXTRA_DIST= \ python/google/protobuf/message.py \ python/google/protobuf/message_factory.py \ python/google/protobuf/python_protobuf.h \ + python/google/protobuf/proto_api.h \ python/google/protobuf/proto_builder.py \ python/google/protobuf/pyext/README \ python/google/protobuf/pyext/__init__.py \ @@ -778,6 +1050,10 @@ python_EXTRA_DIST= \ python/google/protobuf/pyext/map_container.h \ python/google/protobuf/pyext/message.cc \ python/google/protobuf/pyext/message.h \ + python/google/protobuf/pyext/field.cc \ + python/google/protobuf/pyext/field.h \ + python/google/protobuf/pyext/unknown_fields.cc \ + python/google/protobuf/pyext/unknown_fields.h \ python/google/protobuf/pyext/message_factory.cc \ python/google/protobuf/pyext/message_factory.h \ python/google/protobuf/pyext/message_module.cc \ @@ -795,6 +1071,7 @@ python_EXTRA_DIST= \ python/google/protobuf/symbol_database.py \ python/google/protobuf/text_encoding.py \ python/google/protobuf/text_format.py \ + python/google/protobuf/util/__init__.py \ python/release.sh \ python/mox.py \ python/setup.cfg \ @@ -817,17 +1094,21 @@ ruby_EXTRA_DIST= \ ruby/compatibility_tests/v3.0.0/test.sh \ ruby/compatibility_tests/v3.0.0/Rakefile \ ruby/compatibility_tests/v3.0.0/README.md \ + ruby/ext/google/protobuf_c/convert.c \ + ruby/ext/google/protobuf_c/convert.h \ ruby/ext/google/protobuf_c/defs.c \ - ruby/ext/google/protobuf_c/encode_decode.c \ + ruby/ext/google/protobuf_c/defs.h \ ruby/ext/google/protobuf_c/extconf.rb \ ruby/ext/google/protobuf_c/map.c \ + ruby/ext/google/protobuf_c/map.h \ ruby/ext/google/protobuf_c/message.c \ + ruby/ext/google/protobuf_c/message.h \ ruby/ext/google/protobuf_c/protobuf.c \ ruby/ext/google/protobuf_c/protobuf.h \ ruby/ext/google/protobuf_c/repeated_field.c \ - ruby/ext/google/protobuf_c/storage.c \ - ruby/ext/google/protobuf_c/upb.c \ - ruby/ext/google/protobuf_c/upb.h \ + ruby/ext/google/protobuf_c/repeated_field.h \ + ruby/ext/google/protobuf_c/ruby-upb.c \ + ruby/ext/google/protobuf_c/ruby-upb.h \ ruby/ext/google/protobuf_c/wrap_memcpy.c \ ruby/google-protobuf.gemspec \ ruby/lib/google/protobuf/message_exts.rb \ @@ -838,13 +1119,15 @@ ruby_EXTRA_DIST= \ ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java \ ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java \ ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java \ + ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java \ ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java \ ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java \ - ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java \ ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java \ + ruby/src/main/java/com/google/protobuf/jruby/RubyFileBuilderContext.java \ + ruby/src/main/java/com/google/protobuf/jruby/RubyFileDescriptor.java \ ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java \ - ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java \ ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java \ + ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java \ ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java \ ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java \ ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java \ @@ -853,13 +1136,27 @@ ruby_EXTRA_DIST= \ ruby/src/main/java/com/google/protobuf/jruby/Utils.java \ ruby/src/main/java/google/ProtobufJavaService.java \ ruby/src/main/sentinel.proto \ + ruby/tests/basic_proto2.rb \ + ruby/tests/basic_test_proto2.proto \ + ruby/tests/basic_test.proto \ ruby/tests/basic.rb \ + ruby/tests/common_tests.rb \ + ruby/tests/encode_decode_test.rb \ + ruby/tests/gc_test.rb \ ruby/tests/repeated_field_test.rb \ ruby/tests/stress.rb \ + ruby/tests/generated_code_proto2_test.rb \ + ruby/tests/generated_code_proto2.proto \ ruby/tests/generated_code.proto \ + ruby/tests/multi_level_nesting_test.proto \ + ruby/tests/multi_level_nesting_test.rb \ + ruby/tests/test_import_proto2.proto \ ruby/tests/test_import.proto \ + ruby/tests/test_ruby_package_proto2.proto \ + ruby/tests/test_ruby_package.proto \ ruby/tests/generated_code_test.rb \ ruby/tests/well_known_types_test.rb \ + ruby/tests/type_errors.rb \ ruby/travis-test.sh js_EXTRA_DIST= \ @@ -884,6 +1181,7 @@ js_EXTRA_DIST= \ js/commonjs/import_test.js \ js/commonjs/jasmine.json \ js/commonjs/rewrite_tests_for_commonjs.js \ + js/commonjs/strict_test.js \ js/commonjs/test6/test6.proto \ js/commonjs/test7/test7.proto \ js/compatibility_tests/v3.0.0/binary/arith_test.js \ @@ -939,6 +1237,10 @@ js_EXTRA_DIST= \ js/data.proto \ js/debug.js \ js/debug_test.js \ + js/experimental/runtime/kernel/message_set.js \ + js/experimental/runtime/kernel/message_set_test.js \ + js/experimental/runtime/kernel/tag.js \ + js/experimental/runtime/kernel/tag_test.js \ js/gulpfile.js \ js/jasmine.json \ js/map.js \ @@ -955,11 +1257,90 @@ js_EXTRA_DIST= \ js/test4.proto \ js/test5.proto \ js/test8.proto \ + js/test9.proto \ + js/test10.proto \ + js/test11.proto \ + js/test12.proto \ + js/test13.proto \ + js/test14.proto \ + js/test15.proto \ js/test_bootstrap.js \ js/testbinary.proto \ - js/testempty.proto + js/testempty.proto \ + js/testlargenumbers.proto \ + js/experimental/runtime/testing/jasmine_protobuf.js \ + js/experimental/runtime/testing/ensure_custom_equality_test.js \ + js/experimental/runtime/testing/binary/test_message.js \ + js/experimental/runtime/kernel/writer_test.js \ + js/experimental/runtime/kernel/writer.js \ + js/experimental/runtime/kernel/wire_type.js \ + js/experimental/runtime/kernel/uint8arrays_test.js \ + js/experimental/runtime/kernel/uint8arrays.js \ + js/experimental/runtime/kernel/uint32_test_pairs.js \ + js/experimental/runtime/kernel/typed_arrays_test.js \ + js/experimental/runtime/kernel/typed_arrays.js \ + js/experimental/runtime/kernel/textencoding_test.js \ + js/experimental/runtime/kernel/textencoding.js \ + js/experimental/runtime/kernel/storage.js \ + js/experimental/runtime/kernel/sint64_test_pairs.js \ + js/experimental/runtime/kernel/sint32_test_pairs.js \ + js/experimental/runtime/kernel/sfixed64_test_pairs.js \ + js/experimental/runtime/kernel/sfixed32_test_pairs.js \ + js/experimental/runtime/kernel/reader_test.js \ + js/experimental/runtime/kernel/reader.js \ + js/experimental/runtime/kernel/packed_uint32_test_pairs.js \ + js/experimental/runtime/kernel/packed_sint64_test_pairs.js \ + js/experimental/runtime/kernel/packed_sint32_test_pairs.js \ + js/experimental/runtime/kernel/packed_sfixed64_test_pairs.js \ + js/experimental/runtime/kernel/packed_sfixed32_test_pairs.js \ + js/experimental/runtime/kernel/packed_int64_test_pairs.js \ + js/experimental/runtime/kernel/packed_int32_test_pairs.js \ + js/experimental/runtime/kernel/packed_float_test_pairs.js \ + js/experimental/runtime/kernel/packed_fixed32_test_pairs.js \ + js/experimental/runtime/kernel/packed_double_test_pairs.js \ + js/experimental/runtime/kernel/packed_bool_test_pairs.js \ + js/experimental/runtime/kernel/kernel_test.js \ + js/experimental/runtime/kernel/kernel_repeated_test.js \ + js/experimental/runtime/kernel/kernel_compatibility_test.js \ + js/experimental/runtime/kernel/kernel.js \ + js/experimental/runtime/kernel/internal_message.js \ + js/experimental/runtime/kernel/int64_test_pairs.js \ + js/experimental/runtime/kernel/int32_test_pairs.js \ + js/experimental/runtime/kernel/indexer_test.js \ + js/experimental/runtime/kernel/indexer.js \ + js/experimental/runtime/kernel/float_test_pairs.js \ + js/experimental/runtime/kernel/fixed32_test_pairs.js \ + js/experimental/runtime/kernel/field.js \ + js/experimental/runtime/kernel/double_test_pairs.js \ + js/experimental/runtime/kernel/conformance/wire_format.js \ + js/experimental/runtime/kernel/conformance/test_all_types_proto3.js \ + js/experimental/runtime/kernel/conformance/test_all_types_proto2.js \ + js/experimental/runtime/kernel/conformance/conformance_testee_runner_node.js \ + js/experimental/runtime/kernel/conformance/conformance_testee.js \ + js/experimental/runtime/kernel/conformance/conformance_response.js \ + js/experimental/runtime/kernel/conformance/conformance_request.js \ + js/experimental/runtime/kernel/buffer_decoder_test.js \ + js/experimental/runtime/kernel/buffer_decoder_helper.js \ + js/experimental/runtime/kernel/buffer_decoder.js \ + js/experimental/runtime/kernel/bool_test_pairs.js \ + js/experimental/runtime/kernel/binary_storage_test.js \ + js/experimental/runtime/kernel/binary_storage.js \ + js/experimental/runtime/internal/checks_test.js \ + js/experimental/runtime/internal/checks.js \ + js/experimental/runtime/int64_test.js \ + js/experimental/runtime/int64.js \ + js/experimental/runtime/bytestring_test.js \ + js/experimental/runtime/bytestring_internal.js \ + js/experimental/runtime/bytestring.js \ + js/experimental/benchmarks/code_size/kernel/popular_types.js \ + js/experimental/benchmarks/code_size/kernel/all_types.js \ + js/experimental/benchmarks/code_size/code_size_base.js \ + js/experimental/benchmarks/code_size/apps_jspb/popular_types_proto3.js \ + js/experimental/benchmarks/code_size/apps_jspb/popular_types_proto2.js \ + js/experimental/benchmarks/code_size/apps_jspb/all_types_proto3.js \ + js/experimental/benchmarks/code_size/apps_jspb/all_types_proto2.js -all_EXTRA_DIST=$(csharp_EXTRA_DIST) $(java_EXTRA_DIST) $(javanano_EXTRA_DIST) $(objectivec_EXTRA_DIST) $(php_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST) $(js_EXTRA_DIST) +all_EXTRA_DIST=$(csharp_EXTRA_DIST) $(java_EXTRA_DIST) $(objectivec_EXTRA_DIST) $(php_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST) $(js_EXTRA_DIST) EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \ autogen.sh \ @@ -970,10 +1351,10 @@ EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \ CHANGES.txt \ update_file_lists.sh \ BUILD \ - gmock.BUILD \ WORKSPACE \ cmake/CMakeLists.txt \ cmake/README.md \ + cmake/conformance.cmake \ cmake/examples.cmake \ cmake/extract_includes.bat.in \ cmake/install.cmake \ @@ -982,34 +1363,44 @@ EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \ cmake/libprotoc.cmake \ cmake/protobuf-config-version.cmake.in \ cmake/protobuf-config.cmake.in \ + cmake/protobuf-lite.pc.cmake \ cmake/protobuf-module.cmake.in \ cmake/protobuf-options.cmake \ + cmake/protobuf.pc.cmake \ cmake/protoc.cmake \ cmake/tests.cmake \ + cmake/version.rc.in \ + compiler_config_setting.bzl \ + build_files_updated_unittest.sh \ + cc_proto_blacklist_test.bzl \ editors/README.txt \ editors/proto.vim \ editors/protobuf-mode.el \ + examples/AddPerson.java \ + examples/BUILD \ examples/CMakeLists.txt \ - examples/README.txt \ + examples/ListPeople.java \ examples/Makefile \ - examples/addressbook.proto \ + examples/README.md \ + examples/WORKSPACE \ examples/add_person.cc \ + examples/add_person.dart \ examples/add_person.go \ + examples/add_person.py \ examples/add_person_test.go \ + examples/addressbook.proto \ examples/list_people.cc \ + examples/list_people.dart \ examples/list_people.go \ - examples/AddPerson.java \ - examples/CMakeLists.txt \ - examples/ListPeople.java \ - examples/add_person.py \ examples/list_people.py \ examples/list_people_test.go \ + examples/pubspec.yaml \ protobuf.bzl \ - python/release/wheel/build_wheel_manylinux.sh \ - python/release/wheel/Dockerfile \ - python/release/wheel/protobuf_optimized_pip.sh \ - python/release/wheel/README.md \ - six.BUILD \ + protobuf_deps.bzl \ + third_party/six.BUILD \ + third_party/zlib.BUILD \ + third_party/wyhash/LICENSE \ + third_party/wyhash/wyhash.h \ util/python/BUILD diff --git a/Protobuf-C++.podspec b/Protobuf-C++.podspec new file mode 100644 index 0000000000000..e794cb2a49c32 --- /dev/null +++ b/Protobuf-C++.podspec @@ -0,0 +1,42 @@ +Pod::Spec.new do |s| + s.name = 'Protobuf-C++' + s.version = '3.15.0' + s.summary = 'Protocol Buffers v3 runtime library for C++.' + s.homepage = 'https://github.com/google/protobuf' + s.license = '3-Clause BSD License' + s.authors = { 'The Protocol Buffers contributors' => 'protobuf@googlegroups.com' } + s.cocoapods_version = '>= 1.0' + + s.source = { :git => 'https://github.com/google/protobuf.git', + :tag => "v#{s.version}" } + + s.source_files = 'src/google/protobuf/*.{h,cc,inc}', + 'src/google/protobuf/stubs/*.{h,cc}', + 'src/google/protobuf/io/*.{h,cc}', + 'src/google/protobuf/util/*.{h,cc}', + 'src/google/protobuf/util/internal/*.{h,cc}' + + # Excluding all the tests in the directories above + s.exclude_files = 'src/google/**/*_test.{h,cc,inc}', + 'src/google/**/*_unittest.{h,cc}', + 'src/google/protobuf/test_util*.{h,cc}', + 'src/google/protobuf/map_lite_test_util.{h,cc}', + 'src/google/protobuf/map_test_util*.{h,cc,inc}' + + s.header_mappings_dir = 'src' + + s.ios.deployment_target = '7.0' + s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '9.0' + s.watchos.deployment_target = '2.0' + + s.pod_target_xcconfig = { + # Do not let src/google/protobuf/stubs/time.h override system API + 'USE_HEADERMAP' => 'NO', + 'ALWAYS_SEARCH_USER_PATHS' => 'NO', + + # Configure tool is not being used for Xcode. When building, assume pthread is supported. + 'GCC_PREPROCESSOR_DEFINITIONS' => '"$(inherited)" "HAVE_PTHREAD=1"', + } + +end diff --git a/Protobuf.podspec b/Protobuf.podspec index 88bd5b7d7256c..d982b9de8b7a2 100644 --- a/Protobuf.podspec +++ b/Protobuf.podspec @@ -5,27 +5,27 @@ # dependent projects use the :git notation to refer to the library. Pod::Spec.new do |s| s.name = 'Protobuf' - s.version = '3.4.0' + s.version = '3.15.0' s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.' - s.homepage = 'https://github.com/google/protobuf' + s.homepage = 'https://github.com/protocolbuffers/protobuf' s.license = '3-Clause BSD License' s.authors = { 'The Protocol Buffers contributors' => 'protobuf@googlegroups.com' } s.cocoapods_version = '>= 1.0' - s.source = { :git => 'https://github.com/google/protobuf.git', + s.source = { :git => 'https://github.com/protocolbuffers/protobuf.git', :tag => "v#{s.version}" } s.source_files = 'objectivec/*.{h,m}', - 'objectivec/google/protobuf/Any.pbobjc.{h,m}', - 'objectivec/google/protobuf/Api.pbobjc.{h,m}', - 'objectivec/google/protobuf/Duration.pbobjc.{h,m}', - 'objectivec/google/protobuf/Empty.pbobjc.{h,m}', - 'objectivec/google/protobuf/FieldMask.pbobjc.{h,m}', - 'objectivec/google/protobuf/SourceContext.pbobjc.{h,m}', - 'objectivec/google/protobuf/Struct.pbobjc.{h,m}', - 'objectivec/google/protobuf/Timestamp.pbobjc.{h,m}', - 'objectivec/google/protobuf/Type.pbobjc.{h,m}', - 'objectivec/google/protobuf/Wrappers.pbobjc.{h,m}' + 'objectivec/google/protobuf/Any.pbobjc.h', + 'objectivec/google/protobuf/Api.pbobjc.h', + 'objectivec/google/protobuf/Duration.pbobjc.h', + 'objectivec/google/protobuf/Empty.pbobjc.h', + 'objectivec/google/protobuf/FieldMask.pbobjc.h', + 'objectivec/google/protobuf/SourceContext.pbobjc.h', + 'objectivec/google/protobuf/Struct.pbobjc.h', + 'objectivec/google/protobuf/Timestamp.pbobjc.h', + 'objectivec/google/protobuf/Type.pbobjc.h', + 'objectivec/google/protobuf/Wrappers.pbobjc.h' # The following would cause duplicate symbol definitions. GPBProtocolBuffers is expected to be # left out, as it's an umbrella implementation file. s.exclude_files = 'objectivec/GPBProtocolBuffers.m' @@ -34,7 +34,7 @@ Pod::Spec.new do |s| s.user_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1' } s.pod_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1' } - s.ios.deployment_target = '7.0' + s.ios.deployment_target = '9.0' s.osx.deployment_target = '10.9' s.tvos.deployment_target = '9.0' s.watchos.deployment_target = '2.0' diff --git a/README.md b/README.md index 653f663276b4b..118b8966686b5 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ Protocol Buffers - Google's data interchange format =================================================== -[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) [![Build Status](https://grpc-testing.appspot.com/buildStatus/icon?job=protobuf_branch)](https://grpc-testing.appspot.com/job/protobuf_branch) [![Build Status](https://grpc-testing.appspot.com/job/protobuf_branch_32/badge/icon)](https://grpc-testing.appspot.com/job/protobuf_branch_32) [![Build Status](http://ci.bazel.io/buildStatus/icon?job=protobuf)](http://ci.bazel.io/job/protobuf/) - Copyright 2008 Google Inc. https://developers.google.com/protocol-buffers/ @@ -28,7 +26,7 @@ with the C++ runtime. For non-C++ users, the simplest way to install the protocol compiler is to download a pre-built binary from our release page: - [https://github.com/google/protobuf/releases](https://github.com/google/protobuf/releases) + [https://github.com/protocolbuffers/protobuf/releases](https://github.com/protocolbuffers/protobuf/releases) In the downloads section of each release, you can find pre-built binaries in zip packages: protoc-$VERSION-$PLATFORM.zip. It contains the protoc binary @@ -54,23 +52,32 @@ Protobuf supports several different programming languages. For each programming language, you can find instructions in the corresponding source directory about how to install protobuf runtime for that specific language: -| Language | Source | -|--------------------------------------|-------------------------------------------------------------| -| C++ (include C++ runtime and protoc) | [src](src) | -| Java | [java](java) | -| Python | [python](python) | -| Objective-C | [objectivec](objectivec) | -| C# | [csharp](csharp) | -| JavaNano | [javanano](javanano) | -| JavaScript | [js](js) | -| Ruby | [ruby](ruby) | -| Go | [golang/protobuf](https://github.com/golang/protobuf) | -| PHP | [php](php) | -| Dart | [dart-lang/protobuf](https://github.com/dart-lang/protobuf) | - - -Usage ------ +| Language | Source | Ubuntu | MacOS | Windows | +|--------------------------------------|-------------------------------------------------------------|--------|-------|---------| +| C++ (include C++ runtime and protoc) | [src](src) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-cpp_distcheck.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fcpp_distcheck%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-bazel.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fbazel%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-dist_install.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fdist_install%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fcpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-cpp_distcheck.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fcpp_distcheck%2Fcontinuous) | [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) | +| Java | [java](java) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-java_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_compatibility%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-java_jdk7.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_jdk7%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-java_oracle7.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_oracle7%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-java_linkage_monitor.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_linkage_monitor%2Fcontinuous) | | | +| Python | [python](python) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-python27.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-python35.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-python36.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-python37.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-python_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_compatibility%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-python27_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-python35_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-python36_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-python37_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-python.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-python_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/windows-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fwindows%2Fpython_release%2Fcontinuous) | +| Objective-C | [objectivec](objectivec) | | [![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-objectivec_cocoapods_integration.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_cocoapods_integration%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-objectivec_ios_debug.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_ios_debug%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-objectivec_ios_release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_ios_release%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-objectivec_osx.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_osx%2Fcontinuous) | | +| C# | [csharp](csharp) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-csharp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fcsharp%2Fcontinuous) | | [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/windows-csharp-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fwindows%2Fcsharp_release%2Fcontinuous) | +| JavaScript | [js](js) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjavascript%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fjavascript%2Fcontinuous) | | +| Ruby | [ruby](ruby) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-ruby23.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby23%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-ruby24.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby24%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-ruby25.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby25%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-ruby26.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby26%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-ruby-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-ruby23.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby23%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-ruby24.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby24%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-ruby25.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby25%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-ruby26.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby26%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-ruby-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby_release%2Fcontinuous) | | +| Go | [protocolbuffers/protobuf-go](https://github.com/protocolbuffers/protobuf-go) | | | | +| PHP | [php](php) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-php_all.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fphp_all%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-32-bit.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2F32-bit%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/linux-php80.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fphp80%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-php5.6_mac.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fphp5.6_mac%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-badges/status-badge/macos-php7.0_mac.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fphp7.0_mac%2Fcontinuous) | | +| Dart | [dart-lang/protobuf](https://github.com/dart-lang/protobuf) | [![Build Status](https://travis-ci.org/dart-lang/protobuf.svg?branch=master)](https://travis-ci.org/dart-lang/protobuf) | | | + +Quick Start +----------- + +The best way to learn how to use protobuf is to follow the tutorials in our +developer guide: + +https://developers.google.com/protocol-buffers/docs/tutorials + +If you want to learn from code examples, take a look at the examples in the +[examples](examples) directory. + +Documentation +------------- The complete documentation for Protocol Buffers is available via the web at: diff --git a/WORKSPACE b/WORKSPACE index 2a49e3723abfd..5a767a97c0ac6 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1,40 +1,54 @@ -new_git_repository( - name = "googletest", - build_file = "gmock.BUILD", - remote = "https://github.com/google/googletest", - tag = "release-1.8.0", +workspace(name = "com_google_protobuf") + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +local_repository( + name = "com_google_protobuf_examples", + path = "examples", ) -new_http_archive( - name = "six_archive", - build_file = "six.BUILD", - sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a", - url = "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55", +http_archive( + name = "com_google_googletest", + sha256 = "9dc9157a9a1551ec7a7e43daea9a694a0bb5fb8bec81235d8a1e6ef64c716dcb", + strip_prefix = "googletest-release-1.10.0", + urls = [ + "https://mirror.bazel.build/github.com/google/googletest/archive/release-1.10.0.tar.gz", + "https://github.com/google/googletest/archive/release-1.10.0.tar.gz", + ], ) +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load("//:protobuf_deps.bzl", "protobuf_deps") + +# Load common dependencies. +protobuf_deps() +load("@bazel_tools//tools/build_defs/repo:jvm.bzl", "jvm_maven_import_external") + bind( name = "python_headers", actual = "//util/python:python_headers", ) +# TODO(yannic): Remove in 3.14.0. bind( name = "gtest", - actual = "@googletest//:gtest", + actual = "@com_google_googletest//:gtest", ) +# TODO(yannic): Remove in 3.14.0. bind( name = "gtest_main", - actual = "@googletest//:gtest_main", -) - -bind( - name = "six", - actual = "@six_archive//:six", + actual = "@com_google_googletest//:gtest_main", ) -maven_jar( +jvm_maven_import_external( name = "guava_maven", artifact = "com.google.guava:guava:18.0", + artifact_sha256 = "d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99", + server_urls = [ + "https://jcenter.bintray.com/", + "https://repo1.maven.org/maven2", + ], ) bind( @@ -42,12 +56,37 @@ bind( actual = "@guava_maven//jar", ) -maven_jar( +jvm_maven_import_external( name = "gson_maven", artifact = "com.google.code.gson:gson:2.7", + artifact_sha256 = "2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32", + server_urls = [ + "https://jcenter.bintray.com/", + "https://repo1.maven.org/maven2", + ], ) bind( name = "gson", actual = "@gson_maven//jar", ) + +jvm_maven_import_external( + name = "error_prone_annotations_maven", + artifact = "com.google.errorprone:error_prone_annotations:2.3.2", + artifact_sha256 = "357cd6cfb067c969226c442451502aee13800a24e950fdfde77bcdb4565a668d", + server_urls = [ + "https://jcenter.bintray.com/", + "https://repo1.maven.org/maven2", + ], +) + +bind( + name = "error_prone_annotations", + actual = "@error_prone_annotations_maven//jar", +) + +# For `cc_proto_blacklist_test`. +load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") + +bazel_skylib_workspace() diff --git a/appveyor.bat b/appveyor.bat index ca88b25c3ea8e..7a35ceb4d678e 100644 --- a/appveyor.bat +++ b/appveyor.bat @@ -1,11 +1,23 @@ setlocal +IF %platform%==MinGW GOTO build_mingw IF %language%==cpp GOTO build_cpp IF %language%==csharp GOTO build_csharp -echo Unsupported language %language%. Exiting. +echo Unsupported language %language% and platform %platform%. Exiting. goto :error +:build_mingw +echo Building MinGW +set PATH=C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;%PATH:C:\Program Files\Git\usr\bin;=% +mkdir build_mingw +cd build_mingw +cmake -G "%generator%" -Dprotobuf_BUILD_SHARED_LIBS=%BUILD_DLL% -Dprotobuf_UNICODE=%UNICODE% -Dprotobuf_BUILD_TESTS=0 ../cmake +mingw32-make -j8 all || goto error +rem cd %configuration% +rem tests.exe || goto error +goto :EOF + :build_cpp echo Building C++ mkdir build_msvc @@ -26,8 +38,8 @@ dotnet restore dotnet build -c %configuration% || goto error echo Testing C# -dotnet run -c %configuration% -f netcoreapp1.0 -p Google.Protobuf.Test\Google.Protobuf.Test.csproj || goto error -dotnet run -c %configuration% -f net451 -p Google.Protobuf.Test\Google.Protobuf.Test.csproj || goto error +dotnet test -c %configuration% -f netcoreapp2.1 Google.Protobuf.Test\Google.Protobuf.Test.csproj || goto error +dotnet test -c %configuration% -f net451 Google.Protobuf.Test\Google.Protobuf.Test.csproj || goto error goto :EOF diff --git a/appveyor.yml b/appveyor.yml index 8b440b6396ed0..91f737a8c019f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,19 +1,29 @@ -# Only test one combination: "Visual Studio 12 + Win64 + Debug + DLL". We can -# test more combinations but AppVeyor just takes too long to finish (each -# combination takes ~15mins). -platform: - - Win64 - configuration: - Debug environment: matrix: - - language: cpp + # Only test few combinations: "Visual Studio 2015 (14) + Win64/MinGW + Debug + DLL". We can + # test more combinations but AppVeyor just takes too long to finish (each + # combination takes ~15mins). + - platform: MinGW + language: cpp + image: Visual Studio 2015 + + - platform: Win64 + language: cpp + image: Visual Studio 2015 BUILD_DLL: ON UNICODE: ON - - language: csharp + - platform: Win64 + language: cpp + image: Visual Studio 2017 + BUILD_DLL: OFF + UNICODE: ON + + - platform: Win64 + language: csharp image: Visual Studio 2017 # Our build scripts run tests automatically; we don't want AppVeyor @@ -21,19 +31,12 @@ environment: test: off install: - - curl -L -o release-1.7.0.zip https://github.com/google/googlemock/archive/release-1.7.0.zip - - 7z x release-1.7.0.zip - - del /Q release-1.7.0.zip - - rename googlemock-release-1.7.0 gmock - - curl -L -o release-1.7.0.zip "https://github.com/google/googletest/archive/release-1.7.0.zip" - - 7z x release-1.7.0.zip - - del /Q release-1.7.0.zip - - rename googletest-release-1.7.0 gtest - - move gtest gmock + - git submodule update --init --recursive before_build: - - if %platform%==Win32 set generator=Visual Studio 12 - - if %platform%==Win64 set generator=Visual Studio 12 Win64 + - if %platform%==MinGW set generator=MinGW Makefiles + - if %platform%==Win32 set generator=Visual Studio 14 + - if %platform%==Win64 set generator=Visual Studio 14 Win64 - if %platform%==Win32 set vcplatform=Win32 - if %platform%==Win64 set vcplatform=x64 diff --git a/autogen.sh b/autogen.sh index 9f266425856bb..d00d21727c2d8 100755 --- a/autogen.sh +++ b/autogen.sh @@ -17,7 +17,6 @@ if [ ! -z "$@" ]; then done fi - # Check that we're being run from the right directory. if test ! -f src/google/protobuf/stubs/common.h; then cat >&2 << __EOF__ @@ -27,23 +26,13 @@ __EOF__ exit 1 fi -# Check that gmock is present. Usually it is already there since the -# directory is set up as an SVN external. -if test ! -e gmock; then - echo "Google Mock not present. Fetching gmock-1.7.0 from the web..." - curl $curlopts -L -O https://github.com/google/googlemock/archive/release-1.7.0.zip - unzip -q release-1.7.0.zip - rm release-1.7.0.zip - mv googlemock-release-1.7.0 gmock - - curl $curlopts -L -O https://github.com/google/googletest/archive/release-1.7.0.zip - unzip -q release-1.7.0.zip - rm release-1.7.0.zip - mv googletest-release-1.7.0 gmock/gtest -fi - set -ex +# The absence of a m4 directory in googletest causes autoreconf to fail when +# building under the CentOS docker image. It's a warning in regular build on +# Ubuntu/gLinux as well. +mkdir -p third_party/googletest/m4 + # TODO(kenton): Remove the ",no-obsolete" part and fix the resulting warnings. autoreconf -f -i -Wall,no-obsolete diff --git a/benchmarks/Makefile.am b/benchmarks/Makefile.am index d98eae5eadbbe..2b2204d082353 100644 --- a/benchmarks/Makefile.am +++ b/benchmarks/Makefile.am @@ -1,78 +1,664 @@ +benchmarks_protoc_inputs_benchmark_wrapper = \ + benchmarks.proto -benchmarks_protoc_inputs = \ - benchmarks.proto \ - benchmark_messages_proto3.proto +benchmarks_protoc_inputs = \ + datasets/google_message1/proto3/benchmark_message1_proto3.proto -benchmarks_protoc_inputs_proto2 = \ - benchmark_messages_proto2.proto +benchmarks_protoc_inputs_proto2 = \ + datasets/google_message1/proto2/benchmark_message1_proto2.proto \ + datasets/google_message2/benchmark_message2.proto \ + datasets/google_message3/benchmark_message3.proto \ + datasets/google_message3/benchmark_message3_1.proto \ + datasets/google_message3/benchmark_message3_2.proto \ + datasets/google_message3/benchmark_message3_3.proto \ + datasets/google_message3/benchmark_message3_4.proto \ + datasets/google_message3/benchmark_message3_5.proto \ + datasets/google_message3/benchmark_message3_6.proto \ + datasets/google_message3/benchmark_message3_7.proto \ + datasets/google_message3/benchmark_message3_8.proto \ + datasets/google_message4/benchmark_message4.proto \ + datasets/google_message4/benchmark_message4_1.proto \ + datasets/google_message4/benchmark_message4_2.proto \ + datasets/google_message4/benchmark_message4_3.proto -benchmarks_protoc_outputs = \ - benchmarks.pb.cc \ - benchmarks.pb.h \ - benchmark_messages_proto3.pb.cc \ - benchmark_messages_proto3.pb.h +make_tmp_dir: + mkdir -p 'tmp/java/src/main/java' + touch make_tmp_dir -benchmarks_protoc_outputs_proto2 = \ - benchmark_messages_proto2.pb.cc \ - benchmark_messages_proto2.pb.h + +# We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is +# relative to srcdir, which may not be the same as the current directory when +# building out-of-tree. +protoc_middleman: make_tmp_dir $(top_srcdir)/src/protoc$(EXEEXT) $(benchmarks_protoc_inputs) $(well_known_type_protoc_inputs) $(benchmarks_protoc_inputs_benchmark_wrapper) + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd/cpp --java_out=$$oldpwd/tmp/java/src/main/java --python_out=$$oldpwd/tmp $(benchmarks_protoc_inputs) $(benchmarks_protoc_inputs_benchmark_wrapper) ) + touch protoc_middleman + +protoc_middleman2: make_tmp_dir $(top_srcdir)/src/protoc$(EXEEXT) $(benchmarks_protoc_inputs_proto2) $(well_known_type_protoc_inputs) + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd/cpp --java_out=$$oldpwd/tmp/java/src/main/java --python_out=$$oldpwd/tmp $(benchmarks_protoc_inputs_proto2) ) + touch protoc_middleman2 + +all_data = $$(find $$(cd $(srcdir) && pwd) -type f -name "dataset.*.pb" -not -path "$$(cd $(srcdir) && pwd)/tmp/*") + +############# CPP RULES ############## + +benchmarks_protoc_outputs = \ + cpp/benchmarks.pb.cc \ + cpp/datasets/google_message1/proto3/benchmark_message1_proto3.pb.cc + +benchmarks_protoc_outputs_header = \ + cpp/benchmarks.pb.h \ + cpp/datasets/google_message1/proto3/benchmark_message1_proto3.pb.h + +benchmarks_protoc_outputs_proto2_header = \ + cpp/datasets/google_message1/proto2/benchmark_message1_proto2.pb.h \ + cpp/datasets/google_message2/benchmark_message2.pb.h \ + cpp/datasets/google_message3/benchmark_message3.pb.h \ + cpp/datasets/google_message3/benchmark_message3_1.pb.h \ + cpp/datasets/google_message3/benchmark_message3_2.pb.h \ + cpp/datasets/google_message3/benchmark_message3_3.pb.h \ + cpp/datasets/google_message3/benchmark_message3_4.pb.h \ + cpp/datasets/google_message3/benchmark_message3_5.pb.h \ + cpp/datasets/google_message3/benchmark_message3_6.pb.h \ + cpp/datasets/google_message3/benchmark_message3_7.pb.h \ + cpp/datasets/google_message3/benchmark_message3_8.pb.h \ + cpp/datasets/google_message4/benchmark_message4.pb.h \ + cpp/datasets/google_message4/benchmark_message4_1.pb.h \ + cpp/datasets/google_message4/benchmark_message4_2.pb.h \ + cpp/datasets/google_message4/benchmark_message4_3.pb.h + +benchmarks_protoc_outputs_proto2 = \ + cpp/datasets/google_message1/proto2/benchmark_message1_proto2.pb.cc \ + cpp/datasets/google_message2/benchmark_message2.pb.cc \ + cpp/datasets/google_message3/benchmark_message3.pb.cc \ + cpp/datasets/google_message3/benchmark_message3_1.pb.cc \ + cpp/datasets/google_message3/benchmark_message3_2.pb.cc \ + cpp/datasets/google_message3/benchmark_message3_3.pb.cc \ + cpp/datasets/google_message3/benchmark_message3_4.pb.cc \ + cpp/datasets/google_message3/benchmark_message3_5.pb.cc \ + cpp/datasets/google_message3/benchmark_message3_6.pb.cc \ + cpp/datasets/google_message3/benchmark_message3_7.pb.cc \ + cpp/datasets/google_message3/benchmark_message3_8.pb.cc \ + cpp/datasets/google_message4/benchmark_message4.pb.cc \ + cpp/datasets/google_message4/benchmark_message4_1.pb.cc \ + cpp/datasets/google_message4/benchmark_message4_2.pb.cc \ + cpp/datasets/google_message4/benchmark_message4_3.pb.cc + + +$(benchmarks_protoc_outputs): protoc_middleman +$(benchmarks_protoc_outputs_header): protoc_middleman +$(benchmarks_protoc_outputs_proto2): protoc_middleman2 +$(benchmarks_protoc_outputs_proto2_header): protoc_middleman2 + +initialize_submodule: + oldpwd=`pwd` + cd $(top_srcdir) && git submodule update --init -r third_party/benchmark && \ + cd third_party/benchmark && cmake -DCMAKE_BUILD_TYPE=Release && make + cd $$oldpwd + touch initialize_submodule + +$(top_srcdir)/third_party/benchmark/src/libbenchmark.a: initialize_submodule AM_CXXFLAGS = $(NO_OPT_CXXFLAGS) $(PROTOBUF_OPT_FLAG) -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare -bin_PROGRAMS = generate-datasets cpp-benchmark +bin_PROGRAMS = cpp-benchmark + +cpp_benchmark_LDADD = $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/third_party/benchmark/src/libbenchmark.a +cpp_benchmark_SOURCES = cpp/cpp_benchmark.cc +cpp_benchmark_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/cpp -I$(top_srcdir)/third_party/benchmark/include +# Explicit deps because BUILT_SOURCES are only done before a "make all/check" +# so a direct "make test_cpp" could fail if parallel enough. +# See: https://www.gnu.org/software/automake/manual/html_node/Built-Sources-Example.html#Recording-Dependencies-manually +cpp/cpp_benchmark-cpp_benchmark.$(OBJEXT): $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2) $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header) $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/third_party/benchmark/src/libbenchmark.a +cpp/benchmark-cpp_benchmark.$(OBJEXT): $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2) $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header) $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/third_party/benchmark/src/libbenchmark.a +nodist_cpp_benchmark_SOURCES = \ + $(benchmarks_protoc_outputs) \ + $(benchmarks_protoc_outputs_proto2) \ + $(benchmarks_protoc_outputs_proto2_header) \ + $(benchmarks_protoc_outputs_header) + +cpp: protoc_middleman protoc_middleman2 cpp-benchmark initialize_submodule + ./cpp-benchmark $(all_data) + +############ CPP RULES END ############ + +############# JAVA RULES ############## + +java_benchmark_testing_files = \ + java/src/main/java/com/google/protobuf/ProtoCaliperBenchmark.java + +javac_middleman: $(java_benchmark_testing_files) protoc_middleman protoc_middleman2 + cp -r $(srcdir)/java tmp + mkdir -p tmp/java/lib + cp $(top_srcdir)/java/core/target/*.jar tmp/java/lib/protobuf-java.jar + cd tmp/java && mvn clean compile assembly:single -Dprotobuf.version=$(PACKAGE_VERSION) && cd ../.. + @touch javac_middleman + +java-benchmark: javac_middleman + @echo "Writing shortcut script java-benchmark..." + @echo '#! /bin/bash' > java-benchmark + @echo 'all_data=""' >> java-benchmark + @echo 'conf=()' >> java-benchmark + @echo 'data_files=""' >> java-benchmark + @echo 'for arg in $$@; do if [[ $${arg:0:1} == "-" ]]; then conf+=($$arg); else data_files+="$$arg,"; fi; done' >> java-benchmark + @echo 'java -cp '\"tmp/java/target/*:$(top_srcdir)/java/core/target/*:$(top_srcdir)/java/util/target/*\"" \\" >>java-benchmark + @echo ' com.google.caliper.runner.CaliperMain com.google.protobuf.ProtoCaliperBenchmark -i runtime '"\\" >> java-benchmark + @echo ' -b serializeToByteArray,serializeToMemoryStream,deserializeFromByteArray,deserializeFromMemoryStream '"\\" >> java-benchmark + @echo ' -DdataFile=$${data_files:0:-1} $${conf[*]}' >> java-benchmark + @chmod +x java-benchmark + +java: protoc_middleman protoc_middleman2 java-benchmark + ./java-benchmark $(all_data) + +############# JAVA RULES END ############## + + +############# PYTHON RULES ############## + +python_add_init: protoc_middleman protoc_middleman2 + all_file=`find tmp -type f -regex '.*\.py'` && \ + for file in $${all_file[@]}; do \ + path="$${file%/*}"; \ + while true; do \ + touch "$$path/__init__.py" && chmod +x "$$path/__init__.py"; \ + if [[ $$path != *"/"* ]]; then break; fi; \ + path=$${path%/*}; \ + done \ + done + +python_cpp_pkg_flags = `pkg-config --cflags --libs python` + +lib_LTLIBRARIES = libbenchmark_messages.la +libbenchmark_messages_la_SOURCES = python/python_benchmark_messages.cc +libbenchmark_messages_la_LIBADD = $(top_srcdir)/src/.libs/libprotobuf.la +libbenchmark_messages_la_LDFLAGS = -version-info 1:0:0 -export-dynamic +libbenchmark_messages_la_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/cpp $(python_cpp_pkg_flags) +libbenchmark_messages_la-python_benchmark_messages.$(OBJEXT): $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header) $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2) +nodist_libbenchmark_messages_la_SOURCES = \ + $(benchmarks_protoc_outputs) \ + $(benchmarks_protoc_outputs_proto2) \ + $(benchmarks_protoc_outputs_proto2_header) \ + $(benchmarks_protoc_outputs_header) + +python-pure-python-benchmark: python_add_init + @echo "Writing shortcut script python-pure-python-benchmark..." + @echo '#! /bin/bash' > python-pure-python-benchmark + @echo export LD_LIBRARY_PATH=$(top_srcdir)/src/.libs >> python-pure-python-benchmark + @echo export DYLD_LIBRARY_PATH=$(top_srcdir)/src/.libs >> python-pure-python-benchmark + @echo export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=\'python\' >> python-pure-python-benchmark + @echo cp $(srcdir)/python/py_benchmark.py tmp >> python-pure-python-benchmark + @echo python tmp/py_benchmark.py '$$@' >> python-pure-python-benchmark + @chmod +x python-pure-python-benchmark + +python-cpp-reflection-benchmark: python_add_init + @echo "Writing shortcut script python-cpp-reflection-benchmark..." + @echo '#! /bin/bash' > python-cpp-reflection-benchmark + @echo export LD_LIBRARY_PATH=$(top_srcdir)/src/.libs >> python-cpp-reflection-benchmark + @echo export DYLD_LIBRARY_PATH=$(top_srcdir)/src/.libs >> python-cpp-reflection-benchmark + @echo export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=\'cpp\' >> python-cpp-reflection-benchmark + @echo cp $(srcdir)/python/py_benchmark.py tmp >> python-cpp-reflection-benchmark + @echo python tmp/py_benchmark.py '$$@' >> python-cpp-reflection-benchmark + @chmod +x python-cpp-reflection-benchmark + +python-cpp-generated-code-benchmark: python_add_init libbenchmark_messages.la + @echo "Writing shortcut script python-cpp-generated-code-benchmark..." + @echo '#! /bin/bash' > python-cpp-generated-code-benchmark + @echo export LD_LIBRARY_PATH=$(top_srcdir)/src/.libs >> python-cpp-generated-code-benchmark + @echo export DYLD_LIBRARY_PATH=$(top_srcdir)/src/.libs >> python-cpp-generated-code-benchmark + @echo export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=\'cpp\' >> python-cpp-generated-code-benchmark + @echo cp $(srcdir)/python/py_benchmark.py tmp >> python-cpp-generated-code-benchmark + @echo python tmp/py_benchmark.py --cpp_generated '$$@' >> python-cpp-generated-code-benchmark + @chmod +x python-cpp-generated-code-benchmark + +python-pure-python: python-pure-python-benchmark + ./python-pure-python-benchmark $(all_data) + +python-cpp-reflection: python-cpp-reflection-benchmark + ./python-cpp-reflection-benchmark $(all_data) + +python-cpp-generated-code: python-cpp-generated-code-benchmark + ./python-cpp-generated-code-benchmark $(all_data) + +############# PYTHON RULES END ############## + +############# GO RULES BEGIN ############## + +benchmarks_protoc_inputs_proto2_message1 = \ + datasets/google_message1/proto2/benchmark_message1_proto2.proto + +benchmarks_protoc_inputs_proto2_message2 = \ + datasets/google_message2/benchmark_message2.proto + +benchmarks_protoc_inputs_proto2_message3 = \ + datasets/google_message3/benchmark_message3.proto \ + datasets/google_message3/benchmark_message3_1.proto \ + datasets/google_message3/benchmark_message3_2.proto \ + datasets/google_message3/benchmark_message3_3.proto \ + datasets/google_message3/benchmark_message3_4.proto \ + datasets/google_message3/benchmark_message3_5.proto \ + datasets/google_message3/benchmark_message3_6.proto \ + datasets/google_message3/benchmark_message3_7.proto \ + datasets/google_message3/benchmark_message3_8.proto + +benchmarks_protoc_inputs_proto2_message4 = \ + datasets/google_message4/benchmark_message4.proto \ + datasets/google_message4/benchmark_message4_1.proto \ + datasets/google_message4/benchmark_message4_2.proto \ + datasets/google_message4/benchmark_message4_3.proto + +go_protoc_middleman: make_tmp_dir $(top_srcdir)/src/protoc$(EXEEXT) $(benchmarks_protoc_inputs) $(well_known_type_protoc_inputs) $(benchmarks_protoc_inputs_proto2_message1) $(benchmarks_protoc_inputs_proto2_message2) $(benchmarks_protoc_inputs_proto2_message3) $(benchmarks_protoc_inputs_proto2_message4) $(well_known_type_protoc_inputs) + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --go_out=$$oldpwd/tmp $(benchmarks_protoc_inputs) ) + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --go_out=$$oldpwd/tmp $(benchmarks_protoc_inputs_benchmark_wrapper) ) + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --go_out=$$oldpwd/tmp $(benchmarks_protoc_inputs_proto2_message1) ) + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --go_out=$$oldpwd/tmp $(benchmarks_protoc_inputs_proto2_message2) ) + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --go_out=$$oldpwd/tmp $(benchmarks_protoc_inputs_proto2_message3) ) + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --go_out=$$oldpwd/tmp $(benchmarks_protoc_inputs_proto2_message4) ) + touch go_protoc_middleman + +go-benchmark: go_protoc_middleman + @echo "Writing shortcut script go-benchmark..." + @echo '#! /bin/bash' > go-benchmark + @echo 'cd $(srcdir)/go' >> go-benchmark + @echo 'all_data=""' >> go-benchmark + @echo 'conf=()' >> go-benchmark + @echo 'data_files=()' >> go-benchmark + @echo 'for arg in $$@; do if [[ $${arg:0:1} == "-" ]]; then conf+=($$arg); else data_files+=("$$arg"); fi; done' >> go-benchmark + @echo 'go test -bench=. $${conf[*]} -- $${data_files[*]}' >> go-benchmark + @echo 'cd ..' >> go-benchmark + @chmod +x go-benchmark + +go: go_protoc_middleman go-benchmark + ./go-benchmark $(all_data) + +############# GO RULES END ############## + +############# GOGO RULES BEGIN ############ + +cpp_no_group_benchmarks_protoc_outputs_header = \ + gogo/cpp_no_group/benchmarks.pb.h \ + gogo/cpp_no_group/datasets/google_message1/proto3/benchmark_message1_proto3.pb.h + +cpp_no_group_benchmarks_protoc_outputs = \ + gogo/cpp_no_group/benchmarks.pb.cc \ + gogo/cpp_no_group/datasets/google_message1/proto3/benchmark_message1_proto3.pb.cc + +cpp_no_group_benchmarks_protoc_outputs_proto2_header = \ + gogo/cpp_no_group/datasets/google_message1/proto2/benchmark_message1_proto2.pb.h \ + gogo/cpp_no_group/datasets/google_message2/benchmark_message2.pb.h \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3.pb.h \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_1.pb.h \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_2.pb.h \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_3.pb.h \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_4.pb.h \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_5.pb.h \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_6.pb.h \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_7.pb.h \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_8.pb.h \ + gogo/cpp_no_group/datasets/google_message4/benchmark_message4.pb.h \ + gogo/cpp_no_group/datasets/google_message4/benchmark_message4_1.pb.h \ + gogo/cpp_no_group/datasets/google_message4/benchmark_message4_2.pb.h \ + gogo/cpp_no_group/datasets/google_message4/benchmark_message4_3.pb.h + +cpp_no_group_benchmarks_protoc_outputs_proto2 = \ + gogo/cpp_no_group/datasets/google_message1/proto2/benchmark_message1_proto2.pb.cc \ + gogo/cpp_no_group/datasets/google_message2/benchmark_message2.pb.cc \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3.pb.cc \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_1.pb.cc \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_2.pb.cc \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_3.pb.cc \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_4.pb.cc \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_5.pb.cc \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_6.pb.cc \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_7.pb.cc \ + gogo/cpp_no_group/datasets/google_message3/benchmark_message3_8.pb.cc \ + gogo/cpp_no_group/datasets/google_message4/benchmark_message4.pb.cc \ + gogo/cpp_no_group/datasets/google_message4/benchmark_message4_1.pb.cc \ + gogo/cpp_no_group/datasets/google_message4/benchmark_message4_2.pb.cc \ + gogo/cpp_no_group/datasets/google_message4/benchmark_message4_3.pb.cc + +$(cpp_no_group_benchmarks_protoc_outputs): cpp_no_group_protoc_middleman +$(cpp_no_group_benchmarks_protoc_outputs_header): cpp_no_group_protoc_middleman +$(cpp_no_group_benchmarks_protoc_outputs_proto2): cpp_no_group_protoc_middleman +$(cpp_no_group_benchmarks_protoc_outputs_proto2_header): cpp_no_group_protoc_middleman -generate_datasets_LDADD = $(top_srcdir)/src/libprotobuf.la -generate_datasets_SOURCES = generate_datasets.cc -generate_datasets_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir) -nodist_generate_datasets_SOURCES = \ - $(benchmarks_protoc_outputs) \ - $(benchmarks_protoc_outputs_proto2) +generate_cpp_no_group_benchmark_code: + cp $(srcdir)/cpp/cpp_benchmark.cc gogo/cpp_no_group/cpp_benchmark.cc + sed -i -e "s/\#include \"datasets/\#include \"gogo\/cpp_no_group\/datasets/g" gogo/cpp_no_group/cpp_benchmark.cc + sed -i -e "s/\#include \"benchmarks.pb.h/\#include \"gogo\/cpp_no_group\/benchmarks.pb.h/g" gogo/cpp_no_group/cpp_benchmark.cc + touch generate_cpp_no_group_benchmark_code +bin_PROGRAMS += cpp-no-group-benchmark +cpp_no_group_benchmark_LDADD = $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/third_party/benchmark/src/libbenchmark.a +cpp_no_group_benchmark_SOURCES = gogo/cpp_no_group/cpp_benchmark.cc +cpp_no_group_benchmark_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/gogo/cpp_no_group -I$(top_srcdir)/third_party/benchmark/include # Explicit deps because BUILT_SOURCES are only done before a "make all/check" # so a direct "make test_cpp" could fail if parallel enough. # See: https://www.gnu.org/software/automake/manual/html_node/Built-Sources-Example.html#Recording-Dependencies-manually -generate_datasets-generate_datasets.$(OBJEXT): benchmarks.pb.h +gogo/cpp_no_group/cpp_no_group_benchmark-cpp_benchmark.$(OBJEXT): $(cpp_no_group_benchmarks_protoc_outputs) $(cpp_no_group_benchmarks_protoc_outputs_proto2) $(cpp_no_group_benchmarks_protoc_outputs_header) \ + $(cpp_no_group_benchmarks_protoc_outputs_proto2_header) $(top_srcdir)/third_party/benchmark/src/libbenchmark.a generate_cpp_no_group_benchmark_code +gogo/cpp_no_group/cpp_benchmark.cc: generate_cpp_no_group_benchmark_code +nodist_cpp_no_group_benchmark_SOURCES = \ + $(cpp_no_group_benchmarks_protoc_outputs_proto2) \ + $(cpp_no_group_benchmarks_protoc_outputs) \ + $(cpp_no_group_benchmarks_protoc_outputs_header) \ + $(cpp_no_group_benchmarks_protoc_outputs_proto2_header) -cpp_benchmark_LDADD = $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/third_party/benchmark/src/libbenchmark.a -cpp_benchmark_SOURCES = cpp_benchmark.cc -cpp_benchmark_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir) -I$(top_srcdir)/third_party/benchmark/include -nodist_cpp_benchmark_SOURCES = \ - $(benchmarks_protoc_outputs) \ - $(benchmarks_protoc_outputs_proto2) +cpp_no_group: cpp_no_group_protoc_middleman generate_gogo_data cpp-no-group-benchmark + ./cpp-no-group-benchmark $(gogo_data) -$(benchmarks_protoc_outputs): protoc_middleman -$(benchmarks_protoc_outputs_proto2): protoc_middleman2 +gogo_proto_middleman: protoc-gen-gogoproto + mkdir -p "tmp/gogo_proto" + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I$(srcdir) -I$(top_srcdir) --plugin=protoc-gen-gogoproto --gogoproto_out=$$oldpwd/tmp/gogo_proto $(benchmarks_protoc_inputs) $(benchmarks_protoc_inputs_benchmark_wrapper) $(benchmarks_protoc_inputs_proto2) ) + touch gogo_proto_middleman -CLEANFILES = \ - $(benchmarks_protoc_outputs) \ - $(benchmarks_protoc_outputs_proto2) \ - protoc_middleman \ - protoc_middleman2 \ - dataset.* +gogo_data = $$(for data in $(all_data); do echo "tmp/gogo_data$${data\#$(srcdir)}"; done | xargs) -MAINTAINERCLEANFILES = \ - Makefile.in +generate_gogo_data: protoc_middleman protoc_middleman2 gogo-data-scrubber + mkdir -p `dirname $(gogo_data)` + ./gogo-data-scrubber $(all_data) $(gogo_data) + touch generate_gogo_data -if USE_EXTERNAL_PROTOC +make_tmp_dir_gogo: + mkdir -p tmp/go_no_group/benchmark_code + mkdir -p tmp/gogofast/benchmark_code + mkdir -p tmp/gogofaster/benchmark_code + mkdir -p tmp/gogoslick/benchmark_code + touch make_tmp_dir_gogo -protoc_middleman: $(benchmarks_protoc_inputs) - $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. $(benchmarks_protoc_inputs) - touch protoc_middleman +go_no_group_protoc_middleman: make_tmp_dir_gogo $(top_srcdir)/src/protoc$(EXEEXT) gogo_proto_middleman $(well_known_type_protoc_inputs) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --go_out=$$oldpwd/tmp/go_no_group $(benchmarks_protoc_inputs) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --go_out=$$oldpwd/tmp/go_no_group $(benchmarks_protoc_inputs_benchmark_wrapper) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --go_out=$$oldpwd/tmp/go_no_group $(benchmarks_protoc_inputs_proto2_message1) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --go_out=$$oldpwd/tmp/go_no_group $(benchmarks_protoc_inputs_proto2_message2) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --go_out=$$oldpwd/tmp/go_no_group $(benchmarks_protoc_inputs_proto2_message3) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --go_out=$$oldpwd/tmp/go_no_group $(benchmarks_protoc_inputs_proto2_message4) ) + touch go_no_group_protoc_middleman -protoc_middleman2: $(benchmarks_protoc_inputs_proto2) - $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. $(benchmarks_protoc_inputs_proto2) - touch protoc_middleman2 +cpp_no_group_protoc_middleman: make_tmp_dir_gogo $(top_srcdir)/src/protoc$(EXEEXT) gogo_proto_middleman $(well_known_type_protoc_inputs) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --cpp_out=$$oldpwd/gogo/cpp_no_group $(benchmarks_protoc_inputs) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --cpp_out=$$oldpwd/gogo/cpp_no_group $(benchmarks_protoc_inputs_benchmark_wrapper) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --cpp_out=$$oldpwd/gogo/cpp_no_group $(benchmarks_protoc_inputs_proto2_message1) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --cpp_out=$$oldpwd/gogo/cpp_no_group $(benchmarks_protoc_inputs_proto2_message2) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --cpp_out=$$oldpwd/gogo/cpp_no_group $(benchmarks_protoc_inputs_proto2_message3) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --cpp_out=$$oldpwd/gogo/cpp_no_group $(benchmarks_protoc_inputs_proto2_message4) ) + touch cpp_no_group_protoc_middleman -else +gogofast_protoc_middleman: make_tmp_dir_gogo $(top_srcdir)/src/protoc$(EXEEXT) gogo_proto_middleman $(well_known_type_protoc_inputs) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofast_out=$$oldpwd/tmp/gogofast $(benchmarks_protoc_inputs) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofast_out=$$oldpwd/tmp/gogofast $(benchmarks_protoc_inputs_benchmark_wrapper) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofast_out=$$oldpwd/tmp/gogofast $(benchmarks_protoc_inputs_proto2_message1) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofast_out=$$oldpwd/tmp/gogofast $(benchmarks_protoc_inputs_proto2_message2) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofast_out=$$oldpwd/tmp/gogofast $(benchmarks_protoc_inputs_proto2_message3) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofast_out=$$oldpwd/tmp/gogofast $(benchmarks_protoc_inputs_proto2_message4) ) + touch gogofast_protoc_middleman -# We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is -# relative to srcdir, which may not be the same as the current directory when -# building out-of-tree. -protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(benchmarks_protoc_inputs) $(well_known_type_protoc_inputs) - oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd $(benchmarks_protoc_inputs) ) - touch protoc_middleman +gogofaster_protoc_middleman: make_tmp_dir_gogo $(top_srcdir)/src/protoc$(EXEEXT) gogo_proto_middleman $(well_known_type_protoc_inputs) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofaster_out=$$oldpwd/tmp/gogofaster $(benchmarks_protoc_inputs) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofaster_out=$$oldpwd/tmp/gogofaster $(benchmarks_protoc_inputs_benchmark_wrapper) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofaster_out=$$oldpwd/tmp/gogofaster $(benchmarks_protoc_inputs_proto2_message1) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofaster_out=$$oldpwd/tmp/gogofaster $(benchmarks_protoc_inputs_proto2_message2) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofaster_out=$$oldpwd/tmp/gogofaster $(benchmarks_protoc_inputs_proto2_message3) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofaster_out=$$oldpwd/tmp/gogofaster $(benchmarks_protoc_inputs_proto2_message4) ) + touch gogofaster_protoc_middleman -protoc_middleman2: $(top_srcdir)/src/protoc$(EXEEXT) $(benchmarks_protoc_inputs_proto2) $(well_known_type_protoc_inputs) - oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd $(benchmarks_protoc_inputs_proto2) ) - touch protoc_middleman +gogoslick_protoc_middleman: make_tmp_dir_gogo $(top_srcdir)/src/protoc$(EXEEXT) gogo_proto_middleman $(well_known_type_protoc_inputs) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogoslick_out=$$oldpwd/tmp/gogoslick $(benchmarks_protoc_inputs) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogoslick_out=$$oldpwd/tmp/gogoslick $(benchmarks_protoc_inputs_benchmark_wrapper) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogoslick_out=$$oldpwd/tmp/gogoslick $(benchmarks_protoc_inputs_proto2_message1) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogoslick_out=$$oldpwd/tmp/gogoslick $(benchmarks_protoc_inputs_proto2_message2) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogoslick_out=$$oldpwd/tmp/gogoslick $(benchmarks_protoc_inputs_proto2_message3) ) + oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogoslick_out=$$oldpwd/tmp/gogoslick $(benchmarks_protoc_inputs_proto2_message4) ) + touch gogoslick_protoc_middleman + +generate-gogo-benchmark-code: + @echo '#! /bin/bash' > generate-gogo-benchmark-code + @echo 'cp $(srcdir)/go/go_benchmark_test.go tmp/$$1/benchmark_code/$$1_benchmark1_test.go' >> generate-gogo-benchmark-code + @echo 'sed -i -e "s/\.\.\/tmp/../g" tmp/$$1/benchmark_code/$$1_benchmark1_test.go' >> generate-gogo-benchmark-code + @echo 'sed -i -e "s/b\.Run(\"\(.*\)\"/b.Run(\"\1\_$$1\"/g" tmp/$$1/benchmark_code/$$1_benchmark1_test.go' >> generate-gogo-benchmark-code + @echo 'if [[ $$2 == 1 ]]; then sed -i -e "s/github\.com\/golang/github.com\/gogo/g" tmp/$$1/benchmark_code/$$1_benchmark1_test.go; fi ' >> generate-gogo-benchmark-code + @chmod +x generate-gogo-benchmark-code + +generate_all_gogo_benchmark_code: generate-gogo-benchmark-code make_tmp_dir_gogo + ./generate-gogo-benchmark-code go_no_group 0 + ./generate-gogo-benchmark-code gogofast 1 + ./generate-gogo-benchmark-code gogofaster 1 + ./generate-gogo-benchmark-code gogoslick 1 + +gogo-benchmark: + @echo "Writing shortcut script gogo-benchmark..." + @echo '#! /bin/bash' > gogo-benchmark + @echo 'cd tmp/$$1/benchmark_code' >> gogo-benchmark + @echo 'shift' >> gogo-benchmark + @echo 'all_data=""' >> gogo-benchmark + @echo 'for data_file in $$@; do all_data="$$all_data ../../../$$data_file"; done' >> gogo-benchmark + @echo 'go test -bench=. -- $$all_data' >> gogo-benchmark + @echo 'cd ../..' >> gogo-benchmark + @chmod +x gogo-benchmark + +go_no_group: go_no_group_protoc_middleman generate_gogo_data generate_all_gogo_benchmark_code gogo-benchmark + ./gogo-benchmark go_no_group $(gogo_data) + +gogofast: gogofast_protoc_middleman generate_gogo_data gogo-benchmark generate_all_gogo_benchmark_code + ./gogo-benchmark gogofast $(gogo_data) + +gogofaster: gogofaster_protoc_middleman generate_gogo_data gogo-benchmark generate_all_gogo_benchmark_code + ./gogo-benchmark gogofaster $(gogo_data) + +gogoslick: gogoslick_protoc_middleman generate_gogo_data gogo-benchmark generate_all_gogo_benchmark_code + ./gogo-benchmark gogoslick $(gogo_data) + + +############# GOGO RULES END ############ + + +############ UTIL RULES BEGIN ############ + +bin_PROGRAMS += protoc-gen-gogoproto gogo-data-scrubber protoc-gen-proto2_to_proto3 proto3-data-stripper + +protoc_gen_gogoproto_LDADD = $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/src/libprotoc.la +protoc_gen_gogoproto_SOURCES = util/protoc-gen-gogoproto.cc +protoc_gen_gogoproto_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/cpp -I$(srcdir)/util + +gogo_data_scrubber_LDADD = $(top_srcdir)/src/libprotobuf.la +gogo_data_scrubber_SOURCES = util/gogo_data_scrubber.cc +gogo_data_scrubber_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/cpp -I$(srcdir)/util +util/gogo_data_scrubber-gogo_data_scrubber.$(OBJEXT): $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2) $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header) +nodist_gogo_data_scrubber_SOURCES = \ + $(benchmarks_protoc_outputs) \ + $(benchmarks_protoc_outputs_proto2) \ + $(benchmarks_protoc_outputs_proto2_header) \ + $(benchmarks_protoc_outputs_header) + +protoc_gen_proto2_to_proto3_LDADD = $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/src/libprotoc.la +protoc_gen_proto2_to_proto3_SOURCES = util/protoc-gen-proto2_to_proto3.cc +protoc_gen_proto2_to_proto3_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/cpp -I$(srcdir)/util + +proto3_data_stripper_LDADD = $(top_srcdir)/src/libprotobuf.la +proto3_data_stripper_SOURCES = util/proto3_data_stripper.cc +proto3_data_stripper_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/cpp -I$(srcdir)/util +util/proto3_data_stripper-proto3_data_stripper.$(OBJEXT): $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2) $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header) +nodist_proto3_data_stripper_SOURCES = \ + $(benchmarks_protoc_outputs) \ + $(benchmarks_protoc_outputs_proto2) \ + $(benchmarks_protoc_outputs_proto2_header) \ + $(benchmarks_protoc_outputs_header) + + +############ UTIL RULES END ############ + +############ PROTO3 PREPARATION BEGIN ############# + +proto3_proto_middleman: protoc-gen-proto2_to_proto3 + mkdir -p "tmp/proto3_proto" + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I$(srcdir) -I$(top_srcdir) --plugin=protoc-gen-proto2_to_proto3 --proto2_to_proto3_out=$$oldpwd/tmp/proto3_proto $(benchmarks_protoc_inputs) $(benchmarks_protoc_inputs_benchmark_wrapper) $(benchmarks_protoc_inputs_proto2) ) + touch proto3_proto_middleman + +full_srcdir = $$(cd $(srcdir) && pwd) +proto3_data = $$(for data in $(all_data); do echo $(full_srcdir)"/tmp/proto3_data$${data\#$(full_srcdir)}"; done | xargs) + +generate_proto3_data: protoc_middleman protoc_middleman2 proto3-data-stripper + mkdir -p `dirname $(proto3_data)` + ./proto3-data-stripper $(all_data) $(proto3_data) + touch generate_proto3_data + +############ PROTO3 PREPARATION END ############# + +############ PHP RULES BEGIN ################# + +proto3_middleman_php: proto3_proto_middleman + mkdir -p "tmp/php" + oldpwd=`pwd` && ( cd tmp/proto3_proto && $$oldpwd/../src/protoc$(EXEEXT) -I$(srcdir) -I$(top_srcdir) --php_out=$$oldpwd/tmp/php $(benchmarks_protoc_inputs) $(benchmarks_protoc_inputs_benchmark_wrapper) $(benchmarks_protoc_inputs_proto2) ) + touch proto3_middleman_php + +php-benchmark: proto3_middleman_php generate_proto3_data + mkdir -p "tmp/php/Google/Protobuf/Benchmark" && cp php/PhpBenchmark.php "tmp/php/Google/Protobuf/Benchmark" + cp php/autoload.php "tmp/php" + @echo "Writing shortcut script php-benchmark..." + @echo '#! /bin/bash' > php-benchmark + @echo 'export PROTOBUF_PHP_SRCDIR="$$(cd $(top_srcdir) && pwd)/php/src"' >> php-benchmark + @echo 'cd tmp/php' >> php-benchmark + @echo 'export CURRENT_DIR=$$(pwd)' >> php-benchmark + @echo 'php -d auto_prepend_file="autoload.php" -d include_path="$$(pwd)" Google/Protobuf/Benchmark/PhpBenchmark.php $$@' >> php-benchmark + @echo 'cd ../..' >> php-benchmark + @chmod +x php-benchmark + +php: php-benchmark proto3_middleman_php + ./php-benchmark --behavior_prefix="php" $(proto3_data) + +php_c_extension: + cd $(top_srcdir)/php/ext/google/protobuf && phpize && ./configure CFLAGS='-O3' && make -j8 + +php-c-benchmark: proto3_middleman_php generate_proto3_data php_c_extension php_c_extension + mkdir -p "tmp/php/Google/Protobuf/Benchmark" && cp php/PhpBenchmark.php "tmp/php/Google/Protobuf/Benchmark" + cp php/autoload.php "tmp/php" + @echo "Writing shortcut script php-c-benchmark..." + @echo '#! /bin/bash' > php-c-benchmark + @echo 'export PROTOBUF_PHP_SRCDIR="$$(cd $(top_srcdir) && pwd)/php/src"' >> php-c-benchmark + @echo 'export PROTOBUF_PHP_EXTDIR="$$PROTOBUF_PHP_SRCDIR/../ext/google/protobuf/modules"' >> php-c-benchmark + @echo 'cd tmp/php' >> php-c-benchmark + @echo 'export CURRENT_DIR=$$(pwd)' >> php-c-benchmark + @echo 'php -d auto_prepend_file="autoload.php" -d include_path="$$(pwd)" -d extension="$$PROTOBUF_PHP_EXTDIR/protobuf.so" Google/Protobuf/Benchmark/PhpBenchmark.php $$@' >> php-c-benchmark + @echo 'cd ../..' >> php-c-benchmark + @chmod +x php-c-benchmark + +php_c: php-c-benchmark proto3_middleman_php + ./php-c-benchmark --behavior_prefix="php_c" $(proto3_data) + + +############ PHP RULES END ################# + +############ protobuf.js RULE BEGIN ############# + +pbjs_preparation: + mkdir -p tmp/protobuf.js + cd tmp/protobuf.js && git clone https://github.com/dcodeIO/protobuf.js.git && \ + cd protobuf.js && npm install && npm run build + cd tmp/protobuf.js && npm install benchmark + cp protobuf.js/* tmp/protobuf.js + cp js/benchmark_suite.js tmp/protobuf.js + touch pbjs_preparation + +pbjs_middleman: pbjs_preparation + export OLDDIR=$$(pwd) && cd tmp/protobuf.js && node generate_pbjs_files.js --target static-module --include_path=$$OLDDIR -o generated_bundle_code.js $(benchmarks_protoc_inputs) $(benchmarks_protoc_inputs_benchmark_wrapper) $(benchmarks_protoc_inputs_proto2) + touch pbjs_middleman + +pbjs-benchmark: pbjs_middleman + @echo '#! /bin/bash' > pbjs-benchmark + @echo 'cd tmp/protobuf.js' >> pbjs-benchmark + @echo 'sed -i "s/protobufjs/.\/protobuf.js/g" generated_bundle_code.js' >> pbjs-benchmark + @echo 'env NODE_PATH=".:./node_modules:$$NODE_PATH" node protobufjs_benchmark.js $$@' >> pbjs-benchmark + @chmod +x pbjs-benchmark + +pbjs: pbjs-benchmark + ./pbjs-benchmark $(all_data) + +############ protobuf.js RULE END ############# + +############ JS RULE BEGIN ############# + +js_preparation: + mkdir -p tmp/js + oldpwd=$$(pwd) && cd $(top_srcdir)/js && npm install && npm test + cd tmp/js && npm install benchmark + cp js/* tmp/js + touch js_preparation + +js_middleman: js_preparation + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --js_out=import_style=commonjs,binary:$$oldpwd/tmp/js $(benchmarks_protoc_inputs) $(benchmarks_protoc_inputs_benchmark_wrapper) $(benchmarks_protoc_inputs_proto2)) + touch js_middleman + +js-benchmark: js_middleman + @echo '#! /bin/bash' > js-benchmark + @echo 'export TOP_JS_SRCDIR=$$(cd $(top_srcdir)/js && pwd)' >> js-benchmark + @echo 'cd tmp/js' >> js-benchmark + @echo 'env NODE_PATH="$$TOP_JS_SRCDIR:.:./node_modules:$$NODE_PATH" node --max-old-space-size=4096 js_benchmark.js $$@' >> js-benchmark + @chmod +x js-benchmark + +js: js-benchmark + ./js-benchmark $(all_data) + +############ JS RULE END ############# + +EXTRA_DIST = \ + $(benchmarks_protoc_inputs_benchmark_wrapper) \ + $(benchmarks_protoc_inputs) \ + $(benchmarks_protoc_inputs_proto2) \ + google_size.proto + +MAINTAINERCLEANFILES = \ + Makefile.in + +CLEANFILES = \ + $(benchmarks_protoc_outputs) \ + $(benchmarks_protoc_outputs_header) \ + $(benchmarks_protoc_outputs_proto2) \ + $(benchmarks_protoc_outputs_proto2_header) \ + initialize_submodule \ + make_tmp_dir \ + protoc_middleman \ + protoc_middleman2 \ + javac_middleman \ + java-benchmark \ + python_cpp_proto_library \ + python-pure-python-benchmark \ + python-cpp-reflection-benchmark \ + python-cpp-generated-code-benchmark \ + go-benchmark \ + go_protoc_middleman \ + make_tmp_dir_gogo \ + gogo_proto_middleman \ + generate_gogo_data \ + go_no_group_protoc_middleman \ + go_no_group \ + go-no-group-benchmark \ + $(cpp_no_group_benchmarks_protoc_outputs_header) \ + $(cpp_no_group_benchmarks_protoc_outputs) \ + $(cpp_no_group_benchmarks_protoc_outputs_proto2_header) \ + $(cpp_no_group_benchmarks_protoc_outputs_proto2) \ + generate_all_gogo_benchmark_code \ + generate-gogo-benchmark-code \ + cpp_no_group_protoc_middleman \ + generate_cpp_no_group_benchmark_code \ + generate_gogo_benchmark_code \ + gogofast_protoc_middleman \ + gogofast \ + gogofaster_protoc_middleman \ + gogofaster \ + gogoslick_protoc_middleman \ + gogoslick \ + gogo-benchmark \ + gogo/cpp_no_group/cpp_benchmark.* \ + proto3_proto_middleman \ + generate_proto3_data \ + php-benchmark \ + php-c-benchmark \ + proto3_middleman_php \ + pbjs_preparation \ + pbjs_middleman \ + pbjs-benchmark \ + js_preparation \ + js_middleman \ + js-benchmark + +clean-local: + -rm -rf tmp/* -endif diff --git a/benchmarks/ProtoBench.java b/benchmarks/ProtoBench.java deleted file mode 100644 index 86d62feb67a3f..0000000000000 --- a/benchmarks/ProtoBench.java +++ /dev/null @@ -1,203 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2009 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.protocolbuffers; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.lang.reflect.Method; - -import com.google.protobuf.ByteString; -import com.google.protobuf.CodedInputStream; -import com.google.protobuf.CodedOutputStream; -import com.google.protobuf.Message; - -public class ProtoBench { - - private static final long MIN_SAMPLE_TIME_MS = 2 * 1000; - private static final long TARGET_TIME_MS = 30 * 1000; - - private ProtoBench() { - // Prevent instantiation - } - - public static void main(String[] args) { - if (args.length < 2 || (args.length % 2) != 0) { - System.err.println("Usage: ProtoBench "); - System.err.println("The descriptor type name is the fully-qualified message name,"); - System.err.println("e.g. com.google.protocolbuffers.benchmark.Message1"); - System.err.println("(You can specify multiple pairs of descriptor type name and input data.)"); - System.exit(1); - } - boolean success = true; - for (int i = 0; i < args.length; i += 2) { - success &= runTest(args[i], args[i + 1]); - } - System.exit(success ? 0 : 1); - } - - /** - * Runs a single test. Error messages are displayed to stderr, and the return value - * indicates general success/failure. - */ - public static boolean runTest(String type, String file) { - System.out.println("Benchmarking " + type + " with file " + file); - final Message defaultMessage; - try { - Class clazz = Class.forName(type); - Method method = clazz.getDeclaredMethod("getDefaultInstance"); - defaultMessage = (Message) method.invoke(null); - } catch (Exception e) { - // We want to do the same thing with all exceptions. Not generally nice, - // but this is slightly different. - System.err.println("Unable to get default message for " + type); - return false; - } - - try { - final byte[] inputData = readAllBytes(file); - final ByteArrayInputStream inputStream = new ByteArrayInputStream(inputData); - final ByteString inputString = ByteString.copyFrom(inputData); - final Message sampleMessage = defaultMessage.newBuilderForType().mergeFrom(inputString).build(); - FileOutputStream devNullTemp = null; - CodedOutputStream reuseDevNullTemp = null; - try { - devNullTemp = new FileOutputStream("/dev/null"); - reuseDevNullTemp = CodedOutputStream.newInstance(devNullTemp); - } catch (FileNotFoundException e) { - // ignore: this is probably Windows, where /dev/null does not exist - } - final FileOutputStream devNull = devNullTemp; - final CodedOutputStream reuseDevNull = reuseDevNullTemp; - benchmark("Serialize to byte string", inputData.length, new Action() { - public void execute() { sampleMessage.toByteString(); } - }); - benchmark("Serialize to byte array", inputData.length, new Action() { - public void execute() { sampleMessage.toByteArray(); } - }); - benchmark("Serialize to memory stream", inputData.length, new Action() { - public void execute() throws IOException { - sampleMessage.writeTo(new ByteArrayOutputStream()); - } - }); - if (devNull != null) { - benchmark("Serialize to /dev/null with FileOutputStream", inputData.length, new Action() { - public void execute() throws IOException { - sampleMessage.writeTo(devNull); - } - }); - benchmark("Serialize to /dev/null reusing FileOutputStream", inputData.length, new Action() { - public void execute() throws IOException { - sampleMessage.writeTo(reuseDevNull); - reuseDevNull.flush(); // force the write to the OutputStream - } - }); - } - benchmark("Deserialize from byte string", inputData.length, new Action() { - public void execute() throws IOException { - defaultMessage.newBuilderForType().mergeFrom(inputString).build(); - } - }); - benchmark("Deserialize from byte array", inputData.length, new Action() { - public void execute() throws IOException { - defaultMessage.newBuilderForType() - .mergeFrom(CodedInputStream.newInstance(inputData)).build(); - } - }); - benchmark("Deserialize from memory stream", inputData.length, new Action() { - public void execute() throws IOException { - defaultMessage.newBuilderForType() - .mergeFrom(CodedInputStream.newInstance(inputStream)).build(); - inputStream.reset(); - } - }); - System.out.println(); - return true; - } catch (Exception e) { - System.err.println("Error: " + e.getMessage()); - System.err.println("Detailed exception information:"); - e.printStackTrace(System.err); - return false; - } - } - - private static void benchmark(String name, long dataSize, Action action) throws IOException { - // Make sure it's JITted "reasonably" hard before running the first progress test - for (int i=0; i < 100; i++) { - action.execute(); - } - - // Run it progressively more times until we've got a reasonable sample - int iterations = 1; - long elapsed = timeAction(action, iterations); - while (elapsed < MIN_SAMPLE_TIME_MS) { - iterations *= 2; - elapsed = timeAction(action, iterations); - } - - // Upscale the sample to the target time. Do this in floating point arithmetic - // to avoid overflow issues. - iterations = (int) ((TARGET_TIME_MS / (double) elapsed) * iterations); - elapsed = timeAction(action, iterations); - System.out.println(name + ": " + iterations + " iterations in " - + (elapsed/1000f) + "s; " - + (iterations * dataSize) / (elapsed * 1024 * 1024 / 1000f) - + "MB/s"); - } - - private static long timeAction(Action action, int iterations) throws IOException { - System.gc(); - long start = System.currentTimeMillis(); - for (int i = 0; i < iterations; i++) { - action.execute(); - } - long end = System.currentTimeMillis(); - return end - start; - } - - private static byte[] readAllBytes(String filename) throws IOException { - RandomAccessFile file = new RandomAccessFile(new File(filename), "r"); - byte[] content = new byte[(int) file.length()]; - file.readFully(content); - return content; - } - - /** - * Interface used to capture a single action to benchmark. - */ - interface Action { - void execute() throws IOException; - } -} diff --git a/benchmarks/README.md b/benchmarks/README.md index c902780582a00..76788175c6566 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -3,23 +3,238 @@ This directory contains benchmarking schemas and data sets that you can use to test a variety of performance scenarios against your -protobuf language runtime. +protobuf language runtime. If you are looking for performance +numbers of officially support languages, see [here]( +https://github.com/protocolbuffers/protobuf/blob/master/docs/performance.md) -The schema for the datasets is described in `benchmarks.proto`. +## Prerequisite + +First, you need to follow the instruction in the root directory's README to +build your language's protobuf, then: + +### CPP +You need to install [cmake](https://cmake.org/) before building the benchmark. + +We are using [google/benchmark](https://github.com/google/benchmark) as the +benchmark tool for testing cpp. This will be automatically made during build the +cpp benchmark. + +The cpp protobuf performance can be improved by linking with [tcmalloc library]( +https://gperftools.github.io/gperftools/tcmalloc.html). For using tcmalloc, you +need to build [gpertools](https://github.com/gperftools/gperftools) to generate +libtcmallc.so library. + +### Java +We're using maven to build the java benchmarks, which is the same as to build +the Java protobuf. There're no other tools need to install. We're using +[google/caliper](https://github.com/google/caliper) as benchmark tool, which +can be automatically included by maven. + +### Python +We're using python C++ API for testing the generated +CPP proto version of python protobuf, which is also a prerequisite for Python +protobuf cpp implementation. You need to install the correct version of Python +C++ extension package before run generated CPP proto version of Python +protobuf's benchmark. e.g. under Ubuntu, you need to + +``` +$ sudo apt-get install python-dev +$ sudo apt-get install python3-dev +``` +And you also need to make sure `pkg-config` is installed. + +### Go +Go protobufs are maintained at [github.com/golang/protobuf]( +http://github.com/golang/protobuf). If not done already, you need to install the +toolchain and the Go protoc-gen-go plugin for protoc. + +To install protoc-gen-go, run: + +``` +$ go get -u github.com/golang/protobuf/protoc-gen-go +$ export PATH=$PATH:$(go env GOPATH)/bin +``` + +The first command installs `protoc-gen-go` into the `bin` directory in your local `GOPATH`. +The second command adds the `bin` directory to your `PATH` so that `protoc` can locate the plugin later. + +### PHP +PHP benchmark's requirement is the same as PHP protobuf's requirements. The benchmark will automatically +include PHP protobuf's src and build the c extension if required. + +### Node.js +Node.js benchmark need [node](https://nodejs.org/en/)(higher than V6) and [npm](https://www.npmjs.com/) package manager installed. This benchmark is using the [benchmark](https://www.npmjs.com/package/benchmark) framework to test, which needn't to manually install. And another prerequisite is [protobuf js](https://github.com/protocolbuffers/protobuf/tree/master/js), which needn't to manually install either + +### C# +The C# benchmark code is built as part of the main Google.Protobuf +solution. It requires the .NET Core SDK, and depends on +[BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet), which +will be downloaded automatically. + +### Big data + +There's some optional big testing data which is not included in the directory +initially, you need to run the following command to download the testing data: + +``` +$ ./download_data.sh +``` + +After doing this the big data file will automatically generated in the +benchmark directory. + +## Run instructions + +To run all the benchmark dataset: -Generate the data sets like so: +### Java: ``` -$ make -$ ./generate-datasets -Wrote dataset: dataset.google_message1_proto3.pb -Wrote dataset: dataset.google_message1_proto2.pb -Wrote dataset: dataset.google_message2.pb -$ +$ make java ``` -Each data set will be written to its own file. Benchmarks will -likely want to run several benchmarks against each data set (parse, +### CPP: + +``` +$ make cpp +``` + +For linking with tcmalloc: + +``` +$ env LD_PRELOAD={directory to libtcmalloc.so} make cpp +``` + +### Python: + +We have three versions of python protobuf implementation: pure python, cpp +reflection and cpp generated code. To run these version benchmark, you need to: + +#### Pure Python: + +``` +$ make python-pure-python +``` + +#### CPP reflection: + +``` +$ make python-cpp-reflection +``` + +#### CPP generated code: + +``` +$ make python-cpp-generated-code +``` + +### Go +``` +$ make go +``` + + +### PHP +We have two version of php protobuf implementation: pure php, php with c extension. To run these version benchmark, you need to: +#### Pure PHP +``` +$ make php +``` +#### PHP with c extension +``` +$ make php_c +``` + +### Node.js +``` +$ make js +``` + +To run a specific dataset or run with specific options: + +### Java: + +``` +$ make java-benchmark +$ ./java-benchmark $(specific generated dataset file name) [$(caliper options)] +``` + +### CPP: + +``` +$ make cpp-benchmark +$ ./cpp-benchmark $(specific generated dataset file name) [$(benchmark options)] +``` + +### Python: + +For Python benchmark we have `--json` for outputting the json result + +#### Pure Python: + +``` +$ make python-pure-python-benchmark +$ ./python-pure-python-benchmark [--json] $(specific generated dataset file name) +``` + +#### CPP reflection: + +``` +$ make python-cpp-reflection-benchmark +$ ./python-cpp-reflection-benchmark [--json] $(specific generated dataset file name) +``` + +#### CPP generated code: + +``` +$ make python-cpp-generated-code-benchmark +$ ./python-cpp-generated-code-benchmark [--json] $(specific generated dataset file name) +``` + +### Go: +``` +$ make go-benchmark +$ ./go-benchmark $(specific generated dataset file name) [go testing options] +``` + +### PHP +#### Pure PHP +``` +$ make php-benchmark +$ ./php-benchmark $(specific generated dataset file name) +``` +#### PHP with c extension +``` +$ make php-c-benchmark +$ ./php-c-benchmark $(specific generated dataset file name) +``` + +### Node.js +``` +$ make js-benchmark +$ ./js-benchmark $(specific generated dataset file name) +``` + +### C# +From `csharp/src/Google.Protobuf.Benchmarks`, run: + +``` +$ dotnet run -c Release +``` + +We intend to add support for this within the makefile in due course. + +## Benchmark datasets + +Each data set is in the format of benchmarks.proto: + +1. name is the benchmark dataset's name. +2. message_name is the benchmark's message type full name (including package and message name) +3. payload is the list of raw data. + +The schema for the datasets is described in `benchmarks.proto`. + +Benchmark likely want to run several benchmarks against each data set (parse, serialize, possibly JSON, possibly using different APIs, etc). We would like to add more data sets. In general we will favor data sets diff --git a/benchmarks/__init__.py b/benchmarks/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/benchmarks/benchmark_messages_proto2.proto b/benchmarks/benchmark_messages_proto2.proto deleted file mode 100644 index 590855033cc08..0000000000000 --- a/benchmarks/benchmark_messages_proto2.proto +++ /dev/null @@ -1,143 +0,0 @@ -// Benchmark messages for proto2. - -syntax = "proto2"; - -package benchmarks.proto2; -option java_package = "com.google.protobuf.benchmarks"; - -// This is the default, but we specify it here explicitly. -option optimize_for = SPEED; - -option cc_enable_arenas = true; - -message GoogleMessage1 { - required string field1 = 1; - optional string field9 = 9; - optional string field18 = 18; - optional bool field80 = 80 [default=false]; - optional bool field81 = 81 [default=true]; - required int32 field2 = 2; - required int32 field3 = 3; - optional int32 field280 = 280; - optional int32 field6 = 6 [default=0]; - optional int64 field22 = 22; - optional string field4 = 4; - repeated fixed64 field5 = 5; - optional bool field59 = 59 [default=false]; - optional string field7 = 7; - optional int32 field16 = 16; - optional int32 field130 = 130 [default=0]; - optional bool field12 = 12 [default=true]; - optional bool field17 = 17 [default=true]; - optional bool field13 = 13 [default=true]; - optional bool field14 = 14 [default=true]; - optional int32 field104 = 104 [default=0]; - optional int32 field100 = 100 [default=0]; - optional int32 field101 = 101 [default=0]; - optional string field102 = 102; - optional string field103 = 103; - optional int32 field29 = 29 [default=0]; - optional bool field30 = 30 [default=false]; - optional int32 field60 = 60 [default=-1]; - optional int32 field271 = 271 [default=-1]; - optional int32 field272 = 272 [default=-1]; - optional int32 field150 = 150; - optional int32 field23 = 23 [default=0]; - optional bool field24 = 24 [default=false]; - optional int32 field25 = 25 [default=0]; - optional GoogleMessage1SubMessage field15 = 15; - optional bool field78 = 78; - optional int32 field67 = 67 [default=0]; - optional int32 field68 = 68; - optional int32 field128 = 128 [default=0]; - optional string field129 = 129 [default="xxxxxxxxxxxxxxxxxxxxx"]; - optional int32 field131 = 131 [default=0]; -} - -message GoogleMessage1SubMessage { - optional int32 field1 = 1 [default=0]; - optional int32 field2 = 2 [default=0]; - optional int32 field3 = 3 [default=0]; - optional string field15 = 15; - optional bool field12 = 12 [default=true]; - optional int64 field13 = 13; - optional int64 field14 = 14; - optional int32 field16 = 16; - optional int32 field19 = 19 [default=2]; - optional bool field20 = 20 [default=true]; - optional bool field28 = 28 [default=true]; - optional fixed64 field21 = 21; - optional int32 field22 = 22; - optional bool field23 = 23 [ default=false ]; - optional bool field206 = 206 [default=false]; - optional fixed32 field203 = 203; - optional int32 field204 = 204; - optional string field205 = 205; - optional uint64 field207 = 207; - optional uint64 field300 = 300; -} - -message GoogleMessage2 { - optional string field1 = 1; - optional int64 field3 = 3; - optional int64 field4 = 4; - optional int64 field30 = 30; - optional bool field75 = 75 [default=false]; - optional string field6 = 6; - optional bytes field2 = 2; - optional int32 field21 = 21 [default=0]; - optional int32 field71 = 71; - optional float field25 = 25; - optional int32 field109 = 109 [default=0]; - optional int32 field210 = 210 [default=0]; - optional int32 field211 = 211 [default=0]; - optional int32 field212 = 212 [default=0]; - optional int32 field213 = 213 [default=0]; - optional int32 field216 = 216 [default=0]; - optional int32 field217 = 217 [default=0]; - optional int32 field218 = 218 [default=0]; - optional int32 field220 = 220 [default=0]; - optional int32 field221 = 221 [default=0]; - optional float field222 = 222 [default=0.0]; - optional int32 field63 = 63; - - repeated group Group1 = 10 { - required float field11 = 11; - optional float field26 = 26; - optional string field12 = 12; - optional string field13 = 13; - repeated string field14 = 14; - required uint64 field15 = 15; - optional int32 field5 = 5; - optional string field27 = 27; - optional int32 field28 = 28; - optional string field29 = 29; - optional string field16 = 16; - repeated string field22 = 22; - repeated int32 field73 = 73; - optional int32 field20 = 20 [default=0]; - optional string field24 = 24; - optional GoogleMessage2GroupedMessage field31 = 31; - } - repeated string field128 = 128; - optional int64 field131 = 131; - repeated string field127 = 127; - optional int32 field129 = 129; - repeated int64 field130 = 130; - optional bool field205 = 205 [default=false]; - optional bool field206 = 206 [default=false]; -} - -message GoogleMessage2GroupedMessage { - optional float field1 = 1; - optional float field2 = 2; - optional float field3 = 3 [default=0.0]; - optional bool field4 = 4; - optional bool field5 = 5; - optional bool field6 = 6 [default=true]; - optional bool field7 = 7 [default=false]; - optional float field8 = 8; - optional bool field9 = 9; - optional float field10 = 10; - optional int64 field11 = 11; -} diff --git a/benchmarks/benchmark_messages_proto3.proto b/benchmarks/benchmark_messages_proto3.proto deleted file mode 100644 index 090b554be9c0c..0000000000000 --- a/benchmarks/benchmark_messages_proto3.proto +++ /dev/null @@ -1,78 +0,0 @@ -// Benchmark messages for proto3. - -syntax = "proto3"; - -package benchmarks.proto3; -option java_package = "com.google.protobuf.benchmarks"; - -// This is the default, but we specify it here explicitly. -option optimize_for = SPEED; - -option cc_enable_arenas = true; - -message GoogleMessage1 { - string field1 = 1; - string field9 = 9; - string field18 = 18; - bool field80 = 80; - bool field81 = 81; - int32 field2 = 2; - int32 field3 = 3; - int32 field280 = 280; - int32 field6 = 6; - int64 field22 = 22; - string field4 = 4; - repeated fixed64 field5 = 5; - bool field59 = 59; - string field7 = 7; - int32 field16 = 16; - int32 field130 = 130; - bool field12 = 12; - bool field17 = 17; - bool field13 = 13; - bool field14 = 14; - int32 field104 = 104; - int32 field100 = 100; - int32 field101 = 101; - string field102 = 102; - string field103 = 103; - int32 field29 = 29; - bool field30 = 30; - int32 field60 = 60; - int32 field271 = 271; - int32 field272 = 272; - int32 field150 = 150; - int32 field23 = 23; - bool field24 = 24; - int32 field25 = 25; - GoogleMessage1SubMessage field15 = 15; - bool field78 = 78; - int32 field67 = 67; - int32 field68 = 68; - int32 field128 = 128; - string field129 = 129; - int32 field131 = 131; -} - -message GoogleMessage1SubMessage { - int32 field1 = 1; - int32 field2 = 2; - int32 field3 = 3; - string field15 = 15; - bool field12 = 12; - int64 field13 = 13; - int64 field14 = 14; - int32 field16 = 16; - int32 field19 = 19; - bool field20 = 20; - bool field28 = 28; - fixed64 field21 = 21; - int32 field22 = 22; - bool field23 = 23; - bool field206 = 206; - fixed32 field203 = 203; - int32 field204 = 204; - string field205 = 205; - uint64 field207 = 207; - uint64 field300 = 300; -} diff --git a/benchmarks/cpp_benchmark.cc b/benchmarks/cpp/cpp_benchmark.cc similarity index 87% rename from benchmarks/cpp_benchmark.cc rename to benchmarks/cpp/cpp_benchmark.cc index 0e6febc2f1526..036d234fb7417 100644 --- a/benchmarks/cpp_benchmark.cc +++ b/benchmarks/cpp/cpp_benchmark.cc @@ -28,13 +28,16 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include -#include #include -#include "benchmark/benchmark_api.h" +#include +#include "benchmark/benchmark.h" #include "benchmarks.pb.h" -#include "benchmark_messages_proto2.pb.h" -#include "benchmark_messages_proto3.pb.h" +#include "datasets/google_message1/proto2/benchmark_message1_proto2.pb.h" +#include "datasets/google_message1/proto3/benchmark_message1_proto3.pb.h" +#include "datasets/google_message2/benchmark_message2.pb.h" +#include "datasets/google_message3/benchmark_message3.pb.h" +#include "datasets/google_message4/benchmark_message4.pb.h" + #define PREFIX "dataset." #define SUFFIX ".pb" @@ -118,9 +121,10 @@ class ParseNewArenaFixture : public Fixture { virtual void BenchmarkCase(benchmark::State& state) { WrappingCounter i(payloads_.size()); size_t total = 0; + Arena arena; while (state.KeepRunning()) { - Arena arena; + arena.Reset(); Message* m = Arena::CreateMessage(&arena); const std::string& payload = payloads_[i.Next()]; total += payload.size(); @@ -219,6 +223,14 @@ void RegisterBenchmarks(const std::string& dataset_bytes) { RegisterBenchmarksForType(dataset); } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage2") { RegisterBenchmarksForType(dataset); + } else if (dataset.message_name() == + "benchmarks.google_message3.GoogleMessage3") { + RegisterBenchmarksForType + (dataset); + } else if (dataset.message_name() == + "benchmarks.google_message4.GoogleMessage4") { + RegisterBenchmarksForType + (dataset); } else { std::cerr << "Unknown message type: " << dataset.message_name(); exit(1); @@ -226,17 +238,17 @@ void RegisterBenchmarks(const std::string& dataset_bytes) { } int main(int argc, char *argv[]) { - glob_t glob_result; - if (glob("dataset.*.pb", 0, NULL, &glob_result) != 0) { - fprintf(stderr, "No dataset files found.\n"); + ::benchmark::Initialize(&argc, argv); + if (argc == 1) { + std::cerr << "Usage: ./cpp-benchmark " << std::endl; + std::cerr << "input data is in the format of \"benchmarks.proto\"" + << std::endl; return 1; + } else { + for (int i = 1; i < argc; i++) { + RegisterBenchmarks(ReadFile(argv[i])); + } } - for (size_t i = 0; i < glob_result.gl_pathc; i++) { - fprintf(stderr, "Found input dataset: %s\n", glob_result.gl_pathv[i]); - RegisterBenchmarks(ReadFile(glob_result.gl_pathv[i])); - } - - ::benchmark::Initialize(&argc, argv); ::benchmark::RunSpecifiedBenchmarks(); } diff --git a/benchmarks/datasets/google_message1/proto2/benchmark_message1_proto2.proto b/benchmarks/datasets/google_message1/proto2/benchmark_message1_proto2.proto new file mode 100644 index 0000000000000..e404b9fe1b47b --- /dev/null +++ b/benchmarks/datasets/google_message1/proto2/benchmark_message1_proto2.proto @@ -0,0 +1,108 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Benchmark messages for proto2. + +syntax = "proto2"; + +package benchmarks.proto2; +option java_package = "com.google.protobuf.benchmarks"; + +// This is the default, but we specify it here explicitly. +option optimize_for = SPEED; + +option cc_enable_arenas = true; + +message GoogleMessage1 { + required string field1 = 1; + optional string field9 = 9; + optional string field18 = 18; + optional bool field80 = 80 [default = false]; + optional bool field81 = 81 [default = true]; + required int32 field2 = 2; + required int32 field3 = 3; + optional int32 field280 = 280; + optional int32 field6 = 6 [default = 0]; + optional int64 field22 = 22; + optional string field4 = 4; + repeated fixed64 field5 = 5; + optional bool field59 = 59 [default = false]; + optional string field7 = 7; + optional int32 field16 = 16; + optional int32 field130 = 130 [default = 0]; + optional bool field12 = 12 [default = true]; + optional bool field17 = 17 [default = true]; + optional bool field13 = 13 [default = true]; + optional bool field14 = 14 [default = true]; + optional int32 field104 = 104 [default = 0]; + optional int32 field100 = 100 [default = 0]; + optional int32 field101 = 101 [default = 0]; + optional string field102 = 102; + optional string field103 = 103; + optional int32 field29 = 29 [default = 0]; + optional bool field30 = 30 [default = false]; + optional int32 field60 = 60 [default = -1]; + optional int32 field271 = 271 [default = -1]; + optional int32 field272 = 272 [default = -1]; + optional int32 field150 = 150; + optional int32 field23 = 23 [default = 0]; + optional bool field24 = 24 [default = false]; + optional int32 field25 = 25 [default = 0]; + optional GoogleMessage1SubMessage field15 = 15; + optional bool field78 = 78; + optional int32 field67 = 67 [default = 0]; + optional int32 field68 = 68; + optional int32 field128 = 128 [default = 0]; + optional string field129 = 129 [default = "xxxxxxxxxxxxxxxxxxxxx"]; + optional int32 field131 = 131 [default = 0]; +} + +message GoogleMessage1SubMessage { + optional int32 field1 = 1 [default = 0]; + optional int32 field2 = 2 [default = 0]; + optional int32 field3 = 3 [default = 0]; + optional string field15 = 15; + optional bool field12 = 12 [default = true]; + optional int64 field13 = 13; + optional int64 field14 = 14; + optional int32 field16 = 16; + optional int32 field19 = 19 [default = 2]; + optional bool field20 = 20 [default = true]; + optional bool field28 = 28 [default = true]; + optional fixed64 field21 = 21; + optional int32 field22 = 22; + optional bool field23 = 23 [default = false]; + optional bool field206 = 206 [default = false]; + optional fixed32 field203 = 203; + optional int32 field204 = 204; + optional string field205 = 205; + optional uint64 field207 = 207; + optional uint64 field300 = 300; +} diff --git a/benchmarks/datasets/google_message1/proto2/dataset.google_message1_proto2.pb b/benchmarks/datasets/google_message1/proto2/dataset.google_message1_proto2.pb new file mode 100644 index 0000000000000..f6fe7848cb889 Binary files /dev/null and b/benchmarks/datasets/google_message1/proto2/dataset.google_message1_proto2.pb differ diff --git a/benchmarks/datasets/google_message1/proto3/benchmark_message1_proto3.proto b/benchmarks/datasets/google_message1/proto3/benchmark_message1_proto3.proto new file mode 100644 index 0000000000000..8aee2f6728327 --- /dev/null +++ b/benchmarks/datasets/google_message1/proto3/benchmark_message1_proto3.proto @@ -0,0 +1,108 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Benchmark messages for proto3. + +syntax = "proto3"; + +package benchmarks.proto3; +option java_package = "com.google.protobuf.benchmarks"; + +// This is the default, but we specify it here explicitly. +option optimize_for = SPEED; + +option cc_enable_arenas = true; + +message GoogleMessage1 { + string field1 = 1; + string field9 = 9; + string field18 = 18; + bool field80 = 80; + bool field81 = 81; + int32 field2 = 2; + int32 field3 = 3; + int32 field280 = 280; + int32 field6 = 6; + int64 field22 = 22; + string field4 = 4; + repeated fixed64 field5 = 5; + bool field59 = 59; + string field7 = 7; + int32 field16 = 16; + int32 field130 = 130; + bool field12 = 12; + bool field17 = 17; + bool field13 = 13; + bool field14 = 14; + int32 field104 = 104; + int32 field100 = 100; + int32 field101 = 101; + string field102 = 102; + string field103 = 103; + int32 field29 = 29; + bool field30 = 30; + int32 field60 = 60; + int32 field271 = 271; + int32 field272 = 272; + int32 field150 = 150; + int32 field23 = 23; + bool field24 = 24; + int32 field25 = 25; + GoogleMessage1SubMessage field15 = 15; + bool field78 = 78; + int32 field67 = 67; + int32 field68 = 68; + int32 field128 = 128; + string field129 = 129; + int32 field131 = 131; +} + +message GoogleMessage1SubMessage { + int32 field1 = 1; + int32 field2 = 2; + int32 field3 = 3; + string field15 = 15; + bool field12 = 12; + int64 field13 = 13; + int64 field14 = 14; + int32 field16 = 16; + int32 field19 = 19; + bool field20 = 20; + bool field28 = 28; + fixed64 field21 = 21; + int32 field22 = 22; + bool field23 = 23; + bool field206 = 206; + fixed32 field203 = 203; + int32 field204 = 204; + string field205 = 205; + uint64 field207 = 207; + uint64 field300 = 300; +} diff --git a/benchmarks/datasets/google_message1/proto3/dataset.google_message1_proto3.pb b/benchmarks/datasets/google_message1/proto3/dataset.google_message1_proto3.pb new file mode 100644 index 0000000000000..4955bed31b5ae Binary files /dev/null and b/benchmarks/datasets/google_message1/proto3/dataset.google_message1_proto3.pb differ diff --git a/benchmarks/datasets/google_message2/benchmark_message2.proto b/benchmarks/datasets/google_message2/benchmark_message2.proto new file mode 100644 index 0000000000000..500c5d699f1e4 --- /dev/null +++ b/benchmarks/datasets/google_message2/benchmark_message2.proto @@ -0,0 +1,108 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// LINT: ALLOW_GROUPS + +// Benchmark messages for proto2. + +syntax = "proto2"; + +package benchmarks.proto2; +option java_package = "com.google.protobuf.benchmarks"; + +// This is the default, but we specify it here explicitly. +option optimize_for = SPEED; + +option cc_enable_arenas = true; + +message GoogleMessage2 { + optional string field1 = 1; + optional int64 field3 = 3; + optional int64 field4 = 4; + optional int64 field30 = 30; + optional bool field75 = 75 [default = false]; + optional string field6 = 6; + optional bytes field2 = 2; + optional int32 field21 = 21 [default = 0]; + optional int32 field71 = 71; + optional float field25 = 25; + optional int32 field109 = 109 [default = 0]; + optional int32 field210 = 210 [default = 0]; + optional int32 field211 = 211 [default = 0]; + optional int32 field212 = 212 [default = 0]; + optional int32 field213 = 213 [default = 0]; + optional int32 field216 = 216 [default = 0]; + optional int32 field217 = 217 [default = 0]; + optional int32 field218 = 218 [default = 0]; + optional int32 field220 = 220 [default = 0]; + optional int32 field221 = 221 [default = 0]; + optional float field222 = 222 [default = 0.0]; + optional int32 field63 = 63; + + repeated group Group1 = 10 { + required float field11 = 11; + optional float field26 = 26; + optional string field12 = 12; + optional string field13 = 13; + repeated string field14 = 14; + required uint64 field15 = 15; + optional int32 field5 = 5; + optional string field27 = 27; + optional int32 field28 = 28; + optional string field29 = 29; + optional string field16 = 16; + repeated string field22 = 22; + repeated int32 field73 = 73; + optional int32 field20 = 20 [default = 0]; + optional string field24 = 24; + optional GoogleMessage2GroupedMessage field31 = 31; + } + repeated string field128 = 128; + optional int64 field131 = 131; + repeated string field127 = 127; + optional int32 field129 = 129; + repeated int64 field130 = 130; + optional bool field205 = 205 [default = false]; + optional bool field206 = 206 [default = false]; +} + +message GoogleMessage2GroupedMessage { + optional float field1 = 1; + optional float field2 = 2; + optional float field3 = 3 [default = 0.0]; + optional bool field4 = 4; + optional bool field5 = 5; + optional bool field6 = 6 [default = true]; + optional bool field7 = 7 [default = false]; + optional float field8 = 8; + optional bool field9 = 9; + optional float field10 = 10; + optional int64 field11 = 11; +} diff --git a/benchmarks/datasets/google_message2/dataset.google_message2.pb b/benchmarks/datasets/google_message2/dataset.google_message2.pb new file mode 100644 index 0000000000000..3fa0e49e57db7 Binary files /dev/null and b/benchmarks/datasets/google_message2/dataset.google_message2.pb differ diff --git a/benchmarks/datasets/google_message3/benchmark_message3.proto b/benchmarks/datasets/google_message3/benchmark_message3.proto new file mode 100644 index 0000000000000..82422f924ea4a --- /dev/null +++ b/benchmarks/datasets/google_message3/benchmark_message3.proto @@ -0,0 +1,566 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// LINT: ALLOW_GROUPS + +syntax = "proto2"; + +package benchmarks.google_message3; + +import "datasets/google_message3/benchmark_message3_1.proto"; +import "datasets/google_message3/benchmark_message3_2.proto"; +import "datasets/google_message3/benchmark_message3_3.proto"; +import "datasets/google_message3/benchmark_message3_4.proto"; +import "datasets/google_message3/benchmark_message3_5.proto"; +import "datasets/google_message3/benchmark_message3_7.proto"; +import "datasets/google_message3/benchmark_message3_8.proto"; + +option cc_enable_arenas = true; +option java_package = "com.google.protobuf.benchmarks"; + +message GoogleMessage3 { + optional .benchmarks.google_message3.Message37487 field37519 = 2; + optional .benchmarks.google_message3.Message36876 field37520 = 3; + optional .benchmarks.google_message3.Message13062 field37521 = 4; + optional .benchmarks.google_message3.Message952 field37522 = 5; + optional .benchmarks.google_message3.UnusedEmptyMessage field37523 = 6; + optional .benchmarks.google_message3.UnusedEmptyMessage field37524 = 7; + optional .benchmarks.google_message3.UnusedEmptyMessage field37525 = 8; + optional .benchmarks.google_message3.UnusedEmptyMessage field37526 = 9; + optional .benchmarks.google_message3.UnusedEmptyMessage field37527 = 10; + optional .benchmarks.google_message3.UnusedEmptyMessage field37528 = 11; + optional .benchmarks.google_message3.UnusedEmptyMessage field37529 = 12; + optional .benchmarks.google_message3.UnusedEmptyMessage field37530 = 13; + optional .benchmarks.google_message3.UnusedEmptyMessage field37531 = 14; + optional .benchmarks.google_message3.UnusedEmptyMessage field37532 = 15; + optional .benchmarks.google_message3.UnusedEmptyMessage field37533 = 16; +} + +message Message1327 { + repeated .benchmarks.google_message3.UnusedEmptyMessage field1369 = 1; + repeated .benchmarks.google_message3.Message1328 field1370 = 3; + repeated .benchmarks.google_message3.UnusedEmptyMessage field1371 = 5; + repeated .benchmarks.google_message3.UnusedEmptyMessage field1372 = 6; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message1327 field1373 = 23104162; + } +} + +message Message3672 { + optional .benchmarks.google_message3.Enum3476 field3727 = 1; + optional int32 field3728 = 11; + optional int32 field3729 = 2; + repeated group Message3673 = 3 { + required .benchmarks.google_message3.Enum3476 field3738 = 4; + required int32 field3739 = 5; + } + repeated group Message3674 = 6 { + required .benchmarks.google_message3.Enum3476 field3740 = 7; + required int32 field3741 = 8; + } + optional bool field3732 = 9; + optional int32 field3733 = 10; + optional .benchmarks.google_message3.Enum3476 field3734 = 20; + optional int32 field3735 = 21; + optional .benchmarks.google_message3.UnusedEmptyMessage field3736 = 50; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message3672 field3737 = 3144435; + } +} + +message Message3804 { + required int64 field3818 = 1; + required bool field3819 = 2; + repeated .benchmarks.google_message3.Enum3805 field3820 = 4; + optional int32 field3821 = 5; + optional bool field3822 = 6; + optional int64 field3823 = 7; + optional .benchmarks.google_message3.Enum3783 field3824 = 8; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message3804 field3825 = 59241828; + } +} + +message Message6849 { + repeated .benchmarks.google_message3.Message6850 field6910 = 1; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message6849 field6911 = 107558455; + } +} + +message Message6866 { + repeated .benchmarks.google_message3.Message6863 field6973 = 1; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message6866 field6974 = 22259060; + } +} + +message Message6870 { + repeated .benchmarks.google_message3.Message6871 field6991 = 1; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message6870 field6992 = 90034652; + } +} + +message Message7651 { + optional string field7685 = 1; + optional int64 field7686 = 2; + optional int64 field7687 = 3; + optional int64 field7688 = 4; + optional int32 field7689 = 5; + optional int32 field7690 = 6; + optional int32 field7691 = 7; + optional int32 field7692 = 8; + optional int32 field7693 = 9; + optional int32 field7694 = 10; + optional int32 field7695 = 11; + optional int32 field7696 = 12; + optional int32 field7697 = 13; + optional int32 field7698 = 14; + optional int32 field7699 = 15; + optional int32 field7700 = 16; + optional int32 field7701 = 17; + optional int32 field7702 = 18; + optional bool field7703 = 19; + repeated int32 field7704 = 20; + repeated int32 field7705 = 21; + repeated string field7706 = 22; + repeated string field7707 = 23; + optional .benchmarks.google_message3.UnusedEmptyMessage field7708 = 24; + optional int32 field7709 = 25; + optional int32 field7710 = 26; + optional int32 field7711 = 27; + optional int32 field7712 = 43; + optional int32 field7713 = 28; + optional int32 field7714 = 29; + repeated .benchmarks.google_message3.Message7547 field7715 = 30; + repeated .benchmarks.google_message3.Message7547 field7716 = 31; + repeated .benchmarks.google_message3.UnusedEmptyMessage field7717 = 32; + repeated string field7718 = 33; + repeated string field7719 = 34; + repeated .benchmarks.google_message3.Message7648 field7720 = 35; + optional bool field7721 = 36; + optional bool field7722 = 37; + optional bool field7723 = 38; + optional bool field7724 = 39; + optional .benchmarks.google_message3.UnusedEmptyMessage field7725 = 40; + optional .benchmarks.google_message3.UnusedEnum field7726 = 41; + optional .benchmarks.google_message3.Enum7654 field7727 = 42; + optional string field7728 = 44; + optional .benchmarks.google_message3.UnusedEmptyMessage field7729 = 45; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message7651 field7730 = 55876009; + } +} + +message Message7864 { + optional string field7866 = 1; + optional string field7867 = 2; + repeated .benchmarks.google_message3.Message7865 field7868 = 5; + repeated .benchmarks.google_message3.Message7865 field7869 = 6; + repeated .benchmarks.google_message3.Message7865 field7870 = 7; + repeated .benchmarks.google_message3.UnusedEmptyMessage field7871 = 8; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message7864 field7872 = 44542730; + } +} + +message Message7929 { + optional int64 field7942 = 1; + optional int64 field7943 = 4; + optional int64 field7944 = 5; + optional int64 field7945 = 12; + optional int64 field7946 = 13; + optional int64 field7947 = 18; + optional int64 field7948 = 6; + optional int64 field7949 = 7; + repeated .benchmarks.google_message3.Message7919 field7950 = 8; + repeated .benchmarks.google_message3.UnusedEmptyMessage field7951 = 20; + repeated .benchmarks.google_message3.Message7920 field7952 = 14; + repeated .benchmarks.google_message3.Message7921 field7953 = 15; + repeated .benchmarks.google_message3.Message7928 field7954 = 17; + optional int64 field7955 = 19; + optional bool field7956 = 2; + optional int64 field7957 = 3; + optional int64 field7958 = 9; + repeated .benchmarks.google_message3.UnusedEmptyMessage field7959 = 10; + repeated bytes field7960 = 11; + optional int64 field7961 = 16; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message7929 field7962 = 53392238; + } +} + +message Message8508 { + repeated .benchmarks.google_message3.Message8511 field8517 = 8; + repeated .benchmarks.google_message3.Message8512 field8518 = 9; + repeated .benchmarks.google_message3.Message8513 field8519 = 11; + optional bool field8520 = 13; + optional .benchmarks.google_message3.Message8514 field8521 = 14; + repeated .benchmarks.google_message3.UnusedEmptyMessage field8522 = 15; + repeated .benchmarks.google_message3.Message8515 field8523 = 16; + repeated .benchmarks.google_message3.UnusedEmptyMessage field8524 = 17; + optional int64 field8525 = 1; + optional float field8526 = 2; + optional int64 field8527 = 3; + optional int64 field8528 = 4; + optional int32 field8529 = 5; + optional bytes field8530 = 6; + repeated bytes field8531 = 7; + optional bool field8532 = 10; + optional bytes field8533 = 12; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message8508 field8534 = 3811804; + } +} + +message Message9122 { + optional float field9132 = 1; + optional float field9133 = 2; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message9122 field9134 = 120398939; + } +} + +message Message10177 { + repeated .benchmarks.google_message3.Message10155 field10270 = 1; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message10177 field10271 = 26801105; + } +} + +message Message10278 { + repeated int32 field10286 = 1 [packed = true]; + repeated int32 field10287 = 2 [packed = true]; + optional int32 field10288 = 3; + extend .benchmarks.google_message3.Message10155 { + optional .benchmarks.google_message3.Message10278 field10289 = 29374161; + } +} + +message Message10323 { + repeated .benchmarks.google_message3.Message10320 field10360 = 1; + extend .benchmarks.google_message3.Message10155 { + optional .benchmarks.google_message3.Message10323 field10361 = 27922524; + } +} + +message Message10324 { + repeated .benchmarks.google_message3.Message10322 field10362 = 1; + optional .benchmarks.google_message3.Message10321 field10363 = 2; + extend .benchmarks.google_message3.Message10155 { + optional .benchmarks.google_message3.Message10324 field10364 = 27832297; + } +} + +message Message11990 { + repeated .benchmarks.google_message3.Message11988 field12030 = 1; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message11990 field12031 = 21265426; + } +} + +message Message12691 { + optional string field12713 = 1; + optional int32 field12714 = 2; + optional .benchmarks.google_message3.Message12668 field12715 = 3; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message12691 field12716 = 28426536; + } +} + +message Message12870 { + required int32 field12879 = 1; + optional int32 field12880 = 7; + required int32 field12881 = 2; + optional uint64 field12882 = 3; + optional string field12883 = 2001; + optional fixed64 field12884 = 4; + repeated fixed64 field12885 = 14; + optional int32 field12886 = 9; + optional int64 field12887 = 18; + repeated .benchmarks.google_message3.Message12870 field12888 = 8; + optional int32 field12889 = 5; + optional uint64 field12890 = 6; + optional int32 field12891 = 10; + optional int32 field12892 = 11; + optional double field12893 = 12; + optional .benchmarks.google_message3.Message12825 field12894 = 13; + optional double field12895 = 15; + optional string field12896 = 16; + optional .benchmarks.google_message3.Enum12871 field12897 = 17; + optional int32 field12898 = 19; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message12870 field12899 = 5447656; + } +} + +message Message13154 { + required float field13164 = 1; + required float field13165 = 2; + extend .benchmarks.google_message3.Message13145 { + optional .benchmarks.google_message3.Message13154 field13166 = 47301086; + } +} + +message Message16507 { + optional bool field16510 = 3; + optional bool field16511 = 4; + optional bool field16512 = 14; + repeated string field16513 = 5; + repeated string field16514 = 6; + optional string field16515 = 8; + repeated int32 field16516 = 9; + repeated int32 field16517 = 10; + optional int32 field16518 = 7; + optional string field16519 = 15; + repeated string field16520 = 11; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16521 = 27; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16522 = 22; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16523 = 28; + optional string field16524 = 18; + optional int32 field16525 = 19; + optional int32 field16526 = 20; + optional .benchmarks.google_message3.UnusedEmptyMessage field16527 = 23; + optional bool field16528 = 24; + repeated string field16529 = 25; + optional double field16530 = 26; + optional .benchmarks.google_message3.Message16478 field16531 = 30; + optional bool field16532 = 31; + optional string field16533 = 32; + optional bool field16534 = 33; + optional bool field16535 = 35; + optional bool field16536 = 36; + optional bool field16537 = 37; + optional bool field16538 = 38; + optional bool field16539 = 39; + optional bool field16540 = 40; + repeated string field16541 = 41; + extensions 21 to 21; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message16507 field16542 = 5569941; + } +} + +message Message16564 { + repeated .benchmarks.google_message3.Message16552 field16568 = 1; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message16564 field16569 = 25830030; + } +} + +message Message16661 { + repeated .benchmarks.google_message3.Message16660 field16671 = 1; + repeated uint64 field16672 = 2; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message16661 field16673 = 31274398; + } +} + +message Message16746 { + repeated .benchmarks.google_message3.Message16727 field16806 = 1; + optional bool field16807 = 2; + optional bool field16808 = 3; + repeated .benchmarks.google_message3.Message16725 field16809 = 4; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message16746 field16810 = 28406765; + } +} + +message Message17786 { + repeated group Message17787 = 1 { + required int32 field18177 = 2; + required int32 field18178 = 3; + optional .benchmarks.google_message3.Message17783 field18179 = 4; + optional .benchmarks.google_message3.UnusedEmptyMessage field18180 = 5; + optional .benchmarks.google_message3.UnusedEmptyMessage field18181 = 6; + repeated .benchmarks.google_message3.UnusedEmptyMessage field18182 = 8; + optional .benchmarks.google_message3.UnusedEmptyMessage field18183 = 9; + optional .benchmarks.google_message3.Message17726 field18184 = 10; + optional .benchmarks.google_message3.UnusedEmptyMessage field18185 = 11; + optional .benchmarks.google_message3.Message16945 field18186 = 102; + optional .benchmarks.google_message3.UnusedEmptyMessage field18187 = 12; + optional .benchmarks.google_message3.UnusedEmptyMessage field18188 = 13; + optional .benchmarks.google_message3.UnusedEmptyMessage field18189 = 7; + optional .benchmarks.google_message3.UnusedEmptyMessage field18190 = 100; + optional .benchmarks.google_message3.UnusedEmptyMessage field18191 = 101; + optional .benchmarks.google_message3.UnusedEmptyMessage field18192 = 14; + optional .benchmarks.google_message3.UnusedEmptyMessage field18193 = 19; + optional .benchmarks.google_message3.UnusedEmptyMessage field18194 = 22; + optional .benchmarks.google_message3.UnusedEmptyMessage field18195 = 24; + optional .benchmarks.google_message3.Enum16925 field18196 = 21; + optional bool field18197 = 18; + repeated .benchmarks.google_message3.UnusedEnum field18198 = 23; + optional .benchmarks.google_message3.UnusedEmptyMessage field18199 = 15; + optional string field18200 = 16; + optional string field18201 = 17; + optional bool field18202 = 99; + } + repeated .benchmarks.google_message3.Message17782 field18175 = 20; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message17786 field18176 = 11823055; + } +} + +message Message22857 { + repeated .benchmarks.google_message3.Message22853 field22874 = 1; + extend .benchmarks.google_message3.Message10155 { + optional .benchmarks.google_message3.Message22857 field22875 = 67799715; + } +} + +message Message24404 { + repeated group Message24405 = 1 { + required int32 field24686 = 2; + required int32 field24687 = 3; + optional .benchmarks.google_message3.Message24317 field24688 = 4; + optional .benchmarks.google_message3.UnusedEmptyMessage field24689 = 5; + optional .benchmarks.google_message3.Message24376 field24690 = 6; + optional .benchmarks.google_message3.Message24345 field24691 = 7; + optional .benchmarks.google_message3.UnusedEmptyMessage field24692 = 8; + optional .benchmarks.google_message3.Message24379 field24693 = 9; + optional .benchmarks.google_message3.UnusedEmptyMessage field24694 = 10; + optional .benchmarks.google_message3.UnusedEmptyMessage field24695 = 11; + optional .benchmarks.google_message3.Message24391 field24696 = 12; + optional .benchmarks.google_message3.UnusedEmptyMessage field24697 = 13; + optional .benchmarks.google_message3.UnusedEmptyMessage field24698 = 14; + optional .benchmarks.google_message3.UnusedEmptyMessage field24699 = 22; + optional .benchmarks.google_message3.UnusedEmptyMessage field24700 = 23; + optional .benchmarks.google_message3.UnusedEmptyMessage field24701 = 25; + optional .benchmarks.google_message3.Enum16925 field24702 = 18; + optional float field24703 = 20; + optional bool field24704 = 19; + repeated .benchmarks.google_message3.Enum16891 field24705 = 24; + optional .benchmarks.google_message3.UnusedEmptyMessage field24706 = 15; + optional string field24707 = 16; + optional string field24708 = 17; + optional float field24709 = 21; + optional bool field24710 = 26; + optional .benchmarks.google_message3.UnusedEnum field24711 = 27; + optional bool field24712 = 28; + optional .benchmarks.google_message3.UnusedEnum field24713 = 29; + optional bool field24714 = 31; + optional bool field24715 = 99; + optional int64 field24716 = 32; + } + optional .benchmarks.google_message3.Message24403 field24684 = 30; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message24404 field24685 = 9129287; + } +} + +message Message27300 { + repeated .benchmarks.google_message3.UnusedEmptyMessage field27302 = 1; + optional string field27303 = 2; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message27300 field27304 = 24956467; + } +} + +message Message27453 { + optional string field27459 = 15; + repeated string field27460 = 1; + repeated float field27461 = 6; + repeated int32 field27462 = 27; + repeated int32 field27463 = 28; + repeated .benchmarks.google_message3.Message27454 field27464 = 24; + repeated string field27465 = 2; + repeated float field27466 = 7; + repeated string field27467 = 22; + repeated string field27468 = 23; + optional string field27469 = 26; + repeated .benchmarks.google_message3.Message27357 field27470 = 8; + optional .benchmarks.google_message3.Message27360 field27471 = 16; + optional string field27472 = 25; + optional string field27473 = 11; + optional bool field27474 = 13; + optional bool field27475 = 14; + optional bool field27476 = 17; + optional .benchmarks.google_message3.UnusedEmptyMessage field27477 = 12; + optional bool field27478 = 34268945; + optional bool field27479 = 20; + optional string field27480 = 21; + optional .benchmarks.google_message3.UnusedEmptyMessage field27481 = 10; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message27453 field27482 = 8086204; + } +} + +extend .benchmarks.google_message3.Message16945 { + optional string field17026 = 472; + repeated string field17027 = 818; + optional .benchmarks.google_message3.Message0 field17031 = 215; + repeated .benchmarks.google_message3.Message0 field17032 = 292; + repeated .benchmarks.google_message3.Message0 field17038 = 234; + repeated .benchmarks.google_message3.Message0 field17039 = 235; + optional .benchmarks.google_message3.Message0 field17042 = 246; + optional string field17043 = 224; + optional string field17044 = 225; + repeated string field17048 = 63; + repeated string field17049 = 64; + repeated .benchmarks.google_message3.Message0 field17052 = 233; + repeated .benchmarks.google_message3.Message0 field17053 = 66; + repeated string field17056 = 275; + optional string field17057 = 226; + repeated .benchmarks.google_message3.Message0 field17060 = 27; + repeated string field17073 = 75; + repeated .benchmarks.google_message3.Message0 field17076 = 77; + repeated string field17078 = 296; + repeated .benchmarks.google_message3.Message0 field17082 = 160; + repeated .benchmarks.google_message3.Message0 field17091 = 585; + repeated .benchmarks.google_message3.Message0 field17098 = 987; + repeated .benchmarks.google_message3.Message0 field17101 = 157; + repeated string field17102 = 158; + repeated string field17107 = 166; + repeated string field17133 = 567; + repeated string field17134 = 572; + repeated string field17160 = 49; + repeated string field17168 = 32; + repeated string field17170 = 34; + repeated .benchmarks.google_message3.Message0 field17172 = 509; + repeated string field17174 = 39; + repeated .benchmarks.google_message3.Message0 field17175 = 40; + repeated .benchmarks.google_message3.Message0 field17178 = 511; + repeated .benchmarks.google_message3.Message0 field17185 = 50; + repeated int32 field17207 = 1081; + repeated .benchmarks.google_message3.Message0 field17238 = 184; + repeated .benchmarks.google_message3.Message0 field17289 = 177; + repeated .benchmarks.google_message3.Message0 field17290 = 178; + repeated .benchmarks.google_message3.Message0 field17296 = 474; + repeated string field17298 = 44; + repeated .benchmarks.google_message3.Message0 field17301 = 47; + optional .benchmarks.google_message3.Message0 field17412 = 21; + repeated .benchmarks.google_message3.Message0 field17438 = 132; + repeated .benchmarks.google_message3.Message0 field17458 = 512; + repeated string field17460 = 560; + repeated string field17466 = 552; + repeated .benchmarks.google_message3.Message0 field17617 = 1080; + repeated int32 field17618 = 1084; +} diff --git a/benchmarks/datasets/google_message3/benchmark_message3_1.proto b/benchmarks/datasets/google_message3/benchmark_message3_1.proto new file mode 100644 index 0000000000000..1ee5c9eca624e --- /dev/null +++ b/benchmarks/datasets/google_message3/benchmark_message3_1.proto @@ -0,0 +1,1298 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// LINT: ALLOW_GROUPS + +syntax = "proto2"; + +package benchmarks.google_message3; + +import "datasets/google_message3/benchmark_message3_2.proto"; +import "datasets/google_message3/benchmark_message3_3.proto"; +import "datasets/google_message3/benchmark_message3_5.proto"; +import "datasets/google_message3/benchmark_message3_7.proto"; +import "datasets/google_message3/benchmark_message3_8.proto"; + +option cc_enable_arenas = true; +option java_package = "com.google.protobuf.benchmarks"; + +message Message34390 { + repeated .benchmarks.google_message3.Message34387 field34452 = 1; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message34390 field34453 = 92144610; + } +} + +message Message34624 { + optional .benchmarks.google_message3.Message34621 field34683 = 1; + optional .benchmarks.google_message3.Message34621 field34684 = 2; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message34624 field34685 = 18178548; + } +} + +message Message34791 { + optional fixed64 field34793 = 1; + repeated group Message34792 = 2 { + required string field34808 = 3; + optional string field34809 = 4; + } + optional int32 field34795 = 5; + optional int32 field34796 = 6; + optional int32 field34797 = 7; + optional int32 field34798 = 8; + optional int32 field34799 = 9; + optional int32 field34800 = 10; + optional bool field34801 = 11; + optional float field34802 = 12; + optional int32 field34803 = 13; + optional string field34804 = 14; + optional int64 field34805 = 15; + repeated fixed64 field34806 = 17 [packed = true]; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message34791 field34807 = 6330340; + } +} + +message Message35483 { + optional int32 field35499 = 1; + optional string field35500 = 2; + optional string field35501 = 3; + optional string field35502 = 4; + repeated .benchmarks.google_message3.Message35476 field35503 = 5; + optional .benchmarks.google_message3.UnusedEmptyMessage field35504 = 6; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message35483 field35505 = 7913554; + } +} + +message Message35807 { + optional int32 field35810 = 1; + optional int32 field35811 = 2; + optional int32 field35812 = 3; + optional int32 field35813 = 4; + optional int32 field35814 = 5; + optional int32 field35815 = 6; + optional int32 field35816 = 7; + optional int32 field35817 = 8; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message35807 field35818 = 3803299; + } +} + +message Message37487 { + optional bytes field37501 = 2; + optional bool field37502 = 3; +} + +message Message13062 { + optional int64 field13075 = 1; + optional string field13076 = 2; + optional int32 field13077 = 3; + optional string field13078 = 4; + optional int32 field13079 = 5; +} + +message Message952 { + repeated .benchmarks.google_message3.Message949 field963 = 1; +} + +message Message36876 { + optional .benchmarks.google_message3.Message2356 field36980 = 1; + repeated group Message36877 = 111 { + required string field37044 = 112; + optional int32 field37045 = 113; + optional bytes field37046 = 114; + optional int32 field37047 = 115; + optional int32 field37048 = 157; + } + repeated group Message36878 = 168 {} + repeated group Message36879 = 55 { + required string field37050 = 56; + optional int32 field37051 = 69; + } + repeated .benchmarks.google_message3.UnusedEmptyMessage field36984 = 78; + optional group Message36880 = 137 {} + optional uint64 field36986 = 59; + optional bytes field36987 = 121; + optional .benchmarks.google_message3.UnusedEmptyMessage field36988 = 2; + optional .benchmarks.google_message3.Message7029 field36989 = 118; + optional .benchmarks.google_message3.Message35573 field36990 = 11; + optional .benchmarks.google_message3.UnusedEmptyMessage field36991 = 21; + optional .benchmarks.google_message3.UnusedEmptyMessage field36992 = 22; + optional float field36993 = 13; + optional int32 field36994 = 20; + optional bool field36995 = 51; + optional bool field36996 = 57; + repeated .benchmarks.google_message3.UnusedEmptyMessage field36997 = 100; + optional int32 field36998 = 47; + optional int32 field36999 = 48; + optional .benchmarks.google_message3.UnusedEmptyMessage field37000 = 68; + repeated group Message36881 = 23 {} + optional .benchmarks.google_message3.Message4144 field37002 = 125; + repeated group Message36882 = 35 {} + optional .benchmarks.google_message3.UnusedEmptyMessage field37004 = 49; + optional .benchmarks.google_message3.Message18921 field37005 = 52; + optional .benchmarks.google_message3.Message36858 field37006 = 46; + optional .benchmarks.google_message3.Message18831 field37007 = 54; + optional .benchmarks.google_message3.UnusedEmptyMessage field37008 = 58; + optional .benchmarks.google_message3.Message18283 field37009 = 10; + optional string field37010 = 44; + optional string field37011 = 103; + optional .benchmarks.google_message3.Message0 field37012 = 43; + optional .benchmarks.google_message3.Message0 field37013 = 143; + optional .benchmarks.google_message3.UnusedEmptyMessage field37014 = 53; + optional .benchmarks.google_message3.Message36869 field37015 = 15; + optional group Message36883 = 3 {} + repeated group Message36884 = 16 {} + repeated group Message36885 = 27 {} + optional group Message36886 = 32 {} + repeated .benchmarks.google_message3.UnusedEnum field37020 = 71; + repeated int32 field37021 = 70; + optional .benchmarks.google_message3.UnusedEmptyMessage field37022 = 66; + optional .benchmarks.google_message3.Message13090 field37023 = 67; + optional group Message36887 = 62 {} + repeated .benchmarks.google_message3.Message10155 field37025 = 50; + repeated .benchmarks.google_message3.Message11874 field37026 = 151; + optional string field37027 = 12; + optional int64 field37028 = 72; + optional .benchmarks.google_message3.UnusedEmptyMessage field37029 = 73; + optional .benchmarks.google_message3.Message35546 field37030 = 108; + optional group Message36888 = 74 { + optional uint64 field37089 = 75; + optional bool field37090 = 76; + optional uint64 field37091 = 165; + optional double field37092 = 166; + optional uint64 field37093 = 109; + optional bytes field37094 = 122; + } + repeated .benchmarks.google_message3.Message19255 field37032 = 104; + optional .benchmarks.google_message3.Message33968 field37033 = 105; + optional bool field37034 = 106; + repeated .benchmarks.google_message3.UnusedEmptyMessage field37035 = 107; + optional .benchmarks.google_message3.Message6644 field37036 = 110; + optional bytes field37037 = 133; + optional group Message36889 = 116 { + optional int64 field37095 = 117; + optional string field37096 = 145; + optional int32 field37097 = 123; + optional bool field37098 = 163; + optional int32 field37099 = 164; + optional int32 field37100 = 149; + optional .benchmarks.google_message3.UnusedEmptyMessage field37101 = 129; + optional .benchmarks.google_message3.Message13174 field37102 = 124; + optional .benchmarks.google_message3.Message13169 field37103 = 128; + optional uint64 field37104 = 132; + repeated .benchmarks.google_message3.Enum36890 field37105 = 131; + optional bool field37106 = 134; + optional bool field37107 = 140; + optional .benchmarks.google_message3.UnusedEmptyMessage field37108 = 135; + optional float field37109 = 136; + optional float field37110 = 156; + optional bool field37111 = 142; + optional int64 field37112 = 167; + optional .benchmarks.google_message3.UnusedEmptyMessage field37113 = 146; + optional bool field37114 = 148; + optional .benchmarks.google_message3.UnusedEmptyMessage field37115 = 154; + optional .benchmarks.google_message3.UnusedEnum field37116 = 158; + repeated .benchmarks.google_message3.UnusedEnum field37117 = 159; + optional int32 field37118 = 160; + repeated string field37119 = 161; + } + repeated group Message36910 = 119 {} + optional group Message36911 = 126 { + optional .benchmarks.google_message3.UnusedEmptyMessage field37121 = 127; + optional .benchmarks.google_message3.Message35538 field37122 = 130; + optional .benchmarks.google_message3.Message35540 field37123 = 144; + optional .benchmarks.google_message3.Message35542 field37124 = 150; + } + optional group Message36912 = 152 { + optional .benchmarks.google_message3.Message3901 field37125 = 153; + optional .benchmarks.google_message3.Message3901 field37126 = 162; + } + optional .benchmarks.google_message3.UnusedEmptyMessage field37042 = 155; +} + +message Message1328 {} + +message Message6850 {} + +message Message6863 { + optional .benchmarks.google_message3.Enum6858 field6931 = 1; + optional .benchmarks.google_message3.Enum6858 field6932 = 2; + optional .benchmarks.google_message3.UnusedEnum field6933 = 36; + optional bool field6934 = 27; + optional .benchmarks.google_message3.Message6773 field6935 = 26; + optional int32 field6936 = 30; + optional int32 field6937 = 37; + optional .benchmarks.google_message3.Enum6815 field6938 = 31; + optional string field6939 = 3; + optional int32 field6940 = 4; + optional .benchmarks.google_message3.Enum6822 field6941 = 15; + optional bool field6942 = 10; + optional bool field6943 = 17; + optional float field6944 = 18; + optional float field6945 = 19; + optional int32 field6946 = 5; + optional int32 field6947 = 6; + optional bool field6948 = 7; + optional int32 field6949 = 12; + optional .benchmarks.google_message3.UnusedEmptyMessage field6950 = 8; + optional uint64 field6951 = 9; + optional string field6952 = 11; + optional bytes field6953 = 13; + optional int32 field6954 = 14; + optional .benchmarks.google_message3.UnusedEmptyMessage field6955 = 16; + optional .benchmarks.google_message3.UnusedEmptyMessage field6956 = 22; + optional .benchmarks.google_message3.Message3886 field6957 = 38; + optional string field6958 = 20; + optional uint32 field6959 = 21; + optional .benchmarks.google_message3.Message6743 field6960 = 23; + optional .benchmarks.google_message3.UnusedEmptyMessage field6961 = 29; + optional .benchmarks.google_message3.UnusedEmptyMessage field6962 = 33; + optional bool field6963 = 34; +} + +message Message6871 {} + +message Message7547 { + required bytes field7549 = 1; + required int32 field7550 = 2; +} + +message Message7648 { + optional string field7669 = 1; + optional int32 field7670 = 2; + optional int32 field7671 = 3; + optional int32 field7672 = 4; + optional int32 field7673 = 5; + optional int32 field7674 = 6; + optional float field7675 = 7; + optional bool field7676 = 8; + optional bool field7677 = 9; + optional bool field7678 = 10; + optional bool field7679 = 11; + optional bool field7680 = 12; +} + +message Message7865 {} + +message Message7928 { + optional string field7940 = 1; + optional int64 field7941 = 2; +} + +message Message7919 { + optional fixed64 field7931 = 1; + optional int64 field7932 = 2; + optional bytes field7933 = 3; +} + +message Message7920 { + optional int64 field7934 = 1; + optional int64 field7935 = 2; +} + +message Message7921 { + optional int32 field7936 = 1; + optional int64 field7937 = 2; + optional float field7938 = 3; + optional .benchmarks.google_message3.UnusedEnum field7939 = 4; +} + +message Message8511 { + optional .benchmarks.google_message3.Message8224 field8539 = 1; + optional string field8540 = 2; + optional bool field8541 = 3; + optional int64 field8542 = 4; + optional string field8543 = 5; +} + +message Message8512 { + optional .benchmarks.google_message3.Message8301 field8544 = 1; + optional .benchmarks.google_message3.Message8302 field8545 = 2; + optional string field8546 = 3; + optional bool field8547 = 4; + optional int64 field8548 = 5; + optional string field8549 = 6; +} + +message Message8513 { + repeated .benchmarks.google_message3.Message8392 field8550 = 1; + optional string field8551 = 2; + optional bool field8552 = 3; + optional string field8553 = 4; +} + +message Message8514 { + optional string field8554 = 1; + optional int64 field8555 = 2; + optional bool field8556 = 3; + repeated .benchmarks.google_message3.Message8130 field8557 = 4; + optional string field8558 = 5; +} + +message Message8515 { + optional .benchmarks.google_message3.Message8479 field8559 = 1; + optional .benchmarks.google_message3.Message8478 field8560 = 2; + optional string field8561 = 3; +} + +message Message10320 { + optional .benchmarks.google_message3.Enum10335 field10347 = 1; + repeated .benchmarks.google_message3.Message10319 field10348 = 2; + optional int32 field10349 = 3; + optional int32 field10350 = 4; + optional int32 field10351 = 5; + optional int32 field10352 = 6; + optional .benchmarks.google_message3.Enum10337 field10353 = 7; +} + +message Message10321 { + optional int32 field10354 = 1; + optional int32 field10355 = 2; + optional uint64 field10356 = 3; +} + +message Message10322 { + optional .benchmarks.google_message3.Message4016 field10357 = 1; + optional bool field10358 = 2; + optional bool field10359 = 3; +} + +message Message11988 { + optional string field12021 = 1; + optional string field12022 = 2; + optional .benchmarks.google_message3.UnusedEmptyMessage field12023 = 3; + optional .benchmarks.google_message3.Message10155 field12024 = 4; +} + +message Message12668 { + repeated .benchmarks.google_message3.Message12669 field12677 = 1; + optional int32 field12678 = 2; + optional int32 field12679 = 3; + optional int32 field12680 = 4; +} + +message Message12825 { + repeated .benchmarks.google_message3.Message12818 field12862 = 1; + optional int32 field12863 = 2; + optional .benchmarks.google_message3.Message12819 field12864 = 3; + optional .benchmarks.google_message3.Message12820 field12865 = 4; + optional int32 field12866 = 5; + repeated .benchmarks.google_message3.Message12821 field12867 = 6; + repeated .benchmarks.google_message3.UnusedEmptyMessage field12868 = 7; +} + +message Message16478 { + repeated .benchmarks.google_message3.Message16479 field16481 = 1; + optional bool field16482 = 3; + optional int32 field16483 = 2; +} + +message Message16552 { + optional fixed64 field16565 = 1; + optional int32 field16566 = 2; + optional .benchmarks.google_message3.Enum16553 field16567 = 3; +} + +message Message16660 { + optional string field16668 = 1; + optional string field16669 = 2; + optional int32 field16670 = 3; +} + +message Message16727 { + required .benchmarks.google_message3.Enum16728 field16782 = 1; + required string field16783 = 2; + optional string field16784 = 3; + optional int32 field16785 = 23; + required string field16786 = 4; + optional string field16787 = 5; + optional string field16788 = 6; + required .benchmarks.google_message3.Enum16732 field16789 = 7; + optional string field16790 = 8; + optional string field16791 = 9; + optional string field16792 = 10; + optional .benchmarks.google_message3.Enum16738 field16793 = 11; + optional int32 field16794 = 12; + repeated .benchmarks.google_message3.Message16722 field16795 = 13; + optional bool field16796 = 19; + optional bool field16797 = 24; + optional string field16798 = 14; + optional int64 field16799 = 15; + optional bool field16800 = 16; + optional string field16801 = 17; + optional .benchmarks.google_message3.Enum16698 field16802 = 18; + optional .benchmarks.google_message3.Message16724 field16803 = 20; + optional bool field16804 = 22; + optional .benchmarks.google_message3.UnusedEmptyMessage field16805 = 25; + extensions 1000 to 536870911; +} + +message Message16725 { + optional .benchmarks.google_message3.Enum16728 field16774 = 1; + repeated string field16775 = 2; +} + +message Message17726 { + optional string field17801 = 1; + repeated string field17802 = 2; + optional string field17803 = 3; + repeated string field17804 = 4; + optional string field17805 = 5; + repeated string field17806 = 6; + optional string field17807 = 7; + optional string field17808 = 8; + repeated string field17809 = 15; + repeated string field17810 = 16; + repeated string field17811 = 17; + repeated .benchmarks.google_message3.UnusedEmptyMessage field17812 = 18; + optional string field17813 = 9; + optional string field17814 = 10; + optional string field17815 = 11; + optional string field17816 = 12; + optional string field17817 = 13; + optional string field17818 = 14; + optional string field17819 = 19; + repeated .benchmarks.google_message3.Message17728 field17820 = 20; + repeated .benchmarks.google_message3.Message17728 field17821 = 21; + repeated .benchmarks.google_message3.UnusedEmptyMessage field17822 = 30; +} + +message Message17782 { + optional string field18153 = 1; + optional string field18154 = 2; +} + +message Message17783 { + optional string field18155 = 1; + optional string field18156 = 2; + optional string field18157 = 3; + repeated group Message17784 = 4 { + optional string field18162 = 5; + optional string field18163 = 6; + optional string field18164 = 7; + repeated string field18165 = 8; + optional string field18166 = 17; + optional string field18167 = 18; + } + repeated group Message17785 = 9 { + optional string field18168 = 10; + optional string field18169 = 11; + optional .benchmarks.google_message3.Message17783 field18170 = 12; + optional string field18171 = 13; + optional string field18172 = 14; + repeated string field18173 = 15; + } + repeated string field18160 = 16; +} + +message Message16945 { + optional string field16946 = 1; + optional string field16947 = 2; + optional string field16948 = 3; + optional string field16949 = 4; + optional string field16950 = 5; + optional .benchmarks.google_message3.UnusedEmptyMessage field16951 = 872; + repeated .benchmarks.google_message3.Message0 field16952 = 16; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16953 = 54; + repeated .benchmarks.google_message3.Message0 field16954 = 55; + repeated string field16955 = 58; + repeated string field16956 = 59; + repeated string field16957 = 62; + repeated string field16958 = 37; + repeated string field16959 = 18; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16960 = 38; + repeated .benchmarks.google_message3.Message0 field16961 = 67; + repeated .benchmarks.google_message3.Message0 field16962 = 130; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16963 = 136; + repeated string field16964 = 138; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16965 = 156; + repeated string field16966 = 139; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16967 = 126; + repeated string field16968 = 152; + repeated .benchmarks.google_message3.Message0 field16969 = 183; + repeated string field16970 = 168; + repeated string field16971 = 212; + repeated string field16972 = 213; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16973 = 189; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16974 = 190; + repeated string field16975 = 191; + repeated string field16976 = 192; + repeated .benchmarks.google_message3.Message0 field16977 = 193; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16978 = 194; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16979 = 195; + repeated int32 field16980 = 196; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16981 = 95; + repeated string field16982 = 96; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16983 = 97; + repeated string field16984 = 1086; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16985 = 98; + repeated string field16986 = 99; + repeated string field16987 = 100; + repeated string field16988 = 48; + optional string field16989 = 22; + repeated .benchmarks.google_message3.UnusedEmptyMessage field16990 = 51; + repeated string field16991 = 81; + repeated string field16992 = 85; + repeated string field16993 = 169; + optional .benchmarks.google_message3.UnusedEmptyMessage field16994 = 260; + optional int32 field16995 = 198; + optional int32 field16996 = 204; + optional string field16997 = 1087; + repeated string field16998 = 197; + repeated string field16999 = 206; + optional string field17000 = 211; + repeated string field17001 = 205; + repeated .benchmarks.google_message3.UnusedEmptyMessage field17002 = 68; + repeated .benchmarks.google_message3.UnusedEmptyMessage field17003 = 69; + repeated .benchmarks.google_message3.UnusedEmptyMessage field17004 = 70; + repeated .benchmarks.google_message3.UnusedEmptyMessage field17005 = 71; + repeated .benchmarks.google_message3.UnusedEmptyMessage field17006 = 72; + repeated .benchmarks.google_message3.UnusedEmptyMessage field17007 = 19; + repeated .benchmarks.google_message3.UnusedEmptyMessage field17008 = 24; + optional .benchmarks.google_message3.UnusedEmptyMessage field17009 = 23; + repeated .benchmarks.google_message3.Message0 field17010 = 131; + repeated string field17011 = 133; + repeated .benchmarks.google_message3.UnusedEmptyMessage field17012 = 142; + repeated string field17013 = 143; + repeated .benchmarks.google_message3.UnusedEmptyMessage field17014 = 153; + repeated .benchmarks.google_message3.Message0 field17015 = 170; + repeated string field17016 = 171; + repeated string field17017 = 172; + repeated string field17018 = 173; + repeated string field17019 = 174; + repeated string field17020 = 175; + repeated string field17021 = 186; + repeated string field17022 = 101; + repeated .benchmarks.google_message3.Message0 field17023 = 102; + repeated string field17024 = 274; + extensions 17 to 17; + extensions 21 to 21; + extensions 25 to 25; + extensions 27 to 27; + extensions 29 to 29; + extensions 30 to 30; + extensions 31 to 31; + extensions 32 to 32; + extensions 33 to 33; + extensions 34 to 34; + extensions 35 to 35; + extensions 36 to 36; + extensions 39 to 39; + extensions 40 to 40; + extensions 41 to 41; + extensions 42 to 42; + extensions 43 to 43; + extensions 44 to 44; + extensions 45 to 45; + extensions 46 to 46; + extensions 47 to 47; + extensions 49 to 49; + extensions 50 to 50; + extensions 52 to 52; + extensions 53 to 53; + extensions 56 to 56; + extensions 57 to 57; + extensions 60 to 60; + extensions 61 to 61; + extensions 63 to 63; + extensions 64 to 64; + extensions 65 to 65; + extensions 66 to 66; + extensions 73 to 73; + extensions 74 to 74; + extensions 75 to 75; + extensions 76 to 76; + extensions 77 to 77; + extensions 78 to 78; + extensions 79 to 79; + extensions 80 to 80; + extensions 82 to 82; + extensions 83 to 83; + extensions 84 to 84; + extensions 86 to 86; + extensions 87 to 87; + extensions 88 to 88; + extensions 89 to 89; + extensions 90 to 90; + extensions 91 to 91; + extensions 92 to 92; + extensions 93 to 93; + extensions 94 to 94; + extensions 103 to 103; + extensions 104 to 104; + extensions 105 to 105; + extensions 106 to 106; + extensions 107 to 107; + extensions 108 to 108; + extensions 109 to 109; + extensions 110 to 110; + extensions 111 to 111; + extensions 112 to 112; + extensions 113 to 113; + extensions 114 to 114; + extensions 115 to 115; + extensions 116 to 116; + extensions 117 to 117; + extensions 118 to 118; + extensions 119 to 119; + extensions 120 to 120; + extensions 121 to 121; + extensions 122 to 122; + extensions 123 to 123; + extensions 124 to 124; + extensions 125 to 125; + extensions 127 to 127; + extensions 128 to 128; + extensions 129 to 129; + extensions 132 to 132; + extensions 134 to 134; + extensions 135 to 135; + extensions 137 to 137; + extensions 140 to 140; + extensions 141 to 141; + extensions 144 to 144; + extensions 145 to 145; + extensions 146 to 146; + extensions 147 to 147; + extensions 148 to 148; + extensions 149 to 149; + extensions 150 to 150; + extensions 151 to 151; + extensions 154 to 154; + extensions 155 to 155; + extensions 157 to 157; + extensions 158 to 158; + extensions 159 to 159; + extensions 160 to 160; + extensions 161 to 161; + extensions 162 to 162; + extensions 163 to 163; + extensions 164 to 164; + extensions 165 to 165; + extensions 166 to 166; + extensions 167 to 167; + extensions 176 to 176; + extensions 177 to 177; + extensions 178 to 178; + extensions 179 to 179; + extensions 180 to 180; + extensions 181 to 181; + extensions 182 to 182; + extensions 184 to 184; + extensions 185 to 185; + extensions 187 to 187; + extensions 188 to 188; + extensions 199 to 199; + extensions 200 to 200; + extensions 201 to 201; + extensions 202 to 202; + extensions 203 to 203; + extensions 207 to 207; + extensions 208 to 208; + extensions 209 to 209; + extensions 210 to 210; + extensions 214 to 214; + extensions 215 to 215; + extensions 216 to 216; + extensions 217 to 217; + extensions 218 to 218; + extensions 219 to 219; + extensions 220 to 220; + extensions 221 to 221; + extensions 222 to 222; + extensions 223 to 223; + extensions 224 to 224; + extensions 225 to 225; + extensions 226 to 226; + extensions 227 to 227; + extensions 228 to 228; + extensions 229 to 229; + extensions 230 to 230; + extensions 231 to 231; + extensions 232 to 232; + extensions 233 to 233; + extensions 234 to 234; + extensions 235 to 235; + extensions 236 to 236; + extensions 237 to 237; + extensions 238 to 238; + extensions 239 to 239; + extensions 240 to 240; + extensions 241 to 241; + extensions 242 to 242; + extensions 243 to 243; + extensions 244 to 244; + extensions 245 to 245; + extensions 246 to 246; + extensions 247 to 247; + extensions 248 to 248; + extensions 249 to 249; + extensions 250 to 250; + extensions 251 to 251; + extensions 252 to 252; + extensions 253 to 253; + extensions 254 to 254; + extensions 255 to 255; + extensions 256 to 256; + extensions 257 to 257; + extensions 258 to 258; + extensions 259 to 259; + extensions 261 to 261; + extensions 262 to 262; + extensions 263 to 263; + extensions 264 to 264; + extensions 265 to 265; + extensions 266 to 266; + extensions 267 to 267; + extensions 268 to 268; + extensions 269 to 269; + extensions 270 to 270; + extensions 271 to 271; + extensions 272 to 272; + extensions 273 to 273; + extensions 275 to 275; + extensions 276 to 276; + extensions 277 to 277; + extensions 278 to 278; + extensions 279 to 279; + extensions 280 to 280; + extensions 281 to 281; + extensions 282 to 282; + extensions 283 to 283; + extensions 284 to 284; + extensions 285 to 285; + extensions 286 to 286; + extensions 290 to 290; + extensions 291 to 291; + extensions 292 to 292; + extensions 293 to 293; + extensions 294 to 294; + extensions 295 to 295; + extensions 296 to 296; + extensions 297 to 297; + extensions 298 to 298; + extensions 299 to 299; + extensions 300 to 300; + extensions 301 to 301; + extensions 302 to 302; + extensions 303 to 303; + extensions 304 to 304; + extensions 305 to 305; + extensions 306 to 306; + extensions 307 to 307; + extensions 308 to 308; + extensions 309 to 309; + extensions 310 to 310; + extensions 311 to 311; + extensions 312 to 312; + extensions 313 to 313; + extensions 314 to 314; + extensions 315 to 315; + extensions 316 to 316; + extensions 317 to 317; + extensions 318 to 318; + extensions 319 to 319; + extensions 320 to 320; + extensions 321 to 321; + extensions 322 to 322; + extensions 323 to 323; + extensions 324 to 324; + extensions 325 to 325; + extensions 326 to 326; + extensions 327 to 327; + extensions 328 to 328; + extensions 329 to 329; + extensions 330 to 330; + extensions 331 to 331; + extensions 332 to 332; + extensions 333 to 333; + extensions 334 to 334; + extensions 335 to 335; + extensions 336 to 336; + extensions 337 to 337; + extensions 338 to 338; + extensions 339 to 339; + extensions 340 to 340; + extensions 341 to 341; + extensions 342 to 342; + extensions 343 to 343; + extensions 344 to 344; + extensions 345 to 345; + extensions 346 to 346; + extensions 347 to 347; + extensions 348 to 348; + extensions 349 to 349; + extensions 350 to 350; + extensions 351 to 351; + extensions 352 to 352; + extensions 353 to 353; + extensions 354 to 354; + extensions 355 to 355; + extensions 356 to 356; + extensions 357 to 357; + extensions 358 to 358; + extensions 359 to 359; + extensions 360 to 360; + extensions 361 to 361; + extensions 362 to 362; + extensions 363 to 363; + extensions 364 to 364; + extensions 365 to 365; + extensions 366 to 366; + extensions 367 to 367; + extensions 368 to 368; + extensions 369 to 369; + extensions 370 to 370; + extensions 371 to 371; + extensions 372 to 372; + extensions 373 to 373; + extensions 374 to 374; + extensions 375 to 375; + extensions 376 to 376; + extensions 377 to 377; + extensions 378 to 378; + extensions 379 to 379; + extensions 380 to 380; + extensions 381 to 381; + extensions 382 to 382; + extensions 383 to 383; + extensions 384 to 384; + extensions 385 to 385; + extensions 386 to 386; + extensions 387 to 387; + extensions 388 to 388; + extensions 389 to 389; + extensions 390 to 390; + extensions 391 to 391; + extensions 392 to 392; + extensions 393 to 393; + extensions 394 to 394; + extensions 395 to 395; + extensions 396 to 396; + extensions 397 to 397; + extensions 398 to 398; + extensions 399 to 399; + extensions 400 to 400; + extensions 401 to 401; + extensions 402 to 402; + extensions 403 to 403; + extensions 404 to 404; + extensions 405 to 405; + extensions 406 to 406; + extensions 407 to 407; + extensions 408 to 408; + extensions 409 to 409; + extensions 410 to 410; + extensions 411 to 411; + extensions 412 to 412; + extensions 413 to 413; + extensions 414 to 414; + extensions 415 to 415; + extensions 416 to 416; + extensions 417 to 417; + extensions 418 to 418; + extensions 419 to 419; + extensions 420 to 420; + extensions 421 to 421; + extensions 422 to 422; + extensions 423 to 423; + extensions 424 to 424; + extensions 425 to 425; + extensions 426 to 426; + extensions 427 to 427; + extensions 428 to 428; + extensions 429 to 429; + extensions 430 to 430; + extensions 431 to 431; + extensions 432 to 432; + extensions 433 to 433; + extensions 434 to 434; + extensions 435 to 435; + extensions 436 to 436; + extensions 437 to 437; + extensions 438 to 438; + extensions 439 to 439; + extensions 440 to 440; + extensions 441 to 441; + extensions 442 to 442; + extensions 443 to 443; + extensions 444 to 444; + extensions 445 to 445; + extensions 446 to 446; + extensions 447 to 447; + extensions 448 to 448; + extensions 449 to 449; + extensions 450 to 450; + extensions 451 to 451; + extensions 452 to 452; + extensions 453 to 453; + extensions 454 to 454; + extensions 455 to 455; + extensions 456 to 456; + extensions 457 to 457; + extensions 458 to 458; + extensions 459 to 459; + extensions 460 to 460; + extensions 461 to 461; + extensions 462 to 462; + extensions 463 to 463; + extensions 464 to 464; + extensions 465 to 465; + extensions 466 to 466; + extensions 467 to 467; + extensions 468 to 468; + extensions 469 to 469; + extensions 470 to 470; + extensions 471 to 471; + extensions 472 to 472; + extensions 473 to 473; + extensions 474 to 474; + extensions 509 to 509; + extensions 511 to 511; + extensions 512 to 512; + extensions 513 to 513; + extensions 514 to 514; + extensions 515 to 515; + extensions 516 to 516; + extensions 517 to 517; + extensions 518 to 518; + extensions 519 to 519; + extensions 520 to 520; + extensions 521 to 521; + extensions 522 to 522; + extensions 523 to 523; + extensions 524 to 524; + extensions 525 to 525; + extensions 526 to 526; + extensions 527 to 527; + extensions 528 to 528; + extensions 529 to 529; + extensions 530 to 530; + extensions 531 to 531; + extensions 532 to 532; + extensions 533 to 533; + extensions 534 to 534; + extensions 535 to 535; + extensions 536 to 536; + extensions 537 to 537; + extensions 538 to 538; + extensions 539 to 539; + extensions 540 to 540; + extensions 541 to 541; + extensions 542 to 542; + extensions 543 to 543; + extensions 544 to 544; + extensions 545 to 545; + extensions 546 to 546; + extensions 547 to 547; + extensions 548 to 548; + extensions 549 to 549; + extensions 550 to 550; + extensions 551 to 551; + extensions 552 to 552; + extensions 553 to 553; + extensions 554 to 554; + extensions 555 to 555; + extensions 556 to 556; + extensions 557 to 557; + extensions 558 to 558; + extensions 559 to 559; + extensions 560 to 560; + extensions 561 to 561; + extensions 562 to 562; + extensions 563 to 563; + extensions 564 to 564; + extensions 565 to 565; + extensions 566 to 566; + extensions 567 to 567; + extensions 568 to 568; + extensions 569 to 569; + extensions 570 to 570; + extensions 571 to 571; + extensions 572 to 572; + extensions 573 to 573; + extensions 574 to 574; + extensions 575 to 575; + extensions 576 to 576; + extensions 577 to 577; + extensions 578 to 578; + extensions 579 to 579; + extensions 580 to 580; + extensions 581 to 581; + extensions 582 to 582; + extensions 583 to 583; + extensions 584 to 584; + extensions 585 to 585; + extensions 586 to 586; + extensions 587 to 587; + extensions 588 to 588; + extensions 589 to 589; + extensions 590 to 590; + extensions 604 to 604; + extensions 605 to 605; + extensions 606 to 606; + extensions 607 to 607; + extensions 608 to 608; + extensions 609 to 609; + extensions 610 to 610; + extensions 611 to 611; + extensions 612 to 612; + extensions 613 to 613; + extensions 614 to 614; + extensions 615 to 615; + extensions 616 to 616; + extensions 617 to 617; + extensions 618 to 618; + extensions 619 to 619; + extensions 620 to 620; + extensions 621 to 621; + extensions 622 to 622; + extensions 623 to 623; + extensions 624 to 624; + extensions 625 to 625; + extensions 626 to 626; + extensions 627 to 627; + extensions 628 to 628; + extensions 629 to 629; + extensions 813 to 813; + extensions 814 to 814; + extensions 815 to 815; + extensions 816 to 816; + extensions 817 to 817; + extensions 818 to 818; + extensions 819 to 819; + extensions 820 to 820; + extensions 821 to 821; + extensions 822 to 822; + extensions 823 to 823; + extensions 824 to 824; + extensions 827 to 827; + extensions 828 to 828; + extensions 829 to 829; + extensions 830 to 830; + extensions 831 to 831; + extensions 832 to 832; + extensions 833 to 833; + extensions 834 to 834; + extensions 835 to 835; + extensions 836 to 836; + extensions 837 to 837; + extensions 838 to 838; + extensions 839 to 839; + extensions 840 to 840; + extensions 841 to 841; + extensions 842 to 842; + extensions 843 to 843; + extensions 844 to 844; + extensions 845 to 845; + extensions 846 to 846; + extensions 847 to 847; + extensions 848 to 848; + extensions 849 to 849; + extensions 850 to 850; + extensions 851 to 851; + extensions 852 to 852; + extensions 853 to 853; + extensions 854 to 854; + extensions 855 to 855; + extensions 856 to 856; + extensions 857 to 857; + extensions 858 to 858; + extensions 859 to 859; + extensions 860 to 860; + extensions 861 to 861; + extensions 862 to 862; + extensions 863 to 863; + extensions 864 to 864; + extensions 865 to 865; + extensions 866 to 866; + extensions 867 to 867; + extensions 868 to 868; + extensions 869 to 869; + extensions 870 to 870; + extensions 871 to 871; + extensions 880 to 880; + extensions 881 to 881; + extensions 882 to 882; + extensions 883 to 883; + extensions 884 to 884; + extensions 885 to 885; + extensions 886 to 886; + extensions 887 to 887; + extensions 888 to 888; + extensions 890 to 890; + extensions 891 to 891; + extensions 892 to 892; + extensions 912 to 912; + extensions 914 to 914; + extensions 915 to 915; + extensions 916 to 916; + extensions 917 to 917; + extensions 918 to 918; + extensions 919 to 919; + extensions 920 to 920; + extensions 921 to 921; + extensions 922 to 922; + extensions 923 to 923; + extensions 924 to 924; + extensions 925 to 925; + extensions 926 to 926; + extensions 927 to 927; + extensions 928 to 928; + extensions 929 to 929; + extensions 930 to 930; + extensions 931 to 931; + extensions 932 to 932; + extensions 933 to 933; + extensions 934 to 934; + extensions 935 to 935; + extensions 936 to 936; + extensions 937 to 937; + extensions 938 to 938; + extensions 939 to 939; + extensions 940 to 940; + extensions 941 to 941; + extensions 942 to 942; + extensions 943 to 943; + extensions 944 to 944; + extensions 945 to 945; + extensions 946 to 946; + extensions 947 to 947; + extensions 949 to 949; + extensions 950 to 950; + extensions 951 to 951; + extensions 952 to 952; + extensions 954 to 954; + extensions 955 to 955; + extensions 956 to 956; + extensions 957 to 957; + extensions 958 to 958; + extensions 959 to 959; + extensions 960 to 960; + extensions 961 to 961; + extensions 962 to 962; + extensions 963 to 963; + extensions 964 to 964; + extensions 965 to 965; + extensions 966 to 966; + extensions 967 to 967; + extensions 968 to 968; + extensions 969 to 969; + extensions 970 to 970; + extensions 971 to 971; + extensions 972 to 972; + extensions 973 to 973; + extensions 974 to 974; + extensions 975 to 975; + extensions 976 to 976; + extensions 977 to 977; + extensions 978 to 978; + extensions 979 to 979; + extensions 980 to 980; + extensions 981 to 981; + extensions 982 to 982; + extensions 983 to 983; + extensions 984 to 984; + extensions 985 to 985; + extensions 987 to 987; + extensions 988 to 988; + extensions 1000 to 1000; + extensions 1001 to 1001; + extensions 1002 to 1002; + extensions 1003 to 1003; + extensions 1004 to 1004; + extensions 1005 to 1005; + extensions 1006 to 1006; + extensions 1007 to 1007; + extensions 1008 to 1008; + extensions 1009 to 1009; + extensions 1010 to 1010; + extensions 1011 to 1011; + extensions 1012 to 1012; + extensions 1013 to 1013; + extensions 1014 to 1014; + extensions 1015 to 1015; + extensions 1016 to 1016; + extensions 1017 to 1017; + extensions 1018 to 1018; + extensions 1019 to 1019; + extensions 1020 to 1020; + extensions 1021 to 1021; + extensions 1022 to 1022; + extensions 1023 to 1023; + extensions 1024 to 1024; + extensions 1025 to 1025; + extensions 1026 to 1026; + extensions 1027 to 1027; + extensions 1028 to 1028; + extensions 1029 to 1029; + extensions 1030 to 1030; + extensions 1031 to 1031; + extensions 1032 to 1032; + extensions 1033 to 1033; + extensions 1034 to 1034; + extensions 1035 to 1035; + extensions 1036 to 1036; + extensions 1037 to 1037; + extensions 1038 to 1038; + extensions 1039 to 1039; + extensions 1040 to 1040; + extensions 1041 to 1041; + extensions 1042 to 1042; + extensions 1043 to 1043; + extensions 1044 to 1044; + extensions 1045 to 1045; + extensions 1046 to 1046; + extensions 1047 to 1047; + extensions 1048 to 1048; + extensions 1049 to 1049; + extensions 1050 to 1050; + extensions 1051 to 1051; + extensions 1052 to 1052; + extensions 1053 to 1053; + extensions 1054 to 1054; + extensions 1055 to 1055; + extensions 1056 to 1056; + extensions 1057 to 1057; + extensions 1058 to 1058; + extensions 1079 to 1079; + extensions 1080 to 1080; + extensions 1081 to 1081; + extensions 1082 to 1082; + extensions 1083 to 1083; + extensions 1084 to 1084; + extensions 1085 to 1085; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message16945 field17025 = 22068132; + } +} diff --git a/benchmarks/datasets/google_message3/benchmark_message3_2.proto b/benchmarks/datasets/google_message3/benchmark_message3_2.proto new file mode 100644 index 0000000000000..d123a7204caaf --- /dev/null +++ b/benchmarks/datasets/google_message3/benchmark_message3_2.proto @@ -0,0 +1,528 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// LINT: ALLOW_GROUPS + +syntax = "proto2"; + +package benchmarks.google_message3; + +import "datasets/google_message3/benchmark_message3_3.proto"; +import "datasets/google_message3/benchmark_message3_4.proto"; +import "datasets/google_message3/benchmark_message3_5.proto"; +import "datasets/google_message3/benchmark_message3_7.proto"; +import "datasets/google_message3/benchmark_message3_8.proto"; + +option cc_enable_arenas = true; +option java_package = "com.google.protobuf.benchmarks"; + +message Message22853 { + optional .benchmarks.google_message3.Enum22854 field22869 = 1; + repeated uint32 field22870 = 2 [packed = true]; + repeated float field22871 = 3 [packed = true]; + repeated float field22872 = 5 [packed = true]; + optional .benchmarks.google_message3.UnusedEmptyMessage field22873 = 4; +} + +message Message24345 { + optional string field24533 = 1; + optional .benchmarks.google_message3.UnusedEnum field24534 = 22; + optional .benchmarks.google_message3.Message24346 field24535 = 2; + optional string field24536 = 3; + optional string field24537 = 4; + optional .benchmarks.google_message3.UnusedEnum field24538 = 23; + optional string field24539 = 5; + required string field24540 = 6; + optional string field24541 = 7; + optional string field24542 = 8; + optional .benchmarks.google_message3.Message24316 field24543 = 9; + optional .benchmarks.google_message3.Message24376 field24544 = 10; + optional string field24545 = 11; + optional string field24546 = 19; + optional string field24547 = 20; + optional string field24548 = 21; + optional .benchmarks.google_message3.UnusedEmptyMessage field24549 = 12; + optional .benchmarks.google_message3.UnusedEmptyMessage field24550 = 13; + repeated string field24551 = 14; + optional string field24552 = 15; + optional int32 field24553 = 18; + optional .benchmarks.google_message3.Message24379 field24554 = 16; + optional string field24555 = 17; + repeated .benchmarks.google_message3.Message24356 field24556 = 24; + repeated .benchmarks.google_message3.Message24366 field24557 = 25; +} + +message Message24403 { + optional .benchmarks.google_message3.Message24401 field24681 = 1; + optional .benchmarks.google_message3.Message24402 field24682 = 2; +} + +message Message24391 { + optional string field24631 = 1; + optional string field24632 = 2; + repeated string field24633 = 3; + optional string field24634 = 4; + repeated string field24635 = 5; + repeated string field24636 = 16; + optional string field24637 = 17; + optional .benchmarks.google_message3.UnusedEmptyMessage field24638 = 25; + optional string field24639 = 7; + optional string field24640 = 18; + optional string field24641 = 19; + optional string field24642 = 20; + optional int32 field24643 = 24; + optional .benchmarks.google_message3.Message24379 field24644 = 8; + repeated .benchmarks.google_message3.UnusedEmptyMessage field24645 = 9; + optional .benchmarks.google_message3.UnusedEmptyMessage field24646 = 10; + optional .benchmarks.google_message3.UnusedEmptyMessage field24647 = 11; + optional .benchmarks.google_message3.UnusedEmptyMessage field24648 = 12; + repeated .benchmarks.google_message3.UnusedEmptyMessage field24649 = 13; + optional .benchmarks.google_message3.UnusedEmptyMessage field24650 = 14; + optional string field24651 = 21; + optional int32 field24652 = 22; + optional int32 field24653 = 23; + repeated string field24654 = 15; + repeated string field24655 = 6; +} + +message Message27454 {} + +message Message27357 { + optional string field27410 = 1; + optional float field27411 = 2; + optional string field27412 = 3; + optional bool field27413 = 4; + optional bool field27414 = 5; +} + +message Message27360 { + optional .benchmarks.google_message3.Message27358 field27426 = 1; + optional .benchmarks.google_message3.Enum27361 field27427 = 2; + optional .benchmarks.google_message3.Message27358 field27428 = 3; + repeated .benchmarks.google_message3.UnusedEmptyMessage field27429 = 4; +} + +message Message34387 { + optional string field34446 = 1; + repeated .benchmarks.google_message3.Message34381 field34447 = 2; + optional .benchmarks.google_message3.UnusedEnum field34448 = 3; + optional .benchmarks.google_message3.Enum34388 field34449 = 4; + optional int64 field34450 = 5; +} + +message Message34621 { + optional double field34651 = 1; + optional double field34652 = 2; + optional double field34653 = 3; + optional double field34654 = 4; + optional double field34655 = 11; + optional .benchmarks.google_message3.UnusedEmptyMessage field34656 = 13; + optional .benchmarks.google_message3.Message34619 field34657 = 14; + optional string field34658 = 5; + optional string field34659 = 9; + optional double field34660 = 12; + optional bytes field34661 = 19; + optional string field34662 = 15; + optional string field34663 = 16; + optional string field34664 = 17; + optional .benchmarks.google_message3.UnusedEmptyMessage field34665 = 18; + optional .benchmarks.google_message3.Message34621 field34666 = 20; + repeated .benchmarks.google_message3.UnusedEmptyMessage field34667 = 100; + optional .benchmarks.google_message3.UnusedEmptyMessage field34668 = 101; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message34621 field34669 = 17562023; + } +} + +message Message35476 { + optional string field35484 = 1; + optional string field35485 = 2; + optional string field35486 = 3; + optional .benchmarks.google_message3.Enum35477 field35487 = 4; + optional float field35488 = 5; + optional float field35489 = 6; + optional float field35490 = 7; + optional float field35491 = 8; + optional .benchmarks.google_message3.UnusedEmptyMessage field35492 = 9; + optional int32 field35493 = 10; + optional int32 field35494 = 11; + optional int32 field35495 = 12; + optional string field35496 = 13; + optional string field35497 = 14; +} + +message Message949 { + optional string field955 = 1; + optional int64 field956 = 2; + optional int64 field957 = 3; + optional .benchmarks.google_message3.Message730 field958 = 4; + repeated string field959 = 5; + optional string field960 = 6; + optional bool field961 = 7; +} + +message Message36869 { + optional int32 field36970 = 1; + optional int32 field36971 = 2; +} + +message Message33968 { + repeated group Message33969 = 1 {} + repeated .benchmarks.google_message3.Message33958 field33989 = 3; + optional .benchmarks.google_message3.UnusedEmptyMessage field33990 = 106; + optional bool field33991 = 108; + optional .benchmarks.google_message3.UnusedEnum field33992 = 107; +} + +message Message6644 { + optional .benchmarks.google_message3.UnusedEmptyMessage field6701 = 8; + optional string field6702 = 1; + optional double field6703 = 2; + optional .benchmarks.google_message3.UnusedEmptyMessage field6704 = 9; + optional bytes field6705 = 3; + optional bytes field6706 = 19; + optional .benchmarks.google_message3.Message6637 field6707 = 4; + repeated .benchmarks.google_message3.Message6126 field6708 = 18; + optional bool field6709 = 6; + optional .benchmarks.google_message3.Message6643 field6710 = 10; + optional string field6711 = 12; + optional .benchmarks.google_message3.UnusedEmptyMessage field6712 = 14; + optional .benchmarks.google_message3.UnusedEmptyMessage field6713 = 15; + optional .benchmarks.google_message3.UnusedEmptyMessage field6714 = 16; + optional int32 field6715 = 17; + optional .benchmarks.google_message3.UnusedEmptyMessage field6716 = 20; +} + +message Message18831 { + repeated group Message18832 = 1 { + optional int32 field18836 = 2; + optional string field18837 = 5; + optional float field18838 = 3; + optional float field18839 = 9; + optional int32 field18840 = 11; + repeated uint64 field18841 = 4; + repeated group Message18833 = 6 { + required uint64 field18843 = 7; + optional string field18844 = 8; + optional float field18845 = 10; + optional int32 field18846 = 12; + optional bool field18847 = 13; + } + } +} + +message Message13090 { + optional .benchmarks.google_message3.Message13083 field13141 = 1; + optional .benchmarks.google_message3.Message13088 field13142 = 2; +} + +message Message11874 { + optional .benchmarks.google_message3.Message10391 field11888 = 3; + optional string field11889 = 4; + optional .benchmarks.google_message3.Message11873 field11890 = 6; + optional bool field11891 = 7; + extensions 1 to 1; + extensions 2 to 2; + extensions 5 to 5; +} + +message Message4144 { + repeated group Message4145 = 1 { + required .benchmarks.google_message3.Enum4146 field4165 = 2; + required int32 field4166 = 3; + optional .benchmarks.google_message3.Enum4160 field4167 = 9; + optional bytes field4168 = 4; + optional .benchmarks.google_message3.Enum4152 field4169 = 5; + optional string field4170 = 6; + } +} + +message Message35573 { + optional fixed64 field35695 = 16; + optional string field35696 = 1000; + optional string field35697 = 1004; + optional int32 field35698 = 1003; + repeated group Message35574 = 1012 {} + optional int64 field35700 = 1011; + optional int64 field35701 = 1005; + optional int64 field35702 = 1006; + optional int64 field35703 = 1007; + optional int64 field35704 = 1008; + repeated group Message35575 = 1 { + optional int64 field35709 = 2; + optional string field35710 = 3; + optional string field35711 = 19; + optional int32 field35712 = 20; + optional int32 field35713 = 21; + optional int32 field35714 = 22; + optional bool field35715 = 23; + optional int32 field35716 = 47; + optional int32 field35717 = 48; + optional bool field35718 = 24; + optional fixed64 field35719 = 25; + optional bytes field35720 = 52; + optional int32 field35721 = 18; + optional fixed32 field35722 = 43; + optional bool field35723 = 26; + optional int32 field35724 = 27; + optional int32 field35725 = 17; + optional bool field35726 = 45; + repeated int32 field35727 = 33; + repeated int32 field35728 = 58; + optional float field35729 = 34; + optional float field35730 = 1009; + optional int32 field35731 = 28; + repeated fixed64 field35732 = 1001; + repeated fixed64 field35733 = 1002; + optional int32 field35734 = 44; + optional int32 field35735 = 50; + optional int32 field35736 = 36; + optional int32 field35737 = 40; + optional bool field35738 = 1016; + optional bool field35739 = 1010; + optional int32 field35740 = 37; + optional int32 field35741 = 38; + optional string field35742 = 46; + optional uint32 field35743 = 60; + repeated bytes field35744 = 56; + optional .benchmarks.google_message3.Message0 field35745 = 57; + required group Message35576 = 4 { + optional fixed64 field35747 = 5; + optional int32 field35748 = 6; + optional int32 field35749 = 49; + optional int32 field35750 = 7; + optional uint32 field35751 = 59; + optional int32 field35752 = 14; + optional int32 field35753 = 15; + optional int32 field35754 = 35; + optional bytes field35755 = 53; + optional int32 field35756 = 8; + optional string field35757 = 9; + optional fixed64 field35758 = 10; + optional int32 field35759 = 11; + optional int32 field35760 = 12; + optional int32 field35761 = 41; + optional int32 field35762 = 30; + optional int32 field35763 = 31; + optional int32 field35764 = 13; + optional bytes field35765 = 39; + optional string field35766 = 29; + optional int32 field35767 = 42; + repeated int32 field35768 = 32; + repeated int32 field35769 = 51; + optional int64 field35770 = 54; + optional .benchmarks.google_message3.Message0 field35771 = 55; + } + } +} + +message Message36858 { + repeated int32 field36956 = 1; + repeated string field36957 = 2; + repeated string field36958 = 12; + optional int32 field36959 = 3; + optional int32 field36960 = 4; + optional int32 field36961 = 14; + optional string field36962 = 11; + optional bool field36963 = 5; + optional bool field36964 = 13; + optional int64 field36965 = 6; + optional .benchmarks.google_message3.Message35506 field36966 = 7; + repeated group Message36859 = 8 { + required .benchmarks.google_message3.Enum36860 field36968 = 9; + optional float field36969 = 10; + } +} + +message Message13174 { + required int32 field13237 = 6; + optional int32 field13238 = 3; + required int32 field13239 = 4; + optional int32 field13240 = 8; + optional double field13241 = 5; + optional double field13242 = 7; + optional int32 field13243 = 17; + optional int32 field13244 = 19; + optional double field13245 = 20; + optional int32 field13246 = 9; + optional double field13247 = 10; + optional int32 field13248 = 11; + optional .benchmarks.google_message3.Message13151 field13249 = 21; + optional int32 field13250 = 1; + optional double field13251 = 2; + optional double field13252 = 15; + optional double field13253 = 16; + optional double field13254 = 12; + optional double field13255 = 13; + optional double field13256 = 14; + optional int32 field13257 = 18; +} + +message Message18283 { + optional .benchmarks.google_message3.UnusedEmptyMessage field18478 = 1; + optional int32 field18479 = 4; + optional int32 field18480 = 106; + optional int32 field18481 = 107; + optional int32 field18482 = 108; + optional int32 field18483 = 109; + optional int32 field18484 = 105; + optional int32 field18485 = 113; + optional int32 field18486 = 114; + optional int32 field18487 = 124; + optional int32 field18488 = 125; + optional int32 field18489 = 128; + optional int32 field18490 = 135; + optional bool field18491 = 166; + optional bool field18492 = 136; + optional int32 field18493 = 140; + optional int32 field18494 = 171; + optional int32 field18495 = 148; + optional int32 field18496 = 145; + optional float field18497 = 117; + optional int32 field18498 = 146; + optional string field18499 = 3; + optional .benchmarks.google_message3.UnusedEmptyMessage field18500 = 5; + optional .benchmarks.google_message3.UnusedEmptyMessage field18501 = 6; + optional .benchmarks.google_message3.UnusedEmptyMessage field18502 = 9; + optional .benchmarks.google_message3.Message18253 field18503 = 155; + optional .benchmarks.google_message3.UnusedEmptyMessage field18504 = 184; + optional .benchmarks.google_message3.UnusedEmptyMessage field18505 = 163; + optional .benchmarks.google_message3.UnusedEmptyMessage field18506 = 16; + repeated int32 field18507 = 20; + repeated int32 field18508 = 7; + repeated string field18509 = 194; + optional bytes field18510 = 30; + optional int32 field18511 = 31; + optional .benchmarks.google_message3.UnusedEmptyMessage field18512 = 178; + optional string field18513 = 8; + optional float field18514 = 2; + optional float field18515 = 100; + optional float field18516 = 101; + optional float field18517 = 102; + optional int32 field18518 = 103; + repeated .benchmarks.google_message3.UnusedEmptyMessage field18519 = 104; + optional int32 field18520 = 110; + optional int32 field18521 = 112; + optional .benchmarks.google_message3.UnusedEmptyMessage field18522 = 111; + optional .benchmarks.google_message3.UnusedEmptyMessage field18523 = 115; + optional .benchmarks.google_message3.UnusedEmptyMessage field18524 = 119; + optional .benchmarks.google_message3.UnusedEmptyMessage field18525 = 127; + optional .benchmarks.google_message3.UnusedEmptyMessage field18526 = 185; + optional int32 field18527 = 120; + optional int32 field18528 = 132; + optional .benchmarks.google_message3.UnusedEmptyMessage field18529 = 126; + optional .benchmarks.google_message3.UnusedEmptyMessage field18530 = 129; + optional .benchmarks.google_message3.UnusedEmptyMessage field18531 = 131; + optional fixed64 field18532 = 150; + optional int32 field18533 = 133; + optional int32 field18534 = 134; + optional int32 field18535 = 139; + optional fixed64 field18536 = 137; + optional fixed64 field18537 = 138; + optional .benchmarks.google_message3.UnusedEmptyMessage field18538 = 141; + optional int32 field18539 = 142; + optional int32 field18540 = 181; + optional .benchmarks.google_message3.Message16816 field18541 = 143; + optional .benchmarks.google_message3.Message16685 field18542 = 154; + optional int32 field18543 = 144; + optional int64 field18544 = 147; + optional int64 field18545 = 149; + optional int32 field18546 = 151; + optional int32 field18547 = 152; + optional int32 field18548 = 153; + optional float field18549 = 161; + optional .benchmarks.google_message3.Message0 field18550 = 123; + repeated int64 field18551 = 156; + optional int32 field18552 = 157; + repeated fixed64 field18553 = 188; + optional int32 field18554 = 158; + optional .benchmarks.google_message3.UnusedEmptyMessage field18555 = 159; + optional bool field18556 = 160; + optional uint64 field18557 = 162; + optional int32 field18558 = 164; + optional .benchmarks.google_message3.UnusedEmptyMessage field18559 = 10; + optional .benchmarks.google_message3.UnusedEmptyMessage field18560 = 167; + optional int32 field18561 = 168; + repeated fixed64 field18562 = 169; + repeated string field18563 = 170; + optional .benchmarks.google_message3.UnusedEmptyMessage field18564 = 172; + optional int64 field18565 = 173; + optional .benchmarks.google_message3.UnusedEmptyMessage field18566 = 174; + optional int64 field18567 = 175; + optional uint32 field18568 = 189; + optional .benchmarks.google_message3.UnusedEmptyMessage field18569 = 176; + optional .benchmarks.google_message3.UnusedEmptyMessage field18570 = 177; + optional uint32 field18571 = 179; + optional uint32 field18572 = 180; + optional .benchmarks.google_message3.UnusedEmptyMessage field18573 = 182; + optional .benchmarks.google_message3.UnusedEmptyMessage field18574 = 183; + optional .benchmarks.google_message3.UnusedEmptyMessage field18575 = 121; + optional .benchmarks.google_message3.UnusedEmptyMessage field18576 = 186; + optional .benchmarks.google_message3.UnusedEmptyMessage field18577 = 187; + optional .benchmarks.google_message3.UnusedEmptyMessage field18578 = 190; + optional int32 field18579 = 191; + optional float field18580 = 192; + optional bool field18581 = 193; + extensions 116 to 116; + extensions 118 to 118; + extensions 130 to 130; + extensions 165 to 165; +} + +message Message13169 { + repeated .benchmarks.google_message3.Message13168 field13223 = 1; + required .benchmarks.google_message3.Message13167 field13224 = 2; + optional string field13225 = 3; +} + +message Message19255 { + optional string field19257 = 1; +} + +message Message35542 { + optional bool field35543 = 1; + optional bool field35544 = 2; + optional bool field35545 = 3; +} + +message Message3901 { + optional int32 field3990 = 1; + optional int32 field3991 = 2; + optional int32 field3992 = 3; + optional int32 field3993 = 4; + optional int32 field3994 = 7; + optional int32 field3995 = 8; + optional int32 field3996 = 9; + optional int32 field3997 = 10; + optional int32 field3998 = 11; + optional int32 field3999 = 12; + optional .benchmarks.google_message3.UnusedEnum field4000 = 6; + optional int32 field4001 = 5; +} diff --git a/benchmarks/datasets/google_message3/benchmark_message3_3.proto b/benchmarks/datasets/google_message3/benchmark_message3_3.proto new file mode 100644 index 0000000000000..2e534a67d6c50 --- /dev/null +++ b/benchmarks/datasets/google_message3/benchmark_message3_3.proto @@ -0,0 +1,496 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// LINT: ALLOW_GROUPS + +syntax = "proto2"; + +package benchmarks.google_message3; + +import "datasets/google_message3/benchmark_message3_4.proto"; +import "datasets/google_message3/benchmark_message3_5.proto"; +import "datasets/google_message3/benchmark_message3_7.proto"; +import "datasets/google_message3/benchmark_message3_8.proto"; + +option cc_enable_arenas = true; +option java_package = "com.google.protobuf.benchmarks"; + +message Message35546 { + optional int64 field35556 = 1; + optional int32 field35557 = 2; + optional bool field35558 = 3; + optional int64 field35559 = 13; + optional group Message35547 = 4 { + required int32 field35569 = 5; + required int32 field35570 = 6; + } + optional group Message35548 = 10 { + required int64 field35571 = 11; + required int64 field35572 = 12; + } + optional bool field35562 = 14; + optional bool field35563 = 15; + optional int32 field35564 = 16; + optional bool field35565 = 17; + optional bool field35566 = 18; + optional string field35567 = 100; +} + +message Message2356 { + optional .benchmarks.google_message3.Message1374 field2368 = 121; + optional uint64 field2369 = 1; + optional int32 field2370 = 2; + optional int32 field2371 = 17; + required string field2372 = 3; + optional int32 field2373 = 7; + optional bytes field2374 = 8; + optional string field2375 = 4; + optional string field2376 = 101; + optional int32 field2377 = 102; + optional int32 field2378 = 103; + optional int32 field2379 = 104; + optional int32 field2380 = 113; + optional int32 field2381 = 114; + optional int32 field2382 = 115; + optional int32 field2383 = 117; + optional int32 field2384 = 118; + optional int32 field2385 = 119; + optional int32 field2386 = 105; + optional bytes field2387 = 5; + optional group Message2357 = 6 { + optional int64 field2399 = 9; + optional int32 field2400 = 10; + optional int32 field2401 = 11; + optional int32 field2402 = 12; + optional int32 field2403 = 13; + optional int32 field2404 = 116; + optional int32 field2405 = 106; + required bytes field2406 = 14; + optional int32 field2407 = 45; + optional int32 field2408 = 112; + optional bool field2409 = 122; + optional bytes field2410 = 124; + } + optional string field2389 = 120; + optional group Message2358 = 107 {} + repeated group Message2359 = 40 { + optional string field2413 = 41; + optional string field2414 = 42; + optional string field2415 = 43; + optional string field2416 = 44; + optional int32 field2417 = 46; + optional string field2418 = 47; + optional float field2419 = 110; + optional float field2420 = 111; + } + optional int32 field2392 = 50; + optional .benchmarks.google_message3.UnusedEmptyMessage field2393 = 60; + optional .benchmarks.google_message3.UnusedEmptyMessage field2394 = 70; + optional .benchmarks.google_message3.UnusedEmptyMessage field2395 = 80; + optional .benchmarks.google_message3.UnusedEmptyMessage field2396 = 90; + optional string field2397 = 100; + optional string field2398 = 123; +} + +message Message7029 { + required int32 field7183 = 1; + optional int32 field7184 = 2; + optional int32 field7185 = 3; + optional int32 field7186 = 4; + optional int32 field7187 = 5; + optional int32 field7188 = 6; + optional int32 field7189 = 17; + optional int32 field7190 = 18; + optional int32 field7191 = 49; + optional int32 field7192 = 28; + optional int32 field7193 = 33; + optional int32 field7194 = 25; + optional int32 field7195 = 26; + optional int32 field7196 = 40; + optional int32 field7197 = 41; + optional int32 field7198 = 42; + optional int32 field7199 = 43; + optional int32 field7200 = 19; + optional int32 field7201 = 7; + optional int32 field7202 = 8; + optional int32 field7203 = 9; + optional int32 field7204 = 10; + optional int32 field7205 = 11; + optional int32 field7206 = 12; + repeated group Message7030 = 13 { + optional string field7226 = 14; + optional string field7227 = 15; + optional int64 field7228 = 16; + } + repeated group Message7031 = 21 { + optional string field7229 = 22; + optional int32 field7230 = 23; + optional int32 field7231 = 24; + optional int32 field7232 = 30; + optional int32 field7233 = 31; + optional int32 field7234 = 35; + } + optional int32 field7209 = 20; + optional float field7210 = 27; + optional int32 field7211 = 29; + optional int32 field7212 = 32; + optional string field7213 = 48; + optional bool field7214 = 34; + optional int32 field7215 = 36; + optional float field7216 = 37; + optional bool field7217 = 38; + optional bool field7218 = 39; + optional .benchmarks.google_message3.UnusedEmptyMessage field7219 = 44; + optional int32 field7220 = 45; + optional int32 field7221 = 46; + optional int32 field7222 = 47; + optional .benchmarks.google_message3.UnusedEmptyMessage field7223 = 50; + optional int32 field7224 = 51; +} + +message Message35538 { + required int64 field35539 = 1; +} + +message Message18921 { + optional string field18946 = 1; + optional fixed64 field18947 = 2; + optional int32 field18948 = 3; + optional double field18949 = 4; + optional bool field18950 = 17; + optional bool field18951 = 23; + optional .benchmarks.google_message3.UnusedEmptyMessage field18952 = 24; + repeated group Message18922 = 5 { + optional uint64 field18959 = 6; + optional string field18960 = 13; + optional bool field18961 = 21; + optional bool field18962 = 33; + optional int32 field18963 = 7; + optional int32 field18964 = 8; + optional string field18965 = 9; + optional .benchmarks.google_message3.Message18856 field18966 = 10; + optional uint64 field18967 = 34; + optional .benchmarks.google_message3.UnusedEmptyMessage field18968 = 11; + optional uint64 field18969 = 35; + optional float field18970 = 12; + repeated string field18971 = 14; + optional bool field18972 = 15; + optional bool field18973 = 16; + optional float field18974 = 22; + optional int32 field18975 = 18; + optional int32 field18976 = 19; + optional int32 field18977 = 20; + optional .benchmarks.google_message3.UnusedEmptyMessage field18978 = 25; + optional .benchmarks.google_message3.UnusedEnum field18979 = 26; + repeated string field18980 = 27; + optional float field18981 = 28; + } + repeated .benchmarks.google_message3.UnusedEmptyMessage field18954 = 29; + repeated .benchmarks.google_message3.Message18943 field18955 = 30; + repeated .benchmarks.google_message3.Message18944 field18956 = 31; + repeated .benchmarks.google_message3.UnusedEmptyMessage field18957 = 32; +} + +message Message35540 { + optional bool field35541 = 1; +} + +message Message3886 { + repeated group Message3887 = 1 { + required string field3932 = 2; + optional string field3933 = 9; + optional .benchmarks.google_message3.Message3850 field3934 = 3; + optional bytes field3935 = 8; + } +} + +message Message6743 { + optional .benchmarks.google_message3.Message6721 field6759 = 1; + optional .benchmarks.google_message3.Message6723 field6760 = 2; + optional .benchmarks.google_message3.Message6723 field6761 = 8; + optional .benchmarks.google_message3.Message6725 field6762 = 3; + optional .benchmarks.google_message3.Message6726 field6763 = 4; + optional .benchmarks.google_message3.Message6733 field6764 = 5; + optional .benchmarks.google_message3.Message6734 field6765 = 6; + optional .benchmarks.google_message3.Message6742 field6766 = 7; +} + +message Message6773 { + optional .benchmarks.google_message3.Enum6769 field6794 = 1; + optional int32 field6795 = 9; + optional .benchmarks.google_message3.UnusedEnum field6796 = 10; + optional int32 field6797 = 11; + optional int32 field6798 = 2; + optional .benchmarks.google_message3.Enum6774 field6799 = 3; + optional double field6800 = 5; + optional double field6801 = 7; + optional double field6802 = 8; + optional .benchmarks.google_message3.Enum6782 field6803 = 6; +} + +message Message8224 { + optional .benchmarks.google_message3.UnusedEmptyMessage field8255 = 1; + optional .benchmarks.google_message3.Message8184 field8256 = 2; + optional .benchmarks.google_message3.Message7966 field8257 = 3; + optional string field8258 = 4; + optional string field8259 = 5; + optional bool field8260 = 6; + optional int64 field8261 = 7; + optional string field8262 = 8; + optional int64 field8263 = 9; + optional double field8264 = 10; + optional int64 field8265 = 11; + repeated string field8266 = 12; + optional int64 field8267 = 13; + optional int32 field8268 = 14; + optional int32 field8269 = 15; + optional int64 field8270 = 16; + optional double field8271 = 17; + optional .benchmarks.google_message3.UnusedEmptyMessage field8272 = 18; + optional .benchmarks.google_message3.UnusedEmptyMessage field8273 = 19; + repeated .benchmarks.google_message3.UnusedEmptyMessage field8274 = 20; + optional bool field8275 = 21; + optional .benchmarks.google_message3.UnusedEmptyMessage field8276 = 22; + optional .benchmarks.google_message3.UnusedEmptyMessage field8277 = 23; + repeated .benchmarks.google_message3.UnusedEmptyMessage field8278 = 24; + optional .benchmarks.google_message3.UnusedEmptyMessage field8279 = 25; + optional bool field8280 = 26; + repeated .benchmarks.google_message3.UnusedEmptyMessage field8281 = 27; +} + +message Message8392 { + optional string field8395 = 1; + optional string field8396 = 2; + optional .benchmarks.google_message3.Message7966 field8397 = 3; + optional string field8398 = 4; + optional string field8399 = 5; + optional string field8400 = 6; + optional string field8401 = 7; + optional string field8402 = 8; + optional string field8403 = 9; +} + +message Message8130 { + optional string field8156 = 1; + optional string field8157 = 2; + optional string field8158 = 4; + optional .benchmarks.google_message3.UnusedEmptyMessage field8159 = 6; + repeated string field8160 = 7; + optional int64 field8161 = 8; + optional .benchmarks.google_message3.UnusedEmptyMessage field8162 = 9; + optional string field8163 = 10; + optional string field8164 = 11; + optional string field8165 = 12; + optional string field8166 = 13; + optional .benchmarks.google_message3.UnusedEmptyMessage field8167 = 14; + optional .benchmarks.google_message3.UnusedEmptyMessage field8168 = 15; + optional string field8169 = 16; + optional .benchmarks.google_message3.UnusedEnum field8170 = 17; + optional .benchmarks.google_message3.UnusedEnum field8171 = 18; + optional bool field8172 = 19; + optional bool field8173 = 20; + optional double field8174 = 21; + optional int32 field8175 = 22; + optional int32 field8176 = 23; + optional .benchmarks.google_message3.UnusedEmptyMessage field8177 = 24; + repeated .benchmarks.google_message3.UnusedEmptyMessage field8178 = 25; + repeated .benchmarks.google_message3.UnusedEmptyMessage field8179 = 26; +} + +message Message8478 { + optional string field8489 = 7; + optional .benchmarks.google_message3.Message7966 field8490 = 1; + optional .benchmarks.google_message3.Message8476 field8491 = 2; + optional int64 field8492 = 3; + optional .benchmarks.google_message3.Message8476 field8493 = 4; + repeated .benchmarks.google_message3.Message8477 field8494 = 5; + optional .benchmarks.google_message3.Message8454 field8495 = 6; + optional .benchmarks.google_message3.UnusedEmptyMessage field8496 = 8; +} + +message Message8479 { + optional .benchmarks.google_message3.Message8475 field8497 = 1; + optional .benchmarks.google_message3.Message7966 field8498 = 2; + optional .benchmarks.google_message3.Message8476 field8499 = 3; + optional .benchmarks.google_message3.Message8476 field8500 = 4; + optional string field8501 = 6; + optional string field8502 = 7; + optional .benchmarks.google_message3.Message7966 field8503 = 8; + optional .benchmarks.google_message3.Message8455 field8504 = 5; + optional .benchmarks.google_message3.UnusedEmptyMessage field8505 = 9; +} + +message Message10319 { + optional .benchmarks.google_message3.Enum10325 field10340 = 1; + optional int32 field10341 = 4; + optional int32 field10342 = 5; + optional bytes field10343 = 3; + optional string field10344 = 2; + optional string field10345 = 6; + optional string field10346 = 7; +} + +message Message4016 { + required int32 field4017 = 1; + required int32 field4018 = 2; + required int32 field4019 = 3; + required int32 field4020 = 4; +} + +message Message12669 { + optional .benchmarks.google_message3.Message12559 field12681 = 1; + optional float field12682 = 2; + optional bool field12683 = 3; + optional .benchmarks.google_message3.Enum12670 field12684 = 4; +} + +message Message12819 { + optional double field12834 = 1; + optional double field12835 = 2; + optional double field12836 = 3; + optional double field12837 = 4; + optional double field12838 = 5; + optional double field12839 = 6; +} + +message Message12820 { + optional int32 field12840 = 1; + optional int32 field12841 = 2; + optional int32 field12842 = 3; + optional int32 field12843 = 8; + optional int32 field12844 = 4; + optional int32 field12845 = 5; + optional int32 field12846 = 6; + optional int32 field12847 = 7; +} + +message Message12821 { + optional int32 field12848 = 1; + optional int32 field12849 = 2; + optional int32 field12850 = 3; + optional int32 field12851 = 4; + optional int32 field12852 = 5; +} + +message Message12818 { + optional uint64 field12829 = 1; + optional int32 field12830 = 2; + optional int32 field12831 = 3; + optional int32 field12832 = 5; + repeated .benchmarks.google_message3.Message12817 field12833 = 4; +} + +message Message16479 { + optional .benchmarks.google_message3.Message16480 field16484 = 1; + optional int32 field16485 = 5; + optional float field16486 = 2; + optional uint32 field16487 = 4; + optional bool field16488 = 3; + optional uint32 field16489 = 6; +} + +message Message16722 { + optional string field16752 = 1; + optional string field16753 = 2; + optional string field16754 = 3; + optional int32 field16755 = 5; + optional string field16756 = 4; +} + +message Message16724 { + optional int64 field16761 = 1; + optional float field16762 = 2; + optional int64 field16763 = 3; + optional int64 field16764 = 4; + optional bool field16765 = 5; + repeated string field16766 = 6; + repeated string field16767 = 7; + optional .benchmarks.google_message3.UnusedEmptyMessage field16768 = 8; + optional bool field16769 = 9; + optional uint32 field16770 = 10; + optional .benchmarks.google_message3.Enum16728 field16771 = 11; + repeated int32 field16772 = 12; + optional bool field16773 = 13; +} + +message Message17728 {} + +message Message24356 { + optional string field24559 = 1; + optional string field24560 = 2; + optional int32 field24561 = 14; + optional string field24562 = 3; + optional string field24563 = 4; + optional string field24564 = 5; + optional .benchmarks.google_message3.UnusedEnum field24565 = 13; + optional string field24566 = 6; + optional .benchmarks.google_message3.Enum24361 field24567 = 12; + optional string field24568 = 7; + optional string field24569 = 8; + optional string field24570 = 9; + repeated .benchmarks.google_message3.UnusedEmptyMessage field24571 = 10; + repeated string field24572 = 11; + repeated string field24573 = 15; +} + +message Message24376 { + optional string field24589 = 1; + optional string field24590 = 2; + optional string field24591 = 3; + required .benchmarks.google_message3.Message24377 field24592 = 4; + optional .benchmarks.google_message3.Message24317 field24593 = 5; + optional string field24594 = 6; + optional .benchmarks.google_message3.Message24378 field24595 = 7; + repeated string field24596 = 8; + repeated .benchmarks.google_message3.UnusedEmptyMessage field24597 = 14; + repeated string field24598 = 9; + repeated string field24599 = 10; + repeated string field24600 = 11; + optional string field24601 = 12; + repeated string field24602 = 13; +} + +message Message24366 { + optional string field24574 = 1; + optional string field24575 = 2; + optional string field24576 = 3; + optional int32 field24577 = 10; + optional string field24578 = 13; + optional string field24579 = 4; + optional string field24580 = 5; + optional .benchmarks.google_message3.UnusedEnum field24581 = 9; + optional string field24582 = 14; + optional .benchmarks.google_message3.UnusedEnum field24583 = 15; + optional string field24584 = 6; + optional string field24585 = 12; + repeated .benchmarks.google_message3.UnusedEmptyMessage field24586 = 7; + repeated string field24587 = 8; + repeated string field24588 = 11; +} diff --git a/benchmarks/datasets/google_message3/benchmark_message3_4.proto b/benchmarks/datasets/google_message3/benchmark_message3_4.proto new file mode 100644 index 0000000000000..b304148198151 --- /dev/null +++ b/benchmarks/datasets/google_message3/benchmark_message3_4.proto @@ -0,0 +1,514 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// LINT: ALLOW_GROUPS + +syntax = "proto2"; + +package benchmarks.google_message3; + +import "datasets/google_message3/benchmark_message3_5.proto"; +import "datasets/google_message3/benchmark_message3_6.proto"; +import "datasets/google_message3/benchmark_message3_7.proto"; +import "datasets/google_message3/benchmark_message3_8.proto"; + +option cc_enable_arenas = true; +option java_package = "com.google.protobuf.benchmarks"; + +message Message24346 {} + +message Message24401 { + optional .benchmarks.google_message3.Message24400 field24679 = 1; +} + +message Message24402 { + optional .benchmarks.google_message3.Message24400 field24680 = 1; +} + +message Message24379 { + optional string field24603 = 1; + optional string field24604 = 2; + optional string field24605 = 3; + required .benchmarks.google_message3.Message24380 field24606 = 4; + optional .benchmarks.google_message3.UnusedEmptyMessage field24607 = 5; + optional string field24608 = 6; + optional .benchmarks.google_message3.Message24381 field24609 = 7; + repeated string field24610 = 8; + repeated .benchmarks.google_message3.UnusedEmptyMessage field24611 = 17; + repeated string field24612 = 9; + repeated string field24613 = 10; + repeated string field24614 = 11; + optional string field24615 = 14; + optional string field24616 = 12; + optional string field24617 = 16; + repeated .benchmarks.google_message3.UnusedEmptyMessage field24618 = 13; + repeated string field24619 = 15; + repeated string field24620 = 18; +} + +message Message27358 { + optional int32 field27415 = 1; + optional int32 field27416 = 2; +} + +message Message34381 { + optional string field34398 = 1; + optional .benchmarks.google_message3.UnusedEmptyMessage field34399 = 2; + optional .benchmarks.google_message3.UnusedEmptyMessage field34400 = 3; + optional .benchmarks.google_message3.UnusedEmptyMessage field34401 = 4; + optional .benchmarks.google_message3.UnusedEmptyMessage field34402 = 5; + optional bool field34403 = 6; + optional bool field34404 = 7; + optional .benchmarks.google_message3.UnusedEmptyMessage field34405 = 8; + optional bool field34406 = 9; + optional .benchmarks.google_message3.UnusedEmptyMessage field34407 = 10; +} + +message Message34619 { + optional double field34641 = 1; + optional double field34642 = 2; + optional double field34643 = 3; + optional double field34644 = 4; + optional double field34645 = 11; + optional double field34646 = 5; + optional .benchmarks.google_message3.UnusedEmptyMessage field34647 = 100; +} + +message Message730 { + optional string field897 = 19; + repeated string field898 = 27; + repeated string field899 = 28; + repeated string field900 = 21; + optional string field901 = 30; + repeated uint32 field902 = 20; + repeated uint32 field903 = 32; + repeated string field904 = 16; + repeated .benchmarks.google_message3.Message697 field905 = 6; + repeated .benchmarks.google_message3.Message704 field906 = 7; + repeated string field907 = 18; + repeated .benchmarks.google_message3.Message703 field908 = 8; + repeated string field909 = 9; + optional .benchmarks.google_message3.Message716 field910 = 10; + optional .benchmarks.google_message3.Message718 field911 = 11; + optional bool field912 = 14; + repeated .benchmarks.google_message3.Message715 field913 = 4; + repeated string field914 = 17; + repeated string field915 = 23; + repeated .benchmarks.google_message3.Message719 field916 = 24; + repeated .benchmarks.google_message3.Message728 field917 = 26; + repeated .benchmarks.google_message3.Message702 field918 = 35; + optional string field919 = 36; + repeated string field920 = 37; + optional int64 field921 = 38; + repeated .benchmarks.google_message3.UnusedEmptyMessage field922 = 39; + repeated .benchmarks.google_message3.UnusedEmptyMessage field923 = 1; + optional .benchmarks.google_message3.UnusedEmptyMessage field924 = 2; + optional .benchmarks.google_message3.UnusedEmptyMessage field925 = 3; + optional .benchmarks.google_message3.UnusedEmptyMessage field926 = 5; + optional .benchmarks.google_message3.UnusedEmptyMessage field927 = 13; + repeated string field928 = 22; + optional bytes field929 = 31; + extensions 25 to 25; + extensions 29 to 29; + extensions 34 to 34; + extensions 15 to 15; +} + +message Message33958 { + optional string field33977 = 1; + optional string field33978 = 9; + repeated group Message33959 = 2 { + required string field33982 = 3; + optional string field33983 = 4; + optional string field33984 = 5; + optional fixed64 field33985 = 8; + optional bool field33986 = 10; + optional .benchmarks.google_message3.Message0 field33987 = 6; + } + optional .benchmarks.google_message3.Enum33960 field33980 = 7; + extend .benchmarks.google_message3.Message0 { + optional .benchmarks.google_message3.Message33958 field33981 = 10747482; + } +} + +message Message6637 { + optional .benchmarks.google_message3.UnusedEmptyMessage field6670 = 2; + repeated .benchmarks.google_message3.UnusedEmptyMessage field6671 = 1; + optional int32 field6672 = 3; + repeated string field6673 = 4; + optional .benchmarks.google_message3.UnusedEmptyMessage field6674 = 5; +} + +message Message6643 { + optional .benchmarks.google_message3.UnusedEmptyMessage field6683 = 3; + optional .benchmarks.google_message3.UnusedEmptyMessage field6684 = 4; + optional double field6685 = 5; + optional double field6686 = 6; + optional int32 field6687 = 1; + optional int32 field6688 = 2; + optional double field6689 = 9; + optional bytes field6690 = 10; + optional int32 field6691 = 11; + optional bool field6692 = 12; + optional bool field6693 = 13; + optional .benchmarks.google_message3.Message6578 field6694 = 15; + optional .benchmarks.google_message3.UnusedEnum field6695 = 16; + optional int64 field6696 = 17; + repeated .benchmarks.google_message3.UnusedEmptyMessage field6697 = 22; + optional .benchmarks.google_message3.UnusedEmptyMessage field6698 = 19; + optional .benchmarks.google_message3.UnusedEmptyMessage field6699 = 20; + optional int32 field6700 = 21; +} + +message Message6126 { + required string field6152 = 1; + repeated .benchmarks.google_message3.UnusedEmptyMessage field6153 = 9; + optional int32 field6154 = 14; + optional bytes field6155 = 10; + optional .benchmarks.google_message3.Message6024 field6156 = 12; + optional int32 field6157 = 4; + optional string field6158 = 5; + optional int32 field6159 = 6; + repeated int32 field6160 = 2; + repeated int32 field6161 = 3; + repeated .benchmarks.google_message3.Message6052 field6162 = 7; + repeated .benchmarks.google_message3.UnusedEmptyMessage field6163 = 11; + optional .benchmarks.google_message3.Enum6065 field6164 = 15; + repeated .benchmarks.google_message3.UnusedEmptyMessage field6165 = 8; + optional bool field6166 = 13; + optional bool field6167 = 16; + optional bool field6168 = 18; + repeated .benchmarks.google_message3.Message6054 field6169 = 17; + optional int32 field6170 = 19; +} + +message Message13083 { + optional float field13096 = 1; + repeated group Message13084 = 2 { + required float field13107 = 3; + required int32 field13108 = 4; + optional float field13109 = 5; + repeated .benchmarks.google_message3.Enum13092 field13110 = 6; + } + optional float field13098 = 44; + optional float field13099 = 45; + optional uint64 field13100 = 46; + optional float field13101 = 47; + optional group Message13085 = 16 {} + repeated group Message13086 = 23 {} + repeated group Message13087 = 29 {} + optional .benchmarks.google_message3.UnusedEmptyMessage field13105 = 43; +} + +message Message13088 { + repeated group Message13089 = 1 { + required string field13139 = 2; + optional float field13140 = 3; + } + optional int64 field13136 = 4; + optional bool field13137 = 5; +} + +message Message10391 { + optional .benchmarks.google_message3.Enum10392 field10411 = 1; + optional .benchmarks.google_message3.UnusedEnum field10412 = 2; + optional int64 field10413 = 3; + optional string field10414 = 4; + optional string field10415 = 5; + optional bytes field10416 = 6; + optional bool field10417 = 8; + optional .benchmarks.google_message3.UnusedEmptyMessage field10418 = 9; + optional bool field10419 = 10; +} + +message Message11873 { + optional string field11876 = 1; + optional string field11877 = 4; + optional .benchmarks.google_message3.Message10573 field11878 = 5; + optional .benchmarks.google_message3.Message10582 field11879 = 6; + optional .benchmarks.google_message3.Message10824 field11880 = 7; + optional .benchmarks.google_message3.Message10773 field11881 = 12; + optional .benchmarks.google_message3.Message11866 field11882 = 8; + optional .benchmarks.google_message3.Message10818 field11883 = 13; + optional .benchmarks.google_message3.UnusedEmptyMessage field11884 = 16; + optional .benchmarks.google_message3.Message10155 field11885 = 11; + optional .benchmarks.google_message3.Message10469 field11886 = 14; + optional .benchmarks.google_message3.UnusedEmptyMessage field11887 = 15; + extensions 9 to 9; + extensions 10 to 10; +} + +message Message35506 { + optional int32 field35524 = 1; + optional string field35525 = 2; + optional .benchmarks.google_message3.Enum35507 field35526 = 3; + repeated .benchmarks.google_message3.UnusedEmptyMessage field35527 = 4; +} + +message Message13151 { + repeated .benchmarks.google_message3.Message13145 field13158 = 1; +} + +message Message18253 { + repeated group Message18254 = 1 { + required fixed64 field18362 = 2; + required double field18363 = 3; + } +} + +message Message16685 { + repeated .benchmarks.google_message3.Message16686 field16694 = 2; +} + +message Message16816 { + optional float field16826 = 1; + optional .benchmarks.google_message3.Enum16819 field16827 = 2; + optional float field16828 = 3; + repeated group Message16817 = 4 {} + optional bool field16830 = 7; + optional bool field16831 = 8; + repeated group Message16818 = 12 {} + optional string field16833 = 10; + optional bool field16834 = 13; + optional bool field16835 = 14; +} + +message Message13168 { + required int32 field13212 = 1; + optional fixed64 field13213 = 7; + optional bool field13214 = 8; + optional fixed64 field13215 = 10; + optional bool field13216 = 11; + optional .benchmarks.google_message3.Message12796 field13217 = 9; + required double field13218 = 2; + required bool field13219 = 3; + optional int32 field13220 = 4; + required bool field13221 = 5; + optional int32 field13222 = 6; +} + +message Message13167 { + required int32 field13199 = 1; + optional int32 field13200 = 2; + optional int32 field13201 = 3; + optional bool field13202 = 8; + optional fixed64 field13203 = 12; + optional bool field13204 = 13; + optional .benchmarks.google_message3.Message12796 field13205 = 11; + optional fixed64 field13206 = 9; + optional bool field13207 = 10; + repeated int32 field13208 = 4; + optional int32 field13209 = 5; + optional int32 field13210 = 6; + optional int32 field13211 = 7; +} + +message Message1374 { + required string field1375 = 1; + optional string field1376 = 2; +} + +message Message18943 {} + +message Message18944 {} + +message Message18856 { + optional string field18857 = 1; + optional string field18858 = 2; + optional bool field18859 = 31; + optional string field18860 = 26; + optional string field18861 = 3; + optional string field18862 = 4; + optional string field18863 = 5; + optional string field18864 = 17; + optional string field18865 = 6; + optional string field18866 = 7; + optional string field18867 = 8; + optional string field18868 = 9; + optional string field18869 = 10; + optional string field18870 = 11; + optional string field18871 = 21; + optional string field18872 = 18; + optional string field18873 = 19; + optional string field18874 = 20; + optional string field18875 = 22; + optional string field18876 = 23; + optional string field18877 = 24; + optional string field18878 = 25; + optional string field18879 = 12; + optional string field18880 = 13; + optional string field18881 = 29; + optional string field18882 = 30; + optional string field18883 = 15; + optional string field18884 = 16; + repeated string field18885 = 14; + optional string field18886 = 27; + optional string field18887 = 28; +} + +message Message3850 { + optional .benchmarks.google_message3.Enum3851 field3924 = 2; + optional bool field3925 = 12; + optional int32 field3926 = 4; + optional bool field3927 = 10; + optional bool field3928 = 13; + optional bool field3929 = 14; +} + +message Message6721 { + optional .benchmarks.google_message3.Message6722 field6744 = 1; + optional bool field6745 = 2; + optional bool field6746 = 3; + optional bool field6747 = 4; +} + +message Message6742 { + optional bool field6758 = 1; +} + +message Message6726 { + optional int64 field6752 = 1; + repeated .benchmarks.google_message3.Message6727 field6753 = 2; +} + +message Message6733 { + optional int64 field6754 = 1; + optional int64 field6755 = 2; + optional bool field6756 = 3; +} + +message Message6723 { + optional int64 field6748 = 1; + repeated .benchmarks.google_message3.Message6724 field6749 = 2; +} + +message Message6725 { + optional int32 field6750 = 1; + optional int32 field6751 = 2; +} + +message Message6734 { + repeated .benchmarks.google_message3.Message6735 field6757 = 1; +} + +message Message8184 { + optional .benchmarks.google_message3.Message7966 field8228 = 1; + optional bool field8229 = 2; + repeated .benchmarks.google_message3.Message8183 field8230 = 3; +} + +message Message8477 { + optional .benchmarks.google_message3.Message7966 field8486 = 1; + optional int64 field8487 = 2; + optional string field8488 = 3; +} + +message Message8454 { + optional .benchmarks.google_message3.Message8449 field8465 = 1; + optional int64 field8466 = 3; + optional int32 field8467 = 4; + optional bool field8468 = 5; + extend .benchmarks.google_message3.Message8301 { + optional .benchmarks.google_message3.Message8454 field8469 = 66; + } +} + +message Message8476 { + optional string field8483 = 1; + optional string field8484 = 2; + optional string field8485 = 3; +} + +message Message8455 { + optional .benchmarks.google_message3.Message8449 field8470 = 1; + repeated .benchmarks.google_message3.Message8456 field8471 = 2; + optional .benchmarks.google_message3.Message8457 field8472 = 5; + optional .benchmarks.google_message3.UnusedEmptyMessage field8473 = 6; + extend .benchmarks.google_message3.Message8302 { + optional .benchmarks.google_message3.Message8455 field8474 = 66; + } +} + +message Message8475 { + optional string field8481 = 1; + optional int64 field8482 = 2; +} + +message Message12559 {} + +message Message12817 { + optional int32 field12826 = 1; + optional int32 field12827 = 2; + optional int32 field12828 = 3; +} + +message Message16480 { + optional .benchmarks.google_message3.Message13358 field16490 = 1; + optional .benchmarks.google_message3.Enum16042 field16491 = 2; + optional .benchmarks.google_message3.Message13912 field16492 = 3; + optional string field16493 = 4; + optional string field16494 = 5; + optional string field16495 = 6; + optional string field16496 = 7; + optional .benchmarks.google_message3.Message13358 field16497 = 8; + optional fixed32 field16498 = 9; +} + +message Message24317 { + optional string field24446 = 1; + optional .benchmarks.google_message3.Message24312 field24447 = 2; + repeated .benchmarks.google_message3.Message24315 field24448 = 3; + repeated .benchmarks.google_message3.Message24313 field24449 = 4; + repeated .benchmarks.google_message3.Message24316 field24450 = 5; + repeated .benchmarks.google_message3.UnusedEmptyMessage field24451 = 6; + optional .benchmarks.google_message3.UnusedEmptyMessage field24452 = 7; + repeated string field24453 = 8; + repeated string field24454 = 9; + repeated string field24455 = 10; + repeated string field24456 = 28; + optional string field24457 = 11; + optional string field24458 = 12; + optional string field24459 = 13; + optional string field24460 = 14; + repeated string field24461 = 15; + optional string field24462 = 16; + repeated string field24463 = 17; + repeated string field24464 = 18; + repeated string field24465 = 19; + repeated string field24466 = 20; + repeated string field24467 = 21; + repeated string field24468 = 22; + repeated string field24469 = 23; + repeated string field24470 = 24; + optional string field24471 = 25; + optional string field24472 = 26; + repeated string field24473 = 27; + optional bool field24474 = 40; +} diff --git a/benchmarks/datasets/google_message3/benchmark_message3_5.proto b/benchmarks/datasets/google_message3/benchmark_message3_5.proto new file mode 100644 index 0000000000000..e72d7ee85af42 --- /dev/null +++ b/benchmarks/datasets/google_message3/benchmark_message3_5.proto @@ -0,0 +1,496 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// LINT: ALLOW_GROUPS + +syntax = "proto2"; + +package benchmarks.google_message3; + +import "datasets/google_message3/benchmark_message3_6.proto"; +import "datasets/google_message3/benchmark_message3_7.proto"; +import "datasets/google_message3/benchmark_message3_8.proto"; + +option cc_enable_arenas = true; +option java_package = "com.google.protobuf.benchmarks"; + +message Message24377 {} + +message Message24378 {} + +message Message24400 { + optional int32 field24674 = 1; + optional int32 field24675 = 2; + optional int32 field24676 = 3; + optional int32 field24677 = 4; + optional int32 field24678 = 5; +} + +message Message24380 {} + +message Message24381 {} + +message Message719 { + repeated string field881 = 1; + repeated string field882 = 2; + repeated string field883 = 3; + optional .benchmarks.google_message3.Enum720 field884 = 4; +} + +message Message728 { + required string field887 = 1; + repeated string field888 = 2; + repeated .benchmarks.google_message3.Message703 field889 = 3; + repeated .benchmarks.google_message3.Message715 field890 = 4; + repeated string field891 = 5; + repeated string field892 = 6; + optional .benchmarks.google_message3.Message718 field893 = 7; + optional .benchmarks.google_message3.Message716 field894 = 8; + repeated string field895 = 9; + extensions 10 to 10; + extensions 11 to 11; + extensions 12 to 12; +} + +message Message704 { + optional string field800 = 1; + optional string field801 = 7; + optional string field802 = 2; + optional string field803 = 3; + optional string field804 = 4; + optional string field805 = 5; + optional .benchmarks.google_message3.UnusedEmptyMessage field806 = 6; +} + +message Message697 { + optional string field743 = 7; + repeated string field744 = 1; + repeated string field745 = 2; + repeated string field746 = 33; + repeated string field747 = 29; + repeated string field748 = 30; + repeated string field749 = 31; + repeated string field750 = 32; + repeated string field751 = 13; + repeated string field752 = 6; + repeated string field753 = 3; + repeated string field754 = 14; + repeated string field755 = 15; + repeated string field756 = 16; + repeated string field757 = 4; + repeated string field758 = 34; + repeated string field759 = 35; + repeated string field760 = 5; + repeated string field761 = 17; + repeated string field762 = 18; + repeated string field763 = 19; + optional bool field764 = 36; + repeated string field765 = 8; + repeated string field766 = 9; + optional string field767 = 27; + optional bool field768 = 25; + optional .benchmarks.google_message3.Message700 field769 = 10; + optional bool field770 = 11; + optional bool field771 = 24; + repeated string field772 = 12; + repeated string field773 = 20; + repeated string field774 = 21; + repeated string field775 = 22; + repeated .benchmarks.google_message3.Message699 field776 = 23; + repeated .benchmarks.google_message3.Message698 field777 = 37; + optional int64 field778 = 38; + extensions 28 to 28; + extensions 26 to 26; +} + +message Message0 { + option message_set_wire_format = true; + + extensions 4 to 2147483646; +} + +message Message6578 { + optional .benchmarks.google_message3.Enum6579 field6632 = 1; + optional .benchmarks.google_message3.Enum6588 field6633 = 2; +} + +message Message6024 { + optional .benchmarks.google_message3.Enum6025 field6048 = 1; + optional string field6049 = 2; + optional .benchmarks.google_message3.UnusedEmptyMessage field6050 = 3; +} + +message Message6052 { + required string field6084 = 1; + required bytes field6085 = 2; +} + +message Message6054 { + required string field6089 = 1; + optional string field6090 = 2; +} + +message Message10573 { + repeated .benchmarks.google_message3.Message10576 field10580 = 1; + optional string field10581 = 2; + extensions 10000 to 536870911; +} + +message Message10824 { + required string field10825 = 1; + optional int32 field10826 = 2; +} + +message Message10582 { + required bool field10583 = 1; + required double field10584 = 2; + optional bool field10585 = 3; + optional double field10586 = 4; + optional double field10587 = 5; + optional bool field10588 = 6; +} + +message Message10155 { + required int32 field10195 = 1; + required int32 field10196 = 2; + optional .benchmarks.google_message3.Enum10157 field10197 = 59; + optional int32 field10198 = 18; + optional int32 field10199 = 19; + optional int32 field10200 = 21; + repeated group Message10156 = 50 { + optional .benchmarks.google_message3.Enum8862 field10266 = 51; + optional int32 field10267 = 52; + optional int32 field10268 = 53; + optional int32 field10269 = 54; + } + optional int32 field10202 = 3; + optional int32 field10203 = 4; + optional int32 field10204 = 5; + optional bool field10205 = 84; + optional bool field10206 = 33; + optional int32 field10207 = 75; + optional float field10208 = 26; + optional int32 field10209 = 27; + optional int32 field10210 = 49; + optional int32 field10211 = 10; + optional float field10212 = 78; + optional .benchmarks.google_message3.Message9151 field10213 = 91; + optional int32 field10214 = 11; + optional int32 field10215 = 12; + optional float field10216 = 41; + optional .benchmarks.google_message3.Message10154 field10217 = 61; + optional int32 field10218 = 23; + optional bytes field10219 = 24; + optional int32 field10220 = 65; + repeated bytes field10221 = 66; + optional int32 field10222 = 70; + optional bytes field10223 = 71; + repeated fixed64 field10224 = 73; + optional float field10225 = 29; + optional int32 field10226 = 30; + optional float field10227 = 31; + optional int32 field10228 = 32; + optional float field10229 = 34; + optional int32 field10230 = 35; + optional string field10231 = 22; + optional fixed64 field10232 = 13; + optional fixed64 field10233 = 20; + optional bool field10234 = 79; + repeated .benchmarks.google_message3.Enum10167 field10235 = 80 + [packed = true]; + optional int32 field10236 = 14; + optional int32 field10237 = 15; + optional int32 field10238 = 28; + repeated string field10239 = 16; + optional .benchmarks.google_message3.Message9182 field10240 = 17; + optional int32 field10241 = 63; + optional float field10242 = 64; + optional float field10243 = 37; + repeated float field10244 = 43; + optional int32 field10245 = 44; + optional .benchmarks.google_message3.Message9242 field10246 = 45; + optional .benchmarks.google_message3.UnusedEmptyMessage field10247 = 46; + optional .benchmarks.google_message3.UnusedEmptyMessage field10248 = 62; + optional .benchmarks.google_message3.Message8944 field10249 = 48; + optional .benchmarks.google_message3.UnusedEmptyMessage field10250 = 87; + optional int32 field10251 = 58; + optional int32 field10252 = 92; + optional .benchmarks.google_message3.Message9123 field10253 = 93; + optional .benchmarks.google_message3.Message9160 field10254 = 60; + optional .benchmarks.google_message3.Message8890 field10255 = 67; + optional string field10256 = 69; + optional int64 field10257 = 74; + optional float field10258 = 82; + optional float field10259 = 85; + optional float field10260 = 86; + optional int64 field10261 = 83; + optional string field10262 = 77; + optional bool field10263 = 88; + repeated .benchmarks.google_message3.Message9628 field10264 = 94; + extensions 57 to 57; + extensions 1000 to 536870911; +} + +message Message11866 { + required .benchmarks.google_message3.Message11014 field11868 = 1; + optional bool field11869 = 2; + optional double field11870 = 3; + optional double field11871 = 4; + repeated .benchmarks.google_message3.UnusedEmptyMessage field11872 = 5; +} + +message Message10469 { + optional string field10473 = 1; + optional float field10474 = 2; + optional int32 field10475 = 3; + optional int32 field10476 = 4; + optional int32 field10477 = 5; + optional bool field10478 = 6; + optional bool field10479 = 7; + optional int32 field10480 = 8; + optional float field10481 = 9; +} + +message Message10818 { + optional .benchmarks.google_message3.Message10800 field10819 = 1; + optional .benchmarks.google_message3.Message10801 field10820 = 2; +} + +message Message10773 { + optional bool field10774 = 9; + optional bool field10775 = 1; + optional bool field10776 = 23; + optional bool field10777 = 2; + optional bool field10778 = 3; + optional int32 field10779 = 4; + optional int32 field10780 = 5; + optional int32 field10781 = 6; + optional int32 field10782 = 7; + optional int32 field10783 = 8; + optional int32 field10784 = 10; + optional .benchmarks.google_message3.Message10749 field10785 = 11; + repeated .benchmarks.google_message3.UnusedEmptyMessage field10786 = 12; + optional bool field10787 = 13; + optional bool field10788 = 15; + optional bool field10789 = 16; + optional int32 field10790 = 17; + optional int32 field10791 = 18; + optional bool field10792 = 19; + optional bool field10793 = 20; + optional bool field10794 = 21; + optional .benchmarks.google_message3.UnusedEnum field10795 = 14; + optional .benchmarks.google_message3.UnusedEnum field10796 = 22; +} + +message Message13145 { + required .benchmarks.google_message3.Enum13146 field13155 = 1; + optional float field13156 = 2; + optional float field13157 = 3; + extensions 1000 to 536870911; +} + +message Message16686 {} + +message Message12796 { + repeated fixed64 field12800 = 1; + optional uint64 field12801 = 2; +} + +message Message6722 {} + +message Message6727 {} + +message Message6724 {} + +message Message6735 {} + +message Message8183 { + optional string field8226 = 1; + optional string field8227 = 2; +} + +message Message8301 { + optional string field8328 = 1; + optional .benchmarks.google_message3.Message7966 field8329 = 2; + optional string field8330 = 3; + optional string field8331 = 4; + repeated .benchmarks.google_message3.Message8290 field8332 = 5; + optional .benchmarks.google_message3.Message7966 field8333 = 6; + repeated .benchmarks.google_message3.Message8298 field8334 = 7; + optional .benchmarks.google_message3.Message8300 field8335 = 8; + optional int64 field8336 = 9; + optional .benchmarks.google_message3.UnusedEmptyMessage field8337 = 10; + optional .benchmarks.google_message3.Message7965 field8338 = 11; + extensions 64 to 536870911; +} + +message Message8456 {} + +message Message8302 { + optional string field8339 = 1; + optional .benchmarks.google_message3.Message7966 field8340 = 2; + optional string field8341 = 3; + optional string field8342 = 4; + optional string field8343 = 5; + optional string field8344 = 6; + optional string field8345 = 7; + optional int64 field8346 = 8; + optional int64 field8347 = 9; + repeated .benchmarks.google_message3.Message8290 field8348 = 10; + optional string field8349 = 11; + optional .benchmarks.google_message3.UnusedEmptyMessage field8350 = 12; + optional .benchmarks.google_message3.Message8291 field8351 = 13; + optional int64 field8352 = 14; + optional .benchmarks.google_message3.Message8296 field8353 = 15; + optional string field8354 = 16; + optional .benchmarks.google_message3.UnusedEmptyMessage field8355 = 17; + repeated int32 field8356 = 18; + repeated int32 field8357 = 19; + repeated .benchmarks.google_message3.UnusedEmptyMessage field8358 = 20; + optional .benchmarks.google_message3.Message7965 field8359 = 21; + extensions 64 to 536870911; +} + +message Message8457 {} + +message Message8449 { + optional string field8458 = 1; + optional bool field8459 = 2; + optional .benchmarks.google_message3.Enum8450 field8460 = 3; + repeated string field8461 = 4; + optional string field8462 = 5; + optional string field8463 = 6; + optional .benchmarks.google_message3.Message7966 field8464 = 7; +} + +message Message13358 { + required fixed64 field13359 = 1; + required fixed64 field13360 = 2; + optional .benchmarks.google_message3.UnusedEmptyMessage field13361 = 3; +} + +message Message13912 { + required fixed32 field13913 = 1; + required fixed32 field13914 = 2; + optional .benchmarks.google_message3.UnusedEmptyMessage field13915 = 500; + optional .benchmarks.google_message3.UnusedEmptyMessage field13916 = 15; +} + +message Message24316 { + repeated string field24443 = 1; + repeated string field24444 = 2; + repeated string field24445 = 3; +} + +message Message24312 { + optional string field24421 = 1; + optional string field24422 = 2; + repeated string field24423 = 3; + repeated string field24424 = 4; + repeated string field24425 = 5; + repeated string field24426 = 6; +} + +message Message24313 { + optional string field24427 = 1; + optional string field24428 = 2; + repeated string field24429 = 3; + optional string field24430 = 4; + optional string field24431 = 5; + optional string field24432 = 6; + optional string field24433 = 7; + repeated string field24434 = 8; + optional string field24435 = 9; + repeated string field24436 = 10; +} + +message Message24315 { + required string field24440 = 1; + repeated string field24441 = 2; + repeated string field24442 = 3; +} + +message Message716 { + required string field872 = 1; + required int32 field873 = 2; + optional bool field874 = 3; + optional .benchmarks.google_message3.Message717 field875 = 4; +} + +message Message718 { + repeated string field878 = 1; + repeated string field879 = 2; + optional string field880 = 3; +} + +message Message703 { + required string field795 = 1; + repeated string field796 = 2; + repeated string field797 = 3; + optional string field798 = 4; + repeated string field799 = 5; +} + +message Message715 { + required string field859 = 1; + optional string field860 = 7; + repeated .benchmarks.google_message3.Message707 field861 = 2; + repeated .benchmarks.google_message3.Message708 field862 = 3; + repeated .benchmarks.google_message3.Message711 field863 = 4; + repeated .benchmarks.google_message3.Message712 field864 = 5; + repeated .benchmarks.google_message3.Message713 field865 = 6; + repeated .benchmarks.google_message3.Message714 field866 = 8; + repeated .benchmarks.google_message3.Message710 field867 = 9; + repeated .benchmarks.google_message3.Message709 field868 = 10; + repeated .benchmarks.google_message3.Message705 field869 = 11; + repeated .benchmarks.google_message3.Message702 field870 = 12; + repeated .benchmarks.google_message3.Message706 field871 = 13; +} + +message Message700 { + repeated string field789 = 1; + repeated string field790 = 2; +} + +message Message699 { + required string field787 = 1; + repeated string field788 = 2; +} + +message Message698 { + optional string field779 = 1; + optional string field780 = 2; + optional string field781 = 3; + optional string field782 = 4; + optional uint64 field783 = 5; + optional uint32 field784 = 6; + optional int64 field785 = 7; + repeated string field786 = 8; +} diff --git a/benchmarks/datasets/google_message3/benchmark_message3_6.proto b/benchmarks/datasets/google_message3/benchmark_message3_6.proto new file mode 100644 index 0000000000000..c766f7c2efb08 --- /dev/null +++ b/benchmarks/datasets/google_message3/benchmark_message3_6.proto @@ -0,0 +1,483 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// LINT: ALLOW_GROUPS + +syntax = "proto2"; + +package benchmarks.google_message3; + +import "datasets/google_message3/benchmark_message3_7.proto"; +import "datasets/google_message3/benchmark_message3_8.proto"; + +option cc_enable_arenas = true; +option java_package = "com.google.protobuf.benchmarks"; + +message Message10576 {} + +message Message10154 { + optional bytes field10192 = 1; + optional int32 field10193 = 2; +} + +message Message8944 { + optional string field9045 = 2; + optional string field9046 = 3; + optional string field9047 = 23; + optional string field9048 = 52; + optional int32 field9049 = 53; + optional int32 field9050 = 54; + optional float field9051 = 55; + optional float field9052 = 56; + optional string field9053 = 57; + optional int64 field9054 = 1; + optional bool field9055 = 4; + optional int32 field9056 = 5; + optional int32 field9057 = 6; + optional int32 field9058 = 7; + optional float field9059 = 8; + optional float field9060 = 11; + optional float field9061 = 9; + optional float field9062 = 10; + optional float field9063 = 13; + optional bool field9064 = 14; + optional float field9065 = 70; + optional int32 field9066 = 71; + optional .benchmarks.google_message3.Enum8945 field9067 = 15; + optional int32 field9068 = 16; + optional int32 field9069 = 17; + optional float field9070 = 18; + optional float field9071 = 19; + optional int32 field9072 = 28; + optional int32 field9073 = 29; + optional float field9074 = 60; + optional float field9075 = 61; + optional int32 field9076 = 72; + optional int32 field9077 = 73; + optional .benchmarks.google_message3.Enum8951 field9078 = 62; + optional string field9079 = 20; + optional string field9080 = 21; + optional string field9081 = 22; + optional double field9082 = 31; + optional double field9083 = 32; + optional double field9084 = 33; + optional double field9085 = 36; + optional .benchmarks.google_message3.UnusedEnum field9086 = 37; + optional double field9087 = 38; + optional double field9088 = 39; + optional double field9089 = 63; + optional double field9090 = 64; + optional double field9091 = 65; + optional double field9092 = 34; + optional .benchmarks.google_message3.UnusedEnum field9093 = 35; + optional .benchmarks.google_message3.UnusedEnum field9094 = 66; + optional string field9095 = 40; + optional string field9096 = 41; + optional string field9097 = 42; + optional string field9098 = 43; + optional string field9099 = 44; + optional string field9100 = 45; + optional string field9101 = 46; + optional string field9102 = 47; + optional string field9103 = 48; + optional string field9104 = 49; + optional .benchmarks.google_message3.Message8939 field9105 = 100; + optional int64 field9106 = 101; +} + +message Message9182 { + optional string field9205 = 1; + optional string field9206 = 2; + optional float field9207 = 16; + optional int32 field9208 = 17; + optional int32 field9209 = 27; + optional int32 field9210 = 7; + optional int32 field9211 = 8; + optional float field9212 = 26; + optional float field9213 = 22; + optional bool field9214 = 28; + repeated .benchmarks.google_message3.UnusedEmptyMessage field9215 = 21; + repeated .benchmarks.google_message3.UnusedEmptyMessage field9216 = 25; + repeated .benchmarks.google_message3.Message9181 field9217 = 29; + optional bool field9218 = 18; + optional bool field9219 = 19; + optional bool field9220 = 20; + optional .benchmarks.google_message3.Message9164 field9221 = 30; + optional .benchmarks.google_message3.Message9165 field9222 = 31; + optional .benchmarks.google_message3.Message9166 field9223 = 32; + optional float field9224 = 33; + optional .benchmarks.google_message3.Message9151 field9225 = 34; + optional float field9226 = 35; + optional float field9227 = 36; + optional float field9228 = 37; + optional float field9229 = 38; + optional float field9230 = 39; + extensions 3 to 6; + extensions 9 to 15; + extensions 23 to 23; + extensions 24 to 24; + extensions 1000 to 536870911; +} + +message Message9160 { + optional int32 field9161 = 1; + optional bytes field9162 = 2; +} + +message Message9242 { + repeated .benchmarks.google_message3.Enum9243 field9327 = 1; +} + +message Message8890 { + repeated .benchmarks.google_message3.Message8888 field8916 = 1; +} + +message Message9123 { + optional float field9135 = 1; +} + +message Message9628 { + optional .benchmarks.google_message3.Message9627 field9673 = 1; + optional string field9674 = 2; + repeated int32 field9675 = 3; + optional int32 field9676 = 4; +} + +message Message11014 { + optional int32 field11780 = 40; + optional string field11781 = 46; + optional bool field11782 = 47; + optional .benchmarks.google_message3.Enum11107 field11783 = 1; + optional int32 field11784 = 2; + optional double field11785 = 4; + optional int32 field11786 = 5; + optional int32 field11787 = 6; + optional double field11788 = 7; + optional double field11789 = 8; + optional int64 field11790 = 9; + optional bool field11791 = 10; + optional int64 field11792 = 28; + optional bool field11793 = 37; + optional .benchmarks.google_message3.Enum11541 field11794 = 44; + optional double field11795 = 49; + optional double field11796 = 51; + optional int64 field11797 = 54; + optional int64 field11798 = 55; + optional .benchmarks.google_message3.UnusedEnum field11799 = 57; + optional .benchmarks.google_message3.Enum11468 field11800 = 58; + optional int32 field11801 = 59; + optional .benchmarks.google_message3.UnusedEnum field11802 = 60; + optional int32 field11803 = 61; + optional int32 field11804 = 62; + optional int32 field11805 = 69; + optional .benchmarks.google_message3.UnusedEmptyMessage field11806 = 68; + repeated .benchmarks.google_message3.Message11018 field11807 = 71; + optional bool field11808 = 50; + optional bool field11809 = 56; + optional bool field11810 = 66; + optional bool field11811 = 63; + optional bool field11812 = 64; + optional bool field11813 = 65; + optional bool field11814 = 67; + optional .benchmarks.google_message3.Enum11107 field11815 = 15; + optional int64 field11816 = 16; + optional double field11817 = 17; + optional int64 field11818 = 18; + optional int32 field11819 = 19; + optional int64 field11820 = 20; + optional int32 field11821 = 42; + optional int64 field11822 = 52; + optional int64 field11823 = 53; + optional int64 field11824 = 41; + optional double field11825 = 48; + repeated .benchmarks.google_message3.Message11020 field11826 = 70; + repeated .benchmarks.google_message3.UnusedEmptyMessage field11827 = 72; + optional double field11828 = 25; + optional string field11829 = 26; + optional int64 field11830 = 27; + optional int64 field11831 = 32; + optional uint64 field11832 = 33; + optional bool field11833 = 29; + optional bool field11834 = 34; + optional string field11835 = 30; + optional int32 field11836 = 3; + optional int32 field11837 = 31; + optional int32 field11838 = 73; + optional int32 field11839 = 35; + optional .benchmarks.google_message3.Enum11022 field11840 = 36; + optional .benchmarks.google_message3.Message11013 field11841 = 38; + optional double field11842 = 39; + optional int32 field11843 = 45; + optional bool field11844 = 74; +} + +message Message10801 { + optional .benchmarks.google_message3.Message10800 field10812 = 1; + repeated .benchmarks.google_message3.Message10802 field10813 = 2; + optional int32 field10814 = 3; +} + +message Message10749 { + repeated .benchmarks.google_message3.Message10748 field10754 = 1; +} + +message Message8298 { + optional .benchmarks.google_message3.Message7966 field8321 = 1; + optional int64 field8322 = 2; + optional string field8323 = 3; +} + +message Message8300 { + optional string field8326 = 1; + optional .benchmarks.google_message3.Message7966 field8327 = 2; +} + +message Message8291 { + optional string field8306 = 1; + optional int32 field8307 = 2; + optional string field8308 = 3; + optional string field8309 = 4; + optional .benchmarks.google_message3.Enum8292 field8310 = 5; +} + +message Message8296 { + optional .benchmarks.google_message3.Message7966 field8311 = 1; + optional string field8312 = 2; + optional .benchmarks.google_message3.Message7966 field8313 = 3; + optional int32 field8314 = 4; + optional int32 field8315 = 5; + optional string field8316 = 6; +} + +message Message7965 { + optional int32 field7967 = 1; + optional int32 field7968 = 2; +} + +message Message8290 { + optional string field8304 = 1; + optional string field8305 = 2; +} + +message Message717 { + repeated string field876 = 1; + optional double field877 = 2; +} + +message Message713 { + required .benchmarks.google_message3.Message708 field852 = 1; + repeated string field853 = 2; +} + +message Message705 { + required string field807 = 1; + optional string field808 = 2; + optional string field809 = 3; + optional bool field810 = 4; + optional string field811 = 5; + optional string field812 = 6; + repeated string field813 = 7; +} + +message Message709 { + repeated string field829 = 1; + repeated string field830 = 2; + repeated string field831 = 3; + repeated string field832 = 4; + repeated string field833 = 5; +} + +message Message702 { + optional string field793 = 1; + optional string field794 = 2; +} + +message Message714 { + optional string field854 = 1; + optional string field855 = 2; + optional string field856 = 3; + optional string field857 = 4; + optional uint32 field858 = 5; +} + +message Message710 { + repeated string field834 = 1; + optional string field835 = 2; + optional string field836 = 3; + repeated string field837 = 4; + repeated string field838 = 5; +} + +message Message706 { + repeated string field814 = 1; + optional string field815 = 2; + repeated string field816 = 3; + repeated string field817 = 4; +} + +message Message707 { + required string field818 = 1; + required string field819 = 2; + required string field820 = 3; + optional bool field821 = 4; + repeated string field822 = 5; +} + +message Message711 { + optional .benchmarks.google_message3.UnusedEmptyMessage field839 = 1; + repeated string field840 = 4; + repeated string field841 = 2; + repeated string field842 = 3; +} + +message Message712 { + repeated string field843 = 1; + required string field844 = 2; + optional string field845 = 3; + repeated string field846 = 4; + repeated string field847 = 5; + optional string field848 = 6; + repeated string field849 = 7; + optional string field850 = 8; + optional string field851 = 9; +} + +message Message8939 { + optional string field9010 = 1; + optional string field9011 = 2; + optional string field9012 = 3; + repeated string field9013 = 4; + optional string field9014 = 5; + repeated group Message8940 = 11 {} + optional int64 field9016 = 21; + optional int64 field9017 = 22; + optional int64 field9018 = 23; + optional group Message8941 = 31 { + optional string field9033 = 32; + optional string field9034 = 33; + optional string field9035 = 34; + optional string field9036 = 35; + optional string field9037 = 36; + optional string field9038 = 37; + } + optional .benchmarks.google_message3.Message8942 field9020 = 38; + repeated .benchmarks.google_message3.UnusedEmptyMessage field9021 = 39; + repeated string field9022 = 41; + optional string field9023 = 42; + optional string field9024 = 43; + optional string field9025 = 44; + optional string field9026 = 45; + optional string field9027 = 46; + optional string field9028 = 47; + optional .benchmarks.google_message3.UnusedEnum field9029 = 48; + optional .benchmarks.google_message3.UnusedEnum field9030 = 49; + optional group Message8943 = 51 { + optional string field9039 = 1; + optional string field9040 = 2; + optional string field9041 = 3; + optional string field9042 = 4; + optional string field9043 = 5; + optional string field9044 = 6; + } +} + +message Message9181 { + optional string field9204 = 1; +} + +message Message9164 { + optional int32 field9168 = 1; + optional int32 field9169 = 2; + optional int32 field9170 = 3; +} + +message Message9165 { + optional float field9171 = 1; + optional float field9172 = 2; +} + +message Message9166 { + optional float field9173 = 1; + optional int32 field9174 = 2; +} + +message Message9151 { + optional double field9152 = 1; + optional double field9153 = 2; + optional float field9154 = 3; + optional float field9155 = 4; + optional float field9156 = 5; + optional float field9157 = 6; + optional float field9158 = 7; + optional float field9159 = 8; +} + +message Message8888 { + optional int32 field8908 = 1; + optional .benchmarks.google_message3.Enum8900 field8909 = 4; + repeated int32 field8910 = 2 [packed = true]; + optional bytes field8911 = 3; +} + +message Message9627 { + required int32 field9668 = 1; + required int32 field9669 = 2; + required int32 field9670 = 3; + required int32 field9671 = 4; + optional float field9672 = 5; +} + +message Message11020 {} + +message Message11013 { + optional bytes field11757 = 19; + optional bytes field11758 = 1; + optional bytes field11759 = 2; + optional bytes field11760 = 3; + optional bytes field11761 = 4; + optional bytes field11762 = 5; + optional bytes field11763 = 6; + optional bytes field11764 = 7; + optional bytes field11765 = 8; + optional bytes field11766 = 9; + optional bytes field11767 = 10; + optional bytes field11768 = 11; + optional bytes field11769 = 12; + optional bytes field11770 = 13; + optional bytes field11771 = 14; + optional bytes field11772 = 15; + optional bytes field11773 = 16; + optional bytes field11774 = 17; + optional bytes field11775 = 18; + optional bytes field11776 = 20; + optional bytes field11777 = 21; + optional .benchmarks.google_message3.UnusedEmptyMessage field11778 = 23; + repeated .benchmarks.google_message3.Message11011 field11779 = 22; +} diff --git a/benchmarks/datasets/google_message3/benchmark_message3_7.proto b/benchmarks/datasets/google_message3/benchmark_message3_7.proto new file mode 100644 index 0000000000000..0f8f10cd3732b --- /dev/null +++ b/benchmarks/datasets/google_message3/benchmark_message3_7.proto @@ -0,0 +1,81 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package benchmarks.google_message3; + +option cc_enable_arenas = true; +option java_package = "com.google.protobuf.benchmarks"; + +message Message11018 {} + +message Message10800 { + optional string field10808 = 1; + optional int64 field10809 = 2; + optional bool field10810 = 3; + optional float field10811 = 4; +} + +message Message10802 {} + +message Message10748 { + optional string field10750 = 1; + optional int32 field10751 = 2; + optional int32 field10752 = 3; + optional int32 field10753 = 4; +} + +message Message7966 { + optional string field7969 = 1; + optional bool field7970 = 2; +} + +message Message708 { + optional .benchmarks.google_message3.Message741 field823 = 1; + repeated string field824 = 6; + optional string field825 = 2; + optional string field826 = 3; + repeated string field827 = 4; + repeated string field828 = 5; +} + +message Message8942 {} + +message Message11011 { + required bytes field11752 = 1; + required bytes field11753 = 2; +} + +message UnusedEmptyMessage {} + +message Message741 { + repeated string field936 = 1; +} diff --git a/benchmarks/datasets/google_message3/benchmark_message3_8.proto b/benchmarks/datasets/google_message3/benchmark_message3_8.proto new file mode 100644 index 0000000000000..68fe8e901a6c0 --- /dev/null +++ b/benchmarks/datasets/google_message3/benchmark_message3_8.proto @@ -0,0 +1,1925 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package benchmarks.google_message3; + +option cc_enable_arenas = true; +option java_package = "com.google.protobuf.benchmarks"; + +enum Enum720 { + ENUM_VALUE721 = 1; + ENUM_VALUE722 = 2; +} + +enum Enum3476 { + ENUM_VALUE3477 = 0; + ENUM_VALUE3478 = 1; + ENUM_VALUE3479 = 2; + ENUM_VALUE3480 = 3; + ENUM_VALUE3481 = 4; + ENUM_VALUE3482 = 5; + ENUM_VALUE3483 = 6; + ENUM_VALUE3484 = 7; + ENUM_VALUE3485 = 8; + ENUM_VALUE3486 = 9; + ENUM_VALUE3487 = 10; + ENUM_VALUE3488 = 11; + ENUM_VALUE3489 = 12; + ENUM_VALUE3490 = 13; + ENUM_VALUE3491 = 14; + ENUM_VALUE3492 = 15; + ENUM_VALUE3493 = 16; + ENUM_VALUE3494 = 17; + ENUM_VALUE3495 = 18; + ENUM_VALUE3496 = 19; + ENUM_VALUE3497 = 20; + ENUM_VALUE3498 = 21; + ENUM_VALUE3499 = 22; + ENUM_VALUE3500 = 23; + ENUM_VALUE3501 = 24; + ENUM_VALUE3502 = 25; + ENUM_VALUE3503 = 26; + ENUM_VALUE3504 = 27; + ENUM_VALUE3505 = 28; + ENUM_VALUE3506 = 29; + ENUM_VALUE3507 = 30; + ENUM_VALUE3508 = 31; + ENUM_VALUE3509 = 32; + ENUM_VALUE3510 = 33; + ENUM_VALUE3511 = 34; + ENUM_VALUE3512 = 35; + ENUM_VALUE3513 = 36; + ENUM_VALUE3514 = 37; + ENUM_VALUE3515 = 38; + ENUM_VALUE3516 = 39; + ENUM_VALUE3517 = 40; + ENUM_VALUE3518 = 41; + ENUM_VALUE3519 = 42; + ENUM_VALUE3520 = 43; + ENUM_VALUE3521 = 44; + ENUM_VALUE3522 = 45; + ENUM_VALUE3523 = 46; + ENUM_VALUE3524 = 47; + ENUM_VALUE3525 = 48; + ENUM_VALUE3526 = 49; + ENUM_VALUE3527 = 50; + ENUM_VALUE3528 = 51; + ENUM_VALUE3529 = 52; + ENUM_VALUE3530 = 53; + ENUM_VALUE3531 = 54; + ENUM_VALUE3532 = 55; + ENUM_VALUE3533 = 56; + ENUM_VALUE3534 = 57; + ENUM_VALUE3535 = 58; + ENUM_VALUE3536 = 59; + ENUM_VALUE3537 = 60; + ENUM_VALUE3538 = 61; + ENUM_VALUE3539 = 62; + ENUM_VALUE3540 = 63; + ENUM_VALUE3541 = 64; + ENUM_VALUE3542 = 65; + ENUM_VALUE3543 = 66; + ENUM_VALUE3544 = 67; + ENUM_VALUE3545 = 68; + ENUM_VALUE3546 = 69; + ENUM_VALUE3547 = 70; + ENUM_VALUE3548 = 71; + ENUM_VALUE3549 = 72; + ENUM_VALUE3550 = 73; + ENUM_VALUE3551 = 74; + ENUM_VALUE3552 = 75; + ENUM_VALUE3553 = 76; + ENUM_VALUE3554 = 77; + ENUM_VALUE3555 = 78; + ENUM_VALUE3556 = 79; + ENUM_VALUE3557 = 80; + ENUM_VALUE3558 = 81; + ENUM_VALUE3559 = 82; + ENUM_VALUE3560 = 83; + ENUM_VALUE3561 = 84; + ENUM_VALUE3562 = 85; + ENUM_VALUE3563 = 86; + ENUM_VALUE3564 = 87; + ENUM_VALUE3565 = 88; + ENUM_VALUE3566 = 89; + ENUM_VALUE3567 = 90; + ENUM_VALUE3568 = 91; + ENUM_VALUE3569 = 92; + ENUM_VALUE3570 = 93; + ENUM_VALUE3571 = 94; + ENUM_VALUE3572 = 95; + ENUM_VALUE3573 = 96; + ENUM_VALUE3574 = 97; + ENUM_VALUE3575 = 98; + ENUM_VALUE3576 = 99; + ENUM_VALUE3577 = 100; + ENUM_VALUE3578 = 101; + ENUM_VALUE3579 = 102; + ENUM_VALUE3580 = 103; + ENUM_VALUE3581 = 104; + ENUM_VALUE3582 = 105; + ENUM_VALUE3583 = 106; + ENUM_VALUE3584 = 107; + ENUM_VALUE3585 = 108; + ENUM_VALUE3586 = 109; + ENUM_VALUE3587 = 110; + ENUM_VALUE3588 = 111; + ENUM_VALUE3589 = 112; + ENUM_VALUE3590 = 113; + ENUM_VALUE3591 = 114; + ENUM_VALUE3592 = 115; + ENUM_VALUE3593 = 116; + ENUM_VALUE3594 = 117; + ENUM_VALUE3595 = 118; + ENUM_VALUE3596 = 119; + ENUM_VALUE3597 = 120; + ENUM_VALUE3598 = 121; + ENUM_VALUE3599 = 122; + ENUM_VALUE3600 = 123; + ENUM_VALUE3601 = 124; + ENUM_VALUE3602 = 125; + ENUM_VALUE3603 = 126; + ENUM_VALUE3604 = 127; + ENUM_VALUE3605 = 128; + ENUM_VALUE3606 = 129; + ENUM_VALUE3607 = 130; + ENUM_VALUE3608 = 131; + ENUM_VALUE3609 = 132; + ENUM_VALUE3610 = 133; + ENUM_VALUE3611 = 134; + ENUM_VALUE3612 = 135; + ENUM_VALUE3613 = 136; + ENUM_VALUE3614 = 137; + ENUM_VALUE3615 = 138; + ENUM_VALUE3616 = 139; + ENUM_VALUE3617 = 140; + ENUM_VALUE3618 = 141; + ENUM_VALUE3619 = 142; + ENUM_VALUE3620 = 143; + ENUM_VALUE3621 = 144; + ENUM_VALUE3622 = 145; + ENUM_VALUE3623 = 146; + ENUM_VALUE3624 = 147; + ENUM_VALUE3625 = 148; + ENUM_VALUE3626 = 149; + ENUM_VALUE3627 = 150; + ENUM_VALUE3628 = 151; + ENUM_VALUE3629 = 152; + ENUM_VALUE3630 = 153; + ENUM_VALUE3631 = 154; + ENUM_VALUE3632 = 155; + ENUM_VALUE3633 = 156; + ENUM_VALUE3634 = 157; + ENUM_VALUE3635 = 158; + ENUM_VALUE3636 = 159; + ENUM_VALUE3637 = 160; + ENUM_VALUE3638 = 161; + ENUM_VALUE3639 = 162; + ENUM_VALUE3640 = 163; + ENUM_VALUE3641 = 164; + ENUM_VALUE3642 = 165; + ENUM_VALUE3643 = 166; + ENUM_VALUE3644 = 167; + ENUM_VALUE3645 = 168; + ENUM_VALUE3646 = 169; + ENUM_VALUE3647 = 170; + ENUM_VALUE3648 = 171; + ENUM_VALUE3649 = 172; + ENUM_VALUE3650 = 173; + ENUM_VALUE3651 = 174; + ENUM_VALUE3652 = 175; + ENUM_VALUE3653 = 176; + ENUM_VALUE3654 = 177; + ENUM_VALUE3655 = 178; + ENUM_VALUE3656 = 179; + ENUM_VALUE3657 = 180; + ENUM_VALUE3658 = 181; + ENUM_VALUE3659 = 182; + ENUM_VALUE3660 = 183; +} + +enum Enum3805 { + ENUM_VALUE3806 = 0; + ENUM_VALUE3807 = 1; + ENUM_VALUE3808 = 2; + ENUM_VALUE3809 = 3; + ENUM_VALUE3810 = 4; + ENUM_VALUE3811 = 5; + ENUM_VALUE3812 = 6; + ENUM_VALUE3813 = 7; + ENUM_VALUE3814 = 8; + ENUM_VALUE3815 = 9; + ENUM_VALUE3816 = 11; + ENUM_VALUE3817 = 10; +} + +enum Enum3783 { + ENUM_VALUE3784 = 0; + ENUM_VALUE3785 = 1; + ENUM_VALUE3786 = 2; + ENUM_VALUE3787 = 3; + ENUM_VALUE3788 = 4; + ENUM_VALUE3789 = 5; + ENUM_VALUE3790 = 6; + ENUM_VALUE3791 = 7; + ENUM_VALUE3792 = 8; + ENUM_VALUE3793 = 9; + ENUM_VALUE3794 = 10; + ENUM_VALUE3795 = 11; + ENUM_VALUE3796 = 12; + ENUM_VALUE3797 = 13; + ENUM_VALUE3798 = 14; + ENUM_VALUE3799 = 15; + ENUM_VALUE3800 = 16; + ENUM_VALUE3801 = 20; + ENUM_VALUE3802 = 21; + ENUM_VALUE3803 = 50; +} + +enum Enum3851 { + ENUM_VALUE3852 = 0; + ENUM_VALUE3853 = 1; + ENUM_VALUE3854 = 2; + ENUM_VALUE3855 = 3; + ENUM_VALUE3856 = 4; + ENUM_VALUE3857 = 5; + ENUM_VALUE3858 = 6; + ENUM_VALUE3859 = 7; + ENUM_VALUE3860 = 8; + ENUM_VALUE3861 = 9; + ENUM_VALUE3862 = 10; + ENUM_VALUE3863 = 11; + ENUM_VALUE3864 = 12; + ENUM_VALUE3865 = 13; + ENUM_VALUE3866 = 14; + ENUM_VALUE3867 = 15; + ENUM_VALUE3868 = 16; + ENUM_VALUE3869 = 17; +} + +enum UnusedEnum { + UNUSED_ENUM_VALUE1 = 0; + UNUSED_ENUM_VALUE2 = 1; +} + +enum Enum4146 { + ENUM_VALUE4147 = 0; + ENUM_VALUE4148 = 1; + ENUM_VALUE4149 = 2; + ENUM_VALUE4150 = 3; + ENUM_VALUE4151 = 4; +} + +enum Enum4160 { + ENUM_VALUE4161 = 0; + ENUM_VALUE4162 = 1; +} + +enum Enum4152 { + ENUM_VALUE4153 = 0; + ENUM_VALUE4154 = 1; + ENUM_VALUE4155 = 2; + ENUM_VALUE4156 = 3; + ENUM_VALUE4157 = 4; + ENUM_VALUE4158 = 5; + ENUM_VALUE4159 = 6; +} + +enum Enum6025 { + ENUM_VALUE6026 = 0; + ENUM_VALUE6027 = 1; + ENUM_VALUE6028 = 2; + ENUM_VALUE6029 = 3; + ENUM_VALUE6030 = 4; + ENUM_VALUE6031 = 5; + ENUM_VALUE6032 = 6; + ENUM_VALUE6033 = 7; + ENUM_VALUE6034 = 8; + ENUM_VALUE6035 = 9; + ENUM_VALUE6036 = 10; + ENUM_VALUE6037 = 11; + ENUM_VALUE6038 = 12; + ENUM_VALUE6039 = 13; + ENUM_VALUE6040 = 14; + ENUM_VALUE6041 = 15; + ENUM_VALUE6042 = 16; + ENUM_VALUE6043 = 17; + ENUM_VALUE6044 = 18; + ENUM_VALUE6045 = 19; + ENUM_VALUE6046 = 20; + ENUM_VALUE6047 = 21; +} + +enum Enum6065 { + ENUM_VALUE6066 = 0; + ENUM_VALUE6067 = 1; + ENUM_VALUE6068 = 2; + ENUM_VALUE6069 = 3; + ENUM_VALUE6070 = 4; + ENUM_VALUE6071 = 5; + ENUM_VALUE6072 = 6; + ENUM_VALUE6073 = 7; + ENUM_VALUE6074 = 8; + ENUM_VALUE6075 = 9; + ENUM_VALUE6076 = 10; + ENUM_VALUE6077 = 11; + ENUM_VALUE6078 = 12; + ENUM_VALUE6079 = 13; + ENUM_VALUE6080 = 14; +} + +enum Enum6579 { + ENUM_VALUE6580 = 0; + ENUM_VALUE6581 = 2; + ENUM_VALUE6582 = 3; + ENUM_VALUE6583 = 5; + ENUM_VALUE6584 = 10; + ENUM_VALUE6585 = 15; + ENUM_VALUE6586 = 25; + ENUM_VALUE6587 = 30; +} + +enum Enum6588 { + ENUM_VALUE6589 = 0; + ENUM_VALUE6590 = 1; + ENUM_VALUE6591 = 2; + ENUM_VALUE6592 = 3; + ENUM_VALUE6593 = 4; + ENUM_VALUE6594 = 5; + ENUM_VALUE6595 = 6; + ENUM_VALUE6596 = 7; + ENUM_VALUE6597 = 8; + ENUM_VALUE6598 = 9; + ENUM_VALUE6599 = 10; + ENUM_VALUE6600 = 11; + ENUM_VALUE6601 = 12; + ENUM_VALUE6602 = 13; + ENUM_VALUE6603 = 14; + ENUM_VALUE6604 = 15; + ENUM_VALUE6605 = 16; + ENUM_VALUE6606 = 17; + ENUM_VALUE6607 = 19; + ENUM_VALUE6608 = 20; + ENUM_VALUE6609 = 21; + ENUM_VALUE6610 = 22; + ENUM_VALUE6611 = 23; + ENUM_VALUE6612 = 24; + ENUM_VALUE6613 = 25; + ENUM_VALUE6614 = 26; + ENUM_VALUE6615 = 27; + ENUM_VALUE6616 = 28; + ENUM_VALUE6617 = 29; + ENUM_VALUE6618 = 30; + ENUM_VALUE6619 = 31; + ENUM_VALUE6620 = 32; + ENUM_VALUE6621 = 33; + ENUM_VALUE6622 = 34; +} + +enum Enum6769 { + ENUM_VALUE6770 = 0; + ENUM_VALUE6771 = 1; + ENUM_VALUE6772 = 2; +} + +enum Enum6774 { + ENUM_VALUE6775 = 0; + ENUM_VALUE6776 = 1; + ENUM_VALUE6777 = 2; + ENUM_VALUE6778 = 3; + ENUM_VALUE6779 = 4; + ENUM_VALUE6780 = 5; + ENUM_VALUE6781 = 6; +} + +enum Enum6782 { + ENUM_VALUE6783 = 0; + ENUM_VALUE6784 = 1; + ENUM_VALUE6785 = 2; + ENUM_VALUE6786 = 3; + ENUM_VALUE6787 = 4; + ENUM_VALUE6788 = 5; +} + +enum Enum6858 { + ENUM_VALUE6859 = 1; + ENUM_VALUE6860 = 2; + ENUM_VALUE6861 = 3; + ENUM_VALUE6862 = 4; +} + +enum Enum6815 { + ENUM_VALUE6816 = 0; + ENUM_VALUE6817 = 1; + ENUM_VALUE6818 = 2; + ENUM_VALUE6819 = 3; + ENUM_VALUE6820 = 4; + ENUM_VALUE6821 = 5; +} + +enum Enum6822 { + ENUM_VALUE6823 = 0; + ENUM_VALUE6824 = 1; + ENUM_VALUE6825 = 2; + ENUM_VALUE6826 = 3; +} + +enum Enum7654 { + ENUM_VALUE7655 = 1; + ENUM_VALUE7656 = 2; + ENUM_VALUE7657 = 3; +} + +enum Enum8292 { + ENUM_VALUE8293 = 0; + ENUM_VALUE8294 = 1; + ENUM_VALUE8295 = 2; +} + +enum Enum8450 { + ENUM_VALUE8451 = 0; + ENUM_VALUE8452 = 1; + ENUM_VALUE8453 = 2; +} + +enum Enum8900 { + ENUM_VALUE8901 = 0; + ENUM_VALUE8902 = 1; + ENUM_VALUE8903 = 2; + ENUM_VALUE8904 = 3; + ENUM_VALUE8905 = 4; +} + +enum Enum8945 { + ENUM_VALUE8946 = 0; + ENUM_VALUE8947 = 1; + ENUM_VALUE8948 = 2; + ENUM_VALUE8949 = 3; + ENUM_VALUE8950 = 4; +} + +enum Enum8951 { + ENUM_VALUE8952 = 1; + ENUM_VALUE8953 = 2; + ENUM_VALUE8954 = 3; + ENUM_VALUE8955 = 4; + ENUM_VALUE8956 = 5; + ENUM_VALUE8957 = 6; + ENUM_VALUE8958 = 7; + ENUM_VALUE8959 = 8; +} + +enum Enum9243 { + ENUM_VALUE9244 = -1; + ENUM_VALUE9245 = 0; + ENUM_VALUE9246 = 1; + ENUM_VALUE9247 = 2; + ENUM_VALUE9248 = 3; + ENUM_VALUE9249 = 4; + ENUM_VALUE9250 = 5; + ENUM_VALUE9251 = 6; + ENUM_VALUE9252 = 7; + ENUM_VALUE9253 = 8; + ENUM_VALUE9254 = 9; + ENUM_VALUE9255 = 10; + ENUM_VALUE9256 = 11; + ENUM_VALUE9257 = 12; + ENUM_VALUE9258 = 13; + ENUM_VALUE9259 = 14; + ENUM_VALUE9260 = 15; + ENUM_VALUE9261 = 16; + ENUM_VALUE9262 = 17; + ENUM_VALUE9263 = 71; + ENUM_VALUE9264 = 72; + ENUM_VALUE9265 = 73; + ENUM_VALUE9266 = 74; + ENUM_VALUE9267 = 18; + ENUM_VALUE9268 = 20; + ENUM_VALUE9269 = 21; + ENUM_VALUE9270 = 22; + ENUM_VALUE9271 = 23; + ENUM_VALUE9272 = 61; + ENUM_VALUE9273 = 62; + ENUM_VALUE9274 = 63; + ENUM_VALUE9275 = 64; + ENUM_VALUE9276 = 66; + ENUM_VALUE9277 = 67; + ENUM_VALUE9278 = 24; + ENUM_VALUE9279 = 25; + ENUM_VALUE9280 = 26; + ENUM_VALUE9281 = 27; + ENUM_VALUE9282 = 28; + ENUM_VALUE9283 = 29; + ENUM_VALUE9284 = 30; + ENUM_VALUE9285 = 31; + ENUM_VALUE9286 = 32; + ENUM_VALUE9287 = 33; + ENUM_VALUE9288 = 34; + ENUM_VALUE9289 = 35; + ENUM_VALUE9290 = 36; + ENUM_VALUE9291 = 37; + ENUM_VALUE9292 = 38; + ENUM_VALUE9293 = 39; + ENUM_VALUE9294 = 40; + ENUM_VALUE9295 = 41; + ENUM_VALUE9296 = 42; + ENUM_VALUE9297 = 43; + ENUM_VALUE9298 = 44; + ENUM_VALUE9299 = 45; + ENUM_VALUE9300 = 46; + ENUM_VALUE9301 = 47; + ENUM_VALUE9302 = 48; + ENUM_VALUE9303 = 49; + ENUM_VALUE9304 = 50; + ENUM_VALUE9305 = 51; + ENUM_VALUE9306 = 52; + ENUM_VALUE9307 = 53; + ENUM_VALUE9308 = 54; + ENUM_VALUE9309 = 55; + ENUM_VALUE9310 = 56; + ENUM_VALUE9311 = 57; + ENUM_VALUE9312 = 58; + ENUM_VALUE9313 = 59; + ENUM_VALUE9314 = 60; + ENUM_VALUE9315 = 68; + ENUM_VALUE9316 = 69; + ENUM_VALUE9317 = 70; + ENUM_VALUE9318 = 1000; + ENUM_VALUE9319 = 1001; + ENUM_VALUE9320 = 1002; + ENUM_VALUE9321 = 1003; + ENUM_VALUE9322 = 1004; + ENUM_VALUE9323 = 1005; + ENUM_VALUE9324 = 1006; + ENUM_VALUE9325 = 1007; + ENUM_VALUE9326 = 65; +} + +enum Enum10157 { + ENUM_VALUE10158 = 0; + ENUM_VALUE10159 = 1; + ENUM_VALUE10160 = 2; + ENUM_VALUE10161 = 3; + ENUM_VALUE10162 = 4; + ENUM_VALUE10163 = 5; + ENUM_VALUE10164 = 6; + ENUM_VALUE10165 = 7; + ENUM_VALUE10166 = 8; +} + +enum Enum10167 { + ENUM_VALUE10168 = 0; + ENUM_VALUE10169 = 1; + ENUM_VALUE10170 = 2; + ENUM_VALUE10171 = 3; + ENUM_VALUE10172 = 4; + ENUM_VALUE10173 = 5; + ENUM_VALUE10174 = 6; + ENUM_VALUE10175 = 7; + ENUM_VALUE10176 = 8; +} + +enum Enum8862 { + ENUM_VALUE8863 = 0; + ENUM_VALUE8864 = 1; + ENUM_VALUE8865 = 2; + ENUM_VALUE8866 = 3; + ENUM_VALUE8867 = 4; + ENUM_VALUE8868 = 5; + ENUM_VALUE8869 = 6; + ENUM_VALUE8870 = 7; + ENUM_VALUE8871 = 13; + ENUM_VALUE8872 = 14; + ENUM_VALUE8873 = 8; + ENUM_VALUE8874 = 9; + ENUM_VALUE8875 = 10; + ENUM_VALUE8876 = 11; + ENUM_VALUE8877 = 12; + ENUM_VALUE8878 = 15; +} + +enum Enum10325 { + ENUM_VALUE10326 = 0; + ENUM_VALUE10327 = 1; + ENUM_VALUE10328 = 2; + ENUM_VALUE10329 = 3; + ENUM_VALUE10330 = 4; + ENUM_VALUE10331 = 5; + ENUM_VALUE10332 = 6; + ENUM_VALUE10333 = 7; + ENUM_VALUE10334 = 8; +} + +enum Enum10335 { ENUM_VALUE10336 = 0; } + +enum Enum10337 { + ENUM_VALUE10338 = 0; + ENUM_VALUE10339 = 1; +} + +enum Enum10392 { + ENUM_VALUE10393 = 0; + ENUM_VALUE10394 = 1; + ENUM_VALUE10395 = 2; + ENUM_VALUE10396 = 3; + ENUM_VALUE10397 = 4; + ENUM_VALUE10398 = 5; + ENUM_VALUE10399 = 6; + ENUM_VALUE10400 = 7; + ENUM_VALUE10401 = 8; + ENUM_VALUE10402 = 15; + ENUM_VALUE10403 = 9; + ENUM_VALUE10404 = 10; + ENUM_VALUE10405 = 11; + ENUM_VALUE10406 = 12; + ENUM_VALUE10407 = 13; + ENUM_VALUE10408 = 14; + ENUM_VALUE10409 = 101; + ENUM_VALUE10410 = 102; +} + +enum Enum11107 { + ENUM_VALUE11108 = 0; + ENUM_VALUE11109 = 1; + ENUM_VALUE11110 = 2; + ENUM_VALUE11111 = 3; + ENUM_VALUE11112 = 4; + ENUM_VALUE11113 = 5; + ENUM_VALUE11114 = 6; + ENUM_VALUE11115 = 7; + ENUM_VALUE11116 = 8; + ENUM_VALUE11117 = 9; + ENUM_VALUE11118 = 10; + ENUM_VALUE11119 = 11; + ENUM_VALUE11120 = 12; + ENUM_VALUE11121 = 13; + ENUM_VALUE11122 = 14; + ENUM_VALUE11123 = 15; + ENUM_VALUE11124 = 16; + ENUM_VALUE11125 = 17; + ENUM_VALUE11126 = 18; + ENUM_VALUE11127 = 19; + ENUM_VALUE11128 = 20; + ENUM_VALUE11129 = 21; + ENUM_VALUE11130 = 22; + ENUM_VALUE11131 = 23; + ENUM_VALUE11132 = 24; + ENUM_VALUE11133 = 25; + ENUM_VALUE11134 = 26; + ENUM_VALUE11135 = 27; + ENUM_VALUE11136 = 28; + ENUM_VALUE11137 = 29; + ENUM_VALUE11138 = 30; + ENUM_VALUE11139 = 31; + ENUM_VALUE11140 = 32; + ENUM_VALUE11141 = 33; + ENUM_VALUE11142 = 34; + ENUM_VALUE11143 = 35; + ENUM_VALUE11144 = 36; + ENUM_VALUE11145 = 37; + ENUM_VALUE11146 = 38; + ENUM_VALUE11147 = 39; + ENUM_VALUE11148 = 40; + ENUM_VALUE11149 = 41; + ENUM_VALUE11150 = 42; + ENUM_VALUE11151 = 43; + ENUM_VALUE11152 = 44; + ENUM_VALUE11153 = 45; + ENUM_VALUE11154 = 46; + ENUM_VALUE11155 = 47; + ENUM_VALUE11156 = 48; + ENUM_VALUE11157 = 49; + ENUM_VALUE11158 = 50; + ENUM_VALUE11159 = 51; + ENUM_VALUE11160 = 52; + ENUM_VALUE11161 = 53; + ENUM_VALUE11162 = 54; + ENUM_VALUE11163 = 55; + ENUM_VALUE11164 = 56; + ENUM_VALUE11165 = 57; + ENUM_VALUE11166 = 58; + ENUM_VALUE11167 = 59; + ENUM_VALUE11168 = 60; + ENUM_VALUE11169 = 61; + ENUM_VALUE11170 = 62; + ENUM_VALUE11171 = 63; + ENUM_VALUE11172 = 64; + ENUM_VALUE11173 = 65; + ENUM_VALUE11174 = 66; + ENUM_VALUE11175 = 67; + ENUM_VALUE11176 = 68; + ENUM_VALUE11177 = 69; + ENUM_VALUE11178 = 70; + ENUM_VALUE11179 = 71; + ENUM_VALUE11180 = 72; + ENUM_VALUE11181 = 73; + ENUM_VALUE11182 = 74; + ENUM_VALUE11183 = 75; + ENUM_VALUE11184 = 76; + ENUM_VALUE11185 = 77; + ENUM_VALUE11186 = 78; + ENUM_VALUE11187 = 79; + ENUM_VALUE11188 = 80; + ENUM_VALUE11189 = 81; + ENUM_VALUE11190 = 82; + ENUM_VALUE11191 = 83; + ENUM_VALUE11192 = 84; + ENUM_VALUE11193 = 85; + ENUM_VALUE11194 = 86; + ENUM_VALUE11195 = 87; + ENUM_VALUE11196 = 88; + ENUM_VALUE11197 = 89; + ENUM_VALUE11198 = 90; + ENUM_VALUE11199 = 91; + ENUM_VALUE11200 = 92; + ENUM_VALUE11201 = 93; + ENUM_VALUE11202 = 94; + ENUM_VALUE11203 = 95; + ENUM_VALUE11204 = 96; + ENUM_VALUE11205 = 97; + ENUM_VALUE11206 = 98; + ENUM_VALUE11207 = 99; + ENUM_VALUE11208 = 100; + ENUM_VALUE11209 = 101; + ENUM_VALUE11210 = 102; + ENUM_VALUE11211 = 103; + ENUM_VALUE11212 = 104; + ENUM_VALUE11213 = 105; + ENUM_VALUE11214 = 106; + ENUM_VALUE11215 = 107; + ENUM_VALUE11216 = 108; + ENUM_VALUE11217 = 109; + ENUM_VALUE11218 = 110; + ENUM_VALUE11219 = 111; + ENUM_VALUE11220 = 112; + ENUM_VALUE11221 = 113; + ENUM_VALUE11222 = 114; + ENUM_VALUE11223 = 115; + ENUM_VALUE11224 = 116; + ENUM_VALUE11225 = 117; + ENUM_VALUE11226 = 118; + ENUM_VALUE11227 = 119; + ENUM_VALUE11228 = 120; + ENUM_VALUE11229 = 121; + ENUM_VALUE11230 = 122; + ENUM_VALUE11231 = 123; + ENUM_VALUE11232 = 124; + ENUM_VALUE11233 = 125; + ENUM_VALUE11234 = 126; + ENUM_VALUE11235 = 127; + ENUM_VALUE11236 = 128; + ENUM_VALUE11237 = 129; + ENUM_VALUE11238 = 130; + ENUM_VALUE11239 = 131; + ENUM_VALUE11240 = 132; + ENUM_VALUE11241 = 133; + ENUM_VALUE11242 = 134; + ENUM_VALUE11243 = 135; + ENUM_VALUE11244 = 136; + ENUM_VALUE11245 = 137; + ENUM_VALUE11246 = 138; + ENUM_VALUE11247 = 139; + ENUM_VALUE11248 = 140; + ENUM_VALUE11249 = 141; + ENUM_VALUE11250 = 142; + ENUM_VALUE11251 = 143; + ENUM_VALUE11252 = 144; + ENUM_VALUE11253 = 145; + ENUM_VALUE11254 = 146; + ENUM_VALUE11255 = 147; + ENUM_VALUE11256 = 148; + ENUM_VALUE11257 = 149; + ENUM_VALUE11258 = 150; + ENUM_VALUE11259 = 151; + ENUM_VALUE11260 = 152; + ENUM_VALUE11261 = 153; + ENUM_VALUE11262 = 154; + ENUM_VALUE11263 = 155; + ENUM_VALUE11264 = 156; + ENUM_VALUE11265 = 157; + ENUM_VALUE11266 = 158; + ENUM_VALUE11267 = 159; + ENUM_VALUE11268 = 160; + ENUM_VALUE11269 = 161; + ENUM_VALUE11270 = 163; + ENUM_VALUE11271 = 164; + ENUM_VALUE11272 = 165; + ENUM_VALUE11273 = 166; + ENUM_VALUE11274 = 167; + ENUM_VALUE11275 = 168; + ENUM_VALUE11276 = 169; + ENUM_VALUE11277 = 170; + ENUM_VALUE11278 = 171; + ENUM_VALUE11279 = 172; + ENUM_VALUE11280 = 173; + ENUM_VALUE11281 = 174; + ENUM_VALUE11282 = 175; + ENUM_VALUE11283 = 176; + ENUM_VALUE11284 = 177; + ENUM_VALUE11285 = 178; + ENUM_VALUE11286 = 179; + ENUM_VALUE11287 = 180; + ENUM_VALUE11288 = 181; + ENUM_VALUE11289 = 182; + ENUM_VALUE11290 = 183; + ENUM_VALUE11291 = 184; + ENUM_VALUE11292 = 185; + ENUM_VALUE11293 = 187; + ENUM_VALUE11294 = 188; + ENUM_VALUE11295 = 189; + ENUM_VALUE11296 = 190; + ENUM_VALUE11297 = 191; + ENUM_VALUE11298 = 192; + ENUM_VALUE11299 = 193; + ENUM_VALUE11300 = 194; + ENUM_VALUE11301 = 195; + ENUM_VALUE11302 = 196; + ENUM_VALUE11303 = 197; + ENUM_VALUE11304 = 198; + ENUM_VALUE11305 = 65535; + ENUM_VALUE11306 = 65536; + ENUM_VALUE11307 = 65537; + ENUM_VALUE11308 = 65538; + ENUM_VALUE11309 = 65539; + ENUM_VALUE11310 = 65540; + ENUM_VALUE11311 = 65541; + ENUM_VALUE11312 = 65542; + ENUM_VALUE11313 = 65543; + ENUM_VALUE11314 = 65544; + ENUM_VALUE11315 = 65545; + ENUM_VALUE11316 = 65546; + ENUM_VALUE11317 = 65547; + ENUM_VALUE11318 = 65548; + ENUM_VALUE11319 = 65549; + ENUM_VALUE11320 = 65550; + ENUM_VALUE11321 = 65551; + ENUM_VALUE11322 = 65552; + ENUM_VALUE11323 = 65553; + ENUM_VALUE11324 = 65554; + ENUM_VALUE11325 = 65555; + ENUM_VALUE11326 = 65556; + ENUM_VALUE11327 = 65557; + ENUM_VALUE11328 = 65558; + ENUM_VALUE11329 = 65559; + ENUM_VALUE11330 = 65560; + ENUM_VALUE11331 = 65561; + ENUM_VALUE11332 = 65562; + ENUM_VALUE11333 = 65563; + ENUM_VALUE11334 = 69632; + ENUM_VALUE11335 = 69633; + ENUM_VALUE11336 = 69634; + ENUM_VALUE11337 = 69635; + ENUM_VALUE11338 = 69636; + ENUM_VALUE11339 = 69637; + ENUM_VALUE11340 = 69638; + ENUM_VALUE11341 = 69639; + ENUM_VALUE11342 = 69640; + ENUM_VALUE11343 = 69641; + ENUM_VALUE11344 = 69642; + ENUM_VALUE11345 = 69643; + ENUM_VALUE11346 = 69644; + ENUM_VALUE11347 = 69645; + ENUM_VALUE11348 = 69646; + ENUM_VALUE11349 = 69647; + ENUM_VALUE11350 = 69648; + ENUM_VALUE11351 = 69649; + ENUM_VALUE11352 = 69650; + ENUM_VALUE11353 = 69651; + ENUM_VALUE11354 = 69652; + ENUM_VALUE11355 = 69653; + ENUM_VALUE11356 = 69654; + ENUM_VALUE11357 = 69655; + ENUM_VALUE11358 = 69656; + ENUM_VALUE11359 = 69657; + ENUM_VALUE11360 = 69658; + ENUM_VALUE11361 = 69659; + ENUM_VALUE11362 = 69660; + ENUM_VALUE11363 = 69661; + ENUM_VALUE11364 = 69662; + ENUM_VALUE11365 = 73728; + ENUM_VALUE11366 = 73729; + ENUM_VALUE11367 = 77824; + ENUM_VALUE11368 = 77825; + ENUM_VALUE11369 = 81920; + ENUM_VALUE11370 = 81921; + ENUM_VALUE11371 = 81922; + ENUM_VALUE11372 = 81923; + ENUM_VALUE11373 = 86016; + ENUM_VALUE11374 = 86017; + ENUM_VALUE11375 = 86018; + ENUM_VALUE11376 = 86019; + ENUM_VALUE11377 = 86020; + ENUM_VALUE11378 = 86021; + ENUM_VALUE11379 = 86022; + ENUM_VALUE11380 = 86023; + ENUM_VALUE11381 = 86024; + ENUM_VALUE11382 = 86025; + ENUM_VALUE11383 = 86026; + ENUM_VALUE11384 = 86027; + ENUM_VALUE11385 = 86028; + ENUM_VALUE11386 = 86029; + ENUM_VALUE11387 = 86030; + ENUM_VALUE11388 = 86031; + ENUM_VALUE11389 = 86032; + ENUM_VALUE11390 = 86033; + ENUM_VALUE11391 = 86034; + ENUM_VALUE11392 = 86035; + ENUM_VALUE11393 = 86036; + ENUM_VALUE11394 = 86037; + ENUM_VALUE11395 = 86038; + ENUM_VALUE11396 = 86039; + ENUM_VALUE11397 = 86040; + ENUM_VALUE11398 = 86041; + ENUM_VALUE11399 = 86042; + ENUM_VALUE11400 = 86043; + ENUM_VALUE11401 = 86044; + ENUM_VALUE11402 = 86045; + ENUM_VALUE11403 = 86046; + ENUM_VALUE11404 = 86047; + ENUM_VALUE11405 = 86048; + ENUM_VALUE11406 = 86049; + ENUM_VALUE11407 = 86050; + ENUM_VALUE11408 = 86051; + ENUM_VALUE11409 = 86052; + ENUM_VALUE11410 = 86053; + ENUM_VALUE11411 = 86054; + ENUM_VALUE11412 = 86055; + ENUM_VALUE11413 = 86056; + ENUM_VALUE11414 = 86057; + ENUM_VALUE11415 = 86058; + ENUM_VALUE11416 = 86059; + ENUM_VALUE11417 = 86060; + ENUM_VALUE11418 = 86061; + ENUM_VALUE11419 = 86062; + ENUM_VALUE11420 = 86063; + ENUM_VALUE11421 = 86064; + ENUM_VALUE11422 = 86065; + ENUM_VALUE11423 = 86066; + ENUM_VALUE11424 = 86067; + ENUM_VALUE11425 = 86068; + ENUM_VALUE11426 = 86069; + ENUM_VALUE11427 = 86070; + ENUM_VALUE11428 = 86071; + ENUM_VALUE11429 = 86072; + ENUM_VALUE11430 = 86073; + ENUM_VALUE11431 = 86074; + ENUM_VALUE11432 = 86077; + ENUM_VALUE11433 = 86078; + ENUM_VALUE11434 = 86079; + ENUM_VALUE11435 = 86080; + ENUM_VALUE11436 = 86081; + ENUM_VALUE11437 = 86082; + ENUM_VALUE11438 = 86083; + ENUM_VALUE11439 = 86084; + ENUM_VALUE11440 = 90112; + ENUM_VALUE11441 = 94208; + ENUM_VALUE11442 = 94209; + ENUM_VALUE11443 = 94210; + ENUM_VALUE11444 = 94211; + ENUM_VALUE11445 = 94212; + ENUM_VALUE11446 = 94213; + ENUM_VALUE11447 = 94214; + ENUM_VALUE11448 = 94215; + ENUM_VALUE11449 = 94216; + ENUM_VALUE11450 = 94217; + ENUM_VALUE11451 = 94218; + ENUM_VALUE11452 = 94219; + ENUM_VALUE11453 = 94220; + ENUM_VALUE11454 = 94221; + ENUM_VALUE11455 = 94222; + ENUM_VALUE11456 = 94223; + ENUM_VALUE11457 = 94224; + ENUM_VALUE11458 = 98304; + ENUM_VALUE11459 = 98305; + ENUM_VALUE11460 = 98306; + ENUM_VALUE11461 = 98307; + ENUM_VALUE11462 = 98308; + ENUM_VALUE11463 = 102400; + ENUM_VALUE11464 = 131072; + ENUM_VALUE11465 = 131073; + ENUM_VALUE11466 = 135168; + ENUM_VALUE11467 = 9439507; +} + +enum Enum11541 { + ENUM_VALUE11542 = -1; + ENUM_VALUE11543 = 0; + ENUM_VALUE11544 = 1; + ENUM_VALUE11545 = 2; + ENUM_VALUE11546 = 3; + ENUM_VALUE11547 = 4; + ENUM_VALUE11548 = 5; + ENUM_VALUE11549 = 6; + ENUM_VALUE11550 = 7; + ENUM_VALUE11551 = 8; + ENUM_VALUE11552 = 9; + ENUM_VALUE11553 = 10; + ENUM_VALUE11554 = 11; + ENUM_VALUE11555 = 12; + ENUM_VALUE11556 = 13; + ENUM_VALUE11557 = 14; + ENUM_VALUE11558 = 15; + ENUM_VALUE11559 = 16; + ENUM_VALUE11560 = 17; + ENUM_VALUE11561 = 18; + ENUM_VALUE11562 = 19; + ENUM_VALUE11563 = 20; + ENUM_VALUE11564 = 21; + ENUM_VALUE11565 = 22; + ENUM_VALUE11566 = 23; + ENUM_VALUE11567 = 24; + ENUM_VALUE11568 = 25; + ENUM_VALUE11569 = 26; + ENUM_VALUE11570 = 27; + ENUM_VALUE11571 = 28; + ENUM_VALUE11572 = 29; + ENUM_VALUE11573 = 30; + ENUM_VALUE11574 = 31; + ENUM_VALUE11575 = 32; + ENUM_VALUE11576 = 33; + ENUM_VALUE11577 = 34; + ENUM_VALUE11578 = 35; + ENUM_VALUE11579 = 36; + ENUM_VALUE11580 = 37; + ENUM_VALUE11581 = 38; + ENUM_VALUE11582 = 39; + ENUM_VALUE11583 = 40; + ENUM_VALUE11584 = 41; + ENUM_VALUE11585 = 42; + ENUM_VALUE11586 = 43; + ENUM_VALUE11587 = 44; + ENUM_VALUE11588 = 45; + ENUM_VALUE11589 = 46; + ENUM_VALUE11590 = 47; + ENUM_VALUE11591 = 48; + ENUM_VALUE11592 = 49; + ENUM_VALUE11593 = 50; + ENUM_VALUE11594 = 51; + ENUM_VALUE11595 = 52; + ENUM_VALUE11596 = 53; + ENUM_VALUE11597 = 54; + ENUM_VALUE11598 = 55; + ENUM_VALUE11599 = 56; + ENUM_VALUE11600 = 57; + ENUM_VALUE11601 = 58; + ENUM_VALUE11602 = 59; + ENUM_VALUE11603 = 60; + ENUM_VALUE11604 = 61; + ENUM_VALUE11605 = 62; + ENUM_VALUE11606 = 63; + ENUM_VALUE11607 = 64; + ENUM_VALUE11608 = 65; + ENUM_VALUE11609 = 66; + ENUM_VALUE11610 = 67; + ENUM_VALUE11611 = 68; + ENUM_VALUE11612 = 69; + ENUM_VALUE11613 = 70; + ENUM_VALUE11614 = 71; + ENUM_VALUE11615 = 72; + ENUM_VALUE11616 = 73; + ENUM_VALUE11617 = 74; + ENUM_VALUE11618 = 75; + ENUM_VALUE11619 = 76; + ENUM_VALUE11620 = 77; + ENUM_VALUE11621 = 78; + ENUM_VALUE11622 = 79; + ENUM_VALUE11623 = 80; + ENUM_VALUE11624 = 81; + ENUM_VALUE11625 = 82; + ENUM_VALUE11626 = 83; + ENUM_VALUE11627 = 84; + ENUM_VALUE11628 = 85; + ENUM_VALUE11629 = 86; + ENUM_VALUE11630 = 87; + ENUM_VALUE11631 = 88; + ENUM_VALUE11632 = 89; + ENUM_VALUE11633 = 90; + ENUM_VALUE11634 = 91; + ENUM_VALUE11635 = 92; + ENUM_VALUE11636 = 93; + ENUM_VALUE11637 = 94; + ENUM_VALUE11638 = 95; + ENUM_VALUE11639 = 96; + ENUM_VALUE11640 = 97; + ENUM_VALUE11641 = 98; + ENUM_VALUE11642 = 99; + ENUM_VALUE11643 = 100; + ENUM_VALUE11644 = 101; + ENUM_VALUE11645 = 102; + ENUM_VALUE11646 = 103; + ENUM_VALUE11647 = 104; + ENUM_VALUE11648 = 105; + ENUM_VALUE11649 = 106; + ENUM_VALUE11650 = 107; + ENUM_VALUE11651 = 108; + ENUM_VALUE11652 = 109; + ENUM_VALUE11653 = 110; + ENUM_VALUE11654 = 111; + ENUM_VALUE11655 = 112; + ENUM_VALUE11656 = 113; + ENUM_VALUE11657 = 114; + ENUM_VALUE11658 = 115; + ENUM_VALUE11659 = 116; + ENUM_VALUE11660 = 117; + ENUM_VALUE11661 = 118; + ENUM_VALUE11662 = 119; + ENUM_VALUE11663 = 120; + ENUM_VALUE11664 = 121; + ENUM_VALUE11665 = 122; + ENUM_VALUE11666 = 123; + ENUM_VALUE11667 = 124; + ENUM_VALUE11668 = 125; + ENUM_VALUE11669 = 126; + ENUM_VALUE11670 = 127; + ENUM_VALUE11671 = 128; + ENUM_VALUE11672 = 129; + ENUM_VALUE11673 = 130; + ENUM_VALUE11674 = 131; + ENUM_VALUE11675 = 132; + ENUM_VALUE11676 = 133; + ENUM_VALUE11677 = 134; + ENUM_VALUE11678 = 135; + ENUM_VALUE11679 = 136; + ENUM_VALUE11680 = 137; + ENUM_VALUE11681 = 138; + ENUM_VALUE11682 = 139; + ENUM_VALUE11683 = 140; + ENUM_VALUE11684 = 141; + ENUM_VALUE11685 = 142; + ENUM_VALUE11686 = 143; + ENUM_VALUE11687 = 144; + ENUM_VALUE11688 = 145; + ENUM_VALUE11689 = 146; + ENUM_VALUE11690 = 147; + ENUM_VALUE11691 = 148; + ENUM_VALUE11692 = 149; + ENUM_VALUE11693 = 150; + ENUM_VALUE11694 = 151; + ENUM_VALUE11695 = 152; + ENUM_VALUE11696 = 153; + ENUM_VALUE11697 = 154; + ENUM_VALUE11698 = 155; + ENUM_VALUE11699 = 156; + ENUM_VALUE11700 = 157; + ENUM_VALUE11701 = 158; + ENUM_VALUE11702 = 159; + ENUM_VALUE11703 = 160; + ENUM_VALUE11704 = 161; + ENUM_VALUE11705 = 162; + ENUM_VALUE11706 = 163; + ENUM_VALUE11707 = 164; + ENUM_VALUE11708 = 165; + ENUM_VALUE11709 = 166; + ENUM_VALUE11710 = 167; + ENUM_VALUE11711 = 168; + ENUM_VALUE11712 = 169; + ENUM_VALUE11713 = 170; + ENUM_VALUE11714 = 171; + ENUM_VALUE11715 = 172; + ENUM_VALUE11716 = 173; + ENUM_VALUE11717 = 174; + ENUM_VALUE11718 = 175; + ENUM_VALUE11719 = 176; + ENUM_VALUE11720 = 177; + ENUM_VALUE11721 = 178; + ENUM_VALUE11722 = 179; + ENUM_VALUE11723 = 180; + ENUM_VALUE11724 = 181; + ENUM_VALUE11725 = 182; + ENUM_VALUE11726 = 183; + ENUM_VALUE11727 = 184; + ENUM_VALUE11728 = 185; + ENUM_VALUE11729 = 186; + ENUM_VALUE11730 = 187; + ENUM_VALUE11731 = 188; + ENUM_VALUE11732 = 16777215; +} + +enum Enum11468 { + ENUM_VALUE11469 = -99; + ENUM_VALUE11470 = 0; + ENUM_VALUE11471 = 1; + ENUM_VALUE11472 = 2; + ENUM_VALUE11473 = 3; + ENUM_VALUE11474 = 4; + ENUM_VALUE11475 = 28; + ENUM_VALUE11476 = 22; + ENUM_VALUE11477 = 38; + ENUM_VALUE11478 = 512; + ENUM_VALUE11479 = 2048; + ENUM_VALUE11480 = 66; + ENUM_VALUE11481 = 578; + ENUM_VALUE11482 = 77; + ENUM_VALUE11483 = 88; + ENUM_VALUE11484 = 100; + ENUM_VALUE11485 = 110; + ENUM_VALUE11486 = 2158; + ENUM_VALUE11487 = 122; + ENUM_VALUE11488 = 2170; + ENUM_VALUE11489 = 144; + ENUM_VALUE11490 = 244; + ENUM_VALUE11491 = 2292; + ENUM_VALUE11492 = 44; +} + +enum Enum11022 { + ENUM_VALUE11023 = 0; + ENUM_VALUE11024 = 1; + ENUM_VALUE11025 = 2; + ENUM_VALUE11026 = 3; + ENUM_VALUE11027 = 4; + ENUM_VALUE11028 = 5; + ENUM_VALUE11029 = 6; + ENUM_VALUE11030 = 7; + ENUM_VALUE11031 = 8; + ENUM_VALUE11032 = 9; + ENUM_VALUE11033 = 10; + ENUM_VALUE11034 = 11; + ENUM_VALUE11035 = 12; + ENUM_VALUE11036 = 13; + ENUM_VALUE11037 = 14; + ENUM_VALUE11038 = 15; + ENUM_VALUE11039 = 16; + ENUM_VALUE11040 = 17; + ENUM_VALUE11041 = 18; + ENUM_VALUE11042 = 19; + ENUM_VALUE11043 = 20; + ENUM_VALUE11044 = 21; + ENUM_VALUE11045 = 22; + ENUM_VALUE11046 = 23; + ENUM_VALUE11047 = 24; + ENUM_VALUE11048 = 25; + ENUM_VALUE11049 = 26; + ENUM_VALUE11050 = 27; + ENUM_VALUE11051 = 28; + ENUM_VALUE11052 = 29; + ENUM_VALUE11053 = 30; + ENUM_VALUE11054 = 31; + ENUM_VALUE11055 = 32; + ENUM_VALUE11056 = 33; + ENUM_VALUE11057 = 34; + ENUM_VALUE11058 = 35; + ENUM_VALUE11059 = 36; + ENUM_VALUE11060 = 37; + ENUM_VALUE11061 = 38; + ENUM_VALUE11062 = 39; + ENUM_VALUE11063 = 40; + ENUM_VALUE11064 = 41; + ENUM_VALUE11065 = 42; + ENUM_VALUE11066 = 43; + ENUM_VALUE11067 = 44; + ENUM_VALUE11068 = 45; + ENUM_VALUE11069 = 46; + ENUM_VALUE11070 = 47; + ENUM_VALUE11071 = 48; + ENUM_VALUE11072 = 49; + ENUM_VALUE11073 = 50; + ENUM_VALUE11074 = 51; + ENUM_VALUE11075 = 52; + ENUM_VALUE11076 = 53; + ENUM_VALUE11077 = 54; + ENUM_VALUE11078 = 55; + ENUM_VALUE11079 = 56; + ENUM_VALUE11080 = 57; + ENUM_VALUE11081 = 58; + ENUM_VALUE11082 = 59; + ENUM_VALUE11083 = 60; + ENUM_VALUE11084 = 61; + ENUM_VALUE11085 = 62; + ENUM_VALUE11086 = 63; + ENUM_VALUE11087 = 64; + ENUM_VALUE11088 = 65; + ENUM_VALUE11089 = 66; + ENUM_VALUE11090 = 67; + ENUM_VALUE11091 = 68; + ENUM_VALUE11092 = 69; + ENUM_VALUE11093 = 70; + ENUM_VALUE11094 = 71; + ENUM_VALUE11095 = 72; + ENUM_VALUE11096 = 73; + ENUM_VALUE11097 = 74; + ENUM_VALUE11098 = 75; + ENUM_VALUE11099 = 76; + ENUM_VALUE11100 = 77; + ENUM_VALUE11101 = 78; + ENUM_VALUE11102 = 79; + ENUM_VALUE11103 = 80; + ENUM_VALUE11104 = 81; + ENUM_VALUE11105 = 82; + ENUM_VALUE11106 = 83; +} + +enum Enum12670 { + ENUM_VALUE12671 = 0; + ENUM_VALUE12672 = 1; + ENUM_VALUE12673 = 2; +} + +enum Enum12871 { + ENUM_VALUE12872 = 1; + ENUM_VALUE12873 = 2; + ENUM_VALUE12874 = 3; + ENUM_VALUE12875 = 4; + ENUM_VALUE12876 = 5; + ENUM_VALUE12877 = 6; +} + +enum Enum13092 { + ENUM_VALUE13093 = 1; + ENUM_VALUE13094 = 2; + ENUM_VALUE13095 = 3; +} + +enum Enum13146 { + ENUM_VALUE13147 = 0; + ENUM_VALUE13148 = 1; + ENUM_VALUE13149 = 2; + ENUM_VALUE13150 = 3; +} + +enum Enum16042 { + ENUM_VALUE16043 = 0; + ENUM_VALUE16044 = 1; + ENUM_VALUE16045 = 17; + ENUM_VALUE16046 = 273; + ENUM_VALUE16047 = 274; + ENUM_VALUE16048 = 4385; + ENUM_VALUE16049 = 4386; + ENUM_VALUE16050 = 4387; + ENUM_VALUE16051 = 4388; + ENUM_VALUE16052 = 4389; + ENUM_VALUE16053 = 4390; + ENUM_VALUE16054 = 4391; + ENUM_VALUE16055 = 4392; + ENUM_VALUE16056 = 4393; + ENUM_VALUE16057 = 276; + ENUM_VALUE16058 = 277; + ENUM_VALUE16059 = 18; + ENUM_VALUE16060 = 289; + ENUM_VALUE16061 = 291; + ENUM_VALUE16062 = 4657; + ENUM_VALUE16063 = 74513; + ENUM_VALUE16064 = 4658; + ENUM_VALUE16065 = 4659; + ENUM_VALUE16066 = 4660; + ENUM_VALUE16067 = 4661; + ENUM_VALUE16068 = 4662; + ENUM_VALUE16069 = 4663; + ENUM_VALUE16070 = 4664; + ENUM_VALUE16071 = 292; + ENUM_VALUE16072 = 4673; + ENUM_VALUE16073 = 4674; + ENUM_VALUE16074 = 293; + ENUM_VALUE16075 = 19; + ENUM_VALUE16076 = 20; + ENUM_VALUE16077 = 321; + ENUM_VALUE16078 = 5137; + ENUM_VALUE16079 = 5138; + ENUM_VALUE16080 = 5139; + ENUM_VALUE16081 = 5140; + ENUM_VALUE16082 = 5141; + ENUM_VALUE16083 = 5142; + ENUM_VALUE16084 = 82273; + ENUM_VALUE16085 = 82274; + ENUM_VALUE16086 = 82275; + ENUM_VALUE16087 = 82276; + ENUM_VALUE16088 = 82277; + ENUM_VALUE16089 = 82278; + ENUM_VALUE16090 = 5143; + ENUM_VALUE16091 = 5144; + ENUM_VALUE16092 = 5145; + ENUM_VALUE16093 = 5146; + ENUM_VALUE16094 = 82337; + ENUM_VALUE16095 = 5147; + ENUM_VALUE16096 = 5148; + ENUM_VALUE16097 = 322; + ENUM_VALUE16098 = 323; + ENUM_VALUE16099 = 324; + ENUM_VALUE16100 = 325; + ENUM_VALUE16101 = 326; + ENUM_VALUE16102 = 327; + ENUM_VALUE16103 = 328; + ENUM_VALUE16104 = 21; + ENUM_VALUE16105 = 337; + ENUM_VALUE16106 = 22; + ENUM_VALUE16107 = 23; + ENUM_VALUE16108 = 24; + ENUM_VALUE16109 = 2; + ENUM_VALUE16110 = 33; + ENUM_VALUE16111 = 34; + ENUM_VALUE16112 = 545; + ENUM_VALUE16113 = 8721; + ENUM_VALUE16114 = 8723; + ENUM_VALUE16115 = 8724; + ENUM_VALUE16116 = 546; + ENUM_VALUE16117 = 8739; + ENUM_VALUE16118 = 8740; + ENUM_VALUE16119 = 547; + ENUM_VALUE16120 = 548; + ENUM_VALUE16121 = 549; + ENUM_VALUE16122 = 550; + ENUM_VALUE16123 = 551; + ENUM_VALUE16124 = 552; + ENUM_VALUE16125 = 553; + ENUM_VALUE16126 = 35; + ENUM_VALUE16127 = 36; + ENUM_VALUE16128 = 37; + ENUM_VALUE16129 = 593; + ENUM_VALUE16130 = 594; + ENUM_VALUE16131 = 595; + ENUM_VALUE16132 = 596; + ENUM_VALUE16133 = 597; + ENUM_VALUE16134 = 38; + ENUM_VALUE16135 = 609; + ENUM_VALUE16136 = 610; + ENUM_VALUE16137 = 617; + ENUM_VALUE16138 = 614; + ENUM_VALUE16139 = 615; + ENUM_VALUE16140 = 616; + ENUM_VALUE16141 = 618; + ENUM_VALUE16142 = 620; + ENUM_VALUE16143 = 9937; + ENUM_VALUE16144 = 9938; + ENUM_VALUE16145 = 9939; + ENUM_VALUE16146 = 9940; + ENUM_VALUE16147 = 9941; + ENUM_VALUE16148 = 39; + ENUM_VALUE16149 = 40; + ENUM_VALUE16150 = 41; + ENUM_VALUE16151 = 42; + ENUM_VALUE16152 = 43; + ENUM_VALUE16153 = 44; + ENUM_VALUE16154 = 45; + ENUM_VALUE16155 = 11793; + ENUM_VALUE16156 = 3; + ENUM_VALUE16157 = 49; + ENUM_VALUE16158 = 50; + ENUM_VALUE16159 = 51; + ENUM_VALUE16160 = 817; + ENUM_VALUE16161 = 818; + ENUM_VALUE16162 = 819; + ENUM_VALUE16163 = 52; + ENUM_VALUE16164 = 833; + ENUM_VALUE16165 = 53; + ENUM_VALUE16166 = 54; + ENUM_VALUE16167 = 4; + ENUM_VALUE16168 = 1041; + ENUM_VALUE16169 = 16657; + ENUM_VALUE16170 = 16658; + ENUM_VALUE16171 = 16659; + ENUM_VALUE16172 = 16660; + ENUM_VALUE16173 = 16661; + ENUM_VALUE16174 = 1042; + ENUM_VALUE16175 = 16673; + ENUM_VALUE16176 = 1043; + ENUM_VALUE16177 = 16689; + ENUM_VALUE16178 = 16690; + ENUM_VALUE16179 = 16691; + ENUM_VALUE16180 = 16692; + ENUM_VALUE16181 = 16693; + ENUM_VALUE16182 = 16694; + ENUM_VALUE16183 = 16695; + ENUM_VALUE16184 = 1044; + ENUM_VALUE16185 = 16705; + ENUM_VALUE16186 = 16706; + ENUM_VALUE16187 = 16707; + ENUM_VALUE16188 = 16708; + ENUM_VALUE16189 = 16709; + ENUM_VALUE16190 = 16710; + ENUM_VALUE16191 = 16711; + ENUM_VALUE16192 = 16712; + ENUM_VALUE16193 = 16713; + ENUM_VALUE16194 = 1046; + ENUM_VALUE16195 = 16737; + ENUM_VALUE16196 = 1047; + ENUM_VALUE16197 = 16753; + ENUM_VALUE16198 = 268049; + ENUM_VALUE16199 = 268050; + ENUM_VALUE16200 = 268051; + ENUM_VALUE16201 = 268052; + ENUM_VALUE16202 = 1048; + ENUM_VALUE16203 = 16769; + ENUM_VALUE16204 = 16770; + ENUM_VALUE16205 = 16771; + ENUM_VALUE16206 = 16772; + ENUM_VALUE16207 = 16773; + ENUM_VALUE16208 = 1049; + ENUM_VALUE16209 = 1056; + ENUM_VALUE16210 = 1058; + ENUM_VALUE16211 = 1059; + ENUM_VALUE16212 = 1060; + ENUM_VALUE16213 = 1061; + ENUM_VALUE16214 = 5; + ENUM_VALUE16215 = 6; + ENUM_VALUE16216 = 97; + ENUM_VALUE16217 = 98; + ENUM_VALUE16218 = 99; + ENUM_VALUE16219 = 100; + ENUM_VALUE16220 = 101; + ENUM_VALUE16221 = 102; + ENUM_VALUE16222 = 103; + ENUM_VALUE16223 = 104; + ENUM_VALUE16224 = 105; + ENUM_VALUE16225 = 106; + ENUM_VALUE16226 = 108; + ENUM_VALUE16227 = 1729; + ENUM_VALUE16228 = 1730; + ENUM_VALUE16229 = 1731; + ENUM_VALUE16230 = 7; + ENUM_VALUE16231 = 8; + ENUM_VALUE16232 = 9; + ENUM_VALUE16233 = 10; + ENUM_VALUE16234 = 161; + ENUM_VALUE16235 = 2577; + ENUM_VALUE16236 = 41233; + ENUM_VALUE16237 = 41234; + ENUM_VALUE16238 = 2578; + ENUM_VALUE16239 = 2579; + ENUM_VALUE16240 = 41265; + ENUM_VALUE16241 = 2580; + ENUM_VALUE16242 = 2581; + ENUM_VALUE16243 = 41297; + ENUM_VALUE16244 = 41298; + ENUM_VALUE16245 = 41299; + ENUM_VALUE16246 = 41300; + ENUM_VALUE16247 = 2582; + ENUM_VALUE16248 = 2583; + ENUM_VALUE16249 = 2584; + ENUM_VALUE16250 = 162; + ENUM_VALUE16251 = 2593; + ENUM_VALUE16252 = 41489; + ENUM_VALUE16253 = 663825; + ENUM_VALUE16254 = 663826; + ENUM_VALUE16255 = 41490; + ENUM_VALUE16256 = 41491; + ENUM_VALUE16257 = 41492; + ENUM_VALUE16258 = 663873; + ENUM_VALUE16259 = 2594; + ENUM_VALUE16260 = 41505; + ENUM_VALUE16261 = 41506; + ENUM_VALUE16262 = 41507; + ENUM_VALUE16263 = 2595; + ENUM_VALUE16264 = 41521; + ENUM_VALUE16265 = 41522; + ENUM_VALUE16266 = 41523; + ENUM_VALUE16267 = 41524; + ENUM_VALUE16268 = 41525; + ENUM_VALUE16269 = 664401; + ENUM_VALUE16270 = 664402; + ENUM_VALUE16271 = 41526; + ENUM_VALUE16272 = 41527; + ENUM_VALUE16273 = 2596; + ENUM_VALUE16274 = 2597; + ENUM_VALUE16275 = 2598; + ENUM_VALUE16276 = 41569; + ENUM_VALUE16277 = 41570; + ENUM_VALUE16278 = 41571; + ENUM_VALUE16279 = 41572; + ENUM_VALUE16280 = 41573; + ENUM_VALUE16281 = 665169; + ENUM_VALUE16282 = 665170; + ENUM_VALUE16283 = 665171; + ENUM_VALUE16284 = 665172; + ENUM_VALUE16285 = 2599; + ENUM_VALUE16286 = 2600; + ENUM_VALUE16287 = 2601; + ENUM_VALUE16288 = 2603; + ENUM_VALUE16289 = 2604; + ENUM_VALUE16290 = 163; + ENUM_VALUE16291 = 2608; + ENUM_VALUE16292 = 2609; + ENUM_VALUE16293 = 2610; + ENUM_VALUE16294 = 2611; + ENUM_VALUE16295 = 2612; + ENUM_VALUE16296 = 164; + ENUM_VALUE16297 = 2625; + ENUM_VALUE16298 = 2626; + ENUM_VALUE16299 = 42017; + ENUM_VALUE16300 = 42018; + ENUM_VALUE16301 = 42019; + ENUM_VALUE16302 = 2627; + ENUM_VALUE16303 = 2628; + ENUM_VALUE16304 = 165; + ENUM_VALUE16305 = 2641; + ENUM_VALUE16306 = 42257; + ENUM_VALUE16307 = 42258; + ENUM_VALUE16308 = 2642; + ENUM_VALUE16309 = 2643; + ENUM_VALUE16310 = 2644; + ENUM_VALUE16311 = 2646; + ENUM_VALUE16312 = 2647; + ENUM_VALUE16313 = 42353; + ENUM_VALUE16314 = 2648; + ENUM_VALUE16315 = 2649; + ENUM_VALUE16316 = 2650; + ENUM_VALUE16317 = 2651; + ENUM_VALUE16318 = 2652; + ENUM_VALUE16319 = 2653; + ENUM_VALUE16320 = 2654; + ENUM_VALUE16321 = 42481; + ENUM_VALUE16322 = 42482; + ENUM_VALUE16323 = 42483; + ENUM_VALUE16324 = 166; + ENUM_VALUE16325 = 2657; + ENUM_VALUE16326 = 2658; + ENUM_VALUE16327 = 42529; + ENUM_VALUE16328 = 2659; + ENUM_VALUE16329 = 2660; + ENUM_VALUE16330 = 2661; + ENUM_VALUE16331 = 2662; + ENUM_VALUE16332 = 2663; + ENUM_VALUE16333 = 42609; + ENUM_VALUE16334 = 2664; + ENUM_VALUE16335 = 2665; + ENUM_VALUE16336 = 42753; + ENUM_VALUE16337 = 42754; + ENUM_VALUE16338 = 42755; + ENUM_VALUE16339 = 11; + ENUM_VALUE16340 = 177; + ENUM_VALUE16341 = 2833; + ENUM_VALUE16342 = 179; + ENUM_VALUE16343 = 180; + ENUM_VALUE16344 = 2881; + ENUM_VALUE16345 = 182; + ENUM_VALUE16346 = 183; + ENUM_VALUE16347 = 12; + ENUM_VALUE16348 = 3089; + ENUM_VALUE16349 = 194; + ENUM_VALUE16350 = 195; + ENUM_VALUE16351 = 196; + ENUM_VALUE16352 = 198; + ENUM_VALUE16353 = 3169; + ENUM_VALUE16354 = 199; + ENUM_VALUE16355 = 200; + ENUM_VALUE16356 = 208; + ENUM_VALUE16357 = 3329; + ENUM_VALUE16358 = 3330; + ENUM_VALUE16359 = 3331; + ENUM_VALUE16360 = 209; + ENUM_VALUE16361 = 210; + ENUM_VALUE16362 = 211; + ENUM_VALUE16363 = 3377; + ENUM_VALUE16364 = 3378; + ENUM_VALUE16365 = 3379; + ENUM_VALUE16366 = 3380; + ENUM_VALUE16367 = 3381; + ENUM_VALUE16368 = 865809; + ENUM_VALUE16369 = 865810; + ENUM_VALUE16370 = 865811; + ENUM_VALUE16371 = 865812; + ENUM_VALUE16372 = 865813; + ENUM_VALUE16373 = 865814; + ENUM_VALUE16374 = 865815; + ENUM_VALUE16375 = 865816; + ENUM_VALUE16376 = 865817; + ENUM_VALUE16377 = 865818; + ENUM_VALUE16378 = 865819; + ENUM_VALUE16379 = 865820; + ENUM_VALUE16380 = 865821; + ENUM_VALUE16381 = 865822; + ENUM_VALUE16382 = 865823; + ENUM_VALUE16383 = 865824; + ENUM_VALUE16384 = 865825; + ENUM_VALUE16385 = 865826; + ENUM_VALUE16386 = 865827; + ENUM_VALUE16387 = 865828; + ENUM_VALUE16388 = 865829; + ENUM_VALUE16389 = 212; + ENUM_VALUE16390 = 3393; + ENUM_VALUE16391 = 3394; + ENUM_VALUE16392 = 3395; + ENUM_VALUE16393 = 213; + ENUM_VALUE16394 = 214; + ENUM_VALUE16395 = 215; + ENUM_VALUE16396 = 3441; + ENUM_VALUE16397 = 3442; + ENUM_VALUE16398 = 216; + ENUM_VALUE16399 = 217; + ENUM_VALUE16400 = 3473; + ENUM_VALUE16401 = 3474; + ENUM_VALUE16402 = 3475; + ENUM_VALUE16403 = 254; + ENUM_VALUE16404 = 255; +} + +enum Enum16553 { + ENUM_VALUE16554 = 0; + ENUM_VALUE16555 = 1; + ENUM_VALUE16556 = 2; + ENUM_VALUE16557 = 3; + ENUM_VALUE16558 = 4; + ENUM_VALUE16559 = 5; + ENUM_VALUE16560 = 6; + ENUM_VALUE16561 = 7; + ENUM_VALUE16562 = 8; + ENUM_VALUE16563 = 9; +} + +enum Enum16728 { + ENUM_VALUE16729 = 1; + ENUM_VALUE16730 = 2; + ENUM_VALUE16731 = 3; +} + +enum Enum16732 { + ENUM_VALUE16733 = 1; + ENUM_VALUE16734 = 2; + ENUM_VALUE16735 = 3; + ENUM_VALUE16736 = 4; + ENUM_VALUE16737 = 5; +} + +enum Enum16738 { + ENUM_VALUE16739 = 1; + ENUM_VALUE16740 = 2; + ENUM_VALUE16741 = 3; + ENUM_VALUE16742 = 4; + ENUM_VALUE16743 = 5; + ENUM_VALUE16744 = 6; + ENUM_VALUE16745 = 7; +} + +enum Enum16698 { + ENUM_VALUE16699 = -1; + ENUM_VALUE16700 = 100; + ENUM_VALUE16701 = 2; + ENUM_VALUE16702 = 0; + ENUM_VALUE16703 = 1; + ENUM_VALUE16704 = 4; + ENUM_VALUE16705 = 11; + ENUM_VALUE16706 = 12; + ENUM_VALUE16707 = 3; + ENUM_VALUE16708 = 5; + ENUM_VALUE16709 = 6; + ENUM_VALUE16710 = 7; + ENUM_VALUE16711 = 8; + ENUM_VALUE16712 = 9; + ENUM_VALUE16713 = 10; + ENUM_VALUE16714 = 13; + ENUM_VALUE16715 = 14; + ENUM_VALUE16716 = 15; + ENUM_VALUE16717 = 16; + ENUM_VALUE16718 = 18; + ENUM_VALUE16719 = 17; + ENUM_VALUE16720 = 19; + ENUM_VALUE16721 = 20; +} + +enum Enum16819 { + ENUM_VALUE16820 = 0; + ENUM_VALUE16821 = 1; + ENUM_VALUE16822 = 2; + ENUM_VALUE16823 = 3; + ENUM_VALUE16824 = 4; + ENUM_VALUE16825 = 5; +} + +enum Enum16925 { + ENUM_VALUE16926 = 0; + ENUM_VALUE16927 = 1; + ENUM_VALUE16928 = 2; + ENUM_VALUE16929 = 3; + ENUM_VALUE16930 = 4; + ENUM_VALUE16931 = 5; + ENUM_VALUE16932 = 6; + ENUM_VALUE16933 = 7; + ENUM_VALUE16934 = 8; + ENUM_VALUE16935 = 9; + ENUM_VALUE16936 = 10; + ENUM_VALUE16937 = 11; + ENUM_VALUE16938 = 12; + ENUM_VALUE16939 = 13; +} + +enum Enum22854 { + ENUM_VALUE22855 = 0; + ENUM_VALUE22856 = 1; +} + +enum Enum24361 { + ENUM_VALUE24362 = 0; + ENUM_VALUE24363 = 1; + ENUM_VALUE24364 = 2; + ENUM_VALUE24365 = 3; +} + +enum Enum16891 { + ENUM_VALUE16892 = 0; + ENUM_VALUE16893 = 1; + ENUM_VALUE16894 = 2; + ENUM_VALUE16895 = 3; + ENUM_VALUE16896 = 4; + ENUM_VALUE16897 = 5; + ENUM_VALUE16898 = 6; + ENUM_VALUE16899 = 7; + ENUM_VALUE16900 = 8; + ENUM_VALUE16901 = 9; + ENUM_VALUE16902 = 10; + ENUM_VALUE16903 = 11; + ENUM_VALUE16904 = 12; + ENUM_VALUE16905 = 13; + ENUM_VALUE16906 = 14; + ENUM_VALUE16907 = 15; + ENUM_VALUE16908 = 16; + ENUM_VALUE16909 = 17; + ENUM_VALUE16910 = 18; + ENUM_VALUE16911 = 19; + ENUM_VALUE16912 = 20; + ENUM_VALUE16913 = 21; + ENUM_VALUE16914 = 22; + ENUM_VALUE16915 = 23; + ENUM_VALUE16916 = 24; + ENUM_VALUE16917 = 25; + ENUM_VALUE16918 = 26; + ENUM_VALUE16919 = 27; + ENUM_VALUE16920 = 28; + ENUM_VALUE16921 = 29; + ENUM_VALUE16922 = 30; + ENUM_VALUE16923 = 31; +} + +enum Enum27361 { + ENUM_VALUE27362 = 0; + ENUM_VALUE27363 = 1; + ENUM_VALUE27364 = 2; + ENUM_VALUE27365 = 3; + ENUM_VALUE27366 = 4; +} + +enum Enum33960 { + ENUM_VALUE33961 = 0; + ENUM_VALUE33962 = 1; + ENUM_VALUE33963 = 2; + ENUM_VALUE33964 = 3; + ENUM_VALUE33965 = 4; + ENUM_VALUE33966 = 5; + ENUM_VALUE33967 = 6; +} + +enum Enum34388 { ENUM_VALUE34389 = 1; } + +enum Enum35477 { + ENUM_VALUE35478 = 4; + ENUM_VALUE35479 = 3; + ENUM_VALUE35480 = 2; + ENUM_VALUE35481 = 1; + ENUM_VALUE35482 = 0; +} + +enum Enum35507 { + ENUM_VALUE35508 = 0; + ENUM_VALUE35509 = 1; + ENUM_VALUE35510 = 2; + ENUM_VALUE35511 = 3; + ENUM_VALUE35512 = 4; + ENUM_VALUE35513 = 5; + ENUM_VALUE35514 = 6; + ENUM_VALUE35515 = 7; + ENUM_VALUE35516 = 8; + ENUM_VALUE35517 = 9; +} + +enum Enum36860 { + ENUM_VALUE36861 = 0; + ENUM_VALUE36862 = 1; + ENUM_VALUE36863 = 2; + ENUM_VALUE36864 = 3; + ENUM_VALUE36865 = 4; + ENUM_VALUE36866 = 5; + ENUM_VALUE36867 = 6; + ENUM_VALUE36868 = 7; +} + +enum Enum36890 { + ENUM_VALUE36891 = 0; + ENUM_VALUE36892 = 1; +} diff --git a/benchmarks/datasets/google_message4/benchmark_message4.proto b/benchmarks/datasets/google_message4/benchmark_message4.proto new file mode 100644 index 0000000000000..424ed10811691 --- /dev/null +++ b/benchmarks/datasets/google_message4/benchmark_message4.proto @@ -0,0 +1,484 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// LINT: ALLOW_GROUPS + +syntax = "proto2"; + +package benchmarks.google_message4; + +import "datasets/google_message4/benchmark_message4_1.proto"; +import "datasets/google_message4/benchmark_message4_2.proto"; +import "datasets/google_message4/benchmark_message4_3.proto"; + +option cc_enable_arenas = true; +option java_package = "com.google.protobuf.benchmarks"; + +message GoogleMessage4 { + optional int32 field37503 = 1; + optional .benchmarks.google_message4.UnusedEmptyMessage field37504 = 2; + optional .benchmarks.google_message4.UnusedEmptyMessage field37505 = 3; + optional .benchmarks.google_message4.UnusedEmptyMessage field37506 = 4; + optional .benchmarks.google_message4.UnusedEmptyMessage field37507 = 5; + optional .benchmarks.google_message4.Message37489 field37508 = 6; + optional .benchmarks.google_message4.UnusedEmptyMessage field37509 = 7; + optional .benchmarks.google_message4.UnusedEmptyMessage field37510 = 8; + optional .benchmarks.google_message4.UnusedEmptyMessage field37511 = 9; + optional .benchmarks.google_message4.UnusedEmptyMessage field37512 = 10; + optional .benchmarks.google_message4.UnusedEmptyMessage field37513 = 11; + optional .benchmarks.google_message4.UnusedEmptyMessage field37514 = 12; + optional .benchmarks.google_message4.UnusedEmptyMessage field37515 = 13; + optional .benchmarks.google_message4.UnusedEmptyMessage field37516 = 14; + optional .benchmarks.google_message4.UnusedEmptyMessage field37517 = 15; + optional .benchmarks.google_message4.UnusedEmptyMessage field37518 = 16; +} + +message Message37489 { + optional .benchmarks.google_message4.Message2517 field37534 = 3; + optional .benchmarks.google_message4.Message7330 field37535 = 4; + optional .benchmarks.google_message4.Message8815 field37536 = 6; + optional .benchmarks.google_message4.Message8817 field37537 = 7; + optional .benchmarks.google_message4.Message8835 field37538 = 8; + optional .benchmarks.google_message4.Message8848 field37539 = 9; + optional .benchmarks.google_message4.Message8856 field37540 = 11; + optional .benchmarks.google_message4.Message12717 field37541 = 15; + optional .benchmarks.google_message4.Message12748 field37542 = 20; + optional .benchmarks.google_message4.Message7319 field37543 = 22; + optional .benchmarks.google_message4.Message12908 field37544 = 24; + optional .benchmarks.google_message4.Message12910 field37545 = 25; + optional .benchmarks.google_message4.Message12960 field37546 = 30; + optional .benchmarks.google_message4.Message176 field37547 = 33; + optional .benchmarks.google_message4.Message13000 field37548 = 34; + optional .benchmarks.google_message4.Message13035 field37549 = 35; + optional .benchmarks.google_message4.Message37331 field37550 = 36; + optional .benchmarks.google_message4.Message37329 field37551 = 37; + optional .benchmarks.google_message4.Message37327 field37552 = 38; + optional .benchmarks.google_message4.Message37333 field37553 = 39; + optional .benchmarks.google_message4.Message37335 field37554 = 40; +} + +message Message7319 { + optional .benchmarks.google_message4.UnusedEmptyMessage field7321 = 1; + optional .benchmarks.google_message4.UnusedEmptyMessage field7322 = 7; +} + +message Message12717 { + optional .benchmarks.google_message4.UnusedEmptyMessage field12719 = 1; + optional string field12720 = 2; + optional uint32 field12721 = 3; + optional .benchmarks.google_message4.Message11976 field12722 = 4; + repeated .benchmarks.google_message4.Message11948 field12723 = 5; + optional .benchmarks.google_message4.Message11947 field12724 = 6; + optional .benchmarks.google_message4.Message12687 field12725 = 7; + repeated .benchmarks.google_message4.Message11948 field12726 = 8; + optional int64 field12727 = 9; +} + +message Message37331 { + optional .benchmarks.google_message4.UnusedEmptyMessage field37367 = 4; + required .benchmarks.google_message4.Message37326 field37368 = 1; + required int64 field37369 = 2; + required bytes field37370 = 3; +} + +message Message8815 { + optional .benchmarks.google_message4.UnusedEmptyMessage field8819 = 1; + repeated .benchmarks.google_message4.Message8768 field8820 = 2; + optional bool field8821 = 3; +} + +message Message7330 { + optional .benchmarks.google_message4.UnusedEmptyMessage field7332 = 1; + optional .benchmarks.google_message4.Message3069 field7333 = 2; + optional .benchmarks.google_message4.Message7320 field7334 = 3; + optional .benchmarks.google_message4.UnusedEmptyMessage field7335 = 4; + optional bool field7336 = 5; + optional int64 field7337 = 6; +} + +message Message12960 { + optional .benchmarks.google_message4.UnusedEmptyMessage field12962 = 1; + optional .benchmarks.google_message4.Message12948 field12963 = 2; +} + +message Message176 { + required string field408 = 1; + optional int32 field409 = 4; + optional string field410 = 50; + optional int32 field411 = 2; + optional uint64 field412 = 47; + optional string field413 = 56; + optional int32 field414 = 24; + optional string field415 = 21; + optional bytes field416 = 3; + optional string field417 = 57; + optional int32 field418 = 51; + optional float field419 = 7; + optional bool field420 = 5; + optional bool field421 = 28; + optional int32 field422 = 6; + repeated int32 field423 = 40; + optional .benchmarks.google_message4.UnusedEmptyMessage field424 = 41; + optional bool field425 = 25; + optional uint64 field426 = 26; + optional int32 field427 = 38; + optional bytes field428 = 15; + optional bytes field429 = 55; + optional bytes field430 = 16; + optional bytes field431 = 23; + optional bool field432 = 33; + optional bytes field433 = 31; + optional bytes field434 = 32; + optional int32 field435 = 36; + optional uint64 field436 = 17; + optional int32 field437 = 45; + optional uint64 field438 = 18; + optional string field439 = 46; + optional .benchmarks.google_message4.UnusedEmptyMessage field440 = 64; + optional int32 field441 = 39; + optional uint64 field442 = 48; + optional bytes field443 = 19; + optional bytes field444 = 42; + optional bytes field445 = 43; + optional string field446 = 44; + optional string field447 = 49; + optional int64 field448 = 20; + optional bool field449 = 53; + optional .benchmarks.google_message4.UnusedEmptyMessage field450 = 54; + repeated .benchmarks.google_message4.UnusedEmptyMessage field451 = 22; + optional .benchmarks.google_message4.UnusedEnum field452 = 27; + optional int32 field453 = 29; + optional int32 field454 = 30; + optional .benchmarks.google_message4.UnusedEnum field455 = 37; + optional .benchmarks.google_message4.UnusedEnum field456 = 34; + optional int32 field457 = 35; + repeated group Message178 = 101 {} + optional bool field459 = 52; + optional uint64 field460 = 58; + optional uint64 field461 = 59; + optional .benchmarks.google_message4.UnusedEmptyMessage field462 = 60; + optional .benchmarks.google_message4.UnusedEmptyMessage field463 = 61; + optional .benchmarks.google_message4.UnusedEnum field464 = 62; + repeated string field465 = 63; + optional .benchmarks.google_message4.UnusedEmptyMessage field466 = 65; +} + +message Message8817 { + optional .benchmarks.google_message4.UnusedEmptyMessage field8825 = 1; + repeated .benchmarks.google_message4.Message8768 field8826 = 2; + optional string field8827 = 3; +} + +message Message8835 { + optional .benchmarks.google_message4.UnusedEmptyMessage field8837 = 1; + repeated string field8838 = 2; + optional .benchmarks.google_message4.UnusedEnum field8839 = 3; +} + +message Message37333 { + optional .benchmarks.google_message4.UnusedEmptyMessage field37372 = 3; + required .benchmarks.google_message4.Message37326 field37373 = 1; + optional uint64 field37374 = 2; +} + +message Message13000 { + optional int64 field13015 = 1; + repeated .benchmarks.google_message4.Message12979 field13016 = 2; +} + +message Message37335 { + optional .benchmarks.google_message4.UnusedEmptyMessage field37376 = 4; + required .benchmarks.google_message4.Message37326 field37377 = 1; + required .benchmarks.google_message4.Message37173 field37378 = 2; + optional uint64 field37379 = 3; +} + +message Message8848 { + optional .benchmarks.google_message4.UnusedEmptyMessage field8850 = 1; + optional string field8851 = 2; + optional bytes field8852 = 3; +} + +message Message13035 { + optional int64 field13058 = 1; + repeated int64 field13059 = 2; +} + +message Message8856 { + optional .benchmarks.google_message4.UnusedEmptyMessage field8858 = 1; + optional string field8859 = 2; +} + +message Message12908 { + optional .benchmarks.google_message4.UnusedEmptyMessage field12912 = 1; + optional string field12913 = 2; + optional .benchmarks.google_message4.Message12799 field12914 = 3; + optional int64 field12915 = 4; + optional .benchmarks.google_message4.Message3804 field12916 = 5; + optional .benchmarks.google_message4.Message12870 field12917 = 6; +} + +message Message12910 { + optional .benchmarks.google_message4.UnusedEmptyMessage field12920 = 1; + optional .benchmarks.google_message4.Message12818 field12921 = 2; + repeated .benchmarks.google_message4.Message12903 field12922 = 3; +} + +message Message37327 { + optional .benchmarks.google_message4.UnusedEmptyMessage field37347 = 11; + required .benchmarks.google_message4.Message37326 field37348 = 1; + optional bool field37349 = 2; + optional bool field37350 = 3; + optional bool field37351 = 4; + optional bool field37352 = 5; + optional bool field37353 = 6; + optional .benchmarks.google_message4.UnusedEmptyMessage field37354 = 7; + optional uint64 field37355 = 8; + optional bool field37356 = 9; + optional bool field37357 = 10; +} + +message Message37329 { + optional .benchmarks.google_message4.UnusedEmptyMessage field37359 = 6; + required .benchmarks.google_message4.Message37326 field37360 = 1; + required int64 field37361 = 2; + required int64 field37362 = 3; + optional bool field37363 = 4; +} + +message Message2517 { + optional .benchmarks.google_message4.UnusedEmptyMessage field2519 = 1; + optional .benchmarks.google_message4.Message2356 field2520 = 2; + optional .benchmarks.google_message4.Message0 field2521 = 3; + optional .benchmarks.google_message4.Message2463 field2522 = 4; + repeated .benchmarks.google_message4.Message971 field2523 = 5; +} + +message Message12748 { + optional .benchmarks.google_message4.UnusedEmptyMessage field12754 = 1; + optional string field12755 = 2; + optional string field12756 = 3; + optional .benchmarks.google_message4.Enum12735 field12757 = 4; +} + +message Message12687 { + repeated .benchmarks.google_message4.Message12686 field12701 = 1; +} + +message Message11948 { + optional string field11954 = 1; + repeated .benchmarks.google_message4.Message11949 field11955 = 2; + optional bool field11956 = 3; +} + +message Message11976 { + repeated .benchmarks.google_message4.Message11975 field12002 = 1; +} + +message Message7320 { + optional .benchmarks.google_message4.UnusedEmptyMessage field7323 = 1; + optional .benchmarks.google_message4.Message7287 field7324 = 8; +} + +message Message3069 { + optional .benchmarks.google_message4.Message3061 field3374 = 1; + optional bytes field3375 = 2; + repeated group Message3070 = 3 { + required .benchmarks.google_message4.Enum3071 field3378 = 4; + required bytes field3379 = 5; + } + extensions 10000 to 536870911; +} + +message Message12948 { + repeated .benchmarks.google_message4.Message12949 field12958 = 1; +} + +message Message8768 { + optional string field8782 = 1; + optional .benchmarks.google_message4.Message8572 field8783 = 2; + optional bool field8784 = 3; + repeated .benchmarks.google_message4.Message8774 field8785 = 4; + optional int64 field8786 = 5; + optional .benchmarks.google_message4.UnusedEmptyMessage field8787 = 6; + optional string field8788 = 7; +} + +message Message12979 { + required bytes field12981 = 1; + repeated string field12982 = 2; + optional .benchmarks.google_message4.UnusedEmptyMessage field12983 = 3; + optional int64 field12984 = 4; + optional string field12985 = 5; + optional int32 field12986 = 6; + optional .benchmarks.google_message4.UnusedEmptyMessage field12987 = 7; +} + +message Message37173 { + optional string field37252 = 1; + optional int64 field37253 = 2; + optional .benchmarks.google_message4.UnusedEnum field37254 = 4; + optional bool field37255 = 5; + optional bool field37256 = 6; + optional bool field37257 = 7; + optional string field37258 = 8; + optional string field37259 = 9; + optional uint32 field37260 = 10; + optional fixed32 field37261 = 11; + optional string field37262 = 12; + optional string field37263 = 13; + optional string field37264 = 14; + optional int32 field37265 = 15; + optional int64 field37266 = 16; + optional int64 field37267 = 17; + optional int32 field37268 = 18; + optional int32 field37269 = 19; + optional .benchmarks.google_message4.UnusedEmptyMessage field37270 = 20; + optional .benchmarks.google_message4.UnusedEmptyMessage field37271 = 21; + optional .benchmarks.google_message4.UnusedEmptyMessage field37272 = 22; + optional .benchmarks.google_message4.UnusedEmptyMessage field37273 = 23; + optional .benchmarks.google_message4.UnusedEmptyMessage field37274 = 24; + optional string field37275 = 25; + optional bool field37276 = 26; +} + +message Message12799 { + required string field12809 = 1; + repeated fixed64 field12810 = 2; + repeated .benchmarks.google_message4.Message12776 field12811 = 8; + repeated int32 field12812 = 4; + repeated .benchmarks.google_message4.Message12798 field12813 = 5; + required int32 field12814 = 3; + optional int32 field12815 = 6; + optional .benchmarks.google_message4.Message12797 field12816 = 7; +} + +message Message12870 { + required int32 field12879 = 1; + optional int32 field12880 = 7; + required int32 field12881 = 2; + optional uint64 field12882 = 3; + optional string field12883 = 2001; + optional fixed64 field12884 = 4; + repeated fixed64 field12885 = 14; + optional int32 field12886 = 9; + optional int64 field12887 = 18; + repeated .benchmarks.google_message4.Message12870 field12888 = 8; + optional int32 field12889 = 5; + optional uint64 field12890 = 6; + optional int32 field12891 = 10; + optional int32 field12892 = 11; + optional double field12893 = 12; + optional .benchmarks.google_message4.Message12825 field12894 = 13; + optional double field12895 = 15; + optional string field12896 = 16; + optional .benchmarks.google_message4.Enum12871 field12897 = 17; + optional int32 field12898 = 19; +} + +message Message3804 { + required int64 field3818 = 1; + required bool field3819 = 2; + repeated .benchmarks.google_message4.Enum3805 field3820 = 4; + optional int32 field3821 = 5; + optional bool field3822 = 6; + optional int64 field3823 = 7; + optional .benchmarks.google_message4.Enum3783 field3824 = 8; +} + +message Message12903 { + optional string field12905 = 1; + optional .benchmarks.google_message4.Message8587 field12906 = 2; + repeated .benchmarks.google_message4.Message8590 field12907 = 3; +} + +message Message37326 { + required string field37345 = 1; + optional string field37346 = 2; +} + +message Message2356 { + optional .benchmarks.google_message4.Message1374 field2368 = 121; + optional uint64 field2369 = 1; + optional int32 field2370 = 2; + optional int32 field2371 = 17; + required string field2372 = 3; + optional int32 field2373 = 7; + optional bytes field2374 = 8; + optional string field2375 = 4; + optional string field2376 = 101; + optional int32 field2377 = 102; + optional int32 field2378 = 103; + optional int32 field2379 = 104; + optional int32 field2380 = 113; + optional int32 field2381 = 114; + optional int32 field2382 = 115; + optional int32 field2383 = 117; + optional int32 field2384 = 118; + optional int32 field2385 = 119; + optional int32 field2386 = 105; + optional bytes field2387 = 5; + optional group Message2357 = 6 { + optional int64 field2399 = 9; + optional int32 field2400 = 10; + optional int32 field2401 = 11; + optional int32 field2402 = 12; + optional int32 field2403 = 13; + optional int32 field2404 = 116; + optional int32 field2405 = 106; + required bytes field2406 = 14; + optional int32 field2407 = 45; + optional int32 field2408 = 112; + optional bool field2409 = 122; + optional bytes field2410 = 124; + } + optional string field2389 = 120; + optional group Message2358 = 107 {} + repeated group Message2359 = 40 {} + optional int32 field2392 = 50; + optional .benchmarks.google_message4.UnusedEmptyMessage field2393 = 60; + optional .benchmarks.google_message4.UnusedEmptyMessage field2394 = 70; + optional .benchmarks.google_message4.UnusedEmptyMessage field2395 = 80; + optional .benchmarks.google_message4.UnusedEmptyMessage field2396 = 90; + optional string field2397 = 100; + optional string field2398 = 123; +} + +message Message0 { + option message_set_wire_format = true; + + extensions 4 to 2147483646; +} + +message Message971 { + optional string field972 = 1; + optional int32 field973 = 2; + optional bool field974 = 3; +} diff --git a/benchmarks/datasets/google_message4/benchmark_message4_1.proto b/benchmarks/datasets/google_message4/benchmark_message4_1.proto new file mode 100644 index 0000000000000..c5deecd0df841 --- /dev/null +++ b/benchmarks/datasets/google_message4/benchmark_message4_1.proto @@ -0,0 +1,500 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// LINT: ALLOW_GROUPS + +syntax = "proto2"; + +package benchmarks.google_message4; + +import "datasets/google_message4/benchmark_message4_2.proto"; +import "datasets/google_message4/benchmark_message4_3.proto"; + +option cc_enable_arenas = true; +option java_package = "com.google.protobuf.benchmarks"; + +message Message2463 { + repeated .benchmarks.google_message4.Message2462 field2498 = 1; +} + +message Message12686 { + optional string field12699 = 1; + optional .benchmarks.google_message4.Message12685 field12700 = 2; +} + +message Message11949 {} + +message Message11975 { + optional string field11992 = 1; + optional int32 field11993 = 2; + repeated .benchmarks.google_message4.Message10320 field11994 = 3; + optional .benchmarks.google_message4.Message11947 field11995 = 4; + optional .benchmarks.google_message4.Message11920 field11996 = 5; + optional bool field11997 = 6; + repeated string field11998 = 7; + optional float field11999 = 8; + repeated .benchmarks.google_message4.UnusedEnum field12000 = 9; + optional int32 field12001 = 11; +} + +message Message7287 { + optional .benchmarks.google_message4.Message6133 field7311 = 1; + optional .benchmarks.google_message4.UnusedEmptyMessage field7312 = 8; + optional string field7313 = 3; + optional .benchmarks.google_message4.Message6643 field7314 = 4; + optional .benchmarks.google_message4.Enum7288 field7315 = 5; + optional bytes field7316 = 6; + optional .benchmarks.google_message4.UnusedEmptyMessage field7317 = 7; + optional .benchmarks.google_message4.UnusedEmptyMessage field7318 = 9; +} + +message Message3061 { + optional string field3286 = 2; + optional int32 field3287 = 77; + optional string field3288 = 49; + required .benchmarks.google_message4.Message3046 field3289 = 3; + optional .benchmarks.google_message4.Message3046 field3290 = 58; + optional group Message3062 = 4 { + required int32 field3335 = 5; + optional int32 field3336 = 6; + optional int32 field3337 = 7; + } + optional .benchmarks.google_message4.Message3060 field3292 = 104; + optional int64 field3293 = 32; + optional int32 field3294 = 41; + optional group Message3063 = 13 { + required int32 field3338 = 14; + optional .benchmarks.google_message4.Enum2851 field3339 = 18; + optional int64 field3340 = 15; + optional int64 field3341 = 23; + } + optional .benchmarks.google_message4.Enum2834 field3296 = 94; + optional bool field3297 = 25; + optional bool field3298 = 50; + optional string field3299 = 89; + optional string field3300 = 91; + optional string field3301 = 105; + optional .benchmarks.google_message4.Message3050 field3302 = 53; + optional fixed64 field3303 = 51; + optional fixed64 field3304 = 106; + optional int32 field3305 = 60; + optional string field3306 = 44; + optional bytes field3307 = 81; + optional string field3308 = 70; + optional bytes field3309 = 45; + optional .benchmarks.google_message4.Enum2806 field3310 = 71; + optional int32 field3311 = 72; + optional bytes field3312 = 78; + optional int32 field3313 = 20; + repeated group Message3064 = 8 { + required .benchmarks.google_message4.Enum2602 field3342 = 9; + optional int32 field3343 = 92; + optional string field3344 = 10; + optional bytes field3345 = 11; + optional int32 field3346 = 12; + optional .benchmarks.google_message4.Message3060 field3347 = 98; + optional .benchmarks.google_message4.UnusedEmptyMessage field3348 = 82; + optional .benchmarks.google_message4.Message3050 field3349 = 80; + optional fixed64 field3350 = 52; + optional int32 field3351 = 33; + optional string field3352 = 42; + optional string field3353 = 69; + optional bytes field3354 = 43; + optional .benchmarks.google_message4.Enum2806 field3355 = 73; + optional int32 field3356 = 74; + optional int32 field3357 = 90; + optional bytes field3358 = 79; + optional int32 field3359 = 19; + optional .benchmarks.google_message4.Enum2834 field3360 = 95; + } + optional .benchmarks.google_message4.UnusedEmptyMessage field3315 = 39; + optional int32 field3316 = 76; + optional group Message3065 = 63 {} + optional .benchmarks.google_message4.Enum2806 field3318 = 54; + optional int32 field3319 = 46; + repeated string field3320 = 24; + optional fixed32 field3321 = 38; + optional bytes field3322 = 99; + optional fixed64 field3323 = 1; + optional fixed64 field3324 = 97; + repeated .benchmarks.google_message4.Message3040 field3325 = 16; + repeated .benchmarks.google_message4.Message3041 field3326 = 61; + optional group Message3066 = 21 { + optional int32 field3366 = 22; + optional int32 field3367 = 55; + optional int32 field3368 = 88; + optional int32 field3369 = 56; + optional int32 field3370 = 75; + optional int32 field3371 = 57; + optional .benchmarks.google_message4.UnusedEmptyMessage field3372 = 85; + optional .benchmarks.google_message4.UnusedEmptyMessage field3373 = 96; + } + optional .benchmarks.google_message4.UnusedEmptyMessage field3328 = 47; + optional .benchmarks.google_message4.UnusedEmptyMessage field3329 = 48; + optional fixed64 field3330 = 40; + optional .benchmarks.google_message4.UnusedEmptyMessage field3331 = 86; + optional .benchmarks.google_message4.UnusedEmptyMessage field3332 = 59; + optional int32 field3333 = 17; +} + +message Message12949 {} + +message Message8572 { + optional bytes field8647 = 1; + optional bytes field8648 = 3; + optional .benchmarks.google_message4.Message3886 field8649 = 4; + optional .benchmarks.google_message4.Message3919 field8650 = 57; + optional bool field8651 = 5; + optional int32 field8652 = 6; + optional int32 field8653 = 49; + optional .benchmarks.google_message4.Message7905 field8654 = 7; + optional int32 field8655 = 10; + optional .benchmarks.google_message4.UnusedEmptyMessage field8656 = 11; + optional bool field8657 = 35; + optional bytes field8658 = 12; + optional string field8659 = 14; + optional .benchmarks.google_message4.UnusedEmptyMessage field8660 = 13; + optional bytes field8661 = 15; + optional .benchmarks.google_message4.UnusedEmptyMessage field8662 = 17; + optional int32 field8663 = 18; + optional int32 field8664 = 19; + optional bool field8665 = 20; + optional .benchmarks.google_message4.Enum3476 field8666 = 31; + optional bool field8667 = 36; + optional .benchmarks.google_message4.UnusedEmptyMessage field8668 = 39; + optional bytes field8669 = 22; + optional int32 field8670 = 24; + optional .benchmarks.google_message4.Message3052 field8671 = 25; + optional bytes field8672 = 26; + optional bytes field8673 = 28; + optional int32 field8674 = 29; + optional bytes field8675 = 30; + optional bytes field8676 = 32; + optional string field8677 = 33; + optional int32 field8678 = 34; + optional int32 field8679 = 37; + optional double field8680 = 38; + optional double field8681 = 42; + optional .benchmarks.google_message4.Message3922 field8682 = 40; + optional .benchmarks.google_message4.UnusedEmptyMessage field8683 = 43; + optional int64 field8684 = 44; + optional .benchmarks.google_message4.Message7929 field8685 = 45; + optional uint64 field8686 = 46; + optional uint32 field8687 = 48; + optional .benchmarks.google_message4.Message7843 field8688 = 47; + optional .benchmarks.google_message4.Message7864 field8689 = 50; + optional .benchmarks.google_message4.UnusedEmptyMessage field8690 = 52; + optional bool field8691 = 58; + optional bool field8692 = 54; + optional string field8693 = 55; + optional .benchmarks.google_message4.UnusedEmptyMessage field8694 = 41; + optional .benchmarks.google_message4.UnusedEmptyMessage field8695 = 53; + optional .benchmarks.google_message4.Message8575 field8696 = 61; +} + +message Message8774 { + optional string field8810 = 1; + optional string field8811 = 2; + optional string field8812 = 3; + optional string field8813 = 4; + optional string field8814 = 5; +} + +message Message12776 { + optional string field12786 = 1; + optional fixed64 field12787 = 11; + optional int32 field12788 = 6; + optional int32 field12789 = 13; + optional int32 field12790 = 14; + optional int32 field12791 = 15; + optional int32 field12792 = 16; + optional .benchmarks.google_message4.UnusedEmptyMessage field12793 = 8; + optional .benchmarks.google_message4.Message12774 field12794 = 10; + optional .benchmarks.google_message4.UnusedEmptyMessage field12795 = 12; + extensions 2 to 2; + extensions 3 to 3; + extensions 4 to 4; + extensions 5 to 5; + extensions 7 to 7; + extensions 9 to 9; +} + +message Message12798 { + optional int32 field12805 = 1; + optional int32 field12806 = 2; + optional .benchmarks.google_message4.Message12774 field12807 = 6; + optional bool field12808 = 7; +} + +message Message12797 { + optional .benchmarks.google_message4.Message12796 field12802 = 1; + repeated .benchmarks.google_message4.Message12796 field12803 = 2; + optional string field12804 = 3; +} + +message Message12825 { + repeated .benchmarks.google_message4.Message12818 field12862 = 1; + optional int32 field12863 = 2; + optional .benchmarks.google_message4.Message12819 field12864 = 3; + optional .benchmarks.google_message4.Message12820 field12865 = 4; + optional int32 field12866 = 5; + repeated .benchmarks.google_message4.Message12821 field12867 = 6; + repeated .benchmarks.google_message4.UnusedEmptyMessage field12868 = 7; +} + +message Message8590 {} + +message Message8587 {} + +message Message1374 { + required string field1375 = 1; + optional string field1376 = 2; +} + +message Message2462 { + required bytes field2496 = 1; + required double field2497 = 2; +} + +message Message12685 { + repeated string field12692 = 1; + repeated string field12693 = 2; + optional int64 field12694 = 3; + optional uint32 field12695 = 4; + repeated string field12696 = 5; + optional string field12697 = 6; + optional string field12698 = 7; +} + +message Message10320 { + optional .benchmarks.google_message4.Enum10335 field10347 = 1; + repeated .benchmarks.google_message4.Message10319 field10348 = 2; + optional int32 field10349 = 3; + optional int32 field10350 = 4; + optional int32 field10351 = 5; + optional int32 field10352 = 6; + optional .benchmarks.google_message4.Enum10337 field10353 = 7; +} + +message Message11947 { + optional uint32 field11951 = 1; + optional bool field11952 = 2; + optional int32 field11953 = 3; +} + +message Message11920 { + optional .benchmarks.google_message4.Enum11901 field11945 = 1; + optional .benchmarks.google_message4.UnusedEnum field11946 = 2; +} + +message Message6643 { + optional .benchmarks.google_message4.UnusedEmptyMessage field6683 = 3; + optional .benchmarks.google_message4.UnusedEmptyMessage field6684 = 4; + optional double field6685 = 5; + optional double field6686 = 6; + optional int32 field6687 = 1; + optional int32 field6688 = 2; + optional double field6689 = 9; + optional bytes field6690 = 10; + optional int32 field6691 = 11; + optional bool field6692 = 12; + optional bool field6693 = 13; + optional .benchmarks.google_message4.Message6578 field6694 = 15; + optional .benchmarks.google_message4.UnusedEnum field6695 = 16; + optional int64 field6696 = 17; + repeated .benchmarks.google_message4.UnusedEmptyMessage field6697 = 22; + optional .benchmarks.google_message4.UnusedEmptyMessage field6698 = 19; + optional .benchmarks.google_message4.UnusedEmptyMessage field6699 = 20; + optional int32 field6700 = 21; +} + +message Message6133 { + optional .benchmarks.google_message4.Message4016 field6173 = 12; + optional double field6174 = 16; + required string field6175 = 1; + required string field6176 = 2; + required string field6177 = 3; + optional string field6178 = 4; + optional string field6179 = 8; + repeated .benchmarks.google_message4.Message6109 field6180 = 5; + repeated .benchmarks.google_message4.Message5908 field6181 = 13; + repeated .benchmarks.google_message4.Message6107 field6182 = 7; + repeated .benchmarks.google_message4.Message6126 field6183 = 9; + repeated .benchmarks.google_message4.Message6129 field6184 = 15; + optional int32 field6185 = 10; + optional int32 field6186 = 11; + optional .benchmarks.google_message4.Message4016 field6187 = 17; + optional double field6188 = 14; + optional double field6189 = 18; + optional string field6190 = 19; + optional string field6191 = 20; + repeated .benchmarks.google_message4.Message5881 field6192 = 21; +} + +message Message6109 { + optional string field6140 = 1; + required .benchmarks.google_message4.Enum6111 field6141 = 2; + optional int32 field6142 = 9; + optional string field6143 = 3; + repeated .benchmarks.google_message4.Message6110 field6144 = 4; + repeated int32 field6145 = 7; + repeated int32 field6146 = 8; + optional .benchmarks.google_message4.Message6133 field6147 = 10; + repeated int32 field6148 = 11; + optional string field6149 = 12; + optional string field6150 = 13; + optional bool field6151 = 14; + extensions 1000 to 536870911; +} + +message Message3046 { + required .benchmarks.google_message4.Enum2593 field3222 = 1; + optional int32 field3223 = 4; +} + +message Message3060 { + optional int64 field3283 = 1; + optional int64 field3284 = 2; + optional int64 field3285 = 3; +} + +message Message3041 { + optional string field3214 = 1; + optional int32 field3215 = 2; +} + +message Message3040 { + required fixed64 field3209 = 1; + repeated fixed64 field3210 = 4; + optional int32 field3211 = 5; + optional fixed64 field3212 = 2; + required string field3213 = 3; +} + +message Message3050 { + optional bytes field3245 = 5; + optional int32 field3246 = 2; + optional bytes field3247 = 6; + optional int32 field3248 = 4; + optional fixed32 field3249 = 1; + optional fixed32 field3250 = 3; +} + +message Message7905 { + optional int32 field7911 = 1; + optional bool field7912 = 2; + optional bytes field7913 = 3; + optional int32 field7914 = 4; + optional int32 field7915 = 5; + optional bytes field7916 = 6; + optional int32 field7917 = 7; +} + +message Message3886 { + repeated group Message3887 = 1 { + required string field3932 = 2; + optional string field3933 = 9; + optional .benchmarks.google_message4.Message3850 field3934 = 3; + optional bytes field3935 = 8; + } +} + +message Message7864 { + optional string field7866 = 1; + optional string field7867 = 2; + repeated .benchmarks.google_message4.Message7865 field7868 = 5; + repeated .benchmarks.google_message4.Message7865 field7869 = 6; + repeated .benchmarks.google_message4.Message7865 field7870 = 7; + repeated .benchmarks.google_message4.UnusedEmptyMessage field7871 = 8; +} + +message Message3922 { + optional uint64 field4012 = 1; +} + +message Message3052 { + repeated string field3254 = 1; + repeated string field3255 = 2; + repeated bytes field3256 = 3; + repeated string field3257 = 4; + optional bool field3258 = 5; + optional int32 field3259 = 6; + optional int32 field3260 = 7; + optional string field3261 = 8; + optional string field3262 = 9; +} + +message Message8575 {} + +message Message7843 { + optional bool field7844 = 5; + optional int32 field7845 = 1; + optional .benchmarks.google_message4.UnusedEmptyMessage field7846 = 22; + repeated int32 field7847 = 3; + repeated string field7848 = 11; + optional .benchmarks.google_message4.UnusedEnum field7849 = 15; + optional .benchmarks.google_message4.UnusedEmptyMessage field7850 = 6; + optional .benchmarks.google_message4.UnusedEmptyMessage field7851 = 14; + optional .benchmarks.google_message4.UnusedEmptyMessage field7852 = 10; + optional .benchmarks.google_message4.Message7511 field7853 = 13; + optional .benchmarks.google_message4.UnusedEmptyMessage field7854 = 16; + optional .benchmarks.google_message4.UnusedEmptyMessage field7855 = 17; + optional .benchmarks.google_message4.UnusedEmptyMessage field7856 = 19; + optional .benchmarks.google_message4.UnusedEmptyMessage field7857 = 18; + optional .benchmarks.google_message4.UnusedEnum field7858 = 20; + optional int32 field7859 = 2; +} + +message Message3919 { + repeated .benchmarks.google_message4.Message3920 field4009 = 1; +} + +message Message7929 { + optional int64 field7942 = 1; + optional int64 field7943 = 4; + optional int64 field7944 = 5; + optional int64 field7945 = 12; + optional int64 field7946 = 13; + optional int64 field7947 = 18; + optional int64 field7948 = 6; + optional int64 field7949 = 7; + repeated .benchmarks.google_message4.Message7919 field7950 = 8; + repeated .benchmarks.google_message4.UnusedEmptyMessage field7951 = 20; + repeated .benchmarks.google_message4.Message7920 field7952 = 14; + repeated .benchmarks.google_message4.Message7921 field7953 = 15; + repeated .benchmarks.google_message4.Message7928 field7954 = 17; + optional int64 field7955 = 19; + optional bool field7956 = 2; + optional int64 field7957 = 3; + optional int64 field7958 = 9; + repeated .benchmarks.google_message4.UnusedEmptyMessage field7959 = 10; + repeated bytes field7960 = 11; + optional int64 field7961 = 16; +} diff --git a/benchmarks/datasets/google_message4/benchmark_message4_2.proto b/benchmarks/datasets/google_message4/benchmark_message4_2.proto new file mode 100644 index 0000000000000..0c4cdfd853a1d --- /dev/null +++ b/benchmarks/datasets/google_message4/benchmark_message4_2.proto @@ -0,0 +1,316 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package benchmarks.google_message4; + +import "datasets/google_message4/benchmark_message4_3.proto"; + +option cc_enable_arenas = true; +option java_package = "com.google.protobuf.benchmarks"; + +message Message12774 { + optional uint32 field12777 = 1; + optional uint32 field12778 = 2; + optional uint32 field12779 = 3; + optional uint32 field12780 = 4; + optional uint32 field12781 = 5; + optional bool field12782 = 6; +} + +message Message12796 { + repeated fixed64 field12800 = 1; + optional uint64 field12801 = 2; +} + +message Message12821 { + optional int32 field12848 = 1; + optional int32 field12849 = 2; + optional int32 field12850 = 3; + optional int32 field12851 = 4; + optional int32 field12852 = 5; +} + +message Message12820 { + optional int32 field12840 = 1; + optional int32 field12841 = 2; + optional int32 field12842 = 3; + optional int32 field12843 = 8; + optional int32 field12844 = 4; + optional int32 field12845 = 5; + optional int32 field12846 = 6; + optional int32 field12847 = 7; +} + +message Message12819 { + optional double field12834 = 1; + optional double field12835 = 2; + optional double field12836 = 3; + optional double field12837 = 4; + optional double field12838 = 5; + optional double field12839 = 6; +} + +message Message12818 { + optional uint64 field12829 = 1; + optional int32 field12830 = 2; + optional int32 field12831 = 3; + optional int32 field12832 = 5; + repeated .benchmarks.google_message4.Message12817 field12833 = 4; +} + +message Message10319 { + optional .benchmarks.google_message4.Enum10325 field10340 = 1; + optional int32 field10341 = 4; + optional int32 field10342 = 5; + optional bytes field10343 = 3; + optional string field10344 = 2; + optional string field10345 = 6; + optional string field10346 = 7; +} + +message Message6578 { + optional .benchmarks.google_message4.Enum6579 field6632 = 1; + optional .benchmarks.google_message4.Enum6588 field6633 = 2; +} + +message Message6126 { + required string field6152 = 1; + repeated .benchmarks.google_message4.Message6127 field6153 = 9; + optional int32 field6154 = 14; + optional bytes field6155 = 10; + optional .benchmarks.google_message4.Message6024 field6156 = 12; + optional int32 field6157 = 4; + optional string field6158 = 5; + optional int32 field6159 = 6; + repeated int32 field6160 = 2; + repeated int32 field6161 = 3; + repeated .benchmarks.google_message4.Message6052 field6162 = 7; + repeated .benchmarks.google_message4.UnusedEmptyMessage field6163 = 11; + optional .benchmarks.google_message4.Enum6065 field6164 = 15; + repeated .benchmarks.google_message4.Message6127 field6165 = 8; + optional bool field6166 = 13; + optional bool field6167 = 16; + optional bool field6168 = 18; + repeated .benchmarks.google_message4.Message6054 field6169 = 17; + optional int32 field6170 = 19; +} + +message Message5881 { + required double field5897 = 1; + optional string field5898 = 5; + optional .benchmarks.google_message4.Message5861 field5899 = 2; + optional .benchmarks.google_message4.UnusedEmptyMessage field5900 = 3; + optional .benchmarks.google_message4.Message5867 field5901 = 4; + optional .benchmarks.google_message4.Message5880 field5902 = 6; +} + +message Message6110 {} + +message Message6107 { + optional .benchmarks.google_message4.Message4016 field6134 = 1; + optional int32 field6135 = 2; + optional string field6136 = 3; + repeated int32 field6137 = 4; + optional int32 field6138 = 5; + repeated .benchmarks.google_message4.Message6108 field6139 = 6; +} + +message Message6129 { + required .benchmarks.google_message4.Enum6130 field6171 = 1; + required string field6172 = 2; +} + +message Message5908 { + optional string field5971 = 1; + optional int32 field5972 = 2; + optional int32 field5973 = 3; + optional .benchmarks.google_message4.Enum5909 field5974 = 45; + optional .benchmarks.google_message4.Enum5912 field5975 = 4; + optional fixed32 field5976 = 50; + optional fixed32 field5977 = 5; + optional fixed32 field5978 = 6; + optional string field5979 = 7; + optional .benchmarks.google_message4.Enum5915 field5980 = 8; + optional .benchmarks.google_message4.Message5903 field5981 = 9; + optional .benchmarks.google_message4.Message5903 field5982 = 10; + optional .benchmarks.google_message4.Enum5920 field5983 = 11; + optional .benchmarks.google_message4.Enum5923 field5984 = 40; + optional .benchmarks.google_message4.Message5903 field5985 = 41; + optional .benchmarks.google_message4.Message5903 field5986 = 42; + optional .benchmarks.google_message4.Enum5928 field5987 = 47; + optional bool field5988 = 48; + repeated fixed32 field5989 = 49; + optional string field5990 = 12; + optional .benchmarks.google_message4.Message5903 field5991 = 13; + optional .benchmarks.google_message4.Message5903 field5992 = 14; + optional .benchmarks.google_message4.Message5903 field5993 = 15; + optional .benchmarks.google_message4.Message5903 field5994 = 16; + optional .benchmarks.google_message4.Message5903 field5995 = 32; + optional .benchmarks.google_message4.Message5903 field5996 = 33; + optional .benchmarks.google_message4.Message5903 field5997 = 34; + optional .benchmarks.google_message4.Message5903 field5998 = 35; + optional .benchmarks.google_message4.Enum5931 field5999 = 17; + optional .benchmarks.google_message4.Enum5935 field6000 = 18; + optional .benchmarks.google_message4.Enum5939 field6001 = 36; + optional .benchmarks.google_message4.Enum5939 field6002 = 37; + repeated int32 field6003 = 19; + optional uint32 field6004 = 20; + optional uint32 field6005 = 21; + optional uint32 field6006 = 22; + optional uint32 field6007 = 23; + optional .benchmarks.google_message4.Enum5946 field6008 = 24; + optional .benchmarks.google_message4.Enum5946 field6009 = 25; + optional .benchmarks.google_message4.Enum5946 field6010 = 26; + optional .benchmarks.google_message4.Enum5946 field6011 = 27; + optional fixed32 field6012 = 28; + optional fixed32 field6013 = 29; + optional fixed32 field6014 = 30; + optional fixed32 field6015 = 31; + optional int32 field6016 = 38; + optional float field6017 = 39; + optional .benchmarks.google_message4.Enum5957 field6018 = 43; + optional .benchmarks.google_message4.Message5907 field6019 = 44; + optional .benchmarks.google_message4.Enum5962 field6020 = 46; +} + +message Message3850 { + optional .benchmarks.google_message4.Enum3851 field3924 = 2; + optional bool field3925 = 12; + optional int32 field3926 = 4; + optional bool field3927 = 10; + optional bool field3928 = 13; + optional bool field3929 = 14; +} + +message Message7865 {} + +message Message7511 { + optional bool field7523 = 1; + optional .benchmarks.google_message4.Enum7512 field7524 = 2; + optional int32 field7525 = 3; + optional int32 field7526 = 4; + optional bool field7527 = 5; + optional int32 field7528 = 6; + optional int32 field7529 = 7; +} + +message Message3920 {} + +message Message7928 { + optional string field7940 = 1; + optional int64 field7941 = 2; +} + +message Message7921 { + optional int32 field7936 = 1; + optional int64 field7937 = 2; + optional float field7938 = 3; + optional .benchmarks.google_message4.Enum7922 field7939 = 4; +} + +message Message7920 { + optional int64 field7934 = 1; + optional int64 field7935 = 2; +} + +message Message7919 { + optional fixed64 field7931 = 1; + optional int64 field7932 = 2; + optional bytes field7933 = 3; +} + +message Message12817 { + optional int32 field12826 = 1; + optional int32 field12827 = 2; + optional int32 field12828 = 3; +} + +message Message6054 { + required string field6089 = 1; + optional string field6090 = 2; +} + +message Message6127 {} + +message Message6052 { + required string field6084 = 1; + required bytes field6085 = 2; +} + +message Message6024 { + optional .benchmarks.google_message4.Enum6025 field6048 = 1; + optional string field6049 = 2; + optional .benchmarks.google_message4.UnusedEmptyMessage field6050 = 3; +} + +message Message5861 { + required .benchmarks.google_message4.Enum5862 field5882 = 1; + required string field5883 = 2; + optional bool field5884 = 3; + optional string field5885 = 4; +} + +message Message5880 { + optional string field5896 = 1; +} + +message Message5867 { + optional .benchmarks.google_message4.Enum5868 field5890 = 1; + optional string field5891 = 2; + optional .benchmarks.google_message4.Enum5873 field5892 = 3; + optional int32 field5893 = 4; + optional .benchmarks.google_message4.UnusedEnum field5894 = 5; + optional bool field5895 = 6; +} + +message Message4016 { + required int32 field4017 = 1; + required int32 field4018 = 2; + required int32 field4019 = 3; + required int32 field4020 = 4; +} + +message Message6108 {} + +message Message5907 { + optional .benchmarks.google_message4.Message5903 field5967 = 1; + optional .benchmarks.google_message4.Message5903 field5968 = 2; + optional .benchmarks.google_message4.Message5903 field5969 = 3; + optional .benchmarks.google_message4.Message5903 field5970 = 4; +} + +message UnusedEmptyMessage {} + +message Message5903 { + required int32 field5965 = 1; + optional .benchmarks.google_message4.Enum5904 field5966 = 2; +} diff --git a/benchmarks/datasets/google_message4/benchmark_message4_3.proto b/benchmarks/datasets/google_message4/benchmark_message4_3.proto new file mode 100644 index 0000000000000..42e254b762f47 --- /dev/null +++ b/benchmarks/datasets/google_message4/benchmark_message4_3.proto @@ -0,0 +1,779 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package benchmarks.google_message4; + +option cc_enable_arenas = true; +option java_package = "com.google.protobuf.benchmarks"; + +enum UnusedEnum { + UNUSED_ENUM_VALUE1 = 0; + UNUSED_ENUM_VALUE2 = 1; +} + +enum Enum2593 { + ENUM_VALUE2594 = 0; + ENUM_VALUE2595 = 1; + ENUM_VALUE2596 = 2; + ENUM_VALUE2597 = 3; + ENUM_VALUE2598 = 4; + ENUM_VALUE2599 = 5; + ENUM_VALUE2600 = 6; + ENUM_VALUE2601 = 7; +} + +enum Enum2834 { + ENUM_VALUE2835 = 0; + ENUM_VALUE2836 = 1; + ENUM_VALUE2837 = 2; +} + +enum Enum2806 { + ENUM_VALUE2807 = 0; + ENUM_VALUE2808 = 1; + ENUM_VALUE2809 = 2; + ENUM_VALUE2810 = 3; + ENUM_VALUE2811 = 4; + ENUM_VALUE2812 = 5; + ENUM_VALUE2813 = 6; + ENUM_VALUE2814 = 7; + ENUM_VALUE2815 = 8; + ENUM_VALUE2816 = 9; + ENUM_VALUE2817 = 10; + ENUM_VALUE2818 = 11; + ENUM_VALUE2819 = 12; + ENUM_VALUE2820 = 13; + ENUM_VALUE2821 = 14; +} + +enum Enum2851 { + option allow_alias = true; + + ENUM_VALUE2852 = 0; + ENUM_VALUE2853 = 0; + ENUM_VALUE2854 = 1; + ENUM_VALUE2855 = 2; + ENUM_VALUE2856 = 3; + ENUM_VALUE2857 = 4; + ENUM_VALUE2858 = 5; + ENUM_VALUE2859 = 6; + ENUM_VALUE2860 = 7; + ENUM_VALUE2861 = 8; + ENUM_VALUE2862 = 9; + ENUM_VALUE2863 = 10; + ENUM_VALUE2864 = 11; + ENUM_VALUE2865 = 12; + ENUM_VALUE2866 = 13; + ENUM_VALUE2867 = 14; + ENUM_VALUE2868 = 15; + ENUM_VALUE2869 = 16; + ENUM_VALUE2870 = 17; + ENUM_VALUE2871 = 18; + ENUM_VALUE2872 = 19; + ENUM_VALUE2873 = 20; + ENUM_VALUE2874 = 21; + ENUM_VALUE2875 = 22; + ENUM_VALUE2876 = 23; + ENUM_VALUE2877 = 24; + ENUM_VALUE2878 = 25; + ENUM_VALUE2879 = 26; + ENUM_VALUE2880 = 27; + ENUM_VALUE2881 = 28; + ENUM_VALUE2882 = 29; + ENUM_VALUE2883 = 30; + ENUM_VALUE2884 = 31; + ENUM_VALUE2885 = 32; + ENUM_VALUE2886 = 33; + ENUM_VALUE2887 = 34; + ENUM_VALUE2888 = 35; + ENUM_VALUE2889 = 36; + ENUM_VALUE2890 = 37; + ENUM_VALUE2891 = 38; + ENUM_VALUE2892 = 39; + ENUM_VALUE2893 = 40; + ENUM_VALUE2894 = 41; + ENUM_VALUE2895 = 42; + ENUM_VALUE2896 = 43; + ENUM_VALUE2897 = 44; + ENUM_VALUE2898 = 45; + ENUM_VALUE2899 = 46; + ENUM_VALUE2900 = 47; + ENUM_VALUE2901 = 48; + ENUM_VALUE2902 = 49; + ENUM_VALUE2903 = 50; + ENUM_VALUE2904 = 51; + ENUM_VALUE2905 = 52; + ENUM_VALUE2906 = 53; + ENUM_VALUE2907 = 54; + ENUM_VALUE2908 = 55; + ENUM_VALUE2909 = 56; + ENUM_VALUE2910 = 57; + ENUM_VALUE2911 = 58; + ENUM_VALUE2912 = 59; + ENUM_VALUE2913 = 60; + ENUM_VALUE2914 = 61; + ENUM_VALUE2915 = 62; + ENUM_VALUE2916 = 63; + ENUM_VALUE2917 = 64; + ENUM_VALUE2918 = 65; + ENUM_VALUE2919 = 66; + ENUM_VALUE2920 = 67; + ENUM_VALUE2921 = 68; + ENUM_VALUE2922 = 69; + ENUM_VALUE2923 = 70; + ENUM_VALUE2924 = 71; + ENUM_VALUE2925 = 72; + ENUM_VALUE2926 = 73; + ENUM_VALUE2927 = 74; + ENUM_VALUE2928 = 75; + ENUM_VALUE2929 = 76; + ENUM_VALUE2930 = 77; + ENUM_VALUE2931 = 78; + ENUM_VALUE2932 = 79; + ENUM_VALUE2933 = 80; + ENUM_VALUE2934 = 81; + ENUM_VALUE2935 = 82; + ENUM_VALUE2936 = 83; + ENUM_VALUE2937 = 84; + ENUM_VALUE2938 = 85; + ENUM_VALUE2939 = 86; + ENUM_VALUE2940 = 87; + ENUM_VALUE2941 = 88; + ENUM_VALUE2942 = 89; + ENUM_VALUE2943 = 90; + ENUM_VALUE2944 = 91; + ENUM_VALUE2945 = 92; + ENUM_VALUE2946 = 93; + ENUM_VALUE2947 = 94; + ENUM_VALUE2948 = 95; + ENUM_VALUE2949 = 96; + ENUM_VALUE2950 = 97; + ENUM_VALUE2951 = 98; + ENUM_VALUE2952 = 99; + ENUM_VALUE2953 = 100; + ENUM_VALUE2954 = 101; + ENUM_VALUE2955 = 102; + ENUM_VALUE2956 = 103; + ENUM_VALUE2957 = 104; + ENUM_VALUE2958 = 105; + ENUM_VALUE2959 = 106; + ENUM_VALUE2960 = 107; + ENUM_VALUE2961 = 108; + ENUM_VALUE2962 = 109; + ENUM_VALUE2963 = 110; + ENUM_VALUE2964 = 111; + ENUM_VALUE2965 = 112; + ENUM_VALUE2966 = 113; + ENUM_VALUE2967 = 114; + ENUM_VALUE2968 = 115; + ENUM_VALUE2969 = 116; + ENUM_VALUE2970 = 117; + ENUM_VALUE2971 = 118; + ENUM_VALUE2972 = 119; +} + +enum Enum2602 { + ENUM_VALUE2603 = 0; + ENUM_VALUE2604 = 1; + ENUM_VALUE2605 = 2; + ENUM_VALUE2606 = 3; + ENUM_VALUE2607 = 4; + ENUM_VALUE2608 = 5; + ENUM_VALUE2609 = 6; + ENUM_VALUE2610 = 7; + ENUM_VALUE2611 = 8; + ENUM_VALUE2612 = 9; + ENUM_VALUE2613 = 10; + ENUM_VALUE2614 = 11; +} + +enum Enum3071 { + ENUM_VALUE3072 = 1; + ENUM_VALUE3073 = 2; + ENUM_VALUE3074 = 3; + ENUM_VALUE3075 = 4; + ENUM_VALUE3076 = 5; + ENUM_VALUE3077 = 6; + ENUM_VALUE3078 = 7; + ENUM_VALUE3079 = 8; + ENUM_VALUE3080 = 9; + ENUM_VALUE3081 = 10; + ENUM_VALUE3082 = 11; + ENUM_VALUE3083 = 12; + ENUM_VALUE3084 = 13; + ENUM_VALUE3085 = 14; + ENUM_VALUE3086 = 15; + ENUM_VALUE3087 = 16; + ENUM_VALUE3088 = 17; + ENUM_VALUE3089 = 18; + ENUM_VALUE3090 = 19; + ENUM_VALUE3091 = 20; + ENUM_VALUE3092 = 21; + ENUM_VALUE3093 = 22; + ENUM_VALUE3094 = 23; + ENUM_VALUE3095 = 24; + ENUM_VALUE3096 = 25; + ENUM_VALUE3097 = 26; + ENUM_VALUE3098 = 27; + ENUM_VALUE3099 = 28; +} + +enum Enum3805 { + ENUM_VALUE3806 = 0; + ENUM_VALUE3807 = 1; + ENUM_VALUE3808 = 2; + ENUM_VALUE3809 = 3; + ENUM_VALUE3810 = 4; + ENUM_VALUE3811 = 5; + ENUM_VALUE3812 = 6; + ENUM_VALUE3813 = 7; + ENUM_VALUE3814 = 8; + ENUM_VALUE3815 = 9; + ENUM_VALUE3816 = 11; + ENUM_VALUE3817 = 10; +} + +enum Enum3783 { + ENUM_VALUE3784 = 0; + ENUM_VALUE3785 = 1; + ENUM_VALUE3786 = 2; + ENUM_VALUE3787 = 3; + ENUM_VALUE3788 = 4; + ENUM_VALUE3789 = 5; + ENUM_VALUE3790 = 6; + ENUM_VALUE3791 = 7; + ENUM_VALUE3792 = 8; + ENUM_VALUE3793 = 9; + ENUM_VALUE3794 = 10; + ENUM_VALUE3795 = 11; + ENUM_VALUE3796 = 12; + ENUM_VALUE3797 = 13; + ENUM_VALUE3798 = 14; + ENUM_VALUE3799 = 15; + ENUM_VALUE3800 = 16; + ENUM_VALUE3801 = 20; + ENUM_VALUE3802 = 21; + ENUM_VALUE3803 = 50; +} + +enum Enum3851 { + ENUM_VALUE3852 = 0; + ENUM_VALUE3853 = 1; + ENUM_VALUE3854 = 2; + ENUM_VALUE3855 = 3; + ENUM_VALUE3856 = 4; + ENUM_VALUE3857 = 5; + ENUM_VALUE3858 = 6; + ENUM_VALUE3859 = 7; + ENUM_VALUE3860 = 8; + ENUM_VALUE3861 = 9; + ENUM_VALUE3862 = 10; + ENUM_VALUE3863 = 11; + ENUM_VALUE3864 = 12; + ENUM_VALUE3865 = 13; + ENUM_VALUE3866 = 14; + ENUM_VALUE3867 = 15; + ENUM_VALUE3868 = 16; + ENUM_VALUE3869 = 17; +} + +enum Enum5862 { + ENUM_VALUE5863 = 1; + ENUM_VALUE5864 = 2; + ENUM_VALUE5865 = 3; +} + +enum Enum5868 { + ENUM_VALUE5869 = 0; + ENUM_VALUE5870 = 1; + ENUM_VALUE5871 = 2; + ENUM_VALUE5872 = 3; +} + +enum Enum5873 { + ENUM_VALUE5874 = 0; + ENUM_VALUE5875 = 1; + ENUM_VALUE5876 = 2; +} + +enum Enum5904 { + ENUM_VALUE5905 = 0; + ENUM_VALUE5906 = 1; +} + +enum Enum5909 { + ENUM_VALUE5910 = 0; + ENUM_VALUE5911 = 1; +} + +enum Enum5912 { + ENUM_VALUE5913 = 0; + ENUM_VALUE5914 = 1; +} + +enum Enum5915 { + ENUM_VALUE5916 = 0; + ENUM_VALUE5917 = 1; + ENUM_VALUE5918 = 2; + ENUM_VALUE5919 = 3; +} + +enum Enum5920 { + ENUM_VALUE5921 = 0; + ENUM_VALUE5922 = 1; +} + +enum Enum5923 { + ENUM_VALUE5924 = 0; + ENUM_VALUE5925 = 1; + ENUM_VALUE5926 = 2; + ENUM_VALUE5927 = 3; +} + +enum Enum5928 { + ENUM_VALUE5929 = 0; + ENUM_VALUE5930 = 1; +} + +enum Enum5931 { + ENUM_VALUE5932 = 0; + ENUM_VALUE5933 = 1; + ENUM_VALUE5934 = 2; +} + +enum Enum5935 { + ENUM_VALUE5936 = 0; + ENUM_VALUE5937 = 1; + ENUM_VALUE5938 = 2; +} + +enum Enum5939 { + ENUM_VALUE5940 = 0; + ENUM_VALUE5941 = 1; + ENUM_VALUE5942 = 2; + ENUM_VALUE5943 = 3; + ENUM_VALUE5944 = 4; + ENUM_VALUE5945 = 5; +} + +enum Enum5946 { + ENUM_VALUE5947 = 0; + ENUM_VALUE5948 = 1; + ENUM_VALUE5949 = 2; + ENUM_VALUE5950 = 3; + ENUM_VALUE5951 = 4; + ENUM_VALUE5952 = 5; + ENUM_VALUE5953 = 6; + ENUM_VALUE5954 = 7; + ENUM_VALUE5955 = 8; + ENUM_VALUE5956 = 9; +} + +enum Enum5957 { + ENUM_VALUE5958 = 0; + ENUM_VALUE5959 = 1; + ENUM_VALUE5960 = 2; + ENUM_VALUE5961 = 3; +} + +enum Enum5962 { + ENUM_VALUE5963 = 0; + ENUM_VALUE5964 = 1; +} + +enum Enum6025 { + ENUM_VALUE6026 = 0; + ENUM_VALUE6027 = 1; + ENUM_VALUE6028 = 2; + ENUM_VALUE6029 = 3; + ENUM_VALUE6030 = 4; + ENUM_VALUE6031 = 5; + ENUM_VALUE6032 = 6; + ENUM_VALUE6033 = 7; + ENUM_VALUE6034 = 8; + ENUM_VALUE6035 = 9; + ENUM_VALUE6036 = 10; + ENUM_VALUE6037 = 11; + ENUM_VALUE6038 = 12; + ENUM_VALUE6039 = 13; + ENUM_VALUE6040 = 14; + ENUM_VALUE6041 = 15; + ENUM_VALUE6042 = 16; + ENUM_VALUE6043 = 17; + ENUM_VALUE6044 = 18; + ENUM_VALUE6045 = 19; + ENUM_VALUE6046 = 20; + ENUM_VALUE6047 = 21; +} + +enum Enum6111 { + ENUM_VALUE6112 = 1; + ENUM_VALUE6113 = 2; + ENUM_VALUE6114 = 3; + ENUM_VALUE6115 = 4; + ENUM_VALUE6116 = 5; + ENUM_VALUE6117 = 6; + ENUM_VALUE6118 = 7; + ENUM_VALUE6119 = 8; + ENUM_VALUE6120 = 9; + ENUM_VALUE6121 = 10; + ENUM_VALUE6122 = 11; + ENUM_VALUE6123 = 12; + ENUM_VALUE6124 = 13; + ENUM_VALUE6125 = 14; +} + +enum Enum6065 { + ENUM_VALUE6066 = 0; + ENUM_VALUE6067 = 1; + ENUM_VALUE6068 = 2; + ENUM_VALUE6069 = 3; + ENUM_VALUE6070 = 4; + ENUM_VALUE6071 = 5; + ENUM_VALUE6072 = 6; + ENUM_VALUE6073 = 7; + ENUM_VALUE6074 = 8; + ENUM_VALUE6075 = 9; + ENUM_VALUE6076 = 10; + ENUM_VALUE6077 = 11; + ENUM_VALUE6078 = 12; + ENUM_VALUE6079 = 13; + ENUM_VALUE6080 = 14; +} + +enum Enum6130 { + ENUM_VALUE6131 = 0; + ENUM_VALUE6132 = 1; +} + +enum Enum6579 { + ENUM_VALUE6580 = 0; + ENUM_VALUE6581 = 2; + ENUM_VALUE6582 = 3; + ENUM_VALUE6583 = 5; + ENUM_VALUE6584 = 10; + ENUM_VALUE6585 = 15; + ENUM_VALUE6586 = 25; + ENUM_VALUE6587 = 30; +} + +enum Enum6588 { + ENUM_VALUE6589 = 0; + ENUM_VALUE6590 = 1; + ENUM_VALUE6591 = 2; + ENUM_VALUE6592 = 3; + ENUM_VALUE6593 = 4; + ENUM_VALUE6594 = 5; + ENUM_VALUE6595 = 6; + ENUM_VALUE6596 = 7; + ENUM_VALUE6597 = 8; + ENUM_VALUE6598 = 9; + ENUM_VALUE6599 = 10; + ENUM_VALUE6600 = 11; + ENUM_VALUE6601 = 12; + ENUM_VALUE6602 = 13; + ENUM_VALUE6603 = 14; + ENUM_VALUE6604 = 15; + ENUM_VALUE6605 = 16; + ENUM_VALUE6606 = 17; + ENUM_VALUE6607 = 19; + ENUM_VALUE6608 = 20; + ENUM_VALUE6609 = 21; + ENUM_VALUE6610 = 22; + ENUM_VALUE6611 = 23; + ENUM_VALUE6612 = 24; + ENUM_VALUE6613 = 25; + ENUM_VALUE6614 = 26; + ENUM_VALUE6615 = 27; + ENUM_VALUE6616 = 28; + ENUM_VALUE6617 = 29; + ENUM_VALUE6618 = 30; + ENUM_VALUE6619 = 31; + ENUM_VALUE6620 = 32; + ENUM_VALUE6621 = 33; + ENUM_VALUE6622 = 34; +} + +enum Enum7288 { + ENUM_VALUE7289 = 0; + ENUM_VALUE7290 = 1; + ENUM_VALUE7291 = 2; + ENUM_VALUE7292 = 3; +} + +enum Enum7512 { + ENUM_VALUE7513 = 0; + ENUM_VALUE7514 = 1; + ENUM_VALUE7515 = 2; + ENUM_VALUE7516 = 3; + ENUM_VALUE7517 = 4; + ENUM_VALUE7518 = 5; + ENUM_VALUE7519 = 6; + ENUM_VALUE7520 = 7; +} + +enum Enum7922 { + ENUM_VALUE7923 = 1; + ENUM_VALUE7924 = 2; + ENUM_VALUE7925 = 3; + ENUM_VALUE7926 = 4; + ENUM_VALUE7927 = 5; +} + +enum Enum3476 { + ENUM_VALUE3477 = 0; + ENUM_VALUE3478 = 1; + ENUM_VALUE3479 = 2; + ENUM_VALUE3480 = 3; + ENUM_VALUE3481 = 4; + ENUM_VALUE3482 = 5; + ENUM_VALUE3483 = 6; + ENUM_VALUE3484 = 7; + ENUM_VALUE3485 = 8; + ENUM_VALUE3486 = 9; + ENUM_VALUE3487 = 10; + ENUM_VALUE3488 = 11; + ENUM_VALUE3489 = 12; + ENUM_VALUE3490 = 13; + ENUM_VALUE3491 = 14; + ENUM_VALUE3492 = 15; + ENUM_VALUE3493 = 16; + ENUM_VALUE3494 = 17; + ENUM_VALUE3495 = 18; + ENUM_VALUE3496 = 19; + ENUM_VALUE3497 = 20; + ENUM_VALUE3498 = 21; + ENUM_VALUE3499 = 22; + ENUM_VALUE3500 = 23; + ENUM_VALUE3501 = 24; + ENUM_VALUE3502 = 25; + ENUM_VALUE3503 = 26; + ENUM_VALUE3504 = 27; + ENUM_VALUE3505 = 28; + ENUM_VALUE3506 = 29; + ENUM_VALUE3507 = 30; + ENUM_VALUE3508 = 31; + ENUM_VALUE3509 = 32; + ENUM_VALUE3510 = 33; + ENUM_VALUE3511 = 34; + ENUM_VALUE3512 = 35; + ENUM_VALUE3513 = 36; + ENUM_VALUE3514 = 37; + ENUM_VALUE3515 = 38; + ENUM_VALUE3516 = 39; + ENUM_VALUE3517 = 40; + ENUM_VALUE3518 = 41; + ENUM_VALUE3519 = 42; + ENUM_VALUE3520 = 43; + ENUM_VALUE3521 = 44; + ENUM_VALUE3522 = 45; + ENUM_VALUE3523 = 46; + ENUM_VALUE3524 = 47; + ENUM_VALUE3525 = 48; + ENUM_VALUE3526 = 49; + ENUM_VALUE3527 = 50; + ENUM_VALUE3528 = 51; + ENUM_VALUE3529 = 52; + ENUM_VALUE3530 = 53; + ENUM_VALUE3531 = 54; + ENUM_VALUE3532 = 55; + ENUM_VALUE3533 = 56; + ENUM_VALUE3534 = 57; + ENUM_VALUE3535 = 58; + ENUM_VALUE3536 = 59; + ENUM_VALUE3537 = 60; + ENUM_VALUE3538 = 61; + ENUM_VALUE3539 = 62; + ENUM_VALUE3540 = 63; + ENUM_VALUE3541 = 64; + ENUM_VALUE3542 = 65; + ENUM_VALUE3543 = 66; + ENUM_VALUE3544 = 67; + ENUM_VALUE3545 = 68; + ENUM_VALUE3546 = 69; + ENUM_VALUE3547 = 70; + ENUM_VALUE3548 = 71; + ENUM_VALUE3549 = 72; + ENUM_VALUE3550 = 73; + ENUM_VALUE3551 = 74; + ENUM_VALUE3552 = 75; + ENUM_VALUE3553 = 76; + ENUM_VALUE3554 = 77; + ENUM_VALUE3555 = 78; + ENUM_VALUE3556 = 79; + ENUM_VALUE3557 = 80; + ENUM_VALUE3558 = 81; + ENUM_VALUE3559 = 82; + ENUM_VALUE3560 = 83; + ENUM_VALUE3561 = 84; + ENUM_VALUE3562 = 85; + ENUM_VALUE3563 = 86; + ENUM_VALUE3564 = 87; + ENUM_VALUE3565 = 88; + ENUM_VALUE3566 = 89; + ENUM_VALUE3567 = 90; + ENUM_VALUE3568 = 91; + ENUM_VALUE3569 = 92; + ENUM_VALUE3570 = 93; + ENUM_VALUE3571 = 94; + ENUM_VALUE3572 = 95; + ENUM_VALUE3573 = 96; + ENUM_VALUE3574 = 97; + ENUM_VALUE3575 = 98; + ENUM_VALUE3576 = 99; + ENUM_VALUE3577 = 100; + ENUM_VALUE3578 = 101; + ENUM_VALUE3579 = 102; + ENUM_VALUE3580 = 103; + ENUM_VALUE3581 = 104; + ENUM_VALUE3582 = 105; + ENUM_VALUE3583 = 106; + ENUM_VALUE3584 = 107; + ENUM_VALUE3585 = 108; + ENUM_VALUE3586 = 109; + ENUM_VALUE3587 = 110; + ENUM_VALUE3588 = 111; + ENUM_VALUE3589 = 112; + ENUM_VALUE3590 = 113; + ENUM_VALUE3591 = 114; + ENUM_VALUE3592 = 115; + ENUM_VALUE3593 = 116; + ENUM_VALUE3594 = 117; + ENUM_VALUE3595 = 118; + ENUM_VALUE3596 = 119; + ENUM_VALUE3597 = 120; + ENUM_VALUE3598 = 121; + ENUM_VALUE3599 = 122; + ENUM_VALUE3600 = 123; + ENUM_VALUE3601 = 124; + ENUM_VALUE3602 = 125; + ENUM_VALUE3603 = 126; + ENUM_VALUE3604 = 127; + ENUM_VALUE3605 = 128; + ENUM_VALUE3606 = 129; + ENUM_VALUE3607 = 130; + ENUM_VALUE3608 = 131; + ENUM_VALUE3609 = 132; + ENUM_VALUE3610 = 133; + ENUM_VALUE3611 = 134; + ENUM_VALUE3612 = 135; + ENUM_VALUE3613 = 136; + ENUM_VALUE3614 = 137; + ENUM_VALUE3615 = 138; + ENUM_VALUE3616 = 139; + ENUM_VALUE3617 = 140; + ENUM_VALUE3618 = 141; + ENUM_VALUE3619 = 142; + ENUM_VALUE3620 = 143; + ENUM_VALUE3621 = 144; + ENUM_VALUE3622 = 145; + ENUM_VALUE3623 = 146; + ENUM_VALUE3624 = 147; + ENUM_VALUE3625 = 148; + ENUM_VALUE3626 = 149; + ENUM_VALUE3627 = 150; + ENUM_VALUE3628 = 151; + ENUM_VALUE3629 = 152; + ENUM_VALUE3630 = 153; + ENUM_VALUE3631 = 154; + ENUM_VALUE3632 = 155; + ENUM_VALUE3633 = 156; + ENUM_VALUE3634 = 157; + ENUM_VALUE3635 = 158; + ENUM_VALUE3636 = 159; + ENUM_VALUE3637 = 160; + ENUM_VALUE3638 = 161; + ENUM_VALUE3639 = 162; + ENUM_VALUE3640 = 163; + ENUM_VALUE3641 = 164; + ENUM_VALUE3642 = 165; + ENUM_VALUE3643 = 166; + ENUM_VALUE3644 = 167; + ENUM_VALUE3645 = 168; + ENUM_VALUE3646 = 169; + ENUM_VALUE3647 = 170; + ENUM_VALUE3648 = 171; + ENUM_VALUE3649 = 172; + ENUM_VALUE3650 = 173; + ENUM_VALUE3651 = 174; + ENUM_VALUE3652 = 175; + ENUM_VALUE3653 = 176; + ENUM_VALUE3654 = 177; + ENUM_VALUE3655 = 178; + ENUM_VALUE3656 = 179; + ENUM_VALUE3657 = 180; + ENUM_VALUE3658 = 181; + ENUM_VALUE3659 = 182; + ENUM_VALUE3660 = 183; +} + +enum Enum10325 { + ENUM_VALUE10326 = 0; + ENUM_VALUE10327 = 1; + ENUM_VALUE10328 = 2; + ENUM_VALUE10329 = 3; + ENUM_VALUE10330 = 4; + ENUM_VALUE10331 = 5; + ENUM_VALUE10332 = 6; + ENUM_VALUE10333 = 7; + ENUM_VALUE10334 = 8; +} + +enum Enum10335 { ENUM_VALUE10336 = 0; } + +enum Enum10337 { + ENUM_VALUE10338 = 0; + ENUM_VALUE10339 = 1; +} + +enum Enum11901 { + ENUM_VALUE11902 = 0; + ENUM_VALUE11903 = 1; + ENUM_VALUE11904 = 2; + ENUM_VALUE11905 = 3; +} + +enum Enum12735 { + ENUM_VALUE12736 = 0; + ENUM_VALUE12737 = 1; + ENUM_VALUE12738 = 2; + ENUM_VALUE12739 = 3; +} + +enum Enum12871 { + ENUM_VALUE12872 = 1; + ENUM_VALUE12873 = 2; + ENUM_VALUE12874 = 3; + ENUM_VALUE12875 = 4; + ENUM_VALUE12876 = 5; + ENUM_VALUE12877 = 6; +} diff --git a/benchmarks/download_data.sh b/benchmarks/download_data.sh new file mode 100755 index 0000000000000..fa0729e9a336e --- /dev/null +++ b/benchmarks/download_data.sh @@ -0,0 +1,5 @@ +#! /bin/sh + +curl -O https://storage.googleapis.com/protobuf_opensource_benchmark_data/datasets.tar.gz +tar -zvxf datasets.tar.gz + diff --git a/benchmarks/generate_datasets.cc b/benchmarks/generate_datasets.cc deleted file mode 100644 index 61e7adf1ba3f0..0000000000000 --- a/benchmarks/generate_datasets.cc +++ /dev/null @@ -1,117 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include -#include -#include "benchmarks.pb.h" - -using benchmarks::BenchmarkDataset; -using google::protobuf::Descriptor; -using google::protobuf::DescriptorPool; -using google::protobuf::Message; -using google::protobuf::MessageFactory; - -std::set names; - -const char *file_prefix = "dataset."; -const char *file_suffix = ".pb"; - -void WriteFileWithPayloads(const std::string& name, - const std::string& message_name, - const std::vector& payload) { - if (!names.insert(name).second) { - std::cerr << "Duplicate test name: " << name << "\n"; - abort(); - } - - // First verify that this message name exists in our set of benchmark messages - // and that these payloads are valid for the given message. - const Descriptor* d = - DescriptorPool::generated_pool()->FindMessageTypeByName(message_name); - - if (!d) { - std::cerr << "For dataset " << name << ", no such message: " - << message_name << "\n"; - abort(); - } - - Message* m = MessageFactory::generated_factory()->GetPrototype(d)->New(); - - for (size_t i = 0; i < payload.size(); i++) { - if (!m->ParseFromString(payload[i])) { - std::cerr << "For dataset " << name << ", payload[" << i << "] fails " - << "to parse\n"; - abort(); - } - } - - BenchmarkDataset dataset; - dataset.set_name(name); - dataset.set_message_name(message_name); - for (size_t i = 0; i < payload.size(); i++) { - dataset.add_payload()->assign(payload[i]); - } - - std::ofstream writer; - std::string fname = file_prefix + name + file_suffix; - writer.open(fname.c_str()); - dataset.SerializeToOstream(&writer); - writer.close(); - - std::cerr << "Wrote dataset: " << fname << "\n"; -} - -void WriteFile(const std::string& name, const std::string& message_name, - const std::string& payload) { - std::vector payloads; - payloads.push_back(payload); - WriteFileWithPayloads(name, message_name, payloads); -} - -std::string ReadFile(const std::string& name) { - std::ifstream file(name.c_str()); - GOOGLE_CHECK(file.is_open()) << "Couldn't find file '" << name << - "', please make sure you are running " - "this command from the benchmarks/ " - "directory.\n"; - return std::string((std::istreambuf_iterator(file)), - std::istreambuf_iterator()); -} - -int main() { - WriteFile("google_message1_proto3", "benchmarks.proto3.GoogleMessage1", - ReadFile("google_message1.dat")); - WriteFile("google_message1_proto2", "benchmarks.proto2.GoogleMessage1", - ReadFile("google_message1.dat")); - - // Not in proto3 because it has a group, which is not supported. - WriteFile("google_message2", "benchmarks.proto2.GoogleMessage2", - ReadFile("google_message2.dat")); -} diff --git a/benchmarks/go/go_benchmark_test.go b/benchmarks/go/go_benchmark_test.go new file mode 100644 index 0000000000000..8c741b710649f --- /dev/null +++ b/benchmarks/go/go_benchmark_test.go @@ -0,0 +1,124 @@ +package main + +import ( + benchmarkWrapper "../tmp" + googleMessage1Proto2 "../tmp/datasets/google_message1/proto2" + googleMessage1Proto3 "../tmp/datasets/google_message1/proto3" + googleMessage2 "../tmp/datasets/google_message2" + googleMessage3 "../tmp/datasets/google_message3" + googleMessage4 "../tmp/datasets/google_message4" + "flag" + "github.com/golang/protobuf/proto" + "io/ioutil" + "testing" +) + +// Data is returned by the Load function. +type Dataset struct { + name string + newMessage func() proto.Message + marshaled [][]byte + unmarshaled []proto.Message +} + +var datasets []Dataset + +// This is used to getDefaultInstance for a message type. +func generateNewMessageFunction(dataset benchmarkWrapper.BenchmarkDataset) func() proto.Message { + switch dataset.MessageName { + case "benchmarks.proto3.GoogleMessage1": + return func() proto.Message { return new(googleMessage1Proto3.GoogleMessage1) } + case "benchmarks.proto2.GoogleMessage1": + return func() proto.Message { return new(googleMessage1Proto2.GoogleMessage1) } + case "benchmarks.proto2.GoogleMessage2": + return func() proto.Message { return new(googleMessage2.GoogleMessage2) } + case "benchmarks.google_message3.GoogleMessage3": + return func() proto.Message { return new(googleMessage3.GoogleMessage3) } + case "benchmarks.google_message4.GoogleMessage4": + return func() proto.Message { return new(googleMessage4.GoogleMessage4) } + default: + panic("Unknown message type: " + dataset.MessageName) + } +} + +func init() { + flag.Parse() + for _, f := range flag.Args() { + // Load the benchmark. + b, err := ioutil.ReadFile(f) + if err != nil { + panic(err) + } + + // Parse the benchmark. + var dm benchmarkWrapper.BenchmarkDataset + if err := proto.Unmarshal(b, &dm); err != nil { + panic(err) + } + + // Determine the concrete protobuf message type to use. + var ds Dataset + ds.newMessage = generateNewMessageFunction(dm) + + // Unmarshal each test message. + for _, payload := range dm.Payload { + ds.marshaled = append(ds.marshaled, payload) + m := ds.newMessage() + if err := proto.Unmarshal(payload, m); err != nil { + panic(err) + } + ds.unmarshaled = append(ds.unmarshaled, m) + } + ds.name = f + + datasets = append(datasets, ds) + } +} + +func Benchmark(b *testing.B) { + for _, ds := range datasets { + b.Run(ds.name, func(b *testing.B) { + b.Run("Unmarshal", func(b *testing.B) { + for i := 0; i < b.N; i++ { + for j, payload := range ds.marshaled { + out := ds.newMessage() + if err := proto.Unmarshal(payload, out); err != nil { + b.Fatalf("can't unmarshal message %d %v", j, err) + } + } + } + }) + b.Run("Marshal", func(b *testing.B) { + for i := 0; i < b.N; i++ { + for j, m := range ds.unmarshaled { + if _, err := proto.Marshal(m); err != nil { + b.Fatalf("can't marshal message %d %+v: %v", j, m, err) + } + } + } + }) + b.Run("Size", func(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, m := range ds.unmarshaled { + proto.Size(m) + } + } + }) + b.Run("Clone", func(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, m := range ds.unmarshaled { + proto.Clone(m) + } + } + }) + b.Run("Merge", func(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, m := range ds.unmarshaled { + out := ds.newMessage() + proto.Merge(out, m) + } + } + }) + }) + } +} diff --git a/benchmarks/google_message1.dat b/benchmarks/google_message1.dat deleted file mode 100644 index bc0f064cc2ebd..0000000000000 Binary files a/benchmarks/google_message1.dat and /dev/null differ diff --git a/benchmarks/google_message2.dat b/benchmarks/google_message2.dat deleted file mode 100644 index 06c09441b9e1a..0000000000000 Binary files a/benchmarks/google_message2.dat and /dev/null differ diff --git a/benchmarks/java/pom.xml b/benchmarks/java/pom.xml new file mode 100644 index 0000000000000..570bd6644fd7c --- /dev/null +++ b/benchmarks/java/pom.xml @@ -0,0 +1,98 @@ + + + + 4.0.0 + protobuf-java-benchmark + com.google.protobuf + 1.0.0 + Protocol Buffers [Benchmark] + The benchmark tools for Protobuf Java. + + + + com.google.protobuf + protobuf-java + ${protobuf.version} + jar + system + ${project.basedir}/lib/protobuf-java.jar + + + com.google.caliper + caliper + 1.0-beta-2 + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.4.1 + + + + jar-with-dependencies + + + + + com.mkyong.core.utils.App + + + + + + make-assembly + + package + + single + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-jar-plugin + 2.5 + + + + true + com.google.protocolbuffers.ProtoBench + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.4 + + + attach-sources + + jar-no-fork + + + + + + + + + diff --git a/benchmarks/java/src/main/java/com/google/protobuf/ProtoCaliperBenchmark.java b/benchmarks/java/src/main/java/com/google/protobuf/ProtoCaliperBenchmark.java new file mode 100644 index 0000000000000..a4402481b0a07 --- /dev/null +++ b/benchmarks/java/src/main/java/com/google/protobuf/ProtoCaliperBenchmark.java @@ -0,0 +1,214 @@ + +package com.google.protobuf; + +import com.google.caliper.BeforeExperiment; +import com.google.caliper.AfterExperiment; +import com.google.caliper.Benchmark; +import com.google.caliper.Param; +import com.google.caliper.api.VmOptions; +import com.google.protobuf.ByteString; +import com.google.protobuf.CodedOutputStream; +import com.google.protobuf.ExtensionRegistry; +import com.google.protobuf.Message; +import com.google.protobuf.benchmarks.Benchmarks.BenchmarkDataset; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.ArrayList; +import java.util.List; + +// Caliper set CICompilerCount to 1 for making sure compilation doesn't run in parallel with itself, +// This makes TieredCompilation not working. We just disable TieredCompilation by default. In master +// branch this has been disabled by default in caliper: +// https://github.com/google/caliper/blob/master/caliper-runner/src/main/java/com/google/caliper/runner/target/Jvm.java#L38:14 +// But this haven't been added into most recent release. +@VmOptions("-XX:-TieredCompilation") +public class ProtoCaliperBenchmark { + public enum BenchmarkMessageType { + GOOGLE_MESSAGE1_PROTO3 { + @Override ExtensionRegistry getExtensionRegistry() { return ExtensionRegistry.newInstance(); } + @Override + Message getDefaultInstance() { + return com.google.protobuf.benchmarks.BenchmarkMessage1Proto3.GoogleMessage1 + .getDefaultInstance(); + } + }, + GOOGLE_MESSAGE1_PROTO2 { + @Override ExtensionRegistry getExtensionRegistry() { return ExtensionRegistry.newInstance(); } + @Override + Message getDefaultInstance() { + return com.google.protobuf.benchmarks.BenchmarkMessage1Proto2.GoogleMessage1 + .getDefaultInstance(); + } + }, + GOOGLE_MESSAGE2 { + @Override ExtensionRegistry getExtensionRegistry() { return ExtensionRegistry.newInstance(); } + @Override + Message getDefaultInstance() { + return com.google.protobuf.benchmarks.BenchmarkMessage2.GoogleMessage2.getDefaultInstance(); + } + }, + GOOGLE_MESSAGE3 { + @Override + ExtensionRegistry getExtensionRegistry() { + ExtensionRegistry extensions = ExtensionRegistry.newInstance(); + com.google.protobuf.benchmarks.BenchmarkMessage38.registerAllExtensions(extensions); + com.google.protobuf.benchmarks.BenchmarkMessage37.registerAllExtensions(extensions); + com.google.protobuf.benchmarks.BenchmarkMessage36.registerAllExtensions(extensions); + com.google.protobuf.benchmarks.BenchmarkMessage35.registerAllExtensions(extensions); + com.google.protobuf.benchmarks.BenchmarkMessage34.registerAllExtensions(extensions); + com.google.protobuf.benchmarks.BenchmarkMessage33.registerAllExtensions(extensions); + com.google.protobuf.benchmarks.BenchmarkMessage32.registerAllExtensions(extensions); + com.google.protobuf.benchmarks.BenchmarkMessage31.registerAllExtensions(extensions); + com.google.protobuf.benchmarks.BenchmarkMessage3.registerAllExtensions(extensions); + return extensions; + } + @Override + Message getDefaultInstance() { + return com.google.protobuf.benchmarks.BenchmarkMessage3.GoogleMessage3.getDefaultInstance(); + } + }, + GOOGLE_MESSAGE4 { + @Override + ExtensionRegistry getExtensionRegistry() { + ExtensionRegistry extensions = ExtensionRegistry.newInstance(); + com.google.protobuf.benchmarks.BenchmarkMessage43.registerAllExtensions(extensions); + com.google.protobuf.benchmarks.BenchmarkMessage42.registerAllExtensions(extensions); + com.google.protobuf.benchmarks.BenchmarkMessage41.registerAllExtensions(extensions); + com.google.protobuf.benchmarks.BenchmarkMessage4.registerAllExtensions(extensions); + return extensions; + } + @Override + Message getDefaultInstance() { + return com.google.protobuf.benchmarks.BenchmarkMessage4.GoogleMessage4.getDefaultInstance(); + } + }; + + abstract ExtensionRegistry getExtensionRegistry(); + abstract Message getDefaultInstance(); + } + + private BenchmarkMessageType benchmarkMessageType; + @Param("") + private String dataFile; + + private byte[] inputData; + private BenchmarkDataset benchmarkDataset; + private Message defaultMessage; + private ExtensionRegistry extensions; + private List inputDataList; + private List inputStreamList; + private List inputStringList; + private List sampleMessageList; + + private BenchmarkMessageType getMessageType() throws IOException { + if (benchmarkDataset.getMessageName().equals("benchmarks.proto3.GoogleMessage1")) { + return BenchmarkMessageType.GOOGLE_MESSAGE1_PROTO3; + } else if (benchmarkDataset.getMessageName().equals("benchmarks.proto2.GoogleMessage1")) { + return BenchmarkMessageType.GOOGLE_MESSAGE1_PROTO2; + } else if (benchmarkDataset.getMessageName().equals("benchmarks.proto2.GoogleMessage2")) { + return BenchmarkMessageType.GOOGLE_MESSAGE2; + } else if (benchmarkDataset.getMessageName(). + equals("benchmarks.google_message3.GoogleMessage3")) { + return BenchmarkMessageType.GOOGLE_MESSAGE3; + } else if (benchmarkDataset.getMessageName(). + equals("benchmarks.google_message4.GoogleMessage4")) { + return BenchmarkMessageType.GOOGLE_MESSAGE4; + } else { + throw new IllegalStateException("Invalid DataFile! There's no testing message named " + + benchmarkDataset.getMessageName()); + } + } + + @BeforeExperiment + void setUp() throws IOException { + if (!dataFile.equals("")) { + RandomAccessFile file = new RandomAccessFile(new File(dataFile), "r"); + inputData = new byte[(int) file.length()]; + file.readFully(inputData); + benchmarkDataset = BenchmarkDataset.parseFrom(inputData); + benchmarkMessageType = getMessageType(); + } else { + inputData = new byte[0]; + benchmarkDataset = BenchmarkDataset.parseFrom(inputData); + benchmarkMessageType = BenchmarkMessageType.GOOGLE_MESSAGE2; + } + defaultMessage = benchmarkMessageType.getDefaultInstance(); + extensions = benchmarkMessageType.getExtensionRegistry(); + inputDataList = new ArrayList(); + inputStreamList = new ArrayList(); + inputStringList = new ArrayList(); + sampleMessageList = new ArrayList(); + + for (int i = 0; i < benchmarkDataset.getPayloadCount(); i++) { + byte[] singleInputData = benchmarkDataset.getPayload(i).toByteArray(); + inputDataList.add(benchmarkDataset.getPayload(i).toByteArray()); + inputStreamList.add(new ByteArrayInputStream( + benchmarkDataset.getPayload(i).toByteArray())); + inputStringList.add(benchmarkDataset.getPayload(i)); + sampleMessageList.add( + defaultMessage.newBuilderForType().mergeFrom(singleInputData, extensions).build()); + } + } + + + @Benchmark + void serializeToByteArray(int reps) throws IOException { + if (sampleMessageList.size() == 0) { + return; + } + for (int i = 0; i < reps; i++) { + for (int j = 0; j < sampleMessageList.size(); j++) { + sampleMessageList.get(j).toByteArray(); + } + } + } + + @Benchmark + void serializeToMemoryStream(int reps) throws IOException { + if (sampleMessageList.size() == 0) { + return; + } + for (int i = 0; i < reps; i++) { + for (int j = 0; j < sampleMessageList.size(); j++) { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + sampleMessageList.get(j).writeTo(output); + } + } + } + + @Benchmark + void deserializeFromByteArray(int reps) throws IOException { + if (inputDataList.size() == 0) { + return; + } + for (int i = 0; i < reps; i++) { + for (int j = 0; j < inputDataList.size(); j++) { + benchmarkMessageType.getDefaultInstance().getParserForType().parseFrom( + inputDataList.get(j), extensions); + } + } + } + + @Benchmark + void deserializeFromMemoryStream(int reps) throws IOException { + if (inputStreamList.size() == 0) { + return; + } + for (int i = 0; i < reps; i++) { + for (int j = 0; j < inputStreamList.size(); j++) { + benchmarkMessageType.getDefaultInstance().getParserForType().parseFrom( + inputStreamList.get(j), extensions); + inputStreamList.get(j).reset(); + } + } + } +} + + diff --git a/benchmarks/js/benchmark_suite.js b/benchmarks/js/benchmark_suite.js new file mode 100644 index 0000000000000..c5c3e5105a487 --- /dev/null +++ b/benchmarks/js/benchmark_suite.js @@ -0,0 +1,33 @@ +var benchmark = require("benchmark"); + +function newBenchmark(messageName, filename, language) { + var benches = []; + return { + suite: new benchmark.Suite(messageName + filename + language ) + .on("add", function(event) { + benches.push(event.target); + }) + .on("start", function() { + process.stdout.write( + "benchmarking message " + messageName + + " of dataset file " + filename + + "'s performance ..." + "\n\n"); + }) + .on("cycle", function(event) { + process.stdout.write(String(event.target) + "\n"); + }) + .on("complete", function() { + var getHz = function(bench) { + return 1 / (bench.stats.mean + bench.stats.moe); + } + benches.forEach(function(val, index) { + benches[index] = getHz(val); + }); + }), + benches: benches + } +} + +module.exports = { + newBenchmark: newBenchmark +} diff --git a/benchmarks/js/js_benchmark.js b/benchmarks/js/js_benchmark.js new file mode 100644 index 0000000000000..9ba4828969168 --- /dev/null +++ b/benchmarks/js/js_benchmark.js @@ -0,0 +1,82 @@ +require('./datasets/google_message1/proto2/benchmark_message1_proto2_pb.js'); +require('./datasets/google_message1/proto3/benchmark_message1_proto3_pb.js'); +require('./datasets/google_message2/benchmark_message2_pb.js'); +require('./datasets/google_message3/benchmark_message3_pb.js'); +require('./datasets/google_message4/benchmark_message4_pb.js'); +require('./benchmarks_pb.js'); + +var fs = require('fs'); +var benchmarkSuite = require("./benchmark_suite.js"); + + +function getNewPrototype(name) { + var message = eval("proto." + name); + if (typeof(message) == "undefined") { + throw "type " + name + " is undefined"; + } + return message; +} + +var results = []; +var json_file = ""; + +console.log("#####################################################"); +console.log("Js Benchmark: "); +process.argv.forEach(function(filename, index) { + if (index < 2) { + return; + } + if (filename.indexOf("--json_output") != -1) { + json_file = filename.replace(/^--json_output=/, ''); + return; + } + + var benchmarkDataset = + proto.benchmarks.BenchmarkDataset.deserializeBinary(fs.readFileSync(filename)); + var messageList = []; + var totalBytes = 0; + benchmarkDataset.getPayloadList().forEach(function(onePayload) { + var message = getNewPrototype(benchmarkDataset.getMessageName()); + messageList.push(message.deserializeBinary(onePayload)); + totalBytes += onePayload.length; + }); + + var scenarios = benchmarkSuite.newBenchmark( + benchmarkDataset.getMessageName(), filename, "js"); + scenarios.suite + .add("js deserialize", function() { + benchmarkDataset.getPayloadList().forEach(function(onePayload) { + var protoType = getNewPrototype(benchmarkDataset.getMessageName()); + protoType.deserializeBinary(onePayload); + }); + }) + .add("js serialize", function() { + var protoType = getNewPrototype(benchmarkDataset.getMessageName()); + messageList.forEach(function(message) { + message.serializeBinary(); + }); + }) + .run({"Async": false}); + + results.push({ + filename: filename, + benchmarks: { + protobufjs_decoding: scenarios.benches[0] * totalBytes / 1024 / 1024, + protobufjs_encoding: scenarios.benches[1] * totalBytes / 1024 / 1024 + } + }) + + console.log("Throughput for deserialize: " + + scenarios.benches[0] * totalBytes / 1024 / 1024 + "MB/s" ); + console.log("Throughput for serialize: " + + scenarios.benches[1] * totalBytes / 1024 / 1024 + "MB/s" ); + console.log(""); +}); +console.log("#####################################################"); + +if (json_file != "") { + fs.writeFile(json_file, JSON.stringify(results), (err) => { + if (err) throw err; + }); +} + diff --git a/benchmarks/php/PhpBenchmark.php b/benchmarks/php/PhpBenchmark.php new file mode 100644 index 0000000000000..d3db61d248dac --- /dev/null +++ b/benchmarks/php/PhpBenchmark.php @@ -0,0 +1,170 @@ +getPayload(); + for ($i = $payloads->count() - 1; $i >= 0; $i--) { + (new $args[1]())->mergeFromString($payloads->offsetGet($i)); + } + } + + // $args: array of message + static function serialize(&$args) { + foreach ($args as &$temp_message) { + $temp_message->serializeToString(); + } + } +} + +class Benchmark +{ + private $benchmark_name; + private $args; + private $benchmark_time; + private $total_bytes; + private $coefficient; + + public function __construct($benchmark_name, $args, $total_bytes, + $benchmark_time = 5.0) { + $this->args = $args; + $this->benchmark_name = $benchmark_name; + $this->benchmark_time = $benchmark_time; + $this->total_bytes = $total_bytes; + $this->coefficient = pow (10, 0) / pow(2, 20); + } + + public function runBenchmark() { + $t = $this->runBenchmarkWithTimes(1); + $times = ceil($this->benchmark_time / $t); + return $this->total_bytes * $times / + ($times == 1 ? $t : $this->runBenchmarkWithTimes($times)) * + $this->coefficient; + } + + private function runBenchmarkWithTimes($times) { + $st = microtime(true); + for ($i = 0; $i < $times; $i++) { + call_user_func_array($this->benchmark_name, array(&$this->args)); + } + $en = microtime(true); + return $en - $st; + } +} + +function getMessageName(&$dataset) { + switch ($dataset->getMessageName()) { + case "benchmarks.proto3.GoogleMessage1": + return "\Benchmarks\Proto3\GoogleMessage1"; + case "benchmarks.proto2.GoogleMessage1": + return "\Benchmarks\Proto2\GoogleMessage1"; + case "benchmarks.proto2.GoogleMessage2": + return "\Benchmarks\Proto2\GoogleMessage2"; + case "benchmarks.google_message3.GoogleMessage3": + return "\Benchmarks\Google_message3\GoogleMessage3"; + case "benchmarks.google_message4.GoogleMessage4": + return "\Benchmarks\Google_message4\GoogleMessage4"; + default: + exit("Message " . $dataset->getMessageName() . " not found !"); + } +} + +function runBenchmark($file, $behavior_prefix) { + $datafile = fopen($file, "r") or die("Unable to open file " . $file); + $bytes = fread($datafile, filesize($file)); + $dataset = new BenchmarkDataset(NULL); + $dataset->mergeFromString($bytes); + $message_name = getMessageName($dataset); + $message_list = array(); + $total_bytes = 0; + $payloads = $dataset->getPayload(); + for ($i = $payloads->count() - 1; $i >= 0; $i--) { + $new_message = new $message_name(); + $new_message->mergeFromString($payloads->offsetGet($i)); + array_push($message_list, $new_message); + $total_bytes += strlen($payloads->offsetGet($i)); + } + + $parse_benchmark = new Benchmark( + "\Google\Protobuf\Benchmark\BenchmarkMethod::parse", + array($dataset, $message_name), $total_bytes); + $serialize_benchmark = new Benchmark( + "\Google\Protobuf\Benchmark\BenchmarkMethod::serialize", + $message_list, $total_bytes); + + return array( + "filename" => $file, + "benchmarks" => array( + $behavior_prefix . "_parse" => $parse_benchmark->runBenchmark(), + $behavior_prefix . "_serailize" => $serialize_benchmark->runBenchmark() + ), + "message_name" => $dataset->getMessageName() + ); +} + +// main +$json_output = false; +$results = array(); +$behavior_prefix = ""; + +foreach ($argv as $index => $arg) { + if ($index == 0) { + continue; + } + if ($arg == "--json") { + $json_output = true; + } else if (strpos($arg, "--behavior_prefix") == 0) { + $behavior_prefix = str_replace("--behavior_prefix=", "", $arg); + } +} + +foreach ($argv as $index => $arg) { + if ($index == 0) { + continue; + } + if (substr($arg, 0, 2) == "--") { + continue; + } else { + array_push($results, runBenchmark($arg, $behavior_prefix)); + } +} + +if ($json_output) { + print json_encode($results); +} else { + print "PHP protobuf benchmark result:\n\n"; + foreach ($results as $result) { + printf("result for test data file: %s\n", $result["filename"]); + foreach ($result["benchmarks"] as $benchmark => $throughput) { + printf(" Throughput for benchmark %s: %.2f MB/s\n", + $benchmark, $throughput); + } + } +} + +?> diff --git a/benchmarks/php/autoload.php b/benchmarks/php/autoload.php new file mode 100644 index 0000000000000..52a8741f80f0b --- /dev/null +++ b/benchmarks/php/autoload.php @@ -0,0 +1,25 @@ + 6 && arg.substring(arg.length - 6) == ".proto") { + protoFiles.push(arg); + } else if (arg.length > 15 && arg.substring(0, 15) == "--include_path=") { + prefix = arg.substring(15); + } else if (index >= 2) { + argv.push(arg); + } +}); +protoFiles.forEach(function(val) { + argv.push(prefix + "/" + val); +}); + +pbjs.main(argv, function(err, output){ + if (err) { + console.log(err); + } +}); + diff --git a/benchmarks/protobuf.js/protobufjs_benchmark.js b/benchmarks/protobuf.js/protobufjs_benchmark.js new file mode 100644 index 0000000000000..e062d1c6b898b --- /dev/null +++ b/benchmarks/protobuf.js/protobufjs_benchmark.js @@ -0,0 +1,66 @@ +var root = require("./generated_bundle_code.js"); +var fs = require('fs'); +var benchmark = require("./node_modules/benchmark"); +var benchmarkSuite = require("./benchmark_suite.js"); + + +function getNewPrototype(name) { + var message = eval("root." + name); + if (typeof(message) == "undefined") { + throw "type " + name + " is undefined"; + } + return message; +} + + +var results = []; + +console.log("#####################################################"); +console.log("ProtobufJs Benchmark: "); +process.argv.forEach(function(filename, index) { + if (index < 2) { + return; + } + var benchmarkDataset = + root.benchmarks.BenchmarkDataset.decode(fs.readFileSync(filename)); + var messageList = []; + var totalBytes = 0; + benchmarkDataset.payload.forEach(function(onePayload) { + var message = getNewPrototype(benchmarkDataset.messageName); + messageList.push(message.decode(onePayload)); + totalBytes += onePayload.length; + }); + + var scenarios = benchmarkSuite.newBenchmark( + benchmarkDataset.messageName, filename, "protobufjs"); + scenarios.suite + .add("protobuf.js static decoding", function() { + benchmarkDataset.payload.forEach(function(onePayload) { + var protoType = getNewPrototype(benchmarkDataset.messageName); + protoType.decode(onePayload); + }); + }) + .add("protobuf.js static encoding", function() { + var protoType = getNewPrototype(benchmarkDataset.messageName); + messageList.forEach(function(message) { + protoType.encode(message).finish(); + }); + }) + .run({"Async": false}); + + results.push({ + filename: filename, + benchmarks: { + protobufjs_decoding: scenarios.benches[0] * totalBytes, + protobufjs_encoding: scenarios.benches[1] * totalBytes + } + }) + + console.log("Throughput for decoding: " + + scenarios.benches[0] * totalBytes / 1024 / 1024 + "MB/s" ); + console.log("Throughput for encoding: " + + scenarios.benches[1] * totalBytes / 1024 / 1024 + "MB/s" ); + console.log(""); +}); +console.log("#####################################################"); + diff --git a/benchmarks/python/__init__.py b/benchmarks/python/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/benchmarks/python/py_benchmark.py b/benchmarks/python/py_benchmark.py new file mode 100644 index 0000000000000..60e377e4b8cc4 --- /dev/null +++ b/benchmarks/python/py_benchmark.py @@ -0,0 +1,161 @@ +from __future__ import print_function +import sys +import os +import timeit +import math +import argparse +import fnmatch +import json + +parser = argparse.ArgumentParser(description="Python protobuf benchmark") +parser.add_argument("data_files", metavar="dataFile", nargs="+", + help="testing data files.") +parser.add_argument("--json", action="store_const", dest="json", + const="yes", default="no", + help="Whether to output json results") +parser.add_argument("--behavior_prefix", dest="behavior_prefix", + help="The output json format's behavior's name's prefix", + default="") +# BEGIN CPP GENERATED MESSAGE +parser.add_argument("--cpp_generated", action="store_const", + dest="cpp_generated", const="yes", default="no", + help="Whether to link generated code library") +# END CPP GENERATED MESSAGE +args = parser.parse_args() +# BEGIN CPP GENERATED MESSAGE +# CPP generated code must be linked before importing the generated Python code +# for the descriptor can be found in the pool +if args.cpp_generated != "no": + sys.path.append( os.path.dirname( os.path.dirname( os.path.abspath(__file__) ) ) + "/.libs" ) + import libbenchmark_messages + sys.path.append( os.path.dirname( os.path.dirname( os.path.abspath(__file__) ) ) + "/tmp" ) +# END CPP GENERATED MESSAGE + + +import datasets.google_message1.proto2.benchmark_message1_proto2_pb2 as benchmark_message1_proto2_pb2 +import datasets.google_message1.proto3.benchmark_message1_proto3_pb2 as benchmark_message1_proto3_pb2 +import datasets.google_message2.benchmark_message2_pb2 as benchmark_message2_pb2 +import datasets.google_message3.benchmark_message3_pb2 as benchmark_message3_pb2 +import datasets.google_message4.benchmark_message4_pb2 as benchmark_message4_pb2 +import benchmarks_pb2 as benchmarks_pb2 + + +def run_one_test(filename): + data = open(filename, "rb").read() + benchmark_dataset = benchmarks_pb2.BenchmarkDataset() + benchmark_dataset.ParseFromString(data) + total_bytes = 0 + for payload in benchmark_dataset.payload: + total_bytes += len(payload) + benchmark_util = Benchmark(full_iteration=len(benchmark_dataset.payload), + module="py_benchmark", + setup_method="init", + total_bytes=total_bytes) + result={} + result["filename"] = filename + result["message_name"] = benchmark_dataset.message_name + result["benchmarks"] = {} + benchmark_util.set_test_method("parse_from_benchmark") + result["benchmarks"][args.behavior_prefix + "_parse_from_benchmark"] = \ + benchmark_util.run_benchmark(setup_method_args='"%s"' % (filename)) + benchmark_util.set_test_method("serialize_to_benchmark") + result["benchmarks"][args.behavior_prefix + "_serialize_to_benchmark"] = \ + benchmark_util.run_benchmark(setup_method_args='"%s"' % (filename)) + return result + + +def init(filename): + global benchmark_dataset, message_class, message_list, counter, total_bytes + message_list=[] + counter = 0 + total_bytes = 0 + data = open(filename, "rb").read() + benchmark_dataset = benchmarks_pb2.BenchmarkDataset() + benchmark_dataset.ParseFromString(data) + + if benchmark_dataset.message_name == "benchmarks.proto3.GoogleMessage1": + message_class = benchmark_message1_proto3_pb2.GoogleMessage1 + elif benchmark_dataset.message_name == "benchmarks.proto2.GoogleMessage1": + message_class = benchmark_message1_proto2_pb2.GoogleMessage1 + elif benchmark_dataset.message_name == "benchmarks.proto2.GoogleMessage2": + message_class = benchmark_message2_pb2.GoogleMessage2 + elif benchmark_dataset.message_name == "benchmarks.google_message3.GoogleMessage3": + message_class = benchmark_message3_pb2.GoogleMessage3 + elif benchmark_dataset.message_name == "benchmarks.google_message4.GoogleMessage4": + message_class = benchmark_message4_pb2.GoogleMessage4 + else: + raise IOError("Message %s not found!" % (benchmark_dataset.message_name)) + + for one_payload in benchmark_dataset.payload: + temp = message_class() + temp.ParseFromString(one_payload) + message_list.append(temp) + total_bytes += len(one_payload) + + +def parse_from_benchmark(): + global counter, message_class, benchmark_dataset + m = message_class().ParseFromString(benchmark_dataset.payload[counter % len(benchmark_dataset.payload)]) + counter = counter + 1 + + +def serialize_to_benchmark(): + global counter, message_list, message_class + s = message_list[counter % len(benchmark_dataset.payload)].SerializeToString() + counter = counter + 1 + + +class Benchmark: + def __init__(self, module=None, test_method=None, + setup_method=None, total_bytes=None, full_iteration = 1): + self.full_iteration = full_iteration + self.module = module + self.test_method = test_method + self.setup_method = setup_method + self.total_bytes = total_bytes + + def set_test_method(self, test_method): + self.test_method = test_method + + def full_setup_code(self, setup_method_args=''): + setup_code = "" + setup_code += "from %s import %s\n" % (self.module, self.test_method) + setup_code += "from %s import %s\n" % (self.module, self.setup_method) + setup_code += "%s(%s)\n" % (self.setup_method, setup_method_args) + return setup_code + + def dry_run(self, test_method_args='', setup_method_args=''): + return timeit.timeit(stmt="%s(%s)" % (self.test_method, test_method_args), + setup=self.full_setup_code(setup_method_args), + number=self.full_iteration); + + def run_benchmark(self, test_method_args='', setup_method_args=''): + reps = self.full_iteration; + t = self.dry_run(test_method_args, setup_method_args); + if t < 3 : + reps = int(math.ceil(3 / t)) * self.full_iteration + if reps != self.full_iteration: + t = timeit.timeit(stmt="%s(%s)" % (self.test_method, test_method_args), + setup=self.full_setup_code(setup_method_args), + number=reps); + return self.total_bytes * 1.0 / 2 ** 20 / (1.0 * t / reps * self.full_iteration) + + +if __name__ == "__main__": + results = [] + for file in args.data_files: + results.append(run_one_test(file)) + + if args.json != "no": + print(json.dumps(results)) + else: + for result in results: + print("Message %s of dataset file %s" % \ + (result["message_name"], result["filename"])) + print("Average throughput for parse_from_benchmark: %.2f MB/s" % \ + (result["benchmarks"][ \ + args.behavior_prefix + "_parse_from_benchmark"])) + print("Average throughput for serialize_to_benchmark: %.2f MB/s" % \ + (result["benchmarks"][ \ + args.behavior_prefix + "_serialize_to_benchmark"])) + print("") diff --git a/benchmarks/python/python_benchmark_messages.cc b/benchmarks/python/python_benchmark_messages.cc new file mode 100644 index 0000000000000..ded16fe96e952 --- /dev/null +++ b/benchmarks/python/python_benchmark_messages.cc @@ -0,0 +1,29 @@ +#include + +#include "benchmarks.pb.h" +#include "datasets/google_message1/proto2/benchmark_message1_proto2.pb.h" +#include "datasets/google_message1/proto3/benchmark_message1_proto3.pb.h" +#include "datasets/google_message2/benchmark_message2.pb.h" +#include "datasets/google_message3/benchmark_message3.pb.h" +#include "datasets/google_message4/benchmark_message4.pb.h" + +static PyMethodDef python_benchmark_methods[] = { + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + + +PyMODINIT_FUNC +initlibbenchmark_messages() { + benchmarks::BenchmarkDataset().descriptor(); + benchmarks::proto3::GoogleMessage1().descriptor(); + benchmarks::proto2::GoogleMessage1().descriptor(); + benchmarks::proto2::GoogleMessage2().descriptor(); + benchmarks::google_message3::GoogleMessage3().descriptor(); + benchmarks::google_message4::GoogleMessage4().descriptor(); + + PyObject *m; + + m = Py_InitModule("libbenchmark_messages", python_benchmark_methods); + if (m == NULL) + return; +} diff --git a/benchmarks/readme.txt b/benchmarks/readme.txt deleted file mode 100644 index b08b8bc09caba..0000000000000 --- a/benchmarks/readme.txt +++ /dev/null @@ -1,46 +0,0 @@ -Contents --------- - -This folder contains three kinds of file: - -- Code, such as ProtoBench.java, to build the benchmarking framework. -- Protocol buffer definitions (.proto files) -- Sample data files - -If we end up with a lot of different benchmarks it may be worth -separating these out info different directories, but while there are -so few they might as well all be together. - -Running a benchmark (Java) --------------------------- - -1) Build protoc and the Java protocol buffer library. The examples - below assume a jar file (protobuf.jar) has been built and copied - into this directory. - -2) Build ProtoBench: - $ javac -d tmp -cp protobuf.jar ProtoBench.java - -3) Generate code for the relevant benchmark protocol buffer, e.g. - $ protoc --java_out=tmp google_size.proto - -4) Build the generated code, e.g. - $ javac -d tmp -cp protobuf.jar tmp/benchmarks/*.java - -5) Run the test. Arguments are given in pairs - the first argument - is the descriptor type; the second is the filename. For example: - $ java -cp tmp:protobuf.jar com.google.protocolbuffers.ProtoBench \ - 'benchmarks.GoogleSize$SizeMessage1' google_message1.dat \ - 'benchmarks.GoogleSize$SizeMessage2' google_message2.dat - -6) Wait! Each test runs for around 30 seconds, and there are 8 tests - per class/data combination. The above command would therefore take - about 8 minutes to run. - - -Benchmarks available --------------------- - -From Google: -google_size.proto, -messages google_message1.dat and google_message2.dat. diff --git a/benchmarks/util/__init__.py b/benchmarks/util/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/benchmarks/util/big_query_utils.py b/benchmarks/util/big_query_utils.py new file mode 100755 index 0000000000000..aea55bbd89639 --- /dev/null +++ b/benchmarks/util/big_query_utils.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python2.7 + +from __future__ import print_function +import argparse +import json +import uuid +import httplib2 + +from apiclient import discovery +from apiclient.errors import HttpError +from oauth2client.client import GoogleCredentials + +# 30 days in milliseconds +_EXPIRATION_MS = 30 * 24 * 60 * 60 * 1000 +NUM_RETRIES = 3 + + +def create_big_query(): + """Authenticates with cloud platform and gets a BiqQuery service object + """ + creds = GoogleCredentials.get_application_default() + return discovery.build( + 'bigquery', 'v2', credentials=creds, cache_discovery=False) + + +def create_dataset(biq_query, project_id, dataset_id): + is_success = True + body = { + 'datasetReference': { + 'projectId': project_id, + 'datasetId': dataset_id + } + } + + try: + dataset_req = biq_query.datasets().insert( + projectId=project_id, body=body) + dataset_req.execute(num_retries=NUM_RETRIES) + except HttpError as http_error: + if http_error.resp.status == 409: + print('Warning: The dataset %s already exists' % dataset_id) + else: + # Note: For more debugging info, print "http_error.content" + print('Error in creating dataset: %s. Err: %s' % (dataset_id, + http_error)) + is_success = False + return is_success + + +def create_table(big_query, project_id, dataset_id, table_id, table_schema, + description): + fields = [{ + 'name': field_name, + 'type': field_type, + 'description': field_description + } for (field_name, field_type, field_description) in table_schema] + return create_table2(big_query, project_id, dataset_id, table_id, fields, + description) + + +def create_partitioned_table(big_query, + project_id, + dataset_id, + table_id, + table_schema, + description, + partition_type='DAY', + expiration_ms=_EXPIRATION_MS): + """Creates a partitioned table. By default, a date-paritioned table is created with + each partition lasting 30 days after it was last modified. + """ + fields = [{ + 'name': field_name, + 'type': field_type, + 'description': field_description + } for (field_name, field_type, field_description) in table_schema] + return create_table2(big_query, project_id, dataset_id, table_id, fields, + description, partition_type, expiration_ms) + + +def create_table2(big_query, + project_id, + dataset_id, + table_id, + fields_schema, + description, + partition_type=None, + expiration_ms=None): + is_success = True + + body = { + 'description': description, + 'schema': { + 'fields': fields_schema + }, + 'tableReference': { + 'datasetId': dataset_id, + 'projectId': project_id, + 'tableId': table_id + } + } + + if partition_type and expiration_ms: + body["timePartitioning"] = { + "type": partition_type, + "expirationMs": expiration_ms + } + + try: + table_req = big_query.tables().insert( + projectId=project_id, datasetId=dataset_id, body=body) + res = table_req.execute(num_retries=NUM_RETRIES) + print('Successfully created %s "%s"' % (res['kind'], res['id'])) + except HttpError as http_error: + if http_error.resp.status == 409: + print('Warning: Table %s already exists' % table_id) + else: + print('Error in creating table: %s. Err: %s' % (table_id, + http_error)) + is_success = False + return is_success + + +def patch_table(big_query, project_id, dataset_id, table_id, fields_schema): + is_success = True + + body = { + 'schema': { + 'fields': fields_schema + }, + 'tableReference': { + 'datasetId': dataset_id, + 'projectId': project_id, + 'tableId': table_id + } + } + + try: + table_req = big_query.tables().patch( + projectId=project_id, + datasetId=dataset_id, + tableId=table_id, + body=body) + res = table_req.execute(num_retries=NUM_RETRIES) + print('Successfully patched %s "%s"' % (res['kind'], res['id'])) + except HttpError as http_error: + print('Error in creating table: %s. Err: %s' % (table_id, http_error)) + is_success = False + return is_success + + +def insert_rows(big_query, project_id, dataset_id, table_id, rows_list): + is_success = True + body = {'rows': rows_list} + try: + insert_req = big_query.tabledata().insertAll( + projectId=project_id, + datasetId=dataset_id, + tableId=table_id, + body=body) + res = insert_req.execute(num_retries=NUM_RETRIES) + if res.get('insertErrors', None): + print('Error inserting rows! Response: %s' % res) + is_success = False + except HttpError as http_error: + print('Error inserting rows to the table %s' % table_id) + is_success = False + + return is_success + + +def sync_query_job(big_query, project_id, query, timeout=5000): + query_data = {'query': query, 'timeoutMs': timeout} + query_job = None + try: + query_job = big_query.jobs().query( + projectId=project_id, + body=query_data).execute(num_retries=NUM_RETRIES) + except HttpError as http_error: + print('Query execute job failed with error: %s' % http_error) + print(http_error.content) + return query_job + + + # List of (column name, column type, description) tuples +def make_row(unique_row_id, row_values_dict): + """row_values_dict is a dictionary of column name and column value. + """ + return {'insertId': unique_row_id, 'json': row_values_dict} diff --git a/benchmarks/util/data_proto2_to_proto3_util.h b/benchmarks/util/data_proto2_to_proto3_util.h new file mode 100644 index 0000000000000..5eea850900ae7 --- /dev/null +++ b/benchmarks/util/data_proto2_to_proto3_util.h @@ -0,0 +1,64 @@ +#ifndef PROTOBUF_BENCHMARKS_UTIL_DATA_PROTO2_TO_PROTO3_UTIL_H_ +#define PROTOBUF_BENCHMARKS_UTIL_DATA_PROTO2_TO_PROTO3_UTIL_H_ + +#include "google/protobuf/message.h" +#include "google/protobuf/descriptor.h" + +using google::protobuf::FieldDescriptor; +using google::protobuf::Message; +using google::protobuf::Reflection; + +namespace google { +namespace protobuf { +namespace util { + +class DataStripper { + public: + void StripMessage(Message *message) { + std::vector set_fields; + const Reflection* reflection = message->GetReflection(); + reflection->ListFields(*message, &set_fields); + + for (size_t i = 0; i < set_fields.size(); i++) { + const FieldDescriptor* field = set_fields[i]; + if (ShouldBeClear(field)) { + reflection->ClearField(message, field); + continue; + } + if (field->type() == FieldDescriptor::TYPE_MESSAGE) { + if (field->is_repeated()) { + for (int j = 0; j < reflection->FieldSize(*message, field); j++) { + StripMessage(reflection->MutableRepeatedMessage(message, field, j)); + } + } else { + StripMessage(reflection->MutableMessage(message, field)); + } + } + } + + reflection->MutableUnknownFields(message)->Clear(); + } + private: + virtual bool ShouldBeClear(const FieldDescriptor *field) = 0; +}; + +class GogoDataStripper : public DataStripper { + private: + virtual bool ShouldBeClear(const FieldDescriptor *field) { + return field->type() == FieldDescriptor::TYPE_GROUP; + } +}; + +class Proto3DataStripper : public DataStripper { + private: + virtual bool ShouldBeClear(const FieldDescriptor *field) { + return field->type() == FieldDescriptor::TYPE_GROUP || + field->is_extension(); + } +}; + +} // namespace util +} // namespace protobuf +} // namespace google + +#endif // PROTOBUF_BENCHMARKS_UTIL_DATA_PROTO2_TO_PROTO3_UTIL_H_ diff --git a/benchmarks/util/gogo_data_scrubber.cc b/benchmarks/util/gogo_data_scrubber.cc new file mode 100644 index 0000000000000..9ef57b0da041f --- /dev/null +++ b/benchmarks/util/gogo_data_scrubber.cc @@ -0,0 +1,74 @@ +#include "benchmarks.pb.h" +#include "datasets/google_message1/proto2/benchmark_message1_proto2.pb.h" +#include "datasets/google_message1/proto3/benchmark_message1_proto3.pb.h" +#include "datasets/google_message2/benchmark_message2.pb.h" +#include "datasets/google_message3/benchmark_message3.pb.h" +#include "datasets/google_message4/benchmark_message4.pb.h" +#include "data_proto2_to_proto3_util.h" + +#include + +using google::protobuf::util::GogoDataStripper; + +std::string ReadFile(const std::string& name) { + std::ifstream file(name.c_str()); + GOOGLE_CHECK(file.is_open()) << "Couldn't find file '" + << name + << "', please make sure you are running this command from the benchmarks" + << " directory.\n"; + return std::string((std::istreambuf_iterator(file)), + std::istreambuf_iterator()); +} + +int main(int argc, char *argv[]) { + if (argc % 2 == 0 || argc == 1) { + std::cerr << "Usage: [input_files] [output_file_names] where " << + "input_files are one to one mapping to output_file_names." << + std::endl; + return 1; + } + + for (int i = argc / 2; i > 0; i--) { + const std::string &input_file = argv[i]; + const std::string &output_file = argv[i + argc / 2]; + + std::cerr << "Generating " << input_file + << " to " << output_file << std::endl; + benchmarks::BenchmarkDataset dataset; + Message* message; + std::string dataset_payload = ReadFile(input_file); + GOOGLE_CHECK(dataset.ParseFromString(dataset_payload)) + << "Can' t parse data file " << input_file; + + if (dataset.message_name() == "benchmarks.proto3.GoogleMessage1") { + message = new benchmarks::proto3::GoogleMessage1; + } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage1") { + message = new benchmarks::proto2::GoogleMessage1; + } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage2") { + message = new benchmarks::proto2::GoogleMessage2; + } else if (dataset.message_name() == + "benchmarks.google_message3.GoogleMessage3") { + message = new benchmarks::google_message3::GoogleMessage3; + } else if (dataset.message_name() == + "benchmarks.google_message4.GoogleMessage4") { + message = new benchmarks::google_message4::GoogleMessage4; + } else { + std::cerr << "Unknown message type: " << dataset.message_name(); + exit(1); + } + + for (int i = 0; i < dataset.payload_size(); i++) { + message->ParseFromString(dataset.payload(i)); + GogoDataStripper stripper; + stripper.StripMessage(message); + dataset.set_payload(i, message->SerializeAsString()); + } + + std::ofstream ofs(output_file); + ofs << dataset.SerializeAsString(); + ofs.close(); + } + + + return 0; +} diff --git a/benchmarks/util/proto3_data_stripper.cc b/benchmarks/util/proto3_data_stripper.cc new file mode 100644 index 0000000000000..3096c4c115dcc --- /dev/null +++ b/benchmarks/util/proto3_data_stripper.cc @@ -0,0 +1,74 @@ +#include "benchmarks.pb.h" +#include "datasets/google_message1/proto2/benchmark_message1_proto2.pb.h" +#include "datasets/google_message1/proto3/benchmark_message1_proto3.pb.h" +#include "datasets/google_message2/benchmark_message2.pb.h" +#include "datasets/google_message3/benchmark_message3.pb.h" +#include "datasets/google_message4/benchmark_message4.pb.h" +#include "data_proto2_to_proto3_util.h" + +#include + +using google::protobuf::util::Proto3DataStripper; + +std::string ReadFile(const std::string& name) { + std::ifstream file(name.c_str()); + GOOGLE_CHECK(file.is_open()) << "Couldn't find file '" + << name + << "', please make sure you are running this command from the benchmarks" + << " directory.\n"; + return std::string((std::istreambuf_iterator(file)), + std::istreambuf_iterator()); +} + +int main(int argc, char *argv[]) { + if (argc % 2 == 0 || argc == 1) { + std::cerr << "Usage: [input_files] [output_file_names] where " << + "input_files are one to one mapping to output_file_names." << + std::endl; + return 1; + } + + for (int i = argc / 2; i > 0; i--) { + const std::string &input_file = argv[i]; + const std::string &output_file = argv[i + argc / 2]; + + std::cerr << "Generating " << input_file + << " to " << output_file << std::endl; + benchmarks::BenchmarkDataset dataset; + Message* message; + std::string dataset_payload = ReadFile(input_file); + GOOGLE_CHECK(dataset.ParseFromString(dataset_payload)) + << "Can' t parse data file " << input_file; + + if (dataset.message_name() == "benchmarks.proto3.GoogleMessage1") { + message = new benchmarks::proto3::GoogleMessage1; + } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage1") { + message = new benchmarks::proto2::GoogleMessage1; + } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage2") { + message = new benchmarks::proto2::GoogleMessage2; + } else if (dataset.message_name() == + "benchmarks.google_message3.GoogleMessage3") { + message = new benchmarks::google_message3::GoogleMessage3; + } else if (dataset.message_name() == + "benchmarks.google_message4.GoogleMessage4") { + message = new benchmarks::google_message4::GoogleMessage4; + } else { + std::cerr << "Unknown message type: " << dataset.message_name(); + exit(1); + } + + for (int i = 0; i < dataset.payload_size(); i++) { + message->ParseFromString(dataset.payload(i)); + Proto3DataStripper stripper; + stripper.StripMessage(message); + dataset.set_payload(i, message->SerializeAsString()); + } + + std::ofstream ofs(output_file); + ofs << dataset.SerializeAsString(); + ofs.close(); + } + + + return 0; +} diff --git a/benchmarks/util/protoc-gen-gogoproto.cc b/benchmarks/util/protoc-gen-gogoproto.cc new file mode 100644 index 0000000000000..9c1b3d04e8ef8 --- /dev/null +++ b/benchmarks/util/protoc-gen-gogoproto.cc @@ -0,0 +1,103 @@ +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/io/zero_copy_stream.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "schema_proto2_to_proto3_util.h" + +#include "google/protobuf/compiler/plugin.h" + +using google::protobuf::FileDescriptorProto; +using google::protobuf::FileDescriptor; +using google::protobuf::DescriptorPool; +using google::protobuf::io::Printer; +using google::protobuf::util::SchemaGroupStripper; +using google::protobuf::util::EnumScrubber; + +namespace google { +namespace protobuf { +namespace compiler { + +namespace { + +string StripProto(string filename) { + if (filename.substr(filename.size() - 11) == ".protodevel") { + // .protodevel + return filename.substr(0, filename.size() - 11); + } else { + // .proto + return filename.substr(0, filename.size() - 6); + } +} + +DescriptorPool new_pool_; + +} // namespace + +class GoGoProtoGenerator : public CodeGenerator { + public: + virtual bool GenerateAll(const std::vector& files, + const string& parameter, + GeneratorContext* context, + string* error) const { + for (int i = 0; i < files.size(); i++) { + for (auto file : files) { + bool can_generate = + (new_pool_.FindFileByName(file->name()) == nullptr); + for (int j = 0; j < file->dependency_count(); j++) { + can_generate &= (new_pool_.FindFileByName( + file->dependency(j)->name()) != nullptr); + } + for (int j = 0; j < file->public_dependency_count(); j++) { + can_generate &= (new_pool_.FindFileByName( + file->public_dependency(j)->name()) != nullptr); + } + for (int j = 0; j < file->weak_dependency_count(); j++) { + can_generate &= (new_pool_.FindFileByName( + file->weak_dependency(j)->name()) != nullptr); + } + if (can_generate) { + Generate(file, parameter, context, error); + break; + } + } + } + + return true; + } + + virtual bool Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* context, + string* error) const { + FileDescriptorProto new_file; + file->CopyTo(&new_file); + SchemaGroupStripper::StripFile(file, &new_file); + + EnumScrubber enum_scrubber; + enum_scrubber.ScrubFile(&new_file); + + string filename = file->name(); + string basename = StripProto(filename); + + std::vector> option_pairs; + ParseGeneratorParameter(parameter, &option_pairs); + + std::unique_ptr output( + context->Open(basename + ".proto")); + string content = new_pool_.BuildFile(new_file)->DebugString(); + Printer printer(output.get(), '$'); + printer.WriteRaw(content.c_str(), content.size()); + + return true; + } +}; + +} // namespace compiler +} // namespace protobuf +} // namespace google + +int main(int argc, char* argv[]) { + google::protobuf::compiler::GoGoProtoGenerator generator; + return google::protobuf::compiler::PluginMain(argc, argv, &generator); +} diff --git a/benchmarks/util/protoc-gen-proto2_to_proto3.cc b/benchmarks/util/protoc-gen-proto2_to_proto3.cc new file mode 100644 index 0000000000000..d0a8902347517 --- /dev/null +++ b/benchmarks/util/protoc-gen-proto2_to_proto3.cc @@ -0,0 +1,115 @@ +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/io/zero_copy_stream.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "schema_proto2_to_proto3_util.h" + +#include "google/protobuf/compiler/plugin.h" + +using google::protobuf::FileDescriptorProto; +using google::protobuf::FileDescriptor; +using google::protobuf::DescriptorPool; +using google::protobuf::io::Printer; +using google::protobuf::util::SchemaGroupStripper; +using google::protobuf::util::EnumScrubber; +using google::protobuf::util::ExtensionStripper; +using google::protobuf::util::FieldScrubber; + +namespace google { +namespace protobuf { +namespace compiler { + +namespace { + +string StripProto(string filename) { + return filename.substr(0, filename.rfind(".proto")); +} + +DescriptorPool* GetPool() { + static DescriptorPool *pool = new DescriptorPool(); + return pool; +} + +} // namespace + +class Proto2ToProto3Generator final : public CodeGenerator { + public: + bool GenerateAll(const std::vector& files, + const string& parameter, + GeneratorContext* context, + string* error) const { + for (int i = 0; i < files.size(); i++) { + for (auto file : files) { + if (CanGenerate(file)) { + Generate(file, parameter, context, error); + break; + } + } + } + + return true; + } + + bool Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* context, + string* error) const { + FileDescriptorProto new_file; + file->CopyTo(&new_file); + SchemaGroupStripper::StripFile(file, &new_file); + + EnumScrubber enum_scrubber; + enum_scrubber.ScrubFile(&new_file); + ExtensionStripper::StripFile(&new_file); + FieldScrubber::ScrubFile(&new_file); + new_file.set_syntax("proto3"); + + string filename = file->name(); + string basename = StripProto(filename); + + std::vector> option_pairs; + ParseGeneratorParameter(parameter, &option_pairs); + + std::unique_ptr output( + context->Open(basename + ".proto")); + string content = GetPool()->BuildFile(new_file)->DebugString(); + Printer printer(output.get(), '$'); + printer.WriteRaw(content.c_str(), content.size()); + + return true; + } + private: + bool CanGenerate(const FileDescriptor* file) const { + if (GetPool()->FindFileByName(file->name()) != nullptr) { + return false; + } + for (int j = 0; j < file->dependency_count(); j++) { + if (GetPool()->FindFileByName(file->dependency(j)->name()) == nullptr) { + return false; + } + } + for (int j = 0; j < file->public_dependency_count(); j++) { + if (GetPool()->FindFileByName( + file->public_dependency(j)->name()) == nullptr) { + return false; + } + } + for (int j = 0; j < file->weak_dependency_count(); j++) { + if (GetPool()->FindFileByName( + file->weak_dependency(j)->name()) == nullptr) { + return false; + } + } + return true; + } +}; + +} // namespace compiler +} // namespace protobuf +} // namespace google + +int main(int argc, char* argv[]) { + google::protobuf::compiler::Proto2ToProto3Generator generator; + return google::protobuf::compiler::PluginMain(argc, argv, &generator); +} diff --git a/benchmarks/util/result_parser.py b/benchmarks/util/result_parser.py new file mode 100644 index 0000000000000..b09f387a6b07a --- /dev/null +++ b/benchmarks/util/result_parser.py @@ -0,0 +1,300 @@ +# This import depends on the automake rule protoc_middleman, please make sure +# protoc_middleman has been built before run this file. +import json +import re +import os.path +# BEGIN OPENSOURCE +import sys +sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir)) +# END OPENSOURCE +import tmp.benchmarks_pb2 as benchmarks_pb2 + +__file_size_map = {} + +def __get_data_size(filename): + if filename[0] != '/': + filename = os.path.dirname(os.path.abspath(__file__)) + "/../" + filename + if filename in __file_size_map: + return __file_size_map[filename] + benchmark_dataset = benchmarks_pb2.BenchmarkDataset() + benchmark_dataset.ParseFromString( + open(filename, "rb").read()) + size = 0 + count = 0 + for payload in benchmark_dataset.payload: + size += len(payload) + count += 1 + __file_size_map[filename] = (size, 1.0 * size / count) + return size, 1.0 * size / count + + +def __extract_file_name(file_name): + name_list = re.split(r"[/\.]", file_name) + short_file_name = "" + for name in name_list: + if name[:14] == "google_message": + short_file_name = name + return short_file_name + + +__results = [] + + +# CPP results example: +# [ +# "benchmarks": [ +# { +# "bytes_per_second": int, +# "cpu_time_ns": double, +# "iterations": int, +# "name: string, +# "real_time_ns: double, +# ... +# }, +# ... +# ], +# ... +# ] +def __parse_cpp_result(filename): + if filename == "": + return + if filename[0] != '/': + filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename + with open(filename, "rb") as f: + results = json.loads(f.read()) + for benchmark in results["benchmarks"]: + data_filename = "".join( + re.split("(_parse_|_serialize)", benchmark["name"])[0]) + behavior = benchmark["name"][len(data_filename) + 1:] + if data_filename[:2] == "BM": + data_filename = data_filename[3:] + __results.append({ + "language": "cpp", + "dataFilename": data_filename, + "behavior": behavior, + "throughput": benchmark["bytes_per_second"] / 2.0 ** 20 + }) + + +# Synthetic benchmark results example: +# [ +# "benchmarks": [ +# { +# "cpu_time_ns": double, +# "iterations": int, +# "name: string, +# "real_time_ns: double, +# ... +# }, +# ... +# ], +# ... +# ] +def __parse_synthetic_result(filename): + if filename == "": + return + if filename[0] != "/": + filename = os.path.dirname(os.path.abspath(__file__)) + "/" + filename + with open(filename, "rb") as f: + results = json.loads(f.read()) + for benchmark in results["benchmarks"]: + __results.append({ + "language": "cpp", + "dataFilename": "", + "behavior": "synthetic", + "throughput": 10.0**9 / benchmark["cpu_time_ns"] + }) + + +# Python results example: +# [ +# [ +# { +# "filename": string, +# "benchmarks": { +# behavior: results, +# ... +# }, +# }, +# ... +# ], #pure-python +# ... +# ] +def __parse_python_result(filename): + if filename == "": + return + if filename[0] != '/': + filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename + with open(filename, "rb") as f: + results_list = json.loads(f.read()) + for results in results_list: + for result in results: + _, avg_size = __get_data_size(result["filename"]) + for behavior in result["benchmarks"]: + __results.append({ + "language": "python", + "dataFilename": __extract_file_name(result["filename"]), + "behavior": behavior, + "throughput": result["benchmarks"][behavior] + }) + + +# Java results example: +# [ +# { +# "id": string, +# "instrumentSpec": {...}, +# "measurements": [ +# { +# "weight": float, +# "value": { +# "magnitude": float, +# "unit": string +# }, +# ... +# }, +# ... +# ], +# "run": {...}, +# "scenario": { +# "benchmarkSpec": { +# "methodName": string, +# "parameters": { +# defined parameters in the benchmark: parameters value +# }, +# ... +# }, +# ... +# } +# +# }, +# ... +# ] +def __parse_java_result(filename): + if filename == "": + return + if filename[0] != '/': + filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename + with open(filename, "rb") as f: + results = json.loads(f.read()) + for result in results: + total_weight = 0 + total_value = 0 + for measurement in result["measurements"]: + total_weight += measurement["weight"] + total_value += measurement["value"]["magnitude"] + avg_time = total_value * 1.0 / total_weight + total_size, _ = __get_data_size( + result["scenario"]["benchmarkSpec"]["parameters"]["dataFile"]) + __results.append({ + "language": "java", + "throughput": total_size / avg_time * 1e9 / 2 ** 20, + "behavior": result["scenario"]["benchmarkSpec"]["methodName"], + "dataFilename": __extract_file_name( + result["scenario"]["benchmarkSpec"]["parameters"]["dataFile"]) + }) + + +# Go benchmark results: +# +# goos: linux +# goarch: amd64 +# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Unmarshal-12 3000 705784 ns/op +# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Marshal-12 2000 634648 ns/op +# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Size-12 5000 244174 ns/op +# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Clone-12 300 4120954 ns/op +# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Merge-12 300 4108632 ns/op +# PASS +# ok _/usr/local/google/home/yilunchong/mygit/protobuf/benchmarks 124.173s +def __parse_go_result(filename): + if filename == "": + return + if filename[0] != '/': + filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename + with open(filename, "rb") as f: + for line in f: + result_list = re.split(r"[\ \t]+", line) + if result_list[0][:9] != "Benchmark": + continue + first_slash_index = result_list[0].find('/') + last_slash_index = result_list[0].rfind('/') + full_filename = result_list[0][first_slash_index+1:last_slash_index] + total_bytes, _ = __get_data_size(full_filename) + behavior_with_suffix = result_list[0][last_slash_index+1:] + last_dash = behavior_with_suffix.rfind("-") + if last_dash == -1: + behavior = behavior_with_suffix + else: + behavior = behavior_with_suffix[:last_dash] + __results.append({ + "dataFilename": __extract_file_name(full_filename), + "throughput": total_bytes / float(result_list[2]) * 1e9 / 2 ** 20, + "behavior": behavior, + "language": "go" + }) + + +# Self built json results example: +# +# [ +# { +# "filename": string, +# "benchmarks": { +# behavior: results, +# ... +# }, +# }, +# ... +# ] +def __parse_custom_result(filename, language): + if filename == "": + return + if filename[0] != '/': + filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename + with open(filename, "rb") as f: + results = json.loads(f.read()) + for result in results: + _, avg_size = __get_data_size(result["filename"]) + for behavior in result["benchmarks"]: + __results.append({ + "language": language, + "dataFilename": __extract_file_name(result["filename"]), + "behavior": behavior, + "throughput": result["benchmarks"][behavior] + }) + + +def __parse_js_result(filename, language): + return __parse_custom_result(filename, language) + +def __parse_php_result(filename, language): + return __parse_custom_result(filename, language) + + +def get_result_from_file(cpp_file="", + java_file="", + python_file="", + go_file="", + synthetic_file="", + node_file="", + php_c_file="", + php_file=""): + results = {} + if cpp_file != "": + __parse_cpp_result(cpp_file) + if java_file != "": + __parse_java_result(java_file) + if python_file != "": + __parse_python_result(python_file) + if go_file != "": + __parse_go_result(go_file) + if synthetic_file != "": + __parse_synthetic_result(synthetic_file) + if node_file != "": + __parse_js_result(node_file, "node") + if php_file != "": + __parse_php_result(php_file, "php") + if php_c_file != "": + __parse_php_result(php_c_file, "php") + + return __results diff --git a/benchmarks/util/result_uploader.py b/benchmarks/util/result_uploader.py new file mode 100644 index 0000000000000..2a35d9694d16d --- /dev/null +++ b/benchmarks/util/result_uploader.py @@ -0,0 +1,107 @@ +from __future__ import print_function +from __future__ import absolute_import +import argparse +import os +import re +import copy +import uuid +import calendar +import time +import datetime + +from util import big_query_utils +from util import result_parser + +_PROJECT_ID = 'grpc-testing' +_DATASET = 'protobuf_benchmark_result' +_TABLE = 'opensource_result_v2' +_NOW = "%d%02d%02d" % (datetime.datetime.now().year, + datetime.datetime.now().month, + datetime.datetime.now().day) + +_INITIAL_TIME = calendar.timegm(time.gmtime()) + +def get_metadata(): + build_number = os.getenv('BUILD_NUMBER') + build_url = os.getenv('BUILD_URL') + job_name = os.getenv('JOB_NAME') + git_commit = os.getenv('GIT_COMMIT') + # actual commit is the actual head of PR that is getting tested + git_actual_commit = os.getenv('ghprbActualCommit') + + utc_timestamp = str(calendar.timegm(time.gmtime())) + metadata = {'created': utc_timestamp} + + if build_number: + metadata['buildNumber'] = build_number + if build_url: + metadata['buildUrl'] = build_url + if job_name: + metadata['jobName'] = job_name + if git_commit: + metadata['gitCommit'] = git_commit + if git_actual_commit: + metadata['gitActualCommit'] = git_actual_commit + + return metadata + + +def upload_result(result_list, metadata): + for result in result_list: + new_result = {} + new_result["metric"] = "throughput" + new_result["value"] = result["throughput"] + new_result["unit"] = "MB/s" + new_result["test"] = "protobuf_benchmark" + new_result["product_name"] = "protobuf" + labels_string = "" + for key in result: + labels_string += ",|%s:%s|" % (key, result[key]) + new_result["labels"] = labels_string[1:] + new_result["timestamp"] = _INITIAL_TIME + print(labels_string) + + bq = big_query_utils.create_big_query() + row = big_query_utils.make_row(str(uuid.uuid4()), new_result) + if not big_query_utils.insert_rows(bq, _PROJECT_ID, _DATASET, + _TABLE + "$" + _NOW, + [row]): + print('Error when uploading result', new_result) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("-cpp", "--cpp_input_file", + help="The CPP benchmark result file's name", + default="") + parser.add_argument("-java", "--java_input_file", + help="The Java benchmark result file's name", + default="") + parser.add_argument("-python", "--python_input_file", + help="The Python benchmark result file's name", + default="") + parser.add_argument("-go", "--go_input_file", + help="The golang benchmark result file's name", + default="") + parser.add_argument("-node", "--node_input_file", + help="The node.js benchmark result file's name", + default="") + parser.add_argument("-php", "--php_input_file", + help="The pure php benchmark result file's name", + default="") + parser.add_argument("-php_c", "--php_c_input_file", + help="The php with c ext benchmark result file's name", + default="") + args = parser.parse_args() + + metadata = get_metadata() + print("uploading results...") + upload_result(result_parser.get_result_from_file( + cpp_file=args.cpp_input_file, + java_file=args.java_input_file, + python_file=args.python_input_file, + go_file=args.go_input_file, + node_file=args.node_input_file, + php_file=args.php_input_file, + php_c_file=args.php_c_input_file, + ), metadata) diff --git a/benchmarks/util/schema_proto2_to_proto3_util.h b/benchmarks/util/schema_proto2_to_proto3_util.h new file mode 100644 index 0000000000000..0079f6f1452e8 --- /dev/null +++ b/benchmarks/util/schema_proto2_to_proto3_util.h @@ -0,0 +1,194 @@ +#ifndef PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_ +#define PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_ + +#include "google/protobuf/message.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" + +#include +#include + +using google::protobuf::Descriptor; +using google::protobuf::DescriptorProto; +using google::protobuf::FileDescriptorProto; +using google::protobuf::FieldDescriptorProto; +using google::protobuf::Message; +using google::protobuf::EnumValueDescriptorProto; + +namespace google { +namespace protobuf { +namespace util { + +class SchemaGroupStripper { + + public: + static void StripFile(const FileDescriptor* old_file, + FileDescriptorProto *file) { + for (int i = file->mutable_message_type()->size() - 1; i >= 0; i--) { + if (IsMessageSet(old_file->message_type(i))) { + file->mutable_message_type()->DeleteSubrange(i, 1); + continue; + } + StripMessage(old_file->message_type(i), file->mutable_message_type(i)); + } + for (int i = file->mutable_extension()->size() - 1; i >= 0; i--) { + auto field = old_file->extension(i); + if (field->type() == FieldDescriptor::TYPE_GROUP || + IsMessageSet(field->message_type()) || + IsMessageSet(field->containing_type())) { + file->mutable_extension()->DeleteSubrange(i, 1); + } + } + } + + private: + static bool IsMessageSet(const Descriptor *descriptor) { + if (descriptor != nullptr + && descriptor->options().message_set_wire_format()) { + return true; + } + return false; + } + + static void StripMessage(const Descriptor *old_message, + DescriptorProto *new_message) { + for (int i = new_message->mutable_field()->size() - 1; i >= 0; i--) { + if (old_message->field(i)->type() == FieldDescriptor::TYPE_GROUP || + IsMessageSet(old_message->field(i)->message_type())) { + new_message->mutable_field()->DeleteSubrange(i, 1); + } + } + for (int i = new_message->mutable_extension()->size() - 1; i >= 0; i--) { + auto field_type_name = new_message->mutable_extension(i)->type_name(); + if (old_message->extension(i)->type() == FieldDescriptor::TYPE_GROUP || + IsMessageSet(old_message->extension(i)->containing_type()) || + IsMessageSet(old_message->extension(i)->message_type())) { + new_message->mutable_extension()->DeleteSubrange(i, 1); + } + } + for (int i = 0; i < new_message->mutable_nested_type()->size(); i++) { + StripMessage(old_message->nested_type(i), + new_message->mutable_nested_type(i)); + } + } + +}; + +class EnumScrubber { + + public: + EnumScrubber() + : total_added_(0) { + } + + void ScrubFile(FileDescriptorProto *file) { + for (int i = 0; i < file->enum_type_size(); i++) { + ScrubEnum(file->mutable_enum_type(i)); + } + for (int i = 0; i < file->mutable_message_type()->size(); i++) { + ScrubMessage(file->mutable_message_type(i)); + } + } + + private: + void ScrubEnum(EnumDescriptorProto *enum_type) { + if (enum_type->value(0).number() != 0) { + bool has_zero = false; + for (int j = 0; j < enum_type->value().size(); j++) { + if (enum_type->value(j).number() == 0) { + EnumValueDescriptorProto temp_enum_value; + temp_enum_value.CopyFrom(enum_type->value(j)); + enum_type->mutable_value(j)->CopyFrom(enum_type->value(0)); + enum_type->mutable_value(0)->CopyFrom(temp_enum_value); + has_zero = true; + break; + } + } + if (!has_zero) { + enum_type->mutable_value()->Add(); + for (int i = enum_type->mutable_value()->size() - 1; i > 0; i--) { + enum_type->mutable_value(i)->CopyFrom( + *enum_type->mutable_value(i - 1)); + } + enum_type->mutable_value(0)->set_number(0); + enum_type->mutable_value(0)->set_name("ADDED_ZERO_VALUE_" + + std::to_string(total_added_++)); + } + } + + } + + void ScrubMessage(DescriptorProto *message_type) { + for (int i = 0; i < message_type->mutable_enum_type()->size(); i++) { + ScrubEnum(message_type->mutable_enum_type(i)); + } + for (int i = 0; i < message_type->mutable_nested_type()->size(); i++) { + ScrubMessage(message_type->mutable_nested_type(i)); + } + } + + int total_added_; +}; + +class ExtensionStripper { + public: + static void StripFile(FileDescriptorProto *file) { + for (int i = 0; i < file->mutable_message_type()->size(); i++) { + StripMessage(file->mutable_message_type(i)); + } + file->mutable_extension()->Clear(); + } + private: + static void StripMessage(DescriptorProto *message_type) { + message_type->mutable_extension()->Clear(); + message_type->clear_extension_range(); + for (int i = 0; i < message_type->mutable_nested_type()->size(); i++) { + StripMessage(message_type->mutable_nested_type(i)); + } + } +}; + + +class FieldScrubber { + public: + static void ScrubFile(FileDescriptorProto *file) { + for (int i = 0; i < file->mutable_message_type()->size(); i++) { + ScrubMessage(file->mutable_message_type(i)); + } + for (int i = 0; i < file->mutable_extension()->size(); i++) { + file->mutable_extension(i)->clear_default_value(); + if (ShouldClearLabel(file->mutable_extension(i))) { + file->mutable_extension(i)->clear_label(); + } + } + } + private: + static bool ShouldClearLabel(const FieldDescriptorProto *field) { + return field->label() == FieldDescriptorProto::LABEL_REQUIRED; + } + + static void ScrubMessage(DescriptorProto *message_type) { + message_type->mutable_extension()->Clear(); + for (int i = 0; i < message_type->mutable_extension()->size(); i++) { + message_type->mutable_extension(i)->clear_default_value(); + if (ShouldClearLabel(message_type->mutable_extension(i))) { + message_type->mutable_extension(i)->clear_label(); + } + } + for (int i = 0; i < message_type->mutable_field()->size(); i++) { + message_type->mutable_field(i)->clear_default_value(); + if (ShouldClearLabel(message_type->mutable_field(i))) { + message_type->mutable_field(i)->clear_label(); + } + } + for (int i = 0; i < message_type->mutable_nested_type()->size(); i++) { + ScrubMessage(message_type->mutable_nested_type(i)); + } + } +}; + +} // namespace util +} // namespace protobuf +} // namespace google + +#endif // PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_ diff --git a/build_files_updated_unittest.sh b/build_files_updated_unittest.sh new file mode 100755 index 0000000000000..c86307193ce8d --- /dev/null +++ b/build_files_updated_unittest.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +# This script verifies that BUILD files and cmake files are in sync with src/Makefile.am + +set -eo pipefail + +if [ "$(uname)" != "Linux" ]; then + echo "build_files_updated_unittest only supported on Linux. Skipping..." + exit 0 +fi + +# Keep in sync with files needed by update_file_lists.sh +generated_files=( + "BUILD" + "cmake/extract_includes.bat.in" + "cmake/libprotobuf-lite.cmake" + "cmake/libprotobuf.cmake" + "cmake/libprotoc.cmake" + "cmake/tests.cmake" + "src/Makefile.am" +) + +# If we're running in Bazel, use the Bazel-provided temp-dir. +if [ -n "${TEST_TMPDIR}" ]; then + # Env-var TEST_TMPDIR is set, assume that this is Bazel. + # Bazel may have opinions whether we are allowed to delete TEST_TMPDIR. + test_root="${TEST_TMPDIR}/build_files_updated_unittest" + mkdir "${test_root}" +else + # Seems like we're not executed by Bazel. + test_root=$(mktemp -d) +fi + +# From now on, fail if there are any unbound variables. +set -u + +# Remove artifacts after test is finished. +function cleanup { + rm -rf "${test_root}" +} +trap cleanup EXIT + +# Create golden dir and add snapshot of current state. +golden_dir="${test_root}/golden" +mkdir -p "${golden_dir}/cmake" "${golden_dir}/src" +for file in ${generated_files[@]}; do + cp "${file}" "${golden_dir}/${file}" +done + +# Create test dir, copy current state into it, and execute update script. +test_dir="${test_root}/test" +cp -R "${golden_dir}" "${test_dir}" + +cp "update_file_lists.sh" "${test_dir}/update_file_lists.sh" +chmod +x "${test_dir}/update_file_lists.sh" +cd "${test_root}/test" +bash "${test_dir}/update_file_lists.sh" + +# Test whether there are any differences +for file in ${generated_files[@]}; do + diff "${golden_dir}/${file}" "${test_dir}/${file}" +done diff --git a/cc_proto_blacklist_test.bzl b/cc_proto_blacklist_test.bzl new file mode 100644 index 0000000000000..df54293cbd0f4 --- /dev/null +++ b/cc_proto_blacklist_test.bzl @@ -0,0 +1,38 @@ +"""Contains a unittest to verify that `cc_proto_library` does not generate code for blacklisted `.proto` sources (i.e. WKPs).""" + +load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest") + +def _cc_proto_blacklist_test_impl(ctx): + """Verifies that there are no C++ compile actions for Well-Known-Protos. + + Args: + ctx: The rule context. + + Returns: A (not further specified) sequence of providers. + """ + + env = unittest.begin(ctx) + + for dep in ctx.attr.deps: + files = len(dep.files.to_list()) + asserts.equals( + env, + 0, + files, + "Expected that target '{}' does not provide files, got {}".format( + dep.label, + files, + ), + ) + + return unittest.end(env) + +cc_proto_blacklist_test = unittest.make( + impl = _cc_proto_blacklist_test_impl, + attrs = { + "deps": attr.label_list( + mandatory = True, + providers = [CcInfo], + ), + }, +) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 7618ba21a13fb..52661f522d997 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -1,5 +1,5 @@ # Minimum CMake required -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.1.3) if(protobuf_VERBOSE) message(STATUS "Protocol Buffers Configuring...") @@ -7,13 +7,44 @@ endif() # CMake policies cmake_policy(SET CMP0022 NEW) +# On MacOS use @rpath/ for target's install name prefix path +if (POLICY CMP0042) + cmake_policy(SET CMP0042 NEW) +endif () +# Clear VERSION variables when no VERSION is given to project() +if(POLICY CMP0048) + cmake_policy(SET CMP0048 NEW) +endif() # Project project(protobuf C CXX) +# Add c++11 flags +if (CYGWIN) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") +else() + set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + set(CMAKE_CXX_EXTENSIONS OFF) +endif() + +# The Intel compiler isn't able to deal with noinline member functions of +# template classes defined in headers. As such it spams the output with +# warning #2196: routine is both "inline" and "noinline" +# This silences that warning. +if (CMAKE_CXX_COMPILER_ID MATCHES Intel) + string(APPEND CMAKE_CXX_FLAGS " -diag-disable=2196") +endif() + # Options +if(WITH_PROTOC) + set(protobuf_PROTOC_EXE ${WITH_PROTOC} CACHE FILEPATH "Protocol Buffer Compiler executable" FORCE) +endif() option(protobuf_BUILD_TESTS "Build tests" ON) +option(protobuf_BUILD_CONFORMANCE "Build conformance tests" OFF) option(protobuf_BUILD_EXAMPLES "Build examples" OFF) +option(protobuf_BUILD_PROTOC_BINARIES "Build libprotoc and protoc compiler" ON) +option(protobuf_BUILD_LIBPROTOC "Build libprotoc" OFF) if (BUILD_SHARED_LIBS) set(protobuf_BUILD_SHARED_LIBS_DEFAULT ON) else (BUILD_SHARED_LIBS) @@ -23,11 +54,7 @@ option(protobuf_BUILD_SHARED_LIBS "Build Shared Libraries" ${protobuf_BUILD_SHAR include(CMakeDependentOption) cmake_dependent_option(protobuf_MSVC_STATIC_RUNTIME "Link static runtime libraries" ON "NOT protobuf_BUILD_SHARED_LIBS" OFF) -if (MSVC) - set(protobuf_WITH_ZLIB_DEFAULT OFF) -else (MSVC) - set(protobuf_WITH_ZLIB_DEFAULT ON) -endif (MSVC) +set(protobuf_WITH_ZLIB_DEFAULT ON) option(protobuf_WITH_ZLIB "Build with zlib support" ${protobuf_WITH_ZLIB_DEFAULT}) set(protobuf_DEBUG_POSTFIX "d" CACHE STRING "Default debug postfix") @@ -35,6 +62,10 @@ mark_as_advanced(protobuf_DEBUG_POSTFIX) # User options include(protobuf-options.cmake) +# Overrides for option dependencies +if (protobuf_BUILD_PROTOC_BINARIES OR protobuf_BUILD_TESTS) + set(protobuf_BUILD_LIBPROTOC ON) +endif () # Path to main configure script set(protobuf_CONFIGURE_SCRIPT "../configure.ac") @@ -53,23 +84,28 @@ string(REGEX REPLACE "${protobuf_AC_INIT_REGEX}" "\\2" string(REGEX REPLACE "${protobuf_AC_INIT_REGEX}" "\\3" protobuf_CONTACT "${protobuf_AC_INIT_LINE}") # Parse version tweaks -set(protobuf_VERSION_REGEX "^([0-9]+)\\.([0-9]+)\\.([0-9]+)-?(.*)$") +set(protobuf_VERSION_REGEX "^([0-9]+)\\.([0-9]+)\\.([0-9]+)([-]rc[-]|\\.)?([0-9]*)$") string(REGEX REPLACE "${protobuf_VERSION_REGEX}" "\\1" protobuf_VERSION_MAJOR "${protobuf_VERSION_STRING}") string(REGEX REPLACE "${protobuf_VERSION_REGEX}" "\\2" protobuf_VERSION_MINOR "${protobuf_VERSION_STRING}") string(REGEX REPLACE "${protobuf_VERSION_REGEX}" "\\3" protobuf_VERSION_PATCH "${protobuf_VERSION_STRING}") -string(REGEX REPLACE "${protobuf_VERSION_REGEX}" "\\4" +string(REGEX REPLACE "${protobuf_VERSION_REGEX}" "\\5" protobuf_VERSION_PRERELEASE "${protobuf_VERSION_STRING}") +message(STATUS "${protobuf_VERSION_PRERELEASE}") + # Package version set(protobuf_VERSION "${protobuf_VERSION_MAJOR}.${protobuf_VERSION_MINOR}.${protobuf_VERSION_PATCH}") if(protobuf_VERSION_PRERELEASE) - set(protobuf_VERSION "${protobuf_VERSION}-${protobuf_VERSION_PRERELEASE}") + set(protobuf_VERSION "${protobuf_VERSION}.${protobuf_VERSION_PRERELEASE}") +else() + set(protobuf_VERSION "${protobuf_VERSION}.0") endif() +message(STATUS "${protobuf_VERSION}") if(protobuf_VERBOSE) message(STATUS "Configuration script parsing status [") @@ -112,6 +148,25 @@ if (HAVE_ZLIB) add_definitions(-DHAVE_ZLIB) endif (HAVE_ZLIB) +# We need to link with libatomic on systems that do not have builtin atomics, or +# don't have builtin support for 8 byte atomics +set(protobuf_LINK_LIBATOMIC false) +if (NOT MSVC) + include(CheckCXXSourceCompiles) + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} -std=c++11) + check_cxx_source_compiles(" + #include + int main() { + return std::atomic{}; + } + " protobuf_HAVE_BUILTIN_ATOMICS) + if (NOT protobuf_HAVE_BUILTIN_ATOMICS) + set(protobuf_LINK_LIBATOMIC true) + endif (NOT protobuf_HAVE_BUILTIN_ATOMICS) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) +endif (NOT MSVC) + if (protobuf_BUILD_SHARED_LIBS) set(protobuf_SHARED_OR_STATIC "SHARED") else (protobuf_BUILD_SHARED_LIBS) @@ -135,14 +190,44 @@ endif (protobuf_BUILD_SHARED_LIBS) if (MSVC) # Build with multiple processes add_definitions(/MP) - add_definitions(/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305 /wd4309) + # MSVC warning suppressions + add_definitions( + /wd4018 # 'expression' : signed/unsigned mismatch + /wd4065 # switch statement contains 'default' but no 'case' labels + /wd4146 # unary minus operator applied to unsigned type, result still unsigned + /wd4244 # 'conversion' conversion from 'type1' to 'type2', possible loss of data + /wd4251 # 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2' + /wd4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data + /wd4305 # 'identifier' : truncation from 'type1' to 'type2' + /wd4307 # 'operator' : integral constant overflow + /wd4309 # 'conversion' : truncation of constant value + /wd4334 # 'operator' : result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?) + /wd4355 # 'this' : used in base member initializer list + /wd4506 # no definition for inline function 'function' + /wd4800 # 'type' : forcing value to bool 'true' or 'false' (performance warning) + /wd4996 # The compiler encountered a deprecated declaration. + ) # Allow big object add_definitions(/bigobj) string(REPLACE "/" "\\" PROTOBUF_SOURCE_WIN32_PATH ${protobuf_SOURCE_DIR}) string(REPLACE "/" "\\" PROTOBUF_BINARY_WIN32_PATH ${protobuf_BINARY_DIR}) + string(REPLACE "." "," protobuf_RC_FILEVERSION "${protobuf_VERSION}") configure_file(extract_includes.bat.in extract_includes.bat) + + # Suppress linker warnings about files with no symbols defined. + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221") + + # Configure Resource Compiler + enable_language(RC) + # use English language (0x409) in resource compiler + set(rc_flags "/l0x409") + # fix rc.exe invocations because of usage of add_definitions() + set(CMAKE_RC_COMPILE_OBJECT " ${rc_flags} /fo ") + + configure_file(version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) endif (MSVC) + get_filename_component(protobuf_source_dir ${protobuf_SOURCE_DIR} PATH) include_directories( @@ -165,13 +250,37 @@ endif (protobuf_UNICODE) include(libprotobuf-lite.cmake) include(libprotobuf.cmake) -include(libprotoc.cmake) -include(protoc.cmake) +if (protobuf_BUILD_LIBPROTOC) + include(libprotoc.cmake) +endif (protobuf_BUILD_LIBPROTOC) +if (protobuf_BUILD_PROTOC_BINARIES) + include(protoc.cmake) + if (NOT DEFINED protobuf_PROTOC_EXE) + set(protobuf_PROTOC_EXE protoc) + endif (NOT DEFINED protobuf_PROTOC_EXE) +endif (protobuf_BUILD_PROTOC_BINARIES) + +# Ensure we have a protoc executable if we need one +if (protobuf_BUILD_TESTS OR protobuf_BUILD_CONFORMANCE OR protobuf_BUILD_EXAMPLES) + if (NOT DEFINED protobuf_PROTOC_EXE) + find_program(protobuf_PROTOC_EXE protoc) + if (NOT protobuf_PROTOC_EXE) + message(FATAL "Build requires 'protoc' but binary not found and not building protoc.") + endif () + endif () + if(protobuf_VERBOSE) + message(STATUS "Using protoc : ${protobuf_PROTOC_EXE}") + endif(protobuf_VERBOSE) +endif () if (protobuf_BUILD_TESTS) include(tests.cmake) endif (protobuf_BUILD_TESTS) +if (protobuf_BUILD_CONFORMANCE) + include(conformance.cmake) +endif (protobuf_BUILD_CONFORMANCE) + include(install.cmake) if (protobuf_BUILD_EXAMPLES) @@ -179,5 +288,5 @@ if (protobuf_BUILD_EXAMPLES) endif (protobuf_BUILD_EXAMPLES) if(protobuf_VERBOSE) - message(STATUS "Protocol Buffers Configuring done") -endif() + message(STATUS "Protocol Buffers Configuring done") +endif(protobuf_VERBOSE) diff --git a/cmake/README.md b/cmake/README.md index 1e7410d828547..89d00c1b6f4f7 100644 --- a/cmake/README.md +++ b/cmake/README.md @@ -13,13 +13,13 @@ Environment Setup Open the appropriate *Command Prompt* from the *Start* menu. -For example *VS2013 x64 Native Tools Command Prompt*: +For example *x86 Native Tools Command Prompt for VS 2019*: - C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64> + C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional> Change to your working directory: - C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64>cd C:\Path\to + C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional>cd C:\Path\to C:\Path\to> Where *C:\Path\to* is path to your real working directory. @@ -41,11 +41,18 @@ Good. Now you are ready to continue. Getting Sources =============== -You can get the latest stable source packages from the -[releases](https://github.com/google/protobuf/releases) page. -Or you can type: +You can get the latest stable source packages from the release page: - C:\Path\to> git clone -b [release_tag] https://github.com/google/protobuf.git + https://github.com/protocolbuffers/protobuf/releases/latest + +For example: if you only need C++, download `protobuf-cpp-[VERSION].tar.gz`; if +you need C++ and Java, download `protobuf-java-[VERSION].tar.gz` (every package +contains C++ source already); if you need C++ and multiple other languages, +download `protobuf-all-[VERSION].tar.gz`. + +Or you can use git to clone from protobuf git repository. + + C:\Path\to> git clone -b [release_tag] https://github.com/protocolbuffers/protobuf.git Where *[release_tag]* is a git tag like *v3.0.0-beta-1* or a branch name like *master* if you want to get the latest code. @@ -55,26 +62,16 @@ Go to the project folder: C:\Path\to>cd protobuf C:\Path\to\protobuf> -Protobuf unit-tests require gmock to build. If you download protobuf source code -from the *releases* page, the *gmock* directory should already be there. If you checkout -the code via `git clone`, this *gmock* directory won't exist and you will have to -download it manually or skip building protobuf unit-tests. - -You can download gmock as follows: +Remember to update any submodules if you are using git clone (you can skip this +step if you are using a release .tar.gz or .zip package): - C:\Path\to\protobuf>git clone -b release-1.7.0 https://github.com/google/googlemock.git gmock - -Then go to *gmock* folder and download gtest: - - C:\Path\to\protobuf>cd gmock - C:\Path\to\protobuf\gmock>git clone -b release-1.7.0 https://github.com/google/googletest.git gtest - -If you absolutely don't want to build and run protobuf unit-tests, skip -this steps and use protobuf at your own risk. +```console +C:\Path\to> git submodule update --init --recursive +``` Now go to *cmake* folder in protobuf sources: - C:\Path\to\protobuf\gmock>cd ..\cmake + C:\Path\to\protobuf>cd cmake C:\Path\to\protobuf\cmake> Good. Now you are ready to *CMake* configuration. @@ -124,7 +121,7 @@ It will generate *nmake* *Makefile* in current directory. To create *Visual Studio* solution file: C:\Path\to\protobuf\cmake\build>mkdir solution & cd solution - C:\Path\to\protobuf\cmake\build\solution>cmake -G "Visual Studio 12 2013 Win64" ^ + C:\Path\to\protobuf\cmake\build\solution>cmake -G "Visual Studio 16 2019" ^ -DCMAKE_INSTALL_PREFIX=../../../../install ^ ../.. @@ -133,6 +130,13 @@ It will generate *Visual Studio* solution file *protobuf.sln* in current directo If the *gmock* directory does not exist, and you do not want to build protobuf unit tests, you need to add *cmake* command argument `-Dprotobuf_BUILD_TESTS=OFF` to disable testing. +To make a *Visual Studio* file for Visual Studio 16 2019, create the *Visual Studio* +solution file above and edit the CMakeCache file. + + C:Path\to\protobuf\cmake\build\solution\CMakeCache + +Then create the *Visual Studio* solution file again + Compiling ========= @@ -173,9 +177,9 @@ You should see output similar to: Running main() from gmock_main.cc [==========] Running 1546 tests from 165 test cases. - + ... - + [==========] 1546 tests from 165 test cases ran. (2529 ms total) [ PASSED ] 1546 tests. @@ -194,7 +198,7 @@ To run specific tests: [ RUN ] AnyTest.TestIs [ OK ] AnyTest.TestIs (0 ms) [----------] 3 tests from AnyTest (1 ms total) - + [----------] Global test environment tear-down [==========] 3 tests from 1 test case ran. (2 ms total) [ PASSED ] 3 tests. @@ -302,6 +306,11 @@ further disable the option `-Dprotobuf_MSVC_STATIC_RUNTIME=OFF`. If it reports NOTFOUND for zlib_include or zlib_lib, you might haven't put the headers or the .lib file in the right directory. +If you already have ZLIB library and headers at some other location on your system then alternatively you can define following configuration flags to locate them: + + -DZLIB_INCLUDE_DIR= + -DZLIB_LIB= + Build and testing protobuf as usual. Notes on Compiler Warnings diff --git a/cmake/conformance.cmake b/cmake/conformance.cmake new file mode 100644 index 0000000000000..056b5d0c604b8 --- /dev/null +++ b/cmake/conformance.cmake @@ -0,0 +1,49 @@ + +add_custom_command( + OUTPUT ${protobuf_source_dir}/conformance/conformance.pb.cc + 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=${protobuf_source_dir}/conformance +) + +add_custom_command( + OUTPUT ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.pb.cc + ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.pb.cc + DEPENDS ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.proto + ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.proto + COMMAND ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.proto + ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.proto + --proto_path=${protobuf_source_dir}/src + --cpp_out=${protobuf_source_dir}/src +) + +add_executable(conformance_test_runner + ${protobuf_source_dir}/conformance/conformance.pb.cc + ${protobuf_source_dir}/conformance/conformance_test.cc + ${protobuf_source_dir}/conformance/binary_json_conformance_suite.cc + ${protobuf_source_dir}/conformance/binary_json_conformance_suite.h + ${protobuf_source_dir}/conformance/conformance_test_runner.cc + ${protobuf_source_dir}/conformance/third_party/jsoncpp/json.h + ${protobuf_source_dir}/conformance/third_party/jsoncpp/jsoncpp.cpp + ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.pb.cc + ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.pb.cc +) + +add_executable(conformance_cpp + ${protobuf_source_dir}/conformance/conformance.pb.cc + ${protobuf_source_dir}/conformance/conformance_cpp.cc + ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.pb.cc + ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.pb.cc +) + +target_include_directories( + conformance_test_runner + PUBLIC ${protobuf_source_dir}/conformance) + +target_include_directories( + conformance_cpp + PUBLIC ${protobuf_source_dir}/conformance) + +target_link_libraries(conformance_test_runner libprotobuf) +target_link_libraries(conformance_cpp libprotobuf) diff --git a/cmake/extract_includes.bat.in b/cmake/extract_includes.bat.in index deb6de3bfbfb6..5c5799efa1e8d 100644 --- a/cmake/extract_includes.bat.in +++ b/cmake/extract_includes.bat.in @@ -5,7 +5,6 @@ mkdir include\google\protobuf\compiler mkdir include\google\protobuf\compiler\cpp mkdir include\google\protobuf\compiler\csharp mkdir include\google\protobuf\compiler\java -mkdir include\google\protobuf\compiler\javanano mkdir include\google\protobuf\compiler\js mkdir include\google\protobuf\compiler\objectivec mkdir include\google\protobuf\compiler\php @@ -28,7 +27,6 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\cshar copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\importer.h" include\google\protobuf\compiler\importer.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_generator.h" include\google\protobuf\compiler\java\java_generator.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_names.h" include\google\protobuf\compiler\java\java_names.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\javanano\javanano_generator.h" include\google\protobuf\compiler\javanano\javanano_generator.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\js\js_generator.h" include\google\protobuf\compiler\js\js_generator.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\js\well_known_types_embed.h" include\google\protobuf\compiler\js\well_known_types_embed.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_generator.h" include\google\protobuf\compiler\objectivec\objectivec_generator.h @@ -46,6 +44,7 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\duration.pb.h" includ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\dynamic_message.h" include\google\protobuf\dynamic_message.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\empty.pb.h" include\google\protobuf\empty.pb.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\extension_set.h" include\google\protobuf\extension_set.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\extension_set_inl.h" include\google\protobuf\extension_set_inl.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_mask.pb.h" include\google\protobuf\field_mask.pb.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_reflection.h" include\google\protobuf\generated_enum_reflection.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_util.h" include\google\protobuf\generated_enum_util.h @@ -53,8 +52,10 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_ref copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_table_driven.h" include\google\protobuf\generated_message_table_driven.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_util.h" include\google\protobuf\generated_message_util.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\has_bits.h" include\google\protobuf\has_bits.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\implicit_weak_message.h" include\google\protobuf\implicit_weak_message.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\coded_stream.h" include\google\protobuf\io\coded_stream.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\gzip_stream.h" include\google\protobuf\io\gzip_stream.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\io_win32.h" include\google\protobuf\io\io_win32.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\printer.h" include\google\protobuf\io\printer.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\strtod.h" include\google\protobuf\io\strtod.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\tokenizer.h" include\google\protobuf\io\tokenizer.h @@ -72,47 +73,33 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message.h" include\go copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message_lite.h" include\google\protobuf\message_lite.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata.h" include\google\protobuf\metadata.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata_lite.h" include\google\protobuf\metadata_lite.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\parse_context.h" include\google\protobuf\parse_context.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\port.h" include\google\protobuf\port.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\port_def.inc" include\google\protobuf\port_def.inc +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\port_undef.inc" include\google\protobuf\port_undef.inc copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection.h" include\google\protobuf\reflection.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection_ops.h" include\google\protobuf\reflection_ops.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field.h" include\google\protobuf\repeated_field.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\service.h" include\google\protobuf\service.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\source_context.pb.h" include\google\protobuf\source_context.pb.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\struct.pb.h" include\google\protobuf\struct.pb.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomic_sequence_num.h" include\google\protobuf\stubs\atomic_sequence_num.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops.h" include\google\protobuf\stubs\atomicops.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm64_gcc.h" include\google\protobuf\stubs\atomicops_internals_arm64_gcc.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm_gcc.h" include\google\protobuf\stubs\atomicops_internals_arm_gcc.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm_qnx.h" include\google\protobuf\stubs\atomicops_internals_arm_qnx.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_atomicword_compat.h" include\google\protobuf\stubs\atomicops_internals_atomicword_compat.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_generic_c11_atomic.h" include\google\protobuf\stubs\atomicops_internals_generic_c11_atomic.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_generic_gcc.h" include\google\protobuf\stubs\atomicops_internals_generic_gcc.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_mips_gcc.h" include\google\protobuf\stubs\atomicops_internals_mips_gcc.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_power.h" include\google\protobuf\stubs\atomicops_internals_power.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_ppc_gcc.h" include\google\protobuf\stubs\atomicops_internals_ppc_gcc.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_solaris.h" include\google\protobuf\stubs\atomicops_internals_solaris.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_tsan.h" include\google\protobuf\stubs\atomicops_internals_tsan.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_x86_gcc.h" include\google\protobuf\stubs\atomicops_internals_x86_gcc.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.h" include\google\protobuf\stubs\atomicops_internals_x86_msvc.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\bytestream.h" include\google\protobuf\stubs\bytestream.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\callback.h" include\google\protobuf\stubs\callback.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\casts.h" include\google\protobuf\stubs\casts.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\common.h" include\google\protobuf\stubs\common.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\fastmem.h" include\google\protobuf\stubs\fastmem.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\hash.h" include\google\protobuf\stubs\hash.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\logging.h" include\google\protobuf\stubs\logging.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\macros.h" include\google\protobuf\stubs\macros.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\map_util.h" include\google\protobuf\stubs\map_util.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\mutex.h" include\google\protobuf\stubs\mutex.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\once.h" include\google\protobuf\stubs\once.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\platform_macros.h" include\google\protobuf\stubs\platform_macros.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\port.h" include\google\protobuf\stubs\port.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\scoped_ptr.h" include\google\protobuf\stubs\scoped_ptr.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\shared_ptr.h" include\google\protobuf\stubs\shared_ptr.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\singleton.h" include\google\protobuf\stubs\singleton.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\status.h" include\google\protobuf\stubs\status.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stl_util.h" include\google\protobuf\stubs\stl_util.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stringpiece.h" include\google\protobuf\stubs\stringpiece.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\strutil.h" include\google\protobuf\stubs\strutil.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\template_util.h" include\google\protobuf\stubs\template_util.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\type_traits.h" include\google\protobuf\stubs\type_traits.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\text_format.h" include\google\protobuf\text_format.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\timestamp.pb.h" include\google\protobuf\timestamp.pb.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\type.pb.h" include\google\protobuf\type.pb.h @@ -127,5 +114,16 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver.h" copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver_util.h" include\google\protobuf\util\type_resolver_util.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format.h" include\google\protobuf\wire_format.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format_lite.h" include\google\protobuf\wire_format_lite.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format_lite_inl.h" include\google\protobuf\wire_format_lite_inl.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wrappers.pb.h" include\google\protobuf\wrappers.pb.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.proto" include\google\protobuf\any.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\api.proto" include\google\protobuf\api.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.proto" include\google\protobuf\compiler\plugin.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.proto" include\google\protobuf\descriptor.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\duration.proto" include\google\protobuf\duration.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\empty.proto" include\google\protobuf\empty.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_mask.proto" include\google\protobuf\field_mask.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\source_context.proto" include\google\protobuf\source_context.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\struct.proto" include\google\protobuf\struct.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\timestamp.proto" include\google\protobuf\timestamp.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\type.proto" include\google\protobuf\type.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wrappers.proto" include\google\protobuf\wrappers.proto diff --git a/cmake/install.cmake b/cmake/install.cmake index 441bf5532a385..9dd6e7710f0ce 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -5,22 +5,40 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/protobuf.pc.cmake configure_file(${CMAKE_CURRENT_SOURCE_DIR}/protobuf-lite.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/protobuf-lite.pc @ONLY) -foreach(_library - libprotobuf-lite - libprotobuf - libprotoc) +set(_protobuf_libraries libprotobuf-lite libprotobuf) +if (protobuf_BUILD_LIBPROTOC) + list(APPEND _protobuf_libraries libprotoc) +endif (protobuf_BUILD_LIBPROTOC) + +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") + elseif (APPLE) + set_property(TARGET ${_library} + PROPERTY INSTALL_RPATH "@loader_path") + endif() install(TARGETS ${_library} EXPORT protobuf-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${_library} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library}) endforeach() -install(TARGETS protoc EXPORT protobuf-targets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc) +if (protobuf_BUILD_PROTOC_BINARIES) + install(TARGETS protoc EXPORT protobuf-targets + RUNTIME 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() +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") @@ -84,12 +102,16 @@ endforeach() # Install configuration set(_cmakedir_desc "Directory relative to CMAKE_INSTALL to install the cmake configuration files") +set(_exampledir_desc "Directory relative to CMAKE_INSTALL_DATA to install examples") if(NOT MSVC) set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/protobuf" CACHE STRING "${_cmakedir_desc}") + set(CMAKE_INSTALL_EXAMPLEDIR "${CMAKE_INSTALL_DATADIR}/protobuf/examples" CACHE STRING "${_exampledir_desc}") else() set(CMAKE_INSTALL_CMAKEDIR "cmake" CACHE STRING "${_cmakedir_desc}") + set(CMAKE_INSTALL_EXAMPLEDIR "examples" CACHE STRING "${_exampledir_desc}") endif() mark_as_advanced(CMAKE_INSTALL_CMAKEDIR) +mark_as_advanced(CMAKE_INSTALL_EXAMPLEDIR) configure_file(protobuf-config.cmake.in ${CMAKE_INSTALL_CMAKEDIR}/protobuf-config.cmake @ONLY) @@ -101,10 +123,18 @@ configure_file(protobuf-options.cmake ${CMAKE_INSTALL_CMAKEDIR}/protobuf-options.cmake @ONLY) # Allows the build directory to be used as a find directory. -export(TARGETS libprotobuf-lite libprotobuf libprotoc protoc - NAMESPACE protobuf:: - FILE ${CMAKE_INSTALL_CMAKEDIR}/protobuf-targets.cmake -) + +if (protobuf_BUILD_PROTOC_BINARIES) + export(TARGETS libprotobuf-lite libprotobuf libprotoc protoc + NAMESPACE protobuf:: + FILE ${CMAKE_INSTALL_CMAKEDIR}/protobuf-targets.cmake + ) +else (protobuf_BUILD_PROTOC_BINARIES) + export(TARGETS libprotobuf-lite libprotobuf + NAMESPACE protobuf:: + FILE ${CMAKE_INSTALL_CMAKEDIR}/protobuf-targets.cmake + ) +endif (protobuf_BUILD_PROTOC_BINARIES) install(EXPORT protobuf-targets DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" @@ -119,6 +149,7 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}/ option(protobuf_INSTALL_EXAMPLES "Install the examples folder" OFF) if(protobuf_INSTALL_EXAMPLES) - install(DIRECTORY ../examples/ DESTINATION examples + install(DIRECTORY ../examples/ + DESTINATION "${CMAKE_INSTALL_EXAMPLEDIR}" COMPONENT protobuf-examples) endif() diff --git a/cmake/libprotobuf-lite.cmake b/cmake/libprotobuf-lite.cmake index 9e1fab0a79010..6d325d5dcad42 100644 --- a/cmake/libprotobuf-lite.cmake +++ b/cmake/libprotobuf-lite.cmake @@ -1,21 +1,25 @@ set(libprotobuf_lite_files + ${protobuf_source_dir}/src/google/protobuf/any_lite.cc ${protobuf_source_dir}/src/google/protobuf/arena.cc ${protobuf_source_dir}/src/google/protobuf/arenastring.cc ${protobuf_source_dir}/src/google/protobuf/extension_set.cc + ${protobuf_source_dir}/src/google/protobuf/generated_enum_util.cc ${protobuf_source_dir}/src/google/protobuf/generated_message_table_driven_lite.cc ${protobuf_source_dir}/src/google/protobuf/generated_message_util.cc + ${protobuf_source_dir}/src/google/protobuf/implicit_weak_message.cc ${protobuf_source_dir}/src/google/protobuf/io/coded_stream.cc + ${protobuf_source_dir}/src/google/protobuf/io/io_win32.cc + ${protobuf_source_dir}/src/google/protobuf/io/strtod.cc ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream.cc + ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl.cc ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc + ${protobuf_source_dir}/src/google/protobuf/map.cc ${protobuf_source_dir}/src/google/protobuf/message_lite.cc + ${protobuf_source_dir}/src/google/protobuf/parse_context.cc ${protobuf_source_dir}/src/google/protobuf/repeated_field.cc - ${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc - ${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc ${protobuf_source_dir}/src/google/protobuf/stubs/bytestream.cc ${protobuf_source_dir}/src/google/protobuf/stubs/common.cc ${protobuf_source_dir}/src/google/protobuf/stubs/int128.cc - ${protobuf_source_dir}/src/google/protobuf/stubs/io_win32.cc - ${protobuf_source_dir}/src/google/protobuf/stubs/once.cc ${protobuf_source_dir}/src/google/protobuf/stubs/status.cc ${protobuf_source_dir}/src/google/protobuf/stubs/statusor.cc ${protobuf_source_dir}/src/google/protobuf/stubs/stringpiece.cc @@ -31,12 +35,15 @@ set(libprotobuf_lite_includes ${protobuf_source_dir}/src/google/protobuf/arenastring.h ${protobuf_source_dir}/src/google/protobuf/extension_set.h ${protobuf_source_dir}/src/google/protobuf/generated_message_util.h + ${protobuf_source_dir}/src/google/protobuf/implicit_weak_message.h + ${protobuf_source_dir}/src/google/protobuf/parse_context.h ${protobuf_source_dir}/src/google/protobuf/io/coded_stream.h + ${protobuf_source_dir}/src/google/protobuf/io/strtod.h ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream.h + ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl.h ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.h ${protobuf_source_dir}/src/google/protobuf/message_lite.h ${protobuf_source_dir}/src/google/protobuf/repeated_field.h - ${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h ${protobuf_source_dir}/src/google/protobuf/stubs/bytestream.h ${protobuf_source_dir}/src/google/protobuf/stubs/common.h ${protobuf_source_dir}/src/google/protobuf/stubs/int128.h @@ -50,9 +57,21 @@ set(libprotobuf_lite_includes ${protobuf_source_dir}/src/google/protobuf/wire_format_lite.h ) +if (MSVC) +set(libprotobuf_lite_rc_files + ${CMAKE_CURRENT_BINARY_DIR}/version.rc +) +endif() + add_library(libprotobuf-lite ${protobuf_SHARED_OR_STATIC} - ${libprotobuf_lite_files} ${libprotobuf_lite_includes}) + ${libprotobuf_lite_files} ${libprotobuf_lite_includes} ${libprotobuf_lite_rc_files}) target_link_libraries(libprotobuf-lite ${CMAKE_THREAD_LIBS_INIT}) +if(protobuf_LINK_LIBATOMIC) + target_link_libraries(libprotobuf-lite atomic) +endif() +if(${CMAKE_SYSTEM_NAME} STREQUAL "Android") + target_link_libraries(libprotobuf-lite log) +endif() target_include_directories(libprotobuf-lite PUBLIC ${protobuf_source_dir}/src) if(MSVC AND protobuf_BUILD_SHARED_LIBS) target_compile_definitions(libprotobuf-lite @@ -60,5 +79,7 @@ if(MSVC AND protobuf_BUILD_SHARED_LIBS) PRIVATE LIBPROTOBUF_EXPORTS) endif() set_target_properties(libprotobuf-lite PROPERTIES + VERSION ${protobuf_VERSION} OUTPUT_NAME ${LIB_PREFIX}protobuf-lite DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}") +add_library(protobuf::libprotobuf-lite ALIAS libprotobuf-lite) diff --git a/cmake/libprotobuf.cmake b/cmake/libprotobuf.cmake index 72db915bc99ca..a5be494fb702e 100644 --- a/cmake/libprotobuf.cmake +++ b/cmake/libprotobuf.cmake @@ -16,16 +16,13 @@ set(libprotobuf_files ${protobuf_source_dir}/src/google/protobuf/generated_message_table_driven.cc ${protobuf_source_dir}/src/google/protobuf/io/gzip_stream.cc ${protobuf_source_dir}/src/google/protobuf/io/printer.cc - ${protobuf_source_dir}/src/google/protobuf/io/strtod.cc ${protobuf_source_dir}/src/google/protobuf/io/tokenizer.cc - ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl.cc ${protobuf_source_dir}/src/google/protobuf/map_field.cc ${protobuf_source_dir}/src/google/protobuf/message.cc ${protobuf_source_dir}/src/google/protobuf/reflection_ops.cc ${protobuf_source_dir}/src/google/protobuf/service.cc ${protobuf_source_dir}/src/google/protobuf/source_context.pb.cc ${protobuf_source_dir}/src/google/protobuf/struct.pb.cc - ${protobuf_source_dir}/src/google/protobuf/stubs/mathlimits.cc ${protobuf_source_dir}/src/google/protobuf/stubs/substitute.cc ${protobuf_source_dir}/src/google/protobuf/text_format.cc ${protobuf_source_dir}/src/google/protobuf/timestamp.pb.cc @@ -72,16 +69,13 @@ set(libprotobuf_includes ${protobuf_source_dir}/src/google/protobuf/generated_message_reflection.h ${protobuf_source_dir}/src/google/protobuf/io/gzip_stream.h ${protobuf_source_dir}/src/google/protobuf/io/printer.h - ${protobuf_source_dir}/src/google/protobuf/io/strtod.h ${protobuf_source_dir}/src/google/protobuf/io/tokenizer.h - ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl.h ${protobuf_source_dir}/src/google/protobuf/map_field.h ${protobuf_source_dir}/src/google/protobuf/message.h ${protobuf_source_dir}/src/google/protobuf/reflection_ops.h ${protobuf_source_dir}/src/google/protobuf/service.h ${protobuf_source_dir}/src/google/protobuf/source_context.pb.h ${protobuf_source_dir}/src/google/protobuf/struct.pb.h - ${protobuf_source_dir}/src/google/protobuf/stubs/mathlimits.h ${protobuf_source_dir}/src/google/protobuf/stubs/substitute.h ${protobuf_source_dir}/src/google/protobuf/text_format.h ${protobuf_source_dir}/src/google/protobuf/timestamp.pb.h @@ -112,11 +106,23 @@ set(libprotobuf_includes ${protobuf_source_dir}/src/google/protobuf/wrappers.pb.h ) +if (MSVC) +set(libprotobuf_rc_files + ${CMAKE_CURRENT_BINARY_DIR}/version.rc +) +endif() + add_library(libprotobuf ${protobuf_SHARED_OR_STATIC} - ${libprotobuf_lite_files} ${libprotobuf_files} ${libprotobuf_includes}) + ${libprotobuf_lite_files} ${libprotobuf_files} ${libprotobuf_includes} ${libprotobuf_rc_files}) target_link_libraries(libprotobuf ${CMAKE_THREAD_LIBS_INIT}) if(protobuf_WITH_ZLIB) - target_link_libraries(libprotobuf ${ZLIB_LIBRARIES}) + target_link_libraries(libprotobuf ${ZLIB_LIBRARIES}) +endif() +if(protobuf_LINK_LIBATOMIC) + target_link_libraries(libprotobuf atomic) +endif() +if(${CMAKE_SYSTEM_NAME} STREQUAL "Android") + target_link_libraries(libprotobuf log) endif() target_include_directories(libprotobuf PUBLIC ${protobuf_source_dir}/src) if(MSVC AND protobuf_BUILD_SHARED_LIBS) @@ -125,5 +131,7 @@ if(MSVC AND protobuf_BUILD_SHARED_LIBS) PRIVATE LIBPROTOBUF_EXPORTS) endif() set_target_properties(libprotobuf PROPERTIES + VERSION ${protobuf_VERSION} OUTPUT_NAME ${LIB_PREFIX}protobuf DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}") +add_library(protobuf::libprotobuf ALIAS libprotobuf) diff --git a/cmake/libprotoc.cmake b/cmake/libprotoc.cmake index 9f2aa0c79f400..ecb5a851b8a21 100644 --- a/cmake/libprotoc.cmake +++ b/cmake/libprotoc.cmake @@ -11,6 +11,7 @@ set(libprotoc_files ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_map_field.cc ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message.cc ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_field.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_service.cc ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -43,8 +44,6 @@ set(libprotoc_files ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator.cc ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator_factory.cc ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_helpers.cc - ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_lazy_message_field.cc - ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_map_field.cc ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_map_field_lite.cc ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message.cc @@ -60,17 +59,6 @@ set(libprotoc_files ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_shared_code_generator.cc ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_string_field.cc ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_string_field_lite.cc - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_enum.cc - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_enum_field.cc - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_extension.cc - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_field.cc - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_file.cc - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_generator.cc - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_helpers.cc - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_map_field.cc - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_message.cc - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_message_field.cc - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc ${protobuf_source_dir}/src/google/protobuf/compiler/js/js_generator.cc ${protobuf_source_dir}/src/google/protobuf/compiler/js/well_known_types_embed.cc ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_enum.cc @@ -95,41 +83,30 @@ set(libprotoc_files ) set(libprotoc_headers - ${protobuf_source_dir}/src/google/protobuf/compiler/code_generator.h - ${protobuf_source_dir}/src/google/protobuf/compiler/command_line_interface.h - ${protobuf_source_dir}/src/google/protobuf/compiler/importer.h - ${protobuf_source_dir}/src/google/protobuf/compiler/mock_code_generator.h - ${protobuf_source_dir}/src/google/protobuf/compiler/package_info.h - ${protobuf_source_dir}/src/google/protobuf/compiler/parser.h - ${protobuf_source_dir}/src/google/protobuf/compiler/plugin.h - ${protobuf_source_dir}/src/google/protobuf/compiler/plugin.pb.h - ${protobuf_source_dir}/src/google/protobuf/compiler/subprocess.h - ${protobuf_source_dir}/src/google/protobuf/compiler/zip_writer.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_enum.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_enum_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_extension.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_file.h - ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_generator.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_helpers.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_map_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_field.h + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_names.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_options.h + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_primitive_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_service.h ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_string_field.h - ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_unittest.h ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_doc_comment.h ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_enum.h ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_enum_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_field_base.h - ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_generator.h ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_helpers.h ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_map_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_message.h ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_message_field.h - ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_names.h ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_options.h ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_primitive_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_reflection_class.h @@ -148,11 +125,8 @@ set(libprotoc_headers ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_extension_lite.h ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_file.h - ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator.h ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator_factory.h ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_helpers.h - ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_lazy_message_field.h - ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_map_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_map_field_lite.h ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message.h @@ -161,7 +135,6 @@ set(libprotoc_headers ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_field_lite.h ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_lite.h - ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_names.h ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_name_resolver.h ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_options.h ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_primitive_field.h @@ -170,52 +143,31 @@ set(libprotoc_headers ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_shared_code_generator.h ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_string_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_string_field_lite.h - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_enum.h - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_enum_field.h - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_extension.h - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_field.h - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_file.h - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_generator.h - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_helpers.h - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_map_field.h - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_message.h - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_message_field.h - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_params.h - ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_primitive_field.h - ${protobuf_source_dir}/src/google/protobuf/compiler/js/js_generator.h - ${protobuf_source_dir}/src/google/protobuf/compiler/js/well_known_types_embed.h ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_enum.h ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_extension.h ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_file.h - ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_generator.h ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_helpers.h ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_map_field.h ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_message.h ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_message_field.h + ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_oneof.h ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h - ${protobuf_source_dir}/src/google/protobuf/compiler/php/php_generator.h - ${protobuf_source_dir}/src/google/protobuf/compiler/python/python_generator.h - ${protobuf_source_dir}/src/google/protobuf/compiler/ruby/ruby_generator.h - ${protobuf_source_dir}/src/google/protobuf/compiler/plugin.pb.h + ${protobuf_source_dir}/src/google/protobuf/compiler/scc.h + ${protobuf_source_dir}/src/google/protobuf/compiler/subprocess.h + ${protobuf_source_dir}/src/google/protobuf/compiler/zip_writer.h ) -set(js_well_known_types_sources - ${protobuf_source_dir}/src/google/protobuf/compiler/js/well_known_types/any.js - ${protobuf_source_dir}/src/google/protobuf/compiler/js/well_known_types/struct.js - ${protobuf_source_dir}/src/google/protobuf/compiler/js/well_known_types/timestamp.js -) -add_executable(js_embed ${protobuf_source_dir}/src/google/protobuf/compiler/js/embed.cc) -add_custom_command( - OUTPUT ${protobuf_source_dir}/src/google/protobuf/compiler/js/well_known_types_embed.cc - DEPENDS js_embed ${js_well_known_types_sources} - COMMAND js_embed ${js_well_known_types_sources} > ${protobuf_source_dir}/src/google/protobuf/compiler/js/well_known_types_embed.cc +if (MSVC) +set(libprotoc_rc_files + ${CMAKE_CURRENT_BINARY_DIR}/version.rc ) +endif() add_library(libprotoc ${protobuf_SHARED_OR_STATIC} - ${libprotoc_files} ${libprotoc_headers}) + ${libprotoc_files} ${libprotoc_headers} ${libprotoc_rc_files}) target_link_libraries(libprotoc libprotobuf) if(MSVC AND protobuf_BUILD_SHARED_LIBS) target_compile_definitions(libprotoc @@ -224,5 +176,8 @@ if(MSVC AND protobuf_BUILD_SHARED_LIBS) endif() set_target_properties(libprotoc PROPERTIES COMPILE_DEFINITIONS LIBPROTOC_EXPORTS + VERSION ${protobuf_VERSION} OUTPUT_NAME ${LIB_PREFIX}protoc DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}") +add_library(protobuf::libprotoc ALIAS libprotoc) + diff --git a/cmake/protobuf-config-version.cmake.in b/cmake/protobuf-config-version.cmake.in index ca6da09ad7136..3fa01763ee653 100644 --- a/cmake/protobuf-config-version.cmake.in +++ b/cmake/protobuf-config-version.cmake.in @@ -49,9 +49,9 @@ _check_and_save_build_option(MSVC_STATIC_RUNTIME @protobuf_MSVC_STATIC_RUNTIME@) _check_and_save_build_option(BUILD_SHARED_LIBS @protobuf_BUILD_SHARED_LIBS@) # if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: -if(NOT "${CMAKE_SIZEOF_VOID_P}" STREQUAL "" AND NOT "@CMAKE_SIZEOF_VOID_P@" STREQUAL "") +if(CMAKE_SIZEOF_VOID_P AND "@CMAKE_SIZEOF_VOID_P@") # check that the installed version has the same 32/64bit-ness as the one which is currently searching: - if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "@CMAKE_SIZEOF_VOID_P@") + if(NOT CMAKE_SIZEOF_VOID_P EQUAL "@CMAKE_SIZEOF_VOID_P@") math(EXPR installedBits "@CMAKE_SIZEOF_VOID_P@ * 8") set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") set(PACKAGE_VERSION_UNSUITABLE TRUE) diff --git a/cmake/protobuf-config.cmake.in b/cmake/protobuf-config.cmake.in index 8321354781878..fac5efe44077e 100644 --- a/cmake/protobuf-config.cmake.in +++ b/cmake/protobuf-config.cmake.in @@ -9,14 +9,17 @@ include("${CMAKE_CURRENT_LIST_DIR}/protobuf-targets.cmake") function(protobuf_generate) include(CMakeParseArguments) - set(_singleargs LANGUAGE OUT_VAR) + + set(_options APPEND_PATH) + set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR PLUGIN) if(COMMAND target_sources) list(APPEND _singleargs TARGET) endif() + set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS) - cmake_parse_arguments(protobuf_generate "APPEND_PATH" "${_singleargs}" "PROTOS IMPORT_DIRS GENERATE_EXTENSIONS" "${ARGN}") + cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}") - if(protobuf_generate_PROTOS AND NOT protobuf_generate_TARGET) + if(NOT protobuf_generate_PROTOS AND NOT protobuf_generate_TARGET) message(SEND_ERROR "Error: protobuf_generate called without any targets or source files") return() endif() @@ -31,20 +34,46 @@ function(protobuf_generate) endif() string(TOLOWER ${protobuf_generate_LANGUAGE} protobuf_generate_LANGUAGE) - if(NOT protobuf_GENERATE_EXTENSIONS) + if(NOT protobuf_generate_PROTOC_OUT_DIR) + set(protobuf_generate_PROTOC_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) + endif() + + if(protobuf_generate_EXPORT_MACRO AND protobuf_generate_LANGUAGE STREQUAL cpp) + set(_dll_export_decl "dllexport_decl=${protobuf_generate_EXPORT_MACRO}:") + endif() + + if(protobuf_generate_PLUGIN) + set(_plugin "--plugin=${protobuf_generate_PLUGIN}") + endif() + + if(NOT protobuf_generate_GENERATE_EXTENSIONS) if(protobuf_generate_LANGUAGE STREQUAL cpp) - set(protobuf_GENERATE_EXTENSIONS .pb.h .pb.cc) + set(protobuf_generate_GENERATE_EXTENSIONS .pb.h .pb.cc) elseif(protobuf_generate_LANGUAGE STREQUAL python) - set(protobuf_GENERATE_EXTENSIONS _pb2.py) + set(protobuf_generate_GENERATE_EXTENSIONS _pb2.py) else() message(SEND_ERROR "Error: protobuf_generate given unknown Language ${LANGUAGE}, please provide a value for GENERATE_EXTENSIONS") return() endif() endif() + if(protobuf_generate_TARGET) + get_target_property(_source_list ${protobuf_generate_TARGET} SOURCES) + foreach(_file ${_source_list}) + if(_file MATCHES "proto$") + list(APPEND protobuf_generate_PROTOS ${_file}) + endif() + endforeach() + endif() + + if(NOT protobuf_generate_PROTOS) + message(SEND_ERROR "Error: protobuf_generate could not find any .proto files") + return() + endif() + if(protobuf_generate_APPEND_PATH) # Create an include path for each file specified - foreach(_file ${ARGN}) + foreach(_file ${protobuf_generate_PROTOS}) get_filename_component(_abs_file ${_file} ABSOLUTE) get_filename_component(_abs_path ${_abs_file} PATH) list(FIND _protobuf_include_path ${_abs_path} _contains_already) @@ -52,8 +81,6 @@ function(protobuf_generate) list(APPEND _protobuf_include_path -I ${_abs_path}) endif() endforeach() - else() - set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR}) endif() foreach(DIR ${protobuf_generate_IMPORT_DIRS}) @@ -64,44 +91,57 @@ function(protobuf_generate) endif() endforeach() - if(protobuf_generate_TARGET) - get_target_property(_source_list ${protobuf_generate_TARGET} SOURCES) - foreach(_file ${_source_list}) - if(_file MATCHES "proto$") - list(APPEND protobuf_generate_PROTOS ${_file}) - endif() - endforeach() - endif() - - if(NOT protobuf_generate_PROTOS) - message(SEND_ERROR "Error: protobuf_generate could not find any .proto files") - return() + if(NOT _protobuf_include_path) + set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR}) endif() - set(_generated_srcs) + set(_generated_srcs_all) foreach(_proto ${protobuf_generate_PROTOS}) get_filename_component(_abs_file ${_proto} ABSOLUTE) - get_filename_component(_basename ${_proto} NAME_WE) + get_filename_component(_abs_dir ${_abs_file} DIRECTORY) + + get_filename_component(_file_full_name ${_proto} NAME) + string(FIND "${_file_full_name}" "." _file_last_ext_pos REVERSE) + string(SUBSTRING "${_file_full_name}" 0 ${_file_last_ext_pos} _basename) + + set(_suitable_include_found FALSE) + foreach(DIR ${_protobuf_include_path}) + if(NOT DIR STREQUAL "-I") + file(RELATIVE_PATH _rel_dir ${DIR} ${_abs_dir}) + string(FIND "${_rel_dir}" "../" _is_in_parent_folder) + if (NOT ${_is_in_parent_folder} EQUAL 0) + set(_suitable_include_found TRUE) + break() + endif() + endif() + endforeach() + + if(NOT _suitable_include_found) + message(SEND_ERROR "Error: protobuf_generate could not find any correct proto include directory.") + return() + endif() - foreach(_ext ${_output_extensions}) - list(APPEND _generated_srcs "${CMAKE_CURRENT_BINARY_DIR}/${_basename}${_ext}") + set(_generated_srcs) + foreach(_ext ${protobuf_generate_GENERATE_EXTENSIONS}) + list(APPEND _generated_srcs "${protobuf_generate_PROTOC_OUT_DIR}/${_rel_dir}/${_basename}${_ext}") endforeach() + list(APPEND _generated_srcs_all ${_generated_srcs}) add_custom_command( OUTPUT ${_generated_srcs} COMMAND protobuf::protoc - ARGS --${protobuf_generate_LANGUAGE}_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${_abs_file} - DEPENDS ${ABS_FIL} protobuf::protoc + ARGS --${protobuf_generate_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_protobuf_include_path} ${_abs_file} + DEPENDS ${_abs_file} protobuf::protoc COMMENT "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}" VERBATIM ) endforeach() - set_source_files_properties(${_generated_srcs} PROPERTIES GENERATED TRUE) + set_source_files_properties(${_generated_srcs_all} PROPERTIES GENERATED TRUE) if(protobuf_generate_OUT_VAR) - set(${protobuf_generate_OUT_VAR} ${_generated_srcs} PARENT_SCOPE) + set(${protobuf_generate_OUT_VAR} ${_generated_srcs_all} PARENT_SCOPE) endif() if(protobuf_generate_TARGET) - target_sources(${protobuf_generate_TARGET} PUBLIC ${_generated_srcs}) + target_sources(${protobuf_generate_TARGET} PRIVATE ${_generated_srcs_all}) endif() endfunction() diff --git a/cmake/protobuf-lite.pc.cmake b/cmake/protobuf-lite.pc.cmake index cbe5426afa438..9745cb89c7a7b 100644 --- a/cmake/protobuf-lite.pc.cmake +++ b/cmake/protobuf-lite.pc.cmake @@ -7,5 +7,5 @@ Name: Protocol Buffers Description: Google's Data Interchange Format Version: @protobuf_VERSION@ Libs: -L${libdir} -lprotobuf-lite @CMAKE_THREAD_LIBS_INIT@ -Cflags: -I${includedir} @CMAKE_THREAD_LIBS_INIT@ +Cflags: -I${includedir} Conflicts: protobuf diff --git a/cmake/protobuf-module.cmake.in b/cmake/protobuf-module.cmake.in index 8e4920aa807cb..810256e54cfb4 100644 --- a/cmake/protobuf-module.cmake.in +++ b/cmake/protobuf-module.cmake.in @@ -2,7 +2,10 @@ # Functions function(PROTOBUF_GENERATE_CPP SRCS HDRS) - if(NOT ARGN) + cmake_parse_arguments(protobuf_generate_cpp "" "EXPORT_MACRO" "" ${ARGN}) + + set(_proto_files "${protobuf_generate_cpp_UNPARSED_ARGUMENTS}") + if(NOT _proto_files) message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files") return() endif() @@ -16,7 +19,7 @@ function(PROTOBUF_GENERATE_CPP SRCS HDRS) endif() set(_outvar) - protobuf_generate(${append_arg} LANGUAGE cpp OUT_VAR _outvar ${_import_arg} PROTOS ${ARGN}) + protobuf_generate(${_append_arg} LANGUAGE cpp EXPORT_MACRO ${protobuf_generate_cpp_EXPORT_MACRO} OUT_VAR _outvar ${_import_arg} PROTOS ${_proto_files}) set(${SRCS}) set(${HDRS}) @@ -46,7 +49,7 @@ function(PROTOBUF_GENERATE_PYTHON SRCS) endif() set(_outvar) - protobuf_generate(${append_arg} LANGUAGE cpp OUT_VAR _outvar ${_import_arg} PROTOS ${ARGN}) + protobuf_generate(${_append_arg} LANGUAGE python OUT_VAR _outvar ${_import_arg} PROTOS ${ARGN}) set(${SRCS} ${_outvar} PARENT_SCOPE) endfunction() @@ -94,6 +97,10 @@ function(_protobuf_find_libraries name filename) else() get_target_property(${name}_LIBRARY_RELEASE protobuf::lib${filename} LOCATION_RELEASE) + get_target_property(${name}_LIBRARY_RELWITHDEBINFO protobuf::lib${filename} + LOCATION_RELWITHDEBINFO) + get_target_property(${name}_LIBRARY_MINSIZEREL protobuf::lib${filename} + LOCATION_MINSIZEREL) get_target_property(${name}_LIBRARY_DEBUG protobuf::lib${filename} LOCATION_DEBUG) @@ -143,10 +150,22 @@ get_target_property(Protobuf_INCLUDE_DIRS protobuf::libprotobuf # Set the protoc Executable get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc IMPORTED_LOCATION_RELEASE) +if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}") + get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc + IMPORTED_LOCATION_RELWITHDEBINFO) +endif() +if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}") + get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc + IMPORTED_LOCATION_MINSIZEREL) +endif() if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}") get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc IMPORTED_LOCATION_DEBUG) endif() +if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}") + get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc + IMPORTED_LOCATION_NOCONFIG) +endif() # Version info variable set(Protobuf_VERSION "@protobuf_VERSION@") diff --git a/cmake/protobuf-options.cmake b/cmake/protobuf-options.cmake index 47fb15825752e..93ec898e4a44d 100644 --- a/cmake/protobuf-options.cmake +++ b/cmake/protobuf-options.cmake @@ -2,6 +2,6 @@ option(protobuf_VERBOSE "Enable for verbose output" OFF) mark_as_advanced(protobuf_VERBOSE) -# FindProtobuf module compatibel -option(protobuf_MODULE_COMPATIBLE "CMake build-in FindProtobuf.cmake module compatible" OFF) +# FindProtobuf module compatible +option(protobuf_MODULE_COMPATIBLE "CMake built-in FindProtobuf.cmake module compatible" OFF) mark_as_advanced(protobuf_MODULE_COMPATIBLE) diff --git a/cmake/protobuf.pc.cmake b/cmake/protobuf.pc.cmake index d33e98cca8f05..f068e6926e72e 100644 --- a/cmake/protobuf.pc.cmake +++ b/cmake/protobuf.pc.cmake @@ -7,5 +7,5 @@ Name: Protocol Buffers Description: Google's Data Interchange Format Version: @protobuf_VERSION@ Libs: -L${libdir} -lprotobuf @CMAKE_THREAD_LIBS_INIT@ -Cflags: -I${includedir} @CMAKE_THREAD_LIBS_INIT@ +Cflags: -I${includedir} Conflicts: protobuf-lite diff --git a/cmake/protoc.cmake b/cmake/protoc.cmake index 4f07c389c9767..f90e525e80037 100644 --- a/cmake/protoc.cmake +++ b/cmake/protoc.cmake @@ -2,5 +2,15 @@ set(protoc_files ${protobuf_source_dir}/src/google/protobuf/compiler/main.cc ) -add_executable(protoc ${protoc_files}) -target_link_libraries(protoc libprotobuf libprotoc) +if (MSVC) +set(protoc_rc_files + ${CMAKE_CURRENT_BINARY_DIR}/version.rc +) +endif() + +add_executable(protoc ${protoc_files} ${protoc_rc_files}) +target_link_libraries(protoc libprotoc libprotobuf) +add_executable(protobuf::protoc ALIAS protoc) + +set_target_properties(protoc PROPERTIES + VERSION ${protobuf_VERSION}) diff --git a/cmake/tests.cmake b/cmake/tests.cmake index 389f6a7bcd319..4a54b70d74246 100644 --- a/cmake/tests.cmake +++ b/cmake/tests.cmake @@ -1,24 +1,31 @@ -if (NOT EXISTS "${PROJECT_SOURCE_DIR}/../gmock/CMakeLists.txt") - message(FATAL_ERROR "Cannot find gmock directory.") +if (NOT EXISTS "${PROJECT_SOURCE_DIR}/../third_party/googletest/CMakeLists.txt") + message(FATAL_ERROR + "Cannot find third_party/googletest directory that's needed to " + "build tests. If you use git, make sure you have cloned submodules:\n" + " git submodule update --init --recursive\n" + "If instead you want to skip tests, run cmake with:\n" + " cmake -Dprotobuf_BUILD_TESTS=OFF\n") endif() option(protobuf_ABSOLUTE_TEST_PLUGIN_PATH "Using absolute test_plugin path in tests" ON) mark_as_advanced(protobuf_ABSOLUTE_TEST_PLUGIN_PATH) +set(googlemock_source_dir "${protobuf_source_dir}/third_party/googletest/googlemock") +set(googletest_source_dir "${protobuf_source_dir}/third_party/googletest/googletest") include_directories( - ${protobuf_source_dir}/gmock - ${protobuf_source_dir}/gmock/gtest - ${protobuf_source_dir}/gmock/gtest/include - ${protobuf_source_dir}/gmock/include + ${googlemock_source_dir} + ${googletest_source_dir} + ${googletest_source_dir}/include + ${googlemock_source_dir}/include ) add_library(gmock STATIC - ${protobuf_source_dir}/gmock/src/gmock-all.cc - ${protobuf_source_dir}/gmock/gtest/src/gtest-all.cc + "${googlemock_source_dir}/src/gmock-all.cc" + "${googletest_source_dir}/src/gtest-all.cc" ) target_link_libraries(gmock ${CMAKE_THREAD_LIBS_INIT}) -add_library(gmock_main STATIC ${protobuf_source_dir}/gmock/src/gmock_main.cc) +add_library(gmock_main STATIC "${googlemock_source_dir}/src/gmock_main.cc") target_link_libraries(gmock_main gmock) set(lite_test_protos @@ -26,7 +33,6 @@ set(lite_test_protos google/protobuf/unittest_import_lite.proto google/protobuf/unittest_import_public_lite.proto google/protobuf/unittest_lite.proto - google/protobuf/unittest_no_arena_lite.proto ) set(tests_protos @@ -49,16 +55,16 @@ set(tests_protos google/protobuf/unittest_lite_imports_nonlite.proto google/protobuf/unittest_mset.proto google/protobuf/unittest_mset_wire_format.proto - google/protobuf/unittest_no_arena.proto - google/protobuf/unittest_no_arena_import.proto google/protobuf/unittest_no_field_presence.proto google/protobuf/unittest_no_generic_services.proto google/protobuf/unittest_optimize_for.proto google/protobuf/unittest_preserve_unknown_enum.proto google/protobuf/unittest_preserve_unknown_enum2.proto + google/protobuf/unittest_proto3.proto google/protobuf/unittest_proto3_arena.proto google/protobuf/unittest_proto3_arena_lite.proto google/protobuf/unittest_proto3_lite.proto + google/protobuf/unittest_proto3_optional.proto google/protobuf/unittest_well_known_types.proto google/protobuf/util/internal/testdata/anys.proto google/protobuf/util/internal/testdata/books.proto @@ -71,6 +77,7 @@ set(tests_protos google/protobuf/util/internal/testdata/struct.proto google/protobuf/util/internal/testdata/timestamp_duration.proto google/protobuf/util/internal/testdata/wrappers.proto + google/protobuf/util/json_format.proto google/protobuf/util/json_format_proto3.proto google/protobuf/util/message_differencer_unittest.proto ) @@ -80,10 +87,11 @@ macro(compile_proto_file filename) get_filename_component(basename ${filename} NAME_WE) add_custom_command( OUTPUT ${protobuf_source_dir}/src/${dirname}/${basename}.pb.cc - DEPENDS protoc ${protobuf_source_dir}/src/${dirname}/${basename}.proto - COMMAND protoc ${protobuf_source_dir}/src/${dirname}/${basename}.proto + DEPENDS ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/${dirname}/${basename}.proto + COMMAND ${protobuf_PROTOC_EXE} ${protobuf_source_dir}/src/${dirname}/${basename}.proto --proto_path=${protobuf_source_dir}/src --cpp_out=${protobuf_source_dir}/src + --experimental_allow_proto3_optional ) endmacro(compile_proto_file) @@ -105,8 +113,9 @@ endforeach(proto_file) set(common_test_files ${protobuf_source_dir}/src/google/protobuf/arena_test_util.cc - ${protobuf_source_dir}/src/google/protobuf/map_test_util.cc + ${protobuf_source_dir}/src/google/protobuf/map_test_util.inc ${protobuf_source_dir}/src/google/protobuf/test_util.cc + ${protobuf_source_dir}/src/google/protobuf/test_util.inc ${protobuf_source_dir}/src/google/protobuf/testing/file.cc ${protobuf_source_dir}/src/google/protobuf/testing/googletest.cc ) @@ -121,11 +130,12 @@ set(tests_files ${protobuf_source_dir}/src/google/protobuf/any_test.cc ${protobuf_source_dir}/src/google/protobuf/arena_unittest.cc ${protobuf_source_dir}/src/google/protobuf/arenastring_unittest.cc - ${protobuf_source_dir}/src/google/protobuf/compiler/command_line_interface_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/annotation_test_util.cc ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_move_unittest.cc ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_unittest.inc ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/metadata_test.cc ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc @@ -144,25 +154,26 @@ set(tests_files ${protobuf_source_dir}/src/google/protobuf/extension_set_unittest.cc ${protobuf_source_dir}/src/google/protobuf/generated_message_reflection_unittest.cc ${protobuf_source_dir}/src/google/protobuf/io/coded_stream_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/io/io_win32_unittest.cc ${protobuf_source_dir}/src/google/protobuf/io/printer_unittest.cc ${protobuf_source_dir}/src/google/protobuf/io/tokenizer_unittest.cc ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_unittest.cc ${protobuf_source_dir}/src/google/protobuf/map_field_test.cc ${protobuf_source_dir}/src/google/protobuf/map_test.cc ${protobuf_source_dir}/src/google/protobuf/message_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/message_unittest.inc ${protobuf_source_dir}/src/google/protobuf/no_field_presence_test.cc ${protobuf_source_dir}/src/google/protobuf/preserve_unknown_enum_test.cc ${protobuf_source_dir}/src/google/protobuf/proto3_arena_lite_unittest.cc ${protobuf_source_dir}/src/google/protobuf/proto3_arena_unittest.cc ${protobuf_source_dir}/src/google/protobuf/proto3_lite_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/proto3_lite_unittest.inc ${protobuf_source_dir}/src/google/protobuf/reflection_ops_unittest.cc ${protobuf_source_dir}/src/google/protobuf/repeated_field_reflection_unittest.cc ${protobuf_source_dir}/src/google/protobuf/repeated_field_unittest.cc ${protobuf_source_dir}/src/google/protobuf/stubs/bytestream_unittest.cc ${protobuf_source_dir}/src/google/protobuf/stubs/common_unittest.cc ${protobuf_source_dir}/src/google/protobuf/stubs/int128_unittest.cc - ${protobuf_source_dir}/src/google/protobuf/stubs/io_win32_unittest.cc - ${protobuf_source_dir}/src/google/protobuf/stubs/once_unittest.cc ${protobuf_source_dir}/src/google/protobuf/stubs/status_test.cc ${protobuf_source_dir}/src/google/protobuf/stubs/statusor_test.cc ${protobuf_source_dir}/src/google/protobuf/stubs/stringpiece_unittest.cc @@ -171,7 +182,6 @@ set(tests_files ${protobuf_source_dir}/src/google/protobuf/stubs/strutil_unittest.cc ${protobuf_source_dir}/src/google/protobuf/stubs/template_util_unittest.cc ${protobuf_source_dir}/src/google/protobuf/stubs/time_test.cc - ${protobuf_source_dir}/src/google/protobuf/stubs/type_traits_unittest.cc ${protobuf_source_dir}/src/google/protobuf/text_format_unittest.cc ${protobuf_source_dir}/src/google/protobuf/unknown_field_set_unittest.cc ${protobuf_source_dir}/src/google/protobuf/util/delimited_message_util_test.cc @@ -191,11 +201,31 @@ set(tests_files ${protobuf_source_dir}/src/google/protobuf/wire_format_unittest.cc ) +set(non_msvc_tests_files + ${protobuf_source_dir}/src/google/protobuf/compiler/command_line_interface_unittest.cc +) + +set(all_tests_files + ${tests_files} + ${non_msvc_tests_files} +) + if(protobuf_ABSOLUTE_TEST_PLUGIN_PATH) add_compile_options(-DGOOGLE_PROTOBUF_TEST_PLUGIN_PATH="$") endif() -add_executable(tests ${tests_files} ${common_test_files} ${tests_proto_files} ${lite_test_proto_files}) +if(MINGW) + set_source_files_properties(${all_tests_files} PROPERTIES COMPILE_FLAGS "-Wno-narrowing") + + # required for tests on MinGW Win64 + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--stack,16777216") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj") + endif() + +endif() + +add_executable(tests ${all_tests_files} ${common_test_files} ${tests_proto_files} ${lite_test_proto_files}) target_link_libraries(tests libprotoc libprotobuf gmock_main) set(test_plugin_files diff --git a/cmake/version.rc.in b/cmake/version.rc.in new file mode 100644 index 0000000000000..f6e7c4a3f9e48 --- /dev/null +++ b/cmake/version.rc.in @@ -0,0 +1,45 @@ +#define VS_FF_DEBUG 0x1L +#define VS_VERSION_INFO 0x1L +#define VS_FFI_FILEFLAGSMASK 0x17L +#define VER_PRIVATEBUILD 0x0L +#define VER_PRERELEASE 0x0L +#define VOS__WINDOWS32 0x4L +#define VFT_DLL 0x2L +#define VFT2_UNKNOWN 0x0L + +#ifndef DEBUG +#define VER_DEBUG 0 +#else +#define VER_DEBUG VS_FF_DEBUG +#endif + + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @protobuf_RC_FILEVERSION@ + PRODUCTVERSION @protobuf_RC_FILEVERSION@ + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS VER_DEBUG + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL +BEGIN + BLOCK "VarFileInfo" + BEGIN + // English language (0x409) and the Windows Unicode codepage (1200) + VALUE "Translation", 0x409, 1200 + END + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "Compiled with @CMAKE_CXX_COMPILER_ID@ @CMAKE_CXX_COMPILER_VERSION@\0" + VALUE "ProductVersion", "@protobuf_VERSION@\0" + VALUE "FileVersion", "@protobuf_VERSION@\0" + VALUE "InternalName", "protobuf\0" + VALUE "ProductName", "Protocol Buffers - Google's Data Interchange Format\0" + VALUE "CompanyName", "Google Inc.\0" + VALUE "LegalCopyright", "Copyright 2008 Google Inc. All rights reserved.\0" + VALUE "Licence", "BSD\0" + VALUE "Info", "https://developers.google.com/protocol-buffers/\0" + END + END +END diff --git a/compiler_config_setting.bzl b/compiler_config_setting.bzl new file mode 100644 index 0000000000000..f4d1f7b9ef4ab --- /dev/null +++ b/compiler_config_setting.bzl @@ -0,0 +1,23 @@ +"""Creates config_setting that allows selecting based on 'compiler' value.""" + +def create_compiler_config_setting(name, value, visibility = None): + # The "do_not_use_tools_cpp_compiler_present" attribute exists to + # distinguish between older versions of Bazel that do not support + # "@bazel_tools//tools/cpp:compiler" flag_value, and newer ones that do. + # In the future, the only way to select on the compiler will be through + # flag_values{"@bazel_tools//tools/cpp:compiler"} and the else branch can + # be removed. + if hasattr(cc_common, "do_not_use_tools_cpp_compiler_present"): + native.config_setting( + name = name, + flag_values = { + "@bazel_tools//tools/cpp:compiler": value, + }, + visibility = visibility, + ) + else: + native.config_setting( + name = name, + values = {"compiler": value}, + visibility = visibility, + ) diff --git a/configure.ac b/configure.ac index 04f7eb7a4a590..fed7095bbd437 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ AC_PREREQ(2.59) # In the SVN trunk, the version should always be the next anticipated release # version with the "-pre" suffix. (We used to use "-SNAPSHOT" but this pushed # the size of one file name in the dist tarfile over the 99-char limit.) -AC_INIT([Protocol Buffers],[3.4.0],[protobuf@googlegroups.com],[protobuf]) +AC_INIT([Protocol Buffers],[3.15.0],[protobuf@googlegroups.com],[protobuf]) AM_MAINTAINER_MODE([enable]) @@ -47,11 +47,26 @@ AC_CANONICAL_TARGET AM_INIT_AUTOMAKE([1.9 tar-ustar subdir-objects]) +# Silent rules enabled: the output is minimal but informative. +# In particular, the warnings from the compiler stick out very clearly. +# To see all logs, use the --disable-silent-rules on configure or via make V=1 +AM_SILENT_RULES([yes]) + AC_ARG_WITH([zlib], [AS_HELP_STRING([--with-zlib], [include classes for streaming compressed data in and out @<:@default=check@:>@])], [],[with_zlib=check]) +AC_ARG_WITH([zlib-include], + [AS_HELP_STRING([--with-zlib-include=PATH], + [zlib include directory])], + [CPPFLAGS="-I$withval $CPPFLAGS"]) + +AC_ARG_WITH([zlib-lib], + [AS_HELP_STRING([--with-zlib-lib=PATH], + [zlib lib directory])], + [LDFLAGS="-L$withval $LDFLAGS"]) + AC_ARG_WITH([protoc], [AS_HELP_STRING([--with-protoc=COMMAND], [use the given protoc command instead of building a new one when building tests (useful for cross-compiling)])], @@ -78,7 +93,7 @@ AS_IF([test "x${ac_cv_env_CXXFLAGS_set}" = "x"],[ # Protocol Buffers contains several checks that are intended to be used only # for debugging and which might hurt performance. Most users are probably # end users who don't want these checks, so add -DNDEBUG by default. - CXXFLAGS="$CXXFLAGS -DNDEBUG" + CXXFLAGS="$CXXFLAGS -std=c++11 -DNDEBUG" AC_MSG_RESULT([use default: $PROTOBUF_OPT_FLAG $CXXFLAGS]) ],[ @@ -155,6 +170,26 @@ AS_IF([test "$with_zlib" != no], [ ]) AM_CONDITIONAL([HAVE_ZLIB], [test $HAVE_ZLIB = 1]) +# Add -std=c++11 if necesssary. It is important for us to do this before the +# libatomic check below, since that also depends on C++11. +AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory]) + +dnl On some platforms, std::atomic needs a helper library +AC_MSG_CHECKING(whether -latomic is needed) +AC_LINK_IFELSE([AC_LANG_SOURCE([[ + #include + #include + std::atomic v; + int main() { + return v; + } +]])], STD_ATOMIC_NEED_LIBATOMIC=no, STD_ATOMIC_NEED_LIBATOMIC=yes) +AC_MSG_RESULT($STD_ATOMIC_NEED_LIBATOMIC) +if test "x$STD_ATOMIC_NEED_LIBATOMIC" = xyes; then + LIBATOMIC_LIBS="-latomic" +fi +AC_SUBST([LIBATOMIC_LIBS]) + AS_IF([test "$with_protoc" != "no"], [ PROTOC=$with_protoc AS_IF([test "$with_protoc" = "yes"], [ @@ -174,21 +209,11 @@ AS_IF([test "$with_protoc" != "no"], [ ]) AM_CONDITIONAL([USE_EXTERNAL_PROTOC], [test "$with_protoc" != "no"]) -ACX_PTHREAD -AM_CONDITIONAL([HAVE_PTHREAD], [test "x$acx_pthread_ok" = "xyes"]) - +AX_PTHREAD +AM_CONDITIONAL([HAVE_PTHREAD], [test "x$ax_pthread_ok" = "xyes"]) # We still keep this for improving pbconfig.h for unsupported platforms. AC_CXX_STL_HASH -case "$target_os" in - mingw* | cygwin* | win*) - ;; - *) - # Need to link against rt on Solaris - AC_SEARCH_LIBS([sched_yield], [rt], [], [AC_MSG_FAILURE([sched_yield was not found on your system])]) - ;; -esac - # Enable ObjC support for conformance directory on OS X. OBJC_CONFORMANCE_TEST=0 case "$target_os" in @@ -198,14 +223,12 @@ case "$target_os" in esac AM_CONDITIONAL([OBJC_CONFORMANCE_TEST], [test $OBJC_CONFORMANCE_TEST = 1]) -AX_CXX_COMPILE_STDCXX([11], [noext], [optional]) - # HACK: Make gmock's configure script pick up our copy of CFLAGS and CXXFLAGS, # since the flags added by ACX_CHECK_SUNCC must be used when compiling gmock # too. export CFLAGS export CXXFLAGS -AC_CONFIG_SUBDIRS([gmock]) +AC_CONFIG_SUBDIRS([third_party/googletest]) AC_CONFIG_FILES([Makefile src/Makefile benchmarks/Makefile conformance/Makefile protobuf.pc protobuf-lite.pc]) AC_OUTPUT diff --git a/conformance/ConformanceJava.java b/conformance/ConformanceJava.java index 596d113a9240b..531998262d721 100644 --- a/conformance/ConformanceJava.java +++ b/conformance/ConformanceJava.java @@ -1,16 +1,47 @@ -import com.google.protobuf.ByteString; +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + import com.google.protobuf.AbstractMessage; -import com.google.protobuf.Parser; +import com.google.protobuf.ByteString; import com.google.protobuf.CodedInputStream; -import com.google.protobuf.conformance.Conformance; -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf_test_messages.proto3.TestMessagesProto3; -import com.google.protobuf_test_messages.proto3.TestMessagesProto3.TestAllTypesProto3; -import com.google.protobuf_test_messages.proto2.TestMessagesProto2; -import com.google.protobuf_test_messages.proto2.TestMessagesProto2.TestAllTypesProto2; import com.google.protobuf.ExtensionRegistry; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Parser; +import com.google.protobuf.TextFormat; +import com.google.protobuf.conformance.Conformance; import com.google.protobuf.util.JsonFormat; import com.google.protobuf.util.JsonFormat.TypeRegistry; +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.proto3.TestMessagesProto3.TestAllTypesProto3; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -56,7 +87,7 @@ private void writeLittleEndianIntToStdout(int val) throws Exception { buf[3] = (byte)(val >> 24); writeToStdout(buf); } - + private enum BinaryDecoderType { BTYE_STRING_DECODER, BYTE_ARRAY_DECODER, @@ -68,11 +99,11 @@ private enum BinaryDecoderType { } private static class BinaryDecoder { - public MessageType decode (ByteString bytes, BinaryDecoderType type, + public MessageType decode (ByteString bytes, BinaryDecoderType type, Parser parser, ExtensionRegistry extensions) throws InvalidProtocolBufferException { switch (type) { - case BTYE_STRING_DECODER: + case BTYE_STRING_DECODER: return parser.parseFrom(bytes, extensions); case BYTE_ARRAY_DECODER: return parser.parseFrom(bytes.toByteArray(), extensions); @@ -93,7 +124,7 @@ public MessageType decode (ByteString bytes, BinaryDecoderType type, } catch (InvalidProtocolBufferException e) { throw e; } - } + } case DIRECT_BYTE_BUFFER_DECODER: { ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size()); bytes.copyTo(buffer); @@ -134,7 +165,7 @@ private MessageType parseBinary( ArrayList messages = new ArrayList (); ArrayList exceptions = new ArrayList (); - + for (int i = 0; i < BinaryDecoderType.values().length; i++) { messages.add(null); exceptions.add(null); @@ -205,8 +236,10 @@ private MessageType parseBinary( private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) { com.google.protobuf.AbstractMessage testMessage; - boolean isProto3 = request.getMessageType().equals("protobuf_test_messages.proto3.TestAllTypesProto3"); - boolean isProto2 = request.getMessageType().equals("protobuf_test_messages.proto2.TestAllTypesProto2"); + boolean isProto3 = + request.getMessageType().equals("protobuf_test_messages.proto3.TestAllTypesProto3"); + boolean isProto2 = + request.getMessageType().equals("protobuf_test_messages.proto2.TestAllTypesProto2"); switch (request.getPayloadCase()) { case PROTOBUF_PAYLOAD: { @@ -233,16 +266,57 @@ private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest re } case JSON_PAYLOAD: { try { - TestMessagesProto3.TestAllTypesProto3.Builder builder = - TestMessagesProto3.TestAllTypesProto3.newBuilder(); - JsonFormat.parser().usingTypeRegistry(typeRegistry) - .merge(request.getJsonPayload(), builder); - testMessage = builder.build(); + JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(typeRegistry); + if (request.getTestCategory() + == Conformance.TestCategory.JSON_IGNORE_UNKNOWN_PARSING_TEST) { + parser = parser.ignoringUnknownFields(); + } + if (isProto3) { + TestMessagesProto3.TestAllTypesProto3.Builder builder = + TestMessagesProto3.TestAllTypesProto3.newBuilder(); + parser.merge(request.getJsonPayload(), builder); + testMessage = builder.build(); + } else if (isProto2) { + TestMessagesProto2.TestAllTypesProto2.Builder builder = + TestMessagesProto2.TestAllTypesProto2.newBuilder(); + parser.merge(request.getJsonPayload(), builder); + testMessage = builder.build(); + } else { + throw new RuntimeException("Protobuf request doesn't have specific payload type."); + } } catch (InvalidProtocolBufferException e) { return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build(); } break; } + case TEXT_PAYLOAD: { + if (isProto3) { + try { + TestMessagesProto3.TestAllTypesProto3.Builder builder = + TestMessagesProto3.TestAllTypesProto3.newBuilder(); + TextFormat.merge(request.getTextPayload(), builder); + testMessage = builder.build(); + } catch (TextFormat.ParseException e) { + return Conformance.ConformanceResponse.newBuilder() + .setParseError(e.getMessage()) + .build(); + } + } else if (isProto2) { + try { + TestMessagesProto2.TestAllTypesProto2.Builder builder = + TestMessagesProto2.TestAllTypesProto2.newBuilder(); + TextFormat.merge(request.getTextPayload(), builder); + testMessage = builder.build(); + } catch (TextFormat.ParseException e) { + return Conformance.ConformanceResponse.newBuilder() + .setParseError(e.getMessage()) + .build(); + } + } else { + throw new RuntimeException("Protobuf request doesn't have specific payload type."); + } + break; + } case PAYLOAD_NOT_SET: { throw new RuntimeException("Request didn't have payload."); } @@ -257,7 +331,7 @@ private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest re throw new RuntimeException("Unspecified output format."); case PROTOBUF: { - ByteString MessageString = testMessage.toByteString(); + ByteString MessageString = testMessage.toByteString(); return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(MessageString).build(); } @@ -270,6 +344,10 @@ private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest re e.getMessage()).build(); } + case TEXT_FORMAT: + return Conformance.ConformanceResponse.newBuilder().setTextPayload( + TextFormat.printToString(testMessage)).build(); + default: { throw new RuntimeException("Unexpected request output."); } diff --git a/conformance/ConformanceJavaLite.java b/conformance/ConformanceJavaLite.java index 016f79326fba7..147738dcbeff8 100644 --- a/conformance/ConformanceJavaLite.java +++ b/conformance/ConformanceJavaLite.java @@ -1,3 +1,32 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import com.google.protobuf.conformance.Conformance; import com.google.protobuf.InvalidProtocolBufferException; diff --git a/conformance/Makefile.am b/conformance/Makefile.am index f7ce053bdab46..b281f9cfaa084 100644 --- a/conformance/Makefile.am +++ b/conformance/Makefile.am @@ -5,7 +5,7 @@ conformance_protoc_inputs = \ $(top_srcdir)/src/google/protobuf/test_messages_proto3.proto # proto2 input files, should be separated with proto3, as we -# can't generate proto2 files for ruby, php and objc +# can't generate proto2 files for php. conformance_proto2_protoc_inputs = \ $(top_srcdir)/src/google/protobuf/test_messages_proto2.proto @@ -107,6 +107,7 @@ other_language_protoc_outputs = \ google/protobuf/wrappers_pb2.py \ Conformance/ConformanceRequest.php \ Conformance/ConformanceResponse.php \ + Conformance/FailureSet.php \ Conformance/WireFormat.php \ GPBMetadata/Conformance.php \ GPBMetadata/Google/Protobuf/Any.php \ @@ -206,13 +207,18 @@ EXTRA_DIST = \ conformance_test_runner_LDADD = $(top_srcdir)/src/libprotobuf.la conformance_test_runner_SOURCES = conformance_test.h conformance_test.cc \ + conformance_test_main.cc \ + binary_json_conformance_suite.h \ + binary_json_conformance_suite.cc \ + text_format_conformance_suite.h \ + text_format_conformance_suite.cc \ conformance_test_runner.cc \ third_party/jsoncpp/json.h \ third_party/jsoncpp/jsoncpp.cpp nodist_conformance_test_runner_SOURCES = conformance.pb.cc google/protobuf/test_messages_proto3.pb.cc google/protobuf/test_messages_proto2.pb.cc conformance_test_runner_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir) conformance_test_runner_CXXFLAGS = -std=c++11 -# Explicit deps beacuse BUILT_SOURCES are only done before a "make all/check" +# Explicit deps because BUILT_SOURCES are only done before a "make all/check" # so a direct "make test_cpp" could fail if parallel enough. conformance_test_runner-conformance_test.$(OBJEXT): conformance.pb.h conformance_test_runner-conformance_test_runner.$(OBJEXT): conformance.pb.h @@ -221,7 +227,7 @@ conformance_cpp_LDADD = $(top_srcdir)/src/libprotobuf.la conformance_cpp_SOURCES = conformance_cpp.cc nodist_conformance_cpp_SOURCES = conformance.pb.cc google/protobuf/test_messages_proto3.pb.cc google/protobuf/test_messages_proto2.pb.cc conformance_cpp_CPPFLAGS = -I$(top_srcdir)/src -# Explicit dep beacuse BUILT_SOURCES are only done before a "make all/check" +# Explicit dep because BUILT_SOURCES are only done before a "make all/check" # so a direct "make test_cpp" could fail if parallel enough. conformance_cpp-conformance_cpp.$(OBJEXT): conformance.pb.h @@ -237,7 +243,7 @@ nodist_conformance_objc_SOURCES = Conformance.pbobjc.m google/protobuf/TestMessa # setup for Xcode and old frameworks are being found. conformance_objc_CPPFLAGS = -I$(top_srcdir)/objectivec -isysroot `xcrun --sdk macosx --show-sdk-path` conformance_objc_LDFLAGS = -framework Foundation -# Explicit dep beacuse BUILT_SOURCES are only done before a "make all/check" +# Explicit dep because BUILT_SOURCES are only done before a "make all/check" # so a direct "make test_objc" could fail if parallel enough. conformance_objc-conformance_objc.$(OBJEXT): Conformance.pbobjc.h google/protobuf/TestMessagesProto2.pbobjc.h google/protobuf/TestMessagesProto3.pbobjc.h @@ -255,8 +261,8 @@ if USE_EXTERNAL_PROTOC # Some implementations include pre-generated versions of well-known types. protoc_middleman: $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. --php_out=. --js_out=import_style=commonjs,binary:. $(conformance_protoc_inputs) - $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --objc_out=. --python_out=. --js_out=import_style=commonjs,binary:. $(conformance_proto2_protoc_inputs) - $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --python_out=. --php_out=. --js_out=import_style=commonjs,binary:google-protobuf $(well_known_type_protoc_inputs) + $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. --js_out=import_style=commonjs,binary:. $(conformance_proto2_protoc_inputs) + $(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --python_out=. --js_out=import_style=commonjs,binary:google-protobuf $(well_known_type_protoc_inputs) ## $(PROTOC) -I$(srcdir) -I$(top_srcdir) --java_out=lite:lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) touch protoc_middleman @@ -267,8 +273,8 @@ else # building out-of-tree. protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd --php_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_protoc_inputs) ) - oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --objc_out=. --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_proto2_protoc_inputs) ) - oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --python_out=$$oldpwd --php_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd/google-protobuf $(well_known_type_protoc_inputs) ) + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_proto2_protoc_inputs) ) + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd/google-protobuf $(well_known_type_protoc_inputs) ) ## @mkdir -p lite ## oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --java_out=lite:$$oldpwd/lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) ) touch protoc_middleman @@ -279,8 +285,6 @@ $(protoc_outputs): protoc_middleman $(other_language_protoc_outputs): protoc_middleman -BUILT_SOURCES = $(protoc_outputs) $(other_language_protoc_outputs) - CLEANFILES = $(protoc_outputs) protoc_middleman javac_middleman conformance-java javac_middleman_lite conformance-java-lite conformance-csharp conformance-php conformance-php-c $(other_language_protoc_outputs) MAINTAINERCLEANFILES = \ @@ -312,7 +316,7 @@ conformance-java-lite: javac_middleman_lite conformance-csharp: $(other_language_protoc_outputs) @echo "Writing shortcut script conformance-csharp..." @echo '#! /bin/sh' > conformance-csharp - @echo 'dotnet ../csharp/src/Google.Protobuf.Conformance/bin/Release/netcoreapp1.0/Google.Protobuf.Conformance.dll "$$@"' >> conformance-csharp + @echo 'dotnet ../csharp/src/Google.Protobuf.Conformance/bin/Release/netcoreapp2.1/Google.Protobuf.Conformance.dll "$$@"' >> conformance-csharp @chmod +x conformance-csharp conformance-php: @@ -329,36 +333,50 @@ conformance-php-c: # Targets for actually running tests. test_cpp: protoc_middleman conformance-test-runner conformance-cpp - ./conformance-test-runner --enforce_recommended --failure_list failure_list_cpp.txt ./conformance-cpp + ./conformance-test-runner --enforce_recommended --failure_list failure_list_cpp.txt --text_format_failure_list text_format_failure_list_cpp.txt ./conformance-cpp test_java: protoc_middleman conformance-test-runner conformance-java - ./conformance-test-runner --enforce_recommended --failure_list failure_list_java.txt ./conformance-java + ./conformance-test-runner --enforce_recommended --failure_list failure_list_java.txt --text_format_failure_list text_format_failure_list_java.txt ./conformance-java test_java_lite: protoc_middleman conformance-test-runner conformance-java-lite ./conformance-test-runner --enforce_recommended ./conformance-java-lite test_csharp: protoc_middleman conformance-test-runner conformance-csharp - ./conformance-test-runner --enforce_recommended --failure_list failure_list_csharp.txt ./conformance-csharp + ./conformance-test-runner --enforce_recommended --failure_list failure_list_csharp.txt --text_format_failure_list text_format_failure_list_csharp.txt ./conformance-csharp test_ruby: protoc_middleman conformance-test-runner $(other_language_protoc_outputs) - RUBYLIB=../ruby/lib:. ./conformance-test-runner --enforce_recommended --failure_list failure_list_ruby.txt ./conformance_ruby.rb + RUBYLIB=../ruby/lib:. ./conformance-test-runner --enforce_recommended --failure_list failure_list_ruby.txt --text_format_failure_list text_format_failure_list_ruby.txt ./conformance_ruby.rb + +test_jruby: protoc_middleman conformance-test-runner $(other_language_protoc_outputs) + RUBYLIB=../ruby/lib:. ./conformance-test-runner --enforce_recommended --failure_list failure_list_jruby.txt --text_format_failure_list text_format_failure_list_jruby.txt ./conformance_ruby.rb test_php: protoc_middleman conformance-test-runner conformance-php $(other_language_protoc_outputs) - ./conformance-test-runner --enforce_recommended --failure_list failure_list_php.txt ./conformance-php + ./conformance-test-runner --enforce_recommended --failure_list failure_list_php.txt --text_format_failure_list text_format_failure_list_php.txt ./conformance-php test_php_c: protoc_middleman conformance-test-runner conformance-php-c $(other_language_protoc_outputs) - ./conformance-test-runner --enforce_recommended --failure_list failure_list_php_c.txt ./conformance-php-c - -test_php_zts_c: protoc_middleman conformance-test-runner conformance-php-c $(other_language_protoc_outputs) - ./conformance-test-runner --enforce_recommended --failure_list failure_list_php_zts_c.txt ./conformance-php-c + ./conformance-test-runner --enforce_recommended --failure_list failure_list_php_c.txt --text_format_failure_list text_format_failure_list_php.txt ./conformance-php-c # These depend on library paths being properly set up. The easiest way to # run them is to just use "tox" from the python dir. test_python: protoc_middleman conformance-test-runner - ./conformance-test-runner --enforce_recommended --failure_list failure_list_python.txt ./conformance_python.py + VERSION="$(shell python --version 2>&1)"; \ + if [[ "$$VERSION" == "Python 2.7"* ]]; then \ + echo "Using Python 2.7 failure list."; \ + ./conformance-test-runner --enforce_recommended --failure_list failure_list_python.txt --text_format_failure_list text_format_failure_list_python_2.7.txt ./conformance_python.py; \ + else \ + echo "Using Python >2.7 failure list."; \ + ./conformance-test-runner --enforce_recommended --failure_list failure_list_python.txt --text_format_failure_list text_format_failure_list_python.txt ./conformance_python.py; \ + fi test_python_cpp: protoc_middleman conformance-test-runner - ./conformance-test-runner --enforce_recommended --failure_list failure_list_python_cpp.txt ./conformance_python.py + VERSION="$(shell python --version 2>&1)"; \ + if [[ "$$VERSION" == "Python 2.7"* ]]; then \ + echo "Using Python 2.7 failure list."; \ + ./conformance-test-runner --enforce_recommended --failure_list failure_list_python_cpp.txt --text_format_failure_list text_format_failure_list_python_cpp_2.7.txt ./conformance_python.py; \ + else \ + echo "Using Python >2.7 failure list."; \ + ./conformance-test-runner --enforce_recommended --failure_list failure_list_python_cpp.txt --text_format_failure_list text_format_failure_list_python_cpp.txt ./conformance_python.py; \ + fi test_nodejs: protoc_middleman conformance-test-runner $(other_language_protoc_outputs) NODE_PATH=../js:. ./conformance-test-runner --enforce_recommended --failure_list failure_list_js.txt ./conformance_nodejs.js diff --git a/conformance/README.md b/conformance/README.md index 971fe8f60de35..06925dbb55fe8 100644 --- a/conformance/README.md +++ b/conformance/README.md @@ -1,8 +1,6 @@ Protocol Buffers - Google's data interchange format =================================================== -[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) - Copyright 2008 Google Inc. This directory contains conformance tests for testing completeness and @@ -59,10 +57,10 @@ Testing other Protocol Buffer implementations To run these tests against a new Protocol Buffers implementation, write a program in your language that uses the protobuf implementation you want to test. This program should implement the testing protocol defined in -[conformance.proto](https://github.com/google/protobuf/blob/master/conformance/conformance.proto). +[conformance.proto](https://github.com/protocolbuffers/protobuf/blob/master/conformance/conformance.proto). This is designed to be as easy as possible: the C++ version is only 150 lines and is a good example for what this program should look like -(see [conformance_cpp.cc](https://github.com/google/protobuf/blob/master/conformance/conformance_cpp.cc)). +(see [conformance_cpp.cc](https://github.com/protocolbuffers/protobuf/blob/master/conformance/conformance_cpp.cc)). The program only needs to be able to read from stdin and write to stdout. Portability diff --git a/conformance/autoload.php b/conformance/autoload.php index 2cee31c476b9e..0f49aecb16aed 100644 --- a/conformance/autoload.php +++ b/conformance/autoload.php @@ -2,7 +2,7 @@ define("GOOGLE_INTERNAL_NAMESPACE", "Google\\Protobuf\\Internal\\"); define("GOOGLE_NAMESPACE", "Google\\Protobuf\\"); -define("GOOGLE_GPBMETADATA_NAMESPACE", "GPBMetadata\\Google\\Protobuf\\Internal\\"); +define("GOOGLE_GPBMETADATA_NAMESPACE", "GPBMetadata\\Google\\Protobuf\\"); function protobuf_autoloader_impl($class, $prefix) { $length = strlen($prefix); diff --git a/conformance/binary_json_conformance_suite.cc b/conformance/binary_json_conformance_suite.cc new file mode 100644 index 0000000000000..4a0d8e8480487 --- /dev/null +++ b/conformance/binary_json_conformance_suite.cc @@ -0,0 +1,3258 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "binary_json_conformance_suite.h" + +#include +#include +#include +#include +#include "third_party/jsoncpp/json.h" +#include "conformance_test.h" +#include +#include +#include + +namespace proto2_messages = protobuf_test_messages::proto2; + +using conformance::ConformanceRequest; +using conformance::ConformanceResponse; +using conformance::WireFormat; +using google::protobuf::Descriptor; +using google::protobuf::FieldDescriptor; +using google::protobuf::Message; +using google::protobuf::TextFormat; +using google::protobuf::internal::WireFormatLite; +using google::protobuf::util::NewTypeResolverForDescriptorPool; +using proto2_messages::TestAllTypesProto2; +using protobuf_test_messages::proto3::TestAllTypesProto3; +using std::string; + +namespace { + +static const char kTypeUrlPrefix[] = "type.googleapis.com"; + +static string GetTypeUrl(const Descriptor* message) { + return string(kTypeUrlPrefix) + "/" + message->full_name(); +} + +/* Routines for building arbitrary protos *************************************/ + +// We would use CodedOutputStream except that we want more freedom to build +// arbitrary protos (even invalid ones). + +const string empty; + +string cat(const string& a, const string& b, + const string& c = empty, + const string& d = empty, + const string& e = empty, + const string& f = empty, + const string& g = empty, + const string& h = empty, + const string& i = empty, + const string& j = empty, + const string& k = empty, + const string& l = empty) { + string ret; + ret.reserve(a.size() + b.size() + c.size() + d.size() + e.size() + f.size() + + g.size() + h.size() + i.size() + j.size() + k.size() + l.size()); + ret.append(a); + ret.append(b); + ret.append(c); + ret.append(d); + ret.append(e); + ret.append(f); + ret.append(g); + ret.append(h); + ret.append(i); + ret.append(j); + ret.append(k); + ret.append(l); + return ret; +} + +// The maximum number of bytes that it takes to encode a 64-bit varint. +#define VARINT_MAX_LEN 10 + +size_t vencode64(uint64_t val, int over_encoded_bytes, char *buf) { + if (val == 0) { buf[0] = 0; return 1; } + size_t i = 0; + while (val) { + uint8_t byte = val & 0x7fU; + val >>= 7; + if (val || over_encoded_bytes) byte |= 0x80U; + buf[i++] = byte; + } + while (over_encoded_bytes--) { + assert(i < 10); + uint8_t byte = over_encoded_bytes ? 0x80 : 0; + buf[i++] = byte; + } + return i; +} + +string varint(uint64_t x) { + char buf[VARINT_MAX_LEN]; + size_t len = vencode64(x, 0, buf); + return string(buf, len); +} + +// Encodes a varint that is |extra| bytes longer than it needs to be, but still +// valid. +string longvarint(uint64_t x, int extra) { + char buf[VARINT_MAX_LEN]; + size_t len = vencode64(x, extra, buf); + return string(buf, len); +} + +// TODO: proper byte-swapping for big-endian machines. +string fixed32(void *data) { return string(static_cast(data), 4); } +string fixed64(void *data) { return string(static_cast(data), 8); } + +string delim(const string& buf) { return cat(varint(buf.size()), buf); } +string u32(uint32_t u32) { return fixed32(&u32); } +string u64(uint64_t u64) { return fixed64(&u64); } +string flt(float f) { return fixed32(&f); } +string dbl(double d) { return fixed64(&d); } +string zz32(int32_t x) { return varint(WireFormatLite::ZigZagEncode32(x)); } +string zz64(int64_t x) { return varint(WireFormatLite::ZigZagEncode64(x)); } + +string tag(uint32_t fieldnum, char wire_type) { + return varint((fieldnum << 3) | wire_type); +} + +string GetDefaultValue(FieldDescriptor::Type type) { + switch (type) { + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_ENUM: + case FieldDescriptor::TYPE_BOOL: + return varint(0); + case FieldDescriptor::TYPE_SINT32: + return zz32(0); + case FieldDescriptor::TYPE_SINT64: + return zz64(0); + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_SFIXED32: + return u32(0); + case FieldDescriptor::TYPE_FIXED64: + case FieldDescriptor::TYPE_SFIXED64: + return u64(0); + case FieldDescriptor::TYPE_FLOAT: + return flt(0); + case FieldDescriptor::TYPE_DOUBLE: + return dbl(0); + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_BYTES: + case FieldDescriptor::TYPE_MESSAGE: + return delim(""); + default: + return ""; + } + return ""; +} + +string GetNonDefaultValue(FieldDescriptor::Type type) { + switch (type) { + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_ENUM: + case FieldDescriptor::TYPE_BOOL: + return varint(1); + case FieldDescriptor::TYPE_SINT32: + return zz32(1); + case FieldDescriptor::TYPE_SINT64: + return zz64(1); + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_SFIXED32: + return u32(1); + case FieldDescriptor::TYPE_FIXED64: + case FieldDescriptor::TYPE_SFIXED64: + return u64(1); + case FieldDescriptor::TYPE_FLOAT: + return flt(1); + case FieldDescriptor::TYPE_DOUBLE: + return dbl(1); + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_BYTES: + return delim("a"); + case FieldDescriptor::TYPE_MESSAGE: + return delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234))); + default: + return ""; + } + return ""; +} + +#define UNKNOWN_FIELD 666 + +enum class Packed { + UNSPECIFIED = 0, + TRUE = 1, + FALSE = 2, +}; + +const FieldDescriptor* GetFieldForType(FieldDescriptor::Type type, + bool repeated, bool is_proto3, + Packed packed = Packed::UNSPECIFIED) { + const Descriptor* d = is_proto3 ? + TestAllTypesProto3().GetDescriptor() : TestAllTypesProto2().GetDescriptor(); + for (int i = 0; i < d->field_count(); i++) { + const FieldDescriptor* f = d->field(i); + if (f->type() == type && f->is_repeated() == repeated) { + if ((packed == Packed::TRUE && !f->is_packed()) || + (packed == Packed::FALSE && f->is_packed())) { + continue; + } + return f; + } + } + + string packed_string = ""; + const string repeated_string = repeated ? "Repeated " : "Singular "; + const string proto_string = is_proto3 ? "Proto3" : "Proto2"; + if (packed == Packed::TRUE) { + packed_string = "Packed "; + } + if (packed == Packed::FALSE) { + packed_string = "Unpacked "; + } + GOOGLE_LOG(FATAL) << "Couldn't find field with type: " << repeated_string.c_str() + << packed_string.c_str() << FieldDescriptor::TypeName(type) + << " for " << proto_string.c_str(); + return nullptr; +} + +const FieldDescriptor* GetFieldForMapType(FieldDescriptor::Type key_type, + FieldDescriptor::Type value_type, + bool is_proto3) { + const Descriptor* d = is_proto3 ? TestAllTypesProto3().GetDescriptor() + : TestAllTypesProto2().GetDescriptor(); + for (int i = 0; i < d->field_count(); i++) { + const FieldDescriptor* f = d->field(i); + if (f->is_map()) { + const Descriptor* map_entry = f->message_type(); + const FieldDescriptor* key = map_entry->field(0); + const FieldDescriptor* value = map_entry->field(1); + if (key->type() == key_type && value->type() == value_type) { + return f; + } + } + } + + const string proto_string = is_proto3 ? "Proto3" : "Proto2"; + GOOGLE_LOG(FATAL) << "Couldn't find map field with type: " + << FieldDescriptor::TypeName(key_type) << " and " + << FieldDescriptor::TypeName(key_type) << " for " + << proto_string.c_str(); + return nullptr; +} + +const FieldDescriptor* GetFieldForOneofType(FieldDescriptor::Type type, + bool is_proto3, + bool exclusive = false) { + const Descriptor* d = is_proto3 ? TestAllTypesProto3().GetDescriptor() + : TestAllTypesProto2().GetDescriptor(); + for (int i = 0; i < d->field_count(); i++) { + const FieldDescriptor* f = d->field(i); + if (f->containing_oneof() && ((f->type() == type) ^ exclusive)) { + return f; + } + } + + const string proto_string = is_proto3 ? "Proto3" : "Proto2"; + GOOGLE_LOG(FATAL) << "Couldn't find oneof field with type: " + << FieldDescriptor::TypeName(type) << " for " + << proto_string.c_str(); + return nullptr; +} + +string UpperCase(string str) { + for (int i = 0; i < str.size(); i++) { + str[i] = toupper(str[i]); + } + return str; +} + +std::unique_ptr NewTestMessage(bool is_proto3) { + std::unique_ptr prototype; + if (is_proto3) { + prototype.reset(new TestAllTypesProto3()); + } else { + prototype.reset(new TestAllTypesProto2()); + } + return prototype; +} + +bool IsProto3Default(FieldDescriptor::Type type, const string& binary_data) { + switch (type) { + case FieldDescriptor::TYPE_DOUBLE: + return binary_data == dbl(0); + case FieldDescriptor::TYPE_FLOAT: + return binary_data == flt(0); + case FieldDescriptor::TYPE_BOOL: + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_SINT64: + case FieldDescriptor::TYPE_ENUM: + return binary_data == varint(0); + case FieldDescriptor::TYPE_FIXED64: + case FieldDescriptor::TYPE_SFIXED64: + return binary_data == u64(0); + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_SFIXED32: + return binary_data == u32(0); + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_BYTES: + return binary_data == delim(""); + default: + return false; + } +} + +} // anonymous namespace + +namespace google { +namespace protobuf { + +bool BinaryAndJsonConformanceSuite::ParseJsonResponse( + const ConformanceResponse& response, + Message* test_message) { + string binary_protobuf; + util::Status status = + JsonToBinaryString(type_resolver_.get(), type_url_, + response.json_payload(), &binary_protobuf); + + if (!status.ok()) { + return false; + } + + if (!test_message->ParseFromString(binary_protobuf)) { + GOOGLE_LOG(FATAL) << "INTERNAL ERROR: internal JSON->protobuf transcode " + << "yielded unparseable proto."; + return false; + } + + return true; +} + +bool BinaryAndJsonConformanceSuite::ParseResponse( + const ConformanceResponse& response, + const ConformanceRequestSetting& setting, + Message* test_message) { + const ConformanceRequest& request = setting.GetRequest(); + WireFormat requested_output = request.requested_output_format(); + const string& test_name = setting.GetTestName(); + ConformanceLevel level = setting.GetLevel(); + + switch (response.result_case()) { + case ConformanceResponse::kProtobufPayload: { + if (requested_output != conformance::PROTOBUF) { + ReportFailure(test_name, level, request, response, + StrCat("Test was asked for ", + WireFormatToString(requested_output), + " output but provided PROTOBUF instead.") + .c_str()); + return false; + } + + if (!test_message->ParseFromString(response.protobuf_payload())) { + ReportFailure(test_name, level, request, response, + "Protobuf output we received from test was unparseable."); + return false; + } + + break; + } + + case ConformanceResponse::kJsonPayload: { + if (requested_output != conformance::JSON) { + ReportFailure(test_name, level, request, response, + StrCat("Test was asked for ", + WireFormatToString(requested_output), + " output but provided JSON instead.") + .c_str()); + return false; + } + + if (!ParseJsonResponse(response, test_message)) { + ReportFailure(test_name, level, request, response, + "JSON output we received from test was unparseable."); + return false; + } + + break; + } + + default: + GOOGLE_LOG(FATAL) << test_name + << ": unknown payload type: " << response.result_case(); + } + + return true; +} + +void BinaryAndJsonConformanceSuite::ExpectParseFailureForProtoWithProtoVersion ( + const string& proto, const string& test_name, ConformanceLevel level, + bool is_proto3) { + std::unique_ptr prototype = NewTestMessage(is_proto3); + // We don't expect output, but if the program erroneously accepts the protobuf + // we let it send its response as this. We must not leave it unspecified. + ConformanceRequestSetting setting( + level, conformance::PROTOBUF, conformance::PROTOBUF, + conformance::BINARY_TEST, + *prototype, test_name, proto); + + const ConformanceRequest& request = setting.GetRequest(); + ConformanceResponse response; + string effective_test_name = StrCat( + setting.ConformanceLevelToString(level), + (is_proto3 ? ".Proto3" : ".Proto2"), ".ProtobufInput.", test_name); + + RunTest(effective_test_name, request, &response); + if (response.result_case() == ConformanceResponse::kParseError) { + ReportSuccess(effective_test_name); + } else if (response.result_case() == ConformanceResponse::kSkipped) { + ReportSkip(effective_test_name, request, response); + } else { + ReportFailure(effective_test_name, level, request, response, + "Should have failed to parse, but didn't."); + } +} + +// Expect that this precise protobuf will cause a parse error. +void BinaryAndJsonConformanceSuite::ExpectParseFailureForProto( + const string& proto, const string& test_name, ConformanceLevel level) { + ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level, true); + ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level, false); +} + +// Expect that this protobuf will cause a parse error, even if it is followed +// by valid protobuf data. We can try running this twice: once with this +// data verbatim and once with this data followed by some valid data. +// +// TODO(haberman): implement the second of these. +void BinaryAndJsonConformanceSuite::ExpectHardParseFailureForProto( + const string& proto, const string& test_name, ConformanceLevel level) { + return ExpectParseFailureForProto(proto, test_name, level); +} + +void BinaryAndJsonConformanceSuite::RunValidJsonTest( + const string& test_name, ConformanceLevel level, const string& input_json, + const string& equivalent_text_format) { + TestAllTypesProto3 prototype; + ConformanceRequestSetting setting1( + level, conformance::JSON, conformance::PROTOBUF, + conformance::JSON_TEST, + prototype, test_name, input_json); + RunValidInputTest(setting1, equivalent_text_format); + ConformanceRequestSetting setting2( + level, conformance::JSON, conformance::JSON, + conformance::JSON_TEST, + prototype, test_name, input_json); + RunValidInputTest(setting2, equivalent_text_format); +} + +void BinaryAndJsonConformanceSuite::RunValidJsonTestWithProtobufInput( + const string& test_name, ConformanceLevel level, const TestAllTypesProto3& input, + const string& equivalent_text_format) { + ConformanceRequestSetting setting( + level, conformance::PROTOBUF, conformance::JSON, + conformance::JSON_TEST, + input, test_name, input.SerializeAsString()); + RunValidInputTest(setting, equivalent_text_format); +} + +void BinaryAndJsonConformanceSuite::RunValidJsonIgnoreUnknownTest( + const string& test_name, ConformanceLevel level, const string& input_json, + const string& equivalent_text_format) { + TestAllTypesProto3 prototype; + ConformanceRequestSetting setting( + level, conformance::JSON, conformance::PROTOBUF, + conformance::JSON_IGNORE_UNKNOWN_PARSING_TEST, + prototype, test_name, input_json); + RunValidInputTest(setting, equivalent_text_format); +} + +void BinaryAndJsonConformanceSuite::RunValidProtobufTest( + const string& test_name, ConformanceLevel level, + const string& input_protobuf, const string& equivalent_text_format, + bool is_proto3) { + std::unique_ptr prototype = NewTestMessage(is_proto3); + + ConformanceRequestSetting setting1( + level, conformance::PROTOBUF, conformance::PROTOBUF, + conformance::BINARY_TEST, + *prototype, test_name, input_protobuf); + RunValidInputTest(setting1, equivalent_text_format); + + if (is_proto3) { + ConformanceRequestSetting setting2( + level, conformance::PROTOBUF, conformance::JSON, + conformance::BINARY_TEST, + *prototype, test_name, input_protobuf); + RunValidInputTest(setting2, equivalent_text_format); + } +} + +void BinaryAndJsonConformanceSuite::RunValidBinaryProtobufTest( + const string& test_name, ConformanceLevel level, + const string& input_protobuf, bool is_proto3) { + RunValidBinaryProtobufTest(test_name, level, input_protobuf, input_protobuf, + is_proto3); +} + +void BinaryAndJsonConformanceSuite::RunValidBinaryProtobufTest( + const string& test_name, ConformanceLevel level, + const string& input_protobuf, const string& expected_protobuf, + bool is_proto3) { + std::unique_ptr prototype = NewTestMessage(is_proto3); + ConformanceRequestSetting setting( + level, conformance::PROTOBUF, conformance::PROTOBUF, + conformance::BINARY_TEST, + *prototype, test_name, input_protobuf); + RunValidBinaryInputTest(setting, expected_protobuf, true); +} + +void BinaryAndJsonConformanceSuite::RunValidProtobufTestWithMessage( + const string& test_name, ConformanceLevel level, const Message *input, + const string& equivalent_text_format, bool is_proto3) { + RunValidProtobufTest(test_name, level, input->SerializeAsString(), + equivalent_text_format, is_proto3); +} + +// According to proto JSON specification, JSON serializers follow more strict +// rules than parsers (e.g., a serializer must serialize int32 values as JSON +// numbers while the parser is allowed to accept them as JSON strings). This +// method allows strict checking on a proto JSON serializer by inspecting +// the JSON output directly. +void BinaryAndJsonConformanceSuite::RunValidJsonTestWithValidator( + const string& test_name, ConformanceLevel level, const string& input_json, + const Validator& validator, bool is_proto3) { + std::unique_ptr prototype = NewTestMessage(is_proto3); + ConformanceRequestSetting setting(level, conformance::JSON, conformance::JSON, + conformance::JSON_TEST, *prototype, + test_name, input_json); + const ConformanceRequest& request = setting.GetRequest(); + ConformanceResponse response; + string effective_test_name = + StrCat(setting.ConformanceLevelToString(level), + is_proto3 ? ".Proto3.JsonInput." : ".Proto2.JsonInput.", + test_name, ".Validator"); + + RunTest(effective_test_name, request, &response); + + if (response.result_case() == ConformanceResponse::kSkipped) { + ReportSkip(effective_test_name, request, response); + return; + } + + if (response.result_case() != ConformanceResponse::kJsonPayload) { + ReportFailure(effective_test_name, level, request, response, + "Expected JSON payload but got type %d.", + response.result_case()); + return; + } + Json::Reader reader; + Json::Value value; + if (!reader.parse(response.json_payload(), value)) { + ReportFailure(effective_test_name, level, request, response, + "JSON payload cannot be parsed as valid JSON: %s", + reader.getFormattedErrorMessages().c_str()); + return; + } + if (!validator(value)) { + ReportFailure(effective_test_name, level, request, response, + "JSON payload validation failed."); + return; + } + ReportSuccess(effective_test_name); +} + +void BinaryAndJsonConformanceSuite::ExpectParseFailureForJson( + const string& test_name, ConformanceLevel level, const string& input_json) { + TestAllTypesProto3 prototype; + // We don't expect output, but if the program erroneously accepts the protobuf + // we let it send its response as this. We must not leave it unspecified. + ConformanceRequestSetting setting( + level, conformance::JSON, conformance::JSON, + conformance::JSON_TEST, + prototype, test_name, input_json); + const ConformanceRequest& request = setting.GetRequest(); + ConformanceResponse response; + string effective_test_name = StrCat( + setting.ConformanceLevelToString(level), ".Proto3.JsonInput.", test_name); + + RunTest(effective_test_name, request, &response); + if (response.result_case() == ConformanceResponse::kParseError) { + ReportSuccess(effective_test_name); + } else if (response.result_case() == ConformanceResponse::kSkipped) { + ReportSkip(effective_test_name, request, response); + } else { + ReportFailure(effective_test_name, level, request, response, + "Should have failed to parse, but didn't."); + } +} + +void BinaryAndJsonConformanceSuite::ExpectSerializeFailureForJson( + const string& test_name, ConformanceLevel level, const string& text_format) { + TestAllTypesProto3 payload_message; + GOOGLE_CHECK(TextFormat::ParseFromString(text_format, &payload_message)) + << "Failed to parse: " << text_format; + + TestAllTypesProto3 prototype; + ConformanceRequestSetting setting( + level, conformance::PROTOBUF, conformance::JSON, + conformance::JSON_TEST, + prototype, test_name, payload_message.SerializeAsString()); + const ConformanceRequest& request = setting.GetRequest(); + ConformanceResponse response; + string effective_test_name = StrCat( + setting.ConformanceLevelToString(level), ".", test_name, ".JsonOutput"); + + RunTest(effective_test_name, request, &response); + if (response.result_case() == ConformanceResponse::kSerializeError) { + ReportSuccess(effective_test_name); + } else if (response.result_case() == ConformanceResponse::kSkipped) { + ReportSkip(effective_test_name, request, response); + } else { + ReportFailure(effective_test_name, level, request, response, + "Should have failed to serialize, but didn't."); + } +} + +void BinaryAndJsonConformanceSuite::TestPrematureEOFForType( + FieldDescriptor::Type type) { + // Incomplete values for each wire type. + static const string incompletes[6] = { + string("\x80"), // VARINT + string("abcdefg"), // 64BIT + string("\x80"), // DELIMITED (partial length) + string(), // START_GROUP (no value required) + string(), // END_GROUP (no value required) + string("abc") // 32BIT + }; + + const FieldDescriptor* field = GetFieldForType(type, false, true); + const FieldDescriptor* rep_field = GetFieldForType(type, true, true); + WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( + static_cast(type)); + const string& incomplete = incompletes[wire_type]; + const string type_name = + UpperCase(string(".") + FieldDescriptor::TypeName(type)); + + ExpectParseFailureForProto( + tag(field->number(), wire_type), + "PrematureEofBeforeKnownNonRepeatedValue" + type_name, REQUIRED); + + ExpectParseFailureForProto( + tag(rep_field->number(), wire_type), + "PrematureEofBeforeKnownRepeatedValue" + type_name, REQUIRED); + + ExpectParseFailureForProto( + tag(UNKNOWN_FIELD, wire_type), + "PrematureEofBeforeUnknownValue" + type_name, REQUIRED); + + ExpectParseFailureForProto( + cat( tag(field->number(), wire_type), incomplete ), + "PrematureEofInsideKnownNonRepeatedValue" + type_name, REQUIRED); + + ExpectParseFailureForProto( + cat( tag(rep_field->number(), wire_type), incomplete ), + "PrematureEofInsideKnownRepeatedValue" + type_name, REQUIRED); + + ExpectParseFailureForProto( + cat( tag(UNKNOWN_FIELD, wire_type), incomplete ), + "PrematureEofInsideUnknownValue" + type_name, REQUIRED); + + if (wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + ExpectParseFailureForProto( + cat( tag(field->number(), wire_type), varint(1) ), + "PrematureEofInDelimitedDataForKnownNonRepeatedValue" + type_name, + REQUIRED); + + ExpectParseFailureForProto( + cat( tag(rep_field->number(), wire_type), varint(1) ), + "PrematureEofInDelimitedDataForKnownRepeatedValue" + type_name, + REQUIRED); + + // EOF in the middle of delimited data for unknown value. + ExpectParseFailureForProto( + cat( tag(UNKNOWN_FIELD, wire_type), varint(1) ), + "PrematureEofInDelimitedDataForUnknownValue" + type_name, REQUIRED); + + if (type == FieldDescriptor::TYPE_MESSAGE) { + // Submessage ends in the middle of a value. + string incomplete_submsg = + cat( tag(WireFormatLite::TYPE_INT32, WireFormatLite::WIRETYPE_VARINT), + incompletes[WireFormatLite::WIRETYPE_VARINT] ); + ExpectHardParseFailureForProto( + cat( tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + varint(incomplete_submsg.size()), + incomplete_submsg ), + "PrematureEofInSubmessageValue" + type_name, REQUIRED); + } + } else if (type != FieldDescriptor::TYPE_GROUP) { + // Non-delimited, non-group: eligible for packing. + + // Packed region ends in the middle of a value. + ExpectHardParseFailureForProto( + cat(tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + varint(incomplete.size()), incomplete), + "PrematureEofInPackedFieldValue" + type_name, REQUIRED); + + // EOF in the middle of packed region. + ExpectParseFailureForProto( + cat(tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + varint(1)), + "PrematureEofInPackedField" + type_name, REQUIRED); + } +} + +void BinaryAndJsonConformanceSuite::TestValidDataForType( + FieldDescriptor::Type type, + std::vector> values) { + for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { + const string type_name = + UpperCase(string(".") + FieldDescriptor::TypeName(type)); + WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( + static_cast(type)); + const FieldDescriptor* field = GetFieldForType(type, false, is_proto3); + const FieldDescriptor* rep_field = GetFieldForType(type, true, is_proto3); + + // Test singular data for singular fields. + for (size_t i = 0; i < values.size(); i++) { + string proto = cat(tag(field->number(), wire_type), values[i].first); + // In proto3, default primitive fields should not be encoded. + string expected_proto = + is_proto3 && IsProto3Default(field->type(), values[i].second) + ? "" + : cat(tag(field->number(), wire_type), values[i].second); + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(expected_proto); + string text = test_message->DebugString(); + + RunValidProtobufTest( + StrCat("ValidDataScalar", type_name, "[", i, "]"), REQUIRED, + proto, text, is_proto3); + RunValidBinaryProtobufTest( + StrCat("ValidDataScalarBinary", type_name, "[", i, "]"), + RECOMMENDED, proto, expected_proto, is_proto3); + } + + // Test repeated data for singular fields. + // For scalar message fields, repeated values are merged, which is tested + // separately. + if (type != FieldDescriptor::TYPE_MESSAGE) { + string proto; + for (size_t i = 0; i < values.size(); i++) { + proto += cat(tag(field->number(), wire_type), values[i].first); + } + string expected_proto = + cat(tag(field->number(), wire_type), values.back().second); + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(expected_proto); + string text = test_message->DebugString(); + + RunValidProtobufTest("RepeatedScalarSelectsLast" + type_name, REQUIRED, + proto, text, is_proto3); + } + + // Test repeated fields. + if (FieldDescriptor::IsTypePackable(type)) { + const FieldDescriptor* packed_field = + GetFieldForType(type, true, is_proto3, Packed::TRUE); + const FieldDescriptor* unpacked_field = + GetFieldForType(type, true, is_proto3, Packed::FALSE); + + string default_proto_packed; + string default_proto_unpacked; + string default_proto_packed_expected; + string default_proto_unpacked_expected; + string packed_proto_packed; + string packed_proto_unpacked; + string packed_proto_expected; + string unpacked_proto_packed; + string unpacked_proto_unpacked; + string unpacked_proto_expected; + + for (size_t i = 0; i < values.size(); i++) { + default_proto_unpacked += + cat(tag(rep_field->number(), wire_type), values[i].first); + default_proto_unpacked_expected += + cat(tag(rep_field->number(), wire_type), values[i].second); + default_proto_packed += values[i].first; + default_proto_packed_expected += values[i].second; + packed_proto_unpacked += + cat(tag(packed_field->number(), wire_type), values[i].first); + packed_proto_packed += values[i].first; + packed_proto_expected += values[i].second; + unpacked_proto_unpacked += + cat(tag(unpacked_field->number(), wire_type), values[i].first); + unpacked_proto_packed += values[i].first; + unpacked_proto_expected += + cat(tag(unpacked_field->number(), wire_type), values[i].second); + } + default_proto_packed = cat( + tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(default_proto_packed)); + default_proto_packed_expected = cat( + tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(default_proto_packed_expected)); + packed_proto_packed = cat(tag(packed_field->number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(packed_proto_packed)); + packed_proto_expected = + cat(tag(packed_field->number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(packed_proto_expected)); + unpacked_proto_packed = + cat(tag(unpacked_field->number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(unpacked_proto_packed)); + + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(default_proto_packed_expected); + string text = test_message->DebugString(); + + // Ensures both packed and unpacked data can be parsed. + RunValidProtobufTest( + StrCat("ValidDataRepeated", type_name, ".UnpackedInput"), + REQUIRED, default_proto_unpacked, text, is_proto3); + RunValidProtobufTest( + StrCat("ValidDataRepeated", type_name, ".PackedInput"), + REQUIRED, default_proto_packed, text, is_proto3); + + // proto2 should encode as unpacked by default and proto3 should encode as + // packed by default. + string expected_proto = rep_field->is_packed() + ? default_proto_packed_expected + : default_proto_unpacked_expected; + RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name, + ".UnpackedInput.DefaultOutput"), + RECOMMENDED, default_proto_unpacked, + expected_proto, is_proto3); + RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name, + ".PackedInput.DefaultOutput"), + RECOMMENDED, default_proto_packed, + expected_proto, is_proto3); + RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name, + ".UnpackedInput.PackedOutput"), + RECOMMENDED, packed_proto_unpacked, + packed_proto_expected, is_proto3); + RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name, + ".PackedInput.PackedOutput"), + RECOMMENDED, packed_proto_packed, + packed_proto_expected, is_proto3); + RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name, + ".UnpackedInput.UnpackedOutput"), + RECOMMENDED, unpacked_proto_unpacked, + unpacked_proto_expected, is_proto3); + RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name, + ".PackedInput.UnpackedOutput"), + RECOMMENDED, unpacked_proto_packed, + unpacked_proto_expected, is_proto3); + } else { + string proto; + string expected_proto; + for (size_t i = 0; i < values.size(); i++) { + proto += cat(tag(rep_field->number(), wire_type), values[i].first); + expected_proto += + cat(tag(rep_field->number(), wire_type), values[i].second); + } + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(expected_proto); + string text = test_message->DebugString(); + + RunValidProtobufTest(StrCat("ValidDataRepeated", type_name), + REQUIRED, proto, text, is_proto3); + } + } +} + +void BinaryAndJsonConformanceSuite::TestValidDataForRepeatedScalarMessage() { + std::vector values = { + delim(cat( + tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234), + tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1234), + tag(31, WireFormatLite::WIRETYPE_VARINT), varint(1234))))), + delim(cat( + tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(4321), + tag(3, WireFormatLite::WIRETYPE_VARINT), varint(4321), + tag(31, WireFormatLite::WIRETYPE_VARINT), varint(4321))))), + }; + + const std::string expected = + R"({ + corecursive: { + optional_int32: 4321, + optional_int64: 1234, + optional_uint32: 4321, + repeated_int32: [1234, 4321], + } + })"; + + for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { + string proto; + const FieldDescriptor* field = + GetFieldForType(FieldDescriptor::TYPE_MESSAGE, false, is_proto3); + for (size_t i = 0; i < values.size(); i++) { + proto += + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + values[i]); + } + + RunValidProtobufTest("RepeatedScalarMessageMerge", REQUIRED, proto, + field->name() + ": " + expected, is_proto3); + } +} + +void BinaryAndJsonConformanceSuite::TestValidDataForMapType( + FieldDescriptor::Type key_type, FieldDescriptor::Type value_type) { + const string key_type_name = + UpperCase(string(".") + FieldDescriptor::TypeName(key_type)); + const string value_type_name = + UpperCase(string(".") + FieldDescriptor::TypeName(value_type)); + WireFormatLite::WireType key_wire_type = WireFormatLite::WireTypeForFieldType( + static_cast(key_type)); + WireFormatLite::WireType value_wire_type = + WireFormatLite::WireTypeForFieldType( + static_cast(value_type)); + + string key1_data = cat(tag(1, key_wire_type), GetDefaultValue(key_type)); + string value1_data = + cat(tag(2, value_wire_type), GetDefaultValue(value_type)); + string key2_data = cat(tag(1, key_wire_type), GetNonDefaultValue(key_type)); + string value2_data = + cat(tag(2, value_wire_type), GetNonDefaultValue(value_type)); + + for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { + const FieldDescriptor* field = + GetFieldForMapType(key_type, value_type, is_proto3); + + { + // Tests map with default key and value. + string proto = + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(key1_data, value1_data))); + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(proto); + string text = test_message->DebugString(); + RunValidProtobufTest(StrCat("ValidDataMap", key_type_name, + value_type_name, ".Default"), + REQUIRED, proto, text, is_proto3); + } + + { + // Tests map with missing default key and value. + string proto = + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim("")); + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(proto); + string text = test_message->DebugString(); + RunValidProtobufTest(StrCat("ValidDataMap", key_type_name, + value_type_name, ".MissingDefault"), + REQUIRED, proto, text, is_proto3); + } + + { + // Tests map with non-default key and value. + string proto = + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(key2_data, value2_data))); + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(proto); + string text = test_message->DebugString(); + RunValidProtobufTest(StrCat("ValidDataMap", key_type_name, + value_type_name, ".NonDefault"), + REQUIRED, proto, text, is_proto3); + } + + { + // Tests map with unordered key and value. + string proto = + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(value2_data, key2_data))); + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(proto); + string text = test_message->DebugString(); + RunValidProtobufTest(StrCat("ValidDataMap", key_type_name, + value_type_name, ".Unordered"), + REQUIRED, proto, text, is_proto3); + } + + { + // Tests map with duplicate key. + string proto1 = + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(key2_data, value1_data))); + string proto2 = + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(key2_data, value2_data))); + string proto = cat(proto1, proto2); + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(proto2); + string text = test_message->DebugString(); + RunValidProtobufTest(StrCat("ValidDataMap", key_type_name, + value_type_name, ".DuplicateKey"), + REQUIRED, proto, text, is_proto3); + } + + { + // Tests map with duplicate key in map entry. + string proto = + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(key1_data, key2_data, value2_data))); + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(proto); + string text = test_message->DebugString(); + RunValidProtobufTest( + StrCat("ValidDataMap", key_type_name, value_type_name, + ".DuplicateKeyInMapEntry"), + REQUIRED, proto, text, is_proto3); + } + + { + // Tests map with duplicate value in map entry. + string proto = + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(key2_data, value1_data, value2_data))); + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(proto); + string text = test_message->DebugString(); + RunValidProtobufTest( + StrCat("ValidDataMap", key_type_name, value_type_name, + ".DuplicateValueInMapEntry"), + REQUIRED, proto, text, is_proto3); + } + } +} + +void BinaryAndJsonConformanceSuite::TestOverwriteMessageValueMap() { + string key_data = + cat(tag(1, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), delim("")); + string field1_data = cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1)); + string field2_data = cat(tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1)); + string field31_data = + cat(tag(31, WireFormatLite::WIRETYPE_VARINT), varint(1)); + string submsg1_data = delim(cat(field1_data, field31_data)); + string submsg2_data = delim(cat(field2_data, field31_data)); + string value1_data = + cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + submsg1_data))); + string value2_data = + cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + submsg2_data))); + + for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { + const FieldDescriptor* field = GetFieldForMapType( + FieldDescriptor::TYPE_STRING, FieldDescriptor::TYPE_MESSAGE, is_proto3); + + string proto1 = + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(key_data, value1_data))); + string proto2 = + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(key_data, value2_data))); + string proto = cat(proto1, proto2); + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(proto2); + string text = test_message->DebugString(); + RunValidProtobufTest("ValidDataMap.STRING.MESSAGE.MergeValue", REQUIRED, + proto, text, is_proto3); + } +} + +void BinaryAndJsonConformanceSuite::TestValidDataForOneofType( + FieldDescriptor::Type type) { + const string type_name = + UpperCase(string(".") + FieldDescriptor::TypeName(type)); + WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( + static_cast(type)); + + for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { + const FieldDescriptor* field = GetFieldForOneofType(type, is_proto3); + const string default_value = + cat(tag(field->number(), wire_type), GetDefaultValue(type)); + const string non_default_value = + cat(tag(field->number(), wire_type), GetNonDefaultValue(type)); + + { + // Tests oneof with default value. + const string proto = default_value; + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(proto); + string text = test_message->DebugString(); + + RunValidProtobufTest( + StrCat("ValidDataOneof", type_name, ".DefaultValue"), REQUIRED, + proto, text, is_proto3); + RunValidBinaryProtobufTest( + StrCat("ValidDataOneofBinary", type_name, ".DefaultValue"), + RECOMMENDED, proto, proto, is_proto3); + } + + { + // Tests oneof with non-default value. + const string proto = non_default_value; + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(proto); + string text = test_message->DebugString(); + + RunValidProtobufTest( + StrCat("ValidDataOneof", type_name, ".NonDefaultValue"), + REQUIRED, proto, text, is_proto3); + RunValidBinaryProtobufTest( + StrCat("ValidDataOneofBinary", type_name, ".NonDefaultValue"), + RECOMMENDED, proto, proto, is_proto3); + } + + { + // Tests oneof with multiple values of the same field. + const string proto = StrCat(default_value, non_default_value); + const string expected_proto = non_default_value; + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(expected_proto); + string text = test_message->DebugString(); + + RunValidProtobufTest(StrCat("ValidDataOneof", type_name, + ".MultipleValuesForSameField"), + REQUIRED, proto, text, is_proto3); + RunValidBinaryProtobufTest(StrCat("ValidDataOneofBinary", type_name, + ".MultipleValuesForSameField"), + RECOMMENDED, proto, expected_proto, is_proto3); + } + + { + // Tests oneof with multiple values of the different fields. + const FieldDescriptor* other_field = + GetFieldForOneofType(type, is_proto3, true); + FieldDescriptor::Type other_type = other_field->type(); + WireFormatLite::WireType other_wire_type = + WireFormatLite::WireTypeForFieldType( + static_cast(other_type)); + const string other_value = + cat(tag(other_field->number(), other_wire_type), + GetDefaultValue(other_type)); + + const string proto = StrCat(other_value, non_default_value); + const string expected_proto = non_default_value; + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(expected_proto); + string text = test_message->DebugString(); + + RunValidProtobufTest(StrCat("ValidDataOneof", type_name, + ".MultipleValuesForDifferentField"), + REQUIRED, proto, text, is_proto3); + RunValidBinaryProtobufTest( + StrCat("ValidDataOneofBinary", type_name, + ".MultipleValuesForDifferentField"), + RECOMMENDED, proto, expected_proto, is_proto3); + } + } +} + +void BinaryAndJsonConformanceSuite::TestMergeOneofMessage() { + string field1_data = cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1)); + string field2a_data = cat(tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1)); + string field2b_data = cat(tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1)); + string field89_data = + cat(tag(89, WireFormatLite::WIRETYPE_VARINT), varint(1)); + string submsg1_data = + cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(field1_data, field2a_data, field89_data))); + string submsg2_data = cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(field2b_data, field89_data))); + string merged_data = + cat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(cat(field1_data, field2b_data, field89_data, field89_data))); + + for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { + const FieldDescriptor* field = + GetFieldForOneofType(FieldDescriptor::TYPE_MESSAGE, is_proto3); + + string proto1 = + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(submsg1_data)); + string proto2 = + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(submsg2_data)); + string proto = cat(proto1, proto2); + string expected_proto = + cat(tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(merged_data)); + + std::unique_ptr test_message = NewTestMessage(is_proto3); + test_message->MergeFromString(expected_proto); + string text = test_message->DebugString(); + RunValidProtobufTest("ValidDataOneof.MESSAGE.Merge", REQUIRED, proto, text, + is_proto3); + RunValidBinaryProtobufTest("ValidDataOneofBinary.MESSAGE.Merge", + RECOMMENDED, proto, expected_proto, is_proto3); + } +} + +void BinaryAndJsonConformanceSuite::TestIllegalTags() { + // field num 0 is illegal + string nullfield[] = { + "\1DEADBEEF", + "\2\1\1", + "\3\4", + "\5DEAD" + }; + for (int i = 0; i < 4; i++) { + string name = "IllegalZeroFieldNum_Case_0"; + name.back() += i; + ExpectParseFailureForProto(nullfield[i], name, REQUIRED); + } +} +template +void BinaryAndJsonConformanceSuite::TestOneofMessage ( + MessageType &message, bool is_proto3) { + message.set_oneof_uint32(0); + RunValidProtobufTestWithMessage( + "OneofZeroUint32", RECOMMENDED, &message, "oneof_uint32: 0", is_proto3); + message.mutable_oneof_nested_message()->set_a(0); + RunValidProtobufTestWithMessage( + "OneofZeroMessage", RECOMMENDED, &message, + is_proto3 ? "oneof_nested_message: {}" : "oneof_nested_message: {a: 0}", + is_proto3); + message.mutable_oneof_nested_message()->set_a(1); + RunValidProtobufTestWithMessage( + "OneofZeroMessageSetTwice", RECOMMENDED, &message, + "oneof_nested_message: {a: 1}", + is_proto3); + message.set_oneof_string(""); + RunValidProtobufTestWithMessage( + "OneofZeroString", RECOMMENDED, &message, "oneof_string: \"\"", is_proto3); + message.set_oneof_bytes(""); + RunValidProtobufTestWithMessage( + "OneofZeroBytes", RECOMMENDED, &message, "oneof_bytes: \"\"", is_proto3); + message.set_oneof_bool(false); + RunValidProtobufTestWithMessage( + "OneofZeroBool", RECOMMENDED, &message, "oneof_bool: false", is_proto3); + message.set_oneof_uint64(0); + RunValidProtobufTestWithMessage( + "OneofZeroUint64", RECOMMENDED, &message, "oneof_uint64: 0", is_proto3); + message.set_oneof_float(0.0f); + RunValidProtobufTestWithMessage( + "OneofZeroFloat", RECOMMENDED, &message, "oneof_float: 0", is_proto3); + message.set_oneof_double(0.0); + RunValidProtobufTestWithMessage( + "OneofZeroDouble", RECOMMENDED, &message, "oneof_double: 0", is_proto3); + message.set_oneof_enum(MessageType::FOO); + RunValidProtobufTestWithMessage( + "OneofZeroEnum", RECOMMENDED, &message, "oneof_enum: FOO", is_proto3); +} + +template +void BinaryAndJsonConformanceSuite::TestUnknownMessage( + MessageType& message, bool is_proto3) { + message.ParseFromString("\xA8\x1F\x01"); + RunValidBinaryProtobufTest("UnknownVarint", REQUIRED, + message.SerializeAsString(), is_proto3); +} + +void BinaryAndJsonConformanceSuite::RunSuiteImpl() { + // Hack to get the list of test failures based on whether + // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER is enabled or not. + conformance::FailureSet failure_set; + ConformanceRequest req; + ConformanceResponse res; + req.set_message_type(failure_set.GetTypeName()); + req.set_protobuf_payload(""); + req.set_requested_output_format(conformance::WireFormat::PROTOBUF); + RunTest("FindFailures", req, &res); + GOOGLE_CHECK(failure_set.MergeFromString(res.protobuf_payload())); + for (const string& failure : failure_set.failure()) { + AddExpectedFailedTest(failure); + } + + type_resolver_.reset(NewTypeResolverForDescriptorPool( + kTypeUrlPrefix, DescriptorPool::generated_pool())); + type_url_ = GetTypeUrl(TestAllTypesProto3::descriptor()); + + for (int i = 1; i <= FieldDescriptor::MAX_TYPE; i++) { + if (i == FieldDescriptor::TYPE_GROUP) continue; + TestPrematureEOFForType(static_cast(i)); + } + + TestIllegalTags(); + + int64 kInt64Min = -9223372036854775808ULL; + int64 kInt64Max = 9223372036854775807ULL; + uint64 kUint64Max = 18446744073709551615ULL; + int32 kInt32Max = 2147483647; + int32 kInt32Min = -2147483648; + uint32 kUint32Max = 4294967295UL; + + TestValidDataForType( + FieldDescriptor::TYPE_DOUBLE, + { + {dbl(0), dbl(0)}, + {dbl(0.1), dbl(0.1)}, + {dbl(1.7976931348623157e+308), dbl(1.7976931348623157e+308)}, + {dbl(2.22507385850720138309e-308), dbl(2.22507385850720138309e-308)}, + }); + TestValidDataForType( + FieldDescriptor::TYPE_FLOAT, + { + {flt(0), flt(0)}, + {flt(0.1), flt(0.1)}, + {flt(1.00000075e-36), flt(1.00000075e-36)}, + {flt(3.402823e+38), flt(3.402823e+38)}, // 3.40282347e+38 + {flt(1.17549435e-38f), flt(1.17549435e-38)}, + }); + TestValidDataForType(FieldDescriptor::TYPE_INT64, + { + {varint(0), varint(0)}, + {varint(12345), varint(12345)}, + {varint(kInt64Max), varint(kInt64Max)}, + {varint(kInt64Min), varint(kInt64Min)}, + }); + TestValidDataForType(FieldDescriptor::TYPE_UINT64, + { + {varint(0), varint(0)}, + {varint(12345), varint(12345)}, + {varint(kUint64Max), varint(kUint64Max)}, + }); + TestValidDataForType(FieldDescriptor::TYPE_INT32, + { + {varint(0), varint(0)}, + {varint(12345), varint(12345)}, + {longvarint(12345, 2), varint(12345)}, + {longvarint(12345, 7), varint(12345)}, + {varint(kInt32Max), varint(kInt32Max)}, + {varint(kInt32Min), varint(kInt32Min)}, + {varint(1LL << 33), varint(0)}, + {varint((1LL << 33) - 1), varint(-1)}, + {varint(kInt64Max), varint(-1)}, + {varint(kInt64Min + 1), varint(1)}, + }); + TestValidDataForType( + FieldDescriptor::TYPE_UINT32, + { + {varint(0), varint(0)}, + {varint(12345), varint(12345)}, + {longvarint(12345, 2), varint(12345)}, + {longvarint(12345, 7), varint(12345)}, + {varint(kUint32Max), varint(kUint32Max)}, // UINT32_MAX + {varint(1LL << 33), varint(0)}, + {varint((1LL << 33) + 1), varint(1)}, + {varint((1LL << 33) - 1), varint((1LL << 32) - 1)}, + {varint(kInt64Max), varint((1LL << 32) - 1)}, + {varint(kInt64Min + 1), varint(1)}, + }); + TestValidDataForType(FieldDescriptor::TYPE_FIXED64, + { + {u64(0), u64(0)}, + {u64(12345), u64(12345)}, + {u64(kUint64Max), u64(kUint64Max)}, + }); + TestValidDataForType(FieldDescriptor::TYPE_FIXED32, + { + {u32(0), u32(0)}, + {u32(12345), u32(12345)}, + {u32(kUint32Max), u32(kUint32Max)}, // UINT32_MAX + }); + TestValidDataForType(FieldDescriptor::TYPE_SFIXED64, + { + {u64(0), u64(0)}, + {u64(12345), u64(12345)}, + {u64(kInt64Max), u64(kInt64Max)}, + {u64(kInt64Min), u64(kInt64Min)}, + }); + TestValidDataForType(FieldDescriptor::TYPE_SFIXED32, + { + {u32(0), u32(0)}, + {u32(12345), u32(12345)}, + {u32(kInt32Max), u32(kInt32Max)}, + {u32(kInt32Min), u32(kInt32Min)}, + }); + // Bools should be serialized as 0 for false and 1 for true. Parsers should + // also interpret any nonzero value as true. + TestValidDataForType(FieldDescriptor::TYPE_BOOL, + { + {varint(0), varint(0)}, + {varint(1), varint(1)}, + {varint(-1), varint(1)}, + {varint(12345678), varint(1)}, + {varint(1LL << 33), varint(1)}, + {varint(kInt64Max), varint(1)}, + {varint(kInt64Min), varint(1)}, + }); + TestValidDataForType(FieldDescriptor::TYPE_SINT32, + { + {zz32(0), zz32(0)}, + {zz32(12345), zz32(12345)}, + {zz32(kInt32Max), zz32(kInt32Max)}, + {zz32(kInt32Min), zz32(kInt32Min)}, + {zz64(kInt32Max + 2LL), zz32(1)}, + }); + TestValidDataForType(FieldDescriptor::TYPE_SINT64, + { + {zz64(0), zz64(0)}, + {zz64(12345), zz64(12345)}, + {zz64(kInt64Max), zz64(kInt64Max)}, + {zz64(kInt64Min), zz64(kInt64Min)}, + }); + TestValidDataForType( + FieldDescriptor::TYPE_STRING, + { + {delim(""), delim("")}, + {delim("Hello world!"), delim("Hello world!")}, + {delim("\'\"\?\\\a\b\f\n\r\t\v"), + delim("\'\"\?\\\a\b\f\n\r\t\v")}, // escape + {delim("谷歌"), delim("谷歌")}, // Google in Chinese + {delim("\u8C37\u6B4C"), delim("谷歌")}, // unicode escape + {delim("\u8c37\u6b4c"), delim("谷歌")}, // lowercase unicode + {delim("\xF0\x9F\x98\x81"), delim("\xF0\x9F\x98\x81")}, // emoji: 😁 + }); + TestValidDataForType(FieldDescriptor::TYPE_BYTES, + { + {delim(""), delim("")}, + {delim("Hello world!"), delim("Hello world!")}, + {delim("\x01\x02"), delim("\x01\x02")}, + {delim("\xfb"), delim("\xfb")}, + }); + TestValidDataForType(FieldDescriptor::TYPE_ENUM, + { + {varint(0), varint(0)}, + {varint(1), varint(1)}, + {varint(2), varint(2)}, + {varint(-1), varint(-1)}, + {varint(kInt64Max), varint(-1)}, + {varint(kInt64Min + 1), varint(1)}, + }); + TestValidDataForRepeatedScalarMessage(); + TestValidDataForType( + FieldDescriptor::TYPE_MESSAGE, + { + {delim(""), delim("")}, + {delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234))), + delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234)))}, + }); + + TestValidDataForMapType(FieldDescriptor::TYPE_INT32, + FieldDescriptor::TYPE_INT32); + TestValidDataForMapType(FieldDescriptor::TYPE_INT64, + FieldDescriptor::TYPE_INT64); + TestValidDataForMapType(FieldDescriptor::TYPE_UINT32, + FieldDescriptor::TYPE_UINT32); + TestValidDataForMapType(FieldDescriptor::TYPE_UINT64, + FieldDescriptor::TYPE_UINT64); + TestValidDataForMapType(FieldDescriptor::TYPE_SINT32, + FieldDescriptor::TYPE_SINT32); + TestValidDataForMapType(FieldDescriptor::TYPE_SINT64, + FieldDescriptor::TYPE_SINT64); + TestValidDataForMapType(FieldDescriptor::TYPE_FIXED32, + FieldDescriptor::TYPE_FIXED32); + TestValidDataForMapType(FieldDescriptor::TYPE_FIXED64, + FieldDescriptor::TYPE_FIXED64); + TestValidDataForMapType(FieldDescriptor::TYPE_SFIXED32, + FieldDescriptor::TYPE_SFIXED32); + TestValidDataForMapType(FieldDescriptor::TYPE_SFIXED64, + FieldDescriptor::TYPE_SFIXED64); + TestValidDataForMapType(FieldDescriptor::TYPE_INT32, + FieldDescriptor::TYPE_FLOAT); + TestValidDataForMapType(FieldDescriptor::TYPE_INT32, + FieldDescriptor::TYPE_DOUBLE); + TestValidDataForMapType(FieldDescriptor::TYPE_BOOL, + FieldDescriptor::TYPE_BOOL); + TestValidDataForMapType(FieldDescriptor::TYPE_STRING, + FieldDescriptor::TYPE_STRING); + TestValidDataForMapType(FieldDescriptor::TYPE_STRING, + FieldDescriptor::TYPE_BYTES); + TestValidDataForMapType(FieldDescriptor::TYPE_STRING, + FieldDescriptor::TYPE_ENUM); + TestValidDataForMapType(FieldDescriptor::TYPE_STRING, + FieldDescriptor::TYPE_MESSAGE); + // Additional test to check overwriting message value map. + TestOverwriteMessageValueMap(); + + TestValidDataForOneofType(FieldDescriptor::TYPE_UINT32); + TestValidDataForOneofType(FieldDescriptor::TYPE_BOOL); + TestValidDataForOneofType(FieldDescriptor::TYPE_UINT64); + TestValidDataForOneofType(FieldDescriptor::TYPE_FLOAT); + TestValidDataForOneofType(FieldDescriptor::TYPE_DOUBLE); + TestValidDataForOneofType(FieldDescriptor::TYPE_STRING); + TestValidDataForOneofType(FieldDescriptor::TYPE_BYTES); + TestValidDataForOneofType(FieldDescriptor::TYPE_ENUM); + TestValidDataForOneofType(FieldDescriptor::TYPE_MESSAGE); + // Additional test to check merging oneof message. + TestMergeOneofMessage(); + + // TODO(haberman): + // TestValidDataForType(FieldDescriptor::TYPE_GROUP + + // Unknown fields. + { + TestAllTypesProto3 messageProto3; + TestAllTypesProto2 messageProto2; + // TODO(yilunchong): update this behavior when unknown field's behavior + // changed in open source. Also delete + // Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput + // from failure list of python_cpp python java + TestUnknownMessage(messageProto3, true); + TestUnknownMessage(messageProto2, false); + } + + RunJsonTests(); +} + +void BinaryAndJsonConformanceSuite::RunJsonTests() { + RunValidJsonTest("HelloWorld", REQUIRED, + "{\"optionalString\":\"Hello, World!\"}", + "optional_string: 'Hello, World!'"); + + // NOTE: The spec for JSON support is still being sorted out, these may not + // all be correct. + + RunJsonTestsForFieldNameConvention(); + RunJsonTestsForNonRepeatedTypes(); + RunJsonTestsForRepeatedTypes(); + RunJsonTestsForNullTypes(); + RunJsonTestsForWrapperTypes(); + RunJsonTestsForFieldMask(); + RunJsonTestsForStruct(); + RunJsonTestsForValue(); + RunJsonTestsForAny(); + + RunValidJsonIgnoreUnknownTest("IgnoreUnknownJsonNumber", REQUIRED, + R"({ + "unknown": 1 + })", + ""); + RunValidJsonIgnoreUnknownTest("IgnoreUnknownJsonString", REQUIRED, + R"({ + "unknown": "a" + })", + ""); + RunValidJsonIgnoreUnknownTest("IgnoreUnknownJsonTrue", REQUIRED, + R"({ + "unknown": true + })", + ""); + RunValidJsonIgnoreUnknownTest("IgnoreUnknownJsonFalse", REQUIRED, + R"({ + "unknown": false + })", + ""); + RunValidJsonIgnoreUnknownTest("IgnoreUnknownJsonNull", REQUIRED, + R"({ + "unknown": null + })", + ""); + RunValidJsonIgnoreUnknownTest("IgnoreUnknownJsonObject", REQUIRED, + R"({ + "unknown": {"a": 1} + })", + ""); + + ExpectParseFailureForJson("RejectTopLevelNull", REQUIRED, "null"); +} + +void BinaryAndJsonConformanceSuite::RunJsonTestsForFieldNameConvention() { + RunValidJsonTest( + "FieldNameInSnakeCase", REQUIRED, + R"({ + "fieldname1": 1, + "fieldName2": 2, + "FieldName3": 3, + "fieldName4": 4 + })", + R"( + fieldname1: 1 + field_name2: 2 + _field_name3: 3 + field__name4_: 4 + )"); + RunValidJsonTest( + "FieldNameWithNumbers", REQUIRED, + R"({ + "field0name5": 5, + "field0Name6": 6 + })", + R"( + field0name5: 5 + field_0_name6: 6 + )"); + RunValidJsonTest( + "FieldNameWithMixedCases", REQUIRED, + R"({ + "fieldName7": 7, + "FieldName8": 8, + "fieldName9": 9, + "FieldName10": 10, + "FIELDNAME11": 11, + "FIELDName12": 12 + })", + R"( + fieldName7: 7 + FieldName8: 8 + field_Name9: 9 + Field_Name10: 10 + FIELD_NAME11: 11 + FIELD_name12: 12 + )"); + RunValidJsonTest( + "FieldNameWithDoubleUnderscores", RECOMMENDED, + R"({ + "FieldName13": 13, + "FieldName14": 14, + "fieldName15": 15, + "fieldName16": 16, + "fieldName17": 17, + "FieldName18": 18 + })", + R"( + __field_name13: 13 + __Field_name14: 14 + field__name15: 15 + field__Name16: 16 + field_name17__: 17 + Field_name18__: 18 + )"); + // Using the original proto field name in JSON is also allowed. + RunValidJsonTest( + "OriginalProtoFieldName", REQUIRED, + R"({ + "fieldname1": 1, + "field_name2": 2, + "_field_name3": 3, + "field__name4_": 4, + "field0name5": 5, + "field_0_name6": 6, + "fieldName7": 7, + "FieldName8": 8, + "field_Name9": 9, + "Field_Name10": 10, + "FIELD_NAME11": 11, + "FIELD_name12": 12, + "__field_name13": 13, + "__Field_name14": 14, + "field__name15": 15, + "field__Name16": 16, + "field_name17__": 17, + "Field_name18__": 18 + })", + R"( + fieldname1: 1 + field_name2: 2 + _field_name3: 3 + field__name4_: 4 + field0name5: 5 + field_0_name6: 6 + fieldName7: 7 + FieldName8: 8 + field_Name9: 9 + Field_Name10: 10 + FIELD_NAME11: 11 + FIELD_name12: 12 + __field_name13: 13 + __Field_name14: 14 + field__name15: 15 + field__Name16: 16 + field_name17__: 17 + Field_name18__: 18 + )"); + // Field names can be escaped. + RunValidJsonTest( + "FieldNameEscaped", REQUIRED, + R"({"fieldn\u0061me1": 1})", + "fieldname1: 1"); + // String ends with escape character. + ExpectParseFailureForJson( + "StringEndsWithEscapeChar", RECOMMENDED, + "{\"optionalString\": \"abc\\"); + // Field names must be quoted (or it's not valid JSON). + ExpectParseFailureForJson( + "FieldNameNotQuoted", RECOMMENDED, + "{fieldname1: 1}"); + // Trailing comma is not allowed (not valid JSON). + ExpectParseFailureForJson( + "TrailingCommaInAnObject", RECOMMENDED, + R"({"fieldname1":1,})"); + ExpectParseFailureForJson( + "TrailingCommaInAnObjectWithSpace", RECOMMENDED, + R"({"fieldname1":1 ,})"); + ExpectParseFailureForJson( + "TrailingCommaInAnObjectWithSpaceCommaSpace", RECOMMENDED, + R"({"fieldname1":1 , })"); + ExpectParseFailureForJson( + "TrailingCommaInAnObjectWithNewlines", RECOMMENDED, + R"({ + "fieldname1":1, + })"); + // JSON doesn't support comments. + ExpectParseFailureForJson( + "JsonWithComments", RECOMMENDED, + R"({ + // This is a comment. + "fieldname1": 1 + })"); + // JSON spec says whitespace doesn't matter, so try a few spacings to be sure. + RunValidJsonTest( + "OneLineNoSpaces", RECOMMENDED, + "{\"optionalInt32\":1,\"optionalInt64\":2}", + R"( + optional_int32: 1 + optional_int64: 2 + )"); + RunValidJsonTest( + "OneLineWithSpaces", RECOMMENDED, + "{ \"optionalInt32\" : 1 , \"optionalInt64\" : 2 }", + R"( + optional_int32: 1 + optional_int64: 2 + )"); + RunValidJsonTest( + "MultilineNoSpaces", RECOMMENDED, + "{\n\"optionalInt32\"\n:\n1\n,\n\"optionalInt64\"\n:\n2\n}", + R"( + optional_int32: 1 + optional_int64: 2 + )"); + RunValidJsonTest( + "MultilineWithSpaces", RECOMMENDED, + "{\n \"optionalInt32\" : 1\n ,\n \"optionalInt64\" : 2\n}\n", + R"( + optional_int32: 1 + optional_int64: 2 + )"); + // Missing comma between key/value pairs. + ExpectParseFailureForJson( + "MissingCommaOneLine", RECOMMENDED, + "{ \"optionalInt32\": 1 \"optionalInt64\": 2 }"); + ExpectParseFailureForJson( + "MissingCommaMultiline", RECOMMENDED, + "{\n \"optionalInt32\": 1\n \"optionalInt64\": 2\n}"); + // Duplicated field names are not allowed. + ExpectParseFailureForJson( + "FieldNameDuplicate", RECOMMENDED, + R"({ + "optionalNestedMessage": {a: 1}, + "optionalNestedMessage": {} + })"); + ExpectParseFailureForJson( + "FieldNameDuplicateDifferentCasing1", RECOMMENDED, + R"({ + "optional_nested_message": {a: 1}, + "optionalNestedMessage": {} + })"); + ExpectParseFailureForJson( + "FieldNameDuplicateDifferentCasing2", RECOMMENDED, + R"({ + "optionalNestedMessage": {a: 1}, + "optional_nested_message": {} + })"); + // Serializers should use lowerCamelCase by default. + RunValidJsonTestWithValidator( + "FieldNameInLowerCamelCase", REQUIRED, + R"({ + "fieldname1": 1, + "fieldName2": 2, + "FieldName3": 3, + "fieldName4": 4 + })", + [](const Json::Value& value) { + return value.isMember("fieldname1") && + value.isMember("fieldName2") && + value.isMember("FieldName3") && + value.isMember("fieldName4"); + }, + true); + RunValidJsonTestWithValidator( + "FieldNameWithNumbers", REQUIRED, + R"({ + "field0name5": 5, + "field0Name6": 6 + })", + [](const Json::Value& value) { + return value.isMember("field0name5") && + value.isMember("field0Name6"); + }, + true); + RunValidJsonTestWithValidator( + "FieldNameWithMixedCases", REQUIRED, + R"({ + "fieldName7": 7, + "FieldName8": 8, + "fieldName9": 9, + "FieldName10": 10, + "FIELDNAME11": 11, + "FIELDName12": 12 + })", + [](const Json::Value& value) { + return value.isMember("fieldName7") && + value.isMember("FieldName8") && + value.isMember("fieldName9") && + value.isMember("FieldName10") && + value.isMember("FIELDNAME11") && + value.isMember("FIELDName12"); + }, + true); + RunValidJsonTestWithValidator( + "FieldNameWithDoubleUnderscores", RECOMMENDED, + R"({ + "FieldName13": 13, + "FieldName14": 14, + "fieldName15": 15, + "fieldName16": 16, + "fieldName17": 17, + "FieldName18": 18 + })", + [](const Json::Value& value) { + return value.isMember("FieldName13") && + value.isMember("FieldName14") && + value.isMember("fieldName15") && + value.isMember("fieldName16") && + value.isMember("fieldName17") && + value.isMember("FieldName18"); + }, + true); + RunValidJsonTestWithValidator( + "StoresDefaultPrimitive", REQUIRED, + R"({ + "FieldName13": 0 + })", + [](const Json::Value& value) { return value.isMember("FieldName13"); }, + false); + RunValidJsonTestWithValidator( + "SkipsDefaultPrimitive", REQUIRED, + R"({ + "FieldName13": 0 + })", + [](const Json::Value& value) { return !value.isMember("FieldName13"); }, + true); + RunValidJsonTestWithValidator( + "FieldNameExtension", RECOMMENDED, + R"({ + "[protobuf_test_messages.proto2.extension_int32]": 1 + })", + [](const Json::Value& value) { + return value.isMember( + "[protobuf_test_messages.proto2.extension_int32]"); + }, + false); +} + +void BinaryAndJsonConformanceSuite::RunJsonTestsForNonRepeatedTypes() { + // Integer fields. + RunValidJsonTest( + "Int32FieldMaxValue", REQUIRED, + R"({"optionalInt32": 2147483647})", + "optional_int32: 2147483647"); + RunValidJsonTest( + "Int32FieldMinValue", REQUIRED, + R"({"optionalInt32": -2147483648})", + "optional_int32: -2147483648"); + RunValidJsonTest( + "Uint32FieldMaxValue", REQUIRED, + R"({"optionalUint32": 4294967295})", + "optional_uint32: 4294967295"); + RunValidJsonTest( + "Int64FieldMaxValue", REQUIRED, + R"({"optionalInt64": "9223372036854775807"})", + "optional_int64: 9223372036854775807"); + RunValidJsonTest( + "Int64FieldMinValue", REQUIRED, + R"({"optionalInt64": "-9223372036854775808"})", + "optional_int64: -9223372036854775808"); + RunValidJsonTest( + "Uint64FieldMaxValue", REQUIRED, + R"({"optionalUint64": "18446744073709551615"})", + "optional_uint64: 18446744073709551615"); + // While not the largest Int64, this is the largest + // Int64 which can be exactly represented within an + // IEEE-754 64-bit float, which is the expected level + // of interoperability guarantee. Larger values may + // work in some implementations, but should not be + // relied upon. + RunValidJsonTest( + "Int64FieldMaxValueNotQuoted", REQUIRED, + R"({"optionalInt64": 9223372036854774784})", + "optional_int64: 9223372036854774784"); + RunValidJsonTest( + "Int64FieldMinValueNotQuoted", REQUIRED, + R"({"optionalInt64": -9223372036854775808})", + "optional_int64: -9223372036854775808"); + // Largest interoperable Uint64; see comment above + // for Int64FieldMaxValueNotQuoted. + RunValidJsonTest( + "Uint64FieldMaxValueNotQuoted", REQUIRED, + R"({"optionalUint64": 18446744073709549568})", + "optional_uint64: 18446744073709549568"); + // Values can be represented as JSON strings. + RunValidJsonTest( + "Int32FieldStringValue", REQUIRED, + R"({"optionalInt32": "2147483647"})", + "optional_int32: 2147483647"); + RunValidJsonTest( + "Int32FieldStringValueEscaped", REQUIRED, + R"({"optionalInt32": "2\u003147483647"})", + "optional_int32: 2147483647"); + + // Parsers reject out-of-bound integer values. + ExpectParseFailureForJson( + "Int32FieldTooLarge", REQUIRED, + R"({"optionalInt32": 2147483648})"); + ExpectParseFailureForJson( + "Int32FieldTooSmall", REQUIRED, + R"({"optionalInt32": -2147483649})"); + ExpectParseFailureForJson( + "Uint32FieldTooLarge", REQUIRED, + R"({"optionalUint32": 4294967296})"); + ExpectParseFailureForJson( + "Int64FieldTooLarge", REQUIRED, + R"({"optionalInt64": "9223372036854775808"})"); + ExpectParseFailureForJson( + "Int64FieldTooSmall", REQUIRED, + R"({"optionalInt64": "-9223372036854775809"})"); + ExpectParseFailureForJson( + "Uint64FieldTooLarge", REQUIRED, + R"({"optionalUint64": "18446744073709551616"})"); + // Parser reject non-integer numeric values as well. + ExpectParseFailureForJson( + "Int32FieldNotInteger", REQUIRED, + R"({"optionalInt32": 0.5})"); + ExpectParseFailureForJson( + "Uint32FieldNotInteger", REQUIRED, + R"({"optionalUint32": 0.5})"); + ExpectParseFailureForJson( + "Int64FieldNotInteger", REQUIRED, + R"({"optionalInt64": "0.5"})"); + ExpectParseFailureForJson( + "Uint64FieldNotInteger", REQUIRED, + R"({"optionalUint64": "0.5"})"); + + // Integers but represented as float values are accepted. + RunValidJsonTest( + "Int32FieldFloatTrailingZero", REQUIRED, + R"({"optionalInt32": 100000.000})", + "optional_int32: 100000"); + RunValidJsonTest( + "Int32FieldExponentialFormat", REQUIRED, + R"({"optionalInt32": 1e5})", + "optional_int32: 100000"); + RunValidJsonTest( + "Int32FieldMaxFloatValue", REQUIRED, + R"({"optionalInt32": 2.147483647e9})", + "optional_int32: 2147483647"); + RunValidJsonTest( + "Int32FieldMinFloatValue", REQUIRED, + R"({"optionalInt32": -2.147483648e9})", + "optional_int32: -2147483648"); + RunValidJsonTest( + "Uint32FieldMaxFloatValue", REQUIRED, + R"({"optionalUint32": 4.294967295e9})", + "optional_uint32: 4294967295"); + + // Parser reject non-numeric values. + ExpectParseFailureForJson( + "Int32FieldNotNumber", REQUIRED, + R"({"optionalInt32": "3x3"})"); + ExpectParseFailureForJson( + "Uint32FieldNotNumber", REQUIRED, + R"({"optionalUint32": "3x3"})"); + ExpectParseFailureForJson( + "Int64FieldNotNumber", REQUIRED, + R"({"optionalInt64": "3x3"})"); + ExpectParseFailureForJson( + "Uint64FieldNotNumber", REQUIRED, + R"({"optionalUint64": "3x3"})"); + // JSON does not allow "+" on numeric values. + ExpectParseFailureForJson( + "Int32FieldPlusSign", REQUIRED, + R"({"optionalInt32": +1})"); + // JSON doesn't allow leading 0s. + ExpectParseFailureForJson( + "Int32FieldLeadingZero", REQUIRED, + R"({"optionalInt32": 01})"); + ExpectParseFailureForJson( + "Int32FieldNegativeWithLeadingZero", REQUIRED, + R"({"optionalInt32": -01})"); + // String values must follow the same syntax rule. Specifically leading + // or trailing spaces are not allowed. + ExpectParseFailureForJson( + "Int32FieldLeadingSpace", REQUIRED, + R"({"optionalInt32": " 1"})"); + ExpectParseFailureForJson( + "Int32FieldTrailingSpace", REQUIRED, + R"({"optionalInt32": "1 "})"); + + // 64-bit values are serialized as strings. + RunValidJsonTestWithValidator( + "Int64FieldBeString", RECOMMENDED, R"({"optionalInt64": 1})", + [](const Json::Value& value) { + return value["optionalInt64"].type() == Json::stringValue && + value["optionalInt64"].asString() == "1"; + }, + true); + RunValidJsonTestWithValidator( + "Uint64FieldBeString", RECOMMENDED, R"({"optionalUint64": 1})", + [](const Json::Value& value) { + return value["optionalUint64"].type() == Json::stringValue && + value["optionalUint64"].asString() == "1"; + }, + true); + + // Bool fields. + RunValidJsonTest( + "BoolFieldTrue", REQUIRED, + R"({"optionalBool":true})", + "optional_bool: true"); + RunValidJsonTest( + "BoolFieldFalse", REQUIRED, + R"({"optionalBool":false})", + "optional_bool: false"); + + // Other forms are not allowed. + ExpectParseFailureForJson( + "BoolFieldIntegerZero", RECOMMENDED, + R"({"optionalBool":0})"); + ExpectParseFailureForJson( + "BoolFieldIntegerOne", RECOMMENDED, + R"({"optionalBool":1})"); + ExpectParseFailureForJson( + "BoolFieldCamelCaseTrue", RECOMMENDED, + R"({"optionalBool":True})"); + ExpectParseFailureForJson( + "BoolFieldCamelCaseFalse", RECOMMENDED, + R"({"optionalBool":False})"); + ExpectParseFailureForJson( + "BoolFieldAllCapitalTrue", RECOMMENDED, + R"({"optionalBool":TRUE})"); + ExpectParseFailureForJson( + "BoolFieldAllCapitalFalse", RECOMMENDED, + R"({"optionalBool":FALSE})"); + ExpectParseFailureForJson( + "BoolFieldDoubleQuotedTrue", RECOMMENDED, + R"({"optionalBool":"true"})"); + ExpectParseFailureForJson( + "BoolFieldDoubleQuotedFalse", RECOMMENDED, + R"({"optionalBool":"false"})"); + + // Float fields. + RunValidJsonTest( + "FloatFieldMinPositiveValue", REQUIRED, + R"({"optionalFloat": 1.175494e-38})", + "optional_float: 1.175494e-38"); + RunValidJsonTest( + "FloatFieldMaxNegativeValue", REQUIRED, + R"({"optionalFloat": -1.175494e-38})", + "optional_float: -1.175494e-38"); + RunValidJsonTest( + "FloatFieldMaxPositiveValue", REQUIRED, + R"({"optionalFloat": 3.402823e+38})", + "optional_float: 3.402823e+38"); + RunValidJsonTest( + "FloatFieldMinNegativeValue", REQUIRED, + R"({"optionalFloat": 3.402823e+38})", + "optional_float: 3.402823e+38"); + // Values can be quoted. + RunValidJsonTest( + "FloatFieldQuotedValue", REQUIRED, + R"({"optionalFloat": "1"})", + "optional_float: 1"); + // Special values. + RunValidJsonTest( + "FloatFieldNan", REQUIRED, + R"({"optionalFloat": "NaN"})", + "optional_float: nan"); + RunValidJsonTest( + "FloatFieldInfinity", REQUIRED, + R"({"optionalFloat": "Infinity"})", + "optional_float: inf"); + RunValidJsonTest( + "FloatFieldNegativeInfinity", REQUIRED, + R"({"optionalFloat": "-Infinity"})", + "optional_float: -inf"); + // Non-canonical Nan will be correctly normalized. + { + TestAllTypesProto3 message; + // IEEE floating-point standard 32-bit quiet NaN: + // 0111 1111 1xxx xxxx xxxx xxxx xxxx xxxx + message.set_optional_float( + WireFormatLite::DecodeFloat(0x7FA12345)); + RunValidJsonTestWithProtobufInput( + "FloatFieldNormalizeQuietNan", REQUIRED, message, + "optional_float: nan"); + // IEEE floating-point standard 64-bit signaling NaN: + // 1111 1111 1xxx xxxx xxxx xxxx xxxx xxxx + message.set_optional_float( + WireFormatLite::DecodeFloat(0xFFB54321)); + RunValidJsonTestWithProtobufInput( + "FloatFieldNormalizeSignalingNan", REQUIRED, message, + "optional_float: nan"); + } + + // Special values must be quoted. + ExpectParseFailureForJson( + "FloatFieldNanNotQuoted", RECOMMENDED, + R"({"optionalFloat": NaN})"); + ExpectParseFailureForJson( + "FloatFieldInfinityNotQuoted", RECOMMENDED, + R"({"optionalFloat": Infinity})"); + ExpectParseFailureForJson( + "FloatFieldNegativeInfinityNotQuoted", RECOMMENDED, + R"({"optionalFloat": -Infinity})"); + // Parsers should reject out-of-bound values. + ExpectParseFailureForJson( + "FloatFieldTooSmall", REQUIRED, + R"({"optionalFloat": -3.502823e+38})"); + ExpectParseFailureForJson( + "FloatFieldTooLarge", REQUIRED, + R"({"optionalFloat": 3.502823e+38})"); + + // Double fields. + RunValidJsonTest( + "DoubleFieldMinPositiveValue", REQUIRED, + R"({"optionalDouble": 2.22507e-308})", + "optional_double: 2.22507e-308"); + RunValidJsonTest( + "DoubleFieldMaxNegativeValue", REQUIRED, + R"({"optionalDouble": -2.22507e-308})", + "optional_double: -2.22507e-308"); + RunValidJsonTest( + "DoubleFieldMaxPositiveValue", REQUIRED, + R"({"optionalDouble": 1.79769e+308})", + "optional_double: 1.79769e+308"); + RunValidJsonTest( + "DoubleFieldMinNegativeValue", REQUIRED, + R"({"optionalDouble": -1.79769e+308})", + "optional_double: -1.79769e+308"); + // Values can be quoted. + RunValidJsonTest( + "DoubleFieldQuotedValue", REQUIRED, + R"({"optionalDouble": "1"})", + "optional_double: 1"); + // Special values. + RunValidJsonTest( + "DoubleFieldNan", REQUIRED, + R"({"optionalDouble": "NaN"})", + "optional_double: nan"); + RunValidJsonTest( + "DoubleFieldInfinity", REQUIRED, + R"({"optionalDouble": "Infinity"})", + "optional_double: inf"); + RunValidJsonTest( + "DoubleFieldNegativeInfinity", REQUIRED, + R"({"optionalDouble": "-Infinity"})", + "optional_double: -inf"); + // Non-canonical Nan will be correctly normalized. + { + TestAllTypesProto3 message; + message.set_optional_double( + WireFormatLite::DecodeDouble(int64{0x7FFA123456789ABC})); + RunValidJsonTestWithProtobufInput( + "DoubleFieldNormalizeQuietNan", REQUIRED, message, + "optional_double: nan"); + message.set_optional_double( + WireFormatLite::DecodeDouble(uint64{0xFFFBCBA987654321})); + RunValidJsonTestWithProtobufInput( + "DoubleFieldNormalizeSignalingNan", REQUIRED, message, + "optional_double: nan"); + } + + // Special values must be quoted. + ExpectParseFailureForJson( + "DoubleFieldNanNotQuoted", RECOMMENDED, + R"({"optionalDouble": NaN})"); + ExpectParseFailureForJson( + "DoubleFieldInfinityNotQuoted", RECOMMENDED, + R"({"optionalDouble": Infinity})"); + ExpectParseFailureForJson( + "DoubleFieldNegativeInfinityNotQuoted", RECOMMENDED, + R"({"optionalDouble": -Infinity})"); + + // Parsers should reject out-of-bound values. + ExpectParseFailureForJson( + "DoubleFieldTooSmall", REQUIRED, + R"({"optionalDouble": -1.89769e+308})"); + ExpectParseFailureForJson( + "DoubleFieldTooLarge", REQUIRED, + R"({"optionalDouble": +1.89769e+308})"); + + // Enum fields. + RunValidJsonTest( + "EnumField", REQUIRED, + R"({"optionalNestedEnum": "FOO"})", + "optional_nested_enum: FOO"); + // Enum fields with alias + RunValidJsonTest( + "EnumFieldWithAlias", REQUIRED, + R"({"optionalAliasedEnum": "ALIAS_BAZ"})", + "optional_aliased_enum: ALIAS_BAZ"); + RunValidJsonTest( + "EnumFieldWithAliasUseAlias", REQUIRED, + R"({"optionalAliasedEnum": "QUX"})", + "optional_aliased_enum: ALIAS_BAZ"); + RunValidJsonTest( + "EnumFieldWithAliasLowerCase", REQUIRED, + R"({"optionalAliasedEnum": "qux"})", + "optional_aliased_enum: ALIAS_BAZ"); + RunValidJsonTest( + "EnumFieldWithAliasDifferentCase", REQUIRED, + R"({"optionalAliasedEnum": "bAz"})", + "optional_aliased_enum: ALIAS_BAZ"); + // Enum values must be represented as strings. + ExpectParseFailureForJson( + "EnumFieldNotQuoted", REQUIRED, + R"({"optionalNestedEnum": FOO})"); + // Numeric values are allowed. + RunValidJsonTest( + "EnumFieldNumericValueZero", REQUIRED, + R"({"optionalNestedEnum": 0})", + "optional_nested_enum: FOO"); + RunValidJsonTest( + "EnumFieldNumericValueNonZero", REQUIRED, + R"({"optionalNestedEnum": 1})", + "optional_nested_enum: BAR"); + // Unknown enum values are represented as numeric values. + RunValidJsonTestWithValidator( + "EnumFieldUnknownValue", REQUIRED, R"({"optionalNestedEnum": 123})", + [](const Json::Value& value) { + return value["optionalNestedEnum"].type() == Json::intValue && + value["optionalNestedEnum"].asInt() == 123; + }, + true); + + // String fields. + RunValidJsonTest( + "StringField", REQUIRED, + R"({"optionalString": "Hello world!"})", + "optional_string: \"Hello world!\""); + RunValidJsonTest( + "StringFieldUnicode", REQUIRED, + // Google in Chinese. + R"({"optionalString": "谷歌"})", + R"(optional_string: "谷歌")"); + RunValidJsonTest( + "StringFieldEscape", REQUIRED, + R"({"optionalString": "\"\\\/\b\f\n\r\t"})", + R"(optional_string: "\"\\/\b\f\n\r\t")"); + RunValidJsonTest( + "StringFieldUnicodeEscape", REQUIRED, + R"({"optionalString": "\u8C37\u6B4C"})", + R"(optional_string: "谷歌")"); + RunValidJsonTest( + "StringFieldUnicodeEscapeWithLowercaseHexLetters", REQUIRED, + R"({"optionalString": "\u8c37\u6b4c"})", + R"(optional_string: "谷歌")"); + RunValidJsonTest( + "StringFieldSurrogatePair", REQUIRED, + // The character is an emoji: grinning face with smiling eyes. 😁 + R"({"optionalString": "\uD83D\uDE01"})", + R"(optional_string: "\xF0\x9F\x98\x81")"); + + // Unicode escapes must start with "\u" (lowercase u). + ExpectParseFailureForJson( + "StringFieldUppercaseEscapeLetter", RECOMMENDED, + R"({"optionalString": "\U8C37\U6b4C"})"); + ExpectParseFailureForJson( + "StringFieldInvalidEscape", RECOMMENDED, + R"({"optionalString": "\uXXXX\u6B4C"})"); + ExpectParseFailureForJson( + "StringFieldUnterminatedEscape", RECOMMENDED, + R"({"optionalString": "\u8C3"})"); + ExpectParseFailureForJson( + "StringFieldUnpairedHighSurrogate", RECOMMENDED, + R"({"optionalString": "\uD800"})"); + ExpectParseFailureForJson( + "StringFieldUnpairedLowSurrogate", RECOMMENDED, + R"({"optionalString": "\uDC00"})"); + ExpectParseFailureForJson( + "StringFieldSurrogateInWrongOrder", RECOMMENDED, + R"({"optionalString": "\uDE01\uD83D"})"); + ExpectParseFailureForJson( + "StringFieldNotAString", REQUIRED, + R"({"optionalString": 12345})"); + + // Bytes fields. + RunValidJsonTest( + "BytesField", REQUIRED, + R"({"optionalBytes": "AQI="})", + R"(optional_bytes: "\x01\x02")"); + RunValidJsonTest( + "BytesFieldBase64Url", RECOMMENDED, + R"({"optionalBytes": "-_"})", + R"(optional_bytes: "\xfb")"); + + // Message fields. + RunValidJsonTest( + "MessageField", REQUIRED, + R"({"optionalNestedMessage": {"a": 1234}})", + "optional_nested_message: {a: 1234}"); + + // Oneof fields. + ExpectParseFailureForJson( + "OneofFieldDuplicate", REQUIRED, + R"({"oneofUint32": 1, "oneofString": "test"})"); + // Ensure zero values for oneof make it out/backs. + TestAllTypesProto3 messageProto3; + TestAllTypesProto2 messageProto2; + TestOneofMessage(messageProto3, true); + TestOneofMessage(messageProto2, false); + RunValidJsonTest( + "OneofZeroUint32", RECOMMENDED, + R"({"oneofUint32": 0})", "oneof_uint32: 0"); + RunValidJsonTest( + "OneofZeroMessage", RECOMMENDED, + R"({"oneofNestedMessage": {}})", "oneof_nested_message: {}"); + RunValidJsonTest( + "OneofZeroString", RECOMMENDED, + R"({"oneofString": ""})", "oneof_string: \"\""); + RunValidJsonTest( + "OneofZeroBytes", RECOMMENDED, + R"({"oneofBytes": ""})", "oneof_bytes: \"\""); + RunValidJsonTest( + "OneofZeroBool", RECOMMENDED, + R"({"oneofBool": false})", "oneof_bool: false"); + RunValidJsonTest( + "OneofZeroUint64", RECOMMENDED, + R"({"oneofUint64": 0})", "oneof_uint64: 0"); + RunValidJsonTest( + "OneofZeroFloat", RECOMMENDED, + R"({"oneofFloat": 0.0})", "oneof_float: 0"); + RunValidJsonTest( + "OneofZeroDouble", RECOMMENDED, + R"({"oneofDouble": 0.0})", "oneof_double: 0"); + RunValidJsonTest( + "OneofZeroEnum", RECOMMENDED, + R"({"oneofEnum":"FOO"})", "oneof_enum: FOO"); + + // Map fields. + RunValidJsonTest( + "Int32MapField", REQUIRED, + R"({"mapInt32Int32": {"1": 2, "3": 4}})", + "map_int32_int32: {key: 1 value: 2}" + "map_int32_int32: {key: 3 value: 4}"); + ExpectParseFailureForJson( + "Int32MapFieldKeyNotQuoted", RECOMMENDED, + R"({"mapInt32Int32": {1: 2, 3: 4}})"); + RunValidJsonTest( + "Uint32MapField", REQUIRED, + R"({"mapUint32Uint32": {"1": 2, "3": 4}})", + "map_uint32_uint32: {key: 1 value: 2}" + "map_uint32_uint32: {key: 3 value: 4}"); + ExpectParseFailureForJson( + "Uint32MapFieldKeyNotQuoted", RECOMMENDED, + R"({"mapUint32Uint32": {1: 2, 3: 4}})"); + RunValidJsonTest( + "Int64MapField", REQUIRED, + R"({"mapInt64Int64": {"1": 2, "3": 4}})", + "map_int64_int64: {key: 1 value: 2}" + "map_int64_int64: {key: 3 value: 4}"); + ExpectParseFailureForJson( + "Int64MapFieldKeyNotQuoted", RECOMMENDED, + R"({"mapInt64Int64": {1: 2, 3: 4}})"); + RunValidJsonTest( + "Uint64MapField", REQUIRED, + R"({"mapUint64Uint64": {"1": 2, "3": 4}})", + "map_uint64_uint64: {key: 1 value: 2}" + "map_uint64_uint64: {key: 3 value: 4}"); + ExpectParseFailureForJson( + "Uint64MapFieldKeyNotQuoted", RECOMMENDED, + R"({"mapUint64Uint64": {1: 2, 3: 4}})"); + RunValidJsonTest( + "BoolMapField", REQUIRED, + R"({"mapBoolBool": {"true": true, "false": false}})", + "map_bool_bool: {key: true value: true}" + "map_bool_bool: {key: false value: false}"); + ExpectParseFailureForJson( + "BoolMapFieldKeyNotQuoted", RECOMMENDED, + R"({"mapBoolBool": {true: true, false: false}})"); + RunValidJsonTest( + "MessageMapField", REQUIRED, + R"({ + "mapStringNestedMessage": { + "hello": {"a": 1234}, + "world": {"a": 5678} + } + })", + R"( + map_string_nested_message: { + key: "hello" + value: {a: 1234} + } + map_string_nested_message: { + key: "world" + value: {a: 5678} + } + )"); + // Since Map keys are represented as JSON strings, escaping should be allowed. + RunValidJsonTest( + "Int32MapEscapedKey", REQUIRED, + R"({"mapInt32Int32": {"\u0031": 2}})", + "map_int32_int32: {key: 1 value: 2}"); + RunValidJsonTest( + "Int64MapEscapedKey", REQUIRED, + R"({"mapInt64Int64": {"\u0031": 2}})", + "map_int64_int64: {key: 1 value: 2}"); + RunValidJsonTest( + "BoolMapEscapedKey", REQUIRED, + R"({"mapBoolBool": {"tr\u0075e": true}})", + "map_bool_bool: {key: true value: true}"); + + // http://www.rfc-editor.org/rfc/rfc7159.txt says strings have to use double + // quotes. + ExpectParseFailureForJson("StringFieldSingleQuoteKey", RECOMMENDED, + R"({'optionalString': "Hello world!"})"); + ExpectParseFailureForJson("StringFieldSingleQuoteValue", RECOMMENDED, + R"({"optionalString": 'Hello world!'})"); + ExpectParseFailureForJson("StringFieldSingleQuoteBoth", RECOMMENDED, + R"({'optionalString': 'Hello world!'})"); +} + +void BinaryAndJsonConformanceSuite::RunJsonTestsForRepeatedTypes() { + // Repeated fields. + RunValidJsonTest("PrimitiveRepeatedField", REQUIRED, + R"({"repeatedInt32": [1, 2, 3, 4]})", + "repeated_int32: [1, 2, 3, 4]"); + RunValidJsonTest("EnumRepeatedField", REQUIRED, + R"({"repeatedNestedEnum": ["FOO", "BAR", "BAZ"]})", + "repeated_nested_enum: [FOO, BAR, BAZ]"); + RunValidJsonTest("StringRepeatedField", REQUIRED, + R"({"repeatedString": ["Hello", "world"]})", + R"(repeated_string: ["Hello", "world"])"); + RunValidJsonTest("BytesRepeatedField", REQUIRED, + R"({"repeatedBytes": ["AAEC", "AQI="]})", + R"(repeated_bytes: ["\x00\x01\x02", "\x01\x02"])"); + RunValidJsonTest("MessageRepeatedField", REQUIRED, + R"({"repeatedNestedMessage": [{"a": 1234}, {"a": 5678}]})", + "repeated_nested_message: {a: 1234}" + "repeated_nested_message: {a: 5678}"); + + // Repeated field elements are of incorrect type. + ExpectParseFailureForJson( + "RepeatedFieldWrongElementTypeExpectingIntegersGotBool", REQUIRED, + R"({"repeatedInt32": [1, false, 3, 4]})"); + ExpectParseFailureForJson( + "RepeatedFieldWrongElementTypeExpectingIntegersGotString", REQUIRED, + R"({"repeatedInt32": [1, 2, "name", 4]})"); + ExpectParseFailureForJson( + "RepeatedFieldWrongElementTypeExpectingIntegersGotMessage", REQUIRED, + R"({"repeatedInt32": [1, 2, 3, {"a": 4}]})"); + ExpectParseFailureForJson( + "RepeatedFieldWrongElementTypeExpectingStringsGotInt", REQUIRED, + R"({"repeatedString": ["1", 2, "3", "4"]})"); + ExpectParseFailureForJson( + "RepeatedFieldWrongElementTypeExpectingStringsGotBool", REQUIRED, + R"({"repeatedString": ["1", "2", false, "4"]})"); + ExpectParseFailureForJson( + "RepeatedFieldWrongElementTypeExpectingStringsGotMessage", REQUIRED, + R"({"repeatedString": ["1", 2, "3", {"a": 4}]})"); + ExpectParseFailureForJson( + "RepeatedFieldWrongElementTypeExpectingMessagesGotInt", REQUIRED, + R"({"repeatedNestedMessage": [{"a": 1}, 2]})"); + ExpectParseFailureForJson( + "RepeatedFieldWrongElementTypeExpectingMessagesGotBool", REQUIRED, + R"({"repeatedNestedMessage": [{"a": 1}, false]})"); + ExpectParseFailureForJson( + "RepeatedFieldWrongElementTypeExpectingMessagesGotString", REQUIRED, + R"({"repeatedNestedMessage": [{"a": 1}, "2"]})"); + // Trailing comma in the repeated field is not allowed. + ExpectParseFailureForJson("RepeatedFieldTrailingComma", RECOMMENDED, + R"({"repeatedInt32": [1, 2, 3, 4,]})"); + ExpectParseFailureForJson("RepeatedFieldTrailingCommaWithSpace", RECOMMENDED, + "{\"repeatedInt32\": [1, 2, 3, 4 ,]}"); + ExpectParseFailureForJson("RepeatedFieldTrailingCommaWithSpaceCommaSpace", + RECOMMENDED, + "{\"repeatedInt32\": [1, 2, 3, 4 , ]}"); + ExpectParseFailureForJson( + "RepeatedFieldTrailingCommaWithNewlines", RECOMMENDED, + "{\"repeatedInt32\": [\n 1,\n 2,\n 3,\n 4,\n]}"); +} + +void BinaryAndJsonConformanceSuite::RunJsonTestsForNullTypes() { + // "null" is accepted for all fields types. + RunValidJsonTest( + "AllFieldAcceptNull", REQUIRED, + R"({ + "optionalInt32": null, + "optionalInt64": null, + "optionalUint32": null, + "optionalUint64": null, + "optionalSint32": null, + "optionalSint64": null, + "optionalFixed32": null, + "optionalFixed64": null, + "optionalSfixed32": null, + "optionalSfixed64": null, + "optionalFloat": null, + "optionalDouble": null, + "optionalBool": null, + "optionalString": null, + "optionalBytes": null, + "optionalNestedEnum": null, + "optionalNestedMessage": null, + "repeatedInt32": null, + "repeatedInt64": null, + "repeatedUint32": null, + "repeatedUint64": null, + "repeatedSint32": null, + "repeatedSint64": null, + "repeatedFixed32": null, + "repeatedFixed64": null, + "repeatedSfixed32": null, + "repeatedSfixed64": null, + "repeatedFloat": null, + "repeatedDouble": null, + "repeatedBool": null, + "repeatedString": null, + "repeatedBytes": null, + "repeatedNestedEnum": null, + "repeatedNestedMessage": null, + "mapInt32Int32": null, + "mapBoolBool": null, + "mapStringNestedMessage": null + })", + ""); + + // Repeated field elements cannot be null. + ExpectParseFailureForJson( + "RepeatedFieldPrimitiveElementIsNull", RECOMMENDED, + R"({"repeatedInt32": [1, null, 2]})"); + ExpectParseFailureForJson( + "RepeatedFieldMessageElementIsNull", RECOMMENDED, + R"({"repeatedNestedMessage": [{"a":1}, null, {"a":2}]})"); + // Map field keys cannot be null. + ExpectParseFailureForJson( + "MapFieldKeyIsNull", RECOMMENDED, + R"({"mapInt32Int32": {null: 1}})"); + // Map field values cannot be null. + ExpectParseFailureForJson( + "MapFieldValueIsNull", RECOMMENDED, + R"({"mapInt32Int32": {"0": null}})"); +} + +void BinaryAndJsonConformanceSuite::RunJsonTestsForWrapperTypes() { + RunValidJsonTest("OptionalBoolWrapper", REQUIRED, + R"({"optionalBoolWrapper": false})", + "optional_bool_wrapper: {value: false}"); + RunValidJsonTest( + "OptionalInt32Wrapper", REQUIRED, + R"({"optionalInt32Wrapper": 0})", + "optional_int32_wrapper: {value: 0}"); + RunValidJsonTest( + "OptionalUint32Wrapper", REQUIRED, + R"({"optionalUint32Wrapper": 0})", + "optional_uint32_wrapper: {value: 0}"); + RunValidJsonTest( + "OptionalInt64Wrapper", REQUIRED, + R"({"optionalInt64Wrapper": 0})", + "optional_int64_wrapper: {value: 0}"); + RunValidJsonTest( + "OptionalUint64Wrapper", REQUIRED, + R"({"optionalUint64Wrapper": 0})", + "optional_uint64_wrapper: {value: 0}"); + RunValidJsonTest( + "OptionalFloatWrapper", REQUIRED, + R"({"optionalFloatWrapper": 0})", + "optional_float_wrapper: {value: 0}"); + RunValidJsonTest( + "OptionalDoubleWrapper", REQUIRED, + R"({"optionalDoubleWrapper": 0})", + "optional_double_wrapper: {value: 0}"); + RunValidJsonTest( + "OptionalStringWrapper", REQUIRED, + R"({"optionalStringWrapper": ""})", + R"(optional_string_wrapper: {value: ""})"); + RunValidJsonTest( + "OptionalBytesWrapper", REQUIRED, + R"({"optionalBytesWrapper": ""})", + R"(optional_bytes_wrapper: {value: ""})"); + RunValidJsonTest( + "OptionalWrapperTypesWithNonDefaultValue", REQUIRED, + R"({ + "optionalBoolWrapper": true, + "optionalInt32Wrapper": 1, + "optionalUint32Wrapper": 1, + "optionalInt64Wrapper": "1", + "optionalUint64Wrapper": "1", + "optionalFloatWrapper": 1, + "optionalDoubleWrapper": 1, + "optionalStringWrapper": "1", + "optionalBytesWrapper": "AQI=" + })", + R"( + optional_bool_wrapper: {value: true} + optional_int32_wrapper: {value: 1} + optional_uint32_wrapper: {value: 1} + optional_int64_wrapper: {value: 1} + optional_uint64_wrapper: {value: 1} + optional_float_wrapper: {value: 1} + optional_double_wrapper: {value: 1} + optional_string_wrapper: {value: "1"} + optional_bytes_wrapper: {value: "\x01\x02"} + )"); + RunValidJsonTest( + "RepeatedBoolWrapper", REQUIRED, + R"({"repeatedBoolWrapper": [true, false]})", + "repeated_bool_wrapper: {value: true}" + "repeated_bool_wrapper: {value: false}"); + RunValidJsonTest( + "RepeatedInt32Wrapper", REQUIRED, + R"({"repeatedInt32Wrapper": [0, 1]})", + "repeated_int32_wrapper: {value: 0}" + "repeated_int32_wrapper: {value: 1}"); + RunValidJsonTest( + "RepeatedUint32Wrapper", REQUIRED, + R"({"repeatedUint32Wrapper": [0, 1]})", + "repeated_uint32_wrapper: {value: 0}" + "repeated_uint32_wrapper: {value: 1}"); + RunValidJsonTest( + "RepeatedInt64Wrapper", REQUIRED, + R"({"repeatedInt64Wrapper": [0, 1]})", + "repeated_int64_wrapper: {value: 0}" + "repeated_int64_wrapper: {value: 1}"); + RunValidJsonTest( + "RepeatedUint64Wrapper", REQUIRED, + R"({"repeatedUint64Wrapper": [0, 1]})", + "repeated_uint64_wrapper: {value: 0}" + "repeated_uint64_wrapper: {value: 1}"); + RunValidJsonTest( + "RepeatedFloatWrapper", REQUIRED, + R"({"repeatedFloatWrapper": [0, 1]})", + "repeated_float_wrapper: {value: 0}" + "repeated_float_wrapper: {value: 1}"); + RunValidJsonTest( + "RepeatedDoubleWrapper", REQUIRED, + R"({"repeatedDoubleWrapper": [0, 1]})", + "repeated_double_wrapper: {value: 0}" + "repeated_double_wrapper: {value: 1}"); + RunValidJsonTest( + "RepeatedStringWrapper", REQUIRED, + R"({"repeatedStringWrapper": ["", "AQI="]})", + R"( + repeated_string_wrapper: {value: ""} + repeated_string_wrapper: {value: "AQI="} + )"); + RunValidJsonTest( + "RepeatedBytesWrapper", REQUIRED, + R"({"repeatedBytesWrapper": ["", "AQI="]})", + R"( + repeated_bytes_wrapper: {value: ""} + repeated_bytes_wrapper: {value: "\x01\x02"} + )"); + RunValidJsonTest( + "WrapperTypesWithNullValue", REQUIRED, + R"({ + "optionalBoolWrapper": null, + "optionalInt32Wrapper": null, + "optionalUint32Wrapper": null, + "optionalInt64Wrapper": null, + "optionalUint64Wrapper": null, + "optionalFloatWrapper": null, + "optionalDoubleWrapper": null, + "optionalStringWrapper": null, + "optionalBytesWrapper": null, + "repeatedBoolWrapper": null, + "repeatedInt32Wrapper": null, + "repeatedUint32Wrapper": null, + "repeatedInt64Wrapper": null, + "repeatedUint64Wrapper": null, + "repeatedFloatWrapper": null, + "repeatedDoubleWrapper": null, + "repeatedStringWrapper": null, + "repeatedBytesWrapper": null + })", + ""); + + // Duration + RunValidJsonTest( + "DurationMinValue", REQUIRED, + R"({"optionalDuration": "-315576000000.999999999s"})", + "optional_duration: {seconds: -315576000000 nanos: -999999999}"); + RunValidJsonTest( + "DurationMaxValue", REQUIRED, + R"({"optionalDuration": "315576000000.999999999s"})", + "optional_duration: {seconds: 315576000000 nanos: 999999999}"); + RunValidJsonTest( + "DurationRepeatedValue", REQUIRED, + R"({"repeatedDuration": ["1.5s", "-1.5s"]})", + "repeated_duration: {seconds: 1 nanos: 500000000}" + "repeated_duration: {seconds: -1 nanos: -500000000}"); + RunValidJsonTest( + "DurationNull", REQUIRED, + R"({"optionalDuration": null})", + ""); + + ExpectParseFailureForJson( + "DurationMissingS", REQUIRED, + R"({"optionalDuration": "1"})"); + ExpectParseFailureForJson( + "DurationJsonInputTooSmall", REQUIRED, + R"({"optionalDuration": "-315576000001.000000000s"})"); + ExpectParseFailureForJson( + "DurationJsonInputTooLarge", REQUIRED, + R"({"optionalDuration": "315576000001.000000000s"})"); + ExpectSerializeFailureForJson( + "DurationProtoInputTooSmall", REQUIRED, + "optional_duration: {seconds: -315576000001 nanos: 0}"); + ExpectSerializeFailureForJson( + "DurationProtoInputTooLarge", REQUIRED, + "optional_duration: {seconds: 315576000001 nanos: 0}"); + + RunValidJsonTestWithValidator( + "DurationHasZeroFractionalDigit", RECOMMENDED, + R"({"optionalDuration": "1.000000000s"})", + [](const Json::Value& value) { + return value["optionalDuration"].asString() == "1s"; + }, + true); + RunValidJsonTestWithValidator( + "DurationHas3FractionalDigits", RECOMMENDED, + R"({"optionalDuration": "1.010000000s"})", + [](const Json::Value& value) { + return value["optionalDuration"].asString() == "1.010s"; + }, + true); + RunValidJsonTestWithValidator( + "DurationHas6FractionalDigits", RECOMMENDED, + R"({"optionalDuration": "1.000010000s"})", + [](const Json::Value& value) { + return value["optionalDuration"].asString() == "1.000010s"; + }, + true); + RunValidJsonTestWithValidator( + "DurationHas9FractionalDigits", RECOMMENDED, + R"({"optionalDuration": "1.000000010s"})", + [](const Json::Value& value) { + return value["optionalDuration"].asString() == "1.000000010s"; + }, + true); + + // Timestamp + RunValidJsonTest( + "TimestampMinValue", REQUIRED, + R"({"optionalTimestamp": "0001-01-01T00:00:00Z"})", + "optional_timestamp: {seconds: -62135596800}"); + RunValidJsonTest( + "TimestampMaxValue", REQUIRED, + R"({"optionalTimestamp": "9999-12-31T23:59:59.999999999Z"})", + "optional_timestamp: {seconds: 253402300799 nanos: 999999999}"); + RunValidJsonTest( + "TimestampRepeatedValue", REQUIRED, + R"({ + "repeatedTimestamp": [ + "0001-01-01T00:00:00Z", + "9999-12-31T23:59:59.999999999Z" + ] + })", + "repeated_timestamp: {seconds: -62135596800}" + "repeated_timestamp: {seconds: 253402300799 nanos: 999999999}"); + RunValidJsonTest("TimestampLeap", REQUIRED, + R"({"optionalTimestamp": "1993-02-10T00:00:00.000Z"})", + "optional_timestamp: {seconds: 729302400}"); + RunValidJsonTest("TimestampWithPositiveOffset", REQUIRED, + R"({"optionalTimestamp": "1970-01-01T08:00:01+08:00"})", + "optional_timestamp: {seconds: 1}"); + RunValidJsonTest("TimestampWithNegativeOffset", REQUIRED, + R"({"optionalTimestamp": "1969-12-31T16:00:01-08:00"})", + "optional_timestamp: {seconds: 1}"); + RunValidJsonTest( + "TimestampNull", REQUIRED, + R"({"optionalTimestamp": null})", + ""); + + ExpectParseFailureForJson( + "TimestampJsonInputTooSmall", REQUIRED, + R"({"optionalTimestamp": "0000-01-01T00:00:00Z"})"); + ExpectParseFailureForJson( + "TimestampJsonInputTooLarge", REQUIRED, + R"({"optionalTimestamp": "10000-01-01T00:00:00Z"})"); + ExpectParseFailureForJson( + "TimestampJsonInputMissingZ", REQUIRED, + R"({"optionalTimestamp": "0001-01-01T00:00:00"})"); + ExpectParseFailureForJson( + "TimestampJsonInputMissingT", REQUIRED, + R"({"optionalTimestamp": "0001-01-01 00:00:00Z"})"); + ExpectParseFailureForJson( + "TimestampJsonInputLowercaseZ", REQUIRED, + R"({"optionalTimestamp": "0001-01-01T00:00:00z"})"); + ExpectParseFailureForJson( + "TimestampJsonInputLowercaseT", REQUIRED, + R"({"optionalTimestamp": "0001-01-01t00:00:00Z"})"); + ExpectSerializeFailureForJson( + "TimestampProtoInputTooSmall", REQUIRED, + "optional_timestamp: {seconds: -62135596801}"); + ExpectSerializeFailureForJson( + "TimestampProtoInputTooLarge", REQUIRED, + "optional_timestamp: {seconds: 253402300800}"); + RunValidJsonTestWithValidator( + "TimestampZeroNormalized", RECOMMENDED, + R"({"optionalTimestamp": "1969-12-31T16:00:00-08:00"})", + [](const Json::Value& value) { + return value["optionalTimestamp"].asString() == "1970-01-01T00:00:00Z"; + }, + true); + RunValidJsonTestWithValidator( + "TimestampHasZeroFractionalDigit", RECOMMENDED, + R"({"optionalTimestamp": "1970-01-01T00:00:00.000000000Z"})", + [](const Json::Value& value) { + return value["optionalTimestamp"].asString() == "1970-01-01T00:00:00Z"; + }, + true); + RunValidJsonTestWithValidator( + "TimestampHas3FractionalDigits", RECOMMENDED, + R"({"optionalTimestamp": "1970-01-01T00:00:00.010000000Z"})", + [](const Json::Value& value) { + return value["optionalTimestamp"].asString() == + "1970-01-01T00:00:00.010Z"; + }, + true); + RunValidJsonTestWithValidator( + "TimestampHas6FractionalDigits", RECOMMENDED, + R"({"optionalTimestamp": "1970-01-01T00:00:00.000010000Z"})", + [](const Json::Value& value) { + return value["optionalTimestamp"].asString() == + "1970-01-01T00:00:00.000010Z"; + }, + true); + RunValidJsonTestWithValidator( + "TimestampHas9FractionalDigits", RECOMMENDED, + R"({"optionalTimestamp": "1970-01-01T00:00:00.000000010Z"})", + [](const Json::Value& value) { + return value["optionalTimestamp"].asString() == + "1970-01-01T00:00:00.000000010Z"; + }, + true); +} + +void BinaryAndJsonConformanceSuite::RunJsonTestsForFieldMask() { + RunValidJsonTest( + "FieldMask", REQUIRED, + R"({"optionalFieldMask": "foo,barBaz"})", + R"(optional_field_mask: {paths: "foo" paths: "bar_baz"})"); + RunValidJsonTest( + "EmptyFieldMask", REQUIRED, + R"({"optionalFieldMask": ""})", + R"(optional_field_mask: {})"); + ExpectParseFailureForJson( + "FieldMaskInvalidCharacter", RECOMMENDED, + R"({"optionalFieldMask": "foo,bar_bar"})"); + ExpectSerializeFailureForJson( + "FieldMaskPathsDontRoundTrip", RECOMMENDED, + R"(optional_field_mask: {paths: "fooBar"})"); + ExpectSerializeFailureForJson( + "FieldMaskNumbersDontRoundTrip", RECOMMENDED, + R"(optional_field_mask: {paths: "foo_3_bar"})"); + ExpectSerializeFailureForJson( + "FieldMaskTooManyUnderscore", RECOMMENDED, + R"(optional_field_mask: {paths: "foo__bar"})"); +} + +void BinaryAndJsonConformanceSuite::RunJsonTestsForStruct() { + RunValidJsonTest( + "Struct", REQUIRED, + R"({ + "optionalStruct": { + "nullValue": null, + "intValue": 1234, + "boolValue": true, + "doubleValue": 1234.5678, + "stringValue": "Hello world!", + "listValue": [1234, "5678"], + "objectValue": { + "value": 0 + } + } + })", + R"( + optional_struct: { + fields: { + key: "nullValue" + value: {null_value: NULL_VALUE} + } + fields: { + key: "intValue" + value: {number_value: 1234} + } + fields: { + key: "boolValue" + value: {bool_value: true} + } + fields: { + key: "doubleValue" + value: {number_value: 1234.5678} + } + fields: { + key: "stringValue" + value: {string_value: "Hello world!"} + } + fields: { + key: "listValue" + value: { + list_value: { + values: { + number_value: 1234 + } + values: { + string_value: "5678" + } + } + } + } + fields: { + key: "objectValue" + value: { + struct_value: { + fields: { + key: "value" + value: { + number_value: 0 + } + } + } + } + } + } + )"); + RunValidJsonTest( + "StructWithEmptyListValue", REQUIRED, + R"({ + "optionalStruct": { + "listValue": [] + } + })", + R"( + optional_struct: { + fields: { + key: "listValue" + value: { + list_value: { + } + } + } + } + )"); +} + +void BinaryAndJsonConformanceSuite::RunJsonTestsForValue() { + RunValidJsonTest( + "ValueAcceptInteger", REQUIRED, + R"({"optionalValue": 1})", + "optional_value: { number_value: 1}"); + RunValidJsonTest( + "ValueAcceptFloat", REQUIRED, + R"({"optionalValue": 1.5})", + "optional_value: { number_value: 1.5}"); + RunValidJsonTest( + "ValueAcceptBool", REQUIRED, + R"({"optionalValue": false})", + "optional_value: { bool_value: false}"); + RunValidJsonTest( + "ValueAcceptNull", REQUIRED, + R"({"optionalValue": null})", + "optional_value: { null_value: NULL_VALUE}"); + RunValidJsonTest( + "ValueAcceptString", REQUIRED, + R"({"optionalValue": "hello"})", + R"(optional_value: { string_value: "hello"})"); + RunValidJsonTest( + "ValueAcceptList", REQUIRED, + R"({"optionalValue": [0, "hello"]})", + R"( + optional_value: { + list_value: { + values: { + number_value: 0 + } + values: { + string_value: "hello" + } + } + } + )"); + RunValidJsonTest( + "ValueAcceptObject", REQUIRED, + R"({"optionalValue": {"value": 1}})", + R"( + optional_value: { + struct_value: { + fields: { + key: "value" + value: { + number_value: 1 + } + } + } + } + )"); + RunValidJsonTest( + "RepeatedValue", REQUIRED, + R"({ + "repeatedValue": [["a"]] + })", + R"( + repeated_value: [ + { + list_value: { + values: [ + { string_value: "a"} + ] + } + } + ] + )"); + RunValidJsonTest( + "RepeatedListValue", REQUIRED, + R"({ + "repeatedListValue": [["a"]] + })", + R"( + repeated_list_value: [ + { + values: [ + { string_value: "a"} + ] + } + ] + )"); + RunValidJsonTestWithValidator( + "NullValueInOtherOneofOldFormat", RECOMMENDED, + R"({"oneofNullValue": "NULL_VALUE"})", + [](const Json::Value& value) { + return (value.isMember("oneofNullValue") && + value["oneofNullValue"].isNull()); + }, + true); + RunValidJsonTestWithValidator( + "NullValueInOtherOneofNewFormat", RECOMMENDED, + R"({"oneofNullValue": null})", + [](const Json::Value& value) { + return (value.isMember("oneofNullValue") && + value["oneofNullValue"].isNull()); + }, + true); + RunValidJsonTestWithValidator( + "NullValueInNormalMessage", RECOMMENDED, + R"({"optionalNullValue": null})", + [](const Json::Value& value) { + return value.empty(); + }, + true); +} + +void BinaryAndJsonConformanceSuite::RunJsonTestsForAny() { + RunValidJsonTest( + "Any", REQUIRED, + R"({ + "optionalAny": { + "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3", + "optionalInt32": 12345 + } + })", + R"( + optional_any: { + [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { + optional_int32: 12345 + } + } + )"); + RunValidJsonTest( + "AnyNested", REQUIRED, + R"({ + "optionalAny": { + "@type": "type.googleapis.com/google.protobuf.Any", + "value": { + "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3", + "optionalInt32": 12345 + } + } + })", + R"( + optional_any: { + [type.googleapis.com/google.protobuf.Any] { + [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { + optional_int32: 12345 + } + } + } + )"); + // The special "@type" tag is not required to appear first. + RunValidJsonTest( + "AnyUnorderedTypeTag", REQUIRED, + R"({ + "optionalAny": { + "optionalInt32": 12345, + "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3" + } + })", + R"( + optional_any: { + [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { + optional_int32: 12345 + } + } + )"); + // Well-known types in Any. + RunValidJsonTest( + "AnyWithInt32ValueWrapper", REQUIRED, + R"({ + "optionalAny": { + "@type": "type.googleapis.com/google.protobuf.Int32Value", + "value": 12345 + } + })", + R"( + optional_any: { + [type.googleapis.com/google.protobuf.Int32Value] { + value: 12345 + } + } + )"); + RunValidJsonTest( + "AnyWithDuration", REQUIRED, + R"({ + "optionalAny": { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.5s" + } + })", + R"( + optional_any: { + [type.googleapis.com/google.protobuf.Duration] { + seconds: 1 + nanos: 500000000 + } + } + )"); + RunValidJsonTest( + "AnyWithTimestamp", REQUIRED, + R"({ + "optionalAny": { + "@type": "type.googleapis.com/google.protobuf.Timestamp", + "value": "1970-01-01T00:00:00Z" + } + })", + R"( + optional_any: { + [type.googleapis.com/google.protobuf.Timestamp] { + seconds: 0 + nanos: 0 + } + } + )"); + RunValidJsonTest( + "AnyWithFieldMask", REQUIRED, + R"({ + "optionalAny": { + "@type": "type.googleapis.com/google.protobuf.FieldMask", + "value": "foo,barBaz" + } + })", + R"( + optional_any: { + [type.googleapis.com/google.protobuf.FieldMask] { + paths: ["foo", "bar_baz"] + } + } + )"); + RunValidJsonTest( + "AnyWithStruct", REQUIRED, + R"({ + "optionalAny": { + "@type": "type.googleapis.com/google.protobuf.Struct", + "value": { + "foo": 1 + } + } + })", + R"( + optional_any: { + [type.googleapis.com/google.protobuf.Struct] { + fields: { + key: "foo" + value: { + number_value: 1 + } + } + } + } + )"); + RunValidJsonTest( + "AnyWithValueForJsonObject", REQUIRED, + R"({ + "optionalAny": { + "@type": "type.googleapis.com/google.protobuf.Value", + "value": { + "foo": 1 + } + } + })", + R"( + optional_any: { + [type.googleapis.com/google.protobuf.Value] { + struct_value: { + fields: { + key: "foo" + value: { + number_value: 1 + } + } + } + } + } + )"); + RunValidJsonTest( + "AnyWithValueForInteger", REQUIRED, + R"({ + "optionalAny": { + "@type": "type.googleapis.com/google.protobuf.Value", + "value": 1 + } + })", + R"( + optional_any: { + [type.googleapis.com/google.protobuf.Value] { + number_value: 1 + } + } + )"); +} + +} // namespace protobuf +} // namespace google diff --git a/conformance/binary_json_conformance_suite.h b/conformance/binary_json_conformance_suite.h new file mode 100644 index 0000000000000..0a1752634d554 --- /dev/null +++ b/conformance/binary_json_conformance_suite.h @@ -0,0 +1,141 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CONFORMANCE_BINARY_JSON_CONFORMANCE_SUITE_H +#define CONFORMANCE_BINARY_JSON_CONFORMANCE_SUITE_H + +#include "third_party/jsoncpp/json.h" +#include "conformance_test.h" + +namespace google { +namespace protobuf { + +class BinaryAndJsonConformanceSuite : public ConformanceTestSuite { + public: + BinaryAndJsonConformanceSuite() {} + + private: + void RunSuiteImpl(); + void RunJsonTests(); + void RunJsonTestsForFieldNameConvention(); + void RunJsonTestsForNonRepeatedTypes(); + void RunJsonTestsForRepeatedTypes(); + void RunJsonTestsForNullTypes(); + void RunJsonTestsForWrapperTypes(); + void RunJsonTestsForFieldMask(); + void RunJsonTestsForStruct(); + void RunJsonTestsForValue(); + void RunJsonTestsForAny(); + void RunValidJsonTest(const std::string& test_name, ConformanceLevel level, + const std::string& input_json, + const std::string& equivalent_text_format); + void RunValidJsonTestWithProtobufInput( + const std::string& test_name, ConformanceLevel level, + const protobuf_test_messages::proto3::TestAllTypesProto3& input, + const std::string& equivalent_text_format); + void RunValidJsonIgnoreUnknownTest(const std::string& test_name, + ConformanceLevel level, + const std::string& input_json, + const std::string& equivalent_text_format); + void RunValidProtobufTest(const std::string& test_name, + ConformanceLevel level, + const std::string& input_protobuf, + const std::string& equivalent_text_format, + bool is_proto3); + void RunValidBinaryProtobufTest(const std::string& test_name, + ConformanceLevel level, + const std::string& input_protobuf, + bool is_proto3); + void RunValidBinaryProtobufTest(const std::string& test_name, + ConformanceLevel level, + const std::string& input_protobuf, + const std::string& expected_protobuf, + bool is_proto3); + void RunValidProtobufTestWithMessage( + const std::string& test_name, ConformanceLevel level, + const Message* input, const std::string& equivalent_text_format, + bool is_proto3); + + bool ParseJsonResponse( + const conformance::ConformanceResponse& response, + Message* test_message); + bool ParseResponse( + const conformance::ConformanceResponse& response, + const ConformanceRequestSetting& setting, + Message* test_message) override; + + typedef std::function Validator; + void RunValidJsonTestWithValidator(const std::string& test_name, + ConformanceLevel level, + const std::string& input_json, + const Validator& validator, + bool is_proto3); + void ExpectParseFailureForJson(const std::string& test_name, + ConformanceLevel level, + const std::string& input_json); + void ExpectSerializeFailureForJson(const std::string& test_name, + ConformanceLevel level, + const std::string& text_format); + void ExpectParseFailureForProtoWithProtoVersion(const std::string& proto, + const std::string& test_name, + ConformanceLevel level, + bool is_proto3); + void ExpectParseFailureForProto(const std::string& proto, + const std::string& test_name, + ConformanceLevel level); + void ExpectHardParseFailureForProto(const std::string& proto, + const std::string& test_name, + ConformanceLevel level); + void TestPrematureEOFForType(google::protobuf::FieldDescriptor::Type type); + void TestIllegalTags(); + template + void TestOneofMessage (MessageType &message, + bool is_proto3); + template + void TestUnknownMessage (MessageType &message, + bool is_proto3); + void TestValidDataForType( + google::protobuf::FieldDescriptor::Type, + std::vector> values); + void TestValidDataForRepeatedScalarMessage(); + void TestValidDataForMapType(google::protobuf::FieldDescriptor::Type, + google::protobuf::FieldDescriptor::Type); + void TestValidDataForOneofType(google::protobuf::FieldDescriptor::Type); + void TestMergeOneofMessage(); + void TestOverwriteMessageValueMap(); + + std::unique_ptr type_resolver_; + std::string type_url_; +}; + +} // namespace protobuf +} // namespace google + +#endif // CONFORMANCE_BINARY_JSON_CONFORMANCE_SUITE_H diff --git a/conformance/conformance.proto b/conformance/conformance.proto index 525140e946713..49608b38f4c4d 100644 --- a/conformance/conformance.proto +++ b/conformance/conformance.proto @@ -55,6 +55,32 @@ enum WireFormat { UNSPECIFIED = 0; PROTOBUF = 1; JSON = 2; + JSPB = 3; // Google internal only. Opensource testees just skip it. + TEXT_FORMAT = 4; +} + +enum TestCategory { + UNSPECIFIED_TEST = 0; + BINARY_TEST = 1; // Test binary wire format. + JSON_TEST = 2; // Test json wire format. + // Similar to JSON_TEST. However, during parsing json, testee should ignore + // unknown fields. This feature is optional. Each implementation can decide + // whether to support it. See + // https://developers.google.com/protocol-buffers/docs/proto3#json_options + // for more detail. + JSON_IGNORE_UNKNOWN_PARSING_TEST = 3; + // Test jspb wire format. Google internal only. Opensource testees just skip it. + JSPB_TEST = 4; + // Test text format. For cpp, java and python, testees can already deal with + // this type. Testees of other languages can simply skip it. + TEXT_FORMAT_TEST = 5; +} + +// The conformance runner will request a list of failures as the first request. +// This will be known by message_type == "conformance.FailureSet", a conformance +// test should return a serialized FailureSet in protobuf_payload. +message FailureSet { + repeated string failure = 1; } // Represents a single test case's input. The testee should: @@ -73,6 +99,9 @@ message ConformanceRequest { oneof payload { bytes protobuf_payload = 1; string json_payload = 2; + // Google internal only. Opensource testees just skip it. + string jspb_payload = 7; + string text_payload = 8; } // Which format should the testee serialize its message to? @@ -82,6 +111,18 @@ message ConformanceRequest { // protobuf_test_messages.proto3.TestAllTypesProto3 or // protobuf_test_messages.proto2.TestAllTypesProto2. string message_type = 4; + + // Each test is given a specific test category. Some category may need + // specific support in testee programs. Refer to the definition of TestCategory + // for more information. + TestCategory test_category = 5; + + // Specify details for how to encode jspb. + JspbEncodingConfig jspb_encoding_options = 6; + + // This can be used in json and text format. If true, testee should print + // unknown fields instead of ignore. This feature is optional. + bool print_unknown_fields = 9; } // Represents a single test case's output. @@ -115,5 +156,21 @@ message ConformanceResponse { // For when the testee skipped the test, likely because a certain feature // wasn't supported, like JSON input/output. string skipped = 5; + + // If the input was successfully parsed and the requested output was JSPB, + // serialize to JSPB and set it in this field. JSPB is google internal only + // format. Opensource testees can just skip it. + string jspb_payload = 7; + + // If the input was successfully parsed and the requested output was + // TEXT_FORMAT, serialize to TEXT_FORMAT and set it in this field. + string text_payload = 8; } } + +// Encoding options for jspb format. +message JspbEncodingConfig { + // Encode the value field of Any as jspb array if true, otherwise binary. + bool use_jspb_array_any_format = 1; +} + diff --git a/conformance/conformance_cpp.cc b/conformance/conformance_cpp.cc index bf70309a69c75..9546518bf553a 100644 --- a/conformance/conformance_cpp.cc +++ b/conformance/conformance_cpp.cc @@ -32,12 +32,15 @@ #include #include -#include "conformance.pb.h" -#include -#include #include +#include #include #include +#include +#include "conformance.pb.h" +#include +#include +#include using conformance::ConformanceRequest; using conformance::ConformanceResponse; @@ -45,17 +48,20 @@ using google::protobuf::Descriptor; using google::protobuf::DescriptorPool; using google::protobuf::Message; using google::protobuf::MessageFactory; -using google::protobuf::internal::scoped_ptr; +using google::protobuf::TextFormat; using google::protobuf::util::BinaryToJsonString; +using google::protobuf::util::JsonParseOptions; using google::protobuf::util::JsonToBinaryString; using google::protobuf::util::NewTypeResolverForDescriptorPool; -using google::protobuf::util::Status; using google::protobuf::util::TypeResolver; using protobuf_test_messages::proto3::TestAllTypesProto3; using std::string; static const char kTypeUrlPrefix[] = "type.googleapis.com"; +const char* kFailures[] = { +}; + static string GetTypeUrl(const Descriptor* message) { return string(kTypeUrlPrefix) + "/" + message->full_name(); } @@ -65,6 +71,10 @@ bool verbose = false; TypeResolver* type_resolver; string* type_url; +namespace google { +namespace protobuf { + +using util::Status; bool CheckedRead(int fd, void *buf, size_t len) { size_t ofs = 0; @@ -74,7 +84,7 @@ bool CheckedRead(int fd, void *buf, size_t len) { if (bytes_read == 0) return false; if (bytes_read < 0) { - GOOGLE_LOG(FATAL) << "Error reading from test runner: " << strerror(errno); + GOOGLE_LOG(FATAL) << "Error reading from test runner: " << strerror(errno); } len -= bytes_read; @@ -112,11 +122,16 @@ void DoTest(const ConformanceRequest& request, ConformanceResponse* response) { case ConformanceRequest::kJsonPayload: { string proto_binary; - Status status = JsonToBinaryString(type_resolver, *type_url, - request.json_payload(), &proto_binary); + JsonParseOptions options; + options.ignore_unknown_fields = + (request.test_category() == + conformance::JSON_IGNORE_UNKNOWN_PARSING_TEST); + util::Status status = + JsonToBinaryString(type_resolver, *type_url, request.json_payload(), + &proto_binary, options); if (!status.ok()) { response->set_parse_error(string("Parse error: ") + - status.error_message().as_string()); + std::string(status.error_message())); return; } @@ -128,9 +143,27 @@ void DoTest(const ConformanceRequest& request, ConformanceResponse* response) { break; } + case ConformanceRequest::kTextPayload: { + if (!TextFormat::ParseFromString(request.text_payload(), test_message)) { + response->set_parse_error("Parse error"); + return; + } + break; + } + case ConformanceRequest::PAYLOAD_NOT_SET: GOOGLE_LOG(FATAL) << "Request didn't have payload."; break; + + default: + GOOGLE_LOG(FATAL) << "unknown payload type: " << request.payload_case(); + break; + } + + conformance::FailureSet failures; + if (descriptor == failures.GetDescriptor()) { + for (const char* s : kFailures) failures.add_failure(s); + test_message = &failures; } switch (request.requested_output_format()) { @@ -139,27 +172,37 @@ void DoTest(const ConformanceRequest& request, ConformanceResponse* response) { break; case conformance::PROTOBUF: { - GOOGLE_CHECK(test_message->SerializeToString(response->mutable_protobuf_payload())); + GOOGLE_CHECK(test_message->SerializeToString( + response->mutable_protobuf_payload())); break; } case conformance::JSON: { string proto_binary; GOOGLE_CHECK(test_message->SerializeToString(&proto_binary)); - Status status = BinaryToJsonString(type_resolver, *type_url, proto_binary, - response->mutable_json_payload()); + util::Status status = + BinaryToJsonString(type_resolver, *type_url, proto_binary, + response->mutable_json_payload()); if (!status.ok()) { response->set_serialize_error( string("Failed to serialize JSON output: ") + - status.error_message().as_string()); + std::string(status.error_message())); return; } break; } + case conformance::TEXT_FORMAT: { + TextFormat::Printer printer; + printer.SetHideUnknownFields(!request.print_unknown_fields()); + GOOGLE_CHECK(printer.PrintToString(*test_message, + response->mutable_text_payload())); + break; + } + default: GOOGLE_LOG(FATAL) << "Unknown output format: " - << request.requested_output_format(); + << request.requested_output_format(); } } @@ -205,12 +248,15 @@ bool DoTestIo() { return true; } +} // namespace protobuf +} // namespace google + int main() { type_resolver = NewTypeResolverForDescriptorPool( kTypeUrlPrefix, DescriptorPool::generated_pool()); type_url = new string(GetTypeUrl(TestAllTypesProto3::descriptor())); while (1) { - if (!DoTestIo()) { + if (!google::protobuf::DoTestIo()) { fprintf(stderr, "conformance-cpp: received EOF from test runner " "after %d tests, exiting\n", test_count); return 0; diff --git a/conformance/conformance_nodejs.js b/conformance/conformance_nodejs.js index 5d3955f77b449..4d96a3851e0c4 100755 --- a/conformance/conformance_nodejs.js +++ b/conformance/conformance_nodejs.js @@ -76,6 +76,10 @@ function doTest(request) { response.setSkipped("JSON not supported."); return response; + case conformance.ConformanceRequest.PayloadCase.TEXT_PAYLOAD: + response.setSkipped("Text format not supported."); + return response; + case conformance.ConformanceRequest.PayloadCase.PAYLOAD_NOT_SET: response.setRuntimeError("Request didn't have payload"); return response; diff --git a/conformance/conformance_objc.m b/conformance/conformance_objc.m index 84a43811fa1e2..ab751c81de4b9 100644 --- a/conformance/conformance_objc.m +++ b/conformance/conformance_objc.m @@ -68,7 +68,8 @@ static void Die(NSString *format, ...) { switch (request.payloadOneOfCase) { case ConformanceRequest_Payload_OneOfCase_GPBUnsetOneOfCase: - Die(@"Request didn't have a payload: %@", request); + response.runtimeError = + [NSString stringWithFormat:@"Request didn't have a payload: %@", request]; break; case ConformanceRequest_Payload_OneOfCase_ProtobufPayload: { @@ -78,7 +79,10 @@ static void Die(NSString *format, ...) { } else if ([request.messageType isEqual:@"protobuf_test_messages.proto2.TestAllTypesProto2"]) { msgClass = [TestAllTypesProto2 class]; } else { - Die(@"Protobuf request had an unknown message_type: %@", request.messageType); + response.runtimeError = + [NSString stringWithFormat:@"Protobuf request had an unknown message_type: %@", + request.messageType]; + break; } NSError *error = nil; testMessage = [msgClass parseFromData:request.protobufPayload error:&error]; @@ -92,13 +96,24 @@ static void Die(NSString *format, ...) { case ConformanceRequest_Payload_OneOfCase_JsonPayload: response.skipped = @"ObjC doesn't support parsing JSON"; break; + + case ConformanceRequest_Payload_OneOfCase_JspbPayload: + response.skipped = + @"ConformanceRequest had a jspb_payload ConformanceRequest.payload;" + " those aren't supposed to happen with opensource."; + break; + + case ConformanceRequest_Payload_OneOfCase_TextPayload: + response.skipped = @"ObjC doesn't support parsing TextFormat"; + break; } if (testMessage) { switch (request.requestedOutputFormat) { case WireFormat_GPBUnrecognizedEnumeratorValue: case WireFormat_Unspecified: - Die(@"Unrecognized/unspecified output format: %@", request); + response.runtimeError = + [NSString stringWithFormat:@"Unrecognized/unspecified output format: %@", request]; break; case WireFormat_Protobuf: @@ -112,6 +127,18 @@ static void Die(NSString *format, ...) { case WireFormat_Json: response.skipped = @"ObjC doesn't support generating JSON"; break; + + case WireFormat_Jspb: + response.skipped = + @"ConformanceRequest had a requested_output_format of JSPB WireFormat; that" + " isn't supposed to happen with opensource."; + break; + + case WireFormat_TextFormat: + // ObjC only has partial objc generation, so don't attempt any tests that need + // support. + response.skipped = @"ObjC doesn't support generating TextFormat"; + break; } } diff --git a/conformance/conformance_php.php b/conformance/conformance_php.php old mode 100755 new mode 100644 index b6e12c01e1760..9eef0c5a4abc6 --- a/conformance/conformance_php.php +++ b/conformance/conformance_php.php @@ -3,41 +3,26 @@ require_once("Conformance/WireFormat.php"); require_once("Conformance/ConformanceResponse.php"); require_once("Conformance/ConformanceRequest.php"); -require_once("Google/Protobuf/Any.php"); -require_once("Google/Protobuf/Duration.php"); -require_once("Google/Protobuf/FieldMask.php"); -require_once("Google/Protobuf/Struct.php"); -require_once("Google/Protobuf/Value.php"); -require_once("Google/Protobuf/ListValue.php"); -require_once("Google/Protobuf/NullValue.php"); -require_once("Google/Protobuf/Timestamp.php"); -require_once("Google/Protobuf/DoubleValue.php"); -require_once("Google/Protobuf/BytesValue.php"); -require_once("Google/Protobuf/FloatValue.php"); -require_once("Google/Protobuf/Int64Value.php"); -require_once("Google/Protobuf/UInt32Value.php"); -require_once("Google/Protobuf/BoolValue.php"); -require_once("Google/Protobuf/DoubleValue.php"); -require_once("Google/Protobuf/Int32Value.php"); -require_once("Google/Protobuf/StringValue.php"); -require_once("Google/Protobuf/UInt64Value.php"); +require_once("Conformance/FailureSet.php"); +require_once("Conformance/JspbEncodingConfig.php"); +require_once("Conformance/TestCategory.php"); require_once("Protobuf_test_messages/Proto3/ForeignMessage.php"); require_once("Protobuf_test_messages/Proto3/ForeignEnum.php"); require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3.php"); -require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3_NestedMessage.php"); -require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3_NestedEnum.php"); +require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3/AliasedEnum.php"); +require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3/NestedMessage.php"); +require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3/NestedEnum.php"); require_once("GPBMetadata/Conformance.php"); -require_once("GPBMetadata/Google/Protobuf/Any.php"); -require_once("GPBMetadata/Google/Protobuf/Duration.php"); -require_once("GPBMetadata/Google/Protobuf/FieldMask.php"); -require_once("GPBMetadata/Google/Protobuf/Struct.php"); -require_once("GPBMetadata/Google/Protobuf/Timestamp.php"); -require_once("GPBMetadata/Google/Protobuf/Wrappers.php"); require_once("GPBMetadata/Google/Protobuf/TestMessagesProto3.php"); +use \Conformance\TestCategory; use \Conformance\WireFormat; +if (!ini_get("date.timezone")) { + ini_set("date.timezone", "UTC"); +} + $test_count = 0; function doTest($request) @@ -45,7 +30,10 @@ function doTest($request) $test_message = new \Protobuf_test_messages\Proto3\TestAllTypesProto3(); $response = new \Conformance\ConformanceResponse(); if ($request->getPayload() == "protobuf_payload") { - if ($request->getMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3") { + if ($request->getMessageType() == "conformance.FailureSet") { + $response->setProtobufPayload(""); + return $response; + } elseif ($request->getMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3") { try { $test_message->mergeFromString($request->getProtobufPayload()); } catch (Exception $e) { @@ -53,19 +41,26 @@ function doTest($request) return $response; } } elseif ($request->getMessageType() == "protobuf_test_messages.proto2.TestAllTypesProto2") { - $response->setSkipped("PHP doesn't support proto2"); - return $response; + $response->setSkipped("PHP doesn't support proto2"); + return $response; } else { - trigger_error("Protobuf request doesn't have specific payload type", E_USER_ERROR); + trigger_error("Protobuf request doesn't have specific payload type", E_USER_ERROR); } } elseif ($request->getPayload() == "json_payload") { + $ignore_json_unknown = + ($request->getTestCategory() == + TestCategory::JSON_IGNORE_UNKNOWN_PARSING_TEST); try { - $test_message->mergeFromJsonString($request->getJsonPayload()); + $test_message->mergeFromJsonString($request->getJsonPayload(), + $ignore_json_unknown); } catch (Exception $e) { $response->setParseError($e->getMessage()); return $response; } - } else { + } elseif ($request->getPayload() == "text_payload") { + $response->setSkipped("PHP doesn't support text format yet"); + return $response; + } else { trigger_error("Request didn't have payload.", E_USER_ERROR); } @@ -74,7 +69,12 @@ function doTest($request) } elseif ($request->getRequestedOutputFormat() == WireFormat::PROTOBUF) { $response->setProtobufPayload($test_message->serializeToString()); } elseif ($request->getRequestedOutputFormat() == WireFormat::JSON) { - $response->setJsonPayload($test_message->serializeToJsonString()); + try { + $response->setJsonPayload($test_message->serializeToJsonString()); + } catch (Exception $e) { + $response->setSerializeError($e->getMessage()); + return $response; + } } return $response; diff --git a/conformance/conformance_python.py b/conformance/conformance_python.py index c5ba2467a6b54..37ee36e24c51f 100755 --- a/conformance/conformance_python.py +++ b/conformance/conformance_python.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# # Protocol Buffers - Google's data interchange format # Copyright 2008 Google Inc. All rights reserved. # https://developers.google.com/protocol-buffers/ @@ -38,12 +37,11 @@ import struct import sys import os -from google.protobuf import descriptor -from google.protobuf import descriptor_pool from google.protobuf import json_format from google.protobuf import message from google.protobuf import test_messages_proto3_pb2 from google.protobuf import test_messages_proto2_pb2 +from google.protobuf import text_format import conformance_pb2 sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0) @@ -56,29 +54,94 @@ class ProtocolError(Exception): pass def do_test(request): + response = conformance_pb2.ConformanceResponse() + + if request.message_type == "conformance.FailureSet": + failure_set = conformance_pb2.FailureSet() + failures = [] + # TODO(gerbens): Remove, this is a hack to detect if the old vs new + # parser is used by the cpp code. Relying on a bug in the old parser. + hack_proto = test_messages_proto2_pb2.TestAllTypesProto2() + old_parser = True + try: + hack_proto.ParseFromString(b"\322\002\001") + except message.DecodeError as e: + old_parser = False + if old_parser: + # the string above is one of the failing conformance test strings of the + # old parser. If we succeed the c++ implementation is using the old + # parser so we add the list of failing conformance tests. + failures = [ + "Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE", + "Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE", + "Required.Proto3.ProtobufInput.PrematureEofInPackedField.BOOL", + "Required.Proto3.ProtobufInput.PrematureEofInPackedField.DOUBLE", + "Required.Proto3.ProtobufInput.PrematureEofInPackedField.ENUM", + "Required.Proto3.ProtobufInput.PrematureEofInPackedField.FIXED32", + "Required.Proto3.ProtobufInput.PrematureEofInPackedField.FIXED64", + "Required.Proto3.ProtobufInput.PrematureEofInPackedField.FLOAT", + "Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT32", + "Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT64", + "Required.Proto3.ProtobufInput.PrematureEofInPackedField.SFIXED32", + "Required.Proto3.ProtobufInput.PrematureEofInPackedField.SFIXED64", + "Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT32", + "Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT64", + "Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT32", + "Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT64", + "Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE", + "Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE", + "Required.Proto2.ProtobufInput.PrematureEofInPackedField.BOOL", + "Required.Proto2.ProtobufInput.PrematureEofInPackedField.DOUBLE", + "Required.Proto2.ProtobufInput.PrematureEofInPackedField.ENUM", + "Required.Proto2.ProtobufInput.PrematureEofInPackedField.FIXED32", + "Required.Proto2.ProtobufInput.PrematureEofInPackedField.FIXED64", + "Required.Proto2.ProtobufInput.PrematureEofInPackedField.FLOAT", + "Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT32", + "Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT64", + "Required.Proto2.ProtobufInput.PrematureEofInPackedField.SFIXED32", + "Required.Proto2.ProtobufInput.PrematureEofInPackedField.SFIXED64", + "Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT32", + "Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT64", + "Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT32", + "Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64", + ] + for x in failures: + failure_set.failure.append(x) + response.protobuf_payload = failure_set.SerializeToString() + return response + isProto3 = (request.message_type == "protobuf_test_messages.proto3.TestAllTypesProto3") isJson = (request.WhichOneof('payload') == 'json_payload') isProto2 = (request.message_type == "protobuf_test_messages.proto2.TestAllTypesProto2") - + if (not isProto3) and (not isJson) and (not isProto2): raise ProtocolError("Protobuf request doesn't have specific payload type") - + test_message = test_messages_proto2_pb2.TestAllTypesProto2() if isProto2 else \ test_messages_proto3_pb2.TestAllTypesProto3() - response = conformance_pb2.ConformanceResponse() - try: if request.WhichOneof('payload') == 'protobuf_payload': try: test_message.ParseFromString(request.protobuf_payload) except message.DecodeError as e: response.parse_error = str(e) - return response - + return response + elif request.WhichOneof('payload') == 'json_payload': try: - json_format.Parse(request.json_payload, test_message) + ignore_unknown_fields = \ + request.test_category == \ + conformance_pb2.JSON_IGNORE_UNKNOWN_PARSING_TEST + json_format.Parse(request.json_payload, test_message, + ignore_unknown_fields) + except Exception as e: + response.parse_error = str(e) + return response + + elif request.WhichOneof('payload') == 'text_payload': + try: + text_format.Parse(request.text_payload, test_message) except Exception as e: response.parse_error = str(e) return response @@ -93,12 +156,16 @@ def do_test(request): response.protobuf_payload = test_message.SerializeToString() elif request.requested_output_format == conformance_pb2.JSON: - try: + try: response.json_payload = json_format.MessageToJson(test_message) except Exception as e: response.serialize_error = str(e) return response + elif request.requested_output_format == conformance_pb2.TEXT_FORMAT: + response.text_payload = text_format.MessageToString( + test_message, print_unknown_fields=request.print_unknown_fields) + except Exception as e: response.runtime_error = str(e) diff --git a/conformance/conformance_ruby.rb b/conformance/conformance_ruby.rb index df63bf7cedde9..4af7659b09ea8 100755 --- a/conformance/conformance_ruby.rb +++ b/conformance/conformance_ruby.rb @@ -32,6 +32,7 @@ require 'conformance_pb' require 'google/protobuf/test_messages_proto3_pb' +require 'google/protobuf/test_messages_proto2_pb' $test_count = 0 $verbose = false @@ -39,34 +40,40 @@ def do_test(request) test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.new response = Conformance::ConformanceResponse.new + descriptor = Google::Protobuf::DescriptorPool.generated_pool.lookup(request.message_type) + + unless descriptor + response.skipped = "Unknown message type: " + request.message_type + end begin case request.payload when :protobuf_payload - if request.message_type.eql?('protobuf_test_messages.proto3.TestAllTypesProto3') - begin - test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.decode( - request.protobuf_payload) - rescue Google::Protobuf::ParseError => err - response.parse_error = err.message.encode('utf-8') - return response - end - elsif request.message_type.eql?('protobuf_test_messages.proto2.TestAllTypesProto2') - response.skipped = "Ruby doesn't support proto2" + begin + test_message = descriptor.msgclass.decode(request.protobuf_payload) + rescue Google::Protobuf::ParseError => err + response.parse_error = err.message.encode('utf-8') return response - else - fail "Protobuf request doesn't have specific payload type" end when :json_payload begin - test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.decode_json( - request.json_payload) + options = {} + if request.test_category == :JSON_IGNORE_UNKNOWN_PARSING_TEST + options[:ignore_unknown_fields] = true + end + test_message = descriptor.msgclass.decode_json(request.json_payload, options) rescue Google::Protobuf::ParseError => err response.parse_error = err.message.encode('utf-8') 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 @@ -76,10 +83,18 @@ def do_test(request) fail 'Unspecified output format' when :PROTOBUF - response.protobuf_payload = test_message.to_proto + begin + response.protobuf_payload = test_message.to_proto + rescue Google::Protobuf::ParseError => err + response.serialize_error = err.message.encode('utf-8') + end when :JSON - response.json_payload = test_message.to_json + begin + response.json_payload = test_message.to_json + rescue Google::Protobuf::ParseError => err + response.serialize_error = err.message.encode('utf-8') + end when nil fail "Request didn't have requested output format" diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc index b1ff688353d40..07b4150670678 100644 --- a/conformance/conformance_test.cc +++ b/conformance/conformance_test.cc @@ -28,169 +28,153 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include "conformance_test.h" + #include -#include -#include -#include "conformance.pb.h" -#include "conformance_test.h" -#include -#include +#include +#include +#include -#include #include +#include #include #include #include #include -#include -#include - -#include "third_party/jsoncpp/json.h" +#include "conformance.pb.h" using conformance::ConformanceRequest; using conformance::ConformanceResponse; using conformance::WireFormat; -using google::protobuf::Descriptor; -using google::protobuf::FieldDescriptor; -using google::protobuf::internal::WireFormatLite; using google::protobuf::TextFormat; using google::protobuf::util::DefaultFieldComparator; -using google::protobuf::util::JsonToBinaryString; using google::protobuf::util::MessageDifferencer; -using google::protobuf::util::NewTypeResolverForDescriptorPool; -using google::protobuf::util::Status; -using protobuf_test_messages::proto3::TestAllTypesProto3; -using protobuf_test_messages::proto2::TestAllTypesProto2; using std::string; namespace { -static const char kTypeUrlPrefix[] = "type.googleapis.com"; - -static string GetTypeUrl(const Descriptor* message) { - return string(kTypeUrlPrefix) + "/" + message->full_name(); +static string ToOctString(const string& binary_string) { + string oct_string; + for (size_t i = 0; i < binary_string.size(); i++) { + uint8_t c = binary_string.at(i); + uint8_t high = c / 64; + uint8_t mid = (c % 64) / 8; + uint8_t low = c % 8; + oct_string.push_back('\\'); + oct_string.push_back('0' + high); + oct_string.push_back('0' + mid); + oct_string.push_back('0' + low); + } + return oct_string; } -/* Routines for building arbitrary protos *************************************/ +} // namespace -// We would use CodedOutputStream except that we want more freedom to build -// arbitrary protos (even invalid ones). +namespace google { +namespace protobuf { + +ConformanceTestSuite::ConformanceRequestSetting::ConformanceRequestSetting( + ConformanceLevel level, + conformance::WireFormat input_format, + conformance::WireFormat output_format, + conformance::TestCategory test_category, + const Message& prototype_message, + const string& test_name, const string& input) + : level_(level), + input_format_(input_format), + output_format_(output_format), + prototype_message_(prototype_message), + prototype_message_for_compare_(prototype_message.New()), + test_name_(test_name) { + switch (input_format) { + case conformance::PROTOBUF: { + request_.set_protobuf_payload(input); + break; + } -const string empty; + case conformance::JSON: { + request_.set_json_payload(input); + break; + } -string cat(const string& a, const string& b, - const string& c = empty, - const string& d = empty, - const string& e = empty, - const string& f = empty, - const string& g = empty, - const string& h = empty, - const string& i = empty, - const string& j = empty, - const string& k = empty, - const string& l = empty) { - string ret; - ret.reserve(a.size() + b.size() + c.size() + d.size() + e.size() + f.size() + - g.size() + h.size() + i.size() + j.size() + k.size() + l.size()); - ret.append(a); - ret.append(b); - ret.append(c); - ret.append(d); - ret.append(e); - ret.append(f); - ret.append(g); - ret.append(h); - ret.append(i); - ret.append(j); - ret.append(k); - ret.append(l); - return ret; -} + case conformance::JSPB: { + request_.set_jspb_payload(input); + break; + } -// The maximum number of bytes that it takes to encode a 64-bit varint. -#define VARINT_MAX_LEN 10 + case conformance::TEXT_FORMAT: { + request_.set_text_payload(input); + break; + } -size_t vencode64(uint64_t val, int over_encoded_bytes, char *buf) { - if (val == 0) { buf[0] = 0; return 1; } - size_t i = 0; - while (val) { - uint8_t byte = val & 0x7fU; - val >>= 7; - if (val || over_encoded_bytes) byte |= 0x80U; - buf[i++] = byte; - } - while (over_encoded_bytes--) { - assert(i < 10); - uint8_t byte = over_encoded_bytes ? 0x80 : 0; - buf[i++] = byte; + default: + GOOGLE_LOG(FATAL) << "Unspecified input format"; } - return i; -} -string varint(uint64_t x) { - char buf[VARINT_MAX_LEN]; - size_t len = vencode64(x, 0, buf); - return string(buf, len); -} + request_.set_test_category(test_category); -// Encodes a varint that is |extra| bytes longer than it needs to be, but still -// valid. -string longvarint(uint64_t x, int extra) { - char buf[VARINT_MAX_LEN]; - size_t len = vencode64(x, extra, buf); - return string(buf, len); + request_.set_message_type(prototype_message.GetDescriptor()->full_name()); + request_.set_requested_output_format(output_format); } -// TODO: proper byte-swapping for big-endian machines. -string fixed32(void *data) { return string(static_cast(data), 4); } -string fixed64(void *data) { return string(static_cast(data), 8); } +std::unique_ptr +ConformanceTestSuite::ConformanceRequestSetting::NewTestMessage() const { + return std::unique_ptr(prototype_message_for_compare_->New()); +} -string delim(const string& buf) { return cat(varint(buf.size()), buf); } -string u32(uint32_t u32) { return fixed32(&u32); } -string u64(uint64_t u64) { return fixed64(&u64); } -string flt(float f) { return fixed32(&f); } -string dbl(double d) { return fixed64(&d); } -string zz32(int32_t x) { return varint(WireFormatLite::ZigZagEncode32(x)); } -string zz64(int64_t x) { return varint(WireFormatLite::ZigZagEncode64(x)); } +string ConformanceTestSuite::ConformanceRequestSetting:: + GetTestName() const { + string rname = + prototype_message_.GetDescriptor()->file()->syntax() == + FileDescriptor::SYNTAX_PROTO3 ? "Proto3" : "Proto2"; -string tag(uint32_t fieldnum, char wire_type) { - return varint((fieldnum << 3) | wire_type); + return StrCat(ConformanceLevelToString(level_), ".", rname, ".", + InputFormatString(input_format_), ".", test_name_, ".", + OutputFormatString(output_format_)); } -string submsg(uint32_t fn, const string& buf) { - return cat( tag(fn, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), delim(buf) ); +string ConformanceTestSuite::ConformanceRequestSetting:: + ConformanceLevelToString( + ConformanceLevel level) const { + switch (level) { + case REQUIRED: return "Required"; + case RECOMMENDED: return "Recommended"; + } + GOOGLE_LOG(FATAL) << "Unknown value: " << level; + return ""; } -#define UNKNOWN_FIELD 666 - -const FieldDescriptor* GetFieldForType(FieldDescriptor::Type type, - bool repeated, bool isProto3) { - - const Descriptor* d = isProto3 ? - TestAllTypesProto3().GetDescriptor() : TestAllTypesProto2().GetDescriptor(); - for (int i = 0; i < d->field_count(); i++) { - const FieldDescriptor* f = d->field(i); - if (f->type() == type && f->is_repeated() == repeated) { - return f; - } +string ConformanceTestSuite::ConformanceRequestSetting:: + InputFormatString(conformance::WireFormat format) const { + switch (format) { + case conformance::PROTOBUF: + return "ProtobufInput"; + case conformance::JSON: + return "JsonInput"; + case conformance::TEXT_FORMAT: + return "TextFormatInput"; + default: + GOOGLE_LOG(FATAL) << "Unspecified output format"; } - GOOGLE_LOG(FATAL) << "Couldn't find field with type " << (int)type; - return nullptr; + return ""; } -string UpperCase(string str) { - for (int i = 0; i < str.size(); i++) { - str[i] = toupper(str[i]); +string ConformanceTestSuite::ConformanceRequestSetting:: + OutputFormatString(conformance::WireFormat format) const { + switch (format) { + case conformance::PROTOBUF: + return "ProtobufOutput"; + case conformance::JSON: + return "JsonOutput"; + case conformance::TEXT_FORMAT: + return "TextFormatOutput"; + default: + GOOGLE_LOG(FATAL) << "Unspecified output format"; } - return str; + return ""; } -} // anonymous namespace - -namespace google { -namespace protobuf { - void ConformanceTestSuite::ReportSuccess(const string& test_name) { if (expected_to_fail_.erase(test_name) != 0) { StringAppendF(&output_, @@ -237,89 +221,40 @@ void ConformanceTestSuite::ReportSkip(const string& test_name, skipped_.insert(test_name); } -string ConformanceTestSuite::ConformanceLevelToString(ConformanceLevel level) { - switch (level) { - case REQUIRED: return "Required"; - case RECOMMENDED: return "Recommended"; - } - GOOGLE_LOG(FATAL) << "Unknown value: " << level; - return ""; -} - -void ConformanceTestSuite::RunTest(const string& test_name, - const ConformanceRequest& request, - ConformanceResponse* response) { - if (test_names_.insert(test_name).second == false) { - GOOGLE_LOG(FATAL) << "Duplicated test name: " << test_name; - } - - string serialized_request; - string serialized_response; - request.SerializeToString(&serialized_request); - - runner_->RunTest(test_name, serialized_request, &serialized_response); - - if (!response->ParseFromString(serialized_response)) { - response->Clear(); - response->set_runtime_error("response proto could not be parsed."); - } - - if (verbose_) { - StringAppendF(&output_, "conformance test: name=%s, request=%s, response=%s\n", - test_name.c_str(), - request.ShortDebugString().c_str(), - response->ShortDebugString().c_str()); - } -} - void ConformanceTestSuite::RunValidInputTest( - const string& test_name, ConformanceLevel level, const string& input, - WireFormat input_format, const string& equivalent_text_format, - WireFormat requested_output, bool isProto3) { - auto newTestMessage = [&isProto3]() { - Message* newMessage; - if (isProto3) { - newMessage = new TestAllTypesProto3; - } else { - newMessage = new TestAllTypesProto2; - } - return newMessage; - }; - Message* reference_message = newTestMessage(); - GOOGLE_CHECK( - TextFormat::ParseFromString(equivalent_text_format, reference_message)) - << "Failed to parse data for test case: " << test_name - << ", data: " << equivalent_text_format; - - ConformanceRequest request; + const ConformanceRequestSetting& setting, + const string& equivalent_text_format) { + std::unique_ptr reference_message(setting.NewTestMessage()); + GOOGLE_CHECK(TextFormat::ParseFromString(equivalent_text_format, + reference_message.get())) + << "Failed to parse data for test case: " << setting.GetTestName() + << ", data: " << equivalent_text_format; + const string equivalent_wire_format = reference_message->SerializeAsString(); + RunValidBinaryInputTest(setting, equivalent_wire_format); +} + +void ConformanceTestSuite::RunValidBinaryInputTest( + const ConformanceRequestSetting& setting, + const string& equivalent_wire_format, bool require_same_wire_format) { + const ConformanceRequest& request = setting.GetRequest(); ConformanceResponse response; + RunTest(setting.GetTestName(), request, &response); + VerifyResponse(setting, equivalent_wire_format, response, true, + require_same_wire_format); +} - switch (input_format) { - case conformance::PROTOBUF: { - request.set_protobuf_payload(input); - if (isProto3) { - request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); - } else { - request.set_message_type("protobuf_test_messages.proto2.TestAllTypesProto2"); - } - break; - } - - case conformance::JSON: { - request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); - request.set_json_payload(input); - break; - } - - default: - GOOGLE_LOG(FATAL) << "Unspecified input format"; - } - - request.set_requested_output_format(requested_output); - - RunTest(test_name, request, &response); +void ConformanceTestSuite::VerifyResponse( + const ConformanceRequestSetting& setting, + const string& equivalent_wire_format, const ConformanceResponse& response, + bool need_report_success, bool require_same_wire_format) { + std::unique_ptr test_message(setting.NewTestMessage()); + const ConformanceRequest& request = setting.GetRequest(); + const string& test_name = setting.GetTestName(); + ConformanceLevel level = setting.GetLevel(); + std::unique_ptr reference_message = setting.NewTestMessage(); - Message *test_message = newTestMessage(); + GOOGLE_CHECK(reference_message->ParseFromString(equivalent_wire_format)) + << "Failed to parse wire data for test case: " << test_name; switch (response.result_case()) { case ConformanceResponse::RESULT_NOT_SET: @@ -338,53 +273,8 @@ void ConformanceTestSuite::RunValidInputTest( ReportSkip(test_name, request, response); return; - case ConformanceResponse::kJsonPayload: { - if (requested_output != conformance::JSON) { - ReportFailure( - test_name, level, request, response, - "Test was asked for protobuf output but provided JSON instead."); - return; - } - string binary_protobuf; - Status status = - JsonToBinaryString(type_resolver_.get(), type_url_, - response.json_payload(), &binary_protobuf); - if (!status.ok()) { - ReportFailure(test_name, level, request, response, - "JSON output we received from test was unparseable."); - return; - } - - if (!test_message->ParseFromString(binary_protobuf)) { - ReportFailure(test_name, level, request, response, - "INTERNAL ERROR: internal JSON->protobuf transcode " - "yielded unparseable proto."); - return; - } - - break; - } - - case ConformanceResponse::kProtobufPayload: { - if (requested_output != conformance::PROTOBUF) { - ReportFailure( - test_name, level, request, response, - "Test was asked for JSON output but provided protobuf instead."); - return; - } - - if (!test_message->ParseFromString(response.protobuf_payload())) { - ReportFailure(test_name, level, request, response, - "Protobuf output we received from test was unparseable."); - return; - } - - break; - } - default: - GOOGLE_LOG(FATAL) << test_name << ": unknown payload type: " - << response.result_case(); + if (!ParseResponse(response, setting, test_message.get())) return; } MessageDifferencer differencer; @@ -394,341 +284,60 @@ void ConformanceTestSuite::RunValidInputTest( string differences; differencer.ReportDifferencesToString(&differences); - bool check; - check = differencer.Compare(*reference_message, *test_message); - if (check) { - ReportSuccess(test_name); - } else { - ReportFailure(test_name, level, request, response, - "Output was not equivalent to reference message: %s.", - differences.c_str()); - } -} -void ConformanceTestSuite::ExpectParseFailureForProtoWithProtoVersion ( - const string& proto, const string& test_name, ConformanceLevel level, - bool isProto3) { - ConformanceRequest request; - ConformanceResponse response; - request.set_protobuf_payload(proto); - if (isProto3) { - request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); - } else { - request.set_message_type("protobuf_test_messages.proto2.TestAllTypesProto2"); - } - string effective_test_name = ConformanceLevelToString(level) + - (isProto3 ? ".Proto3" : ".Proto2") + - ".ProtobufInput." + test_name; + bool check = false; - // We don't expect output, but if the program erroneously accepts the protobuf - // we let it send its response as this. We must not leave it unspecified. - request.set_requested_output_format(conformance::PROTOBUF); - - RunTest(effective_test_name, request, &response); - if (response.result_case() == ConformanceResponse::kParseError) { - ReportSuccess(effective_test_name); - } else if (response.result_case() == ConformanceResponse::kSkipped) { - ReportSkip(effective_test_name, request, response); + if (require_same_wire_format) { + GOOGLE_DCHECK_EQ(response.result_case(), ConformanceResponse::kProtobufPayload); + const string& protobuf_payload = response.protobuf_payload(); + check = equivalent_wire_format == protobuf_payload; + differences = StrCat("Expect: ", ToOctString(equivalent_wire_format), + ", but got: ", ToOctString(protobuf_payload)); } else { - ReportFailure(effective_test_name, level, request, response, - "Should have failed to parse, but didn't."); - } -} - -// Expect that this precise protobuf will cause a parse error. -void ConformanceTestSuite::ExpectParseFailureForProto( - const string& proto, const string& test_name, ConformanceLevel level) { - ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level, true); - ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level, false); -} - -// Expect that this protobuf will cause a parse error, even if it is followed -// by valid protobuf data. We can try running this twice: once with this -// data verbatim and once with this data followed by some valid data. -// -// TODO(haberman): implement the second of these. -void ConformanceTestSuite::ExpectHardParseFailureForProto( - const string& proto, const string& test_name, ConformanceLevel level) { - return ExpectParseFailureForProto(proto, test_name, level); -} - -void ConformanceTestSuite::RunValidJsonTest( - const string& test_name, ConformanceLevel level, const string& input_json, - const string& equivalent_text_format) { - RunValidInputTest( - ConformanceLevelToString(level) + ".Proto3.JsonInput." + test_name + - ".ProtobufOutput", level, input_json, conformance::JSON, - equivalent_text_format, conformance::PROTOBUF, true); - RunValidInputTest( - ConformanceLevelToString(level) + ".Proto3.JsonInput." + test_name + - ".JsonOutput", level, input_json, conformance::JSON, - equivalent_text_format, conformance::JSON, true); -} - -void ConformanceTestSuite::RunValidJsonTestWithProtobufInput( - const string& test_name, ConformanceLevel level, const TestAllTypesProto3& input, - const string& equivalent_text_format) { - RunValidInputTest( - ConformanceLevelToString(level) + ".Proto3" + ".ProtobufInput." + test_name + - ".JsonOutput", level, input.SerializeAsString(), conformance::PROTOBUF, - equivalent_text_format, conformance::JSON, true); -} - -void ConformanceTestSuite::RunValidProtobufTest( - const string& test_name, ConformanceLevel level, - const string& input_protobuf, const string& equivalent_text_format, - bool isProto3) { - string rname = ".Proto3"; - if (!isProto3) { - rname = ".Proto2"; - } - RunValidInputTest( - ConformanceLevelToString(level) + rname + ".ProtobufInput." + test_name + - ".ProtobufOutput", level, input_protobuf, conformance::PROTOBUF, - equivalent_text_format, conformance::PROTOBUF, isProto3); - if (isProto3) { - RunValidInputTest( - ConformanceLevelToString(level) + rname + ".ProtobufInput." + test_name + - ".JsonOutput", level, input_protobuf, conformance::PROTOBUF, - equivalent_text_format, conformance::JSON, isProto3); - } -} - -void ConformanceTestSuite::RunValidProtobufTestWithMessage( - const string& test_name, ConformanceLevel level, const Message *input, - const string& equivalent_text_format, bool isProto3) { - RunValidProtobufTest(test_name, level, input->SerializeAsString(), equivalent_text_format, isProto3); -} - -// According to proto3 JSON specification, JSON serializers follow more strict -// rules than parsers (e.g., a serializer must serialize int32 values as JSON -// numbers while the parser is allowed to accept them as JSON strings). This -// method allows strict checking on a proto3 JSON serializer by inspecting -// the JSON output directly. -void ConformanceTestSuite::RunValidJsonTestWithValidator( - const string& test_name, ConformanceLevel level, const string& input_json, - const Validator& validator) { - ConformanceRequest request; - ConformanceResponse response; - request.set_json_payload(input_json); - request.set_requested_output_format(conformance::JSON); - request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); - - string effective_test_name = ConformanceLevelToString(level) + - ".Proto3.JsonInput." + test_name + ".Validator"; - - RunTest(effective_test_name, request, &response); - - if (response.result_case() == ConformanceResponse::kSkipped) { - ReportSkip(effective_test_name, request, response); - return; - } - - if (response.result_case() != ConformanceResponse::kJsonPayload) { - ReportFailure(effective_test_name, level, request, response, - "Expected JSON payload but got type %d.", - response.result_case()); - return; - } - Json::Reader reader; - Json::Value value; - if (!reader.parse(response.json_payload(), value)) { - ReportFailure(effective_test_name, level, request, response, - "JSON payload cannot be parsed as valid JSON: %s", - reader.getFormattedErrorMessages().c_str()); - return; + check = differencer.Compare(*reference_message, *test_message); } - if (!validator(value)) { - ReportFailure(effective_test_name, level, request, response, - "JSON payload validation failed."); - return; - } - ReportSuccess(effective_test_name); -} - -void ConformanceTestSuite::ExpectParseFailureForJson( - const string& test_name, ConformanceLevel level, const string& input_json) { - ConformanceRequest request; - ConformanceResponse response; - request.set_json_payload(input_json); - request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); - string effective_test_name = - ConformanceLevelToString(level) + ".Proto3.JsonInput." + test_name; - // We don't expect output, but if the program erroneously accepts the protobuf - // we let it send its response as this. We must not leave it unspecified. - request.set_requested_output_format(conformance::JSON); - - RunTest(effective_test_name, request, &response); - if (response.result_case() == ConformanceResponse::kParseError) { - ReportSuccess(effective_test_name); - } else if (response.result_case() == ConformanceResponse::kSkipped) { - ReportSkip(effective_test_name, request, response); + if (check) { + if (need_report_success) { + ReportSuccess(test_name); + } } else { - ReportFailure(effective_test_name, level, request, response, - "Should have failed to parse, but didn't."); + ReportFailure(test_name, level, request, response, + "Output was not equivalent to reference message: %s.", + differences.c_str()); } } -void ConformanceTestSuite::ExpectSerializeFailureForJson( - const string& test_name, ConformanceLevel level, const string& text_format) { - TestAllTypesProto3 payload_message; - GOOGLE_CHECK( - TextFormat::ParseFromString(text_format, &payload_message)) - << "Failed to parse: " << text_format; - - ConformanceRequest request; - ConformanceResponse response; - request.set_protobuf_payload(payload_message.SerializeAsString()); - request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3"); - string effective_test_name = - ConformanceLevelToString(level) + "." + test_name + ".JsonOutput"; - request.set_requested_output_format(conformance::JSON); - - RunTest(effective_test_name, request, &response); - if (response.result_case() == ConformanceResponse::kSerializeError) { - ReportSuccess(effective_test_name); - } else if (response.result_case() == ConformanceResponse::kSkipped) { - ReportSkip(effective_test_name, request, response); - } else { - ReportFailure(effective_test_name, level, request, response, - "Should have failed to serialize, but didn't."); +void ConformanceTestSuite::RunTest(const string& test_name, + const ConformanceRequest& request, + ConformanceResponse* response) { + if (test_names_.insert(test_name).second == false) { + GOOGLE_LOG(FATAL) << "Duplicated test name: " << test_name; } -} - -//TODO: proto2? -void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) { - // Incomplete values for each wire type. - static const string incompletes[6] = { - string("\x80"), // VARINT - string("abcdefg"), // 64BIT - string("\x80"), // DELIMITED (partial length) - string(), // START_GROUP (no value required) - string(), // END_GROUP (no value required) - string("abc") // 32BIT - }; - - const FieldDescriptor* field = GetFieldForType(type, false, true); - const FieldDescriptor* rep_field = GetFieldForType(type, true, true); - WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( - static_cast(type)); - const string& incomplete = incompletes[wire_type]; - const string type_name = - UpperCase(string(".") + FieldDescriptor::TypeName(type)); - ExpectParseFailureForProto( - tag(field->number(), wire_type), - "PrematureEofBeforeKnownNonRepeatedValue" + type_name, REQUIRED); - - ExpectParseFailureForProto( - tag(rep_field->number(), wire_type), - "PrematureEofBeforeKnownRepeatedValue" + type_name, REQUIRED); - - ExpectParseFailureForProto( - tag(UNKNOWN_FIELD, wire_type), - "PrematureEofBeforeUnknownValue" + type_name, REQUIRED); - - ExpectParseFailureForProto( - cat( tag(field->number(), wire_type), incomplete ), - "PrematureEofInsideKnownNonRepeatedValue" + type_name, REQUIRED); - - ExpectParseFailureForProto( - cat( tag(rep_field->number(), wire_type), incomplete ), - "PrematureEofInsideKnownRepeatedValue" + type_name, REQUIRED); - - ExpectParseFailureForProto( - cat( tag(UNKNOWN_FIELD, wire_type), incomplete ), - "PrematureEofInsideUnknownValue" + type_name, REQUIRED); - - if (wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { - ExpectParseFailureForProto( - cat( tag(field->number(), wire_type), varint(1) ), - "PrematureEofInDelimitedDataForKnownNonRepeatedValue" + type_name, - REQUIRED); - - ExpectParseFailureForProto( - cat( tag(rep_field->number(), wire_type), varint(1) ), - "PrematureEofInDelimitedDataForKnownRepeatedValue" + type_name, - REQUIRED); - - // EOF in the middle of delimited data for unknown value. - ExpectParseFailureForProto( - cat( tag(UNKNOWN_FIELD, wire_type), varint(1) ), - "PrematureEofInDelimitedDataForUnknownValue" + type_name, REQUIRED); - - if (type == FieldDescriptor::TYPE_MESSAGE) { - // Submessage ends in the middle of a value. - string incomplete_submsg = - cat( tag(WireFormatLite::TYPE_INT32, WireFormatLite::WIRETYPE_VARINT), - incompletes[WireFormatLite::WIRETYPE_VARINT] ); - ExpectHardParseFailureForProto( - cat( tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - varint(incomplete_submsg.size()), - incomplete_submsg ), - "PrematureEofInSubmessageValue" + type_name, REQUIRED); - } - } else if (type != FieldDescriptor::TYPE_GROUP) { - // Non-delimited, non-group: eligible for packing. + string serialized_request; + string serialized_response; + request.SerializeToString(&serialized_request); - // Packed region ends in the middle of a value. - ExpectHardParseFailureForProto( - cat(tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - varint(incomplete.size()), incomplete), - "PrematureEofInPackedFieldValue" + type_name, REQUIRED); + runner_->RunTest(test_name, serialized_request, &serialized_response); - // EOF in the middle of packed region. - ExpectParseFailureForProto( - cat(tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - varint(1)), - "PrematureEofInPackedField" + type_name, REQUIRED); + if (!response->ParseFromString(serialized_response)) { + response->Clear(); + response->set_runtime_error("response proto could not be parsed."); } -} -void ConformanceTestSuite::TestValidDataForType( - FieldDescriptor::Type type, - std::vector> values) { - for (int isProto3 = 0; isProto3 < 2; isProto3++) { - const string type_name = - UpperCase(string(".") + FieldDescriptor::TypeName(type)); - WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( - static_cast(type)); - const FieldDescriptor* field = GetFieldForType(type, false, isProto3); - const FieldDescriptor* rep_field = GetFieldForType(type, true, isProto3); - - RunValidProtobufTest("ValidDataScalar" + type_name, REQUIRED, - cat(tag(field->number(), wire_type), values[0].first), - field->name() + ": " + values[0].second, isProto3); - - string proto; - string text = field->name() + ": " + values.back().second; - for (size_t i = 0; i < values.size(); i++) { - proto += cat(tag(field->number(), wire_type), values[i].first); - } - RunValidProtobufTest("RepeatedScalarSelectsLast" + type_name, REQUIRED, - proto, text, isProto3); - - proto.clear(); - text.clear(); - - for (size_t i = 0; i < values.size(); i++) { - proto += cat(tag(rep_field->number(), wire_type), values[i].first); - text += rep_field->name() + ": " + values[i].second + " "; - } - RunValidProtobufTest("ValidDataRepeated" + type_name, REQUIRED, - proto, text, isProto3); + if (verbose_) { + StringAppendF(&output_, + "conformance test: name=%s, request=%s, response=%s\n", + test_name.c_str(), + request.ShortDebugString().c_str(), + response->ShortDebugString().c_str()); } } -void ConformanceTestSuite::SetFailureList(const string& filename, - const vector& failure_list) { - failure_list_filename_ = filename; - expected_to_fail_.clear(); - std::copy(failure_list.begin(), failure_list.end(), - std::inserter(expected_to_fail_, expected_to_fail_.end())); -} - -bool ConformanceTestSuite::CheckSetEmpty(const std::set& set_to_check, - const std::string& write_to_file, - const std::string& msg) { +bool ConformanceTestSuite::CheckSetEmpty( + const std::set& set_to_check, + const std::string& write_to_file, + const std::string& msg) { if (set_to_check.empty()) { return true; } else { @@ -757,62 +366,32 @@ bool ConformanceTestSuite::CheckSetEmpty(const std::set& set_to_check, } } -// TODO: proto2? -void ConformanceTestSuite::TestIllegalTags() { - // field num 0 is illegal - string nullfield[] = { - "\1DEADBEEF", - "\2\1\1", - "\3\4", - "\5DEAD" - }; - for (int i = 0; i < 4; i++) { - string name = "IllegalZeroFieldNum_Case_0"; - name.back() += i; - ExpectParseFailureForProto(nullfield[i], name, REQUIRED); +string ConformanceTestSuite::WireFormatToString( + WireFormat wire_format) { + switch (wire_format) { + case conformance::PROTOBUF: + return "PROTOBUF"; + case conformance::JSON: + return "JSON"; + case conformance::JSPB: + return "JSPB"; + case conformance::TEXT_FORMAT: + return "TEXT_FORMAT"; + case conformance::UNSPECIFIED: + return "UNSPECIFIED"; + default: + GOOGLE_LOG(FATAL) << "unknown wire type: " << wire_format; } + return ""; } -template -void ConformanceTestSuite::TestOneofMessage (MessageType &message, - bool isProto3) { - message.set_oneof_uint32(0); - RunValidProtobufTestWithMessage( - "OneofZeroUint32", RECOMMENDED, &message, "oneof_uint32: 0", isProto3); - message.mutable_oneof_nested_message()->set_a(0); - RunValidProtobufTestWithMessage( - "OneofZeroMessage", RECOMMENDED, &message, - isProto3 ? "oneof_nested_message: {}" : "oneof_nested_message: {a: 0}", - isProto3); - message.mutable_oneof_nested_message()->set_a(1); - RunValidProtobufTestWithMessage( - "OneofZeroMessageSetTwice", RECOMMENDED, &message, - "oneof_nested_message: {a: 1}", - isProto3); - message.set_oneof_string(""); - RunValidProtobufTestWithMessage( - "OneofZeroString", RECOMMENDED, &message, "oneof_string: \"\"", isProto3); - message.set_oneof_bytes(""); - RunValidProtobufTestWithMessage( - "OneofZeroBytes", RECOMMENDED, &message, "oneof_bytes: \"\"", isProto3); - message.set_oneof_bool(false); - RunValidProtobufTestWithMessage( - "OneofZeroBool", RECOMMENDED, &message, "oneof_bool: false", isProto3); - message.set_oneof_uint64(0); - RunValidProtobufTestWithMessage( - "OneofZeroUint64", RECOMMENDED, &message, "oneof_uint64: 0", isProto3); - message.set_oneof_float(0.0f); - RunValidProtobufTestWithMessage( - "OneofZeroFloat", RECOMMENDED, &message, "oneof_float: 0", isProto3); - message.set_oneof_double(0.0); - RunValidProtobufTestWithMessage( - "OneofZeroDouble", RECOMMENDED, &message, "oneof_double: 0", isProto3); - message.set_oneof_enum(MessageType::FOO); - RunValidProtobufTestWithMessage( - "OneofZeroEnum", RECOMMENDED, &message, "oneof_enum: FOO", isProto3); + +void ConformanceTestSuite::AddExpectedFailedTest(const std::string& test_name) { + expected_to_fail_.insert(test_name); } bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, - std::string* output) { + std::string* output, const string& filename, + conformance::FailureSet* failure_list) { runner_ = runner; successes_ = 0; expected_failures_ = 0; @@ -820,1623 +399,15 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, test_names_.clear(); unexpected_failing_tests_.clear(); unexpected_succeeding_tests_.clear(); - type_resolver_.reset(NewTypeResolverForDescriptorPool( - kTypeUrlPrefix, DescriptorPool::generated_pool())); - type_url_ = GetTypeUrl(TestAllTypesProto3::descriptor()); output_ = "\nCONFORMANCE TEST BEGIN ====================================\n\n"; - for (int i = 1; i <= FieldDescriptor::MAX_TYPE; i++) { - if (i == FieldDescriptor::TYPE_GROUP) continue; - TestPrematureEOFForType(static_cast(i)); - } - - TestIllegalTags(); - - int64 kInt64Min = -9223372036854775808ULL; - int64 kInt64Max = 9223372036854775807ULL; - uint64 kUint64Max = 18446744073709551615ULL; - int32 kInt32Max = 2147483647; - int32 kInt32Min = -2147483648; - uint32 kUint32Max = 4294967295UL; - - TestValidDataForType(FieldDescriptor::TYPE_DOUBLE, { - {dbl(0.1), "0.1"}, - {dbl(1.7976931348623157e+308), "1.7976931348623157e+308"}, - {dbl(2.22507385850720138309e-308), "2.22507385850720138309e-308"} - }); - TestValidDataForType(FieldDescriptor::TYPE_FLOAT, { - {flt(0.1), "0.1"}, - {flt(1.00000075e-36), "1.00000075e-36"}, - {flt(3.402823e+38), "3.402823e+38"}, // 3.40282347e+38 - {flt(1.17549435e-38f), "1.17549435e-38"} - }); - TestValidDataForType(FieldDescriptor::TYPE_INT64, { - {varint(12345), "12345"}, - {varint(kInt64Max), std::to_string(kInt64Max)}, - {varint(kInt64Min), std::to_string(kInt64Min)} - }); - TestValidDataForType(FieldDescriptor::TYPE_UINT64, { - {varint(12345), "12345"}, - {varint(kUint64Max), std::to_string(kUint64Max)}, - {varint(0), "0"} - }); - TestValidDataForType(FieldDescriptor::TYPE_INT32, { - {varint(12345), "12345"}, - {longvarint(12345, 2), "12345"}, - {longvarint(12345, 7), "12345"}, - {varint(kInt32Max), std::to_string(kInt32Max)}, - {varint(kInt32Min), std::to_string(kInt32Min)}, - {varint(1LL << 33), std::to_string(static_cast(1LL << 33))}, - {varint((1LL << 33) - 1), - std::to_string(static_cast((1LL << 33) - 1))}, - }); - TestValidDataForType(FieldDescriptor::TYPE_UINT32, { - {varint(12345), "12345"}, - {longvarint(12345, 2), "12345"}, - {longvarint(12345, 7), "12345"}, - {varint(kUint32Max), std::to_string(kUint32Max)}, // UINT32_MAX - {varint(0), "0"}, - {varint(1LL << 33), std::to_string(static_cast(1LL << 33))}, - {varint((1LL << 33) - 1), - std::to_string(static_cast((1LL << 33) - 1))}, - }); - TestValidDataForType(FieldDescriptor::TYPE_FIXED64, { - {u64(12345), "12345"}, - {u64(kUint64Max), std::to_string(kUint64Max)}, - {u64(0), "0"} - }); - TestValidDataForType(FieldDescriptor::TYPE_FIXED32, { - {u32(12345), "12345"}, - {u32(kUint32Max), std::to_string(kUint32Max)}, // UINT32_MAX - {u32(0), "0"} - }); - TestValidDataForType(FieldDescriptor::TYPE_SFIXED64, { - {u64(12345), "12345"}, - {u64(kInt64Max), std::to_string(kInt64Max)}, - {u64(kInt64Min), std::to_string(kInt64Min)} - }); - TestValidDataForType(FieldDescriptor::TYPE_SFIXED32, { - {u32(12345), "12345"}, - {u32(kInt32Max), std::to_string(kInt32Max)}, - {u32(kInt32Min), std::to_string(kInt32Min)} - }); - TestValidDataForType(FieldDescriptor::TYPE_BOOL, { - {varint(1), "true"}, - {varint(0), "false"}, - {varint(12345678), "true"} - }); - TestValidDataForType(FieldDescriptor::TYPE_SINT32, { - {zz32(12345), "12345"}, - {zz32(kInt32Max), std::to_string(kInt32Max)}, - {zz32(kInt32Min), std::to_string(kInt32Min)} - }); - TestValidDataForType(FieldDescriptor::TYPE_SINT64, { - {zz64(12345), "12345"}, - {zz64(kInt64Max), std::to_string(kInt64Max)}, - {zz64(kInt64Min), std::to_string(kInt64Min)} - }); - - // TODO(haberman): - // TestValidDataForType(FieldDescriptor::TYPE_STRING - // TestValidDataForType(FieldDescriptor::TYPE_GROUP - // TestValidDataForType(FieldDescriptor::TYPE_MESSAGE - // TestValidDataForType(FieldDescriptor::TYPE_BYTES - // TestValidDataForType(FieldDescriptor::TYPE_ENUM - - RunValidJsonTest("HelloWorld", REQUIRED, - "{\"optionalString\":\"Hello, World!\"}", - "optional_string: 'Hello, World!'"); - - // NOTE: The spec for JSON support is still being sorted out, these may not - // all be correct. - // Test field name conventions. - RunValidJsonTest( - "FieldNameInSnakeCase", REQUIRED, - R"({ - "fieldname1": 1, - "fieldName2": 2, - "FieldName3": 3, - "fieldName4": 4 - })", - R"( - fieldname1: 1 - field_name2: 2 - _field_name3: 3 - field__name4_: 4 - )"); - RunValidJsonTest( - "FieldNameWithNumbers", REQUIRED, - R"({ - "field0name5": 5, - "field0Name6": 6 - })", - R"( - field0name5: 5 - field_0_name6: 6 - )"); - RunValidJsonTest( - "FieldNameWithMixedCases", REQUIRED, - R"({ - "fieldName7": 7, - "FieldName8": 8, - "fieldName9": 9, - "FieldName10": 10, - "FIELDNAME11": 11, - "FIELDName12": 12 - })", - R"( - fieldName7: 7 - FieldName8: 8 - field_Name9: 9 - Field_Name10: 10 - FIELD_NAME11: 11 - FIELD_name12: 12 - )"); - RunValidJsonTest( - "FieldNameWithDoubleUnderscores", RECOMMENDED, - R"({ - "FieldName13": 13, - "FieldName14": 14, - "fieldName15": 15, - "fieldName16": 16, - "fieldName17": 17, - "FieldName18": 18 - })", - R"( - __field_name13: 13 - __Field_name14: 14 - field__name15: 15 - field__Name16: 16 - field_name17__: 17 - Field_name18__: 18 - )"); - // Using the original proto field name in JSON is also allowed. - RunValidJsonTest( - "OriginalProtoFieldName", REQUIRED, - R"({ - "fieldname1": 1, - "field_name2": 2, - "_field_name3": 3, - "field__name4_": 4, - "field0name5": 5, - "field_0_name6": 6, - "fieldName7": 7, - "FieldName8": 8, - "field_Name9": 9, - "Field_Name10": 10, - "FIELD_NAME11": 11, - "FIELD_name12": 12, - "__field_name13": 13, - "__Field_name14": 14, - "field__name15": 15, - "field__Name16": 16, - "field_name17__": 17, - "Field_name18__": 18 - })", - R"( - fieldname1: 1 - field_name2: 2 - _field_name3: 3 - field__name4_: 4 - field0name5: 5 - field_0_name6: 6 - fieldName7: 7 - FieldName8: 8 - field_Name9: 9 - Field_Name10: 10 - FIELD_NAME11: 11 - FIELD_name12: 12 - __field_name13: 13 - __Field_name14: 14 - field__name15: 15 - field__Name16: 16 - field_name17__: 17 - Field_name18__: 18 - )"); - // Field names can be escaped. - RunValidJsonTest( - "FieldNameEscaped", REQUIRED, - R"({"fieldn\u0061me1": 1})", - "fieldname1: 1"); - // String ends with escape character. - ExpectParseFailureForJson( - "StringEndsWithEscapeChar", RECOMMENDED, - "{\"optionalString\": \"abc\\"); - // Field names must be quoted (or it's not valid JSON). - ExpectParseFailureForJson( - "FieldNameNotQuoted", RECOMMENDED, - "{fieldname1: 1}"); - // Trailing comma is not allowed (not valid JSON). - ExpectParseFailureForJson( - "TrailingCommaInAnObject", RECOMMENDED, - R"({"fieldname1":1,})"); - ExpectParseFailureForJson( - "TrailingCommaInAnObjectWithSpace", RECOMMENDED, - R"({"fieldname1":1 ,})"); - ExpectParseFailureForJson( - "TrailingCommaInAnObjectWithSpaceCommaSpace", RECOMMENDED, - R"({"fieldname1":1 , })"); - ExpectParseFailureForJson( - "TrailingCommaInAnObjectWithNewlines", RECOMMENDED, - R"({ - "fieldname1":1, - })"); - // JSON doesn't support comments. - ExpectParseFailureForJson( - "JsonWithComments", RECOMMENDED, - R"({ - // This is a comment. - "fieldname1": 1 - })"); - // JSON spec says whitespace doesn't matter, so try a few spacings to be sure. - RunValidJsonTest( - "OneLineNoSpaces", RECOMMENDED, - "{\"optionalInt32\":1,\"optionalInt64\":2}", - R"( - optional_int32: 1 - optional_int64: 2 - )"); - RunValidJsonTest( - "OneLineWithSpaces", RECOMMENDED, - "{ \"optionalInt32\" : 1 , \"optionalInt64\" : 2 }", - R"( - optional_int32: 1 - optional_int64: 2 - )"); - RunValidJsonTest( - "MultilineNoSpaces", RECOMMENDED, - "{\n\"optionalInt32\"\n:\n1\n,\n\"optionalInt64\"\n:\n2\n}", - R"( - optional_int32: 1 - optional_int64: 2 - )"); - RunValidJsonTest( - "MultilineWithSpaces", RECOMMENDED, - "{\n \"optionalInt32\" : 1\n ,\n \"optionalInt64\" : 2\n}\n", - R"( - optional_int32: 1 - optional_int64: 2 - )"); - // Missing comma between key/value pairs. - ExpectParseFailureForJson( - "MissingCommaOneLine", RECOMMENDED, - "{ \"optionalInt32\": 1 \"optionalInt64\": 2 }"); - ExpectParseFailureForJson( - "MissingCommaMultiline", RECOMMENDED, - "{\n \"optionalInt32\": 1\n \"optionalInt64\": 2\n}"); - // Duplicated field names are not allowed. - ExpectParseFailureForJson( - "FieldNameDuplicate", RECOMMENDED, - R"({ - "optionalNestedMessage": {a: 1}, - "optionalNestedMessage": {} - })"); - ExpectParseFailureForJson( - "FieldNameDuplicateDifferentCasing1", RECOMMENDED, - R"({ - "optional_nested_message": {a: 1}, - "optionalNestedMessage": {} - })"); - ExpectParseFailureForJson( - "FieldNameDuplicateDifferentCasing2", RECOMMENDED, - R"({ - "optionalNestedMessage": {a: 1}, - "optional_nested_message": {} - })"); - // Serializers should use lowerCamelCase by default. - RunValidJsonTestWithValidator( - "FieldNameInLowerCamelCase", REQUIRED, - R"({ - "fieldname1": 1, - "fieldName2": 2, - "FieldName3": 3, - "fieldName4": 4 - })", - [](const Json::Value& value) { - return value.isMember("fieldname1") && - value.isMember("fieldName2") && - value.isMember("FieldName3") && - value.isMember("fieldName4"); - }); - RunValidJsonTestWithValidator( - "FieldNameWithNumbers", REQUIRED, - R"({ - "field0name5": 5, - "field0Name6": 6 - })", - [](const Json::Value& value) { - return value.isMember("field0name5") && - value.isMember("field0Name6"); - }); - RunValidJsonTestWithValidator( - "FieldNameWithMixedCases", REQUIRED, - R"({ - "fieldName7": 7, - "FieldName8": 8, - "fieldName9": 9, - "FieldName10": 10, - "FIELDNAME11": 11, - "FIELDName12": 12 - })", - [](const Json::Value& value) { - return value.isMember("fieldName7") && - value.isMember("FieldName8") && - value.isMember("fieldName9") && - value.isMember("FieldName10") && - value.isMember("FIELDNAME11") && - value.isMember("FIELDName12"); - }); - RunValidJsonTestWithValidator( - "FieldNameWithDoubleUnderscores", RECOMMENDED, - R"({ - "FieldName13": 13, - "FieldName14": 14, - "fieldName15": 15, - "fieldName16": 16, - "fieldName17": 17, - "FieldName18": 18 - })", - [](const Json::Value& value) { - return value.isMember("FieldName13") && - value.isMember("FieldName14") && - value.isMember("fieldName15") && - value.isMember("fieldName16") && - value.isMember("fieldName17") && - value.isMember("FieldName18"); - }); - - // Integer fields. - RunValidJsonTest( - "Int32FieldMaxValue", REQUIRED, - R"({"optionalInt32": 2147483647})", - "optional_int32: 2147483647"); - RunValidJsonTest( - "Int32FieldMinValue", REQUIRED, - R"({"optionalInt32": -2147483648})", - "optional_int32: -2147483648"); - RunValidJsonTest( - "Uint32FieldMaxValue", REQUIRED, - R"({"optionalUint32": 4294967295})", - "optional_uint32: 4294967295"); - RunValidJsonTest( - "Int64FieldMaxValue", REQUIRED, - R"({"optionalInt64": "9223372036854775807"})", - "optional_int64: 9223372036854775807"); - RunValidJsonTest( - "Int64FieldMinValue", REQUIRED, - R"({"optionalInt64": "-9223372036854775808"})", - "optional_int64: -9223372036854775808"); - RunValidJsonTest( - "Uint64FieldMaxValue", REQUIRED, - R"({"optionalUint64": "18446744073709551615"})", - "optional_uint64: 18446744073709551615"); - // While not the largest Int64, this is the largest - // Int64 which can be exactly represented within an - // IEEE-754 64-bit float, which is the expected level - // of interoperability guarantee. Larger values may - // work in some implementations, but should not be - // relied upon. - RunValidJsonTest( - "Int64FieldMaxValueNotQuoted", REQUIRED, - R"({"optionalInt64": 9223372036854774784})", - "optional_int64: 9223372036854774784"); - RunValidJsonTest( - "Int64FieldMinValueNotQuoted", REQUIRED, - R"({"optionalInt64": -9223372036854775808})", - "optional_int64: -9223372036854775808"); - // Largest interoperable Uint64; see comment above - // for Int64FieldMaxValueNotQuoted. - RunValidJsonTest( - "Uint64FieldMaxValueNotQuoted", REQUIRED, - R"({"optionalUint64": 18446744073709549568})", - "optional_uint64: 18446744073709549568"); - // Values can be represented as JSON strings. - RunValidJsonTest( - "Int32FieldStringValue", REQUIRED, - R"({"optionalInt32": "2147483647"})", - "optional_int32: 2147483647"); - RunValidJsonTest( - "Int32FieldStringValueEscaped", REQUIRED, - R"({"optionalInt32": "2\u003147483647"})", - "optional_int32: 2147483647"); - - // Parsers reject out-of-bound integer values. - ExpectParseFailureForJson( - "Int32FieldTooLarge", REQUIRED, - R"({"optionalInt32": 2147483648})"); - ExpectParseFailureForJson( - "Int32FieldTooSmall", REQUIRED, - R"({"optionalInt32": -2147483649})"); - ExpectParseFailureForJson( - "Uint32FieldTooLarge", REQUIRED, - R"({"optionalUint32": 4294967296})"); - ExpectParseFailureForJson( - "Int64FieldTooLarge", REQUIRED, - R"({"optionalInt64": "9223372036854775808"})"); - ExpectParseFailureForJson( - "Int64FieldTooSmall", REQUIRED, - R"({"optionalInt64": "-9223372036854775809"})"); - ExpectParseFailureForJson( - "Uint64FieldTooLarge", REQUIRED, - R"({"optionalUint64": "18446744073709551616"})"); - // Parser reject non-integer numeric values as well. - ExpectParseFailureForJson( - "Int32FieldNotInteger", REQUIRED, - R"({"optionalInt32": 0.5})"); - ExpectParseFailureForJson( - "Uint32FieldNotInteger", REQUIRED, - R"({"optionalUint32": 0.5})"); - ExpectParseFailureForJson( - "Int64FieldNotInteger", REQUIRED, - R"({"optionalInt64": "0.5"})"); - ExpectParseFailureForJson( - "Uint64FieldNotInteger", REQUIRED, - R"({"optionalUint64": "0.5"})"); - - // Integers but represented as float values are accepted. - RunValidJsonTest( - "Int32FieldFloatTrailingZero", REQUIRED, - R"({"optionalInt32": 100000.000})", - "optional_int32: 100000"); - RunValidJsonTest( - "Int32FieldExponentialFormat", REQUIRED, - R"({"optionalInt32": 1e5})", - "optional_int32: 100000"); - RunValidJsonTest( - "Int32FieldMaxFloatValue", REQUIRED, - R"({"optionalInt32": 2.147483647e9})", - "optional_int32: 2147483647"); - RunValidJsonTest( - "Int32FieldMinFloatValue", REQUIRED, - R"({"optionalInt32": -2.147483648e9})", - "optional_int32: -2147483648"); - RunValidJsonTest( - "Uint32FieldMaxFloatValue", REQUIRED, - R"({"optionalUint32": 4.294967295e9})", - "optional_uint32: 4294967295"); - - // Parser reject non-numeric values. - ExpectParseFailureForJson( - "Int32FieldNotNumber", REQUIRED, - R"({"optionalInt32": "3x3"})"); - ExpectParseFailureForJson( - "Uint32FieldNotNumber", REQUIRED, - R"({"optionalUint32": "3x3"})"); - ExpectParseFailureForJson( - "Int64FieldNotNumber", REQUIRED, - R"({"optionalInt64": "3x3"})"); - ExpectParseFailureForJson( - "Uint64FieldNotNumber", REQUIRED, - R"({"optionalUint64": "3x3"})"); - // JSON does not allow "+" on numric values. - ExpectParseFailureForJson( - "Int32FieldPlusSign", REQUIRED, - R"({"optionalInt32": +1})"); - // JSON doesn't allow leading 0s. - ExpectParseFailureForJson( - "Int32FieldLeadingZero", REQUIRED, - R"({"optionalInt32": 01})"); - ExpectParseFailureForJson( - "Int32FieldNegativeWithLeadingZero", REQUIRED, - R"({"optionalInt32": -01})"); - // String values must follow the same syntax rule. Specifically leading - // or trailing spaces are not allowed. - ExpectParseFailureForJson( - "Int32FieldLeadingSpace", REQUIRED, - R"({"optionalInt32": " 1"})"); - ExpectParseFailureForJson( - "Int32FieldTrailingSpace", REQUIRED, - R"({"optionalInt32": "1 "})"); - - // 64-bit values are serialized as strings. - RunValidJsonTestWithValidator( - "Int64FieldBeString", RECOMMENDED, - R"({"optionalInt64": 1})", - [](const Json::Value& value) { - return value["optionalInt64"].type() == Json::stringValue && - value["optionalInt64"].asString() == "1"; - }); - RunValidJsonTestWithValidator( - "Uint64FieldBeString", RECOMMENDED, - R"({"optionalUint64": 1})", - [](const Json::Value& value) { - return value["optionalUint64"].type() == Json::stringValue && - value["optionalUint64"].asString() == "1"; - }); - - // Bool fields. - RunValidJsonTest( - "BoolFieldTrue", REQUIRED, - R"({"optionalBool":true})", - "optional_bool: true"); - RunValidJsonTest( - "BoolFieldFalse", REQUIRED, - R"({"optionalBool":false})", - "optional_bool: false"); - - // Other forms are not allowed. - ExpectParseFailureForJson( - "BoolFieldIntegerZero", RECOMMENDED, - R"({"optionalBool":0})"); - ExpectParseFailureForJson( - "BoolFieldIntegerOne", RECOMMENDED, - R"({"optionalBool":1})"); - ExpectParseFailureForJson( - "BoolFieldCamelCaseTrue", RECOMMENDED, - R"({"optionalBool":True})"); - ExpectParseFailureForJson( - "BoolFieldCamelCaseFalse", RECOMMENDED, - R"({"optionalBool":False})"); - ExpectParseFailureForJson( - "BoolFieldAllCapitalTrue", RECOMMENDED, - R"({"optionalBool":TRUE})"); - ExpectParseFailureForJson( - "BoolFieldAllCapitalFalse", RECOMMENDED, - R"({"optionalBool":FALSE})"); - ExpectParseFailureForJson( - "BoolFieldDoubleQuotedTrue", RECOMMENDED, - R"({"optionalBool":"true"})"); - ExpectParseFailureForJson( - "BoolFieldDoubleQuotedFalse", RECOMMENDED, - R"({"optionalBool":"false"})"); - - // Float fields. - RunValidJsonTest( - "FloatFieldMinPositiveValue", REQUIRED, - R"({"optionalFloat": 1.175494e-38})", - "optional_float: 1.175494e-38"); - RunValidJsonTest( - "FloatFieldMaxNegativeValue", REQUIRED, - R"({"optionalFloat": -1.175494e-38})", - "optional_float: -1.175494e-38"); - RunValidJsonTest( - "FloatFieldMaxPositiveValue", REQUIRED, - R"({"optionalFloat": 3.402823e+38})", - "optional_float: 3.402823e+38"); - RunValidJsonTest( - "FloatFieldMinNegativeValue", REQUIRED, - R"({"optionalFloat": 3.402823e+38})", - "optional_float: 3.402823e+38"); - // Values can be quoted. - RunValidJsonTest( - "FloatFieldQuotedValue", REQUIRED, - R"({"optionalFloat": "1"})", - "optional_float: 1"); - // Special values. - RunValidJsonTest( - "FloatFieldNan", REQUIRED, - R"({"optionalFloat": "NaN"})", - "optional_float: nan"); - RunValidJsonTest( - "FloatFieldInfinity", REQUIRED, - R"({"optionalFloat": "Infinity"})", - "optional_float: inf"); - RunValidJsonTest( - "FloatFieldNegativeInfinity", REQUIRED, - R"({"optionalFloat": "-Infinity"})", - "optional_float: -inf"); - // Non-cannonical Nan will be correctly normalized. - { - TestAllTypesProto3 message; - // IEEE floating-point standard 32-bit quiet NaN: - // 0111 1111 1xxx xxxx xxxx xxxx xxxx xxxx - message.set_optional_float( - WireFormatLite::DecodeFloat(0x7FA12345)); - RunValidJsonTestWithProtobufInput( - "FloatFieldNormalizeQuietNan", REQUIRED, message, - "optional_float: nan"); - // IEEE floating-point standard 64-bit signaling NaN: - // 1111 1111 1xxx xxxx xxxx xxxx xxxx xxxx - message.set_optional_float( - WireFormatLite::DecodeFloat(0xFFB54321)); - RunValidJsonTestWithProtobufInput( - "FloatFieldNormalizeSignalingNan", REQUIRED, message, - "optional_float: nan"); - } - - // Special values must be quoted. - ExpectParseFailureForJson( - "FloatFieldNanNotQuoted", RECOMMENDED, - R"({"optionalFloat": NaN})"); - ExpectParseFailureForJson( - "FloatFieldInfinityNotQuoted", RECOMMENDED, - R"({"optionalFloat": Infinity})"); - ExpectParseFailureForJson( - "FloatFieldNegativeInfinityNotQuoted", RECOMMENDED, - R"({"optionalFloat": -Infinity})"); - // Parsers should reject out-of-bound values. - ExpectParseFailureForJson( - "FloatFieldTooSmall", REQUIRED, - R"({"optionalFloat": -3.502823e+38})"); - ExpectParseFailureForJson( - "FloatFieldTooLarge", REQUIRED, - R"({"optionalFloat": 3.502823e+38})"); - - // Double fields. - RunValidJsonTest( - "DoubleFieldMinPositiveValue", REQUIRED, - R"({"optionalDouble": 2.22507e-308})", - "optional_double: 2.22507e-308"); - RunValidJsonTest( - "DoubleFieldMaxNegativeValue", REQUIRED, - R"({"optionalDouble": -2.22507e-308})", - "optional_double: -2.22507e-308"); - RunValidJsonTest( - "DoubleFieldMaxPositiveValue", REQUIRED, - R"({"optionalDouble": 1.79769e+308})", - "optional_double: 1.79769e+308"); - RunValidJsonTest( - "DoubleFieldMinNegativeValue", REQUIRED, - R"({"optionalDouble": -1.79769e+308})", - "optional_double: -1.79769e+308"); - // Values can be quoted. - RunValidJsonTest( - "DoubleFieldQuotedValue", REQUIRED, - R"({"optionalDouble": "1"})", - "optional_double: 1"); - // Speical values. - RunValidJsonTest( - "DoubleFieldNan", REQUIRED, - R"({"optionalDouble": "NaN"})", - "optional_double: nan"); - RunValidJsonTest( - "DoubleFieldInfinity", REQUIRED, - R"({"optionalDouble": "Infinity"})", - "optional_double: inf"); - RunValidJsonTest( - "DoubleFieldNegativeInfinity", REQUIRED, - R"({"optionalDouble": "-Infinity"})", - "optional_double: -inf"); - // Non-cannonical Nan will be correctly normalized. - { - TestAllTypesProto3 message; - message.set_optional_double( - WireFormatLite::DecodeDouble(0x7FFA123456789ABCLL)); - RunValidJsonTestWithProtobufInput( - "DoubleFieldNormalizeQuietNan", REQUIRED, message, - "optional_double: nan"); - message.set_optional_double( - WireFormatLite::DecodeDouble(0xFFFBCBA987654321LL)); - RunValidJsonTestWithProtobufInput( - "DoubleFieldNormalizeSignalingNan", REQUIRED, message, - "optional_double: nan"); + failure_list_filename_ = filename; + expected_to_fail_.clear(); + for (const string& failure : failure_list->failure()) { + AddExpectedFailedTest(failure); } - - // Special values must be quoted. - ExpectParseFailureForJson( - "DoubleFieldNanNotQuoted", RECOMMENDED, - R"({"optionalDouble": NaN})"); - ExpectParseFailureForJson( - "DoubleFieldInfinityNotQuoted", RECOMMENDED, - R"({"optionalDouble": Infinity})"); - ExpectParseFailureForJson( - "DoubleFieldNegativeInfinityNotQuoted", RECOMMENDED, - R"({"optionalDouble": -Infinity})"); - - // Parsers should reject out-of-bound values. - ExpectParseFailureForJson( - "DoubleFieldTooSmall", REQUIRED, - R"({"optionalDouble": -1.89769e+308})"); - ExpectParseFailureForJson( - "DoubleFieldTooLarge", REQUIRED, - R"({"optionalDouble": +1.89769e+308})"); - - // Enum fields. - RunValidJsonTest( - "EnumField", REQUIRED, - R"({"optionalNestedEnum": "FOO"})", - "optional_nested_enum: FOO"); - // Enum values must be represented as strings. - ExpectParseFailureForJson( - "EnumFieldNotQuoted", REQUIRED, - R"({"optionalNestedEnum": FOO})"); - // Numeric values are allowed. - RunValidJsonTest( - "EnumFieldNumericValueZero", REQUIRED, - R"({"optionalNestedEnum": 0})", - "optional_nested_enum: FOO"); - RunValidJsonTest( - "EnumFieldNumericValueNonZero", REQUIRED, - R"({"optionalNestedEnum": 1})", - "optional_nested_enum: BAR"); - // Unknown enum values are represented as numeric values. - RunValidJsonTestWithValidator( - "EnumFieldUnknownValue", REQUIRED, - R"({"optionalNestedEnum": 123})", - [](const Json::Value& value) { - return value["optionalNestedEnum"].type() == Json::intValue && - value["optionalNestedEnum"].asInt() == 123; - }); - - // String fields. - RunValidJsonTest( - "StringField", REQUIRED, - R"({"optionalString": "Hello world!"})", - "optional_string: \"Hello world!\""); - RunValidJsonTest( - "StringFieldUnicode", REQUIRED, - // Google in Chinese. - R"({"optionalString": "谷歌"})", - R"(optional_string: "谷歌")"); - RunValidJsonTest( - "StringFieldEscape", REQUIRED, - R"({"optionalString": "\"\\\/\b\f\n\r\t"})", - R"(optional_string: "\"\\/\b\f\n\r\t")"); - RunValidJsonTest( - "StringFieldUnicodeEscape", REQUIRED, - R"({"optionalString": "\u8C37\u6B4C"})", - R"(optional_string: "谷歌")"); - RunValidJsonTest( - "StringFieldUnicodeEscapeWithLowercaseHexLetters", REQUIRED, - R"({"optionalString": "\u8c37\u6b4c"})", - R"(optional_string: "谷歌")"); - RunValidJsonTest( - "StringFieldSurrogatePair", REQUIRED, - // The character is an emoji: grinning face with smiling eyes. 😁 - R"({"optionalString": "\uD83D\uDE01"})", - R"(optional_string: "\xF0\x9F\x98\x81")"); - - // Unicode escapes must start with "\u" (lowercase u). - ExpectParseFailureForJson( - "StringFieldUppercaseEscapeLetter", RECOMMENDED, - R"({"optionalString": "\U8C37\U6b4C"})"); - ExpectParseFailureForJson( - "StringFieldInvalidEscape", RECOMMENDED, - R"({"optionalString": "\uXXXX\u6B4C"})"); - ExpectParseFailureForJson( - "StringFieldUnterminatedEscape", RECOMMENDED, - R"({"optionalString": "\u8C3"})"); - ExpectParseFailureForJson( - "StringFieldUnpairedHighSurrogate", RECOMMENDED, - R"({"optionalString": "\uD800"})"); - ExpectParseFailureForJson( - "StringFieldUnpairedLowSurrogate", RECOMMENDED, - R"({"optionalString": "\uDC00"})"); - ExpectParseFailureForJson( - "StringFieldSurrogateInWrongOrder", RECOMMENDED, - R"({"optionalString": "\uDE01\uD83D"})"); - ExpectParseFailureForJson( - "StringFieldNotAString", REQUIRED, - R"({"optionalString": 12345})"); - - // Bytes fields. - RunValidJsonTest( - "BytesField", REQUIRED, - R"({"optionalBytes": "AQI="})", - R"(optional_bytes: "\x01\x02")"); - RunValidJsonTest( - "BytesFieldBase64Url", RECOMMENDED, - R"({"optionalBytes": "-_"})", - R"(optional_bytes: "\xfb")"); - - // Message fields. - RunValidJsonTest( - "MessageField", REQUIRED, - R"({"optionalNestedMessage": {"a": 1234}})", - "optional_nested_message: {a: 1234}"); - - // Oneof fields. - ExpectParseFailureForJson( - "OneofFieldDuplicate", REQUIRED, - R"({"oneofUint32": 1, "oneofString": "test"})"); - // Ensure zero values for oneof make it out/backs. - TestAllTypesProto3 messageProto3; - TestAllTypesProto2 messageProto2; - TestOneofMessage(messageProto3, true); - TestOneofMessage(messageProto2, false); - RunValidJsonTest( - "OneofZeroUint32", RECOMMENDED, - R"({"oneofUint32": 0})", "oneof_uint32: 0"); - RunValidJsonTest( - "OneofZeroMessage", RECOMMENDED, - R"({"oneofNestedMessage": {}})", "oneof_nested_message: {}"); - RunValidJsonTest( - "OneofZeroString", RECOMMENDED, - R"({"oneofString": ""})", "oneof_string: \"\""); - RunValidJsonTest( - "OneofZeroBytes", RECOMMENDED, - R"({"oneofBytes": ""})", "oneof_bytes: \"\""); - RunValidJsonTest( - "OneofZeroBool", RECOMMENDED, - R"({"oneofBool": false})", "oneof_bool: false"); - RunValidJsonTest( - "OneofZeroUint64", RECOMMENDED, - R"({"oneofUint64": 0})", "oneof_uint64: 0"); - RunValidJsonTest( - "OneofZeroFloat", RECOMMENDED, - R"({"oneofFloat": 0.0})", "oneof_float: 0"); - RunValidJsonTest( - "OneofZeroDouble", RECOMMENDED, - R"({"oneofDouble": 0.0})", "oneof_double: 0"); - RunValidJsonTest( - "OneofZeroEnum", RECOMMENDED, - R"({"oneofEnum":"FOO"})", "oneof_enum: FOO"); - - // Repeated fields. - RunValidJsonTest( - "PrimitiveRepeatedField", REQUIRED, - R"({"repeatedInt32": [1, 2, 3, 4]})", - "repeated_int32: [1, 2, 3, 4]"); - RunValidJsonTest( - "EnumRepeatedField", REQUIRED, - R"({"repeatedNestedEnum": ["FOO", "BAR", "BAZ"]})", - "repeated_nested_enum: [FOO, BAR, BAZ]"); - RunValidJsonTest( - "StringRepeatedField", REQUIRED, - R"({"repeatedString": ["Hello", "world"]})", - R"(repeated_string: ["Hello", "world"])"); - RunValidJsonTest( - "BytesRepeatedField", REQUIRED, - R"({"repeatedBytes": ["AAEC", "AQI="]})", - R"(repeated_bytes: ["\x00\x01\x02", "\x01\x02"])"); - RunValidJsonTest( - "MessageRepeatedField", REQUIRED, - R"({"repeatedNestedMessage": [{"a": 1234}, {"a": 5678}]})", - "repeated_nested_message: {a: 1234}" - "repeated_nested_message: {a: 5678}"); - - // Repeated field elements are of incorrect type. - ExpectParseFailureForJson( - "RepeatedFieldWrongElementTypeExpectingIntegersGotBool", REQUIRED, - R"({"repeatedInt32": [1, false, 3, 4]})"); - ExpectParseFailureForJson( - "RepeatedFieldWrongElementTypeExpectingIntegersGotString", REQUIRED, - R"({"repeatedInt32": [1, 2, "name", 4]})"); - ExpectParseFailureForJson( - "RepeatedFieldWrongElementTypeExpectingIntegersGotMessage", REQUIRED, - R"({"repeatedInt32": [1, 2, 3, {"a": 4}]})"); - ExpectParseFailureForJson( - "RepeatedFieldWrongElementTypeExpectingStringsGotInt", REQUIRED, - R"({"repeatedString": ["1", 2, "3", "4"]})"); - ExpectParseFailureForJson( - "RepeatedFieldWrongElementTypeExpectingStringsGotBool", REQUIRED, - R"({"repeatedString": ["1", "2", false, "4"]})"); - ExpectParseFailureForJson( - "RepeatedFieldWrongElementTypeExpectingStringsGotMessage", REQUIRED, - R"({"repeatedString": ["1", 2, "3", {"a": 4}]})"); - ExpectParseFailureForJson( - "RepeatedFieldWrongElementTypeExpectingMessagesGotInt", REQUIRED, - R"({"repeatedNestedMessage": [{"a": 1}, 2]})"); - ExpectParseFailureForJson( - "RepeatedFieldWrongElementTypeExpectingMessagesGotBool", REQUIRED, - R"({"repeatedNestedMessage": [{"a": 1}, false]})"); - ExpectParseFailureForJson( - "RepeatedFieldWrongElementTypeExpectingMessagesGotString", REQUIRED, - R"({"repeatedNestedMessage": [{"a": 1}, "2"]})"); - // Trailing comma in the repeated field is not allowed. - ExpectParseFailureForJson( - "RepeatedFieldTrailingComma", RECOMMENDED, - R"({"repeatedInt32": [1, 2, 3, 4,]})"); - ExpectParseFailureForJson( - "RepeatedFieldTrailingCommaWithSpace", RECOMMENDED, - "{\"repeatedInt32\": [1, 2, 3, 4 ,]}"); - ExpectParseFailureForJson( - "RepeatedFieldTrailingCommaWithSpaceCommaSpace", RECOMMENDED, - "{\"repeatedInt32\": [1, 2, 3, 4 , ]}"); - ExpectParseFailureForJson( - "RepeatedFieldTrailingCommaWithNewlines", RECOMMENDED, - "{\"repeatedInt32\": [\n 1,\n 2,\n 3,\n 4,\n]}"); - - // Map fields. - RunValidJsonTest( - "Int32MapField", REQUIRED, - R"({"mapInt32Int32": {"1": 2, "3": 4}})", - "map_int32_int32: {key: 1 value: 2}" - "map_int32_int32: {key: 3 value: 4}"); - ExpectParseFailureForJson( - "Int32MapFieldKeyNotQuoted", RECOMMENDED, - R"({"mapInt32Int32": {1: 2, 3: 4}})"); - RunValidJsonTest( - "Uint32MapField", REQUIRED, - R"({"mapUint32Uint32": {"1": 2, "3": 4}})", - "map_uint32_uint32: {key: 1 value: 2}" - "map_uint32_uint32: {key: 3 value: 4}"); - ExpectParseFailureForJson( - "Uint32MapFieldKeyNotQuoted", RECOMMENDED, - R"({"mapUint32Uint32": {1: 2, 3: 4}})"); - RunValidJsonTest( - "Int64MapField", REQUIRED, - R"({"mapInt64Int64": {"1": 2, "3": 4}})", - "map_int64_int64: {key: 1 value: 2}" - "map_int64_int64: {key: 3 value: 4}"); - ExpectParseFailureForJson( - "Int64MapFieldKeyNotQuoted", RECOMMENDED, - R"({"mapInt64Int64": {1: 2, 3: 4}})"); - RunValidJsonTest( - "Uint64MapField", REQUIRED, - R"({"mapUint64Uint64": {"1": 2, "3": 4}})", - "map_uint64_uint64: {key: 1 value: 2}" - "map_uint64_uint64: {key: 3 value: 4}"); - ExpectParseFailureForJson( - "Uint64MapFieldKeyNotQuoted", RECOMMENDED, - R"({"mapUint64Uint64": {1: 2, 3: 4}})"); - RunValidJsonTest( - "BoolMapField", REQUIRED, - R"({"mapBoolBool": {"true": true, "false": false}})", - "map_bool_bool: {key: true value: true}" - "map_bool_bool: {key: false value: false}"); - ExpectParseFailureForJson( - "BoolMapFieldKeyNotQuoted", RECOMMENDED, - R"({"mapBoolBool": {true: true, false: false}})"); - RunValidJsonTest( - "MessageMapField", REQUIRED, - R"({ - "mapStringNestedMessage": { - "hello": {"a": 1234}, - "world": {"a": 5678} - } - })", - R"( - map_string_nested_message: { - key: "hello" - value: {a: 1234} - } - map_string_nested_message: { - key: "world" - value: {a: 5678} - } - )"); - // Since Map keys are represented as JSON strings, escaping should be allowed. - RunValidJsonTest( - "Int32MapEscapedKey", REQUIRED, - R"({"mapInt32Int32": {"\u0031": 2}})", - "map_int32_int32: {key: 1 value: 2}"); - RunValidJsonTest( - "Int64MapEscapedKey", REQUIRED, - R"({"mapInt64Int64": {"\u0031": 2}})", - "map_int64_int64: {key: 1 value: 2}"); - RunValidJsonTest( - "BoolMapEscapedKey", REQUIRED, - R"({"mapBoolBool": {"tr\u0075e": true}})", - "map_bool_bool: {key: true value: true}"); - - // "null" is accepted for all fields types. - RunValidJsonTest( - "AllFieldAcceptNull", REQUIRED, - R"({ - "optionalInt32": null, - "optionalInt64": null, - "optionalUint32": null, - "optionalUint64": null, - "optionalBool": null, - "optionalString": null, - "optionalBytes": null, - "optionalNestedEnum": null, - "optionalNestedMessage": null, - "repeatedInt32": null, - "repeatedInt64": null, - "repeatedUint32": null, - "repeatedUint64": null, - "repeatedBool": null, - "repeatedString": null, - "repeatedBytes": null, - "repeatedNestedEnum": null, - "repeatedNestedMessage": null, - "mapInt32Int32": null, - "mapBoolBool": null, - "mapStringNestedMessage": null - })", - ""); - - // Repeated field elements cannot be null. - ExpectParseFailureForJson( - "RepeatedFieldPrimitiveElementIsNull", RECOMMENDED, - R"({"repeatedInt32": [1, null, 2]})"); - ExpectParseFailureForJson( - "RepeatedFieldMessageElementIsNull", RECOMMENDED, - R"({"repeatedNestedMessage": [{"a":1}, null, {"a":2}]})"); - // Map field keys cannot be null. - ExpectParseFailureForJson( - "MapFieldKeyIsNull", RECOMMENDED, - R"({"mapInt32Int32": {null: 1}})"); - // Map field values cannot be null. - ExpectParseFailureForJson( - "MapFieldValueIsNull", RECOMMENDED, - R"({"mapInt32Int32": {"0": null}})"); - - // http://www.rfc-editor.org/rfc/rfc7159.txt says strings have to use double - // quotes. - ExpectParseFailureForJson( - "StringFieldSingleQuoteKey", RECOMMENDED, - R"({'optionalString': "Hello world!"})"); - ExpectParseFailureForJson( - "StringFieldSingleQuoteValue", RECOMMENDED, - R"({"optionalString": 'Hello world!'})"); - ExpectParseFailureForJson( - "StringFieldSingleQuoteBoth", RECOMMENDED, - R"({'optionalString': 'Hello world!'})"); - - // Wrapper types. - RunValidJsonTest( - "OptionalBoolWrapper", REQUIRED, - R"({"optionalBoolWrapper": false})", - "optional_bool_wrapper: {value: false}"); - RunValidJsonTest( - "OptionalInt32Wrapper", REQUIRED, - R"({"optionalInt32Wrapper": 0})", - "optional_int32_wrapper: {value: 0}"); - RunValidJsonTest( - "OptionalUint32Wrapper", REQUIRED, - R"({"optionalUint32Wrapper": 0})", - "optional_uint32_wrapper: {value: 0}"); - RunValidJsonTest( - "OptionalInt64Wrapper", REQUIRED, - R"({"optionalInt64Wrapper": 0})", - "optional_int64_wrapper: {value: 0}"); - RunValidJsonTest( - "OptionalUint64Wrapper", REQUIRED, - R"({"optionalUint64Wrapper": 0})", - "optional_uint64_wrapper: {value: 0}"); - RunValidJsonTest( - "OptionalFloatWrapper", REQUIRED, - R"({"optionalFloatWrapper": 0})", - "optional_float_wrapper: {value: 0}"); - RunValidJsonTest( - "OptionalDoubleWrapper", REQUIRED, - R"({"optionalDoubleWrapper": 0})", - "optional_double_wrapper: {value: 0}"); - RunValidJsonTest( - "OptionalStringWrapper", REQUIRED, - R"({"optionalStringWrapper": ""})", - R"(optional_string_wrapper: {value: ""})"); - RunValidJsonTest( - "OptionalBytesWrapper", REQUIRED, - R"({"optionalBytesWrapper": ""})", - R"(optional_bytes_wrapper: {value: ""})"); - RunValidJsonTest( - "OptionalWrapperTypesWithNonDefaultValue", REQUIRED, - R"({ - "optionalBoolWrapper": true, - "optionalInt32Wrapper": 1, - "optionalUint32Wrapper": 1, - "optionalInt64Wrapper": "1", - "optionalUint64Wrapper": "1", - "optionalFloatWrapper": 1, - "optionalDoubleWrapper": 1, - "optionalStringWrapper": "1", - "optionalBytesWrapper": "AQI=" - })", - R"( - optional_bool_wrapper: {value: true} - optional_int32_wrapper: {value: 1} - optional_uint32_wrapper: {value: 1} - optional_int64_wrapper: {value: 1} - optional_uint64_wrapper: {value: 1} - optional_float_wrapper: {value: 1} - optional_double_wrapper: {value: 1} - optional_string_wrapper: {value: "1"} - optional_bytes_wrapper: {value: "\x01\x02"} - )"); - RunValidJsonTest( - "RepeatedBoolWrapper", REQUIRED, - R"({"repeatedBoolWrapper": [true, false]})", - "repeated_bool_wrapper: {value: true}" - "repeated_bool_wrapper: {value: false}"); - RunValidJsonTest( - "RepeatedInt32Wrapper", REQUIRED, - R"({"repeatedInt32Wrapper": [0, 1]})", - "repeated_int32_wrapper: {value: 0}" - "repeated_int32_wrapper: {value: 1}"); - RunValidJsonTest( - "RepeatedUint32Wrapper", REQUIRED, - R"({"repeatedUint32Wrapper": [0, 1]})", - "repeated_uint32_wrapper: {value: 0}" - "repeated_uint32_wrapper: {value: 1}"); - RunValidJsonTest( - "RepeatedInt64Wrapper", REQUIRED, - R"({"repeatedInt64Wrapper": [0, 1]})", - "repeated_int64_wrapper: {value: 0}" - "repeated_int64_wrapper: {value: 1}"); - RunValidJsonTest( - "RepeatedUint64Wrapper", REQUIRED, - R"({"repeatedUint64Wrapper": [0, 1]})", - "repeated_uint64_wrapper: {value: 0}" - "repeated_uint64_wrapper: {value: 1}"); - RunValidJsonTest( - "RepeatedFloatWrapper", REQUIRED, - R"({"repeatedFloatWrapper": [0, 1]})", - "repeated_float_wrapper: {value: 0}" - "repeated_float_wrapper: {value: 1}"); - RunValidJsonTest( - "RepeatedDoubleWrapper", REQUIRED, - R"({"repeatedDoubleWrapper": [0, 1]})", - "repeated_double_wrapper: {value: 0}" - "repeated_double_wrapper: {value: 1}"); - RunValidJsonTest( - "RepeatedStringWrapper", REQUIRED, - R"({"repeatedStringWrapper": ["", "AQI="]})", - R"( - repeated_string_wrapper: {value: ""} - repeated_string_wrapper: {value: "AQI="} - )"); - RunValidJsonTest( - "RepeatedBytesWrapper", REQUIRED, - R"({"repeatedBytesWrapper": ["", "AQI="]})", - R"( - repeated_bytes_wrapper: {value: ""} - repeated_bytes_wrapper: {value: "\x01\x02"} - )"); - RunValidJsonTest( - "WrapperTypesWithNullValue", REQUIRED, - R"({ - "optionalBoolWrapper": null, - "optionalInt32Wrapper": null, - "optionalUint32Wrapper": null, - "optionalInt64Wrapper": null, - "optionalUint64Wrapper": null, - "optionalFloatWrapper": null, - "optionalDoubleWrapper": null, - "optionalStringWrapper": null, - "optionalBytesWrapper": null, - "repeatedBoolWrapper": null, - "repeatedInt32Wrapper": null, - "repeatedUint32Wrapper": null, - "repeatedInt64Wrapper": null, - "repeatedUint64Wrapper": null, - "repeatedFloatWrapper": null, - "repeatedDoubleWrapper": null, - "repeatedStringWrapper": null, - "repeatedBytesWrapper": null - })", - ""); - - // Duration - RunValidJsonTest( - "DurationMinValue", REQUIRED, - R"({"optionalDuration": "-315576000000.999999999s"})", - "optional_duration: {seconds: -315576000000 nanos: -999999999}"); - RunValidJsonTest( - "DurationMaxValue", REQUIRED, - R"({"optionalDuration": "315576000000.999999999s"})", - "optional_duration: {seconds: 315576000000 nanos: 999999999}"); - RunValidJsonTest( - "DurationRepeatedValue", REQUIRED, - R"({"repeatedDuration": ["1.5s", "-1.5s"]})", - "repeated_duration: {seconds: 1 nanos: 500000000}" - "repeated_duration: {seconds: -1 nanos: -500000000}"); - - ExpectParseFailureForJson( - "DurationMissingS", REQUIRED, - R"({"optionalDuration": "1"})"); - ExpectParseFailureForJson( - "DurationJsonInputTooSmall", REQUIRED, - R"({"optionalDuration": "-315576000001.000000000s"})"); - ExpectParseFailureForJson( - "DurationJsonInputTooLarge", REQUIRED, - R"({"optionalDuration": "315576000001.000000000s"})"); - ExpectSerializeFailureForJson( - "DurationProtoInputTooSmall", REQUIRED, - "optional_duration: {seconds: -315576000001 nanos: 0}"); - ExpectSerializeFailureForJson( - "DurationProtoInputTooLarge", REQUIRED, - "optional_duration: {seconds: 315576000001 nanos: 0}"); - - RunValidJsonTestWithValidator( - "DurationHasZeroFractionalDigit", RECOMMENDED, - R"({"optionalDuration": "1.000000000s"})", - [](const Json::Value& value) { - return value["optionalDuration"].asString() == "1s"; - }); - RunValidJsonTestWithValidator( - "DurationHas3FractionalDigits", RECOMMENDED, - R"({"optionalDuration": "1.010000000s"})", - [](const Json::Value& value) { - return value["optionalDuration"].asString() == "1.010s"; - }); - RunValidJsonTestWithValidator( - "DurationHas6FractionalDigits", RECOMMENDED, - R"({"optionalDuration": "1.000010000s"})", - [](const Json::Value& value) { - return value["optionalDuration"].asString() == "1.000010s"; - }); - RunValidJsonTestWithValidator( - "DurationHas9FractionalDigits", RECOMMENDED, - R"({"optionalDuration": "1.000000010s"})", - [](const Json::Value& value) { - return value["optionalDuration"].asString() == "1.000000010s"; - }); - - // Timestamp - RunValidJsonTest( - "TimestampMinValue", REQUIRED, - R"({"optionalTimestamp": "0001-01-01T00:00:00Z"})", - "optional_timestamp: {seconds: -62135596800}"); - RunValidJsonTest( - "TimestampMaxValue", REQUIRED, - R"({"optionalTimestamp": "9999-12-31T23:59:59.999999999Z"})", - "optional_timestamp: {seconds: 253402300799 nanos: 999999999}"); - RunValidJsonTest( - "TimestampRepeatedValue", REQUIRED, - R"({ - "repeatedTimestamp": [ - "0001-01-01T00:00:00Z", - "9999-12-31T23:59:59.999999999Z" - ] - })", - "repeated_timestamp: {seconds: -62135596800}" - "repeated_timestamp: {seconds: 253402300799 nanos: 999999999}"); - RunValidJsonTest( - "TimestampWithPositiveOffset", REQUIRED, - R"({"optionalTimestamp": "1970-01-01T08:00:00+08:00"})", - "optional_timestamp: {seconds: 0}"); - RunValidJsonTest( - "TimestampWithNegativeOffset", REQUIRED, - R"({"optionalTimestamp": "1969-12-31T16:00:00-08:00"})", - "optional_timestamp: {seconds: 0}"); - - ExpectParseFailureForJson( - "TimestampJsonInputTooSmall", REQUIRED, - R"({"optionalTimestamp": "0000-01-01T00:00:00Z"})"); - ExpectParseFailureForJson( - "TimestampJsonInputTooLarge", REQUIRED, - R"({"optionalTimestamp": "10000-01-01T00:00:00Z"})"); - ExpectParseFailureForJson( - "TimestampJsonInputMissingZ", REQUIRED, - R"({"optionalTimestamp": "0001-01-01T00:00:00"})"); - ExpectParseFailureForJson( - "TimestampJsonInputMissingT", REQUIRED, - R"({"optionalTimestamp": "0001-01-01 00:00:00Z"})"); - ExpectParseFailureForJson( - "TimestampJsonInputLowercaseZ", REQUIRED, - R"({"optionalTimestamp": "0001-01-01T00:00:00z"})"); - ExpectParseFailureForJson( - "TimestampJsonInputLowercaseT", REQUIRED, - R"({"optionalTimestamp": "0001-01-01t00:00:00Z"})"); - ExpectSerializeFailureForJson( - "TimestampProtoInputTooSmall", REQUIRED, - "optional_timestamp: {seconds: -62135596801}"); - ExpectSerializeFailureForJson( - "TimestampProtoInputTooLarge", REQUIRED, - "optional_timestamp: {seconds: 253402300800}"); - RunValidJsonTestWithValidator( - "TimestampZeroNormalized", RECOMMENDED, - R"({"optionalTimestamp": "1969-12-31T16:00:00-08:00"})", - [](const Json::Value& value) { - return value["optionalTimestamp"].asString() == - "1970-01-01T00:00:00Z"; - }); - RunValidJsonTestWithValidator( - "TimestampHasZeroFractionalDigit", RECOMMENDED, - R"({"optionalTimestamp": "1970-01-01T00:00:00.000000000Z"})", - [](const Json::Value& value) { - return value["optionalTimestamp"].asString() == - "1970-01-01T00:00:00Z"; - }); - RunValidJsonTestWithValidator( - "TimestampHas3FractionalDigits", RECOMMENDED, - R"({"optionalTimestamp": "1970-01-01T00:00:00.010000000Z"})", - [](const Json::Value& value) { - return value["optionalTimestamp"].asString() == - "1970-01-01T00:00:00.010Z"; - }); - RunValidJsonTestWithValidator( - "TimestampHas6FractionalDigits", RECOMMENDED, - R"({"optionalTimestamp": "1970-01-01T00:00:00.000010000Z"})", - [](const Json::Value& value) { - return value["optionalTimestamp"].asString() == - "1970-01-01T00:00:00.000010Z"; - }); - RunValidJsonTestWithValidator( - "TimestampHas9FractionalDigits", RECOMMENDED, - R"({"optionalTimestamp": "1970-01-01T00:00:00.000000010Z"})", - [](const Json::Value& value) { - return value["optionalTimestamp"].asString() == - "1970-01-01T00:00:00.000000010Z"; - }); - - // FieldMask - RunValidJsonTest( - "FieldMask", REQUIRED, - R"({"optionalFieldMask": "foo,barBaz"})", - R"(optional_field_mask: {paths: "foo" paths: "bar_baz"})"); - ExpectParseFailureForJson( - "FieldMaskInvalidCharacter", RECOMMENDED, - R"({"optionalFieldMask": "foo,bar_bar"})"); - ExpectSerializeFailureForJson( - "FieldMaskPathsDontRoundTrip", RECOMMENDED, - R"(optional_field_mask: {paths: "fooBar"})"); - ExpectSerializeFailureForJson( - "FieldMaskNumbersDontRoundTrip", RECOMMENDED, - R"(optional_field_mask: {paths: "foo_3_bar"})"); - ExpectSerializeFailureForJson( - "FieldMaskTooManyUnderscore", RECOMMENDED, - R"(optional_field_mask: {paths: "foo__bar"})"); - - // Struct - RunValidJsonTest( - "Struct", REQUIRED, - R"({ - "optionalStruct": { - "nullValue": null, - "intValue": 1234, - "boolValue": true, - "doubleValue": 1234.5678, - "stringValue": "Hello world!", - "listValue": [1234, "5678"], - "objectValue": { - "value": 0 - } - } - })", - R"( - optional_struct: { - fields: { - key: "nullValue" - value: {null_value: NULL_VALUE} - } - fields: { - key: "intValue" - value: {number_value: 1234} - } - fields: { - key: "boolValue" - value: {bool_value: true} - } - fields: { - key: "doubleValue" - value: {number_value: 1234.5678} - } - fields: { - key: "stringValue" - value: {string_value: "Hello world!"} - } - fields: { - key: "listValue" - value: { - list_value: { - values: { - number_value: 1234 - } - values: { - string_value: "5678" - } - } - } - } - fields: { - key: "objectValue" - value: { - struct_value: { - fields: { - key: "value" - value: { - number_value: 0 - } - } - } - } - } - } - )"); - // Value - RunValidJsonTest( - "ValueAcceptInteger", REQUIRED, - R"({"optionalValue": 1})", - "optional_value: { number_value: 1}"); - RunValidJsonTest( - "ValueAcceptFloat", REQUIRED, - R"({"optionalValue": 1.5})", - "optional_value: { number_value: 1.5}"); - RunValidJsonTest( - "ValueAcceptBool", REQUIRED, - R"({"optionalValue": false})", - "optional_value: { bool_value: false}"); - RunValidJsonTest( - "ValueAcceptNull", REQUIRED, - R"({"optionalValue": null})", - "optional_value: { null_value: NULL_VALUE}"); - RunValidJsonTest( - "ValueAcceptString", REQUIRED, - R"({"optionalValue": "hello"})", - R"(optional_value: { string_value: "hello"})"); - RunValidJsonTest( - "ValueAcceptList", REQUIRED, - R"({"optionalValue": [0, "hello"]})", - R"( - optional_value: { - list_value: { - values: { - number_value: 0 - } - values: { - string_value: "hello" - } - } - } - )"); - RunValidJsonTest( - "ValueAcceptObject", REQUIRED, - R"({"optionalValue": {"value": 1}})", - R"( - optional_value: { - struct_value: { - fields: { - key: "value" - value: { - number_value: 1 - } - } - } - } - )"); - - // Any - RunValidJsonTest( - "Any", REQUIRED, - R"({ - "optionalAny": { - "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3", - "optionalInt32": 12345 - } - })", - R"( - optional_any: { - [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { - optional_int32: 12345 - } - } - )"); - RunValidJsonTest( - "AnyNested", REQUIRED, - R"({ - "optionalAny": { - "@type": "type.googleapis.com/google.protobuf.Any", - "value": { - "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3", - "optionalInt32": 12345 - } - } - })", - R"( - optional_any: { - [type.googleapis.com/google.protobuf.Any] { - [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { - optional_int32: 12345 - } - } - } - )"); - // The special "@type" tag is not required to appear first. - RunValidJsonTest( - "AnyUnorderedTypeTag", REQUIRED, - R"({ - "optionalAny": { - "optionalInt32": 12345, - "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3" - } - })", - R"( - optional_any: { - [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { - optional_int32: 12345 - } - } - )"); - // Well-known types in Any. - RunValidJsonTest( - "AnyWithInt32ValueWrapper", REQUIRED, - R"({ - "optionalAny": { - "@type": "type.googleapis.com/google.protobuf.Int32Value", - "value": 12345 - } - })", - R"( - optional_any: { - [type.googleapis.com/google.protobuf.Int32Value] { - value: 12345 - } - } - )"); - RunValidJsonTest( - "AnyWithDuration", REQUIRED, - R"({ - "optionalAny": { - "@type": "type.googleapis.com/google.protobuf.Duration", - "value": "1.5s" - } - })", - R"( - optional_any: { - [type.googleapis.com/google.protobuf.Duration] { - seconds: 1 - nanos: 500000000 - } - } - )"); - RunValidJsonTest( - "AnyWithTimestamp", REQUIRED, - R"({ - "optionalAny": { - "@type": "type.googleapis.com/google.protobuf.Timestamp", - "value": "1970-01-01T00:00:00Z" - } - })", - R"( - optional_any: { - [type.googleapis.com/google.protobuf.Timestamp] { - seconds: 0 - nanos: 0 - } - } - )"); - RunValidJsonTest( - "AnyWithFieldMask", REQUIRED, - R"({ - "optionalAny": { - "@type": "type.googleapis.com/google.protobuf.FieldMask", - "value": "foo,barBaz" - } - })", - R"( - optional_any: { - [type.googleapis.com/google.protobuf.FieldMask] { - paths: ["foo", "bar_baz"] - } - } - )"); - RunValidJsonTest( - "AnyWithStruct", REQUIRED, - R"({ - "optionalAny": { - "@type": "type.googleapis.com/google.protobuf.Struct", - "value": { - "foo": 1 - } - } - })", - R"( - optional_any: { - [type.googleapis.com/google.protobuf.Struct] { - fields: { - key: "foo" - value: { - number_value: 1 - } - } - } - } - )"); - RunValidJsonTest( - "AnyWithValueForJsonObject", REQUIRED, - R"({ - "optionalAny": { - "@type": "type.googleapis.com/google.protobuf.Value", - "value": { - "foo": 1 - } - } - })", - R"( - optional_any: { - [type.googleapis.com/google.protobuf.Value] { - struct_value: { - fields: { - key: "foo" - value: { - number_value: 1 - } - } - } - } - } - )"); - RunValidJsonTest( - "AnyWithValueForInteger", REQUIRED, - R"({ - "optionalAny": { - "@type": "type.googleapis.com/google.protobuf.Value", - "value": 1 - } - })", - R"( - optional_any: { - [type.googleapis.com/google.protobuf.Value] { - number_value: 1 - } - } - )"); + RunSuiteImpl(); bool ok = true; if (!CheckSetEmpty(expected_to_fail_, "nonexistent_tests.txt", @@ -2472,8 +443,8 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, } StringAppendF(&output_, - "CONFORMANCE SUITE %s: %d successes, %d skipped, " - "%d expected failures, %d unexpected failures.\n", + "CONFORMANCE SUITE %s: %d successes, %zu skipped, " + "%d expected failures, %zu unexpected failures.\n", ok ? "PASSED" : "FAILED", successes_, skipped_.size(), expected_failures_, unexpected_failing_tests_.size()); StringAppendF(&output_, "\n"); diff --git a/conformance/conformance_test.h b/conformance/conformance_test.h index d1a822eba692e..76bd1bc3f1c99 100644 --- a/conformance/conformance_test.h +++ b/conformance/conformance_test.h @@ -40,11 +40,12 @@ #include #include -#include -#include -#include +#include -#include "third_party/jsoncpp/json.h" +#include +#include +#include +#include "conformance.pb.h" namespace conformance { class ConformanceRequest; @@ -60,6 +61,8 @@ class TestAllTypesProto3; namespace google { namespace protobuf { +class ConformanceTestSuite; + class ConformanceTestRunner { public: virtual ~ConformanceTestRunner() {} @@ -76,39 +79,81 @@ class ConformanceTestRunner { std::string* output) = 0; }; +// Test runner that spawns the process being tested and communicates with it +// over a pipe. +class ForkPipeRunner : public ConformanceTestRunner { + public: + // Note: Run() doesn't take ownership of the pointers inside suites. + static int Run(int argc, char *argv[], + const std::vector& suites); + + ForkPipeRunner(const std::string& executable, + const std::vector& executable_args) + : child_pid_(-1), + executable_(executable), + executable_args_(executable_args) {} + + explicit ForkPipeRunner(const std::string& executable) + : child_pid_(-1), executable_(executable) {} + + virtual ~ForkPipeRunner() {} + + void RunTest(const std::string& test_name, + const std::string& request, + std::string* response); + + private: + void SpawnTestProgram(); + + void CheckedWrite(int fd, const void *buf, size_t len); + bool TryRead(int fd, void *buf, size_t len); + void CheckedRead(int fd, void *buf, size_t len); + + int write_fd_; + int read_fd_; + pid_t child_pid_; + std::string executable_; + const std::vector executable_args_; + std::string current_test_name_; +}; + // Class representing the test suite itself. To run it, implement your own -// class derived from ConformanceTestRunner and then write code like: +// class derived from ConformanceTestRunner, class derived from +// ConformanceTestSuite and then write code like: +// +// class MyConformanceTestSuite : public ConformanceTestSuite { +// public: +// void RunSuiteImpl() { +// // INSERT ACTURAL TESTS. +// } +// }; // // class MyConformanceTestRunner : public ConformanceTestRunner { // public: +// static int Run(int argc, char *argv[], +// ConformanceTestSuite* suite); +// +// private: // virtual void RunTest(...) { // // INSERT YOUR FRAMEWORK-SPECIFIC CODE HERE. // } // }; // // int main() { -// MyConformanceTestRunner runner; -// google::protobuf::ConformanceTestSuite suite; -// -// std::string output; -// suite.RunSuite(&runner, &output); +// MyConformanceTestSuite suite; +// MyConformanceTestRunner::Run(argc, argv, &suite); // } // class ConformanceTestSuite { public: - ConformanceTestSuite() : verbose_(false), enforce_recommended_(false) {} + ConformanceTestSuite() + : verbose_(false), + enforce_recommended_(false), + failure_list_flag_name_("--failure_list") {} + virtual ~ConformanceTestSuite() {} void SetVerbose(bool verbose) { verbose_ = verbose; } - // Sets the list of tests that are expected to fail when RunSuite() is called. - // RunSuite() will fail unless the set of failing tests is exactly the same - // as this list. - // - // The filename here is *only* used to create/format useful error messages for - // how to update the failure list. We do NOT read this file at all. - void SetFailureList(const std::string& filename, - const std::vector& failure_list); - // Whether to require the testee to pass RECOMMENDED tests. By default failing // a RECOMMENDED test case will not fail the entire suite but will only // generated a warning. If this flag is set to true, RECOMMENDED tests will @@ -121,19 +166,30 @@ class ConformanceTestSuite { enforce_recommended_ = value; } + // Gets the flag name to the failure list file. + // By default, this would return --failure_list + std::string GetFailureListFlagName() { return failure_list_flag_name_; } + + void SetFailureListFlagName(const std::string& failure_list_flag_name) { + failure_list_flag_name_ = failure_list_flag_name; + } + // Run all the conformance tests against the given test runner. // Test output will be stored in "output". // // Returns true if the set of failing tests was exactly the same as the - // failure list. If SetFailureList() was not called, returns true if all - // tests passed. - bool RunSuite(ConformanceTestRunner* runner, std::string* output); + // failure list. + // The filename here is *only* used to create/format useful error messages for + // how to update the failure list. We do NOT read this file at all. + bool RunSuite(ConformanceTestRunner* runner, std::string* output, + const std::string& filename, + conformance::FailureSet* failure_list); - private: + protected: // Test cases are classified into a few categories: // REQUIRED: the test case must be passed for an implementation to be // interoperable with other implementations. For example, a - // parser implementaiton must accept both packed and unpacked + // parser implementation must accept both packed and unpacked // form of repeated primitive fields. // RECOMMENDED: the test case is not required for the implementation to // be interoperable with other implementations, but is @@ -146,83 +202,101 @@ class ConformanceTestSuite { REQUIRED = 0, RECOMMENDED = 1, }; - string ConformanceLevelToString(ConformanceLevel level); + + class ConformanceRequestSetting { + public: + ConformanceRequestSetting(ConformanceLevel level, + conformance::WireFormat input_format, + conformance::WireFormat output_format, + conformance::TestCategory test_category, + const Message& prototype_message, + const std::string& test_name, + const std::string& input); + virtual ~ConformanceRequestSetting() {} + + std::unique_ptr NewTestMessage() const; + + std::string GetTestName() const; + + const conformance::ConformanceRequest& GetRequest() const { + return request_; + } + + const ConformanceLevel GetLevel() const { + return level_; + } + + std::string ConformanceLevelToString(ConformanceLevel level) const; + + void SetPrintUnknownFields(bool print_unknown_fields) { + request_.set_print_unknown_fields(true); + } + + void SetPrototypeMessageForCompare(const Message& message) { + prototype_message_for_compare_.reset(message.New()); + } + + protected: + virtual std::string InputFormatString(conformance::WireFormat format) const; + virtual std::string OutputFormatString( + conformance::WireFormat format) const; + conformance::ConformanceRequest request_; + + private: + ConformanceLevel level_; + ::conformance::WireFormat input_format_; + ::conformance::WireFormat output_format_; + const Message& prototype_message_; + std::unique_ptr prototype_message_for_compare_; + std::string test_name_; + }; + + bool CheckSetEmpty(const std::set& set_to_check, + const std::string& write_to_file, const std::string& msg); + std::string WireFormatToString(conformance::WireFormat wire_format); + + // Parse payload in the response to the given message. Returns true on + // success. + virtual bool ParseResponse( + const conformance::ConformanceResponse& response, + const ConformanceRequestSetting& setting, + Message* test_message) = 0; + + void VerifyResponse(const ConformanceRequestSetting& setting, + const std::string& equivalent_wire_format, + const conformance::ConformanceResponse& response, + bool need_report_success, bool require_same_wire_format); void ReportSuccess(const std::string& test_name); - void ReportFailure(const string& test_name, - ConformanceLevel level, + void ReportFailure(const std::string& test_name, ConformanceLevel level, const conformance::ConformanceRequest& request, const conformance::ConformanceResponse& response, const char* fmt, ...); - void ReportSkip(const string& test_name, + void ReportSkip(const std::string& test_name, const conformance::ConformanceRequest& request, const conformance::ConformanceResponse& response); + + void RunValidInputTest(const ConformanceRequestSetting& setting, + const std::string& equivalent_text_format); + void RunValidBinaryInputTest(const ConformanceRequestSetting& setting, + const std::string& equivalent_wire_format, + bool require_same_wire_format = false); + void RunTest(const std::string& test_name, const conformance::ConformanceRequest& request, conformance::ConformanceResponse* response); - void RunValidInputTest(const string& test_name, - ConformanceLevel level, - const string& input, - conformance::WireFormat input_format, - const string& equivalent_text_format, - conformance::WireFormat requested_output, - bool isProto3); - void RunValidJsonTest(const string& test_name, - ConformanceLevel level, - const string& input_json, - const string& equivalent_text_format); - void RunValidJsonTestWithProtobufInput( - const string& test_name, - ConformanceLevel level, - const protobuf_test_messages::proto3::TestAllTypesProto3& input, - const string& equivalent_text_format); - void RunValidProtobufTest(const string& test_name, ConformanceLevel level, - const string& input_protobuf, - const string& equivalent_text_format, - bool isProto3); - void RunValidProtobufTestWithMessage( - const string& test_name, ConformanceLevel level, - const Message *input, - const string& equivalent_text_format, - bool isProto3); - - typedef std::function Validator; - void RunValidJsonTestWithValidator(const string& test_name, - ConformanceLevel level, - const string& input_json, - const Validator& validator); - void ExpectParseFailureForJson(const string& test_name, - ConformanceLevel level, - const string& input_json); - void ExpectSerializeFailureForJson(const string& test_name, - ConformanceLevel level, - const string& text_format); - void ExpectParseFailureForProtoWithProtoVersion (const string& proto, - const string& test_name, - ConformanceLevel level, - bool isProto3); - void ExpectParseFailureForProto(const std::string& proto, - const std::string& test_name, - ConformanceLevel level); - void ExpectHardParseFailureForProto(const std::string& proto, - const std::string& test_name, - ConformanceLevel level); - void TestPrematureEOFForType(google::protobuf::FieldDescriptor::Type type); - void TestIllegalTags(); - template - void TestOneofMessage (MessageType &message, - bool isProto3); - void TestValidDataForType( - google::protobuf::FieldDescriptor::Type, - std::vector> values); - bool CheckSetEmpty(const std::set& set_to_check, - const std::string& write_to_file, const std::string& msg); + + void AddExpectedFailedTest(const std::string& test_name); + + virtual void RunSuiteImpl() = 0; + ConformanceTestRunner* runner_; int successes_; int expected_failures_; bool verbose_; bool enforce_recommended_; std::string output_; + std::string failure_list_flag_name_; std::string failure_list_filename_; // The set of test names that are expected to fail in this run, but haven't @@ -241,10 +315,6 @@ class ConformanceTestSuite { // The set of tests that the testee opted out of; std::set skipped_; - - google::protobuf::internal::scoped_ptr - type_resolver_; - std::string type_url_; }; } // namespace protobuf diff --git a/conformance/conformance_test_main.cc b/conformance/conformance_test_main.cc new file mode 100644 index 0000000000000..c7ac9fc55a78b --- /dev/null +++ b/conformance/conformance_test_main.cc @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "binary_json_conformance_suite.h" +#include "conformance_test.h" +#include "text_format_conformance_suite.h" + +int main(int argc, char *argv[]) { + google::protobuf::BinaryAndJsonConformanceSuite binary_and_json_suite; + google::protobuf::TextFormatConformanceTestSuite text_format_suite; + return google::protobuf::ForkPipeRunner::Run( + argc, argv, {&binary_and_json_suite, &text_format_suite}); +} diff --git a/conformance/conformance_test_runner.cc b/conformance/conformance_test_runner.cc index 7e91d388b0d6e..9f893cb8e704f 100644 --- a/conformance/conformance_test_runner.cc +++ b/conformance/conformance_test_runner.cc @@ -53,190 +53,57 @@ // 3. testee sends 4-byte length M (little endian) // 4. testee sends M bytes representing a ConformanceResponse proto -#include #include -#include #include #include #include + +#include +#include #include #include - #include "conformance.pb.h" #include "conformance_test.h" -using conformance::ConformanceRequest; using conformance::ConformanceResponse; -using google::protobuf::internal::scoped_array; -using google::protobuf::StringAppendF; +using google::protobuf::ConformanceTestSuite; using std::string; using std::vector; #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) -#define CHECK_SYSCALL(call) \ +#define GOOGLE_CHECK_SYSCALL(call) \ if (call < 0) { \ perror(#call " " __FILE__ ":" TOSTRING(__LINE__)); \ exit(1); \ } -// Test runner that spawns the process being tested and communicates with it -// over a pipe. -class ForkPipeRunner : public google::protobuf::ConformanceTestRunner { - public: - ForkPipeRunner(const std::string &executable) - : child_pid_(-1), executable_(executable) {} - - virtual ~ForkPipeRunner() {} - - void RunTest(const std::string& test_name, - const std::string& request, - std::string* response) { - if (child_pid_ < 0) { - SpawnTestProgram(); - } - - current_test_name_ = test_name; - - uint32_t len = request.size(); - CheckedWrite(write_fd_, &len, sizeof(uint32_t)); - CheckedWrite(write_fd_, request.c_str(), request.size()); - - if (!TryRead(read_fd_, &len, sizeof(uint32_t))) { - // We failed to read from the child, assume a crash and try to reap. - GOOGLE_LOG(INFO) << "Trying to reap child, pid=" << child_pid_; - - int status; - waitpid(child_pid_, &status, WEXITED); - - string error_msg; - if (WIFEXITED(status)) { - StringAppendF(&error_msg, - "child exited, status=%d", WEXITSTATUS(status)); - } else if (WIFSIGNALED(status)) { - StringAppendF(&error_msg, - "child killed by signal %d", WTERMSIG(status)); - } - GOOGLE_LOG(INFO) << error_msg; - child_pid_ = -1; - - conformance::ConformanceResponse response_obj; - response_obj.set_runtime_error(error_msg); - response_obj.SerializeToString(response); - return; - } - - response->resize(len); - CheckedRead(read_fd_, (void*)response->c_str(), len); - } - - private: - // TODO(haberman): make this work on Windows, instead of using these - // UNIX-specific APIs. - // - // There is a platform-agnostic API in - // src/google/protobuf/compiler/subprocess.h - // - // However that API only supports sending a single message to the subprocess. - // We really want to be able to send messages and receive responses one at a - // time: - // - // 1. Spawning a new process for each test would take way too long for thousands - // of tests and subprocesses like java that can take 100ms or more to start - // up. - // - // 2. Sending all the tests in one big message and receiving all results in one - // big message would take away our visibility about which test(s) caused a - // crash or other fatal error. It would also give us only a single failure - // instead of all of them. - void SpawnTestProgram() { - int toproc_pipe_fd[2]; - int fromproc_pipe_fd[2]; - if (pipe(toproc_pipe_fd) < 0 || pipe(fromproc_pipe_fd) < 0) { - perror("pipe"); - exit(1); - } - - pid_t pid = fork(); - if (pid < 0) { - perror("fork"); - exit(1); - } +namespace google { +namespace protobuf { - if (pid) { - // Parent. - CHECK_SYSCALL(close(toproc_pipe_fd[0])); - CHECK_SYSCALL(close(fromproc_pipe_fd[1])); - write_fd_ = toproc_pipe_fd[1]; - read_fd_ = fromproc_pipe_fd[0]; - child_pid_ = pid; - } else { - // Child. - CHECK_SYSCALL(close(STDIN_FILENO)); - CHECK_SYSCALL(close(STDOUT_FILENO)); - CHECK_SYSCALL(dup2(toproc_pipe_fd[0], STDIN_FILENO)); - CHECK_SYSCALL(dup2(fromproc_pipe_fd[1], STDOUT_FILENO)); - - CHECK_SYSCALL(close(toproc_pipe_fd[0])); - CHECK_SYSCALL(close(fromproc_pipe_fd[1])); - CHECK_SYSCALL(close(toproc_pipe_fd[1])); - CHECK_SYSCALL(close(fromproc_pipe_fd[0])); - - scoped_array executable(new char[executable_.size() + 1]); - memcpy(executable.get(), executable_.c_str(), executable_.size()); - executable[executable_.size()] = '\0'; - - char *const argv[] = {executable.get(), NULL}; - CHECK_SYSCALL(execv(executable.get(), argv)); // Never returns. - } - } +void ParseFailureList(const char *filename, + conformance::FailureSet *failure_list) { + std::ifstream infile(filename); - void CheckedWrite(int fd, const void *buf, size_t len) { - if (write(fd, buf, len) != len) { - GOOGLE_LOG(FATAL) << current_test_name_ - << ": error writing to test program: " - << strerror(errno); - } + if (!infile.is_open()) { + fprintf(stderr, "Couldn't open failure list file: %s\n", filename); + exit(1); } - bool TryRead(int fd, void *buf, size_t len) { - size_t ofs = 0; - while (len > 0) { - ssize_t bytes_read = read(fd, (char*)buf + ofs, len); - - if (bytes_read == 0) { - GOOGLE_LOG(ERROR) << current_test_name_ - << ": unexpected EOF from test program"; - return false; - } else if (bytes_read < 0) { - GOOGLE_LOG(ERROR) << current_test_name_ - << ": error reading from test program: " - << strerror(errno); - return false; - } - - len -= bytes_read; - ofs += bytes_read; - } + for (string line; getline(infile, line);) { + // Remove whitespace. + line.erase(std::remove_if(line.begin(), line.end(), ::isspace), + line.end()); - return true; - } + // Remove comments. + line = line.substr(0, line.find("#")); - void CheckedRead(int fd, void *buf, size_t len) { - if (!TryRead(fd, buf, len)) { - GOOGLE_LOG(FATAL) << current_test_name_ - << ": error reading from test program: " - << strerror(errno); + if (!line.empty()) { + failure_list->add_failure(line); } } - - int write_fd_; - int read_fd_; - pid_t child_pid_; - std::string executable_; - std::string current_test_name_; -}; +} void UsageError() { fprintf(stderr, @@ -251,6 +118,19 @@ void UsageError() { " should contain one test name per\n"); fprintf(stderr, " line. Use '#' for comments.\n"); + fprintf(stderr, + " --text_format_failure_list Use to specify list \n"); + fprintf(stderr, + " of tests that are expected to \n"); + fprintf(stderr, + " fail in the \n"); + fprintf(stderr, + " text_format_conformance_suite. \n"); + fprintf(stderr, + " File should contain one test name \n"); + fprintf(stderr, + " per line. Use '#' for comments.\n"); + fprintf(stderr, " --enforce_recommended Enforce that recommended test\n"); fprintf(stderr, @@ -264,63 +144,202 @@ void UsageError() { exit(1); } -void ParseFailureList(const char *filename, vector* failure_list) { - std::ifstream infile(filename); - - if (!infile.is_open()) { - fprintf(stderr, "Couldn't open failure list file: %s\n", filename); - exit(1); +void ForkPipeRunner::RunTest( + const std::string& test_name, + const std::string& request, + std::string* response) { + if (child_pid_ < 0) { + SpawnTestProgram(); } - for (string line; getline(infile, line);) { - // Remove whitespace. - line.erase(std::remove_if(line.begin(), line.end(), ::isspace), - line.end()); + current_test_name_ = test_name; - // Remove comments. - line = line.substr(0, line.find("#")); + uint32_t len = request.size(); + CheckedWrite(write_fd_, &len, sizeof(uint32_t)); + CheckedWrite(write_fd_, request.c_str(), request.size()); - if (!line.empty()) { - failure_list->push_back(line); + if (!TryRead(read_fd_, &len, sizeof(uint32_t))) { + // We failed to read from the child, assume a crash and try to reap. + GOOGLE_LOG(INFO) << "Trying to reap child, pid=" << child_pid_; + + int status; + waitpid(child_pid_, &status, WEXITED); + + string error_msg; + if (WIFEXITED(status)) { + StringAppendF(&error_msg, + "child exited, status=%d", WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + StringAppendF(&error_msg, + "child killed by signal %d", WTERMSIG(status)); } + GOOGLE_LOG(INFO) << error_msg; + child_pid_ = -1; + + conformance::ConformanceResponse response_obj; + response_obj.set_runtime_error(error_msg); + response_obj.SerializeToString(response); + return; } + + response->resize(len); + CheckedRead(read_fd_, (void*)response->c_str(), len); } -int main(int argc, char *argv[]) { - char *program; - google::protobuf::ConformanceTestSuite suite; - - string failure_list_filename; - vector failure_list; - - for (int arg = 1; arg < argc; ++arg) { - if (strcmp(argv[arg], "--failure_list") == 0) { - if (++arg == argc) UsageError(); - failure_list_filename = argv[arg]; - ParseFailureList(argv[arg], &failure_list); - } else if (strcmp(argv[arg], "--verbose") == 0) { - suite.SetVerbose(true); - } else if (strcmp(argv[arg], "--enforce_recommended") == 0) { - suite.SetEnforceRecommended(true); - } else if (argv[arg][0] == '-') { - fprintf(stderr, "Unknown option: %s\n", argv[arg]); - UsageError(); - } else { - if (arg != argc - 1) { - fprintf(stderr, "Too many arguments.\n"); - UsageError(); +int ForkPipeRunner::Run( + int argc, char *argv[], const std::vector& suites) { + if (suites.empty()) { + fprintf(stderr, "No test suites found.\n"); + return EXIT_FAILURE; + } + bool all_ok = true; + for (ConformanceTestSuite* suite : suites) { + string program; + std::vector program_args; + string failure_list_filename; + conformance::FailureSet failure_list; + + for (int arg = 1; arg < argc; ++arg) { + if (strcmp(argv[arg], suite->GetFailureListFlagName().c_str()) == 0) { + if (++arg == argc) UsageError(); + failure_list_filename = argv[arg]; + ParseFailureList(argv[arg], &failure_list); + } else if (strcmp(argv[arg], "--verbose") == 0) { + suite->SetVerbose(true); + } else if (strcmp(argv[arg], "--enforce_recommended") == 0) { + suite->SetEnforceRecommended(true); + } else if (argv[arg][0] == '-') { + bool recognized_flag = false; + for (ConformanceTestSuite* suite : suites) { + if (strcmp(argv[arg], suite->GetFailureListFlagName().c_str()) == 0) { + if (++arg == argc) UsageError(); + recognized_flag = true; + } + } + if (!recognized_flag) { + fprintf(stderr, "Unknown option: %s\n", argv[arg]); + UsageError(); + } + } else { + program += argv[arg]; + while (arg < argc) { + program_args.push_back(argv[arg]); + arg++; + } } - program = argv[arg]; } + + ForkPipeRunner runner(program, program_args); + + std::string output; + all_ok = all_ok && + suite->RunSuite(&runner, &output, failure_list_filename, &failure_list); + + fwrite(output.c_str(), 1, output.size(), stderr); + } + return all_ok ? EXIT_SUCCESS : EXIT_FAILURE; +} + +// TODO(haberman): make this work on Windows, instead of using these +// UNIX-specific APIs. +// +// There is a platform-agnostic API in +// src/google/protobuf/compiler/subprocess.h +// +// However that API only supports sending a single message to the subprocess. +// We really want to be able to send messages and receive responses one at a +// time: +// +// 1. Spawning a new process for each test would take way too long for thousands +// of tests and subprocesses like java that can take 100ms or more to start +// up. +// +// 2. Sending all the tests in one big message and receiving all results in one +// big message would take away our visibility about which test(s) caused a +// crash or other fatal error. It would also give us only a single failure +// instead of all of them. +void ForkPipeRunner::SpawnTestProgram() { + int toproc_pipe_fd[2]; + int fromproc_pipe_fd[2]; + if (pipe(toproc_pipe_fd) < 0 || pipe(fromproc_pipe_fd) < 0) { + perror("pipe"); + exit(1); + } + + pid_t pid = fork(); + if (pid < 0) { + perror("fork"); + exit(1); + } + + if (pid) { + // Parent. + GOOGLE_CHECK_SYSCALL(close(toproc_pipe_fd[0])); + GOOGLE_CHECK_SYSCALL(close(fromproc_pipe_fd[1])); + write_fd_ = toproc_pipe_fd[1]; + read_fd_ = fromproc_pipe_fd[0]; + child_pid_ = pid; + } else { + // Child. + GOOGLE_CHECK_SYSCALL(close(STDIN_FILENO)); + GOOGLE_CHECK_SYSCALL(close(STDOUT_FILENO)); + GOOGLE_CHECK_SYSCALL(dup2(toproc_pipe_fd[0], STDIN_FILENO)); + GOOGLE_CHECK_SYSCALL(dup2(fromproc_pipe_fd[1], STDOUT_FILENO)); + + GOOGLE_CHECK_SYSCALL(close(toproc_pipe_fd[0])); + GOOGLE_CHECK_SYSCALL(close(fromproc_pipe_fd[1])); + GOOGLE_CHECK_SYSCALL(close(toproc_pipe_fd[1])); + GOOGLE_CHECK_SYSCALL(close(fromproc_pipe_fd[0])); + + std::unique_ptr executable(new char[executable_.size() + 1]); + memcpy(executable.get(), executable_.c_str(), executable_.size()); + executable[executable_.size()] = '\0'; + + std::vector argv; + argv.push_back(executable.get()); + for (int i = 0; i < executable_args_.size(); ++i) { + argv.push_back(executable_args_[i].c_str()); + } + argv.push_back(nullptr); + // Never returns. + GOOGLE_CHECK_SYSCALL(execv(executable.get(), const_cast(argv.data()))); } +} - suite.SetFailureList(failure_list_filename, failure_list); - ForkPipeRunner runner(program); +void ForkPipeRunner::CheckedWrite(int fd, const void *buf, size_t len) { + if (write(fd, buf, len) != len) { + GOOGLE_LOG(FATAL) << current_test_name_ + << ": error writing to test program: " << strerror(errno); + } +} - std::string output; - bool ok = suite.RunSuite(&runner, &output); +bool ForkPipeRunner::TryRead(int fd, void *buf, size_t len) { + size_t ofs = 0; + while (len > 0) { + ssize_t bytes_read = read(fd, (char*)buf + ofs, len); + + if (bytes_read == 0) { + GOOGLE_LOG(ERROR) << current_test_name_ << ": unexpected EOF from test program"; + return false; + } else if (bytes_read < 0) { + GOOGLE_LOG(ERROR) << current_test_name_ + << ": error reading from test program: " << strerror(errno); + return false; + } - fwrite(output.c_str(), 1, output.size(), stderr); + len -= bytes_read; + ofs += bytes_read; + } - return ok ? EXIT_SUCCESS : EXIT_FAILURE; + return true; } + +void ForkPipeRunner::CheckedRead(int fd, void *buf, size_t len) { + if (!TryRead(fd, buf, len)) { + GOOGLE_LOG(FATAL) << current_test_name_ + << ": error reading from test program: " << strerror(errno); + } +} + +} // namespace protobuf +} // namespace google diff --git a/conformance/failure_list_cpp.txt b/conformance/failure_list_cpp.txt index 8c328890d46ee..d55fa9ff349f8 100644 --- a/conformance/failure_list_cpp.txt +++ b/conformance/failure_list_cpp.txt @@ -34,24 +34,4 @@ Recommended.Proto3.JsonInput.TrailingCommaInAnObject Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithNewlines Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpace Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace -Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE -Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE -Required.Proto3.ProtobufInput.PrematureEofInPackedField.BOOL -Required.Proto3.ProtobufInput.PrematureEofInPackedField.ENUM -Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT32 -Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT64 -Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT32 -Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT64 -Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT32 -Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT64 -Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE -Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE -Required.Proto2.ProtobufInput.PrematureEofInPackedField.BOOL -Required.Proto2.ProtobufInput.PrematureEofInPackedField.ENUM -Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT32 -Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT64 -Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT32 -Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT64 -Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT32 -Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64 - +Recommended.Proto2.JsonInput.FieldNameExtension.Validator diff --git a/conformance/failure_list_csharp.txt b/conformance/failure_list_csharp.txt index a938e5bd9fac9..31bdf25ebf451 100644 --- a/conformance/failure_list_csharp.txt +++ b/conformance/failure_list_csharp.txt @@ -1,7 +1,3 @@ Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput -Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_0 -Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_1 -Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_2 -Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_3 - +Recommended.Proto2.JsonInput.FieldNameExtension.Validator diff --git a/conformance/failure_list_java.txt b/conformance/failure_list_java.txt index 5116c569ca65b..b29a63f5e4307 100644 --- a/conformance/failure_list_java.txt +++ b/conformance/failure_list_java.txt @@ -34,6 +34,7 @@ Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate Recommended.Proto3.JsonInput.Uint32MapFieldKeyNotQuoted Recommended.Proto3.JsonInput.Uint64MapFieldKeyNotQuoted +Recommended.Proto2.JsonInput.FieldNameExtension.Validator Required.Proto3.JsonInput.EnumFieldNotQuoted Required.Proto3.JsonInput.Int32FieldLeadingZero Required.Proto3.JsonInput.Int32FieldNegativeWithLeadingZero @@ -44,4 +45,4 @@ Required.Proto3.JsonInput.StringFieldNotAString Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE -Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE \ No newline at end of file +Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE diff --git a/conformance/failure_list_jruby.txt b/conformance/failure_list_jruby.txt new file mode 100644 index 0000000000000..ceaaf92a5f957 --- /dev/null +++ b/conformance/failure_list_jruby.txt @@ -0,0 +1,810 @@ +Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput +Recommended.FieldMaskPathsDontRoundTrip.JsonOutput +Recommended.FieldMaskTooManyUnderscore.JsonOutput +Recommended.Proto2.JsonInput.FieldNameExtension.Validator +Recommended.Proto3.JsonInput.BoolFieldAllCapitalFalse +Recommended.Proto3.JsonInput.BoolFieldAllCapitalTrue +Recommended.Proto3.JsonInput.BoolFieldCamelCaseFalse +Recommended.Proto3.JsonInput.BoolFieldCamelCaseTrue +Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse +Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue +Recommended.Proto3.JsonInput.BoolMapFieldKeyNotQuoted +Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted +Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted +Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted +Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter +Recommended.Proto3.JsonInput.FieldNameDuplicate +Recommended.Proto3.JsonInput.FieldNameNotQuoted +Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted +Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted +Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted +Recommended.Proto3.JsonInput.Int32MapFieldKeyNotQuoted +Recommended.Proto3.JsonInput.Int64MapFieldKeyNotQuoted +Recommended.Proto3.JsonInput.JsonWithComments +Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth +Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey +Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue +Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder +Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate +Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate +Recommended.Proto3.JsonInput.Uint32MapFieldKeyNotQuoted +Recommended.Proto3.JsonInput.Uint64MapFieldKeyNotQuoted +Recommended.Proto3.ProtobufInput.OneofZeroBool.JsonOutput +Recommended.Proto3.ProtobufInput.OneofZeroBool.ProtobufOutput +Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput +Recommended.Proto3.ProtobufInput.OneofZeroBytes.ProtobufOutput +Recommended.Proto3.ProtobufInput.OneofZeroDouble.JsonOutput +Recommended.Proto3.ProtobufInput.OneofZeroDouble.ProtobufOutput +Recommended.Proto3.ProtobufInput.OneofZeroEnum.JsonOutput +Recommended.Proto3.ProtobufInput.OneofZeroEnum.ProtobufOutput +Recommended.Proto3.ProtobufInput.OneofZeroFloat.JsonOutput +Recommended.Proto3.ProtobufInput.OneofZeroFloat.ProtobufOutput +Recommended.Proto3.ProtobufInput.OneofZeroMessage.JsonOutput +Recommended.Proto3.ProtobufInput.OneofZeroMessage.ProtobufOutput +Recommended.Proto3.ProtobufInput.OneofZeroMessageSetTwice.JsonOutput +Recommended.Proto3.ProtobufInput.OneofZeroMessageSetTwice.ProtobufOutput +Recommended.Proto3.ProtobufInput.OneofZeroString.JsonOutput +Recommended.Proto3.ProtobufInput.OneofZeroString.ProtobufOutput +Recommended.Proto3.ProtobufInput.OneofZeroUint32.JsonOutput +Recommended.Proto3.ProtobufInput.OneofZeroUint32.ProtobufOutput +Recommended.Proto3.ProtobufInput.OneofZeroUint64.JsonOutput +Recommended.Proto3.ProtobufInput.OneofZeroUint64.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.DefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.MultipleValuesForDifferentField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.MultipleValuesForSameField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.NonDefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.DefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.MultipleValuesForDifferentField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.MultipleValuesForSameField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.NonDefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.DefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.MultipleValuesForDifferentField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.MultipleValuesForSameField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.NonDefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.DefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.MultipleValuesForDifferentField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.MultipleValuesForSameField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.NonDefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.DefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.MultipleValuesForDifferentField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.MultipleValuesForSameField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.NonDefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.DefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.MultipleValuesForDifferentField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.MultipleValuesForSameField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.NonDefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.DefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.MultipleValuesForDifferentField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.MultipleValuesForSameField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.NonDefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.DefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.MultipleValuesForDifferentField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.MultipleValuesForSameField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.NonDefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.DefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.MultipleValuesForDifferentField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.MultipleValuesForSameField.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.NonDefaultValue.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[2].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[3].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[4].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[5].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[6].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BYTES[3].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.DOUBLE[1].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.DOUBLE[2].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[0].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[1].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[2].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[3].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[4].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[5].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FIXED32[2].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FIXED64[2].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[1].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[2].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[3].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[4].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[1].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[2].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[3].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[4].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[5].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[6].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[7].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[8].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[9].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT64[1].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT64[2].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT64[3].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.MESSAGE[0].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.MESSAGE[1].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED32[2].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED32[3].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED64[2].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED64[3].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[1].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[2].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[3].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[4].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT64[1].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT64[2].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT64[3].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[3].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[4].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[5].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[6].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[1].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[2].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[3].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[4].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[5].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[6].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[7].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[8].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[9].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT64[1].ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT64[2].ProtobufOutput +Required.DurationProtoInputTooLarge.JsonOutput +Required.DurationProtoInputTooSmall.JsonOutput +Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator +Required.Proto3.JsonInput.Any.JsonOutput +Required.Proto3.JsonInput.Any.ProtobufOutput +Required.Proto3.JsonInput.AnyNested.JsonOutput +Required.Proto3.JsonInput.AnyNested.ProtobufOutput +Required.Proto3.JsonInput.AnyUnorderedTypeTag.JsonOutput +Required.Proto3.JsonInput.AnyUnorderedTypeTag.ProtobufOutput +Required.Proto3.JsonInput.AnyWithDuration.JsonOutput +Required.Proto3.JsonInput.AnyWithDuration.ProtobufOutput +Required.Proto3.JsonInput.AnyWithFieldMask.JsonOutput +Required.Proto3.JsonInput.AnyWithFieldMask.ProtobufOutput +Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.JsonOutput +Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput +Required.Proto3.JsonInput.AnyWithStruct.JsonOutput +Required.Proto3.JsonInput.AnyWithStruct.ProtobufOutput +Required.Proto3.JsonInput.AnyWithTimestamp.JsonOutput +Required.Proto3.JsonInput.AnyWithTimestamp.ProtobufOutput +Required.Proto3.JsonInput.AnyWithValueForInteger.JsonOutput +Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput +Required.Proto3.JsonInput.AnyWithValueForJsonObject.JsonOutput +Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput +Required.Proto3.JsonInput.EnumFieldNotQuoted +Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput +Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput +Required.Proto3.JsonInput.Int32FieldLeadingZero +Required.Proto3.JsonInput.Int32FieldNegativeWithLeadingZero +Required.Proto3.JsonInput.Int32FieldPlusSign +Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool +Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt +Required.Proto3.JsonInput.StringFieldNotAString +Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput +Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput +Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput +Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput +Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.BOOL +Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.INT32 +Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.INT64 +Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SINT32 +Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SINT64 +Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.UINT32 +Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.UINT64 +Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BOOL.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BOOL.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BYTES.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BYTES.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.ENUM.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.ENUM.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FLOAT.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FLOAT.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT32.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT32.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT64.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT64.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED32.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED32.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED64.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED64.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT32.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT32.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT64.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT64.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.STRING.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.STRING.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT32.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT32.ProtobufOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT64.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput +Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MergeValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MergeValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Default.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Default.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKey.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKey.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKeyInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKeyInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateValueInMapEntry.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateValueInMapEntry.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.MissingDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.MissingDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.NonDefault.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.NonDefault.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Unordered.JsonOutput +Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Unordered.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.DefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.DefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForDifferentField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForDifferentField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForSameField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForSameField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.NonDefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.NonDefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForDifferentField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForDifferentField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForSameField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForSameField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.NonDefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.NonDefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.DefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.DefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForDifferentField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForDifferentField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForSameField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForSameField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.NonDefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.NonDefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.DefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.DefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForDifferentField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForDifferentField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForSameField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForSameField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.NonDefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.NonDefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.DefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.DefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForDifferentField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForDifferentField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForSameField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForSameField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.NonDefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.NonDefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.DefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.DefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForDifferentField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForDifferentField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForSameField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForSameField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.NonDefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.NonDefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.STRING.DefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.STRING.DefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForDifferentField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForDifferentField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForSameField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForSameField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.STRING.NonDefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.STRING.NonDefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.DefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.DefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForDifferentField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForDifferentField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForSameField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForSameField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.NonDefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.NonDefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.DefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.DefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForDifferentField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForDifferentField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForSameField.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForSameField.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.NonDefaultValue.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.NonDefaultValue.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.MESSAGE.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.MESSAGE.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[2].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[2].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[3].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[3].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[4].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[4].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[5].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[5].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[6].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[6].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.BYTES[3].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.BYTES[3].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[1].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[1].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[2].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[2].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[0].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[0].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[1].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[1].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[2].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[2].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[3].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[3].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[4].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[4].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[5].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[5].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.FIXED32[2].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.FIXED32[2].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.FIXED64[2].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.FIXED64[2].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[1].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[1].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[3].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[3].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[4].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[4].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[1].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[1].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[2].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[2].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[3].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[3].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[4].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[4].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[5].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[5].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[6].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[6].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[7].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[7].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[8].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[8].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[9].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT32[9].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT64[1].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT64[1].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT64[2].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT64[2].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT64[3].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.INT64[3].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[0].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[0].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[1].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[1].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[2].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[2].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[3].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[3].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[2].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[2].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[3].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[3].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[1].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[1].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[2].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[2].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[3].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[3].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[4].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[4].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[1].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[1].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[2].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[2].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[3].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[3].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.STRING[3].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.STRING[3].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.STRING[4].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.STRING[4].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.STRING[5].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.STRING[5].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.STRING[6].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.STRING[6].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[1].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[1].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[2].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[2].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[3].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[3].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[4].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[4].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[5].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[5].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[6].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[6].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[7].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[7].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[8].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[8].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[9].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[9].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[1].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[1].ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[2].JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[2].ProtobufOutput +Required.TimestampProtoInputTooLarge.JsonOutput +Required.TimestampProtoInputTooSmall.JsonOutput diff --git a/conformance/failure_list_js.txt b/conformance/failure_list_js.txt index eb20f659a261f..e69de29bb2d1d 100644 --- a/conformance/failure_list_js.txt +++ b/conformance/failure_list_js.txt @@ -1,19 +0,0 @@ -Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT32.ProtobufOutput -Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT32.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.ProtobufOutput -Required.Proto2.ProtobufInput.RepeatedScalarSelectsLast.INT32.ProtobufOutput -Required.Proto2.ProtobufInput.RepeatedScalarSelectsLast.UINT32.ProtobufOutput -Required.Proto2.ProtobufInput.ValidDataRepeated.INT32.ProtobufOutput -Required.Proto2.ProtobufInput.ValidDataRepeated.UINT32.ProtobufOutput diff --git a/conformance/failure_list_php.txt b/conformance/failure_list_php.txt index 2f91a3f589d84..d51a75dc3644b 100644 --- a/conformance/failure_list_php.txt +++ b/conformance/failure_list_php.txt @@ -1,120 +1,28 @@ Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput Recommended.FieldMaskPathsDontRoundTrip.JsonOutput Recommended.FieldMaskTooManyUnderscore.JsonOutput +Recommended.Proto2.JsonInput.FieldNameExtension.Validator Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput -Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator -Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator -Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator -Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator -Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator -Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator -Recommended.Proto3.JsonInput.TimestampHas9FractionalDigits.Validator -Recommended.Proto3.JsonInput.TimestampHasZeroFractionalDigit.Validator -Recommended.Proto3.JsonInput.TimestampZeroNormalized.Validator -Required.DurationProtoInputTooLarge.JsonOutput -Required.DurationProtoInputTooSmall.JsonOutput -Required.Proto3.JsonInput.Any.JsonOutput -Required.Proto3.JsonInput.Any.ProtobufOutput -Required.Proto3.JsonInput.AnyNested.JsonOutput -Required.Proto3.JsonInput.AnyNested.ProtobufOutput -Required.Proto3.JsonInput.AnyUnorderedTypeTag.JsonOutput -Required.Proto3.JsonInput.AnyUnorderedTypeTag.ProtobufOutput -Required.Proto3.JsonInput.AnyWithDuration.JsonOutput -Required.Proto3.JsonInput.AnyWithDuration.ProtobufOutput -Required.Proto3.JsonInput.AnyWithFieldMask.JsonOutput -Required.Proto3.JsonInput.AnyWithFieldMask.ProtobufOutput -Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.JsonOutput -Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput -Required.Proto3.JsonInput.AnyWithStruct.JsonOutput -Required.Proto3.JsonInput.AnyWithStruct.ProtobufOutput -Required.Proto3.JsonInput.AnyWithTimestamp.JsonOutput -Required.Proto3.JsonInput.AnyWithTimestamp.ProtobufOutput -Required.Proto3.JsonInput.AnyWithValueForInteger.JsonOutput -Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput -Required.Proto3.JsonInput.AnyWithValueForJsonObject.JsonOutput -Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput -Required.Proto3.JsonInput.DurationMaxValue.JsonOutput -Required.Proto3.JsonInput.DurationMaxValue.ProtobufOutput -Required.Proto3.JsonInput.DurationMinValue.JsonOutput -Required.Proto3.JsonInput.DurationMinValue.ProtobufOutput -Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput -Required.Proto3.JsonInput.DurationRepeatedValue.ProtobufOutput -Required.Proto3.JsonInput.FieldMask.JsonOutput -Required.Proto3.JsonInput.FieldMask.ProtobufOutput -Required.Proto3.JsonInput.OptionalBoolWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalBoolWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalBytesWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalBytesWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalDoubleWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalDoubleWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalFloatWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalFloatWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalInt32Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalInt32Wrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalInt64Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalInt64Wrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalStringWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalStringWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalUint32Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalUint32Wrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalUint64Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalUint64Wrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput -Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput -Required.Proto3.JsonInput.RepeatedBoolWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedBoolWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedBytesWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedBytesWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedDoubleWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedDoubleWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedFloatWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedFloatWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedInt32Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedInt32Wrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedInt64Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedInt64Wrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedStringWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedStringWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedUint32Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedUint32Wrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedUint64Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedUint64Wrapper.ProtobufOutput -Required.Proto3.JsonInput.Struct.JsonOutput -Required.Proto3.JsonInput.Struct.ProtobufOutput -Required.Proto3.JsonInput.TimestampMaxValue.JsonOutput -Required.Proto3.JsonInput.TimestampMaxValue.ProtobufOutput -Required.Proto3.JsonInput.TimestampMinValue.JsonOutput -Required.Proto3.JsonInput.TimestampMinValue.ProtobufOutput -Required.Proto3.JsonInput.TimestampRepeatedValue.JsonOutput -Required.Proto3.JsonInput.TimestampRepeatedValue.ProtobufOutput -Required.Proto3.JsonInput.TimestampWithNegativeOffset.JsonOutput -Required.Proto3.JsonInput.TimestampWithNegativeOffset.ProtobufOutput -Required.Proto3.JsonInput.TimestampWithPositiveOffset.JsonOutput -Required.Proto3.JsonInput.TimestampWithPositiveOffset.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptBool.JsonOutput -Required.Proto3.JsonInput.ValueAcceptBool.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptFloat.JsonOutput -Required.Proto3.JsonInput.ValueAcceptFloat.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptInteger.JsonOutput -Required.Proto3.JsonInput.ValueAcceptInteger.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptList.JsonOutput -Required.Proto3.JsonInput.ValueAcceptList.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptNull.JsonOutput -Required.Proto3.JsonInput.ValueAcceptNull.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptObject.JsonOutput -Required.Proto3.JsonInput.ValueAcceptObject.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptString.JsonOutput -Required.Proto3.JsonInput.ValueAcceptString.ProtobufOutput -Required.TimestampProtoInputTooLarge.JsonOutput -Required.TimestampProtoInputTooSmall.JsonOutput +Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput +Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator +Required.Proto3.JsonInput.DoubleFieldTooSmall Required.Proto3.JsonInput.FloatFieldTooLarge Required.Proto3.JsonInput.FloatFieldTooSmall -Required.Proto3.JsonInput.DoubleFieldTooSmall Required.Proto3.JsonInput.Int32FieldNotInteger Required.Proto3.JsonInput.Int64FieldNotInteger +Required.Proto3.JsonInput.OneofFieldDuplicate +Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt +Required.Proto3.JsonInput.RepeatedListValue.JsonOutput +Required.Proto3.JsonInput.RepeatedListValue.ProtobufOutput +Required.Proto3.JsonInput.StringFieldNotAString Required.Proto3.JsonInput.Uint32FieldNotInteger Required.Proto3.JsonInput.Uint64FieldNotInteger -Required.Proto3.JsonInput.Int32FieldLeadingSpace -Required.Proto3.JsonInput.OneofFieldDuplicate -Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.JsonOutput +Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.JsonOutput +Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.ProtobufOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput +Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput diff --git a/conformance/failure_list_php_c.txt b/conformance/failure_list_php_c.txt index 2e3788429881d..63c7e8a024ccf 100644 --- a/conformance/failure_list_php_c.txt +++ b/conformance/failure_list_php_c.txt @@ -1,197 +1,2 @@ -Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput -Recommended.FieldMaskPathsDontRoundTrip.JsonOutput -Recommended.FieldMaskTooManyUnderscore.JsonOutput -Recommended.Proto3.JsonInput.BoolFieldIntegerOne -Recommended.Proto3.JsonInput.BoolFieldIntegerZero -Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator -Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator -Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator -Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator -Recommended.Proto3.JsonInput.Int64FieldBeString.Validator -Recommended.Proto3.JsonInput.MapFieldValueIsNull -Recommended.Proto3.JsonInput.OneofZeroBytes.JsonOutput -Recommended.Proto3.JsonInput.OneofZeroBytes.ProtobufOutput -Recommended.Proto3.JsonInput.OneofZeroString.JsonOutput -Recommended.Proto3.JsonInput.OneofZeroString.ProtobufOutput -Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull -Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull -Recommended.Proto3.JsonInput.StringEndsWithEscapeChar -Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder -Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate -Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate -Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator -Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator -Recommended.Proto3.JsonInput.TimestampHas9FractionalDigits.Validator -Recommended.Proto3.JsonInput.TimestampHasZeroFractionalDigit.Validator -Recommended.Proto3.JsonInput.TimestampZeroNormalized.Validator -Recommended.Proto3.JsonInput.Uint64FieldBeString.Validator -Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput -Recommended.Proto3.ProtobufInput.OneofZeroBytes.ProtobufOutput -Recommended.Proto3.ProtobufInput.OneofZeroString.JsonOutput -Recommended.Proto3.ProtobufInput.OneofZeroString.ProtobufOutput -Required.DurationProtoInputTooLarge.JsonOutput -Required.DurationProtoInputTooSmall.JsonOutput -Required.Proto3.JsonInput.Any.JsonOutput -Required.Proto3.JsonInput.Any.ProtobufOutput -Required.Proto3.JsonInput.AnyNested.JsonOutput -Required.Proto3.JsonInput.AnyNested.ProtobufOutput -Required.Proto3.JsonInput.AnyUnorderedTypeTag.JsonOutput -Required.Proto3.JsonInput.AnyUnorderedTypeTag.ProtobufOutput -Required.Proto3.JsonInput.AnyWithDuration.JsonOutput -Required.Proto3.JsonInput.AnyWithDuration.ProtobufOutput -Required.Proto3.JsonInput.AnyWithFieldMask.JsonOutput -Required.Proto3.JsonInput.AnyWithFieldMask.ProtobufOutput -Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.JsonOutput -Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput -Required.Proto3.JsonInput.AnyWithStruct.JsonOutput -Required.Proto3.JsonInput.AnyWithStruct.ProtobufOutput -Required.Proto3.JsonInput.AnyWithTimestamp.JsonOutput -Required.Proto3.JsonInput.AnyWithTimestamp.ProtobufOutput -Required.Proto3.JsonInput.AnyWithValueForInteger.JsonOutput -Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput -Required.Proto3.JsonInput.AnyWithValueForJsonObject.JsonOutput -Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput -Required.Proto3.JsonInput.BoolMapField.JsonOutput -Required.Proto3.JsonInput.DoubleFieldInfinity.JsonOutput -Required.Proto3.JsonInput.DoubleFieldInfinity.ProtobufOutput -Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput -Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput -Required.Proto3.JsonInput.DoubleFieldMaxPositiveValue.JsonOutput -Required.Proto3.JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput -Required.Proto3.JsonInput.DoubleFieldMinNegativeValue.JsonOutput -Required.Proto3.JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput -Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput -Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput -Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput -Required.Proto3.JsonInput.DoubleFieldNan.ProtobufOutput -Required.Proto3.JsonInput.DoubleFieldNegativeInfinity.JsonOutput -Required.Proto3.JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput -Required.Proto3.JsonInput.DoubleFieldQuotedValue.JsonOutput -Required.Proto3.JsonInput.DoubleFieldQuotedValue.ProtobufOutput -Required.Proto3.JsonInput.DurationMaxValue.JsonOutput -Required.Proto3.JsonInput.DurationMaxValue.ProtobufOutput -Required.Proto3.JsonInput.DurationMinValue.JsonOutput -Required.Proto3.JsonInput.DurationMinValue.ProtobufOutput -Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput -Required.Proto3.JsonInput.DurationRepeatedValue.ProtobufOutput -Required.Proto3.JsonInput.EnumFieldNumericValueNonZero.JsonOutput -Required.Proto3.JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput -Required.Proto3.JsonInput.EnumFieldNumericValueZero.JsonOutput -Required.Proto3.JsonInput.EnumFieldNumericValueZero.ProtobufOutput -Required.Proto3.JsonInput.EnumFieldUnknownValue.Validator -Required.Proto3.JsonInput.FieldMask.JsonOutput -Required.Proto3.JsonInput.FieldMask.ProtobufOutput -Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput -Required.Proto3.JsonInput.FloatFieldInfinity.ProtobufOutput -Required.Proto3.JsonInput.FloatFieldNan.JsonOutput -Required.Proto3.JsonInput.FloatFieldNan.ProtobufOutput -Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput -Required.Proto3.JsonInput.FloatFieldNegativeInfinity.ProtobufOutput -Required.Proto3.JsonInput.FloatFieldQuotedValue.JsonOutput -Required.Proto3.JsonInput.FloatFieldQuotedValue.ProtobufOutput -Required.Proto3.JsonInput.FloatFieldTooLarge -Required.Proto3.JsonInput.FloatFieldTooSmall -Required.Proto3.JsonInput.Int32FieldExponentialFormat.JsonOutput -Required.Proto3.JsonInput.Int32FieldExponentialFormat.ProtobufOutput -Required.Proto3.JsonInput.Int32FieldFloatTrailingZero.JsonOutput -Required.Proto3.JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput -Required.Proto3.JsonInput.Int32FieldMaxFloatValue.JsonOutput -Required.Proto3.JsonInput.Int32FieldMaxFloatValue.ProtobufOutput -Required.Proto3.JsonInput.Int32FieldMinFloatValue.JsonOutput -Required.Proto3.JsonInput.Int32FieldMinFloatValue.ProtobufOutput -Required.Proto3.JsonInput.Int32FieldStringValue.JsonOutput -Required.Proto3.JsonInput.Int32FieldStringValue.ProtobufOutput -Required.Proto3.JsonInput.Int32FieldStringValueEscaped.JsonOutput -Required.Proto3.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput -Required.Proto3.JsonInput.Int64FieldMaxValue.JsonOutput -Required.Proto3.JsonInput.Int64FieldMaxValue.ProtobufOutput -Required.Proto3.JsonInput.Int64FieldMinValue.JsonOutput -Required.Proto3.JsonInput.Int64FieldMinValue.ProtobufOutput -Required.Proto3.JsonInput.MessageField.JsonOutput -Required.Proto3.JsonInput.MessageField.ProtobufOutput -Required.Proto3.JsonInput.OptionalBoolWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalBoolWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalBytesWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalBytesWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalDoubleWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalDoubleWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalFloatWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalFloatWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalInt32Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalInt32Wrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalInt64Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalInt64Wrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalStringWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalStringWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalUint32Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalUint32Wrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalUint64Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalUint64Wrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput -Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput -Required.Proto3.JsonInput.RepeatedBoolWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedBoolWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedBytesWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedBytesWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedDoubleWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedDoubleWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotInt -Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt -Required.Proto3.JsonInput.RepeatedFloatWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedFloatWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedInt32Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedInt32Wrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedInt64Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedInt64Wrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedStringWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedStringWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedUint32Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedUint32Wrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedUint64Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedUint64Wrapper.ProtobufOutput -Required.Proto3.JsonInput.StringFieldEscape.JsonOutput -Required.Proto3.JsonInput.StringFieldEscape.ProtobufOutput -Required.Proto3.JsonInput.StringFieldNotAString -Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput -Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput -Required.Proto3.JsonInput.StringFieldUnicodeEscape.JsonOutput -Required.Proto3.JsonInput.StringFieldUnicodeEscape.ProtobufOutput -Required.Proto3.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOutput -Required.Proto3.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.ProtobufOutput -Required.Proto3.JsonInput.Struct.JsonOutput -Required.Proto3.JsonInput.Struct.ProtobufOutput -Required.Proto3.JsonInput.TimestampMaxValue.JsonOutput -Required.Proto3.JsonInput.TimestampMaxValue.ProtobufOutput -Required.Proto3.JsonInput.TimestampMinValue.JsonOutput -Required.Proto3.JsonInput.TimestampMinValue.ProtobufOutput -Required.Proto3.JsonInput.TimestampRepeatedValue.JsonOutput -Required.Proto3.JsonInput.TimestampRepeatedValue.ProtobufOutput -Required.Proto3.JsonInput.TimestampWithNegativeOffset.JsonOutput -Required.Proto3.JsonInput.TimestampWithNegativeOffset.ProtobufOutput -Required.Proto3.JsonInput.TimestampWithPositiveOffset.JsonOutput -Required.Proto3.JsonInput.TimestampWithPositiveOffset.ProtobufOutput -Required.Proto3.JsonInput.Uint32FieldMaxFloatValue.JsonOutput -Required.Proto3.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput -Required.Proto3.JsonInput.Uint64FieldMaxValue.JsonOutput -Required.Proto3.JsonInput.Uint64FieldMaxValue.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptBool.JsonOutput -Required.Proto3.JsonInput.ValueAcceptBool.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptFloat.JsonOutput -Required.Proto3.JsonInput.ValueAcceptFloat.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptInteger.JsonOutput -Required.Proto3.JsonInput.ValueAcceptInteger.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptList.JsonOutput -Required.Proto3.JsonInput.ValueAcceptList.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptNull.JsonOutput -Required.Proto3.JsonInput.ValueAcceptNull.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptObject.JsonOutput -Required.Proto3.JsonInput.ValueAcceptObject.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptString.JsonOutput -Required.Proto3.JsonInput.ValueAcceptString.ProtobufOutput -Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput -Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput -Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput -Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput -Required.TimestampProtoInputTooLarge.JsonOutput -Required.TimestampProtoInputTooSmall.JsonOutput +Recommended.Proto2.JsonInput.FieldNameExtension.Validator +Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator diff --git a/conformance/failure_list_php_zts_c.txt b/conformance/failure_list_php_zts_c.txt deleted file mode 100644 index d9a8fe36d98b4..0000000000000 --- a/conformance/failure_list_php_zts_c.txt +++ /dev/null @@ -1,225 +0,0 @@ -Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput -Recommended.FieldMaskPathsDontRoundTrip.JsonOutput -Recommended.FieldMaskTooManyUnderscore.JsonOutput -Recommended.JsonInput.BoolFieldIntegerOne -Recommended.JsonInput.BoolFieldIntegerZero -Recommended.JsonInput.DurationHas3FractionalDigits.Validator -Recommended.JsonInput.DurationHas6FractionalDigits.Validator -Recommended.JsonInput.DurationHas9FractionalDigits.Validator -Recommended.JsonInput.DurationHasZeroFractionalDigit.Validator -Recommended.JsonInput.Int64FieldBeString.Validator -Recommended.JsonInput.OneofZeroBytes.JsonOutput -Recommended.JsonInput.OneofZeroBytes.ProtobufOutput -Recommended.JsonInput.OneofZeroDouble.JsonOutput -Recommended.JsonInput.OneofZeroDouble.ProtobufOutput -Recommended.JsonInput.OneofZeroFloat.JsonOutput -Recommended.JsonInput.OneofZeroFloat.ProtobufOutput -Recommended.JsonInput.OneofZeroString.JsonOutput -Recommended.JsonInput.OneofZeroString.ProtobufOutput -Recommended.JsonInput.OneofZeroUint32.JsonOutput -Recommended.JsonInput.OneofZeroUint32.ProtobufOutput -Recommended.JsonInput.OneofZeroUint64.JsonOutput -Recommended.JsonInput.OneofZeroUint64.ProtobufOutput -Recommended.JsonInput.StringEndsWithEscapeChar -Recommended.JsonInput.StringFieldSurrogateInWrongOrder -Recommended.JsonInput.StringFieldUnpairedHighSurrogate -Recommended.JsonInput.StringFieldUnpairedLowSurrogate -Recommended.JsonInput.TimestampHas3FractionalDigits.Validator -Recommended.JsonInput.TimestampHas6FractionalDigits.Validator -Recommended.JsonInput.TimestampHas9FractionalDigits.Validator -Recommended.JsonInput.TimestampHasZeroFractionalDigit.Validator -Recommended.JsonInput.TimestampZeroNormalized.Validator -Recommended.JsonInput.Uint64FieldBeString.Validator -Recommended.ProtobufInput.OneofZeroBytes.JsonOutput -Recommended.ProtobufInput.OneofZeroBytes.ProtobufOutput -Recommended.ProtobufInput.OneofZeroString.JsonOutput -Recommended.ProtobufInput.OneofZeroString.ProtobufOutput -Required.DurationProtoInputTooLarge.JsonOutput -Required.DurationProtoInputTooSmall.JsonOutput -Required.JsonInput.AllFieldAcceptNull.ProtobufOutput -Required.JsonInput.Any.JsonOutput -Required.JsonInput.Any.ProtobufOutput -Required.JsonInput.AnyNested.JsonOutput -Required.JsonInput.AnyNested.ProtobufOutput -Required.JsonInput.AnyUnorderedTypeTag.JsonOutput -Required.JsonInput.AnyUnorderedTypeTag.ProtobufOutput -Required.JsonInput.AnyWithDuration.JsonOutput -Required.JsonInput.AnyWithDuration.ProtobufOutput -Required.JsonInput.AnyWithFieldMask.JsonOutput -Required.JsonInput.AnyWithFieldMask.ProtobufOutput -Required.JsonInput.AnyWithInt32ValueWrapper.JsonOutput -Required.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput -Required.JsonInput.AnyWithStruct.JsonOutput -Required.JsonInput.AnyWithStruct.ProtobufOutput -Required.JsonInput.AnyWithTimestamp.JsonOutput -Required.JsonInput.AnyWithTimestamp.ProtobufOutput -Required.JsonInput.AnyWithValueForInteger.JsonOutput -Required.JsonInput.AnyWithValueForInteger.ProtobufOutput -Required.JsonInput.AnyWithValueForJsonObject.JsonOutput -Required.JsonInput.AnyWithValueForJsonObject.ProtobufOutput -Required.JsonInput.BoolFieldFalse.ProtobufOutput -Required.JsonInput.BoolMapField.JsonOutput -Required.JsonInput.DoubleFieldInfinity.JsonOutput -Required.JsonInput.DoubleFieldInfinity.ProtobufOutput -Required.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput -Required.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput -Required.JsonInput.DoubleFieldMaxPositiveValue.JsonOutput -Required.JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput -Required.JsonInput.DoubleFieldMinNegativeValue.JsonOutput -Required.JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput -Required.JsonInput.DoubleFieldMinPositiveValue.JsonOutput -Required.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput -Required.JsonInput.DoubleFieldNan.JsonOutput -Required.JsonInput.DoubleFieldNan.ProtobufOutput -Required.JsonInput.DoubleFieldNegativeInfinity.JsonOutput -Required.JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput -Required.JsonInput.DoubleFieldQuotedValue.JsonOutput -Required.JsonInput.DoubleFieldQuotedValue.ProtobufOutput -Required.JsonInput.DurationMaxValue.JsonOutput -Required.JsonInput.DurationMaxValue.ProtobufOutput -Required.JsonInput.DurationMinValue.JsonOutput -Required.JsonInput.DurationMinValue.ProtobufOutput -Required.JsonInput.DurationRepeatedValue.JsonOutput -Required.JsonInput.DurationRepeatedValue.ProtobufOutput -Required.JsonInput.EnumField.ProtobufOutput -Required.JsonInput.EnumFieldNumericValueNonZero.JsonOutput -Required.JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput -Required.JsonInput.EnumFieldNumericValueZero.JsonOutput -Required.JsonInput.EnumFieldNumericValueZero.ProtobufOutput -Required.JsonInput.EnumFieldUnknownValue.Validator -Required.JsonInput.FieldMask.JsonOutput -Required.JsonInput.FieldMask.ProtobufOutput -Required.JsonInput.FloatFieldInfinity.JsonOutput -Required.JsonInput.FloatFieldInfinity.ProtobufOutput -Required.JsonInput.FloatFieldNan.JsonOutput -Required.JsonInput.FloatFieldNan.ProtobufOutput -Required.JsonInput.FloatFieldNegativeInfinity.JsonOutput -Required.JsonInput.FloatFieldNegativeInfinity.ProtobufOutput -Required.JsonInput.FloatFieldQuotedValue.JsonOutput -Required.JsonInput.FloatFieldQuotedValue.ProtobufOutput -Required.JsonInput.FloatFieldTooLarge -Required.JsonInput.FloatFieldTooSmall -Required.JsonInput.Int32FieldExponentialFormat.JsonOutput -Required.JsonInput.Int32FieldExponentialFormat.ProtobufOutput -Required.JsonInput.Int32FieldFloatTrailingZero.JsonOutput -Required.JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput -Required.JsonInput.Int32FieldMaxFloatValue.JsonOutput -Required.JsonInput.Int32FieldMaxFloatValue.ProtobufOutput -Required.JsonInput.Int32FieldMinFloatValue.JsonOutput -Required.JsonInput.Int32FieldMinFloatValue.ProtobufOutput -Required.JsonInput.Int32FieldStringValue.JsonOutput -Required.JsonInput.Int32FieldStringValue.ProtobufOutput -Required.JsonInput.Int32FieldStringValueEscaped.JsonOutput -Required.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput -Required.JsonInput.Int32MapEscapedKey.JsonOutput -Required.JsonInput.Int32MapEscapedKey.ProtobufOutput -Required.JsonInput.Int32MapField.JsonOutput -Required.JsonInput.Int32MapField.ProtobufOutput -Required.JsonInput.Int64FieldMaxValue.JsonOutput -Required.JsonInput.Int64FieldMaxValue.ProtobufOutput -Required.JsonInput.Int64FieldMinValue.JsonOutput -Required.JsonInput.Int64FieldMinValue.ProtobufOutput -Required.JsonInput.Int64MapEscapedKey.JsonOutput -Required.JsonInput.Int64MapEscapedKey.ProtobufOutput -Required.JsonInput.Int64MapField.JsonOutput -Required.JsonInput.Int64MapField.ProtobufOutput -Required.JsonInput.MessageField.JsonOutput -Required.JsonInput.MessageField.ProtobufOutput -Required.JsonInput.MessageMapField.JsonOutput -Required.JsonInput.MessageMapField.ProtobufOutput -Required.JsonInput.MessageRepeatedField.JsonOutput -Required.JsonInput.MessageRepeatedField.ProtobufOutput -Required.JsonInput.OptionalBoolWrapper.JsonOutput -Required.JsonInput.OptionalBoolWrapper.ProtobufOutput -Required.JsonInput.OptionalBytesWrapper.JsonOutput -Required.JsonInput.OptionalBytesWrapper.ProtobufOutput -Required.JsonInput.OptionalDoubleWrapper.JsonOutput -Required.JsonInput.OptionalDoubleWrapper.ProtobufOutput -Required.JsonInput.OptionalFloatWrapper.JsonOutput -Required.JsonInput.OptionalFloatWrapper.ProtobufOutput -Required.JsonInput.OptionalInt32Wrapper.JsonOutput -Required.JsonInput.OptionalInt32Wrapper.ProtobufOutput -Required.JsonInput.OptionalInt64Wrapper.JsonOutput -Required.JsonInput.OptionalInt64Wrapper.ProtobufOutput -Required.JsonInput.OptionalStringWrapper.JsonOutput -Required.JsonInput.OptionalStringWrapper.ProtobufOutput -Required.JsonInput.OptionalUint32Wrapper.JsonOutput -Required.JsonInput.OptionalUint32Wrapper.ProtobufOutput -Required.JsonInput.OptionalUint64Wrapper.JsonOutput -Required.JsonInput.OptionalUint64Wrapper.ProtobufOutput -Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput -Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput -Required.JsonInput.PrimitiveRepeatedField.JsonOutput -Required.JsonInput.PrimitiveRepeatedField.ProtobufOutput -Required.JsonInput.RepeatedBoolWrapper.JsonOutput -Required.JsonInput.RepeatedBoolWrapper.ProtobufOutput -Required.JsonInput.RepeatedBytesWrapper.JsonOutput -Required.JsonInput.RepeatedBytesWrapper.ProtobufOutput -Required.JsonInput.RepeatedDoubleWrapper.JsonOutput -Required.JsonInput.RepeatedDoubleWrapper.ProtobufOutput -Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt -Required.JsonInput.RepeatedFloatWrapper.JsonOutput -Required.JsonInput.RepeatedFloatWrapper.ProtobufOutput -Required.JsonInput.RepeatedInt32Wrapper.JsonOutput -Required.JsonInput.RepeatedInt32Wrapper.ProtobufOutput -Required.JsonInput.RepeatedInt64Wrapper.JsonOutput -Required.JsonInput.RepeatedInt64Wrapper.ProtobufOutput -Required.JsonInput.RepeatedStringWrapper.JsonOutput -Required.JsonInput.RepeatedStringWrapper.ProtobufOutput -Required.JsonInput.RepeatedUint32Wrapper.JsonOutput -Required.JsonInput.RepeatedUint32Wrapper.ProtobufOutput -Required.JsonInput.RepeatedUint64Wrapper.JsonOutput -Required.JsonInput.RepeatedUint64Wrapper.ProtobufOutput -Required.JsonInput.StringFieldEscape.JsonOutput -Required.JsonInput.StringFieldEscape.ProtobufOutput -Required.JsonInput.StringFieldNotAString -Required.JsonInput.StringFieldSurrogatePair.JsonOutput -Required.JsonInput.StringFieldSurrogatePair.ProtobufOutput -Required.JsonInput.StringFieldUnicodeEscape.JsonOutput -Required.JsonInput.StringFieldUnicodeEscape.ProtobufOutput -Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOutput -Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.ProtobufOutput -Required.JsonInput.Struct.JsonOutput -Required.JsonInput.Struct.ProtobufOutput -Required.JsonInput.TimestampMaxValue.JsonOutput -Required.JsonInput.TimestampMaxValue.ProtobufOutput -Required.JsonInput.TimestampMinValue.JsonOutput -Required.JsonInput.TimestampMinValue.ProtobufOutput -Required.JsonInput.TimestampRepeatedValue.JsonOutput -Required.JsonInput.TimestampRepeatedValue.ProtobufOutput -Required.JsonInput.TimestampWithNegativeOffset.JsonOutput -Required.JsonInput.TimestampWithNegativeOffset.ProtobufOutput -Required.JsonInput.TimestampWithPositiveOffset.JsonOutput -Required.JsonInput.TimestampWithPositiveOffset.ProtobufOutput -Required.JsonInput.Uint32FieldMaxFloatValue.JsonOutput -Required.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput -Required.JsonInput.Uint32MapField.JsonOutput -Required.JsonInput.Uint32MapField.ProtobufOutput -Required.JsonInput.Uint64FieldMaxValue.JsonOutput -Required.JsonInput.Uint64FieldMaxValue.ProtobufOutput -Required.JsonInput.Uint64MapField.JsonOutput -Required.JsonInput.Uint64MapField.ProtobufOutput -Required.JsonInput.ValueAcceptBool.JsonOutput -Required.JsonInput.ValueAcceptBool.ProtobufOutput -Required.JsonInput.ValueAcceptFloat.JsonOutput -Required.JsonInput.ValueAcceptFloat.ProtobufOutput -Required.JsonInput.ValueAcceptInteger.JsonOutput -Required.JsonInput.ValueAcceptInteger.ProtobufOutput -Required.JsonInput.ValueAcceptList.JsonOutput -Required.JsonInput.ValueAcceptList.ProtobufOutput -Required.JsonInput.ValueAcceptNull.JsonOutput -Required.JsonInput.ValueAcceptNull.ProtobufOutput -Required.JsonInput.ValueAcceptObject.JsonOutput -Required.JsonInput.ValueAcceptObject.ProtobufOutput -Required.JsonInput.ValueAcceptString.JsonOutput -Required.JsonInput.ValueAcceptString.ProtobufOutput -Required.JsonInput.WrapperTypesWithNullValue.ProtobufOutput -Required.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput -Required.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput -Required.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput -Required.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput -Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.ProtobufOutput -Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput -Required.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput -Required.TimestampProtoInputTooLarge.JsonOutput -Required.TimestampProtoInputTooSmall.JsonOutput diff --git a/conformance/failure_list_python.txt b/conformance/failure_list_python.txt index 062c22a8dc798..e69de29bb2d1d 100644 --- a/conformance/failure_list_python.txt +++ b/conformance/failure_list_python.txt @@ -1,22 +0,0 @@ -Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput -Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput -Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted -Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted -Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted -Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted -Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted -Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted -Required.Proto3.JsonInput.DoubleFieldTooSmall -Required.Proto3.JsonInput.EnumFieldUnknownValue.Validator -Required.Proto3.JsonInput.FloatFieldTooLarge -Required.Proto3.JsonInput.FloatFieldTooSmall -Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool -Required.Proto3.JsonInput.TimestampJsonInputLowercaseT -Required.Proto2.ProtobufInput.IllegalZeroFieldNum_Case_0 -Required.Proto2.ProtobufInput.IllegalZeroFieldNum_Case_1 -Required.Proto2.ProtobufInput.IllegalZeroFieldNum_Case_2 -Required.Proto2.ProtobufInput.IllegalZeroFieldNum_Case_3 -Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_0 -Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_1 -Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_2 -Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_3 diff --git a/conformance/failure_list_python_cpp.txt b/conformance/failure_list_python_cpp.txt index e2c258de50db4..9efb6cf8b77b8 100644 --- a/conformance/failure_list_python_cpp.txt +++ b/conformance/failure_list_python_cpp.txt @@ -6,50 +6,3 @@ # # TODO(haberman): insert links to corresponding bugs tracking the issue. # Should we use GitHub issues or the Google-internal bug tracker? - -Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput -Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput -Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted -Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted -Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted -Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted -Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted -Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted -Required.Proto3.JsonInput.DoubleFieldTooSmall -Required.Proto3.JsonInput.EnumFieldUnknownValue.Validator -Required.Proto3.JsonInput.FloatFieldTooLarge -Required.Proto3.JsonInput.FloatFieldTooSmall -Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool -Required.Proto3.JsonInput.TimestampJsonInputLowercaseT -Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE -Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE -Required.Proto3.ProtobufInput.PrematureEofInPackedField.BOOL -Required.Proto3.ProtobufInput.PrematureEofInPackedField.DOUBLE -Required.Proto3.ProtobufInput.PrematureEofInPackedField.ENUM -Required.Proto3.ProtobufInput.PrematureEofInPackedField.FIXED32 -Required.Proto3.ProtobufInput.PrematureEofInPackedField.FIXED64 -Required.Proto3.ProtobufInput.PrematureEofInPackedField.FLOAT -Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT32 -Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT64 -Required.Proto3.ProtobufInput.PrematureEofInPackedField.SFIXED32 -Required.Proto3.ProtobufInput.PrematureEofInPackedField.SFIXED64 -Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT32 -Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT64 -Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT32 -Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT64 -Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE -Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE -Required.Proto2.ProtobufInput.PrematureEofInPackedField.BOOL -Required.Proto2.ProtobufInput.PrematureEofInPackedField.DOUBLE -Required.Proto2.ProtobufInput.PrematureEofInPackedField.ENUM -Required.Proto2.ProtobufInput.PrematureEofInPackedField.FIXED32 -Required.Proto2.ProtobufInput.PrematureEofInPackedField.FIXED64 -Required.Proto2.ProtobufInput.PrematureEofInPackedField.FLOAT -Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT32 -Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT64 -Required.Proto2.ProtobufInput.PrematureEofInPackedField.SFIXED32 -Required.Proto2.ProtobufInput.PrematureEofInPackedField.SFIXED64 -Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT32 -Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT64 -Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT32 -Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64 diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt index 45cfaca659eb2..4938202ad70b6 100644 --- a/conformance/failure_list_ruby.txt +++ b/conformance/failure_list_ruby.txt @@ -1,137 +1,58 @@ -Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput -Recommended.FieldMaskPathsDontRoundTrip.JsonOutput -Recommended.FieldMaskTooManyUnderscore.JsonOutput -Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput -Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput -Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator -Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator -Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator -Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator -Recommended.Proto3.JsonInput.Int64FieldBeString.Validator -Recommended.Proto3.JsonInput.MapFieldValueIsNull -Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull -Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull -Recommended.Proto3.JsonInput.StringEndsWithEscapeChar -Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder -Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate -Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate -Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator -Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator -Recommended.Proto3.JsonInput.TimestampHas9FractionalDigits.Validator -Recommended.Proto3.JsonInput.TimestampHasZeroFractionalDigit.Validator -Recommended.Proto3.JsonInput.TimestampZeroNormalized.Validator -Recommended.Proto3.JsonInput.Uint64FieldBeString.Validator -Required.DurationProtoInputTooLarge.JsonOutput -Required.DurationProtoInputTooSmall.JsonOutput -Required.Proto3.JsonInput.Any.JsonOutput -Required.Proto3.JsonInput.Any.ProtobufOutput -Required.Proto3.JsonInput.AnyNested.JsonOutput -Required.Proto3.JsonInput.AnyNested.ProtobufOutput -Required.Proto3.JsonInput.AnyUnorderedTypeTag.JsonOutput -Required.Proto3.JsonInput.AnyUnorderedTypeTag.ProtobufOutput -Required.Proto3.JsonInput.AnyWithDuration.JsonOutput -Required.Proto3.JsonInput.AnyWithDuration.ProtobufOutput -Required.Proto3.JsonInput.AnyWithFieldMask.JsonOutput -Required.Proto3.JsonInput.AnyWithFieldMask.ProtobufOutput -Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.JsonOutput -Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput -Required.Proto3.JsonInput.AnyWithStruct.JsonOutput -Required.Proto3.JsonInput.AnyWithStruct.ProtobufOutput -Required.Proto3.JsonInput.AnyWithTimestamp.JsonOutput -Required.Proto3.JsonInput.AnyWithTimestamp.ProtobufOutput -Required.Proto3.JsonInput.AnyWithValueForInteger.JsonOutput -Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput -Required.Proto3.JsonInput.AnyWithValueForJsonObject.JsonOutput -Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput -Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput -Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput -Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput -Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput -Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput -Required.Proto3.JsonInput.DurationMaxValue.JsonOutput -Required.Proto3.JsonInput.DurationMaxValue.ProtobufOutput -Required.Proto3.JsonInput.DurationMinValue.JsonOutput -Required.Proto3.JsonInput.DurationMinValue.ProtobufOutput -Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput -Required.Proto3.JsonInput.DurationRepeatedValue.ProtobufOutput -Required.Proto3.JsonInput.FieldMask.JsonOutput -Required.Proto3.JsonInput.FieldMask.ProtobufOutput -Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput -Required.Proto3.JsonInput.FloatFieldNan.JsonOutput -Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput -Required.Proto3.JsonInput.FloatFieldTooLarge -Required.Proto3.JsonInput.FloatFieldTooSmall -Required.Proto3.JsonInput.OneofFieldDuplicate -Required.Proto3.JsonInput.OptionalBoolWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalBoolWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalBytesWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalBytesWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalDoubleWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalDoubleWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalFloatWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalFloatWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalInt32Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalInt32Wrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalInt64Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalInt64Wrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalStringWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalStringWrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalUint32Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalUint32Wrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalUint64Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalUint64Wrapper.ProtobufOutput -Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput -Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput -Required.Proto3.JsonInput.RepeatedBoolWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedBoolWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedBytesWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedBytesWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedDoubleWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedDoubleWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedFloatWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedFloatWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedInt32Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedInt32Wrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedInt64Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedInt64Wrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedStringWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedStringWrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedUint32Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedUint32Wrapper.ProtobufOutput -Required.Proto3.JsonInput.RepeatedUint64Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedUint64Wrapper.ProtobufOutput -Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput -Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput -Required.Proto3.JsonInput.Struct.JsonOutput -Required.Proto3.JsonInput.Struct.ProtobufOutput -Required.Proto3.JsonInput.TimestampMaxValue.JsonOutput -Required.Proto3.JsonInput.TimestampMaxValue.ProtobufOutput -Required.Proto3.JsonInput.TimestampMinValue.JsonOutput -Required.Proto3.JsonInput.TimestampMinValue.ProtobufOutput -Required.Proto3.JsonInput.TimestampRepeatedValue.JsonOutput -Required.Proto3.JsonInput.TimestampRepeatedValue.ProtobufOutput -Required.Proto3.JsonInput.TimestampWithNegativeOffset.JsonOutput -Required.Proto3.JsonInput.TimestampWithNegativeOffset.ProtobufOutput -Required.Proto3.JsonInput.TimestampWithPositiveOffset.JsonOutput -Required.Proto3.JsonInput.TimestampWithPositiveOffset.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptBool.JsonOutput -Required.Proto3.JsonInput.ValueAcceptBool.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptFloat.JsonOutput -Required.Proto3.JsonInput.ValueAcceptFloat.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptInteger.JsonOutput -Required.Proto3.JsonInput.ValueAcceptInteger.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptList.JsonOutput -Required.Proto3.JsonInput.ValueAcceptList.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptNull.JsonOutput -Required.Proto3.JsonInput.ValueAcceptNull.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptObject.JsonOutput -Required.Proto3.JsonInput.ValueAcceptObject.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptString.JsonOutput -Required.Proto3.JsonInput.ValueAcceptString.ProtobufOutput -Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput -Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput -Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput -Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput -Required.TimestampProtoInputTooLarge.JsonOutput -Required.TimestampProtoInputTooSmall.JsonOutput +Recommended.Proto2.JsonInput.FieldNameExtension.Validator +Recommended.Proto2.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput +Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.UnpackedOutput.ProtobufOutput +Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.UnpackedOutput.ProtobufOutput diff --git a/conformance/text_format_conformance_suite.cc b/conformance/text_format_conformance_suite.cc new file mode 100644 index 0000000000000..4c9dc7dbe0518 --- /dev/null +++ b/conformance/text_format_conformance_suite.cc @@ -0,0 +1,457 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "text_format_conformance_suite.h" + +#include +#include +#include "conformance_test.h" +#include +#include + +namespace proto2_messages = protobuf_test_messages::proto2; + +using conformance::ConformanceRequest; +using conformance::ConformanceResponse; +using conformance::WireFormat; +using google::protobuf::Message; +using google::protobuf::TextFormat; +using proto2_messages::TestAllTypesProto2; +using proto2_messages::UnknownToTestAllTypes; +using protobuf_test_messages::proto3::TestAllTypesProto3; +using std::string; + +namespace google { +namespace protobuf { + +TextFormatConformanceTestSuite::TextFormatConformanceTestSuite() { + SetFailureListFlagName("--text_format_failure_list"); +} + +bool TextFormatConformanceTestSuite::ParseTextFormatResponse( + const ConformanceResponse& response, + const ConformanceRequestSetting& setting, Message* test_message) { + TextFormat::Parser parser; + const ConformanceRequest& request = setting.GetRequest(); + if (request.print_unknown_fields()) { + parser.AllowFieldNumber(true); + } + if (!parser.ParseFromString(response.text_payload(), test_message)) { + GOOGLE_LOG(ERROR) << "INTERNAL ERROR: internal text->protobuf transcode " + << "yielded unparseable proto. Text payload: " + << response.text_payload(); + return false; + } + + return true; +} + +bool TextFormatConformanceTestSuite::ParseResponse( + const ConformanceResponse& response, + const ConformanceRequestSetting& setting, Message* test_message) { + const ConformanceRequest& request = setting.GetRequest(); + WireFormat requested_output = request.requested_output_format(); + const string& test_name = setting.GetTestName(); + ConformanceLevel level = setting.GetLevel(); + + switch (response.result_case()) { + case ConformanceResponse::kProtobufPayload: { + if (requested_output != conformance::PROTOBUF) { + ReportFailure(test_name, level, request, response, + StrCat("Test was asked for ", + WireFormatToString(requested_output), + " output but provided PROTOBUF instead.") + .c_str()); + return false; + } + + if (!test_message->ParseFromString(response.protobuf_payload())) { + ReportFailure(test_name, level, request, response, + "Protobuf output we received from test was unparseable."); + return false; + } + + break; + } + + case ConformanceResponse::kTextPayload: { + if (requested_output != conformance::TEXT_FORMAT) { + ReportFailure(test_name, level, request, response, + StrCat("Test was asked for ", + WireFormatToString(requested_output), + " output but provided TEXT_FORMAT instead.") + .c_str()); + return false; + } + + if (!ParseTextFormatResponse(response, setting, test_message)) { + ReportFailure( + test_name, level, request, response, + "TEXT_FORMAT output we received from test was unparseable."); + return false; + } + + break; + } + + default: + GOOGLE_LOG(FATAL) << test_name + << ": unknown payload type: " << response.result_case(); + } + + return true; +} + +void TextFormatConformanceTestSuite::ExpectParseFailure(const string& test_name, + ConformanceLevel level, + const string& input) { + TestAllTypesProto3 prototype; + // We don't expect output, but if the program erroneously accepts the protobuf + // we let it send its response as this. We must not leave it unspecified. + ConformanceRequestSetting setting( + level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT, + conformance::TEXT_FORMAT_TEST, prototype, test_name, input); + const ConformanceRequest& request = setting.GetRequest(); + ConformanceResponse response; + string effective_test_name = + StrCat(setting.ConformanceLevelToString(level), + ".Proto3.TextFormatInput.", test_name); + + RunTest(effective_test_name, request, &response); + if (response.result_case() == ConformanceResponse::kParseError) { + ReportSuccess(effective_test_name); + } else if (response.result_case() == ConformanceResponse::kSkipped) { + ReportSkip(effective_test_name, request, response); + } else { + ReportFailure(effective_test_name, level, request, response, + "Should have failed to parse, but didn't."); + } +} + +void TextFormatConformanceTestSuite::RunValidTextFormatTest( + const string& test_name, ConformanceLevel level, const string& input_text) { + TestAllTypesProto3 prototype; + RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype); +} + +void TextFormatConformanceTestSuite::RunValidTextFormatTestProto2( + const string& test_name, ConformanceLevel level, const string& input_text) { + TestAllTypesProto2 prototype; + RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype); +} + +void TextFormatConformanceTestSuite::RunValidTextFormatTestWithMessage( + const string& test_name, ConformanceLevel level, const string& input_text, + const Message& prototype) { + ConformanceRequestSetting setting1( + level, conformance::TEXT_FORMAT, conformance::PROTOBUF, + conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text); + RunValidInputTest(setting1, input_text); + ConformanceRequestSetting setting2( + level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT, + conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text); + RunValidInputTest(setting2, input_text); +} + +void TextFormatConformanceTestSuite::RunValidUnknownTextFormatTest( + const string& test_name, const Message& message) { + string serialized_input; + message.SerializeToString(&serialized_input); + TestAllTypesProto3 prototype; + ConformanceRequestSetting setting1( + RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT, + conformance::TEXT_FORMAT_TEST, prototype, test_name + "_Drop", + serialized_input); + setting1.SetPrototypeMessageForCompare(message); + RunValidBinaryInputTest(setting1, ""); + + ConformanceRequestSetting setting2( + RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT, + conformance::TEXT_FORMAT_TEST, prototype, test_name + "_Print", + serialized_input); + setting2.SetPrototypeMessageForCompare(message); + setting2.SetPrintUnknownFields(true); + RunValidBinaryInputTest(setting2, serialized_input); +} + +void TextFormatConformanceTestSuite::RunSuiteImpl() { + RunValidTextFormatTest("HelloWorld", REQUIRED, + "optional_string: 'Hello, World!'"); + // Integer fields. + RunValidTextFormatTest("Int32FieldMaxValue", REQUIRED, + "optional_int32: 2147483647"); + RunValidTextFormatTest("Int32FieldMinValue", REQUIRED, + "optional_int32: -2147483648"); + RunValidTextFormatTest("Uint32FieldMaxValue", REQUIRED, + "optional_uint32: 4294967295"); + RunValidTextFormatTest("Int64FieldMaxValue", REQUIRED, + "optional_int64: 9223372036854775807"); + RunValidTextFormatTest("Int64FieldMinValue", REQUIRED, + "optional_int64: -9223372036854775808"); + RunValidTextFormatTest("Uint64FieldMaxValue", REQUIRED, + "optional_uint64: 18446744073709551615"); + + // Parsers reject out-of-bound integer values. + ExpectParseFailure("Int32FieldTooLarge", REQUIRED, + "optional_int32: 2147483648"); + ExpectParseFailure("Int32FieldTooSmall", REQUIRED, + "optional_int32: -2147483649"); + ExpectParseFailure("Uint32FieldTooLarge", REQUIRED, + "optional_uint32: 4294967296"); + ExpectParseFailure("Int64FieldTooLarge", REQUIRED, + "optional_int64: 9223372036854775808"); + ExpectParseFailure("Int64FieldTooSmall", REQUIRED, + "optional_int64: -9223372036854775809"); + ExpectParseFailure("Uint64FieldTooLarge", REQUIRED, + "optional_uint64: 18446744073709551616"); + + // Floating point fields + RunValidTextFormatTest("FloatField", REQUIRED, + "optional_float: 3.192837"); + RunValidTextFormatTest("FloatFieldWithVeryPreciseNumber", REQUIRED, + "optional_float: 3.123456789123456789"); + RunValidTextFormatTest("FloatFieldMaxValue", REQUIRED, + "optional_float: 3.4028235e+38"); + RunValidTextFormatTest("FloatFieldMinValue", REQUIRED, + "optional_float: 1.17549e-38"); + RunValidTextFormatTest("FloatFieldNaNValue", REQUIRED, + "optional_float: NaN"); + RunValidTextFormatTest("FloatFieldPosInfValue", REQUIRED, + "optional_float: inf"); + RunValidTextFormatTest("FloatFieldNegInfValue", REQUIRED, + "optional_float: -inf"); + RunValidTextFormatTest("FloatFieldWithInt32Max", REQUIRED, + "optional_float: 4294967296"); + RunValidTextFormatTest("FloatFieldLargerThanInt64", REQUIRED, + "optional_float: 9223372036854775808"); + RunValidTextFormatTest("FloatFieldTooLarge", REQUIRED, + "optional_float: 3.4028235e+39"); + RunValidTextFormatTest("FloatFieldTooSmall", REQUIRED, + "optional_float: 1.17549e-39"); + RunValidTextFormatTest("FloatFieldLargerThanUint64", REQUIRED, + "optional_float: 18446744073709551616"); + + // String literals x {Strings, Bytes} + for (const auto& field_type : std::vector{"String", "Bytes"}) { + const std::string field_name = + field_type == "String" ? "optional_string" : "optional_bytes"; + RunValidTextFormatTest( + StrCat("StringLiteralConcat", field_type), REQUIRED, + StrCat(field_name, ": 'first' \"second\"\n'third'")); + RunValidTextFormatTest( + StrCat("StringLiteralBasicEscapes", field_type), REQUIRED, + StrCat(field_name, ": '\\a\\b\\f\\n\\r\\t\\v\\?\\\\\\'\\\"'")); + RunValidTextFormatTest( + StrCat("StringLiteralOctalEscapes", field_type), REQUIRED, + StrCat(field_name, ": '\\341\\210\\264'")); + RunValidTextFormatTest(StrCat("StringLiteralHexEscapes", field_type), + REQUIRED, + StrCat(field_name, ": '\\xe1\\x88\\xb4'")); + RunValidTextFormatTest( + StrCat("StringLiteralShortUnicodeEscape", field_type), + RECOMMENDED, StrCat(field_name, ": '\\u1234'")); + RunValidTextFormatTest( + StrCat("StringLiteralLongUnicodeEscapes", field_type), + RECOMMENDED, StrCat(field_name, ": '\\U00001234\\U00010437'")); + // String literals don't include line feeds. + ExpectParseFailure(StrCat("StringLiteralIncludesLF", field_type), + REQUIRED, + StrCat(field_name, ": 'first line\nsecond line'")); + // Unicode escapes don't include code points that lie beyond the planes + // (> 0x10ffff). + ExpectParseFailure( + StrCat("StringLiteralLongUnicodeEscapeTooLarge", field_type), + REQUIRED, StrCat(field_name, ": '\\U00110000'")); + // Unicode escapes don't include surrogates. + ExpectParseFailure( + StrCat("StringLiteralShortUnicodeEscapeSurrogatePair", + field_type), + RECOMMENDED, StrCat(field_name, ": '\\ud801\\udc37'")); + ExpectParseFailure( + StrCat("StringLiteralShortUnicodeEscapeSurrogateFirstOnly", + field_type), + RECOMMENDED, StrCat(field_name, ": '\\ud800'")); + ExpectParseFailure( + StrCat("StringLiteralShortUnicodeEscapeSurrogateSecondOnly", + field_type), + RECOMMENDED, StrCat(field_name, ": '\\udc00'")); + ExpectParseFailure( + StrCat("StringLiteralLongUnicodeEscapeSurrogateFirstOnly", + field_type), + RECOMMENDED, StrCat(field_name, ": '\\U0000d800'")); + ExpectParseFailure( + StrCat("StringLiteralLongUnicodeEscapeSurrogateSecondOnly", + field_type), + RECOMMENDED, StrCat(field_name, ": '\\U0000dc00'")); + ExpectParseFailure( + StrCat("StringLiteralLongUnicodeEscapeSurrogatePair", field_type), + RECOMMENDED, StrCat(field_name, ": '\\U0000d801\\U00000dc37'")); + ExpectParseFailure( + StrCat("StringLiteralUnicodeEscapeSurrogatePairLongShort", + field_type), + RECOMMENDED, StrCat(field_name, ": '\\U0000d801\\udc37'")); + ExpectParseFailure( + StrCat("StringLiteralUnicodeEscapeSurrogatePairShortLong", + field_type), + RECOMMENDED, StrCat(field_name, ": '\\ud801\\U0000dc37'")); + + // The following method depend on the type of field, as strings have extra + // validation. + const auto test_method = + field_type == "String" + ? &TextFormatConformanceTestSuite::ExpectParseFailure + : &TextFormatConformanceTestSuite::RunValidTextFormatTest; + + // String fields reject invalid UTF-8 byte sequences; bytes fields don't. + (this->*test_method)(StrCat(field_type, "FieldBadUTF8Octal"), + REQUIRED, StrCat(field_name, ": '\\300'")); + (this->*test_method)(StrCat(field_type, "FieldBadUTF8Hex"), REQUIRED, + StrCat(field_name, ": '\\xc0'")); + } + + // Group fields + RunValidTextFormatTestProto2("GroupFieldNoColon", REQUIRED, + "Data { group_int32: 1 }"); + RunValidTextFormatTestProto2("GroupFieldWithColon", REQUIRED, + "Data: { group_int32: 1 }"); + RunValidTextFormatTestProto2("GroupFieldEmpty", REQUIRED, + "Data {}"); + + + // Unknown Fields + UnknownToTestAllTypes message; + // Unable to print unknown Fixed32/Fixed64 fields as if they are known. + // Fixed32/Fixed64 fields are not added in the tests. + message.set_optional_int32(123); + message.set_optional_string("hello"); + message.set_optional_bool(true); + RunValidUnknownTextFormatTest("ScalarUnknownFields", message); + + message.Clear(); + message.mutable_nested_message()->set_c(111); + RunValidUnknownTextFormatTest("MessageUnknownFields", message); + + message.Clear(); + message.mutable_optionalgroup()->set_a(321); + RunValidUnknownTextFormatTest("GroupUnknownFields", message); + + message.add_repeated_int32(1); + message.add_repeated_int32(2); + message.add_repeated_int32(3); + RunValidUnknownTextFormatTest("RepeatedUnknownFields", message); + + // Any fields + RunValidTextFormatTest("AnyField", REQUIRED, + R"( + optional_any: { + [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { + optional_int32: 12345 + } + } + )"); + RunValidTextFormatTest("AnyFieldWithRawBytes", REQUIRED, + R"( + optional_any: { + type_url: "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3" + value: "\b\271`" + } + )"); + ExpectParseFailure("AnyFieldWithInvalidType", REQUIRED, + R"( + optional_any: { + [type.googleapis.com/unknown] { + optional_int32: 12345 + } + } + )"); + + // Map fields + TestAllTypesProto3 prototype; + (*prototype.mutable_map_string_string())["c"] = "value"; + (*prototype.mutable_map_string_string())["b"] = "value"; + (*prototype.mutable_map_string_string())["a"] = "value"; + RunValidTextFormatTestWithMessage("AlphabeticallySortedMapStringKeys", + REQUIRED, + R"( + map_string_string { + key: "a" + value: "value" + } + map_string_string { + key: "b" + value: "value" + } + map_string_string { + key: "c" + value: "value" + } + )", + prototype); + + prototype.Clear(); + (*prototype.mutable_map_int32_int32())[3] = 0; + (*prototype.mutable_map_int32_int32())[2] = 0; + (*prototype.mutable_map_int32_int32())[1] = 0; + RunValidTextFormatTestWithMessage("AlphabeticallySortedMapIntKeys", REQUIRED, + R"( + map_int32_int32 { + key: 1 + value: 0 + } + map_int32_int32 { + key: 2 + value: 0 + } + map_int32_int32 { + key: 3 + value: 0 + } + )", + prototype); + + prototype.Clear(); + (*prototype.mutable_map_bool_bool())[true] = false; + (*prototype.mutable_map_bool_bool())[false] = false; + RunValidTextFormatTestWithMessage("AlphabeticallySortedMapBoolKeys", REQUIRED, + R"( + map_bool_bool { + key: false + value: false + } + map_bool_bool { + key: true + value: false + } + )", + prototype); +} + +} // namespace protobuf +} // namespace google diff --git a/conformance/text_format_conformance_suite.h b/conformance/text_format_conformance_suite.h new file mode 100644 index 0000000000000..d68f4aa3ef727 --- /dev/null +++ b/conformance/text_format_conformance_suite.h @@ -0,0 +1,69 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef TEXT_FORMAT_CONFORMANCE_SUITE_H_ +#define TEXT_FORMAT_CONFORMANCE_SUITE_H_ + +#include "conformance_test.h" + +namespace google { +namespace protobuf { + +class TextFormatConformanceTestSuite : public ConformanceTestSuite { + public: + TextFormatConformanceTestSuite(); + + private: + void RunSuiteImpl(); + void RunValidTextFormatTest(const std::string& test_name, + ConformanceLevel level, const std::string& input); + void RunValidTextFormatTestProto2(const std::string& test_name, + ConformanceLevel level, + const std::string& input); + void RunValidTextFormatTestWithMessage(const std::string& test_name, + ConformanceLevel level, + const std::string& input_text, + const Message& prototype); + void RunValidUnknownTextFormatTest(const std::string& test_name, + const Message& message); + void ExpectParseFailure(const std::string& test_name, ConformanceLevel level, + const std::string& input); + bool ParseTextFormatResponse(const conformance::ConformanceResponse& response, + const ConformanceRequestSetting& setting, + Message* test_message); + bool ParseResponse(const conformance::ConformanceResponse& response, + const ConformanceRequestSetting& setting, + Message* test_message) override; +}; + +} // namespace protobuf +} // namespace google + +#endif // TEXT_FORMAT_CONFORMANCE_SUITE_H_ diff --git a/conformance/text_format_failure_list_cpp.txt b/conformance/text_format_failure_list_cpp.txt new file mode 100644 index 0000000000000..a25f04faf2aa2 --- /dev/null +++ b/conformance/text_format_failure_list_cpp.txt @@ -0,0 +1,20 @@ +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString +Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex +Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal +Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes +Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString diff --git a/conformance/text_format_failure_list_csharp.txt b/conformance/text_format_failure_list_csharp.txt new file mode 100644 index 0000000000000..404b64a584313 --- /dev/null +++ b/conformance/text_format_failure_list_csharp.txt @@ -0,0 +1,8 @@ +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_java.txt b/conformance/text_format_failure_list_java.txt new file mode 100644 index 0000000000000..71e32429ec689 --- /dev/null +++ b/conformance/text_format_failure_list_java.txt @@ -0,0 +1,13 @@ +Recommended.Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput +Recommended.Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput +Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput +Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput +Required.Proto3.TextFormatInput.AnyField.ProtobufOutput +Required.Proto3.TextFormatInput.AnyField.TextFormatOutput + +Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex +Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput diff --git a/conformance/text_format_failure_list_jruby.txt b/conformance/text_format_failure_list_jruby.txt new file mode 100644 index 0000000000000..404b64a584313 --- /dev/null +++ b/conformance/text_format_failure_list_jruby.txt @@ -0,0 +1,8 @@ +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_php.txt b/conformance/text_format_failure_list_php.txt new file mode 100644 index 0000000000000..404b64a584313 --- /dev/null +++ b/conformance/text_format_failure_list_php.txt @@ -0,0 +1,8 @@ +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_python.txt b/conformance/text_format_failure_list_python.txt new file mode 100644 index 0000000000000..6bf7c1aa63623 --- /dev/null +++ b/conformance/text_format_failure_list_python.txt @@ -0,0 +1,34 @@ +# This is the list of text format conformance tests that are known to fail right +# now. +# TODO: These should be fixed. +Required.Proto3.TextFormatInput.FloatFieldMaxValue.ProtobufOutput +Required.Proto3.TextFormatInput.FloatFieldMaxValue.TextFormatOutput + +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput diff --git a/conformance/text_format_failure_list_python_2.7.txt b/conformance/text_format_failure_list_python_2.7.txt new file mode 100644 index 0000000000000..cada2bc03b2e3 --- /dev/null +++ b/conformance/text_format_failure_list_python_2.7.txt @@ -0,0 +1,36 @@ +# This is the list of text format conformance tests that are known to fail right +# now. +# TODO: These should be fixed. +Required.Proto3.TextFormatInput.FloatFieldMaxValue.ProtobufOutput +Required.Proto3.TextFormatInput.FloatFieldMaxValue.TextFormatOutput + +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput +Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes +Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString diff --git a/conformance/text_format_failure_list_python_cpp.txt b/conformance/text_format_failure_list_python_cpp.txt new file mode 100644 index 0000000000000..91fc2ea3cdaf0 --- /dev/null +++ b/conformance/text_format_failure_list_python_cpp.txt @@ -0,0 +1,28 @@ +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput diff --git a/conformance/text_format_failure_list_python_cpp_2.7.txt b/conformance/text_format_failure_list_python_cpp_2.7.txt new file mode 100644 index 0000000000000..ba2089bcaad39 --- /dev/null +++ b/conformance/text_format_failure_list_python_cpp_2.7.txt @@ -0,0 +1,30 @@ +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput +Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes +Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString diff --git a/conformance/text_format_failure_list_ruby.txt b/conformance/text_format_failure_list_ruby.txt new file mode 100644 index 0000000000000..404b64a584313 --- /dev/null +++ b/conformance/text_format_failure_list_ruby.txt @@ -0,0 +1,8 @@ +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/third_party/jsoncpp/json.h b/conformance/third_party/jsoncpp/json.h index 42e7e7f4ad036..373ec98bde97a 100644 --- a/conformance/third_party/jsoncpp/json.h +++ b/conformance/third_party/jsoncpp/json.h @@ -6,28 +6,28 @@ // ////////////////////////////////////////////////////////////////////// /* -The JsonCpp library's source code, including accompanying documentation, +The JsonCpp library's source code, including accompanying documentation, tests and demonstration applications, are licensed under the following conditions... -The author (Baptiste Lepilleur) explicitly disclaims copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, this software is released into the Public Domain. In jurisdictions which do not recognize Public Domain property (e.g. Germany as of 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is released under the terms of the MIT License (see below). -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual Public Domain/MIT License conditions described here, as they choose. The MIT License is about as close to Public Domain as a license can get, and is described in clear, concise terms at: http://en.wikipedia.org/wiki/MIT_License - + The full text of the MIT License follows: ======================================================================== @@ -434,7 +434,7 @@ class JSON_API Exception : public std::exception { /** Exceptions which the user cannot easily avoid. * * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input - * + * * \remark derived from Json::Exception */ class JSON_API RuntimeError : public Exception { @@ -445,7 +445,7 @@ class JSON_API RuntimeError : public Exception { /** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. * * These are precondition-violations (user bugs) and internal errors (our bugs). - * + * * \remark derived from Json::Exception */ class JSON_API LogicError : public Exception { @@ -1019,7 +1019,7 @@ class JSON_API PathArgument { * - ".name1.name2.name3" * - ".[0][1][2].name1[3]" * - ".%" => member name is provided as parameter - * - ".[%]" => index is provied as parameter + * - ".[%]" => index is provided as parameter */ class JSON_API Path { public: @@ -1371,7 +1371,7 @@ class JSON_API Reader { */ std::string getFormattedErrorMessages() const; - /** \brief Returns a vector of structured erros encounted while parsing. + /** \brief Returns a vector of structured errors encountered while parsing. * \return A (possibly empty) vector of StructuredError objects. Currently * only one error can be returned, but the caller should tolerate * multiple @@ -1570,7 +1570,7 @@ class JSON_API CharReaderBuilder : public CharReader::Factory { - `"rejectDupKeys": false or true` - If true, `parse()` returns false when a key is duplicated within an object. - `"allowSpecialFloats": false or true` - - If true, special float values (NaNs and infinities) are allowed + - If true, special float values (NaNs and infinities) are allowed and their values are lossfree restorable. You can examine 'settings_` yourself @@ -1816,7 +1816,7 @@ class JSON_API Writer { * * The JSON document is written in a single line. It is not intended for 'human' *consumption, - * but may be usefull to support feature such as RPC where bandwith is limited. + * but may be useful to support feature such as RPC where bandwidth is limited. * \sa Reader, Value * \deprecated Use StreamWriterBuilder. */ @@ -1867,7 +1867,7 @@ class JSON_API FastWriter : public Writer { * - otherwise, it the values do not fit on one line, or the array contains * object or non empty array, then print one value per line. * - * If the Value have comments then they are outputed according to their + * If the Value have comments then they are outputted according to their *#CommentPlacement. * * \sa Reader, Value, Value::setComment() @@ -1928,7 +1928,7 @@ class JSON_API StyledWriter : public Writer { * - otherwise, it the values do not fit on one line, or the array contains * object or non empty array, then print one value per line. * - * If the Value have comments then they are outputed according to their + * If the Value have comments then they are outputted according to their #CommentPlacement. * * \param indentation Each level will be indented by this amount extra. diff --git a/conformance/third_party/jsoncpp/jsoncpp.cpp b/conformance/third_party/jsoncpp/jsoncpp.cpp index f803962adeaa3..78919eac0f0c7 100644 --- a/conformance/third_party/jsoncpp/jsoncpp.cpp +++ b/conformance/third_party/jsoncpp/jsoncpp.cpp @@ -6,28 +6,28 @@ // ////////////////////////////////////////////////////////////////////// /* -The JsonCpp library's source code, including accompanying documentation, +The JsonCpp library's source code, including accompanying documentation, tests and demonstration applications, are licensed under the following conditions... -The author (Baptiste Lepilleur) explicitly disclaims copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, this software is released into the Public Domain. In jurisdictions which do not recognize Public Domain property (e.g. Germany as of 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is released under the terms of the MIT License (see below). -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual Public Domain/MIT License conditions described here, as they choose. The MIT License is about as close to Public Domain as a license can get, and is described in clear, concise terms at: http://en.wikipedia.org/wiki/MIT_License - + The full text of the MIT License follows: ======================================================================== @@ -142,7 +142,7 @@ enum { typedef char UIntToStringBuffer[uintToStringBufferSize]; /** Converts an unsigned integer to string. - * @param value Unsigned interger to convert to string + * @param value Unsigned integer to convert to string * @param current Input/Output string buffer. * Must have at least uintToStringBufferSize chars free. */ @@ -207,7 +207,7 @@ static inline void fixNumericLocale(char* begin, char* end) { #include #if defined(_MSC_VER) -#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above +#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above #define snprintf sprintf_s #elif _MSC_VER >= 1900 // VC++ 14.0 and above #define snprintf std::snprintf @@ -4029,7 +4029,7 @@ Value& Path::make(Value& root) const { #define snprintf std::snprintf #endif -#if defined(__BORLANDC__) +#if defined(__BORLANDC__) #include #define isfinite _finite #define snprintf _snprintf @@ -4112,7 +4112,7 @@ std::string valueToString(double value, bool useSpecialFloats, unsigned int prec sprintf(formatString, "%%.%dg", precision); // Print into the buffer. We need not request the alternative representation - // that always has a decimal point because JSON doesn't distingish the + // that always has a decimal point because JSON doesn't distinguish the // concepts of reals and integers. if (isfinite(value)) { len = snprintf(buffer, sizeof(buffer), formatString, value); @@ -5096,7 +5096,7 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const std::string cs_str = settings_["commentStyle"].asString(); bool eyc = settings_["enableYAMLCompatibility"].asBool(); bool dnp = settings_["dropNullPlaceholders"].asBool(); - bool usf = settings_["useSpecialFloats"].asBool(); + bool usf = settings_["useSpecialFloats"].asBool(); unsigned int pre = settings_["precision"].asUInt(); CommentStyle::Enum cs = CommentStyle::All; if (cs_str == "All") { diff --git a/conformance/update_failure_list.py b/conformance/update_failure_list.py index 63f453df1b29e..ad42ed3c187a1 100755 --- a/conformance/update_failure_list.py +++ b/conformance/update_failure_list.py @@ -35,7 +35,6 @@ """ import argparse -import fileinput parser = argparse.ArgumentParser( description='Adds/removes failures from the failure list.') @@ -62,7 +61,8 @@ add_list = sorted(add_set, reverse=True) -existing_list = file(args.filename).read() +with open(args.filename) as in_file: + existing_list = in_file.read() with open(args.filename, "w") as f: for line in existing_list.splitlines(True): diff --git a/csharp/.gitignore b/csharp/.gitignore index 8ba8849985dad..d0d7ae04f73b9 100644 --- a/csharp/.gitignore +++ b/csharp/.gitignore @@ -29,3 +29,6 @@ mono/*.exe mono/*.dll lib/protoc.exe *.ncrunch* + +# Benchmark output +BenchmarkDotNet.Artifacts/ diff --git a/csharp/CHANGES.txt b/csharp/CHANGES.txt index a87cd4d5dfcf5..8574b7c4a35db 100644 --- a/csharp/CHANGES.txt +++ b/csharp/CHANGES.txt @@ -26,7 +26,7 @@ Changes: - Optimized enum parsing. Fixes: -- Fix for bug in limited input stream's Position, Introduced Position on +- Fix for bug in limited input stream's Position, Introduced Position on output stream - Fix for writing a character to a JSON output overflows allocated buffer - Optimize FromBase64String to return Empty when presented with empty string. @@ -47,14 +47,14 @@ Changes: - Added 'Unsafe' static type in ByteString to allow direct buffer access Fixes: -- Issue 50: The XML serializer will fail to deserialize a message with empty +- Issue 50: The XML serializer will fail to deserialize a message with empty child message - Issue 45: Use of 'item' as a field name causes AmbiguousMatchException - Issue 49: Generated nested static Types class should be partial - Issue 38: Disable CLSCompliant warnings (3021) - Issue 40: proto_path does not work for command-line file names - Issue 54: should retire all bytes in buffer (bufferSize) -- Issue 43: Fix to correct identical 'umbrella_classname' options from trying +- Issue 43: Fix to correct identical 'umbrella_classname' options from trying to write to the same filename. =============================================================================== @@ -66,7 +66,7 @@ Features: NONE, GENERIC, INTERFACE, or IRPCDISPATCH - Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking services and implementations. -- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the +- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the location of protoc.exe. - Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow custom implementation of writers with both speed and size optimizations. @@ -86,9 +86,9 @@ Fixes: - Issue 16: Does not integrate well with other tooling - Issue 19: Support for negative enum values - Issue 26: AddRange in GeneratedBuilder iterates twice. -- Issue 27: Remove XML documentation output from test projects to clear +- Issue 27: Remove XML documentation output from test projects to clear warnings/errors. -- Issue 28: Circular message dependencies result in null default values for +- Issue 28: Circular message dependencies result in null default values for Message fields. - Issue 29: Message classes generated have a public default constructor. You can disable private ctor generation with the option generate_private_ctor. @@ -109,14 +109,14 @@ RELEASE NOTES - Version 2.3.0.277 =============================================================================== Features: -- Added cls_compliance option to generate attributes indicating +- Added cls_compliance option to generate attributes indicating non-CLS-compliance. - Added file_extension option to control the generated output file's extension. - Added umbrella_namespace option to place the umbrella class into a nested - namespace to address issues with proto files having the same name as a + namespace to address issues with proto files having the same name as a message it contains. - Added output_directory option to set the output path for the source file(s). -- Added ignore_google_protobuf option to avoid generating code for includes +- Added ignore_google_protobuf option to avoid generating code for includes from the google.protobuf package. - Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to generate code with "option optimize_for = LITE_RUNTIME;". diff --git a/csharp/Google.Protobuf.Tools.nuspec b/csharp/Google.Protobuf.Tools.nuspec index d32fd943c67a5..0e8b54d9abd15 100644 --- a/csharp/Google.Protobuf.Tools.nuspec +++ b/csharp/Google.Protobuf.Tools.nuspec @@ -1,37 +1,38 @@ - + Google.Protobuf.Tools Google Protocol Buffers tools Tools for Protocol Buffers - Google's data interchange format. See project site for more info. - 3.4.0 + 3.15.0 Google Inc. protobuf-packages - https://github.com/google/protobuf/blob/master/LICENSE - https://github.com/google/protobuf + https://github.com/protocolbuffers/protobuf/blob/master/LICENSE + https://github.com/protocolbuffers/protobuf false Tools for Protocol Buffers Copyright 2015, Google Inc. Protocol Buffers Binary Serialization Format Google proto proto3 - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/csharp/Google.Protobuf.Tools.targets b/csharp/Google.Protobuf.Tools.targets new file mode 100644 index 0000000000000..682e11b024f21 --- /dev/null +++ b/csharp/Google.Protobuf.Tools.targets @@ -0,0 +1,11 @@ + + + $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)/../tools/')) + $([System.IO.Path]::GetFullPath('$(protoc_tools)/linux_x64/protoc')) + $([System.IO.Path]::GetFullPath('$(protoc_tools)/linux_x86/protoc')) + $([System.IO.Path]::GetFullPath('$(protoc_tools)/macosx_x64/protoc')) + $([System.IO.Path]::GetFullPath('$(protoc_tools)/macosx_x86/protoc')) + $([System.IO.Path]::GetFullPath('$(protoc_tools)/windows_x64/protoc.exe')) + $([System.IO.Path]::GetFullPath('$(protoc_tools)/windows_x86/protoc.exe')) + + diff --git a/csharp/README.md b/csharp/README.md index c1d124194abf6..9aab782da19a9 100644 --- a/csharp/README.md +++ b/csharp/README.md @@ -10,7 +10,7 @@ You will also want to install the `Google.Protobuf.Tools` NuGet package, which contains precompiled version of `protoc.exe` and a copy of well known `.proto` files under the package's `tools` directory. -To generate C# files from your `.proto` files, invoke `protoc` with the +To generate C# files from your `.proto` files, invoke `protoc` with the `--csharp_out` option. Supported platforms @@ -37,34 +37,38 @@ later. Although *users* of this project are only expected to have Visual Studio 2012 or later, *developers* of the library are required to have Visual Studio 2017 or later, as the library uses C# 6 features -in its implementation, as well as the new Visual Studio 2017 csproj -format. These features have no impact when using the compiled code - +in its implementation, as well as the new Visual Studio 2017 csproj +format. These features have no impact when using the compiled code - they're only relevant when building the `Google.Protobuf` assembly. +In order to run and debug the AddressBook example in the IDE, you must +install the optional component, ".Net Core 1.0 - 1.1 development tools +for Web" (as it's labelled in current versions of the VS2017 +installer), above and beyond the main .NET Core cross-platform +development feature. + Testing ======= -The unit tests use [NUnit 3](https://github.com/nunit/nunit). NUnit doesn't yet -support `dotnet test`, so for now the test project is a console application -using NUnitLite. Simply run `Google.Protobuf.Test.exe` to run the unit tests -directly, or else use `dotnet run`. +The unit tests use [NUnit 3](https://github.com/nunit/nunit). Tests can be +run using the Visual Studio Test Explorer or `dotnet test`. .NET 3.5 ======== -We don't officially support .NET 3.5. However, there has been some effort -to make enabling .NET 3.5 support relatively painless in case you require it. -There's no guarantee that this will continue in the future, so rely on .NET +We don't officially support .NET 3.5. However, there has been some effort +to make enabling .NET 3.5 support relatively painless in case you require it. +There's no guarantee that this will continue in the future, so rely on .NET 3.5 support at your peril. -To enable .NET 3.5 support, you must edit the `TargetFrameworks` elements of -[src/Google.Protobuf/Google.Protobuf.csproj](src/Google.Protobuf/Google.Protobuf.csproj) -(and [src/Google.Protobuf.Test/Google.Protobuf.Test.csproj](src/Google.Protobuf.Test/Google.Protobuf.Test.csproj) -if you want to run the unit tests): +To enable .NET 3.5 support, you must edit the `TargetFrameworks` elements of +[src/Google.Protobuf/Google.Protobuf.csproj](src/Google.Protobuf/Google.Protobuf.csproj) +(and [src/Google.Protobuf.Test/Google.Protobuf.Test.csproj](src/Google.Protobuf.Test/Google.Protobuf.Test.csproj) +if you want to run the unit tests): -Open the .csproj file in a text editor and simply add `net35` to the list of -target frameworks, noting that the `TargetFrameworks` element appears twice in -the file (once in the first `PropertyGroup` element, and again in the second +Open the .csproj file in a text editor and simply add `net35` to the list of +target frameworks, noting that the `TargetFrameworks` element appears twice in +the file (once in the first `PropertyGroup` element, and again in the second `PropertyGroup` element, i.e., the one with the conditional). History of C# protobufs @@ -73,7 +77,7 @@ History of C# protobufs This subtree was originally imported from https://github.com/jskeet/protobuf-csharp-port and represents the latest development version of C# protobufs, that will now be developed and maintained by Google. All the development will be done in open, under this repository -(https://github.com/google/protobuf). +(https://github.com/protocolbuffers/protobuf). The previous project differs from this project in a number of ways: diff --git a/csharp/build_tools.sh b/csharp/build_tools.sh index 182c5c5c82eab..771affdc400c1 100755 --- a/csharp/build_tools.sh +++ b/csharp/build_tools.sh @@ -19,7 +19,6 @@ VERSION_NUMBER=$1 declare -a FILE_NAMES=( \ windows_x86 windows-x86_32.exe \ windows_x64 windows-x86_64.exe \ - macosx_x86 osx-x86_32.exe \ macosx_x64 osx-x86_64.exe \ linux_x86 linux-x86_32.exe \ linux_x64 linux-x86_64.exe \ diff --git a/csharp/buildall.bat b/csharp/buildall.bat new file mode 100644 index 0000000000000..821ffb3102bec --- /dev/null +++ b/csharp/buildall.bat @@ -0,0 +1,13 @@ +@rem Builds Google.Protobuf and runs the tests + +dotnet build src/Google.Protobuf.sln || goto :error + +echo Running tests. + +dotnet test src/Google.Protobuf.Test/Google.Protobuf.Test.csproj || goto :error + +goto :EOF + +:error +echo Failed! +exit /b %errorlevel% diff --git a/csharp/buildall.sh b/csharp/buildall.sh index dd4b463ddf5f8..43b5ac3ffb29a 100755 --- a/csharp/buildall.sh +++ b/csharp/buildall.sh @@ -10,8 +10,8 @@ dotnet restore $SRC/Google.Protobuf.sln dotnet build -c $CONFIG $SRC/Google.Protobuf.sln echo Running tests. -# Only test netcoreapp1.0, which uses the .NET Core runtime. +# Only test netcoreapp2.1, which uses the .NET Core runtime. # If we want to test the .NET 4.5 version separately, we could # run Mono explicitly. However, we don't have any differences between -# the .NET 4.5 and netstandard1.0 assemblies. -dotnet run -c $CONFIG -f netcoreapp1.0 -p $SRC/Google.Protobuf.Test/Google.Protobuf.Test.csproj +# the .NET 4.5 and netstandard2.1 assemblies. +dotnet test -c $CONFIG -f netcoreapp2.1 $SRC/Google.Protobuf.Test/Google.Protobuf.Test.csproj diff --git a/csharp/compatibility_tests/v3.0.0/protos/csharp/protos/unittest_issues.proto b/csharp/compatibility_tests/v3.0.0/protos/csharp/protos/unittest_issues.proto index 6c9f76344abe9..b6178bf1af69c 100644 --- a/csharp/compatibility_tests/v3.0.0/protos/csharp/protos/unittest_issues.proto +++ b/csharp/compatibility_tests/v3.0.0/protos/csharp/protos/unittest_issues.proto @@ -19,8 +19,8 @@ message Issue307 { } // Old issue 13: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=13 -// New issue 309: https://github.com/google/protobuf/issues/309 - +// New issue 309: https://github.com/protocolbuffers/protobuf/issues/309 + // message A { // optional int32 _A = 1; // } @@ -35,7 +35,7 @@ message Issue307 { // Similar issue with numeric names // Java code failed too, so probably best for this to be a restriction. -// See https://github.com/google/protobuf/issues/308 +// See https://github.com/protocolbuffers/protobuf/issues/308 // message NumberField { // optional int32 _01 = 1; // } @@ -101,21 +101,21 @@ message TestJsonFieldOrdering { // that will require fixing other tests in multiple platforms. // Alternatively, consider just adding this to // unittest_proto3.proto if multiple platforms want it. - + int32 plain_int32 = 4; oneof o1 { string o1_string = 2; int32 o1_int32 = 5; } - + string plain_string = 1; - + oneof o2 { int32 o2_int32 = 6; string o2_string = 3; } - + } message TestJsonName { diff --git a/csharp/compatibility_tests/v3.0.0/protos/src/google/protobuf/unittest_proto3.proto b/csharp/compatibility_tests/v3.0.0/protos/src/google/protobuf/unittest_proto3.proto index f59d217864537..6235d3da722fb 100644 --- a/csharp/compatibility_tests/v3.0.0/protos/src/google/protobuf/unittest_proto3.proto +++ b/csharp/compatibility_tests/v3.0.0/protos/src/google/protobuf/unittest_proto3.proto @@ -142,7 +142,7 @@ message TestAllTypes { } } -// This proto includes a recusively nested message. +// This proto includes a recursively nested message. message NestedTestAllTypes { NestedTestAllTypes child = 1; TestAllTypes payload = 2; diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs index ff44895c065cf..11d06f1d7b435 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs @@ -201,29 +201,29 @@ public void ReadLittleEndian() [Test] public void DecodeZigZag32() { - Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(0)); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(1)); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(2)); - Assert.AreEqual(-2, CodedInputStream.DecodeZigZag32(3)); - Assert.AreEqual(0x3FFFFFFF, CodedInputStream.DecodeZigZag32(0x7FFFFFFE)); - Assert.AreEqual(unchecked((int) 0xC0000000), CodedInputStream.DecodeZigZag32(0x7FFFFFFF)); - Assert.AreEqual(0x7FFFFFFF, CodedInputStream.DecodeZigZag32(0xFFFFFFFE)); - Assert.AreEqual(unchecked((int) 0x80000000), CodedInputStream.DecodeZigZag32(0xFFFFFFFF)); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(0)); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(1)); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(2)); + Assert.AreEqual(-2, ParsingPrimitives.DecodeZigZag32(3)); + Assert.AreEqual(0x3FFFFFFF, ParsingPrimitives.DecodeZigZag32(0x7FFFFFFE)); + Assert.AreEqual(unchecked((int) 0xC0000000), ParsingPrimitives.DecodeZigZag32(0x7FFFFFFF)); + Assert.AreEqual(0x7FFFFFFF, ParsingPrimitives.DecodeZigZag32(0xFFFFFFFE)); + Assert.AreEqual(unchecked((int) 0x80000000), ParsingPrimitives.DecodeZigZag32(0xFFFFFFFF)); } [Test] public void DecodeZigZag64() { - Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(0)); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(1)); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(2)); - Assert.AreEqual(-2, CodedInputStream.DecodeZigZag64(3)); - Assert.AreEqual(0x000000003FFFFFFFL, CodedInputStream.DecodeZigZag64(0x000000007FFFFFFEL)); - Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), CodedInputStream.DecodeZigZag64(0x000000007FFFFFFFL)); - Assert.AreEqual(0x000000007FFFFFFFL, CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFEL)); - Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFFL)); - Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL)); - Assert.AreEqual(unchecked((long) 0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL)); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(0)); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(1)); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(2)); + Assert.AreEqual(-2, ParsingPrimitives.DecodeZigZag64(3)); + Assert.AreEqual(0x000000003FFFFFFFL, ParsingPrimitives.DecodeZigZag64(0x000000007FFFFFFEL)); + Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), ParsingPrimitives.DecodeZigZag64(0x000000007FFFFFFFL)); + Assert.AreEqual(0x000000007FFFFFFFL, ParsingPrimitives.DecodeZigZag64(0x00000000FFFFFFFEL)); + Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), ParsingPrimitives.DecodeZigZag64(0x00000000FFFFFFFFL)); + Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, ParsingPrimitives.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL)); + Assert.AreEqual(unchecked((long) 0x8000000000000000L), ParsingPrimitives.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL)); } [Test] @@ -313,14 +313,14 @@ internal static void AssertMessageDepth(TestRecursiveMessage message, int depth) [Test] public void MaliciousRecursion() { - ByteString data64 = MakeRecursiveMessage(64).ToByteString(); - ByteString data65 = MakeRecursiveMessage(65).ToByteString(); + ByteString atRecursiveLimit = MakeRecursiveMessage(CodedInputStream.DefaultRecursionLimit).ToByteString(); + ByteString beyondRecursiveLimit = MakeRecursiveMessage(CodedInputStream.DefaultRecursionLimit + 1).ToByteString(); - AssertMessageDepth(TestRecursiveMessage.Parser.ParseFrom(data64), 64); + AssertMessageDepth(TestRecursiveMessage.Parser.ParseFrom(atRecursiveLimit), CodedInputStream.DefaultRecursionLimit); - Assert.Throws(() => TestRecursiveMessage.Parser.ParseFrom(data65)); + Assert.Throws(() => TestRecursiveMessage.Parser.ParseFrom(beyondRecursiveLimit)); - CodedInputStream input = CodedInputStream.CreateWithLimits(new MemoryStream(data64.ToByteArray()), 1000000, 63); + CodedInputStream input = CodedInputStream.CreateWithLimits(new MemoryStream(atRecursiveLimit.ToByteArray()), 1000000, CodedInputStream.DefaultRecursionLimit - 1); Assert.Throws(() => TestRecursiveMessage.Parser.ParseFrom(input)); } diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs index 01bd3218f3379..e9b4ea8cf0f37 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs @@ -211,35 +211,35 @@ public void WriteWholeMessage_VaryingBlockSizes() [Test] public void EncodeZigZag32() { - Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag32(0)); - Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag32(-1)); - Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag32(1)); - Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag32(-2)); - Assert.AreEqual(0x7FFFFFFEu, CodedOutputStream.EncodeZigZag32(0x3FFFFFFF)); - Assert.AreEqual(0x7FFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0xC0000000))); - Assert.AreEqual(0xFFFFFFFEu, CodedOutputStream.EncodeZigZag32(0x7FFFFFFF)); - Assert.AreEqual(0xFFFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0x80000000))); + Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag32(0)); + Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag32(-1)); + Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag32(1)); + Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag32(-2)); + Assert.AreEqual(0x7FFFFFFEu, WritingPrimitives.EncodeZigZag32(0x3FFFFFFF)); + Assert.AreEqual(0x7FFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0xC0000000))); + Assert.AreEqual(0xFFFFFFFEu, WritingPrimitives.EncodeZigZag32(0x7FFFFFFF)); + Assert.AreEqual(0xFFFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0x80000000))); } [Test] public void EncodeZigZag64() { - Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag64(0)); - Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag64(-1)); - Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag64(1)); - Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag64(-2)); + Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag64(0)); + Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag64(-1)); + Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag64(1)); + Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag64(-2)); Assert.AreEqual(0x000000007FFFFFFEuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL))); Assert.AreEqual(0x000000007FFFFFFFuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL))); Assert.AreEqual(0x00000000FFFFFFFEuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL))); Assert.AreEqual(0x00000000FFFFFFFFuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL))); Assert.AreEqual(0xFFFFFFFFFFFFFFFEL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL))); Assert.AreEqual(0xFFFFFFFFFFFFFFFFL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x8000000000000000UL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x8000000000000000UL))); } [Test] @@ -247,26 +247,26 @@ public void RoundTripZigZag32() { // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1) // were chosen semi-randomly via keyboard bashing. - Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0))); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1))); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1))); - Assert.AreEqual(14927, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927))); - Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612))); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(0))); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(1))); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-1))); + Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(14927))); + Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-3612))); } [Test] public void RoundTripZigZag64() { - Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0))); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1))); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1))); - Assert.AreEqual(14927, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927))); - Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612))); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(0))); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(1))); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-1))); + Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(14927))); + Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-3612))); Assert.AreEqual(856912304801416L, - CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L))); + ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(856912304801416L))); Assert.AreEqual(-75123905439571256L, - CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L))); + ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-75123905439571256L))); } [Test] @@ -395,7 +395,7 @@ public void Dispose_DisposesUnderlyingStream() Assert.IsTrue(memoryStream.CanWrite); using (var cos = new CodedOutputStream(memoryStream)) { - cos.WriteRawByte(0); + cos.WriteRawBytes(new byte[] {0}); Assert.AreEqual(0, memoryStream.Position); // Not flushed yet } Assert.AreEqual(1, memoryStream.ToArray().Length); // Flushed data from CodedOutputStream to MemoryStream @@ -409,7 +409,7 @@ public void Dispose_WithLeaveOpen() Assert.IsTrue(memoryStream.CanWrite); using (var cos = new CodedOutputStream(memoryStream, true)) { - cos.WriteRawByte(0); + cos.WriteRawBytes(new byte[] {0}); Assert.AreEqual(0, memoryStream.Position); // Not flushed yet } Assert.AreEqual(1, memoryStream.Position); // Flushed data from CodedOutputStream to MemoryStream diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Collections/MapFieldTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Collections/MapFieldTest.cs index 9c8459073c64f..3b4e1d33b1801 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Collections/MapFieldTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Collections/MapFieldTest.cs @@ -86,7 +86,7 @@ public void Indexer_ForbidsNullKeys() var map = new MapField(); Assert.Throws(() => map[null] = new ForeignMessage()); } - + [Test] public void AddPreservesInsertionOrder() { @@ -471,7 +471,7 @@ public void ViewCopyTo() keys.CopyTo(array, 1); CollectionAssert.AreEqual(new[] { null, "foo", "x", null }, array); } - + // Just test keys - we know the implementation is the same for values [Test] public void NonGenericViewCopyTo() diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs index f430b06beda3c..e8a3d360c2198 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs @@ -59,7 +59,7 @@ private void PrivateMethod() [TestCase(typeof(string), typeof(int), false)] [TestCase(typeof(int), typeof(int), true)] [TestCase(typeof(ValueType), typeof(int), true)] - [TestCase(typeof(long), typeof(int), false)] // + [TestCase(typeof(long), typeof(int), false)] // public void IsAssignableFrom(Type target, Type argument, bool expected) { Assert.AreEqual(expected, TypeExtensions.IsAssignableFrom(target, argument)); diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs index 0e2bad59e5fcf..18e8767217975 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs @@ -43,7 +43,7 @@ public class FieldCodecTest #pragma warning disable 0414 // Used by tests via reflection - do not remove! private static readonly List Codecs = new List { - new FieldCodecTestData(FieldCodec.ForBool(100), true, "Bool"), + new FieldCodecTestData(FieldCodec.ForBool(100), true, "FixedBool"), new FieldCodecTestData(FieldCodec.ForString(100), "sample", "String"), new FieldCodecTestData(FieldCodec.ForBytes(100), ByteString.CopyFrom(1, 2, 3), "Bytes"), new FieldCodecTestData(FieldCodec.ForInt32(100), -1000, "Int32"), @@ -56,8 +56,8 @@ public class FieldCodecTest new FieldCodecTestData(FieldCodec.ForSFixed64(100), -1000, "SFixed64"), new FieldCodecTestData(FieldCodec.ForUInt64(100), 1234, "UInt64"), new FieldCodecTestData(FieldCodec.ForFixed64(100), 1234, "Fixed64"), - new FieldCodecTestData(FieldCodec.ForFloat(100), 1234.5f, "Float"), - new FieldCodecTestData(FieldCodec.ForDouble(100), 1234567890.5d, "Double"), + new FieldCodecTestData(FieldCodec.ForFloat(100), 1234.5f, "FixedFloat"), + new FieldCodecTestData(FieldCodec.ForDouble(100), 1234567890.5d, "FixedDouble"), new FieldCodecTestData( FieldCodec.ForEnum(100, t => (int) t, t => (ForeignEnum) t), ForeignEnum.ForeignBaz, "Enum"), new FieldCodecTestData( @@ -124,11 +124,20 @@ public void TestRoundTripRaw() { var stream = new MemoryStream(); var codedOutput = new CodedOutputStream(stream); - codec.ValueWriter(codedOutput, sampleValue); + WriteContext.Initialize(codedOutput, out WriteContext ctx); + try + { + // only write the value using the codec + codec.ValueWriter(ref ctx, sampleValue); + } + finally + { + ctx.CopyStateTo(codedOutput); + } codedOutput.Flush(); stream.Position = 0; var codedInput = new CodedInputStream(stream); - Assert.AreEqual(sampleValue, codec.ValueReader(codedInput)); + Assert.AreEqual(sampleValue, codec.Read(codedInput)); Assert.IsTrue(codedInput.IsAtEnd); } @@ -172,13 +181,22 @@ public void TestDefaultValue() if (codec.DefaultValue != null) // This part isn't appropriate for message types. { codedOutput = new CodedOutputStream(stream); - codec.ValueWriter(codedOutput, codec.DefaultValue); + WriteContext.Initialize(codedOutput, out WriteContext ctx); + try + { + // only write the value using the codec + codec.ValueWriter(ref ctx, codec.DefaultValue); + } + finally + { + ctx.CopyStateTo(codedOutput); + } codedOutput.Flush(); Assert.AreNotEqual(0, stream.Position); Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue)); stream.Position = 0; var codedInput = new CodedInputStream(stream); - Assert.AreEqual(codec.DefaultValue, codec.ValueReader(codedInput)); + Assert.AreEqual(codec.DefaultValue, codec.Read(codedInput)); } } diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/GeneratedMessageTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/GeneratedMessageTest.cs index 8b153d691f273..429c51ff91d30 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/GeneratedMessageTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/GeneratedMessageTest.cs @@ -638,7 +638,7 @@ public void OneofSerialization_DefaultValue() } [Test] - public void IgnoreUnknownFields_RealDataStillRead() + public void DiscardUnknownFields_RealDataStillRead() { var message = SampleMessages.CreateFullTestAllTypes(); var stream = new MemoryStream(); @@ -652,16 +652,18 @@ public void IgnoreUnknownFields_RealDataStillRead() stream.Position = 0; var parsed = TestAllTypes.Parser.ParseFrom(stream); - Assert.AreEqual(message, parsed); + // TODO(jieluo): Add test back after DiscardUnknownFields is supported + // Assert.AreEqual(message, parsed); } [Test] - public void IgnoreUnknownFields_AllTypes() + public void DiscardUnknownFields_AllTypes() { // Simple way of ensuring we can skip all kinds of fields. var data = SampleMessages.CreateFullTestAllTypes().ToByteArray(); var empty = Empty.Parser.ParseFrom(data); - Assert.AreEqual(new Empty(), empty); + // TODO(jieluo): Add test back after DiscardUnknownField is supported. + // Assert.AreEqual(new Empty(), empty); } // This was originally seen as a conformance test failure. @@ -720,4 +722,4 @@ public void CustomDiagnosticMessage_DirectToTextWriterCall() Assert.AreEqual("{ \"c\": 31 }", writer.ToString()); } } -} \ No newline at end of file +} diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj index 06d07b9f4a54d..cbb6fee5f7d41 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj @@ -2,10 +2,9 @@ Exe - net451;netcoreapp1.0 + net451;netcoreapp2.1 ../../keys/Google.Protobuf.snk true - true False @@ -18,13 +17,9 @@ - - - netcoreapp1.0 - - + + + + + diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/JsonTokenizerTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/JsonTokenizerTest.cs index 527ab3361e9f7..2e690c182dfe0 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/JsonTokenizerTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/JsonTokenizerTest.cs @@ -240,7 +240,7 @@ public void SimpleObject() AssertTokens("{'x': 'y'}", JsonToken.StartObject, JsonToken.Name("x"), JsonToken.Value("y"), JsonToken.EndObject); } - + [Test] [TestCase("[10, 20", 3)] [TestCase("[10,", 2)] @@ -305,7 +305,7 @@ public void ArrayMixedType() [Test] public void ObjectMixedType() { - AssertTokens(@"{'a': 1, 'b': 'bar', 'c': null, 'd': false, 'e': true, + AssertTokens(@"{'a': 1, 'b': 'bar', 'c': null, 'd': false, 'e': true, 'f': [2], 'g': {'x':'y' }}", JsonToken.StartObject, JsonToken.Name("a"), @@ -349,12 +349,12 @@ public void CanPushBackEndDocument() Assert.AreEqual(JsonToken.EndDocument, tokenizer.Next()); Assert.Throws(() => tokenizer.Next()); } - + /// /// Asserts that the specified JSON is tokenized into the given sequence of tokens. /// All apostrophes are first converted to double quotes, allowing any tests /// that don't need to check actual apostrophe handling to use apostrophes in the JSON, avoiding - /// messy string literal escaping. The "end document" token is not specified in the list of + /// messy string literal escaping. The "end document" token is not specified in the list of /// expected tokens, but is implicit. /// private static void AssertTokens(string json, params JsonToken[] expectedTokens) @@ -366,7 +366,7 @@ private static void AssertTokens(string json, params JsonToken[] expectedTokens) /// Asserts that the specified JSON is tokenized into the given sequence of tokens. /// Unlike , this does not perform any character /// replacement on the specified JSON, and should be used when the text contains apostrophes which - /// are expected to be used *as* apostrophes. The "end document" token is not specified in the list of + /// are expected to be used *as* apostrophes. The "end document" token is not specified in the list of /// expected tokens, but is implicit. /// private static void AssertTokensNoReplacement(string json, params JsonToken[] expectedTokens) diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs index 52d5a6769729a..0520ada30aa8d 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs @@ -150,7 +150,7 @@ public void FieldDescriptor() Assert.AreEqual(UnittestProto3Reflection.Descriptor, primitiveField.File); Assert.AreEqual(FieldType.Int32, primitiveField.FieldType); Assert.IsNull(primitiveField.Proto.Options); - + Assert.AreEqual("single_nested_enum", enumField.Name); Assert.AreEqual(FieldType.Enum, enumField.FieldType); // Assert.AreEqual(TestAllTypes.Types.NestedEnum.DescriptorProtoFile, enumField.EnumType); @@ -242,7 +242,7 @@ public void MapEntryMessageDescriptor() // NestedMessage single_nested_message = 200; [Test] public void FieldListOrderings() - { + { var fields = TestFieldOrderings.Descriptor.Fields; Assert.AreEqual(new[] { 11, 1, 101, 200 }, fields.InDeclarationOrder().Select(x => x.FieldNumber)); Assert.AreEqual(new[] { 1, 11, 101, 200 }, fields.InFieldNumberOrder().Select(x => x.FieldNumber)); diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs index a488af30d44dd..46cb1afcd5fd1 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs @@ -213,6 +213,6 @@ public void FieldDescriptor_NotFound() var descriptor = TestAllTypes.Descriptor; Assert.Throws(() => descriptor.Fields[999999].ToString()); Assert.Throws(() => descriptor.Fields["not found"].ToString()); - } + } } } diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/SampleEnum.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/SampleEnum.cs index 77447afa12734..44f232a53ef6d 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/SampleEnum.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/SampleEnum.cs @@ -29,7 +29,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion - + namespace Google.Protobuf { // Just a sample enum with positive and negative values to be used in tests. diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs index 9ecd24c62a5b6..548c585a1c980 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs @@ -99,7 +99,7 @@ public void Arithmetic() Duration difference = new Duration { Seconds = 1999, Nanos = Duration.NanosecondsPerSecond - 5000 }; Assert.AreEqual(difference, t1 - t2); Assert.AreEqual(-difference, t2 - t1); - + Assert.AreEqual(t1, t2 + difference); Assert.AreEqual(t2, t1 - difference); } diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs index 5b7185dcd2dba..0df4ac4c79352 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs @@ -135,7 +135,7 @@ public void RepeatedWrappersSerializeDeserialize() DoubleField = { 12.5, -1.5, 0d }, FloatField = { 123.25f, -20f, 0f }, Int32Field = { int.MaxValue, int.MinValue, 0 }, - Int64Field = { long.MaxValue, long.MinValue, 0L }, + Int64Field = { long.MaxValue, long.MinValue, 0L }, StringField = { "First", "Second", "" }, Uint32Field = { uint.MaxValue, uint.MinValue, 0U }, Uint64Field = { ulong.MaxValue, ulong.MinValue, 0UL }, @@ -403,7 +403,7 @@ public void UnknownFieldInWrapper() output.Flush(); stream.Position = 0; - + var message = TestWellKnownTypes.Parser.ParseFrom(stream); Assert.AreEqual(6, message.Int32Field); } diff --git a/csharp/compatibility_tests/v3.0.0/test.sh b/csharp/compatibility_tests/v3.0.0/test.sh index 54d28dfc2608d..f893d64aba830 100755 --- a/csharp/compatibility_tests/v3.0.0/test.sh +++ b/csharp/compatibility_tests/v3.0.0/test.sh @@ -2,17 +2,17 @@ function run_test() { # Generate test proto files. - ./protoc_1 -Iprotos/src -I../../../src/ --csharp_out=src/Google.Protobuf.Test \ + $1 -Iprotos/src -I../../../src/ --csharp_out=src/Google.Protobuf.Test \ --csharp_opt=base_namespace=Google.Protobuf \ protos/src/google/protobuf/unittest_import_proto3.proto \ protos/src/google/protobuf/unittest_import_public_proto3.proto \ protos/src/google/protobuf/unittest_well_known_types.proto - ./protoc_1 -Iprotos/csharp --csharp_out=src/Google.Protobuf.Test \ + $1 -Iprotos/csharp --csharp_out=src/Google.Protobuf.Test \ --csharp_opt=base_namespace=UnitTest.Issues \ protos/csharp/protos/unittest_issues.proto - ./protoc_2 -Iprotos/src --csharp_out=src/Google.Protobuf.Test \ + $2 -Iprotos/src --csharp_out=src/Google.Protobuf.Test \ --csharp_opt=base_namespace=Google.Protobuf \ protos/src/google/protobuf/unittest_proto3.proto \ protos/src/google/protobuf/map_unittest_proto3.proto @@ -22,7 +22,7 @@ function run_test() { dotnet restore src/Google.Protobuf.Test/Google.Protobuf.Test.csproj dotnet build -c Release src/Google.Protobuf/Google.Protobuf.csproj dotnet build -c Release src/Google.Protobuf.Test/Google.Protobuf.Test.csproj - dotnet run -c Release -f netcoreapp1.0 -p src/Google.Protobuf.Test/Google.Protobuf.Test.csproj + dotnet run -c Release -f netcoreapp2.1 -p src/Google.Protobuf.Test/Google.Protobuf.Test.csproj } set -ex @@ -37,26 +37,10 @@ TEST_VERSION=3.0.0 # The old version of protobuf that we are testing compatibility against. This # is usually the same as TEST_VERSION (i.e., we use the tests extracted from # that version to test compatibility of the newest runtime against it), but it -# is also possible to use this same test set to test the compatibiilty of the +# is also possible to use this same test set to test the compatibility of the # latest version against other versions. -case "$1" in - ""|3.0.0) - OLD_VERSION=3.0.0 - OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0/protoc-3.0.0-linux-x86_64.exe - ;; - 3.0.2) - OLD_VERSION=3.0.2 - OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.2/protoc-3.0.2-linux-x86_64.exe - ;; - 3.1.0) - OLD_VERSION=3.1.0 - OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.1.0/protoc-3.1.0-linux-x86_64.exe - ;; - *) - echo "[ERROR]: Unknown version number: $1" - exit 1 - ;; -esac +OLD_VERSION=$1 +OLD_VERSION_PROTOC=https://repo1.maven.org/maven2/com/google/protobuf/protoc/$OLD_VERSION/protoc-$OLD_VERSION-linux-x86_64.exe echo "Running compatibility tests with $OLD_VERSION" @@ -79,26 +63,18 @@ cp ../../keys . -r # Test A.1: # proto set 1: use old version # proto set 2 which may import protos in set 1: use old version -cp old_protoc protoc_1 -cp old_protoc protoc_2 -run_test +run_test "./old_protoc" "./old_protoc" # Test A.2: # proto set 1: use new version # proto set 2 which may import protos in set 1: use old version -cp ../../../src/protoc protoc_1 -cp old_protoc protoc_2 -run_test +run_test "../../../src/protoc" "./old_protoc" # Test A.3: # proto set 1: use old version # proto set 2 which may import protos in set 1: use new version -cp old_protoc protoc_1 -cp ../../../src/protoc protoc_2 -run_test +run_test "./old_protoc" "../../../src/protoc" -rm protoc_1 -rm protoc_2 rm old_protoc rm keys -r rm src/Google.Protobuf -r diff --git a/csharp/generate_protos.sh b/csharp/generate_protos.sh index d2f474796f988..b663138d10871 100755 --- a/csharp/generate_protos.sh +++ b/csharp/generate_protos.sh @@ -3,7 +3,7 @@ # You first need to make sure protoc has been built (see instructions on # building protoc in root of this repository) -set -ex +set -e # cd to repository root pushd $(dirname $0)/.. @@ -40,29 +40,48 @@ $PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf \ src/google/protobuf/type.proto \ src/google/protobuf/wrappers.proto -# Test protos where the namespace matches the target location -$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf.Test \ - --csharp_opt=base_namespace=Google.Protobuf \ - src/google/protobuf/map_unittest_proto3.proto \ - src/google/protobuf/unittest_proto3.proto \ - src/google/protobuf/unittest_import_proto3.proto \ - src/google/protobuf/unittest_import_public_proto3.proto \ - src/google/protobuf/unittest_well_known_types.proto - -# Different base namespace to the protos above -$PROTOC -Isrc -Icsharp/protos --csharp_out=csharp/src/Google.Protobuf.Test \ - --csharp_opt=base_namespace=UnitTest.Issues \ +# Test protos +# Note that this deliberately does *not* include old_extensions1.proto +# and old_extensions2.proto, which are generated with an older version +# of protoc. +$PROTOC -Isrc -Icsharp/protos \ + --experimental_allow_proto3_optional \ + --csharp_out=csharp/src/Google.Protobuf.Test.TestProtos \ + --descriptor_set_out=csharp/src/Google.Protobuf.Test/testprotos.pb \ + --include_source_info \ + --include_imports \ + csharp/protos/map_unittest_proto3.proto \ csharp/protos/unittest_issues.proto \ - csharp/protos/unittest_custom_options_proto3.proto - -# Don't specify a base namespace at all; we just want to make sure the -# results end up in TestProtos. -$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf.Test/TestProtos \ - src/google/protobuf/test_messages_proto3.proto + csharp/protos/unittest_custom_options_proto3.proto \ + csharp/protos/unittest_proto3.proto \ + csharp/protos/unittest_import_proto3.proto \ + csharp/protos/unittest_import_public_proto3.proto \ + csharp/protos/unittest.proto \ + csharp/protos/unittest_import.proto \ + csharp/protos/unittest_import_public.proto \ + csharp/protos/unittest_issue6936_a.proto \ + csharp/protos/unittest_issue6936_b.proto \ + csharp/protos/unittest_issue6936_c.proto \ + csharp/protos/unittest_selfreferential_options.proto \ + src/google/protobuf/unittest_well_known_types.proto \ + src/google/protobuf/test_messages_proto3.proto \ + src/google/protobuf/test_messages_proto2.proto \ + src/google/protobuf/unittest_proto3_optional.proto # AddressBook sample protos -$PROTOC -Iexamples --csharp_out=csharp/src/AddressBook \ +$PROTOC -Iexamples -Isrc --csharp_out=csharp/src/AddressBook \ examples/addressbook.proto $PROTOC -Iconformance -Isrc --csharp_out=csharp/src/Google.Protobuf.Conformance \ conformance/conformance.proto + +# Benchmark protos +$PROTOC -Ibenchmarks \ + benchmarks/datasets/google_message1/proto3/*.proto \ + benchmarks/benchmarks.proto \ + --csharp_out=csharp/src/Google.Protobuf.Benchmarks + +# C# only benchmark protos +$PROTOC -Isrc -Icsharp/src/Google.Protobuf.Benchmarks \ + csharp/src/Google.Protobuf.Benchmarks/*.proto \ + --csharp_out=csharp/src/Google.Protobuf.Benchmarks diff --git a/csharp/global.json b/csharp/global.json deleted file mode 100644 index 3622b564942f2..0000000000000 --- a/csharp/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "version": "1.0.0" - } -} diff --git a/csharp/install_dotnet_sdk.ps1 b/csharp/install_dotnet_sdk.ps1 new file mode 100755 index 0000000000000..8bc967c9f4d68 --- /dev/null +++ b/csharp/install_dotnet_sdk.ps1 @@ -0,0 +1,20 @@ +#!/usr/bin/env powershell +# Install dotnet SDK using the official dotnet-install.ps1 script + +Set-StrictMode -Version 2 +$ErrorActionPreference = 'Stop' + +# avoid "Unknown error on a send" in Invoke-WebRequest +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + +$InstallScriptUrl = 'https://dot.net/v1/dotnet-install.ps1' +$InstallScriptPath = Join-Path "$env:TEMP" 'dotnet-install.ps1' + +# Download install script +Write-Host "Downloading install script: $InstallScriptUrl => $InstallScriptPath" +Invoke-WebRequest -Uri $InstallScriptUrl -OutFile $InstallScriptPath + +# The SDK versions to install should be kept in sync with versions +# installed by kokoro/linux/dockerfile/test/csharp/Dockerfile +&$InstallScriptPath -Version 2.1.802 +&$InstallScriptPath -Version 3.1.301 diff --git a/csharp/protos/README.md b/csharp/protos/README.md new file mode 100644 index 0000000000000..bdd66fcf3958b --- /dev/null +++ b/csharp/protos/README.md @@ -0,0 +1,3 @@ +This directory contains unit test protos adapted from those in +src/google/protobuf, and C#-specific test protos for regression +tests against bugs found in the C# codegen or library. diff --git a/src/google/protobuf/map_unittest_proto3.proto b/csharp/protos/map_unittest_proto3.proto similarity index 93% rename from src/google/protobuf/map_unittest_proto3.proto rename to csharp/protos/map_unittest_proto3.proto index 16be277304bc7..e43e858bc1fd6 100644 --- a/src/google/protobuf/map_unittest_proto3.proto +++ b/csharp/protos/map_unittest_proto3.proto @@ -36,15 +36,11 @@ // required fields in proto3. syntax = "proto3"; -option cc_enable_arenas = true; option csharp_namespace = "Google.Protobuf.TestProtos"; -import "google/protobuf/unittest_proto3.proto"; +import "unittest_proto3.proto"; -// We don't put this in a package within proto2 because we need to make sure -// that the generated code doesn't depend on being in the proto2 namespace. -// In map_test_util.h we do "using namespace unittest = protobuf_unittest". -package protobuf_unittest; +package protobuf_unittest3; // Tests maps. message TestMap { diff --git a/csharp/protos/old_extensions1.proto b/csharp/protos/old_extensions1.proto new file mode 100644 index 0000000000000..58f6eb580c9a7 --- /dev/null +++ b/csharp/protos/old_extensions1.proto @@ -0,0 +1,52 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file we will use for unit testing. +// +// LINT: ALLOW_GROUPS, LEGACY_NAMES + +// This file is part of the unit test for issue #6822. It is +// generated with protoc from version 3.10.1. + +syntax = "proto3"; + +// Import the proto file containing the extension. We don't use it, +// but the import is what caused the issue. +import "old_extensions2.proto"; + +option csharp_namespace = "Google.Protobuf.TestProtos.OldGenerator"; + +// We don't use this message other than to get its descriptor. +message TestMessage { +} diff --git a/csharp/protos/old_extensions2.proto b/csharp/protos/old_extensions2.proto new file mode 100644 index 0000000000000..78f732a8ad43f --- /dev/null +++ b/csharp/protos/old_extensions2.proto @@ -0,0 +1,50 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file we will use for unit testing. +// +// LINT: ALLOW_GROUPS, LEGACY_NAMES + +// This file is part of the unit test for issue #6822. It is +// generated with protoc from version 3.10.1. + +syntax = "proto3"; + +import "google/protobuf/descriptor.proto"; + +option csharp_namespace = "Google.Protobuf.TestProtos.OldGenerator"; + +extend google.protobuf.MethodOptions { + string method_ext = 1234567; +} \ No newline at end of file diff --git a/csharp/protos/unittest.proto b/csharp/protos/unittest.proto new file mode 100644 index 0000000000000..9628b9e0f4484 --- /dev/null +++ b/csharp/protos/unittest.proto @@ -0,0 +1,1113 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file we will use for unit testing. +// +// LINT: ALLOW_GROUPS, LEGACY_NAMES + +syntax = "proto2"; + +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option cc_generic_services = true; // auto-added +option java_generic_services = true; // auto-added +option py_generic_services = true; // auto-added +option cc_enable_arenas = true; + +import "unittest_import.proto"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +// In test_util.h we do "using namespace unittest = protobuf_unittest". +package protobuf_unittest_proto2; + +// Protos optimized for SPEED use a strict superset of the generated code +// of equivalent ones optimized for CODE_SIZE, so we should optimize all our +// tests for speed unless explicitly testing code size optimization. +option optimize_for = SPEED; + +option csharp_namespace = "Google.Protobuf.TestProtos.Proto2"; + +// This proto includes every type of field in both singular and repeated +// forms. +message TestAllTypes { + message NestedMessage { + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + optional int32 bb = 1; + } + + enum NestedEnum { + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + optional int32 optional_int32 = 1; + optional int64 optional_int64 = 2; + optional uint32 optional_uint32 = 3; + optional uint64 optional_uint64 = 4; + optional sint32 optional_sint32 = 5; + optional sint64 optional_sint64 = 6; + optional fixed32 optional_fixed32 = 7; + optional fixed64 optional_fixed64 = 8; + optional sfixed32 optional_sfixed32 = 9; + optional sfixed64 optional_sfixed64 = 10; + optional float optional_float = 11; + optional double optional_double = 12; + optional bool optional_bool = 13; + optional string optional_string = 14; + optional bytes optional_bytes = 15; + + optional group OptionalGroup = 16 { + optional int32 a = 17; + } + + optional NestedMessage optional_nested_message = 18; + optional ForeignMessage optional_foreign_message = 19; + optional protobuf_unittest_import_proto2.ImportMessage optional_import_message = 20; + + optional NestedEnum optional_nested_enum = 21; + optional ForeignEnum optional_foreign_enum = 22; + optional protobuf_unittest_import_proto2.ImportEnum optional_import_enum = 23; + + optional string optional_string_piece = 24 [ctype=STRING_PIECE]; + optional string optional_cord = 25 [ctype=CORD]; + + // Defined in unittest_import_public.proto + optional protobuf_unittest_import_proto2.PublicImportMessage + optional_public_import_message = 26; + + optional NestedMessage optional_lazy_message = 27 [lazy=true]; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated group RepeatedGroup = 46 { + optional int32 a = 47; + } + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + repeated protobuf_unittest_import_proto2.ImportMessage repeated_import_message = 50; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + repeated protobuf_unittest_import_proto2.ImportEnum repeated_import_enum = 53; + + repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; + repeated string repeated_cord = 55 [ctype=CORD]; + + repeated NestedMessage repeated_lazy_message = 57 [lazy=true]; + + // Singular with defaults + optional int32 default_int32 = 61 [default = 41 ]; + optional int64 default_int64 = 62 [default = 42 ]; + optional uint32 default_uint32 = 63 [default = 43 ]; + optional uint64 default_uint64 = 64 [default = 44 ]; + optional sint32 default_sint32 = 65 [default = -45 ]; + optional sint64 default_sint64 = 66 [default = 46 ]; + optional fixed32 default_fixed32 = 67 [default = 47 ]; + optional fixed64 default_fixed64 = 68 [default = 48 ]; + optional sfixed32 default_sfixed32 = 69 [default = 49 ]; + optional sfixed64 default_sfixed64 = 70 [default = -50 ]; + optional float default_float = 71 [default = 51.5 ]; + optional double default_double = 72 [default = 52e3 ]; + optional bool default_bool = 73 [default = true ]; + optional string default_string = 74 [default = "hello"]; + optional bytes default_bytes = 75 [default = "world"]; + + optional NestedEnum default_nested_enum = 81 [default = BAR ]; + optional ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR]; + optional protobuf_unittest_import_proto2.ImportEnum + default_import_enum = 83 [default = IMPORT_BAR]; + + optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"]; + optional string default_cord = 85 [ctype=CORD,default="123"]; + + // For oneof test + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } +} + +// This proto includes a recursively nested message. +message NestedTestAllTypes { + optional NestedTestAllTypes child = 1; + optional TestAllTypes payload = 2; + repeated NestedTestAllTypes repeated_child = 3; +} + +message TestDeprecatedFields { + optional int32 deprecated_int32 = 1 [deprecated=true]; + oneof oneof_fields { + int32 deprecated_int32_in_oneof = 2 [deprecated=true]; + } +} + +message TestDeprecatedMessage { + option deprecated = true; +} + +// Define these after TestAllTypes to make sure the compiler can handle +// that. +message ForeignMessage { + optional int32 c = 1; + optional int32 d = 2; +} + +enum ForeignEnum { + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; +} + +message TestReservedFields { + reserved 2, 15, 9 to 11; + reserved "bar", "baz"; +} + +message TestAllExtensions { + extensions 1 to max; +} + +extend TestAllExtensions { + // Singular + optional int32 optional_int32_extension = 1; + optional int64 optional_int64_extension = 2; + optional uint32 optional_uint32_extension = 3; + optional uint64 optional_uint64_extension = 4; + optional sint32 optional_sint32_extension = 5; + optional sint64 optional_sint64_extension = 6; + optional fixed32 optional_fixed32_extension = 7; + optional fixed64 optional_fixed64_extension = 8; + optional sfixed32 optional_sfixed32_extension = 9; + optional sfixed64 optional_sfixed64_extension = 10; + optional float optional_float_extension = 11; + optional double optional_double_extension = 12; + optional bool optional_bool_extension = 13; + optional string optional_string_extension = 14; + optional bytes optional_bytes_extension = 15; + + optional group OptionalGroup_extension = 16 { + optional int32 a = 17; + } + + optional TestAllTypes.NestedMessage optional_nested_message_extension = 18; + optional ForeignMessage optional_foreign_message_extension = 19; + optional protobuf_unittest_import_proto2.ImportMessage + optional_import_message_extension = 20; + + optional TestAllTypes.NestedEnum optional_nested_enum_extension = 21; + optional ForeignEnum optional_foreign_enum_extension = 22; + optional protobuf_unittest_import_proto2.ImportEnum + optional_import_enum_extension = 23; + + optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE]; + optional string optional_cord_extension = 25 [ctype=CORD]; + + optional protobuf_unittest_import_proto2.PublicImportMessage + optional_public_import_message_extension = 26; + + optional TestAllTypes.NestedMessage + optional_lazy_message_extension = 27 [lazy=true]; + + // Repeated + repeated int32 repeated_int32_extension = 31; + repeated int64 repeated_int64_extension = 32; + repeated uint32 repeated_uint32_extension = 33; + repeated uint64 repeated_uint64_extension = 34; + repeated sint32 repeated_sint32_extension = 35; + repeated sint64 repeated_sint64_extension = 36; + repeated fixed32 repeated_fixed32_extension = 37; + repeated fixed64 repeated_fixed64_extension = 38; + repeated sfixed32 repeated_sfixed32_extension = 39; + repeated sfixed64 repeated_sfixed64_extension = 40; + repeated float repeated_float_extension = 41; + repeated double repeated_double_extension = 42; + repeated bool repeated_bool_extension = 43; + repeated string repeated_string_extension = 44; + repeated bytes repeated_bytes_extension = 45; + + repeated group RepeatedGroup_extension = 46 { + optional int32 a = 47; + } + + repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 48; + repeated ForeignMessage repeated_foreign_message_extension = 49; + repeated protobuf_unittest_import_proto2.ImportMessage + repeated_import_message_extension = 50; + + repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51; + repeated ForeignEnum repeated_foreign_enum_extension = 52; + repeated protobuf_unittest_import_proto2.ImportEnum + repeated_import_enum_extension = 53; + + repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE]; + repeated string repeated_cord_extension = 55 [ctype=CORD]; + + repeated TestAllTypes.NestedMessage + repeated_lazy_message_extension = 57 [lazy=true]; + + // Singular with defaults + optional int32 default_int32_extension = 61 [default = 41 ]; + optional int64 default_int64_extension = 62 [default = 42 ]; + optional uint32 default_uint32_extension = 63 [default = 43 ]; + optional uint64 default_uint64_extension = 64 [default = 44 ]; + optional sint32 default_sint32_extension = 65 [default = -45 ]; + optional sint64 default_sint64_extension = 66 [default = 46 ]; + optional fixed32 default_fixed32_extension = 67 [default = 47 ]; + optional fixed64 default_fixed64_extension = 68 [default = 48 ]; + optional sfixed32 default_sfixed32_extension = 69 [default = 49 ]; + optional sfixed64 default_sfixed64_extension = 70 [default = -50 ]; + optional float default_float_extension = 71 [default = 51.5 ]; + optional double default_double_extension = 72 [default = 52e3 ]; + optional bool default_bool_extension = 73 [default = true ]; + optional string default_string_extension = 74 [default = "hello"]; + optional bytes default_bytes_extension = 75 [default = "world"]; + + optional TestAllTypes.NestedEnum + default_nested_enum_extension = 81 [default = BAR]; + optional ForeignEnum + default_foreign_enum_extension = 82 [default = FOREIGN_BAR]; + optional protobuf_unittest_import_proto2.ImportEnum + default_import_enum_extension = 83 [default = IMPORT_BAR]; + + optional string default_string_piece_extension = 84 [ctype=STRING_PIECE, + default="abc"]; + optional string default_cord_extension = 85 [ctype=CORD, default="123"]; + + // For oneof test + optional uint32 oneof_uint32_extension = 111; + optional TestAllTypes.NestedMessage oneof_nested_message_extension = 112; + optional string oneof_string_extension = 113; + optional bytes oneof_bytes_extension = 114; +} + +message TestGroup { + optional group OptionalGroup = 16 { + optional int32 a = 17; + } + optional ForeignEnum optional_foreign_enum = 22; +} + +message TestGroupExtension { + extensions 1 to max; +} + +message TestNestedExtension { + extend TestAllExtensions { + // Check for bug where string extensions declared in tested scope did not + // compile. + optional string test = 1002 [default="test"]; + // Used to test if generated extension name is correct when there are + // underscores. + optional string nested_string_extension = 1003; + } + + extend TestGroupExtension { + optional group OptionalGroup_extension = 16 { + optional int32 a = 17; + } + optional ForeignEnum optional_foreign_enum_extension = 22; + } +} + +// We have separate messages for testing required fields because it's +// annoying to have to fill in required fields in TestProto in order to +// do anything with it. Note that we don't need to test every type of +// required filed because the code output is basically identical to +// optional fields for all types. +message TestRequired { + required int32 a = 1; + optional int32 dummy2 = 2; + required int32 b = 3; + + extend TestAllExtensions { + optional TestRequired single = 1000; + repeated TestRequired multi = 1001; + } + + // Pad the field count to 32 so that we can test that IsInitialized() + // properly checks multiple elements of has_bits_. + optional int32 dummy4 = 4; + optional int32 dummy5 = 5; + optional int32 dummy6 = 6; + optional int32 dummy7 = 7; + optional int32 dummy8 = 8; + optional int32 dummy9 = 9; + optional int32 dummy10 = 10; + optional int32 dummy11 = 11; + optional int32 dummy12 = 12; + optional int32 dummy13 = 13; + optional int32 dummy14 = 14; + optional int32 dummy15 = 15; + optional int32 dummy16 = 16; + optional int32 dummy17 = 17; + optional int32 dummy18 = 18; + optional int32 dummy19 = 19; + optional int32 dummy20 = 20; + optional int32 dummy21 = 21; + optional int32 dummy22 = 22; + optional int32 dummy23 = 23; + optional int32 dummy24 = 24; + optional int32 dummy25 = 25; + optional int32 dummy26 = 26; + optional int32 dummy27 = 27; + optional int32 dummy28 = 28; + optional int32 dummy29 = 29; + optional int32 dummy30 = 30; + optional int32 dummy31 = 31; + optional int32 dummy32 = 32; + + required int32 c = 33; +} + +message TestRequiredForeign { + optional TestRequired optional_message = 1; + repeated TestRequired repeated_message = 2; + optional int32 dummy = 3; +} + +message TestRequiredMessage { + optional TestRequired optional_message = 1; + repeated TestRequired repeated_message = 2; + required TestRequired required_message = 3; +} + +// Test that we can use NestedMessage from outside TestAllTypes. +message TestForeignNested { + optional TestAllTypes.NestedMessage foreign_nested = 1; +} + +// TestEmptyMessage is used to test unknown field support. +message TestEmptyMessage { +} + +// Like above, but declare all field numbers as potential extensions. No +// actual extensions should ever be defined for this type. +message TestEmptyMessageWithExtensions { + extensions 1 to max; +} + +message TestMultipleExtensionRanges { + extensions 42; + extensions 4143 to 4243; + extensions 65536 to max; +} + +// Test that really large tag numbers don't break anything. +message TestReallyLargeTagNumber { + // The largest possible tag number is 2^28 - 1, since the wire format uses + // three bits to communicate wire type. + optional int32 a = 1; + optional int32 bb = 268435455; +} + +message TestRecursiveMessage { + optional TestRecursiveMessage a = 1; + optional int32 i = 2; +} + +// Test that mutual recursion works. +message TestMutualRecursionA { + message SubMessage { + optional TestMutualRecursionB b = 1; + } + optional TestMutualRecursionB bb = 1; + optional group SubGroup = 2 { + optional SubMessage sub_message = 3; // Needed because of bug in javatest + optional TestAllTypes not_in_this_scc = 4; + } +} + +message TestMutualRecursionB { + optional TestMutualRecursionA a = 1; + optional int32 optional_int32 = 2; +} + +message TestIsInitialized { + message SubMessage { + optional group SubGroup = 1 { + required int32 i = 2; + } + } + optional SubMessage sub_message = 1; +} + +// Test that groups have disjoint field numbers from their siblings and +// parents. This is NOT possible in proto1; only google.protobuf. When attempting +// to compile with proto1, this will emit an error; so we only include it +// in protobuf_unittest_proto. +message TestDupFieldNumber { // NO_PROTO1 + optional int32 a = 1; // NO_PROTO1 + optional group Foo = 2 { optional int32 a = 1; } // NO_PROTO1 + optional group Bar = 3 { optional int32 a = 1; } // NO_PROTO1 +} // NO_PROTO1 + +// Additional messages for testing lazy fields. +message TestEagerMessage { + optional TestAllTypes sub_message = 1 [lazy=false]; +} +message TestLazyMessage { + optional TestAllTypes sub_message = 1 [lazy=true]; +} + +// Needed for a Python test. +message TestNestedMessageHasBits { + message NestedMessage { + repeated int32 nestedmessage_repeated_int32 = 1; + repeated ForeignMessage nestedmessage_repeated_foreignmessage = 2; + } + optional NestedMessage optional_nested_message = 1; +} + + +// Test an enum that has multiple values with the same number. +enum TestEnumWithDupValue { + option allow_alias = true; + + FOO1 = 1; + BAR1 = 2; + BAZ = 3; + FOO2 = 1; + BAR2 = 2; +} + +// Test an enum with large, unordered values. +enum TestSparseEnum { + SPARSE_A = 123; + SPARSE_B = 62374; + SPARSE_C = 12589234; + SPARSE_D = -15; + SPARSE_E = -53452; + SPARSE_F = 0; + SPARSE_G = 2; +} + +// Test message with CamelCase field names. This violates Protocol Buffer +// standard style. +message TestCamelCaseFieldNames { + optional int32 PrimitiveField = 1; + optional string StringField = 2; + optional ForeignEnum EnumField = 3; + optional ForeignMessage MessageField = 4; + optional string StringPieceField = 5 [ctype=STRING_PIECE]; + optional string CordField = 6 [ctype=CORD]; + + repeated int32 RepeatedPrimitiveField = 7; + repeated string RepeatedStringField = 8; + repeated ForeignEnum RepeatedEnumField = 9; + repeated ForeignMessage RepeatedMessageField = 10; + repeated string RepeatedStringPieceField = 11 [ctype=STRING_PIECE]; + repeated string RepeatedCordField = 12 [ctype=CORD]; +} + + +// We list fields out of order, to ensure that we're using field number and not +// field index to determine serialization order. +message TestFieldOrderings { + optional string my_string = 11; + extensions 2 to 10; + optional int64 my_int = 1; + extensions 12 to 100; + optional float my_float = 101; + message NestedMessage { + optional int64 oo = 2; + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + optional int32 bb = 1; + } + + optional NestedMessage optional_nested_message = 200; +} + +extend TestFieldOrderings { + optional string my_extension_string = 50; + optional int32 my_extension_int = 5; +} + +message TestExtensionOrderings1 { + extend TestFieldOrderings { + optional TestExtensionOrderings1 test_ext_orderings1 = 13; + } + optional string my_string = 1; +} + +message TestExtensionOrderings2 { + extend TestFieldOrderings { + optional TestExtensionOrderings2 test_ext_orderings2 = 12; + } + message TestExtensionOrderings3 { + extend TestFieldOrderings { + optional TestExtensionOrderings3 test_ext_orderings3 = 14; + } + optional string my_string = 1; + } + optional string my_string = 1; +} + +message TestExtremeDefaultValues { + optional bytes escaped_bytes = 1 [default = "\0\001\a\b\f\n\r\t\v\\\'\"\xfe"]; + optional uint32 large_uint32 = 2 [default = 0xFFFFFFFF]; + optional uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF]; + optional int32 small_int32 = 4 [default = -0x7FFFFFFF]; + optional int64 small_int64 = 5 [default = -0x7FFFFFFFFFFFFFFF]; + optional int32 really_small_int32 = 21 [default = -0x80000000]; + optional int64 really_small_int64 = 22 [default = -0x8000000000000000]; + + // The default value here is UTF-8 for "\u1234". (We could also just type + // the UTF-8 text directly into this text file rather than escape it, but + // lots of people use editors that would be confused by this.) + optional string utf8_string = 6 [default = "\341\210\264"]; + + // Tests for single-precision floating-point values. + optional float zero_float = 7 [default = 0]; + optional float one_float = 8 [default = 1]; + optional float small_float = 9 [default = 1.5]; + optional float negative_one_float = 10 [default = -1]; + optional float negative_float = 11 [default = -1.5]; + // Using exponents + optional float large_float = 12 [default = 2E8]; + optional float small_negative_float = 13 [default = -8e-28]; + + // Text for nonfinite floating-point values. + optional double inf_double = 14 [default = inf]; + optional double neg_inf_double = 15 [default = -inf]; + optional double nan_double = 16 [default = nan]; + optional float inf_float = 17 [default = inf]; + optional float neg_inf_float = 18 [default = -inf]; + optional float nan_float = 19 [default = nan]; + + // Tests for C++ trigraphs. + // Trigraphs should be escaped in C++ generated files, but they should not be + // escaped for other languages. + // Note that in .proto file, "\?" is a valid way to escape ? in string + // literals. + optional string cpp_trigraph = 20 [default = "? \? ?? \?? \??? ??/ ?\?-"]; + + // String defaults containing the character '\000' + optional string string_with_zero = 23 [default = "hel\000lo"]; + optional bytes bytes_with_zero = 24 [default = "wor\000ld"]; + optional string string_piece_with_zero = 25 [ctype=STRING_PIECE, + default="ab\000c"]; + optional string cord_with_zero = 26 [ctype=CORD, + default="12\0003"]; + optional string replacement_string = 27 [default="${unknown}"]; +} + +message SparseEnumMessage { + optional TestSparseEnum sparse_enum = 1; +} + +// Test String and Bytes: string is for valid UTF-8 strings +message OneString { + optional string data = 1; +} + +message MoreString { + repeated string data = 1; +} + +message OneBytes { + optional bytes data = 1; +} + +message MoreBytes { + repeated bytes data = 1; +} + +// Test int32, uint32, int64, uint64, and bool are all compatible +message Int32Message { + optional int32 data = 1; +} + +message Uint32Message { + optional uint32 data = 1; +} + +message Int64Message { + optional int64 data = 1; +} + +message Uint64Message { + optional uint64 data = 1; +} + +message BoolMessage { + optional bool data = 1; +} + +// Test oneofs. +message TestOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + TestAllTypes foo_message = 3; + group FooGroup = 4 { + optional int32 a = 5; + optional string b = 6; + } + } +} + +message TestOneofBackwardsCompatible { + optional int32 foo_int = 1; + optional string foo_string = 2; + optional TestAllTypes foo_message = 3; + optional group FooGroup = 4 { + optional int32 a = 5; + optional string b = 6; + } +} + +message TestOneof2 { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + string foo_cord = 3 [ctype=CORD]; + string foo_string_piece = 4 [ctype=STRING_PIECE]; + bytes foo_bytes = 5; + NestedEnum foo_enum = 6; + NestedMessage foo_message = 7; + group FooGroup = 8 { + optional int32 a = 9; + optional string b = 10; + } + NestedMessage foo_lazy_message = 11 [lazy=true]; + } + + oneof bar { + int32 bar_int = 12 [default = 5]; + string bar_string = 13 [default = "STRING"]; + string bar_cord = 14 [ctype=CORD, default = "CORD"]; + string bar_string_piece = 15 [ctype=STRING_PIECE, default = "SPIECE"]; + bytes bar_bytes = 16 [default = "BYTES"]; + NestedEnum bar_enum = 17 [default = BAR]; + } + + optional int32 baz_int = 18; + optional string baz_string = 19 [default = "BAZ"]; + + message NestedMessage { + optional int64 qux_int = 1; + repeated int32 corge_int = 2; + } + + enum NestedEnum { + FOO = 1; + BAR = 2; + BAZ = 3; + } +} + +message TestRequiredOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + NestedMessage foo_message = 3; + } + message NestedMessage { + required double required_double = 1; + } +} + +message TestRequiredMap { + map foo = 1; + message NestedMessage { + required int32 required_int32 = 1; + } +} + +// Test messages for packed fields + +message TestPackedTypes { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnum packed_enum = 103 [packed = true]; +} + +// A message with the same fields as TestPackedTypes, but without packing. Used +// to test packed <-> unpacked wire compatibility. +message TestUnpackedTypes { + repeated int32 unpacked_int32 = 90 [packed = false]; + repeated int64 unpacked_int64 = 91 [packed = false]; + repeated uint32 unpacked_uint32 = 92 [packed = false]; + repeated uint64 unpacked_uint64 = 93 [packed = false]; + repeated sint32 unpacked_sint32 = 94 [packed = false]; + repeated sint64 unpacked_sint64 = 95 [packed = false]; + repeated fixed32 unpacked_fixed32 = 96 [packed = false]; + repeated fixed64 unpacked_fixed64 = 97 [packed = false]; + repeated sfixed32 unpacked_sfixed32 = 98 [packed = false]; + repeated sfixed64 unpacked_sfixed64 = 99 [packed = false]; + repeated float unpacked_float = 100 [packed = false]; + repeated double unpacked_double = 101 [packed = false]; + repeated bool unpacked_bool = 102 [packed = false]; + repeated ForeignEnum unpacked_enum = 103 [packed = false]; +} + +message TestPackedExtensions { + extensions 1 to max; +} + +extend TestPackedExtensions { + repeated int32 packed_int32_extension = 90 [packed = true]; + repeated int64 packed_int64_extension = 91 [packed = true]; + repeated uint32 packed_uint32_extension = 92 [packed = true]; + repeated uint64 packed_uint64_extension = 93 [packed = true]; + repeated sint32 packed_sint32_extension = 94 [packed = true]; + repeated sint64 packed_sint64_extension = 95 [packed = true]; + repeated fixed32 packed_fixed32_extension = 96 [packed = true]; + repeated fixed64 packed_fixed64_extension = 97 [packed = true]; + repeated sfixed32 packed_sfixed32_extension = 98 [packed = true]; + repeated sfixed64 packed_sfixed64_extension = 99 [packed = true]; + repeated float packed_float_extension = 100 [packed = true]; + repeated double packed_double_extension = 101 [packed = true]; + repeated bool packed_bool_extension = 102 [packed = true]; + repeated ForeignEnum packed_enum_extension = 103 [packed = true]; +} + +message TestUnpackedExtensions { + extensions 1 to max; +} + +extend TestUnpackedExtensions { + repeated int32 unpacked_int32_extension = 90 [packed = false]; + repeated int64 unpacked_int64_extension = 91 [packed = false]; + repeated uint32 unpacked_uint32_extension = 92 [packed = false]; + repeated uint64 unpacked_uint64_extension = 93 [packed = false]; + repeated sint32 unpacked_sint32_extension = 94 [packed = false]; + repeated sint64 unpacked_sint64_extension = 95 [packed = false]; + repeated fixed32 unpacked_fixed32_extension = 96 [packed = false]; + repeated fixed64 unpacked_fixed64_extension = 97 [packed = false]; + repeated sfixed32 unpacked_sfixed32_extension = 98 [packed = false]; + repeated sfixed64 unpacked_sfixed64_extension = 99 [packed = false]; + repeated float unpacked_float_extension = 100 [packed = false]; + repeated double unpacked_double_extension = 101 [packed = false]; + repeated bool unpacked_bool_extension = 102 [packed = false]; + repeated ForeignEnum unpacked_enum_extension = 103 [packed = false]; +} + +// Used by ExtensionSetTest/DynamicExtensions. The test actually builds +// a set of extensions to TestAllExtensions dynamically, based on the fields +// of this message type. +message TestDynamicExtensions { + enum DynamicEnumType { + DYNAMIC_FOO = 2200; + DYNAMIC_BAR = 2201; + DYNAMIC_BAZ = 2202; + } + message DynamicMessageType { + optional int32 dynamic_field = 2100; + } + + optional fixed32 scalar_extension = 2000; + optional ForeignEnum enum_extension = 2001; + optional DynamicEnumType dynamic_enum_extension = 2002; + + optional ForeignMessage message_extension = 2003; + optional DynamicMessageType dynamic_message_extension = 2004; + + repeated string repeated_extension = 2005; + repeated sint32 packed_extension = 2006 [packed = true]; +} + +message TestRepeatedScalarDifferentTagSizes { + // Parsing repeated fixed size values used to fail. This message needs to be + // used in order to get a tag of the right size; all of the repeated fields + // in TestAllTypes didn't trigger the check. + repeated fixed32 repeated_fixed32 = 12; + // Check for a varint type, just for good measure. + repeated int32 repeated_int32 = 13; + + // These have two-byte tags. + repeated fixed64 repeated_fixed64 = 2046; + repeated int64 repeated_int64 = 2047; + + // Three byte tags. + repeated float repeated_float = 262142; + repeated uint64 repeated_uint64 = 262143; +} + +// Test that if an optional or required message/group field appears multiple +// times in the input, they need to be merged. +message TestParsingMerge { + // RepeatedFieldsGenerator defines matching field types as TestParsingMerge, + // except that all fields are repeated. In the tests, we will serialize the + // RepeatedFieldsGenerator to bytes, and parse the bytes to TestParsingMerge. + // Repeated fields in RepeatedFieldsGenerator are expected to be merged into + // the corresponding required/optional fields in TestParsingMerge. + message RepeatedFieldsGenerator { + repeated TestAllTypes field1 = 1; + repeated TestAllTypes field2 = 2; + repeated TestAllTypes field3 = 3; + repeated group Group1 = 10 { + optional TestAllTypes field1 = 11; + } + repeated group Group2 = 20 { + optional TestAllTypes field1 = 21; + } + repeated TestAllTypes ext1 = 1000; + repeated TestAllTypes ext2 = 1001; + } + required TestAllTypes required_all_types = 1; + optional TestAllTypes optional_all_types = 2; + repeated TestAllTypes repeated_all_types = 3; + optional group OptionalGroup = 10 { + optional TestAllTypes optional_group_all_types = 11; + } + repeated group RepeatedGroup = 20 { + optional TestAllTypes repeated_group_all_types = 21; + } + extensions 1000 to max; + extend TestParsingMerge { + optional TestAllTypes optional_ext = 1000; + repeated TestAllTypes repeated_ext = 1001; + } +} + +message TestCommentInjectionMessage { + // */ <- This should not close the generated doc comment + optional string a = 1 [default="*/ <- Neither should this."]; +} + + +// Test that RPC services work. +message FooRequest {} +message FooResponse {} + +message FooClientMessage {} +message FooServerMessage{} + +service TestService { + rpc Foo(FooRequest) returns (FooResponse); + rpc Bar(BarRequest) returns (BarResponse); +} + + +message BarRequest {} +message BarResponse {} + +message TestJsonName { + optional int32 field_name1 = 1; + optional int32 fieldName2 = 2; + optional int32 FieldName3 = 3; + optional int32 _field_name4 = 4; + optional int32 FIELD_NAME5 = 5; + optional int32 field_name6 = 6 [json_name = "@type"]; +} + +message TestHugeFieldNumbers { + optional int32 optional_int32 = 536870000; + optional int32 fixed_32 = 536870001; + repeated int32 repeated_int32 = 536870002 [packed = false]; + repeated int32 packed_int32 = 536870003 [packed = true]; + + optional ForeignEnum optional_enum = 536870004; + optional string optional_string = 536870005; + optional bytes optional_bytes = 536870006; + optional ForeignMessage optional_message = 536870007; + + optional group OptionalGroup = 536870008 { + optional int32 group_a = 536870009; + } + + map string_string_map = 536870010; + + oneof oneof_field { + uint32 oneof_uint32 = 536870011; + TestAllTypes oneof_test_all_types = 536870012; + string oneof_string = 536870013; + bytes oneof_bytes = 536870014; + } + + extensions 536860000 to 536869999; +} + +extend TestHugeFieldNumbers { + optional TestAllTypes test_all_types = 536860000; +} + +message TestExtensionInsideTable { + optional int32 field1 = 1; + optional int32 field2 = 2; + optional int32 field3 = 3; + optional int32 field4 = 4; + extensions 5 to 5; + optional int32 field6 = 6; + optional int32 field7 = 7; + optional int32 field8 = 8; + optional int32 field9 = 9; + optional int32 field10 = 10; +} + +extend TestExtensionInsideTable { + optional int32 test_extension_inside_table_extension = 5; +} + +enum VeryLargeEnum { + ENUM_LABEL_DEFAULT = 0; + ENUM_LABEL_1 = 1; + ENUM_LABEL_2 = 2; + ENUM_LABEL_3 = 3; + ENUM_LABEL_4 = 4; + ENUM_LABEL_5 = 5; + ENUM_LABEL_6 = 6; + ENUM_LABEL_7 = 7; + ENUM_LABEL_8 = 8; + ENUM_LABEL_9 = 9; + ENUM_LABEL_10 = 10; + ENUM_LABEL_11 = 11; + ENUM_LABEL_12 = 12; + ENUM_LABEL_13 = 13; + ENUM_LABEL_14 = 14; + ENUM_LABEL_15 = 15; + ENUM_LABEL_16 = 16; + ENUM_LABEL_17 = 17; + ENUM_LABEL_18 = 18; + ENUM_LABEL_19 = 19; + ENUM_LABEL_20 = 20; + ENUM_LABEL_21 = 21; + ENUM_LABEL_22 = 22; + ENUM_LABEL_23 = 23; + ENUM_LABEL_24 = 24; + ENUM_LABEL_25 = 25; + ENUM_LABEL_26 = 26; + ENUM_LABEL_27 = 27; + ENUM_LABEL_28 = 28; + ENUM_LABEL_29 = 29; + ENUM_LABEL_30 = 30; + ENUM_LABEL_31 = 31; + ENUM_LABEL_32 = 32; + ENUM_LABEL_33 = 33; + ENUM_LABEL_34 = 34; + ENUM_LABEL_35 = 35; + ENUM_LABEL_36 = 36; + ENUM_LABEL_37 = 37; + ENUM_LABEL_38 = 38; + ENUM_LABEL_39 = 39; + ENUM_LABEL_40 = 40; + ENUM_LABEL_41 = 41; + ENUM_LABEL_42 = 42; + ENUM_LABEL_43 = 43; + ENUM_LABEL_44 = 44; + ENUM_LABEL_45 = 45; + ENUM_LABEL_46 = 46; + ENUM_LABEL_47 = 47; + ENUM_LABEL_48 = 48; + ENUM_LABEL_49 = 49; + ENUM_LABEL_50 = 50; + ENUM_LABEL_51 = 51; + ENUM_LABEL_52 = 52; + ENUM_LABEL_53 = 53; + ENUM_LABEL_54 = 54; + ENUM_LABEL_55 = 55; + ENUM_LABEL_56 = 56; + ENUM_LABEL_57 = 57; + ENUM_LABEL_58 = 58; + ENUM_LABEL_59 = 59; + ENUM_LABEL_60 = 60; + ENUM_LABEL_61 = 61; + ENUM_LABEL_62 = 62; + ENUM_LABEL_63 = 63; + ENUM_LABEL_64 = 64; + ENUM_LABEL_65 = 65; + ENUM_LABEL_66 = 66; + ENUM_LABEL_67 = 67; + ENUM_LABEL_68 = 68; + ENUM_LABEL_69 = 69; + ENUM_LABEL_70 = 70; + ENUM_LABEL_71 = 71; + ENUM_LABEL_72 = 72; + ENUM_LABEL_73 = 73; + ENUM_LABEL_74 = 74; + ENUM_LABEL_75 = 75; + ENUM_LABEL_76 = 76; + ENUM_LABEL_77 = 77; + ENUM_LABEL_78 = 78; + ENUM_LABEL_79 = 79; + ENUM_LABEL_80 = 80; + ENUM_LABEL_81 = 81; + ENUM_LABEL_82 = 82; + ENUM_LABEL_83 = 83; + ENUM_LABEL_84 = 84; + ENUM_LABEL_85 = 85; + ENUM_LABEL_86 = 86; + ENUM_LABEL_87 = 87; + ENUM_LABEL_88 = 88; + ENUM_LABEL_89 = 89; + ENUM_LABEL_90 = 90; + ENUM_LABEL_91 = 91; + ENUM_LABEL_92 = 92; + ENUM_LABEL_93 = 93; + ENUM_LABEL_94 = 94; + ENUM_LABEL_95 = 95; + ENUM_LABEL_96 = 96; + ENUM_LABEL_97 = 97; + ENUM_LABEL_98 = 98; + ENUM_LABEL_99 = 99; + ENUM_LABEL_100 = 100; +}; diff --git a/csharp/protos/unittest_custom_options_proto3.proto b/csharp/protos/unittest_custom_options_proto3.proto index 87bd0f7a84dca..0e7c2e276c87e 100644 --- a/csharp/protos/unittest_custom_options_proto3.proto +++ b/csharp/protos/unittest_custom_options_proto3.proto @@ -286,7 +286,7 @@ message Aggregate { } // Allow Aggregate to be used as an option at all possible locations -// in the .proto grammer. +// in the .proto grammar. extend google.protobuf.FileOptions { Aggregate fileopt = 15478479; } extend google.protobuf.MessageOptions { Aggregate msgopt = 15480088; } extend google.protobuf.FieldOptions { Aggregate fieldopt = 15481374; } diff --git a/csharp/protos/unittest_import.proto b/csharp/protos/unittest_import.proto new file mode 100644 index 0000000000000..a0198c34f11cf --- /dev/null +++ b/csharp/protos/unittest_import.proto @@ -0,0 +1,69 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file which is imported by unittest.proto to test importing. + +syntax = "proto2"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +// In test_util.h we do +// "using namespace unittest_import = protobuf_unittest_import". +package protobuf_unittest_import_proto2; + +option optimize_for = SPEED; +option cc_enable_arenas = true; + +option csharp_namespace = "Google.Protobuf.TestProtos.Proto2"; + +// Test public import +import public "unittest_import_public.proto"; + +message ImportMessage { + optional int32 d = 1; +} + +enum ImportEnum { + IMPORT_FOO = 7; + IMPORT_BAR = 8; + IMPORT_BAZ = 9; +} + + +// To use an enum in a map, it must has the first value as 0. +enum ImportEnumForMap { + UNKNOWN = 0; + FOO = 1; + BAR = 2; +} diff --git a/src/google/protobuf/unittest_import_proto3.proto b/csharp/protos/unittest_import_proto3.proto similarity index 79% rename from src/google/protobuf/unittest_import_proto3.proto rename to csharp/protos/unittest_import_proto3.proto index 59673eaf9d43b..2e6668228663b 100644 --- a/src/google/protobuf/unittest_import_proto3.proto +++ b/csharp/protos/unittest_import_proto3.proto @@ -36,24 +36,12 @@ syntax = "proto3"; -// We don't put this in a package within proto2 because we need to make sure -// that the generated code doesn't depend on being in the proto2 namespace. -// In test_util.h we do -// "using namespace unittest_import = protobuf_unittest_import". package protobuf_unittest_import; -option optimize_for = SPEED; -option cc_enable_arenas = true; - -// Exercise the java_package option. -option java_package = "com.google.protobuf.test"; option csharp_namespace = "Google.Protobuf.TestProtos"; -// Do not set a java_outer_classname here to verify that Proto2 works without -// one. - // Test public import -import public "google/protobuf/unittest_import_public_proto3.proto"; +import public "unittest_import_public_proto3.proto"; message ImportMessage { int32 d = 1; diff --git a/csharp/protos/unittest_import_public.proto b/csharp/protos/unittest_import_public.proto new file mode 100644 index 0000000000000..6ae34efec60a1 --- /dev/null +++ b/csharp/protos/unittest_import_public.proto @@ -0,0 +1,41 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: liujisi@google.com (Pherl Liu) + +syntax = "proto2"; + +package protobuf_unittest_import_proto2; + +option csharp_namespace = "Google.Protobuf.TestProtos.Proto2"; + +message PublicImportMessage { + optional int32 e = 1; +} diff --git a/src/google/protobuf/unittest_import_public_proto3.proto b/csharp/protos/unittest_import_public_proto3.proto similarity index 97% rename from src/google/protobuf/unittest_import_public_proto3.proto rename to csharp/protos/unittest_import_public_proto3.proto index d6f11e28bd1bf..88c20799ae928 100644 --- a/src/google/protobuf/unittest_import_public_proto3.proto +++ b/csharp/protos/unittest_import_public_proto3.proto @@ -34,7 +34,6 @@ syntax = "proto3"; package protobuf_unittest_import; -option java_package = "com.google.protobuf.test"; option csharp_namespace = "Google.Protobuf.TestProtos"; message PublicImportMessage { diff --git a/csharp/protos/unittest_issue6936_a.proto b/csharp/protos/unittest_issue6936_a.proto new file mode 100644 index 0000000000000..097d083a98a73 --- /dev/null +++ b/csharp/protos/unittest_issue6936_a.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +package unittest_issues; + +option csharp_namespace = "UnitTest.Issues.TestProtos"; + +// This file is used as part of a unit test for issue 6936 +// We don't need to use it, we just have to import it in both +// "extensions_issue6936_b.proto" and "extensions_issue6936_c.proto" + +import "google/protobuf/descriptor.proto"; + +extend google.protobuf.MessageOptions { + string opt = 50000; +} \ No newline at end of file diff --git a/csharp/protos/unittest_issue6936_b.proto b/csharp/protos/unittest_issue6936_b.proto new file mode 100644 index 0000000000000..8f71683ba675a --- /dev/null +++ b/csharp/protos/unittest_issue6936_b.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +import "unittest_issue6936_a.proto"; + +package unittest_issues; + +option csharp_namespace = "UnitTest.Issues.TestProtos"; + +// This file is used as part of a unit test for issue 6936 +// We don't need to use it, we just have to import it in "unittest_issue6936_c.proto" + +message Foo { + option (opt) = "foo"; +} \ No newline at end of file diff --git a/csharp/protos/unittest_issue6936_c.proto b/csharp/protos/unittest_issue6936_c.proto new file mode 100644 index 0000000000000..40004ecaaee3a --- /dev/null +++ b/csharp/protos/unittest_issue6936_c.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +import "unittest_issue6936_a.proto"; +import "unittest_issue6936_b.proto"; + +package unittest_issues; + +option csharp_namespace = "UnitTest.Issues.TestProtos"; + +// This file is used as part of a unit test for issue 6936 +// We don't need to use it, we just have to load it at runtime + +message Bar { + option (opt) = "bar"; + Foo foo = 1; +} \ No newline at end of file diff --git a/csharp/protos/unittest_issues.proto b/csharp/protos/unittest_issues.proto index 6c9f76344abe9..388998f0a0ea1 100644 --- a/csharp/protos/unittest_issues.proto +++ b/csharp/protos/unittest_issues.proto @@ -7,7 +7,8 @@ syntax = "proto3"; option csharp_namespace = "UnitTest.Issues.TestProtos"; package unittest_issues; -option optimize_for = SPEED; + +import "google/protobuf/struct.proto"; // Issue 307: when generating doubly-nested types, any references // should be of the form A.Types.B.Types.C. @@ -19,8 +20,8 @@ message Issue307 { } // Old issue 13: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=13 -// New issue 309: https://github.com/google/protobuf/issues/309 - +// New issue 309: https://github.com/protocolbuffers/protobuf/issues/309 + // message A { // optional int32 _A = 1; // } @@ -35,7 +36,7 @@ message Issue307 { // Similar issue with numeric names // Java code failed too, so probably best for this to be a restriction. -// See https://github.com/google/protobuf/issues/308 +// See https://github.com/protocolbuffers/protobuf/issues/308 // message NumberField { // optional int32 _01 = 1; // } @@ -101,21 +102,21 @@ message TestJsonFieldOrdering { // that will require fixing other tests in multiple platforms. // Alternatively, consider just adding this to // unittest_proto3.proto if multiple platforms want it. - + int32 plain_int32 = 4; oneof o1 { string o1_string = 2; int32 o1_int32 = 5; } - + string plain_string = 1; - + oneof o2 { int32 o2_int32 = 6; string o2_string = 3; } - + } message TestJsonName { @@ -124,3 +125,34 @@ message TestJsonName { string description = 2 [json_name = "desc"]; string guid = 3 [json_name = "exid"]; } + +// Issue 3200: When merging two messages which use the same +// oneof case, which is itself a message type, the submessages should +// be merged. +message OneofMerging { + message Nested { + int32 x = 1; + int32 y = 2; + } + + oneof value { + string text = 1; + Nested nested = 2; + } +} + +message NullValueOutsideStruct { + oneof value { + string string_value = 1; + google.protobuf.NullValue null_value = 2; + } +} + +message NullValueNotInOneof { + google.protobuf.NullValue null_value = 2; +} + +message MixedRegularAndOptional { + string regular_field = 1; + optional string optional_field = 2; +} diff --git a/csharp/protos/unittest_proto3.proto b/csharp/protos/unittest_proto3.proto new file mode 100644 index 0000000000000..8c2f2c9e365f6 --- /dev/null +++ b/csharp/protos/unittest_proto3.proto @@ -0,0 +1,410 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file we will use for unit testing. + +syntax = "proto3"; + +option csharp_namespace = "Google.Protobuf.TestProtos"; + +// Only present so we can test that we can read it (as an example +// of a non-C# option) +option java_outer_classname = "UnittestProto"; + +import "unittest_import_proto3.proto"; + +package protobuf_unittest3; + +// This proto includes every type of field in both singular and repeated +// forms. +message TestAllTypes { + message NestedMessage { + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + enum NestedEnum { + NESTED_ENUM_UNSPECIFIED = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 single_int32 = 1; + int64 single_int64 = 2; + uint32 single_uint32 = 3; + uint64 single_uint64 = 4; + sint32 single_sint32 = 5; + sint64 single_sint64 = 6; + fixed32 single_fixed32 = 7; + fixed64 single_fixed64 = 8; + sfixed32 single_sfixed32 = 9; + sfixed64 single_sfixed64 = 10; + float single_float = 11; + double single_double = 12; + bool single_bool = 13; + string single_string = 14; + bytes single_bytes = 15; + + NestedMessage single_nested_message = 18; + ForeignMessage single_foreign_message = 19; + protobuf_unittest_import.ImportMessage single_import_message = 20; + + NestedEnum single_nested_enum = 21; + ForeignEnum single_foreign_enum = 22; + protobuf_unittest_import.ImportEnum single_import_enum = 23; + + // Defined in unittest_import_public.proto + protobuf_unittest_import.PublicImportMessage + single_public_import_message = 26; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53; + // Defined in unittest_import_public.proto + repeated protobuf_unittest_import.PublicImportMessage + repeated_public_import_message = 54; + + // For oneof test + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } +} + +// This proto includes a recursively nested message. +message NestedTestAllTypes { + NestedTestAllTypes child = 1; + TestAllTypes payload = 2; + repeated NestedTestAllTypes repeated_child = 3; +} + +message TestDeprecatedFields { + int32 deprecated_int32 = 1 [deprecated=true]; +} + +// Define these after TestAllTypes to make sure the compiler can handle +// that. +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_UNSPECIFIED = 0; + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; +} + +message TestReservedFields { + reserved 2, 15, 9 to 11; + reserved "bar", "baz"; +} + + +// Test that we can use NestedMessage from outside TestAllTypes. +message TestForeignNested { + TestAllTypes.NestedMessage foreign_nested = 1; +} + +// Test that really large tag numbers don't break anything. +message TestReallyLargeTagNumber { + // The largest possible tag number is 2^28 - 1, since the wire format uses + // three bits to communicate wire type. + int32 a = 1; + int32 bb = 268435455; +} + +message TestRecursiveMessage { + TestRecursiveMessage a = 1; + int32 i = 2; +} + +// Test that mutual recursion works. +message TestMutualRecursionA { + TestMutualRecursionB bb = 1; +} + +message TestMutualRecursionB { + TestMutualRecursionA a = 1; + int32 optional_int32 = 2; +} + +message TestEnumAllowAlias { + TestEnumWithDupValue value = 1; +} + +// Test an enum that has multiple values with the same number. +enum TestEnumWithDupValue { + TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED = 0; + option allow_alias = true; + + FOO1 = 1; + BAR1 = 2; + BAZ = 3; + FOO2 = 1; + BAR2 = 2; +} + +// Test an enum with large, unordered values. +enum TestSparseEnum { + TEST_SPARSE_ENUM_UNSPECIFIED = 0; + SPARSE_A = 123; + SPARSE_B = 62374; + SPARSE_C = 12589234; + SPARSE_D = -15; + SPARSE_E = -53452; + // In proto3, value 0 must be the first one specified + // SPARSE_F = 0; + SPARSE_G = 2; +} + +// Test message with CamelCase field names. This violates Protocol Buffer +// standard style. +message TestCamelCaseFieldNames { + int32 PrimitiveField = 1; + string StringField = 2; + ForeignEnum EnumField = 3; + ForeignMessage MessageField = 4; + + repeated int32 RepeatedPrimitiveField = 7; + repeated string RepeatedStringField = 8; + repeated ForeignEnum RepeatedEnumField = 9; + repeated ForeignMessage RepeatedMessageField = 10; +} + + +// We list fields out of order, to ensure that we're using field number and not +// field index to determine serialization order. +message TestFieldOrderings { + string my_string = 11; + int64 my_int = 1; + float my_float = 101; + message NestedMessage { + int64 oo = 2; + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + NestedMessage single_nested_message = 200; +} + +message SparseEnumMessage { + TestSparseEnum sparse_enum = 1; +} + +// Test String and Bytes: string is for valid UTF-8 strings +message OneString { + string data = 1; +} + +message MoreString { + repeated string data = 1; +} + +message OneBytes { + bytes data = 1; +} + +message MoreBytes { + bytes data = 1; +} + +// Test int32, uint32, int64, uint64, and bool are all compatible +message Int32Message { + int32 data = 1; +} + +message Uint32Message { + uint32 data = 1; +} + +message Int64Message { + int64 data = 1; +} + +message Uint64Message { + uint64 data = 1; +} + +message BoolMessage { + bool data = 1; +} + +// Test oneofs. +message TestOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + TestAllTypes foo_message = 3; + } +} + +// Test messages for packed fields + +message TestPackedTypes { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnum packed_enum = 103 [packed = true]; +} + +// A message with the same fields as TestPackedTypes, but without packing. Used +// to test packed <-> unpacked wire compatibility. +message TestUnpackedTypes { + repeated int32 unpacked_int32 = 90 [packed = false]; + repeated int64 unpacked_int64 = 91 [packed = false]; + repeated uint32 unpacked_uint32 = 92 [packed = false]; + repeated uint64 unpacked_uint64 = 93 [packed = false]; + repeated sint32 unpacked_sint32 = 94 [packed = false]; + repeated sint64 unpacked_sint64 = 95 [packed = false]; + repeated fixed32 unpacked_fixed32 = 96 [packed = false]; + repeated fixed64 unpacked_fixed64 = 97 [packed = false]; + repeated sfixed32 unpacked_sfixed32 = 98 [packed = false]; + repeated sfixed64 unpacked_sfixed64 = 99 [packed = false]; + repeated float unpacked_float = 100 [packed = false]; + repeated double unpacked_double = 101 [packed = false]; + repeated bool unpacked_bool = 102 [packed = false]; + repeated ForeignEnum unpacked_enum = 103 [packed = false]; +} + +message TestRepeatedScalarDifferentTagSizes { + // Parsing repeated fixed size values used to fail. This message needs to be + // used in order to get a tag of the right size; all of the repeated fields + // in TestAllTypes didn't trigger the check. + repeated fixed32 repeated_fixed32 = 12; + // Check for a varint type, just for good measure. + repeated int32 repeated_int32 = 13; + + // These have two-byte tags. + repeated fixed64 repeated_fixed64 = 2046; + repeated int64 repeated_int64 = 2047; + + // Three byte tags. + repeated float repeated_float = 262142; + repeated uint64 repeated_uint64 = 262143; +} + +message TestCommentInjectionMessage { + // */ <- This should not close the generated doc comment + string a = 1; +} + + +// Test that RPC services work. +message FooRequest {} +message FooResponse {} + +message FooClientMessage {} +message FooServerMessage{} + +// This is a test service +service TestService { + // This is a test method + rpc Foo(FooRequest) returns (FooResponse); + rpc Bar(BarRequest) returns (BarResponse); +} + + +message BarRequest {} +message BarResponse {} + +message TestEmptyMessage {} + +// This is leading detached comment 1 + +// This is leading detached comment 2 + +// This is a leading comment +message CommentMessage { + // Leading nested message comment + message NestedCommentMessage { + // Leading nested message field comment + string nested_text = 1; + } + + // Leading nested enum comment + enum NestedCommentEnum { + // Zero value comment + ZERO_VALUE = 0; + } + + // Leading field comment + string text = 1; // Trailing field comment +} + +// Leading enum comment +enum CommentEnum { + // Zero value comment + ZERO_VALUE = 0; +} diff --git a/csharp/protos/unittest_selfreferential_options.proto b/csharp/protos/unittest_selfreferential_options.proto new file mode 100644 index 0000000000000..22f16cfbf5a88 --- /dev/null +++ b/csharp/protos/unittest_selfreferential_options.proto @@ -0,0 +1,64 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package protobuf_unittest_selfreferential_options; +option csharp_namespace = "UnitTest.Issues.TestProtos.SelfreferentialOptions"; + +import "google/protobuf/descriptor.proto"; + +message FooOptions { + // Custom field option used in definition of the extension message. + optional int32 int_opt = 1 [(foo_options) = { + int_opt: 1 + [foo_int_opt]: 2 + [foo_foo_opt]: { + int_opt: 3 + } + }]; + + // Custom field option used in definition of the custom option's message. + optional int32 foo = 2 [(foo_options) = {foo: 1234}]; + + extensions 1000 to max; +} + +extend google.protobuf.FieldOptions { + // Custom field option used on the definition of that field option. + optional int32 bar_options = 1000 [(bar_options) = 1234]; + + optional FooOptions foo_options = 1001; +} + +extend FooOptions { + optional int32 foo_int_opt = 1000; + optional FooOptions foo_foo_opt = 1001; +} diff --git a/csharp/src/AddressBook/AddressBook.csproj b/csharp/src/AddressBook/AddressBook.csproj index 6edfdcabb39bd..f3268c0acf3e3 100644 --- a/csharp/src/AddressBook/AddressBook.csproj +++ b/csharp/src/AddressBook/AddressBook.csproj @@ -1,7 +1,7 @@  - netcoreapp1.0 + netcoreapp2.1 Exe Google.Protobuf.Examples.AddressBook.Program False diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs index 75ed071b749da..042f69ee60b84 100644 --- a/csharp/src/AddressBook/Addressbook.cs +++ b/csharp/src/AddressBook/Addressbook.cs @@ -1,5 +1,7 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: addressbook.proto +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: addressbook.proto +// #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -22,20 +24,22 @@ public static partial class AddressbookReflection { static AddressbookReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "ChFhZGRyZXNzYm9vay5wcm90bxIIdHV0b3JpYWwi1QEKBlBlcnNvbhIMCgRu", - "YW1lGAEgASgJEgoKAmlkGAIgASgFEg0KBWVtYWlsGAMgASgJEiwKBnBob25l", - "cxgEIAMoCzIcLnR1dG9yaWFsLlBlcnNvbi5QaG9uZU51bWJlchpHCgtQaG9u", - "ZU51bWJlchIOCgZudW1iZXIYASABKAkSKAoEdHlwZRgCIAEoDjIaLnR1dG9y", - "aWFsLlBlcnNvbi5QaG9uZVR5cGUiKwoJUGhvbmVUeXBlEgoKBk1PQklMRRAA", - "EggKBEhPTUUQARIICgRXT1JLEAIiLwoLQWRkcmVzc0Jvb2sSIAoGcGVvcGxl", - "GAEgAygLMhAudHV0b3JpYWwuUGVyc29uQlAKFGNvbS5leGFtcGxlLnR1dG9y", - "aWFsQhFBZGRyZXNzQm9va1Byb3Rvc6oCJEdvb2dsZS5Qcm90b2J1Zi5FeGFt", - "cGxlcy5BZGRyZXNzQm9va2IGcHJvdG8z")); + "ChFhZGRyZXNzYm9vay5wcm90bxIIdHV0b3JpYWwaH2dvb2dsZS9wcm90b2J1", + "Zi90aW1lc3RhbXAucHJvdG8ihwIKBlBlcnNvbhIMCgRuYW1lGAEgASgJEgoK", + "AmlkGAIgASgFEg0KBWVtYWlsGAMgASgJEiwKBnBob25lcxgEIAMoCzIcLnR1", + "dG9yaWFsLlBlcnNvbi5QaG9uZU51bWJlchIwCgxsYXN0X3VwZGF0ZWQYBSAB", + "KAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wGkcKC1Bob25lTnVtYmVy", + "Eg4KBm51bWJlchgBIAEoCRIoCgR0eXBlGAIgASgOMhoudHV0b3JpYWwuUGVy", + "c29uLlBob25lVHlwZSIrCglQaG9uZVR5cGUSCgoGTU9CSUxFEAASCAoESE9N", + "RRABEggKBFdPUksQAiIvCgtBZGRyZXNzQm9vaxIgCgZwZW9wbGUYASADKAsy", + "EC50dXRvcmlhbC5QZXJzb25CUAoUY29tLmV4YW1wbGUudHV0b3JpYWxCEUFk", + "ZHJlc3NCb29rUHJvdG9zqgIkR29vZ2xlLlByb3RvYnVmLkV4YW1wbGVzLkFk", + "ZHJlc3NCb29rYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, - new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person), global::Google.Protobuf.Examples.AddressBook.Person.Parser, new[]{ "Name", "Id", "Email", "Phones" }, null, new[]{ typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber), global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber.Parser, new[]{ "Number", "Type" }, null, null, null)}), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.AddressBook), global::Google.Protobuf.Examples.AddressBook.AddressBook.Parser, new[]{ "People" }, null, null, null) + new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person), global::Google.Protobuf.Examples.AddressBook.Person.Parser, new[]{ "Name", "Id", "Email", "Phones", "LastUpdated" }, null, new[]{ typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber), global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber.Parser, new[]{ "Number", "Type" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.AddressBook), global::Google.Protobuf.Examples.AddressBook.AddressBook.Parser, new[]{ "People" }, null, null, null, null) })); } #endregion @@ -45,8 +49,13 @@ static AddressbookReflection() { /// /// [START messages] /// - public sealed partial class Person : pb::IMessage { + public sealed partial class Person : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Person()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -73,6 +82,8 @@ public Person(Person other) : this() { id_ = other.id_; email_ = other.email_; phones_ = other.phones_.Clone(); + lastUpdated_ = other.lastUpdated_ != null ? other.lastUpdated_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -126,6 +137,17 @@ public string Email { get { return phones_; } } + /// Field number for the "last_updated" field. + public const int LastUpdatedFieldNumber = 5; + private global::Google.Protobuf.WellKnownTypes.Timestamp lastUpdated_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.Timestamp LastUpdated { + get { return lastUpdated_; } + set { + lastUpdated_ = value; + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as Person); @@ -143,7 +165,8 @@ public bool Equals(Person other) { if (Id != other.Id) return false; if (Email != other.Email) return false; if(!phones_.Equals(other.phones_)) return false; - return true; + if (!object.Equals(LastUpdated, other.LastUpdated)) return false; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -153,6 +176,10 @@ public override int GetHashCode() { if (Id != 0) hash ^= Id.GetHashCode(); if (Email.Length != 0) hash ^= Email.GetHashCode(); hash ^= phones_.GetHashCode(); + if (lastUpdated_ != null) hash ^= LastUpdated.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -163,6 +190,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -176,7 +206,41 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteString(Email); } phones_.WriteTo(output, _repeated_phones_codec); + if (lastUpdated_ != null) { + output.WriteRawTag(42); + output.WriteMessage(LastUpdated); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (Id != 0) { + output.WriteRawTag(16); + output.WriteInt32(Id); + } + if (Email.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Email); + } + phones_.WriteTo(ref output, _repeated_phones_codec); + if (lastUpdated_ != null) { + output.WriteRawTag(42); + output.WriteMessage(LastUpdated); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -191,6 +255,12 @@ public int CalculateSize() { size += 1 + pb::CodedOutputStream.ComputeStringSize(Email); } size += phones_.CalculateSize(_repeated_phones_codec); + if (lastUpdated_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(LastUpdated); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -209,15 +279,25 @@ public void MergeFrom(Person other) { Email = other.Email; } phones_.Add(other.phones_); + if (other.lastUpdated_ != null) { + if (lastUpdated_ == null) { + LastUpdated = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + } + LastUpdated.MergeFrom(other.LastUpdated); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { Name = input.ReadString(); @@ -235,10 +315,55 @@ public void MergeFrom(pb::CodedInputStream input) { phones_.AddEntriesFrom(input, _repeated_phones_codec); break; } + case 42: { + if (lastUpdated_ == null) { + LastUpdated = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + } + input.ReadMessage(LastUpdated); + break; + } } } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 16: { + Id = input.ReadInt32(); + break; + } + case 26: { + Email = input.ReadString(); + break; + } + case 34: { + phones_.AddEntriesFrom(ref input, _repeated_phones_codec); + break; + } + case 42: { + if (lastUpdated_ == null) { + LastUpdated = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + } + input.ReadMessage(LastUpdated); + break; + } + } + } + } + #endif + #region Nested types /// Container for nested types declared in the Person message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -249,8 +374,13 @@ public enum PhoneType { [pbr::OriginalName("WORK")] Work = 2, } - public sealed partial class PhoneNumber : pb::IMessage { + public sealed partial class PhoneNumber : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PhoneNumber()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -275,6 +405,7 @@ public PhoneNumber() { public PhoneNumber(PhoneNumber other) : this() { number_ = other.number_; type_ = other.type_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -295,7 +426,7 @@ public string Number { /// Field number for the "type" field. public const int TypeFieldNumber = 2; - private global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType type_ = 0; + private global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType type_ = global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.Mobile; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType Type { get { return type_; } @@ -319,14 +450,17 @@ public bool Equals(PhoneNumber other) { } if (Number != other.Number) return false; if (Type != other.Type) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Number.Length != 0) hash ^= Number.GetHashCode(); - if (Type != 0) hash ^= Type.GetHashCode(); + if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.Mobile) hash ^= Type.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -337,15 +471,39 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Number.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Number); + } + if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.Mobile) { + output.WriteRawTag(16); + output.WriteEnum((int) Type); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (Number.Length != 0) { output.WriteRawTag(10); output.WriteString(Number); } - if (Type != 0) { + if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.Mobile) { output.WriteRawTag(16); output.WriteEnum((int) Type); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -353,9 +511,12 @@ public int CalculateSize() { if (Number.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Number); } - if (Type != 0) { + if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.Mobile) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -367,31 +528,58 @@ public void MergeFrom(PhoneNumber other) { if (other.Number.Length != 0) { Number = other.Number; } - if (other.Type != 0) { + if (other.Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.Mobile) { Type = other.Type; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { Number = input.ReadString(); break; } case 16: { - type_ = (global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) input.ReadEnum(); + Type = (global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) input.ReadEnum(); break; } } } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Number = input.ReadString(); + break; + } + case 16: { + Type = (global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) input.ReadEnum(); + break; + } + } + } + } + #endif + } } @@ -402,8 +590,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// /// Our address book file is just one of these. /// - public sealed partial class AddressBook : pb::IMessage { + public sealed partial class AddressBook : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new AddressBook()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -427,6 +620,7 @@ public AddressBook() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public AddressBook(AddressBook other) : this() { people_ = other.people_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -458,13 +652,16 @@ public bool Equals(AddressBook other) { return true; } if(!people_.Equals(other.people_)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= people_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -475,13 +672,33 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else people_.WriteTo(output, _repeated_people_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + people_.WriteTo(ref output, _repeated_people_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += people_.CalculateSize(_repeated_people_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -491,15 +708,19 @@ public void MergeFrom(AddressBook other) { return; } people_.Add(other.people_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { people_.AddEntriesFrom(input, _repeated_people_codec); @@ -507,7 +728,26 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + people_.AddEntriesFrom(ref input, _repeated_people_codec); + break; + } + } + } } + #endif } diff --git a/csharp/src/AddressBook/Program.cs b/csharp/src/AddressBook/Program.cs index ff7b9c085e072..de4867a0ce217 100644 --- a/csharp/src/AddressBook/Program.cs +++ b/csharp/src/AddressBook/Program.cs @@ -37,7 +37,7 @@ namespace Google.Protobuf.Examples.AddressBook /// /// Entry point. Repeatedly prompts user for an action to take, delegating actual behaviour /// to individual actions. Each action has its own Main method, so that it can be used as an - /// invidual complete program. + /// individual complete program. /// internal class Program { diff --git a/csharp/src/Google.Protobuf.Benchmarks/BenchmarkDatasetConfig.cs b/csharp/src/Google.Protobuf.Benchmarks/BenchmarkDatasetConfig.cs new file mode 100644 index 0000000000000..c0754190b6c9b --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/BenchmarkDatasetConfig.cs @@ -0,0 +1,89 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2019 Google Inc. All rights reserved. +// https://github.com/protocolbuffers/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using Benchmarks; +using Google.Protobuf.Reflection; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; + +namespace Google.Protobuf.Benchmarks +{ + /// + /// The configuration for a single serialization test, loaded from a dataset. + /// + public class BenchmarkDatasetConfig + { + private static readonly Dictionary parsersByMessageName = + typeof(GoogleMessageBenchmark).Assembly.GetTypes() + .Where(t => typeof(IMessage).IsAssignableFrom(t)) + .ToDictionary( + t => ((MessageDescriptor) t.GetProperty("Descriptor", BindingFlags.Static | BindingFlags.Public).GetValue(null)).FullName, + t => ((MessageParser) t.GetProperty("Parser", BindingFlags.Static | BindingFlags.Public).GetValue(null))); + + public MessageParser Parser { get; } + public List Payloads { get; } + public string Name { get; } + + public BenchmarkDatasetConfig(string resource, string shortName = null) + { + var data = LoadData(resource); + var dataset = BenchmarkDataset.Parser.ParseFrom(data); + + if (!parsersByMessageName.TryGetValue(dataset.MessageName, out var parser)) + { + throw new ArgumentException($"No parser for message {dataset.MessageName} in this assembly"); + } + Parser = parser; + Payloads = new List(dataset.Payload.Select(p => p.ToByteArray())); + Name = shortName ?? dataset.Name; + } + + private static byte[] LoadData(string resource) + { + using (var stream = typeof(GoogleMessageBenchmark).Assembly.GetManifestResourceStream($"Google.Protobuf.Benchmarks.{resource}")) + { + if (stream == null) + { + throw new ArgumentException($"Unable to load embedded resource {resource}"); + } + var copy = new MemoryStream(); + stream.CopyTo(copy); + return copy.ToArray(); + } + } + + public override string ToString() => Name; + } +} diff --git a/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs b/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs new file mode 100644 index 0000000000000..027da02a10b5c --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs @@ -0,0 +1,2539 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: datasets/google_message1/proto3/benchmark_message1_proto3.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Benchmarks.Proto3 { + + /// Holder for reflection information generated from datasets/google_message1/proto3/benchmark_message1_proto3.proto + public static partial class BenchmarkMessage1Proto3Reflection { + + #region Descriptor + /// File descriptor for datasets/google_message1/proto3/benchmark_message1_proto3.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static BenchmarkMessage1Proto3Reflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Cj9kYXRhc2V0cy9nb29nbGVfbWVzc2FnZTEvcHJvdG8zL2JlbmNobWFya19t", + "ZXNzYWdlMV9wcm90bzMucHJvdG8SEWJlbmNobWFya3MucHJvdG8zIoMGCg5H", + "b29nbGVNZXNzYWdlMRIOCgZmaWVsZDEYASABKAkSDgoGZmllbGQ5GAkgASgJ", + "Eg8KB2ZpZWxkMTgYEiABKAkSDwoHZmllbGQ4MBhQIAEoCBIPCgdmaWVsZDgx", + "GFEgASgIEg4KBmZpZWxkMhgCIAEoBRIOCgZmaWVsZDMYAyABKAUSEQoIZmll", + "bGQyODAYmAIgASgFEg4KBmZpZWxkNhgGIAEoBRIPCgdmaWVsZDIyGBYgASgD", + "Eg4KBmZpZWxkNBgEIAEoCRIOCgZmaWVsZDUYBSADKAYSDwoHZmllbGQ1ORg7", + "IAEoCBIOCgZmaWVsZDcYByABKAkSDwoHZmllbGQxNhgQIAEoBRIRCghmaWVs", + "ZDEzMBiCASABKAUSDwoHZmllbGQxMhgMIAEoCBIPCgdmaWVsZDE3GBEgASgI", + "Eg8KB2ZpZWxkMTMYDSABKAgSDwoHZmllbGQxNBgOIAEoCBIQCghmaWVsZDEw", + "NBhoIAEoBRIQCghmaWVsZDEwMBhkIAEoBRIQCghmaWVsZDEwMRhlIAEoBRIQ", + "CghmaWVsZDEwMhhmIAEoCRIQCghmaWVsZDEwMxhnIAEoCRIPCgdmaWVsZDI5", + "GB0gASgFEg8KB2ZpZWxkMzAYHiABKAgSDwoHZmllbGQ2MBg8IAEoBRIRCghm", + "aWVsZDI3MRiPAiABKAUSEQoIZmllbGQyNzIYkAIgASgFEhEKCGZpZWxkMTUw", + "GJYBIAEoBRIPCgdmaWVsZDIzGBcgASgFEg8KB2ZpZWxkMjQYGCABKAgSDwoH", + "ZmllbGQyNRgZIAEoBRI8CgdmaWVsZDE1GA8gASgLMisuYmVuY2htYXJrcy5w", + "cm90bzMuR29vZ2xlTWVzc2FnZTFTdWJNZXNzYWdlEg8KB2ZpZWxkNzgYTiAB", + "KAgSDwoHZmllbGQ2NxhDIAEoBRIPCgdmaWVsZDY4GEQgASgFEhEKCGZpZWxk", + "MTI4GIABIAEoBRIRCghmaWVsZDEyORiBASABKAkSEQoIZmllbGQxMzEYgwEg", + "ASgFIvcCChhHb29nbGVNZXNzYWdlMVN1Yk1lc3NhZ2USDgoGZmllbGQxGAEg", + "ASgFEg4KBmZpZWxkMhgCIAEoBRIOCgZmaWVsZDMYAyABKAUSDwoHZmllbGQx", + "NRgPIAEoCRIPCgdmaWVsZDEyGAwgASgIEg8KB2ZpZWxkMTMYDSABKAMSDwoH", + "ZmllbGQxNBgOIAEoAxIPCgdmaWVsZDE2GBAgASgFEg8KB2ZpZWxkMTkYEyAB", + "KAUSDwoHZmllbGQyMBgUIAEoCBIPCgdmaWVsZDI4GBwgASgIEg8KB2ZpZWxk", + "MjEYFSABKAYSDwoHZmllbGQyMhgWIAEoBRIPCgdmaWVsZDIzGBcgASgIEhEK", + "CGZpZWxkMjA2GM4BIAEoCBIRCghmaWVsZDIwMxjLASABKAcSEQoIZmllbGQy", + "MDQYzAEgASgFEhEKCGZpZWxkMjA1GM0BIAEoCRIRCghmaWVsZDIwNxjPASAB", + "KAQSEQoIZmllbGQzMDAYrAIgASgEQiUKHmNvbS5nb29nbGUucHJvdG9idWYu", + "YmVuY2htYXJrc0gB+AEBYgZwcm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Benchmarks.Proto3.GoogleMessage1), global::Benchmarks.Proto3.GoogleMessage1.Parser, new[]{ "Field1", "Field9", "Field18", "Field80", "Field81", "Field2", "Field3", "Field280", "Field6", "Field22", "Field4", "Field5", "Field59", "Field7", "Field16", "Field130", "Field12", "Field17", "Field13", "Field14", "Field104", "Field100", "Field101", "Field102", "Field103", "Field29", "Field30", "Field60", "Field271", "Field272", "Field150", "Field23", "Field24", "Field25", "Field15", "Field78", "Field67", "Field68", "Field128", "Field129", "Field131" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Benchmarks.Proto3.GoogleMessage1SubMessage), global::Benchmarks.Proto3.GoogleMessage1SubMessage.Parser, new[]{ "Field1", "Field2", "Field3", "Field15", "Field12", "Field13", "Field14", "Field16", "Field19", "Field20", "Field28", "Field21", "Field22", "Field23", "Field206", "Field203", "Field204", "Field205", "Field207", "Field300" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class GoogleMessage1 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new GoogleMessage1()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Benchmarks.Proto3.BenchmarkMessage1Proto3Reflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public GoogleMessage1() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public GoogleMessage1(GoogleMessage1 other) : this() { + field1_ = other.field1_; + field9_ = other.field9_; + field18_ = other.field18_; + field80_ = other.field80_; + field81_ = other.field81_; + field2_ = other.field2_; + field3_ = other.field3_; + field280_ = other.field280_; + field6_ = other.field6_; + field22_ = other.field22_; + field4_ = other.field4_; + field5_ = other.field5_.Clone(); + field59_ = other.field59_; + field7_ = other.field7_; + field16_ = other.field16_; + field130_ = other.field130_; + field12_ = other.field12_; + field17_ = other.field17_; + field13_ = other.field13_; + field14_ = other.field14_; + field104_ = other.field104_; + field100_ = other.field100_; + field101_ = other.field101_; + field102_ = other.field102_; + field103_ = other.field103_; + field29_ = other.field29_; + field30_ = other.field30_; + field60_ = other.field60_; + field271_ = other.field271_; + field272_ = other.field272_; + field150_ = other.field150_; + field23_ = other.field23_; + field24_ = other.field24_; + field25_ = other.field25_; + field15_ = other.field15_ != null ? other.field15_.Clone() : null; + field78_ = other.field78_; + field67_ = other.field67_; + field68_ = other.field68_; + field128_ = other.field128_; + field129_ = other.field129_; + field131_ = other.field131_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public GoogleMessage1 Clone() { + return new GoogleMessage1(this); + } + + /// Field number for the "field1" field. + public const int Field1FieldNumber = 1; + private string field1_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Field1 { + get { return field1_; } + set { + field1_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "field9" field. + public const int Field9FieldNumber = 9; + private string field9_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Field9 { + get { return field9_; } + set { + field9_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "field18" field. + public const int Field18FieldNumber = 18; + private string field18_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Field18 { + get { return field18_; } + set { + field18_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "field80" field. + public const int Field80FieldNumber = 80; + private bool field80_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field80 { + get { return field80_; } + set { + field80_ = value; + } + } + + /// Field number for the "field81" field. + public const int Field81FieldNumber = 81; + private bool field81_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field81 { + get { return field81_; } + set { + field81_ = value; + } + } + + /// Field number for the "field2" field. + public const int Field2FieldNumber = 2; + private int field2_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field2 { + get { return field2_; } + set { + field2_ = value; + } + } + + /// Field number for the "field3" field. + public const int Field3FieldNumber = 3; + private int field3_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field3 { + get { return field3_; } + set { + field3_ = value; + } + } + + /// Field number for the "field280" field. + public const int Field280FieldNumber = 280; + private int field280_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field280 { + get { return field280_; } + set { + field280_ = value; + } + } + + /// Field number for the "field6" field. + public const int Field6FieldNumber = 6; + private int field6_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field6 { + get { return field6_; } + set { + field6_ = value; + } + } + + /// Field number for the "field22" field. + public const int Field22FieldNumber = 22; + private long field22_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Field22 { + get { return field22_; } + set { + field22_ = value; + } + } + + /// Field number for the "field4" field. + public const int Field4FieldNumber = 4; + private string field4_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Field4 { + get { return field4_; } + set { + field4_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "field5" field. + public const int Field5FieldNumber = 5; + private static readonly pb::FieldCodec _repeated_field5_codec + = pb::FieldCodec.ForFixed64(42); + private readonly pbc::RepeatedField field5_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Field5 { + get { return field5_; } + } + + /// Field number for the "field59" field. + public const int Field59FieldNumber = 59; + private bool field59_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field59 { + get { return field59_; } + set { + field59_ = value; + } + } + + /// Field number for the "field7" field. + public const int Field7FieldNumber = 7; + private string field7_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Field7 { + get { return field7_; } + set { + field7_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "field16" field. + public const int Field16FieldNumber = 16; + private int field16_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field16 { + get { return field16_; } + set { + field16_ = value; + } + } + + /// Field number for the "field130" field. + public const int Field130FieldNumber = 130; + private int field130_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field130 { + get { return field130_; } + set { + field130_ = value; + } + } + + /// Field number for the "field12" field. + public const int Field12FieldNumber = 12; + private bool field12_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field12 { + get { return field12_; } + set { + field12_ = value; + } + } + + /// Field number for the "field17" field. + public const int Field17FieldNumber = 17; + private bool field17_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field17 { + get { return field17_; } + set { + field17_ = value; + } + } + + /// Field number for the "field13" field. + public const int Field13FieldNumber = 13; + private bool field13_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field13 { + get { return field13_; } + set { + field13_ = value; + } + } + + /// Field number for the "field14" field. + public const int Field14FieldNumber = 14; + private bool field14_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field14 { + get { return field14_; } + set { + field14_ = value; + } + } + + /// Field number for the "field104" field. + public const int Field104FieldNumber = 104; + private int field104_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field104 { + get { return field104_; } + set { + field104_ = value; + } + } + + /// Field number for the "field100" field. + public const int Field100FieldNumber = 100; + private int field100_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field100 { + get { return field100_; } + set { + field100_ = value; + } + } + + /// Field number for the "field101" field. + public const int Field101FieldNumber = 101; + private int field101_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field101 { + get { return field101_; } + set { + field101_ = value; + } + } + + /// Field number for the "field102" field. + public const int Field102FieldNumber = 102; + private string field102_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Field102 { + get { return field102_; } + set { + field102_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "field103" field. + public const int Field103FieldNumber = 103; + private string field103_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Field103 { + get { return field103_; } + set { + field103_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "field29" field. + public const int Field29FieldNumber = 29; + private int field29_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field29 { + get { return field29_; } + set { + field29_ = value; + } + } + + /// Field number for the "field30" field. + public const int Field30FieldNumber = 30; + private bool field30_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field30 { + get { return field30_; } + set { + field30_ = value; + } + } + + /// Field number for the "field60" field. + public const int Field60FieldNumber = 60; + private int field60_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field60 { + get { return field60_; } + set { + field60_ = value; + } + } + + /// Field number for the "field271" field. + public const int Field271FieldNumber = 271; + private int field271_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field271 { + get { return field271_; } + set { + field271_ = value; + } + } + + /// Field number for the "field272" field. + public const int Field272FieldNumber = 272; + private int field272_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field272 { + get { return field272_; } + set { + field272_ = value; + } + } + + /// Field number for the "field150" field. + public const int Field150FieldNumber = 150; + private int field150_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field150 { + get { return field150_; } + set { + field150_ = value; + } + } + + /// Field number for the "field23" field. + public const int Field23FieldNumber = 23; + private int field23_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field23 { + get { return field23_; } + set { + field23_ = value; + } + } + + /// Field number for the "field24" field. + public const int Field24FieldNumber = 24; + private bool field24_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field24 { + get { return field24_; } + set { + field24_ = value; + } + } + + /// Field number for the "field25" field. + public const int Field25FieldNumber = 25; + private int field25_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field25 { + get { return field25_; } + set { + field25_ = value; + } + } + + /// Field number for the "field15" field. + public const int Field15FieldNumber = 15; + private global::Benchmarks.Proto3.GoogleMessage1SubMessage field15_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Benchmarks.Proto3.GoogleMessage1SubMessage Field15 { + get { return field15_; } + set { + field15_ = value; + } + } + + /// Field number for the "field78" field. + public const int Field78FieldNumber = 78; + private bool field78_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field78 { + get { return field78_; } + set { + field78_ = value; + } + } + + /// Field number for the "field67" field. + public const int Field67FieldNumber = 67; + private int field67_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field67 { + get { return field67_; } + set { + field67_ = value; + } + } + + /// Field number for the "field68" field. + public const int Field68FieldNumber = 68; + private int field68_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field68 { + get { return field68_; } + set { + field68_ = value; + } + } + + /// Field number for the "field128" field. + public const int Field128FieldNumber = 128; + private int field128_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field128 { + get { return field128_; } + set { + field128_ = value; + } + } + + /// Field number for the "field129" field. + public const int Field129FieldNumber = 129; + private string field129_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Field129 { + get { return field129_; } + set { + field129_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "field131" field. + public const int Field131FieldNumber = 131; + private int field131_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field131 { + get { return field131_; } + set { + field131_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as GoogleMessage1); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(GoogleMessage1 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Field1 != other.Field1) return false; + if (Field9 != other.Field9) return false; + if (Field18 != other.Field18) return false; + if (Field80 != other.Field80) return false; + if (Field81 != other.Field81) return false; + if (Field2 != other.Field2) return false; + if (Field3 != other.Field3) return false; + if (Field280 != other.Field280) return false; + if (Field6 != other.Field6) return false; + if (Field22 != other.Field22) return false; + if (Field4 != other.Field4) return false; + if(!field5_.Equals(other.field5_)) return false; + if (Field59 != other.Field59) return false; + if (Field7 != other.Field7) return false; + if (Field16 != other.Field16) return false; + if (Field130 != other.Field130) return false; + if (Field12 != other.Field12) return false; + if (Field17 != other.Field17) return false; + if (Field13 != other.Field13) return false; + if (Field14 != other.Field14) return false; + if (Field104 != other.Field104) return false; + if (Field100 != other.Field100) return false; + if (Field101 != other.Field101) return false; + if (Field102 != other.Field102) return false; + if (Field103 != other.Field103) return false; + if (Field29 != other.Field29) return false; + if (Field30 != other.Field30) return false; + if (Field60 != other.Field60) return false; + if (Field271 != other.Field271) return false; + if (Field272 != other.Field272) return false; + if (Field150 != other.Field150) return false; + if (Field23 != other.Field23) return false; + if (Field24 != other.Field24) return false; + if (Field25 != other.Field25) return false; + if (!object.Equals(Field15, other.Field15)) return false; + if (Field78 != other.Field78) return false; + if (Field67 != other.Field67) return false; + if (Field68 != other.Field68) return false; + if (Field128 != other.Field128) return false; + if (Field129 != other.Field129) return false; + if (Field131 != other.Field131) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Field1.Length != 0) hash ^= Field1.GetHashCode(); + if (Field9.Length != 0) hash ^= Field9.GetHashCode(); + if (Field18.Length != 0) hash ^= Field18.GetHashCode(); + if (Field80 != false) hash ^= Field80.GetHashCode(); + if (Field81 != false) hash ^= Field81.GetHashCode(); + if (Field2 != 0) hash ^= Field2.GetHashCode(); + if (Field3 != 0) hash ^= Field3.GetHashCode(); + if (Field280 != 0) hash ^= Field280.GetHashCode(); + if (Field6 != 0) hash ^= Field6.GetHashCode(); + if (Field22 != 0L) hash ^= Field22.GetHashCode(); + if (Field4.Length != 0) hash ^= Field4.GetHashCode(); + hash ^= field5_.GetHashCode(); + if (Field59 != false) hash ^= Field59.GetHashCode(); + if (Field7.Length != 0) hash ^= Field7.GetHashCode(); + if (Field16 != 0) hash ^= Field16.GetHashCode(); + if (Field130 != 0) hash ^= Field130.GetHashCode(); + if (Field12 != false) hash ^= Field12.GetHashCode(); + if (Field17 != false) hash ^= Field17.GetHashCode(); + if (Field13 != false) hash ^= Field13.GetHashCode(); + if (Field14 != false) hash ^= Field14.GetHashCode(); + if (Field104 != 0) hash ^= Field104.GetHashCode(); + if (Field100 != 0) hash ^= Field100.GetHashCode(); + if (Field101 != 0) hash ^= Field101.GetHashCode(); + if (Field102.Length != 0) hash ^= Field102.GetHashCode(); + if (Field103.Length != 0) hash ^= Field103.GetHashCode(); + if (Field29 != 0) hash ^= Field29.GetHashCode(); + if (Field30 != false) hash ^= Field30.GetHashCode(); + if (Field60 != 0) hash ^= Field60.GetHashCode(); + if (Field271 != 0) hash ^= Field271.GetHashCode(); + if (Field272 != 0) hash ^= Field272.GetHashCode(); + if (Field150 != 0) hash ^= Field150.GetHashCode(); + if (Field23 != 0) hash ^= Field23.GetHashCode(); + if (Field24 != false) hash ^= Field24.GetHashCode(); + if (Field25 != 0) hash ^= Field25.GetHashCode(); + if (field15_ != null) hash ^= Field15.GetHashCode(); + if (Field78 != false) hash ^= Field78.GetHashCode(); + if (Field67 != 0) hash ^= Field67.GetHashCode(); + if (Field68 != 0) hash ^= Field68.GetHashCode(); + if (Field128 != 0) hash ^= Field128.GetHashCode(); + if (Field129.Length != 0) hash ^= Field129.GetHashCode(); + if (Field131 != 0) hash ^= Field131.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Field1.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Field1); + } + if (Field2 != 0) { + output.WriteRawTag(16); + output.WriteInt32(Field2); + } + if (Field3 != 0) { + output.WriteRawTag(24); + output.WriteInt32(Field3); + } + if (Field4.Length != 0) { + output.WriteRawTag(34); + output.WriteString(Field4); + } + field5_.WriteTo(output, _repeated_field5_codec); + if (Field6 != 0) { + output.WriteRawTag(48); + output.WriteInt32(Field6); + } + if (Field7.Length != 0) { + output.WriteRawTag(58); + output.WriteString(Field7); + } + if (Field9.Length != 0) { + output.WriteRawTag(74); + output.WriteString(Field9); + } + if (Field12 != false) { + output.WriteRawTag(96); + output.WriteBool(Field12); + } + if (Field13 != false) { + output.WriteRawTag(104); + output.WriteBool(Field13); + } + if (Field14 != false) { + output.WriteRawTag(112); + output.WriteBool(Field14); + } + if (field15_ != null) { + output.WriteRawTag(122); + output.WriteMessage(Field15); + } + if (Field16 != 0) { + output.WriteRawTag(128, 1); + output.WriteInt32(Field16); + } + if (Field17 != false) { + output.WriteRawTag(136, 1); + output.WriteBool(Field17); + } + if (Field18.Length != 0) { + output.WriteRawTag(146, 1); + output.WriteString(Field18); + } + if (Field22 != 0L) { + output.WriteRawTag(176, 1); + output.WriteInt64(Field22); + } + if (Field23 != 0) { + output.WriteRawTag(184, 1); + output.WriteInt32(Field23); + } + if (Field24 != false) { + output.WriteRawTag(192, 1); + output.WriteBool(Field24); + } + if (Field25 != 0) { + output.WriteRawTag(200, 1); + output.WriteInt32(Field25); + } + if (Field29 != 0) { + output.WriteRawTag(232, 1); + output.WriteInt32(Field29); + } + if (Field30 != false) { + output.WriteRawTag(240, 1); + output.WriteBool(Field30); + } + if (Field59 != false) { + output.WriteRawTag(216, 3); + output.WriteBool(Field59); + } + if (Field60 != 0) { + output.WriteRawTag(224, 3); + output.WriteInt32(Field60); + } + if (Field67 != 0) { + output.WriteRawTag(152, 4); + output.WriteInt32(Field67); + } + if (Field68 != 0) { + output.WriteRawTag(160, 4); + output.WriteInt32(Field68); + } + if (Field78 != false) { + output.WriteRawTag(240, 4); + output.WriteBool(Field78); + } + if (Field80 != false) { + output.WriteRawTag(128, 5); + output.WriteBool(Field80); + } + if (Field81 != false) { + output.WriteRawTag(136, 5); + output.WriteBool(Field81); + } + if (Field100 != 0) { + output.WriteRawTag(160, 6); + output.WriteInt32(Field100); + } + if (Field101 != 0) { + output.WriteRawTag(168, 6); + output.WriteInt32(Field101); + } + if (Field102.Length != 0) { + output.WriteRawTag(178, 6); + output.WriteString(Field102); + } + if (Field103.Length != 0) { + output.WriteRawTag(186, 6); + output.WriteString(Field103); + } + if (Field104 != 0) { + output.WriteRawTag(192, 6); + output.WriteInt32(Field104); + } + if (Field128 != 0) { + output.WriteRawTag(128, 8); + output.WriteInt32(Field128); + } + if (Field129.Length != 0) { + output.WriteRawTag(138, 8); + output.WriteString(Field129); + } + if (Field130 != 0) { + output.WriteRawTag(144, 8); + output.WriteInt32(Field130); + } + if (Field131 != 0) { + output.WriteRawTag(152, 8); + output.WriteInt32(Field131); + } + if (Field150 != 0) { + output.WriteRawTag(176, 9); + output.WriteInt32(Field150); + } + if (Field271 != 0) { + output.WriteRawTag(248, 16); + output.WriteInt32(Field271); + } + if (Field272 != 0) { + output.WriteRawTag(128, 17); + output.WriteInt32(Field272); + } + if (Field280 != 0) { + output.WriteRawTag(192, 17); + output.WriteInt32(Field280); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Field1.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Field1); + } + if (Field2 != 0) { + output.WriteRawTag(16); + output.WriteInt32(Field2); + } + if (Field3 != 0) { + output.WriteRawTag(24); + output.WriteInt32(Field3); + } + if (Field4.Length != 0) { + output.WriteRawTag(34); + output.WriteString(Field4); + } + field5_.WriteTo(ref output, _repeated_field5_codec); + if (Field6 != 0) { + output.WriteRawTag(48); + output.WriteInt32(Field6); + } + if (Field7.Length != 0) { + output.WriteRawTag(58); + output.WriteString(Field7); + } + if (Field9.Length != 0) { + output.WriteRawTag(74); + output.WriteString(Field9); + } + if (Field12 != false) { + output.WriteRawTag(96); + output.WriteBool(Field12); + } + if (Field13 != false) { + output.WriteRawTag(104); + output.WriteBool(Field13); + } + if (Field14 != false) { + output.WriteRawTag(112); + output.WriteBool(Field14); + } + if (field15_ != null) { + output.WriteRawTag(122); + output.WriteMessage(Field15); + } + if (Field16 != 0) { + output.WriteRawTag(128, 1); + output.WriteInt32(Field16); + } + if (Field17 != false) { + output.WriteRawTag(136, 1); + output.WriteBool(Field17); + } + if (Field18.Length != 0) { + output.WriteRawTag(146, 1); + output.WriteString(Field18); + } + if (Field22 != 0L) { + output.WriteRawTag(176, 1); + output.WriteInt64(Field22); + } + if (Field23 != 0) { + output.WriteRawTag(184, 1); + output.WriteInt32(Field23); + } + if (Field24 != false) { + output.WriteRawTag(192, 1); + output.WriteBool(Field24); + } + if (Field25 != 0) { + output.WriteRawTag(200, 1); + output.WriteInt32(Field25); + } + if (Field29 != 0) { + output.WriteRawTag(232, 1); + output.WriteInt32(Field29); + } + if (Field30 != false) { + output.WriteRawTag(240, 1); + output.WriteBool(Field30); + } + if (Field59 != false) { + output.WriteRawTag(216, 3); + output.WriteBool(Field59); + } + if (Field60 != 0) { + output.WriteRawTag(224, 3); + output.WriteInt32(Field60); + } + if (Field67 != 0) { + output.WriteRawTag(152, 4); + output.WriteInt32(Field67); + } + if (Field68 != 0) { + output.WriteRawTag(160, 4); + output.WriteInt32(Field68); + } + if (Field78 != false) { + output.WriteRawTag(240, 4); + output.WriteBool(Field78); + } + if (Field80 != false) { + output.WriteRawTag(128, 5); + output.WriteBool(Field80); + } + if (Field81 != false) { + output.WriteRawTag(136, 5); + output.WriteBool(Field81); + } + if (Field100 != 0) { + output.WriteRawTag(160, 6); + output.WriteInt32(Field100); + } + if (Field101 != 0) { + output.WriteRawTag(168, 6); + output.WriteInt32(Field101); + } + if (Field102.Length != 0) { + output.WriteRawTag(178, 6); + output.WriteString(Field102); + } + if (Field103.Length != 0) { + output.WriteRawTag(186, 6); + output.WriteString(Field103); + } + if (Field104 != 0) { + output.WriteRawTag(192, 6); + output.WriteInt32(Field104); + } + if (Field128 != 0) { + output.WriteRawTag(128, 8); + output.WriteInt32(Field128); + } + if (Field129.Length != 0) { + output.WriteRawTag(138, 8); + output.WriteString(Field129); + } + if (Field130 != 0) { + output.WriteRawTag(144, 8); + output.WriteInt32(Field130); + } + if (Field131 != 0) { + output.WriteRawTag(152, 8); + output.WriteInt32(Field131); + } + if (Field150 != 0) { + output.WriteRawTag(176, 9); + output.WriteInt32(Field150); + } + if (Field271 != 0) { + output.WriteRawTag(248, 16); + output.WriteInt32(Field271); + } + if (Field272 != 0) { + output.WriteRawTag(128, 17); + output.WriteInt32(Field272); + } + if (Field280 != 0) { + output.WriteRawTag(192, 17); + output.WriteInt32(Field280); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Field1.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Field1); + } + if (Field9.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Field9); + } + if (Field18.Length != 0) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(Field18); + } + if (Field80 != false) { + size += 2 + 1; + } + if (Field81 != false) { + size += 2 + 1; + } + if (Field2 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field2); + } + if (Field3 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field3); + } + if (Field280 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field280); + } + if (Field6 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field6); + } + if (Field22 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Field22); + } + if (Field4.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Field4); + } + size += field5_.CalculateSize(_repeated_field5_codec); + if (Field59 != false) { + size += 2 + 1; + } + if (Field7.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Field7); + } + if (Field16 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field16); + } + if (Field130 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field130); + } + if (Field12 != false) { + size += 1 + 1; + } + if (Field17 != false) { + size += 2 + 1; + } + if (Field13 != false) { + size += 1 + 1; + } + if (Field14 != false) { + size += 1 + 1; + } + if (Field104 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field104); + } + if (Field100 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field100); + } + if (Field101 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field101); + } + if (Field102.Length != 0) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(Field102); + } + if (Field103.Length != 0) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(Field103); + } + if (Field29 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field29); + } + if (Field30 != false) { + size += 2 + 1; + } + if (Field60 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field60); + } + if (Field271 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field271); + } + if (Field272 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field272); + } + if (Field150 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field150); + } + if (Field23 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field23); + } + if (Field24 != false) { + size += 2 + 1; + } + if (Field25 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field25); + } + if (field15_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Field15); + } + if (Field78 != false) { + size += 2 + 1; + } + if (Field67 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field67); + } + if (Field68 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field68); + } + if (Field128 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field128); + } + if (Field129.Length != 0) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(Field129); + } + if (Field131 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field131); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(GoogleMessage1 other) { + if (other == null) { + return; + } + if (other.Field1.Length != 0) { + Field1 = other.Field1; + } + if (other.Field9.Length != 0) { + Field9 = other.Field9; + } + if (other.Field18.Length != 0) { + Field18 = other.Field18; + } + if (other.Field80 != false) { + Field80 = other.Field80; + } + if (other.Field81 != false) { + Field81 = other.Field81; + } + if (other.Field2 != 0) { + Field2 = other.Field2; + } + if (other.Field3 != 0) { + Field3 = other.Field3; + } + if (other.Field280 != 0) { + Field280 = other.Field280; + } + if (other.Field6 != 0) { + Field6 = other.Field6; + } + if (other.Field22 != 0L) { + Field22 = other.Field22; + } + if (other.Field4.Length != 0) { + Field4 = other.Field4; + } + field5_.Add(other.field5_); + if (other.Field59 != false) { + Field59 = other.Field59; + } + if (other.Field7.Length != 0) { + Field7 = other.Field7; + } + if (other.Field16 != 0) { + Field16 = other.Field16; + } + if (other.Field130 != 0) { + Field130 = other.Field130; + } + if (other.Field12 != false) { + Field12 = other.Field12; + } + if (other.Field17 != false) { + Field17 = other.Field17; + } + if (other.Field13 != false) { + Field13 = other.Field13; + } + if (other.Field14 != false) { + Field14 = other.Field14; + } + if (other.Field104 != 0) { + Field104 = other.Field104; + } + if (other.Field100 != 0) { + Field100 = other.Field100; + } + if (other.Field101 != 0) { + Field101 = other.Field101; + } + if (other.Field102.Length != 0) { + Field102 = other.Field102; + } + if (other.Field103.Length != 0) { + Field103 = other.Field103; + } + if (other.Field29 != 0) { + Field29 = other.Field29; + } + if (other.Field30 != false) { + Field30 = other.Field30; + } + if (other.Field60 != 0) { + Field60 = other.Field60; + } + if (other.Field271 != 0) { + Field271 = other.Field271; + } + if (other.Field272 != 0) { + Field272 = other.Field272; + } + if (other.Field150 != 0) { + Field150 = other.Field150; + } + if (other.Field23 != 0) { + Field23 = other.Field23; + } + if (other.Field24 != false) { + Field24 = other.Field24; + } + if (other.Field25 != 0) { + Field25 = other.Field25; + } + if (other.field15_ != null) { + if (field15_ == null) { + Field15 = new global::Benchmarks.Proto3.GoogleMessage1SubMessage(); + } + Field15.MergeFrom(other.Field15); + } + if (other.Field78 != false) { + Field78 = other.Field78; + } + if (other.Field67 != 0) { + Field67 = other.Field67; + } + if (other.Field68 != 0) { + Field68 = other.Field68; + } + if (other.Field128 != 0) { + Field128 = other.Field128; + } + if (other.Field129.Length != 0) { + Field129 = other.Field129; + } + if (other.Field131 != 0) { + Field131 = other.Field131; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Field1 = input.ReadString(); + break; + } + case 16: { + Field2 = input.ReadInt32(); + break; + } + case 24: { + Field3 = input.ReadInt32(); + break; + } + case 34: { + Field4 = input.ReadString(); + break; + } + case 42: + case 41: { + field5_.AddEntriesFrom(input, _repeated_field5_codec); + break; + } + case 48: { + Field6 = input.ReadInt32(); + break; + } + case 58: { + Field7 = input.ReadString(); + break; + } + case 74: { + Field9 = input.ReadString(); + break; + } + case 96: { + Field12 = input.ReadBool(); + break; + } + case 104: { + Field13 = input.ReadBool(); + break; + } + case 112: { + Field14 = input.ReadBool(); + break; + } + case 122: { + if (field15_ == null) { + Field15 = new global::Benchmarks.Proto3.GoogleMessage1SubMessage(); + } + input.ReadMessage(Field15); + break; + } + case 128: { + Field16 = input.ReadInt32(); + break; + } + case 136: { + Field17 = input.ReadBool(); + break; + } + case 146: { + Field18 = input.ReadString(); + break; + } + case 176: { + Field22 = input.ReadInt64(); + break; + } + case 184: { + Field23 = input.ReadInt32(); + break; + } + case 192: { + Field24 = input.ReadBool(); + break; + } + case 200: { + Field25 = input.ReadInt32(); + break; + } + case 232: { + Field29 = input.ReadInt32(); + break; + } + case 240: { + Field30 = input.ReadBool(); + break; + } + case 472: { + Field59 = input.ReadBool(); + break; + } + case 480: { + Field60 = input.ReadInt32(); + break; + } + case 536: { + Field67 = input.ReadInt32(); + break; + } + case 544: { + Field68 = input.ReadInt32(); + break; + } + case 624: { + Field78 = input.ReadBool(); + break; + } + case 640: { + Field80 = input.ReadBool(); + break; + } + case 648: { + Field81 = input.ReadBool(); + break; + } + case 800: { + Field100 = input.ReadInt32(); + break; + } + case 808: { + Field101 = input.ReadInt32(); + break; + } + case 818: { + Field102 = input.ReadString(); + break; + } + case 826: { + Field103 = input.ReadString(); + break; + } + case 832: { + Field104 = input.ReadInt32(); + break; + } + case 1024: { + Field128 = input.ReadInt32(); + break; + } + case 1034: { + Field129 = input.ReadString(); + break; + } + case 1040: { + Field130 = input.ReadInt32(); + break; + } + case 1048: { + Field131 = input.ReadInt32(); + break; + } + case 1200: { + Field150 = input.ReadInt32(); + break; + } + case 2168: { + Field271 = input.ReadInt32(); + break; + } + case 2176: { + Field272 = input.ReadInt32(); + break; + } + case 2240: { + Field280 = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Field1 = input.ReadString(); + break; + } + case 16: { + Field2 = input.ReadInt32(); + break; + } + case 24: { + Field3 = input.ReadInt32(); + break; + } + case 34: { + Field4 = input.ReadString(); + break; + } + case 42: + case 41: { + field5_.AddEntriesFrom(ref input, _repeated_field5_codec); + break; + } + case 48: { + Field6 = input.ReadInt32(); + break; + } + case 58: { + Field7 = input.ReadString(); + break; + } + case 74: { + Field9 = input.ReadString(); + break; + } + case 96: { + Field12 = input.ReadBool(); + break; + } + case 104: { + Field13 = input.ReadBool(); + break; + } + case 112: { + Field14 = input.ReadBool(); + break; + } + case 122: { + if (field15_ == null) { + Field15 = new global::Benchmarks.Proto3.GoogleMessage1SubMessage(); + } + input.ReadMessage(Field15); + break; + } + case 128: { + Field16 = input.ReadInt32(); + break; + } + case 136: { + Field17 = input.ReadBool(); + break; + } + case 146: { + Field18 = input.ReadString(); + break; + } + case 176: { + Field22 = input.ReadInt64(); + break; + } + case 184: { + Field23 = input.ReadInt32(); + break; + } + case 192: { + Field24 = input.ReadBool(); + break; + } + case 200: { + Field25 = input.ReadInt32(); + break; + } + case 232: { + Field29 = input.ReadInt32(); + break; + } + case 240: { + Field30 = input.ReadBool(); + break; + } + case 472: { + Field59 = input.ReadBool(); + break; + } + case 480: { + Field60 = input.ReadInt32(); + break; + } + case 536: { + Field67 = input.ReadInt32(); + break; + } + case 544: { + Field68 = input.ReadInt32(); + break; + } + case 624: { + Field78 = input.ReadBool(); + break; + } + case 640: { + Field80 = input.ReadBool(); + break; + } + case 648: { + Field81 = input.ReadBool(); + break; + } + case 800: { + Field100 = input.ReadInt32(); + break; + } + case 808: { + Field101 = input.ReadInt32(); + break; + } + case 818: { + Field102 = input.ReadString(); + break; + } + case 826: { + Field103 = input.ReadString(); + break; + } + case 832: { + Field104 = input.ReadInt32(); + break; + } + case 1024: { + Field128 = input.ReadInt32(); + break; + } + case 1034: { + Field129 = input.ReadString(); + break; + } + case 1040: { + Field130 = input.ReadInt32(); + break; + } + case 1048: { + Field131 = input.ReadInt32(); + break; + } + case 1200: { + Field150 = input.ReadInt32(); + break; + } + case 2168: { + Field271 = input.ReadInt32(); + break; + } + case 2176: { + Field272 = input.ReadInt32(); + break; + } + case 2240: { + Field280 = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class GoogleMessage1SubMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new GoogleMessage1SubMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Benchmarks.Proto3.BenchmarkMessage1Proto3Reflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public GoogleMessage1SubMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public GoogleMessage1SubMessage(GoogleMessage1SubMessage other) : this() { + field1_ = other.field1_; + field2_ = other.field2_; + field3_ = other.field3_; + field15_ = other.field15_; + field12_ = other.field12_; + field13_ = other.field13_; + field14_ = other.field14_; + field16_ = other.field16_; + field19_ = other.field19_; + field20_ = other.field20_; + field28_ = other.field28_; + field21_ = other.field21_; + field22_ = other.field22_; + field23_ = other.field23_; + field206_ = other.field206_; + field203_ = other.field203_; + field204_ = other.field204_; + field205_ = other.field205_; + field207_ = other.field207_; + field300_ = other.field300_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public GoogleMessage1SubMessage Clone() { + return new GoogleMessage1SubMessage(this); + } + + /// Field number for the "field1" field. + public const int Field1FieldNumber = 1; + private int field1_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field1 { + get { return field1_; } + set { + field1_ = value; + } + } + + /// Field number for the "field2" field. + public const int Field2FieldNumber = 2; + private int field2_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field2 { + get { return field2_; } + set { + field2_ = value; + } + } + + /// Field number for the "field3" field. + public const int Field3FieldNumber = 3; + private int field3_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field3 { + get { return field3_; } + set { + field3_ = value; + } + } + + /// Field number for the "field15" field. + public const int Field15FieldNumber = 15; + private string field15_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Field15 { + get { return field15_; } + set { + field15_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "field12" field. + public const int Field12FieldNumber = 12; + private bool field12_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field12 { + get { return field12_; } + set { + field12_ = value; + } + } + + /// Field number for the "field13" field. + public const int Field13FieldNumber = 13; + private long field13_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Field13 { + get { return field13_; } + set { + field13_ = value; + } + } + + /// Field number for the "field14" field. + public const int Field14FieldNumber = 14; + private long field14_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Field14 { + get { return field14_; } + set { + field14_ = value; + } + } + + /// Field number for the "field16" field. + public const int Field16FieldNumber = 16; + private int field16_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field16 { + get { return field16_; } + set { + field16_ = value; + } + } + + /// Field number for the "field19" field. + public const int Field19FieldNumber = 19; + private int field19_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field19 { + get { return field19_; } + set { + field19_ = value; + } + } + + /// Field number for the "field20" field. + public const int Field20FieldNumber = 20; + private bool field20_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field20 { + get { return field20_; } + set { + field20_ = value; + } + } + + /// Field number for the "field28" field. + public const int Field28FieldNumber = 28; + private bool field28_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field28 { + get { return field28_; } + set { + field28_ = value; + } + } + + /// Field number for the "field21" field. + public const int Field21FieldNumber = 21; + private ulong field21_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong Field21 { + get { return field21_; } + set { + field21_ = value; + } + } + + /// Field number for the "field22" field. + public const int Field22FieldNumber = 22; + private int field22_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field22 { + get { return field22_; } + set { + field22_ = value; + } + } + + /// Field number for the "field23" field. + public const int Field23FieldNumber = 23; + private bool field23_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field23 { + get { return field23_; } + set { + field23_ = value; + } + } + + /// Field number for the "field206" field. + public const int Field206FieldNumber = 206; + private bool field206_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Field206 { + get { return field206_; } + set { + field206_ = value; + } + } + + /// Field number for the "field203" field. + public const int Field203FieldNumber = 203; + private uint field203_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint Field203 { + get { return field203_; } + set { + field203_ = value; + } + } + + /// Field number for the "field204" field. + public const int Field204FieldNumber = 204; + private int field204_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field204 { + get { return field204_; } + set { + field204_ = value; + } + } + + /// Field number for the "field205" field. + public const int Field205FieldNumber = 205; + private string field205_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Field205 { + get { return field205_; } + set { + field205_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "field207" field. + public const int Field207FieldNumber = 207; + private ulong field207_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong Field207 { + get { return field207_; } + set { + field207_ = value; + } + } + + /// Field number for the "field300" field. + public const int Field300FieldNumber = 300; + private ulong field300_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong Field300 { + get { return field300_; } + set { + field300_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as GoogleMessage1SubMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(GoogleMessage1SubMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Field1 != other.Field1) return false; + if (Field2 != other.Field2) return false; + if (Field3 != other.Field3) return false; + if (Field15 != other.Field15) return false; + if (Field12 != other.Field12) return false; + if (Field13 != other.Field13) return false; + if (Field14 != other.Field14) return false; + if (Field16 != other.Field16) return false; + if (Field19 != other.Field19) return false; + if (Field20 != other.Field20) return false; + if (Field28 != other.Field28) return false; + if (Field21 != other.Field21) return false; + if (Field22 != other.Field22) return false; + if (Field23 != other.Field23) return false; + if (Field206 != other.Field206) return false; + if (Field203 != other.Field203) return false; + if (Field204 != other.Field204) return false; + if (Field205 != other.Field205) return false; + if (Field207 != other.Field207) return false; + if (Field300 != other.Field300) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Field1 != 0) hash ^= Field1.GetHashCode(); + if (Field2 != 0) hash ^= Field2.GetHashCode(); + if (Field3 != 0) hash ^= Field3.GetHashCode(); + if (Field15.Length != 0) hash ^= Field15.GetHashCode(); + if (Field12 != false) hash ^= Field12.GetHashCode(); + if (Field13 != 0L) hash ^= Field13.GetHashCode(); + if (Field14 != 0L) hash ^= Field14.GetHashCode(); + if (Field16 != 0) hash ^= Field16.GetHashCode(); + if (Field19 != 0) hash ^= Field19.GetHashCode(); + if (Field20 != false) hash ^= Field20.GetHashCode(); + if (Field28 != false) hash ^= Field28.GetHashCode(); + if (Field21 != 0UL) hash ^= Field21.GetHashCode(); + if (Field22 != 0) hash ^= Field22.GetHashCode(); + if (Field23 != false) hash ^= Field23.GetHashCode(); + if (Field206 != false) hash ^= Field206.GetHashCode(); + if (Field203 != 0) hash ^= Field203.GetHashCode(); + if (Field204 != 0) hash ^= Field204.GetHashCode(); + if (Field205.Length != 0) hash ^= Field205.GetHashCode(); + if (Field207 != 0UL) hash ^= Field207.GetHashCode(); + if (Field300 != 0UL) hash ^= Field300.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Field1 != 0) { + output.WriteRawTag(8); + output.WriteInt32(Field1); + } + if (Field2 != 0) { + output.WriteRawTag(16); + output.WriteInt32(Field2); + } + if (Field3 != 0) { + output.WriteRawTag(24); + output.WriteInt32(Field3); + } + if (Field12 != false) { + output.WriteRawTag(96); + output.WriteBool(Field12); + } + if (Field13 != 0L) { + output.WriteRawTag(104); + output.WriteInt64(Field13); + } + if (Field14 != 0L) { + output.WriteRawTag(112); + output.WriteInt64(Field14); + } + if (Field15.Length != 0) { + output.WriteRawTag(122); + output.WriteString(Field15); + } + if (Field16 != 0) { + output.WriteRawTag(128, 1); + output.WriteInt32(Field16); + } + if (Field19 != 0) { + output.WriteRawTag(152, 1); + output.WriteInt32(Field19); + } + if (Field20 != false) { + output.WriteRawTag(160, 1); + output.WriteBool(Field20); + } + if (Field21 != 0UL) { + output.WriteRawTag(169, 1); + output.WriteFixed64(Field21); + } + if (Field22 != 0) { + output.WriteRawTag(176, 1); + output.WriteInt32(Field22); + } + if (Field23 != false) { + output.WriteRawTag(184, 1); + output.WriteBool(Field23); + } + if (Field28 != false) { + output.WriteRawTag(224, 1); + output.WriteBool(Field28); + } + if (Field203 != 0) { + output.WriteRawTag(221, 12); + output.WriteFixed32(Field203); + } + if (Field204 != 0) { + output.WriteRawTag(224, 12); + output.WriteInt32(Field204); + } + if (Field205.Length != 0) { + output.WriteRawTag(234, 12); + output.WriteString(Field205); + } + if (Field206 != false) { + output.WriteRawTag(240, 12); + output.WriteBool(Field206); + } + if (Field207 != 0UL) { + output.WriteRawTag(248, 12); + output.WriteUInt64(Field207); + } + if (Field300 != 0UL) { + output.WriteRawTag(224, 18); + output.WriteUInt64(Field300); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Field1 != 0) { + output.WriteRawTag(8); + output.WriteInt32(Field1); + } + if (Field2 != 0) { + output.WriteRawTag(16); + output.WriteInt32(Field2); + } + if (Field3 != 0) { + output.WriteRawTag(24); + output.WriteInt32(Field3); + } + if (Field12 != false) { + output.WriteRawTag(96); + output.WriteBool(Field12); + } + if (Field13 != 0L) { + output.WriteRawTag(104); + output.WriteInt64(Field13); + } + if (Field14 != 0L) { + output.WriteRawTag(112); + output.WriteInt64(Field14); + } + if (Field15.Length != 0) { + output.WriteRawTag(122); + output.WriteString(Field15); + } + if (Field16 != 0) { + output.WriteRawTag(128, 1); + output.WriteInt32(Field16); + } + if (Field19 != 0) { + output.WriteRawTag(152, 1); + output.WriteInt32(Field19); + } + if (Field20 != false) { + output.WriteRawTag(160, 1); + output.WriteBool(Field20); + } + if (Field21 != 0UL) { + output.WriteRawTag(169, 1); + output.WriteFixed64(Field21); + } + if (Field22 != 0) { + output.WriteRawTag(176, 1); + output.WriteInt32(Field22); + } + if (Field23 != false) { + output.WriteRawTag(184, 1); + output.WriteBool(Field23); + } + if (Field28 != false) { + output.WriteRawTag(224, 1); + output.WriteBool(Field28); + } + if (Field203 != 0) { + output.WriteRawTag(221, 12); + output.WriteFixed32(Field203); + } + if (Field204 != 0) { + output.WriteRawTag(224, 12); + output.WriteInt32(Field204); + } + if (Field205.Length != 0) { + output.WriteRawTag(234, 12); + output.WriteString(Field205); + } + if (Field206 != false) { + output.WriteRawTag(240, 12); + output.WriteBool(Field206); + } + if (Field207 != 0UL) { + output.WriteRawTag(248, 12); + output.WriteUInt64(Field207); + } + if (Field300 != 0UL) { + output.WriteRawTag(224, 18); + output.WriteUInt64(Field300); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Field1 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field1); + } + if (Field2 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field2); + } + if (Field3 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field3); + } + if (Field15.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Field15); + } + if (Field12 != false) { + size += 1 + 1; + } + if (Field13 != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Field13); + } + if (Field14 != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Field14); + } + if (Field16 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field16); + } + if (Field19 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field19); + } + if (Field20 != false) { + size += 2 + 1; + } + if (Field28 != false) { + size += 2 + 1; + } + if (Field21 != 0UL) { + size += 2 + 8; + } + if (Field22 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field22); + } + if (Field23 != false) { + size += 2 + 1; + } + if (Field206 != false) { + size += 2 + 1; + } + if (Field203 != 0) { + size += 2 + 4; + } + if (Field204 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field204); + } + if (Field205.Length != 0) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(Field205); + } + if (Field207 != 0UL) { + size += 2 + pb::CodedOutputStream.ComputeUInt64Size(Field207); + } + if (Field300 != 0UL) { + size += 2 + pb::CodedOutputStream.ComputeUInt64Size(Field300); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(GoogleMessage1SubMessage other) { + if (other == null) { + return; + } + if (other.Field1 != 0) { + Field1 = other.Field1; + } + if (other.Field2 != 0) { + Field2 = other.Field2; + } + if (other.Field3 != 0) { + Field3 = other.Field3; + } + if (other.Field15.Length != 0) { + Field15 = other.Field15; + } + if (other.Field12 != false) { + Field12 = other.Field12; + } + if (other.Field13 != 0L) { + Field13 = other.Field13; + } + if (other.Field14 != 0L) { + Field14 = other.Field14; + } + if (other.Field16 != 0) { + Field16 = other.Field16; + } + if (other.Field19 != 0) { + Field19 = other.Field19; + } + if (other.Field20 != false) { + Field20 = other.Field20; + } + if (other.Field28 != false) { + Field28 = other.Field28; + } + if (other.Field21 != 0UL) { + Field21 = other.Field21; + } + if (other.Field22 != 0) { + Field22 = other.Field22; + } + if (other.Field23 != false) { + Field23 = other.Field23; + } + if (other.Field206 != false) { + Field206 = other.Field206; + } + if (other.Field203 != 0) { + Field203 = other.Field203; + } + if (other.Field204 != 0) { + Field204 = other.Field204; + } + if (other.Field205.Length != 0) { + Field205 = other.Field205; + } + if (other.Field207 != 0UL) { + Field207 = other.Field207; + } + if (other.Field300 != 0UL) { + Field300 = other.Field300; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Field1 = input.ReadInt32(); + break; + } + case 16: { + Field2 = input.ReadInt32(); + break; + } + case 24: { + Field3 = input.ReadInt32(); + break; + } + case 96: { + Field12 = input.ReadBool(); + break; + } + case 104: { + Field13 = input.ReadInt64(); + break; + } + case 112: { + Field14 = input.ReadInt64(); + break; + } + case 122: { + Field15 = input.ReadString(); + break; + } + case 128: { + Field16 = input.ReadInt32(); + break; + } + case 152: { + Field19 = input.ReadInt32(); + break; + } + case 160: { + Field20 = input.ReadBool(); + break; + } + case 169: { + Field21 = input.ReadFixed64(); + break; + } + case 176: { + Field22 = input.ReadInt32(); + break; + } + case 184: { + Field23 = input.ReadBool(); + break; + } + case 224: { + Field28 = input.ReadBool(); + break; + } + case 1629: { + Field203 = input.ReadFixed32(); + break; + } + case 1632: { + Field204 = input.ReadInt32(); + break; + } + case 1642: { + Field205 = input.ReadString(); + break; + } + case 1648: { + Field206 = input.ReadBool(); + break; + } + case 1656: { + Field207 = input.ReadUInt64(); + break; + } + case 2400: { + Field300 = input.ReadUInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Field1 = input.ReadInt32(); + break; + } + case 16: { + Field2 = input.ReadInt32(); + break; + } + case 24: { + Field3 = input.ReadInt32(); + break; + } + case 96: { + Field12 = input.ReadBool(); + break; + } + case 104: { + Field13 = input.ReadInt64(); + break; + } + case 112: { + Field14 = input.ReadInt64(); + break; + } + case 122: { + Field15 = input.ReadString(); + break; + } + case 128: { + Field16 = input.ReadInt32(); + break; + } + case 152: { + Field19 = input.ReadInt32(); + break; + } + case 160: { + Field20 = input.ReadBool(); + break; + } + case 169: { + Field21 = input.ReadFixed64(); + break; + } + case 176: { + Field22 = input.ReadInt32(); + break; + } + case 184: { + Field23 = input.ReadBool(); + break; + } + case 224: { + Field28 = input.ReadBool(); + break; + } + case 1629: { + Field203 = input.ReadFixed32(); + break; + } + case 1632: { + Field204 = input.ReadInt32(); + break; + } + case 1642: { + Field205 = input.ReadString(); + break; + } + case 1648: { + Field206 = input.ReadBool(); + break; + } + case 1656: { + Field207 = input.ReadUInt64(); + break; + } + case 2400: { + Field300 = input.ReadUInt64(); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs b/csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs new file mode 100644 index 0000000000000..e2578f367fd26 --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs @@ -0,0 +1,306 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: benchmarks.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Benchmarks { + + /// Holder for reflection information generated from benchmarks.proto + public static partial class BenchmarksReflection { + + #region Descriptor + /// File descriptor for benchmarks.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static BenchmarksReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChBiZW5jaG1hcmtzLnByb3RvEgpiZW5jaG1hcmtzIkcKEEJlbmNobWFya0Rh", + "dGFzZXQSDAoEbmFtZRgBIAEoCRIUCgxtZXNzYWdlX25hbWUYAiABKAkSDwoH", + "cGF5bG9hZBgDIAMoDEIgCh5jb20uZ29vZ2xlLnByb3RvYnVmLmJlbmNobWFy", + "a3NiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Benchmarks.BenchmarkDataset), global::Benchmarks.BenchmarkDataset.Parser, new[]{ "Name", "MessageName", "Payload" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class BenchmarkDataset : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BenchmarkDataset()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Benchmarks.BenchmarksReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BenchmarkDataset() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BenchmarkDataset(BenchmarkDataset other) : this() { + name_ = other.name_; + messageName_ = other.messageName_; + payload_ = other.payload_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BenchmarkDataset Clone() { + return new BenchmarkDataset(this); + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 1; + private string name_ = ""; + /// + /// Name of the benchmark dataset. This should be unique across all datasets. + /// Should only contain word characters: [a-zA-Z0-9_] + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "message_name" field. + public const int MessageNameFieldNumber = 2; + private string messageName_ = ""; + /// + /// Fully-qualified name of the protobuf message for this dataset. + /// It will be one of the messages defined benchmark_messages_proto2.proto + /// or benchmark_messages_proto3.proto. + /// + /// Implementations that do not support reflection can implement this with + /// an explicit "if/else" chain that lists every known message defined + /// in those files. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string MessageName { + get { return messageName_; } + set { + messageName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "payload" field. + public const int PayloadFieldNumber = 3; + private static readonly pb::FieldCodec _repeated_payload_codec + = pb::FieldCodec.ForBytes(26); + private readonly pbc::RepeatedField payload_ = new pbc::RepeatedField(); + /// + /// The payload(s) for this dataset. They should be parsed or serialized + /// in sequence, in a loop, ie. + /// + /// while (!benchmarkDone) { // Benchmark runner decides when to exit. + /// for (i = 0; i < benchmark.payload.length; i++) { + /// parse(benchmark.payload[i]) + /// } + /// } + /// + /// This is intended to let datasets include a variety of data to provide + /// potentially more realistic results than just parsing the same message + /// over and over. A single message parsed repeatedly could yield unusually + /// good branch prediction performance. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Payload { + get { return payload_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as BenchmarkDataset); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(BenchmarkDataset other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Name != other.Name) return false; + if (MessageName != other.MessageName) return false; + if(!payload_.Equals(other.payload_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (MessageName.Length != 0) hash ^= MessageName.GetHashCode(); + hash ^= payload_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (MessageName.Length != 0) { + output.WriteRawTag(18); + output.WriteString(MessageName); + } + payload_.WriteTo(output, _repeated_payload_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (MessageName.Length != 0) { + output.WriteRawTag(18); + output.WriteString(MessageName); + } + payload_.WriteTo(ref output, _repeated_payload_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + if (MessageName.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(MessageName); + } + size += payload_.CalculateSize(_repeated_payload_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(BenchmarkDataset other) { + if (other == null) { + return; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + if (other.MessageName.Length != 0) { + MessageName = other.MessageName; + } + payload_.Add(other.payload_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + MessageName = input.ReadString(); + break; + } + case 26: { + payload_.AddEntriesFrom(input, _repeated_payload_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + MessageName = input.ReadString(); + break; + } + case 26: { + payload_.AddEntriesFrom(ref input, _repeated_payload_codec); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Benchmarks/ByteStringBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ByteStringBenchmark.cs new file mode 100644 index 0000000000000..a755850a66e17 --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/ByteStringBenchmark.cs @@ -0,0 +1,72 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2019 Google Inc. All rights reserved. +// https://github.com/protocolbuffers/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using BenchmarkDotNet.Attributes; + +namespace Google.Protobuf.Benchmarks +{ + /// + /// Benchmarks using ByteString. + /// + [MemoryDiagnoser] + public class ByteStringBenchmark + { + private const int Zero = 0; + private const int Kilobyte = 1024; + private const int _128Kilobytes = 1024 * 128; + private const int Megabyte = 1024 * 1024; + private const int _10Megabytes = 1024 * 1024 * 10; + + byte[] byteBuffer; + + [GlobalSetup] + public void GlobalSetup() + { + byteBuffer = new byte[PayloadSize]; + } + + [Params(Zero, Kilobyte, _128Kilobytes, Megabyte, _10Megabytes)] + public int PayloadSize { get; set; } + + [Benchmark] + public ByteString CopyFrom() + { + return ByteString.CopyFrom(byteBuffer); + } + + [Benchmark] + public ByteString UnsafeWrap() + { + return UnsafeByteOperations.UnsafeWrap(byteBuffer); + } + } +} diff --git a/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj b/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj new file mode 100644 index 0000000000000..73042f358c477 --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj @@ -0,0 +1,26 @@ + + + + Exe + netcoreapp3.1 + ../../keys/Google.Protobuf.snk + true + False + pdbonly + true + + + + + + + + + + + + + + + + diff --git a/csharp/src/Google.Protobuf.Benchmarks/GoogleMessageBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/GoogleMessageBenchmark.cs new file mode 100644 index 0000000000000..132967e00a29d --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/GoogleMessageBenchmark.cs @@ -0,0 +1,124 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2019 Google Inc. All rights reserved. +// https://github.com/protocolbuffers/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using BenchmarkDotNet.Attributes; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Google.Protobuf.Benchmarks +{ + /// + /// Benchmark for serializing and deserializing of standard datasets that are also + /// measured by benchmarks in other languages. + /// Over time we may wish to test the various different approaches to serialization and deserialization separately. + /// See https://github.com/protocolbuffers/protobuf/blob/master/benchmarks/README.md + /// See https://github.com/protocolbuffers/protobuf/blob/master/docs/performance.md + /// + [MemoryDiagnoser] + public class GoogleMessageBenchmark + { + /// + /// All the datasets to be tested. Add more datasets to the array as they're available. + /// (When C# supports proto2, this will increase significantly.) + /// + public static BenchmarkDatasetConfig[] DatasetConfigurations => new[] + { + // short name is specified to make results table more readable + new BenchmarkDatasetConfig("dataset.google_message1_proto3.pb", "goog_msg1_proto3") + }; + + [ParamsSource(nameof(DatasetConfigurations))] + public BenchmarkDatasetConfig Dataset { get; set; } + + private MessageParser parser; + /// + /// Each data set can contain multiple messages in a single file. + /// Each "write" operation should write each message in turn, and each "parse" + /// operation should parse each message in turn. + /// + private List subTests; + + [GlobalSetup] + public void GlobalSetup() + { + parser = Dataset.Parser; + subTests = Dataset.Payloads.Select(p => new SubTest(p, parser.ParseFrom(p))).ToList(); + } + + [Benchmark] + public void WriteToStream() => subTests.ForEach(item => item.WriteToStream()); + + [Benchmark] + public void ToByteArray() => subTests.ForEach(item => item.ToByteArray()); + + [Benchmark] + public void ParseFromByteArray() => subTests.ForEach(item => item.ParseFromByteArray(parser)); + + [Benchmark] + public void ParseFromStream() => subTests.ForEach(item => item.ParseFromStream(parser)); + + private class SubTest + { + private readonly Stream destinationStream; + private readonly Stream sourceStream; + private readonly byte[] data; + private readonly IMessage message; + + public SubTest(byte[] data, IMessage message) + { + destinationStream = new MemoryStream(data.Length); + sourceStream = new MemoryStream(data); + this.data = data; + this.message = message; + } + + public void Reset() => destinationStream.Position = 0; + + public void WriteToStream() + { + destinationStream.Position = 0; + message.WriteTo(destinationStream); + } + + public void ToByteArray() => message.ToByteArray(); + + public void ParseFromByteArray(MessageParser parser) => parser.ParseFrom(data); + + public void ParseFromStream(MessageParser parser) + { + sourceStream.Position = 0; + parser.ParseFrom(sourceStream); + } + } + } +} diff --git a/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs new file mode 100644 index 0000000000000..8e6710b7089c3 --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs @@ -0,0 +1,258 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2019 Google Inc. All rights reserved. +// https://github.com/protocolbuffers/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using BenchmarkDotNet.Attributes; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Buffers; +using Google.Protobuf.WellKnownTypes; +using Benchmarks.Proto3; + +namespace Google.Protobuf.Benchmarks +{ + /// + /// Benchmark that tests parsing performance for various messages. + /// + [MemoryDiagnoser] + public class ParseMessagesBenchmark + { + const int MaxMessages = 100; + + SubTest manyWrapperFieldsTest = new SubTest(CreateManyWrapperFieldsMessage(), ManyWrapperFieldsMessage.Parser, () => new ManyWrapperFieldsMessage(), MaxMessages); + SubTest manyPrimitiveFieldsTest = new SubTest(CreateManyPrimitiveFieldsMessage(), ManyPrimitiveFieldsMessage.Parser, () => new ManyPrimitiveFieldsMessage(), MaxMessages); + SubTest repeatedFieldTest = new SubTest(CreateRepeatedFieldMessage(), GoogleMessage1.Parser, () => new GoogleMessage1(), MaxMessages); + SubTest emptyMessageTest = new SubTest(new Empty(), Empty.Parser, () => new Empty(), MaxMessages); + + public IEnumerable MessageCountValues => new[] { 10, 100 }; + + [GlobalSetup] + public void GlobalSetup() + { + } + + [Benchmark] + public IMessage ManyWrapperFieldsMessage_ParseFromByteArray() + { + return manyWrapperFieldsTest.ParseFromByteArray(); + } + + [Benchmark] + public IMessage ManyWrapperFieldsMessage_ParseFromReadOnlySequence() + { + return manyWrapperFieldsTest.ParseFromReadOnlySequence(); + } + + [Benchmark] + public IMessage ManyPrimitiveFieldsMessage_ParseFromByteArray() + { + return manyPrimitiveFieldsTest.ParseFromByteArray(); + } + + [Benchmark] + public IMessage ManyPrimitiveFieldsMessage_ParseFromReadOnlySequence() + { + return manyPrimitiveFieldsTest.ParseFromReadOnlySequence(); + } + + [Benchmark] + public IMessage RepeatedFieldMessage_ParseFromByteArray() + { + return repeatedFieldTest.ParseFromByteArray(); + } + + [Benchmark] + public IMessage RepeatedFieldMessage_ParseFromReadOnlySequence() + { + return repeatedFieldTest.ParseFromReadOnlySequence(); + } + + [Benchmark] + public IMessage EmptyMessage_ParseFromByteArray() + { + return emptyMessageTest.ParseFromByteArray(); + } + + [Benchmark] + public IMessage EmptyMessage_ParseFromReadOnlySequence() + { + return emptyMessageTest.ParseFromReadOnlySequence(); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void ManyWrapperFieldsMessage_ParseDelimitedMessagesFromByteArray(int messageCount) + { + manyWrapperFieldsTest.ParseDelimitedMessagesFromByteArray(messageCount); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void ManyWrapperFieldsMessage_ParseDelimitedMessagesFromReadOnlySequence(int messageCount) + { + manyWrapperFieldsTest.ParseDelimitedMessagesFromReadOnlySequence(messageCount); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void ManyPrimitiveFieldsMessage_ParseDelimitedMessagesFromByteArray(int messageCount) + { + manyPrimitiveFieldsTest.ParseDelimitedMessagesFromByteArray(messageCount); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void ManyPrimitiveFieldsMessage_ParseDelimitedMessagesFromReadOnlySequence(int messageCount) + { + manyPrimitiveFieldsTest.ParseDelimitedMessagesFromReadOnlySequence(messageCount); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void RepeatedFieldMessage_ParseDelimitedMessagesFromByteArray(int messageCount) + { + repeatedFieldTest.ParseDelimitedMessagesFromByteArray(messageCount); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void RepeatedFieldMessage_ParseDelimitedMessagesFromReadOnlySequence(int messageCount) + { + repeatedFieldTest.ParseDelimitedMessagesFromReadOnlySequence(messageCount); + } + + public static ManyWrapperFieldsMessage CreateManyWrapperFieldsMessage() + { + // Example data match data of an internal benchmarks + return new ManyWrapperFieldsMessage() + { + Int64Field19 = 123, + Int64Field37 = 1000032, + Int64Field26 = 3453524500, + DoubleField79 = 1.2, + DoubleField25 = 234, + DoubleField9 = 123.3, + DoubleField28 = 23, + DoubleField7 = 234, + DoubleField50 = 2.45 + }; + } + + public static ManyPrimitiveFieldsMessage CreateManyPrimitiveFieldsMessage() + { + // Example data match data of an internal benchmarks + return new ManyPrimitiveFieldsMessage() + { + Int64Field19 = 123, + Int64Field37 = 1000032, + Int64Field26 = 3453524500, + DoubleField79 = 1.2, + DoubleField25 = 234, + DoubleField9 = 123.3, + DoubleField28 = 23, + DoubleField7 = 234, + DoubleField50 = 2.45 + }; + } + + public static GoogleMessage1 CreateRepeatedFieldMessage() + { + // Message with a repeated fixed length item collection + var message = new GoogleMessage1(); + for (ulong i = 0; i < 1000; i++) + { + message.Field5.Add(i); + } + return message; + } + + private class SubTest + { + private readonly IMessage message; + private readonly MessageParser parser; + private readonly Func factory; + private readonly byte[] data; + private readonly byte[] multipleMessagesData; + + private ReadOnlySequence dataSequence; + private ReadOnlySequence multipleMessagesDataSequence; + + public SubTest(IMessage message, MessageParser parser, Func factory, int maxMessageCount) + { + this.message = message; + this.parser = parser; + this.factory = factory; + this.data = message.ToByteArray(); + this.multipleMessagesData = CreateBufferWithMultipleMessages(message, maxMessageCount); + this.dataSequence = new ReadOnlySequence(this.data); + this.multipleMessagesDataSequence = new ReadOnlySequence(this.multipleMessagesData); + } + + public IMessage ParseFromByteArray() => parser.ParseFrom(data); + + public IMessage ParseFromReadOnlySequence() => parser.ParseFrom(dataSequence); + + public void ParseDelimitedMessagesFromByteArray(int messageCount) + { + var input = new CodedInputStream(multipleMessagesData); + for (int i = 0; i < messageCount; i++) + { + var msg = factory(); + input.ReadMessage(msg); + } + } + + public void ParseDelimitedMessagesFromReadOnlySequence(int messageCount) + { + ParseContext.Initialize(multipleMessagesDataSequence, out ParseContext ctx); + for (int i = 0; i < messageCount; i++) + { + var msg = factory(); + ctx.ReadMessage(msg); + } + } + + private static byte[] CreateBufferWithMultipleMessages(IMessage msg, int msgCount) + { + var ms = new MemoryStream(); + var cos = new CodedOutputStream(ms); + for (int i = 0; i < msgCount; i++) + { + cos.WriteMessage(msg); + } + cos.Flush(); + return ms.ToArray(); + } + } + } +} diff --git a/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs new file mode 100644 index 0000000000000..6df1c872c3ca1 --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs @@ -0,0 +1,536 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2019 Google Inc. All rights reserved. +// https://github.com/protocolbuffers/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using BenchmarkDotNet.Attributes; +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.IO; +using System.Buffers; + +namespace Google.Protobuf.Benchmarks +{ + /// + /// Benchmarks throughput when parsing raw primitives. + /// + [MemoryDiagnoser] + public class ParseRawPrimitivesBenchmark + { + // key is the encodedSize of varint values + Dictionary varintInputBuffers; + + byte[] doubleInputBuffer; + byte[] floatInputBuffer; + byte[] fixedIntInputBuffer; + + // key is the encodedSize of string values + Dictionary stringInputBuffers; + Dictionary> stringInputBuffersSegmented; + + Random random = new Random(417384220); // random but deterministic seed + + public IEnumerable StringEncodedSizes => new[] { 1, 4, 10, 105, 10080 }; + public IEnumerable StringSegmentedEncodedSizes => new[] { 105, 10080 }; + + [GlobalSetup] + public void GlobalSetup() + { + // add some extra values that we won't read just to make sure we are far enough from the end of the buffer + // which allows the parser fastpath to always kick in. + const int paddingValueCount = 100; + + varintInputBuffers = new Dictionary(); + for (int encodedSize = 1; encodedSize <= 10; encodedSize++) + { + byte[] buffer = CreateBufferWithRandomVarints(random, BytesToParse / encodedSize, encodedSize, paddingValueCount); + varintInputBuffers.Add(encodedSize, buffer); + } + + doubleInputBuffer = CreateBufferWithRandomDoubles(random, BytesToParse / sizeof(double), paddingValueCount); + floatInputBuffer = CreateBufferWithRandomFloats(random, BytesToParse / sizeof(float), paddingValueCount); + fixedIntInputBuffer = CreateBufferWithRandomData(random, BytesToParse / sizeof(long), sizeof(long), paddingValueCount); + + stringInputBuffers = new Dictionary(); + foreach (var encodedSize in StringEncodedSizes) + { + byte[] buffer = CreateBufferWithStrings(BytesToParse / encodedSize, encodedSize, encodedSize < 10 ? 10 : 1 ); + stringInputBuffers.Add(encodedSize, buffer); + } + + stringInputBuffersSegmented = new Dictionary>(); + foreach (var encodedSize in StringSegmentedEncodedSizes) + { + byte[] buffer = CreateBufferWithStrings(BytesToParse / encodedSize, encodedSize, encodedSize < 10 ? 10 : 1); + stringInputBuffersSegmented.Add(encodedSize, ReadOnlySequenceFactory.CreateWithContent(buffer, segmentSize: 128, addEmptySegmentDelimiters: false)); + } + } + + // Total number of bytes that each benchmark will parse. + // Measuring the time taken to parse buffer of given size makes it easier to compare parsing speed for different + // types and makes it easy to calculate the througput (in MB/s) + // 10800 bytes is chosen because it is divisible by all possible encoded sizes for all primitive types {1..10} + [Params(10080)] + public int BytesToParse { get; set; } + + [Benchmark] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + public int ParseRawVarint32_CodedInputStream(int encodedSize) + { + CodedInputStream cis = new CodedInputStream(varintInputBuffers[encodedSize]); + int sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += cis.ReadInt32(); + } + return sum; + } + + [Benchmark] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + public int ParseRawVarint32_ParseContext(int encodedSize) + { + InitializeParseContext(varintInputBuffers[encodedSize], out ParseContext ctx); + int sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadInt32(); + } + return sum; + } + + [Benchmark] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + [Arguments(6)] + [Arguments(7)] + [Arguments(8)] + [Arguments(9)] + [Arguments(10)] + public long ParseRawVarint64_CodedInputStream(int encodedSize) + { + CodedInputStream cis = new CodedInputStream(varintInputBuffers[encodedSize]); + long sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += cis.ReadInt64(); + } + return sum; + } + + [Benchmark] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + [Arguments(6)] + [Arguments(7)] + [Arguments(8)] + [Arguments(9)] + [Arguments(10)] + public long ParseRawVarint64_ParseContext(int encodedSize) + { + InitializeParseContext(varintInputBuffers[encodedSize], out ParseContext ctx); + long sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadInt64(); + } + return sum; + } + + [Benchmark] + public uint ParseFixed32_CodedInputStream() + { + const int encodedSize = sizeof(uint); + CodedInputStream cis = new CodedInputStream(fixedIntInputBuffer); + uint sum = 0; + for (uint i = 0; i < BytesToParse / encodedSize; i++) + { + sum += cis.ReadFixed32(); + } + return sum; + } + + [Benchmark] + public uint ParseFixed32_ParseContext() + { + const int encodedSize = sizeof(uint); + InitializeParseContext(fixedIntInputBuffer, out ParseContext ctx); + uint sum = 0; + for (uint i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadFixed32(); + } + return sum; + } + + [Benchmark] + public ulong ParseFixed64_CodedInputStream() + { + const int encodedSize = sizeof(ulong); + CodedInputStream cis = new CodedInputStream(fixedIntInputBuffer); + ulong sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += cis.ReadFixed64(); + } + return sum; + } + + [Benchmark] + public ulong ParseFixed64_ParseContext() + { + const int encodedSize = sizeof(ulong); + InitializeParseContext(fixedIntInputBuffer, out ParseContext ctx); + ulong sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadFixed64(); + } + return sum; + } + + [Benchmark] + public float ParseRawFloat_CodedInputStream() + { + const int encodedSize = sizeof(float); + CodedInputStream cis = new CodedInputStream(floatInputBuffer); + float sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += cis.ReadFloat(); + } + return sum; + } + + [Benchmark] + public float ParseRawFloat_ParseContext() + { + const int encodedSize = sizeof(float); + InitializeParseContext(floatInputBuffer, out ParseContext ctx); + float sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadFloat(); + } + return sum; + } + + [Benchmark] + public double ParseRawDouble_CodedInputStream() + { + const int encodedSize = sizeof(double); + CodedInputStream cis = new CodedInputStream(doubleInputBuffer); + double sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += cis.ReadDouble(); + } + return sum; + } + + [Benchmark] + public double ParseRawDouble_ParseContext() + { + const int encodedSize = sizeof(double); + InitializeParseContext(doubleInputBuffer, out ParseContext ctx); + double sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadDouble(); + } + return sum; + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public int ParseString_CodedInputStream(int encodedSize) + { + CodedInputStream cis = new CodedInputStream(stringInputBuffers[encodedSize]); + int sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += cis.ReadString().Length; + } + return sum; + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public int ParseString_ParseContext(int encodedSize) + { + InitializeParseContext(stringInputBuffers[encodedSize], out ParseContext ctx); + int sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadString().Length; + } + return sum; + } + + [Benchmark] + [ArgumentsSource(nameof(StringSegmentedEncodedSizes))] + public int ParseString_ParseContext_MultipleSegments(int encodedSize) + { + InitializeParseContext(stringInputBuffersSegmented[encodedSize], out ParseContext ctx); + int sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadString().Length; + } + return sum; + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public int ParseBytes_CodedInputStream(int encodedSize) + { + CodedInputStream cis = new CodedInputStream(stringInputBuffers[encodedSize]); + int sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += cis.ReadBytes().Length; + } + return sum; + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public int ParseBytes_ParseContext(int encodedSize) + { + InitializeParseContext(stringInputBuffers[encodedSize], out ParseContext ctx); + int sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadBytes().Length; + } + return sum; + } + + [Benchmark] + [ArgumentsSource(nameof(StringSegmentedEncodedSizes))] + public int ParseBytes_ParseContext_MultipleSegments(int encodedSize) + { + InitializeParseContext(stringInputBuffersSegmented[encodedSize], out ParseContext ctx); + int sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadBytes().Length; + } + return sum; + } + + private static void InitializeParseContext(byte[] buffer, out ParseContext ctx) + { + ParseContext.Initialize(new ReadOnlySequence(buffer), out ctx); + } + + private static void InitializeParseContext(ReadOnlySequence buffer, out ParseContext ctx) + { + ParseContext.Initialize(buffer, out ctx); + } + + private static byte[] CreateBufferWithRandomVarints(Random random, int valueCount, int encodedSize, int paddingValueCount) + { + MemoryStream ms = new MemoryStream(); + CodedOutputStream cos = new CodedOutputStream(ms); + for (int i = 0; i < valueCount + paddingValueCount; i++) + { + cos.WriteUInt64(RandomUnsignedVarint(random, encodedSize, false)); + } + cos.Flush(); + var buffer = ms.ToArray(); + + if (buffer.Length != encodedSize * (valueCount + paddingValueCount)) + { + throw new InvalidOperationException($"Unexpected output buffer length {buffer.Length}"); + } + return buffer; + } + + private static byte[] CreateBufferWithRandomFloats(Random random, int valueCount, int paddingValueCount) + { + MemoryStream ms = new MemoryStream(); + CodedOutputStream cos = new CodedOutputStream(ms); + for (int i = 0; i < valueCount + paddingValueCount; i++) + { + cos.WriteFloat((float)random.NextDouble()); + } + cos.Flush(); + var buffer = ms.ToArray(); + return buffer; + } + + private static byte[] CreateBufferWithRandomDoubles(Random random, int valueCount, int paddingValueCount) + { + MemoryStream ms = new MemoryStream(); + CodedOutputStream cos = new CodedOutputStream(ms); + for (int i = 0; i < valueCount + paddingValueCount; i++) + { + cos.WriteDouble(random.NextDouble()); + } + cos.Flush(); + var buffer = ms.ToArray(); + return buffer; + } + + private static byte[] CreateBufferWithRandomData(Random random, int valueCount, int encodedSize, int paddingValueCount) + { + int bufferSize = (valueCount + paddingValueCount) * encodedSize; + byte[] buffer = new byte[bufferSize]; + random.NextBytes(buffer); + return buffer; + } + + /// + /// Generate a random value that will take exactly "encodedSize" bytes when varint-encoded. + /// + public static ulong RandomUnsignedVarint(Random random, int encodedSize, bool fitsIn32Bits) + { + Span randomBytesBuffer = stackalloc byte[8]; + + if (encodedSize < 1 || encodedSize > 10 || (fitsIn32Bits && encodedSize > 5)) + { + throw new ArgumentException("Illegal encodedSize value requested", nameof(encodedSize)); + } + const int bitsPerByte = 7; + + ulong result = 0; + while (true) + { + random.NextBytes(randomBytesBuffer); + ulong randomValue = BinaryPrimitives.ReadUInt64LittleEndian(randomBytesBuffer); + + // only use the number of random bits we need + ulong bitmask = encodedSize < 10 ? ((1UL << (encodedSize * bitsPerByte)) - 1) : ulong.MaxValue; + result = randomValue & bitmask; + + if (fitsIn32Bits) + { + // make sure the resulting value is representable by a uint. + result &= uint.MaxValue; + } + + if (encodedSize == 10) + { + // for 10-byte values the highest bit always needs to be set (7*9=63) + result |= ulong.MaxValue; + break; + } + + // some random values won't require the full "encodedSize" bytes, check that at least + // one of the top 7 bits is set. Retrying is fine since it only happens rarely + if (encodedSize == 1 || (result & (0x7FUL << ((encodedSize - 1) * bitsPerByte))) != 0) + { + break; + } + } + return result; + } + + private static byte[] CreateBufferWithStrings(int valueCount, int encodedSize, int paddingValueCount) + { + var str = CreateStringWithEncodedSize(encodedSize); + + MemoryStream ms = new MemoryStream(); + CodedOutputStream cos = new CodedOutputStream(ms); + for (int i = 0; i < valueCount + paddingValueCount; i++) + { + cos.WriteString(str); + } + cos.Flush(); + var buffer = ms.ToArray(); + + if (buffer.Length != encodedSize * (valueCount + paddingValueCount)) + { + throw new InvalidOperationException($"Unexpected output buffer length {buffer.Length}"); + } + return buffer; + } + + public static string CreateStringWithEncodedSize(int encodedSize) + { + var str = new string('a', encodedSize); + while (CodedOutputStream.ComputeStringSize(str) > encodedSize) + { + str = str.Substring(1); + } + + if (CodedOutputStream.ComputeStringSize(str) != encodedSize) + { + throw new InvalidOperationException($"Generated string with wrong encodedSize"); + } + return str; + } + + public static string CreateNonAsciiStringWithEncodedSize(int encodedSize) + { + if (encodedSize < 3) + { + throw new ArgumentException("Illegal encoded size for a string with non-ascii chars."); + } + var twoByteChar = '\u00DC'; // U-umlaut, UTF8 encoding has 2 bytes + var str = new string(twoByteChar, encodedSize / 2); + while (CodedOutputStream.ComputeStringSize(str) > encodedSize) + { + str = str.Substring(1); + } + + // add padding of ascii characters to reach the desired encoded size. + while (CodedOutputStream.ComputeStringSize(str) < encodedSize) + { + str += 'a'; + } + + // Note that for a few specific encodedSize values, it might be impossible to generate + // the string with the desired encodedSize using the algorithm above. For testing purposes, checking that + // the encoded size we got is actually correct is good enough. + if (CodedOutputStream.ComputeStringSize(str) != encodedSize) + { + throw new InvalidOperationException($"Generated string with wrong encodedSize"); + } + return str; + } + } +} diff --git a/csharp/src/Google.Protobuf.Benchmarks/Program.cs b/csharp/src/Google.Protobuf.Benchmarks/Program.cs new file mode 100644 index 0000000000000..1f77a26135eba --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/Program.cs @@ -0,0 +1,49 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2019 Google Inc. All rights reserved. +// https://github.com/protocolbuffers/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using BenchmarkDotNet.Running; + +namespace Google.Protobuf.Benchmarks +{ + class Program + { + // typical usage: dotnet run -c Release -f netcoreapp2.1 + // (this can profile both .net core and .net framework; for some reason + // if you start from "-f net461", it goes horribly wrong) + public static void Main(string[] args) + { + BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args); + } + } + + +} diff --git a/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs b/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs new file mode 100644 index 0000000000000..9db92447ee942 --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs @@ -0,0 +1,9350 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: wrapper_benchmark_messages.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Google.Protobuf.Benchmarks { + + /// Holder for reflection information generated from wrapper_benchmark_messages.proto + public static partial class WrapperBenchmarkMessagesReflection { + + #region Descriptor + /// File descriptor for wrapper_benchmark_messages.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static WrapperBenchmarkMessagesReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CiB3cmFwcGVyX2JlbmNobWFya19tZXNzYWdlcy5wcm90bxIaZ29vZ2xlLnBy", + "b3RvYnVmLmJlbmNobWFya3MaHmdvb2dsZS9wcm90b2J1Zi93cmFwcGVycy5w", + "cm90byLeLgoYTWFueVdyYXBwZXJGaWVsZHNNZXNzYWdlEjUKD2RvdWJsZV9m", + "aWVsZF85NRhfIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI0", + "Cg5kb3VibGVfZmllbGRfMRgBIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3Vi", + "bGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRfNzkYTyABKAsyHC5nb29nbGUucHJv", + "dG9idWYuRG91YmxlVmFsdWUSMgoNaW50NjRfZmllbGRfMhgCIAEoCzIbLmdv", + "b2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVlEjUKD2RvdWJsZV9maWVsZF85Nhhg", + "IAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRIyCg1pbnQ2NF9m", + "aWVsZF8zGAMgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSMgoN", + "aW50NjRfZmllbGRfNBgEIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZh", + "bHVlEjUKD2RvdWJsZV9maWVsZF85NxhhIAEoCzIcLmdvb2dsZS5wcm90b2J1", + "Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRfNjUYQSABKAsyHC5nb29n", + "bGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzY2GEIg", + "ASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjQKDmRvdWJsZV9m", + "aWVsZF83GAcgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjUK", + "D2RvdWJsZV9maWVsZF82Mhg+IAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3Vi", + "bGVWYWx1ZRI2ChBkb3VibGVfZmllbGRfMTE4GHYgASgLMhwuZ29vZ2xlLnBy", + "b3RvYnVmLkRvdWJsZVZhbHVlEjYKEGRvdWJsZV9maWVsZF8xMTkYdyABKAsy", + "HC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxk", + "XzY3GEMgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjYKEGRv", + "dWJsZV9maWVsZF8xMjAYeCABKAsyHC5nb29nbGUucHJvdG9idWYuRG91Ymxl", + "VmFsdWUSNgoQZG91YmxlX2ZpZWxkXzEyMRh5IAEoCzIcLmdvb2dsZS5wcm90", + "b2J1Zi5Eb3VibGVWYWx1ZRI2ChBkb3VibGVfZmllbGRfMTIyGHogASgLMhwu", + "Z29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjYKEGRvdWJsZV9maWVsZF8x", + "MjMYeyABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNgoQZG91", + "YmxlX2ZpZWxkXzEyNBh8IAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVW", + "YWx1ZRI0Cg5kb3VibGVfZmllbGRfOBgIIAEoCzIcLmdvb2dsZS5wcm90b2J1", + "Zi5Eb3VibGVWYWx1ZRI0Cg5kb3VibGVfZmllbGRfORgJIAEoCzIcLmdvb2ds", + "ZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRfOTgYYiAB", + "KAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2Zp", + "ZWxkXzEwGAogASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjUK", + "D2RvdWJsZV9maWVsZF8xMRgLIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3Vi", + "bGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRfOTkYYyABKAsyHC5nb29nbGUucHJv", + "dG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzg0GFQgASgLMhwu", + "Z29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjUKD2RvdWJsZV9maWVsZF8x", + "NBgOIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI1Cg9kb3Vi", + "bGVfZmllbGRfNzcYTSABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFs", + "dWUSNQoPZG91YmxlX2ZpZWxkXzE1GA8gASgLMhwuZ29vZ2xlLnByb3RvYnVm", + "LkRvdWJsZVZhbHVlEjMKDmludDY0X2ZpZWxkXzE5GBMgASgLMhsuZ29vZ2xl", + "LnByb3RvYnVmLkludDY0VmFsdWUSNAoPaW50NjRfZmllbGRfMTE1GHMgASgL", + "MhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSNgoQZG91YmxlX2ZpZWxk", + "XzExNhh0IAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI0Cg9p", + "bnQ2NF9maWVsZF8xMTcYdSABKAsyGy5nb29nbGUucHJvdG9idWYuSW50NjRW", + "YWx1ZRI1Cg9kb3VibGVfZmllbGRfMjAYFCABKAsyHC5nb29nbGUucHJvdG9i", + "dWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzIxGBUgASgLMhwuZ29v", + "Z2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjUKD3N0cmluZ19maWVsZF83MxhJ", + "IAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5TdHJpbmdWYWx1ZRI1Cg9zdHJpbmdf", + "ZmllbGRfNzQYSiABKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUS", + "NQoPZG91YmxlX2ZpZWxkXzIyGBYgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRv", + "dWJsZVZhbHVlEjUKD2RvdWJsZV9maWVsZF82ORhFIAEoCzIcLmdvb2dsZS5w", + "cm90b2J1Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRfNzAYRiABKAsy", + "HC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxk", + "XzcxGEcgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjUKD2Rv", + "dWJsZV9maWVsZF83MhhIIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVW", + "YWx1ZRI1Cg9kb3VibGVfZmllbGRfMjUYGSABKAsyHC5nb29nbGUucHJvdG9i", + "dWYuRG91YmxlVmFsdWUSMwoOaW50NjRfZmllbGRfMjYYGiABKAsyGy5nb29n", + "bGUucHJvdG9idWYuSW50NjRWYWx1ZRI1Cg9kb3VibGVfZmllbGRfNjgYRCAB", + "KAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2Zp", + "ZWxkXzI4GBwgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjYK", + "EGRvdWJsZV9maWVsZF8xMDYYaiABKAsyHC5nb29nbGUucHJvdG9idWYuRG91", + "YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzI5GB0gASgLMhwuZ29vZ2xlLnBy", + "b3RvYnVmLkRvdWJsZVZhbHVlEjUKD2RvdWJsZV9maWVsZF8zMBgeIAEoCzIc", + "Lmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI2ChBkb3VibGVfZmllbGRf", + "MTAxGGUgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjYKEGRv", + "dWJsZV9maWVsZF8xMDIYZiABKAsyHC5nb29nbGUucHJvdG9idWYuRG91Ymxl", + "VmFsdWUSNgoQZG91YmxlX2ZpZWxkXzEwMxhnIAEoCzIcLmdvb2dsZS5wcm90", + "b2J1Zi5Eb3VibGVWYWx1ZRI2ChBkb3VibGVfZmllbGRfMTA0GGggASgLMhwu", + "Z29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjYKEGRvdWJsZV9maWVsZF8x", + "MDUYaSABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91", + "YmxlX2ZpZWxkXzMxGB8gASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZh", + "bHVlEjMKDmludDY0X2ZpZWxkXzMyGCAgASgLMhsuZ29vZ2xlLnByb3RvYnVm", + "LkludDY0VmFsdWUSNQoPZG91YmxlX2ZpZWxkXzc1GEsgASgLMhwuZ29vZ2xl", + "LnByb3RvYnVmLkRvdWJsZVZhbHVlEjcKEGRvdWJsZV9maWVsZF8xMjkYgQEg", + "ASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEhUKDWVudW1fZmll", + "bGRfODAYUCABKAUSFQoNZW51bV9maWVsZF84MRhRIAEoBRIzCg5pbnQ2NF9m", + "aWVsZF84MhhSIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVlEhUK", + "DWVudW1fZmllbGRfODMYUyABKAUSMwoOaW50NjRfZmllbGRfODUYVSABKAsy", + "Gy5nb29nbGUucHJvdG9idWYuSW50NjRWYWx1ZRIzCg5pbnQ2NF9maWVsZF84", + "NhhWIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVlEjMKDmludDY0", + "X2ZpZWxkXzg3GFcgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUS", + "NAoPaW50NjRfZmllbGRfMTI1GH0gASgLMhsuZ29vZ2xlLnByb3RvYnVmLklu", + "dDY0VmFsdWUSMwoOaW50NjRfZmllbGRfMzcYJSABKAsyGy5nb29nbGUucHJv", + "dG9idWYuSW50NjRWYWx1ZRI1Cg9kb3VibGVfZmllbGRfMzgYJiABKAsyHC5n", + "b29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSMQoMaW50ZXJhY3Rpb25zGCcg", + "ASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSHgoWcmVwZWF0ZWRf", + "aW50X2ZpZWxkXzEwMBhkIAMoBRI1Cg9kb3VibGVfZmllbGRfNDAYKCABKAsy", + "HC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSMwoOaW50NjRfZmllbGRf", + "NDEYKSABKAsyGy5nb29nbGUucHJvdG9idWYuSW50NjRWYWx1ZRI0Cg9pbnQ2", + "NF9maWVsZF8xMjYYfiABKAsyGy5nb29nbGUucHJvdG9idWYuSW50NjRWYWx1", + "ZRI0Cg9pbnQ2NF9maWVsZF8xMjcYfyABKAsyGy5nb29nbGUucHJvdG9idWYu", + "SW50NjRWYWx1ZRI3ChBkb3VibGVfZmllbGRfMTI4GIABIAEoCzIcLmdvb2ds", + "ZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI2ChBkb3VibGVfZmllbGRfMTA5GG0g", + "ASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjQKD2ludDY0X2Zp", + "ZWxkXzExMBhuIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVlEjYK", + "EGRvdWJsZV9maWVsZF8xMTEYbyABKAsyHC5nb29nbGUucHJvdG9idWYuRG91", + "YmxlVmFsdWUSNAoPaW50NjRfZmllbGRfMTEyGHAgASgLMhsuZ29vZ2xlLnBy", + "b3RvYnVmLkludDY0VmFsdWUSNgoQZG91YmxlX2ZpZWxkXzExMxhxIAEoCzIc", + "Lmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI0Cg9pbnQ2NF9maWVsZF8x", + "MTQYciABKAsyGy5nb29nbGUucHJvdG9idWYuSW50NjRWYWx1ZRI1Cg9kb3Vi", + "bGVfZmllbGRfNDIYKiABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFs", + "dWUSMwoOaW50NjRfZmllbGRfNDMYKyABKAsyGy5nb29nbGUucHJvdG9idWYu", + "SW50NjRWYWx1ZRIzCg5pbnQ2NF9maWVsZF80NBgsIAEoCzIbLmdvb2dsZS5w", + "cm90b2J1Zi5JbnQ2NFZhbHVlEjUKD2RvdWJsZV9maWVsZF80NRgtIAEoCzIc", + "Lmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRf", + "NDYYLiABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91", + "YmxlX2ZpZWxkXzc4GE4gASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZh", + "bHVlEjUKD2RvdWJsZV9maWVsZF84OBhYIAEoCzIcLmdvb2dsZS5wcm90b2J1", + "Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRfNDcYLyABKAsyHC5nb29n", + "bGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzg5GFkg", + "ASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjUKD2RvdWJsZV9m", + "aWVsZF80OBgwIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI1", + "Cg9kb3VibGVfZmllbGRfNDkYMSABKAsyHC5nb29nbGUucHJvdG9idWYuRG91", + "YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzUwGDIgASgLMhwuZ29vZ2xlLnBy", + "b3RvYnVmLkRvdWJsZVZhbHVlEjUKD2RvdWJsZV9maWVsZF85MBhaIAEoCzIc", + "Lmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRf", + "NTEYMyABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91", + "YmxlX2ZpZWxkXzkxGFsgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZh", + "bHVlEjUKD2RvdWJsZV9maWVsZF85MhhcIAEoCzIcLmdvb2dsZS5wcm90b2J1", + "Zi5Eb3VibGVWYWx1ZRI0Cg9pbnQ2NF9maWVsZF8xMDcYayABKAsyGy5nb29n", + "bGUucHJvdG9idWYuSW50NjRWYWx1ZRI1Cg9kb3VibGVfZmllbGRfOTMYXSAB", + "KAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNgoQZG91YmxlX2Zp", + "ZWxkXzEwOBhsIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI1", + "Cg9kb3VibGVfZmllbGRfNTIYNCABKAsyHC5nb29nbGUucHJvdG9idWYuRG91", + "YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzUzGDUgASgLMhwuZ29vZ2xlLnBy", + "b3RvYnVmLkRvdWJsZVZhbHVlEjUKD2RvdWJsZV9maWVsZF85NBheIAEoCzIc", + "Lmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRf", + "NTQYNiABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91", + "YmxlX2ZpZWxkXzU1GDcgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZh", + "bHVlEjUKD2RvdWJsZV9maWVsZF81Nhg4IAEoCzIcLmdvb2dsZS5wcm90b2J1", + "Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRfNTcYOSABKAsyHC5nb29n", + "bGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzU4GDog", + "ASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjMKDmludDY0X2Zp", + "ZWxkXzU5GDsgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSMwoO", + "aW50NjRfZmllbGRfNjAYPCABKAsyGy5nb29nbGUucHJvdG9idWYuSW50NjRW", + "YWx1ZSLwFQoaTWFueVByaW1pdGl2ZUZpZWxkc01lc3NhZ2USFwoPZG91Ymxl", + "X2ZpZWxkXzk1GF8gASgBEhYKDmRvdWJsZV9maWVsZF8xGAEgASgBEhcKD2Rv", + "dWJsZV9maWVsZF83ORhPIAEoARIVCg1pbnQ2NF9maWVsZF8yGAIgASgDEhcK", + "D2RvdWJsZV9maWVsZF85NhhgIAEoARIVCg1pbnQ2NF9maWVsZF8zGAMgASgD", + "EhUKDWludDY0X2ZpZWxkXzQYBCABKAMSFwoPZG91YmxlX2ZpZWxkXzk3GGEg", + "ASgBEhcKD2RvdWJsZV9maWVsZF82NRhBIAEoARIXCg9kb3VibGVfZmllbGRf", + "NjYYQiABKAESFgoOZG91YmxlX2ZpZWxkXzcYByABKAESFwoPZG91YmxlX2Zp", + "ZWxkXzYyGD4gASgBEhgKEGRvdWJsZV9maWVsZF8xMTgYdiABKAESGAoQZG91", + "YmxlX2ZpZWxkXzExORh3IAEoARIXCg9kb3VibGVfZmllbGRfNjcYQyABKAES", + "GAoQZG91YmxlX2ZpZWxkXzEyMBh4IAEoARIYChBkb3VibGVfZmllbGRfMTIx", + "GHkgASgBEhgKEGRvdWJsZV9maWVsZF8xMjIYeiABKAESGAoQZG91YmxlX2Zp", + "ZWxkXzEyMxh7IAEoARIYChBkb3VibGVfZmllbGRfMTI0GHwgASgBEhYKDmRv", + "dWJsZV9maWVsZF84GAggASgBEhYKDmRvdWJsZV9maWVsZF85GAkgASgBEhcK", + "D2RvdWJsZV9maWVsZF85OBhiIAEoARIXCg9kb3VibGVfZmllbGRfMTAYCiAB", + "KAESFwoPZG91YmxlX2ZpZWxkXzExGAsgASgBEhcKD2RvdWJsZV9maWVsZF85", + "ORhjIAEoARIXCg9kb3VibGVfZmllbGRfODQYVCABKAESFwoPZG91YmxlX2Zp", + "ZWxkXzE0GA4gASgBEhcKD2RvdWJsZV9maWVsZF83NxhNIAEoARIXCg9kb3Vi", + "bGVfZmllbGRfMTUYDyABKAESFgoOaW50NjRfZmllbGRfMTkYEyABKAMSFwoP", + "aW50NjRfZmllbGRfMTE1GHMgASgDEhgKEGRvdWJsZV9maWVsZF8xMTYYdCAB", + "KAESFwoPaW50NjRfZmllbGRfMTE3GHUgASgDEhcKD2RvdWJsZV9maWVsZF8y", + "MBgUIAEoARIXCg9kb3VibGVfZmllbGRfMjEYFSABKAESFwoPc3RyaW5nX2Zp", + "ZWxkXzczGEkgASgJEhcKD3N0cmluZ19maWVsZF83NBhKIAEoCRIXCg9kb3Vi", + "bGVfZmllbGRfMjIYFiABKAESFwoPZG91YmxlX2ZpZWxkXzY5GEUgASgBEhcK", + "D2RvdWJsZV9maWVsZF83MBhGIAEoARIXCg9kb3VibGVfZmllbGRfNzEYRyAB", + "KAESFwoPZG91YmxlX2ZpZWxkXzcyGEggASgBEhcKD2RvdWJsZV9maWVsZF8y", + "NRgZIAEoARIWCg5pbnQ2NF9maWVsZF8yNhgaIAEoAxIXCg9kb3VibGVfZmll", + "bGRfNjgYRCABKAESFwoPZG91YmxlX2ZpZWxkXzI4GBwgASgBEhgKEGRvdWJs", + "ZV9maWVsZF8xMDYYaiABKAESFwoPZG91YmxlX2ZpZWxkXzI5GB0gASgBEhcK", + "D2RvdWJsZV9maWVsZF8zMBgeIAEoARIYChBkb3VibGVfZmllbGRfMTAxGGUg", + "ASgBEhgKEGRvdWJsZV9maWVsZF8xMDIYZiABKAESGAoQZG91YmxlX2ZpZWxk", + "XzEwMxhnIAEoARIYChBkb3VibGVfZmllbGRfMTA0GGggASgBEhgKEGRvdWJs", + "ZV9maWVsZF8xMDUYaSABKAESFwoPZG91YmxlX2ZpZWxkXzMxGB8gASgBEhYK", + "DmludDY0X2ZpZWxkXzMyGCAgASgDEhcKD2RvdWJsZV9maWVsZF83NRhLIAEo", + "ARIZChBkb3VibGVfZmllbGRfMTI5GIEBIAEoARIVCg1lbnVtX2ZpZWxkXzgw", + "GFAgASgFEhUKDWVudW1fZmllbGRfODEYUSABKAUSFgoOaW50NjRfZmllbGRf", + "ODIYUiABKAMSFQoNZW51bV9maWVsZF84MxhTIAEoBRIWCg5pbnQ2NF9maWVs", + "ZF84NRhVIAEoAxIWCg5pbnQ2NF9maWVsZF84NhhWIAEoAxIWCg5pbnQ2NF9m", + "aWVsZF84NxhXIAEoAxIXCg9pbnQ2NF9maWVsZF8xMjUYfSABKAMSFgoOaW50", + "NjRfZmllbGRfMzcYJSABKAMSFwoPZG91YmxlX2ZpZWxkXzM4GCYgASgBEhQK", + "DGludGVyYWN0aW9ucxgnIAEoAxIeChZyZXBlYXRlZF9pbnRfZmllbGRfMTAw", + "GGQgAygFEhcKD2RvdWJsZV9maWVsZF80MBgoIAEoARIWCg5pbnQ2NF9maWVs", + "ZF80MRgpIAEoAxIXCg9pbnQ2NF9maWVsZF8xMjYYfiABKAMSFwoPaW50NjRf", + "ZmllbGRfMTI3GH8gASgDEhkKEGRvdWJsZV9maWVsZF8xMjgYgAEgASgBEhgK", + "EGRvdWJsZV9maWVsZF8xMDkYbSABKAESFwoPaW50NjRfZmllbGRfMTEwGG4g", + "ASgDEhgKEGRvdWJsZV9maWVsZF8xMTEYbyABKAESFwoPaW50NjRfZmllbGRf", + "MTEyGHAgASgDEhgKEGRvdWJsZV9maWVsZF8xMTMYcSABKAESFwoPaW50NjRf", + "ZmllbGRfMTE0GHIgASgDEhcKD2RvdWJsZV9maWVsZF80MhgqIAEoARIWCg5p", + "bnQ2NF9maWVsZF80MxgrIAEoAxIWCg5pbnQ2NF9maWVsZF80NBgsIAEoAxIX", + "Cg9kb3VibGVfZmllbGRfNDUYLSABKAESFwoPZG91YmxlX2ZpZWxkXzQ2GC4g", + "ASgBEhcKD2RvdWJsZV9maWVsZF83OBhOIAEoARIXCg9kb3VibGVfZmllbGRf", + "ODgYWCABKAESFwoPZG91YmxlX2ZpZWxkXzQ3GC8gASgBEhcKD2RvdWJsZV9m", + "aWVsZF84ORhZIAEoARIXCg9kb3VibGVfZmllbGRfNDgYMCABKAESFwoPZG91", + "YmxlX2ZpZWxkXzQ5GDEgASgBEhcKD2RvdWJsZV9maWVsZF81MBgyIAEoARIX", + "Cg9kb3VibGVfZmllbGRfOTAYWiABKAESFwoPZG91YmxlX2ZpZWxkXzUxGDMg", + "ASgBEhcKD2RvdWJsZV9maWVsZF85MRhbIAEoARIXCg9kb3VibGVfZmllbGRf", + "OTIYXCABKAESFwoPaW50NjRfZmllbGRfMTA3GGsgASgDEhcKD2RvdWJsZV9m", + "aWVsZF85MxhdIAEoARIYChBkb3VibGVfZmllbGRfMTA4GGwgASgBEhcKD2Rv", + "dWJsZV9maWVsZF81Mhg0IAEoARIXCg9kb3VibGVfZmllbGRfNTMYNSABKAES", + "FwoPZG91YmxlX2ZpZWxkXzk0GF4gASgBEhcKD2RvdWJsZV9maWVsZF81NBg2", + "IAEoARIXCg9kb3VibGVfZmllbGRfNTUYNyABKAESFwoPZG91YmxlX2ZpZWxk", + "XzU2GDggASgBEhcKD2RvdWJsZV9maWVsZF81Nxg5IAEoARIXCg9kb3VibGVf", + "ZmllbGRfNTgYOiABKAESFgoOaW50NjRfZmllbGRfNTkYOyABKAMSFgoOaW50", + "NjRfZmllbGRfNjAYPCABKANiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Benchmarks.ManyWrapperFieldsMessage), global::Google.Protobuf.Benchmarks.ManyWrapperFieldsMessage.Parser, new[]{ "DoubleField95", "DoubleField1", "DoubleField79", "Int64Field2", "DoubleField96", "Int64Field3", "Int64Field4", "DoubleField97", "DoubleField65", "DoubleField66", "DoubleField7", "DoubleField62", "DoubleField118", "DoubleField119", "DoubleField67", "DoubleField120", "DoubleField121", "DoubleField122", "DoubleField123", "DoubleField124", "DoubleField8", "DoubleField9", "DoubleField98", "DoubleField10", "DoubleField11", "DoubleField99", "DoubleField84", "DoubleField14", "DoubleField77", "DoubleField15", "Int64Field19", "Int64Field115", "DoubleField116", "Int64Field117", "DoubleField20", "DoubleField21", "StringField73", "StringField74", "DoubleField22", "DoubleField69", "DoubleField70", "DoubleField71", "DoubleField72", "DoubleField25", "Int64Field26", "DoubleField68", "DoubleField28", "DoubleField106", "DoubleField29", "DoubleField30", "DoubleField101", "DoubleField102", "DoubleField103", "DoubleField104", "DoubleField105", "DoubleField31", "Int64Field32", "DoubleField75", "DoubleField129", "EnumField80", "EnumField81", "Int64Field82", "EnumField83", "Int64Field85", "Int64Field86", "Int64Field87", "Int64Field125", "Int64Field37", "DoubleField38", "Interactions", "RepeatedIntField100", "DoubleField40", "Int64Field41", "Int64Field126", "Int64Field127", "DoubleField128", "DoubleField109", "Int64Field110", "DoubleField111", "Int64Field112", "DoubleField113", "Int64Field114", "DoubleField42", "Int64Field43", "Int64Field44", "DoubleField45", "DoubleField46", "DoubleField78", "DoubleField88", "DoubleField47", "DoubleField89", "DoubleField48", "DoubleField49", "DoubleField50", "DoubleField90", "DoubleField51", "DoubleField91", "DoubleField92", "Int64Field107", "DoubleField93", "DoubleField108", "DoubleField52", "DoubleField53", "DoubleField94", "DoubleField54", "DoubleField55", "DoubleField56", "DoubleField57", "DoubleField58", "Int64Field59", "Int64Field60" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Benchmarks.ManyPrimitiveFieldsMessage), global::Google.Protobuf.Benchmarks.ManyPrimitiveFieldsMessage.Parser, new[]{ "DoubleField95", "DoubleField1", "DoubleField79", "Int64Field2", "DoubleField96", "Int64Field3", "Int64Field4", "DoubleField97", "DoubleField65", "DoubleField66", "DoubleField7", "DoubleField62", "DoubleField118", "DoubleField119", "DoubleField67", "DoubleField120", "DoubleField121", "DoubleField122", "DoubleField123", "DoubleField124", "DoubleField8", "DoubleField9", "DoubleField98", "DoubleField10", "DoubleField11", "DoubleField99", "DoubleField84", "DoubleField14", "DoubleField77", "DoubleField15", "Int64Field19", "Int64Field115", "DoubleField116", "Int64Field117", "DoubleField20", "DoubleField21", "StringField73", "StringField74", "DoubleField22", "DoubleField69", "DoubleField70", "DoubleField71", "DoubleField72", "DoubleField25", "Int64Field26", "DoubleField68", "DoubleField28", "DoubleField106", "DoubleField29", "DoubleField30", "DoubleField101", "DoubleField102", "DoubleField103", "DoubleField104", "DoubleField105", "DoubleField31", "Int64Field32", "DoubleField75", "DoubleField129", "EnumField80", "EnumField81", "Int64Field82", "EnumField83", "Int64Field85", "Int64Field86", "Int64Field87", "Int64Field125", "Int64Field37", "DoubleField38", "Interactions", "RepeatedIntField100", "DoubleField40", "Int64Field41", "Int64Field126", "Int64Field127", "DoubleField128", "DoubleField109", "Int64Field110", "DoubleField111", "Int64Field112", "DoubleField113", "Int64Field114", "DoubleField42", "Int64Field43", "Int64Field44", "DoubleField45", "DoubleField46", "DoubleField78", "DoubleField88", "DoubleField47", "DoubleField89", "DoubleField48", "DoubleField49", "DoubleField50", "DoubleField90", "DoubleField51", "DoubleField91", "DoubleField92", "Int64Field107", "DoubleField93", "DoubleField108", "DoubleField52", "DoubleField53", "DoubleField94", "DoubleField54", "DoubleField55", "DoubleField56", "DoubleField57", "DoubleField58", "Int64Field59", "Int64Field60" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + /// + /// a message that has a large number of wrapper fields + /// obfuscated version of an internal message + /// + public sealed partial class ManyWrapperFieldsMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ManyWrapperFieldsMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.Benchmarks.WrapperBenchmarkMessagesReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ManyWrapperFieldsMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ManyWrapperFieldsMessage(ManyWrapperFieldsMessage other) : this() { + DoubleField95 = other.DoubleField95; + DoubleField1 = other.DoubleField1; + DoubleField79 = other.DoubleField79; + Int64Field2 = other.Int64Field2; + DoubleField96 = other.DoubleField96; + Int64Field3 = other.Int64Field3; + Int64Field4 = other.Int64Field4; + DoubleField97 = other.DoubleField97; + DoubleField65 = other.DoubleField65; + DoubleField66 = other.DoubleField66; + DoubleField7 = other.DoubleField7; + DoubleField62 = other.DoubleField62; + DoubleField118 = other.DoubleField118; + DoubleField119 = other.DoubleField119; + DoubleField67 = other.DoubleField67; + DoubleField120 = other.DoubleField120; + DoubleField121 = other.DoubleField121; + DoubleField122 = other.DoubleField122; + DoubleField123 = other.DoubleField123; + DoubleField124 = other.DoubleField124; + DoubleField8 = other.DoubleField8; + DoubleField9 = other.DoubleField9; + DoubleField98 = other.DoubleField98; + DoubleField10 = other.DoubleField10; + DoubleField11 = other.DoubleField11; + DoubleField99 = other.DoubleField99; + DoubleField84 = other.DoubleField84; + DoubleField14 = other.DoubleField14; + DoubleField77 = other.DoubleField77; + DoubleField15 = other.DoubleField15; + Int64Field19 = other.Int64Field19; + Int64Field115 = other.Int64Field115; + DoubleField116 = other.DoubleField116; + Int64Field117 = other.Int64Field117; + DoubleField20 = other.DoubleField20; + DoubleField21 = other.DoubleField21; + StringField73 = other.StringField73; + StringField74 = other.StringField74; + DoubleField22 = other.DoubleField22; + DoubleField69 = other.DoubleField69; + DoubleField70 = other.DoubleField70; + DoubleField71 = other.DoubleField71; + DoubleField72 = other.DoubleField72; + DoubleField25 = other.DoubleField25; + Int64Field26 = other.Int64Field26; + DoubleField68 = other.DoubleField68; + DoubleField28 = other.DoubleField28; + DoubleField106 = other.DoubleField106; + DoubleField29 = other.DoubleField29; + DoubleField30 = other.DoubleField30; + DoubleField101 = other.DoubleField101; + DoubleField102 = other.DoubleField102; + DoubleField103 = other.DoubleField103; + DoubleField104 = other.DoubleField104; + DoubleField105 = other.DoubleField105; + DoubleField31 = other.DoubleField31; + Int64Field32 = other.Int64Field32; + DoubleField75 = other.DoubleField75; + DoubleField129 = other.DoubleField129; + enumField80_ = other.enumField80_; + enumField81_ = other.enumField81_; + Int64Field82 = other.Int64Field82; + enumField83_ = other.enumField83_; + Int64Field85 = other.Int64Field85; + Int64Field86 = other.Int64Field86; + Int64Field87 = other.Int64Field87; + Int64Field125 = other.Int64Field125; + Int64Field37 = other.Int64Field37; + DoubleField38 = other.DoubleField38; + Interactions = other.Interactions; + repeatedIntField100_ = other.repeatedIntField100_.Clone(); + DoubleField40 = other.DoubleField40; + Int64Field41 = other.Int64Field41; + Int64Field126 = other.Int64Field126; + Int64Field127 = other.Int64Field127; + DoubleField128 = other.DoubleField128; + DoubleField109 = other.DoubleField109; + Int64Field110 = other.Int64Field110; + DoubleField111 = other.DoubleField111; + Int64Field112 = other.Int64Field112; + DoubleField113 = other.DoubleField113; + Int64Field114 = other.Int64Field114; + DoubleField42 = other.DoubleField42; + Int64Field43 = other.Int64Field43; + Int64Field44 = other.Int64Field44; + DoubleField45 = other.DoubleField45; + DoubleField46 = other.DoubleField46; + DoubleField78 = other.DoubleField78; + DoubleField88 = other.DoubleField88; + DoubleField47 = other.DoubleField47; + DoubleField89 = other.DoubleField89; + DoubleField48 = other.DoubleField48; + DoubleField49 = other.DoubleField49; + DoubleField50 = other.DoubleField50; + DoubleField90 = other.DoubleField90; + DoubleField51 = other.DoubleField51; + DoubleField91 = other.DoubleField91; + DoubleField92 = other.DoubleField92; + Int64Field107 = other.Int64Field107; + DoubleField93 = other.DoubleField93; + DoubleField108 = other.DoubleField108; + DoubleField52 = other.DoubleField52; + DoubleField53 = other.DoubleField53; + DoubleField94 = other.DoubleField94; + DoubleField54 = other.DoubleField54; + DoubleField55 = other.DoubleField55; + DoubleField56 = other.DoubleField56; + DoubleField57 = other.DoubleField57; + DoubleField58 = other.DoubleField58; + Int64Field59 = other.Int64Field59; + Int64Field60 = other.Int64Field60; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ManyWrapperFieldsMessage Clone() { + return new ManyWrapperFieldsMessage(this); + } + + /// Field number for the "double_field_95" field. + public const int DoubleField95FieldNumber = 95; + private static readonly pb::FieldCodec _single_doubleField95_codec = pb::FieldCodec.ForStructWrapper(762); + private double? doubleField95_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField95 { + get { return doubleField95_; } + set { + doubleField95_ = value; + } + } + + + /// Field number for the "double_field_1" field. + public const int DoubleField1FieldNumber = 1; + private static readonly pb::FieldCodec _single_doubleField1_codec = pb::FieldCodec.ForStructWrapper(10); + private double? doubleField1_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField1 { + get { return doubleField1_; } + set { + doubleField1_ = value; + } + } + + + /// Field number for the "double_field_79" field. + public const int DoubleField79FieldNumber = 79; + private static readonly pb::FieldCodec _single_doubleField79_codec = pb::FieldCodec.ForStructWrapper(634); + private double? doubleField79_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField79 { + get { return doubleField79_; } + set { + doubleField79_ = value; + } + } + + + /// Field number for the "int64_field_2" field. + public const int Int64Field2FieldNumber = 2; + private static readonly pb::FieldCodec _single_int64Field2_codec = pb::FieldCodec.ForStructWrapper(18); + private long? int64Field2_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field2 { + get { return int64Field2_; } + set { + int64Field2_ = value; + } + } + + + /// Field number for the "double_field_96" field. + public const int DoubleField96FieldNumber = 96; + private static readonly pb::FieldCodec _single_doubleField96_codec = pb::FieldCodec.ForStructWrapper(770); + private double? doubleField96_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField96 { + get { return doubleField96_; } + set { + doubleField96_ = value; + } + } + + + /// Field number for the "int64_field_3" field. + public const int Int64Field3FieldNumber = 3; + private static readonly pb::FieldCodec _single_int64Field3_codec = pb::FieldCodec.ForStructWrapper(26); + private long? int64Field3_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field3 { + get { return int64Field3_; } + set { + int64Field3_ = value; + } + } + + + /// Field number for the "int64_field_4" field. + public const int Int64Field4FieldNumber = 4; + private static readonly pb::FieldCodec _single_int64Field4_codec = pb::FieldCodec.ForStructWrapper(34); + private long? int64Field4_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field4 { + get { return int64Field4_; } + set { + int64Field4_ = value; + } + } + + + /// Field number for the "double_field_97" field. + public const int DoubleField97FieldNumber = 97; + private static readonly pb::FieldCodec _single_doubleField97_codec = pb::FieldCodec.ForStructWrapper(778); + private double? doubleField97_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField97 { + get { return doubleField97_; } + set { + doubleField97_ = value; + } + } + + + /// Field number for the "double_field_65" field. + public const int DoubleField65FieldNumber = 65; + private static readonly pb::FieldCodec _single_doubleField65_codec = pb::FieldCodec.ForStructWrapper(522); + private double? doubleField65_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField65 { + get { return doubleField65_; } + set { + doubleField65_ = value; + } + } + + + /// Field number for the "double_field_66" field. + public const int DoubleField66FieldNumber = 66; + private static readonly pb::FieldCodec _single_doubleField66_codec = pb::FieldCodec.ForStructWrapper(530); + private double? doubleField66_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField66 { + get { return doubleField66_; } + set { + doubleField66_ = value; + } + } + + + /// Field number for the "double_field_7" field. + public const int DoubleField7FieldNumber = 7; + private static readonly pb::FieldCodec _single_doubleField7_codec = pb::FieldCodec.ForStructWrapper(58); + private double? doubleField7_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField7 { + get { return doubleField7_; } + set { + doubleField7_ = value; + } + } + + + /// Field number for the "double_field_62" field. + public const int DoubleField62FieldNumber = 62; + private static readonly pb::FieldCodec _single_doubleField62_codec = pb::FieldCodec.ForStructWrapper(498); + private double? doubleField62_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField62 { + get { return doubleField62_; } + set { + doubleField62_ = value; + } + } + + + /// Field number for the "double_field_118" field. + public const int DoubleField118FieldNumber = 118; + private static readonly pb::FieldCodec _single_doubleField118_codec = pb::FieldCodec.ForStructWrapper(946); + private double? doubleField118_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField118 { + get { return doubleField118_; } + set { + doubleField118_ = value; + } + } + + + /// Field number for the "double_field_119" field. + public const int DoubleField119FieldNumber = 119; + private static readonly pb::FieldCodec _single_doubleField119_codec = pb::FieldCodec.ForStructWrapper(954); + private double? doubleField119_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField119 { + get { return doubleField119_; } + set { + doubleField119_ = value; + } + } + + + /// Field number for the "double_field_67" field. + public const int DoubleField67FieldNumber = 67; + private static readonly pb::FieldCodec _single_doubleField67_codec = pb::FieldCodec.ForStructWrapper(538); + private double? doubleField67_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField67 { + get { return doubleField67_; } + set { + doubleField67_ = value; + } + } + + + /// Field number for the "double_field_120" field. + public const int DoubleField120FieldNumber = 120; + private static readonly pb::FieldCodec _single_doubleField120_codec = pb::FieldCodec.ForStructWrapper(962); + private double? doubleField120_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField120 { + get { return doubleField120_; } + set { + doubleField120_ = value; + } + } + + + /// Field number for the "double_field_121" field. + public const int DoubleField121FieldNumber = 121; + private static readonly pb::FieldCodec _single_doubleField121_codec = pb::FieldCodec.ForStructWrapper(970); + private double? doubleField121_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField121 { + get { return doubleField121_; } + set { + doubleField121_ = value; + } + } + + + /// Field number for the "double_field_122" field. + public const int DoubleField122FieldNumber = 122; + private static readonly pb::FieldCodec _single_doubleField122_codec = pb::FieldCodec.ForStructWrapper(978); + private double? doubleField122_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField122 { + get { return doubleField122_; } + set { + doubleField122_ = value; + } + } + + + /// Field number for the "double_field_123" field. + public const int DoubleField123FieldNumber = 123; + private static readonly pb::FieldCodec _single_doubleField123_codec = pb::FieldCodec.ForStructWrapper(986); + private double? doubleField123_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField123 { + get { return doubleField123_; } + set { + doubleField123_ = value; + } + } + + + /// Field number for the "double_field_124" field. + public const int DoubleField124FieldNumber = 124; + private static readonly pb::FieldCodec _single_doubleField124_codec = pb::FieldCodec.ForStructWrapper(994); + private double? doubleField124_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField124 { + get { return doubleField124_; } + set { + doubleField124_ = value; + } + } + + + /// Field number for the "double_field_8" field. + public const int DoubleField8FieldNumber = 8; + private static readonly pb::FieldCodec _single_doubleField8_codec = pb::FieldCodec.ForStructWrapper(66); + private double? doubleField8_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField8 { + get { return doubleField8_; } + set { + doubleField8_ = value; + } + } + + + /// Field number for the "double_field_9" field. + public const int DoubleField9FieldNumber = 9; + private static readonly pb::FieldCodec _single_doubleField9_codec = pb::FieldCodec.ForStructWrapper(74); + private double? doubleField9_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField9 { + get { return doubleField9_; } + set { + doubleField9_ = value; + } + } + + + /// Field number for the "double_field_98" field. + public const int DoubleField98FieldNumber = 98; + private static readonly pb::FieldCodec _single_doubleField98_codec = pb::FieldCodec.ForStructWrapper(786); + private double? doubleField98_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField98 { + get { return doubleField98_; } + set { + doubleField98_ = value; + } + } + + + /// Field number for the "double_field_10" field. + public const int DoubleField10FieldNumber = 10; + private static readonly pb::FieldCodec _single_doubleField10_codec = pb::FieldCodec.ForStructWrapper(82); + private double? doubleField10_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField10 { + get { return doubleField10_; } + set { + doubleField10_ = value; + } + } + + + /// Field number for the "double_field_11" field. + public const int DoubleField11FieldNumber = 11; + private static readonly pb::FieldCodec _single_doubleField11_codec = pb::FieldCodec.ForStructWrapper(90); + private double? doubleField11_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField11 { + get { return doubleField11_; } + set { + doubleField11_ = value; + } + } + + + /// Field number for the "double_field_99" field. + public const int DoubleField99FieldNumber = 99; + private static readonly pb::FieldCodec _single_doubleField99_codec = pb::FieldCodec.ForStructWrapper(794); + private double? doubleField99_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField99 { + get { return doubleField99_; } + set { + doubleField99_ = value; + } + } + + + /// Field number for the "double_field_84" field. + public const int DoubleField84FieldNumber = 84; + private static readonly pb::FieldCodec _single_doubleField84_codec = pb::FieldCodec.ForStructWrapper(674); + private double? doubleField84_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField84 { + get { return doubleField84_; } + set { + doubleField84_ = value; + } + } + + + /// Field number for the "double_field_14" field. + public const int DoubleField14FieldNumber = 14; + private static readonly pb::FieldCodec _single_doubleField14_codec = pb::FieldCodec.ForStructWrapper(114); + private double? doubleField14_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField14 { + get { return doubleField14_; } + set { + doubleField14_ = value; + } + } + + + /// Field number for the "double_field_77" field. + public const int DoubleField77FieldNumber = 77; + private static readonly pb::FieldCodec _single_doubleField77_codec = pb::FieldCodec.ForStructWrapper(618); + private double? doubleField77_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField77 { + get { return doubleField77_; } + set { + doubleField77_ = value; + } + } + + + /// Field number for the "double_field_15" field. + public const int DoubleField15FieldNumber = 15; + private static readonly pb::FieldCodec _single_doubleField15_codec = pb::FieldCodec.ForStructWrapper(122); + private double? doubleField15_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField15 { + get { return doubleField15_; } + set { + doubleField15_ = value; + } + } + + + /// Field number for the "int64_field_19" field. + public const int Int64Field19FieldNumber = 19; + private static readonly pb::FieldCodec _single_int64Field19_codec = pb::FieldCodec.ForStructWrapper(154); + private long? int64Field19_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field19 { + get { return int64Field19_; } + set { + int64Field19_ = value; + } + } + + + /// Field number for the "int64_field_115" field. + public const int Int64Field115FieldNumber = 115; + private static readonly pb::FieldCodec _single_int64Field115_codec = pb::FieldCodec.ForStructWrapper(922); + private long? int64Field115_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field115 { + get { return int64Field115_; } + set { + int64Field115_ = value; + } + } + + + /// Field number for the "double_field_116" field. + public const int DoubleField116FieldNumber = 116; + private static readonly pb::FieldCodec _single_doubleField116_codec = pb::FieldCodec.ForStructWrapper(930); + private double? doubleField116_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField116 { + get { return doubleField116_; } + set { + doubleField116_ = value; + } + } + + + /// Field number for the "int64_field_117" field. + public const int Int64Field117FieldNumber = 117; + private static readonly pb::FieldCodec _single_int64Field117_codec = pb::FieldCodec.ForStructWrapper(938); + private long? int64Field117_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field117 { + get { return int64Field117_; } + set { + int64Field117_ = value; + } + } + + + /// Field number for the "double_field_20" field. + public const int DoubleField20FieldNumber = 20; + private static readonly pb::FieldCodec _single_doubleField20_codec = pb::FieldCodec.ForStructWrapper(162); + private double? doubleField20_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField20 { + get { return doubleField20_; } + set { + doubleField20_ = value; + } + } + + + /// Field number for the "double_field_21" field. + public const int DoubleField21FieldNumber = 21; + private static readonly pb::FieldCodec _single_doubleField21_codec = pb::FieldCodec.ForStructWrapper(170); + private double? doubleField21_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField21 { + get { return doubleField21_; } + set { + doubleField21_ = value; + } + } + + + /// Field number for the "string_field_73" field. + public const int StringField73FieldNumber = 73; + private static readonly pb::FieldCodec _single_stringField73_codec = pb::FieldCodec.ForClassWrapper(586); + private string stringField73_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string StringField73 { + get { return stringField73_; } + set { + stringField73_ = value; + } + } + + + /// Field number for the "string_field_74" field. + public const int StringField74FieldNumber = 74; + private static readonly pb::FieldCodec _single_stringField74_codec = pb::FieldCodec.ForClassWrapper(594); + private string stringField74_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string StringField74 { + get { return stringField74_; } + set { + stringField74_ = value; + } + } + + + /// Field number for the "double_field_22" field. + public const int DoubleField22FieldNumber = 22; + private static readonly pb::FieldCodec _single_doubleField22_codec = pb::FieldCodec.ForStructWrapper(178); + private double? doubleField22_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField22 { + get { return doubleField22_; } + set { + doubleField22_ = value; + } + } + + + /// Field number for the "double_field_69" field. + public const int DoubleField69FieldNumber = 69; + private static readonly pb::FieldCodec _single_doubleField69_codec = pb::FieldCodec.ForStructWrapper(554); + private double? doubleField69_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField69 { + get { return doubleField69_; } + set { + doubleField69_ = value; + } + } + + + /// Field number for the "double_field_70" field. + public const int DoubleField70FieldNumber = 70; + private static readonly pb::FieldCodec _single_doubleField70_codec = pb::FieldCodec.ForStructWrapper(562); + private double? doubleField70_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField70 { + get { return doubleField70_; } + set { + doubleField70_ = value; + } + } + + + /// Field number for the "double_field_71" field. + public const int DoubleField71FieldNumber = 71; + private static readonly pb::FieldCodec _single_doubleField71_codec = pb::FieldCodec.ForStructWrapper(570); + private double? doubleField71_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField71 { + get { return doubleField71_; } + set { + doubleField71_ = value; + } + } + + + /// Field number for the "double_field_72" field. + public const int DoubleField72FieldNumber = 72; + private static readonly pb::FieldCodec _single_doubleField72_codec = pb::FieldCodec.ForStructWrapper(578); + private double? doubleField72_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField72 { + get { return doubleField72_; } + set { + doubleField72_ = value; + } + } + + + /// Field number for the "double_field_25" field. + public const int DoubleField25FieldNumber = 25; + private static readonly pb::FieldCodec _single_doubleField25_codec = pb::FieldCodec.ForStructWrapper(202); + private double? doubleField25_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField25 { + get { return doubleField25_; } + set { + doubleField25_ = value; + } + } + + + /// Field number for the "int64_field_26" field. + public const int Int64Field26FieldNumber = 26; + private static readonly pb::FieldCodec _single_int64Field26_codec = pb::FieldCodec.ForStructWrapper(210); + private long? int64Field26_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field26 { + get { return int64Field26_; } + set { + int64Field26_ = value; + } + } + + + /// Field number for the "double_field_68" field. + public const int DoubleField68FieldNumber = 68; + private static readonly pb::FieldCodec _single_doubleField68_codec = pb::FieldCodec.ForStructWrapper(546); + private double? doubleField68_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField68 { + get { return doubleField68_; } + set { + doubleField68_ = value; + } + } + + + /// Field number for the "double_field_28" field. + public const int DoubleField28FieldNumber = 28; + private static readonly pb::FieldCodec _single_doubleField28_codec = pb::FieldCodec.ForStructWrapper(226); + private double? doubleField28_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField28 { + get { return doubleField28_; } + set { + doubleField28_ = value; + } + } + + + /// Field number for the "double_field_106" field. + public const int DoubleField106FieldNumber = 106; + private static readonly pb::FieldCodec _single_doubleField106_codec = pb::FieldCodec.ForStructWrapper(850); + private double? doubleField106_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField106 { + get { return doubleField106_; } + set { + doubleField106_ = value; + } + } + + + /// Field number for the "double_field_29" field. + public const int DoubleField29FieldNumber = 29; + private static readonly pb::FieldCodec _single_doubleField29_codec = pb::FieldCodec.ForStructWrapper(234); + private double? doubleField29_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField29 { + get { return doubleField29_; } + set { + doubleField29_ = value; + } + } + + + /// Field number for the "double_field_30" field. + public const int DoubleField30FieldNumber = 30; + private static readonly pb::FieldCodec _single_doubleField30_codec = pb::FieldCodec.ForStructWrapper(242); + private double? doubleField30_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField30 { + get { return doubleField30_; } + set { + doubleField30_ = value; + } + } + + + /// Field number for the "double_field_101" field. + public const int DoubleField101FieldNumber = 101; + private static readonly pb::FieldCodec _single_doubleField101_codec = pb::FieldCodec.ForStructWrapper(810); + private double? doubleField101_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField101 { + get { return doubleField101_; } + set { + doubleField101_ = value; + } + } + + + /// Field number for the "double_field_102" field. + public const int DoubleField102FieldNumber = 102; + private static readonly pb::FieldCodec _single_doubleField102_codec = pb::FieldCodec.ForStructWrapper(818); + private double? doubleField102_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField102 { + get { return doubleField102_; } + set { + doubleField102_ = value; + } + } + + + /// Field number for the "double_field_103" field. + public const int DoubleField103FieldNumber = 103; + private static readonly pb::FieldCodec _single_doubleField103_codec = pb::FieldCodec.ForStructWrapper(826); + private double? doubleField103_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField103 { + get { return doubleField103_; } + set { + doubleField103_ = value; + } + } + + + /// Field number for the "double_field_104" field. + public const int DoubleField104FieldNumber = 104; + private static readonly pb::FieldCodec _single_doubleField104_codec = pb::FieldCodec.ForStructWrapper(834); + private double? doubleField104_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField104 { + get { return doubleField104_; } + set { + doubleField104_ = value; + } + } + + + /// Field number for the "double_field_105" field. + public const int DoubleField105FieldNumber = 105; + private static readonly pb::FieldCodec _single_doubleField105_codec = pb::FieldCodec.ForStructWrapper(842); + private double? doubleField105_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField105 { + get { return doubleField105_; } + set { + doubleField105_ = value; + } + } + + + /// Field number for the "double_field_31" field. + public const int DoubleField31FieldNumber = 31; + private static readonly pb::FieldCodec _single_doubleField31_codec = pb::FieldCodec.ForStructWrapper(250); + private double? doubleField31_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField31 { + get { return doubleField31_; } + set { + doubleField31_ = value; + } + } + + + /// Field number for the "int64_field_32" field. + public const int Int64Field32FieldNumber = 32; + private static readonly pb::FieldCodec _single_int64Field32_codec = pb::FieldCodec.ForStructWrapper(258); + private long? int64Field32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field32 { + get { return int64Field32_; } + set { + int64Field32_ = value; + } + } + + + /// Field number for the "double_field_75" field. + public const int DoubleField75FieldNumber = 75; + private static readonly pb::FieldCodec _single_doubleField75_codec = pb::FieldCodec.ForStructWrapper(602); + private double? doubleField75_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField75 { + get { return doubleField75_; } + set { + doubleField75_ = value; + } + } + + + /// Field number for the "double_field_129" field. + public const int DoubleField129FieldNumber = 129; + private static readonly pb::FieldCodec _single_doubleField129_codec = pb::FieldCodec.ForStructWrapper(1034); + private double? doubleField129_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField129 { + get { return doubleField129_; } + set { + doubleField129_ = value; + } + } + + + /// Field number for the "enum_field_80" field. + public const int EnumField80FieldNumber = 80; + private int enumField80_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int EnumField80 { + get { return enumField80_; } + set { + enumField80_ = value; + } + } + + /// Field number for the "enum_field_81" field. + public const int EnumField81FieldNumber = 81; + private int enumField81_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int EnumField81 { + get { return enumField81_; } + set { + enumField81_ = value; + } + } + + /// Field number for the "int64_field_82" field. + public const int Int64Field82FieldNumber = 82; + private static readonly pb::FieldCodec _single_int64Field82_codec = pb::FieldCodec.ForStructWrapper(658); + private long? int64Field82_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field82 { + get { return int64Field82_; } + set { + int64Field82_ = value; + } + } + + + /// Field number for the "enum_field_83" field. + public const int EnumField83FieldNumber = 83; + private int enumField83_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int EnumField83 { + get { return enumField83_; } + set { + enumField83_ = value; + } + } + + /// Field number for the "int64_field_85" field. + public const int Int64Field85FieldNumber = 85; + private static readonly pb::FieldCodec _single_int64Field85_codec = pb::FieldCodec.ForStructWrapper(682); + private long? int64Field85_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field85 { + get { return int64Field85_; } + set { + int64Field85_ = value; + } + } + + + /// Field number for the "int64_field_86" field. + public const int Int64Field86FieldNumber = 86; + private static readonly pb::FieldCodec _single_int64Field86_codec = pb::FieldCodec.ForStructWrapper(690); + private long? int64Field86_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field86 { + get { return int64Field86_; } + set { + int64Field86_ = value; + } + } + + + /// Field number for the "int64_field_87" field. + public const int Int64Field87FieldNumber = 87; + private static readonly pb::FieldCodec _single_int64Field87_codec = pb::FieldCodec.ForStructWrapper(698); + private long? int64Field87_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field87 { + get { return int64Field87_; } + set { + int64Field87_ = value; + } + } + + + /// Field number for the "int64_field_125" field. + public const int Int64Field125FieldNumber = 125; + private static readonly pb::FieldCodec _single_int64Field125_codec = pb::FieldCodec.ForStructWrapper(1002); + private long? int64Field125_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field125 { + get { return int64Field125_; } + set { + int64Field125_ = value; + } + } + + + /// Field number for the "int64_field_37" field. + public const int Int64Field37FieldNumber = 37; + private static readonly pb::FieldCodec _single_int64Field37_codec = pb::FieldCodec.ForStructWrapper(298); + private long? int64Field37_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field37 { + get { return int64Field37_; } + set { + int64Field37_ = value; + } + } + + + /// Field number for the "double_field_38" field. + public const int DoubleField38FieldNumber = 38; + private static readonly pb::FieldCodec _single_doubleField38_codec = pb::FieldCodec.ForStructWrapper(306); + private double? doubleField38_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField38 { + get { return doubleField38_; } + set { + doubleField38_ = value; + } + } + + + /// Field number for the "interactions" field. + public const int InteractionsFieldNumber = 39; + private static readonly pb::FieldCodec _single_interactions_codec = pb::FieldCodec.ForStructWrapper(314); + private long? interactions_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Interactions { + get { return interactions_; } + set { + interactions_ = value; + } + } + + + /// Field number for the "repeated_int_field_100" field. + public const int RepeatedIntField100FieldNumber = 100; + private static readonly pb::FieldCodec _repeated_repeatedIntField100_codec + = pb::FieldCodec.ForInt32(802); + private readonly pbc::RepeatedField repeatedIntField100_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedIntField100 { + get { return repeatedIntField100_; } + } + + /// Field number for the "double_field_40" field. + public const int DoubleField40FieldNumber = 40; + private static readonly pb::FieldCodec _single_doubleField40_codec = pb::FieldCodec.ForStructWrapper(322); + private double? doubleField40_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField40 { + get { return doubleField40_; } + set { + doubleField40_ = value; + } + } + + + /// Field number for the "int64_field_41" field. + public const int Int64Field41FieldNumber = 41; + private static readonly pb::FieldCodec _single_int64Field41_codec = pb::FieldCodec.ForStructWrapper(330); + private long? int64Field41_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field41 { + get { return int64Field41_; } + set { + int64Field41_ = value; + } + } + + + /// Field number for the "int64_field_126" field. + public const int Int64Field126FieldNumber = 126; + private static readonly pb::FieldCodec _single_int64Field126_codec = pb::FieldCodec.ForStructWrapper(1010); + private long? int64Field126_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field126 { + get { return int64Field126_; } + set { + int64Field126_ = value; + } + } + + + /// Field number for the "int64_field_127" field. + public const int Int64Field127FieldNumber = 127; + private static readonly pb::FieldCodec _single_int64Field127_codec = pb::FieldCodec.ForStructWrapper(1018); + private long? int64Field127_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field127 { + get { return int64Field127_; } + set { + int64Field127_ = value; + } + } + + + /// Field number for the "double_field_128" field. + public const int DoubleField128FieldNumber = 128; + private static readonly pb::FieldCodec _single_doubleField128_codec = pb::FieldCodec.ForStructWrapper(1026); + private double? doubleField128_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField128 { + get { return doubleField128_; } + set { + doubleField128_ = value; + } + } + + + /// Field number for the "double_field_109" field. + public const int DoubleField109FieldNumber = 109; + private static readonly pb::FieldCodec _single_doubleField109_codec = pb::FieldCodec.ForStructWrapper(874); + private double? doubleField109_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField109 { + get { return doubleField109_; } + set { + doubleField109_ = value; + } + } + + + /// Field number for the "int64_field_110" field. + public const int Int64Field110FieldNumber = 110; + private static readonly pb::FieldCodec _single_int64Field110_codec = pb::FieldCodec.ForStructWrapper(882); + private long? int64Field110_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field110 { + get { return int64Field110_; } + set { + int64Field110_ = value; + } + } + + + /// Field number for the "double_field_111" field. + public const int DoubleField111FieldNumber = 111; + private static readonly pb::FieldCodec _single_doubleField111_codec = pb::FieldCodec.ForStructWrapper(890); + private double? doubleField111_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField111 { + get { return doubleField111_; } + set { + doubleField111_ = value; + } + } + + + /// Field number for the "int64_field_112" field. + public const int Int64Field112FieldNumber = 112; + private static readonly pb::FieldCodec _single_int64Field112_codec = pb::FieldCodec.ForStructWrapper(898); + private long? int64Field112_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field112 { + get { return int64Field112_; } + set { + int64Field112_ = value; + } + } + + + /// Field number for the "double_field_113" field. + public const int DoubleField113FieldNumber = 113; + private static readonly pb::FieldCodec _single_doubleField113_codec = pb::FieldCodec.ForStructWrapper(906); + private double? doubleField113_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField113 { + get { return doubleField113_; } + set { + doubleField113_ = value; + } + } + + + /// Field number for the "int64_field_114" field. + public const int Int64Field114FieldNumber = 114; + private static readonly pb::FieldCodec _single_int64Field114_codec = pb::FieldCodec.ForStructWrapper(914); + private long? int64Field114_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field114 { + get { return int64Field114_; } + set { + int64Field114_ = value; + } + } + + + /// Field number for the "double_field_42" field. + public const int DoubleField42FieldNumber = 42; + private static readonly pb::FieldCodec _single_doubleField42_codec = pb::FieldCodec.ForStructWrapper(338); + private double? doubleField42_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField42 { + get { return doubleField42_; } + set { + doubleField42_ = value; + } + } + + + /// Field number for the "int64_field_43" field. + public const int Int64Field43FieldNumber = 43; + private static readonly pb::FieldCodec _single_int64Field43_codec = pb::FieldCodec.ForStructWrapper(346); + private long? int64Field43_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field43 { + get { return int64Field43_; } + set { + int64Field43_ = value; + } + } + + + /// Field number for the "int64_field_44" field. + public const int Int64Field44FieldNumber = 44; + private static readonly pb::FieldCodec _single_int64Field44_codec = pb::FieldCodec.ForStructWrapper(354); + private long? int64Field44_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field44 { + get { return int64Field44_; } + set { + int64Field44_ = value; + } + } + + + /// Field number for the "double_field_45" field. + public const int DoubleField45FieldNumber = 45; + private static readonly pb::FieldCodec _single_doubleField45_codec = pb::FieldCodec.ForStructWrapper(362); + private double? doubleField45_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField45 { + get { return doubleField45_; } + set { + doubleField45_ = value; + } + } + + + /// Field number for the "double_field_46" field. + public const int DoubleField46FieldNumber = 46; + private static readonly pb::FieldCodec _single_doubleField46_codec = pb::FieldCodec.ForStructWrapper(370); + private double? doubleField46_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField46 { + get { return doubleField46_; } + set { + doubleField46_ = value; + } + } + + + /// Field number for the "double_field_78" field. + public const int DoubleField78FieldNumber = 78; + private static readonly pb::FieldCodec _single_doubleField78_codec = pb::FieldCodec.ForStructWrapper(626); + private double? doubleField78_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField78 { + get { return doubleField78_; } + set { + doubleField78_ = value; + } + } + + + /// Field number for the "double_field_88" field. + public const int DoubleField88FieldNumber = 88; + private static readonly pb::FieldCodec _single_doubleField88_codec = pb::FieldCodec.ForStructWrapper(706); + private double? doubleField88_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField88 { + get { return doubleField88_; } + set { + doubleField88_ = value; + } + } + + + /// Field number for the "double_field_47" field. + public const int DoubleField47FieldNumber = 47; + private static readonly pb::FieldCodec _single_doubleField47_codec = pb::FieldCodec.ForStructWrapper(378); + private double? doubleField47_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField47 { + get { return doubleField47_; } + set { + doubleField47_ = value; + } + } + + + /// Field number for the "double_field_89" field. + public const int DoubleField89FieldNumber = 89; + private static readonly pb::FieldCodec _single_doubleField89_codec = pb::FieldCodec.ForStructWrapper(714); + private double? doubleField89_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField89 { + get { return doubleField89_; } + set { + doubleField89_ = value; + } + } + + + /// Field number for the "double_field_48" field. + public const int DoubleField48FieldNumber = 48; + private static readonly pb::FieldCodec _single_doubleField48_codec = pb::FieldCodec.ForStructWrapper(386); + private double? doubleField48_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField48 { + get { return doubleField48_; } + set { + doubleField48_ = value; + } + } + + + /// Field number for the "double_field_49" field. + public const int DoubleField49FieldNumber = 49; + private static readonly pb::FieldCodec _single_doubleField49_codec = pb::FieldCodec.ForStructWrapper(394); + private double? doubleField49_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField49 { + get { return doubleField49_; } + set { + doubleField49_ = value; + } + } + + + /// Field number for the "double_field_50" field. + public const int DoubleField50FieldNumber = 50; + private static readonly pb::FieldCodec _single_doubleField50_codec = pb::FieldCodec.ForStructWrapper(402); + private double? doubleField50_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField50 { + get { return doubleField50_; } + set { + doubleField50_ = value; + } + } + + + /// Field number for the "double_field_90" field. + public const int DoubleField90FieldNumber = 90; + private static readonly pb::FieldCodec _single_doubleField90_codec = pb::FieldCodec.ForStructWrapper(722); + private double? doubleField90_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField90 { + get { return doubleField90_; } + set { + doubleField90_ = value; + } + } + + + /// Field number for the "double_field_51" field. + public const int DoubleField51FieldNumber = 51; + private static readonly pb::FieldCodec _single_doubleField51_codec = pb::FieldCodec.ForStructWrapper(410); + private double? doubleField51_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField51 { + get { return doubleField51_; } + set { + doubleField51_ = value; + } + } + + + /// Field number for the "double_field_91" field. + public const int DoubleField91FieldNumber = 91; + private static readonly pb::FieldCodec _single_doubleField91_codec = pb::FieldCodec.ForStructWrapper(730); + private double? doubleField91_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField91 { + get { return doubleField91_; } + set { + doubleField91_ = value; + } + } + + + /// Field number for the "double_field_92" field. + public const int DoubleField92FieldNumber = 92; + private static readonly pb::FieldCodec _single_doubleField92_codec = pb::FieldCodec.ForStructWrapper(738); + private double? doubleField92_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField92 { + get { return doubleField92_; } + set { + doubleField92_ = value; + } + } + + + /// Field number for the "int64_field_107" field. + public const int Int64Field107FieldNumber = 107; + private static readonly pb::FieldCodec _single_int64Field107_codec = pb::FieldCodec.ForStructWrapper(858); + private long? int64Field107_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field107 { + get { return int64Field107_; } + set { + int64Field107_ = value; + } + } + + + /// Field number for the "double_field_93" field. + public const int DoubleField93FieldNumber = 93; + private static readonly pb::FieldCodec _single_doubleField93_codec = pb::FieldCodec.ForStructWrapper(746); + private double? doubleField93_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField93 { + get { return doubleField93_; } + set { + doubleField93_ = value; + } + } + + + /// Field number for the "double_field_108" field. + public const int DoubleField108FieldNumber = 108; + private static readonly pb::FieldCodec _single_doubleField108_codec = pb::FieldCodec.ForStructWrapper(866); + private double? doubleField108_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField108 { + get { return doubleField108_; } + set { + doubleField108_ = value; + } + } + + + /// Field number for the "double_field_52" field. + public const int DoubleField52FieldNumber = 52; + private static readonly pb::FieldCodec _single_doubleField52_codec = pb::FieldCodec.ForStructWrapper(418); + private double? doubleField52_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField52 { + get { return doubleField52_; } + set { + doubleField52_ = value; + } + } + + + /// Field number for the "double_field_53" field. + public const int DoubleField53FieldNumber = 53; + private static readonly pb::FieldCodec _single_doubleField53_codec = pb::FieldCodec.ForStructWrapper(426); + private double? doubleField53_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField53 { + get { return doubleField53_; } + set { + doubleField53_ = value; + } + } + + + /// Field number for the "double_field_94" field. + public const int DoubleField94FieldNumber = 94; + private static readonly pb::FieldCodec _single_doubleField94_codec = pb::FieldCodec.ForStructWrapper(754); + private double? doubleField94_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField94 { + get { return doubleField94_; } + set { + doubleField94_ = value; + } + } + + + /// Field number for the "double_field_54" field. + public const int DoubleField54FieldNumber = 54; + private static readonly pb::FieldCodec _single_doubleField54_codec = pb::FieldCodec.ForStructWrapper(434); + private double? doubleField54_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField54 { + get { return doubleField54_; } + set { + doubleField54_ = value; + } + } + + + /// Field number for the "double_field_55" field. + public const int DoubleField55FieldNumber = 55; + private static readonly pb::FieldCodec _single_doubleField55_codec = pb::FieldCodec.ForStructWrapper(442); + private double? doubleField55_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField55 { + get { return doubleField55_; } + set { + doubleField55_ = value; + } + } + + + /// Field number for the "double_field_56" field. + public const int DoubleField56FieldNumber = 56; + private static readonly pb::FieldCodec _single_doubleField56_codec = pb::FieldCodec.ForStructWrapper(450); + private double? doubleField56_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField56 { + get { return doubleField56_; } + set { + doubleField56_ = value; + } + } + + + /// Field number for the "double_field_57" field. + public const int DoubleField57FieldNumber = 57; + private static readonly pb::FieldCodec _single_doubleField57_codec = pb::FieldCodec.ForStructWrapper(458); + private double? doubleField57_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField57 { + get { return doubleField57_; } + set { + doubleField57_ = value; + } + } + + + /// Field number for the "double_field_58" field. + public const int DoubleField58FieldNumber = 58; + private static readonly pb::FieldCodec _single_doubleField58_codec = pb::FieldCodec.ForStructWrapper(466); + private double? doubleField58_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? DoubleField58 { + get { return doubleField58_; } + set { + doubleField58_ = value; + } + } + + + /// Field number for the "int64_field_59" field. + public const int Int64Field59FieldNumber = 59; + private static readonly pb::FieldCodec _single_int64Field59_codec = pb::FieldCodec.ForStructWrapper(474); + private long? int64Field59_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field59 { + get { return int64Field59_; } + set { + int64Field59_ = value; + } + } + + + /// Field number for the "int64_field_60" field. + public const int Int64Field60FieldNumber = 60; + private static readonly pb::FieldCodec _single_int64Field60_codec = pb::FieldCodec.ForStructWrapper(482); + private long? int64Field60_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? Int64Field60 { + get { return int64Field60_; } + set { + int64Field60_ = value; + } + } + + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ManyWrapperFieldsMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ManyWrapperFieldsMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField95, other.DoubleField95)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField1, other.DoubleField1)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField79, other.DoubleField79)) return false; + if (Int64Field2 != other.Int64Field2) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField96, other.DoubleField96)) return false; + if (Int64Field3 != other.Int64Field3) return false; + if (Int64Field4 != other.Int64Field4) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField97, other.DoubleField97)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField65, other.DoubleField65)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField66, other.DoubleField66)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField7, other.DoubleField7)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField62, other.DoubleField62)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField118, other.DoubleField118)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField119, other.DoubleField119)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField67, other.DoubleField67)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField120, other.DoubleField120)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField121, other.DoubleField121)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField122, other.DoubleField122)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField123, other.DoubleField123)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField124, other.DoubleField124)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField8, other.DoubleField8)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField9, other.DoubleField9)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField98, other.DoubleField98)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField10, other.DoubleField10)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField11, other.DoubleField11)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField99, other.DoubleField99)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField84, other.DoubleField84)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField14, other.DoubleField14)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField77, other.DoubleField77)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField15, other.DoubleField15)) return false; + if (Int64Field19 != other.Int64Field19) return false; + if (Int64Field115 != other.Int64Field115) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField116, other.DoubleField116)) return false; + if (Int64Field117 != other.Int64Field117) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField20, other.DoubleField20)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField21, other.DoubleField21)) return false; + if (StringField73 != other.StringField73) return false; + if (StringField74 != other.StringField74) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField22, other.DoubleField22)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField69, other.DoubleField69)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField70, other.DoubleField70)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField71, other.DoubleField71)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField72, other.DoubleField72)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField25, other.DoubleField25)) return false; + if (Int64Field26 != other.Int64Field26) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField68, other.DoubleField68)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField28, other.DoubleField28)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField106, other.DoubleField106)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField29, other.DoubleField29)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField30, other.DoubleField30)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField101, other.DoubleField101)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField102, other.DoubleField102)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField103, other.DoubleField103)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField104, other.DoubleField104)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField105, other.DoubleField105)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField31, other.DoubleField31)) return false; + if (Int64Field32 != other.Int64Field32) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField75, other.DoubleField75)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField129, other.DoubleField129)) return false; + if (EnumField80 != other.EnumField80) return false; + if (EnumField81 != other.EnumField81) return false; + if (Int64Field82 != other.Int64Field82) return false; + if (EnumField83 != other.EnumField83) return false; + if (Int64Field85 != other.Int64Field85) return false; + if (Int64Field86 != other.Int64Field86) return false; + if (Int64Field87 != other.Int64Field87) return false; + if (Int64Field125 != other.Int64Field125) return false; + if (Int64Field37 != other.Int64Field37) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField38, other.DoubleField38)) return false; + if (Interactions != other.Interactions) return false; + if(!repeatedIntField100_.Equals(other.repeatedIntField100_)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField40, other.DoubleField40)) return false; + if (Int64Field41 != other.Int64Field41) return false; + if (Int64Field126 != other.Int64Field126) return false; + if (Int64Field127 != other.Int64Field127) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField128, other.DoubleField128)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField109, other.DoubleField109)) return false; + if (Int64Field110 != other.Int64Field110) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField111, other.DoubleField111)) return false; + if (Int64Field112 != other.Int64Field112) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField113, other.DoubleField113)) return false; + if (Int64Field114 != other.Int64Field114) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField42, other.DoubleField42)) return false; + if (Int64Field43 != other.Int64Field43) return false; + if (Int64Field44 != other.Int64Field44) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField45, other.DoubleField45)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField46, other.DoubleField46)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField78, other.DoubleField78)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField88, other.DoubleField88)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField47, other.DoubleField47)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField89, other.DoubleField89)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField48, other.DoubleField48)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField49, other.DoubleField49)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField50, other.DoubleField50)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField90, other.DoubleField90)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField51, other.DoubleField51)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField91, other.DoubleField91)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField92, other.DoubleField92)) return false; + if (Int64Field107 != other.Int64Field107) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField93, other.DoubleField93)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField108, other.DoubleField108)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField52, other.DoubleField52)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField53, other.DoubleField53)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField94, other.DoubleField94)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField54, other.DoubleField54)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField55, other.DoubleField55)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField56, other.DoubleField56)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField57, other.DoubleField57)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField58, other.DoubleField58)) return false; + if (Int64Field59 != other.Int64Field59) return false; + if (Int64Field60 != other.Int64Field60) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (doubleField95_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField95); + if (doubleField1_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField1); + if (doubleField79_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField79); + if (int64Field2_ != null) hash ^= Int64Field2.GetHashCode(); + if (doubleField96_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField96); + if (int64Field3_ != null) hash ^= Int64Field3.GetHashCode(); + if (int64Field4_ != null) hash ^= Int64Field4.GetHashCode(); + if (doubleField97_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField97); + if (doubleField65_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField65); + if (doubleField66_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField66); + if (doubleField7_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField7); + if (doubleField62_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField62); + if (doubleField118_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField118); + if (doubleField119_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField119); + if (doubleField67_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField67); + if (doubleField120_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField120); + if (doubleField121_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField121); + if (doubleField122_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField122); + if (doubleField123_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField123); + if (doubleField124_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField124); + if (doubleField8_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField8); + if (doubleField9_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField9); + if (doubleField98_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField98); + if (doubleField10_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField10); + if (doubleField11_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField11); + if (doubleField99_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField99); + if (doubleField84_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField84); + if (doubleField14_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField14); + if (doubleField77_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField77); + if (doubleField15_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField15); + if (int64Field19_ != null) hash ^= Int64Field19.GetHashCode(); + if (int64Field115_ != null) hash ^= Int64Field115.GetHashCode(); + if (doubleField116_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField116); + if (int64Field117_ != null) hash ^= Int64Field117.GetHashCode(); + if (doubleField20_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField20); + if (doubleField21_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField21); + if (stringField73_ != null) hash ^= StringField73.GetHashCode(); + if (stringField74_ != null) hash ^= StringField74.GetHashCode(); + if (doubleField22_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField22); + if (doubleField69_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField69); + if (doubleField70_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField70); + if (doubleField71_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField71); + if (doubleField72_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField72); + if (doubleField25_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField25); + if (int64Field26_ != null) hash ^= Int64Field26.GetHashCode(); + if (doubleField68_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField68); + if (doubleField28_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField28); + if (doubleField106_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField106); + if (doubleField29_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField29); + if (doubleField30_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField30); + if (doubleField101_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField101); + if (doubleField102_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField102); + if (doubleField103_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField103); + if (doubleField104_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField104); + if (doubleField105_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField105); + if (doubleField31_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField31); + if (int64Field32_ != null) hash ^= Int64Field32.GetHashCode(); + if (doubleField75_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField75); + if (doubleField129_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField129); + if (EnumField80 != 0) hash ^= EnumField80.GetHashCode(); + if (EnumField81 != 0) hash ^= EnumField81.GetHashCode(); + if (int64Field82_ != null) hash ^= Int64Field82.GetHashCode(); + if (EnumField83 != 0) hash ^= EnumField83.GetHashCode(); + if (int64Field85_ != null) hash ^= Int64Field85.GetHashCode(); + if (int64Field86_ != null) hash ^= Int64Field86.GetHashCode(); + if (int64Field87_ != null) hash ^= Int64Field87.GetHashCode(); + if (int64Field125_ != null) hash ^= Int64Field125.GetHashCode(); + if (int64Field37_ != null) hash ^= Int64Field37.GetHashCode(); + if (doubleField38_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField38); + if (interactions_ != null) hash ^= Interactions.GetHashCode(); + hash ^= repeatedIntField100_.GetHashCode(); + if (doubleField40_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField40); + if (int64Field41_ != null) hash ^= Int64Field41.GetHashCode(); + if (int64Field126_ != null) hash ^= Int64Field126.GetHashCode(); + if (int64Field127_ != null) hash ^= Int64Field127.GetHashCode(); + if (doubleField128_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField128); + if (doubleField109_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField109); + if (int64Field110_ != null) hash ^= Int64Field110.GetHashCode(); + if (doubleField111_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField111); + if (int64Field112_ != null) hash ^= Int64Field112.GetHashCode(); + if (doubleField113_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField113); + if (int64Field114_ != null) hash ^= Int64Field114.GetHashCode(); + if (doubleField42_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField42); + if (int64Field43_ != null) hash ^= Int64Field43.GetHashCode(); + if (int64Field44_ != null) hash ^= Int64Field44.GetHashCode(); + if (doubleField45_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField45); + if (doubleField46_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField46); + if (doubleField78_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField78); + if (doubleField88_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField88); + if (doubleField47_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField47); + if (doubleField89_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField89); + if (doubleField48_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField48); + if (doubleField49_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField49); + if (doubleField50_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField50); + if (doubleField90_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField90); + if (doubleField51_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField51); + if (doubleField91_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField91); + if (doubleField92_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField92); + if (int64Field107_ != null) hash ^= Int64Field107.GetHashCode(); + if (doubleField93_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField93); + if (doubleField108_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField108); + if (doubleField52_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField52); + if (doubleField53_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField53); + if (doubleField94_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField94); + if (doubleField54_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField54); + if (doubleField55_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField55); + if (doubleField56_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField56); + if (doubleField57_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField57); + if (doubleField58_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField58); + if (int64Field59_ != null) hash ^= Int64Field59.GetHashCode(); + if (int64Field60_ != null) hash ^= Int64Field60.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (doubleField1_ != null) { + _single_doubleField1_codec.WriteTagAndValue(output, DoubleField1); + } + if (int64Field2_ != null) { + _single_int64Field2_codec.WriteTagAndValue(output, Int64Field2); + } + if (int64Field3_ != null) { + _single_int64Field3_codec.WriteTagAndValue(output, Int64Field3); + } + if (int64Field4_ != null) { + _single_int64Field4_codec.WriteTagAndValue(output, Int64Field4); + } + if (doubleField7_ != null) { + _single_doubleField7_codec.WriteTagAndValue(output, DoubleField7); + } + if (doubleField8_ != null) { + _single_doubleField8_codec.WriteTagAndValue(output, DoubleField8); + } + if (doubleField9_ != null) { + _single_doubleField9_codec.WriteTagAndValue(output, DoubleField9); + } + if (doubleField10_ != null) { + _single_doubleField10_codec.WriteTagAndValue(output, DoubleField10); + } + if (doubleField11_ != null) { + _single_doubleField11_codec.WriteTagAndValue(output, DoubleField11); + } + if (doubleField14_ != null) { + _single_doubleField14_codec.WriteTagAndValue(output, DoubleField14); + } + if (doubleField15_ != null) { + _single_doubleField15_codec.WriteTagAndValue(output, DoubleField15); + } + if (int64Field19_ != null) { + _single_int64Field19_codec.WriteTagAndValue(output, Int64Field19); + } + if (doubleField20_ != null) { + _single_doubleField20_codec.WriteTagAndValue(output, DoubleField20); + } + if (doubleField21_ != null) { + _single_doubleField21_codec.WriteTagAndValue(output, DoubleField21); + } + if (doubleField22_ != null) { + _single_doubleField22_codec.WriteTagAndValue(output, DoubleField22); + } + if (doubleField25_ != null) { + _single_doubleField25_codec.WriteTagAndValue(output, DoubleField25); + } + if (int64Field26_ != null) { + _single_int64Field26_codec.WriteTagAndValue(output, Int64Field26); + } + if (doubleField28_ != null) { + _single_doubleField28_codec.WriteTagAndValue(output, DoubleField28); + } + if (doubleField29_ != null) { + _single_doubleField29_codec.WriteTagAndValue(output, DoubleField29); + } + if (doubleField30_ != null) { + _single_doubleField30_codec.WriteTagAndValue(output, DoubleField30); + } + if (doubleField31_ != null) { + _single_doubleField31_codec.WriteTagAndValue(output, DoubleField31); + } + if (int64Field32_ != null) { + _single_int64Field32_codec.WriteTagAndValue(output, Int64Field32); + } + if (int64Field37_ != null) { + _single_int64Field37_codec.WriteTagAndValue(output, Int64Field37); + } + if (doubleField38_ != null) { + _single_doubleField38_codec.WriteTagAndValue(output, DoubleField38); + } + if (interactions_ != null) { + _single_interactions_codec.WriteTagAndValue(output, Interactions); + } + if (doubleField40_ != null) { + _single_doubleField40_codec.WriteTagAndValue(output, DoubleField40); + } + if (int64Field41_ != null) { + _single_int64Field41_codec.WriteTagAndValue(output, Int64Field41); + } + if (doubleField42_ != null) { + _single_doubleField42_codec.WriteTagAndValue(output, DoubleField42); + } + if (int64Field43_ != null) { + _single_int64Field43_codec.WriteTagAndValue(output, Int64Field43); + } + if (int64Field44_ != null) { + _single_int64Field44_codec.WriteTagAndValue(output, Int64Field44); + } + if (doubleField45_ != null) { + _single_doubleField45_codec.WriteTagAndValue(output, DoubleField45); + } + if (doubleField46_ != null) { + _single_doubleField46_codec.WriteTagAndValue(output, DoubleField46); + } + if (doubleField47_ != null) { + _single_doubleField47_codec.WriteTagAndValue(output, DoubleField47); + } + if (doubleField48_ != null) { + _single_doubleField48_codec.WriteTagAndValue(output, DoubleField48); + } + if (doubleField49_ != null) { + _single_doubleField49_codec.WriteTagAndValue(output, DoubleField49); + } + if (doubleField50_ != null) { + _single_doubleField50_codec.WriteTagAndValue(output, DoubleField50); + } + if (doubleField51_ != null) { + _single_doubleField51_codec.WriteTagAndValue(output, DoubleField51); + } + if (doubleField52_ != null) { + _single_doubleField52_codec.WriteTagAndValue(output, DoubleField52); + } + if (doubleField53_ != null) { + _single_doubleField53_codec.WriteTagAndValue(output, DoubleField53); + } + if (doubleField54_ != null) { + _single_doubleField54_codec.WriteTagAndValue(output, DoubleField54); + } + if (doubleField55_ != null) { + _single_doubleField55_codec.WriteTagAndValue(output, DoubleField55); + } + if (doubleField56_ != null) { + _single_doubleField56_codec.WriteTagAndValue(output, DoubleField56); + } + if (doubleField57_ != null) { + _single_doubleField57_codec.WriteTagAndValue(output, DoubleField57); + } + if (doubleField58_ != null) { + _single_doubleField58_codec.WriteTagAndValue(output, DoubleField58); + } + if (int64Field59_ != null) { + _single_int64Field59_codec.WriteTagAndValue(output, Int64Field59); + } + if (int64Field60_ != null) { + _single_int64Field60_codec.WriteTagAndValue(output, Int64Field60); + } + if (doubleField62_ != null) { + _single_doubleField62_codec.WriteTagAndValue(output, DoubleField62); + } + if (doubleField65_ != null) { + _single_doubleField65_codec.WriteTagAndValue(output, DoubleField65); + } + if (doubleField66_ != null) { + _single_doubleField66_codec.WriteTagAndValue(output, DoubleField66); + } + if (doubleField67_ != null) { + _single_doubleField67_codec.WriteTagAndValue(output, DoubleField67); + } + if (doubleField68_ != null) { + _single_doubleField68_codec.WriteTagAndValue(output, DoubleField68); + } + if (doubleField69_ != null) { + _single_doubleField69_codec.WriteTagAndValue(output, DoubleField69); + } + if (doubleField70_ != null) { + _single_doubleField70_codec.WriteTagAndValue(output, DoubleField70); + } + if (doubleField71_ != null) { + _single_doubleField71_codec.WriteTagAndValue(output, DoubleField71); + } + if (doubleField72_ != null) { + _single_doubleField72_codec.WriteTagAndValue(output, DoubleField72); + } + if (stringField73_ != null) { + _single_stringField73_codec.WriteTagAndValue(output, StringField73); + } + if (stringField74_ != null) { + _single_stringField74_codec.WriteTagAndValue(output, StringField74); + } + if (doubleField75_ != null) { + _single_doubleField75_codec.WriteTagAndValue(output, DoubleField75); + } + if (doubleField77_ != null) { + _single_doubleField77_codec.WriteTagAndValue(output, DoubleField77); + } + if (doubleField78_ != null) { + _single_doubleField78_codec.WriteTagAndValue(output, DoubleField78); + } + if (doubleField79_ != null) { + _single_doubleField79_codec.WriteTagAndValue(output, DoubleField79); + } + if (EnumField80 != 0) { + output.WriteRawTag(128, 5); + output.WriteInt32(EnumField80); + } + if (EnumField81 != 0) { + output.WriteRawTag(136, 5); + output.WriteInt32(EnumField81); + } + if (int64Field82_ != null) { + _single_int64Field82_codec.WriteTagAndValue(output, Int64Field82); + } + if (EnumField83 != 0) { + output.WriteRawTag(152, 5); + output.WriteInt32(EnumField83); + } + if (doubleField84_ != null) { + _single_doubleField84_codec.WriteTagAndValue(output, DoubleField84); + } + if (int64Field85_ != null) { + _single_int64Field85_codec.WriteTagAndValue(output, Int64Field85); + } + if (int64Field86_ != null) { + _single_int64Field86_codec.WriteTagAndValue(output, Int64Field86); + } + if (int64Field87_ != null) { + _single_int64Field87_codec.WriteTagAndValue(output, Int64Field87); + } + if (doubleField88_ != null) { + _single_doubleField88_codec.WriteTagAndValue(output, DoubleField88); + } + if (doubleField89_ != null) { + _single_doubleField89_codec.WriteTagAndValue(output, DoubleField89); + } + if (doubleField90_ != null) { + _single_doubleField90_codec.WriteTagAndValue(output, DoubleField90); + } + if (doubleField91_ != null) { + _single_doubleField91_codec.WriteTagAndValue(output, DoubleField91); + } + if (doubleField92_ != null) { + _single_doubleField92_codec.WriteTagAndValue(output, DoubleField92); + } + if (doubleField93_ != null) { + _single_doubleField93_codec.WriteTagAndValue(output, DoubleField93); + } + if (doubleField94_ != null) { + _single_doubleField94_codec.WriteTagAndValue(output, DoubleField94); + } + if (doubleField95_ != null) { + _single_doubleField95_codec.WriteTagAndValue(output, DoubleField95); + } + if (doubleField96_ != null) { + _single_doubleField96_codec.WriteTagAndValue(output, DoubleField96); + } + if (doubleField97_ != null) { + _single_doubleField97_codec.WriteTagAndValue(output, DoubleField97); + } + if (doubleField98_ != null) { + _single_doubleField98_codec.WriteTagAndValue(output, DoubleField98); + } + if (doubleField99_ != null) { + _single_doubleField99_codec.WriteTagAndValue(output, DoubleField99); + } + repeatedIntField100_.WriteTo(output, _repeated_repeatedIntField100_codec); + if (doubleField101_ != null) { + _single_doubleField101_codec.WriteTagAndValue(output, DoubleField101); + } + if (doubleField102_ != null) { + _single_doubleField102_codec.WriteTagAndValue(output, DoubleField102); + } + if (doubleField103_ != null) { + _single_doubleField103_codec.WriteTagAndValue(output, DoubleField103); + } + if (doubleField104_ != null) { + _single_doubleField104_codec.WriteTagAndValue(output, DoubleField104); + } + if (doubleField105_ != null) { + _single_doubleField105_codec.WriteTagAndValue(output, DoubleField105); + } + if (doubleField106_ != null) { + _single_doubleField106_codec.WriteTagAndValue(output, DoubleField106); + } + if (int64Field107_ != null) { + _single_int64Field107_codec.WriteTagAndValue(output, Int64Field107); + } + if (doubleField108_ != null) { + _single_doubleField108_codec.WriteTagAndValue(output, DoubleField108); + } + if (doubleField109_ != null) { + _single_doubleField109_codec.WriteTagAndValue(output, DoubleField109); + } + if (int64Field110_ != null) { + _single_int64Field110_codec.WriteTagAndValue(output, Int64Field110); + } + if (doubleField111_ != null) { + _single_doubleField111_codec.WriteTagAndValue(output, DoubleField111); + } + if (int64Field112_ != null) { + _single_int64Field112_codec.WriteTagAndValue(output, Int64Field112); + } + if (doubleField113_ != null) { + _single_doubleField113_codec.WriteTagAndValue(output, DoubleField113); + } + if (int64Field114_ != null) { + _single_int64Field114_codec.WriteTagAndValue(output, Int64Field114); + } + if (int64Field115_ != null) { + _single_int64Field115_codec.WriteTagAndValue(output, Int64Field115); + } + if (doubleField116_ != null) { + _single_doubleField116_codec.WriteTagAndValue(output, DoubleField116); + } + if (int64Field117_ != null) { + _single_int64Field117_codec.WriteTagAndValue(output, Int64Field117); + } + if (doubleField118_ != null) { + _single_doubleField118_codec.WriteTagAndValue(output, DoubleField118); + } + if (doubleField119_ != null) { + _single_doubleField119_codec.WriteTagAndValue(output, DoubleField119); + } + if (doubleField120_ != null) { + _single_doubleField120_codec.WriteTagAndValue(output, DoubleField120); + } + if (doubleField121_ != null) { + _single_doubleField121_codec.WriteTagAndValue(output, DoubleField121); + } + if (doubleField122_ != null) { + _single_doubleField122_codec.WriteTagAndValue(output, DoubleField122); + } + if (doubleField123_ != null) { + _single_doubleField123_codec.WriteTagAndValue(output, DoubleField123); + } + if (doubleField124_ != null) { + _single_doubleField124_codec.WriteTagAndValue(output, DoubleField124); + } + if (int64Field125_ != null) { + _single_int64Field125_codec.WriteTagAndValue(output, Int64Field125); + } + if (int64Field126_ != null) { + _single_int64Field126_codec.WriteTagAndValue(output, Int64Field126); + } + if (int64Field127_ != null) { + _single_int64Field127_codec.WriteTagAndValue(output, Int64Field127); + } + if (doubleField128_ != null) { + _single_doubleField128_codec.WriteTagAndValue(output, DoubleField128); + } + if (doubleField129_ != null) { + _single_doubleField129_codec.WriteTagAndValue(output, DoubleField129); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (doubleField1_ != null) { + _single_doubleField1_codec.WriteTagAndValue(ref output, DoubleField1); + } + if (int64Field2_ != null) { + _single_int64Field2_codec.WriteTagAndValue(ref output, Int64Field2); + } + if (int64Field3_ != null) { + _single_int64Field3_codec.WriteTagAndValue(ref output, Int64Field3); + } + if (int64Field4_ != null) { + _single_int64Field4_codec.WriteTagAndValue(ref output, Int64Field4); + } + if (doubleField7_ != null) { + _single_doubleField7_codec.WriteTagAndValue(ref output, DoubleField7); + } + if (doubleField8_ != null) { + _single_doubleField8_codec.WriteTagAndValue(ref output, DoubleField8); + } + if (doubleField9_ != null) { + _single_doubleField9_codec.WriteTagAndValue(ref output, DoubleField9); + } + if (doubleField10_ != null) { + _single_doubleField10_codec.WriteTagAndValue(ref output, DoubleField10); + } + if (doubleField11_ != null) { + _single_doubleField11_codec.WriteTagAndValue(ref output, DoubleField11); + } + if (doubleField14_ != null) { + _single_doubleField14_codec.WriteTagAndValue(ref output, DoubleField14); + } + if (doubleField15_ != null) { + _single_doubleField15_codec.WriteTagAndValue(ref output, DoubleField15); + } + if (int64Field19_ != null) { + _single_int64Field19_codec.WriteTagAndValue(ref output, Int64Field19); + } + if (doubleField20_ != null) { + _single_doubleField20_codec.WriteTagAndValue(ref output, DoubleField20); + } + if (doubleField21_ != null) { + _single_doubleField21_codec.WriteTagAndValue(ref output, DoubleField21); + } + if (doubleField22_ != null) { + _single_doubleField22_codec.WriteTagAndValue(ref output, DoubleField22); + } + if (doubleField25_ != null) { + _single_doubleField25_codec.WriteTagAndValue(ref output, DoubleField25); + } + if (int64Field26_ != null) { + _single_int64Field26_codec.WriteTagAndValue(ref output, Int64Field26); + } + if (doubleField28_ != null) { + _single_doubleField28_codec.WriteTagAndValue(ref output, DoubleField28); + } + if (doubleField29_ != null) { + _single_doubleField29_codec.WriteTagAndValue(ref output, DoubleField29); + } + if (doubleField30_ != null) { + _single_doubleField30_codec.WriteTagAndValue(ref output, DoubleField30); + } + if (doubleField31_ != null) { + _single_doubleField31_codec.WriteTagAndValue(ref output, DoubleField31); + } + if (int64Field32_ != null) { + _single_int64Field32_codec.WriteTagAndValue(ref output, Int64Field32); + } + if (int64Field37_ != null) { + _single_int64Field37_codec.WriteTagAndValue(ref output, Int64Field37); + } + if (doubleField38_ != null) { + _single_doubleField38_codec.WriteTagAndValue(ref output, DoubleField38); + } + if (interactions_ != null) { + _single_interactions_codec.WriteTagAndValue(ref output, Interactions); + } + if (doubleField40_ != null) { + _single_doubleField40_codec.WriteTagAndValue(ref output, DoubleField40); + } + if (int64Field41_ != null) { + _single_int64Field41_codec.WriteTagAndValue(ref output, Int64Field41); + } + if (doubleField42_ != null) { + _single_doubleField42_codec.WriteTagAndValue(ref output, DoubleField42); + } + if (int64Field43_ != null) { + _single_int64Field43_codec.WriteTagAndValue(ref output, Int64Field43); + } + if (int64Field44_ != null) { + _single_int64Field44_codec.WriteTagAndValue(ref output, Int64Field44); + } + if (doubleField45_ != null) { + _single_doubleField45_codec.WriteTagAndValue(ref output, DoubleField45); + } + if (doubleField46_ != null) { + _single_doubleField46_codec.WriteTagAndValue(ref output, DoubleField46); + } + if (doubleField47_ != null) { + _single_doubleField47_codec.WriteTagAndValue(ref output, DoubleField47); + } + if (doubleField48_ != null) { + _single_doubleField48_codec.WriteTagAndValue(ref output, DoubleField48); + } + if (doubleField49_ != null) { + _single_doubleField49_codec.WriteTagAndValue(ref output, DoubleField49); + } + if (doubleField50_ != null) { + _single_doubleField50_codec.WriteTagAndValue(ref output, DoubleField50); + } + if (doubleField51_ != null) { + _single_doubleField51_codec.WriteTagAndValue(ref output, DoubleField51); + } + if (doubleField52_ != null) { + _single_doubleField52_codec.WriteTagAndValue(ref output, DoubleField52); + } + if (doubleField53_ != null) { + _single_doubleField53_codec.WriteTagAndValue(ref output, DoubleField53); + } + if (doubleField54_ != null) { + _single_doubleField54_codec.WriteTagAndValue(ref output, DoubleField54); + } + if (doubleField55_ != null) { + _single_doubleField55_codec.WriteTagAndValue(ref output, DoubleField55); + } + if (doubleField56_ != null) { + _single_doubleField56_codec.WriteTagAndValue(ref output, DoubleField56); + } + if (doubleField57_ != null) { + _single_doubleField57_codec.WriteTagAndValue(ref output, DoubleField57); + } + if (doubleField58_ != null) { + _single_doubleField58_codec.WriteTagAndValue(ref output, DoubleField58); + } + if (int64Field59_ != null) { + _single_int64Field59_codec.WriteTagAndValue(ref output, Int64Field59); + } + if (int64Field60_ != null) { + _single_int64Field60_codec.WriteTagAndValue(ref output, Int64Field60); + } + if (doubleField62_ != null) { + _single_doubleField62_codec.WriteTagAndValue(ref output, DoubleField62); + } + if (doubleField65_ != null) { + _single_doubleField65_codec.WriteTagAndValue(ref output, DoubleField65); + } + if (doubleField66_ != null) { + _single_doubleField66_codec.WriteTagAndValue(ref output, DoubleField66); + } + if (doubleField67_ != null) { + _single_doubleField67_codec.WriteTagAndValue(ref output, DoubleField67); + } + if (doubleField68_ != null) { + _single_doubleField68_codec.WriteTagAndValue(ref output, DoubleField68); + } + if (doubleField69_ != null) { + _single_doubleField69_codec.WriteTagAndValue(ref output, DoubleField69); + } + if (doubleField70_ != null) { + _single_doubleField70_codec.WriteTagAndValue(ref output, DoubleField70); + } + if (doubleField71_ != null) { + _single_doubleField71_codec.WriteTagAndValue(ref output, DoubleField71); + } + if (doubleField72_ != null) { + _single_doubleField72_codec.WriteTagAndValue(ref output, DoubleField72); + } + if (stringField73_ != null) { + _single_stringField73_codec.WriteTagAndValue(ref output, StringField73); + } + if (stringField74_ != null) { + _single_stringField74_codec.WriteTagAndValue(ref output, StringField74); + } + if (doubleField75_ != null) { + _single_doubleField75_codec.WriteTagAndValue(ref output, DoubleField75); + } + if (doubleField77_ != null) { + _single_doubleField77_codec.WriteTagAndValue(ref output, DoubleField77); + } + if (doubleField78_ != null) { + _single_doubleField78_codec.WriteTagAndValue(ref output, DoubleField78); + } + if (doubleField79_ != null) { + _single_doubleField79_codec.WriteTagAndValue(ref output, DoubleField79); + } + if (EnumField80 != 0) { + output.WriteRawTag(128, 5); + output.WriteInt32(EnumField80); + } + if (EnumField81 != 0) { + output.WriteRawTag(136, 5); + output.WriteInt32(EnumField81); + } + if (int64Field82_ != null) { + _single_int64Field82_codec.WriteTagAndValue(ref output, Int64Field82); + } + if (EnumField83 != 0) { + output.WriteRawTag(152, 5); + output.WriteInt32(EnumField83); + } + if (doubleField84_ != null) { + _single_doubleField84_codec.WriteTagAndValue(ref output, DoubleField84); + } + if (int64Field85_ != null) { + _single_int64Field85_codec.WriteTagAndValue(ref output, Int64Field85); + } + if (int64Field86_ != null) { + _single_int64Field86_codec.WriteTagAndValue(ref output, Int64Field86); + } + if (int64Field87_ != null) { + _single_int64Field87_codec.WriteTagAndValue(ref output, Int64Field87); + } + if (doubleField88_ != null) { + _single_doubleField88_codec.WriteTagAndValue(ref output, DoubleField88); + } + if (doubleField89_ != null) { + _single_doubleField89_codec.WriteTagAndValue(ref output, DoubleField89); + } + if (doubleField90_ != null) { + _single_doubleField90_codec.WriteTagAndValue(ref output, DoubleField90); + } + if (doubleField91_ != null) { + _single_doubleField91_codec.WriteTagAndValue(ref output, DoubleField91); + } + if (doubleField92_ != null) { + _single_doubleField92_codec.WriteTagAndValue(ref output, DoubleField92); + } + if (doubleField93_ != null) { + _single_doubleField93_codec.WriteTagAndValue(ref output, DoubleField93); + } + if (doubleField94_ != null) { + _single_doubleField94_codec.WriteTagAndValue(ref output, DoubleField94); + } + if (doubleField95_ != null) { + _single_doubleField95_codec.WriteTagAndValue(ref output, DoubleField95); + } + if (doubleField96_ != null) { + _single_doubleField96_codec.WriteTagAndValue(ref output, DoubleField96); + } + if (doubleField97_ != null) { + _single_doubleField97_codec.WriteTagAndValue(ref output, DoubleField97); + } + if (doubleField98_ != null) { + _single_doubleField98_codec.WriteTagAndValue(ref output, DoubleField98); + } + if (doubleField99_ != null) { + _single_doubleField99_codec.WriteTagAndValue(ref output, DoubleField99); + } + repeatedIntField100_.WriteTo(ref output, _repeated_repeatedIntField100_codec); + if (doubleField101_ != null) { + _single_doubleField101_codec.WriteTagAndValue(ref output, DoubleField101); + } + if (doubleField102_ != null) { + _single_doubleField102_codec.WriteTagAndValue(ref output, DoubleField102); + } + if (doubleField103_ != null) { + _single_doubleField103_codec.WriteTagAndValue(ref output, DoubleField103); + } + if (doubleField104_ != null) { + _single_doubleField104_codec.WriteTagAndValue(ref output, DoubleField104); + } + if (doubleField105_ != null) { + _single_doubleField105_codec.WriteTagAndValue(ref output, DoubleField105); + } + if (doubleField106_ != null) { + _single_doubleField106_codec.WriteTagAndValue(ref output, DoubleField106); + } + if (int64Field107_ != null) { + _single_int64Field107_codec.WriteTagAndValue(ref output, Int64Field107); + } + if (doubleField108_ != null) { + _single_doubleField108_codec.WriteTagAndValue(ref output, DoubleField108); + } + if (doubleField109_ != null) { + _single_doubleField109_codec.WriteTagAndValue(ref output, DoubleField109); + } + if (int64Field110_ != null) { + _single_int64Field110_codec.WriteTagAndValue(ref output, Int64Field110); + } + if (doubleField111_ != null) { + _single_doubleField111_codec.WriteTagAndValue(ref output, DoubleField111); + } + if (int64Field112_ != null) { + _single_int64Field112_codec.WriteTagAndValue(ref output, Int64Field112); + } + if (doubleField113_ != null) { + _single_doubleField113_codec.WriteTagAndValue(ref output, DoubleField113); + } + if (int64Field114_ != null) { + _single_int64Field114_codec.WriteTagAndValue(ref output, Int64Field114); + } + if (int64Field115_ != null) { + _single_int64Field115_codec.WriteTagAndValue(ref output, Int64Field115); + } + if (doubleField116_ != null) { + _single_doubleField116_codec.WriteTagAndValue(ref output, DoubleField116); + } + if (int64Field117_ != null) { + _single_int64Field117_codec.WriteTagAndValue(ref output, Int64Field117); + } + if (doubleField118_ != null) { + _single_doubleField118_codec.WriteTagAndValue(ref output, DoubleField118); + } + if (doubleField119_ != null) { + _single_doubleField119_codec.WriteTagAndValue(ref output, DoubleField119); + } + if (doubleField120_ != null) { + _single_doubleField120_codec.WriteTagAndValue(ref output, DoubleField120); + } + if (doubleField121_ != null) { + _single_doubleField121_codec.WriteTagAndValue(ref output, DoubleField121); + } + if (doubleField122_ != null) { + _single_doubleField122_codec.WriteTagAndValue(ref output, DoubleField122); + } + if (doubleField123_ != null) { + _single_doubleField123_codec.WriteTagAndValue(ref output, DoubleField123); + } + if (doubleField124_ != null) { + _single_doubleField124_codec.WriteTagAndValue(ref output, DoubleField124); + } + if (int64Field125_ != null) { + _single_int64Field125_codec.WriteTagAndValue(ref output, Int64Field125); + } + if (int64Field126_ != null) { + _single_int64Field126_codec.WriteTagAndValue(ref output, Int64Field126); + } + if (int64Field127_ != null) { + _single_int64Field127_codec.WriteTagAndValue(ref output, Int64Field127); + } + if (doubleField128_ != null) { + _single_doubleField128_codec.WriteTagAndValue(ref output, DoubleField128); + } + if (doubleField129_ != null) { + _single_doubleField129_codec.WriteTagAndValue(ref output, DoubleField129); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (doubleField95_ != null) { + size += _single_doubleField95_codec.CalculateSizeWithTag(DoubleField95); + } + if (doubleField1_ != null) { + size += _single_doubleField1_codec.CalculateSizeWithTag(DoubleField1); + } + if (doubleField79_ != null) { + size += _single_doubleField79_codec.CalculateSizeWithTag(DoubleField79); + } + if (int64Field2_ != null) { + size += _single_int64Field2_codec.CalculateSizeWithTag(Int64Field2); + } + if (doubleField96_ != null) { + size += _single_doubleField96_codec.CalculateSizeWithTag(DoubleField96); + } + if (int64Field3_ != null) { + size += _single_int64Field3_codec.CalculateSizeWithTag(Int64Field3); + } + if (int64Field4_ != null) { + size += _single_int64Field4_codec.CalculateSizeWithTag(Int64Field4); + } + if (doubleField97_ != null) { + size += _single_doubleField97_codec.CalculateSizeWithTag(DoubleField97); + } + if (doubleField65_ != null) { + size += _single_doubleField65_codec.CalculateSizeWithTag(DoubleField65); + } + if (doubleField66_ != null) { + size += _single_doubleField66_codec.CalculateSizeWithTag(DoubleField66); + } + if (doubleField7_ != null) { + size += _single_doubleField7_codec.CalculateSizeWithTag(DoubleField7); + } + if (doubleField62_ != null) { + size += _single_doubleField62_codec.CalculateSizeWithTag(DoubleField62); + } + if (doubleField118_ != null) { + size += _single_doubleField118_codec.CalculateSizeWithTag(DoubleField118); + } + if (doubleField119_ != null) { + size += _single_doubleField119_codec.CalculateSizeWithTag(DoubleField119); + } + if (doubleField67_ != null) { + size += _single_doubleField67_codec.CalculateSizeWithTag(DoubleField67); + } + if (doubleField120_ != null) { + size += _single_doubleField120_codec.CalculateSizeWithTag(DoubleField120); + } + if (doubleField121_ != null) { + size += _single_doubleField121_codec.CalculateSizeWithTag(DoubleField121); + } + if (doubleField122_ != null) { + size += _single_doubleField122_codec.CalculateSizeWithTag(DoubleField122); + } + if (doubleField123_ != null) { + size += _single_doubleField123_codec.CalculateSizeWithTag(DoubleField123); + } + if (doubleField124_ != null) { + size += _single_doubleField124_codec.CalculateSizeWithTag(DoubleField124); + } + if (doubleField8_ != null) { + size += _single_doubleField8_codec.CalculateSizeWithTag(DoubleField8); + } + if (doubleField9_ != null) { + size += _single_doubleField9_codec.CalculateSizeWithTag(DoubleField9); + } + if (doubleField98_ != null) { + size += _single_doubleField98_codec.CalculateSizeWithTag(DoubleField98); + } + if (doubleField10_ != null) { + size += _single_doubleField10_codec.CalculateSizeWithTag(DoubleField10); + } + if (doubleField11_ != null) { + size += _single_doubleField11_codec.CalculateSizeWithTag(DoubleField11); + } + if (doubleField99_ != null) { + size += _single_doubleField99_codec.CalculateSizeWithTag(DoubleField99); + } + if (doubleField84_ != null) { + size += _single_doubleField84_codec.CalculateSizeWithTag(DoubleField84); + } + if (doubleField14_ != null) { + size += _single_doubleField14_codec.CalculateSizeWithTag(DoubleField14); + } + if (doubleField77_ != null) { + size += _single_doubleField77_codec.CalculateSizeWithTag(DoubleField77); + } + if (doubleField15_ != null) { + size += _single_doubleField15_codec.CalculateSizeWithTag(DoubleField15); + } + if (int64Field19_ != null) { + size += _single_int64Field19_codec.CalculateSizeWithTag(Int64Field19); + } + if (int64Field115_ != null) { + size += _single_int64Field115_codec.CalculateSizeWithTag(Int64Field115); + } + if (doubleField116_ != null) { + size += _single_doubleField116_codec.CalculateSizeWithTag(DoubleField116); + } + if (int64Field117_ != null) { + size += _single_int64Field117_codec.CalculateSizeWithTag(Int64Field117); + } + if (doubleField20_ != null) { + size += _single_doubleField20_codec.CalculateSizeWithTag(DoubleField20); + } + if (doubleField21_ != null) { + size += _single_doubleField21_codec.CalculateSizeWithTag(DoubleField21); + } + if (stringField73_ != null) { + size += _single_stringField73_codec.CalculateSizeWithTag(StringField73); + } + if (stringField74_ != null) { + size += _single_stringField74_codec.CalculateSizeWithTag(StringField74); + } + if (doubleField22_ != null) { + size += _single_doubleField22_codec.CalculateSizeWithTag(DoubleField22); + } + if (doubleField69_ != null) { + size += _single_doubleField69_codec.CalculateSizeWithTag(DoubleField69); + } + if (doubleField70_ != null) { + size += _single_doubleField70_codec.CalculateSizeWithTag(DoubleField70); + } + if (doubleField71_ != null) { + size += _single_doubleField71_codec.CalculateSizeWithTag(DoubleField71); + } + if (doubleField72_ != null) { + size += _single_doubleField72_codec.CalculateSizeWithTag(DoubleField72); + } + if (doubleField25_ != null) { + size += _single_doubleField25_codec.CalculateSizeWithTag(DoubleField25); + } + if (int64Field26_ != null) { + size += _single_int64Field26_codec.CalculateSizeWithTag(Int64Field26); + } + if (doubleField68_ != null) { + size += _single_doubleField68_codec.CalculateSizeWithTag(DoubleField68); + } + if (doubleField28_ != null) { + size += _single_doubleField28_codec.CalculateSizeWithTag(DoubleField28); + } + if (doubleField106_ != null) { + size += _single_doubleField106_codec.CalculateSizeWithTag(DoubleField106); + } + if (doubleField29_ != null) { + size += _single_doubleField29_codec.CalculateSizeWithTag(DoubleField29); + } + if (doubleField30_ != null) { + size += _single_doubleField30_codec.CalculateSizeWithTag(DoubleField30); + } + if (doubleField101_ != null) { + size += _single_doubleField101_codec.CalculateSizeWithTag(DoubleField101); + } + if (doubleField102_ != null) { + size += _single_doubleField102_codec.CalculateSizeWithTag(DoubleField102); + } + if (doubleField103_ != null) { + size += _single_doubleField103_codec.CalculateSizeWithTag(DoubleField103); + } + if (doubleField104_ != null) { + size += _single_doubleField104_codec.CalculateSizeWithTag(DoubleField104); + } + if (doubleField105_ != null) { + size += _single_doubleField105_codec.CalculateSizeWithTag(DoubleField105); + } + if (doubleField31_ != null) { + size += _single_doubleField31_codec.CalculateSizeWithTag(DoubleField31); + } + if (int64Field32_ != null) { + size += _single_int64Field32_codec.CalculateSizeWithTag(Int64Field32); + } + if (doubleField75_ != null) { + size += _single_doubleField75_codec.CalculateSizeWithTag(DoubleField75); + } + if (doubleField129_ != null) { + size += _single_doubleField129_codec.CalculateSizeWithTag(DoubleField129); + } + if (EnumField80 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(EnumField80); + } + if (EnumField81 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(EnumField81); + } + if (int64Field82_ != null) { + size += _single_int64Field82_codec.CalculateSizeWithTag(Int64Field82); + } + if (EnumField83 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(EnumField83); + } + if (int64Field85_ != null) { + size += _single_int64Field85_codec.CalculateSizeWithTag(Int64Field85); + } + if (int64Field86_ != null) { + size += _single_int64Field86_codec.CalculateSizeWithTag(Int64Field86); + } + if (int64Field87_ != null) { + size += _single_int64Field87_codec.CalculateSizeWithTag(Int64Field87); + } + if (int64Field125_ != null) { + size += _single_int64Field125_codec.CalculateSizeWithTag(Int64Field125); + } + if (int64Field37_ != null) { + size += _single_int64Field37_codec.CalculateSizeWithTag(Int64Field37); + } + if (doubleField38_ != null) { + size += _single_doubleField38_codec.CalculateSizeWithTag(DoubleField38); + } + if (interactions_ != null) { + size += _single_interactions_codec.CalculateSizeWithTag(Interactions); + } + size += repeatedIntField100_.CalculateSize(_repeated_repeatedIntField100_codec); + if (doubleField40_ != null) { + size += _single_doubleField40_codec.CalculateSizeWithTag(DoubleField40); + } + if (int64Field41_ != null) { + size += _single_int64Field41_codec.CalculateSizeWithTag(Int64Field41); + } + if (int64Field126_ != null) { + size += _single_int64Field126_codec.CalculateSizeWithTag(Int64Field126); + } + if (int64Field127_ != null) { + size += _single_int64Field127_codec.CalculateSizeWithTag(Int64Field127); + } + if (doubleField128_ != null) { + size += _single_doubleField128_codec.CalculateSizeWithTag(DoubleField128); + } + if (doubleField109_ != null) { + size += _single_doubleField109_codec.CalculateSizeWithTag(DoubleField109); + } + if (int64Field110_ != null) { + size += _single_int64Field110_codec.CalculateSizeWithTag(Int64Field110); + } + if (doubleField111_ != null) { + size += _single_doubleField111_codec.CalculateSizeWithTag(DoubleField111); + } + if (int64Field112_ != null) { + size += _single_int64Field112_codec.CalculateSizeWithTag(Int64Field112); + } + if (doubleField113_ != null) { + size += _single_doubleField113_codec.CalculateSizeWithTag(DoubleField113); + } + if (int64Field114_ != null) { + size += _single_int64Field114_codec.CalculateSizeWithTag(Int64Field114); + } + if (doubleField42_ != null) { + size += _single_doubleField42_codec.CalculateSizeWithTag(DoubleField42); + } + if (int64Field43_ != null) { + size += _single_int64Field43_codec.CalculateSizeWithTag(Int64Field43); + } + if (int64Field44_ != null) { + size += _single_int64Field44_codec.CalculateSizeWithTag(Int64Field44); + } + if (doubleField45_ != null) { + size += _single_doubleField45_codec.CalculateSizeWithTag(DoubleField45); + } + if (doubleField46_ != null) { + size += _single_doubleField46_codec.CalculateSizeWithTag(DoubleField46); + } + if (doubleField78_ != null) { + size += _single_doubleField78_codec.CalculateSizeWithTag(DoubleField78); + } + if (doubleField88_ != null) { + size += _single_doubleField88_codec.CalculateSizeWithTag(DoubleField88); + } + if (doubleField47_ != null) { + size += _single_doubleField47_codec.CalculateSizeWithTag(DoubleField47); + } + if (doubleField89_ != null) { + size += _single_doubleField89_codec.CalculateSizeWithTag(DoubleField89); + } + if (doubleField48_ != null) { + size += _single_doubleField48_codec.CalculateSizeWithTag(DoubleField48); + } + if (doubleField49_ != null) { + size += _single_doubleField49_codec.CalculateSizeWithTag(DoubleField49); + } + if (doubleField50_ != null) { + size += _single_doubleField50_codec.CalculateSizeWithTag(DoubleField50); + } + if (doubleField90_ != null) { + size += _single_doubleField90_codec.CalculateSizeWithTag(DoubleField90); + } + if (doubleField51_ != null) { + size += _single_doubleField51_codec.CalculateSizeWithTag(DoubleField51); + } + if (doubleField91_ != null) { + size += _single_doubleField91_codec.CalculateSizeWithTag(DoubleField91); + } + if (doubleField92_ != null) { + size += _single_doubleField92_codec.CalculateSizeWithTag(DoubleField92); + } + if (int64Field107_ != null) { + size += _single_int64Field107_codec.CalculateSizeWithTag(Int64Field107); + } + if (doubleField93_ != null) { + size += _single_doubleField93_codec.CalculateSizeWithTag(DoubleField93); + } + if (doubleField108_ != null) { + size += _single_doubleField108_codec.CalculateSizeWithTag(DoubleField108); + } + if (doubleField52_ != null) { + size += _single_doubleField52_codec.CalculateSizeWithTag(DoubleField52); + } + if (doubleField53_ != null) { + size += _single_doubleField53_codec.CalculateSizeWithTag(DoubleField53); + } + if (doubleField94_ != null) { + size += _single_doubleField94_codec.CalculateSizeWithTag(DoubleField94); + } + if (doubleField54_ != null) { + size += _single_doubleField54_codec.CalculateSizeWithTag(DoubleField54); + } + if (doubleField55_ != null) { + size += _single_doubleField55_codec.CalculateSizeWithTag(DoubleField55); + } + if (doubleField56_ != null) { + size += _single_doubleField56_codec.CalculateSizeWithTag(DoubleField56); + } + if (doubleField57_ != null) { + size += _single_doubleField57_codec.CalculateSizeWithTag(DoubleField57); + } + if (doubleField58_ != null) { + size += _single_doubleField58_codec.CalculateSizeWithTag(DoubleField58); + } + if (int64Field59_ != null) { + size += _single_int64Field59_codec.CalculateSizeWithTag(Int64Field59); + } + if (int64Field60_ != null) { + size += _single_int64Field60_codec.CalculateSizeWithTag(Int64Field60); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ManyWrapperFieldsMessage other) { + if (other == null) { + return; + } + if (other.doubleField95_ != null) { + if (doubleField95_ == null || other.DoubleField95 != 0D) { + DoubleField95 = other.DoubleField95; + } + } + if (other.doubleField1_ != null) { + if (doubleField1_ == null || other.DoubleField1 != 0D) { + DoubleField1 = other.DoubleField1; + } + } + if (other.doubleField79_ != null) { + if (doubleField79_ == null || other.DoubleField79 != 0D) { + DoubleField79 = other.DoubleField79; + } + } + if (other.int64Field2_ != null) { + if (int64Field2_ == null || other.Int64Field2 != 0L) { + Int64Field2 = other.Int64Field2; + } + } + if (other.doubleField96_ != null) { + if (doubleField96_ == null || other.DoubleField96 != 0D) { + DoubleField96 = other.DoubleField96; + } + } + if (other.int64Field3_ != null) { + if (int64Field3_ == null || other.Int64Field3 != 0L) { + Int64Field3 = other.Int64Field3; + } + } + if (other.int64Field4_ != null) { + if (int64Field4_ == null || other.Int64Field4 != 0L) { + Int64Field4 = other.Int64Field4; + } + } + if (other.doubleField97_ != null) { + if (doubleField97_ == null || other.DoubleField97 != 0D) { + DoubleField97 = other.DoubleField97; + } + } + if (other.doubleField65_ != null) { + if (doubleField65_ == null || other.DoubleField65 != 0D) { + DoubleField65 = other.DoubleField65; + } + } + if (other.doubleField66_ != null) { + if (doubleField66_ == null || other.DoubleField66 != 0D) { + DoubleField66 = other.DoubleField66; + } + } + if (other.doubleField7_ != null) { + if (doubleField7_ == null || other.DoubleField7 != 0D) { + DoubleField7 = other.DoubleField7; + } + } + if (other.doubleField62_ != null) { + if (doubleField62_ == null || other.DoubleField62 != 0D) { + DoubleField62 = other.DoubleField62; + } + } + if (other.doubleField118_ != null) { + if (doubleField118_ == null || other.DoubleField118 != 0D) { + DoubleField118 = other.DoubleField118; + } + } + if (other.doubleField119_ != null) { + if (doubleField119_ == null || other.DoubleField119 != 0D) { + DoubleField119 = other.DoubleField119; + } + } + if (other.doubleField67_ != null) { + if (doubleField67_ == null || other.DoubleField67 != 0D) { + DoubleField67 = other.DoubleField67; + } + } + if (other.doubleField120_ != null) { + if (doubleField120_ == null || other.DoubleField120 != 0D) { + DoubleField120 = other.DoubleField120; + } + } + if (other.doubleField121_ != null) { + if (doubleField121_ == null || other.DoubleField121 != 0D) { + DoubleField121 = other.DoubleField121; + } + } + if (other.doubleField122_ != null) { + if (doubleField122_ == null || other.DoubleField122 != 0D) { + DoubleField122 = other.DoubleField122; + } + } + if (other.doubleField123_ != null) { + if (doubleField123_ == null || other.DoubleField123 != 0D) { + DoubleField123 = other.DoubleField123; + } + } + if (other.doubleField124_ != null) { + if (doubleField124_ == null || other.DoubleField124 != 0D) { + DoubleField124 = other.DoubleField124; + } + } + if (other.doubleField8_ != null) { + if (doubleField8_ == null || other.DoubleField8 != 0D) { + DoubleField8 = other.DoubleField8; + } + } + if (other.doubleField9_ != null) { + if (doubleField9_ == null || other.DoubleField9 != 0D) { + DoubleField9 = other.DoubleField9; + } + } + if (other.doubleField98_ != null) { + if (doubleField98_ == null || other.DoubleField98 != 0D) { + DoubleField98 = other.DoubleField98; + } + } + if (other.doubleField10_ != null) { + if (doubleField10_ == null || other.DoubleField10 != 0D) { + DoubleField10 = other.DoubleField10; + } + } + if (other.doubleField11_ != null) { + if (doubleField11_ == null || other.DoubleField11 != 0D) { + DoubleField11 = other.DoubleField11; + } + } + if (other.doubleField99_ != null) { + if (doubleField99_ == null || other.DoubleField99 != 0D) { + DoubleField99 = other.DoubleField99; + } + } + if (other.doubleField84_ != null) { + if (doubleField84_ == null || other.DoubleField84 != 0D) { + DoubleField84 = other.DoubleField84; + } + } + if (other.doubleField14_ != null) { + if (doubleField14_ == null || other.DoubleField14 != 0D) { + DoubleField14 = other.DoubleField14; + } + } + if (other.doubleField77_ != null) { + if (doubleField77_ == null || other.DoubleField77 != 0D) { + DoubleField77 = other.DoubleField77; + } + } + if (other.doubleField15_ != null) { + if (doubleField15_ == null || other.DoubleField15 != 0D) { + DoubleField15 = other.DoubleField15; + } + } + if (other.int64Field19_ != null) { + if (int64Field19_ == null || other.Int64Field19 != 0L) { + Int64Field19 = other.Int64Field19; + } + } + if (other.int64Field115_ != null) { + if (int64Field115_ == null || other.Int64Field115 != 0L) { + Int64Field115 = other.Int64Field115; + } + } + if (other.doubleField116_ != null) { + if (doubleField116_ == null || other.DoubleField116 != 0D) { + DoubleField116 = other.DoubleField116; + } + } + if (other.int64Field117_ != null) { + if (int64Field117_ == null || other.Int64Field117 != 0L) { + Int64Field117 = other.Int64Field117; + } + } + if (other.doubleField20_ != null) { + if (doubleField20_ == null || other.DoubleField20 != 0D) { + DoubleField20 = other.DoubleField20; + } + } + if (other.doubleField21_ != null) { + if (doubleField21_ == null || other.DoubleField21 != 0D) { + DoubleField21 = other.DoubleField21; + } + } + if (other.stringField73_ != null) { + if (stringField73_ == null || other.StringField73 != "") { + StringField73 = other.StringField73; + } + } + if (other.stringField74_ != null) { + if (stringField74_ == null || other.StringField74 != "") { + StringField74 = other.StringField74; + } + } + if (other.doubleField22_ != null) { + if (doubleField22_ == null || other.DoubleField22 != 0D) { + DoubleField22 = other.DoubleField22; + } + } + if (other.doubleField69_ != null) { + if (doubleField69_ == null || other.DoubleField69 != 0D) { + DoubleField69 = other.DoubleField69; + } + } + if (other.doubleField70_ != null) { + if (doubleField70_ == null || other.DoubleField70 != 0D) { + DoubleField70 = other.DoubleField70; + } + } + if (other.doubleField71_ != null) { + if (doubleField71_ == null || other.DoubleField71 != 0D) { + DoubleField71 = other.DoubleField71; + } + } + if (other.doubleField72_ != null) { + if (doubleField72_ == null || other.DoubleField72 != 0D) { + DoubleField72 = other.DoubleField72; + } + } + if (other.doubleField25_ != null) { + if (doubleField25_ == null || other.DoubleField25 != 0D) { + DoubleField25 = other.DoubleField25; + } + } + if (other.int64Field26_ != null) { + if (int64Field26_ == null || other.Int64Field26 != 0L) { + Int64Field26 = other.Int64Field26; + } + } + if (other.doubleField68_ != null) { + if (doubleField68_ == null || other.DoubleField68 != 0D) { + DoubleField68 = other.DoubleField68; + } + } + if (other.doubleField28_ != null) { + if (doubleField28_ == null || other.DoubleField28 != 0D) { + DoubleField28 = other.DoubleField28; + } + } + if (other.doubleField106_ != null) { + if (doubleField106_ == null || other.DoubleField106 != 0D) { + DoubleField106 = other.DoubleField106; + } + } + if (other.doubleField29_ != null) { + if (doubleField29_ == null || other.DoubleField29 != 0D) { + DoubleField29 = other.DoubleField29; + } + } + if (other.doubleField30_ != null) { + if (doubleField30_ == null || other.DoubleField30 != 0D) { + DoubleField30 = other.DoubleField30; + } + } + if (other.doubleField101_ != null) { + if (doubleField101_ == null || other.DoubleField101 != 0D) { + DoubleField101 = other.DoubleField101; + } + } + if (other.doubleField102_ != null) { + if (doubleField102_ == null || other.DoubleField102 != 0D) { + DoubleField102 = other.DoubleField102; + } + } + if (other.doubleField103_ != null) { + if (doubleField103_ == null || other.DoubleField103 != 0D) { + DoubleField103 = other.DoubleField103; + } + } + if (other.doubleField104_ != null) { + if (doubleField104_ == null || other.DoubleField104 != 0D) { + DoubleField104 = other.DoubleField104; + } + } + if (other.doubleField105_ != null) { + if (doubleField105_ == null || other.DoubleField105 != 0D) { + DoubleField105 = other.DoubleField105; + } + } + if (other.doubleField31_ != null) { + if (doubleField31_ == null || other.DoubleField31 != 0D) { + DoubleField31 = other.DoubleField31; + } + } + if (other.int64Field32_ != null) { + if (int64Field32_ == null || other.Int64Field32 != 0L) { + Int64Field32 = other.Int64Field32; + } + } + if (other.doubleField75_ != null) { + if (doubleField75_ == null || other.DoubleField75 != 0D) { + DoubleField75 = other.DoubleField75; + } + } + if (other.doubleField129_ != null) { + if (doubleField129_ == null || other.DoubleField129 != 0D) { + DoubleField129 = other.DoubleField129; + } + } + if (other.EnumField80 != 0) { + EnumField80 = other.EnumField80; + } + if (other.EnumField81 != 0) { + EnumField81 = other.EnumField81; + } + if (other.int64Field82_ != null) { + if (int64Field82_ == null || other.Int64Field82 != 0L) { + Int64Field82 = other.Int64Field82; + } + } + if (other.EnumField83 != 0) { + EnumField83 = other.EnumField83; + } + if (other.int64Field85_ != null) { + if (int64Field85_ == null || other.Int64Field85 != 0L) { + Int64Field85 = other.Int64Field85; + } + } + if (other.int64Field86_ != null) { + if (int64Field86_ == null || other.Int64Field86 != 0L) { + Int64Field86 = other.Int64Field86; + } + } + if (other.int64Field87_ != null) { + if (int64Field87_ == null || other.Int64Field87 != 0L) { + Int64Field87 = other.Int64Field87; + } + } + if (other.int64Field125_ != null) { + if (int64Field125_ == null || other.Int64Field125 != 0L) { + Int64Field125 = other.Int64Field125; + } + } + if (other.int64Field37_ != null) { + if (int64Field37_ == null || other.Int64Field37 != 0L) { + Int64Field37 = other.Int64Field37; + } + } + if (other.doubleField38_ != null) { + if (doubleField38_ == null || other.DoubleField38 != 0D) { + DoubleField38 = other.DoubleField38; + } + } + if (other.interactions_ != null) { + if (interactions_ == null || other.Interactions != 0L) { + Interactions = other.Interactions; + } + } + repeatedIntField100_.Add(other.repeatedIntField100_); + if (other.doubleField40_ != null) { + if (doubleField40_ == null || other.DoubleField40 != 0D) { + DoubleField40 = other.DoubleField40; + } + } + if (other.int64Field41_ != null) { + if (int64Field41_ == null || other.Int64Field41 != 0L) { + Int64Field41 = other.Int64Field41; + } + } + if (other.int64Field126_ != null) { + if (int64Field126_ == null || other.Int64Field126 != 0L) { + Int64Field126 = other.Int64Field126; + } + } + if (other.int64Field127_ != null) { + if (int64Field127_ == null || other.Int64Field127 != 0L) { + Int64Field127 = other.Int64Field127; + } + } + if (other.doubleField128_ != null) { + if (doubleField128_ == null || other.DoubleField128 != 0D) { + DoubleField128 = other.DoubleField128; + } + } + if (other.doubleField109_ != null) { + if (doubleField109_ == null || other.DoubleField109 != 0D) { + DoubleField109 = other.DoubleField109; + } + } + if (other.int64Field110_ != null) { + if (int64Field110_ == null || other.Int64Field110 != 0L) { + Int64Field110 = other.Int64Field110; + } + } + if (other.doubleField111_ != null) { + if (doubleField111_ == null || other.DoubleField111 != 0D) { + DoubleField111 = other.DoubleField111; + } + } + if (other.int64Field112_ != null) { + if (int64Field112_ == null || other.Int64Field112 != 0L) { + Int64Field112 = other.Int64Field112; + } + } + if (other.doubleField113_ != null) { + if (doubleField113_ == null || other.DoubleField113 != 0D) { + DoubleField113 = other.DoubleField113; + } + } + if (other.int64Field114_ != null) { + if (int64Field114_ == null || other.Int64Field114 != 0L) { + Int64Field114 = other.Int64Field114; + } + } + if (other.doubleField42_ != null) { + if (doubleField42_ == null || other.DoubleField42 != 0D) { + DoubleField42 = other.DoubleField42; + } + } + if (other.int64Field43_ != null) { + if (int64Field43_ == null || other.Int64Field43 != 0L) { + Int64Field43 = other.Int64Field43; + } + } + if (other.int64Field44_ != null) { + if (int64Field44_ == null || other.Int64Field44 != 0L) { + Int64Field44 = other.Int64Field44; + } + } + if (other.doubleField45_ != null) { + if (doubleField45_ == null || other.DoubleField45 != 0D) { + DoubleField45 = other.DoubleField45; + } + } + if (other.doubleField46_ != null) { + if (doubleField46_ == null || other.DoubleField46 != 0D) { + DoubleField46 = other.DoubleField46; + } + } + if (other.doubleField78_ != null) { + if (doubleField78_ == null || other.DoubleField78 != 0D) { + DoubleField78 = other.DoubleField78; + } + } + if (other.doubleField88_ != null) { + if (doubleField88_ == null || other.DoubleField88 != 0D) { + DoubleField88 = other.DoubleField88; + } + } + if (other.doubleField47_ != null) { + if (doubleField47_ == null || other.DoubleField47 != 0D) { + DoubleField47 = other.DoubleField47; + } + } + if (other.doubleField89_ != null) { + if (doubleField89_ == null || other.DoubleField89 != 0D) { + DoubleField89 = other.DoubleField89; + } + } + if (other.doubleField48_ != null) { + if (doubleField48_ == null || other.DoubleField48 != 0D) { + DoubleField48 = other.DoubleField48; + } + } + if (other.doubleField49_ != null) { + if (doubleField49_ == null || other.DoubleField49 != 0D) { + DoubleField49 = other.DoubleField49; + } + } + if (other.doubleField50_ != null) { + if (doubleField50_ == null || other.DoubleField50 != 0D) { + DoubleField50 = other.DoubleField50; + } + } + if (other.doubleField90_ != null) { + if (doubleField90_ == null || other.DoubleField90 != 0D) { + DoubleField90 = other.DoubleField90; + } + } + if (other.doubleField51_ != null) { + if (doubleField51_ == null || other.DoubleField51 != 0D) { + DoubleField51 = other.DoubleField51; + } + } + if (other.doubleField91_ != null) { + if (doubleField91_ == null || other.DoubleField91 != 0D) { + DoubleField91 = other.DoubleField91; + } + } + if (other.doubleField92_ != null) { + if (doubleField92_ == null || other.DoubleField92 != 0D) { + DoubleField92 = other.DoubleField92; + } + } + if (other.int64Field107_ != null) { + if (int64Field107_ == null || other.Int64Field107 != 0L) { + Int64Field107 = other.Int64Field107; + } + } + if (other.doubleField93_ != null) { + if (doubleField93_ == null || other.DoubleField93 != 0D) { + DoubleField93 = other.DoubleField93; + } + } + if (other.doubleField108_ != null) { + if (doubleField108_ == null || other.DoubleField108 != 0D) { + DoubleField108 = other.DoubleField108; + } + } + if (other.doubleField52_ != null) { + if (doubleField52_ == null || other.DoubleField52 != 0D) { + DoubleField52 = other.DoubleField52; + } + } + if (other.doubleField53_ != null) { + if (doubleField53_ == null || other.DoubleField53 != 0D) { + DoubleField53 = other.DoubleField53; + } + } + if (other.doubleField94_ != null) { + if (doubleField94_ == null || other.DoubleField94 != 0D) { + DoubleField94 = other.DoubleField94; + } + } + if (other.doubleField54_ != null) { + if (doubleField54_ == null || other.DoubleField54 != 0D) { + DoubleField54 = other.DoubleField54; + } + } + if (other.doubleField55_ != null) { + if (doubleField55_ == null || other.DoubleField55 != 0D) { + DoubleField55 = other.DoubleField55; + } + } + if (other.doubleField56_ != null) { + if (doubleField56_ == null || other.DoubleField56 != 0D) { + DoubleField56 = other.DoubleField56; + } + } + if (other.doubleField57_ != null) { + if (doubleField57_ == null || other.DoubleField57 != 0D) { + DoubleField57 = other.DoubleField57; + } + } + if (other.doubleField58_ != null) { + if (doubleField58_ == null || other.DoubleField58 != 0D) { + DoubleField58 = other.DoubleField58; + } + } + if (other.int64Field59_ != null) { + if (int64Field59_ == null || other.Int64Field59 != 0L) { + Int64Field59 = other.Int64Field59; + } + } + if (other.int64Field60_ != null) { + if (int64Field60_ == null || other.Int64Field60 != 0L) { + Int64Field60 = other.Int64Field60; + } + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + double? value = _single_doubleField1_codec.Read(input); + if (doubleField1_ == null || value != 0D) { + DoubleField1 = value; + } + break; + } + case 18: { + long? value = _single_int64Field2_codec.Read(input); + if (int64Field2_ == null || value != 0L) { + Int64Field2 = value; + } + break; + } + case 26: { + long? value = _single_int64Field3_codec.Read(input); + if (int64Field3_ == null || value != 0L) { + Int64Field3 = value; + } + break; + } + case 34: { + long? value = _single_int64Field4_codec.Read(input); + if (int64Field4_ == null || value != 0L) { + Int64Field4 = value; + } + break; + } + case 58: { + double? value = _single_doubleField7_codec.Read(input); + if (doubleField7_ == null || value != 0D) { + DoubleField7 = value; + } + break; + } + case 66: { + double? value = _single_doubleField8_codec.Read(input); + if (doubleField8_ == null || value != 0D) { + DoubleField8 = value; + } + break; + } + case 74: { + double? value = _single_doubleField9_codec.Read(input); + if (doubleField9_ == null || value != 0D) { + DoubleField9 = value; + } + break; + } + case 82: { + double? value = _single_doubleField10_codec.Read(input); + if (doubleField10_ == null || value != 0D) { + DoubleField10 = value; + } + break; + } + case 90: { + double? value = _single_doubleField11_codec.Read(input); + if (doubleField11_ == null || value != 0D) { + DoubleField11 = value; + } + break; + } + case 114: { + double? value = _single_doubleField14_codec.Read(input); + if (doubleField14_ == null || value != 0D) { + DoubleField14 = value; + } + break; + } + case 122: { + double? value = _single_doubleField15_codec.Read(input); + if (doubleField15_ == null || value != 0D) { + DoubleField15 = value; + } + break; + } + case 154: { + long? value = _single_int64Field19_codec.Read(input); + if (int64Field19_ == null || value != 0L) { + Int64Field19 = value; + } + break; + } + case 162: { + double? value = _single_doubleField20_codec.Read(input); + if (doubleField20_ == null || value != 0D) { + DoubleField20 = value; + } + break; + } + case 170: { + double? value = _single_doubleField21_codec.Read(input); + if (doubleField21_ == null || value != 0D) { + DoubleField21 = value; + } + break; + } + case 178: { + double? value = _single_doubleField22_codec.Read(input); + if (doubleField22_ == null || value != 0D) { + DoubleField22 = value; + } + break; + } + case 202: { + double? value = _single_doubleField25_codec.Read(input); + if (doubleField25_ == null || value != 0D) { + DoubleField25 = value; + } + break; + } + case 210: { + long? value = _single_int64Field26_codec.Read(input); + if (int64Field26_ == null || value != 0L) { + Int64Field26 = value; + } + break; + } + case 226: { + double? value = _single_doubleField28_codec.Read(input); + if (doubleField28_ == null || value != 0D) { + DoubleField28 = value; + } + break; + } + case 234: { + double? value = _single_doubleField29_codec.Read(input); + if (doubleField29_ == null || value != 0D) { + DoubleField29 = value; + } + break; + } + case 242: { + double? value = _single_doubleField30_codec.Read(input); + if (doubleField30_ == null || value != 0D) { + DoubleField30 = value; + } + break; + } + case 250: { + double? value = _single_doubleField31_codec.Read(input); + if (doubleField31_ == null || value != 0D) { + DoubleField31 = value; + } + break; + } + case 258: { + long? value = _single_int64Field32_codec.Read(input); + if (int64Field32_ == null || value != 0L) { + Int64Field32 = value; + } + break; + } + case 298: { + long? value = _single_int64Field37_codec.Read(input); + if (int64Field37_ == null || value != 0L) { + Int64Field37 = value; + } + break; + } + case 306: { + double? value = _single_doubleField38_codec.Read(input); + if (doubleField38_ == null || value != 0D) { + DoubleField38 = value; + } + break; + } + case 314: { + long? value = _single_interactions_codec.Read(input); + if (interactions_ == null || value != 0L) { + Interactions = value; + } + break; + } + case 322: { + double? value = _single_doubleField40_codec.Read(input); + if (doubleField40_ == null || value != 0D) { + DoubleField40 = value; + } + break; + } + case 330: { + long? value = _single_int64Field41_codec.Read(input); + if (int64Field41_ == null || value != 0L) { + Int64Field41 = value; + } + break; + } + case 338: { + double? value = _single_doubleField42_codec.Read(input); + if (doubleField42_ == null || value != 0D) { + DoubleField42 = value; + } + break; + } + case 346: { + long? value = _single_int64Field43_codec.Read(input); + if (int64Field43_ == null || value != 0L) { + Int64Field43 = value; + } + break; + } + case 354: { + long? value = _single_int64Field44_codec.Read(input); + if (int64Field44_ == null || value != 0L) { + Int64Field44 = value; + } + break; + } + case 362: { + double? value = _single_doubleField45_codec.Read(input); + if (doubleField45_ == null || value != 0D) { + DoubleField45 = value; + } + break; + } + case 370: { + double? value = _single_doubleField46_codec.Read(input); + if (doubleField46_ == null || value != 0D) { + DoubleField46 = value; + } + break; + } + case 378: { + double? value = _single_doubleField47_codec.Read(input); + if (doubleField47_ == null || value != 0D) { + DoubleField47 = value; + } + break; + } + case 386: { + double? value = _single_doubleField48_codec.Read(input); + if (doubleField48_ == null || value != 0D) { + DoubleField48 = value; + } + break; + } + case 394: { + double? value = _single_doubleField49_codec.Read(input); + if (doubleField49_ == null || value != 0D) { + DoubleField49 = value; + } + break; + } + case 402: { + double? value = _single_doubleField50_codec.Read(input); + if (doubleField50_ == null || value != 0D) { + DoubleField50 = value; + } + break; + } + case 410: { + double? value = _single_doubleField51_codec.Read(input); + if (doubleField51_ == null || value != 0D) { + DoubleField51 = value; + } + break; + } + case 418: { + double? value = _single_doubleField52_codec.Read(input); + if (doubleField52_ == null || value != 0D) { + DoubleField52 = value; + } + break; + } + case 426: { + double? value = _single_doubleField53_codec.Read(input); + if (doubleField53_ == null || value != 0D) { + DoubleField53 = value; + } + break; + } + case 434: { + double? value = _single_doubleField54_codec.Read(input); + if (doubleField54_ == null || value != 0D) { + DoubleField54 = value; + } + break; + } + case 442: { + double? value = _single_doubleField55_codec.Read(input); + if (doubleField55_ == null || value != 0D) { + DoubleField55 = value; + } + break; + } + case 450: { + double? value = _single_doubleField56_codec.Read(input); + if (doubleField56_ == null || value != 0D) { + DoubleField56 = value; + } + break; + } + case 458: { + double? value = _single_doubleField57_codec.Read(input); + if (doubleField57_ == null || value != 0D) { + DoubleField57 = value; + } + break; + } + case 466: { + double? value = _single_doubleField58_codec.Read(input); + if (doubleField58_ == null || value != 0D) { + DoubleField58 = value; + } + break; + } + case 474: { + long? value = _single_int64Field59_codec.Read(input); + if (int64Field59_ == null || value != 0L) { + Int64Field59 = value; + } + break; + } + case 482: { + long? value = _single_int64Field60_codec.Read(input); + if (int64Field60_ == null || value != 0L) { + Int64Field60 = value; + } + break; + } + case 498: { + double? value = _single_doubleField62_codec.Read(input); + if (doubleField62_ == null || value != 0D) { + DoubleField62 = value; + } + break; + } + case 522: { + double? value = _single_doubleField65_codec.Read(input); + if (doubleField65_ == null || value != 0D) { + DoubleField65 = value; + } + break; + } + case 530: { + double? value = _single_doubleField66_codec.Read(input); + if (doubleField66_ == null || value != 0D) { + DoubleField66 = value; + } + break; + } + case 538: { + double? value = _single_doubleField67_codec.Read(input); + if (doubleField67_ == null || value != 0D) { + DoubleField67 = value; + } + break; + } + case 546: { + double? value = _single_doubleField68_codec.Read(input); + if (doubleField68_ == null || value != 0D) { + DoubleField68 = value; + } + break; + } + case 554: { + double? value = _single_doubleField69_codec.Read(input); + if (doubleField69_ == null || value != 0D) { + DoubleField69 = value; + } + break; + } + case 562: { + double? value = _single_doubleField70_codec.Read(input); + if (doubleField70_ == null || value != 0D) { + DoubleField70 = value; + } + break; + } + case 570: { + double? value = _single_doubleField71_codec.Read(input); + if (doubleField71_ == null || value != 0D) { + DoubleField71 = value; + } + break; + } + case 578: { + double? value = _single_doubleField72_codec.Read(input); + if (doubleField72_ == null || value != 0D) { + DoubleField72 = value; + } + break; + } + case 586: { + string value = _single_stringField73_codec.Read(input); + if (stringField73_ == null || value != "") { + StringField73 = value; + } + break; + } + case 594: { + string value = _single_stringField74_codec.Read(input); + if (stringField74_ == null || value != "") { + StringField74 = value; + } + break; + } + case 602: { + double? value = _single_doubleField75_codec.Read(input); + if (doubleField75_ == null || value != 0D) { + DoubleField75 = value; + } + break; + } + case 618: { + double? value = _single_doubleField77_codec.Read(input); + if (doubleField77_ == null || value != 0D) { + DoubleField77 = value; + } + break; + } + case 626: { + double? value = _single_doubleField78_codec.Read(input); + if (doubleField78_ == null || value != 0D) { + DoubleField78 = value; + } + break; + } + case 634: { + double? value = _single_doubleField79_codec.Read(input); + if (doubleField79_ == null || value != 0D) { + DoubleField79 = value; + } + break; + } + case 640: { + EnumField80 = input.ReadInt32(); + break; + } + case 648: { + EnumField81 = input.ReadInt32(); + break; + } + case 658: { + long? value = _single_int64Field82_codec.Read(input); + if (int64Field82_ == null || value != 0L) { + Int64Field82 = value; + } + break; + } + case 664: { + EnumField83 = input.ReadInt32(); + break; + } + case 674: { + double? value = _single_doubleField84_codec.Read(input); + if (doubleField84_ == null || value != 0D) { + DoubleField84 = value; + } + break; + } + case 682: { + long? value = _single_int64Field85_codec.Read(input); + if (int64Field85_ == null || value != 0L) { + Int64Field85 = value; + } + break; + } + case 690: { + long? value = _single_int64Field86_codec.Read(input); + if (int64Field86_ == null || value != 0L) { + Int64Field86 = value; + } + break; + } + case 698: { + long? value = _single_int64Field87_codec.Read(input); + if (int64Field87_ == null || value != 0L) { + Int64Field87 = value; + } + break; + } + case 706: { + double? value = _single_doubleField88_codec.Read(input); + if (doubleField88_ == null || value != 0D) { + DoubleField88 = value; + } + break; + } + case 714: { + double? value = _single_doubleField89_codec.Read(input); + if (doubleField89_ == null || value != 0D) { + DoubleField89 = value; + } + break; + } + case 722: { + double? value = _single_doubleField90_codec.Read(input); + if (doubleField90_ == null || value != 0D) { + DoubleField90 = value; + } + break; + } + case 730: { + double? value = _single_doubleField91_codec.Read(input); + if (doubleField91_ == null || value != 0D) { + DoubleField91 = value; + } + break; + } + case 738: { + double? value = _single_doubleField92_codec.Read(input); + if (doubleField92_ == null || value != 0D) { + DoubleField92 = value; + } + break; + } + case 746: { + double? value = _single_doubleField93_codec.Read(input); + if (doubleField93_ == null || value != 0D) { + DoubleField93 = value; + } + break; + } + case 754: { + double? value = _single_doubleField94_codec.Read(input); + if (doubleField94_ == null || value != 0D) { + DoubleField94 = value; + } + break; + } + case 762: { + double? value = _single_doubleField95_codec.Read(input); + if (doubleField95_ == null || value != 0D) { + DoubleField95 = value; + } + break; + } + case 770: { + double? value = _single_doubleField96_codec.Read(input); + if (doubleField96_ == null || value != 0D) { + DoubleField96 = value; + } + break; + } + case 778: { + double? value = _single_doubleField97_codec.Read(input); + if (doubleField97_ == null || value != 0D) { + DoubleField97 = value; + } + break; + } + case 786: { + double? value = _single_doubleField98_codec.Read(input); + if (doubleField98_ == null || value != 0D) { + DoubleField98 = value; + } + break; + } + case 794: { + double? value = _single_doubleField99_codec.Read(input); + if (doubleField99_ == null || value != 0D) { + DoubleField99 = value; + } + break; + } + case 802: + case 800: { + repeatedIntField100_.AddEntriesFrom(input, _repeated_repeatedIntField100_codec); + break; + } + case 810: { + double? value = _single_doubleField101_codec.Read(input); + if (doubleField101_ == null || value != 0D) { + DoubleField101 = value; + } + break; + } + case 818: { + double? value = _single_doubleField102_codec.Read(input); + if (doubleField102_ == null || value != 0D) { + DoubleField102 = value; + } + break; + } + case 826: { + double? value = _single_doubleField103_codec.Read(input); + if (doubleField103_ == null || value != 0D) { + DoubleField103 = value; + } + break; + } + case 834: { + double? value = _single_doubleField104_codec.Read(input); + if (doubleField104_ == null || value != 0D) { + DoubleField104 = value; + } + break; + } + case 842: { + double? value = _single_doubleField105_codec.Read(input); + if (doubleField105_ == null || value != 0D) { + DoubleField105 = value; + } + break; + } + case 850: { + double? value = _single_doubleField106_codec.Read(input); + if (doubleField106_ == null || value != 0D) { + DoubleField106 = value; + } + break; + } + case 858: { + long? value = _single_int64Field107_codec.Read(input); + if (int64Field107_ == null || value != 0L) { + Int64Field107 = value; + } + break; + } + case 866: { + double? value = _single_doubleField108_codec.Read(input); + if (doubleField108_ == null || value != 0D) { + DoubleField108 = value; + } + break; + } + case 874: { + double? value = _single_doubleField109_codec.Read(input); + if (doubleField109_ == null || value != 0D) { + DoubleField109 = value; + } + break; + } + case 882: { + long? value = _single_int64Field110_codec.Read(input); + if (int64Field110_ == null || value != 0L) { + Int64Field110 = value; + } + break; + } + case 890: { + double? value = _single_doubleField111_codec.Read(input); + if (doubleField111_ == null || value != 0D) { + DoubleField111 = value; + } + break; + } + case 898: { + long? value = _single_int64Field112_codec.Read(input); + if (int64Field112_ == null || value != 0L) { + Int64Field112 = value; + } + break; + } + case 906: { + double? value = _single_doubleField113_codec.Read(input); + if (doubleField113_ == null || value != 0D) { + DoubleField113 = value; + } + break; + } + case 914: { + long? value = _single_int64Field114_codec.Read(input); + if (int64Field114_ == null || value != 0L) { + Int64Field114 = value; + } + break; + } + case 922: { + long? value = _single_int64Field115_codec.Read(input); + if (int64Field115_ == null || value != 0L) { + Int64Field115 = value; + } + break; + } + case 930: { + double? value = _single_doubleField116_codec.Read(input); + if (doubleField116_ == null || value != 0D) { + DoubleField116 = value; + } + break; + } + case 938: { + long? value = _single_int64Field117_codec.Read(input); + if (int64Field117_ == null || value != 0L) { + Int64Field117 = value; + } + break; + } + case 946: { + double? value = _single_doubleField118_codec.Read(input); + if (doubleField118_ == null || value != 0D) { + DoubleField118 = value; + } + break; + } + case 954: { + double? value = _single_doubleField119_codec.Read(input); + if (doubleField119_ == null || value != 0D) { + DoubleField119 = value; + } + break; + } + case 962: { + double? value = _single_doubleField120_codec.Read(input); + if (doubleField120_ == null || value != 0D) { + DoubleField120 = value; + } + break; + } + case 970: { + double? value = _single_doubleField121_codec.Read(input); + if (doubleField121_ == null || value != 0D) { + DoubleField121 = value; + } + break; + } + case 978: { + double? value = _single_doubleField122_codec.Read(input); + if (doubleField122_ == null || value != 0D) { + DoubleField122 = value; + } + break; + } + case 986: { + double? value = _single_doubleField123_codec.Read(input); + if (doubleField123_ == null || value != 0D) { + DoubleField123 = value; + } + break; + } + case 994: { + double? value = _single_doubleField124_codec.Read(input); + if (doubleField124_ == null || value != 0D) { + DoubleField124 = value; + } + break; + } + case 1002: { + long? value = _single_int64Field125_codec.Read(input); + if (int64Field125_ == null || value != 0L) { + Int64Field125 = value; + } + break; + } + case 1010: { + long? value = _single_int64Field126_codec.Read(input); + if (int64Field126_ == null || value != 0L) { + Int64Field126 = value; + } + break; + } + case 1018: { + long? value = _single_int64Field127_codec.Read(input); + if (int64Field127_ == null || value != 0L) { + Int64Field127 = value; + } + break; + } + case 1026: { + double? value = _single_doubleField128_codec.Read(input); + if (doubleField128_ == null || value != 0D) { + DoubleField128 = value; + } + break; + } + case 1034: { + double? value = _single_doubleField129_codec.Read(input); + if (doubleField129_ == null || value != 0D) { + DoubleField129 = value; + } + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + double? value = _single_doubleField1_codec.Read(ref input); + if (doubleField1_ == null || value != 0D) { + DoubleField1 = value; + } + break; + } + case 18: { + long? value = _single_int64Field2_codec.Read(ref input); + if (int64Field2_ == null || value != 0L) { + Int64Field2 = value; + } + break; + } + case 26: { + long? value = _single_int64Field3_codec.Read(ref input); + if (int64Field3_ == null || value != 0L) { + Int64Field3 = value; + } + break; + } + case 34: { + long? value = _single_int64Field4_codec.Read(ref input); + if (int64Field4_ == null || value != 0L) { + Int64Field4 = value; + } + break; + } + case 58: { + double? value = _single_doubleField7_codec.Read(ref input); + if (doubleField7_ == null || value != 0D) { + DoubleField7 = value; + } + break; + } + case 66: { + double? value = _single_doubleField8_codec.Read(ref input); + if (doubleField8_ == null || value != 0D) { + DoubleField8 = value; + } + break; + } + case 74: { + double? value = _single_doubleField9_codec.Read(ref input); + if (doubleField9_ == null || value != 0D) { + DoubleField9 = value; + } + break; + } + case 82: { + double? value = _single_doubleField10_codec.Read(ref input); + if (doubleField10_ == null || value != 0D) { + DoubleField10 = value; + } + break; + } + case 90: { + double? value = _single_doubleField11_codec.Read(ref input); + if (doubleField11_ == null || value != 0D) { + DoubleField11 = value; + } + break; + } + case 114: { + double? value = _single_doubleField14_codec.Read(ref input); + if (doubleField14_ == null || value != 0D) { + DoubleField14 = value; + } + break; + } + case 122: { + double? value = _single_doubleField15_codec.Read(ref input); + if (doubleField15_ == null || value != 0D) { + DoubleField15 = value; + } + break; + } + case 154: { + long? value = _single_int64Field19_codec.Read(ref input); + if (int64Field19_ == null || value != 0L) { + Int64Field19 = value; + } + break; + } + case 162: { + double? value = _single_doubleField20_codec.Read(ref input); + if (doubleField20_ == null || value != 0D) { + DoubleField20 = value; + } + break; + } + case 170: { + double? value = _single_doubleField21_codec.Read(ref input); + if (doubleField21_ == null || value != 0D) { + DoubleField21 = value; + } + break; + } + case 178: { + double? value = _single_doubleField22_codec.Read(ref input); + if (doubleField22_ == null || value != 0D) { + DoubleField22 = value; + } + break; + } + case 202: { + double? value = _single_doubleField25_codec.Read(ref input); + if (doubleField25_ == null || value != 0D) { + DoubleField25 = value; + } + break; + } + case 210: { + long? value = _single_int64Field26_codec.Read(ref input); + if (int64Field26_ == null || value != 0L) { + Int64Field26 = value; + } + break; + } + case 226: { + double? value = _single_doubleField28_codec.Read(ref input); + if (doubleField28_ == null || value != 0D) { + DoubleField28 = value; + } + break; + } + case 234: { + double? value = _single_doubleField29_codec.Read(ref input); + if (doubleField29_ == null || value != 0D) { + DoubleField29 = value; + } + break; + } + case 242: { + double? value = _single_doubleField30_codec.Read(ref input); + if (doubleField30_ == null || value != 0D) { + DoubleField30 = value; + } + break; + } + case 250: { + double? value = _single_doubleField31_codec.Read(ref input); + if (doubleField31_ == null || value != 0D) { + DoubleField31 = value; + } + break; + } + case 258: { + long? value = _single_int64Field32_codec.Read(ref input); + if (int64Field32_ == null || value != 0L) { + Int64Field32 = value; + } + break; + } + case 298: { + long? value = _single_int64Field37_codec.Read(ref input); + if (int64Field37_ == null || value != 0L) { + Int64Field37 = value; + } + break; + } + case 306: { + double? value = _single_doubleField38_codec.Read(ref input); + if (doubleField38_ == null || value != 0D) { + DoubleField38 = value; + } + break; + } + case 314: { + long? value = _single_interactions_codec.Read(ref input); + if (interactions_ == null || value != 0L) { + Interactions = value; + } + break; + } + case 322: { + double? value = _single_doubleField40_codec.Read(ref input); + if (doubleField40_ == null || value != 0D) { + DoubleField40 = value; + } + break; + } + case 330: { + long? value = _single_int64Field41_codec.Read(ref input); + if (int64Field41_ == null || value != 0L) { + Int64Field41 = value; + } + break; + } + case 338: { + double? value = _single_doubleField42_codec.Read(ref input); + if (doubleField42_ == null || value != 0D) { + DoubleField42 = value; + } + break; + } + case 346: { + long? value = _single_int64Field43_codec.Read(ref input); + if (int64Field43_ == null || value != 0L) { + Int64Field43 = value; + } + break; + } + case 354: { + long? value = _single_int64Field44_codec.Read(ref input); + if (int64Field44_ == null || value != 0L) { + Int64Field44 = value; + } + break; + } + case 362: { + double? value = _single_doubleField45_codec.Read(ref input); + if (doubleField45_ == null || value != 0D) { + DoubleField45 = value; + } + break; + } + case 370: { + double? value = _single_doubleField46_codec.Read(ref input); + if (doubleField46_ == null || value != 0D) { + DoubleField46 = value; + } + break; + } + case 378: { + double? value = _single_doubleField47_codec.Read(ref input); + if (doubleField47_ == null || value != 0D) { + DoubleField47 = value; + } + break; + } + case 386: { + double? value = _single_doubleField48_codec.Read(ref input); + if (doubleField48_ == null || value != 0D) { + DoubleField48 = value; + } + break; + } + case 394: { + double? value = _single_doubleField49_codec.Read(ref input); + if (doubleField49_ == null || value != 0D) { + DoubleField49 = value; + } + break; + } + case 402: { + double? value = _single_doubleField50_codec.Read(ref input); + if (doubleField50_ == null || value != 0D) { + DoubleField50 = value; + } + break; + } + case 410: { + double? value = _single_doubleField51_codec.Read(ref input); + if (doubleField51_ == null || value != 0D) { + DoubleField51 = value; + } + break; + } + case 418: { + double? value = _single_doubleField52_codec.Read(ref input); + if (doubleField52_ == null || value != 0D) { + DoubleField52 = value; + } + break; + } + case 426: { + double? value = _single_doubleField53_codec.Read(ref input); + if (doubleField53_ == null || value != 0D) { + DoubleField53 = value; + } + break; + } + case 434: { + double? value = _single_doubleField54_codec.Read(ref input); + if (doubleField54_ == null || value != 0D) { + DoubleField54 = value; + } + break; + } + case 442: { + double? value = _single_doubleField55_codec.Read(ref input); + if (doubleField55_ == null || value != 0D) { + DoubleField55 = value; + } + break; + } + case 450: { + double? value = _single_doubleField56_codec.Read(ref input); + if (doubleField56_ == null || value != 0D) { + DoubleField56 = value; + } + break; + } + case 458: { + double? value = _single_doubleField57_codec.Read(ref input); + if (doubleField57_ == null || value != 0D) { + DoubleField57 = value; + } + break; + } + case 466: { + double? value = _single_doubleField58_codec.Read(ref input); + if (doubleField58_ == null || value != 0D) { + DoubleField58 = value; + } + break; + } + case 474: { + long? value = _single_int64Field59_codec.Read(ref input); + if (int64Field59_ == null || value != 0L) { + Int64Field59 = value; + } + break; + } + case 482: { + long? value = _single_int64Field60_codec.Read(ref input); + if (int64Field60_ == null || value != 0L) { + Int64Field60 = value; + } + break; + } + case 498: { + double? value = _single_doubleField62_codec.Read(ref input); + if (doubleField62_ == null || value != 0D) { + DoubleField62 = value; + } + break; + } + case 522: { + double? value = _single_doubleField65_codec.Read(ref input); + if (doubleField65_ == null || value != 0D) { + DoubleField65 = value; + } + break; + } + case 530: { + double? value = _single_doubleField66_codec.Read(ref input); + if (doubleField66_ == null || value != 0D) { + DoubleField66 = value; + } + break; + } + case 538: { + double? value = _single_doubleField67_codec.Read(ref input); + if (doubleField67_ == null || value != 0D) { + DoubleField67 = value; + } + break; + } + case 546: { + double? value = _single_doubleField68_codec.Read(ref input); + if (doubleField68_ == null || value != 0D) { + DoubleField68 = value; + } + break; + } + case 554: { + double? value = _single_doubleField69_codec.Read(ref input); + if (doubleField69_ == null || value != 0D) { + DoubleField69 = value; + } + break; + } + case 562: { + double? value = _single_doubleField70_codec.Read(ref input); + if (doubleField70_ == null || value != 0D) { + DoubleField70 = value; + } + break; + } + case 570: { + double? value = _single_doubleField71_codec.Read(ref input); + if (doubleField71_ == null || value != 0D) { + DoubleField71 = value; + } + break; + } + case 578: { + double? value = _single_doubleField72_codec.Read(ref input); + if (doubleField72_ == null || value != 0D) { + DoubleField72 = value; + } + break; + } + case 586: { + string value = _single_stringField73_codec.Read(ref input); + if (stringField73_ == null || value != "") { + StringField73 = value; + } + break; + } + case 594: { + string value = _single_stringField74_codec.Read(ref input); + if (stringField74_ == null || value != "") { + StringField74 = value; + } + break; + } + case 602: { + double? value = _single_doubleField75_codec.Read(ref input); + if (doubleField75_ == null || value != 0D) { + DoubleField75 = value; + } + break; + } + case 618: { + double? value = _single_doubleField77_codec.Read(ref input); + if (doubleField77_ == null || value != 0D) { + DoubleField77 = value; + } + break; + } + case 626: { + double? value = _single_doubleField78_codec.Read(ref input); + if (doubleField78_ == null || value != 0D) { + DoubleField78 = value; + } + break; + } + case 634: { + double? value = _single_doubleField79_codec.Read(ref input); + if (doubleField79_ == null || value != 0D) { + DoubleField79 = value; + } + break; + } + case 640: { + EnumField80 = input.ReadInt32(); + break; + } + case 648: { + EnumField81 = input.ReadInt32(); + break; + } + case 658: { + long? value = _single_int64Field82_codec.Read(ref input); + if (int64Field82_ == null || value != 0L) { + Int64Field82 = value; + } + break; + } + case 664: { + EnumField83 = input.ReadInt32(); + break; + } + case 674: { + double? value = _single_doubleField84_codec.Read(ref input); + if (doubleField84_ == null || value != 0D) { + DoubleField84 = value; + } + break; + } + case 682: { + long? value = _single_int64Field85_codec.Read(ref input); + if (int64Field85_ == null || value != 0L) { + Int64Field85 = value; + } + break; + } + case 690: { + long? value = _single_int64Field86_codec.Read(ref input); + if (int64Field86_ == null || value != 0L) { + Int64Field86 = value; + } + break; + } + case 698: { + long? value = _single_int64Field87_codec.Read(ref input); + if (int64Field87_ == null || value != 0L) { + Int64Field87 = value; + } + break; + } + case 706: { + double? value = _single_doubleField88_codec.Read(ref input); + if (doubleField88_ == null || value != 0D) { + DoubleField88 = value; + } + break; + } + case 714: { + double? value = _single_doubleField89_codec.Read(ref input); + if (doubleField89_ == null || value != 0D) { + DoubleField89 = value; + } + break; + } + case 722: { + double? value = _single_doubleField90_codec.Read(ref input); + if (doubleField90_ == null || value != 0D) { + DoubleField90 = value; + } + break; + } + case 730: { + double? value = _single_doubleField91_codec.Read(ref input); + if (doubleField91_ == null || value != 0D) { + DoubleField91 = value; + } + break; + } + case 738: { + double? value = _single_doubleField92_codec.Read(ref input); + if (doubleField92_ == null || value != 0D) { + DoubleField92 = value; + } + break; + } + case 746: { + double? value = _single_doubleField93_codec.Read(ref input); + if (doubleField93_ == null || value != 0D) { + DoubleField93 = value; + } + break; + } + case 754: { + double? value = _single_doubleField94_codec.Read(ref input); + if (doubleField94_ == null || value != 0D) { + DoubleField94 = value; + } + break; + } + case 762: { + double? value = _single_doubleField95_codec.Read(ref input); + if (doubleField95_ == null || value != 0D) { + DoubleField95 = value; + } + break; + } + case 770: { + double? value = _single_doubleField96_codec.Read(ref input); + if (doubleField96_ == null || value != 0D) { + DoubleField96 = value; + } + break; + } + case 778: { + double? value = _single_doubleField97_codec.Read(ref input); + if (doubleField97_ == null || value != 0D) { + DoubleField97 = value; + } + break; + } + case 786: { + double? value = _single_doubleField98_codec.Read(ref input); + if (doubleField98_ == null || value != 0D) { + DoubleField98 = value; + } + break; + } + case 794: { + double? value = _single_doubleField99_codec.Read(ref input); + if (doubleField99_ == null || value != 0D) { + DoubleField99 = value; + } + break; + } + case 802: + case 800: { + repeatedIntField100_.AddEntriesFrom(ref input, _repeated_repeatedIntField100_codec); + break; + } + case 810: { + double? value = _single_doubleField101_codec.Read(ref input); + if (doubleField101_ == null || value != 0D) { + DoubleField101 = value; + } + break; + } + case 818: { + double? value = _single_doubleField102_codec.Read(ref input); + if (doubleField102_ == null || value != 0D) { + DoubleField102 = value; + } + break; + } + case 826: { + double? value = _single_doubleField103_codec.Read(ref input); + if (doubleField103_ == null || value != 0D) { + DoubleField103 = value; + } + break; + } + case 834: { + double? value = _single_doubleField104_codec.Read(ref input); + if (doubleField104_ == null || value != 0D) { + DoubleField104 = value; + } + break; + } + case 842: { + double? value = _single_doubleField105_codec.Read(ref input); + if (doubleField105_ == null || value != 0D) { + DoubleField105 = value; + } + break; + } + case 850: { + double? value = _single_doubleField106_codec.Read(ref input); + if (doubleField106_ == null || value != 0D) { + DoubleField106 = value; + } + break; + } + case 858: { + long? value = _single_int64Field107_codec.Read(ref input); + if (int64Field107_ == null || value != 0L) { + Int64Field107 = value; + } + break; + } + case 866: { + double? value = _single_doubleField108_codec.Read(ref input); + if (doubleField108_ == null || value != 0D) { + DoubleField108 = value; + } + break; + } + case 874: { + double? value = _single_doubleField109_codec.Read(ref input); + if (doubleField109_ == null || value != 0D) { + DoubleField109 = value; + } + break; + } + case 882: { + long? value = _single_int64Field110_codec.Read(ref input); + if (int64Field110_ == null || value != 0L) { + Int64Field110 = value; + } + break; + } + case 890: { + double? value = _single_doubleField111_codec.Read(ref input); + if (doubleField111_ == null || value != 0D) { + DoubleField111 = value; + } + break; + } + case 898: { + long? value = _single_int64Field112_codec.Read(ref input); + if (int64Field112_ == null || value != 0L) { + Int64Field112 = value; + } + break; + } + case 906: { + double? value = _single_doubleField113_codec.Read(ref input); + if (doubleField113_ == null || value != 0D) { + DoubleField113 = value; + } + break; + } + case 914: { + long? value = _single_int64Field114_codec.Read(ref input); + if (int64Field114_ == null || value != 0L) { + Int64Field114 = value; + } + break; + } + case 922: { + long? value = _single_int64Field115_codec.Read(ref input); + if (int64Field115_ == null || value != 0L) { + Int64Field115 = value; + } + break; + } + case 930: { + double? value = _single_doubleField116_codec.Read(ref input); + if (doubleField116_ == null || value != 0D) { + DoubleField116 = value; + } + break; + } + case 938: { + long? value = _single_int64Field117_codec.Read(ref input); + if (int64Field117_ == null || value != 0L) { + Int64Field117 = value; + } + break; + } + case 946: { + double? value = _single_doubleField118_codec.Read(ref input); + if (doubleField118_ == null || value != 0D) { + DoubleField118 = value; + } + break; + } + case 954: { + double? value = _single_doubleField119_codec.Read(ref input); + if (doubleField119_ == null || value != 0D) { + DoubleField119 = value; + } + break; + } + case 962: { + double? value = _single_doubleField120_codec.Read(ref input); + if (doubleField120_ == null || value != 0D) { + DoubleField120 = value; + } + break; + } + case 970: { + double? value = _single_doubleField121_codec.Read(ref input); + if (doubleField121_ == null || value != 0D) { + DoubleField121 = value; + } + break; + } + case 978: { + double? value = _single_doubleField122_codec.Read(ref input); + if (doubleField122_ == null || value != 0D) { + DoubleField122 = value; + } + break; + } + case 986: { + double? value = _single_doubleField123_codec.Read(ref input); + if (doubleField123_ == null || value != 0D) { + DoubleField123 = value; + } + break; + } + case 994: { + double? value = _single_doubleField124_codec.Read(ref input); + if (doubleField124_ == null || value != 0D) { + DoubleField124 = value; + } + break; + } + case 1002: { + long? value = _single_int64Field125_codec.Read(ref input); + if (int64Field125_ == null || value != 0L) { + Int64Field125 = value; + } + break; + } + case 1010: { + long? value = _single_int64Field126_codec.Read(ref input); + if (int64Field126_ == null || value != 0L) { + Int64Field126 = value; + } + break; + } + case 1018: { + long? value = _single_int64Field127_codec.Read(ref input); + if (int64Field127_ == null || value != 0L) { + Int64Field127 = value; + } + break; + } + case 1026: { + double? value = _single_doubleField128_codec.Read(ref input); + if (doubleField128_ == null || value != 0D) { + DoubleField128 = value; + } + break; + } + case 1034: { + double? value = _single_doubleField129_codec.Read(ref input); + if (doubleField129_ == null || value != 0D) { + DoubleField129 = value; + } + break; + } + } + } + } + #endif + + } + + /// + /// same as ManyWrapperFieldsMessages, but with primitive fields + /// for comparison. + /// + public sealed partial class ManyPrimitiveFieldsMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ManyPrimitiveFieldsMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.Benchmarks.WrapperBenchmarkMessagesReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ManyPrimitiveFieldsMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ManyPrimitiveFieldsMessage(ManyPrimitiveFieldsMessage other) : this() { + doubleField95_ = other.doubleField95_; + doubleField1_ = other.doubleField1_; + doubleField79_ = other.doubleField79_; + int64Field2_ = other.int64Field2_; + doubleField96_ = other.doubleField96_; + int64Field3_ = other.int64Field3_; + int64Field4_ = other.int64Field4_; + doubleField97_ = other.doubleField97_; + doubleField65_ = other.doubleField65_; + doubleField66_ = other.doubleField66_; + doubleField7_ = other.doubleField7_; + doubleField62_ = other.doubleField62_; + doubleField118_ = other.doubleField118_; + doubleField119_ = other.doubleField119_; + doubleField67_ = other.doubleField67_; + doubleField120_ = other.doubleField120_; + doubleField121_ = other.doubleField121_; + doubleField122_ = other.doubleField122_; + doubleField123_ = other.doubleField123_; + doubleField124_ = other.doubleField124_; + doubleField8_ = other.doubleField8_; + doubleField9_ = other.doubleField9_; + doubleField98_ = other.doubleField98_; + doubleField10_ = other.doubleField10_; + doubleField11_ = other.doubleField11_; + doubleField99_ = other.doubleField99_; + doubleField84_ = other.doubleField84_; + doubleField14_ = other.doubleField14_; + doubleField77_ = other.doubleField77_; + doubleField15_ = other.doubleField15_; + int64Field19_ = other.int64Field19_; + int64Field115_ = other.int64Field115_; + doubleField116_ = other.doubleField116_; + int64Field117_ = other.int64Field117_; + doubleField20_ = other.doubleField20_; + doubleField21_ = other.doubleField21_; + stringField73_ = other.stringField73_; + stringField74_ = other.stringField74_; + doubleField22_ = other.doubleField22_; + doubleField69_ = other.doubleField69_; + doubleField70_ = other.doubleField70_; + doubleField71_ = other.doubleField71_; + doubleField72_ = other.doubleField72_; + doubleField25_ = other.doubleField25_; + int64Field26_ = other.int64Field26_; + doubleField68_ = other.doubleField68_; + doubleField28_ = other.doubleField28_; + doubleField106_ = other.doubleField106_; + doubleField29_ = other.doubleField29_; + doubleField30_ = other.doubleField30_; + doubleField101_ = other.doubleField101_; + doubleField102_ = other.doubleField102_; + doubleField103_ = other.doubleField103_; + doubleField104_ = other.doubleField104_; + doubleField105_ = other.doubleField105_; + doubleField31_ = other.doubleField31_; + int64Field32_ = other.int64Field32_; + doubleField75_ = other.doubleField75_; + doubleField129_ = other.doubleField129_; + enumField80_ = other.enumField80_; + enumField81_ = other.enumField81_; + int64Field82_ = other.int64Field82_; + enumField83_ = other.enumField83_; + int64Field85_ = other.int64Field85_; + int64Field86_ = other.int64Field86_; + int64Field87_ = other.int64Field87_; + int64Field125_ = other.int64Field125_; + int64Field37_ = other.int64Field37_; + doubleField38_ = other.doubleField38_; + interactions_ = other.interactions_; + repeatedIntField100_ = other.repeatedIntField100_.Clone(); + doubleField40_ = other.doubleField40_; + int64Field41_ = other.int64Field41_; + int64Field126_ = other.int64Field126_; + int64Field127_ = other.int64Field127_; + doubleField128_ = other.doubleField128_; + doubleField109_ = other.doubleField109_; + int64Field110_ = other.int64Field110_; + doubleField111_ = other.doubleField111_; + int64Field112_ = other.int64Field112_; + doubleField113_ = other.doubleField113_; + int64Field114_ = other.int64Field114_; + doubleField42_ = other.doubleField42_; + int64Field43_ = other.int64Field43_; + int64Field44_ = other.int64Field44_; + doubleField45_ = other.doubleField45_; + doubleField46_ = other.doubleField46_; + doubleField78_ = other.doubleField78_; + doubleField88_ = other.doubleField88_; + doubleField47_ = other.doubleField47_; + doubleField89_ = other.doubleField89_; + doubleField48_ = other.doubleField48_; + doubleField49_ = other.doubleField49_; + doubleField50_ = other.doubleField50_; + doubleField90_ = other.doubleField90_; + doubleField51_ = other.doubleField51_; + doubleField91_ = other.doubleField91_; + doubleField92_ = other.doubleField92_; + int64Field107_ = other.int64Field107_; + doubleField93_ = other.doubleField93_; + doubleField108_ = other.doubleField108_; + doubleField52_ = other.doubleField52_; + doubleField53_ = other.doubleField53_; + doubleField94_ = other.doubleField94_; + doubleField54_ = other.doubleField54_; + doubleField55_ = other.doubleField55_; + doubleField56_ = other.doubleField56_; + doubleField57_ = other.doubleField57_; + doubleField58_ = other.doubleField58_; + int64Field59_ = other.int64Field59_; + int64Field60_ = other.int64Field60_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ManyPrimitiveFieldsMessage Clone() { + return new ManyPrimitiveFieldsMessage(this); + } + + /// Field number for the "double_field_95" field. + public const int DoubleField95FieldNumber = 95; + private double doubleField95_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField95 { + get { return doubleField95_; } + set { + doubleField95_ = value; + } + } + + /// Field number for the "double_field_1" field. + public const int DoubleField1FieldNumber = 1; + private double doubleField1_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField1 { + get { return doubleField1_; } + set { + doubleField1_ = value; + } + } + + /// Field number for the "double_field_79" field. + public const int DoubleField79FieldNumber = 79; + private double doubleField79_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField79 { + get { return doubleField79_; } + set { + doubleField79_ = value; + } + } + + /// Field number for the "int64_field_2" field. + public const int Int64Field2FieldNumber = 2; + private long int64Field2_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field2 { + get { return int64Field2_; } + set { + int64Field2_ = value; + } + } + + /// Field number for the "double_field_96" field. + public const int DoubleField96FieldNumber = 96; + private double doubleField96_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField96 { + get { return doubleField96_; } + set { + doubleField96_ = value; + } + } + + /// Field number for the "int64_field_3" field. + public const int Int64Field3FieldNumber = 3; + private long int64Field3_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field3 { + get { return int64Field3_; } + set { + int64Field3_ = value; + } + } + + /// Field number for the "int64_field_4" field. + public const int Int64Field4FieldNumber = 4; + private long int64Field4_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field4 { + get { return int64Field4_; } + set { + int64Field4_ = value; + } + } + + /// Field number for the "double_field_97" field. + public const int DoubleField97FieldNumber = 97; + private double doubleField97_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField97 { + get { return doubleField97_; } + set { + doubleField97_ = value; + } + } + + /// Field number for the "double_field_65" field. + public const int DoubleField65FieldNumber = 65; + private double doubleField65_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField65 { + get { return doubleField65_; } + set { + doubleField65_ = value; + } + } + + /// Field number for the "double_field_66" field. + public const int DoubleField66FieldNumber = 66; + private double doubleField66_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField66 { + get { return doubleField66_; } + set { + doubleField66_ = value; + } + } + + /// Field number for the "double_field_7" field. + public const int DoubleField7FieldNumber = 7; + private double doubleField7_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField7 { + get { return doubleField7_; } + set { + doubleField7_ = value; + } + } + + /// Field number for the "double_field_62" field. + public const int DoubleField62FieldNumber = 62; + private double doubleField62_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField62 { + get { return doubleField62_; } + set { + doubleField62_ = value; + } + } + + /// Field number for the "double_field_118" field. + public const int DoubleField118FieldNumber = 118; + private double doubleField118_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField118 { + get { return doubleField118_; } + set { + doubleField118_ = value; + } + } + + /// Field number for the "double_field_119" field. + public const int DoubleField119FieldNumber = 119; + private double doubleField119_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField119 { + get { return doubleField119_; } + set { + doubleField119_ = value; + } + } + + /// Field number for the "double_field_67" field. + public const int DoubleField67FieldNumber = 67; + private double doubleField67_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField67 { + get { return doubleField67_; } + set { + doubleField67_ = value; + } + } + + /// Field number for the "double_field_120" field. + public const int DoubleField120FieldNumber = 120; + private double doubleField120_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField120 { + get { return doubleField120_; } + set { + doubleField120_ = value; + } + } + + /// Field number for the "double_field_121" field. + public const int DoubleField121FieldNumber = 121; + private double doubleField121_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField121 { + get { return doubleField121_; } + set { + doubleField121_ = value; + } + } + + /// Field number for the "double_field_122" field. + public const int DoubleField122FieldNumber = 122; + private double doubleField122_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField122 { + get { return doubleField122_; } + set { + doubleField122_ = value; + } + } + + /// Field number for the "double_field_123" field. + public const int DoubleField123FieldNumber = 123; + private double doubleField123_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField123 { + get { return doubleField123_; } + set { + doubleField123_ = value; + } + } + + /// Field number for the "double_field_124" field. + public const int DoubleField124FieldNumber = 124; + private double doubleField124_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField124 { + get { return doubleField124_; } + set { + doubleField124_ = value; + } + } + + /// Field number for the "double_field_8" field. + public const int DoubleField8FieldNumber = 8; + private double doubleField8_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField8 { + get { return doubleField8_; } + set { + doubleField8_ = value; + } + } + + /// Field number for the "double_field_9" field. + public const int DoubleField9FieldNumber = 9; + private double doubleField9_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField9 { + get { return doubleField9_; } + set { + doubleField9_ = value; + } + } + + /// Field number for the "double_field_98" field. + public const int DoubleField98FieldNumber = 98; + private double doubleField98_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField98 { + get { return doubleField98_; } + set { + doubleField98_ = value; + } + } + + /// Field number for the "double_field_10" field. + public const int DoubleField10FieldNumber = 10; + private double doubleField10_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField10 { + get { return doubleField10_; } + set { + doubleField10_ = value; + } + } + + /// Field number for the "double_field_11" field. + public const int DoubleField11FieldNumber = 11; + private double doubleField11_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField11 { + get { return doubleField11_; } + set { + doubleField11_ = value; + } + } + + /// Field number for the "double_field_99" field. + public const int DoubleField99FieldNumber = 99; + private double doubleField99_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField99 { + get { return doubleField99_; } + set { + doubleField99_ = value; + } + } + + /// Field number for the "double_field_84" field. + public const int DoubleField84FieldNumber = 84; + private double doubleField84_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField84 { + get { return doubleField84_; } + set { + doubleField84_ = value; + } + } + + /// Field number for the "double_field_14" field. + public const int DoubleField14FieldNumber = 14; + private double doubleField14_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField14 { + get { return doubleField14_; } + set { + doubleField14_ = value; + } + } + + /// Field number for the "double_field_77" field. + public const int DoubleField77FieldNumber = 77; + private double doubleField77_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField77 { + get { return doubleField77_; } + set { + doubleField77_ = value; + } + } + + /// Field number for the "double_field_15" field. + public const int DoubleField15FieldNumber = 15; + private double doubleField15_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField15 { + get { return doubleField15_; } + set { + doubleField15_ = value; + } + } + + /// Field number for the "int64_field_19" field. + public const int Int64Field19FieldNumber = 19; + private long int64Field19_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field19 { + get { return int64Field19_; } + set { + int64Field19_ = value; + } + } + + /// Field number for the "int64_field_115" field. + public const int Int64Field115FieldNumber = 115; + private long int64Field115_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field115 { + get { return int64Field115_; } + set { + int64Field115_ = value; + } + } + + /// Field number for the "double_field_116" field. + public const int DoubleField116FieldNumber = 116; + private double doubleField116_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField116 { + get { return doubleField116_; } + set { + doubleField116_ = value; + } + } + + /// Field number for the "int64_field_117" field. + public const int Int64Field117FieldNumber = 117; + private long int64Field117_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field117 { + get { return int64Field117_; } + set { + int64Field117_ = value; + } + } + + /// Field number for the "double_field_20" field. + public const int DoubleField20FieldNumber = 20; + private double doubleField20_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField20 { + get { return doubleField20_; } + set { + doubleField20_ = value; + } + } + + /// Field number for the "double_field_21" field. + public const int DoubleField21FieldNumber = 21; + private double doubleField21_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField21 { + get { return doubleField21_; } + set { + doubleField21_ = value; + } + } + + /// Field number for the "string_field_73" field. + public const int StringField73FieldNumber = 73; + private string stringField73_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string StringField73 { + get { return stringField73_; } + set { + stringField73_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "string_field_74" field. + public const int StringField74FieldNumber = 74; + private string stringField74_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string StringField74 { + get { return stringField74_; } + set { + stringField74_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "double_field_22" field. + public const int DoubleField22FieldNumber = 22; + private double doubleField22_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField22 { + get { return doubleField22_; } + set { + doubleField22_ = value; + } + } + + /// Field number for the "double_field_69" field. + public const int DoubleField69FieldNumber = 69; + private double doubleField69_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField69 { + get { return doubleField69_; } + set { + doubleField69_ = value; + } + } + + /// Field number for the "double_field_70" field. + public const int DoubleField70FieldNumber = 70; + private double doubleField70_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField70 { + get { return doubleField70_; } + set { + doubleField70_ = value; + } + } + + /// Field number for the "double_field_71" field. + public const int DoubleField71FieldNumber = 71; + private double doubleField71_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField71 { + get { return doubleField71_; } + set { + doubleField71_ = value; + } + } + + /// Field number for the "double_field_72" field. + public const int DoubleField72FieldNumber = 72; + private double doubleField72_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField72 { + get { return doubleField72_; } + set { + doubleField72_ = value; + } + } + + /// Field number for the "double_field_25" field. + public const int DoubleField25FieldNumber = 25; + private double doubleField25_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField25 { + get { return doubleField25_; } + set { + doubleField25_ = value; + } + } + + /// Field number for the "int64_field_26" field. + public const int Int64Field26FieldNumber = 26; + private long int64Field26_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field26 { + get { return int64Field26_; } + set { + int64Field26_ = value; + } + } + + /// Field number for the "double_field_68" field. + public const int DoubleField68FieldNumber = 68; + private double doubleField68_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField68 { + get { return doubleField68_; } + set { + doubleField68_ = value; + } + } + + /// Field number for the "double_field_28" field. + public const int DoubleField28FieldNumber = 28; + private double doubleField28_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField28 { + get { return doubleField28_; } + set { + doubleField28_ = value; + } + } + + /// Field number for the "double_field_106" field. + public const int DoubleField106FieldNumber = 106; + private double doubleField106_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField106 { + get { return doubleField106_; } + set { + doubleField106_ = value; + } + } + + /// Field number for the "double_field_29" field. + public const int DoubleField29FieldNumber = 29; + private double doubleField29_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField29 { + get { return doubleField29_; } + set { + doubleField29_ = value; + } + } + + /// Field number for the "double_field_30" field. + public const int DoubleField30FieldNumber = 30; + private double doubleField30_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField30 { + get { return doubleField30_; } + set { + doubleField30_ = value; + } + } + + /// Field number for the "double_field_101" field. + public const int DoubleField101FieldNumber = 101; + private double doubleField101_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField101 { + get { return doubleField101_; } + set { + doubleField101_ = value; + } + } + + /// Field number for the "double_field_102" field. + public const int DoubleField102FieldNumber = 102; + private double doubleField102_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField102 { + get { return doubleField102_; } + set { + doubleField102_ = value; + } + } + + /// Field number for the "double_field_103" field. + public const int DoubleField103FieldNumber = 103; + private double doubleField103_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField103 { + get { return doubleField103_; } + set { + doubleField103_ = value; + } + } + + /// Field number for the "double_field_104" field. + public const int DoubleField104FieldNumber = 104; + private double doubleField104_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField104 { + get { return doubleField104_; } + set { + doubleField104_ = value; + } + } + + /// Field number for the "double_field_105" field. + public const int DoubleField105FieldNumber = 105; + private double doubleField105_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField105 { + get { return doubleField105_; } + set { + doubleField105_ = value; + } + } + + /// Field number for the "double_field_31" field. + public const int DoubleField31FieldNumber = 31; + private double doubleField31_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField31 { + get { return doubleField31_; } + set { + doubleField31_ = value; + } + } + + /// Field number for the "int64_field_32" field. + public const int Int64Field32FieldNumber = 32; + private long int64Field32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field32 { + get { return int64Field32_; } + set { + int64Field32_ = value; + } + } + + /// Field number for the "double_field_75" field. + public const int DoubleField75FieldNumber = 75; + private double doubleField75_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField75 { + get { return doubleField75_; } + set { + doubleField75_ = value; + } + } + + /// Field number for the "double_field_129" field. + public const int DoubleField129FieldNumber = 129; + private double doubleField129_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField129 { + get { return doubleField129_; } + set { + doubleField129_ = value; + } + } + + /// Field number for the "enum_field_80" field. + public const int EnumField80FieldNumber = 80; + private int enumField80_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int EnumField80 { + get { return enumField80_; } + set { + enumField80_ = value; + } + } + + /// Field number for the "enum_field_81" field. + public const int EnumField81FieldNumber = 81; + private int enumField81_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int EnumField81 { + get { return enumField81_; } + set { + enumField81_ = value; + } + } + + /// Field number for the "int64_field_82" field. + public const int Int64Field82FieldNumber = 82; + private long int64Field82_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field82 { + get { return int64Field82_; } + set { + int64Field82_ = value; + } + } + + /// Field number for the "enum_field_83" field. + public const int EnumField83FieldNumber = 83; + private int enumField83_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int EnumField83 { + get { return enumField83_; } + set { + enumField83_ = value; + } + } + + /// Field number for the "int64_field_85" field. + public const int Int64Field85FieldNumber = 85; + private long int64Field85_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field85 { + get { return int64Field85_; } + set { + int64Field85_ = value; + } + } + + /// Field number for the "int64_field_86" field. + public const int Int64Field86FieldNumber = 86; + private long int64Field86_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field86 { + get { return int64Field86_; } + set { + int64Field86_ = value; + } + } + + /// Field number for the "int64_field_87" field. + public const int Int64Field87FieldNumber = 87; + private long int64Field87_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field87 { + get { return int64Field87_; } + set { + int64Field87_ = value; + } + } + + /// Field number for the "int64_field_125" field. + public const int Int64Field125FieldNumber = 125; + private long int64Field125_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field125 { + get { return int64Field125_; } + set { + int64Field125_ = value; + } + } + + /// Field number for the "int64_field_37" field. + public const int Int64Field37FieldNumber = 37; + private long int64Field37_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field37 { + get { return int64Field37_; } + set { + int64Field37_ = value; + } + } + + /// Field number for the "double_field_38" field. + public const int DoubleField38FieldNumber = 38; + private double doubleField38_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField38 { + get { return doubleField38_; } + set { + doubleField38_ = value; + } + } + + /// Field number for the "interactions" field. + public const int InteractionsFieldNumber = 39; + private long interactions_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Interactions { + get { return interactions_; } + set { + interactions_ = value; + } + } + + /// Field number for the "repeated_int_field_100" field. + public const int RepeatedIntField100FieldNumber = 100; + private static readonly pb::FieldCodec _repeated_repeatedIntField100_codec + = pb::FieldCodec.ForInt32(802); + private readonly pbc::RepeatedField repeatedIntField100_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedIntField100 { + get { return repeatedIntField100_; } + } + + /// Field number for the "double_field_40" field. + public const int DoubleField40FieldNumber = 40; + private double doubleField40_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField40 { + get { return doubleField40_; } + set { + doubleField40_ = value; + } + } + + /// Field number for the "int64_field_41" field. + public const int Int64Field41FieldNumber = 41; + private long int64Field41_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field41 { + get { return int64Field41_; } + set { + int64Field41_ = value; + } + } + + /// Field number for the "int64_field_126" field. + public const int Int64Field126FieldNumber = 126; + private long int64Field126_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field126 { + get { return int64Field126_; } + set { + int64Field126_ = value; + } + } + + /// Field number for the "int64_field_127" field. + public const int Int64Field127FieldNumber = 127; + private long int64Field127_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field127 { + get { return int64Field127_; } + set { + int64Field127_ = value; + } + } + + /// Field number for the "double_field_128" field. + public const int DoubleField128FieldNumber = 128; + private double doubleField128_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField128 { + get { return doubleField128_; } + set { + doubleField128_ = value; + } + } + + /// Field number for the "double_field_109" field. + public const int DoubleField109FieldNumber = 109; + private double doubleField109_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField109 { + get { return doubleField109_; } + set { + doubleField109_ = value; + } + } + + /// Field number for the "int64_field_110" field. + public const int Int64Field110FieldNumber = 110; + private long int64Field110_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field110 { + get { return int64Field110_; } + set { + int64Field110_ = value; + } + } + + /// Field number for the "double_field_111" field. + public const int DoubleField111FieldNumber = 111; + private double doubleField111_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField111 { + get { return doubleField111_; } + set { + doubleField111_ = value; + } + } + + /// Field number for the "int64_field_112" field. + public const int Int64Field112FieldNumber = 112; + private long int64Field112_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field112 { + get { return int64Field112_; } + set { + int64Field112_ = value; + } + } + + /// Field number for the "double_field_113" field. + public const int DoubleField113FieldNumber = 113; + private double doubleField113_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField113 { + get { return doubleField113_; } + set { + doubleField113_ = value; + } + } + + /// Field number for the "int64_field_114" field. + public const int Int64Field114FieldNumber = 114; + private long int64Field114_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field114 { + get { return int64Field114_; } + set { + int64Field114_ = value; + } + } + + /// Field number for the "double_field_42" field. + public const int DoubleField42FieldNumber = 42; + private double doubleField42_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField42 { + get { return doubleField42_; } + set { + doubleField42_ = value; + } + } + + /// Field number for the "int64_field_43" field. + public const int Int64Field43FieldNumber = 43; + private long int64Field43_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field43 { + get { return int64Field43_; } + set { + int64Field43_ = value; + } + } + + /// Field number for the "int64_field_44" field. + public const int Int64Field44FieldNumber = 44; + private long int64Field44_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field44 { + get { return int64Field44_; } + set { + int64Field44_ = value; + } + } + + /// Field number for the "double_field_45" field. + public const int DoubleField45FieldNumber = 45; + private double doubleField45_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField45 { + get { return doubleField45_; } + set { + doubleField45_ = value; + } + } + + /// Field number for the "double_field_46" field. + public const int DoubleField46FieldNumber = 46; + private double doubleField46_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField46 { + get { return doubleField46_; } + set { + doubleField46_ = value; + } + } + + /// Field number for the "double_field_78" field. + public const int DoubleField78FieldNumber = 78; + private double doubleField78_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField78 { + get { return doubleField78_; } + set { + doubleField78_ = value; + } + } + + /// Field number for the "double_field_88" field. + public const int DoubleField88FieldNumber = 88; + private double doubleField88_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField88 { + get { return doubleField88_; } + set { + doubleField88_ = value; + } + } + + /// Field number for the "double_field_47" field. + public const int DoubleField47FieldNumber = 47; + private double doubleField47_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField47 { + get { return doubleField47_; } + set { + doubleField47_ = value; + } + } + + /// Field number for the "double_field_89" field. + public const int DoubleField89FieldNumber = 89; + private double doubleField89_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField89 { + get { return doubleField89_; } + set { + doubleField89_ = value; + } + } + + /// Field number for the "double_field_48" field. + public const int DoubleField48FieldNumber = 48; + private double doubleField48_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField48 { + get { return doubleField48_; } + set { + doubleField48_ = value; + } + } + + /// Field number for the "double_field_49" field. + public const int DoubleField49FieldNumber = 49; + private double doubleField49_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField49 { + get { return doubleField49_; } + set { + doubleField49_ = value; + } + } + + /// Field number for the "double_field_50" field. + public const int DoubleField50FieldNumber = 50; + private double doubleField50_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField50 { + get { return doubleField50_; } + set { + doubleField50_ = value; + } + } + + /// Field number for the "double_field_90" field. + public const int DoubleField90FieldNumber = 90; + private double doubleField90_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField90 { + get { return doubleField90_; } + set { + doubleField90_ = value; + } + } + + /// Field number for the "double_field_51" field. + public const int DoubleField51FieldNumber = 51; + private double doubleField51_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField51 { + get { return doubleField51_; } + set { + doubleField51_ = value; + } + } + + /// Field number for the "double_field_91" field. + public const int DoubleField91FieldNumber = 91; + private double doubleField91_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField91 { + get { return doubleField91_; } + set { + doubleField91_ = value; + } + } + + /// Field number for the "double_field_92" field. + public const int DoubleField92FieldNumber = 92; + private double doubleField92_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField92 { + get { return doubleField92_; } + set { + doubleField92_ = value; + } + } + + /// Field number for the "int64_field_107" field. + public const int Int64Field107FieldNumber = 107; + private long int64Field107_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field107 { + get { return int64Field107_; } + set { + int64Field107_ = value; + } + } + + /// Field number for the "double_field_93" field. + public const int DoubleField93FieldNumber = 93; + private double doubleField93_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField93 { + get { return doubleField93_; } + set { + doubleField93_ = value; + } + } + + /// Field number for the "double_field_108" field. + public const int DoubleField108FieldNumber = 108; + private double doubleField108_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField108 { + get { return doubleField108_; } + set { + doubleField108_ = value; + } + } + + /// Field number for the "double_field_52" field. + public const int DoubleField52FieldNumber = 52; + private double doubleField52_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField52 { + get { return doubleField52_; } + set { + doubleField52_ = value; + } + } + + /// Field number for the "double_field_53" field. + public const int DoubleField53FieldNumber = 53; + private double doubleField53_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField53 { + get { return doubleField53_; } + set { + doubleField53_ = value; + } + } + + /// Field number for the "double_field_94" field. + public const int DoubleField94FieldNumber = 94; + private double doubleField94_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField94 { + get { return doubleField94_; } + set { + doubleField94_ = value; + } + } + + /// Field number for the "double_field_54" field. + public const int DoubleField54FieldNumber = 54; + private double doubleField54_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField54 { + get { return doubleField54_; } + set { + doubleField54_ = value; + } + } + + /// Field number for the "double_field_55" field. + public const int DoubleField55FieldNumber = 55; + private double doubleField55_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField55 { + get { return doubleField55_; } + set { + doubleField55_ = value; + } + } + + /// Field number for the "double_field_56" field. + public const int DoubleField56FieldNumber = 56; + private double doubleField56_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField56 { + get { return doubleField56_; } + set { + doubleField56_ = value; + } + } + + /// Field number for the "double_field_57" field. + public const int DoubleField57FieldNumber = 57; + private double doubleField57_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField57 { + get { return doubleField57_; } + set { + doubleField57_ = value; + } + } + + /// Field number for the "double_field_58" field. + public const int DoubleField58FieldNumber = 58; + private double doubleField58_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DoubleField58 { + get { return doubleField58_; } + set { + doubleField58_ = value; + } + } + + /// Field number for the "int64_field_59" field. + public const int Int64Field59FieldNumber = 59; + private long int64Field59_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field59 { + get { return int64Field59_; } + set { + int64Field59_ = value; + } + } + + /// Field number for the "int64_field_60" field. + public const int Int64Field60FieldNumber = 60; + private long int64Field60_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Int64Field60 { + get { return int64Field60_; } + set { + int64Field60_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ManyPrimitiveFieldsMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ManyPrimitiveFieldsMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField95, other.DoubleField95)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField1, other.DoubleField1)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField79, other.DoubleField79)) return false; + if (Int64Field2 != other.Int64Field2) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField96, other.DoubleField96)) return false; + if (Int64Field3 != other.Int64Field3) return false; + if (Int64Field4 != other.Int64Field4) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField97, other.DoubleField97)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField65, other.DoubleField65)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField66, other.DoubleField66)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField7, other.DoubleField7)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField62, other.DoubleField62)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField118, other.DoubleField118)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField119, other.DoubleField119)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField67, other.DoubleField67)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField120, other.DoubleField120)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField121, other.DoubleField121)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField122, other.DoubleField122)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField123, other.DoubleField123)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField124, other.DoubleField124)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField8, other.DoubleField8)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField9, other.DoubleField9)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField98, other.DoubleField98)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField10, other.DoubleField10)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField11, other.DoubleField11)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField99, other.DoubleField99)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField84, other.DoubleField84)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField14, other.DoubleField14)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField77, other.DoubleField77)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField15, other.DoubleField15)) return false; + if (Int64Field19 != other.Int64Field19) return false; + if (Int64Field115 != other.Int64Field115) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField116, other.DoubleField116)) return false; + if (Int64Field117 != other.Int64Field117) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField20, other.DoubleField20)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField21, other.DoubleField21)) return false; + if (StringField73 != other.StringField73) return false; + if (StringField74 != other.StringField74) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField22, other.DoubleField22)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField69, other.DoubleField69)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField70, other.DoubleField70)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField71, other.DoubleField71)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField72, other.DoubleField72)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField25, other.DoubleField25)) return false; + if (Int64Field26 != other.Int64Field26) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField68, other.DoubleField68)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField28, other.DoubleField28)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField106, other.DoubleField106)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField29, other.DoubleField29)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField30, other.DoubleField30)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField101, other.DoubleField101)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField102, other.DoubleField102)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField103, other.DoubleField103)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField104, other.DoubleField104)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField105, other.DoubleField105)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField31, other.DoubleField31)) return false; + if (Int64Field32 != other.Int64Field32) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField75, other.DoubleField75)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField129, other.DoubleField129)) return false; + if (EnumField80 != other.EnumField80) return false; + if (EnumField81 != other.EnumField81) return false; + if (Int64Field82 != other.Int64Field82) return false; + if (EnumField83 != other.EnumField83) return false; + if (Int64Field85 != other.Int64Field85) return false; + if (Int64Field86 != other.Int64Field86) return false; + if (Int64Field87 != other.Int64Field87) return false; + if (Int64Field125 != other.Int64Field125) return false; + if (Int64Field37 != other.Int64Field37) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField38, other.DoubleField38)) return false; + if (Interactions != other.Interactions) return false; + if(!repeatedIntField100_.Equals(other.repeatedIntField100_)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField40, other.DoubleField40)) return false; + if (Int64Field41 != other.Int64Field41) return false; + if (Int64Field126 != other.Int64Field126) return false; + if (Int64Field127 != other.Int64Field127) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField128, other.DoubleField128)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField109, other.DoubleField109)) return false; + if (Int64Field110 != other.Int64Field110) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField111, other.DoubleField111)) return false; + if (Int64Field112 != other.Int64Field112) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField113, other.DoubleField113)) return false; + if (Int64Field114 != other.Int64Field114) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField42, other.DoubleField42)) return false; + if (Int64Field43 != other.Int64Field43) return false; + if (Int64Field44 != other.Int64Field44) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField45, other.DoubleField45)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField46, other.DoubleField46)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField78, other.DoubleField78)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField88, other.DoubleField88)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField47, other.DoubleField47)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField89, other.DoubleField89)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField48, other.DoubleField48)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField49, other.DoubleField49)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField50, other.DoubleField50)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField90, other.DoubleField90)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField51, other.DoubleField51)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField91, other.DoubleField91)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField92, other.DoubleField92)) return false; + if (Int64Field107 != other.Int64Field107) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField93, other.DoubleField93)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField108, other.DoubleField108)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField52, other.DoubleField52)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField53, other.DoubleField53)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField94, other.DoubleField94)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField54, other.DoubleField54)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField55, other.DoubleField55)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField56, other.DoubleField56)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField57, other.DoubleField57)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField58, other.DoubleField58)) return false; + if (Int64Field59 != other.Int64Field59) return false; + if (Int64Field60 != other.Int64Field60) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (DoubleField95 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField95); + if (DoubleField1 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField1); + if (DoubleField79 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField79); + if (Int64Field2 != 0L) hash ^= Int64Field2.GetHashCode(); + if (DoubleField96 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField96); + if (Int64Field3 != 0L) hash ^= Int64Field3.GetHashCode(); + if (Int64Field4 != 0L) hash ^= Int64Field4.GetHashCode(); + if (DoubleField97 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField97); + if (DoubleField65 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField65); + if (DoubleField66 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField66); + if (DoubleField7 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField7); + if (DoubleField62 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField62); + if (DoubleField118 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField118); + if (DoubleField119 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField119); + if (DoubleField67 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField67); + if (DoubleField120 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField120); + if (DoubleField121 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField121); + if (DoubleField122 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField122); + if (DoubleField123 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField123); + if (DoubleField124 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField124); + if (DoubleField8 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField8); + if (DoubleField9 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField9); + if (DoubleField98 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField98); + if (DoubleField10 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField10); + if (DoubleField11 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField11); + if (DoubleField99 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField99); + if (DoubleField84 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField84); + if (DoubleField14 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField14); + if (DoubleField77 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField77); + if (DoubleField15 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField15); + if (Int64Field19 != 0L) hash ^= Int64Field19.GetHashCode(); + if (Int64Field115 != 0L) hash ^= Int64Field115.GetHashCode(); + if (DoubleField116 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField116); + if (Int64Field117 != 0L) hash ^= Int64Field117.GetHashCode(); + if (DoubleField20 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField20); + if (DoubleField21 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField21); + if (StringField73.Length != 0) hash ^= StringField73.GetHashCode(); + if (StringField74.Length != 0) hash ^= StringField74.GetHashCode(); + if (DoubleField22 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField22); + if (DoubleField69 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField69); + if (DoubleField70 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField70); + if (DoubleField71 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField71); + if (DoubleField72 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField72); + if (DoubleField25 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField25); + if (Int64Field26 != 0L) hash ^= Int64Field26.GetHashCode(); + if (DoubleField68 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField68); + if (DoubleField28 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField28); + if (DoubleField106 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField106); + if (DoubleField29 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField29); + if (DoubleField30 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField30); + if (DoubleField101 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField101); + if (DoubleField102 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField102); + if (DoubleField103 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField103); + if (DoubleField104 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField104); + if (DoubleField105 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField105); + if (DoubleField31 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField31); + if (Int64Field32 != 0L) hash ^= Int64Field32.GetHashCode(); + if (DoubleField75 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField75); + if (DoubleField129 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField129); + if (EnumField80 != 0) hash ^= EnumField80.GetHashCode(); + if (EnumField81 != 0) hash ^= EnumField81.GetHashCode(); + if (Int64Field82 != 0L) hash ^= Int64Field82.GetHashCode(); + if (EnumField83 != 0) hash ^= EnumField83.GetHashCode(); + if (Int64Field85 != 0L) hash ^= Int64Field85.GetHashCode(); + if (Int64Field86 != 0L) hash ^= Int64Field86.GetHashCode(); + if (Int64Field87 != 0L) hash ^= Int64Field87.GetHashCode(); + if (Int64Field125 != 0L) hash ^= Int64Field125.GetHashCode(); + if (Int64Field37 != 0L) hash ^= Int64Field37.GetHashCode(); + if (DoubleField38 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField38); + if (Interactions != 0L) hash ^= Interactions.GetHashCode(); + hash ^= repeatedIntField100_.GetHashCode(); + if (DoubleField40 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField40); + if (Int64Field41 != 0L) hash ^= Int64Field41.GetHashCode(); + if (Int64Field126 != 0L) hash ^= Int64Field126.GetHashCode(); + if (Int64Field127 != 0L) hash ^= Int64Field127.GetHashCode(); + if (DoubleField128 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField128); + if (DoubleField109 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField109); + if (Int64Field110 != 0L) hash ^= Int64Field110.GetHashCode(); + if (DoubleField111 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField111); + if (Int64Field112 != 0L) hash ^= Int64Field112.GetHashCode(); + if (DoubleField113 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField113); + if (Int64Field114 != 0L) hash ^= Int64Field114.GetHashCode(); + if (DoubleField42 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField42); + if (Int64Field43 != 0L) hash ^= Int64Field43.GetHashCode(); + if (Int64Field44 != 0L) hash ^= Int64Field44.GetHashCode(); + if (DoubleField45 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField45); + if (DoubleField46 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField46); + if (DoubleField78 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField78); + if (DoubleField88 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField88); + if (DoubleField47 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField47); + if (DoubleField89 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField89); + if (DoubleField48 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField48); + if (DoubleField49 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField49); + if (DoubleField50 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField50); + if (DoubleField90 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField90); + if (DoubleField51 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField51); + if (DoubleField91 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField91); + if (DoubleField92 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField92); + if (Int64Field107 != 0L) hash ^= Int64Field107.GetHashCode(); + if (DoubleField93 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField93); + if (DoubleField108 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField108); + if (DoubleField52 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField52); + if (DoubleField53 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField53); + if (DoubleField94 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField94); + if (DoubleField54 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField54); + if (DoubleField55 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField55); + if (DoubleField56 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField56); + if (DoubleField57 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField57); + if (DoubleField58 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField58); + if (Int64Field59 != 0L) hash ^= Int64Field59.GetHashCode(); + if (Int64Field60 != 0L) hash ^= Int64Field60.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (DoubleField1 != 0D) { + output.WriteRawTag(9); + output.WriteDouble(DoubleField1); + } + if (Int64Field2 != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Int64Field2); + } + if (Int64Field3 != 0L) { + output.WriteRawTag(24); + output.WriteInt64(Int64Field3); + } + if (Int64Field4 != 0L) { + output.WriteRawTag(32); + output.WriteInt64(Int64Field4); + } + if (DoubleField7 != 0D) { + output.WriteRawTag(57); + output.WriteDouble(DoubleField7); + } + if (DoubleField8 != 0D) { + output.WriteRawTag(65); + output.WriteDouble(DoubleField8); + } + if (DoubleField9 != 0D) { + output.WriteRawTag(73); + output.WriteDouble(DoubleField9); + } + if (DoubleField10 != 0D) { + output.WriteRawTag(81); + output.WriteDouble(DoubleField10); + } + if (DoubleField11 != 0D) { + output.WriteRawTag(89); + output.WriteDouble(DoubleField11); + } + if (DoubleField14 != 0D) { + output.WriteRawTag(113); + output.WriteDouble(DoubleField14); + } + if (DoubleField15 != 0D) { + output.WriteRawTag(121); + output.WriteDouble(DoubleField15); + } + if (Int64Field19 != 0L) { + output.WriteRawTag(152, 1); + output.WriteInt64(Int64Field19); + } + if (DoubleField20 != 0D) { + output.WriteRawTag(161, 1); + output.WriteDouble(DoubleField20); + } + if (DoubleField21 != 0D) { + output.WriteRawTag(169, 1); + output.WriteDouble(DoubleField21); + } + if (DoubleField22 != 0D) { + output.WriteRawTag(177, 1); + output.WriteDouble(DoubleField22); + } + if (DoubleField25 != 0D) { + output.WriteRawTag(201, 1); + output.WriteDouble(DoubleField25); + } + if (Int64Field26 != 0L) { + output.WriteRawTag(208, 1); + output.WriteInt64(Int64Field26); + } + if (DoubleField28 != 0D) { + output.WriteRawTag(225, 1); + output.WriteDouble(DoubleField28); + } + if (DoubleField29 != 0D) { + output.WriteRawTag(233, 1); + output.WriteDouble(DoubleField29); + } + if (DoubleField30 != 0D) { + output.WriteRawTag(241, 1); + output.WriteDouble(DoubleField30); + } + if (DoubleField31 != 0D) { + output.WriteRawTag(249, 1); + output.WriteDouble(DoubleField31); + } + if (Int64Field32 != 0L) { + output.WriteRawTag(128, 2); + output.WriteInt64(Int64Field32); + } + if (Int64Field37 != 0L) { + output.WriteRawTag(168, 2); + output.WriteInt64(Int64Field37); + } + if (DoubleField38 != 0D) { + output.WriteRawTag(177, 2); + output.WriteDouble(DoubleField38); + } + if (Interactions != 0L) { + output.WriteRawTag(184, 2); + output.WriteInt64(Interactions); + } + if (DoubleField40 != 0D) { + output.WriteRawTag(193, 2); + output.WriteDouble(DoubleField40); + } + if (Int64Field41 != 0L) { + output.WriteRawTag(200, 2); + output.WriteInt64(Int64Field41); + } + if (DoubleField42 != 0D) { + output.WriteRawTag(209, 2); + output.WriteDouble(DoubleField42); + } + if (Int64Field43 != 0L) { + output.WriteRawTag(216, 2); + output.WriteInt64(Int64Field43); + } + if (Int64Field44 != 0L) { + output.WriteRawTag(224, 2); + output.WriteInt64(Int64Field44); + } + if (DoubleField45 != 0D) { + output.WriteRawTag(233, 2); + output.WriteDouble(DoubleField45); + } + if (DoubleField46 != 0D) { + output.WriteRawTag(241, 2); + output.WriteDouble(DoubleField46); + } + if (DoubleField47 != 0D) { + output.WriteRawTag(249, 2); + output.WriteDouble(DoubleField47); + } + if (DoubleField48 != 0D) { + output.WriteRawTag(129, 3); + output.WriteDouble(DoubleField48); + } + if (DoubleField49 != 0D) { + output.WriteRawTag(137, 3); + output.WriteDouble(DoubleField49); + } + if (DoubleField50 != 0D) { + output.WriteRawTag(145, 3); + output.WriteDouble(DoubleField50); + } + if (DoubleField51 != 0D) { + output.WriteRawTag(153, 3); + output.WriteDouble(DoubleField51); + } + if (DoubleField52 != 0D) { + output.WriteRawTag(161, 3); + output.WriteDouble(DoubleField52); + } + if (DoubleField53 != 0D) { + output.WriteRawTag(169, 3); + output.WriteDouble(DoubleField53); + } + if (DoubleField54 != 0D) { + output.WriteRawTag(177, 3); + output.WriteDouble(DoubleField54); + } + if (DoubleField55 != 0D) { + output.WriteRawTag(185, 3); + output.WriteDouble(DoubleField55); + } + if (DoubleField56 != 0D) { + output.WriteRawTag(193, 3); + output.WriteDouble(DoubleField56); + } + if (DoubleField57 != 0D) { + output.WriteRawTag(201, 3); + output.WriteDouble(DoubleField57); + } + if (DoubleField58 != 0D) { + output.WriteRawTag(209, 3); + output.WriteDouble(DoubleField58); + } + if (Int64Field59 != 0L) { + output.WriteRawTag(216, 3); + output.WriteInt64(Int64Field59); + } + if (Int64Field60 != 0L) { + output.WriteRawTag(224, 3); + output.WriteInt64(Int64Field60); + } + if (DoubleField62 != 0D) { + output.WriteRawTag(241, 3); + output.WriteDouble(DoubleField62); + } + if (DoubleField65 != 0D) { + output.WriteRawTag(137, 4); + output.WriteDouble(DoubleField65); + } + if (DoubleField66 != 0D) { + output.WriteRawTag(145, 4); + output.WriteDouble(DoubleField66); + } + if (DoubleField67 != 0D) { + output.WriteRawTag(153, 4); + output.WriteDouble(DoubleField67); + } + if (DoubleField68 != 0D) { + output.WriteRawTag(161, 4); + output.WriteDouble(DoubleField68); + } + if (DoubleField69 != 0D) { + output.WriteRawTag(169, 4); + output.WriteDouble(DoubleField69); + } + if (DoubleField70 != 0D) { + output.WriteRawTag(177, 4); + output.WriteDouble(DoubleField70); + } + if (DoubleField71 != 0D) { + output.WriteRawTag(185, 4); + output.WriteDouble(DoubleField71); + } + if (DoubleField72 != 0D) { + output.WriteRawTag(193, 4); + output.WriteDouble(DoubleField72); + } + if (StringField73.Length != 0) { + output.WriteRawTag(202, 4); + output.WriteString(StringField73); + } + if (StringField74.Length != 0) { + output.WriteRawTag(210, 4); + output.WriteString(StringField74); + } + if (DoubleField75 != 0D) { + output.WriteRawTag(217, 4); + output.WriteDouble(DoubleField75); + } + if (DoubleField77 != 0D) { + output.WriteRawTag(233, 4); + output.WriteDouble(DoubleField77); + } + if (DoubleField78 != 0D) { + output.WriteRawTag(241, 4); + output.WriteDouble(DoubleField78); + } + if (DoubleField79 != 0D) { + output.WriteRawTag(249, 4); + output.WriteDouble(DoubleField79); + } + if (EnumField80 != 0) { + output.WriteRawTag(128, 5); + output.WriteInt32(EnumField80); + } + if (EnumField81 != 0) { + output.WriteRawTag(136, 5); + output.WriteInt32(EnumField81); + } + if (Int64Field82 != 0L) { + output.WriteRawTag(144, 5); + output.WriteInt64(Int64Field82); + } + if (EnumField83 != 0) { + output.WriteRawTag(152, 5); + output.WriteInt32(EnumField83); + } + if (DoubleField84 != 0D) { + output.WriteRawTag(161, 5); + output.WriteDouble(DoubleField84); + } + if (Int64Field85 != 0L) { + output.WriteRawTag(168, 5); + output.WriteInt64(Int64Field85); + } + if (Int64Field86 != 0L) { + output.WriteRawTag(176, 5); + output.WriteInt64(Int64Field86); + } + if (Int64Field87 != 0L) { + output.WriteRawTag(184, 5); + output.WriteInt64(Int64Field87); + } + if (DoubleField88 != 0D) { + output.WriteRawTag(193, 5); + output.WriteDouble(DoubleField88); + } + if (DoubleField89 != 0D) { + output.WriteRawTag(201, 5); + output.WriteDouble(DoubleField89); + } + if (DoubleField90 != 0D) { + output.WriteRawTag(209, 5); + output.WriteDouble(DoubleField90); + } + if (DoubleField91 != 0D) { + output.WriteRawTag(217, 5); + output.WriteDouble(DoubleField91); + } + if (DoubleField92 != 0D) { + output.WriteRawTag(225, 5); + output.WriteDouble(DoubleField92); + } + if (DoubleField93 != 0D) { + output.WriteRawTag(233, 5); + output.WriteDouble(DoubleField93); + } + if (DoubleField94 != 0D) { + output.WriteRawTag(241, 5); + output.WriteDouble(DoubleField94); + } + if (DoubleField95 != 0D) { + output.WriteRawTag(249, 5); + output.WriteDouble(DoubleField95); + } + if (DoubleField96 != 0D) { + output.WriteRawTag(129, 6); + output.WriteDouble(DoubleField96); + } + if (DoubleField97 != 0D) { + output.WriteRawTag(137, 6); + output.WriteDouble(DoubleField97); + } + if (DoubleField98 != 0D) { + output.WriteRawTag(145, 6); + output.WriteDouble(DoubleField98); + } + if (DoubleField99 != 0D) { + output.WriteRawTag(153, 6); + output.WriteDouble(DoubleField99); + } + repeatedIntField100_.WriteTo(output, _repeated_repeatedIntField100_codec); + if (DoubleField101 != 0D) { + output.WriteRawTag(169, 6); + output.WriteDouble(DoubleField101); + } + if (DoubleField102 != 0D) { + output.WriteRawTag(177, 6); + output.WriteDouble(DoubleField102); + } + if (DoubleField103 != 0D) { + output.WriteRawTag(185, 6); + output.WriteDouble(DoubleField103); + } + if (DoubleField104 != 0D) { + output.WriteRawTag(193, 6); + output.WriteDouble(DoubleField104); + } + if (DoubleField105 != 0D) { + output.WriteRawTag(201, 6); + output.WriteDouble(DoubleField105); + } + if (DoubleField106 != 0D) { + output.WriteRawTag(209, 6); + output.WriteDouble(DoubleField106); + } + if (Int64Field107 != 0L) { + output.WriteRawTag(216, 6); + output.WriteInt64(Int64Field107); + } + if (DoubleField108 != 0D) { + output.WriteRawTag(225, 6); + output.WriteDouble(DoubleField108); + } + if (DoubleField109 != 0D) { + output.WriteRawTag(233, 6); + output.WriteDouble(DoubleField109); + } + if (Int64Field110 != 0L) { + output.WriteRawTag(240, 6); + output.WriteInt64(Int64Field110); + } + if (DoubleField111 != 0D) { + output.WriteRawTag(249, 6); + output.WriteDouble(DoubleField111); + } + if (Int64Field112 != 0L) { + output.WriteRawTag(128, 7); + output.WriteInt64(Int64Field112); + } + if (DoubleField113 != 0D) { + output.WriteRawTag(137, 7); + output.WriteDouble(DoubleField113); + } + if (Int64Field114 != 0L) { + output.WriteRawTag(144, 7); + output.WriteInt64(Int64Field114); + } + if (Int64Field115 != 0L) { + output.WriteRawTag(152, 7); + output.WriteInt64(Int64Field115); + } + if (DoubleField116 != 0D) { + output.WriteRawTag(161, 7); + output.WriteDouble(DoubleField116); + } + if (Int64Field117 != 0L) { + output.WriteRawTag(168, 7); + output.WriteInt64(Int64Field117); + } + if (DoubleField118 != 0D) { + output.WriteRawTag(177, 7); + output.WriteDouble(DoubleField118); + } + if (DoubleField119 != 0D) { + output.WriteRawTag(185, 7); + output.WriteDouble(DoubleField119); + } + if (DoubleField120 != 0D) { + output.WriteRawTag(193, 7); + output.WriteDouble(DoubleField120); + } + if (DoubleField121 != 0D) { + output.WriteRawTag(201, 7); + output.WriteDouble(DoubleField121); + } + if (DoubleField122 != 0D) { + output.WriteRawTag(209, 7); + output.WriteDouble(DoubleField122); + } + if (DoubleField123 != 0D) { + output.WriteRawTag(217, 7); + output.WriteDouble(DoubleField123); + } + if (DoubleField124 != 0D) { + output.WriteRawTag(225, 7); + output.WriteDouble(DoubleField124); + } + if (Int64Field125 != 0L) { + output.WriteRawTag(232, 7); + output.WriteInt64(Int64Field125); + } + if (Int64Field126 != 0L) { + output.WriteRawTag(240, 7); + output.WriteInt64(Int64Field126); + } + if (Int64Field127 != 0L) { + output.WriteRawTag(248, 7); + output.WriteInt64(Int64Field127); + } + if (DoubleField128 != 0D) { + output.WriteRawTag(129, 8); + output.WriteDouble(DoubleField128); + } + if (DoubleField129 != 0D) { + output.WriteRawTag(137, 8); + output.WriteDouble(DoubleField129); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (DoubleField1 != 0D) { + output.WriteRawTag(9); + output.WriteDouble(DoubleField1); + } + if (Int64Field2 != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Int64Field2); + } + if (Int64Field3 != 0L) { + output.WriteRawTag(24); + output.WriteInt64(Int64Field3); + } + if (Int64Field4 != 0L) { + output.WriteRawTag(32); + output.WriteInt64(Int64Field4); + } + if (DoubleField7 != 0D) { + output.WriteRawTag(57); + output.WriteDouble(DoubleField7); + } + if (DoubleField8 != 0D) { + output.WriteRawTag(65); + output.WriteDouble(DoubleField8); + } + if (DoubleField9 != 0D) { + output.WriteRawTag(73); + output.WriteDouble(DoubleField9); + } + if (DoubleField10 != 0D) { + output.WriteRawTag(81); + output.WriteDouble(DoubleField10); + } + if (DoubleField11 != 0D) { + output.WriteRawTag(89); + output.WriteDouble(DoubleField11); + } + if (DoubleField14 != 0D) { + output.WriteRawTag(113); + output.WriteDouble(DoubleField14); + } + if (DoubleField15 != 0D) { + output.WriteRawTag(121); + output.WriteDouble(DoubleField15); + } + if (Int64Field19 != 0L) { + output.WriteRawTag(152, 1); + output.WriteInt64(Int64Field19); + } + if (DoubleField20 != 0D) { + output.WriteRawTag(161, 1); + output.WriteDouble(DoubleField20); + } + if (DoubleField21 != 0D) { + output.WriteRawTag(169, 1); + output.WriteDouble(DoubleField21); + } + if (DoubleField22 != 0D) { + output.WriteRawTag(177, 1); + output.WriteDouble(DoubleField22); + } + if (DoubleField25 != 0D) { + output.WriteRawTag(201, 1); + output.WriteDouble(DoubleField25); + } + if (Int64Field26 != 0L) { + output.WriteRawTag(208, 1); + output.WriteInt64(Int64Field26); + } + if (DoubleField28 != 0D) { + output.WriteRawTag(225, 1); + output.WriteDouble(DoubleField28); + } + if (DoubleField29 != 0D) { + output.WriteRawTag(233, 1); + output.WriteDouble(DoubleField29); + } + if (DoubleField30 != 0D) { + output.WriteRawTag(241, 1); + output.WriteDouble(DoubleField30); + } + if (DoubleField31 != 0D) { + output.WriteRawTag(249, 1); + output.WriteDouble(DoubleField31); + } + if (Int64Field32 != 0L) { + output.WriteRawTag(128, 2); + output.WriteInt64(Int64Field32); + } + if (Int64Field37 != 0L) { + output.WriteRawTag(168, 2); + output.WriteInt64(Int64Field37); + } + if (DoubleField38 != 0D) { + output.WriteRawTag(177, 2); + output.WriteDouble(DoubleField38); + } + if (Interactions != 0L) { + output.WriteRawTag(184, 2); + output.WriteInt64(Interactions); + } + if (DoubleField40 != 0D) { + output.WriteRawTag(193, 2); + output.WriteDouble(DoubleField40); + } + if (Int64Field41 != 0L) { + output.WriteRawTag(200, 2); + output.WriteInt64(Int64Field41); + } + if (DoubleField42 != 0D) { + output.WriteRawTag(209, 2); + output.WriteDouble(DoubleField42); + } + if (Int64Field43 != 0L) { + output.WriteRawTag(216, 2); + output.WriteInt64(Int64Field43); + } + if (Int64Field44 != 0L) { + output.WriteRawTag(224, 2); + output.WriteInt64(Int64Field44); + } + if (DoubleField45 != 0D) { + output.WriteRawTag(233, 2); + output.WriteDouble(DoubleField45); + } + if (DoubleField46 != 0D) { + output.WriteRawTag(241, 2); + output.WriteDouble(DoubleField46); + } + if (DoubleField47 != 0D) { + output.WriteRawTag(249, 2); + output.WriteDouble(DoubleField47); + } + if (DoubleField48 != 0D) { + output.WriteRawTag(129, 3); + output.WriteDouble(DoubleField48); + } + if (DoubleField49 != 0D) { + output.WriteRawTag(137, 3); + output.WriteDouble(DoubleField49); + } + if (DoubleField50 != 0D) { + output.WriteRawTag(145, 3); + output.WriteDouble(DoubleField50); + } + if (DoubleField51 != 0D) { + output.WriteRawTag(153, 3); + output.WriteDouble(DoubleField51); + } + if (DoubleField52 != 0D) { + output.WriteRawTag(161, 3); + output.WriteDouble(DoubleField52); + } + if (DoubleField53 != 0D) { + output.WriteRawTag(169, 3); + output.WriteDouble(DoubleField53); + } + if (DoubleField54 != 0D) { + output.WriteRawTag(177, 3); + output.WriteDouble(DoubleField54); + } + if (DoubleField55 != 0D) { + output.WriteRawTag(185, 3); + output.WriteDouble(DoubleField55); + } + if (DoubleField56 != 0D) { + output.WriteRawTag(193, 3); + output.WriteDouble(DoubleField56); + } + if (DoubleField57 != 0D) { + output.WriteRawTag(201, 3); + output.WriteDouble(DoubleField57); + } + if (DoubleField58 != 0D) { + output.WriteRawTag(209, 3); + output.WriteDouble(DoubleField58); + } + if (Int64Field59 != 0L) { + output.WriteRawTag(216, 3); + output.WriteInt64(Int64Field59); + } + if (Int64Field60 != 0L) { + output.WriteRawTag(224, 3); + output.WriteInt64(Int64Field60); + } + if (DoubleField62 != 0D) { + output.WriteRawTag(241, 3); + output.WriteDouble(DoubleField62); + } + if (DoubleField65 != 0D) { + output.WriteRawTag(137, 4); + output.WriteDouble(DoubleField65); + } + if (DoubleField66 != 0D) { + output.WriteRawTag(145, 4); + output.WriteDouble(DoubleField66); + } + if (DoubleField67 != 0D) { + output.WriteRawTag(153, 4); + output.WriteDouble(DoubleField67); + } + if (DoubleField68 != 0D) { + output.WriteRawTag(161, 4); + output.WriteDouble(DoubleField68); + } + if (DoubleField69 != 0D) { + output.WriteRawTag(169, 4); + output.WriteDouble(DoubleField69); + } + if (DoubleField70 != 0D) { + output.WriteRawTag(177, 4); + output.WriteDouble(DoubleField70); + } + if (DoubleField71 != 0D) { + output.WriteRawTag(185, 4); + output.WriteDouble(DoubleField71); + } + if (DoubleField72 != 0D) { + output.WriteRawTag(193, 4); + output.WriteDouble(DoubleField72); + } + if (StringField73.Length != 0) { + output.WriteRawTag(202, 4); + output.WriteString(StringField73); + } + if (StringField74.Length != 0) { + output.WriteRawTag(210, 4); + output.WriteString(StringField74); + } + if (DoubleField75 != 0D) { + output.WriteRawTag(217, 4); + output.WriteDouble(DoubleField75); + } + if (DoubleField77 != 0D) { + output.WriteRawTag(233, 4); + output.WriteDouble(DoubleField77); + } + if (DoubleField78 != 0D) { + output.WriteRawTag(241, 4); + output.WriteDouble(DoubleField78); + } + if (DoubleField79 != 0D) { + output.WriteRawTag(249, 4); + output.WriteDouble(DoubleField79); + } + if (EnumField80 != 0) { + output.WriteRawTag(128, 5); + output.WriteInt32(EnumField80); + } + if (EnumField81 != 0) { + output.WriteRawTag(136, 5); + output.WriteInt32(EnumField81); + } + if (Int64Field82 != 0L) { + output.WriteRawTag(144, 5); + output.WriteInt64(Int64Field82); + } + if (EnumField83 != 0) { + output.WriteRawTag(152, 5); + output.WriteInt32(EnumField83); + } + if (DoubleField84 != 0D) { + output.WriteRawTag(161, 5); + output.WriteDouble(DoubleField84); + } + if (Int64Field85 != 0L) { + output.WriteRawTag(168, 5); + output.WriteInt64(Int64Field85); + } + if (Int64Field86 != 0L) { + output.WriteRawTag(176, 5); + output.WriteInt64(Int64Field86); + } + if (Int64Field87 != 0L) { + output.WriteRawTag(184, 5); + output.WriteInt64(Int64Field87); + } + if (DoubleField88 != 0D) { + output.WriteRawTag(193, 5); + output.WriteDouble(DoubleField88); + } + if (DoubleField89 != 0D) { + output.WriteRawTag(201, 5); + output.WriteDouble(DoubleField89); + } + if (DoubleField90 != 0D) { + output.WriteRawTag(209, 5); + output.WriteDouble(DoubleField90); + } + if (DoubleField91 != 0D) { + output.WriteRawTag(217, 5); + output.WriteDouble(DoubleField91); + } + if (DoubleField92 != 0D) { + output.WriteRawTag(225, 5); + output.WriteDouble(DoubleField92); + } + if (DoubleField93 != 0D) { + output.WriteRawTag(233, 5); + output.WriteDouble(DoubleField93); + } + if (DoubleField94 != 0D) { + output.WriteRawTag(241, 5); + output.WriteDouble(DoubleField94); + } + if (DoubleField95 != 0D) { + output.WriteRawTag(249, 5); + output.WriteDouble(DoubleField95); + } + if (DoubleField96 != 0D) { + output.WriteRawTag(129, 6); + output.WriteDouble(DoubleField96); + } + if (DoubleField97 != 0D) { + output.WriteRawTag(137, 6); + output.WriteDouble(DoubleField97); + } + if (DoubleField98 != 0D) { + output.WriteRawTag(145, 6); + output.WriteDouble(DoubleField98); + } + if (DoubleField99 != 0D) { + output.WriteRawTag(153, 6); + output.WriteDouble(DoubleField99); + } + repeatedIntField100_.WriteTo(ref output, _repeated_repeatedIntField100_codec); + if (DoubleField101 != 0D) { + output.WriteRawTag(169, 6); + output.WriteDouble(DoubleField101); + } + if (DoubleField102 != 0D) { + output.WriteRawTag(177, 6); + output.WriteDouble(DoubleField102); + } + if (DoubleField103 != 0D) { + output.WriteRawTag(185, 6); + output.WriteDouble(DoubleField103); + } + if (DoubleField104 != 0D) { + output.WriteRawTag(193, 6); + output.WriteDouble(DoubleField104); + } + if (DoubleField105 != 0D) { + output.WriteRawTag(201, 6); + output.WriteDouble(DoubleField105); + } + if (DoubleField106 != 0D) { + output.WriteRawTag(209, 6); + output.WriteDouble(DoubleField106); + } + if (Int64Field107 != 0L) { + output.WriteRawTag(216, 6); + output.WriteInt64(Int64Field107); + } + if (DoubleField108 != 0D) { + output.WriteRawTag(225, 6); + output.WriteDouble(DoubleField108); + } + if (DoubleField109 != 0D) { + output.WriteRawTag(233, 6); + output.WriteDouble(DoubleField109); + } + if (Int64Field110 != 0L) { + output.WriteRawTag(240, 6); + output.WriteInt64(Int64Field110); + } + if (DoubleField111 != 0D) { + output.WriteRawTag(249, 6); + output.WriteDouble(DoubleField111); + } + if (Int64Field112 != 0L) { + output.WriteRawTag(128, 7); + output.WriteInt64(Int64Field112); + } + if (DoubleField113 != 0D) { + output.WriteRawTag(137, 7); + output.WriteDouble(DoubleField113); + } + if (Int64Field114 != 0L) { + output.WriteRawTag(144, 7); + output.WriteInt64(Int64Field114); + } + if (Int64Field115 != 0L) { + output.WriteRawTag(152, 7); + output.WriteInt64(Int64Field115); + } + if (DoubleField116 != 0D) { + output.WriteRawTag(161, 7); + output.WriteDouble(DoubleField116); + } + if (Int64Field117 != 0L) { + output.WriteRawTag(168, 7); + output.WriteInt64(Int64Field117); + } + if (DoubleField118 != 0D) { + output.WriteRawTag(177, 7); + output.WriteDouble(DoubleField118); + } + if (DoubleField119 != 0D) { + output.WriteRawTag(185, 7); + output.WriteDouble(DoubleField119); + } + if (DoubleField120 != 0D) { + output.WriteRawTag(193, 7); + output.WriteDouble(DoubleField120); + } + if (DoubleField121 != 0D) { + output.WriteRawTag(201, 7); + output.WriteDouble(DoubleField121); + } + if (DoubleField122 != 0D) { + output.WriteRawTag(209, 7); + output.WriteDouble(DoubleField122); + } + if (DoubleField123 != 0D) { + output.WriteRawTag(217, 7); + output.WriteDouble(DoubleField123); + } + if (DoubleField124 != 0D) { + output.WriteRawTag(225, 7); + output.WriteDouble(DoubleField124); + } + if (Int64Field125 != 0L) { + output.WriteRawTag(232, 7); + output.WriteInt64(Int64Field125); + } + if (Int64Field126 != 0L) { + output.WriteRawTag(240, 7); + output.WriteInt64(Int64Field126); + } + if (Int64Field127 != 0L) { + output.WriteRawTag(248, 7); + output.WriteInt64(Int64Field127); + } + if (DoubleField128 != 0D) { + output.WriteRawTag(129, 8); + output.WriteDouble(DoubleField128); + } + if (DoubleField129 != 0D) { + output.WriteRawTag(137, 8); + output.WriteDouble(DoubleField129); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (DoubleField95 != 0D) { + size += 2 + 8; + } + if (DoubleField1 != 0D) { + size += 1 + 8; + } + if (DoubleField79 != 0D) { + size += 2 + 8; + } + if (Int64Field2 != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Int64Field2); + } + if (DoubleField96 != 0D) { + size += 2 + 8; + } + if (Int64Field3 != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Int64Field3); + } + if (Int64Field4 != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Int64Field4); + } + if (DoubleField97 != 0D) { + size += 2 + 8; + } + if (DoubleField65 != 0D) { + size += 2 + 8; + } + if (DoubleField66 != 0D) { + size += 2 + 8; + } + if (DoubleField7 != 0D) { + size += 1 + 8; + } + if (DoubleField62 != 0D) { + size += 2 + 8; + } + if (DoubleField118 != 0D) { + size += 2 + 8; + } + if (DoubleField119 != 0D) { + size += 2 + 8; + } + if (DoubleField67 != 0D) { + size += 2 + 8; + } + if (DoubleField120 != 0D) { + size += 2 + 8; + } + if (DoubleField121 != 0D) { + size += 2 + 8; + } + if (DoubleField122 != 0D) { + size += 2 + 8; + } + if (DoubleField123 != 0D) { + size += 2 + 8; + } + if (DoubleField124 != 0D) { + size += 2 + 8; + } + if (DoubleField8 != 0D) { + size += 1 + 8; + } + if (DoubleField9 != 0D) { + size += 1 + 8; + } + if (DoubleField98 != 0D) { + size += 2 + 8; + } + if (DoubleField10 != 0D) { + size += 1 + 8; + } + if (DoubleField11 != 0D) { + size += 1 + 8; + } + if (DoubleField99 != 0D) { + size += 2 + 8; + } + if (DoubleField84 != 0D) { + size += 2 + 8; + } + if (DoubleField14 != 0D) { + size += 1 + 8; + } + if (DoubleField77 != 0D) { + size += 2 + 8; + } + if (DoubleField15 != 0D) { + size += 1 + 8; + } + if (Int64Field19 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field19); + } + if (Int64Field115 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field115); + } + if (DoubleField116 != 0D) { + size += 2 + 8; + } + if (Int64Field117 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field117); + } + if (DoubleField20 != 0D) { + size += 2 + 8; + } + if (DoubleField21 != 0D) { + size += 2 + 8; + } + if (StringField73.Length != 0) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(StringField73); + } + if (StringField74.Length != 0) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(StringField74); + } + if (DoubleField22 != 0D) { + size += 2 + 8; + } + if (DoubleField69 != 0D) { + size += 2 + 8; + } + if (DoubleField70 != 0D) { + size += 2 + 8; + } + if (DoubleField71 != 0D) { + size += 2 + 8; + } + if (DoubleField72 != 0D) { + size += 2 + 8; + } + if (DoubleField25 != 0D) { + size += 2 + 8; + } + if (Int64Field26 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field26); + } + if (DoubleField68 != 0D) { + size += 2 + 8; + } + if (DoubleField28 != 0D) { + size += 2 + 8; + } + if (DoubleField106 != 0D) { + size += 2 + 8; + } + if (DoubleField29 != 0D) { + size += 2 + 8; + } + if (DoubleField30 != 0D) { + size += 2 + 8; + } + if (DoubleField101 != 0D) { + size += 2 + 8; + } + if (DoubleField102 != 0D) { + size += 2 + 8; + } + if (DoubleField103 != 0D) { + size += 2 + 8; + } + if (DoubleField104 != 0D) { + size += 2 + 8; + } + if (DoubleField105 != 0D) { + size += 2 + 8; + } + if (DoubleField31 != 0D) { + size += 2 + 8; + } + if (Int64Field32 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field32); + } + if (DoubleField75 != 0D) { + size += 2 + 8; + } + if (DoubleField129 != 0D) { + size += 2 + 8; + } + if (EnumField80 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(EnumField80); + } + if (EnumField81 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(EnumField81); + } + if (Int64Field82 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field82); + } + if (EnumField83 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(EnumField83); + } + if (Int64Field85 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field85); + } + if (Int64Field86 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field86); + } + if (Int64Field87 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field87); + } + if (Int64Field125 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field125); + } + if (Int64Field37 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field37); + } + if (DoubleField38 != 0D) { + size += 2 + 8; + } + if (Interactions != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Interactions); + } + size += repeatedIntField100_.CalculateSize(_repeated_repeatedIntField100_codec); + if (DoubleField40 != 0D) { + size += 2 + 8; + } + if (Int64Field41 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field41); + } + if (Int64Field126 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field126); + } + if (Int64Field127 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field127); + } + if (DoubleField128 != 0D) { + size += 2 + 8; + } + if (DoubleField109 != 0D) { + size += 2 + 8; + } + if (Int64Field110 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field110); + } + if (DoubleField111 != 0D) { + size += 2 + 8; + } + if (Int64Field112 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field112); + } + if (DoubleField113 != 0D) { + size += 2 + 8; + } + if (Int64Field114 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field114); + } + if (DoubleField42 != 0D) { + size += 2 + 8; + } + if (Int64Field43 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field43); + } + if (Int64Field44 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field44); + } + if (DoubleField45 != 0D) { + size += 2 + 8; + } + if (DoubleField46 != 0D) { + size += 2 + 8; + } + if (DoubleField78 != 0D) { + size += 2 + 8; + } + if (DoubleField88 != 0D) { + size += 2 + 8; + } + if (DoubleField47 != 0D) { + size += 2 + 8; + } + if (DoubleField89 != 0D) { + size += 2 + 8; + } + if (DoubleField48 != 0D) { + size += 2 + 8; + } + if (DoubleField49 != 0D) { + size += 2 + 8; + } + if (DoubleField50 != 0D) { + size += 2 + 8; + } + if (DoubleField90 != 0D) { + size += 2 + 8; + } + if (DoubleField51 != 0D) { + size += 2 + 8; + } + if (DoubleField91 != 0D) { + size += 2 + 8; + } + if (DoubleField92 != 0D) { + size += 2 + 8; + } + if (Int64Field107 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field107); + } + if (DoubleField93 != 0D) { + size += 2 + 8; + } + if (DoubleField108 != 0D) { + size += 2 + 8; + } + if (DoubleField52 != 0D) { + size += 2 + 8; + } + if (DoubleField53 != 0D) { + size += 2 + 8; + } + if (DoubleField94 != 0D) { + size += 2 + 8; + } + if (DoubleField54 != 0D) { + size += 2 + 8; + } + if (DoubleField55 != 0D) { + size += 2 + 8; + } + if (DoubleField56 != 0D) { + size += 2 + 8; + } + if (DoubleField57 != 0D) { + size += 2 + 8; + } + if (DoubleField58 != 0D) { + size += 2 + 8; + } + if (Int64Field59 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field59); + } + if (Int64Field60 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field60); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ManyPrimitiveFieldsMessage other) { + if (other == null) { + return; + } + if (other.DoubleField95 != 0D) { + DoubleField95 = other.DoubleField95; + } + if (other.DoubleField1 != 0D) { + DoubleField1 = other.DoubleField1; + } + if (other.DoubleField79 != 0D) { + DoubleField79 = other.DoubleField79; + } + if (other.Int64Field2 != 0L) { + Int64Field2 = other.Int64Field2; + } + if (other.DoubleField96 != 0D) { + DoubleField96 = other.DoubleField96; + } + if (other.Int64Field3 != 0L) { + Int64Field3 = other.Int64Field3; + } + if (other.Int64Field4 != 0L) { + Int64Field4 = other.Int64Field4; + } + if (other.DoubleField97 != 0D) { + DoubleField97 = other.DoubleField97; + } + if (other.DoubleField65 != 0D) { + DoubleField65 = other.DoubleField65; + } + if (other.DoubleField66 != 0D) { + DoubleField66 = other.DoubleField66; + } + if (other.DoubleField7 != 0D) { + DoubleField7 = other.DoubleField7; + } + if (other.DoubleField62 != 0D) { + DoubleField62 = other.DoubleField62; + } + if (other.DoubleField118 != 0D) { + DoubleField118 = other.DoubleField118; + } + if (other.DoubleField119 != 0D) { + DoubleField119 = other.DoubleField119; + } + if (other.DoubleField67 != 0D) { + DoubleField67 = other.DoubleField67; + } + if (other.DoubleField120 != 0D) { + DoubleField120 = other.DoubleField120; + } + if (other.DoubleField121 != 0D) { + DoubleField121 = other.DoubleField121; + } + if (other.DoubleField122 != 0D) { + DoubleField122 = other.DoubleField122; + } + if (other.DoubleField123 != 0D) { + DoubleField123 = other.DoubleField123; + } + if (other.DoubleField124 != 0D) { + DoubleField124 = other.DoubleField124; + } + if (other.DoubleField8 != 0D) { + DoubleField8 = other.DoubleField8; + } + if (other.DoubleField9 != 0D) { + DoubleField9 = other.DoubleField9; + } + if (other.DoubleField98 != 0D) { + DoubleField98 = other.DoubleField98; + } + if (other.DoubleField10 != 0D) { + DoubleField10 = other.DoubleField10; + } + if (other.DoubleField11 != 0D) { + DoubleField11 = other.DoubleField11; + } + if (other.DoubleField99 != 0D) { + DoubleField99 = other.DoubleField99; + } + if (other.DoubleField84 != 0D) { + DoubleField84 = other.DoubleField84; + } + if (other.DoubleField14 != 0D) { + DoubleField14 = other.DoubleField14; + } + if (other.DoubleField77 != 0D) { + DoubleField77 = other.DoubleField77; + } + if (other.DoubleField15 != 0D) { + DoubleField15 = other.DoubleField15; + } + if (other.Int64Field19 != 0L) { + Int64Field19 = other.Int64Field19; + } + if (other.Int64Field115 != 0L) { + Int64Field115 = other.Int64Field115; + } + if (other.DoubleField116 != 0D) { + DoubleField116 = other.DoubleField116; + } + if (other.Int64Field117 != 0L) { + Int64Field117 = other.Int64Field117; + } + if (other.DoubleField20 != 0D) { + DoubleField20 = other.DoubleField20; + } + if (other.DoubleField21 != 0D) { + DoubleField21 = other.DoubleField21; + } + if (other.StringField73.Length != 0) { + StringField73 = other.StringField73; + } + if (other.StringField74.Length != 0) { + StringField74 = other.StringField74; + } + if (other.DoubleField22 != 0D) { + DoubleField22 = other.DoubleField22; + } + if (other.DoubleField69 != 0D) { + DoubleField69 = other.DoubleField69; + } + if (other.DoubleField70 != 0D) { + DoubleField70 = other.DoubleField70; + } + if (other.DoubleField71 != 0D) { + DoubleField71 = other.DoubleField71; + } + if (other.DoubleField72 != 0D) { + DoubleField72 = other.DoubleField72; + } + if (other.DoubleField25 != 0D) { + DoubleField25 = other.DoubleField25; + } + if (other.Int64Field26 != 0L) { + Int64Field26 = other.Int64Field26; + } + if (other.DoubleField68 != 0D) { + DoubleField68 = other.DoubleField68; + } + if (other.DoubleField28 != 0D) { + DoubleField28 = other.DoubleField28; + } + if (other.DoubleField106 != 0D) { + DoubleField106 = other.DoubleField106; + } + if (other.DoubleField29 != 0D) { + DoubleField29 = other.DoubleField29; + } + if (other.DoubleField30 != 0D) { + DoubleField30 = other.DoubleField30; + } + if (other.DoubleField101 != 0D) { + DoubleField101 = other.DoubleField101; + } + if (other.DoubleField102 != 0D) { + DoubleField102 = other.DoubleField102; + } + if (other.DoubleField103 != 0D) { + DoubleField103 = other.DoubleField103; + } + if (other.DoubleField104 != 0D) { + DoubleField104 = other.DoubleField104; + } + if (other.DoubleField105 != 0D) { + DoubleField105 = other.DoubleField105; + } + if (other.DoubleField31 != 0D) { + DoubleField31 = other.DoubleField31; + } + if (other.Int64Field32 != 0L) { + Int64Field32 = other.Int64Field32; + } + if (other.DoubleField75 != 0D) { + DoubleField75 = other.DoubleField75; + } + if (other.DoubleField129 != 0D) { + DoubleField129 = other.DoubleField129; + } + if (other.EnumField80 != 0) { + EnumField80 = other.EnumField80; + } + if (other.EnumField81 != 0) { + EnumField81 = other.EnumField81; + } + if (other.Int64Field82 != 0L) { + Int64Field82 = other.Int64Field82; + } + if (other.EnumField83 != 0) { + EnumField83 = other.EnumField83; + } + if (other.Int64Field85 != 0L) { + Int64Field85 = other.Int64Field85; + } + if (other.Int64Field86 != 0L) { + Int64Field86 = other.Int64Field86; + } + if (other.Int64Field87 != 0L) { + Int64Field87 = other.Int64Field87; + } + if (other.Int64Field125 != 0L) { + Int64Field125 = other.Int64Field125; + } + if (other.Int64Field37 != 0L) { + Int64Field37 = other.Int64Field37; + } + if (other.DoubleField38 != 0D) { + DoubleField38 = other.DoubleField38; + } + if (other.Interactions != 0L) { + Interactions = other.Interactions; + } + repeatedIntField100_.Add(other.repeatedIntField100_); + if (other.DoubleField40 != 0D) { + DoubleField40 = other.DoubleField40; + } + if (other.Int64Field41 != 0L) { + Int64Field41 = other.Int64Field41; + } + if (other.Int64Field126 != 0L) { + Int64Field126 = other.Int64Field126; + } + if (other.Int64Field127 != 0L) { + Int64Field127 = other.Int64Field127; + } + if (other.DoubleField128 != 0D) { + DoubleField128 = other.DoubleField128; + } + if (other.DoubleField109 != 0D) { + DoubleField109 = other.DoubleField109; + } + if (other.Int64Field110 != 0L) { + Int64Field110 = other.Int64Field110; + } + if (other.DoubleField111 != 0D) { + DoubleField111 = other.DoubleField111; + } + if (other.Int64Field112 != 0L) { + Int64Field112 = other.Int64Field112; + } + if (other.DoubleField113 != 0D) { + DoubleField113 = other.DoubleField113; + } + if (other.Int64Field114 != 0L) { + Int64Field114 = other.Int64Field114; + } + if (other.DoubleField42 != 0D) { + DoubleField42 = other.DoubleField42; + } + if (other.Int64Field43 != 0L) { + Int64Field43 = other.Int64Field43; + } + if (other.Int64Field44 != 0L) { + Int64Field44 = other.Int64Field44; + } + if (other.DoubleField45 != 0D) { + DoubleField45 = other.DoubleField45; + } + if (other.DoubleField46 != 0D) { + DoubleField46 = other.DoubleField46; + } + if (other.DoubleField78 != 0D) { + DoubleField78 = other.DoubleField78; + } + if (other.DoubleField88 != 0D) { + DoubleField88 = other.DoubleField88; + } + if (other.DoubleField47 != 0D) { + DoubleField47 = other.DoubleField47; + } + if (other.DoubleField89 != 0D) { + DoubleField89 = other.DoubleField89; + } + if (other.DoubleField48 != 0D) { + DoubleField48 = other.DoubleField48; + } + if (other.DoubleField49 != 0D) { + DoubleField49 = other.DoubleField49; + } + if (other.DoubleField50 != 0D) { + DoubleField50 = other.DoubleField50; + } + if (other.DoubleField90 != 0D) { + DoubleField90 = other.DoubleField90; + } + if (other.DoubleField51 != 0D) { + DoubleField51 = other.DoubleField51; + } + if (other.DoubleField91 != 0D) { + DoubleField91 = other.DoubleField91; + } + if (other.DoubleField92 != 0D) { + DoubleField92 = other.DoubleField92; + } + if (other.Int64Field107 != 0L) { + Int64Field107 = other.Int64Field107; + } + if (other.DoubleField93 != 0D) { + DoubleField93 = other.DoubleField93; + } + if (other.DoubleField108 != 0D) { + DoubleField108 = other.DoubleField108; + } + if (other.DoubleField52 != 0D) { + DoubleField52 = other.DoubleField52; + } + if (other.DoubleField53 != 0D) { + DoubleField53 = other.DoubleField53; + } + if (other.DoubleField94 != 0D) { + DoubleField94 = other.DoubleField94; + } + if (other.DoubleField54 != 0D) { + DoubleField54 = other.DoubleField54; + } + if (other.DoubleField55 != 0D) { + DoubleField55 = other.DoubleField55; + } + if (other.DoubleField56 != 0D) { + DoubleField56 = other.DoubleField56; + } + if (other.DoubleField57 != 0D) { + DoubleField57 = other.DoubleField57; + } + if (other.DoubleField58 != 0D) { + DoubleField58 = other.DoubleField58; + } + if (other.Int64Field59 != 0L) { + Int64Field59 = other.Int64Field59; + } + if (other.Int64Field60 != 0L) { + Int64Field60 = other.Int64Field60; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 9: { + DoubleField1 = input.ReadDouble(); + break; + } + case 16: { + Int64Field2 = input.ReadInt64(); + break; + } + case 24: { + Int64Field3 = input.ReadInt64(); + break; + } + case 32: { + Int64Field4 = input.ReadInt64(); + break; + } + case 57: { + DoubleField7 = input.ReadDouble(); + break; + } + case 65: { + DoubleField8 = input.ReadDouble(); + break; + } + case 73: { + DoubleField9 = input.ReadDouble(); + break; + } + case 81: { + DoubleField10 = input.ReadDouble(); + break; + } + case 89: { + DoubleField11 = input.ReadDouble(); + break; + } + case 113: { + DoubleField14 = input.ReadDouble(); + break; + } + case 121: { + DoubleField15 = input.ReadDouble(); + break; + } + case 152: { + Int64Field19 = input.ReadInt64(); + break; + } + case 161: { + DoubleField20 = input.ReadDouble(); + break; + } + case 169: { + DoubleField21 = input.ReadDouble(); + break; + } + case 177: { + DoubleField22 = input.ReadDouble(); + break; + } + case 201: { + DoubleField25 = input.ReadDouble(); + break; + } + case 208: { + Int64Field26 = input.ReadInt64(); + break; + } + case 225: { + DoubleField28 = input.ReadDouble(); + break; + } + case 233: { + DoubleField29 = input.ReadDouble(); + break; + } + case 241: { + DoubleField30 = input.ReadDouble(); + break; + } + case 249: { + DoubleField31 = input.ReadDouble(); + break; + } + case 256: { + Int64Field32 = input.ReadInt64(); + break; + } + case 296: { + Int64Field37 = input.ReadInt64(); + break; + } + case 305: { + DoubleField38 = input.ReadDouble(); + break; + } + case 312: { + Interactions = input.ReadInt64(); + break; + } + case 321: { + DoubleField40 = input.ReadDouble(); + break; + } + case 328: { + Int64Field41 = input.ReadInt64(); + break; + } + case 337: { + DoubleField42 = input.ReadDouble(); + break; + } + case 344: { + Int64Field43 = input.ReadInt64(); + break; + } + case 352: { + Int64Field44 = input.ReadInt64(); + break; + } + case 361: { + DoubleField45 = input.ReadDouble(); + break; + } + case 369: { + DoubleField46 = input.ReadDouble(); + break; + } + case 377: { + DoubleField47 = input.ReadDouble(); + break; + } + case 385: { + DoubleField48 = input.ReadDouble(); + break; + } + case 393: { + DoubleField49 = input.ReadDouble(); + break; + } + case 401: { + DoubleField50 = input.ReadDouble(); + break; + } + case 409: { + DoubleField51 = input.ReadDouble(); + break; + } + case 417: { + DoubleField52 = input.ReadDouble(); + break; + } + case 425: { + DoubleField53 = input.ReadDouble(); + break; + } + case 433: { + DoubleField54 = input.ReadDouble(); + break; + } + case 441: { + DoubleField55 = input.ReadDouble(); + break; + } + case 449: { + DoubleField56 = input.ReadDouble(); + break; + } + case 457: { + DoubleField57 = input.ReadDouble(); + break; + } + case 465: { + DoubleField58 = input.ReadDouble(); + break; + } + case 472: { + Int64Field59 = input.ReadInt64(); + break; + } + case 480: { + Int64Field60 = input.ReadInt64(); + break; + } + case 497: { + DoubleField62 = input.ReadDouble(); + break; + } + case 521: { + DoubleField65 = input.ReadDouble(); + break; + } + case 529: { + DoubleField66 = input.ReadDouble(); + break; + } + case 537: { + DoubleField67 = input.ReadDouble(); + break; + } + case 545: { + DoubleField68 = input.ReadDouble(); + break; + } + case 553: { + DoubleField69 = input.ReadDouble(); + break; + } + case 561: { + DoubleField70 = input.ReadDouble(); + break; + } + case 569: { + DoubleField71 = input.ReadDouble(); + break; + } + case 577: { + DoubleField72 = input.ReadDouble(); + break; + } + case 586: { + StringField73 = input.ReadString(); + break; + } + case 594: { + StringField74 = input.ReadString(); + break; + } + case 601: { + DoubleField75 = input.ReadDouble(); + break; + } + case 617: { + DoubleField77 = input.ReadDouble(); + break; + } + case 625: { + DoubleField78 = input.ReadDouble(); + break; + } + case 633: { + DoubleField79 = input.ReadDouble(); + break; + } + case 640: { + EnumField80 = input.ReadInt32(); + break; + } + case 648: { + EnumField81 = input.ReadInt32(); + break; + } + case 656: { + Int64Field82 = input.ReadInt64(); + break; + } + case 664: { + EnumField83 = input.ReadInt32(); + break; + } + case 673: { + DoubleField84 = input.ReadDouble(); + break; + } + case 680: { + Int64Field85 = input.ReadInt64(); + break; + } + case 688: { + Int64Field86 = input.ReadInt64(); + break; + } + case 696: { + Int64Field87 = input.ReadInt64(); + break; + } + case 705: { + DoubleField88 = input.ReadDouble(); + break; + } + case 713: { + DoubleField89 = input.ReadDouble(); + break; + } + case 721: { + DoubleField90 = input.ReadDouble(); + break; + } + case 729: { + DoubleField91 = input.ReadDouble(); + break; + } + case 737: { + DoubleField92 = input.ReadDouble(); + break; + } + case 745: { + DoubleField93 = input.ReadDouble(); + break; + } + case 753: { + DoubleField94 = input.ReadDouble(); + break; + } + case 761: { + DoubleField95 = input.ReadDouble(); + break; + } + case 769: { + DoubleField96 = input.ReadDouble(); + break; + } + case 777: { + DoubleField97 = input.ReadDouble(); + break; + } + case 785: { + DoubleField98 = input.ReadDouble(); + break; + } + case 793: { + DoubleField99 = input.ReadDouble(); + break; + } + case 802: + case 800: { + repeatedIntField100_.AddEntriesFrom(input, _repeated_repeatedIntField100_codec); + break; + } + case 809: { + DoubleField101 = input.ReadDouble(); + break; + } + case 817: { + DoubleField102 = input.ReadDouble(); + break; + } + case 825: { + DoubleField103 = input.ReadDouble(); + break; + } + case 833: { + DoubleField104 = input.ReadDouble(); + break; + } + case 841: { + DoubleField105 = input.ReadDouble(); + break; + } + case 849: { + DoubleField106 = input.ReadDouble(); + break; + } + case 856: { + Int64Field107 = input.ReadInt64(); + break; + } + case 865: { + DoubleField108 = input.ReadDouble(); + break; + } + case 873: { + DoubleField109 = input.ReadDouble(); + break; + } + case 880: { + Int64Field110 = input.ReadInt64(); + break; + } + case 889: { + DoubleField111 = input.ReadDouble(); + break; + } + case 896: { + Int64Field112 = input.ReadInt64(); + break; + } + case 905: { + DoubleField113 = input.ReadDouble(); + break; + } + case 912: { + Int64Field114 = input.ReadInt64(); + break; + } + case 920: { + Int64Field115 = input.ReadInt64(); + break; + } + case 929: { + DoubleField116 = input.ReadDouble(); + break; + } + case 936: { + Int64Field117 = input.ReadInt64(); + break; + } + case 945: { + DoubleField118 = input.ReadDouble(); + break; + } + case 953: { + DoubleField119 = input.ReadDouble(); + break; + } + case 961: { + DoubleField120 = input.ReadDouble(); + break; + } + case 969: { + DoubleField121 = input.ReadDouble(); + break; + } + case 977: { + DoubleField122 = input.ReadDouble(); + break; + } + case 985: { + DoubleField123 = input.ReadDouble(); + break; + } + case 993: { + DoubleField124 = input.ReadDouble(); + break; + } + case 1000: { + Int64Field125 = input.ReadInt64(); + break; + } + case 1008: { + Int64Field126 = input.ReadInt64(); + break; + } + case 1016: { + Int64Field127 = input.ReadInt64(); + break; + } + case 1025: { + DoubleField128 = input.ReadDouble(); + break; + } + case 1033: { + DoubleField129 = input.ReadDouble(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 9: { + DoubleField1 = input.ReadDouble(); + break; + } + case 16: { + Int64Field2 = input.ReadInt64(); + break; + } + case 24: { + Int64Field3 = input.ReadInt64(); + break; + } + case 32: { + Int64Field4 = input.ReadInt64(); + break; + } + case 57: { + DoubleField7 = input.ReadDouble(); + break; + } + case 65: { + DoubleField8 = input.ReadDouble(); + break; + } + case 73: { + DoubleField9 = input.ReadDouble(); + break; + } + case 81: { + DoubleField10 = input.ReadDouble(); + break; + } + case 89: { + DoubleField11 = input.ReadDouble(); + break; + } + case 113: { + DoubleField14 = input.ReadDouble(); + break; + } + case 121: { + DoubleField15 = input.ReadDouble(); + break; + } + case 152: { + Int64Field19 = input.ReadInt64(); + break; + } + case 161: { + DoubleField20 = input.ReadDouble(); + break; + } + case 169: { + DoubleField21 = input.ReadDouble(); + break; + } + case 177: { + DoubleField22 = input.ReadDouble(); + break; + } + case 201: { + DoubleField25 = input.ReadDouble(); + break; + } + case 208: { + Int64Field26 = input.ReadInt64(); + break; + } + case 225: { + DoubleField28 = input.ReadDouble(); + break; + } + case 233: { + DoubleField29 = input.ReadDouble(); + break; + } + case 241: { + DoubleField30 = input.ReadDouble(); + break; + } + case 249: { + DoubleField31 = input.ReadDouble(); + break; + } + case 256: { + Int64Field32 = input.ReadInt64(); + break; + } + case 296: { + Int64Field37 = input.ReadInt64(); + break; + } + case 305: { + DoubleField38 = input.ReadDouble(); + break; + } + case 312: { + Interactions = input.ReadInt64(); + break; + } + case 321: { + DoubleField40 = input.ReadDouble(); + break; + } + case 328: { + Int64Field41 = input.ReadInt64(); + break; + } + case 337: { + DoubleField42 = input.ReadDouble(); + break; + } + case 344: { + Int64Field43 = input.ReadInt64(); + break; + } + case 352: { + Int64Field44 = input.ReadInt64(); + break; + } + case 361: { + DoubleField45 = input.ReadDouble(); + break; + } + case 369: { + DoubleField46 = input.ReadDouble(); + break; + } + case 377: { + DoubleField47 = input.ReadDouble(); + break; + } + case 385: { + DoubleField48 = input.ReadDouble(); + break; + } + case 393: { + DoubleField49 = input.ReadDouble(); + break; + } + case 401: { + DoubleField50 = input.ReadDouble(); + break; + } + case 409: { + DoubleField51 = input.ReadDouble(); + break; + } + case 417: { + DoubleField52 = input.ReadDouble(); + break; + } + case 425: { + DoubleField53 = input.ReadDouble(); + break; + } + case 433: { + DoubleField54 = input.ReadDouble(); + break; + } + case 441: { + DoubleField55 = input.ReadDouble(); + break; + } + case 449: { + DoubleField56 = input.ReadDouble(); + break; + } + case 457: { + DoubleField57 = input.ReadDouble(); + break; + } + case 465: { + DoubleField58 = input.ReadDouble(); + break; + } + case 472: { + Int64Field59 = input.ReadInt64(); + break; + } + case 480: { + Int64Field60 = input.ReadInt64(); + break; + } + case 497: { + DoubleField62 = input.ReadDouble(); + break; + } + case 521: { + DoubleField65 = input.ReadDouble(); + break; + } + case 529: { + DoubleField66 = input.ReadDouble(); + break; + } + case 537: { + DoubleField67 = input.ReadDouble(); + break; + } + case 545: { + DoubleField68 = input.ReadDouble(); + break; + } + case 553: { + DoubleField69 = input.ReadDouble(); + break; + } + case 561: { + DoubleField70 = input.ReadDouble(); + break; + } + case 569: { + DoubleField71 = input.ReadDouble(); + break; + } + case 577: { + DoubleField72 = input.ReadDouble(); + break; + } + case 586: { + StringField73 = input.ReadString(); + break; + } + case 594: { + StringField74 = input.ReadString(); + break; + } + case 601: { + DoubleField75 = input.ReadDouble(); + break; + } + case 617: { + DoubleField77 = input.ReadDouble(); + break; + } + case 625: { + DoubleField78 = input.ReadDouble(); + break; + } + case 633: { + DoubleField79 = input.ReadDouble(); + break; + } + case 640: { + EnumField80 = input.ReadInt32(); + break; + } + case 648: { + EnumField81 = input.ReadInt32(); + break; + } + case 656: { + Int64Field82 = input.ReadInt64(); + break; + } + case 664: { + EnumField83 = input.ReadInt32(); + break; + } + case 673: { + DoubleField84 = input.ReadDouble(); + break; + } + case 680: { + Int64Field85 = input.ReadInt64(); + break; + } + case 688: { + Int64Field86 = input.ReadInt64(); + break; + } + case 696: { + Int64Field87 = input.ReadInt64(); + break; + } + case 705: { + DoubleField88 = input.ReadDouble(); + break; + } + case 713: { + DoubleField89 = input.ReadDouble(); + break; + } + case 721: { + DoubleField90 = input.ReadDouble(); + break; + } + case 729: { + DoubleField91 = input.ReadDouble(); + break; + } + case 737: { + DoubleField92 = input.ReadDouble(); + break; + } + case 745: { + DoubleField93 = input.ReadDouble(); + break; + } + case 753: { + DoubleField94 = input.ReadDouble(); + break; + } + case 761: { + DoubleField95 = input.ReadDouble(); + break; + } + case 769: { + DoubleField96 = input.ReadDouble(); + break; + } + case 777: { + DoubleField97 = input.ReadDouble(); + break; + } + case 785: { + DoubleField98 = input.ReadDouble(); + break; + } + case 793: { + DoubleField99 = input.ReadDouble(); + break; + } + case 802: + case 800: { + repeatedIntField100_.AddEntriesFrom(ref input, _repeated_repeatedIntField100_codec); + break; + } + case 809: { + DoubleField101 = input.ReadDouble(); + break; + } + case 817: { + DoubleField102 = input.ReadDouble(); + break; + } + case 825: { + DoubleField103 = input.ReadDouble(); + break; + } + case 833: { + DoubleField104 = input.ReadDouble(); + break; + } + case 841: { + DoubleField105 = input.ReadDouble(); + break; + } + case 849: { + DoubleField106 = input.ReadDouble(); + break; + } + case 856: { + Int64Field107 = input.ReadInt64(); + break; + } + case 865: { + DoubleField108 = input.ReadDouble(); + break; + } + case 873: { + DoubleField109 = input.ReadDouble(); + break; + } + case 880: { + Int64Field110 = input.ReadInt64(); + break; + } + case 889: { + DoubleField111 = input.ReadDouble(); + break; + } + case 896: { + Int64Field112 = input.ReadInt64(); + break; + } + case 905: { + DoubleField113 = input.ReadDouble(); + break; + } + case 912: { + Int64Field114 = input.ReadInt64(); + break; + } + case 920: { + Int64Field115 = input.ReadInt64(); + break; + } + case 929: { + DoubleField116 = input.ReadDouble(); + break; + } + case 936: { + Int64Field117 = input.ReadInt64(); + break; + } + case 945: { + DoubleField118 = input.ReadDouble(); + break; + } + case 953: { + DoubleField119 = input.ReadDouble(); + break; + } + case 961: { + DoubleField120 = input.ReadDouble(); + break; + } + case 969: { + DoubleField121 = input.ReadDouble(); + break; + } + case 977: { + DoubleField122 = input.ReadDouble(); + break; + } + case 985: { + DoubleField123 = input.ReadDouble(); + break; + } + case 993: { + DoubleField124 = input.ReadDouble(); + break; + } + case 1000: { + Int64Field125 = input.ReadInt64(); + break; + } + case 1008: { + Int64Field126 = input.ReadInt64(); + break; + } + case 1016: { + Int64Field127 = input.ReadInt64(); + break; + } + case 1025: { + DoubleField128 = input.ReadDouble(); + break; + } + case 1033: { + DoubleField129 = input.ReadDouble(); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs new file mode 100644 index 0000000000000..5a3bba74d260e --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs @@ -0,0 +1,198 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2019 Google Inc. All rights reserved. +// https://github.com/protocolbuffers/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using BenchmarkDotNet.Attributes; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Buffers; +using Google.Protobuf.WellKnownTypes; + +namespace Google.Protobuf.Benchmarks +{ + /// + /// Benchmark that tests writing performance for various messages. + /// + [MemoryDiagnoser] + public class WriteMessagesBenchmark + { + const int MaxMessages = 100; + + SubTest manyWrapperFieldsTest = new SubTest(ParseMessagesBenchmark.CreateManyWrapperFieldsMessage(), MaxMessages); + SubTest manyPrimitiveFieldsTest = new SubTest(ParseMessagesBenchmark.CreateManyPrimitiveFieldsMessage(), MaxMessages); + SubTest emptyMessageTest = new SubTest(new Empty(), MaxMessages); + + public IEnumerable MessageCountValues => new[] { 10, 100 }; + + [GlobalSetup] + public void GlobalSetup() + { + } + + [Benchmark] + public byte[] ManyWrapperFieldsMessage_ToByteArray() + { + return manyWrapperFieldsTest.ToByteArray(); + } + + [Benchmark] + public byte[] ManyWrapperFieldsMessage_WriteToCodedOutputStream() + { + return manyWrapperFieldsTest.WriteToCodedOutputStream_PreAllocatedBuffer(); + } + + [Benchmark] + public byte[] ManyWrapperFieldsMessage_WriteToSpan() + { + return manyWrapperFieldsTest.WriteToSpan_PreAllocatedBuffer(); + } + + + [Benchmark] + public byte[] ManyPrimitiveFieldsMessage_ToByteArray() + { + return manyPrimitiveFieldsTest.ToByteArray(); + } + + [Benchmark] + public byte[] ManyPrimitiveFieldsMessage_WriteToCodedOutputStream() + { + return manyPrimitiveFieldsTest.WriteToCodedOutputStream_PreAllocatedBuffer(); + } + + [Benchmark] + public byte[] ManyPrimitiveFieldsMessage_WriteToSpan() + { + return manyPrimitiveFieldsTest.WriteToSpan_PreAllocatedBuffer(); + } + + [Benchmark] + public byte[] EmptyMessage_ToByteArray() + { + return emptyMessageTest.ToByteArray(); + } + + [Benchmark] + public byte[] EmptyMessage_WriteToCodedOutputStream() + { + return emptyMessageTest.WriteToCodedOutputStream_PreAllocatedBuffer(); + } + + [Benchmark] + public byte[] EmptyMessage_WriteToSpan() + { + return emptyMessageTest.WriteToSpan_PreAllocatedBuffer(); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void ManyWrapperFieldsMessage_WriteDelimitedMessagesToCodedOutputStream(int messageCount) + { + manyWrapperFieldsTest.WriteDelimitedMessagesToCodedOutputStream_PreAllocatedBuffer(messageCount); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void ManyWrapperFieldsMessage_WriteDelimitedMessagesToSpan(int messageCount) + { + manyWrapperFieldsTest.WriteDelimitedMessagesToSpan_PreAllocatedBuffer(messageCount); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void ManyPrimitiveFieldsMessage_WriteDelimitedMessagesToCodedOutputStream(int messageCount) + { + manyPrimitiveFieldsTest.WriteDelimitedMessagesToCodedOutputStream_PreAllocatedBuffer(messageCount); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void ManyPrimitiveFieldsMessage_WriteDelimitedMessagesToSpan(int messageCount) + { + manyPrimitiveFieldsTest.WriteDelimitedMessagesToSpan_PreAllocatedBuffer(messageCount); + } + + private class SubTest + { + private readonly IMessage message; + private readonly byte[] outputBuffer; + private readonly byte[] multipleMessagesOutputBuffer; + + public SubTest(IMessage message, int maxMessageCount) + { + this.message = message; + + int messageSize = message.CalculateSize(); + this.outputBuffer = new byte[messageSize]; + this.multipleMessagesOutputBuffer = new byte[maxMessageCount * (messageSize + CodedOutputStream.ComputeLengthSize(messageSize))]; + } + + public byte[] ToByteArray() => message.ToByteArray(); + + public byte[] WriteToCodedOutputStream_PreAllocatedBuffer() + { + var cos = new CodedOutputStream(outputBuffer); // use pre-existing output buffer + message.WriteTo(cos); + return outputBuffer; + } + + public byte[] WriteToSpan_PreAllocatedBuffer() + { + var span = new Span(outputBuffer); // use pre-existing output buffer + message.WriteTo(span); + return outputBuffer; + } + + public byte[] WriteDelimitedMessagesToCodedOutputStream_PreAllocatedBuffer(int messageCount) + { + var cos = new CodedOutputStream(multipleMessagesOutputBuffer); // use pre-existing output buffer + for (int i = 0; i < messageCount; i++) + { + cos.WriteMessage(message); + } + return multipleMessagesOutputBuffer; + } + + public byte[] WriteDelimitedMessagesToSpan_PreAllocatedBuffer(int messageCount) + { + var span = new Span(multipleMessagesOutputBuffer); // use pre-existing output buffer + WriteContext.Initialize(ref span, out WriteContext ctx); + for (int i = 0; i < messageCount; i++) + { + ctx.WriteMessage(message); + } + return multipleMessagesOutputBuffer; + } + } + } +} diff --git a/csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs new file mode 100644 index 0000000000000..66b6b4a02828f --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs @@ -0,0 +1,519 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2019 Google Inc. All rights reserved. +// https://github.com/protocolbuffers/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using BenchmarkDotNet.Attributes; +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.IO; +using System.Buffers; +using System.Text; + +namespace Google.Protobuf.Benchmarks +{ + /// + /// Benchmarks throughput when writing raw primitives. + /// + [MemoryDiagnoser] + public class WriteRawPrimitivesBenchmark + { + // key is the encodedSize of varint values + Dictionary varint32Values; + Dictionary varint64Values; + + double[] doubleValues; + float[] floatValues; + + // key is the encodedSize of string values + Dictionary stringValues; + + // key is the encodedSize of string values + Dictionary nonAsciiStringValues; + + // key is the encodedSize of string values + Dictionary byteStringValues; + + // the buffer to which all the data will be written + byte[] outputBuffer; + + Random random = new Random(417384220); // random but deterministic seed + + public IEnumerable StringEncodedSizes => new[] { 1, 4, 10, 105, 10080 }; + + public IEnumerable NonAsciiStringEncodedSizes => new[] { 4, 10, 105, 10080 }; + + [GlobalSetup] + public void GlobalSetup() + { + outputBuffer = new byte[BytesToWrite]; + + varint32Values = new Dictionary(); + varint64Values = new Dictionary(); + for (int encodedSize = 1; encodedSize <= 10; encodedSize++) + { + if (encodedSize <= 5) + { + varint32Values.Add(encodedSize, CreateRandomVarints32(random, BytesToWrite / encodedSize, encodedSize)); + } + varint64Values.Add(encodedSize, CreateRandomVarints64(random, BytesToWrite / encodedSize, encodedSize)); + } + + doubleValues = CreateRandomDoubles(random, BytesToWrite / sizeof(double)); + floatValues = CreateRandomFloats(random, BytesToWrite / sizeof(float)); + + stringValues = new Dictionary(); + + byteStringValues = new Dictionary(); + foreach(var encodedSize in StringEncodedSizes) + { + stringValues.Add(encodedSize, CreateStrings(BytesToWrite / encodedSize, encodedSize)); + byteStringValues.Add(encodedSize, CreateByteStrings(BytesToWrite / encodedSize, encodedSize)); + } + + nonAsciiStringValues = new Dictionary(); + foreach(var encodedSize in NonAsciiStringEncodedSizes) + { + nonAsciiStringValues.Add(encodedSize, CreateNonAsciiStrings(BytesToWrite / encodedSize, encodedSize)); + } + } + + // Total number of bytes that each benchmark will write. + // Measuring the time taken to write buffer of given size makes it easier to compare parsing speed for different + // types and makes it easy to calculate the througput (in MB/s) + // 10800 bytes is chosen because it is divisible by all possible encoded sizes for all primitive types {1..10} + [Params(10080)] + public int BytesToWrite { get; set; } + + [Benchmark] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + public void WriteRawVarint32_CodedOutputStream(int encodedSize) + { + var values = varint32Values[encodedSize]; + var cos = new CodedOutputStream(outputBuffer); + for (int i = 0; i < values.Length; i++) + { + cos.WriteRawVarint32(values[i]); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + public void WriteRawVarint32_WriteContext(int encodedSize) + { + var values = varint32Values[encodedSize]; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + for (int i = 0; i < values.Length; i++) + { + ctx.WriteUInt32(values[i]); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + [Arguments(6)] + [Arguments(7)] + [Arguments(8)] + [Arguments(9)] + [Arguments(10)] + public void WriteRawVarint64_CodedOutputStream(int encodedSize) + { + var values = varint64Values[encodedSize]; + var cos = new CodedOutputStream(outputBuffer); + for (int i = 0; i < values.Length; i++) + { + cos.WriteRawVarint64(values[i]); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + [Arguments(6)] + [Arguments(7)] + [Arguments(8)] + [Arguments(9)] + [Arguments(10)] + public void WriteRawVarint64_WriteContext(int encodedSize) + { + var values = varint64Values[encodedSize]; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + for (int i = 0; i < values.Length; i++) + { + ctx.WriteUInt64(values[i]); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteFixed32_CodedOutputStream() + { + const int encodedSize = sizeof(uint); + var cos = new CodedOutputStream(outputBuffer); + for (int i = 0; i < BytesToWrite / encodedSize; i++) + { + cos.WriteFixed32(12345); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteFixed32_WriteContext() + { + const int encodedSize = sizeof(uint); + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + for (uint i = 0; i < BytesToWrite / encodedSize; i++) + { + ctx.WriteFixed32(12345); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteFixed64_CodedOutputStream() + { + const int encodedSize = sizeof(ulong); + var cos = new CodedOutputStream(outputBuffer); + for(int i = 0; i < BytesToWrite / encodedSize; i++) + { + cos.WriteFixed64(123456789); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteFixed64_WriteContext() + { + const int encodedSize = sizeof(ulong); + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + for (uint i = 0; i < BytesToWrite / encodedSize; i++) + { + ctx.WriteFixed64(123456789); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteRawTag_OneByte_WriteContext() + { + const int encodedSize = 1; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + for (uint i = 0; i < BytesToWrite / encodedSize; i++) + { + ctx.WriteRawTag(16); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteRawTag_TwoBytes_WriteContext() + { + const int encodedSize = 2; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + for (uint i = 0; i < BytesToWrite / encodedSize; i++) + { + ctx.WriteRawTag(137, 6); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteRawTag_ThreeBytes_WriteContext() + { + const int encodedSize = 3; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + for (uint i = 0; i < BytesToWrite / encodedSize; i++) + { + ctx.WriteRawTag(160, 131, 1); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void Baseline_WriteContext() + { + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + ctx.state.position = outputBuffer.Length; + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteRawFloat_CodedOutputStream() + { + var cos = new CodedOutputStream(outputBuffer); + foreach (var value in floatValues) + { + cos.WriteFloat(value); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteRawFloat_WriteContext() + { + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + foreach (var value in floatValues) + { + ctx.WriteFloat(value); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteRawDouble_CodedOutputStream() + { + var cos = new CodedOutputStream(outputBuffer); + foreach (var value in doubleValues) + { + cos.WriteDouble(value); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteRawDouble_WriteContext() + { + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + foreach (var value in doubleValues) + { + ctx.WriteDouble(value); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public void WriteString_CodedOutputStream(int encodedSize) + { + var values = stringValues[encodedSize]; + var cos = new CodedOutputStream(outputBuffer); + foreach (var value in values) + { + cos.WriteString(value); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public void WriteString_WriteContext(int encodedSize) + { + var values = stringValues[encodedSize]; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + foreach (var value in values) + { + ctx.WriteString(value); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + [ArgumentsSource(nameof(NonAsciiStringEncodedSizes))] + public void WriteNonAsciiString_CodedOutputStream(int encodedSize) + { + var values = nonAsciiStringValues[encodedSize]; + var cos = new CodedOutputStream(outputBuffer); + foreach (var value in values) + { + cos.WriteString(value); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + [ArgumentsSource(nameof(NonAsciiStringEncodedSizes))] + public void WriteNonAsciiString_WriteContext(int encodedSize) + { + var values = nonAsciiStringValues[encodedSize]; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + foreach (var value in values) + { + ctx.WriteString(value); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public void WriteBytes_CodedOutputStream(int encodedSize) + { + var values = byteStringValues[encodedSize]; + var cos = new CodedOutputStream(outputBuffer); + foreach (var value in values) + { + cos.WriteBytes(value); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public void WriteBytes_WriteContext(int encodedSize) + { + var values = byteStringValues[encodedSize]; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + foreach (var value in values) + { + ctx.WriteBytes(value); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + private static uint[] CreateRandomVarints32(Random random, int valueCount, int encodedSize) + { + var result = new uint[valueCount]; + for (int i = 0; i < valueCount; i++) + { + result[i] = (uint) ParseRawPrimitivesBenchmark.RandomUnsignedVarint(random, encodedSize, true); + } + return result; + } + + private static ulong[] CreateRandomVarints64(Random random, int valueCount, int encodedSize) + { + var result = new ulong[valueCount]; + for (int i = 0; i < valueCount; i++) + { + result[i] = ParseRawPrimitivesBenchmark.RandomUnsignedVarint(random, encodedSize, false); + } + return result; + } + + private static float[] CreateRandomFloats(Random random, int valueCount) + { + var result = new float[valueCount]; + for (int i = 0; i < valueCount; i++) + { + result[i] = (float)random.NextDouble(); + } + return result; + } + + private static double[] CreateRandomDoubles(Random random, int valueCount) + { + var result = new double[valueCount]; + for (int i = 0; i < valueCount; i++) + { + result[i] = random.NextDouble(); + } + return result; + } + + private static string[] CreateStrings(int valueCount, int encodedSize) + { + var str = ParseRawPrimitivesBenchmark.CreateStringWithEncodedSize(encodedSize); + + var result = new string[valueCount]; + for (int i = 0; i < valueCount; i++) + { + result[i] = str; + } + return result; + } + + private static string[] CreateNonAsciiStrings(int valueCount, int encodedSize) + { + var str = ParseRawPrimitivesBenchmark.CreateNonAsciiStringWithEncodedSize(encodedSize); + + var result = new string[valueCount]; + for (int i = 0; i < valueCount; i++) + { + result[i] = str; + } + return result; + } + + private static ByteString[] CreateByteStrings(int valueCount, int encodedSize) + { + var str = ParseRawPrimitivesBenchmark.CreateStringWithEncodedSize(encodedSize); + + var result = new ByteString[valueCount]; + for (int i = 0; i < valueCount; i++) + { + result[i] = ByteString.CopyFrom(Encoding.UTF8.GetBytes(str)); + } + return result; + } + } +} diff --git a/csharp/src/Google.Protobuf.Benchmarks/wrapper_benchmark_messages.proto b/csharp/src/Google.Protobuf.Benchmarks/wrapper_benchmark_messages.proto new file mode 100644 index 0000000000000..6802c252ba0c8 --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/wrapper_benchmark_messages.proto @@ -0,0 +1,237 @@ +syntax = "proto3"; + +package google.protobuf.benchmarks; + +import "google/protobuf/wrappers.proto"; + +// a message that has a large number of wrapper fields +// obfuscated version of an internal message +message ManyWrapperFieldsMessage { + google.protobuf.DoubleValue double_field_95 = 95; + google.protobuf.DoubleValue double_field_1 = 1; + google.protobuf.DoubleValue double_field_79 = 79; + google.protobuf.Int64Value int64_field_2 = 2; + google.protobuf.DoubleValue double_field_96 = 96; + google.protobuf.Int64Value int64_field_3 = 3; + google.protobuf.Int64Value int64_field_4 = 4; + google.protobuf.DoubleValue double_field_97 = 97; + google.protobuf.DoubleValue double_field_65 = 65; + google.protobuf.DoubleValue double_field_66 = 66; + google.protobuf.DoubleValue double_field_7 = 7; + google.protobuf.DoubleValue double_field_62 = 62; + google.protobuf.DoubleValue double_field_118 = 118; + google.protobuf.DoubleValue double_field_119 = 119; + google.protobuf.DoubleValue double_field_67 = 67; + google.protobuf.DoubleValue double_field_120 = 120; + google.protobuf.DoubleValue double_field_121 = 121; + google.protobuf.DoubleValue double_field_122 = 122; + google.protobuf.DoubleValue double_field_123 = 123; + google.protobuf.DoubleValue double_field_124 = 124; + google.protobuf.DoubleValue double_field_8 = 8; + google.protobuf.DoubleValue double_field_9 = 9; + google.protobuf.DoubleValue double_field_98 = 98; + google.protobuf.DoubleValue double_field_10 = 10; + google.protobuf.DoubleValue double_field_11 = 11; + google.protobuf.DoubleValue double_field_99 = 99; + google.protobuf.DoubleValue double_field_84 = 84; + google.protobuf.DoubleValue double_field_14 = 14; + google.protobuf.DoubleValue double_field_77 = 77; + google.protobuf.DoubleValue double_field_15 = 15; + google.protobuf.Int64Value int64_field_19 = 19; + google.protobuf.Int64Value int64_field_115 = 115; + google.protobuf.DoubleValue double_field_116 = 116; + google.protobuf.Int64Value int64_field_117 = 117; + google.protobuf.DoubleValue double_field_20 = 20; + google.protobuf.DoubleValue double_field_21 = 21; + google.protobuf.StringValue string_field_73 = 73; + google.protobuf.StringValue string_field_74 = 74; + google.protobuf.DoubleValue double_field_22 = 22; + google.protobuf.DoubleValue double_field_69 = 69; + google.protobuf.DoubleValue double_field_70 = 70; + google.protobuf.DoubleValue double_field_71 = 71; + google.protobuf.DoubleValue double_field_72 = 72; + google.protobuf.DoubleValue double_field_25 = 25; + google.protobuf.Int64Value int64_field_26 = 26; + google.protobuf.DoubleValue double_field_68 = 68; + google.protobuf.DoubleValue double_field_28 = 28; + google.protobuf.DoubleValue double_field_106 = 106; + google.protobuf.DoubleValue double_field_29 = 29; + google.protobuf.DoubleValue double_field_30 = 30; + google.protobuf.DoubleValue double_field_101 = 101; + google.protobuf.DoubleValue double_field_102 = 102; + google.protobuf.DoubleValue double_field_103 = 103; + google.protobuf.DoubleValue double_field_104 = 104; + google.protobuf.DoubleValue double_field_105 = 105; + google.protobuf.DoubleValue double_field_31 = 31; + google.protobuf.Int64Value int64_field_32 = 32; + google.protobuf.DoubleValue double_field_75 = 75; + google.protobuf.DoubleValue double_field_129 = 129; + int32 enum_field_80 = 80; + int32 enum_field_81 = 81; + google.protobuf.Int64Value int64_field_82 = 82; + int32 enum_field_83 = 83; + google.protobuf.Int64Value int64_field_85 = 85; + google.protobuf.Int64Value int64_field_86 = 86; + google.protobuf.Int64Value int64_field_87 = 87; + google.protobuf.Int64Value int64_field_125 = 125; + google.protobuf.Int64Value int64_field_37 = 37; + google.protobuf.DoubleValue double_field_38 = 38; + google.protobuf.Int64Value interactions = 39; + repeated int32 repeated_int_field_100 = 100; + google.protobuf.DoubleValue double_field_40 = 40; + google.protobuf.Int64Value int64_field_41 = 41; + google.protobuf.Int64Value int64_field_126 = 126; + google.protobuf.Int64Value int64_field_127 = 127; + google.protobuf.DoubleValue double_field_128 = 128; + google.protobuf.DoubleValue double_field_109 = 109; + google.protobuf.Int64Value int64_field_110 = 110; + google.protobuf.DoubleValue double_field_111 = 111; + google.protobuf.Int64Value int64_field_112 = 112; + google.protobuf.DoubleValue double_field_113 = 113; + google.protobuf.Int64Value int64_field_114 = 114; + google.protobuf.DoubleValue double_field_42 = 42; + google.protobuf.Int64Value int64_field_43 = 43; + google.protobuf.Int64Value int64_field_44 = 44; + google.protobuf.DoubleValue double_field_45 = 45; + google.protobuf.DoubleValue double_field_46 = 46; + google.protobuf.DoubleValue double_field_78 = 78; + google.protobuf.DoubleValue double_field_88 = 88; + google.protobuf.DoubleValue double_field_47 = 47; + google.protobuf.DoubleValue double_field_89 = 89; + google.protobuf.DoubleValue double_field_48 = 48; + google.protobuf.DoubleValue double_field_49 = 49; + google.protobuf.DoubleValue double_field_50 = 50; + google.protobuf.DoubleValue double_field_90 = 90; + google.protobuf.DoubleValue double_field_51 = 51; + google.protobuf.DoubleValue double_field_91 = 91; + google.protobuf.DoubleValue double_field_92 = 92; + google.protobuf.Int64Value int64_field_107 = 107; + google.protobuf.DoubleValue double_field_93 = 93; + google.protobuf.DoubleValue double_field_108 = 108; + google.protobuf.DoubleValue double_field_52 = 52; + google.protobuf.DoubleValue double_field_53 = 53; + google.protobuf.DoubleValue double_field_94 = 94; + google.protobuf.DoubleValue double_field_54 = 54; + google.protobuf.DoubleValue double_field_55 = 55; + google.protobuf.DoubleValue double_field_56 = 56; + google.protobuf.DoubleValue double_field_57 = 57; + google.protobuf.DoubleValue double_field_58 = 58; + google.protobuf.Int64Value int64_field_59 = 59; + google.protobuf.Int64Value int64_field_60 = 60; +} + +// same as ManyWrapperFieldsMessages, but with primitive fields +// for comparison. +message ManyPrimitiveFieldsMessage { + double double_field_95 = 95; + double double_field_1 = 1; + double double_field_79 = 79; + int64 int64_field_2 = 2; + double double_field_96 = 96; + int64 int64_field_3 = 3; + int64 int64_field_4 = 4; + double double_field_97 = 97; + double double_field_65 = 65; + double double_field_66 = 66; + double double_field_7 = 7; + double double_field_62 = 62; + double double_field_118 = 118; + double double_field_119 = 119; + double double_field_67 = 67; + double double_field_120 = 120; + double double_field_121 = 121; + double double_field_122 = 122; + double double_field_123 = 123; + double double_field_124 = 124; + double double_field_8 = 8; + double double_field_9 = 9; + double double_field_98 = 98; + double double_field_10 = 10; + double double_field_11 = 11; + double double_field_99 = 99; + double double_field_84 = 84; + double double_field_14 = 14; + double double_field_77 = 77; + double double_field_15 = 15; + int64 int64_field_19 = 19; + int64 int64_field_115 = 115; + double double_field_116 = 116; + int64 int64_field_117 = 117; + double double_field_20 = 20; + double double_field_21 = 21; + string string_field_73 = 73; + string string_field_74 = 74; + double double_field_22 = 22; + double double_field_69 = 69; + double double_field_70 = 70; + double double_field_71 = 71; + double double_field_72 = 72; + double double_field_25 = 25; + int64 int64_field_26 = 26; + double double_field_68 = 68; + double double_field_28 = 28; + double double_field_106 = 106; + double double_field_29 = 29; + double double_field_30 = 30; + double double_field_101 = 101; + double double_field_102 = 102; + double double_field_103 = 103; + double double_field_104 = 104; + double double_field_105 = 105; + double double_field_31 = 31; + int64 int64_field_32 = 32; + double double_field_75 = 75; + double double_field_129 = 129; + int32 enum_field_80 = 80; + int32 enum_field_81 = 81; + int64 int64_field_82 = 82; + int32 enum_field_83 = 83; + int64 int64_field_85 = 85; + int64 int64_field_86 = 86; + int64 int64_field_87 = 87; + int64 int64_field_125 = 125; + int64 int64_field_37 = 37; + double double_field_38 = 38; + int64 interactions = 39; + repeated int32 repeated_int_field_100 = 100; + double double_field_40 = 40; + int64 int64_field_41 = 41; + int64 int64_field_126 = 126; + int64 int64_field_127 = 127; + double double_field_128 = 128; + double double_field_109 = 109; + int64 int64_field_110 = 110; + double double_field_111 = 111; + int64 int64_field_112 = 112; + double double_field_113 = 113; + int64 int64_field_114 = 114; + double double_field_42 = 42; + int64 int64_field_43 = 43; + int64 int64_field_44 = 44; + double double_field_45 = 45; + double double_field_46 = 46; + double double_field_78 = 78; + double double_field_88 = 88; + double double_field_47 = 47; + double double_field_89 = 89; + double double_field_48 = 48; + double double_field_49 = 49; + double double_field_50 = 50; + double double_field_90 = 90; + double double_field_51 = 51; + double double_field_91 = 91; + double double_field_92 = 92; + int64 int64_field_107 = 107; + double double_field_93 = 93; + double double_field_108 = 108; + double double_field_52 = 52; + double double_field_53 = 53; + double double_field_94 = 94; + double double_field_54 = 54; + double double_field_55 = 55; + double double_field_56 = 56; + double double_field_57 = 57; + double double_field_58 = 58; + int64 int64_field_59 = 59; + int64 int64_field_60 = 60; +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.cs index 394607b90a819..06b61ea8bd6e4 100644 --- a/csharp/src/Google.Protobuf.Conformance/Conformance.cs +++ b/csharp/src/Google.Protobuf.Conformance/Conformance.cs @@ -1,5 +1,7 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: conformance.proto +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: conformance.proto +// #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -22,22 +24,35 @@ public static partial class ConformanceReflection { static ConformanceReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UiowEKEkNvbmZvcm1h", - "bmNlUmVxdWVzdBIaChBwcm90b2J1Zl9wYXlsb2FkGAEgASgMSAASFgoManNv", - "bl9wYXlsb2FkGAIgASgJSAASOAoXcmVxdWVzdGVkX291dHB1dF9mb3JtYXQY", - "AyABKA4yFy5jb25mb3JtYW5jZS5XaXJlRm9ybWF0EhQKDG1lc3NhZ2VfdHlw", - "ZRgEIAEoCUIJCgdwYXlsb2FkIrEBChNDb25mb3JtYW5jZVJlc3BvbnNlEhUK", - "C3BhcnNlX2Vycm9yGAEgASgJSAASGQoPc2VyaWFsaXplX2Vycm9yGAYgASgJ", - "SAASFwoNcnVudGltZV9lcnJvchgCIAEoCUgAEhoKEHByb3RvYnVmX3BheWxv", - "YWQYAyABKAxIABIWCgxqc29uX3BheWxvYWQYBCABKAlIABIRCgdza2lwcGVk", - "GAUgASgJSABCCAoGcmVzdWx0KjUKCldpcmVGb3JtYXQSDwoLVU5TUEVDSUZJ", - "RUQQABIMCghQUk9UT0JVRhABEggKBEpTT04QAkIhCh9jb20uZ29vZ2xlLnBy", - "b3RvYnVmLmNvbmZvcm1hbmNlYgZwcm90bzM=")); + "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UiHQoKRmFpbHVyZVNl", + "dBIPCgdmYWlsdXJlGAEgAygJIuMCChJDb25mb3JtYW5jZVJlcXVlc3QSGgoQ", + "cHJvdG9idWZfcGF5bG9hZBgBIAEoDEgAEhYKDGpzb25fcGF5bG9hZBgCIAEo", + "CUgAEhYKDGpzcGJfcGF5bG9hZBgHIAEoCUgAEhYKDHRleHRfcGF5bG9hZBgI", + "IAEoCUgAEjgKF3JlcXVlc3RlZF9vdXRwdXRfZm9ybWF0GAMgASgOMhcuY29u", + "Zm9ybWFuY2UuV2lyZUZvcm1hdBIUCgxtZXNzYWdlX3R5cGUYBCABKAkSMAoN", + "dGVzdF9jYXRlZ29yeRgFIAEoDjIZLmNvbmZvcm1hbmNlLlRlc3RDYXRlZ29y", + "eRI+ChVqc3BiX2VuY29kaW5nX29wdGlvbnMYBiABKAsyHy5jb25mb3JtYW5j", + "ZS5Kc3BiRW5jb2RpbmdDb25maWcSHAoUcHJpbnRfdW5rbm93bl9maWVsZHMY", + "CSABKAhCCQoHcGF5bG9hZCLhAQoTQ29uZm9ybWFuY2VSZXNwb25zZRIVCgtw", + "YXJzZV9lcnJvchgBIAEoCUgAEhkKD3NlcmlhbGl6ZV9lcnJvchgGIAEoCUgA", + "EhcKDXJ1bnRpbWVfZXJyb3IYAiABKAlIABIaChBwcm90b2J1Zl9wYXlsb2Fk", + "GAMgASgMSAASFgoManNvbl9wYXlsb2FkGAQgASgJSAASEQoHc2tpcHBlZBgF", + "IAEoCUgAEhYKDGpzcGJfcGF5bG9hZBgHIAEoCUgAEhYKDHRleHRfcGF5bG9h", + "ZBgIIAEoCUgAQggKBnJlc3VsdCI3ChJKc3BiRW5jb2RpbmdDb25maWcSIQoZ", + "dXNlX2pzcGJfYXJyYXlfYW55X2Zvcm1hdBgBIAEoCCpQCgpXaXJlRm9ybWF0", + "Eg8KC1VOU1BFQ0lGSUVEEAASDAoIUFJPVE9CVUYQARIICgRKU09OEAISCAoE", + "SlNQQhADEg8KC1RFWFRfRk9STUFUEAQqjwEKDFRlc3RDYXRlZ29yeRIUChBV", + "TlNQRUNJRklFRF9URVNUEAASDwoLQklOQVJZX1RFU1QQARINCglKU09OX1RF", + "U1QQAhIkCiBKU09OX0lHTk9SRV9VTktOT1dOX1BBUlNJTkdfVEVTVBADEg0K", + "CUpTUEJfVEVTVBAEEhQKEFRFWFRfRk9STUFUX1RFU1QQBUIhCh9jb20uZ29v", + "Z2xlLnByb3RvYnVmLmNvbmZvcm1hbmNlYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Conformance.WireFormat), }, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "RequestedOutputFormat", "MessageType" }, new[]{ "Payload" }, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "SerializeError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped" }, new[]{ "Result" }, null, null) + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Conformance.WireFormat), typeof(global::Conformance.TestCategory), }, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.FailureSet), global::Conformance.FailureSet.Parser, new[]{ "Failure" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "JspbPayload", "TextPayload", "RequestedOutputFormat", "MessageType", "TestCategory", "JspbEncodingOptions", "PrintUnknownFields" }, new[]{ "Payload" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "SerializeError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped", "JspbPayload", "TextPayload" }, new[]{ "Result" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.JspbEncodingConfig), global::Conformance.JspbEncodingConfig.Parser, new[]{ "UseJspbArrayAnyFormat" }, null, null, null, null) })); } #endregion @@ -48,11 +63,211 @@ public enum WireFormat { [pbr::OriginalName("UNSPECIFIED")] Unspecified = 0, [pbr::OriginalName("PROTOBUF")] Protobuf = 1, [pbr::OriginalName("JSON")] Json = 2, + /// + /// Google internal only. Opensource testees just skip it. + /// + [pbr::OriginalName("JSPB")] Jspb = 3, + [pbr::OriginalName("TEXT_FORMAT")] TextFormat = 4, + } + + public enum TestCategory { + [pbr::OriginalName("UNSPECIFIED_TEST")] UnspecifiedTest = 0, + /// + /// Test binary wire format. + /// + [pbr::OriginalName("BINARY_TEST")] BinaryTest = 1, + /// + /// Test json wire format. + /// + [pbr::OriginalName("JSON_TEST")] JsonTest = 2, + /// + /// Similar to JSON_TEST. However, during parsing json, testee should ignore + /// unknown fields. This feature is optional. Each implementation can decide + /// whether to support it. See + /// https://developers.google.com/protocol-buffers/docs/proto3#json_options + /// for more detail. + /// + [pbr::OriginalName("JSON_IGNORE_UNKNOWN_PARSING_TEST")] JsonIgnoreUnknownParsingTest = 3, + /// + /// Test jspb wire format. Google internal only. Opensource testees just skip it. + /// + [pbr::OriginalName("JSPB_TEST")] JspbTest = 4, + /// + /// Test text format. For cpp, java and python, testees can already deal with + /// this type. Testees of other languages can simply skip it. + /// + [pbr::OriginalName("TEXT_FORMAT_TEST")] TextFormatTest = 5, } #endregion #region Messages + /// + /// The conformance runner will request a list of failures as the first request. + /// This will be known by message_type == "conformance.FailureSet", a conformance + /// test should return a serialized FailureSet in protobuf_payload. + /// + public sealed partial class FailureSet : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FailureSet()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FailureSet() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FailureSet(FailureSet other) : this() { + failure_ = other.failure_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FailureSet Clone() { + return new FailureSet(this); + } + + /// Field number for the "failure" field. + public const int FailureFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_failure_codec + = pb::FieldCodec.ForString(10); + private readonly pbc::RepeatedField failure_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Failure { + get { return failure_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FailureSet); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FailureSet other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!failure_.Equals(other.failure_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= failure_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + failure_.WriteTo(output, _repeated_failure_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + failure_.WriteTo(ref output, _repeated_failure_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += failure_.CalculateSize(_repeated_failure_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FailureSet other) { + if (other == null) { + return; + } + failure_.Add(other.failure_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + failure_.AddEntriesFrom(input, _repeated_failure_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + failure_.AddEntriesFrom(ref input, _repeated_failure_codec); + break; + } + } + } + } + #endif + + } + /// /// Represents a single test case's input. The testee should: /// @@ -60,14 +275,19 @@ public enum WireFormat { /// 2. parse the protobuf or JSON payload in "payload" (which may fail) /// 3. if the parse succeeded, serialize the message in the requested format. /// - public sealed partial class ConformanceRequest : pb::IMessage { + public sealed partial class ConformanceRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ConformanceRequest()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { - get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[0]; } + get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -86,6 +306,9 @@ public ConformanceRequest() { public ConformanceRequest(ConformanceRequest other) : this() { requestedOutputFormat_ = other.requestedOutputFormat_; messageType_ = other.messageType_; + testCategory_ = other.testCategory_; + jspbEncodingOptions_ = other.jspbEncodingOptions_ != null ? other.jspbEncodingOptions_.Clone() : null; + printUnknownFields_ = other.printUnknownFields_; switch (other.PayloadCase) { case PayloadOneofCase.ProtobufPayload: ProtobufPayload = other.ProtobufPayload; @@ -93,8 +316,15 @@ public ConformanceRequest(ConformanceRequest other) : this() { case PayloadOneofCase.JsonPayload: JsonPayload = other.JsonPayload; break; + case PayloadOneofCase.JspbPayload: + JspbPayload = other.JspbPayload; + break; + case PayloadOneofCase.TextPayload: + TextPayload = other.TextPayload; + break; } + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -124,9 +354,34 @@ public string JsonPayload { } } + /// Field number for the "jspb_payload" field. + public const int JspbPayloadFieldNumber = 7; + /// + /// Google internal only. Opensource testees just skip it. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string JspbPayload { + get { return payloadCase_ == PayloadOneofCase.JspbPayload ? (string) payload_ : ""; } + set { + payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + payloadCase_ = PayloadOneofCase.JspbPayload; + } + } + + /// Field number for the "text_payload" field. + public const int TextPayloadFieldNumber = 8; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string TextPayload { + get { return payloadCase_ == PayloadOneofCase.TextPayload ? (string) payload_ : ""; } + set { + payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + payloadCase_ = PayloadOneofCase.TextPayload; + } + } + /// Field number for the "requested_output_format" field. public const int RequestedOutputFormatFieldNumber = 3; - private global::Conformance.WireFormat requestedOutputFormat_ = 0; + private global::Conformance.WireFormat requestedOutputFormat_ = global::Conformance.WireFormat.Unspecified; /// /// Which format should the testee serialize its message to? /// @@ -154,12 +409,59 @@ public string MessageType { } } + /// Field number for the "test_category" field. + public const int TestCategoryFieldNumber = 5; + private global::Conformance.TestCategory testCategory_ = global::Conformance.TestCategory.UnspecifiedTest; + /// + /// Each test is given a specific test category. Some category may need + /// specific support in testee programs. Refer to the definition of TestCategory + /// for more information. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Conformance.TestCategory TestCategory { + get { return testCategory_; } + set { + testCategory_ = value; + } + } + + /// Field number for the "jspb_encoding_options" field. + public const int JspbEncodingOptionsFieldNumber = 6; + private global::Conformance.JspbEncodingConfig jspbEncodingOptions_; + /// + /// Specify details for how to encode jspb. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Conformance.JspbEncodingConfig JspbEncodingOptions { + get { return jspbEncodingOptions_; } + set { + jspbEncodingOptions_ = value; + } + } + + /// Field number for the "print_unknown_fields" field. + public const int PrintUnknownFieldsFieldNumber = 9; + private bool printUnknownFields_; + /// + /// This can be used in json and text format. If true, testee should print + /// unknown fields instead of ignore. This feature is optional. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool PrintUnknownFields { + get { return printUnknownFields_; } + set { + printUnknownFields_ = value; + } + } + private object payload_; /// Enum of possible cases for the "payload" oneof. public enum PayloadOneofCase { None = 0, ProtobufPayload = 1, JsonPayload = 2, + JspbPayload = 7, + TextPayload = 8, } private PayloadOneofCase payloadCase_ = PayloadOneofCase.None; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -188,10 +490,15 @@ public bool Equals(ConformanceRequest other) { } if (ProtobufPayload != other.ProtobufPayload) return false; if (JsonPayload != other.JsonPayload) return false; + if (JspbPayload != other.JspbPayload) return false; + if (TextPayload != other.TextPayload) return false; if (RequestedOutputFormat != other.RequestedOutputFormat) return false; if (MessageType != other.MessageType) return false; + if (TestCategory != other.TestCategory) return false; + if (!object.Equals(JspbEncodingOptions, other.JspbEncodingOptions)) return false; + if (PrintUnknownFields != other.PrintUnknownFields) return false; if (PayloadCase != other.PayloadCase) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -199,9 +506,17 @@ public override int GetHashCode() { int hash = 1; if (payloadCase_ == PayloadOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode(); if (payloadCase_ == PayloadOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode(); - if (RequestedOutputFormat != 0) hash ^= RequestedOutputFormat.GetHashCode(); + if (payloadCase_ == PayloadOneofCase.JspbPayload) hash ^= JspbPayload.GetHashCode(); + if (payloadCase_ == PayloadOneofCase.TextPayload) hash ^= TextPayload.GetHashCode(); + if (RequestedOutputFormat != global::Conformance.WireFormat.Unspecified) hash ^= RequestedOutputFormat.GetHashCode(); if (MessageType.Length != 0) hash ^= MessageType.GetHashCode(); + if (TestCategory != global::Conformance.TestCategory.UnspecifiedTest) hash ^= TestCategory.GetHashCode(); + if (jspbEncodingOptions_ != null) hash ^= JspbEncodingOptions.GetHashCode(); + if (PrintUnknownFields != false) hash ^= PrintUnknownFields.GetHashCode(); hash ^= (int) payloadCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -212,6 +527,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (payloadCase_ == PayloadOneofCase.ProtobufPayload) { output.WriteRawTag(10); output.WriteBytes(ProtobufPayload); @@ -220,7 +538,7 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(18); output.WriteString(JsonPayload); } - if (RequestedOutputFormat != 0) { + if (RequestedOutputFormat != global::Conformance.WireFormat.Unspecified) { output.WriteRawTag(24); output.WriteEnum((int) RequestedOutputFormat); } @@ -228,8 +546,77 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(34); output.WriteString(MessageType); } + if (TestCategory != global::Conformance.TestCategory.UnspecifiedTest) { + output.WriteRawTag(40); + output.WriteEnum((int) TestCategory); + } + if (jspbEncodingOptions_ != null) { + output.WriteRawTag(50); + output.WriteMessage(JspbEncodingOptions); + } + if (payloadCase_ == PayloadOneofCase.JspbPayload) { + output.WriteRawTag(58); + output.WriteString(JspbPayload); + } + if (payloadCase_ == PayloadOneofCase.TextPayload) { + output.WriteRawTag(66); + output.WriteString(TextPayload); + } + if (PrintUnknownFields != false) { + output.WriteRawTag(72); + output.WriteBool(PrintUnknownFields); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (payloadCase_ == PayloadOneofCase.ProtobufPayload) { + output.WriteRawTag(10); + output.WriteBytes(ProtobufPayload); + } + if (payloadCase_ == PayloadOneofCase.JsonPayload) { + output.WriteRawTag(18); + output.WriteString(JsonPayload); + } + if (RequestedOutputFormat != global::Conformance.WireFormat.Unspecified) { + output.WriteRawTag(24); + output.WriteEnum((int) RequestedOutputFormat); + } + if (MessageType.Length != 0) { + output.WriteRawTag(34); + output.WriteString(MessageType); + } + if (TestCategory != global::Conformance.TestCategory.UnspecifiedTest) { + output.WriteRawTag(40); + output.WriteEnum((int) TestCategory); + } + if (jspbEncodingOptions_ != null) { + output.WriteRawTag(50); + output.WriteMessage(JspbEncodingOptions); + } + if (payloadCase_ == PayloadOneofCase.JspbPayload) { + output.WriteRawTag(58); + output.WriteString(JspbPayload); + } + if (payloadCase_ == PayloadOneofCase.TextPayload) { + output.WriteRawTag(66); + output.WriteString(TextPayload); + } + if (PrintUnknownFields != false) { + output.WriteRawTag(72); + output.WriteBool(PrintUnknownFields); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -239,12 +626,30 @@ public int CalculateSize() { if (payloadCase_ == PayloadOneofCase.JsonPayload) { size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonPayload); } - if (RequestedOutputFormat != 0) { + if (payloadCase_ == PayloadOneofCase.JspbPayload) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(JspbPayload); + } + if (payloadCase_ == PayloadOneofCase.TextPayload) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(TextPayload); + } + if (RequestedOutputFormat != global::Conformance.WireFormat.Unspecified) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RequestedOutputFormat); } if (MessageType.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(MessageType); } + if (TestCategory != global::Conformance.TestCategory.UnspecifiedTest) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) TestCategory); + } + if (jspbEncodingOptions_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(JspbEncodingOptions); + } + if (PrintUnknownFields != false) { + size += 1 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -253,12 +658,24 @@ public void MergeFrom(ConformanceRequest other) { if (other == null) { return; } - if (other.RequestedOutputFormat != 0) { + if (other.RequestedOutputFormat != global::Conformance.WireFormat.Unspecified) { RequestedOutputFormat = other.RequestedOutputFormat; } if (other.MessageType.Length != 0) { MessageType = other.MessageType; } + if (other.TestCategory != global::Conformance.TestCategory.UnspecifiedTest) { + TestCategory = other.TestCategory; + } + if (other.jspbEncodingOptions_ != null) { + if (jspbEncodingOptions_ == null) { + JspbEncodingOptions = new global::Conformance.JspbEncodingConfig(); + } + JspbEncodingOptions.MergeFrom(other.JspbEncodingOptions); + } + if (other.PrintUnknownFields != false) { + PrintUnknownFields = other.PrintUnknownFields; + } switch (other.PayloadCase) { case PayloadOneofCase.ProtobufPayload: ProtobufPayload = other.ProtobufPayload; @@ -266,17 +683,27 @@ public void MergeFrom(ConformanceRequest other) { case PayloadOneofCase.JsonPayload: JsonPayload = other.JsonPayload; break; + case PayloadOneofCase.JspbPayload: + JspbPayload = other.JspbPayload; + break; + case PayloadOneofCase.TextPayload: + TextPayload = other.TextPayload; + break; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { ProtobufPayload = input.ReadBytes(); @@ -287,30 +714,112 @@ public void MergeFrom(pb::CodedInputStream input) { break; } case 24: { - requestedOutputFormat_ = (global::Conformance.WireFormat) input.ReadEnum(); + RequestedOutputFormat = (global::Conformance.WireFormat) input.ReadEnum(); break; } case 34: { MessageType = input.ReadString(); break; } + case 40: { + TestCategory = (global::Conformance.TestCategory) input.ReadEnum(); + break; + } + case 50: { + if (jspbEncodingOptions_ == null) { + JspbEncodingOptions = new global::Conformance.JspbEncodingConfig(); + } + input.ReadMessage(JspbEncodingOptions); + break; + } + case 58: { + JspbPayload = input.ReadString(); + break; + } + case 66: { + TextPayload = input.ReadString(); + break; + } + case 72: { + PrintUnknownFields = input.ReadBool(); + break; + } } } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + ProtobufPayload = input.ReadBytes(); + break; + } + case 18: { + JsonPayload = input.ReadString(); + break; + } + case 24: { + RequestedOutputFormat = (global::Conformance.WireFormat) input.ReadEnum(); + break; + } + case 34: { + MessageType = input.ReadString(); + break; + } + case 40: { + TestCategory = (global::Conformance.TestCategory) input.ReadEnum(); + break; + } + case 50: { + if (jspbEncodingOptions_ == null) { + JspbEncodingOptions = new global::Conformance.JspbEncodingConfig(); + } + input.ReadMessage(JspbEncodingOptions); + break; + } + case 58: { + JspbPayload = input.ReadString(); + break; + } + case 66: { + TextPayload = input.ReadString(); + break; + } + case 72: { + PrintUnknownFields = input.ReadBool(); + break; + } + } + } + } + #endif + } /// /// Represents a single test case's output. /// - public sealed partial class ConformanceResponse : pb::IMessage { + public sealed partial class ConformanceResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ConformanceResponse()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { - get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[1]; } + get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -346,8 +855,15 @@ public ConformanceResponse(ConformanceResponse other) : this() { case ResultOneofCase.Skipped: Skipped = other.Skipped; break; + case ResultOneofCase.JspbPayload: + JspbPayload = other.JspbPayload; + break; + case ResultOneofCase.TextPayload: + TextPayload = other.TextPayload; + break; } + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -450,6 +966,37 @@ public string Skipped { } } + /// Field number for the "jspb_payload" field. + public const int JspbPayloadFieldNumber = 7; + /// + /// If the input was successfully parsed and the requested output was JSPB, + /// serialize to JSPB and set it in this field. JSPB is google internal only + /// format. Opensource testees can just skip it. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string JspbPayload { + get { return resultCase_ == ResultOneofCase.JspbPayload ? (string) result_ : ""; } + set { + result_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + resultCase_ = ResultOneofCase.JspbPayload; + } + } + + /// Field number for the "text_payload" field. + public const int TextPayloadFieldNumber = 8; + /// + /// If the input was successfully parsed and the requested output was + /// TEXT_FORMAT, serialize to TEXT_FORMAT and set it in this field. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string TextPayload { + get { return resultCase_ == ResultOneofCase.TextPayload ? (string) result_ : ""; } + set { + result_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + resultCase_ = ResultOneofCase.TextPayload; + } + } + private object result_; /// Enum of possible cases for the "result" oneof. public enum ResultOneofCase { @@ -460,6 +1007,8 @@ public enum ResultOneofCase { ProtobufPayload = 3, JsonPayload = 4, Skipped = 5, + JspbPayload = 7, + TextPayload = 8, } private ResultOneofCase resultCase_ = ResultOneofCase.None; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -492,8 +1041,10 @@ public bool Equals(ConformanceResponse other) { if (ProtobufPayload != other.ProtobufPayload) return false; if (JsonPayload != other.JsonPayload) return false; if (Skipped != other.Skipped) return false; + if (JspbPayload != other.JspbPayload) return false; + if (TextPayload != other.TextPayload) return false; if (ResultCase != other.ResultCase) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -505,7 +1056,12 @@ public override int GetHashCode() { if (resultCase_ == ResultOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode(); if (resultCase_ == ResultOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode(); if (resultCase_ == ResultOneofCase.Skipped) hash ^= Skipped.GetHashCode(); + if (resultCase_ == ResultOneofCase.JspbPayload) hash ^= JspbPayload.GetHashCode(); + if (resultCase_ == ResultOneofCase.TextPayload) hash ^= TextPayload.GetHashCode(); hash ^= (int) resultCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -516,6 +1072,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (resultCase_ == ResultOneofCase.ParseError) { output.WriteRawTag(10); output.WriteString(ParseError); @@ -540,8 +1099,61 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(50); output.WriteString(SerializeError); } + if (resultCase_ == ResultOneofCase.JspbPayload) { + output.WriteRawTag(58); + output.WriteString(JspbPayload); + } + if (resultCase_ == ResultOneofCase.TextPayload) { + output.WriteRawTag(66); + output.WriteString(TextPayload); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (resultCase_ == ResultOneofCase.ParseError) { + output.WriteRawTag(10); + output.WriteString(ParseError); + } + if (resultCase_ == ResultOneofCase.RuntimeError) { + output.WriteRawTag(18); + output.WriteString(RuntimeError); + } + if (resultCase_ == ResultOneofCase.ProtobufPayload) { + output.WriteRawTag(26); + output.WriteBytes(ProtobufPayload); + } + if (resultCase_ == ResultOneofCase.JsonPayload) { + output.WriteRawTag(34); + output.WriteString(JsonPayload); + } + if (resultCase_ == ResultOneofCase.Skipped) { + output.WriteRawTag(42); + output.WriteString(Skipped); + } + if (resultCase_ == ResultOneofCase.SerializeError) { + output.WriteRawTag(50); + output.WriteString(SerializeError); + } + if (resultCase_ == ResultOneofCase.JspbPayload) { + output.WriteRawTag(58); + output.WriteString(JspbPayload); + } + if (resultCase_ == ResultOneofCase.TextPayload) { + output.WriteRawTag(66); + output.WriteString(TextPayload); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -563,6 +1175,15 @@ public int CalculateSize() { if (resultCase_ == ResultOneofCase.Skipped) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Skipped); } + if (resultCase_ == ResultOneofCase.JspbPayload) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(JspbPayload); + } + if (resultCase_ == ResultOneofCase.TextPayload) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(TextPayload); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -590,17 +1211,73 @@ public void MergeFrom(ConformanceResponse other) { case ResultOneofCase.Skipped: Skipped = other.Skipped; break; + case ResultOneofCase.JspbPayload: + JspbPayload = other.JspbPayload; + break; + case ResultOneofCase.TextPayload: + TextPayload = other.TextPayload; + break; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + ParseError = input.ReadString(); + break; + } + case 18: { + RuntimeError = input.ReadString(); + break; + } + case 26: { + ProtobufPayload = input.ReadBytes(); + break; + } + case 34: { + JsonPayload = input.ReadString(); + break; + } + case 42: { + Skipped = input.ReadString(); + break; + } + case 50: { + SerializeError = input.ReadString(); + break; + } + case 58: { + JspbPayload = input.ReadString(); + break; + } + case 66: { + TextPayload = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { ParseError = input.ReadString(); @@ -626,9 +1303,196 @@ public void MergeFrom(pb::CodedInputStream input) { SerializeError = input.ReadString(); break; } + case 58: { + JspbPayload = input.ReadString(); + break; + } + case 66: { + TextPayload = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// Encoding options for jspb format. + /// + public sealed partial class JspbEncodingConfig : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new JspbEncodingConfig()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public JspbEncodingConfig() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public JspbEncodingConfig(JspbEncodingConfig other) : this() { + useJspbArrayAnyFormat_ = other.useJspbArrayAnyFormat_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public JspbEncodingConfig Clone() { + return new JspbEncodingConfig(this); + } + + /// Field number for the "use_jspb_array_any_format" field. + public const int UseJspbArrayAnyFormatFieldNumber = 1; + private bool useJspbArrayAnyFormat_; + /// + /// Encode the value field of Any as jspb array if true, otherwise binary. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool UseJspbArrayAnyFormat { + get { return useJspbArrayAnyFormat_; } + set { + useJspbArrayAnyFormat_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as JspbEncodingConfig); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(JspbEncodingConfig other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (UseJspbArrayAnyFormat != other.UseJspbArrayAnyFormat) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (UseJspbArrayAnyFormat != false) hash ^= UseJspbArrayAnyFormat.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (UseJspbArrayAnyFormat != false) { + output.WriteRawTag(8); + output.WriteBool(UseJspbArrayAnyFormat); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (UseJspbArrayAnyFormat != false) { + output.WriteRawTag(8); + output.WriteBool(UseJspbArrayAnyFormat); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (UseJspbArrayAnyFormat != false) { + size += 1 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(JspbEncodingConfig other) { + if (other == null) { + return; + } + if (other.UseJspbArrayAnyFormat != false) { + UseJspbArrayAnyFormat = other.UseJspbArrayAnyFormat; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + UseJspbArrayAnyFormat = input.ReadBool(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + UseJspbArrayAnyFormat = input.ReadBool(); + break; + } } } } + #endif } diff --git a/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj b/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj index b654c0b2cfdf8..ec8fb9138947c 100644 --- a/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj +++ b/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj @@ -1,7 +1,7 @@  - netcoreapp1.0 + netcoreapp2.1 Exe False diff --git a/csharp/src/Google.Protobuf.Conformance/Program.cs b/csharp/src/Google.Protobuf.Conformance/Program.cs index 96dc354e99441..d721ecfcb7afa 100644 --- a/csharp/src/Google.Protobuf.Conformance/Program.cs +++ b/csharp/src/Google.Protobuf.Conformance/Program.cs @@ -48,7 +48,9 @@ private static void Main(string[] args) // This way we get the binary streams instead of readers/writers. var input = new BinaryReader(Console.OpenStandardInput()); var output = new BinaryWriter(Console.OpenStandardOutput()); - var typeRegistry = TypeRegistry.FromMessages(ProtobufTestMessages.Proto3.TestAllTypesProto3.Descriptor); + var typeRegistry = TypeRegistry.FromMessages( + ProtobufTestMessages.Proto3.TestAllTypesProto3.Descriptor, + ProtobufTestMessages.Proto2.TestAllTypesProto2.Descriptor); int count = 0; while (RunTest(input, output, typeRegistry)) @@ -81,31 +83,52 @@ private static bool RunTest(BinaryReader input, BinaryWriter output, TypeRegistr private static ConformanceResponse PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry) { - ProtobufTestMessages.Proto3.TestAllTypesProto3 message; + ExtensionRegistry proto2ExtensionRegistry = new ExtensionRegistry + { + ProtobufTestMessages.Proto2.TestMessagesProto2Extensions.ExtensionInt32, + ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension1.Extensions.MessageSetExtension, + ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension2.Extensions.MessageSetExtension + }; + IMessage message; try { switch (request.PayloadCase) { case ConformanceRequest.PayloadOneofCase.JsonPayload: - var parser = new JsonParser(new JsonParser.Settings(20, typeRegistry)); - message = parser.Parse(request.JsonPayload); - break; - case ConformanceRequest.PayloadOneofCase.ProtobufPayload: - { - if (request.MessageType.Equals("protobuf_test_messages.proto3.TestAllTypesProto3")) + if (request.TestCategory == global::Conformance.TestCategory.JsonIgnoreUnknownParsingTest) { - message = ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser.ParseFrom(request.ProtobufPayload); - } - else if (request.MessageType.Equals("protobuf_test_messages.proto2.TestAllTypesProto2")) + return new ConformanceResponse { Skipped = "CSharp doesn't support skipping unknown fields in json parsing." }; + } + var parser = new JsonParser(new JsonParser.Settings(20, typeRegistry)); + switch (request.MessageType) { - return new ConformanceResponse { Skipped = "CSharp doesn't support proto2" }; + case "protobuf_test_messages.proto3.TestAllTypesProto3": + message = parser.Parse(request.JsonPayload); + break; + case "protobuf_test_messages.proto2.TestAllTypesProto2": + message = parser.Parse(request.JsonPayload); + break; + default: + throw new Exception($" Protobuf request doesn't have specific payload type ({request.MessageType})"); } - else + break; + case ConformanceRequest.PayloadOneofCase.ProtobufPayload: + switch (request.MessageType) { - throw new Exception(" Protobuf request doesn't have specific payload type"); + case "protobuf_test_messages.proto3.TestAllTypesProto3": + message = ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser.ParseFrom(request.ProtobufPayload); + break; + case "protobuf_test_messages.proto2.TestAllTypesProto2": + message = ProtobufTestMessages.Proto2.TestAllTypesProto2.Parser + .WithExtensionRegistry(proto2ExtensionRegistry) + .ParseFrom(request.ProtobufPayload); + break; + default: + throw new Exception($" Protobuf request doesn't have specific payload type ({request.MessageType})"); } break; - } + case ConformanceRequest.PayloadOneofCase.TextPayload: + return new ConformanceResponse { Skipped = "CSharp doesn't support text format" }; default: throw new Exception("Unsupported request payload: " + request.PayloadCase); } @@ -128,7 +151,7 @@ private static ConformanceResponse PerformRequest(ConformanceRequest request, Ty case global::Conformance.WireFormat.Protobuf: return new ConformanceResponse { ProtobufPayload = message.ToByteString() }; default: - throw new Exception("Unsupported request output format: " + request.PayloadCase); + throw new Exception("Unsupported request output format: " + request.RequestedOutputFormat); } } catch (InvalidOperationException e) diff --git a/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj b/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj index 4eda641ad67b0..fee35be9910d3 100644 --- a/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj +++ b/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj @@ -1,7 +1,7 @@  - netcoreapp1.0 + netcoreapp2.1 Exe False diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs b/csharp/src/Google.Protobuf.Test.TestProtos/ForeignMessagePartial.cs similarity index 96% rename from csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs rename to csharp/src/Google.Protobuf.Test.TestProtos/ForeignMessagePartial.cs index 5663a69902e59..909bcea96e59a 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/ForeignMessagePartial.cs @@ -39,7 +39,7 @@ public partial class ForeignMessage : ICustomDiagnosticMessage { public string ToDiagnosticString() { - return $"{{ \"c\": {C}, \"@cInHex\": \"{C:x}\" }}"; + return string.Format("{{ \"c\": {0}, \"@cInHex\": \"{0:x}\" }}", C); } } } diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/Google.Protobuf.Test.TestProtos.csproj b/csharp/src/Google.Protobuf.Test.TestProtos/Google.Protobuf.Test.TestProtos.csproj new file mode 100644 index 0000000000000..9f2ba6b0deeb9 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/Google.Protobuf.Test.TestProtos.csproj @@ -0,0 +1,25 @@ + + + + + net45;netstandard1.1;netstandard2.0 + 3.0 + ../../keys/Google.Protobuf.snk + true + False + + + + + + + + + + + + diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs new file mode 100644 index 0000000000000..bbf0061f880b1 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs @@ -0,0 +1,2126 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: map_unittest_proto3.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Google.Protobuf.TestProtos { + + /// Holder for reflection information generated from map_unittest_proto3.proto + public static partial class MapUnittestProto3Reflection { + + #region Descriptor + /// File descriptor for map_unittest_proto3.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static MapUnittestProto3Reflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChltYXBfdW5pdHRlc3RfcHJvdG8zLnByb3RvEhJwcm90b2J1Zl91bml0dGVz", + "dDMaFXVuaXR0ZXN0X3Byb3RvMy5wcm90byKpEgoHVGVzdE1hcBJHCg9tYXBf", + "aW50MzJfaW50MzIYASADKAsyLi5wcm90b2J1Zl91bml0dGVzdDMuVGVzdE1h", + "cC5NYXBJbnQzMkludDMyRW50cnkSRwoPbWFwX2ludDY0X2ludDY0GAIgAygL", + "Mi4ucHJvdG9idWZfdW5pdHRlc3QzLlRlc3RNYXAuTWFwSW50NjRJbnQ2NEVu", + "dHJ5EksKEW1hcF91aW50MzJfdWludDMyGAMgAygLMjAucHJvdG9idWZfdW5p", + "dHRlc3QzLlRlc3RNYXAuTWFwVWludDMyVWludDMyRW50cnkSSwoRbWFwX3Vp", + "bnQ2NF91aW50NjQYBCADKAsyMC5wcm90b2J1Zl91bml0dGVzdDMuVGVzdE1h", + "cC5NYXBVaW50NjRVaW50NjRFbnRyeRJLChFtYXBfc2ludDMyX3NpbnQzMhgF", + "IAMoCzIwLnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0TWFwLk1hcFNpbnQzMlNp", + "bnQzMkVudHJ5EksKEW1hcF9zaW50NjRfc2ludDY0GAYgAygLMjAucHJvdG9i", + "dWZfdW5pdHRlc3QzLlRlc3RNYXAuTWFwU2ludDY0U2ludDY0RW50cnkSTwoT", + "bWFwX2ZpeGVkMzJfZml4ZWQzMhgHIAMoCzIyLnByb3RvYnVmX3VuaXR0ZXN0", + "My5UZXN0TWFwLk1hcEZpeGVkMzJGaXhlZDMyRW50cnkSTwoTbWFwX2ZpeGVk", + "NjRfZml4ZWQ2NBgIIAMoCzIyLnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0TWFw", + "Lk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSUwoVbWFwX3NmaXhlZDMyX3NmaXhl", + "ZDMyGAkgAygLMjQucHJvdG9idWZfdW5pdHRlc3QzLlRlc3RNYXAuTWFwU2Zp", + "eGVkMzJTZml4ZWQzMkVudHJ5ElMKFW1hcF9zZml4ZWQ2NF9zZml4ZWQ2NBgK", + "IAMoCzI0LnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0TWFwLk1hcFNmaXhlZDY0", + "U2ZpeGVkNjRFbnRyeRJHCg9tYXBfaW50MzJfZmxvYXQYCyADKAsyLi5wcm90", + "b2J1Zl91bml0dGVzdDMuVGVzdE1hcC5NYXBJbnQzMkZsb2F0RW50cnkSSQoQ", + "bWFwX2ludDMyX2RvdWJsZRgMIAMoCzIvLnByb3RvYnVmX3VuaXR0ZXN0My5U", + "ZXN0TWFwLk1hcEludDMyRG91YmxlRW50cnkSQwoNbWFwX2Jvb2xfYm9vbBgN", + "IAMoCzIsLnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0TWFwLk1hcEJvb2xCb29s", + "RW50cnkSSwoRbWFwX3N0cmluZ19zdHJpbmcYDiADKAsyMC5wcm90b2J1Zl91", + "bml0dGVzdDMuVGVzdE1hcC5NYXBTdHJpbmdTdHJpbmdFbnRyeRJHCg9tYXBf", + "aW50MzJfYnl0ZXMYDyADKAsyLi5wcm90b2J1Zl91bml0dGVzdDMuVGVzdE1h", + "cC5NYXBJbnQzMkJ5dGVzRW50cnkSRQoObWFwX2ludDMyX2VudW0YECADKAsy", + "LS5wcm90b2J1Zl91bml0dGVzdDMuVGVzdE1hcC5NYXBJbnQzMkVudW1FbnRy", + "eRJaChltYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdlGBEgAygLMjcucHJvdG9i", + "dWZfdW5pdHRlc3QzLlRlc3RNYXAuTWFwSW50MzJGb3JlaWduTWVzc2FnZUVu", + "dHJ5GjQKEk1hcEludDMySW50MzJFbnRyeRILCgNrZXkYASABKAUSDQoFdmFs", + "dWUYAiABKAU6AjgBGjQKEk1hcEludDY0SW50NjRFbnRyeRILCgNrZXkYASAB", + "KAMSDQoFdmFsdWUYAiABKAM6AjgBGjYKFE1hcFVpbnQzMlVpbnQzMkVudHJ5", + "EgsKA2tleRgBIAEoDRINCgV2YWx1ZRgCIAEoDToCOAEaNgoUTWFwVWludDY0", + "VWludDY0RW50cnkSCwoDa2V5GAEgASgEEg0KBXZhbHVlGAIgASgEOgI4ARo2", + "ChRNYXBTaW50MzJTaW50MzJFbnRyeRILCgNrZXkYASABKBESDQoFdmFsdWUY", + "AiABKBE6AjgBGjYKFE1hcFNpbnQ2NFNpbnQ2NEVudHJ5EgsKA2tleRgBIAEo", + "EhINCgV2YWx1ZRgCIAEoEjoCOAEaOAoWTWFwRml4ZWQzMkZpeGVkMzJFbnRy", + "eRILCgNrZXkYASABKAcSDQoFdmFsdWUYAiABKAc6AjgBGjgKFk1hcEZpeGVk", + "NjRGaXhlZDY0RW50cnkSCwoDa2V5GAEgASgGEg0KBXZhbHVlGAIgASgGOgI4", + "ARo6ChhNYXBTZml4ZWQzMlNmaXhlZDMyRW50cnkSCwoDa2V5GAEgASgPEg0K", + "BXZhbHVlGAIgASgPOgI4ARo6ChhNYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkS", + "CwoDa2V5GAEgASgQEg0KBXZhbHVlGAIgASgQOgI4ARo0ChJNYXBJbnQzMkZs", + "b2F0RW50cnkSCwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgCOgI4ARo1ChNN", + "YXBJbnQzMkRvdWJsZUVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEo", + "AToCOAEaMgoQTWFwQm9vbEJvb2xFbnRyeRILCgNrZXkYASABKAgSDQoFdmFs", + "dWUYAiABKAg6AjgBGjYKFE1hcFN0cmluZ1N0cmluZ0VudHJ5EgsKA2tleRgB", + "IAEoCRINCgV2YWx1ZRgCIAEoCToCOAEaNAoSTWFwSW50MzJCeXRlc0VudHJ5", + "EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoDDoCOAEaUAoRTWFwSW50MzJF", + "bnVtRW50cnkSCwoDa2V5GAEgASgFEioKBXZhbHVlGAIgASgOMhsucHJvdG9i", + "dWZfdW5pdHRlc3QzLk1hcEVudW06AjgBGmEKG01hcEludDMyRm9yZWlnbk1l", + "c3NhZ2VFbnRyeRILCgNrZXkYASABKAUSMQoFdmFsdWUYAiABKAsyIi5wcm90", + "b2J1Zl91bml0dGVzdDMuRm9yZWlnbk1lc3NhZ2U6AjgBIkIKEVRlc3RNYXBT", + "dWJtZXNzYWdlEi0KCHRlc3RfbWFwGAEgASgLMhsucHJvdG9idWZfdW5pdHRl", + "c3QzLlRlc3RNYXAivgEKDlRlc3RNZXNzYWdlTWFwElIKEW1hcF9pbnQzMl9t", + "ZXNzYWdlGAEgAygLMjcucHJvdG9idWZfdW5pdHRlc3QzLlRlc3RNZXNzYWdl", + "TWFwLk1hcEludDMyTWVzc2FnZUVudHJ5GlgKFE1hcEludDMyTWVzc2FnZUVu", + "dHJ5EgsKA2tleRgBIAEoBRIvCgV2YWx1ZRgCIAEoCzIgLnByb3RvYnVmX3Vu", + "aXR0ZXN0My5UZXN0QWxsVHlwZXM6AjgBIuUBCg9UZXN0U2FtZVR5cGVNYXAS", + "OwoEbWFwMRgBIAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0U2FtZVR5", + "cGVNYXAuTWFwMUVudHJ5EjsKBG1hcDIYAiADKAsyLS5wcm90b2J1Zl91bml0", + "dGVzdDMuVGVzdFNhbWVUeXBlTWFwLk1hcDJFbnRyeRorCglNYXAxRW50cnkS", + "CwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgFOgI4ARorCglNYXAyRW50cnkS", + "CwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgFOgI4ASL1EAoMVGVzdEFyZW5h", + "TWFwEkwKD21hcF9pbnQzMl9pbnQzMhgBIAMoCzIzLnByb3RvYnVmX3VuaXR0", + "ZXN0My5UZXN0QXJlbmFNYXAuTWFwSW50MzJJbnQzMkVudHJ5EkwKD21hcF9p", + "bnQ2NF9pbnQ2NBgCIAMoCzIzLnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0QXJl", + "bmFNYXAuTWFwSW50NjRJbnQ2NEVudHJ5ElAKEW1hcF91aW50MzJfdWludDMy", + "GAMgAygLMjUucHJvdG9idWZfdW5pdHRlc3QzLlRlc3RBcmVuYU1hcC5NYXBV", + "aW50MzJVaW50MzJFbnRyeRJQChFtYXBfdWludDY0X3VpbnQ2NBgEIAMoCzI1", + "LnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0QXJlbmFNYXAuTWFwVWludDY0VWlu", + "dDY0RW50cnkSUAoRbWFwX3NpbnQzMl9zaW50MzIYBSADKAsyNS5wcm90b2J1", + "Zl91bml0dGVzdDMuVGVzdEFyZW5hTWFwLk1hcFNpbnQzMlNpbnQzMkVudHJ5", + "ElAKEW1hcF9zaW50NjRfc2ludDY0GAYgAygLMjUucHJvdG9idWZfdW5pdHRl", + "c3QzLlRlc3RBcmVuYU1hcC5NYXBTaW50NjRTaW50NjRFbnRyeRJUChNtYXBf", + "Zml4ZWQzMl9maXhlZDMyGAcgAygLMjcucHJvdG9idWZfdW5pdHRlc3QzLlRl", + "c3RBcmVuYU1hcC5NYXBGaXhlZDMyRml4ZWQzMkVudHJ5ElQKE21hcF9maXhl", + "ZDY0X2ZpeGVkNjQYCCADKAsyNy5wcm90b2J1Zl91bml0dGVzdDMuVGVzdEFy", + "ZW5hTWFwLk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSWAoVbWFwX3NmaXhlZDMy", + "X3NmaXhlZDMyGAkgAygLMjkucHJvdG9idWZfdW5pdHRlc3QzLlRlc3RBcmVu", + "YU1hcC5NYXBTZml4ZWQzMlNmaXhlZDMyRW50cnkSWAoVbWFwX3NmaXhlZDY0", + "X3NmaXhlZDY0GAogAygLMjkucHJvdG9idWZfdW5pdHRlc3QzLlRlc3RBcmVu", + "YU1hcC5NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkSTAoPbWFwX2ludDMyX2Zs", + "b2F0GAsgAygLMjMucHJvdG9idWZfdW5pdHRlc3QzLlRlc3RBcmVuYU1hcC5N", + "YXBJbnQzMkZsb2F0RW50cnkSTgoQbWFwX2ludDMyX2RvdWJsZRgMIAMoCzI0", + "LnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0QXJlbmFNYXAuTWFwSW50MzJEb3Vi", + "bGVFbnRyeRJICg1tYXBfYm9vbF9ib29sGA0gAygLMjEucHJvdG9idWZfdW5p", + "dHRlc3QzLlRlc3RBcmVuYU1hcC5NYXBCb29sQm9vbEVudHJ5EkoKDm1hcF9p", + "bnQzMl9lbnVtGA4gAygLMjIucHJvdG9idWZfdW5pdHRlc3QzLlRlc3RBcmVu", + "YU1hcC5NYXBJbnQzMkVudW1FbnRyeRJfChltYXBfaW50MzJfZm9yZWlnbl9t", + "ZXNzYWdlGA8gAygLMjwucHJvdG9idWZfdW5pdHRlc3QzLlRlc3RBcmVuYU1h", + "cC5NYXBJbnQzMkZvcmVpZ25NZXNzYWdlRW50cnkaNAoSTWFwSW50MzJJbnQz", + "MkVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEaNAoSTWFw", + "SW50NjRJbnQ2NEVudHJ5EgsKA2tleRgBIAEoAxINCgV2YWx1ZRgCIAEoAzoC", + "OAEaNgoUTWFwVWludDMyVWludDMyRW50cnkSCwoDa2V5GAEgASgNEg0KBXZh", + "bHVlGAIgASgNOgI4ARo2ChRNYXBVaW50NjRVaW50NjRFbnRyeRILCgNrZXkY", + "ASABKAQSDQoFdmFsdWUYAiABKAQ6AjgBGjYKFE1hcFNpbnQzMlNpbnQzMkVu", + "dHJ5EgsKA2tleRgBIAEoERINCgV2YWx1ZRgCIAEoEToCOAEaNgoUTWFwU2lu", + "dDY0U2ludDY0RW50cnkSCwoDa2V5GAEgASgSEg0KBXZhbHVlGAIgASgSOgI4", + "ARo4ChZNYXBGaXhlZDMyRml4ZWQzMkVudHJ5EgsKA2tleRgBIAEoBxINCgV2", + "YWx1ZRgCIAEoBzoCOAEaOAoWTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRILCgNr", + "ZXkYASABKAYSDQoFdmFsdWUYAiABKAY6AjgBGjoKGE1hcFNmaXhlZDMyU2Zp", + "eGVkMzJFbnRyeRILCgNrZXkYASABKA8SDQoFdmFsdWUYAiABKA86AjgBGjoK", + "GE1hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeRILCgNrZXkYASABKBASDQoFdmFs", + "dWUYAiABKBA6AjgBGjQKEk1hcEludDMyRmxvYXRFbnRyeRILCgNrZXkYASAB", + "KAUSDQoFdmFsdWUYAiABKAI6AjgBGjUKE01hcEludDMyRG91YmxlRW50cnkS", + "CwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgBOgI4ARoyChBNYXBCb29sQm9v", + "bEVudHJ5EgsKA2tleRgBIAEoCBINCgV2YWx1ZRgCIAEoCDoCOAEaUAoRTWFw", + "SW50MzJFbnVtRW50cnkSCwoDa2V5GAEgASgFEioKBXZhbHVlGAIgASgOMhsu", + "cHJvdG9idWZfdW5pdHRlc3QzLk1hcEVudW06AjgBGmEKG01hcEludDMyRm9y", + "ZWlnbk1lc3NhZ2VFbnRyeRILCgNrZXkYASABKAUSMQoFdmFsdWUYAiABKAsy", + "Ii5wcm90b2J1Zl91bml0dGVzdDMuRm9yZWlnbk1lc3NhZ2U6AjgBIuYBCh9N", + "ZXNzYWdlQ29udGFpbmluZ0VudW1DYWxsZWRUeXBlEksKBHR5cGUYASADKAsy", + "PS5wcm90b2J1Zl91bml0dGVzdDMuTWVzc2FnZUNvbnRhaW5pbmdFbnVtQ2Fs", + "bGVkVHlwZS5UeXBlRW50cnkaYAoJVHlwZUVudHJ5EgsKA2tleRgBIAEoBRJC", + "CgV2YWx1ZRgCIAEoCzIzLnByb3RvYnVmX3VuaXR0ZXN0My5NZXNzYWdlQ29u", + "dGFpbmluZ0VudW1DYWxsZWRUeXBlOgI4ASIUCgRUeXBlEgwKCFRZUEVfRk9P", + "EAAingEKH01lc3NhZ2VDb250YWluaW5nTWFwQ2FsbGVkRW50cnkSTQoFZW50", + "cnkYASADKAsyPi5wcm90b2J1Zl91bml0dGVzdDMuTWVzc2FnZUNvbnRhaW5p", + "bmdNYXBDYWxsZWRFbnRyeS5FbnRyeUVudHJ5GiwKCkVudHJ5RW50cnkSCwoD", + "a2V5GAEgASgFEg0KBXZhbHVlGAIgASgFOgI4ASo/CgdNYXBFbnVtEhAKDE1B", + "UF9FTlVNX0ZPTxAAEhAKDE1BUF9FTlVNX0JBUhABEhAKDE1BUF9FTlVNX0JB", + "WhACQh2qAhpHb29nbGUuUHJvdG9idWYuVGVzdFByb3Rvc2IGcHJvdG8z")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.MapEnum), }, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMap), global::Google.Protobuf.TestProtos.TestMap.Parser, new[]{ "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapInt32Bytes", "MapInt32Enum", "MapInt32ForeignMessage" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMapSubmessage), global::Google.Protobuf.TestProtos.TestMapSubmessage.Parser, new[]{ "TestMap" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMessageMap), global::Google.Protobuf.TestProtos.TestMessageMap.Parser, new[]{ "MapInt32Message" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestSameTypeMap), global::Google.Protobuf.TestProtos.TestSameTypeMap.Parser, new[]{ "Map1", "Map2" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestArenaMap), global::Google.Protobuf.TestProtos.TestArenaMap.Parser, new[]{ "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapInt32Enum", "MapInt32ForeignMessage" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType), global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Parser, new[]{ "Type" }, null, new[]{ typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Types.Type) }, null, new pbr::GeneratedClrTypeInfo[] { null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry), global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry.Parser, new[]{ "Entry" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, }) + })); + } + #endregion + + } + #region Enums + public enum MapEnum { + [pbr::OriginalName("MAP_ENUM_FOO")] Foo = 0, + [pbr::OriginalName("MAP_ENUM_BAR")] Bar = 1, + [pbr::OriginalName("MAP_ENUM_BAZ")] Baz = 2, + } + + #endregion + + #region Messages + /// + /// Tests maps. + /// + public sealed partial class TestMap : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMap()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMap() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMap(TestMap other) : this() { + mapInt32Int32_ = other.mapInt32Int32_.Clone(); + mapInt64Int64_ = other.mapInt64Int64_.Clone(); + mapUint32Uint32_ = other.mapUint32Uint32_.Clone(); + mapUint64Uint64_ = other.mapUint64Uint64_.Clone(); + mapSint32Sint32_ = other.mapSint32Sint32_.Clone(); + mapSint64Sint64_ = other.mapSint64Sint64_.Clone(); + mapFixed32Fixed32_ = other.mapFixed32Fixed32_.Clone(); + mapFixed64Fixed64_ = other.mapFixed64Fixed64_.Clone(); + mapSfixed32Sfixed32_ = other.mapSfixed32Sfixed32_.Clone(); + mapSfixed64Sfixed64_ = other.mapSfixed64Sfixed64_.Clone(); + mapInt32Float_ = other.mapInt32Float_.Clone(); + mapInt32Double_ = other.mapInt32Double_.Clone(); + mapBoolBool_ = other.mapBoolBool_.Clone(); + mapStringString_ = other.mapStringString_.Clone(); + mapInt32Bytes_ = other.mapInt32Bytes_.Clone(); + mapInt32Enum_ = other.mapInt32Enum_.Clone(); + mapInt32ForeignMessage_ = other.mapInt32ForeignMessage_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMap Clone() { + return new TestMap(this); + } + + /// Field number for the "map_int32_int32" field. + public const int MapInt32Int32FieldNumber = 1; + private static readonly pbc::MapField.Codec _map_mapInt32Int32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForInt32(16, 0), 10); + private readonly pbc::MapField mapInt32Int32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Int32 { + get { return mapInt32Int32_; } + } + + /// Field number for the "map_int64_int64" field. + public const int MapInt64Int64FieldNumber = 2; + private static readonly pbc::MapField.Codec _map_mapInt64Int64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt64(8, 0L), pb::FieldCodec.ForInt64(16, 0L), 18); + private readonly pbc::MapField mapInt64Int64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt64Int64 { + get { return mapInt64Int64_; } + } + + /// Field number for the "map_uint32_uint32" field. + public const int MapUint32Uint32FieldNumber = 3; + private static readonly pbc::MapField.Codec _map_mapUint32Uint32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForUInt32(8, 0), pb::FieldCodec.ForUInt32(16, 0), 26); + private readonly pbc::MapField mapUint32Uint32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapUint32Uint32 { + get { return mapUint32Uint32_; } + } + + /// Field number for the "map_uint64_uint64" field. + public const int MapUint64Uint64FieldNumber = 4; + private static readonly pbc::MapField.Codec _map_mapUint64Uint64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForUInt64(8, 0UL), pb::FieldCodec.ForUInt64(16, 0UL), 34); + private readonly pbc::MapField mapUint64Uint64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapUint64Uint64 { + get { return mapUint64Uint64_; } + } + + /// Field number for the "map_sint32_sint32" field. + public const int MapSint32Sint32FieldNumber = 5; + private static readonly pbc::MapField.Codec _map_mapSint32Sint32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSInt32(8, 0), pb::FieldCodec.ForSInt32(16, 0), 42); + private readonly pbc::MapField mapSint32Sint32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSint32Sint32 { + get { return mapSint32Sint32_; } + } + + /// Field number for the "map_sint64_sint64" field. + public const int MapSint64Sint64FieldNumber = 6; + private static readonly pbc::MapField.Codec _map_mapSint64Sint64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSInt64(8, 0L), pb::FieldCodec.ForSInt64(16, 0L), 50); + private readonly pbc::MapField mapSint64Sint64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSint64Sint64 { + get { return mapSint64Sint64_; } + } + + /// Field number for the "map_fixed32_fixed32" field. + public const int MapFixed32Fixed32FieldNumber = 7; + private static readonly pbc::MapField.Codec _map_mapFixed32Fixed32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForFixed32(13, 0), pb::FieldCodec.ForFixed32(21, 0), 58); + private readonly pbc::MapField mapFixed32Fixed32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapFixed32Fixed32 { + get { return mapFixed32Fixed32_; } + } + + /// Field number for the "map_fixed64_fixed64" field. + public const int MapFixed64Fixed64FieldNumber = 8; + private static readonly pbc::MapField.Codec _map_mapFixed64Fixed64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForFixed64(9, 0UL), pb::FieldCodec.ForFixed64(17, 0UL), 66); + private readonly pbc::MapField mapFixed64Fixed64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapFixed64Fixed64 { + get { return mapFixed64Fixed64_; } + } + + /// Field number for the "map_sfixed32_sfixed32" field. + public const int MapSfixed32Sfixed32FieldNumber = 9; + private static readonly pbc::MapField.Codec _map_mapSfixed32Sfixed32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSFixed32(13, 0), pb::FieldCodec.ForSFixed32(21, 0), 74); + private readonly pbc::MapField mapSfixed32Sfixed32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSfixed32Sfixed32 { + get { return mapSfixed32Sfixed32_; } + } + + /// Field number for the "map_sfixed64_sfixed64" field. + public const int MapSfixed64Sfixed64FieldNumber = 10; + private static readonly pbc::MapField.Codec _map_mapSfixed64Sfixed64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSFixed64(9, 0L), pb::FieldCodec.ForSFixed64(17, 0L), 82); + private readonly pbc::MapField mapSfixed64Sfixed64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSfixed64Sfixed64 { + get { return mapSfixed64Sfixed64_; } + } + + /// Field number for the "map_int32_float" field. + public const int MapInt32FloatFieldNumber = 11; + private static readonly pbc::MapField.Codec _map_mapInt32Float_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForFloat(21, 0F), 90); + private readonly pbc::MapField mapInt32Float_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Float { + get { return mapInt32Float_; } + } + + /// Field number for the "map_int32_double" field. + public const int MapInt32DoubleFieldNumber = 12; + private static readonly pbc::MapField.Codec _map_mapInt32Double_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForDouble(17, 0D), 98); + private readonly pbc::MapField mapInt32Double_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Double { + get { return mapInt32Double_; } + } + + /// Field number for the "map_bool_bool" field. + public const int MapBoolBoolFieldNumber = 13; + private static readonly pbc::MapField.Codec _map_mapBoolBool_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForBool(8, false), pb::FieldCodec.ForBool(16, false), 106); + private readonly pbc::MapField mapBoolBool_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapBoolBool { + get { return mapBoolBool_; } + } + + /// Field number for the "map_string_string" field. + public const int MapStringStringFieldNumber = 14; + private static readonly pbc::MapField.Codec _map_mapStringString_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForString(18, ""), 114); + private readonly pbc::MapField mapStringString_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapStringString { + get { return mapStringString_; } + } + + /// Field number for the "map_int32_bytes" field. + public const int MapInt32BytesFieldNumber = 15; + private static readonly pbc::MapField.Codec _map_mapInt32Bytes_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForBytes(18, pb::ByteString.Empty), 122); + private readonly pbc::MapField mapInt32Bytes_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Bytes { + get { return mapInt32Bytes_; } + } + + /// Field number for the "map_int32_enum" field. + public const int MapInt32EnumFieldNumber = 16; + private static readonly pbc::MapField.Codec _map_mapInt32Enum_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Google.Protobuf.TestProtos.MapEnum) x, global::Google.Protobuf.TestProtos.MapEnum.Foo), 130); + private readonly pbc::MapField mapInt32Enum_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Enum { + get { return mapInt32Enum_; } + } + + /// Field number for the "map_int32_foreign_message" field. + public const int MapInt32ForeignMessageFieldNumber = 17; + private static readonly pbc::MapField.Codec _map_mapInt32ForeignMessage_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.ForeignMessage.Parser), 138); + private readonly pbc::MapField mapInt32ForeignMessage_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32ForeignMessage { + get { return mapInt32ForeignMessage_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestMap); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestMap other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!MapInt32Int32.Equals(other.MapInt32Int32)) return false; + if (!MapInt64Int64.Equals(other.MapInt64Int64)) return false; + if (!MapUint32Uint32.Equals(other.MapUint32Uint32)) return false; + if (!MapUint64Uint64.Equals(other.MapUint64Uint64)) return false; + if (!MapSint32Sint32.Equals(other.MapSint32Sint32)) return false; + if (!MapSint64Sint64.Equals(other.MapSint64Sint64)) return false; + if (!MapFixed32Fixed32.Equals(other.MapFixed32Fixed32)) return false; + if (!MapFixed64Fixed64.Equals(other.MapFixed64Fixed64)) return false; + if (!MapSfixed32Sfixed32.Equals(other.MapSfixed32Sfixed32)) return false; + if (!MapSfixed64Sfixed64.Equals(other.MapSfixed64Sfixed64)) return false; + if (!MapInt32Float.Equals(other.MapInt32Float)) return false; + if (!MapInt32Double.Equals(other.MapInt32Double)) return false; + if (!MapBoolBool.Equals(other.MapBoolBool)) return false; + if (!MapStringString.Equals(other.MapStringString)) return false; + if (!MapInt32Bytes.Equals(other.MapInt32Bytes)) return false; + if (!MapInt32Enum.Equals(other.MapInt32Enum)) return false; + if (!MapInt32ForeignMessage.Equals(other.MapInt32ForeignMessage)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= MapInt32Int32.GetHashCode(); + hash ^= MapInt64Int64.GetHashCode(); + hash ^= MapUint32Uint32.GetHashCode(); + hash ^= MapUint64Uint64.GetHashCode(); + hash ^= MapSint32Sint32.GetHashCode(); + hash ^= MapSint64Sint64.GetHashCode(); + hash ^= MapFixed32Fixed32.GetHashCode(); + hash ^= MapFixed64Fixed64.GetHashCode(); + hash ^= MapSfixed32Sfixed32.GetHashCode(); + hash ^= MapSfixed64Sfixed64.GetHashCode(); + hash ^= MapInt32Float.GetHashCode(); + hash ^= MapInt32Double.GetHashCode(); + hash ^= MapBoolBool.GetHashCode(); + hash ^= MapStringString.GetHashCode(); + hash ^= MapInt32Bytes.GetHashCode(); + hash ^= MapInt32Enum.GetHashCode(); + hash ^= MapInt32ForeignMessage.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec); + mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec); + mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec); + mapUint64Uint64_.WriteTo(output, _map_mapUint64Uint64_codec); + mapSint32Sint32_.WriteTo(output, _map_mapSint32Sint32_codec); + mapSint64Sint64_.WriteTo(output, _map_mapSint64Sint64_codec); + mapFixed32Fixed32_.WriteTo(output, _map_mapFixed32Fixed32_codec); + mapFixed64Fixed64_.WriteTo(output, _map_mapFixed64Fixed64_codec); + mapSfixed32Sfixed32_.WriteTo(output, _map_mapSfixed32Sfixed32_codec); + mapSfixed64Sfixed64_.WriteTo(output, _map_mapSfixed64Sfixed64_codec); + mapInt32Float_.WriteTo(output, _map_mapInt32Float_codec); + mapInt32Double_.WriteTo(output, _map_mapInt32Double_codec); + mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec); + mapStringString_.WriteTo(output, _map_mapStringString_codec); + mapInt32Bytes_.WriteTo(output, _map_mapInt32Bytes_codec); + mapInt32Enum_.WriteTo(output, _map_mapInt32Enum_codec); + mapInt32ForeignMessage_.WriteTo(output, _map_mapInt32ForeignMessage_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + mapInt32Int32_.WriteTo(ref output, _map_mapInt32Int32_codec); + mapInt64Int64_.WriteTo(ref output, _map_mapInt64Int64_codec); + mapUint32Uint32_.WriteTo(ref output, _map_mapUint32Uint32_codec); + mapUint64Uint64_.WriteTo(ref output, _map_mapUint64Uint64_codec); + mapSint32Sint32_.WriteTo(ref output, _map_mapSint32Sint32_codec); + mapSint64Sint64_.WriteTo(ref output, _map_mapSint64Sint64_codec); + mapFixed32Fixed32_.WriteTo(ref output, _map_mapFixed32Fixed32_codec); + mapFixed64Fixed64_.WriteTo(ref output, _map_mapFixed64Fixed64_codec); + mapSfixed32Sfixed32_.WriteTo(ref output, _map_mapSfixed32Sfixed32_codec); + mapSfixed64Sfixed64_.WriteTo(ref output, _map_mapSfixed64Sfixed64_codec); + mapInt32Float_.WriteTo(ref output, _map_mapInt32Float_codec); + mapInt32Double_.WriteTo(ref output, _map_mapInt32Double_codec); + mapBoolBool_.WriteTo(ref output, _map_mapBoolBool_codec); + mapStringString_.WriteTo(ref output, _map_mapStringString_codec); + mapInt32Bytes_.WriteTo(ref output, _map_mapInt32Bytes_codec); + mapInt32Enum_.WriteTo(ref output, _map_mapInt32Enum_codec); + mapInt32ForeignMessage_.WriteTo(ref output, _map_mapInt32ForeignMessage_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec); + size += mapInt64Int64_.CalculateSize(_map_mapInt64Int64_codec); + size += mapUint32Uint32_.CalculateSize(_map_mapUint32Uint32_codec); + size += mapUint64Uint64_.CalculateSize(_map_mapUint64Uint64_codec); + size += mapSint32Sint32_.CalculateSize(_map_mapSint32Sint32_codec); + size += mapSint64Sint64_.CalculateSize(_map_mapSint64Sint64_codec); + size += mapFixed32Fixed32_.CalculateSize(_map_mapFixed32Fixed32_codec); + size += mapFixed64Fixed64_.CalculateSize(_map_mapFixed64Fixed64_codec); + size += mapSfixed32Sfixed32_.CalculateSize(_map_mapSfixed32Sfixed32_codec); + size += mapSfixed64Sfixed64_.CalculateSize(_map_mapSfixed64Sfixed64_codec); + size += mapInt32Float_.CalculateSize(_map_mapInt32Float_codec); + size += mapInt32Double_.CalculateSize(_map_mapInt32Double_codec); + size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec); + size += mapStringString_.CalculateSize(_map_mapStringString_codec); + size += mapInt32Bytes_.CalculateSize(_map_mapInt32Bytes_codec); + size += mapInt32Enum_.CalculateSize(_map_mapInt32Enum_codec); + size += mapInt32ForeignMessage_.CalculateSize(_map_mapInt32ForeignMessage_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestMap other) { + if (other == null) { + return; + } + mapInt32Int32_.Add(other.mapInt32Int32_); + mapInt64Int64_.Add(other.mapInt64Int64_); + mapUint32Uint32_.Add(other.mapUint32Uint32_); + mapUint64Uint64_.Add(other.mapUint64Uint64_); + mapSint32Sint32_.Add(other.mapSint32Sint32_); + mapSint64Sint64_.Add(other.mapSint64Sint64_); + mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_); + mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_); + mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_); + mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_); + mapInt32Float_.Add(other.mapInt32Float_); + mapInt32Double_.Add(other.mapInt32Double_); + mapBoolBool_.Add(other.mapBoolBool_); + mapStringString_.Add(other.mapStringString_); + mapInt32Bytes_.Add(other.mapInt32Bytes_); + mapInt32Enum_.Add(other.mapInt32Enum_); + mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec); + break; + } + case 18: { + mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec); + break; + } + case 26: { + mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec); + break; + } + case 34: { + mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec); + break; + } + case 42: { + mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec); + break; + } + case 50: { + mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec); + break; + } + case 58: { + mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec); + break; + } + case 66: { + mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec); + break; + } + case 74: { + mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec); + break; + } + case 82: { + mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec); + break; + } + case 90: { + mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec); + break; + } + case 98: { + mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec); + break; + } + case 106: { + mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec); + break; + } + case 114: { + mapStringString_.AddEntriesFrom(input, _map_mapStringString_codec); + break; + } + case 122: { + mapInt32Bytes_.AddEntriesFrom(input, _map_mapInt32Bytes_codec); + break; + } + case 130: { + mapInt32Enum_.AddEntriesFrom(input, _map_mapInt32Enum_codec); + break; + } + case 138: { + mapInt32ForeignMessage_.AddEntriesFrom(input, _map_mapInt32ForeignMessage_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + mapInt32Int32_.AddEntriesFrom(ref input, _map_mapInt32Int32_codec); + break; + } + case 18: { + mapInt64Int64_.AddEntriesFrom(ref input, _map_mapInt64Int64_codec); + break; + } + case 26: { + mapUint32Uint32_.AddEntriesFrom(ref input, _map_mapUint32Uint32_codec); + break; + } + case 34: { + mapUint64Uint64_.AddEntriesFrom(ref input, _map_mapUint64Uint64_codec); + break; + } + case 42: { + mapSint32Sint32_.AddEntriesFrom(ref input, _map_mapSint32Sint32_codec); + break; + } + case 50: { + mapSint64Sint64_.AddEntriesFrom(ref input, _map_mapSint64Sint64_codec); + break; + } + case 58: { + mapFixed32Fixed32_.AddEntriesFrom(ref input, _map_mapFixed32Fixed32_codec); + break; + } + case 66: { + mapFixed64Fixed64_.AddEntriesFrom(ref input, _map_mapFixed64Fixed64_codec); + break; + } + case 74: { + mapSfixed32Sfixed32_.AddEntriesFrom(ref input, _map_mapSfixed32Sfixed32_codec); + break; + } + case 82: { + mapSfixed64Sfixed64_.AddEntriesFrom(ref input, _map_mapSfixed64Sfixed64_codec); + break; + } + case 90: { + mapInt32Float_.AddEntriesFrom(ref input, _map_mapInt32Float_codec); + break; + } + case 98: { + mapInt32Double_.AddEntriesFrom(ref input, _map_mapInt32Double_codec); + break; + } + case 106: { + mapBoolBool_.AddEntriesFrom(ref input, _map_mapBoolBool_codec); + break; + } + case 114: { + mapStringString_.AddEntriesFrom(ref input, _map_mapStringString_codec); + break; + } + case 122: { + mapInt32Bytes_.AddEntriesFrom(ref input, _map_mapInt32Bytes_codec); + break; + } + case 130: { + mapInt32Enum_.AddEntriesFrom(ref input, _map_mapInt32Enum_codec); + break; + } + case 138: { + mapInt32ForeignMessage_.AddEntriesFrom(ref input, _map_mapInt32ForeignMessage_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestMapSubmessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMapSubmessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMapSubmessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMapSubmessage(TestMapSubmessage other) : this() { + testMap_ = other.testMap_ != null ? other.testMap_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMapSubmessage Clone() { + return new TestMapSubmessage(this); + } + + /// Field number for the "test_map" field. + public const int TestMapFieldNumber = 1; + private global::Google.Protobuf.TestProtos.TestMap testMap_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.TestMap TestMap { + get { return testMap_; } + set { + testMap_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestMapSubmessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestMapSubmessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(TestMap, other.TestMap)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (testMap_ != null) hash ^= TestMap.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (testMap_ != null) { + output.WriteRawTag(10); + output.WriteMessage(TestMap); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (testMap_ != null) { + output.WriteRawTag(10); + output.WriteMessage(TestMap); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (testMap_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(TestMap); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestMapSubmessage other) { + if (other == null) { + return; + } + if (other.testMap_ != null) { + if (testMap_ == null) { + TestMap = new global::Google.Protobuf.TestProtos.TestMap(); + } + TestMap.MergeFrom(other.TestMap); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (testMap_ == null) { + TestMap = new global::Google.Protobuf.TestProtos.TestMap(); + } + input.ReadMessage(TestMap); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (testMap_ == null) { + TestMap = new global::Google.Protobuf.TestProtos.TestMap(); + } + input.ReadMessage(TestMap); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestMessageMap : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMessageMap()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessageMap() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessageMap(TestMessageMap other) : this() { + mapInt32Message_ = other.mapInt32Message_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessageMap Clone() { + return new TestMessageMap(this); + } + + /// Field number for the "map_int32_message" field. + public const int MapInt32MessageFieldNumber = 1; + private static readonly pbc::MapField.Codec _map_mapInt32Message_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.TestAllTypes.Parser), 10); + private readonly pbc::MapField mapInt32Message_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Message { + get { return mapInt32Message_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestMessageMap); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestMessageMap other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!MapInt32Message.Equals(other.MapInt32Message)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= MapInt32Message.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + mapInt32Message_.WriteTo(output, _map_mapInt32Message_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + mapInt32Message_.WriteTo(ref output, _map_mapInt32Message_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += mapInt32Message_.CalculateSize(_map_mapInt32Message_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestMessageMap other) { + if (other == null) { + return; + } + mapInt32Message_.Add(other.mapInt32Message_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + mapInt32Message_.AddEntriesFrom(input, _map_mapInt32Message_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + mapInt32Message_.AddEntriesFrom(ref input, _map_mapInt32Message_codec); + break; + } + } + } + } + #endif + + } + + /// + /// Two map fields share the same entry default instance. + /// + public sealed partial class TestSameTypeMap : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestSameTypeMap()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestSameTypeMap() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestSameTypeMap(TestSameTypeMap other) : this() { + map1_ = other.map1_.Clone(); + map2_ = other.map2_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestSameTypeMap Clone() { + return new TestSameTypeMap(this); + } + + /// Field number for the "map1" field. + public const int Map1FieldNumber = 1; + private static readonly pbc::MapField.Codec _map_map1_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForInt32(16, 0), 10); + private readonly pbc::MapField map1_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField Map1 { + get { return map1_; } + } + + /// Field number for the "map2" field. + public const int Map2FieldNumber = 2; + private static readonly pbc::MapField.Codec _map_map2_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForInt32(16, 0), 18); + private readonly pbc::MapField map2_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField Map2 { + get { return map2_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestSameTypeMap); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestSameTypeMap other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!Map1.Equals(other.Map1)) return false; + if (!Map2.Equals(other.Map2)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= Map1.GetHashCode(); + hash ^= Map2.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + map1_.WriteTo(output, _map_map1_codec); + map2_.WriteTo(output, _map_map2_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + map1_.WriteTo(ref output, _map_map1_codec); + map2_.WriteTo(ref output, _map_map2_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += map1_.CalculateSize(_map_map1_codec); + size += map2_.CalculateSize(_map_map2_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestSameTypeMap other) { + if (other == null) { + return; + } + map1_.Add(other.map1_); + map2_.Add(other.map2_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + map1_.AddEntriesFrom(input, _map_map1_codec); + break; + } + case 18: { + map2_.AddEntriesFrom(input, _map_map2_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + map1_.AddEntriesFrom(ref input, _map_map1_codec); + break; + } + case 18: { + map2_.AddEntriesFrom(ref input, _map_map2_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestArenaMap : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestArenaMap()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestArenaMap() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestArenaMap(TestArenaMap other) : this() { + mapInt32Int32_ = other.mapInt32Int32_.Clone(); + mapInt64Int64_ = other.mapInt64Int64_.Clone(); + mapUint32Uint32_ = other.mapUint32Uint32_.Clone(); + mapUint64Uint64_ = other.mapUint64Uint64_.Clone(); + mapSint32Sint32_ = other.mapSint32Sint32_.Clone(); + mapSint64Sint64_ = other.mapSint64Sint64_.Clone(); + mapFixed32Fixed32_ = other.mapFixed32Fixed32_.Clone(); + mapFixed64Fixed64_ = other.mapFixed64Fixed64_.Clone(); + mapSfixed32Sfixed32_ = other.mapSfixed32Sfixed32_.Clone(); + mapSfixed64Sfixed64_ = other.mapSfixed64Sfixed64_.Clone(); + mapInt32Float_ = other.mapInt32Float_.Clone(); + mapInt32Double_ = other.mapInt32Double_.Clone(); + mapBoolBool_ = other.mapBoolBool_.Clone(); + mapInt32Enum_ = other.mapInt32Enum_.Clone(); + mapInt32ForeignMessage_ = other.mapInt32ForeignMessage_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestArenaMap Clone() { + return new TestArenaMap(this); + } + + /// Field number for the "map_int32_int32" field. + public const int MapInt32Int32FieldNumber = 1; + private static readonly pbc::MapField.Codec _map_mapInt32Int32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForInt32(16, 0), 10); + private readonly pbc::MapField mapInt32Int32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Int32 { + get { return mapInt32Int32_; } + } + + /// Field number for the "map_int64_int64" field. + public const int MapInt64Int64FieldNumber = 2; + private static readonly pbc::MapField.Codec _map_mapInt64Int64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt64(8, 0L), pb::FieldCodec.ForInt64(16, 0L), 18); + private readonly pbc::MapField mapInt64Int64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt64Int64 { + get { return mapInt64Int64_; } + } + + /// Field number for the "map_uint32_uint32" field. + public const int MapUint32Uint32FieldNumber = 3; + private static readonly pbc::MapField.Codec _map_mapUint32Uint32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForUInt32(8, 0), pb::FieldCodec.ForUInt32(16, 0), 26); + private readonly pbc::MapField mapUint32Uint32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapUint32Uint32 { + get { return mapUint32Uint32_; } + } + + /// Field number for the "map_uint64_uint64" field. + public const int MapUint64Uint64FieldNumber = 4; + private static readonly pbc::MapField.Codec _map_mapUint64Uint64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForUInt64(8, 0UL), pb::FieldCodec.ForUInt64(16, 0UL), 34); + private readonly pbc::MapField mapUint64Uint64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapUint64Uint64 { + get { return mapUint64Uint64_; } + } + + /// Field number for the "map_sint32_sint32" field. + public const int MapSint32Sint32FieldNumber = 5; + private static readonly pbc::MapField.Codec _map_mapSint32Sint32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSInt32(8, 0), pb::FieldCodec.ForSInt32(16, 0), 42); + private readonly pbc::MapField mapSint32Sint32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSint32Sint32 { + get { return mapSint32Sint32_; } + } + + /// Field number for the "map_sint64_sint64" field. + public const int MapSint64Sint64FieldNumber = 6; + private static readonly pbc::MapField.Codec _map_mapSint64Sint64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSInt64(8, 0L), pb::FieldCodec.ForSInt64(16, 0L), 50); + private readonly pbc::MapField mapSint64Sint64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSint64Sint64 { + get { return mapSint64Sint64_; } + } + + /// Field number for the "map_fixed32_fixed32" field. + public const int MapFixed32Fixed32FieldNumber = 7; + private static readonly pbc::MapField.Codec _map_mapFixed32Fixed32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForFixed32(13, 0), pb::FieldCodec.ForFixed32(21, 0), 58); + private readonly pbc::MapField mapFixed32Fixed32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapFixed32Fixed32 { + get { return mapFixed32Fixed32_; } + } + + /// Field number for the "map_fixed64_fixed64" field. + public const int MapFixed64Fixed64FieldNumber = 8; + private static readonly pbc::MapField.Codec _map_mapFixed64Fixed64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForFixed64(9, 0UL), pb::FieldCodec.ForFixed64(17, 0UL), 66); + private readonly pbc::MapField mapFixed64Fixed64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapFixed64Fixed64 { + get { return mapFixed64Fixed64_; } + } + + /// Field number for the "map_sfixed32_sfixed32" field. + public const int MapSfixed32Sfixed32FieldNumber = 9; + private static readonly pbc::MapField.Codec _map_mapSfixed32Sfixed32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSFixed32(13, 0), pb::FieldCodec.ForSFixed32(21, 0), 74); + private readonly pbc::MapField mapSfixed32Sfixed32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSfixed32Sfixed32 { + get { return mapSfixed32Sfixed32_; } + } + + /// Field number for the "map_sfixed64_sfixed64" field. + public const int MapSfixed64Sfixed64FieldNumber = 10; + private static readonly pbc::MapField.Codec _map_mapSfixed64Sfixed64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSFixed64(9, 0L), pb::FieldCodec.ForSFixed64(17, 0L), 82); + private readonly pbc::MapField mapSfixed64Sfixed64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSfixed64Sfixed64 { + get { return mapSfixed64Sfixed64_; } + } + + /// Field number for the "map_int32_float" field. + public const int MapInt32FloatFieldNumber = 11; + private static readonly pbc::MapField.Codec _map_mapInt32Float_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForFloat(21, 0F), 90); + private readonly pbc::MapField mapInt32Float_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Float { + get { return mapInt32Float_; } + } + + /// Field number for the "map_int32_double" field. + public const int MapInt32DoubleFieldNumber = 12; + private static readonly pbc::MapField.Codec _map_mapInt32Double_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForDouble(17, 0D), 98); + private readonly pbc::MapField mapInt32Double_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Double { + get { return mapInt32Double_; } + } + + /// Field number for the "map_bool_bool" field. + public const int MapBoolBoolFieldNumber = 13; + private static readonly pbc::MapField.Codec _map_mapBoolBool_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForBool(8, false), pb::FieldCodec.ForBool(16, false), 106); + private readonly pbc::MapField mapBoolBool_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapBoolBool { + get { return mapBoolBool_; } + } + + /// Field number for the "map_int32_enum" field. + public const int MapInt32EnumFieldNumber = 14; + private static readonly pbc::MapField.Codec _map_mapInt32Enum_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Google.Protobuf.TestProtos.MapEnum) x, global::Google.Protobuf.TestProtos.MapEnum.Foo), 114); + private readonly pbc::MapField mapInt32Enum_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Enum { + get { return mapInt32Enum_; } + } + + /// Field number for the "map_int32_foreign_message" field. + public const int MapInt32ForeignMessageFieldNumber = 15; + private static readonly pbc::MapField.Codec _map_mapInt32ForeignMessage_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.ForeignMessage.Parser), 122); + private readonly pbc::MapField mapInt32ForeignMessage_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32ForeignMessage { + get { return mapInt32ForeignMessage_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestArenaMap); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestArenaMap other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!MapInt32Int32.Equals(other.MapInt32Int32)) return false; + if (!MapInt64Int64.Equals(other.MapInt64Int64)) return false; + if (!MapUint32Uint32.Equals(other.MapUint32Uint32)) return false; + if (!MapUint64Uint64.Equals(other.MapUint64Uint64)) return false; + if (!MapSint32Sint32.Equals(other.MapSint32Sint32)) return false; + if (!MapSint64Sint64.Equals(other.MapSint64Sint64)) return false; + if (!MapFixed32Fixed32.Equals(other.MapFixed32Fixed32)) return false; + if (!MapFixed64Fixed64.Equals(other.MapFixed64Fixed64)) return false; + if (!MapSfixed32Sfixed32.Equals(other.MapSfixed32Sfixed32)) return false; + if (!MapSfixed64Sfixed64.Equals(other.MapSfixed64Sfixed64)) return false; + if (!MapInt32Float.Equals(other.MapInt32Float)) return false; + if (!MapInt32Double.Equals(other.MapInt32Double)) return false; + if (!MapBoolBool.Equals(other.MapBoolBool)) return false; + if (!MapInt32Enum.Equals(other.MapInt32Enum)) return false; + if (!MapInt32ForeignMessage.Equals(other.MapInt32ForeignMessage)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= MapInt32Int32.GetHashCode(); + hash ^= MapInt64Int64.GetHashCode(); + hash ^= MapUint32Uint32.GetHashCode(); + hash ^= MapUint64Uint64.GetHashCode(); + hash ^= MapSint32Sint32.GetHashCode(); + hash ^= MapSint64Sint64.GetHashCode(); + hash ^= MapFixed32Fixed32.GetHashCode(); + hash ^= MapFixed64Fixed64.GetHashCode(); + hash ^= MapSfixed32Sfixed32.GetHashCode(); + hash ^= MapSfixed64Sfixed64.GetHashCode(); + hash ^= MapInt32Float.GetHashCode(); + hash ^= MapInt32Double.GetHashCode(); + hash ^= MapBoolBool.GetHashCode(); + hash ^= MapInt32Enum.GetHashCode(); + hash ^= MapInt32ForeignMessage.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec); + mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec); + mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec); + mapUint64Uint64_.WriteTo(output, _map_mapUint64Uint64_codec); + mapSint32Sint32_.WriteTo(output, _map_mapSint32Sint32_codec); + mapSint64Sint64_.WriteTo(output, _map_mapSint64Sint64_codec); + mapFixed32Fixed32_.WriteTo(output, _map_mapFixed32Fixed32_codec); + mapFixed64Fixed64_.WriteTo(output, _map_mapFixed64Fixed64_codec); + mapSfixed32Sfixed32_.WriteTo(output, _map_mapSfixed32Sfixed32_codec); + mapSfixed64Sfixed64_.WriteTo(output, _map_mapSfixed64Sfixed64_codec); + mapInt32Float_.WriteTo(output, _map_mapInt32Float_codec); + mapInt32Double_.WriteTo(output, _map_mapInt32Double_codec); + mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec); + mapInt32Enum_.WriteTo(output, _map_mapInt32Enum_codec); + mapInt32ForeignMessage_.WriteTo(output, _map_mapInt32ForeignMessage_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + mapInt32Int32_.WriteTo(ref output, _map_mapInt32Int32_codec); + mapInt64Int64_.WriteTo(ref output, _map_mapInt64Int64_codec); + mapUint32Uint32_.WriteTo(ref output, _map_mapUint32Uint32_codec); + mapUint64Uint64_.WriteTo(ref output, _map_mapUint64Uint64_codec); + mapSint32Sint32_.WriteTo(ref output, _map_mapSint32Sint32_codec); + mapSint64Sint64_.WriteTo(ref output, _map_mapSint64Sint64_codec); + mapFixed32Fixed32_.WriteTo(ref output, _map_mapFixed32Fixed32_codec); + mapFixed64Fixed64_.WriteTo(ref output, _map_mapFixed64Fixed64_codec); + mapSfixed32Sfixed32_.WriteTo(ref output, _map_mapSfixed32Sfixed32_codec); + mapSfixed64Sfixed64_.WriteTo(ref output, _map_mapSfixed64Sfixed64_codec); + mapInt32Float_.WriteTo(ref output, _map_mapInt32Float_codec); + mapInt32Double_.WriteTo(ref output, _map_mapInt32Double_codec); + mapBoolBool_.WriteTo(ref output, _map_mapBoolBool_codec); + mapInt32Enum_.WriteTo(ref output, _map_mapInt32Enum_codec); + mapInt32ForeignMessage_.WriteTo(ref output, _map_mapInt32ForeignMessage_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec); + size += mapInt64Int64_.CalculateSize(_map_mapInt64Int64_codec); + size += mapUint32Uint32_.CalculateSize(_map_mapUint32Uint32_codec); + size += mapUint64Uint64_.CalculateSize(_map_mapUint64Uint64_codec); + size += mapSint32Sint32_.CalculateSize(_map_mapSint32Sint32_codec); + size += mapSint64Sint64_.CalculateSize(_map_mapSint64Sint64_codec); + size += mapFixed32Fixed32_.CalculateSize(_map_mapFixed32Fixed32_codec); + size += mapFixed64Fixed64_.CalculateSize(_map_mapFixed64Fixed64_codec); + size += mapSfixed32Sfixed32_.CalculateSize(_map_mapSfixed32Sfixed32_codec); + size += mapSfixed64Sfixed64_.CalculateSize(_map_mapSfixed64Sfixed64_codec); + size += mapInt32Float_.CalculateSize(_map_mapInt32Float_codec); + size += mapInt32Double_.CalculateSize(_map_mapInt32Double_codec); + size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec); + size += mapInt32Enum_.CalculateSize(_map_mapInt32Enum_codec); + size += mapInt32ForeignMessage_.CalculateSize(_map_mapInt32ForeignMessage_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestArenaMap other) { + if (other == null) { + return; + } + mapInt32Int32_.Add(other.mapInt32Int32_); + mapInt64Int64_.Add(other.mapInt64Int64_); + mapUint32Uint32_.Add(other.mapUint32Uint32_); + mapUint64Uint64_.Add(other.mapUint64Uint64_); + mapSint32Sint32_.Add(other.mapSint32Sint32_); + mapSint64Sint64_.Add(other.mapSint64Sint64_); + mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_); + mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_); + mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_); + mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_); + mapInt32Float_.Add(other.mapInt32Float_); + mapInt32Double_.Add(other.mapInt32Double_); + mapBoolBool_.Add(other.mapBoolBool_); + mapInt32Enum_.Add(other.mapInt32Enum_); + mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec); + break; + } + case 18: { + mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec); + break; + } + case 26: { + mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec); + break; + } + case 34: { + mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec); + break; + } + case 42: { + mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec); + break; + } + case 50: { + mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec); + break; + } + case 58: { + mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec); + break; + } + case 66: { + mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec); + break; + } + case 74: { + mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec); + break; + } + case 82: { + mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec); + break; + } + case 90: { + mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec); + break; + } + case 98: { + mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec); + break; + } + case 106: { + mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec); + break; + } + case 114: { + mapInt32Enum_.AddEntriesFrom(input, _map_mapInt32Enum_codec); + break; + } + case 122: { + mapInt32ForeignMessage_.AddEntriesFrom(input, _map_mapInt32ForeignMessage_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + mapInt32Int32_.AddEntriesFrom(ref input, _map_mapInt32Int32_codec); + break; + } + case 18: { + mapInt64Int64_.AddEntriesFrom(ref input, _map_mapInt64Int64_codec); + break; + } + case 26: { + mapUint32Uint32_.AddEntriesFrom(ref input, _map_mapUint32Uint32_codec); + break; + } + case 34: { + mapUint64Uint64_.AddEntriesFrom(ref input, _map_mapUint64Uint64_codec); + break; + } + case 42: { + mapSint32Sint32_.AddEntriesFrom(ref input, _map_mapSint32Sint32_codec); + break; + } + case 50: { + mapSint64Sint64_.AddEntriesFrom(ref input, _map_mapSint64Sint64_codec); + break; + } + case 58: { + mapFixed32Fixed32_.AddEntriesFrom(ref input, _map_mapFixed32Fixed32_codec); + break; + } + case 66: { + mapFixed64Fixed64_.AddEntriesFrom(ref input, _map_mapFixed64Fixed64_codec); + break; + } + case 74: { + mapSfixed32Sfixed32_.AddEntriesFrom(ref input, _map_mapSfixed32Sfixed32_codec); + break; + } + case 82: { + mapSfixed64Sfixed64_.AddEntriesFrom(ref input, _map_mapSfixed64Sfixed64_codec); + break; + } + case 90: { + mapInt32Float_.AddEntriesFrom(ref input, _map_mapInt32Float_codec); + break; + } + case 98: { + mapInt32Double_.AddEntriesFrom(ref input, _map_mapInt32Double_codec); + break; + } + case 106: { + mapBoolBool_.AddEntriesFrom(ref input, _map_mapBoolBool_codec); + break; + } + case 114: { + mapInt32Enum_.AddEntriesFrom(ref input, _map_mapInt32Enum_codec); + break; + } + case 122: { + mapInt32ForeignMessage_.AddEntriesFrom(ref input, _map_mapInt32ForeignMessage_codec); + break; + } + } + } + } + #endif + + } + + /// + /// Previously, message containing enum called Type cannot be used as value of + /// map field. + /// + public sealed partial class MessageContainingEnumCalledType : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageContainingEnumCalledType()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageContainingEnumCalledType() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageContainingEnumCalledType(MessageContainingEnumCalledType other) : this() { + type_ = other.type_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageContainingEnumCalledType Clone() { + return new MessageContainingEnumCalledType(this); + } + + /// Field number for the "type" field. + public const int TypeFieldNumber = 1; + private static readonly pbc::MapField.Codec _map_type_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Parser), 10); + private readonly pbc::MapField type_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField Type { + get { return type_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as MessageContainingEnumCalledType); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(MessageContainingEnumCalledType other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!Type.Equals(other.Type)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= Type.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + type_.WriteTo(output, _map_type_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + type_.WriteTo(ref output, _map_type_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += type_.CalculateSize(_map_type_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(MessageContainingEnumCalledType other) { + if (other == null) { + return; + } + type_.Add(other.type_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + type_.AddEntriesFrom(input, _map_type_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + type_.AddEntriesFrom(ref input, _map_type_codec); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the MessageContainingEnumCalledType message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum Type { + [pbr::OriginalName("TYPE_FOO")] Foo = 0, + } + + } + #endregion + + } + + /// + /// Previously, message cannot contain map field called "entry". + /// + public sealed partial class MessageContainingMapCalledEntry : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageContainingMapCalledEntry()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[6]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageContainingMapCalledEntry() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageContainingMapCalledEntry(MessageContainingMapCalledEntry other) : this() { + entry_ = other.entry_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageContainingMapCalledEntry Clone() { + return new MessageContainingMapCalledEntry(this); + } + + /// Field number for the "entry" field. + public const int EntryFieldNumber = 1; + private static readonly pbc::MapField.Codec _map_entry_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForInt32(16, 0), 10); + private readonly pbc::MapField entry_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField Entry { + get { return entry_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as MessageContainingMapCalledEntry); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(MessageContainingMapCalledEntry other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!Entry.Equals(other.Entry)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= Entry.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + entry_.WriteTo(output, _map_entry_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + entry_.WriteTo(ref output, _map_entry_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += entry_.CalculateSize(_map_entry_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(MessageContainingMapCalledEntry other) { + if (other == null) { + return; + } + entry_.Add(other.entry_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + entry_.AddEntriesFrom(input, _map_entry_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + entry_.AddEntriesFrom(ref input, _map_entry_codec); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/OldExtensions1.cs b/csharp/src/Google.Protobuf.Test.TestProtos/OldExtensions1.cs new file mode 100644 index 0000000000000..3824f4c6eabc5 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/OldExtensions1.cs @@ -0,0 +1,148 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: old_extensions1.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Google.Protobuf.TestProtos.OldGenerator { + + /// Holder for reflection information generated from old_extensions1.proto + public static partial class OldExtensions1Reflection { + + #region Descriptor + /// File descriptor for old_extensions1.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static OldExtensions1Reflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChVvbGRfZXh0ZW5zaW9uczEucHJvdG8aFW9sZF9leHRlbnNpb25zMi5wcm90", + "byINCgtUZXN0TWVzc2FnZUIqqgInR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90", + "b3MuT2xkR2VuZXJhdG9yYgZwcm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.OldGenerator.OldExtensions2Reflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.OldGenerator.TestMessage), global::Google.Protobuf.TestProtos.OldGenerator.TestMessage.Parser, null, null, null, null) + })); + } + #endregion + + } + #region Messages + /// + /// We don't use this message other than to get its descriptor. + /// + public sealed partial class TestMessage : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.OldGenerator.OldExtensions1Reflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessage(TestMessage other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessage Clone() { + return new TestMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestMessage other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + } + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/OldExtensions2.cs b/csharp/src/Google.Protobuf.Test.TestProtos/OldExtensions2.cs new file mode 100644 index 0000000000000..265dd3ba588ad --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/OldExtensions2.cs @@ -0,0 +1,40 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: old_extensions2.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Google.Protobuf.TestProtos.OldGenerator { + + /// Holder for reflection information generated from old_extensions2.proto + public static partial class OldExtensions2Reflection { + + #region Descriptor + /// File descriptor for old_extensions2.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static OldExtensions2Reflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChVvbGRfZXh0ZW5zaW9uczIucHJvdG8aIGdvb2dsZS9wcm90b2J1Zi9kZXNj", + "cmlwdG9yLnByb3RvOjQKCm1ldGhvZF9leHQSHi5nb29nbGUucHJvdG9idWYu", + "TWV0aG9kT3B0aW9ucxiHrUsgASgJQiqqAidHb29nbGUuUHJvdG9idWYuVGVz", + "dFByb3Rvcy5PbGRHZW5lcmF0b3JiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { pbr::FileDescriptor.DescriptorProtoFileDescriptor, }, + new pbr::GeneratedClrTypeInfo(null, null)); + } + #endregion + + } +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs new file mode 100644 index 0000000000000..de1ece351afca --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs @@ -0,0 +1,6592 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/test_messages_proto2.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace ProtobufTestMessages.Proto2 { + + /// Holder for reflection information generated from google/protobuf/test_messages_proto2.proto + public static partial class TestMessagesProto2Reflection { + + #region Descriptor + /// File descriptor for google/protobuf/test_messages_proto2.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static TestMessagesProto2Reflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Cipnb29nbGUvcHJvdG9idWYvdGVzdF9tZXNzYWdlc19wcm90bzIucHJvdG8S", + "HXByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8yIv45ChJUZXN0QWxsVHlw", + "ZXNQcm90bzISFgoOb3B0aW9uYWxfaW50MzIYASABKAUSFgoOb3B0aW9uYWxf", + "aW50NjQYAiABKAMSFwoPb3B0aW9uYWxfdWludDMyGAMgASgNEhcKD29wdGlv", + "bmFsX3VpbnQ2NBgEIAEoBBIXCg9vcHRpb25hbF9zaW50MzIYBSABKBESFwoP", + "b3B0aW9uYWxfc2ludDY0GAYgASgSEhgKEG9wdGlvbmFsX2ZpeGVkMzIYByAB", + "KAcSGAoQb3B0aW9uYWxfZml4ZWQ2NBgIIAEoBhIZChFvcHRpb25hbF9zZml4", + "ZWQzMhgJIAEoDxIZChFvcHRpb25hbF9zZml4ZWQ2NBgKIAEoEBIWCg5vcHRp", + "b25hbF9mbG9hdBgLIAEoAhIXCg9vcHRpb25hbF9kb3VibGUYDCABKAESFQoN", + "b3B0aW9uYWxfYm9vbBgNIAEoCBIXCg9vcHRpb25hbF9zdHJpbmcYDiABKAkS", + "FgoOb3B0aW9uYWxfYnl0ZXMYDyABKAwSYAoXb3B0aW9uYWxfbmVzdGVkX21l", + "c3NhZ2UYEiABKAsyPy5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMi5U", + "ZXN0QWxsVHlwZXNQcm90bzIuTmVzdGVkTWVzc2FnZRJVChhvcHRpb25hbF9m", + "b3JlaWduX21lc3NhZ2UYEyABKAsyMy5wcm90b2J1Zl90ZXN0X21lc3NhZ2Vz", + "LnByb3RvMi5Gb3JlaWduTWVzc2FnZVByb3RvMhJaChRvcHRpb25hbF9uZXN0", + "ZWRfZW51bRgVIAEoDjI8LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8y", + "LlRlc3RBbGxUeXBlc1Byb3RvMi5OZXN0ZWRFbnVtEk8KFW9wdGlvbmFsX2Zv", + "cmVpZ25fZW51bRgWIAEoDjIwLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJv", + "dG8yLkZvcmVpZ25FbnVtUHJvdG8yEiEKFW9wdGlvbmFsX3N0cmluZ19waWVj", + "ZRgYIAEoCUICCAISGQoNb3B0aW9uYWxfY29yZBgZIAEoCUICCAESTAoRcmVj", + "dXJzaXZlX21lc3NhZ2UYGyABKAsyMS5wcm90b2J1Zl90ZXN0X21lc3NhZ2Vz", + "LnByb3RvMi5UZXN0QWxsVHlwZXNQcm90bzISFgoOcmVwZWF0ZWRfaW50MzIY", + "HyADKAUSFgoOcmVwZWF0ZWRfaW50NjQYICADKAMSFwoPcmVwZWF0ZWRfdWlu", + "dDMyGCEgAygNEhcKD3JlcGVhdGVkX3VpbnQ2NBgiIAMoBBIXCg9yZXBlYXRl", + "ZF9zaW50MzIYIyADKBESFwoPcmVwZWF0ZWRfc2ludDY0GCQgAygSEhgKEHJl", + "cGVhdGVkX2ZpeGVkMzIYJSADKAcSGAoQcmVwZWF0ZWRfZml4ZWQ2NBgmIAMo", + "BhIZChFyZXBlYXRlZF9zZml4ZWQzMhgnIAMoDxIZChFyZXBlYXRlZF9zZml4", + "ZWQ2NBgoIAMoEBIWCg5yZXBlYXRlZF9mbG9hdBgpIAMoAhIXCg9yZXBlYXRl", + "ZF9kb3VibGUYKiADKAESFQoNcmVwZWF0ZWRfYm9vbBgrIAMoCBIXCg9yZXBl", + "YXRlZF9zdHJpbmcYLCADKAkSFgoOcmVwZWF0ZWRfYnl0ZXMYLSADKAwSYAoX", + "cmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UYMCADKAsyPy5wcm90b2J1Zl90ZXN0", + "X21lc3NhZ2VzLnByb3RvMi5UZXN0QWxsVHlwZXNQcm90bzIuTmVzdGVkTWVz", + "c2FnZRJVChhyZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UYMSADKAsyMy5wcm90", + "b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMi5Gb3JlaWduTWVzc2FnZVByb3Rv", + "MhJaChRyZXBlYXRlZF9uZXN0ZWRfZW51bRgzIAMoDjI8LnByb3RvYnVmX3Rl", + "c3RfbWVzc2FnZXMucHJvdG8yLlRlc3RBbGxUeXBlc1Byb3RvMi5OZXN0ZWRF", + "bnVtEk8KFXJlcGVhdGVkX2ZvcmVpZ25fZW51bRg0IAMoDjIwLnByb3RvYnVm", + "X3Rlc3RfbWVzc2FnZXMucHJvdG8yLkZvcmVpZ25FbnVtUHJvdG8yEiEKFXJl", + "cGVhdGVkX3N0cmluZ19waWVjZRg2IAMoCUICCAISGQoNcmVwZWF0ZWRfY29y", + "ZBg3IAMoCUICCAESGAoMcGFja2VkX2ludDMyGEsgAygFQgIQARIYCgxwYWNr", + "ZWRfaW50NjQYTCADKANCAhABEhkKDXBhY2tlZF91aW50MzIYTSADKA1CAhAB", + "EhkKDXBhY2tlZF91aW50NjQYTiADKARCAhABEhkKDXBhY2tlZF9zaW50MzIY", + "TyADKBFCAhABEhkKDXBhY2tlZF9zaW50NjQYUCADKBJCAhABEhoKDnBhY2tl", + "ZF9maXhlZDMyGFEgAygHQgIQARIaCg5wYWNrZWRfZml4ZWQ2NBhSIAMoBkIC", + "EAESGwoPcGFja2VkX3NmaXhlZDMyGFMgAygPQgIQARIbCg9wYWNrZWRfc2Zp", + "eGVkNjQYVCADKBBCAhABEhgKDHBhY2tlZF9mbG9hdBhVIAMoAkICEAESGQoN", + "cGFja2VkX2RvdWJsZRhWIAMoAUICEAESFwoLcGFja2VkX2Jvb2wYVyADKAhC", + "AhABElwKEnBhY2tlZF9uZXN0ZWRfZW51bRhYIAMoDjI8LnByb3RvYnVmX3Rl", + "c3RfbWVzc2FnZXMucHJvdG8yLlRlc3RBbGxUeXBlc1Byb3RvMi5OZXN0ZWRF", + "bnVtQgIQARIaCg51bnBhY2tlZF9pbnQzMhhZIAMoBUICEAASGgoOdW5wYWNr", + "ZWRfaW50NjQYWiADKANCAhAAEhsKD3VucGFja2VkX3VpbnQzMhhbIAMoDUIC", + "EAASGwoPdW5wYWNrZWRfdWludDY0GFwgAygEQgIQABIbCg91bnBhY2tlZF9z", + "aW50MzIYXSADKBFCAhAAEhsKD3VucGFja2VkX3NpbnQ2NBheIAMoEkICEAAS", + "HAoQdW5wYWNrZWRfZml4ZWQzMhhfIAMoB0ICEAASHAoQdW5wYWNrZWRfZml4", + "ZWQ2NBhgIAMoBkICEAASHQoRdW5wYWNrZWRfc2ZpeGVkMzIYYSADKA9CAhAA", + "Eh0KEXVucGFja2VkX3NmaXhlZDY0GGIgAygQQgIQABIaCg51bnBhY2tlZF9m", + "bG9hdBhjIAMoAkICEAASGwoPdW5wYWNrZWRfZG91YmxlGGQgAygBQgIQABIZ", + "Cg11bnBhY2tlZF9ib29sGGUgAygIQgIQABJeChR1bnBhY2tlZF9uZXN0ZWRf", + "ZW51bRhmIAMoDjI8LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8yLlRl", + "c3RBbGxUeXBlc1Byb3RvMi5OZXN0ZWRFbnVtQgIQABJdCg9tYXBfaW50MzJf", + "aW50MzIYOCADKAsyRC5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMi5U", + "ZXN0QWxsVHlwZXNQcm90bzIuTWFwSW50MzJJbnQzMkVudHJ5El0KD21hcF9p", + "bnQ2NF9pbnQ2NBg5IAMoCzJELnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJv", + "dG8yLlRlc3RBbGxUeXBlc1Byb3RvMi5NYXBJbnQ2NEludDY0RW50cnkSYQoR", + "bWFwX3VpbnQzMl91aW50MzIYOiADKAsyRi5wcm90b2J1Zl90ZXN0X21lc3Nh", + "Z2VzLnByb3RvMi5UZXN0QWxsVHlwZXNQcm90bzIuTWFwVWludDMyVWludDMy", + "RW50cnkSYQoRbWFwX3VpbnQ2NF91aW50NjQYOyADKAsyRi5wcm90b2J1Zl90", + "ZXN0X21lc3NhZ2VzLnByb3RvMi5UZXN0QWxsVHlwZXNQcm90bzIuTWFwVWlu", + "dDY0VWludDY0RW50cnkSYQoRbWFwX3NpbnQzMl9zaW50MzIYPCADKAsyRi5w", + "cm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMi5UZXN0QWxsVHlwZXNQcm90", + "bzIuTWFwU2ludDMyU2ludDMyRW50cnkSYQoRbWFwX3NpbnQ2NF9zaW50NjQY", + "PSADKAsyRi5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMi5UZXN0QWxs", + "VHlwZXNQcm90bzIuTWFwU2ludDY0U2ludDY0RW50cnkSZQoTbWFwX2ZpeGVk", + "MzJfZml4ZWQzMhg+IAMoCzJILnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJv", + "dG8yLlRlc3RBbGxUeXBlc1Byb3RvMi5NYXBGaXhlZDMyRml4ZWQzMkVudHJ5", + "EmUKE21hcF9maXhlZDY0X2ZpeGVkNjQYPyADKAsySC5wcm90b2J1Zl90ZXN0", + "X21lc3NhZ2VzLnByb3RvMi5UZXN0QWxsVHlwZXNQcm90bzIuTWFwRml4ZWQ2", + "NEZpeGVkNjRFbnRyeRJpChVtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIYQCADKAsy", + "Si5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMi5UZXN0QWxsVHlwZXNQ", + "cm90bzIuTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5EmkKFW1hcF9zZml4ZWQ2", + "NF9zZml4ZWQ2NBhBIAMoCzJKLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJv", + "dG8yLlRlc3RBbGxUeXBlc1Byb3RvMi5NYXBTZml4ZWQ2NFNmaXhlZDY0RW50", + "cnkSXQoPbWFwX2ludDMyX2Zsb2F0GEIgAygLMkQucHJvdG9idWZfdGVzdF9t", + "ZXNzYWdlcy5wcm90bzIuVGVzdEFsbFR5cGVzUHJvdG8yLk1hcEludDMyRmxv", + "YXRFbnRyeRJfChBtYXBfaW50MzJfZG91YmxlGEMgAygLMkUucHJvdG9idWZf", + "dGVzdF9tZXNzYWdlcy5wcm90bzIuVGVzdEFsbFR5cGVzUHJvdG8yLk1hcElu", + "dDMyRG91YmxlRW50cnkSWQoNbWFwX2Jvb2xfYm9vbBhEIAMoCzJCLnByb3Rv", + "YnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8yLlRlc3RBbGxUeXBlc1Byb3RvMi5N", + "YXBCb29sQm9vbEVudHJ5EmEKEW1hcF9zdHJpbmdfc3RyaW5nGEUgAygLMkYu", + "cHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzIuVGVzdEFsbFR5cGVzUHJv", + "dG8yLk1hcFN0cmluZ1N0cmluZ0VudHJ5El8KEG1hcF9zdHJpbmdfYnl0ZXMY", + "RiADKAsyRS5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMi5UZXN0QWxs", + "VHlwZXNQcm90bzIuTWFwU3RyaW5nQnl0ZXNFbnRyeRJwChltYXBfc3RyaW5n", + "X25lc3RlZF9tZXNzYWdlGEcgAygLMk0ucHJvdG9idWZfdGVzdF9tZXNzYWdl", + "cy5wcm90bzIuVGVzdEFsbFR5cGVzUHJvdG8yLk1hcFN0cmluZ05lc3RlZE1l", + "c3NhZ2VFbnRyeRJyChptYXBfc3RyaW5nX2ZvcmVpZ25fbWVzc2FnZRhIIAMo", + "CzJOLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8yLlRlc3RBbGxUeXBl", + "c1Byb3RvMi5NYXBTdHJpbmdGb3JlaWduTWVzc2FnZUVudHJ5EmoKFm1hcF9z", + "dHJpbmdfbmVzdGVkX2VudW0YSSADKAsySi5wcm90b2J1Zl90ZXN0X21lc3Nh", + "Z2VzLnByb3RvMi5UZXN0QWxsVHlwZXNQcm90bzIuTWFwU3RyaW5nTmVzdGVk", + "RW51bUVudHJ5EmwKF21hcF9zdHJpbmdfZm9yZWlnbl9lbnVtGEogAygLMksu", + "cHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzIuVGVzdEFsbFR5cGVzUHJv", + "dG8yLk1hcFN0cmluZ0ZvcmVpZ25FbnVtRW50cnkSFgoMb25lb2ZfdWludDMy", + "GG8gASgNSAASXwoUb25lb2ZfbmVzdGVkX21lc3NhZ2UYcCABKAsyPy5wcm90", + "b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMi5UZXN0QWxsVHlwZXNQcm90bzIu", + "TmVzdGVkTWVzc2FnZUgAEhYKDG9uZW9mX3N0cmluZxhxIAEoCUgAEhUKC29u", + "ZW9mX2J5dGVzGHIgASgMSAASFAoKb25lb2ZfYm9vbBhzIAEoCEgAEhYKDG9u", + "ZW9mX3VpbnQ2NBh0IAEoBEgAEhUKC29uZW9mX2Zsb2F0GHUgASgCSAASFgoM", + "b25lb2ZfZG91YmxlGHYgASgBSAASUgoKb25lb2ZfZW51bRh3IAEoDjI8LnBy", + "b3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8yLlRlc3RBbGxUeXBlc1Byb3Rv", + "Mi5OZXN0ZWRFbnVtSAASRQoEZGF0YRjJASABKAoyNi5wcm90b2J1Zl90ZXN0", + "X21lc3NhZ2VzLnByb3RvMi5UZXN0QWxsVHlwZXNQcm90bzIuRGF0YRITCgpm", + "aWVsZG5hbWUxGJEDIAEoBRIUCgtmaWVsZF9uYW1lMhiSAyABKAUSFQoMX2Zp", + "ZWxkX25hbWUzGJMDIAEoBRIWCg1maWVsZF9fbmFtZTRfGJQDIAEoBRIUCgtm", + "aWVsZDBuYW1lNRiVAyABKAUSFgoNZmllbGRfMF9uYW1lNhiWAyABKAUSEwoK", + "ZmllbGROYW1lNxiXAyABKAUSEwoKRmllbGROYW1lOBiYAyABKAUSFAoLZmll", + "bGRfTmFtZTkYmQMgASgFEhUKDEZpZWxkX05hbWUxMBiaAyABKAUSFQoMRklF", + "TERfTkFNRTExGJsDIAEoBRIVCgxGSUVMRF9uYW1lMTIYnAMgASgFEhcKDl9f", + "ZmllbGRfbmFtZTEzGJ0DIAEoBRIXCg5fX0ZpZWxkX25hbWUxNBieAyABKAUS", + "FgoNZmllbGRfX25hbWUxNRifAyABKAUSFgoNZmllbGRfX05hbWUxNhigAyAB", + "KAUSFwoOZmllbGRfbmFtZTE3X18YoQMgASgFEhcKDkZpZWxkX25hbWUxOF9f", + "GKIDIAEoBRpiCg1OZXN0ZWRNZXNzYWdlEgkKAWEYASABKAUSRgoLY29yZWN1", + "cnNpdmUYAiABKAsyMS5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMi5U", + "ZXN0QWxsVHlwZXNQcm90bzIaNAoSTWFwSW50MzJJbnQzMkVudHJ5EgsKA2tl", + "eRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEaNAoSTWFwSW50NjRJbnQ2NEVu", + "dHJ5EgsKA2tleRgBIAEoAxINCgV2YWx1ZRgCIAEoAzoCOAEaNgoUTWFwVWlu", + "dDMyVWludDMyRW50cnkSCwoDa2V5GAEgASgNEg0KBXZhbHVlGAIgASgNOgI4", + "ARo2ChRNYXBVaW50NjRVaW50NjRFbnRyeRILCgNrZXkYASABKAQSDQoFdmFs", + "dWUYAiABKAQ6AjgBGjYKFE1hcFNpbnQzMlNpbnQzMkVudHJ5EgsKA2tleRgB", + "IAEoERINCgV2YWx1ZRgCIAEoEToCOAEaNgoUTWFwU2ludDY0U2ludDY0RW50", + "cnkSCwoDa2V5GAEgASgSEg0KBXZhbHVlGAIgASgSOgI4ARo4ChZNYXBGaXhl", + "ZDMyRml4ZWQzMkVudHJ5EgsKA2tleRgBIAEoBxINCgV2YWx1ZRgCIAEoBzoC", + "OAEaOAoWTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRILCgNrZXkYASABKAYSDQoF", + "dmFsdWUYAiABKAY6AjgBGjoKGE1hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeRIL", + "CgNrZXkYASABKA8SDQoFdmFsdWUYAiABKA86AjgBGjoKGE1hcFNmaXhlZDY0", + "U2ZpeGVkNjRFbnRyeRILCgNrZXkYASABKBASDQoFdmFsdWUYAiABKBA6AjgB", + "GjQKEk1hcEludDMyRmxvYXRFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUY", + "AiABKAI6AjgBGjUKE01hcEludDMyRG91YmxlRW50cnkSCwoDa2V5GAEgASgF", + "Eg0KBXZhbHVlGAIgASgBOgI4ARoyChBNYXBCb29sQm9vbEVudHJ5EgsKA2tl", + "eRgBIAEoCBINCgV2YWx1ZRgCIAEoCDoCOAEaNgoUTWFwU3RyaW5nU3RyaW5n", + "RW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ARo1ChNNYXBT", + "dHJpbmdCeXRlc0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoDDoC", + "OAEafgobTWFwU3RyaW5nTmVzdGVkTWVzc2FnZUVudHJ5EgsKA2tleRgBIAEo", + "CRJOCgV2YWx1ZRgCIAEoCzI/LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJv", + "dG8yLlRlc3RBbGxUeXBlc1Byb3RvMi5OZXN0ZWRNZXNzYWdlOgI4ARpzChxN", + "YXBTdHJpbmdGb3JlaWduTWVzc2FnZUVudHJ5EgsKA2tleRgBIAEoCRJCCgV2", + "YWx1ZRgCIAEoCzIzLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8yLkZv", + "cmVpZ25NZXNzYWdlUHJvdG8yOgI4ARp4ChhNYXBTdHJpbmdOZXN0ZWRFbnVt", + "RW50cnkSCwoDa2V5GAEgASgJEksKBXZhbHVlGAIgASgOMjwucHJvdG9idWZf", + "dGVzdF9tZXNzYWdlcy5wcm90bzIuVGVzdEFsbFR5cGVzUHJvdG8yLk5lc3Rl", + "ZEVudW06AjgBGm0KGU1hcFN0cmluZ0ZvcmVpZ25FbnVtRW50cnkSCwoDa2V5", + "GAEgASgJEj8KBXZhbHVlGAIgASgOMjAucHJvdG9idWZfdGVzdF9tZXNzYWdl", + "cy5wcm90bzIuRm9yZWlnbkVudW1Qcm90bzI6AjgBGjMKBERhdGESFAoLZ3Jv", + "dXBfaW50MzIYygEgASgFEhUKDGdyb3VwX3VpbnQzMhjLASABKA0aIQoRTWVz", + "c2FnZVNldENvcnJlY3QqCAgEEP////8HOgIIARrgAQobTWVzc2FnZVNldENv", + "cnJlY3RFeHRlbnNpb24xEgsKA3N0chgZIAEoCTKzAQoVbWVzc2FnZV9zZXRf", + "ZXh0ZW5zaW9uEkMucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzIuVGVz", + "dEFsbFR5cGVzUHJvdG8yLk1lc3NhZ2VTZXRDb3JyZWN0GPm7XiABKAsyTS5w", + "cm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMi5UZXN0QWxsVHlwZXNQcm90", + "bzIuTWVzc2FnZVNldENvcnJlY3RFeHRlbnNpb24xGt8BChtNZXNzYWdlU2V0", + "Q29ycmVjdEV4dGVuc2lvbjISCQoBaRgJIAEoBTK0AQoVbWVzc2FnZV9zZXRf", + "ZXh0ZW5zaW9uEkMucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzIuVGVz", + "dEFsbFR5cGVzUHJvdG8yLk1lc3NhZ2VTZXRDb3JyZWN0GJCz/AEgASgLMk0u", + "cHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzIuVGVzdEFsbFR5cGVzUHJv", + "dG8yLk1lc3NhZ2VTZXRDb3JyZWN0RXh0ZW5zaW9uMiI5CgpOZXN0ZWRFbnVt", + "EgcKA0ZPTxAAEgcKA0JBUhABEgcKA0JBWhACEhAKA05FRxD///////////8B", + "KgUIeBDJAUINCgtvbmVvZl9maWVsZEoGCOgHEJBOIiEKFEZvcmVpZ25NZXNz", + "YWdlUHJvdG8yEgkKAWMYASABKAUiwQIKFVVua25vd25Ub1Rlc3RBbGxUeXBl", + "cxIXCg5vcHRpb25hbF9pbnQzMhjpByABKAUSGAoPb3B0aW9uYWxfc3RyaW5n", + "GOoHIAEoCRJMCg5uZXN0ZWRfbWVzc2FnZRjrByABKAsyMy5wcm90b2J1Zl90", + "ZXN0X21lc3NhZ2VzLnByb3RvMi5Gb3JlaWduTWVzc2FnZVByb3RvMhJaCg1v", + "cHRpb25hbGdyb3VwGOwHIAEoCjJCLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMu", + "cHJvdG8yLlVua25vd25Ub1Rlc3RBbGxUeXBlcy5PcHRpb25hbEdyb3VwEhYK", + "DW9wdGlvbmFsX2Jvb2wY7gcgASgIEhcKDnJlcGVhdGVkX2ludDMyGPMHIAMo", + "BRoaCg1PcHRpb25hbEdyb3VwEgkKAWEYASABKAUqRgoRRm9yZWlnbkVudW1Q", + "cm90bzISDwoLRk9SRUlHTl9GT08QABIPCgtGT1JFSUdOX0JBUhABEg8KC0ZP", + "UkVJR05fQkFaEAI6SgoPZXh0ZW5zaW9uX2ludDMyEjEucHJvdG9idWZfdGVz", + "dF9tZXNzYWdlcy5wcm90bzIuVGVzdEFsbFR5cGVzUHJvdG8yGHggASgFQi8K", + "KGNvbS5nb29nbGUucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzJIAfgB", + "AQ==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ProtobufTestMessages.Proto2.ForeignEnumProto2), }, new pb::Extension[] { TestMessagesProto2Extensions.ExtensionInt32 }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.TestAllTypesProto2), global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedNestedEnum", "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedNestedEnum", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OneofBool", "OneofUint64", "OneofFloat", "OneofDouble", "OneofEnum", "Data", "Fieldname1", "FieldName2", "FieldName3", "FieldName4", "Field0Name5", "Field0Name6", "FieldName7", "FieldName8", "FieldName9", "FieldName10", "FIELDNAME11", "FIELDName12", "FieldName13", "FieldName14", "FieldName15", "FieldName16", "FieldName17", "FieldName18" }, new[]{ "OneofField" }, new[]{ typeof(global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage), global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage.Parser, new[]{ "A", "Corecursive" }, null, null, null, null), + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.Data), global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.Data.Parser, new[]{ "GroupInt32", "GroupUint32" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrect), global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrect.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension1), global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension1.Parser, new[]{ "Str" }, null, null, new pb::Extension[] { global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension1.Extensions.MessageSetExtension }, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension2), global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension2.Parser, new[]{ "I" }, null, null, new pb::Extension[] { global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension2.Extensions.MessageSetExtension }, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.ForeignMessageProto2), global::ProtobufTestMessages.Proto2.ForeignMessageProto2.Parser, new[]{ "C" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes), global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Parser, new[]{ "OptionalInt32", "OptionalString", "NestedMessage", "OptionalGroup", "OptionalBool", "RepeatedInt32" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Types.OptionalGroup), global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Types.OptionalGroup.Parser, new[]{ "A" }, null, null, null, null)}) + })); + } + #endregion + + } + /// Holder for extension identifiers generated from the top level of google/protobuf/test_messages_proto2.proto + public static partial class TestMessagesProto2Extensions { + public static readonly pb::Extension ExtensionInt32 = + new pb::Extension(120, pb::FieldCodec.ForInt32(960, 0)); + } + + #region Enums + public enum ForeignEnumProto2 { + [pbr::OriginalName("FOREIGN_FOO")] ForeignFoo = 0, + [pbr::OriginalName("FOREIGN_BAR")] ForeignBar = 1, + [pbr::OriginalName("FOREIGN_BAZ")] ForeignBaz = 2, + } + + #endregion + + #region Messages + /// + /// This proto includes every type of field in both singular and repeated + /// forms. + /// + /// Also, crucially, all messages and enums in this file are eventually + /// submessages of this message. So for example, a fuzz test of TestAllTypes + /// could trigger bugs that occur in any message type in this file. We verify + /// this stays true in a unit test. + /// + public sealed partial class TestAllTypesProto2 : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestAllTypesProto2()); + private pb::UnknownFieldSet _unknownFields; + private pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + private int _hasBits0; + private int _hasBits1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufTestMessages.Proto2.TestMessagesProto2Reflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllTypesProto2() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllTypesProto2(TestAllTypesProto2 other) : this() { + _hasBits0 = other._hasBits0; + _hasBits1 = other._hasBits1; + optionalInt32_ = other.optionalInt32_; + optionalInt64_ = other.optionalInt64_; + optionalUint32_ = other.optionalUint32_; + optionalUint64_ = other.optionalUint64_; + optionalSint32_ = other.optionalSint32_; + optionalSint64_ = other.optionalSint64_; + optionalFixed32_ = other.optionalFixed32_; + optionalFixed64_ = other.optionalFixed64_; + optionalSfixed32_ = other.optionalSfixed32_; + optionalSfixed64_ = other.optionalSfixed64_; + optionalFloat_ = other.optionalFloat_; + optionalDouble_ = other.optionalDouble_; + optionalBool_ = other.optionalBool_; + optionalString_ = other.optionalString_; + optionalBytes_ = other.optionalBytes_; + optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null; + optionalForeignMessage_ = other.optionalForeignMessage_ != null ? other.optionalForeignMessage_.Clone() : null; + optionalNestedEnum_ = other.optionalNestedEnum_; + optionalForeignEnum_ = other.optionalForeignEnum_; + optionalStringPiece_ = other.optionalStringPiece_; + optionalCord_ = other.optionalCord_; + recursiveMessage_ = other.recursiveMessage_ != null ? other.recursiveMessage_.Clone() : null; + repeatedInt32_ = other.repeatedInt32_.Clone(); + repeatedInt64_ = other.repeatedInt64_.Clone(); + repeatedUint32_ = other.repeatedUint32_.Clone(); + repeatedUint64_ = other.repeatedUint64_.Clone(); + repeatedSint32_ = other.repeatedSint32_.Clone(); + repeatedSint64_ = other.repeatedSint64_.Clone(); + repeatedFixed32_ = other.repeatedFixed32_.Clone(); + repeatedFixed64_ = other.repeatedFixed64_.Clone(); + repeatedSfixed32_ = other.repeatedSfixed32_.Clone(); + repeatedSfixed64_ = other.repeatedSfixed64_.Clone(); + repeatedFloat_ = other.repeatedFloat_.Clone(); + repeatedDouble_ = other.repeatedDouble_.Clone(); + repeatedBool_ = other.repeatedBool_.Clone(); + repeatedString_ = other.repeatedString_.Clone(); + repeatedBytes_ = other.repeatedBytes_.Clone(); + repeatedNestedMessage_ = other.repeatedNestedMessage_.Clone(); + repeatedForeignMessage_ = other.repeatedForeignMessage_.Clone(); + repeatedNestedEnum_ = other.repeatedNestedEnum_.Clone(); + repeatedForeignEnum_ = other.repeatedForeignEnum_.Clone(); + repeatedStringPiece_ = other.repeatedStringPiece_.Clone(); + repeatedCord_ = other.repeatedCord_.Clone(); + packedInt32_ = other.packedInt32_.Clone(); + packedInt64_ = other.packedInt64_.Clone(); + packedUint32_ = other.packedUint32_.Clone(); + packedUint64_ = other.packedUint64_.Clone(); + packedSint32_ = other.packedSint32_.Clone(); + packedSint64_ = other.packedSint64_.Clone(); + packedFixed32_ = other.packedFixed32_.Clone(); + packedFixed64_ = other.packedFixed64_.Clone(); + packedSfixed32_ = other.packedSfixed32_.Clone(); + packedSfixed64_ = other.packedSfixed64_.Clone(); + packedFloat_ = other.packedFloat_.Clone(); + packedDouble_ = other.packedDouble_.Clone(); + packedBool_ = other.packedBool_.Clone(); + packedNestedEnum_ = other.packedNestedEnum_.Clone(); + unpackedInt32_ = other.unpackedInt32_.Clone(); + unpackedInt64_ = other.unpackedInt64_.Clone(); + unpackedUint32_ = other.unpackedUint32_.Clone(); + unpackedUint64_ = other.unpackedUint64_.Clone(); + unpackedSint32_ = other.unpackedSint32_.Clone(); + unpackedSint64_ = other.unpackedSint64_.Clone(); + unpackedFixed32_ = other.unpackedFixed32_.Clone(); + unpackedFixed64_ = other.unpackedFixed64_.Clone(); + unpackedSfixed32_ = other.unpackedSfixed32_.Clone(); + unpackedSfixed64_ = other.unpackedSfixed64_.Clone(); + unpackedFloat_ = other.unpackedFloat_.Clone(); + unpackedDouble_ = other.unpackedDouble_.Clone(); + unpackedBool_ = other.unpackedBool_.Clone(); + unpackedNestedEnum_ = other.unpackedNestedEnum_.Clone(); + mapInt32Int32_ = other.mapInt32Int32_.Clone(); + mapInt64Int64_ = other.mapInt64Int64_.Clone(); + mapUint32Uint32_ = other.mapUint32Uint32_.Clone(); + mapUint64Uint64_ = other.mapUint64Uint64_.Clone(); + mapSint32Sint32_ = other.mapSint32Sint32_.Clone(); + mapSint64Sint64_ = other.mapSint64Sint64_.Clone(); + mapFixed32Fixed32_ = other.mapFixed32Fixed32_.Clone(); + mapFixed64Fixed64_ = other.mapFixed64Fixed64_.Clone(); + mapSfixed32Sfixed32_ = other.mapSfixed32Sfixed32_.Clone(); + mapSfixed64Sfixed64_ = other.mapSfixed64Sfixed64_.Clone(); + mapInt32Float_ = other.mapInt32Float_.Clone(); + mapInt32Double_ = other.mapInt32Double_.Clone(); + mapBoolBool_ = other.mapBoolBool_.Clone(); + mapStringString_ = other.mapStringString_.Clone(); + mapStringBytes_ = other.mapStringBytes_.Clone(); + mapStringNestedMessage_ = other.mapStringNestedMessage_.Clone(); + mapStringForeignMessage_ = other.mapStringForeignMessage_.Clone(); + mapStringNestedEnum_ = other.mapStringNestedEnum_.Clone(); + mapStringForeignEnum_ = other.mapStringForeignEnum_.Clone(); + data_ = other.HasData ? other.data_.Clone() : null; + fieldname1_ = other.fieldname1_; + fieldName2_ = other.fieldName2_; + FieldName3_ = other.FieldName3_; + fieldName4_ = other.fieldName4_; + field0Name5_ = other.field0Name5_; + field0Name6_ = other.field0Name6_; + fieldName7_ = other.fieldName7_; + fieldName8_ = other.fieldName8_; + fieldName9_ = other.fieldName9_; + fieldName10_ = other.fieldName10_; + fIELDNAME11_ = other.fIELDNAME11_; + fIELDName12_ = other.fIELDName12_; + FieldName13_ = other.FieldName13_; + FieldName14_ = other.FieldName14_; + fieldName15_ = other.fieldName15_; + fieldName16_ = other.fieldName16_; + fieldName17_ = other.fieldName17_; + fieldName18_ = other.fieldName18_; + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: + OneofUint32 = other.OneofUint32; + break; + case OneofFieldOneofCase.OneofNestedMessage: + OneofNestedMessage = other.OneofNestedMessage.Clone(); + break; + case OneofFieldOneofCase.OneofString: + OneofString = other.OneofString; + break; + case OneofFieldOneofCase.OneofBytes: + OneofBytes = other.OneofBytes; + break; + case OneofFieldOneofCase.OneofBool: + OneofBool = other.OneofBool; + break; + case OneofFieldOneofCase.OneofUint64: + OneofUint64 = other.OneofUint64; + break; + case OneofFieldOneofCase.OneofFloat: + OneofFloat = other.OneofFloat; + break; + case OneofFieldOneofCase.OneofDouble: + OneofDouble = other.OneofDouble; + break; + case OneofFieldOneofCase.OneofEnum: + OneofEnum = other.OneofEnum; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllTypesProto2 Clone() { + return new TestAllTypesProto2(this); + } + + /// Field number for the "optional_int32" field. + public const int OptionalInt32FieldNumber = 1; + private readonly static int OptionalInt32DefaultValue = 0; + + private int optionalInt32_; + /// + /// Singular + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalInt32 { + get { if ((_hasBits0 & 1) != 0) { return optionalInt32_; } else { return OptionalInt32DefaultValue; } } + set { + _hasBits0 |= 1; + optionalInt32_ = value; + } + } + /// Gets whether the "optional_int32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalInt32 { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "optional_int32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalInt32() { + _hasBits0 &= ~1; + } + + /// Field number for the "optional_int64" field. + public const int OptionalInt64FieldNumber = 2; + private readonly static long OptionalInt64DefaultValue = 0L; + + private long optionalInt64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalInt64 { + get { if ((_hasBits0 & 2) != 0) { return optionalInt64_; } else { return OptionalInt64DefaultValue; } } + set { + _hasBits0 |= 2; + optionalInt64_ = value; + } + } + /// Gets whether the "optional_int64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalInt64 { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "optional_int64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalInt64() { + _hasBits0 &= ~2; + } + + /// Field number for the "optional_uint32" field. + public const int OptionalUint32FieldNumber = 3; + private readonly static uint OptionalUint32DefaultValue = 0; + + private uint optionalUint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OptionalUint32 { + get { if ((_hasBits0 & 4) != 0) { return optionalUint32_; } else { return OptionalUint32DefaultValue; } } + set { + _hasBits0 |= 4; + optionalUint32_ = value; + } + } + /// Gets whether the "optional_uint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalUint32 { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "optional_uint32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalUint32() { + _hasBits0 &= ~4; + } + + /// Field number for the "optional_uint64" field. + public const int OptionalUint64FieldNumber = 4; + private readonly static ulong OptionalUint64DefaultValue = 0UL; + + private ulong optionalUint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong OptionalUint64 { + get { if ((_hasBits0 & 8) != 0) { return optionalUint64_; } else { return OptionalUint64DefaultValue; } } + set { + _hasBits0 |= 8; + optionalUint64_ = value; + } + } + /// Gets whether the "optional_uint64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalUint64 { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "optional_uint64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalUint64() { + _hasBits0 &= ~8; + } + + /// Field number for the "optional_sint32" field. + public const int OptionalSint32FieldNumber = 5; + private readonly static int OptionalSint32DefaultValue = 0; + + private int optionalSint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalSint32 { + get { if ((_hasBits0 & 16) != 0) { return optionalSint32_; } else { return OptionalSint32DefaultValue; } } + set { + _hasBits0 |= 16; + optionalSint32_ = value; + } + } + /// Gets whether the "optional_sint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSint32 { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "optional_sint32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSint32() { + _hasBits0 &= ~16; + } + + /// Field number for the "optional_sint64" field. + public const int OptionalSint64FieldNumber = 6; + private readonly static long OptionalSint64DefaultValue = 0L; + + private long optionalSint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalSint64 { + get { if ((_hasBits0 & 32) != 0) { return optionalSint64_; } else { return OptionalSint64DefaultValue; } } + set { + _hasBits0 |= 32; + optionalSint64_ = value; + } + } + /// Gets whether the "optional_sint64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSint64 { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "optional_sint64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSint64() { + _hasBits0 &= ~32; + } + + /// Field number for the "optional_fixed32" field. + public const int OptionalFixed32FieldNumber = 7; + private readonly static uint OptionalFixed32DefaultValue = 0; + + private uint optionalFixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OptionalFixed32 { + get { if ((_hasBits0 & 64) != 0) { return optionalFixed32_; } else { return OptionalFixed32DefaultValue; } } + set { + _hasBits0 |= 64; + optionalFixed32_ = value; + } + } + /// Gets whether the "optional_fixed32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalFixed32 { + get { return (_hasBits0 & 64) != 0; } + } + /// Clears the value of the "optional_fixed32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalFixed32() { + _hasBits0 &= ~64; + } + + /// Field number for the "optional_fixed64" field. + public const int OptionalFixed64FieldNumber = 8; + private readonly static ulong OptionalFixed64DefaultValue = 0UL; + + private ulong optionalFixed64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong OptionalFixed64 { + get { if ((_hasBits0 & 128) != 0) { return optionalFixed64_; } else { return OptionalFixed64DefaultValue; } } + set { + _hasBits0 |= 128; + optionalFixed64_ = value; + } + } + /// Gets whether the "optional_fixed64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalFixed64 { + get { return (_hasBits0 & 128) != 0; } + } + /// Clears the value of the "optional_fixed64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalFixed64() { + _hasBits0 &= ~128; + } + + /// Field number for the "optional_sfixed32" field. + public const int OptionalSfixed32FieldNumber = 9; + private readonly static int OptionalSfixed32DefaultValue = 0; + + private int optionalSfixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalSfixed32 { + get { if ((_hasBits0 & 256) != 0) { return optionalSfixed32_; } else { return OptionalSfixed32DefaultValue; } } + set { + _hasBits0 |= 256; + optionalSfixed32_ = value; + } + } + /// Gets whether the "optional_sfixed32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSfixed32 { + get { return (_hasBits0 & 256) != 0; } + } + /// Clears the value of the "optional_sfixed32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSfixed32() { + _hasBits0 &= ~256; + } + + /// Field number for the "optional_sfixed64" field. + public const int OptionalSfixed64FieldNumber = 10; + private readonly static long OptionalSfixed64DefaultValue = 0L; + + private long optionalSfixed64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalSfixed64 { + get { if ((_hasBits0 & 512) != 0) { return optionalSfixed64_; } else { return OptionalSfixed64DefaultValue; } } + set { + _hasBits0 |= 512; + optionalSfixed64_ = value; + } + } + /// Gets whether the "optional_sfixed64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSfixed64 { + get { return (_hasBits0 & 512) != 0; } + } + /// Clears the value of the "optional_sfixed64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSfixed64() { + _hasBits0 &= ~512; + } + + /// Field number for the "optional_float" field. + public const int OptionalFloatFieldNumber = 11; + private readonly static float OptionalFloatDefaultValue = 0F; + + private float optionalFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float OptionalFloat { + get { if ((_hasBits0 & 1024) != 0) { return optionalFloat_; } else { return OptionalFloatDefaultValue; } } + set { + _hasBits0 |= 1024; + optionalFloat_ = value; + } + } + /// Gets whether the "optional_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalFloat { + get { return (_hasBits0 & 1024) != 0; } + } + /// Clears the value of the "optional_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalFloat() { + _hasBits0 &= ~1024; + } + + /// Field number for the "optional_double" field. + public const int OptionalDoubleFieldNumber = 12; + private readonly static double OptionalDoubleDefaultValue = 0D; + + private double optionalDouble_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double OptionalDouble { + get { if ((_hasBits0 & 2048) != 0) { return optionalDouble_; } else { return OptionalDoubleDefaultValue; } } + set { + _hasBits0 |= 2048; + optionalDouble_ = value; + } + } + /// Gets whether the "optional_double" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalDouble { + get { return (_hasBits0 & 2048) != 0; } + } + /// Clears the value of the "optional_double" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalDouble() { + _hasBits0 &= ~2048; + } + + /// Field number for the "optional_bool" field. + public const int OptionalBoolFieldNumber = 13; + private readonly static bool OptionalBoolDefaultValue = false; + + private bool optionalBool_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool OptionalBool { + get { if ((_hasBits0 & 4096) != 0) { return optionalBool_; } else { return OptionalBoolDefaultValue; } } + set { + _hasBits0 |= 4096; + optionalBool_ = value; + } + } + /// Gets whether the "optional_bool" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalBool { + get { return (_hasBits0 & 4096) != 0; } + } + /// Clears the value of the "optional_bool" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalBool() { + _hasBits0 &= ~4096; + } + + /// Field number for the "optional_string" field. + public const int OptionalStringFieldNumber = 14; + private readonly static string OptionalStringDefaultValue = ""; + + private string optionalString_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalString { + get { return optionalString_ ?? OptionalStringDefaultValue; } + set { + optionalString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalString { + get { return optionalString_ != null; } + } + /// Clears the value of the "optional_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalString() { + optionalString_ = null; + } + + /// Field number for the "optional_bytes" field. + public const int OptionalBytesFieldNumber = 15; + private readonly static pb::ByteString OptionalBytesDefaultValue = pb::ByteString.Empty; + + private pb::ByteString optionalBytes_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString OptionalBytes { + get { return optionalBytes_ ?? OptionalBytesDefaultValue; } + set { + optionalBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_bytes" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalBytes { + get { return optionalBytes_ != null; } + } + /// Clears the value of the "optional_bytes" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalBytes() { + optionalBytes_ = null; + } + + /// Field number for the "optional_nested_message" field. + public const int OptionalNestedMessageFieldNumber = 18; + private global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage optionalNestedMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage OptionalNestedMessage { + get { return optionalNestedMessage_; } + set { + optionalNestedMessage_ = value; + } + } + + /// Field number for the "optional_foreign_message" field. + public const int OptionalForeignMessageFieldNumber = 19; + private global::ProtobufTestMessages.Proto2.ForeignMessageProto2 optionalForeignMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto2.ForeignMessageProto2 OptionalForeignMessage { + get { return optionalForeignMessage_; } + set { + optionalForeignMessage_ = value; + } + } + + /// Field number for the "optional_nested_enum" field. + public const int OptionalNestedEnumFieldNumber = 21; + private readonly static global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum OptionalNestedEnumDefaultValue = global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum.Foo; + + private global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum optionalNestedEnum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum OptionalNestedEnum { + get { if ((_hasBits0 & 8192) != 0) { return optionalNestedEnum_; } else { return OptionalNestedEnumDefaultValue; } } + set { + _hasBits0 |= 8192; + optionalNestedEnum_ = value; + } + } + /// Gets whether the "optional_nested_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalNestedEnum { + get { return (_hasBits0 & 8192) != 0; } + } + /// Clears the value of the "optional_nested_enum" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalNestedEnum() { + _hasBits0 &= ~8192; + } + + /// Field number for the "optional_foreign_enum" field. + public const int OptionalForeignEnumFieldNumber = 22; + private readonly static global::ProtobufTestMessages.Proto2.ForeignEnumProto2 OptionalForeignEnumDefaultValue = global::ProtobufTestMessages.Proto2.ForeignEnumProto2.ForeignFoo; + + private global::ProtobufTestMessages.Proto2.ForeignEnumProto2 optionalForeignEnum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto2.ForeignEnumProto2 OptionalForeignEnum { + get { if ((_hasBits0 & 16384) != 0) { return optionalForeignEnum_; } else { return OptionalForeignEnumDefaultValue; } } + set { + _hasBits0 |= 16384; + optionalForeignEnum_ = value; + } + } + /// Gets whether the "optional_foreign_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalForeignEnum { + get { return (_hasBits0 & 16384) != 0; } + } + /// Clears the value of the "optional_foreign_enum" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalForeignEnum() { + _hasBits0 &= ~16384; + } + + /// Field number for the "optional_string_piece" field. + public const int OptionalStringPieceFieldNumber = 24; + private readonly static string OptionalStringPieceDefaultValue = ""; + + private string optionalStringPiece_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalStringPiece { + get { return optionalStringPiece_ ?? OptionalStringPieceDefaultValue; } + set { + optionalStringPiece_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_string_piece" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalStringPiece { + get { return optionalStringPiece_ != null; } + } + /// Clears the value of the "optional_string_piece" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalStringPiece() { + optionalStringPiece_ = null; + } + + /// Field number for the "optional_cord" field. + public const int OptionalCordFieldNumber = 25; + private readonly static string OptionalCordDefaultValue = ""; + + private string optionalCord_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalCord { + get { return optionalCord_ ?? OptionalCordDefaultValue; } + set { + optionalCord_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_cord" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalCord { + get { return optionalCord_ != null; } + } + /// Clears the value of the "optional_cord" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalCord() { + optionalCord_ = null; + } + + /// Field number for the "recursive_message" field. + public const int RecursiveMessageFieldNumber = 27; + private global::ProtobufTestMessages.Proto2.TestAllTypesProto2 recursiveMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto2.TestAllTypesProto2 RecursiveMessage { + get { return recursiveMessage_; } + set { + recursiveMessage_ = value; + } + } + + /// Field number for the "repeated_int32" field. + public const int RepeatedInt32FieldNumber = 31; + private static readonly pb::FieldCodec _repeated_repeatedInt32_codec + = pb::FieldCodec.ForInt32(248); + private readonly pbc::RepeatedField repeatedInt32_ = new pbc::RepeatedField(); + /// + /// Repeated + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt32 { + get { return repeatedInt32_; } + } + + /// Field number for the "repeated_int64" field. + public const int RepeatedInt64FieldNumber = 32; + private static readonly pb::FieldCodec _repeated_repeatedInt64_codec + = pb::FieldCodec.ForInt64(256); + private readonly pbc::RepeatedField repeatedInt64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt64 { + get { return repeatedInt64_; } + } + + /// Field number for the "repeated_uint32" field. + public const int RepeatedUint32FieldNumber = 33; + private static readonly pb::FieldCodec _repeated_repeatedUint32_codec + = pb::FieldCodec.ForUInt32(264); + private readonly pbc::RepeatedField repeatedUint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedUint32 { + get { return repeatedUint32_; } + } + + /// Field number for the "repeated_uint64" field. + public const int RepeatedUint64FieldNumber = 34; + private static readonly pb::FieldCodec _repeated_repeatedUint64_codec + = pb::FieldCodec.ForUInt64(272); + private readonly pbc::RepeatedField repeatedUint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedUint64 { + get { return repeatedUint64_; } + } + + /// Field number for the "repeated_sint32" field. + public const int RepeatedSint32FieldNumber = 35; + private static readonly pb::FieldCodec _repeated_repeatedSint32_codec + = pb::FieldCodec.ForSInt32(280); + private readonly pbc::RepeatedField repeatedSint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSint32 { + get { return repeatedSint32_; } + } + + /// Field number for the "repeated_sint64" field. + public const int RepeatedSint64FieldNumber = 36; + private static readonly pb::FieldCodec _repeated_repeatedSint64_codec + = pb::FieldCodec.ForSInt64(288); + private readonly pbc::RepeatedField repeatedSint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSint64 { + get { return repeatedSint64_; } + } + + /// Field number for the "repeated_fixed32" field. + public const int RepeatedFixed32FieldNumber = 37; + private static readonly pb::FieldCodec _repeated_repeatedFixed32_codec + = pb::FieldCodec.ForFixed32(301); + private readonly pbc::RepeatedField repeatedFixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFixed32 { + get { return repeatedFixed32_; } + } + + /// Field number for the "repeated_fixed64" field. + public const int RepeatedFixed64FieldNumber = 38; + private static readonly pb::FieldCodec _repeated_repeatedFixed64_codec + = pb::FieldCodec.ForFixed64(305); + private readonly pbc::RepeatedField repeatedFixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFixed64 { + get { return repeatedFixed64_; } + } + + /// Field number for the "repeated_sfixed32" field. + public const int RepeatedSfixed32FieldNumber = 39; + private static readonly pb::FieldCodec _repeated_repeatedSfixed32_codec + = pb::FieldCodec.ForSFixed32(317); + private readonly pbc::RepeatedField repeatedSfixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSfixed32 { + get { return repeatedSfixed32_; } + } + + /// Field number for the "repeated_sfixed64" field. + public const int RepeatedSfixed64FieldNumber = 40; + private static readonly pb::FieldCodec _repeated_repeatedSfixed64_codec + = pb::FieldCodec.ForSFixed64(321); + private readonly pbc::RepeatedField repeatedSfixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSfixed64 { + get { return repeatedSfixed64_; } + } + + /// Field number for the "repeated_float" field. + public const int RepeatedFloatFieldNumber = 41; + private static readonly pb::FieldCodec _repeated_repeatedFloat_codec + = pb::FieldCodec.ForFloat(333); + private readonly pbc::RepeatedField repeatedFloat_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFloat { + get { return repeatedFloat_; } + } + + /// Field number for the "repeated_double" field. + public const int RepeatedDoubleFieldNumber = 42; + private static readonly pb::FieldCodec _repeated_repeatedDouble_codec + = pb::FieldCodec.ForDouble(337); + private readonly pbc::RepeatedField repeatedDouble_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedDouble { + get { return repeatedDouble_; } + } + + /// Field number for the "repeated_bool" field. + public const int RepeatedBoolFieldNumber = 43; + private static readonly pb::FieldCodec _repeated_repeatedBool_codec + = pb::FieldCodec.ForBool(344); + private readonly pbc::RepeatedField repeatedBool_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedBool { + get { return repeatedBool_; } + } + + /// Field number for the "repeated_string" field. + public const int RepeatedStringFieldNumber = 44; + private static readonly pb::FieldCodec _repeated_repeatedString_codec + = pb::FieldCodec.ForString(354); + private readonly pbc::RepeatedField repeatedString_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedString { + get { return repeatedString_; } + } + + /// Field number for the "repeated_bytes" field. + public const int RepeatedBytesFieldNumber = 45; + private static readonly pb::FieldCodec _repeated_repeatedBytes_codec + = pb::FieldCodec.ForBytes(362); + private readonly pbc::RepeatedField repeatedBytes_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedBytes { + get { return repeatedBytes_; } + } + + /// Field number for the "repeated_nested_message" field. + public const int RepeatedNestedMessageFieldNumber = 48; + private static readonly pb::FieldCodec _repeated_repeatedNestedMessage_codec + = pb::FieldCodec.ForMessage(386, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage.Parser); + private readonly pbc::RepeatedField repeatedNestedMessage_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedNestedMessage { + get { return repeatedNestedMessage_; } + } + + /// Field number for the "repeated_foreign_message" field. + public const int RepeatedForeignMessageFieldNumber = 49; + private static readonly pb::FieldCodec _repeated_repeatedForeignMessage_codec + = pb::FieldCodec.ForMessage(394, global::ProtobufTestMessages.Proto2.ForeignMessageProto2.Parser); + private readonly pbc::RepeatedField repeatedForeignMessage_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedForeignMessage { + get { return repeatedForeignMessage_; } + } + + /// Field number for the "repeated_nested_enum" field. + public const int RepeatedNestedEnumFieldNumber = 51; + private static readonly pb::FieldCodec _repeated_repeatedNestedEnum_codec + = pb::FieldCodec.ForEnum(408, x => (int) x, x => (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum) x); + private readonly pbc::RepeatedField repeatedNestedEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedNestedEnum { + get { return repeatedNestedEnum_; } + } + + /// Field number for the "repeated_foreign_enum" field. + public const int RepeatedForeignEnumFieldNumber = 52; + private static readonly pb::FieldCodec _repeated_repeatedForeignEnum_codec + = pb::FieldCodec.ForEnum(416, x => (int) x, x => (global::ProtobufTestMessages.Proto2.ForeignEnumProto2) x); + private readonly pbc::RepeatedField repeatedForeignEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedForeignEnum { + get { return repeatedForeignEnum_; } + } + + /// Field number for the "repeated_string_piece" field. + public const int RepeatedStringPieceFieldNumber = 54; + private static readonly pb::FieldCodec _repeated_repeatedStringPiece_codec + = pb::FieldCodec.ForString(434); + private readonly pbc::RepeatedField repeatedStringPiece_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedStringPiece { + get { return repeatedStringPiece_; } + } + + /// Field number for the "repeated_cord" field. + public const int RepeatedCordFieldNumber = 55; + private static readonly pb::FieldCodec _repeated_repeatedCord_codec + = pb::FieldCodec.ForString(442); + private readonly pbc::RepeatedField repeatedCord_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedCord { + get { return repeatedCord_; } + } + + /// Field number for the "packed_int32" field. + public const int PackedInt32FieldNumber = 75; + private static readonly pb::FieldCodec _repeated_packedInt32_codec + = pb::FieldCodec.ForInt32(602); + private readonly pbc::RepeatedField packedInt32_ = new pbc::RepeatedField(); + /// + /// Packed + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedInt32 { + get { return packedInt32_; } + } + + /// Field number for the "packed_int64" field. + public const int PackedInt64FieldNumber = 76; + private static readonly pb::FieldCodec _repeated_packedInt64_codec + = pb::FieldCodec.ForInt64(610); + private readonly pbc::RepeatedField packedInt64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedInt64 { + get { return packedInt64_; } + } + + /// Field number for the "packed_uint32" field. + public const int PackedUint32FieldNumber = 77; + private static readonly pb::FieldCodec _repeated_packedUint32_codec + = pb::FieldCodec.ForUInt32(618); + private readonly pbc::RepeatedField packedUint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedUint32 { + get { return packedUint32_; } + } + + /// Field number for the "packed_uint64" field. + public const int PackedUint64FieldNumber = 78; + private static readonly pb::FieldCodec _repeated_packedUint64_codec + = pb::FieldCodec.ForUInt64(626); + private readonly pbc::RepeatedField packedUint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedUint64 { + get { return packedUint64_; } + } + + /// Field number for the "packed_sint32" field. + public const int PackedSint32FieldNumber = 79; + private static readonly pb::FieldCodec _repeated_packedSint32_codec + = pb::FieldCodec.ForSInt32(634); + private readonly pbc::RepeatedField packedSint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSint32 { + get { return packedSint32_; } + } + + /// Field number for the "packed_sint64" field. + public const int PackedSint64FieldNumber = 80; + private static readonly pb::FieldCodec _repeated_packedSint64_codec + = pb::FieldCodec.ForSInt64(642); + private readonly pbc::RepeatedField packedSint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSint64 { + get { return packedSint64_; } + } + + /// Field number for the "packed_fixed32" field. + public const int PackedFixed32FieldNumber = 81; + private static readonly pb::FieldCodec _repeated_packedFixed32_codec + = pb::FieldCodec.ForFixed32(650); + private readonly pbc::RepeatedField packedFixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedFixed32 { + get { return packedFixed32_; } + } + + /// Field number for the "packed_fixed64" field. + public const int PackedFixed64FieldNumber = 82; + private static readonly pb::FieldCodec _repeated_packedFixed64_codec + = pb::FieldCodec.ForFixed64(658); + private readonly pbc::RepeatedField packedFixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedFixed64 { + get { return packedFixed64_; } + } + + /// Field number for the "packed_sfixed32" field. + public const int PackedSfixed32FieldNumber = 83; + private static readonly pb::FieldCodec _repeated_packedSfixed32_codec + = pb::FieldCodec.ForSFixed32(666); + private readonly pbc::RepeatedField packedSfixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSfixed32 { + get { return packedSfixed32_; } + } + + /// Field number for the "packed_sfixed64" field. + public const int PackedSfixed64FieldNumber = 84; + private static readonly pb::FieldCodec _repeated_packedSfixed64_codec + = pb::FieldCodec.ForSFixed64(674); + private readonly pbc::RepeatedField packedSfixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSfixed64 { + get { return packedSfixed64_; } + } + + /// Field number for the "packed_float" field. + public const int PackedFloatFieldNumber = 85; + private static readonly pb::FieldCodec _repeated_packedFloat_codec + = pb::FieldCodec.ForFloat(682); + private readonly pbc::RepeatedField packedFloat_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedFloat { + get { return packedFloat_; } + } + + /// Field number for the "packed_double" field. + public const int PackedDoubleFieldNumber = 86; + private static readonly pb::FieldCodec _repeated_packedDouble_codec + = pb::FieldCodec.ForDouble(690); + private readonly pbc::RepeatedField packedDouble_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedDouble { + get { return packedDouble_; } + } + + /// Field number for the "packed_bool" field. + public const int PackedBoolFieldNumber = 87; + private static readonly pb::FieldCodec _repeated_packedBool_codec + = pb::FieldCodec.ForBool(698); + private readonly pbc::RepeatedField packedBool_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedBool { + get { return packedBool_; } + } + + /// Field number for the "packed_nested_enum" field. + public const int PackedNestedEnumFieldNumber = 88; + private static readonly pb::FieldCodec _repeated_packedNestedEnum_codec + = pb::FieldCodec.ForEnum(706, x => (int) x, x => (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum) x); + private readonly pbc::RepeatedField packedNestedEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedNestedEnum { + get { return packedNestedEnum_; } + } + + /// Field number for the "unpacked_int32" field. + public const int UnpackedInt32FieldNumber = 89; + private static readonly pb::FieldCodec _repeated_unpackedInt32_codec + = pb::FieldCodec.ForInt32(712); + private readonly pbc::RepeatedField unpackedInt32_ = new pbc::RepeatedField(); + /// + /// Unpacked + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedInt32 { + get { return unpackedInt32_; } + } + + /// Field number for the "unpacked_int64" field. + public const int UnpackedInt64FieldNumber = 90; + private static readonly pb::FieldCodec _repeated_unpackedInt64_codec + = pb::FieldCodec.ForInt64(720); + private readonly pbc::RepeatedField unpackedInt64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedInt64 { + get { return unpackedInt64_; } + } + + /// Field number for the "unpacked_uint32" field. + public const int UnpackedUint32FieldNumber = 91; + private static readonly pb::FieldCodec _repeated_unpackedUint32_codec + = pb::FieldCodec.ForUInt32(728); + private readonly pbc::RepeatedField unpackedUint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedUint32 { + get { return unpackedUint32_; } + } + + /// Field number for the "unpacked_uint64" field. + public const int UnpackedUint64FieldNumber = 92; + private static readonly pb::FieldCodec _repeated_unpackedUint64_codec + = pb::FieldCodec.ForUInt64(736); + private readonly pbc::RepeatedField unpackedUint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedUint64 { + get { return unpackedUint64_; } + } + + /// Field number for the "unpacked_sint32" field. + public const int UnpackedSint32FieldNumber = 93; + private static readonly pb::FieldCodec _repeated_unpackedSint32_codec + = pb::FieldCodec.ForSInt32(744); + private readonly pbc::RepeatedField unpackedSint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSint32 { + get { return unpackedSint32_; } + } + + /// Field number for the "unpacked_sint64" field. + public const int UnpackedSint64FieldNumber = 94; + private static readonly pb::FieldCodec _repeated_unpackedSint64_codec + = pb::FieldCodec.ForSInt64(752); + private readonly pbc::RepeatedField unpackedSint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSint64 { + get { return unpackedSint64_; } + } + + /// Field number for the "unpacked_fixed32" field. + public const int UnpackedFixed32FieldNumber = 95; + private static readonly pb::FieldCodec _repeated_unpackedFixed32_codec + = pb::FieldCodec.ForFixed32(765); + private readonly pbc::RepeatedField unpackedFixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedFixed32 { + get { return unpackedFixed32_; } + } + + /// Field number for the "unpacked_fixed64" field. + public const int UnpackedFixed64FieldNumber = 96; + private static readonly pb::FieldCodec _repeated_unpackedFixed64_codec + = pb::FieldCodec.ForFixed64(769); + private readonly pbc::RepeatedField unpackedFixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedFixed64 { + get { return unpackedFixed64_; } + } + + /// Field number for the "unpacked_sfixed32" field. + public const int UnpackedSfixed32FieldNumber = 97; + private static readonly pb::FieldCodec _repeated_unpackedSfixed32_codec + = pb::FieldCodec.ForSFixed32(781); + private readonly pbc::RepeatedField unpackedSfixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSfixed32 { + get { return unpackedSfixed32_; } + } + + /// Field number for the "unpacked_sfixed64" field. + public const int UnpackedSfixed64FieldNumber = 98; + private static readonly pb::FieldCodec _repeated_unpackedSfixed64_codec + = pb::FieldCodec.ForSFixed64(785); + private readonly pbc::RepeatedField unpackedSfixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSfixed64 { + get { return unpackedSfixed64_; } + } + + /// Field number for the "unpacked_float" field. + public const int UnpackedFloatFieldNumber = 99; + private static readonly pb::FieldCodec _repeated_unpackedFloat_codec + = pb::FieldCodec.ForFloat(797); + private readonly pbc::RepeatedField unpackedFloat_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedFloat { + get { return unpackedFloat_; } + } + + /// Field number for the "unpacked_double" field. + public const int UnpackedDoubleFieldNumber = 100; + private static readonly pb::FieldCodec _repeated_unpackedDouble_codec + = pb::FieldCodec.ForDouble(801); + private readonly pbc::RepeatedField unpackedDouble_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedDouble { + get { return unpackedDouble_; } + } + + /// Field number for the "unpacked_bool" field. + public const int UnpackedBoolFieldNumber = 101; + private static readonly pb::FieldCodec _repeated_unpackedBool_codec + = pb::FieldCodec.ForBool(808); + private readonly pbc::RepeatedField unpackedBool_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedBool { + get { return unpackedBool_; } + } + + /// Field number for the "unpacked_nested_enum" field. + public const int UnpackedNestedEnumFieldNumber = 102; + private static readonly pb::FieldCodec _repeated_unpackedNestedEnum_codec + = pb::FieldCodec.ForEnum(816, x => (int) x, x => (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum) x); + private readonly pbc::RepeatedField unpackedNestedEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedNestedEnum { + get { return unpackedNestedEnum_; } + } + + /// Field number for the "map_int32_int32" field. + public const int MapInt32Int32FieldNumber = 56; + private static readonly pbc::MapField.Codec _map_mapInt32Int32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForInt32(16, 0), 450); + private readonly pbc::MapField mapInt32Int32_ = new pbc::MapField(); + /// + /// Map + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Int32 { + get { return mapInt32Int32_; } + } + + /// Field number for the "map_int64_int64" field. + public const int MapInt64Int64FieldNumber = 57; + private static readonly pbc::MapField.Codec _map_mapInt64Int64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt64(8, 0L), pb::FieldCodec.ForInt64(16, 0L), 458); + private readonly pbc::MapField mapInt64Int64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt64Int64 { + get { return mapInt64Int64_; } + } + + /// Field number for the "map_uint32_uint32" field. + public const int MapUint32Uint32FieldNumber = 58; + private static readonly pbc::MapField.Codec _map_mapUint32Uint32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForUInt32(8, 0), pb::FieldCodec.ForUInt32(16, 0), 466); + private readonly pbc::MapField mapUint32Uint32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapUint32Uint32 { + get { return mapUint32Uint32_; } + } + + /// Field number for the "map_uint64_uint64" field. + public const int MapUint64Uint64FieldNumber = 59; + private static readonly pbc::MapField.Codec _map_mapUint64Uint64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForUInt64(8, 0UL), pb::FieldCodec.ForUInt64(16, 0UL), 474); + private readonly pbc::MapField mapUint64Uint64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapUint64Uint64 { + get { return mapUint64Uint64_; } + } + + /// Field number for the "map_sint32_sint32" field. + public const int MapSint32Sint32FieldNumber = 60; + private static readonly pbc::MapField.Codec _map_mapSint32Sint32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSInt32(8, 0), pb::FieldCodec.ForSInt32(16, 0), 482); + private readonly pbc::MapField mapSint32Sint32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSint32Sint32 { + get { return mapSint32Sint32_; } + } + + /// Field number for the "map_sint64_sint64" field. + public const int MapSint64Sint64FieldNumber = 61; + private static readonly pbc::MapField.Codec _map_mapSint64Sint64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSInt64(8, 0L), pb::FieldCodec.ForSInt64(16, 0L), 490); + private readonly pbc::MapField mapSint64Sint64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSint64Sint64 { + get { return mapSint64Sint64_; } + } + + /// Field number for the "map_fixed32_fixed32" field. + public const int MapFixed32Fixed32FieldNumber = 62; + private static readonly pbc::MapField.Codec _map_mapFixed32Fixed32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForFixed32(13, 0), pb::FieldCodec.ForFixed32(21, 0), 498); + private readonly pbc::MapField mapFixed32Fixed32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapFixed32Fixed32 { + get { return mapFixed32Fixed32_; } + } + + /// Field number for the "map_fixed64_fixed64" field. + public const int MapFixed64Fixed64FieldNumber = 63; + private static readonly pbc::MapField.Codec _map_mapFixed64Fixed64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForFixed64(9, 0UL), pb::FieldCodec.ForFixed64(17, 0UL), 506); + private readonly pbc::MapField mapFixed64Fixed64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapFixed64Fixed64 { + get { return mapFixed64Fixed64_; } + } + + /// Field number for the "map_sfixed32_sfixed32" field. + public const int MapSfixed32Sfixed32FieldNumber = 64; + private static readonly pbc::MapField.Codec _map_mapSfixed32Sfixed32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSFixed32(13, 0), pb::FieldCodec.ForSFixed32(21, 0), 514); + private readonly pbc::MapField mapSfixed32Sfixed32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSfixed32Sfixed32 { + get { return mapSfixed32Sfixed32_; } + } + + /// Field number for the "map_sfixed64_sfixed64" field. + public const int MapSfixed64Sfixed64FieldNumber = 65; + private static readonly pbc::MapField.Codec _map_mapSfixed64Sfixed64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSFixed64(9, 0L), pb::FieldCodec.ForSFixed64(17, 0L), 522); + private readonly pbc::MapField mapSfixed64Sfixed64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSfixed64Sfixed64 { + get { return mapSfixed64Sfixed64_; } + } + + /// Field number for the "map_int32_float" field. + public const int MapInt32FloatFieldNumber = 66; + private static readonly pbc::MapField.Codec _map_mapInt32Float_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForFloat(21, 0F), 530); + private readonly pbc::MapField mapInt32Float_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Float { + get { return mapInt32Float_; } + } + + /// Field number for the "map_int32_double" field. + public const int MapInt32DoubleFieldNumber = 67; + private static readonly pbc::MapField.Codec _map_mapInt32Double_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForDouble(17, 0D), 538); + private readonly pbc::MapField mapInt32Double_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Double { + get { return mapInt32Double_; } + } + + /// Field number for the "map_bool_bool" field. + public const int MapBoolBoolFieldNumber = 68; + private static readonly pbc::MapField.Codec _map_mapBoolBool_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForBool(8, false), pb::FieldCodec.ForBool(16, false), 546); + private readonly pbc::MapField mapBoolBool_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapBoolBool { + get { return mapBoolBool_; } + } + + /// Field number for the "map_string_string" field. + public const int MapStringStringFieldNumber = 69; + private static readonly pbc::MapField.Codec _map_mapStringString_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForString(18, ""), 554); + private readonly pbc::MapField mapStringString_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapStringString { + get { return mapStringString_; } + } + + /// Field number for the "map_string_bytes" field. + public const int MapStringBytesFieldNumber = 70; + private static readonly pbc::MapField.Codec _map_mapStringBytes_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForBytes(18, pb::ByteString.Empty), 562); + private readonly pbc::MapField mapStringBytes_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapStringBytes { + get { return mapStringBytes_; } + } + + /// Field number for the "map_string_nested_message" field. + public const int MapStringNestedMessageFieldNumber = 71; + private static readonly pbc::MapField.Codec _map_mapStringNestedMessage_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForMessage(18, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage.Parser), 570); + private readonly pbc::MapField mapStringNestedMessage_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapStringNestedMessage { + get { return mapStringNestedMessage_; } + } + + /// Field number for the "map_string_foreign_message" field. + public const int MapStringForeignMessageFieldNumber = 72; + private static readonly pbc::MapField.Codec _map_mapStringForeignMessage_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForMessage(18, global::ProtobufTestMessages.Proto2.ForeignMessageProto2.Parser), 578); + private readonly pbc::MapField mapStringForeignMessage_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapStringForeignMessage { + get { return mapStringForeignMessage_; } + } + + /// Field number for the "map_string_nested_enum" field. + public const int MapStringNestedEnumFieldNumber = 73; + private static readonly pbc::MapField.Codec _map_mapStringNestedEnum_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum) x, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum.Foo), 586); + private readonly pbc::MapField mapStringNestedEnum_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapStringNestedEnum { + get { return mapStringNestedEnum_; } + } + + /// Field number for the "map_string_foreign_enum" field. + public const int MapStringForeignEnumFieldNumber = 74; + private static readonly pbc::MapField.Codec _map_mapStringForeignEnum_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::ProtobufTestMessages.Proto2.ForeignEnumProto2) x, global::ProtobufTestMessages.Proto2.ForeignEnumProto2.ForeignFoo), 594); + private readonly pbc::MapField mapStringForeignEnum_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapStringForeignEnum { + get { return mapStringForeignEnum_; } + } + + /// Field number for the "oneof_uint32" field. + public const int OneofUint32FieldNumber = 111; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OneofUint32 { + get { return HasOneofUint32 ? (uint) oneofField_ : 0; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; + } + } + /// Gets whether the "oneof_uint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofUint32 { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32; } + } + /// Clears the value of the oneof if it's currently set to "oneof_uint32" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofUint32() { + if (HasOneofUint32) { + ClearOneofField(); + } + } + + /// Field number for the "oneof_nested_message" field. + public const int OneofNestedMessageFieldNumber = 112; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage OneofNestedMessage { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage) oneofField_ : null; } + set { + oneofField_ = value; + oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage; + } + } + + /// Field number for the "oneof_string" field. + public const int OneofStringFieldNumber = 113; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OneofString { + get { return HasOneofString ? (string) oneofField_ : ""; } + set { + oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + oneofFieldCase_ = OneofFieldOneofCase.OneofString; + } + } + /// Gets whether the "oneof_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofString { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString; } + } + /// Clears the value of the oneof if it's currently set to "oneof_string" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofString() { + if (HasOneofString) { + ClearOneofField(); + } + } + + /// Field number for the "oneof_bytes" field. + public const int OneofBytesFieldNumber = 114; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString OneofBytes { + get { return HasOneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; } + set { + oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; + } + } + /// Gets whether the "oneof_bytes" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofBytes { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes; } + } + /// Clears the value of the oneof if it's currently set to "oneof_bytes" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofBytes() { + if (HasOneofBytes) { + ClearOneofField(); + } + } + + /// Field number for the "oneof_bool" field. + public const int OneofBoolFieldNumber = 115; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool OneofBool { + get { return HasOneofBool ? (bool) oneofField_ : false; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofBool; + } + } + /// Gets whether the "oneof_bool" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofBool { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBool; } + } + /// Clears the value of the oneof if it's currently set to "oneof_bool" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofBool() { + if (HasOneofBool) { + ClearOneofField(); + } + } + + /// Field number for the "oneof_uint64" field. + public const int OneofUint64FieldNumber = 116; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong OneofUint64 { + get { return HasOneofUint64 ? (ulong) oneofField_ : 0UL; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofUint64; + } + } + /// Gets whether the "oneof_uint64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofUint64 { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint64; } + } + /// Clears the value of the oneof if it's currently set to "oneof_uint64" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofUint64() { + if (HasOneofUint64) { + ClearOneofField(); + } + } + + /// Field number for the "oneof_float" field. + public const int OneofFloatFieldNumber = 117; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float OneofFloat { + get { return HasOneofFloat ? (float) oneofField_ : 0F; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofFloat; + } + } + /// Gets whether the "oneof_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofFloat { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofFloat; } + } + /// Clears the value of the oneof if it's currently set to "oneof_float" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofFloat() { + if (HasOneofFloat) { + ClearOneofField(); + } + } + + /// Field number for the "oneof_double" field. + public const int OneofDoubleFieldNumber = 118; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double OneofDouble { + get { return HasOneofDouble ? (double) oneofField_ : 0D; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofDouble; + } + } + /// Gets whether the "oneof_double" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofDouble { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofDouble; } + } + /// Clears the value of the oneof if it's currently set to "oneof_double" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofDouble() { + if (HasOneofDouble) { + ClearOneofField(); + } + } + + /// Field number for the "oneof_enum" field. + public const int OneofEnumFieldNumber = 119; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum OneofEnum { + get { return HasOneofEnum ? (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum) oneofField_ : global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum.Foo; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofEnum; + } + } + /// Gets whether the "oneof_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofEnum { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofEnum; } + } + /// Clears the value of the oneof if it's currently set to "oneof_enum" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofEnum() { + if (HasOneofEnum) { + ClearOneofField(); + } + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 201; + private global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.Data data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.Data Data { + get { return data_; } + set { + data_ = value; + } + } + /// Gets whether the data field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasData { + get { return data_ != null; } + } + /// Clears the value of the data field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearData() { + data_ = null; + } + + /// Field number for the "fieldname1" field. + public const int Fieldname1FieldNumber = 401; + private readonly static int Fieldname1DefaultValue = 0; + + private int fieldname1_; + /// + /// Test field-name-to-JSON-name convention. + /// (protobuf says names can be any valid C/C++ identifier.) + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Fieldname1 { + get { if ((_hasBits0 & 32768) != 0) { return fieldname1_; } else { return Fieldname1DefaultValue; } } + set { + _hasBits0 |= 32768; + fieldname1_ = value; + } + } + /// Gets whether the "fieldname1" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldname1 { + get { return (_hasBits0 & 32768) != 0; } + } + /// Clears the value of the "fieldname1" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldname1() { + _hasBits0 &= ~32768; + } + + /// Field number for the "field_name2" field. + public const int FieldName2FieldNumber = 402; + private readonly static int FieldName2DefaultValue = 0; + + private int fieldName2_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName2 { + get { if ((_hasBits0 & 65536) != 0) { return fieldName2_; } else { return FieldName2DefaultValue; } } + set { + _hasBits0 |= 65536; + fieldName2_ = value; + } + } + /// Gets whether the "field_name2" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName2 { + get { return (_hasBits0 & 65536) != 0; } + } + /// Clears the value of the "field_name2" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName2() { + _hasBits0 &= ~65536; + } + + /// Field number for the "_field_name3" field. + public const int FieldName3FieldNumber = 403; + private readonly static int FieldName3DefaultValue = 0; + + private int FieldName3_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName3 { + get { if ((_hasBits0 & 131072) != 0) { return FieldName3_; } else { return FieldName3DefaultValue; } } + set { + _hasBits0 |= 131072; + FieldName3_ = value; + } + } + /// Gets whether the "_field_name3" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName3 { + get { return (_hasBits0 & 131072) != 0; } + } + /// Clears the value of the "_field_name3" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName3() { + _hasBits0 &= ~131072; + } + + /// Field number for the "field__name4_" field. + public const int FieldName4FieldNumber = 404; + private readonly static int FieldName4DefaultValue = 0; + + private int fieldName4_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName4 { + get { if ((_hasBits0 & 262144) != 0) { return fieldName4_; } else { return FieldName4DefaultValue; } } + set { + _hasBits0 |= 262144; + fieldName4_ = value; + } + } + /// Gets whether the "field__name4_" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName4 { + get { return (_hasBits0 & 262144) != 0; } + } + /// Clears the value of the "field__name4_" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName4() { + _hasBits0 &= ~262144; + } + + /// Field number for the "field0name5" field. + public const int Field0Name5FieldNumber = 405; + private readonly static int Field0Name5DefaultValue = 0; + + private int field0Name5_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field0Name5 { + get { if ((_hasBits0 & 524288) != 0) { return field0Name5_; } else { return Field0Name5DefaultValue; } } + set { + _hasBits0 |= 524288; + field0Name5_ = value; + } + } + /// Gets whether the "field0name5" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasField0Name5 { + get { return (_hasBits0 & 524288) != 0; } + } + /// Clears the value of the "field0name5" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearField0Name5() { + _hasBits0 &= ~524288; + } + + /// Field number for the "field_0_name6" field. + public const int Field0Name6FieldNumber = 406; + private readonly static int Field0Name6DefaultValue = 0; + + private int field0Name6_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field0Name6 { + get { if ((_hasBits0 & 1048576) != 0) { return field0Name6_; } else { return Field0Name6DefaultValue; } } + set { + _hasBits0 |= 1048576; + field0Name6_ = value; + } + } + /// Gets whether the "field_0_name6" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasField0Name6 { + get { return (_hasBits0 & 1048576) != 0; } + } + /// Clears the value of the "field_0_name6" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearField0Name6() { + _hasBits0 &= ~1048576; + } + + /// Field number for the "fieldName7" field. + public const int FieldName7FieldNumber = 407; + private readonly static int FieldName7DefaultValue = 0; + + private int fieldName7_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName7 { + get { if ((_hasBits0 & 2097152) != 0) { return fieldName7_; } else { return FieldName7DefaultValue; } } + set { + _hasBits0 |= 2097152; + fieldName7_ = value; + } + } + /// Gets whether the "fieldName7" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName7 { + get { return (_hasBits0 & 2097152) != 0; } + } + /// Clears the value of the "fieldName7" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName7() { + _hasBits0 &= ~2097152; + } + + /// Field number for the "FieldName8" field. + public const int FieldName8FieldNumber = 408; + private readonly static int FieldName8DefaultValue = 0; + + private int fieldName8_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName8 { + get { if ((_hasBits0 & 4194304) != 0) { return fieldName8_; } else { return FieldName8DefaultValue; } } + set { + _hasBits0 |= 4194304; + fieldName8_ = value; + } + } + /// Gets whether the "FieldName8" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName8 { + get { return (_hasBits0 & 4194304) != 0; } + } + /// Clears the value of the "FieldName8" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName8() { + _hasBits0 &= ~4194304; + } + + /// Field number for the "field_Name9" field. + public const int FieldName9FieldNumber = 409; + private readonly static int FieldName9DefaultValue = 0; + + private int fieldName9_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName9 { + get { if ((_hasBits0 & 8388608) != 0) { return fieldName9_; } else { return FieldName9DefaultValue; } } + set { + _hasBits0 |= 8388608; + fieldName9_ = value; + } + } + /// Gets whether the "field_Name9" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName9 { + get { return (_hasBits0 & 8388608) != 0; } + } + /// Clears the value of the "field_Name9" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName9() { + _hasBits0 &= ~8388608; + } + + /// Field number for the "Field_Name10" field. + public const int FieldName10FieldNumber = 410; + private readonly static int FieldName10DefaultValue = 0; + + private int fieldName10_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName10 { + get { if ((_hasBits0 & 16777216) != 0) { return fieldName10_; } else { return FieldName10DefaultValue; } } + set { + _hasBits0 |= 16777216; + fieldName10_ = value; + } + } + /// Gets whether the "Field_Name10" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName10 { + get { return (_hasBits0 & 16777216) != 0; } + } + /// Clears the value of the "Field_Name10" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName10() { + _hasBits0 &= ~16777216; + } + + /// Field number for the "FIELD_NAME11" field. + public const int FIELDNAME11FieldNumber = 411; + private readonly static int FIELDNAME11DefaultValue = 0; + + private int fIELDNAME11_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FIELDNAME11 { + get { if ((_hasBits0 & 33554432) != 0) { return fIELDNAME11_; } else { return FIELDNAME11DefaultValue; } } + set { + _hasBits0 |= 33554432; + fIELDNAME11_ = value; + } + } + /// Gets whether the "FIELD_NAME11" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFIELDNAME11 { + get { return (_hasBits0 & 33554432) != 0; } + } + /// Clears the value of the "FIELD_NAME11" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFIELDNAME11() { + _hasBits0 &= ~33554432; + } + + /// Field number for the "FIELD_name12" field. + public const int FIELDName12FieldNumber = 412; + private readonly static int FIELDName12DefaultValue = 0; + + private int fIELDName12_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FIELDName12 { + get { if ((_hasBits0 & 67108864) != 0) { return fIELDName12_; } else { return FIELDName12DefaultValue; } } + set { + _hasBits0 |= 67108864; + fIELDName12_ = value; + } + } + /// Gets whether the "FIELD_name12" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFIELDName12 { + get { return (_hasBits0 & 67108864) != 0; } + } + /// Clears the value of the "FIELD_name12" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFIELDName12() { + _hasBits0 &= ~67108864; + } + + /// Field number for the "__field_name13" field. + public const int FieldName13FieldNumber = 413; + private readonly static int FieldName13DefaultValue = 0; + + private int FieldName13_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName13 { + get { if ((_hasBits0 & 134217728) != 0) { return FieldName13_; } else { return FieldName13DefaultValue; } } + set { + _hasBits0 |= 134217728; + FieldName13_ = value; + } + } + /// Gets whether the "__field_name13" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName13 { + get { return (_hasBits0 & 134217728) != 0; } + } + /// Clears the value of the "__field_name13" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName13() { + _hasBits0 &= ~134217728; + } + + /// Field number for the "__Field_name14" field. + public const int FieldName14FieldNumber = 414; + private readonly static int FieldName14DefaultValue = 0; + + private int FieldName14_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName14 { + get { if ((_hasBits0 & 268435456) != 0) { return FieldName14_; } else { return FieldName14DefaultValue; } } + set { + _hasBits0 |= 268435456; + FieldName14_ = value; + } + } + /// Gets whether the "__Field_name14" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName14 { + get { return (_hasBits0 & 268435456) != 0; } + } + /// Clears the value of the "__Field_name14" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName14() { + _hasBits0 &= ~268435456; + } + + /// Field number for the "field__name15" field. + public const int FieldName15FieldNumber = 415; + private readonly static int FieldName15DefaultValue = 0; + + private int fieldName15_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName15 { + get { if ((_hasBits0 & 536870912) != 0) { return fieldName15_; } else { return FieldName15DefaultValue; } } + set { + _hasBits0 |= 536870912; + fieldName15_ = value; + } + } + /// Gets whether the "field__name15" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName15 { + get { return (_hasBits0 & 536870912) != 0; } + } + /// Clears the value of the "field__name15" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName15() { + _hasBits0 &= ~536870912; + } + + /// Field number for the "field__Name16" field. + public const int FieldName16FieldNumber = 416; + private readonly static int FieldName16DefaultValue = 0; + + private int fieldName16_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName16 { + get { if ((_hasBits0 & 1073741824) != 0) { return fieldName16_; } else { return FieldName16DefaultValue; } } + set { + _hasBits0 |= 1073741824; + fieldName16_ = value; + } + } + /// Gets whether the "field__Name16" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName16 { + get { return (_hasBits0 & 1073741824) != 0; } + } + /// Clears the value of the "field__Name16" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName16() { + _hasBits0 &= ~1073741824; + } + + /// Field number for the "field_name17__" field. + public const int FieldName17FieldNumber = 417; + private readonly static int FieldName17DefaultValue = 0; + + private int fieldName17_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName17 { + get { if ((_hasBits0 & -2147483648) != 0) { return fieldName17_; } else { return FieldName17DefaultValue; } } + set { + _hasBits0 |= -2147483648; + fieldName17_ = value; + } + } + /// Gets whether the "field_name17__" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName17 { + get { return (_hasBits0 & -2147483648) != 0; } + } + /// Clears the value of the "field_name17__" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName17() { + _hasBits0 &= ~-2147483648; + } + + /// Field number for the "Field_name18__" field. + public const int FieldName18FieldNumber = 418; + private readonly static int FieldName18DefaultValue = 0; + + private int fieldName18_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName18 { + get { if ((_hasBits1 & 1) != 0) { return fieldName18_; } else { return FieldName18DefaultValue; } } + set { + _hasBits1 |= 1; + fieldName18_ = value; + } + } + /// Gets whether the "Field_name18__" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName18 { + get { return (_hasBits1 & 1) != 0; } + } + /// Clears the value of the "Field_name18__" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName18() { + _hasBits1 &= ~1; + } + + private object oneofField_; + /// Enum of possible cases for the "oneof_field" oneof. + public enum OneofFieldOneofCase { + None = 0, + OneofUint32 = 111, + OneofNestedMessage = 112, + OneofString = 113, + OneofBytes = 114, + OneofBool = 115, + OneofUint64 = 116, + OneofFloat = 117, + OneofDouble = 118, + OneofEnum = 119, + } + private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneofFieldOneofCase OneofFieldCase { + get { return oneofFieldCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofField() { + oneofFieldCase_ = OneofFieldOneofCase.None; + oneofField_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestAllTypesProto2); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestAllTypesProto2 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (OptionalInt32 != other.OptionalInt32) return false; + if (OptionalInt64 != other.OptionalInt64) return false; + if (OptionalUint32 != other.OptionalUint32) return false; + if (OptionalUint64 != other.OptionalUint64) return false; + if (OptionalSint32 != other.OptionalSint32) return false; + if (OptionalSint64 != other.OptionalSint64) return false; + if (OptionalFixed32 != other.OptionalFixed32) return false; + if (OptionalFixed64 != other.OptionalFixed64) return false; + if (OptionalSfixed32 != other.OptionalSfixed32) return false; + if (OptionalSfixed64 != other.OptionalSfixed64) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(OptionalFloat, other.OptionalFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OptionalDouble, other.OptionalDouble)) return false; + if (OptionalBool != other.OptionalBool) return false; + if (OptionalString != other.OptionalString) return false; + if (OptionalBytes != other.OptionalBytes) return false; + if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false; + if (!object.Equals(OptionalForeignMessage, other.OptionalForeignMessage)) return false; + if (OptionalNestedEnum != other.OptionalNestedEnum) return false; + if (OptionalForeignEnum != other.OptionalForeignEnum) return false; + if (OptionalStringPiece != other.OptionalStringPiece) return false; + if (OptionalCord != other.OptionalCord) return false; + if (!object.Equals(RecursiveMessage, other.RecursiveMessage)) return false; + if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false; + if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false; + if(!repeatedUint32_.Equals(other.repeatedUint32_)) return false; + if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false; + if(!repeatedSint32_.Equals(other.repeatedSint32_)) return false; + if(!repeatedSint64_.Equals(other.repeatedSint64_)) return false; + if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false; + if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false; + if(!repeatedSfixed32_.Equals(other.repeatedSfixed32_)) return false; + if(!repeatedSfixed64_.Equals(other.repeatedSfixed64_)) return false; + if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false; + if(!repeatedDouble_.Equals(other.repeatedDouble_)) return false; + if(!repeatedBool_.Equals(other.repeatedBool_)) return false; + if(!repeatedString_.Equals(other.repeatedString_)) return false; + if(!repeatedBytes_.Equals(other.repeatedBytes_)) return false; + if(!repeatedNestedMessage_.Equals(other.repeatedNestedMessage_)) return false; + if(!repeatedForeignMessage_.Equals(other.repeatedForeignMessage_)) return false; + if(!repeatedNestedEnum_.Equals(other.repeatedNestedEnum_)) return false; + if(!repeatedForeignEnum_.Equals(other.repeatedForeignEnum_)) return false; + if(!repeatedStringPiece_.Equals(other.repeatedStringPiece_)) return false; + if(!repeatedCord_.Equals(other.repeatedCord_)) return false; + if(!packedInt32_.Equals(other.packedInt32_)) return false; + if(!packedInt64_.Equals(other.packedInt64_)) return false; + if(!packedUint32_.Equals(other.packedUint32_)) return false; + if(!packedUint64_.Equals(other.packedUint64_)) return false; + if(!packedSint32_.Equals(other.packedSint32_)) return false; + if(!packedSint64_.Equals(other.packedSint64_)) return false; + if(!packedFixed32_.Equals(other.packedFixed32_)) return false; + if(!packedFixed64_.Equals(other.packedFixed64_)) return false; + if(!packedSfixed32_.Equals(other.packedSfixed32_)) return false; + if(!packedSfixed64_.Equals(other.packedSfixed64_)) return false; + if(!packedFloat_.Equals(other.packedFloat_)) return false; + if(!packedDouble_.Equals(other.packedDouble_)) return false; + if(!packedBool_.Equals(other.packedBool_)) return false; + if(!packedNestedEnum_.Equals(other.packedNestedEnum_)) return false; + if(!unpackedInt32_.Equals(other.unpackedInt32_)) return false; + if(!unpackedInt64_.Equals(other.unpackedInt64_)) return false; + if(!unpackedUint32_.Equals(other.unpackedUint32_)) return false; + if(!unpackedUint64_.Equals(other.unpackedUint64_)) return false; + if(!unpackedSint32_.Equals(other.unpackedSint32_)) return false; + if(!unpackedSint64_.Equals(other.unpackedSint64_)) return false; + if(!unpackedFixed32_.Equals(other.unpackedFixed32_)) return false; + if(!unpackedFixed64_.Equals(other.unpackedFixed64_)) return false; + if(!unpackedSfixed32_.Equals(other.unpackedSfixed32_)) return false; + if(!unpackedSfixed64_.Equals(other.unpackedSfixed64_)) return false; + if(!unpackedFloat_.Equals(other.unpackedFloat_)) return false; + if(!unpackedDouble_.Equals(other.unpackedDouble_)) return false; + if(!unpackedBool_.Equals(other.unpackedBool_)) return false; + if(!unpackedNestedEnum_.Equals(other.unpackedNestedEnum_)) return false; + if (!MapInt32Int32.Equals(other.MapInt32Int32)) return false; + if (!MapInt64Int64.Equals(other.MapInt64Int64)) return false; + if (!MapUint32Uint32.Equals(other.MapUint32Uint32)) return false; + if (!MapUint64Uint64.Equals(other.MapUint64Uint64)) return false; + if (!MapSint32Sint32.Equals(other.MapSint32Sint32)) return false; + if (!MapSint64Sint64.Equals(other.MapSint64Sint64)) return false; + if (!MapFixed32Fixed32.Equals(other.MapFixed32Fixed32)) return false; + if (!MapFixed64Fixed64.Equals(other.MapFixed64Fixed64)) return false; + if (!MapSfixed32Sfixed32.Equals(other.MapSfixed32Sfixed32)) return false; + if (!MapSfixed64Sfixed64.Equals(other.MapSfixed64Sfixed64)) return false; + if (!MapInt32Float.Equals(other.MapInt32Float)) return false; + if (!MapInt32Double.Equals(other.MapInt32Double)) return false; + if (!MapBoolBool.Equals(other.MapBoolBool)) return false; + if (!MapStringString.Equals(other.MapStringString)) return false; + if (!MapStringBytes.Equals(other.MapStringBytes)) return false; + if (!MapStringNestedMessage.Equals(other.MapStringNestedMessage)) return false; + if (!MapStringForeignMessage.Equals(other.MapStringForeignMessage)) return false; + if (!MapStringNestedEnum.Equals(other.MapStringNestedEnum)) return false; + if (!MapStringForeignEnum.Equals(other.MapStringForeignEnum)) return false; + if (OneofUint32 != other.OneofUint32) return false; + if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false; + if (OneofString != other.OneofString) return false; + if (OneofBytes != other.OneofBytes) return false; + if (OneofBool != other.OneofBool) return false; + if (OneofUint64 != other.OneofUint64) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(OneofFloat, other.OneofFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OneofDouble, other.OneofDouble)) return false; + if (OneofEnum != other.OneofEnum) return false; + if (!object.Equals(Data, other.Data)) return false; + if (Fieldname1 != other.Fieldname1) return false; + if (FieldName2 != other.FieldName2) return false; + if (FieldName3 != other.FieldName3) return false; + if (FieldName4 != other.FieldName4) return false; + if (Field0Name5 != other.Field0Name5) return false; + if (Field0Name6 != other.Field0Name6) return false; + if (FieldName7 != other.FieldName7) return false; + if (FieldName8 != other.FieldName8) return false; + if (FieldName9 != other.FieldName9) return false; + if (FieldName10 != other.FieldName10) return false; + if (FIELDNAME11 != other.FIELDNAME11) return false; + if (FIELDName12 != other.FIELDName12) return false; + if (FieldName13 != other.FieldName13) return false; + if (FieldName14 != other.FieldName14) return false; + if (FieldName15 != other.FieldName15) return false; + if (FieldName16 != other.FieldName16) return false; + if (FieldName17 != other.FieldName17) return false; + if (FieldName18 != other.FieldName18) return false; + if (OneofFieldCase != other.OneofFieldCase) return false; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasOptionalInt32) hash ^= OptionalInt32.GetHashCode(); + if (HasOptionalInt64) hash ^= OptionalInt64.GetHashCode(); + if (HasOptionalUint32) hash ^= OptionalUint32.GetHashCode(); + if (HasOptionalUint64) hash ^= OptionalUint64.GetHashCode(); + if (HasOptionalSint32) hash ^= OptionalSint32.GetHashCode(); + if (HasOptionalSint64) hash ^= OptionalSint64.GetHashCode(); + if (HasOptionalFixed32) hash ^= OptionalFixed32.GetHashCode(); + if (HasOptionalFixed64) hash ^= OptionalFixed64.GetHashCode(); + if (HasOptionalSfixed32) hash ^= OptionalSfixed32.GetHashCode(); + if (HasOptionalSfixed64) hash ^= OptionalSfixed64.GetHashCode(); + if (HasOptionalFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(OptionalFloat); + if (HasOptionalDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OptionalDouble); + if (HasOptionalBool) hash ^= OptionalBool.GetHashCode(); + if (HasOptionalString) hash ^= OptionalString.GetHashCode(); + if (HasOptionalBytes) hash ^= OptionalBytes.GetHashCode(); + if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode(); + if (optionalForeignMessage_ != null) hash ^= OptionalForeignMessage.GetHashCode(); + if (HasOptionalNestedEnum) hash ^= OptionalNestedEnum.GetHashCode(); + if (HasOptionalForeignEnum) hash ^= OptionalForeignEnum.GetHashCode(); + if (HasOptionalStringPiece) hash ^= OptionalStringPiece.GetHashCode(); + if (HasOptionalCord) hash ^= OptionalCord.GetHashCode(); + if (recursiveMessage_ != null) hash ^= RecursiveMessage.GetHashCode(); + hash ^= repeatedInt32_.GetHashCode(); + hash ^= repeatedInt64_.GetHashCode(); + hash ^= repeatedUint32_.GetHashCode(); + hash ^= repeatedUint64_.GetHashCode(); + hash ^= repeatedSint32_.GetHashCode(); + hash ^= repeatedSint64_.GetHashCode(); + hash ^= repeatedFixed32_.GetHashCode(); + hash ^= repeatedFixed64_.GetHashCode(); + hash ^= repeatedSfixed32_.GetHashCode(); + hash ^= repeatedSfixed64_.GetHashCode(); + hash ^= repeatedFloat_.GetHashCode(); + hash ^= repeatedDouble_.GetHashCode(); + hash ^= repeatedBool_.GetHashCode(); + hash ^= repeatedString_.GetHashCode(); + hash ^= repeatedBytes_.GetHashCode(); + hash ^= repeatedNestedMessage_.GetHashCode(); + hash ^= repeatedForeignMessage_.GetHashCode(); + hash ^= repeatedNestedEnum_.GetHashCode(); + hash ^= repeatedForeignEnum_.GetHashCode(); + hash ^= repeatedStringPiece_.GetHashCode(); + hash ^= repeatedCord_.GetHashCode(); + hash ^= packedInt32_.GetHashCode(); + hash ^= packedInt64_.GetHashCode(); + hash ^= packedUint32_.GetHashCode(); + hash ^= packedUint64_.GetHashCode(); + hash ^= packedSint32_.GetHashCode(); + hash ^= packedSint64_.GetHashCode(); + hash ^= packedFixed32_.GetHashCode(); + hash ^= packedFixed64_.GetHashCode(); + hash ^= packedSfixed32_.GetHashCode(); + hash ^= packedSfixed64_.GetHashCode(); + hash ^= packedFloat_.GetHashCode(); + hash ^= packedDouble_.GetHashCode(); + hash ^= packedBool_.GetHashCode(); + hash ^= packedNestedEnum_.GetHashCode(); + hash ^= unpackedInt32_.GetHashCode(); + hash ^= unpackedInt64_.GetHashCode(); + hash ^= unpackedUint32_.GetHashCode(); + hash ^= unpackedUint64_.GetHashCode(); + hash ^= unpackedSint32_.GetHashCode(); + hash ^= unpackedSint64_.GetHashCode(); + hash ^= unpackedFixed32_.GetHashCode(); + hash ^= unpackedFixed64_.GetHashCode(); + hash ^= unpackedSfixed32_.GetHashCode(); + hash ^= unpackedSfixed64_.GetHashCode(); + hash ^= unpackedFloat_.GetHashCode(); + hash ^= unpackedDouble_.GetHashCode(); + hash ^= unpackedBool_.GetHashCode(); + hash ^= unpackedNestedEnum_.GetHashCode(); + hash ^= MapInt32Int32.GetHashCode(); + hash ^= MapInt64Int64.GetHashCode(); + hash ^= MapUint32Uint32.GetHashCode(); + hash ^= MapUint64Uint64.GetHashCode(); + hash ^= MapSint32Sint32.GetHashCode(); + hash ^= MapSint64Sint64.GetHashCode(); + hash ^= MapFixed32Fixed32.GetHashCode(); + hash ^= MapFixed64Fixed64.GetHashCode(); + hash ^= MapSfixed32Sfixed32.GetHashCode(); + hash ^= MapSfixed64Sfixed64.GetHashCode(); + hash ^= MapInt32Float.GetHashCode(); + hash ^= MapInt32Double.GetHashCode(); + hash ^= MapBoolBool.GetHashCode(); + hash ^= MapStringString.GetHashCode(); + hash ^= MapStringBytes.GetHashCode(); + hash ^= MapStringNestedMessage.GetHashCode(); + hash ^= MapStringForeignMessage.GetHashCode(); + hash ^= MapStringNestedEnum.GetHashCode(); + hash ^= MapStringForeignEnum.GetHashCode(); + if (HasOneofUint32) hash ^= OneofUint32.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode(); + if (HasOneofString) hash ^= OneofString.GetHashCode(); + if (HasOneofBytes) hash ^= OneofBytes.GetHashCode(); + if (HasOneofBool) hash ^= OneofBool.GetHashCode(); + if (HasOneofUint64) hash ^= OneofUint64.GetHashCode(); + if (HasOneofFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(OneofFloat); + if (HasOneofDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OneofDouble); + if (HasOneofEnum) hash ^= OneofEnum.GetHashCode(); + if (HasData) hash ^= Data.GetHashCode(); + if (HasFieldname1) hash ^= Fieldname1.GetHashCode(); + if (HasFieldName2) hash ^= FieldName2.GetHashCode(); + if (HasFieldName3) hash ^= FieldName3.GetHashCode(); + if (HasFieldName4) hash ^= FieldName4.GetHashCode(); + if (HasField0Name5) hash ^= Field0Name5.GetHashCode(); + if (HasField0Name6) hash ^= Field0Name6.GetHashCode(); + if (HasFieldName7) hash ^= FieldName7.GetHashCode(); + if (HasFieldName8) hash ^= FieldName8.GetHashCode(); + if (HasFieldName9) hash ^= FieldName9.GetHashCode(); + if (HasFieldName10) hash ^= FieldName10.GetHashCode(); + if (HasFIELDNAME11) hash ^= FIELDNAME11.GetHashCode(); + if (HasFIELDName12) hash ^= FIELDName12.GetHashCode(); + if (HasFieldName13) hash ^= FieldName13.GetHashCode(); + if (HasFieldName14) hash ^= FieldName14.GetHashCode(); + if (HasFieldName15) hash ^= FieldName15.GetHashCode(); + if (HasFieldName16) hash ^= FieldName16.GetHashCode(); + if (HasFieldName17) hash ^= FieldName17.GetHashCode(); + if (HasFieldName18) hash ^= FieldName18.GetHashCode(); + hash ^= (int) oneofFieldCase_; + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasOptionalInt32) { + output.WriteRawTag(8); + output.WriteInt32(OptionalInt32); + } + if (HasOptionalInt64) { + output.WriteRawTag(16); + output.WriteInt64(OptionalInt64); + } + if (HasOptionalUint32) { + output.WriteRawTag(24); + output.WriteUInt32(OptionalUint32); + } + if (HasOptionalUint64) { + output.WriteRawTag(32); + output.WriteUInt64(OptionalUint64); + } + if (HasOptionalSint32) { + output.WriteRawTag(40); + output.WriteSInt32(OptionalSint32); + } + if (HasOptionalSint64) { + output.WriteRawTag(48); + output.WriteSInt64(OptionalSint64); + } + if (HasOptionalFixed32) { + output.WriteRawTag(61); + output.WriteFixed32(OptionalFixed32); + } + if (HasOptionalFixed64) { + output.WriteRawTag(65); + output.WriteFixed64(OptionalFixed64); + } + if (HasOptionalSfixed32) { + output.WriteRawTag(77); + output.WriteSFixed32(OptionalSfixed32); + } + if (HasOptionalSfixed64) { + output.WriteRawTag(81); + output.WriteSFixed64(OptionalSfixed64); + } + if (HasOptionalFloat) { + output.WriteRawTag(93); + output.WriteFloat(OptionalFloat); + } + if (HasOptionalDouble) { + output.WriteRawTag(97); + output.WriteDouble(OptionalDouble); + } + if (HasOptionalBool) { + output.WriteRawTag(104); + output.WriteBool(OptionalBool); + } + if (HasOptionalString) { + output.WriteRawTag(114); + output.WriteString(OptionalString); + } + if (HasOptionalBytes) { + output.WriteRawTag(122); + output.WriteBytes(OptionalBytes); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(OptionalNestedMessage); + } + if (optionalForeignMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(OptionalForeignMessage); + } + if (HasOptionalNestedEnum) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) OptionalNestedEnum); + } + if (HasOptionalForeignEnum) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) OptionalForeignEnum); + } + if (HasOptionalStringPiece) { + output.WriteRawTag(194, 1); + output.WriteString(OptionalStringPiece); + } + if (HasOptionalCord) { + output.WriteRawTag(202, 1); + output.WriteString(OptionalCord); + } + if (recursiveMessage_ != null) { + output.WriteRawTag(218, 1); + output.WriteMessage(RecursiveMessage); + } + repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec); + repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec); + repeatedUint32_.WriteTo(output, _repeated_repeatedUint32_codec); + repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec); + repeatedSint32_.WriteTo(output, _repeated_repeatedSint32_codec); + repeatedSint64_.WriteTo(output, _repeated_repeatedSint64_codec); + repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec); + repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec); + repeatedSfixed32_.WriteTo(output, _repeated_repeatedSfixed32_codec); + repeatedSfixed64_.WriteTo(output, _repeated_repeatedSfixed64_codec); + repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec); + repeatedDouble_.WriteTo(output, _repeated_repeatedDouble_codec); + repeatedBool_.WriteTo(output, _repeated_repeatedBool_codec); + repeatedString_.WriteTo(output, _repeated_repeatedString_codec); + repeatedBytes_.WriteTo(output, _repeated_repeatedBytes_codec); + repeatedNestedMessage_.WriteTo(output, _repeated_repeatedNestedMessage_codec); + repeatedForeignMessage_.WriteTo(output, _repeated_repeatedForeignMessage_codec); + repeatedNestedEnum_.WriteTo(output, _repeated_repeatedNestedEnum_codec); + repeatedForeignEnum_.WriteTo(output, _repeated_repeatedForeignEnum_codec); + repeatedStringPiece_.WriteTo(output, _repeated_repeatedStringPiece_codec); + repeatedCord_.WriteTo(output, _repeated_repeatedCord_codec); + mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec); + mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec); + mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec); + mapUint64Uint64_.WriteTo(output, _map_mapUint64Uint64_codec); + mapSint32Sint32_.WriteTo(output, _map_mapSint32Sint32_codec); + mapSint64Sint64_.WriteTo(output, _map_mapSint64Sint64_codec); + mapFixed32Fixed32_.WriteTo(output, _map_mapFixed32Fixed32_codec); + mapFixed64Fixed64_.WriteTo(output, _map_mapFixed64Fixed64_codec); + mapSfixed32Sfixed32_.WriteTo(output, _map_mapSfixed32Sfixed32_codec); + mapSfixed64Sfixed64_.WriteTo(output, _map_mapSfixed64Sfixed64_codec); + mapInt32Float_.WriteTo(output, _map_mapInt32Float_codec); + mapInt32Double_.WriteTo(output, _map_mapInt32Double_codec); + mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec); + mapStringString_.WriteTo(output, _map_mapStringString_codec); + mapStringBytes_.WriteTo(output, _map_mapStringBytes_codec); + mapStringNestedMessage_.WriteTo(output, _map_mapStringNestedMessage_codec); + mapStringForeignMessage_.WriteTo(output, _map_mapStringForeignMessage_codec); + mapStringNestedEnum_.WriteTo(output, _map_mapStringNestedEnum_codec); + mapStringForeignEnum_.WriteTo(output, _map_mapStringForeignEnum_codec); + packedInt32_.WriteTo(output, _repeated_packedInt32_codec); + packedInt64_.WriteTo(output, _repeated_packedInt64_codec); + packedUint32_.WriteTo(output, _repeated_packedUint32_codec); + packedUint64_.WriteTo(output, _repeated_packedUint64_codec); + packedSint32_.WriteTo(output, _repeated_packedSint32_codec); + packedSint64_.WriteTo(output, _repeated_packedSint64_codec); + packedFixed32_.WriteTo(output, _repeated_packedFixed32_codec); + packedFixed64_.WriteTo(output, _repeated_packedFixed64_codec); + packedSfixed32_.WriteTo(output, _repeated_packedSfixed32_codec); + packedSfixed64_.WriteTo(output, _repeated_packedSfixed64_codec); + packedFloat_.WriteTo(output, _repeated_packedFloat_codec); + packedDouble_.WriteTo(output, _repeated_packedDouble_codec); + packedBool_.WriteTo(output, _repeated_packedBool_codec); + packedNestedEnum_.WriteTo(output, _repeated_packedNestedEnum_codec); + unpackedInt32_.WriteTo(output, _repeated_unpackedInt32_codec); + unpackedInt64_.WriteTo(output, _repeated_unpackedInt64_codec); + unpackedUint32_.WriteTo(output, _repeated_unpackedUint32_codec); + unpackedUint64_.WriteTo(output, _repeated_unpackedUint64_codec); + unpackedSint32_.WriteTo(output, _repeated_unpackedSint32_codec); + unpackedSint64_.WriteTo(output, _repeated_unpackedSint64_codec); + unpackedFixed32_.WriteTo(output, _repeated_unpackedFixed32_codec); + unpackedFixed64_.WriteTo(output, _repeated_unpackedFixed64_codec); + unpackedSfixed32_.WriteTo(output, _repeated_unpackedSfixed32_codec); + unpackedSfixed64_.WriteTo(output, _repeated_unpackedSfixed64_codec); + unpackedFloat_.WriteTo(output, _repeated_unpackedFloat_codec); + unpackedDouble_.WriteTo(output, _repeated_unpackedDouble_codec); + unpackedBool_.WriteTo(output, _repeated_unpackedBool_codec); + unpackedNestedEnum_.WriteTo(output, _repeated_unpackedNestedEnum_codec); + if (HasOneofUint32) { + output.WriteRawTag(248, 6); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + output.WriteRawTag(130, 7); + output.WriteMessage(OneofNestedMessage); + } + if (HasOneofString) { + output.WriteRawTag(138, 7); + output.WriteString(OneofString); + } + if (HasOneofBytes) { + output.WriteRawTag(146, 7); + output.WriteBytes(OneofBytes); + } + if (HasOneofBool) { + output.WriteRawTag(152, 7); + output.WriteBool(OneofBool); + } + if (HasOneofUint64) { + output.WriteRawTag(160, 7); + output.WriteUInt64(OneofUint64); + } + if (HasOneofFloat) { + output.WriteRawTag(173, 7); + output.WriteFloat(OneofFloat); + } + if (HasOneofDouble) { + output.WriteRawTag(177, 7); + output.WriteDouble(OneofDouble); + } + if (HasOneofEnum) { + output.WriteRawTag(184, 7); + output.WriteEnum((int) OneofEnum); + } + if (HasData) { + output.WriteRawTag(203, 12); + output.WriteGroup(Data); + output.WriteRawTag(204, 12); + } + if (HasFieldname1) { + output.WriteRawTag(136, 25); + output.WriteInt32(Fieldname1); + } + if (HasFieldName2) { + output.WriteRawTag(144, 25); + output.WriteInt32(FieldName2); + } + if (HasFieldName3) { + output.WriteRawTag(152, 25); + output.WriteInt32(FieldName3); + } + if (HasFieldName4) { + output.WriteRawTag(160, 25); + output.WriteInt32(FieldName4); + } + if (HasField0Name5) { + output.WriteRawTag(168, 25); + output.WriteInt32(Field0Name5); + } + if (HasField0Name6) { + output.WriteRawTag(176, 25); + output.WriteInt32(Field0Name6); + } + if (HasFieldName7) { + output.WriteRawTag(184, 25); + output.WriteInt32(FieldName7); + } + if (HasFieldName8) { + output.WriteRawTag(192, 25); + output.WriteInt32(FieldName8); + } + if (HasFieldName9) { + output.WriteRawTag(200, 25); + output.WriteInt32(FieldName9); + } + if (HasFieldName10) { + output.WriteRawTag(208, 25); + output.WriteInt32(FieldName10); + } + if (HasFIELDNAME11) { + output.WriteRawTag(216, 25); + output.WriteInt32(FIELDNAME11); + } + if (HasFIELDName12) { + output.WriteRawTag(224, 25); + output.WriteInt32(FIELDName12); + } + if (HasFieldName13) { + output.WriteRawTag(232, 25); + output.WriteInt32(FieldName13); + } + if (HasFieldName14) { + output.WriteRawTag(240, 25); + output.WriteInt32(FieldName14); + } + if (HasFieldName15) { + output.WriteRawTag(248, 25); + output.WriteInt32(FieldName15); + } + if (HasFieldName16) { + output.WriteRawTag(128, 26); + output.WriteInt32(FieldName16); + } + if (HasFieldName17) { + output.WriteRawTag(136, 26); + output.WriteInt32(FieldName17); + } + if (HasFieldName18) { + output.WriteRawTag(144, 26); + output.WriteInt32(FieldName18); + } + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasOptionalInt32) { + output.WriteRawTag(8); + output.WriteInt32(OptionalInt32); + } + if (HasOptionalInt64) { + output.WriteRawTag(16); + output.WriteInt64(OptionalInt64); + } + if (HasOptionalUint32) { + output.WriteRawTag(24); + output.WriteUInt32(OptionalUint32); + } + if (HasOptionalUint64) { + output.WriteRawTag(32); + output.WriteUInt64(OptionalUint64); + } + if (HasOptionalSint32) { + output.WriteRawTag(40); + output.WriteSInt32(OptionalSint32); + } + if (HasOptionalSint64) { + output.WriteRawTag(48); + output.WriteSInt64(OptionalSint64); + } + if (HasOptionalFixed32) { + output.WriteRawTag(61); + output.WriteFixed32(OptionalFixed32); + } + if (HasOptionalFixed64) { + output.WriteRawTag(65); + output.WriteFixed64(OptionalFixed64); + } + if (HasOptionalSfixed32) { + output.WriteRawTag(77); + output.WriteSFixed32(OptionalSfixed32); + } + if (HasOptionalSfixed64) { + output.WriteRawTag(81); + output.WriteSFixed64(OptionalSfixed64); + } + if (HasOptionalFloat) { + output.WriteRawTag(93); + output.WriteFloat(OptionalFloat); + } + if (HasOptionalDouble) { + output.WriteRawTag(97); + output.WriteDouble(OptionalDouble); + } + if (HasOptionalBool) { + output.WriteRawTag(104); + output.WriteBool(OptionalBool); + } + if (HasOptionalString) { + output.WriteRawTag(114); + output.WriteString(OptionalString); + } + if (HasOptionalBytes) { + output.WriteRawTag(122); + output.WriteBytes(OptionalBytes); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(OptionalNestedMessage); + } + if (optionalForeignMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(OptionalForeignMessage); + } + if (HasOptionalNestedEnum) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) OptionalNestedEnum); + } + if (HasOptionalForeignEnum) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) OptionalForeignEnum); + } + if (HasOptionalStringPiece) { + output.WriteRawTag(194, 1); + output.WriteString(OptionalStringPiece); + } + if (HasOptionalCord) { + output.WriteRawTag(202, 1); + output.WriteString(OptionalCord); + } + if (recursiveMessage_ != null) { + output.WriteRawTag(218, 1); + output.WriteMessage(RecursiveMessage); + } + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec); + repeatedUint32_.WriteTo(ref output, _repeated_repeatedUint32_codec); + repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec); + repeatedSint32_.WriteTo(ref output, _repeated_repeatedSint32_codec); + repeatedSint64_.WriteTo(ref output, _repeated_repeatedSint64_codec); + repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec); + repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec); + repeatedSfixed32_.WriteTo(ref output, _repeated_repeatedSfixed32_codec); + repeatedSfixed64_.WriteTo(ref output, _repeated_repeatedSfixed64_codec); + repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec); + repeatedDouble_.WriteTo(ref output, _repeated_repeatedDouble_codec); + repeatedBool_.WriteTo(ref output, _repeated_repeatedBool_codec); + repeatedString_.WriteTo(ref output, _repeated_repeatedString_codec); + repeatedBytes_.WriteTo(ref output, _repeated_repeatedBytes_codec); + repeatedNestedMessage_.WriteTo(ref output, _repeated_repeatedNestedMessage_codec); + repeatedForeignMessage_.WriteTo(ref output, _repeated_repeatedForeignMessage_codec); + repeatedNestedEnum_.WriteTo(ref output, _repeated_repeatedNestedEnum_codec); + repeatedForeignEnum_.WriteTo(ref output, _repeated_repeatedForeignEnum_codec); + repeatedStringPiece_.WriteTo(ref output, _repeated_repeatedStringPiece_codec); + repeatedCord_.WriteTo(ref output, _repeated_repeatedCord_codec); + mapInt32Int32_.WriteTo(ref output, _map_mapInt32Int32_codec); + mapInt64Int64_.WriteTo(ref output, _map_mapInt64Int64_codec); + mapUint32Uint32_.WriteTo(ref output, _map_mapUint32Uint32_codec); + mapUint64Uint64_.WriteTo(ref output, _map_mapUint64Uint64_codec); + mapSint32Sint32_.WriteTo(ref output, _map_mapSint32Sint32_codec); + mapSint64Sint64_.WriteTo(ref output, _map_mapSint64Sint64_codec); + mapFixed32Fixed32_.WriteTo(ref output, _map_mapFixed32Fixed32_codec); + mapFixed64Fixed64_.WriteTo(ref output, _map_mapFixed64Fixed64_codec); + mapSfixed32Sfixed32_.WriteTo(ref output, _map_mapSfixed32Sfixed32_codec); + mapSfixed64Sfixed64_.WriteTo(ref output, _map_mapSfixed64Sfixed64_codec); + mapInt32Float_.WriteTo(ref output, _map_mapInt32Float_codec); + mapInt32Double_.WriteTo(ref output, _map_mapInt32Double_codec); + mapBoolBool_.WriteTo(ref output, _map_mapBoolBool_codec); + mapStringString_.WriteTo(ref output, _map_mapStringString_codec); + mapStringBytes_.WriteTo(ref output, _map_mapStringBytes_codec); + mapStringNestedMessage_.WriteTo(ref output, _map_mapStringNestedMessage_codec); + mapStringForeignMessage_.WriteTo(ref output, _map_mapStringForeignMessage_codec); + mapStringNestedEnum_.WriteTo(ref output, _map_mapStringNestedEnum_codec); + mapStringForeignEnum_.WriteTo(ref output, _map_mapStringForeignEnum_codec); + packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec); + packedInt64_.WriteTo(ref output, _repeated_packedInt64_codec); + packedUint32_.WriteTo(ref output, _repeated_packedUint32_codec); + packedUint64_.WriteTo(ref output, _repeated_packedUint64_codec); + packedSint32_.WriteTo(ref output, _repeated_packedSint32_codec); + packedSint64_.WriteTo(ref output, _repeated_packedSint64_codec); + packedFixed32_.WriteTo(ref output, _repeated_packedFixed32_codec); + packedFixed64_.WriteTo(ref output, _repeated_packedFixed64_codec); + packedSfixed32_.WriteTo(ref output, _repeated_packedSfixed32_codec); + packedSfixed64_.WriteTo(ref output, _repeated_packedSfixed64_codec); + packedFloat_.WriteTo(ref output, _repeated_packedFloat_codec); + packedDouble_.WriteTo(ref output, _repeated_packedDouble_codec); + packedBool_.WriteTo(ref output, _repeated_packedBool_codec); + packedNestedEnum_.WriteTo(ref output, _repeated_packedNestedEnum_codec); + unpackedInt32_.WriteTo(ref output, _repeated_unpackedInt32_codec); + unpackedInt64_.WriteTo(ref output, _repeated_unpackedInt64_codec); + unpackedUint32_.WriteTo(ref output, _repeated_unpackedUint32_codec); + unpackedUint64_.WriteTo(ref output, _repeated_unpackedUint64_codec); + unpackedSint32_.WriteTo(ref output, _repeated_unpackedSint32_codec); + unpackedSint64_.WriteTo(ref output, _repeated_unpackedSint64_codec); + unpackedFixed32_.WriteTo(ref output, _repeated_unpackedFixed32_codec); + unpackedFixed64_.WriteTo(ref output, _repeated_unpackedFixed64_codec); + unpackedSfixed32_.WriteTo(ref output, _repeated_unpackedSfixed32_codec); + unpackedSfixed64_.WriteTo(ref output, _repeated_unpackedSfixed64_codec); + unpackedFloat_.WriteTo(ref output, _repeated_unpackedFloat_codec); + unpackedDouble_.WriteTo(ref output, _repeated_unpackedDouble_codec); + unpackedBool_.WriteTo(ref output, _repeated_unpackedBool_codec); + unpackedNestedEnum_.WriteTo(ref output, _repeated_unpackedNestedEnum_codec); + if (HasOneofUint32) { + output.WriteRawTag(248, 6); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + output.WriteRawTag(130, 7); + output.WriteMessage(OneofNestedMessage); + } + if (HasOneofString) { + output.WriteRawTag(138, 7); + output.WriteString(OneofString); + } + if (HasOneofBytes) { + output.WriteRawTag(146, 7); + output.WriteBytes(OneofBytes); + } + if (HasOneofBool) { + output.WriteRawTag(152, 7); + output.WriteBool(OneofBool); + } + if (HasOneofUint64) { + output.WriteRawTag(160, 7); + output.WriteUInt64(OneofUint64); + } + if (HasOneofFloat) { + output.WriteRawTag(173, 7); + output.WriteFloat(OneofFloat); + } + if (HasOneofDouble) { + output.WriteRawTag(177, 7); + output.WriteDouble(OneofDouble); + } + if (HasOneofEnum) { + output.WriteRawTag(184, 7); + output.WriteEnum((int) OneofEnum); + } + if (HasData) { + output.WriteRawTag(203, 12); + output.WriteGroup(Data); + output.WriteRawTag(204, 12); + } + if (HasFieldname1) { + output.WriteRawTag(136, 25); + output.WriteInt32(Fieldname1); + } + if (HasFieldName2) { + output.WriteRawTag(144, 25); + output.WriteInt32(FieldName2); + } + if (HasFieldName3) { + output.WriteRawTag(152, 25); + output.WriteInt32(FieldName3); + } + if (HasFieldName4) { + output.WriteRawTag(160, 25); + output.WriteInt32(FieldName4); + } + if (HasField0Name5) { + output.WriteRawTag(168, 25); + output.WriteInt32(Field0Name5); + } + if (HasField0Name6) { + output.WriteRawTag(176, 25); + output.WriteInt32(Field0Name6); + } + if (HasFieldName7) { + output.WriteRawTag(184, 25); + output.WriteInt32(FieldName7); + } + if (HasFieldName8) { + output.WriteRawTag(192, 25); + output.WriteInt32(FieldName8); + } + if (HasFieldName9) { + output.WriteRawTag(200, 25); + output.WriteInt32(FieldName9); + } + if (HasFieldName10) { + output.WriteRawTag(208, 25); + output.WriteInt32(FieldName10); + } + if (HasFIELDNAME11) { + output.WriteRawTag(216, 25); + output.WriteInt32(FIELDNAME11); + } + if (HasFIELDName12) { + output.WriteRawTag(224, 25); + output.WriteInt32(FIELDName12); + } + if (HasFieldName13) { + output.WriteRawTag(232, 25); + output.WriteInt32(FieldName13); + } + if (HasFieldName14) { + output.WriteRawTag(240, 25); + output.WriteInt32(FieldName14); + } + if (HasFieldName15) { + output.WriteRawTag(248, 25); + output.WriteInt32(FieldName15); + } + if (HasFieldName16) { + output.WriteRawTag(128, 26); + output.WriteInt32(FieldName16); + } + if (HasFieldName17) { + output.WriteRawTag(136, 26); + output.WriteInt32(FieldName17); + } + if (HasFieldName18) { + output.WriteRawTag(144, 26); + output.WriteInt32(FieldName18); + } + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasOptionalInt32) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32); + } + if (HasOptionalInt64) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(OptionalInt64); + } + if (HasOptionalUint32) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(OptionalUint32); + } + if (HasOptionalUint64) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(OptionalUint64); + } + if (HasOptionalSint32) { + size += 1 + pb::CodedOutputStream.ComputeSInt32Size(OptionalSint32); + } + if (HasOptionalSint64) { + size += 1 + pb::CodedOutputStream.ComputeSInt64Size(OptionalSint64); + } + if (HasOptionalFixed32) { + size += 1 + 4; + } + if (HasOptionalFixed64) { + size += 1 + 8; + } + if (HasOptionalSfixed32) { + size += 1 + 4; + } + if (HasOptionalSfixed64) { + size += 1 + 8; + } + if (HasOptionalFloat) { + size += 1 + 4; + } + if (HasOptionalDouble) { + size += 1 + 8; + } + if (HasOptionalBool) { + size += 1 + 1; + } + if (HasOptionalString) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(OptionalString); + } + if (HasOptionalBytes) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(OptionalBytes); + } + if (optionalNestedMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage); + } + if (optionalForeignMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalForeignMessage); + } + if (HasOptionalNestedEnum) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalNestedEnum); + } + if (HasOptionalForeignEnum) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalForeignEnum); + } + if (HasOptionalStringPiece) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalStringPiece); + } + if (HasOptionalCord) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalCord); + } + if (recursiveMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(RecursiveMessage); + } + size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec); + size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec); + size += repeatedUint32_.CalculateSize(_repeated_repeatedUint32_codec); + size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec); + size += repeatedSint32_.CalculateSize(_repeated_repeatedSint32_codec); + size += repeatedSint64_.CalculateSize(_repeated_repeatedSint64_codec); + size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec); + size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec); + size += repeatedSfixed32_.CalculateSize(_repeated_repeatedSfixed32_codec); + size += repeatedSfixed64_.CalculateSize(_repeated_repeatedSfixed64_codec); + size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec); + size += repeatedDouble_.CalculateSize(_repeated_repeatedDouble_codec); + size += repeatedBool_.CalculateSize(_repeated_repeatedBool_codec); + size += repeatedString_.CalculateSize(_repeated_repeatedString_codec); + size += repeatedBytes_.CalculateSize(_repeated_repeatedBytes_codec); + size += repeatedNestedMessage_.CalculateSize(_repeated_repeatedNestedMessage_codec); + size += repeatedForeignMessage_.CalculateSize(_repeated_repeatedForeignMessage_codec); + size += repeatedNestedEnum_.CalculateSize(_repeated_repeatedNestedEnum_codec); + size += repeatedForeignEnum_.CalculateSize(_repeated_repeatedForeignEnum_codec); + size += repeatedStringPiece_.CalculateSize(_repeated_repeatedStringPiece_codec); + size += repeatedCord_.CalculateSize(_repeated_repeatedCord_codec); + size += packedInt32_.CalculateSize(_repeated_packedInt32_codec); + size += packedInt64_.CalculateSize(_repeated_packedInt64_codec); + size += packedUint32_.CalculateSize(_repeated_packedUint32_codec); + size += packedUint64_.CalculateSize(_repeated_packedUint64_codec); + size += packedSint32_.CalculateSize(_repeated_packedSint32_codec); + size += packedSint64_.CalculateSize(_repeated_packedSint64_codec); + size += packedFixed32_.CalculateSize(_repeated_packedFixed32_codec); + size += packedFixed64_.CalculateSize(_repeated_packedFixed64_codec); + size += packedSfixed32_.CalculateSize(_repeated_packedSfixed32_codec); + size += packedSfixed64_.CalculateSize(_repeated_packedSfixed64_codec); + size += packedFloat_.CalculateSize(_repeated_packedFloat_codec); + size += packedDouble_.CalculateSize(_repeated_packedDouble_codec); + size += packedBool_.CalculateSize(_repeated_packedBool_codec); + size += packedNestedEnum_.CalculateSize(_repeated_packedNestedEnum_codec); + size += unpackedInt32_.CalculateSize(_repeated_unpackedInt32_codec); + size += unpackedInt64_.CalculateSize(_repeated_unpackedInt64_codec); + size += unpackedUint32_.CalculateSize(_repeated_unpackedUint32_codec); + size += unpackedUint64_.CalculateSize(_repeated_unpackedUint64_codec); + size += unpackedSint32_.CalculateSize(_repeated_unpackedSint32_codec); + size += unpackedSint64_.CalculateSize(_repeated_unpackedSint64_codec); + size += unpackedFixed32_.CalculateSize(_repeated_unpackedFixed32_codec); + size += unpackedFixed64_.CalculateSize(_repeated_unpackedFixed64_codec); + size += unpackedSfixed32_.CalculateSize(_repeated_unpackedSfixed32_codec); + size += unpackedSfixed64_.CalculateSize(_repeated_unpackedSfixed64_codec); + size += unpackedFloat_.CalculateSize(_repeated_unpackedFloat_codec); + size += unpackedDouble_.CalculateSize(_repeated_unpackedDouble_codec); + size += unpackedBool_.CalculateSize(_repeated_unpackedBool_codec); + size += unpackedNestedEnum_.CalculateSize(_repeated_unpackedNestedEnum_codec); + size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec); + size += mapInt64Int64_.CalculateSize(_map_mapInt64Int64_codec); + size += mapUint32Uint32_.CalculateSize(_map_mapUint32Uint32_codec); + size += mapUint64Uint64_.CalculateSize(_map_mapUint64Uint64_codec); + size += mapSint32Sint32_.CalculateSize(_map_mapSint32Sint32_codec); + size += mapSint64Sint64_.CalculateSize(_map_mapSint64Sint64_codec); + size += mapFixed32Fixed32_.CalculateSize(_map_mapFixed32Fixed32_codec); + size += mapFixed64Fixed64_.CalculateSize(_map_mapFixed64Fixed64_codec); + size += mapSfixed32Sfixed32_.CalculateSize(_map_mapSfixed32Sfixed32_codec); + size += mapSfixed64Sfixed64_.CalculateSize(_map_mapSfixed64Sfixed64_codec); + size += mapInt32Float_.CalculateSize(_map_mapInt32Float_codec); + size += mapInt32Double_.CalculateSize(_map_mapInt32Double_codec); + size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec); + size += mapStringString_.CalculateSize(_map_mapStringString_codec); + size += mapStringBytes_.CalculateSize(_map_mapStringBytes_codec); + size += mapStringNestedMessage_.CalculateSize(_map_mapStringNestedMessage_codec); + size += mapStringForeignMessage_.CalculateSize(_map_mapStringForeignMessage_codec); + size += mapStringNestedEnum_.CalculateSize(_map_mapStringNestedEnum_codec); + size += mapStringForeignEnum_.CalculateSize(_map_mapStringForeignEnum_codec); + if (HasOneofUint32) { + size += 2 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OneofNestedMessage); + } + if (HasOneofString) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OneofString); + } + if (HasOneofBytes) { + size += 2 + pb::CodedOutputStream.ComputeBytesSize(OneofBytes); + } + if (HasOneofBool) { + size += 2 + 1; + } + if (HasOneofUint64) { + size += 2 + pb::CodedOutputStream.ComputeUInt64Size(OneofUint64); + } + if (HasOneofFloat) { + size += 2 + 4; + } + if (HasOneofDouble) { + size += 2 + 8; + } + if (HasOneofEnum) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OneofEnum); + } + if (HasData) { + size += 4 + pb::CodedOutputStream.ComputeGroupSize(Data); + } + if (HasFieldname1) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Fieldname1); + } + if (HasFieldName2) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName2); + } + if (HasFieldName3) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName3); + } + if (HasFieldName4) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName4); + } + if (HasField0Name5) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field0Name5); + } + if (HasField0Name6) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field0Name6); + } + if (HasFieldName7) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName7); + } + if (HasFieldName8) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName8); + } + if (HasFieldName9) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName9); + } + if (HasFieldName10) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName10); + } + if (HasFIELDNAME11) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FIELDNAME11); + } + if (HasFIELDName12) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FIELDName12); + } + if (HasFieldName13) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName13); + } + if (HasFieldName14) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName14); + } + if (HasFieldName15) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName15); + } + if (HasFieldName16) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName16); + } + if (HasFieldName17) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName17); + } + if (HasFieldName18) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName18); + } + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestAllTypesProto2 other) { + if (other == null) { + return; + } + if (other.HasOptionalInt32) { + OptionalInt32 = other.OptionalInt32; + } + if (other.HasOptionalInt64) { + OptionalInt64 = other.OptionalInt64; + } + if (other.HasOptionalUint32) { + OptionalUint32 = other.OptionalUint32; + } + if (other.HasOptionalUint64) { + OptionalUint64 = other.OptionalUint64; + } + if (other.HasOptionalSint32) { + OptionalSint32 = other.OptionalSint32; + } + if (other.HasOptionalSint64) { + OptionalSint64 = other.OptionalSint64; + } + if (other.HasOptionalFixed32) { + OptionalFixed32 = other.OptionalFixed32; + } + if (other.HasOptionalFixed64) { + OptionalFixed64 = other.OptionalFixed64; + } + if (other.HasOptionalSfixed32) { + OptionalSfixed32 = other.OptionalSfixed32; + } + if (other.HasOptionalSfixed64) { + OptionalSfixed64 = other.OptionalSfixed64; + } + if (other.HasOptionalFloat) { + OptionalFloat = other.OptionalFloat; + } + if (other.HasOptionalDouble) { + OptionalDouble = other.OptionalDouble; + } + if (other.HasOptionalBool) { + OptionalBool = other.OptionalBool; + } + if (other.HasOptionalString) { + OptionalString = other.OptionalString; + } + if (other.HasOptionalBytes) { + OptionalBytes = other.OptionalBytes; + } + if (other.optionalNestedMessage_ != null) { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage(); + } + OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage); + } + if (other.optionalForeignMessage_ != null) { + if (optionalForeignMessage_ == null) { + OptionalForeignMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2(); + } + OptionalForeignMessage.MergeFrom(other.OptionalForeignMessage); + } + if (other.HasOptionalNestedEnum) { + OptionalNestedEnum = other.OptionalNestedEnum; + } + if (other.HasOptionalForeignEnum) { + OptionalForeignEnum = other.OptionalForeignEnum; + } + if (other.HasOptionalStringPiece) { + OptionalStringPiece = other.OptionalStringPiece; + } + if (other.HasOptionalCord) { + OptionalCord = other.OptionalCord; + } + if (other.recursiveMessage_ != null) { + if (recursiveMessage_ == null) { + RecursiveMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2(); + } + RecursiveMessage.MergeFrom(other.RecursiveMessage); + } + repeatedInt32_.Add(other.repeatedInt32_); + repeatedInt64_.Add(other.repeatedInt64_); + repeatedUint32_.Add(other.repeatedUint32_); + repeatedUint64_.Add(other.repeatedUint64_); + repeatedSint32_.Add(other.repeatedSint32_); + repeatedSint64_.Add(other.repeatedSint64_); + repeatedFixed32_.Add(other.repeatedFixed32_); + repeatedFixed64_.Add(other.repeatedFixed64_); + repeatedSfixed32_.Add(other.repeatedSfixed32_); + repeatedSfixed64_.Add(other.repeatedSfixed64_); + repeatedFloat_.Add(other.repeatedFloat_); + repeatedDouble_.Add(other.repeatedDouble_); + repeatedBool_.Add(other.repeatedBool_); + repeatedString_.Add(other.repeatedString_); + repeatedBytes_.Add(other.repeatedBytes_); + repeatedNestedMessage_.Add(other.repeatedNestedMessage_); + repeatedForeignMessage_.Add(other.repeatedForeignMessage_); + repeatedNestedEnum_.Add(other.repeatedNestedEnum_); + repeatedForeignEnum_.Add(other.repeatedForeignEnum_); + repeatedStringPiece_.Add(other.repeatedStringPiece_); + repeatedCord_.Add(other.repeatedCord_); + packedInt32_.Add(other.packedInt32_); + packedInt64_.Add(other.packedInt64_); + packedUint32_.Add(other.packedUint32_); + packedUint64_.Add(other.packedUint64_); + packedSint32_.Add(other.packedSint32_); + packedSint64_.Add(other.packedSint64_); + packedFixed32_.Add(other.packedFixed32_); + packedFixed64_.Add(other.packedFixed64_); + packedSfixed32_.Add(other.packedSfixed32_); + packedSfixed64_.Add(other.packedSfixed64_); + packedFloat_.Add(other.packedFloat_); + packedDouble_.Add(other.packedDouble_); + packedBool_.Add(other.packedBool_); + packedNestedEnum_.Add(other.packedNestedEnum_); + unpackedInt32_.Add(other.unpackedInt32_); + unpackedInt64_.Add(other.unpackedInt64_); + unpackedUint32_.Add(other.unpackedUint32_); + unpackedUint64_.Add(other.unpackedUint64_); + unpackedSint32_.Add(other.unpackedSint32_); + unpackedSint64_.Add(other.unpackedSint64_); + unpackedFixed32_.Add(other.unpackedFixed32_); + unpackedFixed64_.Add(other.unpackedFixed64_); + unpackedSfixed32_.Add(other.unpackedSfixed32_); + unpackedSfixed64_.Add(other.unpackedSfixed64_); + unpackedFloat_.Add(other.unpackedFloat_); + unpackedDouble_.Add(other.unpackedDouble_); + unpackedBool_.Add(other.unpackedBool_); + unpackedNestedEnum_.Add(other.unpackedNestedEnum_); + mapInt32Int32_.Add(other.mapInt32Int32_); + mapInt64Int64_.Add(other.mapInt64Int64_); + mapUint32Uint32_.Add(other.mapUint32Uint32_); + mapUint64Uint64_.Add(other.mapUint64Uint64_); + mapSint32Sint32_.Add(other.mapSint32Sint32_); + mapSint64Sint64_.Add(other.mapSint64Sint64_); + mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_); + mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_); + mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_); + mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_); + mapInt32Float_.Add(other.mapInt32Float_); + mapInt32Double_.Add(other.mapInt32Double_); + mapBoolBool_.Add(other.mapBoolBool_); + mapStringString_.Add(other.mapStringString_); + mapStringBytes_.Add(other.mapStringBytes_); + mapStringNestedMessage_.Add(other.mapStringNestedMessage_); + mapStringForeignMessage_.Add(other.mapStringForeignMessage_); + mapStringNestedEnum_.Add(other.mapStringNestedEnum_); + mapStringForeignEnum_.Add(other.mapStringForeignEnum_); + if (other.HasData) { + if (!HasData) { + Data = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.Data(); + } + Data.MergeFrom(other.Data); + } + if (other.HasFieldname1) { + Fieldname1 = other.Fieldname1; + } + if (other.HasFieldName2) { + FieldName2 = other.FieldName2; + } + if (other.HasFieldName3) { + FieldName3 = other.FieldName3; + } + if (other.HasFieldName4) { + FieldName4 = other.FieldName4; + } + if (other.HasField0Name5) { + Field0Name5 = other.Field0Name5; + } + if (other.HasField0Name6) { + Field0Name6 = other.Field0Name6; + } + if (other.HasFieldName7) { + FieldName7 = other.FieldName7; + } + if (other.HasFieldName8) { + FieldName8 = other.FieldName8; + } + if (other.HasFieldName9) { + FieldName9 = other.FieldName9; + } + if (other.HasFieldName10) { + FieldName10 = other.FieldName10; + } + if (other.HasFIELDNAME11) { + FIELDNAME11 = other.FIELDNAME11; + } + if (other.HasFIELDName12) { + FIELDName12 = other.FIELDName12; + } + if (other.HasFieldName13) { + FieldName13 = other.FieldName13; + } + if (other.HasFieldName14) { + FieldName14 = other.FieldName14; + } + if (other.HasFieldName15) { + FieldName15 = other.FieldName15; + } + if (other.HasFieldName16) { + FieldName16 = other.FieldName16; + } + if (other.HasFieldName17) { + FieldName17 = other.FieldName17; + } + if (other.HasFieldName18) { + FieldName18 = other.FieldName18; + } + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: + OneofUint32 = other.OneofUint32; + break; + case OneofFieldOneofCase.OneofNestedMessage: + if (OneofNestedMessage == null) { + OneofNestedMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage(); + } + OneofNestedMessage.MergeFrom(other.OneofNestedMessage); + break; + case OneofFieldOneofCase.OneofString: + OneofString = other.OneofString; + break; + case OneofFieldOneofCase.OneofBytes: + OneofBytes = other.OneofBytes; + break; + case OneofFieldOneofCase.OneofBool: + OneofBool = other.OneofBool; + break; + case OneofFieldOneofCase.OneofUint64: + OneofUint64 = other.OneofUint64; + break; + case OneofFieldOneofCase.OneofFloat: + OneofFloat = other.OneofFloat; + break; + case OneofFieldOneofCase.OneofDouble: + OneofDouble = other.OneofDouble; + break; + case OneofFieldOneofCase.OneofEnum: + OneofEnum = other.OneofEnum; + break; + } + + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + case 8: { + OptionalInt32 = input.ReadInt32(); + break; + } + case 16: { + OptionalInt64 = input.ReadInt64(); + break; + } + case 24: { + OptionalUint32 = input.ReadUInt32(); + break; + } + case 32: { + OptionalUint64 = input.ReadUInt64(); + break; + } + case 40: { + OptionalSint32 = input.ReadSInt32(); + break; + } + case 48: { + OptionalSint64 = input.ReadSInt64(); + break; + } + case 61: { + OptionalFixed32 = input.ReadFixed32(); + break; + } + case 65: { + OptionalFixed64 = input.ReadFixed64(); + break; + } + case 77: { + OptionalSfixed32 = input.ReadSFixed32(); + break; + } + case 81: { + OptionalSfixed64 = input.ReadSFixed64(); + break; + } + case 93: { + OptionalFloat = input.ReadFloat(); + break; + } + case 97: { + OptionalDouble = input.ReadDouble(); + break; + } + case 104: { + OptionalBool = input.ReadBool(); + break; + } + case 114: { + OptionalString = input.ReadString(); + break; + } + case 122: { + OptionalBytes = input.ReadBytes(); + break; + } + case 146: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + case 154: { + if (optionalForeignMessage_ == null) { + OptionalForeignMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2(); + } + input.ReadMessage(OptionalForeignMessage); + break; + } + case 168: { + OptionalNestedEnum = (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum) input.ReadEnum(); + break; + } + case 176: { + OptionalForeignEnum = (global::ProtobufTestMessages.Proto2.ForeignEnumProto2) input.ReadEnum(); + break; + } + case 194: { + OptionalStringPiece = input.ReadString(); + break; + } + case 202: { + OptionalCord = input.ReadString(); + break; + } + case 218: { + if (recursiveMessage_ == null) { + RecursiveMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2(); + } + input.ReadMessage(RecursiveMessage); + break; + } + case 250: + case 248: { + repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); + break; + } + case 258: + case 256: { + repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec); + break; + } + case 266: + case 264: { + repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec); + break; + } + case 274: + case 272: { + repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec); + break; + } + case 282: + case 280: { + repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec); + break; + } + case 290: + case 288: { + repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec); + break; + } + case 298: + case 301: { + repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec); + break; + } + case 306: + case 305: { + repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec); + break; + } + case 314: + case 317: { + repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec); + break; + } + case 322: + case 321: { + repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec); + break; + } + case 330: + case 333: { + repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec); + break; + } + case 338: + case 337: { + repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec); + break; + } + case 346: + case 344: { + repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec); + break; + } + case 354: { + repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec); + break; + } + case 362: { + repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec); + break; + } + case 386: { + repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec); + break; + } + case 394: { + repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec); + break; + } + case 410: + case 408: { + repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec); + break; + } + case 418: + case 416: { + repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec); + break; + } + case 434: { + repeatedStringPiece_.AddEntriesFrom(input, _repeated_repeatedStringPiece_codec); + break; + } + case 442: { + repeatedCord_.AddEntriesFrom(input, _repeated_repeatedCord_codec); + break; + } + case 450: { + mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec); + break; + } + case 458: { + mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec); + break; + } + case 466: { + mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec); + break; + } + case 474: { + mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec); + break; + } + case 482: { + mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec); + break; + } + case 490: { + mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec); + break; + } + case 498: { + mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec); + break; + } + case 506: { + mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec); + break; + } + case 514: { + mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec); + break; + } + case 522: { + mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec); + break; + } + case 530: { + mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec); + break; + } + case 538: { + mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec); + break; + } + case 546: { + mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec); + break; + } + case 554: { + mapStringString_.AddEntriesFrom(input, _map_mapStringString_codec); + break; + } + case 562: { + mapStringBytes_.AddEntriesFrom(input, _map_mapStringBytes_codec); + break; + } + case 570: { + mapStringNestedMessage_.AddEntriesFrom(input, _map_mapStringNestedMessage_codec); + break; + } + case 578: { + mapStringForeignMessage_.AddEntriesFrom(input, _map_mapStringForeignMessage_codec); + break; + } + case 586: { + mapStringNestedEnum_.AddEntriesFrom(input, _map_mapStringNestedEnum_codec); + break; + } + case 594: { + mapStringForeignEnum_.AddEntriesFrom(input, _map_mapStringForeignEnum_codec); + break; + } + case 602: + case 600: { + packedInt32_.AddEntriesFrom(input, _repeated_packedInt32_codec); + break; + } + case 610: + case 608: { + packedInt64_.AddEntriesFrom(input, _repeated_packedInt64_codec); + break; + } + case 618: + case 616: { + packedUint32_.AddEntriesFrom(input, _repeated_packedUint32_codec); + break; + } + case 626: + case 624: { + packedUint64_.AddEntriesFrom(input, _repeated_packedUint64_codec); + break; + } + case 634: + case 632: { + packedSint32_.AddEntriesFrom(input, _repeated_packedSint32_codec); + break; + } + case 642: + case 640: { + packedSint64_.AddEntriesFrom(input, _repeated_packedSint64_codec); + break; + } + case 650: + case 653: { + packedFixed32_.AddEntriesFrom(input, _repeated_packedFixed32_codec); + break; + } + case 658: + case 657: { + packedFixed64_.AddEntriesFrom(input, _repeated_packedFixed64_codec); + break; + } + case 666: + case 669: { + packedSfixed32_.AddEntriesFrom(input, _repeated_packedSfixed32_codec); + break; + } + case 674: + case 673: { + packedSfixed64_.AddEntriesFrom(input, _repeated_packedSfixed64_codec); + break; + } + case 682: + case 685: { + packedFloat_.AddEntriesFrom(input, _repeated_packedFloat_codec); + break; + } + case 690: + case 689: { + packedDouble_.AddEntriesFrom(input, _repeated_packedDouble_codec); + break; + } + case 698: + case 696: { + packedBool_.AddEntriesFrom(input, _repeated_packedBool_codec); + break; + } + case 706: + case 704: { + packedNestedEnum_.AddEntriesFrom(input, _repeated_packedNestedEnum_codec); + break; + } + case 714: + case 712: { + unpackedInt32_.AddEntriesFrom(input, _repeated_unpackedInt32_codec); + break; + } + case 722: + case 720: { + unpackedInt64_.AddEntriesFrom(input, _repeated_unpackedInt64_codec); + break; + } + case 730: + case 728: { + unpackedUint32_.AddEntriesFrom(input, _repeated_unpackedUint32_codec); + break; + } + case 738: + case 736: { + unpackedUint64_.AddEntriesFrom(input, _repeated_unpackedUint64_codec); + break; + } + case 746: + case 744: { + unpackedSint32_.AddEntriesFrom(input, _repeated_unpackedSint32_codec); + break; + } + case 754: + case 752: { + unpackedSint64_.AddEntriesFrom(input, _repeated_unpackedSint64_codec); + break; + } + case 762: + case 765: { + unpackedFixed32_.AddEntriesFrom(input, _repeated_unpackedFixed32_codec); + break; + } + case 770: + case 769: { + unpackedFixed64_.AddEntriesFrom(input, _repeated_unpackedFixed64_codec); + break; + } + case 778: + case 781: { + unpackedSfixed32_.AddEntriesFrom(input, _repeated_unpackedSfixed32_codec); + break; + } + case 786: + case 785: { + unpackedSfixed64_.AddEntriesFrom(input, _repeated_unpackedSfixed64_codec); + break; + } + case 794: + case 797: { + unpackedFloat_.AddEntriesFrom(input, _repeated_unpackedFloat_codec); + break; + } + case 802: + case 801: { + unpackedDouble_.AddEntriesFrom(input, _repeated_unpackedDouble_codec); + break; + } + case 810: + case 808: { + unpackedBool_.AddEntriesFrom(input, _repeated_unpackedBool_codec); + break; + } + case 818: + case 816: { + unpackedNestedEnum_.AddEntriesFrom(input, _repeated_unpackedNestedEnum_codec); + break; + } + case 888: { + OneofUint32 = input.ReadUInt32(); + break; + } + case 898: { + global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage subBuilder = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + subBuilder.MergeFrom(OneofNestedMessage); + } + input.ReadMessage(subBuilder); + OneofNestedMessage = subBuilder; + break; + } + case 906: { + OneofString = input.ReadString(); + break; + } + case 914: { + OneofBytes = input.ReadBytes(); + break; + } + case 920: { + OneofBool = input.ReadBool(); + break; + } + case 928: { + OneofUint64 = input.ReadUInt64(); + break; + } + case 941: { + OneofFloat = input.ReadFloat(); + break; + } + case 945: { + OneofDouble = input.ReadDouble(); + break; + } + case 952: { + oneofField_ = input.ReadEnum(); + oneofFieldCase_ = OneofFieldOneofCase.OneofEnum; + break; + } + case 1611: { + if (!HasData) { + Data = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.Data(); + } + input.ReadGroup(Data); + break; + } + case 3208: { + Fieldname1 = input.ReadInt32(); + break; + } + case 3216: { + FieldName2 = input.ReadInt32(); + break; + } + case 3224: { + FieldName3 = input.ReadInt32(); + break; + } + case 3232: { + FieldName4 = input.ReadInt32(); + break; + } + case 3240: { + Field0Name5 = input.ReadInt32(); + break; + } + case 3248: { + Field0Name6 = input.ReadInt32(); + break; + } + case 3256: { + FieldName7 = input.ReadInt32(); + break; + } + case 3264: { + FieldName8 = input.ReadInt32(); + break; + } + case 3272: { + FieldName9 = input.ReadInt32(); + break; + } + case 3280: { + FieldName10 = input.ReadInt32(); + break; + } + case 3288: { + FIELDNAME11 = input.ReadInt32(); + break; + } + case 3296: { + FIELDName12 = input.ReadInt32(); + break; + } + case 3304: { + FieldName13 = input.ReadInt32(); + break; + } + case 3312: { + FieldName14 = input.ReadInt32(); + break; + } + case 3320: { + FieldName15 = input.ReadInt32(); + break; + } + case 3328: { + FieldName16 = input.ReadInt32(); + break; + } + case 3336: { + FieldName17 = input.ReadInt32(); + break; + } + case 3344: { + FieldName18 = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + case 8: { + OptionalInt32 = input.ReadInt32(); + break; + } + case 16: { + OptionalInt64 = input.ReadInt64(); + break; + } + case 24: { + OptionalUint32 = input.ReadUInt32(); + break; + } + case 32: { + OptionalUint64 = input.ReadUInt64(); + break; + } + case 40: { + OptionalSint32 = input.ReadSInt32(); + break; + } + case 48: { + OptionalSint64 = input.ReadSInt64(); + break; + } + case 61: { + OptionalFixed32 = input.ReadFixed32(); + break; + } + case 65: { + OptionalFixed64 = input.ReadFixed64(); + break; + } + case 77: { + OptionalSfixed32 = input.ReadSFixed32(); + break; + } + case 81: { + OptionalSfixed64 = input.ReadSFixed64(); + break; + } + case 93: { + OptionalFloat = input.ReadFloat(); + break; + } + case 97: { + OptionalDouble = input.ReadDouble(); + break; + } + case 104: { + OptionalBool = input.ReadBool(); + break; + } + case 114: { + OptionalString = input.ReadString(); + break; + } + case 122: { + OptionalBytes = input.ReadBytes(); + break; + } + case 146: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + case 154: { + if (optionalForeignMessage_ == null) { + OptionalForeignMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2(); + } + input.ReadMessage(OptionalForeignMessage); + break; + } + case 168: { + OptionalNestedEnum = (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedEnum) input.ReadEnum(); + break; + } + case 176: { + OptionalForeignEnum = (global::ProtobufTestMessages.Proto2.ForeignEnumProto2) input.ReadEnum(); + break; + } + case 194: { + OptionalStringPiece = input.ReadString(); + break; + } + case 202: { + OptionalCord = input.ReadString(); + break; + } + case 218: { + if (recursiveMessage_ == null) { + RecursiveMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2(); + } + input.ReadMessage(RecursiveMessage); + break; + } + case 250: + case 248: { + repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec); + break; + } + case 258: + case 256: { + repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec); + break; + } + case 266: + case 264: { + repeatedUint32_.AddEntriesFrom(ref input, _repeated_repeatedUint32_codec); + break; + } + case 274: + case 272: { + repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec); + break; + } + case 282: + case 280: { + repeatedSint32_.AddEntriesFrom(ref input, _repeated_repeatedSint32_codec); + break; + } + case 290: + case 288: { + repeatedSint64_.AddEntriesFrom(ref input, _repeated_repeatedSint64_codec); + break; + } + case 298: + case 301: { + repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec); + break; + } + case 306: + case 305: { + repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec); + break; + } + case 314: + case 317: { + repeatedSfixed32_.AddEntriesFrom(ref input, _repeated_repeatedSfixed32_codec); + break; + } + case 322: + case 321: { + repeatedSfixed64_.AddEntriesFrom(ref input, _repeated_repeatedSfixed64_codec); + break; + } + case 330: + case 333: { + repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec); + break; + } + case 338: + case 337: { + repeatedDouble_.AddEntriesFrom(ref input, _repeated_repeatedDouble_codec); + break; + } + case 346: + case 344: { + repeatedBool_.AddEntriesFrom(ref input, _repeated_repeatedBool_codec); + break; + } + case 354: { + repeatedString_.AddEntriesFrom(ref input, _repeated_repeatedString_codec); + break; + } + case 362: { + repeatedBytes_.AddEntriesFrom(ref input, _repeated_repeatedBytes_codec); + break; + } + case 386: { + repeatedNestedMessage_.AddEntriesFrom(ref input, _repeated_repeatedNestedMessage_codec); + break; + } + case 394: { + repeatedForeignMessage_.AddEntriesFrom(ref input, _repeated_repeatedForeignMessage_codec); + break; + } + case 410: + case 408: { + repeatedNestedEnum_.AddEntriesFrom(ref input, _repeated_repeatedNestedEnum_codec); + break; + } + case 418: + case 416: { + repeatedForeignEnum_.AddEntriesFrom(ref input, _repeated_repeatedForeignEnum_codec); + break; + } + case 434: { + repeatedStringPiece_.AddEntriesFrom(ref input, _repeated_repeatedStringPiece_codec); + break; + } + case 442: { + repeatedCord_.AddEntriesFrom(ref input, _repeated_repeatedCord_codec); + break; + } + case 450: { + mapInt32Int32_.AddEntriesFrom(ref input, _map_mapInt32Int32_codec); + break; + } + case 458: { + mapInt64Int64_.AddEntriesFrom(ref input, _map_mapInt64Int64_codec); + break; + } + case 466: { + mapUint32Uint32_.AddEntriesFrom(ref input, _map_mapUint32Uint32_codec); + break; + } + case 474: { + mapUint64Uint64_.AddEntriesFrom(ref input, _map_mapUint64Uint64_codec); + break; + } + case 482: { + mapSint32Sint32_.AddEntriesFrom(ref input, _map_mapSint32Sint32_codec); + break; + } + case 490: { + mapSint64Sint64_.AddEntriesFrom(ref input, _map_mapSint64Sint64_codec); + break; + } + case 498: { + mapFixed32Fixed32_.AddEntriesFrom(ref input, _map_mapFixed32Fixed32_codec); + break; + } + case 506: { + mapFixed64Fixed64_.AddEntriesFrom(ref input, _map_mapFixed64Fixed64_codec); + break; + } + case 514: { + mapSfixed32Sfixed32_.AddEntriesFrom(ref input, _map_mapSfixed32Sfixed32_codec); + break; + } + case 522: { + mapSfixed64Sfixed64_.AddEntriesFrom(ref input, _map_mapSfixed64Sfixed64_codec); + break; + } + case 530: { + mapInt32Float_.AddEntriesFrom(ref input, _map_mapInt32Float_codec); + break; + } + case 538: { + mapInt32Double_.AddEntriesFrom(ref input, _map_mapInt32Double_codec); + break; + } + case 546: { + mapBoolBool_.AddEntriesFrom(ref input, _map_mapBoolBool_codec); + break; + } + case 554: { + mapStringString_.AddEntriesFrom(ref input, _map_mapStringString_codec); + break; + } + case 562: { + mapStringBytes_.AddEntriesFrom(ref input, _map_mapStringBytes_codec); + break; + } + case 570: { + mapStringNestedMessage_.AddEntriesFrom(ref input, _map_mapStringNestedMessage_codec); + break; + } + case 578: { + mapStringForeignMessage_.AddEntriesFrom(ref input, _map_mapStringForeignMessage_codec); + break; + } + case 586: { + mapStringNestedEnum_.AddEntriesFrom(ref input, _map_mapStringNestedEnum_codec); + break; + } + case 594: { + mapStringForeignEnum_.AddEntriesFrom(ref input, _map_mapStringForeignEnum_codec); + break; + } + case 602: + case 600: { + packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec); + break; + } + case 610: + case 608: { + packedInt64_.AddEntriesFrom(ref input, _repeated_packedInt64_codec); + break; + } + case 618: + case 616: { + packedUint32_.AddEntriesFrom(ref input, _repeated_packedUint32_codec); + break; + } + case 626: + case 624: { + packedUint64_.AddEntriesFrom(ref input, _repeated_packedUint64_codec); + break; + } + case 634: + case 632: { + packedSint32_.AddEntriesFrom(ref input, _repeated_packedSint32_codec); + break; + } + case 642: + case 640: { + packedSint64_.AddEntriesFrom(ref input, _repeated_packedSint64_codec); + break; + } + case 650: + case 653: { + packedFixed32_.AddEntriesFrom(ref input, _repeated_packedFixed32_codec); + break; + } + case 658: + case 657: { + packedFixed64_.AddEntriesFrom(ref input, _repeated_packedFixed64_codec); + break; + } + case 666: + case 669: { + packedSfixed32_.AddEntriesFrom(ref input, _repeated_packedSfixed32_codec); + break; + } + case 674: + case 673: { + packedSfixed64_.AddEntriesFrom(ref input, _repeated_packedSfixed64_codec); + break; + } + case 682: + case 685: { + packedFloat_.AddEntriesFrom(ref input, _repeated_packedFloat_codec); + break; + } + case 690: + case 689: { + packedDouble_.AddEntriesFrom(ref input, _repeated_packedDouble_codec); + break; + } + case 698: + case 696: { + packedBool_.AddEntriesFrom(ref input, _repeated_packedBool_codec); + break; + } + case 706: + case 704: { + packedNestedEnum_.AddEntriesFrom(ref input, _repeated_packedNestedEnum_codec); + break; + } + case 714: + case 712: { + unpackedInt32_.AddEntriesFrom(ref input, _repeated_unpackedInt32_codec); + break; + } + case 722: + case 720: { + unpackedInt64_.AddEntriesFrom(ref input, _repeated_unpackedInt64_codec); + break; + } + case 730: + case 728: { + unpackedUint32_.AddEntriesFrom(ref input, _repeated_unpackedUint32_codec); + break; + } + case 738: + case 736: { + unpackedUint64_.AddEntriesFrom(ref input, _repeated_unpackedUint64_codec); + break; + } + case 746: + case 744: { + unpackedSint32_.AddEntriesFrom(ref input, _repeated_unpackedSint32_codec); + break; + } + case 754: + case 752: { + unpackedSint64_.AddEntriesFrom(ref input, _repeated_unpackedSint64_codec); + break; + } + case 762: + case 765: { + unpackedFixed32_.AddEntriesFrom(ref input, _repeated_unpackedFixed32_codec); + break; + } + case 770: + case 769: { + unpackedFixed64_.AddEntriesFrom(ref input, _repeated_unpackedFixed64_codec); + break; + } + case 778: + case 781: { + unpackedSfixed32_.AddEntriesFrom(ref input, _repeated_unpackedSfixed32_codec); + break; + } + case 786: + case 785: { + unpackedSfixed64_.AddEntriesFrom(ref input, _repeated_unpackedSfixed64_codec); + break; + } + case 794: + case 797: { + unpackedFloat_.AddEntriesFrom(ref input, _repeated_unpackedFloat_codec); + break; + } + case 802: + case 801: { + unpackedDouble_.AddEntriesFrom(ref input, _repeated_unpackedDouble_codec); + break; + } + case 810: + case 808: { + unpackedBool_.AddEntriesFrom(ref input, _repeated_unpackedBool_codec); + break; + } + case 818: + case 816: { + unpackedNestedEnum_.AddEntriesFrom(ref input, _repeated_unpackedNestedEnum_codec); + break; + } + case 888: { + OneofUint32 = input.ReadUInt32(); + break; + } + case 898: { + global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage subBuilder = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + subBuilder.MergeFrom(OneofNestedMessage); + } + input.ReadMessage(subBuilder); + OneofNestedMessage = subBuilder; + break; + } + case 906: { + OneofString = input.ReadString(); + break; + } + case 914: { + OneofBytes = input.ReadBytes(); + break; + } + case 920: { + OneofBool = input.ReadBool(); + break; + } + case 928: { + OneofUint64 = input.ReadUInt64(); + break; + } + case 941: { + OneofFloat = input.ReadFloat(); + break; + } + case 945: { + OneofDouble = input.ReadDouble(); + break; + } + case 952: { + oneofField_ = input.ReadEnum(); + oneofFieldCase_ = OneofFieldOneofCase.OneofEnum; + break; + } + case 1611: { + if (!HasData) { + Data = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.Data(); + } + input.ReadGroup(Data); + break; + } + case 3208: { + Fieldname1 = input.ReadInt32(); + break; + } + case 3216: { + FieldName2 = input.ReadInt32(); + break; + } + case 3224: { + FieldName3 = input.ReadInt32(); + break; + } + case 3232: { + FieldName4 = input.ReadInt32(); + break; + } + case 3240: { + Field0Name5 = input.ReadInt32(); + break; + } + case 3248: { + Field0Name6 = input.ReadInt32(); + break; + } + case 3256: { + FieldName7 = input.ReadInt32(); + break; + } + case 3264: { + FieldName8 = input.ReadInt32(); + break; + } + case 3272: { + FieldName9 = input.ReadInt32(); + break; + } + case 3280: { + FieldName10 = input.ReadInt32(); + break; + } + case 3288: { + FIELDNAME11 = input.ReadInt32(); + break; + } + case 3296: { + FIELDName12 = input.ReadInt32(); + break; + } + case 3304: { + FieldName13 = input.ReadInt32(); + break; + } + case 3312: { + FieldName14 = input.ReadInt32(); + break; + } + case 3320: { + FieldName15 = input.ReadInt32(); + break; + } + case 3328: { + FieldName16 = input.ReadInt32(); + break; + } + case 3336: { + FieldName17 = input.ReadInt32(); + break; + } + case 3344: { + FieldName18 = input.ReadInt32(); + break; + } + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + + #region Nested types + /// Container for nested types declared in the TestAllTypesProto2 message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum NestedEnum { + [pbr::OriginalName("FOO")] Foo = 0, + [pbr::OriginalName("BAR")] Bar = 1, + [pbr::OriginalName("BAZ")] Baz = 2, + /// + /// Intentionally negative. + /// + [pbr::OriginalName("NEG")] Neg = -1, + } + + public sealed partial class NestedMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + corecursive_ = other.corecursive_ != null ? other.corecursive_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private readonly static int ADefaultValue = 0; + + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + /// Field number for the "corecursive" field. + public const int CorecursiveFieldNumber = 2; + private global::ProtobufTestMessages.Proto2.TestAllTypesProto2 corecursive_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto2.TestAllTypesProto2 Corecursive { + get { return corecursive_; } + set { + corecursive_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + if (!object.Equals(Corecursive, other.Corecursive)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (corecursive_ != null) hash ^= Corecursive.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (corecursive_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Corecursive); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (corecursive_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Corecursive); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (corecursive_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Corecursive); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + if (other.corecursive_ != null) { + if (corecursive_ == null) { + Corecursive = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2(); + } + Corecursive.MergeFrom(other.Corecursive); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + A = input.ReadInt32(); + break; + } + case 18: { + if (corecursive_ == null) { + Corecursive = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2(); + } + input.ReadMessage(Corecursive); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + A = input.ReadInt32(); + break; + } + case 18: { + if (corecursive_ == null) { + Corecursive = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2(); + } + input.ReadMessage(Corecursive); + break; + } + } + } + } + #endif + + } + + /// + /// groups + /// + public sealed partial class Data : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Data()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Descriptor.NestedTypes[20]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Data() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Data(Data other) : this() { + _hasBits0 = other._hasBits0; + groupInt32_ = other.groupInt32_; + groupUint32_ = other.groupUint32_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Data Clone() { + return new Data(this); + } + + /// Field number for the "group_int32" field. + public const int GroupInt32FieldNumber = 202; + private readonly static int GroupInt32DefaultValue = 0; + + private int groupInt32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int GroupInt32 { + get { if ((_hasBits0 & 1) != 0) { return groupInt32_; } else { return GroupInt32DefaultValue; } } + set { + _hasBits0 |= 1; + groupInt32_ = value; + } + } + /// Gets whether the "group_int32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasGroupInt32 { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "group_int32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearGroupInt32() { + _hasBits0 &= ~1; + } + + /// Field number for the "group_uint32" field. + public const int GroupUint32FieldNumber = 203; + private readonly static uint GroupUint32DefaultValue = 0; + + private uint groupUint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint GroupUint32 { + get { if ((_hasBits0 & 2) != 0) { return groupUint32_; } else { return GroupUint32DefaultValue; } } + set { + _hasBits0 |= 2; + groupUint32_ = value; + } + } + /// Gets whether the "group_uint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasGroupUint32 { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "group_uint32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearGroupUint32() { + _hasBits0 &= ~2; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Data); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Data other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (GroupInt32 != other.GroupInt32) return false; + if (GroupUint32 != other.GroupUint32) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasGroupInt32) hash ^= GroupInt32.GetHashCode(); + if (HasGroupUint32) hash ^= GroupUint32.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasGroupInt32) { + output.WriteRawTag(208, 12); + output.WriteInt32(GroupInt32); + } + if (HasGroupUint32) { + output.WriteRawTag(216, 12); + output.WriteUInt32(GroupUint32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasGroupInt32) { + output.WriteRawTag(208, 12); + output.WriteInt32(GroupInt32); + } + if (HasGroupUint32) { + output.WriteRawTag(216, 12); + output.WriteUInt32(GroupUint32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasGroupInt32) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(GroupInt32); + } + if (HasGroupUint32) { + size += 2 + pb::CodedOutputStream.ComputeUInt32Size(GroupUint32); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Data other) { + if (other == null) { + return; + } + if (other.HasGroupInt32) { + GroupInt32 = other.GroupInt32; + } + if (other.HasGroupUint32) { + GroupUint32 = other.GroupUint32; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 1612: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 1616: { + GroupInt32 = input.ReadInt32(); + break; + } + case 1624: { + GroupUint32 = input.ReadUInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 1612: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 1616: { + GroupInt32 = input.ReadInt32(); + break; + } + case 1624: { + GroupUint32 = input.ReadUInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// message_set test case. + /// + public sealed partial class MessageSetCorrect : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageSetCorrect()); + private pb::UnknownFieldSet _unknownFields; + private pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Descriptor.NestedTypes[21]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageSetCorrect() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageSetCorrect(MessageSetCorrect other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageSetCorrect Clone() { + return new MessageSetCorrect(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as MessageSetCorrect); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(MessageSetCorrect other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(MessageSetCorrect other) { + if (other == null) { + return; + } + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + + } + + public sealed partial class MessageSetCorrectExtension1 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageSetCorrectExtension1()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Descriptor.NestedTypes[22]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageSetCorrectExtension1() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageSetCorrectExtension1(MessageSetCorrectExtension1 other) : this() { + str_ = other.str_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageSetCorrectExtension1 Clone() { + return new MessageSetCorrectExtension1(this); + } + + /// Field number for the "str" field. + public const int StrFieldNumber = 25; + private readonly static string StrDefaultValue = ""; + + private string str_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Str { + get { return str_ ?? StrDefaultValue; } + set { + str_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "str" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStr { + get { return str_ != null; } + } + /// Clears the value of the "str" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStr() { + str_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as MessageSetCorrectExtension1); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(MessageSetCorrectExtension1 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Str != other.Str) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasStr) hash ^= Str.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasStr) { + output.WriteRawTag(202, 1); + output.WriteString(Str); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasStr) { + output.WriteRawTag(202, 1); + output.WriteString(Str); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasStr) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(Str); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(MessageSetCorrectExtension1 other) { + if (other == null) { + return; + } + if (other.HasStr) { + Str = other.Str; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 202: { + Str = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 202: { + Str = input.ReadString(); + break; + } + } + } + } + #endif + + #region Extensions + /// Container for extensions for other messages declared in the MessageSetCorrectExtension1 message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Extensions { + public static readonly pb::Extension MessageSetExtension = + new pb::Extension(1547769, pb::FieldCodec.ForMessage(12382154, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension1.Parser)); + } + #endregion + + } + + public sealed partial class MessageSetCorrectExtension2 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageSetCorrectExtension2()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Descriptor.NestedTypes[23]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageSetCorrectExtension2() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageSetCorrectExtension2(MessageSetCorrectExtension2 other) : this() { + _hasBits0 = other._hasBits0; + i_ = other.i_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageSetCorrectExtension2 Clone() { + return new MessageSetCorrectExtension2(this); + } + + /// Field number for the "i" field. + public const int IFieldNumber = 9; + private readonly static int IDefaultValue = 0; + + private int i_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int I { + get { if ((_hasBits0 & 1) != 0) { return i_; } else { return IDefaultValue; } } + set { + _hasBits0 |= 1; + i_ = value; + } + } + /// Gets whether the "i" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasI { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "i" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearI() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as MessageSetCorrectExtension2); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(MessageSetCorrectExtension2 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (I != other.I) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasI) hash ^= I.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasI) { + output.WriteRawTag(72); + output.WriteInt32(I); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasI) { + output.WriteRawTag(72); + output.WriteInt32(I); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasI) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(I); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(MessageSetCorrectExtension2 other) { + if (other == null) { + return; + } + if (other.HasI) { + I = other.I; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 72: { + I = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 72: { + I = input.ReadInt32(); + break; + } + } + } + } + #endif + + #region Extensions + /// Container for extensions for other messages declared in the MessageSetCorrectExtension2 message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Extensions { + public static readonly pb::Extension MessageSetExtension = + new pb::Extension(4135312, pb::FieldCodec.ForMessage(33082498, global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension2.Parser)); + } + #endregion + + } + + } + #endregion + + } + + public sealed partial class ForeignMessageProto2 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ForeignMessageProto2()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufTestMessages.Proto2.TestMessagesProto2Reflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ForeignMessageProto2() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ForeignMessageProto2(ForeignMessageProto2 other) : this() { + _hasBits0 = other._hasBits0; + c_ = other.c_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ForeignMessageProto2 Clone() { + return new ForeignMessageProto2(this); + } + + /// Field number for the "c" field. + public const int CFieldNumber = 1; + private readonly static int CDefaultValue = 0; + + private int c_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int C { + get { if ((_hasBits0 & 1) != 0) { return c_; } else { return CDefaultValue; } } + set { + _hasBits0 |= 1; + c_ = value; + } + } + /// Gets whether the "c" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasC { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "c" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearC() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ForeignMessageProto2); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ForeignMessageProto2 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (C != other.C) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasC) hash ^= C.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasC) { + output.WriteRawTag(8); + output.WriteInt32(C); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasC) { + output.WriteRawTag(8); + output.WriteInt32(C); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasC) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(C); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ForeignMessageProto2 other) { + if (other == null) { + return; + } + if (other.HasC) { + C = other.C; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + C = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + C = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class UnknownToTestAllTypes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new UnknownToTestAllTypes()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufTestMessages.Proto2.TestMessagesProto2Reflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public UnknownToTestAllTypes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public UnknownToTestAllTypes(UnknownToTestAllTypes other) : this() { + _hasBits0 = other._hasBits0; + optionalInt32_ = other.optionalInt32_; + optionalString_ = other.optionalString_; + nestedMessage_ = other.nestedMessage_ != null ? other.nestedMessage_.Clone() : null; + optionalGroup_ = other.HasOptionalGroup ? other.optionalGroup_.Clone() : null; + optionalBool_ = other.optionalBool_; + repeatedInt32_ = other.repeatedInt32_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public UnknownToTestAllTypes Clone() { + return new UnknownToTestAllTypes(this); + } + + /// Field number for the "optional_int32" field. + public const int OptionalInt32FieldNumber = 1001; + private readonly static int OptionalInt32DefaultValue = 0; + + private int optionalInt32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalInt32 { + get { if ((_hasBits0 & 1) != 0) { return optionalInt32_; } else { return OptionalInt32DefaultValue; } } + set { + _hasBits0 |= 1; + optionalInt32_ = value; + } + } + /// Gets whether the "optional_int32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalInt32 { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "optional_int32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalInt32() { + _hasBits0 &= ~1; + } + + /// Field number for the "optional_string" field. + public const int OptionalStringFieldNumber = 1002; + private readonly static string OptionalStringDefaultValue = ""; + + private string optionalString_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalString { + get { return optionalString_ ?? OptionalStringDefaultValue; } + set { + optionalString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalString { + get { return optionalString_ != null; } + } + /// Clears the value of the "optional_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalString() { + optionalString_ = null; + } + + /// Field number for the "nested_message" field. + public const int NestedMessageFieldNumber = 1003; + private global::ProtobufTestMessages.Proto2.ForeignMessageProto2 nestedMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto2.ForeignMessageProto2 NestedMessage { + get { return nestedMessage_; } + set { + nestedMessage_ = value; + } + } + + /// Field number for the "optionalgroup" field. + public const int OptionalGroupFieldNumber = 1004; + private global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Types.OptionalGroup optionalGroup_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Types.OptionalGroup OptionalGroup { + get { return optionalGroup_; } + set { + optionalGroup_ = value; + } + } + /// Gets whether the optionalgroup field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalGroup { + get { return optionalGroup_ != null; } + } + /// Clears the value of the optionalgroup field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalGroup() { + optionalGroup_ = null; + } + + /// Field number for the "optional_bool" field. + public const int OptionalBoolFieldNumber = 1006; + private readonly static bool OptionalBoolDefaultValue = false; + + private bool optionalBool_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool OptionalBool { + get { if ((_hasBits0 & 2) != 0) { return optionalBool_; } else { return OptionalBoolDefaultValue; } } + set { + _hasBits0 |= 2; + optionalBool_ = value; + } + } + /// Gets whether the "optional_bool" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalBool { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "optional_bool" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalBool() { + _hasBits0 &= ~2; + } + + /// Field number for the "repeated_int32" field. + public const int RepeatedInt32FieldNumber = 1011; + private static readonly pb::FieldCodec _repeated_repeatedInt32_codec + = pb::FieldCodec.ForInt32(8088); + private readonly pbc::RepeatedField repeatedInt32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt32 { + get { return repeatedInt32_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as UnknownToTestAllTypes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(UnknownToTestAllTypes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (OptionalInt32 != other.OptionalInt32) return false; + if (OptionalString != other.OptionalString) return false; + if (!object.Equals(NestedMessage, other.NestedMessage)) return false; + if (!object.Equals(OptionalGroup, other.OptionalGroup)) return false; + if (OptionalBool != other.OptionalBool) return false; + if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasOptionalInt32) hash ^= OptionalInt32.GetHashCode(); + if (HasOptionalString) hash ^= OptionalString.GetHashCode(); + if (nestedMessage_ != null) hash ^= NestedMessage.GetHashCode(); + if (HasOptionalGroup) hash ^= OptionalGroup.GetHashCode(); + if (HasOptionalBool) hash ^= OptionalBool.GetHashCode(); + hash ^= repeatedInt32_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasOptionalInt32) { + output.WriteRawTag(200, 62); + output.WriteInt32(OptionalInt32); + } + if (HasOptionalString) { + output.WriteRawTag(210, 62); + output.WriteString(OptionalString); + } + if (nestedMessage_ != null) { + output.WriteRawTag(218, 62); + output.WriteMessage(NestedMessage); + } + if (HasOptionalGroup) { + output.WriteRawTag(227, 62); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(228, 62); + } + if (HasOptionalBool) { + output.WriteRawTag(240, 62); + output.WriteBool(OptionalBool); + } + repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasOptionalInt32) { + output.WriteRawTag(200, 62); + output.WriteInt32(OptionalInt32); + } + if (HasOptionalString) { + output.WriteRawTag(210, 62); + output.WriteString(OptionalString); + } + if (nestedMessage_ != null) { + output.WriteRawTag(218, 62); + output.WriteMessage(NestedMessage); + } + if (HasOptionalGroup) { + output.WriteRawTag(227, 62); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(228, 62); + } + if (HasOptionalBool) { + output.WriteRawTag(240, 62); + output.WriteBool(OptionalBool); + } + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasOptionalInt32) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32); + } + if (HasOptionalString) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalString); + } + if (nestedMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(NestedMessage); + } + if (HasOptionalGroup) { + size += 4 + pb::CodedOutputStream.ComputeGroupSize(OptionalGroup); + } + if (HasOptionalBool) { + size += 2 + 1; + } + size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(UnknownToTestAllTypes other) { + if (other == null) { + return; + } + if (other.HasOptionalInt32) { + OptionalInt32 = other.OptionalInt32; + } + if (other.HasOptionalString) { + OptionalString = other.OptionalString; + } + if (other.nestedMessage_ != null) { + if (nestedMessage_ == null) { + NestedMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2(); + } + NestedMessage.MergeFrom(other.NestedMessage); + } + if (other.HasOptionalGroup) { + if (!HasOptionalGroup) { + OptionalGroup = new global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Types.OptionalGroup(); + } + OptionalGroup.MergeFrom(other.OptionalGroup); + } + if (other.HasOptionalBool) { + OptionalBool = other.OptionalBool; + } + repeatedInt32_.Add(other.repeatedInt32_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 8008: { + OptionalInt32 = input.ReadInt32(); + break; + } + case 8018: { + OptionalString = input.ReadString(); + break; + } + case 8026: { + if (nestedMessage_ == null) { + NestedMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2(); + } + input.ReadMessage(NestedMessage); + break; + } + case 8035: { + if (!HasOptionalGroup) { + OptionalGroup = new global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Types.OptionalGroup(); + } + input.ReadGroup(OptionalGroup); + break; + } + case 8048: { + OptionalBool = input.ReadBool(); + break; + } + case 8090: + case 8088: { + repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 8008: { + OptionalInt32 = input.ReadInt32(); + break; + } + case 8018: { + OptionalString = input.ReadString(); + break; + } + case 8026: { + if (nestedMessage_ == null) { + NestedMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2(); + } + input.ReadMessage(NestedMessage); + break; + } + case 8035: { + if (!HasOptionalGroup) { + OptionalGroup = new global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Types.OptionalGroup(); + } + input.ReadGroup(OptionalGroup); + break; + } + case 8048: { + OptionalBool = input.ReadBool(); + break; + } + case 8090: + case 8088: { + repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the UnknownToTestAllTypes message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class OptionalGroup : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OptionalGroup()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup(OptionalGroup other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup Clone() { + return new OptionalGroup(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private readonly static int ADefaultValue = 0; + + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as OptionalGroup); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(OptionalGroup other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(OptionalGroup other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 8036: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + A = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 8036: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + A = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs new file mode 100644 index 0000000000000..6f915cb79bf9e --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs @@ -0,0 +1,5664 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/test_messages_proto3.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace ProtobufTestMessages.Proto3 { + + /// Holder for reflection information generated from google/protobuf/test_messages_proto3.proto + public static partial class TestMessagesProto3Reflection { + + #region Descriptor + /// File descriptor for google/protobuf/test_messages_proto3.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static TestMessagesProto3Reflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Cipnb29nbGUvcHJvdG9idWYvdGVzdF9tZXNzYWdlc19wcm90bzMucHJvdG8S", + "HXByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zGhlnb29nbGUvcHJvdG9i", + "dWYvYW55LnByb3RvGh5nb29nbGUvcHJvdG9idWYvZHVyYXRpb24ucHJvdG8a", + "IGdvb2dsZS9wcm90b2J1Zi9maWVsZF9tYXNrLnByb3RvGhxnb29nbGUvcHJv", + "dG9idWYvc3RydWN0LnByb3RvGh9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1w", + "LnByb3RvGh5nb29nbGUvcHJvdG9idWYvd3JhcHBlcnMucHJvdG8isUUKElRl", + "c3RBbGxUeXBlc1Byb3RvMxIWCg5vcHRpb25hbF9pbnQzMhgBIAEoBRIWCg5v", + "cHRpb25hbF9pbnQ2NBgCIAEoAxIXCg9vcHRpb25hbF91aW50MzIYAyABKA0S", + "FwoPb3B0aW9uYWxfdWludDY0GAQgASgEEhcKD29wdGlvbmFsX3NpbnQzMhgF", + "IAEoERIXCg9vcHRpb25hbF9zaW50NjQYBiABKBISGAoQb3B0aW9uYWxfZml4", + "ZWQzMhgHIAEoBxIYChBvcHRpb25hbF9maXhlZDY0GAggASgGEhkKEW9wdGlv", + "bmFsX3NmaXhlZDMyGAkgASgPEhkKEW9wdGlvbmFsX3NmaXhlZDY0GAogASgQ", + "EhYKDm9wdGlvbmFsX2Zsb2F0GAsgASgCEhcKD29wdGlvbmFsX2RvdWJsZRgM", + "IAEoARIVCg1vcHRpb25hbF9ib29sGA0gASgIEhcKD29wdGlvbmFsX3N0cmlu", + "ZxgOIAEoCRIWCg5vcHRpb25hbF9ieXRlcxgPIAEoDBJgChdvcHRpb25hbF9u", + "ZXN0ZWRfbWVzc2FnZRgSIAEoCzI/LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMu", + "cHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5OZXN0ZWRNZXNzYWdlEk8KGG9w", + "dGlvbmFsX2ZvcmVpZ25fbWVzc2FnZRgTIAEoCzItLnByb3RvYnVmX3Rlc3Rf", + "bWVzc2FnZXMucHJvdG8zLkZvcmVpZ25NZXNzYWdlEloKFG9wdGlvbmFsX25l", + "c3RlZF9lbnVtGBUgASgOMjwucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90", + "bzMuVGVzdEFsbFR5cGVzUHJvdG8zLk5lc3RlZEVudW0SSQoVb3B0aW9uYWxf", + "Zm9yZWlnbl9lbnVtGBYgASgOMioucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5w", + "cm90bzMuRm9yZWlnbkVudW0SXAoVb3B0aW9uYWxfYWxpYXNlZF9lbnVtGBcg", + "ASgOMj0ucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5", + "cGVzUHJvdG8zLkFsaWFzZWRFbnVtEiEKFW9wdGlvbmFsX3N0cmluZ19waWVj", + "ZRgYIAEoCUICCAISGQoNb3B0aW9uYWxfY29yZBgZIAEoCUICCAESTAoRcmVj", + "dXJzaXZlX21lc3NhZ2UYGyABKAsyMS5wcm90b2J1Zl90ZXN0X21lc3NhZ2Vz", + "LnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMSFgoOcmVwZWF0ZWRfaW50MzIY", + "HyADKAUSFgoOcmVwZWF0ZWRfaW50NjQYICADKAMSFwoPcmVwZWF0ZWRfdWlu", + "dDMyGCEgAygNEhcKD3JlcGVhdGVkX3VpbnQ2NBgiIAMoBBIXCg9yZXBlYXRl", + "ZF9zaW50MzIYIyADKBESFwoPcmVwZWF0ZWRfc2ludDY0GCQgAygSEhgKEHJl", + "cGVhdGVkX2ZpeGVkMzIYJSADKAcSGAoQcmVwZWF0ZWRfZml4ZWQ2NBgmIAMo", + "BhIZChFyZXBlYXRlZF9zZml4ZWQzMhgnIAMoDxIZChFyZXBlYXRlZF9zZml4", + "ZWQ2NBgoIAMoEBIWCg5yZXBlYXRlZF9mbG9hdBgpIAMoAhIXCg9yZXBlYXRl", + "ZF9kb3VibGUYKiADKAESFQoNcmVwZWF0ZWRfYm9vbBgrIAMoCBIXCg9yZXBl", + "YXRlZF9zdHJpbmcYLCADKAkSFgoOcmVwZWF0ZWRfYnl0ZXMYLSADKAwSYAoX", + "cmVwZWF0ZWRfbmVzdGVkX21lc3NhZ2UYMCADKAsyPy5wcm90b2J1Zl90ZXN0", + "X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTmVzdGVkTWVz", + "c2FnZRJPChhyZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UYMSADKAsyLS5wcm90", + "b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5Gb3JlaWduTWVzc2FnZRJaChRy", + "ZXBlYXRlZF9uZXN0ZWRfZW51bRgzIAMoDjI8LnByb3RvYnVmX3Rlc3RfbWVz", + "c2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5OZXN0ZWRFbnVtEkkK", + "FXJlcGVhdGVkX2ZvcmVpZ25fZW51bRg0IAMoDjIqLnByb3RvYnVmX3Rlc3Rf", + "bWVzc2FnZXMucHJvdG8zLkZvcmVpZ25FbnVtEiEKFXJlcGVhdGVkX3N0cmlu", + "Z19waWVjZRg2IAMoCUICCAISGQoNcmVwZWF0ZWRfY29yZBg3IAMoCUICCAES", + "GAoMcGFja2VkX2ludDMyGEsgAygFQgIQARIYCgxwYWNrZWRfaW50NjQYTCAD", + "KANCAhABEhkKDXBhY2tlZF91aW50MzIYTSADKA1CAhABEhkKDXBhY2tlZF91", + "aW50NjQYTiADKARCAhABEhkKDXBhY2tlZF9zaW50MzIYTyADKBFCAhABEhkK", + "DXBhY2tlZF9zaW50NjQYUCADKBJCAhABEhoKDnBhY2tlZF9maXhlZDMyGFEg", + "AygHQgIQARIaCg5wYWNrZWRfZml4ZWQ2NBhSIAMoBkICEAESGwoPcGFja2Vk", + "X3NmaXhlZDMyGFMgAygPQgIQARIbCg9wYWNrZWRfc2ZpeGVkNjQYVCADKBBC", + "AhABEhgKDHBhY2tlZF9mbG9hdBhVIAMoAkICEAESGQoNcGFja2VkX2RvdWJs", + "ZRhWIAMoAUICEAESFwoLcGFja2VkX2Jvb2wYVyADKAhCAhABElwKEnBhY2tl", + "ZF9uZXN0ZWRfZW51bRhYIAMoDjI8LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMu", + "cHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5OZXN0ZWRFbnVtQgIQARIaCg51", + "bnBhY2tlZF9pbnQzMhhZIAMoBUICEAASGgoOdW5wYWNrZWRfaW50NjQYWiAD", + "KANCAhAAEhsKD3VucGFja2VkX3VpbnQzMhhbIAMoDUICEAASGwoPdW5wYWNr", + "ZWRfdWludDY0GFwgAygEQgIQABIbCg91bnBhY2tlZF9zaW50MzIYXSADKBFC", + "AhAAEhsKD3VucGFja2VkX3NpbnQ2NBheIAMoEkICEAASHAoQdW5wYWNrZWRf", + "Zml4ZWQzMhhfIAMoB0ICEAASHAoQdW5wYWNrZWRfZml4ZWQ2NBhgIAMoBkIC", + "EAASHQoRdW5wYWNrZWRfc2ZpeGVkMzIYYSADKA9CAhAAEh0KEXVucGFja2Vk", + "X3NmaXhlZDY0GGIgAygQQgIQABIaCg51bnBhY2tlZF9mbG9hdBhjIAMoAkIC", + "EAASGwoPdW5wYWNrZWRfZG91YmxlGGQgAygBQgIQABIZCg11bnBhY2tlZF9i", + "b29sGGUgAygIQgIQABJeChR1bnBhY2tlZF9uZXN0ZWRfZW51bRhmIAMoDjI8", + "LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1By", + "b3RvMy5OZXN0ZWRFbnVtQgIQABJdCg9tYXBfaW50MzJfaW50MzIYOCADKAsy", + "RC5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQ", + "cm90bzMuTWFwSW50MzJJbnQzMkVudHJ5El0KD21hcF9pbnQ2NF9pbnQ2NBg5", + "IAMoCzJELnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxU", + "eXBlc1Byb3RvMy5NYXBJbnQ2NEludDY0RW50cnkSYQoRbWFwX3VpbnQzMl91", + "aW50MzIYOiADKAsyRi5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5U", + "ZXN0QWxsVHlwZXNQcm90bzMuTWFwVWludDMyVWludDMyRW50cnkSYQoRbWFw", + "X3VpbnQ2NF91aW50NjQYOyADKAsyRi5wcm90b2J1Zl90ZXN0X21lc3NhZ2Vz", + "LnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTWFwVWludDY0VWludDY0RW50", + "cnkSYQoRbWFwX3NpbnQzMl9zaW50MzIYPCADKAsyRi5wcm90b2J1Zl90ZXN0", + "X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTWFwU2ludDMy", + "U2ludDMyRW50cnkSYQoRbWFwX3NpbnQ2NF9zaW50NjQYPSADKAsyRi5wcm90", + "b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMu", + "TWFwU2ludDY0U2ludDY0RW50cnkSZQoTbWFwX2ZpeGVkMzJfZml4ZWQzMhg+", + "IAMoCzJILnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxU", + "eXBlc1Byb3RvMy5NYXBGaXhlZDMyRml4ZWQzMkVudHJ5EmUKE21hcF9maXhl", + "ZDY0X2ZpeGVkNjQYPyADKAsySC5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnBy", + "b3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTWFwRml4ZWQ2NEZpeGVkNjRFbnRy", + "eRJpChVtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIYQCADKAsySi5wcm90b2J1Zl90", + "ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTWFwU2Zp", + "eGVkMzJTZml4ZWQzMkVudHJ5EmkKFW1hcF9zZml4ZWQ2NF9zZml4ZWQ2NBhB", + "IAMoCzJKLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxU", + "eXBlc1Byb3RvMy5NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkSXQoPbWFwX2lu", + "dDMyX2Zsb2F0GEIgAygLMkQucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90", + "bzMuVGVzdEFsbFR5cGVzUHJvdG8zLk1hcEludDMyRmxvYXRFbnRyeRJfChBt", + "YXBfaW50MzJfZG91YmxlGEMgAygLMkUucHJvdG9idWZfdGVzdF9tZXNzYWdl", + "cy5wcm90bzMuVGVzdEFsbFR5cGVzUHJvdG8zLk1hcEludDMyRG91YmxlRW50", + "cnkSWQoNbWFwX2Jvb2xfYm9vbBhEIAMoCzJCLnByb3RvYnVmX3Rlc3RfbWVz", + "c2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5NYXBCb29sQm9vbEVu", + "dHJ5EmEKEW1hcF9zdHJpbmdfc3RyaW5nGEUgAygLMkYucHJvdG9idWZfdGVz", + "dF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzUHJvdG8zLk1hcFN0cmlu", + "Z1N0cmluZ0VudHJ5El8KEG1hcF9zdHJpbmdfYnl0ZXMYRiADKAsyRS5wcm90", + "b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMu", + "TWFwU3RyaW5nQnl0ZXNFbnRyeRJwChltYXBfc3RyaW5nX25lc3RlZF9tZXNz", + "YWdlGEcgAygLMk0ucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuVGVz", + "dEFsbFR5cGVzUHJvdG8zLk1hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRyeRJy", + "ChptYXBfc3RyaW5nX2ZvcmVpZ25fbWVzc2FnZRhIIAMoCzJOLnByb3RvYnVm", + "X3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5NYXBT", + "dHJpbmdGb3JlaWduTWVzc2FnZUVudHJ5EmoKFm1hcF9zdHJpbmdfbmVzdGVk", + "X2VudW0YSSADKAsySi5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5U", + "ZXN0QWxsVHlwZXNQcm90bzMuTWFwU3RyaW5nTmVzdGVkRW51bUVudHJ5EmwK", + "F21hcF9zdHJpbmdfZm9yZWlnbl9lbnVtGEogAygLMksucHJvdG9idWZfdGVz", + "dF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzUHJvdG8zLk1hcFN0cmlu", + "Z0ZvcmVpZ25FbnVtRW50cnkSFgoMb25lb2ZfdWludDMyGG8gASgNSAASXwoU", + "b25lb2ZfbmVzdGVkX21lc3NhZ2UYcCABKAsyPy5wcm90b2J1Zl90ZXN0X21l", + "c3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTmVzdGVkTWVzc2Fn", + "ZUgAEhYKDG9uZW9mX3N0cmluZxhxIAEoCUgAEhUKC29uZW9mX2J5dGVzGHIg", + "ASgMSAASFAoKb25lb2ZfYm9vbBhzIAEoCEgAEhYKDG9uZW9mX3VpbnQ2NBh0", + "IAEoBEgAEhUKC29uZW9mX2Zsb2F0GHUgASgCSAASFgoMb25lb2ZfZG91Ymxl", + "GHYgASgBSAASUgoKb25lb2ZfZW51bRh3IAEoDjI8LnByb3RvYnVmX3Rlc3Rf", + "bWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5OZXN0ZWRFbnVt", + "SAASNgoQb25lb2ZfbnVsbF92YWx1ZRh4IAEoDjIaLmdvb2dsZS5wcm90b2J1", + "Zi5OdWxsVmFsdWVIABI6ChVvcHRpb25hbF9ib29sX3dyYXBwZXIYyQEgASgL", + "MhouZ29vZ2xlLnByb3RvYnVmLkJvb2xWYWx1ZRI8ChZvcHRpb25hbF9pbnQz", + "Ml93cmFwcGVyGMoBIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVl", + "EjwKFm9wdGlvbmFsX2ludDY0X3dyYXBwZXIYywEgASgLMhsuZ29vZ2xlLnBy", + "b3RvYnVmLkludDY0VmFsdWUSPgoXb3B0aW9uYWxfdWludDMyX3dyYXBwZXIY", + "zAEgASgLMhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlEj4KF29wdGlv", + "bmFsX3VpbnQ2NF93cmFwcGVyGM0BIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5V", + "SW50NjRWYWx1ZRI8ChZvcHRpb25hbF9mbG9hdF93cmFwcGVyGM4BIAEoCzIb", + "Lmdvb2dsZS5wcm90b2J1Zi5GbG9hdFZhbHVlEj4KF29wdGlvbmFsX2RvdWJs", + "ZV93cmFwcGVyGM8BIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1", + "ZRI+ChdvcHRpb25hbF9zdHJpbmdfd3JhcHBlchjQASABKAsyHC5nb29nbGUu", + "cHJvdG9idWYuU3RyaW5nVmFsdWUSPAoWb3B0aW9uYWxfYnl0ZXNfd3JhcHBl", + "chjRASABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZRI6ChVyZXBl", + "YXRlZF9ib29sX3dyYXBwZXIY0wEgAygLMhouZ29vZ2xlLnByb3RvYnVmLkJv", + "b2xWYWx1ZRI8ChZyZXBlYXRlZF9pbnQzMl93cmFwcGVyGNQBIAMoCzIbLmdv", + "b2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVlEjwKFnJlcGVhdGVkX2ludDY0X3dy", + "YXBwZXIY1QEgAygLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSPgoX", + "cmVwZWF0ZWRfdWludDMyX3dyYXBwZXIY1gEgAygLMhwuZ29vZ2xlLnByb3Rv", + "YnVmLlVJbnQzMlZhbHVlEj4KF3JlcGVhdGVkX3VpbnQ2NF93cmFwcGVyGNcB", + "IAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50NjRWYWx1ZRI8ChZyZXBlYXRl", + "ZF9mbG9hdF93cmFwcGVyGNgBIAMoCzIbLmdvb2dsZS5wcm90b2J1Zi5GbG9h", + "dFZhbHVlEj4KF3JlcGVhdGVkX2RvdWJsZV93cmFwcGVyGNkBIAMoCzIcLmdv", + "b2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI+ChdyZXBlYXRlZF9zdHJpbmdf", + "d3JhcHBlchjaASADKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUS", + "PAoWcmVwZWF0ZWRfYnl0ZXNfd3JhcHBlchjbASADKAsyGy5nb29nbGUucHJv", + "dG9idWYuQnl0ZXNWYWx1ZRI1ChFvcHRpb25hbF9kdXJhdGlvbhitAiABKAsy", + "GS5nb29nbGUucHJvdG9idWYuRHVyYXRpb24SNwoSb3B0aW9uYWxfdGltZXN0", + "YW1wGK4CIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASOAoTb3B0", + "aW9uYWxfZmllbGRfbWFzaxivAiABKAsyGi5nb29nbGUucHJvdG9idWYuRmll", + "bGRNYXNrEjEKD29wdGlvbmFsX3N0cnVjdBiwAiABKAsyFy5nb29nbGUucHJv", + "dG9idWYuU3RydWN0EisKDG9wdGlvbmFsX2FueRixAiABKAsyFC5nb29nbGUu", + "cHJvdG9idWYuQW55Ei8KDm9wdGlvbmFsX3ZhbHVlGLICIAEoCzIWLmdvb2ds", + "ZS5wcm90b2J1Zi5WYWx1ZRI4ChNvcHRpb25hbF9udWxsX3ZhbHVlGLMCIAEo", + "DjIaLmdvb2dsZS5wcm90b2J1Zi5OdWxsVmFsdWUSNQoRcmVwZWF0ZWRfZHVy", + "YXRpb24YtwIgAygLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEjcKEnJl", + "cGVhdGVkX3RpbWVzdGFtcBi4AiADKAsyGi5nb29nbGUucHJvdG9idWYuVGlt", + "ZXN0YW1wEjcKEnJlcGVhdGVkX2ZpZWxkbWFzaxi5AiADKAsyGi5nb29nbGUu", + "cHJvdG9idWYuRmllbGRNYXNrEjEKD3JlcGVhdGVkX3N0cnVjdBjEAiADKAsy", + "Fy5nb29nbGUucHJvdG9idWYuU3RydWN0EisKDHJlcGVhdGVkX2FueRi7AiAD", + "KAsyFC5nb29nbGUucHJvdG9idWYuQW55Ei8KDnJlcGVhdGVkX3ZhbHVlGLwC", + "IAMoCzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZRI4ChNyZXBlYXRlZF9saXN0", + "X3ZhbHVlGL0CIAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5MaXN0VmFsdWUSEwoK", + "ZmllbGRuYW1lMRiRAyABKAUSFAoLZmllbGRfbmFtZTIYkgMgASgFEhUKDF9m", + "aWVsZF9uYW1lMxiTAyABKAUSFgoNZmllbGRfX25hbWU0XxiUAyABKAUSFAoL", + "ZmllbGQwbmFtZTUYlQMgASgFEhYKDWZpZWxkXzBfbmFtZTYYlgMgASgFEhMK", + "CmZpZWxkTmFtZTcYlwMgASgFEhMKCkZpZWxkTmFtZTgYmAMgASgFEhQKC2Zp", + "ZWxkX05hbWU5GJkDIAEoBRIVCgxGaWVsZF9OYW1lMTAYmgMgASgFEhUKDEZJ", + "RUxEX05BTUUxMRibAyABKAUSFQoMRklFTERfbmFtZTEyGJwDIAEoBRIXCg5f", + "X2ZpZWxkX25hbWUxMxidAyABKAUSFwoOX19GaWVsZF9uYW1lMTQYngMgASgF", + "EhYKDWZpZWxkX19uYW1lMTUYnwMgASgFEhYKDWZpZWxkX19OYW1lMTYYoAMg", + "ASgFEhcKDmZpZWxkX25hbWUxN19fGKEDIAEoBRIXCg5GaWVsZF9uYW1lMThf", + "XxiiAyABKAUaYgoNTmVzdGVkTWVzc2FnZRIJCgFhGAEgASgFEkYKC2NvcmVj", + "dXJzaXZlGAIgASgLMjEucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMu", + "VGVzdEFsbFR5cGVzUHJvdG8zGjQKEk1hcEludDMySW50MzJFbnRyeRILCgNr", + "ZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1hcEludDY0SW50NjRF", + "bnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6AjgBGjYKFE1hcFVp", + "bnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2YWx1ZRgCIAEoDToC", + "OAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5GAEgASgEEg0KBXZh", + "bHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJFbnRyeRILCgNrZXkY", + "ASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNpbnQ2NFNpbnQ2NEVu", + "dHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoCOAEaOAoWTWFwRml4", + "ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoFdmFsdWUYAiABKAc6", + "AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoDa2V5GAEgASgGEg0K", + "BXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNmaXhlZDMyRW50cnkS", + "CwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6ChhNYXBTZml4ZWQ2", + "NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZhbHVlGAIgASgQOgI4", + "ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEgASgFEg0KBXZhbHVl", + "GAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5EgsKA2tleRgBIAEo", + "BRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJvb2xFbnRyeRILCgNr", + "ZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGjYKFE1hcFN0cmluZ1N0cmlu", + "Z0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEaNQoTTWFw", + "U3RyaW5nQnl0ZXNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAw6", + "AjgBGn4KG01hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRyeRILCgNrZXkYASAB", + "KAkSTgoFdmFsdWUYAiABKAsyPy5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnBy", + "b3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTmVzdGVkTWVzc2FnZToCOAEabQoc", + "TWFwU3RyaW5nRm9yZWlnbk1lc3NhZ2VFbnRyeRILCgNrZXkYASABKAkSPAoF", + "dmFsdWUYAiABKAsyLS5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5G", + "b3JlaWduTWVzc2FnZToCOAEaeAoYTWFwU3RyaW5nTmVzdGVkRW51bUVudHJ5", + "EgsKA2tleRgBIAEoCRJLCgV2YWx1ZRgCIAEoDjI8LnByb3RvYnVmX3Rlc3Rf", + "bWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5OZXN0ZWRFbnVt", + "OgI4ARpnChlNYXBTdHJpbmdGb3JlaWduRW51bUVudHJ5EgsKA2tleRgBIAEo", + "CRI5CgV2YWx1ZRgCIAEoDjIqLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJv", + "dG8zLkZvcmVpZ25FbnVtOgI4ASI5CgpOZXN0ZWRFbnVtEgcKA0ZPTxAAEgcK", + "A0JBUhABEgcKA0JBWhACEhAKA05FRxD///////////8BIlkKC0FsaWFzZWRF", + "bnVtEg0KCUFMSUFTX0ZPTxAAEg0KCUFMSUFTX0JBUhABEg0KCUFMSUFTX0JB", + "WhACEgcKA1FVWBACEgcKA3F1eBACEgcKA2JBehACGgIQAUINCgtvbmVvZl9m", + "aWVsZEoGCPUDEP8DIhsKDkZvcmVpZ25NZXNzYWdlEgkKAWMYASABKAUqQAoL", + "Rm9yZWlnbkVudW0SDwoLRk9SRUlHTl9GT08QABIPCgtGT1JFSUdOX0JBUhAB", + "Eg8KC0ZPUkVJR05fQkFaEAJCOAooY29tLmdvb2dsZS5wcm90b2J1Zl90ZXN0", + "X21lc3NhZ2VzLnByb3RvM0gB+AEBogIGUHJvdG8zYgZwcm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ProtobufTestMessages.Proto3.ForeignEnum), }, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3), global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalAliasedEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedNestedEnum", "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedNestedEnum", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OneofBool", "OneofUint64", "OneofFloat", "OneofDouble", "OneofEnum", "OneofNullValue", "OptionalBoolWrapper", "OptionalInt32Wrapper", "OptionalInt64Wrapper", "OptionalUint32Wrapper", "OptionalUint64Wrapper", "OptionalFloatWrapper", "OptionalDoubleWrapper", "OptionalStringWrapper", "OptionalBytesWrapper", "RepeatedBoolWrapper", "RepeatedInt32Wrapper", "RepeatedInt64Wrapper", "RepeatedUint32Wrapper", "RepeatedUint64Wrapper", "RepeatedFloatWrapper", "RepeatedDoubleWrapper", "RepeatedStringWrapper", "RepeatedBytesWrapper", "OptionalDuration", "OptionalTimestamp", "OptionalFieldMask", "OptionalStruct", "OptionalAny", "OptionalValue", "OptionalNullValue", "RepeatedDuration", "RepeatedTimestamp", "RepeatedFieldmask", "RepeatedStruct", "RepeatedAny", "RepeatedValue", "RepeatedListValue", "Fieldname1", "FieldName2", "FieldName3", "FieldName4", "Field0Name5", "Field0Name6", "FieldName7", "FieldName8", "FieldName9", "FieldName10", "FIELDNAME11", "FIELDName12", "FieldName13", "FieldName14", "FieldName15", "FieldName16", "FieldName17", "FieldName18" }, new[]{ "OneofField" }, new[]{ typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum), typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage), global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser, new[]{ "A", "Corecursive" }, null, null, null, null), + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.ForeignMessage), global::ProtobufTestMessages.Proto3.ForeignMessage.Parser, new[]{ "C" }, null, null, null, null) + })); + } + #endregion + + } + #region Enums + public enum ForeignEnum { + [pbr::OriginalName("FOREIGN_FOO")] ForeignFoo = 0, + [pbr::OriginalName("FOREIGN_BAR")] ForeignBar = 1, + [pbr::OriginalName("FOREIGN_BAZ")] ForeignBaz = 2, + } + + #endregion + + #region Messages + /// + /// This proto includes every type of field in both singular and repeated + /// forms. + /// + /// Also, crucially, all messages and enums in this file are eventually + /// submessages of this message. So for example, a fuzz test of TestAllTypes + /// could trigger bugs that occur in any message type in this file. We verify + /// this stays true in a unit test. + /// + public sealed partial class TestAllTypesProto3 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestAllTypesProto3()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufTestMessages.Proto3.TestMessagesProto3Reflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllTypesProto3() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllTypesProto3(TestAllTypesProto3 other) : this() { + optionalInt32_ = other.optionalInt32_; + optionalInt64_ = other.optionalInt64_; + optionalUint32_ = other.optionalUint32_; + optionalUint64_ = other.optionalUint64_; + optionalSint32_ = other.optionalSint32_; + optionalSint64_ = other.optionalSint64_; + optionalFixed32_ = other.optionalFixed32_; + optionalFixed64_ = other.optionalFixed64_; + optionalSfixed32_ = other.optionalSfixed32_; + optionalSfixed64_ = other.optionalSfixed64_; + optionalFloat_ = other.optionalFloat_; + optionalDouble_ = other.optionalDouble_; + optionalBool_ = other.optionalBool_; + optionalString_ = other.optionalString_; + optionalBytes_ = other.optionalBytes_; + optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null; + optionalForeignMessage_ = other.optionalForeignMessage_ != null ? other.optionalForeignMessage_.Clone() : null; + optionalNestedEnum_ = other.optionalNestedEnum_; + optionalForeignEnum_ = other.optionalForeignEnum_; + optionalAliasedEnum_ = other.optionalAliasedEnum_; + optionalStringPiece_ = other.optionalStringPiece_; + optionalCord_ = other.optionalCord_; + recursiveMessage_ = other.recursiveMessage_ != null ? other.recursiveMessage_.Clone() : null; + repeatedInt32_ = other.repeatedInt32_.Clone(); + repeatedInt64_ = other.repeatedInt64_.Clone(); + repeatedUint32_ = other.repeatedUint32_.Clone(); + repeatedUint64_ = other.repeatedUint64_.Clone(); + repeatedSint32_ = other.repeatedSint32_.Clone(); + repeatedSint64_ = other.repeatedSint64_.Clone(); + repeatedFixed32_ = other.repeatedFixed32_.Clone(); + repeatedFixed64_ = other.repeatedFixed64_.Clone(); + repeatedSfixed32_ = other.repeatedSfixed32_.Clone(); + repeatedSfixed64_ = other.repeatedSfixed64_.Clone(); + repeatedFloat_ = other.repeatedFloat_.Clone(); + repeatedDouble_ = other.repeatedDouble_.Clone(); + repeatedBool_ = other.repeatedBool_.Clone(); + repeatedString_ = other.repeatedString_.Clone(); + repeatedBytes_ = other.repeatedBytes_.Clone(); + repeatedNestedMessage_ = other.repeatedNestedMessage_.Clone(); + repeatedForeignMessage_ = other.repeatedForeignMessage_.Clone(); + repeatedNestedEnum_ = other.repeatedNestedEnum_.Clone(); + repeatedForeignEnum_ = other.repeatedForeignEnum_.Clone(); + repeatedStringPiece_ = other.repeatedStringPiece_.Clone(); + repeatedCord_ = other.repeatedCord_.Clone(); + packedInt32_ = other.packedInt32_.Clone(); + packedInt64_ = other.packedInt64_.Clone(); + packedUint32_ = other.packedUint32_.Clone(); + packedUint64_ = other.packedUint64_.Clone(); + packedSint32_ = other.packedSint32_.Clone(); + packedSint64_ = other.packedSint64_.Clone(); + packedFixed32_ = other.packedFixed32_.Clone(); + packedFixed64_ = other.packedFixed64_.Clone(); + packedSfixed32_ = other.packedSfixed32_.Clone(); + packedSfixed64_ = other.packedSfixed64_.Clone(); + packedFloat_ = other.packedFloat_.Clone(); + packedDouble_ = other.packedDouble_.Clone(); + packedBool_ = other.packedBool_.Clone(); + packedNestedEnum_ = other.packedNestedEnum_.Clone(); + unpackedInt32_ = other.unpackedInt32_.Clone(); + unpackedInt64_ = other.unpackedInt64_.Clone(); + unpackedUint32_ = other.unpackedUint32_.Clone(); + unpackedUint64_ = other.unpackedUint64_.Clone(); + unpackedSint32_ = other.unpackedSint32_.Clone(); + unpackedSint64_ = other.unpackedSint64_.Clone(); + unpackedFixed32_ = other.unpackedFixed32_.Clone(); + unpackedFixed64_ = other.unpackedFixed64_.Clone(); + unpackedSfixed32_ = other.unpackedSfixed32_.Clone(); + unpackedSfixed64_ = other.unpackedSfixed64_.Clone(); + unpackedFloat_ = other.unpackedFloat_.Clone(); + unpackedDouble_ = other.unpackedDouble_.Clone(); + unpackedBool_ = other.unpackedBool_.Clone(); + unpackedNestedEnum_ = other.unpackedNestedEnum_.Clone(); + mapInt32Int32_ = other.mapInt32Int32_.Clone(); + mapInt64Int64_ = other.mapInt64Int64_.Clone(); + mapUint32Uint32_ = other.mapUint32Uint32_.Clone(); + mapUint64Uint64_ = other.mapUint64Uint64_.Clone(); + mapSint32Sint32_ = other.mapSint32Sint32_.Clone(); + mapSint64Sint64_ = other.mapSint64Sint64_.Clone(); + mapFixed32Fixed32_ = other.mapFixed32Fixed32_.Clone(); + mapFixed64Fixed64_ = other.mapFixed64Fixed64_.Clone(); + mapSfixed32Sfixed32_ = other.mapSfixed32Sfixed32_.Clone(); + mapSfixed64Sfixed64_ = other.mapSfixed64Sfixed64_.Clone(); + mapInt32Float_ = other.mapInt32Float_.Clone(); + mapInt32Double_ = other.mapInt32Double_.Clone(); + mapBoolBool_ = other.mapBoolBool_.Clone(); + mapStringString_ = other.mapStringString_.Clone(); + mapStringBytes_ = other.mapStringBytes_.Clone(); + mapStringNestedMessage_ = other.mapStringNestedMessage_.Clone(); + mapStringForeignMessage_ = other.mapStringForeignMessage_.Clone(); + mapStringNestedEnum_ = other.mapStringNestedEnum_.Clone(); + mapStringForeignEnum_ = other.mapStringForeignEnum_.Clone(); + OptionalBoolWrapper = other.OptionalBoolWrapper; + OptionalInt32Wrapper = other.OptionalInt32Wrapper; + OptionalInt64Wrapper = other.OptionalInt64Wrapper; + OptionalUint32Wrapper = other.OptionalUint32Wrapper; + OptionalUint64Wrapper = other.OptionalUint64Wrapper; + OptionalFloatWrapper = other.OptionalFloatWrapper; + OptionalDoubleWrapper = other.OptionalDoubleWrapper; + OptionalStringWrapper = other.OptionalStringWrapper; + OptionalBytesWrapper = other.OptionalBytesWrapper; + repeatedBoolWrapper_ = other.repeatedBoolWrapper_.Clone(); + repeatedInt32Wrapper_ = other.repeatedInt32Wrapper_.Clone(); + repeatedInt64Wrapper_ = other.repeatedInt64Wrapper_.Clone(); + repeatedUint32Wrapper_ = other.repeatedUint32Wrapper_.Clone(); + repeatedUint64Wrapper_ = other.repeatedUint64Wrapper_.Clone(); + repeatedFloatWrapper_ = other.repeatedFloatWrapper_.Clone(); + repeatedDoubleWrapper_ = other.repeatedDoubleWrapper_.Clone(); + repeatedStringWrapper_ = other.repeatedStringWrapper_.Clone(); + repeatedBytesWrapper_ = other.repeatedBytesWrapper_.Clone(); + optionalDuration_ = other.optionalDuration_ != null ? other.optionalDuration_.Clone() : null; + optionalTimestamp_ = other.optionalTimestamp_ != null ? other.optionalTimestamp_.Clone() : null; + optionalFieldMask_ = other.optionalFieldMask_ != null ? other.optionalFieldMask_.Clone() : null; + optionalStruct_ = other.optionalStruct_ != null ? other.optionalStruct_.Clone() : null; + optionalAny_ = other.optionalAny_ != null ? other.optionalAny_.Clone() : null; + optionalValue_ = other.optionalValue_ != null ? other.optionalValue_.Clone() : null; + optionalNullValue_ = other.optionalNullValue_; + repeatedDuration_ = other.repeatedDuration_.Clone(); + repeatedTimestamp_ = other.repeatedTimestamp_.Clone(); + repeatedFieldmask_ = other.repeatedFieldmask_.Clone(); + repeatedStruct_ = other.repeatedStruct_.Clone(); + repeatedAny_ = other.repeatedAny_.Clone(); + repeatedValue_ = other.repeatedValue_.Clone(); + repeatedListValue_ = other.repeatedListValue_.Clone(); + fieldname1_ = other.fieldname1_; + fieldName2_ = other.fieldName2_; + FieldName3_ = other.FieldName3_; + fieldName4_ = other.fieldName4_; + field0Name5_ = other.field0Name5_; + field0Name6_ = other.field0Name6_; + fieldName7_ = other.fieldName7_; + fieldName8_ = other.fieldName8_; + fieldName9_ = other.fieldName9_; + fieldName10_ = other.fieldName10_; + fIELDNAME11_ = other.fIELDNAME11_; + fIELDName12_ = other.fIELDName12_; + FieldName13_ = other.FieldName13_; + FieldName14_ = other.FieldName14_; + fieldName15_ = other.fieldName15_; + fieldName16_ = other.fieldName16_; + fieldName17_ = other.fieldName17_; + fieldName18_ = other.fieldName18_; + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: + OneofUint32 = other.OneofUint32; + break; + case OneofFieldOneofCase.OneofNestedMessage: + OneofNestedMessage = other.OneofNestedMessage.Clone(); + break; + case OneofFieldOneofCase.OneofString: + OneofString = other.OneofString; + break; + case OneofFieldOneofCase.OneofBytes: + OneofBytes = other.OneofBytes; + break; + case OneofFieldOneofCase.OneofBool: + OneofBool = other.OneofBool; + break; + case OneofFieldOneofCase.OneofUint64: + OneofUint64 = other.OneofUint64; + break; + case OneofFieldOneofCase.OneofFloat: + OneofFloat = other.OneofFloat; + break; + case OneofFieldOneofCase.OneofDouble: + OneofDouble = other.OneofDouble; + break; + case OneofFieldOneofCase.OneofEnum: + OneofEnum = other.OneofEnum; + break; + case OneofFieldOneofCase.OneofNullValue: + OneofNullValue = other.OneofNullValue; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllTypesProto3 Clone() { + return new TestAllTypesProto3(this); + } + + /// Field number for the "optional_int32" field. + public const int OptionalInt32FieldNumber = 1; + private int optionalInt32_; + /// + /// Singular + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalInt32 { + get { return optionalInt32_; } + set { + optionalInt32_ = value; + } + } + + /// Field number for the "optional_int64" field. + public const int OptionalInt64FieldNumber = 2; + private long optionalInt64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalInt64 { + get { return optionalInt64_; } + set { + optionalInt64_ = value; + } + } + + /// Field number for the "optional_uint32" field. + public const int OptionalUint32FieldNumber = 3; + private uint optionalUint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OptionalUint32 { + get { return optionalUint32_; } + set { + optionalUint32_ = value; + } + } + + /// Field number for the "optional_uint64" field. + public const int OptionalUint64FieldNumber = 4; + private ulong optionalUint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong OptionalUint64 { + get { return optionalUint64_; } + set { + optionalUint64_ = value; + } + } + + /// Field number for the "optional_sint32" field. + public const int OptionalSint32FieldNumber = 5; + private int optionalSint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalSint32 { + get { return optionalSint32_; } + set { + optionalSint32_ = value; + } + } + + /// Field number for the "optional_sint64" field. + public const int OptionalSint64FieldNumber = 6; + private long optionalSint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalSint64 { + get { return optionalSint64_; } + set { + optionalSint64_ = value; + } + } + + /// Field number for the "optional_fixed32" field. + public const int OptionalFixed32FieldNumber = 7; + private uint optionalFixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OptionalFixed32 { + get { return optionalFixed32_; } + set { + optionalFixed32_ = value; + } + } + + /// Field number for the "optional_fixed64" field. + public const int OptionalFixed64FieldNumber = 8; + private ulong optionalFixed64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong OptionalFixed64 { + get { return optionalFixed64_; } + set { + optionalFixed64_ = value; + } + } + + /// Field number for the "optional_sfixed32" field. + public const int OptionalSfixed32FieldNumber = 9; + private int optionalSfixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalSfixed32 { + get { return optionalSfixed32_; } + set { + optionalSfixed32_ = value; + } + } + + /// Field number for the "optional_sfixed64" field. + public const int OptionalSfixed64FieldNumber = 10; + private long optionalSfixed64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalSfixed64 { + get { return optionalSfixed64_; } + set { + optionalSfixed64_ = value; + } + } + + /// Field number for the "optional_float" field. + public const int OptionalFloatFieldNumber = 11; + private float optionalFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float OptionalFloat { + get { return optionalFloat_; } + set { + optionalFloat_ = value; + } + } + + /// Field number for the "optional_double" field. + public const int OptionalDoubleFieldNumber = 12; + private double optionalDouble_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double OptionalDouble { + get { return optionalDouble_; } + set { + optionalDouble_ = value; + } + } + + /// Field number for the "optional_bool" field. + public const int OptionalBoolFieldNumber = 13; + private bool optionalBool_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool OptionalBool { + get { return optionalBool_; } + set { + optionalBool_ = value; + } + } + + /// Field number for the "optional_string" field. + public const int OptionalStringFieldNumber = 14; + private string optionalString_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalString { + get { return optionalString_; } + set { + optionalString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "optional_bytes" field. + public const int OptionalBytesFieldNumber = 15; + private pb::ByteString optionalBytes_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString OptionalBytes { + get { return optionalBytes_; } + set { + optionalBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "optional_nested_message" field. + public const int OptionalNestedMessageFieldNumber = 18; + private global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage optionalNestedMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage OptionalNestedMessage { + get { return optionalNestedMessage_; } + set { + optionalNestedMessage_ = value; + } + } + + /// Field number for the "optional_foreign_message" field. + public const int OptionalForeignMessageFieldNumber = 19; + private global::ProtobufTestMessages.Proto3.ForeignMessage optionalForeignMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto3.ForeignMessage OptionalForeignMessage { + get { return optionalForeignMessage_; } + set { + optionalForeignMessage_ = value; + } + } + + /// Field number for the "optional_nested_enum" field. + public const int OptionalNestedEnumFieldNumber = 21; + private global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum optionalNestedEnum_ = global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum.Foo; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum OptionalNestedEnum { + get { return optionalNestedEnum_; } + set { + optionalNestedEnum_ = value; + } + } + + /// Field number for the "optional_foreign_enum" field. + public const int OptionalForeignEnumFieldNumber = 22; + private global::ProtobufTestMessages.Proto3.ForeignEnum optionalForeignEnum_ = global::ProtobufTestMessages.Proto3.ForeignEnum.ForeignFoo; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto3.ForeignEnum OptionalForeignEnum { + get { return optionalForeignEnum_; } + set { + optionalForeignEnum_ = value; + } + } + + /// Field number for the "optional_aliased_enum" field. + public const int OptionalAliasedEnumFieldNumber = 23; + private global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum optionalAliasedEnum_ = global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum.AliasFoo; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum OptionalAliasedEnum { + get { return optionalAliasedEnum_; } + set { + optionalAliasedEnum_ = value; + } + } + + /// Field number for the "optional_string_piece" field. + public const int OptionalStringPieceFieldNumber = 24; + private string optionalStringPiece_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalStringPiece { + get { return optionalStringPiece_; } + set { + optionalStringPiece_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "optional_cord" field. + public const int OptionalCordFieldNumber = 25; + private string optionalCord_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalCord { + get { return optionalCord_; } + set { + optionalCord_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "recursive_message" field. + public const int RecursiveMessageFieldNumber = 27; + private global::ProtobufTestMessages.Proto3.TestAllTypesProto3 recursiveMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto3.TestAllTypesProto3 RecursiveMessage { + get { return recursiveMessage_; } + set { + recursiveMessage_ = value; + } + } + + /// Field number for the "repeated_int32" field. + public const int RepeatedInt32FieldNumber = 31; + private static readonly pb::FieldCodec _repeated_repeatedInt32_codec + = pb::FieldCodec.ForInt32(250); + private readonly pbc::RepeatedField repeatedInt32_ = new pbc::RepeatedField(); + /// + /// Repeated + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt32 { + get { return repeatedInt32_; } + } + + /// Field number for the "repeated_int64" field. + public const int RepeatedInt64FieldNumber = 32; + private static readonly pb::FieldCodec _repeated_repeatedInt64_codec + = pb::FieldCodec.ForInt64(258); + private readonly pbc::RepeatedField repeatedInt64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt64 { + get { return repeatedInt64_; } + } + + /// Field number for the "repeated_uint32" field. + public const int RepeatedUint32FieldNumber = 33; + private static readonly pb::FieldCodec _repeated_repeatedUint32_codec + = pb::FieldCodec.ForUInt32(266); + private readonly pbc::RepeatedField repeatedUint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedUint32 { + get { return repeatedUint32_; } + } + + /// Field number for the "repeated_uint64" field. + public const int RepeatedUint64FieldNumber = 34; + private static readonly pb::FieldCodec _repeated_repeatedUint64_codec + = pb::FieldCodec.ForUInt64(274); + private readonly pbc::RepeatedField repeatedUint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedUint64 { + get { return repeatedUint64_; } + } + + /// Field number for the "repeated_sint32" field. + public const int RepeatedSint32FieldNumber = 35; + private static readonly pb::FieldCodec _repeated_repeatedSint32_codec + = pb::FieldCodec.ForSInt32(282); + private readonly pbc::RepeatedField repeatedSint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSint32 { + get { return repeatedSint32_; } + } + + /// Field number for the "repeated_sint64" field. + public const int RepeatedSint64FieldNumber = 36; + private static readonly pb::FieldCodec _repeated_repeatedSint64_codec + = pb::FieldCodec.ForSInt64(290); + private readonly pbc::RepeatedField repeatedSint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSint64 { + get { return repeatedSint64_; } + } + + /// Field number for the "repeated_fixed32" field. + public const int RepeatedFixed32FieldNumber = 37; + private static readonly pb::FieldCodec _repeated_repeatedFixed32_codec + = pb::FieldCodec.ForFixed32(298); + private readonly pbc::RepeatedField repeatedFixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFixed32 { + get { return repeatedFixed32_; } + } + + /// Field number for the "repeated_fixed64" field. + public const int RepeatedFixed64FieldNumber = 38; + private static readonly pb::FieldCodec _repeated_repeatedFixed64_codec + = pb::FieldCodec.ForFixed64(306); + private readonly pbc::RepeatedField repeatedFixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFixed64 { + get { return repeatedFixed64_; } + } + + /// Field number for the "repeated_sfixed32" field. + public const int RepeatedSfixed32FieldNumber = 39; + private static readonly pb::FieldCodec _repeated_repeatedSfixed32_codec + = pb::FieldCodec.ForSFixed32(314); + private readonly pbc::RepeatedField repeatedSfixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSfixed32 { + get { return repeatedSfixed32_; } + } + + /// Field number for the "repeated_sfixed64" field. + public const int RepeatedSfixed64FieldNumber = 40; + private static readonly pb::FieldCodec _repeated_repeatedSfixed64_codec + = pb::FieldCodec.ForSFixed64(322); + private readonly pbc::RepeatedField repeatedSfixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSfixed64 { + get { return repeatedSfixed64_; } + } + + /// Field number for the "repeated_float" field. + public const int RepeatedFloatFieldNumber = 41; + private static readonly pb::FieldCodec _repeated_repeatedFloat_codec + = pb::FieldCodec.ForFloat(330); + private readonly pbc::RepeatedField repeatedFloat_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFloat { + get { return repeatedFloat_; } + } + + /// Field number for the "repeated_double" field. + public const int RepeatedDoubleFieldNumber = 42; + private static readonly pb::FieldCodec _repeated_repeatedDouble_codec + = pb::FieldCodec.ForDouble(338); + private readonly pbc::RepeatedField repeatedDouble_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedDouble { + get { return repeatedDouble_; } + } + + /// Field number for the "repeated_bool" field. + public const int RepeatedBoolFieldNumber = 43; + private static readonly pb::FieldCodec _repeated_repeatedBool_codec + = pb::FieldCodec.ForBool(346); + private readonly pbc::RepeatedField repeatedBool_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedBool { + get { return repeatedBool_; } + } + + /// Field number for the "repeated_string" field. + public const int RepeatedStringFieldNumber = 44; + private static readonly pb::FieldCodec _repeated_repeatedString_codec + = pb::FieldCodec.ForString(354); + private readonly pbc::RepeatedField repeatedString_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedString { + get { return repeatedString_; } + } + + /// Field number for the "repeated_bytes" field. + public const int RepeatedBytesFieldNumber = 45; + private static readonly pb::FieldCodec _repeated_repeatedBytes_codec + = pb::FieldCodec.ForBytes(362); + private readonly pbc::RepeatedField repeatedBytes_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedBytes { + get { return repeatedBytes_; } + } + + /// Field number for the "repeated_nested_message" field. + public const int RepeatedNestedMessageFieldNumber = 48; + private static readonly pb::FieldCodec _repeated_repeatedNestedMessage_codec + = pb::FieldCodec.ForMessage(386, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser); + private readonly pbc::RepeatedField repeatedNestedMessage_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedNestedMessage { + get { return repeatedNestedMessage_; } + } + + /// Field number for the "repeated_foreign_message" field. + public const int RepeatedForeignMessageFieldNumber = 49; + private static readonly pb::FieldCodec _repeated_repeatedForeignMessage_codec + = pb::FieldCodec.ForMessage(394, global::ProtobufTestMessages.Proto3.ForeignMessage.Parser); + private readonly pbc::RepeatedField repeatedForeignMessage_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedForeignMessage { + get { return repeatedForeignMessage_; } + } + + /// Field number for the "repeated_nested_enum" field. + public const int RepeatedNestedEnumFieldNumber = 51; + private static readonly pb::FieldCodec _repeated_repeatedNestedEnum_codec + = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) x); + private readonly pbc::RepeatedField repeatedNestedEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedNestedEnum { + get { return repeatedNestedEnum_; } + } + + /// Field number for the "repeated_foreign_enum" field. + public const int RepeatedForeignEnumFieldNumber = 52; + private static readonly pb::FieldCodec _repeated_repeatedForeignEnum_codec + = pb::FieldCodec.ForEnum(418, x => (int) x, x => (global::ProtobufTestMessages.Proto3.ForeignEnum) x); + private readonly pbc::RepeatedField repeatedForeignEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedForeignEnum { + get { return repeatedForeignEnum_; } + } + + /// Field number for the "repeated_string_piece" field. + public const int RepeatedStringPieceFieldNumber = 54; + private static readonly pb::FieldCodec _repeated_repeatedStringPiece_codec + = pb::FieldCodec.ForString(434); + private readonly pbc::RepeatedField repeatedStringPiece_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedStringPiece { + get { return repeatedStringPiece_; } + } + + /// Field number for the "repeated_cord" field. + public const int RepeatedCordFieldNumber = 55; + private static readonly pb::FieldCodec _repeated_repeatedCord_codec + = pb::FieldCodec.ForString(442); + private readonly pbc::RepeatedField repeatedCord_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedCord { + get { return repeatedCord_; } + } + + /// Field number for the "packed_int32" field. + public const int PackedInt32FieldNumber = 75; + private static readonly pb::FieldCodec _repeated_packedInt32_codec + = pb::FieldCodec.ForInt32(602); + private readonly pbc::RepeatedField packedInt32_ = new pbc::RepeatedField(); + /// + /// Packed + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedInt32 { + get { return packedInt32_; } + } + + /// Field number for the "packed_int64" field. + public const int PackedInt64FieldNumber = 76; + private static readonly pb::FieldCodec _repeated_packedInt64_codec + = pb::FieldCodec.ForInt64(610); + private readonly pbc::RepeatedField packedInt64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedInt64 { + get { return packedInt64_; } + } + + /// Field number for the "packed_uint32" field. + public const int PackedUint32FieldNumber = 77; + private static readonly pb::FieldCodec _repeated_packedUint32_codec + = pb::FieldCodec.ForUInt32(618); + private readonly pbc::RepeatedField packedUint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedUint32 { + get { return packedUint32_; } + } + + /// Field number for the "packed_uint64" field. + public const int PackedUint64FieldNumber = 78; + private static readonly pb::FieldCodec _repeated_packedUint64_codec + = pb::FieldCodec.ForUInt64(626); + private readonly pbc::RepeatedField packedUint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedUint64 { + get { return packedUint64_; } + } + + /// Field number for the "packed_sint32" field. + public const int PackedSint32FieldNumber = 79; + private static readonly pb::FieldCodec _repeated_packedSint32_codec + = pb::FieldCodec.ForSInt32(634); + private readonly pbc::RepeatedField packedSint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSint32 { + get { return packedSint32_; } + } + + /// Field number for the "packed_sint64" field. + public const int PackedSint64FieldNumber = 80; + private static readonly pb::FieldCodec _repeated_packedSint64_codec + = pb::FieldCodec.ForSInt64(642); + private readonly pbc::RepeatedField packedSint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSint64 { + get { return packedSint64_; } + } + + /// Field number for the "packed_fixed32" field. + public const int PackedFixed32FieldNumber = 81; + private static readonly pb::FieldCodec _repeated_packedFixed32_codec + = pb::FieldCodec.ForFixed32(650); + private readonly pbc::RepeatedField packedFixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedFixed32 { + get { return packedFixed32_; } + } + + /// Field number for the "packed_fixed64" field. + public const int PackedFixed64FieldNumber = 82; + private static readonly pb::FieldCodec _repeated_packedFixed64_codec + = pb::FieldCodec.ForFixed64(658); + private readonly pbc::RepeatedField packedFixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedFixed64 { + get { return packedFixed64_; } + } + + /// Field number for the "packed_sfixed32" field. + public const int PackedSfixed32FieldNumber = 83; + private static readonly pb::FieldCodec _repeated_packedSfixed32_codec + = pb::FieldCodec.ForSFixed32(666); + private readonly pbc::RepeatedField packedSfixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSfixed32 { + get { return packedSfixed32_; } + } + + /// Field number for the "packed_sfixed64" field. + public const int PackedSfixed64FieldNumber = 84; + private static readonly pb::FieldCodec _repeated_packedSfixed64_codec + = pb::FieldCodec.ForSFixed64(674); + private readonly pbc::RepeatedField packedSfixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSfixed64 { + get { return packedSfixed64_; } + } + + /// Field number for the "packed_float" field. + public const int PackedFloatFieldNumber = 85; + private static readonly pb::FieldCodec _repeated_packedFloat_codec + = pb::FieldCodec.ForFloat(682); + private readonly pbc::RepeatedField packedFloat_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedFloat { + get { return packedFloat_; } + } + + /// Field number for the "packed_double" field. + public const int PackedDoubleFieldNumber = 86; + private static readonly pb::FieldCodec _repeated_packedDouble_codec + = pb::FieldCodec.ForDouble(690); + private readonly pbc::RepeatedField packedDouble_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedDouble { + get { return packedDouble_; } + } + + /// Field number for the "packed_bool" field. + public const int PackedBoolFieldNumber = 87; + private static readonly pb::FieldCodec _repeated_packedBool_codec + = pb::FieldCodec.ForBool(698); + private readonly pbc::RepeatedField packedBool_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedBool { + get { return packedBool_; } + } + + /// Field number for the "packed_nested_enum" field. + public const int PackedNestedEnumFieldNumber = 88; + private static readonly pb::FieldCodec _repeated_packedNestedEnum_codec + = pb::FieldCodec.ForEnum(706, x => (int) x, x => (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) x); + private readonly pbc::RepeatedField packedNestedEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedNestedEnum { + get { return packedNestedEnum_; } + } + + /// Field number for the "unpacked_int32" field. + public const int UnpackedInt32FieldNumber = 89; + private static readonly pb::FieldCodec _repeated_unpackedInt32_codec + = pb::FieldCodec.ForInt32(712); + private readonly pbc::RepeatedField unpackedInt32_ = new pbc::RepeatedField(); + /// + /// Unpacked + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedInt32 { + get { return unpackedInt32_; } + } + + /// Field number for the "unpacked_int64" field. + public const int UnpackedInt64FieldNumber = 90; + private static readonly pb::FieldCodec _repeated_unpackedInt64_codec + = pb::FieldCodec.ForInt64(720); + private readonly pbc::RepeatedField unpackedInt64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedInt64 { + get { return unpackedInt64_; } + } + + /// Field number for the "unpacked_uint32" field. + public const int UnpackedUint32FieldNumber = 91; + private static readonly pb::FieldCodec _repeated_unpackedUint32_codec + = pb::FieldCodec.ForUInt32(728); + private readonly pbc::RepeatedField unpackedUint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedUint32 { + get { return unpackedUint32_; } + } + + /// Field number for the "unpacked_uint64" field. + public const int UnpackedUint64FieldNumber = 92; + private static readonly pb::FieldCodec _repeated_unpackedUint64_codec + = pb::FieldCodec.ForUInt64(736); + private readonly pbc::RepeatedField unpackedUint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedUint64 { + get { return unpackedUint64_; } + } + + /// Field number for the "unpacked_sint32" field. + public const int UnpackedSint32FieldNumber = 93; + private static readonly pb::FieldCodec _repeated_unpackedSint32_codec + = pb::FieldCodec.ForSInt32(744); + private readonly pbc::RepeatedField unpackedSint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSint32 { + get { return unpackedSint32_; } + } + + /// Field number for the "unpacked_sint64" field. + public const int UnpackedSint64FieldNumber = 94; + private static readonly pb::FieldCodec _repeated_unpackedSint64_codec + = pb::FieldCodec.ForSInt64(752); + private readonly pbc::RepeatedField unpackedSint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSint64 { + get { return unpackedSint64_; } + } + + /// Field number for the "unpacked_fixed32" field. + public const int UnpackedFixed32FieldNumber = 95; + private static readonly pb::FieldCodec _repeated_unpackedFixed32_codec + = pb::FieldCodec.ForFixed32(765); + private readonly pbc::RepeatedField unpackedFixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedFixed32 { + get { return unpackedFixed32_; } + } + + /// Field number for the "unpacked_fixed64" field. + public const int UnpackedFixed64FieldNumber = 96; + private static readonly pb::FieldCodec _repeated_unpackedFixed64_codec + = pb::FieldCodec.ForFixed64(769); + private readonly pbc::RepeatedField unpackedFixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedFixed64 { + get { return unpackedFixed64_; } + } + + /// Field number for the "unpacked_sfixed32" field. + public const int UnpackedSfixed32FieldNumber = 97; + private static readonly pb::FieldCodec _repeated_unpackedSfixed32_codec + = pb::FieldCodec.ForSFixed32(781); + private readonly pbc::RepeatedField unpackedSfixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSfixed32 { + get { return unpackedSfixed32_; } + } + + /// Field number for the "unpacked_sfixed64" field. + public const int UnpackedSfixed64FieldNumber = 98; + private static readonly pb::FieldCodec _repeated_unpackedSfixed64_codec + = pb::FieldCodec.ForSFixed64(785); + private readonly pbc::RepeatedField unpackedSfixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSfixed64 { + get { return unpackedSfixed64_; } + } + + /// Field number for the "unpacked_float" field. + public const int UnpackedFloatFieldNumber = 99; + private static readonly pb::FieldCodec _repeated_unpackedFloat_codec + = pb::FieldCodec.ForFloat(797); + private readonly pbc::RepeatedField unpackedFloat_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedFloat { + get { return unpackedFloat_; } + } + + /// Field number for the "unpacked_double" field. + public const int UnpackedDoubleFieldNumber = 100; + private static readonly pb::FieldCodec _repeated_unpackedDouble_codec + = pb::FieldCodec.ForDouble(801); + private readonly pbc::RepeatedField unpackedDouble_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedDouble { + get { return unpackedDouble_; } + } + + /// Field number for the "unpacked_bool" field. + public const int UnpackedBoolFieldNumber = 101; + private static readonly pb::FieldCodec _repeated_unpackedBool_codec + = pb::FieldCodec.ForBool(808); + private readonly pbc::RepeatedField unpackedBool_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedBool { + get { return unpackedBool_; } + } + + /// Field number for the "unpacked_nested_enum" field. + public const int UnpackedNestedEnumFieldNumber = 102; + private static readonly pb::FieldCodec _repeated_unpackedNestedEnum_codec + = pb::FieldCodec.ForEnum(816, x => (int) x, x => (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) x); + private readonly pbc::RepeatedField unpackedNestedEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedNestedEnum { + get { return unpackedNestedEnum_; } + } + + /// Field number for the "map_int32_int32" field. + public const int MapInt32Int32FieldNumber = 56; + private static readonly pbc::MapField.Codec _map_mapInt32Int32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForInt32(16, 0), 450); + private readonly pbc::MapField mapInt32Int32_ = new pbc::MapField(); + /// + /// Map + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Int32 { + get { return mapInt32Int32_; } + } + + /// Field number for the "map_int64_int64" field. + public const int MapInt64Int64FieldNumber = 57; + private static readonly pbc::MapField.Codec _map_mapInt64Int64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt64(8, 0L), pb::FieldCodec.ForInt64(16, 0L), 458); + private readonly pbc::MapField mapInt64Int64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt64Int64 { + get { return mapInt64Int64_; } + } + + /// Field number for the "map_uint32_uint32" field. + public const int MapUint32Uint32FieldNumber = 58; + private static readonly pbc::MapField.Codec _map_mapUint32Uint32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForUInt32(8, 0), pb::FieldCodec.ForUInt32(16, 0), 466); + private readonly pbc::MapField mapUint32Uint32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapUint32Uint32 { + get { return mapUint32Uint32_; } + } + + /// Field number for the "map_uint64_uint64" field. + public const int MapUint64Uint64FieldNumber = 59; + private static readonly pbc::MapField.Codec _map_mapUint64Uint64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForUInt64(8, 0UL), pb::FieldCodec.ForUInt64(16, 0UL), 474); + private readonly pbc::MapField mapUint64Uint64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapUint64Uint64 { + get { return mapUint64Uint64_; } + } + + /// Field number for the "map_sint32_sint32" field. + public const int MapSint32Sint32FieldNumber = 60; + private static readonly pbc::MapField.Codec _map_mapSint32Sint32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSInt32(8, 0), pb::FieldCodec.ForSInt32(16, 0), 482); + private readonly pbc::MapField mapSint32Sint32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSint32Sint32 { + get { return mapSint32Sint32_; } + } + + /// Field number for the "map_sint64_sint64" field. + public const int MapSint64Sint64FieldNumber = 61; + private static readonly pbc::MapField.Codec _map_mapSint64Sint64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSInt64(8, 0L), pb::FieldCodec.ForSInt64(16, 0L), 490); + private readonly pbc::MapField mapSint64Sint64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSint64Sint64 { + get { return mapSint64Sint64_; } + } + + /// Field number for the "map_fixed32_fixed32" field. + public const int MapFixed32Fixed32FieldNumber = 62; + private static readonly pbc::MapField.Codec _map_mapFixed32Fixed32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForFixed32(13, 0), pb::FieldCodec.ForFixed32(21, 0), 498); + private readonly pbc::MapField mapFixed32Fixed32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapFixed32Fixed32 { + get { return mapFixed32Fixed32_; } + } + + /// Field number for the "map_fixed64_fixed64" field. + public const int MapFixed64Fixed64FieldNumber = 63; + private static readonly pbc::MapField.Codec _map_mapFixed64Fixed64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForFixed64(9, 0UL), pb::FieldCodec.ForFixed64(17, 0UL), 506); + private readonly pbc::MapField mapFixed64Fixed64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapFixed64Fixed64 { + get { return mapFixed64Fixed64_; } + } + + /// Field number for the "map_sfixed32_sfixed32" field. + public const int MapSfixed32Sfixed32FieldNumber = 64; + private static readonly pbc::MapField.Codec _map_mapSfixed32Sfixed32_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSFixed32(13, 0), pb::FieldCodec.ForSFixed32(21, 0), 514); + private readonly pbc::MapField mapSfixed32Sfixed32_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSfixed32Sfixed32 { + get { return mapSfixed32Sfixed32_; } + } + + /// Field number for the "map_sfixed64_sfixed64" field. + public const int MapSfixed64Sfixed64FieldNumber = 65; + private static readonly pbc::MapField.Codec _map_mapSfixed64Sfixed64_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForSFixed64(9, 0L), pb::FieldCodec.ForSFixed64(17, 0L), 522); + private readonly pbc::MapField mapSfixed64Sfixed64_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapSfixed64Sfixed64 { + get { return mapSfixed64Sfixed64_; } + } + + /// Field number for the "map_int32_float" field. + public const int MapInt32FloatFieldNumber = 66; + private static readonly pbc::MapField.Codec _map_mapInt32Float_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForFloat(21, 0F), 530); + private readonly pbc::MapField mapInt32Float_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Float { + get { return mapInt32Float_; } + } + + /// Field number for the "map_int32_double" field. + public const int MapInt32DoubleFieldNumber = 67; + private static readonly pbc::MapField.Codec _map_mapInt32Double_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForDouble(17, 0D), 538); + private readonly pbc::MapField mapInt32Double_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapInt32Double { + get { return mapInt32Double_; } + } + + /// Field number for the "map_bool_bool" field. + public const int MapBoolBoolFieldNumber = 68; + private static readonly pbc::MapField.Codec _map_mapBoolBool_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForBool(8, false), pb::FieldCodec.ForBool(16, false), 546); + private readonly pbc::MapField mapBoolBool_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapBoolBool { + get { return mapBoolBool_; } + } + + /// Field number for the "map_string_string" field. + public const int MapStringStringFieldNumber = 69; + private static readonly pbc::MapField.Codec _map_mapStringString_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForString(18, ""), 554); + private readonly pbc::MapField mapStringString_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapStringString { + get { return mapStringString_; } + } + + /// Field number for the "map_string_bytes" field. + public const int MapStringBytesFieldNumber = 70; + private static readonly pbc::MapField.Codec _map_mapStringBytes_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForBytes(18, pb::ByteString.Empty), 562); + private readonly pbc::MapField mapStringBytes_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapStringBytes { + get { return mapStringBytes_; } + } + + /// Field number for the "map_string_nested_message" field. + public const int MapStringNestedMessageFieldNumber = 71; + private static readonly pbc::MapField.Codec _map_mapStringNestedMessage_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForMessage(18, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser), 570); + private readonly pbc::MapField mapStringNestedMessage_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapStringNestedMessage { + get { return mapStringNestedMessage_; } + } + + /// Field number for the "map_string_foreign_message" field. + public const int MapStringForeignMessageFieldNumber = 72; + private static readonly pbc::MapField.Codec _map_mapStringForeignMessage_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForMessage(18, global::ProtobufTestMessages.Proto3.ForeignMessage.Parser), 578); + private readonly pbc::MapField mapStringForeignMessage_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapStringForeignMessage { + get { return mapStringForeignMessage_; } + } + + /// Field number for the "map_string_nested_enum" field. + public const int MapStringNestedEnumFieldNumber = 73; + private static readonly pbc::MapField.Codec _map_mapStringNestedEnum_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) x, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum.Foo), 586); + private readonly pbc::MapField mapStringNestedEnum_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapStringNestedEnum { + get { return mapStringNestedEnum_; } + } + + /// Field number for the "map_string_foreign_enum" field. + public const int MapStringForeignEnumFieldNumber = 74; + private static readonly pbc::MapField.Codec _map_mapStringForeignEnum_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::ProtobufTestMessages.Proto3.ForeignEnum) x, global::ProtobufTestMessages.Proto3.ForeignEnum.ForeignFoo), 594); + private readonly pbc::MapField mapStringForeignEnum_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField MapStringForeignEnum { + get { return mapStringForeignEnum_; } + } + + /// Field number for the "oneof_uint32" field. + public const int OneofUint32FieldNumber = 111; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OneofUint32 { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; + } + } + + /// Field number for the "oneof_nested_message" field. + public const int OneofNestedMessageFieldNumber = 112; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage OneofNestedMessage { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage) oneofField_ : null; } + set { + oneofField_ = value; + oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage; + } + } + + /// Field number for the "oneof_string" field. + public const int OneofStringFieldNumber = 113; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OneofString { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; } + set { + oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + oneofFieldCase_ = OneofFieldOneofCase.OneofString; + } + } + + /// Field number for the "oneof_bytes" field. + public const int OneofBytesFieldNumber = 114; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString OneofBytes { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; } + set { + oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; + } + } + + /// Field number for the "oneof_bool" field. + public const int OneofBoolFieldNumber = 115; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool OneofBool { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBool ? (bool) oneofField_ : false; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofBool; + } + } + + /// Field number for the "oneof_uint64" field. + public const int OneofUint64FieldNumber = 116; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong OneofUint64 { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint64 ? (ulong) oneofField_ : 0UL; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofUint64; + } + } + + /// Field number for the "oneof_float" field. + public const int OneofFloatFieldNumber = 117; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float OneofFloat { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofFloat ? (float) oneofField_ : 0F; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofFloat; + } + } + + /// Field number for the "oneof_double" field. + public const int OneofDoubleFieldNumber = 118; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double OneofDouble { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofDouble ? (double) oneofField_ : 0D; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofDouble; + } + } + + /// Field number for the "oneof_enum" field. + public const int OneofEnumFieldNumber = 119; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum OneofEnum { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofEnum ? (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) oneofField_ : global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum.Foo; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofEnum; + } + } + + /// Field number for the "oneof_null_value" field. + public const int OneofNullValueFieldNumber = 120; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.NullValue OneofNullValue { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue ? (global::Google.Protobuf.WellKnownTypes.NullValue) oneofField_ : global::Google.Protobuf.WellKnownTypes.NullValue.NullValue; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofNullValue; + } + } + + /// Field number for the "optional_bool_wrapper" field. + public const int OptionalBoolWrapperFieldNumber = 201; + private static readonly pb::FieldCodec _single_optionalBoolWrapper_codec = pb::FieldCodec.ForStructWrapper(1610); + private bool? optionalBoolWrapper_; + /// + /// Well-known types + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool? OptionalBoolWrapper { + get { return optionalBoolWrapper_; } + set { + optionalBoolWrapper_ = value; + } + } + + + /// Field number for the "optional_int32_wrapper" field. + public const int OptionalInt32WrapperFieldNumber = 202; + private static readonly pb::FieldCodec _single_optionalInt32Wrapper_codec = pb::FieldCodec.ForStructWrapper(1618); + private int? optionalInt32Wrapper_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int? OptionalInt32Wrapper { + get { return optionalInt32Wrapper_; } + set { + optionalInt32Wrapper_ = value; + } + } + + + /// Field number for the "optional_int64_wrapper" field. + public const int OptionalInt64WrapperFieldNumber = 203; + private static readonly pb::FieldCodec _single_optionalInt64Wrapper_codec = pb::FieldCodec.ForStructWrapper(1626); + private long? optionalInt64Wrapper_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long? OptionalInt64Wrapper { + get { return optionalInt64Wrapper_; } + set { + optionalInt64Wrapper_ = value; + } + } + + + /// Field number for the "optional_uint32_wrapper" field. + public const int OptionalUint32WrapperFieldNumber = 204; + private static readonly pb::FieldCodec _single_optionalUint32Wrapper_codec = pb::FieldCodec.ForStructWrapper(1634); + private uint? optionalUint32Wrapper_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint? OptionalUint32Wrapper { + get { return optionalUint32Wrapper_; } + set { + optionalUint32Wrapper_ = value; + } + } + + + /// Field number for the "optional_uint64_wrapper" field. + public const int OptionalUint64WrapperFieldNumber = 205; + private static readonly pb::FieldCodec _single_optionalUint64Wrapper_codec = pb::FieldCodec.ForStructWrapper(1642); + private ulong? optionalUint64Wrapper_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong? OptionalUint64Wrapper { + get { return optionalUint64Wrapper_; } + set { + optionalUint64Wrapper_ = value; + } + } + + + /// Field number for the "optional_float_wrapper" field. + public const int OptionalFloatWrapperFieldNumber = 206; + private static readonly pb::FieldCodec _single_optionalFloatWrapper_codec = pb::FieldCodec.ForStructWrapper(1650); + private float? optionalFloatWrapper_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float? OptionalFloatWrapper { + get { return optionalFloatWrapper_; } + set { + optionalFloatWrapper_ = value; + } + } + + + /// Field number for the "optional_double_wrapper" field. + public const int OptionalDoubleWrapperFieldNumber = 207; + private static readonly pb::FieldCodec _single_optionalDoubleWrapper_codec = pb::FieldCodec.ForStructWrapper(1658); + private double? optionalDoubleWrapper_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double? OptionalDoubleWrapper { + get { return optionalDoubleWrapper_; } + set { + optionalDoubleWrapper_ = value; + } + } + + + /// Field number for the "optional_string_wrapper" field. + public const int OptionalStringWrapperFieldNumber = 208; + private static readonly pb::FieldCodec _single_optionalStringWrapper_codec = pb::FieldCodec.ForClassWrapper(1666); + private string optionalStringWrapper_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalStringWrapper { + get { return optionalStringWrapper_; } + set { + optionalStringWrapper_ = value; + } + } + + + /// Field number for the "optional_bytes_wrapper" field. + public const int OptionalBytesWrapperFieldNumber = 209; + private static readonly pb::FieldCodec _single_optionalBytesWrapper_codec = pb::FieldCodec.ForClassWrapper(1674); + private pb::ByteString optionalBytesWrapper_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString OptionalBytesWrapper { + get { return optionalBytesWrapper_; } + set { + optionalBytesWrapper_ = value; + } + } + + + /// Field number for the "repeated_bool_wrapper" field. + public const int RepeatedBoolWrapperFieldNumber = 211; + private static readonly pb::FieldCodec _repeated_repeatedBoolWrapper_codec + = pb::FieldCodec.ForStructWrapper(1690); + private readonly pbc::RepeatedField repeatedBoolWrapper_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedBoolWrapper { + get { return repeatedBoolWrapper_; } + } + + /// Field number for the "repeated_int32_wrapper" field. + public const int RepeatedInt32WrapperFieldNumber = 212; + private static readonly pb::FieldCodec _repeated_repeatedInt32Wrapper_codec + = pb::FieldCodec.ForStructWrapper(1698); + private readonly pbc::RepeatedField repeatedInt32Wrapper_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt32Wrapper { + get { return repeatedInt32Wrapper_; } + } + + /// Field number for the "repeated_int64_wrapper" field. + public const int RepeatedInt64WrapperFieldNumber = 213; + private static readonly pb::FieldCodec _repeated_repeatedInt64Wrapper_codec + = pb::FieldCodec.ForStructWrapper(1706); + private readonly pbc::RepeatedField repeatedInt64Wrapper_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt64Wrapper { + get { return repeatedInt64Wrapper_; } + } + + /// Field number for the "repeated_uint32_wrapper" field. + public const int RepeatedUint32WrapperFieldNumber = 214; + private static readonly pb::FieldCodec _repeated_repeatedUint32Wrapper_codec + = pb::FieldCodec.ForStructWrapper(1714); + private readonly pbc::RepeatedField repeatedUint32Wrapper_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedUint32Wrapper { + get { return repeatedUint32Wrapper_; } + } + + /// Field number for the "repeated_uint64_wrapper" field. + public const int RepeatedUint64WrapperFieldNumber = 215; + private static readonly pb::FieldCodec _repeated_repeatedUint64Wrapper_codec + = pb::FieldCodec.ForStructWrapper(1722); + private readonly pbc::RepeatedField repeatedUint64Wrapper_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedUint64Wrapper { + get { return repeatedUint64Wrapper_; } + } + + /// Field number for the "repeated_float_wrapper" field. + public const int RepeatedFloatWrapperFieldNumber = 216; + private static readonly pb::FieldCodec _repeated_repeatedFloatWrapper_codec + = pb::FieldCodec.ForStructWrapper(1730); + private readonly pbc::RepeatedField repeatedFloatWrapper_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFloatWrapper { + get { return repeatedFloatWrapper_; } + } + + /// Field number for the "repeated_double_wrapper" field. + public const int RepeatedDoubleWrapperFieldNumber = 217; + private static readonly pb::FieldCodec _repeated_repeatedDoubleWrapper_codec + = pb::FieldCodec.ForStructWrapper(1738); + private readonly pbc::RepeatedField repeatedDoubleWrapper_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedDoubleWrapper { + get { return repeatedDoubleWrapper_; } + } + + /// Field number for the "repeated_string_wrapper" field. + public const int RepeatedStringWrapperFieldNumber = 218; + private static readonly pb::FieldCodec _repeated_repeatedStringWrapper_codec + = pb::FieldCodec.ForClassWrapper(1746); + private readonly pbc::RepeatedField repeatedStringWrapper_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedStringWrapper { + get { return repeatedStringWrapper_; } + } + + /// Field number for the "repeated_bytes_wrapper" field. + public const int RepeatedBytesWrapperFieldNumber = 219; + private static readonly pb::FieldCodec _repeated_repeatedBytesWrapper_codec + = pb::FieldCodec.ForClassWrapper(1754); + private readonly pbc::RepeatedField repeatedBytesWrapper_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedBytesWrapper { + get { return repeatedBytesWrapper_; } + } + + /// Field number for the "optional_duration" field. + public const int OptionalDurationFieldNumber = 301; + private global::Google.Protobuf.WellKnownTypes.Duration optionalDuration_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.Duration OptionalDuration { + get { return optionalDuration_; } + set { + optionalDuration_ = value; + } + } + + /// Field number for the "optional_timestamp" field. + public const int OptionalTimestampFieldNumber = 302; + private global::Google.Protobuf.WellKnownTypes.Timestamp optionalTimestamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.Timestamp OptionalTimestamp { + get { return optionalTimestamp_; } + set { + optionalTimestamp_ = value; + } + } + + /// Field number for the "optional_field_mask" field. + public const int OptionalFieldMaskFieldNumber = 303; + private global::Google.Protobuf.WellKnownTypes.FieldMask optionalFieldMask_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.FieldMask OptionalFieldMask { + get { return optionalFieldMask_; } + set { + optionalFieldMask_ = value; + } + } + + /// Field number for the "optional_struct" field. + public const int OptionalStructFieldNumber = 304; + private global::Google.Protobuf.WellKnownTypes.Struct optionalStruct_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.Struct OptionalStruct { + get { return optionalStruct_; } + set { + optionalStruct_ = value; + } + } + + /// Field number for the "optional_any" field. + public const int OptionalAnyFieldNumber = 305; + private global::Google.Protobuf.WellKnownTypes.Any optionalAny_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.Any OptionalAny { + get { return optionalAny_; } + set { + optionalAny_ = value; + } + } + + /// Field number for the "optional_value" field. + public const int OptionalValueFieldNumber = 306; + private global::Google.Protobuf.WellKnownTypes.Value optionalValue_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.Value OptionalValue { + get { return optionalValue_; } + set { + optionalValue_ = value; + } + } + + /// Field number for the "optional_null_value" field. + public const int OptionalNullValueFieldNumber = 307; + private global::Google.Protobuf.WellKnownTypes.NullValue optionalNullValue_ = global::Google.Protobuf.WellKnownTypes.NullValue.NullValue; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.NullValue OptionalNullValue { + get { return optionalNullValue_; } + set { + optionalNullValue_ = value; + } + } + + /// Field number for the "repeated_duration" field. + public const int RepeatedDurationFieldNumber = 311; + private static readonly pb::FieldCodec _repeated_repeatedDuration_codec + = pb::FieldCodec.ForMessage(2490, global::Google.Protobuf.WellKnownTypes.Duration.Parser); + private readonly pbc::RepeatedField repeatedDuration_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedDuration { + get { return repeatedDuration_; } + } + + /// Field number for the "repeated_timestamp" field. + public const int RepeatedTimestampFieldNumber = 312; + private static readonly pb::FieldCodec _repeated_repeatedTimestamp_codec + = pb::FieldCodec.ForMessage(2498, global::Google.Protobuf.WellKnownTypes.Timestamp.Parser); + private readonly pbc::RepeatedField repeatedTimestamp_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedTimestamp { + get { return repeatedTimestamp_; } + } + + /// Field number for the "repeated_fieldmask" field. + public const int RepeatedFieldmaskFieldNumber = 313; + private static readonly pb::FieldCodec _repeated_repeatedFieldmask_codec + = pb::FieldCodec.ForMessage(2506, global::Google.Protobuf.WellKnownTypes.FieldMask.Parser); + private readonly pbc::RepeatedField repeatedFieldmask_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFieldmask { + get { return repeatedFieldmask_; } + } + + /// Field number for the "repeated_struct" field. + public const int RepeatedStructFieldNumber = 324; + private static readonly pb::FieldCodec _repeated_repeatedStruct_codec + = pb::FieldCodec.ForMessage(2594, global::Google.Protobuf.WellKnownTypes.Struct.Parser); + private readonly pbc::RepeatedField repeatedStruct_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedStruct { + get { return repeatedStruct_; } + } + + /// Field number for the "repeated_any" field. + public const int RepeatedAnyFieldNumber = 315; + private static readonly pb::FieldCodec _repeated_repeatedAny_codec + = pb::FieldCodec.ForMessage(2522, global::Google.Protobuf.WellKnownTypes.Any.Parser); + private readonly pbc::RepeatedField repeatedAny_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedAny { + get { return repeatedAny_; } + } + + /// Field number for the "repeated_value" field. + public const int RepeatedValueFieldNumber = 316; + private static readonly pb::FieldCodec _repeated_repeatedValue_codec + = pb::FieldCodec.ForMessage(2530, global::Google.Protobuf.WellKnownTypes.Value.Parser); + private readonly pbc::RepeatedField repeatedValue_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedValue { + get { return repeatedValue_; } + } + + /// Field number for the "repeated_list_value" field. + public const int RepeatedListValueFieldNumber = 317; + private static readonly pb::FieldCodec _repeated_repeatedListValue_codec + = pb::FieldCodec.ForMessage(2538, global::Google.Protobuf.WellKnownTypes.ListValue.Parser); + private readonly pbc::RepeatedField repeatedListValue_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedListValue { + get { return repeatedListValue_; } + } + + /// Field number for the "fieldname1" field. + public const int Fieldname1FieldNumber = 401; + private int fieldname1_; + /// + /// Test field-name-to-JSON-name convention. + /// (protobuf says names can be any valid C/C++ identifier.) + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Fieldname1 { + get { return fieldname1_; } + set { + fieldname1_ = value; + } + } + + /// Field number for the "field_name2" field. + public const int FieldName2FieldNumber = 402; + private int fieldName2_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName2 { + get { return fieldName2_; } + set { + fieldName2_ = value; + } + } + + /// Field number for the "_field_name3" field. + public const int FieldName3FieldNumber = 403; + private int FieldName3_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName3 { + get { return FieldName3_; } + set { + FieldName3_ = value; + } + } + + /// Field number for the "field__name4_" field. + public const int FieldName4FieldNumber = 404; + private int fieldName4_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName4 { + get { return fieldName4_; } + set { + fieldName4_ = value; + } + } + + /// Field number for the "field0name5" field. + public const int Field0Name5FieldNumber = 405; + private int field0Name5_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field0Name5 { + get { return field0Name5_; } + set { + field0Name5_ = value; + } + } + + /// Field number for the "field_0_name6" field. + public const int Field0Name6FieldNumber = 406; + private int field0Name6_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field0Name6 { + get { return field0Name6_; } + set { + field0Name6_ = value; + } + } + + /// Field number for the "fieldName7" field. + public const int FieldName7FieldNumber = 407; + private int fieldName7_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName7 { + get { return fieldName7_; } + set { + fieldName7_ = value; + } + } + + /// Field number for the "FieldName8" field. + public const int FieldName8FieldNumber = 408; + private int fieldName8_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName8 { + get { return fieldName8_; } + set { + fieldName8_ = value; + } + } + + /// Field number for the "field_Name9" field. + public const int FieldName9FieldNumber = 409; + private int fieldName9_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName9 { + get { return fieldName9_; } + set { + fieldName9_ = value; + } + } + + /// Field number for the "Field_Name10" field. + public const int FieldName10FieldNumber = 410; + private int fieldName10_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName10 { + get { return fieldName10_; } + set { + fieldName10_ = value; + } + } + + /// Field number for the "FIELD_NAME11" field. + public const int FIELDNAME11FieldNumber = 411; + private int fIELDNAME11_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FIELDNAME11 { + get { return fIELDNAME11_; } + set { + fIELDNAME11_ = value; + } + } + + /// Field number for the "FIELD_name12" field. + public const int FIELDName12FieldNumber = 412; + private int fIELDName12_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FIELDName12 { + get { return fIELDName12_; } + set { + fIELDName12_ = value; + } + } + + /// Field number for the "__field_name13" field. + public const int FieldName13FieldNumber = 413; + private int FieldName13_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName13 { + get { return FieldName13_; } + set { + FieldName13_ = value; + } + } + + /// Field number for the "__Field_name14" field. + public const int FieldName14FieldNumber = 414; + private int FieldName14_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName14 { + get { return FieldName14_; } + set { + FieldName14_ = value; + } + } + + /// Field number for the "field__name15" field. + public const int FieldName15FieldNumber = 415; + private int fieldName15_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName15 { + get { return fieldName15_; } + set { + fieldName15_ = value; + } + } + + /// Field number for the "field__Name16" field. + public const int FieldName16FieldNumber = 416; + private int fieldName16_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName16 { + get { return fieldName16_; } + set { + fieldName16_ = value; + } + } + + /// Field number for the "field_name17__" field. + public const int FieldName17FieldNumber = 417; + private int fieldName17_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName17 { + get { return fieldName17_; } + set { + fieldName17_ = value; + } + } + + /// Field number for the "Field_name18__" field. + public const int FieldName18FieldNumber = 418; + private int fieldName18_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName18 { + get { return fieldName18_; } + set { + fieldName18_ = value; + } + } + + private object oneofField_; + /// Enum of possible cases for the "oneof_field" oneof. + public enum OneofFieldOneofCase { + None = 0, + OneofUint32 = 111, + OneofNestedMessage = 112, + OneofString = 113, + OneofBytes = 114, + OneofBool = 115, + OneofUint64 = 116, + OneofFloat = 117, + OneofDouble = 118, + OneofEnum = 119, + OneofNullValue = 120, + } + private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneofFieldOneofCase OneofFieldCase { + get { return oneofFieldCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofField() { + oneofFieldCase_ = OneofFieldOneofCase.None; + oneofField_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestAllTypesProto3); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestAllTypesProto3 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (OptionalInt32 != other.OptionalInt32) return false; + if (OptionalInt64 != other.OptionalInt64) return false; + if (OptionalUint32 != other.OptionalUint32) return false; + if (OptionalUint64 != other.OptionalUint64) return false; + if (OptionalSint32 != other.OptionalSint32) return false; + if (OptionalSint64 != other.OptionalSint64) return false; + if (OptionalFixed32 != other.OptionalFixed32) return false; + if (OptionalFixed64 != other.OptionalFixed64) return false; + if (OptionalSfixed32 != other.OptionalSfixed32) return false; + if (OptionalSfixed64 != other.OptionalSfixed64) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(OptionalFloat, other.OptionalFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OptionalDouble, other.OptionalDouble)) return false; + if (OptionalBool != other.OptionalBool) return false; + if (OptionalString != other.OptionalString) return false; + if (OptionalBytes != other.OptionalBytes) return false; + if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false; + if (!object.Equals(OptionalForeignMessage, other.OptionalForeignMessage)) return false; + if (OptionalNestedEnum != other.OptionalNestedEnum) return false; + if (OptionalForeignEnum != other.OptionalForeignEnum) return false; + if (OptionalAliasedEnum != other.OptionalAliasedEnum) return false; + if (OptionalStringPiece != other.OptionalStringPiece) return false; + if (OptionalCord != other.OptionalCord) return false; + if (!object.Equals(RecursiveMessage, other.RecursiveMessage)) return false; + if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false; + if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false; + if(!repeatedUint32_.Equals(other.repeatedUint32_)) return false; + if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false; + if(!repeatedSint32_.Equals(other.repeatedSint32_)) return false; + if(!repeatedSint64_.Equals(other.repeatedSint64_)) return false; + if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false; + if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false; + if(!repeatedSfixed32_.Equals(other.repeatedSfixed32_)) return false; + if(!repeatedSfixed64_.Equals(other.repeatedSfixed64_)) return false; + if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false; + if(!repeatedDouble_.Equals(other.repeatedDouble_)) return false; + if(!repeatedBool_.Equals(other.repeatedBool_)) return false; + if(!repeatedString_.Equals(other.repeatedString_)) return false; + if(!repeatedBytes_.Equals(other.repeatedBytes_)) return false; + if(!repeatedNestedMessage_.Equals(other.repeatedNestedMessage_)) return false; + if(!repeatedForeignMessage_.Equals(other.repeatedForeignMessage_)) return false; + if(!repeatedNestedEnum_.Equals(other.repeatedNestedEnum_)) return false; + if(!repeatedForeignEnum_.Equals(other.repeatedForeignEnum_)) return false; + if(!repeatedStringPiece_.Equals(other.repeatedStringPiece_)) return false; + if(!repeatedCord_.Equals(other.repeatedCord_)) return false; + if(!packedInt32_.Equals(other.packedInt32_)) return false; + if(!packedInt64_.Equals(other.packedInt64_)) return false; + if(!packedUint32_.Equals(other.packedUint32_)) return false; + if(!packedUint64_.Equals(other.packedUint64_)) return false; + if(!packedSint32_.Equals(other.packedSint32_)) return false; + if(!packedSint64_.Equals(other.packedSint64_)) return false; + if(!packedFixed32_.Equals(other.packedFixed32_)) return false; + if(!packedFixed64_.Equals(other.packedFixed64_)) return false; + if(!packedSfixed32_.Equals(other.packedSfixed32_)) return false; + if(!packedSfixed64_.Equals(other.packedSfixed64_)) return false; + if(!packedFloat_.Equals(other.packedFloat_)) return false; + if(!packedDouble_.Equals(other.packedDouble_)) return false; + if(!packedBool_.Equals(other.packedBool_)) return false; + if(!packedNestedEnum_.Equals(other.packedNestedEnum_)) return false; + if(!unpackedInt32_.Equals(other.unpackedInt32_)) return false; + if(!unpackedInt64_.Equals(other.unpackedInt64_)) return false; + if(!unpackedUint32_.Equals(other.unpackedUint32_)) return false; + if(!unpackedUint64_.Equals(other.unpackedUint64_)) return false; + if(!unpackedSint32_.Equals(other.unpackedSint32_)) return false; + if(!unpackedSint64_.Equals(other.unpackedSint64_)) return false; + if(!unpackedFixed32_.Equals(other.unpackedFixed32_)) return false; + if(!unpackedFixed64_.Equals(other.unpackedFixed64_)) return false; + if(!unpackedSfixed32_.Equals(other.unpackedSfixed32_)) return false; + if(!unpackedSfixed64_.Equals(other.unpackedSfixed64_)) return false; + if(!unpackedFloat_.Equals(other.unpackedFloat_)) return false; + if(!unpackedDouble_.Equals(other.unpackedDouble_)) return false; + if(!unpackedBool_.Equals(other.unpackedBool_)) return false; + if(!unpackedNestedEnum_.Equals(other.unpackedNestedEnum_)) return false; + if (!MapInt32Int32.Equals(other.MapInt32Int32)) return false; + if (!MapInt64Int64.Equals(other.MapInt64Int64)) return false; + if (!MapUint32Uint32.Equals(other.MapUint32Uint32)) return false; + if (!MapUint64Uint64.Equals(other.MapUint64Uint64)) return false; + if (!MapSint32Sint32.Equals(other.MapSint32Sint32)) return false; + if (!MapSint64Sint64.Equals(other.MapSint64Sint64)) return false; + if (!MapFixed32Fixed32.Equals(other.MapFixed32Fixed32)) return false; + if (!MapFixed64Fixed64.Equals(other.MapFixed64Fixed64)) return false; + if (!MapSfixed32Sfixed32.Equals(other.MapSfixed32Sfixed32)) return false; + if (!MapSfixed64Sfixed64.Equals(other.MapSfixed64Sfixed64)) return false; + if (!MapInt32Float.Equals(other.MapInt32Float)) return false; + if (!MapInt32Double.Equals(other.MapInt32Double)) return false; + if (!MapBoolBool.Equals(other.MapBoolBool)) return false; + if (!MapStringString.Equals(other.MapStringString)) return false; + if (!MapStringBytes.Equals(other.MapStringBytes)) return false; + if (!MapStringNestedMessage.Equals(other.MapStringNestedMessage)) return false; + if (!MapStringForeignMessage.Equals(other.MapStringForeignMessage)) return false; + if (!MapStringNestedEnum.Equals(other.MapStringNestedEnum)) return false; + if (!MapStringForeignEnum.Equals(other.MapStringForeignEnum)) return false; + if (OneofUint32 != other.OneofUint32) return false; + if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false; + if (OneofString != other.OneofString) return false; + if (OneofBytes != other.OneofBytes) return false; + if (OneofBool != other.OneofBool) return false; + if (OneofUint64 != other.OneofUint64) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(OneofFloat, other.OneofFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OneofDouble, other.OneofDouble)) return false; + if (OneofEnum != other.OneofEnum) return false; + if (OneofNullValue != other.OneofNullValue) return false; + if (OptionalBoolWrapper != other.OptionalBoolWrapper) return false; + if (OptionalInt32Wrapper != other.OptionalInt32Wrapper) return false; + if (OptionalInt64Wrapper != other.OptionalInt64Wrapper) return false; + if (OptionalUint32Wrapper != other.OptionalUint32Wrapper) return false; + if (OptionalUint64Wrapper != other.OptionalUint64Wrapper) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.Equals(OptionalFloatWrapper, other.OptionalFloatWrapper)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(OptionalDoubleWrapper, other.OptionalDoubleWrapper)) return false; + if (OptionalStringWrapper != other.OptionalStringWrapper) return false; + if (OptionalBytesWrapper != other.OptionalBytesWrapper) return false; + if(!repeatedBoolWrapper_.Equals(other.repeatedBoolWrapper_)) return false; + if(!repeatedInt32Wrapper_.Equals(other.repeatedInt32Wrapper_)) return false; + if(!repeatedInt64Wrapper_.Equals(other.repeatedInt64Wrapper_)) return false; + if(!repeatedUint32Wrapper_.Equals(other.repeatedUint32Wrapper_)) return false; + if(!repeatedUint64Wrapper_.Equals(other.repeatedUint64Wrapper_)) return false; + if(!repeatedFloatWrapper_.Equals(other.repeatedFloatWrapper_)) return false; + if(!repeatedDoubleWrapper_.Equals(other.repeatedDoubleWrapper_)) return false; + if(!repeatedStringWrapper_.Equals(other.repeatedStringWrapper_)) return false; + if(!repeatedBytesWrapper_.Equals(other.repeatedBytesWrapper_)) return false; + if (!object.Equals(OptionalDuration, other.OptionalDuration)) return false; + if (!object.Equals(OptionalTimestamp, other.OptionalTimestamp)) return false; + if (!object.Equals(OptionalFieldMask, other.OptionalFieldMask)) return false; + if (!object.Equals(OptionalStruct, other.OptionalStruct)) return false; + if (!object.Equals(OptionalAny, other.OptionalAny)) return false; + if (!object.Equals(OptionalValue, other.OptionalValue)) return false; + if (OptionalNullValue != other.OptionalNullValue) return false; + if(!repeatedDuration_.Equals(other.repeatedDuration_)) return false; + if(!repeatedTimestamp_.Equals(other.repeatedTimestamp_)) return false; + if(!repeatedFieldmask_.Equals(other.repeatedFieldmask_)) return false; + if(!repeatedStruct_.Equals(other.repeatedStruct_)) return false; + if(!repeatedAny_.Equals(other.repeatedAny_)) return false; + if(!repeatedValue_.Equals(other.repeatedValue_)) return false; + if(!repeatedListValue_.Equals(other.repeatedListValue_)) return false; + if (Fieldname1 != other.Fieldname1) return false; + if (FieldName2 != other.FieldName2) return false; + if (FieldName3 != other.FieldName3) return false; + if (FieldName4 != other.FieldName4) return false; + if (Field0Name5 != other.Field0Name5) return false; + if (Field0Name6 != other.Field0Name6) return false; + if (FieldName7 != other.FieldName7) return false; + if (FieldName8 != other.FieldName8) return false; + if (FieldName9 != other.FieldName9) return false; + if (FieldName10 != other.FieldName10) return false; + if (FIELDNAME11 != other.FIELDNAME11) return false; + if (FIELDName12 != other.FIELDName12) return false; + if (FieldName13 != other.FieldName13) return false; + if (FieldName14 != other.FieldName14) return false; + if (FieldName15 != other.FieldName15) return false; + if (FieldName16 != other.FieldName16) return false; + if (FieldName17 != other.FieldName17) return false; + if (FieldName18 != other.FieldName18) return false; + if (OneofFieldCase != other.OneofFieldCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (OptionalInt32 != 0) hash ^= OptionalInt32.GetHashCode(); + if (OptionalInt64 != 0L) hash ^= OptionalInt64.GetHashCode(); + if (OptionalUint32 != 0) hash ^= OptionalUint32.GetHashCode(); + if (OptionalUint64 != 0UL) hash ^= OptionalUint64.GetHashCode(); + if (OptionalSint32 != 0) hash ^= OptionalSint32.GetHashCode(); + if (OptionalSint64 != 0L) hash ^= OptionalSint64.GetHashCode(); + if (OptionalFixed32 != 0) hash ^= OptionalFixed32.GetHashCode(); + if (OptionalFixed64 != 0UL) hash ^= OptionalFixed64.GetHashCode(); + if (OptionalSfixed32 != 0) hash ^= OptionalSfixed32.GetHashCode(); + if (OptionalSfixed64 != 0L) hash ^= OptionalSfixed64.GetHashCode(); + if (OptionalFloat != 0F) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(OptionalFloat); + if (OptionalDouble != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OptionalDouble); + if (OptionalBool != false) hash ^= OptionalBool.GetHashCode(); + if (OptionalString.Length != 0) hash ^= OptionalString.GetHashCode(); + if (OptionalBytes.Length != 0) hash ^= OptionalBytes.GetHashCode(); + if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode(); + if (optionalForeignMessage_ != null) hash ^= OptionalForeignMessage.GetHashCode(); + if (OptionalNestedEnum != global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum.Foo) hash ^= OptionalNestedEnum.GetHashCode(); + if (OptionalForeignEnum != global::ProtobufTestMessages.Proto3.ForeignEnum.ForeignFoo) hash ^= OptionalForeignEnum.GetHashCode(); + if (OptionalAliasedEnum != global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum.AliasFoo) hash ^= OptionalAliasedEnum.GetHashCode(); + if (OptionalStringPiece.Length != 0) hash ^= OptionalStringPiece.GetHashCode(); + if (OptionalCord.Length != 0) hash ^= OptionalCord.GetHashCode(); + if (recursiveMessage_ != null) hash ^= RecursiveMessage.GetHashCode(); + hash ^= repeatedInt32_.GetHashCode(); + hash ^= repeatedInt64_.GetHashCode(); + hash ^= repeatedUint32_.GetHashCode(); + hash ^= repeatedUint64_.GetHashCode(); + hash ^= repeatedSint32_.GetHashCode(); + hash ^= repeatedSint64_.GetHashCode(); + hash ^= repeatedFixed32_.GetHashCode(); + hash ^= repeatedFixed64_.GetHashCode(); + hash ^= repeatedSfixed32_.GetHashCode(); + hash ^= repeatedSfixed64_.GetHashCode(); + hash ^= repeatedFloat_.GetHashCode(); + hash ^= repeatedDouble_.GetHashCode(); + hash ^= repeatedBool_.GetHashCode(); + hash ^= repeatedString_.GetHashCode(); + hash ^= repeatedBytes_.GetHashCode(); + hash ^= repeatedNestedMessage_.GetHashCode(); + hash ^= repeatedForeignMessage_.GetHashCode(); + hash ^= repeatedNestedEnum_.GetHashCode(); + hash ^= repeatedForeignEnum_.GetHashCode(); + hash ^= repeatedStringPiece_.GetHashCode(); + hash ^= repeatedCord_.GetHashCode(); + hash ^= packedInt32_.GetHashCode(); + hash ^= packedInt64_.GetHashCode(); + hash ^= packedUint32_.GetHashCode(); + hash ^= packedUint64_.GetHashCode(); + hash ^= packedSint32_.GetHashCode(); + hash ^= packedSint64_.GetHashCode(); + hash ^= packedFixed32_.GetHashCode(); + hash ^= packedFixed64_.GetHashCode(); + hash ^= packedSfixed32_.GetHashCode(); + hash ^= packedSfixed64_.GetHashCode(); + hash ^= packedFloat_.GetHashCode(); + hash ^= packedDouble_.GetHashCode(); + hash ^= packedBool_.GetHashCode(); + hash ^= packedNestedEnum_.GetHashCode(); + hash ^= unpackedInt32_.GetHashCode(); + hash ^= unpackedInt64_.GetHashCode(); + hash ^= unpackedUint32_.GetHashCode(); + hash ^= unpackedUint64_.GetHashCode(); + hash ^= unpackedSint32_.GetHashCode(); + hash ^= unpackedSint64_.GetHashCode(); + hash ^= unpackedFixed32_.GetHashCode(); + hash ^= unpackedFixed64_.GetHashCode(); + hash ^= unpackedSfixed32_.GetHashCode(); + hash ^= unpackedSfixed64_.GetHashCode(); + hash ^= unpackedFloat_.GetHashCode(); + hash ^= unpackedDouble_.GetHashCode(); + hash ^= unpackedBool_.GetHashCode(); + hash ^= unpackedNestedEnum_.GetHashCode(); + hash ^= MapInt32Int32.GetHashCode(); + hash ^= MapInt64Int64.GetHashCode(); + hash ^= MapUint32Uint32.GetHashCode(); + hash ^= MapUint64Uint64.GetHashCode(); + hash ^= MapSint32Sint32.GetHashCode(); + hash ^= MapSint64Sint64.GetHashCode(); + hash ^= MapFixed32Fixed32.GetHashCode(); + hash ^= MapFixed64Fixed64.GetHashCode(); + hash ^= MapSfixed32Sfixed32.GetHashCode(); + hash ^= MapSfixed64Sfixed64.GetHashCode(); + hash ^= MapInt32Float.GetHashCode(); + hash ^= MapInt32Double.GetHashCode(); + hash ^= MapBoolBool.GetHashCode(); + hash ^= MapStringString.GetHashCode(); + hash ^= MapStringBytes.GetHashCode(); + hash ^= MapStringNestedMessage.GetHashCode(); + hash ^= MapStringForeignMessage.GetHashCode(); + hash ^= MapStringNestedEnum.GetHashCode(); + hash ^= MapStringForeignEnum.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) hash ^= OneofUint32.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) hash ^= OneofString.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) hash ^= OneofBytes.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBool) hash ^= OneofBool.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint64) hash ^= OneofUint64.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(OneofFloat); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OneofDouble); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) hash ^= OneofEnum.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue) hash ^= OneofNullValue.GetHashCode(); + if (optionalBoolWrapper_ != null) hash ^= OptionalBoolWrapper.GetHashCode(); + if (optionalInt32Wrapper_ != null) hash ^= OptionalInt32Wrapper.GetHashCode(); + if (optionalInt64Wrapper_ != null) hash ^= OptionalInt64Wrapper.GetHashCode(); + if (optionalUint32Wrapper_ != null) hash ^= OptionalUint32Wrapper.GetHashCode(); + if (optionalUint64Wrapper_ != null) hash ^= OptionalUint64Wrapper.GetHashCode(); + if (optionalFloatWrapper_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.GetHashCode(OptionalFloatWrapper); + if (optionalDoubleWrapper_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(OptionalDoubleWrapper); + if (optionalStringWrapper_ != null) hash ^= OptionalStringWrapper.GetHashCode(); + if (optionalBytesWrapper_ != null) hash ^= OptionalBytesWrapper.GetHashCode(); + hash ^= repeatedBoolWrapper_.GetHashCode(); + hash ^= repeatedInt32Wrapper_.GetHashCode(); + hash ^= repeatedInt64Wrapper_.GetHashCode(); + hash ^= repeatedUint32Wrapper_.GetHashCode(); + hash ^= repeatedUint64Wrapper_.GetHashCode(); + hash ^= repeatedFloatWrapper_.GetHashCode(); + hash ^= repeatedDoubleWrapper_.GetHashCode(); + hash ^= repeatedStringWrapper_.GetHashCode(); + hash ^= repeatedBytesWrapper_.GetHashCode(); + if (optionalDuration_ != null) hash ^= OptionalDuration.GetHashCode(); + if (optionalTimestamp_ != null) hash ^= OptionalTimestamp.GetHashCode(); + if (optionalFieldMask_ != null) hash ^= OptionalFieldMask.GetHashCode(); + if (optionalStruct_ != null) hash ^= OptionalStruct.GetHashCode(); + if (optionalAny_ != null) hash ^= OptionalAny.GetHashCode(); + if (optionalValue_ != null) hash ^= OptionalValue.GetHashCode(); + if (OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) hash ^= OptionalNullValue.GetHashCode(); + hash ^= repeatedDuration_.GetHashCode(); + hash ^= repeatedTimestamp_.GetHashCode(); + hash ^= repeatedFieldmask_.GetHashCode(); + hash ^= repeatedStruct_.GetHashCode(); + hash ^= repeatedAny_.GetHashCode(); + hash ^= repeatedValue_.GetHashCode(); + hash ^= repeatedListValue_.GetHashCode(); + if (Fieldname1 != 0) hash ^= Fieldname1.GetHashCode(); + if (FieldName2 != 0) hash ^= FieldName2.GetHashCode(); + if (FieldName3 != 0) hash ^= FieldName3.GetHashCode(); + if (FieldName4 != 0) hash ^= FieldName4.GetHashCode(); + if (Field0Name5 != 0) hash ^= Field0Name5.GetHashCode(); + if (Field0Name6 != 0) hash ^= Field0Name6.GetHashCode(); + if (FieldName7 != 0) hash ^= FieldName7.GetHashCode(); + if (FieldName8 != 0) hash ^= FieldName8.GetHashCode(); + if (FieldName9 != 0) hash ^= FieldName9.GetHashCode(); + if (FieldName10 != 0) hash ^= FieldName10.GetHashCode(); + if (FIELDNAME11 != 0) hash ^= FIELDNAME11.GetHashCode(); + if (FIELDName12 != 0) hash ^= FIELDName12.GetHashCode(); + if (FieldName13 != 0) hash ^= FieldName13.GetHashCode(); + if (FieldName14 != 0) hash ^= FieldName14.GetHashCode(); + if (FieldName15 != 0) hash ^= FieldName15.GetHashCode(); + if (FieldName16 != 0) hash ^= FieldName16.GetHashCode(); + if (FieldName17 != 0) hash ^= FieldName17.GetHashCode(); + if (FieldName18 != 0) hash ^= FieldName18.GetHashCode(); + hash ^= (int) oneofFieldCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (OptionalInt32 != 0) { + output.WriteRawTag(8); + output.WriteInt32(OptionalInt32); + } + if (OptionalInt64 != 0L) { + output.WriteRawTag(16); + output.WriteInt64(OptionalInt64); + } + if (OptionalUint32 != 0) { + output.WriteRawTag(24); + output.WriteUInt32(OptionalUint32); + } + if (OptionalUint64 != 0UL) { + output.WriteRawTag(32); + output.WriteUInt64(OptionalUint64); + } + if (OptionalSint32 != 0) { + output.WriteRawTag(40); + output.WriteSInt32(OptionalSint32); + } + if (OptionalSint64 != 0L) { + output.WriteRawTag(48); + output.WriteSInt64(OptionalSint64); + } + if (OptionalFixed32 != 0) { + output.WriteRawTag(61); + output.WriteFixed32(OptionalFixed32); + } + if (OptionalFixed64 != 0UL) { + output.WriteRawTag(65); + output.WriteFixed64(OptionalFixed64); + } + if (OptionalSfixed32 != 0) { + output.WriteRawTag(77); + output.WriteSFixed32(OptionalSfixed32); + } + if (OptionalSfixed64 != 0L) { + output.WriteRawTag(81); + output.WriteSFixed64(OptionalSfixed64); + } + if (OptionalFloat != 0F) { + output.WriteRawTag(93); + output.WriteFloat(OptionalFloat); + } + if (OptionalDouble != 0D) { + output.WriteRawTag(97); + output.WriteDouble(OptionalDouble); + } + if (OptionalBool != false) { + output.WriteRawTag(104); + output.WriteBool(OptionalBool); + } + if (OptionalString.Length != 0) { + output.WriteRawTag(114); + output.WriteString(OptionalString); + } + if (OptionalBytes.Length != 0) { + output.WriteRawTag(122); + output.WriteBytes(OptionalBytes); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(OptionalNestedMessage); + } + if (optionalForeignMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(OptionalForeignMessage); + } + if (OptionalNestedEnum != global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum.Foo) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) OptionalNestedEnum); + } + if (OptionalForeignEnum != global::ProtobufTestMessages.Proto3.ForeignEnum.ForeignFoo) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) OptionalForeignEnum); + } + if (OptionalAliasedEnum != global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum.AliasFoo) { + output.WriteRawTag(184, 1); + output.WriteEnum((int) OptionalAliasedEnum); + } + if (OptionalStringPiece.Length != 0) { + output.WriteRawTag(194, 1); + output.WriteString(OptionalStringPiece); + } + if (OptionalCord.Length != 0) { + output.WriteRawTag(202, 1); + output.WriteString(OptionalCord); + } + if (recursiveMessage_ != null) { + output.WriteRawTag(218, 1); + output.WriteMessage(RecursiveMessage); + } + repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec); + repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec); + repeatedUint32_.WriteTo(output, _repeated_repeatedUint32_codec); + repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec); + repeatedSint32_.WriteTo(output, _repeated_repeatedSint32_codec); + repeatedSint64_.WriteTo(output, _repeated_repeatedSint64_codec); + repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec); + repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec); + repeatedSfixed32_.WriteTo(output, _repeated_repeatedSfixed32_codec); + repeatedSfixed64_.WriteTo(output, _repeated_repeatedSfixed64_codec); + repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec); + repeatedDouble_.WriteTo(output, _repeated_repeatedDouble_codec); + repeatedBool_.WriteTo(output, _repeated_repeatedBool_codec); + repeatedString_.WriteTo(output, _repeated_repeatedString_codec); + repeatedBytes_.WriteTo(output, _repeated_repeatedBytes_codec); + repeatedNestedMessage_.WriteTo(output, _repeated_repeatedNestedMessage_codec); + repeatedForeignMessage_.WriteTo(output, _repeated_repeatedForeignMessage_codec); + repeatedNestedEnum_.WriteTo(output, _repeated_repeatedNestedEnum_codec); + repeatedForeignEnum_.WriteTo(output, _repeated_repeatedForeignEnum_codec); + repeatedStringPiece_.WriteTo(output, _repeated_repeatedStringPiece_codec); + repeatedCord_.WriteTo(output, _repeated_repeatedCord_codec); + mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec); + mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec); + mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec); + mapUint64Uint64_.WriteTo(output, _map_mapUint64Uint64_codec); + mapSint32Sint32_.WriteTo(output, _map_mapSint32Sint32_codec); + mapSint64Sint64_.WriteTo(output, _map_mapSint64Sint64_codec); + mapFixed32Fixed32_.WriteTo(output, _map_mapFixed32Fixed32_codec); + mapFixed64Fixed64_.WriteTo(output, _map_mapFixed64Fixed64_codec); + mapSfixed32Sfixed32_.WriteTo(output, _map_mapSfixed32Sfixed32_codec); + mapSfixed64Sfixed64_.WriteTo(output, _map_mapSfixed64Sfixed64_codec); + mapInt32Float_.WriteTo(output, _map_mapInt32Float_codec); + mapInt32Double_.WriteTo(output, _map_mapInt32Double_codec); + mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec); + mapStringString_.WriteTo(output, _map_mapStringString_codec); + mapStringBytes_.WriteTo(output, _map_mapStringBytes_codec); + mapStringNestedMessage_.WriteTo(output, _map_mapStringNestedMessage_codec); + mapStringForeignMessage_.WriteTo(output, _map_mapStringForeignMessage_codec); + mapStringNestedEnum_.WriteTo(output, _map_mapStringNestedEnum_codec); + mapStringForeignEnum_.WriteTo(output, _map_mapStringForeignEnum_codec); + packedInt32_.WriteTo(output, _repeated_packedInt32_codec); + packedInt64_.WriteTo(output, _repeated_packedInt64_codec); + packedUint32_.WriteTo(output, _repeated_packedUint32_codec); + packedUint64_.WriteTo(output, _repeated_packedUint64_codec); + packedSint32_.WriteTo(output, _repeated_packedSint32_codec); + packedSint64_.WriteTo(output, _repeated_packedSint64_codec); + packedFixed32_.WriteTo(output, _repeated_packedFixed32_codec); + packedFixed64_.WriteTo(output, _repeated_packedFixed64_codec); + packedSfixed32_.WriteTo(output, _repeated_packedSfixed32_codec); + packedSfixed64_.WriteTo(output, _repeated_packedSfixed64_codec); + packedFloat_.WriteTo(output, _repeated_packedFloat_codec); + packedDouble_.WriteTo(output, _repeated_packedDouble_codec); + packedBool_.WriteTo(output, _repeated_packedBool_codec); + packedNestedEnum_.WriteTo(output, _repeated_packedNestedEnum_codec); + unpackedInt32_.WriteTo(output, _repeated_unpackedInt32_codec); + unpackedInt64_.WriteTo(output, _repeated_unpackedInt64_codec); + unpackedUint32_.WriteTo(output, _repeated_unpackedUint32_codec); + unpackedUint64_.WriteTo(output, _repeated_unpackedUint64_codec); + unpackedSint32_.WriteTo(output, _repeated_unpackedSint32_codec); + unpackedSint64_.WriteTo(output, _repeated_unpackedSint64_codec); + unpackedFixed32_.WriteTo(output, _repeated_unpackedFixed32_codec); + unpackedFixed64_.WriteTo(output, _repeated_unpackedFixed64_codec); + unpackedSfixed32_.WriteTo(output, _repeated_unpackedSfixed32_codec); + unpackedSfixed64_.WriteTo(output, _repeated_unpackedSfixed64_codec); + unpackedFloat_.WriteTo(output, _repeated_unpackedFloat_codec); + unpackedDouble_.WriteTo(output, _repeated_unpackedDouble_codec); + unpackedBool_.WriteTo(output, _repeated_unpackedBool_codec); + unpackedNestedEnum_.WriteTo(output, _repeated_unpackedNestedEnum_codec); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { + output.WriteRawTag(248, 6); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + output.WriteRawTag(130, 7); + output.WriteMessage(OneofNestedMessage); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { + output.WriteRawTag(138, 7); + output.WriteString(OneofString); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { + output.WriteRawTag(146, 7); + output.WriteBytes(OneofBytes); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBool) { + output.WriteRawTag(152, 7); + output.WriteBool(OneofBool); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint64) { + output.WriteRawTag(160, 7); + output.WriteUInt64(OneofUint64); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) { + output.WriteRawTag(173, 7); + output.WriteFloat(OneofFloat); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) { + output.WriteRawTag(177, 7); + output.WriteDouble(OneofDouble); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) { + output.WriteRawTag(184, 7); + output.WriteEnum((int) OneofEnum); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue) { + output.WriteRawTag(192, 7); + output.WriteEnum((int) OneofNullValue); + } + if (optionalBoolWrapper_ != null) { + _single_optionalBoolWrapper_codec.WriteTagAndValue(output, OptionalBoolWrapper); + } + if (optionalInt32Wrapper_ != null) { + _single_optionalInt32Wrapper_codec.WriteTagAndValue(output, OptionalInt32Wrapper); + } + if (optionalInt64Wrapper_ != null) { + _single_optionalInt64Wrapper_codec.WriteTagAndValue(output, OptionalInt64Wrapper); + } + if (optionalUint32Wrapper_ != null) { + _single_optionalUint32Wrapper_codec.WriteTagAndValue(output, OptionalUint32Wrapper); + } + if (optionalUint64Wrapper_ != null) { + _single_optionalUint64Wrapper_codec.WriteTagAndValue(output, OptionalUint64Wrapper); + } + if (optionalFloatWrapper_ != null) { + _single_optionalFloatWrapper_codec.WriteTagAndValue(output, OptionalFloatWrapper); + } + if (optionalDoubleWrapper_ != null) { + _single_optionalDoubleWrapper_codec.WriteTagAndValue(output, OptionalDoubleWrapper); + } + if (optionalStringWrapper_ != null) { + _single_optionalStringWrapper_codec.WriteTagAndValue(output, OptionalStringWrapper); + } + if (optionalBytesWrapper_ != null) { + _single_optionalBytesWrapper_codec.WriteTagAndValue(output, OptionalBytesWrapper); + } + repeatedBoolWrapper_.WriteTo(output, _repeated_repeatedBoolWrapper_codec); + repeatedInt32Wrapper_.WriteTo(output, _repeated_repeatedInt32Wrapper_codec); + repeatedInt64Wrapper_.WriteTo(output, _repeated_repeatedInt64Wrapper_codec); + repeatedUint32Wrapper_.WriteTo(output, _repeated_repeatedUint32Wrapper_codec); + repeatedUint64Wrapper_.WriteTo(output, _repeated_repeatedUint64Wrapper_codec); + repeatedFloatWrapper_.WriteTo(output, _repeated_repeatedFloatWrapper_codec); + repeatedDoubleWrapper_.WriteTo(output, _repeated_repeatedDoubleWrapper_codec); + repeatedStringWrapper_.WriteTo(output, _repeated_repeatedStringWrapper_codec); + repeatedBytesWrapper_.WriteTo(output, _repeated_repeatedBytesWrapper_codec); + if (optionalDuration_ != null) { + output.WriteRawTag(234, 18); + output.WriteMessage(OptionalDuration); + } + if (optionalTimestamp_ != null) { + output.WriteRawTag(242, 18); + output.WriteMessage(OptionalTimestamp); + } + if (optionalFieldMask_ != null) { + output.WriteRawTag(250, 18); + output.WriteMessage(OptionalFieldMask); + } + if (optionalStruct_ != null) { + output.WriteRawTag(130, 19); + output.WriteMessage(OptionalStruct); + } + if (optionalAny_ != null) { + output.WriteRawTag(138, 19); + output.WriteMessage(OptionalAny); + } + if (optionalValue_ != null) { + output.WriteRawTag(146, 19); + output.WriteMessage(OptionalValue); + } + if (OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + output.WriteRawTag(152, 19); + output.WriteEnum((int) OptionalNullValue); + } + repeatedDuration_.WriteTo(output, _repeated_repeatedDuration_codec); + repeatedTimestamp_.WriteTo(output, _repeated_repeatedTimestamp_codec); + repeatedFieldmask_.WriteTo(output, _repeated_repeatedFieldmask_codec); + repeatedAny_.WriteTo(output, _repeated_repeatedAny_codec); + repeatedValue_.WriteTo(output, _repeated_repeatedValue_codec); + repeatedListValue_.WriteTo(output, _repeated_repeatedListValue_codec); + repeatedStruct_.WriteTo(output, _repeated_repeatedStruct_codec); + if (Fieldname1 != 0) { + output.WriteRawTag(136, 25); + output.WriteInt32(Fieldname1); + } + if (FieldName2 != 0) { + output.WriteRawTag(144, 25); + output.WriteInt32(FieldName2); + } + if (FieldName3 != 0) { + output.WriteRawTag(152, 25); + output.WriteInt32(FieldName3); + } + if (FieldName4 != 0) { + output.WriteRawTag(160, 25); + output.WriteInt32(FieldName4); + } + if (Field0Name5 != 0) { + output.WriteRawTag(168, 25); + output.WriteInt32(Field0Name5); + } + if (Field0Name6 != 0) { + output.WriteRawTag(176, 25); + output.WriteInt32(Field0Name6); + } + if (FieldName7 != 0) { + output.WriteRawTag(184, 25); + output.WriteInt32(FieldName7); + } + if (FieldName8 != 0) { + output.WriteRawTag(192, 25); + output.WriteInt32(FieldName8); + } + if (FieldName9 != 0) { + output.WriteRawTag(200, 25); + output.WriteInt32(FieldName9); + } + if (FieldName10 != 0) { + output.WriteRawTag(208, 25); + output.WriteInt32(FieldName10); + } + if (FIELDNAME11 != 0) { + output.WriteRawTag(216, 25); + output.WriteInt32(FIELDNAME11); + } + if (FIELDName12 != 0) { + output.WriteRawTag(224, 25); + output.WriteInt32(FIELDName12); + } + if (FieldName13 != 0) { + output.WriteRawTag(232, 25); + output.WriteInt32(FieldName13); + } + if (FieldName14 != 0) { + output.WriteRawTag(240, 25); + output.WriteInt32(FieldName14); + } + if (FieldName15 != 0) { + output.WriteRawTag(248, 25); + output.WriteInt32(FieldName15); + } + if (FieldName16 != 0) { + output.WriteRawTag(128, 26); + output.WriteInt32(FieldName16); + } + if (FieldName17 != 0) { + output.WriteRawTag(136, 26); + output.WriteInt32(FieldName17); + } + if (FieldName18 != 0) { + output.WriteRawTag(144, 26); + output.WriteInt32(FieldName18); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (OptionalInt32 != 0) { + output.WriteRawTag(8); + output.WriteInt32(OptionalInt32); + } + if (OptionalInt64 != 0L) { + output.WriteRawTag(16); + output.WriteInt64(OptionalInt64); + } + if (OptionalUint32 != 0) { + output.WriteRawTag(24); + output.WriteUInt32(OptionalUint32); + } + if (OptionalUint64 != 0UL) { + output.WriteRawTag(32); + output.WriteUInt64(OptionalUint64); + } + if (OptionalSint32 != 0) { + output.WriteRawTag(40); + output.WriteSInt32(OptionalSint32); + } + if (OptionalSint64 != 0L) { + output.WriteRawTag(48); + output.WriteSInt64(OptionalSint64); + } + if (OptionalFixed32 != 0) { + output.WriteRawTag(61); + output.WriteFixed32(OptionalFixed32); + } + if (OptionalFixed64 != 0UL) { + output.WriteRawTag(65); + output.WriteFixed64(OptionalFixed64); + } + if (OptionalSfixed32 != 0) { + output.WriteRawTag(77); + output.WriteSFixed32(OptionalSfixed32); + } + if (OptionalSfixed64 != 0L) { + output.WriteRawTag(81); + output.WriteSFixed64(OptionalSfixed64); + } + if (OptionalFloat != 0F) { + output.WriteRawTag(93); + output.WriteFloat(OptionalFloat); + } + if (OptionalDouble != 0D) { + output.WriteRawTag(97); + output.WriteDouble(OptionalDouble); + } + if (OptionalBool != false) { + output.WriteRawTag(104); + output.WriteBool(OptionalBool); + } + if (OptionalString.Length != 0) { + output.WriteRawTag(114); + output.WriteString(OptionalString); + } + if (OptionalBytes.Length != 0) { + output.WriteRawTag(122); + output.WriteBytes(OptionalBytes); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(OptionalNestedMessage); + } + if (optionalForeignMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(OptionalForeignMessage); + } + if (OptionalNestedEnum != global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum.Foo) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) OptionalNestedEnum); + } + if (OptionalForeignEnum != global::ProtobufTestMessages.Proto3.ForeignEnum.ForeignFoo) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) OptionalForeignEnum); + } + if (OptionalAliasedEnum != global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum.AliasFoo) { + output.WriteRawTag(184, 1); + output.WriteEnum((int) OptionalAliasedEnum); + } + if (OptionalStringPiece.Length != 0) { + output.WriteRawTag(194, 1); + output.WriteString(OptionalStringPiece); + } + if (OptionalCord.Length != 0) { + output.WriteRawTag(202, 1); + output.WriteString(OptionalCord); + } + if (recursiveMessage_ != null) { + output.WriteRawTag(218, 1); + output.WriteMessage(RecursiveMessage); + } + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec); + repeatedUint32_.WriteTo(ref output, _repeated_repeatedUint32_codec); + repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec); + repeatedSint32_.WriteTo(ref output, _repeated_repeatedSint32_codec); + repeatedSint64_.WriteTo(ref output, _repeated_repeatedSint64_codec); + repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec); + repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec); + repeatedSfixed32_.WriteTo(ref output, _repeated_repeatedSfixed32_codec); + repeatedSfixed64_.WriteTo(ref output, _repeated_repeatedSfixed64_codec); + repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec); + repeatedDouble_.WriteTo(ref output, _repeated_repeatedDouble_codec); + repeatedBool_.WriteTo(ref output, _repeated_repeatedBool_codec); + repeatedString_.WriteTo(ref output, _repeated_repeatedString_codec); + repeatedBytes_.WriteTo(ref output, _repeated_repeatedBytes_codec); + repeatedNestedMessage_.WriteTo(ref output, _repeated_repeatedNestedMessage_codec); + repeatedForeignMessage_.WriteTo(ref output, _repeated_repeatedForeignMessage_codec); + repeatedNestedEnum_.WriteTo(ref output, _repeated_repeatedNestedEnum_codec); + repeatedForeignEnum_.WriteTo(ref output, _repeated_repeatedForeignEnum_codec); + repeatedStringPiece_.WriteTo(ref output, _repeated_repeatedStringPiece_codec); + repeatedCord_.WriteTo(ref output, _repeated_repeatedCord_codec); + mapInt32Int32_.WriteTo(ref output, _map_mapInt32Int32_codec); + mapInt64Int64_.WriteTo(ref output, _map_mapInt64Int64_codec); + mapUint32Uint32_.WriteTo(ref output, _map_mapUint32Uint32_codec); + mapUint64Uint64_.WriteTo(ref output, _map_mapUint64Uint64_codec); + mapSint32Sint32_.WriteTo(ref output, _map_mapSint32Sint32_codec); + mapSint64Sint64_.WriteTo(ref output, _map_mapSint64Sint64_codec); + mapFixed32Fixed32_.WriteTo(ref output, _map_mapFixed32Fixed32_codec); + mapFixed64Fixed64_.WriteTo(ref output, _map_mapFixed64Fixed64_codec); + mapSfixed32Sfixed32_.WriteTo(ref output, _map_mapSfixed32Sfixed32_codec); + mapSfixed64Sfixed64_.WriteTo(ref output, _map_mapSfixed64Sfixed64_codec); + mapInt32Float_.WriteTo(ref output, _map_mapInt32Float_codec); + mapInt32Double_.WriteTo(ref output, _map_mapInt32Double_codec); + mapBoolBool_.WriteTo(ref output, _map_mapBoolBool_codec); + mapStringString_.WriteTo(ref output, _map_mapStringString_codec); + mapStringBytes_.WriteTo(ref output, _map_mapStringBytes_codec); + mapStringNestedMessage_.WriteTo(ref output, _map_mapStringNestedMessage_codec); + mapStringForeignMessage_.WriteTo(ref output, _map_mapStringForeignMessage_codec); + mapStringNestedEnum_.WriteTo(ref output, _map_mapStringNestedEnum_codec); + mapStringForeignEnum_.WriteTo(ref output, _map_mapStringForeignEnum_codec); + packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec); + packedInt64_.WriteTo(ref output, _repeated_packedInt64_codec); + packedUint32_.WriteTo(ref output, _repeated_packedUint32_codec); + packedUint64_.WriteTo(ref output, _repeated_packedUint64_codec); + packedSint32_.WriteTo(ref output, _repeated_packedSint32_codec); + packedSint64_.WriteTo(ref output, _repeated_packedSint64_codec); + packedFixed32_.WriteTo(ref output, _repeated_packedFixed32_codec); + packedFixed64_.WriteTo(ref output, _repeated_packedFixed64_codec); + packedSfixed32_.WriteTo(ref output, _repeated_packedSfixed32_codec); + packedSfixed64_.WriteTo(ref output, _repeated_packedSfixed64_codec); + packedFloat_.WriteTo(ref output, _repeated_packedFloat_codec); + packedDouble_.WriteTo(ref output, _repeated_packedDouble_codec); + packedBool_.WriteTo(ref output, _repeated_packedBool_codec); + packedNestedEnum_.WriteTo(ref output, _repeated_packedNestedEnum_codec); + unpackedInt32_.WriteTo(ref output, _repeated_unpackedInt32_codec); + unpackedInt64_.WriteTo(ref output, _repeated_unpackedInt64_codec); + unpackedUint32_.WriteTo(ref output, _repeated_unpackedUint32_codec); + unpackedUint64_.WriteTo(ref output, _repeated_unpackedUint64_codec); + unpackedSint32_.WriteTo(ref output, _repeated_unpackedSint32_codec); + unpackedSint64_.WriteTo(ref output, _repeated_unpackedSint64_codec); + unpackedFixed32_.WriteTo(ref output, _repeated_unpackedFixed32_codec); + unpackedFixed64_.WriteTo(ref output, _repeated_unpackedFixed64_codec); + unpackedSfixed32_.WriteTo(ref output, _repeated_unpackedSfixed32_codec); + unpackedSfixed64_.WriteTo(ref output, _repeated_unpackedSfixed64_codec); + unpackedFloat_.WriteTo(ref output, _repeated_unpackedFloat_codec); + unpackedDouble_.WriteTo(ref output, _repeated_unpackedDouble_codec); + unpackedBool_.WriteTo(ref output, _repeated_unpackedBool_codec); + unpackedNestedEnum_.WriteTo(ref output, _repeated_unpackedNestedEnum_codec); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { + output.WriteRawTag(248, 6); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + output.WriteRawTag(130, 7); + output.WriteMessage(OneofNestedMessage); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { + output.WriteRawTag(138, 7); + output.WriteString(OneofString); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { + output.WriteRawTag(146, 7); + output.WriteBytes(OneofBytes); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBool) { + output.WriteRawTag(152, 7); + output.WriteBool(OneofBool); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint64) { + output.WriteRawTag(160, 7); + output.WriteUInt64(OneofUint64); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) { + output.WriteRawTag(173, 7); + output.WriteFloat(OneofFloat); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) { + output.WriteRawTag(177, 7); + output.WriteDouble(OneofDouble); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) { + output.WriteRawTag(184, 7); + output.WriteEnum((int) OneofEnum); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue) { + output.WriteRawTag(192, 7); + output.WriteEnum((int) OneofNullValue); + } + if (optionalBoolWrapper_ != null) { + _single_optionalBoolWrapper_codec.WriteTagAndValue(ref output, OptionalBoolWrapper); + } + if (optionalInt32Wrapper_ != null) { + _single_optionalInt32Wrapper_codec.WriteTagAndValue(ref output, OptionalInt32Wrapper); + } + if (optionalInt64Wrapper_ != null) { + _single_optionalInt64Wrapper_codec.WriteTagAndValue(ref output, OptionalInt64Wrapper); + } + if (optionalUint32Wrapper_ != null) { + _single_optionalUint32Wrapper_codec.WriteTagAndValue(ref output, OptionalUint32Wrapper); + } + if (optionalUint64Wrapper_ != null) { + _single_optionalUint64Wrapper_codec.WriteTagAndValue(ref output, OptionalUint64Wrapper); + } + if (optionalFloatWrapper_ != null) { + _single_optionalFloatWrapper_codec.WriteTagAndValue(ref output, OptionalFloatWrapper); + } + if (optionalDoubleWrapper_ != null) { + _single_optionalDoubleWrapper_codec.WriteTagAndValue(ref output, OptionalDoubleWrapper); + } + if (optionalStringWrapper_ != null) { + _single_optionalStringWrapper_codec.WriteTagAndValue(ref output, OptionalStringWrapper); + } + if (optionalBytesWrapper_ != null) { + _single_optionalBytesWrapper_codec.WriteTagAndValue(ref output, OptionalBytesWrapper); + } + repeatedBoolWrapper_.WriteTo(ref output, _repeated_repeatedBoolWrapper_codec); + repeatedInt32Wrapper_.WriteTo(ref output, _repeated_repeatedInt32Wrapper_codec); + repeatedInt64Wrapper_.WriteTo(ref output, _repeated_repeatedInt64Wrapper_codec); + repeatedUint32Wrapper_.WriteTo(ref output, _repeated_repeatedUint32Wrapper_codec); + repeatedUint64Wrapper_.WriteTo(ref output, _repeated_repeatedUint64Wrapper_codec); + repeatedFloatWrapper_.WriteTo(ref output, _repeated_repeatedFloatWrapper_codec); + repeatedDoubleWrapper_.WriteTo(ref output, _repeated_repeatedDoubleWrapper_codec); + repeatedStringWrapper_.WriteTo(ref output, _repeated_repeatedStringWrapper_codec); + repeatedBytesWrapper_.WriteTo(ref output, _repeated_repeatedBytesWrapper_codec); + if (optionalDuration_ != null) { + output.WriteRawTag(234, 18); + output.WriteMessage(OptionalDuration); + } + if (optionalTimestamp_ != null) { + output.WriteRawTag(242, 18); + output.WriteMessage(OptionalTimestamp); + } + if (optionalFieldMask_ != null) { + output.WriteRawTag(250, 18); + output.WriteMessage(OptionalFieldMask); + } + if (optionalStruct_ != null) { + output.WriteRawTag(130, 19); + output.WriteMessage(OptionalStruct); + } + if (optionalAny_ != null) { + output.WriteRawTag(138, 19); + output.WriteMessage(OptionalAny); + } + if (optionalValue_ != null) { + output.WriteRawTag(146, 19); + output.WriteMessage(OptionalValue); + } + if (OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + output.WriteRawTag(152, 19); + output.WriteEnum((int) OptionalNullValue); + } + repeatedDuration_.WriteTo(ref output, _repeated_repeatedDuration_codec); + repeatedTimestamp_.WriteTo(ref output, _repeated_repeatedTimestamp_codec); + repeatedFieldmask_.WriteTo(ref output, _repeated_repeatedFieldmask_codec); + repeatedAny_.WriteTo(ref output, _repeated_repeatedAny_codec); + repeatedValue_.WriteTo(ref output, _repeated_repeatedValue_codec); + repeatedListValue_.WriteTo(ref output, _repeated_repeatedListValue_codec); + repeatedStruct_.WriteTo(ref output, _repeated_repeatedStruct_codec); + if (Fieldname1 != 0) { + output.WriteRawTag(136, 25); + output.WriteInt32(Fieldname1); + } + if (FieldName2 != 0) { + output.WriteRawTag(144, 25); + output.WriteInt32(FieldName2); + } + if (FieldName3 != 0) { + output.WriteRawTag(152, 25); + output.WriteInt32(FieldName3); + } + if (FieldName4 != 0) { + output.WriteRawTag(160, 25); + output.WriteInt32(FieldName4); + } + if (Field0Name5 != 0) { + output.WriteRawTag(168, 25); + output.WriteInt32(Field0Name5); + } + if (Field0Name6 != 0) { + output.WriteRawTag(176, 25); + output.WriteInt32(Field0Name6); + } + if (FieldName7 != 0) { + output.WriteRawTag(184, 25); + output.WriteInt32(FieldName7); + } + if (FieldName8 != 0) { + output.WriteRawTag(192, 25); + output.WriteInt32(FieldName8); + } + if (FieldName9 != 0) { + output.WriteRawTag(200, 25); + output.WriteInt32(FieldName9); + } + if (FieldName10 != 0) { + output.WriteRawTag(208, 25); + output.WriteInt32(FieldName10); + } + if (FIELDNAME11 != 0) { + output.WriteRawTag(216, 25); + output.WriteInt32(FIELDNAME11); + } + if (FIELDName12 != 0) { + output.WriteRawTag(224, 25); + output.WriteInt32(FIELDName12); + } + if (FieldName13 != 0) { + output.WriteRawTag(232, 25); + output.WriteInt32(FieldName13); + } + if (FieldName14 != 0) { + output.WriteRawTag(240, 25); + output.WriteInt32(FieldName14); + } + if (FieldName15 != 0) { + output.WriteRawTag(248, 25); + output.WriteInt32(FieldName15); + } + if (FieldName16 != 0) { + output.WriteRawTag(128, 26); + output.WriteInt32(FieldName16); + } + if (FieldName17 != 0) { + output.WriteRawTag(136, 26); + output.WriteInt32(FieldName17); + } + if (FieldName18 != 0) { + output.WriteRawTag(144, 26); + output.WriteInt32(FieldName18); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (OptionalInt32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32); + } + if (OptionalInt64 != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(OptionalInt64); + } + if (OptionalUint32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(OptionalUint32); + } + if (OptionalUint64 != 0UL) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(OptionalUint64); + } + if (OptionalSint32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeSInt32Size(OptionalSint32); + } + if (OptionalSint64 != 0L) { + size += 1 + pb::CodedOutputStream.ComputeSInt64Size(OptionalSint64); + } + if (OptionalFixed32 != 0) { + size += 1 + 4; + } + if (OptionalFixed64 != 0UL) { + size += 1 + 8; + } + if (OptionalSfixed32 != 0) { + size += 1 + 4; + } + if (OptionalSfixed64 != 0L) { + size += 1 + 8; + } + if (OptionalFloat != 0F) { + size += 1 + 4; + } + if (OptionalDouble != 0D) { + size += 1 + 8; + } + if (OptionalBool != false) { + size += 1 + 1; + } + if (OptionalString.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(OptionalString); + } + if (OptionalBytes.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(OptionalBytes); + } + if (optionalNestedMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage); + } + if (optionalForeignMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalForeignMessage); + } + if (OptionalNestedEnum != global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum.Foo) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalNestedEnum); + } + if (OptionalForeignEnum != global::ProtobufTestMessages.Proto3.ForeignEnum.ForeignFoo) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalForeignEnum); + } + if (OptionalAliasedEnum != global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum.AliasFoo) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalAliasedEnum); + } + if (OptionalStringPiece.Length != 0) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalStringPiece); + } + if (OptionalCord.Length != 0) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalCord); + } + if (recursiveMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(RecursiveMessage); + } + size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec); + size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec); + size += repeatedUint32_.CalculateSize(_repeated_repeatedUint32_codec); + size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec); + size += repeatedSint32_.CalculateSize(_repeated_repeatedSint32_codec); + size += repeatedSint64_.CalculateSize(_repeated_repeatedSint64_codec); + size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec); + size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec); + size += repeatedSfixed32_.CalculateSize(_repeated_repeatedSfixed32_codec); + size += repeatedSfixed64_.CalculateSize(_repeated_repeatedSfixed64_codec); + size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec); + size += repeatedDouble_.CalculateSize(_repeated_repeatedDouble_codec); + size += repeatedBool_.CalculateSize(_repeated_repeatedBool_codec); + size += repeatedString_.CalculateSize(_repeated_repeatedString_codec); + size += repeatedBytes_.CalculateSize(_repeated_repeatedBytes_codec); + size += repeatedNestedMessage_.CalculateSize(_repeated_repeatedNestedMessage_codec); + size += repeatedForeignMessage_.CalculateSize(_repeated_repeatedForeignMessage_codec); + size += repeatedNestedEnum_.CalculateSize(_repeated_repeatedNestedEnum_codec); + size += repeatedForeignEnum_.CalculateSize(_repeated_repeatedForeignEnum_codec); + size += repeatedStringPiece_.CalculateSize(_repeated_repeatedStringPiece_codec); + size += repeatedCord_.CalculateSize(_repeated_repeatedCord_codec); + size += packedInt32_.CalculateSize(_repeated_packedInt32_codec); + size += packedInt64_.CalculateSize(_repeated_packedInt64_codec); + size += packedUint32_.CalculateSize(_repeated_packedUint32_codec); + size += packedUint64_.CalculateSize(_repeated_packedUint64_codec); + size += packedSint32_.CalculateSize(_repeated_packedSint32_codec); + size += packedSint64_.CalculateSize(_repeated_packedSint64_codec); + size += packedFixed32_.CalculateSize(_repeated_packedFixed32_codec); + size += packedFixed64_.CalculateSize(_repeated_packedFixed64_codec); + size += packedSfixed32_.CalculateSize(_repeated_packedSfixed32_codec); + size += packedSfixed64_.CalculateSize(_repeated_packedSfixed64_codec); + size += packedFloat_.CalculateSize(_repeated_packedFloat_codec); + size += packedDouble_.CalculateSize(_repeated_packedDouble_codec); + size += packedBool_.CalculateSize(_repeated_packedBool_codec); + size += packedNestedEnum_.CalculateSize(_repeated_packedNestedEnum_codec); + size += unpackedInt32_.CalculateSize(_repeated_unpackedInt32_codec); + size += unpackedInt64_.CalculateSize(_repeated_unpackedInt64_codec); + size += unpackedUint32_.CalculateSize(_repeated_unpackedUint32_codec); + size += unpackedUint64_.CalculateSize(_repeated_unpackedUint64_codec); + size += unpackedSint32_.CalculateSize(_repeated_unpackedSint32_codec); + size += unpackedSint64_.CalculateSize(_repeated_unpackedSint64_codec); + size += unpackedFixed32_.CalculateSize(_repeated_unpackedFixed32_codec); + size += unpackedFixed64_.CalculateSize(_repeated_unpackedFixed64_codec); + size += unpackedSfixed32_.CalculateSize(_repeated_unpackedSfixed32_codec); + size += unpackedSfixed64_.CalculateSize(_repeated_unpackedSfixed64_codec); + size += unpackedFloat_.CalculateSize(_repeated_unpackedFloat_codec); + size += unpackedDouble_.CalculateSize(_repeated_unpackedDouble_codec); + size += unpackedBool_.CalculateSize(_repeated_unpackedBool_codec); + size += unpackedNestedEnum_.CalculateSize(_repeated_unpackedNestedEnum_codec); + size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec); + size += mapInt64Int64_.CalculateSize(_map_mapInt64Int64_codec); + size += mapUint32Uint32_.CalculateSize(_map_mapUint32Uint32_codec); + size += mapUint64Uint64_.CalculateSize(_map_mapUint64Uint64_codec); + size += mapSint32Sint32_.CalculateSize(_map_mapSint32Sint32_codec); + size += mapSint64Sint64_.CalculateSize(_map_mapSint64Sint64_codec); + size += mapFixed32Fixed32_.CalculateSize(_map_mapFixed32Fixed32_codec); + size += mapFixed64Fixed64_.CalculateSize(_map_mapFixed64Fixed64_codec); + size += mapSfixed32Sfixed32_.CalculateSize(_map_mapSfixed32Sfixed32_codec); + size += mapSfixed64Sfixed64_.CalculateSize(_map_mapSfixed64Sfixed64_codec); + size += mapInt32Float_.CalculateSize(_map_mapInt32Float_codec); + size += mapInt32Double_.CalculateSize(_map_mapInt32Double_codec); + size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec); + size += mapStringString_.CalculateSize(_map_mapStringString_codec); + size += mapStringBytes_.CalculateSize(_map_mapStringBytes_codec); + size += mapStringNestedMessage_.CalculateSize(_map_mapStringNestedMessage_codec); + size += mapStringForeignMessage_.CalculateSize(_map_mapStringForeignMessage_codec); + size += mapStringNestedEnum_.CalculateSize(_map_mapStringNestedEnum_codec); + size += mapStringForeignEnum_.CalculateSize(_map_mapStringForeignEnum_codec); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { + size += 2 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OneofNestedMessage); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OneofString); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { + size += 2 + pb::CodedOutputStream.ComputeBytesSize(OneofBytes); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBool) { + size += 2 + 1; + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint64) { + size += 2 + pb::CodedOutputStream.ComputeUInt64Size(OneofUint64); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) { + size += 2 + 4; + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) { + size += 2 + 8; + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OneofEnum); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OneofNullValue); + } + if (optionalBoolWrapper_ != null) { + size += _single_optionalBoolWrapper_codec.CalculateSizeWithTag(OptionalBoolWrapper); + } + if (optionalInt32Wrapper_ != null) { + size += _single_optionalInt32Wrapper_codec.CalculateSizeWithTag(OptionalInt32Wrapper); + } + if (optionalInt64Wrapper_ != null) { + size += _single_optionalInt64Wrapper_codec.CalculateSizeWithTag(OptionalInt64Wrapper); + } + if (optionalUint32Wrapper_ != null) { + size += _single_optionalUint32Wrapper_codec.CalculateSizeWithTag(OptionalUint32Wrapper); + } + if (optionalUint64Wrapper_ != null) { + size += _single_optionalUint64Wrapper_codec.CalculateSizeWithTag(OptionalUint64Wrapper); + } + if (optionalFloatWrapper_ != null) { + size += _single_optionalFloatWrapper_codec.CalculateSizeWithTag(OptionalFloatWrapper); + } + if (optionalDoubleWrapper_ != null) { + size += _single_optionalDoubleWrapper_codec.CalculateSizeWithTag(OptionalDoubleWrapper); + } + if (optionalStringWrapper_ != null) { + size += _single_optionalStringWrapper_codec.CalculateSizeWithTag(OptionalStringWrapper); + } + if (optionalBytesWrapper_ != null) { + size += _single_optionalBytesWrapper_codec.CalculateSizeWithTag(OptionalBytesWrapper); + } + size += repeatedBoolWrapper_.CalculateSize(_repeated_repeatedBoolWrapper_codec); + size += repeatedInt32Wrapper_.CalculateSize(_repeated_repeatedInt32Wrapper_codec); + size += repeatedInt64Wrapper_.CalculateSize(_repeated_repeatedInt64Wrapper_codec); + size += repeatedUint32Wrapper_.CalculateSize(_repeated_repeatedUint32Wrapper_codec); + size += repeatedUint64Wrapper_.CalculateSize(_repeated_repeatedUint64Wrapper_codec); + size += repeatedFloatWrapper_.CalculateSize(_repeated_repeatedFloatWrapper_codec); + size += repeatedDoubleWrapper_.CalculateSize(_repeated_repeatedDoubleWrapper_codec); + size += repeatedStringWrapper_.CalculateSize(_repeated_repeatedStringWrapper_codec); + size += repeatedBytesWrapper_.CalculateSize(_repeated_repeatedBytesWrapper_codec); + if (optionalDuration_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalDuration); + } + if (optionalTimestamp_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalTimestamp); + } + if (optionalFieldMask_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalFieldMask); + } + if (optionalStruct_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalStruct); + } + if (optionalAny_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalAny); + } + if (optionalValue_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalValue); + } + if (OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalNullValue); + } + size += repeatedDuration_.CalculateSize(_repeated_repeatedDuration_codec); + size += repeatedTimestamp_.CalculateSize(_repeated_repeatedTimestamp_codec); + size += repeatedFieldmask_.CalculateSize(_repeated_repeatedFieldmask_codec); + size += repeatedStruct_.CalculateSize(_repeated_repeatedStruct_codec); + size += repeatedAny_.CalculateSize(_repeated_repeatedAny_codec); + size += repeatedValue_.CalculateSize(_repeated_repeatedValue_codec); + size += repeatedListValue_.CalculateSize(_repeated_repeatedListValue_codec); + if (Fieldname1 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Fieldname1); + } + if (FieldName2 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName2); + } + if (FieldName3 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName3); + } + if (FieldName4 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName4); + } + if (Field0Name5 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field0Name5); + } + if (Field0Name6 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field0Name6); + } + if (FieldName7 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName7); + } + if (FieldName8 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName8); + } + if (FieldName9 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName9); + } + if (FieldName10 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName10); + } + if (FIELDNAME11 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FIELDNAME11); + } + if (FIELDName12 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FIELDName12); + } + if (FieldName13 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName13); + } + if (FieldName14 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName14); + } + if (FieldName15 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName15); + } + if (FieldName16 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName16); + } + if (FieldName17 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName17); + } + if (FieldName18 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName18); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestAllTypesProto3 other) { + if (other == null) { + return; + } + if (other.OptionalInt32 != 0) { + OptionalInt32 = other.OptionalInt32; + } + if (other.OptionalInt64 != 0L) { + OptionalInt64 = other.OptionalInt64; + } + if (other.OptionalUint32 != 0) { + OptionalUint32 = other.OptionalUint32; + } + if (other.OptionalUint64 != 0UL) { + OptionalUint64 = other.OptionalUint64; + } + if (other.OptionalSint32 != 0) { + OptionalSint32 = other.OptionalSint32; + } + if (other.OptionalSint64 != 0L) { + OptionalSint64 = other.OptionalSint64; + } + if (other.OptionalFixed32 != 0) { + OptionalFixed32 = other.OptionalFixed32; + } + if (other.OptionalFixed64 != 0UL) { + OptionalFixed64 = other.OptionalFixed64; + } + if (other.OptionalSfixed32 != 0) { + OptionalSfixed32 = other.OptionalSfixed32; + } + if (other.OptionalSfixed64 != 0L) { + OptionalSfixed64 = other.OptionalSfixed64; + } + if (other.OptionalFloat != 0F) { + OptionalFloat = other.OptionalFloat; + } + if (other.OptionalDouble != 0D) { + OptionalDouble = other.OptionalDouble; + } + if (other.OptionalBool != false) { + OptionalBool = other.OptionalBool; + } + if (other.OptionalString.Length != 0) { + OptionalString = other.OptionalString; + } + if (other.OptionalBytes.Length != 0) { + OptionalBytes = other.OptionalBytes; + } + if (other.optionalNestedMessage_ != null) { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage(); + } + OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage); + } + if (other.optionalForeignMessage_ != null) { + if (optionalForeignMessage_ == null) { + OptionalForeignMessage = new global::ProtobufTestMessages.Proto3.ForeignMessage(); + } + OptionalForeignMessage.MergeFrom(other.OptionalForeignMessage); + } + if (other.OptionalNestedEnum != global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum.Foo) { + OptionalNestedEnum = other.OptionalNestedEnum; + } + if (other.OptionalForeignEnum != global::ProtobufTestMessages.Proto3.ForeignEnum.ForeignFoo) { + OptionalForeignEnum = other.OptionalForeignEnum; + } + if (other.OptionalAliasedEnum != global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum.AliasFoo) { + OptionalAliasedEnum = other.OptionalAliasedEnum; + } + if (other.OptionalStringPiece.Length != 0) { + OptionalStringPiece = other.OptionalStringPiece; + } + if (other.OptionalCord.Length != 0) { + OptionalCord = other.OptionalCord; + } + if (other.recursiveMessage_ != null) { + if (recursiveMessage_ == null) { + RecursiveMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3(); + } + RecursiveMessage.MergeFrom(other.RecursiveMessage); + } + repeatedInt32_.Add(other.repeatedInt32_); + repeatedInt64_.Add(other.repeatedInt64_); + repeatedUint32_.Add(other.repeatedUint32_); + repeatedUint64_.Add(other.repeatedUint64_); + repeatedSint32_.Add(other.repeatedSint32_); + repeatedSint64_.Add(other.repeatedSint64_); + repeatedFixed32_.Add(other.repeatedFixed32_); + repeatedFixed64_.Add(other.repeatedFixed64_); + repeatedSfixed32_.Add(other.repeatedSfixed32_); + repeatedSfixed64_.Add(other.repeatedSfixed64_); + repeatedFloat_.Add(other.repeatedFloat_); + repeatedDouble_.Add(other.repeatedDouble_); + repeatedBool_.Add(other.repeatedBool_); + repeatedString_.Add(other.repeatedString_); + repeatedBytes_.Add(other.repeatedBytes_); + repeatedNestedMessage_.Add(other.repeatedNestedMessage_); + repeatedForeignMessage_.Add(other.repeatedForeignMessage_); + repeatedNestedEnum_.Add(other.repeatedNestedEnum_); + repeatedForeignEnum_.Add(other.repeatedForeignEnum_); + repeatedStringPiece_.Add(other.repeatedStringPiece_); + repeatedCord_.Add(other.repeatedCord_); + packedInt32_.Add(other.packedInt32_); + packedInt64_.Add(other.packedInt64_); + packedUint32_.Add(other.packedUint32_); + packedUint64_.Add(other.packedUint64_); + packedSint32_.Add(other.packedSint32_); + packedSint64_.Add(other.packedSint64_); + packedFixed32_.Add(other.packedFixed32_); + packedFixed64_.Add(other.packedFixed64_); + packedSfixed32_.Add(other.packedSfixed32_); + packedSfixed64_.Add(other.packedSfixed64_); + packedFloat_.Add(other.packedFloat_); + packedDouble_.Add(other.packedDouble_); + packedBool_.Add(other.packedBool_); + packedNestedEnum_.Add(other.packedNestedEnum_); + unpackedInt32_.Add(other.unpackedInt32_); + unpackedInt64_.Add(other.unpackedInt64_); + unpackedUint32_.Add(other.unpackedUint32_); + unpackedUint64_.Add(other.unpackedUint64_); + unpackedSint32_.Add(other.unpackedSint32_); + unpackedSint64_.Add(other.unpackedSint64_); + unpackedFixed32_.Add(other.unpackedFixed32_); + unpackedFixed64_.Add(other.unpackedFixed64_); + unpackedSfixed32_.Add(other.unpackedSfixed32_); + unpackedSfixed64_.Add(other.unpackedSfixed64_); + unpackedFloat_.Add(other.unpackedFloat_); + unpackedDouble_.Add(other.unpackedDouble_); + unpackedBool_.Add(other.unpackedBool_); + unpackedNestedEnum_.Add(other.unpackedNestedEnum_); + mapInt32Int32_.Add(other.mapInt32Int32_); + mapInt64Int64_.Add(other.mapInt64Int64_); + mapUint32Uint32_.Add(other.mapUint32Uint32_); + mapUint64Uint64_.Add(other.mapUint64Uint64_); + mapSint32Sint32_.Add(other.mapSint32Sint32_); + mapSint64Sint64_.Add(other.mapSint64Sint64_); + mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_); + mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_); + mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_); + mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_); + mapInt32Float_.Add(other.mapInt32Float_); + mapInt32Double_.Add(other.mapInt32Double_); + mapBoolBool_.Add(other.mapBoolBool_); + mapStringString_.Add(other.mapStringString_); + mapStringBytes_.Add(other.mapStringBytes_); + mapStringNestedMessage_.Add(other.mapStringNestedMessage_); + mapStringForeignMessage_.Add(other.mapStringForeignMessage_); + mapStringNestedEnum_.Add(other.mapStringNestedEnum_); + mapStringForeignEnum_.Add(other.mapStringForeignEnum_); + if (other.optionalBoolWrapper_ != null) { + if (optionalBoolWrapper_ == null || other.OptionalBoolWrapper != false) { + OptionalBoolWrapper = other.OptionalBoolWrapper; + } + } + if (other.optionalInt32Wrapper_ != null) { + if (optionalInt32Wrapper_ == null || other.OptionalInt32Wrapper != 0) { + OptionalInt32Wrapper = other.OptionalInt32Wrapper; + } + } + if (other.optionalInt64Wrapper_ != null) { + if (optionalInt64Wrapper_ == null || other.OptionalInt64Wrapper != 0L) { + OptionalInt64Wrapper = other.OptionalInt64Wrapper; + } + } + if (other.optionalUint32Wrapper_ != null) { + if (optionalUint32Wrapper_ == null || other.OptionalUint32Wrapper != 0) { + OptionalUint32Wrapper = other.OptionalUint32Wrapper; + } + } + if (other.optionalUint64Wrapper_ != null) { + if (optionalUint64Wrapper_ == null || other.OptionalUint64Wrapper != 0UL) { + OptionalUint64Wrapper = other.OptionalUint64Wrapper; + } + } + if (other.optionalFloatWrapper_ != null) { + if (optionalFloatWrapper_ == null || other.OptionalFloatWrapper != 0F) { + OptionalFloatWrapper = other.OptionalFloatWrapper; + } + } + if (other.optionalDoubleWrapper_ != null) { + if (optionalDoubleWrapper_ == null || other.OptionalDoubleWrapper != 0D) { + OptionalDoubleWrapper = other.OptionalDoubleWrapper; + } + } + if (other.optionalStringWrapper_ != null) { + if (optionalStringWrapper_ == null || other.OptionalStringWrapper != "") { + OptionalStringWrapper = other.OptionalStringWrapper; + } + } + if (other.optionalBytesWrapper_ != null) { + if (optionalBytesWrapper_ == null || other.OptionalBytesWrapper != pb::ByteString.Empty) { + OptionalBytesWrapper = other.OptionalBytesWrapper; + } + } + repeatedBoolWrapper_.Add(other.repeatedBoolWrapper_); + repeatedInt32Wrapper_.Add(other.repeatedInt32Wrapper_); + repeatedInt64Wrapper_.Add(other.repeatedInt64Wrapper_); + repeatedUint32Wrapper_.Add(other.repeatedUint32Wrapper_); + repeatedUint64Wrapper_.Add(other.repeatedUint64Wrapper_); + repeatedFloatWrapper_.Add(other.repeatedFloatWrapper_); + repeatedDoubleWrapper_.Add(other.repeatedDoubleWrapper_); + repeatedStringWrapper_.Add(other.repeatedStringWrapper_); + repeatedBytesWrapper_.Add(other.repeatedBytesWrapper_); + if (other.optionalDuration_ != null) { + if (optionalDuration_ == null) { + OptionalDuration = new global::Google.Protobuf.WellKnownTypes.Duration(); + } + OptionalDuration.MergeFrom(other.OptionalDuration); + } + if (other.optionalTimestamp_ != null) { + if (optionalTimestamp_ == null) { + OptionalTimestamp = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + } + OptionalTimestamp.MergeFrom(other.OptionalTimestamp); + } + if (other.optionalFieldMask_ != null) { + if (optionalFieldMask_ == null) { + OptionalFieldMask = new global::Google.Protobuf.WellKnownTypes.FieldMask(); + } + OptionalFieldMask.MergeFrom(other.OptionalFieldMask); + } + if (other.optionalStruct_ != null) { + if (optionalStruct_ == null) { + OptionalStruct = new global::Google.Protobuf.WellKnownTypes.Struct(); + } + OptionalStruct.MergeFrom(other.OptionalStruct); + } + if (other.optionalAny_ != null) { + if (optionalAny_ == null) { + OptionalAny = new global::Google.Protobuf.WellKnownTypes.Any(); + } + OptionalAny.MergeFrom(other.OptionalAny); + } + if (other.optionalValue_ != null) { + if (optionalValue_ == null) { + OptionalValue = new global::Google.Protobuf.WellKnownTypes.Value(); + } + OptionalValue.MergeFrom(other.OptionalValue); + } + if (other.OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + OptionalNullValue = other.OptionalNullValue; + } + repeatedDuration_.Add(other.repeatedDuration_); + repeatedTimestamp_.Add(other.repeatedTimestamp_); + repeatedFieldmask_.Add(other.repeatedFieldmask_); + repeatedStruct_.Add(other.repeatedStruct_); + repeatedAny_.Add(other.repeatedAny_); + repeatedValue_.Add(other.repeatedValue_); + repeatedListValue_.Add(other.repeatedListValue_); + if (other.Fieldname1 != 0) { + Fieldname1 = other.Fieldname1; + } + if (other.FieldName2 != 0) { + FieldName2 = other.FieldName2; + } + if (other.FieldName3 != 0) { + FieldName3 = other.FieldName3; + } + if (other.FieldName4 != 0) { + FieldName4 = other.FieldName4; + } + if (other.Field0Name5 != 0) { + Field0Name5 = other.Field0Name5; + } + if (other.Field0Name6 != 0) { + Field0Name6 = other.Field0Name6; + } + if (other.FieldName7 != 0) { + FieldName7 = other.FieldName7; + } + if (other.FieldName8 != 0) { + FieldName8 = other.FieldName8; + } + if (other.FieldName9 != 0) { + FieldName9 = other.FieldName9; + } + if (other.FieldName10 != 0) { + FieldName10 = other.FieldName10; + } + if (other.FIELDNAME11 != 0) { + FIELDNAME11 = other.FIELDNAME11; + } + if (other.FIELDName12 != 0) { + FIELDName12 = other.FIELDName12; + } + if (other.FieldName13 != 0) { + FieldName13 = other.FieldName13; + } + if (other.FieldName14 != 0) { + FieldName14 = other.FieldName14; + } + if (other.FieldName15 != 0) { + FieldName15 = other.FieldName15; + } + if (other.FieldName16 != 0) { + FieldName16 = other.FieldName16; + } + if (other.FieldName17 != 0) { + FieldName17 = other.FieldName17; + } + if (other.FieldName18 != 0) { + FieldName18 = other.FieldName18; + } + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: + OneofUint32 = other.OneofUint32; + break; + case OneofFieldOneofCase.OneofNestedMessage: + if (OneofNestedMessage == null) { + OneofNestedMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage(); + } + OneofNestedMessage.MergeFrom(other.OneofNestedMessage); + break; + case OneofFieldOneofCase.OneofString: + OneofString = other.OneofString; + break; + case OneofFieldOneofCase.OneofBytes: + OneofBytes = other.OneofBytes; + break; + case OneofFieldOneofCase.OneofBool: + OneofBool = other.OneofBool; + break; + case OneofFieldOneofCase.OneofUint64: + OneofUint64 = other.OneofUint64; + break; + case OneofFieldOneofCase.OneofFloat: + OneofFloat = other.OneofFloat; + break; + case OneofFieldOneofCase.OneofDouble: + OneofDouble = other.OneofDouble; + break; + case OneofFieldOneofCase.OneofEnum: + OneofEnum = other.OneofEnum; + break; + case OneofFieldOneofCase.OneofNullValue: + OneofNullValue = other.OneofNullValue; + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + OptionalInt32 = input.ReadInt32(); + break; + } + case 16: { + OptionalInt64 = input.ReadInt64(); + break; + } + case 24: { + OptionalUint32 = input.ReadUInt32(); + break; + } + case 32: { + OptionalUint64 = input.ReadUInt64(); + break; + } + case 40: { + OptionalSint32 = input.ReadSInt32(); + break; + } + case 48: { + OptionalSint64 = input.ReadSInt64(); + break; + } + case 61: { + OptionalFixed32 = input.ReadFixed32(); + break; + } + case 65: { + OptionalFixed64 = input.ReadFixed64(); + break; + } + case 77: { + OptionalSfixed32 = input.ReadSFixed32(); + break; + } + case 81: { + OptionalSfixed64 = input.ReadSFixed64(); + break; + } + case 93: { + OptionalFloat = input.ReadFloat(); + break; + } + case 97: { + OptionalDouble = input.ReadDouble(); + break; + } + case 104: { + OptionalBool = input.ReadBool(); + break; + } + case 114: { + OptionalString = input.ReadString(); + break; + } + case 122: { + OptionalBytes = input.ReadBytes(); + break; + } + case 146: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + case 154: { + if (optionalForeignMessage_ == null) { + OptionalForeignMessage = new global::ProtobufTestMessages.Proto3.ForeignMessage(); + } + input.ReadMessage(OptionalForeignMessage); + break; + } + case 168: { + OptionalNestedEnum = (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) input.ReadEnum(); + break; + } + case 176: { + OptionalForeignEnum = (global::ProtobufTestMessages.Proto3.ForeignEnum) input.ReadEnum(); + break; + } + case 184: { + OptionalAliasedEnum = (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum) input.ReadEnum(); + break; + } + case 194: { + OptionalStringPiece = input.ReadString(); + break; + } + case 202: { + OptionalCord = input.ReadString(); + break; + } + case 218: { + if (recursiveMessage_ == null) { + RecursiveMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3(); + } + input.ReadMessage(RecursiveMessage); + break; + } + case 250: + case 248: { + repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); + break; + } + case 258: + case 256: { + repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec); + break; + } + case 266: + case 264: { + repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec); + break; + } + case 274: + case 272: { + repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec); + break; + } + case 282: + case 280: { + repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec); + break; + } + case 290: + case 288: { + repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec); + break; + } + case 298: + case 301: { + repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec); + break; + } + case 306: + case 305: { + repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec); + break; + } + case 314: + case 317: { + repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec); + break; + } + case 322: + case 321: { + repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec); + break; + } + case 330: + case 333: { + repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec); + break; + } + case 338: + case 337: { + repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec); + break; + } + case 346: + case 344: { + repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec); + break; + } + case 354: { + repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec); + break; + } + case 362: { + repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec); + break; + } + case 386: { + repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec); + break; + } + case 394: { + repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec); + break; + } + case 410: + case 408: { + repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec); + break; + } + case 418: + case 416: { + repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec); + break; + } + case 434: { + repeatedStringPiece_.AddEntriesFrom(input, _repeated_repeatedStringPiece_codec); + break; + } + case 442: { + repeatedCord_.AddEntriesFrom(input, _repeated_repeatedCord_codec); + break; + } + case 450: { + mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec); + break; + } + case 458: { + mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec); + break; + } + case 466: { + mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec); + break; + } + case 474: { + mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec); + break; + } + case 482: { + mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec); + break; + } + case 490: { + mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec); + break; + } + case 498: { + mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec); + break; + } + case 506: { + mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec); + break; + } + case 514: { + mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec); + break; + } + case 522: { + mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec); + break; + } + case 530: { + mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec); + break; + } + case 538: { + mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec); + break; + } + case 546: { + mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec); + break; + } + case 554: { + mapStringString_.AddEntriesFrom(input, _map_mapStringString_codec); + break; + } + case 562: { + mapStringBytes_.AddEntriesFrom(input, _map_mapStringBytes_codec); + break; + } + case 570: { + mapStringNestedMessage_.AddEntriesFrom(input, _map_mapStringNestedMessage_codec); + break; + } + case 578: { + mapStringForeignMessage_.AddEntriesFrom(input, _map_mapStringForeignMessage_codec); + break; + } + case 586: { + mapStringNestedEnum_.AddEntriesFrom(input, _map_mapStringNestedEnum_codec); + break; + } + case 594: { + mapStringForeignEnum_.AddEntriesFrom(input, _map_mapStringForeignEnum_codec); + break; + } + case 602: + case 600: { + packedInt32_.AddEntriesFrom(input, _repeated_packedInt32_codec); + break; + } + case 610: + case 608: { + packedInt64_.AddEntriesFrom(input, _repeated_packedInt64_codec); + break; + } + case 618: + case 616: { + packedUint32_.AddEntriesFrom(input, _repeated_packedUint32_codec); + break; + } + case 626: + case 624: { + packedUint64_.AddEntriesFrom(input, _repeated_packedUint64_codec); + break; + } + case 634: + case 632: { + packedSint32_.AddEntriesFrom(input, _repeated_packedSint32_codec); + break; + } + case 642: + case 640: { + packedSint64_.AddEntriesFrom(input, _repeated_packedSint64_codec); + break; + } + case 650: + case 653: { + packedFixed32_.AddEntriesFrom(input, _repeated_packedFixed32_codec); + break; + } + case 658: + case 657: { + packedFixed64_.AddEntriesFrom(input, _repeated_packedFixed64_codec); + break; + } + case 666: + case 669: { + packedSfixed32_.AddEntriesFrom(input, _repeated_packedSfixed32_codec); + break; + } + case 674: + case 673: { + packedSfixed64_.AddEntriesFrom(input, _repeated_packedSfixed64_codec); + break; + } + case 682: + case 685: { + packedFloat_.AddEntriesFrom(input, _repeated_packedFloat_codec); + break; + } + case 690: + case 689: { + packedDouble_.AddEntriesFrom(input, _repeated_packedDouble_codec); + break; + } + case 698: + case 696: { + packedBool_.AddEntriesFrom(input, _repeated_packedBool_codec); + break; + } + case 706: + case 704: { + packedNestedEnum_.AddEntriesFrom(input, _repeated_packedNestedEnum_codec); + break; + } + case 714: + case 712: { + unpackedInt32_.AddEntriesFrom(input, _repeated_unpackedInt32_codec); + break; + } + case 722: + case 720: { + unpackedInt64_.AddEntriesFrom(input, _repeated_unpackedInt64_codec); + break; + } + case 730: + case 728: { + unpackedUint32_.AddEntriesFrom(input, _repeated_unpackedUint32_codec); + break; + } + case 738: + case 736: { + unpackedUint64_.AddEntriesFrom(input, _repeated_unpackedUint64_codec); + break; + } + case 746: + case 744: { + unpackedSint32_.AddEntriesFrom(input, _repeated_unpackedSint32_codec); + break; + } + case 754: + case 752: { + unpackedSint64_.AddEntriesFrom(input, _repeated_unpackedSint64_codec); + break; + } + case 762: + case 765: { + unpackedFixed32_.AddEntriesFrom(input, _repeated_unpackedFixed32_codec); + break; + } + case 770: + case 769: { + unpackedFixed64_.AddEntriesFrom(input, _repeated_unpackedFixed64_codec); + break; + } + case 778: + case 781: { + unpackedSfixed32_.AddEntriesFrom(input, _repeated_unpackedSfixed32_codec); + break; + } + case 786: + case 785: { + unpackedSfixed64_.AddEntriesFrom(input, _repeated_unpackedSfixed64_codec); + break; + } + case 794: + case 797: { + unpackedFloat_.AddEntriesFrom(input, _repeated_unpackedFloat_codec); + break; + } + case 802: + case 801: { + unpackedDouble_.AddEntriesFrom(input, _repeated_unpackedDouble_codec); + break; + } + case 810: + case 808: { + unpackedBool_.AddEntriesFrom(input, _repeated_unpackedBool_codec); + break; + } + case 818: + case 816: { + unpackedNestedEnum_.AddEntriesFrom(input, _repeated_unpackedNestedEnum_codec); + break; + } + case 888: { + OneofUint32 = input.ReadUInt32(); + break; + } + case 898: { + global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage subBuilder = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + subBuilder.MergeFrom(OneofNestedMessage); + } + input.ReadMessage(subBuilder); + OneofNestedMessage = subBuilder; + break; + } + case 906: { + OneofString = input.ReadString(); + break; + } + case 914: { + OneofBytes = input.ReadBytes(); + break; + } + case 920: { + OneofBool = input.ReadBool(); + break; + } + case 928: { + OneofUint64 = input.ReadUInt64(); + break; + } + case 941: { + OneofFloat = input.ReadFloat(); + break; + } + case 945: { + OneofDouble = input.ReadDouble(); + break; + } + case 952: { + oneofField_ = input.ReadEnum(); + oneofFieldCase_ = OneofFieldOneofCase.OneofEnum; + break; + } + case 960: { + oneofField_ = input.ReadEnum(); + oneofFieldCase_ = OneofFieldOneofCase.OneofNullValue; + break; + } + case 1610: { + bool? value = _single_optionalBoolWrapper_codec.Read(input); + if (optionalBoolWrapper_ == null || value != false) { + OptionalBoolWrapper = value; + } + break; + } + case 1618: { + int? value = _single_optionalInt32Wrapper_codec.Read(input); + if (optionalInt32Wrapper_ == null || value != 0) { + OptionalInt32Wrapper = value; + } + break; + } + case 1626: { + long? value = _single_optionalInt64Wrapper_codec.Read(input); + if (optionalInt64Wrapper_ == null || value != 0L) { + OptionalInt64Wrapper = value; + } + break; + } + case 1634: { + uint? value = _single_optionalUint32Wrapper_codec.Read(input); + if (optionalUint32Wrapper_ == null || value != 0) { + OptionalUint32Wrapper = value; + } + break; + } + case 1642: { + ulong? value = _single_optionalUint64Wrapper_codec.Read(input); + if (optionalUint64Wrapper_ == null || value != 0UL) { + OptionalUint64Wrapper = value; + } + break; + } + case 1650: { + float? value = _single_optionalFloatWrapper_codec.Read(input); + if (optionalFloatWrapper_ == null || value != 0F) { + OptionalFloatWrapper = value; + } + break; + } + case 1658: { + double? value = _single_optionalDoubleWrapper_codec.Read(input); + if (optionalDoubleWrapper_ == null || value != 0D) { + OptionalDoubleWrapper = value; + } + break; + } + case 1666: { + string value = _single_optionalStringWrapper_codec.Read(input); + if (optionalStringWrapper_ == null || value != "") { + OptionalStringWrapper = value; + } + break; + } + case 1674: { + pb::ByteString value = _single_optionalBytesWrapper_codec.Read(input); + if (optionalBytesWrapper_ == null || value != pb::ByteString.Empty) { + OptionalBytesWrapper = value; + } + break; + } + case 1690: { + repeatedBoolWrapper_.AddEntriesFrom(input, _repeated_repeatedBoolWrapper_codec); + break; + } + case 1698: { + repeatedInt32Wrapper_.AddEntriesFrom(input, _repeated_repeatedInt32Wrapper_codec); + break; + } + case 1706: { + repeatedInt64Wrapper_.AddEntriesFrom(input, _repeated_repeatedInt64Wrapper_codec); + break; + } + case 1714: { + repeatedUint32Wrapper_.AddEntriesFrom(input, _repeated_repeatedUint32Wrapper_codec); + break; + } + case 1722: { + repeatedUint64Wrapper_.AddEntriesFrom(input, _repeated_repeatedUint64Wrapper_codec); + break; + } + case 1730: { + repeatedFloatWrapper_.AddEntriesFrom(input, _repeated_repeatedFloatWrapper_codec); + break; + } + case 1738: { + repeatedDoubleWrapper_.AddEntriesFrom(input, _repeated_repeatedDoubleWrapper_codec); + break; + } + case 1746: { + repeatedStringWrapper_.AddEntriesFrom(input, _repeated_repeatedStringWrapper_codec); + break; + } + case 1754: { + repeatedBytesWrapper_.AddEntriesFrom(input, _repeated_repeatedBytesWrapper_codec); + break; + } + case 2410: { + if (optionalDuration_ == null) { + OptionalDuration = new global::Google.Protobuf.WellKnownTypes.Duration(); + } + input.ReadMessage(OptionalDuration); + break; + } + case 2418: { + if (optionalTimestamp_ == null) { + OptionalTimestamp = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + } + input.ReadMessage(OptionalTimestamp); + break; + } + case 2426: { + if (optionalFieldMask_ == null) { + OptionalFieldMask = new global::Google.Protobuf.WellKnownTypes.FieldMask(); + } + input.ReadMessage(OptionalFieldMask); + break; + } + case 2434: { + if (optionalStruct_ == null) { + OptionalStruct = new global::Google.Protobuf.WellKnownTypes.Struct(); + } + input.ReadMessage(OptionalStruct); + break; + } + case 2442: { + if (optionalAny_ == null) { + OptionalAny = new global::Google.Protobuf.WellKnownTypes.Any(); + } + input.ReadMessage(OptionalAny); + break; + } + case 2450: { + if (optionalValue_ == null) { + OptionalValue = new global::Google.Protobuf.WellKnownTypes.Value(); + } + input.ReadMessage(OptionalValue); + break; + } + case 2456: { + OptionalNullValue = (global::Google.Protobuf.WellKnownTypes.NullValue) input.ReadEnum(); + break; + } + case 2490: { + repeatedDuration_.AddEntriesFrom(input, _repeated_repeatedDuration_codec); + break; + } + case 2498: { + repeatedTimestamp_.AddEntriesFrom(input, _repeated_repeatedTimestamp_codec); + break; + } + case 2506: { + repeatedFieldmask_.AddEntriesFrom(input, _repeated_repeatedFieldmask_codec); + break; + } + case 2522: { + repeatedAny_.AddEntriesFrom(input, _repeated_repeatedAny_codec); + break; + } + case 2530: { + repeatedValue_.AddEntriesFrom(input, _repeated_repeatedValue_codec); + break; + } + case 2538: { + repeatedListValue_.AddEntriesFrom(input, _repeated_repeatedListValue_codec); + break; + } + case 2594: { + repeatedStruct_.AddEntriesFrom(input, _repeated_repeatedStruct_codec); + break; + } + case 3208: { + Fieldname1 = input.ReadInt32(); + break; + } + case 3216: { + FieldName2 = input.ReadInt32(); + break; + } + case 3224: { + FieldName3 = input.ReadInt32(); + break; + } + case 3232: { + FieldName4 = input.ReadInt32(); + break; + } + case 3240: { + Field0Name5 = input.ReadInt32(); + break; + } + case 3248: { + Field0Name6 = input.ReadInt32(); + break; + } + case 3256: { + FieldName7 = input.ReadInt32(); + break; + } + case 3264: { + FieldName8 = input.ReadInt32(); + break; + } + case 3272: { + FieldName9 = input.ReadInt32(); + break; + } + case 3280: { + FieldName10 = input.ReadInt32(); + break; + } + case 3288: { + FIELDNAME11 = input.ReadInt32(); + break; + } + case 3296: { + FIELDName12 = input.ReadInt32(); + break; + } + case 3304: { + FieldName13 = input.ReadInt32(); + break; + } + case 3312: { + FieldName14 = input.ReadInt32(); + break; + } + case 3320: { + FieldName15 = input.ReadInt32(); + break; + } + case 3328: { + FieldName16 = input.ReadInt32(); + break; + } + case 3336: { + FieldName17 = input.ReadInt32(); + break; + } + case 3344: { + FieldName18 = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + OptionalInt32 = input.ReadInt32(); + break; + } + case 16: { + OptionalInt64 = input.ReadInt64(); + break; + } + case 24: { + OptionalUint32 = input.ReadUInt32(); + break; + } + case 32: { + OptionalUint64 = input.ReadUInt64(); + break; + } + case 40: { + OptionalSint32 = input.ReadSInt32(); + break; + } + case 48: { + OptionalSint64 = input.ReadSInt64(); + break; + } + case 61: { + OptionalFixed32 = input.ReadFixed32(); + break; + } + case 65: { + OptionalFixed64 = input.ReadFixed64(); + break; + } + case 77: { + OptionalSfixed32 = input.ReadSFixed32(); + break; + } + case 81: { + OptionalSfixed64 = input.ReadSFixed64(); + break; + } + case 93: { + OptionalFloat = input.ReadFloat(); + break; + } + case 97: { + OptionalDouble = input.ReadDouble(); + break; + } + case 104: { + OptionalBool = input.ReadBool(); + break; + } + case 114: { + OptionalString = input.ReadString(); + break; + } + case 122: { + OptionalBytes = input.ReadBytes(); + break; + } + case 146: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + case 154: { + if (optionalForeignMessage_ == null) { + OptionalForeignMessage = new global::ProtobufTestMessages.Proto3.ForeignMessage(); + } + input.ReadMessage(OptionalForeignMessage); + break; + } + case 168: { + OptionalNestedEnum = (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) input.ReadEnum(); + break; + } + case 176: { + OptionalForeignEnum = (global::ProtobufTestMessages.Proto3.ForeignEnum) input.ReadEnum(); + break; + } + case 184: { + OptionalAliasedEnum = (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum) input.ReadEnum(); + break; + } + case 194: { + OptionalStringPiece = input.ReadString(); + break; + } + case 202: { + OptionalCord = input.ReadString(); + break; + } + case 218: { + if (recursiveMessage_ == null) { + RecursiveMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3(); + } + input.ReadMessage(RecursiveMessage); + break; + } + case 250: + case 248: { + repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec); + break; + } + case 258: + case 256: { + repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec); + break; + } + case 266: + case 264: { + repeatedUint32_.AddEntriesFrom(ref input, _repeated_repeatedUint32_codec); + break; + } + case 274: + case 272: { + repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec); + break; + } + case 282: + case 280: { + repeatedSint32_.AddEntriesFrom(ref input, _repeated_repeatedSint32_codec); + break; + } + case 290: + case 288: { + repeatedSint64_.AddEntriesFrom(ref input, _repeated_repeatedSint64_codec); + break; + } + case 298: + case 301: { + repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec); + break; + } + case 306: + case 305: { + repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec); + break; + } + case 314: + case 317: { + repeatedSfixed32_.AddEntriesFrom(ref input, _repeated_repeatedSfixed32_codec); + break; + } + case 322: + case 321: { + repeatedSfixed64_.AddEntriesFrom(ref input, _repeated_repeatedSfixed64_codec); + break; + } + case 330: + case 333: { + repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec); + break; + } + case 338: + case 337: { + repeatedDouble_.AddEntriesFrom(ref input, _repeated_repeatedDouble_codec); + break; + } + case 346: + case 344: { + repeatedBool_.AddEntriesFrom(ref input, _repeated_repeatedBool_codec); + break; + } + case 354: { + repeatedString_.AddEntriesFrom(ref input, _repeated_repeatedString_codec); + break; + } + case 362: { + repeatedBytes_.AddEntriesFrom(ref input, _repeated_repeatedBytes_codec); + break; + } + case 386: { + repeatedNestedMessage_.AddEntriesFrom(ref input, _repeated_repeatedNestedMessage_codec); + break; + } + case 394: { + repeatedForeignMessage_.AddEntriesFrom(ref input, _repeated_repeatedForeignMessage_codec); + break; + } + case 410: + case 408: { + repeatedNestedEnum_.AddEntriesFrom(ref input, _repeated_repeatedNestedEnum_codec); + break; + } + case 418: + case 416: { + repeatedForeignEnum_.AddEntriesFrom(ref input, _repeated_repeatedForeignEnum_codec); + break; + } + case 434: { + repeatedStringPiece_.AddEntriesFrom(ref input, _repeated_repeatedStringPiece_codec); + break; + } + case 442: { + repeatedCord_.AddEntriesFrom(ref input, _repeated_repeatedCord_codec); + break; + } + case 450: { + mapInt32Int32_.AddEntriesFrom(ref input, _map_mapInt32Int32_codec); + break; + } + case 458: { + mapInt64Int64_.AddEntriesFrom(ref input, _map_mapInt64Int64_codec); + break; + } + case 466: { + mapUint32Uint32_.AddEntriesFrom(ref input, _map_mapUint32Uint32_codec); + break; + } + case 474: { + mapUint64Uint64_.AddEntriesFrom(ref input, _map_mapUint64Uint64_codec); + break; + } + case 482: { + mapSint32Sint32_.AddEntriesFrom(ref input, _map_mapSint32Sint32_codec); + break; + } + case 490: { + mapSint64Sint64_.AddEntriesFrom(ref input, _map_mapSint64Sint64_codec); + break; + } + case 498: { + mapFixed32Fixed32_.AddEntriesFrom(ref input, _map_mapFixed32Fixed32_codec); + break; + } + case 506: { + mapFixed64Fixed64_.AddEntriesFrom(ref input, _map_mapFixed64Fixed64_codec); + break; + } + case 514: { + mapSfixed32Sfixed32_.AddEntriesFrom(ref input, _map_mapSfixed32Sfixed32_codec); + break; + } + case 522: { + mapSfixed64Sfixed64_.AddEntriesFrom(ref input, _map_mapSfixed64Sfixed64_codec); + break; + } + case 530: { + mapInt32Float_.AddEntriesFrom(ref input, _map_mapInt32Float_codec); + break; + } + case 538: { + mapInt32Double_.AddEntriesFrom(ref input, _map_mapInt32Double_codec); + break; + } + case 546: { + mapBoolBool_.AddEntriesFrom(ref input, _map_mapBoolBool_codec); + break; + } + case 554: { + mapStringString_.AddEntriesFrom(ref input, _map_mapStringString_codec); + break; + } + case 562: { + mapStringBytes_.AddEntriesFrom(ref input, _map_mapStringBytes_codec); + break; + } + case 570: { + mapStringNestedMessage_.AddEntriesFrom(ref input, _map_mapStringNestedMessage_codec); + break; + } + case 578: { + mapStringForeignMessage_.AddEntriesFrom(ref input, _map_mapStringForeignMessage_codec); + break; + } + case 586: { + mapStringNestedEnum_.AddEntriesFrom(ref input, _map_mapStringNestedEnum_codec); + break; + } + case 594: { + mapStringForeignEnum_.AddEntriesFrom(ref input, _map_mapStringForeignEnum_codec); + break; + } + case 602: + case 600: { + packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec); + break; + } + case 610: + case 608: { + packedInt64_.AddEntriesFrom(ref input, _repeated_packedInt64_codec); + break; + } + case 618: + case 616: { + packedUint32_.AddEntriesFrom(ref input, _repeated_packedUint32_codec); + break; + } + case 626: + case 624: { + packedUint64_.AddEntriesFrom(ref input, _repeated_packedUint64_codec); + break; + } + case 634: + case 632: { + packedSint32_.AddEntriesFrom(ref input, _repeated_packedSint32_codec); + break; + } + case 642: + case 640: { + packedSint64_.AddEntriesFrom(ref input, _repeated_packedSint64_codec); + break; + } + case 650: + case 653: { + packedFixed32_.AddEntriesFrom(ref input, _repeated_packedFixed32_codec); + break; + } + case 658: + case 657: { + packedFixed64_.AddEntriesFrom(ref input, _repeated_packedFixed64_codec); + break; + } + case 666: + case 669: { + packedSfixed32_.AddEntriesFrom(ref input, _repeated_packedSfixed32_codec); + break; + } + case 674: + case 673: { + packedSfixed64_.AddEntriesFrom(ref input, _repeated_packedSfixed64_codec); + break; + } + case 682: + case 685: { + packedFloat_.AddEntriesFrom(ref input, _repeated_packedFloat_codec); + break; + } + case 690: + case 689: { + packedDouble_.AddEntriesFrom(ref input, _repeated_packedDouble_codec); + break; + } + case 698: + case 696: { + packedBool_.AddEntriesFrom(ref input, _repeated_packedBool_codec); + break; + } + case 706: + case 704: { + packedNestedEnum_.AddEntriesFrom(ref input, _repeated_packedNestedEnum_codec); + break; + } + case 714: + case 712: { + unpackedInt32_.AddEntriesFrom(ref input, _repeated_unpackedInt32_codec); + break; + } + case 722: + case 720: { + unpackedInt64_.AddEntriesFrom(ref input, _repeated_unpackedInt64_codec); + break; + } + case 730: + case 728: { + unpackedUint32_.AddEntriesFrom(ref input, _repeated_unpackedUint32_codec); + break; + } + case 738: + case 736: { + unpackedUint64_.AddEntriesFrom(ref input, _repeated_unpackedUint64_codec); + break; + } + case 746: + case 744: { + unpackedSint32_.AddEntriesFrom(ref input, _repeated_unpackedSint32_codec); + break; + } + case 754: + case 752: { + unpackedSint64_.AddEntriesFrom(ref input, _repeated_unpackedSint64_codec); + break; + } + case 762: + case 765: { + unpackedFixed32_.AddEntriesFrom(ref input, _repeated_unpackedFixed32_codec); + break; + } + case 770: + case 769: { + unpackedFixed64_.AddEntriesFrom(ref input, _repeated_unpackedFixed64_codec); + break; + } + case 778: + case 781: { + unpackedSfixed32_.AddEntriesFrom(ref input, _repeated_unpackedSfixed32_codec); + break; + } + case 786: + case 785: { + unpackedSfixed64_.AddEntriesFrom(ref input, _repeated_unpackedSfixed64_codec); + break; + } + case 794: + case 797: { + unpackedFloat_.AddEntriesFrom(ref input, _repeated_unpackedFloat_codec); + break; + } + case 802: + case 801: { + unpackedDouble_.AddEntriesFrom(ref input, _repeated_unpackedDouble_codec); + break; + } + case 810: + case 808: { + unpackedBool_.AddEntriesFrom(ref input, _repeated_unpackedBool_codec); + break; + } + case 818: + case 816: { + unpackedNestedEnum_.AddEntriesFrom(ref input, _repeated_unpackedNestedEnum_codec); + break; + } + case 888: { + OneofUint32 = input.ReadUInt32(); + break; + } + case 898: { + global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage subBuilder = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + subBuilder.MergeFrom(OneofNestedMessage); + } + input.ReadMessage(subBuilder); + OneofNestedMessage = subBuilder; + break; + } + case 906: { + OneofString = input.ReadString(); + break; + } + case 914: { + OneofBytes = input.ReadBytes(); + break; + } + case 920: { + OneofBool = input.ReadBool(); + break; + } + case 928: { + OneofUint64 = input.ReadUInt64(); + break; + } + case 941: { + OneofFloat = input.ReadFloat(); + break; + } + case 945: { + OneofDouble = input.ReadDouble(); + break; + } + case 952: { + oneofField_ = input.ReadEnum(); + oneofFieldCase_ = OneofFieldOneofCase.OneofEnum; + break; + } + case 960: { + oneofField_ = input.ReadEnum(); + oneofFieldCase_ = OneofFieldOneofCase.OneofNullValue; + break; + } + case 1610: { + bool? value = _single_optionalBoolWrapper_codec.Read(ref input); + if (optionalBoolWrapper_ == null || value != false) { + OptionalBoolWrapper = value; + } + break; + } + case 1618: { + int? value = _single_optionalInt32Wrapper_codec.Read(ref input); + if (optionalInt32Wrapper_ == null || value != 0) { + OptionalInt32Wrapper = value; + } + break; + } + case 1626: { + long? value = _single_optionalInt64Wrapper_codec.Read(ref input); + if (optionalInt64Wrapper_ == null || value != 0L) { + OptionalInt64Wrapper = value; + } + break; + } + case 1634: { + uint? value = _single_optionalUint32Wrapper_codec.Read(ref input); + if (optionalUint32Wrapper_ == null || value != 0) { + OptionalUint32Wrapper = value; + } + break; + } + case 1642: { + ulong? value = _single_optionalUint64Wrapper_codec.Read(ref input); + if (optionalUint64Wrapper_ == null || value != 0UL) { + OptionalUint64Wrapper = value; + } + break; + } + case 1650: { + float? value = _single_optionalFloatWrapper_codec.Read(ref input); + if (optionalFloatWrapper_ == null || value != 0F) { + OptionalFloatWrapper = value; + } + break; + } + case 1658: { + double? value = _single_optionalDoubleWrapper_codec.Read(ref input); + if (optionalDoubleWrapper_ == null || value != 0D) { + OptionalDoubleWrapper = value; + } + break; + } + case 1666: { + string value = _single_optionalStringWrapper_codec.Read(ref input); + if (optionalStringWrapper_ == null || value != "") { + OptionalStringWrapper = value; + } + break; + } + case 1674: { + pb::ByteString value = _single_optionalBytesWrapper_codec.Read(ref input); + if (optionalBytesWrapper_ == null || value != pb::ByteString.Empty) { + OptionalBytesWrapper = value; + } + break; + } + case 1690: { + repeatedBoolWrapper_.AddEntriesFrom(ref input, _repeated_repeatedBoolWrapper_codec); + break; + } + case 1698: { + repeatedInt32Wrapper_.AddEntriesFrom(ref input, _repeated_repeatedInt32Wrapper_codec); + break; + } + case 1706: { + repeatedInt64Wrapper_.AddEntriesFrom(ref input, _repeated_repeatedInt64Wrapper_codec); + break; + } + case 1714: { + repeatedUint32Wrapper_.AddEntriesFrom(ref input, _repeated_repeatedUint32Wrapper_codec); + break; + } + case 1722: { + repeatedUint64Wrapper_.AddEntriesFrom(ref input, _repeated_repeatedUint64Wrapper_codec); + break; + } + case 1730: { + repeatedFloatWrapper_.AddEntriesFrom(ref input, _repeated_repeatedFloatWrapper_codec); + break; + } + case 1738: { + repeatedDoubleWrapper_.AddEntriesFrom(ref input, _repeated_repeatedDoubleWrapper_codec); + break; + } + case 1746: { + repeatedStringWrapper_.AddEntriesFrom(ref input, _repeated_repeatedStringWrapper_codec); + break; + } + case 1754: { + repeatedBytesWrapper_.AddEntriesFrom(ref input, _repeated_repeatedBytesWrapper_codec); + break; + } + case 2410: { + if (optionalDuration_ == null) { + OptionalDuration = new global::Google.Protobuf.WellKnownTypes.Duration(); + } + input.ReadMessage(OptionalDuration); + break; + } + case 2418: { + if (optionalTimestamp_ == null) { + OptionalTimestamp = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + } + input.ReadMessage(OptionalTimestamp); + break; + } + case 2426: { + if (optionalFieldMask_ == null) { + OptionalFieldMask = new global::Google.Protobuf.WellKnownTypes.FieldMask(); + } + input.ReadMessage(OptionalFieldMask); + break; + } + case 2434: { + if (optionalStruct_ == null) { + OptionalStruct = new global::Google.Protobuf.WellKnownTypes.Struct(); + } + input.ReadMessage(OptionalStruct); + break; + } + case 2442: { + if (optionalAny_ == null) { + OptionalAny = new global::Google.Protobuf.WellKnownTypes.Any(); + } + input.ReadMessage(OptionalAny); + break; + } + case 2450: { + if (optionalValue_ == null) { + OptionalValue = new global::Google.Protobuf.WellKnownTypes.Value(); + } + input.ReadMessage(OptionalValue); + break; + } + case 2456: { + OptionalNullValue = (global::Google.Protobuf.WellKnownTypes.NullValue) input.ReadEnum(); + break; + } + case 2490: { + repeatedDuration_.AddEntriesFrom(ref input, _repeated_repeatedDuration_codec); + break; + } + case 2498: { + repeatedTimestamp_.AddEntriesFrom(ref input, _repeated_repeatedTimestamp_codec); + break; + } + case 2506: { + repeatedFieldmask_.AddEntriesFrom(ref input, _repeated_repeatedFieldmask_codec); + break; + } + case 2522: { + repeatedAny_.AddEntriesFrom(ref input, _repeated_repeatedAny_codec); + break; + } + case 2530: { + repeatedValue_.AddEntriesFrom(ref input, _repeated_repeatedValue_codec); + break; + } + case 2538: { + repeatedListValue_.AddEntriesFrom(ref input, _repeated_repeatedListValue_codec); + break; + } + case 2594: { + repeatedStruct_.AddEntriesFrom(ref input, _repeated_repeatedStruct_codec); + break; + } + case 3208: { + Fieldname1 = input.ReadInt32(); + break; + } + case 3216: { + FieldName2 = input.ReadInt32(); + break; + } + case 3224: { + FieldName3 = input.ReadInt32(); + break; + } + case 3232: { + FieldName4 = input.ReadInt32(); + break; + } + case 3240: { + Field0Name5 = input.ReadInt32(); + break; + } + case 3248: { + Field0Name6 = input.ReadInt32(); + break; + } + case 3256: { + FieldName7 = input.ReadInt32(); + break; + } + case 3264: { + FieldName8 = input.ReadInt32(); + break; + } + case 3272: { + FieldName9 = input.ReadInt32(); + break; + } + case 3280: { + FieldName10 = input.ReadInt32(); + break; + } + case 3288: { + FIELDNAME11 = input.ReadInt32(); + break; + } + case 3296: { + FIELDName12 = input.ReadInt32(); + break; + } + case 3304: { + FieldName13 = input.ReadInt32(); + break; + } + case 3312: { + FieldName14 = input.ReadInt32(); + break; + } + case 3320: { + FieldName15 = input.ReadInt32(); + break; + } + case 3328: { + FieldName16 = input.ReadInt32(); + break; + } + case 3336: { + FieldName17 = input.ReadInt32(); + break; + } + case 3344: { + FieldName18 = input.ReadInt32(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestAllTypesProto3 message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum NestedEnum { + [pbr::OriginalName("FOO")] Foo = 0, + [pbr::OriginalName("BAR")] Bar = 1, + [pbr::OriginalName("BAZ")] Baz = 2, + /// + /// Intentionally negative. + /// + [pbr::OriginalName("NEG")] Neg = -1, + } + + public enum AliasedEnum { + [pbr::OriginalName("ALIAS_FOO")] AliasFoo = 0, + [pbr::OriginalName("ALIAS_BAR")] AliasBar = 1, + [pbr::OriginalName("ALIAS_BAZ")] AliasBaz = 2, + [pbr::OriginalName("QUX", PreferredAlias = false)] Qux = 2, + [pbr::OriginalName("qux", PreferredAlias = false)] Qux_ = 2, + [pbr::OriginalName("bAz", PreferredAlias = false)] BAz = 2, + } + + public sealed partial class NestedMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + a_ = other.a_; + corecursive_ = other.corecursive_ != null ? other.corecursive_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { return a_; } + set { + a_ = value; + } + } + + /// Field number for the "corecursive" field. + public const int CorecursiveFieldNumber = 2; + private global::ProtobufTestMessages.Proto3.TestAllTypesProto3 corecursive_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufTestMessages.Proto3.TestAllTypesProto3 Corecursive { + get { return corecursive_; } + set { + corecursive_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + if (!object.Equals(Corecursive, other.Corecursive)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (A != 0) hash ^= A.GetHashCode(); + if (corecursive_ != null) hash ^= Corecursive.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (A != 0) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (corecursive_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Corecursive); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (A != 0) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (corecursive_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Corecursive); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (A != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (corecursive_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Corecursive); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.A != 0) { + A = other.A; + } + if (other.corecursive_ != null) { + if (corecursive_ == null) { + Corecursive = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3(); + } + Corecursive.MergeFrom(other.Corecursive); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + A = input.ReadInt32(); + break; + } + case 18: { + if (corecursive_ == null) { + Corecursive = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3(); + } + input.ReadMessage(Corecursive); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + A = input.ReadInt32(); + break; + } + case 18: { + if (corecursive_ == null) { + Corecursive = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3(); + } + input.ReadMessage(Corecursive); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class ForeignMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ForeignMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufTestMessages.Proto3.TestMessagesProto3Reflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ForeignMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ForeignMessage(ForeignMessage other) : this() { + c_ = other.c_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ForeignMessage Clone() { + return new ForeignMessage(this); + } + + /// Field number for the "c" field. + public const int CFieldNumber = 1; + private int c_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int C { + get { return c_; } + set { + c_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ForeignMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ForeignMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (C != other.C) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (C != 0) hash ^= C.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (C != 0) { + output.WriteRawTag(8); + output.WriteInt32(C); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (C != 0) { + output.WriteRawTag(8); + output.WriteInt32(C); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (C != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(C); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ForeignMessage other) { + if (other == null) { + return; + } + if (other.C != 0) { + C = other.C; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + C = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + C = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs new file mode 100644 index 0000000000000..a843c4ae8baf6 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs @@ -0,0 +1,29541 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: unittest.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Google.Protobuf.TestProtos.Proto2 { + + /// Holder for reflection information generated from unittest.proto + public static partial class UnittestReflection { + + #region Descriptor + /// File descriptor for unittest.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Cg51bml0dGVzdC5wcm90bxIYcHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yGhV1", + "bml0dGVzdF9pbXBvcnQucHJvdG8igBoKDFRlc3RBbGxUeXBlcxIWCg5vcHRp", + "b25hbF9pbnQzMhgBIAEoBRIWCg5vcHRpb25hbF9pbnQ2NBgCIAEoAxIXCg9v", + "cHRpb25hbF91aW50MzIYAyABKA0SFwoPb3B0aW9uYWxfdWludDY0GAQgASgE", + "EhcKD29wdGlvbmFsX3NpbnQzMhgFIAEoERIXCg9vcHRpb25hbF9zaW50NjQY", + "BiABKBISGAoQb3B0aW9uYWxfZml4ZWQzMhgHIAEoBxIYChBvcHRpb25hbF9m", + "aXhlZDY0GAggASgGEhkKEW9wdGlvbmFsX3NmaXhlZDMyGAkgASgPEhkKEW9w", + "dGlvbmFsX3NmaXhlZDY0GAogASgQEhYKDm9wdGlvbmFsX2Zsb2F0GAsgASgC", + "EhcKD29wdGlvbmFsX2RvdWJsZRgMIAEoARIVCg1vcHRpb25hbF9ib29sGA0g", + "ASgIEhcKD29wdGlvbmFsX3N0cmluZxgOIAEoCRIWCg5vcHRpb25hbF9ieXRl", + "cxgPIAEoDBJLCg1vcHRpb25hbGdyb3VwGBAgASgKMjQucHJvdG9idWZfdW5p", + "dHRlc3RfcHJvdG8yLlRlc3RBbGxUeXBlcy5PcHRpb25hbEdyb3VwElUKF29w", + "dGlvbmFsX25lc3RlZF9tZXNzYWdlGBIgASgLMjQucHJvdG9idWZfdW5pdHRl", + "c3RfcHJvdG8yLlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlEkoKGG9wdGlv", + "bmFsX2ZvcmVpZ25fbWVzc2FnZRgTIAEoCzIoLnByb3RvYnVmX3VuaXR0ZXN0", + "X3Byb3RvMi5Gb3JlaWduTWVzc2FnZRJPChdvcHRpb25hbF9pbXBvcnRfbWVz", + "c2FnZRgUIAEoCzIuLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9wcm90bzIu", + "SW1wb3J0TWVzc2FnZRJPChRvcHRpb25hbF9uZXN0ZWRfZW51bRgVIAEoDjIx", + "LnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsVHlwZXMuTmVzdGVk", + "RW51bRJEChVvcHRpb25hbF9mb3JlaWduX2VudW0YFiABKA4yJS5wcm90b2J1", + "Zl91bml0dGVzdF9wcm90bzIuRm9yZWlnbkVudW0SSQoUb3B0aW9uYWxfaW1w", + "b3J0X2VudW0YFyABKA4yKy5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfcHJv", + "dG8yLkltcG9ydEVudW0SIQoVb3B0aW9uYWxfc3RyaW5nX3BpZWNlGBggASgJ", + "QgIIAhIZCg1vcHRpb25hbF9jb3JkGBkgASgJQgIIARJcCh5vcHRpb25hbF9w", + "dWJsaWNfaW1wb3J0X21lc3NhZ2UYGiABKAsyNC5wcm90b2J1Zl91bml0dGVz", + "dF9pbXBvcnRfcHJvdG8yLlB1YmxpY0ltcG9ydE1lc3NhZ2USVwoVb3B0aW9u", + "YWxfbGF6eV9tZXNzYWdlGBsgASgLMjQucHJvdG9idWZfdW5pdHRlc3RfcHJv", + "dG8yLlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlQgIoARIWCg5yZXBlYXRl", + "ZF9pbnQzMhgfIAMoBRIWCg5yZXBlYXRlZF9pbnQ2NBggIAMoAxIXCg9yZXBl", + "YXRlZF91aW50MzIYISADKA0SFwoPcmVwZWF0ZWRfdWludDY0GCIgAygEEhcK", + "D3JlcGVhdGVkX3NpbnQzMhgjIAMoERIXCg9yZXBlYXRlZF9zaW50NjQYJCAD", + "KBISGAoQcmVwZWF0ZWRfZml4ZWQzMhglIAMoBxIYChByZXBlYXRlZF9maXhl", + "ZDY0GCYgAygGEhkKEXJlcGVhdGVkX3NmaXhlZDMyGCcgAygPEhkKEXJlcGVh", + "dGVkX3NmaXhlZDY0GCggAygQEhYKDnJlcGVhdGVkX2Zsb2F0GCkgAygCEhcK", + "D3JlcGVhdGVkX2RvdWJsZRgqIAMoARIVCg1yZXBlYXRlZF9ib29sGCsgAygI", + "EhcKD3JlcGVhdGVkX3N0cmluZxgsIAMoCRIWCg5yZXBlYXRlZF9ieXRlcxgt", + "IAMoDBJLCg1yZXBlYXRlZGdyb3VwGC4gAygKMjQucHJvdG9idWZfdW5pdHRl", + "c3RfcHJvdG8yLlRlc3RBbGxUeXBlcy5SZXBlYXRlZEdyb3VwElUKF3JlcGVh", + "dGVkX25lc3RlZF9tZXNzYWdlGDAgAygLMjQucHJvdG9idWZfdW5pdHRlc3Rf", + "cHJvdG8yLlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlEkoKGHJlcGVhdGVk", + "X2ZvcmVpZ25fbWVzc2FnZRgxIAMoCzIoLnByb3RvYnVmX3VuaXR0ZXN0X3By", + "b3RvMi5Gb3JlaWduTWVzc2FnZRJPChdyZXBlYXRlZF9pbXBvcnRfbWVzc2Fn", + "ZRgyIAMoCzIuLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydF9wcm90bzIuSW1w", + "b3J0TWVzc2FnZRJPChRyZXBlYXRlZF9uZXN0ZWRfZW51bRgzIAMoDjIxLnBy", + "b3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsVHlwZXMuTmVzdGVkRW51", + "bRJEChVyZXBlYXRlZF9mb3JlaWduX2VudW0YNCADKA4yJS5wcm90b2J1Zl91", + "bml0dGVzdF9wcm90bzIuRm9yZWlnbkVudW0SSQoUcmVwZWF0ZWRfaW1wb3J0", + "X2VudW0YNSADKA4yKy5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnRfcHJvdG8y", + "LkltcG9ydEVudW0SIQoVcmVwZWF0ZWRfc3RyaW5nX3BpZWNlGDYgAygJQgII", + "AhIZCg1yZXBlYXRlZF9jb3JkGDcgAygJQgIIARJXChVyZXBlYXRlZF9sYXp5", + "X21lc3NhZ2UYOSADKAsyNC5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVz", + "dEFsbFR5cGVzLk5lc3RlZE1lc3NhZ2VCAigBEhkKDWRlZmF1bHRfaW50MzIY", + "PSABKAU6AjQxEhkKDWRlZmF1bHRfaW50NjQYPiABKAM6AjQyEhoKDmRlZmF1", + "bHRfdWludDMyGD8gASgNOgI0MxIaCg5kZWZhdWx0X3VpbnQ2NBhAIAEoBDoC", + "NDQSGwoOZGVmYXVsdF9zaW50MzIYQSABKBE6Ay00NRIaCg5kZWZhdWx0X3Np", + "bnQ2NBhCIAEoEjoCNDYSGwoPZGVmYXVsdF9maXhlZDMyGEMgASgHOgI0NxIb", + "Cg9kZWZhdWx0X2ZpeGVkNjQYRCABKAY6AjQ4EhwKEGRlZmF1bHRfc2ZpeGVk", + "MzIYRSABKA86AjQ5Eh0KEGRlZmF1bHRfc2ZpeGVkNjQYRiABKBA6Ay01MBIb", + "Cg1kZWZhdWx0X2Zsb2F0GEcgASgCOgQ1MS41Eh0KDmRlZmF1bHRfZG91Ymxl", + "GEggASgBOgU1MjAwMBIaCgxkZWZhdWx0X2Jvb2wYSSABKAg6BHRydWUSHQoO", + "ZGVmYXVsdF9zdHJpbmcYSiABKAk6BWhlbGxvEhwKDWRlZmF1bHRfYnl0ZXMY", + "SyABKAw6BXdvcmxkElMKE2RlZmF1bHRfbmVzdGVkX2VudW0YUSABKA4yMS5w", + "cm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbFR5cGVzLk5lc3RlZEVu", + "dW06A0JBUhJQChRkZWZhdWx0X2ZvcmVpZ25fZW51bRhSIAEoDjIlLnByb3Rv", + "YnVmX3VuaXR0ZXN0X3Byb3RvMi5Gb3JlaWduRW51bToLRk9SRUlHTl9CQVIS", + "VAoTZGVmYXVsdF9pbXBvcnRfZW51bRhTIAEoDjIrLnByb3RvYnVmX3VuaXR0", + "ZXN0X2ltcG9ydF9wcm90bzIuSW1wb3J0RW51bToKSU1QT1JUX0JBUhIlChRk", + "ZWZhdWx0X3N0cmluZ19waWVjZRhUIAEoCToDYWJjQgIIAhIdCgxkZWZhdWx0", + "X2NvcmQYVSABKAk6AzEyM0ICCAESFgoMb25lb2ZfdWludDMyGG8gASgNSAAS", + "VAoUb25lb2ZfbmVzdGVkX21lc3NhZ2UYcCABKAsyNC5wcm90b2J1Zl91bml0", + "dGVzdF9wcm90bzIuVGVzdEFsbFR5cGVzLk5lc3RlZE1lc3NhZ2VIABIWCgxv", + "bmVvZl9zdHJpbmcYcSABKAlIABIVCgtvbmVvZl9ieXRlcxhyIAEoDEgAGhsK", + "DU5lc3RlZE1lc3NhZ2USCgoCYmIYASABKAUaGgoNT3B0aW9uYWxHcm91cBIJ", + "CgFhGBEgASgFGhoKDVJlcGVhdGVkR3JvdXASCQoBYRgvIAEoBSI5CgpOZXN0", + "ZWRFbnVtEgcKA0ZPTxABEgcKA0JBUhACEgcKA0JBWhADEhAKA05FRxD/////", + "//////8BQg0KC29uZW9mX2ZpZWxkItABChJOZXN0ZWRUZXN0QWxsVHlwZXMS", + "OwoFY2hpbGQYASABKAsyLC5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuTmVz", + "dGVkVGVzdEFsbFR5cGVzEjcKB3BheWxvYWQYAiABKAsyJi5wcm90b2J1Zl91", + "bml0dGVzdF9wcm90bzIuVGVzdEFsbFR5cGVzEkQKDnJlcGVhdGVkX2NoaWxk", + "GAMgAygLMiwucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLk5lc3RlZFRlc3RB", + "bGxUeXBlcyJtChRUZXN0RGVwcmVjYXRlZEZpZWxkcxIcChBkZXByZWNhdGVk", + "X2ludDMyGAEgASgFQgIYARInChlkZXByZWNhdGVkX2ludDMyX2luX29uZW9m", + "GAIgASgFQgIYAUgAQg4KDG9uZW9mX2ZpZWxkcyIbChVUZXN0RGVwcmVjYXRl", + "ZE1lc3NhZ2U6AhgBIiYKDkZvcmVpZ25NZXNzYWdlEgkKAWMYASABKAUSCQoB", + "ZBgCIAEoBSIwChJUZXN0UmVzZXJ2ZWRGaWVsZHNKBAgCEANKBAgPEBBKBAgJ", + "EAxSA2JhclIDYmF6Ih0KEVRlc3RBbGxFeHRlbnNpb25zKggIARCAgICAAiIk", + "ChdPcHRpb25hbEdyb3VwX2V4dGVuc2lvbhIJCgFhGBEgASgFIiQKF1JlcGVh", + "dGVkR3JvdXBfZXh0ZW5zaW9uEgkKAWEYLyABKAUitwEKCVRlc3RHcm91cBJI", + "Cg1vcHRpb25hbGdyb3VwGBAgASgKMjEucHJvdG9idWZfdW5pdHRlc3RfcHJv", + "dG8yLlRlc3RHcm91cC5PcHRpb25hbEdyb3VwEkQKFW9wdGlvbmFsX2ZvcmVp", + "Z25fZW51bRgWIAEoDjIlLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5Gb3Jl", + "aWduRW51bRoaCg1PcHRpb25hbEdyb3VwEgkKAWEYESABKAUiHgoSVGVzdEdy", + "b3VwRXh0ZW5zaW9uKggIARCAgICAAiLhAwoTVGVzdE5lc3RlZEV4dGVuc2lv", + "bhokChdPcHRpb25hbEdyb3VwX2V4dGVuc2lvbhIJCgFhGBEgASgFMkAKBHRl", + "c3QSKy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbEV4dGVuc2lv", + "bnMY6gcgASgJOgR0ZXN0Mk0KF25lc3RlZF9zdHJpbmdfZXh0ZW5zaW9uEisu", + "cHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRlbnNpb25zGOsH", + "IAEoCTKUAQoXb3B0aW9uYWxncm91cF9leHRlbnNpb24SLC5wcm90b2J1Zl91", + "bml0dGVzdF9wcm90bzIuVGVzdEdyb3VwRXh0ZW5zaW9uGBAgASgKMkUucHJv", + "dG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3ROZXN0ZWRFeHRlbnNpb24uT3B0", + "aW9uYWxHcm91cF9leHRlbnNpb24yfAofb3B0aW9uYWxfZm9yZWlnbl9lbnVt", + "X2V4dGVuc2lvbhIsLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0R3Jv", + "dXBFeHRlbnNpb24YFiABKA4yJS5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIu", + "Rm9yZWlnbkVudW0i8QUKDFRlc3RSZXF1aXJlZBIJCgFhGAEgAigFEg4KBmR1", + "bW15MhgCIAEoBRIJCgFiGAMgAigFEg4KBmR1bW15NBgEIAEoBRIOCgZkdW1t", + "eTUYBSABKAUSDgoGZHVtbXk2GAYgASgFEg4KBmR1bW15NxgHIAEoBRIOCgZk", + "dW1teTgYCCABKAUSDgoGZHVtbXk5GAkgASgFEg8KB2R1bW15MTAYCiABKAUS", + "DwoHZHVtbXkxMRgLIAEoBRIPCgdkdW1teTEyGAwgASgFEg8KB2R1bW15MTMY", + "DSABKAUSDwoHZHVtbXkxNBgOIAEoBRIPCgdkdW1teTE1GA8gASgFEg8KB2R1", + "bW15MTYYECABKAUSDwoHZHVtbXkxNxgRIAEoBRIPCgdkdW1teTE4GBIgASgF", + "Eg8KB2R1bW15MTkYEyABKAUSDwoHZHVtbXkyMBgUIAEoBRIPCgdkdW1teTIx", + "GBUgASgFEg8KB2R1bW15MjIYFiABKAUSDwoHZHVtbXkyMxgXIAEoBRIPCgdk", + "dW1teTI0GBggASgFEg8KB2R1bW15MjUYGSABKAUSDwoHZHVtbXkyNhgaIAEo", + "BRIPCgdkdW1teTI3GBsgASgFEg8KB2R1bW15MjgYHCABKAUSDwoHZHVtbXky", + "ORgdIAEoBRIPCgdkdW1teTMwGB4gASgFEg8KB2R1bW15MzEYHyABKAUSDwoH", + "ZHVtbXkzMhggIAEoBRIJCgFjGCEgAigFMmQKBnNpbmdsZRIrLnByb3RvYnVm", + "X3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsRXh0ZW5zaW9ucxjoByABKAsyJi5w", + "cm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdFJlcXVpcmVkMmMKBW11bHRp", + "EisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRlbnNpb25z", + "GOkHIAMoCzImLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0UmVxdWly", + "ZWQiqAEKE1Rlc3RSZXF1aXJlZEZvcmVpZ24SQAoQb3B0aW9uYWxfbWVzc2Fn", + "ZRgBIAEoCzImLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0UmVxdWly", + "ZWQSQAoQcmVwZWF0ZWRfbWVzc2FnZRgCIAMoCzImLnByb3RvYnVmX3VuaXR0", + "ZXN0X3Byb3RvMi5UZXN0UmVxdWlyZWQSDQoFZHVtbXkYAyABKAUi2wEKE1Rl", + "c3RSZXF1aXJlZE1lc3NhZ2USQAoQb3B0aW9uYWxfbWVzc2FnZRgBIAEoCzIm", + "LnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0UmVxdWlyZWQSQAoQcmVw", + "ZWF0ZWRfbWVzc2FnZRgCIAMoCzImLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3Rv", + "Mi5UZXN0UmVxdWlyZWQSQAoQcmVxdWlyZWRfbWVzc2FnZRgDIAIoCzImLnBy", + "b3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0UmVxdWlyZWQiYQoRVGVzdEZv", + "cmVpZ25OZXN0ZWQSTAoOZm9yZWlnbl9uZXN0ZWQYASABKAsyNC5wcm90b2J1", + "Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbFR5cGVzLk5lc3RlZE1lc3NhZ2Ui", + "EgoQVGVzdEVtcHR5TWVzc2FnZSIqCh5UZXN0RW1wdHlNZXNzYWdlV2l0aEV4", + "dGVuc2lvbnMqCAgBEICAgIACIjcKG1Rlc3RNdWx0aXBsZUV4dGVuc2lvblJh", + "bmdlcyoECCoQKyoGCK8gEJQhKgoIgIAEEICAgIACIjQKGFRlc3RSZWFsbHlM", + "YXJnZVRhZ051bWJlchIJCgFhGAEgASgFEg0KAmJiGP///38gASgFIlwKFFRl", + "c3RSZWN1cnNpdmVNZXNzYWdlEjkKAWEYASABKAsyLi5wcm90b2J1Zl91bml0", + "dGVzdF9wcm90bzIuVGVzdFJlY3Vyc2l2ZU1lc3NhZ2USCQoBaRgCIAEoBSKE", + "AwoUVGVzdE11dHVhbFJlY3Vyc2lvbkESOgoCYmIYASABKAsyLi5wcm90b2J1", + "Zl91bml0dGVzdF9wcm90bzIuVGVzdE11dHVhbFJlY3Vyc2lvbkISSQoIc3Vi", + "Z3JvdXAYAiABKAoyNy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdE11", + "dHVhbFJlY3Vyc2lvbkEuU3ViR3JvdXAaRwoKU3ViTWVzc2FnZRI5CgFiGAEg", + "ASgLMi4ucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RNdXR1YWxSZWN1", + "cnNpb25CGpsBCghTdWJHcm91cBJOCgtzdWJfbWVzc2FnZRgDIAEoCzI5LnBy", + "b3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0TXV0dWFsUmVjdXJzaW9uQS5T", + "dWJNZXNzYWdlEj8KD25vdF9pbl90aGlzX3NjYxgEIAEoCzImLnByb3RvYnVm", + "X3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsVHlwZXMiaQoUVGVzdE11dHVhbFJl", + "Y3Vyc2lvbkISOQoBYRgBIAEoCzIuLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3Rv", + "Mi5UZXN0TXV0dWFsUmVjdXJzaW9uQRIWCg5vcHRpb25hbF9pbnQzMhgCIAEo", + "BSLYAQoRVGVzdElzSW5pdGlhbGl6ZWQSSwoLc3ViX21lc3NhZ2UYASABKAsy", + "Ni5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdElzSW5pdGlhbGl6ZWQu", + "U3ViTWVzc2FnZRp2CgpTdWJNZXNzYWdlElEKCHN1Ymdyb3VwGAEgASgKMj8u", + "cHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RJc0luaXRpYWxpemVkLlN1", + "Yk1lc3NhZ2UuU3ViR3JvdXAaFQoIU3ViR3JvdXASCQoBaRgCIAIoBSLBAQoS", + "VGVzdER1cEZpZWxkTnVtYmVyEgkKAWEYASABKAUSPQoDZm9vGAIgASgKMjAu", + "cHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3REdXBGaWVsZE51bWJlci5G", + "b28SPQoDYmFyGAMgASgKMjAucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRl", + "c3REdXBGaWVsZE51bWJlci5CYXIaEAoDRm9vEgkKAWEYASABKAUaEAoDQmFy", + "EgkKAWEYASABKAUiUwoQVGVzdEVhZ2VyTWVzc2FnZRI/CgtzdWJfbWVzc2Fn", + "ZRgBIAEoCzImLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsVHlw", + "ZXNCAigAIlIKD1Rlc3RMYXp5TWVzc2FnZRI/CgtzdWJfbWVzc2FnZRgBIAEo", + "CzImLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsVHlwZXNCAigB", + "Io4CChhUZXN0TmVzdGVkTWVzc2FnZUhhc0JpdHMSYQoXb3B0aW9uYWxfbmVz", + "dGVkX21lc3NhZ2UYASABKAsyQC5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIu", + "VGVzdE5lc3RlZE1lc3NhZ2VIYXNCaXRzLk5lc3RlZE1lc3NhZ2UajgEKDU5l", + "c3RlZE1lc3NhZ2USJAocbmVzdGVkbWVzc2FnZV9yZXBlYXRlZF9pbnQzMhgB", + "IAMoBRJXCiVuZXN0ZWRtZXNzYWdlX3JlcGVhdGVkX2ZvcmVpZ25tZXNzYWdl", + "GAIgAygLMigucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLkZvcmVpZ25NZXNz", + "YWdlIoEEChdUZXN0Q2FtZWxDYXNlRmllbGROYW1lcxIWCg5QcmltaXRpdmVG", + "aWVsZBgBIAEoBRITCgtTdHJpbmdGaWVsZBgCIAEoCRI4CglFbnVtRmllbGQY", + "AyABKA4yJS5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuRm9yZWlnbkVudW0S", + "PgoMTWVzc2FnZUZpZWxkGAQgASgLMigucHJvdG9idWZfdW5pdHRlc3RfcHJv", + "dG8yLkZvcmVpZ25NZXNzYWdlEhwKEFN0cmluZ1BpZWNlRmllbGQYBSABKAlC", + "AggCEhUKCUNvcmRGaWVsZBgGIAEoCUICCAESHgoWUmVwZWF0ZWRQcmltaXRp", + "dmVGaWVsZBgHIAMoBRIbChNSZXBlYXRlZFN0cmluZ0ZpZWxkGAggAygJEkAK", + "EVJlcGVhdGVkRW51bUZpZWxkGAkgAygOMiUucHJvdG9idWZfdW5pdHRlc3Rf", + "cHJvdG8yLkZvcmVpZ25FbnVtEkYKFFJlcGVhdGVkTWVzc2FnZUZpZWxkGAog", + "AygLMigucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLkZvcmVpZ25NZXNzYWdl", + "EiQKGFJlcGVhdGVkU3RyaW5nUGllY2VGaWVsZBgLIAMoCUICCAISHQoRUmVw", + "ZWF0ZWRDb3JkRmllbGQYDCADKAlCAggBItwBChJUZXN0RmllbGRPcmRlcmlu", + "Z3MSEQoJbXlfc3RyaW5nGAsgASgJEg4KBm15X2ludBgBIAEoAxIQCghteV9m", + "bG9hdBhlIAEoAhJcChdvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZRjIASABKAsy", + "Oi5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEZpZWxkT3JkZXJpbmdz", + "Lk5lc3RlZE1lc3NhZ2UaJwoNTmVzdGVkTWVzc2FnZRIKCgJvbxgCIAEoAxIK", + "CgJiYhgBIAEoBSoECAIQCyoECAwQZSKqAQoXVGVzdEV4dGVuc2lvbk9yZGVy", + "aW5nczESEQoJbXlfc3RyaW5nGAEgASgJMnwKE3Rlc3RfZXh0X29yZGVyaW5n", + "czESLC5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEZpZWxkT3JkZXJp", + "bmdzGA0gASgLMjEucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RFeHRl", + "bnNpb25PcmRlcmluZ3MxIvACChdUZXN0RXh0ZW5zaW9uT3JkZXJpbmdzMhIR", + "CglteV9zdHJpbmcYASABKAkawwEKF1Rlc3RFeHRlbnNpb25PcmRlcmluZ3Mz", + "EhEKCW15X3N0cmluZxgBIAEoCTKUAQoTdGVzdF9leHRfb3JkZXJpbmdzMxIs", + "LnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0RmllbGRPcmRlcmluZ3MY", + "DiABKAsySS5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEV4dGVuc2lv", + "bk9yZGVyaW5nczIuVGVzdEV4dGVuc2lvbk9yZGVyaW5nczMyfAoTdGVzdF9l", + "eHRfb3JkZXJpbmdzMhIsLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0", + "RmllbGRPcmRlcmluZ3MYDCABKAsyMS5wcm90b2J1Zl91bml0dGVzdF9wcm90", + "bzIuVGVzdEV4dGVuc2lvbk9yZGVyaW5nczIitgcKGFRlc3RFeHRyZW1lRGVm", + "YXVsdFZhbHVlcxI/Cg1lc2NhcGVkX2J5dGVzGAEgASgMOihcMDAwXDAwMVww", + "MDdcMDEwXDAxNFxuXHJcdFwwMTNcXFwnXCJcMzc2EiAKDGxhcmdlX3VpbnQz", + "MhgCIAEoDToKNDI5NDk2NzI5NRIqCgxsYXJnZV91aW50NjQYAyABKAQ6FDE4", + "NDQ2NzQ0MDczNzA5NTUxNjE1EiAKC3NtYWxsX2ludDMyGAQgASgFOgstMjE0", + "NzQ4MzY0NxIpCgtzbWFsbF9pbnQ2NBgFIAEoAzoULTkyMjMzNzIwMzY4NTQ3", + "NzU4MDcSJwoScmVhbGx5X3NtYWxsX2ludDMyGBUgASgFOgstMjE0NzQ4MzY0", + "OBIwChJyZWFsbHlfc21hbGxfaW50NjQYFiABKAM6FC05MjIzMzcyMDM2ODU0", + "Nzc1ODA4EhgKC3V0Zjhfc3RyaW5nGAYgASgJOgPhiLQSFQoKemVyb19mbG9h", + "dBgHIAEoAjoBMBIUCglvbmVfZmxvYXQYCCABKAI6ATESGAoLc21hbGxfZmxv", + "YXQYCSABKAI6AzEuNRIeChJuZWdhdGl2ZV9vbmVfZmxvYXQYCiABKAI6Ai0x", + "EhwKDm5lZ2F0aXZlX2Zsb2F0GAsgASgCOgQtMS41EhoKC2xhcmdlX2Zsb2F0", + "GAwgASgCOgUyZSswOBIkChRzbWFsbF9uZWdhdGl2ZV9mbG9hdBgNIAEoAjoG", + "LThlLTI4EhcKCmluZl9kb3VibGUYDiABKAE6A2luZhIcCg5uZWdfaW5mX2Rv", + "dWJsZRgPIAEoAToELWluZhIXCgpuYW5fZG91YmxlGBAgASgBOgNuYW4SFgoJ", + "aW5mX2Zsb2F0GBEgASgCOgNpbmYSGwoNbmVnX2luZl9mbG9hdBgSIAEoAjoE", + "LWluZhIWCgluYW5fZmxvYXQYEyABKAI6A25hbhIrCgxjcHBfdHJpZ3JhcGgY", + "FCABKAk6FT8gPyA/PyA/PyA/Pz8gPz8vID8/LRIgChBzdHJpbmdfd2l0aF96", + "ZXJvGBcgASgJOgZoZWwAbG8SIgoPYnl0ZXNfd2l0aF96ZXJvGBggASgMOgl3", + "b3JcMDAwbGQSKAoWc3RyaW5nX3BpZWNlX3dpdGhfemVybxgZIAEoCToEYWIA", + "Y0ICCAISIAoOY29yZF93aXRoX3plcm8YGiABKAk6BDEyADNCAggBEiYKEnJl", + "cGxhY2VtZW50X3N0cmluZxgbIAEoCToKJHt1bmtub3dufSJSChFTcGFyc2VF", + "bnVtTWVzc2FnZRI9CgtzcGFyc2VfZW51bRgBIAEoDjIoLnByb3RvYnVmX3Vu", + "aXR0ZXN0X3Byb3RvMi5UZXN0U3BhcnNlRW51bSIZCglPbmVTdHJpbmcSDAoE", + "ZGF0YRgBIAEoCSIaCgpNb3JlU3RyaW5nEgwKBGRhdGEYASADKAkiGAoIT25l", + "Qnl0ZXMSDAoEZGF0YRgBIAEoDCIZCglNb3JlQnl0ZXMSDAoEZGF0YRgBIAMo", + "DCIcCgxJbnQzMk1lc3NhZ2USDAoEZGF0YRgBIAEoBSIdCg1VaW50MzJNZXNz", + "YWdlEgwKBGRhdGEYASABKA0iHAoMSW50NjRNZXNzYWdlEgwKBGRhdGEYASAB", + "KAMiHQoNVWludDY0TWVzc2FnZRIMCgRkYXRhGAEgASgEIhsKC0Jvb2xNZXNz", + "YWdlEgwKBGRhdGEYASABKAgi3gEKCVRlc3RPbmVvZhIRCgdmb29faW50GAEg", + "ASgFSAASFAoKZm9vX3N0cmluZxgCIAEoCUgAEj0KC2Zvb19tZXNzYWdlGAMg", + "ASgLMiYucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxUeXBlc0gA", + "EkAKCGZvb2dyb3VwGAQgASgKMiwucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8y", + "LlRlc3RPbmVvZi5Gb29Hcm91cEgAGiAKCEZvb0dyb3VwEgkKAWEYBSABKAUS", + "CQoBYhgGIAEoCUIFCgNmb28i9QEKHFRlc3RPbmVvZkJhY2t3YXJkc0NvbXBh", + "dGlibGUSDwoHZm9vX2ludBgBIAEoBRISCgpmb29fc3RyaW5nGAIgASgJEjsK", + "C2Zvb19tZXNzYWdlGAMgASgLMiYucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8y", + "LlRlc3RBbGxUeXBlcxJRCghmb29ncm91cBgEIAEoCjI/LnByb3RvYnVmX3Vu", + "aXR0ZXN0X3Byb3RvMi5UZXN0T25lb2ZCYWNrd2FyZHNDb21wYXRpYmxlLkZv", + "b0dyb3VwGiAKCEZvb0dyb3VwEgkKAWEYBSABKAUSCQoBYhgGIAEoCSLBBgoK", + "VGVzdE9uZW9mMhIRCgdmb29faW50GAEgASgFSAASFAoKZm9vX3N0cmluZxgC", + "IAEoCUgAEhYKCGZvb19jb3JkGAMgASgJQgIIAUgAEh4KEGZvb19zdHJpbmdf", + "cGllY2UYBCABKAlCAggCSAASEwoJZm9vX2J5dGVzGAUgASgMSAASQwoIZm9v", + "X2VudW0YBiABKA4yLy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdE9u", + "ZW9mMi5OZXN0ZWRFbnVtSAASSQoLZm9vX21lc3NhZ2UYByABKAsyMi5wcm90", + "b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdE9uZW9mMi5OZXN0ZWRNZXNzYWdl", + "SAASQQoIZm9vZ3JvdXAYCCABKAoyLS5wcm90b2J1Zl91bml0dGVzdF9wcm90", + "bzIuVGVzdE9uZW9mMi5Gb29Hcm91cEgAElIKEGZvb19sYXp5X21lc3NhZ2UY", + "CyABKAsyMi5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdE9uZW9mMi5O", + "ZXN0ZWRNZXNzYWdlQgIoAUgAEhQKB2Jhcl9pbnQYDCABKAU6ATVIARIcCgpi", + "YXJfc3RyaW5nGA0gASgJOgZTVFJJTkdIARIcCghiYXJfY29yZBgOIAEoCToE", + "Q09SREICCAFIARImChBiYXJfc3RyaW5nX3BpZWNlGA8gASgJOgZTUElFQ0VC", + "AggCSAESGgoJYmFyX2J5dGVzGBAgASgMOgVCWVRFU0gBEkgKCGJhcl9lbnVt", + "GBEgASgOMi8ucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RPbmVvZjIu", + "TmVzdGVkRW51bToDQkFSSAESDwoHYmF6X2ludBgSIAEoBRIXCgpiYXpfc3Ry", + "aW5nGBMgASgJOgNCQVoaIAoIRm9vR3JvdXASCQoBYRgJIAEoBRIJCgFiGAog", + "ASgJGjMKDU5lc3RlZE1lc3NhZ2USDwoHcXV4X2ludBgBIAEoAxIRCgljb3Jn", + "ZV9pbnQYAiADKAUiJwoKTmVzdGVkRW51bRIHCgNGT08QARIHCgNCQVIQAhIH", + "CgNCQVoQA0IFCgNmb29CBQoDYmFyIr8BChFUZXN0UmVxdWlyZWRPbmVvZhIR", + "Cgdmb29faW50GAEgASgFSAASFAoKZm9vX3N0cmluZxgCIAEoCUgAElAKC2Zv", + "b19tZXNzYWdlGAMgASgLMjkucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRl", + "c3RSZXF1aXJlZE9uZW9mLk5lc3RlZE1lc3NhZ2VIABooCg1OZXN0ZWRNZXNz", + "YWdlEhcKD3JlcXVpcmVkX2RvdWJsZRgBIAIoAUIFCgNmb28i4AEKD1Rlc3RS", + "ZXF1aXJlZE1hcBI/CgNmb28YASADKAsyMi5wcm90b2J1Zl91bml0dGVzdF9w", + "cm90bzIuVGVzdFJlcXVpcmVkTWFwLkZvb0VudHJ5GmMKCEZvb0VudHJ5EgsK", + "A2tleRgBIAEoBRJGCgV2YWx1ZRgCIAEoCzI3LnByb3RvYnVmX3VuaXR0ZXN0", + "X3Byb3RvMi5UZXN0UmVxdWlyZWRNYXAuTmVzdGVkTWVzc2FnZToCOAEaJwoN", + "TmVzdGVkTWVzc2FnZRIWCg5yZXF1aXJlZF9pbnQzMhgBIAIoBSKxAwoPVGVz", + "dFBhY2tlZFR5cGVzEhgKDHBhY2tlZF9pbnQzMhhaIAMoBUICEAESGAoMcGFj", + "a2VkX2ludDY0GFsgAygDQgIQARIZCg1wYWNrZWRfdWludDMyGFwgAygNQgIQ", + "ARIZCg1wYWNrZWRfdWludDY0GF0gAygEQgIQARIZCg1wYWNrZWRfc2ludDMy", + "GF4gAygRQgIQARIZCg1wYWNrZWRfc2ludDY0GF8gAygSQgIQARIaCg5wYWNr", + "ZWRfZml4ZWQzMhhgIAMoB0ICEAESGgoOcGFja2VkX2ZpeGVkNjQYYSADKAZC", + "AhABEhsKD3BhY2tlZF9zZml4ZWQzMhhiIAMoD0ICEAESGwoPcGFja2VkX3Nm", + "aXhlZDY0GGMgAygQQgIQARIYCgxwYWNrZWRfZmxvYXQYZCADKAJCAhABEhkK", + "DXBhY2tlZF9kb3VibGUYZSADKAFCAhABEhcKC3BhY2tlZF9ib29sGGYgAygI", + "QgIQARI+CgtwYWNrZWRfZW51bRhnIAMoDjIlLnByb3RvYnVmX3VuaXR0ZXN0", + "X3Byb3RvMi5Gb3JlaWduRW51bUICEAEizwMKEVRlc3RVbnBhY2tlZFR5cGVz", + "EhoKDnVucGFja2VkX2ludDMyGFogAygFQgIQABIaCg51bnBhY2tlZF9pbnQ2", + "NBhbIAMoA0ICEAASGwoPdW5wYWNrZWRfdWludDMyGFwgAygNQgIQABIbCg91", + "bnBhY2tlZF91aW50NjQYXSADKARCAhAAEhsKD3VucGFja2VkX3NpbnQzMhhe", + "IAMoEUICEAASGwoPdW5wYWNrZWRfc2ludDY0GF8gAygSQgIQABIcChB1bnBh", + "Y2tlZF9maXhlZDMyGGAgAygHQgIQABIcChB1bnBhY2tlZF9maXhlZDY0GGEg", + "AygGQgIQABIdChF1bnBhY2tlZF9zZml4ZWQzMhhiIAMoD0ICEAASHQoRdW5w", + "YWNrZWRfc2ZpeGVkNjQYYyADKBBCAhAAEhoKDnVucGFja2VkX2Zsb2F0GGQg", + "AygCQgIQABIbCg91bnBhY2tlZF9kb3VibGUYZSADKAFCAhAAEhkKDXVucGFj", + "a2VkX2Jvb2wYZiADKAhCAhAAEkAKDXVucGFja2VkX2VudW0YZyADKA4yJS5w", + "cm90b2J1Zl91bml0dGVzdF9wcm90bzIuRm9yZWlnbkVudW1CAhAAIiAKFFRl", + "c3RQYWNrZWRFeHRlbnNpb25zKggIARCAgICAAiIiChZUZXN0VW5wYWNrZWRF", + "eHRlbnNpb25zKggIARCAgICAAiK1BAoVVGVzdER5bmFtaWNFeHRlbnNpb25z", + "EhkKEHNjYWxhcl9leHRlbnNpb24Y0A8gASgHEj4KDmVudW1fZXh0ZW5zaW9u", + "GNEPIAEoDjIlLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5Gb3JlaWduRW51", + "bRJgChZkeW5hbWljX2VudW1fZXh0ZW5zaW9uGNIPIAEoDjI/LnByb3RvYnVm", + "X3VuaXR0ZXN0X3Byb3RvMi5UZXN0RHluYW1pY0V4dGVuc2lvbnMuRHluYW1p", + "Y0VudW1UeXBlEkQKEW1lc3NhZ2VfZXh0ZW5zaW9uGNMPIAEoCzIoLnByb3Rv", + "YnVmX3VuaXR0ZXN0X3Byb3RvMi5Gb3JlaWduTWVzc2FnZRJmChlkeW5hbWlj", + "X21lc3NhZ2VfZXh0ZW5zaW9uGNQPIAEoCzJCLnByb3RvYnVmX3VuaXR0ZXN0", + "X3Byb3RvMi5UZXN0RHluYW1pY0V4dGVuc2lvbnMuRHluYW1pY01lc3NhZ2VU", + "eXBlEhsKEnJlcGVhdGVkX2V4dGVuc2lvbhjVDyADKAkSHQoQcGFja2VkX2V4", + "dGVuc2lvbhjWDyADKBFCAhABGiwKEkR5bmFtaWNNZXNzYWdlVHlwZRIWCg1k", + "eW5hbWljX2ZpZWxkGLQQIAEoBSJHCg9EeW5hbWljRW51bVR5cGUSEAoLRFlO", + "QU1JQ19GT08QmBESEAoLRFlOQU1JQ19CQVIQmRESEAoLRFlOQU1JQ19CQVoQ", + "mhEiwAEKI1Rlc3RSZXBlYXRlZFNjYWxhckRpZmZlcmVudFRhZ1NpemVzEhgK", + "EHJlcGVhdGVkX2ZpeGVkMzIYDCADKAcSFgoOcmVwZWF0ZWRfaW50MzIYDSAD", + "KAUSGQoQcmVwZWF0ZWRfZml4ZWQ2NBj+DyADKAYSFwoOcmVwZWF0ZWRfaW50", + "NjQY/w8gAygDEhgKDnJlcGVhdGVkX2Zsb2F0GP7/DyADKAISGQoPcmVwZWF0", + "ZWRfdWludDY0GP//DyADKAQigwsKEFRlc3RQYXJzaW5nTWVyZ2USQgoScmVx", + "dWlyZWRfYWxsX3R5cGVzGAEgAigLMiYucHJvdG9idWZfdW5pdHRlc3RfcHJv", + "dG8yLlRlc3RBbGxUeXBlcxJCChJvcHRpb25hbF9hbGxfdHlwZXMYAiABKAsy", + "Ji5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbFR5cGVzEkIKEnJl", + "cGVhdGVkX2FsbF90eXBlcxgDIAMoCzImLnByb3RvYnVmX3VuaXR0ZXN0X3By", + "b3RvMi5UZXN0QWxsVHlwZXMSTwoNb3B0aW9uYWxncm91cBgKIAEoCjI4LnBy", + "b3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0UGFyc2luZ01lcmdlLk9wdGlv", + "bmFsR3JvdXASTwoNcmVwZWF0ZWRncm91cBgUIAMoCjI4LnByb3RvYnVmX3Vu", + "aXR0ZXN0X3Byb3RvMi5UZXN0UGFyc2luZ01lcmdlLlJlcGVhdGVkR3JvdXAa", + "6QQKF1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yEjYKBmZpZWxkMRgBIAMoCzIm", + "LnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsVHlwZXMSNgoGZmll", + "bGQyGAIgAygLMiYucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxU", + "eXBlcxI2CgZmaWVsZDMYAyADKAsyJi5wcm90b2J1Zl91bml0dGVzdF9wcm90", + "bzIuVGVzdEFsbFR5cGVzElkKBmdyb3VwMRgKIAMoCjJJLnByb3RvYnVmX3Vu", + "aXR0ZXN0X3Byb3RvMi5UZXN0UGFyc2luZ01lcmdlLlJlcGVhdGVkRmllbGRz", + "R2VuZXJhdG9yLkdyb3VwMRJZCgZncm91cDIYFCADKAoySS5wcm90b2J1Zl91", + "bml0dGVzdF9wcm90bzIuVGVzdFBhcnNpbmdNZXJnZS5SZXBlYXRlZEZpZWxk", + "c0dlbmVyYXRvci5Hcm91cDISNQoEZXh0MRjoByADKAsyJi5wcm90b2J1Zl91", + "bml0dGVzdF9wcm90bzIuVGVzdEFsbFR5cGVzEjUKBGV4dDIY6QcgAygLMiYu", + "cHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxUeXBlcxpACgZHcm91", + "cDESNgoGZmllbGQxGAsgASgLMiYucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8y", + "LlRlc3RBbGxUeXBlcxpACgZHcm91cDISNgoGZmllbGQxGBUgASgLMiYucHJv", + "dG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxUeXBlcxpZCg1PcHRpb25h", + "bEdyb3VwEkgKGG9wdGlvbmFsX2dyb3VwX2FsbF90eXBlcxgLIAEoCzImLnBy", + "b3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsVHlwZXMaWQoNUmVwZWF0", + "ZWRHcm91cBJIChhyZXBlYXRlZF9ncm91cF9hbGxfdHlwZXMYFSABKAsyJi5w", + "cm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbFR5cGVzKgkI6AcQgICA", + "gAIyaQoMb3B0aW9uYWxfZXh0EioucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8y", + "LlRlc3RQYXJzaW5nTWVyZ2UY6AcgASgLMiYucHJvdG9idWZfdW5pdHRlc3Rf", + "cHJvdG8yLlRlc3RBbGxUeXBlczJpCgxyZXBlYXRlZF9leHQSKi5wcm90b2J1", + "Zl91bml0dGVzdF9wcm90bzIuVGVzdFBhcnNpbmdNZXJnZRjpByADKAsyJi5w", + "cm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbFR5cGVzIkQKG1Rlc3RD", + "b21tZW50SW5qZWN0aW9uTWVzc2FnZRIlCgFhGAEgASgJOhoqLyA8LSBOZWl0", + "aGVyIHNob3VsZCB0aGlzLiIMCgpGb29SZXF1ZXN0Ig0KC0Zvb1Jlc3BvbnNl", + "IhIKEEZvb0NsaWVudE1lc3NhZ2UiEgoQRm9vU2VydmVyTWVzc2FnZSIMCgpC", + "YXJSZXF1ZXN0Ig0KC0JhclJlc3BvbnNlIpIBCgxUZXN0SnNvbk5hbWUSEwoL", + "ZmllbGRfbmFtZTEYASABKAUSEgoKZmllbGROYW1lMhgCIAEoBRISCgpGaWVs", + "ZE5hbWUzGAMgASgFEhQKDF9maWVsZF9uYW1lNBgEIAEoBRITCgtGSUVMRF9O", + "QU1FNRgFIAEoBRIaCgtmaWVsZF9uYW1lNhgGIAEoBVIFQHR5cGUioAYKFFRl", + "c3RIdWdlRmllbGROdW1iZXJzEhoKDm9wdGlvbmFsX2ludDMyGPD4//8BIAEo", + "BRIUCghmaXhlZF8zMhjx+P//ASABKAUSHgoOcmVwZWF0ZWRfaW50MzIY8vj/", + "/wEgAygFQgIQABIcCgxwYWNrZWRfaW50MzIY8/j//wEgAygFQgIQARJACg1v", + "cHRpb25hbF9lbnVtGPT4//8BIAEoDjIlLnByb3RvYnVmX3VuaXR0ZXN0X3By", + "b3RvMi5Gb3JlaWduRW51bRIbCg9vcHRpb25hbF9zdHJpbmcY9fj//wEgASgJ", + "EhoKDm9wdGlvbmFsX2J5dGVzGPb4//8BIAEoDBJGChBvcHRpb25hbF9tZXNz", + "YWdlGPf4//8BIAEoCzIoLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5Gb3Jl", + "aWduTWVzc2FnZRJXCg1vcHRpb25hbGdyb3VwGPj4//8BIAEoCjI8LnByb3Rv", + "YnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0SHVnZUZpZWxkTnVtYmVycy5PcHRp", + "b25hbEdyb3VwEmIKEXN0cmluZ19zdHJpbmdfbWFwGPr4//8BIAMoCzJDLnBy", + "b3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0SHVnZUZpZWxkTnVtYmVycy5T", + "dHJpbmdTdHJpbmdNYXBFbnRyeRIaCgxvbmVvZl91aW50MzIY+/j//wEgASgN", + "SAASSgoUb25lb2ZfdGVzdF9hbGxfdHlwZXMY/Pj//wEgASgLMiYucHJvdG9i", + "dWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxUeXBlc0gAEhoKDG9uZW9mX3N0", + "cmluZxj9+P//ASABKAlIABIZCgtvbmVvZl9ieXRlcxj++P//ASABKAxIABok", + "Cg1PcHRpb25hbEdyb3VwEhMKB2dyb3VwX2EY+fj//wEgASgFGjYKFFN0cmlu", + "Z1N0cmluZ01hcEVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToC", + "OAEqDAjgqv//ARDw+P//AUINCgtvbmVvZl9maWVsZCKxAQoYVGVzdEV4dGVu", + "c2lvbkluc2lkZVRhYmxlEg4KBmZpZWxkMRgBIAEoBRIOCgZmaWVsZDIYAiAB", + "KAUSDgoGZmllbGQzGAMgASgFEg4KBmZpZWxkNBgEIAEoBRIOCgZmaWVsZDYY", + "BiABKAUSDgoGZmllbGQ3GAcgASgFEg4KBmZpZWxkOBgIIAEoBRIOCgZmaWVs", + "ZDkYCSABKAUSDwoHZmllbGQxMBgKIAEoBSoECAUQBipACgtGb3JlaWduRW51", + "bRIPCgtGT1JFSUdOX0ZPTxAEEg8KC0ZPUkVJR05fQkFSEAUSDwoLRk9SRUlH", + "Tl9CQVoQBipLChRUZXN0RW51bVdpdGhEdXBWYWx1ZRIICgRGT08xEAESCAoE", + "QkFSMRACEgcKA0JBWhADEggKBEZPTzIQARIICgRCQVIyEAIaAhABKokBCg5U", + "ZXN0U3BhcnNlRW51bRIMCghTUEFSU0VfQRB7Eg4KCFNQQVJTRV9CEKbnAxIP", + "CghTUEFSU0VfQxCysYAGEhUKCFNQQVJTRV9EEPH//////////wESFQoIU1BB", + "UlNFX0UQtN78////////ARIMCghTUEFSU0VfRhAAEgwKCFNQQVJTRV9HEAIq", + "iw8KDVZlcnlMYXJnZUVudW0SFgoSRU5VTV9MQUJFTF9ERUZBVUxUEAASEAoM", + "RU5VTV9MQUJFTF8xEAESEAoMRU5VTV9MQUJFTF8yEAISEAoMRU5VTV9MQUJF", + "TF8zEAMSEAoMRU5VTV9MQUJFTF80EAQSEAoMRU5VTV9MQUJFTF81EAUSEAoM", + "RU5VTV9MQUJFTF82EAYSEAoMRU5VTV9MQUJFTF83EAcSEAoMRU5VTV9MQUJF", + "TF84EAgSEAoMRU5VTV9MQUJFTF85EAkSEQoNRU5VTV9MQUJFTF8xMBAKEhEK", + "DUVOVU1fTEFCRUxfMTEQCxIRCg1FTlVNX0xBQkVMXzEyEAwSEQoNRU5VTV9M", + "QUJFTF8xMxANEhEKDUVOVU1fTEFCRUxfMTQQDhIRCg1FTlVNX0xBQkVMXzE1", + "EA8SEQoNRU5VTV9MQUJFTF8xNhAQEhEKDUVOVU1fTEFCRUxfMTcQERIRCg1F", + "TlVNX0xBQkVMXzE4EBISEQoNRU5VTV9MQUJFTF8xORATEhEKDUVOVU1fTEFC", + "RUxfMjAQFBIRCg1FTlVNX0xBQkVMXzIxEBUSEQoNRU5VTV9MQUJFTF8yMhAW", + "EhEKDUVOVU1fTEFCRUxfMjMQFxIRCg1FTlVNX0xBQkVMXzI0EBgSEQoNRU5V", + "TV9MQUJFTF8yNRAZEhEKDUVOVU1fTEFCRUxfMjYQGhIRCg1FTlVNX0xBQkVM", + "XzI3EBsSEQoNRU5VTV9MQUJFTF8yOBAcEhEKDUVOVU1fTEFCRUxfMjkQHRIR", + "Cg1FTlVNX0xBQkVMXzMwEB4SEQoNRU5VTV9MQUJFTF8zMRAfEhEKDUVOVU1f", + "TEFCRUxfMzIQIBIRCg1FTlVNX0xBQkVMXzMzECESEQoNRU5VTV9MQUJFTF8z", + "NBAiEhEKDUVOVU1fTEFCRUxfMzUQIxIRCg1FTlVNX0xBQkVMXzM2ECQSEQoN", + "RU5VTV9MQUJFTF8zNxAlEhEKDUVOVU1fTEFCRUxfMzgQJhIRCg1FTlVNX0xB", + "QkVMXzM5ECcSEQoNRU5VTV9MQUJFTF80MBAoEhEKDUVOVU1fTEFCRUxfNDEQ", + "KRIRCg1FTlVNX0xBQkVMXzQyECoSEQoNRU5VTV9MQUJFTF80MxArEhEKDUVO", + "VU1fTEFCRUxfNDQQLBIRCg1FTlVNX0xBQkVMXzQ1EC0SEQoNRU5VTV9MQUJF", + "TF80NhAuEhEKDUVOVU1fTEFCRUxfNDcQLxIRCg1FTlVNX0xBQkVMXzQ4EDAS", + "EQoNRU5VTV9MQUJFTF80ORAxEhEKDUVOVU1fTEFCRUxfNTAQMhIRCg1FTlVN", + "X0xBQkVMXzUxEDMSEQoNRU5VTV9MQUJFTF81MhA0EhEKDUVOVU1fTEFCRUxf", + "NTMQNRIRCg1FTlVNX0xBQkVMXzU0EDYSEQoNRU5VTV9MQUJFTF81NRA3EhEK", + "DUVOVU1fTEFCRUxfNTYQOBIRCg1FTlVNX0xBQkVMXzU3EDkSEQoNRU5VTV9M", + "QUJFTF81OBA6EhEKDUVOVU1fTEFCRUxfNTkQOxIRCg1FTlVNX0xBQkVMXzYw", + "EDwSEQoNRU5VTV9MQUJFTF82MRA9EhEKDUVOVU1fTEFCRUxfNjIQPhIRCg1F", + "TlVNX0xBQkVMXzYzED8SEQoNRU5VTV9MQUJFTF82NBBAEhEKDUVOVU1fTEFC", + "RUxfNjUQQRIRCg1FTlVNX0xBQkVMXzY2EEISEQoNRU5VTV9MQUJFTF82NxBD", + "EhEKDUVOVU1fTEFCRUxfNjgQRBIRCg1FTlVNX0xBQkVMXzY5EEUSEQoNRU5V", + "TV9MQUJFTF83MBBGEhEKDUVOVU1fTEFCRUxfNzEQRxIRCg1FTlVNX0xBQkVM", + "XzcyEEgSEQoNRU5VTV9MQUJFTF83MxBJEhEKDUVOVU1fTEFCRUxfNzQQShIR", + "Cg1FTlVNX0xBQkVMXzc1EEsSEQoNRU5VTV9MQUJFTF83NhBMEhEKDUVOVU1f", + "TEFCRUxfNzcQTRIRCg1FTlVNX0xBQkVMXzc4EE4SEQoNRU5VTV9MQUJFTF83", + "ORBPEhEKDUVOVU1fTEFCRUxfODAQUBIRCg1FTlVNX0xBQkVMXzgxEFESEQoN", + "RU5VTV9MQUJFTF84MhBSEhEKDUVOVU1fTEFCRUxfODMQUxIRCg1FTlVNX0xB", + "QkVMXzg0EFQSEQoNRU5VTV9MQUJFTF84NRBVEhEKDUVOVU1fTEFCRUxfODYQ", + "VhIRCg1FTlVNX0xBQkVMXzg3EFcSEQoNRU5VTV9MQUJFTF84OBBYEhEKDUVO", + "VU1fTEFCRUxfODkQWRIRCg1FTlVNX0xBQkVMXzkwEFoSEQoNRU5VTV9MQUJF", + "TF85MRBbEhEKDUVOVU1fTEFCRUxfOTIQXBIRCg1FTlVNX0xBQkVMXzkzEF0S", + "EQoNRU5VTV9MQUJFTF85NBBeEhEKDUVOVU1fTEFCRUxfOTUQXxIRCg1FTlVN", + "X0xBQkVMXzk2EGASEQoNRU5VTV9MQUJFTF85NxBhEhEKDUVOVU1fTEFCRUxf", + "OTgQYhIRCg1FTlVNX0xBQkVMXzk5EGMSEgoORU5VTV9MQUJFTF8xMDAQZDK1", + "AQoLVGVzdFNlcnZpY2USUgoDRm9vEiQucHJvdG9idWZfdW5pdHRlc3RfcHJv", + "dG8yLkZvb1JlcXVlc3QaJS5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuRm9v", + "UmVzcG9uc2USUgoDQmFyEiQucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLkJh", + "clJlcXVlc3QaJS5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuQmFyUmVzcG9u", + "c2U6TQoYb3B0aW9uYWxfaW50MzJfZXh0ZW5zaW9uEisucHJvdG9idWZfdW5p", + "dHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRlbnNpb25zGAEgASgFOk0KGG9wdGlv", + "bmFsX2ludDY0X2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3Rv", + "Mi5UZXN0QWxsRXh0ZW5zaW9ucxgCIAEoAzpOChlvcHRpb25hbF91aW50MzJf", + "ZXh0ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxF", + "eHRlbnNpb25zGAMgASgNOk4KGW9wdGlvbmFsX3VpbnQ2NF9leHRlbnNpb24S", + "Ky5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbEV4dGVuc2lvbnMY", + "BCABKAQ6TgoZb3B0aW9uYWxfc2ludDMyX2V4dGVuc2lvbhIrLnByb3RvYnVm", + "X3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsRXh0ZW5zaW9ucxgFIAEoETpOChlv", + "cHRpb25hbF9zaW50NjRfZXh0ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3Rf", + "cHJvdG8yLlRlc3RBbGxFeHRlbnNpb25zGAYgASgSOk8KGm9wdGlvbmFsX2Zp", + "eGVkMzJfZXh0ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRl", + "c3RBbGxFeHRlbnNpb25zGAcgASgHOk8KGm9wdGlvbmFsX2ZpeGVkNjRfZXh0", + "ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRl", + "bnNpb25zGAggASgGOlAKG29wdGlvbmFsX3NmaXhlZDMyX2V4dGVuc2lvbhIr", + "LnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsRXh0ZW5zaW9ucxgJ", + "IAEoDzpQChtvcHRpb25hbF9zZml4ZWQ2NF9leHRlbnNpb24SKy5wcm90b2J1", + "Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbEV4dGVuc2lvbnMYCiABKBA6TQoY", + "b3B0aW9uYWxfZmxvYXRfZXh0ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3Rf", + "cHJvdG8yLlRlc3RBbGxFeHRlbnNpb25zGAsgASgCOk4KGW9wdGlvbmFsX2Rv", + "dWJsZV9leHRlbnNpb24SKy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVz", + "dEFsbEV4dGVuc2lvbnMYDCABKAE6TAoXb3B0aW9uYWxfYm9vbF9leHRlbnNp", + "b24SKy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbEV4dGVuc2lv", + "bnMYDSABKAg6TgoZb3B0aW9uYWxfc3RyaW5nX2V4dGVuc2lvbhIrLnByb3Rv", + "YnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsRXh0ZW5zaW9ucxgOIAEoCTpN", + "ChhvcHRpb25hbF9ieXRlc19leHRlbnNpb24SKy5wcm90b2J1Zl91bml0dGVz", + "dF9wcm90bzIuVGVzdEFsbEV4dGVuc2lvbnMYDyABKAw6fwoXb3B0aW9uYWxn", + "cm91cF9leHRlbnNpb24SKy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVz", + "dEFsbEV4dGVuc2lvbnMYECABKAoyMS5wcm90b2J1Zl91bml0dGVzdF9wcm90", + "bzIuT3B0aW9uYWxHcm91cF9leHRlbnNpb246jAEKIW9wdGlvbmFsX25lc3Rl", + "ZF9tZXNzYWdlX2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3Rv", + "Mi5UZXN0QWxsRXh0ZW5zaW9ucxgSIAEoCzI0LnByb3RvYnVmX3VuaXR0ZXN0", + "X3Byb3RvMi5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZTqBAQoib3B0aW9u", + "YWxfZm9yZWlnbl9tZXNzYWdlX2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0", + "ZXN0X3Byb3RvMi5UZXN0QWxsRXh0ZW5zaW9ucxgTIAEoCzIoLnByb3RvYnVm", + "X3VuaXR0ZXN0X3Byb3RvMi5Gb3JlaWduTWVzc2FnZTqGAQohb3B0aW9uYWxf", + "aW1wb3J0X21lc3NhZ2VfZXh0ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3Rf", + "cHJvdG8yLlRlc3RBbGxFeHRlbnNpb25zGBQgASgLMi4ucHJvdG9idWZfdW5p", + "dHRlc3RfaW1wb3J0X3Byb3RvMi5JbXBvcnRNZXNzYWdlOoYBCh5vcHRpb25h", + "bF9uZXN0ZWRfZW51bV9leHRlbnNpb24SKy5wcm90b2J1Zl91bml0dGVzdF9w", + "cm90bzIuVGVzdEFsbEV4dGVuc2lvbnMYFSABKA4yMS5wcm90b2J1Zl91bml0", + "dGVzdF9wcm90bzIuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW06ewofb3B0aW9u", + "YWxfZm9yZWlnbl9lbnVtX2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0", + "X3Byb3RvMi5UZXN0QWxsRXh0ZW5zaW9ucxgWIAEoDjIlLnByb3RvYnVmX3Vu", + "aXR0ZXN0X3Byb3RvMi5Gb3JlaWduRW51bTqAAQoeb3B0aW9uYWxfaW1wb3J0", + "X2VudW1fZXh0ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRl", + "c3RBbGxFeHRlbnNpb25zGBcgASgOMisucHJvdG9idWZfdW5pdHRlc3RfaW1w", + "b3J0X3Byb3RvMi5JbXBvcnRFbnVtOlgKH29wdGlvbmFsX3N0cmluZ19waWVj", + "ZV9leHRlbnNpb24SKy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFs", + "bEV4dGVuc2lvbnMYGCABKAlCAggCOlAKF29wdGlvbmFsX2NvcmRfZXh0ZW5z", + "aW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRlbnNp", + "b25zGBkgASgJQgIIATqTAQoob3B0aW9uYWxfcHVibGljX2ltcG9ydF9tZXNz", + "YWdlX2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0", + "QWxsRXh0ZW5zaW9ucxgaIAEoCzI0LnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9y", + "dF9wcm90bzIuUHVibGljSW1wb3J0TWVzc2FnZTqOAQofb3B0aW9uYWxfbGF6", + "eV9tZXNzYWdlX2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3Rv", + "Mi5UZXN0QWxsRXh0ZW5zaW9ucxgbIAEoCzI0LnByb3RvYnVmX3VuaXR0ZXN0", + "X3Byb3RvMi5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZUICKAE6TQoYcmVw", + "ZWF0ZWRfaW50MzJfZXh0ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJv", + "dG8yLlRlc3RBbGxFeHRlbnNpb25zGB8gAygFOk0KGHJlcGVhdGVkX2ludDY0", + "X2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxs", + "RXh0ZW5zaW9ucxggIAMoAzpOChlyZXBlYXRlZF91aW50MzJfZXh0ZW5zaW9u", + "EisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRlbnNpb25z", + "GCEgAygNOk4KGXJlcGVhdGVkX3VpbnQ2NF9leHRlbnNpb24SKy5wcm90b2J1", + "Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbEV4dGVuc2lvbnMYIiADKAQ6TgoZ", + "cmVwZWF0ZWRfc2ludDMyX2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0", + "X3Byb3RvMi5UZXN0QWxsRXh0ZW5zaW9ucxgjIAMoETpOChlyZXBlYXRlZF9z", + "aW50NjRfZXh0ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRl", + "c3RBbGxFeHRlbnNpb25zGCQgAygSOk8KGnJlcGVhdGVkX2ZpeGVkMzJfZXh0", + "ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRl", + "bnNpb25zGCUgAygHOk8KGnJlcGVhdGVkX2ZpeGVkNjRfZXh0ZW5zaW9uEisu", + "cHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRlbnNpb25zGCYg", + "AygGOlAKG3JlcGVhdGVkX3NmaXhlZDMyX2V4dGVuc2lvbhIrLnByb3RvYnVm", + "X3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsRXh0ZW5zaW9ucxgnIAMoDzpQChty", + "ZXBlYXRlZF9zZml4ZWQ2NF9leHRlbnNpb24SKy5wcm90b2J1Zl91bml0dGVz", + "dF9wcm90bzIuVGVzdEFsbEV4dGVuc2lvbnMYKCADKBA6TQoYcmVwZWF0ZWRf", + "ZmxvYXRfZXh0ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRl", + "c3RBbGxFeHRlbnNpb25zGCkgAygCOk4KGXJlcGVhdGVkX2RvdWJsZV9leHRl", + "bnNpb24SKy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbEV4dGVu", + "c2lvbnMYKiADKAE6TAoXcmVwZWF0ZWRfYm9vbF9leHRlbnNpb24SKy5wcm90", + "b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbEV4dGVuc2lvbnMYKyADKAg6", + "TgoZcmVwZWF0ZWRfc3RyaW5nX2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0", + "ZXN0X3Byb3RvMi5UZXN0QWxsRXh0ZW5zaW9ucxgsIAMoCTpNChhyZXBlYXRl", + "ZF9ieXRlc19leHRlbnNpb24SKy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIu", + "VGVzdEFsbEV4dGVuc2lvbnMYLSADKAw6fwoXcmVwZWF0ZWRncm91cF9leHRl", + "bnNpb24SKy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbEV4dGVu", + "c2lvbnMYLiADKAoyMS5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuUmVwZWF0", + "ZWRHcm91cF9leHRlbnNpb246jAEKIXJlcGVhdGVkX25lc3RlZF9tZXNzYWdl", + "X2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxs", + "RXh0ZW5zaW9ucxgwIAMoCzI0LnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5U", + "ZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZTqBAQoicmVwZWF0ZWRfZm9yZWln", + "bl9tZXNzYWdlX2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3Rv", + "Mi5UZXN0QWxsRXh0ZW5zaW9ucxgxIAMoCzIoLnByb3RvYnVmX3VuaXR0ZXN0", + "X3Byb3RvMi5Gb3JlaWduTWVzc2FnZTqGAQohcmVwZWF0ZWRfaW1wb3J0X21l", + "c3NhZ2VfZXh0ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRl", + "c3RBbGxFeHRlbnNpb25zGDIgAygLMi4ucHJvdG9idWZfdW5pdHRlc3RfaW1w", + "b3J0X3Byb3RvMi5JbXBvcnRNZXNzYWdlOoYBCh5yZXBlYXRlZF9uZXN0ZWRf", + "ZW51bV9leHRlbnNpb24SKy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVz", + "dEFsbEV4dGVuc2lvbnMYMyADKA4yMS5wcm90b2J1Zl91bml0dGVzdF9wcm90", + "bzIuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW06ewofcmVwZWF0ZWRfZm9yZWln", + "bl9lbnVtX2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5U", + "ZXN0QWxsRXh0ZW5zaW9ucxg0IAMoDjIlLnByb3RvYnVmX3VuaXR0ZXN0X3By", + "b3RvMi5Gb3JlaWduRW51bTqAAQoecmVwZWF0ZWRfaW1wb3J0X2VudW1fZXh0", + "ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRl", + "bnNpb25zGDUgAygOMisucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0X3Byb3Rv", + "Mi5JbXBvcnRFbnVtOlgKH3JlcGVhdGVkX3N0cmluZ19waWVjZV9leHRlbnNp", + "b24SKy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbEV4dGVuc2lv", + "bnMYNiADKAlCAggCOlAKF3JlcGVhdGVkX2NvcmRfZXh0ZW5zaW9uEisucHJv", + "dG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRlbnNpb25zGDcgAygJ", + "QgIIATqOAQofcmVwZWF0ZWRfbGF6eV9tZXNzYWdlX2V4dGVuc2lvbhIrLnBy", + "b3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsRXh0ZW5zaW9ucxg5IAMo", + "CzI0LnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsVHlwZXMuTmVz", + "dGVkTWVzc2FnZUICKAE6UAoXZGVmYXVsdF9pbnQzMl9leHRlbnNpb24SKy5w", + "cm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFsbEV4dGVuc2lvbnMYPSAB", + "KAU6AjQxOlAKF2RlZmF1bHRfaW50NjRfZXh0ZW5zaW9uEisucHJvdG9idWZf", + "dW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRlbnNpb25zGD4gASgDOgI0MjpR", + "ChhkZWZhdWx0X3VpbnQzMl9leHRlbnNpb24SKy5wcm90b2J1Zl91bml0dGVz", + "dF9wcm90bzIuVGVzdEFsbEV4dGVuc2lvbnMYPyABKA06AjQzOlEKGGRlZmF1", + "bHRfdWludDY0X2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3Rv", + "Mi5UZXN0QWxsRXh0ZW5zaW9ucxhAIAEoBDoCNDQ6UgoYZGVmYXVsdF9zaW50", + "MzJfZXh0ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RB", + "bGxFeHRlbnNpb25zGEEgASgROgMtNDU6UQoYZGVmYXVsdF9zaW50NjRfZXh0", + "ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRl", + "bnNpb25zGEIgASgSOgI0NjpSChlkZWZhdWx0X2ZpeGVkMzJfZXh0ZW5zaW9u", + "EisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRlbnNpb25z", + "GEMgASgHOgI0NzpSChlkZWZhdWx0X2ZpeGVkNjRfZXh0ZW5zaW9uEisucHJv", + "dG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRlbnNpb25zGEQgASgG", + "OgI0ODpTChpkZWZhdWx0X3NmaXhlZDMyX2V4dGVuc2lvbhIrLnByb3RvYnVm", + "X3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsRXh0ZW5zaW9ucxhFIAEoDzoCNDk6", + "VAoaZGVmYXVsdF9zZml4ZWQ2NF9leHRlbnNpb24SKy5wcm90b2J1Zl91bml0", + "dGVzdF9wcm90bzIuVGVzdEFsbEV4dGVuc2lvbnMYRiABKBA6Ay01MDpSChdk", + "ZWZhdWx0X2Zsb2F0X2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0X3By", + "b3RvMi5UZXN0QWxsRXh0ZW5zaW9ucxhHIAEoAjoENTEuNTpUChhkZWZhdWx0", + "X2RvdWJsZV9leHRlbnNpb24SKy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIu", + "VGVzdEFsbEV4dGVuc2lvbnMYSCABKAE6BTUyMDAwOlEKFmRlZmF1bHRfYm9v", + "bF9leHRlbnNpb24SKy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFs", + "bEV4dGVuc2lvbnMYSSABKAg6BHRydWU6VAoYZGVmYXVsdF9zdHJpbmdfZXh0", + "ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRl", + "bnNpb25zGEogASgJOgVoZWxsbzpTChdkZWZhdWx0X2J5dGVzX2V4dGVuc2lv", + "bhIrLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsRXh0ZW5zaW9u", + "cxhLIAEoDDoFd29ybGQ6igEKHWRlZmF1bHRfbmVzdGVkX2VudW1fZXh0ZW5z", + "aW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRlbnNp", + "b25zGFEgASgOMjEucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxU", + "eXBlcy5OZXN0ZWRFbnVtOgNCQVI6hwEKHmRlZmF1bHRfZm9yZWlnbl9lbnVt", + "X2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxs", + "RXh0ZW5zaW9ucxhSIAEoDjIlLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5G", + "b3JlaWduRW51bToLRk9SRUlHTl9CQVI6iwEKHWRlZmF1bHRfaW1wb3J0X2Vu", + "dW1fZXh0ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RB", + "bGxFeHRlbnNpb25zGFMgASgOMisucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0", + "X3Byb3RvMi5JbXBvcnRFbnVtOgpJTVBPUlRfQkFSOlwKHmRlZmF1bHRfc3Ry", + "aW5nX3BpZWNlX2V4dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3Rv", + "Mi5UZXN0QWxsRXh0ZW5zaW9ucxhUIAEoCToDYWJjQgIIAjpUChZkZWZhdWx0", + "X2NvcmRfZXh0ZW5zaW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRl", + "c3RBbGxFeHRlbnNpb25zGFUgASgJOgMxMjNCAggBOksKFm9uZW9mX3VpbnQz", + "Ml9leHRlbnNpb24SKy5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdEFs", + "bEV4dGVuc2lvbnMYbyABKA06iQEKHm9uZW9mX25lc3RlZF9tZXNzYWdlX2V4", + "dGVuc2lvbhIrLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsRXh0", + "ZW5zaW9ucxhwIAEoCzI0LnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0", + "QWxsVHlwZXMuTmVzdGVkTWVzc2FnZTpLChZvbmVvZl9zdHJpbmdfZXh0ZW5z", + "aW9uEisucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RBbGxFeHRlbnNp", + "b25zGHEgASgJOkoKFW9uZW9mX2J5dGVzX2V4dGVuc2lvbhIrLnByb3RvYnVm", + "X3VuaXR0ZXN0X3Byb3RvMi5UZXN0QWxsRXh0ZW5zaW9ucxhyIAEoDDpJChNt", + "eV9leHRlbnNpb25fc3RyaW5nEiwucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8y", + "LlRlc3RGaWVsZE9yZGVyaW5ncxgyIAEoCTpGChBteV9leHRlbnNpb25faW50", + "EiwucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RGaWVsZE9yZGVyaW5n", + "cxgFIAEoBTpSChZwYWNrZWRfaW50MzJfZXh0ZW5zaW9uEi4ucHJvdG9idWZf", + "dW5pdHRlc3RfcHJvdG8yLlRlc3RQYWNrZWRFeHRlbnNpb25zGFogAygFQgIQ", + "ATpSChZwYWNrZWRfaW50NjRfZXh0ZW5zaW9uEi4ucHJvdG9idWZfdW5pdHRl", + "c3RfcHJvdG8yLlRlc3RQYWNrZWRFeHRlbnNpb25zGFsgAygDQgIQATpTChdw", + "YWNrZWRfdWludDMyX2V4dGVuc2lvbhIuLnByb3RvYnVmX3VuaXR0ZXN0X3By", + "b3RvMi5UZXN0UGFja2VkRXh0ZW5zaW9ucxhcIAMoDUICEAE6UwoXcGFja2Vk", + "X3VpbnQ2NF9leHRlbnNpb24SLi5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIu", + "VGVzdFBhY2tlZEV4dGVuc2lvbnMYXSADKARCAhABOlMKF3BhY2tlZF9zaW50", + "MzJfZXh0ZW5zaW9uEi4ucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RQ", + "YWNrZWRFeHRlbnNpb25zGF4gAygRQgIQATpTChdwYWNrZWRfc2ludDY0X2V4", + "dGVuc2lvbhIuLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0UGFja2Vk", + "RXh0ZW5zaW9ucxhfIAMoEkICEAE6VAoYcGFja2VkX2ZpeGVkMzJfZXh0ZW5z", + "aW9uEi4ucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RQYWNrZWRFeHRl", + "bnNpb25zGGAgAygHQgIQATpUChhwYWNrZWRfZml4ZWQ2NF9leHRlbnNpb24S", + "Li5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdFBhY2tlZEV4dGVuc2lv", + "bnMYYSADKAZCAhABOlUKGXBhY2tlZF9zZml4ZWQzMl9leHRlbnNpb24SLi5w", + "cm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdFBhY2tlZEV4dGVuc2lvbnMY", + "YiADKA9CAhABOlUKGXBhY2tlZF9zZml4ZWQ2NF9leHRlbnNpb24SLi5wcm90", + "b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdFBhY2tlZEV4dGVuc2lvbnMYYyAD", + "KBBCAhABOlIKFnBhY2tlZF9mbG9hdF9leHRlbnNpb24SLi5wcm90b2J1Zl91", + "bml0dGVzdF9wcm90bzIuVGVzdFBhY2tlZEV4dGVuc2lvbnMYZCADKAJCAhAB", + "OlMKF3BhY2tlZF9kb3VibGVfZXh0ZW5zaW9uEi4ucHJvdG9idWZfdW5pdHRl", + "c3RfcHJvdG8yLlRlc3RQYWNrZWRFeHRlbnNpb25zGGUgAygBQgIQATpRChVw", + "YWNrZWRfYm9vbF9leHRlbnNpb24SLi5wcm90b2J1Zl91bml0dGVzdF9wcm90", + "bzIuVGVzdFBhY2tlZEV4dGVuc2lvbnMYZiADKAhCAhABOngKFXBhY2tlZF9l", + "bnVtX2V4dGVuc2lvbhIuLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0", + "UGFja2VkRXh0ZW5zaW9ucxhnIAMoDjIlLnByb3RvYnVmX3VuaXR0ZXN0X3By", + "b3RvMi5Gb3JlaWduRW51bUICEAE6VgoYdW5wYWNrZWRfaW50MzJfZXh0ZW5z", + "aW9uEjAucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RVbnBhY2tlZEV4", + "dGVuc2lvbnMYWiADKAVCAhAAOlYKGHVucGFja2VkX2ludDY0X2V4dGVuc2lv", + "bhIwLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0VW5wYWNrZWRFeHRl", + "bnNpb25zGFsgAygDQgIQADpXChl1bnBhY2tlZF91aW50MzJfZXh0ZW5zaW9u", + "EjAucHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RVbnBhY2tlZEV4dGVu", + "c2lvbnMYXCADKA1CAhAAOlcKGXVucGFja2VkX3VpbnQ2NF9leHRlbnNpb24S", + "MC5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdFVucGFja2VkRXh0ZW5z", + "aW9ucxhdIAMoBEICEAA6VwoZdW5wYWNrZWRfc2ludDMyX2V4dGVuc2lvbhIw", + "LnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0VW5wYWNrZWRFeHRlbnNp", + "b25zGF4gAygRQgIQADpXChl1bnBhY2tlZF9zaW50NjRfZXh0ZW5zaW9uEjAu", + "cHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RVbnBhY2tlZEV4dGVuc2lv", + "bnMYXyADKBJCAhAAOlgKGnVucGFja2VkX2ZpeGVkMzJfZXh0ZW5zaW9uEjAu", + "cHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RVbnBhY2tlZEV4dGVuc2lv", + "bnMYYCADKAdCAhAAOlgKGnVucGFja2VkX2ZpeGVkNjRfZXh0ZW5zaW9uEjAu", + "cHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RVbnBhY2tlZEV4dGVuc2lv", + "bnMYYSADKAZCAhAAOlkKG3VucGFja2VkX3NmaXhlZDMyX2V4dGVuc2lvbhIw", + "LnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5UZXN0VW5wYWNrZWRFeHRlbnNp", + "b25zGGIgAygPQgIQADpZCht1bnBhY2tlZF9zZml4ZWQ2NF9leHRlbnNpb24S", + "MC5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdFVucGFja2VkRXh0ZW5z", + "aW9ucxhjIAMoEEICEAA6VgoYdW5wYWNrZWRfZmxvYXRfZXh0ZW5zaW9uEjAu", + "cHJvdG9idWZfdW5pdHRlc3RfcHJvdG8yLlRlc3RVbnBhY2tlZEV4dGVuc2lv", + "bnMYZCADKAJCAhAAOlcKGXVucGFja2VkX2RvdWJsZV9leHRlbnNpb24SMC5w", + "cm90b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdFVucGFja2VkRXh0ZW5zaW9u", + "cxhlIAMoAUICEAA6VQoXdW5wYWNrZWRfYm9vbF9leHRlbnNpb24SMC5wcm90", + "b2J1Zl91bml0dGVzdF9wcm90bzIuVGVzdFVucGFja2VkRXh0ZW5zaW9ucxhm", + "IAMoCEICEAA6fAoXdW5wYWNrZWRfZW51bV9leHRlbnNpb24SMC5wcm90b2J1", + "Zl91bml0dGVzdF9wcm90bzIuVGVzdFVucGFja2VkRXh0ZW5zaW9ucxhnIAMo", + "DjIlLnByb3RvYnVmX3VuaXR0ZXN0X3Byb3RvMi5Gb3JlaWduRW51bUICEAA6", + "cgoOdGVzdF9hbGxfdHlwZXMSLi5wcm90b2J1Zl91bml0dGVzdF9wcm90bzIu", + "VGVzdEh1Z2VGaWVsZE51bWJlcnMY4Kr//wEgASgLMiYucHJvdG9idWZfdW5p", + "dHRlc3RfcHJvdG8yLlRlc3RBbGxUeXBlczphCiV0ZXN0X2V4dGVuc2lvbl9p", + "bnNpZGVfdGFibGVfZXh0ZW5zaW9uEjIucHJvdG9idWZfdW5pdHRlc3RfcHJv", + "dG8yLlRlc3RFeHRlbnNpb25JbnNpZGVUYWJsZRgFIAEoBUIySAGAAQGIAQGQ", + "AQH4AQGqAiFHb29nbGUuUHJvdG9idWYuVGVzdFByb3Rvcy5Qcm90bzI=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.Proto2.UnittestImportReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.Proto2.ForeignEnum), typeof(global::Google.Protobuf.TestProtos.Proto2.TestEnumWithDupValue), typeof(global::Google.Protobuf.TestProtos.Proto2.TestSparseEnum), typeof(global::Google.Protobuf.TestProtos.Proto2.VeryLargeEnum), }, new pb::Extension[] { UnittestExtensions.OptionalInt32Extension, UnittestExtensions.OptionalInt64Extension, UnittestExtensions.OptionalUint32Extension, UnittestExtensions.OptionalUint64Extension, UnittestExtensions.OptionalSint32Extension, UnittestExtensions.OptionalSint64Extension, UnittestExtensions.OptionalFixed32Extension, UnittestExtensions.OptionalFixed64Extension, UnittestExtensions.OptionalSfixed32Extension, UnittestExtensions.OptionalSfixed64Extension, UnittestExtensions.OptionalFloatExtension, UnittestExtensions.OptionalDoubleExtension, UnittestExtensions.OptionalBoolExtension, UnittestExtensions.OptionalStringExtension, UnittestExtensions.OptionalBytesExtension, UnittestExtensions.OptionalGroupExtension, UnittestExtensions.OptionalNestedMessageExtension, UnittestExtensions.OptionalForeignMessageExtension, UnittestExtensions.OptionalImportMessageExtension, UnittestExtensions.OptionalNestedEnumExtension, UnittestExtensions.OptionalForeignEnumExtension, UnittestExtensions.OptionalImportEnumExtension, UnittestExtensions.OptionalStringPieceExtension, UnittestExtensions.OptionalCordExtension, UnittestExtensions.OptionalPublicImportMessageExtension, UnittestExtensions.OptionalLazyMessageExtension, UnittestExtensions.RepeatedInt32Extension, UnittestExtensions.RepeatedInt64Extension, UnittestExtensions.RepeatedUint32Extension, UnittestExtensions.RepeatedUint64Extension, UnittestExtensions.RepeatedSint32Extension, UnittestExtensions.RepeatedSint64Extension, UnittestExtensions.RepeatedFixed32Extension, UnittestExtensions.RepeatedFixed64Extension, UnittestExtensions.RepeatedSfixed32Extension, UnittestExtensions.RepeatedSfixed64Extension, UnittestExtensions.RepeatedFloatExtension, UnittestExtensions.RepeatedDoubleExtension, UnittestExtensions.RepeatedBoolExtension, UnittestExtensions.RepeatedStringExtension, UnittestExtensions.RepeatedBytesExtension, UnittestExtensions.RepeatedGroupExtension, UnittestExtensions.RepeatedNestedMessageExtension, UnittestExtensions.RepeatedForeignMessageExtension, UnittestExtensions.RepeatedImportMessageExtension, UnittestExtensions.RepeatedNestedEnumExtension, UnittestExtensions.RepeatedForeignEnumExtension, UnittestExtensions.RepeatedImportEnumExtension, UnittestExtensions.RepeatedStringPieceExtension, UnittestExtensions.RepeatedCordExtension, UnittestExtensions.RepeatedLazyMessageExtension, UnittestExtensions.DefaultInt32Extension, UnittestExtensions.DefaultInt64Extension, UnittestExtensions.DefaultUint32Extension, UnittestExtensions.DefaultUint64Extension, UnittestExtensions.DefaultSint32Extension, UnittestExtensions.DefaultSint64Extension, UnittestExtensions.DefaultFixed32Extension, UnittestExtensions.DefaultFixed64Extension, UnittestExtensions.DefaultSfixed32Extension, UnittestExtensions.DefaultSfixed64Extension, UnittestExtensions.DefaultFloatExtension, UnittestExtensions.DefaultDoubleExtension, UnittestExtensions.DefaultBoolExtension, UnittestExtensions.DefaultStringExtension, UnittestExtensions.DefaultBytesExtension, UnittestExtensions.DefaultNestedEnumExtension, UnittestExtensions.DefaultForeignEnumExtension, UnittestExtensions.DefaultImportEnumExtension, UnittestExtensions.DefaultStringPieceExtension, UnittestExtensions.DefaultCordExtension, UnittestExtensions.OneofUint32Extension, UnittestExtensions.OneofNestedMessageExtension, UnittestExtensions.OneofStringExtension, UnittestExtensions.OneofBytesExtension, UnittestExtensions.MyExtensionString, UnittestExtensions.MyExtensionInt, UnittestExtensions.PackedInt32Extension, UnittestExtensions.PackedInt64Extension, UnittestExtensions.PackedUint32Extension, UnittestExtensions.PackedUint64Extension, UnittestExtensions.PackedSint32Extension, UnittestExtensions.PackedSint64Extension, UnittestExtensions.PackedFixed32Extension, UnittestExtensions.PackedFixed64Extension, UnittestExtensions.PackedSfixed32Extension, UnittestExtensions.PackedSfixed64Extension, UnittestExtensions.PackedFloatExtension, UnittestExtensions.PackedDoubleExtension, UnittestExtensions.PackedBoolExtension, UnittestExtensions.PackedEnumExtension, UnittestExtensions.UnpackedInt32Extension, UnittestExtensions.UnpackedInt64Extension, UnittestExtensions.UnpackedUint32Extension, UnittestExtensions.UnpackedUint64Extension, UnittestExtensions.UnpackedSint32Extension, UnittestExtensions.UnpackedSint64Extension, UnittestExtensions.UnpackedFixed32Extension, UnittestExtensions.UnpackedFixed64Extension, UnittestExtensions.UnpackedSfixed32Extension, UnittestExtensions.UnpackedSfixed64Extension, UnittestExtensions.UnpackedFloatExtension, UnittestExtensions.UnpackedDoubleExtension, UnittestExtensions.UnpackedBoolExtension, UnittestExtensions.UnpackedEnumExtension, UnittestExtensions.TestAllTypes, UnittestExtensions.TestExtensionInsideTableExtension }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestAllTypes), global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalGroup", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalImportMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalImportEnum", "OptionalStringPiece", "OptionalCord", "OptionalPublicImportMessage", "OptionalLazyMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedGroup", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedImportMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedImportEnum", "RepeatedStringPiece", "RepeatedCord", "RepeatedLazyMessage", "DefaultInt32", "DefaultInt64", "DefaultUint32", "DefaultUint64", "DefaultSint32", "DefaultSint64", "DefaultFixed32", "DefaultFixed64", "DefaultSfixed32", "DefaultSfixed64", "DefaultFloat", "DefaultDouble", "DefaultBool", "DefaultString", "DefaultBytes", "DefaultNestedEnum", "DefaultForeignEnum", "DefaultImportEnum", "DefaultStringPiece", "DefaultCord", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes" }, new[]{ "OneofField" }, new[]{ typeof(global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage), global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser, new[]{ "Bb" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.OptionalGroup), global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.OptionalGroup.Parser, new[]{ "A" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.RepeatedGroup), global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.RepeatedGroup.Parser, new[]{ "A" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes), global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes.Parser, new[]{ "Child", "Payload", "RepeatedChild" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestDeprecatedFields), global::Google.Protobuf.TestProtos.Proto2.TestDeprecatedFields.Parser, new[]{ "DeprecatedInt32", "DeprecatedInt32InOneof" }, new[]{ "OneofFields" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestDeprecatedMessage), global::Google.Protobuf.TestProtos.Proto2.TestDeprecatedMessage.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.ForeignMessage), global::Google.Protobuf.TestProtos.Proto2.ForeignMessage.Parser, new[]{ "C", "D" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestReservedFields), global::Google.Protobuf.TestProtos.Proto2.TestReservedFields.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestAllExtensions), global::Google.Protobuf.TestProtos.Proto2.TestAllExtensions.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.OptionalGroup_extension), global::Google.Protobuf.TestProtos.Proto2.OptionalGroup_extension.Parser, new[]{ "A" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.RepeatedGroup_extension), global::Google.Protobuf.TestProtos.Proto2.RepeatedGroup_extension.Parser, new[]{ "A" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestGroup), global::Google.Protobuf.TestProtos.Proto2.TestGroup.Parser, new[]{ "OptionalGroup", "OptionalForeignEnum" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestGroup.Types.OptionalGroup), global::Google.Protobuf.TestProtos.Proto2.TestGroup.Types.OptionalGroup.Parser, new[]{ "A" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestGroupExtension), global::Google.Protobuf.TestProtos.Proto2.TestGroupExtension.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestNestedExtension), global::Google.Protobuf.TestProtos.Proto2.TestNestedExtension.Parser, null, null, null, new pb::Extension[] { global::Google.Protobuf.TestProtos.Proto2.TestNestedExtension.Extensions.Test, global::Google.Protobuf.TestProtos.Proto2.TestNestedExtension.Extensions.NestedStringExtension, global::Google.Protobuf.TestProtos.Proto2.TestNestedExtension.Extensions.OptionalGroupExtension, global::Google.Protobuf.TestProtos.Proto2.TestNestedExtension.Extensions.OptionalForeignEnumExtension }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestNestedExtension.Types.OptionalGroup_extension), global::Google.Protobuf.TestProtos.Proto2.TestNestedExtension.Types.OptionalGroup_extension.Parser, new[]{ "A" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestRequired), global::Google.Protobuf.TestProtos.Proto2.TestRequired.Parser, new[]{ "A", "Dummy2", "B", "Dummy4", "Dummy5", "Dummy6", "Dummy7", "Dummy8", "Dummy9", "Dummy10", "Dummy11", "Dummy12", "Dummy13", "Dummy14", "Dummy15", "Dummy16", "Dummy17", "Dummy18", "Dummy19", "Dummy20", "Dummy21", "Dummy22", "Dummy23", "Dummy24", "Dummy25", "Dummy26", "Dummy27", "Dummy28", "Dummy29", "Dummy30", "Dummy31", "Dummy32", "C" }, null, null, new pb::Extension[] { global::Google.Protobuf.TestProtos.Proto2.TestRequired.Extensions.Single, global::Google.Protobuf.TestProtos.Proto2.TestRequired.Extensions.Multi }, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestRequiredForeign), global::Google.Protobuf.TestProtos.Proto2.TestRequiredForeign.Parser, new[]{ "OptionalMessage", "RepeatedMessage", "Dummy" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestRequiredMessage), global::Google.Protobuf.TestProtos.Proto2.TestRequiredMessage.Parser, new[]{ "OptionalMessage", "RepeatedMessage", "RequiredMessage" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestForeignNested), global::Google.Protobuf.TestProtos.Proto2.TestForeignNested.Parser, new[]{ "ForeignNested" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestEmptyMessage), global::Google.Protobuf.TestProtos.Proto2.TestEmptyMessage.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestEmptyMessageWithExtensions), global::Google.Protobuf.TestProtos.Proto2.TestEmptyMessageWithExtensions.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestMultipleExtensionRanges), global::Google.Protobuf.TestProtos.Proto2.TestMultipleExtensionRanges.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestReallyLargeTagNumber), global::Google.Protobuf.TestProtos.Proto2.TestReallyLargeTagNumber.Parser, new[]{ "A", "Bb" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestRecursiveMessage), global::Google.Protobuf.TestProtos.Proto2.TestRecursiveMessage.Parser, new[]{ "A", "I" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA), global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Parser, new[]{ "Bb", "SubGroup" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubMessage), global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubMessage.Parser, new[]{ "B" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubGroup), global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubGroup.Parser, new[]{ "SubMessage", "NotInThisScc" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB), global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB.Parser, new[]{ "A", "OptionalInt32" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized), global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Parser, new[]{ "SubMessage" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage), global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage.Parser, new[]{ "SubGroup" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage.Types.SubGroup), global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage.Types.SubGroup.Parser, new[]{ "I" }, null, null, null, null)})}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber), global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Parser, new[]{ "A", "Foo", "Bar" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Foo), global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Foo.Parser, new[]{ "A" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Bar), global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Bar.Parser, new[]{ "A" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestEagerMessage), global::Google.Protobuf.TestProtos.Proto2.TestEagerMessage.Parser, new[]{ "SubMessage" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestLazyMessage), global::Google.Protobuf.TestProtos.Proto2.TestLazyMessage.Parser, new[]{ "SubMessage" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits), global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Parser, new[]{ "OptionalNestedMessage" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Types.NestedMessage), global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Types.NestedMessage.Parser, new[]{ "NestedmessageRepeatedInt32", "NestedmessageRepeatedForeignmessage" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestCamelCaseFieldNames), global::Google.Protobuf.TestProtos.Proto2.TestCamelCaseFieldNames.Parser, new[]{ "PrimitiveField", "StringField", "EnumField", "MessageField", "StringPieceField", "CordField", "RepeatedPrimitiveField", "RepeatedStringField", "RepeatedEnumField", "RepeatedMessageField", "RepeatedStringPieceField", "RepeatedCordField" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings), global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Parser, new[]{ "MyString", "MyInt", "MyFloat", "OptionalNestedMessage" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Types.NestedMessage), global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Types.NestedMessage.Parser, new[]{ "Oo", "Bb" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings1), global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings1.Parser, new[]{ "MyString" }, null, null, new pb::Extension[] { global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings1.Extensions.TestExtOrderings1 }, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2), global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2.Parser, new[]{ "MyString" }, null, null, new pb::Extension[] { global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2.Extensions.TestExtOrderings2 }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2.Types.TestExtensionOrderings3), global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2.Types.TestExtensionOrderings3.Parser, new[]{ "MyString" }, null, null, new pb::Extension[] { global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2.Types.TestExtensionOrderings3.Extensions.TestExtOrderings3 }, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestExtremeDefaultValues), global::Google.Protobuf.TestProtos.Proto2.TestExtremeDefaultValues.Parser, new[]{ "EscapedBytes", "LargeUint32", "LargeUint64", "SmallInt32", "SmallInt64", "ReallySmallInt32", "ReallySmallInt64", "Utf8String", "ZeroFloat", "OneFloat", "SmallFloat", "NegativeOneFloat", "NegativeFloat", "LargeFloat", "SmallNegativeFloat", "InfDouble", "NegInfDouble", "NanDouble", "InfFloat", "NegInfFloat", "NanFloat", "CppTrigraph", "StringWithZero", "BytesWithZero", "StringPieceWithZero", "CordWithZero", "ReplacementString" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.SparseEnumMessage), global::Google.Protobuf.TestProtos.Proto2.SparseEnumMessage.Parser, new[]{ "SparseEnum" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.OneString), global::Google.Protobuf.TestProtos.Proto2.OneString.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.MoreString), global::Google.Protobuf.TestProtos.Proto2.MoreString.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.OneBytes), global::Google.Protobuf.TestProtos.Proto2.OneBytes.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.MoreBytes), global::Google.Protobuf.TestProtos.Proto2.MoreBytes.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.Int32Message), global::Google.Protobuf.TestProtos.Proto2.Int32Message.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.Uint32Message), global::Google.Protobuf.TestProtos.Proto2.Uint32Message.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.Int64Message), global::Google.Protobuf.TestProtos.Proto2.Int64Message.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.Uint64Message), global::Google.Protobuf.TestProtos.Proto2.Uint64Message.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.BoolMessage), global::Google.Protobuf.TestProtos.Proto2.BoolMessage.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestOneof), global::Google.Protobuf.TestProtos.Proto2.TestOneof.Parser, new[]{ "FooInt", "FooString", "FooMessage", "FooGroup" }, new[]{ "Foo" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestOneof.Types.FooGroup), global::Google.Protobuf.TestProtos.Proto2.TestOneof.Types.FooGroup.Parser, new[]{ "A", "B" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestOneofBackwardsCompatible), global::Google.Protobuf.TestProtos.Proto2.TestOneofBackwardsCompatible.Parser, new[]{ "FooInt", "FooString", "FooMessage", "FooGroup" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestOneofBackwardsCompatible.Types.FooGroup), global::Google.Protobuf.TestProtos.Proto2.TestOneofBackwardsCompatible.Types.FooGroup.Parser, new[]{ "A", "B" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestOneof2), global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Parser, new[]{ "FooInt", "FooString", "FooCord", "FooStringPiece", "FooBytes", "FooEnum", "FooMessage", "FooGroup", "FooLazyMessage", "BarInt", "BarString", "BarCord", "BarStringPiece", "BarBytes", "BarEnum", "BazInt", "BazString" }, new[]{ "Foo", "Bar" }, new[]{ typeof(global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.FooGroup), global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.FooGroup.Parser, new[]{ "A", "B" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage), global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage.Parser, new[]{ "QuxInt", "CorgeInt" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof), global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Parser, new[]{ "FooInt", "FooString", "FooMessage" }, new[]{ "Foo" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage), global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage.Parser, new[]{ "RequiredDouble" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestRequiredMap), global::Google.Protobuf.TestProtos.Proto2.TestRequiredMap.Parser, new[]{ "Foo" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestRequiredMap.Types.NestedMessage), global::Google.Protobuf.TestProtos.Proto2.TestRequiredMap.Types.NestedMessage.Parser, new[]{ "RequiredInt32" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestPackedTypes), global::Google.Protobuf.TestProtos.Proto2.TestPackedTypes.Parser, new[]{ "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedEnum" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestUnpackedTypes), global::Google.Protobuf.TestProtos.Proto2.TestUnpackedTypes.Parser, new[]{ "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedEnum" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestPackedExtensions), global::Google.Protobuf.TestProtos.Proto2.TestPackedExtensions.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestUnpackedExtensions), global::Google.Protobuf.TestProtos.Proto2.TestUnpackedExtensions.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions), global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Parser, new[]{ "ScalarExtension", "EnumExtension", "DynamicEnumExtension", "MessageExtension", "DynamicMessageExtension", "RepeatedExtension", "PackedExtension" }, null, new[]{ typeof(global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicEnumType) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicMessageType), global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicMessageType.Parser, new[]{ "DynamicField" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestRepeatedScalarDifferentTagSizes), global::Google.Protobuf.TestProtos.Proto2.TestRepeatedScalarDifferentTagSizes.Parser, new[]{ "RepeatedFixed32", "RepeatedInt32", "RepeatedFixed64", "RepeatedInt64", "RepeatedFloat", "RepeatedUint64" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge), global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Parser, new[]{ "RequiredAllTypes", "OptionalAllTypes", "RepeatedAllTypes", "OptionalGroup", "RepeatedGroup" }, null, null, new pb::Extension[] { global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Extensions.OptionalExt, global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Extensions.RepeatedExt }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator), global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Parser, new[]{ "Field1", "Field2", "Field3", "Group1", "Group2", "Ext1", "Ext2" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Types.Group1), global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Types.Group1.Parser, new[]{ "Field1" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Types.Group2), global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Types.Group2.Parser, new[]{ "Field1" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.OptionalGroup), global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.OptionalGroup.Parser, new[]{ "OptionalGroupAllTypes" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedGroup), global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedGroup.Parser, new[]{ "RepeatedGroupAllTypes" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestCommentInjectionMessage), global::Google.Protobuf.TestProtos.Proto2.TestCommentInjectionMessage.Parser, new[]{ "A" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.FooRequest), global::Google.Protobuf.TestProtos.Proto2.FooRequest.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.FooResponse), global::Google.Protobuf.TestProtos.Proto2.FooResponse.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.FooClientMessage), global::Google.Protobuf.TestProtos.Proto2.FooClientMessage.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.FooServerMessage), global::Google.Protobuf.TestProtos.Proto2.FooServerMessage.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.BarRequest), global::Google.Protobuf.TestProtos.Proto2.BarRequest.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.BarResponse), global::Google.Protobuf.TestProtos.Proto2.BarResponse.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestJsonName), global::Google.Protobuf.TestProtos.Proto2.TestJsonName.Parser, new[]{ "FieldName1", "FieldName2", "FieldName3", "FieldName4", "FIELDNAME5", "FieldName6" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestHugeFieldNumbers), global::Google.Protobuf.TestProtos.Proto2.TestHugeFieldNumbers.Parser, new[]{ "OptionalInt32", "Fixed32", "RepeatedInt32", "PackedInt32", "OptionalEnum", "OptionalString", "OptionalBytes", "OptionalMessage", "OptionalGroup", "StringStringMap", "OneofUint32", "OneofTestAllTypes", "OneofString", "OneofBytes" }, new[]{ "OneofField" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestHugeFieldNumbers.Types.OptionalGroup), global::Google.Protobuf.TestProtos.Proto2.TestHugeFieldNumbers.Types.OptionalGroup.Parser, new[]{ "GroupA" }, null, null, null, null), + null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.TestExtensionInsideTable), global::Google.Protobuf.TestProtos.Proto2.TestExtensionInsideTable.Parser, new[]{ "Field1", "Field2", "Field3", "Field4", "Field6", "Field7", "Field8", "Field9", "Field10" }, null, null, null, null) + })); + } + #endregion + + } + /// Holder for extension identifiers generated from the top level of unittest.proto + public static partial class UnittestExtensions { + /// + /// Singular + /// + public static readonly pb::Extension OptionalInt32Extension = + new pb::Extension(1, pb::FieldCodec.ForInt32(8, 0)); + public static readonly pb::Extension OptionalInt64Extension = + new pb::Extension(2, pb::FieldCodec.ForInt64(16, 0L)); + public static readonly pb::Extension OptionalUint32Extension = + new pb::Extension(3, pb::FieldCodec.ForUInt32(24, 0)); + public static readonly pb::Extension OptionalUint64Extension = + new pb::Extension(4, pb::FieldCodec.ForUInt64(32, 0UL)); + public static readonly pb::Extension OptionalSint32Extension = + new pb::Extension(5, pb::FieldCodec.ForSInt32(40, 0)); + public static readonly pb::Extension OptionalSint64Extension = + new pb::Extension(6, pb::FieldCodec.ForSInt64(48, 0L)); + public static readonly pb::Extension OptionalFixed32Extension = + new pb::Extension(7, pb::FieldCodec.ForFixed32(61, 0)); + public static readonly pb::Extension OptionalFixed64Extension = + new pb::Extension(8, pb::FieldCodec.ForFixed64(65, 0UL)); + public static readonly pb::Extension OptionalSfixed32Extension = + new pb::Extension(9, pb::FieldCodec.ForSFixed32(77, 0)); + public static readonly pb::Extension OptionalSfixed64Extension = + new pb::Extension(10, pb::FieldCodec.ForSFixed64(81, 0L)); + public static readonly pb::Extension OptionalFloatExtension = + new pb::Extension(11, pb::FieldCodec.ForFloat(93, 0F)); + public static readonly pb::Extension OptionalDoubleExtension = + new pb::Extension(12, pb::FieldCodec.ForDouble(97, 0D)); + public static readonly pb::Extension OptionalBoolExtension = + new pb::Extension(13, pb::FieldCodec.ForBool(104, false)); + public static readonly pb::Extension OptionalStringExtension = + new pb::Extension(14, pb::FieldCodec.ForString(114, "")); + public static readonly pb::Extension OptionalBytesExtension = + new pb::Extension(15, pb::FieldCodec.ForBytes(122, pb::ByteString.Empty)); + public static readonly pb::Extension OptionalGroupExtension = + new pb::Extension(16, pb::FieldCodec.ForGroup(131, 132, global::Google.Protobuf.TestProtos.Proto2.OptionalGroup_extension.Parser)); + public static readonly pb::Extension OptionalNestedMessageExtension = + new pb::Extension(18, pb::FieldCodec.ForMessage(146, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser)); + public static readonly pb::Extension OptionalForeignMessageExtension = + new pb::Extension(19, pb::FieldCodec.ForMessage(154, global::Google.Protobuf.TestProtos.Proto2.ForeignMessage.Parser)); + public static readonly pb::Extension OptionalImportMessageExtension = + new pb::Extension(20, pb::FieldCodec.ForMessage(162, global::Google.Protobuf.TestProtos.Proto2.ImportMessage.Parser)); + public static readonly pb::Extension OptionalNestedEnumExtension = + new pb::Extension(21, pb::FieldCodec.ForEnum(168, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum) x, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum.Foo)); + public static readonly pb::Extension OptionalForeignEnumExtension = + new pb::Extension(22, pb::FieldCodec.ForEnum(176, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) x, global::Google.Protobuf.TestProtos.Proto2.ForeignEnum.ForeignFoo)); + public static readonly pb::Extension OptionalImportEnumExtension = + new pb::Extension(23, pb::FieldCodec.ForEnum(184, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ImportEnum) x, global::Google.Protobuf.TestProtos.Proto2.ImportEnum.ImportFoo)); + public static readonly pb::Extension OptionalStringPieceExtension = + new pb::Extension(24, pb::FieldCodec.ForString(194, "")); + public static readonly pb::Extension OptionalCordExtension = + new pb::Extension(25, pb::FieldCodec.ForString(202, "")); + public static readonly pb::Extension OptionalPublicImportMessageExtension = + new pb::Extension(26, pb::FieldCodec.ForMessage(210, global::Google.Protobuf.TestProtos.Proto2.PublicImportMessage.Parser)); + public static readonly pb::Extension OptionalLazyMessageExtension = + new pb::Extension(27, pb::FieldCodec.ForMessage(218, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser)); + /// + /// Repeated + /// + public static readonly pb::RepeatedExtension RepeatedInt32Extension = + new pb::RepeatedExtension(31, pb::FieldCodec.ForInt32(248)); + public static readonly pb::RepeatedExtension RepeatedInt64Extension = + new pb::RepeatedExtension(32, pb::FieldCodec.ForInt64(256)); + public static readonly pb::RepeatedExtension RepeatedUint32Extension = + new pb::RepeatedExtension(33, pb::FieldCodec.ForUInt32(264)); + public static readonly pb::RepeatedExtension RepeatedUint64Extension = + new pb::RepeatedExtension(34, pb::FieldCodec.ForUInt64(272)); + public static readonly pb::RepeatedExtension RepeatedSint32Extension = + new pb::RepeatedExtension(35, pb::FieldCodec.ForSInt32(280)); + public static readonly pb::RepeatedExtension RepeatedSint64Extension = + new pb::RepeatedExtension(36, pb::FieldCodec.ForSInt64(288)); + public static readonly pb::RepeatedExtension RepeatedFixed32Extension = + new pb::RepeatedExtension(37, pb::FieldCodec.ForFixed32(301)); + public static readonly pb::RepeatedExtension RepeatedFixed64Extension = + new pb::RepeatedExtension(38, pb::FieldCodec.ForFixed64(305)); + public static readonly pb::RepeatedExtension RepeatedSfixed32Extension = + new pb::RepeatedExtension(39, pb::FieldCodec.ForSFixed32(317)); + public static readonly pb::RepeatedExtension RepeatedSfixed64Extension = + new pb::RepeatedExtension(40, pb::FieldCodec.ForSFixed64(321)); + public static readonly pb::RepeatedExtension RepeatedFloatExtension = + new pb::RepeatedExtension(41, pb::FieldCodec.ForFloat(333)); + public static readonly pb::RepeatedExtension RepeatedDoubleExtension = + new pb::RepeatedExtension(42, pb::FieldCodec.ForDouble(337)); + public static readonly pb::RepeatedExtension RepeatedBoolExtension = + new pb::RepeatedExtension(43, pb::FieldCodec.ForBool(344)); + public static readonly pb::RepeatedExtension RepeatedStringExtension = + new pb::RepeatedExtension(44, pb::FieldCodec.ForString(354)); + public static readonly pb::RepeatedExtension RepeatedBytesExtension = + new pb::RepeatedExtension(45, pb::FieldCodec.ForBytes(362)); + public static readonly pb::RepeatedExtension RepeatedGroupExtension = + new pb::RepeatedExtension(46, pb::FieldCodec.ForGroup(371, 372, global::Google.Protobuf.TestProtos.Proto2.RepeatedGroup_extension.Parser)); + public static readonly pb::RepeatedExtension RepeatedNestedMessageExtension = + new pb::RepeatedExtension(48, pb::FieldCodec.ForMessage(386, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser)); + public static readonly pb::RepeatedExtension RepeatedForeignMessageExtension = + new pb::RepeatedExtension(49, pb::FieldCodec.ForMessage(394, global::Google.Protobuf.TestProtos.Proto2.ForeignMessage.Parser)); + public static readonly pb::RepeatedExtension RepeatedImportMessageExtension = + new pb::RepeatedExtension(50, pb::FieldCodec.ForMessage(402, global::Google.Protobuf.TestProtos.Proto2.ImportMessage.Parser)); + public static readonly pb::RepeatedExtension RepeatedNestedEnumExtension = + new pb::RepeatedExtension(51, pb::FieldCodec.ForEnum(408, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum) x)); + public static readonly pb::RepeatedExtension RepeatedForeignEnumExtension = + new pb::RepeatedExtension(52, pb::FieldCodec.ForEnum(416, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) x)); + public static readonly pb::RepeatedExtension RepeatedImportEnumExtension = + new pb::RepeatedExtension(53, pb::FieldCodec.ForEnum(424, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ImportEnum) x)); + public static readonly pb::RepeatedExtension RepeatedStringPieceExtension = + new pb::RepeatedExtension(54, pb::FieldCodec.ForString(434)); + public static readonly pb::RepeatedExtension RepeatedCordExtension = + new pb::RepeatedExtension(55, pb::FieldCodec.ForString(442)); + public static readonly pb::RepeatedExtension RepeatedLazyMessageExtension = + new pb::RepeatedExtension(57, pb::FieldCodec.ForMessage(458, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser)); + /// + /// Singular with defaults + /// + public static readonly pb::Extension DefaultInt32Extension = + new pb::Extension(61, pb::FieldCodec.ForInt32(488, 41)); + public static readonly pb::Extension DefaultInt64Extension = + new pb::Extension(62, pb::FieldCodec.ForInt64(496, 42L)); + public static readonly pb::Extension DefaultUint32Extension = + new pb::Extension(63, pb::FieldCodec.ForUInt32(504, 43)); + public static readonly pb::Extension DefaultUint64Extension = + new pb::Extension(64, pb::FieldCodec.ForUInt64(512, 44UL)); + public static readonly pb::Extension DefaultSint32Extension = + new pb::Extension(65, pb::FieldCodec.ForSInt32(520, -45)); + public static readonly pb::Extension DefaultSint64Extension = + new pb::Extension(66, pb::FieldCodec.ForSInt64(528, 46L)); + public static readonly pb::Extension DefaultFixed32Extension = + new pb::Extension(67, pb::FieldCodec.ForFixed32(541, 47)); + public static readonly pb::Extension DefaultFixed64Extension = + new pb::Extension(68, pb::FieldCodec.ForFixed64(545, 48UL)); + public static readonly pb::Extension DefaultSfixed32Extension = + new pb::Extension(69, pb::FieldCodec.ForSFixed32(557, 49)); + public static readonly pb::Extension DefaultSfixed64Extension = + new pb::Extension(70, pb::FieldCodec.ForSFixed64(561, -50L)); + public static readonly pb::Extension DefaultFloatExtension = + new pb::Extension(71, pb::FieldCodec.ForFloat(573, 51.5F)); + public static readonly pb::Extension DefaultDoubleExtension = + new pb::Extension(72, pb::FieldCodec.ForDouble(577, 52000D)); + public static readonly pb::Extension DefaultBoolExtension = + new pb::Extension(73, pb::FieldCodec.ForBool(584, true)); + public static readonly pb::Extension DefaultStringExtension = + new pb::Extension(74, pb::FieldCodec.ForString(594, global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("aGVsbG8="), 0, 5))); + public static readonly pb::Extension DefaultBytesExtension = + new pb::Extension(75, pb::FieldCodec.ForBytes(602, pb::ByteString.FromBase64("d29ybGQ="))); + public static readonly pb::Extension DefaultNestedEnumExtension = + new pb::Extension(81, pb::FieldCodec.ForEnum(648, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum) x, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum.Bar)); + public static readonly pb::Extension DefaultForeignEnumExtension = + new pb::Extension(82, pb::FieldCodec.ForEnum(656, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) x, global::Google.Protobuf.TestProtos.Proto2.ForeignEnum.ForeignBar)); + public static readonly pb::Extension DefaultImportEnumExtension = + new pb::Extension(83, pb::FieldCodec.ForEnum(664, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ImportEnum) x, global::Google.Protobuf.TestProtos.Proto2.ImportEnum.ImportBar)); + public static readonly pb::Extension DefaultStringPieceExtension = + new pb::Extension(84, pb::FieldCodec.ForString(674, global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("YWJj"), 0, 3))); + public static readonly pb::Extension DefaultCordExtension = + new pb::Extension(85, pb::FieldCodec.ForString(682, global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("MTIz"), 0, 3))); + /// + /// For oneof test + /// + public static readonly pb::Extension OneofUint32Extension = + new pb::Extension(111, pb::FieldCodec.ForUInt32(888, 0)); + public static readonly pb::Extension OneofNestedMessageExtension = + new pb::Extension(112, pb::FieldCodec.ForMessage(898, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser)); + public static readonly pb::Extension OneofStringExtension = + new pb::Extension(113, pb::FieldCodec.ForString(906, "")); + public static readonly pb::Extension OneofBytesExtension = + new pb::Extension(114, pb::FieldCodec.ForBytes(914, pb::ByteString.Empty)); + public static readonly pb::Extension MyExtensionString = + new pb::Extension(50, pb::FieldCodec.ForString(402, "")); + public static readonly pb::Extension MyExtensionInt = + new pb::Extension(5, pb::FieldCodec.ForInt32(40, 0)); + public static readonly pb::RepeatedExtension PackedInt32Extension = + new pb::RepeatedExtension(90, pb::FieldCodec.ForInt32(722)); + public static readonly pb::RepeatedExtension PackedInt64Extension = + new pb::RepeatedExtension(91, pb::FieldCodec.ForInt64(730)); + public static readonly pb::RepeatedExtension PackedUint32Extension = + new pb::RepeatedExtension(92, pb::FieldCodec.ForUInt32(738)); + public static readonly pb::RepeatedExtension PackedUint64Extension = + new pb::RepeatedExtension(93, pb::FieldCodec.ForUInt64(746)); + public static readonly pb::RepeatedExtension PackedSint32Extension = + new pb::RepeatedExtension(94, pb::FieldCodec.ForSInt32(754)); + public static readonly pb::RepeatedExtension PackedSint64Extension = + new pb::RepeatedExtension(95, pb::FieldCodec.ForSInt64(762)); + public static readonly pb::RepeatedExtension PackedFixed32Extension = + new pb::RepeatedExtension(96, pb::FieldCodec.ForFixed32(770)); + public static readonly pb::RepeatedExtension PackedFixed64Extension = + new pb::RepeatedExtension(97, pb::FieldCodec.ForFixed64(778)); + public static readonly pb::RepeatedExtension PackedSfixed32Extension = + new pb::RepeatedExtension(98, pb::FieldCodec.ForSFixed32(786)); + public static readonly pb::RepeatedExtension PackedSfixed64Extension = + new pb::RepeatedExtension(99, pb::FieldCodec.ForSFixed64(794)); + public static readonly pb::RepeatedExtension PackedFloatExtension = + new pb::RepeatedExtension(100, pb::FieldCodec.ForFloat(802)); + public static readonly pb::RepeatedExtension PackedDoubleExtension = + new pb::RepeatedExtension(101, pb::FieldCodec.ForDouble(810)); + public static readonly pb::RepeatedExtension PackedBoolExtension = + new pb::RepeatedExtension(102, pb::FieldCodec.ForBool(818)); + public static readonly pb::RepeatedExtension PackedEnumExtension = + new pb::RepeatedExtension(103, pb::FieldCodec.ForEnum(826, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) x)); + public static readonly pb::RepeatedExtension UnpackedInt32Extension = + new pb::RepeatedExtension(90, pb::FieldCodec.ForInt32(720)); + public static readonly pb::RepeatedExtension UnpackedInt64Extension = + new pb::RepeatedExtension(91, pb::FieldCodec.ForInt64(728)); + public static readonly pb::RepeatedExtension UnpackedUint32Extension = + new pb::RepeatedExtension(92, pb::FieldCodec.ForUInt32(736)); + public static readonly pb::RepeatedExtension UnpackedUint64Extension = + new pb::RepeatedExtension(93, pb::FieldCodec.ForUInt64(744)); + public static readonly pb::RepeatedExtension UnpackedSint32Extension = + new pb::RepeatedExtension(94, pb::FieldCodec.ForSInt32(752)); + public static readonly pb::RepeatedExtension UnpackedSint64Extension = + new pb::RepeatedExtension(95, pb::FieldCodec.ForSInt64(760)); + public static readonly pb::RepeatedExtension UnpackedFixed32Extension = + new pb::RepeatedExtension(96, pb::FieldCodec.ForFixed32(773)); + public static readonly pb::RepeatedExtension UnpackedFixed64Extension = + new pb::RepeatedExtension(97, pb::FieldCodec.ForFixed64(777)); + public static readonly pb::RepeatedExtension UnpackedSfixed32Extension = + new pb::RepeatedExtension(98, pb::FieldCodec.ForSFixed32(789)); + public static readonly pb::RepeatedExtension UnpackedSfixed64Extension = + new pb::RepeatedExtension(99, pb::FieldCodec.ForSFixed64(793)); + public static readonly pb::RepeatedExtension UnpackedFloatExtension = + new pb::RepeatedExtension(100, pb::FieldCodec.ForFloat(805)); + public static readonly pb::RepeatedExtension UnpackedDoubleExtension = + new pb::RepeatedExtension(101, pb::FieldCodec.ForDouble(809)); + public static readonly pb::RepeatedExtension UnpackedBoolExtension = + new pb::RepeatedExtension(102, pb::FieldCodec.ForBool(816)); + public static readonly pb::RepeatedExtension UnpackedEnumExtension = + new pb::RepeatedExtension(103, pb::FieldCodec.ForEnum(824, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) x)); + public static readonly pb::Extension TestAllTypes = + new pb::Extension(536860000, pb::FieldCodec.ForMessage(4294880002, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser)); + public static readonly pb::Extension TestExtensionInsideTableExtension = + new pb::Extension(5, pb::FieldCodec.ForInt32(40, 0)); + } + + #region Enums + public enum ForeignEnum { + [pbr::OriginalName("FOREIGN_FOO")] ForeignFoo = 4, + [pbr::OriginalName("FOREIGN_BAR")] ForeignBar = 5, + [pbr::OriginalName("FOREIGN_BAZ")] ForeignBaz = 6, + } + + /// + /// Test an enum that has multiple values with the same number. + /// + public enum TestEnumWithDupValue { + [pbr::OriginalName("FOO1")] Foo1 = 1, + [pbr::OriginalName("BAR1")] Bar1 = 2, + [pbr::OriginalName("BAZ")] Baz = 3, + [pbr::OriginalName("FOO2", PreferredAlias = false)] Foo2 = 1, + [pbr::OriginalName("BAR2", PreferredAlias = false)] Bar2 = 2, + } + + /// + /// Test an enum with large, unordered values. + /// + public enum TestSparseEnum { + [pbr::OriginalName("SPARSE_A")] SparseA = 123, + [pbr::OriginalName("SPARSE_B")] SparseB = 62374, + [pbr::OriginalName("SPARSE_C")] SparseC = 12589234, + [pbr::OriginalName("SPARSE_D")] SparseD = -15, + [pbr::OriginalName("SPARSE_E")] SparseE = -53452, + [pbr::OriginalName("SPARSE_F")] SparseF = 0, + [pbr::OriginalName("SPARSE_G")] SparseG = 2, + } + + public enum VeryLargeEnum { + [pbr::OriginalName("ENUM_LABEL_DEFAULT")] EnumLabelDefault = 0, + [pbr::OriginalName("ENUM_LABEL_1")] EnumLabel1 = 1, + [pbr::OriginalName("ENUM_LABEL_2")] EnumLabel2 = 2, + [pbr::OriginalName("ENUM_LABEL_3")] EnumLabel3 = 3, + [pbr::OriginalName("ENUM_LABEL_4")] EnumLabel4 = 4, + [pbr::OriginalName("ENUM_LABEL_5")] EnumLabel5 = 5, + [pbr::OriginalName("ENUM_LABEL_6")] EnumLabel6 = 6, + [pbr::OriginalName("ENUM_LABEL_7")] EnumLabel7 = 7, + [pbr::OriginalName("ENUM_LABEL_8")] EnumLabel8 = 8, + [pbr::OriginalName("ENUM_LABEL_9")] EnumLabel9 = 9, + [pbr::OriginalName("ENUM_LABEL_10")] EnumLabel10 = 10, + [pbr::OriginalName("ENUM_LABEL_11")] EnumLabel11 = 11, + [pbr::OriginalName("ENUM_LABEL_12")] EnumLabel12 = 12, + [pbr::OriginalName("ENUM_LABEL_13")] EnumLabel13 = 13, + [pbr::OriginalName("ENUM_LABEL_14")] EnumLabel14 = 14, + [pbr::OriginalName("ENUM_LABEL_15")] EnumLabel15 = 15, + [pbr::OriginalName("ENUM_LABEL_16")] EnumLabel16 = 16, + [pbr::OriginalName("ENUM_LABEL_17")] EnumLabel17 = 17, + [pbr::OriginalName("ENUM_LABEL_18")] EnumLabel18 = 18, + [pbr::OriginalName("ENUM_LABEL_19")] EnumLabel19 = 19, + [pbr::OriginalName("ENUM_LABEL_20")] EnumLabel20 = 20, + [pbr::OriginalName("ENUM_LABEL_21")] EnumLabel21 = 21, + [pbr::OriginalName("ENUM_LABEL_22")] EnumLabel22 = 22, + [pbr::OriginalName("ENUM_LABEL_23")] EnumLabel23 = 23, + [pbr::OriginalName("ENUM_LABEL_24")] EnumLabel24 = 24, + [pbr::OriginalName("ENUM_LABEL_25")] EnumLabel25 = 25, + [pbr::OriginalName("ENUM_LABEL_26")] EnumLabel26 = 26, + [pbr::OriginalName("ENUM_LABEL_27")] EnumLabel27 = 27, + [pbr::OriginalName("ENUM_LABEL_28")] EnumLabel28 = 28, + [pbr::OriginalName("ENUM_LABEL_29")] EnumLabel29 = 29, + [pbr::OriginalName("ENUM_LABEL_30")] EnumLabel30 = 30, + [pbr::OriginalName("ENUM_LABEL_31")] EnumLabel31 = 31, + [pbr::OriginalName("ENUM_LABEL_32")] EnumLabel32 = 32, + [pbr::OriginalName("ENUM_LABEL_33")] EnumLabel33 = 33, + [pbr::OriginalName("ENUM_LABEL_34")] EnumLabel34 = 34, + [pbr::OriginalName("ENUM_LABEL_35")] EnumLabel35 = 35, + [pbr::OriginalName("ENUM_LABEL_36")] EnumLabel36 = 36, + [pbr::OriginalName("ENUM_LABEL_37")] EnumLabel37 = 37, + [pbr::OriginalName("ENUM_LABEL_38")] EnumLabel38 = 38, + [pbr::OriginalName("ENUM_LABEL_39")] EnumLabel39 = 39, + [pbr::OriginalName("ENUM_LABEL_40")] EnumLabel40 = 40, + [pbr::OriginalName("ENUM_LABEL_41")] EnumLabel41 = 41, + [pbr::OriginalName("ENUM_LABEL_42")] EnumLabel42 = 42, + [pbr::OriginalName("ENUM_LABEL_43")] EnumLabel43 = 43, + [pbr::OriginalName("ENUM_LABEL_44")] EnumLabel44 = 44, + [pbr::OriginalName("ENUM_LABEL_45")] EnumLabel45 = 45, + [pbr::OriginalName("ENUM_LABEL_46")] EnumLabel46 = 46, + [pbr::OriginalName("ENUM_LABEL_47")] EnumLabel47 = 47, + [pbr::OriginalName("ENUM_LABEL_48")] EnumLabel48 = 48, + [pbr::OriginalName("ENUM_LABEL_49")] EnumLabel49 = 49, + [pbr::OriginalName("ENUM_LABEL_50")] EnumLabel50 = 50, + [pbr::OriginalName("ENUM_LABEL_51")] EnumLabel51 = 51, + [pbr::OriginalName("ENUM_LABEL_52")] EnumLabel52 = 52, + [pbr::OriginalName("ENUM_LABEL_53")] EnumLabel53 = 53, + [pbr::OriginalName("ENUM_LABEL_54")] EnumLabel54 = 54, + [pbr::OriginalName("ENUM_LABEL_55")] EnumLabel55 = 55, + [pbr::OriginalName("ENUM_LABEL_56")] EnumLabel56 = 56, + [pbr::OriginalName("ENUM_LABEL_57")] EnumLabel57 = 57, + [pbr::OriginalName("ENUM_LABEL_58")] EnumLabel58 = 58, + [pbr::OriginalName("ENUM_LABEL_59")] EnumLabel59 = 59, + [pbr::OriginalName("ENUM_LABEL_60")] EnumLabel60 = 60, + [pbr::OriginalName("ENUM_LABEL_61")] EnumLabel61 = 61, + [pbr::OriginalName("ENUM_LABEL_62")] EnumLabel62 = 62, + [pbr::OriginalName("ENUM_LABEL_63")] EnumLabel63 = 63, + [pbr::OriginalName("ENUM_LABEL_64")] EnumLabel64 = 64, + [pbr::OriginalName("ENUM_LABEL_65")] EnumLabel65 = 65, + [pbr::OriginalName("ENUM_LABEL_66")] EnumLabel66 = 66, + [pbr::OriginalName("ENUM_LABEL_67")] EnumLabel67 = 67, + [pbr::OriginalName("ENUM_LABEL_68")] EnumLabel68 = 68, + [pbr::OriginalName("ENUM_LABEL_69")] EnumLabel69 = 69, + [pbr::OriginalName("ENUM_LABEL_70")] EnumLabel70 = 70, + [pbr::OriginalName("ENUM_LABEL_71")] EnumLabel71 = 71, + [pbr::OriginalName("ENUM_LABEL_72")] EnumLabel72 = 72, + [pbr::OriginalName("ENUM_LABEL_73")] EnumLabel73 = 73, + [pbr::OriginalName("ENUM_LABEL_74")] EnumLabel74 = 74, + [pbr::OriginalName("ENUM_LABEL_75")] EnumLabel75 = 75, + [pbr::OriginalName("ENUM_LABEL_76")] EnumLabel76 = 76, + [pbr::OriginalName("ENUM_LABEL_77")] EnumLabel77 = 77, + [pbr::OriginalName("ENUM_LABEL_78")] EnumLabel78 = 78, + [pbr::OriginalName("ENUM_LABEL_79")] EnumLabel79 = 79, + [pbr::OriginalName("ENUM_LABEL_80")] EnumLabel80 = 80, + [pbr::OriginalName("ENUM_LABEL_81")] EnumLabel81 = 81, + [pbr::OriginalName("ENUM_LABEL_82")] EnumLabel82 = 82, + [pbr::OriginalName("ENUM_LABEL_83")] EnumLabel83 = 83, + [pbr::OriginalName("ENUM_LABEL_84")] EnumLabel84 = 84, + [pbr::OriginalName("ENUM_LABEL_85")] EnumLabel85 = 85, + [pbr::OriginalName("ENUM_LABEL_86")] EnumLabel86 = 86, + [pbr::OriginalName("ENUM_LABEL_87")] EnumLabel87 = 87, + [pbr::OriginalName("ENUM_LABEL_88")] EnumLabel88 = 88, + [pbr::OriginalName("ENUM_LABEL_89")] EnumLabel89 = 89, + [pbr::OriginalName("ENUM_LABEL_90")] EnumLabel90 = 90, + [pbr::OriginalName("ENUM_LABEL_91")] EnumLabel91 = 91, + [pbr::OriginalName("ENUM_LABEL_92")] EnumLabel92 = 92, + [pbr::OriginalName("ENUM_LABEL_93")] EnumLabel93 = 93, + [pbr::OriginalName("ENUM_LABEL_94")] EnumLabel94 = 94, + [pbr::OriginalName("ENUM_LABEL_95")] EnumLabel95 = 95, + [pbr::OriginalName("ENUM_LABEL_96")] EnumLabel96 = 96, + [pbr::OriginalName("ENUM_LABEL_97")] EnumLabel97 = 97, + [pbr::OriginalName("ENUM_LABEL_98")] EnumLabel98 = 98, + [pbr::OriginalName("ENUM_LABEL_99")] EnumLabel99 = 99, + [pbr::OriginalName("ENUM_LABEL_100")] EnumLabel100 = 100, + } + + #endregion + + #region Messages + /// + /// This proto includes every type of field in both singular and repeated + /// forms. + /// + public sealed partial class TestAllTypes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestAllTypes()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + private int _hasBits1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllTypes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllTypes(TestAllTypes other) : this() { + _hasBits0 = other._hasBits0; + _hasBits1 = other._hasBits1; + optionalInt32_ = other.optionalInt32_; + optionalInt64_ = other.optionalInt64_; + optionalUint32_ = other.optionalUint32_; + optionalUint64_ = other.optionalUint64_; + optionalSint32_ = other.optionalSint32_; + optionalSint64_ = other.optionalSint64_; + optionalFixed32_ = other.optionalFixed32_; + optionalFixed64_ = other.optionalFixed64_; + optionalSfixed32_ = other.optionalSfixed32_; + optionalSfixed64_ = other.optionalSfixed64_; + optionalFloat_ = other.optionalFloat_; + optionalDouble_ = other.optionalDouble_; + optionalBool_ = other.optionalBool_; + optionalString_ = other.optionalString_; + optionalBytes_ = other.optionalBytes_; + optionalGroup_ = other.HasOptionalGroup ? other.optionalGroup_.Clone() : null; + optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null; + optionalForeignMessage_ = other.optionalForeignMessage_ != null ? other.optionalForeignMessage_.Clone() : null; + optionalImportMessage_ = other.optionalImportMessage_ != null ? other.optionalImportMessage_.Clone() : null; + optionalNestedEnum_ = other.optionalNestedEnum_; + optionalForeignEnum_ = other.optionalForeignEnum_; + optionalImportEnum_ = other.optionalImportEnum_; + optionalStringPiece_ = other.optionalStringPiece_; + optionalCord_ = other.optionalCord_; + optionalPublicImportMessage_ = other.optionalPublicImportMessage_ != null ? other.optionalPublicImportMessage_.Clone() : null; + optionalLazyMessage_ = other.optionalLazyMessage_ != null ? other.optionalLazyMessage_.Clone() : null; + repeatedInt32_ = other.repeatedInt32_.Clone(); + repeatedInt64_ = other.repeatedInt64_.Clone(); + repeatedUint32_ = other.repeatedUint32_.Clone(); + repeatedUint64_ = other.repeatedUint64_.Clone(); + repeatedSint32_ = other.repeatedSint32_.Clone(); + repeatedSint64_ = other.repeatedSint64_.Clone(); + repeatedFixed32_ = other.repeatedFixed32_.Clone(); + repeatedFixed64_ = other.repeatedFixed64_.Clone(); + repeatedSfixed32_ = other.repeatedSfixed32_.Clone(); + repeatedSfixed64_ = other.repeatedSfixed64_.Clone(); + repeatedFloat_ = other.repeatedFloat_.Clone(); + repeatedDouble_ = other.repeatedDouble_.Clone(); + repeatedBool_ = other.repeatedBool_.Clone(); + repeatedString_ = other.repeatedString_.Clone(); + repeatedBytes_ = other.repeatedBytes_.Clone(); + repeatedGroup_ = other.repeatedGroup_.Clone(); + repeatedNestedMessage_ = other.repeatedNestedMessage_.Clone(); + repeatedForeignMessage_ = other.repeatedForeignMessage_.Clone(); + repeatedImportMessage_ = other.repeatedImportMessage_.Clone(); + repeatedNestedEnum_ = other.repeatedNestedEnum_.Clone(); + repeatedForeignEnum_ = other.repeatedForeignEnum_.Clone(); + repeatedImportEnum_ = other.repeatedImportEnum_.Clone(); + repeatedStringPiece_ = other.repeatedStringPiece_.Clone(); + repeatedCord_ = other.repeatedCord_.Clone(); + repeatedLazyMessage_ = other.repeatedLazyMessage_.Clone(); + defaultInt32_ = other.defaultInt32_; + defaultInt64_ = other.defaultInt64_; + defaultUint32_ = other.defaultUint32_; + defaultUint64_ = other.defaultUint64_; + defaultSint32_ = other.defaultSint32_; + defaultSint64_ = other.defaultSint64_; + defaultFixed32_ = other.defaultFixed32_; + defaultFixed64_ = other.defaultFixed64_; + defaultSfixed32_ = other.defaultSfixed32_; + defaultSfixed64_ = other.defaultSfixed64_; + defaultFloat_ = other.defaultFloat_; + defaultDouble_ = other.defaultDouble_; + defaultBool_ = other.defaultBool_; + defaultString_ = other.defaultString_; + defaultBytes_ = other.defaultBytes_; + defaultNestedEnum_ = other.defaultNestedEnum_; + defaultForeignEnum_ = other.defaultForeignEnum_; + defaultImportEnum_ = other.defaultImportEnum_; + defaultStringPiece_ = other.defaultStringPiece_; + defaultCord_ = other.defaultCord_; + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: + OneofUint32 = other.OneofUint32; + break; + case OneofFieldOneofCase.OneofNestedMessage: + OneofNestedMessage = other.OneofNestedMessage.Clone(); + break; + case OneofFieldOneofCase.OneofString: + OneofString = other.OneofString; + break; + case OneofFieldOneofCase.OneofBytes: + OneofBytes = other.OneofBytes; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllTypes Clone() { + return new TestAllTypes(this); + } + + /// Field number for the "optional_int32" field. + public const int OptionalInt32FieldNumber = 1; + private readonly static int OptionalInt32DefaultValue = 0; + + private int optionalInt32_; + /// + /// Singular + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalInt32 { + get { if ((_hasBits0 & 1) != 0) { return optionalInt32_; } else { return OptionalInt32DefaultValue; } } + set { + _hasBits0 |= 1; + optionalInt32_ = value; + } + } + /// Gets whether the "optional_int32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalInt32 { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "optional_int32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalInt32() { + _hasBits0 &= ~1; + } + + /// Field number for the "optional_int64" field. + public const int OptionalInt64FieldNumber = 2; + private readonly static long OptionalInt64DefaultValue = 0L; + + private long optionalInt64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalInt64 { + get { if ((_hasBits0 & 2) != 0) { return optionalInt64_; } else { return OptionalInt64DefaultValue; } } + set { + _hasBits0 |= 2; + optionalInt64_ = value; + } + } + /// Gets whether the "optional_int64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalInt64 { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "optional_int64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalInt64() { + _hasBits0 &= ~2; + } + + /// Field number for the "optional_uint32" field. + public const int OptionalUint32FieldNumber = 3; + private readonly static uint OptionalUint32DefaultValue = 0; + + private uint optionalUint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OptionalUint32 { + get { if ((_hasBits0 & 4) != 0) { return optionalUint32_; } else { return OptionalUint32DefaultValue; } } + set { + _hasBits0 |= 4; + optionalUint32_ = value; + } + } + /// Gets whether the "optional_uint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalUint32 { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "optional_uint32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalUint32() { + _hasBits0 &= ~4; + } + + /// Field number for the "optional_uint64" field. + public const int OptionalUint64FieldNumber = 4; + private readonly static ulong OptionalUint64DefaultValue = 0UL; + + private ulong optionalUint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong OptionalUint64 { + get { if ((_hasBits0 & 8) != 0) { return optionalUint64_; } else { return OptionalUint64DefaultValue; } } + set { + _hasBits0 |= 8; + optionalUint64_ = value; + } + } + /// Gets whether the "optional_uint64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalUint64 { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "optional_uint64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalUint64() { + _hasBits0 &= ~8; + } + + /// Field number for the "optional_sint32" field. + public const int OptionalSint32FieldNumber = 5; + private readonly static int OptionalSint32DefaultValue = 0; + + private int optionalSint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalSint32 { + get { if ((_hasBits0 & 16) != 0) { return optionalSint32_; } else { return OptionalSint32DefaultValue; } } + set { + _hasBits0 |= 16; + optionalSint32_ = value; + } + } + /// Gets whether the "optional_sint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSint32 { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "optional_sint32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSint32() { + _hasBits0 &= ~16; + } + + /// Field number for the "optional_sint64" field. + public const int OptionalSint64FieldNumber = 6; + private readonly static long OptionalSint64DefaultValue = 0L; + + private long optionalSint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalSint64 { + get { if ((_hasBits0 & 32) != 0) { return optionalSint64_; } else { return OptionalSint64DefaultValue; } } + set { + _hasBits0 |= 32; + optionalSint64_ = value; + } + } + /// Gets whether the "optional_sint64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSint64 { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "optional_sint64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSint64() { + _hasBits0 &= ~32; + } + + /// Field number for the "optional_fixed32" field. + public const int OptionalFixed32FieldNumber = 7; + private readonly static uint OptionalFixed32DefaultValue = 0; + + private uint optionalFixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OptionalFixed32 { + get { if ((_hasBits0 & 64) != 0) { return optionalFixed32_; } else { return OptionalFixed32DefaultValue; } } + set { + _hasBits0 |= 64; + optionalFixed32_ = value; + } + } + /// Gets whether the "optional_fixed32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalFixed32 { + get { return (_hasBits0 & 64) != 0; } + } + /// Clears the value of the "optional_fixed32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalFixed32() { + _hasBits0 &= ~64; + } + + /// Field number for the "optional_fixed64" field. + public const int OptionalFixed64FieldNumber = 8; + private readonly static ulong OptionalFixed64DefaultValue = 0UL; + + private ulong optionalFixed64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong OptionalFixed64 { + get { if ((_hasBits0 & 128) != 0) { return optionalFixed64_; } else { return OptionalFixed64DefaultValue; } } + set { + _hasBits0 |= 128; + optionalFixed64_ = value; + } + } + /// Gets whether the "optional_fixed64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalFixed64 { + get { return (_hasBits0 & 128) != 0; } + } + /// Clears the value of the "optional_fixed64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalFixed64() { + _hasBits0 &= ~128; + } + + /// Field number for the "optional_sfixed32" field. + public const int OptionalSfixed32FieldNumber = 9; + private readonly static int OptionalSfixed32DefaultValue = 0; + + private int optionalSfixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalSfixed32 { + get { if ((_hasBits0 & 256) != 0) { return optionalSfixed32_; } else { return OptionalSfixed32DefaultValue; } } + set { + _hasBits0 |= 256; + optionalSfixed32_ = value; + } + } + /// Gets whether the "optional_sfixed32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSfixed32 { + get { return (_hasBits0 & 256) != 0; } + } + /// Clears the value of the "optional_sfixed32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSfixed32() { + _hasBits0 &= ~256; + } + + /// Field number for the "optional_sfixed64" field. + public const int OptionalSfixed64FieldNumber = 10; + private readonly static long OptionalSfixed64DefaultValue = 0L; + + private long optionalSfixed64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalSfixed64 { + get { if ((_hasBits0 & 512) != 0) { return optionalSfixed64_; } else { return OptionalSfixed64DefaultValue; } } + set { + _hasBits0 |= 512; + optionalSfixed64_ = value; + } + } + /// Gets whether the "optional_sfixed64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSfixed64 { + get { return (_hasBits0 & 512) != 0; } + } + /// Clears the value of the "optional_sfixed64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSfixed64() { + _hasBits0 &= ~512; + } + + /// Field number for the "optional_float" field. + public const int OptionalFloatFieldNumber = 11; + private readonly static float OptionalFloatDefaultValue = 0F; + + private float optionalFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float OptionalFloat { + get { if ((_hasBits0 & 1024) != 0) { return optionalFloat_; } else { return OptionalFloatDefaultValue; } } + set { + _hasBits0 |= 1024; + optionalFloat_ = value; + } + } + /// Gets whether the "optional_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalFloat { + get { return (_hasBits0 & 1024) != 0; } + } + /// Clears the value of the "optional_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalFloat() { + _hasBits0 &= ~1024; + } + + /// Field number for the "optional_double" field. + public const int OptionalDoubleFieldNumber = 12; + private readonly static double OptionalDoubleDefaultValue = 0D; + + private double optionalDouble_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double OptionalDouble { + get { if ((_hasBits0 & 2048) != 0) { return optionalDouble_; } else { return OptionalDoubleDefaultValue; } } + set { + _hasBits0 |= 2048; + optionalDouble_ = value; + } + } + /// Gets whether the "optional_double" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalDouble { + get { return (_hasBits0 & 2048) != 0; } + } + /// Clears the value of the "optional_double" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalDouble() { + _hasBits0 &= ~2048; + } + + /// Field number for the "optional_bool" field. + public const int OptionalBoolFieldNumber = 13; + private readonly static bool OptionalBoolDefaultValue = false; + + private bool optionalBool_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool OptionalBool { + get { if ((_hasBits0 & 4096) != 0) { return optionalBool_; } else { return OptionalBoolDefaultValue; } } + set { + _hasBits0 |= 4096; + optionalBool_ = value; + } + } + /// Gets whether the "optional_bool" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalBool { + get { return (_hasBits0 & 4096) != 0; } + } + /// Clears the value of the "optional_bool" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalBool() { + _hasBits0 &= ~4096; + } + + /// Field number for the "optional_string" field. + public const int OptionalStringFieldNumber = 14; + private readonly static string OptionalStringDefaultValue = ""; + + private string optionalString_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalString { + get { return optionalString_ ?? OptionalStringDefaultValue; } + set { + optionalString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalString { + get { return optionalString_ != null; } + } + /// Clears the value of the "optional_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalString() { + optionalString_ = null; + } + + /// Field number for the "optional_bytes" field. + public const int OptionalBytesFieldNumber = 15; + private readonly static pb::ByteString OptionalBytesDefaultValue = pb::ByteString.Empty; + + private pb::ByteString optionalBytes_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString OptionalBytes { + get { return optionalBytes_ ?? OptionalBytesDefaultValue; } + set { + optionalBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_bytes" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalBytes { + get { return optionalBytes_ != null; } + } + /// Clears the value of the "optional_bytes" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalBytes() { + optionalBytes_ = null; + } + + /// Field number for the "optionalgroup" field. + public const int OptionalGroupFieldNumber = 16; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.OptionalGroup optionalGroup_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.OptionalGroup OptionalGroup { + get { return optionalGroup_; } + set { + optionalGroup_ = value; + } + } + /// Gets whether the optionalgroup field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalGroup { + get { return optionalGroup_ != null; } + } + /// Clears the value of the optionalgroup field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalGroup() { + optionalGroup_ = null; + } + + /// Field number for the "optional_nested_message" field. + public const int OptionalNestedMessageFieldNumber = 18; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage optionalNestedMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage OptionalNestedMessage { + get { return optionalNestedMessage_; } + set { + optionalNestedMessage_ = value; + } + } + + /// Field number for the "optional_foreign_message" field. + public const int OptionalForeignMessageFieldNumber = 19; + private global::Google.Protobuf.TestProtos.Proto2.ForeignMessage optionalForeignMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.ForeignMessage OptionalForeignMessage { + get { return optionalForeignMessage_; } + set { + optionalForeignMessage_ = value; + } + } + + /// Field number for the "optional_import_message" field. + public const int OptionalImportMessageFieldNumber = 20; + private global::Google.Protobuf.TestProtos.Proto2.ImportMessage optionalImportMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.ImportMessage OptionalImportMessage { + get { return optionalImportMessage_; } + set { + optionalImportMessage_ = value; + } + } + + /// Field number for the "optional_nested_enum" field. + public const int OptionalNestedEnumFieldNumber = 21; + private readonly static global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum OptionalNestedEnumDefaultValue = global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum.Foo; + + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum optionalNestedEnum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum OptionalNestedEnum { + get { if ((_hasBits0 & 8192) != 0) { return optionalNestedEnum_; } else { return OptionalNestedEnumDefaultValue; } } + set { + _hasBits0 |= 8192; + optionalNestedEnum_ = value; + } + } + /// Gets whether the "optional_nested_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalNestedEnum { + get { return (_hasBits0 & 8192) != 0; } + } + /// Clears the value of the "optional_nested_enum" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalNestedEnum() { + _hasBits0 &= ~8192; + } + + /// Field number for the "optional_foreign_enum" field. + public const int OptionalForeignEnumFieldNumber = 22; + private readonly static global::Google.Protobuf.TestProtos.Proto2.ForeignEnum OptionalForeignEnumDefaultValue = global::Google.Protobuf.TestProtos.Proto2.ForeignEnum.ForeignFoo; + + private global::Google.Protobuf.TestProtos.Proto2.ForeignEnum optionalForeignEnum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.ForeignEnum OptionalForeignEnum { + get { if ((_hasBits0 & 16384) != 0) { return optionalForeignEnum_; } else { return OptionalForeignEnumDefaultValue; } } + set { + _hasBits0 |= 16384; + optionalForeignEnum_ = value; + } + } + /// Gets whether the "optional_foreign_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalForeignEnum { + get { return (_hasBits0 & 16384) != 0; } + } + /// Clears the value of the "optional_foreign_enum" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalForeignEnum() { + _hasBits0 &= ~16384; + } + + /// Field number for the "optional_import_enum" field. + public const int OptionalImportEnumFieldNumber = 23; + private readonly static global::Google.Protobuf.TestProtos.Proto2.ImportEnum OptionalImportEnumDefaultValue = global::Google.Protobuf.TestProtos.Proto2.ImportEnum.ImportFoo; + + private global::Google.Protobuf.TestProtos.Proto2.ImportEnum optionalImportEnum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.ImportEnum OptionalImportEnum { + get { if ((_hasBits0 & 32768) != 0) { return optionalImportEnum_; } else { return OptionalImportEnumDefaultValue; } } + set { + _hasBits0 |= 32768; + optionalImportEnum_ = value; + } + } + /// Gets whether the "optional_import_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalImportEnum { + get { return (_hasBits0 & 32768) != 0; } + } + /// Clears the value of the "optional_import_enum" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalImportEnum() { + _hasBits0 &= ~32768; + } + + /// Field number for the "optional_string_piece" field. + public const int OptionalStringPieceFieldNumber = 24; + private readonly static string OptionalStringPieceDefaultValue = ""; + + private string optionalStringPiece_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalStringPiece { + get { return optionalStringPiece_ ?? OptionalStringPieceDefaultValue; } + set { + optionalStringPiece_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_string_piece" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalStringPiece { + get { return optionalStringPiece_ != null; } + } + /// Clears the value of the "optional_string_piece" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalStringPiece() { + optionalStringPiece_ = null; + } + + /// Field number for the "optional_cord" field. + public const int OptionalCordFieldNumber = 25; + private readonly static string OptionalCordDefaultValue = ""; + + private string optionalCord_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalCord { + get { return optionalCord_ ?? OptionalCordDefaultValue; } + set { + optionalCord_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_cord" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalCord { + get { return optionalCord_ != null; } + } + /// Clears the value of the "optional_cord" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalCord() { + optionalCord_ = null; + } + + /// Field number for the "optional_public_import_message" field. + public const int OptionalPublicImportMessageFieldNumber = 26; + private global::Google.Protobuf.TestProtos.Proto2.PublicImportMessage optionalPublicImportMessage_; + /// + /// Defined in unittest_import_public.proto + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.PublicImportMessage OptionalPublicImportMessage { + get { return optionalPublicImportMessage_; } + set { + optionalPublicImportMessage_ = value; + } + } + + /// Field number for the "optional_lazy_message" field. + public const int OptionalLazyMessageFieldNumber = 27; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage optionalLazyMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage OptionalLazyMessage { + get { return optionalLazyMessage_; } + set { + optionalLazyMessage_ = value; + } + } + + /// Field number for the "repeated_int32" field. + public const int RepeatedInt32FieldNumber = 31; + private static readonly pb::FieldCodec _repeated_repeatedInt32_codec + = pb::FieldCodec.ForInt32(248); + private readonly pbc::RepeatedField repeatedInt32_ = new pbc::RepeatedField(); + /// + /// Repeated + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt32 { + get { return repeatedInt32_; } + } + + /// Field number for the "repeated_int64" field. + public const int RepeatedInt64FieldNumber = 32; + private static readonly pb::FieldCodec _repeated_repeatedInt64_codec + = pb::FieldCodec.ForInt64(256); + private readonly pbc::RepeatedField repeatedInt64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt64 { + get { return repeatedInt64_; } + } + + /// Field number for the "repeated_uint32" field. + public const int RepeatedUint32FieldNumber = 33; + private static readonly pb::FieldCodec _repeated_repeatedUint32_codec + = pb::FieldCodec.ForUInt32(264); + private readonly pbc::RepeatedField repeatedUint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedUint32 { + get { return repeatedUint32_; } + } + + /// Field number for the "repeated_uint64" field. + public const int RepeatedUint64FieldNumber = 34; + private static readonly pb::FieldCodec _repeated_repeatedUint64_codec + = pb::FieldCodec.ForUInt64(272); + private readonly pbc::RepeatedField repeatedUint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedUint64 { + get { return repeatedUint64_; } + } + + /// Field number for the "repeated_sint32" field. + public const int RepeatedSint32FieldNumber = 35; + private static readonly pb::FieldCodec _repeated_repeatedSint32_codec + = pb::FieldCodec.ForSInt32(280); + private readonly pbc::RepeatedField repeatedSint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSint32 { + get { return repeatedSint32_; } + } + + /// Field number for the "repeated_sint64" field. + public const int RepeatedSint64FieldNumber = 36; + private static readonly pb::FieldCodec _repeated_repeatedSint64_codec + = pb::FieldCodec.ForSInt64(288); + private readonly pbc::RepeatedField repeatedSint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSint64 { + get { return repeatedSint64_; } + } + + /// Field number for the "repeated_fixed32" field. + public const int RepeatedFixed32FieldNumber = 37; + private static readonly pb::FieldCodec _repeated_repeatedFixed32_codec + = pb::FieldCodec.ForFixed32(301); + private readonly pbc::RepeatedField repeatedFixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFixed32 { + get { return repeatedFixed32_; } + } + + /// Field number for the "repeated_fixed64" field. + public const int RepeatedFixed64FieldNumber = 38; + private static readonly pb::FieldCodec _repeated_repeatedFixed64_codec + = pb::FieldCodec.ForFixed64(305); + private readonly pbc::RepeatedField repeatedFixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFixed64 { + get { return repeatedFixed64_; } + } + + /// Field number for the "repeated_sfixed32" field. + public const int RepeatedSfixed32FieldNumber = 39; + private static readonly pb::FieldCodec _repeated_repeatedSfixed32_codec + = pb::FieldCodec.ForSFixed32(317); + private readonly pbc::RepeatedField repeatedSfixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSfixed32 { + get { return repeatedSfixed32_; } + } + + /// Field number for the "repeated_sfixed64" field. + public const int RepeatedSfixed64FieldNumber = 40; + private static readonly pb::FieldCodec _repeated_repeatedSfixed64_codec + = pb::FieldCodec.ForSFixed64(321); + private readonly pbc::RepeatedField repeatedSfixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSfixed64 { + get { return repeatedSfixed64_; } + } + + /// Field number for the "repeated_float" field. + public const int RepeatedFloatFieldNumber = 41; + private static readonly pb::FieldCodec _repeated_repeatedFloat_codec + = pb::FieldCodec.ForFloat(333); + private readonly pbc::RepeatedField repeatedFloat_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFloat { + get { return repeatedFloat_; } + } + + /// Field number for the "repeated_double" field. + public const int RepeatedDoubleFieldNumber = 42; + private static readonly pb::FieldCodec _repeated_repeatedDouble_codec + = pb::FieldCodec.ForDouble(337); + private readonly pbc::RepeatedField repeatedDouble_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedDouble { + get { return repeatedDouble_; } + } + + /// Field number for the "repeated_bool" field. + public const int RepeatedBoolFieldNumber = 43; + private static readonly pb::FieldCodec _repeated_repeatedBool_codec + = pb::FieldCodec.ForBool(344); + private readonly pbc::RepeatedField repeatedBool_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedBool { + get { return repeatedBool_; } + } + + /// Field number for the "repeated_string" field. + public const int RepeatedStringFieldNumber = 44; + private static readonly pb::FieldCodec _repeated_repeatedString_codec + = pb::FieldCodec.ForString(354); + private readonly pbc::RepeatedField repeatedString_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedString { + get { return repeatedString_; } + } + + /// Field number for the "repeated_bytes" field. + public const int RepeatedBytesFieldNumber = 45; + private static readonly pb::FieldCodec _repeated_repeatedBytes_codec + = pb::FieldCodec.ForBytes(362); + private readonly pbc::RepeatedField repeatedBytes_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedBytes { + get { return repeatedBytes_; } + } + + /// Field number for the "repeatedgroup" field. + public const int RepeatedGroupFieldNumber = 46; + private static readonly pb::FieldCodec _repeated_repeatedGroup_codec + = pb::FieldCodec.ForGroup(371, 372, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.RepeatedGroup.Parser); + private readonly pbc::RepeatedField repeatedGroup_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedGroup { + get { return repeatedGroup_; } + } + + /// Field number for the "repeated_nested_message" field. + public const int RepeatedNestedMessageFieldNumber = 48; + private static readonly pb::FieldCodec _repeated_repeatedNestedMessage_codec + = pb::FieldCodec.ForMessage(386, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser); + private readonly pbc::RepeatedField repeatedNestedMessage_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedNestedMessage { + get { return repeatedNestedMessage_; } + } + + /// Field number for the "repeated_foreign_message" field. + public const int RepeatedForeignMessageFieldNumber = 49; + private static readonly pb::FieldCodec _repeated_repeatedForeignMessage_codec + = pb::FieldCodec.ForMessage(394, global::Google.Protobuf.TestProtos.Proto2.ForeignMessage.Parser); + private readonly pbc::RepeatedField repeatedForeignMessage_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedForeignMessage { + get { return repeatedForeignMessage_; } + } + + /// Field number for the "repeated_import_message" field. + public const int RepeatedImportMessageFieldNumber = 50; + private static readonly pb::FieldCodec _repeated_repeatedImportMessage_codec + = pb::FieldCodec.ForMessage(402, global::Google.Protobuf.TestProtos.Proto2.ImportMessage.Parser); + private readonly pbc::RepeatedField repeatedImportMessage_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedImportMessage { + get { return repeatedImportMessage_; } + } + + /// Field number for the "repeated_nested_enum" field. + public const int RepeatedNestedEnumFieldNumber = 51; + private static readonly pb::FieldCodec _repeated_repeatedNestedEnum_codec + = pb::FieldCodec.ForEnum(408, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum) x); + private readonly pbc::RepeatedField repeatedNestedEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedNestedEnum { + get { return repeatedNestedEnum_; } + } + + /// Field number for the "repeated_foreign_enum" field. + public const int RepeatedForeignEnumFieldNumber = 52; + private static readonly pb::FieldCodec _repeated_repeatedForeignEnum_codec + = pb::FieldCodec.ForEnum(416, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) x); + private readonly pbc::RepeatedField repeatedForeignEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedForeignEnum { + get { return repeatedForeignEnum_; } + } + + /// Field number for the "repeated_import_enum" field. + public const int RepeatedImportEnumFieldNumber = 53; + private static readonly pb::FieldCodec _repeated_repeatedImportEnum_codec + = pb::FieldCodec.ForEnum(424, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ImportEnum) x); + private readonly pbc::RepeatedField repeatedImportEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedImportEnum { + get { return repeatedImportEnum_; } + } + + /// Field number for the "repeated_string_piece" field. + public const int RepeatedStringPieceFieldNumber = 54; + private static readonly pb::FieldCodec _repeated_repeatedStringPiece_codec + = pb::FieldCodec.ForString(434); + private readonly pbc::RepeatedField repeatedStringPiece_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedStringPiece { + get { return repeatedStringPiece_; } + } + + /// Field number for the "repeated_cord" field. + public const int RepeatedCordFieldNumber = 55; + private static readonly pb::FieldCodec _repeated_repeatedCord_codec + = pb::FieldCodec.ForString(442); + private readonly pbc::RepeatedField repeatedCord_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedCord { + get { return repeatedCord_; } + } + + /// Field number for the "repeated_lazy_message" field. + public const int RepeatedLazyMessageFieldNumber = 57; + private static readonly pb::FieldCodec _repeated_repeatedLazyMessage_codec + = pb::FieldCodec.ForMessage(458, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser); + private readonly pbc::RepeatedField repeatedLazyMessage_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedLazyMessage { + get { return repeatedLazyMessage_; } + } + + /// Field number for the "default_int32" field. + public const int DefaultInt32FieldNumber = 61; + private readonly static int DefaultInt32DefaultValue = 41; + + private int defaultInt32_; + /// + /// Singular with defaults + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int DefaultInt32 { + get { if ((_hasBits0 & 65536) != 0) { return defaultInt32_; } else { return DefaultInt32DefaultValue; } } + set { + _hasBits0 |= 65536; + defaultInt32_ = value; + } + } + /// Gets whether the "default_int32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultInt32 { + get { return (_hasBits0 & 65536) != 0; } + } + /// Clears the value of the "default_int32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultInt32() { + _hasBits0 &= ~65536; + } + + /// Field number for the "default_int64" field. + public const int DefaultInt64FieldNumber = 62; + private readonly static long DefaultInt64DefaultValue = 42L; + + private long defaultInt64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long DefaultInt64 { + get { if ((_hasBits0 & 131072) != 0) { return defaultInt64_; } else { return DefaultInt64DefaultValue; } } + set { + _hasBits0 |= 131072; + defaultInt64_ = value; + } + } + /// Gets whether the "default_int64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultInt64 { + get { return (_hasBits0 & 131072) != 0; } + } + /// Clears the value of the "default_int64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultInt64() { + _hasBits0 &= ~131072; + } + + /// Field number for the "default_uint32" field. + public const int DefaultUint32FieldNumber = 63; + private readonly static uint DefaultUint32DefaultValue = 43; + + private uint defaultUint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint DefaultUint32 { + get { if ((_hasBits0 & 262144) != 0) { return defaultUint32_; } else { return DefaultUint32DefaultValue; } } + set { + _hasBits0 |= 262144; + defaultUint32_ = value; + } + } + /// Gets whether the "default_uint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultUint32 { + get { return (_hasBits0 & 262144) != 0; } + } + /// Clears the value of the "default_uint32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultUint32() { + _hasBits0 &= ~262144; + } + + /// Field number for the "default_uint64" field. + public const int DefaultUint64FieldNumber = 64; + private readonly static ulong DefaultUint64DefaultValue = 44UL; + + private ulong defaultUint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong DefaultUint64 { + get { if ((_hasBits0 & 524288) != 0) { return defaultUint64_; } else { return DefaultUint64DefaultValue; } } + set { + _hasBits0 |= 524288; + defaultUint64_ = value; + } + } + /// Gets whether the "default_uint64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultUint64 { + get { return (_hasBits0 & 524288) != 0; } + } + /// Clears the value of the "default_uint64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultUint64() { + _hasBits0 &= ~524288; + } + + /// Field number for the "default_sint32" field. + public const int DefaultSint32FieldNumber = 65; + private readonly static int DefaultSint32DefaultValue = -45; + + private int defaultSint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int DefaultSint32 { + get { if ((_hasBits0 & 1048576) != 0) { return defaultSint32_; } else { return DefaultSint32DefaultValue; } } + set { + _hasBits0 |= 1048576; + defaultSint32_ = value; + } + } + /// Gets whether the "default_sint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultSint32 { + get { return (_hasBits0 & 1048576) != 0; } + } + /// Clears the value of the "default_sint32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultSint32() { + _hasBits0 &= ~1048576; + } + + /// Field number for the "default_sint64" field. + public const int DefaultSint64FieldNumber = 66; + private readonly static long DefaultSint64DefaultValue = 46L; + + private long defaultSint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long DefaultSint64 { + get { if ((_hasBits0 & 2097152) != 0) { return defaultSint64_; } else { return DefaultSint64DefaultValue; } } + set { + _hasBits0 |= 2097152; + defaultSint64_ = value; + } + } + /// Gets whether the "default_sint64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultSint64 { + get { return (_hasBits0 & 2097152) != 0; } + } + /// Clears the value of the "default_sint64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultSint64() { + _hasBits0 &= ~2097152; + } + + /// Field number for the "default_fixed32" field. + public const int DefaultFixed32FieldNumber = 67; + private readonly static uint DefaultFixed32DefaultValue = 47; + + private uint defaultFixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint DefaultFixed32 { + get { if ((_hasBits0 & 4194304) != 0) { return defaultFixed32_; } else { return DefaultFixed32DefaultValue; } } + set { + _hasBits0 |= 4194304; + defaultFixed32_ = value; + } + } + /// Gets whether the "default_fixed32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultFixed32 { + get { return (_hasBits0 & 4194304) != 0; } + } + /// Clears the value of the "default_fixed32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultFixed32() { + _hasBits0 &= ~4194304; + } + + /// Field number for the "default_fixed64" field. + public const int DefaultFixed64FieldNumber = 68; + private readonly static ulong DefaultFixed64DefaultValue = 48UL; + + private ulong defaultFixed64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong DefaultFixed64 { + get { if ((_hasBits0 & 8388608) != 0) { return defaultFixed64_; } else { return DefaultFixed64DefaultValue; } } + set { + _hasBits0 |= 8388608; + defaultFixed64_ = value; + } + } + /// Gets whether the "default_fixed64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultFixed64 { + get { return (_hasBits0 & 8388608) != 0; } + } + /// Clears the value of the "default_fixed64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultFixed64() { + _hasBits0 &= ~8388608; + } + + /// Field number for the "default_sfixed32" field. + public const int DefaultSfixed32FieldNumber = 69; + private readonly static int DefaultSfixed32DefaultValue = 49; + + private int defaultSfixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int DefaultSfixed32 { + get { if ((_hasBits0 & 16777216) != 0) { return defaultSfixed32_; } else { return DefaultSfixed32DefaultValue; } } + set { + _hasBits0 |= 16777216; + defaultSfixed32_ = value; + } + } + /// Gets whether the "default_sfixed32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultSfixed32 { + get { return (_hasBits0 & 16777216) != 0; } + } + /// Clears the value of the "default_sfixed32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultSfixed32() { + _hasBits0 &= ~16777216; + } + + /// Field number for the "default_sfixed64" field. + public const int DefaultSfixed64FieldNumber = 70; + private readonly static long DefaultSfixed64DefaultValue = -50L; + + private long defaultSfixed64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long DefaultSfixed64 { + get { if ((_hasBits0 & 33554432) != 0) { return defaultSfixed64_; } else { return DefaultSfixed64DefaultValue; } } + set { + _hasBits0 |= 33554432; + defaultSfixed64_ = value; + } + } + /// Gets whether the "default_sfixed64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultSfixed64 { + get { return (_hasBits0 & 33554432) != 0; } + } + /// Clears the value of the "default_sfixed64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultSfixed64() { + _hasBits0 &= ~33554432; + } + + /// Field number for the "default_float" field. + public const int DefaultFloatFieldNumber = 71; + private readonly static float DefaultFloatDefaultValue = 51.5F; + + private float defaultFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float DefaultFloat { + get { if ((_hasBits0 & 67108864) != 0) { return defaultFloat_; } else { return DefaultFloatDefaultValue; } } + set { + _hasBits0 |= 67108864; + defaultFloat_ = value; + } + } + /// Gets whether the "default_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultFloat { + get { return (_hasBits0 & 67108864) != 0; } + } + /// Clears the value of the "default_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultFloat() { + _hasBits0 &= ~67108864; + } + + /// Field number for the "default_double" field. + public const int DefaultDoubleFieldNumber = 72; + private readonly static double DefaultDoubleDefaultValue = 52000D; + + private double defaultDouble_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double DefaultDouble { + get { if ((_hasBits0 & 134217728) != 0) { return defaultDouble_; } else { return DefaultDoubleDefaultValue; } } + set { + _hasBits0 |= 134217728; + defaultDouble_ = value; + } + } + /// Gets whether the "default_double" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultDouble { + get { return (_hasBits0 & 134217728) != 0; } + } + /// Clears the value of the "default_double" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultDouble() { + _hasBits0 &= ~134217728; + } + + /// Field number for the "default_bool" field. + public const int DefaultBoolFieldNumber = 73; + private readonly static bool DefaultBoolDefaultValue = true; + + private bool defaultBool_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool DefaultBool { + get { if ((_hasBits0 & 268435456) != 0) { return defaultBool_; } else { return DefaultBoolDefaultValue; } } + set { + _hasBits0 |= 268435456; + defaultBool_ = value; + } + } + /// Gets whether the "default_bool" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultBool { + get { return (_hasBits0 & 268435456) != 0; } + } + /// Clears the value of the "default_bool" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultBool() { + _hasBits0 &= ~268435456; + } + + /// Field number for the "default_string" field. + public const int DefaultStringFieldNumber = 74; + private readonly static string DefaultStringDefaultValue = global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("aGVsbG8="), 0, 5); + + private string defaultString_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string DefaultString { + get { return defaultString_ ?? DefaultStringDefaultValue; } + set { + defaultString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "default_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultString { + get { return defaultString_ != null; } + } + /// Clears the value of the "default_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultString() { + defaultString_ = null; + } + + /// Field number for the "default_bytes" field. + public const int DefaultBytesFieldNumber = 75; + private readonly static pb::ByteString DefaultBytesDefaultValue = pb::ByteString.FromBase64("d29ybGQ="); + + private pb::ByteString defaultBytes_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString DefaultBytes { + get { return defaultBytes_ ?? DefaultBytesDefaultValue; } + set { + defaultBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "default_bytes" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultBytes { + get { return defaultBytes_ != null; } + } + /// Clears the value of the "default_bytes" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultBytes() { + defaultBytes_ = null; + } + + /// Field number for the "default_nested_enum" field. + public const int DefaultNestedEnumFieldNumber = 81; + private readonly static global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum DefaultNestedEnumDefaultValue = global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum.Bar; + + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum defaultNestedEnum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum DefaultNestedEnum { + get { if ((_hasBits0 & 536870912) != 0) { return defaultNestedEnum_; } else { return DefaultNestedEnumDefaultValue; } } + set { + _hasBits0 |= 536870912; + defaultNestedEnum_ = value; + } + } + /// Gets whether the "default_nested_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultNestedEnum { + get { return (_hasBits0 & 536870912) != 0; } + } + /// Clears the value of the "default_nested_enum" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultNestedEnum() { + _hasBits0 &= ~536870912; + } + + /// Field number for the "default_foreign_enum" field. + public const int DefaultForeignEnumFieldNumber = 82; + private readonly static global::Google.Protobuf.TestProtos.Proto2.ForeignEnum DefaultForeignEnumDefaultValue = global::Google.Protobuf.TestProtos.Proto2.ForeignEnum.ForeignBar; + + private global::Google.Protobuf.TestProtos.Proto2.ForeignEnum defaultForeignEnum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.ForeignEnum DefaultForeignEnum { + get { if ((_hasBits0 & 1073741824) != 0) { return defaultForeignEnum_; } else { return DefaultForeignEnumDefaultValue; } } + set { + _hasBits0 |= 1073741824; + defaultForeignEnum_ = value; + } + } + /// Gets whether the "default_foreign_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultForeignEnum { + get { return (_hasBits0 & 1073741824) != 0; } + } + /// Clears the value of the "default_foreign_enum" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultForeignEnum() { + _hasBits0 &= ~1073741824; + } + + /// Field number for the "default_import_enum" field. + public const int DefaultImportEnumFieldNumber = 83; + private readonly static global::Google.Protobuf.TestProtos.Proto2.ImportEnum DefaultImportEnumDefaultValue = global::Google.Protobuf.TestProtos.Proto2.ImportEnum.ImportBar; + + private global::Google.Protobuf.TestProtos.Proto2.ImportEnum defaultImportEnum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.ImportEnum DefaultImportEnum { + get { if ((_hasBits0 & -2147483648) != 0) { return defaultImportEnum_; } else { return DefaultImportEnumDefaultValue; } } + set { + _hasBits0 |= -2147483648; + defaultImportEnum_ = value; + } + } + /// Gets whether the "default_import_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultImportEnum { + get { return (_hasBits0 & -2147483648) != 0; } + } + /// Clears the value of the "default_import_enum" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultImportEnum() { + _hasBits0 &= ~-2147483648; + } + + /// Field number for the "default_string_piece" field. + public const int DefaultStringPieceFieldNumber = 84; + private readonly static string DefaultStringPieceDefaultValue = global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("YWJj"), 0, 3); + + private string defaultStringPiece_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string DefaultStringPiece { + get { return defaultStringPiece_ ?? DefaultStringPieceDefaultValue; } + set { + defaultStringPiece_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "default_string_piece" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultStringPiece { + get { return defaultStringPiece_ != null; } + } + /// Clears the value of the "default_string_piece" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultStringPiece() { + defaultStringPiece_ = null; + } + + /// Field number for the "default_cord" field. + public const int DefaultCordFieldNumber = 85; + private readonly static string DefaultCordDefaultValue = global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("MTIz"), 0, 3); + + private string defaultCord_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string DefaultCord { + get { return defaultCord_ ?? DefaultCordDefaultValue; } + set { + defaultCord_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "default_cord" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultCord { + get { return defaultCord_ != null; } + } + /// Clears the value of the "default_cord" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultCord() { + defaultCord_ = null; + } + + /// Field number for the "oneof_uint32" field. + public const int OneofUint32FieldNumber = 111; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OneofUint32 { + get { return HasOneofUint32 ? (uint) oneofField_ : 0; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; + } + } + /// Gets whether the "oneof_uint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofUint32 { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32; } + } + /// Clears the value of the oneof if it's currently set to "oneof_uint32" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofUint32() { + if (HasOneofUint32) { + ClearOneofField(); + } + } + + /// Field number for the "oneof_nested_message" field. + public const int OneofNestedMessageFieldNumber = 112; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage OneofNestedMessage { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage) oneofField_ : null; } + set { + oneofField_ = value; + oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage; + } + } + + /// Field number for the "oneof_string" field. + public const int OneofStringFieldNumber = 113; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OneofString { + get { return HasOneofString ? (string) oneofField_ : ""; } + set { + oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + oneofFieldCase_ = OneofFieldOneofCase.OneofString; + } + } + /// Gets whether the "oneof_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofString { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString; } + } + /// Clears the value of the oneof if it's currently set to "oneof_string" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofString() { + if (HasOneofString) { + ClearOneofField(); + } + } + + /// Field number for the "oneof_bytes" field. + public const int OneofBytesFieldNumber = 114; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString OneofBytes { + get { return HasOneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; } + set { + oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; + } + } + /// Gets whether the "oneof_bytes" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofBytes { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes; } + } + /// Clears the value of the oneof if it's currently set to "oneof_bytes" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofBytes() { + if (HasOneofBytes) { + ClearOneofField(); + } + } + + private object oneofField_; + /// Enum of possible cases for the "oneof_field" oneof. + public enum OneofFieldOneofCase { + None = 0, + OneofUint32 = 111, + OneofNestedMessage = 112, + OneofString = 113, + OneofBytes = 114, + } + private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneofFieldOneofCase OneofFieldCase { + get { return oneofFieldCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofField() { + oneofFieldCase_ = OneofFieldOneofCase.None; + oneofField_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestAllTypes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestAllTypes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (OptionalInt32 != other.OptionalInt32) return false; + if (OptionalInt64 != other.OptionalInt64) return false; + if (OptionalUint32 != other.OptionalUint32) return false; + if (OptionalUint64 != other.OptionalUint64) return false; + if (OptionalSint32 != other.OptionalSint32) return false; + if (OptionalSint64 != other.OptionalSint64) return false; + if (OptionalFixed32 != other.OptionalFixed32) return false; + if (OptionalFixed64 != other.OptionalFixed64) return false; + if (OptionalSfixed32 != other.OptionalSfixed32) return false; + if (OptionalSfixed64 != other.OptionalSfixed64) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(OptionalFloat, other.OptionalFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OptionalDouble, other.OptionalDouble)) return false; + if (OptionalBool != other.OptionalBool) return false; + if (OptionalString != other.OptionalString) return false; + if (OptionalBytes != other.OptionalBytes) return false; + if (!object.Equals(OptionalGroup, other.OptionalGroup)) return false; + if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false; + if (!object.Equals(OptionalForeignMessage, other.OptionalForeignMessage)) return false; + if (!object.Equals(OptionalImportMessage, other.OptionalImportMessage)) return false; + if (OptionalNestedEnum != other.OptionalNestedEnum) return false; + if (OptionalForeignEnum != other.OptionalForeignEnum) return false; + if (OptionalImportEnum != other.OptionalImportEnum) return false; + if (OptionalStringPiece != other.OptionalStringPiece) return false; + if (OptionalCord != other.OptionalCord) return false; + if (!object.Equals(OptionalPublicImportMessage, other.OptionalPublicImportMessage)) return false; + if (!object.Equals(OptionalLazyMessage, other.OptionalLazyMessage)) return false; + if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false; + if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false; + if(!repeatedUint32_.Equals(other.repeatedUint32_)) return false; + if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false; + if(!repeatedSint32_.Equals(other.repeatedSint32_)) return false; + if(!repeatedSint64_.Equals(other.repeatedSint64_)) return false; + if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false; + if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false; + if(!repeatedSfixed32_.Equals(other.repeatedSfixed32_)) return false; + if(!repeatedSfixed64_.Equals(other.repeatedSfixed64_)) return false; + if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false; + if(!repeatedDouble_.Equals(other.repeatedDouble_)) return false; + if(!repeatedBool_.Equals(other.repeatedBool_)) return false; + if(!repeatedString_.Equals(other.repeatedString_)) return false; + if(!repeatedBytes_.Equals(other.repeatedBytes_)) return false; + if(!repeatedGroup_.Equals(other.repeatedGroup_)) return false; + if(!repeatedNestedMessage_.Equals(other.repeatedNestedMessage_)) return false; + if(!repeatedForeignMessage_.Equals(other.repeatedForeignMessage_)) return false; + if(!repeatedImportMessage_.Equals(other.repeatedImportMessage_)) return false; + if(!repeatedNestedEnum_.Equals(other.repeatedNestedEnum_)) return false; + if(!repeatedForeignEnum_.Equals(other.repeatedForeignEnum_)) return false; + if(!repeatedImportEnum_.Equals(other.repeatedImportEnum_)) return false; + if(!repeatedStringPiece_.Equals(other.repeatedStringPiece_)) return false; + if(!repeatedCord_.Equals(other.repeatedCord_)) return false; + if(!repeatedLazyMessage_.Equals(other.repeatedLazyMessage_)) return false; + if (DefaultInt32 != other.DefaultInt32) return false; + if (DefaultInt64 != other.DefaultInt64) return false; + if (DefaultUint32 != other.DefaultUint32) return false; + if (DefaultUint64 != other.DefaultUint64) return false; + if (DefaultSint32 != other.DefaultSint32) return false; + if (DefaultSint64 != other.DefaultSint64) return false; + if (DefaultFixed32 != other.DefaultFixed32) return false; + if (DefaultFixed64 != other.DefaultFixed64) return false; + if (DefaultSfixed32 != other.DefaultSfixed32) return false; + if (DefaultSfixed64 != other.DefaultSfixed64) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(DefaultFloat, other.DefaultFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DefaultDouble, other.DefaultDouble)) return false; + if (DefaultBool != other.DefaultBool) return false; + if (DefaultString != other.DefaultString) return false; + if (DefaultBytes != other.DefaultBytes) return false; + if (DefaultNestedEnum != other.DefaultNestedEnum) return false; + if (DefaultForeignEnum != other.DefaultForeignEnum) return false; + if (DefaultImportEnum != other.DefaultImportEnum) return false; + if (DefaultStringPiece != other.DefaultStringPiece) return false; + if (DefaultCord != other.DefaultCord) return false; + if (OneofUint32 != other.OneofUint32) return false; + if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false; + if (OneofString != other.OneofString) return false; + if (OneofBytes != other.OneofBytes) return false; + if (OneofFieldCase != other.OneofFieldCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasOptionalInt32) hash ^= OptionalInt32.GetHashCode(); + if (HasOptionalInt64) hash ^= OptionalInt64.GetHashCode(); + if (HasOptionalUint32) hash ^= OptionalUint32.GetHashCode(); + if (HasOptionalUint64) hash ^= OptionalUint64.GetHashCode(); + if (HasOptionalSint32) hash ^= OptionalSint32.GetHashCode(); + if (HasOptionalSint64) hash ^= OptionalSint64.GetHashCode(); + if (HasOptionalFixed32) hash ^= OptionalFixed32.GetHashCode(); + if (HasOptionalFixed64) hash ^= OptionalFixed64.GetHashCode(); + if (HasOptionalSfixed32) hash ^= OptionalSfixed32.GetHashCode(); + if (HasOptionalSfixed64) hash ^= OptionalSfixed64.GetHashCode(); + if (HasOptionalFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(OptionalFloat); + if (HasOptionalDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OptionalDouble); + if (HasOptionalBool) hash ^= OptionalBool.GetHashCode(); + if (HasOptionalString) hash ^= OptionalString.GetHashCode(); + if (HasOptionalBytes) hash ^= OptionalBytes.GetHashCode(); + if (HasOptionalGroup) hash ^= OptionalGroup.GetHashCode(); + if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode(); + if (optionalForeignMessage_ != null) hash ^= OptionalForeignMessage.GetHashCode(); + if (optionalImportMessage_ != null) hash ^= OptionalImportMessage.GetHashCode(); + if (HasOptionalNestedEnum) hash ^= OptionalNestedEnum.GetHashCode(); + if (HasOptionalForeignEnum) hash ^= OptionalForeignEnum.GetHashCode(); + if (HasOptionalImportEnum) hash ^= OptionalImportEnum.GetHashCode(); + if (HasOptionalStringPiece) hash ^= OptionalStringPiece.GetHashCode(); + if (HasOptionalCord) hash ^= OptionalCord.GetHashCode(); + if (optionalPublicImportMessage_ != null) hash ^= OptionalPublicImportMessage.GetHashCode(); + if (optionalLazyMessage_ != null) hash ^= OptionalLazyMessage.GetHashCode(); + hash ^= repeatedInt32_.GetHashCode(); + hash ^= repeatedInt64_.GetHashCode(); + hash ^= repeatedUint32_.GetHashCode(); + hash ^= repeatedUint64_.GetHashCode(); + hash ^= repeatedSint32_.GetHashCode(); + hash ^= repeatedSint64_.GetHashCode(); + hash ^= repeatedFixed32_.GetHashCode(); + hash ^= repeatedFixed64_.GetHashCode(); + hash ^= repeatedSfixed32_.GetHashCode(); + hash ^= repeatedSfixed64_.GetHashCode(); + hash ^= repeatedFloat_.GetHashCode(); + hash ^= repeatedDouble_.GetHashCode(); + hash ^= repeatedBool_.GetHashCode(); + hash ^= repeatedString_.GetHashCode(); + hash ^= repeatedBytes_.GetHashCode(); + hash ^= repeatedGroup_.GetHashCode(); + hash ^= repeatedNestedMessage_.GetHashCode(); + hash ^= repeatedForeignMessage_.GetHashCode(); + hash ^= repeatedImportMessage_.GetHashCode(); + hash ^= repeatedNestedEnum_.GetHashCode(); + hash ^= repeatedForeignEnum_.GetHashCode(); + hash ^= repeatedImportEnum_.GetHashCode(); + hash ^= repeatedStringPiece_.GetHashCode(); + hash ^= repeatedCord_.GetHashCode(); + hash ^= repeatedLazyMessage_.GetHashCode(); + if (HasDefaultInt32) hash ^= DefaultInt32.GetHashCode(); + if (HasDefaultInt64) hash ^= DefaultInt64.GetHashCode(); + if (HasDefaultUint32) hash ^= DefaultUint32.GetHashCode(); + if (HasDefaultUint64) hash ^= DefaultUint64.GetHashCode(); + if (HasDefaultSint32) hash ^= DefaultSint32.GetHashCode(); + if (HasDefaultSint64) hash ^= DefaultSint64.GetHashCode(); + if (HasDefaultFixed32) hash ^= DefaultFixed32.GetHashCode(); + if (HasDefaultFixed64) hash ^= DefaultFixed64.GetHashCode(); + if (HasDefaultSfixed32) hash ^= DefaultSfixed32.GetHashCode(); + if (HasDefaultSfixed64) hash ^= DefaultSfixed64.GetHashCode(); + if (HasDefaultFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(DefaultFloat); + if (HasDefaultDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DefaultDouble); + if (HasDefaultBool) hash ^= DefaultBool.GetHashCode(); + if (HasDefaultString) hash ^= DefaultString.GetHashCode(); + if (HasDefaultBytes) hash ^= DefaultBytes.GetHashCode(); + if (HasDefaultNestedEnum) hash ^= DefaultNestedEnum.GetHashCode(); + if (HasDefaultForeignEnum) hash ^= DefaultForeignEnum.GetHashCode(); + if (HasDefaultImportEnum) hash ^= DefaultImportEnum.GetHashCode(); + if (HasDefaultStringPiece) hash ^= DefaultStringPiece.GetHashCode(); + if (HasDefaultCord) hash ^= DefaultCord.GetHashCode(); + if (HasOneofUint32) hash ^= OneofUint32.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode(); + if (HasOneofString) hash ^= OneofString.GetHashCode(); + if (HasOneofBytes) hash ^= OneofBytes.GetHashCode(); + hash ^= (int) oneofFieldCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasOptionalInt32) { + output.WriteRawTag(8); + output.WriteInt32(OptionalInt32); + } + if (HasOptionalInt64) { + output.WriteRawTag(16); + output.WriteInt64(OptionalInt64); + } + if (HasOptionalUint32) { + output.WriteRawTag(24); + output.WriteUInt32(OptionalUint32); + } + if (HasOptionalUint64) { + output.WriteRawTag(32); + output.WriteUInt64(OptionalUint64); + } + if (HasOptionalSint32) { + output.WriteRawTag(40); + output.WriteSInt32(OptionalSint32); + } + if (HasOptionalSint64) { + output.WriteRawTag(48); + output.WriteSInt64(OptionalSint64); + } + if (HasOptionalFixed32) { + output.WriteRawTag(61); + output.WriteFixed32(OptionalFixed32); + } + if (HasOptionalFixed64) { + output.WriteRawTag(65); + output.WriteFixed64(OptionalFixed64); + } + if (HasOptionalSfixed32) { + output.WriteRawTag(77); + output.WriteSFixed32(OptionalSfixed32); + } + if (HasOptionalSfixed64) { + output.WriteRawTag(81); + output.WriteSFixed64(OptionalSfixed64); + } + if (HasOptionalFloat) { + output.WriteRawTag(93); + output.WriteFloat(OptionalFloat); + } + if (HasOptionalDouble) { + output.WriteRawTag(97); + output.WriteDouble(OptionalDouble); + } + if (HasOptionalBool) { + output.WriteRawTag(104); + output.WriteBool(OptionalBool); + } + if (HasOptionalString) { + output.WriteRawTag(114); + output.WriteString(OptionalString); + } + if (HasOptionalBytes) { + output.WriteRawTag(122); + output.WriteBytes(OptionalBytes); + } + if (HasOptionalGroup) { + output.WriteRawTag(131, 1); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(132, 1); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(OptionalNestedMessage); + } + if (optionalForeignMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(OptionalForeignMessage); + } + if (optionalImportMessage_ != null) { + output.WriteRawTag(162, 1); + output.WriteMessage(OptionalImportMessage); + } + if (HasOptionalNestedEnum) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) OptionalNestedEnum); + } + if (HasOptionalForeignEnum) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) OptionalForeignEnum); + } + if (HasOptionalImportEnum) { + output.WriteRawTag(184, 1); + output.WriteEnum((int) OptionalImportEnum); + } + if (HasOptionalStringPiece) { + output.WriteRawTag(194, 1); + output.WriteString(OptionalStringPiece); + } + if (HasOptionalCord) { + output.WriteRawTag(202, 1); + output.WriteString(OptionalCord); + } + if (optionalPublicImportMessage_ != null) { + output.WriteRawTag(210, 1); + output.WriteMessage(OptionalPublicImportMessage); + } + if (optionalLazyMessage_ != null) { + output.WriteRawTag(218, 1); + output.WriteMessage(OptionalLazyMessage); + } + repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec); + repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec); + repeatedUint32_.WriteTo(output, _repeated_repeatedUint32_codec); + repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec); + repeatedSint32_.WriteTo(output, _repeated_repeatedSint32_codec); + repeatedSint64_.WriteTo(output, _repeated_repeatedSint64_codec); + repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec); + repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec); + repeatedSfixed32_.WriteTo(output, _repeated_repeatedSfixed32_codec); + repeatedSfixed64_.WriteTo(output, _repeated_repeatedSfixed64_codec); + repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec); + repeatedDouble_.WriteTo(output, _repeated_repeatedDouble_codec); + repeatedBool_.WriteTo(output, _repeated_repeatedBool_codec); + repeatedString_.WriteTo(output, _repeated_repeatedString_codec); + repeatedBytes_.WriteTo(output, _repeated_repeatedBytes_codec); + repeatedGroup_.WriteTo(output, _repeated_repeatedGroup_codec); + repeatedNestedMessage_.WriteTo(output, _repeated_repeatedNestedMessage_codec); + repeatedForeignMessage_.WriteTo(output, _repeated_repeatedForeignMessage_codec); + repeatedImportMessage_.WriteTo(output, _repeated_repeatedImportMessage_codec); + repeatedNestedEnum_.WriteTo(output, _repeated_repeatedNestedEnum_codec); + repeatedForeignEnum_.WriteTo(output, _repeated_repeatedForeignEnum_codec); + repeatedImportEnum_.WriteTo(output, _repeated_repeatedImportEnum_codec); + repeatedStringPiece_.WriteTo(output, _repeated_repeatedStringPiece_codec); + repeatedCord_.WriteTo(output, _repeated_repeatedCord_codec); + repeatedLazyMessage_.WriteTo(output, _repeated_repeatedLazyMessage_codec); + if (HasDefaultInt32) { + output.WriteRawTag(232, 3); + output.WriteInt32(DefaultInt32); + } + if (HasDefaultInt64) { + output.WriteRawTag(240, 3); + output.WriteInt64(DefaultInt64); + } + if (HasDefaultUint32) { + output.WriteRawTag(248, 3); + output.WriteUInt32(DefaultUint32); + } + if (HasDefaultUint64) { + output.WriteRawTag(128, 4); + output.WriteUInt64(DefaultUint64); + } + if (HasDefaultSint32) { + output.WriteRawTag(136, 4); + output.WriteSInt32(DefaultSint32); + } + if (HasDefaultSint64) { + output.WriteRawTag(144, 4); + output.WriteSInt64(DefaultSint64); + } + if (HasDefaultFixed32) { + output.WriteRawTag(157, 4); + output.WriteFixed32(DefaultFixed32); + } + if (HasDefaultFixed64) { + output.WriteRawTag(161, 4); + output.WriteFixed64(DefaultFixed64); + } + if (HasDefaultSfixed32) { + output.WriteRawTag(173, 4); + output.WriteSFixed32(DefaultSfixed32); + } + if (HasDefaultSfixed64) { + output.WriteRawTag(177, 4); + output.WriteSFixed64(DefaultSfixed64); + } + if (HasDefaultFloat) { + output.WriteRawTag(189, 4); + output.WriteFloat(DefaultFloat); + } + if (HasDefaultDouble) { + output.WriteRawTag(193, 4); + output.WriteDouble(DefaultDouble); + } + if (HasDefaultBool) { + output.WriteRawTag(200, 4); + output.WriteBool(DefaultBool); + } + if (HasDefaultString) { + output.WriteRawTag(210, 4); + output.WriteString(DefaultString); + } + if (HasDefaultBytes) { + output.WriteRawTag(218, 4); + output.WriteBytes(DefaultBytes); + } + if (HasDefaultNestedEnum) { + output.WriteRawTag(136, 5); + output.WriteEnum((int) DefaultNestedEnum); + } + if (HasDefaultForeignEnum) { + output.WriteRawTag(144, 5); + output.WriteEnum((int) DefaultForeignEnum); + } + if (HasDefaultImportEnum) { + output.WriteRawTag(152, 5); + output.WriteEnum((int) DefaultImportEnum); + } + if (HasDefaultStringPiece) { + output.WriteRawTag(162, 5); + output.WriteString(DefaultStringPiece); + } + if (HasDefaultCord) { + output.WriteRawTag(170, 5); + output.WriteString(DefaultCord); + } + if (HasOneofUint32) { + output.WriteRawTag(248, 6); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + output.WriteRawTag(130, 7); + output.WriteMessage(OneofNestedMessage); + } + if (HasOneofString) { + output.WriteRawTag(138, 7); + output.WriteString(OneofString); + } + if (HasOneofBytes) { + output.WriteRawTag(146, 7); + output.WriteBytes(OneofBytes); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasOptionalInt32) { + output.WriteRawTag(8); + output.WriteInt32(OptionalInt32); + } + if (HasOptionalInt64) { + output.WriteRawTag(16); + output.WriteInt64(OptionalInt64); + } + if (HasOptionalUint32) { + output.WriteRawTag(24); + output.WriteUInt32(OptionalUint32); + } + if (HasOptionalUint64) { + output.WriteRawTag(32); + output.WriteUInt64(OptionalUint64); + } + if (HasOptionalSint32) { + output.WriteRawTag(40); + output.WriteSInt32(OptionalSint32); + } + if (HasOptionalSint64) { + output.WriteRawTag(48); + output.WriteSInt64(OptionalSint64); + } + if (HasOptionalFixed32) { + output.WriteRawTag(61); + output.WriteFixed32(OptionalFixed32); + } + if (HasOptionalFixed64) { + output.WriteRawTag(65); + output.WriteFixed64(OptionalFixed64); + } + if (HasOptionalSfixed32) { + output.WriteRawTag(77); + output.WriteSFixed32(OptionalSfixed32); + } + if (HasOptionalSfixed64) { + output.WriteRawTag(81); + output.WriteSFixed64(OptionalSfixed64); + } + if (HasOptionalFloat) { + output.WriteRawTag(93); + output.WriteFloat(OptionalFloat); + } + if (HasOptionalDouble) { + output.WriteRawTag(97); + output.WriteDouble(OptionalDouble); + } + if (HasOptionalBool) { + output.WriteRawTag(104); + output.WriteBool(OptionalBool); + } + if (HasOptionalString) { + output.WriteRawTag(114); + output.WriteString(OptionalString); + } + if (HasOptionalBytes) { + output.WriteRawTag(122); + output.WriteBytes(OptionalBytes); + } + if (HasOptionalGroup) { + output.WriteRawTag(131, 1); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(132, 1); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(OptionalNestedMessage); + } + if (optionalForeignMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(OptionalForeignMessage); + } + if (optionalImportMessage_ != null) { + output.WriteRawTag(162, 1); + output.WriteMessage(OptionalImportMessage); + } + if (HasOptionalNestedEnum) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) OptionalNestedEnum); + } + if (HasOptionalForeignEnum) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) OptionalForeignEnum); + } + if (HasOptionalImportEnum) { + output.WriteRawTag(184, 1); + output.WriteEnum((int) OptionalImportEnum); + } + if (HasOptionalStringPiece) { + output.WriteRawTag(194, 1); + output.WriteString(OptionalStringPiece); + } + if (HasOptionalCord) { + output.WriteRawTag(202, 1); + output.WriteString(OptionalCord); + } + if (optionalPublicImportMessage_ != null) { + output.WriteRawTag(210, 1); + output.WriteMessage(OptionalPublicImportMessage); + } + if (optionalLazyMessage_ != null) { + output.WriteRawTag(218, 1); + output.WriteMessage(OptionalLazyMessage); + } + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec); + repeatedUint32_.WriteTo(ref output, _repeated_repeatedUint32_codec); + repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec); + repeatedSint32_.WriteTo(ref output, _repeated_repeatedSint32_codec); + repeatedSint64_.WriteTo(ref output, _repeated_repeatedSint64_codec); + repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec); + repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec); + repeatedSfixed32_.WriteTo(ref output, _repeated_repeatedSfixed32_codec); + repeatedSfixed64_.WriteTo(ref output, _repeated_repeatedSfixed64_codec); + repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec); + repeatedDouble_.WriteTo(ref output, _repeated_repeatedDouble_codec); + repeatedBool_.WriteTo(ref output, _repeated_repeatedBool_codec); + repeatedString_.WriteTo(ref output, _repeated_repeatedString_codec); + repeatedBytes_.WriteTo(ref output, _repeated_repeatedBytes_codec); + repeatedGroup_.WriteTo(ref output, _repeated_repeatedGroup_codec); + repeatedNestedMessage_.WriteTo(ref output, _repeated_repeatedNestedMessage_codec); + repeatedForeignMessage_.WriteTo(ref output, _repeated_repeatedForeignMessage_codec); + repeatedImportMessage_.WriteTo(ref output, _repeated_repeatedImportMessage_codec); + repeatedNestedEnum_.WriteTo(ref output, _repeated_repeatedNestedEnum_codec); + repeatedForeignEnum_.WriteTo(ref output, _repeated_repeatedForeignEnum_codec); + repeatedImportEnum_.WriteTo(ref output, _repeated_repeatedImportEnum_codec); + repeatedStringPiece_.WriteTo(ref output, _repeated_repeatedStringPiece_codec); + repeatedCord_.WriteTo(ref output, _repeated_repeatedCord_codec); + repeatedLazyMessage_.WriteTo(ref output, _repeated_repeatedLazyMessage_codec); + if (HasDefaultInt32) { + output.WriteRawTag(232, 3); + output.WriteInt32(DefaultInt32); + } + if (HasDefaultInt64) { + output.WriteRawTag(240, 3); + output.WriteInt64(DefaultInt64); + } + if (HasDefaultUint32) { + output.WriteRawTag(248, 3); + output.WriteUInt32(DefaultUint32); + } + if (HasDefaultUint64) { + output.WriteRawTag(128, 4); + output.WriteUInt64(DefaultUint64); + } + if (HasDefaultSint32) { + output.WriteRawTag(136, 4); + output.WriteSInt32(DefaultSint32); + } + if (HasDefaultSint64) { + output.WriteRawTag(144, 4); + output.WriteSInt64(DefaultSint64); + } + if (HasDefaultFixed32) { + output.WriteRawTag(157, 4); + output.WriteFixed32(DefaultFixed32); + } + if (HasDefaultFixed64) { + output.WriteRawTag(161, 4); + output.WriteFixed64(DefaultFixed64); + } + if (HasDefaultSfixed32) { + output.WriteRawTag(173, 4); + output.WriteSFixed32(DefaultSfixed32); + } + if (HasDefaultSfixed64) { + output.WriteRawTag(177, 4); + output.WriteSFixed64(DefaultSfixed64); + } + if (HasDefaultFloat) { + output.WriteRawTag(189, 4); + output.WriteFloat(DefaultFloat); + } + if (HasDefaultDouble) { + output.WriteRawTag(193, 4); + output.WriteDouble(DefaultDouble); + } + if (HasDefaultBool) { + output.WriteRawTag(200, 4); + output.WriteBool(DefaultBool); + } + if (HasDefaultString) { + output.WriteRawTag(210, 4); + output.WriteString(DefaultString); + } + if (HasDefaultBytes) { + output.WriteRawTag(218, 4); + output.WriteBytes(DefaultBytes); + } + if (HasDefaultNestedEnum) { + output.WriteRawTag(136, 5); + output.WriteEnum((int) DefaultNestedEnum); + } + if (HasDefaultForeignEnum) { + output.WriteRawTag(144, 5); + output.WriteEnum((int) DefaultForeignEnum); + } + if (HasDefaultImportEnum) { + output.WriteRawTag(152, 5); + output.WriteEnum((int) DefaultImportEnum); + } + if (HasDefaultStringPiece) { + output.WriteRawTag(162, 5); + output.WriteString(DefaultStringPiece); + } + if (HasDefaultCord) { + output.WriteRawTag(170, 5); + output.WriteString(DefaultCord); + } + if (HasOneofUint32) { + output.WriteRawTag(248, 6); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + output.WriteRawTag(130, 7); + output.WriteMessage(OneofNestedMessage); + } + if (HasOneofString) { + output.WriteRawTag(138, 7); + output.WriteString(OneofString); + } + if (HasOneofBytes) { + output.WriteRawTag(146, 7); + output.WriteBytes(OneofBytes); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasOptionalInt32) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32); + } + if (HasOptionalInt64) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(OptionalInt64); + } + if (HasOptionalUint32) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(OptionalUint32); + } + if (HasOptionalUint64) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(OptionalUint64); + } + if (HasOptionalSint32) { + size += 1 + pb::CodedOutputStream.ComputeSInt32Size(OptionalSint32); + } + if (HasOptionalSint64) { + size += 1 + pb::CodedOutputStream.ComputeSInt64Size(OptionalSint64); + } + if (HasOptionalFixed32) { + size += 1 + 4; + } + if (HasOptionalFixed64) { + size += 1 + 8; + } + if (HasOptionalSfixed32) { + size += 1 + 4; + } + if (HasOptionalSfixed64) { + size += 1 + 8; + } + if (HasOptionalFloat) { + size += 1 + 4; + } + if (HasOptionalDouble) { + size += 1 + 8; + } + if (HasOptionalBool) { + size += 1 + 1; + } + if (HasOptionalString) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(OptionalString); + } + if (HasOptionalBytes) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(OptionalBytes); + } + if (HasOptionalGroup) { + size += 4 + pb::CodedOutputStream.ComputeGroupSize(OptionalGroup); + } + if (optionalNestedMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage); + } + if (optionalForeignMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalForeignMessage); + } + if (optionalImportMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalImportMessage); + } + if (HasOptionalNestedEnum) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalNestedEnum); + } + if (HasOptionalForeignEnum) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalForeignEnum); + } + if (HasOptionalImportEnum) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalImportEnum); + } + if (HasOptionalStringPiece) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalStringPiece); + } + if (HasOptionalCord) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalCord); + } + if (optionalPublicImportMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalPublicImportMessage); + } + if (optionalLazyMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalLazyMessage); + } + size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec); + size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec); + size += repeatedUint32_.CalculateSize(_repeated_repeatedUint32_codec); + size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec); + size += repeatedSint32_.CalculateSize(_repeated_repeatedSint32_codec); + size += repeatedSint64_.CalculateSize(_repeated_repeatedSint64_codec); + size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec); + size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec); + size += repeatedSfixed32_.CalculateSize(_repeated_repeatedSfixed32_codec); + size += repeatedSfixed64_.CalculateSize(_repeated_repeatedSfixed64_codec); + size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec); + size += repeatedDouble_.CalculateSize(_repeated_repeatedDouble_codec); + size += repeatedBool_.CalculateSize(_repeated_repeatedBool_codec); + size += repeatedString_.CalculateSize(_repeated_repeatedString_codec); + size += repeatedBytes_.CalculateSize(_repeated_repeatedBytes_codec); + size += repeatedGroup_.CalculateSize(_repeated_repeatedGroup_codec); + size += repeatedNestedMessage_.CalculateSize(_repeated_repeatedNestedMessage_codec); + size += repeatedForeignMessage_.CalculateSize(_repeated_repeatedForeignMessage_codec); + size += repeatedImportMessage_.CalculateSize(_repeated_repeatedImportMessage_codec); + size += repeatedNestedEnum_.CalculateSize(_repeated_repeatedNestedEnum_codec); + size += repeatedForeignEnum_.CalculateSize(_repeated_repeatedForeignEnum_codec); + size += repeatedImportEnum_.CalculateSize(_repeated_repeatedImportEnum_codec); + size += repeatedStringPiece_.CalculateSize(_repeated_repeatedStringPiece_codec); + size += repeatedCord_.CalculateSize(_repeated_repeatedCord_codec); + size += repeatedLazyMessage_.CalculateSize(_repeated_repeatedLazyMessage_codec); + if (HasDefaultInt32) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(DefaultInt32); + } + if (HasDefaultInt64) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(DefaultInt64); + } + if (HasDefaultUint32) { + size += 2 + pb::CodedOutputStream.ComputeUInt32Size(DefaultUint32); + } + if (HasDefaultUint64) { + size += 2 + pb::CodedOutputStream.ComputeUInt64Size(DefaultUint64); + } + if (HasDefaultSint32) { + size += 2 + pb::CodedOutputStream.ComputeSInt32Size(DefaultSint32); + } + if (HasDefaultSint64) { + size += 2 + pb::CodedOutputStream.ComputeSInt64Size(DefaultSint64); + } + if (HasDefaultFixed32) { + size += 2 + 4; + } + if (HasDefaultFixed64) { + size += 2 + 8; + } + if (HasDefaultSfixed32) { + size += 2 + 4; + } + if (HasDefaultSfixed64) { + size += 2 + 8; + } + if (HasDefaultFloat) { + size += 2 + 4; + } + if (HasDefaultDouble) { + size += 2 + 8; + } + if (HasDefaultBool) { + size += 2 + 1; + } + if (HasDefaultString) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(DefaultString); + } + if (HasDefaultBytes) { + size += 2 + pb::CodedOutputStream.ComputeBytesSize(DefaultBytes); + } + if (HasDefaultNestedEnum) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) DefaultNestedEnum); + } + if (HasDefaultForeignEnum) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) DefaultForeignEnum); + } + if (HasDefaultImportEnum) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) DefaultImportEnum); + } + if (HasDefaultStringPiece) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(DefaultStringPiece); + } + if (HasDefaultCord) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(DefaultCord); + } + if (HasOneofUint32) { + size += 2 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OneofNestedMessage); + } + if (HasOneofString) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OneofString); + } + if (HasOneofBytes) { + size += 2 + pb::CodedOutputStream.ComputeBytesSize(OneofBytes); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestAllTypes other) { + if (other == null) { + return; + } + if (other.HasOptionalInt32) { + OptionalInt32 = other.OptionalInt32; + } + if (other.HasOptionalInt64) { + OptionalInt64 = other.OptionalInt64; + } + if (other.HasOptionalUint32) { + OptionalUint32 = other.OptionalUint32; + } + if (other.HasOptionalUint64) { + OptionalUint64 = other.OptionalUint64; + } + if (other.HasOptionalSint32) { + OptionalSint32 = other.OptionalSint32; + } + if (other.HasOptionalSint64) { + OptionalSint64 = other.OptionalSint64; + } + if (other.HasOptionalFixed32) { + OptionalFixed32 = other.OptionalFixed32; + } + if (other.HasOptionalFixed64) { + OptionalFixed64 = other.OptionalFixed64; + } + if (other.HasOptionalSfixed32) { + OptionalSfixed32 = other.OptionalSfixed32; + } + if (other.HasOptionalSfixed64) { + OptionalSfixed64 = other.OptionalSfixed64; + } + if (other.HasOptionalFloat) { + OptionalFloat = other.OptionalFloat; + } + if (other.HasOptionalDouble) { + OptionalDouble = other.OptionalDouble; + } + if (other.HasOptionalBool) { + OptionalBool = other.OptionalBool; + } + if (other.HasOptionalString) { + OptionalString = other.OptionalString; + } + if (other.HasOptionalBytes) { + OptionalBytes = other.OptionalBytes; + } + if (other.HasOptionalGroup) { + if (!HasOptionalGroup) { + OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.OptionalGroup(); + } + OptionalGroup.MergeFrom(other.OptionalGroup); + } + if (other.optionalNestedMessage_ != null) { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage(); + } + OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage); + } + if (other.optionalForeignMessage_ != null) { + if (optionalForeignMessage_ == null) { + OptionalForeignMessage = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage(); + } + OptionalForeignMessage.MergeFrom(other.OptionalForeignMessage); + } + if (other.optionalImportMessage_ != null) { + if (optionalImportMessage_ == null) { + OptionalImportMessage = new global::Google.Protobuf.TestProtos.Proto2.ImportMessage(); + } + OptionalImportMessage.MergeFrom(other.OptionalImportMessage); + } + if (other.HasOptionalNestedEnum) { + OptionalNestedEnum = other.OptionalNestedEnum; + } + if (other.HasOptionalForeignEnum) { + OptionalForeignEnum = other.OptionalForeignEnum; + } + if (other.HasOptionalImportEnum) { + OptionalImportEnum = other.OptionalImportEnum; + } + if (other.HasOptionalStringPiece) { + OptionalStringPiece = other.OptionalStringPiece; + } + if (other.HasOptionalCord) { + OptionalCord = other.OptionalCord; + } + if (other.optionalPublicImportMessage_ != null) { + if (optionalPublicImportMessage_ == null) { + OptionalPublicImportMessage = new global::Google.Protobuf.TestProtos.Proto2.PublicImportMessage(); + } + OptionalPublicImportMessage.MergeFrom(other.OptionalPublicImportMessage); + } + if (other.optionalLazyMessage_ != null) { + if (optionalLazyMessage_ == null) { + OptionalLazyMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage(); + } + OptionalLazyMessage.MergeFrom(other.OptionalLazyMessage); + } + repeatedInt32_.Add(other.repeatedInt32_); + repeatedInt64_.Add(other.repeatedInt64_); + repeatedUint32_.Add(other.repeatedUint32_); + repeatedUint64_.Add(other.repeatedUint64_); + repeatedSint32_.Add(other.repeatedSint32_); + repeatedSint64_.Add(other.repeatedSint64_); + repeatedFixed32_.Add(other.repeatedFixed32_); + repeatedFixed64_.Add(other.repeatedFixed64_); + repeatedSfixed32_.Add(other.repeatedSfixed32_); + repeatedSfixed64_.Add(other.repeatedSfixed64_); + repeatedFloat_.Add(other.repeatedFloat_); + repeatedDouble_.Add(other.repeatedDouble_); + repeatedBool_.Add(other.repeatedBool_); + repeatedString_.Add(other.repeatedString_); + repeatedBytes_.Add(other.repeatedBytes_); + repeatedGroup_.Add(other.repeatedGroup_); + repeatedNestedMessage_.Add(other.repeatedNestedMessage_); + repeatedForeignMessage_.Add(other.repeatedForeignMessage_); + repeatedImportMessage_.Add(other.repeatedImportMessage_); + repeatedNestedEnum_.Add(other.repeatedNestedEnum_); + repeatedForeignEnum_.Add(other.repeatedForeignEnum_); + repeatedImportEnum_.Add(other.repeatedImportEnum_); + repeatedStringPiece_.Add(other.repeatedStringPiece_); + repeatedCord_.Add(other.repeatedCord_); + repeatedLazyMessage_.Add(other.repeatedLazyMessage_); + if (other.HasDefaultInt32) { + DefaultInt32 = other.DefaultInt32; + } + if (other.HasDefaultInt64) { + DefaultInt64 = other.DefaultInt64; + } + if (other.HasDefaultUint32) { + DefaultUint32 = other.DefaultUint32; + } + if (other.HasDefaultUint64) { + DefaultUint64 = other.DefaultUint64; + } + if (other.HasDefaultSint32) { + DefaultSint32 = other.DefaultSint32; + } + if (other.HasDefaultSint64) { + DefaultSint64 = other.DefaultSint64; + } + if (other.HasDefaultFixed32) { + DefaultFixed32 = other.DefaultFixed32; + } + if (other.HasDefaultFixed64) { + DefaultFixed64 = other.DefaultFixed64; + } + if (other.HasDefaultSfixed32) { + DefaultSfixed32 = other.DefaultSfixed32; + } + if (other.HasDefaultSfixed64) { + DefaultSfixed64 = other.DefaultSfixed64; + } + if (other.HasDefaultFloat) { + DefaultFloat = other.DefaultFloat; + } + if (other.HasDefaultDouble) { + DefaultDouble = other.DefaultDouble; + } + if (other.HasDefaultBool) { + DefaultBool = other.DefaultBool; + } + if (other.HasDefaultString) { + DefaultString = other.DefaultString; + } + if (other.HasDefaultBytes) { + DefaultBytes = other.DefaultBytes; + } + if (other.HasDefaultNestedEnum) { + DefaultNestedEnum = other.DefaultNestedEnum; + } + if (other.HasDefaultForeignEnum) { + DefaultForeignEnum = other.DefaultForeignEnum; + } + if (other.HasDefaultImportEnum) { + DefaultImportEnum = other.DefaultImportEnum; + } + if (other.HasDefaultStringPiece) { + DefaultStringPiece = other.DefaultStringPiece; + } + if (other.HasDefaultCord) { + DefaultCord = other.DefaultCord; + } + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: + OneofUint32 = other.OneofUint32; + break; + case OneofFieldOneofCase.OneofNestedMessage: + if (OneofNestedMessage == null) { + OneofNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage(); + } + OneofNestedMessage.MergeFrom(other.OneofNestedMessage); + break; + case OneofFieldOneofCase.OneofString: + OneofString = other.OneofString; + break; + case OneofFieldOneofCase.OneofBytes: + OneofBytes = other.OneofBytes; + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + OptionalInt32 = input.ReadInt32(); + break; + } + case 16: { + OptionalInt64 = input.ReadInt64(); + break; + } + case 24: { + OptionalUint32 = input.ReadUInt32(); + break; + } + case 32: { + OptionalUint64 = input.ReadUInt64(); + break; + } + case 40: { + OptionalSint32 = input.ReadSInt32(); + break; + } + case 48: { + OptionalSint64 = input.ReadSInt64(); + break; + } + case 61: { + OptionalFixed32 = input.ReadFixed32(); + break; + } + case 65: { + OptionalFixed64 = input.ReadFixed64(); + break; + } + case 77: { + OptionalSfixed32 = input.ReadSFixed32(); + break; + } + case 81: { + OptionalSfixed64 = input.ReadSFixed64(); + break; + } + case 93: { + OptionalFloat = input.ReadFloat(); + break; + } + case 97: { + OptionalDouble = input.ReadDouble(); + break; + } + case 104: { + OptionalBool = input.ReadBool(); + break; + } + case 114: { + OptionalString = input.ReadString(); + break; + } + case 122: { + OptionalBytes = input.ReadBytes(); + break; + } + case 131: { + if (!HasOptionalGroup) { + OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.OptionalGroup(); + } + input.ReadGroup(OptionalGroup); + break; + } + case 146: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + case 154: { + if (optionalForeignMessage_ == null) { + OptionalForeignMessage = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage(); + } + input.ReadMessage(OptionalForeignMessage); + break; + } + case 162: { + if (optionalImportMessage_ == null) { + OptionalImportMessage = new global::Google.Protobuf.TestProtos.Proto2.ImportMessage(); + } + input.ReadMessage(OptionalImportMessage); + break; + } + case 168: { + OptionalNestedEnum = (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum) input.ReadEnum(); + break; + } + case 176: { + OptionalForeignEnum = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum(); + break; + } + case 184: { + OptionalImportEnum = (global::Google.Protobuf.TestProtos.Proto2.ImportEnum) input.ReadEnum(); + break; + } + case 194: { + OptionalStringPiece = input.ReadString(); + break; + } + case 202: { + OptionalCord = input.ReadString(); + break; + } + case 210: { + if (optionalPublicImportMessage_ == null) { + OptionalPublicImportMessage = new global::Google.Protobuf.TestProtos.Proto2.PublicImportMessage(); + } + input.ReadMessage(OptionalPublicImportMessage); + break; + } + case 218: { + if (optionalLazyMessage_ == null) { + OptionalLazyMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage(); + } + input.ReadMessage(OptionalLazyMessage); + break; + } + case 250: + case 248: { + repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); + break; + } + case 258: + case 256: { + repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec); + break; + } + case 266: + case 264: { + repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec); + break; + } + case 274: + case 272: { + repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec); + break; + } + case 282: + case 280: { + repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec); + break; + } + case 290: + case 288: { + repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec); + break; + } + case 298: + case 301: { + repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec); + break; + } + case 306: + case 305: { + repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec); + break; + } + case 314: + case 317: { + repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec); + break; + } + case 322: + case 321: { + repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec); + break; + } + case 330: + case 333: { + repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec); + break; + } + case 338: + case 337: { + repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec); + break; + } + case 346: + case 344: { + repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec); + break; + } + case 354: { + repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec); + break; + } + case 362: { + repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec); + break; + } + case 371: { + repeatedGroup_.AddEntriesFrom(input, _repeated_repeatedGroup_codec); + break; + } + case 386: { + repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec); + break; + } + case 394: { + repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec); + break; + } + case 402: { + repeatedImportMessage_.AddEntriesFrom(input, _repeated_repeatedImportMessage_codec); + break; + } + case 410: + case 408: { + repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec); + break; + } + case 418: + case 416: { + repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec); + break; + } + case 426: + case 424: { + repeatedImportEnum_.AddEntriesFrom(input, _repeated_repeatedImportEnum_codec); + break; + } + case 434: { + repeatedStringPiece_.AddEntriesFrom(input, _repeated_repeatedStringPiece_codec); + break; + } + case 442: { + repeatedCord_.AddEntriesFrom(input, _repeated_repeatedCord_codec); + break; + } + case 458: { + repeatedLazyMessage_.AddEntriesFrom(input, _repeated_repeatedLazyMessage_codec); + break; + } + case 488: { + DefaultInt32 = input.ReadInt32(); + break; + } + case 496: { + DefaultInt64 = input.ReadInt64(); + break; + } + case 504: { + DefaultUint32 = input.ReadUInt32(); + break; + } + case 512: { + DefaultUint64 = input.ReadUInt64(); + break; + } + case 520: { + DefaultSint32 = input.ReadSInt32(); + break; + } + case 528: { + DefaultSint64 = input.ReadSInt64(); + break; + } + case 541: { + DefaultFixed32 = input.ReadFixed32(); + break; + } + case 545: { + DefaultFixed64 = input.ReadFixed64(); + break; + } + case 557: { + DefaultSfixed32 = input.ReadSFixed32(); + break; + } + case 561: { + DefaultSfixed64 = input.ReadSFixed64(); + break; + } + case 573: { + DefaultFloat = input.ReadFloat(); + break; + } + case 577: { + DefaultDouble = input.ReadDouble(); + break; + } + case 584: { + DefaultBool = input.ReadBool(); + break; + } + case 594: { + DefaultString = input.ReadString(); + break; + } + case 602: { + DefaultBytes = input.ReadBytes(); + break; + } + case 648: { + DefaultNestedEnum = (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum) input.ReadEnum(); + break; + } + case 656: { + DefaultForeignEnum = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum(); + break; + } + case 664: { + DefaultImportEnum = (global::Google.Protobuf.TestProtos.Proto2.ImportEnum) input.ReadEnum(); + break; + } + case 674: { + DefaultStringPiece = input.ReadString(); + break; + } + case 682: { + DefaultCord = input.ReadString(); + break; + } + case 888: { + OneofUint32 = input.ReadUInt32(); + break; + } + case 898: { + global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + subBuilder.MergeFrom(OneofNestedMessage); + } + input.ReadMessage(subBuilder); + OneofNestedMessage = subBuilder; + break; + } + case 906: { + OneofString = input.ReadString(); + break; + } + case 914: { + OneofBytes = input.ReadBytes(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + OptionalInt32 = input.ReadInt32(); + break; + } + case 16: { + OptionalInt64 = input.ReadInt64(); + break; + } + case 24: { + OptionalUint32 = input.ReadUInt32(); + break; + } + case 32: { + OptionalUint64 = input.ReadUInt64(); + break; + } + case 40: { + OptionalSint32 = input.ReadSInt32(); + break; + } + case 48: { + OptionalSint64 = input.ReadSInt64(); + break; + } + case 61: { + OptionalFixed32 = input.ReadFixed32(); + break; + } + case 65: { + OptionalFixed64 = input.ReadFixed64(); + break; + } + case 77: { + OptionalSfixed32 = input.ReadSFixed32(); + break; + } + case 81: { + OptionalSfixed64 = input.ReadSFixed64(); + break; + } + case 93: { + OptionalFloat = input.ReadFloat(); + break; + } + case 97: { + OptionalDouble = input.ReadDouble(); + break; + } + case 104: { + OptionalBool = input.ReadBool(); + break; + } + case 114: { + OptionalString = input.ReadString(); + break; + } + case 122: { + OptionalBytes = input.ReadBytes(); + break; + } + case 131: { + if (!HasOptionalGroup) { + OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.OptionalGroup(); + } + input.ReadGroup(OptionalGroup); + break; + } + case 146: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + case 154: { + if (optionalForeignMessage_ == null) { + OptionalForeignMessage = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage(); + } + input.ReadMessage(OptionalForeignMessage); + break; + } + case 162: { + if (optionalImportMessage_ == null) { + OptionalImportMessage = new global::Google.Protobuf.TestProtos.Proto2.ImportMessage(); + } + input.ReadMessage(OptionalImportMessage); + break; + } + case 168: { + OptionalNestedEnum = (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum) input.ReadEnum(); + break; + } + case 176: { + OptionalForeignEnum = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum(); + break; + } + case 184: { + OptionalImportEnum = (global::Google.Protobuf.TestProtos.Proto2.ImportEnum) input.ReadEnum(); + break; + } + case 194: { + OptionalStringPiece = input.ReadString(); + break; + } + case 202: { + OptionalCord = input.ReadString(); + break; + } + case 210: { + if (optionalPublicImportMessage_ == null) { + OptionalPublicImportMessage = new global::Google.Protobuf.TestProtos.Proto2.PublicImportMessage(); + } + input.ReadMessage(OptionalPublicImportMessage); + break; + } + case 218: { + if (optionalLazyMessage_ == null) { + OptionalLazyMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage(); + } + input.ReadMessage(OptionalLazyMessage); + break; + } + case 250: + case 248: { + repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec); + break; + } + case 258: + case 256: { + repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec); + break; + } + case 266: + case 264: { + repeatedUint32_.AddEntriesFrom(ref input, _repeated_repeatedUint32_codec); + break; + } + case 274: + case 272: { + repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec); + break; + } + case 282: + case 280: { + repeatedSint32_.AddEntriesFrom(ref input, _repeated_repeatedSint32_codec); + break; + } + case 290: + case 288: { + repeatedSint64_.AddEntriesFrom(ref input, _repeated_repeatedSint64_codec); + break; + } + case 298: + case 301: { + repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec); + break; + } + case 306: + case 305: { + repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec); + break; + } + case 314: + case 317: { + repeatedSfixed32_.AddEntriesFrom(ref input, _repeated_repeatedSfixed32_codec); + break; + } + case 322: + case 321: { + repeatedSfixed64_.AddEntriesFrom(ref input, _repeated_repeatedSfixed64_codec); + break; + } + case 330: + case 333: { + repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec); + break; + } + case 338: + case 337: { + repeatedDouble_.AddEntriesFrom(ref input, _repeated_repeatedDouble_codec); + break; + } + case 346: + case 344: { + repeatedBool_.AddEntriesFrom(ref input, _repeated_repeatedBool_codec); + break; + } + case 354: { + repeatedString_.AddEntriesFrom(ref input, _repeated_repeatedString_codec); + break; + } + case 362: { + repeatedBytes_.AddEntriesFrom(ref input, _repeated_repeatedBytes_codec); + break; + } + case 371: { + repeatedGroup_.AddEntriesFrom(ref input, _repeated_repeatedGroup_codec); + break; + } + case 386: { + repeatedNestedMessage_.AddEntriesFrom(ref input, _repeated_repeatedNestedMessage_codec); + break; + } + case 394: { + repeatedForeignMessage_.AddEntriesFrom(ref input, _repeated_repeatedForeignMessage_codec); + break; + } + case 402: { + repeatedImportMessage_.AddEntriesFrom(ref input, _repeated_repeatedImportMessage_codec); + break; + } + case 410: + case 408: { + repeatedNestedEnum_.AddEntriesFrom(ref input, _repeated_repeatedNestedEnum_codec); + break; + } + case 418: + case 416: { + repeatedForeignEnum_.AddEntriesFrom(ref input, _repeated_repeatedForeignEnum_codec); + break; + } + case 426: + case 424: { + repeatedImportEnum_.AddEntriesFrom(ref input, _repeated_repeatedImportEnum_codec); + break; + } + case 434: { + repeatedStringPiece_.AddEntriesFrom(ref input, _repeated_repeatedStringPiece_codec); + break; + } + case 442: { + repeatedCord_.AddEntriesFrom(ref input, _repeated_repeatedCord_codec); + break; + } + case 458: { + repeatedLazyMessage_.AddEntriesFrom(ref input, _repeated_repeatedLazyMessage_codec); + break; + } + case 488: { + DefaultInt32 = input.ReadInt32(); + break; + } + case 496: { + DefaultInt64 = input.ReadInt64(); + break; + } + case 504: { + DefaultUint32 = input.ReadUInt32(); + break; + } + case 512: { + DefaultUint64 = input.ReadUInt64(); + break; + } + case 520: { + DefaultSint32 = input.ReadSInt32(); + break; + } + case 528: { + DefaultSint64 = input.ReadSInt64(); + break; + } + case 541: { + DefaultFixed32 = input.ReadFixed32(); + break; + } + case 545: { + DefaultFixed64 = input.ReadFixed64(); + break; + } + case 557: { + DefaultSfixed32 = input.ReadSFixed32(); + break; + } + case 561: { + DefaultSfixed64 = input.ReadSFixed64(); + break; + } + case 573: { + DefaultFloat = input.ReadFloat(); + break; + } + case 577: { + DefaultDouble = input.ReadDouble(); + break; + } + case 584: { + DefaultBool = input.ReadBool(); + break; + } + case 594: { + DefaultString = input.ReadString(); + break; + } + case 602: { + DefaultBytes = input.ReadBytes(); + break; + } + case 648: { + DefaultNestedEnum = (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedEnum) input.ReadEnum(); + break; + } + case 656: { + DefaultForeignEnum = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum(); + break; + } + case 664: { + DefaultImportEnum = (global::Google.Protobuf.TestProtos.Proto2.ImportEnum) input.ReadEnum(); + break; + } + case 674: { + DefaultStringPiece = input.ReadString(); + break; + } + case 682: { + DefaultCord = input.ReadString(); + break; + } + case 888: { + OneofUint32 = input.ReadUInt32(); + break; + } + case 898: { + global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + subBuilder.MergeFrom(OneofNestedMessage); + } + input.ReadMessage(subBuilder); + OneofNestedMessage = subBuilder; + break; + } + case 906: { + OneofString = input.ReadString(); + break; + } + case 914: { + OneofBytes = input.ReadBytes(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestAllTypes message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum NestedEnum { + [pbr::OriginalName("FOO")] Foo = 1, + [pbr::OriginalName("BAR")] Bar = 2, + [pbr::OriginalName("BAZ")] Baz = 3, + /// + /// Intentionally negative. + /// + [pbr::OriginalName("NEG")] Neg = -1, + } + + public sealed partial class NestedMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + _hasBits0 = other._hasBits0; + bb_ = other.bb_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "bb" field. + public const int BbFieldNumber = 1; + private readonly static int BbDefaultValue = 0; + + private int bb_; + /// + /// The field name "b" fails to compile in proto1 because it conflicts with + /// a local variable named "b" in one of the generated methods. Doh. + /// This file needs to compile in proto1 to test backwards-compatibility. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Bb { + get { if ((_hasBits0 & 1) != 0) { return bb_; } else { return BbDefaultValue; } } + set { + _hasBits0 |= 1; + bb_ = value; + } + } + /// Gets whether the "bb" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBb { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "bb" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBb() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Bb != other.Bb) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasBb) hash ^= Bb.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasBb) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasBb) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasBb) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Bb); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.HasBb) { + Bb = other.Bb; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Bb = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Bb = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class OptionalGroup : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OptionalGroup()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Descriptor.NestedTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup(OptionalGroup other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup Clone() { + return new OptionalGroup(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 17; + private readonly static int ADefaultValue = 0; + + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as OptionalGroup); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(OptionalGroup other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(136, 1); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(136, 1); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(OptionalGroup other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 132: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 136: { + A = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 132: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 136: { + A = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class RepeatedGroup : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RepeatedGroup()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Descriptor.NestedTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RepeatedGroup() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RepeatedGroup(RepeatedGroup other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RepeatedGroup Clone() { + return new RepeatedGroup(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 47; + private readonly static int ADefaultValue = 0; + + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as RepeatedGroup); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(RepeatedGroup other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(248, 2); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(248, 2); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(RepeatedGroup other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 372: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 376: { + A = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 372: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 376: { + A = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + /// + /// This proto includes a recursively nested message. + /// + public sealed partial class NestedTestAllTypes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedTestAllTypes()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedTestAllTypes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedTestAllTypes(NestedTestAllTypes other) : this() { + child_ = other.child_ != null ? other.child_.Clone() : null; + payload_ = other.payload_ != null ? other.payload_.Clone() : null; + repeatedChild_ = other.repeatedChild_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedTestAllTypes Clone() { + return new NestedTestAllTypes(this); + } + + /// Field number for the "child" field. + public const int ChildFieldNumber = 1; + private global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes child_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes Child { + get { return child_; } + set { + child_ = value; + } + } + + /// Field number for the "payload" field. + public const int PayloadFieldNumber = 2; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes payload_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes Payload { + get { return payload_; } + set { + payload_ = value; + } + } + + /// Field number for the "repeated_child" field. + public const int RepeatedChildFieldNumber = 3; + private static readonly pb::FieldCodec _repeated_repeatedChild_codec + = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes.Parser); + private readonly pbc::RepeatedField repeatedChild_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedChild { + get { return repeatedChild_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedTestAllTypes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedTestAllTypes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Child, other.Child)) return false; + if (!object.Equals(Payload, other.Payload)) return false; + if(!repeatedChild_.Equals(other.repeatedChild_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (child_ != null) hash ^= Child.GetHashCode(); + if (payload_ != null) hash ^= Payload.GetHashCode(); + hash ^= repeatedChild_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (child_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Child); + } + if (payload_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Payload); + } + repeatedChild_.WriteTo(output, _repeated_repeatedChild_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (child_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Child); + } + if (payload_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Payload); + } + repeatedChild_.WriteTo(ref output, _repeated_repeatedChild_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (child_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Child); + } + if (payload_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); + } + size += repeatedChild_.CalculateSize(_repeated_repeatedChild_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedTestAllTypes other) { + if (other == null) { + return; + } + if (other.child_ != null) { + if (child_ == null) { + Child = new global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes(); + } + Child.MergeFrom(other.Child); + } + if (other.payload_ != null) { + if (payload_ == null) { + Payload = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + Payload.MergeFrom(other.Payload); + } + repeatedChild_.Add(other.repeatedChild_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (child_ == null) { + Child = new global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes(); + } + input.ReadMessage(Child); + break; + } + case 18: { + if (payload_ == null) { + Payload = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(Payload); + break; + } + case 26: { + repeatedChild_.AddEntriesFrom(input, _repeated_repeatedChild_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (child_ == null) { + Child = new global::Google.Protobuf.TestProtos.Proto2.NestedTestAllTypes(); + } + input.ReadMessage(Child); + break; + } + case 18: { + if (payload_ == null) { + Payload = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(Payload); + break; + } + case 26: { + repeatedChild_.AddEntriesFrom(ref input, _repeated_repeatedChild_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestDeprecatedFields : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestDeprecatedFields()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDeprecatedFields() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDeprecatedFields(TestDeprecatedFields other) : this() { + _hasBits0 = other._hasBits0; + deprecatedInt32_ = other.deprecatedInt32_; + switch (other.OneofFieldsCase) { + case OneofFieldsOneofCase.DeprecatedInt32InOneof: + DeprecatedInt32InOneof = other.DeprecatedInt32InOneof; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDeprecatedFields Clone() { + return new TestDeprecatedFields(this); + } + + /// Field number for the "deprecated_int32" field. + public const int DeprecatedInt32FieldNumber = 1; + private readonly static int DeprecatedInt32DefaultValue = 0; + + private int deprecatedInt32_; + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int DeprecatedInt32 { + get { if ((_hasBits0 & 1) != 0) { return deprecatedInt32_; } else { return DeprecatedInt32DefaultValue; } } + set { + _hasBits0 |= 1; + deprecatedInt32_ = value; + } + } + /// Gets whether the "deprecated_int32" field is set + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDeprecatedInt32 { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "deprecated_int32" field + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDeprecatedInt32() { + _hasBits0 &= ~1; + } + + /// Field number for the "deprecated_int32_in_oneof" field. + public const int DeprecatedInt32InOneofFieldNumber = 2; + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int DeprecatedInt32InOneof { + get { return HasDeprecatedInt32InOneof ? (int) oneofFields_ : 0; } + set { + oneofFields_ = value; + oneofFieldsCase_ = OneofFieldsOneofCase.DeprecatedInt32InOneof; + } + } + /// Gets whether the "deprecated_int32_in_oneof" field is set + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDeprecatedInt32InOneof { + get { return oneofFieldsCase_ == OneofFieldsOneofCase.DeprecatedInt32InOneof; } + } + /// Clears the value of the oneof if it's currently set to "deprecated_int32_in_oneof" + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDeprecatedInt32InOneof() { + if (HasDeprecatedInt32InOneof) { + ClearOneofFields(); + } + } + + private object oneofFields_; + /// Enum of possible cases for the "oneof_fields" oneof. + public enum OneofFieldsOneofCase { + None = 0, + DeprecatedInt32InOneof = 2, + } + private OneofFieldsOneofCase oneofFieldsCase_ = OneofFieldsOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneofFieldsOneofCase OneofFieldsCase { + get { return oneofFieldsCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofFields() { + oneofFieldsCase_ = OneofFieldsOneofCase.None; + oneofFields_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestDeprecatedFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestDeprecatedFields other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (DeprecatedInt32 != other.DeprecatedInt32) return false; + if (DeprecatedInt32InOneof != other.DeprecatedInt32InOneof) return false; + if (OneofFieldsCase != other.OneofFieldsCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasDeprecatedInt32) hash ^= DeprecatedInt32.GetHashCode(); + if (HasDeprecatedInt32InOneof) hash ^= DeprecatedInt32InOneof.GetHashCode(); + hash ^= (int) oneofFieldsCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasDeprecatedInt32) { + output.WriteRawTag(8); + output.WriteInt32(DeprecatedInt32); + } + if (HasDeprecatedInt32InOneof) { + output.WriteRawTag(16); + output.WriteInt32(DeprecatedInt32InOneof); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasDeprecatedInt32) { + output.WriteRawTag(8); + output.WriteInt32(DeprecatedInt32); + } + if (HasDeprecatedInt32InOneof) { + output.WriteRawTag(16); + output.WriteInt32(DeprecatedInt32InOneof); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasDeprecatedInt32) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(DeprecatedInt32); + } + if (HasDeprecatedInt32InOneof) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(DeprecatedInt32InOneof); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestDeprecatedFields other) { + if (other == null) { + return; + } + if (other.HasDeprecatedInt32) { + DeprecatedInt32 = other.DeprecatedInt32; + } + switch (other.OneofFieldsCase) { + case OneofFieldsOneofCase.DeprecatedInt32InOneof: + DeprecatedInt32InOneof = other.DeprecatedInt32InOneof; + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + DeprecatedInt32 = input.ReadInt32(); + break; + } + case 16: { + DeprecatedInt32InOneof = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + DeprecatedInt32 = input.ReadInt32(); + break; + } + case 16: { + DeprecatedInt32InOneof = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + [global::System.ObsoleteAttribute] + public sealed partial class TestDeprecatedMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestDeprecatedMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDeprecatedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDeprecatedMessage(TestDeprecatedMessage other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDeprecatedMessage Clone() { + return new TestDeprecatedMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestDeprecatedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestDeprecatedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestDeprecatedMessage other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + /// + /// Define these after TestAllTypes to make sure the compiler can handle + /// that. + /// + public sealed partial class ForeignMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ForeignMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ForeignMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ForeignMessage(ForeignMessage other) : this() { + _hasBits0 = other._hasBits0; + c_ = other.c_; + d_ = other.d_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ForeignMessage Clone() { + return new ForeignMessage(this); + } + + /// Field number for the "c" field. + public const int CFieldNumber = 1; + private readonly static int CDefaultValue = 0; + + private int c_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int C { + get { if ((_hasBits0 & 1) != 0) { return c_; } else { return CDefaultValue; } } + set { + _hasBits0 |= 1; + c_ = value; + } + } + /// Gets whether the "c" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasC { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "c" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearC() { + _hasBits0 &= ~1; + } + + /// Field number for the "d" field. + public const int DFieldNumber = 2; + private readonly static int DDefaultValue = 0; + + private int d_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int D { + get { if ((_hasBits0 & 2) != 0) { return d_; } else { return DDefaultValue; } } + set { + _hasBits0 |= 2; + d_ = value; + } + } + /// Gets whether the "d" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasD { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "d" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearD() { + _hasBits0 &= ~2; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ForeignMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ForeignMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (C != other.C) return false; + if (D != other.D) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasC) hash ^= C.GetHashCode(); + if (HasD) hash ^= D.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasC) { + output.WriteRawTag(8); + output.WriteInt32(C); + } + if (HasD) { + output.WriteRawTag(16); + output.WriteInt32(D); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasC) { + output.WriteRawTag(8); + output.WriteInt32(C); + } + if (HasD) { + output.WriteRawTag(16); + output.WriteInt32(D); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasC) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(C); + } + if (HasD) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(D); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ForeignMessage other) { + if (other == null) { + return; + } + if (other.HasC) { + C = other.C; + } + if (other.HasD) { + D = other.D; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + C = input.ReadInt32(); + break; + } + case 16: { + D = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + C = input.ReadInt32(); + break; + } + case 16: { + D = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestReservedFields : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestReservedFields()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestReservedFields() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestReservedFields(TestReservedFields other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestReservedFields Clone() { + return new TestReservedFields(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestReservedFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestReservedFields other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestReservedFields other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class TestAllExtensions : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestAllExtensions()); + private pb::UnknownFieldSet _unknownFields; + private pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[6]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllExtensions() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllExtensions(TestAllExtensions other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllExtensions Clone() { + return new TestAllExtensions(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestAllExtensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestAllExtensions other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestAllExtensions other) { + if (other == null) { + return; + } + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + + } + + public sealed partial class OptionalGroup_extension : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OptionalGroup_extension()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[7]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup_extension() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup_extension(OptionalGroup_extension other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup_extension Clone() { + return new OptionalGroup_extension(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 17; + private readonly static int ADefaultValue = 0; + + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as OptionalGroup_extension); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(OptionalGroup_extension other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(136, 1); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(136, 1); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(OptionalGroup_extension other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 132: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 136: { + A = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 132: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 136: { + A = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class RepeatedGroup_extension : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RepeatedGroup_extension()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[8]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RepeatedGroup_extension() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RepeatedGroup_extension(RepeatedGroup_extension other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RepeatedGroup_extension Clone() { + return new RepeatedGroup_extension(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 47; + private readonly static int ADefaultValue = 0; + + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as RepeatedGroup_extension); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(RepeatedGroup_extension other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(248, 2); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(248, 2); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(RepeatedGroup_extension other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 372: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 376: { + A = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 372: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 376: { + A = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestGroup : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestGroup()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[9]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestGroup() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestGroup(TestGroup other) : this() { + _hasBits0 = other._hasBits0; + optionalGroup_ = other.HasOptionalGroup ? other.optionalGroup_.Clone() : null; + optionalForeignEnum_ = other.optionalForeignEnum_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestGroup Clone() { + return new TestGroup(this); + } + + /// Field number for the "optionalgroup" field. + public const int OptionalGroupFieldNumber = 16; + private global::Google.Protobuf.TestProtos.Proto2.TestGroup.Types.OptionalGroup optionalGroup_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestGroup.Types.OptionalGroup OptionalGroup { + get { return optionalGroup_; } + set { + optionalGroup_ = value; + } + } + /// Gets whether the optionalgroup field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalGroup { + get { return optionalGroup_ != null; } + } + /// Clears the value of the optionalgroup field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalGroup() { + optionalGroup_ = null; + } + + /// Field number for the "optional_foreign_enum" field. + public const int OptionalForeignEnumFieldNumber = 22; + private readonly static global::Google.Protobuf.TestProtos.Proto2.ForeignEnum OptionalForeignEnumDefaultValue = global::Google.Protobuf.TestProtos.Proto2.ForeignEnum.ForeignFoo; + + private global::Google.Protobuf.TestProtos.Proto2.ForeignEnum optionalForeignEnum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.ForeignEnum OptionalForeignEnum { + get { if ((_hasBits0 & 1) != 0) { return optionalForeignEnum_; } else { return OptionalForeignEnumDefaultValue; } } + set { + _hasBits0 |= 1; + optionalForeignEnum_ = value; + } + } + /// Gets whether the "optional_foreign_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalForeignEnum { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "optional_foreign_enum" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalForeignEnum() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestGroup); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestGroup other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(OptionalGroup, other.OptionalGroup)) return false; + if (OptionalForeignEnum != other.OptionalForeignEnum) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasOptionalGroup) hash ^= OptionalGroup.GetHashCode(); + if (HasOptionalForeignEnum) hash ^= OptionalForeignEnum.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasOptionalGroup) { + output.WriteRawTag(131, 1); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(132, 1); + } + if (HasOptionalForeignEnum) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) OptionalForeignEnum); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasOptionalGroup) { + output.WriteRawTag(131, 1); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(132, 1); + } + if (HasOptionalForeignEnum) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) OptionalForeignEnum); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasOptionalGroup) { + size += 4 + pb::CodedOutputStream.ComputeGroupSize(OptionalGroup); + } + if (HasOptionalForeignEnum) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalForeignEnum); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestGroup other) { + if (other == null) { + return; + } + if (other.HasOptionalGroup) { + if (!HasOptionalGroup) { + OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestGroup.Types.OptionalGroup(); + } + OptionalGroup.MergeFrom(other.OptionalGroup); + } + if (other.HasOptionalForeignEnum) { + OptionalForeignEnum = other.OptionalForeignEnum; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 131: { + if (!HasOptionalGroup) { + OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestGroup.Types.OptionalGroup(); + } + input.ReadGroup(OptionalGroup); + break; + } + case 176: { + OptionalForeignEnum = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 131: { + if (!HasOptionalGroup) { + OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestGroup.Types.OptionalGroup(); + } + input.ReadGroup(OptionalGroup); + break; + } + case 176: { + OptionalForeignEnum = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestGroup message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class OptionalGroup : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OptionalGroup()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestGroup.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup(OptionalGroup other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup Clone() { + return new OptionalGroup(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 17; + private readonly static int ADefaultValue = 0; + + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as OptionalGroup); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(OptionalGroup other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(136, 1); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(136, 1); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(OptionalGroup other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 132: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 136: { + A = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 132: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 136: { + A = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class TestGroupExtension : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestGroupExtension()); + private pb::UnknownFieldSet _unknownFields; + private pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[10]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestGroupExtension() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestGroupExtension(TestGroupExtension other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestGroupExtension Clone() { + return new TestGroupExtension(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestGroupExtension); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestGroupExtension other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestGroupExtension other) { + if (other == null) { + return; + } + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + + } + + public sealed partial class TestNestedExtension : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestNestedExtension()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[11]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestNestedExtension() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestNestedExtension(TestNestedExtension other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestNestedExtension Clone() { + return new TestNestedExtension(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestNestedExtension); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestNestedExtension other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestNestedExtension other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestNestedExtension message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class OptionalGroup_extension : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OptionalGroup_extension()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestNestedExtension.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup_extension() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup_extension(OptionalGroup_extension other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup_extension Clone() { + return new OptionalGroup_extension(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 17; + private readonly static int ADefaultValue = 0; + + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as OptionalGroup_extension); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(OptionalGroup_extension other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(136, 1); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(136, 1); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(OptionalGroup_extension other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 132: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 136: { + A = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 132: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 136: { + A = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + #region Extensions + /// Container for extensions for other messages declared in the TestNestedExtension message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Extensions { + /// + /// Check for bug where string extensions declared in tested scope did not + /// compile. + /// + public static readonly pb::Extension Test = + new pb::Extension(1002, pb::FieldCodec.ForString(8018, global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("dGVzdA=="), 0, 4))); + /// + /// Used to test if generated extension name is correct when there are + /// underscores. + /// + public static readonly pb::Extension NestedStringExtension = + new pb::Extension(1003, pb::FieldCodec.ForString(8026, "")); + public static readonly pb::Extension OptionalGroupExtension = + new pb::Extension(16, pb::FieldCodec.ForGroup(131, 132, global::Google.Protobuf.TestProtos.Proto2.TestNestedExtension.Types.OptionalGroup_extension.Parser)); + public static readonly pb::Extension OptionalForeignEnumExtension = + new pb::Extension(22, pb::FieldCodec.ForEnum(176, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) x, global::Google.Protobuf.TestProtos.Proto2.ForeignEnum.ForeignFoo)); + } + #endregion + + } + + /// + /// We have separate messages for testing required fields because it's + /// annoying to have to fill in required fields in TestProto in order to + /// do anything with it. Note that we don't need to test every type of + /// required filed because the code output is basically identical to + /// optional fields for all types. + /// + public sealed partial class TestRequired : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRequired()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + private int _hasBits1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[12]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequired() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequired(TestRequired other) : this() { + _hasBits0 = other._hasBits0; + _hasBits1 = other._hasBits1; + a_ = other.a_; + dummy2_ = other.dummy2_; + b_ = other.b_; + dummy4_ = other.dummy4_; + dummy5_ = other.dummy5_; + dummy6_ = other.dummy6_; + dummy7_ = other.dummy7_; + dummy8_ = other.dummy8_; + dummy9_ = other.dummy9_; + dummy10_ = other.dummy10_; + dummy11_ = other.dummy11_; + dummy12_ = other.dummy12_; + dummy13_ = other.dummy13_; + dummy14_ = other.dummy14_; + dummy15_ = other.dummy15_; + dummy16_ = other.dummy16_; + dummy17_ = other.dummy17_; + dummy18_ = other.dummy18_; + dummy19_ = other.dummy19_; + dummy20_ = other.dummy20_; + dummy21_ = other.dummy21_; + dummy22_ = other.dummy22_; + dummy23_ = other.dummy23_; + dummy24_ = other.dummy24_; + dummy25_ = other.dummy25_; + dummy26_ = other.dummy26_; + dummy27_ = other.dummy27_; + dummy28_ = other.dummy28_; + dummy29_ = other.dummy29_; + dummy30_ = other.dummy30_; + dummy31_ = other.dummy31_; + dummy32_ = other.dummy32_; + c_ = other.c_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequired Clone() { + return new TestRequired(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private readonly static int ADefaultValue = 0; + + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + /// Field number for the "dummy2" field. + public const int Dummy2FieldNumber = 2; + private readonly static int Dummy2DefaultValue = 0; + + private int dummy2_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy2 { + get { if ((_hasBits0 & 2) != 0) { return dummy2_; } else { return Dummy2DefaultValue; } } + set { + _hasBits0 |= 2; + dummy2_ = value; + } + } + /// Gets whether the "dummy2" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy2 { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "dummy2" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy2() { + _hasBits0 &= ~2; + } + + /// Field number for the "b" field. + public const int BFieldNumber = 3; + private readonly static int BDefaultValue = 0; + + private int b_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int B { + get { if ((_hasBits0 & 4) != 0) { return b_; } else { return BDefaultValue; } } + set { + _hasBits0 |= 4; + b_ = value; + } + } + /// Gets whether the "b" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasB { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "b" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearB() { + _hasBits0 &= ~4; + } + + /// Field number for the "dummy4" field. + public const int Dummy4FieldNumber = 4; + private readonly static int Dummy4DefaultValue = 0; + + private int dummy4_; + /// + /// Pad the field count to 32 so that we can test that IsInitialized() + /// properly checks multiple elements of has_bits_. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy4 { + get { if ((_hasBits0 & 8) != 0) { return dummy4_; } else { return Dummy4DefaultValue; } } + set { + _hasBits0 |= 8; + dummy4_ = value; + } + } + /// Gets whether the "dummy4" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy4 { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "dummy4" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy4() { + _hasBits0 &= ~8; + } + + /// Field number for the "dummy5" field. + public const int Dummy5FieldNumber = 5; + private readonly static int Dummy5DefaultValue = 0; + + private int dummy5_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy5 { + get { if ((_hasBits0 & 16) != 0) { return dummy5_; } else { return Dummy5DefaultValue; } } + set { + _hasBits0 |= 16; + dummy5_ = value; + } + } + /// Gets whether the "dummy5" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy5 { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "dummy5" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy5() { + _hasBits0 &= ~16; + } + + /// Field number for the "dummy6" field. + public const int Dummy6FieldNumber = 6; + private readonly static int Dummy6DefaultValue = 0; + + private int dummy6_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy6 { + get { if ((_hasBits0 & 32) != 0) { return dummy6_; } else { return Dummy6DefaultValue; } } + set { + _hasBits0 |= 32; + dummy6_ = value; + } + } + /// Gets whether the "dummy6" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy6 { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "dummy6" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy6() { + _hasBits0 &= ~32; + } + + /// Field number for the "dummy7" field. + public const int Dummy7FieldNumber = 7; + private readonly static int Dummy7DefaultValue = 0; + + private int dummy7_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy7 { + get { if ((_hasBits0 & 64) != 0) { return dummy7_; } else { return Dummy7DefaultValue; } } + set { + _hasBits0 |= 64; + dummy7_ = value; + } + } + /// Gets whether the "dummy7" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy7 { + get { return (_hasBits0 & 64) != 0; } + } + /// Clears the value of the "dummy7" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy7() { + _hasBits0 &= ~64; + } + + /// Field number for the "dummy8" field. + public const int Dummy8FieldNumber = 8; + private readonly static int Dummy8DefaultValue = 0; + + private int dummy8_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy8 { + get { if ((_hasBits0 & 128) != 0) { return dummy8_; } else { return Dummy8DefaultValue; } } + set { + _hasBits0 |= 128; + dummy8_ = value; + } + } + /// Gets whether the "dummy8" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy8 { + get { return (_hasBits0 & 128) != 0; } + } + /// Clears the value of the "dummy8" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy8() { + _hasBits0 &= ~128; + } + + /// Field number for the "dummy9" field. + public const int Dummy9FieldNumber = 9; + private readonly static int Dummy9DefaultValue = 0; + + private int dummy9_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy9 { + get { if ((_hasBits0 & 256) != 0) { return dummy9_; } else { return Dummy9DefaultValue; } } + set { + _hasBits0 |= 256; + dummy9_ = value; + } + } + /// Gets whether the "dummy9" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy9 { + get { return (_hasBits0 & 256) != 0; } + } + /// Clears the value of the "dummy9" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy9() { + _hasBits0 &= ~256; + } + + /// Field number for the "dummy10" field. + public const int Dummy10FieldNumber = 10; + private readonly static int Dummy10DefaultValue = 0; + + private int dummy10_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy10 { + get { if ((_hasBits0 & 512) != 0) { return dummy10_; } else { return Dummy10DefaultValue; } } + set { + _hasBits0 |= 512; + dummy10_ = value; + } + } + /// Gets whether the "dummy10" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy10 { + get { return (_hasBits0 & 512) != 0; } + } + /// Clears the value of the "dummy10" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy10() { + _hasBits0 &= ~512; + } + + /// Field number for the "dummy11" field. + public const int Dummy11FieldNumber = 11; + private readonly static int Dummy11DefaultValue = 0; + + private int dummy11_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy11 { + get { if ((_hasBits0 & 1024) != 0) { return dummy11_; } else { return Dummy11DefaultValue; } } + set { + _hasBits0 |= 1024; + dummy11_ = value; + } + } + /// Gets whether the "dummy11" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy11 { + get { return (_hasBits0 & 1024) != 0; } + } + /// Clears the value of the "dummy11" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy11() { + _hasBits0 &= ~1024; + } + + /// Field number for the "dummy12" field. + public const int Dummy12FieldNumber = 12; + private readonly static int Dummy12DefaultValue = 0; + + private int dummy12_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy12 { + get { if ((_hasBits0 & 2048) != 0) { return dummy12_; } else { return Dummy12DefaultValue; } } + set { + _hasBits0 |= 2048; + dummy12_ = value; + } + } + /// Gets whether the "dummy12" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy12 { + get { return (_hasBits0 & 2048) != 0; } + } + /// Clears the value of the "dummy12" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy12() { + _hasBits0 &= ~2048; + } + + /// Field number for the "dummy13" field. + public const int Dummy13FieldNumber = 13; + private readonly static int Dummy13DefaultValue = 0; + + private int dummy13_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy13 { + get { if ((_hasBits0 & 4096) != 0) { return dummy13_; } else { return Dummy13DefaultValue; } } + set { + _hasBits0 |= 4096; + dummy13_ = value; + } + } + /// Gets whether the "dummy13" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy13 { + get { return (_hasBits0 & 4096) != 0; } + } + /// Clears the value of the "dummy13" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy13() { + _hasBits0 &= ~4096; + } + + /// Field number for the "dummy14" field. + public const int Dummy14FieldNumber = 14; + private readonly static int Dummy14DefaultValue = 0; + + private int dummy14_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy14 { + get { if ((_hasBits0 & 8192) != 0) { return dummy14_; } else { return Dummy14DefaultValue; } } + set { + _hasBits0 |= 8192; + dummy14_ = value; + } + } + /// Gets whether the "dummy14" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy14 { + get { return (_hasBits0 & 8192) != 0; } + } + /// Clears the value of the "dummy14" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy14() { + _hasBits0 &= ~8192; + } + + /// Field number for the "dummy15" field. + public const int Dummy15FieldNumber = 15; + private readonly static int Dummy15DefaultValue = 0; + + private int dummy15_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy15 { + get { if ((_hasBits0 & 16384) != 0) { return dummy15_; } else { return Dummy15DefaultValue; } } + set { + _hasBits0 |= 16384; + dummy15_ = value; + } + } + /// Gets whether the "dummy15" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy15 { + get { return (_hasBits0 & 16384) != 0; } + } + /// Clears the value of the "dummy15" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy15() { + _hasBits0 &= ~16384; + } + + /// Field number for the "dummy16" field. + public const int Dummy16FieldNumber = 16; + private readonly static int Dummy16DefaultValue = 0; + + private int dummy16_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy16 { + get { if ((_hasBits0 & 32768) != 0) { return dummy16_; } else { return Dummy16DefaultValue; } } + set { + _hasBits0 |= 32768; + dummy16_ = value; + } + } + /// Gets whether the "dummy16" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy16 { + get { return (_hasBits0 & 32768) != 0; } + } + /// Clears the value of the "dummy16" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy16() { + _hasBits0 &= ~32768; + } + + /// Field number for the "dummy17" field. + public const int Dummy17FieldNumber = 17; + private readonly static int Dummy17DefaultValue = 0; + + private int dummy17_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy17 { + get { if ((_hasBits0 & 65536) != 0) { return dummy17_; } else { return Dummy17DefaultValue; } } + set { + _hasBits0 |= 65536; + dummy17_ = value; + } + } + /// Gets whether the "dummy17" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy17 { + get { return (_hasBits0 & 65536) != 0; } + } + /// Clears the value of the "dummy17" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy17() { + _hasBits0 &= ~65536; + } + + /// Field number for the "dummy18" field. + public const int Dummy18FieldNumber = 18; + private readonly static int Dummy18DefaultValue = 0; + + private int dummy18_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy18 { + get { if ((_hasBits0 & 131072) != 0) { return dummy18_; } else { return Dummy18DefaultValue; } } + set { + _hasBits0 |= 131072; + dummy18_ = value; + } + } + /// Gets whether the "dummy18" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy18 { + get { return (_hasBits0 & 131072) != 0; } + } + /// Clears the value of the "dummy18" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy18() { + _hasBits0 &= ~131072; + } + + /// Field number for the "dummy19" field. + public const int Dummy19FieldNumber = 19; + private readonly static int Dummy19DefaultValue = 0; + + private int dummy19_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy19 { + get { if ((_hasBits0 & 262144) != 0) { return dummy19_; } else { return Dummy19DefaultValue; } } + set { + _hasBits0 |= 262144; + dummy19_ = value; + } + } + /// Gets whether the "dummy19" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy19 { + get { return (_hasBits0 & 262144) != 0; } + } + /// Clears the value of the "dummy19" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy19() { + _hasBits0 &= ~262144; + } + + /// Field number for the "dummy20" field. + public const int Dummy20FieldNumber = 20; + private readonly static int Dummy20DefaultValue = 0; + + private int dummy20_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy20 { + get { if ((_hasBits0 & 524288) != 0) { return dummy20_; } else { return Dummy20DefaultValue; } } + set { + _hasBits0 |= 524288; + dummy20_ = value; + } + } + /// Gets whether the "dummy20" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy20 { + get { return (_hasBits0 & 524288) != 0; } + } + /// Clears the value of the "dummy20" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy20() { + _hasBits0 &= ~524288; + } + + /// Field number for the "dummy21" field. + public const int Dummy21FieldNumber = 21; + private readonly static int Dummy21DefaultValue = 0; + + private int dummy21_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy21 { + get { if ((_hasBits0 & 1048576) != 0) { return dummy21_; } else { return Dummy21DefaultValue; } } + set { + _hasBits0 |= 1048576; + dummy21_ = value; + } + } + /// Gets whether the "dummy21" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy21 { + get { return (_hasBits0 & 1048576) != 0; } + } + /// Clears the value of the "dummy21" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy21() { + _hasBits0 &= ~1048576; + } + + /// Field number for the "dummy22" field. + public const int Dummy22FieldNumber = 22; + private readonly static int Dummy22DefaultValue = 0; + + private int dummy22_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy22 { + get { if ((_hasBits0 & 2097152) != 0) { return dummy22_; } else { return Dummy22DefaultValue; } } + set { + _hasBits0 |= 2097152; + dummy22_ = value; + } + } + /// Gets whether the "dummy22" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy22 { + get { return (_hasBits0 & 2097152) != 0; } + } + /// Clears the value of the "dummy22" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy22() { + _hasBits0 &= ~2097152; + } + + /// Field number for the "dummy23" field. + public const int Dummy23FieldNumber = 23; + private readonly static int Dummy23DefaultValue = 0; + + private int dummy23_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy23 { + get { if ((_hasBits0 & 4194304) != 0) { return dummy23_; } else { return Dummy23DefaultValue; } } + set { + _hasBits0 |= 4194304; + dummy23_ = value; + } + } + /// Gets whether the "dummy23" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy23 { + get { return (_hasBits0 & 4194304) != 0; } + } + /// Clears the value of the "dummy23" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy23() { + _hasBits0 &= ~4194304; + } + + /// Field number for the "dummy24" field. + public const int Dummy24FieldNumber = 24; + private readonly static int Dummy24DefaultValue = 0; + + private int dummy24_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy24 { + get { if ((_hasBits0 & 8388608) != 0) { return dummy24_; } else { return Dummy24DefaultValue; } } + set { + _hasBits0 |= 8388608; + dummy24_ = value; + } + } + /// Gets whether the "dummy24" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy24 { + get { return (_hasBits0 & 8388608) != 0; } + } + /// Clears the value of the "dummy24" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy24() { + _hasBits0 &= ~8388608; + } + + /// Field number for the "dummy25" field. + public const int Dummy25FieldNumber = 25; + private readonly static int Dummy25DefaultValue = 0; + + private int dummy25_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy25 { + get { if ((_hasBits0 & 16777216) != 0) { return dummy25_; } else { return Dummy25DefaultValue; } } + set { + _hasBits0 |= 16777216; + dummy25_ = value; + } + } + /// Gets whether the "dummy25" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy25 { + get { return (_hasBits0 & 16777216) != 0; } + } + /// Clears the value of the "dummy25" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy25() { + _hasBits0 &= ~16777216; + } + + /// Field number for the "dummy26" field. + public const int Dummy26FieldNumber = 26; + private readonly static int Dummy26DefaultValue = 0; + + private int dummy26_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy26 { + get { if ((_hasBits0 & 33554432) != 0) { return dummy26_; } else { return Dummy26DefaultValue; } } + set { + _hasBits0 |= 33554432; + dummy26_ = value; + } + } + /// Gets whether the "dummy26" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy26 { + get { return (_hasBits0 & 33554432) != 0; } + } + /// Clears the value of the "dummy26" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy26() { + _hasBits0 &= ~33554432; + } + + /// Field number for the "dummy27" field. + public const int Dummy27FieldNumber = 27; + private readonly static int Dummy27DefaultValue = 0; + + private int dummy27_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy27 { + get { if ((_hasBits0 & 67108864) != 0) { return dummy27_; } else { return Dummy27DefaultValue; } } + set { + _hasBits0 |= 67108864; + dummy27_ = value; + } + } + /// Gets whether the "dummy27" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy27 { + get { return (_hasBits0 & 67108864) != 0; } + } + /// Clears the value of the "dummy27" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy27() { + _hasBits0 &= ~67108864; + } + + /// Field number for the "dummy28" field. + public const int Dummy28FieldNumber = 28; + private readonly static int Dummy28DefaultValue = 0; + + private int dummy28_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy28 { + get { if ((_hasBits0 & 134217728) != 0) { return dummy28_; } else { return Dummy28DefaultValue; } } + set { + _hasBits0 |= 134217728; + dummy28_ = value; + } + } + /// Gets whether the "dummy28" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy28 { + get { return (_hasBits0 & 134217728) != 0; } + } + /// Clears the value of the "dummy28" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy28() { + _hasBits0 &= ~134217728; + } + + /// Field number for the "dummy29" field. + public const int Dummy29FieldNumber = 29; + private readonly static int Dummy29DefaultValue = 0; + + private int dummy29_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy29 { + get { if ((_hasBits0 & 268435456) != 0) { return dummy29_; } else { return Dummy29DefaultValue; } } + set { + _hasBits0 |= 268435456; + dummy29_ = value; + } + } + /// Gets whether the "dummy29" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy29 { + get { return (_hasBits0 & 268435456) != 0; } + } + /// Clears the value of the "dummy29" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy29() { + _hasBits0 &= ~268435456; + } + + /// Field number for the "dummy30" field. + public const int Dummy30FieldNumber = 30; + private readonly static int Dummy30DefaultValue = 0; + + private int dummy30_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy30 { + get { if ((_hasBits0 & 536870912) != 0) { return dummy30_; } else { return Dummy30DefaultValue; } } + set { + _hasBits0 |= 536870912; + dummy30_ = value; + } + } + /// Gets whether the "dummy30" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy30 { + get { return (_hasBits0 & 536870912) != 0; } + } + /// Clears the value of the "dummy30" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy30() { + _hasBits0 &= ~536870912; + } + + /// Field number for the "dummy31" field. + public const int Dummy31FieldNumber = 31; + private readonly static int Dummy31DefaultValue = 0; + + private int dummy31_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy31 { + get { if ((_hasBits0 & 1073741824) != 0) { return dummy31_; } else { return Dummy31DefaultValue; } } + set { + _hasBits0 |= 1073741824; + dummy31_ = value; + } + } + /// Gets whether the "dummy31" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy31 { + get { return (_hasBits0 & 1073741824) != 0; } + } + /// Clears the value of the "dummy31" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy31() { + _hasBits0 &= ~1073741824; + } + + /// Field number for the "dummy32" field. + public const int Dummy32FieldNumber = 32; + private readonly static int Dummy32DefaultValue = 0; + + private int dummy32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy32 { + get { if ((_hasBits0 & -2147483648) != 0) { return dummy32_; } else { return Dummy32DefaultValue; } } + set { + _hasBits0 |= -2147483648; + dummy32_ = value; + } + } + /// Gets whether the "dummy32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy32 { + get { return (_hasBits0 & -2147483648) != 0; } + } + /// Clears the value of the "dummy32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy32() { + _hasBits0 &= ~-2147483648; + } + + /// Field number for the "c" field. + public const int CFieldNumber = 33; + private readonly static int CDefaultValue = 0; + + private int c_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int C { + get { if ((_hasBits1 & 1) != 0) { return c_; } else { return CDefaultValue; } } + set { + _hasBits1 |= 1; + c_ = value; + } + } + /// Gets whether the "c" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasC { + get { return (_hasBits1 & 1) != 0; } + } + /// Clears the value of the "c" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearC() { + _hasBits1 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestRequired); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestRequired other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + if (Dummy2 != other.Dummy2) return false; + if (B != other.B) return false; + if (Dummy4 != other.Dummy4) return false; + if (Dummy5 != other.Dummy5) return false; + if (Dummy6 != other.Dummy6) return false; + if (Dummy7 != other.Dummy7) return false; + if (Dummy8 != other.Dummy8) return false; + if (Dummy9 != other.Dummy9) return false; + if (Dummy10 != other.Dummy10) return false; + if (Dummy11 != other.Dummy11) return false; + if (Dummy12 != other.Dummy12) return false; + if (Dummy13 != other.Dummy13) return false; + if (Dummy14 != other.Dummy14) return false; + if (Dummy15 != other.Dummy15) return false; + if (Dummy16 != other.Dummy16) return false; + if (Dummy17 != other.Dummy17) return false; + if (Dummy18 != other.Dummy18) return false; + if (Dummy19 != other.Dummy19) return false; + if (Dummy20 != other.Dummy20) return false; + if (Dummy21 != other.Dummy21) return false; + if (Dummy22 != other.Dummy22) return false; + if (Dummy23 != other.Dummy23) return false; + if (Dummy24 != other.Dummy24) return false; + if (Dummy25 != other.Dummy25) return false; + if (Dummy26 != other.Dummy26) return false; + if (Dummy27 != other.Dummy27) return false; + if (Dummy28 != other.Dummy28) return false; + if (Dummy29 != other.Dummy29) return false; + if (Dummy30 != other.Dummy30) return false; + if (Dummy31 != other.Dummy31) return false; + if (Dummy32 != other.Dummy32) return false; + if (C != other.C) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (HasDummy2) hash ^= Dummy2.GetHashCode(); + if (HasB) hash ^= B.GetHashCode(); + if (HasDummy4) hash ^= Dummy4.GetHashCode(); + if (HasDummy5) hash ^= Dummy5.GetHashCode(); + if (HasDummy6) hash ^= Dummy6.GetHashCode(); + if (HasDummy7) hash ^= Dummy7.GetHashCode(); + if (HasDummy8) hash ^= Dummy8.GetHashCode(); + if (HasDummy9) hash ^= Dummy9.GetHashCode(); + if (HasDummy10) hash ^= Dummy10.GetHashCode(); + if (HasDummy11) hash ^= Dummy11.GetHashCode(); + if (HasDummy12) hash ^= Dummy12.GetHashCode(); + if (HasDummy13) hash ^= Dummy13.GetHashCode(); + if (HasDummy14) hash ^= Dummy14.GetHashCode(); + if (HasDummy15) hash ^= Dummy15.GetHashCode(); + if (HasDummy16) hash ^= Dummy16.GetHashCode(); + if (HasDummy17) hash ^= Dummy17.GetHashCode(); + if (HasDummy18) hash ^= Dummy18.GetHashCode(); + if (HasDummy19) hash ^= Dummy19.GetHashCode(); + if (HasDummy20) hash ^= Dummy20.GetHashCode(); + if (HasDummy21) hash ^= Dummy21.GetHashCode(); + if (HasDummy22) hash ^= Dummy22.GetHashCode(); + if (HasDummy23) hash ^= Dummy23.GetHashCode(); + if (HasDummy24) hash ^= Dummy24.GetHashCode(); + if (HasDummy25) hash ^= Dummy25.GetHashCode(); + if (HasDummy26) hash ^= Dummy26.GetHashCode(); + if (HasDummy27) hash ^= Dummy27.GetHashCode(); + if (HasDummy28) hash ^= Dummy28.GetHashCode(); + if (HasDummy29) hash ^= Dummy29.GetHashCode(); + if (HasDummy30) hash ^= Dummy30.GetHashCode(); + if (HasDummy31) hash ^= Dummy31.GetHashCode(); + if (HasDummy32) hash ^= Dummy32.GetHashCode(); + if (HasC) hash ^= C.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (HasDummy2) { + output.WriteRawTag(16); + output.WriteInt32(Dummy2); + } + if (HasB) { + output.WriteRawTag(24); + output.WriteInt32(B); + } + if (HasDummy4) { + output.WriteRawTag(32); + output.WriteInt32(Dummy4); + } + if (HasDummy5) { + output.WriteRawTag(40); + output.WriteInt32(Dummy5); + } + if (HasDummy6) { + output.WriteRawTag(48); + output.WriteInt32(Dummy6); + } + if (HasDummy7) { + output.WriteRawTag(56); + output.WriteInt32(Dummy7); + } + if (HasDummy8) { + output.WriteRawTag(64); + output.WriteInt32(Dummy8); + } + if (HasDummy9) { + output.WriteRawTag(72); + output.WriteInt32(Dummy9); + } + if (HasDummy10) { + output.WriteRawTag(80); + output.WriteInt32(Dummy10); + } + if (HasDummy11) { + output.WriteRawTag(88); + output.WriteInt32(Dummy11); + } + if (HasDummy12) { + output.WriteRawTag(96); + output.WriteInt32(Dummy12); + } + if (HasDummy13) { + output.WriteRawTag(104); + output.WriteInt32(Dummy13); + } + if (HasDummy14) { + output.WriteRawTag(112); + output.WriteInt32(Dummy14); + } + if (HasDummy15) { + output.WriteRawTag(120); + output.WriteInt32(Dummy15); + } + if (HasDummy16) { + output.WriteRawTag(128, 1); + output.WriteInt32(Dummy16); + } + if (HasDummy17) { + output.WriteRawTag(136, 1); + output.WriteInt32(Dummy17); + } + if (HasDummy18) { + output.WriteRawTag(144, 1); + output.WriteInt32(Dummy18); + } + if (HasDummy19) { + output.WriteRawTag(152, 1); + output.WriteInt32(Dummy19); + } + if (HasDummy20) { + output.WriteRawTag(160, 1); + output.WriteInt32(Dummy20); + } + if (HasDummy21) { + output.WriteRawTag(168, 1); + output.WriteInt32(Dummy21); + } + if (HasDummy22) { + output.WriteRawTag(176, 1); + output.WriteInt32(Dummy22); + } + if (HasDummy23) { + output.WriteRawTag(184, 1); + output.WriteInt32(Dummy23); + } + if (HasDummy24) { + output.WriteRawTag(192, 1); + output.WriteInt32(Dummy24); + } + if (HasDummy25) { + output.WriteRawTag(200, 1); + output.WriteInt32(Dummy25); + } + if (HasDummy26) { + output.WriteRawTag(208, 1); + output.WriteInt32(Dummy26); + } + if (HasDummy27) { + output.WriteRawTag(216, 1); + output.WriteInt32(Dummy27); + } + if (HasDummy28) { + output.WriteRawTag(224, 1); + output.WriteInt32(Dummy28); + } + if (HasDummy29) { + output.WriteRawTag(232, 1); + output.WriteInt32(Dummy29); + } + if (HasDummy30) { + output.WriteRawTag(240, 1); + output.WriteInt32(Dummy30); + } + if (HasDummy31) { + output.WriteRawTag(248, 1); + output.WriteInt32(Dummy31); + } + if (HasDummy32) { + output.WriteRawTag(128, 2); + output.WriteInt32(Dummy32); + } + if (HasC) { + output.WriteRawTag(136, 2); + output.WriteInt32(C); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (HasDummy2) { + output.WriteRawTag(16); + output.WriteInt32(Dummy2); + } + if (HasB) { + output.WriteRawTag(24); + output.WriteInt32(B); + } + if (HasDummy4) { + output.WriteRawTag(32); + output.WriteInt32(Dummy4); + } + if (HasDummy5) { + output.WriteRawTag(40); + output.WriteInt32(Dummy5); + } + if (HasDummy6) { + output.WriteRawTag(48); + output.WriteInt32(Dummy6); + } + if (HasDummy7) { + output.WriteRawTag(56); + output.WriteInt32(Dummy7); + } + if (HasDummy8) { + output.WriteRawTag(64); + output.WriteInt32(Dummy8); + } + if (HasDummy9) { + output.WriteRawTag(72); + output.WriteInt32(Dummy9); + } + if (HasDummy10) { + output.WriteRawTag(80); + output.WriteInt32(Dummy10); + } + if (HasDummy11) { + output.WriteRawTag(88); + output.WriteInt32(Dummy11); + } + if (HasDummy12) { + output.WriteRawTag(96); + output.WriteInt32(Dummy12); + } + if (HasDummy13) { + output.WriteRawTag(104); + output.WriteInt32(Dummy13); + } + if (HasDummy14) { + output.WriteRawTag(112); + output.WriteInt32(Dummy14); + } + if (HasDummy15) { + output.WriteRawTag(120); + output.WriteInt32(Dummy15); + } + if (HasDummy16) { + output.WriteRawTag(128, 1); + output.WriteInt32(Dummy16); + } + if (HasDummy17) { + output.WriteRawTag(136, 1); + output.WriteInt32(Dummy17); + } + if (HasDummy18) { + output.WriteRawTag(144, 1); + output.WriteInt32(Dummy18); + } + if (HasDummy19) { + output.WriteRawTag(152, 1); + output.WriteInt32(Dummy19); + } + if (HasDummy20) { + output.WriteRawTag(160, 1); + output.WriteInt32(Dummy20); + } + if (HasDummy21) { + output.WriteRawTag(168, 1); + output.WriteInt32(Dummy21); + } + if (HasDummy22) { + output.WriteRawTag(176, 1); + output.WriteInt32(Dummy22); + } + if (HasDummy23) { + output.WriteRawTag(184, 1); + output.WriteInt32(Dummy23); + } + if (HasDummy24) { + output.WriteRawTag(192, 1); + output.WriteInt32(Dummy24); + } + if (HasDummy25) { + output.WriteRawTag(200, 1); + output.WriteInt32(Dummy25); + } + if (HasDummy26) { + output.WriteRawTag(208, 1); + output.WriteInt32(Dummy26); + } + if (HasDummy27) { + output.WriteRawTag(216, 1); + output.WriteInt32(Dummy27); + } + if (HasDummy28) { + output.WriteRawTag(224, 1); + output.WriteInt32(Dummy28); + } + if (HasDummy29) { + output.WriteRawTag(232, 1); + output.WriteInt32(Dummy29); + } + if (HasDummy30) { + output.WriteRawTag(240, 1); + output.WriteInt32(Dummy30); + } + if (HasDummy31) { + output.WriteRawTag(248, 1); + output.WriteInt32(Dummy31); + } + if (HasDummy32) { + output.WriteRawTag(128, 2); + output.WriteInt32(Dummy32); + } + if (HasC) { + output.WriteRawTag(136, 2); + output.WriteInt32(C); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (HasDummy2) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Dummy2); + } + if (HasB) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(B); + } + if (HasDummy4) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Dummy4); + } + if (HasDummy5) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Dummy5); + } + if (HasDummy6) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Dummy6); + } + if (HasDummy7) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Dummy7); + } + if (HasDummy8) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Dummy8); + } + if (HasDummy9) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Dummy9); + } + if (HasDummy10) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Dummy10); + } + if (HasDummy11) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Dummy11); + } + if (HasDummy12) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Dummy12); + } + if (HasDummy13) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Dummy13); + } + if (HasDummy14) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Dummy14); + } + if (HasDummy15) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Dummy15); + } + if (HasDummy16) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy16); + } + if (HasDummy17) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy17); + } + if (HasDummy18) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy18); + } + if (HasDummy19) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy19); + } + if (HasDummy20) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy20); + } + if (HasDummy21) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy21); + } + if (HasDummy22) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy22); + } + if (HasDummy23) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy23); + } + if (HasDummy24) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy24); + } + if (HasDummy25) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy25); + } + if (HasDummy26) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy26); + } + if (HasDummy27) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy27); + } + if (HasDummy28) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy28); + } + if (HasDummy29) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy29); + } + if (HasDummy30) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy30); + } + if (HasDummy31) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy31); + } + if (HasDummy32) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Dummy32); + } + if (HasC) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(C); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestRequired other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + if (other.HasDummy2) { + Dummy2 = other.Dummy2; + } + if (other.HasB) { + B = other.B; + } + if (other.HasDummy4) { + Dummy4 = other.Dummy4; + } + if (other.HasDummy5) { + Dummy5 = other.Dummy5; + } + if (other.HasDummy6) { + Dummy6 = other.Dummy6; + } + if (other.HasDummy7) { + Dummy7 = other.Dummy7; + } + if (other.HasDummy8) { + Dummy8 = other.Dummy8; + } + if (other.HasDummy9) { + Dummy9 = other.Dummy9; + } + if (other.HasDummy10) { + Dummy10 = other.Dummy10; + } + if (other.HasDummy11) { + Dummy11 = other.Dummy11; + } + if (other.HasDummy12) { + Dummy12 = other.Dummy12; + } + if (other.HasDummy13) { + Dummy13 = other.Dummy13; + } + if (other.HasDummy14) { + Dummy14 = other.Dummy14; + } + if (other.HasDummy15) { + Dummy15 = other.Dummy15; + } + if (other.HasDummy16) { + Dummy16 = other.Dummy16; + } + if (other.HasDummy17) { + Dummy17 = other.Dummy17; + } + if (other.HasDummy18) { + Dummy18 = other.Dummy18; + } + if (other.HasDummy19) { + Dummy19 = other.Dummy19; + } + if (other.HasDummy20) { + Dummy20 = other.Dummy20; + } + if (other.HasDummy21) { + Dummy21 = other.Dummy21; + } + if (other.HasDummy22) { + Dummy22 = other.Dummy22; + } + if (other.HasDummy23) { + Dummy23 = other.Dummy23; + } + if (other.HasDummy24) { + Dummy24 = other.Dummy24; + } + if (other.HasDummy25) { + Dummy25 = other.Dummy25; + } + if (other.HasDummy26) { + Dummy26 = other.Dummy26; + } + if (other.HasDummy27) { + Dummy27 = other.Dummy27; + } + if (other.HasDummy28) { + Dummy28 = other.Dummy28; + } + if (other.HasDummy29) { + Dummy29 = other.Dummy29; + } + if (other.HasDummy30) { + Dummy30 = other.Dummy30; + } + if (other.HasDummy31) { + Dummy31 = other.Dummy31; + } + if (other.HasDummy32) { + Dummy32 = other.Dummy32; + } + if (other.HasC) { + C = other.C; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + A = input.ReadInt32(); + break; + } + case 16: { + Dummy2 = input.ReadInt32(); + break; + } + case 24: { + B = input.ReadInt32(); + break; + } + case 32: { + Dummy4 = input.ReadInt32(); + break; + } + case 40: { + Dummy5 = input.ReadInt32(); + break; + } + case 48: { + Dummy6 = input.ReadInt32(); + break; + } + case 56: { + Dummy7 = input.ReadInt32(); + break; + } + case 64: { + Dummy8 = input.ReadInt32(); + break; + } + case 72: { + Dummy9 = input.ReadInt32(); + break; + } + case 80: { + Dummy10 = input.ReadInt32(); + break; + } + case 88: { + Dummy11 = input.ReadInt32(); + break; + } + case 96: { + Dummy12 = input.ReadInt32(); + break; + } + case 104: { + Dummy13 = input.ReadInt32(); + break; + } + case 112: { + Dummy14 = input.ReadInt32(); + break; + } + case 120: { + Dummy15 = input.ReadInt32(); + break; + } + case 128: { + Dummy16 = input.ReadInt32(); + break; + } + case 136: { + Dummy17 = input.ReadInt32(); + break; + } + case 144: { + Dummy18 = input.ReadInt32(); + break; + } + case 152: { + Dummy19 = input.ReadInt32(); + break; + } + case 160: { + Dummy20 = input.ReadInt32(); + break; + } + case 168: { + Dummy21 = input.ReadInt32(); + break; + } + case 176: { + Dummy22 = input.ReadInt32(); + break; + } + case 184: { + Dummy23 = input.ReadInt32(); + break; + } + case 192: { + Dummy24 = input.ReadInt32(); + break; + } + case 200: { + Dummy25 = input.ReadInt32(); + break; + } + case 208: { + Dummy26 = input.ReadInt32(); + break; + } + case 216: { + Dummy27 = input.ReadInt32(); + break; + } + case 224: { + Dummy28 = input.ReadInt32(); + break; + } + case 232: { + Dummy29 = input.ReadInt32(); + break; + } + case 240: { + Dummy30 = input.ReadInt32(); + break; + } + case 248: { + Dummy31 = input.ReadInt32(); + break; + } + case 256: { + Dummy32 = input.ReadInt32(); + break; + } + case 264: { + C = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + A = input.ReadInt32(); + break; + } + case 16: { + Dummy2 = input.ReadInt32(); + break; + } + case 24: { + B = input.ReadInt32(); + break; + } + case 32: { + Dummy4 = input.ReadInt32(); + break; + } + case 40: { + Dummy5 = input.ReadInt32(); + break; + } + case 48: { + Dummy6 = input.ReadInt32(); + break; + } + case 56: { + Dummy7 = input.ReadInt32(); + break; + } + case 64: { + Dummy8 = input.ReadInt32(); + break; + } + case 72: { + Dummy9 = input.ReadInt32(); + break; + } + case 80: { + Dummy10 = input.ReadInt32(); + break; + } + case 88: { + Dummy11 = input.ReadInt32(); + break; + } + case 96: { + Dummy12 = input.ReadInt32(); + break; + } + case 104: { + Dummy13 = input.ReadInt32(); + break; + } + case 112: { + Dummy14 = input.ReadInt32(); + break; + } + case 120: { + Dummy15 = input.ReadInt32(); + break; + } + case 128: { + Dummy16 = input.ReadInt32(); + break; + } + case 136: { + Dummy17 = input.ReadInt32(); + break; + } + case 144: { + Dummy18 = input.ReadInt32(); + break; + } + case 152: { + Dummy19 = input.ReadInt32(); + break; + } + case 160: { + Dummy20 = input.ReadInt32(); + break; + } + case 168: { + Dummy21 = input.ReadInt32(); + break; + } + case 176: { + Dummy22 = input.ReadInt32(); + break; + } + case 184: { + Dummy23 = input.ReadInt32(); + break; + } + case 192: { + Dummy24 = input.ReadInt32(); + break; + } + case 200: { + Dummy25 = input.ReadInt32(); + break; + } + case 208: { + Dummy26 = input.ReadInt32(); + break; + } + case 216: { + Dummy27 = input.ReadInt32(); + break; + } + case 224: { + Dummy28 = input.ReadInt32(); + break; + } + case 232: { + Dummy29 = input.ReadInt32(); + break; + } + case 240: { + Dummy30 = input.ReadInt32(); + break; + } + case 248: { + Dummy31 = input.ReadInt32(); + break; + } + case 256: { + Dummy32 = input.ReadInt32(); + break; + } + case 264: { + C = input.ReadInt32(); + break; + } + } + } + } + #endif + + #region Extensions + /// Container for extensions for other messages declared in the TestRequired message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Extensions { + public static readonly pb::Extension Single = + new pb::Extension(1000, pb::FieldCodec.ForMessage(8002, global::Google.Protobuf.TestProtos.Proto2.TestRequired.Parser)); + public static readonly pb::RepeatedExtension Multi = + new pb::RepeatedExtension(1001, pb::FieldCodec.ForMessage(8010, global::Google.Protobuf.TestProtos.Proto2.TestRequired.Parser)); + } + #endregion + + } + + public sealed partial class TestRequiredForeign : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRequiredForeign()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[13]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequiredForeign() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequiredForeign(TestRequiredForeign other) : this() { + _hasBits0 = other._hasBits0; + optionalMessage_ = other.optionalMessage_ != null ? other.optionalMessage_.Clone() : null; + repeatedMessage_ = other.repeatedMessage_.Clone(); + dummy_ = other.dummy_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequiredForeign Clone() { + return new TestRequiredForeign(this); + } + + /// Field number for the "optional_message" field. + public const int OptionalMessageFieldNumber = 1; + private global::Google.Protobuf.TestProtos.Proto2.TestRequired optionalMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestRequired OptionalMessage { + get { return optionalMessage_; } + set { + optionalMessage_ = value; + } + } + + /// Field number for the "repeated_message" field. + public const int RepeatedMessageFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_repeatedMessage_codec + = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.Proto2.TestRequired.Parser); + private readonly pbc::RepeatedField repeatedMessage_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedMessage { + get { return repeatedMessage_; } + } + + /// Field number for the "dummy" field. + public const int DummyFieldNumber = 3; + private readonly static int DummyDefaultValue = 0; + + private int dummy_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Dummy { + get { if ((_hasBits0 & 1) != 0) { return dummy_; } else { return DummyDefaultValue; } } + set { + _hasBits0 |= 1; + dummy_ = value; + } + } + /// Gets whether the "dummy" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDummy { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "dummy" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDummy() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestRequiredForeign); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestRequiredForeign other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(OptionalMessage, other.OptionalMessage)) return false; + if(!repeatedMessage_.Equals(other.repeatedMessage_)) return false; + if (Dummy != other.Dummy) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (optionalMessage_ != null) hash ^= OptionalMessage.GetHashCode(); + hash ^= repeatedMessage_.GetHashCode(); + if (HasDummy) hash ^= Dummy.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (optionalMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(OptionalMessage); + } + repeatedMessage_.WriteTo(output, _repeated_repeatedMessage_codec); + if (HasDummy) { + output.WriteRawTag(24); + output.WriteInt32(Dummy); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (optionalMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(OptionalMessage); + } + repeatedMessage_.WriteTo(ref output, _repeated_repeatedMessage_codec); + if (HasDummy) { + output.WriteRawTag(24); + output.WriteInt32(Dummy); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (optionalMessage_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(OptionalMessage); + } + size += repeatedMessage_.CalculateSize(_repeated_repeatedMessage_codec); + if (HasDummy) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Dummy); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestRequiredForeign other) { + if (other == null) { + return; + } + if (other.optionalMessage_ != null) { + if (optionalMessage_ == null) { + OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired(); + } + OptionalMessage.MergeFrom(other.OptionalMessage); + } + repeatedMessage_.Add(other.repeatedMessage_); + if (other.HasDummy) { + Dummy = other.Dummy; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (optionalMessage_ == null) { + OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired(); + } + input.ReadMessage(OptionalMessage); + break; + } + case 18: { + repeatedMessage_.AddEntriesFrom(input, _repeated_repeatedMessage_codec); + break; + } + case 24: { + Dummy = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (optionalMessage_ == null) { + OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired(); + } + input.ReadMessage(OptionalMessage); + break; + } + case 18: { + repeatedMessage_.AddEntriesFrom(ref input, _repeated_repeatedMessage_codec); + break; + } + case 24: { + Dummy = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestRequiredMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRequiredMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[14]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequiredMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequiredMessage(TestRequiredMessage other) : this() { + optionalMessage_ = other.optionalMessage_ != null ? other.optionalMessage_.Clone() : null; + repeatedMessage_ = other.repeatedMessage_.Clone(); + requiredMessage_ = other.requiredMessage_ != null ? other.requiredMessage_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequiredMessage Clone() { + return new TestRequiredMessage(this); + } + + /// Field number for the "optional_message" field. + public const int OptionalMessageFieldNumber = 1; + private global::Google.Protobuf.TestProtos.Proto2.TestRequired optionalMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestRequired OptionalMessage { + get { return optionalMessage_; } + set { + optionalMessage_ = value; + } + } + + /// Field number for the "repeated_message" field. + public const int RepeatedMessageFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_repeatedMessage_codec + = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.Proto2.TestRequired.Parser); + private readonly pbc::RepeatedField repeatedMessage_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedMessage { + get { return repeatedMessage_; } + } + + /// Field number for the "required_message" field. + public const int RequiredMessageFieldNumber = 3; + private global::Google.Protobuf.TestProtos.Proto2.TestRequired requiredMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestRequired RequiredMessage { + get { return requiredMessage_; } + set { + requiredMessage_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestRequiredMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestRequiredMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(OptionalMessage, other.OptionalMessage)) return false; + if(!repeatedMessage_.Equals(other.repeatedMessage_)) return false; + if (!object.Equals(RequiredMessage, other.RequiredMessage)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (optionalMessage_ != null) hash ^= OptionalMessage.GetHashCode(); + hash ^= repeatedMessage_.GetHashCode(); + if (requiredMessage_ != null) hash ^= RequiredMessage.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (optionalMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(OptionalMessage); + } + repeatedMessage_.WriteTo(output, _repeated_repeatedMessage_codec); + if (requiredMessage_ != null) { + output.WriteRawTag(26); + output.WriteMessage(RequiredMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (optionalMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(OptionalMessage); + } + repeatedMessage_.WriteTo(ref output, _repeated_repeatedMessage_codec); + if (requiredMessage_ != null) { + output.WriteRawTag(26); + output.WriteMessage(RequiredMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (optionalMessage_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(OptionalMessage); + } + size += repeatedMessage_.CalculateSize(_repeated_repeatedMessage_codec); + if (requiredMessage_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(RequiredMessage); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestRequiredMessage other) { + if (other == null) { + return; + } + if (other.optionalMessage_ != null) { + if (optionalMessage_ == null) { + OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired(); + } + OptionalMessage.MergeFrom(other.OptionalMessage); + } + repeatedMessage_.Add(other.repeatedMessage_); + if (other.requiredMessage_ != null) { + if (requiredMessage_ == null) { + RequiredMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired(); + } + RequiredMessage.MergeFrom(other.RequiredMessage); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (optionalMessage_ == null) { + OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired(); + } + input.ReadMessage(OptionalMessage); + break; + } + case 18: { + repeatedMessage_.AddEntriesFrom(input, _repeated_repeatedMessage_codec); + break; + } + case 26: { + if (requiredMessage_ == null) { + RequiredMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired(); + } + input.ReadMessage(RequiredMessage); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (optionalMessage_ == null) { + OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired(); + } + input.ReadMessage(OptionalMessage); + break; + } + case 18: { + repeatedMessage_.AddEntriesFrom(ref input, _repeated_repeatedMessage_codec); + break; + } + case 26: { + if (requiredMessage_ == null) { + RequiredMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequired(); + } + input.ReadMessage(RequiredMessage); + break; + } + } + } + } + #endif + + } + + /// + /// Test that we can use NestedMessage from outside TestAllTypes. + /// + public sealed partial class TestForeignNested : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestForeignNested()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[15]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestForeignNested() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestForeignNested(TestForeignNested other) : this() { + foreignNested_ = other.foreignNested_ != null ? other.foreignNested_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestForeignNested Clone() { + return new TestForeignNested(this); + } + + /// Field number for the "foreign_nested" field. + public const int ForeignNestedFieldNumber = 1; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage foreignNested_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage ForeignNested { + get { return foreignNested_; } + set { + foreignNested_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestForeignNested); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestForeignNested other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(ForeignNested, other.ForeignNested)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (foreignNested_ != null) hash ^= ForeignNested.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (foreignNested_ != null) { + output.WriteRawTag(10); + output.WriteMessage(ForeignNested); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (foreignNested_ != null) { + output.WriteRawTag(10); + output.WriteMessage(ForeignNested); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (foreignNested_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ForeignNested); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestForeignNested other) { + if (other == null) { + return; + } + if (other.foreignNested_ != null) { + if (foreignNested_ == null) { + ForeignNested = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage(); + } + ForeignNested.MergeFrom(other.ForeignNested); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (foreignNested_ == null) { + ForeignNested = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage(); + } + input.ReadMessage(ForeignNested); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (foreignNested_ == null) { + ForeignNested = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Types.NestedMessage(); + } + input.ReadMessage(ForeignNested); + break; + } + } + } + } + #endif + + } + + /// + /// TestEmptyMessage is used to test unknown field support. + /// + public sealed partial class TestEmptyMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestEmptyMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[16]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEmptyMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEmptyMessage(TestEmptyMessage other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEmptyMessage Clone() { + return new TestEmptyMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestEmptyMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestEmptyMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestEmptyMessage other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + /// + /// Like above, but declare all field numbers as potential extensions. No + /// actual extensions should ever be defined for this type. + /// + public sealed partial class TestEmptyMessageWithExtensions : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestEmptyMessageWithExtensions()); + private pb::UnknownFieldSet _unknownFields; + private pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[17]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEmptyMessageWithExtensions() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEmptyMessageWithExtensions(TestEmptyMessageWithExtensions other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEmptyMessageWithExtensions Clone() { + return new TestEmptyMessageWithExtensions(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestEmptyMessageWithExtensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestEmptyMessageWithExtensions other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestEmptyMessageWithExtensions other) { + if (other == null) { + return; + } + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + + } + + public sealed partial class TestMultipleExtensionRanges : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMultipleExtensionRanges()); + private pb::UnknownFieldSet _unknownFields; + private pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[18]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMultipleExtensionRanges() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMultipleExtensionRanges(TestMultipleExtensionRanges other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMultipleExtensionRanges Clone() { + return new TestMultipleExtensionRanges(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestMultipleExtensionRanges); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestMultipleExtensionRanges other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestMultipleExtensionRanges other) { + if (other == null) { + return; + } + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + + } + + /// + /// Test that really large tag numbers don't break anything. + /// + public sealed partial class TestReallyLargeTagNumber : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestReallyLargeTagNumber()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[19]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestReallyLargeTagNumber() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestReallyLargeTagNumber(TestReallyLargeTagNumber other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + bb_ = other.bb_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestReallyLargeTagNumber Clone() { + return new TestReallyLargeTagNumber(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private readonly static int ADefaultValue = 0; + + private int a_; + /// + /// The largest possible tag number is 2^28 - 1, since the wire format uses + /// three bits to communicate wire type. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + /// Field number for the "bb" field. + public const int BbFieldNumber = 268435455; + private readonly static int BbDefaultValue = 0; + + private int bb_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Bb { + get { if ((_hasBits0 & 2) != 0) { return bb_; } else { return BbDefaultValue; } } + set { + _hasBits0 |= 2; + bb_ = value; + } + } + /// Gets whether the "bb" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBb { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "bb" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBb() { + _hasBits0 &= ~2; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestReallyLargeTagNumber); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestReallyLargeTagNumber other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + if (Bb != other.Bb) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (HasBb) hash ^= Bb.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (HasBb) { + output.WriteRawTag(248, 255, 255, 255, 7); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (HasBb) { + output.WriteRawTag(248, 255, 255, 255, 7); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (HasBb) { + size += 5 + pb::CodedOutputStream.ComputeInt32Size(Bb); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestReallyLargeTagNumber other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + if (other.HasBb) { + Bb = other.Bb; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + A = input.ReadInt32(); + break; + } + case 2147483640: { + Bb = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + A = input.ReadInt32(); + break; + } + case 2147483640: { + Bb = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestRecursiveMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRecursiveMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[20]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRecursiveMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRecursiveMessage(TestRecursiveMessage other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_ != null ? other.a_.Clone() : null; + i_ = other.i_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRecursiveMessage Clone() { + return new TestRecursiveMessage(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private global::Google.Protobuf.TestProtos.Proto2.TestRecursiveMessage a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestRecursiveMessage A { + get { return a_; } + set { + a_ = value; + } + } + + /// Field number for the "i" field. + public const int IFieldNumber = 2; + private readonly static int IDefaultValue = 0; + + private int i_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int I { + get { if ((_hasBits0 & 1) != 0) { return i_; } else { return IDefaultValue; } } + set { + _hasBits0 |= 1; + i_ = value; + } + } + /// Gets whether the "i" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasI { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "i" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearI() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestRecursiveMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestRecursiveMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(A, other.A)) return false; + if (I != other.I) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (a_ != null) hash ^= A.GetHashCode(); + if (HasI) hash ^= I.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (a_ != null) { + output.WriteRawTag(10); + output.WriteMessage(A); + } + if (HasI) { + output.WriteRawTag(16); + output.WriteInt32(I); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (a_ != null) { + output.WriteRawTag(10); + output.WriteMessage(A); + } + if (HasI) { + output.WriteRawTag(16); + output.WriteInt32(I); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (a_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(A); + } + if (HasI) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(I); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestRecursiveMessage other) { + if (other == null) { + return; + } + if (other.a_ != null) { + if (a_ == null) { + A = new global::Google.Protobuf.TestProtos.Proto2.TestRecursiveMessage(); + } + A.MergeFrom(other.A); + } + if (other.HasI) { + I = other.I; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (a_ == null) { + A = new global::Google.Protobuf.TestProtos.Proto2.TestRecursiveMessage(); + } + input.ReadMessage(A); + break; + } + case 16: { + I = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (a_ == null) { + A = new global::Google.Protobuf.TestProtos.Proto2.TestRecursiveMessage(); + } + input.ReadMessage(A); + break; + } + case 16: { + I = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// Test that mutual recursion works. + /// + public sealed partial class TestMutualRecursionA : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMutualRecursionA()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[21]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMutualRecursionA() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMutualRecursionA(TestMutualRecursionA other) : this() { + bb_ = other.bb_ != null ? other.bb_.Clone() : null; + subGroup_ = other.HasSubGroup ? other.subGroup_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMutualRecursionA Clone() { + return new TestMutualRecursionA(this); + } + + /// Field number for the "bb" field. + public const int BbFieldNumber = 1; + private global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB bb_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB Bb { + get { return bb_; } + set { + bb_ = value; + } + } + + /// Field number for the "subgroup" field. + public const int SubGroupFieldNumber = 2; + private global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubGroup subGroup_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubGroup SubGroup { + get { return subGroup_; } + set { + subGroup_ = value; + } + } + /// Gets whether the subgroup field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSubGroup { + get { return subGroup_ != null; } + } + /// Clears the value of the subgroup field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSubGroup() { + subGroup_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestMutualRecursionA); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestMutualRecursionA other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Bb, other.Bb)) return false; + if (!object.Equals(SubGroup, other.SubGroup)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (bb_ != null) hash ^= Bb.GetHashCode(); + if (HasSubGroup) hash ^= SubGroup.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (bb_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Bb); + } + if (HasSubGroup) { + output.WriteRawTag(19); + output.WriteGroup(SubGroup); + output.WriteRawTag(20); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (bb_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Bb); + } + if (HasSubGroup) { + output.WriteRawTag(19); + output.WriteGroup(SubGroup); + output.WriteRawTag(20); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (bb_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Bb); + } + if (HasSubGroup) { + size += 2 + pb::CodedOutputStream.ComputeGroupSize(SubGroup); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestMutualRecursionA other) { + if (other == null) { + return; + } + if (other.bb_ != null) { + if (bb_ == null) { + Bb = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB(); + } + Bb.MergeFrom(other.Bb); + } + if (other.HasSubGroup) { + if (!HasSubGroup) { + SubGroup = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubGroup(); + } + SubGroup.MergeFrom(other.SubGroup); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (bb_ == null) { + Bb = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB(); + } + input.ReadMessage(Bb); + break; + } + case 19: { + if (!HasSubGroup) { + SubGroup = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubGroup(); + } + input.ReadGroup(SubGroup); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (bb_ == null) { + Bb = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB(); + } + input.ReadMessage(Bb); + break; + } + case 19: { + if (!HasSubGroup) { + SubGroup = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubGroup(); + } + input.ReadGroup(SubGroup); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestMutualRecursionA message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class SubMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SubMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubMessage(SubMessage other) : this() { + b_ = other.b_ != null ? other.b_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubMessage Clone() { + return new SubMessage(this); + } + + /// Field number for the "b" field. + public const int BFieldNumber = 1; + private global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB b_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB B { + get { return b_; } + set { + b_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SubMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SubMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(B, other.B)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (b_ != null) hash ^= B.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (b_ != null) { + output.WriteRawTag(10); + output.WriteMessage(B); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (b_ != null) { + output.WriteRawTag(10); + output.WriteMessage(B); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (b_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(B); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SubMessage other) { + if (other == null) { + return; + } + if (other.b_ != null) { + if (b_ == null) { + B = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB(); + } + B.MergeFrom(other.B); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (b_ == null) { + B = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB(); + } + input.ReadMessage(B); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (b_ == null) { + B = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionB(); + } + input.ReadMessage(B); + break; + } + } + } + } + #endif + + } + + public sealed partial class SubGroup : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SubGroup()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Descriptor.NestedTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubGroup() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubGroup(SubGroup other) : this() { + subMessage_ = other.subMessage_ != null ? other.subMessage_.Clone() : null; + notInThisScc_ = other.notInThisScc_ != null ? other.notInThisScc_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubGroup Clone() { + return new SubGroup(this); + } + + /// Field number for the "sub_message" field. + public const int SubMessageFieldNumber = 3; + private global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubMessage subMessage_; + /// + /// Needed because of bug in javatest + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubMessage SubMessage { + get { return subMessage_; } + set { + subMessage_ = value; + } + } + + /// Field number for the "not_in_this_scc" field. + public const int NotInThisSccFieldNumber = 4; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes notInThisScc_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes NotInThisScc { + get { return notInThisScc_; } + set { + notInThisScc_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SubGroup); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SubGroup other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(SubMessage, other.SubMessage)) return false; + if (!object.Equals(NotInThisScc, other.NotInThisScc)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (subMessage_ != null) hash ^= SubMessage.GetHashCode(); + if (notInThisScc_ != null) hash ^= NotInThisScc.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (subMessage_ != null) { + output.WriteRawTag(26); + output.WriteMessage(SubMessage); + } + if (notInThisScc_ != null) { + output.WriteRawTag(34); + output.WriteMessage(NotInThisScc); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (subMessage_ != null) { + output.WriteRawTag(26); + output.WriteMessage(SubMessage); + } + if (notInThisScc_ != null) { + output.WriteRawTag(34); + output.WriteMessage(NotInThisScc); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (subMessage_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(SubMessage); + } + if (notInThisScc_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(NotInThisScc); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SubGroup other) { + if (other == null) { + return; + } + if (other.subMessage_ != null) { + if (subMessage_ == null) { + SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubMessage(); + } + SubMessage.MergeFrom(other.SubMessage); + } + if (other.notInThisScc_ != null) { + if (notInThisScc_ == null) { + NotInThisScc = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + NotInThisScc.MergeFrom(other.NotInThisScc); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 20: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 26: { + if (subMessage_ == null) { + SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubMessage(); + } + input.ReadMessage(SubMessage); + break; + } + case 34: { + if (notInThisScc_ == null) { + NotInThisScc = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(NotInThisScc); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 20: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 26: { + if (subMessage_ == null) { + SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA.Types.SubMessage(); + } + input.ReadMessage(SubMessage); + break; + } + case 34: { + if (notInThisScc_ == null) { + NotInThisScc = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(NotInThisScc); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class TestMutualRecursionB : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMutualRecursionB()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[22]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMutualRecursionB() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMutualRecursionB(TestMutualRecursionB other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_ != null ? other.a_.Clone() : null; + optionalInt32_ = other.optionalInt32_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMutualRecursionB Clone() { + return new TestMutualRecursionB(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA A { + get { return a_; } + set { + a_ = value; + } + } + + /// Field number for the "optional_int32" field. + public const int OptionalInt32FieldNumber = 2; + private readonly static int OptionalInt32DefaultValue = 0; + + private int optionalInt32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalInt32 { + get { if ((_hasBits0 & 1) != 0) { return optionalInt32_; } else { return OptionalInt32DefaultValue; } } + set { + _hasBits0 |= 1; + optionalInt32_ = value; + } + } + /// Gets whether the "optional_int32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalInt32 { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "optional_int32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalInt32() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestMutualRecursionB); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestMutualRecursionB other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(A, other.A)) return false; + if (OptionalInt32 != other.OptionalInt32) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (a_ != null) hash ^= A.GetHashCode(); + if (HasOptionalInt32) hash ^= OptionalInt32.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (a_ != null) { + output.WriteRawTag(10); + output.WriteMessage(A); + } + if (HasOptionalInt32) { + output.WriteRawTag(16); + output.WriteInt32(OptionalInt32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (a_ != null) { + output.WriteRawTag(10); + output.WriteMessage(A); + } + if (HasOptionalInt32) { + output.WriteRawTag(16); + output.WriteInt32(OptionalInt32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (a_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(A); + } + if (HasOptionalInt32) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestMutualRecursionB other) { + if (other == null) { + return; + } + if (other.a_ != null) { + if (a_ == null) { + A = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA(); + } + A.MergeFrom(other.A); + } + if (other.HasOptionalInt32) { + OptionalInt32 = other.OptionalInt32; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (a_ == null) { + A = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA(); + } + input.ReadMessage(A); + break; + } + case 16: { + OptionalInt32 = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (a_ == null) { + A = new global::Google.Protobuf.TestProtos.Proto2.TestMutualRecursionA(); + } + input.ReadMessage(A); + break; + } + case 16: { + OptionalInt32 = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestIsInitialized : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestIsInitialized()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[23]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestIsInitialized() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestIsInitialized(TestIsInitialized other) : this() { + subMessage_ = other.subMessage_ != null ? other.subMessage_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestIsInitialized Clone() { + return new TestIsInitialized(this); + } + + /// Field number for the "sub_message" field. + public const int SubMessageFieldNumber = 1; + private global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage subMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage SubMessage { + get { return subMessage_; } + set { + subMessage_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestIsInitialized); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestIsInitialized other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(SubMessage, other.SubMessage)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (subMessage_ != null) hash ^= SubMessage.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (subMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(SubMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (subMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(SubMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (subMessage_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(SubMessage); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestIsInitialized other) { + if (other == null) { + return; + } + if (other.subMessage_ != null) { + if (subMessage_ == null) { + SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage(); + } + SubMessage.MergeFrom(other.SubMessage); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (subMessage_ == null) { + SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage(); + } + input.ReadMessage(SubMessage); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (subMessage_ == null) { + SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage(); + } + input.ReadMessage(SubMessage); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestIsInitialized message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class SubMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SubMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubMessage(SubMessage other) : this() { + subGroup_ = other.HasSubGroup ? other.subGroup_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubMessage Clone() { + return new SubMessage(this); + } + + /// Field number for the "subgroup" field. + public const int SubGroupFieldNumber = 1; + private global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage.Types.SubGroup subGroup_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage.Types.SubGroup SubGroup { + get { return subGroup_; } + set { + subGroup_ = value; + } + } + /// Gets whether the subgroup field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSubGroup { + get { return subGroup_ != null; } + } + /// Clears the value of the subgroup field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSubGroup() { + subGroup_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SubMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SubMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(SubGroup, other.SubGroup)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasSubGroup) hash ^= SubGroup.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasSubGroup) { + output.WriteRawTag(11); + output.WriteGroup(SubGroup); + output.WriteRawTag(12); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasSubGroup) { + output.WriteRawTag(11); + output.WriteGroup(SubGroup); + output.WriteRawTag(12); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasSubGroup) { + size += 2 + pb::CodedOutputStream.ComputeGroupSize(SubGroup); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SubMessage other) { + if (other == null) { + return; + } + if (other.HasSubGroup) { + if (!HasSubGroup) { + SubGroup = new global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage.Types.SubGroup(); + } + SubGroup.MergeFrom(other.SubGroup); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 11: { + if (!HasSubGroup) { + SubGroup = new global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage.Types.SubGroup(); + } + input.ReadGroup(SubGroup); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 11: { + if (!HasSubGroup) { + SubGroup = new global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage.Types.SubGroup(); + } + input.ReadGroup(SubGroup); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the SubMessage message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class SubGroup : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SubGroup()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestIsInitialized.Types.SubMessage.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubGroup() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubGroup(SubGroup other) : this() { + _hasBits0 = other._hasBits0; + i_ = other.i_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SubGroup Clone() { + return new SubGroup(this); + } + + /// Field number for the "i" field. + public const int IFieldNumber = 2; + private readonly static int IDefaultValue = 0; + + private int i_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int I { + get { if ((_hasBits0 & 1) != 0) { return i_; } else { return IDefaultValue; } } + set { + _hasBits0 |= 1; + i_ = value; + } + } + /// Gets whether the "i" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasI { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "i" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearI() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SubGroup); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SubGroup other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (I != other.I) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasI) hash ^= I.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasI) { + output.WriteRawTag(16); + output.WriteInt32(I); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasI) { + output.WriteRawTag(16); + output.WriteInt32(I); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasI) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(I); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SubGroup other) { + if (other == null) { + return; + } + if (other.HasI) { + I = other.I; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 12: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 16: { + I = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 12: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 16: { + I = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + } + #endregion + + } + + /// + /// Test that groups have disjoint field numbers from their siblings and + /// parents. This is NOT possible in proto1; only google.protobuf. When attempting + /// to compile with proto1, this will emit an error; so we only include it + /// in protobuf_unittest_proto. + /// + public sealed partial class TestDupFieldNumber : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestDupFieldNumber()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[24]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDupFieldNumber() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDupFieldNumber(TestDupFieldNumber other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + foo_ = other.HasFoo ? other.foo_.Clone() : null; + bar_ = other.HasBar ? other.bar_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDupFieldNumber Clone() { + return new TestDupFieldNumber(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private readonly static int ADefaultValue = 0; + + private int a_; + /// + /// NO_PROTO1 + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + /// Field number for the "foo" field. + public const int FooFieldNumber = 2; + private global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Foo foo_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Foo Foo { + get { return foo_; } + set { + foo_ = value; + } + } + /// Gets whether the foo field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFoo { + get { return foo_ != null; } + } + /// Clears the value of the foo field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFoo() { + foo_ = null; + } + + /// Field number for the "bar" field. + public const int BarFieldNumber = 3; + private global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Bar bar_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Bar Bar { + get { return bar_; } + set { + bar_ = value; + } + } + /// Gets whether the bar field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBar { + get { return bar_ != null; } + } + /// Clears the value of the bar field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBar() { + bar_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestDupFieldNumber); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestDupFieldNumber other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + if (!object.Equals(Foo, other.Foo)) return false; + if (!object.Equals(Bar, other.Bar)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (HasFoo) hash ^= Foo.GetHashCode(); + if (HasBar) hash ^= Bar.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (HasFoo) { + output.WriteRawTag(19); + output.WriteGroup(Foo); + output.WriteRawTag(20); + } + if (HasBar) { + output.WriteRawTag(27); + output.WriteGroup(Bar); + output.WriteRawTag(28); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (HasFoo) { + output.WriteRawTag(19); + output.WriteGroup(Foo); + output.WriteRawTag(20); + } + if (HasBar) { + output.WriteRawTag(27); + output.WriteGroup(Bar); + output.WriteRawTag(28); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (HasFoo) { + size += 2 + pb::CodedOutputStream.ComputeGroupSize(Foo); + } + if (HasBar) { + size += 2 + pb::CodedOutputStream.ComputeGroupSize(Bar); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestDupFieldNumber other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + if (other.HasFoo) { + if (!HasFoo) { + Foo = new global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Foo(); + } + Foo.MergeFrom(other.Foo); + } + if (other.HasBar) { + if (!HasBar) { + Bar = new global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Bar(); + } + Bar.MergeFrom(other.Bar); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + A = input.ReadInt32(); + break; + } + case 19: { + if (!HasFoo) { + Foo = new global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Foo(); + } + input.ReadGroup(Foo); + break; + } + case 27: { + if (!HasBar) { + Bar = new global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Bar(); + } + input.ReadGroup(Bar); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + A = input.ReadInt32(); + break; + } + case 19: { + if (!HasFoo) { + Foo = new global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Foo(); + } + input.ReadGroup(Foo); + break; + } + case 27: { + if (!HasBar) { + Bar = new global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Types.Bar(); + } + input.ReadGroup(Bar); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestDupFieldNumber message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class Foo : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Foo()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Foo() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Foo(Foo other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Foo Clone() { + return new Foo(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private readonly static int ADefaultValue = 0; + + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Foo); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Foo other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Foo other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 20: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + A = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 20: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + A = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class Bar : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Bar()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestDupFieldNumber.Descriptor.NestedTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Bar() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Bar(Bar other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Bar Clone() { + return new Bar(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private readonly static int ADefaultValue = 0; + + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Bar); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Bar other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Bar other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 28: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + A = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 28: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + A = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + /// + /// Additional messages for testing lazy fields. + /// + public sealed partial class TestEagerMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestEagerMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[25]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEagerMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEagerMessage(TestEagerMessage other) : this() { + subMessage_ = other.subMessage_ != null ? other.subMessage_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEagerMessage Clone() { + return new TestEagerMessage(this); + } + + /// Field number for the "sub_message" field. + public const int SubMessageFieldNumber = 1; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes subMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes SubMessage { + get { return subMessage_; } + set { + subMessage_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestEagerMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestEagerMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(SubMessage, other.SubMessage)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (subMessage_ != null) hash ^= SubMessage.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (subMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(SubMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (subMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(SubMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (subMessage_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(SubMessage); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestEagerMessage other) { + if (other == null) { + return; + } + if (other.subMessage_ != null) { + if (subMessage_ == null) { + SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + SubMessage.MergeFrom(other.SubMessage); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (subMessage_ == null) { + SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(SubMessage); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (subMessage_ == null) { + SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(SubMessage); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestLazyMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestLazyMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[26]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestLazyMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestLazyMessage(TestLazyMessage other) : this() { + subMessage_ = other.subMessage_ != null ? other.subMessage_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestLazyMessage Clone() { + return new TestLazyMessage(this); + } + + /// Field number for the "sub_message" field. + public const int SubMessageFieldNumber = 1; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes subMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes SubMessage { + get { return subMessage_; } + set { + subMessage_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestLazyMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestLazyMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(SubMessage, other.SubMessage)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (subMessage_ != null) hash ^= SubMessage.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (subMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(SubMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (subMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(SubMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (subMessage_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(SubMessage); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestLazyMessage other) { + if (other == null) { + return; + } + if (other.subMessage_ != null) { + if (subMessage_ == null) { + SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + SubMessage.MergeFrom(other.SubMessage); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (subMessage_ == null) { + SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(SubMessage); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (subMessage_ == null) { + SubMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(SubMessage); + break; + } + } + } + } + #endif + + } + + /// + /// Needed for a Python test. + /// + public sealed partial class TestNestedMessageHasBits : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestNestedMessageHasBits()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[27]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestNestedMessageHasBits() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestNestedMessageHasBits(TestNestedMessageHasBits other) : this() { + optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestNestedMessageHasBits Clone() { + return new TestNestedMessageHasBits(this); + } + + /// Field number for the "optional_nested_message" field. + public const int OptionalNestedMessageFieldNumber = 1; + private global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Types.NestedMessage optionalNestedMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Types.NestedMessage OptionalNestedMessage { + get { return optionalNestedMessage_; } + set { + optionalNestedMessage_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestNestedMessageHasBits); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestNestedMessageHasBits other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (optionalNestedMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(OptionalNestedMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (optionalNestedMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(OptionalNestedMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (optionalNestedMessage_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestNestedMessageHasBits other) { + if (other == null) { + return; + } + if (other.optionalNestedMessage_ != null) { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Types.NestedMessage(); + } + OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestNestedMessageHasBits message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class NestedMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestNestedMessageHasBits.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + nestedmessageRepeatedInt32_ = other.nestedmessageRepeatedInt32_.Clone(); + nestedmessageRepeatedForeignmessage_ = other.nestedmessageRepeatedForeignmessage_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "nestedmessage_repeated_int32" field. + public const int NestedmessageRepeatedInt32FieldNumber = 1; + private static readonly pb::FieldCodec _repeated_nestedmessageRepeatedInt32_codec + = pb::FieldCodec.ForInt32(8); + private readonly pbc::RepeatedField nestedmessageRepeatedInt32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField NestedmessageRepeatedInt32 { + get { return nestedmessageRepeatedInt32_; } + } + + /// Field number for the "nestedmessage_repeated_foreignmessage" field. + public const int NestedmessageRepeatedForeignmessageFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_nestedmessageRepeatedForeignmessage_codec + = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.Proto2.ForeignMessage.Parser); + private readonly pbc::RepeatedField nestedmessageRepeatedForeignmessage_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField NestedmessageRepeatedForeignmessage { + get { return nestedmessageRepeatedForeignmessage_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!nestedmessageRepeatedInt32_.Equals(other.nestedmessageRepeatedInt32_)) return false; + if(!nestedmessageRepeatedForeignmessage_.Equals(other.nestedmessageRepeatedForeignmessage_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= nestedmessageRepeatedInt32_.GetHashCode(); + hash ^= nestedmessageRepeatedForeignmessage_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + nestedmessageRepeatedInt32_.WriteTo(output, _repeated_nestedmessageRepeatedInt32_codec); + nestedmessageRepeatedForeignmessage_.WriteTo(output, _repeated_nestedmessageRepeatedForeignmessage_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + nestedmessageRepeatedInt32_.WriteTo(ref output, _repeated_nestedmessageRepeatedInt32_codec); + nestedmessageRepeatedForeignmessage_.WriteTo(ref output, _repeated_nestedmessageRepeatedForeignmessage_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += nestedmessageRepeatedInt32_.CalculateSize(_repeated_nestedmessageRepeatedInt32_codec); + size += nestedmessageRepeatedForeignmessage_.CalculateSize(_repeated_nestedmessageRepeatedForeignmessage_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + nestedmessageRepeatedInt32_.Add(other.nestedmessageRepeatedInt32_); + nestedmessageRepeatedForeignmessage_.Add(other.nestedmessageRepeatedForeignmessage_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: + case 8: { + nestedmessageRepeatedInt32_.AddEntriesFrom(input, _repeated_nestedmessageRepeatedInt32_codec); + break; + } + case 18: { + nestedmessageRepeatedForeignmessage_.AddEntriesFrom(input, _repeated_nestedmessageRepeatedForeignmessage_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: + case 8: { + nestedmessageRepeatedInt32_.AddEntriesFrom(ref input, _repeated_nestedmessageRepeatedInt32_codec); + break; + } + case 18: { + nestedmessageRepeatedForeignmessage_.AddEntriesFrom(ref input, _repeated_nestedmessageRepeatedForeignmessage_codec); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + /// + /// Test message with CamelCase field names. This violates Protocol Buffer + /// standard style. + /// + public sealed partial class TestCamelCaseFieldNames : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestCamelCaseFieldNames()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[28]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestCamelCaseFieldNames() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestCamelCaseFieldNames(TestCamelCaseFieldNames other) : this() { + _hasBits0 = other._hasBits0; + primitiveField_ = other.primitiveField_; + stringField_ = other.stringField_; + enumField_ = other.enumField_; + messageField_ = other.messageField_ != null ? other.messageField_.Clone() : null; + stringPieceField_ = other.stringPieceField_; + cordField_ = other.cordField_; + repeatedPrimitiveField_ = other.repeatedPrimitiveField_.Clone(); + repeatedStringField_ = other.repeatedStringField_.Clone(); + repeatedEnumField_ = other.repeatedEnumField_.Clone(); + repeatedMessageField_ = other.repeatedMessageField_.Clone(); + repeatedStringPieceField_ = other.repeatedStringPieceField_.Clone(); + repeatedCordField_ = other.repeatedCordField_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestCamelCaseFieldNames Clone() { + return new TestCamelCaseFieldNames(this); + } + + /// Field number for the "PrimitiveField" field. + public const int PrimitiveFieldFieldNumber = 1; + private readonly static int PrimitiveFieldDefaultValue = 0; + + private int primitiveField_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int PrimitiveField { + get { if ((_hasBits0 & 1) != 0) { return primitiveField_; } else { return PrimitiveFieldDefaultValue; } } + set { + _hasBits0 |= 1; + primitiveField_ = value; + } + } + /// Gets whether the "PrimitiveField" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPrimitiveField { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "PrimitiveField" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPrimitiveField() { + _hasBits0 &= ~1; + } + + /// Field number for the "StringField" field. + public const int StringFieldFieldNumber = 2; + private readonly static string StringFieldDefaultValue = ""; + + private string stringField_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string StringField { + get { return stringField_ ?? StringFieldDefaultValue; } + set { + stringField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "StringField" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStringField { + get { return stringField_ != null; } + } + /// Clears the value of the "StringField" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStringField() { + stringField_ = null; + } + + /// Field number for the "EnumField" field. + public const int EnumFieldFieldNumber = 3; + private readonly static global::Google.Protobuf.TestProtos.Proto2.ForeignEnum EnumFieldDefaultValue = global::Google.Protobuf.TestProtos.Proto2.ForeignEnum.ForeignFoo; + + private global::Google.Protobuf.TestProtos.Proto2.ForeignEnum enumField_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.ForeignEnum EnumField { + get { if ((_hasBits0 & 2) != 0) { return enumField_; } else { return EnumFieldDefaultValue; } } + set { + _hasBits0 |= 2; + enumField_ = value; + } + } + /// Gets whether the "EnumField" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasEnumField { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "EnumField" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearEnumField() { + _hasBits0 &= ~2; + } + + /// Field number for the "MessageField" field. + public const int MessageFieldFieldNumber = 4; + private global::Google.Protobuf.TestProtos.Proto2.ForeignMessage messageField_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.ForeignMessage MessageField { + get { return messageField_; } + set { + messageField_ = value; + } + } + + /// Field number for the "StringPieceField" field. + public const int StringPieceFieldFieldNumber = 5; + private readonly static string StringPieceFieldDefaultValue = ""; + + private string stringPieceField_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string StringPieceField { + get { return stringPieceField_ ?? StringPieceFieldDefaultValue; } + set { + stringPieceField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "StringPieceField" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStringPieceField { + get { return stringPieceField_ != null; } + } + /// Clears the value of the "StringPieceField" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStringPieceField() { + stringPieceField_ = null; + } + + /// Field number for the "CordField" field. + public const int CordFieldFieldNumber = 6; + private readonly static string CordFieldDefaultValue = ""; + + private string cordField_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string CordField { + get { return cordField_ ?? CordFieldDefaultValue; } + set { + cordField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "CordField" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCordField { + get { return cordField_ != null; } + } + /// Clears the value of the "CordField" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCordField() { + cordField_ = null; + } + + /// Field number for the "RepeatedPrimitiveField" field. + public const int RepeatedPrimitiveFieldFieldNumber = 7; + private static readonly pb::FieldCodec _repeated_repeatedPrimitiveField_codec + = pb::FieldCodec.ForInt32(56); + private readonly pbc::RepeatedField repeatedPrimitiveField_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedPrimitiveField { + get { return repeatedPrimitiveField_; } + } + + /// Field number for the "RepeatedStringField" field. + public const int RepeatedStringFieldFieldNumber = 8; + private static readonly pb::FieldCodec _repeated_repeatedStringField_codec + = pb::FieldCodec.ForString(66); + private readonly pbc::RepeatedField repeatedStringField_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedStringField { + get { return repeatedStringField_; } + } + + /// Field number for the "RepeatedEnumField" field. + public const int RepeatedEnumFieldFieldNumber = 9; + private static readonly pb::FieldCodec _repeated_repeatedEnumField_codec + = pb::FieldCodec.ForEnum(72, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) x); + private readonly pbc::RepeatedField repeatedEnumField_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedEnumField { + get { return repeatedEnumField_; } + } + + /// Field number for the "RepeatedMessageField" field. + public const int RepeatedMessageFieldFieldNumber = 10; + private static readonly pb::FieldCodec _repeated_repeatedMessageField_codec + = pb::FieldCodec.ForMessage(82, global::Google.Protobuf.TestProtos.Proto2.ForeignMessage.Parser); + private readonly pbc::RepeatedField repeatedMessageField_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedMessageField { + get { return repeatedMessageField_; } + } + + /// Field number for the "RepeatedStringPieceField" field. + public const int RepeatedStringPieceFieldFieldNumber = 11; + private static readonly pb::FieldCodec _repeated_repeatedStringPieceField_codec + = pb::FieldCodec.ForString(90); + private readonly pbc::RepeatedField repeatedStringPieceField_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedStringPieceField { + get { return repeatedStringPieceField_; } + } + + /// Field number for the "RepeatedCordField" field. + public const int RepeatedCordFieldFieldNumber = 12; + private static readonly pb::FieldCodec _repeated_repeatedCordField_codec + = pb::FieldCodec.ForString(98); + private readonly pbc::RepeatedField repeatedCordField_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedCordField { + get { return repeatedCordField_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestCamelCaseFieldNames); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestCamelCaseFieldNames other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (PrimitiveField != other.PrimitiveField) return false; + if (StringField != other.StringField) return false; + if (EnumField != other.EnumField) return false; + if (!object.Equals(MessageField, other.MessageField)) return false; + if (StringPieceField != other.StringPieceField) return false; + if (CordField != other.CordField) return false; + if(!repeatedPrimitiveField_.Equals(other.repeatedPrimitiveField_)) return false; + if(!repeatedStringField_.Equals(other.repeatedStringField_)) return false; + if(!repeatedEnumField_.Equals(other.repeatedEnumField_)) return false; + if(!repeatedMessageField_.Equals(other.repeatedMessageField_)) return false; + if(!repeatedStringPieceField_.Equals(other.repeatedStringPieceField_)) return false; + if(!repeatedCordField_.Equals(other.repeatedCordField_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasPrimitiveField) hash ^= PrimitiveField.GetHashCode(); + if (HasStringField) hash ^= StringField.GetHashCode(); + if (HasEnumField) hash ^= EnumField.GetHashCode(); + if (messageField_ != null) hash ^= MessageField.GetHashCode(); + if (HasStringPieceField) hash ^= StringPieceField.GetHashCode(); + if (HasCordField) hash ^= CordField.GetHashCode(); + hash ^= repeatedPrimitiveField_.GetHashCode(); + hash ^= repeatedStringField_.GetHashCode(); + hash ^= repeatedEnumField_.GetHashCode(); + hash ^= repeatedMessageField_.GetHashCode(); + hash ^= repeatedStringPieceField_.GetHashCode(); + hash ^= repeatedCordField_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasPrimitiveField) { + output.WriteRawTag(8); + output.WriteInt32(PrimitiveField); + } + if (HasStringField) { + output.WriteRawTag(18); + output.WriteString(StringField); + } + if (HasEnumField) { + output.WriteRawTag(24); + output.WriteEnum((int) EnumField); + } + if (messageField_ != null) { + output.WriteRawTag(34); + output.WriteMessage(MessageField); + } + if (HasStringPieceField) { + output.WriteRawTag(42); + output.WriteString(StringPieceField); + } + if (HasCordField) { + output.WriteRawTag(50); + output.WriteString(CordField); + } + repeatedPrimitiveField_.WriteTo(output, _repeated_repeatedPrimitiveField_codec); + repeatedStringField_.WriteTo(output, _repeated_repeatedStringField_codec); + repeatedEnumField_.WriteTo(output, _repeated_repeatedEnumField_codec); + repeatedMessageField_.WriteTo(output, _repeated_repeatedMessageField_codec); + repeatedStringPieceField_.WriteTo(output, _repeated_repeatedStringPieceField_codec); + repeatedCordField_.WriteTo(output, _repeated_repeatedCordField_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasPrimitiveField) { + output.WriteRawTag(8); + output.WriteInt32(PrimitiveField); + } + if (HasStringField) { + output.WriteRawTag(18); + output.WriteString(StringField); + } + if (HasEnumField) { + output.WriteRawTag(24); + output.WriteEnum((int) EnumField); + } + if (messageField_ != null) { + output.WriteRawTag(34); + output.WriteMessage(MessageField); + } + if (HasStringPieceField) { + output.WriteRawTag(42); + output.WriteString(StringPieceField); + } + if (HasCordField) { + output.WriteRawTag(50); + output.WriteString(CordField); + } + repeatedPrimitiveField_.WriteTo(ref output, _repeated_repeatedPrimitiveField_codec); + repeatedStringField_.WriteTo(ref output, _repeated_repeatedStringField_codec); + repeatedEnumField_.WriteTo(ref output, _repeated_repeatedEnumField_codec); + repeatedMessageField_.WriteTo(ref output, _repeated_repeatedMessageField_codec); + repeatedStringPieceField_.WriteTo(ref output, _repeated_repeatedStringPieceField_codec); + repeatedCordField_.WriteTo(ref output, _repeated_repeatedCordField_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasPrimitiveField) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(PrimitiveField); + } + if (HasStringField) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(StringField); + } + if (HasEnumField) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumField); + } + if (messageField_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageField); + } + if (HasStringPieceField) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(StringPieceField); + } + if (HasCordField) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(CordField); + } + size += repeatedPrimitiveField_.CalculateSize(_repeated_repeatedPrimitiveField_codec); + size += repeatedStringField_.CalculateSize(_repeated_repeatedStringField_codec); + size += repeatedEnumField_.CalculateSize(_repeated_repeatedEnumField_codec); + size += repeatedMessageField_.CalculateSize(_repeated_repeatedMessageField_codec); + size += repeatedStringPieceField_.CalculateSize(_repeated_repeatedStringPieceField_codec); + size += repeatedCordField_.CalculateSize(_repeated_repeatedCordField_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestCamelCaseFieldNames other) { + if (other == null) { + return; + } + if (other.HasPrimitiveField) { + PrimitiveField = other.PrimitiveField; + } + if (other.HasStringField) { + StringField = other.StringField; + } + if (other.HasEnumField) { + EnumField = other.EnumField; + } + if (other.messageField_ != null) { + if (messageField_ == null) { + MessageField = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage(); + } + MessageField.MergeFrom(other.MessageField); + } + if (other.HasStringPieceField) { + StringPieceField = other.StringPieceField; + } + if (other.HasCordField) { + CordField = other.CordField; + } + repeatedPrimitiveField_.Add(other.repeatedPrimitiveField_); + repeatedStringField_.Add(other.repeatedStringField_); + repeatedEnumField_.Add(other.repeatedEnumField_); + repeatedMessageField_.Add(other.repeatedMessageField_); + repeatedStringPieceField_.Add(other.repeatedStringPieceField_); + repeatedCordField_.Add(other.repeatedCordField_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + PrimitiveField = input.ReadInt32(); + break; + } + case 18: { + StringField = input.ReadString(); + break; + } + case 24: { + EnumField = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum(); + break; + } + case 34: { + if (messageField_ == null) { + MessageField = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage(); + } + input.ReadMessage(MessageField); + break; + } + case 42: { + StringPieceField = input.ReadString(); + break; + } + case 50: { + CordField = input.ReadString(); + break; + } + case 58: + case 56: { + repeatedPrimitiveField_.AddEntriesFrom(input, _repeated_repeatedPrimitiveField_codec); + break; + } + case 66: { + repeatedStringField_.AddEntriesFrom(input, _repeated_repeatedStringField_codec); + break; + } + case 74: + case 72: { + repeatedEnumField_.AddEntriesFrom(input, _repeated_repeatedEnumField_codec); + break; + } + case 82: { + repeatedMessageField_.AddEntriesFrom(input, _repeated_repeatedMessageField_codec); + break; + } + case 90: { + repeatedStringPieceField_.AddEntriesFrom(input, _repeated_repeatedStringPieceField_codec); + break; + } + case 98: { + repeatedCordField_.AddEntriesFrom(input, _repeated_repeatedCordField_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + PrimitiveField = input.ReadInt32(); + break; + } + case 18: { + StringField = input.ReadString(); + break; + } + case 24: { + EnumField = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum(); + break; + } + case 34: { + if (messageField_ == null) { + MessageField = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage(); + } + input.ReadMessage(MessageField); + break; + } + case 42: { + StringPieceField = input.ReadString(); + break; + } + case 50: { + CordField = input.ReadString(); + break; + } + case 58: + case 56: { + repeatedPrimitiveField_.AddEntriesFrom(ref input, _repeated_repeatedPrimitiveField_codec); + break; + } + case 66: { + repeatedStringField_.AddEntriesFrom(ref input, _repeated_repeatedStringField_codec); + break; + } + case 74: + case 72: { + repeatedEnumField_.AddEntriesFrom(ref input, _repeated_repeatedEnumField_codec); + break; + } + case 82: { + repeatedMessageField_.AddEntriesFrom(ref input, _repeated_repeatedMessageField_codec); + break; + } + case 90: { + repeatedStringPieceField_.AddEntriesFrom(ref input, _repeated_repeatedStringPieceField_codec); + break; + } + case 98: { + repeatedCordField_.AddEntriesFrom(ref input, _repeated_repeatedCordField_codec); + break; + } + } + } + } + #endif + + } + + /// + /// We list fields out of order, to ensure that we're using field number and not + /// field index to determine serialization order. + /// + public sealed partial class TestFieldOrderings : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestFieldOrderings()); + private pb::UnknownFieldSet _unknownFields; + private pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[29]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestFieldOrderings() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestFieldOrderings(TestFieldOrderings other) : this() { + _hasBits0 = other._hasBits0; + myString_ = other.myString_; + myInt_ = other.myInt_; + myFloat_ = other.myFloat_; + optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestFieldOrderings Clone() { + return new TestFieldOrderings(this); + } + + /// Field number for the "my_string" field. + public const int MyStringFieldNumber = 11; + private readonly static string MyStringDefaultValue = ""; + + private string myString_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string MyString { + get { return myString_ ?? MyStringDefaultValue; } + set { + myString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "my_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMyString { + get { return myString_ != null; } + } + /// Clears the value of the "my_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMyString() { + myString_ = null; + } + + /// Field number for the "my_int" field. + public const int MyIntFieldNumber = 1; + private readonly static long MyIntDefaultValue = 0L; + + private long myInt_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long MyInt { + get { if ((_hasBits0 & 1) != 0) { return myInt_; } else { return MyIntDefaultValue; } } + set { + _hasBits0 |= 1; + myInt_ = value; + } + } + /// Gets whether the "my_int" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMyInt { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "my_int" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMyInt() { + _hasBits0 &= ~1; + } + + /// Field number for the "my_float" field. + public const int MyFloatFieldNumber = 101; + private readonly static float MyFloatDefaultValue = 0F; + + private float myFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float MyFloat { + get { if ((_hasBits0 & 2) != 0) { return myFloat_; } else { return MyFloatDefaultValue; } } + set { + _hasBits0 |= 2; + myFloat_ = value; + } + } + /// Gets whether the "my_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMyFloat { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "my_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMyFloat() { + _hasBits0 &= ~2; + } + + /// Field number for the "optional_nested_message" field. + public const int OptionalNestedMessageFieldNumber = 200; + private global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Types.NestedMessage optionalNestedMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Types.NestedMessage OptionalNestedMessage { + get { return optionalNestedMessage_; } + set { + optionalNestedMessage_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestFieldOrderings); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestFieldOrderings other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (MyString != other.MyString) return false; + if (MyInt != other.MyInt) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(MyFloat, other.MyFloat)) return false; + if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasMyString) hash ^= MyString.GetHashCode(); + if (HasMyInt) hash ^= MyInt.GetHashCode(); + if (HasMyFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(MyFloat); + if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasMyInt) { + output.WriteRawTag(8); + output.WriteInt64(MyInt); + } + if (HasMyString) { + output.WriteRawTag(90); + output.WriteString(MyString); + } + if (HasMyFloat) { + output.WriteRawTag(173, 6); + output.WriteFloat(MyFloat); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(194, 12); + output.WriteMessage(OptionalNestedMessage); + } + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasMyInt) { + output.WriteRawTag(8); + output.WriteInt64(MyInt); + } + if (HasMyString) { + output.WriteRawTag(90); + output.WriteString(MyString); + } + if (HasMyFloat) { + output.WriteRawTag(173, 6); + output.WriteFloat(MyFloat); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(194, 12); + output.WriteMessage(OptionalNestedMessage); + } + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasMyString) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(MyString); + } + if (HasMyInt) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(MyInt); + } + if (HasMyFloat) { + size += 2 + 4; + } + if (optionalNestedMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage); + } + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestFieldOrderings other) { + if (other == null) { + return; + } + if (other.HasMyString) { + MyString = other.MyString; + } + if (other.HasMyInt) { + MyInt = other.MyInt; + } + if (other.HasMyFloat) { + MyFloat = other.MyFloat; + } + if (other.optionalNestedMessage_ != null) { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Types.NestedMessage(); + } + OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage); + } + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + case 8: { + MyInt = input.ReadInt64(); + break; + } + case 90: { + MyString = input.ReadString(); + break; + } + case 813: { + MyFloat = input.ReadFloat(); + break; + } + case 1602: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + case 8: { + MyInt = input.ReadInt64(); + break; + } + case 90: { + MyString = input.ReadString(); + break; + } + case 813: { + MyFloat = input.ReadFloat(); + break; + } + case 1602: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + + #region Nested types + /// Container for nested types declared in the TestFieldOrderings message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class NestedMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestFieldOrderings.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + _hasBits0 = other._hasBits0; + oo_ = other.oo_; + bb_ = other.bb_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "oo" field. + public const int OoFieldNumber = 2; + private readonly static long OoDefaultValue = 0L; + + private long oo_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Oo { + get { if ((_hasBits0 & 2) != 0) { return oo_; } else { return OoDefaultValue; } } + set { + _hasBits0 |= 2; + oo_ = value; + } + } + /// Gets whether the "oo" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOo { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "oo" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOo() { + _hasBits0 &= ~2; + } + + /// Field number for the "bb" field. + public const int BbFieldNumber = 1; + private readonly static int BbDefaultValue = 0; + + private int bb_; + /// + /// The field name "b" fails to compile in proto1 because it conflicts with + /// a local variable named "b" in one of the generated methods. Doh. + /// This file needs to compile in proto1 to test backwards-compatibility. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Bb { + get { if ((_hasBits0 & 1) != 0) { return bb_; } else { return BbDefaultValue; } } + set { + _hasBits0 |= 1; + bb_ = value; + } + } + /// Gets whether the "bb" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBb { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "bb" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBb() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Oo != other.Oo) return false; + if (Bb != other.Bb) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasOo) hash ^= Oo.GetHashCode(); + if (HasBb) hash ^= Bb.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasBb) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (HasOo) { + output.WriteRawTag(16); + output.WriteInt64(Oo); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasBb) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (HasOo) { + output.WriteRawTag(16); + output.WriteInt64(Oo); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasOo) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Oo); + } + if (HasBb) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Bb); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.HasOo) { + Oo = other.Oo; + } + if (other.HasBb) { + Bb = other.Bb; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Bb = input.ReadInt32(); + break; + } + case 16: { + Oo = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Bb = input.ReadInt32(); + break; + } + case 16: { + Oo = input.ReadInt64(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class TestExtensionOrderings1 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestExtensionOrderings1()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[30]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtensionOrderings1() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtensionOrderings1(TestExtensionOrderings1 other) : this() { + myString_ = other.myString_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtensionOrderings1 Clone() { + return new TestExtensionOrderings1(this); + } + + /// Field number for the "my_string" field. + public const int MyStringFieldNumber = 1; + private readonly static string MyStringDefaultValue = ""; + + private string myString_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string MyString { + get { return myString_ ?? MyStringDefaultValue; } + set { + myString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "my_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMyString { + get { return myString_ != null; } + } + /// Clears the value of the "my_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMyString() { + myString_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestExtensionOrderings1); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestExtensionOrderings1 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (MyString != other.MyString) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasMyString) hash ^= MyString.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasMyString) { + output.WriteRawTag(10); + output.WriteString(MyString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasMyString) { + output.WriteRawTag(10); + output.WriteString(MyString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasMyString) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(MyString); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestExtensionOrderings1 other) { + if (other == null) { + return; + } + if (other.HasMyString) { + MyString = other.MyString; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + MyString = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + MyString = input.ReadString(); + break; + } + } + } + } + #endif + + #region Extensions + /// Container for extensions for other messages declared in the TestExtensionOrderings1 message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Extensions { + public static readonly pb::Extension TestExtOrderings1 = + new pb::Extension(13, pb::FieldCodec.ForMessage(106, global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings1.Parser)); + } + #endregion + + } + + public sealed partial class TestExtensionOrderings2 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestExtensionOrderings2()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[31]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtensionOrderings2() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtensionOrderings2(TestExtensionOrderings2 other) : this() { + myString_ = other.myString_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtensionOrderings2 Clone() { + return new TestExtensionOrderings2(this); + } + + /// Field number for the "my_string" field. + public const int MyStringFieldNumber = 1; + private readonly static string MyStringDefaultValue = ""; + + private string myString_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string MyString { + get { return myString_ ?? MyStringDefaultValue; } + set { + myString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "my_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMyString { + get { return myString_ != null; } + } + /// Clears the value of the "my_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMyString() { + myString_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestExtensionOrderings2); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestExtensionOrderings2 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (MyString != other.MyString) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasMyString) hash ^= MyString.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasMyString) { + output.WriteRawTag(10); + output.WriteString(MyString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasMyString) { + output.WriteRawTag(10); + output.WriteString(MyString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasMyString) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(MyString); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestExtensionOrderings2 other) { + if (other == null) { + return; + } + if (other.HasMyString) { + MyString = other.MyString; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + MyString = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + MyString = input.ReadString(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestExtensionOrderings2 message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class TestExtensionOrderings3 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestExtensionOrderings3()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtensionOrderings3() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtensionOrderings3(TestExtensionOrderings3 other) : this() { + myString_ = other.myString_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtensionOrderings3 Clone() { + return new TestExtensionOrderings3(this); + } + + /// Field number for the "my_string" field. + public const int MyStringFieldNumber = 1; + private readonly static string MyStringDefaultValue = ""; + + private string myString_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string MyString { + get { return myString_ ?? MyStringDefaultValue; } + set { + myString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "my_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMyString { + get { return myString_ != null; } + } + /// Clears the value of the "my_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMyString() { + myString_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestExtensionOrderings3); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestExtensionOrderings3 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (MyString != other.MyString) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasMyString) hash ^= MyString.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasMyString) { + output.WriteRawTag(10); + output.WriteString(MyString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasMyString) { + output.WriteRawTag(10); + output.WriteString(MyString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasMyString) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(MyString); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestExtensionOrderings3 other) { + if (other == null) { + return; + } + if (other.HasMyString) { + MyString = other.MyString; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + MyString = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + MyString = input.ReadString(); + break; + } + } + } + } + #endif + + #region Extensions + /// Container for extensions for other messages declared in the TestExtensionOrderings3 message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Extensions { + public static readonly pb::Extension TestExtOrderings3 = + new pb::Extension(14, pb::FieldCodec.ForMessage(114, global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2.Types.TestExtensionOrderings3.Parser)); + } + #endregion + + } + + } + #endregion + + #region Extensions + /// Container for extensions for other messages declared in the TestExtensionOrderings2 message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Extensions { + public static readonly pb::Extension TestExtOrderings2 = + new pb::Extension(12, pb::FieldCodec.ForMessage(98, global::Google.Protobuf.TestProtos.Proto2.TestExtensionOrderings2.Parser)); + } + #endregion + + } + + public sealed partial class TestExtremeDefaultValues : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestExtremeDefaultValues()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[32]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtremeDefaultValues() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtremeDefaultValues(TestExtremeDefaultValues other) : this() { + _hasBits0 = other._hasBits0; + escapedBytes_ = other.escapedBytes_; + largeUint32_ = other.largeUint32_; + largeUint64_ = other.largeUint64_; + smallInt32_ = other.smallInt32_; + smallInt64_ = other.smallInt64_; + reallySmallInt32_ = other.reallySmallInt32_; + reallySmallInt64_ = other.reallySmallInt64_; + utf8String_ = other.utf8String_; + zeroFloat_ = other.zeroFloat_; + oneFloat_ = other.oneFloat_; + smallFloat_ = other.smallFloat_; + negativeOneFloat_ = other.negativeOneFloat_; + negativeFloat_ = other.negativeFloat_; + largeFloat_ = other.largeFloat_; + smallNegativeFloat_ = other.smallNegativeFloat_; + infDouble_ = other.infDouble_; + negInfDouble_ = other.negInfDouble_; + nanDouble_ = other.nanDouble_; + infFloat_ = other.infFloat_; + negInfFloat_ = other.negInfFloat_; + nanFloat_ = other.nanFloat_; + cppTrigraph_ = other.cppTrigraph_; + stringWithZero_ = other.stringWithZero_; + bytesWithZero_ = other.bytesWithZero_; + stringPieceWithZero_ = other.stringPieceWithZero_; + cordWithZero_ = other.cordWithZero_; + replacementString_ = other.replacementString_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtremeDefaultValues Clone() { + return new TestExtremeDefaultValues(this); + } + + /// Field number for the "escaped_bytes" field. + public const int EscapedBytesFieldNumber = 1; + private readonly static pb::ByteString EscapedBytesDefaultValue = pb::ByteString.FromBase64("AAEHCAwKDQkLXCci/g=="); + + private pb::ByteString escapedBytes_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString EscapedBytes { + get { return escapedBytes_ ?? EscapedBytesDefaultValue; } + set { + escapedBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "escaped_bytes" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasEscapedBytes { + get { return escapedBytes_ != null; } + } + /// Clears the value of the "escaped_bytes" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearEscapedBytes() { + escapedBytes_ = null; + } + + /// Field number for the "large_uint32" field. + public const int LargeUint32FieldNumber = 2; + private readonly static uint LargeUint32DefaultValue = 4294967295; + + private uint largeUint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint LargeUint32 { + get { if ((_hasBits0 & 1) != 0) { return largeUint32_; } else { return LargeUint32DefaultValue; } } + set { + _hasBits0 |= 1; + largeUint32_ = value; + } + } + /// Gets whether the "large_uint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLargeUint32 { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "large_uint32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLargeUint32() { + _hasBits0 &= ~1; + } + + /// Field number for the "large_uint64" field. + public const int LargeUint64FieldNumber = 3; + private readonly static ulong LargeUint64DefaultValue = 18446744073709551615UL; + + private ulong largeUint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong LargeUint64 { + get { if ((_hasBits0 & 2) != 0) { return largeUint64_; } else { return LargeUint64DefaultValue; } } + set { + _hasBits0 |= 2; + largeUint64_ = value; + } + } + /// Gets whether the "large_uint64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLargeUint64 { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "large_uint64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLargeUint64() { + _hasBits0 &= ~2; + } + + /// Field number for the "small_int32" field. + public const int SmallInt32FieldNumber = 4; + private readonly static int SmallInt32DefaultValue = -2147483647; + + private int smallInt32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int SmallInt32 { + get { if ((_hasBits0 & 4) != 0) { return smallInt32_; } else { return SmallInt32DefaultValue; } } + set { + _hasBits0 |= 4; + smallInt32_ = value; + } + } + /// Gets whether the "small_int32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSmallInt32 { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "small_int32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSmallInt32() { + _hasBits0 &= ~4; + } + + /// Field number for the "small_int64" field. + public const int SmallInt64FieldNumber = 5; + private readonly static long SmallInt64DefaultValue = -9223372036854775807L; + + private long smallInt64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long SmallInt64 { + get { if ((_hasBits0 & 8) != 0) { return smallInt64_; } else { return SmallInt64DefaultValue; } } + set { + _hasBits0 |= 8; + smallInt64_ = value; + } + } + /// Gets whether the "small_int64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSmallInt64 { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "small_int64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSmallInt64() { + _hasBits0 &= ~8; + } + + /// Field number for the "really_small_int32" field. + public const int ReallySmallInt32FieldNumber = 21; + private readonly static int ReallySmallInt32DefaultValue = -2147483648; + + private int reallySmallInt32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int ReallySmallInt32 { + get { if ((_hasBits0 & 131072) != 0) { return reallySmallInt32_; } else { return ReallySmallInt32DefaultValue; } } + set { + _hasBits0 |= 131072; + reallySmallInt32_ = value; + } + } + /// Gets whether the "really_small_int32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasReallySmallInt32 { + get { return (_hasBits0 & 131072) != 0; } + } + /// Clears the value of the "really_small_int32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearReallySmallInt32() { + _hasBits0 &= ~131072; + } + + /// Field number for the "really_small_int64" field. + public const int ReallySmallInt64FieldNumber = 22; + private readonly static long ReallySmallInt64DefaultValue = -9223372036854775808L; + + private long reallySmallInt64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long ReallySmallInt64 { + get { if ((_hasBits0 & 262144) != 0) { return reallySmallInt64_; } else { return ReallySmallInt64DefaultValue; } } + set { + _hasBits0 |= 262144; + reallySmallInt64_ = value; + } + } + /// Gets whether the "really_small_int64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasReallySmallInt64 { + get { return (_hasBits0 & 262144) != 0; } + } + /// Clears the value of the "really_small_int64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearReallySmallInt64() { + _hasBits0 &= ~262144; + } + + /// Field number for the "utf8_string" field. + public const int Utf8StringFieldNumber = 6; + private readonly static string Utf8StringDefaultValue = global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("4Yi0"), 0, 3); + + private string utf8String_; + /// + /// The default value here is UTF-8 for "\u1234". (We could also just type + /// the UTF-8 text directly into this text file rather than escape it, but + /// lots of people use editors that would be confused by this.) + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Utf8String { + get { return utf8String_ ?? Utf8StringDefaultValue; } + set { + utf8String_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "utf8_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasUtf8String { + get { return utf8String_ != null; } + } + /// Clears the value of the "utf8_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearUtf8String() { + utf8String_ = null; + } + + /// Field number for the "zero_float" field. + public const int ZeroFloatFieldNumber = 7; + private readonly static float ZeroFloatDefaultValue = 0F; + + private float zeroFloat_; + /// + /// Tests for single-precision floating-point values. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float ZeroFloat { + get { if ((_hasBits0 & 16) != 0) { return zeroFloat_; } else { return ZeroFloatDefaultValue; } } + set { + _hasBits0 |= 16; + zeroFloat_ = value; + } + } + /// Gets whether the "zero_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasZeroFloat { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "zero_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearZeroFloat() { + _hasBits0 &= ~16; + } + + /// Field number for the "one_float" field. + public const int OneFloatFieldNumber = 8; + private readonly static float OneFloatDefaultValue = 1F; + + private float oneFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float OneFloat { + get { if ((_hasBits0 & 32) != 0) { return oneFloat_; } else { return OneFloatDefaultValue; } } + set { + _hasBits0 |= 32; + oneFloat_ = value; + } + } + /// Gets whether the "one_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneFloat { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "one_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneFloat() { + _hasBits0 &= ~32; + } + + /// Field number for the "small_float" field. + public const int SmallFloatFieldNumber = 9; + private readonly static float SmallFloatDefaultValue = 1.5F; + + private float smallFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float SmallFloat { + get { if ((_hasBits0 & 64) != 0) { return smallFloat_; } else { return SmallFloatDefaultValue; } } + set { + _hasBits0 |= 64; + smallFloat_ = value; + } + } + /// Gets whether the "small_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSmallFloat { + get { return (_hasBits0 & 64) != 0; } + } + /// Clears the value of the "small_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSmallFloat() { + _hasBits0 &= ~64; + } + + /// Field number for the "negative_one_float" field. + public const int NegativeOneFloatFieldNumber = 10; + private readonly static float NegativeOneFloatDefaultValue = -1F; + + private float negativeOneFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float NegativeOneFloat { + get { if ((_hasBits0 & 128) != 0) { return negativeOneFloat_; } else { return NegativeOneFloatDefaultValue; } } + set { + _hasBits0 |= 128; + negativeOneFloat_ = value; + } + } + /// Gets whether the "negative_one_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNegativeOneFloat { + get { return (_hasBits0 & 128) != 0; } + } + /// Clears the value of the "negative_one_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNegativeOneFloat() { + _hasBits0 &= ~128; + } + + /// Field number for the "negative_float" field. + public const int NegativeFloatFieldNumber = 11; + private readonly static float NegativeFloatDefaultValue = -1.5F; + + private float negativeFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float NegativeFloat { + get { if ((_hasBits0 & 256) != 0) { return negativeFloat_; } else { return NegativeFloatDefaultValue; } } + set { + _hasBits0 |= 256; + negativeFloat_ = value; + } + } + /// Gets whether the "negative_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNegativeFloat { + get { return (_hasBits0 & 256) != 0; } + } + /// Clears the value of the "negative_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNegativeFloat() { + _hasBits0 &= ~256; + } + + /// Field number for the "large_float" field. + public const int LargeFloatFieldNumber = 12; + private readonly static float LargeFloatDefaultValue = 2e+08F; + + private float largeFloat_; + /// + /// Using exponents + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float LargeFloat { + get { if ((_hasBits0 & 512) != 0) { return largeFloat_; } else { return LargeFloatDefaultValue; } } + set { + _hasBits0 |= 512; + largeFloat_ = value; + } + } + /// Gets whether the "large_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLargeFloat { + get { return (_hasBits0 & 512) != 0; } + } + /// Clears the value of the "large_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLargeFloat() { + _hasBits0 &= ~512; + } + + /// Field number for the "small_negative_float" field. + public const int SmallNegativeFloatFieldNumber = 13; + private readonly static float SmallNegativeFloatDefaultValue = -8e-28F; + + private float smallNegativeFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float SmallNegativeFloat { + get { if ((_hasBits0 & 1024) != 0) { return smallNegativeFloat_; } else { return SmallNegativeFloatDefaultValue; } } + set { + _hasBits0 |= 1024; + smallNegativeFloat_ = value; + } + } + /// Gets whether the "small_negative_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSmallNegativeFloat { + get { return (_hasBits0 & 1024) != 0; } + } + /// Clears the value of the "small_negative_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSmallNegativeFloat() { + _hasBits0 &= ~1024; + } + + /// Field number for the "inf_double" field. + public const int InfDoubleFieldNumber = 14; + private readonly static double InfDoubleDefaultValue = double.PositiveInfinity; + + private double infDouble_; + /// + /// Text for nonfinite floating-point values. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double InfDouble { + get { if ((_hasBits0 & 2048) != 0) { return infDouble_; } else { return InfDoubleDefaultValue; } } + set { + _hasBits0 |= 2048; + infDouble_ = value; + } + } + /// Gets whether the "inf_double" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasInfDouble { + get { return (_hasBits0 & 2048) != 0; } + } + /// Clears the value of the "inf_double" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearInfDouble() { + _hasBits0 &= ~2048; + } + + /// Field number for the "neg_inf_double" field. + public const int NegInfDoubleFieldNumber = 15; + private readonly static double NegInfDoubleDefaultValue = double.NegativeInfinity; + + private double negInfDouble_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double NegInfDouble { + get { if ((_hasBits0 & 4096) != 0) { return negInfDouble_; } else { return NegInfDoubleDefaultValue; } } + set { + _hasBits0 |= 4096; + negInfDouble_ = value; + } + } + /// Gets whether the "neg_inf_double" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNegInfDouble { + get { return (_hasBits0 & 4096) != 0; } + } + /// Clears the value of the "neg_inf_double" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNegInfDouble() { + _hasBits0 &= ~4096; + } + + /// Field number for the "nan_double" field. + public const int NanDoubleFieldNumber = 16; + private readonly static double NanDoubleDefaultValue = double.NaN; + + private double nanDouble_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double NanDouble { + get { if ((_hasBits0 & 8192) != 0) { return nanDouble_; } else { return NanDoubleDefaultValue; } } + set { + _hasBits0 |= 8192; + nanDouble_ = value; + } + } + /// Gets whether the "nan_double" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNanDouble { + get { return (_hasBits0 & 8192) != 0; } + } + /// Clears the value of the "nan_double" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNanDouble() { + _hasBits0 &= ~8192; + } + + /// Field number for the "inf_float" field. + public const int InfFloatFieldNumber = 17; + private readonly static float InfFloatDefaultValue = float.PositiveInfinity; + + private float infFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float InfFloat { + get { if ((_hasBits0 & 16384) != 0) { return infFloat_; } else { return InfFloatDefaultValue; } } + set { + _hasBits0 |= 16384; + infFloat_ = value; + } + } + /// Gets whether the "inf_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasInfFloat { + get { return (_hasBits0 & 16384) != 0; } + } + /// Clears the value of the "inf_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearInfFloat() { + _hasBits0 &= ~16384; + } + + /// Field number for the "neg_inf_float" field. + public const int NegInfFloatFieldNumber = 18; + private readonly static float NegInfFloatDefaultValue = float.NegativeInfinity; + + private float negInfFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float NegInfFloat { + get { if ((_hasBits0 & 32768) != 0) { return negInfFloat_; } else { return NegInfFloatDefaultValue; } } + set { + _hasBits0 |= 32768; + negInfFloat_ = value; + } + } + /// Gets whether the "neg_inf_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNegInfFloat { + get { return (_hasBits0 & 32768) != 0; } + } + /// Clears the value of the "neg_inf_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNegInfFloat() { + _hasBits0 &= ~32768; + } + + /// Field number for the "nan_float" field. + public const int NanFloatFieldNumber = 19; + private readonly static float NanFloatDefaultValue = float.NaN; + + private float nanFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float NanFloat { + get { if ((_hasBits0 & 65536) != 0) { return nanFloat_; } else { return NanFloatDefaultValue; } } + set { + _hasBits0 |= 65536; + nanFloat_ = value; + } + } + /// Gets whether the "nan_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNanFloat { + get { return (_hasBits0 & 65536) != 0; } + } + /// Clears the value of the "nan_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNanFloat() { + _hasBits0 &= ~65536; + } + + /// Field number for the "cpp_trigraph" field. + public const int CppTrigraphFieldNumber = 20; + private readonly static string CppTrigraphDefaultValue = global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("PyA/ID8/ID8/ID8/PyA/Py8gPz8t"), 0, 21); + + private string cppTrigraph_; + /// + /// Tests for C++ trigraphs. + /// Trigraphs should be escaped in C++ generated files, but they should not be + /// escaped for other languages. + /// Note that in .proto file, "\?" is a valid way to escape ? in string + /// literals. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string CppTrigraph { + get { return cppTrigraph_ ?? CppTrigraphDefaultValue; } + set { + cppTrigraph_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "cpp_trigraph" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCppTrigraph { + get { return cppTrigraph_ != null; } + } + /// Clears the value of the "cpp_trigraph" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCppTrigraph() { + cppTrigraph_ = null; + } + + /// Field number for the "string_with_zero" field. + public const int StringWithZeroFieldNumber = 23; + private readonly static string StringWithZeroDefaultValue = global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("aGVsAGxv"), 0, 6); + + private string stringWithZero_; + /// + /// String defaults containing the character '\000' + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string StringWithZero { + get { return stringWithZero_ ?? StringWithZeroDefaultValue; } + set { + stringWithZero_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "string_with_zero" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStringWithZero { + get { return stringWithZero_ != null; } + } + /// Clears the value of the "string_with_zero" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStringWithZero() { + stringWithZero_ = null; + } + + /// Field number for the "bytes_with_zero" field. + public const int BytesWithZeroFieldNumber = 24; + private readonly static pb::ByteString BytesWithZeroDefaultValue = pb::ByteString.FromBase64("d29yAGxk"); + + private pb::ByteString bytesWithZero_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString BytesWithZero { + get { return bytesWithZero_ ?? BytesWithZeroDefaultValue; } + set { + bytesWithZero_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "bytes_with_zero" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBytesWithZero { + get { return bytesWithZero_ != null; } + } + /// Clears the value of the "bytes_with_zero" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBytesWithZero() { + bytesWithZero_ = null; + } + + /// Field number for the "string_piece_with_zero" field. + public const int StringPieceWithZeroFieldNumber = 25; + private readonly static string StringPieceWithZeroDefaultValue = global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("YWIAYw=="), 0, 4); + + private string stringPieceWithZero_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string StringPieceWithZero { + get { return stringPieceWithZero_ ?? StringPieceWithZeroDefaultValue; } + set { + stringPieceWithZero_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "string_piece_with_zero" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStringPieceWithZero { + get { return stringPieceWithZero_ != null; } + } + /// Clears the value of the "string_piece_with_zero" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStringPieceWithZero() { + stringPieceWithZero_ = null; + } + + /// Field number for the "cord_with_zero" field. + public const int CordWithZeroFieldNumber = 26; + private readonly static string CordWithZeroDefaultValue = global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("MTIAMw=="), 0, 4); + + private string cordWithZero_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string CordWithZero { + get { return cordWithZero_ ?? CordWithZeroDefaultValue; } + set { + cordWithZero_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "cord_with_zero" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCordWithZero { + get { return cordWithZero_ != null; } + } + /// Clears the value of the "cord_with_zero" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCordWithZero() { + cordWithZero_ = null; + } + + /// Field number for the "replacement_string" field. + public const int ReplacementStringFieldNumber = 27; + private readonly static string ReplacementStringDefaultValue = global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("JHt1bmtub3dufQ=="), 0, 10); + + private string replacementString_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string ReplacementString { + get { return replacementString_ ?? ReplacementStringDefaultValue; } + set { + replacementString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "replacement_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasReplacementString { + get { return replacementString_ != null; } + } + /// Clears the value of the "replacement_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearReplacementString() { + replacementString_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestExtremeDefaultValues); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestExtremeDefaultValues other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (EscapedBytes != other.EscapedBytes) return false; + if (LargeUint32 != other.LargeUint32) return false; + if (LargeUint64 != other.LargeUint64) return false; + if (SmallInt32 != other.SmallInt32) return false; + if (SmallInt64 != other.SmallInt64) return false; + if (ReallySmallInt32 != other.ReallySmallInt32) return false; + if (ReallySmallInt64 != other.ReallySmallInt64) return false; + if (Utf8String != other.Utf8String) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(ZeroFloat, other.ZeroFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(OneFloat, other.OneFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(SmallFloat, other.SmallFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(NegativeOneFloat, other.NegativeOneFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(NegativeFloat, other.NegativeFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(LargeFloat, other.LargeFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(SmallNegativeFloat, other.SmallNegativeFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(InfDouble, other.InfDouble)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(NegInfDouble, other.NegInfDouble)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(NanDouble, other.NanDouble)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(InfFloat, other.InfFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(NegInfFloat, other.NegInfFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(NanFloat, other.NanFloat)) return false; + if (CppTrigraph != other.CppTrigraph) return false; + if (StringWithZero != other.StringWithZero) return false; + if (BytesWithZero != other.BytesWithZero) return false; + if (StringPieceWithZero != other.StringPieceWithZero) return false; + if (CordWithZero != other.CordWithZero) return false; + if (ReplacementString != other.ReplacementString) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasEscapedBytes) hash ^= EscapedBytes.GetHashCode(); + if (HasLargeUint32) hash ^= LargeUint32.GetHashCode(); + if (HasLargeUint64) hash ^= LargeUint64.GetHashCode(); + if (HasSmallInt32) hash ^= SmallInt32.GetHashCode(); + if (HasSmallInt64) hash ^= SmallInt64.GetHashCode(); + if (HasReallySmallInt32) hash ^= ReallySmallInt32.GetHashCode(); + if (HasReallySmallInt64) hash ^= ReallySmallInt64.GetHashCode(); + if (HasUtf8String) hash ^= Utf8String.GetHashCode(); + if (HasZeroFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(ZeroFloat); + if (HasOneFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(OneFloat); + if (HasSmallFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(SmallFloat); + if (HasNegativeOneFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(NegativeOneFloat); + if (HasNegativeFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(NegativeFloat); + if (HasLargeFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(LargeFloat); + if (HasSmallNegativeFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(SmallNegativeFloat); + if (HasInfDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(InfDouble); + if (HasNegInfDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(NegInfDouble); + if (HasNanDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(NanDouble); + if (HasInfFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(InfFloat); + if (HasNegInfFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(NegInfFloat); + if (HasNanFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(NanFloat); + if (HasCppTrigraph) hash ^= CppTrigraph.GetHashCode(); + if (HasStringWithZero) hash ^= StringWithZero.GetHashCode(); + if (HasBytesWithZero) hash ^= BytesWithZero.GetHashCode(); + if (HasStringPieceWithZero) hash ^= StringPieceWithZero.GetHashCode(); + if (HasCordWithZero) hash ^= CordWithZero.GetHashCode(); + if (HasReplacementString) hash ^= ReplacementString.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasEscapedBytes) { + output.WriteRawTag(10); + output.WriteBytes(EscapedBytes); + } + if (HasLargeUint32) { + output.WriteRawTag(16); + output.WriteUInt32(LargeUint32); + } + if (HasLargeUint64) { + output.WriteRawTag(24); + output.WriteUInt64(LargeUint64); + } + if (HasSmallInt32) { + output.WriteRawTag(32); + output.WriteInt32(SmallInt32); + } + if (HasSmallInt64) { + output.WriteRawTag(40); + output.WriteInt64(SmallInt64); + } + if (HasUtf8String) { + output.WriteRawTag(50); + output.WriteString(Utf8String); + } + if (HasZeroFloat) { + output.WriteRawTag(61); + output.WriteFloat(ZeroFloat); + } + if (HasOneFloat) { + output.WriteRawTag(69); + output.WriteFloat(OneFloat); + } + if (HasSmallFloat) { + output.WriteRawTag(77); + output.WriteFloat(SmallFloat); + } + if (HasNegativeOneFloat) { + output.WriteRawTag(85); + output.WriteFloat(NegativeOneFloat); + } + if (HasNegativeFloat) { + output.WriteRawTag(93); + output.WriteFloat(NegativeFloat); + } + if (HasLargeFloat) { + output.WriteRawTag(101); + output.WriteFloat(LargeFloat); + } + if (HasSmallNegativeFloat) { + output.WriteRawTag(109); + output.WriteFloat(SmallNegativeFloat); + } + if (HasInfDouble) { + output.WriteRawTag(113); + output.WriteDouble(InfDouble); + } + if (HasNegInfDouble) { + output.WriteRawTag(121); + output.WriteDouble(NegInfDouble); + } + if (HasNanDouble) { + output.WriteRawTag(129, 1); + output.WriteDouble(NanDouble); + } + if (HasInfFloat) { + output.WriteRawTag(141, 1); + output.WriteFloat(InfFloat); + } + if (HasNegInfFloat) { + output.WriteRawTag(149, 1); + output.WriteFloat(NegInfFloat); + } + if (HasNanFloat) { + output.WriteRawTag(157, 1); + output.WriteFloat(NanFloat); + } + if (HasCppTrigraph) { + output.WriteRawTag(162, 1); + output.WriteString(CppTrigraph); + } + if (HasReallySmallInt32) { + output.WriteRawTag(168, 1); + output.WriteInt32(ReallySmallInt32); + } + if (HasReallySmallInt64) { + output.WriteRawTag(176, 1); + output.WriteInt64(ReallySmallInt64); + } + if (HasStringWithZero) { + output.WriteRawTag(186, 1); + output.WriteString(StringWithZero); + } + if (HasBytesWithZero) { + output.WriteRawTag(194, 1); + output.WriteBytes(BytesWithZero); + } + if (HasStringPieceWithZero) { + output.WriteRawTag(202, 1); + output.WriteString(StringPieceWithZero); + } + if (HasCordWithZero) { + output.WriteRawTag(210, 1); + output.WriteString(CordWithZero); + } + if (HasReplacementString) { + output.WriteRawTag(218, 1); + output.WriteString(ReplacementString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasEscapedBytes) { + output.WriteRawTag(10); + output.WriteBytes(EscapedBytes); + } + if (HasLargeUint32) { + output.WriteRawTag(16); + output.WriteUInt32(LargeUint32); + } + if (HasLargeUint64) { + output.WriteRawTag(24); + output.WriteUInt64(LargeUint64); + } + if (HasSmallInt32) { + output.WriteRawTag(32); + output.WriteInt32(SmallInt32); + } + if (HasSmallInt64) { + output.WriteRawTag(40); + output.WriteInt64(SmallInt64); + } + if (HasUtf8String) { + output.WriteRawTag(50); + output.WriteString(Utf8String); + } + if (HasZeroFloat) { + output.WriteRawTag(61); + output.WriteFloat(ZeroFloat); + } + if (HasOneFloat) { + output.WriteRawTag(69); + output.WriteFloat(OneFloat); + } + if (HasSmallFloat) { + output.WriteRawTag(77); + output.WriteFloat(SmallFloat); + } + if (HasNegativeOneFloat) { + output.WriteRawTag(85); + output.WriteFloat(NegativeOneFloat); + } + if (HasNegativeFloat) { + output.WriteRawTag(93); + output.WriteFloat(NegativeFloat); + } + if (HasLargeFloat) { + output.WriteRawTag(101); + output.WriteFloat(LargeFloat); + } + if (HasSmallNegativeFloat) { + output.WriteRawTag(109); + output.WriteFloat(SmallNegativeFloat); + } + if (HasInfDouble) { + output.WriteRawTag(113); + output.WriteDouble(InfDouble); + } + if (HasNegInfDouble) { + output.WriteRawTag(121); + output.WriteDouble(NegInfDouble); + } + if (HasNanDouble) { + output.WriteRawTag(129, 1); + output.WriteDouble(NanDouble); + } + if (HasInfFloat) { + output.WriteRawTag(141, 1); + output.WriteFloat(InfFloat); + } + if (HasNegInfFloat) { + output.WriteRawTag(149, 1); + output.WriteFloat(NegInfFloat); + } + if (HasNanFloat) { + output.WriteRawTag(157, 1); + output.WriteFloat(NanFloat); + } + if (HasCppTrigraph) { + output.WriteRawTag(162, 1); + output.WriteString(CppTrigraph); + } + if (HasReallySmallInt32) { + output.WriteRawTag(168, 1); + output.WriteInt32(ReallySmallInt32); + } + if (HasReallySmallInt64) { + output.WriteRawTag(176, 1); + output.WriteInt64(ReallySmallInt64); + } + if (HasStringWithZero) { + output.WriteRawTag(186, 1); + output.WriteString(StringWithZero); + } + if (HasBytesWithZero) { + output.WriteRawTag(194, 1); + output.WriteBytes(BytesWithZero); + } + if (HasStringPieceWithZero) { + output.WriteRawTag(202, 1); + output.WriteString(StringPieceWithZero); + } + if (HasCordWithZero) { + output.WriteRawTag(210, 1); + output.WriteString(CordWithZero); + } + if (HasReplacementString) { + output.WriteRawTag(218, 1); + output.WriteString(ReplacementString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasEscapedBytes) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(EscapedBytes); + } + if (HasLargeUint32) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(LargeUint32); + } + if (HasLargeUint64) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(LargeUint64); + } + if (HasSmallInt32) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(SmallInt32); + } + if (HasSmallInt64) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(SmallInt64); + } + if (HasReallySmallInt32) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(ReallySmallInt32); + } + if (HasReallySmallInt64) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(ReallySmallInt64); + } + if (HasUtf8String) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Utf8String); + } + if (HasZeroFloat) { + size += 1 + 4; + } + if (HasOneFloat) { + size += 1 + 4; + } + if (HasSmallFloat) { + size += 1 + 4; + } + if (HasNegativeOneFloat) { + size += 1 + 4; + } + if (HasNegativeFloat) { + size += 1 + 4; + } + if (HasLargeFloat) { + size += 1 + 4; + } + if (HasSmallNegativeFloat) { + size += 1 + 4; + } + if (HasInfDouble) { + size += 1 + 8; + } + if (HasNegInfDouble) { + size += 1 + 8; + } + if (HasNanDouble) { + size += 2 + 8; + } + if (HasInfFloat) { + size += 2 + 4; + } + if (HasNegInfFloat) { + size += 2 + 4; + } + if (HasNanFloat) { + size += 2 + 4; + } + if (HasCppTrigraph) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(CppTrigraph); + } + if (HasStringWithZero) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(StringWithZero); + } + if (HasBytesWithZero) { + size += 2 + pb::CodedOutputStream.ComputeBytesSize(BytesWithZero); + } + if (HasStringPieceWithZero) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(StringPieceWithZero); + } + if (HasCordWithZero) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(CordWithZero); + } + if (HasReplacementString) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(ReplacementString); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestExtremeDefaultValues other) { + if (other == null) { + return; + } + if (other.HasEscapedBytes) { + EscapedBytes = other.EscapedBytes; + } + if (other.HasLargeUint32) { + LargeUint32 = other.LargeUint32; + } + if (other.HasLargeUint64) { + LargeUint64 = other.LargeUint64; + } + if (other.HasSmallInt32) { + SmallInt32 = other.SmallInt32; + } + if (other.HasSmallInt64) { + SmallInt64 = other.SmallInt64; + } + if (other.HasReallySmallInt32) { + ReallySmallInt32 = other.ReallySmallInt32; + } + if (other.HasReallySmallInt64) { + ReallySmallInt64 = other.ReallySmallInt64; + } + if (other.HasUtf8String) { + Utf8String = other.Utf8String; + } + if (other.HasZeroFloat) { + ZeroFloat = other.ZeroFloat; + } + if (other.HasOneFloat) { + OneFloat = other.OneFloat; + } + if (other.HasSmallFloat) { + SmallFloat = other.SmallFloat; + } + if (other.HasNegativeOneFloat) { + NegativeOneFloat = other.NegativeOneFloat; + } + if (other.HasNegativeFloat) { + NegativeFloat = other.NegativeFloat; + } + if (other.HasLargeFloat) { + LargeFloat = other.LargeFloat; + } + if (other.HasSmallNegativeFloat) { + SmallNegativeFloat = other.SmallNegativeFloat; + } + if (other.HasInfDouble) { + InfDouble = other.InfDouble; + } + if (other.HasNegInfDouble) { + NegInfDouble = other.NegInfDouble; + } + if (other.HasNanDouble) { + NanDouble = other.NanDouble; + } + if (other.HasInfFloat) { + InfFloat = other.InfFloat; + } + if (other.HasNegInfFloat) { + NegInfFloat = other.NegInfFloat; + } + if (other.HasNanFloat) { + NanFloat = other.NanFloat; + } + if (other.HasCppTrigraph) { + CppTrigraph = other.CppTrigraph; + } + if (other.HasStringWithZero) { + StringWithZero = other.StringWithZero; + } + if (other.HasBytesWithZero) { + BytesWithZero = other.BytesWithZero; + } + if (other.HasStringPieceWithZero) { + StringPieceWithZero = other.StringPieceWithZero; + } + if (other.HasCordWithZero) { + CordWithZero = other.CordWithZero; + } + if (other.HasReplacementString) { + ReplacementString = other.ReplacementString; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + EscapedBytes = input.ReadBytes(); + break; + } + case 16: { + LargeUint32 = input.ReadUInt32(); + break; + } + case 24: { + LargeUint64 = input.ReadUInt64(); + break; + } + case 32: { + SmallInt32 = input.ReadInt32(); + break; + } + case 40: { + SmallInt64 = input.ReadInt64(); + break; + } + case 50: { + Utf8String = input.ReadString(); + break; + } + case 61: { + ZeroFloat = input.ReadFloat(); + break; + } + case 69: { + OneFloat = input.ReadFloat(); + break; + } + case 77: { + SmallFloat = input.ReadFloat(); + break; + } + case 85: { + NegativeOneFloat = input.ReadFloat(); + break; + } + case 93: { + NegativeFloat = input.ReadFloat(); + break; + } + case 101: { + LargeFloat = input.ReadFloat(); + break; + } + case 109: { + SmallNegativeFloat = input.ReadFloat(); + break; + } + case 113: { + InfDouble = input.ReadDouble(); + break; + } + case 121: { + NegInfDouble = input.ReadDouble(); + break; + } + case 129: { + NanDouble = input.ReadDouble(); + break; + } + case 141: { + InfFloat = input.ReadFloat(); + break; + } + case 149: { + NegInfFloat = input.ReadFloat(); + break; + } + case 157: { + NanFloat = input.ReadFloat(); + break; + } + case 162: { + CppTrigraph = input.ReadString(); + break; + } + case 168: { + ReallySmallInt32 = input.ReadInt32(); + break; + } + case 176: { + ReallySmallInt64 = input.ReadInt64(); + break; + } + case 186: { + StringWithZero = input.ReadString(); + break; + } + case 194: { + BytesWithZero = input.ReadBytes(); + break; + } + case 202: { + StringPieceWithZero = input.ReadString(); + break; + } + case 210: { + CordWithZero = input.ReadString(); + break; + } + case 218: { + ReplacementString = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + EscapedBytes = input.ReadBytes(); + break; + } + case 16: { + LargeUint32 = input.ReadUInt32(); + break; + } + case 24: { + LargeUint64 = input.ReadUInt64(); + break; + } + case 32: { + SmallInt32 = input.ReadInt32(); + break; + } + case 40: { + SmallInt64 = input.ReadInt64(); + break; + } + case 50: { + Utf8String = input.ReadString(); + break; + } + case 61: { + ZeroFloat = input.ReadFloat(); + break; + } + case 69: { + OneFloat = input.ReadFloat(); + break; + } + case 77: { + SmallFloat = input.ReadFloat(); + break; + } + case 85: { + NegativeOneFloat = input.ReadFloat(); + break; + } + case 93: { + NegativeFloat = input.ReadFloat(); + break; + } + case 101: { + LargeFloat = input.ReadFloat(); + break; + } + case 109: { + SmallNegativeFloat = input.ReadFloat(); + break; + } + case 113: { + InfDouble = input.ReadDouble(); + break; + } + case 121: { + NegInfDouble = input.ReadDouble(); + break; + } + case 129: { + NanDouble = input.ReadDouble(); + break; + } + case 141: { + InfFloat = input.ReadFloat(); + break; + } + case 149: { + NegInfFloat = input.ReadFloat(); + break; + } + case 157: { + NanFloat = input.ReadFloat(); + break; + } + case 162: { + CppTrigraph = input.ReadString(); + break; + } + case 168: { + ReallySmallInt32 = input.ReadInt32(); + break; + } + case 176: { + ReallySmallInt64 = input.ReadInt64(); + break; + } + case 186: { + StringWithZero = input.ReadString(); + break; + } + case 194: { + BytesWithZero = input.ReadBytes(); + break; + } + case 202: { + StringPieceWithZero = input.ReadString(); + break; + } + case 210: { + CordWithZero = input.ReadString(); + break; + } + case 218: { + ReplacementString = input.ReadString(); + break; + } + } + } + } + #endif + + } + + public sealed partial class SparseEnumMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SparseEnumMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[33]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SparseEnumMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SparseEnumMessage(SparseEnumMessage other) : this() { + _hasBits0 = other._hasBits0; + sparseEnum_ = other.sparseEnum_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SparseEnumMessage Clone() { + return new SparseEnumMessage(this); + } + + /// Field number for the "sparse_enum" field. + public const int SparseEnumFieldNumber = 1; + private readonly static global::Google.Protobuf.TestProtos.Proto2.TestSparseEnum SparseEnumDefaultValue = global::Google.Protobuf.TestProtos.Proto2.TestSparseEnum.SparseA; + + private global::Google.Protobuf.TestProtos.Proto2.TestSparseEnum sparseEnum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestSparseEnum SparseEnum { + get { if ((_hasBits0 & 1) != 0) { return sparseEnum_; } else { return SparseEnumDefaultValue; } } + set { + _hasBits0 |= 1; + sparseEnum_ = value; + } + } + /// Gets whether the "sparse_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSparseEnum { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "sparse_enum" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSparseEnum() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SparseEnumMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SparseEnumMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (SparseEnum != other.SparseEnum) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasSparseEnum) hash ^= SparseEnum.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasSparseEnum) { + output.WriteRawTag(8); + output.WriteEnum((int) SparseEnum); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasSparseEnum) { + output.WriteRawTag(8); + output.WriteEnum((int) SparseEnum); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasSparseEnum) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) SparseEnum); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SparseEnumMessage other) { + if (other == null) { + return; + } + if (other.HasSparseEnum) { + SparseEnum = other.SparseEnum; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + SparseEnum = (global::Google.Protobuf.TestProtos.Proto2.TestSparseEnum) input.ReadEnum(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + SparseEnum = (global::Google.Protobuf.TestProtos.Proto2.TestSparseEnum) input.ReadEnum(); + break; + } + } + } + } + #endif + + } + + /// + /// Test String and Bytes: string is for valid UTF-8 strings + /// + public sealed partial class OneString : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneString()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[34]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneString() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneString(OneString other) : this() { + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneString Clone() { + return new OneString(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private readonly static string DataDefaultValue = ""; + + private string data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Data { + get { return data_ ?? DataDefaultValue; } + set { + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "data" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasData { + get { return data_ != null; } + } + /// Clears the value of the "data" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearData() { + data_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as OneString); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(OneString other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasData) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasData) { + output.WriteRawTag(10); + output.WriteString(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasData) { + output.WriteRawTag(10); + output.WriteString(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasData) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(OneString other) { + if (other == null) { + return; + } + if (other.HasData) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Data = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Data = input.ReadString(); + break; + } + } + } + } + #endif + + } + + public sealed partial class MoreString : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MoreString()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[35]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MoreString() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MoreString(MoreString other) : this() { + data_ = other.data_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MoreString Clone() { + return new MoreString(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_data_codec + = pb::FieldCodec.ForString(10); + private readonly pbc::RepeatedField data_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Data { + get { return data_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as MoreString); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(MoreString other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!data_.Equals(other.data_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= data_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + data_.WriteTo(output, _repeated_data_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + data_.WriteTo(ref output, _repeated_data_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += data_.CalculateSize(_repeated_data_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(MoreString other) { + if (other == null) { + return; + } + data_.Add(other.data_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + data_.AddEntriesFrom(input, _repeated_data_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + data_.AddEntriesFrom(ref input, _repeated_data_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class OneBytes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneBytes()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[36]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneBytes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneBytes(OneBytes other) : this() { + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneBytes Clone() { + return new OneBytes(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private readonly static pb::ByteString DataDefaultValue = pb::ByteString.Empty; + + private pb::ByteString data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString Data { + get { return data_ ?? DataDefaultValue; } + set { + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "data" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasData { + get { return data_ != null; } + } + /// Clears the value of the "data" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearData() { + data_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as OneBytes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(OneBytes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasData) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasData) { + output.WriteRawTag(10); + output.WriteBytes(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasData) { + output.WriteRawTag(10); + output.WriteBytes(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasData) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(OneBytes other) { + if (other == null) { + return; + } + if (other.HasData) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Data = input.ReadBytes(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Data = input.ReadBytes(); + break; + } + } + } + } + #endif + + } + + public sealed partial class MoreBytes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MoreBytes()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[37]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MoreBytes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MoreBytes(MoreBytes other) : this() { + data_ = other.data_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MoreBytes Clone() { + return new MoreBytes(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_data_codec + = pb::FieldCodec.ForBytes(10); + private readonly pbc::RepeatedField data_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Data { + get { return data_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as MoreBytes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(MoreBytes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!data_.Equals(other.data_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= data_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + data_.WriteTo(output, _repeated_data_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + data_.WriteTo(ref output, _repeated_data_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += data_.CalculateSize(_repeated_data_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(MoreBytes other) { + if (other == null) { + return; + } + data_.Add(other.data_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + data_.AddEntriesFrom(input, _repeated_data_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + data_.AddEntriesFrom(ref input, _repeated_data_codec); + break; + } + } + } + } + #endif + + } + + /// + /// Test int32, uint32, int64, uint64, and bool are all compatible + /// + public sealed partial class Int32Message : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Int32Message()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[38]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Int32Message() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Int32Message(Int32Message other) : this() { + _hasBits0 = other._hasBits0; + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Int32Message Clone() { + return new Int32Message(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private readonly static int DataDefaultValue = 0; + + private int data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Data { + get { if ((_hasBits0 & 1) != 0) { return data_; } else { return DataDefaultValue; } } + set { + _hasBits0 |= 1; + data_ = value; + } + } + /// Gets whether the "data" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasData { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "data" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearData() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Int32Message); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Int32Message other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasData) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasData) { + output.WriteRawTag(8); + output.WriteInt32(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasData) { + output.WriteRawTag(8); + output.WriteInt32(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasData) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Int32Message other) { + if (other == null) { + return; + } + if (other.HasData) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class Uint32Message : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Uint32Message()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[39]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Uint32Message() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Uint32Message(Uint32Message other) : this() { + _hasBits0 = other._hasBits0; + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Uint32Message Clone() { + return new Uint32Message(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private readonly static uint DataDefaultValue = 0; + + private uint data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint Data { + get { if ((_hasBits0 & 1) != 0) { return data_; } else { return DataDefaultValue; } } + set { + _hasBits0 |= 1; + data_ = value; + } + } + /// Gets whether the "data" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasData { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "data" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearData() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Uint32Message); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Uint32Message other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasData) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasData) { + output.WriteRawTag(8); + output.WriteUInt32(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasData) { + output.WriteRawTag(8); + output.WriteUInt32(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasData) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Uint32Message other) { + if (other == null) { + return; + } + if (other.HasData) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadUInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadUInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class Int64Message : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Int64Message()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[40]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Int64Message() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Int64Message(Int64Message other) : this() { + _hasBits0 = other._hasBits0; + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Int64Message Clone() { + return new Int64Message(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private readonly static long DataDefaultValue = 0L; + + private long data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Data { + get { if ((_hasBits0 & 1) != 0) { return data_; } else { return DataDefaultValue; } } + set { + _hasBits0 |= 1; + data_ = value; + } + } + /// Gets whether the "data" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasData { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "data" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearData() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Int64Message); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Int64Message other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasData) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasData) { + output.WriteRawTag(8); + output.WriteInt64(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasData) { + output.WriteRawTag(8); + output.WriteInt64(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasData) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Int64Message other) { + if (other == null) { + return; + } + if (other.HasData) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadInt64(); + break; + } + } + } + } + #endif + + } + + public sealed partial class Uint64Message : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Uint64Message()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[41]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Uint64Message() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Uint64Message(Uint64Message other) : this() { + _hasBits0 = other._hasBits0; + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Uint64Message Clone() { + return new Uint64Message(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private readonly static ulong DataDefaultValue = 0UL; + + private ulong data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong Data { + get { if ((_hasBits0 & 1) != 0) { return data_; } else { return DataDefaultValue; } } + set { + _hasBits0 |= 1; + data_ = value; + } + } + /// Gets whether the "data" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasData { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "data" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearData() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Uint64Message); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Uint64Message other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasData) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasData) { + output.WriteRawTag(8); + output.WriteUInt64(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasData) { + output.WriteRawTag(8); + output.WriteUInt64(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasData) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Uint64Message other) { + if (other == null) { + return; + } + if (other.HasData) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadUInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadUInt64(); + break; + } + } + } + } + #endif + + } + + public sealed partial class BoolMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BoolMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[42]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BoolMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BoolMessage(BoolMessage other) : this() { + _hasBits0 = other._hasBits0; + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BoolMessage Clone() { + return new BoolMessage(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private readonly static bool DataDefaultValue = false; + + private bool data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Data { + get { if ((_hasBits0 & 1) != 0) { return data_; } else { return DataDefaultValue; } } + set { + _hasBits0 |= 1; + data_ = value; + } + } + /// Gets whether the "data" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasData { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "data" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearData() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as BoolMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(BoolMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasData) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasData) { + output.WriteRawTag(8); + output.WriteBool(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasData) { + output.WriteRawTag(8); + output.WriteBool(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasData) { + size += 1 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(BoolMessage other) { + if (other == null) { + return; + } + if (other.HasData) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadBool(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadBool(); + break; + } + } + } + } + #endif + + } + + /// + /// Test oneofs. + /// + public sealed partial class TestOneof : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestOneof()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[43]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestOneof() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestOneof(TestOneof other) : this() { + switch (other.FooCase) { + case FooOneofCase.FooInt: + FooInt = other.FooInt; + break; + case FooOneofCase.FooString: + FooString = other.FooString; + break; + case FooOneofCase.FooMessage: + FooMessage = other.FooMessage.Clone(); + break; + case FooOneofCase.FooGroup: + FooGroup = other.FooGroup.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestOneof Clone() { + return new TestOneof(this); + } + + /// Field number for the "foo_int" field. + public const int FooIntFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FooInt { + get { return HasFooInt ? (int) foo_ : 0; } + set { + foo_ = value; + fooCase_ = FooOneofCase.FooInt; + } + } + /// Gets whether the "foo_int" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooInt { + get { return fooCase_ == FooOneofCase.FooInt; } + } + /// Clears the value of the oneof if it's currently set to "foo_int" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooInt() { + if (HasFooInt) { + ClearFoo(); + } + } + + /// Field number for the "foo_string" field. + public const int FooStringFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string FooString { + get { return HasFooString ? (string) foo_ : ""; } + set { + foo_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + fooCase_ = FooOneofCase.FooString; + } + } + /// Gets whether the "foo_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooString { + get { return fooCase_ == FooOneofCase.FooString; } + } + /// Clears the value of the oneof if it's currently set to "foo_string" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooString() { + if (HasFooString) { + ClearFoo(); + } + } + + /// Field number for the "foo_message" field. + public const int FooMessageFieldNumber = 3; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes FooMessage { + get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes) foo_ : null; } + set { + foo_ = value; + fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooMessage; + } + } + + /// Field number for the "foogroup" field. + public const int FooGroupFieldNumber = 4; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestOneof.Types.FooGroup FooGroup { + get { return HasFooGroup ? (global::Google.Protobuf.TestProtos.Proto2.TestOneof.Types.FooGroup) foo_ : null; } + set { + foo_ = value; + fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooGroup; + } + } + /// Gets whether the "foogroup" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooGroup { + get { return fooCase_ == FooOneofCase.FooGroup; } + } + /// Clears the value of the oneof if it's currently set to "foogroup" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooGroup() { + if (HasFooGroup) { + ClearFoo(); + } + } + + private object foo_; + /// Enum of possible cases for the "foo" oneof. + public enum FooOneofCase { + None = 0, + FooInt = 1, + FooString = 2, + FooMessage = 3, + FooGroup = 4, + } + private FooOneofCase fooCase_ = FooOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooOneofCase FooCase { + get { return fooCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFoo() { + fooCase_ = FooOneofCase.None; + foo_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestOneof); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestOneof other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (FooInt != other.FooInt) return false; + if (FooString != other.FooString) return false; + if (!object.Equals(FooMessage, other.FooMessage)) return false; + if (!object.Equals(FooGroup, other.FooGroup)) return false; + if (FooCase != other.FooCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasFooInt) hash ^= FooInt.GetHashCode(); + if (HasFooString) hash ^= FooString.GetHashCode(); + if (fooCase_ == FooOneofCase.FooMessage) hash ^= FooMessage.GetHashCode(); + if (HasFooGroup) hash ^= FooGroup.GetHashCode(); + hash ^= (int) fooCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasFooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (HasFooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (fooCase_ == FooOneofCase.FooMessage) { + output.WriteRawTag(26); + output.WriteMessage(FooMessage); + } + if (HasFooGroup) { + output.WriteRawTag(35); + output.WriteGroup(FooGroup); + output.WriteRawTag(36); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasFooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (HasFooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (fooCase_ == FooOneofCase.FooMessage) { + output.WriteRawTag(26); + output.WriteMessage(FooMessage); + } + if (HasFooGroup) { + output.WriteRawTag(35); + output.WriteGroup(FooGroup); + output.WriteRawTag(36); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasFooInt) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(FooInt); + } + if (HasFooString) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FooString); + } + if (fooCase_ == FooOneofCase.FooMessage) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(FooMessage); + } + if (HasFooGroup) { + size += 2 + pb::CodedOutputStream.ComputeGroupSize(FooGroup); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestOneof other) { + if (other == null) { + return; + } + switch (other.FooCase) { + case FooOneofCase.FooInt: + FooInt = other.FooInt; + break; + case FooOneofCase.FooString: + FooString = other.FooString; + break; + case FooOneofCase.FooMessage: + if (FooMessage == null) { + FooMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + FooMessage.MergeFrom(other.FooMessage); + break; + case FooOneofCase.FooGroup: + if (FooGroup == null) { + FooGroup = new global::Google.Protobuf.TestProtos.Proto2.TestOneof.Types.FooGroup(); + } + FooGroup.MergeFrom(other.FooGroup); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + FooInt = input.ReadInt32(); + break; + } + case 18: { + FooString = input.ReadString(); + break; + } + case 26: { + global::Google.Protobuf.TestProtos.Proto2.TestAllTypes subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + if (fooCase_ == FooOneofCase.FooMessage) { + subBuilder.MergeFrom(FooMessage); + } + input.ReadMessage(subBuilder); + FooMessage = subBuilder; + break; + } + case 35: { + global::Google.Protobuf.TestProtos.Proto2.TestOneof.Types.FooGroup subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestOneof.Types.FooGroup(); + if (HasFooGroup) { + subBuilder.MergeFrom(FooGroup); + } + input.ReadGroup(subBuilder); + FooGroup = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + FooInt = input.ReadInt32(); + break; + } + case 18: { + FooString = input.ReadString(); + break; + } + case 26: { + global::Google.Protobuf.TestProtos.Proto2.TestAllTypes subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + if (fooCase_ == FooOneofCase.FooMessage) { + subBuilder.MergeFrom(FooMessage); + } + input.ReadMessage(subBuilder); + FooMessage = subBuilder; + break; + } + case 35: { + global::Google.Protobuf.TestProtos.Proto2.TestOneof.Types.FooGroup subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestOneof.Types.FooGroup(); + if (HasFooGroup) { + subBuilder.MergeFrom(FooGroup); + } + input.ReadGroup(subBuilder); + FooGroup = subBuilder; + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestOneof message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class FooGroup : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooGroup()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestOneof.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooGroup() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooGroup(FooGroup other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + b_ = other.b_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooGroup Clone() { + return new FooGroup(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 5; + private readonly static int ADefaultValue = 0; + + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + /// Field number for the "b" field. + public const int BFieldNumber = 6; + private readonly static string BDefaultValue = ""; + + private string b_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string B { + get { return b_ ?? BDefaultValue; } + set { + b_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "b" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasB { + get { return b_ != null; } + } + /// Clears the value of the "b" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearB() { + b_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FooGroup); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FooGroup other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + if (B != other.B) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (HasB) hash ^= B.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(40); + output.WriteInt32(A); + } + if (HasB) { + output.WriteRawTag(50); + output.WriteString(B); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(40); + output.WriteInt32(A); + } + if (HasB) { + output.WriteRawTag(50); + output.WriteString(B); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (HasB) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(B); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FooGroup other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + if (other.HasB) { + B = other.B; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 36: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 40: { + A = input.ReadInt32(); + break; + } + case 50: { + B = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 36: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 40: { + A = input.ReadInt32(); + break; + } + case 50: { + B = input.ReadString(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class TestOneofBackwardsCompatible : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestOneofBackwardsCompatible()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[44]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestOneofBackwardsCompatible() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestOneofBackwardsCompatible(TestOneofBackwardsCompatible other) : this() { + _hasBits0 = other._hasBits0; + fooInt_ = other.fooInt_; + fooString_ = other.fooString_; + fooMessage_ = other.fooMessage_ != null ? other.fooMessage_.Clone() : null; + fooGroup_ = other.HasFooGroup ? other.fooGroup_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestOneofBackwardsCompatible Clone() { + return new TestOneofBackwardsCompatible(this); + } + + /// Field number for the "foo_int" field. + public const int FooIntFieldNumber = 1; + private readonly static int FooIntDefaultValue = 0; + + private int fooInt_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FooInt { + get { if ((_hasBits0 & 1) != 0) { return fooInt_; } else { return FooIntDefaultValue; } } + set { + _hasBits0 |= 1; + fooInt_ = value; + } + } + /// Gets whether the "foo_int" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooInt { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "foo_int" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooInt() { + _hasBits0 &= ~1; + } + + /// Field number for the "foo_string" field. + public const int FooStringFieldNumber = 2; + private readonly static string FooStringDefaultValue = ""; + + private string fooString_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string FooString { + get { return fooString_ ?? FooStringDefaultValue; } + set { + fooString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "foo_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooString { + get { return fooString_ != null; } + } + /// Clears the value of the "foo_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooString() { + fooString_ = null; + } + + /// Field number for the "foo_message" field. + public const int FooMessageFieldNumber = 3; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes fooMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes FooMessage { + get { return fooMessage_; } + set { + fooMessage_ = value; + } + } + + /// Field number for the "foogroup" field. + public const int FooGroupFieldNumber = 4; + private global::Google.Protobuf.TestProtos.Proto2.TestOneofBackwardsCompatible.Types.FooGroup fooGroup_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestOneofBackwardsCompatible.Types.FooGroup FooGroup { + get { return fooGroup_; } + set { + fooGroup_ = value; + } + } + /// Gets whether the foogroup field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooGroup { + get { return fooGroup_ != null; } + } + /// Clears the value of the foogroup field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooGroup() { + fooGroup_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestOneofBackwardsCompatible); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestOneofBackwardsCompatible other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (FooInt != other.FooInt) return false; + if (FooString != other.FooString) return false; + if (!object.Equals(FooMessage, other.FooMessage)) return false; + if (!object.Equals(FooGroup, other.FooGroup)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasFooInt) hash ^= FooInt.GetHashCode(); + if (HasFooString) hash ^= FooString.GetHashCode(); + if (fooMessage_ != null) hash ^= FooMessage.GetHashCode(); + if (HasFooGroup) hash ^= FooGroup.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasFooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (HasFooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (fooMessage_ != null) { + output.WriteRawTag(26); + output.WriteMessage(FooMessage); + } + if (HasFooGroup) { + output.WriteRawTag(35); + output.WriteGroup(FooGroup); + output.WriteRawTag(36); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasFooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (HasFooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (fooMessage_ != null) { + output.WriteRawTag(26); + output.WriteMessage(FooMessage); + } + if (HasFooGroup) { + output.WriteRawTag(35); + output.WriteGroup(FooGroup); + output.WriteRawTag(36); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasFooInt) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(FooInt); + } + if (HasFooString) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FooString); + } + if (fooMessage_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(FooMessage); + } + if (HasFooGroup) { + size += 2 + pb::CodedOutputStream.ComputeGroupSize(FooGroup); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestOneofBackwardsCompatible other) { + if (other == null) { + return; + } + if (other.HasFooInt) { + FooInt = other.FooInt; + } + if (other.HasFooString) { + FooString = other.FooString; + } + if (other.fooMessage_ != null) { + if (fooMessage_ == null) { + FooMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + FooMessage.MergeFrom(other.FooMessage); + } + if (other.HasFooGroup) { + if (!HasFooGroup) { + FooGroup = new global::Google.Protobuf.TestProtos.Proto2.TestOneofBackwardsCompatible.Types.FooGroup(); + } + FooGroup.MergeFrom(other.FooGroup); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + FooInt = input.ReadInt32(); + break; + } + case 18: { + FooString = input.ReadString(); + break; + } + case 26: { + if (fooMessage_ == null) { + FooMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(FooMessage); + break; + } + case 35: { + if (!HasFooGroup) { + FooGroup = new global::Google.Protobuf.TestProtos.Proto2.TestOneofBackwardsCompatible.Types.FooGroup(); + } + input.ReadGroup(FooGroup); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + FooInt = input.ReadInt32(); + break; + } + case 18: { + FooString = input.ReadString(); + break; + } + case 26: { + if (fooMessage_ == null) { + FooMessage = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(FooMessage); + break; + } + case 35: { + if (!HasFooGroup) { + FooGroup = new global::Google.Protobuf.TestProtos.Proto2.TestOneofBackwardsCompatible.Types.FooGroup(); + } + input.ReadGroup(FooGroup); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestOneofBackwardsCompatible message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class FooGroup : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooGroup()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestOneofBackwardsCompatible.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooGroup() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooGroup(FooGroup other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + b_ = other.b_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooGroup Clone() { + return new FooGroup(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 5; + private readonly static int ADefaultValue = 0; + + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + /// Field number for the "b" field. + public const int BFieldNumber = 6; + private readonly static string BDefaultValue = ""; + + private string b_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string B { + get { return b_ ?? BDefaultValue; } + set { + b_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "b" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasB { + get { return b_ != null; } + } + /// Clears the value of the "b" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearB() { + b_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FooGroup); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FooGroup other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + if (B != other.B) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (HasB) hash ^= B.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(40); + output.WriteInt32(A); + } + if (HasB) { + output.WriteRawTag(50); + output.WriteString(B); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(40); + output.WriteInt32(A); + } + if (HasB) { + output.WriteRawTag(50); + output.WriteString(B); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (HasB) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(B); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FooGroup other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + if (other.HasB) { + B = other.B; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 36: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 40: { + A = input.ReadInt32(); + break; + } + case 50: { + B = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 36: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 40: { + A = input.ReadInt32(); + break; + } + case 50: { + B = input.ReadString(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class TestOneof2 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestOneof2()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[45]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestOneof2() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestOneof2(TestOneof2 other) : this() { + _hasBits0 = other._hasBits0; + bazInt_ = other.bazInt_; + bazString_ = other.bazString_; + switch (other.FooCase) { + case FooOneofCase.FooInt: + FooInt = other.FooInt; + break; + case FooOneofCase.FooString: + FooString = other.FooString; + break; + case FooOneofCase.FooCord: + FooCord = other.FooCord; + break; + case FooOneofCase.FooStringPiece: + FooStringPiece = other.FooStringPiece; + break; + case FooOneofCase.FooBytes: + FooBytes = other.FooBytes; + break; + case FooOneofCase.FooEnum: + FooEnum = other.FooEnum; + break; + case FooOneofCase.FooMessage: + FooMessage = other.FooMessage.Clone(); + break; + case FooOneofCase.FooGroup: + FooGroup = other.FooGroup.Clone(); + break; + case FooOneofCase.FooLazyMessage: + FooLazyMessage = other.FooLazyMessage.Clone(); + break; + } + + switch (other.BarCase) { + case BarOneofCase.BarInt: + BarInt = other.BarInt; + break; + case BarOneofCase.BarString: + BarString = other.BarString; + break; + case BarOneofCase.BarCord: + BarCord = other.BarCord; + break; + case BarOneofCase.BarStringPiece: + BarStringPiece = other.BarStringPiece; + break; + case BarOneofCase.BarBytes: + BarBytes = other.BarBytes; + break; + case BarOneofCase.BarEnum: + BarEnum = other.BarEnum; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestOneof2 Clone() { + return new TestOneof2(this); + } + + /// Field number for the "foo_int" field. + public const int FooIntFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FooInt { + get { return HasFooInt ? (int) foo_ : 0; } + set { + foo_ = value; + fooCase_ = FooOneofCase.FooInt; + } + } + /// Gets whether the "foo_int" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooInt { + get { return fooCase_ == FooOneofCase.FooInt; } + } + /// Clears the value of the oneof if it's currently set to "foo_int" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooInt() { + if (HasFooInt) { + ClearFoo(); + } + } + + /// Field number for the "foo_string" field. + public const int FooStringFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string FooString { + get { return HasFooString ? (string) foo_ : ""; } + set { + foo_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + fooCase_ = FooOneofCase.FooString; + } + } + /// Gets whether the "foo_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooString { + get { return fooCase_ == FooOneofCase.FooString; } + } + /// Clears the value of the oneof if it's currently set to "foo_string" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooString() { + if (HasFooString) { + ClearFoo(); + } + } + + /// Field number for the "foo_cord" field. + public const int FooCordFieldNumber = 3; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string FooCord { + get { return HasFooCord ? (string) foo_ : ""; } + set { + foo_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + fooCase_ = FooOneofCase.FooCord; + } + } + /// Gets whether the "foo_cord" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooCord { + get { return fooCase_ == FooOneofCase.FooCord; } + } + /// Clears the value of the oneof if it's currently set to "foo_cord" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooCord() { + if (HasFooCord) { + ClearFoo(); + } + } + + /// Field number for the "foo_string_piece" field. + public const int FooStringPieceFieldNumber = 4; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string FooStringPiece { + get { return HasFooStringPiece ? (string) foo_ : ""; } + set { + foo_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + fooCase_ = FooOneofCase.FooStringPiece; + } + } + /// Gets whether the "foo_string_piece" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooStringPiece { + get { return fooCase_ == FooOneofCase.FooStringPiece; } + } + /// Clears the value of the oneof if it's currently set to "foo_string_piece" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooStringPiece() { + if (HasFooStringPiece) { + ClearFoo(); + } + } + + /// Field number for the "foo_bytes" field. + public const int FooBytesFieldNumber = 5; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString FooBytes { + get { return HasFooBytes ? (pb::ByteString) foo_ : pb::ByteString.Empty; } + set { + foo_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + fooCase_ = FooOneofCase.FooBytes; + } + } + /// Gets whether the "foo_bytes" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooBytes { + get { return fooCase_ == FooOneofCase.FooBytes; } + } + /// Clears the value of the oneof if it's currently set to "foo_bytes" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooBytes() { + if (HasFooBytes) { + ClearFoo(); + } + } + + /// Field number for the "foo_enum" field. + public const int FooEnumFieldNumber = 6; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedEnum FooEnum { + get { return HasFooEnum ? (global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedEnum) foo_ : global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedEnum.Foo; } + set { + foo_ = value; + fooCase_ = FooOneofCase.FooEnum; + } + } + /// Gets whether the "foo_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooEnum { + get { return fooCase_ == FooOneofCase.FooEnum; } + } + /// Clears the value of the oneof if it's currently set to "foo_enum" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooEnum() { + if (HasFooEnum) { + ClearFoo(); + } + } + + /// Field number for the "foo_message" field. + public const int FooMessageFieldNumber = 7; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage FooMessage { + get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage) foo_ : null; } + set { + foo_ = value; + fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooMessage; + } + } + + /// Field number for the "foogroup" field. + public const int FooGroupFieldNumber = 8; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.FooGroup FooGroup { + get { return HasFooGroup ? (global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.FooGroup) foo_ : null; } + set { + foo_ = value; + fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooGroup; + } + } + /// Gets whether the "foogroup" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooGroup { + get { return fooCase_ == FooOneofCase.FooGroup; } + } + /// Clears the value of the oneof if it's currently set to "foogroup" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooGroup() { + if (HasFooGroup) { + ClearFoo(); + } + } + + /// Field number for the "foo_lazy_message" field. + public const int FooLazyMessageFieldNumber = 11; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage FooLazyMessage { + get { return fooCase_ == FooOneofCase.FooLazyMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage) foo_ : null; } + set { + foo_ = value; + fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooLazyMessage; + } + } + + /// Field number for the "bar_int" field. + public const int BarIntFieldNumber = 12; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int BarInt { + get { return HasBarInt ? (int) bar_ : 5; } + set { + bar_ = value; + barCase_ = BarOneofCase.BarInt; + } + } + /// Gets whether the "bar_int" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBarInt { + get { return barCase_ == BarOneofCase.BarInt; } + } + /// Clears the value of the oneof if it's currently set to "bar_int" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBarInt() { + if (HasBarInt) { + ClearBar(); + } + } + + /// Field number for the "bar_string" field. + public const int BarStringFieldNumber = 13; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string BarString { + get { return HasBarString ? (string) bar_ : global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("U1RSSU5H"), 0, 6); } + set { + bar_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + barCase_ = BarOneofCase.BarString; + } + } + /// Gets whether the "bar_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBarString { + get { return barCase_ == BarOneofCase.BarString; } + } + /// Clears the value of the oneof if it's currently set to "bar_string" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBarString() { + if (HasBarString) { + ClearBar(); + } + } + + /// Field number for the "bar_cord" field. + public const int BarCordFieldNumber = 14; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string BarCord { + get { return HasBarCord ? (string) bar_ : global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("Q09SRA=="), 0, 4); } + set { + bar_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + barCase_ = BarOneofCase.BarCord; + } + } + /// Gets whether the "bar_cord" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBarCord { + get { return barCase_ == BarOneofCase.BarCord; } + } + /// Clears the value of the oneof if it's currently set to "bar_cord" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBarCord() { + if (HasBarCord) { + ClearBar(); + } + } + + /// Field number for the "bar_string_piece" field. + public const int BarStringPieceFieldNumber = 15; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string BarStringPiece { + get { return HasBarStringPiece ? (string) bar_ : global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("U1BJRUNF"), 0, 6); } + set { + bar_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + barCase_ = BarOneofCase.BarStringPiece; + } + } + /// Gets whether the "bar_string_piece" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBarStringPiece { + get { return barCase_ == BarOneofCase.BarStringPiece; } + } + /// Clears the value of the oneof if it's currently set to "bar_string_piece" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBarStringPiece() { + if (HasBarStringPiece) { + ClearBar(); + } + } + + /// Field number for the "bar_bytes" field. + public const int BarBytesFieldNumber = 16; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString BarBytes { + get { return HasBarBytes ? (pb::ByteString) bar_ : pb::ByteString.FromBase64("QllURVM="); } + set { + bar_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + barCase_ = BarOneofCase.BarBytes; + } + } + /// Gets whether the "bar_bytes" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBarBytes { + get { return barCase_ == BarOneofCase.BarBytes; } + } + /// Clears the value of the oneof if it's currently set to "bar_bytes" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBarBytes() { + if (HasBarBytes) { + ClearBar(); + } + } + + /// Field number for the "bar_enum" field. + public const int BarEnumFieldNumber = 17; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedEnum BarEnum { + get { return HasBarEnum ? (global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedEnum) bar_ : global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedEnum.Bar; } + set { + bar_ = value; + barCase_ = BarOneofCase.BarEnum; + } + } + /// Gets whether the "bar_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBarEnum { + get { return barCase_ == BarOneofCase.BarEnum; } + } + /// Clears the value of the oneof if it's currently set to "bar_enum" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBarEnum() { + if (HasBarEnum) { + ClearBar(); + } + } + + /// Field number for the "baz_int" field. + public const int BazIntFieldNumber = 18; + private readonly static int BazIntDefaultValue = 0; + + private int bazInt_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int BazInt { + get { if ((_hasBits0 & 1) != 0) { return bazInt_; } else { return BazIntDefaultValue; } } + set { + _hasBits0 |= 1; + bazInt_ = value; + } + } + /// Gets whether the "baz_int" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBazInt { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "baz_int" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBazInt() { + _hasBits0 &= ~1; + } + + /// Field number for the "baz_string" field. + public const int BazStringFieldNumber = 19; + private readonly static string BazStringDefaultValue = global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("QkFa"), 0, 3); + + private string bazString_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string BazString { + get { return bazString_ ?? BazStringDefaultValue; } + set { + bazString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "baz_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBazString { + get { return bazString_ != null; } + } + /// Clears the value of the "baz_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBazString() { + bazString_ = null; + } + + private object foo_; + /// Enum of possible cases for the "foo" oneof. + public enum FooOneofCase { + None = 0, + FooInt = 1, + FooString = 2, + FooCord = 3, + FooStringPiece = 4, + FooBytes = 5, + FooEnum = 6, + FooMessage = 7, + FooGroup = 8, + FooLazyMessage = 11, + } + private FooOneofCase fooCase_ = FooOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooOneofCase FooCase { + get { return fooCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFoo() { + fooCase_ = FooOneofCase.None; + foo_ = null; + } + + private object bar_; + /// Enum of possible cases for the "bar" oneof. + public enum BarOneofCase { + None = 0, + BarInt = 12, + BarString = 13, + BarCord = 14, + BarStringPiece = 15, + BarBytes = 16, + BarEnum = 17, + } + private BarOneofCase barCase_ = BarOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BarOneofCase BarCase { + get { return barCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBar() { + barCase_ = BarOneofCase.None; + bar_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestOneof2); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestOneof2 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (FooInt != other.FooInt) return false; + if (FooString != other.FooString) return false; + if (FooCord != other.FooCord) return false; + if (FooStringPiece != other.FooStringPiece) return false; + if (FooBytes != other.FooBytes) return false; + if (FooEnum != other.FooEnum) return false; + if (!object.Equals(FooMessage, other.FooMessage)) return false; + if (!object.Equals(FooGroup, other.FooGroup)) return false; + if (!object.Equals(FooLazyMessage, other.FooLazyMessage)) return false; + if (BarInt != other.BarInt) return false; + if (BarString != other.BarString) return false; + if (BarCord != other.BarCord) return false; + if (BarStringPiece != other.BarStringPiece) return false; + if (BarBytes != other.BarBytes) return false; + if (BarEnum != other.BarEnum) return false; + if (BazInt != other.BazInt) return false; + if (BazString != other.BazString) return false; + if (FooCase != other.FooCase) return false; + if (BarCase != other.BarCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasFooInt) hash ^= FooInt.GetHashCode(); + if (HasFooString) hash ^= FooString.GetHashCode(); + if (HasFooCord) hash ^= FooCord.GetHashCode(); + if (HasFooStringPiece) hash ^= FooStringPiece.GetHashCode(); + if (HasFooBytes) hash ^= FooBytes.GetHashCode(); + if (HasFooEnum) hash ^= FooEnum.GetHashCode(); + if (fooCase_ == FooOneofCase.FooMessage) hash ^= FooMessage.GetHashCode(); + if (HasFooGroup) hash ^= FooGroup.GetHashCode(); + if (fooCase_ == FooOneofCase.FooLazyMessage) hash ^= FooLazyMessage.GetHashCode(); + if (HasBarInt) hash ^= BarInt.GetHashCode(); + if (HasBarString) hash ^= BarString.GetHashCode(); + if (HasBarCord) hash ^= BarCord.GetHashCode(); + if (HasBarStringPiece) hash ^= BarStringPiece.GetHashCode(); + if (HasBarBytes) hash ^= BarBytes.GetHashCode(); + if (HasBarEnum) hash ^= BarEnum.GetHashCode(); + if (HasBazInt) hash ^= BazInt.GetHashCode(); + if (HasBazString) hash ^= BazString.GetHashCode(); + hash ^= (int) fooCase_; + hash ^= (int) barCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasFooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (HasFooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (HasFooCord) { + output.WriteRawTag(26); + output.WriteString(FooCord); + } + if (HasFooStringPiece) { + output.WriteRawTag(34); + output.WriteString(FooStringPiece); + } + if (HasFooBytes) { + output.WriteRawTag(42); + output.WriteBytes(FooBytes); + } + if (HasFooEnum) { + output.WriteRawTag(48); + output.WriteEnum((int) FooEnum); + } + if (fooCase_ == FooOneofCase.FooMessage) { + output.WriteRawTag(58); + output.WriteMessage(FooMessage); + } + if (HasFooGroup) { + output.WriteRawTag(67); + output.WriteGroup(FooGroup); + output.WriteRawTag(68); + } + if (fooCase_ == FooOneofCase.FooLazyMessage) { + output.WriteRawTag(90); + output.WriteMessage(FooLazyMessage); + } + if (HasBarInt) { + output.WriteRawTag(96); + output.WriteInt32(BarInt); + } + if (HasBarString) { + output.WriteRawTag(106); + output.WriteString(BarString); + } + if (HasBarCord) { + output.WriteRawTag(114); + output.WriteString(BarCord); + } + if (HasBarStringPiece) { + output.WriteRawTag(122); + output.WriteString(BarStringPiece); + } + if (HasBarBytes) { + output.WriteRawTag(130, 1); + output.WriteBytes(BarBytes); + } + if (HasBarEnum) { + output.WriteRawTag(136, 1); + output.WriteEnum((int) BarEnum); + } + if (HasBazInt) { + output.WriteRawTag(144, 1); + output.WriteInt32(BazInt); + } + if (HasBazString) { + output.WriteRawTag(154, 1); + output.WriteString(BazString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasFooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (HasFooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (HasFooCord) { + output.WriteRawTag(26); + output.WriteString(FooCord); + } + if (HasFooStringPiece) { + output.WriteRawTag(34); + output.WriteString(FooStringPiece); + } + if (HasFooBytes) { + output.WriteRawTag(42); + output.WriteBytes(FooBytes); + } + if (HasFooEnum) { + output.WriteRawTag(48); + output.WriteEnum((int) FooEnum); + } + if (fooCase_ == FooOneofCase.FooMessage) { + output.WriteRawTag(58); + output.WriteMessage(FooMessage); + } + if (HasFooGroup) { + output.WriteRawTag(67); + output.WriteGroup(FooGroup); + output.WriteRawTag(68); + } + if (fooCase_ == FooOneofCase.FooLazyMessage) { + output.WriteRawTag(90); + output.WriteMessage(FooLazyMessage); + } + if (HasBarInt) { + output.WriteRawTag(96); + output.WriteInt32(BarInt); + } + if (HasBarString) { + output.WriteRawTag(106); + output.WriteString(BarString); + } + if (HasBarCord) { + output.WriteRawTag(114); + output.WriteString(BarCord); + } + if (HasBarStringPiece) { + output.WriteRawTag(122); + output.WriteString(BarStringPiece); + } + if (HasBarBytes) { + output.WriteRawTag(130, 1); + output.WriteBytes(BarBytes); + } + if (HasBarEnum) { + output.WriteRawTag(136, 1); + output.WriteEnum((int) BarEnum); + } + if (HasBazInt) { + output.WriteRawTag(144, 1); + output.WriteInt32(BazInt); + } + if (HasBazString) { + output.WriteRawTag(154, 1); + output.WriteString(BazString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasFooInt) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(FooInt); + } + if (HasFooString) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FooString); + } + if (HasFooCord) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FooCord); + } + if (HasFooStringPiece) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FooStringPiece); + } + if (HasFooBytes) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(FooBytes); + } + if (HasFooEnum) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) FooEnum); + } + if (fooCase_ == FooOneofCase.FooMessage) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(FooMessage); + } + if (HasFooGroup) { + size += 2 + pb::CodedOutputStream.ComputeGroupSize(FooGroup); + } + if (fooCase_ == FooOneofCase.FooLazyMessage) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(FooLazyMessage); + } + if (HasBarInt) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(BarInt); + } + if (HasBarString) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(BarString); + } + if (HasBarCord) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(BarCord); + } + if (HasBarStringPiece) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(BarStringPiece); + } + if (HasBarBytes) { + size += 2 + pb::CodedOutputStream.ComputeBytesSize(BarBytes); + } + if (HasBarEnum) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) BarEnum); + } + if (HasBazInt) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(BazInt); + } + if (HasBazString) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(BazString); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestOneof2 other) { + if (other == null) { + return; + } + if (other.HasBazInt) { + BazInt = other.BazInt; + } + if (other.HasBazString) { + BazString = other.BazString; + } + switch (other.FooCase) { + case FooOneofCase.FooInt: + FooInt = other.FooInt; + break; + case FooOneofCase.FooString: + FooString = other.FooString; + break; + case FooOneofCase.FooCord: + FooCord = other.FooCord; + break; + case FooOneofCase.FooStringPiece: + FooStringPiece = other.FooStringPiece; + break; + case FooOneofCase.FooBytes: + FooBytes = other.FooBytes; + break; + case FooOneofCase.FooEnum: + FooEnum = other.FooEnum; + break; + case FooOneofCase.FooMessage: + if (FooMessage == null) { + FooMessage = new global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage(); + } + FooMessage.MergeFrom(other.FooMessage); + break; + case FooOneofCase.FooGroup: + if (FooGroup == null) { + FooGroup = new global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.FooGroup(); + } + FooGroup.MergeFrom(other.FooGroup); + break; + case FooOneofCase.FooLazyMessage: + if (FooLazyMessage == null) { + FooLazyMessage = new global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage(); + } + FooLazyMessage.MergeFrom(other.FooLazyMessage); + break; + } + + switch (other.BarCase) { + case BarOneofCase.BarInt: + BarInt = other.BarInt; + break; + case BarOneofCase.BarString: + BarString = other.BarString; + break; + case BarOneofCase.BarCord: + BarCord = other.BarCord; + break; + case BarOneofCase.BarStringPiece: + BarStringPiece = other.BarStringPiece; + break; + case BarOneofCase.BarBytes: + BarBytes = other.BarBytes; + break; + case BarOneofCase.BarEnum: + BarEnum = other.BarEnum; + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + FooInt = input.ReadInt32(); + break; + } + case 18: { + FooString = input.ReadString(); + break; + } + case 26: { + FooCord = input.ReadString(); + break; + } + case 34: { + FooStringPiece = input.ReadString(); + break; + } + case 42: { + FooBytes = input.ReadBytes(); + break; + } + case 48: { + foo_ = input.ReadEnum(); + fooCase_ = FooOneofCase.FooEnum; + break; + } + case 58: { + global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage(); + if (fooCase_ == FooOneofCase.FooMessage) { + subBuilder.MergeFrom(FooMessage); + } + input.ReadMessage(subBuilder); + FooMessage = subBuilder; + break; + } + case 67: { + global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.FooGroup subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.FooGroup(); + if (HasFooGroup) { + subBuilder.MergeFrom(FooGroup); + } + input.ReadGroup(subBuilder); + FooGroup = subBuilder; + break; + } + case 90: { + global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage(); + if (fooCase_ == FooOneofCase.FooLazyMessage) { + subBuilder.MergeFrom(FooLazyMessage); + } + input.ReadMessage(subBuilder); + FooLazyMessage = subBuilder; + break; + } + case 96: { + BarInt = input.ReadInt32(); + break; + } + case 106: { + BarString = input.ReadString(); + break; + } + case 114: { + BarCord = input.ReadString(); + break; + } + case 122: { + BarStringPiece = input.ReadString(); + break; + } + case 130: { + BarBytes = input.ReadBytes(); + break; + } + case 136: { + bar_ = input.ReadEnum(); + barCase_ = BarOneofCase.BarEnum; + break; + } + case 144: { + BazInt = input.ReadInt32(); + break; + } + case 154: { + BazString = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + FooInt = input.ReadInt32(); + break; + } + case 18: { + FooString = input.ReadString(); + break; + } + case 26: { + FooCord = input.ReadString(); + break; + } + case 34: { + FooStringPiece = input.ReadString(); + break; + } + case 42: { + FooBytes = input.ReadBytes(); + break; + } + case 48: { + foo_ = input.ReadEnum(); + fooCase_ = FooOneofCase.FooEnum; + break; + } + case 58: { + global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage(); + if (fooCase_ == FooOneofCase.FooMessage) { + subBuilder.MergeFrom(FooMessage); + } + input.ReadMessage(subBuilder); + FooMessage = subBuilder; + break; + } + case 67: { + global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.FooGroup subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.FooGroup(); + if (HasFooGroup) { + subBuilder.MergeFrom(FooGroup); + } + input.ReadGroup(subBuilder); + FooGroup = subBuilder; + break; + } + case 90: { + global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Types.NestedMessage(); + if (fooCase_ == FooOneofCase.FooLazyMessage) { + subBuilder.MergeFrom(FooLazyMessage); + } + input.ReadMessage(subBuilder); + FooLazyMessage = subBuilder; + break; + } + case 96: { + BarInt = input.ReadInt32(); + break; + } + case 106: { + BarString = input.ReadString(); + break; + } + case 114: { + BarCord = input.ReadString(); + break; + } + case 122: { + BarStringPiece = input.ReadString(); + break; + } + case 130: { + BarBytes = input.ReadBytes(); + break; + } + case 136: { + bar_ = input.ReadEnum(); + barCase_ = BarOneofCase.BarEnum; + break; + } + case 144: { + BazInt = input.ReadInt32(); + break; + } + case 154: { + BazString = input.ReadString(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestOneof2 message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum NestedEnum { + [pbr::OriginalName("FOO")] Foo = 1, + [pbr::OriginalName("BAR")] Bar = 2, + [pbr::OriginalName("BAZ")] Baz = 3, + } + + public sealed partial class FooGroup : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooGroup()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooGroup() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooGroup(FooGroup other) : this() { + _hasBits0 = other._hasBits0; + a_ = other.a_; + b_ = other.b_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooGroup Clone() { + return new FooGroup(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 9; + private readonly static int ADefaultValue = 0; + + private int a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { if ((_hasBits0 & 1) != 0) { return a_; } else { return ADefaultValue; } } + set { + _hasBits0 |= 1; + a_ = value; + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + _hasBits0 &= ~1; + } + + /// Field number for the "b" field. + public const int BFieldNumber = 10; + private readonly static string BDefaultValue = ""; + + private string b_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string B { + get { return b_ ?? BDefaultValue; } + set { + b_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "b" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasB { + get { return b_ != null; } + } + /// Clears the value of the "b" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearB() { + b_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FooGroup); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FooGroup other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + if (B != other.B) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (HasB) hash ^= B.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(72); + output.WriteInt32(A); + } + if (HasB) { + output.WriteRawTag(82); + output.WriteString(B); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(72); + output.WriteInt32(A); + } + if (HasB) { + output.WriteRawTag(82); + output.WriteString(B); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (HasB) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(B); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FooGroup other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + if (other.HasB) { + B = other.B; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 68: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 72: { + A = input.ReadInt32(); + break; + } + case 82: { + B = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 68: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 72: { + A = input.ReadInt32(); + break; + } + case 82: { + B = input.ReadString(); + break; + } + } + } + } + #endif + + } + + public sealed partial class NestedMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestOneof2.Descriptor.NestedTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + _hasBits0 = other._hasBits0; + quxInt_ = other.quxInt_; + corgeInt_ = other.corgeInt_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "qux_int" field. + public const int QuxIntFieldNumber = 1; + private readonly static long QuxIntDefaultValue = 0L; + + private long quxInt_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long QuxInt { + get { if ((_hasBits0 & 1) != 0) { return quxInt_; } else { return QuxIntDefaultValue; } } + set { + _hasBits0 |= 1; + quxInt_ = value; + } + } + /// Gets whether the "qux_int" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasQuxInt { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "qux_int" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearQuxInt() { + _hasBits0 &= ~1; + } + + /// Field number for the "corge_int" field. + public const int CorgeIntFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_corgeInt_codec + = pb::FieldCodec.ForInt32(16); + private readonly pbc::RepeatedField corgeInt_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField CorgeInt { + get { return corgeInt_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (QuxInt != other.QuxInt) return false; + if(!corgeInt_.Equals(other.corgeInt_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasQuxInt) hash ^= QuxInt.GetHashCode(); + hash ^= corgeInt_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasQuxInt) { + output.WriteRawTag(8); + output.WriteInt64(QuxInt); + } + corgeInt_.WriteTo(output, _repeated_corgeInt_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasQuxInt) { + output.WriteRawTag(8); + output.WriteInt64(QuxInt); + } + corgeInt_.WriteTo(ref output, _repeated_corgeInt_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasQuxInt) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(QuxInt); + } + size += corgeInt_.CalculateSize(_repeated_corgeInt_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.HasQuxInt) { + QuxInt = other.QuxInt; + } + corgeInt_.Add(other.corgeInt_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + QuxInt = input.ReadInt64(); + break; + } + case 18: + case 16: { + corgeInt_.AddEntriesFrom(input, _repeated_corgeInt_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + QuxInt = input.ReadInt64(); + break; + } + case 18: + case 16: { + corgeInt_.AddEntriesFrom(ref input, _repeated_corgeInt_codec); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class TestRequiredOneof : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRequiredOneof()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[46]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequiredOneof() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequiredOneof(TestRequiredOneof other) : this() { + switch (other.FooCase) { + case FooOneofCase.FooInt: + FooInt = other.FooInt; + break; + case FooOneofCase.FooString: + FooString = other.FooString; + break; + case FooOneofCase.FooMessage: + FooMessage = other.FooMessage.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequiredOneof Clone() { + return new TestRequiredOneof(this); + } + + /// Field number for the "foo_int" field. + public const int FooIntFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FooInt { + get { return HasFooInt ? (int) foo_ : 0; } + set { + foo_ = value; + fooCase_ = FooOneofCase.FooInt; + } + } + /// Gets whether the "foo_int" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooInt { + get { return fooCase_ == FooOneofCase.FooInt; } + } + /// Clears the value of the oneof if it's currently set to "foo_int" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooInt() { + if (HasFooInt) { + ClearFoo(); + } + } + + /// Field number for the "foo_string" field. + public const int FooStringFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string FooString { + get { return HasFooString ? (string) foo_ : ""; } + set { + foo_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + fooCase_ = FooOneofCase.FooString; + } + } + /// Gets whether the "foo_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFooString { + get { return fooCase_ == FooOneofCase.FooString; } + } + /// Clears the value of the oneof if it's currently set to "foo_string" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFooString() { + if (HasFooString) { + ClearFoo(); + } + } + + /// Field number for the "foo_message" field. + public const int FooMessageFieldNumber = 3; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage FooMessage { + get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage) foo_ : null; } + set { + foo_ = value; + fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooMessage; + } + } + + private object foo_; + /// Enum of possible cases for the "foo" oneof. + public enum FooOneofCase { + None = 0, + FooInt = 1, + FooString = 2, + FooMessage = 3, + } + private FooOneofCase fooCase_ = FooOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooOneofCase FooCase { + get { return fooCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFoo() { + fooCase_ = FooOneofCase.None; + foo_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestRequiredOneof); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestRequiredOneof other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (FooInt != other.FooInt) return false; + if (FooString != other.FooString) return false; + if (!object.Equals(FooMessage, other.FooMessage)) return false; + if (FooCase != other.FooCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasFooInt) hash ^= FooInt.GetHashCode(); + if (HasFooString) hash ^= FooString.GetHashCode(); + if (fooCase_ == FooOneofCase.FooMessage) hash ^= FooMessage.GetHashCode(); + hash ^= (int) fooCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasFooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (HasFooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (fooCase_ == FooOneofCase.FooMessage) { + output.WriteRawTag(26); + output.WriteMessage(FooMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasFooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (HasFooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (fooCase_ == FooOneofCase.FooMessage) { + output.WriteRawTag(26); + output.WriteMessage(FooMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasFooInt) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(FooInt); + } + if (HasFooString) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FooString); + } + if (fooCase_ == FooOneofCase.FooMessage) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(FooMessage); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestRequiredOneof other) { + if (other == null) { + return; + } + switch (other.FooCase) { + case FooOneofCase.FooInt: + FooInt = other.FooInt; + break; + case FooOneofCase.FooString: + FooString = other.FooString; + break; + case FooOneofCase.FooMessage: + if (FooMessage == null) { + FooMessage = new global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage(); + } + FooMessage.MergeFrom(other.FooMessage); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + FooInt = input.ReadInt32(); + break; + } + case 18: { + FooString = input.ReadString(); + break; + } + case 26: { + global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage(); + if (fooCase_ == FooOneofCase.FooMessage) { + subBuilder.MergeFrom(FooMessage); + } + input.ReadMessage(subBuilder); + FooMessage = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + FooInt = input.ReadInt32(); + break; + } + case 18: { + FooString = input.ReadString(); + break; + } + case 26: { + global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Types.NestedMessage(); + if (fooCase_ == FooOneofCase.FooMessage) { + subBuilder.MergeFrom(FooMessage); + } + input.ReadMessage(subBuilder); + FooMessage = subBuilder; + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestRequiredOneof message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class NestedMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestRequiredOneof.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + _hasBits0 = other._hasBits0; + requiredDouble_ = other.requiredDouble_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "required_double" field. + public const int RequiredDoubleFieldNumber = 1; + private readonly static double RequiredDoubleDefaultValue = 0D; + + private double requiredDouble_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double RequiredDouble { + get { if ((_hasBits0 & 1) != 0) { return requiredDouble_; } else { return RequiredDoubleDefaultValue; } } + set { + _hasBits0 |= 1; + requiredDouble_ = value; + } + } + /// Gets whether the "required_double" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasRequiredDouble { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "required_double" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearRequiredDouble() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(RequiredDouble, other.RequiredDouble)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasRequiredDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(RequiredDouble); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasRequiredDouble) { + output.WriteRawTag(9); + output.WriteDouble(RequiredDouble); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasRequiredDouble) { + output.WriteRawTag(9); + output.WriteDouble(RequiredDouble); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasRequiredDouble) { + size += 1 + 8; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.HasRequiredDouble) { + RequiredDouble = other.RequiredDouble; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 9: { + RequiredDouble = input.ReadDouble(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 9: { + RequiredDouble = input.ReadDouble(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class TestRequiredMap : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRequiredMap()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[47]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequiredMap() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequiredMap(TestRequiredMap other) : this() { + foo_ = other.foo_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRequiredMap Clone() { + return new TestRequiredMap(this); + } + + /// Field number for the "foo" field. + public const int FooFieldNumber = 1; + private static readonly pbc::MapField.Codec _map_foo_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.Proto2.TestRequiredMap.Types.NestedMessage.Parser), 10); + private readonly pbc::MapField foo_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField Foo { + get { return foo_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestRequiredMap); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestRequiredMap other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!Foo.Equals(other.Foo)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= Foo.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + foo_.WriteTo(output, _map_foo_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + foo_.WriteTo(ref output, _map_foo_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += foo_.CalculateSize(_map_foo_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestRequiredMap other) { + if (other == null) { + return; + } + foo_.Add(other.foo_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + foo_.AddEntriesFrom(input, _map_foo_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + foo_.AddEntriesFrom(ref input, _map_foo_codec); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestRequiredMap message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class NestedMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestRequiredMap.Descriptor.NestedTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + _hasBits0 = other._hasBits0; + requiredInt32_ = other.requiredInt32_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "required_int32" field. + public const int RequiredInt32FieldNumber = 1; + private readonly static int RequiredInt32DefaultValue = 0; + + private int requiredInt32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int RequiredInt32 { + get { if ((_hasBits0 & 1) != 0) { return requiredInt32_; } else { return RequiredInt32DefaultValue; } } + set { + _hasBits0 |= 1; + requiredInt32_ = value; + } + } + /// Gets whether the "required_int32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasRequiredInt32 { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "required_int32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearRequiredInt32() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (RequiredInt32 != other.RequiredInt32) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasRequiredInt32) hash ^= RequiredInt32.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasRequiredInt32) { + output.WriteRawTag(8); + output.WriteInt32(RequiredInt32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasRequiredInt32) { + output.WriteRawTag(8); + output.WriteInt32(RequiredInt32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasRequiredInt32) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(RequiredInt32); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.HasRequiredInt32) { + RequiredInt32 = other.RequiredInt32; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + RequiredInt32 = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + RequiredInt32 = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class TestPackedTypes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestPackedTypes()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[48]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestPackedTypes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestPackedTypes(TestPackedTypes other) : this() { + packedInt32_ = other.packedInt32_.Clone(); + packedInt64_ = other.packedInt64_.Clone(); + packedUint32_ = other.packedUint32_.Clone(); + packedUint64_ = other.packedUint64_.Clone(); + packedSint32_ = other.packedSint32_.Clone(); + packedSint64_ = other.packedSint64_.Clone(); + packedFixed32_ = other.packedFixed32_.Clone(); + packedFixed64_ = other.packedFixed64_.Clone(); + packedSfixed32_ = other.packedSfixed32_.Clone(); + packedSfixed64_ = other.packedSfixed64_.Clone(); + packedFloat_ = other.packedFloat_.Clone(); + packedDouble_ = other.packedDouble_.Clone(); + packedBool_ = other.packedBool_.Clone(); + packedEnum_ = other.packedEnum_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestPackedTypes Clone() { + return new TestPackedTypes(this); + } + + /// Field number for the "packed_int32" field. + public const int PackedInt32FieldNumber = 90; + private static readonly pb::FieldCodec _repeated_packedInt32_codec + = pb::FieldCodec.ForInt32(722); + private readonly pbc::RepeatedField packedInt32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedInt32 { + get { return packedInt32_; } + } + + /// Field number for the "packed_int64" field. + public const int PackedInt64FieldNumber = 91; + private static readonly pb::FieldCodec _repeated_packedInt64_codec + = pb::FieldCodec.ForInt64(730); + private readonly pbc::RepeatedField packedInt64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedInt64 { + get { return packedInt64_; } + } + + /// Field number for the "packed_uint32" field. + public const int PackedUint32FieldNumber = 92; + private static readonly pb::FieldCodec _repeated_packedUint32_codec + = pb::FieldCodec.ForUInt32(738); + private readonly pbc::RepeatedField packedUint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedUint32 { + get { return packedUint32_; } + } + + /// Field number for the "packed_uint64" field. + public const int PackedUint64FieldNumber = 93; + private static readonly pb::FieldCodec _repeated_packedUint64_codec + = pb::FieldCodec.ForUInt64(746); + private readonly pbc::RepeatedField packedUint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedUint64 { + get { return packedUint64_; } + } + + /// Field number for the "packed_sint32" field. + public const int PackedSint32FieldNumber = 94; + private static readonly pb::FieldCodec _repeated_packedSint32_codec + = pb::FieldCodec.ForSInt32(754); + private readonly pbc::RepeatedField packedSint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSint32 { + get { return packedSint32_; } + } + + /// Field number for the "packed_sint64" field. + public const int PackedSint64FieldNumber = 95; + private static readonly pb::FieldCodec _repeated_packedSint64_codec + = pb::FieldCodec.ForSInt64(762); + private readonly pbc::RepeatedField packedSint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSint64 { + get { return packedSint64_; } + } + + /// Field number for the "packed_fixed32" field. + public const int PackedFixed32FieldNumber = 96; + private static readonly pb::FieldCodec _repeated_packedFixed32_codec + = pb::FieldCodec.ForFixed32(770); + private readonly pbc::RepeatedField packedFixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedFixed32 { + get { return packedFixed32_; } + } + + /// Field number for the "packed_fixed64" field. + public const int PackedFixed64FieldNumber = 97; + private static readonly pb::FieldCodec _repeated_packedFixed64_codec + = pb::FieldCodec.ForFixed64(778); + private readonly pbc::RepeatedField packedFixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedFixed64 { + get { return packedFixed64_; } + } + + /// Field number for the "packed_sfixed32" field. + public const int PackedSfixed32FieldNumber = 98; + private static readonly pb::FieldCodec _repeated_packedSfixed32_codec + = pb::FieldCodec.ForSFixed32(786); + private readonly pbc::RepeatedField packedSfixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSfixed32 { + get { return packedSfixed32_; } + } + + /// Field number for the "packed_sfixed64" field. + public const int PackedSfixed64FieldNumber = 99; + private static readonly pb::FieldCodec _repeated_packedSfixed64_codec + = pb::FieldCodec.ForSFixed64(794); + private readonly pbc::RepeatedField packedSfixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSfixed64 { + get { return packedSfixed64_; } + } + + /// Field number for the "packed_float" field. + public const int PackedFloatFieldNumber = 100; + private static readonly pb::FieldCodec _repeated_packedFloat_codec + = pb::FieldCodec.ForFloat(802); + private readonly pbc::RepeatedField packedFloat_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedFloat { + get { return packedFloat_; } + } + + /// Field number for the "packed_double" field. + public const int PackedDoubleFieldNumber = 101; + private static readonly pb::FieldCodec _repeated_packedDouble_codec + = pb::FieldCodec.ForDouble(810); + private readonly pbc::RepeatedField packedDouble_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedDouble { + get { return packedDouble_; } + } + + /// Field number for the "packed_bool" field. + public const int PackedBoolFieldNumber = 102; + private static readonly pb::FieldCodec _repeated_packedBool_codec + = pb::FieldCodec.ForBool(818); + private readonly pbc::RepeatedField packedBool_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedBool { + get { return packedBool_; } + } + + /// Field number for the "packed_enum" field. + public const int PackedEnumFieldNumber = 103; + private static readonly pb::FieldCodec _repeated_packedEnum_codec + = pb::FieldCodec.ForEnum(826, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) x); + private readonly pbc::RepeatedField packedEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedEnum { + get { return packedEnum_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestPackedTypes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestPackedTypes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!packedInt32_.Equals(other.packedInt32_)) return false; + if(!packedInt64_.Equals(other.packedInt64_)) return false; + if(!packedUint32_.Equals(other.packedUint32_)) return false; + if(!packedUint64_.Equals(other.packedUint64_)) return false; + if(!packedSint32_.Equals(other.packedSint32_)) return false; + if(!packedSint64_.Equals(other.packedSint64_)) return false; + if(!packedFixed32_.Equals(other.packedFixed32_)) return false; + if(!packedFixed64_.Equals(other.packedFixed64_)) return false; + if(!packedSfixed32_.Equals(other.packedSfixed32_)) return false; + if(!packedSfixed64_.Equals(other.packedSfixed64_)) return false; + if(!packedFloat_.Equals(other.packedFloat_)) return false; + if(!packedDouble_.Equals(other.packedDouble_)) return false; + if(!packedBool_.Equals(other.packedBool_)) return false; + if(!packedEnum_.Equals(other.packedEnum_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= packedInt32_.GetHashCode(); + hash ^= packedInt64_.GetHashCode(); + hash ^= packedUint32_.GetHashCode(); + hash ^= packedUint64_.GetHashCode(); + hash ^= packedSint32_.GetHashCode(); + hash ^= packedSint64_.GetHashCode(); + hash ^= packedFixed32_.GetHashCode(); + hash ^= packedFixed64_.GetHashCode(); + hash ^= packedSfixed32_.GetHashCode(); + hash ^= packedSfixed64_.GetHashCode(); + hash ^= packedFloat_.GetHashCode(); + hash ^= packedDouble_.GetHashCode(); + hash ^= packedBool_.GetHashCode(); + hash ^= packedEnum_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + packedInt32_.WriteTo(output, _repeated_packedInt32_codec); + packedInt64_.WriteTo(output, _repeated_packedInt64_codec); + packedUint32_.WriteTo(output, _repeated_packedUint32_codec); + packedUint64_.WriteTo(output, _repeated_packedUint64_codec); + packedSint32_.WriteTo(output, _repeated_packedSint32_codec); + packedSint64_.WriteTo(output, _repeated_packedSint64_codec); + packedFixed32_.WriteTo(output, _repeated_packedFixed32_codec); + packedFixed64_.WriteTo(output, _repeated_packedFixed64_codec); + packedSfixed32_.WriteTo(output, _repeated_packedSfixed32_codec); + packedSfixed64_.WriteTo(output, _repeated_packedSfixed64_codec); + packedFloat_.WriteTo(output, _repeated_packedFloat_codec); + packedDouble_.WriteTo(output, _repeated_packedDouble_codec); + packedBool_.WriteTo(output, _repeated_packedBool_codec); + packedEnum_.WriteTo(output, _repeated_packedEnum_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec); + packedInt64_.WriteTo(ref output, _repeated_packedInt64_codec); + packedUint32_.WriteTo(ref output, _repeated_packedUint32_codec); + packedUint64_.WriteTo(ref output, _repeated_packedUint64_codec); + packedSint32_.WriteTo(ref output, _repeated_packedSint32_codec); + packedSint64_.WriteTo(ref output, _repeated_packedSint64_codec); + packedFixed32_.WriteTo(ref output, _repeated_packedFixed32_codec); + packedFixed64_.WriteTo(ref output, _repeated_packedFixed64_codec); + packedSfixed32_.WriteTo(ref output, _repeated_packedSfixed32_codec); + packedSfixed64_.WriteTo(ref output, _repeated_packedSfixed64_codec); + packedFloat_.WriteTo(ref output, _repeated_packedFloat_codec); + packedDouble_.WriteTo(ref output, _repeated_packedDouble_codec); + packedBool_.WriteTo(ref output, _repeated_packedBool_codec); + packedEnum_.WriteTo(ref output, _repeated_packedEnum_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += packedInt32_.CalculateSize(_repeated_packedInt32_codec); + size += packedInt64_.CalculateSize(_repeated_packedInt64_codec); + size += packedUint32_.CalculateSize(_repeated_packedUint32_codec); + size += packedUint64_.CalculateSize(_repeated_packedUint64_codec); + size += packedSint32_.CalculateSize(_repeated_packedSint32_codec); + size += packedSint64_.CalculateSize(_repeated_packedSint64_codec); + size += packedFixed32_.CalculateSize(_repeated_packedFixed32_codec); + size += packedFixed64_.CalculateSize(_repeated_packedFixed64_codec); + size += packedSfixed32_.CalculateSize(_repeated_packedSfixed32_codec); + size += packedSfixed64_.CalculateSize(_repeated_packedSfixed64_codec); + size += packedFloat_.CalculateSize(_repeated_packedFloat_codec); + size += packedDouble_.CalculateSize(_repeated_packedDouble_codec); + size += packedBool_.CalculateSize(_repeated_packedBool_codec); + size += packedEnum_.CalculateSize(_repeated_packedEnum_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestPackedTypes other) { + if (other == null) { + return; + } + packedInt32_.Add(other.packedInt32_); + packedInt64_.Add(other.packedInt64_); + packedUint32_.Add(other.packedUint32_); + packedUint64_.Add(other.packedUint64_); + packedSint32_.Add(other.packedSint32_); + packedSint64_.Add(other.packedSint64_); + packedFixed32_.Add(other.packedFixed32_); + packedFixed64_.Add(other.packedFixed64_); + packedSfixed32_.Add(other.packedSfixed32_); + packedSfixed64_.Add(other.packedSfixed64_); + packedFloat_.Add(other.packedFloat_); + packedDouble_.Add(other.packedDouble_); + packedBool_.Add(other.packedBool_); + packedEnum_.Add(other.packedEnum_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 722: + case 720: { + packedInt32_.AddEntriesFrom(input, _repeated_packedInt32_codec); + break; + } + case 730: + case 728: { + packedInt64_.AddEntriesFrom(input, _repeated_packedInt64_codec); + break; + } + case 738: + case 736: { + packedUint32_.AddEntriesFrom(input, _repeated_packedUint32_codec); + break; + } + case 746: + case 744: { + packedUint64_.AddEntriesFrom(input, _repeated_packedUint64_codec); + break; + } + case 754: + case 752: { + packedSint32_.AddEntriesFrom(input, _repeated_packedSint32_codec); + break; + } + case 762: + case 760: { + packedSint64_.AddEntriesFrom(input, _repeated_packedSint64_codec); + break; + } + case 770: + case 773: { + packedFixed32_.AddEntriesFrom(input, _repeated_packedFixed32_codec); + break; + } + case 778: + case 777: { + packedFixed64_.AddEntriesFrom(input, _repeated_packedFixed64_codec); + break; + } + case 786: + case 789: { + packedSfixed32_.AddEntriesFrom(input, _repeated_packedSfixed32_codec); + break; + } + case 794: + case 793: { + packedSfixed64_.AddEntriesFrom(input, _repeated_packedSfixed64_codec); + break; + } + case 802: + case 805: { + packedFloat_.AddEntriesFrom(input, _repeated_packedFloat_codec); + break; + } + case 810: + case 809: { + packedDouble_.AddEntriesFrom(input, _repeated_packedDouble_codec); + break; + } + case 818: + case 816: { + packedBool_.AddEntriesFrom(input, _repeated_packedBool_codec); + break; + } + case 826: + case 824: { + packedEnum_.AddEntriesFrom(input, _repeated_packedEnum_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 722: + case 720: { + packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec); + break; + } + case 730: + case 728: { + packedInt64_.AddEntriesFrom(ref input, _repeated_packedInt64_codec); + break; + } + case 738: + case 736: { + packedUint32_.AddEntriesFrom(ref input, _repeated_packedUint32_codec); + break; + } + case 746: + case 744: { + packedUint64_.AddEntriesFrom(ref input, _repeated_packedUint64_codec); + break; + } + case 754: + case 752: { + packedSint32_.AddEntriesFrom(ref input, _repeated_packedSint32_codec); + break; + } + case 762: + case 760: { + packedSint64_.AddEntriesFrom(ref input, _repeated_packedSint64_codec); + break; + } + case 770: + case 773: { + packedFixed32_.AddEntriesFrom(ref input, _repeated_packedFixed32_codec); + break; + } + case 778: + case 777: { + packedFixed64_.AddEntriesFrom(ref input, _repeated_packedFixed64_codec); + break; + } + case 786: + case 789: { + packedSfixed32_.AddEntriesFrom(ref input, _repeated_packedSfixed32_codec); + break; + } + case 794: + case 793: { + packedSfixed64_.AddEntriesFrom(ref input, _repeated_packedSfixed64_codec); + break; + } + case 802: + case 805: { + packedFloat_.AddEntriesFrom(ref input, _repeated_packedFloat_codec); + break; + } + case 810: + case 809: { + packedDouble_.AddEntriesFrom(ref input, _repeated_packedDouble_codec); + break; + } + case 818: + case 816: { + packedBool_.AddEntriesFrom(ref input, _repeated_packedBool_codec); + break; + } + case 826: + case 824: { + packedEnum_.AddEntriesFrom(ref input, _repeated_packedEnum_codec); + break; + } + } + } + } + #endif + + } + + /// + /// A message with the same fields as TestPackedTypes, but without packing. Used + /// to test packed <-> unpacked wire compatibility. + /// + public sealed partial class TestUnpackedTypes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestUnpackedTypes()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[49]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestUnpackedTypes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestUnpackedTypes(TestUnpackedTypes other) : this() { + unpackedInt32_ = other.unpackedInt32_.Clone(); + unpackedInt64_ = other.unpackedInt64_.Clone(); + unpackedUint32_ = other.unpackedUint32_.Clone(); + unpackedUint64_ = other.unpackedUint64_.Clone(); + unpackedSint32_ = other.unpackedSint32_.Clone(); + unpackedSint64_ = other.unpackedSint64_.Clone(); + unpackedFixed32_ = other.unpackedFixed32_.Clone(); + unpackedFixed64_ = other.unpackedFixed64_.Clone(); + unpackedSfixed32_ = other.unpackedSfixed32_.Clone(); + unpackedSfixed64_ = other.unpackedSfixed64_.Clone(); + unpackedFloat_ = other.unpackedFloat_.Clone(); + unpackedDouble_ = other.unpackedDouble_.Clone(); + unpackedBool_ = other.unpackedBool_.Clone(); + unpackedEnum_ = other.unpackedEnum_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestUnpackedTypes Clone() { + return new TestUnpackedTypes(this); + } + + /// Field number for the "unpacked_int32" field. + public const int UnpackedInt32FieldNumber = 90; + private static readonly pb::FieldCodec _repeated_unpackedInt32_codec + = pb::FieldCodec.ForInt32(720); + private readonly pbc::RepeatedField unpackedInt32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedInt32 { + get { return unpackedInt32_; } + } + + /// Field number for the "unpacked_int64" field. + public const int UnpackedInt64FieldNumber = 91; + private static readonly pb::FieldCodec _repeated_unpackedInt64_codec + = pb::FieldCodec.ForInt64(728); + private readonly pbc::RepeatedField unpackedInt64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedInt64 { + get { return unpackedInt64_; } + } + + /// Field number for the "unpacked_uint32" field. + public const int UnpackedUint32FieldNumber = 92; + private static readonly pb::FieldCodec _repeated_unpackedUint32_codec + = pb::FieldCodec.ForUInt32(736); + private readonly pbc::RepeatedField unpackedUint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedUint32 { + get { return unpackedUint32_; } + } + + /// Field number for the "unpacked_uint64" field. + public const int UnpackedUint64FieldNumber = 93; + private static readonly pb::FieldCodec _repeated_unpackedUint64_codec + = pb::FieldCodec.ForUInt64(744); + private readonly pbc::RepeatedField unpackedUint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedUint64 { + get { return unpackedUint64_; } + } + + /// Field number for the "unpacked_sint32" field. + public const int UnpackedSint32FieldNumber = 94; + private static readonly pb::FieldCodec _repeated_unpackedSint32_codec + = pb::FieldCodec.ForSInt32(752); + private readonly pbc::RepeatedField unpackedSint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSint32 { + get { return unpackedSint32_; } + } + + /// Field number for the "unpacked_sint64" field. + public const int UnpackedSint64FieldNumber = 95; + private static readonly pb::FieldCodec _repeated_unpackedSint64_codec + = pb::FieldCodec.ForSInt64(760); + private readonly pbc::RepeatedField unpackedSint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSint64 { + get { return unpackedSint64_; } + } + + /// Field number for the "unpacked_fixed32" field. + public const int UnpackedFixed32FieldNumber = 96; + private static readonly pb::FieldCodec _repeated_unpackedFixed32_codec + = pb::FieldCodec.ForFixed32(773); + private readonly pbc::RepeatedField unpackedFixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedFixed32 { + get { return unpackedFixed32_; } + } + + /// Field number for the "unpacked_fixed64" field. + public const int UnpackedFixed64FieldNumber = 97; + private static readonly pb::FieldCodec _repeated_unpackedFixed64_codec + = pb::FieldCodec.ForFixed64(777); + private readonly pbc::RepeatedField unpackedFixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedFixed64 { + get { return unpackedFixed64_; } + } + + /// Field number for the "unpacked_sfixed32" field. + public const int UnpackedSfixed32FieldNumber = 98; + private static readonly pb::FieldCodec _repeated_unpackedSfixed32_codec + = pb::FieldCodec.ForSFixed32(789); + private readonly pbc::RepeatedField unpackedSfixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSfixed32 { + get { return unpackedSfixed32_; } + } + + /// Field number for the "unpacked_sfixed64" field. + public const int UnpackedSfixed64FieldNumber = 99; + private static readonly pb::FieldCodec _repeated_unpackedSfixed64_codec + = pb::FieldCodec.ForSFixed64(793); + private readonly pbc::RepeatedField unpackedSfixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSfixed64 { + get { return unpackedSfixed64_; } + } + + /// Field number for the "unpacked_float" field. + public const int UnpackedFloatFieldNumber = 100; + private static readonly pb::FieldCodec _repeated_unpackedFloat_codec + = pb::FieldCodec.ForFloat(805); + private readonly pbc::RepeatedField unpackedFloat_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedFloat { + get { return unpackedFloat_; } + } + + /// Field number for the "unpacked_double" field. + public const int UnpackedDoubleFieldNumber = 101; + private static readonly pb::FieldCodec _repeated_unpackedDouble_codec + = pb::FieldCodec.ForDouble(809); + private readonly pbc::RepeatedField unpackedDouble_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedDouble { + get { return unpackedDouble_; } + } + + /// Field number for the "unpacked_bool" field. + public const int UnpackedBoolFieldNumber = 102; + private static readonly pb::FieldCodec _repeated_unpackedBool_codec + = pb::FieldCodec.ForBool(816); + private readonly pbc::RepeatedField unpackedBool_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedBool { + get { return unpackedBool_; } + } + + /// Field number for the "unpacked_enum" field. + public const int UnpackedEnumFieldNumber = 103; + private static readonly pb::FieldCodec _repeated_unpackedEnum_codec + = pb::FieldCodec.ForEnum(824, x => (int) x, x => (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) x); + private readonly pbc::RepeatedField unpackedEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedEnum { + get { return unpackedEnum_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestUnpackedTypes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestUnpackedTypes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!unpackedInt32_.Equals(other.unpackedInt32_)) return false; + if(!unpackedInt64_.Equals(other.unpackedInt64_)) return false; + if(!unpackedUint32_.Equals(other.unpackedUint32_)) return false; + if(!unpackedUint64_.Equals(other.unpackedUint64_)) return false; + if(!unpackedSint32_.Equals(other.unpackedSint32_)) return false; + if(!unpackedSint64_.Equals(other.unpackedSint64_)) return false; + if(!unpackedFixed32_.Equals(other.unpackedFixed32_)) return false; + if(!unpackedFixed64_.Equals(other.unpackedFixed64_)) return false; + if(!unpackedSfixed32_.Equals(other.unpackedSfixed32_)) return false; + if(!unpackedSfixed64_.Equals(other.unpackedSfixed64_)) return false; + if(!unpackedFloat_.Equals(other.unpackedFloat_)) return false; + if(!unpackedDouble_.Equals(other.unpackedDouble_)) return false; + if(!unpackedBool_.Equals(other.unpackedBool_)) return false; + if(!unpackedEnum_.Equals(other.unpackedEnum_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= unpackedInt32_.GetHashCode(); + hash ^= unpackedInt64_.GetHashCode(); + hash ^= unpackedUint32_.GetHashCode(); + hash ^= unpackedUint64_.GetHashCode(); + hash ^= unpackedSint32_.GetHashCode(); + hash ^= unpackedSint64_.GetHashCode(); + hash ^= unpackedFixed32_.GetHashCode(); + hash ^= unpackedFixed64_.GetHashCode(); + hash ^= unpackedSfixed32_.GetHashCode(); + hash ^= unpackedSfixed64_.GetHashCode(); + hash ^= unpackedFloat_.GetHashCode(); + hash ^= unpackedDouble_.GetHashCode(); + hash ^= unpackedBool_.GetHashCode(); + hash ^= unpackedEnum_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + unpackedInt32_.WriteTo(output, _repeated_unpackedInt32_codec); + unpackedInt64_.WriteTo(output, _repeated_unpackedInt64_codec); + unpackedUint32_.WriteTo(output, _repeated_unpackedUint32_codec); + unpackedUint64_.WriteTo(output, _repeated_unpackedUint64_codec); + unpackedSint32_.WriteTo(output, _repeated_unpackedSint32_codec); + unpackedSint64_.WriteTo(output, _repeated_unpackedSint64_codec); + unpackedFixed32_.WriteTo(output, _repeated_unpackedFixed32_codec); + unpackedFixed64_.WriteTo(output, _repeated_unpackedFixed64_codec); + unpackedSfixed32_.WriteTo(output, _repeated_unpackedSfixed32_codec); + unpackedSfixed64_.WriteTo(output, _repeated_unpackedSfixed64_codec); + unpackedFloat_.WriteTo(output, _repeated_unpackedFloat_codec); + unpackedDouble_.WriteTo(output, _repeated_unpackedDouble_codec); + unpackedBool_.WriteTo(output, _repeated_unpackedBool_codec); + unpackedEnum_.WriteTo(output, _repeated_unpackedEnum_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + unpackedInt32_.WriteTo(ref output, _repeated_unpackedInt32_codec); + unpackedInt64_.WriteTo(ref output, _repeated_unpackedInt64_codec); + unpackedUint32_.WriteTo(ref output, _repeated_unpackedUint32_codec); + unpackedUint64_.WriteTo(ref output, _repeated_unpackedUint64_codec); + unpackedSint32_.WriteTo(ref output, _repeated_unpackedSint32_codec); + unpackedSint64_.WriteTo(ref output, _repeated_unpackedSint64_codec); + unpackedFixed32_.WriteTo(ref output, _repeated_unpackedFixed32_codec); + unpackedFixed64_.WriteTo(ref output, _repeated_unpackedFixed64_codec); + unpackedSfixed32_.WriteTo(ref output, _repeated_unpackedSfixed32_codec); + unpackedSfixed64_.WriteTo(ref output, _repeated_unpackedSfixed64_codec); + unpackedFloat_.WriteTo(ref output, _repeated_unpackedFloat_codec); + unpackedDouble_.WriteTo(ref output, _repeated_unpackedDouble_codec); + unpackedBool_.WriteTo(ref output, _repeated_unpackedBool_codec); + unpackedEnum_.WriteTo(ref output, _repeated_unpackedEnum_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += unpackedInt32_.CalculateSize(_repeated_unpackedInt32_codec); + size += unpackedInt64_.CalculateSize(_repeated_unpackedInt64_codec); + size += unpackedUint32_.CalculateSize(_repeated_unpackedUint32_codec); + size += unpackedUint64_.CalculateSize(_repeated_unpackedUint64_codec); + size += unpackedSint32_.CalculateSize(_repeated_unpackedSint32_codec); + size += unpackedSint64_.CalculateSize(_repeated_unpackedSint64_codec); + size += unpackedFixed32_.CalculateSize(_repeated_unpackedFixed32_codec); + size += unpackedFixed64_.CalculateSize(_repeated_unpackedFixed64_codec); + size += unpackedSfixed32_.CalculateSize(_repeated_unpackedSfixed32_codec); + size += unpackedSfixed64_.CalculateSize(_repeated_unpackedSfixed64_codec); + size += unpackedFloat_.CalculateSize(_repeated_unpackedFloat_codec); + size += unpackedDouble_.CalculateSize(_repeated_unpackedDouble_codec); + size += unpackedBool_.CalculateSize(_repeated_unpackedBool_codec); + size += unpackedEnum_.CalculateSize(_repeated_unpackedEnum_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestUnpackedTypes other) { + if (other == null) { + return; + } + unpackedInt32_.Add(other.unpackedInt32_); + unpackedInt64_.Add(other.unpackedInt64_); + unpackedUint32_.Add(other.unpackedUint32_); + unpackedUint64_.Add(other.unpackedUint64_); + unpackedSint32_.Add(other.unpackedSint32_); + unpackedSint64_.Add(other.unpackedSint64_); + unpackedFixed32_.Add(other.unpackedFixed32_); + unpackedFixed64_.Add(other.unpackedFixed64_); + unpackedSfixed32_.Add(other.unpackedSfixed32_); + unpackedSfixed64_.Add(other.unpackedSfixed64_); + unpackedFloat_.Add(other.unpackedFloat_); + unpackedDouble_.Add(other.unpackedDouble_); + unpackedBool_.Add(other.unpackedBool_); + unpackedEnum_.Add(other.unpackedEnum_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 722: + case 720: { + unpackedInt32_.AddEntriesFrom(input, _repeated_unpackedInt32_codec); + break; + } + case 730: + case 728: { + unpackedInt64_.AddEntriesFrom(input, _repeated_unpackedInt64_codec); + break; + } + case 738: + case 736: { + unpackedUint32_.AddEntriesFrom(input, _repeated_unpackedUint32_codec); + break; + } + case 746: + case 744: { + unpackedUint64_.AddEntriesFrom(input, _repeated_unpackedUint64_codec); + break; + } + case 754: + case 752: { + unpackedSint32_.AddEntriesFrom(input, _repeated_unpackedSint32_codec); + break; + } + case 762: + case 760: { + unpackedSint64_.AddEntriesFrom(input, _repeated_unpackedSint64_codec); + break; + } + case 770: + case 773: { + unpackedFixed32_.AddEntriesFrom(input, _repeated_unpackedFixed32_codec); + break; + } + case 778: + case 777: { + unpackedFixed64_.AddEntriesFrom(input, _repeated_unpackedFixed64_codec); + break; + } + case 786: + case 789: { + unpackedSfixed32_.AddEntriesFrom(input, _repeated_unpackedSfixed32_codec); + break; + } + case 794: + case 793: { + unpackedSfixed64_.AddEntriesFrom(input, _repeated_unpackedSfixed64_codec); + break; + } + case 802: + case 805: { + unpackedFloat_.AddEntriesFrom(input, _repeated_unpackedFloat_codec); + break; + } + case 810: + case 809: { + unpackedDouble_.AddEntriesFrom(input, _repeated_unpackedDouble_codec); + break; + } + case 818: + case 816: { + unpackedBool_.AddEntriesFrom(input, _repeated_unpackedBool_codec); + break; + } + case 826: + case 824: { + unpackedEnum_.AddEntriesFrom(input, _repeated_unpackedEnum_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 722: + case 720: { + unpackedInt32_.AddEntriesFrom(ref input, _repeated_unpackedInt32_codec); + break; + } + case 730: + case 728: { + unpackedInt64_.AddEntriesFrom(ref input, _repeated_unpackedInt64_codec); + break; + } + case 738: + case 736: { + unpackedUint32_.AddEntriesFrom(ref input, _repeated_unpackedUint32_codec); + break; + } + case 746: + case 744: { + unpackedUint64_.AddEntriesFrom(ref input, _repeated_unpackedUint64_codec); + break; + } + case 754: + case 752: { + unpackedSint32_.AddEntriesFrom(ref input, _repeated_unpackedSint32_codec); + break; + } + case 762: + case 760: { + unpackedSint64_.AddEntriesFrom(ref input, _repeated_unpackedSint64_codec); + break; + } + case 770: + case 773: { + unpackedFixed32_.AddEntriesFrom(ref input, _repeated_unpackedFixed32_codec); + break; + } + case 778: + case 777: { + unpackedFixed64_.AddEntriesFrom(ref input, _repeated_unpackedFixed64_codec); + break; + } + case 786: + case 789: { + unpackedSfixed32_.AddEntriesFrom(ref input, _repeated_unpackedSfixed32_codec); + break; + } + case 794: + case 793: { + unpackedSfixed64_.AddEntriesFrom(ref input, _repeated_unpackedSfixed64_codec); + break; + } + case 802: + case 805: { + unpackedFloat_.AddEntriesFrom(ref input, _repeated_unpackedFloat_codec); + break; + } + case 810: + case 809: { + unpackedDouble_.AddEntriesFrom(ref input, _repeated_unpackedDouble_codec); + break; + } + case 818: + case 816: { + unpackedBool_.AddEntriesFrom(ref input, _repeated_unpackedBool_codec); + break; + } + case 826: + case 824: { + unpackedEnum_.AddEntriesFrom(ref input, _repeated_unpackedEnum_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestPackedExtensions : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestPackedExtensions()); + private pb::UnknownFieldSet _unknownFields; + private pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[50]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestPackedExtensions() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestPackedExtensions(TestPackedExtensions other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestPackedExtensions Clone() { + return new TestPackedExtensions(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestPackedExtensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestPackedExtensions other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestPackedExtensions other) { + if (other == null) { + return; + } + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + + } + + public sealed partial class TestUnpackedExtensions : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestUnpackedExtensions()); + private pb::UnknownFieldSet _unknownFields; + private pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[51]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestUnpackedExtensions() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestUnpackedExtensions(TestUnpackedExtensions other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestUnpackedExtensions Clone() { + return new TestUnpackedExtensions(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestUnpackedExtensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestUnpackedExtensions other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestUnpackedExtensions other) { + if (other == null) { + return; + } + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + + } + + /// + /// Used by ExtensionSetTest/DynamicExtensions. The test actually builds + /// a set of extensions to TestAllExtensions dynamically, based on the fields + /// of this message type. + /// + public sealed partial class TestDynamicExtensions : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestDynamicExtensions()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[52]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDynamicExtensions() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDynamicExtensions(TestDynamicExtensions other) : this() { + _hasBits0 = other._hasBits0; + scalarExtension_ = other.scalarExtension_; + enumExtension_ = other.enumExtension_; + dynamicEnumExtension_ = other.dynamicEnumExtension_; + messageExtension_ = other.messageExtension_ != null ? other.messageExtension_.Clone() : null; + dynamicMessageExtension_ = other.dynamicMessageExtension_ != null ? other.dynamicMessageExtension_.Clone() : null; + repeatedExtension_ = other.repeatedExtension_.Clone(); + packedExtension_ = other.packedExtension_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDynamicExtensions Clone() { + return new TestDynamicExtensions(this); + } + + /// Field number for the "scalar_extension" field. + public const int ScalarExtensionFieldNumber = 2000; + private readonly static uint ScalarExtensionDefaultValue = 0; + + private uint scalarExtension_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint ScalarExtension { + get { if ((_hasBits0 & 1) != 0) { return scalarExtension_; } else { return ScalarExtensionDefaultValue; } } + set { + _hasBits0 |= 1; + scalarExtension_ = value; + } + } + /// Gets whether the "scalar_extension" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasScalarExtension { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "scalar_extension" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearScalarExtension() { + _hasBits0 &= ~1; + } + + /// Field number for the "enum_extension" field. + public const int EnumExtensionFieldNumber = 2001; + private readonly static global::Google.Protobuf.TestProtos.Proto2.ForeignEnum EnumExtensionDefaultValue = global::Google.Protobuf.TestProtos.Proto2.ForeignEnum.ForeignFoo; + + private global::Google.Protobuf.TestProtos.Proto2.ForeignEnum enumExtension_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.ForeignEnum EnumExtension { + get { if ((_hasBits0 & 2) != 0) { return enumExtension_; } else { return EnumExtensionDefaultValue; } } + set { + _hasBits0 |= 2; + enumExtension_ = value; + } + } + /// Gets whether the "enum_extension" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasEnumExtension { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "enum_extension" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearEnumExtension() { + _hasBits0 &= ~2; + } + + /// Field number for the "dynamic_enum_extension" field. + public const int DynamicEnumExtensionFieldNumber = 2002; + private readonly static global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicEnumType DynamicEnumExtensionDefaultValue = global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicEnumType.DynamicFoo; + + private global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicEnumType dynamicEnumExtension_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicEnumType DynamicEnumExtension { + get { if ((_hasBits0 & 4) != 0) { return dynamicEnumExtension_; } else { return DynamicEnumExtensionDefaultValue; } } + set { + _hasBits0 |= 4; + dynamicEnumExtension_ = value; + } + } + /// Gets whether the "dynamic_enum_extension" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDynamicEnumExtension { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "dynamic_enum_extension" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDynamicEnumExtension() { + _hasBits0 &= ~4; + } + + /// Field number for the "message_extension" field. + public const int MessageExtensionFieldNumber = 2003; + private global::Google.Protobuf.TestProtos.Proto2.ForeignMessage messageExtension_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.ForeignMessage MessageExtension { + get { return messageExtension_; } + set { + messageExtension_ = value; + } + } + + /// Field number for the "dynamic_message_extension" field. + public const int DynamicMessageExtensionFieldNumber = 2004; + private global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicMessageType dynamicMessageExtension_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicMessageType DynamicMessageExtension { + get { return dynamicMessageExtension_; } + set { + dynamicMessageExtension_ = value; + } + } + + /// Field number for the "repeated_extension" field. + public const int RepeatedExtensionFieldNumber = 2005; + private static readonly pb::FieldCodec _repeated_repeatedExtension_codec + = pb::FieldCodec.ForString(16042); + private readonly pbc::RepeatedField repeatedExtension_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedExtension { + get { return repeatedExtension_; } + } + + /// Field number for the "packed_extension" field. + public const int PackedExtensionFieldNumber = 2006; + private static readonly pb::FieldCodec _repeated_packedExtension_codec + = pb::FieldCodec.ForSInt32(16050); + private readonly pbc::RepeatedField packedExtension_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedExtension { + get { return packedExtension_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestDynamicExtensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestDynamicExtensions other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ScalarExtension != other.ScalarExtension) return false; + if (EnumExtension != other.EnumExtension) return false; + if (DynamicEnumExtension != other.DynamicEnumExtension) return false; + if (!object.Equals(MessageExtension, other.MessageExtension)) return false; + if (!object.Equals(DynamicMessageExtension, other.DynamicMessageExtension)) return false; + if(!repeatedExtension_.Equals(other.repeatedExtension_)) return false; + if(!packedExtension_.Equals(other.packedExtension_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasScalarExtension) hash ^= ScalarExtension.GetHashCode(); + if (HasEnumExtension) hash ^= EnumExtension.GetHashCode(); + if (HasDynamicEnumExtension) hash ^= DynamicEnumExtension.GetHashCode(); + if (messageExtension_ != null) hash ^= MessageExtension.GetHashCode(); + if (dynamicMessageExtension_ != null) hash ^= DynamicMessageExtension.GetHashCode(); + hash ^= repeatedExtension_.GetHashCode(); + hash ^= packedExtension_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasScalarExtension) { + output.WriteRawTag(133, 125); + output.WriteFixed32(ScalarExtension); + } + if (HasEnumExtension) { + output.WriteRawTag(136, 125); + output.WriteEnum((int) EnumExtension); + } + if (HasDynamicEnumExtension) { + output.WriteRawTag(144, 125); + output.WriteEnum((int) DynamicEnumExtension); + } + if (messageExtension_ != null) { + output.WriteRawTag(154, 125); + output.WriteMessage(MessageExtension); + } + if (dynamicMessageExtension_ != null) { + output.WriteRawTag(162, 125); + output.WriteMessage(DynamicMessageExtension); + } + repeatedExtension_.WriteTo(output, _repeated_repeatedExtension_codec); + packedExtension_.WriteTo(output, _repeated_packedExtension_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasScalarExtension) { + output.WriteRawTag(133, 125); + output.WriteFixed32(ScalarExtension); + } + if (HasEnumExtension) { + output.WriteRawTag(136, 125); + output.WriteEnum((int) EnumExtension); + } + if (HasDynamicEnumExtension) { + output.WriteRawTag(144, 125); + output.WriteEnum((int) DynamicEnumExtension); + } + if (messageExtension_ != null) { + output.WriteRawTag(154, 125); + output.WriteMessage(MessageExtension); + } + if (dynamicMessageExtension_ != null) { + output.WriteRawTag(162, 125); + output.WriteMessage(DynamicMessageExtension); + } + repeatedExtension_.WriteTo(ref output, _repeated_repeatedExtension_codec); + packedExtension_.WriteTo(ref output, _repeated_packedExtension_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasScalarExtension) { + size += 2 + 4; + } + if (HasEnumExtension) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) EnumExtension); + } + if (HasDynamicEnumExtension) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) DynamicEnumExtension); + } + if (messageExtension_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(MessageExtension); + } + if (dynamicMessageExtension_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(DynamicMessageExtension); + } + size += repeatedExtension_.CalculateSize(_repeated_repeatedExtension_codec); + size += packedExtension_.CalculateSize(_repeated_packedExtension_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestDynamicExtensions other) { + if (other == null) { + return; + } + if (other.HasScalarExtension) { + ScalarExtension = other.ScalarExtension; + } + if (other.HasEnumExtension) { + EnumExtension = other.EnumExtension; + } + if (other.HasDynamicEnumExtension) { + DynamicEnumExtension = other.DynamicEnumExtension; + } + if (other.messageExtension_ != null) { + if (messageExtension_ == null) { + MessageExtension = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage(); + } + MessageExtension.MergeFrom(other.MessageExtension); + } + if (other.dynamicMessageExtension_ != null) { + if (dynamicMessageExtension_ == null) { + DynamicMessageExtension = new global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicMessageType(); + } + DynamicMessageExtension.MergeFrom(other.DynamicMessageExtension); + } + repeatedExtension_.Add(other.repeatedExtension_); + packedExtension_.Add(other.packedExtension_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 16005: { + ScalarExtension = input.ReadFixed32(); + break; + } + case 16008: { + EnumExtension = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum(); + break; + } + case 16016: { + DynamicEnumExtension = (global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicEnumType) input.ReadEnum(); + break; + } + case 16026: { + if (messageExtension_ == null) { + MessageExtension = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage(); + } + input.ReadMessage(MessageExtension); + break; + } + case 16034: { + if (dynamicMessageExtension_ == null) { + DynamicMessageExtension = new global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicMessageType(); + } + input.ReadMessage(DynamicMessageExtension); + break; + } + case 16042: { + repeatedExtension_.AddEntriesFrom(input, _repeated_repeatedExtension_codec); + break; + } + case 16050: + case 16048: { + packedExtension_.AddEntriesFrom(input, _repeated_packedExtension_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 16005: { + ScalarExtension = input.ReadFixed32(); + break; + } + case 16008: { + EnumExtension = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum(); + break; + } + case 16016: { + DynamicEnumExtension = (global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicEnumType) input.ReadEnum(); + break; + } + case 16026: { + if (messageExtension_ == null) { + MessageExtension = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage(); + } + input.ReadMessage(MessageExtension); + break; + } + case 16034: { + if (dynamicMessageExtension_ == null) { + DynamicMessageExtension = new global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Types.DynamicMessageType(); + } + input.ReadMessage(DynamicMessageExtension); + break; + } + case 16042: { + repeatedExtension_.AddEntriesFrom(ref input, _repeated_repeatedExtension_codec); + break; + } + case 16050: + case 16048: { + packedExtension_.AddEntriesFrom(ref input, _repeated_packedExtension_codec); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestDynamicExtensions message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum DynamicEnumType { + [pbr::OriginalName("DYNAMIC_FOO")] DynamicFoo = 2200, + [pbr::OriginalName("DYNAMIC_BAR")] DynamicBar = 2201, + [pbr::OriginalName("DYNAMIC_BAZ")] DynamicBaz = 2202, + } + + public sealed partial class DynamicMessageType : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DynamicMessageType()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestDynamicExtensions.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DynamicMessageType() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DynamicMessageType(DynamicMessageType other) : this() { + _hasBits0 = other._hasBits0; + dynamicField_ = other.dynamicField_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DynamicMessageType Clone() { + return new DynamicMessageType(this); + } + + /// Field number for the "dynamic_field" field. + public const int DynamicFieldFieldNumber = 2100; + private readonly static int DynamicFieldDefaultValue = 0; + + private int dynamicField_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int DynamicField { + get { if ((_hasBits0 & 1) != 0) { return dynamicField_; } else { return DynamicFieldDefaultValue; } } + set { + _hasBits0 |= 1; + dynamicField_ = value; + } + } + /// Gets whether the "dynamic_field" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDynamicField { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "dynamic_field" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDynamicField() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as DynamicMessageType); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(DynamicMessageType other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (DynamicField != other.DynamicField) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasDynamicField) hash ^= DynamicField.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasDynamicField) { + output.WriteRawTag(160, 131, 1); + output.WriteInt32(DynamicField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasDynamicField) { + output.WriteRawTag(160, 131, 1); + output.WriteInt32(DynamicField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasDynamicField) { + size += 3 + pb::CodedOutputStream.ComputeInt32Size(DynamicField); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(DynamicMessageType other) { + if (other == null) { + return; + } + if (other.HasDynamicField) { + DynamicField = other.DynamicField; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 16800: { + DynamicField = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 16800: { + DynamicField = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class TestRepeatedScalarDifferentTagSizes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRepeatedScalarDifferentTagSizes()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[53]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRepeatedScalarDifferentTagSizes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRepeatedScalarDifferentTagSizes(TestRepeatedScalarDifferentTagSizes other) : this() { + repeatedFixed32_ = other.repeatedFixed32_.Clone(); + repeatedInt32_ = other.repeatedInt32_.Clone(); + repeatedFixed64_ = other.repeatedFixed64_.Clone(); + repeatedInt64_ = other.repeatedInt64_.Clone(); + repeatedFloat_ = other.repeatedFloat_.Clone(); + repeatedUint64_ = other.repeatedUint64_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRepeatedScalarDifferentTagSizes Clone() { + return new TestRepeatedScalarDifferentTagSizes(this); + } + + /// Field number for the "repeated_fixed32" field. + public const int RepeatedFixed32FieldNumber = 12; + private static readonly pb::FieldCodec _repeated_repeatedFixed32_codec + = pb::FieldCodec.ForFixed32(101); + private readonly pbc::RepeatedField repeatedFixed32_ = new pbc::RepeatedField(); + /// + /// Parsing repeated fixed size values used to fail. This message needs to be + /// used in order to get a tag of the right size; all of the repeated fields + /// in TestAllTypes didn't trigger the check. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFixed32 { + get { return repeatedFixed32_; } + } + + /// Field number for the "repeated_int32" field. + public const int RepeatedInt32FieldNumber = 13; + private static readonly pb::FieldCodec _repeated_repeatedInt32_codec + = pb::FieldCodec.ForInt32(104); + private readonly pbc::RepeatedField repeatedInt32_ = new pbc::RepeatedField(); + /// + /// Check for a varint type, just for good measure. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt32 { + get { return repeatedInt32_; } + } + + /// Field number for the "repeated_fixed64" field. + public const int RepeatedFixed64FieldNumber = 2046; + private static readonly pb::FieldCodec _repeated_repeatedFixed64_codec + = pb::FieldCodec.ForFixed64(16369); + private readonly pbc::RepeatedField repeatedFixed64_ = new pbc::RepeatedField(); + /// + /// These have two-byte tags. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFixed64 { + get { return repeatedFixed64_; } + } + + /// Field number for the "repeated_int64" field. + public const int RepeatedInt64FieldNumber = 2047; + private static readonly pb::FieldCodec _repeated_repeatedInt64_codec + = pb::FieldCodec.ForInt64(16376); + private readonly pbc::RepeatedField repeatedInt64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt64 { + get { return repeatedInt64_; } + } + + /// Field number for the "repeated_float" field. + public const int RepeatedFloatFieldNumber = 262142; + private static readonly pb::FieldCodec _repeated_repeatedFloat_codec + = pb::FieldCodec.ForFloat(2097141); + private readonly pbc::RepeatedField repeatedFloat_ = new pbc::RepeatedField(); + /// + /// Three byte tags. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFloat { + get { return repeatedFloat_; } + } + + /// Field number for the "repeated_uint64" field. + public const int RepeatedUint64FieldNumber = 262143; + private static readonly pb::FieldCodec _repeated_repeatedUint64_codec + = pb::FieldCodec.ForUInt64(2097144); + private readonly pbc::RepeatedField repeatedUint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedUint64 { + get { return repeatedUint64_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestRepeatedScalarDifferentTagSizes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestRepeatedScalarDifferentTagSizes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false; + if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false; + if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false; + if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false; + if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false; + if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= repeatedFixed32_.GetHashCode(); + hash ^= repeatedInt32_.GetHashCode(); + hash ^= repeatedFixed64_.GetHashCode(); + hash ^= repeatedInt64_.GetHashCode(); + hash ^= repeatedFloat_.GetHashCode(); + hash ^= repeatedUint64_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec); + repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec); + repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec); + repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec); + repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec); + repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec); + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec); + repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec); + repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec); + repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec); + size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec); + size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec); + size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec); + size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec); + size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestRepeatedScalarDifferentTagSizes other) { + if (other == null) { + return; + } + repeatedFixed32_.Add(other.repeatedFixed32_); + repeatedInt32_.Add(other.repeatedInt32_); + repeatedFixed64_.Add(other.repeatedFixed64_); + repeatedInt64_.Add(other.repeatedInt64_); + repeatedFloat_.Add(other.repeatedFloat_); + repeatedUint64_.Add(other.repeatedUint64_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 98: + case 101: { + repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec); + break; + } + case 106: + case 104: { + repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); + break; + } + case 16370: + case 16369: { + repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec); + break; + } + case 16378: + case 16376: { + repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec); + break; + } + case 2097138: + case 2097141: { + repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec); + break; + } + case 2097146: + case 2097144: { + repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 98: + case 101: { + repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec); + break; + } + case 106: + case 104: { + repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec); + break; + } + case 16370: + case 16369: { + repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec); + break; + } + case 16378: + case 16376: { + repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec); + break; + } + case 2097138: + case 2097141: { + repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec); + break; + } + case 2097146: + case 2097144: { + repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec); + break; + } + } + } + } + #endif + + } + + /// + /// Test that if an optional or required message/group field appears multiple + /// times in the input, they need to be merged. + /// + public sealed partial class TestParsingMerge : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestParsingMerge()); + private pb::UnknownFieldSet _unknownFields; + private pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[54]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestParsingMerge() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestParsingMerge(TestParsingMerge other) : this() { + requiredAllTypes_ = other.requiredAllTypes_ != null ? other.requiredAllTypes_.Clone() : null; + optionalAllTypes_ = other.optionalAllTypes_ != null ? other.optionalAllTypes_.Clone() : null; + repeatedAllTypes_ = other.repeatedAllTypes_.Clone(); + optionalGroup_ = other.HasOptionalGroup ? other.optionalGroup_.Clone() : null; + repeatedGroup_ = other.repeatedGroup_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestParsingMerge Clone() { + return new TestParsingMerge(this); + } + + /// Field number for the "required_all_types" field. + public const int RequiredAllTypesFieldNumber = 1; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes requiredAllTypes_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes RequiredAllTypes { + get { return requiredAllTypes_; } + set { + requiredAllTypes_ = value; + } + } + + /// Field number for the "optional_all_types" field. + public const int OptionalAllTypesFieldNumber = 2; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes optionalAllTypes_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes OptionalAllTypes { + get { return optionalAllTypes_; } + set { + optionalAllTypes_ = value; + } + } + + /// Field number for the "repeated_all_types" field. + public const int RepeatedAllTypesFieldNumber = 3; + private static readonly pb::FieldCodec _repeated_repeatedAllTypes_codec + = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser); + private readonly pbc::RepeatedField repeatedAllTypes_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedAllTypes { + get { return repeatedAllTypes_; } + } + + /// Field number for the "optionalgroup" field. + public const int OptionalGroupFieldNumber = 10; + private global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.OptionalGroup optionalGroup_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.OptionalGroup OptionalGroup { + get { return optionalGroup_; } + set { + optionalGroup_ = value; + } + } + /// Gets whether the optionalgroup field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalGroup { + get { return optionalGroup_ != null; } + } + /// Clears the value of the optionalgroup field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalGroup() { + optionalGroup_ = null; + } + + /// Field number for the "repeatedgroup" field. + public const int RepeatedGroupFieldNumber = 20; + private static readonly pb::FieldCodec _repeated_repeatedGroup_codec + = pb::FieldCodec.ForGroup(163, 164, global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedGroup.Parser); + private readonly pbc::RepeatedField repeatedGroup_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedGroup { + get { return repeatedGroup_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestParsingMerge); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestParsingMerge other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(RequiredAllTypes, other.RequiredAllTypes)) return false; + if (!object.Equals(OptionalAllTypes, other.OptionalAllTypes)) return false; + if(!repeatedAllTypes_.Equals(other.repeatedAllTypes_)) return false; + if (!object.Equals(OptionalGroup, other.OptionalGroup)) return false; + if(!repeatedGroup_.Equals(other.repeatedGroup_)) return false; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (requiredAllTypes_ != null) hash ^= RequiredAllTypes.GetHashCode(); + if (optionalAllTypes_ != null) hash ^= OptionalAllTypes.GetHashCode(); + hash ^= repeatedAllTypes_.GetHashCode(); + if (HasOptionalGroup) hash ^= OptionalGroup.GetHashCode(); + hash ^= repeatedGroup_.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (requiredAllTypes_ != null) { + output.WriteRawTag(10); + output.WriteMessage(RequiredAllTypes); + } + if (optionalAllTypes_ != null) { + output.WriteRawTag(18); + output.WriteMessage(OptionalAllTypes); + } + repeatedAllTypes_.WriteTo(output, _repeated_repeatedAllTypes_codec); + if (HasOptionalGroup) { + output.WriteRawTag(83); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(84); + } + repeatedGroup_.WriteTo(output, _repeated_repeatedGroup_codec); + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (requiredAllTypes_ != null) { + output.WriteRawTag(10); + output.WriteMessage(RequiredAllTypes); + } + if (optionalAllTypes_ != null) { + output.WriteRawTag(18); + output.WriteMessage(OptionalAllTypes); + } + repeatedAllTypes_.WriteTo(ref output, _repeated_repeatedAllTypes_codec); + if (HasOptionalGroup) { + output.WriteRawTag(83); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(84); + } + repeatedGroup_.WriteTo(ref output, _repeated_repeatedGroup_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (requiredAllTypes_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(RequiredAllTypes); + } + if (optionalAllTypes_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(OptionalAllTypes); + } + size += repeatedAllTypes_.CalculateSize(_repeated_repeatedAllTypes_codec); + if (HasOptionalGroup) { + size += 2 + pb::CodedOutputStream.ComputeGroupSize(OptionalGroup); + } + size += repeatedGroup_.CalculateSize(_repeated_repeatedGroup_codec); + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestParsingMerge other) { + if (other == null) { + return; + } + if (other.requiredAllTypes_ != null) { + if (requiredAllTypes_ == null) { + RequiredAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + RequiredAllTypes.MergeFrom(other.RequiredAllTypes); + } + if (other.optionalAllTypes_ != null) { + if (optionalAllTypes_ == null) { + OptionalAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + OptionalAllTypes.MergeFrom(other.OptionalAllTypes); + } + repeatedAllTypes_.Add(other.repeatedAllTypes_); + if (other.HasOptionalGroup) { + if (!HasOptionalGroup) { + OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.OptionalGroup(); + } + OptionalGroup.MergeFrom(other.OptionalGroup); + } + repeatedGroup_.Add(other.repeatedGroup_); + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + case 10: { + if (requiredAllTypes_ == null) { + RequiredAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(RequiredAllTypes); + break; + } + case 18: { + if (optionalAllTypes_ == null) { + OptionalAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(OptionalAllTypes); + break; + } + case 26: { + repeatedAllTypes_.AddEntriesFrom(input, _repeated_repeatedAllTypes_codec); + break; + } + case 83: { + if (!HasOptionalGroup) { + OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.OptionalGroup(); + } + input.ReadGroup(OptionalGroup); + break; + } + case 163: { + repeatedGroup_.AddEntriesFrom(input, _repeated_repeatedGroup_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + case 10: { + if (requiredAllTypes_ == null) { + RequiredAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(RequiredAllTypes); + break; + } + case 18: { + if (optionalAllTypes_ == null) { + OptionalAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(OptionalAllTypes); + break; + } + case 26: { + repeatedAllTypes_.AddEntriesFrom(ref input, _repeated_repeatedAllTypes_codec); + break; + } + case 83: { + if (!HasOptionalGroup) { + OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.OptionalGroup(); + } + input.ReadGroup(OptionalGroup); + break; + } + case 163: { + repeatedGroup_.AddEntriesFrom(ref input, _repeated_repeatedGroup_codec); + break; + } + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + + #region Nested types + /// Container for nested types declared in the TestParsingMerge message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + /// + /// RepeatedFieldsGenerator defines matching field types as TestParsingMerge, + /// except that all fields are repeated. In the tests, we will serialize the + /// RepeatedFieldsGenerator to bytes, and parse the bytes to TestParsingMerge. + /// Repeated fields in RepeatedFieldsGenerator are expected to be merged into + /// the corresponding required/optional fields in TestParsingMerge. + /// + public sealed partial class RepeatedFieldsGenerator : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RepeatedFieldsGenerator()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RepeatedFieldsGenerator() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RepeatedFieldsGenerator(RepeatedFieldsGenerator other) : this() { + field1_ = other.field1_.Clone(); + field2_ = other.field2_.Clone(); + field3_ = other.field3_.Clone(); + group1_ = other.group1_.Clone(); + group2_ = other.group2_.Clone(); + ext1_ = other.ext1_.Clone(); + ext2_ = other.ext2_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RepeatedFieldsGenerator Clone() { + return new RepeatedFieldsGenerator(this); + } + + /// Field number for the "field1" field. + public const int Field1FieldNumber = 1; + private static readonly pb::FieldCodec _repeated_field1_codec + = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser); + private readonly pbc::RepeatedField field1_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Field1 { + get { return field1_; } + } + + /// Field number for the "field2" field. + public const int Field2FieldNumber = 2; + private static readonly pb::FieldCodec _repeated_field2_codec + = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser); + private readonly pbc::RepeatedField field2_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Field2 { + get { return field2_; } + } + + /// Field number for the "field3" field. + public const int Field3FieldNumber = 3; + private static readonly pb::FieldCodec _repeated_field3_codec + = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser); + private readonly pbc::RepeatedField field3_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Field3 { + get { return field3_; } + } + + /// Field number for the "group1" field. + public const int Group1FieldNumber = 10; + private static readonly pb::FieldCodec _repeated_group1_codec + = pb::FieldCodec.ForGroup(83, 84, global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Types.Group1.Parser); + private readonly pbc::RepeatedField group1_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Group1 { + get { return group1_; } + } + + /// Field number for the "group2" field. + public const int Group2FieldNumber = 20; + private static readonly pb::FieldCodec _repeated_group2_codec + = pb::FieldCodec.ForGroup(163, 164, global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Types.Group2.Parser); + private readonly pbc::RepeatedField group2_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Group2 { + get { return group2_; } + } + + /// Field number for the "ext1" field. + public const int Ext1FieldNumber = 1000; + private static readonly pb::FieldCodec _repeated_ext1_codec + = pb::FieldCodec.ForMessage(8002, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser); + private readonly pbc::RepeatedField ext1_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Ext1 { + get { return ext1_; } + } + + /// Field number for the "ext2" field. + public const int Ext2FieldNumber = 1001; + private static readonly pb::FieldCodec _repeated_ext2_codec + = pb::FieldCodec.ForMessage(8010, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser); + private readonly pbc::RepeatedField ext2_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Ext2 { + get { return ext2_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as RepeatedFieldsGenerator); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(RepeatedFieldsGenerator other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!field1_.Equals(other.field1_)) return false; + if(!field2_.Equals(other.field2_)) return false; + if(!field3_.Equals(other.field3_)) return false; + if(!group1_.Equals(other.group1_)) return false; + if(!group2_.Equals(other.group2_)) return false; + if(!ext1_.Equals(other.ext1_)) return false; + if(!ext2_.Equals(other.ext2_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= field1_.GetHashCode(); + hash ^= field2_.GetHashCode(); + hash ^= field3_.GetHashCode(); + hash ^= group1_.GetHashCode(); + hash ^= group2_.GetHashCode(); + hash ^= ext1_.GetHashCode(); + hash ^= ext2_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + field1_.WriteTo(output, _repeated_field1_codec); + field2_.WriteTo(output, _repeated_field2_codec); + field3_.WriteTo(output, _repeated_field3_codec); + group1_.WriteTo(output, _repeated_group1_codec); + group2_.WriteTo(output, _repeated_group2_codec); + ext1_.WriteTo(output, _repeated_ext1_codec); + ext2_.WriteTo(output, _repeated_ext2_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + field1_.WriteTo(ref output, _repeated_field1_codec); + field2_.WriteTo(ref output, _repeated_field2_codec); + field3_.WriteTo(ref output, _repeated_field3_codec); + group1_.WriteTo(ref output, _repeated_group1_codec); + group2_.WriteTo(ref output, _repeated_group2_codec); + ext1_.WriteTo(ref output, _repeated_ext1_codec); + ext2_.WriteTo(ref output, _repeated_ext2_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += field1_.CalculateSize(_repeated_field1_codec); + size += field2_.CalculateSize(_repeated_field2_codec); + size += field3_.CalculateSize(_repeated_field3_codec); + size += group1_.CalculateSize(_repeated_group1_codec); + size += group2_.CalculateSize(_repeated_group2_codec); + size += ext1_.CalculateSize(_repeated_ext1_codec); + size += ext2_.CalculateSize(_repeated_ext2_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(RepeatedFieldsGenerator other) { + if (other == null) { + return; + } + field1_.Add(other.field1_); + field2_.Add(other.field2_); + field3_.Add(other.field3_); + group1_.Add(other.group1_); + group2_.Add(other.group2_); + ext1_.Add(other.ext1_); + ext2_.Add(other.ext2_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + field1_.AddEntriesFrom(input, _repeated_field1_codec); + break; + } + case 18: { + field2_.AddEntriesFrom(input, _repeated_field2_codec); + break; + } + case 26: { + field3_.AddEntriesFrom(input, _repeated_field3_codec); + break; + } + case 83: { + group1_.AddEntriesFrom(input, _repeated_group1_codec); + break; + } + case 163: { + group2_.AddEntriesFrom(input, _repeated_group2_codec); + break; + } + case 8002: { + ext1_.AddEntriesFrom(input, _repeated_ext1_codec); + break; + } + case 8010: { + ext2_.AddEntriesFrom(input, _repeated_ext2_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + field1_.AddEntriesFrom(ref input, _repeated_field1_codec); + break; + } + case 18: { + field2_.AddEntriesFrom(ref input, _repeated_field2_codec); + break; + } + case 26: { + field3_.AddEntriesFrom(ref input, _repeated_field3_codec); + break; + } + case 83: { + group1_.AddEntriesFrom(ref input, _repeated_group1_codec); + break; + } + case 163: { + group2_.AddEntriesFrom(ref input, _repeated_group2_codec); + break; + } + case 8002: { + ext1_.AddEntriesFrom(ref input, _repeated_ext1_codec); + break; + } + case 8010: { + ext2_.AddEntriesFrom(ref input, _repeated_ext2_codec); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the RepeatedFieldsGenerator message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class Group1 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Group1()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Group1() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Group1(Group1 other) : this() { + field1_ = other.field1_ != null ? other.field1_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Group1 Clone() { + return new Group1(this); + } + + /// Field number for the "field1" field. + public const int Field1FieldNumber = 11; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes field1_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes Field1 { + get { return field1_; } + set { + field1_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Group1); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Group1 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Field1, other.Field1)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (field1_ != null) hash ^= Field1.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (field1_ != null) { + output.WriteRawTag(90); + output.WriteMessage(Field1); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (field1_ != null) { + output.WriteRawTag(90); + output.WriteMessage(Field1); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (field1_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Field1); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Group1 other) { + if (other == null) { + return; + } + if (other.field1_ != null) { + if (field1_ == null) { + Field1 = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + Field1.MergeFrom(other.Field1); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 84: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 90: { + if (field1_ == null) { + Field1 = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(Field1); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 84: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 90: { + if (field1_ == null) { + Field1 = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(Field1); + break; + } + } + } + } + #endif + + } + + public sealed partial class Group2 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Group2()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Types.RepeatedFieldsGenerator.Descriptor.NestedTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Group2() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Group2(Group2 other) : this() { + field1_ = other.field1_ != null ? other.field1_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Group2 Clone() { + return new Group2(this); + } + + /// Field number for the "field1" field. + public const int Field1FieldNumber = 21; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes field1_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes Field1 { + get { return field1_; } + set { + field1_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Group2); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Group2 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Field1, other.Field1)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (field1_ != null) hash ^= Field1.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (field1_ != null) { + output.WriteRawTag(170, 1); + output.WriteMessage(Field1); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (field1_ != null) { + output.WriteRawTag(170, 1); + output.WriteMessage(Field1); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (field1_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(Field1); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Group2 other) { + if (other == null) { + return; + } + if (other.field1_ != null) { + if (field1_ == null) { + Field1 = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + Field1.MergeFrom(other.Field1); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 164: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 170: { + if (field1_ == null) { + Field1 = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(Field1); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 164: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 170: { + if (field1_ == null) { + Field1 = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(Field1); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class OptionalGroup : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OptionalGroup()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Descriptor.NestedTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup(OptionalGroup other) : this() { + optionalGroupAllTypes_ = other.optionalGroupAllTypes_ != null ? other.optionalGroupAllTypes_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup Clone() { + return new OptionalGroup(this); + } + + /// Field number for the "optional_group_all_types" field. + public const int OptionalGroupAllTypesFieldNumber = 11; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes optionalGroupAllTypes_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes OptionalGroupAllTypes { + get { return optionalGroupAllTypes_; } + set { + optionalGroupAllTypes_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as OptionalGroup); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(OptionalGroup other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(OptionalGroupAllTypes, other.OptionalGroupAllTypes)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (optionalGroupAllTypes_ != null) hash ^= OptionalGroupAllTypes.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (optionalGroupAllTypes_ != null) { + output.WriteRawTag(90); + output.WriteMessage(OptionalGroupAllTypes); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (optionalGroupAllTypes_ != null) { + output.WriteRawTag(90); + output.WriteMessage(OptionalGroupAllTypes); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (optionalGroupAllTypes_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(OptionalGroupAllTypes); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(OptionalGroup other) { + if (other == null) { + return; + } + if (other.optionalGroupAllTypes_ != null) { + if (optionalGroupAllTypes_ == null) { + OptionalGroupAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + OptionalGroupAllTypes.MergeFrom(other.OptionalGroupAllTypes); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 84: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 90: { + if (optionalGroupAllTypes_ == null) { + OptionalGroupAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(OptionalGroupAllTypes); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 84: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 90: { + if (optionalGroupAllTypes_ == null) { + OptionalGroupAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(OptionalGroupAllTypes); + break; + } + } + } + } + #endif + + } + + public sealed partial class RepeatedGroup : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RepeatedGroup()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestParsingMerge.Descriptor.NestedTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RepeatedGroup() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RepeatedGroup(RepeatedGroup other) : this() { + repeatedGroupAllTypes_ = other.repeatedGroupAllTypes_ != null ? other.repeatedGroupAllTypes_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public RepeatedGroup Clone() { + return new RepeatedGroup(this); + } + + /// Field number for the "repeated_group_all_types" field. + public const int RepeatedGroupAllTypesFieldNumber = 21; + private global::Google.Protobuf.TestProtos.Proto2.TestAllTypes repeatedGroupAllTypes_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes RepeatedGroupAllTypes { + get { return repeatedGroupAllTypes_; } + set { + repeatedGroupAllTypes_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as RepeatedGroup); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(RepeatedGroup other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(RepeatedGroupAllTypes, other.RepeatedGroupAllTypes)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (repeatedGroupAllTypes_ != null) hash ^= RepeatedGroupAllTypes.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (repeatedGroupAllTypes_ != null) { + output.WriteRawTag(170, 1); + output.WriteMessage(RepeatedGroupAllTypes); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (repeatedGroupAllTypes_ != null) { + output.WriteRawTag(170, 1); + output.WriteMessage(RepeatedGroupAllTypes); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (repeatedGroupAllTypes_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(RepeatedGroupAllTypes); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(RepeatedGroup other) { + if (other == null) { + return; + } + if (other.repeatedGroupAllTypes_ != null) { + if (repeatedGroupAllTypes_ == null) { + RepeatedGroupAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + RepeatedGroupAllTypes.MergeFrom(other.RepeatedGroupAllTypes); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 164: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 170: { + if (repeatedGroupAllTypes_ == null) { + RepeatedGroupAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(RepeatedGroupAllTypes); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 164: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 170: { + if (repeatedGroupAllTypes_ == null) { + RepeatedGroupAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + input.ReadMessage(RepeatedGroupAllTypes); + break; + } + } + } + } + #endif + + } + + } + #endregion + + #region Extensions + /// Container for extensions for other messages declared in the TestParsingMerge message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Extensions { + public static readonly pb::Extension OptionalExt = + new pb::Extension(1000, pb::FieldCodec.ForMessage(8002, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser)); + public static readonly pb::RepeatedExtension RepeatedExt = + new pb::RepeatedExtension(1001, pb::FieldCodec.ForMessage(8010, global::Google.Protobuf.TestProtos.Proto2.TestAllTypes.Parser)); + } + #endregion + + } + + public sealed partial class TestCommentInjectionMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestCommentInjectionMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[55]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestCommentInjectionMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestCommentInjectionMessage(TestCommentInjectionMessage other) : this() { + a_ = other.a_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestCommentInjectionMessage Clone() { + return new TestCommentInjectionMessage(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private readonly static string ADefaultValue = global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String("Ki8gPC0gTmVpdGhlciBzaG91bGQgdGhpcy4="), 0, 26); + + private string a_; + /// + /// */ <- This should not close the generated doc comment + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string A { + get { return a_ ?? ADefaultValue; } + set { + a_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasA { + get { return a_ != null; } + } + /// Clears the value of the "a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearA() { + a_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestCommentInjectionMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestCommentInjectionMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(10); + output.WriteString(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(10); + output.WriteString(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasA) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(A); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestCommentInjectionMessage other) { + if (other == null) { + return; + } + if (other.HasA) { + A = other.A; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + A = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + A = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// Test that RPC services work. + /// + public sealed partial class FooRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[56]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooRequest(FooRequest other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooRequest Clone() { + return new FooRequest(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FooRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FooRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FooRequest other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class FooResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[57]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooResponse(FooResponse other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooResponse Clone() { + return new FooResponse(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FooResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FooResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FooResponse other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class FooClientMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooClientMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[58]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooClientMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooClientMessage(FooClientMessage other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooClientMessage Clone() { + return new FooClientMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FooClientMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FooClientMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FooClientMessage other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class FooServerMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooServerMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[59]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooServerMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooServerMessage(FooServerMessage other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooServerMessage Clone() { + return new FooServerMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FooServerMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FooServerMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FooServerMessage other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class BarRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BarRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[60]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BarRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BarRequest(BarRequest other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BarRequest Clone() { + return new BarRequest(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as BarRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(BarRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(BarRequest other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class BarResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BarResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[61]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BarResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BarResponse(BarResponse other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BarResponse Clone() { + return new BarResponse(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as BarResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(BarResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(BarResponse other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class TestJsonName : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestJsonName()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[62]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestJsonName() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestJsonName(TestJsonName other) : this() { + _hasBits0 = other._hasBits0; + fieldName1_ = other.fieldName1_; + fieldName2_ = other.fieldName2_; + fieldName3_ = other.fieldName3_; + FieldName4_ = other.FieldName4_; + fIELDNAME5_ = other.fIELDNAME5_; + fieldName6_ = other.fieldName6_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestJsonName Clone() { + return new TestJsonName(this); + } + + /// Field number for the "field_name1" field. + public const int FieldName1FieldNumber = 1; + private readonly static int FieldName1DefaultValue = 0; + + private int fieldName1_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName1 { + get { if ((_hasBits0 & 1) != 0) { return fieldName1_; } else { return FieldName1DefaultValue; } } + set { + _hasBits0 |= 1; + fieldName1_ = value; + } + } + /// Gets whether the "field_name1" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName1 { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "field_name1" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName1() { + _hasBits0 &= ~1; + } + + /// Field number for the "fieldName2" field. + public const int FieldName2FieldNumber = 2; + private readonly static int FieldName2DefaultValue = 0; + + private int fieldName2_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName2 { + get { if ((_hasBits0 & 2) != 0) { return fieldName2_; } else { return FieldName2DefaultValue; } } + set { + _hasBits0 |= 2; + fieldName2_ = value; + } + } + /// Gets whether the "fieldName2" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName2 { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "fieldName2" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName2() { + _hasBits0 &= ~2; + } + + /// Field number for the "FieldName3" field. + public const int FieldName3FieldNumber = 3; + private readonly static int FieldName3DefaultValue = 0; + + private int fieldName3_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName3 { + get { if ((_hasBits0 & 4) != 0) { return fieldName3_; } else { return FieldName3DefaultValue; } } + set { + _hasBits0 |= 4; + fieldName3_ = value; + } + } + /// Gets whether the "FieldName3" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName3 { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "FieldName3" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName3() { + _hasBits0 &= ~4; + } + + /// Field number for the "_field_name4" field. + public const int FieldName4FieldNumber = 4; + private readonly static int FieldName4DefaultValue = 0; + + private int FieldName4_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName4 { + get { if ((_hasBits0 & 8) != 0) { return FieldName4_; } else { return FieldName4DefaultValue; } } + set { + _hasBits0 |= 8; + FieldName4_ = value; + } + } + /// Gets whether the "_field_name4" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName4 { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "_field_name4" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName4() { + _hasBits0 &= ~8; + } + + /// Field number for the "FIELD_NAME5" field. + public const int FIELDNAME5FieldNumber = 5; + private readonly static int FIELDNAME5DefaultValue = 0; + + private int fIELDNAME5_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FIELDNAME5 { + get { if ((_hasBits0 & 16) != 0) { return fIELDNAME5_; } else { return FIELDNAME5DefaultValue; } } + set { + _hasBits0 |= 16; + fIELDNAME5_ = value; + } + } + /// Gets whether the "FIELD_NAME5" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFIELDNAME5 { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "FIELD_NAME5" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFIELDNAME5() { + _hasBits0 &= ~16; + } + + /// Field number for the "field_name6" field. + public const int FieldName6FieldNumber = 6; + private readonly static int FieldName6DefaultValue = 0; + + private int fieldName6_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FieldName6 { + get { if ((_hasBits0 & 32) != 0) { return fieldName6_; } else { return FieldName6DefaultValue; } } + set { + _hasBits0 |= 32; + fieldName6_ = value; + } + } + /// Gets whether the "field_name6" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFieldName6 { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "field_name6" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFieldName6() { + _hasBits0 &= ~32; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestJsonName); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestJsonName other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (FieldName1 != other.FieldName1) return false; + if (FieldName2 != other.FieldName2) return false; + if (FieldName3 != other.FieldName3) return false; + if (FieldName4 != other.FieldName4) return false; + if (FIELDNAME5 != other.FIELDNAME5) return false; + if (FieldName6 != other.FieldName6) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasFieldName1) hash ^= FieldName1.GetHashCode(); + if (HasFieldName2) hash ^= FieldName2.GetHashCode(); + if (HasFieldName3) hash ^= FieldName3.GetHashCode(); + if (HasFieldName4) hash ^= FieldName4.GetHashCode(); + if (HasFIELDNAME5) hash ^= FIELDNAME5.GetHashCode(); + if (HasFieldName6) hash ^= FieldName6.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasFieldName1) { + output.WriteRawTag(8); + output.WriteInt32(FieldName1); + } + if (HasFieldName2) { + output.WriteRawTag(16); + output.WriteInt32(FieldName2); + } + if (HasFieldName3) { + output.WriteRawTag(24); + output.WriteInt32(FieldName3); + } + if (HasFieldName4) { + output.WriteRawTag(32); + output.WriteInt32(FieldName4); + } + if (HasFIELDNAME5) { + output.WriteRawTag(40); + output.WriteInt32(FIELDNAME5); + } + if (HasFieldName6) { + output.WriteRawTag(48); + output.WriteInt32(FieldName6); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasFieldName1) { + output.WriteRawTag(8); + output.WriteInt32(FieldName1); + } + if (HasFieldName2) { + output.WriteRawTag(16); + output.WriteInt32(FieldName2); + } + if (HasFieldName3) { + output.WriteRawTag(24); + output.WriteInt32(FieldName3); + } + if (HasFieldName4) { + output.WriteRawTag(32); + output.WriteInt32(FieldName4); + } + if (HasFIELDNAME5) { + output.WriteRawTag(40); + output.WriteInt32(FIELDNAME5); + } + if (HasFieldName6) { + output.WriteRawTag(48); + output.WriteInt32(FieldName6); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasFieldName1) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(FieldName1); + } + if (HasFieldName2) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(FieldName2); + } + if (HasFieldName3) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(FieldName3); + } + if (HasFieldName4) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(FieldName4); + } + if (HasFIELDNAME5) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(FIELDNAME5); + } + if (HasFieldName6) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(FieldName6); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestJsonName other) { + if (other == null) { + return; + } + if (other.HasFieldName1) { + FieldName1 = other.FieldName1; + } + if (other.HasFieldName2) { + FieldName2 = other.FieldName2; + } + if (other.HasFieldName3) { + FieldName3 = other.FieldName3; + } + if (other.HasFieldName4) { + FieldName4 = other.FieldName4; + } + if (other.HasFIELDNAME5) { + FIELDNAME5 = other.FIELDNAME5; + } + if (other.HasFieldName6) { + FieldName6 = other.FieldName6; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + FieldName1 = input.ReadInt32(); + break; + } + case 16: { + FieldName2 = input.ReadInt32(); + break; + } + case 24: { + FieldName3 = input.ReadInt32(); + break; + } + case 32: { + FieldName4 = input.ReadInt32(); + break; + } + case 40: { + FIELDNAME5 = input.ReadInt32(); + break; + } + case 48: { + FieldName6 = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + FieldName1 = input.ReadInt32(); + break; + } + case 16: { + FieldName2 = input.ReadInt32(); + break; + } + case 24: { + FieldName3 = input.ReadInt32(); + break; + } + case 32: { + FieldName4 = input.ReadInt32(); + break; + } + case 40: { + FIELDNAME5 = input.ReadInt32(); + break; + } + case 48: { + FieldName6 = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestHugeFieldNumbers : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestHugeFieldNumbers()); + private pb::UnknownFieldSet _unknownFields; + private pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[63]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestHugeFieldNumbers() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestHugeFieldNumbers(TestHugeFieldNumbers other) : this() { + _hasBits0 = other._hasBits0; + optionalInt32_ = other.optionalInt32_; + fixed32_ = other.fixed32_; + repeatedInt32_ = other.repeatedInt32_.Clone(); + packedInt32_ = other.packedInt32_.Clone(); + optionalEnum_ = other.optionalEnum_; + optionalString_ = other.optionalString_; + optionalBytes_ = other.optionalBytes_; + optionalMessage_ = other.optionalMessage_ != null ? other.optionalMessage_.Clone() : null; + optionalGroup_ = other.HasOptionalGroup ? other.optionalGroup_.Clone() : null; + stringStringMap_ = other.stringStringMap_.Clone(); + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: + OneofUint32 = other.OneofUint32; + break; + case OneofFieldOneofCase.OneofTestAllTypes: + OneofTestAllTypes = other.OneofTestAllTypes.Clone(); + break; + case OneofFieldOneofCase.OneofString: + OneofString = other.OneofString; + break; + case OneofFieldOneofCase.OneofBytes: + OneofBytes = other.OneofBytes; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestHugeFieldNumbers Clone() { + return new TestHugeFieldNumbers(this); + } + + /// Field number for the "optional_int32" field. + public const int OptionalInt32FieldNumber = 536870000; + private readonly static int OptionalInt32DefaultValue = 0; + + private int optionalInt32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalInt32 { + get { if ((_hasBits0 & 1) != 0) { return optionalInt32_; } else { return OptionalInt32DefaultValue; } } + set { + _hasBits0 |= 1; + optionalInt32_ = value; + } + } + /// Gets whether the "optional_int32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalInt32 { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "optional_int32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalInt32() { + _hasBits0 &= ~1; + } + + /// Field number for the "fixed_32" field. + public const int Fixed32FieldNumber = 536870001; + private readonly static int Fixed32DefaultValue = 0; + + private int fixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Fixed32 { + get { if ((_hasBits0 & 2) != 0) { return fixed32_; } else { return Fixed32DefaultValue; } } + set { + _hasBits0 |= 2; + fixed32_ = value; + } + } + /// Gets whether the "fixed_32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFixed32 { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "fixed_32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFixed32() { + _hasBits0 &= ~2; + } + + /// Field number for the "repeated_int32" field. + public const int RepeatedInt32FieldNumber = 536870002; + private static readonly pb::FieldCodec _repeated_repeatedInt32_codec + = pb::FieldCodec.ForInt32(4294960016); + private readonly pbc::RepeatedField repeatedInt32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt32 { + get { return repeatedInt32_; } + } + + /// Field number for the "packed_int32" field. + public const int PackedInt32FieldNumber = 536870003; + private static readonly pb::FieldCodec _repeated_packedInt32_codec + = pb::FieldCodec.ForInt32(4294960026); + private readonly pbc::RepeatedField packedInt32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedInt32 { + get { return packedInt32_; } + } + + /// Field number for the "optional_enum" field. + public const int OptionalEnumFieldNumber = 536870004; + private readonly static global::Google.Protobuf.TestProtos.Proto2.ForeignEnum OptionalEnumDefaultValue = global::Google.Protobuf.TestProtos.Proto2.ForeignEnum.ForeignFoo; + + private global::Google.Protobuf.TestProtos.Proto2.ForeignEnum optionalEnum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.ForeignEnum OptionalEnum { + get { if ((_hasBits0 & 4) != 0) { return optionalEnum_; } else { return OptionalEnumDefaultValue; } } + set { + _hasBits0 |= 4; + optionalEnum_ = value; + } + } + /// Gets whether the "optional_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalEnum { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "optional_enum" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalEnum() { + _hasBits0 &= ~4; + } + + /// Field number for the "optional_string" field. + public const int OptionalStringFieldNumber = 536870005; + private readonly static string OptionalStringDefaultValue = ""; + + private string optionalString_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalString { + get { return optionalString_ ?? OptionalStringDefaultValue; } + set { + optionalString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalString { + get { return optionalString_ != null; } + } + /// Clears the value of the "optional_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalString() { + optionalString_ = null; + } + + /// Field number for the "optional_bytes" field. + public const int OptionalBytesFieldNumber = 536870006; + private readonly static pb::ByteString OptionalBytesDefaultValue = pb::ByteString.Empty; + + private pb::ByteString optionalBytes_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString OptionalBytes { + get { return optionalBytes_ ?? OptionalBytesDefaultValue; } + set { + optionalBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_bytes" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalBytes { + get { return optionalBytes_ != null; } + } + /// Clears the value of the "optional_bytes" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalBytes() { + optionalBytes_ = null; + } + + /// Field number for the "optional_message" field. + public const int OptionalMessageFieldNumber = 536870007; + private global::Google.Protobuf.TestProtos.Proto2.ForeignMessage optionalMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.ForeignMessage OptionalMessage { + get { return optionalMessage_; } + set { + optionalMessage_ = value; + } + } + + /// Field number for the "optionalgroup" field. + public const int OptionalGroupFieldNumber = 536870008; + private global::Google.Protobuf.TestProtos.Proto2.TestHugeFieldNumbers.Types.OptionalGroup optionalGroup_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestHugeFieldNumbers.Types.OptionalGroup OptionalGroup { + get { return optionalGroup_; } + set { + optionalGroup_ = value; + } + } + /// Gets whether the optionalgroup field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalGroup { + get { return optionalGroup_ != null; } + } + /// Clears the value of the optionalgroup field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalGroup() { + optionalGroup_ = null; + } + + /// Field number for the "string_string_map" field. + public const int StringStringMapFieldNumber = 536870010; + private static readonly pbc::MapField.Codec _map_stringStringMap_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForString(18, ""), 4294960082); + private readonly pbc::MapField stringStringMap_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::MapField StringStringMap { + get { return stringStringMap_; } + } + + /// Field number for the "oneof_uint32" field. + public const int OneofUint32FieldNumber = 536870011; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OneofUint32 { + get { return HasOneofUint32 ? (uint) oneofField_ : 0; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; + } + } + /// Gets whether the "oneof_uint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofUint32 { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32; } + } + /// Clears the value of the oneof if it's currently set to "oneof_uint32" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofUint32() { + if (HasOneofUint32) { + ClearOneofField(); + } + } + + /// Field number for the "oneof_test_all_types" field. + public const int OneofTestAllTypesFieldNumber = 536870012; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.Proto2.TestAllTypes OneofTestAllTypes { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes ? (global::Google.Protobuf.TestProtos.Proto2.TestAllTypes) oneofField_ : null; } + set { + oneofField_ = value; + oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofTestAllTypes; + } + } + + /// Field number for the "oneof_string" field. + public const int OneofStringFieldNumber = 536870013; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OneofString { + get { return HasOneofString ? (string) oneofField_ : ""; } + set { + oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + oneofFieldCase_ = OneofFieldOneofCase.OneofString; + } + } + /// Gets whether the "oneof_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofString { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString; } + } + /// Clears the value of the oneof if it's currently set to "oneof_string" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofString() { + if (HasOneofString) { + ClearOneofField(); + } + } + + /// Field number for the "oneof_bytes" field. + public const int OneofBytesFieldNumber = 536870014; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString OneofBytes { + get { return HasOneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; } + set { + oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; + } + } + /// Gets whether the "oneof_bytes" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofBytes { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes; } + } + /// Clears the value of the oneof if it's currently set to "oneof_bytes" + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofBytes() { + if (HasOneofBytes) { + ClearOneofField(); + } + } + + private object oneofField_; + /// Enum of possible cases for the "oneof_field" oneof. + public enum OneofFieldOneofCase { + None = 0, + OneofUint32 = 536870011, + OneofTestAllTypes = 536870012, + OneofString = 536870013, + OneofBytes = 536870014, + } + private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneofFieldOneofCase OneofFieldCase { + get { return oneofFieldCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofField() { + oneofFieldCase_ = OneofFieldOneofCase.None; + oneofField_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestHugeFieldNumbers); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestHugeFieldNumbers other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (OptionalInt32 != other.OptionalInt32) return false; + if (Fixed32 != other.Fixed32) return false; + if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false; + if(!packedInt32_.Equals(other.packedInt32_)) return false; + if (OptionalEnum != other.OptionalEnum) return false; + if (OptionalString != other.OptionalString) return false; + if (OptionalBytes != other.OptionalBytes) return false; + if (!object.Equals(OptionalMessage, other.OptionalMessage)) return false; + if (!object.Equals(OptionalGroup, other.OptionalGroup)) return false; + if (!StringStringMap.Equals(other.StringStringMap)) return false; + if (OneofUint32 != other.OneofUint32) return false; + if (!object.Equals(OneofTestAllTypes, other.OneofTestAllTypes)) return false; + if (OneofString != other.OneofString) return false; + if (OneofBytes != other.OneofBytes) return false; + if (OneofFieldCase != other.OneofFieldCase) return false; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasOptionalInt32) hash ^= OptionalInt32.GetHashCode(); + if (HasFixed32) hash ^= Fixed32.GetHashCode(); + hash ^= repeatedInt32_.GetHashCode(); + hash ^= packedInt32_.GetHashCode(); + if (HasOptionalEnum) hash ^= OptionalEnum.GetHashCode(); + if (HasOptionalString) hash ^= OptionalString.GetHashCode(); + if (HasOptionalBytes) hash ^= OptionalBytes.GetHashCode(); + if (optionalMessage_ != null) hash ^= OptionalMessage.GetHashCode(); + if (HasOptionalGroup) hash ^= OptionalGroup.GetHashCode(); + hash ^= StringStringMap.GetHashCode(); + if (HasOneofUint32) hash ^= OneofUint32.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes) hash ^= OneofTestAllTypes.GetHashCode(); + if (HasOneofString) hash ^= OneofString.GetHashCode(); + if (HasOneofBytes) hash ^= OneofBytes.GetHashCode(); + hash ^= (int) oneofFieldCase_; + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasOptionalInt32) { + output.WriteRawTag(128, 199, 255, 255, 15); + output.WriteInt32(OptionalInt32); + } + if (HasFixed32) { + output.WriteRawTag(136, 199, 255, 255, 15); + output.WriteInt32(Fixed32); + } + repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec); + packedInt32_.WriteTo(output, _repeated_packedInt32_codec); + if (HasOptionalEnum) { + output.WriteRawTag(160, 199, 255, 255, 15); + output.WriteEnum((int) OptionalEnum); + } + if (HasOptionalString) { + output.WriteRawTag(170, 199, 255, 255, 15); + output.WriteString(OptionalString); + } + if (HasOptionalBytes) { + output.WriteRawTag(178, 199, 255, 255, 15); + output.WriteBytes(OptionalBytes); + } + if (optionalMessage_ != null) { + output.WriteRawTag(186, 199, 255, 255, 15); + output.WriteMessage(OptionalMessage); + } + if (HasOptionalGroup) { + output.WriteRawTag(195, 199, 255, 255, 15); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(196, 199, 255, 255, 15); + } + stringStringMap_.WriteTo(output, _map_stringStringMap_codec); + if (HasOneofUint32) { + output.WriteRawTag(216, 199, 255, 255, 15); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes) { + output.WriteRawTag(226, 199, 255, 255, 15); + output.WriteMessage(OneofTestAllTypes); + } + if (HasOneofString) { + output.WriteRawTag(234, 199, 255, 255, 15); + output.WriteString(OneofString); + } + if (HasOneofBytes) { + output.WriteRawTag(242, 199, 255, 255, 15); + output.WriteBytes(OneofBytes); + } + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasOptionalInt32) { + output.WriteRawTag(128, 199, 255, 255, 15); + output.WriteInt32(OptionalInt32); + } + if (HasFixed32) { + output.WriteRawTag(136, 199, 255, 255, 15); + output.WriteInt32(Fixed32); + } + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec); + if (HasOptionalEnum) { + output.WriteRawTag(160, 199, 255, 255, 15); + output.WriteEnum((int) OptionalEnum); + } + if (HasOptionalString) { + output.WriteRawTag(170, 199, 255, 255, 15); + output.WriteString(OptionalString); + } + if (HasOptionalBytes) { + output.WriteRawTag(178, 199, 255, 255, 15); + output.WriteBytes(OptionalBytes); + } + if (optionalMessage_ != null) { + output.WriteRawTag(186, 199, 255, 255, 15); + output.WriteMessage(OptionalMessage); + } + if (HasOptionalGroup) { + output.WriteRawTag(195, 199, 255, 255, 15); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(196, 199, 255, 255, 15); + } + stringStringMap_.WriteTo(ref output, _map_stringStringMap_codec); + if (HasOneofUint32) { + output.WriteRawTag(216, 199, 255, 255, 15); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes) { + output.WriteRawTag(226, 199, 255, 255, 15); + output.WriteMessage(OneofTestAllTypes); + } + if (HasOneofString) { + output.WriteRawTag(234, 199, 255, 255, 15); + output.WriteString(OneofString); + } + if (HasOneofBytes) { + output.WriteRawTag(242, 199, 255, 255, 15); + output.WriteBytes(OneofBytes); + } + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasOptionalInt32) { + size += 5 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32); + } + if (HasFixed32) { + size += 5 + pb::CodedOutputStream.ComputeInt32Size(Fixed32); + } + size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec); + size += packedInt32_.CalculateSize(_repeated_packedInt32_codec); + if (HasOptionalEnum) { + size += 5 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalEnum); + } + if (HasOptionalString) { + size += 5 + pb::CodedOutputStream.ComputeStringSize(OptionalString); + } + if (HasOptionalBytes) { + size += 5 + pb::CodedOutputStream.ComputeBytesSize(OptionalBytes); + } + if (optionalMessage_ != null) { + size += 5 + pb::CodedOutputStream.ComputeMessageSize(OptionalMessage); + } + if (HasOptionalGroup) { + size += 10 + pb::CodedOutputStream.ComputeGroupSize(OptionalGroup); + } + size += stringStringMap_.CalculateSize(_map_stringStringMap_codec); + if (HasOneofUint32) { + size += 5 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes) { + size += 5 + pb::CodedOutputStream.ComputeMessageSize(OneofTestAllTypes); + } + if (HasOneofString) { + size += 5 + pb::CodedOutputStream.ComputeStringSize(OneofString); + } + if (HasOneofBytes) { + size += 5 + pb::CodedOutputStream.ComputeBytesSize(OneofBytes); + } + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestHugeFieldNumbers other) { + if (other == null) { + return; + } + if (other.HasOptionalInt32) { + OptionalInt32 = other.OptionalInt32; + } + if (other.HasFixed32) { + Fixed32 = other.Fixed32; + } + repeatedInt32_.Add(other.repeatedInt32_); + packedInt32_.Add(other.packedInt32_); + if (other.HasOptionalEnum) { + OptionalEnum = other.OptionalEnum; + } + if (other.HasOptionalString) { + OptionalString = other.OptionalString; + } + if (other.HasOptionalBytes) { + OptionalBytes = other.OptionalBytes; + } + if (other.optionalMessage_ != null) { + if (optionalMessage_ == null) { + OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage(); + } + OptionalMessage.MergeFrom(other.OptionalMessage); + } + if (other.HasOptionalGroup) { + if (!HasOptionalGroup) { + OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestHugeFieldNumbers.Types.OptionalGroup(); + } + OptionalGroup.MergeFrom(other.OptionalGroup); + } + stringStringMap_.Add(other.stringStringMap_); + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: + OneofUint32 = other.OneofUint32; + break; + case OneofFieldOneofCase.OneofTestAllTypes: + if (OneofTestAllTypes == null) { + OneofTestAllTypes = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + } + OneofTestAllTypes.MergeFrom(other.OneofTestAllTypes); + break; + case OneofFieldOneofCase.OneofString: + OneofString = other.OneofString; + break; + case OneofFieldOneofCase.OneofBytes: + OneofBytes = other.OneofBytes; + break; + } + + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + case 4294960000: { + OptionalInt32 = input.ReadInt32(); + break; + } + case 4294960008: { + Fixed32 = input.ReadInt32(); + break; + } + case 4294960018: + case 4294960016: { + repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); + break; + } + case 4294960026: + case 4294960024: { + packedInt32_.AddEntriesFrom(input, _repeated_packedInt32_codec); + break; + } + case 4294960032: { + OptionalEnum = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum(); + break; + } + case 4294960042: { + OptionalString = input.ReadString(); + break; + } + case 4294960050: { + OptionalBytes = input.ReadBytes(); + break; + } + case 4294960058: { + if (optionalMessage_ == null) { + OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage(); + } + input.ReadMessage(OptionalMessage); + break; + } + case 4294960067: { + if (!HasOptionalGroup) { + OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestHugeFieldNumbers.Types.OptionalGroup(); + } + input.ReadGroup(OptionalGroup); + break; + } + case 4294960082: { + stringStringMap_.AddEntriesFrom(input, _map_stringStringMap_codec); + break; + } + case 4294960088: { + OneofUint32 = input.ReadUInt32(); + break; + } + case 4294960098: { + global::Google.Protobuf.TestProtos.Proto2.TestAllTypes subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes) { + subBuilder.MergeFrom(OneofTestAllTypes); + } + input.ReadMessage(subBuilder); + OneofTestAllTypes = subBuilder; + break; + } + case 4294960106: { + OneofString = input.ReadString(); + break; + } + case 4294960114: { + OneofBytes = input.ReadBytes(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + case 4294960000: { + OptionalInt32 = input.ReadInt32(); + break; + } + case 4294960008: { + Fixed32 = input.ReadInt32(); + break; + } + case 4294960018: + case 4294960016: { + repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec); + break; + } + case 4294960026: + case 4294960024: { + packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec); + break; + } + case 4294960032: { + OptionalEnum = (global::Google.Protobuf.TestProtos.Proto2.ForeignEnum) input.ReadEnum(); + break; + } + case 4294960042: { + OptionalString = input.ReadString(); + break; + } + case 4294960050: { + OptionalBytes = input.ReadBytes(); + break; + } + case 4294960058: { + if (optionalMessage_ == null) { + OptionalMessage = new global::Google.Protobuf.TestProtos.Proto2.ForeignMessage(); + } + input.ReadMessage(OptionalMessage); + break; + } + case 4294960067: { + if (!HasOptionalGroup) { + OptionalGroup = new global::Google.Protobuf.TestProtos.Proto2.TestHugeFieldNumbers.Types.OptionalGroup(); + } + input.ReadGroup(OptionalGroup); + break; + } + case 4294960082: { + stringStringMap_.AddEntriesFrom(ref input, _map_stringStringMap_codec); + break; + } + case 4294960088: { + OneofUint32 = input.ReadUInt32(); + break; + } + case 4294960098: { + global::Google.Protobuf.TestProtos.Proto2.TestAllTypes subBuilder = new global::Google.Protobuf.TestProtos.Proto2.TestAllTypes(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes) { + subBuilder.MergeFrom(OneofTestAllTypes); + } + input.ReadMessage(subBuilder); + OneofTestAllTypes = subBuilder; + break; + } + case 4294960106: { + OneofString = input.ReadString(); + break; + } + case 4294960114: { + OneofBytes = input.ReadBytes(); + break; + } + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + + #region Nested types + /// Container for nested types declared in the TestHugeFieldNumbers message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class OptionalGroup : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OptionalGroup()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.TestHugeFieldNumbers.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup(OptionalGroup other) : this() { + _hasBits0 = other._hasBits0; + groupA_ = other.groupA_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OptionalGroup Clone() { + return new OptionalGroup(this); + } + + /// Field number for the "group_a" field. + public const int GroupAFieldNumber = 536870009; + private readonly static int GroupADefaultValue = 0; + + private int groupA_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int GroupA { + get { if ((_hasBits0 & 1) != 0) { return groupA_; } else { return GroupADefaultValue; } } + set { + _hasBits0 |= 1; + groupA_ = value; + } + } + /// Gets whether the "group_a" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasGroupA { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "group_a" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearGroupA() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as OptionalGroup); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(OptionalGroup other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (GroupA != other.GroupA) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasGroupA) hash ^= GroupA.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasGroupA) { + output.WriteRawTag(200, 199, 255, 255, 15); + output.WriteInt32(GroupA); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasGroupA) { + output.WriteRawTag(200, 199, 255, 255, 15); + output.WriteInt32(GroupA); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasGroupA) { + size += 5 + pb::CodedOutputStream.ComputeInt32Size(GroupA); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(OptionalGroup other) { + if (other == null) { + return; + } + if (other.HasGroupA) { + GroupA = other.GroupA; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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) { + case 4294960068: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 4294960072: { + GroupA = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + case 4294960068: + return; + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 4294960072: { + GroupA = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class TestExtensionInsideTable : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestExtensionInsideTable()); + private pb::UnknownFieldSet _unknownFields; + private pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestReflection.Descriptor.MessageTypes[64]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtensionInsideTable() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtensionInsideTable(TestExtensionInsideTable other) : this() { + _hasBits0 = other._hasBits0; + field1_ = other.field1_; + field2_ = other.field2_; + field3_ = other.field3_; + field4_ = other.field4_; + field6_ = other.field6_; + field7_ = other.field7_; + field8_ = other.field8_; + field9_ = other.field9_; + field10_ = other.field10_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestExtensionInsideTable Clone() { + return new TestExtensionInsideTable(this); + } + + /// Field number for the "field1" field. + public const int Field1FieldNumber = 1; + private readonly static int Field1DefaultValue = 0; + + private int field1_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field1 { + get { if ((_hasBits0 & 1) != 0) { return field1_; } else { return Field1DefaultValue; } } + set { + _hasBits0 |= 1; + field1_ = value; + } + } + /// Gets whether the "field1" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasField1 { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "field1" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearField1() { + _hasBits0 &= ~1; + } + + /// Field number for the "field2" field. + public const int Field2FieldNumber = 2; + private readonly static int Field2DefaultValue = 0; + + private int field2_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field2 { + get { if ((_hasBits0 & 2) != 0) { return field2_; } else { return Field2DefaultValue; } } + set { + _hasBits0 |= 2; + field2_ = value; + } + } + /// Gets whether the "field2" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasField2 { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "field2" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearField2() { + _hasBits0 &= ~2; + } + + /// Field number for the "field3" field. + public const int Field3FieldNumber = 3; + private readonly static int Field3DefaultValue = 0; + + private int field3_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field3 { + get { if ((_hasBits0 & 4) != 0) { return field3_; } else { return Field3DefaultValue; } } + set { + _hasBits0 |= 4; + field3_ = value; + } + } + /// Gets whether the "field3" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasField3 { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "field3" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearField3() { + _hasBits0 &= ~4; + } + + /// Field number for the "field4" field. + public const int Field4FieldNumber = 4; + private readonly static int Field4DefaultValue = 0; + + private int field4_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field4 { + get { if ((_hasBits0 & 8) != 0) { return field4_; } else { return Field4DefaultValue; } } + set { + _hasBits0 |= 8; + field4_ = value; + } + } + /// Gets whether the "field4" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasField4 { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "field4" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearField4() { + _hasBits0 &= ~8; + } + + /// Field number for the "field6" field. + public const int Field6FieldNumber = 6; + private readonly static int Field6DefaultValue = 0; + + private int field6_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field6 { + get { if ((_hasBits0 & 16) != 0) { return field6_; } else { return Field6DefaultValue; } } + set { + _hasBits0 |= 16; + field6_ = value; + } + } + /// Gets whether the "field6" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasField6 { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "field6" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearField6() { + _hasBits0 &= ~16; + } + + /// Field number for the "field7" field. + public const int Field7FieldNumber = 7; + private readonly static int Field7DefaultValue = 0; + + private int field7_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field7 { + get { if ((_hasBits0 & 32) != 0) { return field7_; } else { return Field7DefaultValue; } } + set { + _hasBits0 |= 32; + field7_ = value; + } + } + /// Gets whether the "field7" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasField7 { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "field7" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearField7() { + _hasBits0 &= ~32; + } + + /// Field number for the "field8" field. + public const int Field8FieldNumber = 8; + private readonly static int Field8DefaultValue = 0; + + private int field8_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field8 { + get { if ((_hasBits0 & 64) != 0) { return field8_; } else { return Field8DefaultValue; } } + set { + _hasBits0 |= 64; + field8_ = value; + } + } + /// Gets whether the "field8" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasField8 { + get { return (_hasBits0 & 64) != 0; } + } + /// Clears the value of the "field8" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearField8() { + _hasBits0 &= ~64; + } + + /// Field number for the "field9" field. + public const int Field9FieldNumber = 9; + private readonly static int Field9DefaultValue = 0; + + private int field9_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field9 { + get { if ((_hasBits0 & 128) != 0) { return field9_; } else { return Field9DefaultValue; } } + set { + _hasBits0 |= 128; + field9_ = value; + } + } + /// Gets whether the "field9" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasField9 { + get { return (_hasBits0 & 128) != 0; } + } + /// Clears the value of the "field9" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearField9() { + _hasBits0 &= ~128; + } + + /// Field number for the "field10" field. + public const int Field10FieldNumber = 10; + private readonly static int Field10DefaultValue = 0; + + private int field10_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Field10 { + get { if ((_hasBits0 & 256) != 0) { return field10_; } else { return Field10DefaultValue; } } + set { + _hasBits0 |= 256; + field10_ = value; + } + } + /// Gets whether the "field10" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasField10 { + get { return (_hasBits0 & 256) != 0; } + } + /// Clears the value of the "field10" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearField10() { + _hasBits0 &= ~256; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestExtensionInsideTable); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestExtensionInsideTable other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Field1 != other.Field1) return false; + if (Field2 != other.Field2) return false; + if (Field3 != other.Field3) return false; + if (Field4 != other.Field4) return false; + if (Field6 != other.Field6) return false; + if (Field7 != other.Field7) return false; + if (Field8 != other.Field8) return false; + if (Field9 != other.Field9) return false; + if (Field10 != other.Field10) return false; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasField1) hash ^= Field1.GetHashCode(); + if (HasField2) hash ^= Field2.GetHashCode(); + if (HasField3) hash ^= Field3.GetHashCode(); + if (HasField4) hash ^= Field4.GetHashCode(); + if (HasField6) hash ^= Field6.GetHashCode(); + if (HasField7) hash ^= Field7.GetHashCode(); + if (HasField8) hash ^= Field8.GetHashCode(); + if (HasField9) hash ^= Field9.GetHashCode(); + if (HasField10) hash ^= Field10.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasField1) { + output.WriteRawTag(8); + output.WriteInt32(Field1); + } + if (HasField2) { + output.WriteRawTag(16); + output.WriteInt32(Field2); + } + if (HasField3) { + output.WriteRawTag(24); + output.WriteInt32(Field3); + } + if (HasField4) { + output.WriteRawTag(32); + output.WriteInt32(Field4); + } + if (HasField6) { + output.WriteRawTag(48); + output.WriteInt32(Field6); + } + if (HasField7) { + output.WriteRawTag(56); + output.WriteInt32(Field7); + } + if (HasField8) { + output.WriteRawTag(64); + output.WriteInt32(Field8); + } + if (HasField9) { + output.WriteRawTag(72); + output.WriteInt32(Field9); + } + if (HasField10) { + output.WriteRawTag(80); + output.WriteInt32(Field10); + } + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasField1) { + output.WriteRawTag(8); + output.WriteInt32(Field1); + } + if (HasField2) { + output.WriteRawTag(16); + output.WriteInt32(Field2); + } + if (HasField3) { + output.WriteRawTag(24); + output.WriteInt32(Field3); + } + if (HasField4) { + output.WriteRawTag(32); + output.WriteInt32(Field4); + } + if (HasField6) { + output.WriteRawTag(48); + output.WriteInt32(Field6); + } + if (HasField7) { + output.WriteRawTag(56); + output.WriteInt32(Field7); + } + if (HasField8) { + output.WriteRawTag(64); + output.WriteInt32(Field8); + } + if (HasField9) { + output.WriteRawTag(72); + output.WriteInt32(Field9); + } + if (HasField10) { + output.WriteRawTag(80); + output.WriteInt32(Field10); + } + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasField1) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field1); + } + if (HasField2) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field2); + } + if (HasField3) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field3); + } + if (HasField4) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field4); + } + if (HasField6) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field6); + } + if (HasField7) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field7); + } + if (HasField8) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field8); + } + if (HasField9) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field9); + } + if (HasField10) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field10); + } + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestExtensionInsideTable other) { + if (other == null) { + return; + } + if (other.HasField1) { + Field1 = other.Field1; + } + if (other.HasField2) { + Field2 = other.Field2; + } + if (other.HasField3) { + Field3 = other.Field3; + } + if (other.HasField4) { + Field4 = other.Field4; + } + if (other.HasField6) { + Field6 = other.Field6; + } + if (other.HasField7) { + Field7 = other.Field7; + } + if (other.HasField8) { + Field8 = other.Field8; + } + if (other.HasField9) { + Field9 = other.Field9; + } + if (other.HasField10) { + Field10 = other.Field10; + } + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + case 8: { + Field1 = input.ReadInt32(); + break; + } + case 16: { + Field2 = input.ReadInt32(); + break; + } + case 24: { + Field3 = input.ReadInt32(); + break; + } + case 32: { + Field4 = input.ReadInt32(); + break; + } + case 48: { + Field6 = input.ReadInt32(); + break; + } + case 56: { + Field7 = input.ReadInt32(); + break; + } + case 64: { + Field8 = input.ReadInt32(); + break; + } + case 72: { + Field9 = input.ReadInt32(); + break; + } + case 80: { + Field10 = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + case 8: { + Field1 = input.ReadInt32(); + break; + } + case 16: { + Field2 = input.ReadInt32(); + break; + } + case 24: { + Field3 = input.ReadInt32(); + break; + } + case 32: { + Field4 = input.ReadInt32(); + break; + } + case 48: { + Field6 = input.ReadInt32(); + break; + } + case 56: { + Field7 = input.ReadInt32(); + break; + } + case 64: { + Field8 = input.ReadInt32(); + break; + } + case 72: { + Field9 = input.ReadInt32(); + break; + } + case 80: { + Field10 = input.ReadInt32(); + break; + } + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs new file mode 100644 index 0000000000000..84a4a7eda20e3 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs @@ -0,0 +1,3837 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: unittest_custom_options_proto3.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace UnitTest.Issues.TestProtos { + + /// Holder for reflection information generated from unittest_custom_options_proto3.proto + public static partial class UnittestCustomOptionsProto3Reflection { + + #region Descriptor + /// File descriptor for unittest_custom_options_proto3.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestCustomOptionsProto3Reflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CiR1bml0dGVzdF9jdXN0b21fb3B0aW9uc19wcm90bzMucHJvdG8SEXByb3Rv", + "YnVmX3VuaXR0ZXN0GiBnb29nbGUvcHJvdG9idWYvZGVzY3JpcHRvci5wcm90", + "byLXAQocVGVzdE1lc3NhZ2VXaXRoQ3VzdG9tT3B0aW9ucxIeCgZmaWVsZDEY", + "ASABKAlCDggBweDDHS3hdQoCAAAAEhUKC29uZW9mX2ZpZWxkGAIgASgFSAAi", + "UwoGQW5FbnVtEhYKEkFORU5VTV9VTlNQRUNJRklFRBAAEg8KC0FORU5VTV9W", + "QUwxEAESFgoLQU5FTlVNX1ZBTDIQAhoFsIb6BXsaCMX2yR3r/P//OhAIAODp", + "wh3I//////////8BQhkKB0FuT25lb2YSDviswx2d//////////8BIhgKFkN1", + "c3RvbU9wdGlvbkZvb1JlcXVlc3QiGQoXQ3VzdG9tT3B0aW9uRm9vUmVzcG9u", + "c2UiHgocQ3VzdG9tT3B0aW9uRm9vQ2xpZW50TWVzc2FnZSIeChxDdXN0b21P", + "cHRpb25Gb29TZXJ2ZXJNZXNzYWdlIo8BChpEdW1teU1lc3NhZ2VDb250YWlu", + "aW5nRW51bSJxCgxUZXN0RW51bVR5cGUSIAocVEVTVF9PUFRJT05fRU5VTV9V", + "TlNQRUNJRklFRBAAEhoKFlRFU1RfT1BUSU9OX0VOVU1fVFlQRTEQFhIjChZU", + "RVNUX09QVElPTl9FTlVNX1RZUEUyEOn//////////wEiIQofRHVtbXlNZXNz", + "YWdlSW52YWxpZEFzT3B0aW9uVHlwZSKKAQocQ3VzdG9tT3B0aW9uTWluSW50", + "ZWdlclZhbHVlczpq0N6yHQDoxrIdgICAgPj/////AbC8sh2AgICAgICAgIAB", + "gJOyHQD49bAdAIDEsB3/////D/iXsB3///////////8BnfWvHQAAAACR7q8d", + "AAAAAAAAAACtja8dAAAAgJnWqB0AAAAAAAAAgCKRAQocQ3VzdG9tT3B0aW9u", + "TWF4SW50ZWdlclZhbHVlczpx0N6yHQHoxrId/////wewvLId//////////9/", + "gJOyHf////8P+PWwHf///////////wGAxLAd/v///w/4l7Ad/v//////////", + "AZ31rx3/////ke6vHf//////////rY2vHf///3+Z1qgd/////////38ibgoX", + "Q3VzdG9tT3B0aW9uT3RoZXJWYWx1ZXM6U+jGsh2c//////////8B9d+jHeeH", + "RUHp3KId+1mMQsrA8z+q3KIdDkhlbGxvLCAiV29ybGQistmiHQtIZWxsbwBX", + "b3JsZIjZoh3p//////////8BIjQKHFNldHRpbmdSZWFsc0Zyb21Qb3NpdGl2", + "ZUludHM6FPXfox0AAEBB6dyiHQAAAAAAQGNAIjQKHFNldHRpbmdSZWFsc0Zy", + "b21OZWdhdGl2ZUludHM6FPXfox0AAEDB6dyiHQAAAAAAQGPAIksKEkNvbXBs", + "ZXhPcHRpb25UeXBlMRILCgNmb28YASABKAUSDAoEZm9vMhgCIAEoBRIMCgRm", + "b28zGAMgASgFEgwKBGZvbzQYBCADKAUigQMKEkNvbXBsZXhPcHRpb25UeXBl", + "MhIyCgNiYXIYASABKAsyJS5wcm90b2J1Zl91bml0dGVzdC5Db21wbGV4T3B0", + "aW9uVHlwZTESCwoDYmF6GAIgASgFEkYKBGZyZWQYAyABKAsyOC5wcm90b2J1", + "Zl91bml0dGVzdC5Db21wbGV4T3B0aW9uVHlwZTIuQ29tcGxleE9wdGlvblR5", + "cGU0EkgKBmJhcm5leRgEIAMoCzI4LnByb3RvYnVmX3VuaXR0ZXN0LkNvbXBs", + "ZXhPcHRpb25UeXBlMi5Db21wbGV4T3B0aW9uVHlwZTQalwEKEkNvbXBsZXhP", + "cHRpb25UeXBlNBINCgV3YWxkbxgBIAEoBTJyCgxjb21wbGV4X29wdDQSHy5n", + "b29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMYivXRAyABKAsyOC5wcm90", + "b2J1Zl91bml0dGVzdC5Db21wbGV4T3B0aW9uVHlwZTIuQ29tcGxleE9wdGlv", + "blR5cGU0IiEKEkNvbXBsZXhPcHRpb25UeXBlMxILCgNxdXgYASABKAUibAoV", + "VmFyaW91c0NvbXBsZXhPcHRpb25zOlOi4pUdAggqouKVHQIgY6LilR0CIFiq", + "/ZAdAxDbB6r9kB0FCgMI5wXSqI8dAwizD6r9kB0FGgMIwQKq/ZAdBCICCGWq", + "/ZAdBSIDCNQB+t6QHQIICSJMCglBZ2dyZWdhdGUSCQoBaRgBIAEoBRIJCgFz", + "GAIgASgJEikKA3N1YhgDIAEoCzIcLnByb3RvYnVmX3VuaXR0ZXN0LkFnZ3Jl", + "Z2F0ZSJZChBBZ2dyZWdhdGVNZXNzYWdlEikKCWZpZWxkbmFtZRgBIAEoBUIW", + "8qGHOxESD0ZpZWxkQW5ub3RhdGlvbjoawtGGOxUIZRIRTWVzc2FnZUFubm90", + "YXRpb24ilwEKEE5lc3RlZE9wdGlvblR5cGUaOwoNTmVzdGVkTWVzc2FnZRIi", + "CgxuZXN0ZWRfZmllbGQYASABKAVCDMHgwx3qAwAAAAAAADoG4OnCHekHIkYK", + "Ck5lc3RlZEVudW0SDwoLVU5TUEVDSUZJRUQQABIdChFORVNURURfRU5VTV9W", + "QUxVRRABGgawhvoF7AcaCMX2yR3rAwAAKlIKCk1ldGhvZE9wdDESGgoWTUVU", + "SE9ET1BUMV9VTlNQRUNJRklFRBAAEhMKD01FVEhPRE9QVDFfVkFMMRABEhMK", + "D01FVEhPRE9QVDFfVkFMMhACKl4KDUFnZ3JlZ2F0ZUVudW0SDwoLVU5TUEVD", + "SUZJRUQQABIlCgVWQUxVRRABGhrK/Ik7FRITRW51bVZhbHVlQW5ub3RhdGlv", + "bhoVkpWIOxASDkVudW1Bbm5vdGF0aW9uMo4BChxUZXN0U2VydmljZVdpdGhD", + "dXN0b21PcHRpb25zEmMKA0ZvbxIpLnByb3RvYnVmX3VuaXR0ZXN0LkN1c3Rv", + "bU9wdGlvbkZvb1JlcXVlc3QaKi5wcm90b2J1Zl91bml0dGVzdC5DdXN0b21P", + "cHRpb25Gb29SZXNwb25zZSIF4PqMHgIaCZCyix7T24DLSTKZAQoQQWdncmVn", + "YXRlU2VydmljZRJrCgZNZXRob2QSIy5wcm90b2J1Zl91bml0dGVzdC5BZ2dy", + "ZWdhdGVNZXNzYWdlGiMucHJvdG9idWZfdW5pdHRlc3QuQWdncmVnYXRlTWVz", + "c2FnZSIXysiWOxISEE1ldGhvZEFubm90YXRpb24aGMr7jjsTEhFTZXJ2aWNl", + "QW5ub3RhdGlvbjoyCglmaWxlX29wdDESHC5nb29nbGUucHJvdG9idWYuRmls", + "ZU9wdGlvbnMYjp3YAyABKAQ6OAoMbWVzc2FnZV9vcHQxEh8uZ29vZ2xlLnBy", + "b3RvYnVmLk1lc3NhZ2VPcHRpb25zGJyt2AMgASgFOjQKCmZpZWxkX29wdDES", + "HS5nb29nbGUucHJvdG9idWYuRmllbGRPcHRpb25zGIi82AMgASgGOjQKCm9u", + "ZW9mX29wdDESHS5nb29nbGUucHJvdG9idWYuT25lb2ZPcHRpb25zGM+12AMg", + "ASgFOjIKCWVudW1fb3B0MRIcLmdvb2dsZS5wcm90b2J1Zi5FbnVtT3B0aW9u", + "cxjontkDIAEoDzo8Cg9lbnVtX3ZhbHVlX29wdDESIS5nb29nbGUucHJvdG9i", + "dWYuRW51bVZhbHVlT3B0aW9ucxjmoF8gASgFOjgKDHNlcnZpY2Vfb3B0MRIf", + "Lmdvb2dsZS5wcm90b2J1Zi5TZXJ2aWNlT3B0aW9ucxiituEDIAEoEjpVCgtt", + "ZXRob2Rfb3B0MRIeLmdvb2dsZS5wcm90b2J1Zi5NZXRob2RPcHRpb25zGKzP", + "4QMgASgOMh0ucHJvdG9idWZfdW5pdHRlc3QuTWV0aG9kT3B0MTo0Cghib29s", + "X29wdBIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxjqq9YDIAEo", + "CDo1CglpbnQzMl9vcHQSHy5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlv", + "bnMY7ajWAyABKAU6NQoJaW50NjRfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1l", + "c3NhZ2VPcHRpb25zGMan1gMgASgDOjYKCnVpbnQzMl9vcHQSHy5nb29nbGUu", + "cHJvdG9idWYuTWVzc2FnZU9wdGlvbnMYsKLWAyABKA06NgoKdWludDY0X29w", + "dBIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxjfjtYDIAEoBDo2", + "CgpzaW50MzJfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRpb25z", + "GMCI1gMgASgROjYKCnNpbnQ2NF9vcHQSHy5nb29nbGUucHJvdG9idWYuTWVz", + "c2FnZU9wdGlvbnMY/4LWAyABKBI6NwoLZml4ZWQzMl9vcHQSHy5nb29nbGUu", + "cHJvdG9idWYuTWVzc2FnZU9wdGlvbnMY0/7VAyABKAc6NwoLZml4ZWQ2NF9v", + "cHQSHy5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMY4v3VAyABKAY6", + "OAoMc2ZpeGVkMzJfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRp", + "b25zGNXx1QMgASgPOjgKDHNmaXhlZDY0X29wdBIfLmdvb2dsZS5wcm90b2J1", + "Zi5NZXNzYWdlT3B0aW9ucxjjitUDIAEoEDo1CglmbG9hdF9vcHQSHy5nb29n", + "bGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMY/rvUAyABKAI6NgoKZG91Ymxl", + "X29wdBIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxjNq9QDIAEo", + "ATo2CgpzdHJpbmdfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRp", + "b25zGMWr1AMgASgJOjUKCWJ5dGVzX29wdBIfLmdvb2dsZS5wcm90b2J1Zi5N", + "ZXNzYWdlT3B0aW9ucxiWq9QDIAEoDDpwCghlbnVtX29wdBIfLmdvb2dsZS5w", + "cm90b2J1Zi5NZXNzYWdlT3B0aW9ucxiRq9QDIAEoDjI6LnByb3RvYnVmX3Vu", + "aXR0ZXN0LkR1bW15TWVzc2FnZUNvbnRhaW5pbmdFbnVtLlRlc3RFbnVtVHlw", + "ZTpwChBtZXNzYWdlX3R5cGVfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3Nh", + "Z2VPcHRpb25zGK/y0wMgASgLMjIucHJvdG9idWZfdW5pdHRlc3QuRHVtbXlN", + "ZXNzYWdlSW52YWxpZEFzT3B0aW9uVHlwZTpfCgxjb21wbGV4X29wdDESHy5n", + "b29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMYpNzSAyABKAsyJS5wcm90", + "b2J1Zl91bml0dGVzdC5Db21wbGV4T3B0aW9uVHlwZTE6XwoMY29tcGxleF9v", + "cHQyEh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRpb25zGNWP0gMgASgL", + "MiUucHJvdG9idWZfdW5pdHRlc3QuQ29tcGxleE9wdGlvblR5cGUyOl8KDGNv", + "bXBsZXhfb3B0MxIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxjv", + "i9IDIAEoCzIlLnByb3RvYnVmX3VuaXR0ZXN0LkNvbXBsZXhPcHRpb25UeXBl", + "MzpOCgdmaWxlb3B0EhwuZ29vZ2xlLnByb3RvYnVmLkZpbGVPcHRpb25zGM/d", + "sAcgASgLMhwucHJvdG9idWZfdW5pdHRlc3QuQWdncmVnYXRlOlAKBm1zZ29w", + "dBIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxiY6rAHIAEoCzIc", + "LnByb3RvYnVmX3VuaXR0ZXN0LkFnZ3JlZ2F0ZTpQCghmaWVsZG9wdBIdLmdv", + "b2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMYnvSwByABKAsyHC5wcm90b2J1", + "Zl91bml0dGVzdC5BZ2dyZWdhdGU6TgoHZW51bW9wdBIcLmdvb2dsZS5wcm90", + "b2J1Zi5FbnVtT3B0aW9ucxjSgrEHIAEoCzIcLnByb3RvYnVmX3VuaXR0ZXN0", + "LkFnZ3JlZ2F0ZTpWCgplbnVtdmFsb3B0EiEuZ29vZ2xlLnByb3RvYnVmLkVu", + "dW1WYWx1ZU9wdGlvbnMYyZ+xByABKAsyHC5wcm90b2J1Zl91bml0dGVzdC5B", + "Z2dyZWdhdGU6VAoKc2VydmljZW9wdBIfLmdvb2dsZS5wcm90b2J1Zi5TZXJ2", + "aWNlT3B0aW9ucxi577EHIAEoCzIcLnByb3RvYnVmX3VuaXR0ZXN0LkFnZ3Jl", + "Z2F0ZTpSCgltZXRob2RvcHQSHi5nb29nbGUucHJvdG9idWYuTWV0aG9kT3B0", + "aW9ucxiJ6bIHIAEoCzIcLnByb3RvYnVmX3VuaXR0ZXN0LkFnZ3JlZ2F0ZUJV", + "qgIaVW5pdFRlc3QuSXNzdWVzLlRlc3RQcm90b3Pw6MEd6q3A5ST67IU7Kghk", + "Eg5GaWxlQW5ub3RhdGlvbhoWEhROZXN0ZWRGaWxlQW5ub3RhdGlvbmIGcHJv", + "dG8z")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.MethodOpt1), typeof(global::UnitTest.Issues.TestProtos.AggregateEnum), }, new pb::Extension[] { UnittestCustomOptionsProto3Extensions.FileOpt1, UnittestCustomOptionsProto3Extensions.MessageOpt1, UnittestCustomOptionsProto3Extensions.FieldOpt1, UnittestCustomOptionsProto3Extensions.OneofOpt1, UnittestCustomOptionsProto3Extensions.EnumOpt1, UnittestCustomOptionsProto3Extensions.EnumValueOpt1, UnittestCustomOptionsProto3Extensions.ServiceOpt1, UnittestCustomOptionsProto3Extensions.MethodOpt1, UnittestCustomOptionsProto3Extensions.BoolOpt, UnittestCustomOptionsProto3Extensions.Int32Opt, UnittestCustomOptionsProto3Extensions.Int64Opt, UnittestCustomOptionsProto3Extensions.Uint32Opt, UnittestCustomOptionsProto3Extensions.Uint64Opt, UnittestCustomOptionsProto3Extensions.Sint32Opt, UnittestCustomOptionsProto3Extensions.Sint64Opt, UnittestCustomOptionsProto3Extensions.Fixed32Opt, UnittestCustomOptionsProto3Extensions.Fixed64Opt, UnittestCustomOptionsProto3Extensions.Sfixed32Opt, UnittestCustomOptionsProto3Extensions.Sfixed64Opt, UnittestCustomOptionsProto3Extensions.FloatOpt, UnittestCustomOptionsProto3Extensions.DoubleOpt, UnittestCustomOptionsProto3Extensions.StringOpt, UnittestCustomOptionsProto3Extensions.BytesOpt, UnittestCustomOptionsProto3Extensions.EnumOpt, UnittestCustomOptionsProto3Extensions.MessageTypeOpt, UnittestCustomOptionsProto3Extensions.ComplexOpt1, UnittestCustomOptionsProto3Extensions.ComplexOpt2, UnittestCustomOptionsProto3Extensions.ComplexOpt3, UnittestCustomOptionsProto3Extensions.Fileopt, UnittestCustomOptionsProto3Extensions.Msgopt, UnittestCustomOptionsProto3Extensions.Fieldopt, UnittestCustomOptionsProto3Extensions.Enumopt, UnittestCustomOptionsProto3Extensions.Enumvalopt, UnittestCustomOptionsProto3Extensions.Serviceopt, UnittestCustomOptionsProto3Extensions.Methodopt }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestMessageWithCustomOptions), global::UnitTest.Issues.TestProtos.TestMessageWithCustomOptions.Parser, new[]{ "Field1", "OneofField" }, new[]{ "AnOneof" }, new[]{ typeof(global::UnitTest.Issues.TestProtos.TestMessageWithCustomOptions.Types.AnEnum) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionFooRequest), global::UnitTest.Issues.TestProtos.CustomOptionFooRequest.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionFooResponse), global::UnitTest.Issues.TestProtos.CustomOptionFooResponse.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionFooClientMessage), global::UnitTest.Issues.TestProtos.CustomOptionFooClientMessage.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionFooServerMessage), global::UnitTest.Issues.TestProtos.CustomOptionFooServerMessage.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DummyMessageContainingEnum), global::UnitTest.Issues.TestProtos.DummyMessageContainingEnum.Parser, null, null, new[]{ typeof(global::UnitTest.Issues.TestProtos.DummyMessageContainingEnum.Types.TestEnumType) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DummyMessageInvalidAsOptionType), global::UnitTest.Issues.TestProtos.DummyMessageInvalidAsOptionType.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionMinIntegerValues), global::UnitTest.Issues.TestProtos.CustomOptionMinIntegerValues.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionMaxIntegerValues), global::UnitTest.Issues.TestProtos.CustomOptionMaxIntegerValues.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionOtherValues), global::UnitTest.Issues.TestProtos.CustomOptionOtherValues.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.SettingRealsFromPositiveInts), global::UnitTest.Issues.TestProtos.SettingRealsFromPositiveInts.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.SettingRealsFromNegativeInts), global::UnitTest.Issues.TestProtos.SettingRealsFromNegativeInts.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ComplexOptionType1), global::UnitTest.Issues.TestProtos.ComplexOptionType1.Parser, new[]{ "Foo", "Foo2", "Foo3", "Foo4" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ComplexOptionType2), global::UnitTest.Issues.TestProtos.ComplexOptionType2.Parser, new[]{ "Bar", "Baz", "Fred", "Barney" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4), global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Parser, new[]{ "Waldo" }, null, null, new pb::Extension[] { global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Extensions.ComplexOpt4 }, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ComplexOptionType3), global::UnitTest.Issues.TestProtos.ComplexOptionType3.Parser, new[]{ "Qux" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.VariousComplexOptions), global::UnitTest.Issues.TestProtos.VariousComplexOptions.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Aggregate), global::UnitTest.Issues.TestProtos.Aggregate.Parser, new[]{ "I", "S", "Sub" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.AggregateMessage), global::UnitTest.Issues.TestProtos.AggregateMessage.Parser, new[]{ "Fieldname" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NestedOptionType), global::UnitTest.Issues.TestProtos.NestedOptionType.Parser, null, null, new[]{ typeof(global::UnitTest.Issues.TestProtos.NestedOptionType.Types.NestedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NestedOptionType.Types.NestedMessage), global::UnitTest.Issues.TestProtos.NestedOptionType.Types.NestedMessage.Parser, new[]{ "NestedField" }, null, null, null, null)}) + })); + } + #endregion + + } + /// Holder for extension identifiers generated from the top level of unittest_custom_options_proto3.proto + public static partial class UnittestCustomOptionsProto3Extensions { + public static readonly pb::Extension FileOpt1 = + new pb::Extension(7736974, pb::FieldCodec.ForUInt64(61895792, 0UL)); + public static readonly pb::Extension MessageOpt1 = + new pb::Extension(7739036, pb::FieldCodec.ForInt32(61912288, 0)); + public static readonly pb::Extension FieldOpt1 = + new pb::Extension(7740936, pb::FieldCodec.ForFixed64(61927489, 0UL)); + public static readonly pb::Extension OneofOpt1 = + new pb::Extension(7740111, pb::FieldCodec.ForInt32(61920888, 0)); + public static readonly pb::Extension EnumOpt1 = + new pb::Extension(7753576, pb::FieldCodec.ForSFixed32(62028613, 0)); + public static readonly pb::Extension EnumValueOpt1 = + new pb::Extension(1560678, pb::FieldCodec.ForInt32(12485424, 0)); + public static readonly pb::Extension ServiceOpt1 = + new pb::Extension(7887650, pb::FieldCodec.ForSInt64(63101200, 0L)); + public static readonly pb::Extension MethodOpt1 = + new pb::Extension(7890860, pb::FieldCodec.ForEnum(63126880, x => (int) x, x => (global::UnitTest.Issues.TestProtos.MethodOpt1) x, global::UnitTest.Issues.TestProtos.MethodOpt1.Unspecified)); + public static readonly pb::Extension BoolOpt = + new pb::Extension(7706090, pb::FieldCodec.ForBool(61648720, false)); + public static readonly pb::Extension Int32Opt = + new pb::Extension(7705709, pb::FieldCodec.ForInt32(61645672, 0)); + public static readonly pb::Extension Int64Opt = + new pb::Extension(7705542, pb::FieldCodec.ForInt64(61644336, 0L)); + public static readonly pb::Extension Uint32Opt = + new pb::Extension(7704880, pb::FieldCodec.ForUInt32(61639040, 0)); + public static readonly pb::Extension Uint64Opt = + new pb::Extension(7702367, pb::FieldCodec.ForUInt64(61618936, 0UL)); + public static readonly pb::Extension Sint32Opt = + new pb::Extension(7701568, pb::FieldCodec.ForSInt32(61612544, 0)); + public static readonly pb::Extension Sint64Opt = + new pb::Extension(7700863, pb::FieldCodec.ForSInt64(61606904, 0L)); + public static readonly pb::Extension Fixed32Opt = + new pb::Extension(7700307, pb::FieldCodec.ForFixed32(61602461, 0)); + public static readonly pb::Extension Fixed64Opt = + new pb::Extension(7700194, pb::FieldCodec.ForFixed64(61601553, 0UL)); + public static readonly pb::Extension Sfixed32Opt = + new pb::Extension(7698645, pb::FieldCodec.ForSFixed32(61589165, 0)); + public static readonly pb::Extension Sfixed64Opt = + new pb::Extension(7685475, pb::FieldCodec.ForSFixed64(61483801, 0L)); + public static readonly pb::Extension FloatOpt = + new pb::Extension(7675390, pb::FieldCodec.ForFloat(61403125, 0F)); + public static readonly pb::Extension DoubleOpt = + new pb::Extension(7673293, pb::FieldCodec.ForDouble(61386345, 0D)); + public static readonly pb::Extension StringOpt = + new pb::Extension(7673285, pb::FieldCodec.ForString(61386282, "")); + public static readonly pb::Extension BytesOpt = + new pb::Extension(7673238, pb::FieldCodec.ForBytes(61385906, pb::ByteString.Empty)); + public static readonly pb::Extension EnumOpt = + new pb::Extension(7673233, pb::FieldCodec.ForEnum(61385864, x => (int) x, x => (global::UnitTest.Issues.TestProtos.DummyMessageContainingEnum.Types.TestEnumType) x, global::UnitTest.Issues.TestProtos.DummyMessageContainingEnum.Types.TestEnumType.TestOptionEnumUnspecified)); + public static readonly pb::Extension MessageTypeOpt = + new pb::Extension(7665967, pb::FieldCodec.ForMessage(61327738, global::UnitTest.Issues.TestProtos.DummyMessageInvalidAsOptionType.Parser)); + public static readonly pb::Extension ComplexOpt1 = + new pb::Extension(7646756, pb::FieldCodec.ForMessage(61174050, global::UnitTest.Issues.TestProtos.ComplexOptionType1.Parser)); + public static readonly pb::Extension ComplexOpt2 = + new pb::Extension(7636949, pb::FieldCodec.ForMessage(61095594, global::UnitTest.Issues.TestProtos.ComplexOptionType2.Parser)); + public static readonly pb::Extension ComplexOpt3 = + new pb::Extension(7636463, pb::FieldCodec.ForMessage(61091706, global::UnitTest.Issues.TestProtos.ComplexOptionType3.Parser)); + public static readonly pb::Extension Fileopt = + new pb::Extension(15478479, pb::FieldCodec.ForMessage(123827834, global::UnitTest.Issues.TestProtos.Aggregate.Parser)); + public static readonly pb::Extension Msgopt = + new pb::Extension(15480088, pb::FieldCodec.ForMessage(123840706, global::UnitTest.Issues.TestProtos.Aggregate.Parser)); + public static readonly pb::Extension Fieldopt = + new pb::Extension(15481374, pb::FieldCodec.ForMessage(123850994, global::UnitTest.Issues.TestProtos.Aggregate.Parser)); + public static readonly pb::Extension Enumopt = + new pb::Extension(15483218, pb::FieldCodec.ForMessage(123865746, global::UnitTest.Issues.TestProtos.Aggregate.Parser)); + public static readonly pb::Extension Enumvalopt = + new pb::Extension(15486921, pb::FieldCodec.ForMessage(123895370, global::UnitTest.Issues.TestProtos.Aggregate.Parser)); + public static readonly pb::Extension Serviceopt = + new pb::Extension(15497145, pb::FieldCodec.ForMessage(123977162, global::UnitTest.Issues.TestProtos.Aggregate.Parser)); + public static readonly pb::Extension Methodopt = + new pb::Extension(15512713, pb::FieldCodec.ForMessage(124101706, global::UnitTest.Issues.TestProtos.Aggregate.Parser)); + } + + #region Enums + public enum MethodOpt1 { + [pbr::OriginalName("METHODOPT1_UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("METHODOPT1_VAL1")] Val1 = 1, + [pbr::OriginalName("METHODOPT1_VAL2")] Val2 = 2, + } + + public enum AggregateEnum { + [pbr::OriginalName("UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("VALUE")] Value = 1, + } + + #endregion + + #region Messages + /// + /// A test message with custom options at all possible locations (and also some + /// regular options, to make sure they interact nicely). + /// + public sealed partial class TestMessageWithCustomOptions : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMessageWithCustomOptions()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessageWithCustomOptions() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessageWithCustomOptions(TestMessageWithCustomOptions other) : this() { + field1_ = other.field1_; + switch (other.AnOneofCase) { + case AnOneofOneofCase.OneofField: + OneofField = other.OneofField; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessageWithCustomOptions Clone() { + return new TestMessageWithCustomOptions(this); + } + + /// Field number for the "field1" field. + public const int Field1FieldNumber = 1; + private string field1_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Field1 { + get { return field1_; } + set { + field1_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "oneof_field" field. + public const int OneofFieldFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OneofField { + get { return anOneofCase_ == AnOneofOneofCase.OneofField ? (int) anOneof_ : 0; } + set { + anOneof_ = value; + anOneofCase_ = AnOneofOneofCase.OneofField; + } + } + + private object anOneof_; + /// Enum of possible cases for the "AnOneof" oneof. + public enum AnOneofOneofCase { + None = 0, + OneofField = 2, + } + private AnOneofOneofCase anOneofCase_ = AnOneofOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public AnOneofOneofCase AnOneofCase { + get { return anOneofCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearAnOneof() { + anOneofCase_ = AnOneofOneofCase.None; + anOneof_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestMessageWithCustomOptions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestMessageWithCustomOptions other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Field1 != other.Field1) return false; + if (OneofField != other.OneofField) return false; + if (AnOneofCase != other.AnOneofCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Field1.Length != 0) hash ^= Field1.GetHashCode(); + if (anOneofCase_ == AnOneofOneofCase.OneofField) hash ^= OneofField.GetHashCode(); + hash ^= (int) anOneofCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Field1.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Field1); + } + if (anOneofCase_ == AnOneofOneofCase.OneofField) { + output.WriteRawTag(16); + output.WriteInt32(OneofField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Field1.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Field1); + } + if (anOneofCase_ == AnOneofOneofCase.OneofField) { + output.WriteRawTag(16); + output.WriteInt32(OneofField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Field1.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Field1); + } + if (anOneofCase_ == AnOneofOneofCase.OneofField) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(OneofField); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestMessageWithCustomOptions other) { + if (other == null) { + return; + } + if (other.Field1.Length != 0) { + Field1 = other.Field1; + } + switch (other.AnOneofCase) { + case AnOneofOneofCase.OneofField: + OneofField = other.OneofField; + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Field1 = input.ReadString(); + break; + } + case 16: { + OneofField = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Field1 = input.ReadString(); + break; + } + case 16: { + OneofField = input.ReadInt32(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestMessageWithCustomOptions message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum AnEnum { + [pbr::OriginalName("ANENUM_UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("ANENUM_VAL1")] Val1 = 1, + [pbr::OriginalName("ANENUM_VAL2")] Val2 = 2, + } + + } + #endregion + + } + + /// + /// A test RPC service with custom options at all possible locations (and also + /// some regular options, to make sure they interact nicely). + /// + public sealed partial class CustomOptionFooRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooRequest(CustomOptionFooRequest other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooRequest Clone() { + return new CustomOptionFooRequest(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomOptionFooRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomOptionFooRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomOptionFooRequest other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class CustomOptionFooResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooResponse(CustomOptionFooResponse other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooResponse Clone() { + return new CustomOptionFooResponse(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomOptionFooResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomOptionFooResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomOptionFooResponse other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class CustomOptionFooClientMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooClientMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooClientMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooClientMessage(CustomOptionFooClientMessage other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooClientMessage Clone() { + return new CustomOptionFooClientMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomOptionFooClientMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomOptionFooClientMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomOptionFooClientMessage other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class CustomOptionFooServerMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooServerMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooServerMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooServerMessage(CustomOptionFooServerMessage other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooServerMessage Clone() { + return new CustomOptionFooServerMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomOptionFooServerMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomOptionFooServerMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomOptionFooServerMessage other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class DummyMessageContainingEnum : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DummyMessageContainingEnum()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DummyMessageContainingEnum() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DummyMessageContainingEnum(DummyMessageContainingEnum other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DummyMessageContainingEnum Clone() { + return new DummyMessageContainingEnum(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as DummyMessageContainingEnum); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(DummyMessageContainingEnum other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(DummyMessageContainingEnum other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the DummyMessageContainingEnum message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum TestEnumType { + [pbr::OriginalName("TEST_OPTION_ENUM_UNSPECIFIED")] TestOptionEnumUnspecified = 0, + [pbr::OriginalName("TEST_OPTION_ENUM_TYPE1")] TestOptionEnumType1 = 22, + [pbr::OriginalName("TEST_OPTION_ENUM_TYPE2")] TestOptionEnumType2 = -23, + } + + } + #endregion + + } + + public sealed partial class DummyMessageInvalidAsOptionType : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DummyMessageInvalidAsOptionType()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[6]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DummyMessageInvalidAsOptionType() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DummyMessageInvalidAsOptionType(DummyMessageInvalidAsOptionType other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DummyMessageInvalidAsOptionType Clone() { + return new DummyMessageInvalidAsOptionType(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as DummyMessageInvalidAsOptionType); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(DummyMessageInvalidAsOptionType other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(DummyMessageInvalidAsOptionType other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class CustomOptionMinIntegerValues : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionMinIntegerValues()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[7]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionMinIntegerValues() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionMinIntegerValues(CustomOptionMinIntegerValues other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionMinIntegerValues Clone() { + return new CustomOptionMinIntegerValues(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomOptionMinIntegerValues); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomOptionMinIntegerValues other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomOptionMinIntegerValues other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class CustomOptionMaxIntegerValues : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionMaxIntegerValues()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[8]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionMaxIntegerValues() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionMaxIntegerValues(CustomOptionMaxIntegerValues other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionMaxIntegerValues Clone() { + return new CustomOptionMaxIntegerValues(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomOptionMaxIntegerValues); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomOptionMaxIntegerValues other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomOptionMaxIntegerValues other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class CustomOptionOtherValues : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionOtherValues()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[9]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionOtherValues() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionOtherValues(CustomOptionOtherValues other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionOtherValues Clone() { + return new CustomOptionOtherValues(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomOptionOtherValues); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomOptionOtherValues other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomOptionOtherValues other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class SettingRealsFromPositiveInts : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SettingRealsFromPositiveInts()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[10]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SettingRealsFromPositiveInts() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SettingRealsFromPositiveInts(SettingRealsFromPositiveInts other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SettingRealsFromPositiveInts Clone() { + return new SettingRealsFromPositiveInts(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SettingRealsFromPositiveInts); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SettingRealsFromPositiveInts other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SettingRealsFromPositiveInts other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class SettingRealsFromNegativeInts : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SettingRealsFromNegativeInts()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[11]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SettingRealsFromNegativeInts() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SettingRealsFromNegativeInts(SettingRealsFromNegativeInts other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SettingRealsFromNegativeInts Clone() { + return new SettingRealsFromNegativeInts(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SettingRealsFromNegativeInts); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SettingRealsFromNegativeInts other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SettingRealsFromNegativeInts other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class ComplexOptionType1 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType1()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[12]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType1() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType1(ComplexOptionType1 other) : this() { + foo_ = other.foo_; + foo2_ = other.foo2_; + foo3_ = other.foo3_; + foo4_ = other.foo4_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType1 Clone() { + return new ComplexOptionType1(this); + } + + /// Field number for the "foo" field. + public const int FooFieldNumber = 1; + private int foo_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Foo { + get { return foo_; } + set { + foo_ = value; + } + } + + /// Field number for the "foo2" field. + public const int Foo2FieldNumber = 2; + private int foo2_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Foo2 { + get { return foo2_; } + set { + foo2_ = value; + } + } + + /// Field number for the "foo3" field. + public const int Foo3FieldNumber = 3; + private int foo3_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Foo3 { + get { return foo3_; } + set { + foo3_ = value; + } + } + + /// Field number for the "foo4" field. + public const int Foo4FieldNumber = 4; + private static readonly pb::FieldCodec _repeated_foo4_codec + = pb::FieldCodec.ForInt32(34); + private readonly pbc::RepeatedField foo4_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Foo4 { + get { return foo4_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ComplexOptionType1); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ComplexOptionType1 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Foo != other.Foo) return false; + if (Foo2 != other.Foo2) return false; + if (Foo3 != other.Foo3) return false; + if(!foo4_.Equals(other.foo4_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Foo != 0) hash ^= Foo.GetHashCode(); + if (Foo2 != 0) hash ^= Foo2.GetHashCode(); + if (Foo3 != 0) hash ^= Foo3.GetHashCode(); + hash ^= foo4_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Foo != 0) { + output.WriteRawTag(8); + output.WriteInt32(Foo); + } + if (Foo2 != 0) { + output.WriteRawTag(16); + output.WriteInt32(Foo2); + } + if (Foo3 != 0) { + output.WriteRawTag(24); + output.WriteInt32(Foo3); + } + foo4_.WriteTo(output, _repeated_foo4_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Foo != 0) { + output.WriteRawTag(8); + output.WriteInt32(Foo); + } + if (Foo2 != 0) { + output.WriteRawTag(16); + output.WriteInt32(Foo2); + } + if (Foo3 != 0) { + output.WriteRawTag(24); + output.WriteInt32(Foo3); + } + foo4_.WriteTo(ref output, _repeated_foo4_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Foo != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Foo); + } + if (Foo2 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Foo2); + } + if (Foo3 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Foo3); + } + size += foo4_.CalculateSize(_repeated_foo4_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ComplexOptionType1 other) { + if (other == null) { + return; + } + if (other.Foo != 0) { + Foo = other.Foo; + } + if (other.Foo2 != 0) { + Foo2 = other.Foo2; + } + if (other.Foo3 != 0) { + Foo3 = other.Foo3; + } + foo4_.Add(other.foo4_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Foo = input.ReadInt32(); + break; + } + case 16: { + Foo2 = input.ReadInt32(); + break; + } + case 24: { + Foo3 = input.ReadInt32(); + break; + } + case 34: + case 32: { + foo4_.AddEntriesFrom(input, _repeated_foo4_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Foo = input.ReadInt32(); + break; + } + case 16: { + Foo2 = input.ReadInt32(); + break; + } + case 24: { + Foo3 = input.ReadInt32(); + break; + } + case 34: + case 32: { + foo4_.AddEntriesFrom(ref input, _repeated_foo4_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class ComplexOptionType2 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType2()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[13]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType2() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType2(ComplexOptionType2 other) : this() { + bar_ = other.bar_ != null ? other.bar_.Clone() : null; + baz_ = other.baz_; + fred_ = other.fred_ != null ? other.fred_.Clone() : null; + barney_ = other.barney_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType2 Clone() { + return new ComplexOptionType2(this); + } + + /// Field number for the "bar" field. + public const int BarFieldNumber = 1; + private global::UnitTest.Issues.TestProtos.ComplexOptionType1 bar_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::UnitTest.Issues.TestProtos.ComplexOptionType1 Bar { + get { return bar_; } + set { + bar_ = value; + } + } + + /// Field number for the "baz" field. + public const int BazFieldNumber = 2; + private int baz_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Baz { + get { return baz_; } + set { + baz_ = value; + } + } + + /// Field number for the "fred" field. + public const int FredFieldNumber = 3; + private global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 fred_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 Fred { + get { return fred_; } + set { + fred_ = value; + } + } + + /// Field number for the "barney" field. + public const int BarneyFieldNumber = 4; + private static readonly pb::FieldCodec _repeated_barney_codec + = pb::FieldCodec.ForMessage(34, global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Parser); + private readonly pbc::RepeatedField barney_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Barney { + get { return barney_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ComplexOptionType2); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ComplexOptionType2 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Bar, other.Bar)) return false; + if (Baz != other.Baz) return false; + if (!object.Equals(Fred, other.Fred)) return false; + if(!barney_.Equals(other.barney_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (bar_ != null) hash ^= Bar.GetHashCode(); + if (Baz != 0) hash ^= Baz.GetHashCode(); + if (fred_ != null) hash ^= Fred.GetHashCode(); + hash ^= barney_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (bar_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Bar); + } + if (Baz != 0) { + output.WriteRawTag(16); + output.WriteInt32(Baz); + } + if (fred_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Fred); + } + barney_.WriteTo(output, _repeated_barney_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (bar_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Bar); + } + if (Baz != 0) { + output.WriteRawTag(16); + output.WriteInt32(Baz); + } + if (fred_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Fred); + } + barney_.WriteTo(ref output, _repeated_barney_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (bar_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Bar); + } + if (Baz != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Baz); + } + if (fred_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Fred); + } + size += barney_.CalculateSize(_repeated_barney_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ComplexOptionType2 other) { + if (other == null) { + return; + } + if (other.bar_ != null) { + if (bar_ == null) { + Bar = new global::UnitTest.Issues.TestProtos.ComplexOptionType1(); + } + Bar.MergeFrom(other.Bar); + } + if (other.Baz != 0) { + Baz = other.Baz; + } + if (other.fred_ != null) { + if (fred_ == null) { + Fred = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4(); + } + Fred.MergeFrom(other.Fred); + } + barney_.Add(other.barney_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (bar_ == null) { + Bar = new global::UnitTest.Issues.TestProtos.ComplexOptionType1(); + } + input.ReadMessage(Bar); + break; + } + case 16: { + Baz = input.ReadInt32(); + break; + } + case 26: { + if (fred_ == null) { + Fred = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4(); + } + input.ReadMessage(Fred); + break; + } + case 34: { + barney_.AddEntriesFrom(input, _repeated_barney_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (bar_ == null) { + Bar = new global::UnitTest.Issues.TestProtos.ComplexOptionType1(); + } + input.ReadMessage(Bar); + break; + } + case 16: { + Baz = input.ReadInt32(); + break; + } + case 26: { + if (fred_ == null) { + Fred = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4(); + } + input.ReadMessage(Fred); + break; + } + case 34: { + barney_.AddEntriesFrom(ref input, _repeated_barney_codec); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the ComplexOptionType2 message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class ComplexOptionType4 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType4()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.ComplexOptionType2.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType4() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType4(ComplexOptionType4 other) : this() { + waldo_ = other.waldo_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType4 Clone() { + return new ComplexOptionType4(this); + } + + /// Field number for the "waldo" field. + public const int WaldoFieldNumber = 1; + private int waldo_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Waldo { + get { return waldo_; } + set { + waldo_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ComplexOptionType4); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ComplexOptionType4 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Waldo != other.Waldo) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Waldo != 0) hash ^= Waldo.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Waldo != 0) { + output.WriteRawTag(8); + output.WriteInt32(Waldo); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Waldo != 0) { + output.WriteRawTag(8); + output.WriteInt32(Waldo); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Waldo != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Waldo); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ComplexOptionType4 other) { + if (other == null) { + return; + } + if (other.Waldo != 0) { + Waldo = other.Waldo; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Waldo = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Waldo = input.ReadInt32(); + break; + } + } + } + } + #endif + + #region Extensions + /// Container for extensions for other messages declared in the ComplexOptionType4 message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Extensions { + public static readonly pb::Extension ComplexOpt4 = + new pb::Extension(7633546, pb::FieldCodec.ForMessage(61068370, global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Parser)); + } + #endregion + + } + + } + #endregion + + } + + public sealed partial class ComplexOptionType3 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType3()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[14]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType3() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType3(ComplexOptionType3 other) : this() { + qux_ = other.qux_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType3 Clone() { + return new ComplexOptionType3(this); + } + + /// Field number for the "qux" field. + public const int QuxFieldNumber = 1; + private int qux_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Qux { + get { return qux_; } + set { + qux_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ComplexOptionType3); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ComplexOptionType3 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Qux != other.Qux) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Qux != 0) hash ^= Qux.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Qux != 0) { + output.WriteRawTag(8); + output.WriteInt32(Qux); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Qux != 0) { + output.WriteRawTag(8); + output.WriteInt32(Qux); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Qux != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Qux); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ComplexOptionType3 other) { + if (other == null) { + return; + } + if (other.Qux != 0) { + Qux = other.Qux; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Qux = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Qux = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// Note that we try various different ways of naming the same extension. + /// + public sealed partial class VariousComplexOptions : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new VariousComplexOptions()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[15]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public VariousComplexOptions() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public VariousComplexOptions(VariousComplexOptions other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public VariousComplexOptions Clone() { + return new VariousComplexOptions(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as VariousComplexOptions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(VariousComplexOptions other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(VariousComplexOptions other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + /// + /// A helper type used to test aggregate option parsing + /// + public sealed partial class Aggregate : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Aggregate()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[16]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Aggregate() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Aggregate(Aggregate other) : this() { + i_ = other.i_; + s_ = other.s_; + sub_ = other.sub_ != null ? other.sub_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Aggregate Clone() { + return new Aggregate(this); + } + + /// Field number for the "i" field. + public const int IFieldNumber = 1; + private int i_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int I { + get { return i_; } + set { + i_ = value; + } + } + + /// Field number for the "s" field. + public const int SFieldNumber = 2; + private string s_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string S { + get { return s_; } + set { + s_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "sub" field. + public const int SubFieldNumber = 3; + private global::UnitTest.Issues.TestProtos.Aggregate sub_; + /// + /// A nested object + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::UnitTest.Issues.TestProtos.Aggregate Sub { + get { return sub_; } + set { + sub_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Aggregate); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Aggregate other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (I != other.I) return false; + if (S != other.S) return false; + if (!object.Equals(Sub, other.Sub)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (I != 0) hash ^= I.GetHashCode(); + if (S.Length != 0) hash ^= S.GetHashCode(); + if (sub_ != null) hash ^= Sub.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (I != 0) { + output.WriteRawTag(8); + output.WriteInt32(I); + } + if (S.Length != 0) { + output.WriteRawTag(18); + output.WriteString(S); + } + if (sub_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Sub); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (I != 0) { + output.WriteRawTag(8); + output.WriteInt32(I); + } + if (S.Length != 0) { + output.WriteRawTag(18); + output.WriteString(S); + } + if (sub_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Sub); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (I != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(I); + } + if (S.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(S); + } + if (sub_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Sub); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Aggregate other) { + if (other == null) { + return; + } + if (other.I != 0) { + I = other.I; + } + if (other.S.Length != 0) { + S = other.S; + } + if (other.sub_ != null) { + if (sub_ == null) { + Sub = new global::UnitTest.Issues.TestProtos.Aggregate(); + } + Sub.MergeFrom(other.Sub); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + I = input.ReadInt32(); + break; + } + case 18: { + S = input.ReadString(); + break; + } + case 26: { + if (sub_ == null) { + Sub = new global::UnitTest.Issues.TestProtos.Aggregate(); + } + input.ReadMessage(Sub); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + I = input.ReadInt32(); + break; + } + case 18: { + S = input.ReadString(); + break; + } + case 26: { + if (sub_ == null) { + Sub = new global::UnitTest.Issues.TestProtos.Aggregate(); + } + input.ReadMessage(Sub); + break; + } + } + } + } + #endif + + } + + public sealed partial class AggregateMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new AggregateMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[17]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public AggregateMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public AggregateMessage(AggregateMessage other) : this() { + fieldname_ = other.fieldname_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public AggregateMessage Clone() { + return new AggregateMessage(this); + } + + /// Field number for the "fieldname" field. + public const int FieldnameFieldNumber = 1; + private int fieldname_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Fieldname { + get { return fieldname_; } + set { + fieldname_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as AggregateMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(AggregateMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Fieldname != other.Fieldname) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Fieldname != 0) hash ^= Fieldname.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Fieldname != 0) { + output.WriteRawTag(8); + output.WriteInt32(Fieldname); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Fieldname != 0) { + output.WriteRawTag(8); + output.WriteInt32(Fieldname); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Fieldname != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Fieldname); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(AggregateMessage other) { + if (other == null) { + return; + } + if (other.Fieldname != 0) { + Fieldname = other.Fieldname; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Fieldname = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Fieldname = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// Test custom options for nested type. + /// + public sealed partial class NestedOptionType : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedOptionType()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[18]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedOptionType() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedOptionType(NestedOptionType other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedOptionType Clone() { + return new NestedOptionType(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedOptionType); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedOptionType other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedOptionType other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the NestedOptionType message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum NestedEnum { + [pbr::OriginalName("UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("NESTED_ENUM_VALUE")] Value = 1, + } + + public sealed partial class NestedMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.NestedOptionType.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + nestedField_ = other.nestedField_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "nested_field" field. + public const int NestedFieldFieldNumber = 1; + private int nestedField_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int NestedField { + get { return nestedField_; } + set { + nestedField_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (NestedField != other.NestedField) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (NestedField != 0) hash ^= NestedField.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (NestedField != 0) { + output.WriteRawTag(8); + output.WriteInt32(NestedField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (NestedField != 0) { + output.WriteRawTag(8); + output.WriteInt32(NestedField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (NestedField != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(NestedField); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.NestedField != 0) { + NestedField = other.NestedField; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + NestedField = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + NestedField = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs new file mode 100644 index 0000000000000..14b054ccbbae2 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs @@ -0,0 +1,253 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: unittest_import.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Google.Protobuf.TestProtos.Proto2 { + + /// Holder for reflection information generated from unittest_import.proto + public static partial class UnittestImportReflection { + + #region Descriptor + /// File descriptor for unittest_import.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestImportReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChV1bml0dGVzdF9pbXBvcnQucHJvdG8SH3Byb3RvYnVmX3VuaXR0ZXN0X2lt", + "cG9ydF9wcm90bzIaHHVuaXR0ZXN0X2ltcG9ydF9wdWJsaWMucHJvdG8iGgoN", + "SW1wb3J0TWVzc2FnZRIJCgFkGAEgASgFKjwKCkltcG9ydEVudW0SDgoKSU1Q", + "T1JUX0ZPTxAHEg4KCklNUE9SVF9CQVIQCBIOCgpJTVBPUlRfQkFaEAkqMQoQ", + "SW1wb3J0RW51bUZvck1hcBILCgdVTktOT1dOEAASBwoDRk9PEAESBwoDQkFS", + "EAJCKUgB+AEBqgIhR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3MuUHJvdG8y", + "UAA=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.Proto2.UnittestImportPublicReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.Proto2.ImportEnum), typeof(global::Google.Protobuf.TestProtos.Proto2.ImportEnumForMap), }, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.ImportMessage), global::Google.Protobuf.TestProtos.Proto2.ImportMessage.Parser, new[]{ "D" }, null, null, null, null) + })); + } + #endregion + + } + #region Enums + public enum ImportEnum { + [pbr::OriginalName("IMPORT_FOO")] ImportFoo = 7, + [pbr::OriginalName("IMPORT_BAR")] ImportBar = 8, + [pbr::OriginalName("IMPORT_BAZ")] ImportBaz = 9, + } + + /// + /// To use an enum in a map, it must has the first value as 0. + /// + public enum ImportEnumForMap { + [pbr::OriginalName("UNKNOWN")] Unknown = 0, + [pbr::OriginalName("FOO")] Foo = 1, + [pbr::OriginalName("BAR")] Bar = 2, + } + + #endregion + + #region Messages + public sealed partial class ImportMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ImportMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestImportReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ImportMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ImportMessage(ImportMessage other) : this() { + _hasBits0 = other._hasBits0; + d_ = other.d_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ImportMessage Clone() { + return new ImportMessage(this); + } + + /// Field number for the "d" field. + public const int DFieldNumber = 1; + private readonly static int DDefaultValue = 0; + + private int d_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int D { + get { if ((_hasBits0 & 1) != 0) { return d_; } else { return DDefaultValue; } } + set { + _hasBits0 |= 1; + d_ = value; + } + } + /// Gets whether the "d" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasD { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "d" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearD() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ImportMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ImportMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (D != other.D) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasD) hash ^= D.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasD) { + output.WriteRawTag(8); + output.WriteInt32(D); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasD) { + output.WriteRawTag(8); + output.WriteInt32(D); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasD) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(D); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ImportMessage other) { + if (other == null) { + return; + } + if (other.HasD) { + D = other.D; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + D = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + D = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs new file mode 100644 index 0000000000000..ecdf40979c2bd --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs @@ -0,0 +1,229 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: unittest_import_proto3.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Google.Protobuf.TestProtos { + + /// Holder for reflection information generated from unittest_import_proto3.proto + public static partial class UnittestImportProto3Reflection { + + #region Descriptor + /// File descriptor for unittest_import_proto3.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestImportProto3Reflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Chx1bml0dGVzdF9pbXBvcnRfcHJvdG8zLnByb3RvEhhwcm90b2J1Zl91bml0", + "dGVzdF9pbXBvcnQaI3VuaXR0ZXN0X2ltcG9ydF9wdWJsaWNfcHJvdG8zLnBy", + "b3RvIhoKDUltcG9ydE1lc3NhZ2USCQoBZBgBIAEoBSpZCgpJbXBvcnRFbnVt", + "EhsKF0lNUE9SVF9FTlVNX1VOU1BFQ0lGSUVEEAASDgoKSU1QT1JUX0ZPTxAH", + "Eg4KCklNUE9SVF9CQVIQCBIOCgpJTVBPUlRfQkFaEAlCHaoCGkdvb2dsZS5Q", + "cm90b2J1Zi5UZXN0UHJvdG9zUABiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportPublicProto3Reflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ImportEnum), }, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.ImportMessage), global::Google.Protobuf.TestProtos.ImportMessage.Parser, new[]{ "D" }, null, null, null, null) + })); + } + #endregion + + } + #region Enums + public enum ImportEnum { + [pbr::OriginalName("IMPORT_ENUM_UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("IMPORT_FOO")] ImportFoo = 7, + [pbr::OriginalName("IMPORT_BAR")] ImportBar = 8, + [pbr::OriginalName("IMPORT_BAZ")] ImportBaz = 9, + } + + #endregion + + #region Messages + public sealed partial class ImportMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ImportMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestImportProto3Reflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ImportMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ImportMessage(ImportMessage other) : this() { + d_ = other.d_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ImportMessage Clone() { + return new ImportMessage(this); + } + + /// Field number for the "d" field. + public const int DFieldNumber = 1; + private int d_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int D { + get { return d_; } + set { + d_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ImportMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ImportMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (D != other.D) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (D != 0) hash ^= D.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (D != 0) { + output.WriteRawTag(8); + output.WriteInt32(D); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (D != 0) { + output.WriteRawTag(8); + output.WriteInt32(D); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (D != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(D); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ImportMessage other) { + if (other == null) { + return; + } + if (other.D != 0) { + D = other.D; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + D = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + D = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs new file mode 100644 index 0000000000000..24c29e9708262 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs @@ -0,0 +1,231 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: unittest_import_public.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Google.Protobuf.TestProtos.Proto2 { + + /// Holder for reflection information generated from unittest_import_public.proto + public static partial class UnittestImportPublicReflection { + + #region Descriptor + /// File descriptor for unittest_import_public.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestImportPublicReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Chx1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvEh9wcm90b2J1Zl91bml0", + "dGVzdF9pbXBvcnRfcHJvdG8yIiAKE1B1YmxpY0ltcG9ydE1lc3NhZ2USCQoB", + "ZRgBIAEoBUIkqgIhR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3MuUHJvdG8y")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.PublicImportMessage), global::Google.Protobuf.TestProtos.Proto2.PublicImportMessage.Parser, new[]{ "E" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class PublicImportMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PublicImportMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.Proto2.UnittestImportPublicReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PublicImportMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PublicImportMessage(PublicImportMessage other) : this() { + _hasBits0 = other._hasBits0; + e_ = other.e_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PublicImportMessage Clone() { + return new PublicImportMessage(this); + } + + /// Field number for the "e" field. + public const int EFieldNumber = 1; + private readonly static int EDefaultValue = 0; + + private int e_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int E { + get { if ((_hasBits0 & 1) != 0) { return e_; } else { return EDefaultValue; } } + set { + _hasBits0 |= 1; + e_ = value; + } + } + /// Gets whether the "e" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasE { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "e" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearE() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as PublicImportMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(PublicImportMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (E != other.E) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasE) hash ^= E.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasE) { + output.WriteRawTag(8); + output.WriteInt32(E); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasE) { + output.WriteRawTag(8); + output.WriteInt32(E); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasE) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(E); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(PublicImportMessage other) { + if (other == null) { + return; + } + if (other.HasE) { + E = other.E; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + E = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + E = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs new file mode 100644 index 0000000000000..2d77a639fa35b --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs @@ -0,0 +1,217 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: unittest_import_public_proto3.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Google.Protobuf.TestProtos { + + /// Holder for reflection information generated from unittest_import_public_proto3.proto + public static partial class UnittestImportPublicProto3Reflection { + + #region Descriptor + /// File descriptor for unittest_import_public_proto3.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestImportPublicProto3Reflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CiN1bml0dGVzdF9pbXBvcnRfcHVibGljX3Byb3RvMy5wcm90bxIYcHJvdG9i", + "dWZfdW5pdHRlc3RfaW1wb3J0IiAKE1B1YmxpY0ltcG9ydE1lc3NhZ2USCQoB", + "ZRgBIAEoBUIdqgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3Rv", + "Mw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.PublicImportMessage), global::Google.Protobuf.TestProtos.PublicImportMessage.Parser, new[]{ "E" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class PublicImportMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PublicImportMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestImportPublicProto3Reflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PublicImportMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PublicImportMessage(PublicImportMessage other) : this() { + e_ = other.e_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PublicImportMessage Clone() { + return new PublicImportMessage(this); + } + + /// Field number for the "e" field. + public const int EFieldNumber = 1; + private int e_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int E { + get { return e_; } + set { + e_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as PublicImportMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(PublicImportMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (E != other.E) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (E != 0) hash ^= E.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (E != 0) { + output.WriteRawTag(8); + output.WriteInt32(E); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (E != 0) { + output.WriteRawTag(8); + output.WriteInt32(E); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (E != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(E); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(PublicImportMessage other) { + if (other == null) { + return; + } + if (other.E != 0) { + E = other.E; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + E = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + E = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936A.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936A.cs new file mode 100644 index 0000000000000..56fde4f00a24a --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936A.cs @@ -0,0 +1,46 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: unittest_issue6936_a.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace UnitTest.Issues.TestProtos { + + /// Holder for reflection information generated from unittest_issue6936_a.proto + public static partial class UnittestIssue6936AReflection { + + #region Descriptor + /// File descriptor for unittest_issue6936_a.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestIssue6936AReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Chp1bml0dGVzdF9pc3N1ZTY5MzZfYS5wcm90bxIPdW5pdHRlc3RfaXNzdWVz", + "GiBnb29nbGUvcHJvdG9idWYvZGVzY3JpcHRvci5wcm90bzouCgNvcHQSHy5n", + "b29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMY0IYDIAEoCUIdqgIaVW5p", + "dFRlc3QuSXNzdWVzLlRlc3RQcm90b3NiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, new pb::Extension[] { UnittestIssue6936AExtensions.Opt }, null)); + } + #endregion + + } + /// Holder for extension identifiers generated from the top level of unittest_issue6936_a.proto + public static partial class UnittestIssue6936AExtensions { + public static readonly pb::Extension Opt = + new pb::Extension(50000, pb::FieldCodec.ForString(400002, "")); + } + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs new file mode 100644 index 0000000000000..e22bf0f8ffb4f --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs @@ -0,0 +1,180 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: unittest_issue6936_b.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace UnitTest.Issues.TestProtos { + + /// Holder for reflection information generated from unittest_issue6936_b.proto + public static partial class UnittestIssue6936BReflection { + + #region Descriptor + /// File descriptor for unittest_issue6936_b.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestIssue6936BReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Chp1bml0dGVzdF9pc3N1ZTY5MzZfYi5wcm90bxIPdW5pdHRlc3RfaXNzdWVz", + "Ghp1bml0dGVzdF9pc3N1ZTY5MzZfYS5wcm90byIOCgNGb286B4K1GANmb29C", + "HaoCGlVuaXRUZXN0Lklzc3Vlcy5UZXN0UHJvdG9zYgZwcm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::UnitTest.Issues.TestProtos.UnittestIssue6936AReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Foo), global::UnitTest.Issues.TestProtos.Foo.Parser, null, null, null, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class Foo : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Foo()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssue6936BReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Foo() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Foo(Foo other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Foo Clone() { + return new Foo(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Foo); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Foo other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Foo other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs new file mode 100644 index 0000000000000..21d36300f87c7 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs @@ -0,0 +1,227 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: unittest_issue6936_c.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace UnitTest.Issues.TestProtos { + + /// Holder for reflection information generated from unittest_issue6936_c.proto + public static partial class UnittestIssue6936CReflection { + + #region Descriptor + /// File descriptor for unittest_issue6936_c.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestIssue6936CReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Chp1bml0dGVzdF9pc3N1ZTY5MzZfYy5wcm90bxIPdW5pdHRlc3RfaXNzdWVz", + "Ghp1bml0dGVzdF9pc3N1ZTY5MzZfYS5wcm90bxoadW5pdHRlc3RfaXNzdWU2", + "OTM2X2IucHJvdG8iMQoDQmFyEiEKA2ZvbxgBIAEoCzIULnVuaXR0ZXN0X2lz", + "c3Vlcy5Gb286B4K1GANiYXJCHaoCGlVuaXRUZXN0Lklzc3Vlcy5UZXN0UHJv", + "dG9zYgZwcm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::UnitTest.Issues.TestProtos.UnittestIssue6936AReflection.Descriptor, global::UnitTest.Issues.TestProtos.UnittestIssue6936BReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Bar), global::UnitTest.Issues.TestProtos.Bar.Parser, new[]{ "Foo" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class Bar : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Bar()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssue6936CReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Bar() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Bar(Bar other) : this() { + foo_ = other.foo_ != null ? other.foo_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Bar Clone() { + return new Bar(this); + } + + /// Field number for the "foo" field. + public const int FooFieldNumber = 1; + private global::UnitTest.Issues.TestProtos.Foo foo_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::UnitTest.Issues.TestProtos.Foo Foo { + get { return foo_; } + set { + foo_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Bar); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Bar other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Foo, other.Foo)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (foo_ != null) hash ^= Foo.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (foo_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Foo); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (foo_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Foo); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (foo_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Foo); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Bar other) { + if (other == null) { + return; + } + if (other.foo_ != null) { + if (foo_ == null) { + Foo = new global::UnitTest.Issues.TestProtos.Foo(); + } + Foo.MergeFrom(other.Foo); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (foo_ == null) { + Foo = new global::UnitTest.Issues.TestProtos.Foo(); + } + input.ReadMessage(Foo); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (foo_ == null) { + Foo = new global::UnitTest.Issues.TestProtos.Foo(); + } + input.ReadMessage(Foo); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs new file mode 100644 index 0000000000000..4377cf3a19cfc --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs @@ -0,0 +1,3532 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: unittest_issues.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace UnitTest.Issues.TestProtos { + + /// Holder for reflection information generated from unittest_issues.proto + public static partial class UnittestIssuesReflection { + + #region Descriptor + /// File descriptor for unittest_issues.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestIssuesReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChV1bml0dGVzdF9pc3N1ZXMucHJvdG8SD3VuaXR0ZXN0X2lzc3VlcxocZ29v", + "Z2xlL3Byb3RvYnVmL3N0cnVjdC5wcm90byInCghJc3N1ZTMwNxobCgpOZXN0", + "ZWRPbmNlGg0KC05lc3RlZFR3aWNlIrABChNOZWdhdGl2ZUVudW1NZXNzYWdl", + "EiwKBXZhbHVlGAEgASgOMh0udW5pdHRlc3RfaXNzdWVzLk5lZ2F0aXZlRW51", + "bRIxCgZ2YWx1ZXMYAiADKA4yHS51bml0dGVzdF9pc3N1ZXMuTmVnYXRpdmVF", + "bnVtQgIQABI4Cg1wYWNrZWRfdmFsdWVzGAMgAygOMh0udW5pdHRlc3RfaXNz", + "dWVzLk5lZ2F0aXZlRW51bUICEAEiEQoPRGVwcmVjYXRlZENoaWxkIrkCChdE", + "ZXByZWNhdGVkRmllbGRzTWVzc2FnZRIaCg5QcmltaXRpdmVWYWx1ZRgBIAEo", + "BUICGAESGgoOUHJpbWl0aXZlQXJyYXkYAiADKAVCAhgBEjoKDE1lc3NhZ2VW", + "YWx1ZRgDIAEoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRC", + "AhgBEjoKDE1lc3NhZ2VBcnJheRgEIAMoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5E", + "ZXByZWNhdGVkQ2hpbGRCAhgBEjYKCUVudW1WYWx1ZRgFIAEoDjIfLnVuaXR0", + "ZXN0X2lzc3Vlcy5EZXByZWNhdGVkRW51bUICGAESNgoJRW51bUFycmF5GAYg", + "AygOMh8udW5pdHRlc3RfaXNzdWVzLkRlcHJlY2F0ZWRFbnVtQgIYASIZCglJ", + "dGVtRmllbGQSDAoEaXRlbRgBIAEoBSJECg1SZXNlcnZlZE5hbWVzEg0KBXR5", + "cGVzGAEgASgFEhIKCmRlc2NyaXB0b3IYAiABKAUaEAoOU29tZU5lc3RlZFR5", + "cGUioAEKFVRlc3RKc29uRmllbGRPcmRlcmluZxITCgtwbGFpbl9pbnQzMhgE", + "IAEoBRITCglvMV9zdHJpbmcYAiABKAlIABISCghvMV9pbnQzMhgFIAEoBUgA", + "EhQKDHBsYWluX3N0cmluZxgBIAEoCRISCghvMl9pbnQzMhgGIAEoBUgBEhMK", + "CW8yX3N0cmluZxgDIAEoCUgBQgQKAm8xQgQKAm8yIksKDFRlc3RKc29uTmFt", + "ZRIMCgRuYW1lGAEgASgJEhkKC2Rlc2NyaXB0aW9uGAIgASgJUgRkZXNjEhIK", + "BGd1aWQYAyABKAlSBGV4aWQifwoMT25lb2ZNZXJnaW5nEg4KBHRleHQYASAB", + "KAlIABI2CgZuZXN0ZWQYAiABKAsyJC51bml0dGVzdF9pc3N1ZXMuT25lb2ZN", + "ZXJnaW5nLk5lc3RlZEgAGh4KBk5lc3RlZBIJCgF4GAEgASgFEgkKAXkYAiAB", + "KAVCBwoFdmFsdWUiawoWTnVsbFZhbHVlT3V0c2lkZVN0cnVjdBIWCgxzdHJp", + "bmdfdmFsdWUYASABKAlIABIwCgpudWxsX3ZhbHVlGAIgASgOMhouZ29vZ2xl", + "LnByb3RvYnVmLk51bGxWYWx1ZUgAQgcKBXZhbHVlIkUKE051bGxWYWx1ZU5v", + "dEluT25lb2YSLgoKbnVsbF92YWx1ZRgCIAEoDjIaLmdvb2dsZS5wcm90b2J1", + "Zi5OdWxsVmFsdWUiYAoXTWl4ZWRSZWd1bGFyQW5kT3B0aW9uYWwSFQoNcmVn", + "dWxhcl9maWVsZBgBIAEoCRIbCg5vcHRpb25hbF9maWVsZBgCIAEoCUgAiAEB", + "QhEKD19vcHRpb25hbF9maWVsZCpVCgxOZWdhdGl2ZUVudW0SFgoSTkVHQVRJ", + "VkVfRU5VTV9aRVJPEAASFgoJRml2ZUJlbG93EPv//////////wESFQoITWlu", + "dXNPbmUQ////////////ASouCg5EZXByZWNhdGVkRW51bRITCg9ERVBSRUNB", + "VEVEX1pFUk8QABIHCgNvbmUQAUIdqgIaVW5pdFRlc3QuSXNzdWVzLlRlc3RQ", + "cm90b3NiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.NegativeEnum), typeof(global::UnitTest.Issues.TestProtos.DeprecatedEnum), }, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307), global::UnitTest.Issues.TestProtos.Issue307.Parser, null, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Parser, null, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice.Parser, null, null, null, null, null)})}), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NegativeEnumMessage), global::UnitTest.Issues.TestProtos.NegativeEnumMessage.Parser, new[]{ "Value", "Values", "PackedValues" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedChild), global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage), global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Parser, new[]{ "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ItemField), global::UnitTest.Issues.TestProtos.ItemField.Parser, new[]{ "Item" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames), global::UnitTest.Issues.TestProtos.ReservedNames.Parser, new[]{ "Types_", "Descriptor_" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType), global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType.Parser, null, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering), global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering.Parser, new[]{ "PlainInt32", "O1String", "O1Int32", "PlainString", "O2Int32", "O2String" }, new[]{ "O1", "O2" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonName), global::UnitTest.Issues.TestProtos.TestJsonName.Parser, new[]{ "Name", "Description", "Guid" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofMerging), global::UnitTest.Issues.TestProtos.OneofMerging.Parser, new[]{ "Text", "Nested" }, new[]{ "Value" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested), global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested.Parser, new[]{ "X", "Y" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NullValueOutsideStruct), global::UnitTest.Issues.TestProtos.NullValueOutsideStruct.Parser, new[]{ "StringValue", "NullValue" }, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NullValueNotInOneof), global::UnitTest.Issues.TestProtos.NullValueNotInOneof.Parser, new[]{ "NullValue" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.MixedRegularAndOptional), global::UnitTest.Issues.TestProtos.MixedRegularAndOptional.Parser, new[]{ "RegularField", "OptionalField" }, new[]{ "OptionalField" }, null, null, null) + })); + } + #endregion + + } + #region Enums + public enum NegativeEnum { + [pbr::OriginalName("NEGATIVE_ENUM_ZERO")] Zero = 0, + [pbr::OriginalName("FiveBelow")] FiveBelow = -5, + [pbr::OriginalName("MinusOne")] MinusOne = -1, + } + + public enum DeprecatedEnum { + [pbr::OriginalName("DEPRECATED_ZERO")] DeprecatedZero = 0, + [pbr::OriginalName("one")] One = 1, + } + + #endregion + + #region Messages + /// + /// Issue 307: when generating doubly-nested types, any references + /// should be of the form A.Types.B.Types.C. + /// + public sealed partial class Issue307 : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Issue307()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Issue307() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Issue307(Issue307 other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Issue307 Clone() { + return new Issue307(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Issue307); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Issue307 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Issue307 other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the Issue307 message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class NestedOnce : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedOnce()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.Issue307.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedOnce() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedOnce(NestedOnce other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedOnce Clone() { + return new NestedOnce(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedOnce); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedOnce other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedOnce other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the NestedOnce message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class NestedTwice : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedTwice()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedTwice() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedTwice(NestedTwice other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedTwice Clone() { + return new NestedTwice(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedTwice); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedTwice other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedTwice other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + } + #endregion + + } + + } + #endregion + + } + + public sealed partial class NegativeEnumMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NegativeEnumMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NegativeEnumMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NegativeEnumMessage(NegativeEnumMessage other) : this() { + value_ = other.value_; + values_ = other.values_.Clone(); + packedValues_ = other.packedValues_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NegativeEnumMessage Clone() { + return new NegativeEnumMessage(this); + } + + /// Field number for the "value" field. + public const int ValueFieldNumber = 1; + private global::UnitTest.Issues.TestProtos.NegativeEnum value_ = global::UnitTest.Issues.TestProtos.NegativeEnum.Zero; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::UnitTest.Issues.TestProtos.NegativeEnum Value { + get { return value_; } + set { + value_ = value; + } + } + + /// Field number for the "values" field. + public const int ValuesFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_values_codec + = pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x); + private readonly pbc::RepeatedField values_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Values { + get { return values_; } + } + + /// Field number for the "packed_values" field. + public const int PackedValuesFieldNumber = 3; + private static readonly pb::FieldCodec _repeated_packedValues_codec + = pb::FieldCodec.ForEnum(26, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x); + private readonly pbc::RepeatedField packedValues_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedValues { + get { return packedValues_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NegativeEnumMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NegativeEnumMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Value != other.Value) return false; + if(!values_.Equals(other.values_)) return false; + if(!packedValues_.Equals(other.packedValues_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.Zero) hash ^= Value.GetHashCode(); + hash ^= values_.GetHashCode(); + hash ^= packedValues_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.Zero) { + output.WriteRawTag(8); + output.WriteEnum((int) Value); + } + values_.WriteTo(output, _repeated_values_codec); + packedValues_.WriteTo(output, _repeated_packedValues_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.Zero) { + output.WriteRawTag(8); + output.WriteEnum((int) Value); + } + values_.WriteTo(ref output, _repeated_values_codec); + packedValues_.WriteTo(ref output, _repeated_packedValues_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.Zero) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Value); + } + size += values_.CalculateSize(_repeated_values_codec); + size += packedValues_.CalculateSize(_repeated_packedValues_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NegativeEnumMessage other) { + if (other == null) { + return; + } + if (other.Value != global::UnitTest.Issues.TestProtos.NegativeEnum.Zero) { + Value = other.Value; + } + values_.Add(other.values_); + packedValues_.Add(other.packedValues_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Value = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum(); + break; + } + case 18: + case 16: { + values_.AddEntriesFrom(input, _repeated_values_codec); + break; + } + case 26: + case 24: { + packedValues_.AddEntriesFrom(input, _repeated_packedValues_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Value = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum(); + break; + } + case 18: + case 16: { + values_.AddEntriesFrom(ref input, _repeated_values_codec); + break; + } + case 26: + case 24: { + packedValues_.AddEntriesFrom(ref input, _repeated_packedValues_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class DeprecatedChild : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DeprecatedChild()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DeprecatedChild() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DeprecatedChild(DeprecatedChild other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DeprecatedChild Clone() { + return new DeprecatedChild(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as DeprecatedChild); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(DeprecatedChild other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(DeprecatedChild other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class DeprecatedFieldsMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DeprecatedFieldsMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DeprecatedFieldsMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DeprecatedFieldsMessage(DeprecatedFieldsMessage other) : this() { + primitiveValue_ = other.primitiveValue_; + primitiveArray_ = other.primitiveArray_.Clone(); + messageValue_ = other.messageValue_ != null ? other.messageValue_.Clone() : null; + messageArray_ = other.messageArray_.Clone(); + enumValue_ = other.enumValue_; + enumArray_ = other.enumArray_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DeprecatedFieldsMessage Clone() { + return new DeprecatedFieldsMessage(this); + } + + /// Field number for the "PrimitiveValue" field. + public const int PrimitiveValueFieldNumber = 1; + private int primitiveValue_; + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int PrimitiveValue { + get { return primitiveValue_; } + set { + primitiveValue_ = value; + } + } + + /// Field number for the "PrimitiveArray" field. + public const int PrimitiveArrayFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_primitiveArray_codec + = pb::FieldCodec.ForInt32(18); + private readonly pbc::RepeatedField primitiveArray_ = new pbc::RepeatedField(); + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PrimitiveArray { + get { return primitiveArray_; } + } + + /// Field number for the "MessageValue" field. + public const int MessageValueFieldNumber = 3; + private global::UnitTest.Issues.TestProtos.DeprecatedChild messageValue_; + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::UnitTest.Issues.TestProtos.DeprecatedChild MessageValue { + get { return messageValue_; } + set { + messageValue_ = value; + } + } + + /// Field number for the "MessageArray" field. + public const int MessageArrayFieldNumber = 4; + private static readonly pb::FieldCodec _repeated_messageArray_codec + = pb::FieldCodec.ForMessage(34, global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser); + private readonly pbc::RepeatedField messageArray_ = new pbc::RepeatedField(); + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField MessageArray { + get { return messageArray_; } + } + + /// Field number for the "EnumValue" field. + public const int EnumValueFieldNumber = 5; + private global::UnitTest.Issues.TestProtos.DeprecatedEnum enumValue_ = global::UnitTest.Issues.TestProtos.DeprecatedEnum.DeprecatedZero; + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::UnitTest.Issues.TestProtos.DeprecatedEnum EnumValue { + get { return enumValue_; } + set { + enumValue_ = value; + } + } + + /// Field number for the "EnumArray" field. + public const int EnumArrayFieldNumber = 6; + private static readonly pb::FieldCodec _repeated_enumArray_codec + = pb::FieldCodec.ForEnum(50, x => (int) x, x => (global::UnitTest.Issues.TestProtos.DeprecatedEnum) x); + private readonly pbc::RepeatedField enumArray_ = new pbc::RepeatedField(); + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField EnumArray { + get { return enumArray_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as DeprecatedFieldsMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(DeprecatedFieldsMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (PrimitiveValue != other.PrimitiveValue) return false; + if(!primitiveArray_.Equals(other.primitiveArray_)) return false; + if (!object.Equals(MessageValue, other.MessageValue)) return false; + if(!messageArray_.Equals(other.messageArray_)) return false; + if (EnumValue != other.EnumValue) return false; + if(!enumArray_.Equals(other.enumArray_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (PrimitiveValue != 0) hash ^= PrimitiveValue.GetHashCode(); + hash ^= primitiveArray_.GetHashCode(); + if (messageValue_ != null) hash ^= MessageValue.GetHashCode(); + hash ^= messageArray_.GetHashCode(); + if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DeprecatedZero) hash ^= EnumValue.GetHashCode(); + hash ^= enumArray_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (PrimitiveValue != 0) { + output.WriteRawTag(8); + output.WriteInt32(PrimitiveValue); + } + primitiveArray_.WriteTo(output, _repeated_primitiveArray_codec); + if (messageValue_ != null) { + output.WriteRawTag(26); + output.WriteMessage(MessageValue); + } + messageArray_.WriteTo(output, _repeated_messageArray_codec); + if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DeprecatedZero) { + output.WriteRawTag(40); + output.WriteEnum((int) EnumValue); + } + enumArray_.WriteTo(output, _repeated_enumArray_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (PrimitiveValue != 0) { + output.WriteRawTag(8); + output.WriteInt32(PrimitiveValue); + } + primitiveArray_.WriteTo(ref output, _repeated_primitiveArray_codec); + if (messageValue_ != null) { + output.WriteRawTag(26); + output.WriteMessage(MessageValue); + } + messageArray_.WriteTo(ref output, _repeated_messageArray_codec); + if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DeprecatedZero) { + output.WriteRawTag(40); + output.WriteEnum((int) EnumValue); + } + enumArray_.WriteTo(ref output, _repeated_enumArray_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (PrimitiveValue != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(PrimitiveValue); + } + size += primitiveArray_.CalculateSize(_repeated_primitiveArray_codec); + if (messageValue_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageValue); + } + size += messageArray_.CalculateSize(_repeated_messageArray_codec); + if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DeprecatedZero) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumValue); + } + size += enumArray_.CalculateSize(_repeated_enumArray_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(DeprecatedFieldsMessage other) { + if (other == null) { + return; + } + if (other.PrimitiveValue != 0) { + PrimitiveValue = other.PrimitiveValue; + } + primitiveArray_.Add(other.primitiveArray_); + if (other.messageValue_ != null) { + if (messageValue_ == null) { + MessageValue = new global::UnitTest.Issues.TestProtos.DeprecatedChild(); + } + MessageValue.MergeFrom(other.MessageValue); + } + messageArray_.Add(other.messageArray_); + if (other.EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DeprecatedZero) { + EnumValue = other.EnumValue; + } + enumArray_.Add(other.enumArray_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + PrimitiveValue = input.ReadInt32(); + break; + } + case 18: + case 16: { + primitiveArray_.AddEntriesFrom(input, _repeated_primitiveArray_codec); + break; + } + case 26: { + if (messageValue_ == null) { + MessageValue = new global::UnitTest.Issues.TestProtos.DeprecatedChild(); + } + input.ReadMessage(MessageValue); + break; + } + case 34: { + messageArray_.AddEntriesFrom(input, _repeated_messageArray_codec); + break; + } + case 40: { + EnumValue = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) input.ReadEnum(); + break; + } + case 50: + case 48: { + enumArray_.AddEntriesFrom(input, _repeated_enumArray_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + PrimitiveValue = input.ReadInt32(); + break; + } + case 18: + case 16: { + primitiveArray_.AddEntriesFrom(ref input, _repeated_primitiveArray_codec); + break; + } + case 26: { + if (messageValue_ == null) { + MessageValue = new global::UnitTest.Issues.TestProtos.DeprecatedChild(); + } + input.ReadMessage(MessageValue); + break; + } + case 34: { + messageArray_.AddEntriesFrom(ref input, _repeated_messageArray_codec); + break; + } + case 40: { + EnumValue = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) input.ReadEnum(); + break; + } + case 50: + case 48: { + enumArray_.AddEntriesFrom(ref input, _repeated_enumArray_codec); + break; + } + } + } + } + #endif + + } + + /// + /// Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45 + /// + public sealed partial class ItemField : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ItemField()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ItemField() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ItemField(ItemField other) : this() { + item_ = other.item_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ItemField Clone() { + return new ItemField(this); + } + + /// Field number for the "item" field. + public const int ItemFieldNumber = 1; + private int item_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Item { + get { return item_; } + set { + item_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ItemField); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ItemField other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Item != other.Item) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Item != 0) hash ^= Item.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Item != 0) { + output.WriteRawTag(8); + output.WriteInt32(Item); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Item != 0) { + output.WriteRawTag(8); + output.WriteInt32(Item); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Item != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Item); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ItemField other) { + if (other == null) { + return; + } + if (other.Item != 0) { + Item = other.Item; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Item = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Item = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class ReservedNames : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ReservedNames()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ReservedNames() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ReservedNames(ReservedNames other) : this() { + types_ = other.types_; + descriptor_ = other.descriptor_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ReservedNames Clone() { + return new ReservedNames(this); + } + + /// Field number for the "types" field. + public const int Types_FieldNumber = 1; + private int types_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Types_ { + get { return types_; } + set { + types_ = value; + } + } + + /// Field number for the "descriptor" field. + public const int Descriptor_FieldNumber = 2; + private int descriptor_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Descriptor_ { + get { return descriptor_; } + set { + descriptor_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ReservedNames); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ReservedNames other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Types_ != other.Types_) return false; + if (Descriptor_ != other.Descriptor_) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Types_ != 0) hash ^= Types_.GetHashCode(); + if (Descriptor_ != 0) hash ^= Descriptor_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Types_ != 0) { + output.WriteRawTag(8); + output.WriteInt32(Types_); + } + if (Descriptor_ != 0) { + output.WriteRawTag(16); + output.WriteInt32(Descriptor_); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Types_ != 0) { + output.WriteRawTag(8); + output.WriteInt32(Types_); + } + if (Descriptor_ != 0) { + output.WriteRawTag(16); + output.WriteInt32(Descriptor_); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Types_ != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Types_); + } + if (Descriptor_ != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Descriptor_); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ReservedNames other) { + if (other == null) { + return; + } + if (other.Types_ != 0) { + Types_ = other.Types_; + } + if (other.Descriptor_ != 0) { + Descriptor_ = other.Descriptor_; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Types_ = input.ReadInt32(); + break; + } + case 16: { + Descriptor_ = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Types_ = input.ReadInt32(); + break; + } + case 16: { + Descriptor_ = input.ReadInt32(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the ReservedNames message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + /// + /// Force a nested type called Types + /// + public sealed partial class SomeNestedType : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SomeNestedType()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.ReservedNames.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SomeNestedType() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SomeNestedType(SomeNestedType other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SomeNestedType Clone() { + return new SomeNestedType(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SomeNestedType); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SomeNestedType other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SomeNestedType other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + } + #endregion + + } + + /// + /// These fields are deliberately not declared in numeric + /// order, and the oneof fields aren't contiguous either. + /// This allows for reasonably robust tests of JSON output + /// ordering. + /// TestFieldOrderings in unittest_proto3.proto is similar, + /// but doesn't include oneofs. + /// TODO: Consider adding oneofs to TestFieldOrderings, although + /// that will require fixing other tests in multiple platforms. + /// Alternatively, consider just adding this to + /// unittest_proto3.proto if multiple platforms want it. + /// + public sealed partial class TestJsonFieldOrdering : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestJsonFieldOrdering()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[6]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestJsonFieldOrdering() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestJsonFieldOrdering(TestJsonFieldOrdering other) : this() { + plainInt32_ = other.plainInt32_; + plainString_ = other.plainString_; + switch (other.O1Case) { + case O1OneofCase.O1String: + O1String = other.O1String; + break; + case O1OneofCase.O1Int32: + O1Int32 = other.O1Int32; + break; + } + + switch (other.O2Case) { + case O2OneofCase.O2Int32: + O2Int32 = other.O2Int32; + break; + case O2OneofCase.O2String: + O2String = other.O2String; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestJsonFieldOrdering Clone() { + return new TestJsonFieldOrdering(this); + } + + /// Field number for the "plain_int32" field. + public const int PlainInt32FieldNumber = 4; + private int plainInt32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int PlainInt32 { + get { return plainInt32_; } + set { + plainInt32_ = value; + } + } + + /// Field number for the "o1_string" field. + public const int O1StringFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string O1String { + get { return o1Case_ == O1OneofCase.O1String ? (string) o1_ : ""; } + set { + o1_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + o1Case_ = O1OneofCase.O1String; + } + } + + /// Field number for the "o1_int32" field. + public const int O1Int32FieldNumber = 5; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int O1Int32 { + get { return o1Case_ == O1OneofCase.O1Int32 ? (int) o1_ : 0; } + set { + o1_ = value; + o1Case_ = O1OneofCase.O1Int32; + } + } + + /// Field number for the "plain_string" field. + public const int PlainStringFieldNumber = 1; + private string plainString_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string PlainString { + get { return plainString_; } + set { + plainString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "o2_int32" field. + public const int O2Int32FieldNumber = 6; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int O2Int32 { + get { return o2Case_ == O2OneofCase.O2Int32 ? (int) o2_ : 0; } + set { + o2_ = value; + o2Case_ = O2OneofCase.O2Int32; + } + } + + /// Field number for the "o2_string" field. + public const int O2StringFieldNumber = 3; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string O2String { + get { return o2Case_ == O2OneofCase.O2String ? (string) o2_ : ""; } + set { + o2_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + o2Case_ = O2OneofCase.O2String; + } + } + + private object o1_; + /// Enum of possible cases for the "o1" oneof. + public enum O1OneofCase { + None = 0, + O1String = 2, + O1Int32 = 5, + } + private O1OneofCase o1Case_ = O1OneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public O1OneofCase O1Case { + get { return o1Case_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearO1() { + o1Case_ = O1OneofCase.None; + o1_ = null; + } + + private object o2_; + /// Enum of possible cases for the "o2" oneof. + public enum O2OneofCase { + None = 0, + O2Int32 = 6, + O2String = 3, + } + private O2OneofCase o2Case_ = O2OneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public O2OneofCase O2Case { + get { return o2Case_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearO2() { + o2Case_ = O2OneofCase.None; + o2_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestJsonFieldOrdering); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestJsonFieldOrdering other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (PlainInt32 != other.PlainInt32) return false; + if (O1String != other.O1String) return false; + if (O1Int32 != other.O1Int32) return false; + if (PlainString != other.PlainString) return false; + if (O2Int32 != other.O2Int32) return false; + if (O2String != other.O2String) return false; + if (O1Case != other.O1Case) return false; + if (O2Case != other.O2Case) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (PlainInt32 != 0) hash ^= PlainInt32.GetHashCode(); + if (o1Case_ == O1OneofCase.O1String) hash ^= O1String.GetHashCode(); + if (o1Case_ == O1OneofCase.O1Int32) hash ^= O1Int32.GetHashCode(); + if (PlainString.Length != 0) hash ^= PlainString.GetHashCode(); + if (o2Case_ == O2OneofCase.O2Int32) hash ^= O2Int32.GetHashCode(); + if (o2Case_ == O2OneofCase.O2String) hash ^= O2String.GetHashCode(); + hash ^= (int) o1Case_; + hash ^= (int) o2Case_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (PlainString.Length != 0) { + output.WriteRawTag(10); + output.WriteString(PlainString); + } + if (o1Case_ == O1OneofCase.O1String) { + output.WriteRawTag(18); + output.WriteString(O1String); + } + if (o2Case_ == O2OneofCase.O2String) { + output.WriteRawTag(26); + output.WriteString(O2String); + } + if (PlainInt32 != 0) { + output.WriteRawTag(32); + output.WriteInt32(PlainInt32); + } + if (o1Case_ == O1OneofCase.O1Int32) { + output.WriteRawTag(40); + output.WriteInt32(O1Int32); + } + if (o2Case_ == O2OneofCase.O2Int32) { + output.WriteRawTag(48); + output.WriteInt32(O2Int32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (PlainString.Length != 0) { + output.WriteRawTag(10); + output.WriteString(PlainString); + } + if (o1Case_ == O1OneofCase.O1String) { + output.WriteRawTag(18); + output.WriteString(O1String); + } + if (o2Case_ == O2OneofCase.O2String) { + output.WriteRawTag(26); + output.WriteString(O2String); + } + if (PlainInt32 != 0) { + output.WriteRawTag(32); + output.WriteInt32(PlainInt32); + } + if (o1Case_ == O1OneofCase.O1Int32) { + output.WriteRawTag(40); + output.WriteInt32(O1Int32); + } + if (o2Case_ == O2OneofCase.O2Int32) { + output.WriteRawTag(48); + output.WriteInt32(O2Int32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (PlainInt32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(PlainInt32); + } + if (o1Case_ == O1OneofCase.O1String) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(O1String); + } + if (o1Case_ == O1OneofCase.O1Int32) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(O1Int32); + } + if (PlainString.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(PlainString); + } + if (o2Case_ == O2OneofCase.O2Int32) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(O2Int32); + } + if (o2Case_ == O2OneofCase.O2String) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(O2String); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestJsonFieldOrdering other) { + if (other == null) { + return; + } + if (other.PlainInt32 != 0) { + PlainInt32 = other.PlainInt32; + } + if (other.PlainString.Length != 0) { + PlainString = other.PlainString; + } + switch (other.O1Case) { + case O1OneofCase.O1String: + O1String = other.O1String; + break; + case O1OneofCase.O1Int32: + O1Int32 = other.O1Int32; + break; + } + + switch (other.O2Case) { + case O2OneofCase.O2Int32: + O2Int32 = other.O2Int32; + break; + case O2OneofCase.O2String: + O2String = other.O2String; + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + PlainString = input.ReadString(); + break; + } + case 18: { + O1String = input.ReadString(); + break; + } + case 26: { + O2String = input.ReadString(); + break; + } + case 32: { + PlainInt32 = input.ReadInt32(); + break; + } + case 40: { + O1Int32 = input.ReadInt32(); + break; + } + case 48: { + O2Int32 = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + PlainString = input.ReadString(); + break; + } + case 18: { + O1String = input.ReadString(); + break; + } + case 26: { + O2String = input.ReadString(); + break; + } + case 32: { + PlainInt32 = input.ReadInt32(); + break; + } + case 40: { + O1Int32 = input.ReadInt32(); + break; + } + case 48: { + O2Int32 = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestJsonName : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestJsonName()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[7]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestJsonName() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestJsonName(TestJsonName other) : this() { + name_ = other.name_; + description_ = other.description_; + guid_ = other.guid_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestJsonName Clone() { + return new TestJsonName(this); + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 1; + private string name_ = ""; + /// + /// Message for testing the effects for of the json_name option + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "description" field. + public const int DescriptionFieldNumber = 2; + private string description_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Description { + get { return description_; } + set { + description_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "guid" field. + public const int GuidFieldNumber = 3; + private string guid_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Guid { + get { return guid_; } + set { + guid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestJsonName); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestJsonName other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Name != other.Name) return false; + if (Description != other.Description) return false; + if (Guid != other.Guid) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (Description.Length != 0) hash ^= Description.GetHashCode(); + if (Guid.Length != 0) hash ^= Guid.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (Description.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Description); + } + if (Guid.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Guid); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (Description.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Description); + } + if (Guid.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Guid); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + if (Description.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Description); + } + if (Guid.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Guid); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestJsonName other) { + if (other == null) { + return; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + if (other.Description.Length != 0) { + Description = other.Description; + } + if (other.Guid.Length != 0) { + Guid = other.Guid; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + Description = input.ReadString(); + break; + } + case 26: { + Guid = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + Description = input.ReadString(); + break; + } + case 26: { + Guid = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// Issue 3200: When merging two messages which use the same + /// oneof case, which is itself a message type, the submessages should + /// be merged. + /// + public sealed partial class OneofMerging : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneofMerging()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[8]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneofMerging() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneofMerging(OneofMerging other) : this() { + switch (other.ValueCase) { + case ValueOneofCase.Text: + Text = other.Text; + break; + case ValueOneofCase.Nested: + Nested = other.Nested.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneofMerging Clone() { + return new OneofMerging(this); + } + + /// Field number for the "text" field. + public const int TextFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Text { + get { return valueCase_ == ValueOneofCase.Text ? (string) value_ : ""; } + set { + value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + valueCase_ = ValueOneofCase.Text; + } + } + + /// Field number for the "nested" field. + public const int NestedFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested Nested { + get { return valueCase_ == ValueOneofCase.Nested ? (global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.Nested; + } + } + + private object value_; + /// Enum of possible cases for the "value" oneof. + public enum ValueOneofCase { + None = 0, + Text = 1, + Nested = 2, + } + private ValueOneofCase valueCase_ = ValueOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ValueOneofCase ValueCase { + get { return valueCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearValue() { + valueCase_ = ValueOneofCase.None; + value_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as OneofMerging); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(OneofMerging other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Text != other.Text) return false; + if (!object.Equals(Nested, other.Nested)) return false; + if (ValueCase != other.ValueCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (valueCase_ == ValueOneofCase.Text) hash ^= Text.GetHashCode(); + if (valueCase_ == ValueOneofCase.Nested) hash ^= Nested.GetHashCode(); + hash ^= (int) valueCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (valueCase_ == ValueOneofCase.Text) { + output.WriteRawTag(10); + output.WriteString(Text); + } + if (valueCase_ == ValueOneofCase.Nested) { + output.WriteRawTag(18); + output.WriteMessage(Nested); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (valueCase_ == ValueOneofCase.Text) { + output.WriteRawTag(10); + output.WriteString(Text); + } + if (valueCase_ == ValueOneofCase.Nested) { + output.WriteRawTag(18); + output.WriteMessage(Nested); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (valueCase_ == ValueOneofCase.Text) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Text); + } + if (valueCase_ == ValueOneofCase.Nested) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Nested); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(OneofMerging other) { + if (other == null) { + return; + } + switch (other.ValueCase) { + case ValueOneofCase.Text: + Text = other.Text; + break; + case ValueOneofCase.Nested: + if (Nested == null) { + Nested = new global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested(); + } + Nested.MergeFrom(other.Nested); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Text = input.ReadString(); + break; + } + case 18: { + global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested subBuilder = new global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested(); + if (valueCase_ == ValueOneofCase.Nested) { + subBuilder.MergeFrom(Nested); + } + input.ReadMessage(subBuilder); + Nested = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Text = input.ReadString(); + break; + } + case 18: { + global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested subBuilder = new global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested(); + if (valueCase_ == ValueOneofCase.Nested) { + subBuilder.MergeFrom(Nested); + } + input.ReadMessage(subBuilder); + Nested = subBuilder; + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the OneofMerging message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class Nested : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Nested()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.OneofMerging.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Nested() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Nested(Nested other) : this() { + x_ = other.x_; + y_ = other.y_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Nested Clone() { + return new Nested(this); + } + + /// Field number for the "x" field. + public const int XFieldNumber = 1; + private int x_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int X { + get { return x_; } + set { + x_ = value; + } + } + + /// Field number for the "y" field. + public const int YFieldNumber = 2; + private int y_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Y { + get { return y_; } + set { + y_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Nested); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Nested other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (X != other.X) return false; + if (Y != other.Y) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (X != 0) hash ^= X.GetHashCode(); + if (Y != 0) hash ^= Y.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (X != 0) { + output.WriteRawTag(8); + output.WriteInt32(X); + } + if (Y != 0) { + output.WriteRawTag(16); + output.WriteInt32(Y); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (X != 0) { + output.WriteRawTag(8); + output.WriteInt32(X); + } + if (Y != 0) { + output.WriteRawTag(16); + output.WriteInt32(Y); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (X != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(X); + } + if (Y != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Y); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Nested other) { + if (other == null) { + return; + } + if (other.X != 0) { + X = other.X; + } + if (other.Y != 0) { + Y = other.Y; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + X = input.ReadInt32(); + break; + } + case 16: { + Y = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + X = input.ReadInt32(); + break; + } + case 16: { + Y = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class NullValueOutsideStruct : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NullValueOutsideStruct()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[9]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NullValueOutsideStruct() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NullValueOutsideStruct(NullValueOutsideStruct other) : this() { + switch (other.ValueCase) { + case ValueOneofCase.StringValue: + StringValue = other.StringValue; + break; + case ValueOneofCase.NullValue: + NullValue = other.NullValue; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NullValueOutsideStruct Clone() { + return new NullValueOutsideStruct(this); + } + + /// Field number for the "string_value" field. + public const int StringValueFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string StringValue { + get { return valueCase_ == ValueOneofCase.StringValue ? (string) value_ : ""; } + set { + value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + valueCase_ = ValueOneofCase.StringValue; + } + } + + /// Field number for the "null_value" field. + public const int NullValueFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.NullValue NullValue { + get { return valueCase_ == ValueOneofCase.NullValue ? (global::Google.Protobuf.WellKnownTypes.NullValue) value_ : global::Google.Protobuf.WellKnownTypes.NullValue.NullValue; } + set { + value_ = value; + valueCase_ = ValueOneofCase.NullValue; + } + } + + private object value_; + /// Enum of possible cases for the "value" oneof. + public enum ValueOneofCase { + None = 0, + StringValue = 1, + NullValue = 2, + } + private ValueOneofCase valueCase_ = ValueOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ValueOneofCase ValueCase { + get { return valueCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearValue() { + valueCase_ = ValueOneofCase.None; + value_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NullValueOutsideStruct); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NullValueOutsideStruct other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (StringValue != other.StringValue) return false; + if (NullValue != other.NullValue) return false; + if (ValueCase != other.ValueCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (valueCase_ == ValueOneofCase.StringValue) hash ^= StringValue.GetHashCode(); + if (valueCase_ == ValueOneofCase.NullValue) hash ^= NullValue.GetHashCode(); + hash ^= (int) valueCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (valueCase_ == ValueOneofCase.StringValue) { + output.WriteRawTag(10); + output.WriteString(StringValue); + } + if (valueCase_ == ValueOneofCase.NullValue) { + output.WriteRawTag(16); + output.WriteEnum((int) NullValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (valueCase_ == ValueOneofCase.StringValue) { + output.WriteRawTag(10); + output.WriteString(StringValue); + } + if (valueCase_ == ValueOneofCase.NullValue) { + output.WriteRawTag(16); + output.WriteEnum((int) NullValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (valueCase_ == ValueOneofCase.StringValue) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(StringValue); + } + if (valueCase_ == ValueOneofCase.NullValue) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) NullValue); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NullValueOutsideStruct other) { + if (other == null) { + return; + } + switch (other.ValueCase) { + case ValueOneofCase.StringValue: + StringValue = other.StringValue; + break; + case ValueOneofCase.NullValue: + NullValue = other.NullValue; + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + StringValue = input.ReadString(); + break; + } + case 16: { + value_ = input.ReadEnum(); + valueCase_ = ValueOneofCase.NullValue; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + StringValue = input.ReadString(); + break; + } + case 16: { + value_ = input.ReadEnum(); + valueCase_ = ValueOneofCase.NullValue; + break; + } + } + } + } + #endif + + } + + public sealed partial class NullValueNotInOneof : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NullValueNotInOneof()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[10]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NullValueNotInOneof() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NullValueNotInOneof(NullValueNotInOneof other) : this() { + nullValue_ = other.nullValue_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NullValueNotInOneof Clone() { + return new NullValueNotInOneof(this); + } + + /// Field number for the "null_value" field. + public const int NullValueFieldNumber = 2; + private global::Google.Protobuf.WellKnownTypes.NullValue nullValue_ = global::Google.Protobuf.WellKnownTypes.NullValue.NullValue; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.NullValue NullValue { + get { return nullValue_; } + set { + nullValue_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NullValueNotInOneof); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NullValueNotInOneof other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (NullValue != other.NullValue) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) hash ^= NullValue.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + output.WriteRawTag(16); + output.WriteEnum((int) NullValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + output.WriteRawTag(16); + output.WriteEnum((int) NullValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) NullValue); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NullValueNotInOneof other) { + if (other == null) { + return; + } + if (other.NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + NullValue = other.NullValue; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 16: { + NullValue = (global::Google.Protobuf.WellKnownTypes.NullValue) input.ReadEnum(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 16: { + NullValue = (global::Google.Protobuf.WellKnownTypes.NullValue) input.ReadEnum(); + break; + } + } + } + } + #endif + + } + + public sealed partial class MixedRegularAndOptional : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MixedRegularAndOptional()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[11]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MixedRegularAndOptional() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MixedRegularAndOptional(MixedRegularAndOptional other) : this() { + regularField_ = other.regularField_; + optionalField_ = other.optionalField_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MixedRegularAndOptional Clone() { + return new MixedRegularAndOptional(this); + } + + /// Field number for the "regular_field" field. + public const int RegularFieldFieldNumber = 1; + private string regularField_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string RegularField { + get { return regularField_; } + set { + regularField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "optional_field" field. + public const int OptionalFieldFieldNumber = 2; + private string optionalField_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalField { + get { return optionalField_ ?? ""; } + set { + optionalField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_field" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalField { + get { return optionalField_ != null; } + } + /// Clears the value of the "optional_field" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalField() { + optionalField_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as MixedRegularAndOptional); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(MixedRegularAndOptional other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (RegularField != other.RegularField) return false; + if (OptionalField != other.OptionalField) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (RegularField.Length != 0) hash ^= RegularField.GetHashCode(); + if (HasOptionalField) hash ^= OptionalField.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (RegularField.Length != 0) { + output.WriteRawTag(10); + output.WriteString(RegularField); + } + if (HasOptionalField) { + output.WriteRawTag(18); + output.WriteString(OptionalField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (RegularField.Length != 0) { + output.WriteRawTag(10); + output.WriteString(RegularField); + } + if (HasOptionalField) { + output.WriteRawTag(18); + output.WriteString(OptionalField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (RegularField.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(RegularField); + } + if (HasOptionalField) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(OptionalField); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(MixedRegularAndOptional other) { + if (other == null) { + return; + } + if (other.RegularField.Length != 0) { + RegularField = other.RegularField; + } + if (other.HasOptionalField) { + OptionalField = other.OptionalField; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + RegularField = input.ReadString(); + break; + } + case 18: { + OptionalField = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + RegularField = input.ReadString(); + break; + } + case 18: { + OptionalField = input.ReadString(); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs new file mode 100644 index 0000000000000..b81eb573836d0 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs @@ -0,0 +1,9902 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: unittest_proto3.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Google.Protobuf.TestProtos { + + /// Holder for reflection information generated from unittest_proto3.proto + public static partial class UnittestProto3Reflection { + + #region Descriptor + /// File descriptor for unittest_proto3.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestProto3Reflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChV1bml0dGVzdF9wcm90bzMucHJvdG8SEnByb3RvYnVmX3VuaXR0ZXN0Mxoc", + "dW5pdHRlc3RfaW1wb3J0X3Byb3RvMy5wcm90byL5DwoMVGVzdEFsbFR5cGVz", + "EhQKDHNpbmdsZV9pbnQzMhgBIAEoBRIUCgxzaW5nbGVfaW50NjQYAiABKAMS", + "FQoNc2luZ2xlX3VpbnQzMhgDIAEoDRIVCg1zaW5nbGVfdWludDY0GAQgASgE", + "EhUKDXNpbmdsZV9zaW50MzIYBSABKBESFQoNc2luZ2xlX3NpbnQ2NBgGIAEo", + "EhIWCg5zaW5nbGVfZml4ZWQzMhgHIAEoBxIWCg5zaW5nbGVfZml4ZWQ2NBgI", + "IAEoBhIXCg9zaW5nbGVfc2ZpeGVkMzIYCSABKA8SFwoPc2luZ2xlX3NmaXhl", + "ZDY0GAogASgQEhQKDHNpbmdsZV9mbG9hdBgLIAEoAhIVCg1zaW5nbGVfZG91", + "YmxlGAwgASgBEhMKC3NpbmdsZV9ib29sGA0gASgIEhUKDXNpbmdsZV9zdHJp", + "bmcYDiABKAkSFAoMc2luZ2xlX2J5dGVzGA8gASgMEk0KFXNpbmdsZV9uZXN0", + "ZWRfbWVzc2FnZRgSIAEoCzIuLnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0QWxs", + "VHlwZXMuTmVzdGVkTWVzc2FnZRJCChZzaW5nbGVfZm9yZWlnbl9tZXNzYWdl", + "GBMgASgLMiIucHJvdG9idWZfdW5pdHRlc3QzLkZvcmVpZ25NZXNzYWdlEkYK", + "FXNpbmdsZV9pbXBvcnRfbWVzc2FnZRgUIAEoCzInLnByb3RvYnVmX3VuaXR0", + "ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlEkcKEnNpbmdsZV9uZXN0ZWRfZW51", + "bRgVIAEoDjIrLnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0QWxsVHlwZXMuTmVz", + "dGVkRW51bRI8ChNzaW5nbGVfZm9yZWlnbl9lbnVtGBYgASgOMh8ucHJvdG9i", + "dWZfdW5pdHRlc3QzLkZvcmVpZ25FbnVtEkAKEnNpbmdsZV9pbXBvcnRfZW51", + "bRgXIAEoDjIkLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVt", + "ElMKHHNpbmdsZV9wdWJsaWNfaW1wb3J0X21lc3NhZ2UYGiABKAsyLS5wcm90", + "b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZRIWCg5y", + "ZXBlYXRlZF9pbnQzMhgfIAMoBRIWCg5yZXBlYXRlZF9pbnQ2NBggIAMoAxIX", + "Cg9yZXBlYXRlZF91aW50MzIYISADKA0SFwoPcmVwZWF0ZWRfdWludDY0GCIg", + "AygEEhcKD3JlcGVhdGVkX3NpbnQzMhgjIAMoERIXCg9yZXBlYXRlZF9zaW50", + "NjQYJCADKBISGAoQcmVwZWF0ZWRfZml4ZWQzMhglIAMoBxIYChByZXBlYXRl", + "ZF9maXhlZDY0GCYgAygGEhkKEXJlcGVhdGVkX3NmaXhlZDMyGCcgAygPEhkK", + "EXJlcGVhdGVkX3NmaXhlZDY0GCggAygQEhYKDnJlcGVhdGVkX2Zsb2F0GCkg", + "AygCEhcKD3JlcGVhdGVkX2RvdWJsZRgqIAMoARIVCg1yZXBlYXRlZF9ib29s", + "GCsgAygIEhcKD3JlcGVhdGVkX3N0cmluZxgsIAMoCRIWCg5yZXBlYXRlZF9i", + "eXRlcxgtIAMoDBJPChdyZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZRgwIAMoCzIu", + "LnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2Fn", + "ZRJEChhyZXBlYXRlZF9mb3JlaWduX21lc3NhZ2UYMSADKAsyIi5wcm90b2J1", + "Zl91bml0dGVzdDMuRm9yZWlnbk1lc3NhZ2USSAoXcmVwZWF0ZWRfaW1wb3J0", + "X21lc3NhZ2UYMiADKAsyJy5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1w", + "b3J0TWVzc2FnZRJJChRyZXBlYXRlZF9uZXN0ZWRfZW51bRgzIAMoDjIrLnBy", + "b3RvYnVmX3VuaXR0ZXN0My5UZXN0QWxsVHlwZXMuTmVzdGVkRW51bRI+ChVy", + "ZXBlYXRlZF9mb3JlaWduX2VudW0YNCADKA4yHy5wcm90b2J1Zl91bml0dGVz", + "dDMuRm9yZWlnbkVudW0SQgoUcmVwZWF0ZWRfaW1wb3J0X2VudW0YNSADKA4y", + "JC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bRJVCh5yZXBl", + "YXRlZF9wdWJsaWNfaW1wb3J0X21lc3NhZ2UYNiADKAsyLS5wcm90b2J1Zl91", + "bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZRIWCgxvbmVvZl91", + "aW50MzIYbyABKA1IABJOChRvbmVvZl9uZXN0ZWRfbWVzc2FnZRhwIAEoCzIu", + "LnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2Fn", + "ZUgAEhYKDG9uZW9mX3N0cmluZxhxIAEoCUgAEhUKC29uZW9mX2J5dGVzGHIg", + "ASgMSAAaGwoNTmVzdGVkTWVzc2FnZRIKCgJiYhgBIAEoBSJWCgpOZXN0ZWRF", + "bnVtEhsKF05FU1RFRF9FTlVNX1VOU1BFQ0lGSUVEEAASBwoDRk9PEAESBwoD", + "QkFSEAISBwoDQkFaEAMSEAoDTkVHEP///////////wFCDQoLb25lb2ZfZmll", + "bGQivgEKEk5lc3RlZFRlc3RBbGxUeXBlcxI1CgVjaGlsZBgBIAEoCzImLnBy", + "b3RvYnVmX3VuaXR0ZXN0My5OZXN0ZWRUZXN0QWxsVHlwZXMSMQoHcGF5bG9h", + "ZBgCIAEoCzIgLnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0QWxsVHlwZXMSPgoO", + "cmVwZWF0ZWRfY2hpbGQYAyADKAsyJi5wcm90b2J1Zl91bml0dGVzdDMuTmVz", + "dGVkVGVzdEFsbFR5cGVzIjQKFFRlc3REZXByZWNhdGVkRmllbGRzEhwKEGRl", + "cHJlY2F0ZWRfaW50MzIYASABKAVCAhgBIhsKDkZvcmVpZ25NZXNzYWdlEgkK", + "AWMYASABKAUiMAoSVGVzdFJlc2VydmVkRmllbGRzSgQIAhADSgQIDxAQSgQI", + "CRAMUgNiYXJSA2JheiJbChFUZXN0Rm9yZWlnbk5lc3RlZBJGCg5mb3JlaWdu", + "X25lc3RlZBgBIAEoCzIuLnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0QWxsVHlw", + "ZXMuTmVzdGVkTWVzc2FnZSI0ChhUZXN0UmVhbGx5TGFyZ2VUYWdOdW1iZXIS", + "CQoBYRgBIAEoBRINCgJiYhj///9/IAEoBSJWChRUZXN0UmVjdXJzaXZlTWVz", + "c2FnZRIzCgFhGAEgASgLMigucHJvdG9idWZfdW5pdHRlc3QzLlRlc3RSZWN1", + "cnNpdmVNZXNzYWdlEgkKAWkYAiABKAUiTAoUVGVzdE11dHVhbFJlY3Vyc2lv", + "bkESNAoCYmIYASABKAsyKC5wcm90b2J1Zl91bml0dGVzdDMuVGVzdE11dHVh", + "bFJlY3Vyc2lvbkIiYwoUVGVzdE11dHVhbFJlY3Vyc2lvbkISMwoBYRgBIAEo", + "CzIoLnByb3RvYnVmX3VuaXR0ZXN0My5UZXN0TXV0dWFsUmVjdXJzaW9uQRIW", + "Cg5vcHRpb25hbF9pbnQzMhgCIAEoBSJNChJUZXN0RW51bUFsbG93QWxpYXMS", + "NwoFdmFsdWUYASABKA4yKC5wcm90b2J1Zl91bml0dGVzdDMuVGVzdEVudW1X", + "aXRoRHVwVmFsdWUi7wIKF1Rlc3RDYW1lbENhc2VGaWVsZE5hbWVzEhYKDlBy", + "aW1pdGl2ZUZpZWxkGAEgASgFEhMKC1N0cmluZ0ZpZWxkGAIgASgJEjIKCUVu", + "dW1GaWVsZBgDIAEoDjIfLnByb3RvYnVmX3VuaXR0ZXN0My5Gb3JlaWduRW51", + "bRI4CgxNZXNzYWdlRmllbGQYBCABKAsyIi5wcm90b2J1Zl91bml0dGVzdDMu", + "Rm9yZWlnbk1lc3NhZ2USHgoWUmVwZWF0ZWRQcmltaXRpdmVGaWVsZBgHIAMo", + "BRIbChNSZXBlYXRlZFN0cmluZ0ZpZWxkGAggAygJEjoKEVJlcGVhdGVkRW51", + "bUZpZWxkGAkgAygOMh8ucHJvdG9idWZfdW5pdHRlc3QzLkZvcmVpZ25FbnVt", + "EkAKFFJlcGVhdGVkTWVzc2FnZUZpZWxkGAogAygLMiIucHJvdG9idWZfdW5p", + "dHRlc3QzLkZvcmVpZ25NZXNzYWdlIsgBChJUZXN0RmllbGRPcmRlcmluZ3MS", + "EQoJbXlfc3RyaW5nGAsgASgJEg4KBm15X2ludBgBIAEoAxIQCghteV9mbG9h", + "dBhlIAEoAhJUChVzaW5nbGVfbmVzdGVkX21lc3NhZ2UYyAEgASgLMjQucHJv", + "dG9idWZfdW5pdHRlc3QzLlRlc3RGaWVsZE9yZGVyaW5ncy5OZXN0ZWRNZXNz", + "YWdlGicKDU5lc3RlZE1lc3NhZ2USCgoCb28YAiABKAMSCgoCYmIYASABKAUi", + "TAoRU3BhcnNlRW51bU1lc3NhZ2USNwoLc3BhcnNlX2VudW0YASABKA4yIi5w", + "cm90b2J1Zl91bml0dGVzdDMuVGVzdFNwYXJzZUVudW0iGQoJT25lU3RyaW5n", + "EgwKBGRhdGEYASABKAkiGgoKTW9yZVN0cmluZxIMCgRkYXRhGAEgAygJIhgK", + "CE9uZUJ5dGVzEgwKBGRhdGEYASABKAwiGQoJTW9yZUJ5dGVzEgwKBGRhdGEY", + "ASABKAwiHAoMSW50MzJNZXNzYWdlEgwKBGRhdGEYASABKAUiHQoNVWludDMy", + "TWVzc2FnZRIMCgRkYXRhGAEgASgNIhwKDEludDY0TWVzc2FnZRIMCgRkYXRh", + "GAEgASgDIh0KDVVpbnQ2NE1lc3NhZ2USDAoEZGF0YRgBIAEoBCIbCgtCb29s", + "TWVzc2FnZRIMCgRkYXRhGAEgASgIInQKCVRlc3RPbmVvZhIRCgdmb29faW50", + "GAEgASgFSAASFAoKZm9vX3N0cmluZxgCIAEoCUgAEjcKC2Zvb19tZXNzYWdl", + "GAMgASgLMiAucHJvdG9idWZfdW5pdHRlc3QzLlRlc3RBbGxUeXBlc0gAQgUK", + "A2ZvbyKrAwoPVGVzdFBhY2tlZFR5cGVzEhgKDHBhY2tlZF9pbnQzMhhaIAMo", + "BUICEAESGAoMcGFja2VkX2ludDY0GFsgAygDQgIQARIZCg1wYWNrZWRfdWlu", + "dDMyGFwgAygNQgIQARIZCg1wYWNrZWRfdWludDY0GF0gAygEQgIQARIZCg1w", + "YWNrZWRfc2ludDMyGF4gAygRQgIQARIZCg1wYWNrZWRfc2ludDY0GF8gAygS", + "QgIQARIaCg5wYWNrZWRfZml4ZWQzMhhgIAMoB0ICEAESGgoOcGFja2VkX2Zp", + "eGVkNjQYYSADKAZCAhABEhsKD3BhY2tlZF9zZml4ZWQzMhhiIAMoD0ICEAES", + "GwoPcGFja2VkX3NmaXhlZDY0GGMgAygQQgIQARIYCgxwYWNrZWRfZmxvYXQY", + "ZCADKAJCAhABEhkKDXBhY2tlZF9kb3VibGUYZSADKAFCAhABEhcKC3BhY2tl", + "ZF9ib29sGGYgAygIQgIQARI4CgtwYWNrZWRfZW51bRhnIAMoDjIfLnByb3Rv", + "YnVmX3VuaXR0ZXN0My5Gb3JlaWduRW51bUICEAEiyQMKEVRlc3RVbnBhY2tl", + "ZFR5cGVzEhoKDnVucGFja2VkX2ludDMyGFogAygFQgIQABIaCg51bnBhY2tl", + "ZF9pbnQ2NBhbIAMoA0ICEAASGwoPdW5wYWNrZWRfdWludDMyGFwgAygNQgIQ", + "ABIbCg91bnBhY2tlZF91aW50NjQYXSADKARCAhAAEhsKD3VucGFja2VkX3Np", + "bnQzMhheIAMoEUICEAASGwoPdW5wYWNrZWRfc2ludDY0GF8gAygSQgIQABIc", + "ChB1bnBhY2tlZF9maXhlZDMyGGAgAygHQgIQABIcChB1bnBhY2tlZF9maXhl", + "ZDY0GGEgAygGQgIQABIdChF1bnBhY2tlZF9zZml4ZWQzMhhiIAMoD0ICEAAS", + "HQoRdW5wYWNrZWRfc2ZpeGVkNjQYYyADKBBCAhAAEhoKDnVucGFja2VkX2Zs", + "b2F0GGQgAygCQgIQABIbCg91bnBhY2tlZF9kb3VibGUYZSADKAFCAhAAEhkK", + "DXVucGFja2VkX2Jvb2wYZiADKAhCAhAAEjoKDXVucGFja2VkX2VudW0YZyAD", + "KA4yHy5wcm90b2J1Zl91bml0dGVzdDMuRm9yZWlnbkVudW1CAhAAIsABCiNU", + "ZXN0UmVwZWF0ZWRTY2FsYXJEaWZmZXJlbnRUYWdTaXplcxIYChByZXBlYXRl", + "ZF9maXhlZDMyGAwgAygHEhYKDnJlcGVhdGVkX2ludDMyGA0gAygFEhkKEHJl", + "cGVhdGVkX2ZpeGVkNjQY/g8gAygGEhcKDnJlcGVhdGVkX2ludDY0GP8PIAMo", + "AxIYCg5yZXBlYXRlZF9mbG9hdBj+/w8gAygCEhkKD3JlcGVhdGVkX3VpbnQ2", + "NBj//w8gAygEIigKG1Rlc3RDb21tZW50SW5qZWN0aW9uTWVzc2FnZRIJCgFh", + "GAEgASgJIgwKCkZvb1JlcXVlc3QiDQoLRm9vUmVzcG9uc2UiEgoQRm9vQ2xp", + "ZW50TWVzc2FnZSISChBGb29TZXJ2ZXJNZXNzYWdlIgwKCkJhclJlcXVlc3Qi", + "DQoLQmFyUmVzcG9uc2UiEgoQVGVzdEVtcHR5TWVzc2FnZSJwCg5Db21tZW50", + "TWVzc2FnZRIMCgR0ZXh0GAEgASgJGisKFE5lc3RlZENvbW1lbnRNZXNzYWdl", + "EhMKC25lc3RlZF90ZXh0GAEgASgJIiMKEU5lc3RlZENvbW1lbnRFbnVtEg4K", + "ClpFUk9fVkFMVUUQACpZCgtGb3JlaWduRW51bRIXChNGT1JFSUdOX1VOU1BF", + "Q0lGSUVEEAASDwoLRk9SRUlHTl9GT08QBBIPCgtGT1JFSUdOX0JBUhAFEg8K", + "C0ZPUkVJR05fQkFaEAYqdQoUVGVzdEVudW1XaXRoRHVwVmFsdWUSKAokVEVT", + "VF9FTlVNX1dJVEhfRFVQX1ZBTFVFX1VOU1BFQ0lGSUVEEAASCAoERk9PMRAB", + "EggKBEJBUjEQAhIHCgNCQVoQAxIICgRGT08yEAESCAoEQkFSMhACGgIQASqd", + "AQoOVGVzdFNwYXJzZUVudW0SIAocVEVTVF9TUEFSU0VfRU5VTV9VTlNQRUNJ", + "RklFRBAAEgwKCFNQQVJTRV9BEHsSDgoIU1BBUlNFX0IQpucDEg8KCFNQQVJT", + "RV9DELKxgAYSFQoIU1BBUlNFX0QQ8f//////////ARIVCghTUEFSU0VfRRC0", + "3vz///////8BEgwKCFNQQVJTRV9HEAIqHQoLQ29tbWVudEVudW0SDgoKWkVS", + "T19WQUxVRRAAMp0BCgtUZXN0U2VydmljZRJGCgNGb28SHi5wcm90b2J1Zl91", + "bml0dGVzdDMuRm9vUmVxdWVzdBofLnByb3RvYnVmX3VuaXR0ZXN0My5Gb29S", + "ZXNwb25zZRJGCgNCYXISHi5wcm90b2J1Zl91bml0dGVzdDMuQmFyUmVxdWVz", + "dBofLnByb3RvYnVmX3VuaXR0ZXN0My5CYXJSZXNwb25zZUIsQg1Vbml0dGVz", + "dFByb3RvqgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportProto3Reflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ForeignEnum), typeof(global::Google.Protobuf.TestProtos.TestEnumWithDupValue), typeof(global::Google.Protobuf.TestProtos.TestSparseEnum), typeof(global::Google.Protobuf.TestProtos.CommentEnum), }, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestAllTypes), global::Google.Protobuf.TestProtos.TestAllTypes.Parser, new[]{ "SingleInt32", "SingleInt64", "SingleUint32", "SingleUint64", "SingleSint32", "SingleSint64", "SingleFixed32", "SingleFixed64", "SingleSfixed32", "SingleSfixed64", "SingleFloat", "SingleDouble", "SingleBool", "SingleString", "SingleBytes", "SingleNestedMessage", "SingleForeignMessage", "SingleImportMessage", "SingleNestedEnum", "SingleForeignEnum", "SingleImportEnum", "SinglePublicImportMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedImportMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedImportEnum", "RepeatedPublicImportMessage", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes" }, new[]{ "OneofField" }, new[]{ typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage), global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage.Parser, new[]{ "Bb" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.NestedTestAllTypes), global::Google.Protobuf.TestProtos.NestedTestAllTypes.Parser, new[]{ "Child", "Payload", "RepeatedChild" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestDeprecatedFields), global::Google.Protobuf.TestProtos.TestDeprecatedFields.Parser, new[]{ "DeprecatedInt32" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.ForeignMessage), global::Google.Protobuf.TestProtos.ForeignMessage.Parser, new[]{ "C" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestReservedFields), global::Google.Protobuf.TestProtos.TestReservedFields.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestForeignNested), global::Google.Protobuf.TestProtos.TestForeignNested.Parser, new[]{ "ForeignNested" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber), global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber.Parser, new[]{ "A", "Bb" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestRecursiveMessage), global::Google.Protobuf.TestProtos.TestRecursiveMessage.Parser, new[]{ "A", "I" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionA), global::Google.Protobuf.TestProtos.TestMutualRecursionA.Parser, new[]{ "Bb" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionB), global::Google.Protobuf.TestProtos.TestMutualRecursionB.Parser, new[]{ "A", "OptionalInt32" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestEnumAllowAlias), global::Google.Protobuf.TestProtos.TestEnumAllowAlias.Parser, new[]{ "Value" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames), global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames.Parser, new[]{ "PrimitiveField", "StringField", "EnumField", "MessageField", "RepeatedPrimitiveField", "RepeatedStringField", "RepeatedEnumField", "RepeatedMessageField" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings), global::Google.Protobuf.TestProtos.TestFieldOrderings.Parser, new[]{ "MyString", "MyInt", "MyFloat", "SingleNestedMessage" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage), global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage.Parser, new[]{ "Oo", "Bb" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.SparseEnumMessage), global::Google.Protobuf.TestProtos.SparseEnumMessage.Parser, new[]{ "SparseEnum" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.OneString), global::Google.Protobuf.TestProtos.OneString.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MoreString), global::Google.Protobuf.TestProtos.MoreString.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.OneBytes), global::Google.Protobuf.TestProtos.OneBytes.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MoreBytes), global::Google.Protobuf.TestProtos.MoreBytes.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Int32Message), global::Google.Protobuf.TestProtos.Int32Message.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Uint32Message), global::Google.Protobuf.TestProtos.Uint32Message.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Int64Message), global::Google.Protobuf.TestProtos.Int64Message.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Uint64Message), global::Google.Protobuf.TestProtos.Uint64Message.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.BoolMessage), global::Google.Protobuf.TestProtos.BoolMessage.Parser, new[]{ "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestOneof), global::Google.Protobuf.TestProtos.TestOneof.Parser, new[]{ "FooInt", "FooString", "FooMessage" }, new[]{ "Foo" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestPackedTypes), global::Google.Protobuf.TestProtos.TestPackedTypes.Parser, new[]{ "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedEnum" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestUnpackedTypes), global::Google.Protobuf.TestProtos.TestUnpackedTypes.Parser, new[]{ "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedEnum" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes), global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes.Parser, new[]{ "RepeatedFixed32", "RepeatedInt32", "RepeatedFixed64", "RepeatedInt64", "RepeatedFloat", "RepeatedUint64" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestCommentInjectionMessage), global::Google.Protobuf.TestProtos.TestCommentInjectionMessage.Parser, new[]{ "A" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooRequest), global::Google.Protobuf.TestProtos.FooRequest.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooResponse), global::Google.Protobuf.TestProtos.FooResponse.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooClientMessage), global::Google.Protobuf.TestProtos.FooClientMessage.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooServerMessage), global::Google.Protobuf.TestProtos.FooServerMessage.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.BarRequest), global::Google.Protobuf.TestProtos.BarRequest.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.BarResponse), global::Google.Protobuf.TestProtos.BarResponse.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestEmptyMessage), global::Google.Protobuf.TestProtos.TestEmptyMessage.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.CommentMessage), global::Google.Protobuf.TestProtos.CommentMessage.Parser, new[]{ "Text" }, null, new[]{ typeof(global::Google.Protobuf.TestProtos.CommentMessage.Types.NestedCommentEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.CommentMessage.Types.NestedCommentMessage), global::Google.Protobuf.TestProtos.CommentMessage.Types.NestedCommentMessage.Parser, new[]{ "NestedText" }, null, null, null, null)}) + })); + } + #endregion + + } + #region Enums + public enum ForeignEnum { + [pbr::OriginalName("FOREIGN_UNSPECIFIED")] ForeignUnspecified = 0, + [pbr::OriginalName("FOREIGN_FOO")] ForeignFoo = 4, + [pbr::OriginalName("FOREIGN_BAR")] ForeignBar = 5, + [pbr::OriginalName("FOREIGN_BAZ")] ForeignBaz = 6, + } + + /// + /// Test an enum that has multiple values with the same number. + /// + public enum TestEnumWithDupValue { + [pbr::OriginalName("TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("FOO1")] Foo1 = 1, + [pbr::OriginalName("BAR1")] Bar1 = 2, + [pbr::OriginalName("BAZ")] Baz = 3, + [pbr::OriginalName("FOO2", PreferredAlias = false)] Foo2 = 1, + [pbr::OriginalName("BAR2", PreferredAlias = false)] Bar2 = 2, + } + + /// + /// Test an enum with large, unordered values. + /// + public enum TestSparseEnum { + [pbr::OriginalName("TEST_SPARSE_ENUM_UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("SPARSE_A")] SparseA = 123, + [pbr::OriginalName("SPARSE_B")] SparseB = 62374, + [pbr::OriginalName("SPARSE_C")] SparseC = 12589234, + [pbr::OriginalName("SPARSE_D")] SparseD = -15, + [pbr::OriginalName("SPARSE_E")] SparseE = -53452, + /// + /// In proto3, value 0 must be the first one specified + /// SPARSE_F = 0; + /// + [pbr::OriginalName("SPARSE_G")] SparseG = 2, + } + + /// + /// Leading enum comment + /// + public enum CommentEnum { + /// + /// Zero value comment + /// + [pbr::OriginalName("ZERO_VALUE")] ZeroValue = 0, + } + + #endregion + + #region Messages + /// + /// This proto includes every type of field in both singular and repeated + /// forms. + /// + public sealed partial class TestAllTypes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestAllTypes()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllTypes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllTypes(TestAllTypes other) : this() { + singleInt32_ = other.singleInt32_; + singleInt64_ = other.singleInt64_; + singleUint32_ = other.singleUint32_; + singleUint64_ = other.singleUint64_; + singleSint32_ = other.singleSint32_; + singleSint64_ = other.singleSint64_; + singleFixed32_ = other.singleFixed32_; + singleFixed64_ = other.singleFixed64_; + singleSfixed32_ = other.singleSfixed32_; + singleSfixed64_ = other.singleSfixed64_; + singleFloat_ = other.singleFloat_; + singleDouble_ = other.singleDouble_; + singleBool_ = other.singleBool_; + singleString_ = other.singleString_; + singleBytes_ = other.singleBytes_; + singleNestedMessage_ = other.singleNestedMessage_ != null ? other.singleNestedMessage_.Clone() : null; + singleForeignMessage_ = other.singleForeignMessage_ != null ? other.singleForeignMessage_.Clone() : null; + singleImportMessage_ = other.singleImportMessage_ != null ? other.singleImportMessage_.Clone() : null; + singleNestedEnum_ = other.singleNestedEnum_; + singleForeignEnum_ = other.singleForeignEnum_; + singleImportEnum_ = other.singleImportEnum_; + singlePublicImportMessage_ = other.singlePublicImportMessage_ != null ? other.singlePublicImportMessage_.Clone() : null; + repeatedInt32_ = other.repeatedInt32_.Clone(); + repeatedInt64_ = other.repeatedInt64_.Clone(); + repeatedUint32_ = other.repeatedUint32_.Clone(); + repeatedUint64_ = other.repeatedUint64_.Clone(); + repeatedSint32_ = other.repeatedSint32_.Clone(); + repeatedSint64_ = other.repeatedSint64_.Clone(); + repeatedFixed32_ = other.repeatedFixed32_.Clone(); + repeatedFixed64_ = other.repeatedFixed64_.Clone(); + repeatedSfixed32_ = other.repeatedSfixed32_.Clone(); + repeatedSfixed64_ = other.repeatedSfixed64_.Clone(); + repeatedFloat_ = other.repeatedFloat_.Clone(); + repeatedDouble_ = other.repeatedDouble_.Clone(); + repeatedBool_ = other.repeatedBool_.Clone(); + repeatedString_ = other.repeatedString_.Clone(); + repeatedBytes_ = other.repeatedBytes_.Clone(); + repeatedNestedMessage_ = other.repeatedNestedMessage_.Clone(); + repeatedForeignMessage_ = other.repeatedForeignMessage_.Clone(); + repeatedImportMessage_ = other.repeatedImportMessage_.Clone(); + repeatedNestedEnum_ = other.repeatedNestedEnum_.Clone(); + repeatedForeignEnum_ = other.repeatedForeignEnum_.Clone(); + repeatedImportEnum_ = other.repeatedImportEnum_.Clone(); + repeatedPublicImportMessage_ = other.repeatedPublicImportMessage_.Clone(); + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: + OneofUint32 = other.OneofUint32; + break; + case OneofFieldOneofCase.OneofNestedMessage: + OneofNestedMessage = other.OneofNestedMessage.Clone(); + break; + case OneofFieldOneofCase.OneofString: + OneofString = other.OneofString; + break; + case OneofFieldOneofCase.OneofBytes: + OneofBytes = other.OneofBytes; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestAllTypes Clone() { + return new TestAllTypes(this); + } + + /// Field number for the "single_int32" field. + public const int SingleInt32FieldNumber = 1; + private int singleInt32_; + /// + /// Singular + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int SingleInt32 { + get { return singleInt32_; } + set { + singleInt32_ = value; + } + } + + /// Field number for the "single_int64" field. + public const int SingleInt64FieldNumber = 2; + private long singleInt64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long SingleInt64 { + get { return singleInt64_; } + set { + singleInt64_ = value; + } + } + + /// Field number for the "single_uint32" field. + public const int SingleUint32FieldNumber = 3; + private uint singleUint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint SingleUint32 { + get { return singleUint32_; } + set { + singleUint32_ = value; + } + } + + /// Field number for the "single_uint64" field. + public const int SingleUint64FieldNumber = 4; + private ulong singleUint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong SingleUint64 { + get { return singleUint64_; } + set { + singleUint64_ = value; + } + } + + /// Field number for the "single_sint32" field. + public const int SingleSint32FieldNumber = 5; + private int singleSint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int SingleSint32 { + get { return singleSint32_; } + set { + singleSint32_ = value; + } + } + + /// Field number for the "single_sint64" field. + public const int SingleSint64FieldNumber = 6; + private long singleSint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long SingleSint64 { + get { return singleSint64_; } + set { + singleSint64_ = value; + } + } + + /// Field number for the "single_fixed32" field. + public const int SingleFixed32FieldNumber = 7; + private uint singleFixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint SingleFixed32 { + get { return singleFixed32_; } + set { + singleFixed32_ = value; + } + } + + /// Field number for the "single_fixed64" field. + public const int SingleFixed64FieldNumber = 8; + private ulong singleFixed64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong SingleFixed64 { + get { return singleFixed64_; } + set { + singleFixed64_ = value; + } + } + + /// Field number for the "single_sfixed32" field. + public const int SingleSfixed32FieldNumber = 9; + private int singleSfixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int SingleSfixed32 { + get { return singleSfixed32_; } + set { + singleSfixed32_ = value; + } + } + + /// Field number for the "single_sfixed64" field. + public const int SingleSfixed64FieldNumber = 10; + private long singleSfixed64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long SingleSfixed64 { + get { return singleSfixed64_; } + set { + singleSfixed64_ = value; + } + } + + /// Field number for the "single_float" field. + public const int SingleFloatFieldNumber = 11; + private float singleFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float SingleFloat { + get { return singleFloat_; } + set { + singleFloat_ = value; + } + } + + /// Field number for the "single_double" field. + public const int SingleDoubleFieldNumber = 12; + private double singleDouble_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double SingleDouble { + get { return singleDouble_; } + set { + singleDouble_ = value; + } + } + + /// Field number for the "single_bool" field. + public const int SingleBoolFieldNumber = 13; + private bool singleBool_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool SingleBool { + get { return singleBool_; } + set { + singleBool_ = value; + } + } + + /// Field number for the "single_string" field. + public const int SingleStringFieldNumber = 14; + private string singleString_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string SingleString { + get { return singleString_; } + set { + singleString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "single_bytes" field. + public const int SingleBytesFieldNumber = 15; + private pb::ByteString singleBytes_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString SingleBytes { + get { return singleBytes_; } + set { + singleBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "single_nested_message" field. + public const int SingleNestedMessageFieldNumber = 18; + private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage singleNestedMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage SingleNestedMessage { + get { return singleNestedMessage_; } + set { + singleNestedMessage_ = value; + } + } + + /// Field number for the "single_foreign_message" field. + public const int SingleForeignMessageFieldNumber = 19; + private global::Google.Protobuf.TestProtos.ForeignMessage singleForeignMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.ForeignMessage SingleForeignMessage { + get { return singleForeignMessage_; } + set { + singleForeignMessage_ = value; + } + } + + /// Field number for the "single_import_message" field. + public const int SingleImportMessageFieldNumber = 20; + private global::Google.Protobuf.TestProtos.ImportMessage singleImportMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.ImportMessage SingleImportMessage { + get { return singleImportMessage_; } + set { + singleImportMessage_ = value; + } + } + + /// Field number for the "single_nested_enum" field. + public const int SingleNestedEnumFieldNumber = 21; + private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum singleNestedEnum_ = global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.Unspecified; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum SingleNestedEnum { + get { return singleNestedEnum_; } + set { + singleNestedEnum_ = value; + } + } + + /// Field number for the "single_foreign_enum" field. + public const int SingleForeignEnumFieldNumber = 22; + private global::Google.Protobuf.TestProtos.ForeignEnum singleForeignEnum_ = global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.ForeignEnum SingleForeignEnum { + get { return singleForeignEnum_; } + set { + singleForeignEnum_ = value; + } + } + + /// Field number for the "single_import_enum" field. + public const int SingleImportEnumFieldNumber = 23; + private global::Google.Protobuf.TestProtos.ImportEnum singleImportEnum_ = global::Google.Protobuf.TestProtos.ImportEnum.Unspecified; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.ImportEnum SingleImportEnum { + get { return singleImportEnum_; } + set { + singleImportEnum_ = value; + } + } + + /// Field number for the "single_public_import_message" field. + public const int SinglePublicImportMessageFieldNumber = 26; + private global::Google.Protobuf.TestProtos.PublicImportMessage singlePublicImportMessage_; + /// + /// Defined in unittest_import_public.proto + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.PublicImportMessage SinglePublicImportMessage { + get { return singlePublicImportMessage_; } + set { + singlePublicImportMessage_ = value; + } + } + + /// Field number for the "repeated_int32" field. + public const int RepeatedInt32FieldNumber = 31; + private static readonly pb::FieldCodec _repeated_repeatedInt32_codec + = pb::FieldCodec.ForInt32(250); + private readonly pbc::RepeatedField repeatedInt32_ = new pbc::RepeatedField(); + /// + /// Repeated + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt32 { + get { return repeatedInt32_; } + } + + /// Field number for the "repeated_int64" field. + public const int RepeatedInt64FieldNumber = 32; + private static readonly pb::FieldCodec _repeated_repeatedInt64_codec + = pb::FieldCodec.ForInt64(258); + private readonly pbc::RepeatedField repeatedInt64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt64 { + get { return repeatedInt64_; } + } + + /// Field number for the "repeated_uint32" field. + public const int RepeatedUint32FieldNumber = 33; + private static readonly pb::FieldCodec _repeated_repeatedUint32_codec + = pb::FieldCodec.ForUInt32(266); + private readonly pbc::RepeatedField repeatedUint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedUint32 { + get { return repeatedUint32_; } + } + + /// Field number for the "repeated_uint64" field. + public const int RepeatedUint64FieldNumber = 34; + private static readonly pb::FieldCodec _repeated_repeatedUint64_codec + = pb::FieldCodec.ForUInt64(274); + private readonly pbc::RepeatedField repeatedUint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedUint64 { + get { return repeatedUint64_; } + } + + /// Field number for the "repeated_sint32" field. + public const int RepeatedSint32FieldNumber = 35; + private static readonly pb::FieldCodec _repeated_repeatedSint32_codec + = pb::FieldCodec.ForSInt32(282); + private readonly pbc::RepeatedField repeatedSint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSint32 { + get { return repeatedSint32_; } + } + + /// Field number for the "repeated_sint64" field. + public const int RepeatedSint64FieldNumber = 36; + private static readonly pb::FieldCodec _repeated_repeatedSint64_codec + = pb::FieldCodec.ForSInt64(290); + private readonly pbc::RepeatedField repeatedSint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSint64 { + get { return repeatedSint64_; } + } + + /// Field number for the "repeated_fixed32" field. + public const int RepeatedFixed32FieldNumber = 37; + private static readonly pb::FieldCodec _repeated_repeatedFixed32_codec + = pb::FieldCodec.ForFixed32(298); + private readonly pbc::RepeatedField repeatedFixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFixed32 { + get { return repeatedFixed32_; } + } + + /// Field number for the "repeated_fixed64" field. + public const int RepeatedFixed64FieldNumber = 38; + private static readonly pb::FieldCodec _repeated_repeatedFixed64_codec + = pb::FieldCodec.ForFixed64(306); + private readonly pbc::RepeatedField repeatedFixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFixed64 { + get { return repeatedFixed64_; } + } + + /// Field number for the "repeated_sfixed32" field. + public const int RepeatedSfixed32FieldNumber = 39; + private static readonly pb::FieldCodec _repeated_repeatedSfixed32_codec + = pb::FieldCodec.ForSFixed32(314); + private readonly pbc::RepeatedField repeatedSfixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSfixed32 { + get { return repeatedSfixed32_; } + } + + /// Field number for the "repeated_sfixed64" field. + public const int RepeatedSfixed64FieldNumber = 40; + private static readonly pb::FieldCodec _repeated_repeatedSfixed64_codec + = pb::FieldCodec.ForSFixed64(322); + private readonly pbc::RepeatedField repeatedSfixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedSfixed64 { + get { return repeatedSfixed64_; } + } + + /// Field number for the "repeated_float" field. + public const int RepeatedFloatFieldNumber = 41; + private static readonly pb::FieldCodec _repeated_repeatedFloat_codec + = pb::FieldCodec.ForFloat(330); + private readonly pbc::RepeatedField repeatedFloat_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFloat { + get { return repeatedFloat_; } + } + + /// Field number for the "repeated_double" field. + public const int RepeatedDoubleFieldNumber = 42; + private static readonly pb::FieldCodec _repeated_repeatedDouble_codec + = pb::FieldCodec.ForDouble(338); + private readonly pbc::RepeatedField repeatedDouble_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedDouble { + get { return repeatedDouble_; } + } + + /// Field number for the "repeated_bool" field. + public const int RepeatedBoolFieldNumber = 43; + private static readonly pb::FieldCodec _repeated_repeatedBool_codec + = pb::FieldCodec.ForBool(346); + private readonly pbc::RepeatedField repeatedBool_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedBool { + get { return repeatedBool_; } + } + + /// Field number for the "repeated_string" field. + public const int RepeatedStringFieldNumber = 44; + private static readonly pb::FieldCodec _repeated_repeatedString_codec + = pb::FieldCodec.ForString(354); + private readonly pbc::RepeatedField repeatedString_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedString { + get { return repeatedString_; } + } + + /// Field number for the "repeated_bytes" field. + public const int RepeatedBytesFieldNumber = 45; + private static readonly pb::FieldCodec _repeated_repeatedBytes_codec + = pb::FieldCodec.ForBytes(362); + private readonly pbc::RepeatedField repeatedBytes_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedBytes { + get { return repeatedBytes_; } + } + + /// Field number for the "repeated_nested_message" field. + public const int RepeatedNestedMessageFieldNumber = 48; + private static readonly pb::FieldCodec _repeated_repeatedNestedMessage_codec + = pb::FieldCodec.ForMessage(386, global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage.Parser); + private readonly pbc::RepeatedField repeatedNestedMessage_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedNestedMessage { + get { return repeatedNestedMessage_; } + } + + /// Field number for the "repeated_foreign_message" field. + public const int RepeatedForeignMessageFieldNumber = 49; + private static readonly pb::FieldCodec _repeated_repeatedForeignMessage_codec + = pb::FieldCodec.ForMessage(394, global::Google.Protobuf.TestProtos.ForeignMessage.Parser); + private readonly pbc::RepeatedField repeatedForeignMessage_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedForeignMessage { + get { return repeatedForeignMessage_; } + } + + /// Field number for the "repeated_import_message" field. + public const int RepeatedImportMessageFieldNumber = 50; + private static readonly pb::FieldCodec _repeated_repeatedImportMessage_codec + = pb::FieldCodec.ForMessage(402, global::Google.Protobuf.TestProtos.ImportMessage.Parser); + private readonly pbc::RepeatedField repeatedImportMessage_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedImportMessage { + get { return repeatedImportMessage_; } + } + + /// Field number for the "repeated_nested_enum" field. + public const int RepeatedNestedEnumFieldNumber = 51; + private static readonly pb::FieldCodec _repeated_repeatedNestedEnum_codec + = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) x); + private readonly pbc::RepeatedField repeatedNestedEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedNestedEnum { + get { return repeatedNestedEnum_; } + } + + /// Field number for the "repeated_foreign_enum" field. + public const int RepeatedForeignEnumFieldNumber = 52; + private static readonly pb::FieldCodec _repeated_repeatedForeignEnum_codec + = pb::FieldCodec.ForEnum(418, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x); + private readonly pbc::RepeatedField repeatedForeignEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedForeignEnum { + get { return repeatedForeignEnum_; } + } + + /// Field number for the "repeated_import_enum" field. + public const int RepeatedImportEnumFieldNumber = 53; + private static readonly pb::FieldCodec _repeated_repeatedImportEnum_codec + = pb::FieldCodec.ForEnum(426, x => (int) x, x => (global::Google.Protobuf.TestProtos.ImportEnum) x); + private readonly pbc::RepeatedField repeatedImportEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedImportEnum { + get { return repeatedImportEnum_; } + } + + /// Field number for the "repeated_public_import_message" field. + public const int RepeatedPublicImportMessageFieldNumber = 54; + private static readonly pb::FieldCodec _repeated_repeatedPublicImportMessage_codec + = pb::FieldCodec.ForMessage(434, global::Google.Protobuf.TestProtos.PublicImportMessage.Parser); + private readonly pbc::RepeatedField repeatedPublicImportMessage_ = new pbc::RepeatedField(); + /// + /// Defined in unittest_import_public.proto + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedPublicImportMessage { + get { return repeatedPublicImportMessage_; } + } + + /// Field number for the "oneof_uint32" field. + public const int OneofUint32FieldNumber = 111; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OneofUint32 { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; + } + } + + /// Field number for the "oneof_nested_message" field. + public const int OneofNestedMessageFieldNumber = 112; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage OneofNestedMessage { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage) oneofField_ : null; } + set { + oneofField_ = value; + oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage; + } + } + + /// Field number for the "oneof_string" field. + public const int OneofStringFieldNumber = 113; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OneofString { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; } + set { + oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + oneofFieldCase_ = OneofFieldOneofCase.OneofString; + } + } + + /// Field number for the "oneof_bytes" field. + public const int OneofBytesFieldNumber = 114; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString OneofBytes { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; } + set { + oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; + } + } + + private object oneofField_; + /// Enum of possible cases for the "oneof_field" oneof. + public enum OneofFieldOneofCase { + None = 0, + OneofUint32 = 111, + OneofNestedMessage = 112, + OneofString = 113, + OneofBytes = 114, + } + private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneofFieldOneofCase OneofFieldCase { + get { return oneofFieldCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofField() { + oneofFieldCase_ = OneofFieldOneofCase.None; + oneofField_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestAllTypes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestAllTypes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (SingleInt32 != other.SingleInt32) return false; + if (SingleInt64 != other.SingleInt64) return false; + if (SingleUint32 != other.SingleUint32) return false; + if (SingleUint64 != other.SingleUint64) return false; + if (SingleSint32 != other.SingleSint32) return false; + if (SingleSint64 != other.SingleSint64) return false; + if (SingleFixed32 != other.SingleFixed32) return false; + if (SingleFixed64 != other.SingleFixed64) return false; + if (SingleSfixed32 != other.SingleSfixed32) return false; + if (SingleSfixed64 != other.SingleSfixed64) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(SingleFloat, other.SingleFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(SingleDouble, other.SingleDouble)) return false; + if (SingleBool != other.SingleBool) return false; + if (SingleString != other.SingleString) return false; + if (SingleBytes != other.SingleBytes) return false; + if (!object.Equals(SingleNestedMessage, other.SingleNestedMessage)) return false; + if (!object.Equals(SingleForeignMessage, other.SingleForeignMessage)) return false; + if (!object.Equals(SingleImportMessage, other.SingleImportMessage)) return false; + if (SingleNestedEnum != other.SingleNestedEnum) return false; + if (SingleForeignEnum != other.SingleForeignEnum) return false; + if (SingleImportEnum != other.SingleImportEnum) return false; + if (!object.Equals(SinglePublicImportMessage, other.SinglePublicImportMessage)) return false; + if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false; + if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false; + if(!repeatedUint32_.Equals(other.repeatedUint32_)) return false; + if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false; + if(!repeatedSint32_.Equals(other.repeatedSint32_)) return false; + if(!repeatedSint64_.Equals(other.repeatedSint64_)) return false; + if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false; + if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false; + if(!repeatedSfixed32_.Equals(other.repeatedSfixed32_)) return false; + if(!repeatedSfixed64_.Equals(other.repeatedSfixed64_)) return false; + if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false; + if(!repeatedDouble_.Equals(other.repeatedDouble_)) return false; + if(!repeatedBool_.Equals(other.repeatedBool_)) return false; + if(!repeatedString_.Equals(other.repeatedString_)) return false; + if(!repeatedBytes_.Equals(other.repeatedBytes_)) return false; + if(!repeatedNestedMessage_.Equals(other.repeatedNestedMessage_)) return false; + if(!repeatedForeignMessage_.Equals(other.repeatedForeignMessage_)) return false; + if(!repeatedImportMessage_.Equals(other.repeatedImportMessage_)) return false; + if(!repeatedNestedEnum_.Equals(other.repeatedNestedEnum_)) return false; + if(!repeatedForeignEnum_.Equals(other.repeatedForeignEnum_)) return false; + if(!repeatedImportEnum_.Equals(other.repeatedImportEnum_)) return false; + if(!repeatedPublicImportMessage_.Equals(other.repeatedPublicImportMessage_)) return false; + if (OneofUint32 != other.OneofUint32) return false; + if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false; + if (OneofString != other.OneofString) return false; + if (OneofBytes != other.OneofBytes) return false; + if (OneofFieldCase != other.OneofFieldCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (SingleInt32 != 0) hash ^= SingleInt32.GetHashCode(); + if (SingleInt64 != 0L) hash ^= SingleInt64.GetHashCode(); + if (SingleUint32 != 0) hash ^= SingleUint32.GetHashCode(); + if (SingleUint64 != 0UL) hash ^= SingleUint64.GetHashCode(); + if (SingleSint32 != 0) hash ^= SingleSint32.GetHashCode(); + if (SingleSint64 != 0L) hash ^= SingleSint64.GetHashCode(); + if (SingleFixed32 != 0) hash ^= SingleFixed32.GetHashCode(); + if (SingleFixed64 != 0UL) hash ^= SingleFixed64.GetHashCode(); + if (SingleSfixed32 != 0) hash ^= SingleSfixed32.GetHashCode(); + if (SingleSfixed64 != 0L) hash ^= SingleSfixed64.GetHashCode(); + if (SingleFloat != 0F) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(SingleFloat); + if (SingleDouble != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(SingleDouble); + if (SingleBool != false) hash ^= SingleBool.GetHashCode(); + if (SingleString.Length != 0) hash ^= SingleString.GetHashCode(); + if (SingleBytes.Length != 0) hash ^= SingleBytes.GetHashCode(); + if (singleNestedMessage_ != null) hash ^= SingleNestedMessage.GetHashCode(); + if (singleForeignMessage_ != null) hash ^= SingleForeignMessage.GetHashCode(); + if (singleImportMessage_ != null) hash ^= SingleImportMessage.GetHashCode(); + if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.Unspecified) hash ^= SingleNestedEnum.GetHashCode(); + if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified) hash ^= SingleForeignEnum.GetHashCode(); + if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.Unspecified) hash ^= SingleImportEnum.GetHashCode(); + if (singlePublicImportMessage_ != null) hash ^= SinglePublicImportMessage.GetHashCode(); + hash ^= repeatedInt32_.GetHashCode(); + hash ^= repeatedInt64_.GetHashCode(); + hash ^= repeatedUint32_.GetHashCode(); + hash ^= repeatedUint64_.GetHashCode(); + hash ^= repeatedSint32_.GetHashCode(); + hash ^= repeatedSint64_.GetHashCode(); + hash ^= repeatedFixed32_.GetHashCode(); + hash ^= repeatedFixed64_.GetHashCode(); + hash ^= repeatedSfixed32_.GetHashCode(); + hash ^= repeatedSfixed64_.GetHashCode(); + hash ^= repeatedFloat_.GetHashCode(); + hash ^= repeatedDouble_.GetHashCode(); + hash ^= repeatedBool_.GetHashCode(); + hash ^= repeatedString_.GetHashCode(); + hash ^= repeatedBytes_.GetHashCode(); + hash ^= repeatedNestedMessage_.GetHashCode(); + hash ^= repeatedForeignMessage_.GetHashCode(); + hash ^= repeatedImportMessage_.GetHashCode(); + hash ^= repeatedNestedEnum_.GetHashCode(); + hash ^= repeatedForeignEnum_.GetHashCode(); + hash ^= repeatedImportEnum_.GetHashCode(); + hash ^= repeatedPublicImportMessage_.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) hash ^= OneofUint32.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) hash ^= OneofString.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) hash ^= OneofBytes.GetHashCode(); + hash ^= (int) oneofFieldCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (SingleInt32 != 0) { + output.WriteRawTag(8); + output.WriteInt32(SingleInt32); + } + if (SingleInt64 != 0L) { + output.WriteRawTag(16); + output.WriteInt64(SingleInt64); + } + if (SingleUint32 != 0) { + output.WriteRawTag(24); + output.WriteUInt32(SingleUint32); + } + if (SingleUint64 != 0UL) { + output.WriteRawTag(32); + output.WriteUInt64(SingleUint64); + } + if (SingleSint32 != 0) { + output.WriteRawTag(40); + output.WriteSInt32(SingleSint32); + } + if (SingleSint64 != 0L) { + output.WriteRawTag(48); + output.WriteSInt64(SingleSint64); + } + if (SingleFixed32 != 0) { + output.WriteRawTag(61); + output.WriteFixed32(SingleFixed32); + } + if (SingleFixed64 != 0UL) { + output.WriteRawTag(65); + output.WriteFixed64(SingleFixed64); + } + if (SingleSfixed32 != 0) { + output.WriteRawTag(77); + output.WriteSFixed32(SingleSfixed32); + } + if (SingleSfixed64 != 0L) { + output.WriteRawTag(81); + output.WriteSFixed64(SingleSfixed64); + } + if (SingleFloat != 0F) { + output.WriteRawTag(93); + output.WriteFloat(SingleFloat); + } + if (SingleDouble != 0D) { + output.WriteRawTag(97); + output.WriteDouble(SingleDouble); + } + if (SingleBool != false) { + output.WriteRawTag(104); + output.WriteBool(SingleBool); + } + if (SingleString.Length != 0) { + output.WriteRawTag(114); + output.WriteString(SingleString); + } + if (SingleBytes.Length != 0) { + output.WriteRawTag(122); + output.WriteBytes(SingleBytes); + } + if (singleNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(SingleNestedMessage); + } + if (singleForeignMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(SingleForeignMessage); + } + if (singleImportMessage_ != null) { + output.WriteRawTag(162, 1); + output.WriteMessage(SingleImportMessage); + } + if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.Unspecified) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) SingleNestedEnum); + } + if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) SingleForeignEnum); + } + if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.Unspecified) { + output.WriteRawTag(184, 1); + output.WriteEnum((int) SingleImportEnum); + } + if (singlePublicImportMessage_ != null) { + output.WriteRawTag(210, 1); + output.WriteMessage(SinglePublicImportMessage); + } + repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec); + repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec); + repeatedUint32_.WriteTo(output, _repeated_repeatedUint32_codec); + repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec); + repeatedSint32_.WriteTo(output, _repeated_repeatedSint32_codec); + repeatedSint64_.WriteTo(output, _repeated_repeatedSint64_codec); + repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec); + repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec); + repeatedSfixed32_.WriteTo(output, _repeated_repeatedSfixed32_codec); + repeatedSfixed64_.WriteTo(output, _repeated_repeatedSfixed64_codec); + repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec); + repeatedDouble_.WriteTo(output, _repeated_repeatedDouble_codec); + repeatedBool_.WriteTo(output, _repeated_repeatedBool_codec); + repeatedString_.WriteTo(output, _repeated_repeatedString_codec); + repeatedBytes_.WriteTo(output, _repeated_repeatedBytes_codec); + repeatedNestedMessage_.WriteTo(output, _repeated_repeatedNestedMessage_codec); + repeatedForeignMessage_.WriteTo(output, _repeated_repeatedForeignMessage_codec); + repeatedImportMessage_.WriteTo(output, _repeated_repeatedImportMessage_codec); + repeatedNestedEnum_.WriteTo(output, _repeated_repeatedNestedEnum_codec); + repeatedForeignEnum_.WriteTo(output, _repeated_repeatedForeignEnum_codec); + repeatedImportEnum_.WriteTo(output, _repeated_repeatedImportEnum_codec); + repeatedPublicImportMessage_.WriteTo(output, _repeated_repeatedPublicImportMessage_codec); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { + output.WriteRawTag(248, 6); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + output.WriteRawTag(130, 7); + output.WriteMessage(OneofNestedMessage); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { + output.WriteRawTag(138, 7); + output.WriteString(OneofString); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { + output.WriteRawTag(146, 7); + output.WriteBytes(OneofBytes); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (SingleInt32 != 0) { + output.WriteRawTag(8); + output.WriteInt32(SingleInt32); + } + if (SingleInt64 != 0L) { + output.WriteRawTag(16); + output.WriteInt64(SingleInt64); + } + if (SingleUint32 != 0) { + output.WriteRawTag(24); + output.WriteUInt32(SingleUint32); + } + if (SingleUint64 != 0UL) { + output.WriteRawTag(32); + output.WriteUInt64(SingleUint64); + } + if (SingleSint32 != 0) { + output.WriteRawTag(40); + output.WriteSInt32(SingleSint32); + } + if (SingleSint64 != 0L) { + output.WriteRawTag(48); + output.WriteSInt64(SingleSint64); + } + if (SingleFixed32 != 0) { + output.WriteRawTag(61); + output.WriteFixed32(SingleFixed32); + } + if (SingleFixed64 != 0UL) { + output.WriteRawTag(65); + output.WriteFixed64(SingleFixed64); + } + if (SingleSfixed32 != 0) { + output.WriteRawTag(77); + output.WriteSFixed32(SingleSfixed32); + } + if (SingleSfixed64 != 0L) { + output.WriteRawTag(81); + output.WriteSFixed64(SingleSfixed64); + } + if (SingleFloat != 0F) { + output.WriteRawTag(93); + output.WriteFloat(SingleFloat); + } + if (SingleDouble != 0D) { + output.WriteRawTag(97); + output.WriteDouble(SingleDouble); + } + if (SingleBool != false) { + output.WriteRawTag(104); + output.WriteBool(SingleBool); + } + if (SingleString.Length != 0) { + output.WriteRawTag(114); + output.WriteString(SingleString); + } + if (SingleBytes.Length != 0) { + output.WriteRawTag(122); + output.WriteBytes(SingleBytes); + } + if (singleNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(SingleNestedMessage); + } + if (singleForeignMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(SingleForeignMessage); + } + if (singleImportMessage_ != null) { + output.WriteRawTag(162, 1); + output.WriteMessage(SingleImportMessage); + } + if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.Unspecified) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) SingleNestedEnum); + } + if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) SingleForeignEnum); + } + if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.Unspecified) { + output.WriteRawTag(184, 1); + output.WriteEnum((int) SingleImportEnum); + } + if (singlePublicImportMessage_ != null) { + output.WriteRawTag(210, 1); + output.WriteMessage(SinglePublicImportMessage); + } + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec); + repeatedUint32_.WriteTo(ref output, _repeated_repeatedUint32_codec); + repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec); + repeatedSint32_.WriteTo(ref output, _repeated_repeatedSint32_codec); + repeatedSint64_.WriteTo(ref output, _repeated_repeatedSint64_codec); + repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec); + repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec); + repeatedSfixed32_.WriteTo(ref output, _repeated_repeatedSfixed32_codec); + repeatedSfixed64_.WriteTo(ref output, _repeated_repeatedSfixed64_codec); + repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec); + repeatedDouble_.WriteTo(ref output, _repeated_repeatedDouble_codec); + repeatedBool_.WriteTo(ref output, _repeated_repeatedBool_codec); + repeatedString_.WriteTo(ref output, _repeated_repeatedString_codec); + repeatedBytes_.WriteTo(ref output, _repeated_repeatedBytes_codec); + repeatedNestedMessage_.WriteTo(ref output, _repeated_repeatedNestedMessage_codec); + repeatedForeignMessage_.WriteTo(ref output, _repeated_repeatedForeignMessage_codec); + repeatedImportMessage_.WriteTo(ref output, _repeated_repeatedImportMessage_codec); + repeatedNestedEnum_.WriteTo(ref output, _repeated_repeatedNestedEnum_codec); + repeatedForeignEnum_.WriteTo(ref output, _repeated_repeatedForeignEnum_codec); + repeatedImportEnum_.WriteTo(ref output, _repeated_repeatedImportEnum_codec); + repeatedPublicImportMessage_.WriteTo(ref output, _repeated_repeatedPublicImportMessage_codec); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { + output.WriteRawTag(248, 6); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + output.WriteRawTag(130, 7); + output.WriteMessage(OneofNestedMessage); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { + output.WriteRawTag(138, 7); + output.WriteString(OneofString); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { + output.WriteRawTag(146, 7); + output.WriteBytes(OneofBytes); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (SingleInt32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(SingleInt32); + } + if (SingleInt64 != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(SingleInt64); + } + if (SingleUint32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(SingleUint32); + } + if (SingleUint64 != 0UL) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(SingleUint64); + } + if (SingleSint32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeSInt32Size(SingleSint32); + } + if (SingleSint64 != 0L) { + size += 1 + pb::CodedOutputStream.ComputeSInt64Size(SingleSint64); + } + if (SingleFixed32 != 0) { + size += 1 + 4; + } + if (SingleFixed64 != 0UL) { + size += 1 + 8; + } + if (SingleSfixed32 != 0) { + size += 1 + 4; + } + if (SingleSfixed64 != 0L) { + size += 1 + 8; + } + if (SingleFloat != 0F) { + size += 1 + 4; + } + if (SingleDouble != 0D) { + size += 1 + 8; + } + if (SingleBool != false) { + size += 1 + 1; + } + if (SingleString.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(SingleString); + } + if (SingleBytes.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(SingleBytes); + } + if (singleNestedMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleNestedMessage); + } + if (singleForeignMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleForeignMessage); + } + if (singleImportMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleImportMessage); + } + if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.Unspecified) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleNestedEnum); + } + if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleForeignEnum); + } + if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.Unspecified) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleImportEnum); + } + if (singlePublicImportMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(SinglePublicImportMessage); + } + size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec); + size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec); + size += repeatedUint32_.CalculateSize(_repeated_repeatedUint32_codec); + size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec); + size += repeatedSint32_.CalculateSize(_repeated_repeatedSint32_codec); + size += repeatedSint64_.CalculateSize(_repeated_repeatedSint64_codec); + size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec); + size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec); + size += repeatedSfixed32_.CalculateSize(_repeated_repeatedSfixed32_codec); + size += repeatedSfixed64_.CalculateSize(_repeated_repeatedSfixed64_codec); + size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec); + size += repeatedDouble_.CalculateSize(_repeated_repeatedDouble_codec); + size += repeatedBool_.CalculateSize(_repeated_repeatedBool_codec); + size += repeatedString_.CalculateSize(_repeated_repeatedString_codec); + size += repeatedBytes_.CalculateSize(_repeated_repeatedBytes_codec); + size += repeatedNestedMessage_.CalculateSize(_repeated_repeatedNestedMessage_codec); + size += repeatedForeignMessage_.CalculateSize(_repeated_repeatedForeignMessage_codec); + size += repeatedImportMessage_.CalculateSize(_repeated_repeatedImportMessage_codec); + size += repeatedNestedEnum_.CalculateSize(_repeated_repeatedNestedEnum_codec); + size += repeatedForeignEnum_.CalculateSize(_repeated_repeatedForeignEnum_codec); + size += repeatedImportEnum_.CalculateSize(_repeated_repeatedImportEnum_codec); + size += repeatedPublicImportMessage_.CalculateSize(_repeated_repeatedPublicImportMessage_codec); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { + size += 2 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OneofNestedMessage); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OneofString); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { + size += 2 + pb::CodedOutputStream.ComputeBytesSize(OneofBytes); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestAllTypes other) { + if (other == null) { + return; + } + if (other.SingleInt32 != 0) { + SingleInt32 = other.SingleInt32; + } + if (other.SingleInt64 != 0L) { + SingleInt64 = other.SingleInt64; + } + if (other.SingleUint32 != 0) { + SingleUint32 = other.SingleUint32; + } + if (other.SingleUint64 != 0UL) { + SingleUint64 = other.SingleUint64; + } + if (other.SingleSint32 != 0) { + SingleSint32 = other.SingleSint32; + } + if (other.SingleSint64 != 0L) { + SingleSint64 = other.SingleSint64; + } + if (other.SingleFixed32 != 0) { + SingleFixed32 = other.SingleFixed32; + } + if (other.SingleFixed64 != 0UL) { + SingleFixed64 = other.SingleFixed64; + } + if (other.SingleSfixed32 != 0) { + SingleSfixed32 = other.SingleSfixed32; + } + if (other.SingleSfixed64 != 0L) { + SingleSfixed64 = other.SingleSfixed64; + } + if (other.SingleFloat != 0F) { + SingleFloat = other.SingleFloat; + } + if (other.SingleDouble != 0D) { + SingleDouble = other.SingleDouble; + } + if (other.SingleBool != false) { + SingleBool = other.SingleBool; + } + if (other.SingleString.Length != 0) { + SingleString = other.SingleString; + } + if (other.SingleBytes.Length != 0) { + SingleBytes = other.SingleBytes; + } + if (other.singleNestedMessage_ != null) { + if (singleNestedMessage_ == null) { + SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage(); + } + SingleNestedMessage.MergeFrom(other.SingleNestedMessage); + } + if (other.singleForeignMessage_ != null) { + if (singleForeignMessage_ == null) { + SingleForeignMessage = new global::Google.Protobuf.TestProtos.ForeignMessage(); + } + SingleForeignMessage.MergeFrom(other.SingleForeignMessage); + } + if (other.singleImportMessage_ != null) { + if (singleImportMessage_ == null) { + SingleImportMessage = new global::Google.Protobuf.TestProtos.ImportMessage(); + } + SingleImportMessage.MergeFrom(other.SingleImportMessage); + } + if (other.SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.Unspecified) { + SingleNestedEnum = other.SingleNestedEnum; + } + if (other.SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified) { + SingleForeignEnum = other.SingleForeignEnum; + } + if (other.SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.Unspecified) { + SingleImportEnum = other.SingleImportEnum; + } + if (other.singlePublicImportMessage_ != null) { + if (singlePublicImportMessage_ == null) { + SinglePublicImportMessage = new global::Google.Protobuf.TestProtos.PublicImportMessage(); + } + SinglePublicImportMessage.MergeFrom(other.SinglePublicImportMessage); + } + repeatedInt32_.Add(other.repeatedInt32_); + repeatedInt64_.Add(other.repeatedInt64_); + repeatedUint32_.Add(other.repeatedUint32_); + repeatedUint64_.Add(other.repeatedUint64_); + repeatedSint32_.Add(other.repeatedSint32_); + repeatedSint64_.Add(other.repeatedSint64_); + repeatedFixed32_.Add(other.repeatedFixed32_); + repeatedFixed64_.Add(other.repeatedFixed64_); + repeatedSfixed32_.Add(other.repeatedSfixed32_); + repeatedSfixed64_.Add(other.repeatedSfixed64_); + repeatedFloat_.Add(other.repeatedFloat_); + repeatedDouble_.Add(other.repeatedDouble_); + repeatedBool_.Add(other.repeatedBool_); + repeatedString_.Add(other.repeatedString_); + repeatedBytes_.Add(other.repeatedBytes_); + repeatedNestedMessage_.Add(other.repeatedNestedMessage_); + repeatedForeignMessage_.Add(other.repeatedForeignMessage_); + repeatedImportMessage_.Add(other.repeatedImportMessage_); + repeatedNestedEnum_.Add(other.repeatedNestedEnum_); + repeatedForeignEnum_.Add(other.repeatedForeignEnum_); + repeatedImportEnum_.Add(other.repeatedImportEnum_); + repeatedPublicImportMessage_.Add(other.repeatedPublicImportMessage_); + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: + OneofUint32 = other.OneofUint32; + break; + case OneofFieldOneofCase.OneofNestedMessage: + if (OneofNestedMessage == null) { + OneofNestedMessage = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage(); + } + OneofNestedMessage.MergeFrom(other.OneofNestedMessage); + break; + case OneofFieldOneofCase.OneofString: + OneofString = other.OneofString; + break; + case OneofFieldOneofCase.OneofBytes: + OneofBytes = other.OneofBytes; + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + SingleInt32 = input.ReadInt32(); + break; + } + case 16: { + SingleInt64 = input.ReadInt64(); + break; + } + case 24: { + SingleUint32 = input.ReadUInt32(); + break; + } + case 32: { + SingleUint64 = input.ReadUInt64(); + break; + } + case 40: { + SingleSint32 = input.ReadSInt32(); + break; + } + case 48: { + SingleSint64 = input.ReadSInt64(); + break; + } + case 61: { + SingleFixed32 = input.ReadFixed32(); + break; + } + case 65: { + SingleFixed64 = input.ReadFixed64(); + break; + } + case 77: { + SingleSfixed32 = input.ReadSFixed32(); + break; + } + case 81: { + SingleSfixed64 = input.ReadSFixed64(); + break; + } + case 93: { + SingleFloat = input.ReadFloat(); + break; + } + case 97: { + SingleDouble = input.ReadDouble(); + break; + } + case 104: { + SingleBool = input.ReadBool(); + break; + } + case 114: { + SingleString = input.ReadString(); + break; + } + case 122: { + SingleBytes = input.ReadBytes(); + break; + } + case 146: { + if (singleNestedMessage_ == null) { + SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage(); + } + input.ReadMessage(SingleNestedMessage); + break; + } + case 154: { + if (singleForeignMessage_ == null) { + SingleForeignMessage = new global::Google.Protobuf.TestProtos.ForeignMessage(); + } + input.ReadMessage(SingleForeignMessage); + break; + } + case 162: { + if (singleImportMessage_ == null) { + SingleImportMessage = new global::Google.Protobuf.TestProtos.ImportMessage(); + } + input.ReadMessage(SingleImportMessage); + break; + } + case 168: { + SingleNestedEnum = (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) input.ReadEnum(); + break; + } + case 176: { + SingleForeignEnum = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum(); + break; + } + case 184: { + SingleImportEnum = (global::Google.Protobuf.TestProtos.ImportEnum) input.ReadEnum(); + break; + } + case 210: { + if (singlePublicImportMessage_ == null) { + SinglePublicImportMessage = new global::Google.Protobuf.TestProtos.PublicImportMessage(); + } + input.ReadMessage(SinglePublicImportMessage); + break; + } + case 250: + case 248: { + repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); + break; + } + case 258: + case 256: { + repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec); + break; + } + case 266: + case 264: { + repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec); + break; + } + case 274: + case 272: { + repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec); + break; + } + case 282: + case 280: { + repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec); + break; + } + case 290: + case 288: { + repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec); + break; + } + case 298: + case 301: { + repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec); + break; + } + case 306: + case 305: { + repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec); + break; + } + case 314: + case 317: { + repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec); + break; + } + case 322: + case 321: { + repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec); + break; + } + case 330: + case 333: { + repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec); + break; + } + case 338: + case 337: { + repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec); + break; + } + case 346: + case 344: { + repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec); + break; + } + case 354: { + repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec); + break; + } + case 362: { + repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec); + break; + } + case 386: { + repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec); + break; + } + case 394: { + repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec); + break; + } + case 402: { + repeatedImportMessage_.AddEntriesFrom(input, _repeated_repeatedImportMessage_codec); + break; + } + case 410: + case 408: { + repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec); + break; + } + case 418: + case 416: { + repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec); + break; + } + case 426: + case 424: { + repeatedImportEnum_.AddEntriesFrom(input, _repeated_repeatedImportEnum_codec); + break; + } + case 434: { + repeatedPublicImportMessage_.AddEntriesFrom(input, _repeated_repeatedPublicImportMessage_codec); + break; + } + case 888: { + OneofUint32 = input.ReadUInt32(); + break; + } + case 898: { + global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + subBuilder.MergeFrom(OneofNestedMessage); + } + input.ReadMessage(subBuilder); + OneofNestedMessage = subBuilder; + break; + } + case 906: { + OneofString = input.ReadString(); + break; + } + case 914: { + OneofBytes = input.ReadBytes(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + SingleInt32 = input.ReadInt32(); + break; + } + case 16: { + SingleInt64 = input.ReadInt64(); + break; + } + case 24: { + SingleUint32 = input.ReadUInt32(); + break; + } + case 32: { + SingleUint64 = input.ReadUInt64(); + break; + } + case 40: { + SingleSint32 = input.ReadSInt32(); + break; + } + case 48: { + SingleSint64 = input.ReadSInt64(); + break; + } + case 61: { + SingleFixed32 = input.ReadFixed32(); + break; + } + case 65: { + SingleFixed64 = input.ReadFixed64(); + break; + } + case 77: { + SingleSfixed32 = input.ReadSFixed32(); + break; + } + case 81: { + SingleSfixed64 = input.ReadSFixed64(); + break; + } + case 93: { + SingleFloat = input.ReadFloat(); + break; + } + case 97: { + SingleDouble = input.ReadDouble(); + break; + } + case 104: { + SingleBool = input.ReadBool(); + break; + } + case 114: { + SingleString = input.ReadString(); + break; + } + case 122: { + SingleBytes = input.ReadBytes(); + break; + } + case 146: { + if (singleNestedMessage_ == null) { + SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage(); + } + input.ReadMessage(SingleNestedMessage); + break; + } + case 154: { + if (singleForeignMessage_ == null) { + SingleForeignMessage = new global::Google.Protobuf.TestProtos.ForeignMessage(); + } + input.ReadMessage(SingleForeignMessage); + break; + } + case 162: { + if (singleImportMessage_ == null) { + SingleImportMessage = new global::Google.Protobuf.TestProtos.ImportMessage(); + } + input.ReadMessage(SingleImportMessage); + break; + } + case 168: { + SingleNestedEnum = (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) input.ReadEnum(); + break; + } + case 176: { + SingleForeignEnum = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum(); + break; + } + case 184: { + SingleImportEnum = (global::Google.Protobuf.TestProtos.ImportEnum) input.ReadEnum(); + break; + } + case 210: { + if (singlePublicImportMessage_ == null) { + SinglePublicImportMessage = new global::Google.Protobuf.TestProtos.PublicImportMessage(); + } + input.ReadMessage(SinglePublicImportMessage); + break; + } + case 250: + case 248: { + repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec); + break; + } + case 258: + case 256: { + repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec); + break; + } + case 266: + case 264: { + repeatedUint32_.AddEntriesFrom(ref input, _repeated_repeatedUint32_codec); + break; + } + case 274: + case 272: { + repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec); + break; + } + case 282: + case 280: { + repeatedSint32_.AddEntriesFrom(ref input, _repeated_repeatedSint32_codec); + break; + } + case 290: + case 288: { + repeatedSint64_.AddEntriesFrom(ref input, _repeated_repeatedSint64_codec); + break; + } + case 298: + case 301: { + repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec); + break; + } + case 306: + case 305: { + repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec); + break; + } + case 314: + case 317: { + repeatedSfixed32_.AddEntriesFrom(ref input, _repeated_repeatedSfixed32_codec); + break; + } + case 322: + case 321: { + repeatedSfixed64_.AddEntriesFrom(ref input, _repeated_repeatedSfixed64_codec); + break; + } + case 330: + case 333: { + repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec); + break; + } + case 338: + case 337: { + repeatedDouble_.AddEntriesFrom(ref input, _repeated_repeatedDouble_codec); + break; + } + case 346: + case 344: { + repeatedBool_.AddEntriesFrom(ref input, _repeated_repeatedBool_codec); + break; + } + case 354: { + repeatedString_.AddEntriesFrom(ref input, _repeated_repeatedString_codec); + break; + } + case 362: { + repeatedBytes_.AddEntriesFrom(ref input, _repeated_repeatedBytes_codec); + break; + } + case 386: { + repeatedNestedMessage_.AddEntriesFrom(ref input, _repeated_repeatedNestedMessage_codec); + break; + } + case 394: { + repeatedForeignMessage_.AddEntriesFrom(ref input, _repeated_repeatedForeignMessage_codec); + break; + } + case 402: { + repeatedImportMessage_.AddEntriesFrom(ref input, _repeated_repeatedImportMessage_codec); + break; + } + case 410: + case 408: { + repeatedNestedEnum_.AddEntriesFrom(ref input, _repeated_repeatedNestedEnum_codec); + break; + } + case 418: + case 416: { + repeatedForeignEnum_.AddEntriesFrom(ref input, _repeated_repeatedForeignEnum_codec); + break; + } + case 426: + case 424: { + repeatedImportEnum_.AddEntriesFrom(ref input, _repeated_repeatedImportEnum_codec); + break; + } + case 434: { + repeatedPublicImportMessage_.AddEntriesFrom(ref input, _repeated_repeatedPublicImportMessage_codec); + break; + } + case 888: { + OneofUint32 = input.ReadUInt32(); + break; + } + case 898: { + global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + subBuilder.MergeFrom(OneofNestedMessage); + } + input.ReadMessage(subBuilder); + OneofNestedMessage = subBuilder; + break; + } + case 906: { + OneofString = input.ReadString(); + break; + } + case 914: { + OneofBytes = input.ReadBytes(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestAllTypes message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum NestedEnum { + [pbr::OriginalName("NESTED_ENUM_UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("FOO")] Foo = 1, + [pbr::OriginalName("BAR")] Bar = 2, + [pbr::OriginalName("BAZ")] Baz = 3, + /// + /// Intentionally negative. + /// + [pbr::OriginalName("NEG")] Neg = -1, + } + + public sealed partial class NestedMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.TestAllTypes.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + bb_ = other.bb_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "bb" field. + public const int BbFieldNumber = 1; + private int bb_; + /// + /// The field name "b" fails to compile in proto1 because it conflicts with + /// a local variable named "b" in one of the generated methods. Doh. + /// This file needs to compile in proto1 to test backwards-compatibility. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Bb { + get { return bb_; } + set { + bb_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Bb != other.Bb) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Bb != 0) hash ^= Bb.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Bb != 0) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Bb != 0) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Bb != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Bb); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.Bb != 0) { + Bb = other.Bb; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Bb = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Bb = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + /// + /// This proto includes a recursively nested message. + /// + public sealed partial class NestedTestAllTypes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedTestAllTypes()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedTestAllTypes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedTestAllTypes(NestedTestAllTypes other) : this() { + child_ = other.child_ != null ? other.child_.Clone() : null; + payload_ = other.payload_ != null ? other.payload_.Clone() : null; + repeatedChild_ = other.repeatedChild_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedTestAllTypes Clone() { + return new NestedTestAllTypes(this); + } + + /// Field number for the "child" field. + public const int ChildFieldNumber = 1; + private global::Google.Protobuf.TestProtos.NestedTestAllTypes child_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.NestedTestAllTypes Child { + get { return child_; } + set { + child_ = value; + } + } + + /// Field number for the "payload" field. + public const int PayloadFieldNumber = 2; + private global::Google.Protobuf.TestProtos.TestAllTypes payload_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.TestAllTypes Payload { + get { return payload_; } + set { + payload_ = value; + } + } + + /// Field number for the "repeated_child" field. + public const int RepeatedChildFieldNumber = 3; + private static readonly pb::FieldCodec _repeated_repeatedChild_codec + = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.TestProtos.NestedTestAllTypes.Parser); + private readonly pbc::RepeatedField repeatedChild_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedChild { + get { return repeatedChild_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedTestAllTypes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedTestAllTypes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Child, other.Child)) return false; + if (!object.Equals(Payload, other.Payload)) return false; + if(!repeatedChild_.Equals(other.repeatedChild_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (child_ != null) hash ^= Child.GetHashCode(); + if (payload_ != null) hash ^= Payload.GetHashCode(); + hash ^= repeatedChild_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (child_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Child); + } + if (payload_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Payload); + } + repeatedChild_.WriteTo(output, _repeated_repeatedChild_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (child_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Child); + } + if (payload_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Payload); + } + repeatedChild_.WriteTo(ref output, _repeated_repeatedChild_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (child_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Child); + } + if (payload_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); + } + size += repeatedChild_.CalculateSize(_repeated_repeatedChild_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedTestAllTypes other) { + if (other == null) { + return; + } + if (other.child_ != null) { + if (child_ == null) { + Child = new global::Google.Protobuf.TestProtos.NestedTestAllTypes(); + } + Child.MergeFrom(other.Child); + } + if (other.payload_ != null) { + if (payload_ == null) { + Payload = new global::Google.Protobuf.TestProtos.TestAllTypes(); + } + Payload.MergeFrom(other.Payload); + } + repeatedChild_.Add(other.repeatedChild_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (child_ == null) { + Child = new global::Google.Protobuf.TestProtos.NestedTestAllTypes(); + } + input.ReadMessage(Child); + break; + } + case 18: { + if (payload_ == null) { + Payload = new global::Google.Protobuf.TestProtos.TestAllTypes(); + } + input.ReadMessage(Payload); + break; + } + case 26: { + repeatedChild_.AddEntriesFrom(input, _repeated_repeatedChild_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (child_ == null) { + Child = new global::Google.Protobuf.TestProtos.NestedTestAllTypes(); + } + input.ReadMessage(Child); + break; + } + case 18: { + if (payload_ == null) { + Payload = new global::Google.Protobuf.TestProtos.TestAllTypes(); + } + input.ReadMessage(Payload); + break; + } + case 26: { + repeatedChild_.AddEntriesFrom(ref input, _repeated_repeatedChild_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestDeprecatedFields : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestDeprecatedFields()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDeprecatedFields() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDeprecatedFields(TestDeprecatedFields other) : this() { + deprecatedInt32_ = other.deprecatedInt32_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestDeprecatedFields Clone() { + return new TestDeprecatedFields(this); + } + + /// Field number for the "deprecated_int32" field. + public const int DeprecatedInt32FieldNumber = 1; + private int deprecatedInt32_; + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int DeprecatedInt32 { + get { return deprecatedInt32_; } + set { + deprecatedInt32_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestDeprecatedFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestDeprecatedFields other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (DeprecatedInt32 != other.DeprecatedInt32) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (DeprecatedInt32 != 0) hash ^= DeprecatedInt32.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (DeprecatedInt32 != 0) { + output.WriteRawTag(8); + output.WriteInt32(DeprecatedInt32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (DeprecatedInt32 != 0) { + output.WriteRawTag(8); + output.WriteInt32(DeprecatedInt32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (DeprecatedInt32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(DeprecatedInt32); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestDeprecatedFields other) { + if (other == null) { + return; + } + if (other.DeprecatedInt32 != 0) { + DeprecatedInt32 = other.DeprecatedInt32; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + DeprecatedInt32 = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + DeprecatedInt32 = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// Define these after TestAllTypes to make sure the compiler can handle + /// that. + /// + public sealed partial class ForeignMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ForeignMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ForeignMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ForeignMessage(ForeignMessage other) : this() { + c_ = other.c_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ForeignMessage Clone() { + return new ForeignMessage(this); + } + + /// Field number for the "c" field. + public const int CFieldNumber = 1; + private int c_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int C { + get { return c_; } + set { + c_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ForeignMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ForeignMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (C != other.C) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (C != 0) hash ^= C.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (C != 0) { + output.WriteRawTag(8); + output.WriteInt32(C); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (C != 0) { + output.WriteRawTag(8); + output.WriteInt32(C); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (C != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(C); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ForeignMessage other) { + if (other == null) { + return; + } + if (other.C != 0) { + C = other.C; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + C = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + C = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestReservedFields : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestReservedFields()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestReservedFields() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestReservedFields(TestReservedFields other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestReservedFields Clone() { + return new TestReservedFields(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestReservedFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestReservedFields other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestReservedFields other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + /// + /// Test that we can use NestedMessage from outside TestAllTypes. + /// + public sealed partial class TestForeignNested : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestForeignNested()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestForeignNested() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestForeignNested(TestForeignNested other) : this() { + foreignNested_ = other.foreignNested_ != null ? other.foreignNested_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestForeignNested Clone() { + return new TestForeignNested(this); + } + + /// Field number for the "foreign_nested" field. + public const int ForeignNestedFieldNumber = 1; + private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage foreignNested_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage ForeignNested { + get { return foreignNested_; } + set { + foreignNested_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestForeignNested); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestForeignNested other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(ForeignNested, other.ForeignNested)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (foreignNested_ != null) hash ^= ForeignNested.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (foreignNested_ != null) { + output.WriteRawTag(10); + output.WriteMessage(ForeignNested); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (foreignNested_ != null) { + output.WriteRawTag(10); + output.WriteMessage(ForeignNested); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (foreignNested_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ForeignNested); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestForeignNested other) { + if (other == null) { + return; + } + if (other.foreignNested_ != null) { + if (foreignNested_ == null) { + ForeignNested = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage(); + } + ForeignNested.MergeFrom(other.ForeignNested); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (foreignNested_ == null) { + ForeignNested = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage(); + } + input.ReadMessage(ForeignNested); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (foreignNested_ == null) { + ForeignNested = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage(); + } + input.ReadMessage(ForeignNested); + break; + } + } + } + } + #endif + + } + + /// + /// Test that really large tag numbers don't break anything. + /// + public sealed partial class TestReallyLargeTagNumber : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestReallyLargeTagNumber()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[6]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestReallyLargeTagNumber() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestReallyLargeTagNumber(TestReallyLargeTagNumber other) : this() { + a_ = other.a_; + bb_ = other.bb_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestReallyLargeTagNumber Clone() { + return new TestReallyLargeTagNumber(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private int a_; + /// + /// The largest possible tag number is 2^28 - 1, since the wire format uses + /// three bits to communicate wire type. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int A { + get { return a_; } + set { + a_ = value; + } + } + + /// Field number for the "bb" field. + public const int BbFieldNumber = 268435455; + private int bb_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Bb { + get { return bb_; } + set { + bb_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestReallyLargeTagNumber); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestReallyLargeTagNumber other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + if (Bb != other.Bb) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (A != 0) hash ^= A.GetHashCode(); + if (Bb != 0) hash ^= Bb.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (A != 0) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (Bb != 0) { + output.WriteRawTag(248, 255, 255, 255, 7); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (A != 0) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (Bb != 0) { + output.WriteRawTag(248, 255, 255, 255, 7); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (A != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (Bb != 0) { + size += 5 + pb::CodedOutputStream.ComputeInt32Size(Bb); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestReallyLargeTagNumber other) { + if (other == null) { + return; + } + if (other.A != 0) { + A = other.A; + } + if (other.Bb != 0) { + Bb = other.Bb; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + A = input.ReadInt32(); + break; + } + case 2147483640: { + Bb = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + A = input.ReadInt32(); + break; + } + case 2147483640: { + Bb = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestRecursiveMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRecursiveMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[7]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRecursiveMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRecursiveMessage(TestRecursiveMessage other) : this() { + a_ = other.a_ != null ? other.a_.Clone() : null; + i_ = other.i_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRecursiveMessage Clone() { + return new TestRecursiveMessage(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private global::Google.Protobuf.TestProtos.TestRecursiveMessage a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.TestRecursiveMessage A { + get { return a_; } + set { + a_ = value; + } + } + + /// Field number for the "i" field. + public const int IFieldNumber = 2; + private int i_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int I { + get { return i_; } + set { + i_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestRecursiveMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestRecursiveMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(A, other.A)) return false; + if (I != other.I) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (a_ != null) hash ^= A.GetHashCode(); + if (I != 0) hash ^= I.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (a_ != null) { + output.WriteRawTag(10); + output.WriteMessage(A); + } + if (I != 0) { + output.WriteRawTag(16); + output.WriteInt32(I); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (a_ != null) { + output.WriteRawTag(10); + output.WriteMessage(A); + } + if (I != 0) { + output.WriteRawTag(16); + output.WriteInt32(I); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (a_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(A); + } + if (I != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(I); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestRecursiveMessage other) { + if (other == null) { + return; + } + if (other.a_ != null) { + if (a_ == null) { + A = new global::Google.Protobuf.TestProtos.TestRecursiveMessage(); + } + A.MergeFrom(other.A); + } + if (other.I != 0) { + I = other.I; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (a_ == null) { + A = new global::Google.Protobuf.TestProtos.TestRecursiveMessage(); + } + input.ReadMessage(A); + break; + } + case 16: { + I = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (a_ == null) { + A = new global::Google.Protobuf.TestProtos.TestRecursiveMessage(); + } + input.ReadMessage(A); + break; + } + case 16: { + I = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// Test that mutual recursion works. + /// + public sealed partial class TestMutualRecursionA : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMutualRecursionA()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[8]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMutualRecursionA() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMutualRecursionA(TestMutualRecursionA other) : this() { + bb_ = other.bb_ != null ? other.bb_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMutualRecursionA Clone() { + return new TestMutualRecursionA(this); + } + + /// Field number for the "bb" field. + public const int BbFieldNumber = 1; + private global::Google.Protobuf.TestProtos.TestMutualRecursionB bb_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.TestMutualRecursionB Bb { + get { return bb_; } + set { + bb_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestMutualRecursionA); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestMutualRecursionA other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Bb, other.Bb)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (bb_ != null) hash ^= Bb.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (bb_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (bb_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (bb_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Bb); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestMutualRecursionA other) { + if (other == null) { + return; + } + if (other.bb_ != null) { + if (bb_ == null) { + Bb = new global::Google.Protobuf.TestProtos.TestMutualRecursionB(); + } + Bb.MergeFrom(other.Bb); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (bb_ == null) { + Bb = new global::Google.Protobuf.TestProtos.TestMutualRecursionB(); + } + input.ReadMessage(Bb); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (bb_ == null) { + Bb = new global::Google.Protobuf.TestProtos.TestMutualRecursionB(); + } + input.ReadMessage(Bb); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestMutualRecursionB : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMutualRecursionB()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[9]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMutualRecursionB() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMutualRecursionB(TestMutualRecursionB other) : this() { + a_ = other.a_ != null ? other.a_.Clone() : null; + optionalInt32_ = other.optionalInt32_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMutualRecursionB Clone() { + return new TestMutualRecursionB(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private global::Google.Protobuf.TestProtos.TestMutualRecursionA a_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.TestMutualRecursionA A { + get { return a_; } + set { + a_ = value; + } + } + + /// Field number for the "optional_int32" field. + public const int OptionalInt32FieldNumber = 2; + private int optionalInt32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalInt32 { + get { return optionalInt32_; } + set { + optionalInt32_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestMutualRecursionB); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestMutualRecursionB other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(A, other.A)) return false; + if (OptionalInt32 != other.OptionalInt32) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (a_ != null) hash ^= A.GetHashCode(); + if (OptionalInt32 != 0) hash ^= OptionalInt32.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (a_ != null) { + output.WriteRawTag(10); + output.WriteMessage(A); + } + if (OptionalInt32 != 0) { + output.WriteRawTag(16); + output.WriteInt32(OptionalInt32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (a_ != null) { + output.WriteRawTag(10); + output.WriteMessage(A); + } + if (OptionalInt32 != 0) { + output.WriteRawTag(16); + output.WriteInt32(OptionalInt32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (a_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(A); + } + if (OptionalInt32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestMutualRecursionB other) { + if (other == null) { + return; + } + if (other.a_ != null) { + if (a_ == null) { + A = new global::Google.Protobuf.TestProtos.TestMutualRecursionA(); + } + A.MergeFrom(other.A); + } + if (other.OptionalInt32 != 0) { + OptionalInt32 = other.OptionalInt32; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (a_ == null) { + A = new global::Google.Protobuf.TestProtos.TestMutualRecursionA(); + } + input.ReadMessage(A); + break; + } + case 16: { + OptionalInt32 = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (a_ == null) { + A = new global::Google.Protobuf.TestProtos.TestMutualRecursionA(); + } + input.ReadMessage(A); + break; + } + case 16: { + OptionalInt32 = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestEnumAllowAlias : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestEnumAllowAlias()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[10]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEnumAllowAlias() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEnumAllowAlias(TestEnumAllowAlias other) : this() { + value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEnumAllowAlias Clone() { + return new TestEnumAllowAlias(this); + } + + /// Field number for the "value" field. + public const int ValueFieldNumber = 1; + private global::Google.Protobuf.TestProtos.TestEnumWithDupValue value_ = global::Google.Protobuf.TestProtos.TestEnumWithDupValue.Unspecified; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.TestEnumWithDupValue Value { + get { return value_; } + set { + value_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestEnumAllowAlias); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestEnumAllowAlias other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Value != other.Value) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Value != global::Google.Protobuf.TestProtos.TestEnumWithDupValue.Unspecified) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Value != global::Google.Protobuf.TestProtos.TestEnumWithDupValue.Unspecified) { + output.WriteRawTag(8); + output.WriteEnum((int) Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != global::Google.Protobuf.TestProtos.TestEnumWithDupValue.Unspecified) { + output.WriteRawTag(8); + output.WriteEnum((int) Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Value != global::Google.Protobuf.TestProtos.TestEnumWithDupValue.Unspecified) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Value); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestEnumAllowAlias other) { + if (other == null) { + return; + } + if (other.Value != global::Google.Protobuf.TestProtos.TestEnumWithDupValue.Unspecified) { + Value = other.Value; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Value = (global::Google.Protobuf.TestProtos.TestEnumWithDupValue) input.ReadEnum(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Value = (global::Google.Protobuf.TestProtos.TestEnumWithDupValue) input.ReadEnum(); + break; + } + } + } + } + #endif + + } + + /// + /// Test message with CamelCase field names. This violates Protocol Buffer + /// standard style. + /// + public sealed partial class TestCamelCaseFieldNames : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestCamelCaseFieldNames()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[11]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestCamelCaseFieldNames() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestCamelCaseFieldNames(TestCamelCaseFieldNames other) : this() { + primitiveField_ = other.primitiveField_; + stringField_ = other.stringField_; + enumField_ = other.enumField_; + messageField_ = other.messageField_ != null ? other.messageField_.Clone() : null; + repeatedPrimitiveField_ = other.repeatedPrimitiveField_.Clone(); + repeatedStringField_ = other.repeatedStringField_.Clone(); + repeatedEnumField_ = other.repeatedEnumField_.Clone(); + repeatedMessageField_ = other.repeatedMessageField_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestCamelCaseFieldNames Clone() { + return new TestCamelCaseFieldNames(this); + } + + /// Field number for the "PrimitiveField" field. + public const int PrimitiveFieldFieldNumber = 1; + private int primitiveField_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int PrimitiveField { + get { return primitiveField_; } + set { + primitiveField_ = value; + } + } + + /// Field number for the "StringField" field. + public const int StringFieldFieldNumber = 2; + private string stringField_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string StringField { + get { return stringField_; } + set { + stringField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "EnumField" field. + public const int EnumFieldFieldNumber = 3; + private global::Google.Protobuf.TestProtos.ForeignEnum enumField_ = global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.ForeignEnum EnumField { + get { return enumField_; } + set { + enumField_ = value; + } + } + + /// Field number for the "MessageField" field. + public const int MessageFieldFieldNumber = 4; + private global::Google.Protobuf.TestProtos.ForeignMessage messageField_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.ForeignMessage MessageField { + get { return messageField_; } + set { + messageField_ = value; + } + } + + /// Field number for the "RepeatedPrimitiveField" field. + public const int RepeatedPrimitiveFieldFieldNumber = 7; + private static readonly pb::FieldCodec _repeated_repeatedPrimitiveField_codec + = pb::FieldCodec.ForInt32(58); + private readonly pbc::RepeatedField repeatedPrimitiveField_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedPrimitiveField { + get { return repeatedPrimitiveField_; } + } + + /// Field number for the "RepeatedStringField" field. + public const int RepeatedStringFieldFieldNumber = 8; + private static readonly pb::FieldCodec _repeated_repeatedStringField_codec + = pb::FieldCodec.ForString(66); + private readonly pbc::RepeatedField repeatedStringField_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedStringField { + get { return repeatedStringField_; } + } + + /// Field number for the "RepeatedEnumField" field. + public const int RepeatedEnumFieldFieldNumber = 9; + private static readonly pb::FieldCodec _repeated_repeatedEnumField_codec + = pb::FieldCodec.ForEnum(74, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x); + private readonly pbc::RepeatedField repeatedEnumField_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedEnumField { + get { return repeatedEnumField_; } + } + + /// Field number for the "RepeatedMessageField" field. + public const int RepeatedMessageFieldFieldNumber = 10; + private static readonly pb::FieldCodec _repeated_repeatedMessageField_codec + = pb::FieldCodec.ForMessage(82, global::Google.Protobuf.TestProtos.ForeignMessage.Parser); + private readonly pbc::RepeatedField repeatedMessageField_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedMessageField { + get { return repeatedMessageField_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestCamelCaseFieldNames); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestCamelCaseFieldNames other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (PrimitiveField != other.PrimitiveField) return false; + if (StringField != other.StringField) return false; + if (EnumField != other.EnumField) return false; + if (!object.Equals(MessageField, other.MessageField)) return false; + if(!repeatedPrimitiveField_.Equals(other.repeatedPrimitiveField_)) return false; + if(!repeatedStringField_.Equals(other.repeatedStringField_)) return false; + if(!repeatedEnumField_.Equals(other.repeatedEnumField_)) return false; + if(!repeatedMessageField_.Equals(other.repeatedMessageField_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (PrimitiveField != 0) hash ^= PrimitiveField.GetHashCode(); + if (StringField.Length != 0) hash ^= StringField.GetHashCode(); + if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified) hash ^= EnumField.GetHashCode(); + if (messageField_ != null) hash ^= MessageField.GetHashCode(); + hash ^= repeatedPrimitiveField_.GetHashCode(); + hash ^= repeatedStringField_.GetHashCode(); + hash ^= repeatedEnumField_.GetHashCode(); + hash ^= repeatedMessageField_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (PrimitiveField != 0) { + output.WriteRawTag(8); + output.WriteInt32(PrimitiveField); + } + if (StringField.Length != 0) { + output.WriteRawTag(18); + output.WriteString(StringField); + } + if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified) { + output.WriteRawTag(24); + output.WriteEnum((int) EnumField); + } + if (messageField_ != null) { + output.WriteRawTag(34); + output.WriteMessage(MessageField); + } + repeatedPrimitiveField_.WriteTo(output, _repeated_repeatedPrimitiveField_codec); + repeatedStringField_.WriteTo(output, _repeated_repeatedStringField_codec); + repeatedEnumField_.WriteTo(output, _repeated_repeatedEnumField_codec); + repeatedMessageField_.WriteTo(output, _repeated_repeatedMessageField_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (PrimitiveField != 0) { + output.WriteRawTag(8); + output.WriteInt32(PrimitiveField); + } + if (StringField.Length != 0) { + output.WriteRawTag(18); + output.WriteString(StringField); + } + if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified) { + output.WriteRawTag(24); + output.WriteEnum((int) EnumField); + } + if (messageField_ != null) { + output.WriteRawTag(34); + output.WriteMessage(MessageField); + } + repeatedPrimitiveField_.WriteTo(ref output, _repeated_repeatedPrimitiveField_codec); + repeatedStringField_.WriteTo(ref output, _repeated_repeatedStringField_codec); + repeatedEnumField_.WriteTo(ref output, _repeated_repeatedEnumField_codec); + repeatedMessageField_.WriteTo(ref output, _repeated_repeatedMessageField_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (PrimitiveField != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(PrimitiveField); + } + if (StringField.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(StringField); + } + if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumField); + } + if (messageField_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageField); + } + size += repeatedPrimitiveField_.CalculateSize(_repeated_repeatedPrimitiveField_codec); + size += repeatedStringField_.CalculateSize(_repeated_repeatedStringField_codec); + size += repeatedEnumField_.CalculateSize(_repeated_repeatedEnumField_codec); + size += repeatedMessageField_.CalculateSize(_repeated_repeatedMessageField_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestCamelCaseFieldNames other) { + if (other == null) { + return; + } + if (other.PrimitiveField != 0) { + PrimitiveField = other.PrimitiveField; + } + if (other.StringField.Length != 0) { + StringField = other.StringField; + } + if (other.EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified) { + EnumField = other.EnumField; + } + if (other.messageField_ != null) { + if (messageField_ == null) { + MessageField = new global::Google.Protobuf.TestProtos.ForeignMessage(); + } + MessageField.MergeFrom(other.MessageField); + } + repeatedPrimitiveField_.Add(other.repeatedPrimitiveField_); + repeatedStringField_.Add(other.repeatedStringField_); + repeatedEnumField_.Add(other.repeatedEnumField_); + repeatedMessageField_.Add(other.repeatedMessageField_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + PrimitiveField = input.ReadInt32(); + break; + } + case 18: { + StringField = input.ReadString(); + break; + } + case 24: { + EnumField = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum(); + break; + } + case 34: { + if (messageField_ == null) { + MessageField = new global::Google.Protobuf.TestProtos.ForeignMessage(); + } + input.ReadMessage(MessageField); + break; + } + case 58: + case 56: { + repeatedPrimitiveField_.AddEntriesFrom(input, _repeated_repeatedPrimitiveField_codec); + break; + } + case 66: { + repeatedStringField_.AddEntriesFrom(input, _repeated_repeatedStringField_codec); + break; + } + case 74: + case 72: { + repeatedEnumField_.AddEntriesFrom(input, _repeated_repeatedEnumField_codec); + break; + } + case 82: { + repeatedMessageField_.AddEntriesFrom(input, _repeated_repeatedMessageField_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + PrimitiveField = input.ReadInt32(); + break; + } + case 18: { + StringField = input.ReadString(); + break; + } + case 24: { + EnumField = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum(); + break; + } + case 34: { + if (messageField_ == null) { + MessageField = new global::Google.Protobuf.TestProtos.ForeignMessage(); + } + input.ReadMessage(MessageField); + break; + } + case 58: + case 56: { + repeatedPrimitiveField_.AddEntriesFrom(ref input, _repeated_repeatedPrimitiveField_codec); + break; + } + case 66: { + repeatedStringField_.AddEntriesFrom(ref input, _repeated_repeatedStringField_codec); + break; + } + case 74: + case 72: { + repeatedEnumField_.AddEntriesFrom(ref input, _repeated_repeatedEnumField_codec); + break; + } + case 82: { + repeatedMessageField_.AddEntriesFrom(ref input, _repeated_repeatedMessageField_codec); + break; + } + } + } + } + #endif + + } + + /// + /// We list fields out of order, to ensure that we're using field number and not + /// field index to determine serialization order. + /// + public sealed partial class TestFieldOrderings : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestFieldOrderings()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[12]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestFieldOrderings() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestFieldOrderings(TestFieldOrderings other) : this() { + myString_ = other.myString_; + myInt_ = other.myInt_; + myFloat_ = other.myFloat_; + singleNestedMessage_ = other.singleNestedMessage_ != null ? other.singleNestedMessage_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestFieldOrderings Clone() { + return new TestFieldOrderings(this); + } + + /// Field number for the "my_string" field. + public const int MyStringFieldNumber = 11; + private string myString_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string MyString { + get { return myString_; } + set { + myString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "my_int" field. + public const int MyIntFieldNumber = 1; + private long myInt_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long MyInt { + get { return myInt_; } + set { + myInt_ = value; + } + } + + /// Field number for the "my_float" field. + public const int MyFloatFieldNumber = 101; + private float myFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float MyFloat { + get { return myFloat_; } + set { + myFloat_ = value; + } + } + + /// Field number for the "single_nested_message" field. + public const int SingleNestedMessageFieldNumber = 200; + private global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage singleNestedMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage SingleNestedMessage { + get { return singleNestedMessage_; } + set { + singleNestedMessage_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestFieldOrderings); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestFieldOrderings other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (MyString != other.MyString) return false; + if (MyInt != other.MyInt) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(MyFloat, other.MyFloat)) return false; + if (!object.Equals(SingleNestedMessage, other.SingleNestedMessage)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (MyString.Length != 0) hash ^= MyString.GetHashCode(); + if (MyInt != 0L) hash ^= MyInt.GetHashCode(); + if (MyFloat != 0F) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(MyFloat); + if (singleNestedMessage_ != null) hash ^= SingleNestedMessage.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (MyInt != 0L) { + output.WriteRawTag(8); + output.WriteInt64(MyInt); + } + if (MyString.Length != 0) { + output.WriteRawTag(90); + output.WriteString(MyString); + } + if (MyFloat != 0F) { + output.WriteRawTag(173, 6); + output.WriteFloat(MyFloat); + } + if (singleNestedMessage_ != null) { + output.WriteRawTag(194, 12); + output.WriteMessage(SingleNestedMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (MyInt != 0L) { + output.WriteRawTag(8); + output.WriteInt64(MyInt); + } + if (MyString.Length != 0) { + output.WriteRawTag(90); + output.WriteString(MyString); + } + if (MyFloat != 0F) { + output.WriteRawTag(173, 6); + output.WriteFloat(MyFloat); + } + if (singleNestedMessage_ != null) { + output.WriteRawTag(194, 12); + output.WriteMessage(SingleNestedMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (MyString.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(MyString); + } + if (MyInt != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(MyInt); + } + if (MyFloat != 0F) { + size += 2 + 4; + } + if (singleNestedMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleNestedMessage); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestFieldOrderings other) { + if (other == null) { + return; + } + if (other.MyString.Length != 0) { + MyString = other.MyString; + } + if (other.MyInt != 0L) { + MyInt = other.MyInt; + } + if (other.MyFloat != 0F) { + MyFloat = other.MyFloat; + } + if (other.singleNestedMessage_ != null) { + if (singleNestedMessage_ == null) { + SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage(); + } + SingleNestedMessage.MergeFrom(other.SingleNestedMessage); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + MyInt = input.ReadInt64(); + break; + } + case 90: { + MyString = input.ReadString(); + break; + } + case 813: { + MyFloat = input.ReadFloat(); + break; + } + case 1602: { + if (singleNestedMessage_ == null) { + SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage(); + } + input.ReadMessage(SingleNestedMessage); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + MyInt = input.ReadInt64(); + break; + } + case 90: { + MyString = input.ReadString(); + break; + } + case 813: { + MyFloat = input.ReadFloat(); + break; + } + case 1602: { + if (singleNestedMessage_ == null) { + SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage(); + } + input.ReadMessage(SingleNestedMessage); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestFieldOrderings message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class NestedMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.TestFieldOrderings.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + oo_ = other.oo_; + bb_ = other.bb_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "oo" field. + public const int OoFieldNumber = 2; + private long oo_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Oo { + get { return oo_; } + set { + oo_ = value; + } + } + + /// Field number for the "bb" field. + public const int BbFieldNumber = 1; + private int bb_; + /// + /// The field name "b" fails to compile in proto1 because it conflicts with + /// a local variable named "b" in one of the generated methods. Doh. + /// This file needs to compile in proto1 to test backwards-compatibility. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Bb { + get { return bb_; } + set { + bb_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Oo != other.Oo) return false; + if (Bb != other.Bb) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Oo != 0L) hash ^= Oo.GetHashCode(); + if (Bb != 0) hash ^= Bb.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Bb != 0) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (Oo != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Oo); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Bb != 0) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (Oo != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Oo); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Oo != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Oo); + } + if (Bb != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Bb); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.Oo != 0L) { + Oo = other.Oo; + } + if (other.Bb != 0) { + Bb = other.Bb; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Bb = input.ReadInt32(); + break; + } + case 16: { + Oo = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Bb = input.ReadInt32(); + break; + } + case 16: { + Oo = input.ReadInt64(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class SparseEnumMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SparseEnumMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[13]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SparseEnumMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SparseEnumMessage(SparseEnumMessage other) : this() { + sparseEnum_ = other.sparseEnum_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SparseEnumMessage Clone() { + return new SparseEnumMessage(this); + } + + /// Field number for the "sparse_enum" field. + public const int SparseEnumFieldNumber = 1; + private global::Google.Protobuf.TestProtos.TestSparseEnum sparseEnum_ = global::Google.Protobuf.TestProtos.TestSparseEnum.Unspecified; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.TestSparseEnum SparseEnum { + get { return sparseEnum_; } + set { + sparseEnum_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SparseEnumMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SparseEnumMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (SparseEnum != other.SparseEnum) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.Unspecified) hash ^= SparseEnum.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.Unspecified) { + output.WriteRawTag(8); + output.WriteEnum((int) SparseEnum); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.Unspecified) { + output.WriteRawTag(8); + output.WriteEnum((int) SparseEnum); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.Unspecified) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) SparseEnum); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SparseEnumMessage other) { + if (other == null) { + return; + } + if (other.SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.Unspecified) { + SparseEnum = other.SparseEnum; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + SparseEnum = (global::Google.Protobuf.TestProtos.TestSparseEnum) input.ReadEnum(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + SparseEnum = (global::Google.Protobuf.TestProtos.TestSparseEnum) input.ReadEnum(); + break; + } + } + } + } + #endif + + } + + /// + /// Test String and Bytes: string is for valid UTF-8 strings + /// + public sealed partial class OneString : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneString()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[14]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneString() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneString(OneString other) : this() { + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneString Clone() { + return new OneString(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private string data_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Data { + get { return data_; } + set { + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as OneString); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(OneString other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Data.Length != 0) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Data.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Data.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(OneString other) { + if (other == null) { + return; + } + if (other.Data.Length != 0) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Data = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Data = input.ReadString(); + break; + } + } + } + } + #endif + + } + + public sealed partial class MoreString : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MoreString()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[15]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MoreString() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MoreString(MoreString other) : this() { + data_ = other.data_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MoreString Clone() { + return new MoreString(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_data_codec + = pb::FieldCodec.ForString(10); + private readonly pbc::RepeatedField data_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Data { + get { return data_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as MoreString); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(MoreString other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!data_.Equals(other.data_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= data_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + data_.WriteTo(output, _repeated_data_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + data_.WriteTo(ref output, _repeated_data_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += data_.CalculateSize(_repeated_data_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(MoreString other) { + if (other == null) { + return; + } + data_.Add(other.data_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + data_.AddEntriesFrom(input, _repeated_data_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + data_.AddEntriesFrom(ref input, _repeated_data_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class OneBytes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneBytes()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[16]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneBytes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneBytes(OneBytes other) : this() { + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneBytes Clone() { + return new OneBytes(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private pb::ByteString data_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString Data { + get { return data_; } + set { + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as OneBytes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(OneBytes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Data.Length != 0) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Data.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Data.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(OneBytes other) { + if (other == null) { + return; + } + if (other.Data.Length != 0) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Data = input.ReadBytes(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Data = input.ReadBytes(); + break; + } + } + } + } + #endif + + } + + public sealed partial class MoreBytes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MoreBytes()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[17]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MoreBytes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MoreBytes(MoreBytes other) : this() { + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MoreBytes Clone() { + return new MoreBytes(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private pb::ByteString data_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString Data { + get { return data_; } + set { + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as MoreBytes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(MoreBytes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Data.Length != 0) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Data.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Data.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(MoreBytes other) { + if (other == null) { + return; + } + if (other.Data.Length != 0) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Data = input.ReadBytes(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Data = input.ReadBytes(); + break; + } + } + } + } + #endif + + } + + /// + /// Test int32, uint32, int64, uint64, and bool are all compatible + /// + public sealed partial class Int32Message : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Int32Message()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[18]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Int32Message() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Int32Message(Int32Message other) : this() { + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Int32Message Clone() { + return new Int32Message(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private int data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Data { + get { return data_; } + set { + data_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Int32Message); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Int32Message other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Data != 0) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Data != 0) { + output.WriteRawTag(8); + output.WriteInt32(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data != 0) { + output.WriteRawTag(8); + output.WriteInt32(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Data != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Int32Message other) { + if (other == null) { + return; + } + if (other.Data != 0) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class Uint32Message : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Uint32Message()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[19]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Uint32Message() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Uint32Message(Uint32Message other) : this() { + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Uint32Message Clone() { + return new Uint32Message(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private uint data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint Data { + get { return data_; } + set { + data_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Uint32Message); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Uint32Message other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Data != 0) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Data != 0) { + output.WriteRawTag(8); + output.WriteUInt32(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data != 0) { + output.WriteRawTag(8); + output.WriteUInt32(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Data != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Uint32Message other) { + if (other == null) { + return; + } + if (other.Data != 0) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadUInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadUInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class Int64Message : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Int64Message()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[20]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Int64Message() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Int64Message(Int64Message other) : this() { + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Int64Message Clone() { + return new Int64Message(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private long data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Data { + get { return data_; } + set { + data_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Int64Message); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Int64Message other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Data != 0L) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Data != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Data != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Int64Message other) { + if (other == null) { + return; + } + if (other.Data != 0L) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadInt64(); + break; + } + } + } + } + #endif + + } + + public sealed partial class Uint64Message : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Uint64Message()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[21]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Uint64Message() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Uint64Message(Uint64Message other) : this() { + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Uint64Message Clone() { + return new Uint64Message(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private ulong data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong Data { + get { return data_; } + set { + data_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Uint64Message); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Uint64Message other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Data != 0UL) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Data != 0UL) { + output.WriteRawTag(8); + output.WriteUInt64(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data != 0UL) { + output.WriteRawTag(8); + output.WriteUInt64(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Data != 0UL) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Uint64Message other) { + if (other == null) { + return; + } + if (other.Data != 0UL) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadUInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadUInt64(); + break; + } + } + } + } + #endif + + } + + public sealed partial class BoolMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BoolMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[22]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BoolMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BoolMessage(BoolMessage other) : this() { + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BoolMessage Clone() { + return new BoolMessage(this); + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 1; + private bool data_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Data { + get { return data_; } + set { + data_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as BoolMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(BoolMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Data != false) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Data != false) { + output.WriteRawTag(8); + output.WriteBool(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data != false) { + output.WriteRawTag(8); + output.WriteBool(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Data != false) { + size += 1 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(BoolMessage other) { + if (other == null) { + return; + } + if (other.Data != false) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadBool(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Data = input.ReadBool(); + break; + } + } + } + } + #endif + + } + + /// + /// Test oneofs. + /// + public sealed partial class TestOneof : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestOneof()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[23]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestOneof() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestOneof(TestOneof other) : this() { + switch (other.FooCase) { + case FooOneofCase.FooInt: + FooInt = other.FooInt; + break; + case FooOneofCase.FooString: + FooString = other.FooString; + break; + case FooOneofCase.FooMessage: + FooMessage = other.FooMessage.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestOneof Clone() { + return new TestOneof(this); + } + + /// Field number for the "foo_int" field. + public const int FooIntFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int FooInt { + get { return fooCase_ == FooOneofCase.FooInt ? (int) foo_ : 0; } + set { + foo_ = value; + fooCase_ = FooOneofCase.FooInt; + } + } + + /// Field number for the "foo_string" field. + public const int FooStringFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string FooString { + get { return fooCase_ == FooOneofCase.FooString ? (string) foo_ : ""; } + set { + foo_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + fooCase_ = FooOneofCase.FooString; + } + } + + /// Field number for the "foo_message" field. + public const int FooMessageFieldNumber = 3; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.TestProtos.TestAllTypes FooMessage { + get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.Protobuf.TestProtos.TestAllTypes) foo_ : null; } + set { + foo_ = value; + fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooMessage; + } + } + + private object foo_; + /// Enum of possible cases for the "foo" oneof. + public enum FooOneofCase { + None = 0, + FooInt = 1, + FooString = 2, + FooMessage = 3, + } + private FooOneofCase fooCase_ = FooOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooOneofCase FooCase { + get { return fooCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFoo() { + fooCase_ = FooOneofCase.None; + foo_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestOneof); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestOneof other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (FooInt != other.FooInt) return false; + if (FooString != other.FooString) return false; + if (!object.Equals(FooMessage, other.FooMessage)) return false; + if (FooCase != other.FooCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (fooCase_ == FooOneofCase.FooInt) hash ^= FooInt.GetHashCode(); + if (fooCase_ == FooOneofCase.FooString) hash ^= FooString.GetHashCode(); + if (fooCase_ == FooOneofCase.FooMessage) hash ^= FooMessage.GetHashCode(); + hash ^= (int) fooCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (fooCase_ == FooOneofCase.FooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (fooCase_ == FooOneofCase.FooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (fooCase_ == FooOneofCase.FooMessage) { + output.WriteRawTag(26); + output.WriteMessage(FooMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (fooCase_ == FooOneofCase.FooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (fooCase_ == FooOneofCase.FooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (fooCase_ == FooOneofCase.FooMessage) { + output.WriteRawTag(26); + output.WriteMessage(FooMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (fooCase_ == FooOneofCase.FooInt) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(FooInt); + } + if (fooCase_ == FooOneofCase.FooString) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FooString); + } + if (fooCase_ == FooOneofCase.FooMessage) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(FooMessage); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestOneof other) { + if (other == null) { + return; + } + switch (other.FooCase) { + case FooOneofCase.FooInt: + FooInt = other.FooInt; + break; + case FooOneofCase.FooString: + FooString = other.FooString; + break; + case FooOneofCase.FooMessage: + if (FooMessage == null) { + FooMessage = new global::Google.Protobuf.TestProtos.TestAllTypes(); + } + FooMessage.MergeFrom(other.FooMessage); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + FooInt = input.ReadInt32(); + break; + } + case 18: { + FooString = input.ReadString(); + break; + } + case 26: { + global::Google.Protobuf.TestProtos.TestAllTypes subBuilder = new global::Google.Protobuf.TestProtos.TestAllTypes(); + if (fooCase_ == FooOneofCase.FooMessage) { + subBuilder.MergeFrom(FooMessage); + } + input.ReadMessage(subBuilder); + FooMessage = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + FooInt = input.ReadInt32(); + break; + } + case 18: { + FooString = input.ReadString(); + break; + } + case 26: { + global::Google.Protobuf.TestProtos.TestAllTypes subBuilder = new global::Google.Protobuf.TestProtos.TestAllTypes(); + if (fooCase_ == FooOneofCase.FooMessage) { + subBuilder.MergeFrom(FooMessage); + } + input.ReadMessage(subBuilder); + FooMessage = subBuilder; + break; + } + } + } + } + #endif + + } + + public sealed partial class TestPackedTypes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestPackedTypes()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[24]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestPackedTypes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestPackedTypes(TestPackedTypes other) : this() { + packedInt32_ = other.packedInt32_.Clone(); + packedInt64_ = other.packedInt64_.Clone(); + packedUint32_ = other.packedUint32_.Clone(); + packedUint64_ = other.packedUint64_.Clone(); + packedSint32_ = other.packedSint32_.Clone(); + packedSint64_ = other.packedSint64_.Clone(); + packedFixed32_ = other.packedFixed32_.Clone(); + packedFixed64_ = other.packedFixed64_.Clone(); + packedSfixed32_ = other.packedSfixed32_.Clone(); + packedSfixed64_ = other.packedSfixed64_.Clone(); + packedFloat_ = other.packedFloat_.Clone(); + packedDouble_ = other.packedDouble_.Clone(); + packedBool_ = other.packedBool_.Clone(); + packedEnum_ = other.packedEnum_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestPackedTypes Clone() { + return new TestPackedTypes(this); + } + + /// Field number for the "packed_int32" field. + public const int PackedInt32FieldNumber = 90; + private static readonly pb::FieldCodec _repeated_packedInt32_codec + = pb::FieldCodec.ForInt32(722); + private readonly pbc::RepeatedField packedInt32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedInt32 { + get { return packedInt32_; } + } + + /// Field number for the "packed_int64" field. + public const int PackedInt64FieldNumber = 91; + private static readonly pb::FieldCodec _repeated_packedInt64_codec + = pb::FieldCodec.ForInt64(730); + private readonly pbc::RepeatedField packedInt64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedInt64 { + get { return packedInt64_; } + } + + /// Field number for the "packed_uint32" field. + public const int PackedUint32FieldNumber = 92; + private static readonly pb::FieldCodec _repeated_packedUint32_codec + = pb::FieldCodec.ForUInt32(738); + private readonly pbc::RepeatedField packedUint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedUint32 { + get { return packedUint32_; } + } + + /// Field number for the "packed_uint64" field. + public const int PackedUint64FieldNumber = 93; + private static readonly pb::FieldCodec _repeated_packedUint64_codec + = pb::FieldCodec.ForUInt64(746); + private readonly pbc::RepeatedField packedUint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedUint64 { + get { return packedUint64_; } + } + + /// Field number for the "packed_sint32" field. + public const int PackedSint32FieldNumber = 94; + private static readonly pb::FieldCodec _repeated_packedSint32_codec + = pb::FieldCodec.ForSInt32(754); + private readonly pbc::RepeatedField packedSint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSint32 { + get { return packedSint32_; } + } + + /// Field number for the "packed_sint64" field. + public const int PackedSint64FieldNumber = 95; + private static readonly pb::FieldCodec _repeated_packedSint64_codec + = pb::FieldCodec.ForSInt64(762); + private readonly pbc::RepeatedField packedSint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSint64 { + get { return packedSint64_; } + } + + /// Field number for the "packed_fixed32" field. + public const int PackedFixed32FieldNumber = 96; + private static readonly pb::FieldCodec _repeated_packedFixed32_codec + = pb::FieldCodec.ForFixed32(770); + private readonly pbc::RepeatedField packedFixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedFixed32 { + get { return packedFixed32_; } + } + + /// Field number for the "packed_fixed64" field. + public const int PackedFixed64FieldNumber = 97; + private static readonly pb::FieldCodec _repeated_packedFixed64_codec + = pb::FieldCodec.ForFixed64(778); + private readonly pbc::RepeatedField packedFixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedFixed64 { + get { return packedFixed64_; } + } + + /// Field number for the "packed_sfixed32" field. + public const int PackedSfixed32FieldNumber = 98; + private static readonly pb::FieldCodec _repeated_packedSfixed32_codec + = pb::FieldCodec.ForSFixed32(786); + private readonly pbc::RepeatedField packedSfixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSfixed32 { + get { return packedSfixed32_; } + } + + /// Field number for the "packed_sfixed64" field. + public const int PackedSfixed64FieldNumber = 99; + private static readonly pb::FieldCodec _repeated_packedSfixed64_codec + = pb::FieldCodec.ForSFixed64(794); + private readonly pbc::RepeatedField packedSfixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedSfixed64 { + get { return packedSfixed64_; } + } + + /// Field number for the "packed_float" field. + public const int PackedFloatFieldNumber = 100; + private static readonly pb::FieldCodec _repeated_packedFloat_codec + = pb::FieldCodec.ForFloat(802); + private readonly pbc::RepeatedField packedFloat_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedFloat { + get { return packedFloat_; } + } + + /// Field number for the "packed_double" field. + public const int PackedDoubleFieldNumber = 101; + private static readonly pb::FieldCodec _repeated_packedDouble_codec + = pb::FieldCodec.ForDouble(810); + private readonly pbc::RepeatedField packedDouble_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedDouble { + get { return packedDouble_; } + } + + /// Field number for the "packed_bool" field. + public const int PackedBoolFieldNumber = 102; + private static readonly pb::FieldCodec _repeated_packedBool_codec + = pb::FieldCodec.ForBool(818); + private readonly pbc::RepeatedField packedBool_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedBool { + get { return packedBool_; } + } + + /// Field number for the "packed_enum" field. + public const int PackedEnumFieldNumber = 103; + private static readonly pb::FieldCodec _repeated_packedEnum_codec + = pb::FieldCodec.ForEnum(826, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x); + private readonly pbc::RepeatedField packedEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField PackedEnum { + get { return packedEnum_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestPackedTypes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestPackedTypes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!packedInt32_.Equals(other.packedInt32_)) return false; + if(!packedInt64_.Equals(other.packedInt64_)) return false; + if(!packedUint32_.Equals(other.packedUint32_)) return false; + if(!packedUint64_.Equals(other.packedUint64_)) return false; + if(!packedSint32_.Equals(other.packedSint32_)) return false; + if(!packedSint64_.Equals(other.packedSint64_)) return false; + if(!packedFixed32_.Equals(other.packedFixed32_)) return false; + if(!packedFixed64_.Equals(other.packedFixed64_)) return false; + if(!packedSfixed32_.Equals(other.packedSfixed32_)) return false; + if(!packedSfixed64_.Equals(other.packedSfixed64_)) return false; + if(!packedFloat_.Equals(other.packedFloat_)) return false; + if(!packedDouble_.Equals(other.packedDouble_)) return false; + if(!packedBool_.Equals(other.packedBool_)) return false; + if(!packedEnum_.Equals(other.packedEnum_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= packedInt32_.GetHashCode(); + hash ^= packedInt64_.GetHashCode(); + hash ^= packedUint32_.GetHashCode(); + hash ^= packedUint64_.GetHashCode(); + hash ^= packedSint32_.GetHashCode(); + hash ^= packedSint64_.GetHashCode(); + hash ^= packedFixed32_.GetHashCode(); + hash ^= packedFixed64_.GetHashCode(); + hash ^= packedSfixed32_.GetHashCode(); + hash ^= packedSfixed64_.GetHashCode(); + hash ^= packedFloat_.GetHashCode(); + hash ^= packedDouble_.GetHashCode(); + hash ^= packedBool_.GetHashCode(); + hash ^= packedEnum_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + packedInt32_.WriteTo(output, _repeated_packedInt32_codec); + packedInt64_.WriteTo(output, _repeated_packedInt64_codec); + packedUint32_.WriteTo(output, _repeated_packedUint32_codec); + packedUint64_.WriteTo(output, _repeated_packedUint64_codec); + packedSint32_.WriteTo(output, _repeated_packedSint32_codec); + packedSint64_.WriteTo(output, _repeated_packedSint64_codec); + packedFixed32_.WriteTo(output, _repeated_packedFixed32_codec); + packedFixed64_.WriteTo(output, _repeated_packedFixed64_codec); + packedSfixed32_.WriteTo(output, _repeated_packedSfixed32_codec); + packedSfixed64_.WriteTo(output, _repeated_packedSfixed64_codec); + packedFloat_.WriteTo(output, _repeated_packedFloat_codec); + packedDouble_.WriteTo(output, _repeated_packedDouble_codec); + packedBool_.WriteTo(output, _repeated_packedBool_codec); + packedEnum_.WriteTo(output, _repeated_packedEnum_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec); + packedInt64_.WriteTo(ref output, _repeated_packedInt64_codec); + packedUint32_.WriteTo(ref output, _repeated_packedUint32_codec); + packedUint64_.WriteTo(ref output, _repeated_packedUint64_codec); + packedSint32_.WriteTo(ref output, _repeated_packedSint32_codec); + packedSint64_.WriteTo(ref output, _repeated_packedSint64_codec); + packedFixed32_.WriteTo(ref output, _repeated_packedFixed32_codec); + packedFixed64_.WriteTo(ref output, _repeated_packedFixed64_codec); + packedSfixed32_.WriteTo(ref output, _repeated_packedSfixed32_codec); + packedSfixed64_.WriteTo(ref output, _repeated_packedSfixed64_codec); + packedFloat_.WriteTo(ref output, _repeated_packedFloat_codec); + packedDouble_.WriteTo(ref output, _repeated_packedDouble_codec); + packedBool_.WriteTo(ref output, _repeated_packedBool_codec); + packedEnum_.WriteTo(ref output, _repeated_packedEnum_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += packedInt32_.CalculateSize(_repeated_packedInt32_codec); + size += packedInt64_.CalculateSize(_repeated_packedInt64_codec); + size += packedUint32_.CalculateSize(_repeated_packedUint32_codec); + size += packedUint64_.CalculateSize(_repeated_packedUint64_codec); + size += packedSint32_.CalculateSize(_repeated_packedSint32_codec); + size += packedSint64_.CalculateSize(_repeated_packedSint64_codec); + size += packedFixed32_.CalculateSize(_repeated_packedFixed32_codec); + size += packedFixed64_.CalculateSize(_repeated_packedFixed64_codec); + size += packedSfixed32_.CalculateSize(_repeated_packedSfixed32_codec); + size += packedSfixed64_.CalculateSize(_repeated_packedSfixed64_codec); + size += packedFloat_.CalculateSize(_repeated_packedFloat_codec); + size += packedDouble_.CalculateSize(_repeated_packedDouble_codec); + size += packedBool_.CalculateSize(_repeated_packedBool_codec); + size += packedEnum_.CalculateSize(_repeated_packedEnum_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestPackedTypes other) { + if (other == null) { + return; + } + packedInt32_.Add(other.packedInt32_); + packedInt64_.Add(other.packedInt64_); + packedUint32_.Add(other.packedUint32_); + packedUint64_.Add(other.packedUint64_); + packedSint32_.Add(other.packedSint32_); + packedSint64_.Add(other.packedSint64_); + packedFixed32_.Add(other.packedFixed32_); + packedFixed64_.Add(other.packedFixed64_); + packedSfixed32_.Add(other.packedSfixed32_); + packedSfixed64_.Add(other.packedSfixed64_); + packedFloat_.Add(other.packedFloat_); + packedDouble_.Add(other.packedDouble_); + packedBool_.Add(other.packedBool_); + packedEnum_.Add(other.packedEnum_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 722: + case 720: { + packedInt32_.AddEntriesFrom(input, _repeated_packedInt32_codec); + break; + } + case 730: + case 728: { + packedInt64_.AddEntriesFrom(input, _repeated_packedInt64_codec); + break; + } + case 738: + case 736: { + packedUint32_.AddEntriesFrom(input, _repeated_packedUint32_codec); + break; + } + case 746: + case 744: { + packedUint64_.AddEntriesFrom(input, _repeated_packedUint64_codec); + break; + } + case 754: + case 752: { + packedSint32_.AddEntriesFrom(input, _repeated_packedSint32_codec); + break; + } + case 762: + case 760: { + packedSint64_.AddEntriesFrom(input, _repeated_packedSint64_codec); + break; + } + case 770: + case 773: { + packedFixed32_.AddEntriesFrom(input, _repeated_packedFixed32_codec); + break; + } + case 778: + case 777: { + packedFixed64_.AddEntriesFrom(input, _repeated_packedFixed64_codec); + break; + } + case 786: + case 789: { + packedSfixed32_.AddEntriesFrom(input, _repeated_packedSfixed32_codec); + break; + } + case 794: + case 793: { + packedSfixed64_.AddEntriesFrom(input, _repeated_packedSfixed64_codec); + break; + } + case 802: + case 805: { + packedFloat_.AddEntriesFrom(input, _repeated_packedFloat_codec); + break; + } + case 810: + case 809: { + packedDouble_.AddEntriesFrom(input, _repeated_packedDouble_codec); + break; + } + case 818: + case 816: { + packedBool_.AddEntriesFrom(input, _repeated_packedBool_codec); + break; + } + case 826: + case 824: { + packedEnum_.AddEntriesFrom(input, _repeated_packedEnum_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 722: + case 720: { + packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec); + break; + } + case 730: + case 728: { + packedInt64_.AddEntriesFrom(ref input, _repeated_packedInt64_codec); + break; + } + case 738: + case 736: { + packedUint32_.AddEntriesFrom(ref input, _repeated_packedUint32_codec); + break; + } + case 746: + case 744: { + packedUint64_.AddEntriesFrom(ref input, _repeated_packedUint64_codec); + break; + } + case 754: + case 752: { + packedSint32_.AddEntriesFrom(ref input, _repeated_packedSint32_codec); + break; + } + case 762: + case 760: { + packedSint64_.AddEntriesFrom(ref input, _repeated_packedSint64_codec); + break; + } + case 770: + case 773: { + packedFixed32_.AddEntriesFrom(ref input, _repeated_packedFixed32_codec); + break; + } + case 778: + case 777: { + packedFixed64_.AddEntriesFrom(ref input, _repeated_packedFixed64_codec); + break; + } + case 786: + case 789: { + packedSfixed32_.AddEntriesFrom(ref input, _repeated_packedSfixed32_codec); + break; + } + case 794: + case 793: { + packedSfixed64_.AddEntriesFrom(ref input, _repeated_packedSfixed64_codec); + break; + } + case 802: + case 805: { + packedFloat_.AddEntriesFrom(ref input, _repeated_packedFloat_codec); + break; + } + case 810: + case 809: { + packedDouble_.AddEntriesFrom(ref input, _repeated_packedDouble_codec); + break; + } + case 818: + case 816: { + packedBool_.AddEntriesFrom(ref input, _repeated_packedBool_codec); + break; + } + case 826: + case 824: { + packedEnum_.AddEntriesFrom(ref input, _repeated_packedEnum_codec); + break; + } + } + } + } + #endif + + } + + /// + /// A message with the same fields as TestPackedTypes, but without packing. Used + /// to test packed <-> unpacked wire compatibility. + /// + public sealed partial class TestUnpackedTypes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestUnpackedTypes()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[25]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestUnpackedTypes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestUnpackedTypes(TestUnpackedTypes other) : this() { + unpackedInt32_ = other.unpackedInt32_.Clone(); + unpackedInt64_ = other.unpackedInt64_.Clone(); + unpackedUint32_ = other.unpackedUint32_.Clone(); + unpackedUint64_ = other.unpackedUint64_.Clone(); + unpackedSint32_ = other.unpackedSint32_.Clone(); + unpackedSint64_ = other.unpackedSint64_.Clone(); + unpackedFixed32_ = other.unpackedFixed32_.Clone(); + unpackedFixed64_ = other.unpackedFixed64_.Clone(); + unpackedSfixed32_ = other.unpackedSfixed32_.Clone(); + unpackedSfixed64_ = other.unpackedSfixed64_.Clone(); + unpackedFloat_ = other.unpackedFloat_.Clone(); + unpackedDouble_ = other.unpackedDouble_.Clone(); + unpackedBool_ = other.unpackedBool_.Clone(); + unpackedEnum_ = other.unpackedEnum_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestUnpackedTypes Clone() { + return new TestUnpackedTypes(this); + } + + /// Field number for the "unpacked_int32" field. + public const int UnpackedInt32FieldNumber = 90; + private static readonly pb::FieldCodec _repeated_unpackedInt32_codec + = pb::FieldCodec.ForInt32(720); + private readonly pbc::RepeatedField unpackedInt32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedInt32 { + get { return unpackedInt32_; } + } + + /// Field number for the "unpacked_int64" field. + public const int UnpackedInt64FieldNumber = 91; + private static readonly pb::FieldCodec _repeated_unpackedInt64_codec + = pb::FieldCodec.ForInt64(728); + private readonly pbc::RepeatedField unpackedInt64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedInt64 { + get { return unpackedInt64_; } + } + + /// Field number for the "unpacked_uint32" field. + public const int UnpackedUint32FieldNumber = 92; + private static readonly pb::FieldCodec _repeated_unpackedUint32_codec + = pb::FieldCodec.ForUInt32(736); + private readonly pbc::RepeatedField unpackedUint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedUint32 { + get { return unpackedUint32_; } + } + + /// Field number for the "unpacked_uint64" field. + public const int UnpackedUint64FieldNumber = 93; + private static readonly pb::FieldCodec _repeated_unpackedUint64_codec + = pb::FieldCodec.ForUInt64(744); + private readonly pbc::RepeatedField unpackedUint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedUint64 { + get { return unpackedUint64_; } + } + + /// Field number for the "unpacked_sint32" field. + public const int UnpackedSint32FieldNumber = 94; + private static readonly pb::FieldCodec _repeated_unpackedSint32_codec + = pb::FieldCodec.ForSInt32(752); + private readonly pbc::RepeatedField unpackedSint32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSint32 { + get { return unpackedSint32_; } + } + + /// Field number for the "unpacked_sint64" field. + public const int UnpackedSint64FieldNumber = 95; + private static readonly pb::FieldCodec _repeated_unpackedSint64_codec + = pb::FieldCodec.ForSInt64(760); + private readonly pbc::RepeatedField unpackedSint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSint64 { + get { return unpackedSint64_; } + } + + /// Field number for the "unpacked_fixed32" field. + public const int UnpackedFixed32FieldNumber = 96; + private static readonly pb::FieldCodec _repeated_unpackedFixed32_codec + = pb::FieldCodec.ForFixed32(773); + private readonly pbc::RepeatedField unpackedFixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedFixed32 { + get { return unpackedFixed32_; } + } + + /// Field number for the "unpacked_fixed64" field. + public const int UnpackedFixed64FieldNumber = 97; + private static readonly pb::FieldCodec _repeated_unpackedFixed64_codec + = pb::FieldCodec.ForFixed64(777); + private readonly pbc::RepeatedField unpackedFixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedFixed64 { + get { return unpackedFixed64_; } + } + + /// Field number for the "unpacked_sfixed32" field. + public const int UnpackedSfixed32FieldNumber = 98; + private static readonly pb::FieldCodec _repeated_unpackedSfixed32_codec + = pb::FieldCodec.ForSFixed32(789); + private readonly pbc::RepeatedField unpackedSfixed32_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSfixed32 { + get { return unpackedSfixed32_; } + } + + /// Field number for the "unpacked_sfixed64" field. + public const int UnpackedSfixed64FieldNumber = 99; + private static readonly pb::FieldCodec _repeated_unpackedSfixed64_codec + = pb::FieldCodec.ForSFixed64(793); + private readonly pbc::RepeatedField unpackedSfixed64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedSfixed64 { + get { return unpackedSfixed64_; } + } + + /// Field number for the "unpacked_float" field. + public const int UnpackedFloatFieldNumber = 100; + private static readonly pb::FieldCodec _repeated_unpackedFloat_codec + = pb::FieldCodec.ForFloat(805); + private readonly pbc::RepeatedField unpackedFloat_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedFloat { + get { return unpackedFloat_; } + } + + /// Field number for the "unpacked_double" field. + public const int UnpackedDoubleFieldNumber = 101; + private static readonly pb::FieldCodec _repeated_unpackedDouble_codec + = pb::FieldCodec.ForDouble(809); + private readonly pbc::RepeatedField unpackedDouble_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedDouble { + get { return unpackedDouble_; } + } + + /// Field number for the "unpacked_bool" field. + public const int UnpackedBoolFieldNumber = 102; + private static readonly pb::FieldCodec _repeated_unpackedBool_codec + = pb::FieldCodec.ForBool(816); + private readonly pbc::RepeatedField unpackedBool_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedBool { + get { return unpackedBool_; } + } + + /// Field number for the "unpacked_enum" field. + public const int UnpackedEnumFieldNumber = 103; + private static readonly pb::FieldCodec _repeated_unpackedEnum_codec + = pb::FieldCodec.ForEnum(824, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x); + private readonly pbc::RepeatedField unpackedEnum_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField UnpackedEnum { + get { return unpackedEnum_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestUnpackedTypes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestUnpackedTypes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!unpackedInt32_.Equals(other.unpackedInt32_)) return false; + if(!unpackedInt64_.Equals(other.unpackedInt64_)) return false; + if(!unpackedUint32_.Equals(other.unpackedUint32_)) return false; + if(!unpackedUint64_.Equals(other.unpackedUint64_)) return false; + if(!unpackedSint32_.Equals(other.unpackedSint32_)) return false; + if(!unpackedSint64_.Equals(other.unpackedSint64_)) return false; + if(!unpackedFixed32_.Equals(other.unpackedFixed32_)) return false; + if(!unpackedFixed64_.Equals(other.unpackedFixed64_)) return false; + if(!unpackedSfixed32_.Equals(other.unpackedSfixed32_)) return false; + if(!unpackedSfixed64_.Equals(other.unpackedSfixed64_)) return false; + if(!unpackedFloat_.Equals(other.unpackedFloat_)) return false; + if(!unpackedDouble_.Equals(other.unpackedDouble_)) return false; + if(!unpackedBool_.Equals(other.unpackedBool_)) return false; + if(!unpackedEnum_.Equals(other.unpackedEnum_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= unpackedInt32_.GetHashCode(); + hash ^= unpackedInt64_.GetHashCode(); + hash ^= unpackedUint32_.GetHashCode(); + hash ^= unpackedUint64_.GetHashCode(); + hash ^= unpackedSint32_.GetHashCode(); + hash ^= unpackedSint64_.GetHashCode(); + hash ^= unpackedFixed32_.GetHashCode(); + hash ^= unpackedFixed64_.GetHashCode(); + hash ^= unpackedSfixed32_.GetHashCode(); + hash ^= unpackedSfixed64_.GetHashCode(); + hash ^= unpackedFloat_.GetHashCode(); + hash ^= unpackedDouble_.GetHashCode(); + hash ^= unpackedBool_.GetHashCode(); + hash ^= unpackedEnum_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + unpackedInt32_.WriteTo(output, _repeated_unpackedInt32_codec); + unpackedInt64_.WriteTo(output, _repeated_unpackedInt64_codec); + unpackedUint32_.WriteTo(output, _repeated_unpackedUint32_codec); + unpackedUint64_.WriteTo(output, _repeated_unpackedUint64_codec); + unpackedSint32_.WriteTo(output, _repeated_unpackedSint32_codec); + unpackedSint64_.WriteTo(output, _repeated_unpackedSint64_codec); + unpackedFixed32_.WriteTo(output, _repeated_unpackedFixed32_codec); + unpackedFixed64_.WriteTo(output, _repeated_unpackedFixed64_codec); + unpackedSfixed32_.WriteTo(output, _repeated_unpackedSfixed32_codec); + unpackedSfixed64_.WriteTo(output, _repeated_unpackedSfixed64_codec); + unpackedFloat_.WriteTo(output, _repeated_unpackedFloat_codec); + unpackedDouble_.WriteTo(output, _repeated_unpackedDouble_codec); + unpackedBool_.WriteTo(output, _repeated_unpackedBool_codec); + unpackedEnum_.WriteTo(output, _repeated_unpackedEnum_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + unpackedInt32_.WriteTo(ref output, _repeated_unpackedInt32_codec); + unpackedInt64_.WriteTo(ref output, _repeated_unpackedInt64_codec); + unpackedUint32_.WriteTo(ref output, _repeated_unpackedUint32_codec); + unpackedUint64_.WriteTo(ref output, _repeated_unpackedUint64_codec); + unpackedSint32_.WriteTo(ref output, _repeated_unpackedSint32_codec); + unpackedSint64_.WriteTo(ref output, _repeated_unpackedSint64_codec); + unpackedFixed32_.WriteTo(ref output, _repeated_unpackedFixed32_codec); + unpackedFixed64_.WriteTo(ref output, _repeated_unpackedFixed64_codec); + unpackedSfixed32_.WriteTo(ref output, _repeated_unpackedSfixed32_codec); + unpackedSfixed64_.WriteTo(ref output, _repeated_unpackedSfixed64_codec); + unpackedFloat_.WriteTo(ref output, _repeated_unpackedFloat_codec); + unpackedDouble_.WriteTo(ref output, _repeated_unpackedDouble_codec); + unpackedBool_.WriteTo(ref output, _repeated_unpackedBool_codec); + unpackedEnum_.WriteTo(ref output, _repeated_unpackedEnum_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += unpackedInt32_.CalculateSize(_repeated_unpackedInt32_codec); + size += unpackedInt64_.CalculateSize(_repeated_unpackedInt64_codec); + size += unpackedUint32_.CalculateSize(_repeated_unpackedUint32_codec); + size += unpackedUint64_.CalculateSize(_repeated_unpackedUint64_codec); + size += unpackedSint32_.CalculateSize(_repeated_unpackedSint32_codec); + size += unpackedSint64_.CalculateSize(_repeated_unpackedSint64_codec); + size += unpackedFixed32_.CalculateSize(_repeated_unpackedFixed32_codec); + size += unpackedFixed64_.CalculateSize(_repeated_unpackedFixed64_codec); + size += unpackedSfixed32_.CalculateSize(_repeated_unpackedSfixed32_codec); + size += unpackedSfixed64_.CalculateSize(_repeated_unpackedSfixed64_codec); + size += unpackedFloat_.CalculateSize(_repeated_unpackedFloat_codec); + size += unpackedDouble_.CalculateSize(_repeated_unpackedDouble_codec); + size += unpackedBool_.CalculateSize(_repeated_unpackedBool_codec); + size += unpackedEnum_.CalculateSize(_repeated_unpackedEnum_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestUnpackedTypes other) { + if (other == null) { + return; + } + unpackedInt32_.Add(other.unpackedInt32_); + unpackedInt64_.Add(other.unpackedInt64_); + unpackedUint32_.Add(other.unpackedUint32_); + unpackedUint64_.Add(other.unpackedUint64_); + unpackedSint32_.Add(other.unpackedSint32_); + unpackedSint64_.Add(other.unpackedSint64_); + unpackedFixed32_.Add(other.unpackedFixed32_); + unpackedFixed64_.Add(other.unpackedFixed64_); + unpackedSfixed32_.Add(other.unpackedSfixed32_); + unpackedSfixed64_.Add(other.unpackedSfixed64_); + unpackedFloat_.Add(other.unpackedFloat_); + unpackedDouble_.Add(other.unpackedDouble_); + unpackedBool_.Add(other.unpackedBool_); + unpackedEnum_.Add(other.unpackedEnum_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 722: + case 720: { + unpackedInt32_.AddEntriesFrom(input, _repeated_unpackedInt32_codec); + break; + } + case 730: + case 728: { + unpackedInt64_.AddEntriesFrom(input, _repeated_unpackedInt64_codec); + break; + } + case 738: + case 736: { + unpackedUint32_.AddEntriesFrom(input, _repeated_unpackedUint32_codec); + break; + } + case 746: + case 744: { + unpackedUint64_.AddEntriesFrom(input, _repeated_unpackedUint64_codec); + break; + } + case 754: + case 752: { + unpackedSint32_.AddEntriesFrom(input, _repeated_unpackedSint32_codec); + break; + } + case 762: + case 760: { + unpackedSint64_.AddEntriesFrom(input, _repeated_unpackedSint64_codec); + break; + } + case 770: + case 773: { + unpackedFixed32_.AddEntriesFrom(input, _repeated_unpackedFixed32_codec); + break; + } + case 778: + case 777: { + unpackedFixed64_.AddEntriesFrom(input, _repeated_unpackedFixed64_codec); + break; + } + case 786: + case 789: { + unpackedSfixed32_.AddEntriesFrom(input, _repeated_unpackedSfixed32_codec); + break; + } + case 794: + case 793: { + unpackedSfixed64_.AddEntriesFrom(input, _repeated_unpackedSfixed64_codec); + break; + } + case 802: + case 805: { + unpackedFloat_.AddEntriesFrom(input, _repeated_unpackedFloat_codec); + break; + } + case 810: + case 809: { + unpackedDouble_.AddEntriesFrom(input, _repeated_unpackedDouble_codec); + break; + } + case 818: + case 816: { + unpackedBool_.AddEntriesFrom(input, _repeated_unpackedBool_codec); + break; + } + case 826: + case 824: { + unpackedEnum_.AddEntriesFrom(input, _repeated_unpackedEnum_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 722: + case 720: { + unpackedInt32_.AddEntriesFrom(ref input, _repeated_unpackedInt32_codec); + break; + } + case 730: + case 728: { + unpackedInt64_.AddEntriesFrom(ref input, _repeated_unpackedInt64_codec); + break; + } + case 738: + case 736: { + unpackedUint32_.AddEntriesFrom(ref input, _repeated_unpackedUint32_codec); + break; + } + case 746: + case 744: { + unpackedUint64_.AddEntriesFrom(ref input, _repeated_unpackedUint64_codec); + break; + } + case 754: + case 752: { + unpackedSint32_.AddEntriesFrom(ref input, _repeated_unpackedSint32_codec); + break; + } + case 762: + case 760: { + unpackedSint64_.AddEntriesFrom(ref input, _repeated_unpackedSint64_codec); + break; + } + case 770: + case 773: { + unpackedFixed32_.AddEntriesFrom(ref input, _repeated_unpackedFixed32_codec); + break; + } + case 778: + case 777: { + unpackedFixed64_.AddEntriesFrom(ref input, _repeated_unpackedFixed64_codec); + break; + } + case 786: + case 789: { + unpackedSfixed32_.AddEntriesFrom(ref input, _repeated_unpackedSfixed32_codec); + break; + } + case 794: + case 793: { + unpackedSfixed64_.AddEntriesFrom(ref input, _repeated_unpackedSfixed64_codec); + break; + } + case 802: + case 805: { + unpackedFloat_.AddEntriesFrom(ref input, _repeated_unpackedFloat_codec); + break; + } + case 810: + case 809: { + unpackedDouble_.AddEntriesFrom(ref input, _repeated_unpackedDouble_codec); + break; + } + case 818: + case 816: { + unpackedBool_.AddEntriesFrom(ref input, _repeated_unpackedBool_codec); + break; + } + case 826: + case 824: { + unpackedEnum_.AddEntriesFrom(ref input, _repeated_unpackedEnum_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestRepeatedScalarDifferentTagSizes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRepeatedScalarDifferentTagSizes()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[26]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRepeatedScalarDifferentTagSizes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRepeatedScalarDifferentTagSizes(TestRepeatedScalarDifferentTagSizes other) : this() { + repeatedFixed32_ = other.repeatedFixed32_.Clone(); + repeatedInt32_ = other.repeatedInt32_.Clone(); + repeatedFixed64_ = other.repeatedFixed64_.Clone(); + repeatedInt64_ = other.repeatedInt64_.Clone(); + repeatedFloat_ = other.repeatedFloat_.Clone(); + repeatedUint64_ = other.repeatedUint64_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestRepeatedScalarDifferentTagSizes Clone() { + return new TestRepeatedScalarDifferentTagSizes(this); + } + + /// Field number for the "repeated_fixed32" field. + public const int RepeatedFixed32FieldNumber = 12; + private static readonly pb::FieldCodec _repeated_repeatedFixed32_codec + = pb::FieldCodec.ForFixed32(98); + private readonly pbc::RepeatedField repeatedFixed32_ = new pbc::RepeatedField(); + /// + /// Parsing repeated fixed size values used to fail. This message needs to be + /// used in order to get a tag of the right size; all of the repeated fields + /// in TestAllTypes didn't trigger the check. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFixed32 { + get { return repeatedFixed32_; } + } + + /// Field number for the "repeated_int32" field. + public const int RepeatedInt32FieldNumber = 13; + private static readonly pb::FieldCodec _repeated_repeatedInt32_codec + = pb::FieldCodec.ForInt32(106); + private readonly pbc::RepeatedField repeatedInt32_ = new pbc::RepeatedField(); + /// + /// Check for a varint type, just for good measure. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt32 { + get { return repeatedInt32_; } + } + + /// Field number for the "repeated_fixed64" field. + public const int RepeatedFixed64FieldNumber = 2046; + private static readonly pb::FieldCodec _repeated_repeatedFixed64_codec + = pb::FieldCodec.ForFixed64(16370); + private readonly pbc::RepeatedField repeatedFixed64_ = new pbc::RepeatedField(); + /// + /// These have two-byte tags. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFixed64 { + get { return repeatedFixed64_; } + } + + /// Field number for the "repeated_int64" field. + public const int RepeatedInt64FieldNumber = 2047; + private static readonly pb::FieldCodec _repeated_repeatedInt64_codec + = pb::FieldCodec.ForInt64(16378); + private readonly pbc::RepeatedField repeatedInt64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedInt64 { + get { return repeatedInt64_; } + } + + /// Field number for the "repeated_float" field. + public const int RepeatedFloatFieldNumber = 262142; + private static readonly pb::FieldCodec _repeated_repeatedFloat_codec + = pb::FieldCodec.ForFloat(2097138); + private readonly pbc::RepeatedField repeatedFloat_ = new pbc::RepeatedField(); + /// + /// Three byte tags. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedFloat { + get { return repeatedFloat_; } + } + + /// Field number for the "repeated_uint64" field. + public const int RepeatedUint64FieldNumber = 262143; + private static readonly pb::FieldCodec _repeated_repeatedUint64_codec + = pb::FieldCodec.ForUInt64(2097146); + private readonly pbc::RepeatedField repeatedUint64_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField RepeatedUint64 { + get { return repeatedUint64_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestRepeatedScalarDifferentTagSizes); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestRepeatedScalarDifferentTagSizes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false; + if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false; + if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false; + if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false; + if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false; + if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= repeatedFixed32_.GetHashCode(); + hash ^= repeatedInt32_.GetHashCode(); + hash ^= repeatedFixed64_.GetHashCode(); + hash ^= repeatedInt64_.GetHashCode(); + hash ^= repeatedFloat_.GetHashCode(); + hash ^= repeatedUint64_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec); + repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec); + repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec); + repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec); + repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec); + repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec); + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec); + repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec); + repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec); + repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec); + size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec); + size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec); + size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec); + size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec); + size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestRepeatedScalarDifferentTagSizes other) { + if (other == null) { + return; + } + repeatedFixed32_.Add(other.repeatedFixed32_); + repeatedInt32_.Add(other.repeatedInt32_); + repeatedFixed64_.Add(other.repeatedFixed64_); + repeatedInt64_.Add(other.repeatedInt64_); + repeatedFloat_.Add(other.repeatedFloat_); + repeatedUint64_.Add(other.repeatedUint64_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 98: + case 101: { + repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec); + break; + } + case 106: + case 104: { + repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); + break; + } + case 16370: + case 16369: { + repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec); + break; + } + case 16378: + case 16376: { + repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec); + break; + } + case 2097138: + case 2097141: { + repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec); + break; + } + case 2097146: + case 2097144: { + repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 98: + case 101: { + repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec); + break; + } + case 106: + case 104: { + repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec); + break; + } + case 16370: + case 16369: { + repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec); + break; + } + case 16378: + case 16376: { + repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec); + break; + } + case 2097138: + case 2097141: { + repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec); + break; + } + case 2097146: + case 2097144: { + repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class TestCommentInjectionMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestCommentInjectionMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[27]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestCommentInjectionMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestCommentInjectionMessage(TestCommentInjectionMessage other) : this() { + a_ = other.a_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestCommentInjectionMessage Clone() { + return new TestCommentInjectionMessage(this); + } + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private string a_ = ""; + /// + /// */ <- This should not close the generated doc comment + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string A { + get { return a_; } + set { + a_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestCommentInjectionMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestCommentInjectionMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (A.Length != 0) hash ^= A.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (A.Length != 0) { + output.WriteRawTag(10); + output.WriteString(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (A.Length != 0) { + output.WriteRawTag(10); + output.WriteString(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (A.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(A); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestCommentInjectionMessage other) { + if (other == null) { + return; + } + if (other.A.Length != 0) { + A = other.A; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + A = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + A = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// Test that RPC services work. + /// + public sealed partial class FooRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[28]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooRequest(FooRequest other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooRequest Clone() { + return new FooRequest(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FooRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FooRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FooRequest other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class FooResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[29]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooResponse(FooResponse other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooResponse Clone() { + return new FooResponse(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FooResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FooResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FooResponse other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class FooClientMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooClientMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[30]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooClientMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooClientMessage(FooClientMessage other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooClientMessage Clone() { + return new FooClientMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FooClientMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FooClientMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FooClientMessage other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class FooServerMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooServerMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[31]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooServerMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooServerMessage(FooServerMessage other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooServerMessage Clone() { + return new FooServerMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FooServerMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FooServerMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FooServerMessage other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class BarRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BarRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[32]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BarRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BarRequest(BarRequest other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BarRequest Clone() { + return new BarRequest(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as BarRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(BarRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(BarRequest other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class BarResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BarResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[33]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BarResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BarResponse(BarResponse other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BarResponse Clone() { + return new BarResponse(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as BarResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(BarResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(BarResponse other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + public sealed partial class TestEmptyMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestEmptyMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[34]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEmptyMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEmptyMessage(TestEmptyMessage other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestEmptyMessage Clone() { + return new TestEmptyMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestEmptyMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestEmptyMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestEmptyMessage other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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; + } + } + } + #endif + + } + + /// + /// This is a leading comment + /// + public sealed partial class CommentMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CommentMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[35]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CommentMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CommentMessage(CommentMessage other) : this() { + text_ = other.text_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CommentMessage Clone() { + return new CommentMessage(this); + } + + /// Field number for the "text" field. + public const int TextFieldNumber = 1; + private string text_ = ""; + /// + /// Leading field comment + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Text { + get { return text_; } + set { + text_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CommentMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CommentMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Text != other.Text) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Text.Length != 0) hash ^= Text.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Text.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Text); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Text.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Text); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Text.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Text); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CommentMessage other) { + if (other == null) { + return; + } + if (other.Text.Length != 0) { + Text = other.Text; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Text = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Text = input.ReadString(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the CommentMessage message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + /// + /// Leading nested enum comment + /// + public enum NestedCommentEnum { + /// + /// Zero value comment + /// + [pbr::OriginalName("ZERO_VALUE")] ZeroValue = 0, + } + + /// + /// Leading nested message comment + /// + public sealed partial class NestedCommentMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedCommentMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.CommentMessage.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedCommentMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedCommentMessage(NestedCommentMessage other) : this() { + nestedText_ = other.nestedText_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedCommentMessage Clone() { + return new NestedCommentMessage(this); + } + + /// Field number for the "nested_text" field. + public const int NestedTextFieldNumber = 1; + private string nestedText_ = ""; + /// + /// Leading nested message field comment + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string NestedText { + get { return nestedText_; } + set { + nestedText_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedCommentMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedCommentMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (NestedText != other.NestedText) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (NestedText.Length != 0) hash ^= NestedText.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (NestedText.Length != 0) { + output.WriteRawTag(10); + output.WriteString(NestedText); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (NestedText.Length != 0) { + output.WriteRawTag(10); + output.WriteString(NestedText); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (NestedText.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(NestedText); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedCommentMessage other) { + if (other == null) { + return; + } + if (other.NestedText.Length != 0) { + NestedText = other.NestedText; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + NestedText = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + NestedText = input.ReadString(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs new file mode 100644 index 0000000000000..7d3a238eb4100 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs @@ -0,0 +1,1796 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/unittest_proto3_optional.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace ProtobufUnittest { + + /// Holder for reflection information generated from google/protobuf/unittest_proto3_optional.proto + public static partial class UnittestProto3OptionalReflection { + + #region Descriptor + /// File descriptor for google/protobuf/unittest_proto3_optional.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestProto3OptionalReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Ci5nb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfcHJvdG8zX29wdGlvbmFsLnBy", + "b3RvEhFwcm90b2J1Zl91bml0dGVzdCKxCgoSVGVzdFByb3RvM09wdGlvbmFs", + "EhsKDm9wdGlvbmFsX2ludDMyGAEgASgFSACIAQESGwoOb3B0aW9uYWxfaW50", + "NjQYAiABKANIAYgBARIcCg9vcHRpb25hbF91aW50MzIYAyABKA1IAogBARIc", + "Cg9vcHRpb25hbF91aW50NjQYBCABKARIA4gBARIcCg9vcHRpb25hbF9zaW50", + "MzIYBSABKBFIBIgBARIcCg9vcHRpb25hbF9zaW50NjQYBiABKBJIBYgBARId", + "ChBvcHRpb25hbF9maXhlZDMyGAcgASgHSAaIAQESHQoQb3B0aW9uYWxfZml4", + "ZWQ2NBgIIAEoBkgHiAEBEh4KEW9wdGlvbmFsX3NmaXhlZDMyGAkgASgPSAiI", + "AQESHgoRb3B0aW9uYWxfc2ZpeGVkNjQYCiABKBBICYgBARIbCg5vcHRpb25h", + "bF9mbG9hdBgLIAEoAkgKiAEBEhwKD29wdGlvbmFsX2RvdWJsZRgMIAEoAUgL", + "iAEBEhoKDW9wdGlvbmFsX2Jvb2wYDSABKAhIDIgBARIcCg9vcHRpb25hbF9z", + "dHJpbmcYDiABKAlIDYgBARIbCg5vcHRpb25hbF9ieXRlcxgPIAEoDEgOiAEB", + "Eh4KDW9wdGlvbmFsX2NvcmQYECABKAlCAggBSA+IAQESWQoXb3B0aW9uYWxf", + "bmVzdGVkX21lc3NhZ2UYEiABKAsyMy5wcm90b2J1Zl91bml0dGVzdC5UZXN0", + "UHJvdG8zT3B0aW9uYWwuTmVzdGVkTWVzc2FnZUgQiAEBElkKE2xhenlfbmVz", + "dGVkX21lc3NhZ2UYEyABKAsyMy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UHJv", + "dG8zT3B0aW9uYWwuTmVzdGVkTWVzc2FnZUICKAFIEYgBARJTChRvcHRpb25h", + "bF9uZXN0ZWRfZW51bRgVIAEoDjIwLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQ", + "cm90bzNPcHRpb25hbC5OZXN0ZWRFbnVtSBKIAQESFgoOc2luZ3VsYXJfaW50", + "MzIYFiABKAUSFgoOc2luZ3VsYXJfaW50NjQYFyABKAMaJwoNTmVzdGVkTWVz", + "c2FnZRIPCgJiYhgBIAEoBUgAiAEBQgUKA19iYiJKCgpOZXN0ZWRFbnVtEg8K", + "C1VOU1BFQ0lGSUVEEAASBwoDRk9PEAESBwoDQkFSEAISBwoDQkFaEAMSEAoD", + "TkVHEP///////////wFCEQoPX29wdGlvbmFsX2ludDMyQhEKD19vcHRpb25h", + "bF9pbnQ2NEISChBfb3B0aW9uYWxfdWludDMyQhIKEF9vcHRpb25hbF91aW50", + "NjRCEgoQX29wdGlvbmFsX3NpbnQzMkISChBfb3B0aW9uYWxfc2ludDY0QhMK", + "EV9vcHRpb25hbF9maXhlZDMyQhMKEV9vcHRpb25hbF9maXhlZDY0QhQKEl9v", + "cHRpb25hbF9zZml4ZWQzMkIUChJfb3B0aW9uYWxfc2ZpeGVkNjRCEQoPX29w", + "dGlvbmFsX2Zsb2F0QhIKEF9vcHRpb25hbF9kb3VibGVCEAoOX29wdGlvbmFs", + "X2Jvb2xCEgoQX29wdGlvbmFsX3N0cmluZ0IRCg9fb3B0aW9uYWxfYnl0ZXNC", + "EAoOX29wdGlvbmFsX2NvcmRCGgoYX29wdGlvbmFsX25lc3RlZF9tZXNzYWdl", + "QhYKFF9sYXp5X25lc3RlZF9tZXNzYWdlQhcKFV9vcHRpb25hbF9uZXN0ZWRf", + "ZW51bSKJAgoZVGVzdFByb3RvM09wdGlvbmFsTWVzc2FnZRJSCg5uZXN0ZWRf", + "bWVzc2FnZRgBIAEoCzI6LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQcm90bzNP", + "cHRpb25hbE1lc3NhZ2UuTmVzdGVkTWVzc2FnZRJgChdvcHRpb25hbF9uZXN0", + "ZWRfbWVzc2FnZRgCIAEoCzI6LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQcm90", + "bzNPcHRpb25hbE1lc3NhZ2UuTmVzdGVkTWVzc2FnZUgAiAEBGhoKDU5lc3Rl", + "ZE1lc3NhZ2USCQoBcxgBIAEoCUIaChhfb3B0aW9uYWxfbmVzdGVkX21lc3Nh", + "Z2VCJQohY29tLmdvb2dsZS5wcm90b2J1Zi50ZXN0aW5nLnByb3RvUAFiBnBy", + "b3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3Optional), global::ProtobufUnittest.TestProto3Optional.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalCord", "OptionalNestedMessage", "LazyNestedMessage", "OptionalNestedEnum", "SingularInt32", "SingularInt64" }, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalCord", "OptionalNestedMessage", "LazyNestedMessage", "OptionalNestedEnum" }, new[]{ typeof(global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage), global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage.Parser, new[]{ "Bb" }, new[]{ "Bb" }, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3OptionalMessage), global::ProtobufUnittest.TestProto3OptionalMessage.Parser, new[]{ "NestedMessage", "OptionalNestedMessage" }, new[]{ "OptionalNestedMessage" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage), global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage.Parser, new[]{ "S" }, null, null, null, null)}) + })); + } + #endregion + + } + #region Messages + public sealed partial class TestProto3Optional : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestProto3Optional()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufUnittest.UnittestProto3OptionalReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestProto3Optional() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestProto3Optional(TestProto3Optional other) : this() { + _hasBits0 = other._hasBits0; + optionalInt32_ = other.optionalInt32_; + optionalInt64_ = other.optionalInt64_; + optionalUint32_ = other.optionalUint32_; + optionalUint64_ = other.optionalUint64_; + optionalSint32_ = other.optionalSint32_; + optionalSint64_ = other.optionalSint64_; + optionalFixed32_ = other.optionalFixed32_; + optionalFixed64_ = other.optionalFixed64_; + optionalSfixed32_ = other.optionalSfixed32_; + optionalSfixed64_ = other.optionalSfixed64_; + optionalFloat_ = other.optionalFloat_; + optionalDouble_ = other.optionalDouble_; + optionalBool_ = other.optionalBool_; + optionalString_ = other.optionalString_; + optionalBytes_ = other.optionalBytes_; + optionalCord_ = other.optionalCord_; + optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null; + lazyNestedMessage_ = other.lazyNestedMessage_ != null ? other.lazyNestedMessage_.Clone() : null; + optionalNestedEnum_ = other.optionalNestedEnum_; + singularInt32_ = other.singularInt32_; + singularInt64_ = other.singularInt64_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestProto3Optional Clone() { + return new TestProto3Optional(this); + } + + /// Field number for the "optional_int32" field. + public const int OptionalInt32FieldNumber = 1; + private int optionalInt32_; + /// + /// Singular + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalInt32 { + get { if ((_hasBits0 & 1) != 0) { return optionalInt32_; } else { return 0; } } + set { + _hasBits0 |= 1; + optionalInt32_ = value; + } + } + /// Gets whether the "optional_int32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalInt32 { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "optional_int32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalInt32() { + _hasBits0 &= ~1; + } + + /// Field number for the "optional_int64" field. + public const int OptionalInt64FieldNumber = 2; + private long optionalInt64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalInt64 { + get { if ((_hasBits0 & 2) != 0) { return optionalInt64_; } else { return 0L; } } + set { + _hasBits0 |= 2; + optionalInt64_ = value; + } + } + /// Gets whether the "optional_int64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalInt64 { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "optional_int64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalInt64() { + _hasBits0 &= ~2; + } + + /// Field number for the "optional_uint32" field. + public const int OptionalUint32FieldNumber = 3; + private uint optionalUint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OptionalUint32 { + get { if ((_hasBits0 & 4) != 0) { return optionalUint32_; } else { return 0; } } + set { + _hasBits0 |= 4; + optionalUint32_ = value; + } + } + /// Gets whether the "optional_uint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalUint32 { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "optional_uint32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalUint32() { + _hasBits0 &= ~4; + } + + /// Field number for the "optional_uint64" field. + public const int OptionalUint64FieldNumber = 4; + private ulong optionalUint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong OptionalUint64 { + get { if ((_hasBits0 & 8) != 0) { return optionalUint64_; } else { return 0UL; } } + set { + _hasBits0 |= 8; + optionalUint64_ = value; + } + } + /// Gets whether the "optional_uint64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalUint64 { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "optional_uint64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalUint64() { + _hasBits0 &= ~8; + } + + /// Field number for the "optional_sint32" field. + public const int OptionalSint32FieldNumber = 5; + private int optionalSint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalSint32 { + get { if ((_hasBits0 & 16) != 0) { return optionalSint32_; } else { return 0; } } + set { + _hasBits0 |= 16; + optionalSint32_ = value; + } + } + /// Gets whether the "optional_sint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSint32 { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "optional_sint32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSint32() { + _hasBits0 &= ~16; + } + + /// Field number for the "optional_sint64" field. + public const int OptionalSint64FieldNumber = 6; + private long optionalSint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalSint64 { + get { if ((_hasBits0 & 32) != 0) { return optionalSint64_; } else { return 0L; } } + set { + _hasBits0 |= 32; + optionalSint64_ = value; + } + } + /// Gets whether the "optional_sint64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSint64 { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "optional_sint64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSint64() { + _hasBits0 &= ~32; + } + + /// Field number for the "optional_fixed32" field. + public const int OptionalFixed32FieldNumber = 7; + private uint optionalFixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OptionalFixed32 { + get { if ((_hasBits0 & 64) != 0) { return optionalFixed32_; } else { return 0; } } + set { + _hasBits0 |= 64; + optionalFixed32_ = value; + } + } + /// Gets whether the "optional_fixed32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalFixed32 { + get { return (_hasBits0 & 64) != 0; } + } + /// Clears the value of the "optional_fixed32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalFixed32() { + _hasBits0 &= ~64; + } + + /// Field number for the "optional_fixed64" field. + public const int OptionalFixed64FieldNumber = 8; + private ulong optionalFixed64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong OptionalFixed64 { + get { if ((_hasBits0 & 128) != 0) { return optionalFixed64_; } else { return 0UL; } } + set { + _hasBits0 |= 128; + optionalFixed64_ = value; + } + } + /// Gets whether the "optional_fixed64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalFixed64 { + get { return (_hasBits0 & 128) != 0; } + } + /// Clears the value of the "optional_fixed64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalFixed64() { + _hasBits0 &= ~128; + } + + /// Field number for the "optional_sfixed32" field. + public const int OptionalSfixed32FieldNumber = 9; + private int optionalSfixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalSfixed32 { + get { if ((_hasBits0 & 256) != 0) { return optionalSfixed32_; } else { return 0; } } + set { + _hasBits0 |= 256; + optionalSfixed32_ = value; + } + } + /// Gets whether the "optional_sfixed32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSfixed32 { + get { return (_hasBits0 & 256) != 0; } + } + /// Clears the value of the "optional_sfixed32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSfixed32() { + _hasBits0 &= ~256; + } + + /// Field number for the "optional_sfixed64" field. + public const int OptionalSfixed64FieldNumber = 10; + private long optionalSfixed64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalSfixed64 { + get { if ((_hasBits0 & 512) != 0) { return optionalSfixed64_; } else { return 0L; } } + set { + _hasBits0 |= 512; + optionalSfixed64_ = value; + } + } + /// Gets whether the "optional_sfixed64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSfixed64 { + get { return (_hasBits0 & 512) != 0; } + } + /// Clears the value of the "optional_sfixed64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSfixed64() { + _hasBits0 &= ~512; + } + + /// Field number for the "optional_float" field. + public const int OptionalFloatFieldNumber = 11; + private float optionalFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float OptionalFloat { + get { if ((_hasBits0 & 1024) != 0) { return optionalFloat_; } else { return 0F; } } + set { + _hasBits0 |= 1024; + optionalFloat_ = value; + } + } + /// Gets whether the "optional_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalFloat { + get { return (_hasBits0 & 1024) != 0; } + } + /// Clears the value of the "optional_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalFloat() { + _hasBits0 &= ~1024; + } + + /// Field number for the "optional_double" field. + public const int OptionalDoubleFieldNumber = 12; + private double optionalDouble_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double OptionalDouble { + get { if ((_hasBits0 & 2048) != 0) { return optionalDouble_; } else { return 0D; } } + set { + _hasBits0 |= 2048; + optionalDouble_ = value; + } + } + /// Gets whether the "optional_double" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalDouble { + get { return (_hasBits0 & 2048) != 0; } + } + /// Clears the value of the "optional_double" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalDouble() { + _hasBits0 &= ~2048; + } + + /// Field number for the "optional_bool" field. + public const int OptionalBoolFieldNumber = 13; + private bool optionalBool_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool OptionalBool { + get { if ((_hasBits0 & 4096) != 0) { return optionalBool_; } else { return false; } } + set { + _hasBits0 |= 4096; + optionalBool_ = value; + } + } + /// Gets whether the "optional_bool" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalBool { + get { return (_hasBits0 & 4096) != 0; } + } + /// Clears the value of the "optional_bool" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalBool() { + _hasBits0 &= ~4096; + } + + /// Field number for the "optional_string" field. + public const int OptionalStringFieldNumber = 14; + private string optionalString_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalString { + get { return optionalString_ ?? ""; } + set { + optionalString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalString { + get { return optionalString_ != null; } + } + /// Clears the value of the "optional_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalString() { + optionalString_ = null; + } + + /// Field number for the "optional_bytes" field. + public const int OptionalBytesFieldNumber = 15; + private pb::ByteString optionalBytes_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString OptionalBytes { + get { return optionalBytes_ ?? pb::ByteString.Empty; } + set { + optionalBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_bytes" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalBytes { + get { return optionalBytes_ != null; } + } + /// Clears the value of the "optional_bytes" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalBytes() { + optionalBytes_ = null; + } + + /// Field number for the "optional_cord" field. + public const int OptionalCordFieldNumber = 16; + private string optionalCord_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalCord { + get { return optionalCord_ ?? ""; } + set { + optionalCord_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_cord" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalCord { + get { return optionalCord_ != null; } + } + /// Clears the value of the "optional_cord" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalCord() { + optionalCord_ = null; + } + + /// Field number for the "optional_nested_message" field. + public const int OptionalNestedMessageFieldNumber = 18; + private global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage optionalNestedMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage OptionalNestedMessage { + get { return optionalNestedMessage_; } + set { + optionalNestedMessage_ = value; + } + } + + /// Field number for the "lazy_nested_message" field. + public const int LazyNestedMessageFieldNumber = 19; + private global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage lazyNestedMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage LazyNestedMessage { + get { return lazyNestedMessage_; } + set { + lazyNestedMessage_ = value; + } + } + + /// Field number for the "optional_nested_enum" field. + public const int OptionalNestedEnumFieldNumber = 21; + private global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum optionalNestedEnum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum OptionalNestedEnum { + get { if ((_hasBits0 & 8192) != 0) { return optionalNestedEnum_; } else { return global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum.Unspecified; } } + set { + _hasBits0 |= 8192; + optionalNestedEnum_ = value; + } + } + /// Gets whether the "optional_nested_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalNestedEnum { + get { return (_hasBits0 & 8192) != 0; } + } + /// Clears the value of the "optional_nested_enum" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalNestedEnum() { + _hasBits0 &= ~8192; + } + + /// Field number for the "singular_int32" field. + public const int SingularInt32FieldNumber = 22; + private int singularInt32_; + /// + /// Add some non-optional fields to verify we can mix them. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int SingularInt32 { + get { return singularInt32_; } + set { + singularInt32_ = value; + } + } + + /// Field number for the "singular_int64" field. + public const int SingularInt64FieldNumber = 23; + private long singularInt64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long SingularInt64 { + get { return singularInt64_; } + set { + singularInt64_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestProto3Optional); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestProto3Optional other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (OptionalInt32 != other.OptionalInt32) return false; + if (OptionalInt64 != other.OptionalInt64) return false; + if (OptionalUint32 != other.OptionalUint32) return false; + if (OptionalUint64 != other.OptionalUint64) return false; + if (OptionalSint32 != other.OptionalSint32) return false; + if (OptionalSint64 != other.OptionalSint64) return false; + if (OptionalFixed32 != other.OptionalFixed32) return false; + if (OptionalFixed64 != other.OptionalFixed64) return false; + if (OptionalSfixed32 != other.OptionalSfixed32) return false; + if (OptionalSfixed64 != other.OptionalSfixed64) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(OptionalFloat, other.OptionalFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OptionalDouble, other.OptionalDouble)) return false; + if (OptionalBool != other.OptionalBool) return false; + if (OptionalString != other.OptionalString) return false; + if (OptionalBytes != other.OptionalBytes) return false; + if (OptionalCord != other.OptionalCord) return false; + if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false; + if (!object.Equals(LazyNestedMessage, other.LazyNestedMessage)) return false; + if (OptionalNestedEnum != other.OptionalNestedEnum) return false; + if (SingularInt32 != other.SingularInt32) return false; + if (SingularInt64 != other.SingularInt64) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasOptionalInt32) hash ^= OptionalInt32.GetHashCode(); + if (HasOptionalInt64) hash ^= OptionalInt64.GetHashCode(); + if (HasOptionalUint32) hash ^= OptionalUint32.GetHashCode(); + if (HasOptionalUint64) hash ^= OptionalUint64.GetHashCode(); + if (HasOptionalSint32) hash ^= OptionalSint32.GetHashCode(); + if (HasOptionalSint64) hash ^= OptionalSint64.GetHashCode(); + if (HasOptionalFixed32) hash ^= OptionalFixed32.GetHashCode(); + if (HasOptionalFixed64) hash ^= OptionalFixed64.GetHashCode(); + if (HasOptionalSfixed32) hash ^= OptionalSfixed32.GetHashCode(); + if (HasOptionalSfixed64) hash ^= OptionalSfixed64.GetHashCode(); + if (HasOptionalFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(OptionalFloat); + if (HasOptionalDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OptionalDouble); + if (HasOptionalBool) hash ^= OptionalBool.GetHashCode(); + if (HasOptionalString) hash ^= OptionalString.GetHashCode(); + if (HasOptionalBytes) hash ^= OptionalBytes.GetHashCode(); + if (HasOptionalCord) hash ^= OptionalCord.GetHashCode(); + if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode(); + if (lazyNestedMessage_ != null) hash ^= LazyNestedMessage.GetHashCode(); + if (HasOptionalNestedEnum) hash ^= OptionalNestedEnum.GetHashCode(); + if (SingularInt32 != 0) hash ^= SingularInt32.GetHashCode(); + if (SingularInt64 != 0L) hash ^= SingularInt64.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasOptionalInt32) { + output.WriteRawTag(8); + output.WriteInt32(OptionalInt32); + } + if (HasOptionalInt64) { + output.WriteRawTag(16); + output.WriteInt64(OptionalInt64); + } + if (HasOptionalUint32) { + output.WriteRawTag(24); + output.WriteUInt32(OptionalUint32); + } + if (HasOptionalUint64) { + output.WriteRawTag(32); + output.WriteUInt64(OptionalUint64); + } + if (HasOptionalSint32) { + output.WriteRawTag(40); + output.WriteSInt32(OptionalSint32); + } + if (HasOptionalSint64) { + output.WriteRawTag(48); + output.WriteSInt64(OptionalSint64); + } + if (HasOptionalFixed32) { + output.WriteRawTag(61); + output.WriteFixed32(OptionalFixed32); + } + if (HasOptionalFixed64) { + output.WriteRawTag(65); + output.WriteFixed64(OptionalFixed64); + } + if (HasOptionalSfixed32) { + output.WriteRawTag(77); + output.WriteSFixed32(OptionalSfixed32); + } + if (HasOptionalSfixed64) { + output.WriteRawTag(81); + output.WriteSFixed64(OptionalSfixed64); + } + if (HasOptionalFloat) { + output.WriteRawTag(93); + output.WriteFloat(OptionalFloat); + } + if (HasOptionalDouble) { + output.WriteRawTag(97); + output.WriteDouble(OptionalDouble); + } + if (HasOptionalBool) { + output.WriteRawTag(104); + output.WriteBool(OptionalBool); + } + if (HasOptionalString) { + output.WriteRawTag(114); + output.WriteString(OptionalString); + } + if (HasOptionalBytes) { + output.WriteRawTag(122); + output.WriteBytes(OptionalBytes); + } + if (HasOptionalCord) { + output.WriteRawTag(130, 1); + output.WriteString(OptionalCord); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(OptionalNestedMessage); + } + if (lazyNestedMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(LazyNestedMessage); + } + if (HasOptionalNestedEnum) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) OptionalNestedEnum); + } + if (SingularInt32 != 0) { + output.WriteRawTag(176, 1); + output.WriteInt32(SingularInt32); + } + if (SingularInt64 != 0L) { + output.WriteRawTag(184, 1); + output.WriteInt64(SingularInt64); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasOptionalInt32) { + output.WriteRawTag(8); + output.WriteInt32(OptionalInt32); + } + if (HasOptionalInt64) { + output.WriteRawTag(16); + output.WriteInt64(OptionalInt64); + } + if (HasOptionalUint32) { + output.WriteRawTag(24); + output.WriteUInt32(OptionalUint32); + } + if (HasOptionalUint64) { + output.WriteRawTag(32); + output.WriteUInt64(OptionalUint64); + } + if (HasOptionalSint32) { + output.WriteRawTag(40); + output.WriteSInt32(OptionalSint32); + } + if (HasOptionalSint64) { + output.WriteRawTag(48); + output.WriteSInt64(OptionalSint64); + } + if (HasOptionalFixed32) { + output.WriteRawTag(61); + output.WriteFixed32(OptionalFixed32); + } + if (HasOptionalFixed64) { + output.WriteRawTag(65); + output.WriteFixed64(OptionalFixed64); + } + if (HasOptionalSfixed32) { + output.WriteRawTag(77); + output.WriteSFixed32(OptionalSfixed32); + } + if (HasOptionalSfixed64) { + output.WriteRawTag(81); + output.WriteSFixed64(OptionalSfixed64); + } + if (HasOptionalFloat) { + output.WriteRawTag(93); + output.WriteFloat(OptionalFloat); + } + if (HasOptionalDouble) { + output.WriteRawTag(97); + output.WriteDouble(OptionalDouble); + } + if (HasOptionalBool) { + output.WriteRawTag(104); + output.WriteBool(OptionalBool); + } + if (HasOptionalString) { + output.WriteRawTag(114); + output.WriteString(OptionalString); + } + if (HasOptionalBytes) { + output.WriteRawTag(122); + output.WriteBytes(OptionalBytes); + } + if (HasOptionalCord) { + output.WriteRawTag(130, 1); + output.WriteString(OptionalCord); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(OptionalNestedMessage); + } + if (lazyNestedMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(LazyNestedMessage); + } + if (HasOptionalNestedEnum) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) OptionalNestedEnum); + } + if (SingularInt32 != 0) { + output.WriteRawTag(176, 1); + output.WriteInt32(SingularInt32); + } + if (SingularInt64 != 0L) { + output.WriteRawTag(184, 1); + output.WriteInt64(SingularInt64); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasOptionalInt32) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32); + } + if (HasOptionalInt64) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(OptionalInt64); + } + if (HasOptionalUint32) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(OptionalUint32); + } + if (HasOptionalUint64) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(OptionalUint64); + } + if (HasOptionalSint32) { + size += 1 + pb::CodedOutputStream.ComputeSInt32Size(OptionalSint32); + } + if (HasOptionalSint64) { + size += 1 + pb::CodedOutputStream.ComputeSInt64Size(OptionalSint64); + } + if (HasOptionalFixed32) { + size += 1 + 4; + } + if (HasOptionalFixed64) { + size += 1 + 8; + } + if (HasOptionalSfixed32) { + size += 1 + 4; + } + if (HasOptionalSfixed64) { + size += 1 + 8; + } + if (HasOptionalFloat) { + size += 1 + 4; + } + if (HasOptionalDouble) { + size += 1 + 8; + } + if (HasOptionalBool) { + size += 1 + 1; + } + if (HasOptionalString) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(OptionalString); + } + if (HasOptionalBytes) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(OptionalBytes); + } + if (HasOptionalCord) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalCord); + } + if (optionalNestedMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage); + } + if (lazyNestedMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(LazyNestedMessage); + } + if (HasOptionalNestedEnum) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalNestedEnum); + } + if (SingularInt32 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(SingularInt32); + } + if (SingularInt64 != 0L) { + size += 2 + pb::CodedOutputStream.ComputeInt64Size(SingularInt64); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestProto3Optional other) { + if (other == null) { + return; + } + if (other.HasOptionalInt32) { + OptionalInt32 = other.OptionalInt32; + } + if (other.HasOptionalInt64) { + OptionalInt64 = other.OptionalInt64; + } + if (other.HasOptionalUint32) { + OptionalUint32 = other.OptionalUint32; + } + if (other.HasOptionalUint64) { + OptionalUint64 = other.OptionalUint64; + } + if (other.HasOptionalSint32) { + OptionalSint32 = other.OptionalSint32; + } + if (other.HasOptionalSint64) { + OptionalSint64 = other.OptionalSint64; + } + if (other.HasOptionalFixed32) { + OptionalFixed32 = other.OptionalFixed32; + } + if (other.HasOptionalFixed64) { + OptionalFixed64 = other.OptionalFixed64; + } + if (other.HasOptionalSfixed32) { + OptionalSfixed32 = other.OptionalSfixed32; + } + if (other.HasOptionalSfixed64) { + OptionalSfixed64 = other.OptionalSfixed64; + } + if (other.HasOptionalFloat) { + OptionalFloat = other.OptionalFloat; + } + if (other.HasOptionalDouble) { + OptionalDouble = other.OptionalDouble; + } + if (other.HasOptionalBool) { + OptionalBool = other.OptionalBool; + } + if (other.HasOptionalString) { + OptionalString = other.OptionalString; + } + if (other.HasOptionalBytes) { + OptionalBytes = other.OptionalBytes; + } + if (other.HasOptionalCord) { + OptionalCord = other.OptionalCord; + } + if (other.optionalNestedMessage_ != null) { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage(); + } + OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage); + } + if (other.lazyNestedMessage_ != null) { + if (lazyNestedMessage_ == null) { + LazyNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage(); + } + LazyNestedMessage.MergeFrom(other.LazyNestedMessage); + } + if (other.HasOptionalNestedEnum) { + OptionalNestedEnum = other.OptionalNestedEnum; + } + if (other.SingularInt32 != 0) { + SingularInt32 = other.SingularInt32; + } + if (other.SingularInt64 != 0L) { + SingularInt64 = other.SingularInt64; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + OptionalInt32 = input.ReadInt32(); + break; + } + case 16: { + OptionalInt64 = input.ReadInt64(); + break; + } + case 24: { + OptionalUint32 = input.ReadUInt32(); + break; + } + case 32: { + OptionalUint64 = input.ReadUInt64(); + break; + } + case 40: { + OptionalSint32 = input.ReadSInt32(); + break; + } + case 48: { + OptionalSint64 = input.ReadSInt64(); + break; + } + case 61: { + OptionalFixed32 = input.ReadFixed32(); + break; + } + case 65: { + OptionalFixed64 = input.ReadFixed64(); + break; + } + case 77: { + OptionalSfixed32 = input.ReadSFixed32(); + break; + } + case 81: { + OptionalSfixed64 = input.ReadSFixed64(); + break; + } + case 93: { + OptionalFloat = input.ReadFloat(); + break; + } + case 97: { + OptionalDouble = input.ReadDouble(); + break; + } + case 104: { + OptionalBool = input.ReadBool(); + break; + } + case 114: { + OptionalString = input.ReadString(); + break; + } + case 122: { + OptionalBytes = input.ReadBytes(); + break; + } + case 130: { + OptionalCord = input.ReadString(); + break; + } + case 146: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + case 154: { + if (lazyNestedMessage_ == null) { + LazyNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage(); + } + input.ReadMessage(LazyNestedMessage); + break; + } + case 168: { + OptionalNestedEnum = (global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum) input.ReadEnum(); + break; + } + case 176: { + SingularInt32 = input.ReadInt32(); + break; + } + case 184: { + SingularInt64 = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + OptionalInt32 = input.ReadInt32(); + break; + } + case 16: { + OptionalInt64 = input.ReadInt64(); + break; + } + case 24: { + OptionalUint32 = input.ReadUInt32(); + break; + } + case 32: { + OptionalUint64 = input.ReadUInt64(); + break; + } + case 40: { + OptionalSint32 = input.ReadSInt32(); + break; + } + case 48: { + OptionalSint64 = input.ReadSInt64(); + break; + } + case 61: { + OptionalFixed32 = input.ReadFixed32(); + break; + } + case 65: { + OptionalFixed64 = input.ReadFixed64(); + break; + } + case 77: { + OptionalSfixed32 = input.ReadSFixed32(); + break; + } + case 81: { + OptionalSfixed64 = input.ReadSFixed64(); + break; + } + case 93: { + OptionalFloat = input.ReadFloat(); + break; + } + case 97: { + OptionalDouble = input.ReadDouble(); + break; + } + case 104: { + OptionalBool = input.ReadBool(); + break; + } + case 114: { + OptionalString = input.ReadString(); + break; + } + case 122: { + OptionalBytes = input.ReadBytes(); + break; + } + case 130: { + OptionalCord = input.ReadString(); + break; + } + case 146: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + case 154: { + if (lazyNestedMessage_ == null) { + LazyNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage(); + } + input.ReadMessage(LazyNestedMessage); + break; + } + case 168: { + OptionalNestedEnum = (global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum) input.ReadEnum(); + break; + } + case 176: { + SingularInt32 = input.ReadInt32(); + break; + } + case 184: { + SingularInt64 = input.ReadInt64(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestProto3Optional message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum NestedEnum { + [pbr::OriginalName("UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("FOO")] Foo = 1, + [pbr::OriginalName("BAR")] Bar = 2, + [pbr::OriginalName("BAZ")] Baz = 3, + /// + /// Intentionally negative. + /// + [pbr::OriginalName("NEG")] Neg = -1, + } + + public sealed partial class NestedMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufUnittest.TestProto3Optional.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + _hasBits0 = other._hasBits0; + bb_ = other.bb_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "bb" field. + public const int BbFieldNumber = 1; + private int bb_; + /// + /// The field name "b" fails to compile in proto1 because it conflicts with + /// a local variable named "b" in one of the generated methods. Doh. + /// This file needs to compile in proto1 to test backwards-compatibility. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Bb { + get { if ((_hasBits0 & 1) != 0) { return bb_; } else { return 0; } } + set { + _hasBits0 |= 1; + bb_ = value; + } + } + /// Gets whether the "bb" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBb { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "bb" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBb() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Bb != other.Bb) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasBb) hash ^= Bb.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasBb) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasBb) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasBb) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Bb); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.HasBb) { + Bb = other.Bb; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Bb = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Bb = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + public sealed partial class TestProto3OptionalMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestProto3OptionalMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufUnittest.UnittestProto3OptionalReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestProto3OptionalMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestProto3OptionalMessage(TestProto3OptionalMessage other) : this() { + nestedMessage_ = other.nestedMessage_ != null ? other.nestedMessage_.Clone() : null; + optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestProto3OptionalMessage Clone() { + return new TestProto3OptionalMessage(this); + } + + /// Field number for the "nested_message" field. + public const int NestedMessageFieldNumber = 1; + private global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage nestedMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage NestedMessage { + get { return nestedMessage_; } + set { + nestedMessage_ = value; + } + } + + /// Field number for the "optional_nested_message" field. + public const int OptionalNestedMessageFieldNumber = 2; + private global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage optionalNestedMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage OptionalNestedMessage { + get { return optionalNestedMessage_; } + set { + optionalNestedMessage_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestProto3OptionalMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestProto3OptionalMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(NestedMessage, other.NestedMessage)) return false; + if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (nestedMessage_ != null) hash ^= NestedMessage.GetHashCode(); + if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (nestedMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(NestedMessage); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(18); + output.WriteMessage(OptionalNestedMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (nestedMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(NestedMessage); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(18); + output.WriteMessage(OptionalNestedMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (nestedMessage_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(NestedMessage); + } + if (optionalNestedMessage_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestProto3OptionalMessage other) { + if (other == null) { + return; + } + if (other.nestedMessage_ != null) { + if (nestedMessage_ == null) { + NestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage(); + } + NestedMessage.MergeFrom(other.NestedMessage); + } + if (other.optionalNestedMessage_ != null) { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage(); + } + OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (nestedMessage_ == null) { + NestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage(); + } + input.ReadMessage(NestedMessage); + break; + } + case 18: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (nestedMessage_ == null) { + NestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage(); + } + input.ReadMessage(NestedMessage); + break; + } + case 18: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the TestProto3OptionalMessage message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public sealed partial class NestedMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufUnittest.TestProto3OptionalMessage.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + s_ = other.s_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "s" field. + public const int SFieldNumber = 1; + private string s_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string S { + get { return s_; } + set { + s_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (S != other.S) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (S.Length != 0) hash ^= S.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (S.Length != 0) { + output.WriteRawTag(10); + output.WriteString(S); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (S.Length != 0) { + output.WriteRawTag(10); + output.WriteString(S); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (S.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(S); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.S.Length != 0) { + S = other.S; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + S = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + S = input.ReadString(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs new file mode 100644 index 0000000000000..7ed1580ab2c50 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs @@ -0,0 +1,357 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: unittest_selfreferential_options.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace UnitTest.Issues.TestProtos.SelfreferentialOptions { + + /// Holder for reflection information generated from unittest_selfreferential_options.proto + public static partial class UnittestSelfreferentialOptionsReflection { + + #region Descriptor + /// File descriptor for unittest_selfreferential_options.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestSelfreferentialOptionsReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CiZ1bml0dGVzdF9zZWxmcmVmZXJlbnRpYWxfb3B0aW9ucy5wcm90bxIpcHJv", + "dG9idWZfdW5pdHRlc3Rfc2VsZnJlZmVyZW50aWFsX29wdGlvbnMaIGdvb2ds", + "ZS9wcm90b2J1Zi9kZXNjcmlwdG9yLnByb3RvIkwKCkZvb09wdGlvbnMSHgoH", + "aW50X29wdBgBIAEoBUINyj4KCAHAPgLKPgIIAxITCgNmb28YAiABKAVCBso+", + "AxDSCSoJCOgHEICAgIACOjkKC2Jhcl9vcHRpb25zEh0uZ29vZ2xlLnByb3Rv", + "YnVmLkZpZWxkT3B0aW9ucxjoByABKAVCBMA+0gk6agoLZm9vX29wdGlvbnMS", + "HS5nb29nbGUucHJvdG9idWYuRmllbGRPcHRpb25zGOkHIAEoCzI1LnByb3Rv", + "YnVmX3VuaXR0ZXN0X3NlbGZyZWZlcmVudGlhbF9vcHRpb25zLkZvb09wdGlv", + "bnM6SwoLZm9vX2ludF9vcHQSNS5wcm90b2J1Zl91bml0dGVzdF9zZWxmcmVm", + "ZXJlbnRpYWxfb3B0aW9ucy5Gb29PcHRpb25zGOgHIAEoBTqCAQoLZm9vX2Zv", + "b19vcHQSNS5wcm90b2J1Zl91bml0dGVzdF9zZWxmcmVmZXJlbnRpYWxfb3B0", + "aW9ucy5Gb29PcHRpb25zGOkHIAEoCzI1LnByb3RvYnVmX3VuaXR0ZXN0X3Nl", + "bGZyZWZlcmVudGlhbF9vcHRpb25zLkZvb09wdGlvbnNCNKoCMVVuaXRUZXN0", + "Lklzc3Vlcy5UZXN0UHJvdG9zLlNlbGZyZWZlcmVudGlhbE9wdGlvbnM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, new pb::Extension[] { UnittestSelfreferentialOptionsExtensions.BarOptions, UnittestSelfreferentialOptionsExtensions.FooOptions, UnittestSelfreferentialOptionsExtensions.FooIntOpt, UnittestSelfreferentialOptionsExtensions.FooFooOpt }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions), global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Parser, new[]{ "IntOpt", "Foo" }, null, null, null, null) + })); + } + #endregion + + } + /// Holder for extension identifiers generated from the top level of unittest_selfreferential_options.proto + public static partial class UnittestSelfreferentialOptionsExtensions { + /// + /// Custom field option used on the definition of that field option. + /// + public static readonly pb::Extension BarOptions = + new pb::Extension(1000, pb::FieldCodec.ForInt32(8000, 0)); + public static readonly pb::Extension FooOptions = + new pb::Extension(1001, pb::FieldCodec.ForMessage(8010, global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Parser)); + public static readonly pb::Extension FooIntOpt = + new pb::Extension(1000, pb::FieldCodec.ForInt32(8000, 0)); + public static readonly pb::Extension FooFooOpt = + new pb::Extension(1001, pb::FieldCodec.ForMessage(8010, global::UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Parser)); + } + + #region Messages + public sealed partial class FooOptions : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooOptions()); + private pb::UnknownFieldSet _unknownFields; + private pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooOptions() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooOptions(FooOptions other) : this() { + _hasBits0 = other._hasBits0; + intOpt_ = other.intOpt_; + foo_ = other.foo_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FooOptions Clone() { + return new FooOptions(this); + } + + /// Field number for the "int_opt" field. + public const int IntOptFieldNumber = 1; + private readonly static int IntOptDefaultValue = 0; + + private int intOpt_; + /// + /// Custom field option used in definition of the extension message. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int IntOpt { + get { if ((_hasBits0 & 1) != 0) { return intOpt_; } else { return IntOptDefaultValue; } } + set { + _hasBits0 |= 1; + intOpt_ = value; + } + } + /// Gets whether the "int_opt" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasIntOpt { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "int_opt" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearIntOpt() { + _hasBits0 &= ~1; + } + + /// Field number for the "foo" field. + public const int FooFieldNumber = 2; + private readonly static int FooDefaultValue = 0; + + private int foo_; + /// + /// Custom field option used in definition of the custom option's message. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Foo { + get { if ((_hasBits0 & 2) != 0) { return foo_; } else { return FooDefaultValue; } } + set { + _hasBits0 |= 2; + foo_ = value; + } + } + /// Gets whether the "foo" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFoo { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "foo" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearFoo() { + _hasBits0 &= ~2; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FooOptions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FooOptions other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (IntOpt != other.IntOpt) return false; + if (Foo != other.Foo) return false; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasIntOpt) hash ^= IntOpt.GetHashCode(); + if (HasFoo) hash ^= Foo.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasIntOpt) { + output.WriteRawTag(8); + output.WriteInt32(IntOpt); + } + if (HasFoo) { + output.WriteRawTag(16); + output.WriteInt32(Foo); + } + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasIntOpt) { + output.WriteRawTag(8); + output.WriteInt32(IntOpt); + } + if (HasFoo) { + output.WriteRawTag(16); + output.WriteInt32(Foo); + } + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasIntOpt) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntOpt); + } + if (HasFoo) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Foo); + } + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FooOptions other) { + if (other == null) { + return; + } + if (other.HasIntOpt) { + IntOpt = other.IntOpt; + } + if (other.HasFoo) { + Foo = other.Foo; + } + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + case 8: { + IntOpt = input.ReadInt32(); + break; + } + case 16: { + Foo = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + case 8: { + IntOpt = input.ReadInt32(); + break; + } + case 16: { + Foo = input.ReadInt32(); + break; + } + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs similarity index 75% rename from csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs rename to csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs index 2c7f0e0e1e537..996e928cfd523 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs @@ -1,5 +1,7 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/unittest_well_known_types.proto +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/unittest_well_known_types.proto +// #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -161,11 +163,11 @@ static UnittestWellKnownTypesReflection() { "dFByb3Rvc2IGcHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.ApiReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.EmptyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, }, - new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestWellKnownTypes), global::Google.Protobuf.TestProtos.TestWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField", "ValueField" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes), global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.OneofWellKnownTypes), global::Google.Protobuf.TestProtos.OneofWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, new[]{ "OneofField" }, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MapWellKnownTypes), global::Google.Protobuf.TestProtos.MapWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }) + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestWellKnownTypes), global::Google.Protobuf.TestProtos.TestWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField", "ValueField" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes), global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.OneofWellKnownTypes), global::Google.Protobuf.TestProtos.OneofWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, new[]{ "OneofField" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MapWellKnownTypes), global::Google.Protobuf.TestProtos.MapWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }) })); } #endregion @@ -177,8 +179,13 @@ static UnittestWellKnownTypesReflection() { /// Each wrapper type is included separately, as languages /// map handle different wrappers in different ways. /// - public sealed partial class TestWellKnownTypes : pb::IMessage { + public sealed partial class TestWellKnownTypes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestWellKnownTypes()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -201,15 +208,15 @@ public TestWellKnownTypes() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public TestWellKnownTypes(TestWellKnownTypes other) : this() { - AnyField = other.anyField_ != null ? other.AnyField.Clone() : null; - ApiField = other.apiField_ != null ? other.ApiField.Clone() : null; - DurationField = other.durationField_ != null ? other.DurationField.Clone() : null; - EmptyField = other.emptyField_ != null ? other.EmptyField.Clone() : null; - FieldMaskField = other.fieldMaskField_ != null ? other.FieldMaskField.Clone() : null; - SourceContextField = other.sourceContextField_ != null ? other.SourceContextField.Clone() : null; - StructField = other.structField_ != null ? other.StructField.Clone() : null; - TimestampField = other.timestampField_ != null ? other.TimestampField.Clone() : null; - TypeField = other.typeField_ != null ? other.TypeField.Clone() : null; + anyField_ = other.anyField_ != null ? other.anyField_.Clone() : null; + apiField_ = other.apiField_ != null ? other.apiField_.Clone() : null; + durationField_ = other.durationField_ != null ? other.durationField_.Clone() : null; + emptyField_ = other.emptyField_ != null ? other.emptyField_.Clone() : null; + fieldMaskField_ = other.fieldMaskField_ != null ? other.fieldMaskField_.Clone() : null; + sourceContextField_ = other.sourceContextField_ != null ? other.sourceContextField_.Clone() : null; + structField_ = other.structField_ != null ? other.structField_.Clone() : null; + timestampField_ = other.timestampField_ != null ? other.timestampField_.Clone() : null; + typeField_ = other.typeField_ != null ? other.typeField_.Clone() : null; DoubleField = other.DoubleField; FloatField = other.FloatField; Int64Field = other.Int64Field; @@ -219,7 +226,8 @@ public TestWellKnownTypes(TestWellKnownTypes other) : this() { BoolField = other.BoolField; StringField = other.StringField; BytesField = other.BytesField; - ValueField = other.valueField_ != null ? other.ValueField.Clone() : null; + valueField_ = other.valueField_ != null ? other.valueField_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -338,6 +346,7 @@ public double? DoubleField { } } + /// Field number for the "float_field" field. public const int FloatFieldFieldNumber = 11; private static readonly pb::FieldCodec _single_floatField_codec = pb::FieldCodec.ForStructWrapper(90); @@ -350,6 +359,7 @@ public float? FloatField { } } + /// Field number for the "int64_field" field. public const int Int64FieldFieldNumber = 12; private static readonly pb::FieldCodec _single_int64Field_codec = pb::FieldCodec.ForStructWrapper(98); @@ -362,6 +372,7 @@ public long? Int64Field { } } + /// Field number for the "uint64_field" field. public const int Uint64FieldFieldNumber = 13; private static readonly pb::FieldCodec _single_uint64Field_codec = pb::FieldCodec.ForStructWrapper(106); @@ -374,6 +385,7 @@ public ulong? Uint64Field { } } + /// Field number for the "int32_field" field. public const int Int32FieldFieldNumber = 14; private static readonly pb::FieldCodec _single_int32Field_codec = pb::FieldCodec.ForStructWrapper(114); @@ -386,6 +398,7 @@ public int? Int32Field { } } + /// Field number for the "uint32_field" field. public const int Uint32FieldFieldNumber = 15; private static readonly pb::FieldCodec _single_uint32Field_codec = pb::FieldCodec.ForStructWrapper(122); @@ -398,6 +411,7 @@ public uint? Uint32Field { } } + /// Field number for the "bool_field" field. public const int BoolFieldFieldNumber = 16; private static readonly pb::FieldCodec _single_boolField_codec = pb::FieldCodec.ForStructWrapper(130); @@ -410,6 +424,7 @@ public bool? BoolField { } } + /// Field number for the "string_field" field. public const int StringFieldFieldNumber = 17; private static readonly pb::FieldCodec _single_stringField_codec = pb::FieldCodec.ForClassWrapper(138); @@ -422,6 +437,7 @@ public string StringField { } } + /// Field number for the "bytes_field" field. public const int BytesFieldFieldNumber = 18; private static readonly pb::FieldCodec _single_bytesField_codec = pb::FieldCodec.ForClassWrapper(146); @@ -434,6 +450,7 @@ public string StringField { } } + /// Field number for the "value_field" field. public const int ValueFieldFieldNumber = 19; private global::Google.Protobuf.WellKnownTypes.Value valueField_; @@ -470,8 +487,8 @@ public bool Equals(TestWellKnownTypes other) { if (!object.Equals(StructField, other.StructField)) return false; if (!object.Equals(TimestampField, other.TimestampField)) return false; if (!object.Equals(TypeField, other.TypeField)) return false; - if (DoubleField != other.DoubleField) return false; - if (FloatField != other.FloatField) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField, other.DoubleField)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.Equals(FloatField, other.FloatField)) return false; if (Int64Field != other.Int64Field) return false; if (Uint64Field != other.Uint64Field) return false; if (Int32Field != other.Int32Field) return false; @@ -480,7 +497,7 @@ public bool Equals(TestWellKnownTypes other) { if (StringField != other.StringField) return false; if (BytesField != other.BytesField) return false; if (!object.Equals(ValueField, other.ValueField)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -495,8 +512,8 @@ public override int GetHashCode() { if (structField_ != null) hash ^= StructField.GetHashCode(); if (timestampField_ != null) hash ^= TimestampField.GetHashCode(); if (typeField_ != null) hash ^= TypeField.GetHashCode(); - if (doubleField_ != null) hash ^= DoubleField.GetHashCode(); - if (floatField_ != null) hash ^= FloatField.GetHashCode(); + if (doubleField_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField); + if (floatField_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.GetHashCode(FloatField); if (int64Field_ != null) hash ^= Int64Field.GetHashCode(); if (uint64Field_ != null) hash ^= Uint64Field.GetHashCode(); if (int32Field_ != null) hash ^= Int32Field.GetHashCode(); @@ -505,6 +522,9 @@ public override int GetHashCode() { if (stringField_ != null) hash ^= StringField.GetHashCode(); if (bytesField_ != null) hash ^= BytesField.GetHashCode(); if (valueField_ != null) hash ^= ValueField.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -515,6 +535,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (anyField_ != null) { output.WriteRawTag(10); output.WriteMessage(AnyField); @@ -582,7 +605,87 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(154, 1); output.WriteMessage(ValueField); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (anyField_ != null) { + output.WriteRawTag(10); + output.WriteMessage(AnyField); + } + if (apiField_ != null) { + output.WriteRawTag(18); + output.WriteMessage(ApiField); + } + if (durationField_ != null) { + output.WriteRawTag(26); + output.WriteMessage(DurationField); + } + if (emptyField_ != null) { + output.WriteRawTag(34); + output.WriteMessage(EmptyField); + } + if (fieldMaskField_ != null) { + output.WriteRawTag(42); + output.WriteMessage(FieldMaskField); + } + if (sourceContextField_ != null) { + output.WriteRawTag(50); + output.WriteMessage(SourceContextField); + } + if (structField_ != null) { + output.WriteRawTag(58); + output.WriteMessage(StructField); + } + if (timestampField_ != null) { + output.WriteRawTag(66); + output.WriteMessage(TimestampField); + } + if (typeField_ != null) { + output.WriteRawTag(74); + output.WriteMessage(TypeField); + } + if (doubleField_ != null) { + _single_doubleField_codec.WriteTagAndValue(ref output, DoubleField); + } + if (floatField_ != null) { + _single_floatField_codec.WriteTagAndValue(ref output, FloatField); + } + if (int64Field_ != null) { + _single_int64Field_codec.WriteTagAndValue(ref output, Int64Field); + } + if (uint64Field_ != null) { + _single_uint64Field_codec.WriteTagAndValue(ref output, Uint64Field); + } + if (int32Field_ != null) { + _single_int32Field_codec.WriteTagAndValue(ref output, Int32Field); + } + if (uint32Field_ != null) { + _single_uint32Field_codec.WriteTagAndValue(ref output, Uint32Field); + } + if (boolField_ != null) { + _single_boolField_codec.WriteTagAndValue(ref output, BoolField); + } + if (stringField_ != null) { + _single_stringField_codec.WriteTagAndValue(ref output, StringField); + } + if (bytesField_ != null) { + _single_bytesField_codec.WriteTagAndValue(ref output, BytesField); + } + if (valueField_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(ValueField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -644,6 +747,9 @@ public int CalculateSize() { if (valueField_ != null) { size += 2 + pb::CodedOutputStream.ComputeMessageSize(ValueField); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -654,55 +760,55 @@ public void MergeFrom(TestWellKnownTypes other) { } if (other.anyField_ != null) { if (anyField_ == null) { - anyField_ = new global::Google.Protobuf.WellKnownTypes.Any(); + AnyField = new global::Google.Protobuf.WellKnownTypes.Any(); } AnyField.MergeFrom(other.AnyField); } if (other.apiField_ != null) { if (apiField_ == null) { - apiField_ = new global::Google.Protobuf.WellKnownTypes.Api(); + ApiField = new global::Google.Protobuf.WellKnownTypes.Api(); } ApiField.MergeFrom(other.ApiField); } if (other.durationField_ != null) { if (durationField_ == null) { - durationField_ = new global::Google.Protobuf.WellKnownTypes.Duration(); + DurationField = new global::Google.Protobuf.WellKnownTypes.Duration(); } DurationField.MergeFrom(other.DurationField); } if (other.emptyField_ != null) { if (emptyField_ == null) { - emptyField_ = new global::Google.Protobuf.WellKnownTypes.Empty(); + EmptyField = new global::Google.Protobuf.WellKnownTypes.Empty(); } EmptyField.MergeFrom(other.EmptyField); } if (other.fieldMaskField_ != null) { if (fieldMaskField_ == null) { - fieldMaskField_ = new global::Google.Protobuf.WellKnownTypes.FieldMask(); + FieldMaskField = new global::Google.Protobuf.WellKnownTypes.FieldMask(); } FieldMaskField.MergeFrom(other.FieldMaskField); } if (other.sourceContextField_ != null) { if (sourceContextField_ == null) { - sourceContextField_ = new global::Google.Protobuf.WellKnownTypes.SourceContext(); + SourceContextField = new global::Google.Protobuf.WellKnownTypes.SourceContext(); } SourceContextField.MergeFrom(other.SourceContextField); } if (other.structField_ != null) { if (structField_ == null) { - structField_ = new global::Google.Protobuf.WellKnownTypes.Struct(); + StructField = new global::Google.Protobuf.WellKnownTypes.Struct(); } StructField.MergeFrom(other.StructField); } if (other.timestampField_ != null) { if (timestampField_ == null) { - timestampField_ = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + TimestampField = new global::Google.Protobuf.WellKnownTypes.Timestamp(); } TimestampField.MergeFrom(other.TimestampField); } if (other.typeField_ != null) { if (typeField_ == null) { - typeField_ = new global::Google.Protobuf.WellKnownTypes.Type(); + TypeField = new global::Google.Protobuf.WellKnownTypes.Type(); } TypeField.MergeFrom(other.TypeField); } @@ -753,81 +859,85 @@ public void MergeFrom(TestWellKnownTypes other) { } if (other.valueField_ != null) { if (valueField_ == null) { - valueField_ = new global::Google.Protobuf.WellKnownTypes.Value(); + ValueField = new global::Google.Protobuf.WellKnownTypes.Value(); } ValueField.MergeFrom(other.ValueField); } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { if (anyField_ == null) { - anyField_ = new global::Google.Protobuf.WellKnownTypes.Any(); + AnyField = new global::Google.Protobuf.WellKnownTypes.Any(); } - input.ReadMessage(anyField_); + input.ReadMessage(AnyField); break; } case 18: { if (apiField_ == null) { - apiField_ = new global::Google.Protobuf.WellKnownTypes.Api(); + ApiField = new global::Google.Protobuf.WellKnownTypes.Api(); } - input.ReadMessage(apiField_); + input.ReadMessage(ApiField); break; } case 26: { if (durationField_ == null) { - durationField_ = new global::Google.Protobuf.WellKnownTypes.Duration(); + DurationField = new global::Google.Protobuf.WellKnownTypes.Duration(); } - input.ReadMessage(durationField_); + input.ReadMessage(DurationField); break; } case 34: { if (emptyField_ == null) { - emptyField_ = new global::Google.Protobuf.WellKnownTypes.Empty(); + EmptyField = new global::Google.Protobuf.WellKnownTypes.Empty(); } - input.ReadMessage(emptyField_); + input.ReadMessage(EmptyField); break; } case 42: { if (fieldMaskField_ == null) { - fieldMaskField_ = new global::Google.Protobuf.WellKnownTypes.FieldMask(); + FieldMaskField = new global::Google.Protobuf.WellKnownTypes.FieldMask(); } - input.ReadMessage(fieldMaskField_); + input.ReadMessage(FieldMaskField); break; } case 50: { if (sourceContextField_ == null) { - sourceContextField_ = new global::Google.Protobuf.WellKnownTypes.SourceContext(); + SourceContextField = new global::Google.Protobuf.WellKnownTypes.SourceContext(); } - input.ReadMessage(sourceContextField_); + input.ReadMessage(SourceContextField); break; } case 58: { if (structField_ == null) { - structField_ = new global::Google.Protobuf.WellKnownTypes.Struct(); + StructField = new global::Google.Protobuf.WellKnownTypes.Struct(); } - input.ReadMessage(structField_); + input.ReadMessage(StructField); break; } case 66: { if (timestampField_ == null) { - timestampField_ = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + TimestampField = new global::Google.Protobuf.WellKnownTypes.Timestamp(); } - input.ReadMessage(timestampField_); + input.ReadMessage(TimestampField); break; } case 74: { if (typeField_ == null) { - typeField_ = new global::Google.Protobuf.WellKnownTypes.Type(); + TypeField = new global::Google.Protobuf.WellKnownTypes.Type(); } - input.ReadMessage(typeField_); + input.ReadMessage(TypeField); break; } case 82: { @@ -895,22 +1005,175 @@ public void MergeFrom(pb::CodedInputStream input) { } case 154: { if (valueField_ == null) { - valueField_ = new global::Google.Protobuf.WellKnownTypes.Value(); + ValueField = new global::Google.Protobuf.WellKnownTypes.Value(); + } + input.ReadMessage(ValueField); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (anyField_ == null) { + AnyField = new global::Google.Protobuf.WellKnownTypes.Any(); + } + input.ReadMessage(AnyField); + break; + } + case 18: { + if (apiField_ == null) { + ApiField = new global::Google.Protobuf.WellKnownTypes.Api(); + } + input.ReadMessage(ApiField); + break; + } + case 26: { + if (durationField_ == null) { + DurationField = new global::Google.Protobuf.WellKnownTypes.Duration(); + } + input.ReadMessage(DurationField); + break; + } + case 34: { + if (emptyField_ == null) { + EmptyField = new global::Google.Protobuf.WellKnownTypes.Empty(); + } + input.ReadMessage(EmptyField); + break; + } + case 42: { + if (fieldMaskField_ == null) { + FieldMaskField = new global::Google.Protobuf.WellKnownTypes.FieldMask(); + } + input.ReadMessage(FieldMaskField); + break; + } + case 50: { + if (sourceContextField_ == null) { + SourceContextField = new global::Google.Protobuf.WellKnownTypes.SourceContext(); + } + input.ReadMessage(SourceContextField); + break; + } + case 58: { + if (structField_ == null) { + StructField = new global::Google.Protobuf.WellKnownTypes.Struct(); + } + input.ReadMessage(StructField); + break; + } + case 66: { + if (timestampField_ == null) { + TimestampField = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + } + input.ReadMessage(TimestampField); + break; + } + case 74: { + if (typeField_ == null) { + TypeField = new global::Google.Protobuf.WellKnownTypes.Type(); + } + input.ReadMessage(TypeField); + break; + } + case 82: { + double? value = _single_doubleField_codec.Read(ref input); + if (doubleField_ == null || value != 0D) { + DoubleField = value; + } + break; + } + case 90: { + float? value = _single_floatField_codec.Read(ref input); + if (floatField_ == null || value != 0F) { + FloatField = value; + } + break; + } + case 98: { + long? value = _single_int64Field_codec.Read(ref input); + if (int64Field_ == null || value != 0L) { + Int64Field = value; + } + break; + } + case 106: { + ulong? value = _single_uint64Field_codec.Read(ref input); + if (uint64Field_ == null || value != 0UL) { + Uint64Field = value; + } + break; + } + case 114: { + int? value = _single_int32Field_codec.Read(ref input); + if (int32Field_ == null || value != 0) { + Int32Field = value; + } + break; + } + case 122: { + uint? value = _single_uint32Field_codec.Read(ref input); + if (uint32Field_ == null || value != 0) { + Uint32Field = value; + } + break; + } + case 130: { + bool? value = _single_boolField_codec.Read(ref input); + if (boolField_ == null || value != false) { + BoolField = value; + } + break; + } + case 138: { + string value = _single_stringField_codec.Read(ref input); + if (stringField_ == null || value != "") { + StringField = value; + } + break; + } + case 146: { + pb::ByteString value = _single_bytesField_codec.Read(ref input); + if (bytesField_ == null || value != pb::ByteString.Empty) { + BytesField = value; + } + break; + } + case 154: { + if (valueField_ == null) { + ValueField = new global::Google.Protobuf.WellKnownTypes.Value(); } - input.ReadMessage(valueField_); + input.ReadMessage(ValueField); break; } } } } + #endif } /// /// A repeated field for each well-known type. /// - public sealed partial class RepeatedWellKnownTypes : pb::IMessage { + public sealed partial class RepeatedWellKnownTypes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RepeatedWellKnownTypes()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -951,6 +1214,7 @@ public RepeatedWellKnownTypes(RepeatedWellKnownTypes other) : this() { boolField_ = other.boolField_.Clone(); stringField_ = other.stringField_.Clone(); bytesField_ = other.bytesField_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1172,7 +1436,7 @@ public bool Equals(RepeatedWellKnownTypes other) { if(!boolField_.Equals(other.boolField_)) return false; if(!stringField_.Equals(other.stringField_)) return false; if(!bytesField_.Equals(other.bytesField_)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1196,6 +1460,9 @@ public override int GetHashCode() { hash ^= boolField_.GetHashCode(); hash ^= stringField_.GetHashCode(); hash ^= bytesField_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -1206,6 +1473,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else anyField_.WriteTo(output, _repeated_anyField_codec); apiField_.WriteTo(output, _repeated_apiField_codec); durationField_.WriteTo(output, _repeated_durationField_codec); @@ -1224,7 +1494,38 @@ public void WriteTo(pb::CodedOutputStream output) { boolField_.WriteTo(output, _repeated_boolField_codec); stringField_.WriteTo(output, _repeated_stringField_codec); bytesField_.WriteTo(output, _repeated_bytesField_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + anyField_.WriteTo(ref output, _repeated_anyField_codec); + apiField_.WriteTo(ref output, _repeated_apiField_codec); + durationField_.WriteTo(ref output, _repeated_durationField_codec); + emptyField_.WriteTo(ref output, _repeated_emptyField_codec); + fieldMaskField_.WriteTo(ref output, _repeated_fieldMaskField_codec); + sourceContextField_.WriteTo(ref output, _repeated_sourceContextField_codec); + structField_.WriteTo(ref output, _repeated_structField_codec); + timestampField_.WriteTo(ref output, _repeated_timestampField_codec); + typeField_.WriteTo(ref output, _repeated_typeField_codec); + doubleField_.WriteTo(ref output, _repeated_doubleField_codec); + floatField_.WriteTo(ref output, _repeated_floatField_codec); + int64Field_.WriteTo(ref output, _repeated_int64Field_codec); + uint64Field_.WriteTo(ref output, _repeated_uint64Field_codec); + int32Field_.WriteTo(ref output, _repeated_int32Field_codec); + uint32Field_.WriteTo(ref output, _repeated_uint32Field_codec); + boolField_.WriteTo(ref output, _repeated_boolField_codec); + stringField_.WriteTo(ref output, _repeated_stringField_codec); + bytesField_.WriteTo(ref output, _repeated_bytesField_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1247,6 +1548,9 @@ public int CalculateSize() { size += boolField_.CalculateSize(_repeated_boolField_codec); size += stringField_.CalculateSize(_repeated_stringField_codec); size += bytesField_.CalculateSize(_repeated_bytesField_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -1273,15 +1577,19 @@ public void MergeFrom(RepeatedWellKnownTypes other) { boolField_.Add(other.boolField_); stringField_.Add(other.stringField_); bytesField_.Add(other.bytesField_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { anyField_.AddEntriesFrom(input, _repeated_anyField_codec); @@ -1357,71 +1665,163 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } - } - - public sealed partial class OneofWellKnownTypes : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneofWellKnownTypes()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypesReflection.Descriptor.MessageTypes[2]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public OneofWellKnownTypes() { - OnConstruction(); - } - - partial void OnConstruction(); - + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public OneofWellKnownTypes(OneofWellKnownTypes other) : this() { - switch (other.OneofFieldCase) { - case OneofFieldOneofCase.AnyField: - AnyField = other.AnyField.Clone(); - break; - case OneofFieldOneofCase.ApiField: - ApiField = other.ApiField.Clone(); - break; - case OneofFieldOneofCase.DurationField: - DurationField = other.DurationField.Clone(); - break; - case OneofFieldOneofCase.EmptyField: - EmptyField = other.EmptyField.Clone(); - break; - case OneofFieldOneofCase.FieldMaskField: - FieldMaskField = other.FieldMaskField.Clone(); - break; - case OneofFieldOneofCase.SourceContextField: - SourceContextField = other.SourceContextField.Clone(); - break; - case OneofFieldOneofCase.StructField: - StructField = other.StructField.Clone(); - break; - case OneofFieldOneofCase.TimestampField: - TimestampField = other.TimestampField.Clone(); - break; - case OneofFieldOneofCase.TypeField: - TypeField = other.TypeField.Clone(); - break; - case OneofFieldOneofCase.DoubleField: - DoubleField = other.DoubleField; - break; - case OneofFieldOneofCase.FloatField: - FloatField = other.FloatField; - break; - case OneofFieldOneofCase.Int64Field: - Int64Field = other.Int64Field; - break; + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + anyField_.AddEntriesFrom(ref input, _repeated_anyField_codec); + break; + } + case 18: { + apiField_.AddEntriesFrom(ref input, _repeated_apiField_codec); + break; + } + case 26: { + durationField_.AddEntriesFrom(ref input, _repeated_durationField_codec); + break; + } + case 34: { + emptyField_.AddEntriesFrom(ref input, _repeated_emptyField_codec); + break; + } + case 42: { + fieldMaskField_.AddEntriesFrom(ref input, _repeated_fieldMaskField_codec); + break; + } + case 50: { + sourceContextField_.AddEntriesFrom(ref input, _repeated_sourceContextField_codec); + break; + } + case 58: { + structField_.AddEntriesFrom(ref input, _repeated_structField_codec); + break; + } + case 66: { + timestampField_.AddEntriesFrom(ref input, _repeated_timestampField_codec); + break; + } + case 74: { + typeField_.AddEntriesFrom(ref input, _repeated_typeField_codec); + break; + } + case 82: { + doubleField_.AddEntriesFrom(ref input, _repeated_doubleField_codec); + break; + } + case 90: { + floatField_.AddEntriesFrom(ref input, _repeated_floatField_codec); + break; + } + case 98: { + int64Field_.AddEntriesFrom(ref input, _repeated_int64Field_codec); + break; + } + case 106: { + uint64Field_.AddEntriesFrom(ref input, _repeated_uint64Field_codec); + break; + } + case 114: { + int32Field_.AddEntriesFrom(ref input, _repeated_int32Field_codec); + break; + } + case 122: { + uint32Field_.AddEntriesFrom(ref input, _repeated_uint32Field_codec); + break; + } + case 130: { + boolField_.AddEntriesFrom(ref input, _repeated_boolField_codec); + break; + } + case 138: { + stringField_.AddEntriesFrom(ref input, _repeated_stringField_codec); + break; + } + case 146: { + bytesField_.AddEntriesFrom(ref input, _repeated_bytesField_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class OneofWellKnownTypes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneofWellKnownTypes()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypesReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneofWellKnownTypes() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public OneofWellKnownTypes(OneofWellKnownTypes other) : this() { + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.AnyField: + AnyField = other.AnyField.Clone(); + break; + case OneofFieldOneofCase.ApiField: + ApiField = other.ApiField.Clone(); + break; + case OneofFieldOneofCase.DurationField: + DurationField = other.DurationField.Clone(); + break; + case OneofFieldOneofCase.EmptyField: + EmptyField = other.EmptyField.Clone(); + break; + case OneofFieldOneofCase.FieldMaskField: + FieldMaskField = other.FieldMaskField.Clone(); + break; + case OneofFieldOneofCase.SourceContextField: + SourceContextField = other.SourceContextField.Clone(); + break; + case OneofFieldOneofCase.StructField: + StructField = other.StructField.Clone(); + break; + case OneofFieldOneofCase.TimestampField: + TimestampField = other.TimestampField.Clone(); + break; + case OneofFieldOneofCase.TypeField: + TypeField = other.TypeField.Clone(); + break; + case OneofFieldOneofCase.DoubleField: + DoubleField = other.DoubleField; + break; + case OneofFieldOneofCase.FloatField: + FloatField = other.FloatField; + break; + case OneofFieldOneofCase.Int64Field: + Int64Field = other.Int64Field; + break; case OneofFieldOneofCase.Uint64Field: Uint64Field = other.Uint64Field; break; @@ -1442,6 +1842,7 @@ public OneofWellKnownTypes(OneofWellKnownTypes other) : this() { break; } + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1713,8 +2114,8 @@ public bool Equals(OneofWellKnownTypes other) { if (!object.Equals(StructField, other.StructField)) return false; if (!object.Equals(TimestampField, other.TimestampField)) return false; if (!object.Equals(TypeField, other.TypeField)) return false; - if (DoubleField != other.DoubleField) return false; - if (FloatField != other.FloatField) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField, other.DoubleField)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.Equals(FloatField, other.FloatField)) return false; if (Int64Field != other.Int64Field) return false; if (Uint64Field != other.Uint64Field) return false; if (Int32Field != other.Int32Field) return false; @@ -1723,7 +2124,7 @@ public bool Equals(OneofWellKnownTypes other) { if (StringField != other.StringField) return false; if (BytesField != other.BytesField) return false; if (OneofFieldCase != other.OneofFieldCase) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1738,8 +2139,8 @@ public override int GetHashCode() { if (oneofFieldCase_ == OneofFieldOneofCase.StructField) hash ^= StructField.GetHashCode(); if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) hash ^= TimestampField.GetHashCode(); if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) hash ^= TypeField.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.DoubleField) hash ^= DoubleField.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.FloatField) hash ^= FloatField.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.DoubleField) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField); + if (oneofFieldCase_ == OneofFieldOneofCase.FloatField) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.GetHashCode(FloatField); if (oneofFieldCase_ == OneofFieldOneofCase.Int64Field) hash ^= Int64Field.GetHashCode(); if (oneofFieldCase_ == OneofFieldOneofCase.Uint64Field) hash ^= Uint64Field.GetHashCode(); if (oneofFieldCase_ == OneofFieldOneofCase.Int32Field) hash ^= Int32Field.GetHashCode(); @@ -1748,6 +2149,9 @@ public override int GetHashCode() { if (oneofFieldCase_ == OneofFieldOneofCase.StringField) hash ^= StringField.GetHashCode(); if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) hash ^= BytesField.GetHashCode(); hash ^= (int) oneofFieldCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -1758,6 +2162,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) { output.WriteRawTag(10); output.WriteMessage(AnyField); @@ -1821,7 +2228,83 @@ public void WriteTo(pb::CodedOutputStream output) { if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) { _oneof_bytesField_codec.WriteTagAndValue(output, (pb::ByteString) oneofField_); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) { + output.WriteRawTag(10); + output.WriteMessage(AnyField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.ApiField) { + output.WriteRawTag(18); + output.WriteMessage(ApiField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.DurationField) { + output.WriteRawTag(26); + output.WriteMessage(DurationField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.EmptyField) { + output.WriteRawTag(34); + output.WriteMessage(EmptyField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField) { + output.WriteRawTag(42); + output.WriteMessage(FieldMaskField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.SourceContextField) { + output.WriteRawTag(50); + output.WriteMessage(SourceContextField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.StructField) { + output.WriteRawTag(58); + output.WriteMessage(StructField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) { + output.WriteRawTag(66); + output.WriteMessage(TimestampField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) { + output.WriteRawTag(74); + output.WriteMessage(TypeField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.DoubleField) { + _oneof_doubleField_codec.WriteTagAndValue(ref output, (double?) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.FloatField) { + _oneof_floatField_codec.WriteTagAndValue(ref output, (float?) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.Int64Field) { + _oneof_int64Field_codec.WriteTagAndValue(ref output, (long?) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.Uint64Field) { + _oneof_uint64Field_codec.WriteTagAndValue(ref output, (ulong?) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.Int32Field) { + _oneof_int32Field_codec.WriteTagAndValue(ref output, (int?) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.Uint32Field) { + _oneof_uint32Field_codec.WriteTagAndValue(ref output, (uint?) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.BoolField) { + _oneof_boolField_codec.WriteTagAndValue(ref output, (bool?) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.StringField) { + _oneof_stringField_codec.WriteTagAndValue(ref output, (string) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) { + _oneof_bytesField_codec.WriteTagAndValue(ref output, (pb::ByteString) oneofField_); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1880,6 +2363,9 @@ public int CalculateSize() { if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) { size += _oneof_bytesField_codec.CalculateSizeWithTag(BytesField); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -1890,31 +2376,58 @@ public void MergeFrom(OneofWellKnownTypes other) { } switch (other.OneofFieldCase) { case OneofFieldOneofCase.AnyField: - AnyField = other.AnyField; + if (AnyField == null) { + AnyField = new global::Google.Protobuf.WellKnownTypes.Any(); + } + AnyField.MergeFrom(other.AnyField); break; case OneofFieldOneofCase.ApiField: - ApiField = other.ApiField; + if (ApiField == null) { + ApiField = new global::Google.Protobuf.WellKnownTypes.Api(); + } + ApiField.MergeFrom(other.ApiField); break; case OneofFieldOneofCase.DurationField: - DurationField = other.DurationField; + if (DurationField == null) { + DurationField = new global::Google.Protobuf.WellKnownTypes.Duration(); + } + DurationField.MergeFrom(other.DurationField); break; case OneofFieldOneofCase.EmptyField: - EmptyField = other.EmptyField; + if (EmptyField == null) { + EmptyField = new global::Google.Protobuf.WellKnownTypes.Empty(); + } + EmptyField.MergeFrom(other.EmptyField); break; case OneofFieldOneofCase.FieldMaskField: - FieldMaskField = other.FieldMaskField; + if (FieldMaskField == null) { + FieldMaskField = new global::Google.Protobuf.WellKnownTypes.FieldMask(); + } + FieldMaskField.MergeFrom(other.FieldMaskField); break; case OneofFieldOneofCase.SourceContextField: - SourceContextField = other.SourceContextField; + if (SourceContextField == null) { + SourceContextField = new global::Google.Protobuf.WellKnownTypes.SourceContext(); + } + SourceContextField.MergeFrom(other.SourceContextField); break; case OneofFieldOneofCase.StructField: - StructField = other.StructField; + if (StructField == null) { + StructField = new global::Google.Protobuf.WellKnownTypes.Struct(); + } + StructField.MergeFrom(other.StructField); break; case OneofFieldOneofCase.TimestampField: - TimestampField = other.TimestampField; + if (TimestampField == null) { + TimestampField = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + } + TimestampField.MergeFrom(other.TimestampField); break; case OneofFieldOneofCase.TypeField: - TypeField = other.TypeField; + if (TypeField == null) { + TypeField = new global::Google.Protobuf.WellKnownTypes.Type(); + } + TypeField.MergeFrom(other.TypeField); break; case OneofFieldOneofCase.DoubleField: DoubleField = other.DoubleField; @@ -1945,15 +2458,19 @@ public void MergeFrom(OneofWellKnownTypes other) { break; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { global::Google.Protobuf.WellKnownTypes.Any subBuilder = new global::Google.Protobuf.WellKnownTypes.Any(); @@ -2074,7 +2591,139 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + global::Google.Protobuf.WellKnownTypes.Any subBuilder = new global::Google.Protobuf.WellKnownTypes.Any(); + if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) { + subBuilder.MergeFrom(AnyField); + } + input.ReadMessage(subBuilder); + AnyField = subBuilder; + break; + } + case 18: { + global::Google.Protobuf.WellKnownTypes.Api subBuilder = new global::Google.Protobuf.WellKnownTypes.Api(); + if (oneofFieldCase_ == OneofFieldOneofCase.ApiField) { + subBuilder.MergeFrom(ApiField); + } + input.ReadMessage(subBuilder); + ApiField = subBuilder; + break; + } + case 26: { + global::Google.Protobuf.WellKnownTypes.Duration subBuilder = new global::Google.Protobuf.WellKnownTypes.Duration(); + if (oneofFieldCase_ == OneofFieldOneofCase.DurationField) { + subBuilder.MergeFrom(DurationField); + } + input.ReadMessage(subBuilder); + DurationField = subBuilder; + break; + } + case 34: { + global::Google.Protobuf.WellKnownTypes.Empty subBuilder = new global::Google.Protobuf.WellKnownTypes.Empty(); + if (oneofFieldCase_ == OneofFieldOneofCase.EmptyField) { + subBuilder.MergeFrom(EmptyField); + } + input.ReadMessage(subBuilder); + EmptyField = subBuilder; + break; + } + case 42: { + global::Google.Protobuf.WellKnownTypes.FieldMask subBuilder = new global::Google.Protobuf.WellKnownTypes.FieldMask(); + if (oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField) { + subBuilder.MergeFrom(FieldMaskField); + } + input.ReadMessage(subBuilder); + FieldMaskField = subBuilder; + break; + } + case 50: { + global::Google.Protobuf.WellKnownTypes.SourceContext subBuilder = new global::Google.Protobuf.WellKnownTypes.SourceContext(); + if (oneofFieldCase_ == OneofFieldOneofCase.SourceContextField) { + subBuilder.MergeFrom(SourceContextField); + } + input.ReadMessage(subBuilder); + SourceContextField = subBuilder; + break; + } + case 58: { + global::Google.Protobuf.WellKnownTypes.Struct subBuilder = new global::Google.Protobuf.WellKnownTypes.Struct(); + if (oneofFieldCase_ == OneofFieldOneofCase.StructField) { + subBuilder.MergeFrom(StructField); + } + input.ReadMessage(subBuilder); + StructField = subBuilder; + break; + } + case 66: { + global::Google.Protobuf.WellKnownTypes.Timestamp subBuilder = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) { + subBuilder.MergeFrom(TimestampField); + } + input.ReadMessage(subBuilder); + TimestampField = subBuilder; + break; + } + case 74: { + global::Google.Protobuf.WellKnownTypes.Type subBuilder = new global::Google.Protobuf.WellKnownTypes.Type(); + if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) { + subBuilder.MergeFrom(TypeField); + } + input.ReadMessage(subBuilder); + TypeField = subBuilder; + break; + } + case 82: { + DoubleField = _oneof_doubleField_codec.Read(ref input); + break; + } + case 90: { + FloatField = _oneof_floatField_codec.Read(ref input); + break; + } + case 98: { + Int64Field = _oneof_int64Field_codec.Read(ref input); + break; + } + case 106: { + Uint64Field = _oneof_uint64Field_codec.Read(ref input); + break; + } + case 114: { + Int32Field = _oneof_int32Field_codec.Read(ref input); + break; + } + case 122: { + Uint32Field = _oneof_uint32Field_codec.Read(ref input); + break; + } + case 130: { + BoolField = _oneof_boolField_codec.Read(ref input); + break; + } + case 138: { + StringField = _oneof_stringField_codec.Read(ref input); + break; + } + case 146: { + BytesField = _oneof_bytesField_codec.Read(ref input); + break; + } + } + } } + #endif } @@ -2083,8 +2732,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// need to worry about the value part of the map being the /// well-known types, as messages can't be map keys. /// - public sealed partial class MapWellKnownTypes : pb::IMessage { + public sealed partial class MapWellKnownTypes : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MapWellKnownTypes()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -2125,6 +2779,7 @@ public MapWellKnownTypes(MapWellKnownTypes other) : this() { boolField_ = other.boolField_.Clone(); stringField_ = other.stringField_.Clone(); bytesField_ = other.bytesField_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2135,7 +2790,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "any_field" field. public const int AnyFieldFieldNumber = 1; private static readonly pbc::MapField.Codec _map_anyField_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Any.Parser), 10); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Any.Parser), 10); private readonly pbc::MapField anyField_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField AnyField { @@ -2145,7 +2800,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "api_field" field. public const int ApiFieldFieldNumber = 2; private static readonly pbc::MapField.Codec _map_apiField_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Api.Parser), 18); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Api.Parser), 18); private readonly pbc::MapField apiField_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField ApiField { @@ -2155,7 +2810,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "duration_field" field. public const int DurationFieldFieldNumber = 3; private static readonly pbc::MapField.Codec _map_durationField_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Duration.Parser), 26); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Duration.Parser), 26); private readonly pbc::MapField durationField_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField DurationField { @@ -2165,7 +2820,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "empty_field" field. public const int EmptyFieldFieldNumber = 4; private static readonly pbc::MapField.Codec _map_emptyField_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Empty.Parser), 34); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Empty.Parser), 34); private readonly pbc::MapField emptyField_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField EmptyField { @@ -2175,7 +2830,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "field_mask_field" field. public const int FieldMaskFieldFieldNumber = 5; private static readonly pbc::MapField.Codec _map_fieldMaskField_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.FieldMask.Parser), 42); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.FieldMask.Parser), 42); private readonly pbc::MapField fieldMaskField_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField FieldMaskField { @@ -2185,7 +2840,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "source_context_field" field. public const int SourceContextFieldFieldNumber = 6; private static readonly pbc::MapField.Codec _map_sourceContextField_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.SourceContext.Parser), 50); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.SourceContext.Parser), 50); private readonly pbc::MapField sourceContextField_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField SourceContextField { @@ -2195,7 +2850,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "struct_field" field. public const int StructFieldFieldNumber = 7; private static readonly pbc::MapField.Codec _map_structField_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Struct.Parser), 58); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Struct.Parser), 58); private readonly pbc::MapField structField_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField StructField { @@ -2205,7 +2860,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "timestamp_field" field. public const int TimestampFieldFieldNumber = 8; private static readonly pbc::MapField.Codec _map_timestampField_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Timestamp.Parser), 66); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Timestamp.Parser), 66); private readonly pbc::MapField timestampField_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField TimestampField { @@ -2215,7 +2870,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "type_field" field. public const int TypeFieldFieldNumber = 9; private static readonly pbc::MapField.Codec _map_typeField_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Type.Parser), 74); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Type.Parser), 74); private readonly pbc::MapField typeField_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField TypeField { @@ -2225,7 +2880,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "double_field" field. public const int DoubleFieldFieldNumber = 10; private static readonly pbc::MapField.Codec _map_doubleField_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper(18), 82); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForStructWrapper(18), 82); private readonly pbc::MapField doubleField_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField DoubleField { @@ -2235,7 +2890,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "float_field" field. public const int FloatFieldFieldNumber = 11; private static readonly pbc::MapField.Codec _map_floatField_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper(18), 90); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForStructWrapper(18), 90); private readonly pbc::MapField floatField_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField FloatField { @@ -2245,7 +2900,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "int64_field" field. public const int Int64FieldFieldNumber = 12; private static readonly pbc::MapField.Codec _map_int64Field_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper(18), 98); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForStructWrapper(18), 98); private readonly pbc::MapField int64Field_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField Int64Field { @@ -2255,7 +2910,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "uint64_field" field. public const int Uint64FieldFieldNumber = 13; private static readonly pbc::MapField.Codec _map_uint64Field_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper(18), 106); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForStructWrapper(18), 106); private readonly pbc::MapField uint64Field_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField Uint64Field { @@ -2265,7 +2920,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "int32_field" field. public const int Int32FieldFieldNumber = 14; private static readonly pbc::MapField.Codec _map_int32Field_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper(18), 114); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForStructWrapper(18), 114); private readonly pbc::MapField int32Field_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField Int32Field { @@ -2275,7 +2930,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "uint32_field" field. public const int Uint32FieldFieldNumber = 15; private static readonly pbc::MapField.Codec _map_uint32Field_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper(18), 122); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForStructWrapper(18), 122); private readonly pbc::MapField uint32Field_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField Uint32Field { @@ -2285,7 +2940,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "bool_field" field. public const int BoolFieldFieldNumber = 16; private static readonly pbc::MapField.Codec _map_boolField_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper(18), 130); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForStructWrapper(18), 130); private readonly pbc::MapField boolField_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField BoolField { @@ -2295,7 +2950,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "string_field" field. public const int StringFieldFieldNumber = 17; private static readonly pbc::MapField.Codec _map_stringField_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForClassWrapper(18), 138); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForClassWrapper(18), 138); private readonly pbc::MapField stringField_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField StringField { @@ -2305,7 +2960,7 @@ public MapWellKnownTypes Clone() { /// Field number for the "bytes_field" field. public const int BytesFieldFieldNumber = 18; private static readonly pbc::MapField.Codec _map_bytesField_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForClassWrapper(18), 146); + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForClassWrapper(18), 146); private readonly pbc::MapField bytesField_ = new pbc::MapField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::MapField BytesField { @@ -2343,7 +2998,7 @@ public bool Equals(MapWellKnownTypes other) { if (!BoolField.Equals(other.BoolField)) return false; if (!StringField.Equals(other.StringField)) return false; if (!BytesField.Equals(other.BytesField)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2367,6 +3022,9 @@ public override int GetHashCode() { hash ^= BoolField.GetHashCode(); hash ^= StringField.GetHashCode(); hash ^= BytesField.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -2377,6 +3035,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else anyField_.WriteTo(output, _map_anyField_codec); apiField_.WriteTo(output, _map_apiField_codec); durationField_.WriteTo(output, _map_durationField_codec); @@ -2395,7 +3056,38 @@ public void WriteTo(pb::CodedOutputStream output) { boolField_.WriteTo(output, _map_boolField_codec); stringField_.WriteTo(output, _map_stringField_codec); bytesField_.WriteTo(output, _map_bytesField_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + anyField_.WriteTo(ref output, _map_anyField_codec); + apiField_.WriteTo(ref output, _map_apiField_codec); + durationField_.WriteTo(ref output, _map_durationField_codec); + emptyField_.WriteTo(ref output, _map_emptyField_codec); + fieldMaskField_.WriteTo(ref output, _map_fieldMaskField_codec); + sourceContextField_.WriteTo(ref output, _map_sourceContextField_codec); + structField_.WriteTo(ref output, _map_structField_codec); + timestampField_.WriteTo(ref output, _map_timestampField_codec); + typeField_.WriteTo(ref output, _map_typeField_codec); + doubleField_.WriteTo(ref output, _map_doubleField_codec); + floatField_.WriteTo(ref output, _map_floatField_codec); + int64Field_.WriteTo(ref output, _map_int64Field_codec); + uint64Field_.WriteTo(ref output, _map_uint64Field_codec); + int32Field_.WriteTo(ref output, _map_int32Field_codec); + uint32Field_.WriteTo(ref output, _map_uint32Field_codec); + boolField_.WriteTo(ref output, _map_boolField_codec); + stringField_.WriteTo(ref output, _map_stringField_codec); + bytesField_.WriteTo(ref output, _map_bytesField_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -2418,6 +3110,9 @@ public int CalculateSize() { size += boolField_.CalculateSize(_map_boolField_codec); size += stringField_.CalculateSize(_map_stringField_codec); size += bytesField_.CalculateSize(_map_bytesField_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -2444,15 +3139,19 @@ public void MergeFrom(MapWellKnownTypes other) { boolField_.Add(other.boolField_); stringField_.Add(other.stringField_); bytesField_.Add(other.bytesField_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { anyField_.AddEntriesFrom(input, _map_anyField_codec); @@ -2528,7 +3227,94 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + anyField_.AddEntriesFrom(ref input, _map_anyField_codec); + break; + } + case 18: { + apiField_.AddEntriesFrom(ref input, _map_apiField_codec); + break; + } + case 26: { + durationField_.AddEntriesFrom(ref input, _map_durationField_codec); + break; + } + case 34: { + emptyField_.AddEntriesFrom(ref input, _map_emptyField_codec); + break; + } + case 42: { + fieldMaskField_.AddEntriesFrom(ref input, _map_fieldMaskField_codec); + break; + } + case 50: { + sourceContextField_.AddEntriesFrom(ref input, _map_sourceContextField_codec); + break; + } + case 58: { + structField_.AddEntriesFrom(ref input, _map_structField_codec); + break; + } + case 66: { + timestampField_.AddEntriesFrom(ref input, _map_timestampField_codec); + break; + } + case 74: { + typeField_.AddEntriesFrom(ref input, _map_typeField_codec); + break; + } + case 82: { + doubleField_.AddEntriesFrom(ref input, _map_doubleField_codec); + break; + } + case 90: { + floatField_.AddEntriesFrom(ref input, _map_floatField_codec); + break; + } + case 98: { + int64Field_.AddEntriesFrom(ref input, _map_int64Field_codec); + break; + } + case 106: { + uint64Field_.AddEntriesFrom(ref input, _map_uint64Field_codec); + break; + } + case 114: { + int32Field_.AddEntriesFrom(ref input, _map_int32Field_codec); + break; + } + case 122: { + uint32Field_.AddEntriesFrom(ref input, _map_uint32Field_codec); + break; + } + case 130: { + boolField_.AddEntriesFrom(ref input, _map_boolField_codec); + break; + } + case 138: { + stringField_.AddEntriesFrom(ref input, _map_stringField_codec); + break; + } + case 146: { + bytesField_.AddEntriesFrom(ref input, _map_bytesField_codec); + break; + } + } + } } + #endif } diff --git a/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs b/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs new file mode 100644 index 0000000000000..5b9913b29035f --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs @@ -0,0 +1,225 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Buffers; +using System.Diagnostics; + +namespace Google.Protobuf.Buffers +{ + /// + /// Represents a heap-based, array-backed output sink into which data can be written. + /// + /// ArrayBufferWriter is originally from corefx, and has been contributed to Protobuf + /// https://github.com/dotnet/runtime/blob/071da4c41aa808c949a773b92dca6f88de9d11f3/src/libraries/Common/src/System/Buffers/ArrayBufferWriter.cs + /// + internal sealed class ArrayBufferWriter : IBufferWriter + { + private T[] _buffer; + private int _index; + + private const int DefaultInitialBufferSize = 256; + + /// + /// Creates an instance of an , in which data can be written to, + /// with the default initial capacity. + /// + public ArrayBufferWriter() + { + _buffer = new T[0]; + _index = 0; + } + + /// + /// Useful for testing writing to buffer writer with a lot of small segments. + /// If set, it limits the max number of bytes by which the buffer grows by at once. + /// + public int? MaxGrowBy { get; set; } + + /// + /// Creates an instance of an , in which data can be written to, + /// with an initial capacity specified. + /// + /// The minimum capacity with which to initialize the underlying buffer. + /// + /// Thrown when is not positive (i.e. less than or equal to 0). + /// + public ArrayBufferWriter(int initialCapacity) + { + if (initialCapacity <= 0) + throw new ArgumentException(nameof(initialCapacity)); + + _buffer = new T[initialCapacity]; + _index = 0; + } + + /// + /// Returns the data written to the underlying buffer so far, as a . + /// + public ReadOnlyMemory WrittenMemory => _buffer.AsMemory(0, _index); + + /// + /// Returns the data written to the underlying buffer so far, as a . + /// + public ReadOnlySpan WrittenSpan => _buffer.AsSpan(0, _index); + + /// + /// Returns the amount of data written to the underlying buffer so far. + /// + public int WrittenCount => _index; + + /// + /// Returns the total amount of space within the underlying buffer. + /// + public int Capacity => _buffer.Length; + + /// + /// Returns the amount of space available that can still be written into without forcing the underlying buffer to grow. + /// + public int FreeCapacity => _buffer.Length - _index; + + /// + /// Clears the data written to the underlying buffer. + /// + /// + /// You must clear the before trying to re-use it. + /// + public void Clear() + { + Debug.Assert(_buffer.Length >= _index); + _buffer.AsSpan(0, _index).Clear(); + _index = 0; + } + + /// + /// Notifies that amount of data was written to the output / + /// + /// + /// Thrown when is negative. + /// + /// + /// Thrown when attempting to advance past the end of the underlying buffer. + /// + /// + /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer. + /// + public void Advance(int count) + { + if (count < 0) + throw new ArgumentException(nameof(count)); + + if (_index > _buffer.Length - count) + throw new InvalidOperationException("Advanced past capacity."); + + _index += count; + } + + /// + /// Returns a to write to that is at least the requested length (specified by ). + /// If no is provided (or it's equal to 0), some non-empty buffer is returned. + /// + /// + /// Thrown when is negative. + /// + /// + /// This will never return an empty . + /// + /// + /// There is no guarantee that successive calls will return the same buffer or the same-sized buffer. + /// + /// + /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer. + /// + public Memory GetMemory(int sizeHint = 0) + { + CheckAndResizeBuffer(sizeHint); + Debug.Assert(_buffer.Length > _index); + return _buffer.AsMemory(_index); + } + + /// + /// Returns a to write to that is at least the requested length (specified by ). + /// If no is provided (or it's equal to 0), some non-empty buffer is returned. + /// + /// + /// Thrown when is negative. + /// + /// + /// This will never return an empty . + /// + /// + /// There is no guarantee that successive calls will return the same buffer or the same-sized buffer. + /// + /// + /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer. + /// + public Span GetSpan(int sizeHint = 0) + { + CheckAndResizeBuffer(sizeHint); + Debug.Assert(_buffer.Length > _index); + return _buffer.AsSpan(_index); + } + + private void CheckAndResizeBuffer(int sizeHint) + { + if (sizeHint < 0) + throw new ArgumentException(nameof(sizeHint)); + + if (sizeHint == 0) + { + sizeHint = 1; + } + + if (sizeHint > FreeCapacity) + { + int growBy = Math.Max(sizeHint, _buffer.Length); + + if (_buffer.Length == 0) + { + growBy = Math.Max(growBy, DefaultInitialBufferSize); + } + + // enable tests that write to small buffer segments + if (MaxGrowBy.HasValue && growBy > MaxGrowBy.Value) + { + growBy = MaxGrowBy.Value; + } + + int newSize = checked(_buffer.Length + growBy); + + Array.Resize(ref _buffer, newSize); + } + + Debug.Assert(FreeCapacity > 0 && FreeCapacity >= sizeHint); + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/ByteStringTest.cs b/csharp/src/Google.Protobuf.Test/ByteStringTest.cs old mode 100755 new mode 100644 index afdd491f36c17..d9f607448d9c1 --- a/csharp/src/Google.Protobuf.Test/ByteStringTest.cs +++ b/csharp/src/Google.Protobuf.Test/ByteStringTest.cs @@ -34,6 +34,13 @@ using System.Text; using NUnit.Framework; using System.IO; +using System.Collections.Generic; +using System.Collections; +using System.Linq; +using System.Buffers; +using System.Runtime.InteropServices; +using System.Threading; +using System.Runtime.CompilerServices; #if !NET35 using System.Threading.Tasks; #endif @@ -54,6 +61,7 @@ public void Equality() EqualityTester.AssertInequality(b1, b3); EqualityTester.AssertInequality(b1, b4); EqualityTester.AssertInequality(b1, null); + EqualityTester.AssertEquality(ByteString.Empty, ByteString.Empty); #pragma warning disable 1718 // Deliberately calling ==(b1, b1) and !=(b1, b1) Assert.IsTrue(b1 == b1); Assert.IsTrue(b1 == b2); @@ -63,6 +71,7 @@ public void Equality() Assert.IsTrue((ByteString) null == null); Assert.IsFalse(b1 != b1); Assert.IsFalse(b1 != b2); + Assert.IsTrue(ByteString.Empty == ByteString.Empty); #pragma warning disable 1718 Assert.IsTrue(b1 != b3); Assert.IsTrue(b1 != b4); @@ -110,6 +119,18 @@ public void CopyFromByteArrayCopiesContents() Assert.AreEqual(10, bs[0]); } + [Test] + public void CopyFromReadOnlySpanCopiesContents() + { + byte[] data = new byte[1]; + data[0] = 10; + ReadOnlySpan byteSpan = data; + var bs = ByteString.CopyFrom(byteSpan); + Assert.AreEqual(10, bs[0]); + data[0] = 5; + Assert.AreEqual(10, bs[0]); + } + [Test] public void ToByteArrayCopiesContents() { @@ -142,6 +163,84 @@ public void CopyFromPortion() Assert.AreEqual(3, bs[1]); } + [Test] + public void CopyTo() + { + byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 }; + ByteString bs = ByteString.CopyFrom(data); + + byte[] dest = new byte[data.Length]; + bs.CopyTo(dest, 0); + + CollectionAssert.AreEqual(data, dest); + } + + [Test] + public void GetEnumerator() + { + byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 }; + ByteString bs = ByteString.CopyFrom(data); + + IEnumerator genericEnumerator = bs.GetEnumerator(); + Assert.IsTrue(genericEnumerator.MoveNext()); + Assert.AreEqual(0, genericEnumerator.Current); + + IEnumerator enumerator = ((IEnumerable)bs).GetEnumerator(); + Assert.IsTrue(enumerator.MoveNext()); + Assert.AreEqual(0, enumerator.Current); + + // Call via LINQ + CollectionAssert.AreEqual(bs.Span.ToArray(), bs.ToArray()); + } + + [Test] + public void UnsafeWrap() + { + byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 }; + ByteString bs = UnsafeByteOperations.UnsafeWrap(data.AsMemory(2, 3)); + ReadOnlySpan s = bs.Span; + + Assert.AreEqual(3, s.Length); + Assert.AreEqual(2, s[0]); + Assert.AreEqual(3, s[1]); + Assert.AreEqual(4, s[2]); + + // Check that the value is not a copy + data[2] = byte.MaxValue; + Assert.AreEqual(byte.MaxValue, s[0]); + } + + [Test] + public void WriteToStream() + { + byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 }; + ByteString bs = ByteString.CopyFrom(data); + + MemoryStream ms = new MemoryStream(); + bs.WriteTo(ms); + + CollectionAssert.AreEqual(data, ms.ToArray()); + } + + [Test] + public void WriteToStream_Stackalloc() + { + byte[] data = Encoding.UTF8.GetBytes("Hello world"); + Span s = stackalloc byte[data.Length]; + data.CopyTo(s); + + MemoryStream ms = new MemoryStream(); + + using (UnmanagedMemoryManager manager = new UnmanagedMemoryManager(s)) + { + ByteString bs = ByteString.AttachBytes(manager.Memory); + + bs.WriteTo(ms); + } + + CollectionAssert.AreEqual(data, ms.ToArray()); + } + [Test] public void ToStringUtf8() { @@ -156,6 +255,21 @@ public void ToStringWithExplicitEncoding() Assert.AreEqual("\u20ac", bs.ToString(Encoding.Unicode)); } + [Test] + public void ToString_Stackalloc() + { + byte[] data = Encoding.UTF8.GetBytes("Hello world"); + Span s = stackalloc byte[data.Length]; + data.CopyTo(s); + + using (UnmanagedMemoryManager manager = new UnmanagedMemoryManager(s)) + { + ByteString bs = ByteString.AttachBytes(manager.Memory); + + Assert.AreEqual("Hello world", bs.ToString(Encoding.UTF8)); + } + } + [Test] public void FromBase64_WithText() { @@ -172,6 +286,29 @@ public void FromBase64_Empty() Assert.AreSame(ByteString.Empty, ByteString.FromBase64("")); } + [Test] + public void ToBase64_Array() + { + ByteString bs = ByteString.CopyFrom(Encoding.UTF8.GetBytes("Hello world")); + + Assert.AreEqual("SGVsbG8gd29ybGQ=", bs.ToBase64()); + } + + [Test] + public void ToBase64_Stackalloc() + { + byte[] data = Encoding.UTF8.GetBytes("Hello world"); + Span s = stackalloc byte[data.Length]; + data.CopyTo(s); + + using (UnmanagedMemoryManager manager = new UnmanagedMemoryManager(s)) + { + ByteString bs = ByteString.AttachBytes(manager.Memory); + + Assert.AreEqual("SGVsbG8gd29ybGQ=", bs.ToBase64()); + } + } + [Test] public void FromStream_Seekable() { @@ -227,11 +364,60 @@ public void GetHashCode_Regression() { // We used to have an awful hash algorithm where only the last four // bytes were relevant. This is a regression test for - // https://github.com/google/protobuf/issues/2511 + // https://github.com/protocolbuffers/protobuf/issues/2511 ByteString b1 = ByteString.CopyFrom(100, 1, 2, 3, 4); ByteString b2 = ByteString.CopyFrom(200, 1, 2, 3, 4); Assert.AreNotEqual(b1.GetHashCode(), b2.GetHashCode()); } + + [Test] + public void GetContentsAsReadOnlySpan() + { + var byteString = ByteString.CopyFrom(1, 2, 3, 4, 5); + var copied = byteString.Span.ToArray(); + CollectionAssert.AreEqual(byteString, copied); + } + + [Test] + public void GetContentsAsReadOnlyMemory() + { + var byteString = ByteString.CopyFrom(1, 2, 3, 4, 5); + var copied = byteString.Memory.ToArray(); + CollectionAssert.AreEqual(byteString, copied); + } + + // Create Memory from non-array source. + // Use by ByteString tests that have optimized path for array backed Memory. + private sealed unsafe class UnmanagedMemoryManager : MemoryManager where T : unmanaged + { + private readonly T* _pointer; + private readonly int _length; + + public UnmanagedMemoryManager(Span span) + { + fixed (T* ptr = &MemoryMarshal.GetReference(span)) + { + _pointer = ptr; + _length = span.Length; + } + } + + public override Span GetSpan() => new Span(_pointer, _length); + + public override MemoryHandle Pin(int elementIndex = 0) + { + if (elementIndex < 0 || elementIndex >= _length) + { + throw new ArgumentOutOfRangeException(nameof(elementIndex)); + } + + return new MemoryHandle(_pointer + elementIndex); + } + + public override void Unpin() { } + + protected override void Dispose(bool disposing) { } + } } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs index e719d2a09023c..0ad286f3787f5 100644 --- a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs +++ b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs @@ -31,8 +31,10 @@ #endregion using System; +using System.Buffers; using System.IO; using Google.Protobuf.TestProtos; +using Proto2 = Google.Protobuf.TestProtos.Proto2; using NUnit.Framework; namespace Google.Protobuf @@ -61,11 +63,22 @@ private static void AssertReadVarint(byte[] data, ulong value) { CodedInputStream input = new CodedInputStream(data); Assert.AreEqual((uint) value, input.ReadRawVarint32()); + Assert.IsTrue(input.IsAtEnd); input = new CodedInputStream(data); Assert.AreEqual(value, input.ReadRawVarint64()); Assert.IsTrue(input.IsAtEnd); + AssertReadFromParseContext(new ReadOnlySequence(data), (ref ParseContext ctx) => + { + Assert.AreEqual((uint) value, ctx.ReadUInt32()); + }, true); + + AssertReadFromParseContext(new ReadOnlySequence(data), (ref ParseContext ctx) => + { + Assert.AreEqual(value, ctx.ReadUInt64()); + }, true); + // Try different block sizes. for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) { @@ -75,6 +88,16 @@ private static void AssertReadVarint(byte[] data, ulong value) input = new CodedInputStream(new SmallBlockInputStream(data, bufferSize)); Assert.AreEqual(value, input.ReadRawVarint64()); Assert.IsTrue(input.IsAtEnd); + + AssertReadFromParseContext(ReadOnlySequenceFactory.CreateWithContent(data, bufferSize), (ref ParseContext ctx) => + { + Assert.AreEqual((uint) value, ctx.ReadUInt32()); + }, true); + + AssertReadFromParseContext(ReadOnlySequenceFactory.CreateWithContent(data, bufferSize), (ref ParseContext ctx) => + { + Assert.AreEqual(value, ctx.ReadUInt64()); + }, true); } // Try reading directly from a MemoryStream. We want to verify that it @@ -103,11 +126,49 @@ private static void AssertReadVarintFailure(InvalidProtocolBufferException expec exception = Assert.Throws(() => input.ReadRawVarint64()); Assert.AreEqual(expected.Message, exception.Message); + AssertReadFromParseContext(new ReadOnlySequence(data), (ref ParseContext ctx) => + { + try + { + ctx.ReadUInt32(); + Assert.Fail(); + } + catch (InvalidProtocolBufferException ex) + { + Assert.AreEqual(expected.Message, ex.Message); + } + }, false); + + AssertReadFromParseContext(new ReadOnlySequence(data), (ref ParseContext ctx) => + { + try + { + ctx.ReadUInt64(); + Assert.Fail(); + } + catch (InvalidProtocolBufferException ex) + { + Assert.AreEqual(expected.Message, ex.Message); + } + }, false); + // Make sure we get the same error when reading directly from a Stream. exception = Assert.Throws(() => CodedInputStream.ReadRawVarint32(new MemoryStream(data))); Assert.AreEqual(expected.Message, exception.Message); } + private delegate void ParseContextAssertAction(ref ParseContext ctx); + + private static void AssertReadFromParseContext(ReadOnlySequence input, ParseContextAssertAction assertAction, bool assertIsAtEnd) + { + ParseContext.Initialize(input, out ParseContext parseCtx); + assertAction(ref parseCtx); + if (assertIsAtEnd) + { + Assert.IsTrue(SegmentedBufferHelper.IsAtEnd(ref parseCtx.buffer, ref parseCtx.state)); + } + } + [Test] public void ReadVarint() { @@ -156,6 +217,11 @@ private static void AssertReadLittleEndian32(byte[] data, uint value) Assert.AreEqual(value, input.ReadRawLittleEndian32()); Assert.IsTrue(input.IsAtEnd); + AssertReadFromParseContext(new ReadOnlySequence(data), (ref ParseContext ctx) => + { + Assert.AreEqual(value, ctx.ReadFixed32()); + }, true); + // Try different block sizes. for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { @@ -163,6 +229,11 @@ private static void AssertReadLittleEndian32(byte[] data, uint value) new SmallBlockInputStream(data, blockSize)); Assert.AreEqual(value, input.ReadRawLittleEndian32()); Assert.IsTrue(input.IsAtEnd); + + AssertReadFromParseContext(ReadOnlySequenceFactory.CreateWithContent(data, blockSize), (ref ParseContext ctx) => + { + Assert.AreEqual(value, ctx.ReadFixed32()); + }, true); } } @@ -176,6 +247,11 @@ private static void AssertReadLittleEndian64(byte[] data, ulong value) Assert.AreEqual(value, input.ReadRawLittleEndian64()); Assert.IsTrue(input.IsAtEnd); + AssertReadFromParseContext(new ReadOnlySequence(data), (ref ParseContext ctx) => + { + Assert.AreEqual(value, ctx.ReadFixed64()); + }, true); + // Try different block sizes. for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { @@ -183,6 +259,11 @@ private static void AssertReadLittleEndian64(byte[] data, ulong value) new SmallBlockInputStream(data, blockSize)); Assert.AreEqual(value, input.ReadRawLittleEndian64()); Assert.IsTrue(input.IsAtEnd); + + AssertReadFromParseContext(ReadOnlySequenceFactory.CreateWithContent(data, blockSize), (ref ParseContext ctx) => + { + Assert.AreEqual(value, ctx.ReadFixed64()); + }, true); } } @@ -201,29 +282,29 @@ public void ReadLittleEndian() [Test] public void DecodeZigZag32() { - Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(0)); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(1)); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(2)); - Assert.AreEqual(-2, CodedInputStream.DecodeZigZag32(3)); - Assert.AreEqual(0x3FFFFFFF, CodedInputStream.DecodeZigZag32(0x7FFFFFFE)); - Assert.AreEqual(unchecked((int) 0xC0000000), CodedInputStream.DecodeZigZag32(0x7FFFFFFF)); - Assert.AreEqual(0x7FFFFFFF, CodedInputStream.DecodeZigZag32(0xFFFFFFFE)); - Assert.AreEqual(unchecked((int) 0x80000000), CodedInputStream.DecodeZigZag32(0xFFFFFFFF)); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(0)); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(1)); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(2)); + Assert.AreEqual(-2, ParsingPrimitives.DecodeZigZag32(3)); + Assert.AreEqual(0x3FFFFFFF, ParsingPrimitives.DecodeZigZag32(0x7FFFFFFE)); + Assert.AreEqual(unchecked((int) 0xC0000000), ParsingPrimitives.DecodeZigZag32(0x7FFFFFFF)); + Assert.AreEqual(0x7FFFFFFF, ParsingPrimitives.DecodeZigZag32(0xFFFFFFFE)); + Assert.AreEqual(unchecked((int) 0x80000000), ParsingPrimitives.DecodeZigZag32(0xFFFFFFFF)); } [Test] public void DecodeZigZag64() { - Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(0)); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(1)); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(2)); - Assert.AreEqual(-2, CodedInputStream.DecodeZigZag64(3)); - Assert.AreEqual(0x000000003FFFFFFFL, CodedInputStream.DecodeZigZag64(0x000000007FFFFFFEL)); - Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), CodedInputStream.DecodeZigZag64(0x000000007FFFFFFFL)); - Assert.AreEqual(0x000000007FFFFFFFL, CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFEL)); - Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFFL)); - Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL)); - Assert.AreEqual(unchecked((long) 0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL)); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(0)); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(1)); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(2)); + Assert.AreEqual(-2, ParsingPrimitives.DecodeZigZag64(3)); + Assert.AreEqual(0x000000003FFFFFFFL, ParsingPrimitives.DecodeZigZag64(0x000000007FFFFFFEL)); + Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), ParsingPrimitives.DecodeZigZag64(0x000000007FFFFFFFL)); + Assert.AreEqual(0x000000007FFFFFFFL, ParsingPrimitives.DecodeZigZag64(0x00000000FFFFFFFEL)); + Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), ParsingPrimitives.DecodeZigZag64(0x00000000FFFFFFFFL)); + Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, ParsingPrimitives.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL)); + Assert.AreEqual(unchecked((long) 0x8000000000000000L), ParsingPrimitives.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL)); } [Test] @@ -243,7 +324,44 @@ public void ReadWholeMessage_VaryingBlockSizes() Assert.AreEqual(message, message2); } } - + + [Test] + public void ReadWholeMessage_VaryingBlockSizes_FromSequence() + { + TestAllTypes message = SampleMessages.CreateFullTestAllTypes(); + + byte[] rawBytes = message.ToByteArray(); + Assert.AreEqual(rawBytes.Length, message.CalculateSize()); + TestAllTypes message2 = TestAllTypes.Parser.ParseFrom(rawBytes); + Assert.AreEqual(message, message2); + + // Try different block sizes. + for (int blockSize = 1; blockSize < 256; blockSize *= 2) + { + message2 = TestAllTypes.Parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(rawBytes, blockSize)); + Assert.AreEqual(message, message2); + } + } + + [Test] + public void ReadInt32Wrapper_VariableBlockSizes() + { + byte[] rawBytes = new byte[] { 202, 1, 11, 8, 254, 255, 255, 255, 255, 255, 255, 255, 255, 1 }; + + for (int blockSize = 1; blockSize <= rawBytes.Length; blockSize++) + { + ReadOnlySequence data = ReadOnlySequenceFactory.CreateWithContent(rawBytes, blockSize); + AssertReadFromParseContext(data, (ref ParseContext ctx) => + { + ctx.ReadTag(); + + var value = ParsingPrimitivesWrappers.ReadInt32Wrapper(ref ctx); + + Assert.AreEqual(-2, value); + }, true); + } + } + [Test] public void ReadHugeBlob() { @@ -284,6 +402,84 @@ public void ReadMaliciouslyLargeBlob() Assert.Throws(() => input.ReadBytes()); } + [Test] + public void ReadBlobGreaterThanCurrentLimit() + { + MemoryStream ms = new MemoryStream(); + CodedOutputStream output = new CodedOutputStream(ms); + uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited); + output.WriteRawVarint32(tag); + output.WriteRawVarint32(4); + output.WriteRawBytes(new byte[4]); // Pad with a few random bytes. + output.Flush(); + ms.Position = 0; + + CodedInputStream input = new CodedInputStream(ms); + Assert.AreEqual(tag, input.ReadTag()); + + // Specify limit smaller than data length + input.PushLimit(3); + Assert.Throws(() => input.ReadBytes()); + + AssertReadFromParseContext(new ReadOnlySequence(ms.ToArray()), (ref ParseContext ctx) => + { + Assert.AreEqual(tag, ctx.ReadTag()); + SegmentedBufferHelper.PushLimit(ref ctx.state, 3); + try + { + ctx.ReadBytes(); + Assert.Fail(); + } + catch (InvalidProtocolBufferException) {} + }, true); + } + + [Test] + public void ReadStringGreaterThanCurrentLimit() + { + MemoryStream ms = new MemoryStream(); + CodedOutputStream output = new CodedOutputStream(ms); + uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited); + output.WriteRawVarint32(tag); + output.WriteRawVarint32(4); + output.WriteRawBytes(new byte[4]); // Pad with a few random bytes. + output.Flush(); + ms.Position = 0; + + CodedInputStream input = new CodedInputStream(ms.ToArray()); + Assert.AreEqual(tag, input.ReadTag()); + + // Specify limit smaller than data length + input.PushLimit(3); + Assert.Throws(() => input.ReadString()); + + AssertReadFromParseContext(new ReadOnlySequence(ms.ToArray()), (ref ParseContext ctx) => + { + Assert.AreEqual(tag, ctx.ReadTag()); + SegmentedBufferHelper.PushLimit(ref ctx.state, 3); + try + { + ctx.ReadString(); + Assert.Fail(); + } + catch (InvalidProtocolBufferException) { } + }, true); + } + + // Representations of a tag for field 0 with various wire types + [Test] + [TestCase(0)] + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + [TestCase(4)] + [TestCase(5)] + public void ReadTag_ZeroFieldRejected(byte tag) + { + CodedInputStream cis = new CodedInputStream(new byte[] { tag }); + Assert.Throws(() => cis.ReadTag()); + } + internal static TestRecursiveMessage MakeRecursiveMessage(int depth) { if (depth == 0) @@ -313,16 +509,76 @@ internal static void AssertMessageDepth(TestRecursiveMessage message, int depth) [Test] public void MaliciousRecursion() { - ByteString data64 = MakeRecursiveMessage(64).ToByteString(); - ByteString data65 = MakeRecursiveMessage(65).ToByteString(); + ByteString atRecursiveLimit = MakeRecursiveMessage(CodedInputStream.DefaultRecursionLimit).ToByteString(); + ByteString beyondRecursiveLimit = MakeRecursiveMessage(CodedInputStream.DefaultRecursionLimit + 1).ToByteString(); - AssertMessageDepth(TestRecursiveMessage.Parser.ParseFrom(data64), 64); + AssertMessageDepth(TestRecursiveMessage.Parser.ParseFrom(atRecursiveLimit), CodedInputStream.DefaultRecursionLimit); - Assert.Throws(() => TestRecursiveMessage.Parser.ParseFrom(data65)); + Assert.Throws(() => TestRecursiveMessage.Parser.ParseFrom(beyondRecursiveLimit)); - CodedInputStream input = CodedInputStream.CreateWithLimits(new MemoryStream(data64.ToByteArray()), 1000000, 63); + CodedInputStream input = CodedInputStream.CreateWithLimits(new MemoryStream(atRecursiveLimit.ToByteArray()), 1000000, CodedInputStream.DefaultRecursionLimit - 1); Assert.Throws(() => TestRecursiveMessage.Parser.ParseFrom(input)); } + + private static byte[] MakeMaliciousRecursionUnknownFieldsPayload(int recursionDepth) + { + // generate recursively nested groups that will be parsed as unknown fields + int unknownFieldNumber = 14; // an unused field number + MemoryStream ms = new MemoryStream(); + CodedOutputStream output = new CodedOutputStream(ms); + for (int i = 0; i < recursionDepth; i++) + { + output.WriteTag(WireFormat.MakeTag(unknownFieldNumber, WireFormat.WireType.StartGroup)); + } + for (int i = 0; i < recursionDepth; i++) + { + output.WriteTag(WireFormat.MakeTag(unknownFieldNumber, WireFormat.WireType.EndGroup)); + } + output.Flush(); + return ms.ToArray(); + } + + [Test] + public void MaliciousRecursion_UnknownFields() + { + byte[] payloadAtRecursiveLimit = MakeMaliciousRecursionUnknownFieldsPayload(CodedInputStream.DefaultRecursionLimit); + byte[] payloadBeyondRecursiveLimit = MakeMaliciousRecursionUnknownFieldsPayload(CodedInputStream.DefaultRecursionLimit + 1); + + Assert.DoesNotThrow(() => TestRecursiveMessage.Parser.ParseFrom(payloadAtRecursiveLimit)); + Assert.Throws(() => TestRecursiveMessage.Parser.ParseFrom(payloadBeyondRecursiveLimit)); + } + + [Test] + public void ReadGroup_WrongEndGroupTag() + { + int groupFieldNumber = Proto2.TestAllTypes.OptionalGroupFieldNumber; + + // write Proto2.TestAllTypes with "optional_group" set, but use wrong EndGroup closing tag + MemoryStream ms = new MemoryStream(); + CodedOutputStream output = new CodedOutputStream(ms); + output.WriteTag(WireFormat.MakeTag(groupFieldNumber, WireFormat.WireType.StartGroup)); + output.WriteGroup(new Proto2.TestAllTypes.Types.OptionalGroup { A = 12345 }); + // end group with different field number + output.WriteTag(WireFormat.MakeTag(groupFieldNumber + 1, WireFormat.WireType.EndGroup)); + output.Flush(); + var payload = ms.ToArray(); + + Assert.Throws(() => Proto2.TestAllTypes.Parser.ParseFrom(payload)); + } + + [Test] + public void ReadGroup_UnknownFields_WrongEndGroupTag() + { + MemoryStream ms = new MemoryStream(); + CodedOutputStream output = new CodedOutputStream(ms); + output.WriteTag(WireFormat.MakeTag(14, WireFormat.WireType.StartGroup)); + // end group with different field number + output.WriteTag(WireFormat.MakeTag(15, WireFormat.WireType.EndGroup)); + output.Flush(); + var payload = ms.ToArray(); + + Assert.Throws(() => TestRecursiveMessage.Parser.ParseFrom(payload)); + } [Test] public void SizeLimit() @@ -359,6 +615,42 @@ public void ReadInvalidUtf8() Assert.AreEqual('\ufffd', text[0]); } + [Test] + public void ReadNegativeSizedStringThrowsInvalidProtocolBufferException() + { + MemoryStream ms = new MemoryStream(); + CodedOutputStream output = new CodedOutputStream(ms); + + uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited); + output.WriteRawVarint32(tag); + output.WriteLength(-1); + output.Flush(); + ms.Position = 0; + + CodedInputStream input = new CodedInputStream(ms); + + Assert.AreEqual(tag, input.ReadTag()); + Assert.Throws(() => input.ReadString()); + } + + [Test] + public void ReadNegativeSizedBytesThrowsInvalidProtocolBufferException() + { + MemoryStream ms = new MemoryStream(); + CodedOutputStream output = new CodedOutputStream(ms); + + uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited); + output.WriteRawVarint32(tag); + output.WriteLength(-1); + output.Flush(); + ms.Position = 0; + + CodedInputStream input = new CodedInputStream(ms); + + Assert.AreEqual(tag, input.ReadTag()); + Assert.Throws(() => input.ReadBytes()); + } + /// /// A stream which limits the number of bytes it reads at a time. /// We use this to make sure that CodedInputStream doesn't screw up when @@ -601,5 +893,88 @@ public void Dispose_FromByteArray() var stream = new CodedInputStream(new byte[10]); stream.Dispose(); } + + [Test] + public void TestParseMessagesCloseTo2G() + { + byte[] serializedMessage = GenerateBigSerializedMessage(); + // How many of these big messages do we need to take us near our 2GB limit? + int count = Int32.MaxValue / serializedMessage.Length; + // Now make a MemoryStream that will fake a near-2GB stream of messages by returning + // our big serialized message 'count' times. + using (RepeatingMemoryStream stream = new RepeatingMemoryStream(serializedMessage, count)) + { + Assert.DoesNotThrow(()=>TestAllTypes.Parser.ParseFrom(stream)); + } + } + + [Test] + public void TestParseMessagesOver2G() + { + byte[] serializedMessage = GenerateBigSerializedMessage(); + // How many of these big messages do we need to take us near our 2GB limit? + int count = Int32.MaxValue / serializedMessage.Length; + // Now add one to take us over the 2GB limit + count++; + // Now make a MemoryStream that will fake a near-2GB stream of messages by returning + // our big serialized message 'count' times. + using (RepeatingMemoryStream stream = new RepeatingMemoryStream(serializedMessage, count)) + { + Assert.Throws(() => TestAllTypes.Parser.ParseFrom(stream), + "Protocol message was too large. May be malicious. " + + "Use CodedInputStream.SetSizeLimit() to increase the size limit."); + } + } + + /// A serialized big message + private static byte[] GenerateBigSerializedMessage() + { + byte[] value = new byte[16 * 1024 * 1024]; + TestAllTypes message = SampleMessages.CreateFullTestAllTypes(); + message.SingleBytes = ByteString.CopyFrom(value); + return message.ToByteArray(); + } + + /// + /// A MemoryStream that repeats a byte arrays' content a number of times. + /// Simulates really large input without consuming loads of memory. Used above + /// to test the parsing behavior when the input size exceeds 2GB or close to it. + /// + private class RepeatingMemoryStream: MemoryStream + { + private readonly byte[] bytes; + private readonly int maxIterations; + private int index = 0; + + public RepeatingMemoryStream(byte[] bytes, int maxIterations) + { + this.bytes = bytes; + this.maxIterations = maxIterations; + } + + public override int Read(byte[] buffer, int offset, int count) + { + if (bytes.Length == 0) + { + return 0; + } + int numBytesCopiedTotal = 0; + while (numBytesCopiedTotal < count && index < maxIterations) + { + int numBytesToCopy = Math.Min(bytes.Length - (int)Position, count); + Array.Copy(bytes, (int)Position, buffer, offset, numBytesToCopy); + numBytesCopiedTotal += numBytesToCopy; + offset += numBytesToCopy; + count -= numBytesCopiedTotal; + Position += numBytesToCopy; + if (Position >= bytes.Length) + { + Position = 0; + index++; + } + } + return numBytesCopiedTotal; + } + } } -} \ No newline at end of file +} diff --git a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs index 98cabd55adc48..1e5333c96501c 100644 --- a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs +++ b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs @@ -33,7 +33,9 @@ using System; using System.IO; using Google.Protobuf.TestProtos; +using Google.Protobuf.Buffers; using NUnit.Framework; +using System.Text; namespace Google.Protobuf { @@ -48,22 +50,39 @@ private static void AssertWriteVarint(byte[] data, ulong value) // Only do 32-bit write if the value fits in 32 bits. if ((value >> 32) == 0) { + // CodedOutputStream MemoryStream rawOutput = new MemoryStream(); CodedOutputStream output = new CodedOutputStream(rawOutput); output.WriteRawVarint32((uint) value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); + + // IBufferWriter + var bufferWriter = new ArrayBufferWriter(); + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteUInt32((uint) value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); + // Also try computing size. Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint32Size((uint) value)); } { + // CodedOutputStream MemoryStream rawOutput = new MemoryStream(); CodedOutputStream output = new CodedOutputStream(rawOutput); output.WriteRawVarint64(value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); + // IBufferWriter + var bufferWriter = new ArrayBufferWriter(); + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteUInt64(value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); + // Also try computing size. Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint64Size(value)); } @@ -80,6 +99,13 @@ private static void AssertWriteVarint(byte[] data, ulong value) output.WriteRawVarint32((uint) value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); + + var bufferWriter = new ArrayBufferWriter(); + bufferWriter.MaxGrowBy = bufferSize; + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteUInt32((uint) value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); } { @@ -88,7 +114,15 @@ private static void AssertWriteVarint(byte[] data, ulong value) output.WriteRawVarint64(value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); + + var bufferWriter = new ArrayBufferWriter(); + bufferWriter.MaxGrowBy = bufferSize; + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteUInt64(value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); } + } } @@ -133,20 +167,35 @@ public void WriteVarint() /// private static void AssertWriteLittleEndian32(byte[] data, uint value) { - MemoryStream rawOutput = new MemoryStream(); - CodedOutputStream output = new CodedOutputStream(rawOutput); - output.WriteRawLittleEndian32(value); - output.Flush(); - Assert.AreEqual(data, rawOutput.ToArray()); + { + var rawOutput = new MemoryStream(); + var output = new CodedOutputStream(rawOutput); + output.WriteRawLittleEndian32(value); + output.Flush(); + Assert.AreEqual(data, rawOutput.ToArray()); + + var bufferWriter = new ArrayBufferWriter(); + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteFixed32(value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); + } // Try different buffer sizes. for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) { - rawOutput = new MemoryStream(); - output = new CodedOutputStream(rawOutput, bufferSize); + var rawOutput = new MemoryStream(); + var output = new CodedOutputStream(rawOutput, bufferSize); output.WriteRawLittleEndian32(value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); + + var bufferWriter = new ArrayBufferWriter(); + bufferWriter.MaxGrowBy = bufferSize; + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteFixed32(value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); } } @@ -156,20 +205,35 @@ private static void AssertWriteLittleEndian32(byte[] data, uint value) /// private static void AssertWriteLittleEndian64(byte[] data, ulong value) { - MemoryStream rawOutput = new MemoryStream(); - CodedOutputStream output = new CodedOutputStream(rawOutput); - output.WriteRawLittleEndian64(value); - output.Flush(); - Assert.AreEqual(data, rawOutput.ToArray()); + { + var rawOutput = new MemoryStream(); + var output = new CodedOutputStream(rawOutput); + output.WriteRawLittleEndian64(value); + output.Flush(); + Assert.AreEqual(data, rawOutput.ToArray()); + + var bufferWriter = new ArrayBufferWriter(); + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteFixed64(value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); + } // Try different block sizes. for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { - rawOutput = new MemoryStream(); - output = new CodedOutputStream(rawOutput, blockSize); + var rawOutput = new MemoryStream(); + var output = new CodedOutputStream(rawOutput, blockSize); output.WriteRawLittleEndian64(value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); + + var bufferWriter = new ArrayBufferWriter(); + bufferWriter.MaxGrowBy = blockSize; + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteFixed64(value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); } } @@ -205,41 +269,72 @@ public void WriteWholeMessage_VaryingBlockSizes() message.WriteTo(output); output.Flush(); Assert.AreEqual(rawBytes, rawOutput.ToArray()); + + var bufferWriter = new ArrayBufferWriter(); + bufferWriter.MaxGrowBy = blockSize; + message.WriteTo(bufferWriter); + Assert.AreEqual(rawBytes, bufferWriter.WrittenSpan.ToArray()); } } + + [Test] + public void WriteContext_WritesWithFlushes() + { + TestAllTypes message = SampleMessages.CreateFullTestAllTypes(); + + MemoryStream expectedOutput = new MemoryStream(); + CodedOutputStream output = new CodedOutputStream(expectedOutput); + output.WriteMessage(message); + output.Flush(); + byte[] expectedBytes1 = expectedOutput.ToArray(); + + output.WriteMessage(message); + output.Flush(); + byte[] expectedBytes2 = expectedOutput.ToArray(); + + var bufferWriter = new ArrayBufferWriter(); + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteMessage(message); + ctx.Flush(); + Assert.AreEqual(expectedBytes1, bufferWriter.WrittenSpan.ToArray()); + + ctx.WriteMessage(message); + ctx.Flush(); + Assert.AreEqual(expectedBytes2, bufferWriter.WrittenSpan.ToArray()); + } [Test] public void EncodeZigZag32() { - Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag32(0)); - Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag32(-1)); - Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag32(1)); - Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag32(-2)); - Assert.AreEqual(0x7FFFFFFEu, CodedOutputStream.EncodeZigZag32(0x3FFFFFFF)); - Assert.AreEqual(0x7FFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0xC0000000))); - Assert.AreEqual(0xFFFFFFFEu, CodedOutputStream.EncodeZigZag32(0x7FFFFFFF)); - Assert.AreEqual(0xFFFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0x80000000))); + Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag32(0)); + Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag32(-1)); + Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag32(1)); + Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag32(-2)); + Assert.AreEqual(0x7FFFFFFEu, WritingPrimitives.EncodeZigZag32(0x3FFFFFFF)); + Assert.AreEqual(0x7FFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0xC0000000))); + Assert.AreEqual(0xFFFFFFFEu, WritingPrimitives.EncodeZigZag32(0x7FFFFFFF)); + Assert.AreEqual(0xFFFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0x80000000))); } [Test] public void EncodeZigZag64() { - Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag64(0)); - Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag64(-1)); - Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag64(1)); - Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag64(-2)); + Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag64(0)); + Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag64(-1)); + Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag64(1)); + Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag64(-2)); Assert.AreEqual(0x000000007FFFFFFEuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL))); Assert.AreEqual(0x000000007FFFFFFFuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL))); Assert.AreEqual(0x00000000FFFFFFFEuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL))); Assert.AreEqual(0x00000000FFFFFFFFuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL))); Assert.AreEqual(0xFFFFFFFFFFFFFFFEL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL))); Assert.AreEqual(0xFFFFFFFFFFFFFFFFL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x8000000000000000UL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x8000000000000000UL))); } [Test] @@ -247,26 +342,26 @@ public void RoundTripZigZag32() { // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1) // were chosen semi-randomly via keyboard bashing. - Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0))); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1))); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1))); - Assert.AreEqual(14927, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927))); - Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612))); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(0))); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(1))); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-1))); + Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(14927))); + Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-3612))); } [Test] public void RoundTripZigZag64() { - Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0))); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1))); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1))); - Assert.AreEqual(14927, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927))); - Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612))); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(0))); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(1))); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-1))); + Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(14927))); + Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-3612))); Assert.AreEqual(856912304801416L, - CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L))); + ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(856912304801416L))); Assert.AreEqual(-75123905439571256L, - CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L))); + ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-75123905439571256L))); } [Test] @@ -395,7 +490,7 @@ public void Dispose_DisposesUnderlyingStream() Assert.IsTrue(memoryStream.CanWrite); using (var cos = new CodedOutputStream(memoryStream)) { - cos.WriteRawByte(0); + cos.WriteRawBytes(new byte[] {0}); Assert.AreEqual(0, memoryStream.Position); // Not flushed yet } Assert.AreEqual(1, memoryStream.ToArray().Length); // Flushed data from CodedOutputStream to MemoryStream @@ -409,7 +504,7 @@ public void Dispose_WithLeaveOpen() Assert.IsTrue(memoryStream.CanWrite); using (var cos = new CodedOutputStream(memoryStream, true)) { - cos.WriteRawByte(0); + cos.WriteRawBytes(new byte[] {0}); Assert.AreEqual(0, memoryStream.Position); // Not flushed yet } Assert.AreEqual(1, memoryStream.Position); // Flushed data from CodedOutputStream to MemoryStream @@ -422,5 +517,28 @@ public void Dispose_FromByteArray() var stream = new CodedOutputStream(new byte[10]); stream.Dispose(); } + + [Test] + public void WriteStringsOfDifferentSizes() + { + for (int i = 1; i <= 1024; i++) + { + var buffer = new byte[4096]; + var output = new CodedOutputStream(buffer); + var sb = new StringBuilder(); + for (int j = 0; j < i; j++) + { + sb.Append((j % 10).ToString()); // incrementing numbers, repeating + } + var s = sb.ToString(); + output.WriteString(s); + + output.Flush(); + + // Verify written content + var input = new CodedInputStream(buffer); + Assert.AreEqual(s, input.ReadString()); + } + } } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs index 68b4de45f68c3..d4c63dc68806c 100644 --- a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs +++ b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs @@ -31,6 +31,7 @@ #endregion using System; +using System.IO; using System.Collections.Generic; using Google.Protobuf.TestProtos; using NUnit.Framework; @@ -86,7 +87,7 @@ public void Indexer_ForbidsNullKeys() var map = new MapField(); Assert.Throws(() => map[null] = new ForeignMessage()); } - + [Test] public void AddPreservesInsertionOrder() { @@ -471,7 +472,7 @@ public void ViewCopyTo() keys.CopyTo(array, 1); CollectionAssert.AreEqual(new[] { null, "foo", "x", null }, array); } - + // Just test keys - we know the implementation is the same for values [Test] public void NonGenericViewCopyTo() @@ -540,6 +541,102 @@ public void ToString_UnsupportedKeyType() Assert.Throws(() => map.ToString()); } + [Test] + public void NaNValuesComparedBitwise() + { + var map1 = new MapField + { + { "x", SampleNaNs.Regular }, + { "y", SampleNaNs.SignallingFlipped } + }; + + var map2 = new MapField + { + { "x", SampleNaNs.Regular }, + { "y", SampleNaNs.PayloadFlipped } + }; + + var map3 = new MapField + { + { "x", SampleNaNs.Regular }, + { "y", SampleNaNs.SignallingFlipped } + }; + + EqualityTester.AssertInequality(map1, map2); + EqualityTester.AssertEquality(map1, map3); + Assert.True(map1.Values.Contains(SampleNaNs.SignallingFlipped)); + Assert.False(map2.Values.Contains(SampleNaNs.SignallingFlipped)); + } + + // This wouldn't usually happen, as protos can't use doubles as map keys, + // but let's be consistent. + [Test] + public void NaNKeysComparedBitwise() + { + var map = new MapField + { + { SampleNaNs.Regular, "x" }, + { SampleNaNs.SignallingFlipped, "y" } + }; + Assert.AreEqual("x", map[SampleNaNs.Regular]); + Assert.AreEqual("y", map[SampleNaNs.SignallingFlipped]); + string ignored; + Assert.False(map.TryGetValue(SampleNaNs.PayloadFlipped, out ignored)); + } + + [Test] + public void AddEntriesFrom_CodedInputStream() + { + // map will have string key and string value + var keyTag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited); + var valueTag = WireFormat.MakeTag(2, WireFormat.WireType.LengthDelimited); + + var memoryStream = new MemoryStream(); + var output = new CodedOutputStream(memoryStream); + output.WriteLength(20); // total of keyTag + key + valueTag + value + output.WriteTag(keyTag); + output.WriteString("the_key"); + output.WriteTag(valueTag); + output.WriteString("the_value"); + output.Flush(); + + var field = new MapField(); + var mapCodec = new MapField.Codec(FieldCodec.ForString(keyTag, ""), FieldCodec.ForString(valueTag, ""), 10); + var input = new CodedInputStream(memoryStream.ToArray()); + + // test the legacy overload of AddEntriesFrom that takes a CodedInputStream + field.AddEntriesFrom(input, mapCodec); + CollectionAssert.AreEquivalent(new[] { "the_key" }, field.Keys); + CollectionAssert.AreEquivalent(new[] { "the_value" }, field.Values); + Assert.IsTrue(input.IsAtEnd); + } + + [Test] + public void AddEntriesFrom_CodedInputStream_MissingKey() + { + // map will have string key and string value + var keyTag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited); + var valueTag = WireFormat.MakeTag(2, WireFormat.WireType.LengthDelimited); + + var memoryStream = new MemoryStream(); + var output = new CodedOutputStream(memoryStream); + output.WriteLength(11); // total of valueTag + value + output.WriteTag(valueTag); + output.WriteString("the_value"); + output.Flush(); + + Console.WriteLine(BitConverter.ToString(memoryStream.ToArray())); + + var field = new MapField(); + var mapCodec = new MapField.Codec(FieldCodec.ForString(keyTag, ""), FieldCodec.ForString(valueTag, ""), 10); + var input = new CodedInputStream(memoryStream.ToArray()); + + field.AddEntriesFrom(input, mapCodec); + CollectionAssert.AreEquivalent(new[] { "" }, field.Keys); + CollectionAssert.AreEquivalent(new[] { "the_value" }, field.Values); + Assert.IsTrue(input.IsAtEnd); + } + #if !NET35 [Test] public void IDictionaryKeys_Equals_IReadOnlyDictionaryKeys() diff --git a/csharp/src/Google.Protobuf.Test/Collections/ProtobufEqualityComparersTest.cs b/csharp/src/Google.Protobuf.Test/Collections/ProtobufEqualityComparersTest.cs new file mode 100644 index 0000000000000..594a879865ac9 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/Collections/ProtobufEqualityComparersTest.cs @@ -0,0 +1,124 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2017 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using NUnit.Framework; +using System.Collections.Generic; +using System.Linq; +using static Google.Protobuf.Collections.ProtobufEqualityComparers; + +namespace Google.Protobuf.Collections +{ + public class ProtobufEqualityComparersTest + { + private static readonly double[] doubles = + { + 0, + 1, + 1.5, + -1.5, + double.PositiveInfinity, + double.NegativeInfinity, + // Three different types of NaN... + SampleNaNs.Regular, + SampleNaNs.SignallingFlipped, + SampleNaNs.PayloadFlipped + }; + + [Test] + public void GetEqualityComparer_Default() + { + // It's more pain than it's worth to try to parameterize these tests. + Assert.AreSame(EqualityComparer.Default, GetEqualityComparer()); + Assert.AreSame(EqualityComparer.Default, GetEqualityComparer()); + Assert.AreSame(EqualityComparer.Default, GetEqualityComparer()); + Assert.AreSame(EqualityComparer.Default, GetEqualityComparer()); + } + + [Test] + public void GetEqualityComparer_NotDefault() + { + // It's more pain than it's worth to try to parameterize these tests. + Assert.AreSame(BitwiseDoubleEqualityComparer, GetEqualityComparer()); + Assert.AreSame(BitwiseSingleEqualityComparer, GetEqualityComparer()); + Assert.AreSame(BitwiseNullableDoubleEqualityComparer, GetEqualityComparer()); + Assert.AreSame(BitwiseNullableSingleEqualityComparer, GetEqualityComparer()); + } + + [Test] + public void DoubleComparisons() + { + ValidateEqualityComparer(BitwiseDoubleEqualityComparer, doubles); + } + + [Test] + public void NullableDoubleComparisons() + { + ValidateEqualityComparer(BitwiseNullableDoubleEqualityComparer, doubles.Select(d => (double?) d).Concat(new double?[] { null })); + } + + [Test] + public void SingleComparisons() + { + ValidateEqualityComparer(BitwiseSingleEqualityComparer, doubles.Select(d => (float) d)); + } + + [Test] + public void NullableSingleComparisons() + { + ValidateEqualityComparer(BitwiseNullableSingleEqualityComparer, doubles.Select(d => (float?) d).Concat(new float?[] { null })); + } + + private static void ValidateEqualityComparer(EqualityComparer comparer, IEnumerable values) + { + var array = values.ToArray(); + // Each value should be equal to itself, but not to any other value. + for (int i = 0; i < array.Length; i++) + { + for (int j = 0; j < array.Length; j++) + { + if (i == j) + { + Assert.IsTrue(comparer.Equals(array[i], array[j]), + "{0} should be equal to itself", array[i], array[j]); + } + else + { + Assert.IsFalse(comparer.Equals(array[i], array[j]), + "{0} and {1} should not be equal", array[i], array[j]); + Assert.AreNotEqual(comparer.GetHashCode(array[i]), comparer.GetHashCode(array[j]), + "Hash codes for {0} and {1} should not be equal", array[i], array[j]); + } + } + } + } + } +} diff --git a/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs index 6852f75f8eb26..61453e5ab2e6d 100644 --- a/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs +++ b/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs @@ -33,6 +33,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text; @@ -594,6 +595,95 @@ public void TestNegativeEnumPackedArray() Assert.AreEqual(((SampleEnum)(-5)), values[5]); } + [Test] + public void TestPackedRepeatedFieldCollectionNonDivisibleLength() + { + uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited); + var codec = FieldCodec.ForFixed32(tag); + var stream = new MemoryStream(); + var output = new CodedOutputStream(stream); + output.WriteTag(tag); + output.WriteString("A long string"); + output.WriteTag(codec.Tag); + output.WriteRawVarint32((uint)codec.FixedSize - 1); // Length not divisible by FixedSize + output.WriteFixed32(uint.MaxValue); + output.Flush(); + stream.Position = 0; + + var input = new CodedInputStream(stream); + input.ReadTag(); + input.ReadString(); + input.ReadTag(); + var field = new RepeatedField(); + Assert.Throws(() => field.AddEntriesFrom(input, codec)); + + // Collection was not pre-initialized + Assert.AreEqual(0, field.Count); + } + + [Test] + public void TestPackedRepeatedFieldCollectionNotAllocatedWhenLengthExceedsBuffer() + { + uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited); + var codec = FieldCodec.ForFixed32(tag); + var stream = new MemoryStream(); + var output = new CodedOutputStream(stream); + output.WriteTag(tag); + output.WriteString("A long string"); + output.WriteTag(codec.Tag); + output.WriteRawVarint32((uint)codec.FixedSize); + // Note that there is no content for the packed field. + // The field length exceeds the remaining length of content. + output.Flush(); + stream.Position = 0; + + var input = new CodedInputStream(stream); + input.ReadTag(); + input.ReadString(); + input.ReadTag(); + var field = new RepeatedField(); + Assert.Throws(() => field.AddEntriesFrom(input, codec)); + + // Collection was not pre-initialized + Assert.AreEqual(0, field.Count); + } + + [Test] + public void TestPackedRepeatedFieldCollectionNotAllocatedWhenLengthExceedsRemainingData() + { + uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited); + var codec = FieldCodec.ForFixed32(tag); + var stream = new MemoryStream(); + var output = new CodedOutputStream(stream); + output.WriteTag(tag); + output.WriteString("A long string"); + output.WriteTag(codec.Tag); + output.WriteRawVarint32((uint)codec.FixedSize); + // Note that there is no content for the packed field. + // The field length exceeds the remaining length of the buffer. + output.Flush(); + stream.Position = 0; + + var sequence = ReadOnlySequenceFactory.CreateWithContent(stream.ToArray()); + ParseContext.Initialize(sequence, out ParseContext ctx); + + ctx.ReadTag(); + ctx.ReadString(); + ctx.ReadTag(); + var field = new RepeatedField(); + try + { + field.AddEntriesFrom(ref ctx, codec); + Assert.Fail(); + } + catch (InvalidProtocolBufferException) + { + } + + // Collection was not pre-initialized + Assert.AreEqual(0, field.Count); + } + // Fairly perfunctory tests for the non-generic IList implementation [Test] public void IList_Indexer() @@ -742,5 +832,66 @@ public void ToString_Struct() var text = list.ToString(); Assert.AreEqual(text, "[ { \"foo\": 20 } ]", message.ToString()); } + + [Test] + public void NaNValuesComparedBitwise() + { + var list1 = new RepeatedField { SampleNaNs.Regular, SampleNaNs.SignallingFlipped }; + var list2 = new RepeatedField { SampleNaNs.Regular, SampleNaNs.PayloadFlipped }; + var list3 = new RepeatedField { SampleNaNs.Regular, SampleNaNs.SignallingFlipped }; + + // All SampleNaNs have the same hashcode under certain targets (e.g. netcoreapp2.1) + EqualityTester.AssertInequality(list1, list2, checkHashcode: false); + EqualityTester.AssertEquality(list1, list3); + Assert.True(list1.Contains(SampleNaNs.SignallingFlipped)); + Assert.False(list2.Contains(SampleNaNs.SignallingFlipped)); + } + + [Test] + public void Capacity_Increase() + { + // Unfortunately this case tests implementation details of RepeatedField. This is necessary + + var list = new RepeatedField() { 1, 2, 3 }; + + Assert.AreEqual(8, list.Capacity); + Assert.AreEqual(3, list.Count); + + list.Capacity = 10; // Set capacity to a larger value to trigger growth + Assert.AreEqual(10, list.Capacity, "Capacity increased"); + Assert.AreEqual(3, list.Count); + + CollectionAssert.AreEqual(new int[] {1, 2, 3}, list.ToArray(), "We didn't lose our data in the resize"); + } + + [Test] + public void Capacity_Decrease() + { + var list = new RepeatedField() { 1, 2, 3 }; + + Assert.AreEqual(8, list.Capacity); + Assert.DoesNotThrow(() => list.Capacity = 5, "Can decrease capacity if new capacity is greater than list.Count"); + Assert.AreEqual(5, list.Capacity); + + Assert.DoesNotThrow(() => list.Capacity = 3, "Can set capacity exactly to list.Count" ); + + Assert.Throws(() => list.Capacity = 2, "Can't set the capacity smaller than list.Count" ); + + Assert.Throws(() => list.Capacity = 0, "Can't set the capacity to zero" ); + + Assert.Throws(() => list.Capacity = -1, "Can't set the capacity to negative" ); + } + + [Test] + public void Capacity_Zero() + { + var list = new RepeatedField() { 1 }; + list.RemoveAt(0); + Assert.AreEqual(0, list.Count); + Assert.AreEqual(8, list.Capacity); + + Assert.DoesNotThrow(() => list.Capacity = 0, "Can set Capacity to 0"); + Assert.AreEqual(0, list.Capacity); + } } } diff --git a/csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs b/csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs old mode 100755 new mode 100644 diff --git a/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs b/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs old mode 100755 new mode 100644 index abbe3c955f4e4..5d86c20896e13 --- a/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs +++ b/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs @@ -59,7 +59,7 @@ private void PrivateMethod() [TestCase(typeof(string), typeof(int), false)] [TestCase(typeof(int), typeof(int), true)] [TestCase(typeof(ValueType), typeof(int), true)] - [TestCase(typeof(long), typeof(int), false)] // + [TestCase(typeof(long), typeof(int), false)] // public void IsAssignableFrom(Type target, Type argument, bool expected) { Assert.AreEqual(expected, TypeExtensions.IsAssignableFrom(target, argument)); diff --git a/csharp/src/Google.Protobuf.Test/EqualityTester.cs b/csharp/src/Google.Protobuf.Test/EqualityTester.cs index a669baba17bfd..d4b3c1341ac68 100644 --- a/csharp/src/Google.Protobuf.Test/EqualityTester.cs +++ b/csharp/src/Google.Protobuf.Test/EqualityTester.cs @@ -49,13 +49,14 @@ public static void AssertEquality(T first, T second) where T : IEquatable Assert.AreEqual(first.GetHashCode(), second.GetHashCode()); } - public static void AssertInequality(T first, T second) where T : IEquatable + public static void AssertInequality(T first, T second, bool checkHashcode = true) where T : IEquatable { Assert.IsFalse(first.Equals(second)); Assert.IsFalse(first.Equals((object) second)); // While this isn't a requirement, the chances of this test failing due to // coincidence rather than a bug are very small. - if (first != null && second != null) + // For such rare cases, an argument can be used to disable the check. + if (checkHashcode && first != null && second != null) { Assert.AreNotEqual(first.GetHashCode(), second.GetHashCode()); } diff --git a/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs b/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs new file mode 100644 index 0000000000000..951e856a59617 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs @@ -0,0 +1,137 @@ +using Google.Protobuf.TestProtos.Proto2; +using NUnit.Framework; + +using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions; + +namespace Google.Protobuf +{ + public class ExtensionSetTest + { + [Test] + public void EmptyExtensionSet() + { + ExtensionSet extensions = new ExtensionSet(); + Assert.AreEqual(0, extensions.CalculateSize()); + } + + [Test] + public void MergeExtensionSet() + { + ExtensionSet extensions = null; + ExtensionSet.Set(ref extensions, OptionalBoolExtension, true); + + ExtensionSet other = null; + + Assert.IsFalse(ExtensionSet.Has(ref other, OptionalBoolExtension)); + ExtensionSet.MergeFrom(ref other, extensions); + Assert.IsTrue(ExtensionSet.Has(ref other, OptionalBoolExtension)); + } + + [Test] + public void TestMergeCodedInput() + { + var message = new TestAllExtensions(); + message.SetExtension(OptionalBoolExtension, true); + var serialized = message.ToByteArray(); + + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertReadingMessage( + TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { OptionalBoolExtension }), + serialized, + other => + { + Assert.AreEqual(message, other); + Assert.AreEqual(message.CalculateSize(), other.CalculateSize()); + }); + } + + [Test] + public void TestMergeMessage() + { + var message = new TestAllExtensions(); + message.SetExtension(OptionalBoolExtension, true); + + var other = new TestAllExtensions(); + + Assert.AreNotEqual(message, other); + Assert.AreNotEqual(message.CalculateSize(), other.CalculateSize()); + + other.MergeFrom(message); + + Assert.AreEqual(message, other); + Assert.AreEqual(message.CalculateSize(), other.CalculateSize()); + } + + [Test] + public void TryMergeFieldFrom_CodedInputStream() + { + var message = new TestAllExtensions(); + message.SetExtension(OptionalStringExtension, "abcd"); + + var input = new CodedInputStream(message.ToByteArray()); + input.ExtensionRegistry = new ExtensionRegistry() { OptionalStringExtension }; + input.ReadTag(); // TryMergeFieldFrom expects that a tag was just read and will inspect the LastTag value + + ExtensionSet extensionSet = null; + // test the legacy overload of TryMergeFieldFrom that takes a CodedInputStream + Assert.IsTrue(ExtensionSet.TryMergeFieldFrom(ref extensionSet, input)); + Assert.AreEqual("abcd", ExtensionSet.Get(ref extensionSet, OptionalStringExtension)); + } + + [Test] + public void TestEquals() + { + var message = new TestAllExtensions(); + message.SetExtension(OptionalBoolExtension, true); + + var other = new TestAllExtensions(); + + Assert.AreNotEqual(message, other); + Assert.AreNotEqual(message.CalculateSize(), other.CalculateSize()); + + other.SetExtension(OptionalBoolExtension, true); + + Assert.AreEqual(message, other); + Assert.AreEqual(message.CalculateSize(), other.CalculateSize()); + } + + [Test] + public void TestHashCode() + { + var message = new TestAllExtensions(); + var hashCode = message.GetHashCode(); + + message.SetExtension(OptionalBoolExtension, true); + + Assert.AreNotEqual(hashCode, message.GetHashCode()); + } + + [Test] + public void TestClone() + { + var message = new TestAllExtensions(); + message.SetExtension(OptionalBoolExtension, true); + + var other = message.Clone(); + + Assert.AreEqual(message, other); + Assert.AreEqual(message.CalculateSize(), other.CalculateSize()); + } + + [Test] + public void TestDefaultValueRoundTrip() + { + var message = new TestAllExtensions(); + message.SetExtension(OptionalBoolExtension, false); + Assert.IsFalse(message.GetExtension(OptionalBoolExtension)); + Assert.IsTrue(message.HasExtension(OptionalBoolExtension)); + + var bytes = message.ToByteArray(); + var registry = new ExtensionRegistry { OptionalBoolExtension }; + var parsed = TestAllExtensions.Parser.WithExtensionRegistry(registry).ParseFrom(bytes); + Assert.IsFalse(parsed.GetExtension(OptionalBoolExtension)); + Assert.IsTrue(parsed.HasExtension(OptionalBoolExtension)); + } + } +} diff --git a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs old mode 100755 new mode 100644 index 77641163c0c20..7f366926fa02c --- a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs +++ b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs @@ -43,7 +43,7 @@ public class FieldCodecTest #pragma warning disable 0414 // Used by tests via reflection - do not remove! private static readonly List Codecs = new List { - new FieldCodecTestData(FieldCodec.ForBool(100), true, "Bool"), + new FieldCodecTestData(FieldCodec.ForBool(100), true, "FixedBool"), new FieldCodecTestData(FieldCodec.ForString(100), "sample", "String"), new FieldCodecTestData(FieldCodec.ForBytes(100), ByteString.CopyFrom(1, 2, 3), "Bytes"), new FieldCodecTestData(FieldCodec.ForInt32(100), -1000, "Int32"), @@ -56,8 +56,8 @@ public class FieldCodecTest new FieldCodecTestData(FieldCodec.ForSFixed64(100), -1000, "SFixed64"), new FieldCodecTestData(FieldCodec.ForUInt64(100), 1234, "UInt64"), new FieldCodecTestData(FieldCodec.ForFixed64(100), 1234, "Fixed64"), - new FieldCodecTestData(FieldCodec.ForFloat(100), 1234.5f, "Float"), - new FieldCodecTestData(FieldCodec.ForDouble(100), 1234567890.5d, "Double"), + new FieldCodecTestData(FieldCodec.ForFloat(100), 1234.5f, "FixedFloat"), + new FieldCodecTestData(FieldCodec.ForDouble(100), 1234567890.5d, "FixedDouble"), new FieldCodecTestData( FieldCodec.ForEnum(100, t => (int) t, t => (ForeignEnum) t), ForeignEnum.ForeignBaz, "Enum"), new FieldCodecTestData( @@ -124,11 +124,21 @@ public void TestRoundTripRaw() { var stream = new MemoryStream(); var codedOutput = new CodedOutputStream(stream); - codec.ValueWriter(codedOutput, sampleValue); + WriteContext.Initialize(codedOutput, out WriteContext ctx); + try + { + // only write the value using the codec + codec.ValueWriter(ref ctx, sampleValue); + } + finally + { + ctx.CopyStateTo(codedOutput); + } + codedOutput.Flush(); stream.Position = 0; var codedInput = new CodedInputStream(stream); - Assert.AreEqual(sampleValue, codec.ValueReader(codedInput)); + Assert.AreEqual(sampleValue, codec.Read(codedInput)); Assert.IsTrue(codedInput.IsAtEnd); } @@ -158,7 +168,7 @@ public void TestDefaultValue() { // WriteTagAndValue ignores default values var stream = new MemoryStream(); - CodedOutputStream codedOutput; + CodedOutputStream codedOutput; #if !NET35 codedOutput = new CodedOutputStream(stream); codec.WriteTagAndValue(codedOutput, codec.DefaultValue); @@ -175,13 +185,23 @@ public void TestDefaultValue() if (codec.DefaultValue != null) // This part isn't appropriate for message types. { codedOutput = new CodedOutputStream(stream); - codec.ValueWriter(codedOutput, codec.DefaultValue); + WriteContext.Initialize(codedOutput, out WriteContext ctx); + try + { + // only write the value using the codec + codec.ValueWriter(ref ctx, codec.DefaultValue); + } + finally + { + ctx.CopyStateTo(codedOutput); + } + codedOutput.Flush(); Assert.AreNotEqual(0, stream.Position); Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue)); stream.Position = 0; var codedInput = new CodedInputStream(stream); - Assert.AreEqual(codec.DefaultValue, codec.ValueReader(codedInput)); + Assert.AreEqual(codec.DefaultValue, codec.Read(codedInput)); } } diff --git a/csharp/src/Google.Protobuf.Test/FieldMaskTreeTest.cs b/csharp/src/Google.Protobuf.Test/FieldMaskTreeTest.cs new file mode 100644 index 0000000000000..f71744a8745a4 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/FieldMaskTreeTest.cs @@ -0,0 +1,436 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System.Collections.Generic; +using Google.Protobuf.Collections; +using Google.Protobuf.TestProtos; +using NUnit.Framework; +using Google.Protobuf.WellKnownTypes; + +namespace Google.Protobuf +{ + public class FieldMaskTreeTest + { + [Test] + public void AddFieldPath() + { + FieldMaskTree tree = new FieldMaskTree(); + RepeatedField paths = tree.ToFieldMask().Paths; + Assert.AreEqual(0, paths.Count); + + tree.AddFieldPath(""); + paths = tree.ToFieldMask().Paths; + Assert.AreEqual(1, paths.Count); + Assert.Contains("", paths); + + // New branch. + tree.AddFieldPath("foo"); + paths = tree.ToFieldMask().Paths; + Assert.AreEqual(2, paths.Count); + Assert.Contains("foo", paths); + + // Redundant path. + tree.AddFieldPath("foo"); + paths = tree.ToFieldMask().Paths; + Assert.AreEqual(2, paths.Count); + + // New branch. + tree.AddFieldPath("bar.baz"); + paths = tree.ToFieldMask().Paths; + Assert.AreEqual(3, paths.Count); + Assert.Contains("bar.baz", paths); + + // Redundant sub-path. + tree.AddFieldPath("foo.bar"); + paths = tree.ToFieldMask().Paths; + Assert.AreEqual(3, paths.Count); + + // New branch from a non-root node. + tree.AddFieldPath("bar.quz"); + paths = tree.ToFieldMask().Paths; + Assert.AreEqual(4, paths.Count); + Assert.Contains("bar.quz", paths); + + // A path that matches several existing sub-paths. + tree.AddFieldPath("bar"); + paths = tree.ToFieldMask().Paths; + Assert.AreEqual(3, paths.Count); + Assert.Contains("foo", paths); + Assert.Contains("bar", paths); + } + + [Test] + public void MergeFromFieldMask() + { + FieldMaskTree tree = new FieldMaskTree(); + tree.MergeFromFieldMask(new FieldMask + { + Paths = {"foo", "bar.baz", "bar.quz"} + }); + RepeatedField paths = tree.ToFieldMask().Paths; + Assert.AreEqual(3, paths.Count); + Assert.Contains("foo", paths); + Assert.Contains("bar.baz", paths); + Assert.Contains("bar.quz", paths); + + tree.MergeFromFieldMask(new FieldMask + { + Paths = {"foo.bar", "bar"} + }); + paths = tree.ToFieldMask().Paths; + Assert.AreEqual(2, paths.Count); + Assert.Contains("foo", paths); + Assert.Contains("bar", paths); + } + + [Test] + public void IntersectFieldPath() + { + FieldMaskTree tree = new FieldMaskTree(); + FieldMaskTree result = new FieldMaskTree(); + tree.MergeFromFieldMask(new FieldMask + { + Paths = {"foo", "bar.baz", "bar.quz"} + }); + + // Empty path. + tree.IntersectFieldPath("", result); + RepeatedField paths = result.ToFieldMask().Paths; + Assert.AreEqual(0, paths.Count); + + // Non-exist path. + tree.IntersectFieldPath("quz", result); + paths = result.ToFieldMask().Paths; + Assert.AreEqual(0, paths.Count); + + // Sub-path of an existing leaf. + tree.IntersectFieldPath("foo.bar", result); + paths = result.ToFieldMask().Paths; + Assert.AreEqual(1, paths.Count); + Assert.Contains("foo.bar", paths); + + // Match an existing leaf node. + tree.IntersectFieldPath("foo", result); + paths = result.ToFieldMask().Paths; + Assert.AreEqual(1, paths.Count); + Assert.Contains("foo", paths); + + // Non-exist path. + tree.IntersectFieldPath("bar.foo", result); + paths = result.ToFieldMask().Paths; + Assert.AreEqual(1, paths.Count); + Assert.Contains("foo", paths); + + // Match a non-leaf node. + tree.IntersectFieldPath("bar", result); + paths = result.ToFieldMask().Paths; + Assert.AreEqual(3, paths.Count); + Assert.Contains("foo", paths); + Assert.Contains("bar.baz", paths); + Assert.Contains("bar.quz", paths); + } + + private void Merge(FieldMaskTree tree, IMessage source, IMessage destination, FieldMask.MergeOptions options, bool useDynamicMessage) + { + if (useDynamicMessage) + { + var newSource = source.Descriptor.Parser.CreateTemplate(); + newSource.MergeFrom(source.ToByteString()); + + var newDestination = source.Descriptor.Parser.CreateTemplate(); + newDestination.MergeFrom(destination.ToByteString()); + + tree.Merge(newSource, newDestination, options); + + // Clear before merging: + foreach (var fieldDescriptor in destination.Descriptor.Fields.InFieldNumberOrder()) + { + fieldDescriptor.Accessor.Clear(destination); + } + destination.MergeFrom(newDestination.ToByteString()); + } + else + { + tree.Merge(source, destination, options); + } + } + + [Test] + [TestCase(true)] + [TestCase(false)] + public void Merge(bool useDynamicMessage) + { + TestAllTypes value = new TestAllTypes + { + SingleInt32 = 1234, + SingleNestedMessage = new TestAllTypes.Types.NestedMessage {Bb = 5678}, + RepeatedInt32 = {4321}, + RepeatedNestedMessage = {new TestAllTypes.Types.NestedMessage {Bb = 8765}} + }; + + NestedTestAllTypes source = new NestedTestAllTypes + { + Payload = value, + Child = new NestedTestAllTypes {Payload = value} + }; + // Now we have a message source with the following structure: + // [root] -+- payload -+- single_int32 + // | +- single_nested_message + // | +- repeated_int32 + // | +- repeated_nested_message + // | + // +- child --- payload -+- single_int32 + // +- single_nested_message + // +- repeated_int32 + // +- repeated_nested_message + + FieldMask.MergeOptions options = new FieldMask.MergeOptions(); + + // Test merging each individual field. + NestedTestAllTypes destination = new NestedTestAllTypes(); + Merge(new FieldMaskTree().AddFieldPath("payload.single_int32"), + source, destination, options, useDynamicMessage); + NestedTestAllTypes expected = new NestedTestAllTypes + { + Payload = new TestAllTypes + { + SingleInt32 = 1234 + } + }; + Assert.AreEqual(expected, destination); + + destination = new NestedTestAllTypes(); + Merge(new FieldMaskTree().AddFieldPath("payload.single_nested_message"), + source, destination, options, useDynamicMessage); + expected = new NestedTestAllTypes + { + Payload = new TestAllTypes + { + SingleNestedMessage = new TestAllTypes.Types.NestedMessage {Bb = 5678} + } + }; + Assert.AreEqual(expected, destination); + + destination = new NestedTestAllTypes(); + Merge(new FieldMaskTree().AddFieldPath("payload.repeated_int32"), + source, destination, options, useDynamicMessage); + expected = new NestedTestAllTypes + { + Payload = new TestAllTypes + { + RepeatedInt32 = {4321} + } + }; + Assert.AreEqual(expected, destination); + + destination = new NestedTestAllTypes(); + Merge(new FieldMaskTree().AddFieldPath("payload.repeated_nested_message"), + source, destination, options, useDynamicMessage); + expected = new NestedTestAllTypes + { + Payload = new TestAllTypes + { + RepeatedNestedMessage = {new TestAllTypes.Types.NestedMessage {Bb = 8765}} + } + }; + Assert.AreEqual(expected, destination); + + destination = new NestedTestAllTypes(); + Merge( + new FieldMaskTree().AddFieldPath("child.payload.single_int32"), + source, + destination, + options, + useDynamicMessage); + expected = new NestedTestAllTypes + { + Child = new NestedTestAllTypes + { + Payload = new TestAllTypes + { + SingleInt32 = 1234 + } + } + }; + Assert.AreEqual(expected, destination); + + destination = new NestedTestAllTypes(); + Merge( + new FieldMaskTree().AddFieldPath("child.payload.single_nested_message"), + source, + destination, + options, + useDynamicMessage); + expected = new NestedTestAllTypes + { + Child = new NestedTestAllTypes + { + Payload = new TestAllTypes + { + SingleNestedMessage = new TestAllTypes.Types.NestedMessage {Bb = 5678} + } + } + }; + Assert.AreEqual(expected, destination); + + destination = new NestedTestAllTypes(); + Merge(new FieldMaskTree().AddFieldPath("child.payload.repeated_int32"), + source, destination, options, useDynamicMessage); + expected = new NestedTestAllTypes + { + Child = new NestedTestAllTypes + { + Payload = new TestAllTypes + { + RepeatedInt32 = {4321} + } + } + }; + Assert.AreEqual(expected, destination); + + destination = new NestedTestAllTypes(); + Merge(new FieldMaskTree().AddFieldPath("child.payload.repeated_nested_message"), + source, destination, options, useDynamicMessage); + expected = new NestedTestAllTypes + { + Child = new NestedTestAllTypes + { + Payload = new TestAllTypes + { + RepeatedNestedMessage = {new TestAllTypes.Types.NestedMessage {Bb = 8765}} + } + } + }; + Assert.AreEqual(expected, destination); + + destination = new NestedTestAllTypes(); + Merge(new FieldMaskTree().AddFieldPath("child").AddFieldPath("payload"), + source, destination, options, useDynamicMessage); + Assert.AreEqual(source, destination); + + // Test repeated options. + destination = new NestedTestAllTypes + { + Payload = new TestAllTypes + { + RepeatedInt32 = { 1000 } + } + }; + Merge(new FieldMaskTree().AddFieldPath("payload.repeated_int32"), + source, destination, options, useDynamicMessage); + // Default behavior is to append repeated fields. + Assert.AreEqual(2, destination.Payload.RepeatedInt32.Count); + Assert.AreEqual(1000, destination.Payload.RepeatedInt32[0]); + Assert.AreEqual(4321, destination.Payload.RepeatedInt32[1]); + // Change to replace repeated fields. + options.ReplaceRepeatedFields = true; + Merge(new FieldMaskTree().AddFieldPath("payload.repeated_int32"), + source, destination, options, useDynamicMessage); + Assert.AreEqual(1, destination.Payload.RepeatedInt32.Count); + Assert.AreEqual(4321, destination.Payload.RepeatedInt32[0]); + + // Test message options. + destination = new NestedTestAllTypes + { + Payload = new TestAllTypes + { + SingleInt32 = 1000, + SingleUint32 = 2000 + } + }; + Merge(new FieldMaskTree().AddFieldPath("payload"), + source, destination, options, useDynamicMessage); + // Default behavior is to merge message fields. + Assert.AreEqual(1234, destination.Payload.SingleInt32); + Assert.AreEqual(2000, destination.Payload.SingleUint32); + + // Test merging unset message fields. + NestedTestAllTypes clearedSource = source.Clone(); + clearedSource.Payload = null; + destination = new NestedTestAllTypes(); + Merge(new FieldMaskTree().AddFieldPath("payload"), + clearedSource, destination, options, useDynamicMessage); + Assert.IsNull(destination.Payload); + + // Skip a message field if they are unset in both source and target. + destination = new NestedTestAllTypes(); + Merge(new FieldMaskTree().AddFieldPath("payload.single_int32"), + clearedSource, destination, options, useDynamicMessage); + Assert.IsNull(destination.Payload); + + // Change to replace message fields. + options.ReplaceMessageFields = true; + destination = new NestedTestAllTypes + { + Payload = new TestAllTypes + { + SingleInt32 = 1000, + SingleUint32 = 2000 + } + }; + Merge(new FieldMaskTree().AddFieldPath("payload"), + source, destination, options, useDynamicMessage); + Assert.AreEqual(1234, destination.Payload.SingleInt32); + Assert.AreEqual(0, destination.Payload.SingleUint32); + + // Test merging unset message fields. + destination = new NestedTestAllTypes + { + Payload = new TestAllTypes + { + SingleInt32 = 1000, + SingleUint32 = 2000 + } + }; + Merge(new FieldMaskTree().AddFieldPath("payload"), + clearedSource, destination, options, useDynamicMessage); + Assert.IsNull(destination.Payload); + + // Test merging unset primitive fields. + destination = source.Clone(); + destination.Payload.SingleInt32 = 0; + NestedTestAllTypes sourceWithPayloadInt32Unset = destination; + destination = source.Clone(); + Merge(new FieldMaskTree().AddFieldPath("payload.single_int32"), + sourceWithPayloadInt32Unset, destination, options, useDynamicMessage); + Assert.AreEqual(0, destination.Payload.SingleInt32); + + // Change to clear unset primitive fields. + options.ReplacePrimitiveFields = true; + destination = source.Clone(); + Merge(new FieldMaskTree().AddFieldPath("payload.single_int32"), + sourceWithPayloadInt32Unset, destination, options, useDynamicMessage); + Assert.IsNotNull(destination.Payload); + } + + } +} diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs new file mode 100644 index 0000000000000..1abed60563c86 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs @@ -0,0 +1,384 @@ +using Google.Protobuf.TestProtos.Proto2; +using Proto2 = Google.Protobuf.TestProtos.Proto2; +using NUnit.Framework; + +using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions; + +namespace Google.Protobuf +{ + /// + /// Tests around the generated TestAllTypes message in unittest.proto + /// + public partial class GeneratedMessageTest + { + [Test] + public void DefaultProto2Values() + { + var message = new TestAllTypes(); + Assert.AreEqual(false, message.OptionalBool); + Assert.AreEqual(ByteString.Empty, message.OptionalBytes); + Assert.AreEqual(0.0, message.OptionalDouble); + Assert.AreEqual(0, message.OptionalFixed32); + Assert.AreEqual(0L, message.OptionalFixed64); + Assert.AreEqual(0.0f, message.OptionalFloat); + Assert.AreEqual(ForeignEnum.ForeignFoo, message.OptionalForeignEnum); + Assert.IsNull(message.OptionalForeignMessage); + Assert.AreEqual(ImportEnum.ImportFoo, message.OptionalImportEnum); + Assert.IsNull(message.OptionalImportMessage); + Assert.AreEqual(0, message.OptionalInt32); + Assert.AreEqual(0L, message.OptionalInt64); + Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Foo, message.OptionalNestedEnum); + Assert.IsNull(message.OptionalNestedMessage); + Assert.IsNull(message.OptionalPublicImportMessage); + Assert.AreEqual(0, message.OptionalSfixed32); + Assert.AreEqual(0L, message.OptionalSfixed64); + Assert.AreEqual(0, message.OptionalSint32); + Assert.AreEqual(0L, message.OptionalSint64); + Assert.AreEqual("", message.OptionalString); + Assert.AreEqual(0U, message.OptionalUint32); + Assert.AreEqual(0UL, message.OptionalUint64); + + // Repeated fields + Assert.AreEqual(0, message.RepeatedBool.Count); + Assert.AreEqual(0, message.RepeatedBytes.Count); + Assert.AreEqual(0, message.RepeatedDouble.Count); + Assert.AreEqual(0, message.RepeatedFixed32.Count); + Assert.AreEqual(0, message.RepeatedFixed64.Count); + Assert.AreEqual(0, message.RepeatedFloat.Count); + Assert.AreEqual(0, message.RepeatedForeignEnum.Count); + Assert.AreEqual(0, message.RepeatedForeignMessage.Count); + Assert.AreEqual(0, message.RepeatedImportEnum.Count); + Assert.AreEqual(0, message.RepeatedImportMessage.Count); + Assert.AreEqual(0, message.RepeatedNestedEnum.Count); + Assert.AreEqual(0, message.RepeatedNestedMessage.Count); + Assert.AreEqual(0, message.RepeatedSfixed32.Count); + Assert.AreEqual(0, message.RepeatedSfixed64.Count); + Assert.AreEqual(0, message.RepeatedSint32.Count); + Assert.AreEqual(0, message.RepeatedSint64.Count); + Assert.AreEqual(0, message.RepeatedString.Count); + Assert.AreEqual(0, message.RepeatedUint32.Count); + Assert.AreEqual(0, message.RepeatedUint64.Count); + + // Oneof fields + Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase); + Assert.AreEqual(0, message.OneofUint32); + Assert.AreEqual("", message.OneofString); + Assert.AreEqual(ByteString.Empty, message.OneofBytes); + Assert.IsNull(message.OneofNestedMessage); + + Assert.AreEqual(true, message.DefaultBool); + Assert.AreEqual(ByteString.CopyFromUtf8("world"), message.DefaultBytes); + Assert.AreEqual("123", message.DefaultCord); + Assert.AreEqual(52e3, message.DefaultDouble); + Assert.AreEqual(47, message.DefaultFixed32); + Assert.AreEqual(48, message.DefaultFixed64); + Assert.AreEqual(51.5, message.DefaultFloat); + Assert.AreEqual(ForeignEnum.ForeignBar, message.DefaultForeignEnum); + Assert.AreEqual(ImportEnum.ImportBar, message.DefaultImportEnum); + Assert.AreEqual(41, message.DefaultInt32); + Assert.AreEqual(42, message.DefaultInt64); + Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Bar, message.DefaultNestedEnum); + Assert.AreEqual(49, message.DefaultSfixed32); + Assert.AreEqual(-50, message.DefaultSfixed64); + Assert.AreEqual(-45, message.DefaultSint32); + Assert.AreEqual(46, message.DefaultSint64); + Assert.AreEqual("hello", message.DefaultString); + Assert.AreEqual("abc", message.DefaultStringPiece); + Assert.AreEqual(43, message.DefaultUint32); + Assert.AreEqual(44, message.DefaultUint64); + + Assert.False(message.HasDefaultBool); + Assert.False(message.HasDefaultBytes); + Assert.False(message.HasDefaultCord); + Assert.False(message.HasDefaultDouble); + Assert.False(message.HasDefaultFixed32); + Assert.False(message.HasDefaultFixed64); + Assert.False(message.HasDefaultFloat); + Assert.False(message.HasDefaultForeignEnum); + Assert.False(message.HasDefaultImportEnum); + Assert.False(message.HasDefaultInt32); + Assert.False(message.HasDefaultInt64); + Assert.False(message.HasDefaultNestedEnum); + Assert.False(message.HasDefaultSfixed32); + Assert.False(message.HasDefaultSfixed64); + Assert.False(message.HasDefaultSint32); + Assert.False(message.HasDefaultSint64); + Assert.False(message.HasDefaultString); + Assert.False(message.HasDefaultStringPiece); + Assert.False(message.HasDefaultUint32); + Assert.False(message.HasDefaultUint64); + } + + [Test] + public void DefaultExtensionValues() + { + var message = new TestAllExtensions(); + Assert.AreEqual(false, message.GetExtension(OptionalBoolExtension)); + Assert.AreEqual(ByteString.Empty, message.GetExtension(OptionalBytesExtension)); + Assert.AreEqual(0.0, message.GetExtension(OptionalDoubleExtension)); + Assert.AreEqual(0, message.GetExtension(OptionalFixed32Extension)); + Assert.AreEqual(0L, message.GetExtension(OptionalFixed64Extension)); + Assert.AreEqual(0.0f, message.GetExtension(OptionalFloatExtension)); + Assert.AreEqual(ForeignEnum.ForeignFoo, message.GetExtension(OptionalForeignEnumExtension)); + Assert.IsNull(message.GetExtension(OptionalForeignMessageExtension)); + Assert.AreEqual(ImportEnum.ImportFoo, message.GetExtension(OptionalImportEnumExtension)); + Assert.IsNull(message.GetExtension(OptionalImportMessageExtension)); + Assert.AreEqual(0, message.GetExtension(OptionalInt32Extension)); + Assert.AreEqual(0L, message.GetExtension(OptionalInt64Extension)); + Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Foo, message.GetExtension(OptionalNestedEnumExtension)); + Assert.IsNull(message.GetExtension(OptionalNestedMessageExtension)); + Assert.IsNull(message.GetExtension(OptionalPublicImportMessageExtension)); + Assert.AreEqual(0, message.GetExtension(OptionalSfixed32Extension)); + Assert.AreEqual(0L, message.GetExtension(OptionalSfixed64Extension)); + Assert.AreEqual(0, message.GetExtension(OptionalSint32Extension)); + Assert.AreEqual(0L, message.GetExtension(OptionalSint64Extension)); + Assert.AreEqual("", message.GetExtension(OptionalStringExtension)); + Assert.AreEqual(0U, message.GetExtension(OptionalUint32Extension)); + Assert.AreEqual(0UL, message.GetExtension(OptionalUint64Extension)); + + // Repeated fields + Assert.IsNull(message.GetExtension(RepeatedBoolExtension)); + Assert.IsNull(message.GetExtension(RepeatedBytesExtension)); + Assert.IsNull(message.GetExtension(RepeatedDoubleExtension)); + Assert.IsNull(message.GetExtension(RepeatedFixed32Extension)); + Assert.IsNull(message.GetExtension(RepeatedFixed64Extension)); + Assert.IsNull(message.GetExtension(RepeatedFloatExtension)); + Assert.IsNull(message.GetExtension(RepeatedForeignEnumExtension)); + Assert.IsNull(message.GetExtension(RepeatedForeignMessageExtension)); + Assert.IsNull(message.GetExtension(RepeatedImportEnumExtension)); + Assert.IsNull(message.GetExtension(RepeatedImportMessageExtension)); + Assert.IsNull(message.GetExtension(RepeatedNestedEnumExtension)); + Assert.IsNull(message.GetExtension(RepeatedNestedMessageExtension)); + Assert.IsNull(message.GetExtension(RepeatedSfixed32Extension)); + Assert.IsNull(message.GetExtension(RepeatedSfixed64Extension)); + Assert.IsNull(message.GetExtension(RepeatedSint32Extension)); + Assert.IsNull(message.GetExtension(RepeatedSint64Extension)); + Assert.IsNull(message.GetExtension(RepeatedStringExtension)); + Assert.IsNull(message.GetExtension(RepeatedUint32Extension)); + Assert.IsNull(message.GetExtension(RepeatedUint64Extension)); + + // Oneof fields + Assert.AreEqual(0, message.GetExtension(OneofUint32Extension)); + Assert.AreEqual("", message.GetExtension(OneofStringExtension)); + Assert.AreEqual(ByteString.Empty, message.GetExtension(OneofBytesExtension)); + Assert.IsNull(message.GetExtension(OneofNestedMessageExtension)); + + Assert.AreEqual(true, message.GetExtension(DefaultBoolExtension)); + Assert.AreEqual(ByteString.CopyFromUtf8("world"), message.GetExtension(DefaultBytesExtension)); + Assert.AreEqual("123", message.GetExtension(DefaultCordExtension)); + Assert.AreEqual(52e3, message.GetExtension(DefaultDoubleExtension)); + Assert.AreEqual(47, message.GetExtension(DefaultFixed32Extension)); + Assert.AreEqual(48, message.GetExtension(DefaultFixed64Extension)); + Assert.AreEqual(51.5, message.GetExtension(DefaultFloatExtension)); + Assert.AreEqual(ForeignEnum.ForeignBar, message.GetExtension(DefaultForeignEnumExtension)); + Assert.AreEqual(ImportEnum.ImportBar, message.GetExtension(DefaultImportEnumExtension)); + Assert.AreEqual(41, message.GetExtension(DefaultInt32Extension)); + Assert.AreEqual(42, message.GetExtension(DefaultInt64Extension)); + Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Bar, message.GetExtension(DefaultNestedEnumExtension)); + Assert.AreEqual(49, message.GetExtension(DefaultSfixed32Extension)); + Assert.AreEqual(-50, message.GetExtension(DefaultSfixed64Extension)); + Assert.AreEqual(-45, message.GetExtension(DefaultSint32Extension)); + Assert.AreEqual(46, message.GetExtension(DefaultSint64Extension)); + Assert.AreEqual("hello", message.GetExtension(DefaultStringExtension)); + Assert.AreEqual("abc", message.GetExtension(DefaultStringPieceExtension)); + Assert.AreEqual(43, message.GetExtension(DefaultUint32Extension)); + Assert.AreEqual(44, message.GetExtension(DefaultUint64Extension)); + + Assert.False(message.HasExtension(DefaultBoolExtension)); + Assert.False(message.HasExtension(DefaultBytesExtension)); + Assert.False(message.HasExtension(DefaultCordExtension)); + Assert.False(message.HasExtension(DefaultDoubleExtension)); + Assert.False(message.HasExtension(DefaultFixed32Extension)); + Assert.False(message.HasExtension(DefaultFixed64Extension)); + Assert.False(message.HasExtension(DefaultFloatExtension)); + Assert.False(message.HasExtension(DefaultForeignEnumExtension)); + Assert.False(message.HasExtension(DefaultImportEnumExtension)); + Assert.False(message.HasExtension(DefaultInt32Extension)); + Assert.False(message.HasExtension(DefaultInt64Extension)); + Assert.False(message.HasExtension(DefaultNestedEnumExtension)); + Assert.False(message.HasExtension(DefaultSfixed32Extension)); + Assert.False(message.HasExtension(DefaultSfixed64Extension)); + Assert.False(message.HasExtension(DefaultSint32Extension)); + Assert.False(message.HasExtension(DefaultSint64Extension)); + Assert.False(message.HasExtension(DefaultStringExtension)); + Assert.False(message.HasExtension(DefaultStringPieceExtension)); + Assert.False(message.HasExtension(DefaultUint32Extension)); + Assert.False(message.HasExtension(DefaultUint64Extension)); + } + + [Test] + public void FieldPresence() + { + var message = new TestAllTypes(); + + Assert.False(message.HasOptionalBool); + Assert.False(message.OptionalBool); + + message.OptionalBool = true; + + Assert.True(message.HasOptionalBool); + Assert.True(message.OptionalBool); + + message.OptionalBool = false; + + Assert.True(message.HasOptionalBool); + Assert.False(message.OptionalBool); + + message.ClearOptionalBool(); + + Assert.False(message.HasOptionalBool); + Assert.False(message.OptionalBool); + + Assert.False(message.HasDefaultBool); + Assert.True(message.DefaultBool); + + message.DefaultBool = false; + + Assert.True(message.HasDefaultBool); + Assert.False(message.DefaultBool); + + message.DefaultBool = true; + + Assert.True(message.HasDefaultBool); + Assert.True(message.DefaultBool); + + message.ClearDefaultBool(); + + Assert.False(message.HasDefaultBool); + Assert.True(message.DefaultBool); + } + + [Test] + public void RequiredFields() + { + var message = new TestRequired(); + Assert.False(message.IsInitialized()); + + message.A = 1; + message.B = 2; + message.C = 3; + + Assert.True(message.IsInitialized()); + } + + /// + /// Code was accidentally left in message parser that threw exceptions when missing required fields after parsing. + /// We've decided to not throw exceptions on missing fields, instead leaving it up to the consumer how they + /// want to check and handle missing fields. + /// + [Test] + public void RequiredFieldsNoThrow() + { + Assert.DoesNotThrow(() => MessageParsingHelpers.AssertReadingMessage(TestRequired.Parser, new byte[0], m => { })); + Assert.DoesNotThrow(() => MessageParsingHelpers.AssertReadingMessage(TestRequired.Parser as MessageParser, new byte[0], m => { })); + } + + [Test] + public void RequiredFieldsInExtensions() + { + var message = new TestAllExtensions(); + Assert.True(message.IsInitialized()); + + message.SetExtension(TestRequired.Extensions.Single, new TestRequired()); + + Assert.False(message.IsInitialized()); + + var extensionMessage = message.GetExtension(TestRequired.Extensions.Single); + extensionMessage.A = 1; + extensionMessage.B = 2; + extensionMessage.C = 3; + + Assert.True(message.IsInitialized()); + + message.GetOrInitializeExtension(TestRequired.Extensions.Multi); + + Assert.True(message.IsInitialized()); + + message.GetExtension(TestRequired.Extensions.Multi).Add(new TestRequired()); + + Assert.False(message.IsInitialized()); + + extensionMessage = message.GetExtension(TestRequired.Extensions.Multi)[0]; + extensionMessage.A = 1; + extensionMessage.B = 2; + extensionMessage.C = 3; + + Assert.True(message.IsInitialized()); + + message.SetExtension(UnittestExtensions.OptionalBoolExtension, true); + + Assert.True(message.IsInitialized()); + + message.GetOrInitializeExtension(UnittestExtensions.RepeatedBoolExtension).Add(true); + + Assert.True(message.IsInitialized()); + } + + [Test] + public void RequiredFieldInNestedMessageMapValue() + { + var message = new TestRequiredMap(); + message.Foo.Add(0, new TestRequiredMap.Types.NestedMessage()); + + Assert.False(message.IsInitialized()); + + message.Foo[0].RequiredInt32 = 12; + + Assert.True(message.IsInitialized()); + } + + [Test] + public void RoundTrip_Groups() + { + var message = new TestAllTypes + { + OptionalGroup = new TestAllTypes.Types.OptionalGroup + { + A = 10 + }, + RepeatedGroup = + { + new TestAllTypes.Types.RepeatedGroup { A = 10 }, + new TestAllTypes.Types.RepeatedGroup { A = 20 }, + new TestAllTypes.Types.RepeatedGroup { A = 30 } + } + }; + + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertRoundtrip(Proto2.TestAllTypes.Parser, message); + } + + [Test] + public void RoundTrip_ExtensionGroups() + { + var message = new TestAllExtensions(); + message.SetExtension(UnittestExtensions.OptionalGroupExtension, new OptionalGroup_extension { A = 10 }); + message.GetOrInitializeExtension(UnittestExtensions.RepeatedGroupExtension).AddRange(new[] + { + new RepeatedGroup_extension { A = 10 }, + new RepeatedGroup_extension { A = 20 }, + new RepeatedGroup_extension { A = 30 } + }); + + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertRoundtrip( + TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { UnittestExtensions.OptionalGroupExtension, UnittestExtensions.RepeatedGroupExtension }), + message); + } + + [Test] + public void RoundTrip_NestedExtensionGroup() + { + var message = new TestGroupExtension(); + message.SetExtension(TestNestedExtension.Extensions.OptionalGroupExtension, new TestNestedExtension.Types.OptionalGroup_extension { A = 10 }); + + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertRoundtrip( + TestGroupExtension.Parser.WithExtensionRegistry(new ExtensionRegistry() { TestNestedExtension.Extensions.OptionalGroupExtension }), + message); + } + } +} diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs index 8b153d691f273..06af5e9e9a043 100644 --- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs +++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs @@ -33,6 +33,7 @@ using System; using System.IO; using Google.Protobuf.TestProtos; +using Proto2 = Google.Protobuf.TestProtos.Proto2; using NUnit.Framework; using System.Collections; using System.Collections.Generic; @@ -44,7 +45,7 @@ namespace Google.Protobuf /// /// Tests around the generated TestAllTypes message. /// - public class GeneratedMessageTest + public partial class GeneratedMessageTest { [Test] public void EmptyMessageFieldDistinctFromMissingMessageField() @@ -130,8 +131,10 @@ public void RoundTrip_Empty() // Without setting any values, there's nothing to write. byte[] bytes = message.ToByteArray(); Assert.AreEqual(0, bytes.Length); - TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, parsed); + + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message); } [Test] @@ -163,9 +166,9 @@ public void RoundTrip_SingleValues() SingleUint64 = ulong.MaxValue }; - byte[] bytes = message.ToByteArray(); - TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, parsed); + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message); } [Test] @@ -197,9 +200,9 @@ public void RoundTrip_RepeatedValues() RepeatedUint64 = { ulong.MaxValue, uint.MinValue } }; - byte[] bytes = message.ToByteArray(); - TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, parsed); + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message); } // Note that not every map within map_unittest_proto3 is used. They all go through very @@ -229,9 +232,9 @@ public void RoundTrip_Maps() } }; - byte[] bytes = message.ToByteArray(); - TestMap parsed = TestMap.Parser.ParseFrom(bytes); - Assert.AreEqual(message, parsed); + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertRoundtrip(TestMap.Parser, message); } [Test] @@ -245,9 +248,16 @@ public void MapWithEmptyEntry() byte[] bytes = message.ToByteArray(); Assert.AreEqual(2, bytes.Length); // Tag for field entry (1 byte), length of entry (0; 1 byte) - var parsed = TestMap.Parser.ParseFrom(bytes); - Assert.AreEqual(1, parsed.MapInt32Bytes.Count); - Assert.AreEqual(ByteString.Empty, parsed.MapInt32Bytes[0]); + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + bytes, + parsed=> + { + Assert.AreEqual(1, parsed.MapInt32Bytes.Count); + Assert.AreEqual(ByteString.Empty, parsed.MapInt32Bytes[0]); + }); } [Test] @@ -264,8 +274,13 @@ public void MapWithOnlyValue() output.WriteMessage(nestedMessage); output.Flush(); - var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); - Assert.AreEqual(nestedMessage, parsed.MapInt32ForeignMessage[0]); + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + memoryStream.ToArray(), + parsed => + { + Assert.AreEqual(nestedMessage, parsed.MapInt32ForeignMessage[0]); + }); } [Test] @@ -281,8 +296,13 @@ public void MapWithOnlyKey_PrimitiveValue() output.WriteInt32(key); output.Flush(); - var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); - Assert.AreEqual(0.0, parsed.MapInt32Double[key]); + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + memoryStream.ToArray(), + parsed => + { + Assert.AreEqual(0.0, parsed.MapInt32Double[key]); + }); } [Test] @@ -298,8 +318,13 @@ public void MapWithOnlyKey_MessageValue() output.WriteInt32(key); output.Flush(); - var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); - Assert.AreEqual(new ForeignMessage(), parsed.MapInt32ForeignMessage[key]); + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + memoryStream.ToArray(), + parsed => + { + Assert.AreEqual(new ForeignMessage(), parsed.MapInt32ForeignMessage[key]); + }); } [Test] @@ -326,8 +351,13 @@ public void MapIgnoresExtraFieldsWithinEntryMessages() output.WriteInt32(extra); output.Flush(); - var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); - Assert.AreEqual(value, parsed.MapInt32Int32[key]); + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + memoryStream.ToArray(), + parsed => + { + Assert.AreEqual(value, parsed.MapInt32Int32[key]); + }); } [Test] @@ -350,8 +380,13 @@ public void MapFieldOrderIsIrrelevant() output.WriteInt32(key); output.Flush(); - var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); - Assert.AreEqual(value, parsed.MapInt32Int32[key]); + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + memoryStream.ToArray(), + parsed => + { + Assert.AreEqual(value, parsed.MapInt32Int32[key]); + }); } [Test] @@ -396,13 +431,19 @@ public void MapNonContiguousEntries() output.WriteInt32(value3); output.Flush(); - var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); - var expected = new TestMap - { - MapInt32Int32 = { { key1, value1 }, { key3, value3 } }, - MapStringString = { { key2, value2 } } - }; - Assert.AreEqual(expected, parsed); + + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + memoryStream.ToArray(), + parsed => + { + var expected = new TestMap + { + MapInt32Int32 = { { key1, value1 }, { key3, value3 } }, + MapStringString = { { key2, value2 } } + }; + Assert.AreEqual(expected, parsed); + }); } [Test] @@ -432,8 +473,13 @@ public void DuplicateKeys_LastEntryWins() output.WriteInt32(value2); output.Flush(); - var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); - Assert.AreEqual(value2, parsed.MapInt32Int32[key]); + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + memoryStream.ToArray(), + parsed => + { + Assert.AreEqual(value2, parsed.MapInt32Int32[key]); + }); } [Test] @@ -618,9 +664,12 @@ public void OneofSerialization_NonDefaultValue() var bytes = message.ToByteArray(); Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - no string! - var message2 = TestAllTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, message2); - Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase); + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message, parsedMessage => + { + Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, parsedMessage.OneofFieldCase); + }); } [Test] @@ -632,13 +681,16 @@ public void OneofSerialization_DefaultValue() var bytes = message.ToByteArray(); Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - it's still serialized - var message2 = TestAllTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, message2); - Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase); + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message, parsedMessage => + { + Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, parsedMessage.OneofFieldCase); + }); } [Test] - public void IgnoreUnknownFields_RealDataStillRead() + public void DiscardUnknownFields_RealDataStillRead() { var message = SampleMessages.CreateFullTestAllTypes(); var stream = new MemoryStream(); @@ -650,18 +702,31 @@ public void IgnoreUnknownFields_RealDataStillRead() message.WriteTo(output); output.Flush(); - stream.Position = 0; - var parsed = TestAllTypes.Parser.ParseFrom(stream); - Assert.AreEqual(message, parsed); + MessageParsingHelpers.AssertReadingMessage( + TestAllTypes.Parser, + stream.ToArray(), + parsed => + { + // TODO(jieluo): Add test back when DiscardUnknownFields API is supported. + // Assert.AreEqual(message, parsed); + }); } [Test] - public void IgnoreUnknownFields_AllTypes() + public void DiscardUnknownFields_AllTypes() { // Simple way of ensuring we can skip all kinds of fields. var data = SampleMessages.CreateFullTestAllTypes().ToByteArray(); var empty = Empty.Parser.ParseFrom(data); - Assert.AreEqual(new Empty(), empty); + + MessageParsingHelpers.AssertReadingMessage( + Empty.Parser, + data, + parsed => + { + // TODO(jieluo): Add test back when DiscardUnknownFields API is supported. + // Assert.AreNotEqual(new Empty(), empty); + }); } // This was originally seen as a conformance test failure. @@ -671,7 +736,7 @@ public void TruncatedMessageFieldThrows() // 130, 3 is the message tag // 1 is the data length - but there's no data. var data = new byte[] { 130, 3, 1 }; - Assert.Throws(() => TestAllTypes.Parser.ParseFrom(data)); + MessageParsingHelpers.AssertReadingMessageThrows(TestAllTypes.Parser, data); } /// @@ -692,7 +757,7 @@ public void ExtraEndGroupThrows() output.Flush(); stream.Position = 0; - Assert.Throws(() => TestAllTypes.Parser.ParseFrom(stream)); + MessageParsingHelpers.AssertReadingMessageThrows(TestAllTypes.Parser, stream.ToArray()); } [Test] @@ -719,5 +784,16 @@ public void CustomDiagnosticMessage_DirectToTextWriterCall() JsonFormatter.Default.Format(message, writer); Assert.AreEqual("{ \"c\": 31 }", writer.ToString()); } + + [Test] + public void NaNComparisons() + { + var message1 = new TestAllTypes { SingleDouble = SampleNaNs.Regular }; + var message2 = new TestAllTypes { SingleDouble = SampleNaNs.PayloadFlipped }; + var message3 = new TestAllTypes { SingleDouble = SampleNaNs.Regular }; + + EqualityTester.AssertInequality(message1, message2); + EqualityTester.AssertEquality(message1, message3); + } } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj index 06d07b9f4a54d..7bd3f84e459e6 100644 --- a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj +++ b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj @@ -1,30 +1,31 @@  - Exe - net451;netcoreapp1.0 + net451;netcoreapp2.1 ../../keys/Google.Protobuf.snk true - true False + True + - - + + + + + + + + + + + + - - - netcoreapp1.0 - - diff --git a/csharp/src/Google.Protobuf.Test/IssuesTest.cs b/csharp/src/Google.Protobuf.Test/IssuesTest.cs index a38d6b08b568f..2904c461df301 100644 --- a/csharp/src/Google.Protobuf.Test/IssuesTest.cs +++ b/csharp/src/Google.Protobuf.Test/IssuesTest.cs @@ -33,7 +33,8 @@ using Google.Protobuf.Reflection; using UnitTest.Issues.TestProtos; using NUnit.Framework; - +using System.IO; +using static UnitTest.Issues.TestProtos.OneofMerging.Types; namespace Google.Protobuf { @@ -78,5 +79,38 @@ public void JsonNameFormatTest() Assert.AreEqual("{ \"name\": \"test\", \"desc\": \"test2\", \"exid\": \"test3\" }", JsonFormatter.Default.Format(message)); } + + [Test] + public void OneofMerging() + { + var message1 = new OneofMerging { Nested = new Nested { X = 10 } }; + var message2 = new OneofMerging { Nested = new Nested { Y = 20 } }; + var expected = new OneofMerging { Nested = new Nested { X = 10, Y = 20 } }; + + var merged = message1.Clone(); + merged.MergeFrom(message2); + Assert.AreEqual(expected, merged); + } + + // Check that a tag immediately followed by end of limit can still be read. + [Test] + public void CodedInputStream_LimitReachedRightAfterTag() + { + MemoryStream ms = new MemoryStream(); + var cos = new CodedOutputStream(ms); + cos.WriteTag(11, WireFormat.WireType.Varint); + Assert.AreEqual(1, cos.Position); + cos.WriteString("some extra padding"); // ensure is currentLimit distinct from the end of the buffer. + cos.Flush(); + + var cis = new CodedInputStream(ms.ToArray()); + cis.PushLimit(1); // make sure we reach the limit right after reading the tag. + + // we still must read the tag correctly, even though the tag is at the very end of our limited input + // (which is a corner case and will most likely result in an error when trying to read value of the field + // described by this tag, but it would be a logical error not to read the tag that's actually present). + // See https://github.com/protocolbuffers/protobuf/pull/7289 + cis.AssertNextTag(WireFormat.MakeTag(11, WireFormat.WireType.Varint)); + } } } diff --git a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs index 53ac3dc9beb47..1a650933efd43 100644 --- a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs @@ -40,6 +40,7 @@ using static Google.Protobuf.JsonParserTest; // For WrapInQuotes using System.IO; using Google.Protobuf.Collections; +using ProtobufUnittest; namespace Google.Protobuf { @@ -153,6 +154,48 @@ public void AllSingleFields() AssertJson(expectedText, actualText); } + [Test] + public void WithFormatDefaultValues_DoesNotAffectMessageFields() + { + var message = new TestAllTypes(); + var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); + var json = formatter.Format(message); + Assert.IsFalse(json.Contains("\"singleNestedMessage\"")); + Assert.IsFalse(json.Contains("\"singleForeignMessage\"")); + Assert.IsFalse(json.Contains("\"singleImportMessage\"")); + } + + [Test] + public void WithFormatDefaultValues_DoesNotAffectProto3OptionalFields() + { + var message = new TestProto3Optional(); + message.OptionalInt32 = 0; + var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); + var json = formatter.Format(message); + // The non-optional proto3 fields are formatted, as is the optional-but-specified field. + AssertJson("{ 'optionalInt32': 0, 'singularInt32': 0, 'singularInt64': '0' }", json); + } + + [Test] + public void WithFormatDefaultValues_DoesNotAffectProto2Fields() + { + var message = new TestProtos.Proto2.ForeignMessage(); + message.C = 0; + var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); + var json = formatter.Format(message); + // The specified field is formatted, but the non-specified field (d) is not. + AssertJson("{ 'c': 0 }", json); + } + + [Test] + public void WithFormatDefaultValues_DoesNotAffectOneofFields() + { + var message = new TestOneof(); + var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); + var json = formatter.Format(message); + AssertJson("{ }", json); + } + [Test] public void RepeatedField() { @@ -183,6 +226,28 @@ public void MapField_BoolBool() JsonFormatter.Default.Format(new TestMap { MapBoolBool = { { false, true }, { true, false } } })); } + [Test] + public void NullValueOutsideStruct() + { + var message = new NullValueOutsideStruct { NullValue = NullValue.NullValue }; + AssertJson("{ 'nullValue': null }", JsonFormatter.Default.Format(message)); + } + + [Test] + public void NullValueNotInOneof() + { + var message = new NullValueNotInOneof(); + AssertJson("{ }", JsonFormatter.Default.Format(message)); + } + + [Test] + public void NullValueNotInOneof_FormatDefaults() + { + var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); + var message = new NullValueNotInOneof(); + AssertJson("{ 'nullValue': null }", formatter.Format(message)); + } + [TestCase(1.0, "1")] [TestCase(double.NaN, "'NaN'")] [TestCase(double.PositiveInfinity, "'Infinity'")] @@ -243,7 +308,7 @@ public void SurrogatePairEscaping() [Test] public void InvalidSurrogatePairsFail() { - // Note: don't use TestCase for these, as the strings can't be reliably represented + // Note: don't use TestCase for these, as the strings can't be reliably represented // See http://codeblog.jonskeet.uk/2014/11/07/when-is-a-string-not-a-string/ // Lone low surrogate @@ -313,14 +378,16 @@ public void WrapperFormatting_Message() } [Test] - public void WrapperFormatting_IncludeNull() + public void WrapperFormatting_FormatDefaultValuesDoesNotFormatNull() { // The actual JSON here is very large because there are lots of fields. Just test a couple of them. var message = new TestWellKnownTypes { Int32Field = 10 }; var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); var actualJson = formatter.Format(message); - Assert.IsTrue(actualJson.Contains("\"int64Field\": null")); - Assert.IsFalse(actualJson.Contains("\"int32Field\": null")); + // This *used* to include "int64Field": null, but that was a bug. + // WithDefaultValues should not affect message fields, including wrapper types. + Assert.IsFalse(actualJson.Contains("\"int64Field\": null")); + Assert.IsTrue(actualJson.Contains("\"int32Field\": 10")); } [Test] @@ -514,7 +581,7 @@ public void AnyMessageType() var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithTypeRegistry(TypeRegistry.FromMessages(TestAllTypes.Descriptor))); var message = new TestAllTypes { SingleInt32 = 10, SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 } }; var any = Any.Pack(message); - AssertJson("{ '@type': 'type.googleapis.com/protobuf_unittest.TestAllTypes', 'singleInt32': 10, 'singleNestedMessage': { 'bb': 20 } }", formatter.Format(any)); + AssertJson("{ '@type': 'type.googleapis.com/protobuf_unittest3.TestAllTypes', 'singleInt32': 10, 'singleNestedMessage': { 'bb': 20 } }", formatter.Format(any)); } [Test] @@ -523,7 +590,7 @@ public void AnyMessageType_CustomPrefix() var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithTypeRegistry(TypeRegistry.FromMessages(TestAllTypes.Descriptor))); var message = new TestAllTypes { SingleInt32 = 10 }; var any = Any.Pack(message, "foo.bar/baz"); - AssertJson("{ '@type': 'foo.bar/baz/protobuf_unittest.TestAllTypes', 'singleInt32': 10 }", formatter.Format(any)); + AssertJson("{ '@type': 'foo.bar/baz/protobuf_unittest3.TestAllTypes', 'singleInt32': 10 }", formatter.Format(any)); } [Test] @@ -536,7 +603,7 @@ public void AnyNested() var doubleNestedMessage = new TestAllTypes { SingleInt32 = 20 }; var nestedMessage = Any.Pack(doubleNestedMessage); var message = new TestWellKnownTypes { AnyField = Any.Pack(nestedMessage) }; - AssertJson("{ 'anyField': { '@type': 'type.googleapis.com/google.protobuf.Any', 'value': { '@type': 'type.googleapis.com/protobuf_unittest.TestAllTypes', 'singleInt32': 20 } } }", + AssertJson("{ 'anyField': { '@type': 'type.googleapis.com/google.protobuf.Any', 'value': { '@type': 'type.googleapis.com/protobuf_unittest3.TestAllTypes', 'singleInt32': 20 } } }", formatter.Format(message)); } @@ -602,6 +669,13 @@ public void WriteValue_List() AssertWriteValue(value, "[ 1, 2, 3 ]"); } + [Test] + public void Proto2_DefaultValuesWritten() + { + var value = new ProtobufTestMessages.Proto2.TestAllTypesProto2() { FieldName13 = 0 }; + AssertWriteValue(value, "{ 'FieldName13': 0 }"); + } + private static void AssertWriteValue(object value, string expectedJson) { var writer = new StringWriter(); diff --git a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs index f595455aa161f..e170fcc5a09cd 100644 --- a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs @@ -34,7 +34,9 @@ using Google.Protobuf.TestProtos; using Google.Protobuf.WellKnownTypes; using NUnit.Framework; +using ProtobufTestMessages.Proto2; using System; +using UnitTest.Issues.TestProtos; namespace Google.Protobuf { @@ -695,6 +697,22 @@ public void StructValue_List() Assert.AreEqual(Value.ForList(Value.ForNumber(1), Value.ForString("x")), Value.Parser.ParseJson("[1, \"x\"]")); } + [Test] + public void Value_List_WithNullElement() + { + var expected = Value.ForList(Value.ForString("x"), Value.ForNull(), Value.ForString("y")); + var actual = Value.Parser.ParseJson("[\"x\", null, \"y\"]"); + Assert.AreEqual(expected, actual); + } + + [Test] + public void StructValue_NullElement() + { + var expected = Value.ForStruct(new Struct { Fields = { { "x", Value.ForNull() } } }); + var actual = Value.Parser.ParseJson("{ \"x\": null }"); + Assert.AreEqual(expected, actual); + } + [Test] public void ParseListValue() { @@ -809,7 +827,7 @@ public void Any_RegularMessage() var json = formatter.Format(original); // This is tested in JsonFormatterTest var parser = new JsonParser(new JsonParser.Settings(10, registry)); Assert.AreEqual(original, parser.Parse(json)); - string valueFirstJson = "{ \"singleInt32\": 10, \"singleNestedMessage\": { \"bb\": 20 }, \"@type\": \"type.googleapis.com/protobuf_unittest.TestAllTypes\" }"; + string valueFirstJson = "{ \"singleInt32\": 10, \"singleNestedMessage\": { \"bb\": 20 }, \"@type\": \"type.googleapis.com/protobuf_unittest3.TestAllTypes\" }"; Assert.AreEqual(original, parser.Parse(valueFirstJson)); } @@ -820,7 +838,7 @@ public void Any_CustomPrefix() var message = new TestAllTypes { SingleInt32 = 10 }; var original = Any.Pack(message, "custom.prefix/middle-part"); var parser = new JsonParser(new JsonParser.Settings(10, registry)); - string json = "{ \"@type\": \"custom.prefix/middle-part/protobuf_unittest.TestAllTypes\", \"singleInt32\": 10 }"; + string json = "{ \"@type\": \"custom.prefix/middle-part/protobuf_unittest3.TestAllTypes\", \"singleInt32\": 10 }"; Assert.AreEqual(original, parser.Parse(json)); } @@ -926,6 +944,74 @@ public void OneofDuplicate_Invalid() Assert.Throws(() => TestAllTypes.Parser.ParseJson(json)); } + [Test] + public void UnknownField_NotIgnored() + { + string json = "{ \"unknownField\": 10, \"singleString\": \"x\" }"; + Assert.Throws(() => TestAllTypes.Parser.ParseJson(json)); + } + + [Test] + public void Proto2_DefaultValuesPreserved() + { + string json = "{ \"FieldName13\": 0 }"; + var parsed = TestAllTypesProto2.Parser.ParseJson(json); + Assert.False(parsed.HasFieldName10); + Assert.True(parsed.HasFieldName13); + Assert.AreEqual(0, parsed.FieldName13); + } + + [Test] + [TestCase("5")] + [TestCase("\"text\"")] + [TestCase("[0, 1, 2]")] + [TestCase("{ \"a\": { \"b\": 10 } }")] + public void UnknownField_Ignored(string value) + { + var parser = new JsonParser(JsonParser.Settings.Default.WithIgnoreUnknownFields(true)); + string json = "{ \"unknownField\": " + value + ", \"singleString\": \"x\" }"; + var actual = parser.Parse(json); + var expected = new TestAllTypes { SingleString = "x" }; + Assert.AreEqual(expected, actual); + } + + [Test] + public void NullValueOutsideStruct_NullLiteral() + { + string json = "{ \"nullValue\": null }"; + var message = NullValueOutsideStruct.Parser.ParseJson(json); + Assert.AreEqual(NullValueOutsideStruct.ValueOneofCase.NullValue, message.ValueCase); + } + + [Test] + public void NullValueNotInOneof_NullLiteral() + { + // We'd only normally see this with FormatDefaultValues set to true. + string json = "{ \"nullValue\": null }"; + var message = NullValueNotInOneof.Parser.ParseJson(json); + Assert.AreEqual(NullValue.NullValue, message.NullValue); + } + + // NullValue used to only be converted to the null literal when part of a struct. + // Otherwise, it would end up as a string "NULL_VALUE" (the name of the enum value). + // We still parse that form, for compatibility. + [Test] + public void NullValueOutsideStruct_Compatibility() + { + string json = "{ \"nullValue\": \"NULL_VALUE\" }"; + var message = NullValueOutsideStruct.Parser.ParseJson(json); + Assert.AreEqual(NullValueOutsideStruct.ValueOneofCase.NullValue, message.ValueCase); + } + + [Test] + public void NullValueNotInOneof_Compatibility() + { + // We'd only normally see this with FormatDefaultValues set to true. + string json = "{ \"nullValue\": \"NULL_VALUE\" }"; + var message = NullValueNotInOneof.Parser.ParseJson(json); + Assert.AreEqual(NullValue.NullValue, message.NullValue); + } + /// /// Various tests use strings which have quotes round them for parsing or as the result /// of formatting, but without those quotes being specified in the tests (for the sake of readability). diff --git a/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs b/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs index 527ab3361e9f7..df43effd4ff0f 100644 --- a/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs @@ -240,7 +240,7 @@ public void SimpleObject() AssertTokens("{'x': 'y'}", JsonToken.StartObject, JsonToken.Name("x"), JsonToken.Value("y"), JsonToken.EndObject); } - + [Test] [TestCase("[10, 20", 3)] [TestCase("[10,", 2)] @@ -305,7 +305,7 @@ public void ArrayMixedType() [Test] public void ObjectMixedType() { - AssertTokens(@"{'a': 1, 'b': 'bar', 'c': null, 'd': false, 'e': true, + AssertTokens(@"{'a': 1, 'b': 'bar', 'c': null, 'd': false, 'e': true, 'f': [2], 'g': {'x':'y' }}", JsonToken.StartObject, JsonToken.Name("a"), @@ -349,12 +349,28 @@ public void CanPushBackEndDocument() Assert.AreEqual(JsonToken.EndDocument, tokenizer.Next()); Assert.Throws(() => tokenizer.Next()); } - + + [Test] + [TestCase("{ 'skip': 0, 'next': 1")] + [TestCase("{ 'skip': [0, 1, 2], 'next': 1")] + [TestCase("{ 'skip': 'x', 'next': 1")] + [TestCase("{ 'skip': ['x', 'y'], 'next': 1")] + [TestCase("{ 'skip': {'a': 0}, 'next': 1")] + [TestCase("{ 'skip': {'a': [0, {'b':[]}]}, 'next': 1")] + public void SkipValue(string json) + { + var tokenizer = JsonTokenizer.FromTextReader(new StringReader(json.Replace('\'', '"'))); + Assert.AreEqual(JsonToken.StartObject, tokenizer.Next()); + Assert.AreEqual("skip", tokenizer.Next().StringValue); + tokenizer.SkipValue(); + Assert.AreEqual("next", tokenizer.Next().StringValue); + } + /// /// Asserts that the specified JSON is tokenized into the given sequence of tokens. /// All apostrophes are first converted to double quotes, allowing any tests /// that don't need to check actual apostrophe handling to use apostrophes in the JSON, avoiding - /// messy string literal escaping. The "end document" token is not specified in the list of + /// messy string literal escaping. The "end document" token is not specified in the list of /// expected tokens, but is implicit. /// private static void AssertTokens(string json, params JsonToken[] expectedTokens) @@ -366,7 +382,7 @@ private static void AssertTokens(string json, params JsonToken[] expectedTokens) /// Asserts that the specified JSON is tokenized into the given sequence of tokens. /// Unlike , this does not perform any character /// replacement on the specified JSON, and should be used when the text contains apostrophes which - /// are expected to be used *as* apostrophes. The "end document" token is not specified in the list of + /// are expected to be used *as* apostrophes. The "end document" token is not specified in the list of /// expected tokens, but is implicit. /// private static void AssertTokensNoReplacement(string json, params JsonToken[] expectedTokens) diff --git a/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs b/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs new file mode 100644 index 0000000000000..da7b4a8c077a4 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs @@ -0,0 +1,296 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion +using Google.Protobuf; +using Google.Protobuf.Reflection; +using System.Buffers; +using pb = global::Google.Protobuf; +using pbr = global::Google.Protobuf.Reflection; +using NUnit.Framework; +using System.IO; +using System; +using Google.Protobuf.Buffers; + +namespace Google.Protobuf +{ + public class LegacyGeneratedCodeTest + { + [Test] + public void IntermixingOfNewAndLegacyGeneratedCodeWorksWithCodedInputStream() + { + var message = new ParseContextEnabledMessageB + { + A = new LegacyGeneratedCodeMessageA + { + Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 } + }, + OptionalInt32 = 6789 + }; + var data = message.ToByteArray(); + + // when parsing started using CodedInputStream and a message with legacy generated code + // is encountered somewhere in the parse tree, we still need to be able to use its + // MergeFrom(CodedInputStream) method to parse correctly. + var codedInput = new CodedInputStream(data); + var parsed = new ParseContextEnabledMessageB(); + codedInput.ReadRawMessage(parsed); + Assert.IsTrue(codedInput.IsAtEnd); + + Assert.AreEqual(12345, parsed.A.Bb.OptionalInt32); + Assert.AreEqual(6789, parsed.OptionalInt32); + } + + [Test] + public void LegacyGeneratedCodeThrowsWithReadOnlySequence() + { + var message = new ParseContextEnabledMessageB + { + A = new LegacyGeneratedCodeMessageA + { + Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 } + }, + OptionalInt32 = 6789 + }; + var data = message.ToByteArray(); + + // if parsing started using ReadOnlySequence and we don't have a CodedInputStream + // instance at hand, we cannot fall back to the legacy MergeFrom(CodedInputStream) + // method and parsing will fail. As a consequence, one can only use parsing + // from ReadOnlySequence if all the messages in the parsing tree have their generated + // code up to date. + var exception = Assert.Throws(() => + { + ParseContext.Initialize(new ReadOnlySequence(data), out ParseContext parseCtx); + var parsed = new ParseContextEnabledMessageB(); + ParsingPrimitivesMessages.ReadRawMessage(ref parseCtx, parsed); + }); + Assert.AreEqual($"Message {typeof(LegacyGeneratedCodeMessageA).Name} doesn't provide the generated method that enables ParseContext-based parsing. You might need to regenerate the generated protobuf code.", exception.Message); + } + + [Test] + public void IntermixingOfNewAndLegacyGeneratedCodeWorksWithCodedOutputStream() + { + // when serialization started using CodedOutputStream and a message with legacy generated code + // is encountered somewhere in the parse tree, we still need to be able to use its + // WriteTo(CodedOutputStream) method to serialize correctly. + var ms = new MemoryStream(); + var codedOutput = new CodedOutputStream(ms); + var message = new ParseContextEnabledMessageB + { + A = new LegacyGeneratedCodeMessageA + { + Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 } + }, + OptionalInt32 = 6789 + }; + message.WriteTo(codedOutput); + codedOutput.Flush(); + + var codedInput = new CodedInputStream(ms.ToArray()); + var parsed = new ParseContextEnabledMessageB(); + codedInput.ReadRawMessage(parsed); + Assert.IsTrue(codedInput.IsAtEnd); + + Assert.AreEqual(12345, parsed.A.Bb.OptionalInt32); + Assert.AreEqual(6789, parsed.OptionalInt32); + } + + [Test] + public void LegacyGeneratedCodeThrowsWithIBufferWriter() + { + // if serialization started using IBufferWriter and we don't have a CodedOutputStream + // instance at hand, we cannot fall back to the legacy WriteTo(CodedOutputStream) + // method and serializatin will fail. As a consequence, one can only use serialization + // to IBufferWriter if all the messages in the parsing tree have their generated + // code up to date. + var message = new ParseContextEnabledMessageB + { + A = new LegacyGeneratedCodeMessageA + { + Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 } + }, + OptionalInt32 = 6789 + }; + var exception = Assert.Throws(() => + { + WriteContext.Initialize(new ArrayBufferWriter(), out WriteContext writeCtx); + ((IBufferMessage)message).InternalWriteTo(ref writeCtx); + }); + Assert.AreEqual($"Message {typeof(LegacyGeneratedCodeMessageA).Name} doesn't provide the generated method that enables WriteContext-based serialization. You might need to regenerate the generated protobuf code.", exception.Message); + } + + // hand-modified version of a generated message that only provides the legacy + // MergeFrom(CodedInputStream) method and doesn't implement IBufferMessage. + private sealed partial class LegacyGeneratedCodeMessageA : pb::IMessage { + private pb::UnknownFieldSet _unknownFields; + + pbr::MessageDescriptor pb::IMessage.Descriptor => throw new System.NotImplementedException(); + + /// Field number for the "bb" field. + public const int BbFieldNumber = 1; + private ParseContextEnabledMessageB bb_; + public ParseContextEnabledMessageB Bb { + get { return bb_; } + set { + bb_ = value; + } + } + + public void WriteTo(pb::CodedOutputStream output) { + if (bb_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + public int CalculateSize() { + int size = 0; + if (bb_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Bb); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (bb_ == null) { + Bb = new ParseContextEnabledMessageB(); + } + input.ReadMessage(Bb); + break; + } + } + } + } + } + + // hand-modified version of a generated message that does provide + // the new InternalMergeFrom(ref ParseContext) method. + private sealed partial class ParseContextEnabledMessageB : pb::IBufferMessage { + private pb::UnknownFieldSet _unknownFields; + + pbr::MessageDescriptor pb::IMessage.Descriptor => throw new System.NotImplementedException(); + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private LegacyGeneratedCodeMessageA a_; + public LegacyGeneratedCodeMessageA A { + get { return a_; } + set { + a_ = value; + } + } + + /// Field number for the "optional_int32" field. + public const int OptionalInt32FieldNumber = 2; + private int optionalInt32_; + public int OptionalInt32 { + get { return optionalInt32_; } + set { + optionalInt32_ = value; + } + } + + public void WriteTo(pb::CodedOutputStream output) { + output.WriteRawMessage(this); + } + + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (a_ != null) + { + output.WriteRawTag(10); + output.WriteMessage(A); + } + if (OptionalInt32 != 0) + { + output.WriteRawTag(16); + output.WriteInt32(OptionalInt32); + } + if (_unknownFields != null) + { + _unknownFields.WriteTo(ref output); + } + } + + public int CalculateSize() { + int size = 0; + if (a_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(A); + } + if (OptionalInt32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (a_ == null) { + A = new LegacyGeneratedCodeMessageA(); + } + input.ReadMessage(A); + break; + } + case 16: { + OptionalInt32 = input.ReadInt32(); + break; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs b/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs new file mode 100644 index 0000000000000..36a2f02229461 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs @@ -0,0 +1,142 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using NUnit.Framework; +using System; +using System.Buffers; +using Google.Protobuf.Buffers; + +namespace Google.Protobuf +{ + public static class MessageParsingHelpers + { + public static void AssertReadingMessage(MessageParser parser, byte[] bytes, Action assert) where T : IMessage + { + var parsedStream = parser.ParseFrom(bytes); + + // Load content as single segment + var parsedBuffer = parser.ParseFrom(new ReadOnlySequence(bytes)); + assert(parsedBuffer); + + // Load content as multiple segments + parsedBuffer = parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(bytes)); + assert(parsedBuffer); + + assert(parsedStream); + } + + public static void AssertReadingMessage(MessageParser parser, byte[] bytes, Action assert) + { + var parsedStream = parser.ParseFrom(bytes); + + // Load content as single segment + var parsedBuffer = parser.ParseFrom(new ReadOnlySequence(bytes)); + assert(parsedBuffer); + + // Load content as multiple segments + parsedBuffer = parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(bytes)); + assert(parsedBuffer); + + assert(parsedStream); + } + + public static void AssertReadingMessageThrows(MessageParser parser, byte[] bytes) + where TMessage : IMessage + where TException : Exception + { + Assert.Throws(() => parser.ParseFrom(bytes)); + + Assert.Throws(() => parser.ParseFrom(new ReadOnlySequence(bytes))); + } + + public static void AssertRoundtrip(MessageParser parser, T message, Action additionalAssert = null) where T : IMessage + { + var bytes = message.ToByteArray(); + + // also serialize using IBufferWriter and check it leads to the same data + var bufferWriter = new ArrayBufferWriter(); + message.WriteTo(bufferWriter); + Assert.AreEqual(bytes, bufferWriter.WrittenSpan.ToArray(), "Both serialization approaches need to result in the same data."); + + // Load content as single segment + var parsedBuffer = parser.ParseFrom(new ReadOnlySequence(bytes)); + Assert.AreEqual(message, parsedBuffer); + additionalAssert?.Invoke(parsedBuffer); + + // Load content as multiple segments + parsedBuffer = parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(bytes)); + Assert.AreEqual(message, parsedBuffer); + additionalAssert?.Invoke(parsedBuffer); + + var parsedStream = parser.ParseFrom(bytes); + + Assert.AreEqual(message, parsedStream); + additionalAssert?.Invoke(parsedStream); + } + + public static void AssertWritingMessage(IMessage message) + { + // serialize using CodedOutputStream + var bytes = message.ToByteArray(); + + int messageSize = message.CalculateSize(); + Assert.AreEqual(message.CalculateSize(), bytes.Length); + + // serialize using IBufferWriter and check it leads to the same output + var bufferWriter = new ArrayBufferWriter(); + message.WriteTo(bufferWriter); + Assert.AreEqual(bytes, bufferWriter.WrittenSpan.ToArray()); + + // serialize into a single span and check it leads to the same output + var singleSpan = new Span(new byte[messageSize]); + message.WriteTo(singleSpan); + Assert.AreEqual(bytes, singleSpan.ToArray()); + + // test for different IBufferWriter.GetSpan() segment sizes + for (int blockSize = 1; blockSize < 256; blockSize *= 2) + { + var segmentedBufferWriter = new ArrayBufferWriter(); + segmentedBufferWriter.MaxGrowBy = blockSize; + message.WriteTo(segmentedBufferWriter); + Assert.AreEqual(bytes, segmentedBufferWriter.WrittenSpan.ToArray()); + } + + // if the full message is small enough, try serializing directly into stack-allocated buffer + if (bytes.Length <= 256) + { + Span stackAllocBuffer = stackalloc byte[bytes.Length]; + message.WriteTo(stackAllocBuffer); + Assert.AreEqual(bytes, stackAllocBuffer.ToArray()); + } + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/Program.cs b/csharp/src/Google.Protobuf.Test/Program.cs deleted file mode 100755 index 954c02b5a2642..0000000000000 --- a/csharp/src/Google.Protobuf.Test/Program.cs +++ /dev/null @@ -1,48 +0,0 @@ -#region Copyright notice and license -// Protocol Buffers - Google's data interchange format -// Copyright 2017 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#endregion -using NUnitLite; -using System.Reflection; - -namespace Google.Protobuf.Test -{ - class Program - { - public static int Main(string[] args) - { - #if NET35 - return new AutoRun(typeof(Program).Assembly).Execute(args); - #else - return new AutoRun(typeof(Program).GetTypeInfo().Assembly).Execute(args); - #endif - } - } -} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs b/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs new file mode 100644 index 0000000000000..46a8c57a78ab3 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs @@ -0,0 +1,153 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using NUnit.Framework; +using ProtobufUnittest; +using System; +using System.IO; +using UnitTest.Issues.TestProtos; + +namespace Google.Protobuf.Test +{ + class Proto3OptionalTest + { + [Test] + public void OptionalInt32FieldLifecycle() + { + var message = new TestProto3Optional(); + Assert.IsFalse(message.HasOptionalInt32); + Assert.AreEqual(0, message.OptionalInt32); + + message.OptionalInt32 = 5; + Assert.IsTrue(message.HasOptionalInt32); + Assert.AreEqual(5, message.OptionalInt32); + + message.OptionalInt32 = 0; + Assert.IsTrue(message.HasOptionalInt32); + Assert.AreEqual(0, message.OptionalInt32); + + message.ClearOptionalInt32(); + Assert.IsFalse(message.HasOptionalInt32); + Assert.AreEqual(0, message.OptionalInt32); + } + + [Test] + public void OptionalStringFieldLifecycle() + { + var message = new TestProto3Optional(); + Assert.IsFalse(message.HasOptionalString); + Assert.AreEqual("", message.OptionalString); + + message.OptionalString = "x"; + Assert.IsTrue(message.HasOptionalString); + Assert.AreEqual("x", message.OptionalString); + + message.OptionalString = ""; + Assert.IsTrue(message.HasOptionalString); + Assert.AreEqual("", message.OptionalString); + + message.ClearOptionalString(); + Assert.IsFalse(message.HasOptionalString); + Assert.AreEqual("", message.OptionalString); + + Assert.Throws(() => message.OptionalString = null); + } + + [Test] + public void Clone() + { + var original = new TestProto3Optional { OptionalInt64 = 0L }; + + var clone = original.Clone(); + Assert.False(clone.HasOptionalInt32); + Assert.AreEqual(0, clone.OptionalInt32); + Assert.True(clone.HasOptionalInt64); + Assert.AreEqual(0L, clone.OptionalInt64); + } + + [Test] + public void Serialization_NotSet() + { + var stream = new MemoryStream(); + var message = new TestProto3Optional(); + message.WriteTo(stream); + Assert.AreEqual(0, stream.Length); + } + + [Test] + public void Serialization_SetToDefault() + { + var stream = new MemoryStream(); + var message = new TestProto3Optional { OptionalInt32 = 0 }; + message.WriteTo(stream); + Assert.AreEqual(2, stream.Length); // Tag and value + } + + [Test] + public void Serialization_Roundtrip() + { + var original = new TestProto3Optional { OptionalInt64 = 0L, OptionalFixed32 = 5U }; + var stream = new MemoryStream(); + original.WriteTo(stream); + stream.Position = 0; + var deserialized = TestProto3Optional.Parser.ParseFrom(stream); + + Assert.AreEqual(0, deserialized.OptionalInt32); + Assert.IsFalse(deserialized.HasOptionalInt32); + + Assert.AreEqual(0L, deserialized.OptionalInt64); + Assert.IsTrue(deserialized.HasOptionalInt64); + + Assert.AreEqual(5U, deserialized.OptionalFixed32); + Assert.IsTrue(deserialized.HasOptionalFixed32); + } + + [Test] + public void Equality_IgnoresPresence() + { + var message1 = new TestProto3Optional { OptionalInt32 = 0 }; + var message2 = new TestProto3Optional(); + + Assert.IsTrue(message1.Equals(message2)); + message1.ClearOptionalInt32(); + } + + [Test] + public void MixedFields() + { + var descriptor = MixedRegularAndOptional.Descriptor; + Assert.AreEqual(1, descriptor.Oneofs.Count); + Assert.AreEqual(0, descriptor.RealOneofCount); + Assert.True(descriptor.Oneofs[0].IsSynthetic); + } + } +} diff --git a/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs b/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs new file mode 100644 index 0000000000000..f0248ac3c34f8 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs @@ -0,0 +1,139 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Google.Protobuf +{ + internal static class ReadOnlySequenceFactory + { + /// + /// Create a sequence from the specified data. The data will be divided up into segments in the sequence. + /// + public static ReadOnlySequence CreateWithContent(byte[] data, int segmentSize = 1, bool addEmptySegmentDelimiters = true) + { + var segments = new List(); + + if (addEmptySegmentDelimiters) + { + segments.Add(new byte[0]); + } + + var currentIndex = 0; + while (currentIndex < data.Length) + { + var segment = new List(); + while (segment.Count < segmentSize && currentIndex < data.Length) + { + segment.Add(data[currentIndex++]); + } + segments.Add(segment.ToArray()); + + if (addEmptySegmentDelimiters) + { + segments.Add(new byte[0]); + } + } + + return CreateSegments(segments.ToArray()); + } + + /// + /// Originally from corefx, and has been contributed to Protobuf + /// https://github.com/dotnet/corefx/blob/e99ec129cfd594d53f4390bf97d1d736cff6f860/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceFactory.byte.cs + /// + private static ReadOnlySequence CreateSegments(params byte[][] inputs) + { + if (inputs == null || inputs.Length == 0) + { + throw new InvalidOperationException(); + } + + int i = 0; + + BufferSegment last = null; + BufferSegment first = null; + + do + { + byte[] s = inputs[i]; + int length = s.Length; + int dataOffset = length; + var chars = new byte[length * 2]; + + for (int j = 0; j < length; j++) + { + chars[dataOffset + j] = s[j]; + } + + // Create a segment that has offset relative to the OwnedMemory and OwnedMemory itself has offset relative to array + var memory = new Memory(chars).Slice(length, length); + + if (first == null) + { + first = new BufferSegment(memory); + last = first; + } + else + { + last = last.Append(memory); + } + i++; + } while (i < inputs.Length); + + return new ReadOnlySequence(first, 0, last, last.Memory.Length); + } + + private class BufferSegment : ReadOnlySequenceSegment + { + public BufferSegment(Memory memory) + { + Memory = memory; + } + + public BufferSegment Append(Memory memory) + { + var segment = new BufferSegment(memory) + { + RunningIndex = RunningIndex + Memory.Length + }; + Next = segment; + return segment; + } + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs b/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs new file mode 100644 index 0000000000000..f2d9a2d4e2e40 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs @@ -0,0 +1,119 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using NUnit.Framework; +using System.Diagnostics; +using System; +using System.Reflection; +using System.IO; + +namespace Google.Protobuf +{ + public class RefStructCompatibilityTest + { + /// + /// Checks that the generated code can be compiler with an old C# compiler. + /// The reason why this test is needed is that even though dotnet SDK projects allow to set LangVersion, + /// this setting doesn't accurately simulate compilation with an actual old pre-roslyn C# compiler. + /// For instance, the "ref struct" types are only supported by C# 7.2 and higher, but even if + /// LangVersion is set low, the roslyn compiler still understands the concept of ref struct + /// and silently accepts them. Therefore we try to build the generated code with an actual old C# compiler + /// to be able to catch these sort of compatibility problems. + /// + [Test] + public void GeneratedCodeCompilesWithOldCsharpCompiler() + { + if (Environment.OSVersion.Platform != PlatformID.Win32NT) + { + // This tests needs old C# compiler which is only available on Windows. Skipping it on all other platforms. + return; + } + + var currentAssemblyDir = Path.GetDirectoryName(typeof(RefStructCompatibilityTest).GetTypeInfo().Assembly.Location); + var testProtosProjectDir = Path.GetFullPath(Path.Combine(currentAssemblyDir, "..", "..", "..", "..", "Google.Protobuf.Test.TestProtos")); + var testProtosOutputDir = (currentAssemblyDir.Contains("bin/Debug/") || currentAssemblyDir.Contains("bin\\Debug\\")) ? "bin\\Debug\\net45" : "bin\\Release\\net45"; + + // If "ref struct" types are used in the generated code, compilation with an old compiler will fail with the following error: + // "XYZ is obsolete: 'Types with embedded references are not supported in this version of your compiler.'" + // We build the code with GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE to avoid the use of ref struct in the generated code. + var compatibilityFlag = "-define:GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE"; + var sources = "*.cs"; // the generated sources from the TestProtos project + var args = $"-langversion:3 -target:library {compatibilityFlag} -reference:{testProtosOutputDir}\\Google.Protobuf.dll -out:{testProtosOutputDir}\\TestProtos.RefStructCompatibilityTest.OldCompiler.dll {sources}"; + RunOldCsharpCompilerAndCheckSuccess(args, testProtosProjectDir); + } + + /// + /// Invoke an old C# compiler in a subprocess and check it finished successful. + /// + /// + /// + private void RunOldCsharpCompilerAndCheckSuccess(string args, string workingDirectory) + { + using (var process = new Process()) + { + // Get the path to the old C# 5 compiler from .NET framework. This approach is not 100% reliable, but works on most machines. + // Alternative way of getting the framework path is System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() + // but it only works with the net45 target. + var oldCsharpCompilerPath = Path.Combine(Environment.GetEnvironmentVariable("WINDIR"), "Microsoft.NET", "Framework", "v4.0.30319", "csc.exe"); + process.StartInfo.FileName = oldCsharpCompilerPath; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.RedirectStandardError = true; + process.StartInfo.UseShellExecute = false; + process.StartInfo.Arguments = args; + process.StartInfo.WorkingDirectory = workingDirectory; + + process.OutputDataReceived += (sender, e) => + { + if (e.Data != null) + { + Console.WriteLine(e.Data); + } + }; + process.ErrorDataReceived += (sender, e) => + { + if (e.Data != null) + { + Console.WriteLine(e.Data); + } + }; + + process.Start(); + + process.BeginErrorReadLine(); + process.BeginOutputReadLine(); + + process.WaitForExit(); + Assert.AreEqual(0, process.ExitCode); + } + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs index 68b4d6af7cf8b..68b9bd35074fc 100644 --- a/csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs +++ b/csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs @@ -1,4 +1,4 @@ -#region Copyright notice and license +#region Copyright notice and license // Protocol Buffers - Google's data interchange format // Copyright 2017 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ @@ -33,64 +33,20 @@ using Google.Protobuf.Reflection; using Google.Protobuf.WellKnownTypes; using NUnit.Framework; +using System; using System.IO; using System.Linq; using UnitTest.Issues.TestProtos; using static Google.Protobuf.WireFormat; using static UnitTest.Issues.TestProtos.ComplexOptionType2.Types; +using static UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Extensions; using static UnitTest.Issues.TestProtos.DummyMessageContainingEnum.Types; -using static Google.Protobuf.Test.Reflection.CustomOptionNumber; +using Google.Protobuf.TestProtos; + +#pragma warning disable CS0618 namespace Google.Protobuf.Test.Reflection { - // Internal enum to allow us to use "using static" for convenience. - // These are the options defined in unittest_custom_options_proto3.proto - internal enum CustomOptionNumber - { - FileOpt1 = 7736974, - MessageOpt1 = 7739036, - FieldOpt1 = 7740936, - OneofOpt1 = 7740111, - EnumOpt1 = 7753576, - EnumValueOpt1 = 1560678, - ServiceOpt1 = 7887650, - MethodOpt1 = 7890860, - - // All message options... - BoolOpt = 7706090, - Int32Opt = 7705709, - Int64Opt = 7705542, - UInt32Opt = 7704880, - UInt64Opt = 7702367, - SInt32Opt = 7701568, - SInt64Opt = 7700863, - Fixed32Opt = 7700307, - Fixed64Opt = 7700194, - SFixed32Opt = 7698645, - SFixed64Opt = 7685475, - FloatOpt = 7675390, - DoubleOpt = 7673293, - StringOpt = 7673285, - BytesOpt = 7673238, - EnumOpt = 7673233, - MessageTypeOpt = 7665967, - - // Miscellaneous - ComplexOpt4 = 7633546, - ComplexOpt1 = 7646756, - ComplexOpt2 = 7636949, - ComplexOpt3 = 7636463, - - // Aggregates - AggregateFileOpt = 15478479, - AggregateMsgOpt = 15480088, - AggregateFieldOpt = 15481374, - AggregateEnumOpt = 15483218, - AggregateEnumValueOpt = 15486921, - AggregateServiceOpt = 15497145, - AggregateMethodOpt = 15512713, - } - /// /// The majority of the testing here is done via parsed descriptors. That's simpler to /// achieve (and more important) than constructing a CodedInputStream manually. @@ -99,173 +55,209 @@ public class CustomOptionsTest { delegate bool OptionFetcher(int field, out T value); - [Test] - public void EmptyOptionsIsShared() + OptionFetcher EnumFetcher(CustomOptions options) { - var structOptions = Struct.Descriptor.CustomOptions; - var timestampOptions = Struct.Descriptor.CustomOptions; - Assert.AreSame(structOptions, timestampOptions); + return (int i, out E v) => { + if (options.TryGetInt32(i, out int value)) + { + v = (E)(object)value; + return true; + } + else + { + v = default(E); + return false; + } + }; } [Test] - public void SimpleIntegerTest() + public void BuiltinOptionsCanBeRetrieved() { - var stream = new MemoryStream(); - var output = new CodedOutputStream(stream); - output.WriteTag(MakeTag(1, WireType.Varint)); - output.WriteInt32(1234567); - output.Flush(); - stream.Position = 0; - var input = new CodedInputStream(stream); - input.ReadTag(); - - var options = CustomOptions.Empty; - options = options.ReadOrSkipUnknownField(input); - - int intValue; - Assert.True(options.TryGetInt32(1, out intValue)); - Assert.AreEqual(1234567, intValue); - - string stringValue; - // No ByteString stored values - Assert.False(options.TryGetString(1, out stringValue)); - // Nothing stored for field 2 - Assert.False(options.TryGetInt32(2, out intValue)); + // non-custom options (that are not extensions but regular fields) can only be accessed via descriptor.Options + var fileOptions = UnittestProto3Reflection.Descriptor.GetOptions(); + Assert.AreEqual("Google.Protobuf.TestProtos", fileOptions.CsharpNamespace); } [Test] - public void SimpleStringTest() + public void OptionPresenceCanBeDetected() { - var stream = new MemoryStream(); - var output = new CodedOutputStream(stream); - output.WriteTag(MakeTag(1, WireType.LengthDelimited)); - output.WriteString("value"); - output.Flush(); - stream.Position = 0; - var input = new CodedInputStream(stream); - input.ReadTag(); - - var options = CustomOptions.Empty; - options = options.ReadOrSkipUnknownField(input); + // case 1: the descriptor has no options at all so the options message is not present + Assert.IsNull(TestAllTypes.Descriptor.GetOptions()); - string stringValue; - Assert.True(options.TryGetString(1, out stringValue)); - Assert.AreEqual("value", stringValue); + // case 2: the descriptor has some options, but not the one we're looking for + // HasExtension will be false and GetExtension returns extension's default value + Assert.IsFalse(UnittestProto3Reflection.Descriptor.GetOptions().HasExtension(FileOpt1)); + Assert.AreEqual(0, UnittestProto3Reflection.Descriptor.GetOptions().GetExtension(FileOpt1)); - int intValue; - // No numeric stored values - Assert.False(options.TryGetInt32(1, out intValue)); - // Nothing stored for field 2 - Assert.False(options.TryGetString(2, out stringValue)); + // case 3: option is present + Assert.IsTrue(UnittestCustomOptionsProto3Reflection.Descriptor.GetOptions().HasExtension(FileOpt1)); + Assert.AreEqual(9876543210UL, UnittestCustomOptionsProto3Reflection.Descriptor.GetOptions().GetExtension(FileOpt1)); } [Test] public void ScalarOptions() { - var options = CustomOptionOtherValues.Descriptor.CustomOptions; - AssertOption(-100, options.TryGetInt32, Int32Opt); - AssertOption(12.3456789f, options.TryGetFloat, FloatOpt); - AssertOption(1.234567890123456789d, options.TryGetDouble, DoubleOpt); - AssertOption("Hello, \"World\"", options.TryGetString, StringOpt); - AssertOption(ByteString.CopyFromUtf8("Hello\0World"), options.TryGetBytes, BytesOpt); - AssertOption((int) TestEnumType.TestOptionEnumType2, options.TryGetInt32, EnumOpt); + var d = CustomOptionOtherValues.Descriptor; + var customOptions = d.CustomOptions; + AssertOption(-100, customOptions.TryGetInt32, Int32Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(12.3456789f, customOptions.TryGetFloat, FloatOpt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(1.234567890123456789d, customOptions.TryGetDouble, DoubleOpt, d.GetOption, d.GetOptions().GetExtension); + AssertOption("Hello, \"World\"", customOptions.TryGetString, StringOpt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(ByteString.CopyFromUtf8("Hello\0World"), customOptions.TryGetBytes, BytesOpt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(TestEnumType.TestOptionEnumType2, EnumFetcher(customOptions), EnumOpt, d.GetOption, d.GetOptions().GetExtension); } [Test] public void MessageOptions() { - var options = VariousComplexOptions.Descriptor.CustomOptions; - AssertOption(new ComplexOptionType1 { Foo = 42, Foo4 = { 99, 88 } }, options.TryGetMessage, ComplexOpt1); + var d = VariousComplexOptions.Descriptor; + var customOptions = d.CustomOptions; + AssertOption(new ComplexOptionType1 { Foo = 42, Foo4 = { 99, 88 } }, customOptions.TryGetMessage, ComplexOpt1, d.GetOption, d.GetOptions().GetExtension); AssertOption(new ComplexOptionType2 - { - Baz = 987, Bar = new ComplexOptionType1 { Foo = 743 }, - Fred = new ComplexOptionType4 { Waldo = 321 }, - Barney = { new ComplexOptionType4 { Waldo = 101 }, new ComplexOptionType4 { Waldo = 212 } } - }, - options.TryGetMessage, ComplexOpt2); - AssertOption(new ComplexOptionType3 { Qux = 9 }, options.TryGetMessage, ComplexOpt3); + { + Baz = 987, + Bar = new ComplexOptionType1 { Foo = 743 }, + Fred = new ComplexOptionType4 { Waldo = 321 }, + Barney = { new ComplexOptionType4 { Waldo = 101 }, new ComplexOptionType4 { Waldo = 212 } } + }, + customOptions.TryGetMessage, ComplexOpt2, d.GetOption, d.GetOptions().GetExtension); + AssertOption(new ComplexOptionType3 { Qux = 9 }, customOptions.TryGetMessage, ComplexOpt3, d.GetOption, d.GetOptions().GetExtension); } [Test] public void OptionLocations() { - var fileOptions = UnittestCustomOptionsProto3Reflection.Descriptor.CustomOptions; - AssertOption(9876543210UL, fileOptions.TryGetUInt64, FileOpt1); + var fileDescriptor = UnittestCustomOptionsProto3Reflection.Descriptor; + AssertOption(9876543210UL, fileDescriptor.CustomOptions.TryGetUInt64, FileOpt1, fileDescriptor.GetOption, fileDescriptor.GetOptions().GetExtension); - var messageOptions = TestMessageWithCustomOptions.Descriptor.CustomOptions; - AssertOption(-56, messageOptions.TryGetInt32, MessageOpt1); + var messageDescriptor = TestMessageWithCustomOptions.Descriptor; + AssertOption(-56, messageDescriptor.CustomOptions.TryGetInt32, MessageOpt1, messageDescriptor.GetOption, messageDescriptor.GetOptions().GetExtension); - var fieldOptions = TestMessageWithCustomOptions.Descriptor.Fields["field1"] .CustomOptions; - AssertOption(8765432109UL, fieldOptions.TryGetFixed64, FieldOpt1); + var fieldDescriptor = TestMessageWithCustomOptions.Descriptor.Fields["field1"]; + AssertOption(8765432109UL, fieldDescriptor.CustomOptions.TryGetFixed64, FieldOpt1, fieldDescriptor.GetOption, fieldDescriptor.GetOptions().GetExtension); - var oneofOptions = TestMessageWithCustomOptions.Descriptor.Oneofs[0].CustomOptions; - AssertOption(-99, oneofOptions.TryGetInt32, OneofOpt1); + var oneofDescriptor = TestMessageWithCustomOptions.Descriptor.Oneofs[0]; + AssertOption(-99, oneofDescriptor.CustomOptions.TryGetInt32, OneofOpt1, oneofDescriptor.GetOption, oneofDescriptor.GetOptions().GetExtension); - var enumOptions = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].CustomOptions; - AssertOption(-789, enumOptions.TryGetSFixed32, EnumOpt1); + var enumDescriptor = TestMessageWithCustomOptions.Descriptor.EnumTypes[0]; + AssertOption(-789, enumDescriptor.CustomOptions.TryGetSFixed32, EnumOpt1, enumDescriptor.GetOption, enumDescriptor.GetOptions().GetExtension); - var enumValueOptions = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2).CustomOptions; - AssertOption(123, enumValueOptions.TryGetInt32, EnumValueOpt1); + var enumValueDescriptor = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2); + AssertOption(123, enumValueDescriptor.CustomOptions.TryGetInt32, EnumValueOpt1, enumValueDescriptor.GetOption, enumValueDescriptor.GetOptions().GetExtension); - var service = UnittestCustomOptionsProto3Reflection.Descriptor.Services + var serviceDescriptor = UnittestCustomOptionsProto3Reflection.Descriptor.Services .Single(s => s.Name == "TestServiceWithCustomOptions"); - var serviceOptions = service.CustomOptions; - AssertOption(-9876543210, serviceOptions.TryGetSInt64, ServiceOpt1); + AssertOption(-9876543210, serviceDescriptor.CustomOptions.TryGetSInt64, ServiceOpt1, serviceDescriptor.GetOption, serviceDescriptor.GetOptions().GetExtension); - var methodOptions = service.Methods[0].CustomOptions; - AssertOption((int) UnitTest.Issues.TestProtos.MethodOpt1.Val2, methodOptions.TryGetInt32, CustomOptionNumber.MethodOpt1); + var methodDescriptor = serviceDescriptor.Methods[0]; + AssertOption(UnitTest.Issues.TestProtos.MethodOpt1.Val2, EnumFetcher(methodDescriptor.CustomOptions), UnittestCustomOptionsProto3Extensions.MethodOpt1, methodDescriptor.GetOption, methodDescriptor.GetOptions().GetExtension); } [Test] public void MinValues() { - var options = CustomOptionMinIntegerValues.Descriptor.CustomOptions; - AssertOption(false, options.TryGetBool, BoolOpt); - AssertOption(int.MinValue, options.TryGetInt32, Int32Opt); - AssertOption(long.MinValue, options.TryGetInt64, Int64Opt); - AssertOption(uint.MinValue, options.TryGetUInt32, UInt32Opt); - AssertOption(ulong.MinValue, options.TryGetUInt64, UInt64Opt); - AssertOption(int.MinValue, options.TryGetSInt32, SInt32Opt); - AssertOption(long.MinValue, options.TryGetSInt64, SInt64Opt); - AssertOption(uint.MinValue, options.TryGetUInt32, Fixed32Opt); - AssertOption(ulong.MinValue, options.TryGetUInt64, Fixed64Opt); - AssertOption(int.MinValue, options.TryGetInt32, SFixed32Opt); - AssertOption(long.MinValue, options.TryGetInt64, SFixed64Opt); + var d = CustomOptionMinIntegerValues.Descriptor; + var customOptions = d.CustomOptions; + AssertOption(false, customOptions.TryGetBool, BoolOpt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(int.MinValue, customOptions.TryGetInt32, Int32Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(long.MinValue, customOptions.TryGetInt64, Int64Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(uint.MinValue, customOptions.TryGetUInt32, Uint32Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(ulong.MinValue, customOptions.TryGetUInt64, Uint64Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(int.MinValue, customOptions.TryGetSInt32, Sint32Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(long.MinValue, customOptions.TryGetSInt64, Sint64Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(uint.MinValue, customOptions.TryGetUInt32, Fixed32Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(ulong.MinValue, customOptions.TryGetUInt64, Fixed64Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(int.MinValue, customOptions.TryGetInt32, Sfixed32Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(long.MinValue, customOptions.TryGetInt64, Sfixed64Opt, d.GetOption, d.GetOptions().GetExtension); } [Test] public void MaxValues() { - var options = CustomOptionMaxIntegerValues.Descriptor.CustomOptions; - AssertOption(true, options.TryGetBool, BoolOpt); - AssertOption(int.MaxValue, options.TryGetInt32, Int32Opt); - AssertOption(long.MaxValue, options.TryGetInt64, Int64Opt); - AssertOption(uint.MaxValue, options.TryGetUInt32, UInt32Opt); - AssertOption(ulong.MaxValue, options.TryGetUInt64, UInt64Opt); - AssertOption(int.MaxValue, options.TryGetSInt32, SInt32Opt); - AssertOption(long.MaxValue, options.TryGetSInt64, SInt64Opt); - AssertOption(uint.MaxValue, options.TryGetFixed32, Fixed32Opt); - AssertOption(ulong.MaxValue, options.TryGetFixed64, Fixed64Opt); - AssertOption(int.MaxValue, options.TryGetSFixed32, SFixed32Opt); - AssertOption(long.MaxValue, options.TryGetSFixed64, SFixed64Opt); + var d = CustomOptionMaxIntegerValues.Descriptor; + var customOptions = d.CustomOptions; + AssertOption(true, customOptions.TryGetBool, BoolOpt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(int.MaxValue, customOptions.TryGetInt32, Int32Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(long.MaxValue, customOptions.TryGetInt64, Int64Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(uint.MaxValue, customOptions.TryGetUInt32, Uint32Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(ulong.MaxValue, customOptions.TryGetUInt64, Uint64Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(int.MaxValue, customOptions.TryGetSInt32, Sint32Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(long.MaxValue, customOptions.TryGetSInt64, Sint64Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(uint.MaxValue, customOptions.TryGetFixed32, Fixed32Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(ulong.MaxValue, customOptions.TryGetFixed64, Fixed64Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(int.MaxValue, customOptions.TryGetSFixed32, Sfixed32Opt, d.GetOption, d.GetOptions().GetExtension); + AssertOption(long.MaxValue, customOptions.TryGetSFixed64, Sfixed64Opt, d.GetOption, d.GetOptions().GetExtension); } [Test] public void AggregateOptions() { // Just two examples - var messageOptions = AggregateMessage.Descriptor.CustomOptions; - AssertOption(new Aggregate { I = 101, S = "MessageAnnotation" }, messageOptions.TryGetMessage, AggregateMsgOpt); + var messageDescriptor = AggregateMessage.Descriptor; + AssertOption(new Aggregate { I = 101, S = "MessageAnnotation" }, messageDescriptor.CustomOptions.TryGetMessage, Msgopt, messageDescriptor.GetOption, messageDescriptor.GetOptions().GetExtension); - var fieldOptions = AggregateMessage.Descriptor.Fields["fieldname"].CustomOptions; - AssertOption(new Aggregate { S = "FieldAnnotation" }, fieldOptions.TryGetMessage, AggregateFieldOpt); + var fieldDescriptor = messageDescriptor.Fields["fieldname"]; + AssertOption(new Aggregate { S = "FieldAnnotation" }, fieldDescriptor.CustomOptions.TryGetMessage, Fieldopt, fieldDescriptor.GetOption, fieldDescriptor.GetOptions().GetExtension); } - private void AssertOption(T expected, OptionFetcher fetcher, CustomOptionNumber field) + [Test] + public void NoOptions() { - T actual; - Assert.IsTrue(fetcher((int) field, out actual)); - Assert.AreEqual(expected, actual); + var fileDescriptor = UnittestProto3Reflection.Descriptor; + var messageDescriptor = TestAllTypes.Descriptor; + Assert.NotNull(fileDescriptor.CustomOptions); + Assert.NotNull(messageDescriptor.CustomOptions); + Assert.NotNull(messageDescriptor.Fields[1].CustomOptions); + Assert.NotNull(fileDescriptor.Services[0].CustomOptions); + Assert.NotNull(fileDescriptor.Services[0].Methods[0].CustomOptions); + Assert.NotNull(fileDescriptor.EnumTypes[0].CustomOptions); + Assert.NotNull(fileDescriptor.EnumTypes[0].Values[0].CustomOptions); + Assert.NotNull(TestAllTypes.Descriptor.Oneofs[0].CustomOptions); + } + + [Test] + public void MultipleImportOfSameFileWithExtension() + { + var descriptor = UnittestIssue6936CReflection.Descriptor; + var foo = Foo.Descriptor; + var bar = Bar.Descriptor; + AssertOption("foo", foo.CustomOptions.TryGetString, UnittestIssue6936AExtensions.Opt, foo.GetOption, foo.GetOptions().GetExtension); + AssertOption("bar", bar.CustomOptions.TryGetString, UnittestIssue6936AExtensions.Opt, bar.GetOption, bar.GetOptions().GetExtension); + } + + [Test] + public void SelfReferentialOptions() + { + // Custom field option used in definition of the custom option's message. + var fooField = UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Descriptor.FindFieldByName("foo"); + var fooFieldFooExtensionValue = fooField.GetOptions().GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.FooOptions); + Assert.AreEqual(1234, fooFieldFooExtensionValue.Foo); + + // Custom field option used on the definition of that field option. + var fileDescriptor = UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsReflection.Descriptor; + var barOptionsField = fileDescriptor.Extensions.UnorderedExtensions.Single(field => field.Name == "bar_options"); + var barExtensionValue = barOptionsField.GetOptions().GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.BarOptions); + Assert.AreEqual(1234, barExtensionValue); + + // Custom field option used in definition of the extension message. + var intOptField = UnitTest.Issues.TestProtos.SelfreferentialOptions.FooOptions.Descriptor.FindFieldByName("int_opt"); + var intOptFieldFooExtensionValue = intOptField.GetOptions().GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.FooOptions); + Assert.AreEqual(1, intOptFieldFooExtensionValue.IntOpt); + Assert.AreEqual(2, intOptFieldFooExtensionValue.GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.FooIntOpt)); + Assert.AreEqual(3, intOptFieldFooExtensionValue.GetExtension(UnitTest.Issues.TestProtos.SelfreferentialOptions.UnittestSelfreferentialOptionsExtensions.FooFooOpt).IntOpt); + } + + private void AssertOption(T expected, OptionFetcher customOptionFetcher, Extension extension, Func, T> getOptionFetcher, Func, T> extensionFetcher) where D : IExtendableMessage + { + Assert.IsTrue(customOptionFetcher(extension.FieldNumber, out T customOptionsValue)); + Assert.AreEqual(expected, customOptionsValue); + + T getOptionValue = getOptionFetcher(extension); + Assert.AreEqual(expected, getOptionValue); + + T extensionValue = extensionFetcher(extension); + Assert.AreEqual(expected, extensionValue); } } } diff --git a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorDeclarationTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorDeclarationTest.cs new file mode 100644 index 0000000000000..d9d56672458cd --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorDeclarationTest.cs @@ -0,0 +1,175 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2018 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using Google.Protobuf.Reflection; +using NUnit.Framework; +using System.Linq; +using System.Reflection; + +namespace Google.Protobuf.Test.Reflection +{ + // In reality this isn't a test for DescriptorDeclaration so much as the way they're loaded. + public class DescriptorDeclarationTest + { + static readonly FileDescriptor unitTestProto3Descriptor = LoadProtos(); + + // Note: we don't expose a declaration for FileDescriptor as it doesn't have comments + // at the moment and the locations aren't terribly useful. + + // The tests for most elements are quite basic: we don't test every aspect of every element. + // The code within the library falls into two categories: + // - Exposing the properties for *any* declaration + // - Finding the right declaration for an element from the descriptor data + // We have a per-element check to make sure we *are* finding the right declaration, and we + // check every property of declarations in at least one test, but we don't have a cross-product. + // That would effectively be testing protoc, which seems redundant here. + + [Test] + public void ServiceComments() + { + var service = unitTestProto3Descriptor.FindTypeByName("TestService"); + Assert.NotNull(service.Declaration); + Assert.AreEqual(" This is a test service\n", service.Declaration.LeadingComments); + } + + [Test] + public void MethodComments() + { + var service = unitTestProto3Descriptor.FindTypeByName("TestService"); + var method = service.FindMethodByName("Foo"); + Assert.NotNull(method.Declaration); + Assert.AreEqual(" This is a test method\n", method.Declaration.LeadingComments); + } + + [Test] + public void MessageComments() + { + var message = unitTestProto3Descriptor.FindTypeByName("CommentMessage"); + Assert.NotNull(message.Declaration); + Assert.AreEqual(" This is a leading comment\n", message.Declaration.LeadingComments); + Assert.AreEqual(new[] { " This is leading detached comment 1\n", " This is leading detached comment 2\n" }, + message.Declaration.LeadingDetachedComments); + } + + // Note: this test is somewhat brittle; a change earlier in the proto will break it. + [Test] + public void MessageLocations() + { + var message = unitTestProto3Descriptor.FindTypeByName("CommentMessage"); + Assert.NotNull(message.Declaration); + Assert.AreEqual(389, message.Declaration.StartLine); + Assert.AreEqual(1, message.Declaration.StartColumn); + + Assert.AreEqual(404, message.Declaration.EndLine); + Assert.AreEqual(2, message.Declaration.EndColumn); + } + + [Test] + public void EnumComments() + { + var descriptor = unitTestProto3Descriptor.FindTypeByName("CommentEnum"); + Assert.NotNull(descriptor.Declaration); + Assert.AreEqual(" Leading enum comment\n", descriptor.Declaration.LeadingComments); + } + + [Test] + public void NestedMessageComments() + { + var outer = unitTestProto3Descriptor.FindTypeByName("CommentMessage"); + var nested = outer.FindDescriptor("NestedCommentMessage"); + Assert.NotNull(nested.Declaration); + Assert.AreEqual(" Leading nested message comment\n", nested.Declaration.LeadingComments); + } + + [Test] + public void NestedEnumComments() + { + var outer = unitTestProto3Descriptor.FindTypeByName("CommentMessage"); + var nested = outer.FindDescriptor("NestedCommentEnum"); + Assert.NotNull(nested.Declaration); + Assert.AreEqual(" Leading nested enum comment\n", nested.Declaration.LeadingComments); + } + + [Test] + public void FieldComments() + { + var message = unitTestProto3Descriptor.FindTypeByName("CommentMessage"); + var field = message.FindFieldByName("text"); + Assert.NotNull(field.Declaration); + Assert.AreEqual(" Leading field comment\n", field.Declaration.LeadingComments); + Assert.AreEqual(" Trailing field comment\n", field.Declaration.TrailingComments); + } + + [Test] + public void NestedMessageFieldComments() + { + var outer = unitTestProto3Descriptor.FindTypeByName("CommentMessage"); + var nested = outer.FindDescriptor("NestedCommentMessage"); + var field = nested.FindFieldByName("nested_text"); + Assert.NotNull(field.Declaration); + Assert.AreEqual(" Leading nested message field comment\n", field.Declaration.LeadingComments); + } + + [Test] + public void EnumValueComments() + { + var enumDescriptor = unitTestProto3Descriptor.FindTypeByName("CommentEnum"); + var value = enumDescriptor.FindValueByName("ZERO_VALUE"); + Assert.NotNull(value.Declaration); + Assert.AreEqual(" Zero value comment\n", value.Declaration.LeadingComments); + } + + [Test] + public void NestedEnumValueComments() + { + var outer = unitTestProto3Descriptor.FindTypeByName("CommentMessage"); + var nested = outer.FindDescriptor("NestedCommentEnum"); + var value = nested.FindValueByName("ZERO_VALUE"); + Assert.NotNull(value.Declaration); + Assert.AreEqual(" Zero value comment\n", value.Declaration.LeadingComments); + } + + private static FileDescriptor LoadProtos() + { + var type = typeof(DescriptorDeclarationTest); + // TODO: Make this simpler :) + FileDescriptorSet descriptorSet; + using (var stream = type.GetTypeInfo().Assembly.GetManifestResourceStream($"Google.Protobuf.Test.testprotos.pb")) + { + descriptorSet = FileDescriptorSet.Parser.ParseFrom(stream); + } + var byteStrings = descriptorSet.File.Select(f => f.ToByteString()).ToList(); + var descriptors = FileDescriptor.BuildFromByteStrings(byteStrings); + return descriptors.Single(d => d.Name == "unittest_proto3.proto"); + } + } +} diff --git a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs index 52d5a6769729a..fab983d463517 100644 --- a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs +++ b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs @@ -30,9 +30,13 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion -using System.Linq; using Google.Protobuf.TestProtos; using NUnit.Framework; +using ProtobufUnittest; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; using UnitTest.Issues.TestProtos; namespace Google.Protobuf.Reflection @@ -44,31 +48,66 @@ namespace Google.Protobuf.Reflection public class DescriptorsTest { [Test] - public void FileDescriptor() + public void FileDescriptor_GeneratedCode() { - FileDescriptor file = UnittestProto3Reflection.Descriptor; + TestFileDescriptor( + UnittestProto3Reflection.Descriptor, + UnittestImportProto3Reflection.Descriptor, + UnittestImportPublicProto3Reflection.Descriptor); + } - Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Name); - Assert.AreEqual("protobuf_unittest", file.Package); + [Test] + public void FileDescriptor_BuildFromByteStrings() + { + // The descriptors have to be supplied in an order such that all the + // dependencies come before the descriptors depending on them. + var descriptorData = new List + { + UnittestImportPublicProto3Reflection.Descriptor.SerializedData, + UnittestImportProto3Reflection.Descriptor.SerializedData, + UnittestProto3Reflection.Descriptor.SerializedData + }; + var converted = FileDescriptor.BuildFromByteStrings(descriptorData); + Assert.AreEqual(3, converted.Count); + TestFileDescriptor(converted[2], converted[1], converted[0]); + } + + [Test] + public void FileDescriptor_BuildFromByteStrings_WithExtensionRegistry() + { + var extension = UnittestCustomOptionsProto3Extensions.MessageOpt1; + + var byteStrings = new[] + { + DescriptorReflection.Descriptor.Proto.ToByteString(), + UnittestCustomOptionsProto3Reflection.Descriptor.Proto.ToByteString() + }; + var registry = new ExtensionRegistry { extension }; + + var descriptor = FileDescriptor.BuildFromByteStrings(byteStrings, registry).Last(); + var message = descriptor.MessageTypes.Single(t => t.Name == nameof(TestMessageWithCustomOptions)); + var extensionValue = message.GetOptions().GetExtension(extension); + Assert.AreEqual(-56, extensionValue); + } + + private void TestFileDescriptor(FileDescriptor file, FileDescriptor importedFile, FileDescriptor importedPublicFile) + { + Assert.AreEqual("unittest_proto3.proto", file.Name); + Assert.AreEqual("protobuf_unittest3", file.Package); Assert.AreEqual("UnittestProto", file.Proto.Options.JavaOuterClassname); - Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Proto.Name); + Assert.AreEqual("unittest_proto3.proto", file.Proto.Name); - // unittest.proto doesn't have any public imports, but unittest_import.proto does. + // unittest_proto3.proto doesn't have any public imports, but unittest_import_proto3.proto does. Assert.AreEqual(0, file.PublicDependencies.Count); - Assert.AreEqual(1, UnittestImportProto3Reflection.Descriptor.PublicDependencies.Count); - Assert.AreEqual(UnittestImportPublicProto3Reflection.Descriptor, UnittestImportProto3Reflection.Descriptor.PublicDependencies[0]); + Assert.AreEqual(1, importedFile.PublicDependencies.Count); + Assert.AreEqual(importedPublicFile, importedFile.PublicDependencies[0]); Assert.AreEqual(1, file.Dependencies.Count); - Assert.AreEqual(UnittestImportProto3Reflection.Descriptor, file.Dependencies[0]); + Assert.AreEqual(importedFile, file.Dependencies[0]); - MessageDescriptor messageType = TestAllTypes.Descriptor; - Assert.AreSame(typeof(TestAllTypes), messageType.ClrType); - Assert.AreSame(TestAllTypes.Parser, messageType.Parser); - Assert.AreEqual(messageType, file.MessageTypes[0]); - Assert.AreEqual(messageType, file.FindTypeByName("TestAllTypes")); Assert.Null(file.FindTypeByName("NoSuchType")); - Assert.Null(file.FindTypeByName("protobuf_unittest.TestAllTypes")); + Assert.Null(file.FindTypeByName("protobuf_unittest3.TestAllTypes")); for (int i = 0; i < file.MessageTypes.Count; i++) { Assert.AreEqual(i, file.MessageTypes[i].Index); @@ -76,9 +115,9 @@ public void FileDescriptor() Assert.AreEqual(file.EnumTypes[0], file.FindTypeByName("ForeignEnum")); Assert.Null(file.FindTypeByName("NoSuchType")); - Assert.Null(file.FindTypeByName("protobuf_unittest.ForeignEnum")); - Assert.AreEqual(1, UnittestImportProto3Reflection.Descriptor.EnumTypes.Count); - Assert.AreEqual("ImportEnum", UnittestImportProto3Reflection.Descriptor.EnumTypes[0].Name); + Assert.Null(file.FindTypeByName("protobuf_unittest3.ForeignEnum")); + Assert.AreEqual(1, importedFile.EnumTypes.Count); + Assert.AreEqual("ImportEnum", importedFile.EnumTypes[0].Name); for (int i = 0; i < file.EnumTypes.Count; i++) { Assert.AreEqual(i, file.EnumTypes[i].Index); @@ -87,6 +126,66 @@ public void FileDescriptor() Assert.AreEqual(10, file.SerializedData[0]); } + [Test] + public void FileDescriptor_NonRootPath() + { + // unittest_proto3.proto used to be in google/protobuf. Now it's in the C#-specific location, + // let's test something that's still in a directory. + FileDescriptor file = UnittestWellKnownTypesReflection.Descriptor; + Assert.AreEqual("google/protobuf/unittest_well_known_types.proto", file.Name); + Assert.AreEqual("protobuf_unittest", file.Package); + } + + [Test] + public void FileDescriptor_BuildFromByteStrings_MissingDependency() + { + var descriptorData = new List + { + UnittestImportProto3Reflection.Descriptor.SerializedData, + UnittestProto3Reflection.Descriptor.SerializedData, + }; + // This will fail, because we're missing UnittestImportPublicProto3Reflection + Assert.Throws(() => FileDescriptor.BuildFromByteStrings(descriptorData)); + } + + [Test] + public void FileDescriptor_BuildFromByteStrings_DuplicateNames() + { + var descriptorData = new List + { + UnittestImportPublicProto3Reflection.Descriptor.SerializedData, + UnittestImportPublicProto3Reflection.Descriptor.SerializedData, + }; + // This will fail due to the same name being used twice + Assert.Throws(() => FileDescriptor.BuildFromByteStrings(descriptorData)); + } + + [Test] + public void FileDescriptor_BuildFromByteStrings_IncorrectOrder() + { + var descriptorData = new List + { + UnittestProto3Reflection.Descriptor.SerializedData, + UnittestImportPublicProto3Reflection.Descriptor.SerializedData, + UnittestImportProto3Reflection.Descriptor.SerializedData + }; + // This will fail, because the dependencies should come first + Assert.Throws(() => FileDescriptor.BuildFromByteStrings(descriptorData)); + + } + + [Test] + public void MessageDescriptorFromGeneratedCodeFileDescriptor() + { + var file = UnittestProto3Reflection.Descriptor; + + MessageDescriptor messageType = TestAllTypes.Descriptor; + Assert.AreSame(typeof(TestAllTypes), messageType.ClrType); + Assert.AreSame(TestAllTypes.Parser, messageType.Parser); + Assert.AreEqual(messageType, file.MessageTypes[0]); + Assert.AreEqual(messageType, file.FindTypeByName("TestAllTypes")); + } + [Test] public void MessageDescriptor() { @@ -94,7 +193,7 @@ public void MessageDescriptor() MessageDescriptor nestedType = TestAllTypes.Types.NestedMessage.Descriptor; Assert.AreEqual("TestAllTypes", messageType.Name); - Assert.AreEqual("protobuf_unittest.TestAllTypes", messageType.FullName); + Assert.AreEqual("protobuf_unittest3.TestAllTypes", messageType.FullName); Assert.AreEqual(UnittestProto3Reflection.Descriptor, messageType.File); Assert.IsNull(messageType.ContainingType); Assert.IsNull(messageType.Proto.Options); @@ -102,7 +201,7 @@ public void MessageDescriptor() Assert.AreEqual("TestAllTypes", messageType.Name); Assert.AreEqual("NestedMessage", nestedType.Name); - Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedMessage", nestedType.FullName); + Assert.AreEqual("protobuf_unittest3.TestAllTypes.NestedMessage", nestedType.FullName); Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File); Assert.AreEqual(messageType, nestedType.ContainingType); @@ -135,29 +234,66 @@ public void MessageDescriptor() } [Test] - public void FieldDescriptor() + public void FieldDescriptor_GeneratedCode() { - MessageDescriptor messageType = TestAllTypes.Descriptor; - FieldDescriptor primitiveField = messageType.FindDescriptor("single_int32"); - FieldDescriptor enumField = messageType.FindDescriptor("single_nested_enum"); - FieldDescriptor messageField = messageType.FindDescriptor("single_foreign_message"); + TestFieldDescriptor(UnittestProto3Reflection.Descriptor, TestAllTypes.Descriptor, ForeignMessage.Descriptor, ImportMessage.Descriptor); + } + + [Test] + public void FieldDescriptor_BuildFromByteStrings() + { + // The descriptors have to be supplied in an order such that all the + // dependencies come before the descriptors depending on them. + var descriptorData = new List + { + UnittestImportPublicProto3Reflection.Descriptor.SerializedData, + UnittestImportProto3Reflection.Descriptor.SerializedData, + UnittestProto3Reflection.Descriptor.SerializedData + }; + var converted = FileDescriptor.BuildFromByteStrings(descriptorData); + TestFieldDescriptor( + converted[2], + converted[2].FindTypeByName("TestAllTypes"), + converted[2].FindTypeByName("ForeignMessage"), + converted[1].FindTypeByName("ImportMessage")); + } + + public void TestFieldDescriptor( + FileDescriptor unitTestProto3Descriptor, + MessageDescriptor testAllTypesDescriptor, + MessageDescriptor foreignMessageDescriptor, + MessageDescriptor importMessageDescriptor) + { + FieldDescriptor primitiveField = testAllTypesDescriptor.FindDescriptor("single_int32"); + FieldDescriptor enumField = testAllTypesDescriptor.FindDescriptor("single_nested_enum"); + FieldDescriptor foreignMessageField = testAllTypesDescriptor.FindDescriptor("single_foreign_message"); + FieldDescriptor importMessageField = testAllTypesDescriptor.FindDescriptor("single_import_message"); + FieldDescriptor fieldInOneof = testAllTypesDescriptor.FindDescriptor("oneof_string"); Assert.AreEqual("single_int32", primitiveField.Name); - Assert.AreEqual("protobuf_unittest.TestAllTypes.single_int32", + Assert.AreEqual("protobuf_unittest3.TestAllTypes.single_int32", primitiveField.FullName); Assert.AreEqual(1, primitiveField.FieldNumber); - Assert.AreEqual(messageType, primitiveField.ContainingType); - Assert.AreEqual(UnittestProto3Reflection.Descriptor, primitiveField.File); + Assert.AreEqual(testAllTypesDescriptor, primitiveField.ContainingType); + Assert.AreEqual(unitTestProto3Descriptor, primitiveField.File); Assert.AreEqual(FieldType.Int32, primitiveField.FieldType); Assert.IsNull(primitiveField.Proto.Options); - + Assert.AreEqual("single_nested_enum", enumField.Name); Assert.AreEqual(FieldType.Enum, enumField.FieldType); - // Assert.AreEqual(TestAllTypes.Types.NestedEnum.DescriptorProtoFile, enumField.EnumType); + Assert.AreEqual(testAllTypesDescriptor.EnumTypes[0], enumField.EnumType); + + Assert.AreEqual("single_foreign_message", foreignMessageField.Name); + Assert.AreEqual(FieldType.Message, foreignMessageField.FieldType); + Assert.AreEqual(foreignMessageDescriptor, foreignMessageField.MessageType); - Assert.AreEqual("single_foreign_message", messageField.Name); - Assert.AreEqual(FieldType.Message, messageField.FieldType); - Assert.AreEqual(ForeignMessage.Descriptor, messageField.MessageType); + Assert.AreEqual("single_import_message", importMessageField.Name); + Assert.AreEqual(FieldType.Message, importMessageField.FieldType); + Assert.AreEqual(importMessageDescriptor, importMessageField.MessageType); + + // For a field in a regular onoef, ContainingOneof and RealContainingOneof should be the same. + Assert.AreEqual("oneof_field", fieldInOneof.ContainingOneof.Name); + Assert.AreSame(fieldInOneof.ContainingOneof, fieldInOneof.RealContainingOneof); } [Test] @@ -180,13 +316,13 @@ public void EnumDescriptor() EnumDescriptor nestedType = TestAllTypes.Descriptor.FindDescriptor("NestedEnum"); Assert.AreEqual("ForeignEnum", enumType.Name); - Assert.AreEqual("protobuf_unittest.ForeignEnum", enumType.FullName); + Assert.AreEqual("protobuf_unittest3.ForeignEnum", enumType.FullName); Assert.AreEqual(UnittestProto3Reflection.Descriptor, enumType.File); Assert.Null(enumType.ContainingType); Assert.Null(enumType.Proto.Options); Assert.AreEqual("NestedEnum", nestedType.Name); - Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedEnum", + Assert.AreEqual("protobuf_unittest3.TestAllTypes.NestedEnum", nestedType.FullName); Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File); Assert.AreEqual(TestAllTypes.Descriptor, nestedType.ContainingType); @@ -208,8 +344,9 @@ public void EnumDescriptor() public void OneofDescriptor() { OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor("oneof_field"); + Assert.IsFalse(descriptor.IsSynthetic); Assert.AreEqual("oneof_field", descriptor.Name); - Assert.AreEqual("protobuf_unittest.TestAllTypes.oneof_field", descriptor.FullName); + Assert.AreEqual("protobuf_unittest3.TestAllTypes.oneof_field", descriptor.FullName); var expectedFields = new[] { TestAllTypes.OneofBytesFieldNumber, @@ -242,7 +379,7 @@ public void MapEntryMessageDescriptor() // NestedMessage single_nested_message = 200; [Test] public void FieldListOrderings() - { + { var fields = TestFieldOrderings.Descriptor.Fields; Assert.AreEqual(new[] { 11, 1, 101, 200 }, fields.InDeclarationOrder().Select(x => x.FieldNumber)); Assert.AreEqual(new[] { 1, 11, 101, 200 }, fields.InFieldNumberOrder().Select(x => x.FieldNumber)); @@ -255,5 +392,66 @@ public void DescriptorProtoFileDescriptor() var descriptor = Google.Protobuf.Reflection.FileDescriptor.DescriptorProtoFileDescriptor; Assert.AreEqual("google/protobuf/descriptor.proto", descriptor.Name); } + + [Test] + public void DescriptorImportingExtensionsFromOldCodeGen() + { + // The extension collection includes a null extension. There's not a lot we can do about that + // in itself, as the old generator didn't provide us the extension information. + var extensions = TestProtos.OldGenerator.OldExtensions2Reflection.Descriptor.Extensions; + Assert.AreEqual(1, extensions.UnorderedExtensions.Count); + // Note: this assertion is present so that it will fail if OldExtensions2 is regenerated + // with a new generator. + Assert.Null(extensions.UnorderedExtensions[0].Extension); + + // ... but we can make sure we at least don't cause a failure when retrieving descriptors. + // In particular, old_extensions1.proto imports old_extensions2.proto, and this used to cause + // an execution-time failure. + var importingDescriptor = TestProtos.OldGenerator.OldExtensions1Reflection.Descriptor; + Assert.NotNull(importingDescriptor); + } + + [Test] + public void Proto3OptionalDescriptors() + { + var descriptor = TestProto3Optional.Descriptor; + var field = descriptor.Fields[TestProto3Optional.OptionalInt32FieldNumber]; + Assert.NotNull(field.ContainingOneof); + Assert.IsTrue(field.ContainingOneof.IsSynthetic); + Assert.Null(field.RealContainingOneof); + } + + + [Test] + public void SyntheticOneofReflection() + { + // Expect every oneof in TestProto3Optional to be synthetic + var proto3OptionalDescriptor = TestProto3Optional.Descriptor; + Assert.AreEqual(0, proto3OptionalDescriptor.RealOneofCount); + foreach (var oneof in proto3OptionalDescriptor.Oneofs) + { + Assert.True(oneof.IsSynthetic); + } + + // Expect no oneof in the original proto3 unit test file to be synthetic. + foreach (var descriptor in ProtobufTestMessages.Proto3.TestMessagesProto3Reflection.Descriptor.MessageTypes) + { + Assert.AreEqual(descriptor.Oneofs.Count, descriptor.RealOneofCount); + foreach (var oneof in descriptor.Oneofs) + { + Assert.False(oneof.IsSynthetic); + } + } + + // Expect no oneof in the original proto2 unit test file to be synthetic. + foreach (var descriptor in ProtobufTestMessages.Proto2.TestMessagesProto2Reflection.Descriptor.MessageTypes) + { + Assert.AreEqual(descriptor.Oneofs.Count, descriptor.RealOneofCount); + foreach (var oneof in descriptor.Oneofs) + { + Assert.False(oneof.IsSynthetic); + } + } + } } } diff --git a/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs index a488af30d44dd..b4dcdabdc7514 100644 --- a/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs +++ b/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs @@ -31,11 +31,15 @@ #endregion using Google.Protobuf.TestProtos; +using Proto2 = Google.Protobuf.TestProtos.Proto2; using NUnit.Framework; using System; using System.Collections; using System.Collections.Generic; +using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions; +using ProtobufUnittest; + namespace Google.Protobuf.Reflection { public class FieldAccessTest @@ -44,36 +48,36 @@ public class FieldAccessTest public void GetValue() { var message = SampleMessages.CreateFullTestAllTypes(); - var fields = TestAllTypes.Descriptor.Fields; - Assert.AreEqual(message.SingleBool, fields[TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleBytes, fields[TestAllTypes.SingleBytesFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleDouble, fields[TestAllTypes.SingleDoubleFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleFixed32, fields[TestAllTypes.SingleFixed32FieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleFixed64, fields[TestAllTypes.SingleFixed64FieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleFloat, fields[TestAllTypes.SingleFloatFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleForeignEnum, fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleForeignMessage, fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleImportEnum, fields[TestAllTypes.SingleImportEnumFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleImportMessage, fields[TestAllTypes.SingleImportMessageFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleInt32, fields[TestAllTypes.SingleInt32FieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleInt64, fields[TestAllTypes.SingleInt64FieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleNestedEnum, fields[TestAllTypes.SingleNestedEnumFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleNestedMessage, fields[TestAllTypes.SingleNestedMessageFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SinglePublicImportMessage, fields[TestAllTypes.SinglePublicImportMessageFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleSint32, fields[TestAllTypes.SingleSint32FieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleSint64, fields[TestAllTypes.SingleSint64FieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleString, fields[TestAllTypes.SingleStringFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleSfixed32, fields[TestAllTypes.SingleSfixed32FieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleSfixed64, fields[TestAllTypes.SingleSfixed64FieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleUint32, fields[TestAllTypes.SingleUint32FieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.SingleUint64, fields[TestAllTypes.SingleUint64FieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.OneofBytes, fields[TestAllTypes.OneofBytesFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.OneofString, fields[TestAllTypes.OneofStringFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.OneofNestedMessage, fields[TestAllTypes.OneofNestedMessageFieldNumber].Accessor.GetValue(message)); - Assert.AreEqual(message.OneofUint32, fields[TestAllTypes.OneofUint32FieldNumber].Accessor.GetValue(message)); + var fields = TestProtos.TestAllTypes.Descriptor.Fields; + Assert.AreEqual(message.SingleBool, fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleBytes, fields[TestProtos.TestAllTypes.SingleBytesFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleDouble, fields[TestProtos.TestAllTypes.SingleDoubleFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleFixed32, fields[TestProtos.TestAllTypes.SingleFixed32FieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleFixed64, fields[TestProtos.TestAllTypes.SingleFixed64FieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleFloat, fields[TestProtos.TestAllTypes.SingleFloatFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleForeignEnum, fields[TestProtos.TestAllTypes.SingleForeignEnumFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleForeignMessage, fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleImportEnum, fields[TestProtos.TestAllTypes.SingleImportEnumFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleImportMessage, fields[TestProtos.TestAllTypes.SingleImportMessageFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleInt32, fields[TestProtos.TestAllTypes.SingleInt32FieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleInt64, fields[TestProtos.TestAllTypes.SingleInt64FieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleNestedEnum, fields[TestProtos.TestAllTypes.SingleNestedEnumFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleNestedMessage, fields[TestProtos.TestAllTypes.SingleNestedMessageFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SinglePublicImportMessage, fields[TestProtos.TestAllTypes.SinglePublicImportMessageFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleSint32, fields[TestProtos.TestAllTypes.SingleSint32FieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleSint64, fields[TestProtos.TestAllTypes.SingleSint64FieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleString, fields[TestProtos.TestAllTypes.SingleStringFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleSfixed32, fields[TestProtos.TestAllTypes.SingleSfixed32FieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleSfixed64, fields[TestProtos.TestAllTypes.SingleSfixed64FieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleUint32, fields[TestProtos.TestAllTypes.SingleUint32FieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.SingleUint64, fields[TestProtos.TestAllTypes.SingleUint64FieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.OneofBytes, fields[TestProtos.TestAllTypes.OneofBytesFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.OneofString, fields[TestProtos.TestAllTypes.OneofStringFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.OneofNestedMessage, fields[TestProtos.TestAllTypes.OneofNestedMessageFieldNumber].Accessor.GetValue(message)); + Assert.AreEqual(message.OneofUint32, fields[TestProtos.TestAllTypes.OneofUint32FieldNumber].Accessor.GetValue(message)); // Just one example for repeated fields - they're all just returning the list - var list = (IList) fields[TestAllTypes.RepeatedInt32FieldNumber].Accessor.GetValue(message); + var list = (IList) fields[TestProtos.TestAllTypes.RepeatedInt32FieldNumber].Accessor.GetValue(message); Assert.AreEqual(message.RepeatedInt32, list); Assert.AreEqual(message.RepeatedInt32[0], list[0]); // Just in case there was any doubt... @@ -86,36 +90,118 @@ public void GetValue() } [Test] - public void Clear() + public void GetValue_IncorrectType() { - var message = SampleMessages.CreateFullTestAllTypes(); - var fields = TestAllTypes.Descriptor.Fields; - fields[TestAllTypes.SingleBoolFieldNumber].Accessor.Clear(message); - fields[TestAllTypes.SingleInt32FieldNumber].Accessor.Clear(message); - fields[TestAllTypes.SingleStringFieldNumber].Accessor.Clear(message); - fields[TestAllTypes.SingleBytesFieldNumber].Accessor.Clear(message); - fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.Clear(message); - fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.Clear(message); - fields[TestAllTypes.RepeatedDoubleFieldNumber].Accessor.Clear(message); + IMessage message = SampleMessages.CreateFullTestAllTypes(); + var fields = message.Descriptor.Fields; + Assert.Throws(() => fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(new TestMap())); + } - var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes()) - { - SingleBool = false, - SingleInt32 = 0, - SingleString = "", - SingleBytes = ByteString.Empty, - SingleForeignEnum = 0, - SingleForeignMessage = null, - }; - expected.RepeatedDouble.Clear(); + [Test] + public void HasValue_Proto3_Message() + { + var message = new TestAllTypes(); + var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].Accessor; + Assert.False(accessor.HasValue(message)); + message.SingleForeignMessage = new ForeignMessage(); + Assert.True(accessor.HasValue(message)); + message.SingleForeignMessage = null; + Assert.False(accessor.HasValue(message)); + } - Assert.AreEqual(expected, message); + [Test] + public void HasValue_Proto3_Oneof() + { + TestAllTypes message = new TestAllTypes(); + var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.OneofStringFieldNumber].Accessor; + Assert.False(accessor.HasValue(message)); + // Even though it's the default value, we still have a value. + message.OneofString = ""; + Assert.True(accessor.HasValue(message)); + message.OneofString = "hello"; + Assert.True(accessor.HasValue(message)); + message.OneofUint32 = 10; + Assert.False(accessor.HasValue(message)); + } - // Separately, maps. - var mapMessage = new TestMap { MapStringString = { { "key1", "value1" }, { "key2", "value2" } } }; - fields = TestMap.Descriptor.Fields; - fields[TestMap.MapStringStringFieldNumber].Accessor.Clear(mapMessage); - Assert.AreEqual(0, mapMessage.MapStringString.Count); + [Test] + public void HasValue_Proto3_Primitive_Optional() + { + var message = new TestProto3Optional(); + var accessor = ((IMessage) message).Descriptor.Fields[TestProto3Optional.OptionalInt64FieldNumber].Accessor; + Assert.IsFalse(accessor.HasValue(message)); + message.OptionalInt64 = 5L; + Assert.IsTrue(accessor.HasValue(message)); + message.ClearOptionalInt64(); + Assert.IsFalse(accessor.HasValue(message)); + message.OptionalInt64 = 0L; + Assert.IsTrue(accessor.HasValue(message)); + } + + [Test] + public void HasValue_Proto3_Primitive_NotOptional() + { + IMessage message = SampleMessages.CreateFullTestAllTypes(); + var fields = message.Descriptor.Fields; + Assert.Throws(() => fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.HasValue(message)); + } + + [Test] + public void HasValue_Proto3_Repeated() + { + var message = new TestAllTypes(); + var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.RepeatedBoolFieldNumber].Accessor; + Assert.Throws(() => accessor.HasValue(message)); + } + + [Test] + public void HasValue_Proto2_Primitive() + { + var message = new Proto2.TestAllTypes(); + var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OptionalInt64FieldNumber].Accessor; + + Assert.IsFalse(accessor.HasValue(message)); + message.OptionalInt64 = 5L; + Assert.IsTrue(accessor.HasValue(message)); + message.ClearOptionalInt64(); + Assert.IsFalse(accessor.HasValue(message)); + message.OptionalInt64 = 0L; + Assert.IsTrue(accessor.HasValue(message)); + } + + [Test] + public void HasValue_Proto2_Message() + { + var message = new Proto2.TestAllTypes(); + var field = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OptionalForeignMessageFieldNumber]; + Assert.False(field.Accessor.HasValue(message)); + message.OptionalForeignMessage = new Proto2.ForeignMessage(); + Assert.True(field.Accessor.HasValue(message)); + message.OptionalForeignMessage = null; + Assert.False(field.Accessor.HasValue(message)); + } + + [Test] + public void HasValue_Proto2_Oneof() + { + var message = new Proto2.TestAllTypes(); + var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OneofStringFieldNumber].Accessor; + Assert.False(accessor.HasValue(message)); + // Even though it's the default value, we still have a value. + message.OneofString = ""; + Assert.True(accessor.HasValue(message)); + message.OneofString = "hello"; + Assert.True(accessor.HasValue(message)); + message.OneofUint32 = 10; + Assert.False(accessor.HasValue(message)); + } + + [Test] + public void HasValue_Proto2_Repeated() + { + var message = new Proto2.TestAllTypes(); + var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.RepeatedBoolFieldNumber].Accessor; + Assert.Throws(() => accessor.HasValue(message)); } [Test] @@ -123,14 +209,14 @@ public void SetValue_SingleFields() { // Just a sample (primitives, messages, enums, strings, byte strings) var message = SampleMessages.CreateFullTestAllTypes(); - var fields = TestAllTypes.Descriptor.Fields; - fields[TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, false); - fields[TestAllTypes.SingleInt32FieldNumber].Accessor.SetValue(message, 500); - fields[TestAllTypes.SingleStringFieldNumber].Accessor.SetValue(message, "It's a string"); - fields[TestAllTypes.SingleBytesFieldNumber].Accessor.SetValue(message, ByteString.CopyFrom(99, 98, 97)); - fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.SetValue(message, ForeignEnum.ForeignFoo); - fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.SetValue(message, new ForeignMessage { C = 12345 }); - fields[TestAllTypes.SingleDoubleFieldNumber].Accessor.SetValue(message, 20150701.5); + var fields = TestProtos.TestAllTypes.Descriptor.Fields; + fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, false); + fields[TestProtos.TestAllTypes.SingleInt32FieldNumber].Accessor.SetValue(message, 500); + fields[TestProtos.TestAllTypes.SingleStringFieldNumber].Accessor.SetValue(message, "It's a string"); + fields[TestProtos.TestAllTypes.SingleBytesFieldNumber].Accessor.SetValue(message, ByteString.CopyFrom(99, 98, 97)); + fields[TestProtos.TestAllTypes.SingleForeignEnumFieldNumber].Accessor.SetValue(message, ForeignEnum.ForeignFoo); + fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].Accessor.SetValue(message, new ForeignMessage { C = 12345 }); + fields[TestProtos.TestAllTypes.SingleDoubleFieldNumber].Accessor.SetValue(message, 20150701.5); var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes()) { @@ -151,7 +237,7 @@ public void SetValue_SingleFields_WrongType() { IMessage message = SampleMessages.CreateFullTestAllTypes(); var fields = message.Descriptor.Fields; - Assert.Throws(() => fields[TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, "This isn't a bool")); + Assert.Throws(() => fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, "This isn't a bool")); } [Test] @@ -167,52 +253,184 @@ public void SetValue_RepeatedFields() { IMessage message = SampleMessages.CreateFullTestAllTypes(); var fields = message.Descriptor.Fields; - Assert.Throws(() => fields[TestAllTypes.RepeatedDoubleFieldNumber].Accessor.SetValue(message, new double[10])); - } - - [Test] - public void GetValue_IncorrectType() - { - IMessage message = SampleMessages.CreateFullTestAllTypes(); - var fields = message.Descriptor.Fields; - Assert.Throws(() => fields[TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(new TestMap())); + Assert.Throws(() => fields[TestProtos.TestAllTypes.RepeatedDoubleFieldNumber].Accessor.SetValue(message, new double[10])); } [Test] public void Oneof() { var message = new TestAllTypes(); - var descriptor = TestAllTypes.Descriptor; + var descriptor = TestProtos.TestAllTypes.Descriptor; Assert.AreEqual(1, descriptor.Oneofs.Count); var oneof = descriptor.Oneofs[0]; Assert.AreEqual("oneof_field", oneof.Name); Assert.IsNull(oneof.Accessor.GetCaseFieldDescriptor(message)); message.OneofString = "foo"; - Assert.AreSame(descriptor.Fields[TestAllTypes.OneofStringFieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message)); + Assert.AreSame(descriptor.Fields[TestProtos.TestAllTypes.OneofStringFieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message)); message.OneofUint32 = 10; - Assert.AreSame(descriptor.Fields[TestAllTypes.OneofUint32FieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message)); + Assert.AreSame(descriptor.Fields[TestProtos.TestAllTypes.OneofUint32FieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message)); oneof.Accessor.Clear(message); - Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase); + Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase); + } + + [Test] + public void Clear() + { + var message = SampleMessages.CreateFullTestAllTypes(); + var fields = TestProtos.TestAllTypes.Descriptor.Fields; + fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.Clear(message); + fields[TestProtos.TestAllTypes.SingleInt32FieldNumber].Accessor.Clear(message); + fields[TestProtos.TestAllTypes.SingleStringFieldNumber].Accessor.Clear(message); + fields[TestProtos.TestAllTypes.SingleBytesFieldNumber].Accessor.Clear(message); + fields[TestProtos.TestAllTypes.SingleForeignEnumFieldNumber].Accessor.Clear(message); + fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].Accessor.Clear(message); + fields[TestProtos.TestAllTypes.RepeatedDoubleFieldNumber].Accessor.Clear(message); + + var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes()) + { + SingleBool = false, + SingleInt32 = 0, + SingleString = "", + SingleBytes = ByteString.Empty, + SingleForeignEnum = 0, + SingleForeignMessage = null, + }; + expected.RepeatedDouble.Clear(); + + Assert.AreEqual(expected, message); + + // Separately, maps. + var mapMessage = new TestMap { MapStringString = { { "key1", "value1" }, { "key2", "value2" } } }; + fields = TestMap.Descriptor.Fields; + fields[TestMap.MapStringStringFieldNumber].Accessor.Clear(mapMessage); + Assert.AreEqual(0, mapMessage.MapStringString.Count); + } + + [Test] + public void Clear_Proto3Optional() + { + TestProto3Optional message = new TestProto3Optional + { + OptionalInt32 = 0, + OptionalNestedMessage = new TestProto3Optional.Types.NestedMessage() + }; + var primitiveField = TestProto3Optional.Descriptor.Fields[TestProto3Optional.OptionalInt32FieldNumber]; + var messageField = TestProto3Optional.Descriptor.Fields[TestProto3Optional.OptionalNestedMessageFieldNumber]; + + Assert.True(message.HasOptionalInt32); + Assert.NotNull(message.OptionalNestedMessage); + + primitiveField.Accessor.Clear(message); + messageField.Accessor.Clear(message); + + Assert.False(message.HasOptionalInt32); + Assert.Null(message.OptionalNestedMessage); + } + + [Test] + public void Clear_Proto3_Oneof() + { + var message = new TestAllTypes(); + var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.OneofUint32FieldNumber].Accessor; + + // The field accessor Clear method only affects a oneof if the current case is the one being cleared. + message.OneofString = "hello"; + Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase); + accessor.Clear(message); + Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase); + + message.OneofUint32 = 100; + Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase); + accessor.Clear(message); + Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase); + } + + [Test] + public void Clear_Proto2_Oneof() + { + var message = new Proto2.TestAllTypes(); + var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OneofUint32FieldNumber].Accessor; + + // The field accessor Clear method only affects a oneof if the current case is the one being cleared. + message.OneofString = "hello"; + Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase); + accessor.Clear(message); + Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase); + + message.OneofUint32 = 100; + Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase); + accessor.Clear(message); + Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase); } [Test] public void FieldDescriptor_ByName() { - var descriptor = TestAllTypes.Descriptor; + var descriptor = TestProtos.TestAllTypes.Descriptor; Assert.AreSame( - descriptor.Fields[TestAllTypes.SingleBoolFieldNumber], + descriptor.Fields[TestProtos.TestAllTypes.SingleBoolFieldNumber], descriptor.Fields["single_bool"]); } [Test] public void FieldDescriptor_NotFound() { - var descriptor = TestAllTypes.Descriptor; + var descriptor = TestProtos.TestAllTypes.Descriptor; Assert.Throws(() => descriptor.Fields[999999].ToString()); Assert.Throws(() => descriptor.Fields["not found"].ToString()); - } + } + + [Test] + public void GetExtensionValue() + { + var message = SampleMessages.CreateFullTestAllExtensions(); + + // test that the reflector works, since the reflector just runs through IExtendableMessage + Assert.AreEqual(message.GetExtension(OptionalBoolExtension), Proto2.TestAllExtensions.Descriptor.FindFieldByNumber(OptionalBoolExtension.FieldNumber).Accessor.GetValue(message)); + } + + [Test] + public void GetRepeatedExtensionValue() + { + // check to make sure repeated accessor uses GetOrRegister + var message = new Proto2.TestAllExtensions(); + + Assert.IsNull(message.GetExtension(RepeatedBoolExtension)); + Assert.IsNotNull(Proto2.TestAllExtensions.Descriptor.FindFieldByNumber(RepeatedBoolExtension.FieldNumber).Accessor.GetValue(message)); + Assert.IsNotNull(message.GetExtension(RepeatedBoolExtension)); + + message.ClearExtension(RepeatedBoolExtension); + Assert.IsNull(message.GetExtension(RepeatedBoolExtension)); + } + + [Test] + public void HasPresence() + { + // Proto3 + var fields = TestProtos.TestAllTypes.Descriptor.Fields; + Assert.IsFalse(fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].HasPresence); + Assert.IsTrue(fields[TestProtos.TestAllTypes.OneofBytesFieldNumber].HasPresence); + Assert.IsTrue(fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].HasPresence); + Assert.IsFalse(fields[TestProtos.TestAllTypes.RepeatedBoolFieldNumber].HasPresence); + + fields = TestMap.Descriptor.Fields; + Assert.IsFalse(fields[TestMap.MapBoolBoolFieldNumber].HasPresence); + + fields = TestProto3Optional.Descriptor.Fields; + Assert.IsTrue(fields[TestProto3Optional.OptionalBoolFieldNumber].HasPresence); + + // Proto2 + fields = Proto2.TestAllTypes.Descriptor.Fields; + Assert.IsTrue(fields[Proto2.TestAllTypes.OptionalBoolFieldNumber].HasPresence); + Assert.IsTrue(fields[Proto2.TestAllTypes.OneofBytesFieldNumber].HasPresence); + Assert.IsTrue(fields[Proto2.TestAllTypes.OptionalForeignMessageFieldNumber].HasPresence); + Assert.IsFalse(fields[Proto2.TestAllTypes.RepeatedBoolFieldNumber].HasPresence); + + fields = Proto2.TestRequired.Descriptor.Fields; + Assert.IsTrue(fields[Proto2.TestRequired.AFieldNumber].HasPresence); + } } } diff --git a/csharp/src/Google.Protobuf.Test/SampleEnum.cs b/csharp/src/Google.Protobuf.Test/SampleEnum.cs index 77447afa12734..44f232a53ef6d 100644 --- a/csharp/src/Google.Protobuf.Test/SampleEnum.cs +++ b/csharp/src/Google.Protobuf.Test/SampleEnum.cs @@ -29,7 +29,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion - + namespace Google.Protobuf { // Just a sample enum with positive and negative values to be used in tests. diff --git a/csharp/src/Google.Protobuf.Test/SampleMessages.cs b/csharp/src/Google.Protobuf.Test/SampleMessages.cs index ffa4e2a7c27d2..03a20d6685a2f 100644 --- a/csharp/src/Google.Protobuf.Test/SampleMessages.cs +++ b/csharp/src/Google.Protobuf.Test/SampleMessages.cs @@ -32,6 +32,9 @@ using System; using Google.Protobuf.TestProtos; +using Proto2 = Google.Protobuf.TestProtos.Proto2; + +using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions; namespace Google.Protobuf { @@ -60,7 +63,7 @@ public static TestAllTypes CreateFullTestAllTypes() SingleImportMessage = new ImportMessage { D = 20 }, SingleInt32 = 100, SingleInt64 = 3210987654321, - SingleNestedEnum = TestAllTypes.Types.NestedEnum.Foo, + SingleNestedEnum = TestProtos.TestAllTypes.Types.NestedEnum.Foo, SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 }, SinglePublicImportMessage = new PublicImportMessage { E = 54 }, SingleSfixed32 = -123, @@ -82,7 +85,7 @@ public static TestAllTypes CreateFullTestAllTypes() RepeatedImportMessage = { new ImportMessage { D = 20 }, new ImportMessage { D = 25 } }, RepeatedInt32 = { 100, 200 }, RepeatedInt64 = { 3210987654321, Int64.MaxValue }, - RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.Foo, TestAllTypes.Types.NestedEnum.Neg }, + RepeatedNestedEnum = { TestProtos.TestAllTypes.Types.NestedEnum.Foo, TestProtos.TestAllTypes.Types.NestedEnum.Neg }, RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 35 }, new TestAllTypes.Types.NestedMessage { Bb = 10 } }, RepeatedPublicImportMessage = { new PublicImportMessage { E = 54 }, new PublicImportMessage { E = -1 } }, RepeatedSfixed32 = { -123, 123 }, @@ -95,5 +98,110 @@ public static TestAllTypes CreateFullTestAllTypes() OneofString = "Oneof string" }; } + + public static Proto2.TestAllTypes CreateFullTestAllTypesProto2() + { + return new Proto2.TestAllTypes + { + OptionalBool = true, + OptionalBytes = ByteString.CopyFrom(1, 2, 3, 4), + OptionalDouble = 23.5, + OptionalFixed32 = 23, + OptionalFixed64 = 1234567890123, + OptionalFloat = 12.25f, + OptionalForeignEnum = Proto2.ForeignEnum.ForeignBar, + OptionalForeignMessage = new Proto2.ForeignMessage { C = 10 }, + OptionalImportEnum = Proto2.ImportEnum.ImportBaz, + OptionalImportMessage = new Proto2.ImportMessage { D = 20 }, + OptionalInt32 = 100, + OptionalInt64 = 3210987654321, + OptionalNestedEnum = Proto2.TestAllTypes.Types.NestedEnum.Foo, + OptionalNestedMessage = new Proto2.TestAllTypes.Types.NestedMessage { Bb = 35 }, + OptionalPublicImportMessage = new Proto2.PublicImportMessage { E = 54 }, + OptionalSfixed32 = -123, + OptionalSfixed64 = -12345678901234, + OptionalSint32 = -456, + OptionalSint64 = -12345678901235, + OptionalString = "test", + OptionalUint32 = UInt32.MaxValue, + OptionalUint64 = UInt64.MaxValue, + OptionalGroup = new Proto2.TestAllTypes.Types.OptionalGroup { A = 10 }, + RepeatedBool = { true, false }, + RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6), ByteString.CopyFrom(new byte[1000]) }, + RepeatedDouble = { -12.25, 23.5 }, + RepeatedFixed32 = { UInt32.MaxValue, 23 }, + RepeatedFixed64 = { UInt64.MaxValue, 1234567890123 }, + RepeatedFloat = { 100f, 12.25f }, + RepeatedForeignEnum = { Proto2.ForeignEnum.ForeignFoo, Proto2.ForeignEnum.ForeignBar }, + RepeatedForeignMessage = { new Proto2.ForeignMessage(), new Proto2.ForeignMessage { C = 10 } }, + RepeatedImportEnum = { Proto2.ImportEnum.ImportBaz, Proto2.ImportEnum.ImportFoo }, + RepeatedImportMessage = { new Proto2.ImportMessage { D = 20 }, new Proto2.ImportMessage { D = 25 } }, + RepeatedInt32 = { 100, 200 }, + RepeatedInt64 = { 3210987654321, Int64.MaxValue }, + RepeatedNestedEnum = { Proto2.TestAllTypes.Types.NestedEnum.Foo, Proto2.TestAllTypes.Types.NestedEnum.Neg }, + RepeatedNestedMessage = { new Proto2.TestAllTypes.Types.NestedMessage { Bb = 35 }, new Proto2.TestAllTypes.Types.NestedMessage { Bb = 10 } }, + RepeatedSfixed32 = { -123, 123 }, + RepeatedSfixed64 = { -12345678901234, 12345678901234 }, + RepeatedSint32 = { -456, 100 }, + RepeatedSint64 = { -12345678901235, 123 }, + RepeatedString = { "foo", "bar" }, + RepeatedUint32 = { UInt32.MaxValue, UInt32.MinValue }, + RepeatedUint64 = { UInt64.MaxValue, UInt32.MinValue }, + RepeatedGroup = { new Proto2.TestAllTypes.Types.RepeatedGroup { A = 10 }, new Proto2.TestAllTypes.Types.RepeatedGroup { A = 20 } }, + OneofString = "Oneof string" + }; + } + + public static Proto2.TestAllExtensions CreateFullTestAllExtensions() + { + var message = new Proto2.TestAllExtensions(); + message.SetExtension(OptionalBoolExtension, true); + message.SetExtension(OptionalBytesExtension, ByteString.CopyFrom(1, 2, 3, 4)); + message.SetExtension(OptionalDoubleExtension, 23.5); + message.SetExtension(OptionalFixed32Extension, 23u); + message.SetExtension(OptionalFixed64Extension, 1234567890123u); + message.SetExtension(OptionalFloatExtension, 12.25f); + message.SetExtension(OptionalForeignEnumExtension, Proto2.ForeignEnum.ForeignBar); + message.SetExtension(OptionalForeignMessageExtension, new Proto2.ForeignMessage { C = 10 }); + message.SetExtension(OptionalImportEnumExtension, Proto2.ImportEnum.ImportBaz); + message.SetExtension(OptionalImportMessageExtension, new Proto2.ImportMessage { D = 20 }); + message.SetExtension(OptionalInt32Extension, 100); + message.SetExtension(OptionalInt64Extension, 3210987654321); + message.SetExtension(OptionalNestedEnumExtension, Proto2.TestAllTypes.Types.NestedEnum.Foo); + message.SetExtension(OptionalNestedMessageExtension, new Proto2.TestAllTypes.Types.NestedMessage { Bb = 35 }); + message.SetExtension(OptionalPublicImportMessageExtension, new Proto2.PublicImportMessage { E = 54 }); + message.SetExtension(OptionalSfixed32Extension, -123); + message.SetExtension(OptionalSfixed64Extension, -12345678901234); + message.SetExtension(OptionalSint32Extension, -456); + message.SetExtension(OptionalSint64Extension, -12345678901235); + message.SetExtension(OptionalStringExtension, "test"); + message.SetExtension(OptionalUint32Extension, UInt32.MaxValue); + message.SetExtension(OptionalUint64Extension, UInt64.MaxValue); + message.SetExtension(OptionalGroupExtension, new Proto2.OptionalGroup_extension { A = 10 }); + message.GetOrInitializeExtension(RepeatedBoolExtension).AddRange(new[] { true, false }); + message.GetOrInitializeExtension(RepeatedBytesExtension).AddRange(new[] { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6), ByteString.CopyFrom(new byte[1000]) }); + message.GetOrInitializeExtension(RepeatedDoubleExtension).AddRange(new[] { -12.25, 23.5 }); + message.GetOrInitializeExtension(RepeatedFixed32Extension).AddRange(new[] { UInt32.MaxValue, 23u }); + message.GetOrInitializeExtension(RepeatedFixed64Extension).AddRange(new[] { UInt64.MaxValue, 1234567890123ul }); + message.GetOrInitializeExtension(RepeatedFloatExtension).AddRange(new[] { 100f, 12.25f }); + message.GetOrInitializeExtension(RepeatedForeignEnumExtension).AddRange(new[] { Proto2.ForeignEnum.ForeignFoo, Proto2.ForeignEnum.ForeignBar }); + message.GetOrInitializeExtension(RepeatedForeignMessageExtension).AddRange(new[] { new Proto2.ForeignMessage(), new Proto2.ForeignMessage { C = 10 } }); + message.GetOrInitializeExtension(RepeatedImportEnumExtension).AddRange(new[] { Proto2.ImportEnum.ImportBaz, Proto2.ImportEnum.ImportFoo }); + message.GetOrInitializeExtension(RepeatedImportMessageExtension).AddRange(new[] { new Proto2.ImportMessage { D = 20 }, new Proto2.ImportMessage { D = 25 } }); + message.GetOrInitializeExtension(RepeatedInt32Extension).AddRange(new[] { 100, 200 }); + message.GetOrInitializeExtension(RepeatedInt64Extension).AddRange(new[] { 3210987654321, Int64.MaxValue }); + message.GetOrInitializeExtension(RepeatedNestedEnumExtension).AddRange(new[] { Proto2.TestAllTypes.Types.NestedEnum.Foo, Proto2.TestAllTypes.Types.NestedEnum.Neg }); + message.GetOrInitializeExtension(RepeatedNestedMessageExtension).AddRange(new[] { new Proto2.TestAllTypes.Types.NestedMessage { Bb = 35 }, new Proto2.TestAllTypes.Types.NestedMessage { Bb = 10 } }); + message.GetOrInitializeExtension(RepeatedSfixed32Extension).AddRange(new[] { -123, 123 }); + message.GetOrInitializeExtension(RepeatedSfixed64Extension).AddRange(new[] { -12345678901234, 12345678901234 }); + message.GetOrInitializeExtension(RepeatedSint32Extension).AddRange(new[] { -456, 100 }); + message.GetOrInitializeExtension(RepeatedSint64Extension).AddRange(new[] { -12345678901235, 123 }); + message.GetOrInitializeExtension(RepeatedStringExtension).AddRange(new[] { "foo", "bar" }); + message.GetOrInitializeExtension(RepeatedUint32Extension).AddRange(new[] { UInt32.MaxValue, UInt32.MinValue }); + message.GetOrInitializeExtension(RepeatedUint64Extension).AddRange(new[] { UInt64.MaxValue, UInt32.MinValue }); + message.GetOrInitializeExtension(RepeatedGroupExtension).AddRange(new[] { new Proto2.RepeatedGroup_extension { A = 10 }, new Proto2.RepeatedGroup_extension { A = 20 } }); + message.SetExtension(OneofStringExtension, "Oneof string"); + return message; + } } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/SampleNaNs.cs b/csharp/src/Google.Protobuf.Test/SampleNaNs.cs new file mode 100644 index 0000000000000..34019ac1d2a21 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/SampleNaNs.cs @@ -0,0 +1,53 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2017 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; + +namespace Google.Protobuf +{ + /// + /// Samples of different not-a-number values, for testing equality comparisons. + /// + public static class SampleNaNs + { + public static double Regular { get; } = double.NaN; + + // Signalling bit is inverted compared with double.NaN. Doesn't really matter + // whether that makes it quiet or signalling - it's different. + public static double SignallingFlipped { get; } = + BitConverter.Int64BitsToDouble(BitConverter.DoubleToInt64Bits(double.NaN) ^ -0x8000_0000_0000_0000L); + + // A bit in the middle of the mantissa is flipped; this difference is preserved when casting to float. + public static double PayloadFlipped { get; } = + BitConverter.Int64BitsToDouble(BitConverter.DoubleToInt64Bits(double.NaN) ^ 0x1_0000_0000L); + } +} diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs deleted file mode 100644 index 9c0518a399da4..0000000000000 --- a/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs +++ /dev/null @@ -1,1599 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/map_unittest_proto3.proto -#pragma warning disable 1591, 0612, 3021 -#region Designer generated code - -using pb = global::Google.Protobuf; -using pbc = global::Google.Protobuf.Collections; -using pbr = global::Google.Protobuf.Reflection; -using scg = global::System.Collections.Generic; -namespace Google.Protobuf.TestProtos { - - /// Holder for reflection information generated from google/protobuf/map_unittest_proto3.proto - public static partial class MapUnittestProto3Reflection { - - #region Descriptor - /// File descriptor for google/protobuf/map_unittest_proto3.proto - public static pbr::FileDescriptor Descriptor { - get { return descriptor; } - } - private static pbr::FileDescriptor descriptor; - - static MapUnittestProto3Reflection() { - byte[] descriptorData = global::System.Convert.FromBase64String( - string.Concat( - "Cilnb29nbGUvcHJvdG9idWYvbWFwX3VuaXR0ZXN0X3Byb3RvMy5wcm90bxIR", - "cHJvdG9idWZfdW5pdHRlc3QaJWdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9w", - "cm90bzMucHJvdG8ilhIKB1Rlc3RNYXASRgoPbWFwX2ludDMyX2ludDMyGAEg", - "AygLMi0ucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkludDMy", - "RW50cnkSRgoPbWFwX2ludDY0X2ludDY0GAIgAygLMi0ucHJvdG9idWZfdW5p", - "dHRlc3QuVGVzdE1hcC5NYXBJbnQ2NEludDY0RW50cnkSSgoRbWFwX3VpbnQz", - "Ml91aW50MzIYAyADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1h", - "cFVpbnQzMlVpbnQzMkVudHJ5EkoKEW1hcF91aW50NjRfdWludDY0GAQgAygL", - "Mi8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBVaW50NjRVaW50NjRF", - "bnRyeRJKChFtYXBfc2ludDMyX3NpbnQzMhgFIAMoCzIvLnByb3RvYnVmX3Vu", - "aXR0ZXN0LlRlc3RNYXAuTWFwU2ludDMyU2ludDMyRW50cnkSSgoRbWFwX3Np", - "bnQ2NF9zaW50NjQYBiADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFw", - "Lk1hcFNpbnQ2NFNpbnQ2NEVudHJ5Ek4KE21hcF9maXhlZDMyX2ZpeGVkMzIY", - "ByADKAsyMS5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1hcEZpeGVkMzJG", - "aXhlZDMyRW50cnkSTgoTbWFwX2ZpeGVkNjRfZml4ZWQ2NBgIIAMoCzIxLnBy", - "b3RvYnVmX3VuaXR0ZXN0LlRlc3RNYXAuTWFwRml4ZWQ2NEZpeGVkNjRFbnRy", - "eRJSChVtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIYCSADKAsyMy5wcm90b2J1Zl91", - "bml0dGVzdC5UZXN0TWFwLk1hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeRJSChVt", - "YXBfc2ZpeGVkNjRfc2ZpeGVkNjQYCiADKAsyMy5wcm90b2J1Zl91bml0dGVz", - "dC5UZXN0TWFwLk1hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeRJGCg9tYXBfaW50", - "MzJfZmxvYXQYCyADKAsyLS5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1h", - "cEludDMyRmxvYXRFbnRyeRJIChBtYXBfaW50MzJfZG91YmxlGAwgAygLMi4u", - "cHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkRvdWJsZUVudHJ5", - "EkIKDW1hcF9ib29sX2Jvb2wYDSADKAsyKy5wcm90b2J1Zl91bml0dGVzdC5U", - "ZXN0TWFwLk1hcEJvb2xCb29sRW50cnkSSgoRbWFwX3N0cmluZ19zdHJpbmcY", - "DiADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1hcFN0cmluZ1N0", - "cmluZ0VudHJ5EkYKD21hcF9pbnQzMl9ieXRlcxgPIAMoCzItLnByb3RvYnVm", - "X3VuaXR0ZXN0LlRlc3RNYXAuTWFwSW50MzJCeXRlc0VudHJ5EkQKDm1hcF9p", - "bnQzMl9lbnVtGBAgAygLMiwucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5N", - "YXBJbnQzMkVudW1FbnRyeRJZChltYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdl", - "GBEgAygLMjYucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkZv", - "cmVpZ25NZXNzYWdlRW50cnkaNAoSTWFwSW50MzJJbnQzMkVudHJ5EgsKA2tl", - "eRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEaNAoSTWFwSW50NjRJbnQ2NEVu", - "dHJ5EgsKA2tleRgBIAEoAxINCgV2YWx1ZRgCIAEoAzoCOAEaNgoUTWFwVWlu", - "dDMyVWludDMyRW50cnkSCwoDa2V5GAEgASgNEg0KBXZhbHVlGAIgASgNOgI4", - "ARo2ChRNYXBVaW50NjRVaW50NjRFbnRyeRILCgNrZXkYASABKAQSDQoFdmFs", - "dWUYAiABKAQ6AjgBGjYKFE1hcFNpbnQzMlNpbnQzMkVudHJ5EgsKA2tleRgB", - "IAEoERINCgV2YWx1ZRgCIAEoEToCOAEaNgoUTWFwU2ludDY0U2ludDY0RW50", - "cnkSCwoDa2V5GAEgASgSEg0KBXZhbHVlGAIgASgSOgI4ARo4ChZNYXBGaXhl", - "ZDMyRml4ZWQzMkVudHJ5EgsKA2tleRgBIAEoBxINCgV2YWx1ZRgCIAEoBzoC", - "OAEaOAoWTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRILCgNrZXkYASABKAYSDQoF", - "dmFsdWUYAiABKAY6AjgBGjoKGE1hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeRIL", - "CgNrZXkYASABKA8SDQoFdmFsdWUYAiABKA86AjgBGjoKGE1hcFNmaXhlZDY0", - "U2ZpeGVkNjRFbnRyeRILCgNrZXkYASABKBASDQoFdmFsdWUYAiABKBA6AjgB", - "GjQKEk1hcEludDMyRmxvYXRFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUY", - "AiABKAI6AjgBGjUKE01hcEludDMyRG91YmxlRW50cnkSCwoDa2V5GAEgASgF", - "Eg0KBXZhbHVlGAIgASgBOgI4ARoyChBNYXBCb29sQm9vbEVudHJ5EgsKA2tl", - "eRgBIAEoCBINCgV2YWx1ZRgCIAEoCDoCOAEaNgoUTWFwU3RyaW5nU3RyaW5n", - "RW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ARo0ChJNYXBJ", - "bnQzMkJ5dGVzRW50cnkSCwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgMOgI4", - "ARpPChFNYXBJbnQzMkVudW1FbnRyeRILCgNrZXkYASABKAUSKQoFdmFsdWUY", - "AiABKA4yGi5wcm90b2J1Zl91bml0dGVzdC5NYXBFbnVtOgI4ARpgChtNYXBJ", - "bnQzMkZvcmVpZ25NZXNzYWdlRW50cnkSCwoDa2V5GAEgASgFEjAKBXZhbHVl", - "GAIgASgLMiEucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2U6AjgB", - "IkEKEVRlc3RNYXBTdWJtZXNzYWdlEiwKCHRlc3RfbWFwGAEgASgLMhoucHJv", - "dG9idWZfdW5pdHRlc3QuVGVzdE1hcCK8AQoOVGVzdE1lc3NhZ2VNYXASUQoR", - "bWFwX2ludDMyX21lc3NhZ2UYASADKAsyNi5wcm90b2J1Zl91bml0dGVzdC5U", - "ZXN0TWVzc2FnZU1hcC5NYXBJbnQzMk1lc3NhZ2VFbnRyeRpXChRNYXBJbnQz", - "Mk1lc3NhZ2VFbnRyeRILCgNrZXkYASABKAUSLgoFdmFsdWUYAiABKAsyHy5w", - "cm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXM6AjgBIuMBCg9UZXN0U2Ft", - "ZVR5cGVNYXASOgoEbWFwMRgBIAMoCzIsLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RTYW1lVHlwZU1hcC5NYXAxRW50cnkSOgoEbWFwMhgCIAMoCzIsLnByb3Rv", - "YnVmX3VuaXR0ZXN0LlRlc3RTYW1lVHlwZU1hcC5NYXAyRW50cnkaKwoJTWFw", - "MUVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEaKwoJTWFw", - "MkVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEi5BAKDFRl", - "c3RBcmVuYU1hcBJLCg9tYXBfaW50MzJfaW50MzIYASADKAsyMi5wcm90b2J1", - "Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwSW50MzJJbnQzMkVudHJ5EksK", - "D21hcF9pbnQ2NF9pbnQ2NBgCIAMoCzIyLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBcmVuYU1hcC5NYXBJbnQ2NEludDY0RW50cnkSTwoRbWFwX3VpbnQzMl91", - "aW50MzIYAyADKAsyNC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAu", - "TWFwVWludDMyVWludDMyRW50cnkSTwoRbWFwX3VpbnQ2NF91aW50NjQYBCAD", - "KAsyNC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwVWludDY0", - "VWludDY0RW50cnkSTwoRbWFwX3NpbnQzMl9zaW50MzIYBSADKAsyNC5wcm90", - "b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwU2ludDMyU2ludDMyRW50", - "cnkSTwoRbWFwX3NpbnQ2NF9zaW50NjQYBiADKAsyNC5wcm90b2J1Zl91bml0", - "dGVzdC5UZXN0QXJlbmFNYXAuTWFwU2ludDY0U2ludDY0RW50cnkSUwoTbWFw", - "X2ZpeGVkMzJfZml4ZWQzMhgHIAMoCzI2LnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBcmVuYU1hcC5NYXBGaXhlZDMyRml4ZWQzMkVudHJ5ElMKE21hcF9maXhl", - "ZDY0X2ZpeGVkNjQYCCADKAsyNi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJl", - "bmFNYXAuTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRJXChVtYXBfc2ZpeGVkMzJf", - "c2ZpeGVkMzIYCSADKAsyOC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFN", - "YXAuTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5ElcKFW1hcF9zZml4ZWQ2NF9z", - "Zml4ZWQ2NBgKIAMoCzI4LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBcmVuYU1h", - "cC5NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkSSwoPbWFwX2ludDMyX2Zsb2F0", - "GAsgAygLMjIucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1hcElu", - "dDMyRmxvYXRFbnRyeRJNChBtYXBfaW50MzJfZG91YmxlGAwgAygLMjMucHJv", - "dG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1hcEludDMyRG91YmxlRW50", - "cnkSRwoNbWFwX2Jvb2xfYm9vbBgNIAMoCzIwLnByb3RvYnVmX3VuaXR0ZXN0", - "LlRlc3RBcmVuYU1hcC5NYXBCb29sQm9vbEVudHJ5EkkKDm1hcF9pbnQzMl9l", - "bnVtGA4gAygLMjEucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1h", - "cEludDMyRW51bUVudHJ5El4KGW1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UY", - "DyADKAsyOy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwSW50", - "MzJGb3JlaWduTWVzc2FnZUVudHJ5GjQKEk1hcEludDMySW50MzJFbnRyeRIL", - "CgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1hcEludDY0SW50", - "NjRFbnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6AjgBGjYKFE1h", - "cFVpbnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2YWx1ZRgCIAEo", - "DToCOAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5GAEgASgEEg0K", - "BXZhbHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJFbnRyeRILCgNr", - "ZXkYASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNpbnQ2NFNpbnQ2", - "NEVudHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoCOAEaOAoWTWFw", - "Rml4ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoFdmFsdWUYAiAB", - "KAc6AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoDa2V5GAEgASgG", - "Eg0KBXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNmaXhlZDMyRW50", - "cnkSCwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6ChhNYXBTZml4", - "ZWQ2NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZhbHVlGAIgASgQ", - "OgI4ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEgASgFEg0KBXZh", - "bHVlGAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5EgsKA2tleRgB", - "IAEoBRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJvb2xFbnRyeRIL", - "CgNrZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGk8KEU1hcEludDMyRW51", - "bUVudHJ5EgsKA2tleRgBIAEoBRIpCgV2YWx1ZRgCIAEoDjIaLnByb3RvYnVm", - "X3VuaXR0ZXN0Lk1hcEVudW06AjgBGmAKG01hcEludDMyRm9yZWlnbk1lc3Nh", - "Z2VFbnRyeRILCgNrZXkYASABKAUSMAoFdmFsdWUYAiABKAsyIS5wcm90b2J1", - "Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZToCOAEi5AEKH01lc3NhZ2VDb250", - "YWluaW5nRW51bUNhbGxlZFR5cGUSSgoEdHlwZRgBIAMoCzI8LnByb3RvYnVm", - "X3VuaXR0ZXN0Lk1lc3NhZ2VDb250YWluaW5nRW51bUNhbGxlZFR5cGUuVHlw", - "ZUVudHJ5Gl8KCVR5cGVFbnRyeRILCgNrZXkYASABKAUSQQoFdmFsdWUYAiAB", - "KAsyMi5wcm90b2J1Zl91bml0dGVzdC5NZXNzYWdlQ29udGFpbmluZ0VudW1D", - "YWxsZWRUeXBlOgI4ASIUCgRUeXBlEgwKCFRZUEVfRk9PEAAinQEKH01lc3Nh", - "Z2VDb250YWluaW5nTWFwQ2FsbGVkRW50cnkSTAoFZW50cnkYASADKAsyPS5w", - "cm90b2J1Zl91bml0dGVzdC5NZXNzYWdlQ29udGFpbmluZ01hcENhbGxlZEVu", - "dHJ5LkVudHJ5RW50cnkaLAoKRW50cnlFbnRyeRILCgNrZXkYASABKAUSDQoF", - "dmFsdWUYAiABKAU6AjgBKj8KB01hcEVudW0SEAoMTUFQX0VOVU1fRk9PEAAS", - "EAoMTUFQX0VOVU1fQkFSEAESEAoMTUFQX0VOVU1fQkFaEAJCIPgBAaoCGkdv", - "b2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zYgZwcm90bzM=")); - descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, - new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor, }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.MapEnum), }, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMap), global::Google.Protobuf.TestProtos.TestMap.Parser, new[]{ "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapInt32Bytes", "MapInt32Enum", "MapInt32ForeignMessage" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMapSubmessage), global::Google.Protobuf.TestProtos.TestMapSubmessage.Parser, new[]{ "TestMap" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMessageMap), global::Google.Protobuf.TestProtos.TestMessageMap.Parser, new[]{ "MapInt32Message" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, }), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestSameTypeMap), global::Google.Protobuf.TestProtos.TestSameTypeMap.Parser, new[]{ "Map1", "Map2" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, }), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestArenaMap), global::Google.Protobuf.TestProtos.TestArenaMap.Parser, new[]{ "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapInt32Enum", "MapInt32ForeignMessage" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType), global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Parser, new[]{ "Type" }, null, new[]{ typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Types.Type) }, new pbr::GeneratedClrTypeInfo[] { null, }), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry), global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry.Parser, new[]{ "Entry" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, }) - })); - } - #endregion - - } - #region Enums - public enum MapEnum { - [pbr::OriginalName("MAP_ENUM_FOO")] Foo = 0, - [pbr::OriginalName("MAP_ENUM_BAR")] Bar = 1, - [pbr::OriginalName("MAP_ENUM_BAZ")] Baz = 2, - } - - #endregion - - #region Messages - /// - /// Tests maps. - /// - public sealed partial class TestMap : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMap()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMap() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMap(TestMap other) : this() { - mapInt32Int32_ = other.mapInt32Int32_.Clone(); - mapInt64Int64_ = other.mapInt64Int64_.Clone(); - mapUint32Uint32_ = other.mapUint32Uint32_.Clone(); - mapUint64Uint64_ = other.mapUint64Uint64_.Clone(); - mapSint32Sint32_ = other.mapSint32Sint32_.Clone(); - mapSint64Sint64_ = other.mapSint64Sint64_.Clone(); - mapFixed32Fixed32_ = other.mapFixed32Fixed32_.Clone(); - mapFixed64Fixed64_ = other.mapFixed64Fixed64_.Clone(); - mapSfixed32Sfixed32_ = other.mapSfixed32Sfixed32_.Clone(); - mapSfixed64Sfixed64_ = other.mapSfixed64Sfixed64_.Clone(); - mapInt32Float_ = other.mapInt32Float_.Clone(); - mapInt32Double_ = other.mapInt32Double_.Clone(); - mapBoolBool_ = other.mapBoolBool_.Clone(); - mapStringString_ = other.mapStringString_.Clone(); - mapInt32Bytes_ = other.mapInt32Bytes_.Clone(); - mapInt32Enum_ = other.mapInt32Enum_.Clone(); - mapInt32ForeignMessage_ = other.mapInt32ForeignMessage_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMap Clone() { - return new TestMap(this); - } - - /// Field number for the "map_int32_int32" field. - public const int MapInt32Int32FieldNumber = 1; - private static readonly pbc::MapField.Codec _map_mapInt32Int32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 10); - private readonly pbc::MapField mapInt32Int32_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32Int32 { - get { return mapInt32Int32_; } - } - - /// Field number for the "map_int64_int64" field. - public const int MapInt64Int64FieldNumber = 2; - private static readonly pbc::MapField.Codec _map_mapInt64Int64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt64(8), pb::FieldCodec.ForInt64(16), 18); - private readonly pbc::MapField mapInt64Int64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt64Int64 { - get { return mapInt64Int64_; } - } - - /// Field number for the "map_uint32_uint32" field. - public const int MapUint32Uint32FieldNumber = 3; - private static readonly pbc::MapField.Codec _map_mapUint32Uint32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForUInt32(8), pb::FieldCodec.ForUInt32(16), 26); - private readonly pbc::MapField mapUint32Uint32_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapUint32Uint32 { - get { return mapUint32Uint32_; } - } - - /// Field number for the "map_uint64_uint64" field. - public const int MapUint64Uint64FieldNumber = 4; - private static readonly pbc::MapField.Codec _map_mapUint64Uint64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForUInt64(8), pb::FieldCodec.ForUInt64(16), 34); - private readonly pbc::MapField mapUint64Uint64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapUint64Uint64 { - get { return mapUint64Uint64_; } - } - - /// Field number for the "map_sint32_sint32" field. - public const int MapSint32Sint32FieldNumber = 5; - private static readonly pbc::MapField.Codec _map_mapSint32Sint32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForSInt32(8), pb::FieldCodec.ForSInt32(16), 42); - private readonly pbc::MapField mapSint32Sint32_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapSint32Sint32 { - get { return mapSint32Sint32_; } - } - - /// Field number for the "map_sint64_sint64" field. - public const int MapSint64Sint64FieldNumber = 6; - private static readonly pbc::MapField.Codec _map_mapSint64Sint64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForSInt64(8), pb::FieldCodec.ForSInt64(16), 50); - private readonly pbc::MapField mapSint64Sint64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapSint64Sint64 { - get { return mapSint64Sint64_; } - } - - /// Field number for the "map_fixed32_fixed32" field. - public const int MapFixed32Fixed32FieldNumber = 7; - private static readonly pbc::MapField.Codec _map_mapFixed32Fixed32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForFixed32(13), pb::FieldCodec.ForFixed32(21), 58); - private readonly pbc::MapField mapFixed32Fixed32_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapFixed32Fixed32 { - get { return mapFixed32Fixed32_; } - } - - /// Field number for the "map_fixed64_fixed64" field. - public const int MapFixed64Fixed64FieldNumber = 8; - private static readonly pbc::MapField.Codec _map_mapFixed64Fixed64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForFixed64(9), pb::FieldCodec.ForFixed64(17), 66); - private readonly pbc::MapField mapFixed64Fixed64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapFixed64Fixed64 { - get { return mapFixed64Fixed64_; } - } - - /// Field number for the "map_sfixed32_sfixed32" field. - public const int MapSfixed32Sfixed32FieldNumber = 9; - private static readonly pbc::MapField.Codec _map_mapSfixed32Sfixed32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForSFixed32(13), pb::FieldCodec.ForSFixed32(21), 74); - private readonly pbc::MapField mapSfixed32Sfixed32_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapSfixed32Sfixed32 { - get { return mapSfixed32Sfixed32_; } - } - - /// Field number for the "map_sfixed64_sfixed64" field. - public const int MapSfixed64Sfixed64FieldNumber = 10; - private static readonly pbc::MapField.Codec _map_mapSfixed64Sfixed64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForSFixed64(9), pb::FieldCodec.ForSFixed64(17), 82); - private readonly pbc::MapField mapSfixed64Sfixed64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapSfixed64Sfixed64 { - get { return mapSfixed64Sfixed64_; } - } - - /// Field number for the "map_int32_float" field. - public const int MapInt32FloatFieldNumber = 11; - private static readonly pbc::MapField.Codec _map_mapInt32Float_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForFloat(21), 90); - private readonly pbc::MapField mapInt32Float_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32Float { - get { return mapInt32Float_; } - } - - /// Field number for the "map_int32_double" field. - public const int MapInt32DoubleFieldNumber = 12; - private static readonly pbc::MapField.Codec _map_mapInt32Double_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForDouble(17), 98); - private readonly pbc::MapField mapInt32Double_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32Double { - get { return mapInt32Double_; } - } - - /// Field number for the "map_bool_bool" field. - public const int MapBoolBoolFieldNumber = 13; - private static readonly pbc::MapField.Codec _map_mapBoolBool_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForBool(8), pb::FieldCodec.ForBool(16), 106); - private readonly pbc::MapField mapBoolBool_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapBoolBool { - get { return mapBoolBool_; } - } - - /// Field number for the "map_string_string" field. - public const int MapStringStringFieldNumber = 14; - private static readonly pbc::MapField.Codec _map_mapStringString_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForString(18), 114); - private readonly pbc::MapField mapStringString_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapStringString { - get { return mapStringString_; } - } - - /// Field number for the "map_int32_bytes" field. - public const int MapInt32BytesFieldNumber = 15; - private static readonly pbc::MapField.Codec _map_mapInt32Bytes_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForBytes(18), 122); - private readonly pbc::MapField mapInt32Bytes_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32Bytes { - get { return mapInt32Bytes_; } - } - - /// Field number for the "map_int32_enum" field. - public const int MapInt32EnumFieldNumber = 16; - private static readonly pbc::MapField.Codec _map_mapInt32Enum_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Google.Protobuf.TestProtos.MapEnum) x), 130); - private readonly pbc::MapField mapInt32Enum_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32Enum { - get { return mapInt32Enum_; } - } - - /// Field number for the "map_int32_foreign_message" field. - public const int MapInt32ForeignMessageFieldNumber = 17; - private static readonly pbc::MapField.Codec _map_mapInt32ForeignMessage_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.ForeignMessage.Parser), 138); - private readonly pbc::MapField mapInt32ForeignMessage_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32ForeignMessage { - get { return mapInt32ForeignMessage_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestMap); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestMap other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!MapInt32Int32.Equals(other.MapInt32Int32)) return false; - if (!MapInt64Int64.Equals(other.MapInt64Int64)) return false; - if (!MapUint32Uint32.Equals(other.MapUint32Uint32)) return false; - if (!MapUint64Uint64.Equals(other.MapUint64Uint64)) return false; - if (!MapSint32Sint32.Equals(other.MapSint32Sint32)) return false; - if (!MapSint64Sint64.Equals(other.MapSint64Sint64)) return false; - if (!MapFixed32Fixed32.Equals(other.MapFixed32Fixed32)) return false; - if (!MapFixed64Fixed64.Equals(other.MapFixed64Fixed64)) return false; - if (!MapSfixed32Sfixed32.Equals(other.MapSfixed32Sfixed32)) return false; - if (!MapSfixed64Sfixed64.Equals(other.MapSfixed64Sfixed64)) return false; - if (!MapInt32Float.Equals(other.MapInt32Float)) return false; - if (!MapInt32Double.Equals(other.MapInt32Double)) return false; - if (!MapBoolBool.Equals(other.MapBoolBool)) return false; - if (!MapStringString.Equals(other.MapStringString)) return false; - if (!MapInt32Bytes.Equals(other.MapInt32Bytes)) return false; - if (!MapInt32Enum.Equals(other.MapInt32Enum)) return false; - if (!MapInt32ForeignMessage.Equals(other.MapInt32ForeignMessage)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - hash ^= MapInt32Int32.GetHashCode(); - hash ^= MapInt64Int64.GetHashCode(); - hash ^= MapUint32Uint32.GetHashCode(); - hash ^= MapUint64Uint64.GetHashCode(); - hash ^= MapSint32Sint32.GetHashCode(); - hash ^= MapSint64Sint64.GetHashCode(); - hash ^= MapFixed32Fixed32.GetHashCode(); - hash ^= MapFixed64Fixed64.GetHashCode(); - hash ^= MapSfixed32Sfixed32.GetHashCode(); - hash ^= MapSfixed64Sfixed64.GetHashCode(); - hash ^= MapInt32Float.GetHashCode(); - hash ^= MapInt32Double.GetHashCode(); - hash ^= MapBoolBool.GetHashCode(); - hash ^= MapStringString.GetHashCode(); - hash ^= MapInt32Bytes.GetHashCode(); - hash ^= MapInt32Enum.GetHashCode(); - hash ^= MapInt32ForeignMessage.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec); - mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec); - mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec); - mapUint64Uint64_.WriteTo(output, _map_mapUint64Uint64_codec); - mapSint32Sint32_.WriteTo(output, _map_mapSint32Sint32_codec); - mapSint64Sint64_.WriteTo(output, _map_mapSint64Sint64_codec); - mapFixed32Fixed32_.WriteTo(output, _map_mapFixed32Fixed32_codec); - mapFixed64Fixed64_.WriteTo(output, _map_mapFixed64Fixed64_codec); - mapSfixed32Sfixed32_.WriteTo(output, _map_mapSfixed32Sfixed32_codec); - mapSfixed64Sfixed64_.WriteTo(output, _map_mapSfixed64Sfixed64_codec); - mapInt32Float_.WriteTo(output, _map_mapInt32Float_codec); - mapInt32Double_.WriteTo(output, _map_mapInt32Double_codec); - mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec); - mapStringString_.WriteTo(output, _map_mapStringString_codec); - mapInt32Bytes_.WriteTo(output, _map_mapInt32Bytes_codec); - mapInt32Enum_.WriteTo(output, _map_mapInt32Enum_codec); - mapInt32ForeignMessage_.WriteTo(output, _map_mapInt32ForeignMessage_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec); - size += mapInt64Int64_.CalculateSize(_map_mapInt64Int64_codec); - size += mapUint32Uint32_.CalculateSize(_map_mapUint32Uint32_codec); - size += mapUint64Uint64_.CalculateSize(_map_mapUint64Uint64_codec); - size += mapSint32Sint32_.CalculateSize(_map_mapSint32Sint32_codec); - size += mapSint64Sint64_.CalculateSize(_map_mapSint64Sint64_codec); - size += mapFixed32Fixed32_.CalculateSize(_map_mapFixed32Fixed32_codec); - size += mapFixed64Fixed64_.CalculateSize(_map_mapFixed64Fixed64_codec); - size += mapSfixed32Sfixed32_.CalculateSize(_map_mapSfixed32Sfixed32_codec); - size += mapSfixed64Sfixed64_.CalculateSize(_map_mapSfixed64Sfixed64_codec); - size += mapInt32Float_.CalculateSize(_map_mapInt32Float_codec); - size += mapInt32Double_.CalculateSize(_map_mapInt32Double_codec); - size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec); - size += mapStringString_.CalculateSize(_map_mapStringString_codec); - size += mapInt32Bytes_.CalculateSize(_map_mapInt32Bytes_codec); - size += mapInt32Enum_.CalculateSize(_map_mapInt32Enum_codec); - size += mapInt32ForeignMessage_.CalculateSize(_map_mapInt32ForeignMessage_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestMap other) { - if (other == null) { - return; - } - mapInt32Int32_.Add(other.mapInt32Int32_); - mapInt64Int64_.Add(other.mapInt64Int64_); - mapUint32Uint32_.Add(other.mapUint32Uint32_); - mapUint64Uint64_.Add(other.mapUint64Uint64_); - mapSint32Sint32_.Add(other.mapSint32Sint32_); - mapSint64Sint64_.Add(other.mapSint64Sint64_); - mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_); - mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_); - mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_); - mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_); - mapInt32Float_.Add(other.mapInt32Float_); - mapInt32Double_.Add(other.mapInt32Double_); - mapBoolBool_.Add(other.mapBoolBool_); - mapStringString_.Add(other.mapStringString_); - mapInt32Bytes_.Add(other.mapInt32Bytes_); - mapInt32Enum_.Add(other.mapInt32Enum_); - mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec); - break; - } - case 18: { - mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec); - break; - } - case 26: { - mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec); - break; - } - case 34: { - mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec); - break; - } - case 42: { - mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec); - break; - } - case 50: { - mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec); - break; - } - case 58: { - mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec); - break; - } - case 66: { - mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec); - break; - } - case 74: { - mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec); - break; - } - case 82: { - mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec); - break; - } - case 90: { - mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec); - break; - } - case 98: { - mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec); - break; - } - case 106: { - mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec); - break; - } - case 114: { - mapStringString_.AddEntriesFrom(input, _map_mapStringString_codec); - break; - } - case 122: { - mapInt32Bytes_.AddEntriesFrom(input, _map_mapInt32Bytes_codec); - break; - } - case 130: { - mapInt32Enum_.AddEntriesFrom(input, _map_mapInt32Enum_codec); - break; - } - case 138: { - mapInt32ForeignMessage_.AddEntriesFrom(input, _map_mapInt32ForeignMessage_codec); - break; - } - } - } - } - - } - - public sealed partial class TestMapSubmessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMapSubmessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[1]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMapSubmessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMapSubmessage(TestMapSubmessage other) : this() { - TestMap = other.testMap_ != null ? other.TestMap.Clone() : null; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMapSubmessage Clone() { - return new TestMapSubmessage(this); - } - - /// Field number for the "test_map" field. - public const int TestMapFieldNumber = 1; - private global::Google.Protobuf.TestProtos.TestMap testMap_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.TestMap TestMap { - get { return testMap_; } - set { - testMap_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestMapSubmessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestMapSubmessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!object.Equals(TestMap, other.TestMap)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (testMap_ != null) hash ^= TestMap.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (testMap_ != null) { - output.WriteRawTag(10); - output.WriteMessage(TestMap); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (testMap_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(TestMap); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestMapSubmessage other) { - if (other == null) { - return; - } - if (other.testMap_ != null) { - if (testMap_ == null) { - testMap_ = new global::Google.Protobuf.TestProtos.TestMap(); - } - TestMap.MergeFrom(other.TestMap); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - if (testMap_ == null) { - testMap_ = new global::Google.Protobuf.TestProtos.TestMap(); - } - input.ReadMessage(testMap_); - break; - } - } - } - } - - } - - public sealed partial class TestMessageMap : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMessageMap()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[2]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMessageMap() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMessageMap(TestMessageMap other) : this() { - mapInt32Message_ = other.mapInt32Message_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMessageMap Clone() { - return new TestMessageMap(this); - } - - /// Field number for the "map_int32_message" field. - public const int MapInt32MessageFieldNumber = 1; - private static readonly pbc::MapField.Codec _map_mapInt32Message_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.TestAllTypes.Parser), 10); - private readonly pbc::MapField mapInt32Message_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32Message { - get { return mapInt32Message_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestMessageMap); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestMessageMap other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!MapInt32Message.Equals(other.MapInt32Message)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - hash ^= MapInt32Message.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - mapInt32Message_.WriteTo(output, _map_mapInt32Message_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - size += mapInt32Message_.CalculateSize(_map_mapInt32Message_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestMessageMap other) { - if (other == null) { - return; - } - mapInt32Message_.Add(other.mapInt32Message_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - mapInt32Message_.AddEntriesFrom(input, _map_mapInt32Message_codec); - break; - } - } - } - } - - } - - /// - /// Two map fields share the same entry default instance. - /// - public sealed partial class TestSameTypeMap : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestSameTypeMap()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[3]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestSameTypeMap() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestSameTypeMap(TestSameTypeMap other) : this() { - map1_ = other.map1_.Clone(); - map2_ = other.map2_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestSameTypeMap Clone() { - return new TestSameTypeMap(this); - } - - /// Field number for the "map1" field. - public const int Map1FieldNumber = 1; - private static readonly pbc::MapField.Codec _map_map1_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 10); - private readonly pbc::MapField map1_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField Map1 { - get { return map1_; } - } - - /// Field number for the "map2" field. - public const int Map2FieldNumber = 2; - private static readonly pbc::MapField.Codec _map_map2_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 18); - private readonly pbc::MapField map2_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField Map2 { - get { return map2_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestSameTypeMap); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestSameTypeMap other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!Map1.Equals(other.Map1)) return false; - if (!Map2.Equals(other.Map2)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - hash ^= Map1.GetHashCode(); - hash ^= Map2.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - map1_.WriteTo(output, _map_map1_codec); - map2_.WriteTo(output, _map_map2_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - size += map1_.CalculateSize(_map_map1_codec); - size += map2_.CalculateSize(_map_map2_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestSameTypeMap other) { - if (other == null) { - return; - } - map1_.Add(other.map1_); - map2_.Add(other.map2_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - map1_.AddEntriesFrom(input, _map_map1_codec); - break; - } - case 18: { - map2_.AddEntriesFrom(input, _map_map2_codec); - break; - } - } - } - } - - } - - public sealed partial class TestArenaMap : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestArenaMap()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[4]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestArenaMap() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestArenaMap(TestArenaMap other) : this() { - mapInt32Int32_ = other.mapInt32Int32_.Clone(); - mapInt64Int64_ = other.mapInt64Int64_.Clone(); - mapUint32Uint32_ = other.mapUint32Uint32_.Clone(); - mapUint64Uint64_ = other.mapUint64Uint64_.Clone(); - mapSint32Sint32_ = other.mapSint32Sint32_.Clone(); - mapSint64Sint64_ = other.mapSint64Sint64_.Clone(); - mapFixed32Fixed32_ = other.mapFixed32Fixed32_.Clone(); - mapFixed64Fixed64_ = other.mapFixed64Fixed64_.Clone(); - mapSfixed32Sfixed32_ = other.mapSfixed32Sfixed32_.Clone(); - mapSfixed64Sfixed64_ = other.mapSfixed64Sfixed64_.Clone(); - mapInt32Float_ = other.mapInt32Float_.Clone(); - mapInt32Double_ = other.mapInt32Double_.Clone(); - mapBoolBool_ = other.mapBoolBool_.Clone(); - mapInt32Enum_ = other.mapInt32Enum_.Clone(); - mapInt32ForeignMessage_ = other.mapInt32ForeignMessage_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestArenaMap Clone() { - return new TestArenaMap(this); - } - - /// Field number for the "map_int32_int32" field. - public const int MapInt32Int32FieldNumber = 1; - private static readonly pbc::MapField.Codec _map_mapInt32Int32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 10); - private readonly pbc::MapField mapInt32Int32_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32Int32 { - get { return mapInt32Int32_; } - } - - /// Field number for the "map_int64_int64" field. - public const int MapInt64Int64FieldNumber = 2; - private static readonly pbc::MapField.Codec _map_mapInt64Int64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt64(8), pb::FieldCodec.ForInt64(16), 18); - private readonly pbc::MapField mapInt64Int64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt64Int64 { - get { return mapInt64Int64_; } - } - - /// Field number for the "map_uint32_uint32" field. - public const int MapUint32Uint32FieldNumber = 3; - private static readonly pbc::MapField.Codec _map_mapUint32Uint32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForUInt32(8), pb::FieldCodec.ForUInt32(16), 26); - private readonly pbc::MapField mapUint32Uint32_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapUint32Uint32 { - get { return mapUint32Uint32_; } - } - - /// Field number for the "map_uint64_uint64" field. - public const int MapUint64Uint64FieldNumber = 4; - private static readonly pbc::MapField.Codec _map_mapUint64Uint64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForUInt64(8), pb::FieldCodec.ForUInt64(16), 34); - private readonly pbc::MapField mapUint64Uint64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapUint64Uint64 { - get { return mapUint64Uint64_; } - } - - /// Field number for the "map_sint32_sint32" field. - public const int MapSint32Sint32FieldNumber = 5; - private static readonly pbc::MapField.Codec _map_mapSint32Sint32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForSInt32(8), pb::FieldCodec.ForSInt32(16), 42); - private readonly pbc::MapField mapSint32Sint32_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapSint32Sint32 { - get { return mapSint32Sint32_; } - } - - /// Field number for the "map_sint64_sint64" field. - public const int MapSint64Sint64FieldNumber = 6; - private static readonly pbc::MapField.Codec _map_mapSint64Sint64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForSInt64(8), pb::FieldCodec.ForSInt64(16), 50); - private readonly pbc::MapField mapSint64Sint64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapSint64Sint64 { - get { return mapSint64Sint64_; } - } - - /// Field number for the "map_fixed32_fixed32" field. - public const int MapFixed32Fixed32FieldNumber = 7; - private static readonly pbc::MapField.Codec _map_mapFixed32Fixed32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForFixed32(13), pb::FieldCodec.ForFixed32(21), 58); - private readonly pbc::MapField mapFixed32Fixed32_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapFixed32Fixed32 { - get { return mapFixed32Fixed32_; } - } - - /// Field number for the "map_fixed64_fixed64" field. - public const int MapFixed64Fixed64FieldNumber = 8; - private static readonly pbc::MapField.Codec _map_mapFixed64Fixed64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForFixed64(9), pb::FieldCodec.ForFixed64(17), 66); - private readonly pbc::MapField mapFixed64Fixed64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapFixed64Fixed64 { - get { return mapFixed64Fixed64_; } - } - - /// Field number for the "map_sfixed32_sfixed32" field. - public const int MapSfixed32Sfixed32FieldNumber = 9; - private static readonly pbc::MapField.Codec _map_mapSfixed32Sfixed32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForSFixed32(13), pb::FieldCodec.ForSFixed32(21), 74); - private readonly pbc::MapField mapSfixed32Sfixed32_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapSfixed32Sfixed32 { - get { return mapSfixed32Sfixed32_; } - } - - /// Field number for the "map_sfixed64_sfixed64" field. - public const int MapSfixed64Sfixed64FieldNumber = 10; - private static readonly pbc::MapField.Codec _map_mapSfixed64Sfixed64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForSFixed64(9), pb::FieldCodec.ForSFixed64(17), 82); - private readonly pbc::MapField mapSfixed64Sfixed64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapSfixed64Sfixed64 { - get { return mapSfixed64Sfixed64_; } - } - - /// Field number for the "map_int32_float" field. - public const int MapInt32FloatFieldNumber = 11; - private static readonly pbc::MapField.Codec _map_mapInt32Float_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForFloat(21), 90); - private readonly pbc::MapField mapInt32Float_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32Float { - get { return mapInt32Float_; } - } - - /// Field number for the "map_int32_double" field. - public const int MapInt32DoubleFieldNumber = 12; - private static readonly pbc::MapField.Codec _map_mapInt32Double_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForDouble(17), 98); - private readonly pbc::MapField mapInt32Double_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32Double { - get { return mapInt32Double_; } - } - - /// Field number for the "map_bool_bool" field. - public const int MapBoolBoolFieldNumber = 13; - private static readonly pbc::MapField.Codec _map_mapBoolBool_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForBool(8), pb::FieldCodec.ForBool(16), 106); - private readonly pbc::MapField mapBoolBool_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapBoolBool { - get { return mapBoolBool_; } - } - - /// Field number for the "map_int32_enum" field. - public const int MapInt32EnumFieldNumber = 14; - private static readonly pbc::MapField.Codec _map_mapInt32Enum_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Google.Protobuf.TestProtos.MapEnum) x), 114); - private readonly pbc::MapField mapInt32Enum_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32Enum { - get { return mapInt32Enum_; } - } - - /// Field number for the "map_int32_foreign_message" field. - public const int MapInt32ForeignMessageFieldNumber = 15; - private static readonly pbc::MapField.Codec _map_mapInt32ForeignMessage_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.ForeignMessage.Parser), 122); - private readonly pbc::MapField mapInt32ForeignMessage_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32ForeignMessage { - get { return mapInt32ForeignMessage_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestArenaMap); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestArenaMap other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!MapInt32Int32.Equals(other.MapInt32Int32)) return false; - if (!MapInt64Int64.Equals(other.MapInt64Int64)) return false; - if (!MapUint32Uint32.Equals(other.MapUint32Uint32)) return false; - if (!MapUint64Uint64.Equals(other.MapUint64Uint64)) return false; - if (!MapSint32Sint32.Equals(other.MapSint32Sint32)) return false; - if (!MapSint64Sint64.Equals(other.MapSint64Sint64)) return false; - if (!MapFixed32Fixed32.Equals(other.MapFixed32Fixed32)) return false; - if (!MapFixed64Fixed64.Equals(other.MapFixed64Fixed64)) return false; - if (!MapSfixed32Sfixed32.Equals(other.MapSfixed32Sfixed32)) return false; - if (!MapSfixed64Sfixed64.Equals(other.MapSfixed64Sfixed64)) return false; - if (!MapInt32Float.Equals(other.MapInt32Float)) return false; - if (!MapInt32Double.Equals(other.MapInt32Double)) return false; - if (!MapBoolBool.Equals(other.MapBoolBool)) return false; - if (!MapInt32Enum.Equals(other.MapInt32Enum)) return false; - if (!MapInt32ForeignMessage.Equals(other.MapInt32ForeignMessage)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - hash ^= MapInt32Int32.GetHashCode(); - hash ^= MapInt64Int64.GetHashCode(); - hash ^= MapUint32Uint32.GetHashCode(); - hash ^= MapUint64Uint64.GetHashCode(); - hash ^= MapSint32Sint32.GetHashCode(); - hash ^= MapSint64Sint64.GetHashCode(); - hash ^= MapFixed32Fixed32.GetHashCode(); - hash ^= MapFixed64Fixed64.GetHashCode(); - hash ^= MapSfixed32Sfixed32.GetHashCode(); - hash ^= MapSfixed64Sfixed64.GetHashCode(); - hash ^= MapInt32Float.GetHashCode(); - hash ^= MapInt32Double.GetHashCode(); - hash ^= MapBoolBool.GetHashCode(); - hash ^= MapInt32Enum.GetHashCode(); - hash ^= MapInt32ForeignMessage.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec); - mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec); - mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec); - mapUint64Uint64_.WriteTo(output, _map_mapUint64Uint64_codec); - mapSint32Sint32_.WriteTo(output, _map_mapSint32Sint32_codec); - mapSint64Sint64_.WriteTo(output, _map_mapSint64Sint64_codec); - mapFixed32Fixed32_.WriteTo(output, _map_mapFixed32Fixed32_codec); - mapFixed64Fixed64_.WriteTo(output, _map_mapFixed64Fixed64_codec); - mapSfixed32Sfixed32_.WriteTo(output, _map_mapSfixed32Sfixed32_codec); - mapSfixed64Sfixed64_.WriteTo(output, _map_mapSfixed64Sfixed64_codec); - mapInt32Float_.WriteTo(output, _map_mapInt32Float_codec); - mapInt32Double_.WriteTo(output, _map_mapInt32Double_codec); - mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec); - mapInt32Enum_.WriteTo(output, _map_mapInt32Enum_codec); - mapInt32ForeignMessage_.WriteTo(output, _map_mapInt32ForeignMessage_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec); - size += mapInt64Int64_.CalculateSize(_map_mapInt64Int64_codec); - size += mapUint32Uint32_.CalculateSize(_map_mapUint32Uint32_codec); - size += mapUint64Uint64_.CalculateSize(_map_mapUint64Uint64_codec); - size += mapSint32Sint32_.CalculateSize(_map_mapSint32Sint32_codec); - size += mapSint64Sint64_.CalculateSize(_map_mapSint64Sint64_codec); - size += mapFixed32Fixed32_.CalculateSize(_map_mapFixed32Fixed32_codec); - size += mapFixed64Fixed64_.CalculateSize(_map_mapFixed64Fixed64_codec); - size += mapSfixed32Sfixed32_.CalculateSize(_map_mapSfixed32Sfixed32_codec); - size += mapSfixed64Sfixed64_.CalculateSize(_map_mapSfixed64Sfixed64_codec); - size += mapInt32Float_.CalculateSize(_map_mapInt32Float_codec); - size += mapInt32Double_.CalculateSize(_map_mapInt32Double_codec); - size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec); - size += mapInt32Enum_.CalculateSize(_map_mapInt32Enum_codec); - size += mapInt32ForeignMessage_.CalculateSize(_map_mapInt32ForeignMessage_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestArenaMap other) { - if (other == null) { - return; - } - mapInt32Int32_.Add(other.mapInt32Int32_); - mapInt64Int64_.Add(other.mapInt64Int64_); - mapUint32Uint32_.Add(other.mapUint32Uint32_); - mapUint64Uint64_.Add(other.mapUint64Uint64_); - mapSint32Sint32_.Add(other.mapSint32Sint32_); - mapSint64Sint64_.Add(other.mapSint64Sint64_); - mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_); - mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_); - mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_); - mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_); - mapInt32Float_.Add(other.mapInt32Float_); - mapInt32Double_.Add(other.mapInt32Double_); - mapBoolBool_.Add(other.mapBoolBool_); - mapInt32Enum_.Add(other.mapInt32Enum_); - mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec); - break; - } - case 18: { - mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec); - break; - } - case 26: { - mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec); - break; - } - case 34: { - mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec); - break; - } - case 42: { - mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec); - break; - } - case 50: { - mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec); - break; - } - case 58: { - mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec); - break; - } - case 66: { - mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec); - break; - } - case 74: { - mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec); - break; - } - case 82: { - mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec); - break; - } - case 90: { - mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec); - break; - } - case 98: { - mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec); - break; - } - case 106: { - mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec); - break; - } - case 114: { - mapInt32Enum_.AddEntriesFrom(input, _map_mapInt32Enum_codec); - break; - } - case 122: { - mapInt32ForeignMessage_.AddEntriesFrom(input, _map_mapInt32ForeignMessage_codec); - break; - } - } - } - } - - } - - /// - /// Previously, message containing enum called Type cannot be used as value of - /// map field. - /// - public sealed partial class MessageContainingEnumCalledType : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageContainingEnumCalledType()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[5]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public MessageContainingEnumCalledType() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public MessageContainingEnumCalledType(MessageContainingEnumCalledType other) : this() { - type_ = other.type_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public MessageContainingEnumCalledType Clone() { - return new MessageContainingEnumCalledType(this); - } - - /// Field number for the "type" field. - public const int TypeFieldNumber = 1; - private static readonly pbc::MapField.Codec _map_type_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Parser), 10); - private readonly pbc::MapField type_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField Type { - get { return type_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as MessageContainingEnumCalledType); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(MessageContainingEnumCalledType other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!Type.Equals(other.Type)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - hash ^= Type.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - type_.WriteTo(output, _map_type_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - size += type_.CalculateSize(_map_type_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(MessageContainingEnumCalledType other) { - if (other == null) { - return; - } - type_.Add(other.type_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - type_.AddEntriesFrom(input, _map_type_codec); - break; - } - } - } - } - - #region Nested types - /// Container for nested types declared in the MessageContainingEnumCalledType message type. - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static partial class Types { - public enum Type { - [pbr::OriginalName("TYPE_FOO")] Foo = 0, - } - - } - #endregion - - } - - /// - /// Previously, message cannot contain map field called "entry". - /// - public sealed partial class MessageContainingMapCalledEntry : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageContainingMapCalledEntry()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.MapUnittestProto3Reflection.Descriptor.MessageTypes[6]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public MessageContainingMapCalledEntry() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public MessageContainingMapCalledEntry(MessageContainingMapCalledEntry other) : this() { - entry_ = other.entry_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public MessageContainingMapCalledEntry Clone() { - return new MessageContainingMapCalledEntry(this); - } - - /// Field number for the "entry" field. - public const int EntryFieldNumber = 1; - private static readonly pbc::MapField.Codec _map_entry_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 10); - private readonly pbc::MapField entry_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField Entry { - get { return entry_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as MessageContainingMapCalledEntry); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(MessageContainingMapCalledEntry other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!Entry.Equals(other.Entry)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - hash ^= Entry.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - entry_.WriteTo(output, _map_entry_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - size += entry_.CalculateSize(_map_entry_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(MessageContainingMapCalledEntry other) { - if (other == null) { - return; - } - entry_.Add(other.entry_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - entry_.AddEntriesFrom(input, _map_entry_codec); - break; - } - } - } - } - - } - - #endregion - -} - -#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs deleted file mode 100644 index 6607be7a1d723..0000000000000 --- a/csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs +++ /dev/null @@ -1,3692 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/test_messages_proto3.proto -#pragma warning disable 1591, 0612, 3021 -#region Designer generated code - -using pb = global::Google.Protobuf; -using pbc = global::Google.Protobuf.Collections; -using pbr = global::Google.Protobuf.Reflection; -using scg = global::System.Collections.Generic; -namespace ProtobufTestMessages.Proto3 { - - /// Holder for reflection information generated from google/protobuf/test_messages_proto3.proto - public static partial class TestMessagesProto3Reflection { - - #region Descriptor - /// File descriptor for google/protobuf/test_messages_proto3.proto - public static pbr::FileDescriptor Descriptor { - get { return descriptor; } - } - private static pbr::FileDescriptor descriptor; - - static TestMessagesProto3Reflection() { - byte[] descriptorData = global::System.Convert.FromBase64String( - string.Concat( - "Cipnb29nbGUvcHJvdG9idWYvdGVzdF9tZXNzYWdlc19wcm90bzMucHJvdG8S", - "HXByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zGhlnb29nbGUvcHJvdG9i", - "dWYvYW55LnByb3RvGh5nb29nbGUvcHJvdG9idWYvZHVyYXRpb24ucHJvdG8a", - "IGdvb2dsZS9wcm90b2J1Zi9maWVsZF9tYXNrLnByb3RvGhxnb29nbGUvcHJv", - "dG9idWYvc3RydWN0LnByb3RvGh9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1w", - "LnByb3RvGh5nb29nbGUvcHJvdG9idWYvd3JhcHBlcnMucHJvdG8irDsKElRl", - "c3RBbGxUeXBlc1Byb3RvMxIWCg5vcHRpb25hbF9pbnQzMhgBIAEoBRIWCg5v", - "cHRpb25hbF9pbnQ2NBgCIAEoAxIXCg9vcHRpb25hbF91aW50MzIYAyABKA0S", - "FwoPb3B0aW9uYWxfdWludDY0GAQgASgEEhcKD29wdGlvbmFsX3NpbnQzMhgF", - "IAEoERIXCg9vcHRpb25hbF9zaW50NjQYBiABKBISGAoQb3B0aW9uYWxfZml4", - "ZWQzMhgHIAEoBxIYChBvcHRpb25hbF9maXhlZDY0GAggASgGEhkKEW9wdGlv", - "bmFsX3NmaXhlZDMyGAkgASgPEhkKEW9wdGlvbmFsX3NmaXhlZDY0GAogASgQ", - "EhYKDm9wdGlvbmFsX2Zsb2F0GAsgASgCEhcKD29wdGlvbmFsX2RvdWJsZRgM", - "IAEoARIVCg1vcHRpb25hbF9ib29sGA0gASgIEhcKD29wdGlvbmFsX3N0cmlu", - "ZxgOIAEoCRIWCg5vcHRpb25hbF9ieXRlcxgPIAEoDBJgChdvcHRpb25hbF9u", - "ZXN0ZWRfbWVzc2FnZRgSIAEoCzI/LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMu", - "cHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5OZXN0ZWRNZXNzYWdlEk8KGG9w", - "dGlvbmFsX2ZvcmVpZ25fbWVzc2FnZRgTIAEoCzItLnByb3RvYnVmX3Rlc3Rf", - "bWVzc2FnZXMucHJvdG8zLkZvcmVpZ25NZXNzYWdlEloKFG9wdGlvbmFsX25l", - "c3RlZF9lbnVtGBUgASgOMjwucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90", - "bzMuVGVzdEFsbFR5cGVzUHJvdG8zLk5lc3RlZEVudW0SSQoVb3B0aW9uYWxf", - "Zm9yZWlnbl9lbnVtGBYgASgOMioucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5w", - "cm90bzMuRm9yZWlnbkVudW0SIQoVb3B0aW9uYWxfc3RyaW5nX3BpZWNlGBgg", - "ASgJQgIIAhIZCg1vcHRpb25hbF9jb3JkGBkgASgJQgIIARJMChFyZWN1cnNp", - "dmVfbWVzc2FnZRgbIAEoCzIxLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJv", - "dG8zLlRlc3RBbGxUeXBlc1Byb3RvMxIWCg5yZXBlYXRlZF9pbnQzMhgfIAMo", - "BRIWCg5yZXBlYXRlZF9pbnQ2NBggIAMoAxIXCg9yZXBlYXRlZF91aW50MzIY", - "ISADKA0SFwoPcmVwZWF0ZWRfdWludDY0GCIgAygEEhcKD3JlcGVhdGVkX3Np", - "bnQzMhgjIAMoERIXCg9yZXBlYXRlZF9zaW50NjQYJCADKBISGAoQcmVwZWF0", - "ZWRfZml4ZWQzMhglIAMoBxIYChByZXBlYXRlZF9maXhlZDY0GCYgAygGEhkK", - "EXJlcGVhdGVkX3NmaXhlZDMyGCcgAygPEhkKEXJlcGVhdGVkX3NmaXhlZDY0", - "GCggAygQEhYKDnJlcGVhdGVkX2Zsb2F0GCkgAygCEhcKD3JlcGVhdGVkX2Rv", - "dWJsZRgqIAMoARIVCg1yZXBlYXRlZF9ib29sGCsgAygIEhcKD3JlcGVhdGVk", - "X3N0cmluZxgsIAMoCRIWCg5yZXBlYXRlZF9ieXRlcxgtIAMoDBJgChdyZXBl", - "YXRlZF9uZXN0ZWRfbWVzc2FnZRgwIAMoCzI/LnByb3RvYnVmX3Rlc3RfbWVz", - "c2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5OZXN0ZWRNZXNzYWdl", - "Ek8KGHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZRgxIAMoCzItLnByb3RvYnVm", - "X3Rlc3RfbWVzc2FnZXMucHJvdG8zLkZvcmVpZ25NZXNzYWdlEloKFHJlcGVh", - "dGVkX25lc3RlZF9lbnVtGDMgAygOMjwucHJvdG9idWZfdGVzdF9tZXNzYWdl", - "cy5wcm90bzMuVGVzdEFsbFR5cGVzUHJvdG8zLk5lc3RlZEVudW0SSQoVcmVw", - "ZWF0ZWRfZm9yZWlnbl9lbnVtGDQgAygOMioucHJvdG9idWZfdGVzdF9tZXNz", - "YWdlcy5wcm90bzMuRm9yZWlnbkVudW0SIQoVcmVwZWF0ZWRfc3RyaW5nX3Bp", - "ZWNlGDYgAygJQgIIAhIZCg1yZXBlYXRlZF9jb3JkGDcgAygJQgIIARJdCg9t", - "YXBfaW50MzJfaW50MzIYOCADKAsyRC5wcm90b2J1Zl90ZXN0X21lc3NhZ2Vz", - "LnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTWFwSW50MzJJbnQzMkVudHJ5", - "El0KD21hcF9pbnQ2NF9pbnQ2NBg5IAMoCzJELnByb3RvYnVmX3Rlc3RfbWVz", - "c2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5NYXBJbnQ2NEludDY0", - "RW50cnkSYQoRbWFwX3VpbnQzMl91aW50MzIYOiADKAsyRi5wcm90b2J1Zl90", - "ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTWFwVWlu", - "dDMyVWludDMyRW50cnkSYQoRbWFwX3VpbnQ2NF91aW50NjQYOyADKAsyRi5w", - "cm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90", - "bzMuTWFwVWludDY0VWludDY0RW50cnkSYQoRbWFwX3NpbnQzMl9zaW50MzIY", - "PCADKAsyRi5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxs", - "VHlwZXNQcm90bzMuTWFwU2ludDMyU2ludDMyRW50cnkSYQoRbWFwX3NpbnQ2", - "NF9zaW50NjQYPSADKAsyRi5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3Rv", - "My5UZXN0QWxsVHlwZXNQcm90bzMuTWFwU2ludDY0U2ludDY0RW50cnkSZQoT", - "bWFwX2ZpeGVkMzJfZml4ZWQzMhg+IAMoCzJILnByb3RvYnVmX3Rlc3RfbWVz", - "c2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5NYXBGaXhlZDMyRml4", - "ZWQzMkVudHJ5EmUKE21hcF9maXhlZDY0X2ZpeGVkNjQYPyADKAsySC5wcm90", - "b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMu", - "TWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRJpChVtYXBfc2ZpeGVkMzJfc2ZpeGVk", - "MzIYQCADKAsySi5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0", - "QWxsVHlwZXNQcm90bzMuTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5EmkKFW1h", - "cF9zZml4ZWQ2NF9zZml4ZWQ2NBhBIAMoCzJKLnByb3RvYnVmX3Rlc3RfbWVz", - "c2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5NYXBTZml4ZWQ2NFNm", - "aXhlZDY0RW50cnkSXQoPbWFwX2ludDMyX2Zsb2F0GEIgAygLMkQucHJvdG9i", - "dWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzUHJvdG8zLk1h", - "cEludDMyRmxvYXRFbnRyeRJfChBtYXBfaW50MzJfZG91YmxlGEMgAygLMkUu", - "cHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzUHJv", - "dG8zLk1hcEludDMyRG91YmxlRW50cnkSWQoNbWFwX2Jvb2xfYm9vbBhEIAMo", - "CzJCLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBl", - "c1Byb3RvMy5NYXBCb29sQm9vbEVudHJ5EmEKEW1hcF9zdHJpbmdfc3RyaW5n", - "GEUgAygLMkYucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFs", - "bFR5cGVzUHJvdG8zLk1hcFN0cmluZ1N0cmluZ0VudHJ5El8KEG1hcF9zdHJp", - "bmdfYnl0ZXMYRiADKAsyRS5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3Rv", - "My5UZXN0QWxsVHlwZXNQcm90bzMuTWFwU3RyaW5nQnl0ZXNFbnRyeRJwChlt", - "YXBfc3RyaW5nX25lc3RlZF9tZXNzYWdlGEcgAygLMk0ucHJvdG9idWZfdGVz", - "dF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzUHJvdG8zLk1hcFN0cmlu", - "Z05lc3RlZE1lc3NhZ2VFbnRyeRJyChptYXBfc3RyaW5nX2ZvcmVpZ25fbWVz", - "c2FnZRhIIAMoCzJOLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRl", - "c3RBbGxUeXBlc1Byb3RvMy5NYXBTdHJpbmdGb3JlaWduTWVzc2FnZUVudHJ5", - "EmoKFm1hcF9zdHJpbmdfbmVzdGVkX2VudW0YSSADKAsySi5wcm90b2J1Zl90", - "ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTWFwU3Ry", - "aW5nTmVzdGVkRW51bUVudHJ5EmwKF21hcF9zdHJpbmdfZm9yZWlnbl9lbnVt", - "GEogAygLMksucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFs", - "bFR5cGVzUHJvdG8zLk1hcFN0cmluZ0ZvcmVpZ25FbnVtRW50cnkSFgoMb25l", - "b2ZfdWludDMyGG8gASgNSAASXwoUb25lb2ZfbmVzdGVkX21lc3NhZ2UYcCAB", - "KAsyPy5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlw", - "ZXNQcm90bzMuTmVzdGVkTWVzc2FnZUgAEhYKDG9uZW9mX3N0cmluZxhxIAEo", - "CUgAEhUKC29uZW9mX2J5dGVzGHIgASgMSAASFAoKb25lb2ZfYm9vbBhzIAEo", - "CEgAEhYKDG9uZW9mX3VpbnQ2NBh0IAEoBEgAEhUKC29uZW9mX2Zsb2F0GHUg", - "ASgCSAASFgoMb25lb2ZfZG91YmxlGHYgASgBSAASUgoKb25lb2ZfZW51bRh3", - "IAEoDjI8LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxU", - "eXBlc1Byb3RvMy5OZXN0ZWRFbnVtSAASOgoVb3B0aW9uYWxfYm9vbF93cmFw", - "cGVyGMkBIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5Cb29sVmFsdWUSPAoWb3B0", - "aW9uYWxfaW50MzJfd3JhcHBlchjKASABKAsyGy5nb29nbGUucHJvdG9idWYu", - "SW50MzJWYWx1ZRI8ChZvcHRpb25hbF9pbnQ2NF93cmFwcGVyGMsBIAEoCzIb", - "Lmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVlEj4KF29wdGlvbmFsX3VpbnQz", - "Ml93cmFwcGVyGMwBIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50MzJWYWx1", - "ZRI+ChdvcHRpb25hbF91aW50NjRfd3JhcHBlchjNASABKAsyHC5nb29nbGUu", - "cHJvdG9idWYuVUludDY0VmFsdWUSPAoWb3B0aW9uYWxfZmxvYXRfd3JhcHBl", - "chjOASABKAsyGy5nb29nbGUucHJvdG9idWYuRmxvYXRWYWx1ZRI+ChdvcHRp", - "b25hbF9kb3VibGVfd3JhcHBlchjPASABKAsyHC5nb29nbGUucHJvdG9idWYu", - "RG91YmxlVmFsdWUSPgoXb3B0aW9uYWxfc3RyaW5nX3dyYXBwZXIY0AEgASgL", - "MhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1ZhbHVlEjwKFm9wdGlvbmFsX2J5", - "dGVzX3dyYXBwZXIY0QEgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkJ5dGVzVmFs", - "dWUSOgoVcmVwZWF0ZWRfYm9vbF93cmFwcGVyGNMBIAMoCzIaLmdvb2dsZS5w", - "cm90b2J1Zi5Cb29sVmFsdWUSPAoWcmVwZWF0ZWRfaW50MzJfd3JhcHBlchjU", - "ASADKAsyGy5nb29nbGUucHJvdG9idWYuSW50MzJWYWx1ZRI8ChZyZXBlYXRl", - "ZF9pbnQ2NF93cmFwcGVyGNUBIAMoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2", - "NFZhbHVlEj4KF3JlcGVhdGVkX3VpbnQzMl93cmFwcGVyGNYBIAMoCzIcLmdv", - "b2dsZS5wcm90b2J1Zi5VSW50MzJWYWx1ZRI+ChdyZXBlYXRlZF91aW50NjRf", - "d3JhcHBlchjXASADKAsyHC5nb29nbGUucHJvdG9idWYuVUludDY0VmFsdWUS", - "PAoWcmVwZWF0ZWRfZmxvYXRfd3JhcHBlchjYASADKAsyGy5nb29nbGUucHJv", - "dG9idWYuRmxvYXRWYWx1ZRI+ChdyZXBlYXRlZF9kb3VibGVfd3JhcHBlchjZ", - "ASADKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSPgoXcmVwZWF0", - "ZWRfc3RyaW5nX3dyYXBwZXIY2gEgAygLMhwuZ29vZ2xlLnByb3RvYnVmLlN0", - "cmluZ1ZhbHVlEjwKFnJlcGVhdGVkX2J5dGVzX3dyYXBwZXIY2wEgAygLMhsu", - "Z29vZ2xlLnByb3RvYnVmLkJ5dGVzVmFsdWUSNQoRb3B0aW9uYWxfZHVyYXRp", - "b24YrQIgASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEjcKEm9wdGlv", - "bmFsX3RpbWVzdGFtcBiuAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0", - "YW1wEjgKE29wdGlvbmFsX2ZpZWxkX21hc2sYrwIgASgLMhouZ29vZ2xlLnBy", - "b3RvYnVmLkZpZWxkTWFzaxIxCg9vcHRpb25hbF9zdHJ1Y3QYsAIgASgLMhcu", - "Z29vZ2xlLnByb3RvYnVmLlN0cnVjdBIrCgxvcHRpb25hbF9hbnkYsQIgASgL", - "MhQuZ29vZ2xlLnByb3RvYnVmLkFueRIvCg5vcHRpb25hbF92YWx1ZRiyAiAB", - "KAsyFi5nb29nbGUucHJvdG9idWYuVmFsdWUSNQoRcmVwZWF0ZWRfZHVyYXRp", - "b24YtwIgAygLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEjcKEnJlcGVh", - "dGVkX3RpbWVzdGFtcBi4AiADKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0", - "YW1wEjcKEnJlcGVhdGVkX2ZpZWxkbWFzaxi5AiADKAsyGi5nb29nbGUucHJv", - "dG9idWYuRmllbGRNYXNrEjEKD3JlcGVhdGVkX3N0cnVjdBjEAiADKAsyFy5n", - "b29nbGUucHJvdG9idWYuU3RydWN0EisKDHJlcGVhdGVkX2FueRi7AiADKAsy", - "FC5nb29nbGUucHJvdG9idWYuQW55Ei8KDnJlcGVhdGVkX3ZhbHVlGLwCIAMo", - "CzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZRITCgpmaWVsZG5hbWUxGJEDIAEo", - "BRIUCgtmaWVsZF9uYW1lMhiSAyABKAUSFQoMX2ZpZWxkX25hbWUzGJMDIAEo", - "BRIWCg1maWVsZF9fbmFtZTRfGJQDIAEoBRIUCgtmaWVsZDBuYW1lNRiVAyAB", - "KAUSFgoNZmllbGRfMF9uYW1lNhiWAyABKAUSEwoKZmllbGROYW1lNxiXAyAB", - "KAUSEwoKRmllbGROYW1lOBiYAyABKAUSFAoLZmllbGRfTmFtZTkYmQMgASgF", - "EhUKDEZpZWxkX05hbWUxMBiaAyABKAUSFQoMRklFTERfTkFNRTExGJsDIAEo", - "BRIVCgxGSUVMRF9uYW1lMTIYnAMgASgFEhcKDl9fZmllbGRfbmFtZTEzGJ0D", - "IAEoBRIXCg5fX0ZpZWxkX25hbWUxNBieAyABKAUSFgoNZmllbGRfX25hbWUx", - "NRifAyABKAUSFgoNZmllbGRfX05hbWUxNhigAyABKAUSFwoOZmllbGRfbmFt", - "ZTE3X18YoQMgASgFEhcKDkZpZWxkX25hbWUxOF9fGKIDIAEoBRpiCg1OZXN0", - "ZWRNZXNzYWdlEgkKAWEYASABKAUSRgoLY29yZWN1cnNpdmUYAiABKAsyMS5w", - "cm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90", - "bzMaNAoSTWFwSW50MzJJbnQzMkVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1", - "ZRgCIAEoBToCOAEaNAoSTWFwSW50NjRJbnQ2NEVudHJ5EgsKA2tleRgBIAEo", - "AxINCgV2YWx1ZRgCIAEoAzoCOAEaNgoUTWFwVWludDMyVWludDMyRW50cnkS", - "CwoDa2V5GAEgASgNEg0KBXZhbHVlGAIgASgNOgI4ARo2ChRNYXBVaW50NjRV", - "aW50NjRFbnRyeRILCgNrZXkYASABKAQSDQoFdmFsdWUYAiABKAQ6AjgBGjYK", - "FE1hcFNpbnQzMlNpbnQzMkVudHJ5EgsKA2tleRgBIAEoERINCgV2YWx1ZRgC", - "IAEoEToCOAEaNgoUTWFwU2ludDY0U2ludDY0RW50cnkSCwoDa2V5GAEgASgS", - "Eg0KBXZhbHVlGAIgASgSOgI4ARo4ChZNYXBGaXhlZDMyRml4ZWQzMkVudHJ5", - "EgsKA2tleRgBIAEoBxINCgV2YWx1ZRgCIAEoBzoCOAEaOAoWTWFwRml4ZWQ2", - "NEZpeGVkNjRFbnRyeRILCgNrZXkYASABKAYSDQoFdmFsdWUYAiABKAY6AjgB", - "GjoKGE1hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeRILCgNrZXkYASABKA8SDQoF", - "dmFsdWUYAiABKA86AjgBGjoKGE1hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeRIL", - "CgNrZXkYASABKBASDQoFdmFsdWUYAiABKBA6AjgBGjQKEk1hcEludDMyRmxv", - "YXRFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAI6AjgBGjUKE01h", - "cEludDMyRG91YmxlRW50cnkSCwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgB", - "OgI4ARoyChBNYXBCb29sQm9vbEVudHJ5EgsKA2tleRgBIAEoCBINCgV2YWx1", - "ZRgCIAEoCDoCOAEaNgoUTWFwU3RyaW5nU3RyaW5nRW50cnkSCwoDa2V5GAEg", - "ASgJEg0KBXZhbHVlGAIgASgJOgI4ARo1ChNNYXBTdHJpbmdCeXRlc0VudHJ5", - "EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoDDoCOAEafgobTWFwU3RyaW5n", - "TmVzdGVkTWVzc2FnZUVudHJ5EgsKA2tleRgBIAEoCRJOCgV2YWx1ZRgCIAEo", - "CzI/LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBl", - "c1Byb3RvMy5OZXN0ZWRNZXNzYWdlOgI4ARptChxNYXBTdHJpbmdGb3JlaWdu", - "TWVzc2FnZUVudHJ5EgsKA2tleRgBIAEoCRI8CgV2YWx1ZRgCIAEoCzItLnBy", - "b3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLkZvcmVpZ25NZXNzYWdlOgI4", - "ARp4ChhNYXBTdHJpbmdOZXN0ZWRFbnVtRW50cnkSCwoDa2V5GAEgASgJEksK", - "BXZhbHVlGAIgASgOMjwucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMu", - "VGVzdEFsbFR5cGVzUHJvdG8zLk5lc3RlZEVudW06AjgBGmcKGU1hcFN0cmlu", - "Z0ZvcmVpZ25FbnVtRW50cnkSCwoDa2V5GAEgASgJEjkKBXZhbHVlGAIgASgO", - "MioucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuRm9yZWlnbkVudW06", - "AjgBIjkKCk5lc3RlZEVudW0SBwoDRk9PEAASBwoDQkFSEAESBwoDQkFaEAIS", - "EAoDTkVHEP///////////wFCDQoLb25lb2ZfZmllbGQiGwoORm9yZWlnbk1l", - "c3NhZ2USCQoBYxgBIAEoBSpACgtGb3JlaWduRW51bRIPCgtGT1JFSUdOX0ZP", - "TxAAEg8KC0ZPUkVJR05fQkFSEAESDwoLRk9SRUlHTl9CQVoQAkI4Cihjb20u", - "Z29vZ2xlLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zSAH4AQGiAgZQ", - "cm90bzNiBnByb3RvMw==")); - descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, - new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ProtobufTestMessages.Proto3.ForeignEnum), }, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3), global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OneofBool", "OneofUint64", "OneofFloat", "OneofDouble", "OneofEnum", "OptionalBoolWrapper", "OptionalInt32Wrapper", "OptionalInt64Wrapper", "OptionalUint32Wrapper", "OptionalUint64Wrapper", "OptionalFloatWrapper", "OptionalDoubleWrapper", "OptionalStringWrapper", "OptionalBytesWrapper", "RepeatedBoolWrapper", "RepeatedInt32Wrapper", "RepeatedInt64Wrapper", "RepeatedUint32Wrapper", "RepeatedUint64Wrapper", "RepeatedFloatWrapper", "RepeatedDoubleWrapper", "RepeatedStringWrapper", "RepeatedBytesWrapper", "OptionalDuration", "OptionalTimestamp", "OptionalFieldMask", "OptionalStruct", "OptionalAny", "OptionalValue", "RepeatedDuration", "RepeatedTimestamp", "RepeatedFieldmask", "RepeatedStruct", "RepeatedAny", "RepeatedValue", "Fieldname1", "FieldName2", "FieldName3", "FieldName4", "Field0Name5", "Field0Name6", "FieldName7", "FieldName8", "FieldName9", "FieldName10", "FIELDNAME11", "FIELDName12", "FieldName13", "FieldName14", "FieldName15", "FieldName16", "FieldName17", "FieldName18" }, new[]{ "OneofField" }, new[]{ typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage), global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser, new[]{ "A", "Corecursive" }, null, null, null), - null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }), - new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.ForeignMessage), global::ProtobufTestMessages.Proto3.ForeignMessage.Parser, new[]{ "C" }, null, null, null) - })); - } - #endregion - - } - #region Enums - public enum ForeignEnum { - [pbr::OriginalName("FOREIGN_FOO")] ForeignFoo = 0, - [pbr::OriginalName("FOREIGN_BAR")] ForeignBar = 1, - [pbr::OriginalName("FOREIGN_BAZ")] ForeignBaz = 2, - } - - #endregion - - #region Messages - /// - /// This proto includes every type of field in both singular and repeated - /// forms. - /// - /// Also, crucially, all messages and enums in this file are eventually - /// submessages of this message. So for example, a fuzz test of TestAllTypes - /// could trigger bugs that occur in any message type in this file. We verify - /// this stays true in a unit test. - /// - public sealed partial class TestAllTypesProto3 : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestAllTypesProto3()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::ProtobufTestMessages.Proto3.TestMessagesProto3Reflection.Descriptor.MessageTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestAllTypesProto3() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestAllTypesProto3(TestAllTypesProto3 other) : this() { - optionalInt32_ = other.optionalInt32_; - optionalInt64_ = other.optionalInt64_; - optionalUint32_ = other.optionalUint32_; - optionalUint64_ = other.optionalUint64_; - optionalSint32_ = other.optionalSint32_; - optionalSint64_ = other.optionalSint64_; - optionalFixed32_ = other.optionalFixed32_; - optionalFixed64_ = other.optionalFixed64_; - optionalSfixed32_ = other.optionalSfixed32_; - optionalSfixed64_ = other.optionalSfixed64_; - optionalFloat_ = other.optionalFloat_; - optionalDouble_ = other.optionalDouble_; - optionalBool_ = other.optionalBool_; - optionalString_ = other.optionalString_; - optionalBytes_ = other.optionalBytes_; - OptionalNestedMessage = other.optionalNestedMessage_ != null ? other.OptionalNestedMessage.Clone() : null; - OptionalForeignMessage = other.optionalForeignMessage_ != null ? other.OptionalForeignMessage.Clone() : null; - optionalNestedEnum_ = other.optionalNestedEnum_; - optionalForeignEnum_ = other.optionalForeignEnum_; - optionalStringPiece_ = other.optionalStringPiece_; - optionalCord_ = other.optionalCord_; - RecursiveMessage = other.recursiveMessage_ != null ? other.RecursiveMessage.Clone() : null; - repeatedInt32_ = other.repeatedInt32_.Clone(); - repeatedInt64_ = other.repeatedInt64_.Clone(); - repeatedUint32_ = other.repeatedUint32_.Clone(); - repeatedUint64_ = other.repeatedUint64_.Clone(); - repeatedSint32_ = other.repeatedSint32_.Clone(); - repeatedSint64_ = other.repeatedSint64_.Clone(); - repeatedFixed32_ = other.repeatedFixed32_.Clone(); - repeatedFixed64_ = other.repeatedFixed64_.Clone(); - repeatedSfixed32_ = other.repeatedSfixed32_.Clone(); - repeatedSfixed64_ = other.repeatedSfixed64_.Clone(); - repeatedFloat_ = other.repeatedFloat_.Clone(); - repeatedDouble_ = other.repeatedDouble_.Clone(); - repeatedBool_ = other.repeatedBool_.Clone(); - repeatedString_ = other.repeatedString_.Clone(); - repeatedBytes_ = other.repeatedBytes_.Clone(); - repeatedNestedMessage_ = other.repeatedNestedMessage_.Clone(); - repeatedForeignMessage_ = other.repeatedForeignMessage_.Clone(); - repeatedNestedEnum_ = other.repeatedNestedEnum_.Clone(); - repeatedForeignEnum_ = other.repeatedForeignEnum_.Clone(); - repeatedStringPiece_ = other.repeatedStringPiece_.Clone(); - repeatedCord_ = other.repeatedCord_.Clone(); - mapInt32Int32_ = other.mapInt32Int32_.Clone(); - mapInt64Int64_ = other.mapInt64Int64_.Clone(); - mapUint32Uint32_ = other.mapUint32Uint32_.Clone(); - mapUint64Uint64_ = other.mapUint64Uint64_.Clone(); - mapSint32Sint32_ = other.mapSint32Sint32_.Clone(); - mapSint64Sint64_ = other.mapSint64Sint64_.Clone(); - mapFixed32Fixed32_ = other.mapFixed32Fixed32_.Clone(); - mapFixed64Fixed64_ = other.mapFixed64Fixed64_.Clone(); - mapSfixed32Sfixed32_ = other.mapSfixed32Sfixed32_.Clone(); - mapSfixed64Sfixed64_ = other.mapSfixed64Sfixed64_.Clone(); - mapInt32Float_ = other.mapInt32Float_.Clone(); - mapInt32Double_ = other.mapInt32Double_.Clone(); - mapBoolBool_ = other.mapBoolBool_.Clone(); - mapStringString_ = other.mapStringString_.Clone(); - mapStringBytes_ = other.mapStringBytes_.Clone(); - mapStringNestedMessage_ = other.mapStringNestedMessage_.Clone(); - mapStringForeignMessage_ = other.mapStringForeignMessage_.Clone(); - mapStringNestedEnum_ = other.mapStringNestedEnum_.Clone(); - mapStringForeignEnum_ = other.mapStringForeignEnum_.Clone(); - OptionalBoolWrapper = other.OptionalBoolWrapper; - OptionalInt32Wrapper = other.OptionalInt32Wrapper; - OptionalInt64Wrapper = other.OptionalInt64Wrapper; - OptionalUint32Wrapper = other.OptionalUint32Wrapper; - OptionalUint64Wrapper = other.OptionalUint64Wrapper; - OptionalFloatWrapper = other.OptionalFloatWrapper; - OptionalDoubleWrapper = other.OptionalDoubleWrapper; - OptionalStringWrapper = other.OptionalStringWrapper; - OptionalBytesWrapper = other.OptionalBytesWrapper; - repeatedBoolWrapper_ = other.repeatedBoolWrapper_.Clone(); - repeatedInt32Wrapper_ = other.repeatedInt32Wrapper_.Clone(); - repeatedInt64Wrapper_ = other.repeatedInt64Wrapper_.Clone(); - repeatedUint32Wrapper_ = other.repeatedUint32Wrapper_.Clone(); - repeatedUint64Wrapper_ = other.repeatedUint64Wrapper_.Clone(); - repeatedFloatWrapper_ = other.repeatedFloatWrapper_.Clone(); - repeatedDoubleWrapper_ = other.repeatedDoubleWrapper_.Clone(); - repeatedStringWrapper_ = other.repeatedStringWrapper_.Clone(); - repeatedBytesWrapper_ = other.repeatedBytesWrapper_.Clone(); - OptionalDuration = other.optionalDuration_ != null ? other.OptionalDuration.Clone() : null; - OptionalTimestamp = other.optionalTimestamp_ != null ? other.OptionalTimestamp.Clone() : null; - OptionalFieldMask = other.optionalFieldMask_ != null ? other.OptionalFieldMask.Clone() : null; - OptionalStruct = other.optionalStruct_ != null ? other.OptionalStruct.Clone() : null; - OptionalAny = other.optionalAny_ != null ? other.OptionalAny.Clone() : null; - OptionalValue = other.optionalValue_ != null ? other.OptionalValue.Clone() : null; - repeatedDuration_ = other.repeatedDuration_.Clone(); - repeatedTimestamp_ = other.repeatedTimestamp_.Clone(); - repeatedFieldmask_ = other.repeatedFieldmask_.Clone(); - repeatedStruct_ = other.repeatedStruct_.Clone(); - repeatedAny_ = other.repeatedAny_.Clone(); - repeatedValue_ = other.repeatedValue_.Clone(); - fieldname1_ = other.fieldname1_; - fieldName2_ = other.fieldName2_; - FieldName3_ = other.FieldName3_; - fieldName4_ = other.fieldName4_; - field0Name5_ = other.field0Name5_; - field0Name6_ = other.field0Name6_; - fieldName7_ = other.fieldName7_; - fieldName8_ = other.fieldName8_; - fieldName9_ = other.fieldName9_; - fieldName10_ = other.fieldName10_; - fIELDNAME11_ = other.fIELDNAME11_; - fIELDName12_ = other.fIELDName12_; - FieldName13_ = other.FieldName13_; - FieldName14_ = other.FieldName14_; - fieldName15_ = other.fieldName15_; - fieldName16_ = other.fieldName16_; - fieldName17_ = other.fieldName17_; - fieldName18_ = other.fieldName18_; - switch (other.OneofFieldCase) { - case OneofFieldOneofCase.OneofUint32: - OneofUint32 = other.OneofUint32; - break; - case OneofFieldOneofCase.OneofNestedMessage: - OneofNestedMessage = other.OneofNestedMessage.Clone(); - break; - case OneofFieldOneofCase.OneofString: - OneofString = other.OneofString; - break; - case OneofFieldOneofCase.OneofBytes: - OneofBytes = other.OneofBytes; - break; - case OneofFieldOneofCase.OneofBool: - OneofBool = other.OneofBool; - break; - case OneofFieldOneofCase.OneofUint64: - OneofUint64 = other.OneofUint64; - break; - case OneofFieldOneofCase.OneofFloat: - OneofFloat = other.OneofFloat; - break; - case OneofFieldOneofCase.OneofDouble: - OneofDouble = other.OneofDouble; - break; - case OneofFieldOneofCase.OneofEnum: - OneofEnum = other.OneofEnum; - break; - } - - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestAllTypesProto3 Clone() { - return new TestAllTypesProto3(this); - } - - /// Field number for the "optional_int32" field. - public const int OptionalInt32FieldNumber = 1; - private int optionalInt32_; - /// - /// Singular - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int OptionalInt32 { - get { return optionalInt32_; } - set { - optionalInt32_ = value; - } - } - - /// Field number for the "optional_int64" field. - public const int OptionalInt64FieldNumber = 2; - private long optionalInt64_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public long OptionalInt64 { - get { return optionalInt64_; } - set { - optionalInt64_ = value; - } - } - - /// Field number for the "optional_uint32" field. - public const int OptionalUint32FieldNumber = 3; - private uint optionalUint32_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint OptionalUint32 { - get { return optionalUint32_; } - set { - optionalUint32_ = value; - } - } - - /// Field number for the "optional_uint64" field. - public const int OptionalUint64FieldNumber = 4; - private ulong optionalUint64_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ulong OptionalUint64 { - get { return optionalUint64_; } - set { - optionalUint64_ = value; - } - } - - /// Field number for the "optional_sint32" field. - public const int OptionalSint32FieldNumber = 5; - private int optionalSint32_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int OptionalSint32 { - get { return optionalSint32_; } - set { - optionalSint32_ = value; - } - } - - /// Field number for the "optional_sint64" field. - public const int OptionalSint64FieldNumber = 6; - private long optionalSint64_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public long OptionalSint64 { - get { return optionalSint64_; } - set { - optionalSint64_ = value; - } - } - - /// Field number for the "optional_fixed32" field. - public const int OptionalFixed32FieldNumber = 7; - private uint optionalFixed32_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint OptionalFixed32 { - get { return optionalFixed32_; } - set { - optionalFixed32_ = value; - } - } - - /// Field number for the "optional_fixed64" field. - public const int OptionalFixed64FieldNumber = 8; - private ulong optionalFixed64_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ulong OptionalFixed64 { - get { return optionalFixed64_; } - set { - optionalFixed64_ = value; - } - } - - /// Field number for the "optional_sfixed32" field. - public const int OptionalSfixed32FieldNumber = 9; - private int optionalSfixed32_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int OptionalSfixed32 { - get { return optionalSfixed32_; } - set { - optionalSfixed32_ = value; - } - } - - /// Field number for the "optional_sfixed64" field. - public const int OptionalSfixed64FieldNumber = 10; - private long optionalSfixed64_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public long OptionalSfixed64 { - get { return optionalSfixed64_; } - set { - optionalSfixed64_ = value; - } - } - - /// Field number for the "optional_float" field. - public const int OptionalFloatFieldNumber = 11; - private float optionalFloat_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public float OptionalFloat { - get { return optionalFloat_; } - set { - optionalFloat_ = value; - } - } - - /// Field number for the "optional_double" field. - public const int OptionalDoubleFieldNumber = 12; - private double optionalDouble_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public double OptionalDouble { - get { return optionalDouble_; } - set { - optionalDouble_ = value; - } - } - - /// Field number for the "optional_bool" field. - public const int OptionalBoolFieldNumber = 13; - private bool optionalBool_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool OptionalBool { - get { return optionalBool_; } - set { - optionalBool_ = value; - } - } - - /// Field number for the "optional_string" field. - public const int OptionalStringFieldNumber = 14; - private string optionalString_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string OptionalString { - get { return optionalString_; } - set { - optionalString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "optional_bytes" field. - public const int OptionalBytesFieldNumber = 15; - private pb::ByteString optionalBytes_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pb::ByteString OptionalBytes { - get { return optionalBytes_; } - set { - optionalBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "optional_nested_message" field. - public const int OptionalNestedMessageFieldNumber = 18; - private global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage optionalNestedMessage_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage OptionalNestedMessage { - get { return optionalNestedMessage_; } - set { - optionalNestedMessage_ = value; - } - } - - /// Field number for the "optional_foreign_message" field. - public const int OptionalForeignMessageFieldNumber = 19; - private global::ProtobufTestMessages.Proto3.ForeignMessage optionalForeignMessage_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::ProtobufTestMessages.Proto3.ForeignMessage OptionalForeignMessage { - get { return optionalForeignMessage_; } - set { - optionalForeignMessage_ = value; - } - } - - /// Field number for the "optional_nested_enum" field. - public const int OptionalNestedEnumFieldNumber = 21; - private global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum optionalNestedEnum_ = 0; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum OptionalNestedEnum { - get { return optionalNestedEnum_; } - set { - optionalNestedEnum_ = value; - } - } - - /// Field number for the "optional_foreign_enum" field. - public const int OptionalForeignEnumFieldNumber = 22; - private global::ProtobufTestMessages.Proto3.ForeignEnum optionalForeignEnum_ = 0; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::ProtobufTestMessages.Proto3.ForeignEnum OptionalForeignEnum { - get { return optionalForeignEnum_; } - set { - optionalForeignEnum_ = value; - } - } - - /// Field number for the "optional_string_piece" field. - public const int OptionalStringPieceFieldNumber = 24; - private string optionalStringPiece_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string OptionalStringPiece { - get { return optionalStringPiece_; } - set { - optionalStringPiece_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "optional_cord" field. - public const int OptionalCordFieldNumber = 25; - private string optionalCord_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string OptionalCord { - get { return optionalCord_; } - set { - optionalCord_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "recursive_message" field. - public const int RecursiveMessageFieldNumber = 27; - private global::ProtobufTestMessages.Proto3.TestAllTypesProto3 recursiveMessage_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::ProtobufTestMessages.Proto3.TestAllTypesProto3 RecursiveMessage { - get { return recursiveMessage_; } - set { - recursiveMessage_ = value; - } - } - - /// Field number for the "repeated_int32" field. - public const int RepeatedInt32FieldNumber = 31; - private static readonly pb::FieldCodec _repeated_repeatedInt32_codec - = pb::FieldCodec.ForInt32(250); - private readonly pbc::RepeatedField repeatedInt32_ = new pbc::RepeatedField(); - /// - /// Repeated - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedInt32 { - get { return repeatedInt32_; } - } - - /// Field number for the "repeated_int64" field. - public const int RepeatedInt64FieldNumber = 32; - private static readonly pb::FieldCodec _repeated_repeatedInt64_codec - = pb::FieldCodec.ForInt64(258); - private readonly pbc::RepeatedField repeatedInt64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedInt64 { - get { return repeatedInt64_; } - } - - /// Field number for the "repeated_uint32" field. - public const int RepeatedUint32FieldNumber = 33; - private static readonly pb::FieldCodec _repeated_repeatedUint32_codec - = pb::FieldCodec.ForUInt32(266); - private readonly pbc::RepeatedField repeatedUint32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedUint32 { - get { return repeatedUint32_; } - } - - /// Field number for the "repeated_uint64" field. - public const int RepeatedUint64FieldNumber = 34; - private static readonly pb::FieldCodec _repeated_repeatedUint64_codec - = pb::FieldCodec.ForUInt64(274); - private readonly pbc::RepeatedField repeatedUint64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedUint64 { - get { return repeatedUint64_; } - } - - /// Field number for the "repeated_sint32" field. - public const int RepeatedSint32FieldNumber = 35; - private static readonly pb::FieldCodec _repeated_repeatedSint32_codec - = pb::FieldCodec.ForSInt32(282); - private readonly pbc::RepeatedField repeatedSint32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedSint32 { - get { return repeatedSint32_; } - } - - /// Field number for the "repeated_sint64" field. - public const int RepeatedSint64FieldNumber = 36; - private static readonly pb::FieldCodec _repeated_repeatedSint64_codec - = pb::FieldCodec.ForSInt64(290); - private readonly pbc::RepeatedField repeatedSint64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedSint64 { - get { return repeatedSint64_; } - } - - /// Field number for the "repeated_fixed32" field. - public const int RepeatedFixed32FieldNumber = 37; - private static readonly pb::FieldCodec _repeated_repeatedFixed32_codec - = pb::FieldCodec.ForFixed32(298); - private readonly pbc::RepeatedField repeatedFixed32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedFixed32 { - get { return repeatedFixed32_; } - } - - /// Field number for the "repeated_fixed64" field. - public const int RepeatedFixed64FieldNumber = 38; - private static readonly pb::FieldCodec _repeated_repeatedFixed64_codec - = pb::FieldCodec.ForFixed64(306); - private readonly pbc::RepeatedField repeatedFixed64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedFixed64 { - get { return repeatedFixed64_; } - } - - /// Field number for the "repeated_sfixed32" field. - public const int RepeatedSfixed32FieldNumber = 39; - private static readonly pb::FieldCodec _repeated_repeatedSfixed32_codec - = pb::FieldCodec.ForSFixed32(314); - private readonly pbc::RepeatedField repeatedSfixed32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedSfixed32 { - get { return repeatedSfixed32_; } - } - - /// Field number for the "repeated_sfixed64" field. - public const int RepeatedSfixed64FieldNumber = 40; - private static readonly pb::FieldCodec _repeated_repeatedSfixed64_codec - = pb::FieldCodec.ForSFixed64(322); - private readonly pbc::RepeatedField repeatedSfixed64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedSfixed64 { - get { return repeatedSfixed64_; } - } - - /// Field number for the "repeated_float" field. - public const int RepeatedFloatFieldNumber = 41; - private static readonly pb::FieldCodec _repeated_repeatedFloat_codec - = pb::FieldCodec.ForFloat(330); - private readonly pbc::RepeatedField repeatedFloat_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedFloat { - get { return repeatedFloat_; } - } - - /// Field number for the "repeated_double" field. - public const int RepeatedDoubleFieldNumber = 42; - private static readonly pb::FieldCodec _repeated_repeatedDouble_codec - = pb::FieldCodec.ForDouble(338); - private readonly pbc::RepeatedField repeatedDouble_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedDouble { - get { return repeatedDouble_; } - } - - /// Field number for the "repeated_bool" field. - public const int RepeatedBoolFieldNumber = 43; - private static readonly pb::FieldCodec _repeated_repeatedBool_codec - = pb::FieldCodec.ForBool(346); - private readonly pbc::RepeatedField repeatedBool_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedBool { - get { return repeatedBool_; } - } - - /// Field number for the "repeated_string" field. - public const int RepeatedStringFieldNumber = 44; - private static readonly pb::FieldCodec _repeated_repeatedString_codec - = pb::FieldCodec.ForString(354); - private readonly pbc::RepeatedField repeatedString_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedString { - get { return repeatedString_; } - } - - /// Field number for the "repeated_bytes" field. - public const int RepeatedBytesFieldNumber = 45; - private static readonly pb::FieldCodec _repeated_repeatedBytes_codec - = pb::FieldCodec.ForBytes(362); - private readonly pbc::RepeatedField repeatedBytes_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedBytes { - get { return repeatedBytes_; } - } - - /// Field number for the "repeated_nested_message" field. - public const int RepeatedNestedMessageFieldNumber = 48; - private static readonly pb::FieldCodec _repeated_repeatedNestedMessage_codec - = pb::FieldCodec.ForMessage(386, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser); - private readonly pbc::RepeatedField repeatedNestedMessage_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedNestedMessage { - get { return repeatedNestedMessage_; } - } - - /// Field number for the "repeated_foreign_message" field. - public const int RepeatedForeignMessageFieldNumber = 49; - private static readonly pb::FieldCodec _repeated_repeatedForeignMessage_codec - = pb::FieldCodec.ForMessage(394, global::ProtobufTestMessages.Proto3.ForeignMessage.Parser); - private readonly pbc::RepeatedField repeatedForeignMessage_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedForeignMessage { - get { return repeatedForeignMessage_; } - } - - /// Field number for the "repeated_nested_enum" field. - public const int RepeatedNestedEnumFieldNumber = 51; - private static readonly pb::FieldCodec _repeated_repeatedNestedEnum_codec - = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) x); - private readonly pbc::RepeatedField repeatedNestedEnum_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedNestedEnum { - get { return repeatedNestedEnum_; } - } - - /// Field number for the "repeated_foreign_enum" field. - public const int RepeatedForeignEnumFieldNumber = 52; - private static readonly pb::FieldCodec _repeated_repeatedForeignEnum_codec - = pb::FieldCodec.ForEnum(418, x => (int) x, x => (global::ProtobufTestMessages.Proto3.ForeignEnum) x); - private readonly pbc::RepeatedField repeatedForeignEnum_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedForeignEnum { - get { return repeatedForeignEnum_; } - } - - /// Field number for the "repeated_string_piece" field. - public const int RepeatedStringPieceFieldNumber = 54; - private static readonly pb::FieldCodec _repeated_repeatedStringPiece_codec - = pb::FieldCodec.ForString(434); - private readonly pbc::RepeatedField repeatedStringPiece_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedStringPiece { - get { return repeatedStringPiece_; } - } - - /// Field number for the "repeated_cord" field. - public const int RepeatedCordFieldNumber = 55; - private static readonly pb::FieldCodec _repeated_repeatedCord_codec - = pb::FieldCodec.ForString(442); - private readonly pbc::RepeatedField repeatedCord_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedCord { - get { return repeatedCord_; } - } - - /// Field number for the "map_int32_int32" field. - public const int MapInt32Int32FieldNumber = 56; - private static readonly pbc::MapField.Codec _map_mapInt32Int32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 450); - private readonly pbc::MapField mapInt32Int32_ = new pbc::MapField(); - /// - /// Map - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32Int32 { - get { return mapInt32Int32_; } - } - - /// Field number for the "map_int64_int64" field. - public const int MapInt64Int64FieldNumber = 57; - private static readonly pbc::MapField.Codec _map_mapInt64Int64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt64(8), pb::FieldCodec.ForInt64(16), 458); - private readonly pbc::MapField mapInt64Int64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt64Int64 { - get { return mapInt64Int64_; } - } - - /// Field number for the "map_uint32_uint32" field. - public const int MapUint32Uint32FieldNumber = 58; - private static readonly pbc::MapField.Codec _map_mapUint32Uint32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForUInt32(8), pb::FieldCodec.ForUInt32(16), 466); - private readonly pbc::MapField mapUint32Uint32_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapUint32Uint32 { - get { return mapUint32Uint32_; } - } - - /// Field number for the "map_uint64_uint64" field. - public const int MapUint64Uint64FieldNumber = 59; - private static readonly pbc::MapField.Codec _map_mapUint64Uint64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForUInt64(8), pb::FieldCodec.ForUInt64(16), 474); - private readonly pbc::MapField mapUint64Uint64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapUint64Uint64 { - get { return mapUint64Uint64_; } - } - - /// Field number for the "map_sint32_sint32" field. - public const int MapSint32Sint32FieldNumber = 60; - private static readonly pbc::MapField.Codec _map_mapSint32Sint32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForSInt32(8), pb::FieldCodec.ForSInt32(16), 482); - private readonly pbc::MapField mapSint32Sint32_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapSint32Sint32 { - get { return mapSint32Sint32_; } - } - - /// Field number for the "map_sint64_sint64" field. - public const int MapSint64Sint64FieldNumber = 61; - private static readonly pbc::MapField.Codec _map_mapSint64Sint64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForSInt64(8), pb::FieldCodec.ForSInt64(16), 490); - private readonly pbc::MapField mapSint64Sint64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapSint64Sint64 { - get { return mapSint64Sint64_; } - } - - /// Field number for the "map_fixed32_fixed32" field. - public const int MapFixed32Fixed32FieldNumber = 62; - private static readonly pbc::MapField.Codec _map_mapFixed32Fixed32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForFixed32(13), pb::FieldCodec.ForFixed32(21), 498); - private readonly pbc::MapField mapFixed32Fixed32_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapFixed32Fixed32 { - get { return mapFixed32Fixed32_; } - } - - /// Field number for the "map_fixed64_fixed64" field. - public const int MapFixed64Fixed64FieldNumber = 63; - private static readonly pbc::MapField.Codec _map_mapFixed64Fixed64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForFixed64(9), pb::FieldCodec.ForFixed64(17), 506); - private readonly pbc::MapField mapFixed64Fixed64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapFixed64Fixed64 { - get { return mapFixed64Fixed64_; } - } - - /// Field number for the "map_sfixed32_sfixed32" field. - public const int MapSfixed32Sfixed32FieldNumber = 64; - private static readonly pbc::MapField.Codec _map_mapSfixed32Sfixed32_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForSFixed32(13), pb::FieldCodec.ForSFixed32(21), 514); - private readonly pbc::MapField mapSfixed32Sfixed32_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapSfixed32Sfixed32 { - get { return mapSfixed32Sfixed32_; } - } - - /// Field number for the "map_sfixed64_sfixed64" field. - public const int MapSfixed64Sfixed64FieldNumber = 65; - private static readonly pbc::MapField.Codec _map_mapSfixed64Sfixed64_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForSFixed64(9), pb::FieldCodec.ForSFixed64(17), 522); - private readonly pbc::MapField mapSfixed64Sfixed64_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapSfixed64Sfixed64 { - get { return mapSfixed64Sfixed64_; } - } - - /// Field number for the "map_int32_float" field. - public const int MapInt32FloatFieldNumber = 66; - private static readonly pbc::MapField.Codec _map_mapInt32Float_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForFloat(21), 530); - private readonly pbc::MapField mapInt32Float_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32Float { - get { return mapInt32Float_; } - } - - /// Field number for the "map_int32_double" field. - public const int MapInt32DoubleFieldNumber = 67; - private static readonly pbc::MapField.Codec _map_mapInt32Double_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForDouble(17), 538); - private readonly pbc::MapField mapInt32Double_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapInt32Double { - get { return mapInt32Double_; } - } - - /// Field number for the "map_bool_bool" field. - public const int MapBoolBoolFieldNumber = 68; - private static readonly pbc::MapField.Codec _map_mapBoolBool_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForBool(8), pb::FieldCodec.ForBool(16), 546); - private readonly pbc::MapField mapBoolBool_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapBoolBool { - get { return mapBoolBool_; } - } - - /// Field number for the "map_string_string" field. - public const int MapStringStringFieldNumber = 69; - private static readonly pbc::MapField.Codec _map_mapStringString_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForString(18), 554); - private readonly pbc::MapField mapStringString_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapStringString { - get { return mapStringString_; } - } - - /// Field number for the "map_string_bytes" field. - public const int MapStringBytesFieldNumber = 70; - private static readonly pbc::MapField.Codec _map_mapStringBytes_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForBytes(18), 562); - private readonly pbc::MapField mapStringBytes_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapStringBytes { - get { return mapStringBytes_; } - } - - /// Field number for the "map_string_nested_message" field. - public const int MapStringNestedMessageFieldNumber = 71; - private static readonly pbc::MapField.Codec _map_mapStringNestedMessage_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForMessage(18, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser), 570); - private readonly pbc::MapField mapStringNestedMessage_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapStringNestedMessage { - get { return mapStringNestedMessage_; } - } - - /// Field number for the "map_string_foreign_message" field. - public const int MapStringForeignMessageFieldNumber = 72; - private static readonly pbc::MapField.Codec _map_mapStringForeignMessage_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForMessage(18, global::ProtobufTestMessages.Proto3.ForeignMessage.Parser), 578); - private readonly pbc::MapField mapStringForeignMessage_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapStringForeignMessage { - get { return mapStringForeignMessage_; } - } - - /// Field number for the "map_string_nested_enum" field. - public const int MapStringNestedEnumFieldNumber = 73; - private static readonly pbc::MapField.Codec _map_mapStringNestedEnum_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) x), 586); - private readonly pbc::MapField mapStringNestedEnum_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapStringNestedEnum { - get { return mapStringNestedEnum_; } - } - - /// Field number for the "map_string_foreign_enum" field. - public const int MapStringForeignEnumFieldNumber = 74; - private static readonly pbc::MapField.Codec _map_mapStringForeignEnum_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::ProtobufTestMessages.Proto3.ForeignEnum) x), 594); - private readonly pbc::MapField mapStringForeignEnum_ = new pbc::MapField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::MapField MapStringForeignEnum { - get { return mapStringForeignEnum_; } - } - - /// Field number for the "oneof_uint32" field. - public const int OneofUint32FieldNumber = 111; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint OneofUint32 { - get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; } - set { - oneofField_ = value; - oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; - } - } - - /// Field number for the "oneof_nested_message" field. - public const int OneofNestedMessageFieldNumber = 112; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage OneofNestedMessage { - get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage) oneofField_ : null; } - set { - oneofField_ = value; - oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage; - } - } - - /// Field number for the "oneof_string" field. - public const int OneofStringFieldNumber = 113; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string OneofString { - get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; } - set { - oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - oneofFieldCase_ = OneofFieldOneofCase.OneofString; - } - } - - /// Field number for the "oneof_bytes" field. - public const int OneofBytesFieldNumber = 114; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pb::ByteString OneofBytes { - get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; } - set { - oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; - } - } - - /// Field number for the "oneof_bool" field. - public const int OneofBoolFieldNumber = 115; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool OneofBool { - get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBool ? (bool) oneofField_ : false; } - set { - oneofField_ = value; - oneofFieldCase_ = OneofFieldOneofCase.OneofBool; - } - } - - /// Field number for the "oneof_uint64" field. - public const int OneofUint64FieldNumber = 116; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ulong OneofUint64 { - get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint64 ? (ulong) oneofField_ : 0UL; } - set { - oneofField_ = value; - oneofFieldCase_ = OneofFieldOneofCase.OneofUint64; - } - } - - /// Field number for the "oneof_float" field. - public const int OneofFloatFieldNumber = 117; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public float OneofFloat { - get { return oneofFieldCase_ == OneofFieldOneofCase.OneofFloat ? (float) oneofField_ : 0F; } - set { - oneofField_ = value; - oneofFieldCase_ = OneofFieldOneofCase.OneofFloat; - } - } - - /// Field number for the "oneof_double" field. - public const int OneofDoubleFieldNumber = 118; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public double OneofDouble { - get { return oneofFieldCase_ == OneofFieldOneofCase.OneofDouble ? (double) oneofField_ : 0D; } - set { - oneofField_ = value; - oneofFieldCase_ = OneofFieldOneofCase.OneofDouble; - } - } - - /// Field number for the "oneof_enum" field. - public const int OneofEnumFieldNumber = 119; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum OneofEnum { - get { return oneofFieldCase_ == OneofFieldOneofCase.OneofEnum ? (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) oneofField_ : 0; } - set { - oneofField_ = value; - oneofFieldCase_ = OneofFieldOneofCase.OneofEnum; - } - } - - /// Field number for the "optional_bool_wrapper" field. - public const int OptionalBoolWrapperFieldNumber = 201; - private static readonly pb::FieldCodec _single_optionalBoolWrapper_codec = pb::FieldCodec.ForStructWrapper(1610); - private bool? optionalBoolWrapper_; - /// - /// Well-known types - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool? OptionalBoolWrapper { - get { return optionalBoolWrapper_; } - set { - optionalBoolWrapper_ = value; - } - } - - /// Field number for the "optional_int32_wrapper" field. - public const int OptionalInt32WrapperFieldNumber = 202; - private static readonly pb::FieldCodec _single_optionalInt32Wrapper_codec = pb::FieldCodec.ForStructWrapper(1618); - private int? optionalInt32Wrapper_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int? OptionalInt32Wrapper { - get { return optionalInt32Wrapper_; } - set { - optionalInt32Wrapper_ = value; - } - } - - /// Field number for the "optional_int64_wrapper" field. - public const int OptionalInt64WrapperFieldNumber = 203; - private static readonly pb::FieldCodec _single_optionalInt64Wrapper_codec = pb::FieldCodec.ForStructWrapper(1626); - private long? optionalInt64Wrapper_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public long? OptionalInt64Wrapper { - get { return optionalInt64Wrapper_; } - set { - optionalInt64Wrapper_ = value; - } - } - - /// Field number for the "optional_uint32_wrapper" field. - public const int OptionalUint32WrapperFieldNumber = 204; - private static readonly pb::FieldCodec _single_optionalUint32Wrapper_codec = pb::FieldCodec.ForStructWrapper(1634); - private uint? optionalUint32Wrapper_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint? OptionalUint32Wrapper { - get { return optionalUint32Wrapper_; } - set { - optionalUint32Wrapper_ = value; - } - } - - /// Field number for the "optional_uint64_wrapper" field. - public const int OptionalUint64WrapperFieldNumber = 205; - private static readonly pb::FieldCodec _single_optionalUint64Wrapper_codec = pb::FieldCodec.ForStructWrapper(1642); - private ulong? optionalUint64Wrapper_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ulong? OptionalUint64Wrapper { - get { return optionalUint64Wrapper_; } - set { - optionalUint64Wrapper_ = value; - } - } - - /// Field number for the "optional_float_wrapper" field. - public const int OptionalFloatWrapperFieldNumber = 206; - private static readonly pb::FieldCodec _single_optionalFloatWrapper_codec = pb::FieldCodec.ForStructWrapper(1650); - private float? optionalFloatWrapper_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public float? OptionalFloatWrapper { - get { return optionalFloatWrapper_; } - set { - optionalFloatWrapper_ = value; - } - } - - /// Field number for the "optional_double_wrapper" field. - public const int OptionalDoubleWrapperFieldNumber = 207; - private static readonly pb::FieldCodec _single_optionalDoubleWrapper_codec = pb::FieldCodec.ForStructWrapper(1658); - private double? optionalDoubleWrapper_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public double? OptionalDoubleWrapper { - get { return optionalDoubleWrapper_; } - set { - optionalDoubleWrapper_ = value; - } - } - - /// Field number for the "optional_string_wrapper" field. - public const int OptionalStringWrapperFieldNumber = 208; - private static readonly pb::FieldCodec _single_optionalStringWrapper_codec = pb::FieldCodec.ForClassWrapper(1666); - private string optionalStringWrapper_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string OptionalStringWrapper { - get { return optionalStringWrapper_; } - set { - optionalStringWrapper_ = value; - } - } - - /// Field number for the "optional_bytes_wrapper" field. - public const int OptionalBytesWrapperFieldNumber = 209; - private static readonly pb::FieldCodec _single_optionalBytesWrapper_codec = pb::FieldCodec.ForClassWrapper(1674); - private pb::ByteString optionalBytesWrapper_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pb::ByteString OptionalBytesWrapper { - get { return optionalBytesWrapper_; } - set { - optionalBytesWrapper_ = value; - } - } - - /// Field number for the "repeated_bool_wrapper" field. - public const int RepeatedBoolWrapperFieldNumber = 211; - private static readonly pb::FieldCodec _repeated_repeatedBoolWrapper_codec - = pb::FieldCodec.ForStructWrapper(1690); - private readonly pbc::RepeatedField repeatedBoolWrapper_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedBoolWrapper { - get { return repeatedBoolWrapper_; } - } - - /// Field number for the "repeated_int32_wrapper" field. - public const int RepeatedInt32WrapperFieldNumber = 212; - private static readonly pb::FieldCodec _repeated_repeatedInt32Wrapper_codec - = pb::FieldCodec.ForStructWrapper(1698); - private readonly pbc::RepeatedField repeatedInt32Wrapper_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedInt32Wrapper { - get { return repeatedInt32Wrapper_; } - } - - /// Field number for the "repeated_int64_wrapper" field. - public const int RepeatedInt64WrapperFieldNumber = 213; - private static readonly pb::FieldCodec _repeated_repeatedInt64Wrapper_codec - = pb::FieldCodec.ForStructWrapper(1706); - private readonly pbc::RepeatedField repeatedInt64Wrapper_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedInt64Wrapper { - get { return repeatedInt64Wrapper_; } - } - - /// Field number for the "repeated_uint32_wrapper" field. - public const int RepeatedUint32WrapperFieldNumber = 214; - private static readonly pb::FieldCodec _repeated_repeatedUint32Wrapper_codec - = pb::FieldCodec.ForStructWrapper(1714); - private readonly pbc::RepeatedField repeatedUint32Wrapper_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedUint32Wrapper { - get { return repeatedUint32Wrapper_; } - } - - /// Field number for the "repeated_uint64_wrapper" field. - public const int RepeatedUint64WrapperFieldNumber = 215; - private static readonly pb::FieldCodec _repeated_repeatedUint64Wrapper_codec - = pb::FieldCodec.ForStructWrapper(1722); - private readonly pbc::RepeatedField repeatedUint64Wrapper_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedUint64Wrapper { - get { return repeatedUint64Wrapper_; } - } - - /// Field number for the "repeated_float_wrapper" field. - public const int RepeatedFloatWrapperFieldNumber = 216; - private static readonly pb::FieldCodec _repeated_repeatedFloatWrapper_codec - = pb::FieldCodec.ForStructWrapper(1730); - private readonly pbc::RepeatedField repeatedFloatWrapper_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedFloatWrapper { - get { return repeatedFloatWrapper_; } - } - - /// Field number for the "repeated_double_wrapper" field. - public const int RepeatedDoubleWrapperFieldNumber = 217; - private static readonly pb::FieldCodec _repeated_repeatedDoubleWrapper_codec - = pb::FieldCodec.ForStructWrapper(1738); - private readonly pbc::RepeatedField repeatedDoubleWrapper_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedDoubleWrapper { - get { return repeatedDoubleWrapper_; } - } - - /// Field number for the "repeated_string_wrapper" field. - public const int RepeatedStringWrapperFieldNumber = 218; - private static readonly pb::FieldCodec _repeated_repeatedStringWrapper_codec - = pb::FieldCodec.ForClassWrapper(1746); - private readonly pbc::RepeatedField repeatedStringWrapper_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedStringWrapper { - get { return repeatedStringWrapper_; } - } - - /// Field number for the "repeated_bytes_wrapper" field. - public const int RepeatedBytesWrapperFieldNumber = 219; - private static readonly pb::FieldCodec _repeated_repeatedBytesWrapper_codec - = pb::FieldCodec.ForClassWrapper(1754); - private readonly pbc::RepeatedField repeatedBytesWrapper_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedBytesWrapper { - get { return repeatedBytesWrapper_; } - } - - /// Field number for the "optional_duration" field. - public const int OptionalDurationFieldNumber = 301; - private global::Google.Protobuf.WellKnownTypes.Duration optionalDuration_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.WellKnownTypes.Duration OptionalDuration { - get { return optionalDuration_; } - set { - optionalDuration_ = value; - } - } - - /// Field number for the "optional_timestamp" field. - public const int OptionalTimestampFieldNumber = 302; - private global::Google.Protobuf.WellKnownTypes.Timestamp optionalTimestamp_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.WellKnownTypes.Timestamp OptionalTimestamp { - get { return optionalTimestamp_; } - set { - optionalTimestamp_ = value; - } - } - - /// Field number for the "optional_field_mask" field. - public const int OptionalFieldMaskFieldNumber = 303; - private global::Google.Protobuf.WellKnownTypes.FieldMask optionalFieldMask_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.WellKnownTypes.FieldMask OptionalFieldMask { - get { return optionalFieldMask_; } - set { - optionalFieldMask_ = value; - } - } - - /// Field number for the "optional_struct" field. - public const int OptionalStructFieldNumber = 304; - private global::Google.Protobuf.WellKnownTypes.Struct optionalStruct_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.WellKnownTypes.Struct OptionalStruct { - get { return optionalStruct_; } - set { - optionalStruct_ = value; - } - } - - /// Field number for the "optional_any" field. - public const int OptionalAnyFieldNumber = 305; - private global::Google.Protobuf.WellKnownTypes.Any optionalAny_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.WellKnownTypes.Any OptionalAny { - get { return optionalAny_; } - set { - optionalAny_ = value; - } - } - - /// Field number for the "optional_value" field. - public const int OptionalValueFieldNumber = 306; - private global::Google.Protobuf.WellKnownTypes.Value optionalValue_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.WellKnownTypes.Value OptionalValue { - get { return optionalValue_; } - set { - optionalValue_ = value; - } - } - - /// Field number for the "repeated_duration" field. - public const int RepeatedDurationFieldNumber = 311; - private static readonly pb::FieldCodec _repeated_repeatedDuration_codec - = pb::FieldCodec.ForMessage(2490, global::Google.Protobuf.WellKnownTypes.Duration.Parser); - private readonly pbc::RepeatedField repeatedDuration_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedDuration { - get { return repeatedDuration_; } - } - - /// Field number for the "repeated_timestamp" field. - public const int RepeatedTimestampFieldNumber = 312; - private static readonly pb::FieldCodec _repeated_repeatedTimestamp_codec - = pb::FieldCodec.ForMessage(2498, global::Google.Protobuf.WellKnownTypes.Timestamp.Parser); - private readonly pbc::RepeatedField repeatedTimestamp_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedTimestamp { - get { return repeatedTimestamp_; } - } - - /// Field number for the "repeated_fieldmask" field. - public const int RepeatedFieldmaskFieldNumber = 313; - private static readonly pb::FieldCodec _repeated_repeatedFieldmask_codec - = pb::FieldCodec.ForMessage(2506, global::Google.Protobuf.WellKnownTypes.FieldMask.Parser); - private readonly pbc::RepeatedField repeatedFieldmask_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedFieldmask { - get { return repeatedFieldmask_; } - } - - /// Field number for the "repeated_struct" field. - public const int RepeatedStructFieldNumber = 324; - private static readonly pb::FieldCodec _repeated_repeatedStruct_codec - = pb::FieldCodec.ForMessage(2594, global::Google.Protobuf.WellKnownTypes.Struct.Parser); - private readonly pbc::RepeatedField repeatedStruct_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedStruct { - get { return repeatedStruct_; } - } - - /// Field number for the "repeated_any" field. - public const int RepeatedAnyFieldNumber = 315; - private static readonly pb::FieldCodec _repeated_repeatedAny_codec - = pb::FieldCodec.ForMessage(2522, global::Google.Protobuf.WellKnownTypes.Any.Parser); - private readonly pbc::RepeatedField repeatedAny_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedAny { - get { return repeatedAny_; } - } - - /// Field number for the "repeated_value" field. - public const int RepeatedValueFieldNumber = 316; - private static readonly pb::FieldCodec _repeated_repeatedValue_codec - = pb::FieldCodec.ForMessage(2530, global::Google.Protobuf.WellKnownTypes.Value.Parser); - private readonly pbc::RepeatedField repeatedValue_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedValue { - get { return repeatedValue_; } - } - - /// Field number for the "fieldname1" field. - public const int Fieldname1FieldNumber = 401; - private int fieldname1_; - /// - /// Test field-name-to-JSON-name convention. - /// (protobuf says names can be any valid C/C++ identifier.) - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Fieldname1 { - get { return fieldname1_; } - set { - fieldname1_ = value; - } - } - - /// Field number for the "field_name2" field. - public const int FieldName2FieldNumber = 402; - private int fieldName2_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FieldName2 { - get { return fieldName2_; } - set { - fieldName2_ = value; - } - } - - /// Field number for the "_field_name3" field. - public const int FieldName3FieldNumber = 403; - private int FieldName3_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FieldName3 { - get { return FieldName3_; } - set { - FieldName3_ = value; - } - } - - /// Field number for the "field__name4_" field. - public const int FieldName4FieldNumber = 404; - private int fieldName4_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FieldName4 { - get { return fieldName4_; } - set { - fieldName4_ = value; - } - } - - /// Field number for the "field0name5" field. - public const int Field0Name5FieldNumber = 405; - private int field0Name5_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Field0Name5 { - get { return field0Name5_; } - set { - field0Name5_ = value; - } - } - - /// Field number for the "field_0_name6" field. - public const int Field0Name6FieldNumber = 406; - private int field0Name6_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Field0Name6 { - get { return field0Name6_; } - set { - field0Name6_ = value; - } - } - - /// Field number for the "fieldName7" field. - public const int FieldName7FieldNumber = 407; - private int fieldName7_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FieldName7 { - get { return fieldName7_; } - set { - fieldName7_ = value; - } - } - - /// Field number for the "FieldName8" field. - public const int FieldName8FieldNumber = 408; - private int fieldName8_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FieldName8 { - get { return fieldName8_; } - set { - fieldName8_ = value; - } - } - - /// Field number for the "field_Name9" field. - public const int FieldName9FieldNumber = 409; - private int fieldName9_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FieldName9 { - get { return fieldName9_; } - set { - fieldName9_ = value; - } - } - - /// Field number for the "Field_Name10" field. - public const int FieldName10FieldNumber = 410; - private int fieldName10_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FieldName10 { - get { return fieldName10_; } - set { - fieldName10_ = value; - } - } - - /// Field number for the "FIELD_NAME11" field. - public const int FIELDNAME11FieldNumber = 411; - private int fIELDNAME11_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FIELDNAME11 { - get { return fIELDNAME11_; } - set { - fIELDNAME11_ = value; - } - } - - /// Field number for the "FIELD_name12" field. - public const int FIELDName12FieldNumber = 412; - private int fIELDName12_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FIELDName12 { - get { return fIELDName12_; } - set { - fIELDName12_ = value; - } - } - - /// Field number for the "__field_name13" field. - public const int FieldName13FieldNumber = 413; - private int FieldName13_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FieldName13 { - get { return FieldName13_; } - set { - FieldName13_ = value; - } - } - - /// Field number for the "__Field_name14" field. - public const int FieldName14FieldNumber = 414; - private int FieldName14_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FieldName14 { - get { return FieldName14_; } - set { - FieldName14_ = value; - } - } - - /// Field number for the "field__name15" field. - public const int FieldName15FieldNumber = 415; - private int fieldName15_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FieldName15 { - get { return fieldName15_; } - set { - fieldName15_ = value; - } - } - - /// Field number for the "field__Name16" field. - public const int FieldName16FieldNumber = 416; - private int fieldName16_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FieldName16 { - get { return fieldName16_; } - set { - fieldName16_ = value; - } - } - - /// Field number for the "field_name17__" field. - public const int FieldName17FieldNumber = 417; - private int fieldName17_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FieldName17 { - get { return fieldName17_; } - set { - fieldName17_ = value; - } - } - - /// Field number for the "Field_name18__" field. - public const int FieldName18FieldNumber = 418; - private int fieldName18_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FieldName18 { - get { return fieldName18_; } - set { - fieldName18_ = value; - } - } - - private object oneofField_; - /// Enum of possible cases for the "oneof_field" oneof. - public enum OneofFieldOneofCase { - None = 0, - OneofUint32 = 111, - OneofNestedMessage = 112, - OneofString = 113, - OneofBytes = 114, - OneofBool = 115, - OneofUint64 = 116, - OneofFloat = 117, - OneofDouble = 118, - OneofEnum = 119, - } - private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public OneofFieldOneofCase OneofFieldCase { - get { return oneofFieldCase_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void ClearOneofField() { - oneofFieldCase_ = OneofFieldOneofCase.None; - oneofField_ = null; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestAllTypesProto3); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestAllTypesProto3 other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (OptionalInt32 != other.OptionalInt32) return false; - if (OptionalInt64 != other.OptionalInt64) return false; - if (OptionalUint32 != other.OptionalUint32) return false; - if (OptionalUint64 != other.OptionalUint64) return false; - if (OptionalSint32 != other.OptionalSint32) return false; - if (OptionalSint64 != other.OptionalSint64) return false; - if (OptionalFixed32 != other.OptionalFixed32) return false; - if (OptionalFixed64 != other.OptionalFixed64) return false; - if (OptionalSfixed32 != other.OptionalSfixed32) return false; - if (OptionalSfixed64 != other.OptionalSfixed64) return false; - if (OptionalFloat != other.OptionalFloat) return false; - if (OptionalDouble != other.OptionalDouble) return false; - if (OptionalBool != other.OptionalBool) return false; - if (OptionalString != other.OptionalString) return false; - if (OptionalBytes != other.OptionalBytes) return false; - if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false; - if (!object.Equals(OptionalForeignMessage, other.OptionalForeignMessage)) return false; - if (OptionalNestedEnum != other.OptionalNestedEnum) return false; - if (OptionalForeignEnum != other.OptionalForeignEnum) return false; - if (OptionalStringPiece != other.OptionalStringPiece) return false; - if (OptionalCord != other.OptionalCord) return false; - if (!object.Equals(RecursiveMessage, other.RecursiveMessage)) return false; - if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false; - if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false; - if(!repeatedUint32_.Equals(other.repeatedUint32_)) return false; - if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false; - if(!repeatedSint32_.Equals(other.repeatedSint32_)) return false; - if(!repeatedSint64_.Equals(other.repeatedSint64_)) return false; - if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false; - if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false; - if(!repeatedSfixed32_.Equals(other.repeatedSfixed32_)) return false; - if(!repeatedSfixed64_.Equals(other.repeatedSfixed64_)) return false; - if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false; - if(!repeatedDouble_.Equals(other.repeatedDouble_)) return false; - if(!repeatedBool_.Equals(other.repeatedBool_)) return false; - if(!repeatedString_.Equals(other.repeatedString_)) return false; - if(!repeatedBytes_.Equals(other.repeatedBytes_)) return false; - if(!repeatedNestedMessage_.Equals(other.repeatedNestedMessage_)) return false; - if(!repeatedForeignMessage_.Equals(other.repeatedForeignMessage_)) return false; - if(!repeatedNestedEnum_.Equals(other.repeatedNestedEnum_)) return false; - if(!repeatedForeignEnum_.Equals(other.repeatedForeignEnum_)) return false; - if(!repeatedStringPiece_.Equals(other.repeatedStringPiece_)) return false; - if(!repeatedCord_.Equals(other.repeatedCord_)) return false; - if (!MapInt32Int32.Equals(other.MapInt32Int32)) return false; - if (!MapInt64Int64.Equals(other.MapInt64Int64)) return false; - if (!MapUint32Uint32.Equals(other.MapUint32Uint32)) return false; - if (!MapUint64Uint64.Equals(other.MapUint64Uint64)) return false; - if (!MapSint32Sint32.Equals(other.MapSint32Sint32)) return false; - if (!MapSint64Sint64.Equals(other.MapSint64Sint64)) return false; - if (!MapFixed32Fixed32.Equals(other.MapFixed32Fixed32)) return false; - if (!MapFixed64Fixed64.Equals(other.MapFixed64Fixed64)) return false; - if (!MapSfixed32Sfixed32.Equals(other.MapSfixed32Sfixed32)) return false; - if (!MapSfixed64Sfixed64.Equals(other.MapSfixed64Sfixed64)) return false; - if (!MapInt32Float.Equals(other.MapInt32Float)) return false; - if (!MapInt32Double.Equals(other.MapInt32Double)) return false; - if (!MapBoolBool.Equals(other.MapBoolBool)) return false; - if (!MapStringString.Equals(other.MapStringString)) return false; - if (!MapStringBytes.Equals(other.MapStringBytes)) return false; - if (!MapStringNestedMessage.Equals(other.MapStringNestedMessage)) return false; - if (!MapStringForeignMessage.Equals(other.MapStringForeignMessage)) return false; - if (!MapStringNestedEnum.Equals(other.MapStringNestedEnum)) return false; - if (!MapStringForeignEnum.Equals(other.MapStringForeignEnum)) return false; - if (OneofUint32 != other.OneofUint32) return false; - if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false; - if (OneofString != other.OneofString) return false; - if (OneofBytes != other.OneofBytes) return false; - if (OneofBool != other.OneofBool) return false; - if (OneofUint64 != other.OneofUint64) return false; - if (OneofFloat != other.OneofFloat) return false; - if (OneofDouble != other.OneofDouble) return false; - if (OneofEnum != other.OneofEnum) return false; - if (OptionalBoolWrapper != other.OptionalBoolWrapper) return false; - if (OptionalInt32Wrapper != other.OptionalInt32Wrapper) return false; - if (OptionalInt64Wrapper != other.OptionalInt64Wrapper) return false; - if (OptionalUint32Wrapper != other.OptionalUint32Wrapper) return false; - if (OptionalUint64Wrapper != other.OptionalUint64Wrapper) return false; - if (OptionalFloatWrapper != other.OptionalFloatWrapper) return false; - if (OptionalDoubleWrapper != other.OptionalDoubleWrapper) return false; - if (OptionalStringWrapper != other.OptionalStringWrapper) return false; - if (OptionalBytesWrapper != other.OptionalBytesWrapper) return false; - if(!repeatedBoolWrapper_.Equals(other.repeatedBoolWrapper_)) return false; - if(!repeatedInt32Wrapper_.Equals(other.repeatedInt32Wrapper_)) return false; - if(!repeatedInt64Wrapper_.Equals(other.repeatedInt64Wrapper_)) return false; - if(!repeatedUint32Wrapper_.Equals(other.repeatedUint32Wrapper_)) return false; - if(!repeatedUint64Wrapper_.Equals(other.repeatedUint64Wrapper_)) return false; - if(!repeatedFloatWrapper_.Equals(other.repeatedFloatWrapper_)) return false; - if(!repeatedDoubleWrapper_.Equals(other.repeatedDoubleWrapper_)) return false; - if(!repeatedStringWrapper_.Equals(other.repeatedStringWrapper_)) return false; - if(!repeatedBytesWrapper_.Equals(other.repeatedBytesWrapper_)) return false; - if (!object.Equals(OptionalDuration, other.OptionalDuration)) return false; - if (!object.Equals(OptionalTimestamp, other.OptionalTimestamp)) return false; - if (!object.Equals(OptionalFieldMask, other.OptionalFieldMask)) return false; - if (!object.Equals(OptionalStruct, other.OptionalStruct)) return false; - if (!object.Equals(OptionalAny, other.OptionalAny)) return false; - if (!object.Equals(OptionalValue, other.OptionalValue)) return false; - if(!repeatedDuration_.Equals(other.repeatedDuration_)) return false; - if(!repeatedTimestamp_.Equals(other.repeatedTimestamp_)) return false; - if(!repeatedFieldmask_.Equals(other.repeatedFieldmask_)) return false; - if(!repeatedStruct_.Equals(other.repeatedStruct_)) return false; - if(!repeatedAny_.Equals(other.repeatedAny_)) return false; - if(!repeatedValue_.Equals(other.repeatedValue_)) return false; - if (Fieldname1 != other.Fieldname1) return false; - if (FieldName2 != other.FieldName2) return false; - if (FieldName3 != other.FieldName3) return false; - if (FieldName4 != other.FieldName4) return false; - if (Field0Name5 != other.Field0Name5) return false; - if (Field0Name6 != other.Field0Name6) return false; - if (FieldName7 != other.FieldName7) return false; - if (FieldName8 != other.FieldName8) return false; - if (FieldName9 != other.FieldName9) return false; - if (FieldName10 != other.FieldName10) return false; - if (FIELDNAME11 != other.FIELDNAME11) return false; - if (FIELDName12 != other.FIELDName12) return false; - if (FieldName13 != other.FieldName13) return false; - if (FieldName14 != other.FieldName14) return false; - if (FieldName15 != other.FieldName15) return false; - if (FieldName16 != other.FieldName16) return false; - if (FieldName17 != other.FieldName17) return false; - if (FieldName18 != other.FieldName18) return false; - if (OneofFieldCase != other.OneofFieldCase) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (OptionalInt32 != 0) hash ^= OptionalInt32.GetHashCode(); - if (OptionalInt64 != 0L) hash ^= OptionalInt64.GetHashCode(); - if (OptionalUint32 != 0) hash ^= OptionalUint32.GetHashCode(); - if (OptionalUint64 != 0UL) hash ^= OptionalUint64.GetHashCode(); - if (OptionalSint32 != 0) hash ^= OptionalSint32.GetHashCode(); - if (OptionalSint64 != 0L) hash ^= OptionalSint64.GetHashCode(); - if (OptionalFixed32 != 0) hash ^= OptionalFixed32.GetHashCode(); - if (OptionalFixed64 != 0UL) hash ^= OptionalFixed64.GetHashCode(); - if (OptionalSfixed32 != 0) hash ^= OptionalSfixed32.GetHashCode(); - if (OptionalSfixed64 != 0L) hash ^= OptionalSfixed64.GetHashCode(); - if (OptionalFloat != 0F) hash ^= OptionalFloat.GetHashCode(); - if (OptionalDouble != 0D) hash ^= OptionalDouble.GetHashCode(); - if (OptionalBool != false) hash ^= OptionalBool.GetHashCode(); - if (OptionalString.Length != 0) hash ^= OptionalString.GetHashCode(); - if (OptionalBytes.Length != 0) hash ^= OptionalBytes.GetHashCode(); - if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode(); - if (optionalForeignMessage_ != null) hash ^= OptionalForeignMessage.GetHashCode(); - if (OptionalNestedEnum != 0) hash ^= OptionalNestedEnum.GetHashCode(); - if (OptionalForeignEnum != 0) hash ^= OptionalForeignEnum.GetHashCode(); - if (OptionalStringPiece.Length != 0) hash ^= OptionalStringPiece.GetHashCode(); - if (OptionalCord.Length != 0) hash ^= OptionalCord.GetHashCode(); - if (recursiveMessage_ != null) hash ^= RecursiveMessage.GetHashCode(); - hash ^= repeatedInt32_.GetHashCode(); - hash ^= repeatedInt64_.GetHashCode(); - hash ^= repeatedUint32_.GetHashCode(); - hash ^= repeatedUint64_.GetHashCode(); - hash ^= repeatedSint32_.GetHashCode(); - hash ^= repeatedSint64_.GetHashCode(); - hash ^= repeatedFixed32_.GetHashCode(); - hash ^= repeatedFixed64_.GetHashCode(); - hash ^= repeatedSfixed32_.GetHashCode(); - hash ^= repeatedSfixed64_.GetHashCode(); - hash ^= repeatedFloat_.GetHashCode(); - hash ^= repeatedDouble_.GetHashCode(); - hash ^= repeatedBool_.GetHashCode(); - hash ^= repeatedString_.GetHashCode(); - hash ^= repeatedBytes_.GetHashCode(); - hash ^= repeatedNestedMessage_.GetHashCode(); - hash ^= repeatedForeignMessage_.GetHashCode(); - hash ^= repeatedNestedEnum_.GetHashCode(); - hash ^= repeatedForeignEnum_.GetHashCode(); - hash ^= repeatedStringPiece_.GetHashCode(); - hash ^= repeatedCord_.GetHashCode(); - hash ^= MapInt32Int32.GetHashCode(); - hash ^= MapInt64Int64.GetHashCode(); - hash ^= MapUint32Uint32.GetHashCode(); - hash ^= MapUint64Uint64.GetHashCode(); - hash ^= MapSint32Sint32.GetHashCode(); - hash ^= MapSint64Sint64.GetHashCode(); - hash ^= MapFixed32Fixed32.GetHashCode(); - hash ^= MapFixed64Fixed64.GetHashCode(); - hash ^= MapSfixed32Sfixed32.GetHashCode(); - hash ^= MapSfixed64Sfixed64.GetHashCode(); - hash ^= MapInt32Float.GetHashCode(); - hash ^= MapInt32Double.GetHashCode(); - hash ^= MapBoolBool.GetHashCode(); - hash ^= MapStringString.GetHashCode(); - hash ^= MapStringBytes.GetHashCode(); - hash ^= MapStringNestedMessage.GetHashCode(); - hash ^= MapStringForeignMessage.GetHashCode(); - hash ^= MapStringNestedEnum.GetHashCode(); - hash ^= MapStringForeignEnum.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) hash ^= OneofUint32.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) hash ^= OneofString.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) hash ^= OneofBytes.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofBool) hash ^= OneofBool.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint64) hash ^= OneofUint64.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) hash ^= OneofFloat.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) hash ^= OneofDouble.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) hash ^= OneofEnum.GetHashCode(); - if (optionalBoolWrapper_ != null) hash ^= OptionalBoolWrapper.GetHashCode(); - if (optionalInt32Wrapper_ != null) hash ^= OptionalInt32Wrapper.GetHashCode(); - if (optionalInt64Wrapper_ != null) hash ^= OptionalInt64Wrapper.GetHashCode(); - if (optionalUint32Wrapper_ != null) hash ^= OptionalUint32Wrapper.GetHashCode(); - if (optionalUint64Wrapper_ != null) hash ^= OptionalUint64Wrapper.GetHashCode(); - if (optionalFloatWrapper_ != null) hash ^= OptionalFloatWrapper.GetHashCode(); - if (optionalDoubleWrapper_ != null) hash ^= OptionalDoubleWrapper.GetHashCode(); - if (optionalStringWrapper_ != null) hash ^= OptionalStringWrapper.GetHashCode(); - if (optionalBytesWrapper_ != null) hash ^= OptionalBytesWrapper.GetHashCode(); - hash ^= repeatedBoolWrapper_.GetHashCode(); - hash ^= repeatedInt32Wrapper_.GetHashCode(); - hash ^= repeatedInt64Wrapper_.GetHashCode(); - hash ^= repeatedUint32Wrapper_.GetHashCode(); - hash ^= repeatedUint64Wrapper_.GetHashCode(); - hash ^= repeatedFloatWrapper_.GetHashCode(); - hash ^= repeatedDoubleWrapper_.GetHashCode(); - hash ^= repeatedStringWrapper_.GetHashCode(); - hash ^= repeatedBytesWrapper_.GetHashCode(); - if (optionalDuration_ != null) hash ^= OptionalDuration.GetHashCode(); - if (optionalTimestamp_ != null) hash ^= OptionalTimestamp.GetHashCode(); - if (optionalFieldMask_ != null) hash ^= OptionalFieldMask.GetHashCode(); - if (optionalStruct_ != null) hash ^= OptionalStruct.GetHashCode(); - if (optionalAny_ != null) hash ^= OptionalAny.GetHashCode(); - if (optionalValue_ != null) hash ^= OptionalValue.GetHashCode(); - hash ^= repeatedDuration_.GetHashCode(); - hash ^= repeatedTimestamp_.GetHashCode(); - hash ^= repeatedFieldmask_.GetHashCode(); - hash ^= repeatedStruct_.GetHashCode(); - hash ^= repeatedAny_.GetHashCode(); - hash ^= repeatedValue_.GetHashCode(); - if (Fieldname1 != 0) hash ^= Fieldname1.GetHashCode(); - if (FieldName2 != 0) hash ^= FieldName2.GetHashCode(); - if (FieldName3 != 0) hash ^= FieldName3.GetHashCode(); - if (FieldName4 != 0) hash ^= FieldName4.GetHashCode(); - if (Field0Name5 != 0) hash ^= Field0Name5.GetHashCode(); - if (Field0Name6 != 0) hash ^= Field0Name6.GetHashCode(); - if (FieldName7 != 0) hash ^= FieldName7.GetHashCode(); - if (FieldName8 != 0) hash ^= FieldName8.GetHashCode(); - if (FieldName9 != 0) hash ^= FieldName9.GetHashCode(); - if (FieldName10 != 0) hash ^= FieldName10.GetHashCode(); - if (FIELDNAME11 != 0) hash ^= FIELDNAME11.GetHashCode(); - if (FIELDName12 != 0) hash ^= FIELDName12.GetHashCode(); - if (FieldName13 != 0) hash ^= FieldName13.GetHashCode(); - if (FieldName14 != 0) hash ^= FieldName14.GetHashCode(); - if (FieldName15 != 0) hash ^= FieldName15.GetHashCode(); - if (FieldName16 != 0) hash ^= FieldName16.GetHashCode(); - if (FieldName17 != 0) hash ^= FieldName17.GetHashCode(); - if (FieldName18 != 0) hash ^= FieldName18.GetHashCode(); - hash ^= (int) oneofFieldCase_; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (OptionalInt32 != 0) { - output.WriteRawTag(8); - output.WriteInt32(OptionalInt32); - } - if (OptionalInt64 != 0L) { - output.WriteRawTag(16); - output.WriteInt64(OptionalInt64); - } - if (OptionalUint32 != 0) { - output.WriteRawTag(24); - output.WriteUInt32(OptionalUint32); - } - if (OptionalUint64 != 0UL) { - output.WriteRawTag(32); - output.WriteUInt64(OptionalUint64); - } - if (OptionalSint32 != 0) { - output.WriteRawTag(40); - output.WriteSInt32(OptionalSint32); - } - if (OptionalSint64 != 0L) { - output.WriteRawTag(48); - output.WriteSInt64(OptionalSint64); - } - if (OptionalFixed32 != 0) { - output.WriteRawTag(61); - output.WriteFixed32(OptionalFixed32); - } - if (OptionalFixed64 != 0UL) { - output.WriteRawTag(65); - output.WriteFixed64(OptionalFixed64); - } - if (OptionalSfixed32 != 0) { - output.WriteRawTag(77); - output.WriteSFixed32(OptionalSfixed32); - } - if (OptionalSfixed64 != 0L) { - output.WriteRawTag(81); - output.WriteSFixed64(OptionalSfixed64); - } - if (OptionalFloat != 0F) { - output.WriteRawTag(93); - output.WriteFloat(OptionalFloat); - } - if (OptionalDouble != 0D) { - output.WriteRawTag(97); - output.WriteDouble(OptionalDouble); - } - if (OptionalBool != false) { - output.WriteRawTag(104); - output.WriteBool(OptionalBool); - } - if (OptionalString.Length != 0) { - output.WriteRawTag(114); - output.WriteString(OptionalString); - } - if (OptionalBytes.Length != 0) { - output.WriteRawTag(122); - output.WriteBytes(OptionalBytes); - } - if (optionalNestedMessage_ != null) { - output.WriteRawTag(146, 1); - output.WriteMessage(OptionalNestedMessage); - } - if (optionalForeignMessage_ != null) { - output.WriteRawTag(154, 1); - output.WriteMessage(OptionalForeignMessage); - } - if (OptionalNestedEnum != 0) { - output.WriteRawTag(168, 1); - output.WriteEnum((int) OptionalNestedEnum); - } - if (OptionalForeignEnum != 0) { - output.WriteRawTag(176, 1); - output.WriteEnum((int) OptionalForeignEnum); - } - if (OptionalStringPiece.Length != 0) { - output.WriteRawTag(194, 1); - output.WriteString(OptionalStringPiece); - } - if (OptionalCord.Length != 0) { - output.WriteRawTag(202, 1); - output.WriteString(OptionalCord); - } - if (recursiveMessage_ != null) { - output.WriteRawTag(218, 1); - output.WriteMessage(RecursiveMessage); - } - repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec); - repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec); - repeatedUint32_.WriteTo(output, _repeated_repeatedUint32_codec); - repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec); - repeatedSint32_.WriteTo(output, _repeated_repeatedSint32_codec); - repeatedSint64_.WriteTo(output, _repeated_repeatedSint64_codec); - repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec); - repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec); - repeatedSfixed32_.WriteTo(output, _repeated_repeatedSfixed32_codec); - repeatedSfixed64_.WriteTo(output, _repeated_repeatedSfixed64_codec); - repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec); - repeatedDouble_.WriteTo(output, _repeated_repeatedDouble_codec); - repeatedBool_.WriteTo(output, _repeated_repeatedBool_codec); - repeatedString_.WriteTo(output, _repeated_repeatedString_codec); - repeatedBytes_.WriteTo(output, _repeated_repeatedBytes_codec); - repeatedNestedMessage_.WriteTo(output, _repeated_repeatedNestedMessage_codec); - repeatedForeignMessage_.WriteTo(output, _repeated_repeatedForeignMessage_codec); - repeatedNestedEnum_.WriteTo(output, _repeated_repeatedNestedEnum_codec); - repeatedForeignEnum_.WriteTo(output, _repeated_repeatedForeignEnum_codec); - repeatedStringPiece_.WriteTo(output, _repeated_repeatedStringPiece_codec); - repeatedCord_.WriteTo(output, _repeated_repeatedCord_codec); - mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec); - mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec); - mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec); - mapUint64Uint64_.WriteTo(output, _map_mapUint64Uint64_codec); - mapSint32Sint32_.WriteTo(output, _map_mapSint32Sint32_codec); - mapSint64Sint64_.WriteTo(output, _map_mapSint64Sint64_codec); - mapFixed32Fixed32_.WriteTo(output, _map_mapFixed32Fixed32_codec); - mapFixed64Fixed64_.WriteTo(output, _map_mapFixed64Fixed64_codec); - mapSfixed32Sfixed32_.WriteTo(output, _map_mapSfixed32Sfixed32_codec); - mapSfixed64Sfixed64_.WriteTo(output, _map_mapSfixed64Sfixed64_codec); - mapInt32Float_.WriteTo(output, _map_mapInt32Float_codec); - mapInt32Double_.WriteTo(output, _map_mapInt32Double_codec); - mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec); - mapStringString_.WriteTo(output, _map_mapStringString_codec); - mapStringBytes_.WriteTo(output, _map_mapStringBytes_codec); - mapStringNestedMessage_.WriteTo(output, _map_mapStringNestedMessage_codec); - mapStringForeignMessage_.WriteTo(output, _map_mapStringForeignMessage_codec); - mapStringNestedEnum_.WriteTo(output, _map_mapStringNestedEnum_codec); - mapStringForeignEnum_.WriteTo(output, _map_mapStringForeignEnum_codec); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { - output.WriteRawTag(248, 6); - output.WriteUInt32(OneofUint32); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { - output.WriteRawTag(130, 7); - output.WriteMessage(OneofNestedMessage); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { - output.WriteRawTag(138, 7); - output.WriteString(OneofString); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { - output.WriteRawTag(146, 7); - output.WriteBytes(OneofBytes); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofBool) { - output.WriteRawTag(152, 7); - output.WriteBool(OneofBool); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint64) { - output.WriteRawTag(160, 7); - output.WriteUInt64(OneofUint64); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) { - output.WriteRawTag(173, 7); - output.WriteFloat(OneofFloat); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) { - output.WriteRawTag(177, 7); - output.WriteDouble(OneofDouble); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) { - output.WriteRawTag(184, 7); - output.WriteEnum((int) OneofEnum); - } - if (optionalBoolWrapper_ != null) { - _single_optionalBoolWrapper_codec.WriteTagAndValue(output, OptionalBoolWrapper); - } - if (optionalInt32Wrapper_ != null) { - _single_optionalInt32Wrapper_codec.WriteTagAndValue(output, OptionalInt32Wrapper); - } - if (optionalInt64Wrapper_ != null) { - _single_optionalInt64Wrapper_codec.WriteTagAndValue(output, OptionalInt64Wrapper); - } - if (optionalUint32Wrapper_ != null) { - _single_optionalUint32Wrapper_codec.WriteTagAndValue(output, OptionalUint32Wrapper); - } - if (optionalUint64Wrapper_ != null) { - _single_optionalUint64Wrapper_codec.WriteTagAndValue(output, OptionalUint64Wrapper); - } - if (optionalFloatWrapper_ != null) { - _single_optionalFloatWrapper_codec.WriteTagAndValue(output, OptionalFloatWrapper); - } - if (optionalDoubleWrapper_ != null) { - _single_optionalDoubleWrapper_codec.WriteTagAndValue(output, OptionalDoubleWrapper); - } - if (optionalStringWrapper_ != null) { - _single_optionalStringWrapper_codec.WriteTagAndValue(output, OptionalStringWrapper); - } - if (optionalBytesWrapper_ != null) { - _single_optionalBytesWrapper_codec.WriteTagAndValue(output, OptionalBytesWrapper); - } - repeatedBoolWrapper_.WriteTo(output, _repeated_repeatedBoolWrapper_codec); - repeatedInt32Wrapper_.WriteTo(output, _repeated_repeatedInt32Wrapper_codec); - repeatedInt64Wrapper_.WriteTo(output, _repeated_repeatedInt64Wrapper_codec); - repeatedUint32Wrapper_.WriteTo(output, _repeated_repeatedUint32Wrapper_codec); - repeatedUint64Wrapper_.WriteTo(output, _repeated_repeatedUint64Wrapper_codec); - repeatedFloatWrapper_.WriteTo(output, _repeated_repeatedFloatWrapper_codec); - repeatedDoubleWrapper_.WriteTo(output, _repeated_repeatedDoubleWrapper_codec); - repeatedStringWrapper_.WriteTo(output, _repeated_repeatedStringWrapper_codec); - repeatedBytesWrapper_.WriteTo(output, _repeated_repeatedBytesWrapper_codec); - if (optionalDuration_ != null) { - output.WriteRawTag(234, 18); - output.WriteMessage(OptionalDuration); - } - if (optionalTimestamp_ != null) { - output.WriteRawTag(242, 18); - output.WriteMessage(OptionalTimestamp); - } - if (optionalFieldMask_ != null) { - output.WriteRawTag(250, 18); - output.WriteMessage(OptionalFieldMask); - } - if (optionalStruct_ != null) { - output.WriteRawTag(130, 19); - output.WriteMessage(OptionalStruct); - } - if (optionalAny_ != null) { - output.WriteRawTag(138, 19); - output.WriteMessage(OptionalAny); - } - if (optionalValue_ != null) { - output.WriteRawTag(146, 19); - output.WriteMessage(OptionalValue); - } - repeatedDuration_.WriteTo(output, _repeated_repeatedDuration_codec); - repeatedTimestamp_.WriteTo(output, _repeated_repeatedTimestamp_codec); - repeatedFieldmask_.WriteTo(output, _repeated_repeatedFieldmask_codec); - repeatedAny_.WriteTo(output, _repeated_repeatedAny_codec); - repeatedValue_.WriteTo(output, _repeated_repeatedValue_codec); - repeatedStruct_.WriteTo(output, _repeated_repeatedStruct_codec); - if (Fieldname1 != 0) { - output.WriteRawTag(136, 25); - output.WriteInt32(Fieldname1); - } - if (FieldName2 != 0) { - output.WriteRawTag(144, 25); - output.WriteInt32(FieldName2); - } - if (FieldName3 != 0) { - output.WriteRawTag(152, 25); - output.WriteInt32(FieldName3); - } - if (FieldName4 != 0) { - output.WriteRawTag(160, 25); - output.WriteInt32(FieldName4); - } - if (Field0Name5 != 0) { - output.WriteRawTag(168, 25); - output.WriteInt32(Field0Name5); - } - if (Field0Name6 != 0) { - output.WriteRawTag(176, 25); - output.WriteInt32(Field0Name6); - } - if (FieldName7 != 0) { - output.WriteRawTag(184, 25); - output.WriteInt32(FieldName7); - } - if (FieldName8 != 0) { - output.WriteRawTag(192, 25); - output.WriteInt32(FieldName8); - } - if (FieldName9 != 0) { - output.WriteRawTag(200, 25); - output.WriteInt32(FieldName9); - } - if (FieldName10 != 0) { - output.WriteRawTag(208, 25); - output.WriteInt32(FieldName10); - } - if (FIELDNAME11 != 0) { - output.WriteRawTag(216, 25); - output.WriteInt32(FIELDNAME11); - } - if (FIELDName12 != 0) { - output.WriteRawTag(224, 25); - output.WriteInt32(FIELDName12); - } - if (FieldName13 != 0) { - output.WriteRawTag(232, 25); - output.WriteInt32(FieldName13); - } - if (FieldName14 != 0) { - output.WriteRawTag(240, 25); - output.WriteInt32(FieldName14); - } - if (FieldName15 != 0) { - output.WriteRawTag(248, 25); - output.WriteInt32(FieldName15); - } - if (FieldName16 != 0) { - output.WriteRawTag(128, 26); - output.WriteInt32(FieldName16); - } - if (FieldName17 != 0) { - output.WriteRawTag(136, 26); - output.WriteInt32(FieldName17); - } - if (FieldName18 != 0) { - output.WriteRawTag(144, 26); - output.WriteInt32(FieldName18); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (OptionalInt32 != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32); - } - if (OptionalInt64 != 0L) { - size += 1 + pb::CodedOutputStream.ComputeInt64Size(OptionalInt64); - } - if (OptionalUint32 != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(OptionalUint32); - } - if (OptionalUint64 != 0UL) { - size += 1 + pb::CodedOutputStream.ComputeUInt64Size(OptionalUint64); - } - if (OptionalSint32 != 0) { - size += 1 + pb::CodedOutputStream.ComputeSInt32Size(OptionalSint32); - } - if (OptionalSint64 != 0L) { - size += 1 + pb::CodedOutputStream.ComputeSInt64Size(OptionalSint64); - } - if (OptionalFixed32 != 0) { - size += 1 + 4; - } - if (OptionalFixed64 != 0UL) { - size += 1 + 8; - } - if (OptionalSfixed32 != 0) { - size += 1 + 4; - } - if (OptionalSfixed64 != 0L) { - size += 1 + 8; - } - if (OptionalFloat != 0F) { - size += 1 + 4; - } - if (OptionalDouble != 0D) { - size += 1 + 8; - } - if (OptionalBool != false) { - size += 1 + 1; - } - if (OptionalString.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(OptionalString); - } - if (OptionalBytes.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(OptionalBytes); - } - if (optionalNestedMessage_ != null) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage); - } - if (optionalForeignMessage_ != null) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalForeignMessage); - } - if (OptionalNestedEnum != 0) { - size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalNestedEnum); - } - if (OptionalForeignEnum != 0) { - size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalForeignEnum); - } - if (OptionalStringPiece.Length != 0) { - size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalStringPiece); - } - if (OptionalCord.Length != 0) { - size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalCord); - } - if (recursiveMessage_ != null) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(RecursiveMessage); - } - size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec); - size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec); - size += repeatedUint32_.CalculateSize(_repeated_repeatedUint32_codec); - size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec); - size += repeatedSint32_.CalculateSize(_repeated_repeatedSint32_codec); - size += repeatedSint64_.CalculateSize(_repeated_repeatedSint64_codec); - size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec); - size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec); - size += repeatedSfixed32_.CalculateSize(_repeated_repeatedSfixed32_codec); - size += repeatedSfixed64_.CalculateSize(_repeated_repeatedSfixed64_codec); - size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec); - size += repeatedDouble_.CalculateSize(_repeated_repeatedDouble_codec); - size += repeatedBool_.CalculateSize(_repeated_repeatedBool_codec); - size += repeatedString_.CalculateSize(_repeated_repeatedString_codec); - size += repeatedBytes_.CalculateSize(_repeated_repeatedBytes_codec); - size += repeatedNestedMessage_.CalculateSize(_repeated_repeatedNestedMessage_codec); - size += repeatedForeignMessage_.CalculateSize(_repeated_repeatedForeignMessage_codec); - size += repeatedNestedEnum_.CalculateSize(_repeated_repeatedNestedEnum_codec); - size += repeatedForeignEnum_.CalculateSize(_repeated_repeatedForeignEnum_codec); - size += repeatedStringPiece_.CalculateSize(_repeated_repeatedStringPiece_codec); - size += repeatedCord_.CalculateSize(_repeated_repeatedCord_codec); - size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec); - size += mapInt64Int64_.CalculateSize(_map_mapInt64Int64_codec); - size += mapUint32Uint32_.CalculateSize(_map_mapUint32Uint32_codec); - size += mapUint64Uint64_.CalculateSize(_map_mapUint64Uint64_codec); - size += mapSint32Sint32_.CalculateSize(_map_mapSint32Sint32_codec); - size += mapSint64Sint64_.CalculateSize(_map_mapSint64Sint64_codec); - size += mapFixed32Fixed32_.CalculateSize(_map_mapFixed32Fixed32_codec); - size += mapFixed64Fixed64_.CalculateSize(_map_mapFixed64Fixed64_codec); - size += mapSfixed32Sfixed32_.CalculateSize(_map_mapSfixed32Sfixed32_codec); - size += mapSfixed64Sfixed64_.CalculateSize(_map_mapSfixed64Sfixed64_codec); - size += mapInt32Float_.CalculateSize(_map_mapInt32Float_codec); - size += mapInt32Double_.CalculateSize(_map_mapInt32Double_codec); - size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec); - size += mapStringString_.CalculateSize(_map_mapStringString_codec); - size += mapStringBytes_.CalculateSize(_map_mapStringBytes_codec); - size += mapStringNestedMessage_.CalculateSize(_map_mapStringNestedMessage_codec); - size += mapStringForeignMessage_.CalculateSize(_map_mapStringForeignMessage_codec); - size += mapStringNestedEnum_.CalculateSize(_map_mapStringNestedEnum_codec); - size += mapStringForeignEnum_.CalculateSize(_map_mapStringForeignEnum_codec); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { - size += 2 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(OneofNestedMessage); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { - size += 2 + pb::CodedOutputStream.ComputeStringSize(OneofString); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { - size += 2 + pb::CodedOutputStream.ComputeBytesSize(OneofBytes); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofBool) { - size += 2 + 1; - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint64) { - size += 2 + pb::CodedOutputStream.ComputeUInt64Size(OneofUint64); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) { - size += 2 + 4; - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) { - size += 2 + 8; - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) { - size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OneofEnum); - } - if (optionalBoolWrapper_ != null) { - size += _single_optionalBoolWrapper_codec.CalculateSizeWithTag(OptionalBoolWrapper); - } - if (optionalInt32Wrapper_ != null) { - size += _single_optionalInt32Wrapper_codec.CalculateSizeWithTag(OptionalInt32Wrapper); - } - if (optionalInt64Wrapper_ != null) { - size += _single_optionalInt64Wrapper_codec.CalculateSizeWithTag(OptionalInt64Wrapper); - } - if (optionalUint32Wrapper_ != null) { - size += _single_optionalUint32Wrapper_codec.CalculateSizeWithTag(OptionalUint32Wrapper); - } - if (optionalUint64Wrapper_ != null) { - size += _single_optionalUint64Wrapper_codec.CalculateSizeWithTag(OptionalUint64Wrapper); - } - if (optionalFloatWrapper_ != null) { - size += _single_optionalFloatWrapper_codec.CalculateSizeWithTag(OptionalFloatWrapper); - } - if (optionalDoubleWrapper_ != null) { - size += _single_optionalDoubleWrapper_codec.CalculateSizeWithTag(OptionalDoubleWrapper); - } - if (optionalStringWrapper_ != null) { - size += _single_optionalStringWrapper_codec.CalculateSizeWithTag(OptionalStringWrapper); - } - if (optionalBytesWrapper_ != null) { - size += _single_optionalBytesWrapper_codec.CalculateSizeWithTag(OptionalBytesWrapper); - } - size += repeatedBoolWrapper_.CalculateSize(_repeated_repeatedBoolWrapper_codec); - size += repeatedInt32Wrapper_.CalculateSize(_repeated_repeatedInt32Wrapper_codec); - size += repeatedInt64Wrapper_.CalculateSize(_repeated_repeatedInt64Wrapper_codec); - size += repeatedUint32Wrapper_.CalculateSize(_repeated_repeatedUint32Wrapper_codec); - size += repeatedUint64Wrapper_.CalculateSize(_repeated_repeatedUint64Wrapper_codec); - size += repeatedFloatWrapper_.CalculateSize(_repeated_repeatedFloatWrapper_codec); - size += repeatedDoubleWrapper_.CalculateSize(_repeated_repeatedDoubleWrapper_codec); - size += repeatedStringWrapper_.CalculateSize(_repeated_repeatedStringWrapper_codec); - size += repeatedBytesWrapper_.CalculateSize(_repeated_repeatedBytesWrapper_codec); - if (optionalDuration_ != null) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalDuration); - } - if (optionalTimestamp_ != null) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalTimestamp); - } - if (optionalFieldMask_ != null) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalFieldMask); - } - if (optionalStruct_ != null) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalStruct); - } - if (optionalAny_ != null) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalAny); - } - if (optionalValue_ != null) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalValue); - } - size += repeatedDuration_.CalculateSize(_repeated_repeatedDuration_codec); - size += repeatedTimestamp_.CalculateSize(_repeated_repeatedTimestamp_codec); - size += repeatedFieldmask_.CalculateSize(_repeated_repeatedFieldmask_codec); - size += repeatedStruct_.CalculateSize(_repeated_repeatedStruct_codec); - size += repeatedAny_.CalculateSize(_repeated_repeatedAny_codec); - size += repeatedValue_.CalculateSize(_repeated_repeatedValue_codec); - if (Fieldname1 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(Fieldname1); - } - if (FieldName2 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName2); - } - if (FieldName3 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName3); - } - if (FieldName4 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName4); - } - if (Field0Name5 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field0Name5); - } - if (Field0Name6 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field0Name6); - } - if (FieldName7 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName7); - } - if (FieldName8 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName8); - } - if (FieldName9 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName9); - } - if (FieldName10 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName10); - } - if (FIELDNAME11 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FIELDNAME11); - } - if (FIELDName12 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FIELDName12); - } - if (FieldName13 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName13); - } - if (FieldName14 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName14); - } - if (FieldName15 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName15); - } - if (FieldName16 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName16); - } - if (FieldName17 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName17); - } - if (FieldName18 != 0) { - size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName18); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestAllTypesProto3 other) { - if (other == null) { - return; - } - if (other.OptionalInt32 != 0) { - OptionalInt32 = other.OptionalInt32; - } - if (other.OptionalInt64 != 0L) { - OptionalInt64 = other.OptionalInt64; - } - if (other.OptionalUint32 != 0) { - OptionalUint32 = other.OptionalUint32; - } - if (other.OptionalUint64 != 0UL) { - OptionalUint64 = other.OptionalUint64; - } - if (other.OptionalSint32 != 0) { - OptionalSint32 = other.OptionalSint32; - } - if (other.OptionalSint64 != 0L) { - OptionalSint64 = other.OptionalSint64; - } - if (other.OptionalFixed32 != 0) { - OptionalFixed32 = other.OptionalFixed32; - } - if (other.OptionalFixed64 != 0UL) { - OptionalFixed64 = other.OptionalFixed64; - } - if (other.OptionalSfixed32 != 0) { - OptionalSfixed32 = other.OptionalSfixed32; - } - if (other.OptionalSfixed64 != 0L) { - OptionalSfixed64 = other.OptionalSfixed64; - } - if (other.OptionalFloat != 0F) { - OptionalFloat = other.OptionalFloat; - } - if (other.OptionalDouble != 0D) { - OptionalDouble = other.OptionalDouble; - } - if (other.OptionalBool != false) { - OptionalBool = other.OptionalBool; - } - if (other.OptionalString.Length != 0) { - OptionalString = other.OptionalString; - } - if (other.OptionalBytes.Length != 0) { - OptionalBytes = other.OptionalBytes; - } - if (other.optionalNestedMessage_ != null) { - if (optionalNestedMessage_ == null) { - optionalNestedMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage(); - } - OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage); - } - if (other.optionalForeignMessage_ != null) { - if (optionalForeignMessage_ == null) { - optionalForeignMessage_ = new global::ProtobufTestMessages.Proto3.ForeignMessage(); - } - OptionalForeignMessage.MergeFrom(other.OptionalForeignMessage); - } - if (other.OptionalNestedEnum != 0) { - OptionalNestedEnum = other.OptionalNestedEnum; - } - if (other.OptionalForeignEnum != 0) { - OptionalForeignEnum = other.OptionalForeignEnum; - } - if (other.OptionalStringPiece.Length != 0) { - OptionalStringPiece = other.OptionalStringPiece; - } - if (other.OptionalCord.Length != 0) { - OptionalCord = other.OptionalCord; - } - if (other.recursiveMessage_ != null) { - if (recursiveMessage_ == null) { - recursiveMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3(); - } - RecursiveMessage.MergeFrom(other.RecursiveMessage); - } - repeatedInt32_.Add(other.repeatedInt32_); - repeatedInt64_.Add(other.repeatedInt64_); - repeatedUint32_.Add(other.repeatedUint32_); - repeatedUint64_.Add(other.repeatedUint64_); - repeatedSint32_.Add(other.repeatedSint32_); - repeatedSint64_.Add(other.repeatedSint64_); - repeatedFixed32_.Add(other.repeatedFixed32_); - repeatedFixed64_.Add(other.repeatedFixed64_); - repeatedSfixed32_.Add(other.repeatedSfixed32_); - repeatedSfixed64_.Add(other.repeatedSfixed64_); - repeatedFloat_.Add(other.repeatedFloat_); - repeatedDouble_.Add(other.repeatedDouble_); - repeatedBool_.Add(other.repeatedBool_); - repeatedString_.Add(other.repeatedString_); - repeatedBytes_.Add(other.repeatedBytes_); - repeatedNestedMessage_.Add(other.repeatedNestedMessage_); - repeatedForeignMessage_.Add(other.repeatedForeignMessage_); - repeatedNestedEnum_.Add(other.repeatedNestedEnum_); - repeatedForeignEnum_.Add(other.repeatedForeignEnum_); - repeatedStringPiece_.Add(other.repeatedStringPiece_); - repeatedCord_.Add(other.repeatedCord_); - mapInt32Int32_.Add(other.mapInt32Int32_); - mapInt64Int64_.Add(other.mapInt64Int64_); - mapUint32Uint32_.Add(other.mapUint32Uint32_); - mapUint64Uint64_.Add(other.mapUint64Uint64_); - mapSint32Sint32_.Add(other.mapSint32Sint32_); - mapSint64Sint64_.Add(other.mapSint64Sint64_); - mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_); - mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_); - mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_); - mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_); - mapInt32Float_.Add(other.mapInt32Float_); - mapInt32Double_.Add(other.mapInt32Double_); - mapBoolBool_.Add(other.mapBoolBool_); - mapStringString_.Add(other.mapStringString_); - mapStringBytes_.Add(other.mapStringBytes_); - mapStringNestedMessage_.Add(other.mapStringNestedMessage_); - mapStringForeignMessage_.Add(other.mapStringForeignMessage_); - mapStringNestedEnum_.Add(other.mapStringNestedEnum_); - mapStringForeignEnum_.Add(other.mapStringForeignEnum_); - if (other.optionalBoolWrapper_ != null) { - if (optionalBoolWrapper_ == null || other.OptionalBoolWrapper != false) { - OptionalBoolWrapper = other.OptionalBoolWrapper; - } - } - if (other.optionalInt32Wrapper_ != null) { - if (optionalInt32Wrapper_ == null || other.OptionalInt32Wrapper != 0) { - OptionalInt32Wrapper = other.OptionalInt32Wrapper; - } - } - if (other.optionalInt64Wrapper_ != null) { - if (optionalInt64Wrapper_ == null || other.OptionalInt64Wrapper != 0L) { - OptionalInt64Wrapper = other.OptionalInt64Wrapper; - } - } - if (other.optionalUint32Wrapper_ != null) { - if (optionalUint32Wrapper_ == null || other.OptionalUint32Wrapper != 0) { - OptionalUint32Wrapper = other.OptionalUint32Wrapper; - } - } - if (other.optionalUint64Wrapper_ != null) { - if (optionalUint64Wrapper_ == null || other.OptionalUint64Wrapper != 0UL) { - OptionalUint64Wrapper = other.OptionalUint64Wrapper; - } - } - if (other.optionalFloatWrapper_ != null) { - if (optionalFloatWrapper_ == null || other.OptionalFloatWrapper != 0F) { - OptionalFloatWrapper = other.OptionalFloatWrapper; - } - } - if (other.optionalDoubleWrapper_ != null) { - if (optionalDoubleWrapper_ == null || other.OptionalDoubleWrapper != 0D) { - OptionalDoubleWrapper = other.OptionalDoubleWrapper; - } - } - if (other.optionalStringWrapper_ != null) { - if (optionalStringWrapper_ == null || other.OptionalStringWrapper != "") { - OptionalStringWrapper = other.OptionalStringWrapper; - } - } - if (other.optionalBytesWrapper_ != null) { - if (optionalBytesWrapper_ == null || other.OptionalBytesWrapper != pb::ByteString.Empty) { - OptionalBytesWrapper = other.OptionalBytesWrapper; - } - } - repeatedBoolWrapper_.Add(other.repeatedBoolWrapper_); - repeatedInt32Wrapper_.Add(other.repeatedInt32Wrapper_); - repeatedInt64Wrapper_.Add(other.repeatedInt64Wrapper_); - repeatedUint32Wrapper_.Add(other.repeatedUint32Wrapper_); - repeatedUint64Wrapper_.Add(other.repeatedUint64Wrapper_); - repeatedFloatWrapper_.Add(other.repeatedFloatWrapper_); - repeatedDoubleWrapper_.Add(other.repeatedDoubleWrapper_); - repeatedStringWrapper_.Add(other.repeatedStringWrapper_); - repeatedBytesWrapper_.Add(other.repeatedBytesWrapper_); - if (other.optionalDuration_ != null) { - if (optionalDuration_ == null) { - optionalDuration_ = new global::Google.Protobuf.WellKnownTypes.Duration(); - } - OptionalDuration.MergeFrom(other.OptionalDuration); - } - if (other.optionalTimestamp_ != null) { - if (optionalTimestamp_ == null) { - optionalTimestamp_ = new global::Google.Protobuf.WellKnownTypes.Timestamp(); - } - OptionalTimestamp.MergeFrom(other.OptionalTimestamp); - } - if (other.optionalFieldMask_ != null) { - if (optionalFieldMask_ == null) { - optionalFieldMask_ = new global::Google.Protobuf.WellKnownTypes.FieldMask(); - } - OptionalFieldMask.MergeFrom(other.OptionalFieldMask); - } - if (other.optionalStruct_ != null) { - if (optionalStruct_ == null) { - optionalStruct_ = new global::Google.Protobuf.WellKnownTypes.Struct(); - } - OptionalStruct.MergeFrom(other.OptionalStruct); - } - if (other.optionalAny_ != null) { - if (optionalAny_ == null) { - optionalAny_ = new global::Google.Protobuf.WellKnownTypes.Any(); - } - OptionalAny.MergeFrom(other.OptionalAny); - } - if (other.optionalValue_ != null) { - if (optionalValue_ == null) { - optionalValue_ = new global::Google.Protobuf.WellKnownTypes.Value(); - } - OptionalValue.MergeFrom(other.OptionalValue); - } - repeatedDuration_.Add(other.repeatedDuration_); - repeatedTimestamp_.Add(other.repeatedTimestamp_); - repeatedFieldmask_.Add(other.repeatedFieldmask_); - repeatedStruct_.Add(other.repeatedStruct_); - repeatedAny_.Add(other.repeatedAny_); - repeatedValue_.Add(other.repeatedValue_); - if (other.Fieldname1 != 0) { - Fieldname1 = other.Fieldname1; - } - if (other.FieldName2 != 0) { - FieldName2 = other.FieldName2; - } - if (other.FieldName3 != 0) { - FieldName3 = other.FieldName3; - } - if (other.FieldName4 != 0) { - FieldName4 = other.FieldName4; - } - if (other.Field0Name5 != 0) { - Field0Name5 = other.Field0Name5; - } - if (other.Field0Name6 != 0) { - Field0Name6 = other.Field0Name6; - } - if (other.FieldName7 != 0) { - FieldName7 = other.FieldName7; - } - if (other.FieldName8 != 0) { - FieldName8 = other.FieldName8; - } - if (other.FieldName9 != 0) { - FieldName9 = other.FieldName9; - } - if (other.FieldName10 != 0) { - FieldName10 = other.FieldName10; - } - if (other.FIELDNAME11 != 0) { - FIELDNAME11 = other.FIELDNAME11; - } - if (other.FIELDName12 != 0) { - FIELDName12 = other.FIELDName12; - } - if (other.FieldName13 != 0) { - FieldName13 = other.FieldName13; - } - if (other.FieldName14 != 0) { - FieldName14 = other.FieldName14; - } - if (other.FieldName15 != 0) { - FieldName15 = other.FieldName15; - } - if (other.FieldName16 != 0) { - FieldName16 = other.FieldName16; - } - if (other.FieldName17 != 0) { - FieldName17 = other.FieldName17; - } - if (other.FieldName18 != 0) { - FieldName18 = other.FieldName18; - } - switch (other.OneofFieldCase) { - case OneofFieldOneofCase.OneofUint32: - OneofUint32 = other.OneofUint32; - break; - case OneofFieldOneofCase.OneofNestedMessage: - OneofNestedMessage = other.OneofNestedMessage; - break; - case OneofFieldOneofCase.OneofString: - OneofString = other.OneofString; - break; - case OneofFieldOneofCase.OneofBytes: - OneofBytes = other.OneofBytes; - break; - case OneofFieldOneofCase.OneofBool: - OneofBool = other.OneofBool; - break; - case OneofFieldOneofCase.OneofUint64: - OneofUint64 = other.OneofUint64; - break; - case OneofFieldOneofCase.OneofFloat: - OneofFloat = other.OneofFloat; - break; - case OneofFieldOneofCase.OneofDouble: - OneofDouble = other.OneofDouble; - break; - case OneofFieldOneofCase.OneofEnum: - OneofEnum = other.OneofEnum; - break; - } - - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - OptionalInt32 = input.ReadInt32(); - break; - } - case 16: { - OptionalInt64 = input.ReadInt64(); - break; - } - case 24: { - OptionalUint32 = input.ReadUInt32(); - break; - } - case 32: { - OptionalUint64 = input.ReadUInt64(); - break; - } - case 40: { - OptionalSint32 = input.ReadSInt32(); - break; - } - case 48: { - OptionalSint64 = input.ReadSInt64(); - break; - } - case 61: { - OptionalFixed32 = input.ReadFixed32(); - break; - } - case 65: { - OptionalFixed64 = input.ReadFixed64(); - break; - } - case 77: { - OptionalSfixed32 = input.ReadSFixed32(); - break; - } - case 81: { - OptionalSfixed64 = input.ReadSFixed64(); - break; - } - case 93: { - OptionalFloat = input.ReadFloat(); - break; - } - case 97: { - OptionalDouble = input.ReadDouble(); - break; - } - case 104: { - OptionalBool = input.ReadBool(); - break; - } - case 114: { - OptionalString = input.ReadString(); - break; - } - case 122: { - OptionalBytes = input.ReadBytes(); - break; - } - case 146: { - if (optionalNestedMessage_ == null) { - optionalNestedMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage(); - } - input.ReadMessage(optionalNestedMessage_); - break; - } - case 154: { - if (optionalForeignMessage_ == null) { - optionalForeignMessage_ = new global::ProtobufTestMessages.Proto3.ForeignMessage(); - } - input.ReadMessage(optionalForeignMessage_); - break; - } - case 168: { - optionalNestedEnum_ = (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) input.ReadEnum(); - break; - } - case 176: { - optionalForeignEnum_ = (global::ProtobufTestMessages.Proto3.ForeignEnum) input.ReadEnum(); - break; - } - case 194: { - OptionalStringPiece = input.ReadString(); - break; - } - case 202: { - OptionalCord = input.ReadString(); - break; - } - case 218: { - if (recursiveMessage_ == null) { - recursiveMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3(); - } - input.ReadMessage(recursiveMessage_); - break; - } - case 250: - case 248: { - repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); - break; - } - case 258: - case 256: { - repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec); - break; - } - case 266: - case 264: { - repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec); - break; - } - case 274: - case 272: { - repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec); - break; - } - case 282: - case 280: { - repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec); - break; - } - case 290: - case 288: { - repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec); - break; - } - case 298: - case 301: { - repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec); - break; - } - case 306: - case 305: { - repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec); - break; - } - case 314: - case 317: { - repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec); - break; - } - case 322: - case 321: { - repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec); - break; - } - case 330: - case 333: { - repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec); - break; - } - case 338: - case 337: { - repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec); - break; - } - case 346: - case 344: { - repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec); - break; - } - case 354: { - repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec); - break; - } - case 362: { - repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec); - break; - } - case 386: { - repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec); - break; - } - case 394: { - repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec); - break; - } - case 410: - case 408: { - repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec); - break; - } - case 418: - case 416: { - repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec); - break; - } - case 434: { - repeatedStringPiece_.AddEntriesFrom(input, _repeated_repeatedStringPiece_codec); - break; - } - case 442: { - repeatedCord_.AddEntriesFrom(input, _repeated_repeatedCord_codec); - break; - } - case 450: { - mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec); - break; - } - case 458: { - mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec); - break; - } - case 466: { - mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec); - break; - } - case 474: { - mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec); - break; - } - case 482: { - mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec); - break; - } - case 490: { - mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec); - break; - } - case 498: { - mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec); - break; - } - case 506: { - mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec); - break; - } - case 514: { - mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec); - break; - } - case 522: { - mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec); - break; - } - case 530: { - mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec); - break; - } - case 538: { - mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec); - break; - } - case 546: { - mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec); - break; - } - case 554: { - mapStringString_.AddEntriesFrom(input, _map_mapStringString_codec); - break; - } - case 562: { - mapStringBytes_.AddEntriesFrom(input, _map_mapStringBytes_codec); - break; - } - case 570: { - mapStringNestedMessage_.AddEntriesFrom(input, _map_mapStringNestedMessage_codec); - break; - } - case 578: { - mapStringForeignMessage_.AddEntriesFrom(input, _map_mapStringForeignMessage_codec); - break; - } - case 586: { - mapStringNestedEnum_.AddEntriesFrom(input, _map_mapStringNestedEnum_codec); - break; - } - case 594: { - mapStringForeignEnum_.AddEntriesFrom(input, _map_mapStringForeignEnum_codec); - break; - } - case 888: { - OneofUint32 = input.ReadUInt32(); - break; - } - case 898: { - global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage subBuilder = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { - subBuilder.MergeFrom(OneofNestedMessage); - } - input.ReadMessage(subBuilder); - OneofNestedMessage = subBuilder; - break; - } - case 906: { - OneofString = input.ReadString(); - break; - } - case 914: { - OneofBytes = input.ReadBytes(); - break; - } - case 920: { - OneofBool = input.ReadBool(); - break; - } - case 928: { - OneofUint64 = input.ReadUInt64(); - break; - } - case 941: { - OneofFloat = input.ReadFloat(); - break; - } - case 945: { - OneofDouble = input.ReadDouble(); - break; - } - case 952: { - oneofField_ = input.ReadEnum(); - oneofFieldCase_ = OneofFieldOneofCase.OneofEnum; - break; - } - case 1610: { - bool? value = _single_optionalBoolWrapper_codec.Read(input); - if (optionalBoolWrapper_ == null || value != false) { - OptionalBoolWrapper = value; - } - break; - } - case 1618: { - int? value = _single_optionalInt32Wrapper_codec.Read(input); - if (optionalInt32Wrapper_ == null || value != 0) { - OptionalInt32Wrapper = value; - } - break; - } - case 1626: { - long? value = _single_optionalInt64Wrapper_codec.Read(input); - if (optionalInt64Wrapper_ == null || value != 0L) { - OptionalInt64Wrapper = value; - } - break; - } - case 1634: { - uint? value = _single_optionalUint32Wrapper_codec.Read(input); - if (optionalUint32Wrapper_ == null || value != 0) { - OptionalUint32Wrapper = value; - } - break; - } - case 1642: { - ulong? value = _single_optionalUint64Wrapper_codec.Read(input); - if (optionalUint64Wrapper_ == null || value != 0UL) { - OptionalUint64Wrapper = value; - } - break; - } - case 1650: { - float? value = _single_optionalFloatWrapper_codec.Read(input); - if (optionalFloatWrapper_ == null || value != 0F) { - OptionalFloatWrapper = value; - } - break; - } - case 1658: { - double? value = _single_optionalDoubleWrapper_codec.Read(input); - if (optionalDoubleWrapper_ == null || value != 0D) { - OptionalDoubleWrapper = value; - } - break; - } - case 1666: { - string value = _single_optionalStringWrapper_codec.Read(input); - if (optionalStringWrapper_ == null || value != "") { - OptionalStringWrapper = value; - } - break; - } - case 1674: { - pb::ByteString value = _single_optionalBytesWrapper_codec.Read(input); - if (optionalBytesWrapper_ == null || value != pb::ByteString.Empty) { - OptionalBytesWrapper = value; - } - break; - } - case 1690: { - repeatedBoolWrapper_.AddEntriesFrom(input, _repeated_repeatedBoolWrapper_codec); - break; - } - case 1698: { - repeatedInt32Wrapper_.AddEntriesFrom(input, _repeated_repeatedInt32Wrapper_codec); - break; - } - case 1706: { - repeatedInt64Wrapper_.AddEntriesFrom(input, _repeated_repeatedInt64Wrapper_codec); - break; - } - case 1714: { - repeatedUint32Wrapper_.AddEntriesFrom(input, _repeated_repeatedUint32Wrapper_codec); - break; - } - case 1722: { - repeatedUint64Wrapper_.AddEntriesFrom(input, _repeated_repeatedUint64Wrapper_codec); - break; - } - case 1730: { - repeatedFloatWrapper_.AddEntriesFrom(input, _repeated_repeatedFloatWrapper_codec); - break; - } - case 1738: { - repeatedDoubleWrapper_.AddEntriesFrom(input, _repeated_repeatedDoubleWrapper_codec); - break; - } - case 1746: { - repeatedStringWrapper_.AddEntriesFrom(input, _repeated_repeatedStringWrapper_codec); - break; - } - case 1754: { - repeatedBytesWrapper_.AddEntriesFrom(input, _repeated_repeatedBytesWrapper_codec); - break; - } - case 2410: { - if (optionalDuration_ == null) { - optionalDuration_ = new global::Google.Protobuf.WellKnownTypes.Duration(); - } - input.ReadMessage(optionalDuration_); - break; - } - case 2418: { - if (optionalTimestamp_ == null) { - optionalTimestamp_ = new global::Google.Protobuf.WellKnownTypes.Timestamp(); - } - input.ReadMessage(optionalTimestamp_); - break; - } - case 2426: { - if (optionalFieldMask_ == null) { - optionalFieldMask_ = new global::Google.Protobuf.WellKnownTypes.FieldMask(); - } - input.ReadMessage(optionalFieldMask_); - break; - } - case 2434: { - if (optionalStruct_ == null) { - optionalStruct_ = new global::Google.Protobuf.WellKnownTypes.Struct(); - } - input.ReadMessage(optionalStruct_); - break; - } - case 2442: { - if (optionalAny_ == null) { - optionalAny_ = new global::Google.Protobuf.WellKnownTypes.Any(); - } - input.ReadMessage(optionalAny_); - break; - } - case 2450: { - if (optionalValue_ == null) { - optionalValue_ = new global::Google.Protobuf.WellKnownTypes.Value(); - } - input.ReadMessage(optionalValue_); - break; - } - case 2490: { - repeatedDuration_.AddEntriesFrom(input, _repeated_repeatedDuration_codec); - break; - } - case 2498: { - repeatedTimestamp_.AddEntriesFrom(input, _repeated_repeatedTimestamp_codec); - break; - } - case 2506: { - repeatedFieldmask_.AddEntriesFrom(input, _repeated_repeatedFieldmask_codec); - break; - } - case 2522: { - repeatedAny_.AddEntriesFrom(input, _repeated_repeatedAny_codec); - break; - } - case 2530: { - repeatedValue_.AddEntriesFrom(input, _repeated_repeatedValue_codec); - break; - } - case 2594: { - repeatedStruct_.AddEntriesFrom(input, _repeated_repeatedStruct_codec); - break; - } - case 3208: { - Fieldname1 = input.ReadInt32(); - break; - } - case 3216: { - FieldName2 = input.ReadInt32(); - break; - } - case 3224: { - FieldName3 = input.ReadInt32(); - break; - } - case 3232: { - FieldName4 = input.ReadInt32(); - break; - } - case 3240: { - Field0Name5 = input.ReadInt32(); - break; - } - case 3248: { - Field0Name6 = input.ReadInt32(); - break; - } - case 3256: { - FieldName7 = input.ReadInt32(); - break; - } - case 3264: { - FieldName8 = input.ReadInt32(); - break; - } - case 3272: { - FieldName9 = input.ReadInt32(); - break; - } - case 3280: { - FieldName10 = input.ReadInt32(); - break; - } - case 3288: { - FIELDNAME11 = input.ReadInt32(); - break; - } - case 3296: { - FIELDName12 = input.ReadInt32(); - break; - } - case 3304: { - FieldName13 = input.ReadInt32(); - break; - } - case 3312: { - FieldName14 = input.ReadInt32(); - break; - } - case 3320: { - FieldName15 = input.ReadInt32(); - break; - } - case 3328: { - FieldName16 = input.ReadInt32(); - break; - } - case 3336: { - FieldName17 = input.ReadInt32(); - break; - } - case 3344: { - FieldName18 = input.ReadInt32(); - break; - } - } - } - } - - #region Nested types - /// Container for nested types declared in the TestAllTypesProto3 message type. - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static partial class Types { - public enum NestedEnum { - [pbr::OriginalName("FOO")] Foo = 0, - [pbr::OriginalName("BAR")] Bar = 1, - [pbr::OriginalName("BAZ")] Baz = 2, - /// - /// Intentionally negative. - /// - [pbr::OriginalName("NEG")] Neg = -1, - } - - public sealed partial class NestedMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Descriptor.NestedTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedMessage(NestedMessage other) : this() { - a_ = other.a_; - Corecursive = other.corecursive_ != null ? other.Corecursive.Clone() : null; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedMessage Clone() { - return new NestedMessage(this); - } - - /// Field number for the "a" field. - public const int AFieldNumber = 1; - private int a_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int A { - get { return a_; } - set { - a_ = value; - } - } - - /// Field number for the "corecursive" field. - public const int CorecursiveFieldNumber = 2; - private global::ProtobufTestMessages.Proto3.TestAllTypesProto3 corecursive_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::ProtobufTestMessages.Proto3.TestAllTypesProto3 Corecursive { - get { return corecursive_; } - set { - corecursive_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as NestedMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(NestedMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (A != other.A) return false; - if (!object.Equals(Corecursive, other.Corecursive)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (A != 0) hash ^= A.GetHashCode(); - if (corecursive_ != null) hash ^= Corecursive.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (A != 0) { - output.WriteRawTag(8); - output.WriteInt32(A); - } - if (corecursive_ != null) { - output.WriteRawTag(18); - output.WriteMessage(Corecursive); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (A != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); - } - if (corecursive_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(Corecursive); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(NestedMessage other) { - if (other == null) { - return; - } - if (other.A != 0) { - A = other.A; - } - if (other.corecursive_ != null) { - if (corecursive_ == null) { - corecursive_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3(); - } - Corecursive.MergeFrom(other.Corecursive); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - A = input.ReadInt32(); - break; - } - case 18: { - if (corecursive_ == null) { - corecursive_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3(); - } - input.ReadMessage(corecursive_); - break; - } - } - } - } - - } - - } - #endregion - - } - - public sealed partial class ForeignMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ForeignMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::ProtobufTestMessages.Proto3.TestMessagesProto3Reflection.Descriptor.MessageTypes[1]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ForeignMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ForeignMessage(ForeignMessage other) : this() { - c_ = other.c_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ForeignMessage Clone() { - return new ForeignMessage(this); - } - - /// Field number for the "c" field. - public const int CFieldNumber = 1; - private int c_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int C { - get { return c_; } - set { - c_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as ForeignMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(ForeignMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (C != other.C) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (C != 0) hash ^= C.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (C != 0) { - output.WriteRawTag(8); - output.WriteInt32(C); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (C != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(C); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(ForeignMessage other) { - if (other == null) { - return; - } - if (other.C != 0) { - C = other.C; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - C = input.ReadInt32(); - break; - } - } - } - } - - } - - #endregion - -} - -#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs deleted file mode 100644 index e21ede9c54745..0000000000000 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs +++ /dev/null @@ -1,2625 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: unittest_custom_options_proto3.proto -#pragma warning disable 1591, 0612, 3021 -#region Designer generated code - -using pb = global::Google.Protobuf; -using pbc = global::Google.Protobuf.Collections; -using pbr = global::Google.Protobuf.Reflection; -using scg = global::System.Collections.Generic; -namespace UnitTest.Issues.TestProtos { - - /// Holder for reflection information generated from unittest_custom_options_proto3.proto - public static partial class UnittestCustomOptionsProto3Reflection { - - #region Descriptor - /// File descriptor for unittest_custom_options_proto3.proto - public static pbr::FileDescriptor Descriptor { - get { return descriptor; } - } - private static pbr::FileDescriptor descriptor; - - static UnittestCustomOptionsProto3Reflection() { - byte[] descriptorData = global::System.Convert.FromBase64String( - string.Concat( - "CiR1bml0dGVzdF9jdXN0b21fb3B0aW9uc19wcm90bzMucHJvdG8SEXByb3Rv", - "YnVmX3VuaXR0ZXN0GiBnb29nbGUvcHJvdG9idWYvZGVzY3JpcHRvci5wcm90", - "byLXAQocVGVzdE1lc3NhZ2VXaXRoQ3VzdG9tT3B0aW9ucxIeCgZmaWVsZDEY", - "ASABKAlCDggBweDDHS3hdQoCAAAAEhUKC29uZW9mX2ZpZWxkGAIgASgFSAAi", - "UwoGQW5FbnVtEhYKEkFORU5VTV9VTlNQRUNJRklFRBAAEg8KC0FORU5VTV9W", - "QUwxEAESFgoLQU5FTlVNX1ZBTDIQAhoFsIb6BXsaCMX2yR3r/P//OhAIAODp", - "wh3I//////////8BQhkKB0FuT25lb2YSDviswx2d//////////8BIhgKFkN1", - "c3RvbU9wdGlvbkZvb1JlcXVlc3QiGQoXQ3VzdG9tT3B0aW9uRm9vUmVzcG9u", - "c2UiHgocQ3VzdG9tT3B0aW9uRm9vQ2xpZW50TWVzc2FnZSIeChxDdXN0b21P", - "cHRpb25Gb29TZXJ2ZXJNZXNzYWdlIo8BChpEdW1teU1lc3NhZ2VDb250YWlu", - "aW5nRW51bSJxCgxUZXN0RW51bVR5cGUSIAocVEVTVF9PUFRJT05fRU5VTV9V", - "TlNQRUNJRklFRBAAEhoKFlRFU1RfT1BUSU9OX0VOVU1fVFlQRTEQFhIjChZU", - "RVNUX09QVElPTl9FTlVNX1RZUEUyEOn//////////wEiIQofRHVtbXlNZXNz", - "YWdlSW52YWxpZEFzT3B0aW9uVHlwZSKKAQocQ3VzdG9tT3B0aW9uTWluSW50", - "ZWdlclZhbHVlczpq0N6yHQDoxrIdgICAgPj/////AbC8sh2AgICAgICAgIAB", - "gJOyHQD49bAdAIDEsB3/////D/iXsB3///////////8BnfWvHQAAAACR7q8d", - "AAAAAAAAAACtja8dAAAAgJnWqB0AAAAAAAAAgCKRAQocQ3VzdG9tT3B0aW9u", - "TWF4SW50ZWdlclZhbHVlczpx0N6yHQHoxrId/////wewvLId//////////9/", - "gJOyHf////8P+PWwHf///////////wGAxLAd/v///w/4l7Ad/v//////////", - "AZ31rx3/////ke6vHf//////////rY2vHf///3+Z1qgd/////////38ibgoX", - "Q3VzdG9tT3B0aW9uT3RoZXJWYWx1ZXM6U+jGsh2c//////////8B9d+jHeeH", - "RUHp3KId+1mMQsrA8z+q3KIdDkhlbGxvLCAiV29ybGQistmiHQtIZWxsbwBX", - "b3JsZIjZoh3p//////////8BIjQKHFNldHRpbmdSZWFsc0Zyb21Qb3NpdGl2", - "ZUludHM6FPXfox0AAEBB6dyiHQAAAAAAQGNAIjQKHFNldHRpbmdSZWFsc0Zy", - "b21OZWdhdGl2ZUludHM6FPXfox0AAEDB6dyiHQAAAAAAQGPAIksKEkNvbXBs", - "ZXhPcHRpb25UeXBlMRILCgNmb28YASABKAUSDAoEZm9vMhgCIAEoBRIMCgRm", - "b28zGAMgASgFEgwKBGZvbzQYBCADKAUigQMKEkNvbXBsZXhPcHRpb25UeXBl", - "MhIyCgNiYXIYASABKAsyJS5wcm90b2J1Zl91bml0dGVzdC5Db21wbGV4T3B0", - "aW9uVHlwZTESCwoDYmF6GAIgASgFEkYKBGZyZWQYAyABKAsyOC5wcm90b2J1", - "Zl91bml0dGVzdC5Db21wbGV4T3B0aW9uVHlwZTIuQ29tcGxleE9wdGlvblR5", - "cGU0EkgKBmJhcm5leRgEIAMoCzI4LnByb3RvYnVmX3VuaXR0ZXN0LkNvbXBs", - "ZXhPcHRpb25UeXBlMi5Db21wbGV4T3B0aW9uVHlwZTQalwEKEkNvbXBsZXhP", - "cHRpb25UeXBlNBINCgV3YWxkbxgBIAEoBTJyCgxjb21wbGV4X29wdDQSHy5n", - "b29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMYivXRAyABKAsyOC5wcm90", - "b2J1Zl91bml0dGVzdC5Db21wbGV4T3B0aW9uVHlwZTIuQ29tcGxleE9wdGlv", - "blR5cGU0IiEKEkNvbXBsZXhPcHRpb25UeXBlMxILCgNxdXgYASABKAUibAoV", - "VmFyaW91c0NvbXBsZXhPcHRpb25zOlOi4pUdAggqouKVHQIgY6LilR0CIFiq", - "/ZAdAxDbB6r9kB0FCgMI5wXSqI8dAwizD6r9kB0FGgMIwQKq/ZAdBCICCGWq", - "/ZAdBSIDCNQB+t6QHQIICSJMCglBZ2dyZWdhdGUSCQoBaRgBIAEoBRIJCgFz", - "GAIgASgJEikKA3N1YhgDIAEoCzIcLnByb3RvYnVmX3VuaXR0ZXN0LkFnZ3Jl", - "Z2F0ZSJZChBBZ2dyZWdhdGVNZXNzYWdlEikKCWZpZWxkbmFtZRgBIAEoBUIW", - "8qGHOxESD0ZpZWxkQW5ub3RhdGlvbjoawtGGOxUIZRIRTWVzc2FnZUFubm90", - "YXRpb24ilwEKEE5lc3RlZE9wdGlvblR5cGUaOwoNTmVzdGVkTWVzc2FnZRIi", - "CgxuZXN0ZWRfZmllbGQYASABKAVCDMHgwx3qAwAAAAAAADoG4OnCHekHIkYK", - "Ck5lc3RlZEVudW0SDwoLVU5TUEVDSUZJRUQQABIdChFORVNURURfRU5VTV9W", - "QUxVRRABGgawhvoF7AcaCMX2yR3rAwAAKlIKCk1ldGhvZE9wdDESGgoWTUVU", - "SE9ET1BUMV9VTlNQRUNJRklFRBAAEhMKD01FVEhPRE9QVDFfVkFMMRABEhMK", - "D01FVEhPRE9QVDFfVkFMMhACKl4KDUFnZ3JlZ2F0ZUVudW0SDwoLVU5TUEVD", - "SUZJRUQQABIlCgVWQUxVRRABGhrK/Ik7FRITRW51bVZhbHVlQW5ub3RhdGlv", - "bhoVkpWIOxASDkVudW1Bbm5vdGF0aW9uMo4BChxUZXN0U2VydmljZVdpdGhD", - "dXN0b21PcHRpb25zEmMKA0ZvbxIpLnByb3RvYnVmX3VuaXR0ZXN0LkN1c3Rv", - "bU9wdGlvbkZvb1JlcXVlc3QaKi5wcm90b2J1Zl91bml0dGVzdC5DdXN0b21P", - "cHRpb25Gb29SZXNwb25zZSIF4PqMHgIaCZCyix7T24DLSTKZAQoQQWdncmVn", - "YXRlU2VydmljZRJrCgZNZXRob2QSIy5wcm90b2J1Zl91bml0dGVzdC5BZ2dy", - "ZWdhdGVNZXNzYWdlGiMucHJvdG9idWZfdW5pdHRlc3QuQWdncmVnYXRlTWVz", - "c2FnZSIXysiWOxISEE1ldGhvZEFubm90YXRpb24aGMr7jjsTEhFTZXJ2aWNl", - "QW5ub3RhdGlvbjoyCglmaWxlX29wdDESHC5nb29nbGUucHJvdG9idWYuRmls", - "ZU9wdGlvbnMYjp3YAyABKAQ6OAoMbWVzc2FnZV9vcHQxEh8uZ29vZ2xlLnBy", - "b3RvYnVmLk1lc3NhZ2VPcHRpb25zGJyt2AMgASgFOjQKCmZpZWxkX29wdDES", - "HS5nb29nbGUucHJvdG9idWYuRmllbGRPcHRpb25zGIi82AMgASgGOjQKCm9u", - "ZW9mX29wdDESHS5nb29nbGUucHJvdG9idWYuT25lb2ZPcHRpb25zGM+12AMg", - "ASgFOjIKCWVudW1fb3B0MRIcLmdvb2dsZS5wcm90b2J1Zi5FbnVtT3B0aW9u", - "cxjontkDIAEoDzo8Cg9lbnVtX3ZhbHVlX29wdDESIS5nb29nbGUucHJvdG9i", - "dWYuRW51bVZhbHVlT3B0aW9ucxjmoF8gASgFOjgKDHNlcnZpY2Vfb3B0MRIf", - "Lmdvb2dsZS5wcm90b2J1Zi5TZXJ2aWNlT3B0aW9ucxiituEDIAEoEjpVCgtt", - "ZXRob2Rfb3B0MRIeLmdvb2dsZS5wcm90b2J1Zi5NZXRob2RPcHRpb25zGKzP", - "4QMgASgOMh0ucHJvdG9idWZfdW5pdHRlc3QuTWV0aG9kT3B0MTo0Cghib29s", - "X29wdBIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxjqq9YDIAEo", - "CDo1CglpbnQzMl9vcHQSHy5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlv", - "bnMY7ajWAyABKAU6NQoJaW50NjRfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1l", - "c3NhZ2VPcHRpb25zGMan1gMgASgDOjYKCnVpbnQzMl9vcHQSHy5nb29nbGUu", - "cHJvdG9idWYuTWVzc2FnZU9wdGlvbnMYsKLWAyABKA06NgoKdWludDY0X29w", - "dBIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxjfjtYDIAEoBDo2", - "CgpzaW50MzJfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRpb25z", - "GMCI1gMgASgROjYKCnNpbnQ2NF9vcHQSHy5nb29nbGUucHJvdG9idWYuTWVz", - "c2FnZU9wdGlvbnMY/4LWAyABKBI6NwoLZml4ZWQzMl9vcHQSHy5nb29nbGUu", - "cHJvdG9idWYuTWVzc2FnZU9wdGlvbnMY0/7VAyABKAc6NwoLZml4ZWQ2NF9v", - "cHQSHy5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMY4v3VAyABKAY6", - "OAoMc2ZpeGVkMzJfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRp", - "b25zGNXx1QMgASgPOjgKDHNmaXhlZDY0X29wdBIfLmdvb2dsZS5wcm90b2J1", - "Zi5NZXNzYWdlT3B0aW9ucxjjitUDIAEoEDo1CglmbG9hdF9vcHQSHy5nb29n", - "bGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMY/rvUAyABKAI6NgoKZG91Ymxl", - "X29wdBIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxjNq9QDIAEo", - "ATo2CgpzdHJpbmdfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRp", - "b25zGMWr1AMgASgJOjUKCWJ5dGVzX29wdBIfLmdvb2dsZS5wcm90b2J1Zi5N", - "ZXNzYWdlT3B0aW9ucxiWq9QDIAEoDDpwCghlbnVtX29wdBIfLmdvb2dsZS5w", - "cm90b2J1Zi5NZXNzYWdlT3B0aW9ucxiRq9QDIAEoDjI6LnByb3RvYnVmX3Vu", - "aXR0ZXN0LkR1bW15TWVzc2FnZUNvbnRhaW5pbmdFbnVtLlRlc3RFbnVtVHlw", - "ZTpwChBtZXNzYWdlX3R5cGVfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3Nh", - "Z2VPcHRpb25zGK/y0wMgASgLMjIucHJvdG9idWZfdW5pdHRlc3QuRHVtbXlN", - "ZXNzYWdlSW52YWxpZEFzT3B0aW9uVHlwZTpfCgxjb21wbGV4X29wdDESHy5n", - "b29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMYpNzSAyABKAsyJS5wcm90", - "b2J1Zl91bml0dGVzdC5Db21wbGV4T3B0aW9uVHlwZTE6XwoMY29tcGxleF9v", - "cHQyEh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRpb25zGNWP0gMgASgL", - "MiUucHJvdG9idWZfdW5pdHRlc3QuQ29tcGxleE9wdGlvblR5cGUyOl8KDGNv", - "bXBsZXhfb3B0MxIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxjv", - "i9IDIAEoCzIlLnByb3RvYnVmX3VuaXR0ZXN0LkNvbXBsZXhPcHRpb25UeXBl", - "MzpOCgdmaWxlb3B0EhwuZ29vZ2xlLnByb3RvYnVmLkZpbGVPcHRpb25zGM/d", - "sAcgASgLMhwucHJvdG9idWZfdW5pdHRlc3QuQWdncmVnYXRlOlAKBm1zZ29w", - "dBIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxiY6rAHIAEoCzIc", - "LnByb3RvYnVmX3VuaXR0ZXN0LkFnZ3JlZ2F0ZTpQCghmaWVsZG9wdBIdLmdv", - "b2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMYnvSwByABKAsyHC5wcm90b2J1", - "Zl91bml0dGVzdC5BZ2dyZWdhdGU6TgoHZW51bW9wdBIcLmdvb2dsZS5wcm90", - "b2J1Zi5FbnVtT3B0aW9ucxjSgrEHIAEoCzIcLnByb3RvYnVmX3VuaXR0ZXN0", - "LkFnZ3JlZ2F0ZTpWCgplbnVtdmFsb3B0EiEuZ29vZ2xlLnByb3RvYnVmLkVu", - "dW1WYWx1ZU9wdGlvbnMYyZ+xByABKAsyHC5wcm90b2J1Zl91bml0dGVzdC5B", - "Z2dyZWdhdGU6VAoKc2VydmljZW9wdBIfLmdvb2dsZS5wcm90b2J1Zi5TZXJ2", - "aWNlT3B0aW9ucxi577EHIAEoCzIcLnByb3RvYnVmX3VuaXR0ZXN0LkFnZ3Jl", - "Z2F0ZTpSCgltZXRob2RvcHQSHi5nb29nbGUucHJvdG9idWYuTWV0aG9kT3B0", - "aW9ucxiJ6bIHIAEoCzIcLnByb3RvYnVmX3VuaXR0ZXN0LkFnZ3JlZ2F0ZUJV", - "qgIaVW5pdFRlc3QuSXNzdWVzLlRlc3RQcm90b3Pw6MEd6q3A5ST67IU7Kghk", - "Eg5GaWxlQW5ub3RhdGlvbhoWEhROZXN0ZWRGaWxlQW5ub3RhdGlvbmIGcHJv", - "dG8z")); - descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, - new pbr::FileDescriptor[] { pbr::FileDescriptor.DescriptorProtoFileDescriptor, }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.MethodOpt1), typeof(global::UnitTest.Issues.TestProtos.AggregateEnum), }, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestMessageWithCustomOptions), global::UnitTest.Issues.TestProtos.TestMessageWithCustomOptions.Parser, new[]{ "Field1", "OneofField" }, new[]{ "AnOneof" }, new[]{ typeof(global::UnitTest.Issues.TestProtos.TestMessageWithCustomOptions.Types.AnEnum) }, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionFooRequest), global::UnitTest.Issues.TestProtos.CustomOptionFooRequest.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionFooResponse), global::UnitTest.Issues.TestProtos.CustomOptionFooResponse.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionFooClientMessage), global::UnitTest.Issues.TestProtos.CustomOptionFooClientMessage.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionFooServerMessage), global::UnitTest.Issues.TestProtos.CustomOptionFooServerMessage.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DummyMessageContainingEnum), global::UnitTest.Issues.TestProtos.DummyMessageContainingEnum.Parser, null, null, new[]{ typeof(global::UnitTest.Issues.TestProtos.DummyMessageContainingEnum.Types.TestEnumType) }, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DummyMessageInvalidAsOptionType), global::UnitTest.Issues.TestProtos.DummyMessageInvalidAsOptionType.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionMinIntegerValues), global::UnitTest.Issues.TestProtos.CustomOptionMinIntegerValues.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionMaxIntegerValues), global::UnitTest.Issues.TestProtos.CustomOptionMaxIntegerValues.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionOtherValues), global::UnitTest.Issues.TestProtos.CustomOptionOtherValues.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.SettingRealsFromPositiveInts), global::UnitTest.Issues.TestProtos.SettingRealsFromPositiveInts.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.SettingRealsFromNegativeInts), global::UnitTest.Issues.TestProtos.SettingRealsFromNegativeInts.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ComplexOptionType1), global::UnitTest.Issues.TestProtos.ComplexOptionType1.Parser, new[]{ "Foo", "Foo2", "Foo3", "Foo4" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ComplexOptionType2), global::UnitTest.Issues.TestProtos.ComplexOptionType2.Parser, new[]{ "Bar", "Baz", "Fred", "Barney" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4), global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Parser, new[]{ "Waldo" }, null, null, null)}), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ComplexOptionType3), global::UnitTest.Issues.TestProtos.ComplexOptionType3.Parser, new[]{ "Qux" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.VariousComplexOptions), global::UnitTest.Issues.TestProtos.VariousComplexOptions.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Aggregate), global::UnitTest.Issues.TestProtos.Aggregate.Parser, new[]{ "I", "S", "Sub" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.AggregateMessage), global::UnitTest.Issues.TestProtos.AggregateMessage.Parser, new[]{ "Fieldname" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NestedOptionType), global::UnitTest.Issues.TestProtos.NestedOptionType.Parser, null, null, new[]{ typeof(global::UnitTest.Issues.TestProtos.NestedOptionType.Types.NestedEnum) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NestedOptionType.Types.NestedMessage), global::UnitTest.Issues.TestProtos.NestedOptionType.Types.NestedMessage.Parser, new[]{ "NestedField" }, null, null, null)}) - })); - } - #endregion - - } - #region Enums - public enum MethodOpt1 { - [pbr::OriginalName("METHODOPT1_UNSPECIFIED")] Unspecified = 0, - [pbr::OriginalName("METHODOPT1_VAL1")] Val1 = 1, - [pbr::OriginalName("METHODOPT1_VAL2")] Val2 = 2, - } - - public enum AggregateEnum { - [pbr::OriginalName("UNSPECIFIED")] Unspecified = 0, - [pbr::OriginalName("VALUE")] Value = 1, - } - - #endregion - - #region Messages - /// - /// A test message with custom options at all possible locations (and also some - /// regular options, to make sure they interact nicely). - /// - public sealed partial class TestMessageWithCustomOptions : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMessageWithCustomOptions()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMessageWithCustomOptions() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMessageWithCustomOptions(TestMessageWithCustomOptions other) : this() { - field1_ = other.field1_; - switch (other.AnOneofCase) { - case AnOneofOneofCase.OneofField: - OneofField = other.OneofField; - break; - } - - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMessageWithCustomOptions Clone() { - return new TestMessageWithCustomOptions(this); - } - - /// Field number for the "field1" field. - public const int Field1FieldNumber = 1; - private string field1_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string Field1 { - get { return field1_; } - set { - field1_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "oneof_field" field. - public const int OneofFieldFieldNumber = 2; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int OneofField { - get { return anOneofCase_ == AnOneofOneofCase.OneofField ? (int) anOneof_ : 0; } - set { - anOneof_ = value; - anOneofCase_ = AnOneofOneofCase.OneofField; - } - } - - private object anOneof_; - /// Enum of possible cases for the "AnOneof" oneof. - public enum AnOneofOneofCase { - None = 0, - OneofField = 2, - } - private AnOneofOneofCase anOneofCase_ = AnOneofOneofCase.None; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public AnOneofOneofCase AnOneofCase { - get { return anOneofCase_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void ClearAnOneof() { - anOneofCase_ = AnOneofOneofCase.None; - anOneof_ = null; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestMessageWithCustomOptions); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestMessageWithCustomOptions other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Field1 != other.Field1) return false; - if (OneofField != other.OneofField) return false; - if (AnOneofCase != other.AnOneofCase) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Field1.Length != 0) hash ^= Field1.GetHashCode(); - if (anOneofCase_ == AnOneofOneofCase.OneofField) hash ^= OneofField.GetHashCode(); - hash ^= (int) anOneofCase_; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Field1.Length != 0) { - output.WriteRawTag(10); - output.WriteString(Field1); - } - if (anOneofCase_ == AnOneofOneofCase.OneofField) { - output.WriteRawTag(16); - output.WriteInt32(OneofField); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Field1.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(Field1); - } - if (anOneofCase_ == AnOneofOneofCase.OneofField) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(OneofField); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestMessageWithCustomOptions other) { - if (other == null) { - return; - } - if (other.Field1.Length != 0) { - Field1 = other.Field1; - } - switch (other.AnOneofCase) { - case AnOneofOneofCase.OneofField: - OneofField = other.OneofField; - break; - } - - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - Field1 = input.ReadString(); - break; - } - case 16: { - OneofField = input.ReadInt32(); - break; - } - } - } - } - - #region Nested types - /// Container for nested types declared in the TestMessageWithCustomOptions message type. - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static partial class Types { - public enum AnEnum { - [pbr::OriginalName("ANENUM_UNSPECIFIED")] Unspecified = 0, - [pbr::OriginalName("ANENUM_VAL1")] Val1 = 1, - [pbr::OriginalName("ANENUM_VAL2")] Val2 = 2, - } - - } - #endregion - - } - - /// - /// A test RPC service with custom options at all possible locations (and also - /// some regular options, to make sure they interact nicely). - /// - public sealed partial class CustomOptionFooRequest : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooRequest()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[1]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionFooRequest() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionFooRequest(CustomOptionFooRequest other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionFooRequest Clone() { - return new CustomOptionFooRequest(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as CustomOptionFooRequest); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(CustomOptionFooRequest other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(CustomOptionFooRequest other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class CustomOptionFooResponse : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooResponse()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[2]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionFooResponse() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionFooResponse(CustomOptionFooResponse other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionFooResponse Clone() { - return new CustomOptionFooResponse(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as CustomOptionFooResponse); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(CustomOptionFooResponse other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(CustomOptionFooResponse other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class CustomOptionFooClientMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooClientMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[3]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionFooClientMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionFooClientMessage(CustomOptionFooClientMessage other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionFooClientMessage Clone() { - return new CustomOptionFooClientMessage(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as CustomOptionFooClientMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(CustomOptionFooClientMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(CustomOptionFooClientMessage other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class CustomOptionFooServerMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooServerMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[4]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionFooServerMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionFooServerMessage(CustomOptionFooServerMessage other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionFooServerMessage Clone() { - return new CustomOptionFooServerMessage(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as CustomOptionFooServerMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(CustomOptionFooServerMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(CustomOptionFooServerMessage other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class DummyMessageContainingEnum : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DummyMessageContainingEnum()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[5]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public DummyMessageContainingEnum() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public DummyMessageContainingEnum(DummyMessageContainingEnum other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public DummyMessageContainingEnum Clone() { - return new DummyMessageContainingEnum(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as DummyMessageContainingEnum); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(DummyMessageContainingEnum other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(DummyMessageContainingEnum other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - #region Nested types - /// Container for nested types declared in the DummyMessageContainingEnum message type. - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static partial class Types { - public enum TestEnumType { - [pbr::OriginalName("TEST_OPTION_ENUM_UNSPECIFIED")] TestOptionEnumUnspecified = 0, - [pbr::OriginalName("TEST_OPTION_ENUM_TYPE1")] TestOptionEnumType1 = 22, - [pbr::OriginalName("TEST_OPTION_ENUM_TYPE2")] TestOptionEnumType2 = -23, - } - - } - #endregion - - } - - public sealed partial class DummyMessageInvalidAsOptionType : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DummyMessageInvalidAsOptionType()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[6]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public DummyMessageInvalidAsOptionType() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public DummyMessageInvalidAsOptionType(DummyMessageInvalidAsOptionType other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public DummyMessageInvalidAsOptionType Clone() { - return new DummyMessageInvalidAsOptionType(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as DummyMessageInvalidAsOptionType); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(DummyMessageInvalidAsOptionType other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(DummyMessageInvalidAsOptionType other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class CustomOptionMinIntegerValues : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionMinIntegerValues()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[7]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionMinIntegerValues() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionMinIntegerValues(CustomOptionMinIntegerValues other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionMinIntegerValues Clone() { - return new CustomOptionMinIntegerValues(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as CustomOptionMinIntegerValues); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(CustomOptionMinIntegerValues other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(CustomOptionMinIntegerValues other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class CustomOptionMaxIntegerValues : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionMaxIntegerValues()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[8]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionMaxIntegerValues() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionMaxIntegerValues(CustomOptionMaxIntegerValues other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionMaxIntegerValues Clone() { - return new CustomOptionMaxIntegerValues(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as CustomOptionMaxIntegerValues); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(CustomOptionMaxIntegerValues other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(CustomOptionMaxIntegerValues other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class CustomOptionOtherValues : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionOtherValues()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[9]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionOtherValues() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionOtherValues(CustomOptionOtherValues other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public CustomOptionOtherValues Clone() { - return new CustomOptionOtherValues(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as CustomOptionOtherValues); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(CustomOptionOtherValues other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(CustomOptionOtherValues other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class SettingRealsFromPositiveInts : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SettingRealsFromPositiveInts()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[10]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public SettingRealsFromPositiveInts() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public SettingRealsFromPositiveInts(SettingRealsFromPositiveInts other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public SettingRealsFromPositiveInts Clone() { - return new SettingRealsFromPositiveInts(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as SettingRealsFromPositiveInts); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(SettingRealsFromPositiveInts other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(SettingRealsFromPositiveInts other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class SettingRealsFromNegativeInts : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SettingRealsFromNegativeInts()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[11]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public SettingRealsFromNegativeInts() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public SettingRealsFromNegativeInts(SettingRealsFromNegativeInts other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public SettingRealsFromNegativeInts Clone() { - return new SettingRealsFromNegativeInts(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as SettingRealsFromNegativeInts); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(SettingRealsFromNegativeInts other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(SettingRealsFromNegativeInts other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class ComplexOptionType1 : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType1()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[12]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ComplexOptionType1() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ComplexOptionType1(ComplexOptionType1 other) : this() { - foo_ = other.foo_; - foo2_ = other.foo2_; - foo3_ = other.foo3_; - foo4_ = other.foo4_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ComplexOptionType1 Clone() { - return new ComplexOptionType1(this); - } - - /// Field number for the "foo" field. - public const int FooFieldNumber = 1; - private int foo_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Foo { - get { return foo_; } - set { - foo_ = value; - } - } - - /// Field number for the "foo2" field. - public const int Foo2FieldNumber = 2; - private int foo2_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Foo2 { - get { return foo2_; } - set { - foo2_ = value; - } - } - - /// Field number for the "foo3" field. - public const int Foo3FieldNumber = 3; - private int foo3_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Foo3 { - get { return foo3_; } - set { - foo3_ = value; - } - } - - /// Field number for the "foo4" field. - public const int Foo4FieldNumber = 4; - private static readonly pb::FieldCodec _repeated_foo4_codec - = pb::FieldCodec.ForInt32(34); - private readonly pbc::RepeatedField foo4_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField Foo4 { - get { return foo4_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as ComplexOptionType1); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(ComplexOptionType1 other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Foo != other.Foo) return false; - if (Foo2 != other.Foo2) return false; - if (Foo3 != other.Foo3) return false; - if(!foo4_.Equals(other.foo4_)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Foo != 0) hash ^= Foo.GetHashCode(); - if (Foo2 != 0) hash ^= Foo2.GetHashCode(); - if (Foo3 != 0) hash ^= Foo3.GetHashCode(); - hash ^= foo4_.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Foo != 0) { - output.WriteRawTag(8); - output.WriteInt32(Foo); - } - if (Foo2 != 0) { - output.WriteRawTag(16); - output.WriteInt32(Foo2); - } - if (Foo3 != 0) { - output.WriteRawTag(24); - output.WriteInt32(Foo3); - } - foo4_.WriteTo(output, _repeated_foo4_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Foo != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Foo); - } - if (Foo2 != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Foo2); - } - if (Foo3 != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Foo3); - } - size += foo4_.CalculateSize(_repeated_foo4_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(ComplexOptionType1 other) { - if (other == null) { - return; - } - if (other.Foo != 0) { - Foo = other.Foo; - } - if (other.Foo2 != 0) { - Foo2 = other.Foo2; - } - if (other.Foo3 != 0) { - Foo3 = other.Foo3; - } - foo4_.Add(other.foo4_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - Foo = input.ReadInt32(); - break; - } - case 16: { - Foo2 = input.ReadInt32(); - break; - } - case 24: { - Foo3 = input.ReadInt32(); - break; - } - case 34: - case 32: { - foo4_.AddEntriesFrom(input, _repeated_foo4_codec); - break; - } - } - } - } - - } - - public sealed partial class ComplexOptionType2 : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType2()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[13]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ComplexOptionType2() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ComplexOptionType2(ComplexOptionType2 other) : this() { - Bar = other.bar_ != null ? other.Bar.Clone() : null; - baz_ = other.baz_; - Fred = other.fred_ != null ? other.Fred.Clone() : null; - barney_ = other.barney_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ComplexOptionType2 Clone() { - return new ComplexOptionType2(this); - } - - /// Field number for the "bar" field. - public const int BarFieldNumber = 1; - private global::UnitTest.Issues.TestProtos.ComplexOptionType1 bar_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::UnitTest.Issues.TestProtos.ComplexOptionType1 Bar { - get { return bar_; } - set { - bar_ = value; - } - } - - /// Field number for the "baz" field. - public const int BazFieldNumber = 2; - private int baz_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Baz { - get { return baz_; } - set { - baz_ = value; - } - } - - /// Field number for the "fred" field. - public const int FredFieldNumber = 3; - private global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 fred_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 Fred { - get { return fred_; } - set { - fred_ = value; - } - } - - /// Field number for the "barney" field. - public const int BarneyFieldNumber = 4; - private static readonly pb::FieldCodec _repeated_barney_codec - = pb::FieldCodec.ForMessage(34, global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Parser); - private readonly pbc::RepeatedField barney_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField Barney { - get { return barney_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as ComplexOptionType2); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(ComplexOptionType2 other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!object.Equals(Bar, other.Bar)) return false; - if (Baz != other.Baz) return false; - if (!object.Equals(Fred, other.Fred)) return false; - if(!barney_.Equals(other.barney_)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (bar_ != null) hash ^= Bar.GetHashCode(); - if (Baz != 0) hash ^= Baz.GetHashCode(); - if (fred_ != null) hash ^= Fred.GetHashCode(); - hash ^= barney_.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (bar_ != null) { - output.WriteRawTag(10); - output.WriteMessage(Bar); - } - if (Baz != 0) { - output.WriteRawTag(16); - output.WriteInt32(Baz); - } - if (fred_ != null) { - output.WriteRawTag(26); - output.WriteMessage(Fred); - } - barney_.WriteTo(output, _repeated_barney_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (bar_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(Bar); - } - if (Baz != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Baz); - } - if (fred_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(Fred); - } - size += barney_.CalculateSize(_repeated_barney_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(ComplexOptionType2 other) { - if (other == null) { - return; - } - if (other.bar_ != null) { - if (bar_ == null) { - bar_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType1(); - } - Bar.MergeFrom(other.Bar); - } - if (other.Baz != 0) { - Baz = other.Baz; - } - if (other.fred_ != null) { - if (fred_ == null) { - fred_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4(); - } - Fred.MergeFrom(other.Fred); - } - barney_.Add(other.barney_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - if (bar_ == null) { - bar_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType1(); - } - input.ReadMessage(bar_); - break; - } - case 16: { - Baz = input.ReadInt32(); - break; - } - case 26: { - if (fred_ == null) { - fred_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4(); - } - input.ReadMessage(fred_); - break; - } - case 34: { - barney_.AddEntriesFrom(input, _repeated_barney_codec); - break; - } - } - } - } - - #region Nested types - /// Container for nested types declared in the ComplexOptionType2 message type. - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static partial class Types { - public sealed partial class ComplexOptionType4 : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType4()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.ComplexOptionType2.Descriptor.NestedTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ComplexOptionType4() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ComplexOptionType4(ComplexOptionType4 other) : this() { - waldo_ = other.waldo_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ComplexOptionType4 Clone() { - return new ComplexOptionType4(this); - } - - /// Field number for the "waldo" field. - public const int WaldoFieldNumber = 1; - private int waldo_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Waldo { - get { return waldo_; } - set { - waldo_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as ComplexOptionType4); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(ComplexOptionType4 other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Waldo != other.Waldo) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Waldo != 0) hash ^= Waldo.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Waldo != 0) { - output.WriteRawTag(8); - output.WriteInt32(Waldo); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Waldo != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Waldo); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(ComplexOptionType4 other) { - if (other == null) { - return; - } - if (other.Waldo != 0) { - Waldo = other.Waldo; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - Waldo = input.ReadInt32(); - break; - } - } - } - } - - } - - } - #endregion - - } - - public sealed partial class ComplexOptionType3 : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType3()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[14]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ComplexOptionType3() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ComplexOptionType3(ComplexOptionType3 other) : this() { - qux_ = other.qux_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ComplexOptionType3 Clone() { - return new ComplexOptionType3(this); - } - - /// Field number for the "qux" field. - public const int QuxFieldNumber = 1; - private int qux_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Qux { - get { return qux_; } - set { - qux_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as ComplexOptionType3); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(ComplexOptionType3 other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Qux != other.Qux) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Qux != 0) hash ^= Qux.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Qux != 0) { - output.WriteRawTag(8); - output.WriteInt32(Qux); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Qux != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Qux); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(ComplexOptionType3 other) { - if (other == null) { - return; - } - if (other.Qux != 0) { - Qux = other.Qux; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - Qux = input.ReadInt32(); - break; - } - } - } - } - - } - - /// - /// Note that we try various different ways of naming the same extension. - /// - public sealed partial class VariousComplexOptions : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new VariousComplexOptions()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[15]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public VariousComplexOptions() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public VariousComplexOptions(VariousComplexOptions other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public VariousComplexOptions Clone() { - return new VariousComplexOptions(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as VariousComplexOptions); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(VariousComplexOptions other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(VariousComplexOptions other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - /// - /// A helper type used to test aggregate option parsing - /// - public sealed partial class Aggregate : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Aggregate()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[16]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Aggregate() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Aggregate(Aggregate other) : this() { - i_ = other.i_; - s_ = other.s_; - Sub = other.sub_ != null ? other.Sub.Clone() : null; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Aggregate Clone() { - return new Aggregate(this); - } - - /// Field number for the "i" field. - public const int IFieldNumber = 1; - private int i_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int I { - get { return i_; } - set { - i_ = value; - } - } - - /// Field number for the "s" field. - public const int SFieldNumber = 2; - private string s_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string S { - get { return s_; } - set { - s_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "sub" field. - public const int SubFieldNumber = 3; - private global::UnitTest.Issues.TestProtos.Aggregate sub_; - /// - /// A nested object - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::UnitTest.Issues.TestProtos.Aggregate Sub { - get { return sub_; } - set { - sub_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as Aggregate); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(Aggregate other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (I != other.I) return false; - if (S != other.S) return false; - if (!object.Equals(Sub, other.Sub)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (I != 0) hash ^= I.GetHashCode(); - if (S.Length != 0) hash ^= S.GetHashCode(); - if (sub_ != null) hash ^= Sub.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (I != 0) { - output.WriteRawTag(8); - output.WriteInt32(I); - } - if (S.Length != 0) { - output.WriteRawTag(18); - output.WriteString(S); - } - if (sub_ != null) { - output.WriteRawTag(26); - output.WriteMessage(Sub); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (I != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(I); - } - if (S.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(S); - } - if (sub_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(Sub); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(Aggregate other) { - if (other == null) { - return; - } - if (other.I != 0) { - I = other.I; - } - if (other.S.Length != 0) { - S = other.S; - } - if (other.sub_ != null) { - if (sub_ == null) { - sub_ = new global::UnitTest.Issues.TestProtos.Aggregate(); - } - Sub.MergeFrom(other.Sub); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - I = input.ReadInt32(); - break; - } - case 18: { - S = input.ReadString(); - break; - } - case 26: { - if (sub_ == null) { - sub_ = new global::UnitTest.Issues.TestProtos.Aggregate(); - } - input.ReadMessage(sub_); - break; - } - } - } - } - - } - - public sealed partial class AggregateMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new AggregateMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[17]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public AggregateMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public AggregateMessage(AggregateMessage other) : this() { - fieldname_ = other.fieldname_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public AggregateMessage Clone() { - return new AggregateMessage(this); - } - - /// Field number for the "fieldname" field. - public const int FieldnameFieldNumber = 1; - private int fieldname_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Fieldname { - get { return fieldname_; } - set { - fieldname_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as AggregateMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(AggregateMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Fieldname != other.Fieldname) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Fieldname != 0) hash ^= Fieldname.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Fieldname != 0) { - output.WriteRawTag(8); - output.WriteInt32(Fieldname); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Fieldname != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Fieldname); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(AggregateMessage other) { - if (other == null) { - return; - } - if (other.Fieldname != 0) { - Fieldname = other.Fieldname; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - Fieldname = input.ReadInt32(); - break; - } - } - } - } - - } - - /// - /// Test custom options for nested type. - /// - public sealed partial class NestedOptionType : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedOptionType()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[18]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedOptionType() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedOptionType(NestedOptionType other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedOptionType Clone() { - return new NestedOptionType(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as NestedOptionType); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(NestedOptionType other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(NestedOptionType other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - #region Nested types - /// Container for nested types declared in the NestedOptionType message type. - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static partial class Types { - public enum NestedEnum { - [pbr::OriginalName("UNSPECIFIED")] Unspecified = 0, - [pbr::OriginalName("NESTED_ENUM_VALUE")] Value = 1, - } - - public sealed partial class NestedMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.NestedOptionType.Descriptor.NestedTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedMessage(NestedMessage other) : this() { - nestedField_ = other.nestedField_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedMessage Clone() { - return new NestedMessage(this); - } - - /// Field number for the "nested_field" field. - public const int NestedFieldFieldNumber = 1; - private int nestedField_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int NestedField { - get { return nestedField_; } - set { - nestedField_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as NestedMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(NestedMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (NestedField != other.NestedField) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (NestedField != 0) hash ^= NestedField.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (NestedField != 0) { - output.WriteRawTag(8); - output.WriteInt32(NestedField); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (NestedField != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(NestedField); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(NestedMessage other) { - if (other == null) { - return; - } - if (other.NestedField != 0) { - NestedField = other.NestedField; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - NestedField = input.ReadInt32(); - break; - } - } - } - } - - } - - } - #endregion - - } - - #endregion - -} - -#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs deleted file mode 100644 index f6df4e872696a..0000000000000 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs +++ /dev/null @@ -1,174 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/unittest_import_proto3.proto -#pragma warning disable 1591, 0612, 3021 -#region Designer generated code - -using pb = global::Google.Protobuf; -using pbc = global::Google.Protobuf.Collections; -using pbr = global::Google.Protobuf.Reflection; -using scg = global::System.Collections.Generic; -namespace Google.Protobuf.TestProtos { - - /// Holder for reflection information generated from google/protobuf/unittest_import_proto3.proto - public static partial class UnittestImportProto3Reflection { - - #region Descriptor - /// File descriptor for google/protobuf/unittest_import_proto3.proto - public static pbr::FileDescriptor Descriptor { - get { return descriptor; } - } - private static pbr::FileDescriptor descriptor; - - static UnittestImportProto3Reflection() { - byte[] descriptorData = global::System.Convert.FromBase64String( - string.Concat( - "Cixnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3Byb3RvMy5wcm90", - "bxIYcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0GjNnb29nbGUvcHJvdG9idWYv", - "dW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90bzMucHJvdG8iGgoNSW1wb3J0", - "TWVzc2FnZRIJCgFkGAEgASgFKlkKCkltcG9ydEVudW0SGwoXSU1QT1JUX0VO", - "VU1fVU5TUEVDSUZJRUQQABIOCgpJTVBPUlRfRk9PEAcSDgoKSU1QT1JUX0JB", - "UhAIEg4KCklNUE9SVF9CQVoQCUI8Chhjb20uZ29vZ2xlLnByb3RvYnVmLnRl", - "c3RIAfgBAaoCGkdvb2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zUABiBnByb3Rv", - "Mw==")); - descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, - new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportPublicProto3Reflection.Descriptor, }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ImportEnum), }, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.ImportMessage), global::Google.Protobuf.TestProtos.ImportMessage.Parser, new[]{ "D" }, null, null, null) - })); - } - #endregion - - } - #region Enums - public enum ImportEnum { - [pbr::OriginalName("IMPORT_ENUM_UNSPECIFIED")] Unspecified = 0, - [pbr::OriginalName("IMPORT_FOO")] ImportFoo = 7, - [pbr::OriginalName("IMPORT_BAR")] ImportBar = 8, - [pbr::OriginalName("IMPORT_BAZ")] ImportBaz = 9, - } - - #endregion - - #region Messages - public sealed partial class ImportMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ImportMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestImportProto3Reflection.Descriptor.MessageTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ImportMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ImportMessage(ImportMessage other) : this() { - d_ = other.d_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ImportMessage Clone() { - return new ImportMessage(this); - } - - /// Field number for the "d" field. - public const int DFieldNumber = 1; - private int d_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int D { - get { return d_; } - set { - d_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as ImportMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(ImportMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (D != other.D) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (D != 0) hash ^= D.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (D != 0) { - output.WriteRawTag(8); - output.WriteInt32(D); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (D != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(D); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(ImportMessage other) { - if (other == null) { - return; - } - if (other.D != 0) { - D = other.D; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - D = input.ReadInt32(); - break; - } - } - } - } - - } - - #endregion - -} - -#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs deleted file mode 100644 index 67b8edf4647f7..0000000000000 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs +++ /dev/null @@ -1,160 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/unittest_import_public_proto3.proto -#pragma warning disable 1591, 0612, 3021 -#region Designer generated code - -using pb = global::Google.Protobuf; -using pbc = global::Google.Protobuf.Collections; -using pbr = global::Google.Protobuf.Reflection; -using scg = global::System.Collections.Generic; -namespace Google.Protobuf.TestProtos { - - /// Holder for reflection information generated from google/protobuf/unittest_import_public_proto3.proto - public static partial class UnittestImportPublicProto3Reflection { - - #region Descriptor - /// File descriptor for google/protobuf/unittest_import_public_proto3.proto - public static pbr::FileDescriptor Descriptor { - get { return descriptor; } - } - private static pbr::FileDescriptor descriptor; - - static UnittestImportPublicProto3Reflection() { - byte[] descriptorData = global::System.Convert.FromBase64String( - string.Concat( - "CjNnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90", - "bzMucHJvdG8SGHByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydCIgChNQdWJsaWNJ", - "bXBvcnRNZXNzYWdlEgkKAWUYASABKAVCNwoYY29tLmdvb2dsZS5wcm90b2J1", - "Zi50ZXN0qgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw==")); - descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, - new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.PublicImportMessage), global::Google.Protobuf.TestProtos.PublicImportMessage.Parser, new[]{ "E" }, null, null, null) - })); - } - #endregion - - } - #region Messages - public sealed partial class PublicImportMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PublicImportMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestImportPublicProto3Reflection.Descriptor.MessageTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public PublicImportMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public PublicImportMessage(PublicImportMessage other) : this() { - e_ = other.e_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public PublicImportMessage Clone() { - return new PublicImportMessage(this); - } - - /// Field number for the "e" field. - public const int EFieldNumber = 1; - private int e_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int E { - get { return e_; } - set { - e_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as PublicImportMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(PublicImportMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (E != other.E) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (E != 0) hash ^= E.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (E != 0) { - output.WriteRawTag(8); - output.WriteInt32(E); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (E != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(E); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(PublicImportMessage other) { - if (other == null) { - return; - } - if (other.E != 0) { - E = other.E; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - E = input.ReadInt32(); - break; - } - } - } - } - - } - - #endregion - -} - -#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs deleted file mode 100644 index 7c0ba8a677c79..0000000000000 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs +++ /dev/null @@ -1,1736 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: unittest_issues.proto -#pragma warning disable 1591, 0612, 3021 -#region Designer generated code - -using pb = global::Google.Protobuf; -using pbc = global::Google.Protobuf.Collections; -using pbr = global::Google.Protobuf.Reflection; -using scg = global::System.Collections.Generic; -namespace UnitTest.Issues.TestProtos { - - /// Holder for reflection information generated from unittest_issues.proto - public static partial class UnittestIssuesReflection { - - #region Descriptor - /// File descriptor for unittest_issues.proto - public static pbr::FileDescriptor Descriptor { - get { return descriptor; } - } - private static pbr::FileDescriptor descriptor; - - static UnittestIssuesReflection() { - byte[] descriptorData = global::System.Convert.FromBase64String( - string.Concat( - "ChV1bml0dGVzdF9pc3N1ZXMucHJvdG8SD3VuaXR0ZXN0X2lzc3VlcyInCghJ", - "c3N1ZTMwNxobCgpOZXN0ZWRPbmNlGg0KC05lc3RlZFR3aWNlIrABChNOZWdh", - "dGl2ZUVudW1NZXNzYWdlEiwKBXZhbHVlGAEgASgOMh0udW5pdHRlc3RfaXNz", - "dWVzLk5lZ2F0aXZlRW51bRIxCgZ2YWx1ZXMYAiADKA4yHS51bml0dGVzdF9p", - "c3N1ZXMuTmVnYXRpdmVFbnVtQgIQABI4Cg1wYWNrZWRfdmFsdWVzGAMgAygO", - "Mh0udW5pdHRlc3RfaXNzdWVzLk5lZ2F0aXZlRW51bUICEAEiEQoPRGVwcmVj", - "YXRlZENoaWxkIrkCChdEZXByZWNhdGVkRmllbGRzTWVzc2FnZRIaCg5Qcmlt", - "aXRpdmVWYWx1ZRgBIAEoBUICGAESGgoOUHJpbWl0aXZlQXJyYXkYAiADKAVC", - "AhgBEjoKDE1lc3NhZ2VWYWx1ZRgDIAEoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5E", - "ZXByZWNhdGVkQ2hpbGRCAhgBEjoKDE1lc3NhZ2VBcnJheRgEIAMoCzIgLnVu", - "aXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRCAhgBEjYKCUVudW1WYWx1", - "ZRgFIAEoDjIfLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkRW51bUICGAES", - "NgoJRW51bUFycmF5GAYgAygOMh8udW5pdHRlc3RfaXNzdWVzLkRlcHJlY2F0", - "ZWRFbnVtQgIYASIZCglJdGVtRmllbGQSDAoEaXRlbRgBIAEoBSJECg1SZXNl", - "cnZlZE5hbWVzEg0KBXR5cGVzGAEgASgFEhIKCmRlc2NyaXB0b3IYAiABKAUa", - "EAoOU29tZU5lc3RlZFR5cGUioAEKFVRlc3RKc29uRmllbGRPcmRlcmluZxIT", - "CgtwbGFpbl9pbnQzMhgEIAEoBRITCglvMV9zdHJpbmcYAiABKAlIABISCghv", - "MV9pbnQzMhgFIAEoBUgAEhQKDHBsYWluX3N0cmluZxgBIAEoCRISCghvMl9p", - "bnQzMhgGIAEoBUgBEhMKCW8yX3N0cmluZxgDIAEoCUgBQgQKAm8xQgQKAm8y", - "IksKDFRlc3RKc29uTmFtZRIMCgRuYW1lGAEgASgJEhkKC2Rlc2NyaXB0aW9u", - "GAIgASgJUgRkZXNjEhIKBGd1aWQYAyABKAlSBGV4aWQqVQoMTmVnYXRpdmVF", - "bnVtEhYKEk5FR0FUSVZFX0VOVU1fWkVSTxAAEhYKCUZpdmVCZWxvdxD7////", - "//////8BEhUKCE1pbnVzT25lEP///////////wEqLgoORGVwcmVjYXRlZEVu", - "dW0SEwoPREVQUkVDQVRFRF9aRVJPEAASBwoDb25lEAFCH0gBqgIaVW5pdFRl", - "c3QuSXNzdWVzLlRlc3RQcm90b3NiBnByb3RvMw==")); - descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, - new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.NegativeEnum), typeof(global::UnitTest.Issues.TestProtos.DeprecatedEnum), }, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307), global::UnitTest.Issues.TestProtos.Issue307.Parser, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Parser, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice.Parser, null, null, null, null)})}), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NegativeEnumMessage), global::UnitTest.Issues.TestProtos.NegativeEnumMessage.Parser, new[]{ "Value", "Values", "PackedValues" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedChild), global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage), global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Parser, new[]{ "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ItemField), global::UnitTest.Issues.TestProtos.ItemField.Parser, new[]{ "Item" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames), global::UnitTest.Issues.TestProtos.ReservedNames.Parser, new[]{ "Types_", "Descriptor_" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType), global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType.Parser, null, null, null, null)}), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering), global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering.Parser, new[]{ "PlainInt32", "O1String", "O1Int32", "PlainString", "O2Int32", "O2String" }, new[]{ "O1", "O2" }, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonName), global::UnitTest.Issues.TestProtos.TestJsonName.Parser, new[]{ "Name", "Description", "Guid" }, null, null, null) - })); - } - #endregion - - } - #region Enums - public enum NegativeEnum { - [pbr::OriginalName("NEGATIVE_ENUM_ZERO")] Zero = 0, - [pbr::OriginalName("FiveBelow")] FiveBelow = -5, - [pbr::OriginalName("MinusOne")] MinusOne = -1, - } - - public enum DeprecatedEnum { - [pbr::OriginalName("DEPRECATED_ZERO")] DeprecatedZero = 0, - [pbr::OriginalName("one")] One = 1, - } - - #endregion - - #region Messages - /// - /// Issue 307: when generating doubly-nested types, any references - /// should be of the form A.Types.B.Types.C. - /// - public sealed partial class Issue307 : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Issue307()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Issue307() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Issue307(Issue307 other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Issue307 Clone() { - return new Issue307(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as Issue307); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(Issue307 other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(Issue307 other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - #region Nested types - /// Container for nested types declared in the Issue307 message type. - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static partial class Types { - public sealed partial class NestedOnce : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedOnce()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.Issue307.Descriptor.NestedTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedOnce() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedOnce(NestedOnce other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedOnce Clone() { - return new NestedOnce(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as NestedOnce); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(NestedOnce other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(NestedOnce other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - #region Nested types - /// Container for nested types declared in the NestedOnce message type. - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static partial class Types { - public sealed partial class NestedTwice : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedTwice()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Descriptor.NestedTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedTwice() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedTwice(NestedTwice other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedTwice Clone() { - return new NestedTwice(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as NestedTwice); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(NestedTwice other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(NestedTwice other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - } - #endregion - - } - - } - #endregion - - } - - public sealed partial class NegativeEnumMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NegativeEnumMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[1]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NegativeEnumMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NegativeEnumMessage(NegativeEnumMessage other) : this() { - value_ = other.value_; - values_ = other.values_.Clone(); - packedValues_ = other.packedValues_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NegativeEnumMessage Clone() { - return new NegativeEnumMessage(this); - } - - /// Field number for the "value" field. - public const int ValueFieldNumber = 1; - private global::UnitTest.Issues.TestProtos.NegativeEnum value_ = 0; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::UnitTest.Issues.TestProtos.NegativeEnum Value { - get { return value_; } - set { - value_ = value; - } - } - - /// Field number for the "values" field. - public const int ValuesFieldNumber = 2; - private static readonly pb::FieldCodec _repeated_values_codec - = pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x); - private readonly pbc::RepeatedField values_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField Values { - get { return values_; } - } - - /// Field number for the "packed_values" field. - public const int PackedValuesFieldNumber = 3; - private static readonly pb::FieldCodec _repeated_packedValues_codec - = pb::FieldCodec.ForEnum(26, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x); - private readonly pbc::RepeatedField packedValues_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedValues { - get { return packedValues_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as NegativeEnumMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(NegativeEnumMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Value != other.Value) return false; - if(!values_.Equals(other.values_)) return false; - if(!packedValues_.Equals(other.packedValues_)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Value != 0) hash ^= Value.GetHashCode(); - hash ^= values_.GetHashCode(); - hash ^= packedValues_.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Value != 0) { - output.WriteRawTag(8); - output.WriteEnum((int) Value); - } - values_.WriteTo(output, _repeated_values_codec); - packedValues_.WriteTo(output, _repeated_packedValues_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Value != 0) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Value); - } - size += values_.CalculateSize(_repeated_values_codec); - size += packedValues_.CalculateSize(_repeated_packedValues_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(NegativeEnumMessage other) { - if (other == null) { - return; - } - if (other.Value != 0) { - Value = other.Value; - } - values_.Add(other.values_); - packedValues_.Add(other.packedValues_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - value_ = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum(); - break; - } - case 18: - case 16: { - values_.AddEntriesFrom(input, _repeated_values_codec); - break; - } - case 26: - case 24: { - packedValues_.AddEntriesFrom(input, _repeated_packedValues_codec); - break; - } - } - } - } - - } - - public sealed partial class DeprecatedChild : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DeprecatedChild()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[2]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public DeprecatedChild() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public DeprecatedChild(DeprecatedChild other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public DeprecatedChild Clone() { - return new DeprecatedChild(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as DeprecatedChild); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(DeprecatedChild other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(DeprecatedChild other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class DeprecatedFieldsMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DeprecatedFieldsMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[3]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public DeprecatedFieldsMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public DeprecatedFieldsMessage(DeprecatedFieldsMessage other) : this() { - primitiveValue_ = other.primitiveValue_; - primitiveArray_ = other.primitiveArray_.Clone(); - MessageValue = other.messageValue_ != null ? other.MessageValue.Clone() : null; - messageArray_ = other.messageArray_.Clone(); - enumValue_ = other.enumValue_; - enumArray_ = other.enumArray_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public DeprecatedFieldsMessage Clone() { - return new DeprecatedFieldsMessage(this); - } - - /// Field number for the "PrimitiveValue" field. - public const int PrimitiveValueFieldNumber = 1; - private int primitiveValue_; - [global::System.ObsoleteAttribute] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int PrimitiveValue { - get { return primitiveValue_; } - set { - primitiveValue_ = value; - } - } - - /// Field number for the "PrimitiveArray" field. - public const int PrimitiveArrayFieldNumber = 2; - private static readonly pb::FieldCodec _repeated_primitiveArray_codec - = pb::FieldCodec.ForInt32(18); - private readonly pbc::RepeatedField primitiveArray_ = new pbc::RepeatedField(); - [global::System.ObsoleteAttribute] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PrimitiveArray { - get { return primitiveArray_; } - } - - /// Field number for the "MessageValue" field. - public const int MessageValueFieldNumber = 3; - private global::UnitTest.Issues.TestProtos.DeprecatedChild messageValue_; - [global::System.ObsoleteAttribute] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::UnitTest.Issues.TestProtos.DeprecatedChild MessageValue { - get { return messageValue_; } - set { - messageValue_ = value; - } - } - - /// Field number for the "MessageArray" field. - public const int MessageArrayFieldNumber = 4; - private static readonly pb::FieldCodec _repeated_messageArray_codec - = pb::FieldCodec.ForMessage(34, global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser); - private readonly pbc::RepeatedField messageArray_ = new pbc::RepeatedField(); - [global::System.ObsoleteAttribute] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField MessageArray { - get { return messageArray_; } - } - - /// Field number for the "EnumValue" field. - public const int EnumValueFieldNumber = 5; - private global::UnitTest.Issues.TestProtos.DeprecatedEnum enumValue_ = 0; - [global::System.ObsoleteAttribute] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::UnitTest.Issues.TestProtos.DeprecatedEnum EnumValue { - get { return enumValue_; } - set { - enumValue_ = value; - } - } - - /// Field number for the "EnumArray" field. - public const int EnumArrayFieldNumber = 6; - private static readonly pb::FieldCodec _repeated_enumArray_codec - = pb::FieldCodec.ForEnum(50, x => (int) x, x => (global::UnitTest.Issues.TestProtos.DeprecatedEnum) x); - private readonly pbc::RepeatedField enumArray_ = new pbc::RepeatedField(); - [global::System.ObsoleteAttribute] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField EnumArray { - get { return enumArray_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as DeprecatedFieldsMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(DeprecatedFieldsMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (PrimitiveValue != other.PrimitiveValue) return false; - if(!primitiveArray_.Equals(other.primitiveArray_)) return false; - if (!object.Equals(MessageValue, other.MessageValue)) return false; - if(!messageArray_.Equals(other.messageArray_)) return false; - if (EnumValue != other.EnumValue) return false; - if(!enumArray_.Equals(other.enumArray_)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (PrimitiveValue != 0) hash ^= PrimitiveValue.GetHashCode(); - hash ^= primitiveArray_.GetHashCode(); - if (messageValue_ != null) hash ^= MessageValue.GetHashCode(); - hash ^= messageArray_.GetHashCode(); - if (EnumValue != 0) hash ^= EnumValue.GetHashCode(); - hash ^= enumArray_.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (PrimitiveValue != 0) { - output.WriteRawTag(8); - output.WriteInt32(PrimitiveValue); - } - primitiveArray_.WriteTo(output, _repeated_primitiveArray_codec); - if (messageValue_ != null) { - output.WriteRawTag(26); - output.WriteMessage(MessageValue); - } - messageArray_.WriteTo(output, _repeated_messageArray_codec); - if (EnumValue != 0) { - output.WriteRawTag(40); - output.WriteEnum((int) EnumValue); - } - enumArray_.WriteTo(output, _repeated_enumArray_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (PrimitiveValue != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(PrimitiveValue); - } - size += primitiveArray_.CalculateSize(_repeated_primitiveArray_codec); - if (messageValue_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageValue); - } - size += messageArray_.CalculateSize(_repeated_messageArray_codec); - if (EnumValue != 0) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumValue); - } - size += enumArray_.CalculateSize(_repeated_enumArray_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(DeprecatedFieldsMessage other) { - if (other == null) { - return; - } - if (other.PrimitiveValue != 0) { - PrimitiveValue = other.PrimitiveValue; - } - primitiveArray_.Add(other.primitiveArray_); - if (other.messageValue_ != null) { - if (messageValue_ == null) { - messageValue_ = new global::UnitTest.Issues.TestProtos.DeprecatedChild(); - } - MessageValue.MergeFrom(other.MessageValue); - } - messageArray_.Add(other.messageArray_); - if (other.EnumValue != 0) { - EnumValue = other.EnumValue; - } - enumArray_.Add(other.enumArray_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - PrimitiveValue = input.ReadInt32(); - break; - } - case 18: - case 16: { - primitiveArray_.AddEntriesFrom(input, _repeated_primitiveArray_codec); - break; - } - case 26: { - if (messageValue_ == null) { - messageValue_ = new global::UnitTest.Issues.TestProtos.DeprecatedChild(); - } - input.ReadMessage(messageValue_); - break; - } - case 34: { - messageArray_.AddEntriesFrom(input, _repeated_messageArray_codec); - break; - } - case 40: { - enumValue_ = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) input.ReadEnum(); - break; - } - case 50: - case 48: { - enumArray_.AddEntriesFrom(input, _repeated_enumArray_codec); - break; - } - } - } - } - - } - - /// - /// Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45 - /// - public sealed partial class ItemField : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ItemField()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[4]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ItemField() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ItemField(ItemField other) : this() { - item_ = other.item_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ItemField Clone() { - return new ItemField(this); - } - - /// Field number for the "item" field. - public const int ItemFieldNumber = 1; - private int item_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Item { - get { return item_; } - set { - item_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as ItemField); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(ItemField other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Item != other.Item) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Item != 0) hash ^= Item.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Item != 0) { - output.WriteRawTag(8); - output.WriteInt32(Item); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Item != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Item); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(ItemField other) { - if (other == null) { - return; - } - if (other.Item != 0) { - Item = other.Item; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - Item = input.ReadInt32(); - break; - } - } - } - } - - } - - public sealed partial class ReservedNames : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ReservedNames()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[5]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ReservedNames() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ReservedNames(ReservedNames other) : this() { - types_ = other.types_; - descriptor_ = other.descriptor_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ReservedNames Clone() { - return new ReservedNames(this); - } - - /// Field number for the "types" field. - public const int Types_FieldNumber = 1; - private int types_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Types_ { - get { return types_; } - set { - types_ = value; - } - } - - /// Field number for the "descriptor" field. - public const int Descriptor_FieldNumber = 2; - private int descriptor_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Descriptor_ { - get { return descriptor_; } - set { - descriptor_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as ReservedNames); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(ReservedNames other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Types_ != other.Types_) return false; - if (Descriptor_ != other.Descriptor_) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Types_ != 0) hash ^= Types_.GetHashCode(); - if (Descriptor_ != 0) hash ^= Descriptor_.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Types_ != 0) { - output.WriteRawTag(8); - output.WriteInt32(Types_); - } - if (Descriptor_ != 0) { - output.WriteRawTag(16); - output.WriteInt32(Descriptor_); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Types_ != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Types_); - } - if (Descriptor_ != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Descriptor_); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(ReservedNames other) { - if (other == null) { - return; - } - if (other.Types_ != 0) { - Types_ = other.Types_; - } - if (other.Descriptor_ != 0) { - Descriptor_ = other.Descriptor_; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - Types_ = input.ReadInt32(); - break; - } - case 16: { - Descriptor_ = input.ReadInt32(); - break; - } - } - } - } - - #region Nested types - /// Container for nested types declared in the ReservedNames message type. - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static partial class Types { - /// - /// Force a nested type called Types - /// - public sealed partial class SomeNestedType : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SomeNestedType()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.ReservedNames.Descriptor.NestedTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public SomeNestedType() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public SomeNestedType(SomeNestedType other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public SomeNestedType Clone() { - return new SomeNestedType(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as SomeNestedType); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(SomeNestedType other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(SomeNestedType other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - } - #endregion - - } - - /// - /// These fields are deliberately not declared in numeric - /// order, and the oneof fields aren't contiguous either. - /// This allows for reasonably robust tests of JSON output - /// ordering. - /// TestFieldOrderings in unittest_proto3.proto is similar, - /// but doesn't include oneofs. - /// TODO: Consider adding oneofs to TestFieldOrderings, although - /// that will require fixing other tests in multiple platforms. - /// Alternatively, consider just adding this to - /// unittest_proto3.proto if multiple platforms want it. - /// - public sealed partial class TestJsonFieldOrdering : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestJsonFieldOrdering()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[6]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestJsonFieldOrdering() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestJsonFieldOrdering(TestJsonFieldOrdering other) : this() { - plainInt32_ = other.plainInt32_; - plainString_ = other.plainString_; - switch (other.O1Case) { - case O1OneofCase.O1String: - O1String = other.O1String; - break; - case O1OneofCase.O1Int32: - O1Int32 = other.O1Int32; - break; - } - - switch (other.O2Case) { - case O2OneofCase.O2Int32: - O2Int32 = other.O2Int32; - break; - case O2OneofCase.O2String: - O2String = other.O2String; - break; - } - - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestJsonFieldOrdering Clone() { - return new TestJsonFieldOrdering(this); - } - - /// Field number for the "plain_int32" field. - public const int PlainInt32FieldNumber = 4; - private int plainInt32_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int PlainInt32 { - get { return plainInt32_; } - set { - plainInt32_ = value; - } - } - - /// Field number for the "o1_string" field. - public const int O1StringFieldNumber = 2; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string O1String { - get { return o1Case_ == O1OneofCase.O1String ? (string) o1_ : ""; } - set { - o1_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - o1Case_ = O1OneofCase.O1String; - } - } - - /// Field number for the "o1_int32" field. - public const int O1Int32FieldNumber = 5; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int O1Int32 { - get { return o1Case_ == O1OneofCase.O1Int32 ? (int) o1_ : 0; } - set { - o1_ = value; - o1Case_ = O1OneofCase.O1Int32; - } - } - - /// Field number for the "plain_string" field. - public const int PlainStringFieldNumber = 1; - private string plainString_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string PlainString { - get { return plainString_; } - set { - plainString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "o2_int32" field. - public const int O2Int32FieldNumber = 6; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int O2Int32 { - get { return o2Case_ == O2OneofCase.O2Int32 ? (int) o2_ : 0; } - set { - o2_ = value; - o2Case_ = O2OneofCase.O2Int32; - } - } - - /// Field number for the "o2_string" field. - public const int O2StringFieldNumber = 3; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string O2String { - get { return o2Case_ == O2OneofCase.O2String ? (string) o2_ : ""; } - set { - o2_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - o2Case_ = O2OneofCase.O2String; - } - } - - private object o1_; - /// Enum of possible cases for the "o1" oneof. - public enum O1OneofCase { - None = 0, - O1String = 2, - O1Int32 = 5, - } - private O1OneofCase o1Case_ = O1OneofCase.None; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public O1OneofCase O1Case { - get { return o1Case_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void ClearO1() { - o1Case_ = O1OneofCase.None; - o1_ = null; - } - - private object o2_; - /// Enum of possible cases for the "o2" oneof. - public enum O2OneofCase { - None = 0, - O2Int32 = 6, - O2String = 3, - } - private O2OneofCase o2Case_ = O2OneofCase.None; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public O2OneofCase O2Case { - get { return o2Case_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void ClearO2() { - o2Case_ = O2OneofCase.None; - o2_ = null; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestJsonFieldOrdering); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestJsonFieldOrdering other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (PlainInt32 != other.PlainInt32) return false; - if (O1String != other.O1String) return false; - if (O1Int32 != other.O1Int32) return false; - if (PlainString != other.PlainString) return false; - if (O2Int32 != other.O2Int32) return false; - if (O2String != other.O2String) return false; - if (O1Case != other.O1Case) return false; - if (O2Case != other.O2Case) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (PlainInt32 != 0) hash ^= PlainInt32.GetHashCode(); - if (o1Case_ == O1OneofCase.O1String) hash ^= O1String.GetHashCode(); - if (o1Case_ == O1OneofCase.O1Int32) hash ^= O1Int32.GetHashCode(); - if (PlainString.Length != 0) hash ^= PlainString.GetHashCode(); - if (o2Case_ == O2OneofCase.O2Int32) hash ^= O2Int32.GetHashCode(); - if (o2Case_ == O2OneofCase.O2String) hash ^= O2String.GetHashCode(); - hash ^= (int) o1Case_; - hash ^= (int) o2Case_; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (PlainString.Length != 0) { - output.WriteRawTag(10); - output.WriteString(PlainString); - } - if (o1Case_ == O1OneofCase.O1String) { - output.WriteRawTag(18); - output.WriteString(O1String); - } - if (o2Case_ == O2OneofCase.O2String) { - output.WriteRawTag(26); - output.WriteString(O2String); - } - if (PlainInt32 != 0) { - output.WriteRawTag(32); - output.WriteInt32(PlainInt32); - } - if (o1Case_ == O1OneofCase.O1Int32) { - output.WriteRawTag(40); - output.WriteInt32(O1Int32); - } - if (o2Case_ == O2OneofCase.O2Int32) { - output.WriteRawTag(48); - output.WriteInt32(O2Int32); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (PlainInt32 != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(PlainInt32); - } - if (o1Case_ == O1OneofCase.O1String) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(O1String); - } - if (o1Case_ == O1OneofCase.O1Int32) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(O1Int32); - } - if (PlainString.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(PlainString); - } - if (o2Case_ == O2OneofCase.O2Int32) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(O2Int32); - } - if (o2Case_ == O2OneofCase.O2String) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(O2String); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestJsonFieldOrdering other) { - if (other == null) { - return; - } - if (other.PlainInt32 != 0) { - PlainInt32 = other.PlainInt32; - } - if (other.PlainString.Length != 0) { - PlainString = other.PlainString; - } - switch (other.O1Case) { - case O1OneofCase.O1String: - O1String = other.O1String; - break; - case O1OneofCase.O1Int32: - O1Int32 = other.O1Int32; - break; - } - - switch (other.O2Case) { - case O2OneofCase.O2Int32: - O2Int32 = other.O2Int32; - break; - case O2OneofCase.O2String: - O2String = other.O2String; - break; - } - - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - PlainString = input.ReadString(); - break; - } - case 18: { - O1String = input.ReadString(); - break; - } - case 26: { - O2String = input.ReadString(); - break; - } - case 32: { - PlainInt32 = input.ReadInt32(); - break; - } - case 40: { - O1Int32 = input.ReadInt32(); - break; - } - case 48: { - O2Int32 = input.ReadInt32(); - break; - } - } - } - } - - } - - public sealed partial class TestJsonName : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestJsonName()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[7]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestJsonName() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestJsonName(TestJsonName other) : this() { - name_ = other.name_; - description_ = other.description_; - guid_ = other.guid_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestJsonName Clone() { - return new TestJsonName(this); - } - - /// Field number for the "name" field. - public const int NameFieldNumber = 1; - private string name_ = ""; - /// - /// Message for testing the effects for of the json_name option - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string Name { - get { return name_; } - set { - name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "description" field. - public const int DescriptionFieldNumber = 2; - private string description_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string Description { - get { return description_; } - set { - description_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "guid" field. - public const int GuidFieldNumber = 3; - private string guid_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string Guid { - get { return guid_; } - set { - guid_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestJsonName); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestJsonName other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Name != other.Name) return false; - if (Description != other.Description) return false; - if (Guid != other.Guid) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Name.Length != 0) hash ^= Name.GetHashCode(); - if (Description.Length != 0) hash ^= Description.GetHashCode(); - if (Guid.Length != 0) hash ^= Guid.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Name.Length != 0) { - output.WriteRawTag(10); - output.WriteString(Name); - } - if (Description.Length != 0) { - output.WriteRawTag(18); - output.WriteString(Description); - } - if (Guid.Length != 0) { - output.WriteRawTag(26); - output.WriteString(Guid); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Name.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); - } - if (Description.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(Description); - } - if (Guid.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(Guid); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestJsonName other) { - if (other == null) { - return; - } - if (other.Name.Length != 0) { - Name = other.Name; - } - if (other.Description.Length != 0) { - Description = other.Description; - } - if (other.Guid.Length != 0) { - Guid = other.Guid; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - Name = input.ReadString(); - break; - } - case 18: { - Description = input.ReadString(); - break; - } - case 26: { - Guid = input.ReadString(); - break; - } - } - } - } - - } - - #endregion - -} - -#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs deleted file mode 100644 index c11ab84d0168d..0000000000000 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs +++ /dev/null @@ -1,6766 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/unittest_proto3.proto -#pragma warning disable 1591, 0612, 3021 -#region Designer generated code - -using pb = global::Google.Protobuf; -using pbc = global::Google.Protobuf.Collections; -using pbr = global::Google.Protobuf.Reflection; -using scg = global::System.Collections.Generic; -namespace Google.Protobuf.TestProtos { - - /// Holder for reflection information generated from google/protobuf/unittest_proto3.proto - public static partial class UnittestProto3Reflection { - - #region Descriptor - /// File descriptor for google/protobuf/unittest_proto3.proto - public static pbr::FileDescriptor Descriptor { - get { return descriptor; } - } - private static pbr::FileDescriptor descriptor; - - static UnittestProto3Reflection() { - byte[] descriptorData = global::System.Convert.FromBase64String( - string.Concat( - "CiVnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfcHJvdG8zLnByb3RvEhFwcm90", - "b2J1Zl91bml0dGVzdBosZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2ltcG9y", - "dF9wcm90bzMucHJvdG8i8A8KDFRlc3RBbGxUeXBlcxIUCgxzaW5nbGVfaW50", - "MzIYASABKAUSFAoMc2luZ2xlX2ludDY0GAIgASgDEhUKDXNpbmdsZV91aW50", - "MzIYAyABKA0SFQoNc2luZ2xlX3VpbnQ2NBgEIAEoBBIVCg1zaW5nbGVfc2lu", - "dDMyGAUgASgREhUKDXNpbmdsZV9zaW50NjQYBiABKBISFgoOc2luZ2xlX2Zp", - "eGVkMzIYByABKAcSFgoOc2luZ2xlX2ZpeGVkNjQYCCABKAYSFwoPc2luZ2xl", - "X3NmaXhlZDMyGAkgASgPEhcKD3NpbmdsZV9zZml4ZWQ2NBgKIAEoEBIUCgxz", - "aW5nbGVfZmxvYXQYCyABKAISFQoNc2luZ2xlX2RvdWJsZRgMIAEoARITCgtz", - "aW5nbGVfYm9vbBgNIAEoCBIVCg1zaW5nbGVfc3RyaW5nGA4gASgJEhQKDHNp", - "bmdsZV9ieXRlcxgPIAEoDBJMChVzaW5nbGVfbmVzdGVkX21lc3NhZ2UYEiAB", - "KAsyLS5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkTWVz", - "c2FnZRJBChZzaW5nbGVfZm9yZWlnbl9tZXNzYWdlGBMgASgLMiEucHJvdG9i", - "dWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2USRgoVc2luZ2xlX2ltcG9ydF9t", - "ZXNzYWdlGBQgASgLMicucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9y", - "dE1lc3NhZ2USRgoSc2luZ2xlX25lc3RlZF9lbnVtGBUgASgOMioucHJvdG9i", - "dWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW0SOwoTc2luZ2xl", - "X2ZvcmVpZ25fZW51bRgWIAEoDjIeLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVp", - "Z25FbnVtEkAKEnNpbmdsZV9pbXBvcnRfZW51bRgXIAEoDjIkLnByb3RvYnVm", - "X3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtElMKHHNpbmdsZV9wdWJsaWNf", - "aW1wb3J0X21lc3NhZ2UYGiABKAsyLS5wcm90b2J1Zl91bml0dGVzdF9pbXBv", - "cnQuUHVibGljSW1wb3J0TWVzc2FnZRIWCg5yZXBlYXRlZF9pbnQzMhgfIAMo", - "BRIWCg5yZXBlYXRlZF9pbnQ2NBggIAMoAxIXCg9yZXBlYXRlZF91aW50MzIY", - "ISADKA0SFwoPcmVwZWF0ZWRfdWludDY0GCIgAygEEhcKD3JlcGVhdGVkX3Np", - "bnQzMhgjIAMoERIXCg9yZXBlYXRlZF9zaW50NjQYJCADKBISGAoQcmVwZWF0", - "ZWRfZml4ZWQzMhglIAMoBxIYChByZXBlYXRlZF9maXhlZDY0GCYgAygGEhkK", - "EXJlcGVhdGVkX3NmaXhlZDMyGCcgAygPEhkKEXJlcGVhdGVkX3NmaXhlZDY0", - "GCggAygQEhYKDnJlcGVhdGVkX2Zsb2F0GCkgAygCEhcKD3JlcGVhdGVkX2Rv", - "dWJsZRgqIAMoARIVCg1yZXBlYXRlZF9ib29sGCsgAygIEhcKD3JlcGVhdGVk", - "X3N0cmluZxgsIAMoCRIWCg5yZXBlYXRlZF9ieXRlcxgtIAMoDBJOChdyZXBl", - "YXRlZF9uZXN0ZWRfbWVzc2FnZRgwIAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0", - "LlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlEkMKGHJlcGVhdGVkX2ZvcmVp", - "Z25fbWVzc2FnZRgxIAMoCzIhLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25N", - "ZXNzYWdlEkgKF3JlcGVhdGVkX2ltcG9ydF9tZXNzYWdlGDIgAygLMicucHJv", - "dG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2USSAoUcmVwZWF0", - "ZWRfbmVzdGVkX2VudW0YMyADKA4yKi5wcm90b2J1Zl91bml0dGVzdC5UZXN0", - "QWxsVHlwZXMuTmVzdGVkRW51bRI9ChVyZXBlYXRlZF9mb3JlaWduX2VudW0Y", - "NCADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bRJCChRyZXBl", - "YXRlZF9pbXBvcnRfZW51bRg1IAMoDjIkLnByb3RvYnVmX3VuaXR0ZXN0X2lt", - "cG9ydC5JbXBvcnRFbnVtElUKHnJlcGVhdGVkX3B1YmxpY19pbXBvcnRfbWVz", - "c2FnZRg2IAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJ", - "bXBvcnRNZXNzYWdlEhYKDG9uZW9mX3VpbnQzMhhvIAEoDUgAEk0KFG9uZW9m", - "X25lc3RlZF9tZXNzYWdlGHAgASgLMi0ucHJvdG9idWZfdW5pdHRlc3QuVGVz", - "dEFsbFR5cGVzLk5lc3RlZE1lc3NhZ2VIABIWCgxvbmVvZl9zdHJpbmcYcSAB", - "KAlIABIVCgtvbmVvZl9ieXRlcxhyIAEoDEgAGhsKDU5lc3RlZE1lc3NhZ2US", - "CgoCYmIYASABKAUiVgoKTmVzdGVkRW51bRIbChdORVNURURfRU5VTV9VTlNQ", - "RUNJRklFRBAAEgcKA0ZPTxABEgcKA0JBUhACEgcKA0JBWhADEhAKA05FRxD/", - "//////////8BQg0KC29uZW9mX2ZpZWxkIrsBChJOZXN0ZWRUZXN0QWxsVHlw", - "ZXMSNAoFY2hpbGQYASABKAsyJS5wcm90b2J1Zl91bml0dGVzdC5OZXN0ZWRU", - "ZXN0QWxsVHlwZXMSMAoHcGF5bG9hZBgCIAEoCzIfLnByb3RvYnVmX3VuaXR0", - "ZXN0LlRlc3RBbGxUeXBlcxI9Cg5yZXBlYXRlZF9jaGlsZBgDIAMoCzIlLnBy", - "b3RvYnVmX3VuaXR0ZXN0Lk5lc3RlZFRlc3RBbGxUeXBlcyI0ChRUZXN0RGVw", - "cmVjYXRlZEZpZWxkcxIcChBkZXByZWNhdGVkX2ludDMyGAEgASgFQgIYASIb", - "Cg5Gb3JlaWduTWVzc2FnZRIJCgFjGAEgASgFIjAKElRlc3RSZXNlcnZlZEZp", - "ZWxkc0oECAIQA0oECA8QEEoECAkQDFIDYmFyUgNiYXoiWgoRVGVzdEZvcmVp", - "Z25OZXN0ZWQSRQoOZm9yZWlnbl9uZXN0ZWQYASABKAsyLS5wcm90b2J1Zl91", - "bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZSI0ChhUZXN0UmVh", - "bGx5TGFyZ2VUYWdOdW1iZXISCQoBYRgBIAEoBRINCgJiYhj///9/IAEoBSJV", - "ChRUZXN0UmVjdXJzaXZlTWVzc2FnZRIyCgFhGAEgASgLMicucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdFJlY3Vyc2l2ZU1lc3NhZ2USCQoBaRgCIAEoBSJLChRU", - "ZXN0TXV0dWFsUmVjdXJzaW9uQRIzCgJiYhgBIAEoCzInLnByb3RvYnVmX3Vu", - "aXR0ZXN0LlRlc3RNdXR1YWxSZWN1cnNpb25CImIKFFRlc3RNdXR1YWxSZWN1", - "cnNpb25CEjIKAWEYASABKAsyJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TXV0", - "dWFsUmVjdXJzaW9uQRIWCg5vcHRpb25hbF9pbnQzMhgCIAEoBSJMChJUZXN0", - "RW51bUFsbG93QWxpYXMSNgoFdmFsdWUYASABKA4yJy5wcm90b2J1Zl91bml0", - "dGVzdC5UZXN0RW51bVdpdGhEdXBWYWx1ZSLrAgoXVGVzdENhbWVsQ2FzZUZp", - "ZWxkTmFtZXMSFgoOUHJpbWl0aXZlRmllbGQYASABKAUSEwoLU3RyaW5nRmll", - "bGQYAiABKAkSMQoJRW51bUZpZWxkGAMgASgOMh4ucHJvdG9idWZfdW5pdHRl", - "c3QuRm9yZWlnbkVudW0SNwoMTWVzc2FnZUZpZWxkGAQgASgLMiEucHJvdG9i", - "dWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2USHgoWUmVwZWF0ZWRQcmltaXRp", - "dmVGaWVsZBgHIAMoBRIbChNSZXBlYXRlZFN0cmluZ0ZpZWxkGAggAygJEjkK", - "EVJlcGVhdGVkRW51bUZpZWxkGAkgAygOMh4ucHJvdG9idWZfdW5pdHRlc3Qu", - "Rm9yZWlnbkVudW0SPwoUUmVwZWF0ZWRNZXNzYWdlRmllbGQYCiADKAsyIS5w", - "cm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZSLHAQoSVGVzdEZpZWxk", - "T3JkZXJpbmdzEhEKCW15X3N0cmluZxgLIAEoCRIOCgZteV9pbnQYASABKAMS", - "EAoIbXlfZmxvYXQYZSABKAISUwoVc2luZ2xlX25lc3RlZF9tZXNzYWdlGMgB", - "IAEoCzIzLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RGaWVsZE9yZGVyaW5ncy5O", - "ZXN0ZWRNZXNzYWdlGicKDU5lc3RlZE1lc3NhZ2USCgoCb28YAiABKAMSCgoC", - "YmIYASABKAUiSwoRU3BhcnNlRW51bU1lc3NhZ2USNgoLc3BhcnNlX2VudW0Y", - "ASABKA4yIS5wcm90b2J1Zl91bml0dGVzdC5UZXN0U3BhcnNlRW51bSIZCglP", - "bmVTdHJpbmcSDAoEZGF0YRgBIAEoCSIaCgpNb3JlU3RyaW5nEgwKBGRhdGEY", - "ASADKAkiGAoIT25lQnl0ZXMSDAoEZGF0YRgBIAEoDCIZCglNb3JlQnl0ZXMS", - "DAoEZGF0YRgBIAEoDCIcCgxJbnQzMk1lc3NhZ2USDAoEZGF0YRgBIAEoBSId", - "Cg1VaW50MzJNZXNzYWdlEgwKBGRhdGEYASABKA0iHAoMSW50NjRNZXNzYWdl", - "EgwKBGRhdGEYASABKAMiHQoNVWludDY0TWVzc2FnZRIMCgRkYXRhGAEgASgE", - "IhsKC0Jvb2xNZXNzYWdlEgwKBGRhdGEYASABKAgicwoJVGVzdE9uZW9mEhEK", - "B2Zvb19pbnQYASABKAVIABIUCgpmb29fc3RyaW5nGAIgASgJSAASNgoLZm9v", - "X21lc3NhZ2UYAyABKAsyHy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlw", - "ZXNIAEIFCgNmb28iqgMKD1Rlc3RQYWNrZWRUeXBlcxIYCgxwYWNrZWRfaW50", - "MzIYWiADKAVCAhABEhgKDHBhY2tlZF9pbnQ2NBhbIAMoA0ICEAESGQoNcGFj", - "a2VkX3VpbnQzMhhcIAMoDUICEAESGQoNcGFja2VkX3VpbnQ2NBhdIAMoBEIC", - "EAESGQoNcGFja2VkX3NpbnQzMhheIAMoEUICEAESGQoNcGFja2VkX3NpbnQ2", - "NBhfIAMoEkICEAESGgoOcGFja2VkX2ZpeGVkMzIYYCADKAdCAhABEhoKDnBh", - "Y2tlZF9maXhlZDY0GGEgAygGQgIQARIbCg9wYWNrZWRfc2ZpeGVkMzIYYiAD", - "KA9CAhABEhsKD3BhY2tlZF9zZml4ZWQ2NBhjIAMoEEICEAESGAoMcGFja2Vk", - "X2Zsb2F0GGQgAygCQgIQARIZCg1wYWNrZWRfZG91YmxlGGUgAygBQgIQARIX", - "CgtwYWNrZWRfYm9vbBhmIAMoCEICEAESNwoLcGFja2VkX2VudW0YZyADKA4y", - "Hi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUICEAEiyAMKEVRlc3RV", - "bnBhY2tlZFR5cGVzEhoKDnVucGFja2VkX2ludDMyGFogAygFQgIQABIaCg51", - "bnBhY2tlZF9pbnQ2NBhbIAMoA0ICEAASGwoPdW5wYWNrZWRfdWludDMyGFwg", - "AygNQgIQABIbCg91bnBhY2tlZF91aW50NjQYXSADKARCAhAAEhsKD3VucGFj", - "a2VkX3NpbnQzMhheIAMoEUICEAASGwoPdW5wYWNrZWRfc2ludDY0GF8gAygS", - "QgIQABIcChB1bnBhY2tlZF9maXhlZDMyGGAgAygHQgIQABIcChB1bnBhY2tl", - "ZF9maXhlZDY0GGEgAygGQgIQABIdChF1bnBhY2tlZF9zZml4ZWQzMhhiIAMo", - "D0ICEAASHQoRdW5wYWNrZWRfc2ZpeGVkNjQYYyADKBBCAhAAEhoKDnVucGFj", - "a2VkX2Zsb2F0GGQgAygCQgIQABIbCg91bnBhY2tlZF9kb3VibGUYZSADKAFC", - "AhAAEhkKDXVucGFja2VkX2Jvb2wYZiADKAhCAhAAEjkKDXVucGFja2VkX2Vu", - "dW0YZyADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUICEAAi", - "wAEKI1Rlc3RSZXBlYXRlZFNjYWxhckRpZmZlcmVudFRhZ1NpemVzEhgKEHJl", - "cGVhdGVkX2ZpeGVkMzIYDCADKAcSFgoOcmVwZWF0ZWRfaW50MzIYDSADKAUS", - "GQoQcmVwZWF0ZWRfZml4ZWQ2NBj+DyADKAYSFwoOcmVwZWF0ZWRfaW50NjQY", - "/w8gAygDEhgKDnJlcGVhdGVkX2Zsb2F0GP7/DyADKAISGQoPcmVwZWF0ZWRf", - "dWludDY0GP//DyADKAQiKAobVGVzdENvbW1lbnRJbmplY3Rpb25NZXNzYWdl", - "EgkKAWEYASABKAkiDAoKRm9vUmVxdWVzdCINCgtGb29SZXNwb25zZSISChBG", - "b29DbGllbnRNZXNzYWdlIhIKEEZvb1NlcnZlck1lc3NhZ2UiDAoKQmFyUmVx", - "dWVzdCINCgtCYXJSZXNwb25zZSpZCgtGb3JlaWduRW51bRIXChNGT1JFSUdO", - "X1VOU1BFQ0lGSUVEEAASDwoLRk9SRUlHTl9GT08QBBIPCgtGT1JFSUdOX0JB", - "UhAFEg8KC0ZPUkVJR05fQkFaEAYqdQoUVGVzdEVudW1XaXRoRHVwVmFsdWUS", - "KAokVEVTVF9FTlVNX1dJVEhfRFVQX1ZBTFVFX1VOU1BFQ0lGSUVEEAASCAoE", - "Rk9PMRABEggKBEJBUjEQAhIHCgNCQVoQAxIICgRGT08yEAESCAoEQkFSMhAC", - "GgIQASqdAQoOVGVzdFNwYXJzZUVudW0SIAocVEVTVF9TUEFSU0VfRU5VTV9V", - "TlNQRUNJRklFRBAAEgwKCFNQQVJTRV9BEHsSDgoIU1BBUlNFX0IQpucDEg8K", - "CFNQQVJTRV9DELKxgAYSFQoIU1BBUlNFX0QQ8f//////////ARIVCghTUEFS", - "U0VfRRC03vz///////8BEgwKCFNQQVJTRV9HEAIymQEKC1Rlc3RTZXJ2aWNl", - "EkQKA0ZvbxIdLnByb3RvYnVmX3VuaXR0ZXN0LkZvb1JlcXVlc3QaHi5wcm90", - "b2J1Zl91bml0dGVzdC5Gb29SZXNwb25zZRJECgNCYXISHS5wcm90b2J1Zl91", - "bml0dGVzdC5CYXJSZXF1ZXN0Gh4ucHJvdG9idWZfdW5pdHRlc3QuQmFyUmVz", - "cG9uc2VCOkINVW5pdHRlc3RQcm90b0gBgAEBiAEBkAEB+AEBqgIaR29vZ2xl", - "LlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw==")); - descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, - new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportProto3Reflection.Descriptor, }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ForeignEnum), typeof(global::Google.Protobuf.TestProtos.TestEnumWithDupValue), typeof(global::Google.Protobuf.TestProtos.TestSparseEnum), }, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestAllTypes), global::Google.Protobuf.TestProtos.TestAllTypes.Parser, new[]{ "SingleInt32", "SingleInt64", "SingleUint32", "SingleUint64", "SingleSint32", "SingleSint64", "SingleFixed32", "SingleFixed64", "SingleSfixed32", "SingleSfixed64", "SingleFloat", "SingleDouble", "SingleBool", "SingleString", "SingleBytes", "SingleNestedMessage", "SingleForeignMessage", "SingleImportMessage", "SingleNestedEnum", "SingleForeignEnum", "SingleImportEnum", "SinglePublicImportMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedImportMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedImportEnum", "RepeatedPublicImportMessage", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes" }, new[]{ "OneofField" }, new[]{ typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage), global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage.Parser, new[]{ "Bb" }, null, null, null)}), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.NestedTestAllTypes), global::Google.Protobuf.TestProtos.NestedTestAllTypes.Parser, new[]{ "Child", "Payload", "RepeatedChild" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestDeprecatedFields), global::Google.Protobuf.TestProtos.TestDeprecatedFields.Parser, new[]{ "DeprecatedInt32" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.ForeignMessage), global::Google.Protobuf.TestProtos.ForeignMessage.Parser, new[]{ "C" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestReservedFields), global::Google.Protobuf.TestProtos.TestReservedFields.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestForeignNested), global::Google.Protobuf.TestProtos.TestForeignNested.Parser, new[]{ "ForeignNested" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber), global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber.Parser, new[]{ "A", "Bb" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestRecursiveMessage), global::Google.Protobuf.TestProtos.TestRecursiveMessage.Parser, new[]{ "A", "I" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionA), global::Google.Protobuf.TestProtos.TestMutualRecursionA.Parser, new[]{ "Bb" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionB), global::Google.Protobuf.TestProtos.TestMutualRecursionB.Parser, new[]{ "A", "OptionalInt32" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestEnumAllowAlias), global::Google.Protobuf.TestProtos.TestEnumAllowAlias.Parser, new[]{ "Value" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames), global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames.Parser, new[]{ "PrimitiveField", "StringField", "EnumField", "MessageField", "RepeatedPrimitiveField", "RepeatedStringField", "RepeatedEnumField", "RepeatedMessageField" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings), global::Google.Protobuf.TestProtos.TestFieldOrderings.Parser, new[]{ "MyString", "MyInt", "MyFloat", "SingleNestedMessage" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage), global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage.Parser, new[]{ "Oo", "Bb" }, null, null, null)}), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.SparseEnumMessage), global::Google.Protobuf.TestProtos.SparseEnumMessage.Parser, new[]{ "SparseEnum" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.OneString), global::Google.Protobuf.TestProtos.OneString.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MoreString), global::Google.Protobuf.TestProtos.MoreString.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.OneBytes), global::Google.Protobuf.TestProtos.OneBytes.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MoreBytes), global::Google.Protobuf.TestProtos.MoreBytes.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Int32Message), global::Google.Protobuf.TestProtos.Int32Message.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Uint32Message), global::Google.Protobuf.TestProtos.Uint32Message.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Int64Message), global::Google.Protobuf.TestProtos.Int64Message.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Uint64Message), global::Google.Protobuf.TestProtos.Uint64Message.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.BoolMessage), global::Google.Protobuf.TestProtos.BoolMessage.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestOneof), global::Google.Protobuf.TestProtos.TestOneof.Parser, new[]{ "FooInt", "FooString", "FooMessage" }, new[]{ "Foo" }, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestPackedTypes), global::Google.Protobuf.TestProtos.TestPackedTypes.Parser, new[]{ "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedEnum" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestUnpackedTypes), global::Google.Protobuf.TestProtos.TestUnpackedTypes.Parser, new[]{ "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedEnum" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes), global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes.Parser, new[]{ "RepeatedFixed32", "RepeatedInt32", "RepeatedFixed64", "RepeatedInt64", "RepeatedFloat", "RepeatedUint64" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestCommentInjectionMessage), global::Google.Protobuf.TestProtos.TestCommentInjectionMessage.Parser, new[]{ "A" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooRequest), global::Google.Protobuf.TestProtos.FooRequest.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooResponse), global::Google.Protobuf.TestProtos.FooResponse.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooClientMessage), global::Google.Protobuf.TestProtos.FooClientMessage.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooServerMessage), global::Google.Protobuf.TestProtos.FooServerMessage.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.BarRequest), global::Google.Protobuf.TestProtos.BarRequest.Parser, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.BarResponse), global::Google.Protobuf.TestProtos.BarResponse.Parser, null, null, null, null) - })); - } - #endregion - - } - #region Enums - public enum ForeignEnum { - [pbr::OriginalName("FOREIGN_UNSPECIFIED")] ForeignUnspecified = 0, - [pbr::OriginalName("FOREIGN_FOO")] ForeignFoo = 4, - [pbr::OriginalName("FOREIGN_BAR")] ForeignBar = 5, - [pbr::OriginalName("FOREIGN_BAZ")] ForeignBaz = 6, - } - - /// - /// Test an enum that has multiple values with the same number. - /// - public enum TestEnumWithDupValue { - [pbr::OriginalName("TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED")] Unspecified = 0, - [pbr::OriginalName("FOO1")] Foo1 = 1, - [pbr::OriginalName("BAR1")] Bar1 = 2, - [pbr::OriginalName("BAZ")] Baz = 3, - [pbr::OriginalName("FOO2", PreferredAlias = false)] Foo2 = 1, - [pbr::OriginalName("BAR2", PreferredAlias = false)] Bar2 = 2, - } - - /// - /// Test an enum with large, unordered values. - /// - public enum TestSparseEnum { - [pbr::OriginalName("TEST_SPARSE_ENUM_UNSPECIFIED")] Unspecified = 0, - [pbr::OriginalName("SPARSE_A")] SparseA = 123, - [pbr::OriginalName("SPARSE_B")] SparseB = 62374, - [pbr::OriginalName("SPARSE_C")] SparseC = 12589234, - [pbr::OriginalName("SPARSE_D")] SparseD = -15, - [pbr::OriginalName("SPARSE_E")] SparseE = -53452, - /// - /// In proto3, value 0 must be the first one specified - /// SPARSE_F = 0; - /// - [pbr::OriginalName("SPARSE_G")] SparseG = 2, - } - - #endregion - - #region Messages - /// - /// This proto includes every type of field in both singular and repeated - /// forms. - /// - public sealed partial class TestAllTypes : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestAllTypes()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestAllTypes() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestAllTypes(TestAllTypes other) : this() { - singleInt32_ = other.singleInt32_; - singleInt64_ = other.singleInt64_; - singleUint32_ = other.singleUint32_; - singleUint64_ = other.singleUint64_; - singleSint32_ = other.singleSint32_; - singleSint64_ = other.singleSint64_; - singleFixed32_ = other.singleFixed32_; - singleFixed64_ = other.singleFixed64_; - singleSfixed32_ = other.singleSfixed32_; - singleSfixed64_ = other.singleSfixed64_; - singleFloat_ = other.singleFloat_; - singleDouble_ = other.singleDouble_; - singleBool_ = other.singleBool_; - singleString_ = other.singleString_; - singleBytes_ = other.singleBytes_; - SingleNestedMessage = other.singleNestedMessage_ != null ? other.SingleNestedMessage.Clone() : null; - SingleForeignMessage = other.singleForeignMessage_ != null ? other.SingleForeignMessage.Clone() : null; - SingleImportMessage = other.singleImportMessage_ != null ? other.SingleImportMessage.Clone() : null; - singleNestedEnum_ = other.singleNestedEnum_; - singleForeignEnum_ = other.singleForeignEnum_; - singleImportEnum_ = other.singleImportEnum_; - SinglePublicImportMessage = other.singlePublicImportMessage_ != null ? other.SinglePublicImportMessage.Clone() : null; - repeatedInt32_ = other.repeatedInt32_.Clone(); - repeatedInt64_ = other.repeatedInt64_.Clone(); - repeatedUint32_ = other.repeatedUint32_.Clone(); - repeatedUint64_ = other.repeatedUint64_.Clone(); - repeatedSint32_ = other.repeatedSint32_.Clone(); - repeatedSint64_ = other.repeatedSint64_.Clone(); - repeatedFixed32_ = other.repeatedFixed32_.Clone(); - repeatedFixed64_ = other.repeatedFixed64_.Clone(); - repeatedSfixed32_ = other.repeatedSfixed32_.Clone(); - repeatedSfixed64_ = other.repeatedSfixed64_.Clone(); - repeatedFloat_ = other.repeatedFloat_.Clone(); - repeatedDouble_ = other.repeatedDouble_.Clone(); - repeatedBool_ = other.repeatedBool_.Clone(); - repeatedString_ = other.repeatedString_.Clone(); - repeatedBytes_ = other.repeatedBytes_.Clone(); - repeatedNestedMessage_ = other.repeatedNestedMessage_.Clone(); - repeatedForeignMessage_ = other.repeatedForeignMessage_.Clone(); - repeatedImportMessage_ = other.repeatedImportMessage_.Clone(); - repeatedNestedEnum_ = other.repeatedNestedEnum_.Clone(); - repeatedForeignEnum_ = other.repeatedForeignEnum_.Clone(); - repeatedImportEnum_ = other.repeatedImportEnum_.Clone(); - repeatedPublicImportMessage_ = other.repeatedPublicImportMessage_.Clone(); - switch (other.OneofFieldCase) { - case OneofFieldOneofCase.OneofUint32: - OneofUint32 = other.OneofUint32; - break; - case OneofFieldOneofCase.OneofNestedMessage: - OneofNestedMessage = other.OneofNestedMessage.Clone(); - break; - case OneofFieldOneofCase.OneofString: - OneofString = other.OneofString; - break; - case OneofFieldOneofCase.OneofBytes: - OneofBytes = other.OneofBytes; - break; - } - - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestAllTypes Clone() { - return new TestAllTypes(this); - } - - /// Field number for the "single_int32" field. - public const int SingleInt32FieldNumber = 1; - private int singleInt32_; - /// - /// Singular - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int SingleInt32 { - get { return singleInt32_; } - set { - singleInt32_ = value; - } - } - - /// Field number for the "single_int64" field. - public const int SingleInt64FieldNumber = 2; - private long singleInt64_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public long SingleInt64 { - get { return singleInt64_; } - set { - singleInt64_ = value; - } - } - - /// Field number for the "single_uint32" field. - public const int SingleUint32FieldNumber = 3; - private uint singleUint32_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint SingleUint32 { - get { return singleUint32_; } - set { - singleUint32_ = value; - } - } - - /// Field number for the "single_uint64" field. - public const int SingleUint64FieldNumber = 4; - private ulong singleUint64_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ulong SingleUint64 { - get { return singleUint64_; } - set { - singleUint64_ = value; - } - } - - /// Field number for the "single_sint32" field. - public const int SingleSint32FieldNumber = 5; - private int singleSint32_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int SingleSint32 { - get { return singleSint32_; } - set { - singleSint32_ = value; - } - } - - /// Field number for the "single_sint64" field. - public const int SingleSint64FieldNumber = 6; - private long singleSint64_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public long SingleSint64 { - get { return singleSint64_; } - set { - singleSint64_ = value; - } - } - - /// Field number for the "single_fixed32" field. - public const int SingleFixed32FieldNumber = 7; - private uint singleFixed32_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint SingleFixed32 { - get { return singleFixed32_; } - set { - singleFixed32_ = value; - } - } - - /// Field number for the "single_fixed64" field. - public const int SingleFixed64FieldNumber = 8; - private ulong singleFixed64_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ulong SingleFixed64 { - get { return singleFixed64_; } - set { - singleFixed64_ = value; - } - } - - /// Field number for the "single_sfixed32" field. - public const int SingleSfixed32FieldNumber = 9; - private int singleSfixed32_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int SingleSfixed32 { - get { return singleSfixed32_; } - set { - singleSfixed32_ = value; - } - } - - /// Field number for the "single_sfixed64" field. - public const int SingleSfixed64FieldNumber = 10; - private long singleSfixed64_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public long SingleSfixed64 { - get { return singleSfixed64_; } - set { - singleSfixed64_ = value; - } - } - - /// Field number for the "single_float" field. - public const int SingleFloatFieldNumber = 11; - private float singleFloat_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public float SingleFloat { - get { return singleFloat_; } - set { - singleFloat_ = value; - } - } - - /// Field number for the "single_double" field. - public const int SingleDoubleFieldNumber = 12; - private double singleDouble_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public double SingleDouble { - get { return singleDouble_; } - set { - singleDouble_ = value; - } - } - - /// Field number for the "single_bool" field. - public const int SingleBoolFieldNumber = 13; - private bool singleBool_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool SingleBool { - get { return singleBool_; } - set { - singleBool_ = value; - } - } - - /// Field number for the "single_string" field. - public const int SingleStringFieldNumber = 14; - private string singleString_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string SingleString { - get { return singleString_; } - set { - singleString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "single_bytes" field. - public const int SingleBytesFieldNumber = 15; - private pb::ByteString singleBytes_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pb::ByteString SingleBytes { - get { return singleBytes_; } - set { - singleBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "single_nested_message" field. - public const int SingleNestedMessageFieldNumber = 18; - private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage singleNestedMessage_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage SingleNestedMessage { - get { return singleNestedMessage_; } - set { - singleNestedMessage_ = value; - } - } - - /// Field number for the "single_foreign_message" field. - public const int SingleForeignMessageFieldNumber = 19; - private global::Google.Protobuf.TestProtos.ForeignMessage singleForeignMessage_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.ForeignMessage SingleForeignMessage { - get { return singleForeignMessage_; } - set { - singleForeignMessage_ = value; - } - } - - /// Field number for the "single_import_message" field. - public const int SingleImportMessageFieldNumber = 20; - private global::Google.Protobuf.TestProtos.ImportMessage singleImportMessage_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.ImportMessage SingleImportMessage { - get { return singleImportMessage_; } - set { - singleImportMessage_ = value; - } - } - - /// Field number for the "single_nested_enum" field. - public const int SingleNestedEnumFieldNumber = 21; - private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum singleNestedEnum_ = 0; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum SingleNestedEnum { - get { return singleNestedEnum_; } - set { - singleNestedEnum_ = value; - } - } - - /// Field number for the "single_foreign_enum" field. - public const int SingleForeignEnumFieldNumber = 22; - private global::Google.Protobuf.TestProtos.ForeignEnum singleForeignEnum_ = 0; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.ForeignEnum SingleForeignEnum { - get { return singleForeignEnum_; } - set { - singleForeignEnum_ = value; - } - } - - /// Field number for the "single_import_enum" field. - public const int SingleImportEnumFieldNumber = 23; - private global::Google.Protobuf.TestProtos.ImportEnum singleImportEnum_ = 0; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.ImportEnum SingleImportEnum { - get { return singleImportEnum_; } - set { - singleImportEnum_ = value; - } - } - - /// Field number for the "single_public_import_message" field. - public const int SinglePublicImportMessageFieldNumber = 26; - private global::Google.Protobuf.TestProtos.PublicImportMessage singlePublicImportMessage_; - /// - /// Defined in unittest_import_public.proto - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.PublicImportMessage SinglePublicImportMessage { - get { return singlePublicImportMessage_; } - set { - singlePublicImportMessage_ = value; - } - } - - /// Field number for the "repeated_int32" field. - public const int RepeatedInt32FieldNumber = 31; - private static readonly pb::FieldCodec _repeated_repeatedInt32_codec - = pb::FieldCodec.ForInt32(250); - private readonly pbc::RepeatedField repeatedInt32_ = new pbc::RepeatedField(); - /// - /// Repeated - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedInt32 { - get { return repeatedInt32_; } - } - - /// Field number for the "repeated_int64" field. - public const int RepeatedInt64FieldNumber = 32; - private static readonly pb::FieldCodec _repeated_repeatedInt64_codec - = pb::FieldCodec.ForInt64(258); - private readonly pbc::RepeatedField repeatedInt64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedInt64 { - get { return repeatedInt64_; } - } - - /// Field number for the "repeated_uint32" field. - public const int RepeatedUint32FieldNumber = 33; - private static readonly pb::FieldCodec _repeated_repeatedUint32_codec - = pb::FieldCodec.ForUInt32(266); - private readonly pbc::RepeatedField repeatedUint32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedUint32 { - get { return repeatedUint32_; } - } - - /// Field number for the "repeated_uint64" field. - public const int RepeatedUint64FieldNumber = 34; - private static readonly pb::FieldCodec _repeated_repeatedUint64_codec - = pb::FieldCodec.ForUInt64(274); - private readonly pbc::RepeatedField repeatedUint64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedUint64 { - get { return repeatedUint64_; } - } - - /// Field number for the "repeated_sint32" field. - public const int RepeatedSint32FieldNumber = 35; - private static readonly pb::FieldCodec _repeated_repeatedSint32_codec - = pb::FieldCodec.ForSInt32(282); - private readonly pbc::RepeatedField repeatedSint32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedSint32 { - get { return repeatedSint32_; } - } - - /// Field number for the "repeated_sint64" field. - public const int RepeatedSint64FieldNumber = 36; - private static readonly pb::FieldCodec _repeated_repeatedSint64_codec - = pb::FieldCodec.ForSInt64(290); - private readonly pbc::RepeatedField repeatedSint64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedSint64 { - get { return repeatedSint64_; } - } - - /// Field number for the "repeated_fixed32" field. - public const int RepeatedFixed32FieldNumber = 37; - private static readonly pb::FieldCodec _repeated_repeatedFixed32_codec - = pb::FieldCodec.ForFixed32(298); - private readonly pbc::RepeatedField repeatedFixed32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedFixed32 { - get { return repeatedFixed32_; } - } - - /// Field number for the "repeated_fixed64" field. - public const int RepeatedFixed64FieldNumber = 38; - private static readonly pb::FieldCodec _repeated_repeatedFixed64_codec - = pb::FieldCodec.ForFixed64(306); - private readonly pbc::RepeatedField repeatedFixed64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedFixed64 { - get { return repeatedFixed64_; } - } - - /// Field number for the "repeated_sfixed32" field. - public const int RepeatedSfixed32FieldNumber = 39; - private static readonly pb::FieldCodec _repeated_repeatedSfixed32_codec - = pb::FieldCodec.ForSFixed32(314); - private readonly pbc::RepeatedField repeatedSfixed32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedSfixed32 { - get { return repeatedSfixed32_; } - } - - /// Field number for the "repeated_sfixed64" field. - public const int RepeatedSfixed64FieldNumber = 40; - private static readonly pb::FieldCodec _repeated_repeatedSfixed64_codec - = pb::FieldCodec.ForSFixed64(322); - private readonly pbc::RepeatedField repeatedSfixed64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedSfixed64 { - get { return repeatedSfixed64_; } - } - - /// Field number for the "repeated_float" field. - public const int RepeatedFloatFieldNumber = 41; - private static readonly pb::FieldCodec _repeated_repeatedFloat_codec - = pb::FieldCodec.ForFloat(330); - private readonly pbc::RepeatedField repeatedFloat_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedFloat { - get { return repeatedFloat_; } - } - - /// Field number for the "repeated_double" field. - public const int RepeatedDoubleFieldNumber = 42; - private static readonly pb::FieldCodec _repeated_repeatedDouble_codec - = pb::FieldCodec.ForDouble(338); - private readonly pbc::RepeatedField repeatedDouble_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedDouble { - get { return repeatedDouble_; } - } - - /// Field number for the "repeated_bool" field. - public const int RepeatedBoolFieldNumber = 43; - private static readonly pb::FieldCodec _repeated_repeatedBool_codec - = pb::FieldCodec.ForBool(346); - private readonly pbc::RepeatedField repeatedBool_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedBool { - get { return repeatedBool_; } - } - - /// Field number for the "repeated_string" field. - public const int RepeatedStringFieldNumber = 44; - private static readonly pb::FieldCodec _repeated_repeatedString_codec - = pb::FieldCodec.ForString(354); - private readonly pbc::RepeatedField repeatedString_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedString { - get { return repeatedString_; } - } - - /// Field number for the "repeated_bytes" field. - public const int RepeatedBytesFieldNumber = 45; - private static readonly pb::FieldCodec _repeated_repeatedBytes_codec - = pb::FieldCodec.ForBytes(362); - private readonly pbc::RepeatedField repeatedBytes_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedBytes { - get { return repeatedBytes_; } - } - - /// Field number for the "repeated_nested_message" field. - public const int RepeatedNestedMessageFieldNumber = 48; - private static readonly pb::FieldCodec _repeated_repeatedNestedMessage_codec - = pb::FieldCodec.ForMessage(386, global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage.Parser); - private readonly pbc::RepeatedField repeatedNestedMessage_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedNestedMessage { - get { return repeatedNestedMessage_; } - } - - /// Field number for the "repeated_foreign_message" field. - public const int RepeatedForeignMessageFieldNumber = 49; - private static readonly pb::FieldCodec _repeated_repeatedForeignMessage_codec - = pb::FieldCodec.ForMessage(394, global::Google.Protobuf.TestProtos.ForeignMessage.Parser); - private readonly pbc::RepeatedField repeatedForeignMessage_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedForeignMessage { - get { return repeatedForeignMessage_; } - } - - /// Field number for the "repeated_import_message" field. - public const int RepeatedImportMessageFieldNumber = 50; - private static readonly pb::FieldCodec _repeated_repeatedImportMessage_codec - = pb::FieldCodec.ForMessage(402, global::Google.Protobuf.TestProtos.ImportMessage.Parser); - private readonly pbc::RepeatedField repeatedImportMessage_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedImportMessage { - get { return repeatedImportMessage_; } - } - - /// Field number for the "repeated_nested_enum" field. - public const int RepeatedNestedEnumFieldNumber = 51; - private static readonly pb::FieldCodec _repeated_repeatedNestedEnum_codec - = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) x); - private readonly pbc::RepeatedField repeatedNestedEnum_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedNestedEnum { - get { return repeatedNestedEnum_; } - } - - /// Field number for the "repeated_foreign_enum" field. - public const int RepeatedForeignEnumFieldNumber = 52; - private static readonly pb::FieldCodec _repeated_repeatedForeignEnum_codec - = pb::FieldCodec.ForEnum(418, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x); - private readonly pbc::RepeatedField repeatedForeignEnum_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedForeignEnum { - get { return repeatedForeignEnum_; } - } - - /// Field number for the "repeated_import_enum" field. - public const int RepeatedImportEnumFieldNumber = 53; - private static readonly pb::FieldCodec _repeated_repeatedImportEnum_codec - = pb::FieldCodec.ForEnum(426, x => (int) x, x => (global::Google.Protobuf.TestProtos.ImportEnum) x); - private readonly pbc::RepeatedField repeatedImportEnum_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedImportEnum { - get { return repeatedImportEnum_; } - } - - /// Field number for the "repeated_public_import_message" field. - public const int RepeatedPublicImportMessageFieldNumber = 54; - private static readonly pb::FieldCodec _repeated_repeatedPublicImportMessage_codec - = pb::FieldCodec.ForMessage(434, global::Google.Protobuf.TestProtos.PublicImportMessage.Parser); - private readonly pbc::RepeatedField repeatedPublicImportMessage_ = new pbc::RepeatedField(); - /// - /// Defined in unittest_import_public.proto - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedPublicImportMessage { - get { return repeatedPublicImportMessage_; } - } - - /// Field number for the "oneof_uint32" field. - public const int OneofUint32FieldNumber = 111; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint OneofUint32 { - get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; } - set { - oneofField_ = value; - oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; - } - } - - /// Field number for the "oneof_nested_message" field. - public const int OneofNestedMessageFieldNumber = 112; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage OneofNestedMessage { - get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage) oneofField_ : null; } - set { - oneofField_ = value; - oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage; - } - } - - /// Field number for the "oneof_string" field. - public const int OneofStringFieldNumber = 113; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string OneofString { - get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; } - set { - oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - oneofFieldCase_ = OneofFieldOneofCase.OneofString; - } - } - - /// Field number for the "oneof_bytes" field. - public const int OneofBytesFieldNumber = 114; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pb::ByteString OneofBytes { - get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; } - set { - oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; - } - } - - private object oneofField_; - /// Enum of possible cases for the "oneof_field" oneof. - public enum OneofFieldOneofCase { - None = 0, - OneofUint32 = 111, - OneofNestedMessage = 112, - OneofString = 113, - OneofBytes = 114, - } - private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public OneofFieldOneofCase OneofFieldCase { - get { return oneofFieldCase_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void ClearOneofField() { - oneofFieldCase_ = OneofFieldOneofCase.None; - oneofField_ = null; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestAllTypes); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestAllTypes other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (SingleInt32 != other.SingleInt32) return false; - if (SingleInt64 != other.SingleInt64) return false; - if (SingleUint32 != other.SingleUint32) return false; - if (SingleUint64 != other.SingleUint64) return false; - if (SingleSint32 != other.SingleSint32) return false; - if (SingleSint64 != other.SingleSint64) return false; - if (SingleFixed32 != other.SingleFixed32) return false; - if (SingleFixed64 != other.SingleFixed64) return false; - if (SingleSfixed32 != other.SingleSfixed32) return false; - if (SingleSfixed64 != other.SingleSfixed64) return false; - if (SingleFloat != other.SingleFloat) return false; - if (SingleDouble != other.SingleDouble) return false; - if (SingleBool != other.SingleBool) return false; - if (SingleString != other.SingleString) return false; - if (SingleBytes != other.SingleBytes) return false; - if (!object.Equals(SingleNestedMessage, other.SingleNestedMessage)) return false; - if (!object.Equals(SingleForeignMessage, other.SingleForeignMessage)) return false; - if (!object.Equals(SingleImportMessage, other.SingleImportMessage)) return false; - if (SingleNestedEnum != other.SingleNestedEnum) return false; - if (SingleForeignEnum != other.SingleForeignEnum) return false; - if (SingleImportEnum != other.SingleImportEnum) return false; - if (!object.Equals(SinglePublicImportMessage, other.SinglePublicImportMessage)) return false; - if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false; - if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false; - if(!repeatedUint32_.Equals(other.repeatedUint32_)) return false; - if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false; - if(!repeatedSint32_.Equals(other.repeatedSint32_)) return false; - if(!repeatedSint64_.Equals(other.repeatedSint64_)) return false; - if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false; - if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false; - if(!repeatedSfixed32_.Equals(other.repeatedSfixed32_)) return false; - if(!repeatedSfixed64_.Equals(other.repeatedSfixed64_)) return false; - if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false; - if(!repeatedDouble_.Equals(other.repeatedDouble_)) return false; - if(!repeatedBool_.Equals(other.repeatedBool_)) return false; - if(!repeatedString_.Equals(other.repeatedString_)) return false; - if(!repeatedBytes_.Equals(other.repeatedBytes_)) return false; - if(!repeatedNestedMessage_.Equals(other.repeatedNestedMessage_)) return false; - if(!repeatedForeignMessage_.Equals(other.repeatedForeignMessage_)) return false; - if(!repeatedImportMessage_.Equals(other.repeatedImportMessage_)) return false; - if(!repeatedNestedEnum_.Equals(other.repeatedNestedEnum_)) return false; - if(!repeatedForeignEnum_.Equals(other.repeatedForeignEnum_)) return false; - if(!repeatedImportEnum_.Equals(other.repeatedImportEnum_)) return false; - if(!repeatedPublicImportMessage_.Equals(other.repeatedPublicImportMessage_)) return false; - if (OneofUint32 != other.OneofUint32) return false; - if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false; - if (OneofString != other.OneofString) return false; - if (OneofBytes != other.OneofBytes) return false; - if (OneofFieldCase != other.OneofFieldCase) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (SingleInt32 != 0) hash ^= SingleInt32.GetHashCode(); - if (SingleInt64 != 0L) hash ^= SingleInt64.GetHashCode(); - if (SingleUint32 != 0) hash ^= SingleUint32.GetHashCode(); - if (SingleUint64 != 0UL) hash ^= SingleUint64.GetHashCode(); - if (SingleSint32 != 0) hash ^= SingleSint32.GetHashCode(); - if (SingleSint64 != 0L) hash ^= SingleSint64.GetHashCode(); - if (SingleFixed32 != 0) hash ^= SingleFixed32.GetHashCode(); - if (SingleFixed64 != 0UL) hash ^= SingleFixed64.GetHashCode(); - if (SingleSfixed32 != 0) hash ^= SingleSfixed32.GetHashCode(); - if (SingleSfixed64 != 0L) hash ^= SingleSfixed64.GetHashCode(); - if (SingleFloat != 0F) hash ^= SingleFloat.GetHashCode(); - if (SingleDouble != 0D) hash ^= SingleDouble.GetHashCode(); - if (SingleBool != false) hash ^= SingleBool.GetHashCode(); - if (SingleString.Length != 0) hash ^= SingleString.GetHashCode(); - if (SingleBytes.Length != 0) hash ^= SingleBytes.GetHashCode(); - if (singleNestedMessage_ != null) hash ^= SingleNestedMessage.GetHashCode(); - if (singleForeignMessage_ != null) hash ^= SingleForeignMessage.GetHashCode(); - if (singleImportMessage_ != null) hash ^= SingleImportMessage.GetHashCode(); - if (SingleNestedEnum != 0) hash ^= SingleNestedEnum.GetHashCode(); - if (SingleForeignEnum != 0) hash ^= SingleForeignEnum.GetHashCode(); - if (SingleImportEnum != 0) hash ^= SingleImportEnum.GetHashCode(); - if (singlePublicImportMessage_ != null) hash ^= SinglePublicImportMessage.GetHashCode(); - hash ^= repeatedInt32_.GetHashCode(); - hash ^= repeatedInt64_.GetHashCode(); - hash ^= repeatedUint32_.GetHashCode(); - hash ^= repeatedUint64_.GetHashCode(); - hash ^= repeatedSint32_.GetHashCode(); - hash ^= repeatedSint64_.GetHashCode(); - hash ^= repeatedFixed32_.GetHashCode(); - hash ^= repeatedFixed64_.GetHashCode(); - hash ^= repeatedSfixed32_.GetHashCode(); - hash ^= repeatedSfixed64_.GetHashCode(); - hash ^= repeatedFloat_.GetHashCode(); - hash ^= repeatedDouble_.GetHashCode(); - hash ^= repeatedBool_.GetHashCode(); - hash ^= repeatedString_.GetHashCode(); - hash ^= repeatedBytes_.GetHashCode(); - hash ^= repeatedNestedMessage_.GetHashCode(); - hash ^= repeatedForeignMessage_.GetHashCode(); - hash ^= repeatedImportMessage_.GetHashCode(); - hash ^= repeatedNestedEnum_.GetHashCode(); - hash ^= repeatedForeignEnum_.GetHashCode(); - hash ^= repeatedImportEnum_.GetHashCode(); - hash ^= repeatedPublicImportMessage_.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) hash ^= OneofUint32.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) hash ^= OneofString.GetHashCode(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) hash ^= OneofBytes.GetHashCode(); - hash ^= (int) oneofFieldCase_; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (SingleInt32 != 0) { - output.WriteRawTag(8); - output.WriteInt32(SingleInt32); - } - if (SingleInt64 != 0L) { - output.WriteRawTag(16); - output.WriteInt64(SingleInt64); - } - if (SingleUint32 != 0) { - output.WriteRawTag(24); - output.WriteUInt32(SingleUint32); - } - if (SingleUint64 != 0UL) { - output.WriteRawTag(32); - output.WriteUInt64(SingleUint64); - } - if (SingleSint32 != 0) { - output.WriteRawTag(40); - output.WriteSInt32(SingleSint32); - } - if (SingleSint64 != 0L) { - output.WriteRawTag(48); - output.WriteSInt64(SingleSint64); - } - if (SingleFixed32 != 0) { - output.WriteRawTag(61); - output.WriteFixed32(SingleFixed32); - } - if (SingleFixed64 != 0UL) { - output.WriteRawTag(65); - output.WriteFixed64(SingleFixed64); - } - if (SingleSfixed32 != 0) { - output.WriteRawTag(77); - output.WriteSFixed32(SingleSfixed32); - } - if (SingleSfixed64 != 0L) { - output.WriteRawTag(81); - output.WriteSFixed64(SingleSfixed64); - } - if (SingleFloat != 0F) { - output.WriteRawTag(93); - output.WriteFloat(SingleFloat); - } - if (SingleDouble != 0D) { - output.WriteRawTag(97); - output.WriteDouble(SingleDouble); - } - if (SingleBool != false) { - output.WriteRawTag(104); - output.WriteBool(SingleBool); - } - if (SingleString.Length != 0) { - output.WriteRawTag(114); - output.WriteString(SingleString); - } - if (SingleBytes.Length != 0) { - output.WriteRawTag(122); - output.WriteBytes(SingleBytes); - } - if (singleNestedMessage_ != null) { - output.WriteRawTag(146, 1); - output.WriteMessage(SingleNestedMessage); - } - if (singleForeignMessage_ != null) { - output.WriteRawTag(154, 1); - output.WriteMessage(SingleForeignMessage); - } - if (singleImportMessage_ != null) { - output.WriteRawTag(162, 1); - output.WriteMessage(SingleImportMessage); - } - if (SingleNestedEnum != 0) { - output.WriteRawTag(168, 1); - output.WriteEnum((int) SingleNestedEnum); - } - if (SingleForeignEnum != 0) { - output.WriteRawTag(176, 1); - output.WriteEnum((int) SingleForeignEnum); - } - if (SingleImportEnum != 0) { - output.WriteRawTag(184, 1); - output.WriteEnum((int) SingleImportEnum); - } - if (singlePublicImportMessage_ != null) { - output.WriteRawTag(210, 1); - output.WriteMessage(SinglePublicImportMessage); - } - repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec); - repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec); - repeatedUint32_.WriteTo(output, _repeated_repeatedUint32_codec); - repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec); - repeatedSint32_.WriteTo(output, _repeated_repeatedSint32_codec); - repeatedSint64_.WriteTo(output, _repeated_repeatedSint64_codec); - repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec); - repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec); - repeatedSfixed32_.WriteTo(output, _repeated_repeatedSfixed32_codec); - repeatedSfixed64_.WriteTo(output, _repeated_repeatedSfixed64_codec); - repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec); - repeatedDouble_.WriteTo(output, _repeated_repeatedDouble_codec); - repeatedBool_.WriteTo(output, _repeated_repeatedBool_codec); - repeatedString_.WriteTo(output, _repeated_repeatedString_codec); - repeatedBytes_.WriteTo(output, _repeated_repeatedBytes_codec); - repeatedNestedMessage_.WriteTo(output, _repeated_repeatedNestedMessage_codec); - repeatedForeignMessage_.WriteTo(output, _repeated_repeatedForeignMessage_codec); - repeatedImportMessage_.WriteTo(output, _repeated_repeatedImportMessage_codec); - repeatedNestedEnum_.WriteTo(output, _repeated_repeatedNestedEnum_codec); - repeatedForeignEnum_.WriteTo(output, _repeated_repeatedForeignEnum_codec); - repeatedImportEnum_.WriteTo(output, _repeated_repeatedImportEnum_codec); - repeatedPublicImportMessage_.WriteTo(output, _repeated_repeatedPublicImportMessage_codec); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { - output.WriteRawTag(248, 6); - output.WriteUInt32(OneofUint32); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { - output.WriteRawTag(130, 7); - output.WriteMessage(OneofNestedMessage); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { - output.WriteRawTag(138, 7); - output.WriteString(OneofString); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { - output.WriteRawTag(146, 7); - output.WriteBytes(OneofBytes); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (SingleInt32 != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(SingleInt32); - } - if (SingleInt64 != 0L) { - size += 1 + pb::CodedOutputStream.ComputeInt64Size(SingleInt64); - } - if (SingleUint32 != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(SingleUint32); - } - if (SingleUint64 != 0UL) { - size += 1 + pb::CodedOutputStream.ComputeUInt64Size(SingleUint64); - } - if (SingleSint32 != 0) { - size += 1 + pb::CodedOutputStream.ComputeSInt32Size(SingleSint32); - } - if (SingleSint64 != 0L) { - size += 1 + pb::CodedOutputStream.ComputeSInt64Size(SingleSint64); - } - if (SingleFixed32 != 0) { - size += 1 + 4; - } - if (SingleFixed64 != 0UL) { - size += 1 + 8; - } - if (SingleSfixed32 != 0) { - size += 1 + 4; - } - if (SingleSfixed64 != 0L) { - size += 1 + 8; - } - if (SingleFloat != 0F) { - size += 1 + 4; - } - if (SingleDouble != 0D) { - size += 1 + 8; - } - if (SingleBool != false) { - size += 1 + 1; - } - if (SingleString.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(SingleString); - } - if (SingleBytes.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(SingleBytes); - } - if (singleNestedMessage_ != null) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleNestedMessage); - } - if (singleForeignMessage_ != null) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleForeignMessage); - } - if (singleImportMessage_ != null) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleImportMessage); - } - if (SingleNestedEnum != 0) { - size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleNestedEnum); - } - if (SingleForeignEnum != 0) { - size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleForeignEnum); - } - if (SingleImportEnum != 0) { - size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleImportEnum); - } - if (singlePublicImportMessage_ != null) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(SinglePublicImportMessage); - } - size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec); - size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec); - size += repeatedUint32_.CalculateSize(_repeated_repeatedUint32_codec); - size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec); - size += repeatedSint32_.CalculateSize(_repeated_repeatedSint32_codec); - size += repeatedSint64_.CalculateSize(_repeated_repeatedSint64_codec); - size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec); - size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec); - size += repeatedSfixed32_.CalculateSize(_repeated_repeatedSfixed32_codec); - size += repeatedSfixed64_.CalculateSize(_repeated_repeatedSfixed64_codec); - size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec); - size += repeatedDouble_.CalculateSize(_repeated_repeatedDouble_codec); - size += repeatedBool_.CalculateSize(_repeated_repeatedBool_codec); - size += repeatedString_.CalculateSize(_repeated_repeatedString_codec); - size += repeatedBytes_.CalculateSize(_repeated_repeatedBytes_codec); - size += repeatedNestedMessage_.CalculateSize(_repeated_repeatedNestedMessage_codec); - size += repeatedForeignMessage_.CalculateSize(_repeated_repeatedForeignMessage_codec); - size += repeatedImportMessage_.CalculateSize(_repeated_repeatedImportMessage_codec); - size += repeatedNestedEnum_.CalculateSize(_repeated_repeatedNestedEnum_codec); - size += repeatedForeignEnum_.CalculateSize(_repeated_repeatedForeignEnum_codec); - size += repeatedImportEnum_.CalculateSize(_repeated_repeatedImportEnum_codec); - size += repeatedPublicImportMessage_.CalculateSize(_repeated_repeatedPublicImportMessage_codec); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { - size += 2 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(OneofNestedMessage); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { - size += 2 + pb::CodedOutputStream.ComputeStringSize(OneofString); - } - if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { - size += 2 + pb::CodedOutputStream.ComputeBytesSize(OneofBytes); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestAllTypes other) { - if (other == null) { - return; - } - if (other.SingleInt32 != 0) { - SingleInt32 = other.SingleInt32; - } - if (other.SingleInt64 != 0L) { - SingleInt64 = other.SingleInt64; - } - if (other.SingleUint32 != 0) { - SingleUint32 = other.SingleUint32; - } - if (other.SingleUint64 != 0UL) { - SingleUint64 = other.SingleUint64; - } - if (other.SingleSint32 != 0) { - SingleSint32 = other.SingleSint32; - } - if (other.SingleSint64 != 0L) { - SingleSint64 = other.SingleSint64; - } - if (other.SingleFixed32 != 0) { - SingleFixed32 = other.SingleFixed32; - } - if (other.SingleFixed64 != 0UL) { - SingleFixed64 = other.SingleFixed64; - } - if (other.SingleSfixed32 != 0) { - SingleSfixed32 = other.SingleSfixed32; - } - if (other.SingleSfixed64 != 0L) { - SingleSfixed64 = other.SingleSfixed64; - } - if (other.SingleFloat != 0F) { - SingleFloat = other.SingleFloat; - } - if (other.SingleDouble != 0D) { - SingleDouble = other.SingleDouble; - } - if (other.SingleBool != false) { - SingleBool = other.SingleBool; - } - if (other.SingleString.Length != 0) { - SingleString = other.SingleString; - } - if (other.SingleBytes.Length != 0) { - SingleBytes = other.SingleBytes; - } - if (other.singleNestedMessage_ != null) { - if (singleNestedMessage_ == null) { - singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage(); - } - SingleNestedMessage.MergeFrom(other.SingleNestedMessage); - } - if (other.singleForeignMessage_ != null) { - if (singleForeignMessage_ == null) { - singleForeignMessage_ = new global::Google.Protobuf.TestProtos.ForeignMessage(); - } - SingleForeignMessage.MergeFrom(other.SingleForeignMessage); - } - if (other.singleImportMessage_ != null) { - if (singleImportMessage_ == null) { - singleImportMessage_ = new global::Google.Protobuf.TestProtos.ImportMessage(); - } - SingleImportMessage.MergeFrom(other.SingleImportMessage); - } - if (other.SingleNestedEnum != 0) { - SingleNestedEnum = other.SingleNestedEnum; - } - if (other.SingleForeignEnum != 0) { - SingleForeignEnum = other.SingleForeignEnum; - } - if (other.SingleImportEnum != 0) { - SingleImportEnum = other.SingleImportEnum; - } - if (other.singlePublicImportMessage_ != null) { - if (singlePublicImportMessage_ == null) { - singlePublicImportMessage_ = new global::Google.Protobuf.TestProtos.PublicImportMessage(); - } - SinglePublicImportMessage.MergeFrom(other.SinglePublicImportMessage); - } - repeatedInt32_.Add(other.repeatedInt32_); - repeatedInt64_.Add(other.repeatedInt64_); - repeatedUint32_.Add(other.repeatedUint32_); - repeatedUint64_.Add(other.repeatedUint64_); - repeatedSint32_.Add(other.repeatedSint32_); - repeatedSint64_.Add(other.repeatedSint64_); - repeatedFixed32_.Add(other.repeatedFixed32_); - repeatedFixed64_.Add(other.repeatedFixed64_); - repeatedSfixed32_.Add(other.repeatedSfixed32_); - repeatedSfixed64_.Add(other.repeatedSfixed64_); - repeatedFloat_.Add(other.repeatedFloat_); - repeatedDouble_.Add(other.repeatedDouble_); - repeatedBool_.Add(other.repeatedBool_); - repeatedString_.Add(other.repeatedString_); - repeatedBytes_.Add(other.repeatedBytes_); - repeatedNestedMessage_.Add(other.repeatedNestedMessage_); - repeatedForeignMessage_.Add(other.repeatedForeignMessage_); - repeatedImportMessage_.Add(other.repeatedImportMessage_); - repeatedNestedEnum_.Add(other.repeatedNestedEnum_); - repeatedForeignEnum_.Add(other.repeatedForeignEnum_); - repeatedImportEnum_.Add(other.repeatedImportEnum_); - repeatedPublicImportMessage_.Add(other.repeatedPublicImportMessage_); - switch (other.OneofFieldCase) { - case OneofFieldOneofCase.OneofUint32: - OneofUint32 = other.OneofUint32; - break; - case OneofFieldOneofCase.OneofNestedMessage: - OneofNestedMessage = other.OneofNestedMessage; - break; - case OneofFieldOneofCase.OneofString: - OneofString = other.OneofString; - break; - case OneofFieldOneofCase.OneofBytes: - OneofBytes = other.OneofBytes; - break; - } - - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - SingleInt32 = input.ReadInt32(); - break; - } - case 16: { - SingleInt64 = input.ReadInt64(); - break; - } - case 24: { - SingleUint32 = input.ReadUInt32(); - break; - } - case 32: { - SingleUint64 = input.ReadUInt64(); - break; - } - case 40: { - SingleSint32 = input.ReadSInt32(); - break; - } - case 48: { - SingleSint64 = input.ReadSInt64(); - break; - } - case 61: { - SingleFixed32 = input.ReadFixed32(); - break; - } - case 65: { - SingleFixed64 = input.ReadFixed64(); - break; - } - case 77: { - SingleSfixed32 = input.ReadSFixed32(); - break; - } - case 81: { - SingleSfixed64 = input.ReadSFixed64(); - break; - } - case 93: { - SingleFloat = input.ReadFloat(); - break; - } - case 97: { - SingleDouble = input.ReadDouble(); - break; - } - case 104: { - SingleBool = input.ReadBool(); - break; - } - case 114: { - SingleString = input.ReadString(); - break; - } - case 122: { - SingleBytes = input.ReadBytes(); - break; - } - case 146: { - if (singleNestedMessage_ == null) { - singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage(); - } - input.ReadMessage(singleNestedMessage_); - break; - } - case 154: { - if (singleForeignMessage_ == null) { - singleForeignMessage_ = new global::Google.Protobuf.TestProtos.ForeignMessage(); - } - input.ReadMessage(singleForeignMessage_); - break; - } - case 162: { - if (singleImportMessage_ == null) { - singleImportMessage_ = new global::Google.Protobuf.TestProtos.ImportMessage(); - } - input.ReadMessage(singleImportMessage_); - break; - } - case 168: { - singleNestedEnum_ = (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) input.ReadEnum(); - break; - } - case 176: { - singleForeignEnum_ = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum(); - break; - } - case 184: { - singleImportEnum_ = (global::Google.Protobuf.TestProtos.ImportEnum) input.ReadEnum(); - break; - } - case 210: { - if (singlePublicImportMessage_ == null) { - singlePublicImportMessage_ = new global::Google.Protobuf.TestProtos.PublicImportMessage(); - } - input.ReadMessage(singlePublicImportMessage_); - break; - } - case 250: - case 248: { - repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); - break; - } - case 258: - case 256: { - repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec); - break; - } - case 266: - case 264: { - repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec); - break; - } - case 274: - case 272: { - repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec); - break; - } - case 282: - case 280: { - repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec); - break; - } - case 290: - case 288: { - repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec); - break; - } - case 298: - case 301: { - repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec); - break; - } - case 306: - case 305: { - repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec); - break; - } - case 314: - case 317: { - repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec); - break; - } - case 322: - case 321: { - repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec); - break; - } - case 330: - case 333: { - repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec); - break; - } - case 338: - case 337: { - repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec); - break; - } - case 346: - case 344: { - repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec); - break; - } - case 354: { - repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec); - break; - } - case 362: { - repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec); - break; - } - case 386: { - repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec); - break; - } - case 394: { - repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec); - break; - } - case 402: { - repeatedImportMessage_.AddEntriesFrom(input, _repeated_repeatedImportMessage_codec); - break; - } - case 410: - case 408: { - repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec); - break; - } - case 418: - case 416: { - repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec); - break; - } - case 426: - case 424: { - repeatedImportEnum_.AddEntriesFrom(input, _repeated_repeatedImportEnum_codec); - break; - } - case 434: { - repeatedPublicImportMessage_.AddEntriesFrom(input, _repeated_repeatedPublicImportMessage_codec); - break; - } - case 888: { - OneofUint32 = input.ReadUInt32(); - break; - } - case 898: { - global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage(); - if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { - subBuilder.MergeFrom(OneofNestedMessage); - } - input.ReadMessage(subBuilder); - OneofNestedMessage = subBuilder; - break; - } - case 906: { - OneofString = input.ReadString(); - break; - } - case 914: { - OneofBytes = input.ReadBytes(); - break; - } - } - } - } - - #region Nested types - /// Container for nested types declared in the TestAllTypes message type. - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static partial class Types { - public enum NestedEnum { - [pbr::OriginalName("NESTED_ENUM_UNSPECIFIED")] Unspecified = 0, - [pbr::OriginalName("FOO")] Foo = 1, - [pbr::OriginalName("BAR")] Bar = 2, - [pbr::OriginalName("BAZ")] Baz = 3, - /// - /// Intentionally negative. - /// - [pbr::OriginalName("NEG")] Neg = -1, - } - - public sealed partial class NestedMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.TestAllTypes.Descriptor.NestedTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedMessage(NestedMessage other) : this() { - bb_ = other.bb_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedMessage Clone() { - return new NestedMessage(this); - } - - /// Field number for the "bb" field. - public const int BbFieldNumber = 1; - private int bb_; - /// - /// The field name "b" fails to compile in proto1 because it conflicts with - /// a local variable named "b" in one of the generated methods. Doh. - /// This file needs to compile in proto1 to test backwards-compatibility. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Bb { - get { return bb_; } - set { - bb_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as NestedMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(NestedMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Bb != other.Bb) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Bb != 0) hash ^= Bb.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Bb != 0) { - output.WriteRawTag(8); - output.WriteInt32(Bb); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Bb != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Bb); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(NestedMessage other) { - if (other == null) { - return; - } - if (other.Bb != 0) { - Bb = other.Bb; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - Bb = input.ReadInt32(); - break; - } - } - } - } - - } - - } - #endregion - - } - - /// - /// This proto includes a recusively nested message. - /// - public sealed partial class NestedTestAllTypes : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedTestAllTypes()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[1]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedTestAllTypes() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedTestAllTypes(NestedTestAllTypes other) : this() { - Child = other.child_ != null ? other.Child.Clone() : null; - Payload = other.payload_ != null ? other.Payload.Clone() : null; - repeatedChild_ = other.repeatedChild_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedTestAllTypes Clone() { - return new NestedTestAllTypes(this); - } - - /// Field number for the "child" field. - public const int ChildFieldNumber = 1; - private global::Google.Protobuf.TestProtos.NestedTestAllTypes child_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.NestedTestAllTypes Child { - get { return child_; } - set { - child_ = value; - } - } - - /// Field number for the "payload" field. - public const int PayloadFieldNumber = 2; - private global::Google.Protobuf.TestProtos.TestAllTypes payload_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.TestAllTypes Payload { - get { return payload_; } - set { - payload_ = value; - } - } - - /// Field number for the "repeated_child" field. - public const int RepeatedChildFieldNumber = 3; - private static readonly pb::FieldCodec _repeated_repeatedChild_codec - = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.TestProtos.NestedTestAllTypes.Parser); - private readonly pbc::RepeatedField repeatedChild_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedChild { - get { return repeatedChild_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as NestedTestAllTypes); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(NestedTestAllTypes other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!object.Equals(Child, other.Child)) return false; - if (!object.Equals(Payload, other.Payload)) return false; - if(!repeatedChild_.Equals(other.repeatedChild_)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (child_ != null) hash ^= Child.GetHashCode(); - if (payload_ != null) hash ^= Payload.GetHashCode(); - hash ^= repeatedChild_.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (child_ != null) { - output.WriteRawTag(10); - output.WriteMessage(Child); - } - if (payload_ != null) { - output.WriteRawTag(18); - output.WriteMessage(Payload); - } - repeatedChild_.WriteTo(output, _repeated_repeatedChild_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (child_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(Child); - } - if (payload_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); - } - size += repeatedChild_.CalculateSize(_repeated_repeatedChild_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(NestedTestAllTypes other) { - if (other == null) { - return; - } - if (other.child_ != null) { - if (child_ == null) { - child_ = new global::Google.Protobuf.TestProtos.NestedTestAllTypes(); - } - Child.MergeFrom(other.Child); - } - if (other.payload_ != null) { - if (payload_ == null) { - payload_ = new global::Google.Protobuf.TestProtos.TestAllTypes(); - } - Payload.MergeFrom(other.Payload); - } - repeatedChild_.Add(other.repeatedChild_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - if (child_ == null) { - child_ = new global::Google.Protobuf.TestProtos.NestedTestAllTypes(); - } - input.ReadMessage(child_); - break; - } - case 18: { - if (payload_ == null) { - payload_ = new global::Google.Protobuf.TestProtos.TestAllTypes(); - } - input.ReadMessage(payload_); - break; - } - case 26: { - repeatedChild_.AddEntriesFrom(input, _repeated_repeatedChild_codec); - break; - } - } - } - } - - } - - public sealed partial class TestDeprecatedFields : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestDeprecatedFields()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[2]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestDeprecatedFields() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestDeprecatedFields(TestDeprecatedFields other) : this() { - deprecatedInt32_ = other.deprecatedInt32_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestDeprecatedFields Clone() { - return new TestDeprecatedFields(this); - } - - /// Field number for the "deprecated_int32" field. - public const int DeprecatedInt32FieldNumber = 1; - private int deprecatedInt32_; - [global::System.ObsoleteAttribute] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int DeprecatedInt32 { - get { return deprecatedInt32_; } - set { - deprecatedInt32_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestDeprecatedFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestDeprecatedFields other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (DeprecatedInt32 != other.DeprecatedInt32) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (DeprecatedInt32 != 0) hash ^= DeprecatedInt32.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (DeprecatedInt32 != 0) { - output.WriteRawTag(8); - output.WriteInt32(DeprecatedInt32); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (DeprecatedInt32 != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(DeprecatedInt32); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestDeprecatedFields other) { - if (other == null) { - return; - } - if (other.DeprecatedInt32 != 0) { - DeprecatedInt32 = other.DeprecatedInt32; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - DeprecatedInt32 = input.ReadInt32(); - break; - } - } - } - } - - } - - /// - /// Define these after TestAllTypes to make sure the compiler can handle - /// that. - /// - public sealed partial class ForeignMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ForeignMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[3]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ForeignMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ForeignMessage(ForeignMessage other) : this() { - c_ = other.c_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ForeignMessage Clone() { - return new ForeignMessage(this); - } - - /// Field number for the "c" field. - public const int CFieldNumber = 1; - private int c_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int C { - get { return c_; } - set { - c_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as ForeignMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(ForeignMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (C != other.C) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (C != 0) hash ^= C.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (C != 0) { - output.WriteRawTag(8); - output.WriteInt32(C); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (C != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(C); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(ForeignMessage other) { - if (other == null) { - return; - } - if (other.C != 0) { - C = other.C; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - C = input.ReadInt32(); - break; - } - } - } - } - - } - - public sealed partial class TestReservedFields : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestReservedFields()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[4]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestReservedFields() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestReservedFields(TestReservedFields other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestReservedFields Clone() { - return new TestReservedFields(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestReservedFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestReservedFields other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestReservedFields other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - /// - /// Test that we can use NestedMessage from outside TestAllTypes. - /// - public sealed partial class TestForeignNested : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestForeignNested()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[5]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestForeignNested() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestForeignNested(TestForeignNested other) : this() { - ForeignNested = other.foreignNested_ != null ? other.ForeignNested.Clone() : null; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestForeignNested Clone() { - return new TestForeignNested(this); - } - - /// Field number for the "foreign_nested" field. - public const int ForeignNestedFieldNumber = 1; - private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage foreignNested_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage ForeignNested { - get { return foreignNested_; } - set { - foreignNested_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestForeignNested); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestForeignNested other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!object.Equals(ForeignNested, other.ForeignNested)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (foreignNested_ != null) hash ^= ForeignNested.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (foreignNested_ != null) { - output.WriteRawTag(10); - output.WriteMessage(ForeignNested); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (foreignNested_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(ForeignNested); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestForeignNested other) { - if (other == null) { - return; - } - if (other.foreignNested_ != null) { - if (foreignNested_ == null) { - foreignNested_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage(); - } - ForeignNested.MergeFrom(other.ForeignNested); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - if (foreignNested_ == null) { - foreignNested_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage(); - } - input.ReadMessage(foreignNested_); - break; - } - } - } - } - - } - - /// - /// Test that really large tag numbers don't break anything. - /// - public sealed partial class TestReallyLargeTagNumber : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestReallyLargeTagNumber()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[6]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestReallyLargeTagNumber() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestReallyLargeTagNumber(TestReallyLargeTagNumber other) : this() { - a_ = other.a_; - bb_ = other.bb_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestReallyLargeTagNumber Clone() { - return new TestReallyLargeTagNumber(this); - } - - /// Field number for the "a" field. - public const int AFieldNumber = 1; - private int a_; - /// - /// The largest possible tag number is 2^28 - 1, since the wire format uses - /// three bits to communicate wire type. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int A { - get { return a_; } - set { - a_ = value; - } - } - - /// Field number for the "bb" field. - public const int BbFieldNumber = 268435455; - private int bb_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Bb { - get { return bb_; } - set { - bb_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestReallyLargeTagNumber); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestReallyLargeTagNumber other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (A != other.A) return false; - if (Bb != other.Bb) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (A != 0) hash ^= A.GetHashCode(); - if (Bb != 0) hash ^= Bb.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (A != 0) { - output.WriteRawTag(8); - output.WriteInt32(A); - } - if (Bb != 0) { - output.WriteRawTag(248, 255, 255, 255, 7); - output.WriteInt32(Bb); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (A != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); - } - if (Bb != 0) { - size += 5 + pb::CodedOutputStream.ComputeInt32Size(Bb); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestReallyLargeTagNumber other) { - if (other == null) { - return; - } - if (other.A != 0) { - A = other.A; - } - if (other.Bb != 0) { - Bb = other.Bb; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - A = input.ReadInt32(); - break; - } - case 2147483640: { - Bb = input.ReadInt32(); - break; - } - } - } - } - - } - - public sealed partial class TestRecursiveMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRecursiveMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[7]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestRecursiveMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestRecursiveMessage(TestRecursiveMessage other) : this() { - A = other.a_ != null ? other.A.Clone() : null; - i_ = other.i_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestRecursiveMessage Clone() { - return new TestRecursiveMessage(this); - } - - /// Field number for the "a" field. - public const int AFieldNumber = 1; - private global::Google.Protobuf.TestProtos.TestRecursiveMessage a_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.TestRecursiveMessage A { - get { return a_; } - set { - a_ = value; - } - } - - /// Field number for the "i" field. - public const int IFieldNumber = 2; - private int i_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int I { - get { return i_; } - set { - i_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestRecursiveMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestRecursiveMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!object.Equals(A, other.A)) return false; - if (I != other.I) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (a_ != null) hash ^= A.GetHashCode(); - if (I != 0) hash ^= I.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (a_ != null) { - output.WriteRawTag(10); - output.WriteMessage(A); - } - if (I != 0) { - output.WriteRawTag(16); - output.WriteInt32(I); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (a_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(A); - } - if (I != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(I); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestRecursiveMessage other) { - if (other == null) { - return; - } - if (other.a_ != null) { - if (a_ == null) { - a_ = new global::Google.Protobuf.TestProtos.TestRecursiveMessage(); - } - A.MergeFrom(other.A); - } - if (other.I != 0) { - I = other.I; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - if (a_ == null) { - a_ = new global::Google.Protobuf.TestProtos.TestRecursiveMessage(); - } - input.ReadMessage(a_); - break; - } - case 16: { - I = input.ReadInt32(); - break; - } - } - } - } - - } - - /// - /// Test that mutual recursion works. - /// - public sealed partial class TestMutualRecursionA : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMutualRecursionA()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[8]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMutualRecursionA() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMutualRecursionA(TestMutualRecursionA other) : this() { - Bb = other.bb_ != null ? other.Bb.Clone() : null; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMutualRecursionA Clone() { - return new TestMutualRecursionA(this); - } - - /// Field number for the "bb" field. - public const int BbFieldNumber = 1; - private global::Google.Protobuf.TestProtos.TestMutualRecursionB bb_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.TestMutualRecursionB Bb { - get { return bb_; } - set { - bb_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestMutualRecursionA); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestMutualRecursionA other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!object.Equals(Bb, other.Bb)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (bb_ != null) hash ^= Bb.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (bb_ != null) { - output.WriteRawTag(10); - output.WriteMessage(Bb); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (bb_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(Bb); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestMutualRecursionA other) { - if (other == null) { - return; - } - if (other.bb_ != null) { - if (bb_ == null) { - bb_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionB(); - } - Bb.MergeFrom(other.Bb); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - if (bb_ == null) { - bb_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionB(); - } - input.ReadMessage(bb_); - break; - } - } - } - } - - } - - public sealed partial class TestMutualRecursionB : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMutualRecursionB()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[9]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMutualRecursionB() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMutualRecursionB(TestMutualRecursionB other) : this() { - A = other.a_ != null ? other.A.Clone() : null; - optionalInt32_ = other.optionalInt32_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestMutualRecursionB Clone() { - return new TestMutualRecursionB(this); - } - - /// Field number for the "a" field. - public const int AFieldNumber = 1; - private global::Google.Protobuf.TestProtos.TestMutualRecursionA a_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.TestMutualRecursionA A { - get { return a_; } - set { - a_ = value; - } - } - - /// Field number for the "optional_int32" field. - public const int OptionalInt32FieldNumber = 2; - private int optionalInt32_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int OptionalInt32 { - get { return optionalInt32_; } - set { - optionalInt32_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestMutualRecursionB); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestMutualRecursionB other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (!object.Equals(A, other.A)) return false; - if (OptionalInt32 != other.OptionalInt32) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (a_ != null) hash ^= A.GetHashCode(); - if (OptionalInt32 != 0) hash ^= OptionalInt32.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (a_ != null) { - output.WriteRawTag(10); - output.WriteMessage(A); - } - if (OptionalInt32 != 0) { - output.WriteRawTag(16); - output.WriteInt32(OptionalInt32); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (a_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(A); - } - if (OptionalInt32 != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestMutualRecursionB other) { - if (other == null) { - return; - } - if (other.a_ != null) { - if (a_ == null) { - a_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionA(); - } - A.MergeFrom(other.A); - } - if (other.OptionalInt32 != 0) { - OptionalInt32 = other.OptionalInt32; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - if (a_ == null) { - a_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionA(); - } - input.ReadMessage(a_); - break; - } - case 16: { - OptionalInt32 = input.ReadInt32(); - break; - } - } - } - } - - } - - public sealed partial class TestEnumAllowAlias : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestEnumAllowAlias()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[10]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestEnumAllowAlias() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestEnumAllowAlias(TestEnumAllowAlias other) : this() { - value_ = other.value_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestEnumAllowAlias Clone() { - return new TestEnumAllowAlias(this); - } - - /// Field number for the "value" field. - public const int ValueFieldNumber = 1; - private global::Google.Protobuf.TestProtos.TestEnumWithDupValue value_ = 0; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.TestEnumWithDupValue Value { - get { return value_; } - set { - value_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestEnumAllowAlias); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestEnumAllowAlias other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Value != other.Value) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Value != 0) hash ^= Value.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Value != 0) { - output.WriteRawTag(8); - output.WriteEnum((int) Value); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Value != 0) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Value); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestEnumAllowAlias other) { - if (other == null) { - return; - } - if (other.Value != 0) { - Value = other.Value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - value_ = (global::Google.Protobuf.TestProtos.TestEnumWithDupValue) input.ReadEnum(); - break; - } - } - } - } - - } - - /// - /// Test message with CamelCase field names. This violates Protocol Buffer - /// standard style. - /// - public sealed partial class TestCamelCaseFieldNames : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestCamelCaseFieldNames()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[11]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestCamelCaseFieldNames() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestCamelCaseFieldNames(TestCamelCaseFieldNames other) : this() { - primitiveField_ = other.primitiveField_; - stringField_ = other.stringField_; - enumField_ = other.enumField_; - MessageField = other.messageField_ != null ? other.MessageField.Clone() : null; - repeatedPrimitiveField_ = other.repeatedPrimitiveField_.Clone(); - repeatedStringField_ = other.repeatedStringField_.Clone(); - repeatedEnumField_ = other.repeatedEnumField_.Clone(); - repeatedMessageField_ = other.repeatedMessageField_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestCamelCaseFieldNames Clone() { - return new TestCamelCaseFieldNames(this); - } - - /// Field number for the "PrimitiveField" field. - public const int PrimitiveFieldFieldNumber = 1; - private int primitiveField_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int PrimitiveField { - get { return primitiveField_; } - set { - primitiveField_ = value; - } - } - - /// Field number for the "StringField" field. - public const int StringFieldFieldNumber = 2; - private string stringField_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string StringField { - get { return stringField_; } - set { - stringField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "EnumField" field. - public const int EnumFieldFieldNumber = 3; - private global::Google.Protobuf.TestProtos.ForeignEnum enumField_ = 0; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.ForeignEnum EnumField { - get { return enumField_; } - set { - enumField_ = value; - } - } - - /// Field number for the "MessageField" field. - public const int MessageFieldFieldNumber = 4; - private global::Google.Protobuf.TestProtos.ForeignMessage messageField_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.ForeignMessage MessageField { - get { return messageField_; } - set { - messageField_ = value; - } - } - - /// Field number for the "RepeatedPrimitiveField" field. - public const int RepeatedPrimitiveFieldFieldNumber = 7; - private static readonly pb::FieldCodec _repeated_repeatedPrimitiveField_codec - = pb::FieldCodec.ForInt32(58); - private readonly pbc::RepeatedField repeatedPrimitiveField_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedPrimitiveField { - get { return repeatedPrimitiveField_; } - } - - /// Field number for the "RepeatedStringField" field. - public const int RepeatedStringFieldFieldNumber = 8; - private static readonly pb::FieldCodec _repeated_repeatedStringField_codec - = pb::FieldCodec.ForString(66); - private readonly pbc::RepeatedField repeatedStringField_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedStringField { - get { return repeatedStringField_; } - } - - /// Field number for the "RepeatedEnumField" field. - public const int RepeatedEnumFieldFieldNumber = 9; - private static readonly pb::FieldCodec _repeated_repeatedEnumField_codec - = pb::FieldCodec.ForEnum(74, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x); - private readonly pbc::RepeatedField repeatedEnumField_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedEnumField { - get { return repeatedEnumField_; } - } - - /// Field number for the "RepeatedMessageField" field. - public const int RepeatedMessageFieldFieldNumber = 10; - private static readonly pb::FieldCodec _repeated_repeatedMessageField_codec - = pb::FieldCodec.ForMessage(82, global::Google.Protobuf.TestProtos.ForeignMessage.Parser); - private readonly pbc::RepeatedField repeatedMessageField_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedMessageField { - get { return repeatedMessageField_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestCamelCaseFieldNames); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestCamelCaseFieldNames other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (PrimitiveField != other.PrimitiveField) return false; - if (StringField != other.StringField) return false; - if (EnumField != other.EnumField) return false; - if (!object.Equals(MessageField, other.MessageField)) return false; - if(!repeatedPrimitiveField_.Equals(other.repeatedPrimitiveField_)) return false; - if(!repeatedStringField_.Equals(other.repeatedStringField_)) return false; - if(!repeatedEnumField_.Equals(other.repeatedEnumField_)) return false; - if(!repeatedMessageField_.Equals(other.repeatedMessageField_)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (PrimitiveField != 0) hash ^= PrimitiveField.GetHashCode(); - if (StringField.Length != 0) hash ^= StringField.GetHashCode(); - if (EnumField != 0) hash ^= EnumField.GetHashCode(); - if (messageField_ != null) hash ^= MessageField.GetHashCode(); - hash ^= repeatedPrimitiveField_.GetHashCode(); - hash ^= repeatedStringField_.GetHashCode(); - hash ^= repeatedEnumField_.GetHashCode(); - hash ^= repeatedMessageField_.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (PrimitiveField != 0) { - output.WriteRawTag(8); - output.WriteInt32(PrimitiveField); - } - if (StringField.Length != 0) { - output.WriteRawTag(18); - output.WriteString(StringField); - } - if (EnumField != 0) { - output.WriteRawTag(24); - output.WriteEnum((int) EnumField); - } - if (messageField_ != null) { - output.WriteRawTag(34); - output.WriteMessage(MessageField); - } - repeatedPrimitiveField_.WriteTo(output, _repeated_repeatedPrimitiveField_codec); - repeatedStringField_.WriteTo(output, _repeated_repeatedStringField_codec); - repeatedEnumField_.WriteTo(output, _repeated_repeatedEnumField_codec); - repeatedMessageField_.WriteTo(output, _repeated_repeatedMessageField_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (PrimitiveField != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(PrimitiveField); - } - if (StringField.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(StringField); - } - if (EnumField != 0) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumField); - } - if (messageField_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageField); - } - size += repeatedPrimitiveField_.CalculateSize(_repeated_repeatedPrimitiveField_codec); - size += repeatedStringField_.CalculateSize(_repeated_repeatedStringField_codec); - size += repeatedEnumField_.CalculateSize(_repeated_repeatedEnumField_codec); - size += repeatedMessageField_.CalculateSize(_repeated_repeatedMessageField_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestCamelCaseFieldNames other) { - if (other == null) { - return; - } - if (other.PrimitiveField != 0) { - PrimitiveField = other.PrimitiveField; - } - if (other.StringField.Length != 0) { - StringField = other.StringField; - } - if (other.EnumField != 0) { - EnumField = other.EnumField; - } - if (other.messageField_ != null) { - if (messageField_ == null) { - messageField_ = new global::Google.Protobuf.TestProtos.ForeignMessage(); - } - MessageField.MergeFrom(other.MessageField); - } - repeatedPrimitiveField_.Add(other.repeatedPrimitiveField_); - repeatedStringField_.Add(other.repeatedStringField_); - repeatedEnumField_.Add(other.repeatedEnumField_); - repeatedMessageField_.Add(other.repeatedMessageField_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - PrimitiveField = input.ReadInt32(); - break; - } - case 18: { - StringField = input.ReadString(); - break; - } - case 24: { - enumField_ = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum(); - break; - } - case 34: { - if (messageField_ == null) { - messageField_ = new global::Google.Protobuf.TestProtos.ForeignMessage(); - } - input.ReadMessage(messageField_); - break; - } - case 58: - case 56: { - repeatedPrimitiveField_.AddEntriesFrom(input, _repeated_repeatedPrimitiveField_codec); - break; - } - case 66: { - repeatedStringField_.AddEntriesFrom(input, _repeated_repeatedStringField_codec); - break; - } - case 74: - case 72: { - repeatedEnumField_.AddEntriesFrom(input, _repeated_repeatedEnumField_codec); - break; - } - case 82: { - repeatedMessageField_.AddEntriesFrom(input, _repeated_repeatedMessageField_codec); - break; - } - } - } - } - - } - - /// - /// We list fields out of order, to ensure that we're using field number and not - /// field index to determine serialization order. - /// - public sealed partial class TestFieldOrderings : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestFieldOrderings()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[12]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestFieldOrderings() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestFieldOrderings(TestFieldOrderings other) : this() { - myString_ = other.myString_; - myInt_ = other.myInt_; - myFloat_ = other.myFloat_; - SingleNestedMessage = other.singleNestedMessage_ != null ? other.SingleNestedMessage.Clone() : null; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestFieldOrderings Clone() { - return new TestFieldOrderings(this); - } - - /// Field number for the "my_string" field. - public const int MyStringFieldNumber = 11; - private string myString_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string MyString { - get { return myString_; } - set { - myString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - /// Field number for the "my_int" field. - public const int MyIntFieldNumber = 1; - private long myInt_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public long MyInt { - get { return myInt_; } - set { - myInt_ = value; - } - } - - /// Field number for the "my_float" field. - public const int MyFloatFieldNumber = 101; - private float myFloat_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public float MyFloat { - get { return myFloat_; } - set { - myFloat_ = value; - } - } - - /// Field number for the "single_nested_message" field. - public const int SingleNestedMessageFieldNumber = 200; - private global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage singleNestedMessage_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage SingleNestedMessage { - get { return singleNestedMessage_; } - set { - singleNestedMessage_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestFieldOrderings); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestFieldOrderings other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (MyString != other.MyString) return false; - if (MyInt != other.MyInt) return false; - if (MyFloat != other.MyFloat) return false; - if (!object.Equals(SingleNestedMessage, other.SingleNestedMessage)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (MyString.Length != 0) hash ^= MyString.GetHashCode(); - if (MyInt != 0L) hash ^= MyInt.GetHashCode(); - if (MyFloat != 0F) hash ^= MyFloat.GetHashCode(); - if (singleNestedMessage_ != null) hash ^= SingleNestedMessage.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (MyInt != 0L) { - output.WriteRawTag(8); - output.WriteInt64(MyInt); - } - if (MyString.Length != 0) { - output.WriteRawTag(90); - output.WriteString(MyString); - } - if (MyFloat != 0F) { - output.WriteRawTag(173, 6); - output.WriteFloat(MyFloat); - } - if (singleNestedMessage_ != null) { - output.WriteRawTag(194, 12); - output.WriteMessage(SingleNestedMessage); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (MyString.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(MyString); - } - if (MyInt != 0L) { - size += 1 + pb::CodedOutputStream.ComputeInt64Size(MyInt); - } - if (MyFloat != 0F) { - size += 2 + 4; - } - if (singleNestedMessage_ != null) { - size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleNestedMessage); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestFieldOrderings other) { - if (other == null) { - return; - } - if (other.MyString.Length != 0) { - MyString = other.MyString; - } - if (other.MyInt != 0L) { - MyInt = other.MyInt; - } - if (other.MyFloat != 0F) { - MyFloat = other.MyFloat; - } - if (other.singleNestedMessage_ != null) { - if (singleNestedMessage_ == null) { - singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage(); - } - SingleNestedMessage.MergeFrom(other.SingleNestedMessage); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - MyInt = input.ReadInt64(); - break; - } - case 90: { - MyString = input.ReadString(); - break; - } - case 813: { - MyFloat = input.ReadFloat(); - break; - } - case 1602: { - if (singleNestedMessage_ == null) { - singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage(); - } - input.ReadMessage(singleNestedMessage_); - break; - } - } - } - } - - #region Nested types - /// Container for nested types declared in the TestFieldOrderings message type. - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static partial class Types { - public sealed partial class NestedMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.TestFieldOrderings.Descriptor.NestedTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedMessage(NestedMessage other) : this() { - oo_ = other.oo_; - bb_ = other.bb_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public NestedMessage Clone() { - return new NestedMessage(this); - } - - /// Field number for the "oo" field. - public const int OoFieldNumber = 2; - private long oo_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public long Oo { - get { return oo_; } - set { - oo_ = value; - } - } - - /// Field number for the "bb" field. - public const int BbFieldNumber = 1; - private int bb_; - /// - /// The field name "b" fails to compile in proto1 because it conflicts with - /// a local variable named "b" in one of the generated methods. Doh. - /// This file needs to compile in proto1 to test backwards-compatibility. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Bb { - get { return bb_; } - set { - bb_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as NestedMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(NestedMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Oo != other.Oo) return false; - if (Bb != other.Bb) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Oo != 0L) hash ^= Oo.GetHashCode(); - if (Bb != 0) hash ^= Bb.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Bb != 0) { - output.WriteRawTag(8); - output.WriteInt32(Bb); - } - if (Oo != 0L) { - output.WriteRawTag(16); - output.WriteInt64(Oo); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Oo != 0L) { - size += 1 + pb::CodedOutputStream.ComputeInt64Size(Oo); - } - if (Bb != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Bb); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(NestedMessage other) { - if (other == null) { - return; - } - if (other.Oo != 0L) { - Oo = other.Oo; - } - if (other.Bb != 0) { - Bb = other.Bb; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - Bb = input.ReadInt32(); - break; - } - case 16: { - Oo = input.ReadInt64(); - break; - } - } - } - } - - } - - } - #endregion - - } - - public sealed partial class SparseEnumMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SparseEnumMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[13]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public SparseEnumMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public SparseEnumMessage(SparseEnumMessage other) : this() { - sparseEnum_ = other.sparseEnum_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public SparseEnumMessage Clone() { - return new SparseEnumMessage(this); - } - - /// Field number for the "sparse_enum" field. - public const int SparseEnumFieldNumber = 1; - private global::Google.Protobuf.TestProtos.TestSparseEnum sparseEnum_ = 0; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.TestSparseEnum SparseEnum { - get { return sparseEnum_; } - set { - sparseEnum_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as SparseEnumMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(SparseEnumMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (SparseEnum != other.SparseEnum) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (SparseEnum != 0) hash ^= SparseEnum.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (SparseEnum != 0) { - output.WriteRawTag(8); - output.WriteEnum((int) SparseEnum); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (SparseEnum != 0) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) SparseEnum); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(SparseEnumMessage other) { - if (other == null) { - return; - } - if (other.SparseEnum != 0) { - SparseEnum = other.SparseEnum; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - sparseEnum_ = (global::Google.Protobuf.TestProtos.TestSparseEnum) input.ReadEnum(); - break; - } - } - } - } - - } - - /// - /// Test String and Bytes: string is for valid UTF-8 strings - /// - public sealed partial class OneString : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneString()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[14]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public OneString() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public OneString(OneString other) : this() { - data_ = other.data_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public OneString Clone() { - return new OneString(this); - } - - /// Field number for the "data" field. - public const int DataFieldNumber = 1; - private string data_ = ""; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string Data { - get { return data_; } - set { - data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as OneString); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(OneString other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Data != other.Data) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Data.Length != 0) hash ^= Data.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Data.Length != 0) { - output.WriteRawTag(10); - output.WriteString(Data); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Data.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(Data); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(OneString other) { - if (other == null) { - return; - } - if (other.Data.Length != 0) { - Data = other.Data; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - Data = input.ReadString(); - break; - } - } - } - } - - } - - public sealed partial class MoreString : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MoreString()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[15]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public MoreString() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public MoreString(MoreString other) : this() { - data_ = other.data_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public MoreString Clone() { - return new MoreString(this); - } - - /// Field number for the "data" field. - public const int DataFieldNumber = 1; - private static readonly pb::FieldCodec _repeated_data_codec - = pb::FieldCodec.ForString(10); - private readonly pbc::RepeatedField data_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField Data { - get { return data_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as MoreString); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(MoreString other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if(!data_.Equals(other.data_)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - hash ^= data_.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - data_.WriteTo(output, _repeated_data_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - size += data_.CalculateSize(_repeated_data_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(MoreString other) { - if (other == null) { - return; - } - data_.Add(other.data_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - data_.AddEntriesFrom(input, _repeated_data_codec); - break; - } - } - } - } - - } - - public sealed partial class OneBytes : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneBytes()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[16]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public OneBytes() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public OneBytes(OneBytes other) : this() { - data_ = other.data_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public OneBytes Clone() { - return new OneBytes(this); - } - - /// Field number for the "data" field. - public const int DataFieldNumber = 1; - private pb::ByteString data_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pb::ByteString Data { - get { return data_; } - set { - data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as OneBytes); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(OneBytes other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Data != other.Data) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Data.Length != 0) hash ^= Data.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Data.Length != 0) { - output.WriteRawTag(10); - output.WriteBytes(Data); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Data.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(Data); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(OneBytes other) { - if (other == null) { - return; - } - if (other.Data.Length != 0) { - Data = other.Data; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - Data = input.ReadBytes(); - break; - } - } - } - } - - } - - public sealed partial class MoreBytes : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MoreBytes()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[17]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public MoreBytes() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public MoreBytes(MoreBytes other) : this() { - data_ = other.data_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public MoreBytes Clone() { - return new MoreBytes(this); - } - - /// Field number for the "data" field. - public const int DataFieldNumber = 1; - private pb::ByteString data_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pb::ByteString Data { - get { return data_; } - set { - data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as MoreBytes); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(MoreBytes other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Data != other.Data) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Data.Length != 0) hash ^= Data.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Data.Length != 0) { - output.WriteRawTag(10); - output.WriteBytes(Data); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Data.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(Data); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(MoreBytes other) { - if (other == null) { - return; - } - if (other.Data.Length != 0) { - Data = other.Data; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - Data = input.ReadBytes(); - break; - } - } - } - } - - } - - /// - /// Test int32, uint32, int64, uint64, and bool are all compatible - /// - public sealed partial class Int32Message : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Int32Message()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[18]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Int32Message() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Int32Message(Int32Message other) : this() { - data_ = other.data_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Int32Message Clone() { - return new Int32Message(this); - } - - /// Field number for the "data" field. - public const int DataFieldNumber = 1; - private int data_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Data { - get { return data_; } - set { - data_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as Int32Message); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(Int32Message other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Data != other.Data) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Data != 0) hash ^= Data.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Data != 0) { - output.WriteRawTag(8); - output.WriteInt32(Data); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Data != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Data); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(Int32Message other) { - if (other == null) { - return; - } - if (other.Data != 0) { - Data = other.Data; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - Data = input.ReadInt32(); - break; - } - } - } - } - - } - - public sealed partial class Uint32Message : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Uint32Message()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[19]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Uint32Message() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Uint32Message(Uint32Message other) : this() { - data_ = other.data_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Uint32Message Clone() { - return new Uint32Message(this); - } - - /// Field number for the "data" field. - public const int DataFieldNumber = 1; - private uint data_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint Data { - get { return data_; } - set { - data_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as Uint32Message); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(Uint32Message other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Data != other.Data) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Data != 0) hash ^= Data.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Data != 0) { - output.WriteRawTag(8); - output.WriteUInt32(Data); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Data != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Data); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(Uint32Message other) { - if (other == null) { - return; - } - if (other.Data != 0) { - Data = other.Data; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - Data = input.ReadUInt32(); - break; - } - } - } - } - - } - - public sealed partial class Int64Message : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Int64Message()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[20]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Int64Message() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Int64Message(Int64Message other) : this() { - data_ = other.data_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Int64Message Clone() { - return new Int64Message(this); - } - - /// Field number for the "data" field. - public const int DataFieldNumber = 1; - private long data_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public long Data { - get { return data_; } - set { - data_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as Int64Message); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(Int64Message other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Data != other.Data) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Data != 0L) hash ^= Data.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Data != 0L) { - output.WriteRawTag(8); - output.WriteInt64(Data); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Data != 0L) { - size += 1 + pb::CodedOutputStream.ComputeInt64Size(Data); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(Int64Message other) { - if (other == null) { - return; - } - if (other.Data != 0L) { - Data = other.Data; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - Data = input.ReadInt64(); - break; - } - } - } - } - - } - - public sealed partial class Uint64Message : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Uint64Message()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[21]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Uint64Message() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Uint64Message(Uint64Message other) : this() { - data_ = other.data_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Uint64Message Clone() { - return new Uint64Message(this); - } - - /// Field number for the "data" field. - public const int DataFieldNumber = 1; - private ulong data_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public ulong Data { - get { return data_; } - set { - data_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as Uint64Message); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(Uint64Message other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Data != other.Data) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Data != 0UL) hash ^= Data.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Data != 0UL) { - output.WriteRawTag(8); - output.WriteUInt64(Data); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Data != 0UL) { - size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Data); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(Uint64Message other) { - if (other == null) { - return; - } - if (other.Data != 0UL) { - Data = other.Data; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - Data = input.ReadUInt64(); - break; - } - } - } - } - - } - - public sealed partial class BoolMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BoolMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[22]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public BoolMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public BoolMessage(BoolMessage other) : this() { - data_ = other.data_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public BoolMessage Clone() { - return new BoolMessage(this); - } - - /// Field number for the "data" field. - public const int DataFieldNumber = 1; - private bool data_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Data { - get { return data_; } - set { - data_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as BoolMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(BoolMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (Data != other.Data) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (Data != false) hash ^= Data.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (Data != false) { - output.WriteRawTag(8); - output.WriteBool(Data); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (Data != false) { - size += 1 + 1; - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(BoolMessage other) { - if (other == null) { - return; - } - if (other.Data != false) { - Data = other.Data; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - Data = input.ReadBool(); - break; - } - } - } - } - - } - - /// - /// Test oneofs. - /// - public sealed partial class TestOneof : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestOneof()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[23]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestOneof() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestOneof(TestOneof other) : this() { - switch (other.FooCase) { - case FooOneofCase.FooInt: - FooInt = other.FooInt; - break; - case FooOneofCase.FooString: - FooString = other.FooString; - break; - case FooOneofCase.FooMessage: - FooMessage = other.FooMessage.Clone(); - break; - } - - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestOneof Clone() { - return new TestOneof(this); - } - - /// Field number for the "foo_int" field. - public const int FooIntFieldNumber = 1; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FooInt { - get { return fooCase_ == FooOneofCase.FooInt ? (int) foo_ : 0; } - set { - foo_ = value; - fooCase_ = FooOneofCase.FooInt; - } - } - - /// Field number for the "foo_string" field. - public const int FooStringFieldNumber = 2; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string FooString { - get { return fooCase_ == FooOneofCase.FooString ? (string) foo_ : ""; } - set { - foo_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - fooCase_ = FooOneofCase.FooString; - } - } - - /// Field number for the "foo_message" field. - public const int FooMessageFieldNumber = 3; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public global::Google.Protobuf.TestProtos.TestAllTypes FooMessage { - get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.Protobuf.TestProtos.TestAllTypes) foo_ : null; } - set { - foo_ = value; - fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooMessage; - } - } - - private object foo_; - /// Enum of possible cases for the "foo" oneof. - public enum FooOneofCase { - None = 0, - FooInt = 1, - FooString = 2, - FooMessage = 3, - } - private FooOneofCase fooCase_ = FooOneofCase.None; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public FooOneofCase FooCase { - get { return fooCase_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void ClearFoo() { - fooCase_ = FooOneofCase.None; - foo_ = null; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestOneof); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestOneof other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (FooInt != other.FooInt) return false; - if (FooString != other.FooString) return false; - if (!object.Equals(FooMessage, other.FooMessage)) return false; - if (FooCase != other.FooCase) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (fooCase_ == FooOneofCase.FooInt) hash ^= FooInt.GetHashCode(); - if (fooCase_ == FooOneofCase.FooString) hash ^= FooString.GetHashCode(); - if (fooCase_ == FooOneofCase.FooMessage) hash ^= FooMessage.GetHashCode(); - hash ^= (int) fooCase_; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (fooCase_ == FooOneofCase.FooInt) { - output.WriteRawTag(8); - output.WriteInt32(FooInt); - } - if (fooCase_ == FooOneofCase.FooString) { - output.WriteRawTag(18); - output.WriteString(FooString); - } - if (fooCase_ == FooOneofCase.FooMessage) { - output.WriteRawTag(26); - output.WriteMessage(FooMessage); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (fooCase_ == FooOneofCase.FooInt) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(FooInt); - } - if (fooCase_ == FooOneofCase.FooString) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(FooString); - } - if (fooCase_ == FooOneofCase.FooMessage) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(FooMessage); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestOneof other) { - if (other == null) { - return; - } - switch (other.FooCase) { - case FooOneofCase.FooInt: - FooInt = other.FooInt; - break; - case FooOneofCase.FooString: - FooString = other.FooString; - break; - case FooOneofCase.FooMessage: - FooMessage = other.FooMessage; - break; - } - - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 8: { - FooInt = input.ReadInt32(); - break; - } - case 18: { - FooString = input.ReadString(); - break; - } - case 26: { - global::Google.Protobuf.TestProtos.TestAllTypes subBuilder = new global::Google.Protobuf.TestProtos.TestAllTypes(); - if (fooCase_ == FooOneofCase.FooMessage) { - subBuilder.MergeFrom(FooMessage); - } - input.ReadMessage(subBuilder); - FooMessage = subBuilder; - break; - } - } - } - } - - } - - public sealed partial class TestPackedTypes : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestPackedTypes()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[24]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestPackedTypes() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestPackedTypes(TestPackedTypes other) : this() { - packedInt32_ = other.packedInt32_.Clone(); - packedInt64_ = other.packedInt64_.Clone(); - packedUint32_ = other.packedUint32_.Clone(); - packedUint64_ = other.packedUint64_.Clone(); - packedSint32_ = other.packedSint32_.Clone(); - packedSint64_ = other.packedSint64_.Clone(); - packedFixed32_ = other.packedFixed32_.Clone(); - packedFixed64_ = other.packedFixed64_.Clone(); - packedSfixed32_ = other.packedSfixed32_.Clone(); - packedSfixed64_ = other.packedSfixed64_.Clone(); - packedFloat_ = other.packedFloat_.Clone(); - packedDouble_ = other.packedDouble_.Clone(); - packedBool_ = other.packedBool_.Clone(); - packedEnum_ = other.packedEnum_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestPackedTypes Clone() { - return new TestPackedTypes(this); - } - - /// Field number for the "packed_int32" field. - public const int PackedInt32FieldNumber = 90; - private static readonly pb::FieldCodec _repeated_packedInt32_codec - = pb::FieldCodec.ForInt32(722); - private readonly pbc::RepeatedField packedInt32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedInt32 { - get { return packedInt32_; } - } - - /// Field number for the "packed_int64" field. - public const int PackedInt64FieldNumber = 91; - private static readonly pb::FieldCodec _repeated_packedInt64_codec - = pb::FieldCodec.ForInt64(730); - private readonly pbc::RepeatedField packedInt64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedInt64 { - get { return packedInt64_; } - } - - /// Field number for the "packed_uint32" field. - public const int PackedUint32FieldNumber = 92; - private static readonly pb::FieldCodec _repeated_packedUint32_codec - = pb::FieldCodec.ForUInt32(738); - private readonly pbc::RepeatedField packedUint32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedUint32 { - get { return packedUint32_; } - } - - /// Field number for the "packed_uint64" field. - public const int PackedUint64FieldNumber = 93; - private static readonly pb::FieldCodec _repeated_packedUint64_codec - = pb::FieldCodec.ForUInt64(746); - private readonly pbc::RepeatedField packedUint64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedUint64 { - get { return packedUint64_; } - } - - /// Field number for the "packed_sint32" field. - public const int PackedSint32FieldNumber = 94; - private static readonly pb::FieldCodec _repeated_packedSint32_codec - = pb::FieldCodec.ForSInt32(754); - private readonly pbc::RepeatedField packedSint32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedSint32 { - get { return packedSint32_; } - } - - /// Field number for the "packed_sint64" field. - public const int PackedSint64FieldNumber = 95; - private static readonly pb::FieldCodec _repeated_packedSint64_codec - = pb::FieldCodec.ForSInt64(762); - private readonly pbc::RepeatedField packedSint64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedSint64 { - get { return packedSint64_; } - } - - /// Field number for the "packed_fixed32" field. - public const int PackedFixed32FieldNumber = 96; - private static readonly pb::FieldCodec _repeated_packedFixed32_codec - = pb::FieldCodec.ForFixed32(770); - private readonly pbc::RepeatedField packedFixed32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedFixed32 { - get { return packedFixed32_; } - } - - /// Field number for the "packed_fixed64" field. - public const int PackedFixed64FieldNumber = 97; - private static readonly pb::FieldCodec _repeated_packedFixed64_codec - = pb::FieldCodec.ForFixed64(778); - private readonly pbc::RepeatedField packedFixed64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedFixed64 { - get { return packedFixed64_; } - } - - /// Field number for the "packed_sfixed32" field. - public const int PackedSfixed32FieldNumber = 98; - private static readonly pb::FieldCodec _repeated_packedSfixed32_codec - = pb::FieldCodec.ForSFixed32(786); - private readonly pbc::RepeatedField packedSfixed32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedSfixed32 { - get { return packedSfixed32_; } - } - - /// Field number for the "packed_sfixed64" field. - public const int PackedSfixed64FieldNumber = 99; - private static readonly pb::FieldCodec _repeated_packedSfixed64_codec - = pb::FieldCodec.ForSFixed64(794); - private readonly pbc::RepeatedField packedSfixed64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedSfixed64 { - get { return packedSfixed64_; } - } - - /// Field number for the "packed_float" field. - public const int PackedFloatFieldNumber = 100; - private static readonly pb::FieldCodec _repeated_packedFloat_codec - = pb::FieldCodec.ForFloat(802); - private readonly pbc::RepeatedField packedFloat_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedFloat { - get { return packedFloat_; } - } - - /// Field number for the "packed_double" field. - public const int PackedDoubleFieldNumber = 101; - private static readonly pb::FieldCodec _repeated_packedDouble_codec - = pb::FieldCodec.ForDouble(810); - private readonly pbc::RepeatedField packedDouble_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedDouble { - get { return packedDouble_; } - } - - /// Field number for the "packed_bool" field. - public const int PackedBoolFieldNumber = 102; - private static readonly pb::FieldCodec _repeated_packedBool_codec - = pb::FieldCodec.ForBool(818); - private readonly pbc::RepeatedField packedBool_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedBool { - get { return packedBool_; } - } - - /// Field number for the "packed_enum" field. - public const int PackedEnumFieldNumber = 103; - private static readonly pb::FieldCodec _repeated_packedEnum_codec - = pb::FieldCodec.ForEnum(826, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x); - private readonly pbc::RepeatedField packedEnum_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField PackedEnum { - get { return packedEnum_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestPackedTypes); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestPackedTypes other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if(!packedInt32_.Equals(other.packedInt32_)) return false; - if(!packedInt64_.Equals(other.packedInt64_)) return false; - if(!packedUint32_.Equals(other.packedUint32_)) return false; - if(!packedUint64_.Equals(other.packedUint64_)) return false; - if(!packedSint32_.Equals(other.packedSint32_)) return false; - if(!packedSint64_.Equals(other.packedSint64_)) return false; - if(!packedFixed32_.Equals(other.packedFixed32_)) return false; - if(!packedFixed64_.Equals(other.packedFixed64_)) return false; - if(!packedSfixed32_.Equals(other.packedSfixed32_)) return false; - if(!packedSfixed64_.Equals(other.packedSfixed64_)) return false; - if(!packedFloat_.Equals(other.packedFloat_)) return false; - if(!packedDouble_.Equals(other.packedDouble_)) return false; - if(!packedBool_.Equals(other.packedBool_)) return false; - if(!packedEnum_.Equals(other.packedEnum_)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - hash ^= packedInt32_.GetHashCode(); - hash ^= packedInt64_.GetHashCode(); - hash ^= packedUint32_.GetHashCode(); - hash ^= packedUint64_.GetHashCode(); - hash ^= packedSint32_.GetHashCode(); - hash ^= packedSint64_.GetHashCode(); - hash ^= packedFixed32_.GetHashCode(); - hash ^= packedFixed64_.GetHashCode(); - hash ^= packedSfixed32_.GetHashCode(); - hash ^= packedSfixed64_.GetHashCode(); - hash ^= packedFloat_.GetHashCode(); - hash ^= packedDouble_.GetHashCode(); - hash ^= packedBool_.GetHashCode(); - hash ^= packedEnum_.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - packedInt32_.WriteTo(output, _repeated_packedInt32_codec); - packedInt64_.WriteTo(output, _repeated_packedInt64_codec); - packedUint32_.WriteTo(output, _repeated_packedUint32_codec); - packedUint64_.WriteTo(output, _repeated_packedUint64_codec); - packedSint32_.WriteTo(output, _repeated_packedSint32_codec); - packedSint64_.WriteTo(output, _repeated_packedSint64_codec); - packedFixed32_.WriteTo(output, _repeated_packedFixed32_codec); - packedFixed64_.WriteTo(output, _repeated_packedFixed64_codec); - packedSfixed32_.WriteTo(output, _repeated_packedSfixed32_codec); - packedSfixed64_.WriteTo(output, _repeated_packedSfixed64_codec); - packedFloat_.WriteTo(output, _repeated_packedFloat_codec); - packedDouble_.WriteTo(output, _repeated_packedDouble_codec); - packedBool_.WriteTo(output, _repeated_packedBool_codec); - packedEnum_.WriteTo(output, _repeated_packedEnum_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - size += packedInt32_.CalculateSize(_repeated_packedInt32_codec); - size += packedInt64_.CalculateSize(_repeated_packedInt64_codec); - size += packedUint32_.CalculateSize(_repeated_packedUint32_codec); - size += packedUint64_.CalculateSize(_repeated_packedUint64_codec); - size += packedSint32_.CalculateSize(_repeated_packedSint32_codec); - size += packedSint64_.CalculateSize(_repeated_packedSint64_codec); - size += packedFixed32_.CalculateSize(_repeated_packedFixed32_codec); - size += packedFixed64_.CalculateSize(_repeated_packedFixed64_codec); - size += packedSfixed32_.CalculateSize(_repeated_packedSfixed32_codec); - size += packedSfixed64_.CalculateSize(_repeated_packedSfixed64_codec); - size += packedFloat_.CalculateSize(_repeated_packedFloat_codec); - size += packedDouble_.CalculateSize(_repeated_packedDouble_codec); - size += packedBool_.CalculateSize(_repeated_packedBool_codec); - size += packedEnum_.CalculateSize(_repeated_packedEnum_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestPackedTypes other) { - if (other == null) { - return; - } - packedInt32_.Add(other.packedInt32_); - packedInt64_.Add(other.packedInt64_); - packedUint32_.Add(other.packedUint32_); - packedUint64_.Add(other.packedUint64_); - packedSint32_.Add(other.packedSint32_); - packedSint64_.Add(other.packedSint64_); - packedFixed32_.Add(other.packedFixed32_); - packedFixed64_.Add(other.packedFixed64_); - packedSfixed32_.Add(other.packedSfixed32_); - packedSfixed64_.Add(other.packedSfixed64_); - packedFloat_.Add(other.packedFloat_); - packedDouble_.Add(other.packedDouble_); - packedBool_.Add(other.packedBool_); - packedEnum_.Add(other.packedEnum_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 722: - case 720: { - packedInt32_.AddEntriesFrom(input, _repeated_packedInt32_codec); - break; - } - case 730: - case 728: { - packedInt64_.AddEntriesFrom(input, _repeated_packedInt64_codec); - break; - } - case 738: - case 736: { - packedUint32_.AddEntriesFrom(input, _repeated_packedUint32_codec); - break; - } - case 746: - case 744: { - packedUint64_.AddEntriesFrom(input, _repeated_packedUint64_codec); - break; - } - case 754: - case 752: { - packedSint32_.AddEntriesFrom(input, _repeated_packedSint32_codec); - break; - } - case 762: - case 760: { - packedSint64_.AddEntriesFrom(input, _repeated_packedSint64_codec); - break; - } - case 770: - case 773: { - packedFixed32_.AddEntriesFrom(input, _repeated_packedFixed32_codec); - break; - } - case 778: - case 777: { - packedFixed64_.AddEntriesFrom(input, _repeated_packedFixed64_codec); - break; - } - case 786: - case 789: { - packedSfixed32_.AddEntriesFrom(input, _repeated_packedSfixed32_codec); - break; - } - case 794: - case 793: { - packedSfixed64_.AddEntriesFrom(input, _repeated_packedSfixed64_codec); - break; - } - case 802: - case 805: { - packedFloat_.AddEntriesFrom(input, _repeated_packedFloat_codec); - break; - } - case 810: - case 809: { - packedDouble_.AddEntriesFrom(input, _repeated_packedDouble_codec); - break; - } - case 818: - case 816: { - packedBool_.AddEntriesFrom(input, _repeated_packedBool_codec); - break; - } - case 826: - case 824: { - packedEnum_.AddEntriesFrom(input, _repeated_packedEnum_codec); - break; - } - } - } - } - - } - - /// - /// A message with the same fields as TestPackedTypes, but without packing. Used - /// to test packed <-> unpacked wire compatibility. - /// - public sealed partial class TestUnpackedTypes : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestUnpackedTypes()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[25]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestUnpackedTypes() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestUnpackedTypes(TestUnpackedTypes other) : this() { - unpackedInt32_ = other.unpackedInt32_.Clone(); - unpackedInt64_ = other.unpackedInt64_.Clone(); - unpackedUint32_ = other.unpackedUint32_.Clone(); - unpackedUint64_ = other.unpackedUint64_.Clone(); - unpackedSint32_ = other.unpackedSint32_.Clone(); - unpackedSint64_ = other.unpackedSint64_.Clone(); - unpackedFixed32_ = other.unpackedFixed32_.Clone(); - unpackedFixed64_ = other.unpackedFixed64_.Clone(); - unpackedSfixed32_ = other.unpackedSfixed32_.Clone(); - unpackedSfixed64_ = other.unpackedSfixed64_.Clone(); - unpackedFloat_ = other.unpackedFloat_.Clone(); - unpackedDouble_ = other.unpackedDouble_.Clone(); - unpackedBool_ = other.unpackedBool_.Clone(); - unpackedEnum_ = other.unpackedEnum_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestUnpackedTypes Clone() { - return new TestUnpackedTypes(this); - } - - /// Field number for the "unpacked_int32" field. - public const int UnpackedInt32FieldNumber = 90; - private static readonly pb::FieldCodec _repeated_unpackedInt32_codec - = pb::FieldCodec.ForInt32(720); - private readonly pbc::RepeatedField unpackedInt32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField UnpackedInt32 { - get { return unpackedInt32_; } - } - - /// Field number for the "unpacked_int64" field. - public const int UnpackedInt64FieldNumber = 91; - private static readonly pb::FieldCodec _repeated_unpackedInt64_codec - = pb::FieldCodec.ForInt64(728); - private readonly pbc::RepeatedField unpackedInt64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField UnpackedInt64 { - get { return unpackedInt64_; } - } - - /// Field number for the "unpacked_uint32" field. - public const int UnpackedUint32FieldNumber = 92; - private static readonly pb::FieldCodec _repeated_unpackedUint32_codec - = pb::FieldCodec.ForUInt32(736); - private readonly pbc::RepeatedField unpackedUint32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField UnpackedUint32 { - get { return unpackedUint32_; } - } - - /// Field number for the "unpacked_uint64" field. - public const int UnpackedUint64FieldNumber = 93; - private static readonly pb::FieldCodec _repeated_unpackedUint64_codec - = pb::FieldCodec.ForUInt64(744); - private readonly pbc::RepeatedField unpackedUint64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField UnpackedUint64 { - get { return unpackedUint64_; } - } - - /// Field number for the "unpacked_sint32" field. - public const int UnpackedSint32FieldNumber = 94; - private static readonly pb::FieldCodec _repeated_unpackedSint32_codec - = pb::FieldCodec.ForSInt32(752); - private readonly pbc::RepeatedField unpackedSint32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField UnpackedSint32 { - get { return unpackedSint32_; } - } - - /// Field number for the "unpacked_sint64" field. - public const int UnpackedSint64FieldNumber = 95; - private static readonly pb::FieldCodec _repeated_unpackedSint64_codec - = pb::FieldCodec.ForSInt64(760); - private readonly pbc::RepeatedField unpackedSint64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField UnpackedSint64 { - get { return unpackedSint64_; } - } - - /// Field number for the "unpacked_fixed32" field. - public const int UnpackedFixed32FieldNumber = 96; - private static readonly pb::FieldCodec _repeated_unpackedFixed32_codec - = pb::FieldCodec.ForFixed32(773); - private readonly pbc::RepeatedField unpackedFixed32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField UnpackedFixed32 { - get { return unpackedFixed32_; } - } - - /// Field number for the "unpacked_fixed64" field. - public const int UnpackedFixed64FieldNumber = 97; - private static readonly pb::FieldCodec _repeated_unpackedFixed64_codec - = pb::FieldCodec.ForFixed64(777); - private readonly pbc::RepeatedField unpackedFixed64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField UnpackedFixed64 { - get { return unpackedFixed64_; } - } - - /// Field number for the "unpacked_sfixed32" field. - public const int UnpackedSfixed32FieldNumber = 98; - private static readonly pb::FieldCodec _repeated_unpackedSfixed32_codec - = pb::FieldCodec.ForSFixed32(789); - private readonly pbc::RepeatedField unpackedSfixed32_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField UnpackedSfixed32 { - get { return unpackedSfixed32_; } - } - - /// Field number for the "unpacked_sfixed64" field. - public const int UnpackedSfixed64FieldNumber = 99; - private static readonly pb::FieldCodec _repeated_unpackedSfixed64_codec - = pb::FieldCodec.ForSFixed64(793); - private readonly pbc::RepeatedField unpackedSfixed64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField UnpackedSfixed64 { - get { return unpackedSfixed64_; } - } - - /// Field number for the "unpacked_float" field. - public const int UnpackedFloatFieldNumber = 100; - private static readonly pb::FieldCodec _repeated_unpackedFloat_codec - = pb::FieldCodec.ForFloat(805); - private readonly pbc::RepeatedField unpackedFloat_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField UnpackedFloat { - get { return unpackedFloat_; } - } - - /// Field number for the "unpacked_double" field. - public const int UnpackedDoubleFieldNumber = 101; - private static readonly pb::FieldCodec _repeated_unpackedDouble_codec - = pb::FieldCodec.ForDouble(809); - private readonly pbc::RepeatedField unpackedDouble_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField UnpackedDouble { - get { return unpackedDouble_; } - } - - /// Field number for the "unpacked_bool" field. - public const int UnpackedBoolFieldNumber = 102; - private static readonly pb::FieldCodec _repeated_unpackedBool_codec - = pb::FieldCodec.ForBool(816); - private readonly pbc::RepeatedField unpackedBool_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField UnpackedBool { - get { return unpackedBool_; } - } - - /// Field number for the "unpacked_enum" field. - public const int UnpackedEnumFieldNumber = 103; - private static readonly pb::FieldCodec _repeated_unpackedEnum_codec - = pb::FieldCodec.ForEnum(824, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x); - private readonly pbc::RepeatedField unpackedEnum_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField UnpackedEnum { - get { return unpackedEnum_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestUnpackedTypes); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestUnpackedTypes other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if(!unpackedInt32_.Equals(other.unpackedInt32_)) return false; - if(!unpackedInt64_.Equals(other.unpackedInt64_)) return false; - if(!unpackedUint32_.Equals(other.unpackedUint32_)) return false; - if(!unpackedUint64_.Equals(other.unpackedUint64_)) return false; - if(!unpackedSint32_.Equals(other.unpackedSint32_)) return false; - if(!unpackedSint64_.Equals(other.unpackedSint64_)) return false; - if(!unpackedFixed32_.Equals(other.unpackedFixed32_)) return false; - if(!unpackedFixed64_.Equals(other.unpackedFixed64_)) return false; - if(!unpackedSfixed32_.Equals(other.unpackedSfixed32_)) return false; - if(!unpackedSfixed64_.Equals(other.unpackedSfixed64_)) return false; - if(!unpackedFloat_.Equals(other.unpackedFloat_)) return false; - if(!unpackedDouble_.Equals(other.unpackedDouble_)) return false; - if(!unpackedBool_.Equals(other.unpackedBool_)) return false; - if(!unpackedEnum_.Equals(other.unpackedEnum_)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - hash ^= unpackedInt32_.GetHashCode(); - hash ^= unpackedInt64_.GetHashCode(); - hash ^= unpackedUint32_.GetHashCode(); - hash ^= unpackedUint64_.GetHashCode(); - hash ^= unpackedSint32_.GetHashCode(); - hash ^= unpackedSint64_.GetHashCode(); - hash ^= unpackedFixed32_.GetHashCode(); - hash ^= unpackedFixed64_.GetHashCode(); - hash ^= unpackedSfixed32_.GetHashCode(); - hash ^= unpackedSfixed64_.GetHashCode(); - hash ^= unpackedFloat_.GetHashCode(); - hash ^= unpackedDouble_.GetHashCode(); - hash ^= unpackedBool_.GetHashCode(); - hash ^= unpackedEnum_.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - unpackedInt32_.WriteTo(output, _repeated_unpackedInt32_codec); - unpackedInt64_.WriteTo(output, _repeated_unpackedInt64_codec); - unpackedUint32_.WriteTo(output, _repeated_unpackedUint32_codec); - unpackedUint64_.WriteTo(output, _repeated_unpackedUint64_codec); - unpackedSint32_.WriteTo(output, _repeated_unpackedSint32_codec); - unpackedSint64_.WriteTo(output, _repeated_unpackedSint64_codec); - unpackedFixed32_.WriteTo(output, _repeated_unpackedFixed32_codec); - unpackedFixed64_.WriteTo(output, _repeated_unpackedFixed64_codec); - unpackedSfixed32_.WriteTo(output, _repeated_unpackedSfixed32_codec); - unpackedSfixed64_.WriteTo(output, _repeated_unpackedSfixed64_codec); - unpackedFloat_.WriteTo(output, _repeated_unpackedFloat_codec); - unpackedDouble_.WriteTo(output, _repeated_unpackedDouble_codec); - unpackedBool_.WriteTo(output, _repeated_unpackedBool_codec); - unpackedEnum_.WriteTo(output, _repeated_unpackedEnum_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - size += unpackedInt32_.CalculateSize(_repeated_unpackedInt32_codec); - size += unpackedInt64_.CalculateSize(_repeated_unpackedInt64_codec); - size += unpackedUint32_.CalculateSize(_repeated_unpackedUint32_codec); - size += unpackedUint64_.CalculateSize(_repeated_unpackedUint64_codec); - size += unpackedSint32_.CalculateSize(_repeated_unpackedSint32_codec); - size += unpackedSint64_.CalculateSize(_repeated_unpackedSint64_codec); - size += unpackedFixed32_.CalculateSize(_repeated_unpackedFixed32_codec); - size += unpackedFixed64_.CalculateSize(_repeated_unpackedFixed64_codec); - size += unpackedSfixed32_.CalculateSize(_repeated_unpackedSfixed32_codec); - size += unpackedSfixed64_.CalculateSize(_repeated_unpackedSfixed64_codec); - size += unpackedFloat_.CalculateSize(_repeated_unpackedFloat_codec); - size += unpackedDouble_.CalculateSize(_repeated_unpackedDouble_codec); - size += unpackedBool_.CalculateSize(_repeated_unpackedBool_codec); - size += unpackedEnum_.CalculateSize(_repeated_unpackedEnum_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestUnpackedTypes other) { - if (other == null) { - return; - } - unpackedInt32_.Add(other.unpackedInt32_); - unpackedInt64_.Add(other.unpackedInt64_); - unpackedUint32_.Add(other.unpackedUint32_); - unpackedUint64_.Add(other.unpackedUint64_); - unpackedSint32_.Add(other.unpackedSint32_); - unpackedSint64_.Add(other.unpackedSint64_); - unpackedFixed32_.Add(other.unpackedFixed32_); - unpackedFixed64_.Add(other.unpackedFixed64_); - unpackedSfixed32_.Add(other.unpackedSfixed32_); - unpackedSfixed64_.Add(other.unpackedSfixed64_); - unpackedFloat_.Add(other.unpackedFloat_); - unpackedDouble_.Add(other.unpackedDouble_); - unpackedBool_.Add(other.unpackedBool_); - unpackedEnum_.Add(other.unpackedEnum_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 722: - case 720: { - unpackedInt32_.AddEntriesFrom(input, _repeated_unpackedInt32_codec); - break; - } - case 730: - case 728: { - unpackedInt64_.AddEntriesFrom(input, _repeated_unpackedInt64_codec); - break; - } - case 738: - case 736: { - unpackedUint32_.AddEntriesFrom(input, _repeated_unpackedUint32_codec); - break; - } - case 746: - case 744: { - unpackedUint64_.AddEntriesFrom(input, _repeated_unpackedUint64_codec); - break; - } - case 754: - case 752: { - unpackedSint32_.AddEntriesFrom(input, _repeated_unpackedSint32_codec); - break; - } - case 762: - case 760: { - unpackedSint64_.AddEntriesFrom(input, _repeated_unpackedSint64_codec); - break; - } - case 770: - case 773: { - unpackedFixed32_.AddEntriesFrom(input, _repeated_unpackedFixed32_codec); - break; - } - case 778: - case 777: { - unpackedFixed64_.AddEntriesFrom(input, _repeated_unpackedFixed64_codec); - break; - } - case 786: - case 789: { - unpackedSfixed32_.AddEntriesFrom(input, _repeated_unpackedSfixed32_codec); - break; - } - case 794: - case 793: { - unpackedSfixed64_.AddEntriesFrom(input, _repeated_unpackedSfixed64_codec); - break; - } - case 802: - case 805: { - unpackedFloat_.AddEntriesFrom(input, _repeated_unpackedFloat_codec); - break; - } - case 810: - case 809: { - unpackedDouble_.AddEntriesFrom(input, _repeated_unpackedDouble_codec); - break; - } - case 818: - case 816: { - unpackedBool_.AddEntriesFrom(input, _repeated_unpackedBool_codec); - break; - } - case 826: - case 824: { - unpackedEnum_.AddEntriesFrom(input, _repeated_unpackedEnum_codec); - break; - } - } - } - } - - } - - public sealed partial class TestRepeatedScalarDifferentTagSizes : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRepeatedScalarDifferentTagSizes()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[26]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestRepeatedScalarDifferentTagSizes() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestRepeatedScalarDifferentTagSizes(TestRepeatedScalarDifferentTagSizes other) : this() { - repeatedFixed32_ = other.repeatedFixed32_.Clone(); - repeatedInt32_ = other.repeatedInt32_.Clone(); - repeatedFixed64_ = other.repeatedFixed64_.Clone(); - repeatedInt64_ = other.repeatedInt64_.Clone(); - repeatedFloat_ = other.repeatedFloat_.Clone(); - repeatedUint64_ = other.repeatedUint64_.Clone(); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestRepeatedScalarDifferentTagSizes Clone() { - return new TestRepeatedScalarDifferentTagSizes(this); - } - - /// Field number for the "repeated_fixed32" field. - public const int RepeatedFixed32FieldNumber = 12; - private static readonly pb::FieldCodec _repeated_repeatedFixed32_codec - = pb::FieldCodec.ForFixed32(98); - private readonly pbc::RepeatedField repeatedFixed32_ = new pbc::RepeatedField(); - /// - /// Parsing repeated fixed size values used to fail. This message needs to be - /// used in order to get a tag of the right size; all of the repeated fields - /// in TestAllTypes didn't trigger the check. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedFixed32 { - get { return repeatedFixed32_; } - } - - /// Field number for the "repeated_int32" field. - public const int RepeatedInt32FieldNumber = 13; - private static readonly pb::FieldCodec _repeated_repeatedInt32_codec - = pb::FieldCodec.ForInt32(106); - private readonly pbc::RepeatedField repeatedInt32_ = new pbc::RepeatedField(); - /// - /// Check for a varint type, just for good measure. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedInt32 { - get { return repeatedInt32_; } - } - - /// Field number for the "repeated_fixed64" field. - public const int RepeatedFixed64FieldNumber = 2046; - private static readonly pb::FieldCodec _repeated_repeatedFixed64_codec - = pb::FieldCodec.ForFixed64(16370); - private readonly pbc::RepeatedField repeatedFixed64_ = new pbc::RepeatedField(); - /// - /// These have two-byte tags. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedFixed64 { - get { return repeatedFixed64_; } - } - - /// Field number for the "repeated_int64" field. - public const int RepeatedInt64FieldNumber = 2047; - private static readonly pb::FieldCodec _repeated_repeatedInt64_codec - = pb::FieldCodec.ForInt64(16378); - private readonly pbc::RepeatedField repeatedInt64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedInt64 { - get { return repeatedInt64_; } - } - - /// Field number for the "repeated_float" field. - public const int RepeatedFloatFieldNumber = 262142; - private static readonly pb::FieldCodec _repeated_repeatedFloat_codec - = pb::FieldCodec.ForFloat(2097138); - private readonly pbc::RepeatedField repeatedFloat_ = new pbc::RepeatedField(); - /// - /// Three byte tags. - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedFloat { - get { return repeatedFloat_; } - } - - /// Field number for the "repeated_uint64" field. - public const int RepeatedUint64FieldNumber = 262143; - private static readonly pb::FieldCodec _repeated_repeatedUint64_codec - = pb::FieldCodec.ForUInt64(2097146); - private readonly pbc::RepeatedField repeatedUint64_ = new pbc::RepeatedField(); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField RepeatedUint64 { - get { return repeatedUint64_; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestRepeatedScalarDifferentTagSizes); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestRepeatedScalarDifferentTagSizes other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false; - if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false; - if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false; - if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false; - if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false; - if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - hash ^= repeatedFixed32_.GetHashCode(); - hash ^= repeatedInt32_.GetHashCode(); - hash ^= repeatedFixed64_.GetHashCode(); - hash ^= repeatedInt64_.GetHashCode(); - hash ^= repeatedFloat_.GetHashCode(); - hash ^= repeatedUint64_.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec); - repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec); - repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec); - repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec); - repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec); - repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec); - size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec); - size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec); - size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec); - size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec); - size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec); - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestRepeatedScalarDifferentTagSizes other) { - if (other == null) { - return; - } - repeatedFixed32_.Add(other.repeatedFixed32_); - repeatedInt32_.Add(other.repeatedInt32_); - repeatedFixed64_.Add(other.repeatedFixed64_); - repeatedInt64_.Add(other.repeatedInt64_); - repeatedFloat_.Add(other.repeatedFloat_); - repeatedUint64_.Add(other.repeatedUint64_); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 98: - case 101: { - repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec); - break; - } - case 106: - case 104: { - repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); - break; - } - case 16370: - case 16369: { - repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec); - break; - } - case 16378: - case 16376: { - repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec); - break; - } - case 2097138: - case 2097141: { - repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec); - break; - } - case 2097146: - case 2097144: { - repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec); - break; - } - } - } - } - - } - - public sealed partial class TestCommentInjectionMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestCommentInjectionMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[27]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestCommentInjectionMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestCommentInjectionMessage(TestCommentInjectionMessage other) : this() { - a_ = other.a_; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public TestCommentInjectionMessage Clone() { - return new TestCommentInjectionMessage(this); - } - - /// Field number for the "a" field. - public const int AFieldNumber = 1; - private string a_ = ""; - /// - /// */ <- This should not close the generated doc comment - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string A { - get { return a_; } - set { - a_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestCommentInjectionMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestCommentInjectionMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (A != other.A) return false; - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (A.Length != 0) hash ^= A.GetHashCode(); - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - if (A.Length != 0) { - output.WriteRawTag(10); - output.WriteString(A); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (A.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(A); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(TestCommentInjectionMessage other) { - if (other == null) { - return; - } - if (other.A.Length != 0) { - A = other.A; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - case 10: { - A = input.ReadString(); - break; - } - } - } - } - - } - - /// - /// Test that RPC services work. - /// - public sealed partial class FooRequest : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooRequest()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[28]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public FooRequest() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public FooRequest(FooRequest other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public FooRequest Clone() { - return new FooRequest(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as FooRequest); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(FooRequest other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(FooRequest other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class FooResponse : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooResponse()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[29]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public FooResponse() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public FooResponse(FooResponse other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public FooResponse Clone() { - return new FooResponse(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as FooResponse); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(FooResponse other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(FooResponse other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class FooClientMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooClientMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[30]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public FooClientMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public FooClientMessage(FooClientMessage other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public FooClientMessage Clone() { - return new FooClientMessage(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as FooClientMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(FooClientMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(FooClientMessage other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class FooServerMessage : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooServerMessage()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[31]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public FooServerMessage() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public FooServerMessage(FooServerMessage other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public FooServerMessage Clone() { - return new FooServerMessage(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as FooServerMessage); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(FooServerMessage other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(FooServerMessage other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class BarRequest : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BarRequest()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[32]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public BarRequest() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public BarRequest(BarRequest other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public BarRequest Clone() { - return new BarRequest(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as BarRequest); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(BarRequest other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(BarRequest other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - public sealed partial class BarResponse : pb::IMessage { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BarResponse()); - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor.MessageTypes[33]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public BarResponse() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public BarResponse(BarResponse other) : this() { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public BarResponse Clone() { - return new BarResponse(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as BarResponse); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(BarResponse other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - return true; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(BarResponse other) { - if (other == null) { - return; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - input.SkipLastField(); - break; - } - } - } - - } - - #endregion - -} - -#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs b/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs new file mode 100644 index 0000000000000..15debc1b6c8e4 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs @@ -0,0 +1,206 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.IO; +using Google.Protobuf.TestProtos; +using Proto2 = Google.Protobuf.TestProtos.Proto2; +using NUnit.Framework; + +namespace Google.Protobuf +{ + public class UnknownFieldSetTest + { + public class Data + { + public static System.Collections.IEnumerable Messages + { + get + { + yield return SampleMessages.CreateFullTestAllTypesProto2(); + yield return SampleMessages.CreateFullTestAllTypes(); + } + } + } + + [Test] + public void EmptyUnknownFieldSet() + { + UnknownFieldSet unknownFields = new UnknownFieldSet(); + Assert.AreEqual(0, unknownFields.CalculateSize()); + } + + [Test] + public void MergeUnknownFieldSet() + { + UnknownFieldSet unknownFields = new UnknownFieldSet(); + UnknownField field = new UnknownField(); + field.AddFixed32(123); + unknownFields.AddOrReplaceField(1, field); + UnknownFieldSet otherUnknownFields = new UnknownFieldSet(); + Assert.IsFalse(otherUnknownFields.HasField(1)); + UnknownFieldSet.MergeFrom(otherUnknownFields, unknownFields); + Assert.IsTrue(otherUnknownFields.HasField(1)); + } + + [Test] + [TestCaseSource(typeof(Data), "Messages")] + public void TestMergeCodedInput(IMessage message) + { + var emptyMessage = new TestEmptyMessage(); + emptyMessage.MergeFrom(message.ToByteArray()); + Assert.AreEqual(message.CalculateSize(), emptyMessage.CalculateSize()); + Assert.AreEqual(message.ToByteArray(), emptyMessage.ToByteArray()); + + var newMessage = message.Descriptor.Parser.ParseFrom(emptyMessage.ToByteArray()); + Assert.AreEqual(message, newMessage); + Assert.AreEqual(message.CalculateSize(), newMessage.CalculateSize()); + } + + [Test] + [TestCaseSource(typeof(Data), "Messages")] + public void TestMergeMessage(IMessage message) + { + var emptyMessage = new TestEmptyMessage(); + var otherEmptyMessage = new TestEmptyMessage(); + emptyMessage.MergeFrom(message.ToByteArray()); + otherEmptyMessage.MergeFrom(emptyMessage); + + Assert.AreEqual(message.CalculateSize(), otherEmptyMessage.CalculateSize()); + Assert.AreEqual(message.ToByteArray(), otherEmptyMessage.ToByteArray()); + } + + [Test] + [TestCaseSource(typeof(Data), "Messages")] + public void TestEquals(IMessage message) + { + var emptyMessage = new TestEmptyMessage(); + var otherEmptyMessage = new TestEmptyMessage(); + Assert.AreEqual(emptyMessage, otherEmptyMessage); + emptyMessage.MergeFrom(message.ToByteArray()); + Assert.AreNotEqual(emptyMessage.CalculateSize(), + otherEmptyMessage.CalculateSize()); + Assert.AreNotEqual(emptyMessage, otherEmptyMessage); + } + + [Test] + [TestCaseSource(typeof(Data), "Messages")] + public void TestHashCode(IMessage message) + { + var emptyMessage = new TestEmptyMessage(); + int hashCode = emptyMessage.GetHashCode(); + emptyMessage.MergeFrom(message.ToByteArray()); + Assert.AreNotEqual(hashCode, emptyMessage.GetHashCode()); + } + + [Test] + [TestCaseSource(typeof(Data), "Messages")] + public void TestClone(IMessage message) + { + var emptyMessage = new TestEmptyMessage(); + var otherEmptyMessage = new TestEmptyMessage(); + otherEmptyMessage = emptyMessage.Clone(); + Assert.AreEqual(emptyMessage.CalculateSize(), otherEmptyMessage.CalculateSize()); + Assert.AreEqual(emptyMessage.ToByteArray(), otherEmptyMessage.ToByteArray()); + + emptyMessage.MergeFrom(message.ToByteArray()); + otherEmptyMessage = emptyMessage.Clone(); + Assert.AreEqual(message.CalculateSize(), otherEmptyMessage.CalculateSize()); + Assert.AreEqual(message.ToByteArray(), otherEmptyMessage.ToByteArray()); + } + + [Test] + [TestCaseSource(typeof(Data), "Messages")] + public void TestDiscardUnknownFields(IMessage message) + { + var goldenEmptyMessage = new TestEmptyMessage(); + byte[] data = message.ToByteArray(); + int fullSize = message.CalculateSize(); + + Action assertEmpty = msg => + { + Assert.AreEqual(0, msg.CalculateSize()); + Assert.AreEqual(goldenEmptyMessage, msg); + }; + + Action assertFull = msg => Assert.AreEqual(fullSize, msg.CalculateSize()); + + // Test the behavior of the parsers with and without discarding, both generic and non-generic. + MessageParser retainingParser1 = TestEmptyMessage.Parser; + MessageParser retainingParser2 = retainingParser1; + MessageParser discardingParser1 = retainingParser1.WithDiscardUnknownFields(true); + MessageParser discardingParser2 = retainingParser2.WithDiscardUnknownFields(true); + + // Test parse from byte[] + MessageParsingHelpers.AssertReadingMessage(retainingParser1, data, m => assertFull(m)); + MessageParsingHelpers.AssertReadingMessage(retainingParser2, data, m => assertFull(m)); + MessageParsingHelpers.AssertReadingMessage(discardingParser1, data, m => assertEmpty(m)); + MessageParsingHelpers.AssertReadingMessage(discardingParser2, data, m => assertEmpty(m)); + + // Test parse from byte[] with offset + assertFull(retainingParser1.ParseFrom(data, 0, data.Length)); + assertFull(retainingParser2.ParseFrom(data, 0, data.Length)); + assertEmpty(discardingParser1.ParseFrom(data, 0, data.Length)); + assertEmpty(discardingParser2.ParseFrom(data, 0, data.Length)); + + // Test parse from CodedInputStream + assertFull(retainingParser1.ParseFrom(new CodedInputStream(data))); + assertFull(retainingParser2.ParseFrom(new CodedInputStream(data))); + assertEmpty(discardingParser1.ParseFrom(new CodedInputStream(data))); + assertEmpty(discardingParser2.ParseFrom(new CodedInputStream(data))); + + // Test parse from Stream + assertFull(retainingParser1.ParseFrom(new MemoryStream(data))); + assertFull(retainingParser2.ParseFrom(new MemoryStream(data))); + assertEmpty(discardingParser1.ParseFrom(new MemoryStream(data))); + assertEmpty(discardingParser2.ParseFrom(new MemoryStream(data))); + } + + [Test] + public void TestReadInvalidWireTypeThrowsInvalidProtocolBufferException() + { + MemoryStream ms = new MemoryStream(); + CodedOutputStream output = new CodedOutputStream(ms); + + uint tag = WireFormat.MakeTag(1, (WireFormat.WireType)6); + output.WriteRawVarint32(tag); + output.WriteLength(-1); + output.Flush(); + ms.Position = 0; + + CodedInputStream input = new CodedInputStream(ms); + Assert.AreEqual(tag, input.ReadTag()); + + Assert.Throws(() => UnknownFieldSet.MergeFieldFrom(null, input)); + } + } +} diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs index a3edd5950cecf..4b9a56939540d 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs @@ -42,7 +42,7 @@ public void Pack() { var message = SampleMessages.CreateFullTestAllTypes(); var any = Any.Pack(message); - Assert.AreEqual("type.googleapis.com/protobuf_unittest.TestAllTypes", any.TypeUrl); + Assert.AreEqual("type.googleapis.com/protobuf_unittest3.TestAllTypes", any.TypeUrl); Assert.AreEqual(message.CalculateSize(), any.Value.Length); } @@ -51,7 +51,7 @@ public void Pack_WithCustomPrefix() { var message = SampleMessages.CreateFullTestAllTypes(); var any = Any.Pack(message, "foo.bar/baz"); - Assert.AreEqual("foo.bar/baz/protobuf_unittest.TestAllTypes", any.TypeUrl); + Assert.AreEqual("foo.bar/baz/protobuf_unittest3.TestAllTypes", any.TypeUrl); Assert.AreEqual(message.CalculateSize(), any.Value.Length); } @@ -60,7 +60,7 @@ public void Pack_WithCustomPrefixTrailingSlash() { var message = SampleMessages.CreateFullTestAllTypes(); var any = Any.Pack(message, "foo.bar/baz/"); - Assert.AreEqual("foo.bar/baz/protobuf_unittest.TestAllTypes", any.TypeUrl); + Assert.AreEqual("foo.bar/baz/protobuf_unittest3.TestAllTypes", any.TypeUrl); Assert.AreEqual(message.CalculateSize(), any.Value.Length); } @@ -140,5 +140,18 @@ public void ToString_MessageContainingAny() var message = new TestWellKnownTypes { AnyField = new Any() }; Assert.AreEqual("{ \"anyField\": { \"@type\": \"\", \"@value\": \"\" } }", message.ToString()); } + + [Test] + public void IsWrongType() + { + var any = Any.Pack(SampleMessages.CreateFullTestAllTypes()); + Assert.False(any.Is(TestOneof.Descriptor)); + } + + public void IsRightType() + { + var any = Any.Pack(SampleMessages.CreateFullTestAllTypes()); + Assert.True(any.Is(TestAllTypes.Descriptor)); + } } } diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs index 1d9908b4d314b..5dc5035703eb0 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs @@ -30,7 +30,8 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion - +using System; +using Google.Protobuf.TestProtos; using NUnit.Framework; namespace Google.Protobuf.WellKnownTypes @@ -58,5 +59,187 @@ public void ToString_Invalid_Precise() "{ \"@warning\": \"Invalid FieldMask\", \"paths\": [ \"x\", \"foo__bar\", \"x\\\\y\" ] }", mask.ToString()); } + + [Test] + public void IsValid() + { + Assert.IsTrue(FieldMask.IsValid("payload")); + Assert.IsFalse(FieldMask.IsValid("nonexist")); + Assert.IsTrue(FieldMask.IsValid("payload.single_int32")); + Assert.IsTrue(FieldMask.IsValid("payload.repeated_int32")); + Assert.IsTrue(FieldMask.IsValid("payload.single_nested_message")); + Assert.IsTrue(FieldMask.IsValid("payload.repeated_nested_message")); + Assert.IsFalse(FieldMask.IsValid("payload.nonexist")); + + Assert.IsTrue(FieldMask.IsValid(FieldMask.FromString("payload"))); + Assert.IsFalse(FieldMask.IsValid(FieldMask.FromString("nonexist"))); + Assert.IsFalse(FieldMask.IsValid(FieldMask.FromString("payload,nonexist"))); + + Assert.IsTrue(FieldMask.IsValid(NestedTestAllTypes.Descriptor, "payload")); + Assert.IsFalse(FieldMask.IsValid(NestedTestAllTypes.Descriptor, "nonexist")); + + Assert.IsTrue(FieldMask.IsValid(NestedTestAllTypes.Descriptor, FieldMask.FromString("payload"))); + Assert.IsFalse(FieldMask.IsValid(NestedTestAllTypes.Descriptor, FieldMask.FromString("nonexist"))); + + Assert.IsTrue(FieldMask.IsValid("payload.single_nested_message.bb")); + + // Repeated fields cannot have sub-paths. + Assert.IsFalse(FieldMask.IsValid("payload.repeated_nested_message.bb")); + + // Non-message fields cannot have sub-paths. + Assert.IsFalse(FieldMask.IsValid("payload.single_int32.bb")); + } + + [Test] + [TestCase(new string[] { }, "\"\"")] + [TestCase(new string[] { "foo" }, "\"foo\"")] + [TestCase(new string[] { "foo", "bar" }, "\"foo,bar\"")] + [TestCase(new string[] { "", "foo", "", "bar", "" }, "\",foo,,bar,\"")] + public void ToString(string[] input, string expectedOutput) + { + FieldMask mask = new FieldMask(); + mask.Paths.AddRange(input); + Assert.AreEqual(expectedOutput, mask.ToString()); + } + + [Test] + [TestCase("", new string[] { })] + [TestCase("foo", new string[] { "foo" })] + [TestCase("foo,bar.baz", new string[] { "foo", "bar.baz" })] + [TestCase(",foo,,bar,", new string[] { "foo", "bar" })] + public void FromString(string input, string[] expectedOutput) + { + FieldMask mask = FieldMask.FromString(input); + Assert.AreEqual(expectedOutput.Length, mask.Paths.Count); + for (int i = 0; i < expectedOutput.Length; i++) + { + Assert.AreEqual(expectedOutput[i], mask.Paths[i]); + } + } + + [Test] + public void FromString_Validated() + { + // Check whether the field paths are valid if a class parameter is provided. + Assert.DoesNotThrow(() => FieldMask.FromString(",payload")); + Assert.Throws(() => FieldMask.FromString("payload,nonexist")); + } + + [Test] + [TestCase(new int[] { }, new string[] { })] + [TestCase(new int[] { TestAllTypes.SingleInt32FieldNumber }, new string[] { "single_int32" })] + [TestCase(new int[] { TestAllTypes.SingleInt32FieldNumber, TestAllTypes.SingleInt64FieldNumber }, new string[] { "single_int32", "single_int64" })] + public void FromFieldNumbers(int[] input, string[] expectedOutput) + { + FieldMask mask = FieldMask.FromFieldNumbers(input); + Assert.AreEqual(expectedOutput.Length, mask.Paths.Count); + for (int i = 0; i < expectedOutput.Length; i++) + { + Assert.AreEqual(expectedOutput[i], mask.Paths[i]); + } + } + + [Test] + public void FromFieldNumbers_Invalid() + { + Assert.Throws(() => + { + int invalidFieldNumber = 1000; + FieldMask.FromFieldNumbers(invalidFieldNumber); + }); + } + + [Test] + [TestCase(new string[] { }, "\"\"")] + [TestCase(new string[] { "foo" }, "\"foo\"")] + [TestCase(new string[] { "foo", "bar" }, "\"foo,bar\"")] + [TestCase(new string[] { "", "foo", "", "bar", "" }, "\",foo,bar\"")] + public void Normalize(string[] input, string expectedOutput) + { + FieldMask mask = new FieldMask(); + mask.Paths.AddRange(input); + FieldMask result = mask.Normalize(); + Assert.AreEqual(expectedOutput, result.ToString()); + } + + [Test] + public void Union() + { + // Only test a simple case here and expect + // {@link FieldMaskTreeTest#AddFieldPath} to cover all scenarios. + FieldMask mask1 = FieldMask.FromString("foo,bar.baz,bar.quz"); + FieldMask mask2 = FieldMask.FromString("foo.bar,bar"); + FieldMask result = mask1.Union(mask2); + Assert.AreEqual(2, result.Paths.Count); + Assert.Contains("bar", result.Paths); + Assert.Contains("foo", result.Paths); + Assert.That(result.Paths, Has.No.Member("bar.baz")); + Assert.That(result.Paths, Has.No.Member("bar.quz")); + Assert.That(result.Paths, Has.No.Member("foo.bar")); + } + + [Test] + public void Union_UsingVarArgs() + { + FieldMask mask1 = FieldMask.FromString("foo"); + FieldMask mask2 = FieldMask.FromString("foo.bar,bar.quz"); + FieldMask mask3 = FieldMask.FromString("bar.quz"); + FieldMask mask4 = FieldMask.FromString("bar"); + FieldMask result = mask1.Union(mask2, mask3, mask4); + Assert.AreEqual(2, result.Paths.Count); + Assert.Contains("bar", result.Paths); + Assert.Contains("foo", result.Paths); + Assert.That(result.Paths, Has.No.Member("foo.bar")); + Assert.That(result.Paths, Has.No.Member("bar.quz")); + } + + [Test] + public void Intersection() + { + // Only test a simple case here and expect + // {@link FieldMaskTreeTest#IntersectFieldPath} to cover all scenarios. + FieldMask mask1 = FieldMask.FromString("foo,bar.baz,bar.quz"); + FieldMask mask2 = FieldMask.FromString("foo.bar,bar"); + FieldMask result = mask1.Intersection(mask2); + Assert.AreEqual(3, result.Paths.Count); + Assert.Contains("foo.bar", result.Paths); + Assert.Contains("bar.baz", result.Paths); + Assert.Contains("bar.quz", result.Paths); + Assert.That(result.Paths, Has.No.Member("foo")); + Assert.That(result.Paths, Has.No.Member("bar")); + } + + [Test] + public void Merge() + { + // Only test a simple case here and expect + // {@link FieldMaskTreeTest#Merge} to cover all scenarios. + FieldMask fieldMask = FieldMask.FromString("payload"); + NestedTestAllTypes source = new NestedTestAllTypes + { + Payload = new TestAllTypes + { + SingleInt32 = 1234, + SingleFixed64 = 4321 + } + }; + NestedTestAllTypes destination = new NestedTestAllTypes(); + fieldMask.Merge(source, destination); + Assert.AreEqual(1234, destination.Payload.SingleInt32); + Assert.AreEqual(4321, destination.Payload.SingleFixed64); + + destination = new NestedTestAllTypes + { + Payload = new TestAllTypes + { + SingleInt32 = 4321, + SingleInt64 = 5678 + } + }; + fieldMask.Merge(source, destination); + Assert.AreEqual(1234, destination.Payload.SingleInt32); + Assert.AreEqual(5678, destination.Payload.SingleInt64); + Assert.AreEqual(4321, destination.Payload.SingleFixed64); + } } } diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs index 9ecd24c62a5b6..ffc60419242d7 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs @@ -99,7 +99,7 @@ public void Arithmetic() Duration difference = new Duration { Seconds = 1999, Nanos = Duration.NanosecondsPerSecond - 5000 }; Assert.AreEqual(difference, t1 - t2); Assert.AreEqual(-difference, t2 - t1); - + Assert.AreEqual(t1, t2 + difference); Assert.AreEqual(t2, t1 - difference); } @@ -111,5 +111,106 @@ public void ToString_NonNormalized() var duration = new Timestamp { Seconds = 1, Nanos = -1 }; Assert.AreEqual("{ \"@warning\": \"Invalid Timestamp\", \"seconds\": \"1\", \"nanos\": -1 }", duration.ToString()); } + + [Test] + public void Comparability() + { + Timestamp + a = null, + b = new Timestamp { Seconds = 1, Nanos = 1 }, + c = new Timestamp { Seconds = 1, Nanos = 10 }, + d = new Timestamp { Seconds = 10, Nanos = 1 }, + e = new Timestamp { Seconds = 10, Nanos = 10 }; + + Assert.IsTrue(b.CompareTo(a) > 0); // null is always first (according to default behavior of Array.Sort) + Assert.IsTrue(b.CompareTo(b) == 0); + Assert.IsTrue(b.CompareTo(b.Clone()) == 0); + Assert.IsTrue(b.CompareTo(c) < 0); + Assert.IsTrue(b.CompareTo(d) < 0); + Assert.IsTrue(b.CompareTo(e) < 0); + + Assert.IsTrue(c.CompareTo(a) > 0); + Assert.IsTrue(c.CompareTo(b) > 0); + Assert.IsTrue(c.CompareTo(c) == 0); + Assert.IsTrue(c.CompareTo(c.Clone()) == 0); + Assert.IsTrue(c.CompareTo(d) < 0); + Assert.IsTrue(c.CompareTo(e) < 0); + + Assert.IsTrue(d.CompareTo(a) > 0); + Assert.IsTrue(d.CompareTo(b) > 0); + Assert.IsTrue(d.CompareTo(c) > 0); + Assert.IsTrue(d.CompareTo(d) == 0); + Assert.IsTrue(d.CompareTo(d.Clone()) == 0); + Assert.IsTrue(d.CompareTo(e) < 0); + + Assert.IsTrue(e.CompareTo(a) > 0); + Assert.IsTrue(e.CompareTo(b) > 0); + Assert.IsTrue(e.CompareTo(c) > 0); + Assert.IsTrue(e.CompareTo(d) > 0); + Assert.IsTrue(e.CompareTo(e) == 0); + Assert.IsTrue(e.CompareTo(e.Clone()) == 0); + } + + + [Test] + public void ComparabilityOperators() + { + Timestamp + a = null, + b = new Timestamp { Seconds = 1, Nanos = 1 }, + c = new Timestamp { Seconds = 1, Nanos = 10 }, + d = new Timestamp { Seconds = 10, Nanos = 1 }, + e = new Timestamp { Seconds = 10, Nanos = 10 }; + +#pragma warning disable CS1718 // Comparison made to same variable + Assert.IsTrue(b > a); + Assert.IsTrue(b == b); + Assert.IsTrue(b == b.Clone()); + Assert.IsTrue(b < c); + Assert.IsTrue(b < d); + Assert.IsTrue(b < e); + + Assert.IsTrue(c > a); + Assert.IsTrue(c > b); + Assert.IsTrue(c == c); + Assert.IsTrue(c == c.Clone()); + Assert.IsTrue(c < d); + Assert.IsTrue(c < e); + + Assert.IsTrue(d > a); + Assert.IsTrue(d > b); + Assert.IsTrue(d > c); + Assert.IsTrue(d == d); + Assert.IsTrue(d == d.Clone()); + Assert.IsTrue(d < e); + + Assert.IsTrue(e > a); + Assert.IsTrue(e > b); + Assert.IsTrue(e > c); + Assert.IsTrue(e > d); + Assert.IsTrue(e == e); + Assert.IsTrue(e == e.Clone()); + + Assert.IsTrue(b >= a); + Assert.IsTrue(b <= c); + Assert.IsTrue(b <= d); + Assert.IsTrue(b <= e); + + Assert.IsTrue(c >= a); + Assert.IsTrue(c >= b); + Assert.IsTrue(c <= d); + Assert.IsTrue(c <= e); + + Assert.IsTrue(d >= a); + Assert.IsTrue(d >= b); + Assert.IsTrue(d >= c); + Assert.IsTrue(d <= e); + + Assert.IsTrue(e >= a); + Assert.IsTrue(e >= b); + Assert.IsTrue(e >= c); + Assert.IsTrue(e >= d); +#pragma warning restore CS1718 // Comparison made to same variable + } } } diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs index 5b7185dcd2dba..5b0e5e8fc1cb2 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs @@ -71,18 +71,42 @@ public void NonDefaultSingleValues() Uint64Field = 4 }; - var bytes = message.ToByteArray(); - var parsed = TestWellKnownTypes.Parser.ParseFrom(bytes); - - Assert.AreEqual("x", parsed.StringField); - Assert.AreEqual(ByteString.CopyFrom(1, 2, 3), parsed.BytesField); - Assert.AreEqual(true, parsed.BoolField); - Assert.AreEqual(12.5f, parsed.FloatField); - Assert.AreEqual(12.25d, parsed.DoubleField); - Assert.AreEqual(1, parsed.Int32Field); - Assert.AreEqual(2L, parsed.Int64Field); - Assert.AreEqual(3U, parsed.Uint32Field); - Assert.AreEqual(4UL, parsed.Uint64Field); + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertRoundtrip(TestWellKnownTypes.Parser, message, parsed => + { + Assert.AreEqual("x", parsed.StringField); + Assert.AreEqual(ByteString.CopyFrom(1, 2, 3), parsed.BytesField); + Assert.AreEqual(true, parsed.BoolField); + Assert.AreEqual(12.5f, parsed.FloatField); + Assert.AreEqual(12.25d, parsed.DoubleField); + Assert.AreEqual(1, parsed.Int32Field); + Assert.AreEqual(2L, parsed.Int64Field); + Assert.AreEqual(3U, parsed.Uint32Field); + Assert.AreEqual(4UL, parsed.Uint64Field); + }); + } + + [Test] + public void NegativeSingleValues() + { + var message = new TestWellKnownTypes + { + FloatField = -12.5f, + DoubleField = -12.25d, + Int32Field = -1, + Int64Field = -2 + }; + + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertRoundtrip(TestWellKnownTypes.Parser, message, parsed => + { + Assert.AreEqual(-12.5f, parsed.FloatField); + Assert.AreEqual(-12.25d, parsed.DoubleField); + Assert.AreEqual(-1, parsed.Int32Field); + Assert.AreEqual(-2L, parsed.Int64Field); + }); } [Test] @@ -101,18 +125,20 @@ public void NonNullDefaultIsPreservedThroughSerialization() Uint64Field = 0 }; - var bytes = message.ToByteArray(); - var parsed = TestWellKnownTypes.Parser.ParseFrom(bytes); - - Assert.AreEqual("", parsed.StringField); - Assert.AreEqual(ByteString.Empty, parsed.BytesField); - Assert.AreEqual(false, parsed.BoolField); - Assert.AreEqual(0f, parsed.FloatField); - Assert.AreEqual(0d, parsed.DoubleField); - Assert.AreEqual(0, parsed.Int32Field); - Assert.AreEqual(0L, parsed.Int64Field); - Assert.AreEqual(0U, parsed.Uint32Field); - Assert.AreEqual(0UL, parsed.Uint64Field); + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertRoundtrip(TestWellKnownTypes.Parser, message, parsed => + { + Assert.AreEqual("", parsed.StringField); + Assert.AreEqual(ByteString.Empty, parsed.BytesField); + Assert.AreEqual(false, parsed.BoolField); + Assert.AreEqual(0f, parsed.FloatField); + Assert.AreEqual(0d, parsed.DoubleField); + Assert.AreEqual(0, parsed.Int32Field); + Assert.AreEqual(0L, parsed.Int64Field); + Assert.AreEqual(0U, parsed.Uint32Field); + Assert.AreEqual(0UL, parsed.Uint64Field); + }); } [Test] @@ -135,17 +161,18 @@ public void RepeatedWrappersSerializeDeserialize() DoubleField = { 12.5, -1.5, 0d }, FloatField = { 123.25f, -20f, 0f }, Int32Field = { int.MaxValue, int.MinValue, 0 }, - Int64Field = { long.MaxValue, long.MinValue, 0L }, + Int64Field = { long.MaxValue, long.MinValue, 0L }, StringField = { "First", "Second", "" }, Uint32Field = { uint.MaxValue, uint.MinValue, 0U }, Uint64Field = { ulong.MaxValue, ulong.MinValue, 0UL }, }; - var bytes = message.ToByteArray(); - var parsed = RepeatedWellKnownTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, parsed); // Just to test a single value for sanity... Assert.AreEqual("Second", message.StringField[1]); + + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertRoundtrip(RepeatedWellKnownTypes.Parser, message); } [Test] @@ -170,6 +197,8 @@ public void RepeatedWrappersBinaryFormat() var message = new RepeatedWellKnownTypes { Int32Field = { 5, 0 } }; var actualBytes = message.ToByteArray(); Assert.AreEqual(expectedBytes, actualBytes); + + MessageParsingHelpers.AssertWritingMessage(message); } [Test] @@ -194,12 +223,12 @@ public void MapWrappersSerializeDeserialize() Uint64Field = { { 18, ulong.MaxValue }, { 19, ulong.MinValue }, { 20, 0UL } }, }; - var bytes = message.ToByteArray(); - var parsed = MapWellKnownTypes.Parser.ParseFrom(bytes); - - Assert.AreEqual(message, parsed); // Just to test a single value for sanity... Assert.AreEqual("Second", message.StringField[12]); + + MessageParsingHelpers.AssertWritingMessage(message); + + MessageParsingHelpers.AssertRoundtrip(MapWellKnownTypes.Parser, message); } [Test] @@ -288,10 +317,10 @@ public void Oneof() private void AssertOneofRoundTrip(OneofWellKnownTypes message) { // Normal roundtrip, but explicitly checking the case... - var bytes = message.ToByteArray(); - var parsed = OneofWellKnownTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, parsed); - Assert.AreEqual(message.OneofFieldCase, parsed.OneofFieldCase); + MessageParsingHelpers.AssertRoundtrip(OneofWellKnownTypes.Parser, message, parsed => + { + Assert.AreEqual(message.OneofFieldCase, parsed.OneofFieldCase); + }); } [Test] @@ -386,7 +415,7 @@ public void MergingMessageWithZero(int? originValue, int? mergingValue, int? exp } [Test] - public void UnknownFieldInWrapper() + public void UnknownFieldInWrapperInt32FastPath() { var stream = new MemoryStream(); var output = new CodedOutputStream(stream); @@ -395,17 +424,102 @@ public void UnknownFieldInWrapper() var valueTag = WireFormat.MakeTag(Int32Value.ValueFieldNumber, WireFormat.WireType.Varint); output.WriteTag(wrapperTag); - output.WriteLength(4); // unknownTag + value 5 + valueType + value 6, each 1 byte + // Wrapper message is just long enough - 6 bytes - to use the wrapper fast-path. + output.WriteLength(6); // unknownTag + value 5 + valueType, each 1 byte, + value 65536, 3 bytes output.WriteTag(unknownTag); output.WriteInt32((int) valueTag); // Sneakily "pretend" it's a tag when it's really a value output.WriteTag(valueTag); + output.WriteInt32(65536); + + output.Flush(); + Assert.AreEqual(8, stream.Length); // tag (1 byte) + length (1 byte) + message (6 bytes) + stream.Position = 0; + + MessageParsingHelpers.AssertReadingMessage( + TestWellKnownTypes.Parser, + stream.ToArray(), + message => Assert.AreEqual(65536, message.Int32Field)); + } + + [Test] + public void UnknownFieldInWrapperInt32SlowPath() + { + var stream = new MemoryStream(); + var output = new CodedOutputStream(stream); + var wrapperTag = WireFormat.MakeTag(TestWellKnownTypes.Int32FieldFieldNumber, WireFormat.WireType.LengthDelimited); + var unknownTag = WireFormat.MakeTag(15, WireFormat.WireType.Varint); + var valueTag = WireFormat.MakeTag(Int32Value.ValueFieldNumber, WireFormat.WireType.Varint); + + output.WriteTag(wrapperTag); + // Wrapper message is too short to be used on the wrapper fast-path. + output.WriteLength(4); // unknownTag + value 5 + valueType + value 6, each 1 byte + output.WriteTag(unknownTag); + output.WriteInt32((int)valueTag); // Sneakily "pretend" it's a tag when it's really a value + output.WriteTag(valueTag); output.WriteInt32(6); output.Flush(); + Assert.Less(stream.Length, 8); // tag (1 byte) + length (1 byte) + message stream.Position = 0; - - var message = TestWellKnownTypes.Parser.ParseFrom(stream); - Assert.AreEqual(6, message.Int32Field); + + MessageParsingHelpers.AssertReadingMessage( + TestWellKnownTypes.Parser, + stream.ToArray(), + message => Assert.AreEqual(6, message.Int32Field)); + } + + [Test] + public void UnknownFieldInWrapperInt64FastPath() + { + var stream = new MemoryStream(); + var output = new CodedOutputStream(stream); + var wrapperTag = WireFormat.MakeTag(TestWellKnownTypes.Int64FieldFieldNumber, WireFormat.WireType.LengthDelimited); + var unknownTag = WireFormat.MakeTag(15, WireFormat.WireType.Varint); + var valueTag = WireFormat.MakeTag(Int64Value.ValueFieldNumber, WireFormat.WireType.Varint); + + output.WriteTag(wrapperTag); + // Wrapper message is just long enough - 10 bytes - to use the wrapper fast-path. + output.WriteLength(11); // unknownTag + value 5 + valueType, each 1 byte, + value 0xfffffffffffff, 8 bytes + output.WriteTag(unknownTag); + output.WriteInt64((int)valueTag); // Sneakily "pretend" it's a tag when it's really a value + output.WriteTag(valueTag); + output.WriteInt64(0xfffffffffffffL); + + output.Flush(); + Assert.AreEqual(13, stream.Length); // tag (1 byte) + length (1 byte) + message (11 bytes) + stream.Position = 0; + + MessageParsingHelpers.AssertReadingMessage( + TestWellKnownTypes.Parser, + stream.ToArray(), + message => Assert.AreEqual(0xfffffffffffffL, message.Int64Field)); + } + + [Test] + public void UnknownFieldInWrapperInt64SlowPath() + { + var stream = new MemoryStream(); + var output = new CodedOutputStream(stream); + var wrapperTag = WireFormat.MakeTag(TestWellKnownTypes.Int64FieldFieldNumber, WireFormat.WireType.LengthDelimited); + var unknownTag = WireFormat.MakeTag(15, WireFormat.WireType.Varint); + var valueTag = WireFormat.MakeTag(Int64Value.ValueFieldNumber, WireFormat.WireType.Varint); + + output.WriteTag(wrapperTag); + // Wrapper message is too short to be used on the wrapper fast-path. + output.WriteLength(4); // unknownTag + value 5 + valueType + value 6, each 1 byte + output.WriteTag(unknownTag); + output.WriteInt64((int)valueTag); // Sneakily "pretend" it's a tag when it's really a value + output.WriteTag(valueTag); + output.WriteInt64(6); + + output.Flush(); + Assert.Less(stream.Length, 12); // tag (1 byte) + length (1 byte) + message + stream.Position = 0; + + MessageParsingHelpers.AssertReadingMessage( + TestWellKnownTypes.Parser, + stream.ToArray(), + message => Assert.AreEqual(6L, message.Int64Field)); } [Test] @@ -417,5 +531,16 @@ public void ClearWithReflection() TestWellKnownTypes.Descriptor.Fields[TestWellKnownTypes.StringFieldFieldNumber].Accessor.Clear(message); Assert.IsNull(message.StringField); } + + [Test] + public void NaNComparisons() + { + var message1 = new TestWellKnownTypes { DoubleField = SampleNaNs.Regular }; + var message2 = new TestWellKnownTypes { DoubleField = SampleNaNs.PayloadFlipped }; + var message3 = new TestWellKnownTypes { DoubleField = SampleNaNs.Regular }; + + EqualityTester.AssertInequality(message1, message2); + EqualityTester.AssertEquality(message1, message3); + } } } diff --git a/csharp/src/Google.Protobuf.Test/testprotos.pb b/csharp/src/Google.Protobuf.Test/testprotos.pb new file mode 100644 index 0000000000000..1569c1e8c81ab Binary files /dev/null and b/csharp/src/Google.Protobuf.Test/testprotos.pb differ diff --git a/csharp/src/Google.Protobuf.sln b/csharp/src/Google.Protobuf.sln index 443ee3e93e49d..b571e53c12eb1 100644 --- a/csharp/src/Google.Protobuf.sln +++ b/csharp/src/Google.Protobuf.sln @@ -1,16 +1,20 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 +Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26114.2 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddressBook", "AddressBook\AddressBook.csproj", "{AFB63919-1E05-43B4-802A-8FB8C9B2F463}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AddressBook", "AddressBook\AddressBook.csproj", "{AFB63919-1E05-43B4-802A-8FB8C9B2F463}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf", "Google.Protobuf\Google.Protobuf.csproj", "{9B576380-726D-4142-8238-60A43AB0E35A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Protobuf", "Google.Protobuf\Google.Protobuf.csproj", "{9B576380-726D-4142-8238-60A43AB0E35A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.Test", "Google.Protobuf.Test\Google.Protobuf.Test.csproj", "{580EB013-D3C7-4578-B845-015F4A3B0591}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Protobuf.Test", "Google.Protobuf.Test\Google.Protobuf.Test.csproj", "{580EB013-D3C7-4578-B845-015F4A3B0591}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.Conformance", "Google.Protobuf.Conformance\Google.Protobuf.Conformance.csproj", "{DDDC055B-E185-4181-BAB0-072F0F984569}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Protobuf.Conformance", "Google.Protobuf.Conformance\Google.Protobuf.Conformance.csproj", "{DDDC055B-E185-4181-BAB0-072F0F984569}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.JsonDump", "Google.Protobuf.JsonDump\Google.Protobuf.JsonDump.csproj", "{9695E08F-9829-497D-B95C-B38F28D48690}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Protobuf.JsonDump", "Google.Protobuf.JsonDump\Google.Protobuf.JsonDump.csproj", "{9695E08F-9829-497D-B95C-B38F28D48690}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.Benchmarks", "Google.Protobuf.Benchmarks\Google.Protobuf.Benchmarks.csproj", "{D25E4804-4DEA-45AB-9F8C-BA4DBD8E5A07}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.Test.TestProtos", "Google.Protobuf.Test.TestProtos\Google.Protobuf.Test.TestProtos.csproj", "{ADF24BEB-A318-4530-8448-356B72B820EA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -38,8 +42,19 @@ Global {9695E08F-9829-497D-B95C-B38F28D48690}.Debug|Any CPU.Build.0 = Debug|Any CPU {9695E08F-9829-497D-B95C-B38F28D48690}.Release|Any CPU.ActiveCfg = Release|Any CPU {9695E08F-9829-497D-B95C-B38F28D48690}.Release|Any CPU.Build.0 = Release|Any CPU + {D25E4804-4DEA-45AB-9F8C-BA4DBD8E5A07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D25E4804-4DEA-45AB-9F8C-BA4DBD8E5A07}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D25E4804-4DEA-45AB-9F8C-BA4DBD8E5A07}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D25E4804-4DEA-45AB-9F8C-BA4DBD8E5A07}.Release|Any CPU.Build.0 = Release|Any CPU + {ADF24BEB-A318-4530-8448-356B72B820EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ADF24BEB-A318-4530-8448-356B72B820EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ADF24BEB-A318-4530-8448-356B72B820EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ADF24BEB-A318-4530-8448-356B72B820EA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7B06C87B-83E1-4F5F-A0DD-6E9AFAC03DAC} + EndGlobalSection EndGlobal diff --git a/csharp/src/Google.Protobuf/ByteString.cs b/csharp/src/Google.Protobuf/ByteString.cs old mode 100755 new mode 100644 index 4abdb7182c5ab..7828658672fe3 --- a/csharp/src/Google.Protobuf/ByteString.cs +++ b/csharp/src/Google.Protobuf/ByteString.cs @@ -34,6 +34,8 @@ using System.Collections; using System.Collections.Generic; using System.IO; +using System.Runtime.InteropServices; +using System.Security; using System.Text; #if !NET35 using System.Threading; @@ -48,49 +50,36 @@ namespace Google.Protobuf /// /// Immutable array of bytes. /// + [SecuritySafeCritical] public sealed class ByteString : IEnumerable, IEquatable { private static readonly ByteString empty = new ByteString(new byte[0]); - private readonly byte[] bytes; + private readonly ReadOnlyMemory bytes; /// - /// Unsafe operations that can cause IO Failure and/or other catestrophic side-effects. + /// Internal use only. Ensure that the provided memory is not mutated and belongs to this instance. /// - internal static class Unsafe + internal static ByteString AttachBytes(ReadOnlyMemory bytes) { - /// - /// Constructs a new ByteString from the given byte array. The array is - /// *not* copied, and must not be modified after this constructor is called. - /// - internal static ByteString FromBytes(byte[] bytes) - { - return new ByteString(bytes); - } - - /// - /// Provides direct, unrestricted access to the bytes contained in this instance. - /// You must not modify or resize the byte array returned by this method. - /// - internal static byte[] GetBuffer(ByteString bytes) - { - return bytes.bytes; - } + return new ByteString(bytes); } /// - /// Internal use only. Ensure that the provided array is not mutated and belongs to this instance. + /// Internal use only. Ensure that the provided memory is not mutated and belongs to this instance. + /// This method encapsulates converting array to memory. Reduces need for SecuritySafeCritical + /// in .NET Framework. /// internal static ByteString AttachBytes(byte[] bytes) { - return new ByteString(bytes); + return AttachBytes(bytes.AsMemory()); } /// - /// Constructs a new ByteString from the given byte array. The array is + /// Constructs a new ByteString from the given memory. The memory is /// *not* copied, and must not be modified after this constructor is called. /// - private ByteString(byte[] bytes) + private ByteString(ReadOnlyMemory bytes) { this.bytes = bytes; } @@ -119,6 +108,24 @@ public bool IsEmpty get { return Length == 0; } } + /// + /// Provides read-only access to the data of this . + /// No data is copied so this is the most efficient way of accessing. + /// + public ReadOnlySpan Span + { + get { return bytes.Span; } + } + + /// + /// Provides read-only access to the data of this . + /// No data is copied so this is the most efficient way of accessing. + /// + public ReadOnlyMemory Memory + { + get { return bytes; } + } + /// /// Converts this into a byte array. /// @@ -126,7 +133,7 @@ public bool IsEmpty /// A byte array with the same data as this ByteString. public byte[] ToByteArray() { - return (byte[]) bytes.Clone(); + return bytes.ToArray(); } /// @@ -135,7 +142,16 @@ public byte[] ToByteArray() /// A base64 representation of this ByteString. public string ToBase64() { - return Convert.ToBase64String(bytes); + if (MemoryMarshal.TryGetArray(bytes, out ArraySegment segment)) + { + // Fast path. ByteString was created with an array, so pass the underlying array. + return Convert.ToBase64String(segment.Array, segment.Offset, segment.Count); + } + else + { + // Slow path. BytesString is not an array. Convert memory and pass result to ToBase64String. + return Convert.ToBase64String(bytes.ToArray()); + } } /// @@ -161,7 +177,7 @@ public static ByteString FromStream(Stream stream) int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0; var memoryStream = new MemoryStream(capacity); stream.CopyTo(memoryStream); -#if NETSTANDARD1_0 +#if NETSTANDARD1_1 || NETSTANDARD2_0 byte[] bytes = memoryStream.ToArray(); #else // Avoid an extra copy if we can. @@ -179,21 +195,10 @@ public static ByteString FromStream(Stream stream) /// The stream to copy into a ByteString. /// The cancellation token to use when reading from the stream, if any. /// A ByteString with content read from the given stream. - public async static Task FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken)) + public static Task FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken)) { ProtoPreconditions.CheckNotNull(stream, nameof(stream)); - int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0; - var memoryStream = new MemoryStream(capacity); - // We have to specify the buffer size here, as there's no overload accepting the cancellation token - // alone. But it's documented to use 81920 by default if not specified. - await stream.CopyToAsync(memoryStream, 81920, cancellationToken); -#if NETSTANDARD1_0 - byte[] bytes = memoryStream.ToArray(); -#else - // Avoid an extra copy if we can. - byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray(); -#endif - return AttachBytes(bytes); + return ByteStringAsync.FromStreamAsyncCore(stream, cancellationToken); } #endif @@ -219,6 +224,16 @@ public static ByteString CopyFrom(byte[] bytes, int offset, int count) return new ByteString(portion); } + /// + /// Constructs a from a read only span. The contents + /// are copied, so further modifications to the span will not + /// be reflected in the returned . + /// + public static ByteString CopyFrom(ReadOnlySpan bytes) + { + return new ByteString(bytes.ToArray()); + } + /// /// Creates a new by encoding the specified text with /// the given encoding. @@ -237,11 +252,11 @@ public static ByteString CopyFromUtf8(string text) } /// - /// Retuns the byte at the given index. + /// Returns the byte at the given index. /// public byte this[int index] { - get { return bytes[index]; } + get { return bytes.Span[index]; } } /// @@ -255,7 +270,18 @@ public byte this[int index] /// The result of decoding the binary data with the given decoding. public string ToString(Encoding encoding) { - return encoding.GetString(bytes, 0, bytes.Length); + if (MemoryMarshal.TryGetArray(bytes, out ArraySegment segment)) + { + // Fast path. ByteString was created with an array. + return encoding.GetString(segment.Array, segment.Offset, segment.Count); + } + else + { + // Slow path. BytesString is not an array. Convert memory and pass result to GetString. + // TODO: Consider using GetString overload that takes a pointer. + byte[] array = bytes.ToArray(); + return encoding.GetString(array, 0, array.Length); + } } /// @@ -275,9 +301,10 @@ public string ToStringUtf8() /// Returns an iterator over the bytes in this . /// /// An iterator over the bytes in this object. + [SecuritySafeCritical] public IEnumerator GetEnumerator() { - return ((IEnumerable) bytes).GetEnumerator(); + return MemoryMarshal.ToEnumerable(bytes).GetEnumerator(); } /// @@ -295,7 +322,17 @@ IEnumerator IEnumerable.GetEnumerator() public CodedInputStream CreateCodedInput() { // We trust CodedInputStream not to reveal the provided byte array or modify it - return new CodedInputStream(bytes); + if (MemoryMarshal.TryGetArray(bytes, out ArraySegment segment) && segment.Count == bytes.Length) + { + // Fast path. ByteString was created with a complete array. + return new CodedInputStream(segment.Array); + } + else + { + // Slow path. BytesString is not an array, or is a slice of an array. + // Convert memory and pass result to WriteRawBytes. + return new CodedInputStream(bytes.ToArray()); + } } /// @@ -314,18 +351,8 @@ public CodedInputStream CreateCodedInput() { return false; } - if (lhs.bytes.Length != rhs.bytes.Length) - { - return false; - } - for (int i = 0; i < lhs.Length; i++) - { - if (rhs.bytes[i] != lhs.bytes[i]) - { - return false; - } - } - return true; + + return lhs.bytes.Span.SequenceEqual(rhs.bytes.Span); } /// @@ -344,6 +371,7 @@ public CodedInputStream CreateCodedInput() /// /// The object to compare this with. /// true if refers to an equal ; false otherwise. + [SecuritySafeCritical] public override bool Equals(object obj) { return this == (obj as ByteString); @@ -354,12 +382,15 @@ public override bool Equals(object obj) /// will return the same hash code. /// /// A hash code for this object. + [SecuritySafeCritical] public override int GetHashCode() { + ReadOnlySpan b = bytes.Span; + int ret = 23; - foreach (byte b in bytes) + for (int i = 0; i < b.Length; i++) { - ret = (ret * 31) + b; + ret = (ret * 31) + b[i]; } return ret; } @@ -374,20 +405,12 @@ public bool Equals(ByteString other) return this == other; } - /// - /// Used internally by CodedOutputStream to avoid creating a copy for the write - /// - internal void WriteRawBytesTo(CodedOutputStream outputStream) - { - outputStream.WriteRawBytes(bytes, 0, bytes.Length); - } - /// /// Copies the entire byte array to the destination array provided at the offset specified. /// public void CopyTo(byte[] array, int position) { - ByteArray.Copy(bytes, 0, array, position, bytes.Length); + bytes.CopyTo(array.AsMemory(position)); } /// @@ -395,7 +418,17 @@ public void CopyTo(byte[] array, int position) /// public void WriteTo(Stream outputStream) { - outputStream.Write(bytes, 0, bytes.Length); + if (MemoryMarshal.TryGetArray(bytes, out ArraySegment segment)) + { + // Fast path. ByteString was created with an array, so pass the underlying array. + outputStream.Write(segment.Array, segment.Offset, segment.Count); + } + else + { + // Slow path. BytesString is not an array. Convert memory and pass result to WriteRawBytes. + var array = bytes.ToArray(); + outputStream.Write(array, 0, array.Length); + } } } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/ByteStringAsync.cs b/csharp/src/Google.Protobuf/ByteStringAsync.cs new file mode 100644 index 0000000000000..3465cc67b40fc --- /dev/null +++ b/csharp/src/Google.Protobuf/ByteStringAsync.cs @@ -0,0 +1,64 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Google.Protobuf +{ + /// + /// SecuritySafeCritical attribute can not be placed on types with async methods. + /// This class has ByteString's async methods so it can be marked with SecuritySafeCritical. + /// + internal static class ByteStringAsync + { +#if !NET35 + internal static async Task FromStreamAsyncCore(Stream stream, CancellationToken cancellationToken) + { + int capacity = stream.CanSeek ? checked((int)(stream.Length - stream.Position)) : 0; + var memoryStream = new MemoryStream(capacity); + // We have to specify the buffer size here, as there's no overload accepting the cancellation token + // alone. But it's documented to use 81920 by default if not specified. + await stream.CopyToAsync(memoryStream, 81920, cancellationToken); +#if NETSTANDARD1_1 + byte[] bytes = memoryStream.ToArray(); +#else + // Avoid an extra copy if we can. + byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray(); +#endif + return ByteString.AttachBytes(bytes); + } +#endif + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/CodedInputStream.cs b/csharp/src/Google.Protobuf/CodedInputStream.cs index 84f90a25516fe..b09f96ce280b7 100644 --- a/csharp/src/Google.Protobuf/CodedInputStream.cs +++ b/csharp/src/Google.Protobuf/CodedInputStream.cs @@ -34,6 +34,9 @@ using System; using System.Collections.Generic; using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; namespace Google.Protobuf { @@ -51,6 +54,7 @@ namespace Google.Protobuf /// and to serialize such fields. /// /// + [SecuritySafeCritical] public sealed class CodedInputStream : IDisposable { /// @@ -64,17 +68,6 @@ public sealed class CodedInputStream : IDisposable /// private readonly byte[] buffer; - /// - /// The index of the buffer at which we need to refill from the stream (if there is one). - /// - private int bufferSize; - - private int bufferSizeAfterLimit = 0; - /// - /// The position within the current buffer (i.e. the next byte to read) - /// - private int bufferPos = 0; - /// /// The stream to read further input from, or null if the byte array buffer was provided /// directly on construction, with no further data available. @@ -82,38 +75,15 @@ public sealed class CodedInputStream : IDisposable private readonly Stream input; /// - /// The last tag we read. 0 indicates we've read to the end of the stream - /// (or haven't read anything yet). - /// - private uint lastTag = 0; - - /// - /// The next tag, used to store the value read by PeekTag. + /// The parser state is kept separately so that other parse implementations can reuse the same + /// parsing primitives. /// - private uint nextTag = 0; - private bool hasNextTag = false; + private ParserInternalState state; - internal const int DefaultRecursionLimit = 64; - internal const int DefaultSizeLimit = 64 << 20; // 64MB + internal const int DefaultRecursionLimit = 100; + internal const int DefaultSizeLimit = Int32.MaxValue; internal const int BufferSize = 4096; - /// - /// The total number of bytes read before the current buffer. The - /// total bytes read up to the current position can be computed as - /// totalBytesRetired + bufferPos. - /// - private int totalBytesRetired = 0; - - /// - /// The absolute position of the end of the current message. - /// - private int currentLimit = int.MaxValue; - - private int recursionDepth = 0; - - private readonly int recursionLimit; - private readonly int sizeLimit; - #region Construction // Note that the checks are performed such that we don't end up checking obviously-valid things // like non-null references for arrays we've just created. @@ -170,11 +140,14 @@ internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int buffer { this.input = input; this.buffer = buffer; - this.bufferPos = bufferPos; - this.bufferSize = bufferSize; - this.sizeLimit = DefaultSizeLimit; - this.recursionLimit = DefaultRecursionLimit; + this.state.bufferPos = bufferPos; + this.state.bufferSize = bufferSize; + this.state.sizeLimit = DefaultSizeLimit; + this.state.recursionLimit = DefaultRecursionLimit; + SegmentedBufferHelper.Initialize(this, out this.state.segmentedBufferHelper); this.leaveOpen = leaveOpen; + + this.state.currentLimit = int.MaxValue; } /// @@ -196,8 +169,8 @@ internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int buffer { throw new ArgumentOutOfRangeException("recursionLimit!", "Recursion limit must be positive"); } - this.sizeLimit = sizeLimit; - this.recursionLimit = recursionLimit; + this.state.sizeLimit = sizeLimit; + this.state.recursionLimit = recursionLimit; } #endregion @@ -230,9 +203,9 @@ public long Position { if (input != null) { - return input.Position - ((bufferSize + bufferSizeAfterLimit) - bufferPos); + return input.Position - ((state.bufferSize + state.bufferSizeAfterLimit) - state.bufferPos); } - return bufferPos; + return state.bufferPos; } } @@ -240,7 +213,7 @@ public long Position /// Returns the last tag read, or 0 if no tags have been read or we've read beyond /// the end of the stream. /// - internal uint LastTag { get { return lastTag; } } + internal uint LastTag { get { return state.lastTag; } } /// /// Returns the size limit for this stream. @@ -248,24 +221,48 @@ public long Position /// /// This limit is applied when reading from the underlying stream, as a sanity check. It is /// not applied when reading from a byte array data source without an underlying stream. - /// The default value is 64MB. + /// The default value is Int32.MaxValue. /// /// /// The size limit. /// - public int SizeLimit { get { return sizeLimit; } } + public int SizeLimit { get { return state.sizeLimit; } } /// /// Returns the recursion limit for this stream. This limit is applied whilst reading messages, /// to avoid maliciously-recursive data. /// /// - /// The default limit is 64. + /// The default limit is 100. /// /// /// The recursion limit for this stream. /// - public int RecursionLimit { get { return recursionLimit; } } + public int RecursionLimit { get { return state.recursionLimit; } } + + /// + /// Internal-only property; when set to true, unknown fields will be discarded while parsing. + /// + internal bool DiscardUnknownFields + { + get { return state.DiscardUnknownFields; } + set { state.DiscardUnknownFields = value; } + } + + /// + /// Internal-only property; provides extension identifiers to compatible messages while parsing. + /// + internal ExtensionRegistry ExtensionRegistry + { + get { return state.ExtensionRegistry; } + set { state.ExtensionRegistry = value; } + } + + internal byte[] InternalBuffer => buffer; + + internal Stream InternalInputStream => input; + + internal ref ParserInternalState InternalState => ref state; /// /// Disposes of this instance, potentially closing any underlying stream. @@ -292,10 +289,7 @@ public void Dispose() /// tag read was not the one specified internal void CheckReadEndOfStreamTag() { - if (lastTag != 0) - { - throw InvalidProtocolBufferException.MoreDataAvailable(); - } + ParsingPrimitivesMessages.CheckReadEndOfStreamTag(ref state); } #endregion @@ -308,16 +302,8 @@ internal void CheckReadEndOfStreamTag() /// public uint PeekTag() { - if (hasNextTag) - { - return nextTag; - } - - uint savedLast = lastTag; - nextTag = ReadTag(); - hasNextTag = true; - lastTag = savedLast; // Undo the side effect of ReadTag - return nextTag; + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.PeekTag(ref span, ref state); } /// @@ -331,54 +317,8 @@ public uint PeekTag() /// The next field tag, or 0 for end of stream. (0 is never a valid tag.) public uint ReadTag() { - if (hasNextTag) - { - lastTag = nextTag; - hasNextTag = false; - return lastTag; - } - - // Optimize for the incredibly common case of having at least two bytes left in the buffer, - // and those two bytes being enough to get the tag. This will be true for fields up to 4095. - if (bufferPos + 2 <= bufferSize) - { - int tmp = buffer[bufferPos++]; - if (tmp < 128) - { - lastTag = (uint)tmp; - } - else - { - int result = tmp & 0x7f; - if ((tmp = buffer[bufferPos++]) < 128) - { - result |= tmp << 7; - lastTag = (uint) result; - } - else - { - // Nope, rewind and go the potentially slow route. - bufferPos -= 2; - lastTag = ReadRawVarint32(); - } - } - } - else - { - if (IsAtEnd) - { - lastTag = 0; - return 0; // This is the only case in which we return 0. - } - - lastTag = ReadRawVarint32(); - } - if (lastTag == 0) - { - // If we actually read zero, that's not a valid tag. - throw InvalidProtocolBufferException.InvalidTag(); - } - return lastTag; + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseTag(ref span, ref state); } /// @@ -396,67 +336,17 @@ public uint ReadTag() /// The last read operation read to the end of the logical stream public void SkipLastField() { - if (lastTag == 0) - { - throw new InvalidOperationException("SkipLastField cannot be called at the end of a stream"); - } - switch (WireFormat.GetTagWireType(lastTag)) - { - case WireFormat.WireType.StartGroup: - SkipGroup(lastTag); - break; - case WireFormat.WireType.EndGroup: - throw new InvalidProtocolBufferException( - "SkipLastField called on an end-group tag, indicating that the corresponding start-group was missing"); - case WireFormat.WireType.Fixed32: - ReadFixed32(); - break; - case WireFormat.WireType.Fixed64: - ReadFixed64(); - break; - case WireFormat.WireType.LengthDelimited: - var length = ReadLength(); - SkipRawBytes(length); - break; - case WireFormat.WireType.Varint: - ReadRawVarint32(); - break; - } + var span = new ReadOnlySpan(buffer); + ParsingPrimitivesMessages.SkipLastField(ref span, ref state); } - private void SkipGroup(uint startGroupTag) + /// + /// Skip a group. + /// + internal void SkipGroup(uint startGroupTag) { - // Note: Currently we expect this to be the way that groups are read. We could put the recursion - // depth changes into the ReadTag method instead, potentially... - recursionDepth++; - if (recursionDepth >= recursionLimit) - { - throw InvalidProtocolBufferException.RecursionLimitExceeded(); - } - uint tag; - while (true) - { - tag = ReadTag(); - if (tag == 0) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - // Can't call SkipLastField for this case- that would throw. - if (WireFormat.GetTagWireType(tag) == WireFormat.WireType.EndGroup) - { - break; - } - // This recursion will allow us to handle nested groups. - SkipLastField(); - } - int startField = WireFormat.GetTagFieldNumber(startGroupTag); - int endField = WireFormat.GetTagFieldNumber(tag); - if (startField != endField) - { - throw new InvalidProtocolBufferException( - $"Mismatched end-group tag. Started with field {startField}; ended with field {endField}"); - } - recursionDepth--; + var span = new ReadOnlySpan(buffer); + ParsingPrimitivesMessages.SkipGroup(ref span, ref state, startGroupTag); } /// @@ -464,7 +354,8 @@ private void SkipGroup(uint startGroupTag) /// public double ReadDouble() { - return BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64()); + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseDouble(ref span, ref state); } /// @@ -472,21 +363,8 @@ public double ReadDouble() /// public float ReadFloat() { - if (BitConverter.IsLittleEndian && 4 <= bufferSize - bufferPos) - { - float ret = BitConverter.ToSingle(buffer, bufferPos); - bufferPos += 4; - return ret; - } - else - { - byte[] rawBytes = ReadRawBytes(4); - if (!BitConverter.IsLittleEndian) - { - ByteArray.Reverse(rawBytes); - } - return BitConverter.ToSingle(rawBytes, 0); - } + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseFloat(ref span, ref state); } /// @@ -534,7 +412,7 @@ public uint ReadFixed32() /// public bool ReadBool() { - return ReadRawVarint32() != 0; + return ReadRawVarint64() != 0; } /// @@ -542,45 +420,47 @@ public bool ReadBool() /// public string ReadString() { - int length = ReadLength(); - // No need to read any data for an empty string. - if (length == 0) + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ReadString(ref span, ref state); + } + + /// + /// Reads an embedded message field value from the stream. + /// + public void ReadMessage(IMessage builder) + { + // TODO(jtattermusch): if the message doesn't implement IBufferMessage (and thus does not provide the InternalMergeFrom method), + // what we're doing here works fine, but could be more efficient. + // What happends is that we first initialize a ParseContext from the current coded input stream only to parse the length of the message, at which point + // we will need to switch back again to CodedInputStream-based parsing (which involves copying and storing the state) to be able to + // invoke the legacy MergeFrom(CodedInputStream) method. + // For now, this inefficiency is fine, considering this is only a backward-compatibility scenario (and regenerating the code fixes it). + var span = new ReadOnlySpan(buffer); + ParseContext.Initialize(ref span, ref state, out ParseContext ctx); + try { - return ""; + ParsingPrimitivesMessages.ReadMessage(ref ctx, builder); } - if (length <= bufferSize - bufferPos) + finally { - // Fast path: We already have the bytes in a contiguous buffer, so - // just copy directly from it. - String result = CodedOutputStream.Utf8Encoding.GetString(buffer, bufferPos, length); - bufferPos += length; - return result; + ctx.CopyStateTo(this); } - // Slow path: Build a byte array first then copy it. - return CodedOutputStream.Utf8Encoding.GetString(ReadRawBytes(length), 0, length); } /// - /// Reads an embedded message field value from the stream. - /// - public void ReadMessage(IMessage builder) + /// Reads an embedded group field from the stream. + /// + public void ReadGroup(IMessage builder) { - int length = ReadLength(); - if (recursionDepth >= recursionLimit) + ParseContext.Initialize(this, out ParseContext ctx); + try { - throw InvalidProtocolBufferException.RecursionLimitExceeded(); + ParsingPrimitivesMessages.ReadGroup(ref ctx, builder); } - int oldLimit = PushLimit(length); - ++recursionDepth; - builder.MergeFrom(this); - CheckReadEndOfStreamTag(); - // Check that we've read exactly as much data as expected. - if (!ReachedLimit) + finally { - throw InvalidProtocolBufferException.TruncatedMessage(); + ctx.CopyStateTo(this); } - --recursionDepth; - PopLimit(oldLimit); } /// @@ -588,20 +468,8 @@ public void ReadMessage(IMessage builder) /// public ByteString ReadBytes() { - int length = ReadLength(); - if (length <= bufferSize - bufferPos && length > 0) - { - // Fast path: We already have the bytes in a contiguous buffer, so - // just copy directly from it. - ByteString result = ByteString.CopyFrom(buffer, bufferPos, length); - bufferPos += length; - return result; - } - else - { - // Slow path: Build a byte array and attach it to a new ByteString. - return ByteString.AttachBytes(ReadRawBytes(length)); - } + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ReadBytes(ref span, ref state); } /// @@ -642,7 +510,7 @@ public long ReadSFixed64() /// public int ReadSInt32() { - return DecodeZigZag32(ReadRawVarint32()); + return ParsingPrimitives.DecodeZigZag32(ReadRawVarint32()); } /// @@ -650,7 +518,7 @@ public int ReadSInt32() /// public long ReadSInt64() { - return DecodeZigZag64(ReadRawVarint64()); + return ParsingPrimitives.DecodeZigZag64(ReadRawVarint64()); } /// @@ -662,7 +530,8 @@ public long ReadSInt64() /// public int ReadLength() { - return (int) ReadRawVarint32(); + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseLength(ref span, ref state); } /// @@ -672,70 +541,14 @@ public int ReadLength() /// public bool MaybeConsumeTag(uint tag) { - if (PeekTag() == tag) - { - hasNextTag = false; - return true; - } - return false; + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.MaybeConsumeTag(ref span, ref state, tag); } - #endregion +#endregion #region Underlying reading primitives - /// - /// Same code as ReadRawVarint32, but read each byte individually, checking for - /// buffer overflow. - /// - private uint SlowReadRawVarint32() - { - int tmp = ReadRawByte(); - if (tmp < 128) - { - return (uint) tmp; - } - int result = tmp & 0x7f; - if ((tmp = ReadRawByte()) < 128) - { - result |= tmp << 7; - } - else - { - result |= (tmp & 0x7f) << 7; - if ((tmp = ReadRawByte()) < 128) - { - result |= tmp << 14; - } - else - { - result |= (tmp & 0x7f) << 14; - if ((tmp = ReadRawByte()) < 128) - { - result |= tmp << 21; - } - else - { - result |= (tmp & 0x7f) << 21; - result |= (tmp = ReadRawByte()) << 28; - if (tmp >= 128) - { - // Discard upper 32 bits. - for (int i = 0; i < 5; i++) - { - if (ReadRawByte() < 128) - { - return (uint) result; - } - } - throw InvalidProtocolBufferException.MalformedVarint(); - } - } - } - } - return (uint) result; - } - /// /// Reads a raw Varint from the stream. If larger than 32 bits, discard the upper bits. /// This method is optimised for the case where we've got lots of data in the buffer. @@ -744,58 +557,8 @@ private uint SlowReadRawVarint32() /// internal uint ReadRawVarint32() { - if (bufferPos + 5 > bufferSize) - { - return SlowReadRawVarint32(); - } - - int tmp = buffer[bufferPos++]; - if (tmp < 128) - { - return (uint) tmp; - } - int result = tmp & 0x7f; - if ((tmp = buffer[bufferPos++]) < 128) - { - result |= tmp << 7; - } - else - { - result |= (tmp & 0x7f) << 7; - if ((tmp = buffer[bufferPos++]) < 128) - { - result |= tmp << 14; - } - else - { - result |= (tmp & 0x7f) << 14; - if ((tmp = buffer[bufferPos++]) < 128) - { - result |= tmp << 21; - } - else - { - result |= (tmp & 0x7f) << 21; - result |= (tmp = buffer[bufferPos++]) << 28; - if (tmp >= 128) - { - // Discard upper 32 bits. - // Note that this has to use ReadRawByte() as we only ensure we've - // got at least 5 bytes at the start of the method. This lets us - // use the fast path in more cases, and we rarely hit this section of code. - for (int i = 0; i < 5; i++) - { - if (ReadRawByte() < 128) - { - return (uint) result; - } - } - throw InvalidProtocolBufferException.MalformedVarint(); - } - } - } - } - return (uint) result; + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseRawVarint32(ref span, ref state); } /// @@ -809,35 +572,7 @@ internal uint ReadRawVarint32() /// internal static uint ReadRawVarint32(Stream input) { - int result = 0; - int offset = 0; - for (; offset < 32; offset += 7) - { - int b = input.ReadByte(); - if (b == -1) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - result |= (b & 0x7f) << offset; - if ((b & 0x80) == 0) - { - return (uint) result; - } - } - // Keep reading up to 64 bits. - for (; offset < 64; offset += 7) - { - int b = input.ReadByte(); - if (b == -1) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - if ((b & 0x80) == 0) - { - return (uint) result; - } - } - throw InvalidProtocolBufferException.MalformedVarint(); + return ParsingPrimitives.ReadRawVarint32(input); } /// @@ -845,19 +580,8 @@ internal static uint ReadRawVarint32(Stream input) /// internal ulong ReadRawVarint64() { - int shift = 0; - ulong result = 0; - while (shift < 64) - { - byte b = ReadRawByte(); - result |= (ulong) (b & 0x7F) << shift; - if ((b & 0x80) == 0) - { - return result; - } - shift += 7; - } - throw InvalidProtocolBufferException.MalformedVarint(); + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseRawVarint64(ref span, ref state); } /// @@ -865,11 +589,8 @@ internal ulong ReadRawVarint64() /// internal uint ReadRawLittleEndian32() { - uint b1 = ReadRawByte(); - uint b2 = ReadRawByte(); - uint b3 = ReadRawByte(); - uint b4 = ReadRawByte(); - return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24); + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseRawLittleEndian32(ref span, ref state); } /// @@ -877,44 +598,8 @@ internal uint ReadRawLittleEndian32() /// internal ulong ReadRawLittleEndian64() { - ulong b1 = ReadRawByte(); - ulong b2 = ReadRawByte(); - ulong b3 = ReadRawByte(); - ulong b4 = ReadRawByte(); - ulong b5 = ReadRawByte(); - ulong b6 = ReadRawByte(); - ulong b7 = ReadRawByte(); - ulong b8 = ReadRawByte(); - return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24) - | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56); - } - - /// - /// Decode a 32-bit value with ZigZag encoding. - /// - /// - /// ZigZag encodes signed integers into values that can be efficiently - /// encoded with varint. (Otherwise, negative values must be - /// sign-extended to 64 bits to be varint encoded, thus always taking - /// 10 bytes on the wire.) - /// - internal static int DecodeZigZag32(uint n) - { - return (int)(n >> 1) ^ -(int)(n & 1); - } - - /// - /// Decode a 32-bit value with ZigZag encoding. - /// - /// - /// ZigZag encodes signed integers into values that can be efficiently - /// encoded with varint. (Otherwise, negative values must be - /// sign-extended to 64 bits to be varint encoded, thus always taking - /// 10 bytes on the wire.) - /// - internal static long DecodeZigZag64(ulong n) - { - return (long)(n >> 1) ^ -(long)(n & 1); + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseRawLittleEndian64(ref span, ref state); } #endregion @@ -928,37 +613,7 @@ internal static long DecodeZigZag64(ulong n) /// The old limit. internal int PushLimit(int byteLimit) { - if (byteLimit < 0) - { - throw InvalidProtocolBufferException.NegativeSize(); - } - byteLimit += totalBytesRetired + bufferPos; - int oldLimit = currentLimit; - if (byteLimit > oldLimit) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - currentLimit = byteLimit; - - RecomputeBufferSizeAfterLimit(); - - return oldLimit; - } - - private void RecomputeBufferSizeAfterLimit() - { - bufferSize += bufferSizeAfterLimit; - int bufferEnd = totalBytesRetired + bufferSize; - if (bufferEnd > currentLimit) - { - // Limit is in current buffer. - bufferSizeAfterLimit = bufferEnd - currentLimit; - bufferSize -= bufferSizeAfterLimit; - } - else - { - bufferSizeAfterLimit = 0; - } + return SegmentedBufferHelper.PushLimit(ref state, byteLimit); } /// @@ -966,8 +621,7 @@ private void RecomputeBufferSizeAfterLimit() /// internal void PopLimit(int oldLimit) { - currentLimit = oldLimit; - RecomputeBufferSizeAfterLimit(); + SegmentedBufferHelper.PopLimit(ref state, oldLimit); } /// @@ -978,12 +632,7 @@ internal bool ReachedLimit { get { - if (currentLimit == int.MaxValue) - { - return false; - } - int currentAbsolutePosition = totalBytesRetired + bufferPos; - return currentAbsolutePosition >= currentLimit; + return SegmentedBufferHelper.IsReachedLimit(ref state); } } @@ -994,12 +643,16 @@ internal bool ReachedLimit /// public bool IsAtEnd { - get { return bufferPos == bufferSize && !RefillBuffer(false); } + get + { + var span = new ReadOnlySpan(buffer); + return SegmentedBufferHelper.IsAtEnd(ref span, ref state); + } } /// /// Called when buffer is empty to read more bytes from the - /// input. If is true, RefillBuffer() gurantees that + /// input. If is true, RefillBuffer() guarantees that /// either there will be at least one byte in the buffer when it returns /// or it will throw an exception. If is false, /// RefillBuffer() returns false if no more bytes were available. @@ -1008,69 +661,8 @@ public bool IsAtEnd /// private bool RefillBuffer(bool mustSucceed) { - if (bufferPos < bufferSize) - { - throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty."); - } - - if (totalBytesRetired + bufferSize == currentLimit) - { - // Oops, we hit a limit. - if (mustSucceed) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - else - { - return false; - } - } - - totalBytesRetired += bufferSize; - - bufferPos = 0; - bufferSize = (input == null) ? 0 : input.Read(buffer, 0, buffer.Length); - if (bufferSize < 0) - { - throw new InvalidOperationException("Stream.Read returned a negative count"); - } - if (bufferSize == 0) - { - if (mustSucceed) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - else - { - return false; - } - } - else - { - RecomputeBufferSizeAfterLimit(); - int totalBytesRead = - totalBytesRetired + bufferSize + bufferSizeAfterLimit; - if (totalBytesRead > sizeLimit || totalBytesRead < 0) - { - throw InvalidProtocolBufferException.SizeLimitExceeded(); - } - return true; - } - } - - /// - /// Read one byte from the input. - /// - /// - /// the end of the stream or the current limit was reached - /// - internal byte ReadRawByte() - { - if (bufferPos == bufferSize) - { - RefillBuffer(true); - } - return buffer[bufferPos++]; + var span = new ReadOnlySpan(buffer); + return state.segmentedBufferHelper.RefillBuffer(ref span, ref state, mustSucceed); } /// @@ -1081,196 +673,27 @@ internal byte ReadRawByte() /// internal byte[] ReadRawBytes(int size) { - if (size < 0) - { - throw InvalidProtocolBufferException.NegativeSize(); - } - - if (totalBytesRetired + bufferPos + size > currentLimit) - { - // Read to the end of the stream (up to the current limit) anyway. - SkipRawBytes(currentLimit - totalBytesRetired - bufferPos); - // Then fail. - throw InvalidProtocolBufferException.TruncatedMessage(); - } - - if (size <= bufferSize - bufferPos) - { - // We have all the bytes we need already. - byte[] bytes = new byte[size]; - ByteArray.Copy(buffer, bufferPos, bytes, 0, size); - bufferPos += size; - return bytes; - } - else if (size < buffer.Length) - { - // Reading more bytes than are in the buffer, but not an excessive number - // of bytes. We can safely allocate the resulting array ahead of time. - - // First copy what we have. - byte[] bytes = new byte[size]; - int pos = bufferSize - bufferPos; - ByteArray.Copy(buffer, bufferPos, bytes, 0, pos); - bufferPos = bufferSize; - - // We want to use RefillBuffer() and then copy from the buffer into our - // byte array rather than reading directly into our byte array because - // the input may be unbuffered. - RefillBuffer(true); - - while (size - pos > bufferSize) - { - Buffer.BlockCopy(buffer, 0, bytes, pos, bufferSize); - pos += bufferSize; - bufferPos = bufferSize; - RefillBuffer(true); - } - - ByteArray.Copy(buffer, 0, bytes, pos, size - pos); - bufferPos = size - pos; - - return bytes; - } - else - { - // The size is very large. For security reasons, we can't allocate the - // entire byte array yet. The size comes directly from the input, so a - // maliciously-crafted message could provide a bogus very large size in - // order to trick the app into allocating a lot of memory. We avoid this - // by allocating and reading only a small chunk at a time, so that the - // malicious message must actually *be* extremely large to cause - // problems. Meanwhile, we limit the allowed size of a message elsewhere. - - // Remember the buffer markers since we'll have to copy the bytes out of - // it later. - int originalBufferPos = bufferPos; - int originalBufferSize = bufferSize; - - // Mark the current buffer consumed. - totalBytesRetired += bufferSize; - bufferPos = 0; - bufferSize = 0; - - // Read all the rest of the bytes we need. - int sizeLeft = size - (originalBufferSize - originalBufferPos); - List chunks = new List(); - - while (sizeLeft > 0) - { - byte[] chunk = new byte[Math.Min(sizeLeft, buffer.Length)]; - int pos = 0; - while (pos < chunk.Length) - { - int n = (input == null) ? -1 : input.Read(chunk, pos, chunk.Length - pos); - if (n <= 0) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - totalBytesRetired += n; - pos += n; - } - sizeLeft -= chunk.Length; - chunks.Add(chunk); - } - - // OK, got everything. Now concatenate it all into one buffer. - byte[] bytes = new byte[size]; - - // Start by copying the leftover bytes from this.buffer. - int newPos = originalBufferSize - originalBufferPos; - ByteArray.Copy(buffer, originalBufferPos, bytes, 0, newPos); - - // And now all the chunks. - foreach (byte[] chunk in chunks) - { - Buffer.BlockCopy(chunk, 0, bytes, newPos, chunk.Length); - newPos += chunk.Length; - } - - // Done. - return bytes; - } + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ReadRawBytes(ref span, ref state, size); } /// - /// Reads and discards bytes. + /// Reads a top-level message or a nested message after the limits for this message have been pushed. + /// (parser will proceed until the end of the current limit) + /// NOTE: this method needs to be public because it's invoked by the generated code - e.g. msg.MergeFrom(CodedInputStream input) method /// - /// the end of the stream - /// or the current limit was reached - private void SkipRawBytes(int size) + public void ReadRawMessage(IMessage message) { - if (size < 0) - { - throw InvalidProtocolBufferException.NegativeSize(); - } - - if (totalBytesRetired + bufferPos + size > currentLimit) - { - // Read to the end of the stream anyway. - SkipRawBytes(currentLimit - totalBytesRetired - bufferPos); - // Then fail. - throw InvalidProtocolBufferException.TruncatedMessage(); - } - - if (size <= bufferSize - bufferPos) + ParseContext.Initialize(this, out ParseContext ctx); + try { - // We have all the bytes we need already. - bufferPos += size; + ParsingPrimitivesMessages.ReadRawMessage(ref ctx, message); } - else + finally { - // Skipping more bytes than are in the buffer. First skip what we have. - int pos = bufferSize - bufferPos; - - // ROK 5/7/2013 Issue #54: should retire all bytes in buffer (bufferSize) - // totalBytesRetired += pos; - totalBytesRetired += bufferSize; - - bufferPos = 0; - bufferSize = 0; - - // Then skip directly from the InputStream for the rest. - if (pos < size) - { - if (input == null) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - SkipImpl(size - pos); - totalBytesRetired += size - pos; - } + ctx.CopyStateTo(this); } } - - /// - /// Abstraction of skipping to cope with streams which can't really skip. - /// - private void SkipImpl(int amountToSkip) - { - if (input.CanSeek) - { - long previousPosition = input.Position; - input.Position += amountToSkip; - if (input.Position != previousPosition + amountToSkip) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - } - else - { - byte[] skipBuffer = new byte[Math.Min(1024, amountToSkip)]; - while (amountToSkip > 0) - { - int bytesRead = input.Read(skipBuffer, 0, Math.Min(skipBuffer.Length, amountToSkip)); - if (bytesRead <= 0) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - amountToSkip -= bytesRead; - } - } - } - - #endregion +#endregion } -} \ No newline at end of file +} diff --git a/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs b/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs index bf221c9c0afa1..cb923549d42eb 100644 --- a/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs +++ b/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs @@ -42,13 +42,17 @@ public sealed partial class CodedOutputStream private const int LittleEndian64Size = 8; private const int LittleEndian32Size = 4; + internal const int DoubleSize = LittleEndian64Size; + internal const int FloatSize = LittleEndian32Size; + internal const int BoolSize = 1; + /// /// Computes the number of bytes that would be needed to encode a /// double field, including the tag. /// public static int ComputeDoubleSize(double value) { - return LittleEndian64Size; + return DoubleSize; } /// @@ -57,7 +61,7 @@ public static int ComputeDoubleSize(double value) /// public static int ComputeFloatSize(float value) { - return LittleEndian32Size; + return FloatSize; } /// @@ -119,7 +123,7 @@ public static int ComputeFixed32Size(uint value) /// public static int ComputeBoolSize(bool value) { - return 1; + return BoolSize; } /// @@ -128,7 +132,7 @@ public static int ComputeBoolSize(bool value) /// public static int ComputeStringSize(String value) { - int byteArraySize = Utf8Encoding.GetByteCount(value); + int byteArraySize = WritingPrimitives.Utf8Encoding.GetByteCount(value); return ComputeLengthSize(byteArraySize) + byteArraySize; } @@ -204,7 +208,7 @@ public static int ComputeSFixed64Size(long value) /// public static int ComputeSInt32Size(int value) { - return ComputeRawVarint32Size(EncodeZigZag32(value)); + return ComputeRawVarint32Size(WritingPrimitives.EncodeZigZag32(value)); } /// @@ -213,7 +217,7 @@ public static int ComputeSInt32Size(int value) /// public static int ComputeSInt64Size(long value) { - return ComputeRawVarint64Size(EncodeZigZag64(value)); + return ComputeRawVarint64Size(WritingPrimitives.EncodeZigZag64(value)); } /// diff --git a/csharp/src/Google.Protobuf/CodedOutputStream.cs b/csharp/src/Google.Protobuf/CodedOutputStream.cs index 6211aac32cb17..20d88ea7dc9b8 100644 --- a/csharp/src/Google.Protobuf/CodedOutputStream.cs +++ b/csharp/src/Google.Protobuf/CodedOutputStream.cs @@ -33,6 +33,7 @@ using Google.Protobuf.Collections; using System; using System.IO; +using System.Security; using System.Text; namespace Google.Protobuf @@ -55,11 +56,9 @@ namespace Google.Protobuf /// and MapField<TKey, TValue> to serialize such fields. /// /// + [SecuritySafeCritical] public sealed partial class CodedOutputStream : IDisposable { - // "Local" copy of Encoding.UTF8, for efficiency. (Yes, it makes a difference.) - internal static readonly Encoding Utf8Encoding = Encoding.UTF8; - /// /// The buffer size used by CreateInstance(Stream). /// @@ -67,8 +66,8 @@ public sealed partial class CodedOutputStream : IDisposable private readonly bool leaveOpen; private readonly byte[] buffer; - private readonly int limit; - private int position; + private WriterInternalState state; + private readonly Stream output; #region Construction @@ -89,9 +88,10 @@ public CodedOutputStream(byte[] flatArray) : this(flatArray, 0, flatArray.Length private CodedOutputStream(byte[] buffer, int offset, int length) { this.output = null; - this.buffer = buffer; - this.position = offset; - this.limit = offset + length; + this.buffer = ProtoPreconditions.CheckNotNull(buffer, nameof(buffer)); + this.state.position = offset; + this.state.limit = offset + length; + WriteBufferHelper.Initialize(this, out this.state.writeBufferHelper); leaveOpen = true; // Simple way of avoiding trying to dispose of a null reference } @@ -99,8 +99,9 @@ private CodedOutputStream(Stream output, byte[] buffer, bool leaveOpen) { this.output = ProtoPreconditions.CheckNotNull(output, nameof(output)); this.buffer = buffer; - this.position = 0; - this.limit = buffer.Length; + this.state.position = 0; + this.state.limit = buffer.Length; + WriteBufferHelper.Initialize(this, out this.state.writeBufferHelper); this.leaveOpen = leaveOpen; } @@ -155,9 +156,9 @@ public long Position { if (output != null) { - return output.Position + position; + return output.Position + state.position; } - return position; + return state.position; } } @@ -169,7 +170,8 @@ public long Position /// The value to write public void WriteDouble(double value) { - WriteRawLittleEndian64((ulong)BitConverter.DoubleToInt64Bits(value)); + var span = new Span(buffer); + WritingPrimitives.WriteDouble(ref span, ref state, value); } /// @@ -178,23 +180,8 @@ public void WriteDouble(double value) /// The value to write public void WriteFloat(float value) { - byte[] rawBytes = BitConverter.GetBytes(value); - if (!BitConverter.IsLittleEndian) - { - ByteArray.Reverse(rawBytes); - } - - if (limit - position >= 4) - { - buffer[position++] = rawBytes[0]; - buffer[position++] = rawBytes[1]; - buffer[position++] = rawBytes[2]; - buffer[position++] = rawBytes[3]; - } - else - { - WriteRawBytes(rawBytes, 0, 4); - } + var span = new Span(buffer); + WritingPrimitives.WriteFloat(ref span, ref state, value); } /// @@ -203,7 +190,8 @@ public void WriteFloat(float value) /// The value to write public void WriteUInt64(ulong value) { - WriteRawVarint64(value); + var span = new Span(buffer); + WritingPrimitives.WriteUInt64(ref span, ref state, value); } /// @@ -212,7 +200,8 @@ public void WriteUInt64(ulong value) /// The value to write public void WriteInt64(long value) { - WriteRawVarint64((ulong) value); + var span = new Span(buffer); + WritingPrimitives.WriteInt64(ref span, ref state, value); } /// @@ -221,15 +210,8 @@ public void WriteInt64(long value) /// The value to write public void WriteInt32(int value) { - if (value >= 0) - { - WriteRawVarint32((uint) value); - } - else - { - // Must sign-extend. - WriteRawVarint64((ulong) value); - } + var span = new Span(buffer); + WritingPrimitives.WriteInt32(ref span, ref state, value); } /// @@ -238,7 +220,8 @@ public void WriteInt32(int value) /// The value to write public void WriteFixed64(ulong value) { - WriteRawLittleEndian64(value); + var span = new Span(buffer); + WritingPrimitives.WriteFixed64(ref span, ref state, value); } /// @@ -247,7 +230,8 @@ public void WriteFixed64(ulong value) /// The value to write public void WriteFixed32(uint value) { - WriteRawLittleEndian32(value); + var span = new Span(buffer); + WritingPrimitives.WriteFixed32(ref span, ref state, value); } /// @@ -256,7 +240,8 @@ public void WriteFixed32(uint value) /// The value to write public void WriteBool(bool value) { - WriteRawByte(value ? (byte) 1 : (byte) 0); + var span = new Span(buffer); + WritingPrimitives.WriteBool(ref span, ref state, value); } /// @@ -266,41 +251,70 @@ public void WriteBool(bool value) /// The value to write public void WriteString(string value) { - // Optimise the case where we have enough space to write - // the string directly to the buffer, which should be common. - int length = Utf8Encoding.GetByteCount(value); - WriteLength(length); - if (limit - position >= length) + var span = new Span(buffer); + WritingPrimitives.WriteString(ref span, ref state, value); + } + + /// + /// Writes a message, without a tag, to the stream. + /// The data is length-prefixed. + /// + /// The value to write + public void WriteMessage(IMessage value) + { + // TODO(jtattermusch): if the message doesn't implement IBufferMessage (and thus does not provide the InternalWriteTo method), + // what we're doing here works fine, but could be more efficient. + // For now, this inefficiency is fine, considering this is only a backward-compatibility scenario (and regenerating the code fixes it). + var span = new Span(buffer); + WriteContext.Initialize(ref span, ref state, out WriteContext ctx); + try { - if (length == value.Length) // Must be all ASCII... - { - for (int i = 0; i < length; i++) - { - buffer[position + i] = (byte)value[i]; - } - } - else - { - Utf8Encoding.GetBytes(value, 0, value.Length, buffer, position); - } - position += length; + WritingPrimitivesMessages.WriteMessage(ref ctx, value); } - else + finally { - byte[] bytes = Utf8Encoding.GetBytes(value); - WriteRawBytes(bytes); + ctx.CopyStateTo(this); } } /// /// Writes a message, without a tag, to the stream. - /// The data is length-prefixed. + /// Only the message data is written, without a length-delimiter. /// /// The value to write - public void WriteMessage(IMessage value) + public void WriteRawMessage(IMessage value) + { + // TODO(jtattermusch): if the message doesn't implement IBufferMessage (and thus does not provide the InternalWriteTo method), + // what we're doing here works fine, but could be more efficient. + // For now, this inefficiency is fine, considering this is only a backward-compatibility scenario (and regenerating the code fixes it). + var span = new Span(buffer); + WriteContext.Initialize(ref span, ref state, out WriteContext ctx); + try + { + WritingPrimitivesMessages.WriteRawMessage(ref ctx, value); + } + finally + { + ctx.CopyStateTo(this); + } + } + + /// + /// Writes a group, without a tag, to the stream. + /// + /// The value to write + public void WriteGroup(IMessage value) { - WriteLength(value.CalculateSize()); - value.WriteTo(this); + var span = new Span(buffer); + WriteContext.Initialize(ref span, ref state, out WriteContext ctx); + try + { + WritingPrimitivesMessages.WriteGroup(ref ctx, value); + } + finally + { + ctx.CopyStateTo(this); + } } /// @@ -310,8 +324,8 @@ public void WriteMessage(IMessage value) /// The value to write public void WriteBytes(ByteString value) { - WriteLength(value.Length); - value.WriteRawBytesTo(this); + var span = new Span(buffer); + WritingPrimitives.WriteBytes(ref span, ref state, value); } /// @@ -320,7 +334,8 @@ public void WriteBytes(ByteString value) /// The value to write public void WriteUInt32(uint value) { - WriteRawVarint32(value); + var span = new Span(buffer); + WritingPrimitives.WriteUInt32(ref span, ref state, value); } /// @@ -329,7 +344,8 @@ public void WriteUInt32(uint value) /// The value to write public void WriteEnum(int value) { - WriteInt32(value); + var span = new Span(buffer); + WritingPrimitives.WriteEnum(ref span, ref state, value); } /// @@ -338,7 +354,8 @@ public void WriteEnum(int value) /// The value to write. public void WriteSFixed32(int value) { - WriteRawLittleEndian32((uint) value); + var span = new Span(buffer); + WritingPrimitives.WriteSFixed32(ref span, ref state, value); } /// @@ -347,7 +364,8 @@ public void WriteSFixed32(int value) /// The value to write public void WriteSFixed64(long value) { - WriteRawLittleEndian64((ulong) value); + var span = new Span(buffer); + WritingPrimitives.WriteSFixed64(ref span, ref state, value); } /// @@ -356,7 +374,8 @@ public void WriteSFixed64(long value) /// The value to write public void WriteSInt32(int value) { - WriteRawVarint32(EncodeZigZag32(value)); + var span = new Span(buffer); + WritingPrimitives.WriteSInt32(ref span, ref state, value); } /// @@ -365,7 +384,8 @@ public void WriteSInt32(int value) /// The value to write public void WriteSInt64(long value) { - WriteRawVarint64(EncodeZigZag64(value)); + var span = new Span(buffer); + WritingPrimitives.WriteSInt64(ref span, ref state, value); } /// @@ -377,7 +397,8 @@ public void WriteSInt64(long value) /// Length value, in bytes. public void WriteLength(int length) { - WriteRawVarint32((uint) length); + var span = new Span(buffer); + WritingPrimitives.WriteLength(ref span, ref state, length); } #endregion @@ -390,7 +411,8 @@ public void WriteLength(int length) /// The wire format type of the tag to write public void WriteTag(int fieldNumber, WireFormat.WireType type) { - WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type)); + var span = new Span(buffer); + WritingPrimitives.WriteTag(ref span, ref state, fieldNumber, type); } /// @@ -399,7 +421,8 @@ public void WriteTag(int fieldNumber, WireFormat.WireType type) /// The encoded tag public void WriteTag(uint tag) { - WriteRawVarint32(tag); + var span = new Span(buffer); + WritingPrimitives.WriteTag(ref span, ref state, tag); } /// @@ -408,7 +431,8 @@ public void WriteTag(uint tag) /// The encoded tag public void WriteRawTag(byte b1) { - WriteRawByte(b1); + var span = new Span(buffer); + WritingPrimitives.WriteRawTag(ref span, ref state, b1); } /// @@ -418,8 +442,8 @@ public void WriteRawTag(byte b1) /// The second byte of the encoded tag public void WriteRawTag(byte b1, byte b2) { - WriteRawByte(b1); - WriteRawByte(b2); + var span = new Span(buffer); + WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2); } /// @@ -430,9 +454,8 @@ public void WriteRawTag(byte b1, byte b2) /// The third byte of the encoded tag public void WriteRawTag(byte b1, byte b2, byte b3) { - WriteRawByte(b1); - WriteRawByte(b2); - WriteRawByte(b3); + var span = new Span(buffer); + WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3); } /// @@ -444,10 +467,8 @@ public void WriteRawTag(byte b1, byte b2, byte b3) /// The fourth byte of the encoded tag public void WriteRawTag(byte b1, byte b2, byte b3, byte b4) { - WriteRawByte(b1); - WriteRawByte(b2); - WriteRawByte(b3); - WriteRawByte(b4); + var span = new Span(buffer); + WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3, b4); } /// @@ -460,15 +481,13 @@ public void WriteRawTag(byte b1, byte b2, byte b3, byte b4) /// The fifth byte of the encoded tag public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5) { - WriteRawByte(b1); - WriteRawByte(b2); - WriteRawByte(b3); - WriteRawByte(b4); - WriteRawByte(b5); + var span = new Span(buffer); + WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3, b4, b5); } #endregion #region Underlying writing primitives + /// /// Writes a 32 bit value as a varint. The fast route is taken when /// there's enough buffer space left to whizz through without checking @@ -476,112 +495,26 @@ public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5) /// internal void WriteRawVarint32(uint value) { - // Optimize for the common case of a single byte value - if (value < 128 && position < limit) - { - buffer[position++] = (byte)value; - return; - } - - while (value > 127 && position < limit) - { - buffer[position++] = (byte) ((value & 0x7F) | 0x80); - value >>= 7; - } - while (value > 127) - { - WriteRawByte((byte) ((value & 0x7F) | 0x80)); - value >>= 7; - } - if (position < limit) - { - buffer[position++] = (byte) value; - } - else - { - WriteRawByte((byte) value); - } + var span = new Span(buffer); + WritingPrimitives.WriteRawVarint32(ref span, ref state, value); } internal void WriteRawVarint64(ulong value) { - while (value > 127 && position < limit) - { - buffer[position++] = (byte) ((value & 0x7F) | 0x80); - value >>= 7; - } - while (value > 127) - { - WriteRawByte((byte) ((value & 0x7F) | 0x80)); - value >>= 7; - } - if (position < limit) - { - buffer[position++] = (byte) value; - } - else - { - WriteRawByte((byte) value); - } + var span = new Span(buffer); + WritingPrimitives.WriteRawVarint64(ref span, ref state, value); } internal void WriteRawLittleEndian32(uint value) { - if (position + 4 > limit) - { - WriteRawByte((byte) value); - WriteRawByte((byte) (value >> 8)); - WriteRawByte((byte) (value >> 16)); - WriteRawByte((byte) (value >> 24)); - } - else - { - buffer[position++] = ((byte) value); - buffer[position++] = ((byte) (value >> 8)); - buffer[position++] = ((byte) (value >> 16)); - buffer[position++] = ((byte) (value >> 24)); - } + var span = new Span(buffer); + WritingPrimitives.WriteRawLittleEndian32(ref span, ref state, value); } internal void WriteRawLittleEndian64(ulong value) { - if (position + 8 > limit) - { - WriteRawByte((byte) value); - WriteRawByte((byte) (value >> 8)); - WriteRawByte((byte) (value >> 16)); - WriteRawByte((byte) (value >> 24)); - WriteRawByte((byte) (value >> 32)); - WriteRawByte((byte) (value >> 40)); - WriteRawByte((byte) (value >> 48)); - WriteRawByte((byte) (value >> 56)); - } - else - { - buffer[position++] = ((byte) value); - buffer[position++] = ((byte) (value >> 8)); - buffer[position++] = ((byte) (value >> 16)); - buffer[position++] = ((byte) (value >> 24)); - buffer[position++] = ((byte) (value >> 32)); - buffer[position++] = ((byte) (value >> 40)); - buffer[position++] = ((byte) (value >> 48)); - buffer[position++] = ((byte) (value >> 56)); - } - } - - internal void WriteRawByte(byte value) - { - if (position == limit) - { - RefreshBuffer(); - } - - buffer[position++] = value; - } - - internal void WriteRawByte(uint value) - { - WriteRawByte((byte) value); + var span = new Span(buffer); + WritingPrimitives.WriteRawLittleEndian64(ref span, ref state, value); } /// @@ -597,85 +530,12 @@ internal void WriteRawBytes(byte[] value) /// internal void WriteRawBytes(byte[] value, int offset, int length) { - if (limit - position >= length) - { - ByteArray.Copy(value, offset, buffer, position, length); - // We have room in the current buffer. - position += length; - } - else - { - // Write extends past current buffer. Fill the rest of this buffer and - // flush. - int bytesWritten = limit - position; - ByteArray.Copy(value, offset, buffer, position, bytesWritten); - offset += bytesWritten; - length -= bytesWritten; - position = limit; - RefreshBuffer(); - - // Now deal with the rest. - // Since we have an output stream, this is our buffer - // and buffer offset == 0 - if (length <= limit) - { - // Fits in new buffer. - ByteArray.Copy(value, offset, buffer, 0, length); - position = length; - } - else - { - // Write is very big. Let's do it all at once. - output.Write(value, offset, length); - } - } + var span = new Span(buffer); + WritingPrimitives.WriteRawBytes(ref span, ref state, value, offset, length); } #endregion - /// - /// Encode a 32-bit value with ZigZag encoding. - /// - /// - /// ZigZag encodes signed integers into values that can be efficiently - /// encoded with varint. (Otherwise, negative values must be - /// sign-extended to 64 bits to be varint encoded, thus always taking - /// 10 bytes on the wire.) - /// - internal static uint EncodeZigZag32(int n) - { - // Note: the right-shift must be arithmetic - return (uint) ((n << 1) ^ (n >> 31)); - } - - /// - /// Encode a 64-bit value with ZigZag encoding. - /// - /// - /// ZigZag encodes signed integers into values that can be efficiently - /// encoded with varint. (Otherwise, negative values must be - /// sign-extended to 64 bits to be varint encoded, thus always taking - /// 10 bytes on the wire.) - /// - internal static ulong EncodeZigZag64(long n) - { - return (ulong) ((n << 1) ^ (n >> 63)); - } - - private void RefreshBuffer() - { - if (output == null) - { - // We're writing to a single buffer. - throw new OutOfSpaceException(); - } - - // Since we have an output stream, this is our buffer - // and buffer offset == 0 - output.Write(buffer, 0, position); - position = 0; - } - /// /// Indicates that a CodedOutputStream wrapping a flat byte array /// ran out of space. @@ -717,45 +577,31 @@ public void Dispose() /// public void Flush() { - if (output != null) - { - RefreshBuffer(); - } + var span = new Span(buffer); + WriteBufferHelper.Flush(ref span, ref state); } /// /// Verifies that SpaceLeft returns zero. It's common to create a byte array /// that is exactly big enough to hold a message, then write to it with /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that - /// the message was actually as big as expected, which can help bugs. + /// the message was actually as big as expected, which can help finding bugs. /// public void CheckNoSpaceLeft() { - if (SpaceLeft != 0) - { - throw new InvalidOperationException("Did not write as much data as expected."); - } + WriteBufferHelper.CheckNoSpaceLeft(ref state); } /// /// If writing to a flat array, returns the space left in the array. Otherwise, /// throws an InvalidOperationException. /// - public int SpaceLeft - { - get - { - if (output == null) - { - return limit - position; - } - else - { - throw new InvalidOperationException( - "SpaceLeft can only be called on CodedOutputStreams that are " + - "writing to a flat array."); - } - } - } + public int SpaceLeft => WriteBufferHelper.GetSpaceLeft(ref state); + + internal byte[] InternalBuffer => buffer; + + internal Stream InternalOutputStream => output; + + internal ref WriterInternalState InternalState => ref state; } } diff --git a/csharp/src/Google.Protobuf/Collections/Lists.cs b/csharp/src/Google.Protobuf/Collections/Lists.cs new file mode 100644 index 0000000000000..860795ceeff8b --- /dev/null +++ b/csharp/src/Google.Protobuf/Collections/Lists.cs @@ -0,0 +1,89 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2017 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace Google.Protobuf.Collections +{ + /// + /// Utility to compare if two Lists are the same, and the hash code + /// of a List. + /// + public static class Lists + { + /// + /// Checks if two lists are equal. + /// + public static bool Equals(List left, List right) + { + if (left == right) + { + return true; + } + if (left == null || right == null) + { + return false; + } + if (left.Count != right.Count) + { + return false; + } + IEqualityComparer comparer = EqualityComparer.Default; + for (int i = 0; i < left.Count; i++) + { + if (!comparer.Equals(left[i], right[i])) + { + return false; + } + } + return true; + } + + /// + /// Gets the list's hash code. + /// + public static int GetHashCode(List list) + { + if (list == null) + { + return 0; + } + int hash = 31; + foreach (T element in list) + { + hash = hash * 29 + element.GetHashCode(); + } + return hash; + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs index 8dac8e301d108..6b7d0f101a157 100644 --- a/csharp/src/Google.Protobuf/Collections/MapField.cs +++ b/csharp/src/Google.Protobuf/Collections/MapField.cs @@ -1,771 +1,762 @@ -#region Copyright notice and license -// Protocol Buffers - Google's data interchange format -// Copyright 2015 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#endregion - -using Google.Protobuf.Compatibility; -using Google.Protobuf.Reflection; -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Google.Protobuf.Collections -{ - /// - /// Representation of a map field in a Protocol Buffer message. - /// - /// Key type in the map. Must be a type supported by Protocol Buffer map keys. - /// Value type in the map. Must be a type supported by Protocol Buffers. - /// - /// - /// For string keys, the equality comparison is provided by . - /// - /// - /// Null values are not permitted in the map, either for wrapper types or regular messages. - /// If a map is deserialized from a data stream and the value is missing from an entry, a default value - /// is created instead. For primitive types, that is the regular default value (0, the empty string and so - /// on); for message types, an empty instance of the message is created, as if the map entry contained a 0-length - /// encoded value for the field. - /// - /// - /// This implementation does not generally prohibit the use of key/value types which are not - /// supported by Protocol Buffers (e.g. using a key type of byte) but nor does it guarantee - /// that all operations will work in such cases. - /// - /// - /// The order in which entries are returned when iterating over this object is undefined, and may change - /// in future versions. - /// - /// - public sealed class MapField : IDeepCloneable>, IDictionary, IEquatable>, IDictionary -#if !NET35 - , IReadOnlyDictionary -#endif - { - // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.) - private readonly Dictionary>> map = - new Dictionary>>(); - private readonly LinkedList> list = new LinkedList>(); - - /// - /// Creates a deep clone of this object. - /// - /// - /// A deep clone of this object. - /// - public MapField Clone() - { - var clone = new MapField(); - // Keys are never cloneable. Values might be. - if (typeof(IDeepCloneable).IsAssignableFrom(typeof(TValue))) - { - foreach (var pair in list) - { - clone.Add(pair.Key, ((IDeepCloneable)pair.Value).Clone()); - } - } - else - { - // Nothing is cloneable, so we don't need to worry. - clone.Add(this); - } - return clone; - } - - /// - /// Adds the specified key/value pair to the map. - /// - /// - /// This operation fails if the key already exists in the map. To replace an existing entry, use the indexer. - /// - /// The key to add - /// The value to add. - /// The given key already exists in map. - public void Add(TKey key, TValue value) - { - // Validation of arguments happens in ContainsKey and the indexer - if (ContainsKey(key)) - { - throw new ArgumentException("Key already exists in map", nameof(key)); - } - this[key] = value; - } - - /// - /// Determines whether the specified key is present in the map. - /// - /// The key to check. - /// true if the map contains the given key; false otherwise. - public bool ContainsKey(TKey key) - { - ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key)); - return map.ContainsKey(key); - } - - private bool ContainsValue(TValue value) - { - var comparer = EqualityComparer.Default; - return list.Any(pair => comparer.Equals(pair.Value, value)); - } - - /// - /// Removes the entry identified by the given key from the map. - /// - /// The key indicating the entry to remove from the map. - /// true if the map contained the given key before the entry was removed; false otherwise. - public bool Remove(TKey key) - { - ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key)); - LinkedListNode> node; - if (map.TryGetValue(key, out node)) - { - map.Remove(key); - node.List.Remove(node); - return true; - } - else - { - return false; - } - } - - /// - /// Gets the value associated with the specified key. - /// - /// The key whose value to get. - /// When this method returns, the value associated with the specified key, if the key is found; - /// otherwise, the default value for the type of the parameter. - /// This parameter is passed uninitialized. - /// true if the map contains an element with the specified key; otherwise, false. - public bool TryGetValue(TKey key, out TValue value) - { - LinkedListNode> node; - if (map.TryGetValue(key, out node)) - { - value = node.Value.Value; - return true; - } - else - { - value = default(TValue); - return false; - } - } - - /// - /// Gets or sets the value associated with the specified key. - /// - /// The key of the value to get or set. - /// The property is retrieved and key does not exist in the collection. - /// The value associated with the specified key. If the specified key is not found, - /// a get operation throws a , and a set operation creates a new element with the specified key. - public TValue this[TKey key] - { - get - { - ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key)); - TValue value; - if (TryGetValue(key, out value)) - { - return value; - } - throw new KeyNotFoundException(); - } - set - { - ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key)); - // value == null check here is redundant, but avoids boxing. - if (value == null) - { - ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value)); - } - LinkedListNode> node; - var pair = new KeyValuePair(key, value); - if (map.TryGetValue(key, out node)) - { - node.Value = pair; - } - else - { - node = list.AddLast(pair); - map[key] = node; - } - } - } - - /// - /// Gets a collection containing the keys in the map. - /// - public ICollection Keys { get { return new MapView(this, pair => pair.Key, ContainsKey); } } - - /// - /// Gets a collection containing the values in the map. - /// - public ICollection Values { get { return new MapView(this, pair => pair.Value, ContainsValue); } } - - /// - /// Adds the specified entries to the map. The keys and values are not automatically cloned. - /// - /// The entries to add to the map. - public void Add(IDictionary entries) - { - ProtoPreconditions.CheckNotNull(entries, nameof(entries)); - foreach (var pair in entries) - { - Add(pair.Key, pair.Value); - } - } - - /// - /// Returns an enumerator that iterates through the collection. - /// - /// - /// An enumerator that can be used to iterate through the collection. - /// - public IEnumerator> GetEnumerator() - { - return list.GetEnumerator(); - } - - /// - /// Returns an enumerator that iterates through a collection. - /// - /// - /// An object that can be used to iterate through the collection. - /// - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - /// - /// Adds the specified item to the map. - /// - /// The item to add to the map. - void ICollection>.Add(KeyValuePair item) - { - Add(item.Key, item.Value); - } - - /// - /// Removes all items from the map. - /// - public void Clear() - { - list.Clear(); - map.Clear(); - } - - /// - /// Determines whether map contains an entry equivalent to the given key/value pair. - /// - /// The key/value pair to find. - /// - bool ICollection>.Contains(KeyValuePair item) - { - TValue value; - return TryGetValue(item.Key, out value) - && EqualityComparer.Default.Equals(item.Value, value); - } - - /// - /// Copies the key/value pairs in this map to an array. - /// - /// The array to copy the entries into. - /// The index of the array at which to start copying values. - void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) - { - list.CopyTo(array, arrayIndex); - } - - /// - /// Removes the specified key/value pair from the map. - /// - /// Both the key and the value must be found for the entry to be removed. - /// The key/value pair to remove. - /// true if the key/value pair was found and removed; false otherwise. - bool ICollection>.Remove(KeyValuePair item) - { - if (item.Key == null) - { - throw new ArgumentException("Key is null", nameof(item)); - } - LinkedListNode> node; - if (map.TryGetValue(item.Key, out node) && - EqualityComparer.Default.Equals(item.Value, node.Value.Value)) - { - map.Remove(item.Key); - node.List.Remove(node); - return true; - } - else - { - return false; - } - } - - /// - /// Gets the number of elements contained in the map. - /// - public int Count { get { return list.Count; } } - - /// - /// Gets a value indicating whether the map is read-only. - /// - public bool IsReadOnly { get { return false; } } - - /// - /// Determines whether the specified , is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object other) - { - return Equals(other as MapField); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - var valueComparer = EqualityComparer.Default; - int hash = 0; - foreach (var pair in list) - { - hash ^= pair.Key.GetHashCode() * 31 + valueComparer.GetHashCode(pair.Value); - } - return hash; - } - - /// - /// Compares this map with another for equality. - /// - /// - /// The order of the key/value pairs in the maps is not deemed significant in this comparison. - /// - /// The map to compare this with. - /// true if refers to an equal map; false otherwise. - public bool Equals(MapField other) - { - if (other == null) - { - return false; - } - if (other == this) - { - return true; - } - if (other.Count != this.Count) - { - return false; - } - var valueComparer = EqualityComparer.Default; - foreach (var pair in this) - { - TValue value; - if (!other.TryGetValue(pair.Key, out value)) - { - return false; - } - if (!valueComparer.Equals(value, pair.Value)) - { - return false; - } - } - return true; - } - - /// - /// Adds entries to the map from the given stream. - /// - /// - /// It is assumed that the stream is initially positioned after the tag specified by the codec. - /// This method will continue reading entries from the stream until the end is reached, or - /// a different tag is encountered. - /// - /// Stream to read from - /// Codec describing how the key/value pairs are encoded - public void AddEntriesFrom(CodedInputStream input, Codec codec) - { - var adapter = new Codec.MessageAdapter(codec); - do - { - adapter.Reset(); - input.ReadMessage(adapter); - this[adapter.Key] = adapter.Value; - } while (input.MaybeConsumeTag(codec.MapTag)); - } - - /// - /// Writes the contents of this map to the given coded output stream, using the specified codec - /// to encode each entry. - /// - /// The output stream to write to. - /// The codec to use for each entry. - public void WriteTo(CodedOutputStream output, Codec codec) - { - var message = new Codec.MessageAdapter(codec); - foreach (var entry in list) - { - message.Key = entry.Key; - message.Value = entry.Value; - output.WriteTag(codec.MapTag); - output.WriteMessage(message); - } - } - - /// - /// Calculates the size of this map based on the given entry codec. - /// - /// The codec to use to encode each entry. - /// - public int CalculateSize(Codec codec) - { - if (Count == 0) - { - return 0; - } - var message = new Codec.MessageAdapter(codec); - int size = 0; - foreach (var entry in list) - { - message.Key = entry.Key; - message.Value = entry.Value; - size += CodedOutputStream.ComputeRawVarint32Size(codec.MapTag); - size += CodedOutputStream.ComputeMessageSize(message); - } - return size; - } - - /// - /// Returns a string representation of this repeated field, in the same - /// way as it would be represented by the default JSON formatter. - /// - public override string ToString() - { - var writer = new StringWriter(); - JsonFormatter.Default.WriteDictionary(writer, this); - return writer.ToString(); - } - - #region IDictionary explicit interface implementation - void IDictionary.Add(object key, object value) - { - Add((TKey)key, (TValue)value); - } - - bool IDictionary.Contains(object key) - { - if (!(key is TKey)) - { - return false; - } - return ContainsKey((TKey)key); - } - - IDictionaryEnumerator IDictionary.GetEnumerator() - { - return new DictionaryEnumerator(GetEnumerator()); - } - - void IDictionary.Remove(object key) - { - ProtoPreconditions.CheckNotNull(key, nameof(key)); - if (!(key is TKey)) - { - return; - } - Remove((TKey)key); - } - - void ICollection.CopyTo(Array array, int index) - { - // This is ugly and slow as heck, but with any luck it will never be used anyway. - ICollection temp = this.Select(pair => new DictionaryEntry(pair.Key, pair.Value)).ToList(); - temp.CopyTo(array, index); - } - - bool IDictionary.IsFixedSize { get { return false; } } - - ICollection IDictionary.Keys { get { return (ICollection)Keys; } } - - ICollection IDictionary.Values { get { return (ICollection)Values; } } - - bool ICollection.IsSynchronized { get { return false; } } - - object ICollection.SyncRoot { get { return this; } } - - object IDictionary.this[object key] - { - get - { - ProtoPreconditions.CheckNotNull(key, nameof(key)); - if (!(key is TKey)) - { - return null; - } - TValue value; - TryGetValue((TKey)key, out value); - return value; - } - - set - { - this[(TKey)key] = (TValue)value; - } - } - #endregion - - #region IReadOnlyDictionary explicit interface implementation -#if !NET35 - IEnumerable IReadOnlyDictionary.Keys => Keys; - - IEnumerable IReadOnlyDictionary.Values => Values; -#endif - #endregion - - private class DictionaryEnumerator : IDictionaryEnumerator - { - private readonly IEnumerator> enumerator; - - internal DictionaryEnumerator(IEnumerator> enumerator) - { - this.enumerator = enumerator; - } - - public bool MoveNext() - { - return enumerator.MoveNext(); - } - - public void Reset() - { - enumerator.Reset(); - } - - public object Current { get { return Entry; } } - public DictionaryEntry Entry { get { return new DictionaryEntry(Key, Value); } } - public object Key { get { return enumerator.Current.Key; } } - public object Value { get { return enumerator.Current.Value; } } - } - - /// - /// A codec for a specific map field. This contains all the information required to encode and - /// decode the nested messages. - /// - public sealed class Codec - { - private readonly FieldCodec keyCodec; - private readonly FieldCodec valueCodec; - private readonly uint mapTag; - - /// - /// Creates a new entry codec based on a separate key codec and value codec, - /// and the tag to use for each map entry. - /// - /// The key codec. - /// The value codec. - /// The map tag to use to introduce each map entry. - public Codec(FieldCodec keyCodec, FieldCodec valueCodec, uint mapTag) - { - this.keyCodec = keyCodec; - this.valueCodec = valueCodec; - this.mapTag = mapTag; - } - - /// - /// The tag used in the enclosing message to indicate map entries. - /// - internal uint MapTag { get { return mapTag; } } - - /// - /// A mutable message class, used for parsing and serializing. This - /// delegates the work to a codec, but implements the interface - /// for interop with and . - /// This is nested inside Codec as it's tightly coupled to the associated codec, - /// and it's simpler if it has direct access to all its fields. - /// - internal class MessageAdapter : IMessage - { - private static readonly byte[] ZeroLengthMessageStreamData = new byte[] { 0 }; - - private readonly Codec codec; - internal TKey Key { get; set; } - internal TValue Value { get; set; } - - internal MessageAdapter(Codec codec) - { - this.codec = codec; - } - - internal void Reset() - { - Key = codec.keyCodec.DefaultValue; - Value = codec.valueCodec.DefaultValue; - } - - public void MergeFrom(CodedInputStream input) - { - uint tag; - while ((tag = input.ReadTag()) != 0) - { - if (tag == codec.keyCodec.Tag) - { - Key = codec.keyCodec.Read(input); - } - else if (tag == codec.valueCodec.Tag) - { - Value = codec.valueCodec.Read(input); - } - else - { - input.SkipLastField(); - } - } - - // Corner case: a map entry with a key but no value, where the value type is a message. - // Read it as if we'd seen an input stream with no data (i.e. create a "default" message). - if (Value == null) - { - Value = codec.valueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData)); - } - } - - public void WriteTo(CodedOutputStream output) - { - codec.keyCodec.WriteTagAndValue(output, Key); - codec.valueCodec.WriteTagAndValue(output, Value); - } - - public int CalculateSize() - { - return codec.keyCodec.CalculateSizeWithTag(Key) + codec.valueCodec.CalculateSizeWithTag(Value); - } - - MessageDescriptor IMessage.Descriptor { get { return null; } } - } - } - - private class MapView : ICollection, ICollection - { - private readonly MapField parent; - private readonly Func, T> projection; - private readonly Func containsCheck; - - internal MapView( - MapField parent, - Func, T> projection, - Func containsCheck) - { - this.parent = parent; - this.projection = projection; - this.containsCheck = containsCheck; - } - - public int Count { get { return parent.Count; } } - - public bool IsReadOnly { get { return true; } } - - public bool IsSynchronized { get { return false; } } - - public object SyncRoot { get { return parent; } } - - public void Add(T item) - { - throw new NotSupportedException(); - } - - public void Clear() - { - throw new NotSupportedException(); - } - - public bool Contains(T item) - { - return containsCheck(item); - } - - public void CopyTo(T[] array, int arrayIndex) - { - if (arrayIndex < 0) - { - throw new ArgumentOutOfRangeException(nameof(arrayIndex)); - } - if (arrayIndex + Count > array.Length) - { - throw new ArgumentException("Not enough space in the array", nameof(array)); - } - foreach (var item in this) - { - array[arrayIndex++] = item; - } - } - - public IEnumerator GetEnumerator() - { - return parent.list.Select(projection).GetEnumerator(); - } - - public bool Remove(T item) - { - throw new NotSupportedException(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - public void CopyTo(Array array, int index) - { - if (index < 0) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - if (index + Count > array.Length) - { - throw new ArgumentException("Not enough space in the array", nameof(array)); - } - foreach (var item in this) - { - array.SetValue(item, index++); - } - } - } - } -} +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using Google.Protobuf.Compatibility; +using Google.Protobuf.Reflection; +using System; +using System.Buffers; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security; + +namespace Google.Protobuf.Collections +{ + /// + /// Representation of a map field in a Protocol Buffer message. + /// + /// Key type in the map. Must be a type supported by Protocol Buffer map keys. + /// Value type in the map. Must be a type supported by Protocol Buffers. + /// + /// + /// For string keys, the equality comparison is provided by . + /// + /// + /// Null values are not permitted in the map, either for wrapper types or regular messages. + /// If a map is deserialized from a data stream and the value is missing from an entry, a default value + /// is created instead. For primitive types, that is the regular default value (0, the empty string and so + /// on); for message types, an empty instance of the message is created, as if the map entry contained a 0-length + /// encoded value for the field. + /// + /// + /// This implementation does not generally prohibit the use of key/value types which are not + /// supported by Protocol Buffers (e.g. using a key type of byte) but nor does it guarantee + /// that all operations will work in such cases. + /// + /// + /// The order in which entries are returned when iterating over this object is undefined, and may change + /// in future versions. + /// + /// + public sealed class MapField : IDeepCloneable>, IDictionary, IEquatable>, IDictionary +#if !NET35 + , IReadOnlyDictionary +#endif + { + private static readonly EqualityComparer ValueEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer(); + private static readonly EqualityComparer KeyEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer(); + + // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.) + private readonly Dictionary>> map = + new Dictionary>>(KeyEqualityComparer); + private readonly LinkedList> list = new LinkedList>(); + + /// + /// Creates a deep clone of this object. + /// + /// + /// A deep clone of this object. + /// + public MapField Clone() + { + var clone = new MapField(); + // Keys are never cloneable. Values might be. + if (typeof(IDeepCloneable).IsAssignableFrom(typeof(TValue))) + { + foreach (var pair in list) + { + clone.Add(pair.Key, ((IDeepCloneable)pair.Value).Clone()); + } + } + else + { + // Nothing is cloneable, so we don't need to worry. + clone.Add(this); + } + return clone; + } + + /// + /// Adds the specified key/value pair to the map. + /// + /// + /// This operation fails if the key already exists in the map. To replace an existing entry, use the indexer. + /// + /// The key to add + /// The value to add. + /// The given key already exists in map. + public void Add(TKey key, TValue value) + { + // Validation of arguments happens in ContainsKey and the indexer + if (ContainsKey(key)) + { + throw new ArgumentException("Key already exists in map", nameof(key)); + } + this[key] = value; + } + + /// + /// Determines whether the specified key is present in the map. + /// + /// The key to check. + /// true if the map contains the given key; false otherwise. + public bool ContainsKey(TKey key) + { + ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key)); + return map.ContainsKey(key); + } + + private bool ContainsValue(TValue value) => + list.Any(pair => ValueEqualityComparer.Equals(pair.Value, value)); + + /// + /// Removes the entry identified by the given key from the map. + /// + /// The key indicating the entry to remove from the map. + /// true if the map contained the given key before the entry was removed; false otherwise. + public bool Remove(TKey key) + { + ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key)); + LinkedListNode> node; + if (map.TryGetValue(key, out node)) + { + map.Remove(key); + node.List.Remove(node); + return true; + } + else + { + return false; + } + } + + /// + /// Gets the value associated with the specified key. + /// + /// The key whose value to get. + /// When this method returns, the value associated with the specified key, if the key is found; + /// otherwise, the default value for the type of the parameter. + /// This parameter is passed uninitialized. + /// true if the map contains an element with the specified key; otherwise, false. + public bool TryGetValue(TKey key, out TValue value) + { + LinkedListNode> node; + if (map.TryGetValue(key, out node)) + { + value = node.Value.Value; + return true; + } + else + { + value = default(TValue); + return false; + } + } + + /// + /// Gets or sets the value associated with the specified key. + /// + /// The key of the value to get or set. + /// The property is retrieved and key does not exist in the collection. + /// The value associated with the specified key. If the specified key is not found, + /// a get operation throws a , and a set operation creates a new element with the specified key. + public TValue this[TKey key] + { + get + { + ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key)); + TValue value; + if (TryGetValue(key, out value)) + { + return value; + } + throw new KeyNotFoundException(); + } + set + { + ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key)); + // value == null check here is redundant, but avoids boxing. + if (value == null) + { + ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value)); + } + LinkedListNode> node; + var pair = new KeyValuePair(key, value); + if (map.TryGetValue(key, out node)) + { + node.Value = pair; + } + else + { + node = list.AddLast(pair); + map[key] = node; + } + } + } + + /// + /// Gets a collection containing the keys in the map. + /// + public ICollection Keys { get { return new MapView(this, pair => pair.Key, ContainsKey); } } + + /// + /// Gets a collection containing the values in the map. + /// + public ICollection Values { get { return new MapView(this, pair => pair.Value, ContainsValue); } } + + /// + /// Adds the specified entries to the map. The keys and values are not automatically cloned. + /// + /// The entries to add to the map. + public void Add(IDictionary entries) + { + ProtoPreconditions.CheckNotNull(entries, nameof(entries)); + foreach (var pair in entries) + { + Add(pair.Key, pair.Value); + } + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// + /// An enumerator that can be used to iterate through the collection. + /// + public IEnumerator> GetEnumerator() + { + return list.GetEnumerator(); + } + + /// + /// Returns an enumerator that iterates through a collection. + /// + /// + /// An object that can be used to iterate through the collection. + /// + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// Adds the specified item to the map. + /// + /// The item to add to the map. + void ICollection>.Add(KeyValuePair item) + { + Add(item.Key, item.Value); + } + + /// + /// Removes all items from the map. + /// + public void Clear() + { + list.Clear(); + map.Clear(); + } + + /// + /// Determines whether map contains an entry equivalent to the given key/value pair. + /// + /// The key/value pair to find. + /// + bool ICollection>.Contains(KeyValuePair item) + { + TValue value; + return TryGetValue(item.Key, out value) && ValueEqualityComparer.Equals(item.Value, value); + } + + /// + /// Copies the key/value pairs in this map to an array. + /// + /// The array to copy the entries into. + /// The index of the array at which to start copying values. + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + { + list.CopyTo(array, arrayIndex); + } + + /// + /// Removes the specified key/value pair from the map. + /// + /// Both the key and the value must be found for the entry to be removed. + /// The key/value pair to remove. + /// true if the key/value pair was found and removed; false otherwise. + bool ICollection>.Remove(KeyValuePair item) + { + if (item.Key == null) + { + throw new ArgumentException("Key is null", nameof(item)); + } + LinkedListNode> node; + if (map.TryGetValue(item.Key, out node) && + EqualityComparer.Default.Equals(item.Value, node.Value.Value)) + { + map.Remove(item.Key); + node.List.Remove(node); + return true; + } + else + { + return false; + } + } + + /// + /// Gets the number of elements contained in the map. + /// + public int Count { get { return list.Count; } } + + /// + /// Gets a value indicating whether the map is read-only. + /// + public bool IsReadOnly { get { return false; } } + + /// + /// Determines whether the specified , is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object other) + { + return Equals(other as MapField); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + var keyComparer = KeyEqualityComparer; + var valueComparer = ValueEqualityComparer; + int hash = 0; + foreach (var pair in list) + { + hash ^= keyComparer.GetHashCode(pair.Key) * 31 + valueComparer.GetHashCode(pair.Value); + } + return hash; + } + + /// + /// Compares this map with another for equality. + /// + /// + /// The order of the key/value pairs in the maps is not deemed significant in this comparison. + /// + /// The map to compare this with. + /// true if refers to an equal map; false otherwise. + public bool Equals(MapField other) + { + if (other == null) + { + return false; + } + if (other == this) + { + return true; + } + if (other.Count != this.Count) + { + return false; + } + var valueComparer = ValueEqualityComparer; + foreach (var pair in this) + { + TValue value; + if (!other.TryGetValue(pair.Key, out value)) + { + return false; + } + if (!valueComparer.Equals(value, pair.Value)) + { + return false; + } + } + return true; + } + + /// + /// Adds entries to the map from the given stream. + /// + /// + /// It is assumed that the stream is initially positioned after the tag specified by the codec. + /// This method will continue reading entries from the stream until the end is reached, or + /// a different tag is encountered. + /// + /// Stream to read from + /// Codec describing how the key/value pairs are encoded + public void AddEntriesFrom(CodedInputStream input, Codec codec) + { + ParseContext.Initialize(input, out ParseContext ctx); + try + { + AddEntriesFrom(ref ctx, codec); + } + finally + { + ctx.CopyStateTo(input); + } + } + + /// + /// Adds entries to the map from the given parse context. + /// + /// + /// It is assumed that the input is initially positioned after the tag specified by the codec. + /// This method will continue reading entries from the input until the end is reached, or + /// a different tag is encountered. + /// + /// Input to read from + /// Codec describing how the key/value pairs are encoded + [SecuritySafeCritical] + public void AddEntriesFrom(ref ParseContext ctx, Codec codec) + { + do + { + KeyValuePair entry = ParsingPrimitivesMessages.ReadMapEntry(ref ctx, codec); + this[entry.Key] = entry.Value; + } while (ParsingPrimitives.MaybeConsumeTag(ref ctx.buffer, ref ctx.state, codec.MapTag)); + } + + /// + /// Writes the contents of this map to the given coded output stream, using the specified codec + /// to encode each entry. + /// + /// The output stream to write to. + /// The codec to use for each entry. + public void WriteTo(CodedOutputStream output, Codec codec) + { + WriteContext.Initialize(output, out WriteContext ctx); + try + { + WriteTo(ref ctx, codec); + } + finally + { + ctx.CopyStateTo(output); + } + } + + /// + /// Writes the contents of this map to the given write context, using the specified codec + /// to encode each entry. + /// + /// The write context to write to. + /// The codec to use for each entry. + [SecuritySafeCritical] + public void WriteTo(ref WriteContext ctx, Codec codec) + { + foreach (var entry in list) + { + ctx.WriteTag(codec.MapTag); + + WritingPrimitives.WriteLength(ref ctx.buffer, ref ctx.state, CalculateEntrySize(codec, entry)); + codec.KeyCodec.WriteTagAndValue(ref ctx, entry.Key); + codec.ValueCodec.WriteTagAndValue(ref ctx, entry.Value); + } + } + + /// + /// Calculates the size of this map based on the given entry codec. + /// + /// The codec to use to encode each entry. + /// + public int CalculateSize(Codec codec) + { + if (Count == 0) + { + return 0; + } + int size = 0; + foreach (var entry in list) + { + int entrySize = CalculateEntrySize(codec, entry); + + size += CodedOutputStream.ComputeRawVarint32Size(codec.MapTag); + size += CodedOutputStream.ComputeLengthSize(entrySize) + entrySize; + } + return size; + } + + private static int CalculateEntrySize(Codec codec, KeyValuePair entry) + { + return codec.KeyCodec.CalculateSizeWithTag(entry.Key) + codec.ValueCodec.CalculateSizeWithTag(entry.Value); + } + + /// + /// Returns a string representation of this repeated field, in the same + /// way as it would be represented by the default JSON formatter. + /// + public override string ToString() + { + var writer = new StringWriter(); + JsonFormatter.Default.WriteDictionary(writer, this); + return writer.ToString(); + } + + #region IDictionary explicit interface implementation + void IDictionary.Add(object key, object value) + { + Add((TKey)key, (TValue)value); + } + + bool IDictionary.Contains(object key) + { + if (!(key is TKey)) + { + return false; + } + return ContainsKey((TKey)key); + } + + IDictionaryEnumerator IDictionary.GetEnumerator() + { + return new DictionaryEnumerator(GetEnumerator()); + } + + void IDictionary.Remove(object key) + { + ProtoPreconditions.CheckNotNull(key, nameof(key)); + if (!(key is TKey)) + { + return; + } + Remove((TKey)key); + } + + void ICollection.CopyTo(Array array, int index) + { + // This is ugly and slow as heck, but with any luck it will never be used anyway. + ICollection temp = this.Select(pair => new DictionaryEntry(pair.Key, pair.Value)).ToList(); + temp.CopyTo(array, index); + } + + bool IDictionary.IsFixedSize { get { return false; } } + + ICollection IDictionary.Keys { get { return (ICollection)Keys; } } + + ICollection IDictionary.Values { get { return (ICollection)Values; } } + + bool ICollection.IsSynchronized { get { return false; } } + + object ICollection.SyncRoot { get { return this; } } + + object IDictionary.this[object key] + { + get + { + ProtoPreconditions.CheckNotNull(key, nameof(key)); + if (!(key is TKey)) + { + return null; + } + TValue value; + TryGetValue((TKey)key, out value); + return value; + } + + set + { + this[(TKey)key] = (TValue)value; + } + } + #endregion + + #region IReadOnlyDictionary explicit interface implementation +#if !NET35 + IEnumerable IReadOnlyDictionary.Keys => Keys; + + IEnumerable IReadOnlyDictionary.Values => Values; +#endif + #endregion + + private class DictionaryEnumerator : IDictionaryEnumerator + { + private readonly IEnumerator> enumerator; + + internal DictionaryEnumerator(IEnumerator> enumerator) + { + this.enumerator = enumerator; + } + + public bool MoveNext() + { + return enumerator.MoveNext(); + } + + public void Reset() + { + enumerator.Reset(); + } + + public object Current { get { return Entry; } } + public DictionaryEntry Entry { get { return new DictionaryEntry(Key, Value); } } + public object Key { get { return enumerator.Current.Key; } } + public object Value { get { return enumerator.Current.Value; } } + } + + /// + /// A codec for a specific map field. This contains all the information required to encode and + /// decode the nested messages. + /// + public sealed class Codec + { + private readonly FieldCodec keyCodec; + private readonly FieldCodec valueCodec; + private readonly uint mapTag; + + /// + /// Creates a new entry codec based on a separate key codec and value codec, + /// and the tag to use for each map entry. + /// + /// The key codec. + /// The value codec. + /// The map tag to use to introduce each map entry. + public Codec(FieldCodec keyCodec, FieldCodec valueCodec, uint mapTag) + { + this.keyCodec = keyCodec; + this.valueCodec = valueCodec; + this.mapTag = mapTag; + } + + /// + /// The key codec. + /// + internal FieldCodec KeyCodec => keyCodec; + + /// + /// The value codec. + /// + internal FieldCodec ValueCodec => valueCodec; + + /// + /// The tag used in the enclosing message to indicate map entries. + /// + internal uint MapTag => mapTag; + } + + private class MapView : ICollection, ICollection + { + private readonly MapField parent; + private readonly Func, T> projection; + private readonly Func containsCheck; + + internal MapView( + MapField parent, + Func, T> projection, + Func containsCheck) + { + this.parent = parent; + this.projection = projection; + this.containsCheck = containsCheck; + } + + public int Count { get { return parent.Count; } } + + public bool IsReadOnly { get { return true; } } + + public bool IsSynchronized { get { return false; } } + + public object SyncRoot { get { return parent; } } + + public void Add(T item) + { + throw new NotSupportedException(); + } + + public void Clear() + { + throw new NotSupportedException(); + } + + public bool Contains(T item) + { + return containsCheck(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + if (arrayIndex < 0) + { + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); + } + if (arrayIndex + Count > array.Length) + { + throw new ArgumentException("Not enough space in the array", nameof(array)); + } + foreach (var item in this) + { + array[arrayIndex++] = item; + } + } + + public IEnumerator GetEnumerator() + { + return parent.list.Select(projection).GetEnumerator(); + } + + public bool Remove(T item) + { + throw new NotSupportedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void CopyTo(Array array, int index) + { + if (index < 0) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + if (index + Count > array.Length) + { + throw new ArgumentException("Not enough space in the array", nameof(array)); + } + foreach (var item in this) + { + array.SetValue(item, index++); + } + } + } + } +} diff --git a/csharp/src/Google.Protobuf/Collections/ProtobufEqualityComparers.cs b/csharp/src/Google.Protobuf/Collections/ProtobufEqualityComparers.cs new file mode 100644 index 0000000000000..13ef60fca56e0 --- /dev/null +++ b/csharp/src/Google.Protobuf/Collections/ProtobufEqualityComparers.cs @@ -0,0 +1,130 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2017 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Collections.Generic; + +namespace Google.Protobuf.Collections +{ + /// + /// Provides a central place to implement equality comparisons, primarily for bitwise float/double equality. + /// + public static class ProtobufEqualityComparers + { + /// + /// Returns an equality comparer for suitable for Protobuf equality comparisons. + /// This is usually just the default equality comparer for the type, but floating point numbers are compared + /// bitwise. + /// + /// The type of equality comparer to return. + /// The equality comparer. + public static EqualityComparer GetEqualityComparer() + { + return typeof(T) == typeof(double) ? (EqualityComparer) (object) BitwiseDoubleEqualityComparer + : typeof(T) == typeof(float) ? (EqualityComparer) (object) BitwiseSingleEqualityComparer + : typeof(T) == typeof(double?) ? (EqualityComparer) (object) BitwiseNullableDoubleEqualityComparer + : typeof(T) == typeof(float?) ? (EqualityComparer) (object) BitwiseNullableSingleEqualityComparer + : EqualityComparer.Default; + } + + /// + /// Returns an equality comparer suitable for comparing 64-bit floating point values, by bitwise comparison. + /// (NaN values are considered equal, but only when they have the same representation.) + /// + public static EqualityComparer BitwiseDoubleEqualityComparer { get; } = new BitwiseDoubleEqualityComparerImpl(); + + /// + /// Returns an equality comparer suitable for comparing 32-bit floating point values, by bitwise comparison. + /// (NaN values are considered equal, but only when they have the same representation.) + /// + public static EqualityComparer BitwiseSingleEqualityComparer { get; } = new BitwiseSingleEqualityComparerImpl(); + + /// + /// Returns an equality comparer suitable for comparing nullable 64-bit floating point values, by bitwise comparison. + /// (NaN values are considered equal, but only when they have the same representation.) + /// + public static EqualityComparer BitwiseNullableDoubleEqualityComparer { get; } = new BitwiseNullableDoubleEqualityComparerImpl(); + + /// + /// Returns an equality comparer suitable for comparing nullable 32-bit floating point values, by bitwise comparison. + /// (NaN values are considered equal, but only when they have the same representation.) + /// + public static EqualityComparer BitwiseNullableSingleEqualityComparer { get; } = new BitwiseNullableSingleEqualityComparerImpl(); + + private class BitwiseDoubleEqualityComparerImpl : EqualityComparer + { + public override bool Equals(double x, double y) => + BitConverter.DoubleToInt64Bits(x) == BitConverter.DoubleToInt64Bits(y); + + public override int GetHashCode(double obj) => + BitConverter.DoubleToInt64Bits(obj).GetHashCode(); + } + + private class BitwiseSingleEqualityComparerImpl : EqualityComparer + { + // Just promote values to double and use BitConverter.DoubleToInt64Bits, + // as there's no BitConverter.SingleToInt32Bits, unfortunately. + + public override bool Equals(float x, float y) => + BitConverter.DoubleToInt64Bits(x) == BitConverter.DoubleToInt64Bits(y); + + public override int GetHashCode(float obj) => + BitConverter.DoubleToInt64Bits(obj).GetHashCode(); + } + + private class BitwiseNullableDoubleEqualityComparerImpl : EqualityComparer + { + public override bool Equals(double? x, double? y) => + x == null && y == null ? true + : x == null || y == null ? false + : BitwiseDoubleEqualityComparer.Equals(x.Value, y.Value); + + // The hash code for null is just a constant which is at least *unlikely* to be used + // elsewhere. (Compared with 0, say.) + public override int GetHashCode(double? obj) => + obj == null ? 293864 : BitwiseDoubleEqualityComparer.GetHashCode(obj.Value); + } + + private class BitwiseNullableSingleEqualityComparerImpl : EqualityComparer + { + public override bool Equals(float? x, float? y) => + x == null && y == null ? true + : x == null || y == null ? false + : BitwiseSingleEqualityComparer.Equals(x.Value, y.Value); + + // The hash code for null is just a constant which is at least *unlikely* to be used + // elsewhere. (Compared with 0, say.) + public override int GetHashCode(float? obj) => + obj == null ? 293864 : BitwiseSingleEqualityComparer.GetHashCode(obj.Value); + } + } +} diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs old mode 100755 new mode 100644 index 6063ff615848b..19114caa2475b --- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs +++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs @@ -1,594 +1,698 @@ -#region Copyright notice and license -// Protocol Buffers - Google's data interchange format -// Copyright 2015 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; - -namespace Google.Protobuf.Collections -{ - /// - /// The contents of a repeated field: essentially, a collection with some extra - /// restrictions (no null values) and capabilities (deep cloning). - /// - /// - /// This implementation does not generally prohibit the use of types which are not - /// supported by Protocol Buffers but nor does it guarantee that all operations will work in such cases. - /// - /// The element type of the repeated field. - public sealed class RepeatedField : IList, IList, IDeepCloneable>, IEquatable> -#if !NET35 - , IReadOnlyList -#endif - { - private static readonly T[] EmptyArray = new T[0]; - private const int MinArraySize = 8; - - private T[] array = EmptyArray; - private int count = 0; - - /// - /// Creates a deep clone of this repeated field. - /// - /// - /// If the field type is - /// a message type, each element is also cloned; otherwise, it is - /// assumed that the field type is primitive (including string and - /// bytes, both of which are immutable) and so a simple copy is - /// equivalent to a deep clone. - /// - /// A deep clone of this repeated field. - public RepeatedField Clone() - { - RepeatedField clone = new RepeatedField(); - if (array != EmptyArray) - { - clone.array = (T[])array.Clone(); - IDeepCloneable[] cloneableArray = clone.array as IDeepCloneable[]; - if (cloneableArray != null) - { - for (int i = 0; i < count; i++) - { - clone.array[i] = cloneableArray[i].Clone(); - } - } - } - clone.count = count; - return clone; - } - - /// - /// Adds the entries from the given input stream, decoding them with the specified codec. - /// - /// The input stream to read from. - /// The codec to use in order to read each entry. - public void AddEntriesFrom(CodedInputStream input, FieldCodec codec) - { - // TODO: Inline some of the Add code, so we can avoid checking the size on every - // iteration. - uint tag = input.LastTag; - var reader = codec.ValueReader; - // Non-nullable value types can be packed or not. - if (FieldCodec.IsPackedRepeatedField(tag)) - { - int length = input.ReadLength(); - if (length > 0) - { - int oldLimit = input.PushLimit(length); - while (!input.ReachedLimit) - { - Add(reader(input)); - } - input.PopLimit(oldLimit); - } - // Empty packed field. Odd, but valid - just ignore. - } - else - { - // Not packed... (possibly not packable) - do - { - Add(reader(input)); - } while (input.MaybeConsumeTag(tag)); - } - } - - /// - /// Calculates the size of this collection based on the given codec. - /// - /// The codec to use when encoding each field. - /// The number of bytes that would be written to a by , - /// using the same codec. - public int CalculateSize(FieldCodec codec) - { - if (count == 0) - { - return 0; - } - uint tag = codec.Tag; - if (codec.PackedRepeatedField) - { - int dataSize = CalculatePackedDataSize(codec); - return CodedOutputStream.ComputeRawVarint32Size(tag) + - CodedOutputStream.ComputeLengthSize(dataSize) + - dataSize; - } - else - { - var sizeCalculator = codec.ValueSizeCalculator; - int size = count * CodedOutputStream.ComputeRawVarint32Size(tag); - for (int i = 0; i < count; i++) - { - size += sizeCalculator(array[i]); - } - return size; - } - } - - private int CalculatePackedDataSize(FieldCodec codec) - { - int fixedSize = codec.FixedSize; - if (fixedSize == 0) - { - var calculator = codec.ValueSizeCalculator; - int tmp = 0; - for (int i = 0; i < count; i++) - { - tmp += calculator(array[i]); - } - return tmp; - } - else - { - return fixedSize * Count; - } - } - - /// - /// Writes the contents of this collection to the given , - /// encoding each value using the specified codec. - /// - /// The output stream to write to. - /// The codec to use when encoding each value. - public void WriteTo(CodedOutputStream output, FieldCodec codec) - { - if (count == 0) - { - return; - } - var writer = codec.ValueWriter; - var tag = codec.Tag; - if (codec.PackedRepeatedField) - { - // Packed primitive type - uint size = (uint)CalculatePackedDataSize(codec); - output.WriteTag(tag); - output.WriteRawVarint32(size); - for (int i = 0; i < count; i++) - { - writer(output, array[i]); - } - } - else - { - // Not packed: a simple tag/value pair for each value. - // Can't use codec.WriteTagAndValue, as that omits default values. - for (int i = 0; i < count; i++) - { - output.WriteTag(tag); - writer(output, array[i]); - } - } - } - - private void EnsureSize(int size) - { - if (array.Length < size) - { - size = Math.Max(size, MinArraySize); - int newSize = Math.Max(array.Length * 2, size); - var tmp = new T[newSize]; - Array.Copy(array, 0, tmp, 0, array.Length); - array = tmp; - } - } - - /// - /// Adds the specified item to the collection. - /// - /// The item to add. - public void Add(T item) - { - ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item)); - EnsureSize(count + 1); - array[count++] = item; - } - - /// - /// Removes all items from the collection. - /// - public void Clear() - { - array = EmptyArray; - count = 0; - } - - /// - /// Determines whether this collection contains the given item. - /// - /// The item to find. - /// true if this collection contains the given item; false otherwise. - public bool Contains(T item) - { - return IndexOf(item) != -1; - } - - /// - /// Copies this collection to the given array. - /// - /// The array to copy to. - /// The first index of the array to copy to. - public void CopyTo(T[] array, int arrayIndex) - { - Array.Copy(this.array, 0, array, arrayIndex, count); - } - - /// - /// Removes the specified item from the collection - /// - /// The item to remove. - /// true if the item was found and removed; false otherwise. - public bool Remove(T item) - { - int index = IndexOf(item); - if (index == -1) - { - return false; - } - Array.Copy(array, index + 1, array, index, count - index - 1); - count--; - array[count] = default(T); - return true; - } - - /// - /// Gets the number of elements contained in the collection. - /// - public int Count => count; - - /// - /// Gets a value indicating whether the collection is read-only. - /// - public bool IsReadOnly => false; - - /// - /// Adds all of the specified values into this collection. - /// - /// The values to add to this collection. - public void AddRange(IEnumerable values) - { - ProtoPreconditions.CheckNotNull(values, nameof(values)); - - // Optimization 1: If the collection we're adding is already a RepeatedField, - // we know the values are valid. - var otherRepeatedField = values as RepeatedField; - if (otherRepeatedField != null) - { - EnsureSize(count + otherRepeatedField.count); - Array.Copy(otherRepeatedField.array, 0, array, count, otherRepeatedField.count); - count += otherRepeatedField.count; - return; - } - - // Optimization 2: The collection is an ICollection, so we can expand - // just once and ask the collection to copy itself into the array. - var collection = values as ICollection; - if (collection != null) - { - var extraCount = collection.Count; - // For reference types and nullable value types, we need to check that there are no nulls - // present. (This isn't a thread-safe approach, but we don't advertise this is thread-safe.) - // We expect the JITter to optimize this test to true/false, so it's effectively conditional - // specialization. - if (default(T) == null) - { - // TODO: Measure whether iterating once to check and then letting the collection copy - // itself is faster or slower than iterating and adding as we go. For large - // collections this will not be great in terms of cache usage... but the optimized - // copy may be significantly faster than doing it one at a time. - foreach (var item in collection) - { - if (item == null) - { - throw new ArgumentException("Sequence contained null element", nameof(values)); - } - } - } - EnsureSize(count + extraCount); - collection.CopyTo(array, count); - count += extraCount; - return; - } - - // We *could* check for ICollection as well, but very very few collections implement - // ICollection but not ICollection. (HashSet does, for one...) - - // Fall back to a slower path of adding items one at a time. - foreach (T item in values) - { - Add(item); - } - } - - /// - /// Adds all of the specified values into this collection. This method is present to - /// allow repeated fields to be constructed from queries within collection initializers. - /// Within non-collection-initializer code, consider using the equivalent - /// method instead for clarity. - /// - /// The values to add to this collection. - public void Add(IEnumerable values) - { - AddRange(values); - } - - /// - /// Returns an enumerator that iterates through the collection. - /// - /// - /// An enumerator that can be used to iterate through the collection. - /// - public IEnumerator GetEnumerator() - { - for (int i = 0; i < count; i++) - { - yield return array[i]; - } - } - - /// - /// Determines whether the specified , is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object obj) - { - return Equals(obj as RepeatedField); - } - - /// - /// Returns an enumerator that iterates through a collection. - /// - /// - /// An object that can be used to iterate through the collection. - /// - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - int hash = 0; - for (int i = 0; i < count; i++) - { - hash = hash * 31 + array[i].GetHashCode(); - } - return hash; - } - - /// - /// Compares this repeated field with another for equality. - /// - /// The repeated field to compare this with. - /// true if refers to an equal repeated field; false otherwise. - public bool Equals(RepeatedField other) - { - if (ReferenceEquals(other, null)) - { - return false; - } - if (ReferenceEquals(other, this)) - { - return true; - } - if (other.Count != this.Count) - { - return false; - } - EqualityComparer comparer = EqualityComparer.Default; - for (int i = 0; i < count; i++) - { - if (!comparer.Equals(array[i], other.array[i])) - { - return false; - } - } - return true; - } - - /// - /// Returns the index of the given item within the collection, or -1 if the item is not - /// present. - /// - /// The item to find in the collection. - /// The zero-based index of the item, or -1 if it is not found. - public int IndexOf(T item) - { - ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item)); - EqualityComparer comparer = EqualityComparer.Default; - for (int i = 0; i < count; i++) - { - if (comparer.Equals(array[i], item)) - { - return i; - } - } - return -1; - } - - /// - /// Inserts the given item at the specified index. - /// - /// The index at which to insert the item. - /// The item to insert. - public void Insert(int index, T item) - { - ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item)); - if (index < 0 || index > count) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - EnsureSize(count + 1); - Array.Copy(array, index, array, index + 1, count - index); - array[index] = item; - count++; - } - - /// - /// Removes the item at the given index. - /// - /// The zero-based index of the item to remove. - public void RemoveAt(int index) - { - if (index < 0 || index >= count) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - Array.Copy(array, index + 1, array, index, count - index - 1); - count--; - array[count] = default(T); - } - - /// - /// Returns a string representation of this repeated field, in the same - /// way as it would be represented by the default JSON formatter. - /// - public override string ToString() - { - var writer = new StringWriter(); - JsonFormatter.Default.WriteList(writer, this); - return writer.ToString(); - } - - /// - /// Gets or sets the item at the specified index. - /// - /// - /// The element at the specified index. - /// - /// The zero-based index of the element to get or set. - /// The item at the specified index. - public T this[int index] - { - get - { - if (index < 0 || index >= count) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - return array[index]; - } - set - { - if (index < 0 || index >= count) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value)); - array[index] = value; - } - } - - #region Explicit interface implementation for IList and ICollection. - bool IList.IsFixedSize => false; - - void ICollection.CopyTo(Array array, int index) - { - Array.Copy(this.array, 0, array, index, count); - } - - bool ICollection.IsSynchronized => false; - - object ICollection.SyncRoot => this; - - object IList.this[int index] - { - get { return this[index]; } - set { this[index] = (T)value; } - } - - int IList.Add(object value) - { - Add((T) value); - return count - 1; - } - - bool IList.Contains(object value) - { - return (value is T && Contains((T)value)); - } - - int IList.IndexOf(object value) - { - if (!(value is T)) - { - return -1; - } - return IndexOf((T)value); - } - - void IList.Insert(int index, object value) - { - Insert(index, (T) value); - } - - void IList.Remove(object value) - { - if (!(value is T)) - { - return; - } - Remove((T)value); - } - #endregion - } -} +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Security; +using System.Threading; + +namespace Google.Protobuf.Collections +{ + /// + /// The contents of a repeated field: essentially, a collection with some extra + /// restrictions (no null values) and capabilities (deep cloning). + /// + /// + /// This implementation does not generally prohibit the use of types which are not + /// supported by Protocol Buffers but nor does it guarantee that all operations will work in such cases. + /// + /// The element type of the repeated field. + public sealed class RepeatedField : IList, IList, IDeepCloneable>, IEquatable> +#if !NET35 + , IReadOnlyList +#endif + { + private static readonly EqualityComparer EqualityComparer = ProtobufEqualityComparers.GetEqualityComparer(); + private static readonly T[] EmptyArray = new T[0]; + private const int MinArraySize = 8; + + private T[] array = EmptyArray; + private int count = 0; + + /// + /// Creates a deep clone of this repeated field. + /// + /// + /// If the field type is + /// a message type, each element is also cloned; otherwise, it is + /// assumed that the field type is primitive (including string and + /// bytes, both of which are immutable) and so a simple copy is + /// equivalent to a deep clone. + /// + /// A deep clone of this repeated field. + public RepeatedField Clone() + { + RepeatedField clone = new RepeatedField(); + if (array != EmptyArray) + { + clone.array = (T[])array.Clone(); + IDeepCloneable[] cloneableArray = clone.array as IDeepCloneable[]; + if (cloneableArray != null) + { + for (int i = 0; i < count; i++) + { + clone.array[i] = cloneableArray[i].Clone(); + } + } + } + clone.count = count; + return clone; + } + + /// + /// Adds the entries from the given input stream, decoding them with the specified codec. + /// + /// The input stream to read from. + /// The codec to use in order to read each entry. + public void AddEntriesFrom(CodedInputStream input, FieldCodec codec) + { + ParseContext.Initialize(input, out ParseContext ctx); + try + { + AddEntriesFrom(ref ctx, codec); + } + finally + { + ctx.CopyStateTo(input); + } + } + + /// + /// Adds the entries from the given parse context, decoding them with the specified codec. + /// + /// The input to read from. + /// The codec to use in order to read each entry. + [SecuritySafeCritical] + public void AddEntriesFrom(ref ParseContext ctx, FieldCodec codec) + { + // TODO: Inline some of the Add code, so we can avoid checking the size on every + // iteration. + uint tag = ctx.state.lastTag; + var reader = codec.ValueReader; + // Non-nullable value types can be packed or not. + if (FieldCodec.IsPackedRepeatedField(tag)) + { + int length = ctx.ReadLength(); + if (length > 0) + { + int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length); + + // If the content is fixed size then we can calculate the length + // of the repeated field and pre-initialize the underlying collection. + // + // Check that the supplied length doesn't exceed the underlying buffer. + // That prevents a malicious length from initializing a very large collection. + if (codec.FixedSize > 0 && length % codec.FixedSize == 0 && ParsingPrimitives.IsDataAvailable(ref ctx.state, length)) + { + EnsureSize(count + (length / codec.FixedSize)); + + while (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state)) + { + // Only FieldCodecs with a fixed size can reach here, and they are all known + // types that don't allow the user to specify a custom reader action. + // reader action will never return null. + array[count++] = reader(ref ctx); + } + } + else + { + // Content is variable size so add until we reach the limit. + while (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state)) + { + Add(reader(ref ctx)); + } + } + SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit); + } + // Empty packed field. Odd, but valid - just ignore. + } + else + { + // Not packed... (possibly not packable) + do + { + Add(reader(ref ctx)); + } while (ParsingPrimitives.MaybeConsumeTag(ref ctx.buffer, ref ctx.state, tag)); + } + } + + /// + /// Calculates the size of this collection based on the given codec. + /// + /// The codec to use when encoding each field. + /// The number of bytes that would be written to an output by one of the WriteTo methods, + /// using the same codec. + public int CalculateSize(FieldCodec codec) + { + if (count == 0) + { + return 0; + } + uint tag = codec.Tag; + if (codec.PackedRepeatedField) + { + int dataSize = CalculatePackedDataSize(codec); + return CodedOutputStream.ComputeRawVarint32Size(tag) + + CodedOutputStream.ComputeLengthSize(dataSize) + + dataSize; + } + else + { + var sizeCalculator = codec.ValueSizeCalculator; + int size = count * CodedOutputStream.ComputeRawVarint32Size(tag); + if (codec.EndTag != 0) + { + size += count * CodedOutputStream.ComputeRawVarint32Size(codec.EndTag); + } + for (int i = 0; i < count; i++) + { + size += sizeCalculator(array[i]); + } + return size; + } + } + + private int CalculatePackedDataSize(FieldCodec codec) + { + int fixedSize = codec.FixedSize; + if (fixedSize == 0) + { + var calculator = codec.ValueSizeCalculator; + int tmp = 0; + for (int i = 0; i < count; i++) + { + tmp += calculator(array[i]); + } + return tmp; + } + else + { + return fixedSize * Count; + } + } + + /// + /// Writes the contents of this collection to the given , + /// encoding each value using the specified codec. + /// + /// The output stream to write to. + /// The codec to use when encoding each value. + public void WriteTo(CodedOutputStream output, FieldCodec codec) + { + WriteContext.Initialize(output, out WriteContext ctx); + try + { + WriteTo(ref ctx, codec); + } + finally + { + ctx.CopyStateTo(output); + } + } + + /// + /// Writes the contents of this collection to the given write context, + /// encoding each value using the specified codec. + /// + /// The write context to write to. + /// The codec to use when encoding each value. + [SecuritySafeCritical] + public void WriteTo(ref WriteContext ctx, FieldCodec codec) + { + if (count == 0) + { + return; + } + var writer = codec.ValueWriter; + var tag = codec.Tag; + if (codec.PackedRepeatedField) + { + // Packed primitive type + int size = CalculatePackedDataSize(codec); + ctx.WriteTag(tag); + ctx.WriteLength(size); + for (int i = 0; i < count; i++) + { + writer(ref ctx, array[i]); + } + } + else + { + // Not packed: a simple tag/value pair for each value. + // Can't use codec.WriteTagAndValue, as that omits default values. + for (int i = 0; i < count; i++) + { + ctx.WriteTag(tag); + writer(ref ctx, array[i]); + if (codec.EndTag != 0) + { + ctx.WriteTag(codec.EndTag); + } + } + } + } + + /// + /// Gets and sets the capacity of the RepeatedField's internal array. WHen set, the internal array is reallocated to the given capacity. + /// The new value is less than Count -or- when Count is less than 0. + /// + public int Capacity + { + get { return array.Length; } + set + { + if (value < count) + { + throw new ArgumentOutOfRangeException("Capacity", value, + $"Cannot set Capacity to a value smaller than the current item count, {count}"); + } + + if (value >= 0 && value != array.Length) + { + SetSize(value); + } + } + } + + // May increase the size of the internal array, but will never shrink it. + private void EnsureSize(int size) + { + if (array.Length < size) + { + size = Math.Max(size, MinArraySize); + int newSize = Math.Max(array.Length * 2, size); + SetSize(newSize); + } + } + + // Sets the internal array to an exact size. + private void SetSize(int size) + { + if (size != array.Length) + { + var tmp = new T[size]; + Array.Copy(array, 0, tmp, 0, count); + array = tmp; + } + } + + /// + /// Adds the specified item to the collection. + /// + /// The item to add. + public void Add(T item) + { + ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item)); + EnsureSize(count + 1); + array[count++] = item; + } + + /// + /// Removes all items from the collection. + /// + public void Clear() + { + array = EmptyArray; + count = 0; + } + + /// + /// Determines whether this collection contains the given item. + /// + /// The item to find. + /// true if this collection contains the given item; false otherwise. + public bool Contains(T item) + { + return IndexOf(item) != -1; + } + + /// + /// Copies this collection to the given array. + /// + /// The array to copy to. + /// The first index of the array to copy to. + public void CopyTo(T[] array, int arrayIndex) + { + Array.Copy(this.array, 0, array, arrayIndex, count); + } + + /// + /// Removes the specified item from the collection + /// + /// The item to remove. + /// true if the item was found and removed; false otherwise. + public bool Remove(T item) + { + int index = IndexOf(item); + if (index == -1) + { + return false; + } + Array.Copy(array, index + 1, array, index, count - index - 1); + count--; + array[count] = default(T); + return true; + } + + /// + /// Gets the number of elements contained in the collection. + /// + public int Count => count; + + /// + /// Gets a value indicating whether the collection is read-only. + /// + public bool IsReadOnly => false; + + /// + /// Adds all of the specified values into this collection. + /// + /// The values to add to this collection. + public void AddRange(IEnumerable values) + { + ProtoPreconditions.CheckNotNull(values, nameof(values)); + + // Optimization 1: If the collection we're adding is already a RepeatedField, + // we know the values are valid. + var otherRepeatedField = values as RepeatedField; + if (otherRepeatedField != null) + { + EnsureSize(count + otherRepeatedField.count); + Array.Copy(otherRepeatedField.array, 0, array, count, otherRepeatedField.count); + count += otherRepeatedField.count; + return; + } + + // Optimization 2: The collection is an ICollection, so we can expand + // just once and ask the collection to copy itself into the array. + var collection = values as ICollection; + if (collection != null) + { + var extraCount = collection.Count; + // For reference types and nullable value types, we need to check that there are no nulls + // present. (This isn't a thread-safe approach, but we don't advertise this is thread-safe.) + // We expect the JITter to optimize this test to true/false, so it's effectively conditional + // specialization. + if (default(T) == null) + { + // TODO: Measure whether iterating once to check and then letting the collection copy + // itself is faster or slower than iterating and adding as we go. For large + // collections this will not be great in terms of cache usage... but the optimized + // copy may be significantly faster than doing it one at a time. + foreach (var item in collection) + { + if (item == null) + { + throw new ArgumentException("Sequence contained null element", nameof(values)); + } + } + } + EnsureSize(count + extraCount); + collection.CopyTo(array, count); + count += extraCount; + return; + } + + // We *could* check for ICollection as well, but very very few collections implement + // ICollection but not ICollection. (HashSet does, for one...) + + // Fall back to a slower path of adding items one at a time. + foreach (T item in values) + { + Add(item); + } + } + + /// + /// Adds all of the specified values into this collection. This method is present to + /// allow repeated fields to be constructed from queries within collection initializers. + /// Within non-collection-initializer code, consider using the equivalent + /// method instead for clarity. + /// + /// The values to add to this collection. + public void Add(IEnumerable values) + { + AddRange(values); + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// + /// An enumerator that can be used to iterate through the collection. + /// + public IEnumerator GetEnumerator() + { + for (int i = 0; i < count; i++) + { + yield return array[i]; + } + } + + /// + /// Determines whether the specified , is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object obj) + { + return Equals(obj as RepeatedField); + } + + /// + /// Returns an enumerator that iterates through a collection. + /// + /// + /// An object that can be used to iterate through the collection. + /// + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + int hash = 0; + for (int i = 0; i < count; i++) + { + hash = hash * 31 + array[i].GetHashCode(); + } + return hash; + } + + /// + /// Compares this repeated field with another for equality. + /// + /// The repeated field to compare this with. + /// true if refers to an equal repeated field; false otherwise. + public bool Equals(RepeatedField other) + { + if (ReferenceEquals(other, null)) + { + return false; + } + if (ReferenceEquals(other, this)) + { + return true; + } + if (other.Count != this.Count) + { + return false; + } + EqualityComparer comparer = EqualityComparer; + for (int i = 0; i < count; i++) + { + if (!comparer.Equals(array[i], other.array[i])) + { + return false; + } + } + return true; + } + + /// + /// Returns the index of the given item within the collection, or -1 if the item is not + /// present. + /// + /// The item to find in the collection. + /// The zero-based index of the item, or -1 if it is not found. + public int IndexOf(T item) + { + ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item)); + EqualityComparer comparer = EqualityComparer; + for (int i = 0; i < count; i++) + { + if (comparer.Equals(array[i], item)) + { + return i; + } + } + return -1; + } + + /// + /// Inserts the given item at the specified index. + /// + /// The index at which to insert the item. + /// The item to insert. + public void Insert(int index, T item) + { + ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item)); + if (index < 0 || index > count) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + EnsureSize(count + 1); + Array.Copy(array, index, array, index + 1, count - index); + array[index] = item; + count++; + } + + /// + /// Removes the item at the given index. + /// + /// The zero-based index of the item to remove. + public void RemoveAt(int index) + { + if (index < 0 || index >= count) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + Array.Copy(array, index + 1, array, index, count - index - 1); + count--; + array[count] = default(T); + } + + /// + /// Returns a string representation of this repeated field, in the same + /// way as it would be represented by the default JSON formatter. + /// + public override string ToString() + { + var writer = new StringWriter(); + JsonFormatter.Default.WriteList(writer, this); + return writer.ToString(); + } + + /// + /// Gets or sets the item at the specified index. + /// + /// + /// The element at the specified index. + /// + /// The zero-based index of the element to get or set. + /// The item at the specified index. + public T this[int index] + { + get + { + if (index < 0 || index >= count) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + return array[index]; + } + set + { + if (index < 0 || index >= count) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value)); + array[index] = value; + } + } + + #region Explicit interface implementation for IList and ICollection. + bool IList.IsFixedSize => false; + + void ICollection.CopyTo(Array array, int index) + { + Array.Copy(this.array, 0, array, index, count); + } + + bool ICollection.IsSynchronized => false; + + object ICollection.SyncRoot => this; + + object IList.this[int index] + { + get { return this[index]; } + set { this[index] = (T)value; } + } + + int IList.Add(object value) + { + Add((T) value); + return count - 1; + } + + bool IList.Contains(object value) + { + return (value is T && Contains((T)value)); + } + + int IList.IndexOf(object value) + { + if (!(value is T)) + { + return -1; + } + return IndexOf((T)value); + } + + void IList.Insert(int index, object value) + { + Insert(index, (T) value); + } + + void IList.Remove(object value) + { + if (!(value is T)) + { + return; + } + Remove((T)value); + } + #endregion + } +} diff --git a/csharp/src/Google.Protobuf/Compatibility/MethodInfoExtensions.cs b/csharp/src/Google.Protobuf/Compatibility/MethodInfoExtensions.cs new file mode 100644 index 0000000000000..7b946cb631fab --- /dev/null +++ b/csharp/src/Google.Protobuf/Compatibility/MethodInfoExtensions.cs @@ -0,0 +1,47 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2017 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +#if NET35 +using System; +using System.Reflection; + +namespace Google.Protobuf.Compatibility +{ + // .NET Core (at least netstandard1.0) doesn't have Delegate.CreateDelegate, and .NET 3.5 doesn't have + // MethodInfo.CreateDelegate. Proxy from one to the other on .NET 3.5... + internal static class MethodInfoExtensions + { + internal static Delegate CreateDelegate(this MethodInfo method, Type type) => + Delegate.CreateDelegate(type, method); + } +} +#endif diff --git a/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs b/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs old mode 100755 new mode 100644 diff --git a/csharp/src/Google.Protobuf/Compatibility/StreamExtensions.cs b/csharp/src/Google.Protobuf/Compatibility/StreamExtensions.cs old mode 100755 new mode 100644 diff --git a/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs b/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs old mode 100755 new mode 100644 diff --git a/csharp/src/Google.Protobuf/Extension.cs b/csharp/src/Google.Protobuf/Extension.cs new file mode 100644 index 0000000000000..6dd1ceaa8ee13 --- /dev/null +++ b/csharp/src/Google.Protobuf/Extension.cs @@ -0,0 +1,119 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; + +namespace Google.Protobuf +{ + /// + /// Represents a non-generic extension definition. This API is experimental and subject to change. + /// + public abstract class Extension + { + internal abstract Type TargetType { get; } + + /// + /// Internal use. Creates a new extension with the specified field number. + /// + protected Extension(int fieldNumber) + { + FieldNumber = fieldNumber; + } + + internal abstract IExtensionValue CreateValue(); + + /// + /// Gets the field number of this extension + /// + public int FieldNumber { get; } + + internal abstract bool IsRepeated { get; } + } + + /// + /// Represents a type-safe extension identifier used for getting and setting single extension values in instances. + /// This API is experimental and subject to change. + /// + /// The message type this field applies to + /// The field value type of this extension + public sealed class Extension : Extension where TTarget : IExtendableMessage + { + private readonly FieldCodec codec; + + /// + /// Creates a new extension identifier with the specified field number and codec + /// + public Extension(int fieldNumber, FieldCodec codec) : base(fieldNumber) + { + this.codec = codec; + } + + internal TValue DefaultValue => codec.DefaultValue; + + internal override Type TargetType => typeof(TTarget); + + internal override bool IsRepeated => false; + + internal override IExtensionValue CreateValue() + { + return new ExtensionValue(codec); + } + } + + /// + /// Represents a type-safe extension identifier used for getting repeated extension values in instances. + /// This API is experimental and subject to change. + /// + /// The message type this field applies to + /// The repeated field value type of this extension + public sealed class RepeatedExtension : Extension where TTarget : IExtendableMessage + { + private readonly FieldCodec codec; + + /// + /// Creates a new repeated extension identifier with the specified field number and codec + /// + public RepeatedExtension(int fieldNumber, FieldCodec codec) : base(fieldNumber) + { + this.codec = codec; + } + + internal override Type TargetType => typeof(TTarget); + + internal override bool IsRepeated => true; + + internal override IExtensionValue CreateValue() + { + return new RepeatedExtensionValue(codec); + } + } +} diff --git a/csharp/src/Google.Protobuf/ExtensionRegistry.cs b/csharp/src/Google.Protobuf/ExtensionRegistry.cs new file mode 100644 index 0000000000000..e72314b22c299 --- /dev/null +++ b/csharp/src/Google.Protobuf/ExtensionRegistry.cs @@ -0,0 +1,184 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Google.Protobuf +{ + /// + /// Provides extensions to messages while parsing. This API is experimental and subject to change. + /// + public sealed class ExtensionRegistry : ICollection, IDeepCloneable + { + internal sealed class ExtensionComparer : IEqualityComparer + { + public bool Equals(Extension a, Extension b) + { + return new ObjectIntPair(a.TargetType, a.FieldNumber).Equals(new ObjectIntPair(b.TargetType, b.FieldNumber)); + } + public int GetHashCode(Extension a) + { + return new ObjectIntPair(a.TargetType, a.FieldNumber).GetHashCode(); + } + + internal static ExtensionComparer Instance = new ExtensionComparer(); + } + private IDictionary, Extension> extensions; + + /// + /// Creates a new empty extension registry + /// + public ExtensionRegistry() + { + extensions = new Dictionary, Extension>(); + } + + private ExtensionRegistry(IDictionary, Extension> collection) + { + extensions = collection.ToDictionary(k => k.Key, v => v.Value); + } + + /// + /// Gets the total number of extensions in this extension registry + /// + public int Count => extensions.Count; + + /// + /// Returns whether the registry is readonly + /// + bool ICollection.IsReadOnly => false; + + internal bool ContainsInputField(uint lastTag, Type target, out Extension extension) + { + return extensions.TryGetValue(new ObjectIntPair(target, WireFormat.GetTagFieldNumber(lastTag)), out extension); + } + + /// + /// Adds the specified extension to the registry + /// + public void Add(Extension extension) + { + ProtoPreconditions.CheckNotNull(extension, nameof(extension)); + + extensions.Add(new ObjectIntPair(extension.TargetType, extension.FieldNumber), extension); + } + + /// + /// Adds the specified extensions to the registry + /// + public void AddRange(IEnumerable extensions) + { + ProtoPreconditions.CheckNotNull(extensions, nameof(extensions)); + + foreach (var extension in extensions) + { + Add(extension); + } + } + + /// + /// Clears the registry of all values + /// + public void Clear() + { + extensions.Clear(); + } + + /// + /// Gets whether the extension registry contains the specified extension + /// + public bool Contains(Extension item) + { + ProtoPreconditions.CheckNotNull(item, nameof(item)); + + return extensions.ContainsKey(new ObjectIntPair(item.TargetType, item.FieldNumber)); + } + + /// + /// Copies the arrays in the registry set to the specified array at the specified index + /// + /// The array to copy to + /// The array index to start at + void ICollection.CopyTo(Extension[] array, int arrayIndex) + { + ProtoPreconditions.CheckNotNull(array, nameof(array)); + if (arrayIndex < 0 || arrayIndex >= array.Length) + { + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); + } + if (array.Length - arrayIndex < Count) + { + throw new ArgumentException("The provided array is shorter than the number of elements in the registry"); + } + + for (int i = 0; i < array.Length; i++) + { + Extension extension = array[i]; + extensions.Add(new ObjectIntPair(extension.TargetType, extension.FieldNumber), extension); + } + } + + /// + /// Returns an enumerator to enumerate through the items in the registry + /// + /// Returns an enumerator for the extensions in this registry + public IEnumerator GetEnumerator() + { + return extensions.Values.GetEnumerator(); + } + + /// + /// Removes the specified extension from the set + /// + /// The extension + /// true if the extension was removed, otherwise false + public bool Remove(Extension item) + { + ProtoPreconditions.CheckNotNull(item, nameof(item)); + + return extensions.Remove(new ObjectIntPair(item.TargetType, item.FieldNumber)); + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + /// + /// Clones the registry into a new registry + /// + public ExtensionRegistry Clone() + { + return new ExtensionRegistry(extensions); + } + } +} diff --git a/csharp/src/Google.Protobuf/ExtensionSet.cs b/csharp/src/Google.Protobuf/ExtensionSet.cs new file mode 100644 index 0000000000000..895b9ae6ea4a8 --- /dev/null +++ b/csharp/src/Google.Protobuf/ExtensionSet.cs @@ -0,0 +1,377 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using Google.Protobuf.Collections; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security; + +namespace Google.Protobuf +{ + /// + /// Methods for managing s with null checking. + /// + /// Most users will not use this class directly and its API is experimental and subject to change. + /// + public static class ExtensionSet + { + private static bool TryGetValue(ref ExtensionSet set, Extension extension, out IExtensionValue value) where TTarget : IExtendableMessage + { + if (set == null) + { + value = null; + return false; + } + return set.ValuesByNumber.TryGetValue(extension.FieldNumber, out value); + } + + /// + /// Gets the value of the specified extension + /// + public static TValue Get(ref ExtensionSet set, Extension extension) where TTarget : IExtendableMessage + { + IExtensionValue value; + if (TryGetValue(ref set, extension, out value)) + { + return ((ExtensionValue)value).GetValue(); + } + else + { + return extension.DefaultValue; + } + } + + /// + /// Gets the value of the specified repeated extension or null if it doesn't exist in this set + /// + public static RepeatedField Get(ref ExtensionSet set, RepeatedExtension extension) where TTarget : IExtendableMessage + { + IExtensionValue value; + if (TryGetValue(ref set, extension, out value)) + { + return ((RepeatedExtensionValue)value).GetValue(); + } + else + { + return null; + } + } + + /// + /// Gets the value of the specified repeated extension, registering it if it doesn't exist + /// + public static RepeatedField GetOrInitialize(ref ExtensionSet set, RepeatedExtension extension) where TTarget : IExtendableMessage + { + IExtensionValue value; + if (set == null) + { + value = extension.CreateValue(); + set = new ExtensionSet(); + set.ValuesByNumber.Add(extension.FieldNumber, value); + } + else + { + if (!set.ValuesByNumber.TryGetValue(extension.FieldNumber, out value)) + { + value = extension.CreateValue(); + set.ValuesByNumber.Add(extension.FieldNumber, value); + } + } + + return ((RepeatedExtensionValue)value).GetValue(); + } + + /// + /// Sets the value of the specified extension. This will make a new instance of ExtensionSet if the set is null. + /// + public static void Set(ref ExtensionSet set, Extension extension, TValue value) where TTarget : IExtendableMessage + { + ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value)); + + IExtensionValue extensionValue; + if (set == null) + { + extensionValue = extension.CreateValue(); + set = new ExtensionSet(); + set.ValuesByNumber.Add(extension.FieldNumber, extensionValue); + } + else + { + if (!set.ValuesByNumber.TryGetValue(extension.FieldNumber, out extensionValue)) + { + extensionValue = extension.CreateValue(); + set.ValuesByNumber.Add(extension.FieldNumber, extensionValue); + } + } + + ((ExtensionValue)extensionValue).SetValue(value); + } + + /// + /// Gets whether the value of the specified extension is set + /// + public static bool Has(ref ExtensionSet set, Extension extension) where TTarget : IExtendableMessage + { + IExtensionValue value; + return TryGetValue(ref set, extension, out value); + } + + /// + /// Clears the value of the specified extension + /// + public static void Clear(ref ExtensionSet set, Extension extension) where TTarget : IExtendableMessage + { + if (set == null) + { + return; + } + set.ValuesByNumber.Remove(extension.FieldNumber); + if (set.ValuesByNumber.Count == 0) + { + set = null; + } + } + + /// + /// Clears the value of the specified extension + /// + public static void Clear(ref ExtensionSet set, RepeatedExtension extension) where TTarget : IExtendableMessage + { + if (set == null) + { + return; + } + set.ValuesByNumber.Remove(extension.FieldNumber); + if (set.ValuesByNumber.Count == 0) + { + set = null; + } + } + + /// + /// Tries to merge a field from the coded input, returning true if the field was merged. + /// If the set is null or the field was not otherwise merged, this returns false. + /// + public static bool TryMergeFieldFrom(ref ExtensionSet set, CodedInputStream stream) where TTarget : IExtendableMessage + { + ParseContext.Initialize(stream, out ParseContext ctx); + try + { + return TryMergeFieldFrom(ref set, ref ctx); + } + finally + { + ctx.CopyStateTo(stream); + } + } + + /// + /// Tries to merge a field from the coded input, returning true if the field was merged. + /// If the set is null or the field was not otherwise merged, this returns false. + /// + public static bool TryMergeFieldFrom(ref ExtensionSet set, ref ParseContext ctx) where TTarget : IExtendableMessage + { + Extension extension; + int lastFieldNumber = WireFormat.GetTagFieldNumber(ctx.LastTag); + + IExtensionValue extensionValue; + if (set != null && set.ValuesByNumber.TryGetValue(lastFieldNumber, out extensionValue)) + { + extensionValue.MergeFrom(ref ctx); + return true; + } + else if (ctx.ExtensionRegistry != null && ctx.ExtensionRegistry.ContainsInputField(ctx.LastTag, typeof(TTarget), out extension)) + { + IExtensionValue value = extension.CreateValue(); + value.MergeFrom(ref ctx); + set = (set ?? new ExtensionSet()); + set.ValuesByNumber.Add(extension.FieldNumber, value); + return true; + } + else + { + return false; + } + } + + /// + /// Merges the second set into the first set, creating a new instance if first is null + /// + public static void MergeFrom(ref ExtensionSet first, ExtensionSet second) where TTarget : IExtendableMessage + { + if (second == null) + { + return; + } + if (first == null) + { + first = new ExtensionSet(); + } + foreach (var pair in second.ValuesByNumber) + { + IExtensionValue value; + if (first.ValuesByNumber.TryGetValue(pair.Key, out value)) + { + value.MergeFrom(pair.Value); + } + else + { + var cloned = pair.Value.Clone(); + first.ValuesByNumber[pair.Key] = cloned; + } + } + } + + /// + /// Clones the set into a new set. If the set is null, this returns null + /// + public static ExtensionSet Clone(ExtensionSet set) where TTarget : IExtendableMessage + { + if (set == null) + { + return null; + } + + var newSet = new ExtensionSet(); + foreach (var pair in set.ValuesByNumber) + { + var cloned = pair.Value.Clone(); + newSet.ValuesByNumber[pair.Key] = cloned; + } + return newSet; + } + } + + /// + /// Used for keeping track of extensions in messages. + /// methods route to this set. + /// + /// Most users will not need to use this class directly + /// + /// The message type that extensions in this set target + public sealed class ExtensionSet where TTarget : IExtendableMessage + { + internal Dictionary ValuesByNumber { get; } = new Dictionary(); + + /// + /// Gets a hash code of the set + /// + public override int GetHashCode() + { + int ret = typeof(TTarget).GetHashCode(); + foreach (KeyValuePair field in ValuesByNumber) + { + // Use ^ here to make the field order irrelevant. + int hash = field.Key.GetHashCode() ^ field.Value.GetHashCode(); + ret ^= hash; + } + return ret; + } + + /// + /// Returns whether this set is equal to the other object + /// + public override bool Equals(object other) + { + if (ReferenceEquals(this, other)) + { + return true; + } + ExtensionSet otherSet = other as ExtensionSet; + if (ValuesByNumber.Count != otherSet.ValuesByNumber.Count) + { + return false; + } + foreach (var pair in ValuesByNumber) + { + IExtensionValue secondValue; + if (!otherSet.ValuesByNumber.TryGetValue(pair.Key, out secondValue)) + { + return false; + } + if (!pair.Value.Equals(secondValue)) + { + return false; + } + } + return true; + } + + /// + /// Calculates the size of this extension set + /// + public int CalculateSize() + { + int size = 0; + foreach (var value in ValuesByNumber.Values) + { + size += value.CalculateSize(); + } + return size; + } + + /// + /// Writes the extension values in this set to the output stream + /// + public void WriteTo(CodedOutputStream stream) + { + + WriteContext.Initialize(stream, out WriteContext ctx); + try + { + WriteTo(ref ctx); + } + finally + { + ctx.CopyStateTo(stream); + } + } + + /// + /// Writes the extension values in this set to the write context + /// + [SecuritySafeCritical] + public void WriteTo(ref WriteContext ctx) + { + foreach (var value in ValuesByNumber.Values) + { + value.WriteTo(ref ctx); + } + } + + internal bool IsInitialized() + { + return ValuesByNumber.Values.All(v => v.IsInitialized()); + } + } +} diff --git a/csharp/src/Google.Protobuf/ExtensionValue.cs b/csharp/src/Google.Protobuf/ExtensionValue.cs new file mode 100644 index 0000000000000..5257c4c955755 --- /dev/null +++ b/csharp/src/Google.Protobuf/ExtensionValue.cs @@ -0,0 +1,225 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using Google.Protobuf.Collections; +using System; +using System.Linq; + +namespace Google.Protobuf +{ + internal interface IExtensionValue : IEquatable, IDeepCloneable + { + void MergeFrom(ref ParseContext ctx); + + void MergeFrom(IExtensionValue value); + void WriteTo(ref WriteContext ctx); + int CalculateSize(); + bool IsInitialized(); + } + + internal sealed class ExtensionValue : IExtensionValue + { + private T field; + private FieldCodec codec; + + internal ExtensionValue(FieldCodec codec) + { + this.codec = codec; + field = codec.DefaultValue; + } + + public int CalculateSize() + { + return codec.CalculateUnconditionalSizeWithTag(field); + } + + public IExtensionValue Clone() + { + return new ExtensionValue(codec) + { + field = field is IDeepCloneable ? (field as IDeepCloneable).Clone() : field + }; + } + + public bool Equals(IExtensionValue other) + { + if (ReferenceEquals(this, other)) + return true; + + return other is ExtensionValue + && codec.Equals((other as ExtensionValue).codec) + && Equals(field, (other as ExtensionValue).field); + // we check for equality in the codec since we could have equal field values however the values could be written in different ways + } + + public override int GetHashCode() + { + unchecked + { + int hash = 17; + hash = hash * 31 + field.GetHashCode(); + hash = hash * 31 + codec.GetHashCode(); + return hash; + } + } + + public void MergeFrom(ref ParseContext ctx) + { + codec.ValueMerger(ref ctx, ref field); + } + + public void MergeFrom(IExtensionValue value) + { + if (value is ExtensionValue) + { + var extensionValue = value as ExtensionValue; + codec.FieldMerger(ref field, extensionValue.field); + } + } + + public void WriteTo(ref WriteContext ctx) + { + ctx.WriteTag(codec.Tag); + codec.ValueWriter(ref ctx, field); + if (codec.EndTag != 0) + { + ctx.WriteTag(codec.EndTag); + } + } + + public T GetValue() => field; + + public void SetValue(T value) + { + field = value; + } + + public bool IsInitialized() + { + if (field is IMessage) + { + return (field as IMessage).IsInitialized(); + } + else + { + return true; + } + } + } + + internal sealed class RepeatedExtensionValue : IExtensionValue + { + private RepeatedField field; + private readonly FieldCodec codec; + + internal RepeatedExtensionValue(FieldCodec codec) + { + this.codec = codec; + field = new RepeatedField(); + } + + public int CalculateSize() + { + return field.CalculateSize(codec); + } + + public IExtensionValue Clone() + { + return new RepeatedExtensionValue(codec) + { + field = field.Clone() + }; + } + + public bool Equals(IExtensionValue other) + { + if (ReferenceEquals(this, other)) + return true; + + return other is RepeatedExtensionValue + && field.Equals((other as RepeatedExtensionValue).field) + && codec.Equals((other as RepeatedExtensionValue).codec); + } + + public override int GetHashCode() + { + unchecked + { + int hash = 17; + hash = hash * 31 + field.GetHashCode(); + hash = hash * 31 + codec.GetHashCode(); + return hash; + } + } + + public void MergeFrom(ref ParseContext ctx) + { + field.AddEntriesFrom(ref ctx, codec); + } + + public void MergeFrom(IExtensionValue value) + { + if (value is RepeatedExtensionValue) + { + field.Add((value as RepeatedExtensionValue).field); + } + } + + public void WriteTo(ref WriteContext ctx) + { + field.WriteTo(ref ctx, codec); + } + + public RepeatedField GetValue() => field; + + public bool IsInitialized() + { + for (int i = 0; i < field.Count; i++) + { + var element = field[i]; + if (element is IMessage) + { + if (!(element as IMessage).IsInitialized()) + { + return false; + } + } + else + { + break; + } + } + + return true; + } + } +} diff --git a/csharp/src/Google.Protobuf/FieldCodec.cs b/csharp/src/Google.Protobuf/FieldCodec.cs index c28b47e1eb76f..ee6bd6a0ebe38 100644 --- a/csharp/src/Google.Protobuf/FieldCodec.cs +++ b/csharp/src/Google.Protobuf/FieldCodec.cs @@ -30,10 +30,12 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Collections; using Google.Protobuf.Compatibility; using Google.Protobuf.WellKnownTypes; using System; using System.Collections.Generic; +using System.Security; namespace Google.Protobuf { @@ -51,7 +53,7 @@ public static class FieldCodec /// A codec for the given tag. public static FieldCodec ForString(uint tag) { - return new FieldCodec(input => input.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag); + return FieldCodec.ForString(tag, ""); } /// @@ -61,7 +63,7 @@ public static FieldCodec ForString(uint tag) /// A codec for the given tag. public static FieldCodec ForBytes(uint tag) { - return new FieldCodec(input => input.ReadBytes(), (output, value) => output.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag); + return FieldCodec.ForBytes(tag, ByteString.Empty); } /// @@ -71,7 +73,7 @@ public static FieldCodec ForBytes(uint tag) /// A codec for the given tag. public static FieldCodec ForBool(uint tag) { - return new FieldCodec(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.ComputeBoolSize, tag); + return FieldCodec.ForBool(tag, false); } /// @@ -81,7 +83,7 @@ public static FieldCodec ForBool(uint tag) /// A codec for the given tag. public static FieldCodec ForInt32(uint tag) { - return new FieldCodec(input => input.ReadInt32(), (output, value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag); + return FieldCodec.ForInt32(tag, 0); } /// @@ -91,7 +93,7 @@ public static FieldCodec ForInt32(uint tag) /// A codec for the given tag. public static FieldCodec ForSInt32(uint tag) { - return new FieldCodec(input => input.ReadSInt32(), (output, value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag); + return FieldCodec.ForSInt32(tag, 0); } /// @@ -101,7 +103,7 @@ public static FieldCodec ForSInt32(uint tag) /// A codec for the given tag. public static FieldCodec ForFixed32(uint tag) { - return new FieldCodec(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag); + return FieldCodec.ForFixed32(tag, 0); } /// @@ -111,7 +113,7 @@ public static FieldCodec ForFixed32(uint tag) /// A codec for the given tag. public static FieldCodec ForSFixed32(uint tag) { - return new FieldCodec(input => input.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), 4, tag); + return FieldCodec.ForSFixed32(tag, 0); } /// @@ -121,7 +123,7 @@ public static FieldCodec ForSFixed32(uint tag) /// A codec for the given tag. public static FieldCodec ForUInt32(uint tag) { - return new FieldCodec(input => input.ReadUInt32(), (output, value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag); + return FieldCodec.ForUInt32(tag, 0); } /// @@ -131,7 +133,7 @@ public static FieldCodec ForUInt32(uint tag) /// A codec for the given tag. public static FieldCodec ForInt64(uint tag) { - return new FieldCodec(input => input.ReadInt64(), (output, value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag); + return FieldCodec.ForInt64(tag, 0); } /// @@ -141,7 +143,7 @@ public static FieldCodec ForInt64(uint tag) /// A codec for the given tag. public static FieldCodec ForSInt64(uint tag) { - return new FieldCodec(input => input.ReadSInt64(), (output, value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag); + return FieldCodec.ForSInt64(tag, 0); } /// @@ -151,7 +153,7 @@ public static FieldCodec ForSInt64(uint tag) /// A codec for the given tag. public static FieldCodec ForFixed64(uint tag) { - return new FieldCodec(input => input.ReadFixed64(), (output, value) => output.WriteFixed64(value), 8, tag); + return FieldCodec.ForFixed64(tag, 0); } /// @@ -161,7 +163,7 @@ public static FieldCodec ForFixed64(uint tag) /// A codec for the given tag. public static FieldCodec ForSFixed64(uint tag) { - return new FieldCodec(input => input.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), 8, tag); + return FieldCodec.ForSFixed64(tag, 0); } /// @@ -171,7 +173,7 @@ public static FieldCodec ForSFixed64(uint tag) /// A codec for the given tag. public static FieldCodec ForUInt64(uint tag) { - return new FieldCodec(input => input.ReadUInt64(), (output, value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag); + return FieldCodec.ForUInt64(tag, 0); } /// @@ -181,7 +183,7 @@ public static FieldCodec ForUInt64(uint tag) /// A codec for the given tag. public static FieldCodec ForFloat(uint tag) { - return new FieldCodec(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.ComputeFloatSize, tag); + return FieldCodec.ForFloat(tag, 0); } /// @@ -191,7 +193,7 @@ public static FieldCodec ForFloat(uint tag) /// A codec for the given tag. public static FieldCodec ForDouble(uint tag) { - return new FieldCodec(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.ComputeDoubleSize, tag); + return FieldCodec.ForDouble(tag, 0); } // Enums are tricky. We can probably use expression trees to build these delegates automatically, @@ -206,10 +208,191 @@ public static FieldCodec ForDouble(uint tag) /// A codec for the given tag. public static FieldCodec ForEnum(uint tag, Func toInt32, Func fromInt32) { - return new FieldCodec(input => fromInt32( - input.ReadEnum()), - (output, value) => output.WriteEnum(toInt32(value)), - value => CodedOutputStream.ComputeEnumSize(toInt32(value)), tag); + return FieldCodec.ForEnum(tag, toInt32, fromInt32, default(T)); + } + + /// + /// Retrieves a codec suitable for a string field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForString(uint tag, string defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadString(), (ref WriteContext ctx, string value) => ctx.WriteString(value), CodedOutputStream.ComputeStringSize, tag, defaultValue); + } + + /// + /// Retrieves a codec suitable for a bytes field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForBytes(uint tag, ByteString defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadBytes(), (ref WriteContext ctx, ByteString value) => ctx.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag, defaultValue); + } + + /// + /// Retrieves a codec suitable for a bool field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForBool(uint tag, bool defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadBool(), (ref WriteContext ctx, bool value) => ctx.WriteBool(value), CodedOutputStream.BoolSize, tag, defaultValue); + } + + /// + /// Retrieves a codec suitable for an int32 field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForInt32(uint tag, int defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadInt32(), (ref WriteContext output, int value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag, defaultValue); + } + + /// + /// Retrieves a codec suitable for an sint32 field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForSInt32(uint tag, int defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadSInt32(), (ref WriteContext output, int value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag, defaultValue); + } + + /// + /// Retrieves a codec suitable for a fixed32 field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForFixed32(uint tag, uint defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadFixed32(), (ref WriteContext output, uint value) => output.WriteFixed32(value), 4, tag, defaultValue); + } + + /// + /// Retrieves a codec suitable for an sfixed32 field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForSFixed32(uint tag, int defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadSFixed32(), (ref WriteContext output, int value) => output.WriteSFixed32(value), 4, tag, defaultValue); + } + + /// + /// Retrieves a codec suitable for a uint32 field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForUInt32(uint tag, uint defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadUInt32(), (ref WriteContext output, uint value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag, defaultValue); + } + + /// + /// Retrieves a codec suitable for an int64 field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForInt64(uint tag, long defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadInt64(), (ref WriteContext output, long value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag, defaultValue); + } + + /// + /// Retrieves a codec suitable for an sint64 field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForSInt64(uint tag, long defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadSInt64(), (ref WriteContext output, long value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag, defaultValue); + } + + /// + /// Retrieves a codec suitable for a fixed64 field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForFixed64(uint tag, ulong defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadFixed64(), (ref WriteContext output, ulong value) => output.WriteFixed64(value), 8, tag, defaultValue); + } + + /// + /// Retrieves a codec suitable for an sfixed64 field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForSFixed64(uint tag, long defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadSFixed64(), (ref WriteContext output, long value) => output.WriteSFixed64(value), 8, tag, defaultValue); + } + + /// + /// Retrieves a codec suitable for a uint64 field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForUInt64(uint tag, ulong defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadUInt64(), (ref WriteContext output, ulong value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag, defaultValue); + } + + /// + /// Retrieves a codec suitable for a float field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForFloat(uint tag, float defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadFloat(), (ref WriteContext output, float value) => output.WriteFloat(value), CodedOutputStream.FloatSize, tag, defaultValue); + } + + /// + /// Retrieves a codec suitable for a double field with the given tag. + /// + /// The tag. + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForDouble(uint tag, double defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => ctx.ReadDouble(), (ref WriteContext output, double value) => output.WriteDouble(value), CodedOutputStream.DoubleSize, tag, defaultValue); + } + + // Enums are tricky. We can probably use expression trees to build these delegates automatically, + // but it's easy to generate the code for it. + + /// + /// Retrieves a codec suitable for an enum field with the given tag. + /// + /// The tag. + /// A conversion function from to the enum type. + /// A conversion function from the enum type to . + /// The default value. + /// A codec for the given tag. + public static FieldCodec ForEnum(uint tag, Func toInt32, Func fromInt32, T defaultValue) + { + return new FieldCodec((ref ParseContext ctx) => fromInt32( + ctx.ReadEnum()), + (ref WriteContext output, T value) => output.WriteEnum(toInt32(value)), + value => CodedOutputStream.ComputeEnumSize(toInt32(value)), tag, defaultValue); } /// @@ -218,10 +401,87 @@ public static FieldCodec ForEnum(uint tag, Func toInt32, FuncThe tag. /// A parser to use for the message type. /// A codec for the given tag. - public static FieldCodec ForMessage(uint tag, MessageParser parser) where T : IMessage + public static FieldCodec ForMessage(uint tag, MessageParser parser) where T : class, IMessage { - return new FieldCodec(input => { T message = parser.CreateTemplate(); input.ReadMessage(message); return message; }, - (output, value) => output.WriteMessage(value), message => CodedOutputStream.ComputeMessageSize(message), tag); + return new FieldCodec( + (ref ParseContext ctx) => + { + T message = parser.CreateTemplate(); + ctx.ReadMessage(message); + return message; + }, + (ref WriteContext output, T value) => output.WriteMessage(value), + (ref ParseContext ctx, ref T v) => + { + if (v == null) + { + v = parser.CreateTemplate(); + } + + ctx.ReadMessage(v); + }, + (ref T v, T v2) => + { + if (v2 == null) + { + return false; + } + else if (v == null) + { + v = v2.Clone(); + } + else + { + v.MergeFrom(v2); + } + return true; + }, + message => CodedOutputStream.ComputeMessageSize(message), tag); + } + + /// + /// Retrieves a codec suitable for a group field with the given tag. + /// + /// The start group tag. + /// The end group tag. + /// A parser to use for the group message type. + /// A codec for given tag + public static FieldCodec ForGroup(uint startTag, uint endTag, MessageParser parser) where T : class, IMessage + { + return new FieldCodec( + (ref ParseContext ctx) => + { + T message = parser.CreateTemplate(); + ctx.ReadGroup(message); + return message; + }, + (ref WriteContext output, T value) => output.WriteGroup(value), + (ref ParseContext ctx, ref T v) => + { + if (v == null) + { + v = parser.CreateTemplate(); + } + + ctx.ReadGroup(v); + }, + (ref T v, T v2) => + { + if (v2 == null) + { + return v == null; + } + else if (v == null) + { + v = v2.Clone(); + } + else + { + v.MergeFrom(v2); + } + return true; + }, + message => CodedOutputStream.ComputeGroupSize(message), startTag, endTag); } /// @@ -231,10 +491,12 @@ public static FieldCodec ForClassWrapper(uint tag) where T : class { var nestedCodec = WrapperCodecs.GetCodec(); return new FieldCodec( - input => WrapperCodecs.Read(input, nestedCodec), - (output, value) => WrapperCodecs.Write(output, value, nestedCodec), + (ref ParseContext ctx) => WrapperCodecs.Read(ref ctx, nestedCodec), + (ref WriteContext output, T value) => WrapperCodecs.Write(ref output, value, nestedCodec), + (ref ParseContext ctx, ref T v) => v = WrapperCodecs.Read(ref ctx, nestedCodec), + (ref T v, T v2) => { v = v2; return v == null; }, value => WrapperCodecs.CalculateSize(value, nestedCodec), - tag, + tag, 0, null); // Default value for the wrapper } @@ -246,10 +508,12 @@ public static FieldCodec ForClassWrapper(uint tag) where T : class { var nestedCodec = WrapperCodecs.GetCodec(); return new FieldCodec( - input => WrapperCodecs.Read(input, nestedCodec), - (output, value) => WrapperCodecs.Write(output, value.Value, nestedCodec), + WrapperCodecs.GetReader(), + (ref WriteContext output, T? value) => WrapperCodecs.Write(ref output, value.Value, nestedCodec), + (ref ParseContext ctx, ref T? v) => v = WrapperCodecs.Read(ref ctx, nestedCodec), + (ref T? v, T? v2) => { if (v2.HasValue) { v = v2; } return v.HasValue; }, value => value == null ? 0 : WrapperCodecs.CalculateSize(value.Value, nestedCodec), - tag, + tag, 0, null); // Default value for the wrapper } @@ -276,9 +540,28 @@ private static class WrapperCodecs { typeof(ByteString), ForBytes(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) } }; + private static readonly Dictionary Readers = new Dictionary + { + // TODO: Provide more optimized readers. + { typeof(bool), (ValueReader)ParsingPrimitivesWrappers.ReadBoolWrapper }, + { typeof(int), (ValueReader)ParsingPrimitivesWrappers.ReadInt32Wrapper }, + { typeof(long), (ValueReader)ParsingPrimitivesWrappers.ReadInt64Wrapper }, + { typeof(uint), (ValueReader)ParsingPrimitivesWrappers.ReadUInt32Wrapper }, + { typeof(ulong), (ValueReader)ParsingPrimitivesWrappers.ReadUInt64Wrapper }, + { typeof(float), BitConverter.IsLittleEndian ? + (ValueReader)ParsingPrimitivesWrappers.ReadFloatWrapperLittleEndian : + (ValueReader)ParsingPrimitivesWrappers.ReadFloatWrapperSlow }, + { typeof(double), BitConverter.IsLittleEndian ? + (ValueReader)ParsingPrimitivesWrappers.ReadDoubleWrapperLittleEndian : + (ValueReader)ParsingPrimitivesWrappers.ReadDoubleWrapperSlow }, + // `string` and `ByteString` less performance-sensitive. Do not implement for now. + { typeof(string), null }, + { typeof(ByteString), null }, + }; + /// /// Returns a field codec which effectively wraps a value of type T in a message. - /// + /// /// internal static FieldCodec GetCodec() { @@ -290,35 +573,53 @@ internal static FieldCodec GetCodec() return (FieldCodec) value; } - internal static T Read(CodedInputStream input, FieldCodec codec) + internal static ValueReader GetReader() where T : struct + { + object value; + if (!Readers.TryGetValue(typeof(T), out value)) + { + throw new InvalidOperationException("Invalid type argument requested for wrapper reader: " + typeof(T)); + } + if (value == null) + { + // Return default unoptimized reader for the wrapper type. + var nestedCoded = GetCodec(); + return (ref ParseContext ctx) => Read(ref ctx, nestedCoded); + } + // Return optimized read for the wrapper type. + return (ValueReader)value; + } + + [SecuritySafeCritical] + internal static T Read(ref ParseContext ctx, FieldCodec codec) { - int length = input.ReadLength(); - int oldLimit = input.PushLimit(length); + int length = ctx.ReadLength(); + int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length); uint tag; T value = codec.DefaultValue; - while ((tag = input.ReadTag()) != 0) + while ((tag = ctx.ReadTag()) != 0) { if (tag == codec.Tag) { - value = codec.Read(input); + value = codec.Read(ref ctx); } else { - input.SkipLastField(); + ParsingPrimitivesMessages.SkipLastField(ref ctx.buffer, ref ctx.state); } } - input.CheckReadEndOfStreamTag(); - input.PopLimit(oldLimit); + ParsingPrimitivesMessages.CheckReadEndOfStreamTag(ref ctx.state); + SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit); return value; } - internal static void Write(CodedOutputStream output, T value, FieldCodec codec) + internal static void Write(ref WriteContext ctx, T value, FieldCodec codec) { - output.WriteLength(codec.CalculateSizeWithTag(value)); - codec.WriteTagAndValue(output, value); + ctx.WriteLength(codec.CalculateSizeWithTag(value)); + codec.WriteTagAndValue(ref ctx, value); } internal static int CalculateSize(T value, FieldCodec codec) @@ -329,6 +630,9 @@ internal static int CalculateSize(T value, FieldCodec codec) } } + internal delegate TValue ValueReader(ref ParseContext ctx); + internal delegate void ValueWriter(ref WriteContext ctx, T value); + /// /// /// An encode/decode pair for a single field. This effectively encapsulates @@ -346,10 +650,21 @@ internal static int CalculateSize(T value, FieldCodec codec) /// public sealed class FieldCodec { + private static readonly EqualityComparer EqualityComparer = ProtobufEqualityComparers.GetEqualityComparer(); private static readonly T DefaultDefault; // Only non-nullable value types support packing. This is the simplest way of detecting that. private static readonly bool TypeSupportsPacking = default(T) != null; + /// + /// Merges an input stream into a value + /// + internal delegate void InputMerger(ref ParseContext ctx, ref T value); + + /// + /// Merges a value into a reference to another value, returning a boolean if the value was set + /// + internal delegate bool ValuesMerger(ref T value, T other); + static FieldCodec() { if (typeof(T) == typeof(string)) @@ -371,7 +686,7 @@ internal static bool IsPackedRepeatedField(uint tag) => /// /// Returns a delegate to write a value (unconditionally) to a coded output stream. /// - internal Action ValueWriter { get; } + internal ValueWriter ValueWriter { get; } /// /// Returns the size calculator for just a value. @@ -382,7 +697,18 @@ internal static bool IsPackedRepeatedField(uint tag) => /// Returns a delegate to read a value from a coded input stream. It is assumed that /// the stream is already positioned on the appropriate tag. /// - internal Func ValueReader { get; } + internal ValueReader ValueReader { get; } + + /// + /// Returns a delegate to merge a value from a coded input stream. + /// It is assumed that the stream is already positioned on the appropriate tag + /// + internal InputMerger ValueMerger { get; } + + /// + /// Returns a delegate to merge two values together. + /// + internal ValuesMerger FieldMerger { get; } /// /// Returns the fixed size for an entry, or 0 if sizes vary. @@ -397,6 +723,14 @@ internal static bool IsPackedRepeatedField(uint tag) => /// internal uint Tag { get; } + /// + /// Gets the end tag of the codec or 0 if there is no end tag + /// + /// + /// The end tag of the codec. + /// + internal uint EndTag { get; } + /// /// Default value for this codec. Usually the same for every instance of the same type, but /// for string/ByteString wrapper fields the codec's default value is null, whereas for @@ -408,38 +742,59 @@ internal static bool IsPackedRepeatedField(uint tag) => internal T DefaultValue { get; } private readonly int tagSize; - + internal FieldCodec( - Func reader, - Action writer, + ValueReader reader, + ValueWriter writer, int fixedSize, - uint tag) : this(reader, writer, _ => fixedSize, tag) + uint tag, + T defaultValue) : this(reader, writer, _ => fixedSize, tag, defaultValue) { FixedSize = fixedSize; } internal FieldCodec( - Func reader, - Action writer, + ValueReader reader, + ValueWriter writer, Func sizeCalculator, - uint tag) : this(reader, writer, sizeCalculator, tag, DefaultDefault) + uint tag, + T defaultValue) : this(reader, writer, (ref ParseContext ctx, ref T v) => v = reader(ref ctx), (ref T v, T v2) => { v = v2; return true; }, sizeCalculator, tag, 0, defaultValue) + { + } + + internal FieldCodec( + ValueReader reader, + ValueWriter writer, + InputMerger inputMerger, + ValuesMerger valuesMerger, + Func sizeCalculator, + uint tag, + uint endTag = 0) : this(reader, writer, inputMerger, valuesMerger, sizeCalculator, tag, endTag, DefaultDefault) { } internal FieldCodec( - Func reader, - Action writer, + ValueReader reader, + ValueWriter writer, + InputMerger inputMerger, + ValuesMerger valuesMerger, Func sizeCalculator, uint tag, + uint endTag, T defaultValue) { ValueReader = reader; ValueWriter = writer; + ValueMerger = inputMerger; + FieldMerger = valuesMerger; ValueSizeCalculator = sizeCalculator; FixedSize = 0; Tag = tag; + EndTag = endTag; DefaultValue = defaultValue; tagSize = CodedOutputStream.ComputeRawVarint32Size(tag); + if (endTag != 0) + tagSize += CodedOutputStream.ComputeRawVarint32Size(endTag); // Detect packed-ness once, so we can check for it within RepeatedField. PackedRepeatedField = IsPackedRepeatedField(tag); } @@ -448,11 +803,42 @@ internal FieldCodec( /// Write a tag and the given value, *if* the value is not the default. /// public void WriteTagAndValue(CodedOutputStream output, T value) + { + WriteContext.Initialize(output, out WriteContext ctx); + try + { + WriteTagAndValue(ref ctx, value); + } + finally + { + ctx.CopyStateTo(output); + } + + + //if (!IsDefault(value)) + //{ + // output.WriteTag(Tag); + // ValueWriter(output, value); + // if (EndTag != 0) + // { + // output.WriteTag(EndTag); + // } + //} + } + + /// + /// Write a tag and the given value, *if* the value is not the default. + /// + public void WriteTagAndValue(ref WriteContext ctx, T value) { if (!IsDefault(value)) { - output.WriteTag(Tag); - ValueWriter(output, value); + ctx.WriteTag(Tag); + ValueWriter(ref ctx, value); + if (EndTag != 0) + { + ctx.WriteTag(EndTag); + } } } @@ -461,7 +847,28 @@ public void WriteTagAndValue(CodedOutputStream output, T value) /// /// The input stream to read from. /// The value read from the stream. - public T Read(CodedInputStream input) => ValueReader(input); + public T Read(CodedInputStream input) + { + ParseContext.Initialize(input, out ParseContext ctx); + try + { + return ValueReader(ref ctx); + } + finally + { + ctx.CopyStateTo(input); + } + } + + /// + /// Reads a value of the codec type from the given . + /// + /// The parse context to read from. + /// The value read. + public T Read(ref ParseContext ctx) + { + return ValueReader(ref ctx); + } /// /// Calculates the size required to write the given value, with a tag, @@ -469,6 +876,12 @@ public void WriteTagAndValue(CodedOutputStream output, T value) /// public int CalculateSizeWithTag(T value) => IsDefault(value) ? 0 : ValueSizeCalculator(value) + tagSize; - private bool IsDefault(T value) => EqualityComparer.Default.Equals(value, DefaultValue); + /// + /// Calculates the size required to write the given value, with a tag, even + /// if the value is the default. + /// + internal int CalculateUnconditionalSizeWithTag(T value) => ValueSizeCalculator(value) + tagSize; + + private bool IsDefault(T value) => EqualityComparer.Equals(value, DefaultValue); } } diff --git a/csharp/src/Google.Protobuf/FieldMaskTree.cs b/csharp/src/Google.Protobuf/FieldMaskTree.cs new file mode 100644 index 0000000000000..2297e7a119d57 --- /dev/null +++ b/csharp/src/Google.Protobuf/FieldMaskTree.cs @@ -0,0 +1,365 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using Google.Protobuf.Reflection; +using Google.Protobuf.WellKnownTypes; + +namespace Google.Protobuf +{ + /// + /// A tree representation of a FieldMask. Each leaf node in this tree represent + /// a field path in the FieldMask. + /// + /// For example, FieldMask "foo.bar,foo.baz,bar.baz" as a tree will be: + /// + /// [root] -+- foo -+- bar + /// | | + /// | +- baz + /// | + /// +- bar --- baz + /// + /// + /// By representing FieldMasks with this tree structure we can easily convert + /// a FieldMask to a canonical form, merge two FieldMasks, calculate the + /// intersection to two FieldMasks and traverse all fields specified by the + /// FieldMask in a message tree. + /// + internal sealed class FieldMaskTree + { + private const char FIELD_PATH_SEPARATOR = '.'; + + internal sealed class Node + { + public Dictionary Children { get; } = new Dictionary(); + } + + private readonly Node root = new Node(); + + /// + /// Creates an empty FieldMaskTree. + /// + public FieldMaskTree() + { + } + + /// + /// Creates a FieldMaskTree for a given FieldMask. + /// + public FieldMaskTree(FieldMask mask) + { + MergeFromFieldMask(mask); + } + + public override string ToString() + { + return ToFieldMask().ToString(); + } + + /// + /// Adds a field path to the tree. In a FieldMask, every field path matches the + /// specified field as well as all its sub-fields. For example, a field path + /// "foo.bar" matches field "foo.bar" and also "foo.bar.baz", etc. When adding + /// a field path to the tree, redundant sub-paths will be removed. That is, + /// after adding "foo.bar" to the tree, "foo.bar.baz" will be removed if it + /// exists, which will turn the tree node for "foo.bar" to a leaf node. + /// Likewise, if the field path to add is a sub-path of an existing leaf node, + /// nothing will be changed in the tree. + /// + public FieldMaskTree AddFieldPath(string path) + { + var parts = path.Split(FIELD_PATH_SEPARATOR); + if (parts.Length == 0) + { + return this; + } + + var node = root; + var createNewBranch = false; + + // Find the matching node in the tree. + foreach (var part in parts) + { + // Check whether the path matches an existing leaf node. + if (!createNewBranch + && node != root + && node.Children.Count == 0) + { + // The path to add is a sub-path of an existing leaf node. + return this; + } + + Node childNode; + if (!node.Children.TryGetValue(part, out childNode)) + { + createNewBranch = true; + childNode = new Node(); + node.Children.Add(part, childNode); + } + node = childNode; + } + + // Turn the matching node into a leaf node (i.e., remove sub-paths). + node.Children.Clear(); + return this; + } + + /// + /// Merges all field paths in a FieldMask into this tree. + /// + public FieldMaskTree MergeFromFieldMask(FieldMask mask) + { + foreach (var path in mask.Paths) + { + AddFieldPath(path); + } + + return this; + } + + /// + /// Converts this tree to a FieldMask. + /// + public FieldMask ToFieldMask() + { + var mask = new FieldMask(); + if (root.Children.Count != 0) + { + var paths = new List(); + GetFieldPaths(root, "", paths); + mask.Paths.AddRange(paths); + } + + return mask; + } + + /// + /// Gathers all field paths in a sub-tree. + /// + private void GetFieldPaths(Node node, string path, List paths) + { + if (node.Children.Count == 0) + { + paths.Add(path); + return; + } + + foreach (var entry in node.Children) + { + var childPath = path.Length == 0 ? entry.Key : path + "." + entry.Key; + GetFieldPaths(entry.Value, childPath, paths); + } + } + + /// + /// Adds the intersection of this tree with the given to . + /// + public void IntersectFieldPath(string path, FieldMaskTree output) + { + if (root.Children.Count == 0) + { + return; + } + + var parts = path.Split(FIELD_PATH_SEPARATOR); + if (parts.Length == 0) + { + return; + } + + var node = root; + foreach (var part in parts) + { + if (node != root + && node.Children.Count == 0) + { + // The given path is a sub-path of an existing leaf node in the tree. + output.AddFieldPath(path); + return; + } + + if (!node.Children.TryGetValue(part, out node)) + { + return; + } + } + + // We found a matching node for the path. All leaf children of this matching + // node is in the intersection. + var paths = new List(); + GetFieldPaths(node, path, paths); + foreach (var value in paths) + { + output.AddFieldPath(value); + } + } + + /// + /// Merges all fields specified by this FieldMaskTree from to . + /// + public void Merge(IMessage source, IMessage destination, FieldMask.MergeOptions options) + { + if (source.Descriptor != destination.Descriptor) + { + throw new InvalidProtocolBufferException("Cannot merge messages of different types."); + } + + if (root.Children.Count == 0) + { + return; + } + + Merge(root, "", source, destination, options); + } + + /// + /// Merges all fields specified by a sub-tree from to . + /// + private void Merge( + Node node, + string path, + IMessage source, + IMessage destination, + FieldMask.MergeOptions options) + { + if (source.Descriptor != destination.Descriptor) + { + throw new InvalidProtocolBufferException($"source ({source.Descriptor}) and destination ({destination.Descriptor}) descriptor must be equal"); + } + + var descriptor = source.Descriptor; + foreach (var entry in node.Children) + { + var field = descriptor.FindFieldByName(entry.Key); + if (field == null) + { + Debug.WriteLine($"Cannot find field \"{entry.Key}\" in message type \"{descriptor.FullName}\""); + continue; + } + + if (entry.Value.Children.Count != 0) + { + if (field.IsRepeated + || field.FieldType != FieldType.Message) + { + Debug.WriteLine($"Field \"{field.FullName}\" is not a singular message field and cannot have sub-fields."); + continue; + } + + var sourceField = field.Accessor.GetValue(source); + var destinationField = field.Accessor.GetValue(destination); + if (sourceField == null + && destinationField == null) + { + // If the message field is not present in both source and destination, skip recursing + // so we don't create unnecessary empty messages. + continue; + } + + if (destinationField == null) + { + // If we have to merge but the destination does not contain the field, create it. + destinationField = field.MessageType.Parser.CreateTemplate(); + field.Accessor.SetValue(destination, destinationField); + } + + var childPath = path.Length == 0 ? entry.Key : path + "." + entry.Key; + Merge(entry.Value, childPath, (IMessage)sourceField, (IMessage)destinationField, options); + continue; + } + + if (field.IsRepeated) + { + if (options.ReplaceRepeatedFields) + { + field.Accessor.Clear(destination); + } + + var sourceField = (IList)field.Accessor.GetValue(source); + var destinationField = (IList)field.Accessor.GetValue(destination); + foreach (var element in sourceField) + { + destinationField.Add(element); + } + } + else + { + var sourceField = field.Accessor.GetValue(source); + if (field.FieldType == FieldType.Message) + { + if (options.ReplaceMessageFields) + { + if (sourceField == null) + { + field.Accessor.Clear(destination); + } + else + { + field.Accessor.SetValue(destination, sourceField); + } + } + else + { + if (sourceField != null) + { + var sourceByteString = ((IMessage)sourceField).ToByteString(); + var destinationValue = (IMessage)field.Accessor.GetValue(destination); + if (destinationValue != null) + { + destinationValue.MergeFrom(sourceByteString); + } + else + { + field.Accessor.SetValue(destination, field.MessageType.Parser.ParseFrom(sourceByteString)); + } + } + } + } + else + { + if (sourceField != null + || !options.ReplacePrimitiveFields) + { + field.Accessor.SetValue(destination, sourceField); + } + else + { + field.Accessor.Clear(destination); + } + } + } + } + } + } +} diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj index 1d21fdc5a411d..4a3dca20c9556 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj +++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj @@ -1,33 +1,42 @@ - + C# runtime library for Protocol Buffers - Google's data interchange format. Copyright 2015, Google Inc. Google Protocol Buffers - 3.4.0 + 3.15.0 + + 7.2 Google Inc. - netstandard1.0;net451 + netstandard1.1;netstandard2.0;net45 true ../../keys/Google.Protobuf.snk true - true Protocol;Buffers;Binary;Serialization;Format;Google;proto;proto3 C# proto3 support - https://github.com/google/protobuf - https://github.com/google/protobuf/blob/master/LICENSE + https://github.com/protocolbuffers/protobuf + https://github.com/protocolbuffers/protobuf/blob/master/LICENSE git - https://github.com/google/protobuf.git - true - true + https://github.com/protocolbuffers/protobuf.git + True + + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb - - - netstandard1.0 + + $(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_FAST_STRING + + + + + + + + + + + + diff --git a/csharp/src/Google.Protobuf/IBufferMessage.cs b/csharp/src/Google.Protobuf/IBufferMessage.cs new file mode 100644 index 0000000000000..05c15db4c62a1 --- /dev/null +++ b/csharp/src/Google.Protobuf/IBufferMessage.cs @@ -0,0 +1,53 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +namespace Google.Protobuf +{ + /// + /// Interface for a Protocol Buffers message, supporting + /// parsing from and writing to . + /// + public interface IBufferMessage : IMessage + { + /// + /// Internal implementation of merging data from given parse context into this message. + /// Users should never invoke this method directly. + /// + void InternalMergeFrom(ref ParseContext ctx); + + /// + /// Internal implementation of writing this message to a given write context. + /// Users should never invoke this method directly. + /// + void InternalWriteTo(ref WriteContext ctx); + } +} diff --git a/csharp/src/Google.Protobuf/IExtendableMessage.cs b/csharp/src/Google.Protobuf/IExtendableMessage.cs new file mode 100644 index 0000000000000..8fca2b427b8b0 --- /dev/null +++ b/csharp/src/Google.Protobuf/IExtendableMessage.cs @@ -0,0 +1,79 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using Google.Protobuf.Collections; + +namespace Google.Protobuf +{ + /// + /// Generic interface for a Protocol Buffers message containing one or more extensions, where the type parameter is expected to be the same type as the implementation class. + /// This interface is experiemental and is subject to change. + /// + public interface IExtendableMessage : IMessage where T : IExtendableMessage + { + /// + /// Gets the value of the specified extension + /// + TValue GetExtension(Extension extension); + + /// + /// Gets the value of the specified repeated extension or null if the extension isn't registered in this set. + /// For a version of this method that never returns null, use + /// + RepeatedField GetExtension(RepeatedExtension extension); + + /// + /// Gets the value of the specified repeated extension, registering it if it hasn't already been registered. + /// + RepeatedField GetOrInitializeExtension(RepeatedExtension extension); + + /// + /// Sets the value of the specified extension + /// + void SetExtension(Extension extension, TValue value); + + /// + /// Gets whether the value of the specified extension is set + /// + bool HasExtension(Extension extension); + + /// + /// Clears the value of the specified extension + /// + void ClearExtension(Extension extension); + + /// + /// Clears the value of the specified repeated extension + /// + void ClearExtension(RepeatedExtension extension); + } +} diff --git a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs index 0fbc530631684..c5ffe9bbf83d4 100644 --- a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs +++ b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs @@ -88,6 +88,12 @@ internal static InvalidProtocolBufferException InvalidTag() "Protocol message contained an invalid tag (zero)."); } + internal static InvalidProtocolBufferException InvalidWireType() + { + return new InvalidProtocolBufferException( + "Protocol message contained a tag with an invalid wire type."); + } + internal static InvalidProtocolBufferException InvalidBase64(Exception innerException) { return new InvalidProtocolBufferException("Invalid base64 data", innerException); @@ -125,5 +131,10 @@ internal static InvalidProtocolBufferException InvalidMessageStreamTag() return new InvalidProtocolBufferException( "Stream of protocol messages had invalid tag. Expected tag is length-delimited field 1."); } - } + + internal static InvalidProtocolBufferException MissingFields() + { + return new InvalidProtocolBufferException("Message was missing required fields"); + } +} } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs old mode 100755 new mode 100644 index 4ae10d8b73ece..4bffd58c1f406 --- a/csharp/src/Google.Protobuf/JsonFormatter.cs +++ b/csharp/src/Google.Protobuf/JsonFormatter.cs @@ -70,7 +70,7 @@ public sealed class JsonFormatter /// public static JsonFormatter Default { get; } = new JsonFormatter(Settings.Default); - // A JSON formatter which *only* exists + // A JSON formatter which *only* exists private static readonly JsonFormatter diagnosticFormatter = new JsonFormatter(Settings.Default); /// @@ -133,7 +133,7 @@ static JsonFormatter() /// The settings. public JsonFormatter(Settings settings) { - this.settings = settings; + this.settings = ProtoPreconditions.CheckNotNull(settings, nameof(settings)); } /// @@ -221,19 +221,12 @@ private bool WriteMessageFields(TextWriter writer, IMessage message, bool assume foreach (var field in fields.InFieldNumberOrder()) { var accessor = field.Accessor; - if (field.ContainingOneof != null && field.ContainingOneof.Accessor.GetCaseFieldDescriptor(message) != field) - { - continue; - } - // Omit default values unless we're asked to format them, or they're oneofs (where the default - // value is still formatted regardless, because that's how we preserve the oneof case). - object value = accessor.GetValue(message); - if (field.ContainingOneof == null && !settings.FormatDefaultValues && IsDefaultValue(accessor, value)) + var value = accessor.GetValue(message); + if (!ShouldFormatFieldValue(message, field, value)) { continue; } - // Okay, all tests complete: let's write the field value... if (!first) { writer.Write(PropertySeparator); @@ -248,6 +241,18 @@ private bool WriteMessageFields(TextWriter writer, IMessage message, bool assume return !first; } + /// + /// Determines whether or not a field value should be serialized according to the field, + /// its value in the message, and the settings of this formatter. + /// + private bool ShouldFormatFieldValue(IMessage message, FieldDescriptor field, object value) => + field.HasPresence + // Fields that support presence *just* use that + ? field.Accessor.HasValue(message) + // Otherwise, format if either we've been asked to format default values, or if it's + // not a default value anyway. + : settings.FormatDefaultValues || !IsDefaultValue(field, value); + // Converted from java/core/src/main/java/com/google/protobuf/Descriptors.java internal static string ToJsonName(string name) { @@ -271,25 +276,43 @@ internal static string ToJsonName(string name) } return result.ToString(); } - + + internal static string FromJsonName(string name) + { + StringBuilder result = new StringBuilder(name.Length); + foreach (char ch in name) + { + if (char.IsUpper(ch)) + { + result.Append('_'); + result.Append(char.ToLowerInvariant(ch)); + } + else + { + result.Append(ch); + } + } + return result.ToString(); + } + private static void WriteNull(TextWriter writer) { writer.Write("null"); } - private static bool IsDefaultValue(IFieldAccessor accessor, object value) + private static bool IsDefaultValue(FieldDescriptor descriptor, object value) { - if (accessor.Descriptor.IsMap) + if (descriptor.IsMap) { IDictionary dictionary = (IDictionary) value; return dictionary.Count == 0; } - if (accessor.Descriptor.IsRepeated) + if (descriptor.IsRepeated) { IList list = (IList) value; return list.Count == 0; } - switch (accessor.Descriptor.FieldType) + switch (descriptor.FieldType) { case FieldType.Bool: return (bool) value == false; @@ -334,7 +357,7 @@ private static bool IsDefaultValue(IFieldAccessor accessor, object value) /// The value to write. May be null. public void WriteValue(TextWriter writer, object value) { - if (value == null) + if (value == null || value is NullValue) { WriteNull(writer); } @@ -561,7 +584,7 @@ private void WriteDiagnosticOnlyAny(TextWriter writer, IMessage value) writer.Write(data.ToBase64()); writer.Write('"'); writer.Write(" }"); - } + } private void WriteStruct(TextWriter writer, IMessage message) { @@ -598,7 +621,7 @@ private void WriteStructFieldValue(TextWriter writer, IMessage message) } object value = specifiedField.Accessor.GetValue(message); - + switch (specifiedField.FieldNumber) { case Value.BoolValueFieldNumber: @@ -775,8 +798,10 @@ static Settings() } /// - /// Whether fields whose values are the default for the field type (e.g. 0 for integers) - /// should be formatted (true) or omitted (false). + /// Whether fields which would otherwise not be included in the formatted data + /// should be formatted even when the value is not present, or has the default value. + /// This option only affects fields which don't support "presence" (e.g. + /// singular non-optional proto3 primitive fields). /// public bool FormatDefaultValues { get; } @@ -853,7 +878,7 @@ private static class OriginalEnumValueHelper // the platforms we target have it. private static readonly Dictionary> dictionaries = new Dictionary>(); - + internal static string GetOriginalName(object value) { var enumType = value.GetType(); diff --git a/csharp/src/Google.Protobuf/JsonParser.cs b/csharp/src/Google.Protobuf/JsonParser.cs index 6b6f2d9ae25a7..cb5f5a8f21a76 100644 --- a/csharp/src/Google.Protobuf/JsonParser.cs +++ b/csharp/src/Google.Protobuf/JsonParser.cs @@ -37,6 +37,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; +using System.Linq; using System.Text; using System.Text.RegularExpressions; @@ -63,6 +64,7 @@ public sealed class JsonParser private static readonly Regex DurationRegex = new Regex(@"^(?-)?(?[0-9]{1,12})(?\.[0-9]{1,9})?s$", FrameworkPortability.CompiledRegexWhereAvailable); private static readonly int[] SubsecondScalingFactors = { 0, 100000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 }; private static readonly char[] FieldMaskPathSeparators = new[] { ',' }; + private static readonly EnumDescriptor NullValueDescriptor = StructReflection.Descriptor.EnumTypes.Single(ed => ed.ClrType == typeof(NullValue)); private static readonly JsonParser defaultInstance = new JsonParser(Settings.Default); @@ -110,7 +112,7 @@ private static void MergeWrapperField(JsonParser parser, IMessage message, JsonT /// The settings. public JsonParser(Settings settings) { - this.settings = settings; + this.settings = ProtoPreconditions.CheckNotNull(settings, nameof(settings)); } /// @@ -203,10 +205,14 @@ private void Merge(IMessage message, JsonTokenizer tokenizer) } else { - // TODO: Is this what we want to do? If not, we'll need to skip the value, - // which may be an object or array. (We might want to put code in the tokenizer - // to do that.) - throw new InvalidProtocolBufferException("Unknown field: " + name); + if (settings.IgnoreUnknownFields) + { + tokenizer.SkipValue(); + } + else + { + throw new InvalidProtocolBufferException("Unknown field: " + name); + } } } } @@ -217,10 +223,11 @@ private void MergeField(IMessage message, FieldDescriptor field, JsonTokenizer t if (token.Type == JsonToken.TokenType.Null) { // Clear the field if we see a null token, unless it's for a singular field of type - // google.protobuf.Value. + // google.protobuf.Value or google.protobuf.NullValue. // Note: different from Java API, which just ignores it. // TODO: Bring it more in line? Discuss... - if (field.IsMap || field.IsRepeated || !IsGoogleProtobufValueField(field)) + if (field.IsMap || field.IsRepeated || + !(IsGoogleProtobufValueField(field) || IsGoogleProtobufNullValueField(field))) { field.Accessor.Clear(message); return; @@ -260,11 +267,12 @@ private void MergeRepeatedField(IMessage message, FieldDescriptor field, JsonTok return; } tokenizer.PushBack(token); - if (token.Type == JsonToken.TokenType.Null) + object value = ParseSingleValue(field, tokenizer); + if (value == null) { throw new InvalidProtocolBufferException("Repeated field elements cannot be null"); } - list.Add(ParseSingleValue(field, tokenizer)); + list.Add(value); } } @@ -309,6 +317,12 @@ private static bool IsGoogleProtobufValueField(FieldDescriptor field) field.MessageType.FullName == Value.Descriptor.FullName; } + private static bool IsGoogleProtobufNullValueField(FieldDescriptor field) + { + return field.FieldType == FieldType.Enum && + field.EnumType.FullName == NullValueDescriptor.FullName; + } + private object ParseSingleValue(FieldDescriptor field, JsonTokenizer tokenizer) { var token = tokenizer.Next(); @@ -320,6 +334,10 @@ private object ParseSingleValue(FieldDescriptor field, JsonTokenizer tokenizer) { return Value.ForNull(); } + if (IsGoogleProtobufNullValueField(field)) + { + return NullValue.NullValue; + } return null; } @@ -669,7 +687,7 @@ private static void CheckInteger(double value) if (value != Math.Floor(value)) { throw new InvalidProtocolBufferException($"Value not an integer: {value}"); - } + } } private static object ParseSingleStringValue(FieldDescriptor field, string text) @@ -914,7 +932,7 @@ private static void MergeFieldMask(IMessage message, JsonToken token) messagePaths.Add(ToSnakeCase(path)); } } - + // Ported from src/google/protobuf/util/internal/utility.cc private static string ToSnakeCase(string text) { @@ -996,6 +1014,19 @@ static Settings() /// public TypeRegistry TypeRegistry { get; } + /// + /// Whether the parser should ignore unknown fields (true) or throw an exception when + /// they are encountered (false). + /// + public bool IgnoreUnknownFields { get; } + + private Settings(int recursionLimit, TypeRegistry typeRegistry, bool ignoreUnknownFields) + { + RecursionLimit = recursionLimit; + TypeRegistry = ProtoPreconditions.CheckNotNull(typeRegistry, nameof(typeRegistry)); + IgnoreUnknownFields = ignoreUnknownFields; + } + /// /// Creates a new object with the specified recursion limit. /// @@ -1009,11 +1040,34 @@ public Settings(int recursionLimit) : this(recursionLimit, TypeRegistry.Empty) /// /// The maximum depth of messages to parse /// The type registry used to parse messages - public Settings(int recursionLimit, TypeRegistry typeRegistry) + public Settings(int recursionLimit, TypeRegistry typeRegistry) : this(recursionLimit, typeRegistry, false) { - RecursionLimit = recursionLimit; - TypeRegistry = ProtoPreconditions.CheckNotNull(typeRegistry, nameof(typeRegistry)); } + + /// + /// Creates a new object set to either ignore unknown fields, or throw an exception + /// when unknown fields are encountered. + /// + /// true if unknown fields should be ignored when parsing; false to throw an exception. + public Settings WithIgnoreUnknownFields(bool ignoreUnknownFields) => + new Settings(RecursionLimit, TypeRegistry, ignoreUnknownFields); + + /// + /// Creates a new object based on this one, but with the specified recursion limit. + /// + /// The new recursion limit. + public Settings WithRecursionLimit(int recursionLimit) => + new Settings(recursionLimit, TypeRegistry, IgnoreUnknownFields); + + /// + /// Creates a new object based on this one, but with the specified type registry. + /// + /// The new type registry. Must not be null. + public Settings WithTypeRegistry(TypeRegistry typeRegistry) => + new Settings( + RecursionLimit, + ProtoPreconditions.CheckNotNull(typeRegistry, nameof(typeRegistry)), + IgnoreUnknownFields); } } } diff --git a/csharp/src/Google.Protobuf/JsonTokenizer.cs b/csharp/src/Google.Protobuf/JsonTokenizer.cs index 09a6d43b7bed7..4725e7cc51197 100644 --- a/csharp/src/Google.Protobuf/JsonTokenizer.cs +++ b/csharp/src/Google.Protobuf/JsonTokenizer.cs @@ -137,6 +137,34 @@ internal JsonToken Next() /// The input text does not comply with RFC 7159 protected abstract JsonToken NextImpl(); + /// + /// Skips the value we're about to read. This must only be called immediately after reading a property name. + /// If the value is an object or an array, the complete object/array is skipped. + /// + internal void SkipValue() + { + // We'll assume that Next() makes sure that the end objects and end arrays are all valid. + // All we care about is the total nesting depth we need to close. + int depth = 0; + + // do/while rather than while loop so that we read at least one token. + do + { + var token = Next(); + switch (token.Type) + { + case JsonToken.TokenType.EndArray: + case JsonToken.TokenType.EndObject: + depth--; + break; + case JsonToken.TokenType.StartArray: + case JsonToken.TokenType.StartObject: + depth++; + break; + } + } while (depth != 0); + } + /// /// Tokenizer which first exhausts a list of tokens, then consults another tokenizer. /// @@ -217,7 +245,7 @@ protected override JsonToken NextImpl() state = State.ObjectAfterColon; break; case ',': - ValidateState(State.ObjectAfterProperty | State.ArrayAfterValue, "Invalid state to read a colon: "); + ValidateState(State.ObjectAfterProperty | State.ArrayAfterValue, "Invalid state to read a comma: "); state = state == State.ObjectAfterProperty ? State.ObjectAfterComma : State.ArrayAfterComma; break; case '"': @@ -586,7 +614,7 @@ private enum ContainerType /// where ^ represents the current position within the text stream. The examples all use string values, /// but could be any value, including nested objects/arrays. /// The complete state of the tokenizer also includes a stack to indicate the contexts (arrays/objects). - /// Any additional notional state of "AfterValue" indicates that a value has been completed, at which + /// Any additional notional state of "AfterValue" indicates that a value has been completed, at which /// point there's an immediate transition to ExpectedEndOfDocument, ObjectAfterProperty or ArrayAfterValue. /// /// @@ -627,7 +655,7 @@ private enum State /// /// { "foo" : ^ "bar", "x": "y" } /// Before any property other than the first in an object. - /// (Equivalently: after any property in an object) + /// (Equivalently: after any property in an object) /// Next states: /// "AfterValue" (value is simple) /// ObjectStart (value is object) diff --git a/csharp/src/Google.Protobuf/LimitedInputStream.cs b/csharp/src/Google.Protobuf/LimitedInputStream.cs index f11d19d944060..50ead9c9929e5 100644 --- a/csharp/src/Google.Protobuf/LimitedInputStream.cs +++ b/csharp/src/Google.Protobuf/LimitedInputStream.cs @@ -29,7 +29,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion - + using System; using System.IO; diff --git a/csharp/src/Google.Protobuf/MessageExtensions.cs b/csharp/src/Google.Protobuf/MessageExtensions.cs index 047156c3ee713..36a9df7286ed1 100644 --- a/csharp/src/Google.Protobuf/MessageExtensions.cs +++ b/csharp/src/Google.Protobuf/MessageExtensions.cs @@ -30,7 +30,13 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Reflection; +using System.Buffers; +using System.Collections; +using System; using System.IO; +using System.Linq; +using System.Security; namespace Google.Protobuf { @@ -44,42 +50,34 @@ public static class MessageExtensions /// /// The message to merge the data into. /// The data to merge, which must be protobuf-encoded binary data. - public static void MergeFrom(this IMessage message, byte[] data) - { - ProtoPreconditions.CheckNotNull(message, "message"); - ProtoPreconditions.CheckNotNull(data, "data"); - CodedInputStream input = new CodedInputStream(data); - message.MergeFrom(input); - input.CheckReadEndOfStreamTag(); - } + public static void MergeFrom(this IMessage message, byte[] data) => + MergeFrom(message, data, false, null); + + /// + /// Merges data from the given byte array slice into an existing message. + /// + /// The message to merge the data into. + /// The data containing the slice to merge, which must be protobuf-encoded binary data. + /// The offset of the slice to merge. + /// The length of the slice to merge. + public static void MergeFrom(this IMessage message, byte[] data, int offset, int length) => + MergeFrom(message, data, offset, length, false, null); /// /// Merges data from the given byte string into an existing message. /// /// The message to merge the data into. /// The data to merge, which must be protobuf-encoded binary data. - public static void MergeFrom(this IMessage message, ByteString data) - { - ProtoPreconditions.CheckNotNull(message, "message"); - ProtoPreconditions.CheckNotNull(data, "data"); - CodedInputStream input = data.CreateCodedInput(); - message.MergeFrom(input); - input.CheckReadEndOfStreamTag(); - } + public static void MergeFrom(this IMessage message, ByteString data) => + MergeFrom(message, data, false, null); /// /// Merges data from the given stream into an existing message. /// /// The message to merge the data into. /// Stream containing the data to merge, which must be protobuf-encoded binary data. - public static void MergeFrom(this IMessage message, Stream input) - { - ProtoPreconditions.CheckNotNull(message, "message"); - ProtoPreconditions.CheckNotNull(input, "input"); - CodedInputStream codedInput = new CodedInputStream(input); - message.MergeFrom(codedInput); - codedInput.CheckReadEndOfStreamTag(); - } + public static void MergeFrom(this IMessage message, Stream input) => + MergeFrom(message, input, false, null); /// /// Merges length-delimited data from the given stream into an existing message. @@ -90,14 +88,8 @@ public static void MergeFrom(this IMessage message, Stream input) /// /// The message to merge the data into. /// Stream containing the data to merge, which must be protobuf-encoded binary data. - public static void MergeDelimitedFrom(this IMessage message, Stream input) - { - ProtoPreconditions.CheckNotNull(message, "message"); - ProtoPreconditions.CheckNotNull(input, "input"); - int size = (int) CodedInputStream.ReadRawVarint32(input); - Stream limitedStream = new LimitedInputStream(input, size); - message.MergeFrom(limitedStream); - } + public static void MergeDelimitedFrom(this IMessage message, Stream input) => + MergeDelimitedFrom(message, input, false, null); /// /// Converts the given message into a byte array in protobuf encoding. @@ -138,7 +130,7 @@ public static void WriteDelimitedTo(this IMessage message, Stream output) ProtoPreconditions.CheckNotNull(message, "message"); ProtoPreconditions.CheckNotNull(output, "output"); CodedOutputStream codedOutput = new CodedOutputStream(output); - codedOutput.WriteRawVarint32((uint)message.CalculateSize()); + codedOutput.WriteLength(message.CalculateSize()); message.WriteTo(codedOutput); codedOutput.Flush(); } @@ -152,6 +144,163 @@ public static ByteString ToByteString(this IMessage message) { ProtoPreconditions.CheckNotNull(message, "message"); return ByteString.AttachBytes(message.ToByteArray()); - } + } + + /// + /// Writes the given message data to the given buffer writer in protobuf encoding. + /// + /// The message to write to the stream. + /// The stream to write to. + [SecuritySafeCritical] + public static void WriteTo(this IMessage message, IBufferWriter output) + { + ProtoPreconditions.CheckNotNull(message, nameof(message)); + ProtoPreconditions.CheckNotNull(output, nameof(output)); + + WriteContext.Initialize(output, out WriteContext ctx); + WritingPrimitivesMessages.WriteRawMessage(ref ctx, message); + ctx.Flush(); + } + + /// + /// Writes the given message data to the given span in protobuf encoding. + /// The size of the destination span needs to fit the serialized size + /// of the message exactly, otherwise an exception is thrown. + /// + /// The message to write to the stream. + /// The span to write to. Size must match size of the message exactly. + [SecuritySafeCritical] + public static void WriteTo(this IMessage message, Span output) + { + ProtoPreconditions.CheckNotNull(message, nameof(message)); + + WriteContext.Initialize(ref output, out WriteContext ctx); + WritingPrimitivesMessages.WriteRawMessage(ref ctx, message); + ctx.CheckNoSpaceLeft(); + } + + /// + /// Checks if all required fields in a message have values set. For proto3 messages, this returns true + /// + public static bool IsInitialized(this IMessage message) + { + if (message.Descriptor.File.Syntax == Syntax.Proto3) + { + return true; + } + + if (!message.Descriptor.IsExtensionsInitialized(message)) + { + return false; + } + + return message.Descriptor + .Fields + .InDeclarationOrder() + .All(f => + { + if (f.IsMap) + { + var valueField = f.MessageType.Fields[2]; + if (valueField.FieldType == FieldType.Message) + { + var map = (IDictionary)f.Accessor.GetValue(message); + return map.Values.Cast().All(IsInitialized); + } + else + { + return true; + } + } + else if (f.IsRepeated && f.FieldType == FieldType.Message || f.FieldType == FieldType.Group) + { + var enumerable = (IEnumerable)f.Accessor.GetValue(message); + return enumerable.Cast().All(IsInitialized); + } + else if (f.FieldType == FieldType.Message || f.FieldType == FieldType.Group) + { + if (f.Accessor.HasValue(message)) + { + return ((IMessage)f.Accessor.GetValue(message)).IsInitialized(); + } + else + { + return !f.IsRequired; + } + } + else if (f.IsRequired) + { + return f.Accessor.HasValue(message); + } + else + { + return true; + } + }); + } + + // Implementations allowing unknown fields to be discarded. + internal static void MergeFrom(this IMessage message, byte[] data, bool discardUnknownFields, ExtensionRegistry registry) + { + ProtoPreconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(data, "data"); + CodedInputStream input = new CodedInputStream(data); + input.DiscardUnknownFields = discardUnknownFields; + input.ExtensionRegistry = registry; + message.MergeFrom(input); + input.CheckReadEndOfStreamTag(); + } + + internal static void MergeFrom(this IMessage message, byte[] data, int offset, int length, bool discardUnknownFields, ExtensionRegistry registry) + { + ProtoPreconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(data, "data"); + CodedInputStream input = new CodedInputStream(data, offset, length); + input.DiscardUnknownFields = discardUnknownFields; + input.ExtensionRegistry = registry; + message.MergeFrom(input); + input.CheckReadEndOfStreamTag(); + } + + internal static void MergeFrom(this IMessage message, ByteString data, bool discardUnknownFields, ExtensionRegistry registry) + { + ProtoPreconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(data, "data"); + CodedInputStream input = data.CreateCodedInput(); + input.DiscardUnknownFields = discardUnknownFields; + input.ExtensionRegistry = registry; + message.MergeFrom(input); + input.CheckReadEndOfStreamTag(); + } + + internal static void MergeFrom(this IMessage message, Stream input, bool discardUnknownFields, ExtensionRegistry registry) + { + ProtoPreconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(input, "input"); + CodedInputStream codedInput = new CodedInputStream(input); + codedInput.DiscardUnknownFields = discardUnknownFields; + codedInput.ExtensionRegistry = registry; + message.MergeFrom(codedInput); + codedInput.CheckReadEndOfStreamTag(); + } + + [SecuritySafeCritical] + internal static void MergeFrom(this IMessage message, ReadOnlySequence data, bool discardUnknownFields, ExtensionRegistry registry) + { + ParseContext.Initialize(data, out ParseContext ctx); + ctx.DiscardUnknownFields = discardUnknownFields; + ctx.ExtensionRegistry = registry; + ParsingPrimitivesMessages.ReadRawMessage(ref ctx, message); + ParsingPrimitivesMessages.CheckReadEndOfStreamTag(ref ctx.state); + } + + internal static void MergeDelimitedFrom(this IMessage message, Stream input, bool discardUnknownFields, ExtensionRegistry registry) + { + ProtoPreconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(input, "input"); + int size = (int) CodedInputStream.ReadRawVarint32(input); + Stream limitedStream = new LimitedInputStream(input, size); + MergeFrom(message, limitedStream, discardUnknownFields, registry); + } } } diff --git a/csharp/src/Google.Protobuf/MessageParser.cs b/csharp/src/Google.Protobuf/MessageParser.cs index 8889638b20a21..f8b26c2348ede 100644 --- a/csharp/src/Google.Protobuf/MessageParser.cs +++ b/csharp/src/Google.Protobuf/MessageParser.cs @@ -29,9 +29,11 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion - + using System; +using System.Buffers; using System.IO; +using System.Security; namespace Google.Protobuf { @@ -42,10 +44,16 @@ namespace Google.Protobuf public class MessageParser { private Func factory; + // TODO: When we use a C# 7.1 compiler, make this private protected. + internal bool DiscardUnknownFields { get; } + + internal ExtensionRegistry Extensions { get; } - internal MessageParser(Func factory) + internal MessageParser(Func factory, bool discardUnknownFields, ExtensionRegistry extensions) { this.factory = factory; + DiscardUnknownFields = discardUnknownFields; + Extensions = extensions; } /// @@ -64,9 +72,22 @@ internal IMessage CreateTemplate() /// The newly parsed message. public IMessage ParseFrom(byte[] data) { - ProtoPreconditions.CheckNotNull(data, "data"); IMessage message = factory(); - message.MergeFrom(data); + message.MergeFrom(data, DiscardUnknownFields, Extensions); + return message; + } + + /// + /// Parses a message from a byte array slice. + /// + /// The byte array containing the message. Must not be null. + /// The offset of the slice to parse. + /// The length of the slice to parse. + /// The newly parsed message. + public IMessage ParseFrom(byte[] data, int offset, int length) + { + IMessage message = factory(); + message.MergeFrom(data, offset, length, DiscardUnknownFields, Extensions); return message; } @@ -77,9 +98,8 @@ public IMessage ParseFrom(byte[] data) /// The parsed message. public IMessage ParseFrom(ByteString data) { - ProtoPreconditions.CheckNotNull(data, "data"); IMessage message = factory(); - message.MergeFrom(data); + message.MergeFrom(data, DiscardUnknownFields, Extensions); return message; } @@ -91,7 +111,20 @@ public IMessage ParseFrom(ByteString data) public IMessage ParseFrom(Stream input) { IMessage message = factory(); - message.MergeFrom(input); + message.MergeFrom(input, DiscardUnknownFields, Extensions); + return message; + } + + /// + /// Parses a message from the given sequence. + /// + /// The data to parse. + /// The parsed message. + [SecuritySafeCritical] + public IMessage ParseFrom(ReadOnlySequence data) + { + IMessage message = factory(); + message.MergeFrom(data, DiscardUnknownFields, Extensions); return message; } @@ -107,7 +140,7 @@ public IMessage ParseFrom(Stream input) public IMessage ParseDelimitedFrom(Stream input) { IMessage message = factory(); - message.MergeDelimitedFrom(input); + message.MergeDelimitedFrom(input, DiscardUnknownFields, Extensions); return message; } @@ -119,7 +152,7 @@ public IMessage ParseDelimitedFrom(Stream input) public IMessage ParseFrom(CodedInputStream input) { IMessage message = factory(); - message.MergeFrom(input); + MergeFrom(message, input); return message; } @@ -136,6 +169,37 @@ public IMessage ParseJson(string json) JsonParser.Default.Merge(message, json); return message; } + + // TODO: When we're using a C# 7.1 compiler, make this private protected. + internal void MergeFrom(IMessage message, CodedInputStream codedInput) + { + bool originalDiscard = codedInput.DiscardUnknownFields; + try + { + codedInput.DiscardUnknownFields = DiscardUnknownFields; + message.MergeFrom(codedInput); + } + finally + { + codedInput.DiscardUnknownFields = originalDiscard; + } + } + + /// + /// Creates a new message parser which optionally discards unknown fields when parsing. + /// + /// Whether or not to discard unknown fields when parsing. + /// A newly configured message parser. + public MessageParser WithDiscardUnknownFields(bool discardUnknownFields) => + new MessageParser(factory, discardUnknownFields, Extensions); + + /// + /// Creates a new message parser which registers extensions from the specified registry upon creating the message instance + /// + /// The extensions to register + /// A newly configured message parser. + public MessageParser WithExtensionRegistry(ExtensionRegistry registry) => + new MessageParser(factory, DiscardUnknownFields, registry); } /// @@ -160,7 +224,7 @@ public sealed class MessageParser : MessageParser where T : IMessage // The current implementation avoids a virtual method call and a cast, which *may* be significant in some cases. // Benchmarking work is required to measure the significance - but it's only a few lines of code in any case. // The API wouldn't change anyway - just the implementation - so this work can be deferred. - private readonly Func factory; + private readonly Func factory; /// /// Creates a new parser. @@ -170,7 +234,11 @@ public sealed class MessageParser : MessageParser where T : IMessage /// to require a parameterless constructor: delegates are significantly faster to execute. /// /// Function to invoke when a new, empty message is required. - public MessageParser(Func factory) : base(() => factory()) + public MessageParser(Func factory) : this(factory, false, null) + { + } + + internal MessageParser(Func factory, bool discardUnknownFields, ExtensionRegistry extensions) : base(() => factory(), discardUnknownFields, extensions) { this.factory = factory; } @@ -191,9 +259,22 @@ public MessageParser(Func factory) : base(() => factory()) /// The newly parsed message. public new T ParseFrom(byte[] data) { - ProtoPreconditions.CheckNotNull(data, "data"); T message = factory(); - message.MergeFrom(data); + message.MergeFrom(data, DiscardUnknownFields, Extensions); + return message; + } + + /// + /// Parses a message from a byte array slice. + /// + /// The byte array containing the message. Must not be null. + /// The offset of the slice to parse. + /// The length of the slice to parse. + /// The newly parsed message. + public new T ParseFrom(byte[] data, int offset, int length) + { + T message = factory(); + message.MergeFrom(data, offset, length, DiscardUnknownFields, Extensions); return message; } @@ -204,9 +285,8 @@ public MessageParser(Func factory) : base(() => factory()) /// The parsed message. public new T ParseFrom(ByteString data) { - ProtoPreconditions.CheckNotNull(data, "data"); T message = factory(); - message.MergeFrom(data); + message.MergeFrom(data, DiscardUnknownFields, Extensions); return message; } @@ -218,7 +298,20 @@ public MessageParser(Func factory) : base(() => factory()) public new T ParseFrom(Stream input) { T message = factory(); - message.MergeFrom(input); + message.MergeFrom(input, DiscardUnknownFields, Extensions); + return message; + } + + /// + /// Parses a message from the given sequence. + /// + /// The data to parse. + /// The parsed message. + [SecuritySafeCritical] + public new T ParseFrom(ReadOnlySequence data) + { + T message = factory(); + message.MergeFrom(data, DiscardUnknownFields, Extensions); return message; } @@ -234,7 +327,7 @@ public MessageParser(Func factory) : base(() => factory()) public new T ParseDelimitedFrom(Stream input) { T message = factory(); - message.MergeDelimitedFrom(input); + message.MergeDelimitedFrom(input, DiscardUnknownFields, Extensions); return message; } @@ -246,7 +339,7 @@ public MessageParser(Func factory) : base(() => factory()) public new T ParseFrom(CodedInputStream input) { T message = factory(); - message.MergeFrom(input); + MergeFrom(message, input); return message; } @@ -263,5 +356,21 @@ public MessageParser(Func factory) : base(() => factory()) JsonParser.Default.Merge(message, json); return message; } + + /// + /// Creates a new message parser which optionally discards unknown fields when parsing. + /// + /// Whether or not to discard unknown fields when parsing. + /// A newly configured message parser. + public new MessageParser WithDiscardUnknownFields(bool discardUnknownFields) => + new MessageParser(factory, discardUnknownFields, Extensions); + + /// + /// Creates a new message parser which registers extensions from the specified registry upon creating the message instance + /// + /// The extensions to register + /// A newly configured message parser. + public new MessageParser WithExtensionRegistry(ExtensionRegistry registry) => + new MessageParser(factory, DiscardUnknownFields, registry); } } diff --git a/csharp/src/Google.Protobuf/ObjectIntPair.cs b/csharp/src/Google.Protobuf/ObjectIntPair.cs new file mode 100644 index 0000000000000..b98d93a517c49 --- /dev/null +++ b/csharp/src/Google.Protobuf/ObjectIntPair.cs @@ -0,0 +1,40 @@ +using System; + +namespace Google.Protobuf +{ + /// + /// Struct used to hold the keys for the fieldByNumber table in DescriptorPool and the keys for the + /// extensionByNumber table in ExtensionRegistry. + /// + internal struct ObjectIntPair : IEquatable> where T : class + { + private readonly int number; + private readonly T obj; + + internal ObjectIntPair(T obj, int number) + { + this.number = number; + this.obj = obj; + } + + public bool Equals(ObjectIntPair other) + { + return obj == other.obj + && number == other.number; + } + + public override bool Equals(object obj) + { + if (obj is ObjectIntPair) + { + return Equals((ObjectIntPair)obj); + } + return false; + } + + public override int GetHashCode() + { + return obj.GetHashCode() * ((1 << 16) - 1) + number; + } + } +} diff --git a/csharp/src/Google.Protobuf/ParseContext.cs b/csharp/src/Google.Protobuf/ParseContext.cs new file mode 100644 index 0000000000000..bf46236565256 --- /dev/null +++ b/csharp/src/Google.Protobuf/ParseContext.cs @@ -0,0 +1,329 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Buffers; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; +using Google.Protobuf.Collections; + +namespace Google.Protobuf +{ + /// + /// An opaque struct that represents the current parsing state and is passed along + /// as the parsing proceeds. + /// All the public methods are intended to be invoked only by the generated code, + /// users should never invoke them directly. + /// + [SecuritySafeCritical] + public ref struct ParseContext + { + internal const int DefaultRecursionLimit = 100; + internal const int DefaultSizeLimit = Int32.MaxValue; + + internal ReadOnlySpan buffer; + internal ParserInternalState state; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(ref ReadOnlySpan buffer, ref ParserInternalState state, out ParseContext ctx) + { + ctx.buffer = buffer; + ctx.state = state; + } + + /// + /// Creates a ParseContext instance from CodedInputStream. + /// WARNING: internally this copies the CodedInputStream's state, so after done with the ParseContext, + /// the CodedInputStream's state needs to be updated. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(CodedInputStream input, out ParseContext ctx) + { + ctx.buffer = new ReadOnlySpan(input.InternalBuffer); + // ideally we would use a reference to the original state, but that doesn't seem possible + // so we just copy the struct that holds the state. We will need to later store the state back + // into CodedInputStream if we want to keep it usable. + ctx.state = input.InternalState; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(ReadOnlySequence input, out ParseContext ctx) + { + Initialize(input, DefaultRecursionLimit, out ctx); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(ReadOnlySequence input, int recursionLimit, out ParseContext ctx) + { + ctx.buffer = default; + ctx.state = default; + ctx.state.lastTag = 0; + ctx.state.recursionDepth = 0; + ctx.state.sizeLimit = DefaultSizeLimit; + ctx.state.recursionLimit = recursionLimit; + ctx.state.currentLimit = int.MaxValue; + SegmentedBufferHelper.Initialize(input, out ctx.state.segmentedBufferHelper, out ctx.buffer); + ctx.state.bufferPos = 0; + ctx.state.bufferSize = ctx.buffer.Length; + + ctx.state.DiscardUnknownFields = false; + ctx.state.ExtensionRegistry = null; + } + + /// + /// Returns the last tag read, or 0 if no tags have been read or we've read beyond + /// the end of the input. + /// + internal uint LastTag { get { return state.lastTag; } } + + /// + /// Internal-only property; when set to true, unknown fields will be discarded while parsing. + /// + internal bool DiscardUnknownFields { + get { return state.DiscardUnknownFields; } + set { state.DiscardUnknownFields = value; } + } + + /// + /// Internal-only property; provides extension identifiers to compatible messages while parsing. + /// + internal ExtensionRegistry ExtensionRegistry + { + get { return state.ExtensionRegistry; } + set { state.ExtensionRegistry = value; } + } + + /// + /// Reads a field tag, returning the tag of 0 for "end of input". + /// + /// + /// If this method returns 0, it doesn't necessarily mean the end of all + /// the data in this CodedInputReader; it may be the end of the logical input + /// for an embedded message, for example. + /// + /// The next field tag, or 0 for end of input. (0 is never a valid tag.) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public uint ReadTag() + { + return ParsingPrimitives.ParseTag(ref buffer, ref state); + } + + /// + /// Reads a double field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public double ReadDouble() + { + return ParsingPrimitives.ParseDouble(ref buffer, ref state); + } + + /// + /// Reads a float field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float ReadFloat() + { + return ParsingPrimitives.ParseFloat(ref buffer, ref state); + } + + /// + /// Reads a uint64 field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ulong ReadUInt64() + { + return ParsingPrimitives.ParseRawVarint64(ref buffer, ref state); + } + + /// + /// Reads an int64 field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public long ReadInt64() + { + return (long)ParsingPrimitives.ParseRawVarint64(ref buffer, ref state); + } + + /// + /// Reads an int32 field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int ReadInt32() + { + return (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + } + + /// + /// Reads a fixed64 field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ulong ReadFixed64() + { + return ParsingPrimitives.ParseRawLittleEndian64(ref buffer, ref state); + } + + /// + /// Reads a fixed32 field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public uint ReadFixed32() + { + return ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state); + } + + /// + /// Reads a bool field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool ReadBool() + { + return ParsingPrimitives.ParseRawVarint64(ref buffer, ref state) != 0; + } + /// + /// Reads a string field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public string ReadString() + { + return ParsingPrimitives.ReadString(ref buffer, ref state); + } + + /// + /// Reads an embedded message field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ReadMessage(IMessage message) + { + ParsingPrimitivesMessages.ReadMessage(ref this, message); + } + + /// + /// Reads an embedded group field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ReadGroup(IMessage message) + { + ParsingPrimitivesMessages.ReadGroup(ref this, message); + } + + /// + /// Reads a bytes field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ByteString ReadBytes() + { + return ParsingPrimitives.ReadBytes(ref buffer, ref state); + } + /// + /// Reads a uint32 field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public uint ReadUInt32() + { + return ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + } + + /// + /// Reads an enum field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int ReadEnum() + { + // Currently just a pass-through, but it's nice to separate it logically from WriteInt32. + return (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + } + + /// + /// Reads an sfixed32 field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int ReadSFixed32() + { + return (int)ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state); + } + + /// + /// Reads an sfixed64 field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public long ReadSFixed64() + { + return (long)ParsingPrimitives.ParseRawLittleEndian64(ref buffer, ref state); + } + + /// + /// Reads an sint32 field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int ReadSInt32() + { + return ParsingPrimitives.DecodeZigZag32(ParsingPrimitives.ParseRawVarint32(ref buffer, ref state)); + } + + /// + /// Reads an sint64 field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public long ReadSInt64() + { + return ParsingPrimitives.DecodeZigZag64(ParsingPrimitives.ParseRawVarint64(ref buffer, ref state)); + } + + /// + /// Reads a length for length-delimited data. + /// + /// + /// This is internally just reading a varint, but this method exists + /// to make the calling code clearer. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int ReadLength() + { + return (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + } + + internal void CopyStateTo(CodedInputStream input) + { + input.InternalState = state; + } + + internal void LoadStateFrom(CodedInputStream input) + { + state = input.InternalState; + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/ParserInternalState.cs b/csharp/src/Google.Protobuf/ParserInternalState.cs new file mode 100644 index 0000000000000..cb4f47143cd80 --- /dev/null +++ b/csharp/src/Google.Protobuf/ParserInternalState.cs @@ -0,0 +1,115 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Buffers; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; +using Google.Protobuf.Collections; + +namespace Google.Protobuf +{ + + // warning: this is a mutable struct, so it needs to be only passed as a ref! + internal struct ParserInternalState + { + // NOTE: the Span representing the current buffer is kept separate so that this doesn't have to be a ref struct and so it can + // be included in CodedInputStream's internal state + + /// + /// The position within the current buffer (i.e. the next byte to read) + /// + internal int bufferPos; + + /// + /// Size of the current buffer + /// + internal int bufferSize; + + /// + /// If we are currently inside a length-delimited block, this is the number of + /// bytes in the buffer that are still available once we leave the delimited block. + /// + internal int bufferSizeAfterLimit; + + /// + /// The absolute position of the end of the current length-delimited block (including totalBytesRetired) + /// + internal int currentLimit; + + /// + /// The total number of consumed before the start of the current buffer. The + /// total bytes read up to the current position can be computed as + /// totalBytesRetired + bufferPos. + /// + internal int totalBytesRetired; + + internal int recursionDepth; // current recursion depth + + internal SegmentedBufferHelper segmentedBufferHelper; + + /// + /// The last tag we read. 0 indicates we've read to the end of the stream + /// (or haven't read anything yet). + /// + internal uint lastTag; + + /// + /// The next tag, used to store the value read by PeekTag. + /// + internal uint nextTag; + internal bool hasNextTag; + + // these fields are configuration, they should be readonly + internal int sizeLimit; + internal int recursionLimit; + + // If non-null, the top level parse method was started with given coded input stream as an argument + // which also means we can potentially fallback to calling MergeFrom(CodedInputStream cis) if needed. + internal CodedInputStream CodedInputStream => segmentedBufferHelper.CodedInputStream; + + /// + /// Internal-only property; when set to true, unknown fields will be discarded while parsing. + /// + internal bool DiscardUnknownFields { get; set; } + + /// + /// Internal-only property; provides extension identifiers to compatible messages while parsing. + /// + internal ExtensionRegistry ExtensionRegistry { get; set; } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/ParsingPrimitives.cs b/csharp/src/Google.Protobuf/ParsingPrimitives.cs new file mode 100644 index 0000000000000..e270ed8aa1f4d --- /dev/null +++ b/csharp/src/Google.Protobuf/ParsingPrimitives.cs @@ -0,0 +1,815 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Buffers; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; +using Google.Protobuf.Collections; + +namespace Google.Protobuf +{ + /// + /// Primitives for parsing protobuf wire format. + /// + [SecuritySafeCritical] + internal static class ParsingPrimitives + { + private const int StackallocThreshold = 256; + + /// + /// Reads a length for length-delimited data. + /// + /// + /// This is internally just reading a varint, but this method exists + /// to make the calling code clearer. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ParseLength(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + return (int)ParseRawVarint32(ref buffer, ref state); + } + + /// + /// Parses the next tag. + /// If the end of logical stream was reached, an invalid tag of 0 is returned. + /// + public static uint ParseTag(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + // The "nextTag" logic is there only as an optimization for reading non-packed repeated / map + // fields and is strictly speaking not necessary. + // TODO(jtattermusch): look into simplifying the ParseTag logic. + if (state.hasNextTag) + { + state.lastTag = state.nextTag; + state.hasNextTag = false; + return state.lastTag; + } + + // Optimize for the incredibly common case of having at least two bytes left in the buffer, + // and those two bytes being enough to get the tag. This will be true for fields up to 4095. + if (state.bufferPos + 2 <= state.bufferSize) + { + int tmp = buffer[state.bufferPos++]; + if (tmp < 128) + { + state.lastTag = (uint)tmp; + } + else + { + int result = tmp & 0x7f; + if ((tmp = buffer[state.bufferPos++]) < 128) + { + result |= tmp << 7; + state.lastTag = (uint) result; + } + else + { + // Nope, rewind and go the potentially slow route. + state.bufferPos -= 2; + state.lastTag = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + } + } + } + else + { + if (SegmentedBufferHelper.IsAtEnd(ref buffer, ref state)) + { + state.lastTag = 0; + return 0; + } + + state.lastTag = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + } + if (WireFormat.GetTagFieldNumber(state.lastTag) == 0) + { + // If we actually read a tag with a field of 0, that's not a valid tag. + throw InvalidProtocolBufferException.InvalidTag(); + } + return state.lastTag; + } + + /// + /// Peeks at the next tag in the stream. If it matches , + /// the tag is consumed and the method returns true; otherwise, the + /// stream is left in the original position and the method returns false. + /// + public static bool MaybeConsumeTag(ref ReadOnlySpan buffer, ref ParserInternalState state, uint tag) + { + if (PeekTag(ref buffer, ref state) == tag) + { + state.hasNextTag = false; + return true; + } + return false; + } + + /// + /// Peeks at the next field tag. This is like calling , but the + /// tag is not consumed. (So a subsequent call to will return the + /// same value.) + /// + public static uint PeekTag(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + if (state.hasNextTag) + { + return state.nextTag; + } + + uint savedLast = state.lastTag; + state.nextTag = ParseTag(ref buffer, ref state); + state.hasNextTag = true; + state.lastTag = savedLast; // Undo the side effect of ReadTag + return state.nextTag; + } + + /// + /// Parses a raw varint. + /// + public static ulong ParseRawVarint64(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + if (state.bufferPos + 10 > state.bufferSize) + { + return ParseRawVarint64SlowPath(ref buffer, ref state); + } + + ulong result = buffer[state.bufferPos++]; + if (result < 128) + { + return result; + } + result &= 0x7f; + int shift = 7; + do + { + byte b = buffer[state.bufferPos++]; + result |= (ulong)(b & 0x7F) << shift; + if (b < 0x80) + { + return result; + } + shift += 7; + } + while (shift < 64); + + throw InvalidProtocolBufferException.MalformedVarint(); + } + + private static ulong ParseRawVarint64SlowPath(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + int shift = 0; + ulong result = 0; + do + { + byte b = ReadRawByte(ref buffer, ref state); + result |= (ulong)(b & 0x7F) << shift; + if (b < 0x80) + { + return result; + } + shift += 7; + } + while (shift < 64); + + throw InvalidProtocolBufferException.MalformedVarint(); + } + + /// + /// Parses a raw Varint. If larger than 32 bits, discard the upper bits. + /// This method is optimised for the case where we've got lots of data in the buffer. + /// That means we can check the size just once, then just read directly from the buffer + /// without constant rechecking of the buffer length. + /// + public static uint ParseRawVarint32(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + if (state.bufferPos + 5 > state.bufferSize) + { + return ParseRawVarint32SlowPath(ref buffer, ref state); + } + + int tmp = buffer[state.bufferPos++]; + if (tmp < 128) + { + return (uint)tmp; + } + int result = tmp & 0x7f; + if ((tmp = buffer[state.bufferPos++]) < 128) + { + result |= tmp << 7; + } + else + { + result |= (tmp & 0x7f) << 7; + if ((tmp = buffer[state.bufferPos++]) < 128) + { + result |= tmp << 14; + } + else + { + result |= (tmp & 0x7f) << 14; + if ((tmp = buffer[state.bufferPos++]) < 128) + { + result |= tmp << 21; + } + else + { + result |= (tmp & 0x7f) << 21; + result |= (tmp = buffer[state.bufferPos++]) << 28; + if (tmp >= 128) + { + // Discard upper 32 bits. + // Note that this has to use ReadRawByte() as we only ensure we've + // got at least 5 bytes at the start of the method. This lets us + // use the fast path in more cases, and we rarely hit this section of code. + for (int i = 0; i < 5; i++) + { + if (ReadRawByte(ref buffer, ref state) < 128) + { + return (uint) result; + } + } + throw InvalidProtocolBufferException.MalformedVarint(); + } + } + } + } + return (uint)result; + } + + private static uint ParseRawVarint32SlowPath(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + int tmp = ReadRawByte(ref buffer, ref state); + if (tmp < 128) + { + return (uint) tmp; + } + int result = tmp & 0x7f; + if ((tmp = ReadRawByte(ref buffer, ref state)) < 128) + { + result |= tmp << 7; + } + else + { + result |= (tmp & 0x7f) << 7; + if ((tmp = ReadRawByte(ref buffer, ref state)) < 128) + { + result |= tmp << 14; + } + else + { + result |= (tmp & 0x7f) << 14; + if ((tmp = ReadRawByte(ref buffer, ref state)) < 128) + { + result |= tmp << 21; + } + else + { + result |= (tmp & 0x7f) << 21; + result |= (tmp = ReadRawByte(ref buffer, ref state)) << 28; + if (tmp >= 128) + { + // Discard upper 32 bits. + for (int i = 0; i < 5; i++) + { + if (ReadRawByte(ref buffer, ref state) < 128) + { + return (uint) result; + } + } + throw InvalidProtocolBufferException.MalformedVarint(); + } + } + } + } + return (uint) result; + } + + /// + /// Parses a 32-bit little-endian integer. + /// + public static uint ParseRawLittleEndian32(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + const int uintLength = sizeof(uint); + const int ulongLength = sizeof(ulong); + if (state.bufferPos + ulongLength > state.bufferSize) + { + return ParseRawLittleEndian32SlowPath(ref buffer, ref state); + } + // ReadUInt32LittleEndian is many times slower than ReadUInt64LittleEndian (at least on some runtimes) + // so it's faster better to use ReadUInt64LittleEndian and truncate the result. + uint result = (uint) BinaryPrimitives.ReadUInt64LittleEndian(buffer.Slice(state.bufferPos, ulongLength)); + state.bufferPos += uintLength; + return result; + } + + private static uint ParseRawLittleEndian32SlowPath(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + uint b1 = ReadRawByte(ref buffer, ref state); + uint b2 = ReadRawByte(ref buffer, ref state); + uint b3 = ReadRawByte(ref buffer, ref state); + uint b4 = ReadRawByte(ref buffer, ref state); + return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24); + } + + /// + /// Parses a 64-bit little-endian integer. + /// + public static ulong ParseRawLittleEndian64(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + const int length = sizeof(ulong); + if (state.bufferPos + length > state.bufferSize) + { + return ParseRawLittleEndian64SlowPath(ref buffer, ref state); + } + ulong result = BinaryPrimitives.ReadUInt64LittleEndian(buffer.Slice(state.bufferPos, length)); + state.bufferPos += length; + return result; + } + + private static ulong ParseRawLittleEndian64SlowPath(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + ulong b1 = ReadRawByte(ref buffer, ref state); + ulong b2 = ReadRawByte(ref buffer, ref state); + ulong b3 = ReadRawByte(ref buffer, ref state); + ulong b4 = ReadRawByte(ref buffer, ref state); + ulong b5 = ReadRawByte(ref buffer, ref state); + ulong b6 = ReadRawByte(ref buffer, ref state); + ulong b7 = ReadRawByte(ref buffer, ref state); + ulong b8 = ReadRawByte(ref buffer, ref state); + return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24) + | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56); + } + + /// + /// Parses a double value. + /// + public static double ParseDouble(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + const int length = sizeof(double); + if (!BitConverter.IsLittleEndian || state.bufferPos + length > state.bufferSize) + { + return BitConverter.Int64BitsToDouble((long)ParseRawLittleEndian64(ref buffer, ref state)); + } + // ReadUnaligned uses processor architecture for endianness. + double result = Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(buffer.Slice(state.bufferPos, length))); + state.bufferPos += length; + return result; + } + + /// + /// Parses a float value. + /// + public static float ParseFloat(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + const int length = sizeof(float); + if (!BitConverter.IsLittleEndian || state.bufferPos + length > state.bufferSize) + { + return ParseFloatSlow(ref buffer, ref state); + } + // ReadUnaligned uses processor architecture for endianness. + float result = Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(buffer.Slice(state.bufferPos, length))); + state.bufferPos += length; + return result; + } + + private static unsafe float ParseFloatSlow(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + const int length = sizeof(float); + byte* stackBuffer = stackalloc byte[length]; + Span tempSpan = new Span(stackBuffer, length); + for (int i = 0; i < length; i++) + { + tempSpan[i] = ReadRawByte(ref buffer, ref state); + } + + // Content is little endian. Reverse if needed to match endianness of architecture. + if (!BitConverter.IsLittleEndian) + { + tempSpan.Reverse(); + } + return Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(tempSpan)); + } + + /// + /// Reads a fixed size of bytes from the input. + /// + /// + /// the end of the stream or the current limit was reached + /// + public static byte[] ReadRawBytes(ref ReadOnlySpan buffer, ref ParserInternalState state, int size) + { + if (size < 0) + { + throw InvalidProtocolBufferException.NegativeSize(); + } + + if (size <= state.bufferSize - state.bufferPos) + { + // We have all the bytes we need already. + byte[] bytes = new byte[size]; + buffer.Slice(state.bufferPos, size).CopyTo(bytes); + state.bufferPos += size; + return bytes; + } + + return ReadRawBytesSlow(ref buffer, ref state, size); + } + + private static byte[] ReadRawBytesSlow(ref ReadOnlySpan buffer, ref ParserInternalState state, int size) + { + ValidateCurrentLimit(ref buffer, ref state, size); + + if ((!state.segmentedBufferHelper.TotalLength.HasValue && size < buffer.Length) || + IsDataAvailableInSource(ref state, size)) + { + // Reading more bytes than are in the buffer, but not an excessive number + // of bytes. We can safely allocate the resulting array ahead of time. + + byte[] bytes = new byte[size]; + ReadRawBytesIntoSpan(ref buffer, ref state, size, bytes); + return bytes; + } + else + { + // The size is very large. For security reasons, we can't allocate the + // entire byte array yet. The size comes directly from the input, so a + // maliciously-crafted message could provide a bogus very large size in + // order to trick the app into allocating a lot of memory. We avoid this + // by allocating and reading only a small chunk at a time, so that the + // malicious message must actually *be* extremely large to cause + // problems. Meanwhile, we limit the allowed size of a message elsewhere. + + List chunks = new List(); + + int pos = state.bufferSize - state.bufferPos; + byte[] firstChunk = new byte[pos]; + buffer.Slice(state.bufferPos, pos).CopyTo(firstChunk); + chunks.Add(firstChunk); + state.bufferPos = state.bufferSize; + + // Read all the rest of the bytes we need. + int sizeLeft = size - pos; + while (sizeLeft > 0) + { + state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true); + byte[] chunk = new byte[Math.Min(sizeLeft, state.bufferSize)]; + + buffer.Slice(0, chunk.Length) + .CopyTo(chunk); + state.bufferPos += chunk.Length; + sizeLeft -= chunk.Length; + chunks.Add(chunk); + } + + // OK, got everything. Now concatenate it all into one buffer. + byte[] bytes = new byte[size]; + int newPos = 0; + foreach (byte[] chunk in chunks) + { + Buffer.BlockCopy(chunk, 0, bytes, newPos, chunk.Length); + newPos += chunk.Length; + } + + // Done. + return bytes; + } + } + + /// + /// Reads and discards bytes. + /// + /// the end of the stream + /// or the current limit was reached + public static void SkipRawBytes(ref ReadOnlySpan buffer, ref ParserInternalState state, int size) + { + if (size < 0) + { + throw InvalidProtocolBufferException.NegativeSize(); + } + + ValidateCurrentLimit(ref buffer, ref state, size); + + if (size <= state.bufferSize - state.bufferPos) + { + // We have all the bytes we need already. + state.bufferPos += size; + } + else + { + // Skipping more bytes than are in the buffer. First skip what we have. + int pos = state.bufferSize - state.bufferPos; + state.bufferPos = state.bufferSize; + + // TODO: If our segmented buffer is backed by a Stream that is seekable, we could skip the bytes more efficiently + // by simply updating stream's Position property. This used to be supported in the past, but the support was dropped + // because it would make the segmentedBufferHelper more complex. Support can be reintroduced if needed. + state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true); + + while (size - pos > state.bufferSize) + { + pos += state.bufferSize; + state.bufferPos = state.bufferSize; + state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true); + } + + state.bufferPos = size - pos; + } + } + + /// + /// Reads a string field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string ReadString(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + int length = ParsingPrimitives.ParseLength(ref buffer, ref state); + return ParsingPrimitives.ReadRawString(ref buffer, ref state, length); + } + + /// + /// Reads a bytes field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ByteString ReadBytes(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + int length = ParsingPrimitives.ParseLength(ref buffer, ref state); + return ByteString.AttachBytes(ParsingPrimitives.ReadRawBytes(ref buffer, ref state, length)); + } + + /// + /// Reads a UTF-8 string from the next "length" bytes. + /// + /// + /// the end of the stream or the current limit was reached + /// + [SecuritySafeCritical] + public static string ReadRawString(ref ReadOnlySpan buffer, ref ParserInternalState state, int length) + { + // No need to read any data for an empty string. + if (length == 0) + { + return string.Empty; + } + + if (length < 0) + { + throw InvalidProtocolBufferException.NegativeSize(); + } + +#if GOOGLE_PROTOBUF_SUPPORT_FAST_STRING + if (length <= state.bufferSize - state.bufferPos) + { + // Fast path: all bytes to decode appear in the same span. + ReadOnlySpan data = buffer.Slice(state.bufferPos, length); + + string value; + unsafe + { + fixed (byte* sourceBytes = &MemoryMarshal.GetReference(data)) + { + value = WritingPrimitives.Utf8Encoding.GetString(sourceBytes, length); + } + } + + state.bufferPos += length; + return value; + } +#endif + + return ReadStringSlow(ref buffer, ref state, length); + } + + /// + /// Reads a string assuming that it is spread across multiple spans in a . + /// + private static string ReadStringSlow(ref ReadOnlySpan buffer, ref ParserInternalState state, int length) + { + ValidateCurrentLimit(ref buffer, ref state, length); + +#if GOOGLE_PROTOBUF_SUPPORT_FAST_STRING + if (IsDataAvailable(ref state, length)) + { + // Read string data into a temporary buffer, either stackalloc'ed or from ArrayPool + // Once all data is read then call Encoding.GetString on buffer and return to pool if needed. + + byte[] byteArray = null; + Span byteSpan = length <= StackallocThreshold ? + stackalloc byte[length] : + (byteArray = ArrayPool.Shared.Rent(length)); + + try + { + unsafe + { + fixed (byte* pByteSpan = &MemoryMarshal.GetReference(byteSpan)) + { + // Compiler doesn't like that a potentially stackalloc'd Span is being used + // in a method with a "ref Span buffer" argument. If the stackalloc'd span was assigned + // to the ref argument then bad things would happen. We'll never do that so it is ok. + // Make compiler happy by passing a new span created from pointer. + var tempSpan = new Span(pByteSpan, byteSpan.Length); + ReadRawBytesIntoSpan(ref buffer, ref state, length, tempSpan); + + return WritingPrimitives.Utf8Encoding.GetString(pByteSpan, length); + } + } + } + finally + { + if (byteArray != null) + { + ArrayPool.Shared.Return(byteArray); + } + } + } +#endif + + // Slow path: Build a byte array first then copy it. + // This will be called when reading from a Stream because we don't know the length of the stream, + // or there is not enough data in the sequence. If there is not enough data then ReadRawBytes will + // throw an exception. + return WritingPrimitives.Utf8Encoding.GetString(ReadRawBytes(ref buffer, ref state, length), 0, length); + } + + /// + /// Validates that the specified size doesn't exceed the current limit. If it does then remaining bytes + /// are skipped and an error is thrown. + /// + private static void ValidateCurrentLimit(ref ReadOnlySpan buffer, ref ParserInternalState state, int size) + { + if (state.totalBytesRetired + state.bufferPos + size > state.currentLimit) + { + // Read to the end of the stream (up to the current limit) anyway. + SkipRawBytes(ref buffer, ref state, state.currentLimit - state.totalBytesRetired - state.bufferPos); + // Then fail. + throw InvalidProtocolBufferException.TruncatedMessage(); + } + } + + [SecuritySafeCritical] + private static byte ReadRawByte(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + if (state.bufferPos == state.bufferSize) + { + state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true); + } + return buffer[state.bufferPos++]; + } + + /// + /// Reads a varint from the input one byte at a time, so that it does not + /// read any bytes after the end of the varint. If you simply wrapped the + /// stream in a CodedInputStream and used ReadRawVarint32(Stream) + /// then you would probably end up reading past the end of the varint since + /// CodedInputStream buffers its input. + /// + /// + /// + public static uint ReadRawVarint32(Stream input) + { + int result = 0; + int offset = 0; + for (; offset < 32; offset += 7) + { + int b = input.ReadByte(); + if (b == -1) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + result |= (b & 0x7f) << offset; + if ((b & 0x80) == 0) + { + return (uint) result; + } + } + // Keep reading up to 64 bits. + for (; offset < 64; offset += 7) + { + int b = input.ReadByte(); + if (b == -1) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + if ((b & 0x80) == 0) + { + return (uint) result; + } + } + throw InvalidProtocolBufferException.MalformedVarint(); + } + + /// + /// Decode a 32-bit value with ZigZag encoding. + /// + /// + /// ZigZag encodes signed integers into values that can be efficiently + /// encoded with varint. (Otherwise, negative values must be + /// sign-extended to 32 bits to be varint encoded, thus always taking + /// 5 bytes on the wire.) + /// + public static int DecodeZigZag32(uint n) + { + return (int)(n >> 1) ^ -(int)(n & 1); + } + + /// + /// Decode a 64-bit value with ZigZag encoding. + /// + /// + /// ZigZag encodes signed integers into values that can be efficiently + /// encoded with varint. (Otherwise, negative values must be + /// sign-extended to 64 bits to be varint encoded, thus always taking + /// 10 bytes on the wire.) + /// + public static long DecodeZigZag64(ulong n) + { + return (long)(n >> 1) ^ -(long)(n & 1); + } + + /// + /// Checks whether there is known data available of the specified size remaining to parse. + /// When parsing from a Stream this can return false because we have no knowledge of the amount + /// of data remaining in the stream until it is read. + /// + public static bool IsDataAvailable(ref ParserInternalState state, int size) + { + // Data fits in remaining buffer + if (size <= state.bufferSize - state.bufferPos) + { + return true; + } + + return IsDataAvailableInSource(ref state, size); + } + + /// + /// Checks whether there is known data available of the specified size remaining to parse + /// in the underlying data source. + /// When parsing from a Stream this will return false because we have no knowledge of the amount + /// of data remaining in the stream until it is read. + /// + private static bool IsDataAvailableInSource(ref ParserInternalState state, int size) + { + // Data fits in remaining source data. + // Note that this will never be true when reading from a stream as the total length is unknown. + return size <= state.segmentedBufferHelper.TotalLength - state.totalBytesRetired - state.bufferPos; + } + + /// + /// Read raw bytes of the specified length into a span. The amount of data available and the current limit should + /// be checked before calling this method. + /// + private static void ReadRawBytesIntoSpan(ref ReadOnlySpan buffer, ref ParserInternalState state, int length, Span byteSpan) + { + int remainingByteLength = length; + while (remainingByteLength > 0) + { + if (state.bufferSize - state.bufferPos == 0) + { + state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true); + } + + ReadOnlySpan unreadSpan = buffer.Slice(state.bufferPos, Math.Min(remainingByteLength, state.bufferSize - state.bufferPos)); + unreadSpan.CopyTo(byteSpan.Slice(length - remainingByteLength)); + + remainingByteLength -= unreadSpan.Length; + state.bufferPos += unreadSpan.Length; + } + } + } +} diff --git a/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs b/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs new file mode 100644 index 0000000000000..eabaf96d5c961 --- /dev/null +++ b/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs @@ -0,0 +1,292 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Buffers; +using System.Collections.Generic; +using System.IO; +using System.Runtime.CompilerServices; +using System.Security; +using Google.Protobuf.Collections; + +namespace Google.Protobuf +{ + /// + /// Reading and skipping messages / groups + /// + [SecuritySafeCritical] + internal static class ParsingPrimitivesMessages + { + private static readonly byte[] ZeroLengthMessageStreamData = new byte[] { 0 }; + + public static void SkipLastField(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + if (state.lastTag == 0) + { + throw new InvalidOperationException("SkipLastField cannot be called at the end of a stream"); + } + switch (WireFormat.GetTagWireType(state.lastTag)) + { + case WireFormat.WireType.StartGroup: + SkipGroup(ref buffer, ref state, state.lastTag); + break; + case WireFormat.WireType.EndGroup: + throw new InvalidProtocolBufferException( + "SkipLastField called on an end-group tag, indicating that the corresponding start-group was missing"); + case WireFormat.WireType.Fixed32: + ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state); + break; + case WireFormat.WireType.Fixed64: + ParsingPrimitives.ParseRawLittleEndian64(ref buffer, ref state); + break; + case WireFormat.WireType.LengthDelimited: + var length = ParsingPrimitives.ParseLength(ref buffer, ref state); + ParsingPrimitives.SkipRawBytes(ref buffer, ref state, length); + break; + case WireFormat.WireType.Varint: + ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + break; + } + } + + /// + /// Skip a group. + /// + public static void SkipGroup(ref ReadOnlySpan buffer, ref ParserInternalState state, uint startGroupTag) + { + // Note: Currently we expect this to be the way that groups are read. We could put the recursion + // depth changes into the ReadTag method instead, potentially... + state.recursionDepth++; + if (state.recursionDepth >= state.recursionLimit) + { + throw InvalidProtocolBufferException.RecursionLimitExceeded(); + } + uint tag; + while (true) + { + tag = ParsingPrimitives.ParseTag(ref buffer, ref state); + if (tag == 0) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + // Can't call SkipLastField for this case- that would throw. + if (WireFormat.GetTagWireType(tag) == WireFormat.WireType.EndGroup) + { + break; + } + // This recursion will allow us to handle nested groups. + SkipLastField(ref buffer, ref state); + } + int startField = WireFormat.GetTagFieldNumber(startGroupTag); + int endField = WireFormat.GetTagFieldNumber(tag); + if (startField != endField) + { + throw new InvalidProtocolBufferException( + $"Mismatched end-group tag. Started with field {startField}; ended with field {endField}"); + } + state.recursionDepth--; + } + + public static void ReadMessage(ref ParseContext ctx, IMessage message) + { + int length = ParsingPrimitives.ParseLength(ref ctx.buffer, ref ctx.state); + if (ctx.state.recursionDepth >= ctx.state.recursionLimit) + { + throw InvalidProtocolBufferException.RecursionLimitExceeded(); + } + int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length); + ++ctx.state.recursionDepth; + + ReadRawMessage(ref ctx, message); + + CheckReadEndOfStreamTag(ref ctx.state); + // Check that we've read exactly as much data as expected. + if (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state)) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + --ctx.state.recursionDepth; + SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit); + } + + public static KeyValuePair ReadMapEntry(ref ParseContext ctx, MapField.Codec codec) + { + int length = ParsingPrimitives.ParseLength(ref ctx.buffer, ref ctx.state); + if (ctx.state.recursionDepth >= ctx.state.recursionLimit) + { + throw InvalidProtocolBufferException.RecursionLimitExceeded(); + } + int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length); + ++ctx.state.recursionDepth; + + TKey key = codec.KeyCodec.DefaultValue; + TValue value = codec.ValueCodec.DefaultValue; + + uint tag; + while ((tag = ctx.ReadTag()) != 0) + { + if (tag == codec.KeyCodec.Tag) + { + key = codec.KeyCodec.Read(ref ctx); + } + else if (tag == codec.ValueCodec.Tag) + { + value = codec.ValueCodec.Read(ref ctx); + } + else + { + SkipLastField(ref ctx.buffer, ref ctx.state); + } + } + + // Corner case: a map entry with a key but no value, where the value type is a message. + // Read it as if we'd seen input with no data (i.e. create a "default" message). + if (value == null) + { + if (ctx.state.CodedInputStream != null) + { + // the decoded message might not support parsing from ParseContext, so + // we need to allow fallback to the legacy MergeFrom(CodedInputStream) parsing. + value = codec.ValueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData)); + } + else + { + ParseContext.Initialize(new ReadOnlySequence(ZeroLengthMessageStreamData), out ParseContext zeroLengthCtx); + value = codec.ValueCodec.Read(ref zeroLengthCtx); + } + } + + CheckReadEndOfStreamTag(ref ctx.state); + // Check that we've read exactly as much data as expected. + if (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state)) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + --ctx.state.recursionDepth; + SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit); + + return new KeyValuePair(key, value); + } + + public static void ReadGroup(ref ParseContext ctx, IMessage message) + { + if (ctx.state.recursionDepth >= ctx.state.recursionLimit) + { + throw InvalidProtocolBufferException.RecursionLimitExceeded(); + } + ++ctx.state.recursionDepth; + + uint tag = ctx.state.lastTag; + int fieldNumber = WireFormat.GetTagFieldNumber(tag); + ReadRawMessage(ref ctx, message); + CheckLastTagWas(ref ctx.state, WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup)); + + --ctx.state.recursionDepth; + } + + public static void ReadGroup(ref ParseContext ctx, int fieldNumber, UnknownFieldSet set) + { + if (ctx.state.recursionDepth >= ctx.state.recursionLimit) + { + throw InvalidProtocolBufferException.RecursionLimitExceeded(); + } + ++ctx.state.recursionDepth; + + set.MergeGroupFrom(ref ctx); + CheckLastTagWas(ref ctx.state, WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup)); + + --ctx.state.recursionDepth; + } + + public static void ReadRawMessage(ref ParseContext ctx, IMessage message) + { + if (message is IBufferMessage bufferMessage) + { + bufferMessage.InternalMergeFrom(ref ctx); + } + else + { + // If we reached here, it means we've ran into a nested message with older generated code + // which doesn't provide the InternalMergeFrom method that takes a ParseContext. + // With a slight performance overhead, we can still parse this message just fine, + // but we need to find the original CodedInputStream instance that initiated this + // parsing process and make sure its internal state is up to date. + // Note that this performance overhead is not very high (basically copying contents of a struct) + // and it will only be incurred in case the application mixes older and newer generated code. + // Regenerating the code from .proto files will remove this overhead because it will + // generate the InternalMergeFrom method we need. + + if (ctx.state.CodedInputStream == null) + { + // This can only happen when the parsing started without providing a CodedInputStream instance + // (e.g. ParseContext was created directly from a ReadOnlySequence). + // That also means that one of the new parsing APIs was used at the top level + // and in such case it is reasonable to require that all the nested message provide + // up-to-date generated code with ParseContext support (and fail otherwise). + throw new InvalidProtocolBufferException($"Message {message.GetType().Name} doesn't provide the generated method that enables ParseContext-based parsing. You might need to regenerate the generated protobuf code."); + } + + ctx.CopyStateTo(ctx.state.CodedInputStream); + try + { + // fallback parse using the CodedInputStream that started current parsing tree + message.MergeFrom(ctx.state.CodedInputStream); + } + finally + { + ctx.LoadStateFrom(ctx.state.CodedInputStream); + } + } + } + + /// + /// Verifies that the last call to ReadTag() returned tag 0 - in other words, + /// we've reached the end of the stream when we expected to. + /// + /// The + /// tag read was not the one specified + public static void CheckReadEndOfStreamTag(ref ParserInternalState state) + { + if (state.lastTag != 0) + { + throw InvalidProtocolBufferException.MoreDataAvailable(); + } + } + + private static void CheckLastTagWas(ref ParserInternalState state, uint expectedTag) + { + if (state.lastTag != expectedTag) { + throw InvalidProtocolBufferException.InvalidEndTag(); + } + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs b/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs new file mode 100644 index 0000000000000..629ec32bd81e9 --- /dev/null +++ b/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs @@ -0,0 +1,355 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Buffers; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; +using Google.Protobuf.Collections; + +namespace Google.Protobuf +{ + /// + /// Fast parsing primitives for wrapper types + /// + [SecuritySafeCritical] + internal static class ParsingPrimitivesWrappers + { + internal static float? ReadFloatWrapperLittleEndian(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + // length:1 + tag:1 + value:4 = 6 bytes + if (state.bufferPos + 6 <= state.bufferSize) + { + // The entire wrapper message is already contained in `buffer`. + int length = buffer[state.bufferPos]; + if (length == 0) + { + state.bufferPos++; + return 0F; + } + // tag:1 + value:4 = length of 5 bytes + // field=1, type=32-bit = tag of 13 + if (length != 5 || buffer[state.bufferPos + 1] != 13) + { + return ReadFloatWrapperSlow(ref buffer, ref state); + } + state.bufferPos += 2; + return ParsingPrimitives.ParseFloat(ref buffer, ref state); + } + else + { + return ReadFloatWrapperSlow(ref buffer, ref state); + } + } + + internal static float? ReadFloatWrapperSlow(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + int length = ParsingPrimitives.ParseLength(ref buffer, ref state); + if (length == 0) + { + return 0F; + } + int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; + float result = 0F; + do + { + // field=1, type=32-bit = tag of 13 + if (ParsingPrimitives.ParseTag(ref buffer, ref state) == 13) + { + result = ParsingPrimitives.ParseFloat(ref buffer, ref state); + } + else + { + ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state); + } + } + while (state.totalBytesRetired + state.bufferPos < finalBufferPos); + return result; + } + + internal static double? ReadDoubleWrapperLittleEndian(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + // length:1 + tag:1 + value:8 = 10 bytes + if (state.bufferPos + 10 <= state.bufferSize) + { + // The entire wrapper message is already contained in `buffer`. + int length = buffer[state.bufferPos]; + if (length == 0) + { + state.bufferPos++; + return 0D; + } + // tag:1 + value:8 = length of 9 bytes + // field=1, type=64-bit = tag of 9 + if (length != 9 || buffer[state.bufferPos + 1] != 9) + { + return ReadDoubleWrapperSlow(ref buffer, ref state); + } + state.bufferPos += 2; + return ParsingPrimitives.ParseDouble(ref buffer, ref state); + } + else + { + return ReadDoubleWrapperSlow(ref buffer, ref state); + } + } + + internal static double? ReadDoubleWrapperSlow(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + int length = ParsingPrimitives.ParseLength(ref buffer, ref state); + if (length == 0) + { + return 0D; + } + int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; + double result = 0D; + do + { + // field=1, type=64-bit = tag of 9 + if (ParsingPrimitives.ParseTag(ref buffer, ref state) == 9) + { + result = ParsingPrimitives.ParseDouble(ref buffer, ref state); + } + else + { + ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state); + } + } + while (state.totalBytesRetired + state.bufferPos < finalBufferPos); + return result; + } + + internal static bool? ReadBoolWrapper(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + return ReadUInt64Wrapper(ref buffer, ref state) != 0; + } + + internal static uint? ReadUInt32Wrapper(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + // field=1, type=varint = tag of 8 + const int expectedTag = 8; + // length:1 + tag:1 + value:10(varint64-max) = 12 bytes + // Value can be 64 bits for negative integers + if (state.bufferPos + 12 <= state.bufferSize) + { + // The entire wrapper message is already contained in `buffer`. + int pos0 = state.bufferPos; + int length = buffer[state.bufferPos++]; + if (length == 0) + { + return 0; + } + // Length will always fit in a single byte. + if (length >= 128) + { + state.bufferPos = pos0; + return ReadUInt32WrapperSlow(ref buffer, ref state); + } + int finalBufferPos = state.bufferPos + length; + if (buffer[state.bufferPos++] != expectedTag) + { + state.bufferPos = pos0; + return ReadUInt32WrapperSlow(ref buffer, ref state); + } + var result = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + // Verify this message only contained a single field. + if (state.bufferPos != finalBufferPos) + { + state.bufferPos = pos0; + return ReadUInt32WrapperSlow(ref buffer, ref state); + } + return result; + } + else + { + return ReadUInt32WrapperSlow(ref buffer, ref state); + } + } + + internal static uint? ReadUInt32WrapperSlow(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + int length = ParsingPrimitives.ParseLength(ref buffer, ref state); + if (length == 0) + { + return 0; + } + int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; + uint result = 0; + do + { + // field=1, type=varint = tag of 8 + if (ParsingPrimitives.ParseTag(ref buffer, ref state) == 8) + { + result = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + } + else + { + ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state); + } + } + while (state.totalBytesRetired + state.bufferPos < finalBufferPos); + return result; + } + + internal static int? ReadInt32Wrapper(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + return (int?)ReadUInt32Wrapper(ref buffer, ref state); + } + + internal static ulong? ReadUInt64Wrapper(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + // field=1, type=varint = tag of 8 + const int expectedTag = 8; + // length:1 + tag:1 + value:10(varint64-max) = 12 bytes + if (state.bufferPos + 12 <= state.bufferSize) + { + // The entire wrapper message is already contained in `buffer`. + int pos0 = state.bufferPos; + int length = buffer[state.bufferPos++]; + if (length == 0) + { + return 0L; + } + // Length will always fit in a single byte. + if (length >= 128) + { + state.bufferPos = pos0; + return ReadUInt64WrapperSlow(ref buffer, ref state); + } + int finalBufferPos = state.bufferPos + length; + if (buffer[state.bufferPos++] != expectedTag) + { + state.bufferPos = pos0; + return ReadUInt64WrapperSlow(ref buffer, ref state); + } + var result = ParsingPrimitives.ParseRawVarint64(ref buffer, ref state); + // Verify this message only contained a single field. + if (state.bufferPos != finalBufferPos) + { + state.bufferPos = pos0; + return ReadUInt64WrapperSlow(ref buffer, ref state); + } + return result; + } + else + { + return ReadUInt64WrapperSlow(ref buffer, ref state); + } + } + + internal static ulong? ReadUInt64WrapperSlow(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + // field=1, type=varint = tag of 8 + const int expectedTag = 8; + int length = ParsingPrimitives.ParseLength(ref buffer, ref state); + if (length == 0) + { + return 0L; + } + int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; + ulong result = 0L; + do + { + if (ParsingPrimitives.ParseTag(ref buffer, ref state) == expectedTag) + { + result = ParsingPrimitives.ParseRawVarint64(ref buffer, ref state); + } + else + { + ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state); + } + } + while (state.totalBytesRetired + state.bufferPos < finalBufferPos); + return result; + } + + internal static long? ReadInt64Wrapper(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + return (long?)ReadUInt64Wrapper(ref buffer, ref state); + } + + internal static float? ReadFloatWrapperLittleEndian(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadFloatWrapperLittleEndian(ref ctx.buffer, ref ctx.state); + } + + internal static float? ReadFloatWrapperSlow(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadFloatWrapperSlow(ref ctx.buffer, ref ctx.state); + } + + internal static double? ReadDoubleWrapperLittleEndian(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadDoubleWrapperLittleEndian(ref ctx.buffer, ref ctx.state); + } + + internal static double? ReadDoubleWrapperSlow(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadDoubleWrapperSlow(ref ctx.buffer, ref ctx.state); + } + + internal static bool? ReadBoolWrapper(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadBoolWrapper(ref ctx.buffer, ref ctx.state); + } + + internal static uint? ReadUInt32Wrapper(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadUInt32Wrapper(ref ctx.buffer, ref ctx.state); + } + + internal static int? ReadInt32Wrapper(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadInt32Wrapper(ref ctx.buffer, ref ctx.state); + } + + internal static ulong? ReadUInt64Wrapper(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadUInt64Wrapper(ref ctx.buffer, ref ctx.state); + } + + internal static ulong? ReadUInt64WrapperSlow(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadUInt64WrapperSlow(ref ctx.buffer, ref ctx.state); + } + + internal static long? ReadInt64Wrapper(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadInt64Wrapper(ref ctx.buffer, ref ctx.state); + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs b/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs index 9b179bd7cd60d..130bcf00041d1 100644 --- a/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs +++ b/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs @@ -47,3 +47,10 @@ "981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" + "b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" + "c5ae9cb6")] + +[assembly: InternalsVisibleTo("Google.Protobuf.Benchmarks, PublicKey=" + + "002400000480000094000000060200000024000052534131000400000100010025800fbcfc63a1" + + "7c66b303aae80b03a6beaa176bb6bef883be436f2a1579edd80ce23edf151a1f4ced97af83abcd" + + "981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" + + "b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" + + "c5ae9cb6")] diff --git a/csharp/src/Google.Protobuf/ProtoPreconditions.cs b/csharp/src/Google.Protobuf/ProtoPreconditions.cs index abaeb9b481d40..590a3bb20fc9e 100644 --- a/csharp/src/Google.Protobuf/ProtoPreconditions.cs +++ b/csharp/src/Google.Protobuf/ProtoPreconditions.cs @@ -1,79 +1,79 @@ -#region Copyright notice and license -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#endregion - -using System; - -namespace Google.Protobuf -{ - /// - /// Helper methods for throwing exceptions when preconditions are not met. - /// - /// - /// This class is used internally and by generated code; it is not particularly - /// expected to be used from application code, although nothing prevents it - /// from being used that way. - /// - public static class ProtoPreconditions - { - /// - /// Throws an ArgumentNullException if the given value is null, otherwise - /// return the value to the caller. - /// - public static T CheckNotNull(T value, string name) where T : class - { - if (value == null) - { - throw new ArgumentNullException(name); - } - return value; - } - - /// - /// Throws an ArgumentNullException if the given value is null, otherwise - /// return the value to the caller. - /// - /// - /// This is equivalent to but without the type parameter - /// constraint. In most cases, the constraint is useful to prevent you from calling CheckNotNull - /// with a value type - but it gets in the way if either you want to use it with a nullable - /// value type, or you want to use it with an unconstrained type parameter. - /// - internal static T CheckNotNullUnconstrained(T value, string name) - { - if (value == null) - { - throw new ArgumentNullException(name); - } - return value; - } - } +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; + +namespace Google.Protobuf +{ + /// + /// Helper methods for throwing exceptions when preconditions are not met. + /// + /// + /// This class is used internally and by generated code; it is not particularly + /// expected to be used from application code, although nothing prevents it + /// from being used that way. + /// + public static class ProtoPreconditions + { + /// + /// Throws an ArgumentNullException if the given value is null, otherwise + /// return the value to the caller. + /// + public static T CheckNotNull(T value, string name) where T : class + { + if (value == null) + { + throw new ArgumentNullException(name); + } + return value; + } + + /// + /// Throws an ArgumentNullException if the given value is null, otherwise + /// return the value to the caller. + /// + /// + /// This is equivalent to but without the type parameter + /// constraint. In most cases, the constraint is useful to prevent you from calling CheckNotNull + /// with a value type - but it gets in the way if either you want to use it with a nullable + /// value type, or you want to use it with an unconstrained type parameter. + /// + internal static T CheckNotNullUnconstrained(T value, string name) + { + if (value == null) + { + throw new ArgumentNullException(name); + } + return value; + } + } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs b/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs index 88b3ec000d315..9fc3766889b80 100644 --- a/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs +++ b/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs @@ -30,8 +30,12 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Collections; using System; +using System.Collections; using System.Collections.Generic; +using System.Linq; +using System.Reflection; namespace Google.Protobuf.Reflection { @@ -59,19 +63,13 @@ namespace Google.Protobuf.Reflection /// public sealed class CustomOptions { - /// - /// Singleton for all descriptors with an empty set of options. - /// - internal static readonly CustomOptions Empty = new CustomOptions(); - - /// - /// A sequence of values per field. This needs to be per field rather than per tag to allow correct deserialization - /// of repeated fields which could be "int, ByteString, int" - unlikely as that is. The fact that values are boxed - /// is unfortunate; we might be able to use a struct instead, and we could combine uint and ulong values. - /// - private readonly Dictionary> valuesByField = new Dictionary>(); + private static readonly object[] EmptyParameters = new object[0]; + private readonly IDictionary values; - private CustomOptions() { } + internal CustomOptions(IDictionary values) + { + this.values = values; + } /// /// Retrieves a Boolean value for the specified option field. @@ -79,12 +77,7 @@ private CustomOptions() { } /// The field to fetch the value for. /// The output variable to populate. /// true if a suitable value for the field was found; false otherwise. - public bool TryGetBool(int field, out bool value) - { - ulong? tmp = GetLastNumericValue(field); - value = tmp == 1UL; - return tmp != null; - } + public bool TryGetBool(int field, out bool value) => TryGetPrimitiveValue(field, out value); /// /// Retrieves a signed 32-bit integer value for the specified option field. @@ -92,12 +85,7 @@ public bool TryGetBool(int field, out bool value) /// The field to fetch the value for. /// The output variable to populate. /// true if a suitable value for the field was found; false otherwise. - public bool TryGetInt32(int field, out int value) - { - ulong? tmp = GetLastNumericValue(field); - value = (int) tmp.GetValueOrDefault(); - return tmp != null; - } + public bool TryGetInt32(int field, out int value) => TryGetPrimitiveValue(field, out value); /// /// Retrieves a signed 64-bit integer value for the specified option field. @@ -105,12 +93,7 @@ public bool TryGetInt32(int field, out int value) /// The field to fetch the value for. /// The output variable to populate. /// true if a suitable value for the field was found; false otherwise. - public bool TryGetInt64(int field, out long value) - { - ulong? tmp = GetLastNumericValue(field); - value = (long) tmp.GetValueOrDefault(); - return tmp != null; - } + public bool TryGetInt64(int field, out long value) => TryGetPrimitiveValue(field, out value); /// /// Retrieves an unsigned 32-bit integer value for the specified option field, @@ -147,7 +130,7 @@ public bool TryGetInt64(int field, out long value) /// The output variable to populate. /// true if a suitable value for the field was found; false otherwise. public bool TryGetSFixed64(int field, out long value) => TryGetInt64(field, out value); - + /// /// Retrieves a signed 32-bit integer value for the specified option field, /// assuming a zigzag encoding. @@ -155,12 +138,7 @@ public bool TryGetInt64(int field, out long value) /// The field to fetch the value for. /// The output variable to populate. /// true if a suitable value for the field was found; false otherwise. - public bool TryGetSInt32(int field, out int value) - { - ulong? tmp = GetLastNumericValue(field); - value = CodedInputStream.DecodeZigZag32((uint) tmp.GetValueOrDefault()); - return tmp != null; - } + public bool TryGetSInt32(int field, out int value) => TryGetPrimitiveValue(field, out value); /// /// Retrieves a signed 64-bit integer value for the specified option field, @@ -169,12 +147,7 @@ public bool TryGetSInt32(int field, out int value) /// The field to fetch the value for. /// The output variable to populate. /// true if a suitable value for the field was found; false otherwise. - public bool TryGetSInt64(int field, out long value) - { - ulong? tmp = GetLastNumericValue(field); - value = CodedInputStream.DecodeZigZag64(tmp.GetValueOrDefault()); - return tmp != null; - } + public bool TryGetSInt64(int field, out long value) => TryGetPrimitiveValue(field, out value); /// /// Retrieves an unsigned 32-bit integer value for the specified option field. @@ -182,12 +155,7 @@ public bool TryGetSInt64(int field, out long value) /// The field to fetch the value for. /// The output variable to populate. /// true if a suitable value for the field was found; false otherwise. - public bool TryGetUInt32(int field, out uint value) - { - ulong? tmp = GetLastNumericValue(field); - value = (uint) tmp.GetValueOrDefault(); - return tmp != null; - } + public bool TryGetUInt32(int field, out uint value) => TryGetPrimitiveValue(field, out value); /// /// Retrieves an unsigned 64-bit integer value for the specified option field. @@ -195,12 +163,7 @@ public bool TryGetUInt32(int field, out uint value) /// The field to fetch the value for. /// The output variable to populate. /// true if a suitable value for the field was found; false otherwise. - public bool TryGetUInt64(int field, out ulong value) - { - ulong? tmp = GetLastNumericValue(field); - value = tmp.GetValueOrDefault(); - return tmp != null; - } + public bool TryGetUInt64(int field, out ulong value) => TryGetPrimitiveValue(field, out value); /// /// Retrieves a 32-bit floating point value for the specified option field. @@ -208,14 +171,7 @@ public bool TryGetUInt64(int field, out ulong value) /// The field to fetch the value for. /// The output variable to populate. /// true if a suitable value for the field was found; false otherwise. - public bool TryGetFloat(int field, out float value) - { - ulong? tmp = GetLastNumericValue(field); - int int32 = (int) tmp.GetValueOrDefault(); - byte[] bytes = BitConverter.GetBytes(int32); - value = BitConverter.ToSingle(bytes, 0); - return tmp != null; - } + public bool TryGetFloat(int field, out float value) => TryGetPrimitiveValue(field, out value); /// /// Retrieves a 64-bit floating point value for the specified option field. @@ -223,12 +179,7 @@ public bool TryGetFloat(int field, out float value) /// The field to fetch the value for. /// The output variable to populate. /// true if a suitable value for the field was found; false otherwise. - public bool TryGetDouble(int field, out double value) - { - ulong? tmp = GetLastNumericValue(field); - value = BitConverter.Int64BitsToDouble((long) tmp.GetValueOrDefault()); - return tmp != null; - } + public bool TryGetDouble(int field, out double value) => TryGetPrimitiveValue(field, out value); /// /// Retrieves a string value for the specified option field. @@ -236,12 +187,7 @@ public bool TryGetDouble(int field, out double value) /// The field to fetch the value for. /// The output variable to populate. /// true if a suitable value for the field was found; false otherwise. - public bool TryGetString(int field, out string value) - { - ByteString bytes = GetLastByteStringValue(field); - value = bytes?.ToStringUtf8(); - return bytes != null; - } + public bool TryGetString(int field, out string value) => TryGetPrimitiveValue(field, out value); /// /// Retrieves a bytes value for the specified option field. @@ -249,12 +195,7 @@ public bool TryGetString(int field, out string value) /// The field to fetch the value for. /// The output variable to populate. /// true if a suitable value for the field was found; false otherwise. - public bool TryGetBytes(int field, out ByteString value) - { - ByteString bytes = GetLastByteStringValue(field); - value = bytes; - return bytes != null; - } + public bool TryGetBytes(int field, out ByteString value) => TryGetPrimitiveValue(field, out value); /// /// Retrieves a message value for the specified option field. @@ -264,127 +205,100 @@ public bool TryGetBytes(int field, out ByteString value) /// true if a suitable value for the field was found; false otherwise. public bool TryGetMessage(int field, out T value) where T : class, IMessage, new() { - value = null; - List values; - if (!valuesByField.TryGetValue(field, out values)) + if (values == null) { + value = default(T); return false; } - foreach (FieldValue fieldValue in values) - { - if (fieldValue.ByteString != null) - { - if (value == null) - { - value = new T(); - } - value.MergeFrom(fieldValue.ByteString); - } - } - return value != null; - } - private ulong? GetLastNumericValue(int field) - { - List values; - if (!valuesByField.TryGetValue(field, out values)) - { - return null; - } - for (int i = values.Count - 1; i >= 0; i--) + IExtensionValue extensionValue; + if (values.TryGetValue(field, out extensionValue)) { - // A non-bytestring value is a numeric value - if (values[i].ByteString == null) + if (extensionValue is ExtensionValue) { - return values[i].Number; + ExtensionValue single = extensionValue as ExtensionValue; + ByteString bytes = single.GetValue().ToByteString(); + value = new T(); + value.MergeFrom(bytes); + return true; } - } - return null; - } - - private ByteString GetLastByteStringValue(int field) - { - List values; - if (!valuesByField.TryGetValue(field, out values)) - { - return null; - } - for (int i = values.Count - 1; i >= 0; i--) - { - if (values[i].ByteString != null) + else if (extensionValue is RepeatedExtensionValue) { - return values[i].ByteString; + RepeatedExtensionValue repeated = extensionValue as RepeatedExtensionValue; + value = repeated.GetValue() + .Select(v => v.ToByteString()) + .Aggregate(new T(), (t, b) => + { + t.MergeFrom(b); + return t; + }); + return true; } } - return null; - } - /// - /// Reads an unknown field, either parsing it and storing it or skipping it. - /// - /// - /// If the current set of options is empty and we manage to read a field, a new set of options - /// will be created and returned. Otherwise, the return value is this. This allows - /// us to start with a singleton empty set of options and just create new ones where necessary. - /// - /// Input stream to read from. - /// The resulting set of custom options, either this or a new set. - internal CustomOptions ReadOrSkipUnknownField(CodedInputStream input) - { - var tag = input.LastTag; - var field = WireFormat.GetTagFieldNumber(tag); - switch (WireFormat.GetTagWireType(tag)) - { - case WireFormat.WireType.LengthDelimited: - return AddValue(field, new FieldValue(input.ReadBytes())); - case WireFormat.WireType.Fixed32: - return AddValue(field, new FieldValue(input.ReadFixed32())); - case WireFormat.WireType.Fixed64: - return AddValue(field, new FieldValue(input.ReadFixed64())); - case WireFormat.WireType.Varint: - return AddValue(field, new FieldValue(input.ReadRawVarint64())); - // For StartGroup, EndGroup or any wire format we don't understand, - // just use the normal behavior (call SkipLastField). - default: - input.SkipLastField(); - return this; - } + value = null; + return false; } - private CustomOptions AddValue(int field, FieldValue value) + private bool TryGetPrimitiveValue(int field, out T value) { - var ret = valuesByField.Count == 0 ? new CustomOptions() : this; - List valuesForField; - if (!ret.valuesByField.TryGetValue(field, out valuesForField)) + if (values == null) { - // Expect almost all - valuesForField = new List(1); - ret.valuesByField[field] = valuesForField; + value = default(T); + return false; } - valuesForField.Add(value); - return ret; - } - /// - /// All field values can be stored as a byte string or a 64-bit integer. - /// This struct avoids unnecessary boxing. - /// - private struct FieldValue - { - internal ulong Number { get; } - internal ByteString ByteString { get; } - - internal FieldValue(ulong number) + IExtensionValue extensionValue; + if (values.TryGetValue(field, out extensionValue)) { - Number = number; - ByteString = null; + if (extensionValue is ExtensionValue) + { + ExtensionValue single = extensionValue as ExtensionValue; + value = single.GetValue(); + return true; + } + else if (extensionValue is RepeatedExtensionValue) + { + RepeatedExtensionValue repeated = extensionValue as RepeatedExtensionValue; + if (repeated.GetValue().Count != 0) + { + RepeatedField repeatedField = repeated.GetValue(); + value = repeatedField[repeatedField.Count - 1]; + return true; + } + } + else // and here we find explicit enum handling since T : Enum ! x is ExtensionValue + { + var type = extensionValue.GetType(); + if (type.GetGenericTypeDefinition() == typeof(ExtensionValue<>)) + { + var typeInfo = type.GetTypeInfo(); + var typeArgs = typeInfo.GenericTypeArguments; + if (typeArgs.Length == 1 && typeArgs[0].GetTypeInfo().IsEnum) + { + value = (T)typeInfo.GetDeclaredMethod(nameof(ExtensionValue.GetValue)).Invoke(extensionValue, EmptyParameters); + return true; + } + } + else if (type.GetGenericTypeDefinition() == typeof(RepeatedExtensionValue<>)) + { + var typeInfo = type.GetTypeInfo(); + var typeArgs = typeInfo.GenericTypeArguments; + if (typeArgs.Length == 1 && typeArgs[0].GetTypeInfo().IsEnum) + { + var values = (IList)typeInfo.GetDeclaredMethod(nameof(RepeatedExtensionValue.GetValue)).Invoke(extensionValue, EmptyParameters); + if (values.Count != 0) + { + value = (T)values[values.Count - 1]; + return true; + } + } + } + } } - internal FieldValue(ByteString byteString) - { - Number = 0; - ByteString = byteString; - } + value = default(T); + return false; } } } diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs index 8311a2c656476..0a1f4a74408a3 100644 --- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs @@ -1,5 +1,7 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/descriptor.proto +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/descriptor.proto +// #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -10,7 +12,7 @@ namespace Google.Protobuf.Reflection { /// Holder for reflection information generated from google/protobuf/descriptor.proto - internal static partial class DescriptorReflection { + public static partial class DescriptorReflection { #region Descriptor /// File descriptor for google/protobuf/descriptor.proto @@ -52,7 +54,7 @@ static DescriptorReflection() { "b2J1Zi5FeHRlbnNpb25SYW5nZU9wdGlvbnMaKwoNUmVzZXJ2ZWRSYW5nZRIN", "CgVzdGFydBgBIAEoBRILCgNlbmQYAiABKAUiZwoVRXh0ZW5zaW9uUmFuZ2VP", "cHRpb25zEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2ds", - "ZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIivAUK", + "ZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIi1QUK", "FEZpZWxkRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSDgoGbnVtYmVy", "GAMgASgFEjoKBWxhYmVsGAQgASgOMisuZ29vZ2xlLnByb3RvYnVmLkZpZWxk", "RGVzY3JpcHRvclByb3RvLkxhYmVsEjgKBHR5cGUYBSABKA4yKi5nb29nbGUu", @@ -60,123 +62,127 @@ static DescriptorReflection() { "bWUYBiABKAkSEAoIZXh0ZW5kZWUYAiABKAkSFQoNZGVmYXVsdF92YWx1ZRgH", "IAEoCRITCgtvbmVvZl9pbmRleBgJIAEoBRIRCglqc29uX25hbWUYCiABKAkS", "LgoHb3B0aW9ucxgIIAEoCzIdLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlv", - "bnMitgIKBFR5cGUSDwoLVFlQRV9ET1VCTEUQARIOCgpUWVBFX0ZMT0FUEAIS", - "DgoKVFlQRV9JTlQ2NBADEg8KC1RZUEVfVUlOVDY0EAQSDgoKVFlQRV9JTlQz", - "MhAFEhAKDFRZUEVfRklYRUQ2NBAGEhAKDFRZUEVfRklYRUQzMhAHEg0KCVRZ", - "UEVfQk9PTBAIEg8KC1RZUEVfU1RSSU5HEAkSDgoKVFlQRV9HUk9VUBAKEhAK", - "DFRZUEVfTUVTU0FHRRALEg4KClRZUEVfQllURVMQDBIPCgtUWVBFX1VJTlQz", - "MhANEg0KCVRZUEVfRU5VTRAOEhEKDVRZUEVfU0ZJWEVEMzIQDxIRCg1UWVBF", - "X1NGSVhFRDY0EBASDwoLVFlQRV9TSU5UMzIQERIPCgtUWVBFX1NJTlQ2NBAS", - "IkMKBUxhYmVsEhIKDkxBQkVMX09QVElPTkFMEAESEgoOTEFCRUxfUkVRVUlS", - "RUQQAhISCg5MQUJFTF9SRVBFQVRFRBADIlQKFE9uZW9mRGVzY3JpcHRvclBy", - "b3RvEgwKBG5hbWUYASABKAkSLgoHb3B0aW9ucxgCIAEoCzIdLmdvb2dsZS5w", - "cm90b2J1Zi5PbmVvZk9wdGlvbnMijAEKE0VudW1EZXNjcmlwdG9yUHJvdG8S", - "DAoEbmFtZRgBIAEoCRI4CgV2YWx1ZRgCIAMoCzIpLmdvb2dsZS5wcm90b2J1", - "Zi5FbnVtVmFsdWVEZXNjcmlwdG9yUHJvdG8SLQoHb3B0aW9ucxgDIAEoCzIc", - "Lmdvb2dsZS5wcm90b2J1Zi5FbnVtT3B0aW9ucyJsChhFbnVtVmFsdWVEZXNj", - "cmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRIOCgZudW1iZXIYAiABKAUSMgoH", - "b3B0aW9ucxgDIAEoCzIhLmdvb2dsZS5wcm90b2J1Zi5FbnVtVmFsdWVPcHRp", - "b25zIpABChZTZXJ2aWNlRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkS", - "NgoGbWV0aG9kGAIgAygLMiYuZ29vZ2xlLnByb3RvYnVmLk1ldGhvZERlc2Ny", - "aXB0b3JQcm90bxIwCgdvcHRpb25zGAMgASgLMh8uZ29vZ2xlLnByb3RvYnVm", - "LlNlcnZpY2VPcHRpb25zIsEBChVNZXRob2REZXNjcmlwdG9yUHJvdG8SDAoE", - "bmFtZRgBIAEoCRISCgppbnB1dF90eXBlGAIgASgJEhMKC291dHB1dF90eXBl", - "GAMgASgJEi8KB29wdGlvbnMYBCABKAsyHi5nb29nbGUucHJvdG9idWYuTWV0", - "aG9kT3B0aW9ucxIfChBjbGllbnRfc3RyZWFtaW5nGAUgASgIOgVmYWxzZRIf", - "ChBzZXJ2ZXJfc3RyZWFtaW5nGAYgASgIOgVmYWxzZSLwBQoLRmlsZU9wdGlv", - "bnMSFAoMamF2YV9wYWNrYWdlGAEgASgJEhwKFGphdmFfb3V0ZXJfY2xhc3Nu", - "YW1lGAggASgJEiIKE2phdmFfbXVsdGlwbGVfZmlsZXMYCiABKAg6BWZhbHNl", - "EikKHWphdmFfZ2VuZXJhdGVfZXF1YWxzX2FuZF9oYXNoGBQgASgIQgIYARIl", - "ChZqYXZhX3N0cmluZ19jaGVja191dGY4GBsgASgIOgVmYWxzZRJGCgxvcHRp", - "bWl6ZV9mb3IYCSABKA4yKS5nb29nbGUucHJvdG9idWYuRmlsZU9wdGlvbnMu", - "T3B0aW1pemVNb2RlOgVTUEVFRBISCgpnb19wYWNrYWdlGAsgASgJEiIKE2Nj", - "X2dlbmVyaWNfc2VydmljZXMYECABKAg6BWZhbHNlEiQKFWphdmFfZ2VuZXJp", - "Y19zZXJ2aWNlcxgRIAEoCDoFZmFsc2USIgoTcHlfZ2VuZXJpY19zZXJ2aWNl", - "cxgSIAEoCDoFZmFsc2USIwoUcGhwX2dlbmVyaWNfc2VydmljZXMYEyABKAg6", - "BWZhbHNlEhkKCmRlcHJlY2F0ZWQYFyABKAg6BWZhbHNlEh8KEGNjX2VuYWJs", - "ZV9hcmVuYXMYHyABKAg6BWZhbHNlEhkKEW9iamNfY2xhc3NfcHJlZml4GCQg", - "ASgJEhgKEGNzaGFycF9uYW1lc3BhY2UYJSABKAkSFAoMc3dpZnRfcHJlZml4", - "GCcgASgJEhgKEHBocF9jbGFzc19wcmVmaXgYKCABKAkSFQoNcGhwX25hbWVz", - "cGFjZRgpIAEoCRJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5n", - "b29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbiI6CgxPcHRpbWl6", - "ZU1vZGUSCQoFU1BFRUQQARINCglDT0RFX1NJWkUQAhIQCgxMSVRFX1JVTlRJ", - "TUUQAyoJCOgHEICAgIACSgQIJhAnIvIBCg5NZXNzYWdlT3B0aW9ucxImChdt", - "ZXNzYWdlX3NldF93aXJlX2Zvcm1hdBgBIAEoCDoFZmFsc2USLgofbm9fc3Rh", - "bmRhcmRfZGVzY3JpcHRvcl9hY2Nlc3NvchgCIAEoCDoFZmFsc2USGQoKZGVw", - "cmVjYXRlZBgDIAEoCDoFZmFsc2USEQoJbWFwX2VudHJ5GAcgASgIEkMKFHVu", - "aW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5V", - "bmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAJKBAgIEAlKBAgJEAoingMK", - "DEZpZWxkT3B0aW9ucxI6CgVjdHlwZRgBIAEoDjIjLmdvb2dsZS5wcm90b2J1", - "Zi5GaWVsZE9wdGlvbnMuQ1R5cGU6BlNUUklORxIOCgZwYWNrZWQYAiABKAgS", - "PwoGanN0eXBlGAYgASgOMiQuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9u", - "cy5KU1R5cGU6CUpTX05PUk1BTBITCgRsYXp5GAUgASgIOgVmYWxzZRIZCgpk", - "ZXByZWNhdGVkGAMgASgIOgVmYWxzZRITCgR3ZWFrGAogASgIOgVmYWxzZRJD", - "ChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9i", - "dWYuVW5pbnRlcnByZXRlZE9wdGlvbiIvCgVDVHlwZRIKCgZTVFJJTkcQABII", - "CgRDT1JEEAESEAoMU1RSSU5HX1BJRUNFEAIiNQoGSlNUeXBlEg0KCUpTX05P", - "Uk1BTBAAEg0KCUpTX1NUUklORxABEg0KCUpTX05VTUJFUhACKgkI6AcQgICA", - "gAJKBAgEEAUiXgoMT25lb2ZPcHRpb25zEkMKFHVuaW50ZXJwcmV0ZWRfb3B0", - "aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0", - "aW9uKgkI6AcQgICAgAIikwEKC0VudW1PcHRpb25zEhMKC2FsbG93X2FsaWFz", - "GAIgASgIEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEkMKFHVuaW50ZXJw", - "cmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVy", - "cHJldGVkT3B0aW9uKgkI6AcQgICAgAJKBAgFEAYifQoQRW51bVZhbHVlT3B0", - "aW9ucxIZCgpkZXByZWNhdGVkGAEgASgIOgVmYWxzZRJDChR1bmludGVycHJl", - "dGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnBy", - "ZXRlZE9wdGlvbioJCOgHEICAgIACInsKDlNlcnZpY2VPcHRpb25zEhkKCmRl", - "cHJlY2F0ZWQYISABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9u", - "GOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9u", - "KgkI6AcQgICAgAIirQIKDU1ldGhvZE9wdGlvbnMSGQoKZGVwcmVjYXRlZBgh", - "IAEoCDoFZmFsc2USXwoRaWRlbXBvdGVuY3lfbGV2ZWwYIiABKA4yLy5nb29n", - "bGUucHJvdG9idWYuTWV0aG9kT3B0aW9ucy5JZGVtcG90ZW5jeUxldmVsOhNJ", - "REVNUE9URU5DWV9VTktOT1dOEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcH", - "IAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIlAK", - "EElkZW1wb3RlbmN5TGV2ZWwSFwoTSURFTVBPVEVOQ1lfVU5LTk9XThAAEhMK", - "D05PX1NJREVfRUZGRUNUUxABEg4KCklERU1QT1RFTlQQAioJCOgHEICAgIAC", - "Ip4CChNVbmludGVycHJldGVkT3B0aW9uEjsKBG5hbWUYAiADKAsyLS5nb29n", - "bGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbi5OYW1lUGFydBIYChBp", - "ZGVudGlmaWVyX3ZhbHVlGAMgASgJEhoKEnBvc2l0aXZlX2ludF92YWx1ZRgE", - "IAEoBBIaChJuZWdhdGl2ZV9pbnRfdmFsdWUYBSABKAMSFAoMZG91YmxlX3Zh", - "bHVlGAYgASgBEhQKDHN0cmluZ192YWx1ZRgHIAEoDBIXCg9hZ2dyZWdhdGVf", - "dmFsdWUYCCABKAkaMwoITmFtZVBhcnQSEQoJbmFtZV9wYXJ0GAEgAigJEhQK", - "DGlzX2V4dGVuc2lvbhgCIAIoCCLVAQoOU291cmNlQ29kZUluZm8SOgoIbG9j", - "YXRpb24YASADKAsyKC5nb29nbGUucHJvdG9idWYuU291cmNlQ29kZUluZm8u", - "TG9jYXRpb24ahgEKCExvY2F0aW9uEhAKBHBhdGgYASADKAVCAhABEhAKBHNw", - "YW4YAiADKAVCAhABEhgKEGxlYWRpbmdfY29tbWVudHMYAyABKAkSGQoRdHJh", - "aWxpbmdfY29tbWVudHMYBCABKAkSIQoZbGVhZGluZ19kZXRhY2hlZF9jb21t", - "ZW50cxgGIAMoCSKnAQoRR2VuZXJhdGVkQ29kZUluZm8SQQoKYW5ub3RhdGlv", - "bhgBIAMoCzItLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRDb2RlSW5mby5B", - "bm5vdGF0aW9uGk8KCkFubm90YXRpb24SEAoEcGF0aBgBIAMoBUICEAESEwoL", - "c291cmNlX2ZpbGUYAiABKAkSDQoFYmVnaW4YAyABKAUSCwoDZW5kGAQgASgF", - "QowBChNjb20uZ29vZ2xlLnByb3RvYnVmQhBEZXNjcmlwdG9yUHJvdG9zSAFa", - "PmdpdGh1Yi5jb20vZ29sYW5nL3Byb3RvYnVmL3Byb3RvYy1nZW4tZ28vZGVz", - "Y3JpcHRvcjtkZXNjcmlwdG9yogIDR1BCqgIaR29vZ2xlLlByb3RvYnVmLlJl", - "ZmxlY3Rpb24=")); + "bnMSFwoPcHJvdG8zX29wdGlvbmFsGBEgASgIIrYCCgRUeXBlEg8KC1RZUEVf", + "RE9VQkxFEAESDgoKVFlQRV9GTE9BVBACEg4KClRZUEVfSU5UNjQQAxIPCgtU", + "WVBFX1VJTlQ2NBAEEg4KClRZUEVfSU5UMzIQBRIQCgxUWVBFX0ZJWEVENjQQ", + "BhIQCgxUWVBFX0ZJWEVEMzIQBxINCglUWVBFX0JPT0wQCBIPCgtUWVBFX1NU", + "UklORxAJEg4KClRZUEVfR1JPVVAQChIQCgxUWVBFX01FU1NBR0UQCxIOCgpU", + "WVBFX0JZVEVTEAwSDwoLVFlQRV9VSU5UMzIQDRINCglUWVBFX0VOVU0QDhIR", + "Cg1UWVBFX1NGSVhFRDMyEA8SEQoNVFlQRV9TRklYRUQ2NBAQEg8KC1RZUEVf", + "U0lOVDMyEBESDwoLVFlQRV9TSU5UNjQQEiJDCgVMYWJlbBISCg5MQUJFTF9P", + "UFRJT05BTBABEhIKDkxBQkVMX1JFUVVJUkVEEAISEgoOTEFCRUxfUkVQRUFU", + "RUQQAyJUChRPbmVvZkRlc2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEi4K", + "B29wdGlvbnMYAiABKAsyHS5nb29nbGUucHJvdG9idWYuT25lb2ZPcHRpb25z", + "IqQCChNFbnVtRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSOAoFdmFs", + "dWUYAiADKAsyKS5nb29nbGUucHJvdG9idWYuRW51bVZhbHVlRGVzY3JpcHRv", + "clByb3RvEi0KB29wdGlvbnMYAyABKAsyHC5nb29nbGUucHJvdG9idWYuRW51", + "bU9wdGlvbnMSTgoOcmVzZXJ2ZWRfcmFuZ2UYBCADKAsyNi5nb29nbGUucHJv", + "dG9idWYuRW51bURlc2NyaXB0b3JQcm90by5FbnVtUmVzZXJ2ZWRSYW5nZRIV", + "Cg1yZXNlcnZlZF9uYW1lGAUgAygJGi8KEUVudW1SZXNlcnZlZFJhbmdlEg0K", + "BXN0YXJ0GAEgASgFEgsKA2VuZBgCIAEoBSJsChhFbnVtVmFsdWVEZXNjcmlw", + "dG9yUHJvdG8SDAoEbmFtZRgBIAEoCRIOCgZudW1iZXIYAiABKAUSMgoHb3B0", + "aW9ucxgDIAEoCzIhLmdvb2dsZS5wcm90b2J1Zi5FbnVtVmFsdWVPcHRpb25z", + "IpABChZTZXJ2aWNlRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSNgoG", + "bWV0aG9kGAIgAygLMiYuZ29vZ2xlLnByb3RvYnVmLk1ldGhvZERlc2NyaXB0", + "b3JQcm90bxIwCgdvcHRpb25zGAMgASgLMh8uZ29vZ2xlLnByb3RvYnVmLlNl", + "cnZpY2VPcHRpb25zIsEBChVNZXRob2REZXNjcmlwdG9yUHJvdG8SDAoEbmFt", + "ZRgBIAEoCRISCgppbnB1dF90eXBlGAIgASgJEhMKC291dHB1dF90eXBlGAMg", + "ASgJEi8KB29wdGlvbnMYBCABKAsyHi5nb29nbGUucHJvdG9idWYuTWV0aG9k", + "T3B0aW9ucxIfChBjbGllbnRfc3RyZWFtaW5nGAUgASgIOgVmYWxzZRIfChBz", + "ZXJ2ZXJfc3RyZWFtaW5nGAYgASgIOgVmYWxzZSKlBgoLRmlsZU9wdGlvbnMS", + "FAoMamF2YV9wYWNrYWdlGAEgASgJEhwKFGphdmFfb3V0ZXJfY2xhc3NuYW1l", + "GAggASgJEiIKE2phdmFfbXVsdGlwbGVfZmlsZXMYCiABKAg6BWZhbHNlEikK", + "HWphdmFfZ2VuZXJhdGVfZXF1YWxzX2FuZF9oYXNoGBQgASgIQgIYARIlChZq", + "YXZhX3N0cmluZ19jaGVja191dGY4GBsgASgIOgVmYWxzZRJGCgxvcHRpbWl6", + "ZV9mb3IYCSABKA4yKS5nb29nbGUucHJvdG9idWYuRmlsZU9wdGlvbnMuT3B0", + "aW1pemVNb2RlOgVTUEVFRBISCgpnb19wYWNrYWdlGAsgASgJEiIKE2NjX2dl", + "bmVyaWNfc2VydmljZXMYECABKAg6BWZhbHNlEiQKFWphdmFfZ2VuZXJpY19z", + "ZXJ2aWNlcxgRIAEoCDoFZmFsc2USIgoTcHlfZ2VuZXJpY19zZXJ2aWNlcxgS", + "IAEoCDoFZmFsc2USIwoUcGhwX2dlbmVyaWNfc2VydmljZXMYKiABKAg6BWZh", + "bHNlEhkKCmRlcHJlY2F0ZWQYFyABKAg6BWZhbHNlEh4KEGNjX2VuYWJsZV9h", + "cmVuYXMYHyABKAg6BHRydWUSGQoRb2JqY19jbGFzc19wcmVmaXgYJCABKAkS", + "GAoQY3NoYXJwX25hbWVzcGFjZRglIAEoCRIUCgxzd2lmdF9wcmVmaXgYJyAB", + "KAkSGAoQcGhwX2NsYXNzX3ByZWZpeBgoIAEoCRIVCg1waHBfbmFtZXNwYWNl", + "GCkgASgJEh4KFnBocF9tZXRhZGF0YV9uYW1lc3BhY2UYLCABKAkSFAoMcnVi", + "eV9wYWNrYWdlGC0gASgJEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMo", + "CzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIjoKDE9w", + "dGltaXplTW9kZRIJCgVTUEVFRBABEg0KCUNPREVfU0laRRACEhAKDExJVEVf", + "UlVOVElNRRADKgkI6AcQgICAgAJKBAgmECci8gEKDk1lc3NhZ2VPcHRpb25z", + "EiYKF21lc3NhZ2Vfc2V0X3dpcmVfZm9ybWF0GAEgASgIOgVmYWxzZRIuCh9u", + "b19zdGFuZGFyZF9kZXNjcmlwdG9yX2FjY2Vzc29yGAIgASgIOgVmYWxzZRIZ", + "CgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRIRCgltYXBfZW50cnkYByABKAgS", + "QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv", + "YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAgQCUoECAkQ", + "CiKeAwoMRmllbGRPcHRpb25zEjoKBWN0eXBlGAEgASgOMiMuZ29vZ2xlLnBy", + "b3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlwZToGU1RSSU5HEg4KBnBhY2tlZBgC", + "IAEoCBI/CgZqc3R5cGUYBiABKA4yJC5nb29nbGUucHJvdG9idWYuRmllbGRP", + "cHRpb25zLkpTVHlwZToJSlNfTk9STUFMEhMKBGxhenkYBSABKAg6BWZhbHNl", + "EhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEhMKBHdlYWsYCiABKAg6BWZh", + "bHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5w", + "cm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIi8KBUNUeXBlEgoKBlNUUklO", + "RxAAEggKBENPUkQQARIQCgxTVFJJTkdfUElFQ0UQAiI1CgZKU1R5cGUSDQoJ", + "SlNfTk9STUFMEAASDQoJSlNfU1RSSU5HEAESDQoJSlNfTlVNQkVSEAIqCQjo", + "BxCAgICAAkoECAQQBSJeCgxPbmVvZk9wdGlvbnMSQwoUdW5pbnRlcnByZXRl", + "ZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0", + "ZWRPcHRpb24qCQjoBxCAgICAAiKTAQoLRW51bU9wdGlvbnMSEwoLYWxsb3df", + "YWxpYXMYAiABKAgSGQoKZGVwcmVjYXRlZBgDIAEoCDoFZmFsc2USQwoUdW5p", + "bnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVu", + "aW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAUQBiJ9ChBFbnVtVmFs", + "dWVPcHRpb25zEhkKCmRlcHJlY2F0ZWQYASABKAg6BWZhbHNlEkMKFHVuaW50", + "ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5Vbmlu", + "dGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIiewoOU2VydmljZU9wdGlvbnMS", + "GQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9v", + "cHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRP", + "cHRpb24qCQjoBxCAgICAAiKtAgoNTWV0aG9kT3B0aW9ucxIZCgpkZXByZWNh", + "dGVkGCEgASgIOgVmYWxzZRJfChFpZGVtcG90ZW5jeV9sZXZlbBgiIAEoDjIv", + "Lmdvb2dsZS5wcm90b2J1Zi5NZXRob2RPcHRpb25zLklkZW1wb3RlbmN5TGV2", + "ZWw6E0lERU1QT1RFTkNZX1VOS05PV04SQwoUdW5pbnRlcnByZXRlZF9vcHRp", + "b24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRp", + "b24iUAoQSWRlbXBvdGVuY3lMZXZlbBIXChNJREVNUE9URU5DWV9VTktOT1dO", + "EAASEwoPTk9fU0lERV9FRkZFQ1RTEAESDgoKSURFTVBPVEVOVBACKgkI6AcQ", + "gICAgAIingIKE1VuaW50ZXJwcmV0ZWRPcHRpb24SOwoEbmFtZRgCIAMoCzIt", + "Lmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uLk5hbWVQYXJ0", + "EhgKEGlkZW50aWZpZXJfdmFsdWUYAyABKAkSGgoScG9zaXRpdmVfaW50X3Zh", + "bHVlGAQgASgEEhoKEm5lZ2F0aXZlX2ludF92YWx1ZRgFIAEoAxIUCgxkb3Vi", + "bGVfdmFsdWUYBiABKAESFAoMc3RyaW5nX3ZhbHVlGAcgASgMEhcKD2FnZ3Jl", + "Z2F0ZV92YWx1ZRgIIAEoCRozCghOYW1lUGFydBIRCgluYW1lX3BhcnQYASAC", + "KAkSFAoMaXNfZXh0ZW5zaW9uGAIgAigIItUBCg5Tb3VyY2VDb2RlSW5mbxI6", + "Cghsb2NhdGlvbhgBIAMoCzIoLmdvb2dsZS5wcm90b2J1Zi5Tb3VyY2VDb2Rl", + "SW5mby5Mb2NhdGlvbhqGAQoITG9jYXRpb24SEAoEcGF0aBgBIAMoBUICEAES", + "EAoEc3BhbhgCIAMoBUICEAESGAoQbGVhZGluZ19jb21tZW50cxgDIAEoCRIZ", + "ChF0cmFpbGluZ19jb21tZW50cxgEIAEoCRIhChlsZWFkaW5nX2RldGFjaGVk", + "X2NvbW1lbnRzGAYgAygJIqcBChFHZW5lcmF0ZWRDb2RlSW5mbxJBCgphbm5v", + "dGF0aW9uGAEgAygLMi0uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZENvZGVJ", + "bmZvLkFubm90YXRpb24aTwoKQW5ub3RhdGlvbhIQCgRwYXRoGAEgAygFQgIQ", + "ARITCgtzb3VyY2VfZmlsZRgCIAEoCRINCgViZWdpbhgDIAEoBRILCgNlbmQY", + "BCABKAVCfgoTY29tLmdvb2dsZS5wcm90b2J1ZkIQRGVzY3JpcHRvclByb3Rv", + "c0gBWi1nb29nbGUuZ29sYW5nLm9yZy9wcm90b2J1Zi90eXBlcy9kZXNjcmlw", + "dG9ycGL4AQGiAgNHUEKqAhpHb29nbGUuUHJvdG9idWYuUmVmbGVjdGlvbg==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorSet), global::Google.Protobuf.Reflection.FileDescriptorSet.Parser, new[]{ "File" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorProto), global::Google.Protobuf.Reflection.FileDescriptorProto.Parser, new[]{ "Name", "Package", "Dependency", "PublicDependency", "WeakDependency", "MessageType", "EnumType", "Service", "Extension", "Options", "SourceCodeInfo", "Syntax" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto), global::Google.Protobuf.Reflection.DescriptorProto.Parser, new[]{ "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange.Parser, new[]{ "Start", "End", "Options" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange.Parser, new[]{ "Start", "End" }, null, null, null)}), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ExtensionRangeOptions), global::Google.Protobuf.Reflection.ExtensionRangeOptions.Parser, new[]{ "UninterpretedOption" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto), global::Google.Protobuf.Reflection.FieldDescriptorProto.Parser, new[]{ "Name", "Number", "Label", "Type", "TypeName", "Extendee", "DefaultValue", "OneofIndex", "JsonName", "Options" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type), typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) }, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.OneofDescriptorProto), global::Google.Protobuf.Reflection.OneofDescriptorProto.Parser, new[]{ "Name", "Options" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumDescriptorProto), global::Google.Protobuf.Reflection.EnumDescriptorProto.Parser, new[]{ "Name", "Value", "Options" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueDescriptorProto), global::Google.Protobuf.Reflection.EnumValueDescriptorProto.Parser, new[]{ "Name", "Number", "Options" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ServiceDescriptorProto), global::Google.Protobuf.Reflection.ServiceDescriptorProto.Parser, new[]{ "Name", "Method", "Options" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MethodDescriptorProto), global::Google.Protobuf.Reflection.MethodDescriptorProto.Parser, new[]{ "Name", "InputType", "OutputType", "Options", "ClientStreaming", "ServerStreaming" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileOptions), global::Google.Protobuf.Reflection.FileOptions.Parser, new[]{ "JavaPackage", "JavaOuterClassname", "JavaMultipleFiles", "JavaGenerateEqualsAndHash", "JavaStringCheckUtf8", "OptimizeFor", "GoPackage", "CcGenericServices", "JavaGenericServices", "PyGenericServices", "PhpGenericServices", "Deprecated", "CcEnableArenas", "ObjcClassPrefix", "CsharpNamespace", "SwiftPrefix", "PhpClassPrefix", "PhpNamespace", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) }, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MessageOptions), global::Google.Protobuf.Reflection.MessageOptions.Parser, new[]{ "MessageSetWireFormat", "NoStandardDescriptorAccessor", "Deprecated", "MapEntry", "UninterpretedOption" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FieldOptions), global::Google.Protobuf.Reflection.FieldOptions.Parser, new[]{ "Ctype", "Packed", "Jstype", "Lazy", "Deprecated", "Weak", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.CType), typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.JSType) }, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.OneofOptions), global::Google.Protobuf.Reflection.OneofOptions.Parser, new[]{ "UninterpretedOption" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumOptions), global::Google.Protobuf.Reflection.EnumOptions.Parser, new[]{ "AllowAlias", "Deprecated", "UninterpretedOption" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueOptions), global::Google.Protobuf.Reflection.EnumValueOptions.Parser, new[]{ "Deprecated", "UninterpretedOption" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ServiceOptions), global::Google.Protobuf.Reflection.ServiceOptions.Parser, new[]{ "Deprecated", "UninterpretedOption" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MethodOptions), global::Google.Protobuf.Reflection.MethodOptions.Parser, new[]{ "Deprecated", "IdempotencyLevel", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel) }, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption), global::Google.Protobuf.Reflection.UninterpretedOption.Parser, new[]{ "Name", "IdentifierValue", "PositiveIntValue", "NegativeIntValue", "DoubleValue", "StringValue", "AggregateValue" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart), global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart.Parser, new[]{ "NamePart_", "IsExtension" }, null, null, null)}), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo), global::Google.Protobuf.Reflection.SourceCodeInfo.Parser, new[]{ "Location" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location), global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location.Parser, new[]{ "Path", "Span", "LeadingComments", "TrailingComments", "LeadingDetachedComments" }, null, null, null)}), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Parser, new[]{ "Annotation" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Parser, new[]{ "Path", "SourceFile", "Begin", "End" }, null, null, null)}) + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorSet), global::Google.Protobuf.Reflection.FileDescriptorSet.Parser, new[]{ "File" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorProto), global::Google.Protobuf.Reflection.FileDescriptorProto.Parser, new[]{ "Name", "Package", "Dependency", "PublicDependency", "WeakDependency", "MessageType", "EnumType", "Service", "Extension", "Options", "SourceCodeInfo", "Syntax" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto), global::Google.Protobuf.Reflection.DescriptorProto.Parser, new[]{ "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange.Parser, new[]{ "Start", "End", "Options" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange.Parser, new[]{ "Start", "End" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ExtensionRangeOptions), global::Google.Protobuf.Reflection.ExtensionRangeOptions.Parser, new[]{ "UninterpretedOption" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto), global::Google.Protobuf.Reflection.FieldDescriptorProto.Parser, new[]{ "Name", "Number", "Label", "Type", "TypeName", "Extendee", "DefaultValue", "OneofIndex", "JsonName", "Options", "Proto3Optional" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type), typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.OneofDescriptorProto), global::Google.Protobuf.Reflection.OneofDescriptorProto.Parser, new[]{ "Name", "Options" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumDescriptorProto), global::Google.Protobuf.Reflection.EnumDescriptorProto.Parser, new[]{ "Name", "Value", "Options", "ReservedRange", "ReservedName" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumDescriptorProto.Types.EnumReservedRange), global::Google.Protobuf.Reflection.EnumDescriptorProto.Types.EnumReservedRange.Parser, new[]{ "Start", "End" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueDescriptorProto), global::Google.Protobuf.Reflection.EnumValueDescriptorProto.Parser, new[]{ "Name", "Number", "Options" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ServiceDescriptorProto), global::Google.Protobuf.Reflection.ServiceDescriptorProto.Parser, new[]{ "Name", "Method", "Options" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MethodDescriptorProto), global::Google.Protobuf.Reflection.MethodDescriptorProto.Parser, new[]{ "Name", "InputType", "OutputType", "Options", "ClientStreaming", "ServerStreaming" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileOptions), global::Google.Protobuf.Reflection.FileOptions.Parser, new[]{ "JavaPackage", "JavaOuterClassname", "JavaMultipleFiles", "JavaGenerateEqualsAndHash", "JavaStringCheckUtf8", "OptimizeFor", "GoPackage", "CcGenericServices", "JavaGenericServices", "PyGenericServices", "PhpGenericServices", "Deprecated", "CcEnableArenas", "ObjcClassPrefix", "CsharpNamespace", "SwiftPrefix", "PhpClassPrefix", "PhpNamespace", "PhpMetadataNamespace", "RubyPackage", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MessageOptions), global::Google.Protobuf.Reflection.MessageOptions.Parser, new[]{ "MessageSetWireFormat", "NoStandardDescriptorAccessor", "Deprecated", "MapEntry", "UninterpretedOption" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FieldOptions), global::Google.Protobuf.Reflection.FieldOptions.Parser, new[]{ "Ctype", "Packed", "Jstype", "Lazy", "Deprecated", "Weak", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.CType), typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.JSType) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.OneofOptions), global::Google.Protobuf.Reflection.OneofOptions.Parser, new[]{ "UninterpretedOption" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumOptions), global::Google.Protobuf.Reflection.EnumOptions.Parser, new[]{ "AllowAlias", "Deprecated", "UninterpretedOption" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueOptions), global::Google.Protobuf.Reflection.EnumValueOptions.Parser, new[]{ "Deprecated", "UninterpretedOption" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ServiceOptions), global::Google.Protobuf.Reflection.ServiceOptions.Parser, new[]{ "Deprecated", "UninterpretedOption" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MethodOptions), global::Google.Protobuf.Reflection.MethodOptions.Parser, new[]{ "Deprecated", "IdempotencyLevel", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption), global::Google.Protobuf.Reflection.UninterpretedOption.Parser, new[]{ "Name", "IdentifierValue", "PositiveIntValue", "NegativeIntValue", "DoubleValue", "StringValue", "AggregateValue" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart), global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart.Parser, new[]{ "NamePart_", "IsExtension" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo), global::Google.Protobuf.Reflection.SourceCodeInfo.Parser, new[]{ "Location" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location), global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location.Parser, new[]{ "Path", "Span", "LeadingComments", "TrailingComments", "LeadingDetachedComments" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Parser, new[]{ "Annotation" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Parser, new[]{ "Path", "SourceFile", "Begin", "End" }, null, null, null, null)}) })); } #endregion @@ -187,8 +193,13 @@ static DescriptorReflection() { /// The protocol compiler can output a FileDescriptorSet containing the .proto /// files it parses. /// - internal sealed partial class FileDescriptorSet : pb::IMessage { + public sealed partial class FileDescriptorSet : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FileDescriptorSet()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -212,6 +223,7 @@ public FileDescriptorSet() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FileDescriptorSet(FileDescriptorSet other) : this() { file_ = other.file_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -243,13 +255,16 @@ public bool Equals(FileDescriptorSet other) { return true; } if(!file_.Equals(other.file_)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= file_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -260,13 +275,33 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else file_.WriteTo(output, _repeated_file_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + file_.WriteTo(ref output, _repeated_file_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += file_.CalculateSize(_repeated_file_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -276,15 +311,19 @@ public void MergeFrom(FileDescriptorSet other) { return; } file_.Add(other.file_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { file_.AddEntriesFrom(input, _repeated_file_codec); @@ -292,15 +331,39 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + file_.AddEntriesFrom(ref input, _repeated_file_codec); + break; + } + } + } } + #endif } /// /// Describes a complete .proto file. /// - internal sealed partial class FileDescriptorProto : pb::IMessage { + public sealed partial class FileDescriptorProto : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FileDescriptorProto()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -332,9 +395,10 @@ public FileDescriptorProto(FileDescriptorProto other) : this() { enumType_ = other.enumType_.Clone(); service_ = other.service_.Clone(); extension_ = other.extension_.Clone(); - Options = other.options_ != null ? other.Options.Clone() : null; - SourceCodeInfo = other.sourceCodeInfo_ != null ? other.SourceCodeInfo.Clone() : null; + options_ = other.options_ != null ? other.options_.Clone() : null; + sourceCodeInfo_ = other.sourceCodeInfo_ != null ? other.sourceCodeInfo_.Clone() : null; syntax_ = other.syntax_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -344,31 +408,55 @@ public FileDescriptorProto Clone() { /// Field number for the "name" field. public const int NameFieldNumber = 1; - private string name_ = ""; + private readonly static string NameDefaultValue = ""; + + private string name_; /// /// file name, relative to root of source tree /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name { - get { return name_; } + get { return name_ ?? NameDefaultValue; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "name" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasName { + get { return name_ != null; } + } + /// Clears the value of the "name" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearName() { + name_ = null; + } /// Field number for the "package" field. public const int PackageFieldNumber = 2; - private string package_ = ""; + private readonly static string PackageDefaultValue = ""; + + private string package_; /// /// e.g. "foo", "foo.bar", etc. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Package { - get { return package_; } + get { return package_ ?? PackageDefaultValue; } set { package_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "package" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPackage { + get { return package_ != null; } + } + /// Clears the value of the "package" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPackage() { + package_ = null; + } /// Field number for the "dependency" field. public const int DependencyFieldNumber = 3; @@ -483,18 +571,30 @@ public string Package { /// Field number for the "syntax" field. public const int SyntaxFieldNumber = 12; - private string syntax_ = ""; + private readonly static string SyntaxDefaultValue = ""; + + private string syntax_; /// /// The syntax of the proto file. /// The supported values are "proto2" and "proto3". /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Syntax { - get { return syntax_; } + get { return syntax_ ?? SyntaxDefaultValue; } set { syntax_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "syntax" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSyntax { + get { return syntax_ != null; } + } + /// Clears the value of the "syntax" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSyntax() { + syntax_ = null; + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { @@ -521,14 +621,14 @@ public bool Equals(FileDescriptorProto other) { if (!object.Equals(Options, other.Options)) return false; if (!object.Equals(SourceCodeInfo, other.SourceCodeInfo)) return false; if (Syntax != other.Syntax) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Name.Length != 0) hash ^= Name.GetHashCode(); - if (Package.Length != 0) hash ^= Package.GetHashCode(); + if (HasName) hash ^= Name.GetHashCode(); + if (HasPackage) hash ^= Package.GetHashCode(); hash ^= dependency_.GetHashCode(); hash ^= publicDependency_.GetHashCode(); hash ^= weakDependency_.GetHashCode(); @@ -538,7 +638,10 @@ public override int GetHashCode() { hash ^= extension_.GetHashCode(); if (options_ != null) hash ^= Options.GetHashCode(); if (sourceCodeInfo_ != null) hash ^= SourceCodeInfo.GetHashCode(); - if (Syntax.Length != 0) hash ^= Syntax.GetHashCode(); + if (HasSyntax) hash ^= Syntax.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -549,11 +652,14 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Name.Length != 0) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasName) { output.WriteRawTag(10); output.WriteString(Name); } - if (Package.Length != 0) { + if (HasPackage) { output.WriteRawTag(18); output.WriteString(Package); } @@ -572,19 +678,59 @@ public void WriteTo(pb::CodedOutputStream output) { } publicDependency_.WriteTo(output, _repeated_publicDependency_codec); weakDependency_.WriteTo(output, _repeated_weakDependency_codec); - if (Syntax.Length != 0) { + if (HasSyntax) { + output.WriteRawTag(98); + output.WriteString(Syntax); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (HasPackage) { + output.WriteRawTag(18); + output.WriteString(Package); + } + dependency_.WriteTo(ref output, _repeated_dependency_codec); + messageType_.WriteTo(ref output, _repeated_messageType_codec); + enumType_.WriteTo(ref output, _repeated_enumType_codec); + service_.WriteTo(ref output, _repeated_service_codec); + extension_.WriteTo(ref output, _repeated_extension_codec); + if (options_ != null) { + output.WriteRawTag(66); + output.WriteMessage(Options); + } + if (sourceCodeInfo_ != null) { + output.WriteRawTag(74); + output.WriteMessage(SourceCodeInfo); + } + publicDependency_.WriteTo(ref output, _repeated_publicDependency_codec); + weakDependency_.WriteTo(ref output, _repeated_weakDependency_codec); + if (HasSyntax) { output.WriteRawTag(98); output.WriteString(Syntax); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Name.Length != 0) { + if (HasName) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } - if (Package.Length != 0) { + if (HasPackage) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Package); } size += dependency_.CalculateSize(_repeated_dependency_codec); @@ -600,9 +746,12 @@ public int CalculateSize() { if (sourceCodeInfo_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceCodeInfo); } - if (Syntax.Length != 0) { + if (HasSyntax) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Syntax); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -611,10 +760,10 @@ public void MergeFrom(FileDescriptorProto other) { if (other == null) { return; } - if (other.Name.Length != 0) { + if (other.HasName) { Name = other.Name; } - if (other.Package.Length != 0) { + if (other.HasPackage) { Package = other.Package; } dependency_.Add(other.dependency_); @@ -626,28 +775,32 @@ public void MergeFrom(FileDescriptorProto other) { extension_.Add(other.extension_); if (other.options_ != null) { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.FileOptions(); + Options = new global::Google.Protobuf.Reflection.FileOptions(); } Options.MergeFrom(other.Options); } if (other.sourceCodeInfo_ != null) { if (sourceCodeInfo_ == null) { - sourceCodeInfo_ = new global::Google.Protobuf.Reflection.SourceCodeInfo(); + SourceCodeInfo = new global::Google.Protobuf.Reflection.SourceCodeInfo(); } SourceCodeInfo.MergeFrom(other.SourceCodeInfo); } - if (other.Syntax.Length != 0) { + if (other.HasSyntax) { Syntax = other.Syntax; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { Name = input.ReadString(); @@ -679,16 +832,16 @@ public void MergeFrom(pb::CodedInputStream input) { } case 66: { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.FileOptions(); + Options = new global::Google.Protobuf.Reflection.FileOptions(); } - input.ReadMessage(options_); + input.ReadMessage(Options); break; } case 74: { if (sourceCodeInfo_ == null) { - sourceCodeInfo_ = new global::Google.Protobuf.Reflection.SourceCodeInfo(); + SourceCodeInfo = new global::Google.Protobuf.Reflection.SourceCodeInfo(); } - input.ReadMessage(sourceCodeInfo_); + input.ReadMessage(SourceCodeInfo); break; } case 82: @@ -707,15 +860,91 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + Package = input.ReadString(); + break; + } + case 26: { + dependency_.AddEntriesFrom(ref input, _repeated_dependency_codec); + break; + } + case 34: { + messageType_.AddEntriesFrom(ref input, _repeated_messageType_codec); + break; + } + case 42: { + enumType_.AddEntriesFrom(ref input, _repeated_enumType_codec); + break; + } + case 50: { + service_.AddEntriesFrom(ref input, _repeated_service_codec); + break; + } + case 58: { + extension_.AddEntriesFrom(ref input, _repeated_extension_codec); + break; + } + case 66: { + if (options_ == null) { + Options = new global::Google.Protobuf.Reflection.FileOptions(); + } + input.ReadMessage(Options); + break; + } + case 74: { + if (sourceCodeInfo_ == null) { + SourceCodeInfo = new global::Google.Protobuf.Reflection.SourceCodeInfo(); + } + input.ReadMessage(SourceCodeInfo); + break; + } + case 82: + case 80: { + publicDependency_.AddEntriesFrom(ref input, _repeated_publicDependency_codec); + break; + } + case 90: + case 88: { + weakDependency_.AddEntriesFrom(ref input, _repeated_weakDependency_codec); + break; + } + case 98: { + Syntax = input.ReadString(); + break; + } + } + } } + #endif } /// /// Describes a message type. /// - internal sealed partial class DescriptorProto : pb::IMessage { + public sealed partial class DescriptorProto : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DescriptorProto()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -745,9 +974,10 @@ public DescriptorProto(DescriptorProto other) : this() { enumType_ = other.enumType_.Clone(); extensionRange_ = other.extensionRange_.Clone(); oneofDecl_ = other.oneofDecl_.Clone(); - Options = other.options_ != null ? other.Options.Clone() : null; + options_ = other.options_ != null ? other.options_.Clone() : null; reservedRange_ = other.reservedRange_.Clone(); reservedName_ = other.reservedName_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -757,14 +987,26 @@ public DescriptorProto Clone() { /// Field number for the "name" field. public const int NameFieldNumber = 1; - private string name_ = ""; + private readonly static string NameDefaultValue = ""; + + private string name_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name { - get { return name_; } + get { return name_ ?? NameDefaultValue; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "name" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasName { + get { return name_ != null; } + } + /// Clears the value of the "name" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearName() { + name_ = null; + } /// Field number for the "field" field. public const int FieldFieldNumber = 2; @@ -884,13 +1126,13 @@ public bool Equals(DescriptorProto other) { if (!object.Equals(Options, other.Options)) return false; if(!reservedRange_.Equals(other.reservedRange_)) return false; if(!reservedName_.Equals(other.reservedName_)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (HasName) hash ^= Name.GetHashCode(); hash ^= field_.GetHashCode(); hash ^= extension_.GetHashCode(); hash ^= nestedType_.GetHashCode(); @@ -900,6 +1142,9 @@ public override int GetHashCode() { if (options_ != null) hash ^= Options.GetHashCode(); hash ^= reservedRange_.GetHashCode(); hash ^= reservedName_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -910,7 +1155,10 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Name.Length != 0) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasName) { output.WriteRawTag(10); output.WriteString(Name); } @@ -926,12 +1174,41 @@ public void WriteTo(pb::CodedOutputStream output) { oneofDecl_.WriteTo(output, _repeated_oneofDecl_codec); reservedRange_.WriteTo(output, _repeated_reservedRange_codec); reservedName_.WriteTo(output, _repeated_reservedName_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + field_.WriteTo(ref output, _repeated_field_codec); + nestedType_.WriteTo(ref output, _repeated_nestedType_codec); + enumType_.WriteTo(ref output, _repeated_enumType_codec); + extensionRange_.WriteTo(ref output, _repeated_extensionRange_codec); + extension_.WriteTo(ref output, _repeated_extension_codec); + if (options_ != null) { + output.WriteRawTag(58); + output.WriteMessage(Options); + } + oneofDecl_.WriteTo(ref output, _repeated_oneofDecl_codec); + reservedRange_.WriteTo(ref output, _repeated_reservedRange_codec); + reservedName_.WriteTo(ref output, _repeated_reservedName_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Name.Length != 0) { + if (HasName) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } size += field_.CalculateSize(_repeated_field_codec); @@ -945,6 +1222,9 @@ public int CalculateSize() { } size += reservedRange_.CalculateSize(_repeated_reservedRange_codec); size += reservedName_.CalculateSize(_repeated_reservedName_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -953,7 +1233,7 @@ public void MergeFrom(DescriptorProto other) { if (other == null) { return; } - if (other.Name.Length != 0) { + if (other.HasName) { Name = other.Name; } field_.Add(other.field_); @@ -964,21 +1244,25 @@ public void MergeFrom(DescriptorProto other) { oneofDecl_.Add(other.oneofDecl_); if (other.options_ != null) { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.MessageOptions(); + Options = new global::Google.Protobuf.Reflection.MessageOptions(); } Options.MergeFrom(other.Options); } reservedRange_.Add(other.reservedRange_); reservedName_.Add(other.reservedName_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { Name = input.ReadString(); @@ -1006,9 +1290,9 @@ public void MergeFrom(pb::CodedInputStream input) { } case 58: { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.MessageOptions(); + Options = new global::Google.Protobuf.Reflection.MessageOptions(); } - input.ReadMessage(options_); + input.ReadMessage(Options); break; } case 66: { @@ -1025,14 +1309,78 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + field_.AddEntriesFrom(ref input, _repeated_field_codec); + break; + } + case 26: { + nestedType_.AddEntriesFrom(ref input, _repeated_nestedType_codec); + break; + } + case 34: { + enumType_.AddEntriesFrom(ref input, _repeated_enumType_codec); + break; + } + case 42: { + extensionRange_.AddEntriesFrom(ref input, _repeated_extensionRange_codec); + break; + } + case 50: { + extension_.AddEntriesFrom(ref input, _repeated_extension_codec); + break; + } + case 58: { + if (options_ == null) { + Options = new global::Google.Protobuf.Reflection.MessageOptions(); + } + input.ReadMessage(Options); + break; + } + case 66: { + oneofDecl_.AddEntriesFrom(ref input, _repeated_oneofDecl_codec); + break; + } + case 74: { + reservedRange_.AddEntriesFrom(ref input, _repeated_reservedRange_codec); + break; + } + case 82: { + reservedName_.AddEntriesFrom(ref input, _repeated_reservedName_codec); + break; + } + } + } } + #endif #region Nested types /// Container for nested types declared in the DescriptorProto message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - internal sealed partial class ExtensionRange : pb::IMessage { + public sealed partial class ExtensionRange : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ExtensionRange()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -1055,9 +1403,11 @@ public ExtensionRange() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ExtensionRange(ExtensionRange other) : this() { + _hasBits0 = other._hasBits0; start_ = other.start_; end_ = other.end_; - Options = other.options_ != null ? other.Options.Clone() : null; + options_ = other.options_ != null ? other.options_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1067,25 +1417,57 @@ public ExtensionRange Clone() { /// Field number for the "start" field. public const int StartFieldNumber = 1; + private readonly static int StartDefaultValue = 0; + private int start_; + /// + /// Inclusive. + /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Start { - get { return start_; } + get { if ((_hasBits0 & 1) != 0) { return start_; } else { return StartDefaultValue; } } set { + _hasBits0 |= 1; start_ = value; } } + /// Gets whether the "start" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStart { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "start" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStart() { + _hasBits0 &= ~1; + } /// Field number for the "end" field. public const int EndFieldNumber = 2; + private readonly static int EndDefaultValue = 0; + private int end_; + /// + /// Exclusive. + /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int End { - get { return end_; } + get { if ((_hasBits0 & 2) != 0) { return end_; } else { return EndDefaultValue; } } set { + _hasBits0 |= 2; end_ = value; } } + /// Gets whether the "end" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasEnd { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "end" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearEnd() { + _hasBits0 &= ~2; + } /// Field number for the "options" field. public const int OptionsFieldNumber = 3; @@ -1114,15 +1496,18 @@ public bool Equals(ExtensionRange other) { if (Start != other.Start) return false; if (End != other.End) return false; if (!object.Equals(Options, other.Options)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Start != 0) hash ^= Start.GetHashCode(); - if (End != 0) hash ^= End.GetHashCode(); + if (HasStart) hash ^= Start.GetHashCode(); + if (HasEnd) hash ^= End.GetHashCode(); if (options_ != null) hash ^= Options.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -1133,11 +1518,35 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Start != 0) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasStart) { + output.WriteRawTag(8); + output.WriteInt32(Start); + } + if (HasEnd) { + output.WriteRawTag(16); + output.WriteInt32(End); + } + if (options_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Options); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasStart) { output.WriteRawTag(8); output.WriteInt32(Start); } - if (End != 0) { + if (HasEnd) { output.WriteRawTag(16); output.WriteInt32(End); } @@ -1145,20 +1554,27 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(26); output.WriteMessage(Options); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Start != 0) { + if (HasStart) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Start); } - if (End != 0) { + if (HasEnd) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(End); } if (options_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -1167,27 +1583,60 @@ public void MergeFrom(ExtensionRange other) { if (other == null) { return; } - if (other.Start != 0) { + if (other.HasStart) { Start = other.Start; } - if (other.End != 0) { + if (other.HasEnd) { End = other.End; } if (other.options_ != null) { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.ExtensionRangeOptions(); + Options = new global::Google.Protobuf.Reflection.ExtensionRangeOptions(); } Options.MergeFrom(other.Options); } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: { + Start = input.ReadInt32(); + break; + } + case 16: { + End = input.ReadInt32(); + break; + } + case 26: { + if (options_ == null) { + Options = new global::Google.Protobuf.Reflection.ExtensionRangeOptions(); + } + input.ReadMessage(Options); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Start = input.ReadInt32(); @@ -1199,14 +1648,15 @@ public void MergeFrom(pb::CodedInputStream input) { } case 26: { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.ExtensionRangeOptions(); + Options = new global::Google.Protobuf.Reflection.ExtensionRangeOptions(); } - input.ReadMessage(options_); + input.ReadMessage(Options); break; } } } } + #endif } @@ -1215,8 +1665,14 @@ public void MergeFrom(pb::CodedInputStream input) { /// fields or extension ranges in the same message. Reserved ranges may /// not overlap. /// - internal sealed partial class ReservedRange : pb::IMessage { + public sealed partial class ReservedRange : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ReservedRange()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -1239,8 +1695,10 @@ public ReservedRange() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ReservedRange(ReservedRange other) : this() { + _hasBits0 = other._hasBits0; start_ = other.start_; end_ = other.end_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1250,31 +1708,57 @@ public ReservedRange Clone() { /// Field number for the "start" field. public const int StartFieldNumber = 1; + private readonly static int StartDefaultValue = 0; + private int start_; /// /// Inclusive. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Start { - get { return start_; } + get { if ((_hasBits0 & 1) != 0) { return start_; } else { return StartDefaultValue; } } set { + _hasBits0 |= 1; start_ = value; } } + /// Gets whether the "start" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStart { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "start" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStart() { + _hasBits0 &= ~1; + } /// Field number for the "end" field. public const int EndFieldNumber = 2; + private readonly static int EndDefaultValue = 0; + private int end_; /// /// Exclusive. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int End { - get { return end_; } + get { if ((_hasBits0 & 2) != 0) { return end_; } else { return EndDefaultValue; } } set { + _hasBits0 |= 2; end_ = value; } } + /// Gets whether the "end" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasEnd { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "end" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearEnd() { + _hasBits0 &= ~2; + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { @@ -1291,14 +1775,17 @@ public bool Equals(ReservedRange other) { } if (Start != other.Start) return false; if (End != other.End) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Start != 0) hash ^= Start.GetHashCode(); - if (End != 0) hash ^= End.GetHashCode(); + if (HasStart) hash ^= Start.GetHashCode(); + if (HasEnd) hash ^= End.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -1309,25 +1796,52 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Start != 0) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasStart) { + output.WriteRawTag(8); + output.WriteInt32(Start); + } + if (HasEnd) { + output.WriteRawTag(16); + output.WriteInt32(End); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasStart) { output.WriteRawTag(8); output.WriteInt32(Start); } - if (End != 0) { + if (HasEnd) { output.WriteRawTag(16); output.WriteInt32(End); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Start != 0) { + if (HasStart) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Start); } - if (End != 0) { + if (HasEnd) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(End); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -1336,21 +1850,47 @@ public void MergeFrom(ReservedRange other) { if (other == null) { return; } - if (other.Start != 0) { + if (other.HasStart) { Start = other.Start; } - if (other.End != 0) { + if (other.HasEnd) { End = other.End; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: { + Start = input.ReadInt32(); + break; + } + case 16: { + End = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Start = input.ReadInt32(); @@ -1363,6 +1903,7 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } @@ -1371,8 +1912,15 @@ public void MergeFrom(pb::CodedInputStream input) { } - internal sealed partial class ExtensionRangeOptions : pb::IMessage { + public sealed partial class ExtensionRangeOptions : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ExtensionRangeOptions()); + private pb::UnknownFieldSet _unknownFields; + internal pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -1396,6 +1944,8 @@ public ExtensionRangeOptions() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ExtensionRangeOptions(ExtensionRangeOptions other) : this() { uninterpretedOption_ = other.uninterpretedOption_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1430,13 +1980,22 @@ public bool Equals(ExtensionRangeOptions other) { return true; } if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false; - return true; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= uninterpretedOption_.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -1447,13 +2006,42 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec); + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -1463,15 +2051,22 @@ public void MergeFrom(ExtensionRangeOptions other) { return; } uninterpretedOption_.Add(other.uninterpretedOption_); + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } break; case 7994: { uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec); @@ -1479,6 +2074,49 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + case 7994: { + uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec); + break; + } + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); } } @@ -1486,8 +2124,14 @@ public void MergeFrom(pb::CodedInputStream input) { /// /// Describes a field within a message. /// - internal sealed partial class FieldDescriptorProto : pb::IMessage { + public sealed partial class FieldDescriptorProto : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FieldDescriptorProto()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -1510,6 +2154,7 @@ public FieldDescriptorProto() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FieldDescriptorProto(FieldDescriptorProto other) : this() { + _hasBits0 = other._hasBits0; name_ = other.name_; number_ = other.number_; label_ = other.label_; @@ -1519,7 +2164,9 @@ public FieldDescriptorProto(FieldDescriptorProto other) : this() { defaultValue_ = other.defaultValue_; oneofIndex_ = other.oneofIndex_; jsonName_ = other.jsonName_; - Options = other.options_ != null ? other.Options.Clone() : null; + options_ = other.options_ != null ? other.options_.Clone() : null; + proto3Optional_ = other.proto3Optional_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1529,55 +2176,108 @@ public FieldDescriptorProto Clone() { /// Field number for the "name" field. public const int NameFieldNumber = 1; - private string name_ = ""; + private readonly static string NameDefaultValue = ""; + + private string name_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name { - get { return name_; } + get { return name_ ?? NameDefaultValue; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "name" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasName { + get { return name_ != null; } + } + /// Clears the value of the "name" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearName() { + name_ = null; + } /// Field number for the "number" field. public const int NumberFieldNumber = 3; + private readonly static int NumberDefaultValue = 0; + private int number_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Number { - get { return number_; } + get { if ((_hasBits0 & 1) != 0) { return number_; } else { return NumberDefaultValue; } } set { + _hasBits0 |= 1; number_ = value; } } + /// Gets whether the "number" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNumber { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "number" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNumber() { + _hasBits0 &= ~1; + } /// Field number for the "label" field. public const int LabelFieldNumber = 4; - private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label label_ = 0; + private readonly static global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label LabelDefaultValue = global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label.Optional; + + private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label label_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label Label { - get { return label_; } + get { if ((_hasBits0 & 2) != 0) { return label_; } else { return LabelDefaultValue; } } set { + _hasBits0 |= 2; label_ = value; } } + /// Gets whether the "label" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLabel { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "label" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLabel() { + _hasBits0 &= ~2; + } /// Field number for the "type" field. public const int TypeFieldNumber = 5; - private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type type_ = 0; + private readonly static global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type TypeDefaultValue = global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type.Double; + + private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type type_; /// /// If type_name is set, this need not be set. If both this and type_name /// are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type Type { - get { return type_; } + get { if ((_hasBits0 & 4) != 0) { return type_; } else { return TypeDefaultValue; } } set { + _hasBits0 |= 4; type_ = value; } } + /// Gets whether the "type" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasType { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "type" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearType() { + _hasBits0 &= ~4; + } /// Field number for the "type_name" field. public const int TypeNameFieldNumber = 6; - private string typeName_ = ""; + private readonly static string TypeNameDefaultValue = ""; + + private string typeName_; /// /// For message and enum types, this is the name of the type. If the name /// starts with a '.', it is fully-qualified. Otherwise, C++-like scoping @@ -1587,30 +2287,54 @@ public int Number { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string TypeName { - get { return typeName_; } + get { return typeName_ ?? TypeNameDefaultValue; } set { typeName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "type_name" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTypeName { + get { return typeName_ != null; } + } + /// Clears the value of the "type_name" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTypeName() { + typeName_ = null; + } /// Field number for the "extendee" field. public const int ExtendeeFieldNumber = 2; - private string extendee_ = ""; + private readonly static string ExtendeeDefaultValue = ""; + + private string extendee_; /// /// For extensions, this is the name of the type being extended. It is /// resolved in the same manner as type_name. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Extendee { - get { return extendee_; } + get { return extendee_ ?? ExtendeeDefaultValue; } set { extendee_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "extendee" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasExtendee { + get { return extendee_ != null; } + } + /// Clears the value of the "extendee" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearExtendee() { + extendee_ = null; + } /// Field number for the "default_value" field. public const int DefaultValueFieldNumber = 7; - private string defaultValue_ = ""; + private readonly static string DefaultValueDefaultValue = ""; + + private string defaultValue_; /// /// For numeric types, contains the original text representation of the value. /// For booleans, "true" or "false". @@ -1620,14 +2344,26 @@ public string Extendee { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string DefaultValue { - get { return defaultValue_; } + get { return defaultValue_ ?? DefaultValueDefaultValue; } set { defaultValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "default_value" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDefaultValue { + get { return defaultValue_ != null; } + } + /// Clears the value of the "default_value" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDefaultValue() { + defaultValue_ = null; + } /// Field number for the "oneof_index" field. public const int OneofIndexFieldNumber = 9; + private readonly static int OneofIndexDefaultValue = 0; + private int oneofIndex_; /// /// If set, gives the index of a oneof in the containing type's oneof_decl @@ -1635,15 +2371,28 @@ public string DefaultValue { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int OneofIndex { - get { return oneofIndex_; } + get { if ((_hasBits0 & 8) != 0) { return oneofIndex_; } else { return OneofIndexDefaultValue; } } set { + _hasBits0 |= 8; oneofIndex_ = value; } } + /// Gets whether the "oneof_index" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOneofIndex { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "oneof_index" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOneofIndex() { + _hasBits0 &= ~8; + } /// Field number for the "json_name" field. public const int JsonNameFieldNumber = 10; - private string jsonName_ = ""; + private readonly static string JsonNameDefaultValue = ""; + + private string jsonName_; /// /// JSON name of this field. The value is set by protocol compiler. If the /// user has set a "json_name" option on this field, that option's value @@ -1652,11 +2401,21 @@ public int OneofIndex { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string JsonName { - get { return jsonName_; } + get { return jsonName_ ?? JsonNameDefaultValue; } set { jsonName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "json_name" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasJsonName { + get { return jsonName_ != null; } + } + /// Clears the value of the "json_name" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearJsonName() { + jsonName_ = null; + } /// Field number for the "options" field. public const int OptionsFieldNumber = 8; @@ -1669,6 +2428,53 @@ public string JsonName { } } + /// Field number for the "proto3_optional" field. + public const int Proto3OptionalFieldNumber = 17; + private readonly static bool Proto3OptionalDefaultValue = false; + + private bool proto3Optional_; + /// + /// If true, this is a proto3 "optional". When a proto3 field is optional, it + /// tracks presence regardless of field type. + /// + /// When proto3_optional is true, this field must be belong to a oneof to + /// signal to old proto3 clients that presence is tracked for this field. This + /// oneof is known as a "synthetic" oneof, and this field must be its sole + /// member (each proto3 optional field gets its own synthetic oneof). Synthetic + /// oneofs exist in the descriptor only, and do not generate any API. Synthetic + /// oneofs must be ordered after all "real" oneofs. + /// + /// For message fields, proto3_optional doesn't create any semantic change, + /// since non-repeated message fields always track presence. However it still + /// indicates the semantic detail of whether the user wrote "optional" or not. + /// This can be useful for round-tripping the .proto file. For consistency we + /// give message fields a synthetic oneof also, even though it is not required + /// to track presence. This is especially important because the parser can't + /// tell if a field is a message or an enum, so it must always create a + /// synthetic oneof. + /// + /// Proto2 optional fields do not set this flag, because they already indicate + /// optional with `LABEL_OPTIONAL`. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Proto3Optional { + get { if ((_hasBits0 & 16) != 0) { return proto3Optional_; } else { return Proto3OptionalDefaultValue; } } + set { + _hasBits0 |= 16; + proto3Optional_ = value; + } + } + /// Gets whether the "proto3_optional" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasProto3Optional { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "proto3_optional" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearProto3Optional() { + _hasBits0 &= ~16; + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as FieldDescriptorProto); @@ -1692,22 +2498,27 @@ public bool Equals(FieldDescriptorProto other) { if (OneofIndex != other.OneofIndex) return false; if (JsonName != other.JsonName) return false; if (!object.Equals(Options, other.Options)) return false; - return true; + if (Proto3Optional != other.Proto3Optional) return false; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Name.Length != 0) hash ^= Name.GetHashCode(); - if (Number != 0) hash ^= Number.GetHashCode(); - if (Label != 0) hash ^= Label.GetHashCode(); - if (Type != 0) hash ^= Type.GetHashCode(); - if (TypeName.Length != 0) hash ^= TypeName.GetHashCode(); - if (Extendee.Length != 0) hash ^= Extendee.GetHashCode(); - if (DefaultValue.Length != 0) hash ^= DefaultValue.GetHashCode(); - if (OneofIndex != 0) hash ^= OneofIndex.GetHashCode(); - if (JsonName.Length != 0) hash ^= JsonName.GetHashCode(); + if (HasName) hash ^= Name.GetHashCode(); + if (HasNumber) hash ^= Number.GetHashCode(); + if (HasLabel) hash ^= Label.GetHashCode(); + if (HasType) hash ^= Type.GetHashCode(); + if (HasTypeName) hash ^= TypeName.GetHashCode(); + if (HasExtendee) hash ^= Extendee.GetHashCode(); + if (HasDefaultValue) hash ^= DefaultValue.GetHashCode(); + if (HasOneofIndex) hash ^= OneofIndex.GetHashCode(); + if (HasJsonName) hash ^= JsonName.GetHashCode(); if (options_ != null) hash ^= Options.GetHashCode(); + if (HasProto3Optional) hash ^= Proto3Optional.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -1718,31 +2529,87 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Name.Length != 0) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (HasExtendee) { + output.WriteRawTag(18); + output.WriteString(Extendee); + } + if (HasNumber) { + output.WriteRawTag(24); + output.WriteInt32(Number); + } + if (HasLabel) { + output.WriteRawTag(32); + output.WriteEnum((int) Label); + } + if (HasType) { + output.WriteRawTag(40); + output.WriteEnum((int) Type); + } + if (HasTypeName) { + output.WriteRawTag(50); + output.WriteString(TypeName); + } + if (HasDefaultValue) { + output.WriteRawTag(58); + output.WriteString(DefaultValue); + } + if (options_ != null) { + output.WriteRawTag(66); + output.WriteMessage(Options); + } + if (HasOneofIndex) { + output.WriteRawTag(72); + output.WriteInt32(OneofIndex); + } + if (HasJsonName) { + output.WriteRawTag(82); + output.WriteString(JsonName); + } + if (HasProto3Optional) { + output.WriteRawTag(136, 1); + output.WriteBool(Proto3Optional); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { output.WriteRawTag(10); output.WriteString(Name); } - if (Extendee.Length != 0) { + if (HasExtendee) { output.WriteRawTag(18); output.WriteString(Extendee); } - if (Number != 0) { + if (HasNumber) { output.WriteRawTag(24); output.WriteInt32(Number); } - if (Label != 0) { + if (HasLabel) { output.WriteRawTag(32); output.WriteEnum((int) Label); } - if (Type != 0) { + if (HasType) { output.WriteRawTag(40); output.WriteEnum((int) Type); } - if (TypeName.Length != 0) { + if (HasTypeName) { output.WriteRawTag(50); output.WriteString(TypeName); } - if (DefaultValue.Length != 0) { + if (HasDefaultValue) { output.WriteRawTag(58); output.WriteString(DefaultValue); } @@ -1750,49 +2617,63 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(66); output.WriteMessage(Options); } - if (OneofIndex != 0) { + if (HasOneofIndex) { output.WriteRawTag(72); output.WriteInt32(OneofIndex); } - if (JsonName.Length != 0) { + if (HasJsonName) { output.WriteRawTag(82); output.WriteString(JsonName); } + if (HasProto3Optional) { + output.WriteRawTag(136, 1); + output.WriteBool(Proto3Optional); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Name.Length != 0) { + if (HasName) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } - if (Number != 0) { + if (HasNumber) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number); } - if (Label != 0) { + if (HasLabel) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Label); } - if (Type != 0) { + if (HasType) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); } - if (TypeName.Length != 0) { + if (HasTypeName) { size += 1 + pb::CodedOutputStream.ComputeStringSize(TypeName); } - if (Extendee.Length != 0) { + if (HasExtendee) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Extendee); } - if (DefaultValue.Length != 0) { + if (HasDefaultValue) { size += 1 + pb::CodedOutputStream.ComputeStringSize(DefaultValue); } - if (OneofIndex != 0) { + if (HasOneofIndex) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(OneofIndex); } - if (JsonName.Length != 0) { + if (HasJsonName) { size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonName); } if (options_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options); } + if (HasProto3Optional) { + size += 2 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -1801,48 +2682,116 @@ public void MergeFrom(FieldDescriptorProto other) { if (other == null) { return; } - if (other.Name.Length != 0) { + if (other.HasName) { Name = other.Name; } - if (other.Number != 0) { + if (other.HasNumber) { Number = other.Number; } - if (other.Label != 0) { + if (other.HasLabel) { Label = other.Label; } - if (other.Type != 0) { + if (other.HasType) { Type = other.Type; } - if (other.TypeName.Length != 0) { + if (other.HasTypeName) { TypeName = other.TypeName; } - if (other.Extendee.Length != 0) { + if (other.HasExtendee) { Extendee = other.Extendee; } - if (other.DefaultValue.Length != 0) { + if (other.HasDefaultValue) { DefaultValue = other.DefaultValue; } - if (other.OneofIndex != 0) { + if (other.HasOneofIndex) { OneofIndex = other.OneofIndex; } - if (other.JsonName.Length != 0) { + if (other.HasJsonName) { JsonName = other.JsonName; } if (other.options_ != null) { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.FieldOptions(); + Options = new global::Google.Protobuf.Reflection.FieldOptions(); } Options.MergeFrom(other.Options); } + if (other.HasProto3Optional) { + Proto3Optional = other.Proto3Optional; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + Extendee = input.ReadString(); + break; + } + case 24: { + Number = input.ReadInt32(); + break; + } + case 32: { + Label = (global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) input.ReadEnum(); + break; + } + case 40: { + Type = (global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type) input.ReadEnum(); + break; + } + case 50: { + TypeName = input.ReadString(); + break; + } + case 58: { + DefaultValue = input.ReadString(); + break; + } + case 66: { + if (options_ == null) { + Options = new global::Google.Protobuf.Reflection.FieldOptions(); + } + input.ReadMessage(Options); + break; + } + case 72: { + OneofIndex = input.ReadInt32(); + break; + } + case 82: { + JsonName = input.ReadString(); + break; + } + case 136: { + Proto3Optional = input.ReadBool(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Name = input.ReadString(); @@ -1857,11 +2806,11 @@ public void MergeFrom(pb::CodedInputStream input) { break; } case 32: { - label_ = (global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) input.ReadEnum(); + Label = (global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) input.ReadEnum(); break; } case 40: { - type_ = (global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type) input.ReadEnum(); + Type = (global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type) input.ReadEnum(); break; } case 50: { @@ -1874,9 +2823,9 @@ public void MergeFrom(pb::CodedInputStream input) { } case 66: { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.FieldOptions(); + Options = new global::Google.Protobuf.Reflection.FieldOptions(); } - input.ReadMessage(options_); + input.ReadMessage(Options); break; } case 72: { @@ -1887,15 +2836,20 @@ public void MergeFrom(pb::CodedInputStream input) { JsonName = input.ReadString(); break; } + case 136: { + Proto3Optional = input.ReadBool(); + break; + } } } } + #endif #region Nested types /// Container for nested types declared in the FieldDescriptorProto message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - internal enum Type { + public enum Type { /// /// 0 is reserved for errors. /// Order is weird for historical reasons. @@ -1946,7 +2900,7 @@ internal enum Type { [pbr::OriginalName("TYPE_SINT64")] Sint64 = 18, } - internal enum Label { + public enum Label { /// /// 0 is reserved for errors /// @@ -1963,8 +2917,13 @@ internal enum Label { /// /// Describes a oneof. /// - internal sealed partial class OneofDescriptorProto : pb::IMessage { + public sealed partial class OneofDescriptorProto : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneofDescriptorProto()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -1988,7 +2947,8 @@ public OneofDescriptorProto() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public OneofDescriptorProto(OneofDescriptorProto other) : this() { name_ = other.name_; - Options = other.options_ != null ? other.Options.Clone() : null; + options_ = other.options_ != null ? other.options_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1998,14 +2958,26 @@ public OneofDescriptorProto Clone() { /// Field number for the "name" field. public const int NameFieldNumber = 1; - private string name_ = ""; + private readonly static string NameDefaultValue = ""; + + private string name_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name { - get { return name_; } + get { return name_ ?? NameDefaultValue; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "name" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasName { + get { return name_ != null; } + } + /// Clears the value of the "name" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearName() { + name_ = null; + } /// Field number for the "options" field. public const int OptionsFieldNumber = 2; @@ -2033,14 +3005,17 @@ public bool Equals(OneofDescriptorProto other) { } if (Name != other.Name) return false; if (!object.Equals(Options, other.Options)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (HasName) hash ^= Name.GetHashCode(); if (options_ != null) hash ^= Options.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -2051,7 +3026,27 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Name.Length != 0) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (options_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Options); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { output.WriteRawTag(10); output.WriteString(Name); } @@ -2059,17 +3054,24 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(18); output.WriteMessage(Options); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Name.Length != 0) { + if (HasName) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } if (options_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -2078,24 +3080,53 @@ public void MergeFrom(OneofDescriptorProto other) { if (other == null) { return; } - if (other.Name.Length != 0) { + if (other.HasName) { Name = other.Name; } if (other.options_ != null) { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.OneofOptions(); + Options = new global::Google.Protobuf.Reflection.OneofOptions(); } Options.MergeFrom(other.Options); } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + if (options_ == null) { + Options = new global::Google.Protobuf.Reflection.OneofOptions(); + } + input.ReadMessage(Options); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Name = input.ReadString(); @@ -2103,22 +3134,28 @@ public void MergeFrom(pb::CodedInputStream input) { } case 18: { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.OneofOptions(); + Options = new global::Google.Protobuf.Reflection.OneofOptions(); } - input.ReadMessage(options_); + input.ReadMessage(Options); break; } } } } + #endif } /// /// Describes an enum type. /// - internal sealed partial class EnumDescriptorProto : pb::IMessage { + public sealed partial class EnumDescriptorProto : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EnumDescriptorProto()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -2143,8 +3180,11 @@ public EnumDescriptorProto() { public EnumDescriptorProto(EnumDescriptorProto other) : this() { name_ = other.name_; value_ = other.value_.Clone(); - Options = other.options_ != null ? other.Options.Clone() : null; - } + options_ = other.options_ != null ? other.options_.Clone() : null; + reservedRange_ = other.reservedRange_.Clone(); + reservedName_ = other.reservedName_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public EnumDescriptorProto Clone() { @@ -2153,14 +3193,26 @@ public EnumDescriptorProto Clone() { /// Field number for the "name" field. public const int NameFieldNumber = 1; - private string name_ = ""; + private readonly static string NameDefaultValue = ""; + + private string name_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name { - get { return name_; } + get { return name_ ?? NameDefaultValue; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "name" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasName { + get { return name_ != null; } + } + /// Clears the value of the "name" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearName() { + name_ = null; + } /// Field number for the "value" field. public const int ValueFieldNumber = 2; @@ -2183,6 +3235,35 @@ public string Name { } } + /// Field number for the "reserved_range" field. + public const int ReservedRangeFieldNumber = 4; + private static readonly pb::FieldCodec _repeated_reservedRange_codec + = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.Reflection.EnumDescriptorProto.Types.EnumReservedRange.Parser); + private readonly pbc::RepeatedField reservedRange_ = new pbc::RepeatedField(); + /// + /// Range of reserved numeric values. Reserved numeric values may not be used + /// by enum values in the same enum declaration. Reserved ranges may not + /// overlap. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField ReservedRange { + get { return reservedRange_; } + } + + /// Field number for the "reserved_name" field. + public const int ReservedNameFieldNumber = 5; + private static readonly pb::FieldCodec _repeated_reservedName_codec + = pb::FieldCodec.ForString(42); + private readonly pbc::RepeatedField reservedName_ = new pbc::RepeatedField(); + /// + /// Reserved enum value names, which may not be reused. A given name may only + /// be reserved once. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField ReservedName { + get { return reservedName_; } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as EnumDescriptorProto); @@ -2199,15 +3280,22 @@ public bool Equals(EnumDescriptorProto other) { if (Name != other.Name) return false; if(!value_.Equals(other.value_)) return false; if (!object.Equals(Options, other.Options)) return false; - return true; + if(!reservedRange_.Equals(other.reservedRange_)) return false; + if(!reservedName_.Equals(other.reservedName_)) return false; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (HasName) hash ^= Name.GetHashCode(); hash ^= value_.GetHashCode(); if (options_ != null) hash ^= Options.GetHashCode(); + hash ^= reservedRange_.GetHashCode(); + hash ^= reservedName_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -2218,7 +3306,10 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Name.Length != 0) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasName) { output.WriteRawTag(10); output.WriteString(Name); } @@ -2227,18 +3318,49 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(26); output.WriteMessage(Options); } + reservedRange_.WriteTo(output, _repeated_reservedRange_codec); + reservedName_.WriteTo(output, _repeated_reservedName_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + value_.WriteTo(ref output, _repeated_value_codec); + if (options_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Options); + } + reservedRange_.WriteTo(ref output, _repeated_reservedRange_codec); + reservedName_.WriteTo(ref output, _repeated_reservedName_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Name.Length != 0) { + if (HasName) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } size += value_.CalculateSize(_repeated_value_codec); if (options_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options); } + size += reservedRange_.CalculateSize(_repeated_reservedRange_codec); + size += reservedName_.CalculateSize(_repeated_reservedName_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -2247,25 +3369,31 @@ public void MergeFrom(EnumDescriptorProto other) { if (other == null) { return; } - if (other.Name.Length != 0) { + if (other.HasName) { Name = other.Name; } value_.Add(other.value_); if (other.options_ != null) { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.EnumOptions(); + Options = new global::Google.Protobuf.Reflection.EnumOptions(); } Options.MergeFrom(other.Options); } + reservedRange_.Add(other.reservedRange_); + reservedName_.Add(other.reservedName_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { Name = input.ReadString(); @@ -2277,22 +3405,331 @@ public void MergeFrom(pb::CodedInputStream input) { } case 26: { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.EnumOptions(); + Options = new global::Google.Protobuf.Reflection.EnumOptions(); } - input.ReadMessage(options_); + input.ReadMessage(Options); + break; + } + case 34: { + reservedRange_.AddEntriesFrom(input, _repeated_reservedRange_codec); + break; + } + case 42: { + reservedName_.AddEntriesFrom(input, _repeated_reservedName_codec); break; } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + value_.AddEntriesFrom(ref input, _repeated_value_codec); + break; + } + case 26: { + if (options_ == null) { + Options = new global::Google.Protobuf.Reflection.EnumOptions(); + } + input.ReadMessage(Options); + break; + } + case 34: { + reservedRange_.AddEntriesFrom(ref input, _repeated_reservedRange_codec); + break; + } + case 42: { + reservedName_.AddEntriesFrom(ref input, _repeated_reservedName_codec); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the EnumDescriptorProto message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + /// + /// Range of reserved numeric values. Reserved values may not be used by + /// entries in the same enum. Reserved ranges may not overlap. + /// + /// Note that this is distinct from DescriptorProto.ReservedRange in that it + /// is inclusive such that it can appropriately represent the entire int32 + /// domain. + /// + public sealed partial class EnumReservedRange : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EnumReservedRange()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.Reflection.EnumDescriptorProto.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public EnumReservedRange() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public EnumReservedRange(EnumReservedRange other) : this() { + _hasBits0 = other._hasBits0; + start_ = other.start_; + end_ = other.end_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public EnumReservedRange Clone() { + return new EnumReservedRange(this); + } + + /// Field number for the "start" field. + public const int StartFieldNumber = 1; + private readonly static int StartDefaultValue = 0; + + private int start_; + /// + /// Inclusive. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Start { + get { if ((_hasBits0 & 1) != 0) { return start_; } else { return StartDefaultValue; } } + set { + _hasBits0 |= 1; + start_ = value; + } + } + /// Gets whether the "start" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStart { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "start" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStart() { + _hasBits0 &= ~1; + } + + /// Field number for the "end" field. + public const int EndFieldNumber = 2; + private readonly static int EndDefaultValue = 0; + + private int end_; + /// + /// Inclusive. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int End { + get { if ((_hasBits0 & 2) != 0) { return end_; } else { return EndDefaultValue; } } + set { + _hasBits0 |= 2; + end_ = value; + } + } + /// Gets whether the "end" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasEnd { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "end" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearEnd() { + _hasBits0 &= ~2; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as EnumReservedRange); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(EnumReservedRange other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Start != other.Start) return false; + if (End != other.End) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasStart) hash ^= Start.GetHashCode(); + if (HasEnd) hash ^= End.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasStart) { + output.WriteRawTag(8); + output.WriteInt32(Start); + } + if (HasEnd) { + output.WriteRawTag(16); + output.WriteInt32(End); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasStart) { + output.WriteRawTag(8); + output.WriteInt32(Start); + } + if (HasEnd) { + output.WriteRawTag(16); + output.WriteInt32(End); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasStart) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Start); + } + if (HasEnd) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(End); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(EnumReservedRange other) { + if (other == null) { + return; + } + if (other.HasStart) { + Start = other.Start; + } + if (other.HasEnd) { + End = other.End; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Start = input.ReadInt32(); + break; + } + case 16: { + End = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Start = input.ReadInt32(); + break; + } + case 16: { + End = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + } + #endregion } /// /// Describes a value within an enum. /// - internal sealed partial class EnumValueDescriptorProto : pb::IMessage { + public sealed partial class EnumValueDescriptorProto : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EnumValueDescriptorProto()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -2315,9 +3752,11 @@ public EnumValueDescriptorProto() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public EnumValueDescriptorProto(EnumValueDescriptorProto other) : this() { + _hasBits0 = other._hasBits0; name_ = other.name_; number_ = other.number_; - Options = other.options_ != null ? other.Options.Clone() : null; + options_ = other.options_ != null ? other.options_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2327,25 +3766,50 @@ public EnumValueDescriptorProto Clone() { /// Field number for the "name" field. public const int NameFieldNumber = 1; - private string name_ = ""; + private readonly static string NameDefaultValue = ""; + + private string name_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name { - get { return name_; } + get { return name_ ?? NameDefaultValue; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "name" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasName { + get { return name_ != null; } + } + /// Clears the value of the "name" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearName() { + name_ = null; + } /// Field number for the "number" field. public const int NumberFieldNumber = 2; + private readonly static int NumberDefaultValue = 0; + private int number_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Number { - get { return number_; } + get { if ((_hasBits0 & 1) != 0) { return number_; } else { return NumberDefaultValue; } } set { + _hasBits0 |= 1; number_ = value; } } + /// Gets whether the "number" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNumber { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "number" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNumber() { + _hasBits0 &= ~1; + } /// Field number for the "options" field. public const int OptionsFieldNumber = 3; @@ -2374,15 +3838,18 @@ public bool Equals(EnumValueDescriptorProto other) { if (Name != other.Name) return false; if (Number != other.Number) return false; if (!object.Equals(Options, other.Options)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Name.Length != 0) hash ^= Name.GetHashCode(); - if (Number != 0) hash ^= Number.GetHashCode(); + if (HasName) hash ^= Name.GetHashCode(); + if (HasNumber) hash ^= Number.GetHashCode(); if (options_ != null) hash ^= Options.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -2393,11 +3860,14 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Name.Length != 0) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasName) { output.WriteRawTag(10); output.WriteString(Name); } - if (Number != 0) { + if (HasNumber) { output.WriteRawTag(16); output.WriteInt32(Number); } @@ -2405,20 +3875,48 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(26); output.WriteMessage(Options); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (HasNumber) { + output.WriteRawTag(16); + output.WriteInt32(Number); + } + if (options_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Options); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Name.Length != 0) { + if (HasName) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } - if (Number != 0) { + if (HasNumber) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number); } if (options_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -2427,27 +3925,31 @@ public void MergeFrom(EnumValueDescriptorProto other) { if (other == null) { return; } - if (other.Name.Length != 0) { + if (other.HasName) { Name = other.Name; } - if (other.Number != 0) { + if (other.HasNumber) { Number = other.Number; } if (other.options_ != null) { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.EnumValueOptions(); + Options = new global::Google.Protobuf.Reflection.EnumValueOptions(); } Options.MergeFrom(other.Options); } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { Name = input.ReadString(); @@ -2459,22 +3961,57 @@ public void MergeFrom(pb::CodedInputStream input) { } case 26: { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.EnumValueOptions(); + Options = new global::Google.Protobuf.Reflection.EnumValueOptions(); } - input.ReadMessage(options_); + input.ReadMessage(Options); break; } } } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 16: { + Number = input.ReadInt32(); + break; + } + case 26: { + if (options_ == null) { + Options = new global::Google.Protobuf.Reflection.EnumValueOptions(); + } + input.ReadMessage(Options); + break; + } + } + } + } + #endif + } /// /// Describes a service. /// - internal sealed partial class ServiceDescriptorProto : pb::IMessage { + public sealed partial class ServiceDescriptorProto : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServiceDescriptorProto()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -2499,7 +4036,8 @@ public ServiceDescriptorProto() { public ServiceDescriptorProto(ServiceDescriptorProto other) : this() { name_ = other.name_; method_ = other.method_.Clone(); - Options = other.options_ != null ? other.Options.Clone() : null; + options_ = other.options_ != null ? other.options_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2509,14 +4047,26 @@ public ServiceDescriptorProto Clone() { /// Field number for the "name" field. public const int NameFieldNumber = 1; - private string name_ = ""; + private readonly static string NameDefaultValue = ""; + + private string name_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name { - get { return name_; } + get { return name_ ?? NameDefaultValue; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "name" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasName { + get { return name_ != null; } + } + /// Clears the value of the "name" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearName() { + name_ = null; + } /// Field number for the "method" field. public const int MethodFieldNumber = 2; @@ -2555,15 +4105,18 @@ public bool Equals(ServiceDescriptorProto other) { if (Name != other.Name) return false; if(!method_.Equals(other.method_)) return false; if (!object.Equals(Options, other.Options)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (HasName) hash ^= Name.GetHashCode(); hash ^= method_.GetHashCode(); if (options_ != null) hash ^= Options.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -2574,7 +4127,10 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Name.Length != 0) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasName) { output.WriteRawTag(10); output.WriteString(Name); } @@ -2583,18 +4139,43 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(26); output.WriteMessage(Options); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + method_.WriteTo(ref output, _repeated_method_codec); + if (options_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Options); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Name.Length != 0) { + if (HasName) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } size += method_.CalculateSize(_repeated_method_codec); if (options_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -2603,25 +4184,29 @@ public void MergeFrom(ServiceDescriptorProto other) { if (other == null) { return; } - if (other.Name.Length != 0) { + if (other.HasName) { Name = other.Name; } method_.Add(other.method_); if (other.options_ != null) { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.ServiceOptions(); + Options = new global::Google.Protobuf.Reflection.ServiceOptions(); } Options.MergeFrom(other.Options); } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { Name = input.ReadString(); @@ -2633,22 +4218,58 @@ public void MergeFrom(pb::CodedInputStream input) { } case 26: { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.ServiceOptions(); + Options = new global::Google.Protobuf.Reflection.ServiceOptions(); + } + input.ReadMessage(Options); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + method_.AddEntriesFrom(ref input, _repeated_method_codec); + break; + } + case 26: { + if (options_ == null) { + Options = new global::Google.Protobuf.Reflection.ServiceOptions(); } - input.ReadMessage(options_); + input.ReadMessage(Options); break; } } } } + #endif } /// /// Describes a method of a service. /// - internal sealed partial class MethodDescriptorProto : pb::IMessage { + public sealed partial class MethodDescriptorProto : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MethodDescriptorProto()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -2671,12 +4292,14 @@ public MethodDescriptorProto() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public MethodDescriptorProto(MethodDescriptorProto other) : this() { + _hasBits0 = other._hasBits0; name_ = other.name_; inputType_ = other.inputType_; outputType_ = other.outputType_; - Options = other.options_ != null ? other.Options.Clone() : null; + options_ = other.options_ != null ? other.options_.Clone() : null; clientStreaming_ = other.clientStreaming_; serverStreaming_ = other.serverStreaming_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2686,40 +4309,76 @@ public MethodDescriptorProto Clone() { /// Field number for the "name" field. public const int NameFieldNumber = 1; - private string name_ = ""; + private readonly static string NameDefaultValue = ""; + + private string name_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name { - get { return name_; } + get { return name_ ?? NameDefaultValue; } set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "name" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasName { + get { return name_ != null; } + } + /// Clears the value of the "name" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearName() { + name_ = null; + } /// Field number for the "input_type" field. public const int InputTypeFieldNumber = 2; - private string inputType_ = ""; + private readonly static string InputTypeDefaultValue = ""; + + private string inputType_; /// /// Input and output type names. These are resolved in the same way as /// FieldDescriptorProto.type_name, but must refer to a message type. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string InputType { - get { return inputType_; } + get { return inputType_ ?? InputTypeDefaultValue; } set { inputType_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "input_type" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasInputType { + get { return inputType_ != null; } + } + /// Clears the value of the "input_type" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearInputType() { + inputType_ = null; + } /// Field number for the "output_type" field. public const int OutputTypeFieldNumber = 3; - private string outputType_ = ""; + private readonly static string OutputTypeDefaultValue = ""; + + private string outputType_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string OutputType { - get { return outputType_; } + get { return outputType_ ?? OutputTypeDefaultValue; } set { outputType_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "output_type" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOutputType { + get { return outputType_ != null; } + } + /// Clears the value of the "output_type" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOutputType() { + outputType_ = null; + } /// Field number for the "options" field. public const int OptionsFieldNumber = 4; @@ -2734,31 +4393,57 @@ public string OutputType { /// Field number for the "client_streaming" field. public const int ClientStreamingFieldNumber = 5; + private readonly static bool ClientStreamingDefaultValue = false; + private bool clientStreaming_; /// /// Identifies if client streams multiple client messages /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool ClientStreaming { - get { return clientStreaming_; } + get { if ((_hasBits0 & 1) != 0) { return clientStreaming_; } else { return ClientStreamingDefaultValue; } } set { + _hasBits0 |= 1; clientStreaming_ = value; } } + /// Gets whether the "client_streaming" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasClientStreaming { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "client_streaming" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearClientStreaming() { + _hasBits0 &= ~1; + } /// Field number for the "server_streaming" field. public const int ServerStreamingFieldNumber = 6; + private readonly static bool ServerStreamingDefaultValue = false; + private bool serverStreaming_; /// /// Identifies if server streams multiple server messages /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool ServerStreaming { - get { return serverStreaming_; } + get { if ((_hasBits0 & 2) != 0) { return serverStreaming_; } else { return ServerStreamingDefaultValue; } } set { + _hasBits0 |= 2; serverStreaming_ = value; } } + /// Gets whether the "server_streaming" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasServerStreaming { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "server_streaming" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearServerStreaming() { + _hasBits0 &= ~2; + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { @@ -2779,18 +4464,21 @@ public bool Equals(MethodDescriptorProto other) { if (!object.Equals(Options, other.Options)) return false; if (ClientStreaming != other.ClientStreaming) return false; if (ServerStreaming != other.ServerStreaming) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Name.Length != 0) hash ^= Name.GetHashCode(); - if (InputType.Length != 0) hash ^= InputType.GetHashCode(); - if (OutputType.Length != 0) hash ^= OutputType.GetHashCode(); + if (HasName) hash ^= Name.GetHashCode(); + if (HasInputType) hash ^= InputType.GetHashCode(); + if (HasOutputType) hash ^= OutputType.GetHashCode(); if (options_ != null) hash ^= Options.GetHashCode(); - if (ClientStreaming != false) hash ^= ClientStreaming.GetHashCode(); - if (ServerStreaming != false) hash ^= ServerStreaming.GetHashCode(); + if (HasClientStreaming) hash ^= ClientStreaming.GetHashCode(); + if (HasServerStreaming) hash ^= ServerStreaming.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -2801,15 +4489,18 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Name.Length != 0) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasName) { output.WriteRawTag(10); output.WriteString(Name); } - if (InputType.Length != 0) { + if (HasInputType) { output.WriteRawTag(18); output.WriteString(InputType); } - if (OutputType.Length != 0) { + if (HasOutputType) { output.WriteRawTag(26); output.WriteString(OutputType); } @@ -2817,37 +4508,77 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(34); output.WriteMessage(Options); } - if (ClientStreaming != false) { + if (HasClientStreaming) { output.WriteRawTag(40); output.WriteBool(ClientStreaming); } - if (ServerStreaming != false) { + if (HasServerStreaming) { output.WriteRawTag(48); output.WriteBool(ServerStreaming); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (HasInputType) { + output.WriteRawTag(18); + output.WriteString(InputType); + } + if (HasOutputType) { + output.WriteRawTag(26); + output.WriteString(OutputType); + } + if (options_ != null) { + output.WriteRawTag(34); + output.WriteMessage(Options); + } + if (HasClientStreaming) { + output.WriteRawTag(40); + output.WriteBool(ClientStreaming); + } + if (HasServerStreaming) { + output.WriteRawTag(48); + output.WriteBool(ServerStreaming); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Name.Length != 0) { + if (HasName) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); } - if (InputType.Length != 0) { + if (HasInputType) { size += 1 + pb::CodedOutputStream.ComputeStringSize(InputType); } - if (OutputType.Length != 0) { + if (HasOutputType) { size += 1 + pb::CodedOutputStream.ComputeStringSize(OutputType); } if (options_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options); } - if (ClientStreaming != false) { + if (HasClientStreaming) { size += 1 + 1; } - if (ServerStreaming != false) { + if (HasServerStreaming) { size += 1 + 1; } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -2856,36 +4587,40 @@ public void MergeFrom(MethodDescriptorProto other) { if (other == null) { return; } - if (other.Name.Length != 0) { + if (other.HasName) { Name = other.Name; } - if (other.InputType.Length != 0) { + if (other.HasInputType) { InputType = other.InputType; } - if (other.OutputType.Length != 0) { + if (other.HasOutputType) { OutputType = other.OutputType; } if (other.options_ != null) { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.MethodOptions(); + Options = new global::Google.Protobuf.Reflection.MethodOptions(); } Options.MergeFrom(other.Options); } - if (other.ClientStreaming != false) { + if (other.HasClientStreaming) { ClientStreaming = other.ClientStreaming; } - if (other.ServerStreaming != false) { + if (other.HasServerStreaming) { ServerStreaming = other.ServerStreaming; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { Name = input.ReadString(); @@ -2901,9 +4636,9 @@ public void MergeFrom(pb::CodedInputStream input) { } case 34: { if (options_ == null) { - options_ = new global::Google.Protobuf.Reflection.MethodOptions(); + Options = new global::Google.Protobuf.Reflection.MethodOptions(); } - input.ReadMessage(options_); + input.ReadMessage(Options); break; } case 40: { @@ -2916,12 +4651,62 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + InputType = input.ReadString(); + break; + } + case 26: { + OutputType = input.ReadString(); + break; + } + case 34: { + if (options_ == null) { + Options = new global::Google.Protobuf.Reflection.MethodOptions(); + } + input.ReadMessage(Options); + break; + } + case 40: { + ClientStreaming = input.ReadBool(); + break; + } + case 48: { + ServerStreaming = input.ReadBool(); + break; + } + } + } + } + #endif + } - internal sealed partial class FileOptions : pb::IMessage { + public sealed partial class FileOptions : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FileOptions()); + private pb::UnknownFieldSet _unknownFields; + internal pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -2935,8 +4720,6 @@ internal sealed partial class FileOptions : pb::IMessage { get { return Descriptor; } } - internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FileOptions() { OnConstruction(); @@ -2946,6 +4729,7 @@ public FileOptions() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FileOptions(FileOptions other) : this() { + _hasBits0 = other._hasBits0; javaPackage_ = other.javaPackage_; javaOuterClassname_ = other.javaOuterClassname_; javaMultipleFiles_ = other.javaMultipleFiles_; @@ -2964,7 +4748,11 @@ public FileOptions(FileOptions other) : this() { swiftPrefix_ = other.swiftPrefix_; phpClassPrefix_ = other.phpClassPrefix_; phpNamespace_ = other.phpNamespace_; + phpMetadataNamespace_ = other.phpMetadataNamespace_; + rubyPackage_ = other.rubyPackage_; uninterpretedOption_ = other.uninterpretedOption_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2974,7 +4762,9 @@ public FileOptions Clone() { /// Field number for the "java_package" field. public const int JavaPackageFieldNumber = 1; - private string javaPackage_ = ""; + private readonly static string JavaPackageDefaultValue = ""; + + private string javaPackage_; /// /// Sets the Java package where classes generated from this .proto will be /// placed. By default, the proto package is used, but this is often @@ -2983,15 +4773,27 @@ public FileOptions Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string JavaPackage { - get { return javaPackage_; } + get { return javaPackage_ ?? JavaPackageDefaultValue; } set { javaPackage_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "java_package" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasJavaPackage { + get { return javaPackage_ != null; } + } + /// Clears the value of the "java_package" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearJavaPackage() { + javaPackage_ = null; + } /// Field number for the "java_outer_classname" field. public const int JavaOuterClassnameFieldNumber = 8; - private string javaOuterClassname_ = ""; + private readonly static string JavaOuterClassnameDefaultValue = ""; + + private string javaOuterClassname_; /// /// If set, all the classes from the .proto file are wrapped in a single /// outer class with the given name. This applies to both Proto1 @@ -3001,14 +4803,26 @@ public string JavaPackage { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string JavaOuterClassname { - get { return javaOuterClassname_; } + get { return javaOuterClassname_ ?? JavaOuterClassnameDefaultValue; } set { javaOuterClassname_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "java_outer_classname" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasJavaOuterClassname { + get { return javaOuterClassname_ != null; } + } + /// Clears the value of the "java_outer_classname" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearJavaOuterClassname() { + javaOuterClassname_ = null; + } /// Field number for the "java_multiple_files" field. public const int JavaMultipleFilesFieldNumber = 10; + private readonly static bool JavaMultipleFilesDefaultValue = false; + private bool javaMultipleFiles_; /// /// If set true, then the Java code generator will generate a separate .java @@ -3020,14 +4834,27 @@ public string JavaOuterClassname { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool JavaMultipleFiles { - get { return javaMultipleFiles_; } + get { if ((_hasBits0 & 2) != 0) { return javaMultipleFiles_; } else { return JavaMultipleFilesDefaultValue; } } set { + _hasBits0 |= 2; javaMultipleFiles_ = value; } } + /// Gets whether the "java_multiple_files" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasJavaMultipleFiles { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "java_multiple_files" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearJavaMultipleFiles() { + _hasBits0 &= ~2; + } /// Field number for the "java_generate_equals_and_hash" field. public const int JavaGenerateEqualsAndHashFieldNumber = 20; + private readonly static bool JavaGenerateEqualsAndHashDefaultValue = false; + private bool javaGenerateEqualsAndHash_; /// /// This option does nothing. @@ -3035,14 +4862,29 @@ public bool JavaMultipleFiles { [global::System.ObsoleteAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool JavaGenerateEqualsAndHash { - get { return javaGenerateEqualsAndHash_; } + get { if ((_hasBits0 & 32) != 0) { return javaGenerateEqualsAndHash_; } else { return JavaGenerateEqualsAndHashDefaultValue; } } set { + _hasBits0 |= 32; javaGenerateEqualsAndHash_ = value; } } + /// Gets whether the "java_generate_equals_and_hash" field is set + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasJavaGenerateEqualsAndHash { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "java_generate_equals_and_hash" field + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearJavaGenerateEqualsAndHash() { + _hasBits0 &= ~32; + } /// Field number for the "java_string_check_utf8" field. public const int JavaStringCheckUtf8FieldNumber = 27; + private readonly static bool JavaStringCheckUtf8DefaultValue = false; + private bool javaStringCheckUtf8_; /// /// If set true, then the Java2 code generator will generate code that @@ -3054,26 +4896,52 @@ public bool JavaGenerateEqualsAndHash { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool JavaStringCheckUtf8 { - get { return javaStringCheckUtf8_; } + get { if ((_hasBits0 & 128) != 0) { return javaStringCheckUtf8_; } else { return JavaStringCheckUtf8DefaultValue; } } set { + _hasBits0 |= 128; javaStringCheckUtf8_ = value; } } + /// Gets whether the "java_string_check_utf8" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasJavaStringCheckUtf8 { + get { return (_hasBits0 & 128) != 0; } + } + /// Clears the value of the "java_string_check_utf8" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearJavaStringCheckUtf8() { + _hasBits0 &= ~128; + } /// Field number for the "optimize_for" field. public const int OptimizeForFieldNumber = 9; - private global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode optimizeFor_ = 0; + private readonly static global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode OptimizeForDefaultValue = global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode.Speed; + + private global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode optimizeFor_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode OptimizeFor { - get { return optimizeFor_; } + get { if ((_hasBits0 & 1) != 0) { return optimizeFor_; } else { return OptimizeForDefaultValue; } } set { + _hasBits0 |= 1; optimizeFor_ = value; } } + /// Gets whether the "optimize_for" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptimizeFor { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "optimize_for" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptimizeFor() { + _hasBits0 &= ~1; + } /// Field number for the "go_package" field. public const int GoPackageFieldNumber = 11; - private string goPackage_ = ""; + private readonly static string GoPackageDefaultValue = ""; + + private string goPackage_; /// /// Sets the Go package where structs generated from this .proto will be /// placed. If omitted, the Go package will be derived from the following: @@ -3083,14 +4951,26 @@ public bool JavaStringCheckUtf8 { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string GoPackage { - get { return goPackage_; } + get { return goPackage_ ?? GoPackageDefaultValue; } set { goPackage_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "go_package" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasGoPackage { + get { return goPackage_ != null; } + } + /// Clears the value of the "go_package" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearGoPackage() { + goPackage_ = null; + } /// Field number for the "cc_generic_services" field. public const int CcGenericServicesFieldNumber = 16; + private readonly static bool CcGenericServicesDefaultValue = false; + private bool ccGenericServices_; /// /// Should generic services be generated in each language? "Generic" services @@ -3106,47 +4986,99 @@ public string GoPackage { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool CcGenericServices { - get { return ccGenericServices_; } + get { if ((_hasBits0 & 4) != 0) { return ccGenericServices_; } else { return CcGenericServicesDefaultValue; } } set { + _hasBits0 |= 4; ccGenericServices_ = value; } } + /// Gets whether the "cc_generic_services" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCcGenericServices { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "cc_generic_services" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCcGenericServices() { + _hasBits0 &= ~4; + } /// Field number for the "java_generic_services" field. public const int JavaGenericServicesFieldNumber = 17; + private readonly static bool JavaGenericServicesDefaultValue = false; + private bool javaGenericServices_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool JavaGenericServices { - get { return javaGenericServices_; } + get { if ((_hasBits0 & 8) != 0) { return javaGenericServices_; } else { return JavaGenericServicesDefaultValue; } } set { + _hasBits0 |= 8; javaGenericServices_ = value; } } + /// Gets whether the "java_generic_services" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasJavaGenericServices { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "java_generic_services" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearJavaGenericServices() { + _hasBits0 &= ~8; + } /// Field number for the "py_generic_services" field. public const int PyGenericServicesFieldNumber = 18; + private readonly static bool PyGenericServicesDefaultValue = false; + private bool pyGenericServices_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool PyGenericServices { - get { return pyGenericServices_; } + get { if ((_hasBits0 & 16) != 0) { return pyGenericServices_; } else { return PyGenericServicesDefaultValue; } } set { + _hasBits0 |= 16; pyGenericServices_ = value; } } + /// Gets whether the "py_generic_services" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPyGenericServices { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "py_generic_services" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPyGenericServices() { + _hasBits0 &= ~16; + } /// Field number for the "php_generic_services" field. - public const int PhpGenericServicesFieldNumber = 19; + public const int PhpGenericServicesFieldNumber = 42; + private readonly static bool PhpGenericServicesDefaultValue = false; + private bool phpGenericServices_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool PhpGenericServices { - get { return phpGenericServices_; } + get { if ((_hasBits0 & 512) != 0) { return phpGenericServices_; } else { return PhpGenericServicesDefaultValue; } } set { + _hasBits0 |= 512; phpGenericServices_ = value; } } + /// Gets whether the "php_generic_services" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPhpGenericServices { + get { return (_hasBits0 & 512) != 0; } + } + /// Clears the value of the "php_generic_services" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPhpGenericServices() { + _hasBits0 &= ~512; + } /// Field number for the "deprecated" field. public const int DeprecatedFieldNumber = 23; + private readonly static bool DeprecatedDefaultValue = false; + private bool deprecated_; /// /// Is this file deprecated? @@ -3156,14 +5088,27 @@ public bool PhpGenericServices { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Deprecated { - get { return deprecated_; } + get { if ((_hasBits0 & 64) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } } set { + _hasBits0 |= 64; deprecated_ = value; } } + /// Gets whether the "deprecated" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDeprecated { + get { return (_hasBits0 & 64) != 0; } + } + /// Clears the value of the "deprecated" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDeprecated() { + _hasBits0 &= ~64; + } /// Field number for the "cc_enable_arenas" field. public const int CcEnableArenasFieldNumber = 31; + private readonly static bool CcEnableArenasDefaultValue = true; + private bool ccEnableArenas_; /// /// Enables the use of arenas for the proto messages in this file. This applies @@ -3171,44 +5116,81 @@ public bool Deprecated { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool CcEnableArenas { - get { return ccEnableArenas_; } + get { if ((_hasBits0 & 256) != 0) { return ccEnableArenas_; } else { return CcEnableArenasDefaultValue; } } set { + _hasBits0 |= 256; ccEnableArenas_ = value; } } + /// Gets whether the "cc_enable_arenas" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCcEnableArenas { + get { return (_hasBits0 & 256) != 0; } + } + /// Clears the value of the "cc_enable_arenas" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCcEnableArenas() { + _hasBits0 &= ~256; + } /// Field number for the "objc_class_prefix" field. public const int ObjcClassPrefixFieldNumber = 36; - private string objcClassPrefix_ = ""; + private readonly static string ObjcClassPrefixDefaultValue = ""; + + private string objcClassPrefix_; /// /// Sets the objective c class prefix which is prepended to all objective c /// generated classes from this .proto. There is no default. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string ObjcClassPrefix { - get { return objcClassPrefix_; } + get { return objcClassPrefix_ ?? ObjcClassPrefixDefaultValue; } set { objcClassPrefix_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "objc_class_prefix" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasObjcClassPrefix { + get { return objcClassPrefix_ != null; } + } + /// Clears the value of the "objc_class_prefix" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearObjcClassPrefix() { + objcClassPrefix_ = null; + } /// Field number for the "csharp_namespace" field. public const int CsharpNamespaceFieldNumber = 37; - private string csharpNamespace_ = ""; + private readonly static string CsharpNamespaceDefaultValue = ""; + + private string csharpNamespace_; /// /// Namespace for generated classes; defaults to the package. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string CsharpNamespace { - get { return csharpNamespace_; } + get { return csharpNamespace_ ?? CsharpNamespaceDefaultValue; } set { csharpNamespace_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "csharp_namespace" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCsharpNamespace { + get { return csharpNamespace_ != null; } + } + /// Clears the value of the "csharp_namespace" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCsharpNamespace() { + csharpNamespace_ = null; + } /// Field number for the "swift_prefix" field. public const int SwiftPrefixFieldNumber = 39; - private string swiftPrefix_ = ""; + private readonly static string SwiftPrefixDefaultValue = ""; + + private string swiftPrefix_; /// /// By default Swift generators will take the proto package and CamelCase it /// replacing '.' with underscore and use that to prefix the types/symbols @@ -3217,30 +5199,54 @@ public string CsharpNamespace { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string SwiftPrefix { - get { return swiftPrefix_; } + get { return swiftPrefix_ ?? SwiftPrefixDefaultValue; } set { swiftPrefix_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "swift_prefix" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSwiftPrefix { + get { return swiftPrefix_ != null; } + } + /// Clears the value of the "swift_prefix" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSwiftPrefix() { + swiftPrefix_ = null; + } /// Field number for the "php_class_prefix" field. public const int PhpClassPrefixFieldNumber = 40; - private string phpClassPrefix_ = ""; + private readonly static string PhpClassPrefixDefaultValue = ""; + + private string phpClassPrefix_; /// /// Sets the php class prefix which is prepended to all php generated classes /// from this .proto. Default is empty. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string PhpClassPrefix { - get { return phpClassPrefix_; } + get { return phpClassPrefix_ ?? PhpClassPrefixDefaultValue; } set { phpClassPrefix_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "php_class_prefix" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPhpClassPrefix { + get { return phpClassPrefix_ != null; } + } + /// Clears the value of the "php_class_prefix" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPhpClassPrefix() { + phpClassPrefix_ = null; + } /// Field number for the "php_namespace" field. public const int PhpNamespaceFieldNumber = 41; - private string phpNamespace_ = ""; + private readonly static string PhpNamespaceDefaultValue = ""; + + private string phpNamespace_; /// /// Use this option to change the namespace of php generated classes. Default /// is empty. When this option is empty, the package name will be used for @@ -3248,11 +5254,77 @@ public string PhpClassPrefix { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string PhpNamespace { - get { return phpNamespace_; } + get { return phpNamespace_ ?? PhpNamespaceDefaultValue; } set { phpNamespace_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "php_namespace" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPhpNamespace { + get { return phpNamespace_ != null; } + } + /// Clears the value of the "php_namespace" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPhpNamespace() { + phpNamespace_ = null; + } + + /// Field number for the "php_metadata_namespace" field. + public const int PhpMetadataNamespaceFieldNumber = 44; + private readonly static string PhpMetadataNamespaceDefaultValue = ""; + + private string phpMetadataNamespace_; + /// + /// Use this option to change the namespace of php generated metadata classes. + /// Default is empty. When this option is empty, the proto file name will be + /// used for determining the namespace. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string PhpMetadataNamespace { + get { return phpMetadataNamespace_ ?? PhpMetadataNamespaceDefaultValue; } + set { + phpMetadataNamespace_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "php_metadata_namespace" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPhpMetadataNamespace { + get { return phpMetadataNamespace_ != null; } + } + /// Clears the value of the "php_metadata_namespace" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPhpMetadataNamespace() { + phpMetadataNamespace_ = null; + } + + /// Field number for the "ruby_package" field. + public const int RubyPackageFieldNumber = 45; + private readonly static string RubyPackageDefaultValue = ""; + + private string rubyPackage_; + /// + /// Use this option to change the package of ruby generated classes. Default + /// is empty. When this option is not set, the package name will be used for + /// determining the ruby package. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string RubyPackage { + get { return rubyPackage_ ?? RubyPackageDefaultValue; } + set { + rubyPackage_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "ruby_package" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasRubyPackage { + get { return rubyPackage_ != null; } + } + /// Clears the value of the "ruby_package" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearRubyPackage() { + rubyPackage_ = null; + } /// Field number for the "uninterpreted_option" field. public const int UninterpretedOptionFieldNumber = 999; @@ -3260,7 +5332,8 @@ public string PhpNamespace { = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.Reflection.UninterpretedOption.Parser); private readonly pbc::RepeatedField uninterpretedOption_ = new pbc::RepeatedField(); /// - /// The parser stores options it doesn't recognize here. See above. + /// The parser stores options it doesn't recognize here. + /// See the documentation for the "Options" section above. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pbc::RepeatedField UninterpretedOption { @@ -3298,32 +5371,45 @@ public bool Equals(FileOptions other) { if (SwiftPrefix != other.SwiftPrefix) return false; if (PhpClassPrefix != other.PhpClassPrefix) return false; if (PhpNamespace != other.PhpNamespace) return false; + if (PhpMetadataNamespace != other.PhpMetadataNamespace) return false; + if (RubyPackage != other.RubyPackage) return false; if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false; - return true; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (JavaPackage.Length != 0) hash ^= JavaPackage.GetHashCode(); - if (JavaOuterClassname.Length != 0) hash ^= JavaOuterClassname.GetHashCode(); - if (JavaMultipleFiles != false) hash ^= JavaMultipleFiles.GetHashCode(); - if (JavaGenerateEqualsAndHash != false) hash ^= JavaGenerateEqualsAndHash.GetHashCode(); - if (JavaStringCheckUtf8 != false) hash ^= JavaStringCheckUtf8.GetHashCode(); - if (OptimizeFor != 0) hash ^= OptimizeFor.GetHashCode(); - if (GoPackage.Length != 0) hash ^= GoPackage.GetHashCode(); - if (CcGenericServices != false) hash ^= CcGenericServices.GetHashCode(); - if (JavaGenericServices != false) hash ^= JavaGenericServices.GetHashCode(); - if (PyGenericServices != false) hash ^= PyGenericServices.GetHashCode(); - if (PhpGenericServices != false) hash ^= PhpGenericServices.GetHashCode(); - if (Deprecated != false) hash ^= Deprecated.GetHashCode(); - if (CcEnableArenas != false) hash ^= CcEnableArenas.GetHashCode(); - if (ObjcClassPrefix.Length != 0) hash ^= ObjcClassPrefix.GetHashCode(); - if (CsharpNamespace.Length != 0) hash ^= CsharpNamespace.GetHashCode(); - if (SwiftPrefix.Length != 0) hash ^= SwiftPrefix.GetHashCode(); - if (PhpClassPrefix.Length != 0) hash ^= PhpClassPrefix.GetHashCode(); - if (PhpNamespace.Length != 0) hash ^= PhpNamespace.GetHashCode(); + if (HasJavaPackage) hash ^= JavaPackage.GetHashCode(); + if (HasJavaOuterClassname) hash ^= JavaOuterClassname.GetHashCode(); + if (HasJavaMultipleFiles) hash ^= JavaMultipleFiles.GetHashCode(); + if (HasJavaGenerateEqualsAndHash) hash ^= JavaGenerateEqualsAndHash.GetHashCode(); + if (HasJavaStringCheckUtf8) hash ^= JavaStringCheckUtf8.GetHashCode(); + if (HasOptimizeFor) hash ^= OptimizeFor.GetHashCode(); + if (HasGoPackage) hash ^= GoPackage.GetHashCode(); + if (HasCcGenericServices) hash ^= CcGenericServices.GetHashCode(); + if (HasJavaGenericServices) hash ^= JavaGenericServices.GetHashCode(); + if (HasPyGenericServices) hash ^= PyGenericServices.GetHashCode(); + if (HasPhpGenericServices) hash ^= PhpGenericServices.GetHashCode(); + if (HasDeprecated) hash ^= Deprecated.GetHashCode(); + if (HasCcEnableArenas) hash ^= CcEnableArenas.GetHashCode(); + if (HasObjcClassPrefix) hash ^= ObjcClassPrefix.GetHashCode(); + if (HasCsharpNamespace) hash ^= CsharpNamespace.GetHashCode(); + if (HasSwiftPrefix) hash ^= SwiftPrefix.GetHashCode(); + if (HasPhpClassPrefix) hash ^= PhpClassPrefix.GetHashCode(); + if (HasPhpNamespace) hash ^= PhpNamespace.GetHashCode(); + if (HasPhpMetadataNamespace) hash ^= PhpMetadataNamespace.GetHashCode(); + if (HasRubyPackage) hash ^= RubyPackage.GetHashCode(); hash ^= uninterpretedOption_.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -3334,139 +5420,262 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (JavaPackage.Length != 0) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasJavaPackage) { output.WriteRawTag(10); output.WriteString(JavaPackage); } - if (JavaOuterClassname.Length != 0) { + if (HasJavaOuterClassname) { output.WriteRawTag(66); output.WriteString(JavaOuterClassname); } - if (OptimizeFor != 0) { + if (HasOptimizeFor) { output.WriteRawTag(72); output.WriteEnum((int) OptimizeFor); } - if (JavaMultipleFiles != false) { + if (HasJavaMultipleFiles) { output.WriteRawTag(80); output.WriteBool(JavaMultipleFiles); } - if (GoPackage.Length != 0) { + if (HasGoPackage) { output.WriteRawTag(90); output.WriteString(GoPackage); } - if (CcGenericServices != false) { + if (HasCcGenericServices) { output.WriteRawTag(128, 1); output.WriteBool(CcGenericServices); } - if (JavaGenericServices != false) { + if (HasJavaGenericServices) { output.WriteRawTag(136, 1); output.WriteBool(JavaGenericServices); } - if (PyGenericServices != false) { + if (HasPyGenericServices) { output.WriteRawTag(144, 1); output.WriteBool(PyGenericServices); } - if (PhpGenericServices != false) { - output.WriteRawTag(152, 1); + if (HasJavaGenerateEqualsAndHash) { + output.WriteRawTag(160, 1); + output.WriteBool(JavaGenerateEqualsAndHash); + } + if (HasDeprecated) { + output.WriteRawTag(184, 1); + output.WriteBool(Deprecated); + } + if (HasJavaStringCheckUtf8) { + output.WriteRawTag(216, 1); + output.WriteBool(JavaStringCheckUtf8); + } + if (HasCcEnableArenas) { + output.WriteRawTag(248, 1); + output.WriteBool(CcEnableArenas); + } + if (HasObjcClassPrefix) { + output.WriteRawTag(162, 2); + output.WriteString(ObjcClassPrefix); + } + if (HasCsharpNamespace) { + output.WriteRawTag(170, 2); + output.WriteString(CsharpNamespace); + } + if (HasSwiftPrefix) { + output.WriteRawTag(186, 2); + output.WriteString(SwiftPrefix); + } + if (HasPhpClassPrefix) { + output.WriteRawTag(194, 2); + output.WriteString(PhpClassPrefix); + } + if (HasPhpNamespace) { + output.WriteRawTag(202, 2); + output.WriteString(PhpNamespace); + } + if (HasPhpGenericServices) { + output.WriteRawTag(208, 2); output.WriteBool(PhpGenericServices); } - if (JavaGenerateEqualsAndHash != false) { + if (HasPhpMetadataNamespace) { + output.WriteRawTag(226, 2); + output.WriteString(PhpMetadataNamespace); + } + if (HasRubyPackage) { + output.WriteRawTag(234, 2); + output.WriteString(RubyPackage); + } + uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasJavaPackage) { + output.WriteRawTag(10); + output.WriteString(JavaPackage); + } + if (HasJavaOuterClassname) { + output.WriteRawTag(66); + output.WriteString(JavaOuterClassname); + } + if (HasOptimizeFor) { + output.WriteRawTag(72); + output.WriteEnum((int) OptimizeFor); + } + if (HasJavaMultipleFiles) { + output.WriteRawTag(80); + output.WriteBool(JavaMultipleFiles); + } + if (HasGoPackage) { + output.WriteRawTag(90); + output.WriteString(GoPackage); + } + if (HasCcGenericServices) { + output.WriteRawTag(128, 1); + output.WriteBool(CcGenericServices); + } + if (HasJavaGenericServices) { + output.WriteRawTag(136, 1); + output.WriteBool(JavaGenericServices); + } + if (HasPyGenericServices) { + output.WriteRawTag(144, 1); + output.WriteBool(PyGenericServices); + } + if (HasJavaGenerateEqualsAndHash) { output.WriteRawTag(160, 1); output.WriteBool(JavaGenerateEqualsAndHash); } - if (Deprecated != false) { + if (HasDeprecated) { output.WriteRawTag(184, 1); output.WriteBool(Deprecated); } - if (JavaStringCheckUtf8 != false) { + if (HasJavaStringCheckUtf8) { output.WriteRawTag(216, 1); output.WriteBool(JavaStringCheckUtf8); } - if (CcEnableArenas != false) { + if (HasCcEnableArenas) { output.WriteRawTag(248, 1); output.WriteBool(CcEnableArenas); } - if (ObjcClassPrefix.Length != 0) { + if (HasObjcClassPrefix) { output.WriteRawTag(162, 2); output.WriteString(ObjcClassPrefix); } - if (CsharpNamespace.Length != 0) { + if (HasCsharpNamespace) { output.WriteRawTag(170, 2); output.WriteString(CsharpNamespace); } - if (SwiftPrefix.Length != 0) { + if (HasSwiftPrefix) { output.WriteRawTag(186, 2); output.WriteString(SwiftPrefix); } - if (PhpClassPrefix.Length != 0) { + if (HasPhpClassPrefix) { output.WriteRawTag(194, 2); output.WriteString(PhpClassPrefix); } - if (PhpNamespace.Length != 0) { + if (HasPhpNamespace) { output.WriteRawTag(202, 2); output.WriteString(PhpNamespace); } - uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); + if (HasPhpGenericServices) { + output.WriteRawTag(208, 2); + output.WriteBool(PhpGenericServices); + } + if (HasPhpMetadataNamespace) { + output.WriteRawTag(226, 2); + output.WriteString(PhpMetadataNamespace); + } + if (HasRubyPackage) { + output.WriteRawTag(234, 2); + output.WriteString(RubyPackage); + } + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (JavaPackage.Length != 0) { + if (HasJavaPackage) { size += 1 + pb::CodedOutputStream.ComputeStringSize(JavaPackage); } - if (JavaOuterClassname.Length != 0) { + if (HasJavaOuterClassname) { size += 1 + pb::CodedOutputStream.ComputeStringSize(JavaOuterClassname); } - if (JavaMultipleFiles != false) { + if (HasJavaMultipleFiles) { size += 1 + 1; } - if (JavaGenerateEqualsAndHash != false) { + if (HasJavaGenerateEqualsAndHash) { size += 2 + 1; } - if (JavaStringCheckUtf8 != false) { + if (HasJavaStringCheckUtf8) { size += 2 + 1; } - if (OptimizeFor != 0) { + if (HasOptimizeFor) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) OptimizeFor); } - if (GoPackage.Length != 0) { + if (HasGoPackage) { size += 1 + pb::CodedOutputStream.ComputeStringSize(GoPackage); } - if (CcGenericServices != false) { + if (HasCcGenericServices) { size += 2 + 1; } - if (JavaGenericServices != false) { + if (HasJavaGenericServices) { size += 2 + 1; } - if (PyGenericServices != false) { + if (HasPyGenericServices) { size += 2 + 1; } - if (PhpGenericServices != false) { + if (HasPhpGenericServices) { size += 2 + 1; } - if (Deprecated != false) { + if (HasDeprecated) { size += 2 + 1; } - if (CcEnableArenas != false) { + if (HasCcEnableArenas) { size += 2 + 1; } - if (ObjcClassPrefix.Length != 0) { + if (HasObjcClassPrefix) { size += 2 + pb::CodedOutputStream.ComputeStringSize(ObjcClassPrefix); } - if (CsharpNamespace.Length != 0) { + if (HasCsharpNamespace) { size += 2 + pb::CodedOutputStream.ComputeStringSize(CsharpNamespace); } - if (SwiftPrefix.Length != 0) { + if (HasSwiftPrefix) { size += 2 + pb::CodedOutputStream.ComputeStringSize(SwiftPrefix); } - if (PhpClassPrefix.Length != 0) { + if (HasPhpClassPrefix) { size += 2 + pb::CodedOutputStream.ComputeStringSize(PhpClassPrefix); } - if (PhpNamespace.Length != 0) { + if (HasPhpNamespace) { size += 2 + pb::CodedOutputStream.ComputeStringSize(PhpNamespace); } + if (HasPhpMetadataNamespace) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(PhpMetadataNamespace); + } + if (HasRubyPackage) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(RubyPackage); + } size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec); + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -3475,70 +5684,183 @@ public void MergeFrom(FileOptions other) { if (other == null) { return; } - if (other.JavaPackage.Length != 0) { + if (other.HasJavaPackage) { JavaPackage = other.JavaPackage; } - if (other.JavaOuterClassname.Length != 0) { + if (other.HasJavaOuterClassname) { JavaOuterClassname = other.JavaOuterClassname; } - if (other.JavaMultipleFiles != false) { + if (other.HasJavaMultipleFiles) { JavaMultipleFiles = other.JavaMultipleFiles; } - if (other.JavaGenerateEqualsAndHash != false) { + if (other.HasJavaGenerateEqualsAndHash) { JavaGenerateEqualsAndHash = other.JavaGenerateEqualsAndHash; } - if (other.JavaStringCheckUtf8 != false) { + if (other.HasJavaStringCheckUtf8) { JavaStringCheckUtf8 = other.JavaStringCheckUtf8; } - if (other.OptimizeFor != 0) { + if (other.HasOptimizeFor) { OptimizeFor = other.OptimizeFor; } - if (other.GoPackage.Length != 0) { + if (other.HasGoPackage) { GoPackage = other.GoPackage; } - if (other.CcGenericServices != false) { + if (other.HasCcGenericServices) { CcGenericServices = other.CcGenericServices; } - if (other.JavaGenericServices != false) { + if (other.HasJavaGenericServices) { JavaGenericServices = other.JavaGenericServices; } - if (other.PyGenericServices != false) { + if (other.HasPyGenericServices) { PyGenericServices = other.PyGenericServices; } - if (other.PhpGenericServices != false) { + if (other.HasPhpGenericServices) { PhpGenericServices = other.PhpGenericServices; } - if (other.Deprecated != false) { + if (other.HasDeprecated) { Deprecated = other.Deprecated; } - if (other.CcEnableArenas != false) { + if (other.HasCcEnableArenas) { CcEnableArenas = other.CcEnableArenas; } - if (other.ObjcClassPrefix.Length != 0) { + if (other.HasObjcClassPrefix) { ObjcClassPrefix = other.ObjcClassPrefix; } - if (other.CsharpNamespace.Length != 0) { + if (other.HasCsharpNamespace) { CsharpNamespace = other.CsharpNamespace; } - if (other.SwiftPrefix.Length != 0) { + if (other.HasSwiftPrefix) { SwiftPrefix = other.SwiftPrefix; } - if (other.PhpClassPrefix.Length != 0) { + if (other.HasPhpClassPrefix) { PhpClassPrefix = other.PhpClassPrefix; } - if (other.PhpNamespace.Length != 0) { + if (other.HasPhpNamespace) { PhpNamespace = other.PhpNamespace; } - uninterpretedOption_.Add(other.uninterpretedOption_); + if (other.HasPhpMetadataNamespace) { + PhpMetadataNamespace = other.PhpMetadataNamespace; + } + if (other.HasRubyPackage) { + RubyPackage = other.RubyPackage; + } + uninterpretedOption_.Add(other.uninterpretedOption_); + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + case 10: { + JavaPackage = input.ReadString(); + break; + } + case 66: { + JavaOuterClassname = input.ReadString(); + break; + } + case 72: { + OptimizeFor = (global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) input.ReadEnum(); + break; + } + case 80: { + JavaMultipleFiles = input.ReadBool(); + break; + } + case 90: { + GoPackage = input.ReadString(); + break; + } + case 128: { + CcGenericServices = input.ReadBool(); + break; + } + case 136: { + JavaGenericServices = input.ReadBool(); + break; + } + case 144: { + PyGenericServices = input.ReadBool(); + break; + } + case 160: { + JavaGenerateEqualsAndHash = input.ReadBool(); + break; + } + case 184: { + Deprecated = input.ReadBool(); + break; + } + case 216: { + JavaStringCheckUtf8 = input.ReadBool(); + break; + } + case 248: { + CcEnableArenas = input.ReadBool(); + break; + } + case 290: { + ObjcClassPrefix = input.ReadString(); + break; + } + case 298: { + CsharpNamespace = input.ReadString(); + break; + } + case 314: { + SwiftPrefix = input.ReadString(); + break; + } + case 322: { + PhpClassPrefix = input.ReadString(); + break; + } + case 330: { + PhpNamespace = input.ReadString(); + break; + } + case 336: { + PhpGenericServices = input.ReadBool(); + break; + } + case 354: { + PhpMetadataNamespace = input.ReadString(); + break; + } + case 362: { + RubyPackage = input.ReadString(); + break; + } + case 7994: { + uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec); + break; + } + } + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } break; case 10: { JavaPackage = input.ReadString(); @@ -3549,7 +5871,7 @@ public void MergeFrom(pb::CodedInputStream input) { break; } case 72: { - optimizeFor_ = (global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) input.ReadEnum(); + OptimizeFor = (global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) input.ReadEnum(); break; } case 80: { @@ -3572,10 +5894,6 @@ public void MergeFrom(pb::CodedInputStream input) { PyGenericServices = input.ReadBool(); break; } - case 152: { - PhpGenericServices = input.ReadBool(); - break; - } case 160: { JavaGenerateEqualsAndHash = input.ReadBool(); break; @@ -3612,13 +5930,48 @@ public void MergeFrom(pb::CodedInputStream input) { PhpNamespace = input.ReadString(); break; } + case 336: { + PhpGenericServices = input.ReadBool(); + break; + } + case 354: { + PhpMetadataNamespace = input.ReadString(); + break; + } + case 362: { + RubyPackage = input.ReadString(); + break; + } case 7994: { - uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec); + uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec); break; } } } } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } #region Nested types /// Container for nested types declared in the FileOptions message type. @@ -3627,7 +5980,7 @@ public static partial class Types { /// /// Generated classes can be optimized for speed or code size. /// - internal enum OptimizeMode { + public enum OptimizeMode { /// /// Generate complete code for parsing, serialization, /// @@ -3647,8 +6000,16 @@ internal enum OptimizeMode { } - internal sealed partial class MessageOptions : pb::IMessage { + public sealed partial class MessageOptions : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageOptions()); + private pb::UnknownFieldSet _unknownFields; + internal pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -3662,8 +6023,6 @@ internal sealed partial class MessageOptions : pb::IMessage { get { return Descriptor; } } - internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public MessageOptions() { OnConstruction(); @@ -3673,11 +6032,14 @@ public MessageOptions() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public MessageOptions(MessageOptions other) : this() { + _hasBits0 = other._hasBits0; messageSetWireFormat_ = other.messageSetWireFormat_; noStandardDescriptorAccessor_ = other.noStandardDescriptorAccessor_; deprecated_ = other.deprecated_; mapEntry_ = other.mapEntry_; uninterpretedOption_ = other.uninterpretedOption_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -3687,6 +6049,8 @@ public MessageOptions Clone() { /// Field number for the "message_set_wire_format" field. public const int MessageSetWireFormatFieldNumber = 1; + private readonly static bool MessageSetWireFormatDefaultValue = false; + private bool messageSetWireFormat_; /// /// Set true to use the old proto1 MessageSet wire format for extensions. @@ -3710,14 +6074,27 @@ public MessageOptions Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool MessageSetWireFormat { - get { return messageSetWireFormat_; } + get { if ((_hasBits0 & 1) != 0) { return messageSetWireFormat_; } else { return MessageSetWireFormatDefaultValue; } } set { + _hasBits0 |= 1; messageSetWireFormat_ = value; } } + /// Gets whether the "message_set_wire_format" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMessageSetWireFormat { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "message_set_wire_format" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMessageSetWireFormat() { + _hasBits0 &= ~1; + } /// Field number for the "no_standard_descriptor_accessor" field. public const int NoStandardDescriptorAccessorFieldNumber = 2; + private readonly static bool NoStandardDescriptorAccessorDefaultValue = false; + private bool noStandardDescriptorAccessor_; /// /// Disables the generation of the standard "descriptor()" accessor, which can @@ -3726,14 +6103,27 @@ public bool MessageSetWireFormat { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool NoStandardDescriptorAccessor { - get { return noStandardDescriptorAccessor_; } + get { if ((_hasBits0 & 2) != 0) { return noStandardDescriptorAccessor_; } else { return NoStandardDescriptorAccessorDefaultValue; } } set { + _hasBits0 |= 2; noStandardDescriptorAccessor_ = value; } } + /// Gets whether the "no_standard_descriptor_accessor" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNoStandardDescriptorAccessor { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "no_standard_descriptor_accessor" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNoStandardDescriptorAccessor() { + _hasBits0 &= ~2; + } /// Field number for the "deprecated" field. public const int DeprecatedFieldNumber = 3; + private readonly static bool DeprecatedDefaultValue = false; + private bool deprecated_; /// /// Is this message deprecated? @@ -3743,14 +6133,27 @@ public bool NoStandardDescriptorAccessor { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Deprecated { - get { return deprecated_; } + get { if ((_hasBits0 & 4) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } } set { + _hasBits0 |= 4; deprecated_ = value; } } + /// Gets whether the "deprecated" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDeprecated { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "deprecated" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDeprecated() { + _hasBits0 &= ~4; + } /// Field number for the "map_entry" field. public const int MapEntryFieldNumber = 7; + private readonly static bool MapEntryDefaultValue = false; + private bool mapEntry_; /// /// Whether the message is an automatically generated map entry type for the @@ -3768,7 +6171,7 @@ public bool Deprecated { /// /// Implementations may choose not to generate the map_entry=true message, but /// use a native map in the target language to hold the keys and values. - /// The reflection APIs in such implementions still need to work as + /// The reflection APIs in such implementations still need to work as /// if the field is a repeated message field. /// /// NOTE: Do not set the option in .proto files. Always use the maps syntax @@ -3777,11 +6180,22 @@ public bool Deprecated { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool MapEntry { - get { return mapEntry_; } + get { if ((_hasBits0 & 8) != 0) { return mapEntry_; } else { return MapEntryDefaultValue; } } set { + _hasBits0 |= 8; mapEntry_ = value; } } + /// Gets whether the "map_entry" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasMapEntry { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "map_entry" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMapEntry() { + _hasBits0 &= ~8; + } /// Field number for the "uninterpreted_option" field. public const int UninterpretedOptionFieldNumber = 999; @@ -3814,17 +6228,26 @@ public bool Equals(MessageOptions other) { if (Deprecated != other.Deprecated) return false; if (MapEntry != other.MapEntry) return false; if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false; - return true; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (MessageSetWireFormat != false) hash ^= MessageSetWireFormat.GetHashCode(); - if (NoStandardDescriptorAccessor != false) hash ^= NoStandardDescriptorAccessor.GetHashCode(); - if (Deprecated != false) hash ^= Deprecated.GetHashCode(); - if (MapEntry != false) hash ^= MapEntry.GetHashCode(); + if (HasMessageSetWireFormat) hash ^= MessageSetWireFormat.GetHashCode(); + if (HasNoStandardDescriptorAccessor) hash ^= NoStandardDescriptorAccessor.GetHashCode(); + if (HasDeprecated) hash ^= Deprecated.GetHashCode(); + if (HasMapEntry) hash ^= MapEntry.GetHashCode(); hash ^= uninterpretedOption_.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -3835,41 +6258,86 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (MessageSetWireFormat != false) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasMessageSetWireFormat) { output.WriteRawTag(8); output.WriteBool(MessageSetWireFormat); } - if (NoStandardDescriptorAccessor != false) { + if (HasNoStandardDescriptorAccessor) { output.WriteRawTag(16); output.WriteBool(NoStandardDescriptorAccessor); } - if (Deprecated != false) { + if (HasDeprecated) { output.WriteRawTag(24); output.WriteBool(Deprecated); } - if (MapEntry != false) { + if (HasMapEntry) { output.WriteRawTag(56); output.WriteBool(MapEntry); } uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasMessageSetWireFormat) { + output.WriteRawTag(8); + output.WriteBool(MessageSetWireFormat); + } + if (HasNoStandardDescriptorAccessor) { + output.WriteRawTag(16); + output.WriteBool(NoStandardDescriptorAccessor); + } + if (HasDeprecated) { + output.WriteRawTag(24); + output.WriteBool(Deprecated); + } + if (HasMapEntry) { + output.WriteRawTag(56); + output.WriteBool(MapEntry); + } + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (MessageSetWireFormat != false) { + if (HasMessageSetWireFormat) { size += 1 + 1; } - if (NoStandardDescriptorAccessor != false) { + if (HasNoStandardDescriptorAccessor) { size += 1 + 1; } - if (Deprecated != false) { + if (HasDeprecated) { size += 1 + 1; } - if (MapEntry != false) { + if (HasMapEntry) { size += 1 + 1; } size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec); + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -3878,28 +6346,35 @@ public void MergeFrom(MessageOptions other) { if (other == null) { return; } - if (other.MessageSetWireFormat != false) { + if (other.HasMessageSetWireFormat) { MessageSetWireFormat = other.MessageSetWireFormat; } - if (other.NoStandardDescriptorAccessor != false) { + if (other.HasNoStandardDescriptorAccessor) { NoStandardDescriptorAccessor = other.NoStandardDescriptorAccessor; } - if (other.Deprecated != false) { + if (other.HasDeprecated) { Deprecated = other.Deprecated; } - if (other.MapEntry != false) { + if (other.HasMapEntry) { MapEntry = other.MapEntry; } uninterpretedOption_.Add(other.uninterpretedOption_); + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } break; case 8: { MessageSetWireFormat = input.ReadBool(); @@ -3923,12 +6398,79 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + case 8: { + MessageSetWireFormat = input.ReadBool(); + break; + } + case 16: { + NoStandardDescriptorAccessor = input.ReadBool(); + break; + } + case 24: { + Deprecated = input.ReadBool(); + break; + } + case 56: { + MapEntry = input.ReadBool(); + break; + } + case 7994: { + uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec); + break; + } + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); } } - internal sealed partial class FieldOptions : pb::IMessage { + public sealed partial class FieldOptions : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FieldOptions()); + private pb::UnknownFieldSet _unknownFields; + internal pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -3942,8 +6484,6 @@ internal sealed partial class FieldOptions : pb::IMessage { get { return Descriptor; } } - internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FieldOptions() { OnConstruction(); @@ -3953,6 +6493,7 @@ public FieldOptions() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FieldOptions(FieldOptions other) : this() { + _hasBits0 = other._hasBits0; ctype_ = other.ctype_; packed_ = other.packed_; jstype_ = other.jstype_; @@ -3960,6 +6501,8 @@ public FieldOptions(FieldOptions other) : this() { deprecated_ = other.deprecated_; weak_ = other.weak_; uninterpretedOption_ = other.uninterpretedOption_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -3969,7 +6512,9 @@ public FieldOptions Clone() { /// Field number for the "ctype" field. public const int CtypeFieldNumber = 1; - private global::Google.Protobuf.Reflection.FieldOptions.Types.CType ctype_ = 0; + private readonly static global::Google.Protobuf.Reflection.FieldOptions.Types.CType CtypeDefaultValue = global::Google.Protobuf.Reflection.FieldOptions.Types.CType.String; + + private global::Google.Protobuf.Reflection.FieldOptions.Types.CType ctype_; /// /// The ctype option instructs the C++ code generator to use a different /// representation of the field than it normally would. See the specific @@ -3978,14 +6523,27 @@ public FieldOptions Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Google.Protobuf.Reflection.FieldOptions.Types.CType Ctype { - get { return ctype_; } + get { if ((_hasBits0 & 1) != 0) { return ctype_; } else { return CtypeDefaultValue; } } set { + _hasBits0 |= 1; ctype_ = value; } } + /// Gets whether the "ctype" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasCtype { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "ctype" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearCtype() { + _hasBits0 &= ~1; + } /// Field number for the "packed" field. public const int PackedFieldNumber = 2; + private readonly static bool PackedDefaultValue = false; + private bool packed_; /// /// The packed option can be enabled for repeated primitive fields to enable @@ -3996,15 +6554,28 @@ public FieldOptions Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Packed { - get { return packed_; } + get { if ((_hasBits0 & 2) != 0) { return packed_; } else { return PackedDefaultValue; } } set { + _hasBits0 |= 2; packed_ = value; } } + /// Gets whether the "packed" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPacked { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "packed" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPacked() { + _hasBits0 &= ~2; + } /// Field number for the "jstype" field. public const int JstypeFieldNumber = 6; - private global::Google.Protobuf.Reflection.FieldOptions.Types.JSType jstype_ = 0; + private readonly static global::Google.Protobuf.Reflection.FieldOptions.Types.JSType JstypeDefaultValue = global::Google.Protobuf.Reflection.FieldOptions.Types.JSType.JsNormal; + + private global::Google.Protobuf.Reflection.FieldOptions.Types.JSType jstype_; /// /// The jstype option determines the JavaScript type used for values of the /// field. The option is permitted only for 64 bit integral and fixed types @@ -4020,14 +6591,27 @@ public bool Packed { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Google.Protobuf.Reflection.FieldOptions.Types.JSType Jstype { - get { return jstype_; } + get { if ((_hasBits0 & 16) != 0) { return jstype_; } else { return JstypeDefaultValue; } } set { + _hasBits0 |= 16; jstype_ = value; } } + /// Gets whether the "jstype" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasJstype { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "jstype" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearJstype() { + _hasBits0 &= ~16; + } /// Field number for the "lazy" field. public const int LazyFieldNumber = 5; + private readonly static bool LazyDefaultValue = false; + private bool lazy_; /// /// Should this field be parsed lazily? Lazy applies only to message-type @@ -4060,14 +6644,27 @@ public bool Packed { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Lazy { - get { return lazy_; } + get { if ((_hasBits0 & 8) != 0) { return lazy_; } else { return LazyDefaultValue; } } set { + _hasBits0 |= 8; lazy_ = value; } } + /// Gets whether the "lazy" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLazy { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "lazy" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLazy() { + _hasBits0 &= ~8; + } /// Field number for the "deprecated" field. public const int DeprecatedFieldNumber = 3; + private readonly static bool DeprecatedDefaultValue = false; + private bool deprecated_; /// /// Is this field deprecated? @@ -4077,25 +6674,49 @@ public bool Lazy { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Deprecated { - get { return deprecated_; } + get { if ((_hasBits0 & 4) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } } set { + _hasBits0 |= 4; deprecated_ = value; } } + /// Gets whether the "deprecated" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDeprecated { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "deprecated" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDeprecated() { + _hasBits0 &= ~4; + } /// Field number for the "weak" field. public const int WeakFieldNumber = 10; + private readonly static bool WeakDefaultValue = false; + private bool weak_; /// /// For Google-internal migration only. Do not use. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Weak { - get { return weak_; } + get { if ((_hasBits0 & 32) != 0) { return weak_; } else { return WeakDefaultValue; } } set { + _hasBits0 |= 32; weak_ = value; } } + /// Gets whether the "weak" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasWeak { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "weak" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearWeak() { + _hasBits0 &= ~32; + } /// Field number for the "uninterpreted_option" field. public const int UninterpretedOptionFieldNumber = 999; @@ -4130,19 +6751,28 @@ public bool Equals(FieldOptions other) { if (Deprecated != other.Deprecated) return false; if (Weak != other.Weak) return false; if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false; - return true; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Ctype != 0) hash ^= Ctype.GetHashCode(); - if (Packed != false) hash ^= Packed.GetHashCode(); - if (Jstype != 0) hash ^= Jstype.GetHashCode(); - if (Lazy != false) hash ^= Lazy.GetHashCode(); - if (Deprecated != false) hash ^= Deprecated.GetHashCode(); - if (Weak != false) hash ^= Weak.GetHashCode(); + if (HasCtype) hash ^= Ctype.GetHashCode(); + if (HasPacked) hash ^= Packed.GetHashCode(); + if (HasJstype) hash ^= Jstype.GetHashCode(); + if (HasLazy) hash ^= Lazy.GetHashCode(); + if (HasDeprecated) hash ^= Deprecated.GetHashCode(); + if (HasWeak) hash ^= Weak.GetHashCode(); hash ^= uninterpretedOption_.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -4153,55 +6783,108 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Ctype != 0) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasCtype) { output.WriteRawTag(8); output.WriteEnum((int) Ctype); } - if (Packed != false) { + if (HasPacked) { output.WriteRawTag(16); output.WriteBool(Packed); } - if (Deprecated != false) { + if (HasDeprecated) { output.WriteRawTag(24); output.WriteBool(Deprecated); } - if (Lazy != false) { + if (HasLazy) { output.WriteRawTag(40); output.WriteBool(Lazy); } - if (Jstype != 0) { + if (HasJstype) { output.WriteRawTag(48); output.WriteEnum((int) Jstype); } - if (Weak != false) { + if (HasWeak) { output.WriteRawTag(80); output.WriteBool(Weak); } uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasCtype) { + output.WriteRawTag(8); + output.WriteEnum((int) Ctype); + } + if (HasPacked) { + output.WriteRawTag(16); + output.WriteBool(Packed); + } + if (HasDeprecated) { + output.WriteRawTag(24); + output.WriteBool(Deprecated); + } + if (HasLazy) { + output.WriteRawTag(40); + output.WriteBool(Lazy); + } + if (HasJstype) { + output.WriteRawTag(48); + output.WriteEnum((int) Jstype); + } + if (HasWeak) { + output.WriteRawTag(80); + output.WriteBool(Weak); + } + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Ctype != 0) { + if (HasCtype) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Ctype); } - if (Packed != false) { + if (HasPacked) { size += 1 + 1; } - if (Jstype != 0) { + if (HasJstype) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Jstype); } - if (Lazy != false) { + if (HasLazy) { size += 1 + 1; } - if (Deprecated != false) { + if (HasDeprecated) { size += 1 + 1; } - if (Weak != false) { + if (HasWeak) { size += 1 + 1; } size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec); + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -4210,37 +6893,44 @@ public void MergeFrom(FieldOptions other) { if (other == null) { return; } - if (other.Ctype != 0) { + if (other.HasCtype) { Ctype = other.Ctype; } - if (other.Packed != false) { + if (other.HasPacked) { Packed = other.Packed; } - if (other.Jstype != 0) { + if (other.HasJstype) { Jstype = other.Jstype; } - if (other.Lazy != false) { + if (other.HasLazy) { Lazy = other.Lazy; } - if (other.Deprecated != false) { + if (other.HasDeprecated) { Deprecated = other.Deprecated; } - if (other.Weak != false) { + if (other.HasWeak) { Weak = other.Weak; } uninterpretedOption_.Add(other.uninterpretedOption_); + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } break; case 8: { - ctype_ = (global::Google.Protobuf.Reflection.FieldOptions.Types.CType) input.ReadEnum(); + Ctype = (global::Google.Protobuf.Reflection.FieldOptions.Types.CType) input.ReadEnum(); break; } case 16: { @@ -4256,7 +6946,7 @@ public void MergeFrom(pb::CodedInputStream input) { break; } case 48: { - jstype_ = (global::Google.Protobuf.Reflection.FieldOptions.Types.JSType) input.ReadEnum(); + Jstype = (global::Google.Protobuf.Reflection.FieldOptions.Types.JSType) input.ReadEnum(); break; } case 80: { @@ -4269,13 +6959,80 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + case 8: { + Ctype = (global::Google.Protobuf.Reflection.FieldOptions.Types.CType) input.ReadEnum(); + break; + } + case 16: { + Packed = input.ReadBool(); + break; + } + case 24: { + Deprecated = input.ReadBool(); + break; + } + case 40: { + Lazy = input.ReadBool(); + break; + } + case 48: { + Jstype = (global::Google.Protobuf.Reflection.FieldOptions.Types.JSType) input.ReadEnum(); + break; + } + case 80: { + Weak = input.ReadBool(); + break; + } + case 7994: { + uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec); + break; + } + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); } #region Nested types /// Container for nested types declared in the FieldOptions message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - internal enum CType { + public enum CType { /// /// Default mode. /// @@ -4284,7 +7041,7 @@ internal enum CType { [pbr::OriginalName("STRING_PIECE")] StringPiece = 2, } - internal enum JSType { + public enum JSType { /// /// Use the default type. /// @@ -4304,8 +7061,15 @@ internal enum JSType { } - internal sealed partial class OneofOptions : pb::IMessage { + public sealed partial class OneofOptions : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneofOptions()); + private pb::UnknownFieldSet _unknownFields; + internal pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -4319,8 +7083,6 @@ internal sealed partial class OneofOptions : pb::IMessage { get { return Descriptor; } } - internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public OneofOptions() { OnConstruction(); @@ -4331,6 +7093,8 @@ public OneofOptions() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public OneofOptions(OneofOptions other) : this() { uninterpretedOption_ = other.uninterpretedOption_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4365,13 +7129,22 @@ public bool Equals(OneofOptions other) { return true; } if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false; - return true; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= uninterpretedOption_.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -4382,13 +7155,42 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec); + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -4398,28 +7200,86 @@ public void MergeFrom(OneofOptions other) { return; } uninterpretedOption_.Add(other.uninterpretedOption_); + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } + break; + case 7994: { + uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec); + break; + } + } + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } break; case 7994: { - uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec); + uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec); break; } } } } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } } - internal sealed partial class EnumOptions : pb::IMessage { + public sealed partial class EnumOptions : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EnumOptions()); + private pb::UnknownFieldSet _unknownFields; + internal pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -4433,8 +7293,6 @@ internal sealed partial class EnumOptions : pb::IMessage { get { return Descriptor; } } - internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public EnumOptions() { OnConstruction(); @@ -4444,9 +7302,12 @@ public EnumOptions() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public EnumOptions(EnumOptions other) : this() { + _hasBits0 = other._hasBits0; allowAlias_ = other.allowAlias_; deprecated_ = other.deprecated_; uninterpretedOption_ = other.uninterpretedOption_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4456,6 +7317,8 @@ public EnumOptions Clone() { /// Field number for the "allow_alias" field. public const int AllowAliasFieldNumber = 2; + private readonly static bool AllowAliasDefaultValue = false; + private bool allowAlias_; /// /// Set this option to true to allow mapping different tag names to the same @@ -4463,14 +7326,27 @@ public EnumOptions Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool AllowAlias { - get { return allowAlias_; } + get { if ((_hasBits0 & 1) != 0) { return allowAlias_; } else { return AllowAliasDefaultValue; } } set { + _hasBits0 |= 1; allowAlias_ = value; } } + /// Gets whether the "allow_alias" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasAllowAlias { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "allow_alias" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearAllowAlias() { + _hasBits0 &= ~1; + } /// Field number for the "deprecated" field. public const int DeprecatedFieldNumber = 3; + private readonly static bool DeprecatedDefaultValue = false; + private bool deprecated_; /// /// Is this enum deprecated? @@ -4480,11 +7356,22 @@ public bool AllowAlias { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Deprecated { - get { return deprecated_; } + get { if ((_hasBits0 & 2) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } } set { + _hasBits0 |= 2; deprecated_ = value; } } + /// Gets whether the "deprecated" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDeprecated { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "deprecated" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDeprecated() { + _hasBits0 &= ~2; + } /// Field number for the "uninterpreted_option" field. public const int UninterpretedOptionFieldNumber = 999; @@ -4515,15 +7402,24 @@ public bool Equals(EnumOptions other) { if (AllowAlias != other.AllowAlias) return false; if (Deprecated != other.Deprecated) return false; if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false; - return true; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (AllowAlias != false) hash ^= AllowAlias.GetHashCode(); - if (Deprecated != false) hash ^= Deprecated.GetHashCode(); + if (HasAllowAlias) hash ^= AllowAlias.GetHashCode(); + if (HasDeprecated) hash ^= Deprecated.GetHashCode(); hash ^= uninterpretedOption_.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -4534,27 +7430,64 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (AllowAlias != false) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasAllowAlias) { output.WriteRawTag(16); output.WriteBool(AllowAlias); } - if (Deprecated != false) { + if (HasDeprecated) { output.WriteRawTag(24); output.WriteBool(Deprecated); } uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasAllowAlias) { + output.WriteRawTag(16); + output.WriteBool(AllowAlias); + } + if (HasDeprecated) { + output.WriteRawTag(24); + output.WriteBool(Deprecated); + } + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (AllowAlias != false) { + if (HasAllowAlias) { size += 1 + 1; } - if (Deprecated != false) { + if (HasDeprecated) { size += 1 + 1; } size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec); + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -4563,22 +7496,29 @@ public void MergeFrom(EnumOptions other) { if (other == null) { return; } - if (other.AllowAlias != false) { + if (other.HasAllowAlias) { AllowAlias = other.AllowAlias; } - if (other.Deprecated != false) { + if (other.HasDeprecated) { Deprecated = other.Deprecated; } uninterpretedOption_.Add(other.uninterpretedOption_); + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } break; case 16: { AllowAlias = input.ReadBool(); @@ -4594,12 +7534,71 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + case 16: { + AllowAlias = input.ReadBool(); + break; + } + case 24: { + Deprecated = input.ReadBool(); + break; + } + case 7994: { + uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec); + break; + } + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); } } - internal sealed partial class EnumValueOptions : pb::IMessage { + public sealed partial class EnumValueOptions : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EnumValueOptions()); + private pb::UnknownFieldSet _unknownFields; + internal pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -4613,8 +7612,6 @@ internal sealed partial class EnumValueOptions : pb::IMessage get { return Descriptor; } } - internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public EnumValueOptions() { OnConstruction(); @@ -4624,8 +7621,11 @@ public EnumValueOptions() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public EnumValueOptions(EnumValueOptions other) : this() { + _hasBits0 = other._hasBits0; deprecated_ = other.deprecated_; uninterpretedOption_ = other.uninterpretedOption_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4635,6 +7635,8 @@ public EnumValueOptions Clone() { /// Field number for the "deprecated" field. public const int DeprecatedFieldNumber = 1; + private readonly static bool DeprecatedDefaultValue = false; + private bool deprecated_; /// /// Is this enum value deprecated? @@ -4644,11 +7646,22 @@ public EnumValueOptions Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Deprecated { - get { return deprecated_; } + get { if ((_hasBits0 & 1) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } } set { + _hasBits0 |= 1; deprecated_ = value; } } + /// Gets whether the "deprecated" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDeprecated { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "deprecated" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDeprecated() { + _hasBits0 &= ~1; + } /// Field number for the "uninterpreted_option" field. public const int UninterpretedOptionFieldNumber = 999; @@ -4678,14 +7691,23 @@ public bool Equals(EnumValueOptions other) { } if (Deprecated != other.Deprecated) return false; if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false; - return true; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Deprecated != false) hash ^= Deprecated.GetHashCode(); + if (HasDeprecated) hash ^= Deprecated.GetHashCode(); hash ^= uninterpretedOption_.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -4696,20 +7718,53 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Deprecated != false) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasDeprecated) { output.WriteRawTag(8); output.WriteBool(Deprecated); } uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasDeprecated) { + output.WriteRawTag(8); + output.WriteBool(Deprecated); + } + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Deprecated != false) { + if (HasDeprecated) { size += 1 + 1; } size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec); + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -4718,19 +7773,26 @@ public void MergeFrom(EnumValueOptions other) { if (other == null) { return; } - if (other.Deprecated != false) { + if (other.HasDeprecated) { Deprecated = other.Deprecated; } uninterpretedOption_.Add(other.uninterpretedOption_); + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } break; case 8: { Deprecated = input.ReadBool(); @@ -4742,12 +7804,67 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + case 8: { + Deprecated = input.ReadBool(); + break; + } + case 7994: { + uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec); + break; + } + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); } } - internal sealed partial class ServiceOptions : pb::IMessage { + public sealed partial class ServiceOptions : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServiceOptions()); + private pb::UnknownFieldSet _unknownFields; + internal pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -4761,8 +7878,6 @@ internal sealed partial class ServiceOptions : pb::IMessage { get { return Descriptor; } } - internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServiceOptions() { OnConstruction(); @@ -4772,8 +7887,11 @@ public ServiceOptions() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServiceOptions(ServiceOptions other) : this() { + _hasBits0 = other._hasBits0; deprecated_ = other.deprecated_; uninterpretedOption_ = other.uninterpretedOption_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4783,6 +7901,8 @@ public ServiceOptions Clone() { /// Field number for the "deprecated" field. public const int DeprecatedFieldNumber = 33; + private readonly static bool DeprecatedDefaultValue = false; + private bool deprecated_; /// /// Is this service deprecated? @@ -4792,11 +7912,22 @@ public ServiceOptions Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Deprecated { - get { return deprecated_; } + get { if ((_hasBits0 & 1) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } } set { + _hasBits0 |= 1; deprecated_ = value; } } + /// Gets whether the "deprecated" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDeprecated { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "deprecated" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDeprecated() { + _hasBits0 &= ~1; + } /// Field number for the "uninterpreted_option" field. public const int UninterpretedOptionFieldNumber = 999; @@ -4826,14 +7957,23 @@ public bool Equals(ServiceOptions other) { } if (Deprecated != other.Deprecated) return false; if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false; - return true; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Deprecated != false) hash ^= Deprecated.GetHashCode(); + if (HasDeprecated) hash ^= Deprecated.GetHashCode(); hash ^= uninterpretedOption_.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -4844,20 +7984,53 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Deprecated != false) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasDeprecated) { output.WriteRawTag(136, 2); output.WriteBool(Deprecated); } uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasDeprecated) { + output.WriteRawTag(136, 2); + output.WriteBool(Deprecated); + } + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Deprecated != false) { + if (HasDeprecated) { size += 2 + 1; } size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec); + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -4866,19 +8039,26 @@ public void MergeFrom(ServiceOptions other) { if (other == null) { return; } - if (other.Deprecated != false) { + if (other.HasDeprecated) { Deprecated = other.Deprecated; } uninterpretedOption_.Add(other.uninterpretedOption_); + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } break; case 264: { Deprecated = input.ReadBool(); @@ -4890,12 +8070,67 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + case 264: { + Deprecated = input.ReadBool(); + break; + } + case 7994: { + uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec); + break; + } + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); } } - internal sealed partial class MethodOptions : pb::IMessage { + public sealed partial class MethodOptions : pb::IExtendableMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MethodOptions()); + private pb::UnknownFieldSet _unknownFields; + internal pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -4909,8 +8144,6 @@ internal sealed partial class MethodOptions : pb::IMessage { get { return Descriptor; } } - internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public MethodOptions() { OnConstruction(); @@ -4920,9 +8153,12 @@ public MethodOptions() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public MethodOptions(MethodOptions other) : this() { + _hasBits0 = other._hasBits0; deprecated_ = other.deprecated_; idempotencyLevel_ = other.idempotencyLevel_; uninterpretedOption_ = other.uninterpretedOption_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4932,6 +8168,8 @@ public MethodOptions Clone() { /// Field number for the "deprecated" field. public const int DeprecatedFieldNumber = 33; + private readonly static bool DeprecatedDefaultValue = false; + private bool deprecated_; /// /// Is this method deprecated? @@ -4941,22 +8179,46 @@ public MethodOptions Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Deprecated { - get { return deprecated_; } + get { if ((_hasBits0 & 1) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } } set { + _hasBits0 |= 1; deprecated_ = value; } } + /// Gets whether the "deprecated" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDeprecated { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "deprecated" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDeprecated() { + _hasBits0 &= ~1; + } /// Field number for the "idempotency_level" field. public const int IdempotencyLevelFieldNumber = 34; - private global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel idempotencyLevel_ = 0; + private readonly static global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel IdempotencyLevelDefaultValue = global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel.IdempotencyUnknown; + + private global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel idempotencyLevel_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel IdempotencyLevel { - get { return idempotencyLevel_; } + get { if ((_hasBits0 & 2) != 0) { return idempotencyLevel_; } else { return IdempotencyLevelDefaultValue; } } set { + _hasBits0 |= 2; idempotencyLevel_ = value; } } + /// Gets whether the "idempotency_level" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasIdempotencyLevel { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "idempotency_level" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearIdempotencyLevel() { + _hasBits0 &= ~2; + } /// Field number for the "uninterpreted_option" field. public const int UninterpretedOptionFieldNumber = 999; @@ -4987,15 +8249,24 @@ public bool Equals(MethodOptions other) { if (Deprecated != other.Deprecated) return false; if (IdempotencyLevel != other.IdempotencyLevel) return false; if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false; - return true; + if (!Equals(_extensions, other._extensions)) { + return false; + } + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Deprecated != false) hash ^= Deprecated.GetHashCode(); - if (IdempotencyLevel != 0) hash ^= IdempotencyLevel.GetHashCode(); + if (HasDeprecated) hash ^= Deprecated.GetHashCode(); + if (HasIdempotencyLevel) hash ^= IdempotencyLevel.GetHashCode(); hash ^= uninterpretedOption_.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -5006,27 +8277,64 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Deprecated != false) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasDeprecated) { output.WriteRawTag(136, 2); output.WriteBool(Deprecated); } - if (IdempotencyLevel != 0) { + if (HasIdempotencyLevel) { output.WriteRawTag(144, 2); output.WriteEnum((int) IdempotencyLevel); } uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasDeprecated) { + output.WriteRawTag(136, 2); + output.WriteBool(Deprecated); + } + if (HasIdempotencyLevel) { + output.WriteRawTag(144, 2); + output.WriteEnum((int) IdempotencyLevel); + } + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Deprecated != false) { + if (HasDeprecated) { size += 2 + 1; } - if (IdempotencyLevel != 0) { + if (HasIdempotencyLevel) { size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) IdempotencyLevel); } size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec); + if (_extensions != null) { + size += _extensions.CalculateSize(); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -5035,29 +8343,36 @@ public void MergeFrom(MethodOptions other) { if (other == null) { return; } - if (other.Deprecated != false) { + if (other.HasDeprecated) { Deprecated = other.Deprecated; } - if (other.IdempotencyLevel != 0) { + if (other.HasIdempotencyLevel) { IdempotencyLevel = other.IdempotencyLevel; } uninterpretedOption_.Add(other.uninterpretedOption_); + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } break; case 264: { Deprecated = input.ReadBool(); break; } case 272: { - idempotencyLevel_ = (global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel) input.ReadEnum(); + IdempotencyLevel = (global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel) input.ReadEnum(); break; } case 7994: { @@ -5066,6 +8381,57 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } + break; + case 264: { + Deprecated = input.ReadBool(); + break; + } + case 272: { + IdempotencyLevel = (global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel) input.ReadEnum(); + break; + } + case 7994: { + uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec); + break; + } + } + } + } + #endif + + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); } #region Nested types @@ -5077,7 +8443,7 @@ public static partial class Types { /// or neither? HTTP based RPC implementation may choose GET verb for safe /// methods, and PUT verb for idempotent methods instead of the default POST. /// - internal enum IdempotencyLevel { + public enum IdempotencyLevel { [pbr::OriginalName("IDEMPOTENCY_UNKNOWN")] IdempotencyUnknown = 0, /// /// implies idempotent @@ -5102,8 +8468,14 @@ internal enum IdempotencyLevel { /// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions /// in them. /// - internal sealed partial class UninterpretedOption : pb::IMessage { + public sealed partial class UninterpretedOption : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new UninterpretedOption()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -5126,6 +8498,7 @@ public UninterpretedOption() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public UninterpretedOption(UninterpretedOption other) : this() { + _hasBits0 = other._hasBits0; name_ = other.name_.Clone(); identifierValue_ = other.identifierValue_; positiveIntValue_ = other.positiveIntValue_; @@ -5133,6 +8506,7 @@ public UninterpretedOption(UninterpretedOption other) : this() { doubleValue_ = other.doubleValue_; stringValue_ = other.stringValue_; aggregateValue_ = other.aggregateValue_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -5152,73 +8526,148 @@ public UninterpretedOption Clone() { /// Field number for the "identifier_value" field. public const int IdentifierValueFieldNumber = 3; - private string identifierValue_ = ""; + private readonly static string IdentifierValueDefaultValue = ""; + + private string identifierValue_; /// /// The value of the uninterpreted option, in whatever type the tokenizer /// identified it as during parsing. Exactly one of these should be set. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string IdentifierValue { - get { return identifierValue_; } + get { return identifierValue_ ?? IdentifierValueDefaultValue; } set { identifierValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "identifier_value" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasIdentifierValue { + get { return identifierValue_ != null; } + } + /// Clears the value of the "identifier_value" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearIdentifierValue() { + identifierValue_ = null; + } /// Field number for the "positive_int_value" field. public const int PositiveIntValueFieldNumber = 4; + private readonly static ulong PositiveIntValueDefaultValue = 0UL; + private ulong positiveIntValue_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ulong PositiveIntValue { - get { return positiveIntValue_; } + get { if ((_hasBits0 & 1) != 0) { return positiveIntValue_; } else { return PositiveIntValueDefaultValue; } } set { + _hasBits0 |= 1; positiveIntValue_ = value; } } + /// Gets whether the "positive_int_value" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasPositiveIntValue { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "positive_int_value" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearPositiveIntValue() { + _hasBits0 &= ~1; + } /// Field number for the "negative_int_value" field. public const int NegativeIntValueFieldNumber = 5; + private readonly static long NegativeIntValueDefaultValue = 0L; + private long negativeIntValue_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public long NegativeIntValue { - get { return negativeIntValue_; } + get { if ((_hasBits0 & 2) != 0) { return negativeIntValue_; } else { return NegativeIntValueDefaultValue; } } set { + _hasBits0 |= 2; negativeIntValue_ = value; } } + /// Gets whether the "negative_int_value" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNegativeIntValue { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "negative_int_value" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNegativeIntValue() { + _hasBits0 &= ~2; + } /// Field number for the "double_value" field. public const int DoubleValueFieldNumber = 6; + private readonly static double DoubleValueDefaultValue = 0D; + private double doubleValue_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public double DoubleValue { - get { return doubleValue_; } + get { if ((_hasBits0 & 4) != 0) { return doubleValue_; } else { return DoubleValueDefaultValue; } } set { + _hasBits0 |= 4; doubleValue_ = value; } } + /// Gets whether the "double_value" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasDoubleValue { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "double_value" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearDoubleValue() { + _hasBits0 &= ~4; + } /// Field number for the "string_value" field. public const int StringValueFieldNumber = 7; - private pb::ByteString stringValue_ = pb::ByteString.Empty; + private readonly static pb::ByteString StringValueDefaultValue = pb::ByteString.Empty; + + private pb::ByteString stringValue_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public pb::ByteString StringValue { - get { return stringValue_; } + get { return stringValue_ ?? StringValueDefaultValue; } set { stringValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "string_value" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasStringValue { + get { return stringValue_ != null; } + } + /// Clears the value of the "string_value" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearStringValue() { + stringValue_ = null; + } /// Field number for the "aggregate_value" field. public const int AggregateValueFieldNumber = 8; - private string aggregateValue_ = ""; + private readonly static string AggregateValueDefaultValue = ""; + + private string aggregateValue_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string AggregateValue { - get { return aggregateValue_; } + get { return aggregateValue_ ?? AggregateValueDefaultValue; } set { aggregateValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "aggregate_value" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasAggregateValue { + get { return aggregateValue_ != null; } + } + /// Clears the value of the "aggregate_value" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearAggregateValue() { + aggregateValue_ = null; + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { @@ -5237,22 +8686,25 @@ public bool Equals(UninterpretedOption other) { if (IdentifierValue != other.IdentifierValue) return false; if (PositiveIntValue != other.PositiveIntValue) return false; if (NegativeIntValue != other.NegativeIntValue) return false; - if (DoubleValue != other.DoubleValue) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleValue, other.DoubleValue)) return false; if (StringValue != other.StringValue) return false; if (AggregateValue != other.AggregateValue) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= name_.GetHashCode(); - if (IdentifierValue.Length != 0) hash ^= IdentifierValue.GetHashCode(); - if (PositiveIntValue != 0UL) hash ^= PositiveIntValue.GetHashCode(); - if (NegativeIntValue != 0L) hash ^= NegativeIntValue.GetHashCode(); - if (DoubleValue != 0D) hash ^= DoubleValue.GetHashCode(); - if (StringValue.Length != 0) hash ^= StringValue.GetHashCode(); - if (AggregateValue.Length != 0) hash ^= AggregateValue.GetHashCode(); + if (HasIdentifierValue) hash ^= IdentifierValue.GetHashCode(); + if (HasPositiveIntValue) hash ^= PositiveIntValue.GetHashCode(); + if (HasNegativeIntValue) hash ^= NegativeIntValue.GetHashCode(); + if (HasDoubleValue) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleValue); + if (HasStringValue) hash ^= StringValue.GetHashCode(); + if (HasAggregateValue) hash ^= AggregateValue.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -5263,55 +8715,99 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else name_.WriteTo(output, _repeated_name_codec); - if (IdentifierValue.Length != 0) { + if (HasIdentifierValue) { + output.WriteRawTag(26); + output.WriteString(IdentifierValue); + } + if (HasPositiveIntValue) { + output.WriteRawTag(32); + output.WriteUInt64(PositiveIntValue); + } + if (HasNegativeIntValue) { + output.WriteRawTag(40); + output.WriteInt64(NegativeIntValue); + } + if (HasDoubleValue) { + output.WriteRawTag(49); + output.WriteDouble(DoubleValue); + } + if (HasStringValue) { + output.WriteRawTag(58); + output.WriteBytes(StringValue); + } + if (HasAggregateValue) { + output.WriteRawTag(66); + output.WriteString(AggregateValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + name_.WriteTo(ref output, _repeated_name_codec); + if (HasIdentifierValue) { output.WriteRawTag(26); output.WriteString(IdentifierValue); } - if (PositiveIntValue != 0UL) { + if (HasPositiveIntValue) { output.WriteRawTag(32); output.WriteUInt64(PositiveIntValue); } - if (NegativeIntValue != 0L) { + if (HasNegativeIntValue) { output.WriteRawTag(40); output.WriteInt64(NegativeIntValue); } - if (DoubleValue != 0D) { + if (HasDoubleValue) { output.WriteRawTag(49); output.WriteDouble(DoubleValue); } - if (StringValue.Length != 0) { + if (HasStringValue) { output.WriteRawTag(58); output.WriteBytes(StringValue); } - if (AggregateValue.Length != 0) { + if (HasAggregateValue) { output.WriteRawTag(66); output.WriteString(AggregateValue); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += name_.CalculateSize(_repeated_name_codec); - if (IdentifierValue.Length != 0) { + if (HasIdentifierValue) { size += 1 + pb::CodedOutputStream.ComputeStringSize(IdentifierValue); } - if (PositiveIntValue != 0UL) { + if (HasPositiveIntValue) { size += 1 + pb::CodedOutputStream.ComputeUInt64Size(PositiveIntValue); } - if (NegativeIntValue != 0L) { + if (HasNegativeIntValue) { size += 1 + pb::CodedOutputStream.ComputeInt64Size(NegativeIntValue); } - if (DoubleValue != 0D) { + if (HasDoubleValue) { size += 1 + 8; } - if (StringValue.Length != 0) { + if (HasStringValue) { size += 1 + pb::CodedOutputStream.ComputeBytesSize(StringValue); } - if (AggregateValue.Length != 0) { + if (HasAggregateValue) { size += 1 + pb::CodedOutputStream.ComputeStringSize(AggregateValue); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -5321,33 +8817,37 @@ public void MergeFrom(UninterpretedOption other) { return; } name_.Add(other.name_); - if (other.IdentifierValue.Length != 0) { + if (other.HasIdentifierValue) { IdentifierValue = other.IdentifierValue; } - if (other.PositiveIntValue != 0UL) { + if (other.HasPositiveIntValue) { PositiveIntValue = other.PositiveIntValue; } - if (other.NegativeIntValue != 0L) { + if (other.HasNegativeIntValue) { NegativeIntValue = other.NegativeIntValue; } - if (other.DoubleValue != 0D) { + if (other.HasDoubleValue) { DoubleValue = other.DoubleValue; } - if (other.StringValue.Length != 0) { + if (other.HasStringValue) { StringValue = other.StringValue; } - if (other.AggregateValue.Length != 0) { + if (other.HasAggregateValue) { AggregateValue = other.AggregateValue; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 18: { name_.AddEntriesFrom(input, _repeated_name_codec); @@ -5379,7 +8879,50 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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 18: { + name_.AddEntriesFrom(ref input, _repeated_name_codec); + break; + } + case 26: { + IdentifierValue = input.ReadString(); + break; + } + case 32: { + PositiveIntValue = input.ReadUInt64(); + break; + } + case 40: { + NegativeIntValue = input.ReadInt64(); + break; + } + case 49: { + DoubleValue = input.ReadDouble(); + break; + } + case 58: { + StringValue = input.ReadBytes(); + break; + } + case 66: { + AggregateValue = input.ReadString(); + break; + } + } + } } + #endif #region Nested types /// Container for nested types declared in the UninterpretedOption message type. @@ -5392,8 +8935,14 @@ public static partial class Types { /// E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents /// "foo.(bar.baz).qux". /// - internal sealed partial class NamePart : pb::IMessage { + public sealed partial class NamePart : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NamePart()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -5416,8 +8965,10 @@ public NamePart() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public NamePart(NamePart other) : this() { + _hasBits0 = other._hasBits0; namePart_ = other.namePart_; isExtension_ = other.isExtension_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -5427,25 +8978,50 @@ public NamePart Clone() { /// Field number for the "name_part" field. public const int NamePart_FieldNumber = 1; - private string namePart_ = ""; + private readonly static string NamePart_DefaultValue = ""; + + private string namePart_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string NamePart_ { - get { return namePart_; } + get { return namePart_ ?? NamePart_DefaultValue; } set { namePart_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "name_part" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasNamePart_ { + get { return namePart_ != null; } + } + /// Clears the value of the "name_part" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearNamePart_() { + namePart_ = null; + } /// Field number for the "is_extension" field. public const int IsExtensionFieldNumber = 2; + private readonly static bool IsExtensionDefaultValue = false; + private bool isExtension_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool IsExtension { - get { return isExtension_; } + get { if ((_hasBits0 & 1) != 0) { return isExtension_; } else { return IsExtensionDefaultValue; } } set { + _hasBits0 |= 1; isExtension_ = value; } } + /// Gets whether the "is_extension" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasIsExtension { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "is_extension" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearIsExtension() { + _hasBits0 &= ~1; + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { @@ -5462,14 +9038,17 @@ public bool Equals(NamePart other) { } if (NamePart_ != other.NamePart_) return false; if (IsExtension != other.IsExtension) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (NamePart_.Length != 0) hash ^= NamePart_.GetHashCode(); - if (IsExtension != false) hash ^= IsExtension.GetHashCode(); + if (HasNamePart_) hash ^= NamePart_.GetHashCode(); + if (HasIsExtension) hash ^= IsExtension.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -5480,25 +9059,52 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (NamePart_.Length != 0) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasNamePart_) { + output.WriteRawTag(10); + output.WriteString(NamePart_); + } + if (HasIsExtension) { + output.WriteRawTag(16); + output.WriteBool(IsExtension); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasNamePart_) { output.WriteRawTag(10); output.WriteString(NamePart_); } - if (IsExtension != false) { + if (HasIsExtension) { output.WriteRawTag(16); output.WriteBool(IsExtension); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (NamePart_.Length != 0) { + if (HasNamePart_) { size += 1 + pb::CodedOutputStream.ComputeStringSize(NamePart_); } - if (IsExtension != false) { + if (HasIsExtension) { size += 1 + 1; } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -5507,21 +9113,47 @@ public void MergeFrom(NamePart other) { if (other == null) { return; } - if (other.NamePart_.Length != 0) { + if (other.HasNamePart_) { NamePart_ = other.NamePart_; } - if (other.IsExtension != false) { + if (other.HasIsExtension) { IsExtension = other.IsExtension; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + NamePart_ = input.ReadString(); + break; + } + case 16: { + IsExtension = input.ReadBool(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { NamePart_ = input.ReadString(); @@ -5534,6 +9166,7 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } @@ -5546,8 +9179,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// Encapsulates information about the original source file from which a /// FileDescriptorProto was generated. /// - internal sealed partial class SourceCodeInfo : pb::IMessage { + public sealed partial class SourceCodeInfo : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SourceCodeInfo()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -5571,6 +9209,7 @@ public SourceCodeInfo() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SourceCodeInfo(SourceCodeInfo other) : this() { location_ = other.location_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -5621,7 +9260,7 @@ public SourceCodeInfo Clone() { /// beginning of the "extend" block and is shared by all extensions within /// the block. /// - Just because a location's span is a subset of some other location's span - /// does not mean that it is a descendent. For example, a "group" defines + /// does not mean that it is a descendant. For example, a "group" defines /// both a type and a field in a single declaration. Thus, the locations /// corresponding to the type and field and their components will overlap. /// - Code which tries to interpret locations should probably be designed to @@ -5647,13 +9286,16 @@ public bool Equals(SourceCodeInfo other) { return true; } if(!location_.Equals(other.location_)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= location_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -5664,13 +9306,33 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else location_.WriteTo(output, _repeated_location_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + location_.WriteTo(ref output, _repeated_location_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += location_.CalculateSize(_repeated_location_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -5680,15 +9342,19 @@ public void MergeFrom(SourceCodeInfo other) { return; } location_.Add(other.location_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { location_.AddEntriesFrom(input, _repeated_location_codec); @@ -5696,14 +9362,38 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + location_.AddEntriesFrom(ref input, _repeated_location_codec); + break; + } + } + } } + #endif #region Nested types /// Container for nested types declared in the SourceCodeInfo message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - internal sealed partial class Location : pb::IMessage { + public sealed partial class Location : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Location()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -5731,6 +9421,7 @@ public Location(Location other) : this() { leadingComments_ = other.leadingComments_; trailingComments_ = other.trailingComments_; leadingDetachedComments_ = other.leadingDetachedComments_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -5792,7 +9483,9 @@ public Location Clone() { /// Field number for the "leading_comments" field. public const int LeadingCommentsFieldNumber = 3; - private string leadingComments_ = ""; + private readonly static string LeadingCommentsDefaultValue = ""; + + private string leadingComments_; /// /// If this SourceCodeInfo represents a complete declaration, these are any /// comments appearing before and after the declaration which appear to be @@ -5844,22 +9537,44 @@ public Location Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string LeadingComments { - get { return leadingComments_; } + get { return leadingComments_ ?? LeadingCommentsDefaultValue; } set { leadingComments_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "leading_comments" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasLeadingComments { + get { return leadingComments_ != null; } + } + /// Clears the value of the "leading_comments" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearLeadingComments() { + leadingComments_ = null; + } /// Field number for the "trailing_comments" field. public const int TrailingCommentsFieldNumber = 4; - private string trailingComments_ = ""; + private readonly static string TrailingCommentsDefaultValue = ""; + + private string trailingComments_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string TrailingComments { - get { return trailingComments_; } + get { return trailingComments_ ?? TrailingCommentsDefaultValue; } set { trailingComments_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "trailing_comments" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasTrailingComments { + get { return trailingComments_ != null; } + } + /// Clears the value of the "trailing_comments" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearTrailingComments() { + trailingComments_ = null; + } /// Field number for the "leading_detached_comments" field. public const int LeadingDetachedCommentsFieldNumber = 6; @@ -5889,7 +9604,7 @@ public bool Equals(Location other) { if (LeadingComments != other.LeadingComments) return false; if (TrailingComments != other.TrailingComments) return false; if(!leadingDetachedComments_.Equals(other.leadingDetachedComments_)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -5897,9 +9612,12 @@ public override int GetHashCode() { int hash = 1; hash ^= path_.GetHashCode(); hash ^= span_.GetHashCode(); - if (LeadingComments.Length != 0) hash ^= LeadingComments.GetHashCode(); - if (TrailingComments.Length != 0) hash ^= TrailingComments.GetHashCode(); + if (HasLeadingComments) hash ^= LeadingComments.GetHashCode(); + if (HasTrailingComments) hash ^= TrailingComments.GetHashCode(); hash ^= leadingDetachedComments_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -5910,31 +9628,61 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else path_.WriteTo(output, _repeated_path_codec); span_.WriteTo(output, _repeated_span_codec); - if (LeadingComments.Length != 0) { + if (HasLeadingComments) { output.WriteRawTag(26); output.WriteString(LeadingComments); } - if (TrailingComments.Length != 0) { + if (HasTrailingComments) { output.WriteRawTag(34); output.WriteString(TrailingComments); } leadingDetachedComments_.WriteTo(output, _repeated_leadingDetachedComments_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + path_.WriteTo(ref output, _repeated_path_codec); + span_.WriteTo(ref output, _repeated_span_codec); + if (HasLeadingComments) { + output.WriteRawTag(26); + output.WriteString(LeadingComments); + } + if (HasTrailingComments) { + output.WriteRawTag(34); + output.WriteString(TrailingComments); + } + leadingDetachedComments_.WriteTo(ref output, _repeated_leadingDetachedComments_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += path_.CalculateSize(_repeated_path_codec); size += span_.CalculateSize(_repeated_span_codec); - if (LeadingComments.Length != 0) { + if (HasLeadingComments) { size += 1 + pb::CodedOutputStream.ComputeStringSize(LeadingComments); } - if (TrailingComments.Length != 0) { + if (HasTrailingComments) { size += 1 + pb::CodedOutputStream.ComputeStringSize(TrailingComments); } size += leadingDetachedComments_.CalculateSize(_repeated_leadingDetachedComments_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -5945,22 +9693,26 @@ public void MergeFrom(Location other) { } path_.Add(other.path_); span_.Add(other.span_); - if (other.LeadingComments.Length != 0) { + if (other.HasLeadingComments) { LeadingComments = other.LeadingComments; } - if (other.TrailingComments.Length != 0) { + if (other.HasTrailingComments) { TrailingComments = other.TrailingComments; } leadingDetachedComments_.Add(other.leadingDetachedComments_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: case 8: { @@ -5986,7 +9738,44 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: + case 8: { + path_.AddEntriesFrom(ref input, _repeated_path_codec); + break; + } + case 18: + case 16: { + span_.AddEntriesFrom(ref input, _repeated_span_codec); + break; + } + case 26: { + LeadingComments = input.ReadString(); + break; + } + case 34: { + TrailingComments = input.ReadString(); + break; + } + case 50: { + leadingDetachedComments_.AddEntriesFrom(ref input, _repeated_leadingDetachedComments_codec); + break; + } + } + } } + #endif } @@ -6000,8 +9789,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// file. A GeneratedCodeInfo message is associated with only one generated /// source file, but may contain references to different source .proto files. /// - internal sealed partial class GeneratedCodeInfo : pb::IMessage { + public sealed partial class GeneratedCodeInfo : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new GeneratedCodeInfo()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -6025,6 +9819,7 @@ public GeneratedCodeInfo() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public GeneratedCodeInfo(GeneratedCodeInfo other) : this() { annotation_ = other.annotation_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -6060,13 +9855,16 @@ public bool Equals(GeneratedCodeInfo other) { return true; } if(!annotation_.Equals(other.annotation_)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= annotation_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -6077,13 +9875,33 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else annotation_.WriteTo(output, _repeated_annotation_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + annotation_.WriteTo(ref output, _repeated_annotation_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += annotation_.CalculateSize(_repeated_annotation_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -6093,15 +9911,19 @@ public void MergeFrom(GeneratedCodeInfo other) { return; } annotation_.Add(other.annotation_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { annotation_.AddEntriesFrom(input, _repeated_annotation_codec); @@ -6109,14 +9931,39 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + annotation_.AddEntriesFrom(ref input, _repeated_annotation_codec); + break; + } + } + } } + #endif #region Nested types /// Container for nested types declared in the GeneratedCodeInfo message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - internal sealed partial class Annotation : pb::IMessage { + public sealed partial class Annotation : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Annotation()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -6139,10 +9986,12 @@ public Annotation() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Annotation(Annotation other) : this() { + _hasBits0 = other._hasBits0; path_ = other.path_.Clone(); sourceFile_ = other.sourceFile_; begin_ = other.begin_; end_ = other.end_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -6166,20 +10015,34 @@ public Annotation Clone() { /// Field number for the "source_file" field. public const int SourceFileFieldNumber = 2; - private string sourceFile_ = ""; + private readonly static string SourceFileDefaultValue = ""; + + private string sourceFile_; /// /// Identifies the filesystem path to the original source .proto. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string SourceFile { - get { return sourceFile_; } + get { return sourceFile_ ?? SourceFileDefaultValue; } set { sourceFile_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } + /// Gets whether the "source_file" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasSourceFile { + get { return sourceFile_ != null; } + } + /// Clears the value of the "source_file" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearSourceFile() { + sourceFile_ = null; + } /// Field number for the "begin" field. public const int BeginFieldNumber = 3; + private readonly static int BeginDefaultValue = 0; + private int begin_; /// /// Identifies the starting offset in bytes in the generated code @@ -6187,14 +10050,27 @@ public string SourceFile { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Begin { - get { return begin_; } + get { if ((_hasBits0 & 1) != 0) { return begin_; } else { return BeginDefaultValue; } } set { + _hasBits0 |= 1; begin_ = value; } } + /// Gets whether the "begin" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBegin { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "begin" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBegin() { + _hasBits0 &= ~1; + } /// Field number for the "end" field. public const int EndFieldNumber = 4; + private readonly static int EndDefaultValue = 0; + private int end_; /// /// Identifies the ending offset in bytes in the generated code that @@ -6203,11 +10079,22 @@ public int Begin { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int End { - get { return end_; } + get { if ((_hasBits0 & 2) != 0) { return end_; } else { return EndDefaultValue; } } set { + _hasBits0 |= 2; end_ = value; } } + /// Gets whether the "end" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasEnd { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "end" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearEnd() { + _hasBits0 &= ~2; + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { @@ -6226,16 +10113,19 @@ public bool Equals(Annotation other) { if (SourceFile != other.SourceFile) return false; if (Begin != other.Begin) return false; if (End != other.End) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= path_.GetHashCode(); - if (SourceFile.Length != 0) hash ^= SourceFile.GetHashCode(); - if (Begin != 0) hash ^= Begin.GetHashCode(); - if (End != 0) hash ^= End.GetHashCode(); + if (HasSourceFile) hash ^= SourceFile.GetHashCode(); + if (HasBegin) hash ^= Begin.GetHashCode(); + if (HasEnd) hash ^= End.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -6246,34 +10136,66 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else path_.WriteTo(output, _repeated_path_codec); - if (SourceFile.Length != 0) { + if (HasSourceFile) { + output.WriteRawTag(18); + output.WriteString(SourceFile); + } + if (HasBegin) { + output.WriteRawTag(24); + output.WriteInt32(Begin); + } + if (HasEnd) { + output.WriteRawTag(32); + output.WriteInt32(End); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + path_.WriteTo(ref output, _repeated_path_codec); + if (HasSourceFile) { output.WriteRawTag(18); output.WriteString(SourceFile); } - if (Begin != 0) { + if (HasBegin) { output.WriteRawTag(24); output.WriteInt32(Begin); } - if (End != 0) { + if (HasEnd) { output.WriteRawTag(32); output.WriteInt32(End); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += path_.CalculateSize(_repeated_path_codec); - if (SourceFile.Length != 0) { + if (HasSourceFile) { size += 1 + pb::CodedOutputStream.ComputeStringSize(SourceFile); } - if (Begin != 0) { + if (HasBegin) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Begin); } - if (End != 0) { + if (HasEnd) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(End); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -6283,24 +10205,28 @@ public void MergeFrom(Annotation other) { return; } path_.Add(other.path_); - if (other.SourceFile.Length != 0) { + if (other.HasSourceFile) { SourceFile = other.SourceFile; } - if (other.Begin != 0) { + if (other.HasBegin) { Begin = other.Begin; } - if (other.End != 0) { + if (other.HasEnd) { End = other.End; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: case 8: { @@ -6321,7 +10247,39 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: + case 8: { + path_.AddEntriesFrom(ref input, _repeated_path_codec); + break; + } + case 18: { + SourceFile = input.ReadString(); + break; + } + case 24: { + Begin = input.ReadInt32(); + break; + } + case 32: { + End = input.ReadInt32(); + break; + } + } + } } + #endif } diff --git a/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs b/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs index 194041a88942c..6befbf1c2b0ef 100644 --- a/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs +++ b/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs @@ -30,6 +30,8 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using System.Collections.Generic; + namespace Google.Protobuf.Reflection { /// @@ -37,29 +39,22 @@ namespace Google.Protobuf.Reflection /// public abstract class DescriptorBase : IDescriptor { - private readonly FileDescriptor file; - private readonly string fullName; - private readonly int index; - internal DescriptorBase(FileDescriptor file, string fullName, int index) { - this.file = file; - this.fullName = fullName; - this.index = index; + File = file; + FullName = fullName; + Index = index; } /// - /// The index of this descriptor within its parent descriptor. + /// The index of this descriptor within its parent descriptor. /// /// /// This returns the index of this descriptor within its parent, for /// this descriptor's type. (There can be duplicate values for different /// types, e.g. one enum type with index 0 and one message type with index 0.) /// - public int Index - { - get { return index; } - } + public int Index { get; } /// /// Returns the name of the entity (field, message etc) being described. @@ -69,17 +64,29 @@ public int Index /// /// The fully qualified name of the descriptor's target. /// - public string FullName - { - get { return fullName; } - } + public string FullName { get; } /// /// The file this descriptor was declared in. /// - public FileDescriptor File - { - get { return file; } - } + public FileDescriptor File { get; } + + /// + /// The declaration information about the descriptor, or null if no declaration information + /// is available for this descriptor. + /// + /// + /// This information is typically only available for dynamically loaded descriptors, + /// for example within a protoc plugin where the full descriptors, including source info, + /// are passed to the code by protoc. + /// + public DescriptorDeclaration Declaration => File.GetDeclaration(this); + + /// + /// Retrieves the list of nested descriptors corresponding to the given field number, if any. + /// If the field is unknown or not a nested descriptor list, return null to terminate the search. + /// The default implementation returns null. + /// + internal virtual IReadOnlyList GetNestedDescriptorListForField(int fieldNumber) => null; } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/DescriptorDeclaration.cs b/csharp/src/Google.Protobuf/Reflection/DescriptorDeclaration.cs new file mode 100644 index 0000000000000..b22048f0a8cb7 --- /dev/null +++ b/csharp/src/Google.Protobuf/Reflection/DescriptorDeclaration.cs @@ -0,0 +1,112 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2018 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using static Google.Protobuf.Reflection.SourceCodeInfo.Types; + +namespace Google.Protobuf.Reflection +{ + /// + /// Provides additional information about the declaration of a descriptor, + /// such as source location and comments. + /// + public sealed class DescriptorDeclaration + { + /// + /// The descriptor this declaration relates to. + /// + public IDescriptor Descriptor { get; } + + /// + /// The start line of the declaration within the source file. This value is 1-based. + /// + public int StartLine { get; } + /// + /// The start column of the declaration within the source file. This value is 1-based. + /// + public int StartColumn { get; } + + /// + /// // The end line of the declaration within the source file. This value is 1-based. + /// + public int EndLine { get; } + /// + /// The end column of the declaration within the source file. This value is 1-based, and + /// exclusive. (The final character of the declaration is on the column before this value.) + /// + public int EndColumn { get; } + + /// + /// Comments appearing before the declaration. Never null, but may be empty. Multi-line comments + /// are represented as a newline-separated string. Leading whitespace and the comment marker ("//") + /// are removed from each line. + /// + public string LeadingComments { get; } + + /// + /// Comments appearing after the declaration. Never null, but may be empty. Multi-line comments + /// are represented as a newline-separated string. Leading whitespace and the comment marker ("//") + /// are removed from each line. + /// + public string TrailingComments { get; } + + /// + /// Comments appearing before the declaration, but separated from it by blank + /// lines. Each string represents a newline-separated paragraph of comments. + /// Leading whitespace and the comment marker ("//") are removed from each line. + /// The list is never null, but may be empty. Likewise each element is never null, but may be empty. + /// + public IReadOnlyList LeadingDetachedComments { get; } + + private DescriptorDeclaration(IDescriptor descriptor, Location location) + { + // TODO: Validation + Descriptor = descriptor; + bool hasEndLine = location.Span.Count == 4; + // Lines and columns are 0-based in the proto. + StartLine = location.Span[0] + 1; + StartColumn = location.Span[1] + 1; + EndLine = hasEndLine ? location.Span[2] + 1 : StartLine; + EndColumn = location.Span[hasEndLine ? 3 : 2] + 1; + LeadingComments = location.LeadingComments; + TrailingComments = location.TrailingComments; + LeadingDetachedComments = new ReadOnlyCollection(location.LeadingDetachedComments.ToList()); + } + + internal static DescriptorDeclaration FromProto(IDescriptor descriptor, Location location) => + new DescriptorDeclaration(descriptor, location); + } +} diff --git a/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs b/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs index 99ca4bf34f141..93f2fa9a4aef8 100644 --- a/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs +++ b/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs @@ -45,21 +45,21 @@ internal sealed class DescriptorPool private readonly IDictionary descriptorsByName = new Dictionary(); - private readonly IDictionary fieldsByNumber = - new Dictionary(); + private readonly IDictionary, FieldDescriptor> fieldsByNumber = + new Dictionary, FieldDescriptor>(); - private readonly IDictionary enumValuesByNumber = - new Dictionary(); + private readonly IDictionary, EnumValueDescriptor> enumValuesByNumber = + new Dictionary, EnumValueDescriptor>(); private readonly HashSet dependencies; - internal DescriptorPool(FileDescriptor[] dependencyFiles) + internal DescriptorPool(IEnumerable dependencyFiles) { dependencies = new HashSet(); - for (int i = 0; i < dependencyFiles.Length; i++) + foreach (var dependencyFile in dependencyFiles) { - dependencies.Add(dependencyFiles[i]); - ImportPublicDependencies(dependencyFiles[i]); + dependencies.Add(dependencyFile); + ImportPublicDependencies(dependencyFile); } foreach (FileDescriptor dependency in dependencyFiles) @@ -209,14 +209,14 @@ private static void ValidateSymbolName(IDescriptor descriptor) internal FieldDescriptor FindFieldByNumber(MessageDescriptor messageDescriptor, int number) { FieldDescriptor ret; - fieldsByNumber.TryGetValue(new DescriptorIntPair(messageDescriptor, number), out ret); + fieldsByNumber.TryGetValue(new ObjectIntPair(messageDescriptor, number), out ret); return ret; } internal EnumValueDescriptor FindEnumValueByNumber(EnumDescriptor enumDescriptor, int number) { EnumValueDescriptor ret; - enumValuesByNumber.TryGetValue(new DescriptorIntPair(enumDescriptor, number), out ret); + enumValuesByNumber.TryGetValue(new ObjectIntPair(enumDescriptor, number), out ret); return ret; } @@ -227,7 +227,8 @@ internal EnumValueDescriptor FindEnumValueByNumber(EnumDescriptor enumDescriptor /// containing type and number already exists. internal void AddFieldByNumber(FieldDescriptor field) { - DescriptorIntPair key = new DescriptorIntPair(field.ContainingType, field.FieldNumber); + // for extensions, we use the extended type, otherwise we use the containing type + ObjectIntPair key = new ObjectIntPair(field.Proto.HasExtendee ? field.ExtendeeType : field.ContainingType, field.FieldNumber); FieldDescriptor old; if (fieldsByNumber.TryGetValue(key, out old)) { @@ -246,7 +247,7 @@ internal void AddFieldByNumber(FieldDescriptor field) /// internal void AddEnumValueByNumber(EnumValueDescriptor enumValue) { - DescriptorIntPair key = new DescriptorIntPair(enumValue.EnumDescriptor, enumValue.Number); + ObjectIntPair key = new ObjectIntPair(enumValue.EnumDescriptor, enumValue.Number); if (!enumValuesByNumber.ContainsKey(key)) { enumValuesByNumber[key] = enumValue; @@ -329,40 +330,5 @@ internal IDescriptor LookupSymbol(string name, IDescriptor relativeTo) return result; } } - - /// - /// Struct used to hold the keys for the fieldByNumber table. - /// - private struct DescriptorIntPair : IEquatable - { - private readonly int number; - private readonly IDescriptor descriptor; - - internal DescriptorIntPair(IDescriptor descriptor, int number) - { - this.number = number; - this.descriptor = descriptor; - } - - public bool Equals(DescriptorIntPair other) - { - return descriptor == other.descriptor - && number == other.number; - } - - public override bool Equals(object obj) - { - if (obj is DescriptorIntPair) - { - return Equals((DescriptorIntPair) obj); - } - return false; - } - - public override int GetHashCode() - { - return descriptor.GetHashCode()*((1 << 16) - 1) + number; - } - } } } \ 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 89c73a61b2a85..f7e8b5b5f28db 100644 --- a/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs @@ -30,6 +30,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Collections; using System; using System.Collections.Generic; @@ -72,6 +73,17 @@ internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageD /// public override string Name { get { return proto.Name; } } + internal override IReadOnlyList GetNestedDescriptorListForField(int fieldNumber) + { + switch (fieldNumber) + { + case EnumDescriptorProto.ValueFieldNumber: + return (IReadOnlyList) Values; + default: + return null; + } + } + /// /// The CLR type for this enum. For generated code, this will be a CLR enum type. /// @@ -116,6 +128,34 @@ public EnumValueDescriptor FindValueByName(string name) /// /// The (possibly empty) set of custom options for this enum. /// - public CustomOptions CustomOptions => Proto.Options?.CustomOptions ?? CustomOptions.Empty; + [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")] + public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber); + + /// + /// The EnumOptions, defined in descriptor.proto. + /// If the options message is not present (i.e. there are no options), null is returned. + /// Custom options can be retrieved as extensions of the returned message. + /// NOTE: A defensive copy is created each time this property is retrieved. + /// + public EnumOptions GetOptions() => Proto.Options?.Clone(); + + /// + /// Gets a single value enum option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public T GetOption(Extension extension) + { + var value = Proto.Options.GetExtension(extension); + return value is IDeepCloneable ? (value as IDeepCloneable).Clone() : value; + } + + /// + /// Gets a repeated value enum option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public RepeatedField GetOption(RepeatedExtension extension) + { + return Proto.Options.GetExtension(extension).Clone(); + } } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs index 8b838c68f0be9..05097bd1da3d7 100644 --- a/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs @@ -30,12 +30,15 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Collections; +using System; + namespace Google.Protobuf.Reflection { /// /// Descriptor for a single enum value within an enum in a .proto file. /// - public sealed class EnumValueDescriptor : DescriptorBase + public sealed class EnumValueDescriptor : DescriptorBase { private readonly EnumDescriptor enumDescriptor; private readonly EnumValueDescriptorProto proto; @@ -70,6 +73,35 @@ internal EnumValueDescriptor(EnumValueDescriptorProto proto, FileDescriptor file /// /// The (possibly empty) set of custom options for this enum value. /// - public CustomOptions CustomOptions => Proto.Options?.CustomOptions ?? CustomOptions.Empty; + [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")] + public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber); + + /// + /// The EnumValueOptions, defined in descriptor.proto. + /// If the options message is not present (i.e. there are no options), null is returned. + /// Custom options can be retrieved as extensions of the returned message. + /// NOTE: A defensive copy is created each time this property is retrieved. + /// + public EnumValueOptions GetOptions() => Proto.Options?.Clone(); + + /// + /// Gets a single value enum value option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public T GetOption(Extension extension) + { + var value = Proto.Options.GetExtension(extension); + return value is IDeepCloneable ? (value as IDeepCloneable).Clone() : value; + } + + /// + /// Gets a repeated value enum value option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public RepeatedField GetOption(RepeatedExtension extension) + { + return Proto.Options.GetExtension(extension).Clone(); + } } -} \ No newline at end of file +} + \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/ExtensionAccessor.cs b/csharp/src/Google.Protobuf/Reflection/ExtensionAccessor.cs new file mode 100644 index 0000000000000..81d6e35f01328 --- /dev/null +++ b/csharp/src/Google.Protobuf/Reflection/ExtensionAccessor.cs @@ -0,0 +1,69 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +namespace Google.Protobuf.Reflection +{ + internal sealed class ExtensionAccessor : IFieldAccessor + { + private readonly Extension extension; + private readonly ReflectionUtil.IExtensionReflectionHelper helper; + + internal ExtensionAccessor(FieldDescriptor descriptor) + { + Descriptor = descriptor; + extension = descriptor.Extension; + helper = ReflectionUtil.CreateExtensionHelper(extension); + } + + public FieldDescriptor Descriptor { get; } + + public void Clear(IMessage message) + { + helper.ClearExtension(message); + } + + public bool HasValue(IMessage message) + { + return helper.HasExtension(message); + } + + public object GetValue(IMessage message) + { + return helper.GetExtension(message); + } + + public void SetValue(IMessage message, object value) + { + helper.SetExtension(message, value); + } + } +} diff --git a/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs b/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs new file mode 100644 index 0000000000000..9664559df2490 --- /dev/null +++ b/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs @@ -0,0 +1,126 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace Google.Protobuf.Reflection +{ + /// + /// A collection to simplify retrieving the descriptors of extensions in a descriptor for a message + /// + public sealed class ExtensionCollection + { + private IDictionary> extensionsByTypeInDeclarationOrder; + private IDictionary> extensionsByTypeInNumberOrder; + + internal ExtensionCollection(FileDescriptor file, Extension[] extensions) + { + UnorderedExtensions = DescriptorUtil.ConvertAndMakeReadOnly( + file.Proto.Extension, + (extension, i) => { + if (extensions?.Length != 0) + { + return new FieldDescriptor(extension, file, null, i, null, extensions?[i]); + } + else + { + return new FieldDescriptor(extension, file, null, i, null, null); // return null if there's no extensions in this array for old code-gen + } + }); + } + + internal ExtensionCollection(MessageDescriptor message, Extension[] extensions) + { + UnorderedExtensions = DescriptorUtil.ConvertAndMakeReadOnly( + message.Proto.Extension, + (extension, i) => { + if (extensions?.Length != 0) + { + return new FieldDescriptor(extension, message.File, message, i, null, extensions?[i]); + } + else + { + return new FieldDescriptor(extension, message.File, message, i, null, null); + } + }); + } + + /// + /// Returns a readonly list of all the extensions defined in this type in + /// the order they were defined in the source .proto file + /// + public IList UnorderedExtensions { get; } + + /// + /// Returns a readonly list of all the extensions define in this type that extend + /// the provided descriptor type in the order they were defined in the source .proto file + /// + public IList GetExtensionsInDeclarationOrder(MessageDescriptor descriptor) + { + return extensionsByTypeInDeclarationOrder[descriptor]; + } + + /// + /// Returns a readonly list of all the extensions define in this type that extend + /// the provided descriptor type in accending field order + /// + public IList GetExtensionsInNumberOrder(MessageDescriptor descriptor) + { + return extensionsByTypeInNumberOrder[descriptor]; + } + + internal void CrossLink() + { + Dictionary> declarationOrder = new Dictionary>(); + foreach (FieldDescriptor descriptor in UnorderedExtensions) + { + descriptor.CrossLink(); + + IList list; + if (!declarationOrder.TryGetValue(descriptor.ExtendeeType, out list)) + { + list = new List(); + declarationOrder.Add(descriptor.ExtendeeType, list); + } + + list.Add(descriptor); + } + + extensionsByTypeInDeclarationOrder = declarationOrder + .ToDictionary(kvp => kvp.Key, kvp => (IList)new ReadOnlyCollection(kvp.Value)); + extensionsByTypeInNumberOrder = declarationOrder + .ToDictionary(kvp => kvp.Key, kvp => (IList)new ReadOnlyCollection(kvp.Value.OrderBy(field => field.FieldNumber).ToArray())); + } + } +} diff --git a/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs b/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs index 82ce50518d8e9..85b7d39a8337a 100644 --- a/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs +++ b/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs @@ -57,6 +57,7 @@ public object GetValue(IMessage message) return getValueDelegate(message); } + public abstract bool HasValue(IMessage message); public abstract void Clear(IMessage message); public abstract void SetValue(IMessage message, object value); } diff --git a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs index 2a3d5c7a2dbab..7324e3dfc6381 100644 --- a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs @@ -30,6 +30,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Collections; using Google.Protobuf.Compatibility; using System; @@ -41,13 +42,14 @@ namespace Google.Protobuf.Reflection public sealed class FieldDescriptor : DescriptorBase, IComparable { private EnumDescriptor enumType; + private MessageDescriptor extendeeType; private MessageDescriptor messageType; private FieldType fieldType; private readonly string propertyName; // Annoyingly, needed in Crosslink. private IFieldAccessor accessor; /// - /// Get the field's containing message type. + /// Get the field's containing message type, or null if it is a field defined at the top level of a file as an extension. /// public MessageDescriptor ContainingType { get; } @@ -56,16 +58,42 @@ public sealed class FieldDescriptor : DescriptorBase, IComparable public OneofDescriptor ContainingOneof { get; } + /// + /// Returns the oneof containing this field if it's a "real" oneof, or null if either this + /// field is not part of a oneof, or the oneof is synthetic. + /// + public OneofDescriptor RealContainingOneof => ContainingOneof?.IsSynthetic == false ? ContainingOneof : null; + /// /// The effective JSON name for this field. This is usually the lower-camel-cased form of the field name, /// but can be overridden using the json_name option in the .proto file. /// public string JsonName { get; } + /// + /// Indicates whether this field supports presence, either implicitly (e.g. due to it being a message + /// type field) or explicitly via Has/Clear members. If this returns true, it is safe to call + /// and + /// on this field's accessor with a suitable message. + /// + public bool HasPresence => + Extension != null ? !Extension.IsRepeated + : IsRepeated ? false + : IsMap ? false + : FieldType == FieldType.Message ? true + // This covers "real oneof members" and "proto3 optional fields" + : ContainingOneof != null ? true + : File.Syntax == Syntax.Proto2; + internal FieldDescriptorProto Proto { get; } + /// + /// An extension identifier for this field, or null if this field isn't an extension. + /// + public Extension Extension { get; } + internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file, - MessageDescriptor parent, int index, string propertyName) + MessageDescriptor parent, int index, string propertyName, Extension extension) : base(file, file.ComputeFullName(parent, proto.Name), index) { Proto = proto; @@ -79,8 +107,7 @@ internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file, throw new DescriptorValidationException(this, "Field numbers must be positive integers."); } ContainingType = parent; - // OneofIndex "defaults" to -1 due to a hack in FieldDescriptor.OnConstruction. - if (proto.OneofIndex != -1) + if (proto.HasOneofIndex) { if (proto.OneofIndex < 0 || proto.OneofIndex >= parent.Proto.OneofDecl.Count) { @@ -97,9 +124,10 @@ internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file, // We could trust the generated code and check whether the type of the property is // a MapField, but that feels a tad nasty. this.propertyName = propertyName; + Extension = extension; JsonName = Proto.JsonName == "" ? JsonFormatter.ToJsonName(Proto.Name) : Proto.JsonName; } - + /// /// The brief name of the descriptor's target. @@ -116,16 +144,21 @@ internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file, /// that is the responsibility of the accessor. /// /// - /// The value returned by this property will be non-null for all regular fields. However, - /// if a message containing a map field is introspected, the list of nested messages will include + /// In descriptors for generated code, the value returned by this property will be non-null for all + /// regular fields. However, if a message containing a map field is introspected, the list of nested messages will include /// an auto-generated nested key/value pair message for the field. This is not represented in any /// generated type, and the value of the map field itself is represented by a dictionary in the /// reflection API. There are never instances of those "hidden" messages, so no accessor is provided /// and this property will return null. /// + /// + /// In dynamically loaded descriptors, the value returned by this property will current be null; + /// if and when dynamic messages are supported, it will return a suitable accessor to work with + /// them. + /// /// public IFieldAccessor Accessor => accessor; - + /// /// Maps a field type as included in the .proto file to a FieldType. /// @@ -179,6 +212,11 @@ private static FieldType GetFieldTypeFromProtoType(FieldDescriptorProto.Types.Ty /// public bool IsRepeated => Proto.Label == FieldDescriptorProto.Types.Label.Repeated; + /// + /// Returns true if this field is a required field; false otherwise. + /// + public bool IsRequired => Proto.Label == FieldDescriptorProto.Types.Label.Required; + /// /// Returns true if this field is a map field; false otherwise. /// @@ -187,13 +225,26 @@ private static FieldType GetFieldTypeFromProtoType(FieldDescriptorProto.Types.Ty /// /// Returns true if this field is a packed, repeated field; false otherwise. /// - public bool IsPacked => - // Note the || rather than && here - we're effectively defaulting to packed, because that *is* - // the default in proto3, which is all we support. We may give the wrong result for the protos - // within descriptor.proto, but that's okay, as they're never exposed and we don't use IsPacked - // within the runtime. - Proto.Options == null || Proto.Options.Packed; - + public bool IsPacked + { + get + { + if (File.Syntax != Syntax.Proto3) + { + return Proto.Options?.Packed ?? false; + } + else + { + return !Proto.Options.HasPacked || Proto.Options.Packed; + } + } + } + + /// + /// Returns true if this field extends another message type; false otherwise. + /// + public bool IsExtension => Proto.HasExtendee; + /// /// Returns the type of the field. /// @@ -242,30 +293,73 @@ public MessageDescriptor MessageType { get { - if (fieldType != FieldType.Message) + if (fieldType != FieldType.Message && fieldType != FieldType.Group) { - throw new InvalidOperationException("MessageType is only valid for message fields."); + throw new InvalidOperationException("MessageType is only valid for message or group fields."); } return messageType; } } + /// + /// For extension fields, returns the extended type + /// + public MessageDescriptor ExtendeeType + { + get + { + if (!Proto.HasExtendee) + { + throw new InvalidOperationException("ExtendeeType is only valid for extension fields."); + } + return extendeeType; + } + } + /// /// The (possibly empty) set of custom options for this field. /// - public CustomOptions CustomOptions => Proto.Options?.CustomOptions ?? CustomOptions.Empty; + [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")] + public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber); + + /// + /// The FieldOptions, defined in descriptor.proto. + /// If the options message is not present (i.e. there are no options), null is returned. + /// Custom options can be retrieved as extensions of the returned message. + /// NOTE: A defensive copy is created each time this property is retrieved. + /// + public FieldOptions GetOptions() => Proto.Options?.Clone(); + + /// + /// Gets a single value field option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public T GetOption(Extension extension) + { + var value = Proto.Options.GetExtension(extension); + return value is IDeepCloneable ? (value as IDeepCloneable).Clone() : value; + } + + /// + /// Gets a repeated value field option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public RepeatedField GetOption(RepeatedExtension extension) + { + return Proto.Options.GetExtension(extension).Clone(); + } /// /// Look up and cross-link all field types etc. /// internal void CrossLink() { - if (Proto.TypeName != "") + if (Proto.HasTypeName) { IDescriptor typeDescriptor = File.DescriptorPool.LookupSymbol(Proto.TypeName, this); - if (Proto.Type != 0) + if (Proto.HasType) { // Choose field type based on symbol. if (typeDescriptor is MessageDescriptor) @@ -282,7 +376,7 @@ internal void CrossLink() } } - if (fieldType == FieldType.Message) + if (fieldType == FieldType.Message || fieldType == FieldType.Group) { if (!(typeDescriptor is MessageDescriptor)) { @@ -290,7 +384,7 @@ internal void CrossLink() } messageType = (MessageDescriptor) typeDescriptor; - if (Proto.DefaultValue != "") + if (Proto.HasDefaultValue) { throw new DescriptorValidationException(this, "Messages can't have default values."); } @@ -316,6 +410,11 @@ internal void CrossLink() } } + if (Proto.HasExtendee) + { + extendeeType = File.DescriptorPool.LookupSymbol(Proto.Extendee, this) as MessageDescriptor; + } + // Note: no attempt to perform any default value parsing File.DescriptorPool.AddFieldByNumber(this); @@ -329,12 +428,19 @@ internal void CrossLink() private IFieldAccessor CreateAccessor() { + if (Extension != null) + { + return new ExtensionAccessor(this); + } + // If we're given no property name, that's because we really don't want an accessor. - // (At the moment, that means it's a map entry message...) + // This could be because it's a map message, or it could be that we're loading a FileDescriptor dynamically. + // TODO: Support dynamic messages. if (propertyName == null) { return null; } + var property = ContainingType.ClrType.GetProperty(propertyName); if (property == null) { @@ -345,4 +451,5 @@ private IFieldAccessor CreateAccessor() : (IFieldAccessor) new SingleFieldAccessor(property, this); } } -} \ No newline at end of file +} + \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/FieldType.cs b/csharp/src/Google.Protobuf/Reflection/FieldType.cs index 1658e34cd1e16..37af17915ee7e 100644 --- a/csharp/src/Google.Protobuf/Reflection/FieldType.cs +++ b/csharp/src/Google.Protobuf/Reflection/FieldType.cs @@ -74,7 +74,7 @@ public enum FieldType /// String, /// - /// The field type used for groups (not supported in this implementation). + /// The field type used for groups. /// Group, /// diff --git a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs index 9124beee04c9e..724bb3a04dad3 100644 --- a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs @@ -30,12 +30,37 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Collections; +using Google.Protobuf.WellKnownTypes; using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using static Google.Protobuf.Reflection.SourceCodeInfo.Types; namespace Google.Protobuf.Reflection { + /// + /// The syntax of a .proto file + /// + public enum Syntax + { + /// + /// Proto2 syntax + /// + Proto2, + /// + /// Proto3 syntax + /// + Proto3, + /// + /// An unknown declared syntax + /// + Unknown + } + /// /// Describes a .proto file, including everything defined within. /// IDescriptor is implemented such that the File property returns this descriptor, @@ -43,12 +68,24 @@ namespace Google.Protobuf.Reflection /// public sealed class FileDescriptor : IDescriptor { - private FileDescriptor(ByteString descriptorData, FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool, bool allowUnknownDependencies, GeneratedClrTypeInfo generatedCodeInfo) + // Prevent linker failures when using IL2CPP with the well-known types. + static FileDescriptor() + { + ForceReflectionInitialization(); + ForceReflectionInitialization(); + ForceReflectionInitialization(); + ForceReflectionInitialization(); + ForceReflectionInitialization(); + } + + private readonly Lazy> declarations; + + private FileDescriptor(ByteString descriptorData, FileDescriptorProto proto, IEnumerable dependencies, DescriptorPool pool, bool allowUnknownDependencies, GeneratedClrTypeInfo generatedCodeInfo) { SerializedData = descriptorData; DescriptorPool = pool; Proto = proto; - Dependencies = new ReadOnlyCollection((FileDescriptor[]) dependencies.Clone()); + Dependencies = new ReadOnlyCollection(dependencies.ToList()); PublicDependencies = DeterminePublicDependencies(this, proto, dependencies, allowUnknownDependencies); @@ -56,15 +93,106 @@ private FileDescriptor(ByteString descriptorData, FileDescriptorProto proto, Fil MessageTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.MessageType, (message, index) => - new MessageDescriptor(message, this, null, index, generatedCodeInfo.NestedTypes[index])); + new MessageDescriptor(message, this, null, index, generatedCodeInfo?.NestedTypes[index])); EnumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType, (enumType, index) => - new EnumDescriptor(enumType, this, null, index, generatedCodeInfo.NestedEnums[index])); + new EnumDescriptor(enumType, this, null, index, generatedCodeInfo?.NestedEnums[index])); Services = DescriptorUtil.ConvertAndMakeReadOnly(proto.Service, (service, index) => new ServiceDescriptor(service, this, index)); + + Extensions = new ExtensionCollection(this, generatedCodeInfo?.Extensions); + + declarations = new Lazy>(CreateDeclarationMap, LazyThreadSafetyMode.ExecutionAndPublication); + + if (!proto.HasSyntax || proto.Syntax == "proto2") + { + Syntax = Syntax.Proto2; + } + else if (proto.Syntax == "proto3") + { + Syntax = Syntax.Proto3; + } + else + { + Syntax = Syntax.Unknown; + } + } + + private Dictionary CreateDeclarationMap() + { + var dictionary = new Dictionary(); + foreach (var location in Proto.SourceCodeInfo?.Location ?? Enumerable.Empty()) + { + var descriptor = FindDescriptorForPath(location.Path); + if (descriptor != null) + { + dictionary[descriptor] = DescriptorDeclaration.FromProto(descriptor, location); + } + } + return dictionary; + } + + private IDescriptor FindDescriptorForPath(IList path) + { + // All complete declarations have an even, non-empty path length + // (There can be an empty path for a descriptor declaration, but that can't have any comments, + // so we currently ignore it.) + if (path.Count == 0 || (path.Count & 1) != 0) + { + return null; + } + IReadOnlyList topLevelList = GetNestedDescriptorListForField(path[0]); + DescriptorBase current = GetDescriptorFromList(topLevelList, path[1]); + + for (int i = 2; current != null && i < path.Count; i += 2) + { + var list = current.GetNestedDescriptorListForField(path[i]); + current = GetDescriptorFromList(list, path[i + 1]); + } + return current; + } + + private DescriptorBase GetDescriptorFromList(IReadOnlyList list, int index) + { + // This is fine: it may be a newer version of protobuf than we understand, with a new descriptor + // field. + if (list == null) + { + return null; + } + // We *could* return null to silently continue, but this is basically data corruption. + if (index < 0 || index >= list.Count) + { + // We don't have much extra information to give at this point unfortunately. If this becomes a problem, + // we can pass in the complete path and report that and the file name. + throw new InvalidProtocolBufferException($"Invalid descriptor location path: index out of range"); + } + return list[index]; + } + + private IReadOnlyList GetNestedDescriptorListForField(int fieldNumber) + { + switch (fieldNumber) + { + case FileDescriptorProto.ServiceFieldNumber: + return (IReadOnlyList) Services; + case FileDescriptorProto.MessageTypeFieldNumber: + return (IReadOnlyList) MessageTypes; + case FileDescriptorProto.EnumTypeFieldNumber: + return (IReadOnlyList) EnumTypes; + default: + return null; + } + } + + internal DescriptorDeclaration GetDeclaration(IDescriptor descriptor) + { + DescriptorDeclaration declaration; + declarations.Value.TryGetValue(descriptor, out declaration); + return declaration; } /// @@ -87,13 +215,9 @@ internal string ComputeFullName(MessageDescriptor parent, string name) /// Extracts public dependencies from direct dependencies. This is a static method despite its /// first parameter, as the value we're in the middle of constructing is only used for exceptions. /// - private static IList DeterminePublicDependencies(FileDescriptor @this, FileDescriptorProto proto, FileDescriptor[] dependencies, bool allowUnknownDependencies) + private static IList DeterminePublicDependencies(FileDescriptor @this, FileDescriptorProto proto, IEnumerable dependencies, bool allowUnknownDependencies) { - var nameToFileMap = new Dictionary(); - foreach (var file in dependencies) - { - nameToFileMap[file.Name] = file; - } + var nameToFileMap = dependencies.ToDictionary(file => file.Name); var publicDependencies = new List(); for (int i = 0; i < proto.PublicDependency.Count; i++) { @@ -103,8 +227,8 @@ private static IList DeterminePublicDependencies(FileDescriptor throw new DescriptorValidationException(@this, "Invalid public dependency index."); } string name = proto.Dependency[index]; - FileDescriptor file = nameToFileMap[name]; - if (file == null) + FileDescriptor file; + if (!nameToFileMap.TryGetValue(name, out file)) { if (!allowUnknownDependencies) { @@ -125,6 +249,11 @@ private static IList DeterminePublicDependencies(FileDescriptor /// internal FileDescriptorProto Proto { get; } + /// + /// The syntax of the file + /// + public Syntax Syntax { get; } + /// /// The file name. /// @@ -151,6 +280,14 @@ private static IList DeterminePublicDependencies(FileDescriptor /// public IList Services { get; } + /// + /// Unmodifiable list of top-level extensions declared in this file. + /// Note that some extensions may be incomplete (FieldDescriptor.Extension may be null) + /// if this descriptor was generated using a version of protoc that did not fully + /// support extensions in C#. + /// + public ExtensionCollection Extensions { get; } + /// /// Unmodifiable list of this file's dependencies (imports). /// @@ -267,6 +404,8 @@ private void CrossLink() { service.CrossLink(); } + + Extensions.CrossLink(); } /// @@ -282,10 +421,13 @@ public static FileDescriptor FromGeneratedCode( FileDescriptor[] dependencies, GeneratedClrTypeInfo generatedCodeInfo) { + ExtensionRegistry registry = new ExtensionRegistry(); + registry.AddRange(GetAllExtensions(dependencies, generatedCodeInfo)); + FileDescriptorProto proto; try { - proto = FileDescriptorProto.Parser.ParseFrom(descriptorData); + proto = FileDescriptorProto.Parser.WithExtensionRegistry(registry).ParseFrom(descriptorData); } catch (InvalidProtocolBufferException e) { @@ -304,6 +446,93 @@ public static FileDescriptor FromGeneratedCode( } } + private static IEnumerable GetAllExtensions(FileDescriptor[] dependencies, GeneratedClrTypeInfo generatedInfo) + { + return dependencies.SelectMany(GetAllDependedExtensions).Distinct(ExtensionRegistry.ExtensionComparer.Instance).Concat(GetAllGeneratedExtensions(generatedInfo)); + } + + private static IEnumerable GetAllGeneratedExtensions(GeneratedClrTypeInfo generated) + { + return generated.Extensions.Concat(generated.NestedTypes.Where(t => t != null).SelectMany(GetAllGeneratedExtensions)); + } + + private static IEnumerable GetAllDependedExtensions(FileDescriptor descriptor) + { + return descriptor.Extensions.UnorderedExtensions + .Select(s => s.Extension) + .Where(e => e != null) + .Concat(descriptor.Dependencies.Concat(descriptor.PublicDependencies).SelectMany(GetAllDependedExtensions)) + .Concat(descriptor.MessageTypes.SelectMany(GetAllDependedExtensionsFromMessage)); + } + + private static IEnumerable GetAllDependedExtensionsFromMessage(MessageDescriptor descriptor) + { + return descriptor.Extensions.UnorderedExtensions + .Select(s => s.Extension) + .Where(e => e != null) + .Concat(descriptor.NestedTypes.SelectMany(GetAllDependedExtensionsFromMessage)); + } + + /// + /// Converts the given descriptor binary data into FileDescriptor objects. + /// Note: reflection using the returned FileDescriptors is not currently supported. + /// + /// The binary file descriptor proto data. Must not be null, and any + /// dependencies must come before the descriptor which depends on them. (If A depends on B, and B + /// depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible + /// with the order in which protoc provides descriptors to plugins. + /// The extension registry to use when parsing, or null if no extensions are required. + /// The file descriptors corresponding to . + public static IReadOnlyList BuildFromByteStrings(IEnumerable descriptorData, ExtensionRegistry registry) + { + ProtoPreconditions.CheckNotNull(descriptorData, nameof(descriptorData)); + + var parser = FileDescriptorProto.Parser.WithExtensionRegistry(registry); + + // TODO: See if we can build a single DescriptorPool instead of building lots of them. + // This will all behave correctly, but it's less efficient than we'd like. + var descriptors = new List(); + var descriptorsByName = new Dictionary(); + foreach (var data in descriptorData) + { + var proto = parser.ParseFrom(data); + var dependencies = new List(); + foreach (var dependencyName in proto.Dependency) + { + FileDescriptor dependency; + if (!descriptorsByName.TryGetValue(dependencyName, out dependency)) + { + throw new ArgumentException($"Dependency missing: {dependencyName}"); + } + dependencies.Add(dependency); + } + var pool = new DescriptorPool(dependencies); + FileDescriptor descriptor = new FileDescriptor( + data, proto, dependencies, pool, + allowUnknownDependencies: false, generatedCodeInfo: null); + descriptor.CrossLink(); + descriptors.Add(descriptor); + if (descriptorsByName.ContainsKey(descriptor.Name)) + { + throw new ArgumentException($"Duplicate descriptor name: {descriptor.Name}"); + } + descriptorsByName.Add(descriptor.Name, descriptor); + } + return new ReadOnlyCollection(descriptors); + } + + /// + /// Converts the given descriptor binary data into FileDescriptor objects. + /// Note: reflection using the returned FileDescriptors is not currently supported. + /// + /// The binary file descriptor proto data. Must not be null, and any + /// dependencies must come before the descriptor which depends on them. (If A depends on B, and B + /// depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible + /// with the order in which protoc provides descriptors to plugins. + /// The file descriptors corresponding to . + public static IReadOnlyList BuildFromByteStrings(IEnumerable descriptorData) => + BuildFromByteStrings(descriptorData, null); + /// /// Returns a that represents this instance. /// @@ -333,6 +562,47 @@ public override string ToString() /// /// The (possibly empty) set of custom options for this file. /// - public CustomOptions CustomOptions => Proto.Options?.CustomOptions ?? CustomOptions.Empty; + [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")] + public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber); + + /// + /// The FileOptions, defined in descriptor.proto. + /// If the options message is not present (i.e. there are no options), null is returned. + /// Custom options can be retrieved as extensions of the returned message. + /// NOTE: A defensive copy is created each time this property is retrieved. + /// + public FileOptions GetOptions() => Proto.Options?.Clone(); + + /// + /// Gets a single value file option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public T GetOption(Extension extension) + { + var value = Proto.Options.GetExtension(extension); + return value is IDeepCloneable ? (value as IDeepCloneable).Clone() : value; + } + + /// + /// Gets a repeated value file option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public RepeatedField GetOption(RepeatedExtension extension) + { + return Proto.Options.GetExtension(extension).Clone(); + } + + /// + /// Performs initialization for the given generic type argument. + /// + /// + /// This method is present for the sake of AOT compilers. It allows code (whether handwritten or generated) + /// to make calls into the reflection machinery of this library to express an intention to use that type + /// reflectively (e.g. for JSON parsing and formatting). The call itself does almost nothing, but AOT compilers + /// attempting to determine which generic type arguments need to be handled will spot the code path and act + /// accordingly. + /// + /// The type to force initialization for. + public static void ForceReflectionInitialization() => ReflectionUtil.ForceInitialize(); } } diff --git a/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs b/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs index fe5db65656fff..479e177130fce 100644 --- a/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs +++ b/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs @@ -42,6 +42,7 @@ public sealed class GeneratedClrTypeInfo { private static readonly string[] EmptyNames = new string[0]; private static readonly GeneratedClrTypeInfo[] EmptyCodeInfo = new GeneratedClrTypeInfo[0]; + private static readonly Extension[] EmptyExtensions = new Extension[0]; /// /// Irrelevant for file descriptors; the CLR type for the message for message descriptors. @@ -59,6 +60,11 @@ public sealed class GeneratedClrTypeInfo /// public string[] PropertyNames { get; } + /// + /// The extensions defined within this file/message descriptor + /// + public Extension[] Extensions { get; } + /// /// Irrelevant for file descriptors; the CLR property "base" names (in message descriptor oneof order) /// for oneofs in the message for message descriptors. It is expected that for a oneof name of "Foo", @@ -82,16 +88,35 @@ public sealed class GeneratedClrTypeInfo /// Each array parameter may be null, to indicate a lack of values. /// The parameter order is designed to make it feasible to format the generated code readably. /// - public GeneratedClrTypeInfo(Type clrType, MessageParser parser, string[] propertyNames, string[] oneofNames, Type[] nestedEnums, GeneratedClrTypeInfo[] nestedTypes) + public GeneratedClrTypeInfo(Type clrType, MessageParser parser, string[] propertyNames, string[] oneofNames, Type[] nestedEnums, Extension[] extensions, GeneratedClrTypeInfo[] nestedTypes) { NestedTypes = nestedTypes ?? EmptyCodeInfo; NestedEnums = nestedEnums ?? ReflectionUtil.EmptyTypes; ClrType = clrType; + Extensions = extensions ?? EmptyExtensions; Parser = parser; PropertyNames = propertyNames ?? EmptyNames; OneofNames = oneofNames ?? EmptyNames; } + /// + /// Creates a GeneratedClrTypeInfo for a message descriptor, with nested types, nested enums, the CLR type, property names and oneof names. + /// Each array parameter may be null, to indicate a lack of values. + /// The parameter order is designed to make it feasible to format the generated code readably. + /// + public GeneratedClrTypeInfo(Type clrType, MessageParser parser, string[] propertyNames, string[] oneofNames, Type[] nestedEnums, GeneratedClrTypeInfo[] nestedTypes) + : this(clrType, parser, propertyNames, oneofNames, nestedEnums, null, nestedTypes) + { + } + + /// + /// Creates a GeneratedClrTypeInfo for a file descriptor, with only types, enums, and extensions. + /// + public GeneratedClrTypeInfo(Type[] nestedEnums, Extension[] extensions, GeneratedClrTypeInfo[] nestedTypes) + : this(null, null, null, null, nestedEnums, extensions, nestedTypes) + { + } + /// /// Creates a GeneratedClrTypeInfo for a file descriptor, with only types and enums. /// diff --git a/csharp/src/Google.Protobuf/Reflection/IDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/IDescriptor.cs index 318d58c968a58..1c1ef387da03f 100644 --- a/csharp/src/Google.Protobuf/Reflection/IDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/IDescriptor.cs @@ -51,5 +51,5 @@ public interface IDescriptor /// Returns the descriptor for the .proto file that this entity is part of. /// FileDescriptor File { get; } - } + } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs index cfe56fde671e4..d73427b73b691 100644 --- a/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs @@ -58,6 +58,12 @@ public interface IFieldAccessor /// object GetValue(IMessage message); + /// + /// Indicates whether the field in the specified message is set. + /// For proto3 fields that aren't explicitly optional, this throws an + /// + bool HasValue(IMessage message); + /// /// Mutator for single "simple" fields only. /// diff --git a/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs index 9ed7f8c4df4c1..56e3dddc947bf 100644 --- a/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs @@ -51,6 +51,11 @@ public override void Clear(IMessage message) list.Clear(); } + public override bool HasValue(IMessage message) + { + throw new InvalidOperationException("HasValue is not implemented for map fields"); + } + public override void SetValue(IMessage message, object value) { throw new InvalidOperationException("SetValue is not implemented for map fields"); diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs old mode 100755 new mode 100644 index 86942acc02250..7b5ab2fb48e78 --- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs @@ -34,6 +34,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; +using System.Reflection; #if NET35 // Needed for ReadOnlyDictionary, which does not exist in .NET 3.5 using Google.Protobuf.Collections; @@ -63,7 +64,8 @@ public sealed class MessageDescriptor : DescriptorBase private readonly IList fieldsInDeclarationOrder; private readonly IList fieldsInNumberOrder; private readonly IDictionary jsonFieldMap; - + private Func extensionSetIsInitialized; + internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex, GeneratedClrTypeInfo generatedCodeInfo) : base(file, file.ComputeFullName(parent, proto.Name), typeIndex) { @@ -72,28 +74,42 @@ internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDe ClrType = generatedCodeInfo?.ClrType; ContainingType = parent; - // Note use of generatedCodeInfo. rather than generatedCodeInfo?. here... we don't expect - // to see any nested oneofs, types or enums in "not actually generated" code... we do - // expect fields though (for map entry messages). + // If generatedCodeInfo is null, we just won't generate an accessor for any fields. Oneofs = DescriptorUtil.ConvertAndMakeReadOnly( proto.OneofDecl, (oneof, index) => - new OneofDescriptor(oneof, file, this, index, generatedCodeInfo.OneofNames[index])); + new OneofDescriptor(oneof, file, this, index, generatedCodeInfo?.OneofNames[index])); + + int syntheticOneofCount = 0; + foreach (var oneof in Oneofs) + { + if (oneof.IsSynthetic) + { + syntheticOneofCount++; + } + else if (syntheticOneofCount != 0) + { + throw new ArgumentException("All synthetic oneofs should come after real oneofs"); + } + } + RealOneofCount = Oneofs.Count - syntheticOneofCount; NestedTypes = DescriptorUtil.ConvertAndMakeReadOnly( proto.NestedType, (type, index) => - new MessageDescriptor(type, file, this, index, generatedCodeInfo.NestedTypes[index])); + new MessageDescriptor(type, file, this, index, generatedCodeInfo?.NestedTypes[index])); EnumTypes = DescriptorUtil.ConvertAndMakeReadOnly( proto.EnumType, (type, index) => - new EnumDescriptor(type, file, this, index, generatedCodeInfo.NestedEnums[index])); + new EnumDescriptor(type, file, this, index, generatedCodeInfo?.NestedEnums[index])); + + Extensions = new ExtensionCollection(this, generatedCodeInfo?.Extensions); fieldsInDeclarationOrder = DescriptorUtil.ConvertAndMakeReadOnly( proto.Field, (field, index) => - new FieldDescriptor(field, file, this, index, generatedCodeInfo?.PropertyNames[index])); + new FieldDescriptor(field, file, this, index, generatedCodeInfo?.PropertyNames[index], null)); fieldsInNumberOrder = new ReadOnlyCollection(fieldsInDeclarationOrder.OrderBy(field => field.FieldNumber).ToArray()); // TODO: Use field => field.Proto.JsonName when we're confident it's appropriate. (And then use it in the formatter, too.) jsonFieldMap = CreateJsonFieldMap(fieldsInNumberOrder); @@ -117,8 +133,38 @@ private static ReadOnlyDictionary CreateJsonFieldMap(IL /// public override string Name => Proto.Name; + internal override IReadOnlyList GetNestedDescriptorListForField(int fieldNumber) + { + switch (fieldNumber) + { + case DescriptorProto.FieldFieldNumber: + return (IReadOnlyList) fieldsInDeclarationOrder; + case DescriptorProto.NestedTypeFieldNumber: + return (IReadOnlyList) NestedTypes; + case DescriptorProto.EnumTypeFieldNumber: + return (IReadOnlyList) EnumTypes; + default: + return null; + } + } + internal DescriptorProto Proto { get; } + internal bool IsExtensionsInitialized(IMessage message) + { + if (Proto.ExtensionRange.Count == 0) + { + return true; + } + + if (extensionSetIsInitialized == null) + { + extensionSetIsInitialized = ReflectionUtil.CreateIsInitializedCaller(ClrType); + } + + return extensionSetIsInitialized(message); + } + /// /// The CLR type used to represent message instances from this descriptor. /// @@ -182,6 +228,14 @@ private static ReadOnlyDictionary CreateJsonFieldMap(IL /// public FieldCollection Fields { get; } + /// + /// An unmodifiable list of extensions defined in this message's scope. + /// Note that some extensions may be incomplete (FieldDescriptor.Extension may be null) + /// if they are declared in a file generated using a version of protoc that did not fully + /// support extensions in C#. + /// + public ExtensionCollection Extensions { get; } + /// /// An unmodifiable list of this message type's nested types. /// @@ -194,9 +248,19 @@ private static ReadOnlyDictionary CreateJsonFieldMap(IL /// /// An unmodifiable list of the "oneof" field collections in this message type. + /// All "real" oneofs (where returns false) + /// come before synthetic ones. /// public IList Oneofs { get; } + /// + /// The number of real "oneof" descriptors in this message type. Every element in + /// with an index less than this will have a property value + /// of false; every element with an index greater than or equal to this will have a + /// property value of true. + /// + public int RealOneofCount { get; } + /// /// Finds a field by field name. /// @@ -223,7 +287,35 @@ public T FindDescriptor(string name) where T : class, IDescriptor => /// /// The (possibly empty) set of custom options for this message. /// - public CustomOptions CustomOptions => Proto.Options?.CustomOptions ?? CustomOptions.Empty; + [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")] + public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber); + + /// + /// The MessageOptions, defined in descriptor.proto. + /// If the options message is not present (i.e. there are no options), null is returned. + /// Custom options can be retrieved as extensions of the returned message. + /// NOTE: A defensive copy is created each time this property is retrieved. + /// + public MessageOptions GetOptions() => Proto.Options?.Clone(); + + /// + /// Gets a single value message option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public T GetOption(Extension extension) + { + var value = Proto.Options.GetExtension(extension); + return value is IDeepCloneable ? (value as IDeepCloneable).Clone() : value; + } + + /// + /// Gets a repeated value message option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public Collections.RepeatedField GetOption(RepeatedExtension extension) + { + return Proto.Options.GetExtension(extension).Clone(); + } /// /// Looks up and cross-links all fields and nested types. @@ -244,6 +336,8 @@ internal void CrossLink() { oneof.CrossLink(); } + + Extensions.CrossLink(); } /// diff --git a/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs index 19d7f8a09258f..8e1503767bd76 100644 --- a/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs @@ -30,6 +30,9 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Collections; +using System; + namespace Google.Protobuf.Reflection { /// @@ -70,7 +73,35 @@ public sealed class MethodDescriptor : DescriptorBase /// /// The (possibly empty) set of custom options for this method. /// - public CustomOptions CustomOptions => Proto.Options?.CustomOptions ?? CustomOptions.Empty; + [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")] + public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber); + + /// + /// The MethodOptions, defined in descriptor.proto. + /// If the options message is not present (i.e. there are no options), null is returned. + /// Custom options can be retrieved as extensions of the returned message. + /// NOTE: A defensive copy is created each time this property is retrieved. + /// + public MethodOptions GetOptions() => Proto.Options?.Clone(); + + /// + /// Gets a single value method option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public T GetOption(Extension extension) + { + var value = Proto.Options.GetExtension(extension); + return value is IDeepCloneable ? (value as IDeepCloneable).Clone() : value; + } + + /// + /// Gets a repeated value method option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public RepeatedField GetOption(RepeatedExtension extension) + { + return Proto.Options.GetExtension(extension).Clone(); + } internal MethodDescriptor(MethodDescriptorProto proto, FileDescriptor file, ServiceDescriptor parent, int index) @@ -105,4 +136,5 @@ internal void CrossLink() outputType = (MessageDescriptor) lookup; } } -} \ No newline at end of file +} + \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs b/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs index 8714ab18efe7c..7523426dc5f55 100644 --- a/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs @@ -43,19 +43,31 @@ public sealed class OneofAccessor { private readonly Func caseDelegate; private readonly Action clearDelegate; - private OneofDescriptor descriptor; - internal OneofAccessor(PropertyInfo caseProperty, MethodInfo clearMethod, OneofDescriptor descriptor) + private OneofAccessor(OneofDescriptor descriptor, Func caseDelegate, Action clearDelegate) { - if (!caseProperty.CanRead) - { - throw new ArgumentException("Cannot read from property"); - } - this.descriptor = descriptor; - caseDelegate = ReflectionUtil.CreateFuncIMessageT(caseProperty.GetGetMethod()); + Descriptor = descriptor; + this.caseDelegate = caseDelegate; + this.clearDelegate = clearDelegate; + } + + internal static OneofAccessor ForRegularOneof( + OneofDescriptor descriptor, + PropertyInfo caseProperty, + MethodInfo clearMethod) => + new OneofAccessor( + descriptor, + ReflectionUtil.CreateFuncIMessageInt32(caseProperty.GetGetMethod()), + ReflectionUtil.CreateActionIMessage(clearMethod)); - this.descriptor = descriptor; - clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod); + internal static OneofAccessor ForSyntheticOneof(OneofDescriptor descriptor) + { + // Note: descriptor.Fields will be null when this method is called, because we haven't + // cross-linked yet. But by the time the delegates are called by user code, all will be + // well. (That's why we capture the descriptor itself rather than a field.) + return new OneofAccessor(descriptor, + message => descriptor.Fields[0].Accessor.HasValue(message) ? descriptor.Fields[0].FieldNumber : 0, + message => descriptor.Fields[0].Accessor.Clear(message)); } /// @@ -64,15 +76,12 @@ internal OneofAccessor(PropertyInfo caseProperty, MethodInfo clearMethod, OneofD /// /// The descriptor of the oneof. /// - public OneofDescriptor Descriptor { get { return descriptor; } } + public OneofDescriptor Descriptor { get; } /// /// Clears the oneof in the specified message. /// - public void Clear(IMessage message) - { - clearDelegate(message); - } + public void Clear(IMessage message) => clearDelegate(message); /// /// Indicates which field in the oneof is set for specified message @@ -80,11 +89,9 @@ public void Clear(IMessage message) public FieldDescriptor GetCaseFieldDescriptor(IMessage message) { int fieldNumber = caseDelegate(message); - if (fieldNumber > 0) - { - return descriptor.ContainingType.FindFieldByNumber(fieldNumber); - } - return null; + return fieldNumber > 0 + ? Descriptor.ContainingType.FindFieldByNumber(fieldNumber) + : null; } } } diff --git a/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs index 5906c2e36d9cf..b41d5205158c8 100644 --- a/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs @@ -30,8 +30,11 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; +using Google.Protobuf.Collections; using Google.Protobuf.Compatibility; namespace Google.Protobuf.Reflection @@ -52,8 +55,13 @@ internal OneofDescriptor(OneofDescriptorProto proto, FileDescriptor file, Messag { this.proto = proto; containingType = parent; - file.DescriptorPool.AddSymbol(this); + + // It's useful to determine whether or not this is a synthetic oneof before cross-linking. That means + // diving into the proto directly rather than using FieldDescriptor, but that's okay. + var firstFieldInOneof = parent.Proto.Field.FirstOrDefault(fieldProto => fieldProto.HasOneofIndex && fieldProto.OneofIndex == index); + IsSynthetic = firstFieldInOneof?.Proto3Optional ?? false; + accessor = CreateAccessor(clrName); } @@ -81,10 +89,26 @@ public MessageDescriptor ContainingType /// public IList Fields { get { return fields; } } + /// + /// Returns true if this oneof is a synthetic oneof containing a proto3 optional field; + /// false otherwise. + /// + public bool IsSynthetic { get; } + /// /// Gets an accessor for reflective access to the values associated with the oneof /// in a particular message. /// + /// + /// + /// In descriptors for generated code, the value returned by this property will always be non-null. + /// + /// + /// In dynamically loaded descriptors, the value returned by this property will current be null; + /// if and when dynamic messages are supported, it will return a suitable accessor to work with + /// them. + /// + /// /// /// The accessor used for reflective access. /// @@ -93,7 +117,35 @@ public MessageDescriptor ContainingType /// /// The (possibly empty) set of custom options for this oneof. /// - public CustomOptions CustomOptions => proto.Options?.CustomOptions ?? CustomOptions.Empty; + [Obsolete("CustomOptions are obsolete. Use the GetOptions method.")] + public CustomOptions CustomOptions => new CustomOptions(proto.Options?._extensions?.ValuesByNumber); + + /// + /// The OneofOptions, defined in descriptor.proto. + /// If the options message is not present (i.e. there are no options), null is returned. + /// Custom options can be retrieved as extensions of the returned message. + /// NOTE: A defensive copy is created each time this property is retrieved. + /// + public OneofOptions GetOptions() => proto.Options?.Clone(); + + /// + /// Gets a single value oneof option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public T GetOption(Extension extension) + { + var value = proto.Options.GetExtension(extension); + return value is IDeepCloneable ? (value as IDeepCloneable).Clone() : value; + } + + /// + /// Gets a repeated value oneof option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public RepeatedField GetOption(RepeatedExtension extension) + { + return proto.Options.GetExtension(extension).Clone(); + } internal void CrossLink() { @@ -110,18 +162,34 @@ internal void CrossLink() private OneofAccessor CreateAccessor(string clrName) { - var caseProperty = containingType.ClrType.GetProperty(clrName + "Case"); - if (caseProperty == null) + // We won't have a CLR name if this is from a dynamically-loaded FileDescriptor. + // TODO: Support dynamic messages. + if (clrName == null) { - throw new DescriptorValidationException(this, $"Property {clrName}Case not found in {containingType.ClrType}"); + return null; } - var clearMethod = containingType.ClrType.GetMethod("Clear" + clrName); - if (clearMethod == null) + if (IsSynthetic) { - throw new DescriptorValidationException(this, $"Method Clear{clrName} not found in {containingType.ClrType}"); + return OneofAccessor.ForSyntheticOneof(this); + } + else + { + var caseProperty = containingType.ClrType.GetProperty(clrName + "Case"); + if (caseProperty == null) + { + throw new DescriptorValidationException(this, $"Property {clrName}Case not found in {containingType.ClrType}"); + } + if (!caseProperty.CanRead) + { + throw new ArgumentException($"Cannot read from property {clrName}Case in {containingType.ClrType}"); + } + var clearMethod = containingType.ClrType.GetMethod("Clear" + clrName); + if (clearMethod == null) + { + throw new DescriptorValidationException(this, $"Method Clear{clrName} not found in {containingType.ClrType}"); + } + return OneofAccessor.ForRegularOneof(this, caseProperty, clearMethod); } - - return new OneofAccessor(caseProperty, clearMethod, this); } } } diff --git a/csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs b/csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs index 07d0fd99afb75..63f5228f3d624 100644 --- a/csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs +++ b/csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs @@ -60,6 +60,6 @@ public OriginalNameAttribute(string name) Name = ProtoPreconditions.CheckNotNull(name, nameof(name)); PreferredAlias = true; } - + } } diff --git a/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs b/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs deleted file mode 100644 index 8c055d6d921ee..0000000000000 --- a/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs +++ /dev/null @@ -1,59 +0,0 @@ -#region Copyright notice and license -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#endregion - -// This file just contains partial classes for any autogenerated classes that need additional support. -namespace Google.Protobuf.Reflection -{ - internal partial class FieldDescriptorProto - { - // We can't tell the difference between "explicitly set to 0" and "not set" - // in proto3, but we need to tell the difference for OneofIndex. descriptor.proto - // is really a proto2 file, but the runtime doesn't know about proto2 semantics... - // We fake it by defaulting to -1. - partial void OnConstruction() - { - OneofIndex = -1; - } - } - - internal partial class FieldOptions - { - // We can't tell the difference between "explicitly set to false" and "not set" - // in proto3, but we need to tell the difference for FieldDescriptor.IsPacked. - // This won't work if we ever need to support proto2, but at that point we'll be - // able to remove this hack and use field presence instead. - partial void OnConstruction() - { - Packed = true; - } - } -} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs b/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs index df820ca36bd8e..fd1ad4e3e0864 100644 --- a/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs +++ b/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs @@ -30,9 +30,8 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Compatibility; using System; -using System.Collections.Generic; -using System.Linq.Expressions; using System.Reflection; namespace Google.Protobuf.Reflection @@ -47,61 +46,318 @@ namespace Google.Protobuf.Reflection /// internal static class ReflectionUtil { + static ReflectionUtil() + { + ForceInitialize(); // Handles all reference types + ForceInitialize(); + ForceInitialize(); + ForceInitialize(); + ForceInitialize(); + ForceInitialize(); + ForceInitialize(); + ForceInitialize(); + ForceInitialize(); + ForceInitialize(); + ForceInitialize(); + ForceInitialize(); + ForceInitialize(); + ForceInitialize(); + ForceInitialize(); + ForceInitialize(); + SampleEnumMethod(); + } + + internal static void ForceInitialize() => new ReflectionHelper(); + /// /// Empty Type[] used when calling GetProperty to force property instead of indexer fetching. /// internal static readonly Type[] EmptyTypes = new Type[0]; /// - /// Creates a delegate which will cast the argument to the appropriate method target type, + /// Creates a delegate which will cast the argument to the type that declares the method, /// call the method on it, then convert the result to object. /// - internal static Func CreateFuncIMessageObject(MethodInfo method) - { - ParameterExpression parameter = Expression.Parameter(typeof(IMessage), "p"); - Expression downcast = Expression.Convert(parameter, method.DeclaringType); - Expression call = Expression.Call(downcast, method); - Expression upcast = Expression.Convert(call, typeof(object)); - return Expression.Lambda>(upcast, parameter).Compile(); - } + /// The method to create a delegate for, which must be declared in an IMessage + /// implementation. + internal static Func CreateFuncIMessageObject(MethodInfo method) => + GetReflectionHelper(method.DeclaringType, method.ReturnType).CreateFuncIMessageObject(method); /// - /// Creates a delegate which will cast the argument to the appropriate method target type, - /// call the method on it, then convert the result to the specified type. + /// Creates a delegate which will cast the argument to the type that declares the method, + /// call the method on it, then convert the result to the specified type. The method is expected + /// to actually return an enum (because of where we're calling it - for oneof cases). Sometimes that + /// means we need some extra work to perform conversions. /// - internal static Func CreateFuncIMessageT(MethodInfo method) - { - ParameterExpression parameter = Expression.Parameter(typeof(IMessage), "p"); - Expression downcast = Expression.Convert(parameter, method.DeclaringType); - Expression call = Expression.Call(downcast, method); - Expression upcast = Expression.Convert(call, typeof(T)); - return Expression.Lambda>(upcast, parameter).Compile(); - } + /// The method to create a delegate for, which must be declared in an IMessage + /// implementation. + internal static Func CreateFuncIMessageInt32(MethodInfo method) => + GetReflectionHelper(method.DeclaringType, method.ReturnType).CreateFuncIMessageInt32(method); /// /// Creates a delegate which will execute the given method after casting the first argument to - /// the target type of the method, and the second argument to the first parameter type of the method. + /// the type that declares the method, and the second argument to the first parameter type of the method. /// - internal static Action CreateActionIMessageObject(MethodInfo method) - { - ParameterExpression targetParameter = Expression.Parameter(typeof(IMessage), "target"); - ParameterExpression argParameter = Expression.Parameter(typeof(object), "arg"); - Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType); - Expression castArgument = Expression.Convert(argParameter, method.GetParameters()[0].ParameterType); - Expression call = Expression.Call(castTarget, method, castArgument); - return Expression.Lambda>(call, targetParameter, argParameter).Compile(); - } + /// The method to create a delegate for, which must be declared in an IMessage + /// implementation. + internal static Action CreateActionIMessageObject(MethodInfo method) => + GetReflectionHelper(method.DeclaringType, method.GetParameters()[0].ParameterType).CreateActionIMessageObject(method); + + /// + /// Creates a delegate which will execute the given method after casting the first argument to + /// type that declares the method. + /// + /// The method to create a delegate for, which must be declared in an IMessage + /// implementation. + internal static Action CreateActionIMessage(MethodInfo method) => + GetReflectionHelper(method.DeclaringType, typeof(object)).CreateActionIMessage(method); + + internal static Func CreateFuncIMessageBool(MethodInfo method) => + GetReflectionHelper(method.DeclaringType, method.ReturnType).CreateFuncIMessageBool(method); + + internal static Func CreateIsInitializedCaller(Type msg) => + ((IExtensionSetReflector)Activator.CreateInstance(typeof(ExtensionSetReflector<>).MakeGenericType(msg))).CreateIsInitializedCaller(); /// /// Creates a delegate which will execute the given method after casting the first argument to - /// the target type of the method. + /// the type that declares the method, and the second argument to the first parameter type of the method. /// - internal static Action CreateActionIMessage(MethodInfo method) + internal static IExtensionReflectionHelper CreateExtensionHelper(Extension extension) => + (IExtensionReflectionHelper)Activator.CreateInstance(typeof(ExtensionReflectionHelper<,>).MakeGenericType(extension.TargetType, extension.GetType().GenericTypeArguments[1]), extension); + + /// + /// Creates a reflection helper for the given type arguments. Currently these are created on demand + /// rather than cached; this will be "busy" when initially loading a message's descriptor, but after that + /// they can be garbage collected. We could cache them by type if that proves to be important, but creating + /// an object is pretty cheap. + /// + private static IReflectionHelper GetReflectionHelper(Type t1, Type t2) => + (IReflectionHelper) Activator.CreateInstance(typeof(ReflectionHelper<,>).MakeGenericType(t1, t2)); + + // Non-generic interface allowing us to use an instance of ReflectionHelper without statically + // knowing the types involved. + private interface IReflectionHelper + { + Func CreateFuncIMessageInt32(MethodInfo method); + Action CreateActionIMessage(MethodInfo method); + Func CreateFuncIMessageObject(MethodInfo method); + Action CreateActionIMessageObject(MethodInfo method); + Func CreateFuncIMessageBool(MethodInfo method); + } + + internal interface IExtensionReflectionHelper + { + object GetExtension(IMessage message); + void SetExtension(IMessage message, object value); + bool HasExtension(IMessage message); + void ClearExtension(IMessage message); + } + + private interface IExtensionSetReflector + { + Func CreateIsInitializedCaller(); + } + + private class ReflectionHelper : IReflectionHelper { - ParameterExpression targetParameter = Expression.Parameter(typeof(IMessage), "target"); - Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType); - Expression call = Expression.Call(castTarget, method); - return Expression.Lambda>(call, targetParameter).Compile(); - } + + public Func CreateFuncIMessageInt32(MethodInfo method) + { + // On pleasant runtimes, we can create a Func from a method returning + // an enum based on an int. That's the fast path. + if (CanConvertEnumFuncToInt32Func) + { + var del = (Func) method.CreateDelegate(typeof(Func)); + return message => del((T1) message); + } + else + { + // On some runtimes (e.g. old Mono) the return type has to be exactly correct, + // so we go via boxing. Reflection is already fairly inefficient, and this is + // only used for one-of case checking, fortunately. + var del = (Func) method.CreateDelegate(typeof(Func)); + return message => (int) (object) del((T1) message); + } + } + + public Action CreateActionIMessage(MethodInfo method) + { + var del = (Action) method.CreateDelegate(typeof(Action)); + return message => del((T1) message); + } + + public Func CreateFuncIMessageObject(MethodInfo method) + { + var del = (Func) method.CreateDelegate(typeof(Func)); + return message => del((T1) message); + } + + public Action CreateActionIMessageObject(MethodInfo method) + { + var del = (Action) method.CreateDelegate(typeof(Action)); + return (message, arg) => del((T1) message, (T2) arg); + } + + public Func CreateFuncIMessageBool(MethodInfo method) + { + var del = (Func)method.CreateDelegate(typeof(Func)); + return message => del((T1)message); + } + } + + private class ExtensionReflectionHelper : IExtensionReflectionHelper + where T1 : IExtendableMessage + { + private readonly Extension extension; + + public ExtensionReflectionHelper(Extension extension) + { + this.extension = extension; + } + + public object GetExtension(IMessage message) + { + if (!(message is T1)) + { + throw new InvalidCastException("Cannot access extension on message that isn't IExtensionMessage"); + } + + T1 extensionMessage = (T1)message; + + if (extension is Extension) + { + return extensionMessage.GetExtension(extension as Extension); + } + else if (extension is RepeatedExtension) + { + return extensionMessage.GetOrInitializeExtension(extension as RepeatedExtension); + } + else + { + throw new InvalidCastException("The provided extension is not a valid extension identifier type"); + } + } + + public bool HasExtension(IMessage message) + { + if (!(message is T1)) + { + throw new InvalidCastException("Cannot access extension on message that isn't IExtensionMessage"); + } + + T1 extensionMessage = (T1)message; + + if (extension is Extension) + { + return extensionMessage.HasExtension(extension as Extension); + } + else if (extension is RepeatedExtension) + { + throw new InvalidOperationException("HasValue is not implemented for repeated extensions"); + } + else + { + throw new InvalidCastException("The provided extension is not a valid extension identifier type"); + } + } + + public void SetExtension(IMessage message, object value) + { + if (!(message is T1)) + { + throw new InvalidCastException("Cannot access extension on message that isn't IExtensionMessage"); + } + + T1 extensionMessage = (T1)message; + + if (extension is Extension) + { + extensionMessage.SetExtension(extension as Extension, (T3)value); + } + else if (extension is RepeatedExtension) + { + throw new InvalidOperationException("SetValue is not implemented for repeated extensions"); + } + else + { + throw new InvalidCastException("The provided extension is not a valid extension identifier type"); + } + } + + public void ClearExtension(IMessage message) + { + if (!(message is T1)) + { + throw new InvalidCastException("Cannot access extension on message that isn't IExtensionMessage"); + } + + T1 extensionMessage = (T1)message; + + if (extension is Extension) + { + extensionMessage.ClearExtension(extension as Extension); + } + else if (extension is RepeatedExtension) + { + extensionMessage.GetExtension(extension as RepeatedExtension).Clear(); + } + else + { + throw new InvalidCastException("The provided extension is not a valid extension identifier type"); + } + } + } + + private class ExtensionSetReflector : IExtensionSetReflector where T1 : IExtendableMessage + { + public Func CreateIsInitializedCaller() + { + var prop = typeof(T1).GetTypeInfo().GetDeclaredProperty("_Extensions"); +#if NET35 + var getFunc = (Func>)prop.GetGetMethod(true).CreateDelegate(typeof(Func>)); +#else + var getFunc = (Func>)prop.GetMethod.CreateDelegate(typeof(Func>)); +#endif + var initializedFunc = (Func, bool>) + typeof(ExtensionSet) + .GetTypeInfo() + .GetDeclaredMethod("IsInitialized") + .CreateDelegate(typeof(Func, bool>)); + return (m) => { + var set = getFunc((T1)m); + return set == null || initializedFunc(set); + }; + } + } + + // Runtime compatibility checking code - see ReflectionHelper.CreateFuncIMessageInt32 for + // details about why we're doing this. + + // Deliberately not inside the generic type. We only want to check this once. + private static bool CanConvertEnumFuncToInt32Func { get; } = CheckCanConvertEnumFuncToInt32Func(); + + private static bool CheckCanConvertEnumFuncToInt32Func() + { + try + { + // Try to do the conversion using reflection, so we can see whether it's supported. + MethodInfo method = typeof(ReflectionUtil).GetMethod(nameof(SampleEnumMethod)); + // If this passes, we're in a reasonable runtime. + method.CreateDelegate(typeof(Func)); + return true; + } + catch (ArgumentException) + { + return false; + } + } + + public enum SampleEnum + { + X + } + + // Public to make the reflection simpler. + public static SampleEnum SampleEnumMethod() => SampleEnum.X; } -} \ No newline at end of file +} diff --git a/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs index bd408470929bf..afb4a693fcef1 100644 --- a/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs @@ -51,6 +51,11 @@ public override void Clear(IMessage message) list.Clear(); } + public override bool HasValue(IMessage message) + { + throw new InvalidOperationException("HasValue is not implemented for repeated fields"); + } + public override void SetValue(IMessage message, object value) { throw new InvalidOperationException("SetValue is not implemented for repeated fields"); diff --git a/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs index fe5c072c8e5d1..dab348b6f8ec6 100644 --- a/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs @@ -30,8 +30,10 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Collections; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; namespace Google.Protobuf.Reflection { @@ -58,6 +60,17 @@ internal ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, in /// public override string Name { get { return proto.Name; } } + internal override IReadOnlyList GetNestedDescriptorListForField(int fieldNumber) + { + switch (fieldNumber) + { + case ServiceDescriptorProto.MethodFieldNumber: + return (IReadOnlyList) methods; + default: + return null; + } + } + internal ServiceDescriptorProto Proto { get { return proto; } } /// @@ -72,7 +85,7 @@ public IList Methods /// Finds a method by name. /// /// The unqualified name of the method (e.g. "Foo"). - /// The method's decsriptor, or null if not found. + /// The method's descriptor, or null if not found. public MethodDescriptor FindMethodByName(String name) { return File.DescriptorPool.FindSymbol(FullName + "." + name); @@ -81,7 +94,35 @@ public MethodDescriptor FindMethodByName(String name) /// /// The (possibly empty) set of custom options for this service. /// - public CustomOptions CustomOptions => Proto.Options?.CustomOptions ?? CustomOptions.Empty; + [Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")] + public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber); + + /// + /// The ServiceOptions, defined in descriptor.proto. + /// If the options message is not present (i.e. there are no options), null is returned. + /// Custom options can be retrieved as extensions of the returned message. + /// NOTE: A defensive copy is created each time this property is retrieved. + /// + public ServiceOptions GetOptions() => Proto.Options?.Clone(); + + /// + /// Gets a single value service option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public T GetOption(Extension extension) + { + var value = Proto.Options.GetExtension(extension); + return value is IDeepCloneable ? (value as IDeepCloneable).Clone() : value; + } + + /// + /// Gets a repeated value service option for this descriptor + /// + [Obsolete("GetOption is obsolete. Use the GetOptions() method.")] + public RepeatedField GetOption(RepeatedExtension extension) + { + return Proto.Options.GetExtension(extension).Clone(); + } internal void CrossLink() { @@ -91,4 +132,5 @@ internal void CrossLink() } } } -} \ No newline at end of file +} + \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs index bbac2173d4d3f..07d84d7fb914d 100644 --- a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs @@ -48,6 +48,7 @@ internal sealed class SingleFieldAccessor : FieldAccessorBase private readonly Action setValueDelegate; private readonly Action clearDelegate; + private readonly Func hasDelegate; internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor) { @@ -57,25 +58,67 @@ internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) } setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod()); - var clrType = property.PropertyType; - - // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.) - object defaultValue = - descriptor.FieldType == FieldType.Message ? null - : clrType == typeof(string) ? "" - : clrType == typeof(ByteString) ? ByteString.Empty - : Activator.CreateInstance(clrType); - clearDelegate = message => SetValue(message, defaultValue); - } + // Note: this looks worrying in that we access the containing oneof, which isn't valid until cross-linking + // is complete... but field accessors aren't created until after cross-linking. + // The oneof itself won't be cross-linked yet, but that's okay: the oneof accessor is created + // earlier. - public override void Clear(IMessage message) - { - clearDelegate(message); - } + // Message fields always support presence, via null checks. + if (descriptor.FieldType == FieldType.Message) + { + hasDelegate = message => GetValue(message) != null; + clearDelegate = message => SetValue(message, null); + } + // Oneof fields always support presence, via case checks. + // Note that clearing the field is a no-op unless that specific field is the current "case". + else if (descriptor.RealContainingOneof != null) + { + var oneofAccessor = descriptor.RealContainingOneof.Accessor; + hasDelegate = message => oneofAccessor.GetCaseFieldDescriptor(message) == descriptor; + clearDelegate = message => + { + // Clear on a field only affects the oneof itself if the current case is the field we're accessing. + if (oneofAccessor.GetCaseFieldDescriptor(message) == descriptor) + { + oneofAccessor.Clear(message); + } + }; + } + // Primitive fields always support presence in proto2, and support presence in proto3 for optional fields. + else if (descriptor.File.Syntax == Syntax.Proto2 || descriptor.Proto.Proto3Optional) + { + MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod; + if (hasMethod == null) + { + throw new ArgumentException("Not all required properties/methods are available"); + } + hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod); + MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes); + if (clearMethod == null) + { + throw new ArgumentException("Not all required properties/methods are available"); + } + clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod); + } + // What's left? + // Primitive proto3 fields without the optional keyword, which aren't in oneofs. + else + { + hasDelegate = message => { throw new InvalidOperationException("Presence is not implemented for this field"); }; - public override void SetValue(IMessage message, object value) - { - setValueDelegate(message, value); + // While presence isn't supported, clearing still is; it's just setting to a default value. + var clrType = property.PropertyType; + + object defaultValue = + clrType == typeof(string) ? "" + : clrType == typeof(ByteString) ? ByteString.Empty + : Activator.CreateInstance(clrType); + clearDelegate = message => SetValue(message, defaultValue); + } } + + public override void Clear(IMessage message) => clearDelegate(message); + public override bool HasValue(IMessage message) => hasDelegate(message); + public override void SetValue(IMessage message, object value) => setValueDelegate(message, value); } } diff --git a/csharp/src/Google.Protobuf/SegmentedBufferHelper.cs b/csharp/src/Google.Protobuf/SegmentedBufferHelper.cs new file mode 100644 index 0000000000000..b5441d34211df --- /dev/null +++ b/csharp/src/Google.Protobuf/SegmentedBufferHelper.cs @@ -0,0 +1,296 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Buffers; +using System.IO; +using System.Runtime.CompilerServices; +using System.Security; + +namespace Google.Protobuf +{ + /// + /// Abstraction for reading from a stream / read only sequence. + /// Parsing from the buffer is a loop of reading from current buffer / refreshing the buffer once done. + /// + [SecuritySafeCritical] + internal struct SegmentedBufferHelper + { + private int? totalLength; + private ReadOnlySequence.Enumerator readOnlySequenceEnumerator; + private CodedInputStream codedInputStream; + + /// + /// Initialize an instance with a coded input stream. + /// This approach is faster than using a constructor because the instance to initialize is passed by reference + /// and we can write directly into it without copying. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Initialize(CodedInputStream codedInputStream, out SegmentedBufferHelper instance) + { + instance.totalLength = codedInputStream.InternalInputStream == null ? (int?)codedInputStream.InternalBuffer.Length : null; + instance.readOnlySequenceEnumerator = default; + instance.codedInputStream = codedInputStream; + } + + /// + /// Initialize an instance with a read only sequence. + /// This approach is faster than using a constructor because the instance to initialize is passed by reference + /// and we can write directly into it without copying. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Initialize(ReadOnlySequence sequence, out SegmentedBufferHelper instance, out ReadOnlySpan firstSpan) + { + instance.codedInputStream = null; + if (sequence.IsSingleSegment) + { + firstSpan = sequence.First.Span; + instance.totalLength = firstSpan.Length; + instance.readOnlySequenceEnumerator = default; + } + else + { + instance.readOnlySequenceEnumerator = sequence.GetEnumerator(); + instance.totalLength = (int) sequence.Length; + + // set firstSpan to the first segment + instance.readOnlySequenceEnumerator.MoveNext(); + firstSpan = instance.readOnlySequenceEnumerator.Current.Span; + } + } + + public bool RefillBuffer(ref ReadOnlySpan buffer, ref ParserInternalState state, bool mustSucceed) + { + if (codedInputStream != null) + { + return RefillFromCodedInputStream(ref buffer, ref state, mustSucceed); + } + else + { + return RefillFromReadOnlySequence(ref buffer, ref state, mustSucceed); + } + } + + public int? TotalLength => totalLength; + + public CodedInputStream CodedInputStream => codedInputStream; + + /// + /// Sets currentLimit to (current position) + byteLimit. This is called + /// when descending into a length-delimited embedded message. The previous + /// limit is returned. + /// + /// The old limit. + public static int PushLimit(ref ParserInternalState state, int byteLimit) + { + if (byteLimit < 0) + { + throw InvalidProtocolBufferException.NegativeSize(); + } + byteLimit += state.totalBytesRetired + state.bufferPos; + int oldLimit = state.currentLimit; + if (byteLimit > oldLimit) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + state.currentLimit = byteLimit; + + RecomputeBufferSizeAfterLimit(ref state); + + return oldLimit; + } + + /// + /// Discards the current limit, returning the previous limit. + /// + public static void PopLimit(ref ParserInternalState state, int oldLimit) + { + state.currentLimit = oldLimit; + RecomputeBufferSizeAfterLimit(ref state); + } + + /// + /// Returns whether or not all the data before the limit has been read. + /// + /// + public static bool IsReachedLimit(ref ParserInternalState state) + { + if (state.currentLimit == int.MaxValue) + { + return false; + } + int currentAbsolutePosition = state.totalBytesRetired + state.bufferPos; + return currentAbsolutePosition >= state.currentLimit; + } + + /// + /// Returns true if the stream has reached the end of the input. This is the + /// case if either the end of the underlying input source has been reached or + /// the stream has reached a limit created using PushLimit. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsAtEnd(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + return state.bufferPos == state.bufferSize && !state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, false); + } + + private bool RefillFromReadOnlySequence(ref ReadOnlySpan buffer, ref ParserInternalState state, bool mustSucceed) + { + CheckCurrentBufferIsEmpty(ref state); + + if (state.totalBytesRetired + state.bufferSize == state.currentLimit) + { + // Oops, we hit a limit. + if (mustSucceed) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + else + { + return false; + } + } + + state.totalBytesRetired += state.bufferSize; + + state.bufferPos = 0; + state.bufferSize = 0; + while (readOnlySequenceEnumerator.MoveNext()) + { + buffer = readOnlySequenceEnumerator.Current.Span; + state.bufferSize = buffer.Length; + if (buffer.Length != 0) + { + break; + } + } + + if (state.bufferSize == 0) + { + if (mustSucceed) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + else + { + return false; + } + } + else + { + RecomputeBufferSizeAfterLimit(ref state); + int totalBytesRead = + state.totalBytesRetired + state.bufferSize + state.bufferSizeAfterLimit; + if (totalBytesRead < 0 || totalBytesRead > state.sizeLimit) + { + throw InvalidProtocolBufferException.SizeLimitExceeded(); + } + return true; + } + } + + private bool RefillFromCodedInputStream(ref ReadOnlySpan buffer, ref ParserInternalState state, bool mustSucceed) + { + CheckCurrentBufferIsEmpty(ref state); + + if (state.totalBytesRetired + state.bufferSize == state.currentLimit) + { + // Oops, we hit a limit. + if (mustSucceed) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + else + { + return false; + } + } + + Stream input = codedInputStream.InternalInputStream; + + state.totalBytesRetired += state.bufferSize; + + state.bufferPos = 0; + state.bufferSize = (input == null) ? 0 : input.Read(codedInputStream.InternalBuffer, 0, buffer.Length); + if (state.bufferSize < 0) + { + throw new InvalidOperationException("Stream.Read returned a negative count"); + } + if (state.bufferSize == 0) + { + if (mustSucceed) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + else + { + return false; + } + } + else + { + RecomputeBufferSizeAfterLimit(ref state); + int totalBytesRead = + state.totalBytesRetired + state.bufferSize + state.bufferSizeAfterLimit; + if (totalBytesRead < 0 || totalBytesRead > state.sizeLimit) + { + throw InvalidProtocolBufferException.SizeLimitExceeded(); + } + return true; + } + } + + private static void RecomputeBufferSizeAfterLimit(ref ParserInternalState state) + { + state.bufferSize += state.bufferSizeAfterLimit; + int bufferEnd = state.totalBytesRetired + state.bufferSize; + if (bufferEnd > state.currentLimit) + { + // Limit is in current buffer. + state.bufferSizeAfterLimit = bufferEnd - state.currentLimit; + state.bufferSize -= state.bufferSizeAfterLimit; + } + else + { + state.bufferSizeAfterLimit = 0; + } + } + + private static void CheckCurrentBufferIsEmpty(ref ParserInternalState state) + { + if (state.bufferPos < state.bufferSize) + { + throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty."); + } + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/UnknownField.cs b/csharp/src/Google.Protobuf/UnknownField.cs new file mode 100644 index 0000000000000..4793a6419d961 --- /dev/null +++ b/csharp/src/Google.Protobuf/UnknownField.cs @@ -0,0 +1,290 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2017 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Google.Protobuf.Collections; + +namespace Google.Protobuf +{ + /// + /// Represents a single field in an UnknownFieldSet. + /// + /// An UnknownField consists of four lists of values. The lists correspond + /// to the four "wire types" used in the protocol buffer binary format. + /// Normally, only one of the four lists will contain any values, since it + /// is impossible to define a valid message type that declares two different + /// types for the same field number. However, the code is designed to allow + /// for the case where the same unknown field number is encountered using + /// multiple different wire types. + /// + /// + internal sealed class UnknownField + { + private List varintList; + private List fixed32List; + private List fixed64List; + private List lengthDelimitedList; + private List groupList; + + /// + /// Creates a new UnknownField. + /// + public UnknownField() + { + } + + /// + /// Checks if two unknown field are equal. + /// + public override bool Equals(object other) + { + if (ReferenceEquals(this, other)) + { + return true; + } + UnknownField otherField = other as UnknownField; + return otherField != null + && Lists.Equals(varintList, otherField.varintList) + && Lists.Equals(fixed32List, otherField.fixed32List) + && Lists.Equals(fixed64List, otherField.fixed64List) + && Lists.Equals(lengthDelimitedList, otherField.lengthDelimitedList) + && Lists.Equals(groupList, otherField.groupList); + } + + /// + /// Get the hash code of the unknown field. + /// + public override int GetHashCode() + { + int hash = 43; + hash = hash * 47 + Lists.GetHashCode(varintList); + hash = hash * 47 + Lists.GetHashCode(fixed32List); + hash = hash * 47 + Lists.GetHashCode(fixed64List); + hash = hash * 47 + Lists.GetHashCode(lengthDelimitedList); + hash = hash * 47 + Lists.GetHashCode(groupList); + return hash; + } + + /// + /// Serializes the field, including the field number, and writes it to + /// + /// + /// The unknown field number. + /// The write context to write to. + internal void WriteTo(int fieldNumber, ref WriteContext output) + { + if (varintList != null) + { + foreach (ulong value in varintList) + { + output.WriteTag(fieldNumber, WireFormat.WireType.Varint); + output.WriteUInt64(value); + } + } + if (fixed32List != null) + { + foreach (uint value in fixed32List) + { + output.WriteTag(fieldNumber, WireFormat.WireType.Fixed32); + output.WriteFixed32(value); + } + } + if (fixed64List != null) + { + foreach (ulong value in fixed64List) + { + output.WriteTag(fieldNumber, WireFormat.WireType.Fixed64); + output.WriteFixed64(value); + } + } + if (lengthDelimitedList != null) + { + foreach (ByteString value in lengthDelimitedList) + { + output.WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); + output.WriteBytes(value); + } + } + if (groupList != null) + { + foreach (UnknownFieldSet value in groupList) + { + output.WriteTag(fieldNumber, WireFormat.WireType.StartGroup); + value.WriteTo(ref output); + output.WriteTag(fieldNumber, WireFormat.WireType.EndGroup); + } + } + } + + /// + /// Computes the number of bytes required to encode this field, including field + /// number. + /// + internal int GetSerializedSize(int fieldNumber) + { + int result = 0; + if (varintList != null) + { + result += CodedOutputStream.ComputeTagSize(fieldNumber) * varintList.Count; + foreach (ulong value in varintList) + { + result += CodedOutputStream.ComputeUInt64Size(value); + } + } + if (fixed32List != null) + { + result += CodedOutputStream.ComputeTagSize(fieldNumber) * fixed32List.Count; + result += CodedOutputStream.ComputeFixed32Size(1) * fixed32List.Count; + } + if (fixed64List != null) + { + result += CodedOutputStream.ComputeTagSize(fieldNumber) * fixed64List.Count; + result += CodedOutputStream.ComputeFixed64Size(1) * fixed64List.Count; + } + if (lengthDelimitedList != null) + { + result += CodedOutputStream.ComputeTagSize(fieldNumber) * lengthDelimitedList.Count; + foreach (ByteString value in lengthDelimitedList) + { + result += CodedOutputStream.ComputeBytesSize(value); + } + } + if (groupList != null) + { + result += CodedOutputStream.ComputeTagSize(fieldNumber) * 2 * groupList.Count; + foreach (UnknownFieldSet value in groupList) + { + result += value.CalculateSize(); + } + } + return result; + } + + /// + /// Merge the values in into this field. For each list + /// of values, 's values are append to the ones in this + /// field. + /// + internal UnknownField MergeFrom(UnknownField other) + { + varintList = AddAll(varintList, other.varintList); + fixed32List = AddAll(fixed32List, other.fixed32List); + fixed64List = AddAll(fixed64List, other.fixed64List); + lengthDelimitedList = AddAll(lengthDelimitedList, other.lengthDelimitedList); + groupList = AddAll(groupList, other.groupList); + return this; + } + + /// + /// Returns a new list containing all of the given specified values from + /// both the and lists. + /// If is null and is null or empty, + /// null is returned. Otherwise, either a new list is created (if + /// is null) or the elements of are added to . + /// + private static List AddAll(List current, IList extras) + { + if (extras == null || extras.Count == 0) + { + return current; + } + if (current == null) + { + current = new List(extras); + } + else + { + current.AddRange(extras); + } + return current; + } + + /// + /// Adds a varint value. + /// + internal UnknownField AddVarint(ulong value) + { + varintList = Add(varintList, value); + return this; + } + + /// + /// Adds a fixed32 value. + /// + internal UnknownField AddFixed32(uint value) + { + fixed32List = Add(fixed32List, value); + return this; + } + + /// + /// Adds a fixed64 value. + /// + internal UnknownField AddFixed64(ulong value) + { + fixed64List = Add(fixed64List, value); + return this; + } + + /// + /// Adds a length-delimited value. + /// + internal UnknownField AddLengthDelimited(ByteString value) + { + lengthDelimitedList = Add(lengthDelimitedList, value); + return this; + } + + internal UnknownField AddGroup(UnknownFieldSet value) + { + groupList = Add(groupList, value); + return this; + } + + /// + /// Adds to the , creating + /// a new list if is null. The list is returned - either + /// the original reference or the new list. + /// + private static List Add(List list, T value) + { + if (list == null) + { + list = new List(); + } + list.Add(value); + return list; + } + } +} diff --git a/csharp/src/Google.Protobuf/UnknownFieldSet.cs b/csharp/src/Google.Protobuf/UnknownFieldSet.cs new file mode 100644 index 0000000000000..9888dd1c3d09c --- /dev/null +++ b/csharp/src/Google.Protobuf/UnknownFieldSet.cs @@ -0,0 +1,393 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Security; +using Google.Protobuf.Reflection; + +namespace Google.Protobuf +{ + /// + /// Used to keep track of fields which were seen when parsing a protocol message + /// but whose field numbers or types are unrecognized. This most frequently + /// occurs when new fields are added to a message type and then messages containing + /// those fields are read by old software that was built before the new types were + /// added. + /// + /// Most users will never need to use this class directly. + /// + public sealed partial class UnknownFieldSet + { + private readonly IDictionary fields; + + /// + /// Creates a new UnknownFieldSet. + /// + internal UnknownFieldSet() + { + this.fields = new Dictionary(); + } + + /// + /// Checks whether or not the given field number is present in the set. + /// + internal bool HasField(int field) + { + return fields.ContainsKey(field); + } + + /// + /// Serializes the set and writes it to . + /// + public void WriteTo(CodedOutputStream output) + { + WriteContext.Initialize(output, out WriteContext ctx); + try + { + WriteTo(ref ctx); + } + finally + { + ctx.CopyStateTo(output); + } + } + + /// + /// Serializes the set and writes it to . + /// + [SecuritySafeCritical] + public void WriteTo(ref WriteContext ctx) + { + foreach (KeyValuePair entry in fields) + { + entry.Value.WriteTo(entry.Key, ref ctx); + } + } + + /// + /// Gets the number of bytes required to encode this set. + /// + public int CalculateSize() + { + int result = 0; + foreach (KeyValuePair entry in fields) + { + result += entry.Value.GetSerializedSize(entry.Key); + } + return result; + } + + /// + /// Checks if two unknown field sets are equal. + /// + public override bool Equals(object other) + { + if (ReferenceEquals(this, other)) + { + return true; + } + UnknownFieldSet otherSet = other as UnknownFieldSet; + IDictionary otherFields = otherSet.fields; + if (fields.Count != otherFields.Count) + { + return false; + } + foreach (KeyValuePair leftEntry in fields) + { + UnknownField rightValue; + if (!otherFields.TryGetValue(leftEntry.Key, out rightValue)) + { + return false; + } + if (!leftEntry.Value.Equals(rightValue)) + { + return false; + } + } + return true; + } + + /// + /// Gets the unknown field set's hash code. + /// + public override int GetHashCode() + { + int ret = 1; + foreach (KeyValuePair field in fields) + { + // Use ^ here to make the field order irrelevant. + int hash = field.Key.GetHashCode() ^ field.Value.GetHashCode(); + ret ^= hash; + } + return ret; + } + + // Optimization: We keep around the last field that was + // modified so that we can efficiently add to it multiple times in a + // row (important when parsing an unknown repeated field). + private int lastFieldNumber; + private UnknownField lastField; + + private UnknownField GetOrAddField(int number) + { + if (lastField != null && number == lastFieldNumber) + { + return lastField; + } + if (number == 0) + { + return null; + } + + UnknownField existing; + if (fields.TryGetValue(number, out existing)) + { + return existing; + } + lastField = new UnknownField(); + AddOrReplaceField(number, lastField); + lastFieldNumber = number; + return lastField; + } + + /// + /// Adds a field to the set. If a field with the same number already exists, it + /// is replaced. + /// + internal UnknownFieldSet AddOrReplaceField(int number, UnknownField field) + { + if (number == 0) + { + throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number."); + } + fields[number] = field; + return this; + } + + /// + /// Parse a single field from and merge it + /// into this set. + /// + /// The parse context from which to read the field + /// false if the tag is an "end group" tag, true otherwise + private bool MergeFieldFrom(ref ParseContext ctx) + { + uint tag = ctx.LastTag; + int number = WireFormat.GetTagFieldNumber(tag); + switch (WireFormat.GetTagWireType(tag)) + { + case WireFormat.WireType.Varint: + { + ulong uint64 = ctx.ReadUInt64(); + GetOrAddField(number).AddVarint(uint64); + return true; + } + case WireFormat.WireType.Fixed32: + { + uint uint32 = ctx.ReadFixed32(); + GetOrAddField(number).AddFixed32(uint32); + return true; + } + case WireFormat.WireType.Fixed64: + { + ulong uint64 = ctx.ReadFixed64(); + GetOrAddField(number).AddFixed64(uint64); + return true; + } + case WireFormat.WireType.LengthDelimited: + { + ByteString bytes = ctx.ReadBytes(); + GetOrAddField(number).AddLengthDelimited(bytes); + return true; + } + case WireFormat.WireType.StartGroup: + { + UnknownFieldSet set = new UnknownFieldSet(); + ParsingPrimitivesMessages.ReadGroup(ref ctx, number, set); + GetOrAddField(number).AddGroup(set); + return true; + } + case WireFormat.WireType.EndGroup: + { + return false; + } + default: + throw InvalidProtocolBufferException.InvalidWireType(); + } + } + + internal void MergeGroupFrom(ref ParseContext ctx) + { + while (true) + { + uint tag = ctx.ReadTag(); + if (tag == 0) + { + break; + } + if (!MergeFieldFrom(ref ctx)) + { + break; + } + } + } + + /// + /// Create a new UnknownFieldSet if unknownFields is null. + /// Parse a single field from and merge it + /// into unknownFields. If is configured to discard unknown fields, + /// will be returned as-is and the field will be skipped. + /// + /// The UnknownFieldSet which need to be merged + /// The coded input stream containing the field + /// The merged UnknownFieldSet + public static UnknownFieldSet MergeFieldFrom(UnknownFieldSet unknownFields, + CodedInputStream input) + { + ParseContext.Initialize(input, out ParseContext ctx); + try + { + return MergeFieldFrom(unknownFields, ref ctx); + } + finally + { + ctx.CopyStateTo(input); + } + } + + /// + /// Create a new UnknownFieldSet if unknownFields is null. + /// Parse a single field from and merge it + /// into unknownFields. If is configured to discard unknown fields, + /// will be returned as-is and the field will be skipped. + /// + /// The UnknownFieldSet which need to be merged + /// The parse context from which to read the field + /// The merged UnknownFieldSet + [SecuritySafeCritical] + public static UnknownFieldSet MergeFieldFrom(UnknownFieldSet unknownFields, + ref ParseContext ctx) + { + if (ctx.DiscardUnknownFields) + { + ParsingPrimitivesMessages.SkipLastField(ref ctx.buffer, ref ctx.state); + return unknownFields; + } + if (unknownFields == null) + { + unknownFields = new UnknownFieldSet(); + } + if (!unknownFields.MergeFieldFrom(ref ctx)) + { + throw new InvalidProtocolBufferException("Merge an unknown field of end-group tag, indicating that the corresponding start-group was missing."); // match the old code-gen + } + return unknownFields; + } + + /// + /// Merges the fields from into this set. + /// If a field number exists in both sets, the values in + /// will be appended to the values in this set. + /// + private UnknownFieldSet MergeFrom(UnknownFieldSet other) + { + if (other != null) + { + foreach (KeyValuePair entry in other.fields) + { + MergeField(entry.Key, entry.Value); + } + } + return this; + } + + /// + /// Created a new UnknownFieldSet to if + /// needed and merges the fields from into the first set. + /// If a field number exists in both sets, the values in + /// will be appended to the values in this set. + /// + public static UnknownFieldSet MergeFrom(UnknownFieldSet unknownFields, + UnknownFieldSet other) + { + if (other == null) + { + return unknownFields; + } + if (unknownFields == null) + { + unknownFields = new UnknownFieldSet(); + } + unknownFields.MergeFrom(other); + return unknownFields; + } + + + /// + /// Adds a field to the unknown field set. If a field with the same + /// number already exists, the two are merged. + /// + private UnknownFieldSet MergeField(int number, UnknownField field) + { + if (number == 0) + { + throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number."); + } + if (HasField(number)) + { + GetOrAddField(number).MergeFrom(field); + } + else + { + AddOrReplaceField(number, field); + } + return this; + } + + /// + /// Clone an unknown field set from . + /// + public static UnknownFieldSet Clone(UnknownFieldSet other) + { + if (other == null) + { + return null; + } + UnknownFieldSet unknownFields = new UnknownFieldSet(); + unknownFields.MergeFrom(other); + return unknownFields; + } + } +} + diff --git a/csharp/src/Google.Protobuf/UnsafeByteOperations.cs b/csharp/src/Google.Protobuf/UnsafeByteOperations.cs new file mode 100644 index 0000000000000..865ea067b8c81 --- /dev/null +++ b/csharp/src/Google.Protobuf/UnsafeByteOperations.cs @@ -0,0 +1,81 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Security; + +namespace Google.Protobuf +{ + /// + /// Provides a number of unsafe byte operations to be used by advanced applications with high performance + /// requirements. These methods are referred to as "unsafe" due to the fact that they potentially expose + /// the backing buffer of a to the application. + /// + /// + /// + /// The methods in this class should only be called if it is guaranteed that the buffer backing the + /// will never change! Mutation of a can lead to unexpected + /// and undesirable consequences in your application, and will likely be difficult to debug. Proceed with caution! + /// + /// + /// This can have a number of significant side affects that have spooky-action-at-a-distance-like behavior. In + /// particular, if the bytes value changes out from under a Protocol Buffer: + /// + /// + /// + /// serialization may throw + /// + /// + /// serialization may succeed but the wrong bytes may be written out + /// + /// + /// objects that are normally immutable (such as ByteString) are no longer immutable + /// + /// + /// hashCode may be incorrect + /// + /// + /// + [SecuritySafeCritical] + public static class UnsafeByteOperations + { + /// + /// Constructs a new from the given bytes. The bytes are not copied, + /// and must not be modified while the is in use. + /// This API is experimental and subject to change. + /// + public static ByteString UnsafeWrap(ReadOnlyMemory bytes) + { + return ByteString.AttachBytes(bytes); + } + } +} diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs index 5b39b80906e87..60ae03da942f4 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs @@ -1,5 +1,7 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/any.proto +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/any.proto +// #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -23,14 +25,14 @@ static AnyReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "Chlnb29nbGUvcHJvdG9idWYvYW55LnByb3RvEg9nb29nbGUucHJvdG9idWYi", - "JgoDQW55EhAKCHR5cGVfdXJsGAEgASgJEg0KBXZhbHVlGAIgASgMQm8KE2Nv", - "bS5nb29nbGUucHJvdG9idWZCCEFueVByb3RvUAFaJWdpdGh1Yi5jb20vZ29s", - "YW5nL3Byb3RvYnVmL3B0eXBlcy9hbnmiAgNHUEKqAh5Hb29nbGUuUHJvdG9i", - "dWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw==")); + "JgoDQW55EhAKCHR5cGVfdXJsGAEgASgJEg0KBXZhbHVlGAIgASgMQnYKE2Nv", + "bS5nb29nbGUucHJvdG9idWZCCEFueVByb3RvUAFaLGdvb2dsZS5nb2xhbmcu", + "b3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL2FueXBiogIDR1BCqgIeR29vZ2xl", + "LlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Any), global::Google.Protobuf.WellKnownTypes.Any.Parser, new[]{ "TypeUrl", "Value" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Any), global::Google.Protobuf.WellKnownTypes.Any.Parser, new[]{ "TypeUrl", "Value" }, null, null, null, null) })); } #endregion @@ -76,10 +78,13 @@ static AnyReflection() { /// Example 4: Pack and unpack a message in Go /// /// foo := &pb.Foo{...} - /// any, err := ptypes.MarshalAny(foo) + /// any, err := anypb.New(foo) + /// if err != nil { + /// ... + /// } /// ... /// foo := &pb.Foo{} - /// if err := ptypes.UnmarshalAny(any, foo); err != nil { + /// if err := any.UnmarshalTo(foo); err != nil { /// ... /// } /// @@ -117,8 +122,13 @@ static AnyReflection() { /// "value": "1.212s" /// } /// - public sealed partial class Any : pb::IMessage { + public sealed partial class Any : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Any()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -143,6 +153,7 @@ public Any() { public Any(Any other) : this() { typeUrl_ = other.typeUrl_; value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -154,17 +165,19 @@ public Any Clone() { public const int TypeUrlFieldNumber = 1; private string typeUrl_ = ""; /// - /// A URL/resource name whose content describes the type of the - /// serialized protocol buffer message. + /// A URL/resource name that uniquely identifies the type of the serialized + /// protocol buffer message. This string must contain at least + /// one "/" character. The last segment of the URL's path must represent + /// the fully qualified name of the type (as in + /// `path/google.protobuf.Duration`). The name should be in a canonical form + /// (e.g., leading "." is not accepted). /// - /// For URLs which use the scheme `http`, `https`, or no scheme, the - /// following restrictions and interpretations apply: + /// In practice, teams usually precompile into the binary all types that they + /// expect it to use in the context of Any. However, for URLs which use the + /// scheme `http`, `https`, or no scheme, one can optionally set up a type + /// server that maps type URLs to message definitions as follows: /// /// * If no scheme is provided, `https` is assumed. - /// * The last segment of the URL's path must represent the fully - /// qualified name of the type (as in `path/google.protobuf.Duration`). - /// The name should be in a canonical form (e.g., leading "." is - /// not accepted). /// * An HTTP GET on the URL must yield a [google.protobuf.Type][] /// value in binary format, or produce an error. /// * Applications are allowed to cache lookup results based on the @@ -173,6 +186,10 @@ public Any Clone() { /// on changes to types. (Use versioned type names to manage /// breaking changes.) /// + /// Note: this functionality is not currently available in the official + /// protobuf release, and it is not used for type URLs beginning with + /// type.googleapis.com. + /// /// Schemes other than `http`, `https` (or the empty scheme) might be /// used with implementation specific semantics. /// @@ -213,7 +230,7 @@ public bool Equals(Any other) { } if (TypeUrl != other.TypeUrl) return false; if (Value != other.Value) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -221,6 +238,9 @@ public override int GetHashCode() { int hash = 1; if (TypeUrl.Length != 0) hash ^= TypeUrl.GetHashCode(); if (Value.Length != 0) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -231,6 +251,26 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (TypeUrl.Length != 0) { + output.WriteRawTag(10); + output.WriteString(TypeUrl); + } + if (Value.Length != 0) { + output.WriteRawTag(18); + output.WriteBytes(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (TypeUrl.Length != 0) { output.WriteRawTag(10); output.WriteString(TypeUrl); @@ -239,7 +279,11 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(18); output.WriteBytes(Value); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -250,6 +294,9 @@ public int CalculateSize() { if (Value.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeBytesSize(Value); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -264,15 +311,41 @@ public void MergeFrom(Any other) { if (other.Value.Length != 0) { Value = other.Value; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + TypeUrl = input.ReadString(); + break; + } + case 18: { + Value = input.ReadBytes(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { TypeUrl = input.ReadString(); @@ -285,6 +358,7 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs index fca689dc08d54..49f259982acbc 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs @@ -49,7 +49,7 @@ private static string GetTypeUrl(MessageDescriptor descriptor, string prefix) => /// /// /// - /// This is always just the last part of the URL, after the final slash. No validation of + /// This is always just the last part of the URL, after the final slash. No validation of /// anything before the trailing slash is performed. If the type URL does not include a slash, /// an empty string is returned rather than an exception being thrown; this won't match any types, /// and the calling code is probably in a better position to give a meaningful error. @@ -67,6 +67,17 @@ public static string GetTypeName(string typeUrl) return lastSlash == -1 ? "" : typeUrl.Substring(lastSlash + 1); } + /// + /// Returns a bool indictating whether this Any message is of the target message type + /// + /// The descriptor of the message type + /// true if the type name matches the descriptor's full name or false otherwise + public bool Is(MessageDescriptor descriptor) + { + ProtoPreconditions.CheckNotNull(descriptor, nameof(descriptor)); + return GetTypeName(TypeUrl) == descriptor.FullName; + } + /// /// Unpacks the content of this Any message into the target message type, /// which must match the type URL within this Any message. diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs index 6705e092e5985..7c65ac761d672 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs @@ -1,5 +1,7 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/api.proto +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/api.proto +// #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -35,16 +37,16 @@ static ApiReflection() { "ChFyZXNwb25zZV90eXBlX3VybBgEIAEoCRIaChJyZXNwb25zZV9zdHJlYW1p", "bmcYBSABKAgSKAoHb3B0aW9ucxgGIAMoCzIXLmdvb2dsZS5wcm90b2J1Zi5P", "cHRpb24SJwoGc3ludGF4GAcgASgOMhcuZ29vZ2xlLnByb3RvYnVmLlN5bnRh", - "eCIjCgVNaXhpbhIMCgRuYW1lGAEgASgJEgwKBHJvb3QYAiABKAlCdQoTY29t", - "Lmdvb2dsZS5wcm90b2J1ZkIIQXBpUHJvdG9QAVorZ29vZ2xlLmdvbGFuZy5v", - "cmcvZ2VucHJvdG8vcHJvdG9idWYvYXBpO2FwaaICA0dQQqoCHkdvb2dsZS5Q", - "cm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJvdG8z")); + "eCIjCgVNaXhpbhIMCgRuYW1lGAEgASgJEgwKBHJvb3QYAiABKAlCdgoTY29t", + "Lmdvb2dsZS5wcm90b2J1ZkIIQXBpUHJvdG9QAVosZ29vZ2xlLmdvbGFuZy5v", + "cmcvcHJvdG9idWYvdHlwZXMva25vd24vYXBpcGKiAgNHUEKqAh5Hb29nbGUu", + "UHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor, }, - new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Api), global::Google.Protobuf.WellKnownTypes.Api.Parser, new[]{ "Name", "Methods", "Options", "Version", "SourceContext", "Mixins", "Syntax" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Method), global::Google.Protobuf.WellKnownTypes.Method.Parser, new[]{ "Name", "RequestTypeUrl", "RequestStreaming", "ResponseTypeUrl", "ResponseStreaming", "Options", "Syntax" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Mixin), global::Google.Protobuf.WellKnownTypes.Mixin.Parser, new[]{ "Name", "Root" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Api), global::Google.Protobuf.WellKnownTypes.Api.Parser, new[]{ "Name", "Methods", "Options", "Version", "SourceContext", "Mixins", "Syntax" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Method), global::Google.Protobuf.WellKnownTypes.Method.Parser, new[]{ "Name", "RequestTypeUrl", "RequestStreaming", "ResponseTypeUrl", "ResponseStreaming", "Options", "Syntax" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Mixin), global::Google.Protobuf.WellKnownTypes.Mixin.Parser, new[]{ "Name", "Root" }, null, null, null, null) })); } #endregion @@ -62,8 +64,13 @@ static ApiReflection() { /// this message itself. See https://cloud.google.com/apis/design/glossary for /// detailed terminology. /// - public sealed partial class Api : pb::IMessage { + public sealed partial class Api : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Api()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -90,9 +97,10 @@ public Api(Api other) : this() { methods_ = other.methods_.Clone(); options_ = other.options_.Clone(); version_ = other.version_; - SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null; + sourceContext_ = other.sourceContext_ != null ? other.sourceContext_.Clone() : null; mixins_ = other.mixins_.Clone(); syntax_ = other.syntax_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -203,7 +211,7 @@ public string Version { /// Field number for the "syntax" field. public const int SyntaxFieldNumber = 7; - private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = 0; + private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = global::Google.Protobuf.WellKnownTypes.Syntax.Proto2; /// /// The source syntax of the service. /// @@ -235,7 +243,7 @@ public bool Equals(Api other) { if (!object.Equals(SourceContext, other.SourceContext)) return false; if(!mixins_.Equals(other.mixins_)) return false; if (Syntax != other.Syntax) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -247,7 +255,10 @@ public override int GetHashCode() { if (Version.Length != 0) hash ^= Version.GetHashCode(); if (sourceContext_ != null) hash ^= SourceContext.GetHashCode(); hash ^= mixins_.GetHashCode(); - if (Syntax != 0) hash ^= Syntax.GetHashCode(); + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) hash ^= Syntax.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -258,6 +269,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -273,12 +287,44 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteMessage(SourceContext); } mixins_.WriteTo(output, _repeated_mixins_codec); - if (Syntax != 0) { + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { output.WriteRawTag(56); output.WriteEnum((int) Syntax); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + methods_.WriteTo(ref output, _repeated_methods_codec); + options_.WriteTo(ref output, _repeated_options_codec); + if (Version.Length != 0) { + output.WriteRawTag(34); + output.WriteString(Version); + } + if (sourceContext_ != null) { + output.WriteRawTag(42); + output.WriteMessage(SourceContext); + } + mixins_.WriteTo(ref output, _repeated_mixins_codec); + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { + output.WriteRawTag(56); + output.WriteEnum((int) Syntax); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -294,9 +340,12 @@ public int CalculateSize() { size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContext); } size += mixins_.CalculateSize(_repeated_mixins_codec); - if (Syntax != 0) { + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -315,23 +364,27 @@ public void MergeFrom(Api other) { } if (other.sourceContext_ != null) { if (sourceContext_ == null) { - sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext(); + SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext(); } SourceContext.MergeFrom(other.SourceContext); } mixins_.Add(other.mixins_); - if (other.Syntax != 0) { + if (other.Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { Syntax = other.Syntax; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { Name = input.ReadString(); @@ -351,9 +404,9 @@ public void MergeFrom(pb::CodedInputStream input) { } case 42: { if (sourceContext_ == null) { - sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext(); + SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext(); } - input.ReadMessage(sourceContext_); + input.ReadMessage(SourceContext); break; } case 50: { @@ -361,20 +414,71 @@ public void MergeFrom(pb::CodedInputStream input) { break; } case 56: { - syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum(); + Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + methods_.AddEntriesFrom(ref input, _repeated_methods_codec); + break; + } + case 26: { + options_.AddEntriesFrom(ref input, _repeated_options_codec); + break; + } + case 34: { + Version = input.ReadString(); + break; + } + case 42: { + if (sourceContext_ == null) { + SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext(); + } + input.ReadMessage(SourceContext); + break; + } + case 50: { + mixins_.AddEntriesFrom(ref input, _repeated_mixins_codec); + break; + } + case 56: { + Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum(); break; } } } } + #endif } /// /// Method represents a method of an API interface. /// - public sealed partial class Method : pb::IMessage { + public sealed partial class Method : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Method()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -404,6 +508,7 @@ public Method(Method other) : this() { responseStreaming_ = other.responseStreaming_; options_ = other.options_.Clone(); syntax_ = other.syntax_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -496,7 +601,7 @@ public bool ResponseStreaming { /// Field number for the "syntax" field. public const int SyntaxFieldNumber = 7; - private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = 0; + private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = global::Google.Protobuf.WellKnownTypes.Syntax.Proto2; /// /// The source syntax of this method. /// @@ -528,7 +633,7 @@ public bool Equals(Method other) { if (ResponseStreaming != other.ResponseStreaming) return false; if(!options_.Equals(other.options_)) return false; if (Syntax != other.Syntax) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -540,7 +645,10 @@ public override int GetHashCode() { if (ResponseTypeUrl.Length != 0) hash ^= ResponseTypeUrl.GetHashCode(); if (ResponseStreaming != false) hash ^= ResponseStreaming.GetHashCode(); hash ^= options_.GetHashCode(); - if (Syntax != 0) hash ^= Syntax.GetHashCode(); + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) hash ^= Syntax.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -551,6 +659,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -572,11 +683,49 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteBool(ResponseStreaming); } options_.WriteTo(output, _repeated_options_codec); - if (Syntax != 0) { + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { + output.WriteRawTag(56); + output.WriteEnum((int) Syntax); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (RequestTypeUrl.Length != 0) { + output.WriteRawTag(18); + output.WriteString(RequestTypeUrl); + } + if (RequestStreaming != false) { + output.WriteRawTag(24); + output.WriteBool(RequestStreaming); + } + if (ResponseTypeUrl.Length != 0) { + output.WriteRawTag(34); + output.WriteString(ResponseTypeUrl); + } + if (ResponseStreaming != false) { + output.WriteRawTag(40); + output.WriteBool(ResponseStreaming); + } + options_.WriteTo(ref output, _repeated_options_codec); + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { output.WriteRawTag(56); output.WriteEnum((int) Syntax); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -597,9 +746,12 @@ public int CalculateSize() { size += 1 + 1; } size += options_.CalculateSize(_repeated_options_codec); - if (Syntax != 0) { + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -624,18 +776,22 @@ public void MergeFrom(Method other) { ResponseStreaming = other.ResponseStreaming; } options_.Add(other.options_); - if (other.Syntax != 0) { + if (other.Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { Syntax = other.Syntax; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { Name = input.ReadString(); @@ -662,12 +818,55 @@ public void MergeFrom(pb::CodedInputStream input) { break; } case 56: { - syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum(); + Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + RequestTypeUrl = input.ReadString(); + break; + } + case 24: { + RequestStreaming = input.ReadBool(); + break; + } + case 34: { + ResponseTypeUrl = input.ReadString(); + break; + } + case 40: { + ResponseStreaming = input.ReadBool(); + break; + } + case 50: { + options_.AddEntriesFrom(ref input, _repeated_options_codec); + break; + } + case 56: { + Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum(); break; } } } } + #endif } @@ -719,7 +918,7 @@ public void MergeFrom(pb::CodedInputStream input) { /// The mixin construct implies that all methods in `AccessControl` are /// also declared with same name and request/response types in /// `Storage`. A documentation generator or annotation processor will - /// see the effective `Storage.GetAcl` method after inherting + /// see the effective `Storage.GetAcl` method after inheriting /// documentation and annotations as follows: /// /// service Storage { @@ -751,8 +950,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// ... /// } /// - public sealed partial class Mixin : pb::IMessage { + public sealed partial class Mixin : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Mixin()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -777,6 +981,7 @@ public Mixin() { public Mixin(Mixin other) : this() { name_ = other.name_; root_ = other.root_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -828,7 +1033,7 @@ public bool Equals(Mixin other) { } if (Name != other.Name) return false; if (Root != other.Root) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -836,6 +1041,9 @@ public override int GetHashCode() { int hash = 1; if (Name.Length != 0) hash ^= Name.GetHashCode(); if (Root.Length != 0) hash ^= Root.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -846,6 +1054,26 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (Root.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Root); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -854,7 +1082,11 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(18); output.WriteString(Root); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -865,6 +1097,9 @@ public int CalculateSize() { if (Root.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Root); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -879,15 +1114,41 @@ public void MergeFrom(Mixin other) { if (other.Root.Length != 0) { Root = other.Root; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + Root = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Name = input.ReadString(); @@ -900,6 +1161,7 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs index 94159cb84cad5..2a653a37547b1 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs @@ -1,5 +1,7 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/duration.proto +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/duration.proto +// #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -24,14 +26,14 @@ static DurationReflection() { string.Concat( "Ch5nb29nbGUvcHJvdG9idWYvZHVyYXRpb24ucHJvdG8SD2dvb2dsZS5wcm90", "b2J1ZiIqCghEdXJhdGlvbhIPCgdzZWNvbmRzGAEgASgDEg0KBW5hbm9zGAIg", - "ASgFQnwKE2NvbS5nb29nbGUucHJvdG9idWZCDUR1cmF0aW9uUHJvdG9QAVoq", - "Z2l0aHViLmNvbS9nb2xhbmcvcHJvdG9idWYvcHR5cGVzL2R1cmF0aW9u+AEB", - "ogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90", - "bzM=")); + "ASgFQoMBChNjb20uZ29vZ2xlLnByb3RvYnVmQg1EdXJhdGlvblByb3RvUAFa", + "MWdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL2R1cmF0", + "aW9ucGL4AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlw", + "ZXNiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Duration), global::Google.Protobuf.WellKnownTypes.Duration.Parser, new[]{ "Seconds", "Nanos" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Duration), global::Google.Protobuf.WellKnownTypes.Duration.Parser, new[]{ "Seconds", "Nanos" }, null, null, null, null) })); } #endregion @@ -60,7 +62,7 @@ static DurationReflection() { /// if (duration.seconds < 0 && duration.nanos > 0) { /// duration.seconds += 1; /// duration.nanos -= 1000000000; - /// } else if (durations.seconds > 0 && duration.nanos < 0) { + /// } else if (duration.seconds > 0 && duration.nanos < 0) { /// duration.seconds -= 1; /// duration.nanos += 1000000000; /// } @@ -98,8 +100,13 @@ static DurationReflection() { /// be expressed in JSON format as "3.000000001s", and 3 seconds and 1 /// microsecond should be expressed in JSON format as "3.000001s". /// - public sealed partial class Duration : pb::IMessage { + public sealed partial class Duration : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Duration()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -124,6 +131,7 @@ public Duration() { public Duration(Duration other) : this() { seconds_ = other.seconds_; nanos_ = other.nanos_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -181,7 +189,7 @@ public bool Equals(Duration other) { } if (Seconds != other.Seconds) return false; if (Nanos != other.Nanos) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -189,6 +197,9 @@ public override int GetHashCode() { int hash = 1; if (Seconds != 0L) hash ^= Seconds.GetHashCode(); if (Nanos != 0) hash ^= Nanos.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -199,6 +210,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Seconds != 0L) { output.WriteRawTag(8); output.WriteInt64(Seconds); @@ -207,8 +221,29 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(16); output.WriteInt32(Nanos); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Seconds != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Seconds); + } + if (Nanos != 0) { + output.WriteRawTag(16); + output.WriteInt32(Nanos); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -218,6 +253,9 @@ public int CalculateSize() { if (Nanos != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Nanos); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -232,15 +270,41 @@ public void MergeFrom(Duration other) { if (other.Nanos != 0) { Nanos = other.Nanos; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: { + Seconds = input.ReadInt64(); + break; + } + case 16: { + Nanos = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Seconds = input.ReadInt64(); @@ -253,6 +317,7 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs index f164bfd19d2e7..9a468fc1988c4 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs @@ -156,7 +156,7 @@ public static Duration FromTimeSpan(TimeSpan timeSpan) return Normalize(lhs.Seconds - rhs.Seconds, lhs.Nanos - rhs.Nanos); } } - + /// /// Creates a duration with the normalized values from the given number of seconds and /// nanoseconds, conforming with the description in the proto file. diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs index aa89e08f59292..e2e35182fd92d 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs @@ -1,5 +1,7 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/empty.proto +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/empty.proto +// #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -23,14 +25,14 @@ static EmptyReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "Chtnb29nbGUvcHJvdG9idWYvZW1wdHkucHJvdG8SD2dvb2dsZS5wcm90b2J1", - "ZiIHCgVFbXB0eUJ2ChNjb20uZ29vZ2xlLnByb3RvYnVmQgpFbXB0eVByb3Rv", - "UAFaJ2dpdGh1Yi5jb20vZ29sYW5nL3Byb3RvYnVmL3B0eXBlcy9lbXB0efgB", - "AaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJv", - "dG8z")); + "ZiIHCgVFbXB0eUJ9ChNjb20uZ29vZ2xlLnByb3RvYnVmQgpFbXB0eVByb3Rv", + "UAFaLmdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL2Vt", + "cHR5cGL4AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlw", + "ZXNiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Empty), global::Google.Protobuf.WellKnownTypes.Empty.Parser, null, null, null, null) + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Empty), global::Google.Protobuf.WellKnownTypes.Empty.Parser, null, null, null, null, null) })); } #endregion @@ -48,8 +50,13 @@ static EmptyReflection() { /// /// The JSON representation for `Empty` is empty JSON object `{}`. /// - public sealed partial class Empty : pb::IMessage { + public sealed partial class Empty : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Empty()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -72,6 +79,7 @@ public Empty() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Empty(Empty other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -92,12 +100,15 @@ public bool Equals(Empty other) { if (ReferenceEquals(other, this)) { return true; } - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -108,11 +119,30 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -121,19 +151,38 @@ public void MergeFrom(Empty other) { if (other == null) { return; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } } + #endif } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs index ef3bc10af7a91..d5da31441e3cb 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs @@ -1,5 +1,7 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/field_mask.proto +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/field_mask.proto +// #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -23,15 +25,14 @@ static FieldMaskReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "CiBnb29nbGUvcHJvdG9idWYvZmllbGRfbWFzay5wcm90bxIPZ29vZ2xlLnBy", - "b3RvYnVmIhoKCUZpZWxkTWFzaxINCgVwYXRocxgBIAMoCUKJAQoTY29tLmdv", - "b2dsZS5wcm90b2J1ZkIORmllbGRNYXNrUHJvdG9QAVo5Z29vZ2xlLmdvbGFu", - "Zy5vcmcvZ2VucHJvdG8vcHJvdG9idWYvZmllbGRfbWFzaztmaWVsZF9tYXNr", - "ogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90", - "bzM=")); + "b3RvYnVmIhoKCUZpZWxkTWFzaxINCgVwYXRocxgBIAMoCUKFAQoTY29tLmdv", + "b2dsZS5wcm90b2J1ZkIORmllbGRNYXNrUHJvdG9QAVoyZ29vZ2xlLmdvbGFu", + "Zy5vcmcvcHJvdG9idWYvdHlwZXMva25vd24vZmllbGRtYXNrcGL4AQGiAgNH", + "UEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.FieldMask), global::Google.Protobuf.WellKnownTypes.FieldMask.Parser, new[]{ "Paths" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.FieldMask), global::Google.Protobuf.WellKnownTypes.FieldMask.Parser, new[]{ "Paths" }, null, null, null, null) })); } #endregion @@ -106,57 +107,49 @@ static FieldMaskReflection() { /// describe the updated values, the API ignores the values of all /// fields not covered by the mask. /// - /// If a repeated field is specified for an update operation, the existing - /// repeated values in the target resource will be overwritten by the new values. - /// Note that a repeated field is only allowed in the last position of a `paths` - /// string. + /// If a repeated field is specified for an update operation, new values will + /// be appended to the existing repeated field in the target resource. Note that + /// a repeated field is only allowed in the last position of a `paths` string. /// /// If a sub-message is specified in the last position of the field mask for an - /// update operation, then the existing sub-message in the target resource is - /// overwritten. Given the target message: + /// update operation, then new value will be merged into the existing sub-message + /// in the target resource. + /// + /// For example, given the target message: /// /// f { /// b { - /// d : 1 - /// x : 2 + /// d: 1 + /// x: 2 /// } - /// c : 1 + /// c: [1] /// } /// /// And an update message: /// /// f { /// b { - /// d : 10 + /// d: 10 /// } + /// c: [2] /// } /// /// then if the field mask is: /// - /// paths: "f.b" + /// paths: ["f.b", "f.c"] /// /// then the result will be: /// /// f { /// b { - /// d : 10 + /// d: 10 + /// x: 2 /// } - /// c : 1 + /// c: [1, 2] /// } /// - /// However, if the update mask was: - /// - /// paths: "f.b.d" - /// - /// then the result would be: - /// - /// f { - /// b { - /// d : 10 - /// x : 2 - /// } - /// c : 1 - /// } + /// An implementation may provide options to override this default behavior for + /// repeated and message fields. /// /// In order to reset a field's value to the default, the field must /// be in the mask and set to the default value in the provided resource. @@ -239,9 +232,20 @@ static FieldMaskReflection() { /// /// Note that oneof type names ("test_oneof" in this case) cannot be used in /// paths. + /// + /// ## Field Mask Verification + /// + /// The implementation of any API method which has a FieldMask type field in the + /// request should verify the included field paths, and return an + /// `INVALID_ARGUMENT` error if any path is unmappable. /// - public sealed partial class FieldMask : pb::IMessage { + public sealed partial class FieldMask : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FieldMask()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -265,6 +269,7 @@ public FieldMask() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FieldMask(FieldMask other) : this() { paths_ = other.paths_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -299,13 +304,16 @@ public bool Equals(FieldMask other) { return true; } if(!paths_.Equals(other.paths_)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= paths_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -316,13 +324,33 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else paths_.WriteTo(output, _repeated_paths_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + paths_.WriteTo(ref output, _repeated_paths_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += paths_.CalculateSize(_repeated_paths_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -332,15 +360,19 @@ public void MergeFrom(FieldMask other) { return; } paths_.Add(other.paths_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { paths_.AddEntriesFrom(input, _repeated_paths_codec); @@ -348,7 +380,26 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + paths_.AddEntriesFrom(ref input, _repeated_paths_codec); + break; + } + } + } } + #endif } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs old mode 100755 new mode 100644 index 4b0670f6fd8ad..91d2ee9094ab3 --- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs @@ -35,15 +35,18 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; +using Google.Protobuf.Reflection; namespace Google.Protobuf.WellKnownTypes { // Manually-written partial class for the FieldMask well-known type. public partial class FieldMask : ICustomDiagnosticMessage { + private const char FIELD_PATH_SEPARATOR = ','; + private const char FIELD_SEPARATOR_REGEX = '.'; + /// - /// Converts a timestamp specified in seconds/nanoseconds to a string. + /// Converts a field mask specified by paths to a string. /// /// /// If the value is a normalized duration in the range described in field_mask.proto, @@ -55,7 +58,7 @@ public partial class FieldMask : ICustomDiagnosticMessage /// The represented field mask is invalid, and is false. internal static string ToJson(IList paths, bool diagnosticOnly) { - var firstInvalid = paths.FirstOrDefault(p => !ValidatePath(p)); + var firstInvalid = paths.FirstOrDefault(p => !IsPathValid(p)); if (firstInvalid == null) { var writer = new StringWriter(); @@ -84,11 +87,103 @@ internal static string ToJson(IList paths, bool diagnosticOnly) } } + /// + /// Returns a string representation of this for diagnostic purposes. + /// + /// + /// Normally the returned value will be a JSON string value (including leading and trailing quotes) but + /// when the value is non-normalized or out of range, a JSON object representation will be returned + /// instead, including a warning. This is to avoid exceptions being thrown when trying to + /// diagnose problems - the regular JSON formatter will still throw an exception for non-normalized + /// values. + /// + /// A string representation of this value. + public string ToDiagnosticString() + { + return ToJson(Paths, true); + } + + /// + /// Parses from a string to a FieldMask. + /// + public static FieldMask FromString(string value) + { + return FromStringEnumerable(new List(value.Split(FIELD_PATH_SEPARATOR))); + } + + /// + /// Parses from a string to a FieldMask and validates all field paths. + /// + /// The type to validate the field paths against. + public static FieldMask FromString(string value) where T : IMessage + { + return FromStringEnumerable(new List(value.Split(FIELD_PATH_SEPARATOR))); + } + + /// + /// Constructs a FieldMask for a list of field paths in a certain type. + /// + /// The type to validate the field paths against. + public static FieldMask FromStringEnumerable(IEnumerable paths) where T : IMessage + { + var mask = new FieldMask(); + foreach (var path in paths) + { + if (path.Length == 0) + { + // Ignore empty field paths. + continue; + } + + if (typeof(T) != typeof(Empty) + && !IsValid(path)) + { + throw new InvalidProtocolBufferException(path + " is not a valid path for " + typeof(T)); + } + + mask.Paths.Add(path); + } + + return mask; + } + + /// + /// Constructs a FieldMask from the passed field numbers. + /// + /// The type to validate the field paths against. + public static FieldMask FromFieldNumbers(params int[] fieldNumbers) where T : IMessage + { + return FromFieldNumbers((IEnumerable)fieldNumbers); + } + + /// + /// Constructs a FieldMask from the passed field numbers. + /// + /// The type to validate the field paths against. + public static FieldMask FromFieldNumbers(IEnumerable fieldNumbers) where T : IMessage + { + var descriptor = Activator.CreateInstance().Descriptor; + + var mask = new FieldMask(); + foreach (var fieldNumber in fieldNumbers) + { + var field = descriptor.FindFieldByNumber(fieldNumber); + if (field == null) + { + throw new ArgumentNullException($"{fieldNumber} is not a valid field number for {descriptor.Name}"); + } + + mask.Paths.Add(field.Name); + } + + return mask; + } + /// /// Checks whether the given path is valid for a field mask. /// /// true if the path is valid; false otherwise - private static bool ValidatePath(string input) + private static bool IsPathValid(string input) { for (int i = 0; i < input.Length; i++) { @@ -110,19 +205,166 @@ private static bool ValidatePath(string input) } /// - /// Returns a string representation of this for diagnostic purposes. + /// Checks whether paths in a given fields mask are valid. /// - /// - /// Normally the returned value will be a JSON string value (including leading and trailing quotes) but - /// when the value is non-normalized or out of range, a JSON object representation will be returned - /// instead, including a warning. This is to avoid exceptions being thrown when trying to - /// diagnose problems - the regular JSON formatter will still throw an exception for non-normalized - /// values. - /// - /// A string representation of this value. - public string ToDiagnosticString() + /// The type to validate the field paths against. + public static bool IsValid(FieldMask fieldMask) where T : IMessage { - return ToJson(Paths, true); + var descriptor = Activator.CreateInstance().Descriptor; + + return IsValid(descriptor, fieldMask); + } + + /// + /// Checks whether paths in a given fields mask are valid. + /// + public static bool IsValid(MessageDescriptor descriptor, FieldMask fieldMask) + { + foreach (var path in fieldMask.Paths) + { + if (!IsValid(descriptor, path)) + { + return false; + } + } + + return true; + } + + /// + /// Checks whether a given field path is valid. + /// + /// The type to validate the field paths against. + public static bool IsValid(string path) where T : IMessage + { + var descriptor = Activator.CreateInstance().Descriptor; + + return IsValid(descriptor, path); + } + + /// + /// Checks whether paths in a given fields mask are valid. + /// + public static bool IsValid(MessageDescriptor descriptor, string path) + { + var parts = path.Split(FIELD_SEPARATOR_REGEX); + if (parts.Length == 0) + { + return false; + } + + foreach (var name in parts) + { + var field = descriptor?.FindFieldByName(name); + if (field == null) + { + return false; + } + + if (!field.IsRepeated + && field.FieldType == FieldType.Message) + { + descriptor = field.MessageType; + } + else + { + descriptor = null; + } + } + + return true; + } + + /// + /// Converts this FieldMask to its canonical form. In the canonical form of a + /// FieldMask, all field paths are sorted alphabetically and redundant field + /// paths are removed. + /// + public FieldMask Normalize() + { + return new FieldMaskTree(this).ToFieldMask(); + } + + /// + /// Creates a union of two or more FieldMasks. + /// + public FieldMask Union(params FieldMask[] otherMasks) + { + var maskTree = new FieldMaskTree(this); + foreach (var mask in otherMasks) + { + maskTree.MergeFromFieldMask(mask); + } + + return maskTree.ToFieldMask(); + } + + /// + /// Calculates the intersection of two FieldMasks. + /// + public FieldMask Intersection(FieldMask additionalMask) + { + var tree = new FieldMaskTree(this); + var result = new FieldMaskTree(); + foreach (var path in additionalMask.Paths) + { + tree.IntersectFieldPath(path, result); + } + + return result.ToFieldMask(); + } + + /// + /// Merges fields specified by this FieldMask from one message to another with the + /// specified merge options. + /// + public void Merge(IMessage source, IMessage destination, MergeOptions options) + { + new FieldMaskTree(this).Merge(source, destination, options); + } + + /// + /// Merges fields specified by this FieldMask from one message to another. + /// + public void Merge(IMessage source, IMessage destination) + { + Merge(source, destination, new MergeOptions()); + } + + /// + /// Options to customize merging behavior. + /// + public sealed class MergeOptions + { + /// + /// Whether to replace message fields(i.e., discard existing content in + /// destination message fields) when merging. + /// Default behavior is to merge the source message field into the + /// destination message field. + /// + public bool ReplaceMessageFields { get; set; } = false; + + /// + /// Whether to replace repeated fields (i.e., discard existing content in + /// destination repeated fields) when merging. + /// Default behavior is to append elements from source repeated field to the + /// destination repeated field. + /// + public bool ReplaceRepeatedFields { get; set; } = false; + + /// + /// Whether to replace primitive (non-repeated and non-message) fields in + /// destination message fields with the source primitive fields (i.e., if the + /// field is set in the source, the value is copied to the + /// destination; if the field is unset in the source, the field is cleared + /// from the destination) when merging. + /// + /// Default behavior is to always set the value of the source primitive + /// field to the destination primitive field, and if the source field is + /// unset, the default value of the source field is copied to the + /// destination. + /// + public bool ReplacePrimitiveFields { get; set; } = false; } } } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs index 6ddadf19ae767..5fe9b895364d4 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs @@ -1,5 +1,7 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/source_context.proto +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/source_context.proto +// #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -24,14 +26,14 @@ static SourceContextReflection() { string.Concat( "CiRnb29nbGUvcHJvdG9idWYvc291cmNlX2NvbnRleHQucHJvdG8SD2dvb2ds", "ZS5wcm90b2J1ZiIiCg1Tb3VyY2VDb250ZXh0EhEKCWZpbGVfbmFtZRgBIAEo", - "CUKVAQoTY29tLmdvb2dsZS5wcm90b2J1ZkISU291cmNlQ29udGV4dFByb3Rv", - "UAFaQWdvb2dsZS5nb2xhbmcub3JnL2dlbnByb3RvL3Byb3RvYnVmL3NvdXJj", - "ZV9jb250ZXh0O3NvdXJjZV9jb250ZXh0ogIDR1BCqgIeR29vZ2xlLlByb3Rv", - "YnVmLldlbGxLbm93blR5cGVzYgZwcm90bzM=")); + "CUKKAQoTY29tLmdvb2dsZS5wcm90b2J1ZkISU291cmNlQ29udGV4dFByb3Rv", + "UAFaNmdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL3Nv", + "dXJjZWNvbnRleHRwYqICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25v", + "d25UeXBlc2IGcHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.SourceContext), global::Google.Protobuf.WellKnownTypes.SourceContext.Parser, new[]{ "FileName" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.SourceContext), global::Google.Protobuf.WellKnownTypes.SourceContext.Parser, new[]{ "FileName" }, null, null, null, null) })); } #endregion @@ -42,8 +44,13 @@ static SourceContextReflection() { /// `SourceContext` represents information about the source of a /// protobuf element, like the file in which it is defined. /// - public sealed partial class SourceContext : pb::IMessage { + public sealed partial class SourceContext : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SourceContext()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -67,6 +74,7 @@ public SourceContext() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public SourceContext(SourceContext other) : this() { fileName_ = other.fileName_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -103,13 +111,16 @@ public bool Equals(SourceContext other) { return true; } if (FileName != other.FileName) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (FileName.Length != 0) hash ^= FileName.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -120,18 +131,41 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (FileName.Length != 0) { output.WriteRawTag(10); output.WriteString(FileName); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (FileName.Length != 0) { + output.WriteRawTag(10); + output.WriteString(FileName); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (FileName.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(FileName); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -143,15 +177,37 @@ public void MergeFrom(SourceContext other) { if (other.FileName.Length != 0) { FileName = other.FileName; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + FileName = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { FileName = input.ReadString(); @@ -160,6 +216,7 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs index 1fa35521551e0..0bbb1fcdf9d58 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs @@ -1,5 +1,7 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/struct.proto +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/struct.proto +// #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -33,16 +35,16 @@ static StructReflection() { "ABIwCgpsaXN0X3ZhbHVlGAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLkxpc3RW", "YWx1ZUgAQgYKBGtpbmQiMwoJTGlzdFZhbHVlEiYKBnZhbHVlcxgBIAMoCzIW", "Lmdvb2dsZS5wcm90b2J1Zi5WYWx1ZSobCglOdWxsVmFsdWUSDgoKTlVMTF9W", - "QUxVRRAAQoEBChNjb20uZ29vZ2xlLnByb3RvYnVmQgtTdHJ1Y3RQcm90b1AB", - "WjFnaXRodWIuY29tL2dvbGFuZy9wcm90b2J1Zi9wdHlwZXMvc3RydWN0O3N0", - "cnVjdHBi+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5", - "cGVzYgZwcm90bzM=")); + "QUxVRRAAQn8KE2NvbS5nb29nbGUucHJvdG9idWZCC1N0cnVjdFByb3RvUAFa", + "L2dvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL3N0cnVj", + "dHBi+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVz", + "YgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.NullValue), }, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Struct), global::Google.Protobuf.WellKnownTypes.Struct.Parser, new[]{ "Fields" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, }), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Value), global::Google.Protobuf.WellKnownTypes.Value.Parser, new[]{ "NullValue", "NumberValue", "StringValue", "BoolValue", "StructValue", "ListValue" }, new[]{ "Kind" }, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.ListValue), global::Google.Protobuf.WellKnownTypes.ListValue.Parser, new[]{ "Values" }, null, null, null) + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.NullValue), }, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Struct), global::Google.Protobuf.WellKnownTypes.Struct.Parser, new[]{ "Fields" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Value), global::Google.Protobuf.WellKnownTypes.Value.Parser, new[]{ "NullValue", "NumberValue", "StringValue", "BoolValue", "StructValue", "ListValue" }, new[]{ "Kind" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.ListValue), global::Google.Protobuf.WellKnownTypes.ListValue.Parser, new[]{ "Values" }, null, null, null, null) })); } #endregion @@ -75,8 +77,13 @@ public enum NullValue { /// /// The JSON representation for `Struct` is JSON object. /// - public sealed partial class Struct : pb::IMessage { + public sealed partial class Struct : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Struct()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -100,6 +107,7 @@ public Struct() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Struct(Struct other) : this() { fields_ = other.fields_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -110,7 +118,7 @@ public Struct Clone() { /// Field number for the "fields" field. public const int FieldsFieldNumber = 1; private static readonly pbc::MapField.Codec _map_fields_codec - = new pbc::MapField.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Value.Parser), 10); + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Value.Parser), 10); private readonly pbc::MapField fields_ = new pbc::MapField(); /// /// Unordered map of dynamically typed values. @@ -134,13 +142,16 @@ public bool Equals(Struct other) { return true; } if (!Fields.Equals(other.Fields)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= Fields.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -151,13 +162,33 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else fields_.WriteTo(output, _map_fields_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + fields_.WriteTo(ref output, _map_fields_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += fields_.CalculateSize(_map_fields_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -167,15 +198,19 @@ public void MergeFrom(Struct other) { return; } fields_.Add(other.fields_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { fields_.AddEntriesFrom(input, _map_fields_codec); @@ -183,7 +218,26 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + fields_.AddEntriesFrom(ref input, _map_fields_codec); + break; + } + } + } } + #endif } @@ -195,8 +249,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// /// The JSON representation for `Value` is JSON value. /// - public sealed partial class Value : pb::IMessage { + public sealed partial class Value : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Value()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -240,6 +299,7 @@ public Value(Value other) : this() { break; } + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -254,7 +314,7 @@ public Value Clone() { /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public global::Google.Protobuf.WellKnownTypes.NullValue NullValue { - get { return kindCase_ == KindOneofCase.NullValue ? (global::Google.Protobuf.WellKnownTypes.NullValue) kind_ : 0; } + get { return kindCase_ == KindOneofCase.NullValue ? (global::Google.Protobuf.WellKnownTypes.NullValue) kind_ : global::Google.Protobuf.WellKnownTypes.NullValue.NullValue; } set { kind_ = value; kindCase_ = KindOneofCase.NullValue; @@ -368,25 +428,28 @@ public bool Equals(Value other) { return true; } if (NullValue != other.NullValue) return false; - if (NumberValue != other.NumberValue) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(NumberValue, other.NumberValue)) return false; if (StringValue != other.StringValue) return false; if (BoolValue != other.BoolValue) return false; if (!object.Equals(StructValue, other.StructValue)) return false; if (!object.Equals(ListValue, other.ListValue)) return false; if (KindCase != other.KindCase) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (kindCase_ == KindOneofCase.NullValue) hash ^= NullValue.GetHashCode(); - if (kindCase_ == KindOneofCase.NumberValue) hash ^= NumberValue.GetHashCode(); + if (kindCase_ == KindOneofCase.NumberValue) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(NumberValue); if (kindCase_ == KindOneofCase.StringValue) hash ^= StringValue.GetHashCode(); if (kindCase_ == KindOneofCase.BoolValue) hash ^= BoolValue.GetHashCode(); if (kindCase_ == KindOneofCase.StructValue) hash ^= StructValue.GetHashCode(); if (kindCase_ == KindOneofCase.ListValue) hash ^= ListValue.GetHashCode(); hash ^= (int) kindCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -397,6 +460,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (kindCase_ == KindOneofCase.NullValue) { output.WriteRawTag(8); output.WriteEnum((int) NullValue); @@ -421,8 +487,45 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(50); output.WriteMessage(ListValue); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (kindCase_ == KindOneofCase.NullValue) { + output.WriteRawTag(8); + output.WriteEnum((int) NullValue); + } + if (kindCase_ == KindOneofCase.NumberValue) { + output.WriteRawTag(17); + output.WriteDouble(NumberValue); + } + if (kindCase_ == KindOneofCase.StringValue) { + output.WriteRawTag(26); + output.WriteString(StringValue); + } + if (kindCase_ == KindOneofCase.BoolValue) { + output.WriteRawTag(32); + output.WriteBool(BoolValue); + } + if (kindCase_ == KindOneofCase.StructValue) { + output.WriteRawTag(42); + output.WriteMessage(StructValue); + } + if (kindCase_ == KindOneofCase.ListValue) { + output.WriteRawTag(50); + output.WriteMessage(ListValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -444,6 +547,9 @@ public int CalculateSize() { if (kindCase_ == KindOneofCase.ListValue) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(ListValue); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -466,22 +572,81 @@ public void MergeFrom(Value other) { BoolValue = other.BoolValue; break; case KindOneofCase.StructValue: - StructValue = other.StructValue; + if (StructValue == null) { + StructValue = new global::Google.Protobuf.WellKnownTypes.Struct(); + } + StructValue.MergeFrom(other.StructValue); break; case KindOneofCase.ListValue: - ListValue = other.ListValue; + if (ListValue == null) { + ListValue = new global::Google.Protobuf.WellKnownTypes.ListValue(); + } + ListValue.MergeFrom(other.ListValue); break; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: { + kind_ = input.ReadEnum(); + kindCase_ = KindOneofCase.NullValue; + break; + } + case 17: { + NumberValue = input.ReadDouble(); + break; + } + case 26: { + StringValue = input.ReadString(); + break; + } + case 32: { + BoolValue = input.ReadBool(); + break; + } + case 42: { + global::Google.Protobuf.WellKnownTypes.Struct subBuilder = new global::Google.Protobuf.WellKnownTypes.Struct(); + if (kindCase_ == KindOneofCase.StructValue) { + subBuilder.MergeFrom(StructValue); + } + input.ReadMessage(subBuilder); + StructValue = subBuilder; + break; + } + case 50: { + global::Google.Protobuf.WellKnownTypes.ListValue subBuilder = new global::Google.Protobuf.WellKnownTypes.ListValue(); + if (kindCase_ == KindOneofCase.ListValue) { + subBuilder.MergeFrom(ListValue); + } + input.ReadMessage(subBuilder); + ListValue = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { kind_ = input.ReadEnum(); @@ -521,6 +686,7 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } @@ -529,8 +695,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// /// The JSON representation for `ListValue` is JSON array. /// - public sealed partial class ListValue : pb::IMessage { + public sealed partial class ListValue : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ListValue()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -554,6 +725,7 @@ public ListValue() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ListValue(ListValue other) : this() { values_ = other.values_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -588,13 +760,16 @@ public bool Equals(ListValue other) { return true; } if(!values_.Equals(other.values_)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; hash ^= values_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -605,13 +780,33 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else values_.WriteTo(output, _repeated_values_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + values_.WriteTo(ref output, _repeated_values_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; size += values_.CalculateSize(_repeated_values_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -621,15 +816,19 @@ public void MergeFrom(ListValue other) { return; } values_.Add(other.values_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { values_.AddEntriesFrom(input, _repeated_values_codec); @@ -637,7 +836,26 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + values_.AddEntriesFrom(ref input, _repeated_values_codec); + break; + } + } + } } + #endif } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs index 911f797e01e9e..2fb1b4d164282 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs @@ -1,5 +1,7 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/timestamp.proto +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/timestamp.proto +// #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -24,14 +26,14 @@ static TimestampReflection() { string.Concat( "Ch9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnByb3RvEg9nb29nbGUucHJv", "dG9idWYiKwoJVGltZXN0YW1wEg8KB3NlY29uZHMYASABKAMSDQoFbmFub3MY", - "AiABKAVCfgoTY29tLmdvb2dsZS5wcm90b2J1ZkIOVGltZXN0YW1wUHJvdG9Q", - "AVorZ2l0aHViLmNvbS9nb2xhbmcvcHJvdG9idWYvcHR5cGVzL3RpbWVzdGFt", - "cPgBAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IG", - "cHJvdG8z")); + "AiABKAVChQEKE2NvbS5nb29nbGUucHJvdG9idWZCDlRpbWVzdGFtcFByb3Rv", + "UAFaMmdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL3Rp", + "bWVzdGFtcHBi+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93", + "blR5cGVzYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Timestamp), global::Google.Protobuf.WellKnownTypes.Timestamp.Parser, new[]{ "Seconds", "Nanos" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Timestamp), global::Google.Protobuf.WellKnownTypes.Timestamp.Parser, new[]{ "Seconds", "Nanos" }, null, null, null, null) })); } #endregion @@ -39,17 +41,19 @@ static TimestampReflection() { } #region Messages /// - /// A Timestamp represents a point in time independent of any time zone - /// or calendar, represented as seconds and fractions of seconds at - /// nanosecond resolution in UTC Epoch time. It is encoded using the - /// Proleptic Gregorian Calendar which extends the Gregorian calendar - /// backwards to year one. It is encoded assuming all minutes are 60 - /// seconds long, i.e. leap seconds are "smeared" so that no leap second - /// table is needed for interpretation. Range is from - /// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. - /// By restricting to that range, we ensure that we can convert to - /// and from RFC 3339 date strings. - /// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). + /// A Timestamp represents a point in time independent of any time zone or local + /// calendar, encoded as a count of seconds and fractions of seconds at + /// nanosecond resolution. The count is relative to an epoch at UTC midnight on + /// January 1, 1970, in the proleptic Gregorian calendar which extends the + /// Gregorian calendar backwards to year one. + /// + /// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + /// second table is needed for interpretation, using a [24-hour linear + /// smear](https://developers.google.com/time/smear). + /// + /// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + /// restricting to that range, we ensure that we can convert to and from [RFC + /// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. /// /// # Examples /// @@ -87,7 +91,15 @@ static TimestampReflection() { /// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) /// .setNanos((int) ((millis % 1000) * 1000000)).build(); /// - /// Example 5: Compute Timestamp from current time in Python. + /// Example 5: Compute Timestamp from Java `Instant.now()`. + /// + /// Instant now = Instant.now(); + /// + /// Timestamp timestamp = + /// Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + /// .setNanos(now.getNano()).build(); + /// + /// Example 6: Compute Timestamp from current time in Python. /// /// timestamp = Timestamp() /// timestamp.GetCurrentTime() @@ -101,22 +113,31 @@ static TimestampReflection() { /// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional /// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), /// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone - /// is required, though only UTC (as indicated by "Z") is presently supported. + /// is required. A proto3 JSON serializer should always use UTC (as indicated by + /// "Z") when printing the Timestamp type and a proto3 JSON parser should be + /// able to accept both UTC and other timezones (as indicated by an offset). /// /// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past /// 01:30 UTC on January 15, 2017. /// /// In JavaScript, one can convert a Date object to this format using the - /// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString] + /// standard + /// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) /// method. In Python, a standard `datetime.datetime` object can be converted - /// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) - /// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one - /// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( - /// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()) - /// to obtain a formatter capable of generating timestamps in this format. + /// to this format using + /// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with + /// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use + /// the Joda Time's [`ISODateTimeFormat.dateTime()`]( + /// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D + /// ) to obtain a formatter capable of generating timestamps in this format. /// - public sealed partial class Timestamp : pb::IMessage { + public sealed partial class Timestamp : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Timestamp()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -141,6 +162,7 @@ public Timestamp() { public Timestamp(Timestamp other) : this() { seconds_ = other.seconds_; nanos_ = other.nanos_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -196,7 +218,7 @@ public bool Equals(Timestamp other) { } if (Seconds != other.Seconds) return false; if (Nanos != other.Nanos) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -204,6 +226,9 @@ public override int GetHashCode() { int hash = 1; if (Seconds != 0L) hash ^= Seconds.GetHashCode(); if (Nanos != 0) hash ^= Nanos.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -214,6 +239,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Seconds != 0L) { output.WriteRawTag(8); output.WriteInt64(Seconds); @@ -222,7 +250,28 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(16); output.WriteInt32(Nanos); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Seconds != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Seconds); + } + if (Nanos != 0) { + output.WriteRawTag(16); + output.WriteInt32(Nanos); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -233,6 +282,9 @@ public int CalculateSize() { if (Nanos != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Nanos); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -247,15 +299,41 @@ public void MergeFrom(Timestamp other) { if (other.Nanos != 0) { Nanos = other.Nanos; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: { + Seconds = input.ReadInt64(); + break; + } + case 16: { + Nanos = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Seconds = input.ReadInt64(); @@ -268,6 +346,7 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs index aa40347342f56..2f5172f1ca7cb 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs @@ -36,7 +36,7 @@ namespace Google.Protobuf.WellKnownTypes { - public partial class Timestamp : ICustomDiagnosticMessage + public partial class Timestamp : ICustomDiagnosticMessage, IComparable { private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); // Constants determined programmatically, but then hard-coded so they can be constant expressions. @@ -222,6 +222,109 @@ internal static string ToJson(long seconds, int nanoseconds, bool diagnosticOnly } } + /// + /// Given another timestamp, returns 0 if the timestamps are equivalent, -1 if this timestamp precedes the other, and 1 otherwise + /// + /// + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// + /// Timestamp to compare + /// an integer indicating whether this timestamp precedes or follows the other + public int CompareTo(Timestamp other) + { + return other == null ? 1 + : Seconds < other.Seconds ? -1 + : Seconds > other.Seconds ? 1 + : Nanos < other.Nanos ? -1 + : Nanos > other.Nanos ? 1 + : 0; + } + + /// + /// Compares two timestamps and returns whether the first is less than (chronologically precedes) the second + /// + /// + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// + /// + /// + /// true if a precedes b + public static bool operator <(Timestamp a, Timestamp b) + { + return a.CompareTo(b) < 0; + } + + /// + /// Compares two timestamps and returns whether the first is greater than (chronologically follows) the second + /// + /// + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// + /// + /// + /// true if a follows b + public static bool operator >(Timestamp a, Timestamp b) + { + return a.CompareTo(b) > 0; + } + + /// + /// Compares two timestamps and returns whether the first is less than (chronologically precedes) the second + /// + /// + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// + /// + /// + /// true if a precedes b + public static bool operator <=(Timestamp a, Timestamp b) + { + return a.CompareTo(b) <= 0; + } + + /// + /// Compares two timestamps and returns whether the first is greater than (chronologically follows) the second + /// + /// + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// + /// + /// + /// true if a follows b + public static bool operator >=(Timestamp a, Timestamp b) + { + return a.CompareTo(b) >= 0; + } + + + /// + /// Returns whether two timestamps are equivalent + /// + /// + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// + /// + /// + /// true if the two timestamps refer to the same nanosecond + public static bool operator ==(Timestamp a, Timestamp b) + { + return ReferenceEquals(a, b) || (ReferenceEquals(a, null) ? (ReferenceEquals(b, null) ? true : false) : a.Equals(b)); + } + + /// + /// Returns whether two timestamps differ + /// + /// + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// + /// + /// + /// true if the two timestamps differ + public static bool operator !=(Timestamp a, Timestamp b) + { + return !(a == b); + } + /// /// Returns a string representation of this for diagnostic purposes. /// diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs index 7375b6cb18e43..f5dfdb7e3e768 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs @@ -1,5 +1,7 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/type.proto +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/type.proto +// #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -54,18 +56,18 @@ static TypeReflection() { "ASgFEigKB29wdGlvbnMYAyADKAsyFy5nb29nbGUucHJvdG9idWYuT3B0aW9u", "IjsKBk9wdGlvbhIMCgRuYW1lGAEgASgJEiMKBXZhbHVlGAIgASgLMhQuZ29v", "Z2xlLnByb3RvYnVmLkFueSouCgZTeW50YXgSEQoNU1lOVEFYX1BST1RPMhAA", - "EhEKDVNZTlRBWF9QUk9UTzMQAUJ9ChNjb20uZ29vZ2xlLnByb3RvYnVmQglU", - "eXBlUHJvdG9QAVovZ29vZ2xlLmdvbGFuZy5vcmcvZ2VucHJvdG8vcHJvdG9i", - "dWYvcHR5cGU7cHR5cGX4AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2Vs", - "bEtub3duVHlwZXNiBnByb3RvMw==")); + "EhEKDVNZTlRBWF9QUk9UTzMQAUJ7ChNjb20uZ29vZ2xlLnByb3RvYnVmQglU", + "eXBlUHJvdG9QAVotZ29vZ2xlLmdvbGFuZy5vcmcvcHJvdG9idWYvdHlwZXMv", + "a25vd24vdHlwZXBi+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxL", + "bm93blR5cGVzYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.Syntax), }, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Type), global::Google.Protobuf.WellKnownTypes.Type.Parser, new[]{ "Name", "Fields", "Oneofs", "Options", "SourceContext", "Syntax" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Field), global::Google.Protobuf.WellKnownTypes.Field.Parser, new[]{ "Kind", "Cardinality", "Number", "Name", "TypeUrl", "OneofIndex", "Packed", "Options", "JsonName", "DefaultValue" }, null, new[]{ typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Kind), typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) }, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Enum), global::Google.Protobuf.WellKnownTypes.Enum.Parser, new[]{ "Name", "Enumvalue", "Options", "SourceContext", "Syntax" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.EnumValue), global::Google.Protobuf.WellKnownTypes.EnumValue.Parser, new[]{ "Name", "Number", "Options" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Option), global::Google.Protobuf.WellKnownTypes.Option.Parser, new[]{ "Name", "Value" }, null, null, null) + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.Syntax), }, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Type), global::Google.Protobuf.WellKnownTypes.Type.Parser, new[]{ "Name", "Fields", "Oneofs", "Options", "SourceContext", "Syntax" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Field), global::Google.Protobuf.WellKnownTypes.Field.Parser, new[]{ "Kind", "Cardinality", "Number", "Name", "TypeUrl", "OneofIndex", "Packed", "Options", "JsonName", "DefaultValue" }, null, new[]{ typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Kind), typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Enum), global::Google.Protobuf.WellKnownTypes.Enum.Parser, new[]{ "Name", "Enumvalue", "Options", "SourceContext", "Syntax" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.EnumValue), global::Google.Protobuf.WellKnownTypes.EnumValue.Parser, new[]{ "Name", "Number", "Options" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Option), global::Google.Protobuf.WellKnownTypes.Option.Parser, new[]{ "Name", "Value" }, null, null, null, null) })); } #endregion @@ -92,8 +94,13 @@ public enum Syntax { /// /// A protocol buffer message type. /// - public sealed partial class Type : pb::IMessage { + public sealed partial class Type : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Type()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -120,8 +127,9 @@ public Type(Type other) : this() { fields_ = other.fields_.Clone(); oneofs_ = other.oneofs_.Clone(); options_ = other.options_.Clone(); - SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null; + sourceContext_ = other.sourceContext_ != null ? other.sourceContext_.Clone() : null; syntax_ = other.syntax_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -198,7 +206,7 @@ public string Name { /// Field number for the "syntax" field. public const int SyntaxFieldNumber = 6; - private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = 0; + private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = global::Google.Protobuf.WellKnownTypes.Syntax.Proto2; /// /// The source syntax. /// @@ -229,7 +237,7 @@ public bool Equals(Type other) { if(!options_.Equals(other.options_)) return false; if (!object.Equals(SourceContext, other.SourceContext)) return false; if (Syntax != other.Syntax) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -240,7 +248,10 @@ public override int GetHashCode() { hash ^= oneofs_.GetHashCode(); hash ^= options_.GetHashCode(); if (sourceContext_ != null) hash ^= SourceContext.GetHashCode(); - if (Syntax != 0) hash ^= Syntax.GetHashCode(); + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) hash ^= Syntax.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -251,6 +262,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -262,11 +276,39 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(42); output.WriteMessage(SourceContext); } - if (Syntax != 0) { + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { + output.WriteRawTag(48); + output.WriteEnum((int) Syntax); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + fields_.WriteTo(ref output, _repeated_fields_codec); + oneofs_.WriteTo(ref output, _repeated_oneofs_codec); + options_.WriteTo(ref output, _repeated_options_codec); + if (sourceContext_ != null) { + output.WriteRawTag(42); + output.WriteMessage(SourceContext); + } + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { output.WriteRawTag(48); output.WriteEnum((int) Syntax); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -280,9 +322,12 @@ public int CalculateSize() { if (sourceContext_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContext); } - if (Syntax != 0) { + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -299,22 +344,26 @@ public void MergeFrom(Type other) { options_.Add(other.options_); if (other.sourceContext_ != null) { if (sourceContext_ == null) { - sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext(); + SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext(); } SourceContext.MergeFrom(other.SourceContext); } - if (other.Syntax != 0) { + if (other.Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { Syntax = other.Syntax; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { Name = input.ReadString(); @@ -334,26 +383,73 @@ public void MergeFrom(pb::CodedInputStream input) { } case 42: { if (sourceContext_ == null) { - sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext(); + SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext(); + } + input.ReadMessage(SourceContext); + break; + } + case 48: { + Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + fields_.AddEntriesFrom(ref input, _repeated_fields_codec); + break; + } + case 26: { + oneofs_.AddEntriesFrom(ref input, _repeated_oneofs_codec); + break; + } + case 34: { + options_.AddEntriesFrom(ref input, _repeated_options_codec); + break; + } + case 42: { + if (sourceContext_ == null) { + SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext(); } - input.ReadMessage(sourceContext_); + input.ReadMessage(SourceContext); break; } case 48: { - syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum(); + Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum(); break; } } } } + #endif } /// /// A single field of a message type. /// - public sealed partial class Field : pb::IMessage { + public sealed partial class Field : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Field()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -386,6 +482,7 @@ public Field(Field other) : this() { options_ = other.options_.Clone(); jsonName_ = other.jsonName_; defaultValue_ = other.defaultValue_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -395,7 +492,7 @@ public Field Clone() { /// Field number for the "kind" field. public const int KindFieldNumber = 1; - private global::Google.Protobuf.WellKnownTypes.Field.Types.Kind kind_ = 0; + private global::Google.Protobuf.WellKnownTypes.Field.Types.Kind kind_ = global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TypeUnknown; /// /// The field type. /// @@ -409,7 +506,7 @@ public Field Clone() { /// Field number for the "cardinality" field. public const int CardinalityFieldNumber = 2; - private global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality cardinality_ = 0; + private global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality cardinality_ = global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.Unknown; /// /// The field cardinality. /// @@ -557,14 +654,14 @@ public bool Equals(Field other) { if(!options_.Equals(other.options_)) return false; if (JsonName != other.JsonName) return false; if (DefaultValue != other.DefaultValue) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Kind != 0) hash ^= Kind.GetHashCode(); - if (Cardinality != 0) hash ^= Cardinality.GetHashCode(); + if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TypeUnknown) hash ^= Kind.GetHashCode(); + if (Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.Unknown) hash ^= Cardinality.GetHashCode(); if (Number != 0) hash ^= Number.GetHashCode(); if (Name.Length != 0) hash ^= Name.GetHashCode(); if (TypeUrl.Length != 0) hash ^= TypeUrl.GetHashCode(); @@ -573,6 +670,9 @@ public override int GetHashCode() { hash ^= options_.GetHashCode(); if (JsonName.Length != 0) hash ^= JsonName.GetHashCode(); if (DefaultValue.Length != 0) hash ^= DefaultValue.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -583,11 +683,14 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Kind != 0) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TypeUnknown) { output.WriteRawTag(8); output.WriteEnum((int) Kind); } - if (Cardinality != 0) { + if (Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.Unknown) { output.WriteRawTag(16); output.WriteEnum((int) Cardinality); } @@ -620,15 +723,65 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(90); output.WriteString(DefaultValue); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TypeUnknown) { + output.WriteRawTag(8); + output.WriteEnum((int) Kind); + } + if (Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.Unknown) { + output.WriteRawTag(16); + output.WriteEnum((int) Cardinality); + } + if (Number != 0) { + output.WriteRawTag(24); + output.WriteInt32(Number); + } + if (Name.Length != 0) { + output.WriteRawTag(34); + output.WriteString(Name); + } + if (TypeUrl.Length != 0) { + output.WriteRawTag(50); + output.WriteString(TypeUrl); + } + if (OneofIndex != 0) { + output.WriteRawTag(56); + output.WriteInt32(OneofIndex); + } + if (Packed != false) { + output.WriteRawTag(64); + output.WriteBool(Packed); + } + options_.WriteTo(ref output, _repeated_options_codec); + if (JsonName.Length != 0) { + output.WriteRawTag(82); + output.WriteString(JsonName); + } + if (DefaultValue.Length != 0) { + output.WriteRawTag(90); + output.WriteString(DefaultValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Kind != 0) { + if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TypeUnknown) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Kind); } - if (Cardinality != 0) { + if (Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.Unknown) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Cardinality); } if (Number != 0) { @@ -653,6 +806,9 @@ public int CalculateSize() { if (DefaultValue.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(DefaultValue); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -661,10 +817,10 @@ public void MergeFrom(Field other) { if (other == null) { return; } - if (other.Kind != 0) { + if (other.Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TypeUnknown) { Kind = other.Kind; } - if (other.Cardinality != 0) { + if (other.Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.Unknown) { Cardinality = other.Cardinality; } if (other.Number != 0) { @@ -689,22 +845,26 @@ public void MergeFrom(Field other) { if (other.DefaultValue.Length != 0) { DefaultValue = other.DefaultValue; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 8: { - kind_ = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum(); + Kind = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum(); break; } case 16: { - cardinality_ = (global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) input.ReadEnum(); + Cardinality = (global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) input.ReadEnum(); break; } case 24: { @@ -741,8 +901,63 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Kind = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum(); + break; + } + case 16: { + Cardinality = (global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) input.ReadEnum(); + break; + } + case 24: { + Number = input.ReadInt32(); + break; + } + case 34: { + Name = input.ReadString(); + break; + } + case 50: { + TypeUrl = input.ReadString(); + break; + } + case 56: { + OneofIndex = input.ReadInt32(); + break; + } + case 64: { + Packed = input.ReadBool(); + break; + } + case 74: { + options_.AddEntriesFrom(ref input, _repeated_options_codec); + break; + } + case 82: { + JsonName = input.ReadString(); + break; + } + case 90: { + DefaultValue = input.ReadString(); + break; + } + } + } + } + #endif + #region Nested types /// Container for nested types declared in the Field message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -859,8 +1074,13 @@ public enum Cardinality { /// /// Enum type definition. /// - public sealed partial class Enum : pb::IMessage { + public sealed partial class Enum : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Enum()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -886,8 +1106,9 @@ public Enum(Enum other) : this() { name_ = other.name_; enumvalue_ = other.enumvalue_.Clone(); options_ = other.options_.Clone(); - SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null; + sourceContext_ = other.sourceContext_ != null ? other.sourceContext_.Clone() : null; syntax_ = other.syntax_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -951,7 +1172,7 @@ public string Name { /// Field number for the "syntax" field. public const int SyntaxFieldNumber = 5; - private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = 0; + private global::Google.Protobuf.WellKnownTypes.Syntax syntax_ = global::Google.Protobuf.WellKnownTypes.Syntax.Proto2; /// /// The source syntax. /// @@ -981,7 +1202,7 @@ public bool Equals(Enum other) { if(!options_.Equals(other.options_)) return false; if (!object.Equals(SourceContext, other.SourceContext)) return false; if (Syntax != other.Syntax) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -991,7 +1212,10 @@ public override int GetHashCode() { hash ^= enumvalue_.GetHashCode(); hash ^= options_.GetHashCode(); if (sourceContext_ != null) hash ^= SourceContext.GetHashCode(); - if (Syntax != 0) hash ^= Syntax.GetHashCode(); + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) hash ^= Syntax.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -1002,6 +1226,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -1012,11 +1239,38 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(34); output.WriteMessage(SourceContext); } - if (Syntax != 0) { + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { + output.WriteRawTag(40); + output.WriteEnum((int) Syntax); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + enumvalue_.WriteTo(ref output, _repeated_enumvalue_codec); + options_.WriteTo(ref output, _repeated_options_codec); + if (sourceContext_ != null) { + output.WriteRawTag(34); + output.WriteMessage(SourceContext); + } + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { output.WriteRawTag(40); output.WriteEnum((int) Syntax); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1029,9 +1283,12 @@ public int CalculateSize() { if (sourceContext_ != null) { size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContext); } - if (Syntax != 0) { + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -1047,22 +1304,26 @@ public void MergeFrom(Enum other) { options_.Add(other.options_); if (other.sourceContext_ != null) { if (sourceContext_ == null) { - sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext(); + SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext(); } SourceContext.MergeFrom(other.SourceContext); } - if (other.Syntax != 0) { + if (other.Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { Syntax = other.Syntax; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { Name = input.ReadString(); @@ -1078,26 +1339,69 @@ public void MergeFrom(pb::CodedInputStream input) { } case 34: { if (sourceContext_ == null) { - sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext(); + SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext(); } - input.ReadMessage(sourceContext_); + input.ReadMessage(SourceContext); break; } case 40: { - syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum(); + Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum(); break; } } } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + enumvalue_.AddEntriesFrom(ref input, _repeated_enumvalue_codec); + break; + } + case 26: { + options_.AddEntriesFrom(ref input, _repeated_options_codec); + break; + } + case 34: { + if (sourceContext_ == null) { + SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext(); + } + input.ReadMessage(SourceContext); + break; + } + case 40: { + Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum(); + break; + } + } + } + } + #endif + } /// /// Enum value definition. /// - public sealed partial class EnumValue : pb::IMessage { + public sealed partial class EnumValue : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EnumValue()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -1123,6 +1427,7 @@ public EnumValue(EnumValue other) : this() { name_ = other.name_; number_ = other.number_; options_ = other.options_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1187,7 +1492,7 @@ public bool Equals(EnumValue other) { if (Name != other.Name) return false; if (Number != other.Number) return false; if(!options_.Equals(other.options_)) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1196,6 +1501,9 @@ public override int GetHashCode() { if (Name.Length != 0) hash ^= Name.GetHashCode(); if (Number != 0) hash ^= Number.GetHashCode(); hash ^= options_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -1206,6 +1514,9 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -1215,7 +1526,29 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteInt32(Number); } options_.WriteTo(output, _repeated_options_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (Number != 0) { + output.WriteRawTag(16); + output.WriteInt32(Number); + } + options_.WriteTo(ref output, _repeated_options_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1227,6 +1560,9 @@ public int CalculateSize() { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number); } size += options_.CalculateSize(_repeated_options_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -1242,15 +1578,19 @@ public void MergeFrom(EnumValue other) { Number = other.Number; } options_.Add(other.options_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 10: { Name = input.ReadString(); @@ -1266,7 +1606,34 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 16: { + Number = input.ReadInt32(); + break; + } + case 26: { + options_.AddEntriesFrom(ref input, _repeated_options_codec); + break; + } + } + } } + #endif } @@ -1274,8 +1641,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// A protocol buffer option, which can be attached to a message, field, /// enumeration, etc. /// - public sealed partial class Option : pb::IMessage - public sealed partial class DoubleValue : pb::IMessage { + public sealed partial class DoubleValue : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DoubleValue()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -80,6 +88,7 @@ public DoubleValue() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public DoubleValue(DoubleValue other) : this() { value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -114,14 +123,17 @@ public bool Equals(DoubleValue other) { if (ReferenceEquals(other, this)) { return true; } - if (Value != other.Value) return false; - return true; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Value, other.Value)) return false; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Value != 0D) hash ^= Value.GetHashCode(); + if (Value != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Value); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -132,18 +144,41 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value != 0D) { output.WriteRawTag(9); output.WriteDouble(Value); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != 0D) { + output.WriteRawTag(9); + output.WriteDouble(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Value != 0D) { size += 1 + 8; } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -155,15 +190,19 @@ public void MergeFrom(DoubleValue other) { if (other.Value != 0D) { Value = other.Value; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 9: { Value = input.ReadDouble(); @@ -171,8 +210,27 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 9: { + Value = input.ReadDouble(); + break; + } + } + } + } + #endif + } /// @@ -180,8 +238,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// /// The JSON representation for `FloatValue` is JSON number. /// - public sealed partial class FloatValue : pb::IMessage { + public sealed partial class FloatValue : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FloatValue()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -205,6 +268,7 @@ public FloatValue() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FloatValue(FloatValue other) : this() { value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -239,14 +303,17 @@ public bool Equals(FloatValue other) { if (ReferenceEquals(other, this)) { return true; } - if (Value != other.Value) return false; - return true; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(Value, other.Value)) return false; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Value != 0F) hash ^= Value.GetHashCode(); + if (Value != 0F) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(Value); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -257,18 +324,41 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value != 0F) { output.WriteRawTag(13); output.WriteFloat(Value); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != 0F) { + output.WriteRawTag(13); + output.WriteFloat(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Value != 0F) { size += 1 + 4; } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -280,15 +370,37 @@ public void MergeFrom(FloatValue other) { if (other.Value != 0F) { Value = other.Value; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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 13: { + Value = input.ReadFloat(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 13: { Value = input.ReadFloat(); @@ -297,6 +409,7 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } @@ -305,8 +418,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// /// The JSON representation for `Int64Value` is JSON string. /// - public sealed partial class Int64Value : pb::IMessage { + public sealed partial class Int64Value : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Int64Value()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -330,6 +448,7 @@ public Int64Value() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Int64Value(Int64Value other) : this() { value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -365,13 +484,16 @@ public bool Equals(Int64Value other) { return true; } if (Value != other.Value) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Value != 0L) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -382,11 +504,31 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Value != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (Value != 0L) { output.WriteRawTag(8); output.WriteInt64(Value); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -394,6 +536,9 @@ public int CalculateSize() { if (Value != 0L) { size += 1 + pb::CodedOutputStream.ComputeInt64Size(Value); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -405,15 +550,19 @@ public void MergeFrom(Int64Value other) { if (other.Value != 0L) { Value = other.Value; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 8: { Value = input.ReadInt64(); @@ -421,8 +570,27 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Value = input.ReadInt64(); + break; + } + } + } + } + #endif + } /// @@ -430,8 +598,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// /// The JSON representation for `UInt64Value` is JSON string. /// - public sealed partial class UInt64Value : pb::IMessage { + public sealed partial class UInt64Value : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new UInt64Value()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -455,6 +628,7 @@ public UInt64Value() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public UInt64Value(UInt64Value other) : this() { value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -490,13 +664,16 @@ public bool Equals(UInt64Value other) { return true; } if (Value != other.Value) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Value != 0UL) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -507,18 +684,41 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value != 0UL) { output.WriteRawTag(8); output.WriteUInt64(Value); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != 0UL) { + output.WriteRawTag(8); + output.WriteUInt64(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Value != 0UL) { size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Value); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -530,15 +730,37 @@ public void MergeFrom(UInt64Value other) { if (other.Value != 0UL) { Value = other.Value; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: { + Value = input.ReadUInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Value = input.ReadUInt64(); @@ -547,6 +769,7 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } @@ -555,8 +778,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// /// The JSON representation for `Int32Value` is JSON number. /// - public sealed partial class Int32Value : pb::IMessage { + public sealed partial class Int32Value : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Int32Value()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -580,6 +808,7 @@ public Int32Value() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public Int32Value(Int32Value other) : this() { value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -615,13 +844,16 @@ public bool Equals(Int32Value other) { return true; } if (Value != other.Value) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Value != 0) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -632,11 +864,31 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Value != 0) { + output.WriteRawTag(8); + output.WriteInt32(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (Value != 0) { output.WriteRawTag(8); output.WriteInt32(Value); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -644,6 +896,9 @@ public int CalculateSize() { if (Value != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(Value); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -655,15 +910,19 @@ public void MergeFrom(Int32Value other) { if (other.Value != 0) { Value = other.Value; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 8: { Value = input.ReadInt32(); @@ -671,8 +930,27 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Value = input.ReadInt32(); + break; + } + } + } + } + #endif + } /// @@ -680,8 +958,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// /// The JSON representation for `UInt32Value` is JSON number. /// - public sealed partial class UInt32Value : pb::IMessage { + public sealed partial class UInt32Value : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new UInt32Value()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -705,6 +988,7 @@ public UInt32Value() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public UInt32Value(UInt32Value other) : this() { value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -740,13 +1024,16 @@ public bool Equals(UInt32Value other) { return true; } if (Value != other.Value) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Value != 0) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -757,18 +1044,41 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value != 0) { output.WriteRawTag(8); output.WriteUInt32(Value); } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != 0) { + output.WriteRawTag(8); + output.WriteUInt32(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; if (Value != 0) { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Value); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -780,15 +1090,19 @@ public void MergeFrom(UInt32Value other) { if (other.Value != 0) { Value = other.Value; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 8: { Value = input.ReadUInt32(); @@ -796,8 +1110,27 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Value = input.ReadUInt32(); + break; + } + } + } + } + #endif + } /// @@ -805,8 +1138,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// /// The JSON representation for `BoolValue` is JSON `true` and `false`. /// - public sealed partial class BoolValue : pb::IMessage { + public sealed partial class BoolValue : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BoolValue()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -830,6 +1168,7 @@ public BoolValue() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public BoolValue(BoolValue other) : this() { value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -865,13 +1204,16 @@ public bool Equals(BoolValue other) { return true; } if (Value != other.Value) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Value != false) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -882,11 +1224,31 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Value != false) { + output.WriteRawTag(8); + output.WriteBool(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (Value != false) { output.WriteRawTag(8); output.WriteBool(Value); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -894,6 +1256,9 @@ public int CalculateSize() { if (Value != false) { size += 1 + 1; } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -905,15 +1270,19 @@ public void MergeFrom(BoolValue other) { if (other.Value != false) { Value = other.Value; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] 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: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 8: { Value = input.ReadBool(); @@ -921,8 +1290,27 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + 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: { + Value = input.ReadBool(); + break; + } + } + } + } + #endif + } /// @@ -930,8 +1318,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// /// The JSON representation for `StringValue` is JSON string. /// - public sealed partial class StringValue : pb::IMessage { + public sealed partial class StringValue : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StringValue()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -955,6 +1348,7 @@ public StringValue() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public StringValue(StringValue other) : this() { value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -990,13 +1384,16 @@ public bool Equals(StringValue other) { return true; } if (Value != other.Value) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Value.Length != 0) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -1007,11 +1404,31 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Value.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (Value.Length != 0) { output.WriteRawTag(10); output.WriteString(Value); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1019,6 +1436,9 @@ public int CalculateSize() { if (Value.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Value); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -1030,15 +1450,37 @@ public void MergeFrom(StringValue other) { if (other.Value.Length != 0) { Value = other.Value; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Value = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Value = input.ReadString(); @@ -1047,6 +1489,7 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } @@ -1055,8 +1498,13 @@ public void MergeFrom(pb::CodedInputStream input) { /// /// The JSON representation for `BytesValue` is JSON string. /// - public sealed partial class BytesValue : pb::IMessage { + public sealed partial class BytesValue : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BytesValue()); + private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -1080,6 +1528,7 @@ public BytesValue() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public BytesValue(BytesValue other) : this() { value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1115,13 +1564,16 @@ public bool Equals(BytesValue other) { return true; } if (Value != other.Value) return false; - return true; + return Equals(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; if (Value.Length != 0) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } return hash; } @@ -1132,11 +1584,31 @@ public override string ToString() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Value.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (Value.Length != 0) { output.WriteRawTag(10); output.WriteBytes(Value); } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1144,6 +1616,9 @@ public int CalculateSize() { if (Value.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeBytesSize(Value); } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } return size; } @@ -1155,15 +1630,37 @@ public void MergeFrom(BytesValue other) { if (other.Value.Length != 0) { Value = other.Value; } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Value = input.ReadBytes(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Value = input.ReadBytes(); @@ -1172,6 +1669,7 @@ public void MergeFrom(pb::CodedInputStream input) { } } } + #endif } diff --git a/csharp/src/Google.Protobuf/WireFormat.cs b/csharp/src/Google.Protobuf/WireFormat.cs index faf1e715ef318..68f0f4a1f5209 100644 --- a/csharp/src/Google.Protobuf/WireFormat.cs +++ b/csharp/src/Google.Protobuf/WireFormat.cs @@ -61,11 +61,11 @@ public enum WireType : uint /// LengthDelimited = 2, /// - /// A "start group" value - not supported by this implementation. + /// A "start group" value /// StartGroup = 3, /// - /// An "end group" value - not supported by this implementation. + /// An "end group" value /// EndGroup = 4, /// @@ -73,7 +73,7 @@ public enum WireType : uint /// Fixed32 = 5 } - + private const int TagTypeBits = 3; private const uint TagTypeMask = (1 << TagTypeBits) - 1; @@ -99,6 +99,6 @@ public static int GetTagFieldNumber(uint tag) public static uint MakeTag(int fieldNumber, WireType wireType) { return (uint) (fieldNumber << TagTypeBits) | (uint) wireType; - } + } } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/WriteBufferHelper.cs b/csharp/src/Google.Protobuf/WriteBufferHelper.cs new file mode 100644 index 0000000000000..f2a59bc56f447 --- /dev/null +++ b/csharp/src/Google.Protobuf/WriteBufferHelper.cs @@ -0,0 +1,166 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Buffers; +using System.IO; +using System.Runtime.CompilerServices; +using System.Security; + +namespace Google.Protobuf +{ + /// + /// Abstraction for writing to a steam / IBufferWriter + /// + [SecuritySafeCritical] + internal struct WriteBufferHelper + { + private IBufferWriter bufferWriter; + private CodedOutputStream codedOutputStream; + + public CodedOutputStream CodedOutputStream => codedOutputStream; + + /// + /// Initialize an instance with a coded output stream. + /// This approach is faster than using a constructor because the instance to initialize is passed by reference + /// and we can write directly into it without copying. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Initialize(CodedOutputStream codedOutputStream, out WriteBufferHelper instance) + { + instance.bufferWriter = null; + instance.codedOutputStream = codedOutputStream; + } + + /// + /// Initialize an instance with a buffer writer. + /// This approach is faster than using a constructor because the instance to initialize is passed by reference + /// and we can write directly into it without copying. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Initialize(IBufferWriter bufferWriter, out WriteBufferHelper instance, out Span buffer) + { + instance.bufferWriter = bufferWriter; + instance.codedOutputStream = null; + buffer = default; // TODO: initialize the initial buffer so that the first write is not via slowpath. + } + + /// + /// Initialize an instance with a buffer represented by a single span (i.e. buffer cannot be refreshed) + /// This approach is faster than using a constructor because the instance to initialize is passed by reference + /// and we can write directly into it without copying. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void InitializeNonRefreshable(out WriteBufferHelper instance) + { + instance.bufferWriter = null; + instance.codedOutputStream = null; + } + + /// + /// Verifies that SpaceLeft returns zero. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CheckNoSpaceLeft(ref WriterInternalState state) + { + if (GetSpaceLeft(ref state) != 0) + { + throw new InvalidOperationException("Did not write as much data as expected."); + } + } + + /// + /// If writing to a flat array, returns the space left in the array. Otherwise, + /// throws an InvalidOperationException. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetSpaceLeft(ref WriterInternalState state) + { + if (state.writeBufferHelper.codedOutputStream?.InternalOutputStream == null && state.writeBufferHelper.bufferWriter == null) + { + return state.limit - state.position; + } + else + { + throw new InvalidOperationException( + "SpaceLeft can only be called on CodedOutputStreams that are " + + "writing to a flat array or when writing to a single span."); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static void RefreshBuffer(ref Span buffer, ref WriterInternalState state) + { + if (state.writeBufferHelper.codedOutputStream?.InternalOutputStream != null) + { + // because we're using coded output stream, we know that "buffer" and codedOutputStream.InternalBuffer are identical. + state.writeBufferHelper.codedOutputStream.InternalOutputStream.Write(state.writeBufferHelper.codedOutputStream.InternalBuffer, 0, state.position); + // reset position, limit stays the same because we are reusing the codedOutputStream's internal buffer. + state.position = 0; + } + else if (state.writeBufferHelper.bufferWriter != null) + { + // commit the bytes and get a new buffer to write to. + state.writeBufferHelper.bufferWriter.Advance(state.position); + state.position = 0; + buffer = state.writeBufferHelper.bufferWriter.GetSpan(); + state.limit = buffer.Length; + } + else + { + // We're writing to a single buffer. + throw new CodedOutputStream.OutOfSpaceException(); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Flush(ref Span buffer, ref WriterInternalState state) + { + if (state.writeBufferHelper.codedOutputStream?.InternalOutputStream != null) + { + // because we're using coded output stream, we know that "buffer" and codedOutputStream.InternalBuffer are identical. + state.writeBufferHelper.codedOutputStream.InternalOutputStream.Write(state.writeBufferHelper.codedOutputStream.InternalBuffer, 0, state.position); + state.position = 0; + } + else if (state.writeBufferHelper.bufferWriter != null) + { + // calling Advance invalidates the current buffer and we must not continue writing to it, + // so we set the current buffer to point to an empty Span. If any subsequent writes happen, + // the first subsequent write will trigger refresing of the buffer. + state.writeBufferHelper.bufferWriter.Advance(state.position); + state.position = 0; + state.limit = 0; + buffer = default; // invalidate the current buffer + } + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/WriteContext.cs b/csharp/src/Google.Protobuf/WriteContext.cs new file mode 100644 index 0000000000000..e822e1d6da4c6 --- /dev/null +++ b/csharp/src/Google.Protobuf/WriteContext.cs @@ -0,0 +1,371 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Buffers; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; +using Google.Protobuf.Collections; + +namespace Google.Protobuf +{ + /// + /// An opaque struct that represents the current serialization state and is passed along + /// as the serialization proceeds. + /// All the public methods are intended to be invoked only by the generated code, + /// users should never invoke them directly. + /// + [SecuritySafeCritical] + public ref struct WriteContext + { + internal Span buffer; + internal WriterInternalState state; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(ref Span buffer, ref WriterInternalState state, out WriteContext ctx) + { + ctx.buffer = buffer; + ctx.state = state; + } + + /// + /// Creates a WriteContext instance from CodedOutputStream. + /// WARNING: internally this copies the CodedOutputStream's state, so after done with the WriteContext, + /// the CodedOutputStream's state needs to be updated. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(CodedOutputStream output, out WriteContext ctx) + { + ctx.buffer = new Span(output.InternalBuffer); + // ideally we would use a reference to the original state, but that doesn't seem possible + // so we just copy the struct that holds the state. We will need to later store the state back + // into CodedOutputStream if we want to keep it usable. + ctx.state = output.InternalState; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(IBufferWriter output, out WriteContext ctx) + { + ctx.buffer = default; + ctx.state = default; + WriteBufferHelper.Initialize(output, out ctx.state.writeBufferHelper, out ctx.buffer); + ctx.state.limit = ctx.buffer.Length; + ctx.state.position = 0; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(ref Span buffer, out WriteContext ctx) + { + ctx.buffer = buffer; + ctx.state = default; + ctx.state.limit = ctx.buffer.Length; + ctx.state.position = 0; + WriteBufferHelper.InitializeNonRefreshable(out ctx.state.writeBufferHelper); + } + + /// + /// Writes a double field value, without a tag. + /// + /// The value to write + public void WriteDouble(double value) + { + WritingPrimitives.WriteDouble(ref buffer, ref state, value); + } + + /// + /// Writes a float field value, without a tag. + /// + /// The value to write + public void WriteFloat(float value) + { + WritingPrimitives.WriteFloat(ref buffer, ref state, value); + } + + /// + /// Writes a uint64 field value, without a tag. + /// + /// The value to write + public void WriteUInt64(ulong value) + { + WritingPrimitives.WriteUInt64(ref buffer, ref state, value); + } + + /// + /// Writes an int64 field value, without a tag. + /// + /// The value to write + public void WriteInt64(long value) + { + WritingPrimitives.WriteInt64(ref buffer, ref state, value); + } + + /// + /// Writes an int32 field value, without a tag. + /// + /// The value to write + public void WriteInt32(int value) + { + WritingPrimitives.WriteInt32(ref buffer, ref state, value); + } + + /// + /// Writes a fixed64 field value, without a tag. + /// + /// The value to write + public void WriteFixed64(ulong value) + { + WritingPrimitives.WriteFixed64(ref buffer, ref state, value); + } + + /// + /// Writes a fixed32 field value, without a tag. + /// + /// The value to write + public void WriteFixed32(uint value) + { + WritingPrimitives.WriteFixed32(ref buffer, ref state, value); + } + + /// + /// Writes a bool field value, without a tag. + /// + /// The value to write + public void WriteBool(bool value) + { + WritingPrimitives.WriteBool(ref buffer, ref state, value); + } + + /// + /// Writes a string field value, without a tag. + /// The data is length-prefixed. + /// + /// The value to write + public void WriteString(string value) + { + WritingPrimitives.WriteString(ref buffer, ref state, value); + } + + /// + /// Writes a message, without a tag. + /// The data is length-prefixed. + /// + /// The value to write + public void WriteMessage(IMessage value) + { + WritingPrimitivesMessages.WriteMessage(ref this, value); + } + + /// + /// Writes a group, without a tag, to the stream. + /// + /// The value to write + public void WriteGroup(IMessage value) + { + WritingPrimitivesMessages.WriteGroup(ref this, value); + } + + /// + /// Write a byte string, without a tag, to the stream. + /// The data is length-prefixed. + /// + /// The value to write + public void WriteBytes(ByteString value) + { + WritingPrimitives.WriteBytes(ref buffer, ref state, value); + } + + /// + /// Writes a uint32 value, without a tag. + /// + /// The value to write + public void WriteUInt32(uint value) + { + WritingPrimitives.WriteUInt32(ref buffer, ref state, value); + } + + /// + /// Writes an enum value, without a tag. + /// + /// The value to write + public void WriteEnum(int value) + { + WritingPrimitives.WriteEnum(ref buffer, ref state, value); + } + + /// + /// Writes an sfixed32 value, without a tag. + /// + /// The value to write. + public void WriteSFixed32(int value) + { + WritingPrimitives.WriteSFixed32(ref buffer, ref state, value); + } + + /// + /// Writes an sfixed64 value, without a tag. + /// + /// The value to write + public void WriteSFixed64(long value) + { + WritingPrimitives.WriteSFixed64(ref buffer, ref state, value); + } + + /// + /// Writes an sint32 value, without a tag. + /// + /// The value to write + public void WriteSInt32(int value) + { + WritingPrimitives.WriteSInt32(ref buffer, ref state, value); + } + + /// + /// Writes an sint64 value, without a tag. + /// + /// The value to write + public void WriteSInt64(long value) + { + WritingPrimitives.WriteSInt64(ref buffer, ref state, value); + } + + /// + /// Writes a length (in bytes) for length-delimited data. + /// + /// + /// This method simply writes a rawint, but exists for clarity in calling code. + /// + /// Length value, in bytes. + public void WriteLength(int length) + { + WritingPrimitives.WriteLength(ref buffer, ref state, length); + } + + /// + /// Encodes and writes a tag. + /// + /// The number of the field to write the tag for + /// The wire format type of the tag to write + public void WriteTag(int fieldNumber, WireFormat.WireType type) + { + WritingPrimitives.WriteTag(ref buffer, ref state, fieldNumber, type); + } + + /// + /// Writes an already-encoded tag. + /// + /// The encoded tag + public void WriteTag(uint tag) + { + WritingPrimitives.WriteTag(ref buffer, ref state, tag); + } + + /// + /// Writes the given single-byte tag. + /// + /// The encoded tag + public void WriteRawTag(byte b1) + { + WritingPrimitives.WriteRawTag(ref buffer, ref state, b1); + } + + /// + /// Writes the given two-byte tag. + /// + /// The first byte of the encoded tag + /// The second byte of the encoded tag + public void WriteRawTag(byte b1, byte b2) + { + WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2); + } + + /// + /// Writes the given three-byte tag. + /// + /// The first byte of the encoded tag + /// The second byte of the encoded tag + /// The third byte of the encoded tag + public void WriteRawTag(byte b1, byte b2, byte b3) + { + WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3); + } + + /// + /// Writes the given four-byte tag. + /// + /// The first byte of the encoded tag + /// The second byte of the encoded tag + /// The third byte of the encoded tag + /// The fourth byte of the encoded tag + public void WriteRawTag(byte b1, byte b2, byte b3, byte b4) + { + WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3, b4); + } + + /// + /// Writes the given five-byte tag. + /// + /// The first byte of the encoded tag + /// The second byte of the encoded tag + /// The third byte of the encoded tag + /// The fourth byte of the encoded tag + /// The fifth byte of the encoded tag + public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5) + { + WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3, b4, b5); + } + + internal void Flush() + { + WriteBufferHelper.Flush(ref buffer, ref state); + } + + internal void CheckNoSpaceLeft() + { + WriteBufferHelper.CheckNoSpaceLeft(ref state); + } + + internal void CopyStateTo(CodedOutputStream output) + { + output.InternalState = state; + } + + internal void LoadStateFrom(CodedOutputStream output) + { + state = output.InternalState; + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/WriterInternalState.cs b/csharp/src/Google.Protobuf/WriterInternalState.cs new file mode 100644 index 0000000000000..a779305bb7301 --- /dev/null +++ b/csharp/src/Google.Protobuf/WriterInternalState.cs @@ -0,0 +1,62 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Buffers; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; +using Google.Protobuf.Collections; + +namespace Google.Protobuf +{ + + // warning: this is a mutable struct, so it needs to be only passed as a ref! + internal struct WriterInternalState + { + // NOTE: the Span representing the current buffer is kept separate so that this doesn't have to be a ref struct and so it can + // be included in CodedOutputStream's internal state + + internal int limit; // the size of the current buffer + internal int position; // position in the current buffer + + internal WriteBufferHelper writeBufferHelper; + + // If non-null, the top level parse method was started with given coded output stream as an argument + // which also means we can potentially fallback to calling WriteTo(CodedOutputStream cos) if needed. + internal CodedOutputStream CodedOutputStream => writeBufferHelper.CodedOutputStream; + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/WritingPrimitives.cs b/csharp/src/Google.Protobuf/WritingPrimitives.cs new file mode 100644 index 0000000000000..cf8fc7ba71fd1 --- /dev/null +++ b/csharp/src/Google.Protobuf/WritingPrimitives.cs @@ -0,0 +1,654 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Buffers.Binary; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; + +namespace Google.Protobuf +{ + /// + /// Primitives for encoding protobuf wire format. + /// + [SecuritySafeCritical] + internal static class WritingPrimitives + { + // "Local" copy of Encoding.UTF8, for efficiency. (Yes, it makes a difference.) + internal static readonly Encoding Utf8Encoding = Encoding.UTF8; + + #region Writing of values (not including tags) + + /// + /// Writes a double field value, without a tag, to the stream. + /// + public static void WriteDouble(ref Span buffer, ref WriterInternalState state, double value) + { + WriteRawLittleEndian64(ref buffer, ref state, (ulong)BitConverter.DoubleToInt64Bits(value)); + } + + /// + /// Writes a float field value, without a tag, to the stream. + /// + public static unsafe void WriteFloat(ref Span buffer, ref WriterInternalState state, float value) + { + const int length = sizeof(float); + if (buffer.Length - state.position >= length) + { + // if there's enough space in the buffer, write the float directly into the buffer + var floatSpan = buffer.Slice(state.position, length); + Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(floatSpan), value); + + if (!BitConverter.IsLittleEndian) + { + floatSpan.Reverse(); + } + state.position += length; + } + else + { + WriteFloatSlowPath(ref buffer, ref state, value); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static unsafe void WriteFloatSlowPath(ref Span buffer, ref WriterInternalState state, float value) + { + const int length = sizeof(float); + + // TODO(jtattermusch): deduplicate the code. Populating the span is the same as for the fastpath. + Span floatSpan = stackalloc byte[length]; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(floatSpan), value); + if (!BitConverter.IsLittleEndian) + { + floatSpan.Reverse(); + } + + WriteRawByte(ref buffer, ref state, floatSpan[0]); + WriteRawByte(ref buffer, ref state, floatSpan[1]); + WriteRawByte(ref buffer, ref state, floatSpan[2]); + WriteRawByte(ref buffer, ref state, floatSpan[3]); + } + + /// + /// Writes a uint64 field value, without a tag, to the stream. + /// + public static void WriteUInt64(ref Span buffer, ref WriterInternalState state, ulong value) + { + WriteRawVarint64(ref buffer, ref state, value); + } + + /// + /// Writes an int64 field value, without a tag, to the stream. + /// + public static void WriteInt64(ref Span buffer, ref WriterInternalState state, long value) + { + WriteRawVarint64(ref buffer, ref state, (ulong)value); + } + + /// + /// Writes an int32 field value, without a tag, to the stream. + /// + public static void WriteInt32(ref Span buffer, ref WriterInternalState state, int value) + { + if (value >= 0) + { + WriteRawVarint32(ref buffer, ref state, (uint)value); + } + else + { + // Must sign-extend. + WriteRawVarint64(ref buffer, ref state, (ulong)value); + } + } + + /// + /// Writes a fixed64 field value, without a tag, to the stream. + /// + public static void WriteFixed64(ref Span buffer, ref WriterInternalState state, ulong value) + { + WriteRawLittleEndian64(ref buffer, ref state, value); + } + + /// + /// Writes a fixed32 field value, without a tag, to the stream. + /// + public static void WriteFixed32(ref Span buffer, ref WriterInternalState state, uint value) + { + WriteRawLittleEndian32(ref buffer, ref state, value); + } + + /// + /// Writes a bool field value, without a tag, to the stream. + /// + public static void WriteBool(ref Span buffer, ref WriterInternalState state, bool value) + { + WriteRawByte(ref buffer, ref state, value ? (byte)1 : (byte)0); + } + + /// + /// Writes a string field value, without a tag, to the stream. + /// The data is length-prefixed. + /// + public static void WriteString(ref Span buffer, ref WriterInternalState state, string value) + { + const int MaxBytesPerChar = 3; + const int MaxSmallStringLength = 128 / MaxBytesPerChar; + + // The string is small enough that the length will always be a 1 byte varint. + // Also there is enough space to write length + bytes to buffer. + // Write string directly to the buffer, and then write length. + // This saves calling GetByteCount on the string. We get the string length from GetBytes. + if (value.Length <= MaxSmallStringLength && buffer.Length - state.position - 1 >= value.Length * MaxBytesPerChar) + { + int indexOfLengthDelimiter = state.position++; + buffer[indexOfLengthDelimiter] = (byte)WriteStringToBuffer(buffer, ref state, value); + return; + } + + int length = Utf8Encoding.GetByteCount(value); + WriteLength(ref buffer, ref state, length); + + // Optimise the case where we have enough space to write + // the string directly to the buffer, which should be common. + if (buffer.Length - state.position >= length) + { + if (length == value.Length) // Must be all ASCII... + { + for (int i = 0; i < length; i++) + { + buffer[state.position + i] = (byte)value[i]; + } + state.position += length; + } + else + { + WriteStringToBuffer(buffer, ref state, value); + } + } + else + { + // Opportunity for future optimization: + // Large strings that don't fit into the current buffer segment + // can probably be optimized by using Utf8Encoding.GetEncoder() + // but more benchmarks would need to be added as evidence. + byte[] bytes = Utf8Encoding.GetBytes(value); + WriteRawBytes(ref buffer, ref state, bytes); + } + } + + private static int WriteStringToBuffer(Span buffer, ref WriterInternalState state, string value) + { +#if NETSTANDARD1_1 + // slowpath when Encoding.GetBytes(Char*, Int32, Byte*, Int32) is not available + byte[] bytes = Utf8Encoding.GetBytes(value); + WriteRawBytes(ref buffer, ref state, bytes); + return bytes.Length; +#else + ReadOnlySpan source = value.AsSpan(); + int bytesUsed; + unsafe + { + fixed (char* sourceChars = &MemoryMarshal.GetReference(source)) + fixed (byte* destinationBytes = &MemoryMarshal.GetReference(buffer)) + { + bytesUsed = Utf8Encoding.GetBytes( + sourceChars, + source.Length, + destinationBytes + state.position, + buffer.Length - state.position); + } + } + state.position += bytesUsed; + return bytesUsed; +#endif + } + + /// + /// Write a byte string, without a tag, to the stream. + /// The data is length-prefixed. + /// + public static void WriteBytes(ref Span buffer, ref WriterInternalState state, ByteString value) + { + WriteLength(ref buffer, ref state, value.Length); + WriteRawBytes(ref buffer, ref state, value.Span); + } + + /// + /// Writes a uint32 value, without a tag, to the stream. + /// + public static void WriteUInt32(ref Span buffer, ref WriterInternalState state, uint value) + { + WriteRawVarint32(ref buffer, ref state, value); + } + + /// + /// Writes an enum value, without a tag, to the stream. + /// + public static void WriteEnum(ref Span buffer, ref WriterInternalState state, int value) + { + WriteInt32(ref buffer, ref state, value); + } + + /// + /// Writes an sfixed32 value, without a tag, to the stream. + /// + public static void WriteSFixed32(ref Span buffer, ref WriterInternalState state, int value) + { + WriteRawLittleEndian32(ref buffer, ref state, (uint)value); + } + + /// + /// Writes an sfixed64 value, without a tag, to the stream. + /// + public static void WriteSFixed64(ref Span buffer, ref WriterInternalState state, long value) + { + WriteRawLittleEndian64(ref buffer, ref state, (ulong)value); + } + + /// + /// Writes an sint32 value, without a tag, to the stream. + /// + public static void WriteSInt32(ref Span buffer, ref WriterInternalState state, int value) + { + WriteRawVarint32(ref buffer, ref state, EncodeZigZag32(value)); + } + + /// + /// Writes an sint64 value, without a tag, to the stream. + /// + public static void WriteSInt64(ref Span buffer, ref WriterInternalState state, long value) + { + WriteRawVarint64(ref buffer, ref state, EncodeZigZag64(value)); + } + + /// + /// Writes a length (in bytes) for length-delimited data. + /// + /// + /// This method simply writes a rawint, but exists for clarity in calling code. + /// + public static void WriteLength(ref Span buffer, ref WriterInternalState state, int length) + { + WriteRawVarint32(ref buffer, ref state, (uint)length); + } + + #endregion + + #region Writing primitives + /// + /// Writes a 32 bit value as a varint. The fast route is taken when + /// there's enough buffer space left to whizz through without checking + /// for each byte; otherwise, we resort to calling WriteRawByte each time. + /// + public static void WriteRawVarint32(ref Span buffer, ref WriterInternalState state, uint value) + { + // Optimize for the common case of a single byte value + if (value < 128 && state.position < buffer.Length) + { + buffer[state.position++] = (byte)value; + return; + } + + // Fast path when capacity is available + while (state.position < buffer.Length) + { + if (value > 127) + { + buffer[state.position++] = (byte)((value & 0x7F) | 0x80); + value >>= 7; + } + else + { + buffer[state.position++] = (byte)value; + return; + } + } + + while (value > 127) + { + WriteRawByte(ref buffer, ref state, (byte)((value & 0x7F) | 0x80)); + value >>= 7; + } + + WriteRawByte(ref buffer, ref state, (byte)value); + } + + public static void WriteRawVarint64(ref Span buffer, ref WriterInternalState state, ulong value) + { + // Optimize for the common case of a single byte value + if (value < 128 && state.position < buffer.Length) + { + buffer[state.position++] = (byte)value; + return; + } + + // Fast path when capacity is available + while (state.position < buffer.Length) + { + if (value > 127) + { + buffer[state.position++] = (byte)((value & 0x7F) | 0x80); + value >>= 7; + } + else + { + buffer[state.position++] = (byte)value; + return; + } + } + + while (value > 127) + { + WriteRawByte(ref buffer, ref state, (byte)((value & 0x7F) | 0x80)); + value >>= 7; + } + + WriteRawByte(ref buffer, ref state, (byte)value); + } + + public static void WriteRawLittleEndian32(ref Span buffer, ref WriterInternalState state, uint value) + { + const int length = sizeof(uint); + if (state.position + length > buffer.Length) + { + WriteRawLittleEndian32SlowPath(ref buffer, ref state, value); + } + else + { + BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(state.position), value); + state.position += length; + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void WriteRawLittleEndian32SlowPath(ref Span buffer, ref WriterInternalState state, uint value) + { + WriteRawByte(ref buffer, ref state, (byte)value); + WriteRawByte(ref buffer, ref state, (byte)(value >> 8)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 16)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 24)); + } + + public static void WriteRawLittleEndian64(ref Span buffer, ref WriterInternalState state, ulong value) + { + const int length = sizeof(ulong); + if (state.position + length > buffer.Length) + { + WriteRawLittleEndian64SlowPath(ref buffer, ref state, value); + } + else + { + BinaryPrimitives.WriteUInt64LittleEndian(buffer.Slice(state.position), value); + state.position += length; + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static void WriteRawLittleEndian64SlowPath(ref Span buffer, ref WriterInternalState state, ulong value) + { + WriteRawByte(ref buffer, ref state, (byte)value); + WriteRawByte(ref buffer, ref state, (byte)(value >> 8)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 16)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 24)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 32)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 40)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 48)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 56)); + } + + private static void WriteRawByte(ref Span buffer, ref WriterInternalState state, byte value) + { + if (state.position == buffer.Length) + { + WriteBufferHelper.RefreshBuffer(ref buffer, ref state); + } + + buffer[state.position++] = value; + } + + /// + /// Writes out an array of bytes. + /// + public static void WriteRawBytes(ref Span buffer, ref WriterInternalState state, byte[] value) + { + WriteRawBytes(ref buffer, ref state, new ReadOnlySpan(value)); + } + + /// + /// Writes out part of an array of bytes. + /// + public static void WriteRawBytes(ref Span buffer, ref WriterInternalState state, byte[] value, int offset, int length) + { + WriteRawBytes(ref buffer, ref state, new ReadOnlySpan(value, offset, length)); + } + + /// + /// Writes out part of an array of bytes. + /// + public static void WriteRawBytes(ref Span buffer, ref WriterInternalState state, ReadOnlySpan value) + { + if (buffer.Length - state.position >= value.Length) + { + // We have room in the current buffer. + value.CopyTo(buffer.Slice(state.position, value.Length)); + state.position += value.Length; + } + else + { + // When writing to a CodedOutputStream backed by a Stream, we could avoid + // copying the data twice (first copying to the current buffer and + // and later writing from the current buffer to the underlying Stream) + // in some circumstances by writing the data directly to the underlying Stream. + // Current this is not being done to avoid specialcasing the code for + // CodedOutputStream vs IBufferWriter. + int bytesWritten = 0; + while (buffer.Length - state.position < value.Length - bytesWritten) + { + int length = buffer.Length - state.position; + value.Slice(bytesWritten, length).CopyTo(buffer.Slice(state.position, length)); + bytesWritten += length; + state.position += length; + WriteBufferHelper.RefreshBuffer(ref buffer, ref state); + } + + // copy the remaining data + int remainderLength = value.Length - bytesWritten; + value.Slice(bytesWritten, remainderLength).CopyTo(buffer.Slice(state.position, remainderLength)); + state.position += remainderLength; + } + } + #endregion + + #region Raw tag writing + /// + /// Encodes and writes a tag. + /// + public static void WriteTag(ref Span buffer, ref WriterInternalState state, int fieldNumber, WireFormat.WireType type) + { + WriteRawVarint32(ref buffer, ref state, WireFormat.MakeTag(fieldNumber, type)); + } + + /// + /// Writes an already-encoded tag. + /// + public static void WriteTag(ref Span buffer, ref WriterInternalState state, uint tag) + { + WriteRawVarint32(ref buffer, ref state, tag); + } + + /// + /// Writes the given single-byte tag directly to the stream. + /// + public static void WriteRawTag(ref Span buffer, ref WriterInternalState state, byte b1) + { + WriteRawByte(ref buffer, ref state, b1); + } + + /// + /// Writes the given two-byte tag directly to the stream. + /// + public static void WriteRawTag(ref Span buffer, ref WriterInternalState state, byte b1, byte b2) + { + if (state.position + 2 > buffer.Length) + { + WriteRawTagSlowPath(ref buffer, ref state, b1, b2); + } + else + { + buffer[state.position++] = b1; + buffer[state.position++] = b2; + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void WriteRawTagSlowPath(ref Span buffer, ref WriterInternalState state, byte b1, byte b2) + { + WriteRawByte(ref buffer, ref state, b1); + WriteRawByte(ref buffer, ref state, b2); + } + + /// + /// Writes the given three-byte tag directly to the stream. + /// + public static void WriteRawTag(ref Span buffer, ref WriterInternalState state, byte b1, byte b2, byte b3) + { + if (state.position + 3 > buffer.Length) + { + WriteRawTagSlowPath(ref buffer, ref state, b1, b2, b3); + } + else + { + buffer[state.position++] = b1; + buffer[state.position++] = b2; + buffer[state.position++] = b3; + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void WriteRawTagSlowPath(ref Span buffer, ref WriterInternalState state, byte b1, byte b2, byte b3) + { + WriteRawByte(ref buffer, ref state, b1); + WriteRawByte(ref buffer, ref state, b2); + WriteRawByte(ref buffer, ref state, b3); + } + + /// + /// Writes the given four-byte tag directly to the stream. + /// + public static void WriteRawTag(ref Span buffer, ref WriterInternalState state, byte b1, byte b2, byte b3, byte b4) + { + if (state.position + 4 > buffer.Length) + { + WriteRawTagSlowPath(ref buffer, ref state, b1, b2, b3, b4); + } + else + { + buffer[state.position++] = b1; + buffer[state.position++] = b2; + buffer[state.position++] = b3; + buffer[state.position++] = b4; + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + + private static void WriteRawTagSlowPath(ref Span buffer, ref WriterInternalState state, byte b1, byte b2, byte b3, byte b4) + { + WriteRawByte(ref buffer, ref state, b1); + WriteRawByte(ref buffer, ref state, b2); + WriteRawByte(ref buffer, ref state, b3); + WriteRawByte(ref buffer, ref state, b4); + } + + /// + /// Writes the given five-byte tag directly to the stream. + /// + public static void WriteRawTag(ref Span buffer, ref WriterInternalState state, byte b1, byte b2, byte b3, byte b4, byte b5) + { + if (state.position + 5 > buffer.Length) + { + WriteRawTagSlowPath(ref buffer, ref state, b1, b2, b3, b4, b5); + } + else + { + buffer[state.position++] = b1; + buffer[state.position++] = b2; + buffer[state.position++] = b3; + buffer[state.position++] = b4; + buffer[state.position++] = b5; + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void WriteRawTagSlowPath(ref Span buffer, ref WriterInternalState state, byte b1, byte b2, byte b3, byte b4, byte b5) + { + WriteRawByte(ref buffer, ref state, b1); + WriteRawByte(ref buffer, ref state, b2); + WriteRawByte(ref buffer, ref state, b3); + WriteRawByte(ref buffer, ref state, b4); + WriteRawByte(ref buffer, ref state, b5); + } + #endregion + + /// + /// Encode a 32-bit value with ZigZag encoding. + /// + /// + /// ZigZag encodes signed integers into values that can be efficiently + /// encoded with varint. (Otherwise, negative values must be + /// sign-extended to 64 bits to be varint encoded, thus always taking + /// 10 bytes on the wire.) + /// + public static uint EncodeZigZag32(int n) + { + // Note: the right-shift must be arithmetic + return (uint)((n << 1) ^ (n >> 31)); + } + + /// + /// Encode a 64-bit value with ZigZag encoding. + /// + /// + /// ZigZag encodes signed integers into values that can be efficiently + /// encoded with varint. (Otherwise, negative values must be + /// sign-extended to 64 bits to be varint encoded, thus always taking + /// 10 bytes on the wire.) + /// + public static ulong EncodeZigZag64(long n) + { + return (ulong)((n << 1) ^ (n >> 63)); + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs b/csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs new file mode 100644 index 0000000000000..cd2d4379154e1 --- /dev/null +++ b/csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs @@ -0,0 +1,112 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices.ComTypes; +using System.Security; + +namespace Google.Protobuf +{ + /// + /// Writing messages / groups. + /// + [SecuritySafeCritical] + internal static class WritingPrimitivesMessages + { + /// + /// Writes a message, without a tag. + /// The data is length-prefixed. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteMessage(ref WriteContext ctx, IMessage value) + { + WritingPrimitives.WriteLength(ref ctx.buffer, ref ctx.state, value.CalculateSize()); + WriteRawMessage(ref ctx, value); + } + + /// + /// Writes a group, without a tag. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteGroup(ref WriteContext ctx, IMessage value) + { + WriteRawMessage(ref ctx, value); + } + + /// + /// Writes a message, without a tag. + /// Message will be written without a length prefix. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteRawMessage(ref WriteContext ctx, IMessage message) + { + if (message is IBufferMessage bufferMessage) + { + bufferMessage.InternalWriteTo(ref ctx); + } + else + { + // If we reached here, it means we've ran into a nested message with older generated code + // which doesn't provide the InternalWriteTo method that takes a WriteContext. + // With a slight performance overhead, we can still serialize this message just fine, + // but we need to find the original CodedOutputStream instance that initiated this + // serialization process and make sure its internal state is up to date. + // Note that this performance overhead is not very high (basically copying contents of a struct) + // and it will only be incurred in case the application mixes older and newer generated code. + // Regenerating the code from .proto files will remove this overhead because it will + // generate the InternalWriteTo method we need. + + if (ctx.state.CodedOutputStream == null) + { + // This can only happen when the serialization started without providing a CodedOutputStream instance + // (e.g. WriteContext was created directly from a IBufferWriter). + // That also means that one of the new parsing APIs was used at the top level + // and in such case it is reasonable to require that all the nested message provide + // up-to-date generated code with WriteContext support (and fail otherwise). + throw new InvalidProtocolBufferException($"Message {message.GetType().Name} doesn't provide the generated method that enables WriteContext-based serialization. You might need to regenerate the generated protobuf code."); + } + + ctx.CopyStateTo(ctx.state.CodedOutputStream); + try + { + // fallback parse using the CodedOutputStream that started current serialization tree + message.WriteTo(ctx.state.CodedOutputStream); + } + finally + { + ctx.LoadStateFrom(ctx.state.CodedOutputStream); + } + } + } + } +} \ No newline at end of file diff --git a/docs/csharp/proto2.md b/docs/csharp/proto2.md new file mode 100644 index 0000000000000..53fc43c7ebb1c --- /dev/null +++ b/docs/csharp/proto2.md @@ -0,0 +1,184 @@ +As part of the 3.10 release of Google.Protobuf, experimental proto2 support has been released. This document outlines the new changes brought about to include proto2 support. This does not break existing proto3 support and users may continue to use proto3 features without changing their current code. Again the generated code and public API associated with proto2 is experimental and subject to change in the future. APIs for proto2 may be added, removed, or adjusted as feedback is received. +Generated code for proto2 may also be modified by adding, removing, or adjusting APIs as feedback is received. + +### Enabling proto2 features + +For information about specific proto2 features, please read the [proto2 language guide](https://developers.google.com/protocol-buffers/docs/proto). + +Much like other languages, proto2 features are used with proto2 files with the syntax declaration `syntax = "proto2";`. However, please note, proto3 is still the recommended version of protobuf and proto2 support is meant for legacy system interop and advanced uses. + +# Generated code + +### Messages + +Messages in proto2 files are very similar to their proto3 counterparts. They expose the usual property for getting and setting, but they also include properties and methods to handle field presence. + +For `optional`/`required` field XYZ, a `HasXYZ` property is included for checking presence and a `ClearXYZ` method is included for clearing the value. + +```proto +message Foo { + optional Bar bar = 1; + required Baz baz = 2; +} +``` +```cs +var foo = new Foo(); +Assert.IsNull(foo.Bar); +Assert.False(foo.HasBar); +foo.Bar = new Bar(); +Assert.True(foo.HasBar); +foo.ClearBar(); +``` + +### Messages with extension ranges + +Messages which define extension ranges implement the `IExtendableMessage` interface as shown below. +See inline comments for more info. + +```cs +public interface IExtendableMessage : IMessage where T : IExtendableMessage +{ + // Gets the value of a single value extension. If the extension isn't present, this returns the default value. + TValue GetExtension(Extension extension); + // Gets the value of a repeated extension. If the extension hasn't been set, this returns null to prevent unnecessary allocations. + RepeatedField GetExtension(RepeatedExtension extension); + // Gets the value of a repeated extension. This will initialize the value of the repeated field and will never return null. + RepeatedField GetOrInitializeExtension(RepeatedExtension extension); + // Sets the value of the extension + void SetExtension(Extension extension, TValue value); + // Returns whether the extension is present in the message + bool HasExtension(Extension extension); + // Clears the value of the extension, removing it from the message + void ClearExtension(Extension extension); + // Clears the value of the repeated extension, removing it from the message. Calling GetExtension after this will always return null. + void ClearExtension(RepeatedExtension extension); +} +``` + +### Extensions + +Extensions are generated in static containers like reflection classes and type classes. +For example for a file called `foo.proto` containing extensions in the file scope, a +`FooExtensions` class is created containing the extensions defined in the file scope. +For easy access, this class can be used with `using static` to bring all extensions into scope. + +```proto +option csharp_namespace = "FooBar"; +extend Foo { + optional Baz foo_ext = 124; +} +message Baz { + extend Foo { + repeated Baz repeated_foo_ext = 125; + } +} +``` +```cs +public static partial class FooExtensions { + public static readonly Extension FooExt = /* initialization */; +} + +public partial class Baz { + public partial static class Extensions { + public static readonly RepeatedExtension RepeatedFooExt = /* initialization */; + } +} +``` +```cs +using static FooBar.FooExtensions; +using static FooBar.Baz.Extensions; + +var foo = new Foo(); +foo.SetExtension(FooExt, new Baz()); +foo.GetOrInitializeExtension(RepeatedFooExt).Add(new Baz()); +``` + +# APIs + +### Message initialization + +Initialization refers to checking the status of required fields in a proto2 message. If a message is uninitialized, not all required fields are set in either the message itself or any of its submessages. In other languages, missing required fields throw errors depending on the merge method used. This could cause unforeseen errors at runtime if the incorrect method is used. +However, in this implementation, parsers and input streams don't check messages for initialization on their own and throw errors. Instead it's up to you to handle messages with missing required fields in whatever way you see fit. +Checking message initialization can be done manually via the `IsInitialized` extension method in `MessageExtensions`. + +### Extension registries + +Just like in Java, extension registries can be constructed to parse extensions when reading new messages +from input streams. The API is fairly similar to the Java API with some added bonuses with C# syntax sugars. + +```proto +message Baz { + extend Foo { + optional Baz foo_ext = 124; + } +} +``` +```cs +var registry = new ExtensionRegistry() +{ + Baz.Extensions.FooExt +}; +var foo = Foo.Factory.WithExtensionRegistry(registry).ParseFrom(input); +Assert.True(foo.HasExtension(Bas.Extensions.FooExt)); +var fooNoRegistry = Foo.Factory.ParseFrom(input); +Assert.False(foo.HasExtension(Bas.Extensions.FooExt)); +``` + +### Custom options + +Due to their limited use and lack of type safety, the original `CustomOptions` APIs are now deprecated. Using the new generated extension identifiers, you can access extensions safely through the GetOption APIs. Note that cloneable values such as +repeated fields and messages will be deep cloned. + +Example based on custom options usage example [here](https://github.com/protocolbuffers/protobuf/issues/5007#issuecomment-411604515). +```cs +foreach (var service in input.Services) +{ + Console.WriteLine($" {service.Name}"); + foreach (var method in service.Methods) + { + var rule = method.GetOption(AnnotationsExtensions.Http); + if (rule != null) + { + Console.WriteLine($" {method.Name}: {rule}"); + } + else + { + Console.WriteLine($" {method.Name}: no HTTP binding"); + } + } +} +``` + +### Reflection + +Reflection APIs have been extended to enable accessing the new proto2 portions of the library and generated code. + + * FieldDescriptor.Extension + * Gets the extension identifier behind an extension field, allowing it to be added to an ExtensionRegistry + * FieldDescriptor.IsExtension + * Returns whether a field is an extension of another type. + * FieldDescriptor.ExtendeeType + * Returns the extended type of an extension field + * IFieldAccessor.HasValue + * Returns whether a field's value is set. For proto3 fields, throws an InvalidOperationException. + * FileDescriptor.Syntax + * Gets the syntax of a file + * FileDescriptor.Extensions + * An immutable list of extensions defined in the file + * MessageDescriptor.Extensions + * An immutable list of extensions defined in the message + +```cs +var extensions = Baz.Descriptor.Extensions.GetExtensionsInDeclarationOrder(Foo.Descriptor); +var registry = new ExtensionRegistry(); +registry.AddRange(extensions.Select(f => f.Extension)); + +var baz = Foo.Descriptor.Parser.WithExtensionRegistry(registry).ParseFrom(input); +foreach (var field in extensions) +{ + if (field.Accessor.HasValue(baz)) + { + Console.WriteLine($"{field.Name}: {field.Accessor.GetValue(baz)}"); + } +} +``` diff --git a/docs/field_presence.md b/docs/field_presence.md new file mode 100644 index 0000000000000..dc16292c85110 --- /dev/null +++ b/docs/field_presence.md @@ -0,0 +1,476 @@ +# Application note: Field presence + +This application note explains the various presence tracking disciplines for protobuf fields. It also explains how to enable experimental support for explicit presence tracking for singular proto3 fields with basic types. + +## Background + +_Field presence_ is the notion of whether a protobuf field has a value. There are two different manifestations of presence for protobufs: _no presence_, where the generated message API stores field values (only), and _explicit presence_, where the API also stores whether or not a field has been set. + +Historically, proto2 has mostly followed _explicit presence_, while proto3 exposes only _no presence_ semantics. Singular proto3 fields of basic types (numeric, string, bytes, and enums) which are defined with the `optional` label have _explicit presence_, like proto2 (this is an experimental feature added as of release 3.12, and must be enabled by passing a flag to `protoc`). + +### Presence disciplines + +_Presence disciplines_ define the semantics for translating between the _API representation_ and the _serialized representation_. The _no presence_ discipline relies upon the field value itself to make decisions at (de)serialization time, while the _explicit presence_ discipline relies upon the explicit tracking state instead. + +### Presence in _tag-value stream_ (wire format) serialization + +The wire format is a stream of tagged, _self-delimiting_ values. By definition, the wire format represents a sequence of _present_ values. In other words, every value found within a serialization represents a _present_ field; furthermore, the serialization contains no information about not-present values. + +The generated API for a proto message includes (de)serialization definitions which translate between API types and a stream of definitionally _present_ (tag, value) pairs. This translation is designed to be forward- and backward-compatibile across changes to the message definition; however, this compatibility introduces some (perhaps surprising) considerations when deserializing wire-formatted messages: + +- When serializing, fields with _no presence_ are not serialized if they contain their default value. + - For numeric types, the default is 0. + - For enums, the default is the zero-valued enumerator. + - For strings, bytes, and repeated fields, the default is the zero-length value. + - For messages, the default is the language-specific null value. +- "Empty" length-delimited values (such as empty strings) can be validly represented in serialized values: the field is "present," in the sense that it appears in the wire format. However, if the generated API does not track presence, then these values may not be re-serialized; i.e., the empty field may be "not present" after a serialization round-trip. +- When deserializing, duplicate field values may be handled in different ways depending on the field definition. + - Duplicate `repeated` fields are typically appended to the field's API representation. (Note that serializing a _packed_ repeated field produces only one, length-delimited value in the tag stream.) + - Duplicate `optional` field values follow the rule that "the last one wins." +- `oneof` fields expose the API-level invariant that only one field is set at a time. However, the wire format may include multiple (tag, value) pairs which notionally belong to the `oneof`. Similar to `optional` fields, the generated API follows the "last one wins" rule. +- Out-of-range values are not returned for enum fields in generated proto2 APIs. However, out-of-range values may be stored as _unknown fields_ in the API, even though the wire-format tag was recognized. + +### Presence in _named-field mapping_ formats + +Protobufs can be represented in human-readable, textual forms. Two notable formats are TextFormat (the output format produced by generated message `DebugString` methods) and JSON. + +These formats have correctness requirements of their own, and are generally stricter than _tagged-value stream_ formats. However, TextFormat more closely mimics the semantics of the wire format, and does, in certain cases, provide similar semantics (for example, appending repeated name-value mappings to a repeated field). In particular, similar to the wire format, TextFormat only includes fields which are present. + +JSON is a much stricter format, however, and cannot validly represent some semantics of the wire format or TextFormat. + +- Notably, JSON _elements_ are semantically unordered, and each member must have a unique name. This is different from TextFormat rules for repeated fields. +- JSON may include fields that are "not present," unlike the _no presence_ discipline for other formats: + - JSON defines a `null` value, which may be used to represent a _defined but not-present field_. + - Repeated field values may be included in the formatted output, even if they are equal to the default (an empty list). +- Because JSON elements are unordered, there is no way to unambiguously interpret the "last one wins" rule. + - In most cases, this is fine: JSON elements must have unique names: repeated field values are not valid JSON, so they do not need to be resolved as they are for TextFormat. + - However, this means that it may not be possible to interpret `oneof` fields unambiguously: if multiple cases are present, they are unordered. + +In theory, JSON _can_ represent presence in a semantic-preserving fashion. In practice, however, presence correctness can vary depending upon implementation choices, especially if JSON was chosen as a means to interoperate with clients not using protobufs. + +### Presence in proto2 APIs + +This table outlines whether presence is tracked for fields in proto2 APIs (both for generated APIs and using dynamic reflection): + +Field type | Explicit Presence +-------------------------------------------- | ----------------- +Singular numeric (integer or floating point) | ✔️ +Singular enum | ✔️ +Singular string or bytes | ✔️ +Singular message | ✔️ +Repeated | +Oneofs | ✔️ +Maps | + +Singular fields (of all types) track presence explicitly in the generated API. The generated message interface includes methods to query presence of fields. For example, the field `foo` has a corresponding `has_foo` method. (The specific name follows the same language-specific naming convention as the field accessors.) These methods are sometimes referred to as "hazzers" within the protobuf implementation. + +Similar to singular fields, `oneof` fields explicitly track which one of the members, if any, contains a value. For example, consider this example `oneof`: + +``` +oneof foo { + int32 a = 1; + float b = 2; +} +``` + +Depending on the target language, the generated API would generally include several methods: + +- A hazzer for the oneof: `has_foo` +- A _oneof case_ method: `foo` +- Hazzers for the members: `has_a`, `has_b` +- Getters for the members: `a`, `b` + +Repeated fields and maps do not track presence: there is no distinction between an _empty_ and a _not-present_ repeated field. + +### Presence in proto3 APIs + +This table outlines whether presence is tracked for fields in proto3 APIs (both for generated APIs and using dynamic reflection): + +Field type | `optional` | Explicit Presence +-------------------------------------------- | ---------- | ----------------- +Singular numeric (integer or floating point) | No | +Singular enum | No | +Singular string or bytes | No | +Singular numeric (integer or floating point) | Yes | ✔️ +Singular enum | Yes | ✔️ +Singular string or bytes | Yes | ✔️ +Singular message | Yes | ✔️ +Singular message | No | ✔️ +Repeated | N/A | +Oneofs | N/A | ✔️ +Maps | N/A | + +Similar to proto2 APIs, proto3 does not track presence explicitly for repeated fields. Without the `optional` label, proto3 APIs do not track presence for basic types (numeric, string, bytes, and enums), either. (Note that `optional` for proto3 fields is only experimentally available as of release 3.12.) Oneof fields affirmatively expose presence, although the same set of hazzer methods may not generated as in proto2 APIs. + +Under the _no presence_ discipline, the default value is synonymous with "not present" for purposes of serialization. To notionally "clear" a field (so it won't be serialized), an API user would set it to the default value. + +The default value for enum-typed fields under _no presence_ is the corresponding 0-valued enumerator. Under proto3 syntax rules, all enum types are required to have an enumerator value which maps to 0. By convention, this is an `UNKNOWN` or similarly-named enumerator. If the zero value is notionally outside the domain of valid values for the application, this behavior can be thought of as tantamount to _explicit presence_. + +## Semantic differences + +The _no presence_ serialization discipline results in visible differences from the _explicit presence_ tracking discipline, when the default value is set. For a singular field with numeric, enum, or string type: + +- _No presence_ discipline: + - Default values are not serialized. + - Default values are _not_ merged-from. + - To "clear" a field, it is set to its default value. + - The default value may mean: + - the field was explicitly set to its default value, which is valid in the application-specific domain of values; + - the field was notionally "cleared" by setting its default; or + - the field was never set. +- _Explicit presence_ discipline: + - Explicitly set values are always serialized, including default values. + - Un-set fields are never merged-from. + - Explicitly set fields -- including default values -- _are_ merged-from. + - A generated `has_foo` method indicates whether or not the field `foo` has been set (and not cleared). + - A generated `clear_foo` method must be used to clear (i.e., un-set) the value. + +### Considerations for merging + +Under the _no presence_ rules, it is effectively impossible for a target field to merge-from its default value (using the protobuf's API merging functions). This is because default values are skipped, similar to the _no presence_ serialization discipline. Merging only updates the target (merged-to) message using the non-skipped values from the update (merged-from) message. + +The difference in merging behavior has further implications for protocols which rely on partial "patch" updates. If field presence is not tracked, then an update patch alone cannot represent an update to the default value, because only non-default values are merged-from. + +Updating to set a default value in this case requires some external mechanism, such as `FieldMask`. However, if presence _is_ tracked, then all explicitly-set values -- even default values -- will be merged into the target. + +### Considerations for change-compatibility + +Changing a field between _explicit presence_ and _no presence_ is a binary-compatible change for serialized values in wire format. However, the serialized representation of the message may differ, depending on which version of the message definition was used for serialization. Specifically, when a "sender" explicitly sets a field to its default value: + +- The serialized value following _no presence_ discipline does not contain the default value, even though it was explicitly set. +- The serialized value following _explicit presence_ discipline contains every "present" field, even if it contains the default value. + +This change may or may not be safe, depending on the application's semantics. For example, consider two clients with different versions of a message definition. + +Client A uses this definition of the message, which follows the _explicit presence_ serialization discipline for field `foo`: + +``` +syntax = "proto3"; +message Msg { + optional int32 foo = 1; +} +``` + +Client B uses a definition of the same message, except that it follows the _no presence_ discipline: + +``` +syntax = "proto3"; +message Msg { + int32 foo = 1; +} +``` + +Now, consider a scenario where client A observes `foo`'s presence as the clients repeatedly exchange the "same" message by deserializing and reserializing: + +``` +// Client A: +Msg m_a; +m_a.set_foo(1); // non-default value +assert(m_a.has_foo()); // OK +Send(m_a.SerializeAsString()); // to client B + +// Client B: +Msg m_b; +m_b.ParseFromString(Receive()); // from client A +assert(m_b.foo() == 1); // OK +Send(m_b.SerializeAsString()); // to client A + +// Client A: +m_a.ParseFromString(Receive()); // from client B +assert(m_a.foo() == 1); // OK +assert(m_a.has_foo()); // OK +m_a.set_foo(0); // default value +Send(m_a.SerializeAsString()); // to client B + +// Client B: +Msg m_b; +m_b.ParseFromString(Receive()); // from client A +assert(m_b.foo() == 0); // OK +Send(m_b.SerializeAsString()); // to client A + +// Client A: +m_a.ParseFromString(Receive()); // from client B +assert(m_a.foo() == 0); // OK +assert(m_a.has_foo()); // FAIL +``` + +If client A depends on _explicit presence_ for `foo`, then a "round trip" through client B will be lossy from the perspective of client A. In the example, this is not a safe change: client A requires (by `assert`) that the field is present; even without any modifications through the API, that requirement fails in a value- and peer-dependent case. + +## How to enable _explicit presence_ in proto3 + +These are the general steps to use the experimental field tracking support for proto3: + +1. Add an `optional` field to a `.proto` file. +1. Run `protoc` (from release 3.12 or later) with an extra flag to recognize `optional` (i.e,. explicit presence) in proto3 files. +1. Use the generated "hazzer" methods and "clear" methods in application code, instead of comparing or setting default values. + +### `.proto` file changes + +This is an example of a proto3 message with fields which follow both _no presence_ and _explicit presence_ semantics: + +``` +syntax = "proto3"; +package example; + +message MyMessage { + // No presence: + int32 not_tracked = 1; + + // Explicit presence: + optional int32 tracked = 2; +} +``` + +### `protoc` invocation + +To enable presence tracking for proto3 messages, pass the `--experimental_allow_proto3_optional` flag to protoc. Without this flag, the `optional` label is an error in files using proto3 syntax. This flag is available in protobuf release 3.12 or later (or at HEAD, if you are reading this application note from Git). + +### Using the generated code + +The generated code for proto3 fields with _explicit presence_ (the `optional` label) will be the same as it would be in a proto2 file. + +This is the definition used in the "no presence" examples below: + +``` +syntax = "proto3"; +package example; +message Msg { + int32 foo = 1; +} +``` + +This is the definition used in the "explicit presence" examples below: + +``` +syntax = "proto3"; +package example; +message Msg { + optional int32 foo = 1; +} +``` + +In the examples, a function `GetProto` constructs and returns a message of type `Msg` with unspecified contents. + +#### C++ example + +No presence: + +``` +Msg m = GetProto(); +if (m.foo() != 0) { + // "Clear" the field: + m.set_foo(0); +} else { + // Default value: field may not have been present. + m.set_foo(1); +} +``` + +Explicit presence: + +``` +Msg m = GetProto(); +if (m.has_foo()) { + // Clear the field: + m.clear_foo(); +} else { + // Field is not present, so set it. + m.set_foo(1); +} +``` + +#### C# example + +No presence: + +``` +var m = GetProto(); +if (m.Foo != 0) { + // "Clear" the field: + m.Foo = 0; +} else { + // Default value: field may not have been present. + m.Foo = 1; +} +``` + +Explicit presence: + +``` +var m = GetProto(); +if (m.HasFoo) { + // Clear the field: + m.ClearFoo(); +} else { + // Field is not present, so set it. + m.Foo = 1; +} +``` + +#### Go example + +No presence: + +``` +m := GetProto() +if (m.GetFoo() != 0) { + // "Clear" the field: + m.Foo = 0; +} else { + // Default value: field may not have been present. + m.Foo = 1; +} +``` + +Explicit presence: + +``` +m := GetProto() +if (m.HasFoo()) { + // Clear the field: + m.Foo = nil +} else { + // Field is not present, so set it. + m.Foo = proto.Int32(1); +} +``` + +#### Java example + +These examples use a `Builder` to demonstrate clearing. Simply checking presence and getting values from a `Builder` follows the same API as the message type. + +No presence: + +``` +Msg.Builder m = GetProto().toBuilder(); +if (m.getFoo() != 0) { + // "Clear" the field: + m.setFoo(0); +} else { + // Default value: field may not have been present. + m.setFoo(1); +} +``` + +Explicit presence: + +``` +Msg.Builder m = GetProto().toBuilder(); +if (m.hasFoo()) { + // Clear the field: + m.clearFoo() +} else { + // Field is not present, so set it. + m.setFoo(1); +} +``` + +#### Python example + +No presence: + +``` +m = example.Msg() +if m.foo != 0: + // "Clear" the field: + m.foo = 0 +else: + // Default value: field may not have been present. + m.foo = 1 +``` + +Explicit presence: + +``` +m = example.Msg() +if m.HasField('foo'): + // Clear the field: + m.ClearField('foo') +else: + // Field is not present, so set it. + m.foo = 1 +``` + +#### Ruby example + +No presence: + +``` +m = Msg.new +if m.foo != 0 + // "Clear" the field: + m.foo = 0 +else + // Default value: field may not have been present. + m.foo = 1 +end +``` + +Explicit presence: + +``` +m = Msg.new +if m.has_foo? + // Clear the field: + m.clear_foo +else + // Field is not present, so set it. + m.foo = 1 +end +``` + +#### Javascript example + +No presence: + +``` +var m = new Msg(); +if (m.getFoo() != 0) { + // "Clear" the field: + m.setFoo(0); +} else { + // Default value: field may not have been present. + m.setFoo(1); +} +``` + +Explicit presence: + +``` +var m = new Msg(); +if (m.hasFoo()) { + // Clear the field: + m.clearFoo() +} else { + // Field is not present, so set it. + m.setFoo(1); +} +``` + +#### Objective C example + +No presence: + +``` +Msg *m = [[Msg alloc] init]; +if (m.foo != 0) { + // "Clear" the field: + m.foo = 0; +} else { + // Default value: field may not have been present. + m.foo = 1; +} +``` + +Explicit presence: + +``` +Msg *m = [[Msg alloc] init]; +if (m.hasFoo()) { + // Clear the field: + [m clearFoo]; +} else { + // Field is not present, so set it. + [m setFoo:1]; +} +``` diff --git a/docs/implementing_proto3_presence.md b/docs/implementing_proto3_presence.md new file mode 100644 index 0000000000000..73f21a3829846 --- /dev/null +++ b/docs/implementing_proto3_presence.md @@ -0,0 +1,400 @@ +# How To Implement Field Presence for Proto3 + +Protobuf release 3.12 adds experimental support for `optional` fields in +proto3. Proto3 optional fields track presence like in proto2. For background +information about what presence tracking means, please see +[docs/field_presence](field_presence.md). + +## Document Summary + +This document is targeted at developers who own or maintain protobuf code +generators. All code generators will need to be updated to support proto3 +optional fields. First-party code generators developed by Google are being +updated already. However third-party code generators will need to be updated +independently by their authors. This includes: + +- implementations of Protocol Buffers for other languages. +- alternate implementations of Protocol Buffers that target specialized use + cases. +- RPC code generators that create generated APIs for service calls. +- code generators that implement some utility code on top of protobuf generated + classes. + +While this document speaks in terms of "code generators", these same principles +apply to implementations that dynamically generate a protocol buffer API "on the +fly", directly from a descriptor, in languages that support this kind of usage. + +## Background + +Presence tracking was added to proto3 in response to user feedback, both from +inside Google and [from open-source +users](https://github.com/protocolbuffers/protobuf/issues/1606). The [proto3 +wrapper +types](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/wrappers.proto) +were previously the only supported presence mechanism for proto3. Users have +pointed to both efficiency and usability issues with the wrapper types. + +Presence in proto3 uses exactly the same syntax and semantics as in proto2. +Proto3 Fields marked `optional` will track presence like proto2, while fields +without any label (known as "singular fields"), will continue to omit presence +information. The `optional` keyword was chosen to minimize differences with +proto2. + +Unfortunately, for the current descriptor protos and `Descriptor` API (as of +3.11.4) it is not possible to use the same representation as proto2. Proto3 +descriptors already use `LABEL_OPTIONAL` for proto3 singular fields, which do +not track presence. There is a lot of existing code that reflects over proto3 +protos and assumes that `LABEL_OPTIONAL` in proto3 means "no presence." Changing +the semantics now would be risky, since old software would likely drop proto3 +presence information, which would be a data loss bug. + +To minimize this risk we chose a descriptor representation that is semantically +compatible with existing proto3 reflection. Every proto3 optional field is +placed into a one-field `oneof`. We call this a "synthetic" oneof, as it was not +present in the source `.proto` file. + +Since oneof fields in proto3 already track presence, existing proto3 +reflection-based algorithms should correctly preserve presence for proto3 +optional fields with no code changes. For example, the JSON and TextFormat +parsers/serializers in C++ and Java did not require any changes to support +proto3 presence. This is the major benefit of synthetic oneofs. + +This design does leave some cruft in descriptors. Synthetic oneofs are a +compatibility measure that we can hopefully clean up in the future. For now +though, it is important to preserve them across different descriptor formats and +APIs. It is never safe to drop synthetic oneofs from a proto schema. Code +generators can (and should) skip synthetic oneofs when generating a user-facing +API or user-facing documentation. But for any schema representation that is +consumed programmatically, it is important to keep the synthetic oneofs around. + +In APIs it can be helpful to offer separate accessors that refer to "real" +oneofs (see [API Changes](#api-changes) below). This is a convenient way to omit +synthetic oneofs in code generators. + +## Updating a Code Generator + +When a user adds an `optional` field to proto3, this is internally rewritten as +a one-field oneof, for backward-compatibility with reflection-based algorithms: + +```protobuf +syntax = "proto3"; + +message Foo { + // Experimental feature, not generally supported yet! + optional int32 foo = 1; + + // Internally rewritten to: + // oneof _foo { + // int32 foo = 1 [proto3_optional=true]; + // } + // + // We call _foo a "synthetic" oneof, since it was not created by the user. +} +``` + +As a result, the main two goals when updating a code generator are: + +1. Give `optional` fields like `foo` normal field presence, as described in + [docs/field_presence](field_presence.md) If your implementation already + supports proto2, a proto3 `optional` field should use exactly the same API + and internal implementation as proto2 `optional`. +2. Avoid generating any oneof-based accessors for the synthetic oneof. Its only + purpose is to make reflection-based algorithms work properly if they are + not aware of proto3 presence. The synthetic oneof should not appear anywhere + in the generated API. + +### Satisfying the Experimental Check + +If you try to run `protoc` on a file with proto3 `optional` fields, you will get +an error because the feature is still experimental: + +``` +$ cat test.proto +syntax = "proto3"; + +message Foo { + // Experimental feature, not generally supported yet! + optional int32 a = 1; +} +$ protoc --cpp_out=. test.proto +test.proto: This file contains proto3 optional fields, but --experimental_allow_proto3_optional was not set. +``` + +There are two options for getting around this error: + +1. Pass `--experimental_allow_proto3_optional` to protoc. +2. Make your filename (or a directory name) contain the string + `test_proto3_optional`. This indicates that the proto file is specifically + for testing proto3 optional support, so the check is suppressed. + +These options are demonstrated below: + +``` +# One option: +$ ./src/protoc test.proto --cpp_out=. --experimental_allow_proto3_optional + +# Another option: +$ cp test.proto test_proto3_optional.proto +$ ./src/protoc test_proto3_optional.proto --cpp_out=. +$ +``` + +The experimental check will be removed in a future release, once we are ready +to make this feature generally available. Ideally this will happen for the 3.13 +release of protobuf, sometime in mid-2020, but there is not a specific date set +for this yet. Some of the timing will depend on feedback we get from the +community, so if you have questions or concerns please get in touch via a +GitHub issue. + +### Signaling That Your Code Generator Supports Proto3 Optional + +If you now try to invoke your own code generator with the test proto, you will +run into a different error: + +``` +$ ./src/protoc test_proto3_optional.proto --my_codegen_out=. +test_proto3_optional.proto: is a proto3 file that contains optional fields, but +code generator --my_codegen_out hasn't been updated to support optional fields in +proto3. Please ask the owner of this code generator to support proto3 optional. +``` + +This check exists to make sure that code generators get a chance to update +before they are used with proto3 `optional` fields. Without this check an old +code generator might emit obsolete generated APIs (like accessors for a +synthetic oneof) and users could start depending on these. That would create +a legacy migration burden once a code generator actually implements the feature. + +To signal that your code generator supports `optional` fields in proto3, you +need to tell `protoc` what features you support. The method for doing this +depends on whether you are using the C++ +`google::protobuf::compiler::CodeGenerator` +framework or not. + +If you are using the CodeGenerator framework: + +```c++ +class MyCodeGenerator : public google::protobuf::compiler::CodeGenerator { + // Add this method. + uint64_t GetSupportedFeatures() const override { + // Indicate that this code generator supports proto3 optional fields. + // (Note: don't release your code generator with this flag set until you + // have actually added and tested your proto3 support!) + return FEATURE_PROTO3_OPTIONAL; + } +} +``` + +If you are generating code using raw `CodeGeneratorRequest` and +`CodeGeneratorResponse` messages from `plugin.proto`, the change will be very +similar: + +```c++ +void GenerateResponse() { + CodeGeneratorResponse response; + response.set_supported_features(CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL); + + // Generate code... +} +``` + +Once you have added this, you should now be able to successfully use your code +generator to generate a file containing proto3 optional fields: + +``` +$ ./src/protoc test_proto3_optional.proto --my_codegen_out=. +``` + +### Updating Your Code Generator + +Now to actually add support for proto3 optional to your code generator. The goal +is to recognize proto3 optional fields as optional, and suppress any output from +synthetic oneofs. + +If your code generator does not currently support proto2, you will need to +design an API and implementation for supporting presence in scalar fields. +Generally this means: + +- allocating a bit inside the generated class to represent whether a given field + is present or not. +- exposing a `has_foo()` method for each field to return the value of this bit. +- make the parser set this bit when a value is parsed from the wire. +- make the serializer test this bit to decide whether to serialize. + +If your code generator already supports proto2, then most of your work is +already done. All you need to do is make sure that proto3 optional fields have +exactly the same API and behave in exactly the same way as proto2 optional +fields. + +From experience updating several of Google's code generators, most of the +updates that are required fall into one of several patterns. Here we will show +the patterns in terms of the C++ CodeGenerator framework. If you are using +`CodeGeneratorRequest` and `CodeGeneratorReply` directly, you can translate the +C++ examples to your own language, referencing the C++ implementation of these +methods where required. + +#### To test whether a field should have presence + +Old: + +```c++ +bool MessageHasPresence(const google::protobuf::Descriptor* message) { + return message->file()->syntax() == + google::protobuf::FileDescriptor::SYNTAX_PROTO2; +} +``` + +New: + +```c++ +// Presence is no longer a property of a message, it's a property of individual +// fields. +bool FieldHasPresence(const google::protobuf::FieldDescriptor* field) { + return field->has_presence(); + // Note, the above will return true for fields in a oneof. + // If you want to filter out oneof fields, write this instead: + // return field->has_presence && !field->real_containing_oneof() +} +``` + +#### To test whether a field is a member of a oneof + +Old: + +```c++ +bool FieldIsInOneof(const google::protobuf::FielDescriptor* field) { + return field->containing_oneof() != nullptr; +} +``` + +New: + +```c++ +bool FieldIsInOneof(const google::protobuf::FielDescriptor* field) { + // real_containing_oneof() returns nullptr for synthetic oneofs. + return field->real_containing_oneof() != nullptr; +} +``` + +#### To iterate over all oneofs + +Old: + +```c++ +bool IterateOverOneofs(const google::protobuf::Descriptor* message) { + for (int i = 0; i < message->oneof_decl_count(); i++) { + const google::protobuf::OneofDescriptor* oneof = message->oneof(i); + // ... + } +} +``` + +New: + +```c++ +bool IterateOverOneofs(const google::protobuf::Descriptor* message) { + // Real oneofs are always first, and real_oneof_decl_count() will return the + // total number of oneofs, excluding synthetic oneofs. + for (int i = 0; i < message->real_oneof_decl_count(); i++) { + const google::protobuf::OneofDescriptor* oneof = message->oneof(i); + // ... + } +} +``` + +## Updating Reflection + +If your implementation offers reflection, there are a few other changes to make: + +### API Changes + +The API for reflecting over fields and oneofs should make the following changes. +These match the changes implemented in C++ reflection. + +1. Add a `FieldDescriptor::has_presence()` method returning `bool` + (adjusted to your language's naming convention). This should return true + for all fields that have explicit presence, as documented in + [docs/field_presence](field_presence.md). In particular, this includes + fields in a oneof, proto2 scalar fields, and proto3 `optional` fields. + This accessor will allow users to query what fields have presence without + thinking about the difference between proto2 and proto3. +2. As a corollary of (1), please do *not* expose an accessor for the + `FieldDescriptorProto.proto3_optional` field. We want to avoid having + users implement any proto2/proto3-specific logic. Users should use the + `has_presence()` function instead. +3. You may also wish to add a `FieldDescriptor::has_optional_keyword()` method + returning `bool`, which indicates whether the `optional` keyword is present. + Message fields will always return `true` for `has_presence()`, so this method + can allow a user to know whether the user wrote `optional` or not. It can + occasionally be useful to have this information, even though it does not + change the presence semantics of the field. +4. If your reflection API may be used for a code generator, you may wish to + implement methods to help users tell the difference between real and + synthetic oneofs. In particular: + - `OneofDescriptor::is_synthetic()`: returns true if this is a synthetic + oneof. + - `FieldDescriptor::real_containing_oneof()`: like `containing_oneof()`, + but returns `nullptr` if the oneof is synthetic. + - `Descriptor::real_oneof_decl_count()`: like `oneof_decl_count()`, but + returns the number of real oneofs only. + +### Implementation Changes + +Proto3 `optional` fields and synthetic oneofs must work correctly when +reflected on. Specifically: + +1. Reflection for synthetic oneofs should work properly. Even though synthetic + oneofs do not really exist in the message, you can still make reflection work + as if they did. In particular, you can make a method like + `Reflection::HasOneof()` or `Reflection::GetOneofFieldDescriptor()` look at + the hasbit to determine if the oneof is present or not. +2. Reflection for proto3 optional fields should work properly. For example, a + method like `Reflection::HasField()` should know to look for the hasbit for a + proto3 `optional` field. It should not be fooled by the synthetic oneof into + thinking that there is a `case` member for the oneof. + +Once you have updated reflection to work properly with proto3 `optional` and +synthetic oneofs, any code that *uses* your reflection interface should work +properly with no changes. This is the benefit of using synthetic oneofs. + +In particular, if you have a reflection-based implementation of protobuf text +format or JSON, it should properly support proto3 optional fields without any +changes to the code. The fields will look like they all belong to a one-field +oneof, and existing proto3 reflection code should know how to test presence for +fields in a oneof. + +So the best way to test your reflection changes is to try round-tripping a +message through text format, JSON, or some other reflection-based parser and +serializer, if you have one. + +### Validating Descriptors + +If your reflection implementation supports loading descriptors at runtime, +you must verify that all synthetic oneofs are ordered after all "real" oneofs. + +Here is the code that implements this validation step in C++, for inspiration: + +```c++ + // Validation that runs for each message. + // Synthetic oneofs must be last. + int first_synthetic = -1; + for (int i = 0; i < message->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = message->oneof_decl(i); + if (oneof->is_synthetic()) { + if (first_synthetic == -1) { + first_synthetic = i; + } + } else { + if (first_synthetic != -1) { + AddError(message->full_name(), proto.oneof_decl(i), + DescriptorPool::ErrorCollector::OTHER, + "Synthetic oneofs must be after all other oneofs"); + } + } + } + + if (first_synthetic == -1) { + message->real_oneof_decl_count_ = message->oneof_decl_count_; + } else { + message->real_oneof_decl_count_ = first_synthetic; + } +``` diff --git a/docs/options.md b/docs/options.md new file mode 100644 index 0000000000000..361216f1bde45 --- /dev/null +++ b/docs/options.md @@ -0,0 +1,270 @@ +# Protobuf Global Extension Registry + +This file contains a global registry of known extensions for descriptor.proto, +so that any developer who wishes to use multiple 3rd party projects, each with +their own extensions, can be confident that there won't be collisions in +extension numbers. + +If you need an extension number for your custom option (see [custom options]( +https://developers.google.com/protocol-buffers/docs/proto#customoptions)), +please [send us a pull request](https://github.com/protocolbuffers/protobuf/pulls) to +add an entry to this doc, or [create an issue](https://github.com/protocolbuffers/protobuf/issues) +with info about your project (name and website) so we can add an entry for you. + +## Existing Registered Extensions + +1. C# port of protocol buffers + * Website: https://github.com/jskeet/protobuf-csharp-port + * Extensions: 1000 + +1. Perl/XS port of protocol buffers + * Website: http://code.google.com/p/protobuf-perlxs + * Extensions: 1001 + +1. Objective-C port of protocol buffers + * Website: http://code.google.com/p/protobuf-objc + * Extensions: 1002 + +1. Google Wave Federation Protocol open-source release (FedOne) + * Website: http://code.google.com/p/wave-protocol + * Extensions: 1003 + +1. PHP code generator plugin + * Website: ??? + * Extensions: 1004 + +1. GWT code generator plugin (third-party!) + * Website: http://code.google.com/p/protobuf-gwt/ + * Extensions: 1005 + +1. Unix Domain RPC code generator plugin + * Website: http://go/udrpc + * Extensions: 1006 + +1. Object-C generator plugin (Plausible Labs) + * Website: http://www.plausible.coop + * Extensions: 1007 + +1. TBD (code42.com) + * Website: ??? + * Extensions: 1008 + +1. Goby Underwater Autonomy Project + * Website: https://github.com/GobySoft/goby + * Extensions: 1009 + +1. Nanopb + * Website: http://kapsi.fi/~jpa/nanopb + * Extensions: 1010 + +1. Bluefin AUV Communication Extensions + * Website: http://www.bluefinrobotics.com + * Extensions: 1011 + +1. Dynamic Compact Control Language + * Website: http://github.com/GobySoft/dccl + * Extensions: 1012 + +1. ScaleOut StateServer® Native C++ API + * Website: http://www.scaleoutsoftware.com + * Extensions: 1013 + +1. FoundationDB SQL Layer + * Website: https://github.com/FoundationDB/sql-layer + * Extensions: 1014 + +1. Fender + * Website: https://github.com/hassox/fender + * Extensions: 1015 + +1. Vortex + * Website: http://www.prismtech.com/vortex + * Extensions: 1016 + +1. tresorit + * Website: https://tresorit.com/ + * Extensions: 1017 + +1. CRIU (Checkpoint Restore In Userspace) + * Website: http://criu.org/Main_Page + * Extensions: 1018 + +1. protobuf-c + * Website: https://github.com/protobuf-c/protobuf-c + * Extensions: 1019 + +1. ScalaPB + * Website: https://scalapb.github.io/ + * Extensions: 1020 + +1. protoc-gen-bq-schema + * Website: https://github.com/GoogleCloudPlatform/protoc-gen-bq-schema + * Extensions: 1021 + +1. grpc-gateway + * Website: https://github.com/gengo/grpc-gateway + * Extensions: 1022 + +1. Certificate Transparency + * Website: https://github.com/google/certificate-transparency + * Extensions: 1023 + +1. JUNOS Router Telemetry + * Website: http://www.juniper.net + * Extensions: 1024 + +1. Spine Event Engine + * Website: https://github.com/SpineEventEngine/core-java + * Extensions: 1025 + +1. Aruba cloud platform + * Website: ??? + * Extensions: 1026 -> 1030 + +1. Voltha + * Website: ??? + * Extensions: 1031 -> 1033 + +1. gator + * Website: ??? + * Extensions: 1034 + +1. protoc-gen-flowtypes + * Website: https://github.com/tmc/grpcutil/tree/master/protoc-gen-flowtypes + * Extensions: 1035 + +1. ProfaneDB + * Website: https://gitlab.com/ProfaneDB/ProfaneDB + * Extensions: 1036 + +1. protobuf-net + * Website: https://github.com/mgravell/protobuf-net + * Extensions: 1037 + +1. FICO / StreamEngine + * Website: http://www.fico.com/ + * Extensions: 1038 + +1. GopherJS + * Website: https://github.com/johanbrandhorst/protobuf + * Extensions: 1039 + +1. ygot + * Website: https://github.com/openconfig/ygot + * Extensions: 1040 + +1. go-grpcmw + * Website: https://github.com/MarquisIO/go-grpcmw + * Extensions: 1041 + +1. grpc-gateway protoc-gen-swagger + * Website: https://github.com/grpc-ecosystem/grpc-gateway + * Extensions: 1042 + +1. AN Message + * Website: TBD + * Extensions: 1043 + +1. protofire + * Website: https://github.com/ribrdb/protofire + * Extensions: 1044 + +1. Gravity + * Website: https://github.com/aphysci/gravity + * Extensions: 1045 + +1. SEMI Standards – I&C Technical Committee + * Website: http://downloads.semi.org/web/wstdsbal.nsf/9c2b317e76523cca88257641005a47f5/88a5863a580e323088256e7b00707489!OpenDocument + * Extensions: 1046 + +1. Elixir plugin + * Website: https://github.com/tony612/grpc-elixir + * Extensions: 1047 + +1. API client generators + * Website: ??? + * Extensions: 1048-1056 + +1. Netifi Proteus + * Website: https://github.com/netifi-proteus + * Extensions: 1057 + +1. CGSN Mooring Project + * Website: https://bitbucket.org/ooicgsn/cgsn-mooring + * Extensions: 1058 + +1. Container Storage Interface + * Website: https://github.com/container-storage-interface/spec + * Extensions: 1059-1069 + +1. TwirpQL Plugin + * Website: https://twirpql.dev + * Extensions: 1070 + +1. Protoc-gen-validate + * Website: https://github.com/envoyproxy/protoc-gen-validate + * Extensions: 1071 + +1. protokt + * Website: https://github.com/toasttab/protokt (Currently Private but will be open soon.) + * Extensions: 1072 + +1. Dart port of protocol buffers + * Website https://github.com/dart-lang/protobuf + * Extensions: 1073 + +1. Ocaml-protoc-plugin + * Website: https://github.com/issuu/ocaml-protoc-plugin + * Extensions: 1074 + +1. Analyze Re Graphene + * Website: https://analyzere.com + * Extensions: 1075 + +1. Wire since and until + * Website: https://square.github.io/wire/ + * Extensions: 1076, 1077 + +1. Bazel, Failure Details + * Website: https://github.com/bazelbuild/bazel + * Extensions: 1078 + +1. grpc-graphql-gateway + * Website: https://github.com/ysugimoto/grpc-graphql-gateway + * Extensions: 1079 + +1. Cloudstate + * Website: https://cloudstate.io + * Extensions: 1080-1084 + +1. SummaFT protoc-plugins + * Website: https://summaft.com/ + * Extensions: 1085 + +1. ADLINK EdgeSDK + * Website: https://www.adlinktech.com/en/Edge-SDK-IoT + * Extensions: 1086 + +1. Wire wire_package + * Website: https://square.github.io/wire/ + * Extensions: 1087 + +1. Confluent Schema Registry + * Website: https://github.com/confluentinc/schema-registry + * Extensions: 1088 + +1. ScalaPB Validate + * Website: https://scalapb.github.io/docs/validation + * Extension: 1089 + +1. Astounding (Currently Private) + * Website: https://github.com/PbPipes/Astounding + * Extension: 1090 + +1. Protoc-gen-psql + * Website: https://github.com/Intrinsec/protoc-gen-psql + * Extension: 1091 + +1. Protoc-gen-sanitize + * Website: https://github.com/Intrinsec/protoc-gen-sanitize + * Extension: 1092 diff --git a/docs/performance.md b/docs/performance.md new file mode 100644 index 0000000000000..8734c700c129e --- /dev/null +++ b/docs/performance.md @@ -0,0 +1,304 @@ +# Protobuf Performance +The following benchmark test results were produced on a workstation utilizing an Intel® Xeon® Processor E5-2630 with 32GB of RAM. + +This table contains the results of three separate languages: + +* **C++** - For C++, there are three parsing methods: + * **new** - This is for using a new operator for creating a message instance. + * **new arena** - This is for using arena for creating a new message instance. + * **reuse** - This is for reusing the same message instance for parsing. +* **Java** - For Java, there are three parsing/serialization methods: + * **byte[]** - This is for parsing from a Byte Array. + * **ByteString** - This is for parsing from a + com.google.protobuf.ByteString. + * **InputStream** - This is for parsing from an InputStream. +* **Python** - For Python, there are three types of Python protobuf for testing: + * **C++-generated-code** - This is for using C++ generated code of the + proto file as a dynamic linked library. + * **C++-reflection** - This is for using C++ reflection, for which there's no + generated code, but still using C++ protobuf library as a dynamic linked + library. + * **pure-Python** - This is for the pure version of Python, which does not link with + any C++ protobuf library. + +## Parsing performance + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
C++C++ with tcmallocjavapython
newnew arenareusenewnew arenareusebyte[]ByteStringInputStreamC++-generated-codeC++-reflectionpure-Python
google_message1_proto2368.717MB/s261.847MB/s799.403MB/s645.183MB/s441.023MB/s1.122GB/s425.437MB/s425.937MB/s251.018MB/s82.8314MB/s47.6763MB/s3.76299MB/s
google_message1_proto3294.517MB/s229.116MB/s469.982MB/s434.510MB/s394.701MB/s591.931MB/s357.597MB/s378.568MB/s221.676MB/s82.0498MB/s39.9467MB/s3.77751MB/s
google_message2277.242MB/s347.611MB/s793.67MB/s503.721MB/s596.333MB/s922.533MB/s416.778MB/s419.543MB/s367.145MB/s241.46MB/s71.5723MB/s2.73538MB/s
google_message3_1213.478MB/s291.58MB/s543.398MB/s539.704MB/s717.300MB/s927.333MB/s684.241MB/s704.47MB/s648.624MB/s209.036MB/s142.356MB/s15.3324MB/s
google_message3_2672.685MB/s802.767MB/s1.21505GB/s985.790MB/s1.136GB/s1.367GB/s1.54439GB/s1.60603GB/s1.33443GB/s573.835MB/s314.33MB/s15.0169MB/s
google_message3_3207.681MB/s140.591MB/s535.181MB/s369.743MB/s262.301MB/s556.644MB/s279.385MB/s304.853MB/s107.575MB/s32.248MB/s26.1431MB/s2.63541MB/s
google_message3_47.96091GB/s7.10024GB/s9.3013GB/s8.518GB/s8.171GB/s9.917GB/s5.78006GB/s5.85198GB/s4.62609GB/s2.49631GB/s2.35442GB/s802.061MB/s
google_message3_576.0072MB/s51.6769MB/s237.856MB/s178.495MB/s111.751MB/s329.569MB/s121.038MB/s132.866MB/s36.9197MB/s10.3962MB/s8.84659MB/s1.25203MB/s
google_message4331.46MB/s404.862MB/s427.99MB/s589.887MB/s720.367MB/s705.373MB/s606.228MB/s589.13MB/s530.692MB/s305.543MB/s174.834MB/s7.86485MB/s
+ +## Serialization performance + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
C++C++ with tcmallocjavapython
byte[]ByteStringInputStreamC++-generated-codeC++-reflectionpure-Python
google_message1_proto21.39698GB/s1.701GB/s1.12915GB/s1.13589GB/s758.609MB/s260.911MB/s58.4815MB/s5.77824MB/s
google_message1_proto3959.305MB/s939.404MB/s1.15372GB/s1.07824GB/s802.337MB/s239.4MB/s33.6336MB/s5.80524MB/s
google_message21.27429GB/s1.402GB/s1.01039GB/s1022.99MB/s798.736MB/s996.755MB/s57.9601MB/s4.09246MB/s
google_message3_11.31916GB/s2.049GB/s991.496MB/s860.332MB/s662.88MB/s1.48625GB/s421.287MB/s18.002MB/s
google_message3_22.15676GB/s2.632GB/s2.14736GB/s2.08136GB/s1.55997GB/s2.39597GB/s326.777MB/s16.0527MB/s
google_message3_3650.456MB/s1.040GB/s593.52MB/s580.667MB/s346.839MB/s123.978MB/s35.893MB/s2.32834MB/s
google_message3_48.70154GB/s9.825GB/s5.88645GB/s5.93946GB/s2.44388GB/s5.9241GB/s4.05837GB/s876.87MB/s
google_message3_5246.33MB/s443.993MB/s283.278MB/s259.167MB/s206.37MB/s37.0285MB/s12.2228MB/s1.1979MB/s
google_message41.56674GB/s2.19601GB/s776.907MB/s770.707MB/s702.931MB/s1.49623GB/s205.116MB/s8.93428MB/s
+ +\* The cpp performance can be improved by using [tcmalloc](https://gperftools.github.io/gperftools/tcmalloc.html), please follow the (instruction)[https://github.com/protocolbuffers/protobuf/blob/master/benchmarks/README.md] to link with tcmalloc to get the faster result. diff --git a/docs/third_party.md b/docs/third_party.md index 385650dfd85b3..7799e308a7afe 100644 --- a/docs/third_party.md +++ b/docs/third_party.md @@ -16,35 +16,44 @@ These are projects we know about implementing Protocol Buffers for other program * C: https://github.com/cloudwu/pbc/ * C: https://github.com/haberman/upb/wiki * C: https://github.com/squidfunk/protobluff +* C: https://github.com/eerimoq/pbtools * C++: https://github.com/google/protobuf (Google-official implementation) +* C++: https://EmbeddedProto.com * C/C++: http://spbc.sf.net/ * C#: http://code.google.com/p/protobuf-csharp-port -* C#: http://code.google.com/p/protosharp/ * C#: https://silentorbit.com/protobuf/ * C#/.NET/WCF/VB: http://code.google.com/p/protobuf-net/ * Clojure: http://github.com/ninjudd/clojure-protobuf -* Common Lisp: http://github.com/ndantam/s-protobuf +* Clojure: https://github.com/clojusc/protobuf +* Clojure: https://protojure.github.io * Common Lisp: http://github.com/brown/protobuf +* Common Lisp: http://github.com/qitab/cl-protobuf +* D: https://github.com/dcarp/protobuf-d * D: https://github.com/msoucy/dproto -* D: http://256.makerslocal.org/wiki/index.php/ProtocolBuffer * D: https://github.com/opticron/ProtocolBuffer * Dart: https://github.com/dart-lang/dart-protobuf (runtime) https://github.com/dart-lang/dart-protoc-plugin (code generator) * Delphi: http://sourceforge.net/projects/protobuf-delphi/ * Delphi: http://fundementals.sourceforge.net/dl.html * Elixir: https://github.com/jeremyong/exprotoc +* Elixir: https://github.com/tony612/protobuf-elixir +* Elixir: https://github.com/ahamez/protox * Elm: https://github.com/tiziano88/elm-protobuf -* Erlang: http://github.com/ngerakines/erlang_protobuffs/tree/master -* Erlang: http://piqi.org/ -* Erlang: https://code.google.com/p/protoc-gen-erl/ -* Erlang: https://github.com/basho/erlang_protobuffs * Erlang: https://github.com/tomas-abrahamsson/gpb +* Erlang: http://piqi.org/ +* Erlang: https://github.com/basho/erlang_protobuffs (no longer maintained, use gpb instead) +* Hacklang/HHVM: https://github.com/y3llowcake/proto-hack +* GDScript: https://github.com/oniksan/godobuf (Godot v3 engine plugin) * Go: https://github.com/golang/protobuf (Google-official implementation) * Go: https://github.com/akunspy/gopbuf * Go: https://github.com/gogo/protobuf +* GopherJS: https://github.com/johanbrandhorst/protobuf * Haskell: http://hackage.haskell.org/package/hprotoc +* Haskell: https://github.com/google/proto-lens (Google-unofficial implementation) +* Haskell: https://github.com/awakesecurity/proto3-suite (code generator) https://github.com/awakesecurity/proto3-wire (binary serializer/deserializer) * Haxe: https://github.com/Atry/protoc-gen-haxe * Java: https://github.com/google/protobuf (Google-official implementation) * Java/Android: https://github.com/square/wire +* Java: https://github.com/HebiRobotics/QuickBuffers/ * Java ME: http://code.google.com/p/protobuf-javame/ * Java ME: http://swingme.sourceforge.net/encode.shtml * Java ME: http://code.google.com/p/protobuf-j2me/ @@ -53,7 +62,11 @@ These are projects we know about implementing Protocol Buffers for other program * Javascript: https://github.com/dcodeIO/ProtoBuf.js * Javascript: http://code.google.com/p/protobuf-for-node/ * Javascript: http://code.google.com/p/protostuff/ +* Javascript: https://github.com/seishun/node-protoc-plugin (Node.js port of plugin.h) +* Javascript: https://github.com/seishun/node-protoc-gen-javascript (Node.js port of the Google-official implementation) * Julia: https://github.com/tanmaykm/ProtoBuf.jl +* Kotlin: https://github.com/marcoferrer/kroto-plus +* Kotlin: https://github.com/Kotlin/kotlinx.serialization * Lua: http://code.google.com/p/protoc-gen-lua/ * Lua: http://github.com/indygreg/lua-protobuf * Lua: https://github.com/Neopallium/lua-pb @@ -71,8 +84,10 @@ These are projects we know about implementing Protocol Buffers for other program * PHP: https://github.com/chobie/php-protocolbuffers * PHP: http://drslump.github.com/Protobuf-PHP * Prolog: http://www.swi-prolog.org/pldoc/package/protobufs.html +* Purescript: https://github.com/xc-jp/purescript-protobuf * Python: https://github.com/google/protobuf (Google-official implementation) -* Python: http://eigenein.github.com/protobuf/ +* Python: https://github.com/eigenein/protobuf +* Python: https://github.com/danielgtaylor/python-betterproto * R: http://cran.r-project.org/package=RProtoBuf * Ruby: http://code.google.com/p/ruby-protobuf/ * Ruby: http://github.com/mozy/ruby-protocol-buffers @@ -82,9 +97,11 @@ These are projects we know about implementing Protocol Buffers for other program * Scala: http://github.com/jeffplaisance/scala-protobuf * Scala: http://code.google.com/p/protobuf-scala * Scala: https://github.com/SandroGrzicic/ScalaBuff -* Scala: http://trueaccord.github.io/ScalaPB/ +* Scala: https://scalapb.github.io +* Solidity: https://github.com/celer-network/pb3-gen-sol * Swift: https://github.com/alexeyxo/protobuf-swift * Swift: https://github.com/apple/swift-protobuf/ +* Typescript: https://github.com/y3llowcake/protoc-gen-ts * Vala: https://launchpad.net/protobuf-vala * Visual Basic: http://code.google.com/p/protobuf-net/ @@ -93,30 +110,39 @@ These are projects we know about implementing Protocol Buffers for other program GRPC (http://www.grpc.io/) is Google's RPC implementation for Protocol Buffers. There are other third-party RPC implementations as well. Some of these actually work with Protocol Buffers service definitions (defined using the `service` keyword in `.proto` files) while others just use Protocol Buffers message objects. * https://github.com/grpc/grpc (C++, Node.js, Python, Ruby, Objective-C, PHP, C#, Google-official implementation) -* http://zeroc.com/ice.html (Multiple languages) -* http://code.google.com/p/protobuf-net/ (C#/.NET/WCF/VB) +* https://zeroc.com/products/ice (Multiple languages) +* https://github.com/protobuf-net/protobuf-net (C#/.NET/WCF/VB) +* http://www.deltavsoft.com/doc/_external_serialization.html#Protobufs (C++) +* https://protojure.github.io (Clojure) +* https://code.google.com/p/protobuf-rpc-pro/ (Java) +* https://github.com/baidu/sofa-pbrpc (C++) +* https://github.com/madhon/protobuf-csharp-rpc (C#) +* https://github.com/madwyn/libpbrpc (C++) +* https://github.com/SeriousMa/grpc-protobuf-validation (Java) +* https://github.com/elixir-grpc/grpc (Elixir) +* https://github.com/johanbrandhorst/protobuf (GopherJS) +* https://github.com/awakesecurity/gRPC-haskell (Haskell) +* https://github.com/Yeolar/raster (C++) +* https://github.com/jnordberg/wsrpc (JavaScript Node.js/Browser) +* https://github.com/ppissias/xsrpcj (Java) + +Inactive: + * https://launchpad.net/txprotobuf/ (Python) * https://github.com/modeswitch/protobuf-rpc (Python) -* http://code.google.com/p/protobuf-socket-rpc/ (Java, Python) -* http://code.google.com/p/proto-streamer/ (Java) -* http://code.google.com/p/server1/ (C++) -* http://deltavsoft.com/RcfUserGuide/Protobufs (C++) -* http://code.google.com/p/protobuf-mina-rpc/ (Python client, Java server) -* http://code.google.com/p/casocklib/ (C++) -* http://code.google.com/p/cxf-protobuf/ (Java) -* http://code.google.com/p/protobuf-remote/ (C++/C#) -* http://code.google.com/p/protobuf-rpc-pro/ (Java) -* https://code.google.com/p/protorpc/ (Go/C++) +* https://github.com/sdeo/protobuf-socket-rpc (Java, Python) +* https://code.google.com/p/proto-streamer/ (Java) +* https://code.google.com/p/server1/ (C++) +* https://code.google.com/p/protobuf-mina-rpc/ (Python client, Java server) +* https://code.google.com/p/casocklib/ (C++) +* https://code.google.com/p/cxf-protobuf/ (Java) +* https://code.google.com/p/protobuf-remote/ (C++/C#) * https://code.google.com/p/eneter-protobuf-serializer/ (Java/.NET) -* http://www.deltavsoft.com/RCFProto.html (C++/Java/Python/C#) -* https://github.com/robbinfan/claire-protorpc (C++) -* https://github.com/BaiduPS/sofa-pbrpc (C++) +* https://github.com/robbinfan/claire/tree/master/protorpc (C++) * https://github.com/ebencheung/arab (C++) -* http://code.google.com/p/protobuf-csharp-rpc/ (C#) +* https://code.google.com/p/protobuf-csharp-rpc/ (C#) * https://github.com/thesamet/rpcz (C++/Python, based on ZeroMQ) * https://github.com/w359405949/libmaid (C++, Python) -* https://github.com/madwyn/libpbrpc (C++) -* https://github.com/SeriousMa/grpc-protobuf-validation (Java) ## Other Utilities @@ -131,7 +157,7 @@ There are miscellaneous other things you may find useful as a Protocol Buffers d * [Alternate encodings (JSON, XML, HTML) for Java protobufs](http://code.google.com/p/protobuf-java-format/) * [Another JSON encoder/decoder for Java](https://github.com/sijuv/protobuf-codec) * [Editor for serialized protobufs](http://code.google.com/p/protobufeditor/) -* [Intellij IDEA plugin](http://github.com/nnmatveev/idea-plugin-protobuf) +* [IntelliJ IDEA plugin](http://github.com/jvolkman/intellij-protobuf-editor) * [TextMate syntax highlighting](http://github.com/michaeledgar/protobuf-tmbundle) * [Oracle PL SQL plugin](http://code.google.com/p/protocol-buffer-plsql/) * [Eclipse editor for protobuf (from Google)](http://code.google.com/p/protobuf-dt/) @@ -150,10 +176,20 @@ There are miscellaneous other things you may find useful as a Protocol Buffers d * [Multi-platform executable JAR and Java API for protoc](https://github.com/os72/protoc-jar) * [Python scripts to convert between Protocol Buffers and JSON](https://github.com/NextTuesday/py-pb-converters) * [Visual Studio Language Service support for Protocol Buffers](http://visualstudiogallery.msdn.microsoft.com/4bc0f38c-b058-4e05-ae38-155e053c19c5) +* [Visual Studio Code Support for Protocol Buffers](https://marketplace.visualstudio.com/items?itemName=zxh404.vscode-proto3) * [C++ library for serialization/de-serialization between Protocol Buffers and JSON.](https://github.com/yinqiwen/pbjson) * [ProtoBuf with Java EE7 Expression Language 3.0; pure Java ProtoBuf Parser and Builder.](https://github.com/protobufel/protobuf-el) * [Notepad++ Syntax Highlighting for .proto files](https://github.com/chai2010/notepadplus-protobuf) * [Linter for .proto files](https://github.com/ckaznocha/protoc-gen-lint) -* [Protocol Buffers Dynamic Schema - create protobuf schemas programmatically (Java)] (https://github.com/os72/protobuf-dynamic) +* [Protocol Buffers Dynamic Schema - create protobuf schemas programmatically (Java)](https://github.com/os72/protobuf-dynamic) * [Make protoc plugins in NodeJS](https://github.com/konsumer/node-protoc-plugin) * [ProfaneDB - A Protocol Buffers database](https://profanedb.gitlab.io) +* [Protocol Buffer property-based testing utility and example message generator (Python / Hypothesis)](https://github.com/CurataEng/hypothesis-protobuf) +* [Protolock - CLI utility to prevent backward-incompatible changes to .proto files](https://github.com/nilslice/protolock) +* [Optional GRPC - GRPC for testable microservices (Python)](https://github.com/mattpaletta/optional-grpc.git) +* [Protobuf Parser - Yet another Go package which parses a Protocol Buffer file (proto2+proto3)](https://github.com/yoheimuta/go-protoparser) +* [Protolint - A tool to enforce Protocol Buffer style and conventions.](https://github.com/yoheimuta/protolint) + * [vscode-protolint: A protobuf linter for visual studio code](https://github.com/plexsystems/vscode-protolint) + * [intellij-protolint: A protobuf linter for JetBrains IDEs](https://github.com/yoheimuta/intellij-protolint) + * [vim-protolint: A protobuf linter for Vim](https://github.com/yoheimuta/vim-protolint) +* [super-linter: Protocol Buffer lint as GitHub Action](https://github.com/github/super-linter) diff --git a/editors/proto.vim b/editors/proto.vim index 7f1aeb730a172..bdc60ce7f8ee8 100644 --- a/editors/proto.vim +++ b/editors/proto.vim @@ -69,10 +69,10 @@ syn keyword pbBool true false syn match pbInt /-\?\<\d\+\>/ syn match pbInt /\<0[xX]\x+\>/ syn match pbFloat /\<-\?\d*\(\.\d*\)\?/ -syn region pbComment start="\/\*" end="\*\/" contains=@pbCommentGrp -syn region pbComment start="//" skip="\\$" end="$" keepend contains=@pbCommentGrp -syn region pbString start=/"/ skip=/\\./ end=/"/ -syn region pbString start=/'/ skip=/\\./ end=/'/ +syn region pbComment start="\/\*" end="\*\/" contains=@pbCommentGrp,@Spell +syn region pbComment start="//" skip="\\$" end="$" keepend contains=@pbCommentGrp,@Spell +syn region pbString start=/"/ skip=/\\./ end=/"/ contains=@Spell +syn region pbString start=/'/ skip=/\\./ end=/'/ contains=@Spell if version >= 508 || !exists("did_proto_syn_inits") if version < 508 diff --git a/editors/protobuf-mode.el b/editors/protobuf-mode.el index d3bdcded70afa..8102771665638 100644 --- a/editors/protobuf-mode.el +++ b/editors/protobuf-mode.el @@ -1,4 +1,4 @@ -;;; protobuf-mode.el --- major mode for editing protocol buffers. +;;; protobuf-mode.el --- major mode for editing protocol buffers. -*- lexical-binding: t; -*- ;; Author: Alexandre Vassalotti ;; Created: 23-Apr-2009 @@ -216,7 +216,11 @@ Key bindings: (c-common-init 'protobuf-mode) (easy-menu-add protobuf-menu) (c-run-mode-hooks 'c-mode-common-hook 'protobuf-mode-hook) - (c-update-modeline)) + (c-update-modeline) + (setq imenu-generic-expression + '(("Message" "^[[:space:]]*message[[:space:]]+\\([[:alnum:]]+\\)" 1) + ("Enum" "^[[:space:]]*enum[[:space:]]+\\([[:alnum:]]+\\)" 1) + ("Service" "^[[:space:]]*service[[:space:]]+\\([[:alnum:]]+\\)" 1)))) (provide 'protobuf-mode) diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 0000000000000..229542d23ce92 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,2 @@ +# Ignore the bazel symlinks +/bazel-* diff --git a/examples/BUILD b/examples/BUILD new file mode 100644 index 0000000000000..7d15e83ab4e86 --- /dev/null +++ b/examples/BUILD @@ -0,0 +1,105 @@ +# This BUILD file shows how to use protobuf with bazel. Before you can use +# proto_library/_proto_library rules in a BUILD file, you need to +# include protobuf repo as remote repositories in your WORKSPACE file. See +# the WORKSPACE file in the same directory with this BUILD file for an +# example. + +load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_proto_library") +load("@rules_java//java:defs.bzl", "java_binary", "java_lite_proto_library", "java_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +# For each .proto file, a proto_library target should be defined. This target +# is not bound to any particular language. Instead, it defines the dependency +# graph of the .proto files (i.e., proto imports) and serves as the provider +# of .proto source files to the protocol compiler. +# +# Remote repository "com_google_protobuf" must be defined to use this rule. +proto_library( + name = "addressbook_proto", + srcs = ["addressbook.proto"], + deps = ["@com_google_protobuf//:timestamp_proto"], +) + +# The cc_proto_library rule generates C++ code for a proto_library rule. It +# must have exactly one proto_library dependency. If you want to use multiple +# proto_library targets, create a separate cc_proto_library target for each +# of them. +# +# Remote repository "com_google_protobuf_cc" must be defined to use this rule. +cc_proto_library( + name = "addressbook_cc_proto", + deps = [":addressbook_proto"], +) + +# cc_library/cc_binary targets can depend on cc_proto_library targets. +cc_binary( + name = "add_person_cpp", + srcs = ["add_person.cc"], + deps = [":addressbook_cc_proto"], +) + +cc_binary( + name = "list_people_cpp", + srcs = ["list_people.cc"], + deps = [":addressbook_cc_proto"], +) + +# Similar to cc_proto_library but for Java. +# +# Remote repository "com_google_protobuf_java" must be defined to use this rule. +java_proto_library( + name = "addressbook_java_proto", + deps = [":addressbook_proto"], +) + +java_binary( + name = "add_person_java", + srcs = ["AddPerson.java"], + main_class = "AddPerson", + deps = [":addressbook_java_proto"], +) + +java_binary( + name = "list_people_java", + srcs = ["ListPeople.java"], + main_class = "ListPeople", + deps = [":addressbook_java_proto"], +) + +# Java lite. +# +# Remote repository "com_google_protobuf_javalite" must be defined to use this +# rule. +java_lite_proto_library( + name = "addressbook_java_lite_proto", + deps = [":addressbook_proto"], +) + +# Java lite API is a subset of the regular Java API so if you only uses this +# subset in your code, you can actually compile your code against both (i.e., +# share code between server build and Android build). +# +# The lite version has a smaller code size, and you can see that by comparing +# the resulted .jar file: +# +# $ bazel build :add_person_java_deploy.jar :add_person_java_lite_deploy.jar +# $ ls -l bazel-bin/*_deploy.jar +# -r-xr-xr-x 1 xiaofeng eng 1230797 Sep 8 12:24 bazel-bin/add_person_java_deploy.jar +# -r-xr-xr-x 1 xiaofeng eng 236166 Sep 8 12:24 bazel-bin/add_person_java_lite_deploy.jar +# +# In the above example, the lite .jar file is 6 times smaller. With proper +# proguard inlining/stripping, the difference can be much more larger than +# that. +java_binary( + name = "add_person_java_lite", + srcs = ["AddPerson.java"], + main_class = "AddPerson", + deps = [":addressbook_java_lite_proto"], +) + +java_binary( + name = "list_people_java_lite", + srcs = ["ListPeople.java"], + main_class = "ListPeople", + deps = [":addressbook_java_lite_proto"], +) diff --git a/examples/ListPeople.java b/examples/ListPeople.java index 789243050888e..580f7ac2af4af 100644 --- a/examples/ListPeople.java +++ b/examples/ListPeople.java @@ -27,6 +27,9 @@ static void Print(AddressBook addressBook) { case WORK: System.out.print(" Work phone #: "); break; + default: + System.out.println(" Unknown phone #: "); + break; } System.out.println(phoneNumber.getNumber()); } diff --git a/examples/Makefile b/examples/Makefile index d16bb56d5ab62..e9f9635ae81e8 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -5,6 +5,7 @@ all: cpp java python cpp: add_person_cpp list_people_cpp +dart: add_person_dart list_people_dart go: add_person_go list_people_go gotest: add_person_gotest list_people_gotest java: add_person_java list_people_java @@ -16,27 +17,39 @@ clean: rm -f protoc_middleman addressbook.pb.cc addressbook.pb.h addressbook_pb2.py com/example/tutorial/AddressBookProtos.java rm -f *.pyc rm -f protoc_middleman_go tutorial/*.pb.go add_person_go list_people_go + rm -f protoc_middleman_dart dart_tutorial/*.pb*.dart + rmdir dart_tutorial 2>/dev/null || true rmdir tutorial 2>/dev/null || true rmdir com/example/tutorial 2>/dev/null || true rmdir com/example 2>/dev/null || true rmdir com 2>/dev/null || true protoc_middleman: addressbook.proto - protoc --cpp_out=. --java_out=. --python_out=. addressbook.proto + protoc $$PROTO_PATH --cpp_out=. --java_out=. --python_out=. addressbook.proto @touch protoc_middleman protoc_middleman_go: addressbook.proto - mkdir tutorial # make directory for go package - protoc --go_out=tutorial addressbook.proto + mkdir -p tutorial # make directory for go package + protoc $$PROTO_PATH --go_out=tutorial addressbook.proto @touch protoc_middleman_go +protoc_middleman_dart: addressbook.proto + mkdir -p dart_tutorial # make directory for the dart package + protoc -I ../src/:. --dart_out=dart_tutorial addressbook.proto ../src/google/protobuf/timestamp.proto + pub get + @touch protoc_middleman_dart + add_person_cpp: add_person.cc protoc_middleman pkg-config --cflags protobuf # fails if protobuf is not installed - c++ add_person.cc addressbook.pb.cc -o add_person_cpp `pkg-config --cflags --libs protobuf` + c++ -std=c++11 add_person.cc addressbook.pb.cc -o add_person_cpp `pkg-config --cflags --libs protobuf` list_people_cpp: list_people.cc protoc_middleman pkg-config --cflags protobuf # fails if protobuf is not installed - c++ list_people.cc addressbook.pb.cc -o list_people_cpp `pkg-config --cflags --libs protobuf` + c++ -std=c++11 list_people.cc addressbook.pb.cc -o list_people_cpp `pkg-config --cflags --libs protobuf` + +add_person_dart: add_person.dart protoc_middleman_dart + +list_people_dart: list_people.dart protoc_middleman_dart add_person_go: add_person.go protoc_middleman_go go build -o add_person_go add_person.go @@ -51,7 +64,7 @@ list_people_gotest: list_people.go list_people_go go test list_people.go list_people_test.go javac_middleman: AddPerson.java ListPeople.java protoc_middleman - javac -cp ../java/core/target/*.jar AddPerson.java ListPeople.java com/example/tutorial/AddressBookProtos.java + javac -cp $$CLASSPATH AddPerson.java ListPeople.java com/example/tutorial/AddressBookProtos.java @touch javac_middleman add_person_java: javac_middleman diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000000000..4bf7c17cccf60 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,144 @@ +# Protocol Buffers - Code Example + +This directory contains example code that uses Protocol Buffers to manage an +address book. Two programs are provided for each supported language. The +add_person example adds a new person to an address book, prompting the user to +input the person's information. The list_people example lists people already in +the address book. The examples use the exact same format in all three languages, +so you can, for example, use add_person_java to create an address book and then +use list_people_python to read it. + +These examples are part of the Protocol Buffers tutorial, located at: + https://developers.google.com/protocol-buffers/docs/tutorials + +## Build the example using bazel + +The example requires bazel 0.5.4 or newer to build. You can download/install +the latest version of bazel from bazel's release page: + + https://github.com/bazelbuild/bazel/releases + +Once you have bazel installed, simply run the following command in this examples +directory to build the code: + + $ bazel build :all + +Then you can run the built binary: + + $ bazel-bin/add_person_cpp addressbook.data + +To use protobuf in your own bazel project, please follow instructions in the +[BUILD](BUILD) file and [WORKSPACE](WORKSPACE) file. + +## Build the example using make + +You must install the protobuf package before you can build it using make. The +minimum requirement is to install protocol compiler (i.e., the protoc binary) +and the protobuf runtime for the language you want to build. + +You can simply run "make" to build the example for all languages (except for +Go). However, since different language has different installation requirement, +it will likely fail. It's better to follow individual instructions below to +build only the language you are interested in. + +### C++ + +You can follow instructions in [../src/README.md](../src/README.md) to install +protoc and protobuf C++ runtime from source. + +Then run "make cpp" in this examples directory to build the C++ example. It +will create two executables: add_person_cpp and list_people_cpp. These programs +simply take an address book file as their parameter. The add_person_cpp +programs will create the file if it doesn't already exist. + +To run the examples: + + $ ./add_person_cpp addressbook.data + $ ./list_people_cpp addressbook.data + +Note that on some platforms you may have to edit the Makefile and remove +"-lpthread" from the linker commands (perhaps replacing it with something else). +We didn't do this automatically because we wanted to keep the example simple. + +### Python + +Follow instructions in [../README.md](../README.md) to install protoc and then +follow [../python/README.md](../python/README.md) to install protobuf python +runtime from source. You can also install python runtime using pip: + + $ pip install protobuf + +Make sure the runtime version is the same as protoc binary, or it may not work. + +After you have install both protoc and python runtime, run "make python" to +build two executables (shell scripts actually): add_person_python and +list_people_python. They work the same way as the C++ executables. + +### Java + +Follow instructions in [../README.md](../README.md) to install protoc and then +download protobuf Java runtime .jar file from maven: + + https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java + +Then run the following: + + $ export CLASSPATH=/path/to/protobuf-java-[version].jar + $ make java + +This will create the add_person_java/list_people_java executables (shell +scripts) and can be used to create/display an address book data file. + +### Go + +The Go example requires a plugin to the protocol buffer compiler, so it is not +build with all the other examples. See: + + https://github.com/golang/protobuf + +for more information about Go protocol buffer support. + +First, install the Protocol Buffers compiler (protoc). + +Then, install the Go Protocol Buffers plugin ($GOPATH/bin must be in your $PATH +for protoc to find it): + + go get github.com/golang/protobuf/protoc-gen-go + +Build the Go samples in this directory with "make go". This creates the +following executable files in the current directory: + + add_person_go list_people_go + +To run the example: + + ./add_person_go addressbook.data + +to add a person to the protocol buffer encoded file addressbook.data. The file +is created if it does not exist. To view the data, run: + + ./list_people_go addressbook.data + +Observe that the C++, Python, Java, and Dart examples in this directory run in a +similar way and can view/modify files created by the Go example and vice +versa. + +### Dart + +First, follow the instructions in [../README.md](../README.md) to install the Protocol Buffer Compiler (protoc). + +Then, install the Dart Protocol Buffer plugin as described [here](https://github.com/dart-lang/dart-protoc-plugin#how-to-build-and-use). +Note, the executable `bin/protoc-gen-dart` must be in your `PATH` for `protoc` to find it. + +Build the Dart samples in this directory with `make dart`. + +To run the examples: + +```sh +$ dart add_person.dart addressbook.data +$ dart list_people.dart addressbook.data +``` + +The two programs take a protocol buffer encoded file as their parameter. +The first can be used to add a person to the file. The file is created +if it does not exist. The second displays the data in the file. diff --git a/examples/README.txt b/examples/README.txt deleted file mode 100644 index 2e4f6e4e8b951..0000000000000 --- a/examples/README.txt +++ /dev/null @@ -1,61 +0,0 @@ -This directory contains example code that uses Protocol Buffers to manage an -address book. Two programs are provided, each with three different -implementations, one written in each of C++, Java, and Python. The add_person -example adds a new person to an address book, prompting the user to input -the person's information. The list_people example lists people already in the -address book. The examples use the exact same format in all three languages, -so you can, for example, use add_person_java to create an address book and then -use list_people_python to read it. - -You must install the protobuf package before you can build these. - -To build all the examples (on a unix-like system), simply run "make". This -creates the following executable files in the current directory: - add_person_cpp list_people_cpp - add_person_java list_people_java - add_person_python list_people_python - -If you only want to compile examples in one language, use "make cpp"*, -"make java", or "make python". - -All of these programs simply take an address book file as their parameter. -The add_person programs will create the file if it doesn't already exist. - -These examples are part of the Protocol Buffers tutorial, located at: - https://developers.google.com/protocol-buffers/docs/tutorials - -* Note that on some platforms you may have to edit the Makefile and remove -"-lpthread" from the linker commands (perhaps replacing it with something else). -We didn't do this automatically because we wanted to keep the example simple. - -## Java ## - -protobuf-java-*.jar can be generated by: - cd ../java - mvn package -and will be used by "make java" - -## Go ## - -The Go example requires a plugin to the protocol buffer compiler, so it is not -build with all the other examples. See: - https://github.com/golang/protobuf -for more information about Go protocol buffer support. - -First, install the Protocol Buffers compiler (protoc). -Then, install the Go Protocol Buffers plugin -($GOPATH/bin must be in your $PATH for protoc to find it): - go get github.com/golang/protobuf/protoc-gen-go - -Build the Go samples in this directory with "make go". This creates the -following executable files in the current directory: - add_person_go list_people_go -To run the example: - ./add_person_go addressbook.data -to add a person to the protocol buffer encoded file addressbook.data. The file -is created if it does not exist. To view the data, run: - ./list_people_go addressbook.data - -Observe that the C++, Python, and Java examples in this directory run in a -similar way and can view/modify files created by the Go example and vice -versa. diff --git a/examples/WORKSPACE b/examples/WORKSPACE new file mode 100644 index 0000000000000..fb36639ae8185 --- /dev/null +++ b/examples/WORKSPACE @@ -0,0 +1,31 @@ +workspace(name = "com_google_protobuf_examples") + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +# This com_google_protobuf repository is required for proto_library rule. +# It provides the protocol compiler binary (i.e., protoc). +# +# We declare it as local_repository so we can test changes +# before they get merged. You'll want to use the following instead: +# +# http_archive( +# name = "com_google_protobuf", +# strip_prefix = "protobuf-master", +# urls = ["https://github.com/protocolbuffers/protobuf/archive/master.zip"], +# ) +local_repository( + name = "com_google_protobuf", + path = "..", +) + +# Similar to com_google_protobuf but for Java lite. If you are building +# for Android, the lite version should be preferred because it has a much +# smaller code size. +local_repository( + name = "com_google_protobuf_javalite", + path = "..", +) + +load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") + +protobuf_deps() diff --git a/examples/add_person.cc b/examples/add_person.cc index 9bec4b374d82d..856e90bb7bb68 100644 --- a/examples/add_person.cc +++ b/examples/add_person.cc @@ -1,11 +1,17 @@ // See README.txt for information and build instructions. -#include +#include #include +#include +#include #include + #include "addressbook.pb.h" + using namespace std; +using google::protobuf::util::TimeUtil; + // This function fills in a Person message based on user input. void PromptForAddress(tutorial::Person* person) { cout << "Enter person ID number: "; @@ -48,6 +54,7 @@ void PromptForAddress(tutorial::Person* person) { cout << "Unknown phone type. Using default." << endl; } } + *person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL)); } // Main function: Reads the entire address book from a file, diff --git a/examples/add_person.dart b/examples/add_person.dart new file mode 100644 index 0000000000000..0352dc7e78389 --- /dev/null +++ b/examples/add_person.dart @@ -0,0 +1,67 @@ +import 'dart:io'; + +import 'dart_tutorial/addressbook.pb.dart'; + +/// This function fills in a Person message based on user input. +Person promptForAddress() { + final person = Person(); + + print('Enter person ID: '); + final input = stdin.readLineSync(); + person.id = int.parse(input); + + print('Enter name'); + person.name = stdin.readLineSync(); + + print('Enter email address (blank for none) : '); + final email = stdin.readLineSync(); + if (email.isNotEmpty) person.email = email; + + while (true) { + print('Enter a phone number (or leave blank to finish): '); + final number = stdin.readLineSync(); + if (number.isEmpty) break; + + final phoneNumber = Person_PhoneNumber()..number = number; + + print('Is this a mobile, home, or work phone? '); + + final type = stdin.readLineSync(); + switch (type) { + case 'mobile': + phoneNumber.type = Person_PhoneType.MOBILE; + break; + case 'home': + phoneNumber.type = Person_PhoneType.HOME; + break; + case 'work': + phoneNumber.type = Person_PhoneType.WORK; + break; + default: + print('Unknown phone type. Using default.'); + } + person.phones.add(phoneNumber); + } + + return person; +} + +/// Reads the entire address book from a file, adds one person based +/// on user input, then writes it back out to the same file. +void main(List arguments) { + if (arguments.length != 1) { + print('Usage: add_person ADDRESS_BOOK_FILE'); + exit(-1); + } + + final file = File(arguments.first); + AddressBook addressBook; + if (!file.existsSync()) { + print('File not found. Creating new file.'); + addressBook = AddressBook(); + } else { + addressBook = AddressBook.fromBuffer(file.readAsBytesSync()); + } + addressBook.people.add(promptForAddress()); + file.writeAsBytes(addressBook.writeToBuffer()); +} diff --git a/examples/add_person.go b/examples/add_person.go index 4f2e7f7418274..7ffb0ab095cc9 100644 --- a/examples/add_person.go +++ b/examples/add_person.go @@ -10,7 +10,7 @@ import ( "strings" "github.com/golang/protobuf/proto" - pb "github.com/google/protobuf/examples/tutorial" + pb "github.com/protocolbuffers/protobuf/examples/tutorial" ) func promptForAddress(r io.Reader) (*pb.Person, error) { diff --git a/examples/add_person.py b/examples/add_person.py index 0b6985792d7a5..aa0fbca7375df 100755 --- a/examples/add_person.py +++ b/examples/add_person.py @@ -5,6 +5,12 @@ import addressbook_pb2 import sys +try: + raw_input # Python 2 +except NameError: + raw_input = input # Python 3 + + # This function fills in a Person message based on user input. def PromptForAddress(person): person.id = int(raw_input("Enter person ID number: ")) @@ -30,13 +36,14 @@ def PromptForAddress(person): elif type == "work": phone_number.type = addressbook_pb2.Person.WORK else: - print "Unknown phone type; leaving as default value." + print("Unknown phone type; leaving as default value.") + # Main procedure: Reads the entire address book from a file, # adds one person based on user input, then writes it back out to the same # file. if len(sys.argv) != 2: - print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE" + print("Usage:", sys.argv[0], "ADDRESS_BOOK_FILE") sys.exit(-1) address_book = addressbook_pb2.AddressBook() @@ -46,7 +53,7 @@ def PromptForAddress(person): with open(sys.argv[1], "rb") as f: address_book.ParseFromString(f.read()) except IOError: - print sys.argv[1] + ": File not found. Creating a new file." + print(sys.argv[1] + ": File not found. Creating a new file.") # Add an address. PromptForAddress(address_book.people.add()) diff --git a/examples/add_person_test.go b/examples/add_person_test.go index 0507db6fc1471..d35f10ece9ca5 100644 --- a/examples/add_person_test.go +++ b/examples/add_person_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/golang/protobuf/proto" - pb "github.com/google/protobuf/examples/tutorial" + pb "github.com/protocolbuffers/protobuf/examples/tutorial" ) func TestPromptForAddressReturnsAddress(t *testing.T) { @@ -30,10 +30,10 @@ unknown t.Errorf("promptForAddress(%q) got %d, want ID %d", in, got.Id, 12345) } if got.Name != "Example Name" { - t.Errorf("promptForAddress(%q) => want name %q, got %q", "Example Name", got.Name) + t.Errorf("promptForAddress(%q) => want name %q, got %q", in, "Example Name", got.Name) } if got.Email != "name@example.com" { - t.Errorf("promptForAddress(%q) => want email %q, got %q", "name@example.com", got.Email) + t.Errorf("promptForAddress(%q) => want email %q, got %q", in, "name@example.com", got.Email) } want := []*pb.Person_PhoneNumber{ diff --git a/examples/addressbook.proto b/examples/addressbook.proto index 23cc2f97e76a0..b4b33b4c65892 100644 --- a/examples/addressbook.proto +++ b/examples/addressbook.proto @@ -9,6 +9,8 @@ // [START declaration] syntax = "proto3"; package tutorial; + +import "google/protobuf/timestamp.proto"; // [END declaration] // [START java_declaration] @@ -38,6 +40,8 @@ message Person { } repeated PhoneNumber phones = 4; + + google.protobuf.Timestamp last_updated = 5; } // Our address book file is just one of these. diff --git a/examples/list_people.cc b/examples/list_people.cc index 68e5666d84e6f..b309c59680473 100644 --- a/examples/list_people.cc +++ b/examples/list_people.cc @@ -1,11 +1,16 @@ // See README.txt for information and build instructions. -#include #include +#include +#include #include + #include "addressbook.pb.h" + using namespace std; +using google::protobuf::util::TimeUtil; + // Iterates though all people in the AddressBook and prints info about them. void ListPeople(const tutorial::AddressBook& address_book) { for (int i = 0; i < address_book.people_size(); i++) { @@ -30,9 +35,15 @@ void ListPeople(const tutorial::AddressBook& address_book) { case tutorial::Person::WORK: cout << " Work phone #: "; break; + default: + cout << " Unknown phone #: "; + break; } cout << phone_number.number() << endl; } + if (person.has_last_updated()) { + cout << " Updated: " << TimeUtil::ToString(person.last_updated()) << endl; + } } } diff --git a/examples/list_people.dart b/examples/list_people.dart new file mode 100644 index 0000000000000..8a96d82338922 --- /dev/null +++ b/examples/list_people.dart @@ -0,0 +1,47 @@ +import 'dart:io'; + +import 'dart_tutorial/addressbook.pb.dart'; +import 'dart_tutorial/addressbook.pbenum.dart'; + +/// Iterates though all people in the AddressBook and prints info about them. +void printAddressBook(AddressBook addressBook) { + for (var person in addressBook.people) { + print('Person ID: ${person.id}'); + print(' Name: ${person.name}'); + if (person.hasEmail()) { + print(' E-mail address:${person.email}'); + } + + for (var phoneNumber in person.phones) { + switch (phoneNumber.type) { + case Person_PhoneType.MOBILE: + print(' Mobile phone #: '); + break; + case Person_PhoneType.HOME: + print(' Home phone #: '); + break; + case Person_PhoneType.WORK: + print(' Work phone #: '); + break; + default: + print(' Unknown phone #: '); + break; + } + print(phoneNumber.number); + } + } +} + +/// Reads the entire address book from a file and prints all +/// the information inside. +void main(List arguments) { + if (arguments.length != 1) { + print('Usage: list_person ADDRESS_BOOK_FILE'); + exit(-1); + } + + // Read the existing address book. + final file = new File(arguments.first); + final addressBook = new AddressBook.fromBuffer(file.readAsBytesSync()); + printAddressBook(addressBook); +} diff --git a/examples/list_people.go b/examples/list_people.go index 70bc589efc5ce..6c2c34ac332a9 100644 --- a/examples/list_people.go +++ b/examples/list_people.go @@ -8,7 +8,7 @@ import ( "os" "github.com/golang/protobuf/proto" - pb "github.com/google/protobuf/examples/tutorial" + pb "github.com/protocolbuffers/protobuf/examples/tutorial" ) func writePerson(w io.Writer, p *pb.Person) { diff --git a/examples/list_people.py b/examples/list_people.py index f131872d841ed..d2c294c6f5cb8 100755 --- a/examples/list_people.py +++ b/examples/list_people.py @@ -2,30 +2,33 @@ # See README.txt for information and build instructions. +from __future__ import print_function import addressbook_pb2 import sys + # Iterates though all people in the AddressBook and prints info about them. def ListPeople(address_book): for person in address_book.people: - print "Person ID:", person.id - print " Name:", person.name + print("Person ID:", person.id) + print(" Name:", person.name) if person.email != "": - print " E-mail address:", person.email + print(" E-mail address:", person.email) for phone_number in person.phones: if phone_number.type == addressbook_pb2.Person.MOBILE: - print " Mobile phone #:", + print(" Mobile phone #:", end=" ") elif phone_number.type == addressbook_pb2.Person.HOME: - print " Home phone #:", + print(" Home phone #:", end=" ") elif phone_number.type == addressbook_pb2.Person.WORK: - print " Work phone #:", - print phone_number.number + print(" Work phone #:", end=" ") + print(phone_number.number) + # Main procedure: Reads the entire address book from a file and prints all # the information inside. if len(sys.argv) != 2: - print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE" + print("Usage:", sys.argv[0], "ADDRESS_BOOK_FILE") sys.exit(-1) address_book = addressbook_pb2.AddressBook() diff --git a/examples/list_people_test.go b/examples/list_people_test.go index 87d6ad6ec671c..aceabd4a61089 100644 --- a/examples/list_people_test.go +++ b/examples/list_people_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - pb "github.com/google/protobuf/examples/tutorial" + pb "github.com/protocolbuffers/protobuf/examples/tutorial" ) func TestWritePersonWritesPerson(t *testing.T) { @@ -34,7 +34,7 @@ func TestWritePersonWritesPerson(t *testing.T) { func TestListPeopleWritesList(t *testing.T) { buf := new(bytes.Buffer) - in := pb.AddressBook{[]*pb.Person{ + in := pb.AddressBook{People: []*pb.Person{ { Name: "John Doe", Id: 101, diff --git a/examples/pubspec.yaml b/examples/pubspec.yaml new file mode 100644 index 0000000000000..0c36dbdcd3384 --- /dev/null +++ b/examples/pubspec.yaml @@ -0,0 +1,5 @@ +name: addressbook +description: dartlang.org example code. + +dependencies: + protobuf: diff --git a/fix_permissions.sh b/fix_permissions.sh new file mode 100755 index 0000000000000..f33c25c3067b1 --- /dev/null +++ b/fix_permissions.sh @@ -0,0 +1,8 @@ +#!/bin/bash +for file in $(find . -type f); do + if [ "$(head -c 2 $file)" == "#!" ]; then + chmod u+x $file + else + chmod a-x $file + fi +done diff --git a/generate_changelog.py b/generate_changelog.py index d90a9b7043107..60803c59dccce 100755 --- a/generate_changelog.py +++ b/generate_changelog.py @@ -20,11 +20,10 @@ def __init__(self, name, pathspec): ]), Language("Java", [ "java", - "javanano", - "src/google/protobuf/compiler/cpp", + "src/google/protobuf/compiler/java", ]), Language("Python", [ - "javanano", + "python", "src/google/protobuf/compiler/python", ]), Language("JavaScript", [ @@ -63,4 +62,4 @@ def __init__(self, name, pathspec): print("") print("To view a commit on GitHub: " + - "https://github.com/google/protobuf/commit/") + "https://github.com/protocolbuffers/protobuf/commit/") diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh index 8a5ed48a2b8b6..dc03fee019d1f 100755 --- a/generate_descriptor_proto.sh +++ b/generate_descriptor_proto.sh @@ -18,14 +18,6 @@ __EOF__ exit 1 fi -if test ! -e src/Makefile; then - cat >&2 << __EOF__ -Could not find src/Makefile. You must run ./configure (and perhaps -./autogen.sh) first. -__EOF__ - exit 1 -fi - cd src declare -a RUNTIME_PROTO_FILES=(\ @@ -51,7 +43,7 @@ while [ $# -gt 0 ]; do case $1 in --bootstrap_protoc) BOOTSTRAP_PROTOC=$2 - shift + shift 2 ;; *) break @@ -70,7 +62,7 @@ do PROTOC=$BOOTSTRAP_PROTOC BOOTSTRAP_PROTOC="" else - make $@ protoc + make -j$(nproc) $@ protoc if test $? -ne 0; then echo "Failed to build protoc." exit 1 @@ -78,8 +70,8 @@ do PROTOC="./protoc" fi - $PROTOC --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:$TMP ${RUNTIME_PROTO_FILES[@]} && \ - $PROTOC --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:$TMP ${COMPILER_PROTO_FILES[@]} + $PROTOC --cpp_out=dllexport_decl=PROTOBUF_EXPORT:$TMP ${RUNTIME_PROTO_FILES[@]} && \ + $PROTOC --cpp_out=dllexport_decl=PROTOC_EXPORT:$TMP ${COMPILER_PROTO_FILES[@]} for PROTO_FILE in ${RUNTIME_PROTO_FILES[@]} ${COMPILER_PROTO_FILES[@]}; do BASE_NAME=${PROTO_FILE%.*} diff --git a/global.json b/global.json new file mode 100644 index 0000000000000..16f71a741fa76 --- /dev/null +++ b/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "3.0.100", + "rollForward": "latestMinor" + } +} diff --git a/gmock.BUILD b/gmock.BUILD deleted file mode 100644 index b1ae15a919309..0000000000000 --- a/gmock.BUILD +++ /dev/null @@ -1,28 +0,0 @@ -cc_library( - name = "gtest", - srcs = [ - "googletest/src/gtest-all.cc", - "googlemock/src/gmock-all.cc", - ], - hdrs = glob([ - "**/*.h", - "googletest/src/*.cc", - "googlemock/src/*.cc", - ]), - includes = [ - "googlemock", - "googletest", - "googletest/include", - "googlemock/include", - ], - linkopts = ["-pthread"], - visibility = ["//visibility:public"], -) - -cc_library( - name = "gtest_main", - srcs = ["googlemock/src/gmock_main.cc"], - linkopts = ["-pthread"], - visibility = ["//visibility:public"], - deps = [":gtest"], -) diff --git a/java/README.md b/java/README.md index 0e0fba647ae18..c8050893e02c3 100644 --- a/java/README.md +++ b/java/README.md @@ -1,17 +1,77 @@ -Protocol Buffers - Google's data interchange format -=================================================== - -[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) +# Protocol Buffers - Google's data interchange format Copyright 2008 Google Inc. -This directory contains the Java Protocol Buffers runtime library. +https://developers.google.com/protocol-buffers/ + +## Use Java Protocol Buffers + +To use protobuf in Java, first obtain the protocol compiler (a.k.a., protoc, +see instructions in the toplevel [README.md](../README.md)) and use it to +generate Java code for your .proto files: + + $ protoc --java_out=${OUTPUT_DIR} path/to/your/proto/file + +Include the generated Java files in your project and add a dependency on the +protobuf Java runtime. + +### Maven + +If you are using Maven, use the following: + +```xml + + com.google.protobuf + protobuf-java + 3.11.0 + +``` + +Make sure the version number of the runtime matches (or is newer than) the +version number of the protoc. + +If you want to use features like protobuf JsonFormat, add a dependency on the +protobuf-java-util package: + +```xml + + com.google.protobuf + protobuf-java-util + 3.11.0 + +``` + +### Gradle + +If you are using Gradle, add the following to your `build.gradle` file's dependencies: +``` + implementation 'com.google.protobuf:protobuf-java:3.11.0' +``` +Again, be sure to check that the version number matches (or is newer than) the version number of protoc that you are using. + +### Use Java Protocol Buffers on Android + +For Android users, it's recommended to use protobuf Java Lite runtime because +of its smaller code size. Java Lite runtime also works better with Proguard +because it doesn't rely on Java reflection and is optimized to allow as much +code stripping as possible. You can following these [instructions to use Java +Lite runtime](lite.md). + +### Use Java Protocol Buffers with Bazel + +Bazel has native build rules to work with protobuf. For Java, you can use the +`java_proto_library` rule for server and the `java_lite_proto_library` rule +for Android. Check out [our build files examples](../examples/BUILD) to learn +how to use them. + +## Build from Source -Installation - With Maven -========================= +Most users should follow the instructions above to use protobuf Java runtime. +If you are contributing code to protobuf or want to use a protobuf version +that hasn't been officially released yet, you can follow the instructions +below to build protobuf from source code. -The Protocol Buffers build is managed using Maven. If you would -rather build without Maven, see below. +### Build from Source - With Maven 1) Install Apache Maven if you don't have it: @@ -45,20 +105,15 @@ rather build without Maven, see below. The .jar will be placed in the "target" directory. -The above instructions will install 3 maven artifacts: +The above instructions will install 2 maven artifacts: * protobuf-java: The core Java Protocol Buffers library. Most users only need this artifact. - * protobuf-lite: The lite version of core Java Protobuf Buffers library. It - is a subset of the core library and is used together with - the 'lite' code generator flag to reduce generated code size - for mobile. * protobuf-java-util: Utilities to work with protos. It contains JSON support as well as utilities to work with proto3 well-known types. -Installation - Without Maven -============================ +### Build from Source - Without Maven If you would rather not install Maven to build the library, you may follow these instructions instead. Note that these instructions skip @@ -83,8 +138,7 @@ library (without the util package). 4) Install the classes wherever you prefer. -Compatibility Notice -==================== +## Compatibility Notice * Protobuf minor version releases are backwards-compatible. If your code can build/run against the old version, it's expected to build/run against @@ -92,7 +146,7 @@ Compatibility Notice are guaranteed for minor version releases if the user follows the guideline described in this section. -* Protobuf major version releases may also be backwards-compatbile with the +* Protobuf major version releases may also be backwards-compatible with the last release of the previous major version. See the release notice for more details. @@ -118,8 +172,7 @@ Compatibility Notice * Protobuf LITE runtime APIs are not stable yet. They are subject to change even in minor version releases. -Documentation -============= +## Documentation The complete documentation for Protocol Buffers is available via the web at: diff --git a/java/bom/pom.xml b/java/bom/pom.xml new file mode 100644 index 0000000000000..7fbd41da5ed50 --- /dev/null +++ b/java/bom/pom.xml @@ -0,0 +1,110 @@ + + + 4.0.0 + + com.google.protobuf + protobuf-bom + 3.15.0 + pom + + Protocol Buffers [BOM] + A compatible set of open source libraries for working with protocol buffers. + https://developers.google.com/protocol-buffers/ + + + Google LLC + https://cloud.google.com + + + + + haon + Hao Nguyen + haon@google.com + Google + https://cloud.google.com + America/Los_Angeles + + + + + + 3-Clause BSD License + https://opensource.org/licenses/BSD-3-Clause + + + + + https://github.com/protocolbuffers/protobuf + scm:git:https://github.com/protocolbuffers/protobuf.git + + + + UTF-8 + + + + + sonatype-nexus-staging + https://oss.sonatype.org/content/repositories/snapshots + + + sonatype-nexus-staging + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + + com.google.protobuf + protobuf-java + ${project.version} + + + com.google.protobuf + protobuf-java-util + ${project.version} + + + + + + + + release + + + + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.6 + true + + https://oss.sonatype.org/ + sonatype-nexus-staging + false + + + + + + + diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/descriptor.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/descriptor.proto index a785f79faf610..95c8d4d2e32b1 100644 --- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/descriptor.proto +++ b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/descriptor.proto @@ -74,7 +74,7 @@ message FileDescriptorProto { optional FileOptions options = 8; // This field contains optional information about the original source code. - // You may safely remove this entire field whithout harming runtime + // You may safely remove this entire field without harming runtime // functionality of the descriptors -- the information is needed only by // development tools. optional SourceCodeInfo source_code_info = 9; @@ -228,7 +228,7 @@ message MethodDescriptorProto { // * For options which will be published and used publicly by multiple // independent entities, e-mail protobuf-global-extension-registry@google.com // to reserve extension numbers. Simply provide your project name (e.g. -// Object-C plugin) and your porject website (if available) -- there's no need +// Object-C plugin) and your project website (if available) -- there's no need // to explain how you intend to use them. Usually you only need one extension // number. You can declare multiple options with only one extension number by // putting them in a sub-message. See the Custom Options section of the docs diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_custom_options.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_custom_options.proto index e591d29447505..2f4e3fdf95c42 100644 --- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_custom_options.proto +++ b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_custom_options.proto @@ -321,7 +321,7 @@ message Aggregate { } // Allow Aggregate to be used as an option at all possible locations -// in the .proto grammer. +// in the .proto grammar. extend google.protobuf.FileOptions { optional Aggregate fileopt = 15478479; } extend google.protobuf.MessageOptions { optional Aggregate msgopt = 15480088; } extend google.protobuf.FieldOptions { optional Aggregate fieldopt = 15481374; } diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import.proto index c115b11171afa..ec36ccadbe846 100644 --- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import.proto +++ b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import.proto @@ -43,7 +43,7 @@ package protobuf_unittest_import; option optimize_for = SPEED; -// Excercise the java_package option. +// Exercise the java_package option. option java_package = "com.google.protobuf.test"; // Do not set a java_outer_classname here to verify that Proto2 works without diff --git a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_optimize_for.proto b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_optimize_for.proto index feecbef8d4a90..658c6a9652229 100644 --- a/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_optimize_for.proto +++ b/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_optimize_for.proto @@ -55,7 +55,7 @@ message TestOptimizedForSize { message TestRequiredOptimizedForSize { required int32 x = 1; } - + message TestOptionalOptimizedForSize { optional TestRequiredOptimizedForSize o = 1; } diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto index a785f79faf610..95c8d4d2e32b1 100644 --- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto +++ b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto @@ -74,7 +74,7 @@ message FileDescriptorProto { optional FileOptions options = 8; // This field contains optional information about the original source code. - // You may safely remove this entire field whithout harming runtime + // You may safely remove this entire field without harming runtime // functionality of the descriptors -- the information is needed only by // development tools. optional SourceCodeInfo source_code_info = 9; @@ -228,7 +228,7 @@ message MethodDescriptorProto { // * For options which will be published and used publicly by multiple // independent entities, e-mail protobuf-global-extension-registry@google.com // to reserve extension numbers. Simply provide your project name (e.g. -// Object-C plugin) and your porject website (if available) -- there's no need +// Object-C plugin) and your project website (if available) -- there's no need // to explain how you intend to use them. Usually you only need one extension // number. You can declare multiple options with only one extension number by // putting them in a sub-message. See the Custom Options section of the docs diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto index e591d29447505..2f4e3fdf95c42 100644 --- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto +++ b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto @@ -321,7 +321,7 @@ message Aggregate { } // Allow Aggregate to be used as an option at all possible locations -// in the .proto grammer. +// in the .proto grammar. extend google.protobuf.FileOptions { optional Aggregate fileopt = 15478479; } extend google.protobuf.MessageOptions { optional Aggregate msgopt = 15480088; } extend google.protobuf.FieldOptions { optional Aggregate fieldopt = 15481374; } diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto index c115b11171afa..ec36ccadbe846 100644 --- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto +++ b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto @@ -43,7 +43,7 @@ package protobuf_unittest_import; option optimize_for = SPEED; -// Excercise the java_package option. +// Exercise the java_package option. option java_package = "com.google.protobuf.test"; // Do not set a java_outer_classname here to verify that Proto2 works without diff --git a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_optimize_for.proto b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_optimize_for.proto index feecbef8d4a90..658c6a9652229 100644 --- a/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_optimize_for.proto +++ b/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_optimize_for.proto @@ -55,7 +55,7 @@ message TestOptimizedForSize { message TestRequiredOptimizedForSize { required int32 x = 1; } - + message TestOptionalOptimizedForSize { optional TestRequiredOptimizedForSize o = 1; } diff --git a/java/compatibility_tests/v2.5.0/test.sh b/java/compatibility_tests/v2.5.0/test.sh index 5d5e9ed43908c..65ea960ca28ef 100755 --- a/java/compatibility_tests/v2.5.0/test.sh +++ b/java/compatibility_tests/v2.5.0/test.sh @@ -5,6 +5,9 @@ set -ex # Change to the script's directory. cd $(dirname $0) +MAVEN_LOCAL_REPOSITORY=/var/maven_local_repository +MVN="mvn --batch-mode -e -X -Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$MAVEN_LOCAL_REPOSITORY" + # Version of the tests (i.e., the version of protobuf from where we extracted # these tests). TEST_VERSION=`grep "^ .*" pom.xml | sed "s| \(.*\)|\1|"` @@ -12,43 +15,15 @@ TEST_VERSION=`grep "^ .*" pom.xml | sed "s| \(.*\) # The old version of protobuf that we are testing compatibility against. This # is usually the same as TEST_VERSION (i.e., we use the tests extracted from # that version to test compatibility of the newest runtime against it), but it -# is also possible to use this same test set to test the compatibiilty of the +# is also possible to use this same test set to test the compatibility of the # latest version against other versions. -case "$1" in - ""|2.5.0) - OLD_VERSION=2.5.0 - OLD_VERSION_PROTOC=https://github.com/xfxyjwf/protobuf-compiler-release/raw/master/v2.5.0/linux/protoc - ;; - 2.6.1) - OLD_VERSION=2.6.1 - OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/2.6.1-build2/protoc-2.6.1-build2-linux-x86_64.exe - ;; - 3.0.0-beta-1) - OLD_VERSION=3.0.0-beta-1 - OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-1/protoc-3.0.0-beta-1-linux-x86_64.exe - ;; - 3.0.0-beta-2) - OLD_VERSION=3.0.0-beta-2 - OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-2/protoc-3.0.0-beta-2-linux-x86_64.exe - ;; - 3.0.0-beta-3) - OLD_VERSION=3.0.0-beta-3 - OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-3/protoc-3.0.0-beta-3-linux-x86_64.exe - ;; - 3.0.0-beta-4) - OLD_VERSION=3.0.0-beta-4 - OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-4/protoc-3.0.0-beta-4-linux-x86_64.exe - ;; - *) - echo "[ERROR]: Unknown version number: $1" - exit 1 - ;; -esac +OLD_VERSION=$1 +OLD_VERSION_PROTOC=https://repo1.maven.org/maven2/com/google/protobuf/protoc/$OLD_VERSION/protoc-$OLD_VERSION-linux-x86_64.exe # Extract the latest protobuf version number. VERSION_NUMBER=`grep "^ .*" ../../pom.xml | sed "s| \(.*\)|\1|"` -echo "Running compatibility tests between $VERSION_NUMBER and $OLD_VERSION" +echo "Running compatibility tests between current $VERSION_NUMBER and released $OLD_VERSION" # Check protoc [ -f ../../../src/protoc ] || { @@ -59,13 +34,13 @@ echo "Running compatibility tests between $VERSION_NUMBER and $OLD_VERSION" # Build and install protobuf-java-$VERSION_NUMBER.jar [ -f ../../core/target/protobuf-java-$VERSION_NUMBER.jar ] || { pushd ../.. - mvn install -Dmaven.test.skip=true + $MVN install -Dmaven.test.skip=true popd } # Download old version source for the compatibility test [ -d protobuf ] || { - git clone https://github.com/google/protobuf.git + git clone https://github.com/protocolbuffers/protobuf.git cd protobuf git reset --hard v$TEST_VERSION cd .. @@ -81,7 +56,7 @@ chmod +x protoc # Test A.1: # protos: use new version # more_protos: use old version -mvn clean test \ +$MVN clean test \ -Dprotobuf.test.source.path=$(pwd)/protobuf \ -Dprotoc.path=$(pwd)/protoc \ -Dprotos.protoc.path=$(pwd)/../../../src/protoc \ @@ -90,7 +65,7 @@ mvn clean test \ # Test A.2: # protos: use old version # more_protos: use new version -mvn clean test \ +$MVN clean test \ -Dprotobuf.test.source.path=$(pwd)/protobuf \ -Dprotoc.path=$(pwd)/protoc \ -Dmore_protos.protoc.path=$(pwd)/../../../src/protoc \ @@ -103,12 +78,12 @@ mvn clean test \ # make it easier to run binary compatibility test (where we will need to run # the jar files directly). cd deps -mvn assembly:single +$MVN assembly:single cd .. cp -f deps/target/compatibility-test-deps-${TEST_VERSION}-jar-with-dependencies.jar deps.jar # Build the old version of all 3 artifacts. -mvn clean install -Dmaven.test.skip=true -Dprotoc.path=$(pwd)/protoc -Dprotobuf.version=$OLD_VERSION +$MVN clean install -Dmaven.test.skip=true -Dprotoc.path=$(pwd)/protoc -Dprotobuf.version=$OLD_VERSION cp -f protos/target/compatibility-protos-${TEST_VERSION}.jar protos.jar cp -f more_protos/target/compatibility-more-protos-${TEST_VERSION}.jar more_protos.jar cp -f tests/target/compatibility-tests-${TEST_VERSION}.jar tests.jar @@ -125,7 +100,7 @@ cd .. # Test B.2: update protos.jar only. cd protos -mvn clean package -Dmaven.test.skip=true -Dprotoc.path=$(pwd)/../../../../src/protoc -Dprotobuf.version=$VERSION_NUMBER +$MVN clean package -Dmaven.test.skip=true -Dprotoc.path=$(pwd)/../../../../src/protoc -Dprotobuf.version=$VERSION_NUMBER cd .. cd protobuf java -cp ../../../core/target/protobuf-java-$VERSION_NUMBER.jar:../protos/target/compatibility-protos-${TEST_VERSION}.jar:../more_protos.jar:../tests.jar:../deps.jar org.junit.runner.JUnitCore $TESTS @@ -133,7 +108,7 @@ cd .. # Test B.3: update more_protos.jar only. cd more_protos -mvn clean package -Dmaven.test.skip=true -Dprotoc.path=$(pwd)/../../../../src/protoc -Dprotobuf.version=$VERSION_NUMBER +$MVN clean package -Dmaven.test.skip=true -Dprotoc.path=$(pwd)/../../../../src/protoc -Dprotobuf.version=$VERSION_NUMBER cd .. cd protobuf java -cp ../../../core/target/protobuf-java-$VERSION_NUMBER.jar:../protos.jar:../more_protos/target/compatibility-more-protos-${TEST_VERSION}.jar:../tests.jar:../deps.jar org.junit.runner.JUnitCore $TESTS diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ByteStringTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ByteStringTest.java index 8bb9f731d2fac..9e334e5e92f4c 100644 --- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ByteStringTest.java +++ b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ByteStringTest.java @@ -342,7 +342,7 @@ public int read() { return -1; } } - + // A stream which exposes the byte array passed into write(byte[], int, int). private static class EvilOutputStream extends OutputStream { public byte[] capturedArray = null; @@ -454,13 +454,13 @@ public void testNewOutput_Mixed() throws IOException { isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length)); } } - + public void testNewOutputEmpty() throws IOException { // Make sure newOutput() correctly builds empty byte strings ByteString byteString = ByteString.newOutput().toByteString(); assertEquals(ByteString.EMPTY, byteString); } - + public void testNewOutput_Mutating() throws IOException { Output os = ByteString.newOutput(5); os.write(new byte[] {1, 2, 3, 4, 5}); diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DeprecatedFieldTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DeprecatedFieldTest.java index ee4e767520da7..a7b77067f4b20 100644 --- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DeprecatedFieldTest.java +++ b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DeprecatedFieldTest.java @@ -39,22 +39,22 @@ import java.lang.reflect.Method; /** * Test field deprecation - * + * * @author birdo@google.com (Roberto Scaramuzzi) */ public class DeprecatedFieldTest extends TestCase { private String[] deprecatedGetterNames = { "hasDeprecatedInt32", "getDeprecatedInt32"}; - + private String[] deprecatedBuilderGetterNames = { "hasDeprecatedInt32", "getDeprecatedInt32", "clearDeprecatedInt32"}; - + private String[] deprecatedBuilderSetterNames = { - "setDeprecatedInt32"}; - + "setDeprecatedInt32"}; + public void testDeprecatedField() throws Exception { Class deprecatedFields = TestDeprecatedFields.class; Class deprecatedFieldsBuilder = TestDeprecatedFields.Builder.class; @@ -74,7 +74,7 @@ public void testDeprecatedField() throws Exception { isDeprecated(method)); } } - + private boolean isDeprecated(AnnotatedElement annotated) { return annotated.isAnnotationPresent(Deprecated.class); } diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DescriptorsTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DescriptorsTest.java index aabd7b4d7307b..37e1ca7350970 100644 --- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DescriptorsTest.java +++ b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DescriptorsTest.java @@ -490,7 +490,7 @@ public void testDescriptorComplexCrosslink() throws Exception { .build(); // translate and crosslink FileDescriptor file = - Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, + Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]); // verify resulting descriptors assertNotNull(file); @@ -511,7 +511,7 @@ public void testDescriptorComplexCrosslink() throws Exception { } assertTrue(barFound); } - + public void testInvalidPublicDependency() throws Exception { FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() .setName("foo.proto") .build(); @@ -595,7 +595,7 @@ public void testPublicDependency() throws Exception { Descriptors.FileDescriptor.buildFrom( fooProto, new FileDescriptor[] {forwardFile}); } - + /** * Tests the translate/crosslink for an example with a more complex namespace * referencing. @@ -644,6 +644,6 @@ public void testComplexNamespacePublicDependency() throws Exception { assertTrue(field.getEnumType().getFile().getName().equals("bar.proto")); assertTrue(field.getEnumType().getFile().getPackage().equals( "a.b.c.d.bar.shared")); - } + } } } diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/GeneratedMessageTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/GeneratedMessageTest.java index 49f114643cea8..1e7d41e8516fc 100644 --- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/GeneratedMessageTest.java +++ b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/GeneratedMessageTest.java @@ -901,7 +901,7 @@ public void testGetFieldBuilderWithInitializedValue() { FieldDescriptor fieldDescriptor = descriptor.findFieldByName("optional_nested_message"); - // Before setting field, builder is initialized by default value. + // Before setting field, builder is initialized by default value. TestAllTypes.Builder builder = TestAllTypes.newBuilder(); NestedMessage.Builder fieldBuilder = (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor); diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LiteralByteStringTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LiteralByteStringTest.java index b2dcc7e88238d..d2ce563a5cab0 100644 --- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LiteralByteStringTest.java +++ b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LiteralByteStringTest.java @@ -87,7 +87,7 @@ public void testByteIterator() { stillEqual = (iter.hasNext() && referenceBytes[i] == iter.nextByte()); } assertTrue(classUnderTest + " must capture the right bytes", stillEqual); - assertFalse(classUnderTest + " must have exhausted the itertor", iter.hasNext()); + assertFalse(classUnderTest + " must have exhausted the iterator", iter.hasNext()); try { iter.nextByte(); @@ -233,7 +233,7 @@ public void testWriteTo() throws IOException { assertTrue(classUnderTest + ".writeTo() must give back the same bytes", Arrays.equals(referenceBytes, roundTripBytes)); } - + public void testWriteTo_mutating() throws IOException { OutputStream os = new OutputStream() { @Override @@ -274,7 +274,7 @@ public void testNewOutput() throws IOException { assertEquals("Output.reset() resets the output", 0, output.size()); assertEquals("Output.reset() resets the output", ByteString.EMPTY, output.toByteString()); - + } public void testHashCode() { @@ -317,7 +317,7 @@ public void testNewInput_skip() throws IOException { assertEquals("InputStream.skip(), no more input", 0, input.available()); assertEquals("InputStream.skip(), no more input", -1, input.read()); input.reset(); - assertEquals("InputStream.reset() succeded", + assertEquals("InputStream.reset() succeeded", stringSize - skipped1, input.available()); assertEquals("InputStream.reset(), read()", stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read()); diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/MessageTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/MessageTest.java index c8c95a87c7cdb..629cabc0c5701 100644 --- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/MessageTest.java +++ b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/MessageTest.java @@ -313,7 +313,7 @@ public void testDynamicParseUnititialized() throws Exception { assertEquals("Message missing required fields: a, b, c", e.getMessage()); } } - + /** Test reading unset repeated message from DynamicMessage. */ public void testDynamicRepeatedMessageNull() throws Exception { Descriptors.Descriptor descriptor = TestRequired.getDescriptor(); @@ -327,7 +327,7 @@ public void testDynamicRepeatedMessageNull() throws Exception { assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType() .findFieldByName("repeated_foreign_message")), 0); } - + /** Test reading repeated message from DynamicMessage. */ public void testDynamicRepeatedMessageNotNull() throws Exception { diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringSubstringTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringSubstringTest.java index 3c1f5035b71ba..c122385ac1ce2 100644 --- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringSubstringTest.java +++ b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringSubstringTest.java @@ -36,7 +36,7 @@ /** * This class tests {@link RopeByteString#substring(int, int)} by inheriting the tests from - * {@link LiteralByteStringTest}. Only a couple of methods are overridden. + * {@link LiteralByteStringTest}. Only a couple of methods are overridden. * * @author carlanton@google.com (Carl Haverl) */ diff --git a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringTest.java b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringTest.java index 8caeadd9a161d..19098de660a27 100644 --- a/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringTest.java +++ b/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringTest.java @@ -38,7 +38,7 @@ /** * This class tests {@link RopeByteString} by inheriting the tests from * {@link LiteralByteStringTest}. Only a couple of methods are overridden. - * + * *

A full test of the result of {@link RopeByteString#substring(int, int)} is found in the * separate class {@link RopeByteStringSubstringTest}. * diff --git a/java/core/BUILD b/java/core/BUILD new file mode 100644 index 0000000000000..e7778f9a62e09 --- /dev/null +++ b/java/core/BUILD @@ -0,0 +1,127 @@ +load("@rules_java//java:defs.bzl", "java_library") +load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain") + +LITE_SRCS = [ + # Keep in sync with `//java/lite:pom.xml`. + "src/main/java/com/google/protobuf/AbstractMessageLite.java", + "src/main/java/com/google/protobuf/AbstractParser.java", + "src/main/java/com/google/protobuf/AbstractProtobufList.java", + "src/main/java/com/google/protobuf/AllocatedBuffer.java", + "src/main/java/com/google/protobuf/Android.java", + "src/main/java/com/google/protobuf/ArrayDecoders.java", + "src/main/java/com/google/protobuf/BinaryReader.java", + "src/main/java/com/google/protobuf/BinaryWriter.java", + "src/main/java/com/google/protobuf/BooleanArrayList.java", + "src/main/java/com/google/protobuf/BufferAllocator.java", + "src/main/java/com/google/protobuf/ByteBufferWriter.java", + "src/main/java/com/google/protobuf/ByteOutput.java", + "src/main/java/com/google/protobuf/ByteString.java", + "src/main/java/com/google/protobuf/CodedInputStream.java", + "src/main/java/com/google/protobuf/CodedInputStreamReader.java", + "src/main/java/com/google/protobuf/CodedOutputStream.java", + "src/main/java/com/google/protobuf/CodedOutputStreamWriter.java", + "src/main/java/com/google/protobuf/DoubleArrayList.java", + "src/main/java/com/google/protobuf/ExperimentalApi.java", + "src/main/java/com/google/protobuf/ExtensionLite.java", + "src/main/java/com/google/protobuf/ExtensionRegistryFactory.java", + "src/main/java/com/google/protobuf/ExtensionRegistryLite.java", + "src/main/java/com/google/protobuf/ExtensionSchema.java", + "src/main/java/com/google/protobuf/ExtensionSchemaLite.java", + "src/main/java/com/google/protobuf/ExtensionSchemas.java", + "src/main/java/com/google/protobuf/FieldInfo.java", + "src/main/java/com/google/protobuf/FieldSet.java", + "src/main/java/com/google/protobuf/FieldType.java", + "src/main/java/com/google/protobuf/FloatArrayList.java", + "src/main/java/com/google/protobuf/GeneratedMessageInfoFactory.java", + "src/main/java/com/google/protobuf/GeneratedMessageLite.java", + "src/main/java/com/google/protobuf/IntArrayList.java", + "src/main/java/com/google/protobuf/Internal.java", + "src/main/java/com/google/protobuf/InvalidProtocolBufferException.java", + "src/main/java/com/google/protobuf/IterableByteBufferInputStream.java", + "src/main/java/com/google/protobuf/JavaType.java", + "src/main/java/com/google/protobuf/LazyField.java", + "src/main/java/com/google/protobuf/LazyFieldLite.java", + "src/main/java/com/google/protobuf/LazyStringArrayList.java", + "src/main/java/com/google/protobuf/LazyStringList.java", + "src/main/java/com/google/protobuf/ListFieldSchema.java", + "src/main/java/com/google/protobuf/LongArrayList.java", + "src/main/java/com/google/protobuf/ManifestSchemaFactory.java", + "src/main/java/com/google/protobuf/MapEntryLite.java", + "src/main/java/com/google/protobuf/MapFieldLite.java", + "src/main/java/com/google/protobuf/MapFieldSchema.java", + "src/main/java/com/google/protobuf/MapFieldSchemaLite.java", + "src/main/java/com/google/protobuf/MapFieldSchemas.java", + "src/main/java/com/google/protobuf/MessageInfo.java", + "src/main/java/com/google/protobuf/MessageInfoFactory.java", + "src/main/java/com/google/protobuf/MessageLite.java", + "src/main/java/com/google/protobuf/MessageLiteOrBuilder.java", + "src/main/java/com/google/protobuf/MessageLiteToString.java", + "src/main/java/com/google/protobuf/MessageSchema.java", + "src/main/java/com/google/protobuf/MessageSetSchema.java", + "src/main/java/com/google/protobuf/MutabilityOracle.java", + "src/main/java/com/google/protobuf/NewInstanceSchema.java", + "src/main/java/com/google/protobuf/NewInstanceSchemaLite.java", + "src/main/java/com/google/protobuf/NewInstanceSchemas.java", + "src/main/java/com/google/protobuf/NioByteString.java", + "src/main/java/com/google/protobuf/OneofInfo.java", + "src/main/java/com/google/protobuf/Parser.java", + "src/main/java/com/google/protobuf/PrimitiveNonBoxingCollection.java", + "src/main/java/com/google/protobuf/ProtoSyntax.java", + "src/main/java/com/google/protobuf/Protobuf.java", + "src/main/java/com/google/protobuf/ProtobufArrayList.java", + "src/main/java/com/google/protobuf/ProtobufLists.java", + "src/main/java/com/google/protobuf/ProtocolStringList.java", + "src/main/java/com/google/protobuf/RawMessageInfo.java", + "src/main/java/com/google/protobuf/Reader.java", + "src/main/java/com/google/protobuf/RopeByteString.java", + "src/main/java/com/google/protobuf/Schema.java", + "src/main/java/com/google/protobuf/SchemaFactory.java", + "src/main/java/com/google/protobuf/SchemaUtil.java", + "src/main/java/com/google/protobuf/SmallSortedMap.java", + "src/main/java/com/google/protobuf/StructuralMessageInfo.java", + "src/main/java/com/google/protobuf/TextFormatEscaper.java", + "src/main/java/com/google/protobuf/UninitializedMessageException.java", + "src/main/java/com/google/protobuf/UnknownFieldSchema.java", + "src/main/java/com/google/protobuf/UnknownFieldSetLite.java", + "src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java", + "src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java", + "src/main/java/com/google/protobuf/UnsafeUtil.java", + "src/main/java/com/google/protobuf/Utf8.java", + "src/main/java/com/google/protobuf/WireFormat.java", + "src/main/java/com/google/protobuf/Writer.java", +] + +# Should be used as `//java/lite`. +java_library( + name = "lite", + srcs = LITE_SRCS, + visibility = [ + "//java/lite:__pkg__", + ], +) + +java_library( + name = "core", + srcs = glob( + [ + "src/main/java/com/google/protobuf/*.java", + ], + exclude = LITE_SRCS, + ) + [ + "//:gen_well_known_protos_java", + ], + visibility = ["//visibility:public"], + exports = [ + "//java/lite", + ], + deps = [ + "//java/lite", + ], +) + +proto_lang_toolchain( + name = "toolchain", + command_line = "--java_out=$(OUT)", + runtime = ":core", + visibility = ["//visibility:public"], +) diff --git a/java/core/generate-test-sources-build.xml b/java/core/generate-test-sources-build.xml index 68951747cae2c..71a88d07b33b3 100644 --- a/java/core/generate-test-sources-build.xml +++ b/java/core/generate-test-sources-build.xml @@ -5,40 +5,57 @@ - + + + + + - - - - - - - + + + + + + + + + + + + + - - + + + + + + - - - - - - + + + + + + + + + diff --git a/java/core/pom.xml b/java/core/pom.xml index 4608fce6574a6..79b967bb0e051 100644 --- a/java/core/pom.xml +++ b/java/core/pom.xml @@ -1,12 +1,10 @@ - + 4.0.0 com.google.protobuf protobuf-parent - 3.4.0 + 3.15.0 protobuf-java @@ -34,6 +32,16 @@ easymockclassextension test + + com.google.guava + guava + test + + + com.google.truth + truth + test + @@ -57,6 +65,15 @@ + + + ${protobuf.source.dir} + + google/protobuf/testdata/golden_message_oneof_implemented + google/protobuf/testdata/golden_packed_fields_message + + + @@ -132,9 +149,11 @@ true + com.google.protobuf https://developers.google.com/protocol-buffers/ com.google.protobuf com.google.protobuf;version=${project.version} + sun.misc;resolution:=optional,* diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java index 065fa1a921ebb..1364fce41ec40 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java +++ b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java @@ -32,7 +32,6 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; -import com.google.protobuf.Descriptors.FileDescriptor.Syntax; import com.google.protobuf.Descriptors.OneofDescriptor; import com.google.protobuf.Internal.EnumLite; import java.io.IOException; @@ -45,15 +44,14 @@ import java.util.Map; /** - * A partial implementation of the {@link Message} interface which implements - * as many methods of that interface as possible in terms of other methods. + * A partial implementation of the {@link Message} interface which implements as many methods of + * that interface as possible in terms of other methods. * * @author kenton@google.com Kenton Varda */ public abstract class AbstractMessage // TODO(dweis): Update GeneratedMessage to parameterize with MessageType and BuilderType. - extends AbstractMessageLite - implements Message { + extends AbstractMessageLite implements Message { @Override public boolean isInitialized() { @@ -61,24 +59,21 @@ public boolean isInitialized() { } /** - * Interface for the parent of a Builder that allows the builder to - * communicate invalidations back to the parent for use when using nested - * builders. + * Interface for the parent of a Builder that allows the builder to communicate invalidations back + * to the parent for use when using nested builders. */ protected interface BuilderParent { /** - * A builder becomes dirty whenever a field is modified -- including fields - * in nested builders -- and becomes clean when build() is called. Thus, - * when a builder becomes dirty, all its parents become dirty as well, and - * when it becomes clean, all its children become clean. The dirtiness - * state is used to invalidate certain cached values. - *
- * To this end, a builder calls markDirty() on its parent whenever it - * transitions from clean to dirty. The parent must propagate this call to - * its own parent, unless it was already dirty, in which case the - * grandparent must necessarily already be dirty as well. The parent can - * only transition back to "clean" after calling build() on all children. + * A builder becomes dirty whenever a field is modified -- including fields in nested builders + * -- and becomes clean when build() is called. Thus, when a builder becomes dirty, all its + * parents become dirty as well, and when it becomes clean, all its children become clean. The + * dirtiness state is used to invalidate certain cached values. + * + *

To this end, a builder calls markDirty() on its parent whenever it transitions from clean + * to dirty. The parent must propagate this call to its own parent, unless it was already dirty, + * in which case the grandparent must necessarily already be dirty as well. The parent can only + * transition back to "clean" after calling build() on all children. */ void markDirty(); } @@ -108,13 +103,12 @@ public boolean hasOneof(OneofDescriptor oneof) { /** TODO(jieluo): Clear it when all subclasses have implemented this method. */ @Override public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) { - throw new UnsupportedOperationException( - "getOneofFieldDescriptor() is not implemented."); + throw new UnsupportedOperationException("getOneofFieldDescriptor() is not implemented."); } @Override public final String toString() { - return TextFormat.printToString(this); + return TextFormat.printer().printToString(this); } @Override @@ -124,6 +118,16 @@ public void writeTo(final CodedOutputStream output) throws IOException { protected int memoizedSize = -1; + @Override + int getMemoizedSerializedSize() { + return memoizedSize; + } + + @Override + void setMemoizedSerializedSize(int size) { + memoizedSize = size; + } + @Override public int getSerializedSize() { int size = memoizedSize; @@ -147,8 +151,8 @@ public boolean equals(final Object other) { if (getDescriptorForType() != otherMessage.getDescriptorForType()) { return false; } - return compareFields(getAllFields(), otherMessage.getAllFields()) && - getUnknownFields().equals(otherMessage.getUnknownFields()); + return compareFields(getAllFields(), otherMessage.getAllFields()) + && getUnknownFields().equals(otherMessage.getUnknownFields()); } @Override @@ -173,26 +177,23 @@ private static ByteString toByteString(Object value) { } /** - * Compares two bytes fields. The parameters must be either a byte array or a - * ByteString object. They can be of different type though. + * Compares two bytes fields. The parameters must be either a byte array or a ByteString object. + * They can be of different type though. */ private static boolean compareBytes(Object a, Object b) { if (a instanceof byte[] && b instanceof byte[]) { - return Arrays.equals((byte[])a, (byte[])b); + return Arrays.equals((byte[]) a, (byte[]) b); } return toByteString(a).equals(toByteString(b)); } - /** - * Converts a list of MapEntry messages into a Map used for equals() and - * hashCode(). - */ + /** Converts a list of MapEntry messages into a Map used for equals() and hashCode(). */ @SuppressWarnings({"rawtypes", "unchecked"}) private static Map convertMapEntryListToMap(List list) { if (list.isEmpty()) { return Collections.emptyMap(); } - Map result = new HashMap(); + Map result = new HashMap<>(); Iterator iterator = list.iterator(); Message entry = (Message) iterator.next(); Descriptors.Descriptor descriptor = entry.getDescriptorForType(); @@ -214,10 +215,7 @@ private static Map convertMapEntryListToMap(List list) { return result; } - /** - * Compares two map fields. The parameters must be a list of MapEntry - * messages. - */ + /** Compares two map fields. The parameters must be a list of MapEntry messages. */ @SuppressWarnings({"rawtypes", "unchecked"}) private static boolean compareMapField(Object a, Object b) { Map ma = convertMapEntryListToMap((List) a); @@ -226,16 +224,13 @@ private static boolean compareMapField(Object a, Object b) { } /** - * Compares two set of fields. - * This method is used to implement {@link AbstractMessage#equals(Object)} - * and {@link AbstractMutableMessage#equals(Object)}. It takes special care - * of bytes fields because immutable messages and mutable messages use - * different Java type to represent a bytes field and this method should be - * able to compare immutable messages, mutable messages and also an immutable - * message to a mutable message. + * Compares two set of fields. This method is used to implement {@link + * AbstractMessage#equals(Object)} and {@link AbstractMutableMessage#equals(Object)}. It takes + * special care of bytes fields because immutable messages and mutable messages use different Java + * type to represent a bytes field and this method should be able to compare immutable messages, + * mutable messages and also an immutable message to a mutable message. */ - static boolean compareFields(Map a, - Map b) { + static boolean compareFields(Map a, Map b) { if (a.size() != b.size()) { return false; } @@ -277,10 +272,7 @@ static boolean compareFields(Map a, return true; } - /** - * Calculates the hash code of a map field. {@code value} must be a list of - * MapEntry messages. - */ + /** Calculates the hash code of a map field. {@code value} must be a list of MapEntry messages. */ @SuppressWarnings("unchecked") private static int hashMapField(Object value) { return MapFieldLite.calculateHashCodeForMap(convertMapEntryListToMap((List) value)); @@ -295,7 +287,7 @@ protected static int hashFields(int hash, Map map) { hash = (37 * hash) + field.getNumber(); if (field.isMapField()) { hash = (53 * hash) + hashMapField(value); - } else if (field.getType() != FieldDescriptor.Type.ENUM){ + } else if (field.getType() != FieldDescriptor.Type.ENUM) { hash = (53 * hash) + value.hashCode(); } else if (field.isRepeated()) { List list = (List) value; @@ -308,8 +300,8 @@ protected static int hashFields(int hash, Map map) { } /** - * Package private helper method for AbstractParser to create - * UninitializedMessageException with missing field information. + * Package private helper method for AbstractParser to create UninitializedMessageException with + * missing field information. */ @Override UninitializedMessageException newUninitializedMessageException() { @@ -319,14 +311,12 @@ UninitializedMessageException newUninitializedMessageException() { // ================================================================= /** - * A partial implementation of the {@link Message.Builder} interface which - * implements as many methods of that interface as possible in terms of - * other methods. + * A partial implementation of the {@link Message.Builder} interface which implements as many + * methods of that interface as possible in terms of other methods. */ @SuppressWarnings("unchecked") - public static abstract class Builder> - extends AbstractMessageLite.Builder - implements Message.Builder { + public abstract static class Builder> + extends AbstractMessageLite.Builder implements Message.Builder { // The compiler produces an error if this is not declared explicitly. // Method isn't abstract to bypass Java 1.6 compiler issue: // http://bugs.java.com/view_bug.do?bug_id=6908259 @@ -344,8 +334,7 @@ public boolean hasOneof(OneofDescriptor oneof) { /** TODO(jieluo): Clear it when all subclasses have implemented this method. */ @Override public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) { - throw new UnsupportedOperationException( - "getOneofFieldDescriptor() is not implemented."); + throw new UnsupportedOperationException("getOneofFieldDescriptor() is not implemented."); } /** TODO(jieluo): Clear it when all subclasses have implemented this method. */ @@ -356,8 +345,7 @@ public BuilderType clearOneof(OneofDescriptor oneof) { @Override public BuilderType clear() { - for (final Map.Entry entry : - getAllFields().entrySet()) { + for (final Map.Entry entry : getAllFields().entrySet()) { clearField(entry.getKey()); } return (BuilderType) this; @@ -380,9 +368,13 @@ protected BuilderType internalMergeFrom(AbstractMessageLite other) { @Override public BuilderType mergeFrom(final Message other) { + return mergeFrom(other, other.getAllFields()); + } + + BuilderType mergeFrom(final Message other, Map allFields) { if (other.getDescriptorForType() != getDescriptorForType()) { throw new IllegalArgumentException( - "mergeFrom(Message) can only merge messages of the same type."); + "mergeFrom(Message) can only merge messages of the same type."); } // Note: We don't attempt to verify that other's fields have valid @@ -394,23 +386,24 @@ public BuilderType mergeFrom(final Message other) { // TODO(kenton): Provide a function somewhere called makeDeepCopy() // which allows people to make secure deep copies of messages. - for (final Map.Entry entry : - other.getAllFields().entrySet()) { + for (final Map.Entry entry : allFields.entrySet()) { final FieldDescriptor field = entry.getKey(); if (field.isRepeated()) { - for (final Object element : (List)entry.getValue()) { + for (final Object element : (List) entry.getValue()) { addRepeatedField(field, element); } } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - final Message existingValue = (Message)getField(field); + final Message existingValue = (Message) getField(field); if (existingValue == existingValue.getDefaultInstanceForType()) { setField(field, entry.getValue()); } else { - setField(field, - existingValue.newBuilderForType() - .mergeFrom(existingValue) - .mergeFrom((Message)entry.getValue()) - .build()); + setField( + field, + existingValue + .newBuilderForType() + .mergeFrom(existingValue) + .mergeFrom((Message) entry.getValue()) + .build()); } } else { setField(field, entry.getValue()); @@ -423,20 +416,15 @@ public BuilderType mergeFrom(final Message other) { } @Override - public BuilderType mergeFrom(final CodedInputStream input) - throws IOException { + public BuilderType mergeFrom(final CodedInputStream input) throws IOException { return mergeFrom(input, ExtensionRegistry.getEmptyRegistry()); } @Override public BuilderType mergeFrom( - final CodedInputStream input, - final ExtensionRegistryLite extensionRegistry) + final CodedInputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException { - boolean discardUnknown = - getDescriptorForType().getFile().getSyntax() == Syntax.PROTO3 - ? input.shouldDiscardUnknownFieldsProto3() - : input.shouldDiscardUnknownFields(); + boolean discardUnknown = input.shouldDiscardUnknownFields(); final UnknownFieldSet.Builder unknownFields = discardUnknown ? null : UnknownFieldSet.newBuilder(getUnknownFields()); while (true) { @@ -447,11 +435,8 @@ public BuilderType mergeFrom( MessageReflection.BuilderAdapter builderAdapter = new MessageReflection.BuilderAdapter(this); - if (!MessageReflection.mergeFieldFrom(input, unknownFields, - extensionRegistry, - getDescriptorForType(), - builderAdapter, - tag)) { + if (!MessageReflection.mergeFieldFrom( + input, unknownFields, extensionRegistry, getDescriptorForType(), builderAdapter, tag)) { // end group tag break; } @@ -465,9 +450,7 @@ public BuilderType mergeFrom( @Override public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) { setUnknownFields( - UnknownFieldSet.newBuilder(getUnknownFields()) - .mergeFrom(unknownFields) - .build()); + UnknownFieldSet.newBuilder(getUnknownFields()).mergeFrom(unknownFields).build()); return (BuilderType) this; } @@ -485,39 +468,33 @@ public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int @Override public String toString() { - return TextFormat.printToString(this); + return TextFormat.printer().printToString(this); } - /** - * Construct an UninitializedMessageException reporting missing fields in - * the given message. - */ - protected static UninitializedMessageException - newUninitializedMessageException(Message message) { - return new UninitializedMessageException( - MessageReflection.findMissingFields(message)); + /** Construct an UninitializedMessageException reporting missing fields in the given message. */ + protected static UninitializedMessageException newUninitializedMessageException( + Message message) { + return new UninitializedMessageException(MessageReflection.findMissingFields(message)); } /** - * Used to support nested builders and called to mark this builder as clean. - * Clean builders will propagate the {@link BuilderParent#markDirty()} event - * to their parent builders, while dirty builders will not, as their parents - * should be dirty already. + * Used to support nested builders and called to mark this builder as clean. Clean builders will + * propagate the {@link BuilderParent#markDirty()} event to their parent builders, while dirty + * builders will not, as their parents should be dirty already. * - * NOTE: Implementations that don't support nested builders don't need to - * override this method. + *

NOTE: Implementations that don't support nested builders don't need to override this + * method. */ void markClean() { throw new IllegalStateException("Should be overridden by subclasses."); } /** - * Used to support nested builders and called when this nested builder is - * no longer used by its parent builder and should release the reference - * to its parent builder. + * Used to support nested builders and called when this nested builder is no longer used by its + * parent builder and should release the reference to its parent builder. * - * NOTE: Implementations that don't support nested builders don't need to - * override this method. + *

NOTE: Implementations that don't support nested builders don't need to override this + * method. */ void dispose() { throw new IllegalStateException("Should be overridden by subclasses."); @@ -543,73 +520,63 @@ void dispose() { // bug. @Override - public BuilderType mergeFrom(final ByteString data) - throws InvalidProtocolBufferException { + public BuilderType mergeFrom(final ByteString data) throws InvalidProtocolBufferException { return (BuilderType) super.mergeFrom(data); } @Override public BuilderType mergeFrom( - final ByteString data, - final ExtensionRegistryLite extensionRegistry) + final ByteString data, final ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return (BuilderType) super.mergeFrom(data, extensionRegistry); } @Override - public BuilderType mergeFrom(final byte[] data) - throws InvalidProtocolBufferException { + public BuilderType mergeFrom(final byte[] data) throws InvalidProtocolBufferException { return (BuilderType) super.mergeFrom(data); } @Override - public BuilderType mergeFrom( - final byte[] data, final int off, final int len) + public BuilderType mergeFrom(final byte[] data, final int off, final int len) throws InvalidProtocolBufferException { return (BuilderType) super.mergeFrom(data, off, len); } @Override - public BuilderType mergeFrom( - final byte[] data, - final ExtensionRegistryLite extensionRegistry) + public BuilderType mergeFrom(final byte[] data, final ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return (BuilderType) super.mergeFrom(data, extensionRegistry); } @Override public BuilderType mergeFrom( - final byte[] data, final int off, final int len, + final byte[] data, + final int off, + final int len, final ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return (BuilderType) super.mergeFrom(data, off, len, extensionRegistry); } @Override - public BuilderType mergeFrom(final InputStream input) - throws IOException { + public BuilderType mergeFrom(final InputStream input) throws IOException { return (BuilderType) super.mergeFrom(input); } @Override public BuilderType mergeFrom( - final InputStream input, - final ExtensionRegistryLite extensionRegistry) - throws IOException { + final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException { return (BuilderType) super.mergeFrom(input, extensionRegistry); } @Override - public boolean mergeDelimitedFrom(final InputStream input) - throws IOException { + public boolean mergeDelimitedFrom(final InputStream input) throws IOException { return super.mergeDelimitedFrom(input); } @Override public boolean mergeDelimitedFrom( - final InputStream input, - final ExtensionRegistryLite extensionRegistry) - throws IOException { + final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException { return super.mergeDelimitedFrom(input, extensionRegistry); } } diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java index 24830c0a32257..4e3cf427184a1 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java +++ b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java @@ -41,22 +41,21 @@ import java.util.List; /** - * A partial implementation of the {@link MessageLite} interface which - * implements as many methods of that interface as possible in terms of other - * methods. + * A partial implementation of the {@link MessageLite} interface which implements as many methods of + * that interface as possible in terms of other methods. * * @author kenton@google.com Kenton Varda */ public abstract class AbstractMessageLite< - MessageType extends AbstractMessageLite, - BuilderType extends AbstractMessageLite.Builder> - implements MessageLite { + MessageType extends AbstractMessageLite, + BuilderType extends AbstractMessageLite.Builder> + implements MessageLite { protected int memoizedHashCode = 0; + @Override public ByteString toByteString() { try { - final ByteString.CodedBuilder out = - ByteString.newCodedBuilder(getSerializedSize()); + final ByteString.CodedBuilder out = ByteString.newCodedBuilder(getSerializedSize()); writeTo(out.getCodedOutput()); return out.build(); } catch (IOException e) { @@ -79,10 +78,8 @@ public byte[] toByteArray() { @Override public void writeTo(final OutputStream output) throws IOException { - final int bufferSize = - CodedOutputStream.computePreferredBufferSize(getSerializedSize()); - final CodedOutputStream codedOutput = - CodedOutputStream.newInstance(output, bufferSize); + final int bufferSize = CodedOutputStream.computePreferredBufferSize(getSerializedSize()); + final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output, bufferSize); writeTo(codedOutput); codedOutput.flush(); } @@ -90,26 +87,45 @@ public void writeTo(final OutputStream output) throws IOException { @Override public void writeDelimitedTo(final OutputStream output) throws IOException { final int serialized = getSerializedSize(); - final int bufferSize = CodedOutputStream.computePreferredBufferSize( - CodedOutputStream.computeRawVarint32Size(serialized) + serialized); - final CodedOutputStream codedOutput = - CodedOutputStream.newInstance(output, bufferSize); + final int bufferSize = + CodedOutputStream.computePreferredBufferSize( + CodedOutputStream.computeRawVarint32Size(serialized) + serialized); + final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output, bufferSize); codedOutput.writeRawVarint32(serialized); writeTo(codedOutput); codedOutput.flush(); } + // We'd like these to be abstract but some folks are extending this class directly. They shouldn't + // be doing that and they should feel bad. + int getMemoizedSerializedSize() { + throw new UnsupportedOperationException(); + } - /** - * Package private helper method for AbstractParser to create - * UninitializedMessageException. - */ + void setMemoizedSerializedSize(int size) { + throw new UnsupportedOperationException(); + } + + + int getSerializedSize(Schema schema) { + int memoizedSerializedSize = getMemoizedSerializedSize(); + if (memoizedSerializedSize == -1) { + memoizedSerializedSize = schema.getSerializedSize(this); + setMemoizedSerializedSize(memoizedSerializedSize); + } + return memoizedSerializedSize; + } + + /** Package private helper method for AbstractParser to create UninitializedMessageException. */ UninitializedMessageException newUninitializedMessageException() { return new UninitializedMessageException(this); } private String getSerializingExceptionMessage(String target) { - return "Serializing " + getClass().getName() + " to a " + target + return "Serializing " + + getClass().getName() + + " to a " + + target + " threw an IOException (should never happen)."; } @@ -130,15 +146,23 @@ protected static void addAll(final Iterable values, final List Builder.addAll(values, list); } + /** Interface for an enum which signifies which field in a {@code oneof} was specified. */ + protected interface InternalOneOfEnum { + /** + * Retrieves the field number of the field which was set in this {@code oneof}, or {@code 0} if + * none were. + */ + int getNumber(); + } + /** - * A partial implementation of the {@link Message.Builder} interface which - * implements as many methods of that interface as possible in terms of - * other methods. + * A partial implementation of the {@link Message.Builder} interface which implements as many + * methods of that interface as possible in terms of other methods. */ @SuppressWarnings("unchecked") public abstract static class Builder< - MessageType extends AbstractMessageLite, - BuilderType extends Builder> + MessageType extends AbstractMessageLite, + BuilderType extends Builder> implements MessageLite.Builder { // The compiler produces an error if this is not declared explicitly. @Override @@ -194,8 +218,7 @@ public BuilderType mergeFrom(final byte[] data) throws InvalidProtocolBufferExce public BuilderType mergeFrom(final byte[] data, final int off, final int len) throws InvalidProtocolBufferException { try { - final CodedInputStream input = - CodedInputStream.newInstance(data, off, len); + final CodedInputStream input = CodedInputStream.newInstance(data, off, len); mergeFrom(input); input.checkLastTagWas(0); return (BuilderType) this; @@ -220,8 +243,7 @@ public BuilderType mergeFrom( final ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { try { - final CodedInputStream input = - CodedInputStream.newInstance(data, off, len); + final CodedInputStream input = CodedInputStream.newInstance(data, off, len); mergeFrom(input, extensionRegistry); input.checkLastTagWas(0); return (BuilderType) this; @@ -250,10 +272,9 @@ public BuilderType mergeFrom( } /** - * An InputStream implementations which reads from some other InputStream - * but is limited to a particular number of bytes. Used by - * mergeDelimitedFrom(). This is intentionally package-private so that - * UnknownFieldSet can share it. + * An InputStream implementations which reads from some other InputStream but is limited to a + * particular number of bytes. Used by mergeDelimitedFrom(). This is intentionally + * package-private so that UnknownFieldSet can share it. */ static final class LimitedInputStream extends FilterInputStream { private int limit; @@ -281,8 +302,7 @@ public int read() throws IOException { } @Override - public int read(final byte[] b, final int off, int len) - throws IOException { + public int read(final byte[] b, final int off, int len) throws IOException { if (limit <= 0) { return -1; } @@ -319,8 +339,7 @@ public boolean mergeDelimitedFrom( @Override public boolean mergeDelimitedFrom(final InputStream input) throws IOException { - return mergeDelimitedFrom(input, - ExtensionRegistryLite.getEmptyRegistry()); + return mergeDelimitedFrom(input, ExtensionRegistryLite.getEmptyRegistry()); } @Override @@ -337,7 +356,10 @@ public BuilderType mergeFrom(final MessageLite other) { protected abstract BuilderType internalMergeFrom(MessageType message); private String getReadingExceptionMessage(String target) { - return "Reading " + getClass().getName() + " from a " + target + return "Reading " + + getClass().getName() + + " from a " + + target + " threw an IOException (should never happen)."; } @@ -360,12 +382,9 @@ private static void addAllCheckingNulls(Iterable values, List } } - /** - * Construct an UninitializedMessageException reporting missing fields in - * the given message. - */ - protected static UninitializedMessageException - newUninitializedMessageException(MessageLite message) { + /** Construct an UninitializedMessageException reporting missing fields in the given message. */ + protected static UninitializedMessageException newUninitializedMessageException( + MessageLite message) { return new UninitializedMessageException(message); } diff --git a/java/core/src/main/java/com/google/protobuf/AbstractParser.java b/java/core/src/main/java/com/google/protobuf/AbstractParser.java index ba570e3df1684..abfaca8cd8b1f 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractParser.java +++ b/java/core/src/main/java/com/google/protobuf/AbstractParser.java @@ -36,23 +36,19 @@ import java.nio.ByteBuffer; /** - * A partial implementation of the {@link Parser} interface which implements - * as many methods of that interface as possible in terms of other methods. + * A partial implementation of the {@link Parser} interface which implements as many methods of that + * interface as possible in terms of other methods. * - * Note: This class implements all the convenience methods in the - * {@link Parser} interface. See {@link Parser} for related javadocs. - * Subclasses need to implement - * {@link Parser#parsePartialFrom(CodedInputStream, ExtensionRegistryLite)} + *

Note: This class implements all the convenience methods in the {@link Parser} interface. See + * {@link Parser} for related javadocs. Subclasses need to implement {@link + * Parser#parsePartialFrom(CodedInputStream, ExtensionRegistryLite)} * * @author liujisi@google.com (Pherl Liu) */ public abstract class AbstractParser implements Parser { - /** - * Creates an UninitializedMessageException for MessageType. - */ - private UninitializedMessageException - newUninitializedMessageException(MessageType message) { + /** Creates an UninitializedMessageException for MessageType. */ + private UninitializedMessageException newUninitializedMessageException(MessageType message) { if (message instanceof AbstractMessageLite) { return ((AbstractMessageLite) message).newUninitializedMessageException(); } @@ -75,8 +71,8 @@ private MessageType checkMessageInitialized(MessageType message) return message; } - private static final ExtensionRegistryLite EMPTY_REGISTRY - = ExtensionRegistryLite.getEmptyRegistry(); + private static final ExtensionRegistryLite EMPTY_REGISTRY = + ExtensionRegistryLite.getEmptyRegistry(); @Override public MessageType parsePartialFrom(CodedInputStream input) @@ -87,8 +83,7 @@ public MessageType parsePartialFrom(CodedInputStream input) @Override public MessageType parseFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { - return checkMessageInitialized( - parsePartialFrom(input, extensionRegistry)); + return checkMessageInitialized(parsePartialFrom(input, extensionRegistry)); } @Override @@ -193,8 +188,7 @@ public MessageType parsePartialFrom(byte[] data) throws InvalidProtocolBufferExc public MessageType parseFrom( byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { - return checkMessageInitialized( - parsePartialFrom(data, off, len, extensionRegistry)); + return checkMessageInitialized(parsePartialFrom(data, off, len, extensionRegistry)); } @Override @@ -235,8 +229,7 @@ public MessageType parsePartialFrom(InputStream input) throws InvalidProtocolBuf @Override public MessageType parseFrom(InputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { - return checkMessageInitialized( - parsePartialFrom(input, extensionRegistry)); + return checkMessageInitialized(parsePartialFrom(input, extensionRegistry)); } @Override @@ -271,8 +264,7 @@ public MessageType parsePartialDelimitedFrom(InputStream input) @Override public MessageType parseDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { - return checkMessageInitialized( - parsePartialDelimitedFrom(input, extensionRegistry)); + return checkMessageInitialized(parsePartialDelimitedFrom(input, extensionRegistry)); } @Override diff --git a/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java b/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java index b17db6e0b3147..e792d7d981198 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java +++ b/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java @@ -31,7 +31,6 @@ package com.google.protobuf; import com.google.protobuf.Internal.ProtobufList; - import java.util.AbstractList; import java.util.Collection; import java.util.List; @@ -39,23 +38,19 @@ /** * An abstract implementation of {@link ProtobufList} which manages mutability semantics. All mutate - * methods must check if the list is mutable before proceeding. Subclasses must invoke - * {@link #ensureIsMutable()} manually when overriding those methods. - *

- * This implementation assumes all subclasses are array based, supporting random access. + * methods must check if the list is mutable before proceeding. Subclasses must invoke {@link + * #ensureIsMutable()} manually when overriding those methods. + * + *

This implementation assumes all subclasses are array based, supporting random access. */ abstract class AbstractProtobufList extends AbstractList implements ProtobufList { protected static final int DEFAULT_CAPACITY = 10; - /** - * Whether or not this list is modifiable. - */ + /** Whether or not this list is modifiable. */ private boolean isMutable; - /** - * Constructs a mutable list by default. - */ + /** Constructs a mutable list by default. */ AbstractProtobufList() { isMutable = true; } @@ -115,7 +110,7 @@ public boolean addAll(Collection c) { ensureIsMutable(); return super.addAll(c); } - + @Override public boolean addAll(int index, Collection c) { ensureIsMutable(); @@ -127,47 +122,52 @@ public void clear() { ensureIsMutable(); super.clear(); } - + @Override public boolean isModifiable() { return isMutable; } - + @Override public final void makeImmutable() { isMutable = false; } - + @Override public E remove(int index) { ensureIsMutable(); return super.remove(index); } - + @Override public boolean remove(Object o) { ensureIsMutable(); - return super.remove(o); + int index = indexOf(o); + if (index == -1) { + return false; + } + remove(index); + return true; } - + @Override public boolean removeAll(Collection c) { ensureIsMutable(); return super.removeAll(c); } - + @Override public boolean retainAll(Collection c) { ensureIsMutable(); return super.retainAll(c); } - + @Override public E set(int index, E element) { ensureIsMutable(); return super.set(index, element); } - + /** * Throws an {@link UnsupportedOperationException} if the list is immutable. Subclasses are * responsible for invoking this method on mutate operations. diff --git a/java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java b/java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java new file mode 100644 index 0000000000000..a01a6c1a8b75f --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java @@ -0,0 +1,263 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.Internal.checkNotNull; + +import java.nio.ByteBuffer; + +/** + * A buffer that was allocated by a {@link BufferAllocator}. For every buffer, it is guaranteed that + * at least one of {@link #hasArray()} or {@link #hasNioBuffer()} will be {@code true}. + */ +@ExperimentalApi +abstract class AllocatedBuffer { + /** + * Indicates whether this buffer contains a backing {@link ByteBuffer} (i.e. it is safe to call + * {@link #nioBuffer()}). + */ + public abstract boolean hasNioBuffer(); + + /** + * Indicates whether this buffer contains a backing array (i.e. it is safe to call {@link + * #array()}). + */ + public abstract boolean hasArray(); + + /** + * Returns the {@link ByteBuffer} that backs this buffer (optional operation). + * + *

Call {@link #hasNioBuffer()} before invoking this method in order to ensure that this buffer + * has a backing {@link ByteBuffer}. + * + * @return The {@link ByteBuffer} that backs this buffer + * @throws UnsupportedOperationException If this buffer is not backed by a {@link ByteBuffer}. + */ + public abstract ByteBuffer nioBuffer(); + + /** + * Returns the byte array that backs this buffer (optional operation). + * + *

Call {@link #hasArray()} before invoking this method in order to ensure that this buffer has + * an accessible backing array. + * + * @return The array that backs this buffer + * @throws java.nio.ReadOnlyBufferException If this buffer is backed by an array but is read-only + * @throws UnsupportedOperationException If this buffer is not backed by an accessible array + */ + public abstract byte[] array(); + + /** + * Returns the offset within this buffer's backing array of the first element of the buffer + * (optional operation). + * + *

If this buffer is backed by an array then {@link #position()} corresponds to the array index + * {@link #position()} {@code +} {@link #arrayOffset()}. + * + *

Invoke the {@link #hasArray hasArray} method before invoking this method in order to ensure + * that this buffer has an accessible backing array. + * + * @return The offset within this buffer's array of the first element of the buffer + * @throws java.nio.ReadOnlyBufferException If this buffer is backed by an array but is read-only + * @throws UnsupportedOperationException If this buffer is not backed by an accessible array + */ + public abstract int arrayOffset(); + + /** + * Returns this buffer's position. + * + * @return The position of this buffer + */ + public abstract int position(); + + /** + * Sets this buffer's position. + * + * @param position The new position value; must be non-negative and no larger than the current + * limit + * @return This buffer + * @throws IllegalArgumentException If the preconditions on {@code position} do not hold + */ + public abstract AllocatedBuffer position(int position); + + /** + * Returns this buffer's limit. + * + * @return The limit of this buffer + */ + public abstract int limit(); + + /** + * Returns the number of elements between the current {@link #position()} and the {@link #limit()} + * . + * + * @return The number of elements remaining in this buffer + */ + public abstract int remaining(); + + /** + * Creates a new {@link AllocatedBuffer} that is backed by the given array. The returned buffer + * will have {@link #hasArray} == {@code true}, {@link #arrayOffset()} == {@code 0}, {@link + * #position()} == {@code 0} and {@link #limit()} equal to the length of {@code bytes}. + */ + public static AllocatedBuffer wrap(byte[] bytes) { + return wrapNoCheck(bytes, 0, bytes.length); + } + + /** + * Creates a new {@link AllocatedBuffer} that is backed by the given array. The returned buffer + * will have {@link #hasArray} == {@code true}, {@link #arrayOffset()} == {@code offset}, {@link + * #position()} == {@code 0} and {@link #limit()} == {@code length}. + */ + public static AllocatedBuffer wrap(final byte[] bytes, final int offset, final int length) { + if (offset < 0 || length < 0 || (offset + length) > bytes.length) { + throw new IndexOutOfBoundsException( + String.format("bytes.length=%d, offset=%d, length=%d", bytes.length, offset, length)); + } + + return wrapNoCheck(bytes, offset, length); + } + + /** + * Creates a new {@link AllocatedBuffer} that is backed by the given {@link ByteBuffer}. The + * returned buffer will have {@link #hasNioBuffer} == {@code true}. + */ + public static AllocatedBuffer wrap(final ByteBuffer buffer) { + checkNotNull(buffer, "buffer"); + + return new AllocatedBuffer() { + + @Override + public boolean hasNioBuffer() { + return true; + } + + @Override + public ByteBuffer nioBuffer() { + return buffer; + } + + @Override + public boolean hasArray() { + return buffer.hasArray(); + } + + @Override + public byte[] array() { + return buffer.array(); + } + + @Override + public int arrayOffset() { + return buffer.arrayOffset(); + } + + @Override + public int position() { + return buffer.position(); + } + + @Override + public AllocatedBuffer position(int position) { + buffer.position(position); + return this; + } + + @Override + public int limit() { + return buffer.limit(); + } + + @Override + public int remaining() { + return buffer.remaining(); + } + }; + } + + private static AllocatedBuffer wrapNoCheck( + final byte[] bytes, final int offset, final int length) { + return new AllocatedBuffer() { + // Relative to offset. + private int position; + + @Override + public boolean hasNioBuffer() { + return false; + } + + @Override + public ByteBuffer nioBuffer() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasArray() { + return true; + } + + @Override + public byte[] array() { + return bytes; + } + + @Override + public int arrayOffset() { + return offset; + } + + @Override + public int position() { + return position; + } + + @Override + public AllocatedBuffer position(int position) { + if (position < 0 || position > length) { + throw new IllegalArgumentException("Invalid position: " + position); + } + this.position = position; + return this; + } + + @Override + public int limit() { + // Relative to offset. + return length; + } + + @Override + public int remaining() { + return length - position; + } + }; + } +} diff --git a/java/core/src/main/java/com/google/protobuf/Android.java b/java/core/src/main/java/com/google/protobuf/Android.java new file mode 100644 index 0000000000000..5a7ce9e581acc --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/Android.java @@ -0,0 +1,64 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +final class Android { + private Android() { + } + + // Set to true in lite_proguard_android.pgcfg. + @SuppressWarnings("ConstantField") + private static boolean ASSUME_ANDROID; + + private static final Class MEMORY_CLASS = getClassForName("libcore.io.Memory"); + + private static final boolean IS_ROBOLECTRIC = + !ASSUME_ANDROID && getClassForName("org.robolectric.Robolectric") != null; + + /** Returns {@code true} if running on an Android device. */ + static boolean isOnAndroidDevice() { + return ASSUME_ANDROID || (MEMORY_CLASS != null && !IS_ROBOLECTRIC); + } + + /** Returns the memory class or {@code null} if not on Android device. */ + static Class getMemoryClass() { + return MEMORY_CLASS; + } + + @SuppressWarnings("unchecked") + private static Class getClassForName(String name) { + try { + return (Class) Class.forName(name); + } catch (Throwable e) { + return null; + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java b/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java new file mode 100644 index 0000000000000..1217e112e0cef --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java @@ -0,0 +1,1076 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.MessageSchema.getMutableUnknownFields; + +import com.google.protobuf.Internal.ProtobufList; +import java.io.IOException; + +/** + * Helper functions to decode protobuf wire format from a byte array. + * + *

Note that these functions don't do boundary check on the byte array but instead rely on Java + * VM to check it. That means parsing routines utilizing these functions must catch + * IndexOutOfBoundsException and convert it to protobuf's InvalidProtocolBufferException when + * crossing protobuf public API boundaries. + */ +final class ArrayDecoders { + /** + * A helper used to return multiple values in a Java function. Java doesn't natively support + * returning multiple values in a function. Creating a new Object to hold the return values will + * be too expensive. Instead, we pass a Registers instance to functions that want to return + * multiple values and let the function set the return value in this Registers instance instead. + * + *

TODO(xiaofeng): This could be merged into CodedInputStream or CodedInputStreamReader which + * is already being passed through all the parsing routines. + */ + static final class Registers { + public int int1; + public long long1; + public Object object1; + public final ExtensionRegistryLite extensionRegistry; + + Registers() { + this.extensionRegistry = ExtensionRegistryLite.getEmptyRegistry(); + } + + Registers(ExtensionRegistryLite extensionRegistry) { + if (extensionRegistry == null) { + throw new NullPointerException(); + } + this.extensionRegistry = extensionRegistry; + } + } + + /** + * Decodes a varint. Returns the position after the varint. The decoded varint is stored in + * registers.int1. + */ + static int decodeVarint32(byte[] data, int position, Registers registers) { + int value = data[position++]; + if (value >= 0) { + registers.int1 = value; + return position; + } + return decodeVarint32(value, data, position, registers); + } + + /** Like decodeVarint32 except that the first byte is already read. */ + static int decodeVarint32(int firstByte, byte[] data, int position, Registers registers) { + int value = firstByte & 0x7F; + final byte b2 = data[position++]; + if (b2 >= 0) { + registers.int1 = value | ((int) b2 << 7); + return position; + } + value |= (b2 & 0x7F) << 7; + + final byte b3 = data[position++]; + if (b3 >= 0) { + registers.int1 = value | ((int) b3 << 14); + return position; + } + value |= (b3 & 0x7F) << 14; + + final byte b4 = data[position++]; + if (b4 >= 0) { + registers.int1 = value | ((int) b4 << 21); + return position; + } + value |= (b4 & 0x7F) << 21; + + final byte b5 = data[position++]; + if (b5 >= 0) { + registers.int1 = value | ((int) b5 << 28); + return position; + } + value |= (b5 & 0x7F) << 28; + + while (data[position++] < 0) {} + + registers.int1 = value; + return position; + } + + /** + * Decodes a varint. Returns the position after the varint. The decoded varint is stored in + * registers.long1. + */ + static int decodeVarint64(byte[] data, int position, Registers registers) { + long value = data[position++]; + if (value >= 0) { + registers.long1 = value; + return position; + } else { + return decodeVarint64(value, data, position, registers); + } + } + + /** Like decodeVarint64 except that the first byte is already read. */ + static int decodeVarint64(long firstByte, byte[] data, int position, Registers registers) { + long value = firstByte & 0x7F; + byte next = data[position++]; + int shift = 7; + value |= (long) (next & 0x7F) << 7; + while (next < 0) { + next = data[position++]; + shift += 7; + value |= (long) (next & 0x7F) << shift; + } + registers.long1 = value; + return position; + } + + /** Decodes and returns a fixed32 value. */ + static int decodeFixed32(byte[] data, int position) { + return (data[position] & 0xff) + | ((data[position + 1] & 0xff) << 8) + | ((data[position + 2] & 0xff) << 16) + | ((data[position + 3] & 0xff) << 24); + } + + /** Decodes and returns a fixed64 value. */ + static long decodeFixed64(byte[] data, int position) { + return (data[position] & 0xffL) + | ((data[position + 1] & 0xffL) << 8) + | ((data[position + 2] & 0xffL) << 16) + | ((data[position + 3] & 0xffL) << 24) + | ((data[position + 4] & 0xffL) << 32) + | ((data[position + 5] & 0xffL) << 40) + | ((data[position + 6] & 0xffL) << 48) + | ((data[position + 7] & 0xffL) << 56); + } + + /** Decodes and returns a double value. */ + static double decodeDouble(byte[] data, int position) { + return Double.longBitsToDouble(decodeFixed64(data, position)); + } + + /** Decodes and returns a float value. */ + static float decodeFloat(byte[] data, int position) { + return Float.intBitsToFloat(decodeFixed32(data, position)); + } + + /** Decodes a string value. */ + static int decodeString(byte[] data, int position, Registers registers) + throws InvalidProtocolBufferException { + position = decodeVarint32(data, position, registers); + final int length = registers.int1; + if (length < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } else if (length == 0) { + registers.object1 = ""; + return position; + } else { + registers.object1 = new String(data, position, length, Internal.UTF_8); + return position + length; + } + } + + /** Decodes a string value with utf8 check. */ + static int decodeStringRequireUtf8(byte[] data, int position, Registers registers) + throws InvalidProtocolBufferException { + position = decodeVarint32(data, position, registers); + final int length = registers.int1; + if (length < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } else if (length == 0) { + registers.object1 = ""; + return position; + } else { + registers.object1 = Utf8.decodeUtf8(data, position, length); + return position + length; + } + } + + /** Decodes a bytes value. */ + static int decodeBytes(byte[] data, int position, Registers registers) + throws InvalidProtocolBufferException { + position = decodeVarint32(data, position, registers); + final int length = registers.int1; + if (length < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } else if (length > data.length - position) { + throw InvalidProtocolBufferException.truncatedMessage(); + } else if (length == 0) { + registers.object1 = ByteString.EMPTY; + return position; + } else { + registers.object1 = ByteString.copyFrom(data, position, length); + return position + length; + } + } + + /** Decodes a message value. */ + @SuppressWarnings({"unchecked", "rawtypes"}) + static int decodeMessageField( + Schema schema, byte[] data, int position, int limit, Registers registers) throws IOException { + int length = data[position++]; + if (length < 0) { + position = decodeVarint32(length, data, position, registers); + length = registers.int1; + } + if (length < 0 || length > limit - position) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + Object result = schema.newInstance(); + schema.mergeFrom(result, data, position, position + length, registers); + schema.makeImmutable(result); + registers.object1 = result; + return position + length; + } + + /** Decodes a group value. */ + @SuppressWarnings({"unchecked", "rawtypes"}) + static int decodeGroupField( + Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers) + throws IOException { + // A group field must has a MessageSchema (the only other subclass of Schema is MessageSetSchema + // and it can't be used in group fields). + final MessageSchema messageSchema = (MessageSchema) schema; + Object result = messageSchema.newInstance(); + // It's OK to directly use parseProto2Message since proto3 doesn't have group. + final int endPosition = + messageSchema.parseProto2Message(result, data, position, limit, endGroup, registers); + messageSchema.makeImmutable(result); + registers.object1 = result; + return endPosition; + } + + /** Decodes a repeated 32-bit varint field. Returns the position after all read values. */ + static int decodeVarint32List( + int tag, byte[] data, int position, int limit, ProtobufList list, Registers registers) { + final IntArrayList output = (IntArrayList) list; + position = decodeVarint32(data, position, registers); + output.addInt(registers.int1); + while (position < limit) { + int nextPosition = decodeVarint32(data, position, registers); + if (tag != registers.int1) { + break; + } + position = decodeVarint32(data, nextPosition, registers); + output.addInt(registers.int1); + } + return position; + } + + /** Decodes a repeated 64-bit varint field. Returns the position after all read values. */ + static int decodeVarint64List( + int tag, byte[] data, int position, int limit, ProtobufList list, Registers registers) { + final LongArrayList output = (LongArrayList) list; + position = decodeVarint64(data, position, registers); + output.addLong(registers.long1); + while (position < limit) { + int nextPosition = decodeVarint32(data, position, registers); + if (tag != registers.int1) { + break; + } + position = decodeVarint64(data, nextPosition, registers); + output.addLong(registers.long1); + } + return position; + } + + /** Decodes a repeated fixed32 field. Returns the position after all read values. */ + static int decodeFixed32List( + int tag, byte[] data, int position, int limit, ProtobufList list, Registers registers) { + final IntArrayList output = (IntArrayList) list; + output.addInt(decodeFixed32(data, position)); + position += 4; + while (position < limit) { + int nextPosition = decodeVarint32(data, position, registers); + if (tag != registers.int1) { + break; + } + output.addInt(decodeFixed32(data, nextPosition)); + position = nextPosition + 4; + } + return position; + } + + /** Decodes a repeated fixed64 field. Returns the position after all read values. */ + static int decodeFixed64List( + int tag, byte[] data, int position, int limit, ProtobufList list, Registers registers) { + final LongArrayList output = (LongArrayList) list; + output.addLong(decodeFixed64(data, position)); + position += 8; + while (position < limit) { + int nextPosition = decodeVarint32(data, position, registers); + if (tag != registers.int1) { + break; + } + output.addLong(decodeFixed64(data, nextPosition)); + position = nextPosition + 8; + } + return position; + } + + /** Decodes a repeated float field. Returns the position after all read values. */ + static int decodeFloatList( + int tag, byte[] data, int position, int limit, ProtobufList list, Registers registers) { + final FloatArrayList output = (FloatArrayList) list; + output.addFloat(decodeFloat(data, position)); + position += 4; + while (position < limit) { + int nextPosition = decodeVarint32(data, position, registers); + if (tag != registers.int1) { + break; + } + output.addFloat(decodeFloat(data, nextPosition)); + position = nextPosition + 4; + } + return position; + } + + /** Decodes a repeated double field. Returns the position after all read values. */ + static int decodeDoubleList( + int tag, byte[] data, int position, int limit, ProtobufList list, Registers registers) { + final DoubleArrayList output = (DoubleArrayList) list; + output.addDouble(decodeDouble(data, position)); + position += 8; + while (position < limit) { + int nextPosition = decodeVarint32(data, position, registers); + if (tag != registers.int1) { + break; + } + output.addDouble(decodeDouble(data, nextPosition)); + position = nextPosition + 8; + } + return position; + } + + /** Decodes a repeated boolean field. Returns the position after all read values. */ + static int decodeBoolList( + int tag, byte[] data, int position, int limit, ProtobufList list, Registers registers) { + final BooleanArrayList output = (BooleanArrayList) list; + position = decodeVarint64(data, position, registers); + output.addBoolean(registers.long1 != 0); + while (position < limit) { + int nextPosition = decodeVarint32(data, position, registers); + if (tag != registers.int1) { + break; + } + position = decodeVarint64(data, nextPosition, registers); + output.addBoolean(registers.long1 != 0); + } + return position; + } + + /** Decodes a repeated sint32 field. Returns the position after all read values. */ + static int decodeSInt32List( + int tag, byte[] data, int position, int limit, ProtobufList list, Registers registers) { + final IntArrayList output = (IntArrayList) list; + position = decodeVarint32(data, position, registers); + output.addInt(CodedInputStream.decodeZigZag32(registers.int1)); + while (position < limit) { + int nextPosition = decodeVarint32(data, position, registers); + if (tag != registers.int1) { + break; + } + position = decodeVarint32(data, nextPosition, registers); + output.addInt(CodedInputStream.decodeZigZag32(registers.int1)); + } + return position; + } + + /** Decodes a repeated sint64 field. Returns the position after all read values. */ + static int decodeSInt64List( + int tag, byte[] data, int position, int limit, ProtobufList list, Registers registers) { + final LongArrayList output = (LongArrayList) list; + position = decodeVarint64(data, position, registers); + output.addLong(CodedInputStream.decodeZigZag64(registers.long1)); + while (position < limit) { + int nextPosition = decodeVarint32(data, position, registers); + if (tag != registers.int1) { + break; + } + position = decodeVarint64(data, nextPosition, registers); + output.addLong(CodedInputStream.decodeZigZag64(registers.long1)); + } + return position; + } + + /** Decodes a packed 32-bit varint field. Returns the position after all read values. */ + static int decodePackedVarint32List( + byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + final IntArrayList output = (IntArrayList) list; + position = decodeVarint32(data, position, registers); + final int fieldLimit = position + registers.int1; + while (position < fieldLimit) { + position = decodeVarint32(data, position, registers); + output.addInt(registers.int1); + } + if (position != fieldLimit) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + return position; + } + + /** Decodes a packed 64-bit varint field. Returns the position after all read values. */ + static int decodePackedVarint64List( + byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + final LongArrayList output = (LongArrayList) list; + position = decodeVarint32(data, position, registers); + final int fieldLimit = position + registers.int1; + while (position < fieldLimit) { + position = decodeVarint64(data, position, registers); + output.addLong(registers.long1); + } + if (position != fieldLimit) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + return position; + } + + /** Decodes a packed fixed32 field. Returns the position after all read values. */ + static int decodePackedFixed32List( + byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + final IntArrayList output = (IntArrayList) list; + position = decodeVarint32(data, position, registers); + final int fieldLimit = position + registers.int1; + while (position < fieldLimit) { + output.addInt(decodeFixed32(data, position)); + position += 4; + } + if (position != fieldLimit) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + return position; + } + + /** Decodes a packed fixed64 field. Returns the position after all read values. */ + static int decodePackedFixed64List( + byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + final LongArrayList output = (LongArrayList) list; + position = decodeVarint32(data, position, registers); + final int fieldLimit = position + registers.int1; + while (position < fieldLimit) { + output.addLong(decodeFixed64(data, position)); + position += 8; + } + if (position != fieldLimit) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + return position; + } + + /** Decodes a packed float field. Returns the position after all read values. */ + static int decodePackedFloatList( + byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + final FloatArrayList output = (FloatArrayList) list; + position = decodeVarint32(data, position, registers); + final int fieldLimit = position + registers.int1; + while (position < fieldLimit) { + output.addFloat(decodeFloat(data, position)); + position += 4; + } + if (position != fieldLimit) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + return position; + } + + /** Decodes a packed double field. Returns the position after all read values. */ + static int decodePackedDoubleList( + byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + final DoubleArrayList output = (DoubleArrayList) list; + position = decodeVarint32(data, position, registers); + final int fieldLimit = position + registers.int1; + while (position < fieldLimit) { + output.addDouble(decodeDouble(data, position)); + position += 8; + } + if (position != fieldLimit) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + return position; + } + + /** Decodes a packed boolean field. Returns the position after all read values. */ + static int decodePackedBoolList( + byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + final BooleanArrayList output = (BooleanArrayList) list; + position = decodeVarint32(data, position, registers); + final int fieldLimit = position + registers.int1; + while (position < fieldLimit) { + position = decodeVarint64(data, position, registers); + output.addBoolean(registers.long1 != 0); + } + if (position != fieldLimit) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + return position; + } + + /** Decodes a packed sint32 field. Returns the position after all read values. */ + static int decodePackedSInt32List( + byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + final IntArrayList output = (IntArrayList) list; + position = decodeVarint32(data, position, registers); + final int fieldLimit = position + registers.int1; + while (position < fieldLimit) { + position = decodeVarint32(data, position, registers); + output.addInt(CodedInputStream.decodeZigZag32(registers.int1)); + } + if (position != fieldLimit) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + return position; + } + + /** Decodes a packed sint64 field. Returns the position after all read values. */ + @SuppressWarnings("unchecked") + static int decodePackedSInt64List( + byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + final LongArrayList output = (LongArrayList) list; + position = decodeVarint32(data, position, registers); + final int fieldLimit = position + registers.int1; + while (position < fieldLimit) { + position = decodeVarint64(data, position, registers); + output.addLong(CodedInputStream.decodeZigZag64(registers.long1)); + } + if (position != fieldLimit) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + return position; + } + + /** Decodes a repeated string field. Returns the position after all read values. */ + @SuppressWarnings("unchecked") + static int decodeStringList( + int tag, byte[] data, int position, int limit, ProtobufList list, Registers registers) + throws InvalidProtocolBufferException { + final ProtobufList output = (ProtobufList) list; + position = decodeVarint32(data, position, registers); + final int length = registers.int1; + if (length < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } else if (length == 0) { + output.add(""); + } else { + String value = new String(data, position, length, Internal.UTF_8); + output.add(value); + position += length; + } + while (position < limit) { + int nextPosition = decodeVarint32(data, position, registers); + if (tag != registers.int1) { + break; + } + position = decodeVarint32(data, nextPosition, registers); + final int nextLength = registers.int1; + if (nextLength < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } else if (nextLength == 0) { + output.add(""); + } else { + String value = new String(data, position, nextLength, Internal.UTF_8); + output.add(value); + position += nextLength; + } + } + return position; + } + + /** + * Decodes a repeated string field with utf8 check. Returns the position after all read values. + */ + @SuppressWarnings("unchecked") + static int decodeStringListRequireUtf8( + int tag, byte[] data, int position, int limit, ProtobufList list, Registers registers) + throws InvalidProtocolBufferException { + final ProtobufList output = (ProtobufList) list; + position = decodeVarint32(data, position, registers); + final int length = registers.int1; + if (length < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } else if (length == 0) { + output.add(""); + } else { + if (!Utf8.isValidUtf8(data, position, position + length)) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + String value = new String(data, position, length, Internal.UTF_8); + output.add(value); + position += length; + } + while (position < limit) { + int nextPosition = decodeVarint32(data, position, registers); + if (tag != registers.int1) { + break; + } + position = decodeVarint32(data, nextPosition, registers); + final int nextLength = registers.int1; + if (nextLength < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } else if (nextLength == 0) { + output.add(""); + } else { + if (!Utf8.isValidUtf8(data, position, position + nextLength)) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + String value = new String(data, position, nextLength, Internal.UTF_8); + output.add(value); + position += nextLength; + } + } + return position; + } + + /** Decodes a repeated bytes field. Returns the position after all read values. */ + @SuppressWarnings("unchecked") + static int decodeBytesList( + int tag, byte[] data, int position, int limit, ProtobufList list, Registers registers) + throws InvalidProtocolBufferException { + final ProtobufList output = (ProtobufList) list; + position = decodeVarint32(data, position, registers); + final int length = registers.int1; + if (length < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } else if (length > data.length - position) { + throw InvalidProtocolBufferException.truncatedMessage(); + } else if (length == 0) { + output.add(ByteString.EMPTY); + } else { + output.add(ByteString.copyFrom(data, position, length)); + position += length; + } + while (position < limit) { + int nextPosition = decodeVarint32(data, position, registers); + if (tag != registers.int1) { + break; + } + position = decodeVarint32(data, nextPosition, registers); + final int nextLength = registers.int1; + if (nextLength < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } else if (nextLength > data.length - position) { + throw InvalidProtocolBufferException.truncatedMessage(); + } else if (nextLength == 0) { + output.add(ByteString.EMPTY); + } else { + output.add(ByteString.copyFrom(data, position, nextLength)); + position += nextLength; + } + } + return position; + } + + /** + * Decodes a repeated message field + * + * @return The position of after read all messages + */ + @SuppressWarnings({"unchecked"}) + static int decodeMessageList( + Schema schema, + int tag, + byte[] data, + int position, + int limit, + ProtobufList list, + Registers registers) + throws IOException { + final ProtobufList output = (ProtobufList) list; + position = decodeMessageField(schema, data, position, limit, registers); + output.add(registers.object1); + while (position < limit) { + int nextPosition = decodeVarint32(data, position, registers); + if (tag != registers.int1) { + break; + } + position = decodeMessageField(schema, data, nextPosition, limit, registers); + output.add(registers.object1); + } + return position; + } + + /** + * Decodes a repeated group field + * + * @return The position of after read all groups + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + static int decodeGroupList( + Schema schema, + int tag, + byte[] data, + int position, + int limit, + ProtobufList list, + Registers registers) + throws IOException { + final ProtobufList output = (ProtobufList) list; + final int endgroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP; + position = decodeGroupField(schema, data, position, limit, endgroup, registers); + output.add(registers.object1); + while (position < limit) { + int nextPosition = decodeVarint32(data, position, registers); + if (tag != registers.int1) { + break; + } + position = decodeGroupField(schema, data, nextPosition, limit, endgroup, registers); + output.add(registers.object1); + } + return position; + } + + static int decodeExtensionOrUnknownField( + int tag, byte[] data, int position, int limit, + Object message, + MessageLite defaultInstance, + UnknownFieldSchema unknownFieldSchema, + Registers registers) + throws IOException { + final int number = tag >>> 3; + GeneratedMessageLite.GeneratedExtension extension = + registers.extensionRegistry.findLiteExtensionByNumber(defaultInstance, number); + if (extension == null) { + return decodeUnknownField( + tag, data, position, limit, getMutableUnknownFields(message), registers); + } else { + ((GeneratedMessageLite.ExtendableMessage) message).ensureExtensionsAreMutable(); + return decodeExtension( + tag, data, position, limit, (GeneratedMessageLite.ExtendableMessage) message, + extension, unknownFieldSchema, registers); + } + } + + static int decodeExtension( + int tag, + byte[] data, + int position, + int limit, + GeneratedMessageLite.ExtendableMessage message, + GeneratedMessageLite.GeneratedExtension extension, + UnknownFieldSchema unknownFieldSchema, + Registers registers) + throws IOException { + final FieldSet extensions = message.extensions; + final int fieldNumber = tag >>> 3; + if (extension.descriptor.isRepeated() && extension.descriptor.isPacked()) { + switch (extension.getLiteType()) { + case DOUBLE: + { + DoubleArrayList list = new DoubleArrayList(); + position = decodePackedDoubleList(data, position, list, registers); + extensions.setField(extension.descriptor, list); + break; + } + case FLOAT: + { + FloatArrayList list = new FloatArrayList(); + position = decodePackedFloatList(data, position, list, registers); + extensions.setField(extension.descriptor, list); + break; + } + case INT64: + case UINT64: + { + LongArrayList list = new LongArrayList(); + position = decodePackedVarint64List(data, position, list, registers); + extensions.setField(extension.descriptor, list); + break; + } + case INT32: + case UINT32: + { + IntArrayList list = new IntArrayList(); + position = decodePackedVarint32List(data, position, list, registers); + extensions.setField(extension.descriptor, list); + break; + } + case FIXED64: + case SFIXED64: + { + LongArrayList list = new LongArrayList(); + position = decodePackedFixed64List(data, position, list, registers); + extensions.setField(extension.descriptor, list); + break; + } + case FIXED32: + case SFIXED32: + { + IntArrayList list = new IntArrayList(); + position = decodePackedFixed32List(data, position, list, registers); + extensions.setField(extension.descriptor, list); + break; + } + case BOOL: + { + BooleanArrayList list = new BooleanArrayList(); + position = decodePackedBoolList(data, position, list, registers); + extensions.setField(extension.descriptor, list); + break; + } + case SINT32: + { + IntArrayList list = new IntArrayList(); + position = decodePackedSInt32List(data, position, list, registers); + extensions.setField(extension.descriptor, list); + break; + } + case SINT64: + { + LongArrayList list = new LongArrayList(); + position = decodePackedSInt64List(data, position, list, registers); + extensions.setField(extension.descriptor, list); + break; + } + case ENUM: + { + IntArrayList list = new IntArrayList(); + position = decodePackedVarint32List(data, position, list, registers); + UnknownFieldSetLite unknownFields = message.unknownFields; + if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) { + unknownFields = null; + } + unknownFields = + SchemaUtil.filterUnknownEnumList( + fieldNumber, + list, + extension.descriptor.getEnumType(), + unknownFields, + unknownFieldSchema); + if (unknownFields != null) { + message.unknownFields = unknownFields; + } + extensions.setField(extension.descriptor, list); + break; + } + default: + throw new IllegalStateException( + "Type cannot be packed: " + extension.descriptor.getLiteType()); + } + } else { + Object value = null; + // Enum is a special case because unknown enum values will be put into UnknownFieldSetLite. + if (extension.getLiteType() == WireFormat.FieldType.ENUM) { + position = decodeVarint32(data, position, registers); + Object enumValue = extension.descriptor.getEnumType().findValueByNumber(registers.int1); + if (enumValue == null) { + UnknownFieldSetLite unknownFields = ((GeneratedMessageLite) message).unknownFields; + if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) { + unknownFields = UnknownFieldSetLite.newInstance(); + ((GeneratedMessageLite) message).unknownFields = unknownFields; + } + SchemaUtil.storeUnknownEnum( + fieldNumber, registers.int1, unknownFields, unknownFieldSchema); + return position; + } + // Note, we store the integer value instead of the actual enum object in FieldSet. + // This is also different from full-runtime where we store EnumValueDescriptor. + value = registers.int1; + } else { + switch (extension.getLiteType()) { + case DOUBLE: + value = decodeDouble(data, position); + position += 8; + break; + case FLOAT: + value = decodeFloat(data, position); + position += 4; + break; + case INT64: + case UINT64: + position = decodeVarint64(data, position, registers); + value = registers.long1; + break; + case INT32: + case UINT32: + position = decodeVarint32(data, position, registers); + value = registers.int1; + break; + case FIXED64: + case SFIXED64: + value = decodeFixed64(data, position); + position += 8; + break; + case FIXED32: + case SFIXED32: + value = decodeFixed32(data, position); + position += 4; + break; + case BOOL: + position = decodeVarint64(data, position, registers); + value = (registers.long1 != 0); + break; + case BYTES: + position = decodeBytes(data, position, registers); + value = registers.object1; + break; + case SINT32: + position = decodeVarint32(data, position, registers); + value = CodedInputStream.decodeZigZag32(registers.int1); + break; + case SINT64: + position = decodeVarint64(data, position, registers); + value = CodedInputStream.decodeZigZag64(registers.long1); + break; + case STRING: + position = decodeString(data, position, registers); + value = registers.object1; + break; + case GROUP: + final int endTag = (fieldNumber << 3) | WireFormat.WIRETYPE_END_GROUP; + position = decodeGroupField( + Protobuf.getInstance().schemaFor(extension.getMessageDefaultInstance().getClass()), + data, position, limit, endTag, registers); + value = registers.object1; + break; + + case MESSAGE: + position = decodeMessageField( + Protobuf.getInstance().schemaFor(extension.getMessageDefaultInstance().getClass()), + data, position, limit, registers); + value = registers.object1; + break; + + case ENUM: + throw new IllegalStateException("Shouldn't reach here."); + } + } + if (extension.isRepeated()) { + extensions.addRepeatedField(extension.descriptor, value); + } else { + switch (extension.getLiteType()) { + case MESSAGE: + case GROUP: + Object oldValue = extensions.getField(extension.descriptor); + if (oldValue != null) { + value = Internal.mergeMessage(oldValue, value); + } + break; + default: + break; + } + extensions.setField(extension.descriptor, value); + } + } + return position; + } + + /** Decodes an unknown field. */ + static int decodeUnknownField( + int tag, + byte[] data, + int position, + int limit, + UnknownFieldSetLite unknownFields, + Registers registers) + throws InvalidProtocolBufferException { + if (WireFormat.getTagFieldNumber(tag) == 0) { + throw InvalidProtocolBufferException.invalidTag(); + } + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + position = decodeVarint64(data, position, registers); + unknownFields.storeField(tag, registers.long1); + return position; + case WireFormat.WIRETYPE_FIXED32: + unknownFields.storeField(tag, decodeFixed32(data, position)); + return position + 4; + case WireFormat.WIRETYPE_FIXED64: + unknownFields.storeField(tag, decodeFixed64(data, position)); + return position + 8; + case WireFormat.WIRETYPE_LENGTH_DELIMITED: + position = decodeVarint32(data, position, registers); + final int length = registers.int1; + if (length < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } else if (length > data.length - position) { + throw InvalidProtocolBufferException.truncatedMessage(); + } else if (length == 0) { + unknownFields.storeField(tag, ByteString.EMPTY); + } else { + unknownFields.storeField(tag, ByteString.copyFrom(data, position, length)); + } + return position + length; + case WireFormat.WIRETYPE_START_GROUP: + final UnknownFieldSetLite child = UnknownFieldSetLite.newInstance(); + final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP; + int lastTag = 0; + while (position < limit) { + position = decodeVarint32(data, position, registers); + lastTag = registers.int1; + if (lastTag == endGroup) { + break; + } + position = decodeUnknownField(lastTag, data, position, limit, child, registers); + } + if (position > limit || lastTag != endGroup) { + throw InvalidProtocolBufferException.parseFailure(); + } + unknownFields.storeField(tag, child); + return position; + default: + throw InvalidProtocolBufferException.invalidTag(); + } + } + + /** Skips an unknown field. */ + static int skipField(int tag, byte[] data, int position, int limit, Registers registers) + throws InvalidProtocolBufferException { + if (WireFormat.getTagFieldNumber(tag) == 0) { + throw InvalidProtocolBufferException.invalidTag(); + } + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + position = decodeVarint64(data, position, registers); + return position; + case WireFormat.WIRETYPE_FIXED32: + return position + 4; + case WireFormat.WIRETYPE_FIXED64: + return position + 8; + case WireFormat.WIRETYPE_LENGTH_DELIMITED: + position = decodeVarint32(data, position, registers); + return position + registers.int1; + case WireFormat.WIRETYPE_START_GROUP: + final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP; + int lastTag = 0; + while (position < limit) { + position = decodeVarint32(data, position, registers); + lastTag = registers.int1; + if (lastTag == endGroup) { + break; + } + position = skipField(lastTag, data, position, limit, registers); + } + if (position > limit || lastTag != endGroup) { + throw InvalidProtocolBufferException.parseFailure(); + } + return position; + default: + throw InvalidProtocolBufferException.invalidTag(); + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/BinaryReader.java b/java/core/src/main/java/com/google/protobuf/BinaryReader.java new file mode 100644 index 0000000000000..d64574c2a581e --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/BinaryReader.java @@ -0,0 +1,1729 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.WireFormat.FIXED32_SIZE; +import static com.google.protobuf.WireFormat.FIXED64_SIZE; +import static com.google.protobuf.WireFormat.WIRETYPE_END_GROUP; +import static com.google.protobuf.WireFormat.WIRETYPE_FIXED32; +import static com.google.protobuf.WireFormat.WIRETYPE_FIXED64; +import static com.google.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED; +import static com.google.protobuf.WireFormat.WIRETYPE_START_GROUP; +import static com.google.protobuf.WireFormat.WIRETYPE_VARINT; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Map; + +/** + * A {@link Reader} that reads from a buffer containing a message serialized with the binary + * protocol. + */ +@ExperimentalApi +abstract class BinaryReader implements Reader { + private static final int FIXED32_MULTIPLE_MASK = FIXED32_SIZE - 1; + private static final int FIXED64_MULTIPLE_MASK = FIXED64_SIZE - 1; + + /** + * Creates a new reader using the given {@code buffer} as input. + * + * @param buffer the input buffer. The buffer (including position, limit, etc.) will not be + * modified. To increment the buffer position after the read completes, use the value returned + * by {@link #getTotalBytesRead()}. + * @param bufferIsImmutable if {@code true} the reader assumes that the content of {@code buffer} + * will never change and any allocated {@link ByteString} instances will by directly wrap + * slices of {@code buffer}. + * @return the reader + */ + public static BinaryReader newInstance(ByteBuffer buffer, boolean bufferIsImmutable) { + if (buffer.hasArray()) { + // TODO(nathanmittler): Add support for unsafe operations. + return new SafeHeapReader(buffer, bufferIsImmutable); + } + // TODO(nathanmittler): Add support for direct buffers + throw new IllegalArgumentException("Direct buffers not yet supported"); + } + + /** Only allow subclassing for inner classes. */ + private BinaryReader() {} + + /** Returns the total number of bytes read so far from the input buffer. */ + public abstract int getTotalBytesRead(); + + @Override + public boolean shouldDiscardUnknownFields() { + return false; + } + + /** + * A {@link BinaryReader} implementation that operates on a heap {@link ByteBuffer}. Uses only + * safe operations on the underlying array. + */ + private static final class SafeHeapReader extends BinaryReader { + private final boolean bufferIsImmutable; + private final byte[] buffer; + private int pos; + private final int initialPos; + private int limit; + private int tag; + private int endGroupTag; + + public SafeHeapReader(ByteBuffer bytebuf, boolean bufferIsImmutable) { + this.bufferIsImmutable = bufferIsImmutable; + buffer = bytebuf.array(); + initialPos = pos = bytebuf.arrayOffset() + bytebuf.position(); + limit = bytebuf.arrayOffset() + bytebuf.limit(); + } + + private boolean isAtEnd() { + return pos == limit; + } + + @Override + public int getTotalBytesRead() { + return pos - initialPos; + } + + @Override + public int getFieldNumber() throws IOException { + if (isAtEnd()) { + return Reader.READ_DONE; + } + tag = readVarint32(); + if (tag == endGroupTag) { + return Reader.READ_DONE; + } + return WireFormat.getTagFieldNumber(tag); + } + + @Override + public int getTag() { + return tag; + } + + @Override + public boolean skipField() throws IOException { + if (isAtEnd() || tag == endGroupTag) { + return false; + } + + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_VARINT: + skipVarint(); + return true; + case WIRETYPE_FIXED64: + skipBytes(FIXED64_SIZE); + return true; + case WIRETYPE_LENGTH_DELIMITED: + skipBytes(readVarint32()); + return true; + case WIRETYPE_FIXED32: + skipBytes(FIXED32_SIZE); + return true; + case WIRETYPE_START_GROUP: + skipGroup(); + return true; + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + + @Override + public double readDouble() throws IOException { + requireWireType(WIRETYPE_FIXED64); + return Double.longBitsToDouble(readLittleEndian64()); + } + + @Override + public float readFloat() throws IOException { + requireWireType(WIRETYPE_FIXED32); + return Float.intBitsToFloat(readLittleEndian32()); + } + + @Override + public long readUInt64() throws IOException { + requireWireType(WIRETYPE_VARINT); + return readVarint64(); + } + + @Override + public long readInt64() throws IOException { + requireWireType(WIRETYPE_VARINT); + return readVarint64(); + } + + @Override + public int readInt32() throws IOException { + requireWireType(WIRETYPE_VARINT); + return readVarint32(); + } + + @Override + public long readFixed64() throws IOException { + requireWireType(WIRETYPE_FIXED64); + return readLittleEndian64(); + } + + @Override + public int readFixed32() throws IOException { + requireWireType(WIRETYPE_FIXED32); + return readLittleEndian32(); + } + + @Override + public boolean readBool() throws IOException { + requireWireType(WIRETYPE_VARINT); + return readVarint32() != 0; + } + + @Override + public String readString() throws IOException { + return readStringInternal(false); + } + + @Override + public String readStringRequireUtf8() throws IOException { + return readStringInternal(true); + } + + public String readStringInternal(boolean requireUtf8) throws IOException { + requireWireType(WIRETYPE_LENGTH_DELIMITED); + final int size = readVarint32(); + if (size == 0) { + return ""; + } + + requireBytes(size); + if (requireUtf8 && !Utf8.isValidUtf8(buffer, pos, pos + size)) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + String result = new String(buffer, pos, size, Internal.UTF_8); + pos += size; + return result; + } + + @Override + public T readMessage(Class clazz, ExtensionRegistryLite extensionRegistry) + throws IOException { + requireWireType(WIRETYPE_LENGTH_DELIMITED); + return readMessage(Protobuf.getInstance().schemaFor(clazz), extensionRegistry); + } + + @Override + public T readMessageBySchemaWithCheck( + Schema schema, ExtensionRegistryLite extensionRegistry) throws IOException { + requireWireType(WIRETYPE_LENGTH_DELIMITED); + return readMessage(schema, extensionRegistry); + } + + private T readMessage(Schema schema, ExtensionRegistryLite extensionRegistry) + throws IOException { + int size = readVarint32(); + requireBytes(size); + + // Update the limit. + int prevLimit = limit; + int newLimit = pos + size; + limit = newLimit; + + try { + // Allocate and read the message. + T message = schema.newInstance(); + schema.mergeFrom(message, this, extensionRegistry); + schema.makeImmutable(message); + + if (pos != newLimit) { + throw InvalidProtocolBufferException.parseFailure(); + } + return message; + } finally { + // Restore the limit. + limit = prevLimit; + } + } + + @Override + public T readGroup(Class clazz, ExtensionRegistryLite extensionRegistry) + throws IOException { + requireWireType(WIRETYPE_START_GROUP); + return readGroup(Protobuf.getInstance().schemaFor(clazz), extensionRegistry); + } + + @Override + public T readGroupBySchemaWithCheck( + Schema schema, ExtensionRegistryLite extensionRegistry) throws IOException { + requireWireType(WIRETYPE_START_GROUP); + return readGroup(schema, extensionRegistry); + } + + private T readGroup(Schema schema, ExtensionRegistryLite extensionRegistry) + throws IOException { + int prevEndGroupTag = endGroupTag; + endGroupTag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WIRETYPE_END_GROUP); + + try { + // Allocate and read the message. + T message = schema.newInstance(); + schema.mergeFrom(message, this, extensionRegistry); + schema.makeImmutable(message); + + if (tag != endGroupTag) { + throw InvalidProtocolBufferException.parseFailure(); + } + return message; + } finally { + // Restore the old end group tag. + endGroupTag = prevEndGroupTag; + } + } + + @Override + public ByteString readBytes() throws IOException { + requireWireType(WIRETYPE_LENGTH_DELIMITED); + int size = readVarint32(); + if (size == 0) { + return ByteString.EMPTY; + } + + requireBytes(size); + ByteString bytes = + bufferIsImmutable + ? ByteString.wrap(buffer, pos, size) + : ByteString.copyFrom(buffer, pos, size); + pos += size; + return bytes; + } + + @Override + public int readUInt32() throws IOException { + requireWireType(WIRETYPE_VARINT); + return readVarint32(); + } + + @Override + public int readEnum() throws IOException { + requireWireType(WIRETYPE_VARINT); + return readVarint32(); + } + + @Override + public int readSFixed32() throws IOException { + requireWireType(WIRETYPE_FIXED32); + return readLittleEndian32(); + } + + @Override + public long readSFixed64() throws IOException { + requireWireType(WIRETYPE_FIXED64); + return readLittleEndian64(); + } + + @Override + public int readSInt32() throws IOException { + requireWireType(WIRETYPE_VARINT); + return CodedInputStream.decodeZigZag32(readVarint32()); + } + + @Override + public long readSInt64() throws IOException { + requireWireType(WIRETYPE_VARINT); + return CodedInputStream.decodeZigZag64(readVarint64()); + } + + @Override + public void readDoubleList(List target) throws IOException { + if (target instanceof DoubleArrayList) { + DoubleArrayList plist = (DoubleArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + verifyPackedFixed64Length(bytes); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + plist.addDouble(Double.longBitsToDouble(readLittleEndian64_NoCheck())); + } + break; + case WIRETYPE_FIXED64: + while (true) { + plist.addDouble(readDouble()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + verifyPackedFixed64Length(bytes); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + target.add(Double.longBitsToDouble(readLittleEndian64_NoCheck())); + } + break; + case WIRETYPE_FIXED64: + while (true) { + target.add(readDouble()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readFloatList(List target) throws IOException { + if (target instanceof FloatArrayList) { + FloatArrayList plist = (FloatArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + verifyPackedFixed32Length(bytes); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + plist.addFloat(Float.intBitsToFloat(readLittleEndian32_NoCheck())); + } + break; + case WIRETYPE_FIXED32: + while (true) { + plist.addFloat(readFloat()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + verifyPackedFixed32Length(bytes); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + target.add(Float.intBitsToFloat(readLittleEndian32_NoCheck())); + } + break; + case WIRETYPE_FIXED32: + while (true) { + target.add(readFloat()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readUInt64List(List target) throws IOException { + if (target instanceof LongArrayList) { + LongArrayList plist = (LongArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + plist.addLong(readVarint64()); + } + requirePosition(fieldEndPos); + break; + case WIRETYPE_VARINT: + while (true) { + plist.addLong(readUInt64()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + target.add(readVarint64()); + } + requirePosition(fieldEndPos); + break; + case WIRETYPE_VARINT: + while (true) { + target.add(readUInt64()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readInt64List(List target) throws IOException { + if (target instanceof LongArrayList) { + LongArrayList plist = (LongArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + plist.addLong(readVarint64()); + } + requirePosition(fieldEndPos); + break; + case WIRETYPE_VARINT: + while (true) { + plist.addLong(readInt64()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + target.add(readVarint64()); + } + requirePosition(fieldEndPos); + break; + case WIRETYPE_VARINT: + while (true) { + target.add(readInt64()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readInt32List(List target) throws IOException { + if (target instanceof IntArrayList) { + IntArrayList plist = (IntArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + plist.addInt(readVarint32()); + } + requirePosition(fieldEndPos); + break; + case WIRETYPE_VARINT: + while (true) { + plist.addInt(readInt32()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + target.add(readVarint32()); + } + requirePosition(fieldEndPos); + break; + case WIRETYPE_VARINT: + while (true) { + target.add(readInt32()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readFixed64List(List target) throws IOException { + if (target instanceof LongArrayList) { + LongArrayList plist = (LongArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + verifyPackedFixed64Length(bytes); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + plist.addLong(readLittleEndian64_NoCheck()); + } + break; + case WIRETYPE_FIXED64: + while (true) { + plist.addLong(readFixed64()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + verifyPackedFixed64Length(bytes); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + target.add(readLittleEndian64_NoCheck()); + } + break; + case WIRETYPE_FIXED64: + while (true) { + target.add(readFixed64()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readFixed32List(List target) throws IOException { + if (target instanceof IntArrayList) { + IntArrayList plist = (IntArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + verifyPackedFixed32Length(bytes); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + plist.addInt(readLittleEndian32_NoCheck()); + } + break; + case WIRETYPE_FIXED32: + while (true) { + plist.addInt(readFixed32()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + verifyPackedFixed32Length(bytes); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + target.add(readLittleEndian32_NoCheck()); + } + break; + case WIRETYPE_FIXED32: + while (true) { + target.add(readFixed32()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readBoolList(List target) throws IOException { + if (target instanceof BooleanArrayList) { + BooleanArrayList plist = (BooleanArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + plist.addBoolean(readVarint32() != 0); + } + requirePosition(fieldEndPos); + break; + case WIRETYPE_VARINT: + while (true) { + plist.addBoolean(readBool()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + target.add(readVarint32() != 0); + } + requirePosition(fieldEndPos); + break; + case WIRETYPE_VARINT: + while (true) { + target.add(readBool()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readStringList(List target) throws IOException { + readStringListInternal(target, false); + } + + @Override + public void readStringListRequireUtf8(List target) throws IOException { + readStringListInternal(target, true); + } + + public void readStringListInternal(List target, boolean requireUtf8) + throws IOException { + if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) { + throw InvalidProtocolBufferException.invalidWireType(); + } + + if (target instanceof LazyStringList && !requireUtf8) { + LazyStringList lazyList = (LazyStringList) target; + while (true) { + lazyList.add(readBytes()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + } else { + while (true) { + target.add(readStringInternal(requireUtf8)); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + } + } + + @Override + public void readMessageList( + List target, Class targetType, ExtensionRegistryLite extensionRegistry) + throws IOException { + final Schema schema = Protobuf.getInstance().schemaFor(targetType); + readMessageList(target, schema, extensionRegistry); + } + + @Override + public void readMessageList( + List target, Schema schema, ExtensionRegistryLite extensionRegistry) + throws IOException { + if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) { + throw InvalidProtocolBufferException.invalidWireType(); + } + final int listTag = tag; + while (true) { + target.add(readMessage(schema, extensionRegistry)); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != listTag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + } + + @Override + public void readGroupList( + List target, Class targetType, ExtensionRegistryLite extensionRegistry) + throws IOException { + final Schema schema = Protobuf.getInstance().schemaFor(targetType); + readGroupList(target, schema, extensionRegistry); + } + + @Override + public void readGroupList( + List target, Schema schema, ExtensionRegistryLite extensionRegistry) + throws IOException { + if (WireFormat.getTagWireType(tag) != WIRETYPE_START_GROUP) { + throw InvalidProtocolBufferException.invalidWireType(); + } + final int listTag = tag; + while (true) { + target.add(readGroup(schema, extensionRegistry)); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != listTag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + } + + @Override + public void readBytesList(List target) throws IOException { + if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) { + throw InvalidProtocolBufferException.invalidWireType(); + } + + while (true) { + target.add(readBytes()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + } + + @Override + public void readUInt32List(List target) throws IOException { + if (target instanceof IntArrayList) { + IntArrayList plist = (IntArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + plist.addInt(readVarint32()); + } + break; + case WIRETYPE_VARINT: + while (true) { + plist.addInt(readUInt32()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + target.add(readVarint32()); + } + break; + case WIRETYPE_VARINT: + while (true) { + target.add(readUInt32()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readEnumList(List target) throws IOException { + if (target instanceof IntArrayList) { + IntArrayList plist = (IntArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + plist.addInt(readVarint32()); + } + break; + case WIRETYPE_VARINT: + while (true) { + plist.addInt(readEnum()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + target.add(readVarint32()); + } + break; + case WIRETYPE_VARINT: + while (true) { + target.add(readEnum()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readSFixed32List(List target) throws IOException { + if (target instanceof IntArrayList) { + IntArrayList plist = (IntArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + verifyPackedFixed32Length(bytes); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + plist.addInt(readLittleEndian32_NoCheck()); + } + break; + case WIRETYPE_FIXED32: + while (true) { + plist.addInt(readSFixed32()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + verifyPackedFixed32Length(bytes); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + target.add(readLittleEndian32_NoCheck()); + } + break; + case WIRETYPE_FIXED32: + while (true) { + target.add(readSFixed32()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readSFixed64List(List target) throws IOException { + if (target instanceof LongArrayList) { + LongArrayList plist = (LongArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + verifyPackedFixed64Length(bytes); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + plist.addLong(readLittleEndian64_NoCheck()); + } + break; + case WIRETYPE_FIXED64: + while (true) { + plist.addLong(readSFixed64()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + verifyPackedFixed64Length(bytes); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + target.add(readLittleEndian64_NoCheck()); + } + break; + case WIRETYPE_FIXED64: + while (true) { + target.add(readSFixed64()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readSInt32List(List target) throws IOException { + if (target instanceof IntArrayList) { + IntArrayList plist = (IntArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + plist.addInt(CodedInputStream.decodeZigZag32(readVarint32())); + } + break; + case WIRETYPE_VARINT: + while (true) { + plist.addInt(readSInt32()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + target.add(CodedInputStream.decodeZigZag32(readVarint32())); + } + break; + case WIRETYPE_VARINT: + while (true) { + target.add(readSInt32()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readSInt64List(List target) throws IOException { + if (target instanceof LongArrayList) { + LongArrayList plist = (LongArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + plist.addLong(CodedInputStream.decodeZigZag64(readVarint64())); + } + break; + case WIRETYPE_VARINT: + while (true) { + plist.addLong(readSInt64()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = readVarint32(); + final int fieldEndPos = pos + bytes; + while (pos < fieldEndPos) { + target.add(CodedInputStream.decodeZigZag64(readVarint64())); + } + break; + case WIRETYPE_VARINT: + while (true) { + target.add(readSInt64()); + + if (isAtEnd()) { + return; + } + int prevPos = pos; + int nextTag = readVarint32(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Rewind the buffer position to before + // the new tag. + pos = prevPos; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public void readMap( + Map target, + MapEntryLite.Metadata metadata, + ExtensionRegistryLite extensionRegistry) + throws IOException { + requireWireType(WIRETYPE_LENGTH_DELIMITED); + int size = readVarint32(); + requireBytes(size); + + // Update the limit. + int prevLimit = limit; + int newLimit = pos + size; + limit = newLimit; + + try { + K key = metadata.defaultKey; + V value = metadata.defaultValue; + while (true) { + int number = getFieldNumber(); + if (number == READ_DONE) { + break; + } + try { + switch (number) { + case 1: + key = (K) readField(metadata.keyType, null, null); + break; + case 2: + value = + (V) + readField( + metadata.valueType, + metadata.defaultValue.getClass(), + extensionRegistry); + break; + default: + if (!skipField()) { + throw new InvalidProtocolBufferException("Unable to parse map entry."); + } + break; + } + } catch (InvalidProtocolBufferException.InvalidWireTypeException ignore) { + // the type doesn't match, skip the field. + if (!skipField()) { + throw new InvalidProtocolBufferException("Unable to parse map entry."); + } + } + } + target.put(key, value); + } finally { + // Restore the limit. + limit = prevLimit; + } + } + + private Object readField( + WireFormat.FieldType fieldType, + Class messageType, + ExtensionRegistryLite extensionRegistry) + throws IOException { + switch (fieldType) { + case BOOL: + return readBool(); + case BYTES: + return readBytes(); + case DOUBLE: + return readDouble(); + case ENUM: + return readEnum(); + case FIXED32: + return readFixed32(); + case FIXED64: + return readFixed64(); + case FLOAT: + return readFloat(); + case INT32: + return readInt32(); + case INT64: + return readInt64(); + case MESSAGE: + return readMessage(messageType, extensionRegistry); + case SFIXED32: + return readSFixed32(); + case SFIXED64: + return readSFixed64(); + case SINT32: + return readSInt32(); + case SINT64: + return readSInt64(); + case STRING: + return readStringRequireUtf8(); + case UINT32: + return readUInt32(); + case UINT64: + return readUInt64(); + default: + throw new RuntimeException("unsupported field type."); + } + } + + /** Read a raw Varint from the stream. If larger than 32 bits, discard the upper bits. */ + private int readVarint32() throws IOException { + // See implementation notes for readRawVarint64 + int i = pos; + + if (limit == pos) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + + int x; + if ((x = buffer[i++]) >= 0) { + pos = i; + return x; + } else if (limit - i < 9) { + return (int) readVarint64SlowPath(); + } else if ((x ^= (buffer[i++] << 7)) < 0) { + x ^= (~0 << 7); + } else if ((x ^= (buffer[i++] << 14)) >= 0) { + x ^= (~0 << 7) ^ (~0 << 14); + } else if ((x ^= (buffer[i++] << 21)) < 0) { + x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21); + } else { + int y = buffer[i++]; + x ^= y << 28; + x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28); + if (y < 0 + && buffer[i++] < 0 + && buffer[i++] < 0 + && buffer[i++] < 0 + && buffer[i++] < 0 + && buffer[i++] < 0) { + throw InvalidProtocolBufferException.malformedVarint(); + } + } + pos = i; + return x; + } + + public long readVarint64() throws IOException { + // Implementation notes: + // + // Optimized for one-byte values, expected to be common. + // The particular code below was selected from various candidates + // empirically, by winning VarintBenchmark. + // + // Sign extension of (signed) Java bytes is usually a nuisance, but + // we exploit it here to more easily obtain the sign of bytes read. + // Instead of cleaning up the sign extension bits by masking eagerly, + // we delay until we find the final (positive) byte, when we clear all + // accumulated bits with one xor. We depend on javac to constant fold. + int i = pos; + + if (limit == i) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + + final byte[] buffer = this.buffer; + long x; + int y; + if ((y = buffer[i++]) >= 0) { + pos = i; + return y; + } else if (limit - i < 9) { + return readVarint64SlowPath(); + } else if ((y ^= (buffer[i++] << 7)) < 0) { + x = y ^ (~0 << 7); + } else if ((y ^= (buffer[i++] << 14)) >= 0) { + x = y ^ ((~0 << 7) ^ (~0 << 14)); + } else if ((y ^= (buffer[i++] << 21)) < 0) { + x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21)); + } else if ((x = y ^ ((long) buffer[i++] << 28)) >= 0L) { + x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28); + } else if ((x ^= ((long) buffer[i++] << 35)) < 0L) { + x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35); + } else if ((x ^= ((long) buffer[i++] << 42)) >= 0L) { + x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42); + } else if ((x ^= ((long) buffer[i++] << 49)) < 0L) { + x ^= + (~0L << 7) + ^ (~0L << 14) + ^ (~0L << 21) + ^ (~0L << 28) + ^ (~0L << 35) + ^ (~0L << 42) + ^ (~0L << 49); + } else { + x ^= ((long) buffer[i++] << 56); + x ^= + (~0L << 7) + ^ (~0L << 14) + ^ (~0L << 21) + ^ (~0L << 28) + ^ (~0L << 35) + ^ (~0L << 42) + ^ (~0L << 49) + ^ (~0L << 56); + if (x < 0L) { + if (buffer[i++] < 0L) { + throw InvalidProtocolBufferException.malformedVarint(); + } + } + } + pos = i; + return x; + } + + private long readVarint64SlowPath() throws IOException { + long result = 0; + for (int shift = 0; shift < 64; shift += 7) { + final byte b = readByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + } + throw InvalidProtocolBufferException.malformedVarint(); + } + + private byte readByte() throws IOException { + if (pos == limit) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + return buffer[pos++]; + } + + private int readLittleEndian32() throws IOException { + requireBytes(FIXED32_SIZE); + return readLittleEndian32_NoCheck(); + } + + private long readLittleEndian64() throws IOException { + requireBytes(FIXED64_SIZE); + return readLittleEndian64_NoCheck(); + } + + private int readLittleEndian32_NoCheck() { + int p = pos; + final byte[] buffer = this.buffer; + pos = p + FIXED32_SIZE; + return (((buffer[p] & 0xff)) + | ((buffer[p + 1] & 0xff) << 8) + | ((buffer[p + 2] & 0xff) << 16) + | ((buffer[p + 3] & 0xff) << 24)); + } + + private long readLittleEndian64_NoCheck() { + int p = pos; + final byte[] buffer = this.buffer; + pos = p + FIXED64_SIZE; + return (((buffer[p] & 0xffL)) + | ((buffer[p + 1] & 0xffL) << 8) + | ((buffer[p + 2] & 0xffL) << 16) + | ((buffer[p + 3] & 0xffL) << 24) + | ((buffer[p + 4] & 0xffL) << 32) + | ((buffer[p + 5] & 0xffL) << 40) + | ((buffer[p + 6] & 0xffL) << 48) + | ((buffer[p + 7] & 0xffL) << 56)); + } + + private void skipVarint() throws IOException { + if (limit - pos >= 10) { + final byte[] buffer = this.buffer; + int p = pos; + for (int i = 0; i < 10; i++) { + if (buffer[p++] >= 0) { + pos = p; + return; + } + } + } + skipVarintSlowPath(); + } + + private void skipVarintSlowPath() throws IOException { + for (int i = 0; i < 10; i++) { + if (readByte() >= 0) { + return; + } + } + throw InvalidProtocolBufferException.malformedVarint(); + } + + private void skipBytes(final int size) throws IOException { + requireBytes(size); + + pos += size; + } + + private void skipGroup() throws IOException { + int prevEndGroupTag = endGroupTag; + endGroupTag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WIRETYPE_END_GROUP); + while (true) { + if (getFieldNumber() == READ_DONE || !skipField()) { + break; + } + } + if (tag != endGroupTag) { + throw InvalidProtocolBufferException.parseFailure(); + } + endGroupTag = prevEndGroupTag; + } + + private void requireBytes(int size) throws IOException { + if (size < 0 || size > (limit - pos)) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + } + + private void requireWireType(int requiredWireType) throws IOException { + if (WireFormat.getTagWireType(tag) != requiredWireType) { + throw InvalidProtocolBufferException.invalidWireType(); + } + } + + private void verifyPackedFixed64Length(int bytes) throws IOException { + requireBytes(bytes); + if ((bytes & FIXED64_MULTIPLE_MASK) != 0) { + // Require that the number of bytes be a multiple of 8. + throw InvalidProtocolBufferException.parseFailure(); + } + } + + private void verifyPackedFixed32Length(int bytes) throws IOException { + requireBytes(bytes); + if ((bytes & FIXED32_MULTIPLE_MASK) != 0) { + // Require that the number of bytes be a multiple of 4. + throw InvalidProtocolBufferException.parseFailure(); + } + } + + private void requirePosition(int expectedPosition) throws IOException { + if (pos != expectedPosition) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/BinaryWriter.java b/java/core/src/main/java/com/google/protobuf/BinaryWriter.java new file mode 100644 index 0000000000000..94259ecd32bba --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/BinaryWriter.java @@ -0,0 +1,3071 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.Internal.checkNotNull; +import static com.google.protobuf.WireFormat.FIXED32_SIZE; +import static com.google.protobuf.WireFormat.FIXED64_SIZE; +import static com.google.protobuf.WireFormat.MAX_VARINT32_SIZE; +import static com.google.protobuf.WireFormat.MAX_VARINT64_SIZE; +import static com.google.protobuf.WireFormat.MESSAGE_SET_ITEM; +import static com.google.protobuf.WireFormat.MESSAGE_SET_MESSAGE; +import static com.google.protobuf.WireFormat.MESSAGE_SET_TYPE_ID; +import static com.google.protobuf.WireFormat.WIRETYPE_END_GROUP; +import static com.google.protobuf.WireFormat.WIRETYPE_FIXED32; +import static com.google.protobuf.WireFormat.WIRETYPE_FIXED64; +import static com.google.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED; +import static com.google.protobuf.WireFormat.WIRETYPE_START_GROUP; +import static com.google.protobuf.WireFormat.WIRETYPE_VARINT; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayDeque; +import java.util.List; +import java.util.Map; +import java.util.Queue; + +/** + * A protobuf writer that serializes messages in their binary form. Messages are serialized in + * reverse in order to avoid calculating the serialized size of each nested message. Since the + * message size is not known in advance, the writer employs a strategy of chunking and buffer + * chaining. Buffers are allocated as-needed by a provided {@link BufferAllocator}. Once writing is + * finished, the application can access the buffers in forward-writing order by calling {@link + * #complete()}. + * + *

Once {@link #complete()} has been called, the writer can not be reused for additional writes. + * The {@link #getTotalBytesWritten()} will continue to reflect the total of the write and will not + * be reset. + */ +@ExperimentalApi +abstract class BinaryWriter extends ByteOutput implements Writer { + public static final int DEFAULT_CHUNK_SIZE = 4096; + + private final BufferAllocator alloc; + private final int chunkSize; + + final ArrayDeque buffers = new ArrayDeque(4); + int totalDoneBytes; + + /** + * Creates a new {@link BinaryWriter} that will allocate heap buffers of {@link + * #DEFAULT_CHUNK_SIZE} as necessary. + */ + public static BinaryWriter newHeapInstance(BufferAllocator alloc) { + return newHeapInstance(alloc, DEFAULT_CHUNK_SIZE); + } + + /** + * Creates a new {@link BinaryWriter} that will allocate heap buffers of {@code chunkSize} as + * necessary. + */ + public static BinaryWriter newHeapInstance(BufferAllocator alloc, int chunkSize) { + return isUnsafeHeapSupported() + ? newUnsafeHeapInstance(alloc, chunkSize) + : newSafeHeapInstance(alloc, chunkSize); + } + + /** + * Creates a new {@link BinaryWriter} that will allocate direct (i.e. non-heap) buffers of {@link + * #DEFAULT_CHUNK_SIZE} as necessary. + */ + public static BinaryWriter newDirectInstance(BufferAllocator alloc) { + return newDirectInstance(alloc, DEFAULT_CHUNK_SIZE); + } + + /** + * Creates a new {@link BinaryWriter} that will allocate direct (i.e. non-heap) buffers of {@code + * chunkSize} as necessary. + */ + public static BinaryWriter newDirectInstance(BufferAllocator alloc, int chunkSize) { + return isUnsafeDirectSupported() + ? newUnsafeDirectInstance(alloc, chunkSize) + : newSafeDirectInstance(alloc, chunkSize); + } + + static boolean isUnsafeHeapSupported() { + return UnsafeHeapWriter.isSupported(); + } + + static boolean isUnsafeDirectSupported() { + return UnsafeDirectWriter.isSupported(); + } + + static BinaryWriter newSafeHeapInstance(BufferAllocator alloc, int chunkSize) { + return new SafeHeapWriter(alloc, chunkSize); + } + + static BinaryWriter newUnsafeHeapInstance(BufferAllocator alloc, int chunkSize) { + if (!isUnsafeHeapSupported()) { + throw new UnsupportedOperationException("Unsafe operations not supported"); + } + return new UnsafeHeapWriter(alloc, chunkSize); + } + + static BinaryWriter newSafeDirectInstance(BufferAllocator alloc, int chunkSize) { + return new SafeDirectWriter(alloc, chunkSize); + } + + static BinaryWriter newUnsafeDirectInstance(BufferAllocator alloc, int chunkSize) { + if (!isUnsafeDirectSupported()) { + throw new UnsupportedOperationException("Unsafe operations not supported"); + } + return new UnsafeDirectWriter(alloc, chunkSize); + } + + /** Only allow subclassing for inner classes. */ + private BinaryWriter(BufferAllocator alloc, int chunkSize) { + if (chunkSize <= 0) { + throw new IllegalArgumentException("chunkSize must be > 0"); + } + this.alloc = checkNotNull(alloc, "alloc"); + this.chunkSize = chunkSize; + } + + @Override + public final FieldOrder fieldOrder() { + return FieldOrder.DESCENDING; + } + + /** + * Completes the write operation and returns a queue of {@link AllocatedBuffer} objects in + * forward-writing order. This method should only be called once. + * + *

After calling this method, the writer can not be reused. Create a new writer for future + * writes. + */ + public final Queue complete() { + finishCurrentBuffer(); + return buffers; + } + + @Override + public final void writeSFixed32(int fieldNumber, int value) throws IOException { + writeFixed32(fieldNumber, value); + } + + @Override + public final void writeInt64(int fieldNumber, long value) throws IOException { + writeUInt64(fieldNumber, value); + } + + @Override + public final void writeSFixed64(int fieldNumber, long value) throws IOException { + writeFixed64(fieldNumber, value); + } + + @Override + public final void writeFloat(int fieldNumber, float value) throws IOException { + writeFixed32(fieldNumber, Float.floatToRawIntBits(value)); + } + + @Override + public final void writeDouble(int fieldNumber, double value) throws IOException { + writeFixed64(fieldNumber, Double.doubleToRawLongBits(value)); + } + + @Override + public final void writeEnum(int fieldNumber, int value) throws IOException { + writeInt32(fieldNumber, value); + } + + @Override + public final void writeInt32List(int fieldNumber, List list, boolean packed) + throws IOException { + if (list instanceof IntArrayList) { + writeInt32List_Internal(fieldNumber, (IntArrayList) list, packed); + } else { + writeInt32List_Internal(fieldNumber, list, packed); + } + } + + private final void writeInt32List_Internal(int fieldNumber, List list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeInt32(list.get(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeInt32(fieldNumber, list.get(i)); + } + } + } + + private final void writeInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeInt32(list.getInt(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeInt32(fieldNumber, list.getInt(i)); + } + } + } + + @Override + public final void writeFixed32List(int fieldNumber, List list, boolean packed) + throws IOException { + if (list instanceof IntArrayList) { + writeFixed32List_Internal(fieldNumber, (IntArrayList) list, packed); + } else { + writeFixed32List_Internal(fieldNumber, list, packed); + } + } + + private final void writeFixed32List_Internal(int fieldNumber, List list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeFixed32(list.get(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeFixed32(fieldNumber, list.get(i)); + } + } + } + + private final void writeFixed32List_Internal(int fieldNumber, IntArrayList list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeFixed32(list.getInt(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeFixed32(fieldNumber, list.getInt(i)); + } + } + } + + @Override + public final void writeInt64List(int fieldNumber, List list, boolean packed) + throws IOException { + writeUInt64List(fieldNumber, list, packed); + } + + @Override + public final void writeUInt64List(int fieldNumber, List list, boolean packed) + throws IOException { + if (list instanceof LongArrayList) { + writeUInt64List_Internal(fieldNumber, (LongArrayList) list, packed); + } else { + writeUInt64List_Internal(fieldNumber, list, packed); + } + } + + private final void writeUInt64List_Internal(int fieldNumber, List list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeVarint64(list.get(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeUInt64(fieldNumber, list.get(i)); + } + } + } + + private final void writeUInt64List_Internal(int fieldNumber, LongArrayList list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeVarint64(list.getLong(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeUInt64(fieldNumber, list.getLong(i)); + } + } + } + + @Override + public final void writeFixed64List(int fieldNumber, List list, boolean packed) + throws IOException { + if (list instanceof LongArrayList) { + writeFixed64List_Internal(fieldNumber, (LongArrayList) list, packed); + } else { + writeFixed64List_Internal(fieldNumber, list, packed); + } + } + + private final void writeFixed64List_Internal(int fieldNumber, List list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeFixed64(list.get(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeFixed64(fieldNumber, list.get(i)); + } + } + } + + private final void writeFixed64List_Internal(int fieldNumber, LongArrayList list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeFixed64(list.getLong(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeFixed64(fieldNumber, list.getLong(i)); + } + } + } + + @Override + public final void writeFloatList(int fieldNumber, List list, boolean packed) + throws IOException { + if (list instanceof FloatArrayList) { + writeFloatList_Internal(fieldNumber, (FloatArrayList) list, packed); + } else { + writeFloatList_Internal(fieldNumber, list, packed); + } + } + + private final void writeFloatList_Internal(int fieldNumber, List list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeFixed32(Float.floatToRawIntBits(list.get(i))); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeFloat(fieldNumber, list.get(i)); + } + } + } + + private final void writeFloatList_Internal(int fieldNumber, FloatArrayList list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeFixed32(Float.floatToRawIntBits(list.getFloat(i))); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeFloat(fieldNumber, list.getFloat(i)); + } + } + } + + @Override + public final void writeDoubleList(int fieldNumber, List list, boolean packed) + throws IOException { + if (list instanceof DoubleArrayList) { + writeDoubleList_Internal(fieldNumber, (DoubleArrayList) list, packed); + } else { + writeDoubleList_Internal(fieldNumber, list, packed); + } + } + + private final void writeDoubleList_Internal(int fieldNumber, List list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeFixed64(Double.doubleToRawLongBits(list.get(i))); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeDouble(fieldNumber, list.get(i)); + } + } + } + + private final void writeDoubleList_Internal(int fieldNumber, DoubleArrayList list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeFixed64(Double.doubleToRawLongBits(list.getDouble(i))); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeDouble(fieldNumber, list.getDouble(i)); + } + } + } + + @Override + public final void writeEnumList(int fieldNumber, List list, boolean packed) + throws IOException { + writeInt32List(fieldNumber, list, packed); + } + + @Override + public final void writeBoolList(int fieldNumber, List list, boolean packed) + throws IOException { + if (list instanceof BooleanArrayList) { + writeBoolList_Internal(fieldNumber, (BooleanArrayList) list, packed); + } else { + writeBoolList_Internal(fieldNumber, list, packed); + } + } + + private final void writeBoolList_Internal(int fieldNumber, List list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + list.size()); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeBool(list.get(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeBool(fieldNumber, list.get(i)); + } + } + } + + private final void writeBoolList_Internal(int fieldNumber, BooleanArrayList list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + list.size()); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeBool(list.getBoolean(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeBool(fieldNumber, list.getBoolean(i)); + } + } + } + + @Override + public final void writeStringList(int fieldNumber, List list) throws IOException { + if (list instanceof LazyStringList) { + final LazyStringList lazyList = (LazyStringList) list; + for (int i = list.size() - 1; i >= 0; i--) { + writeLazyString(fieldNumber, lazyList.getRaw(i)); + } + } else { + for (int i = list.size() - 1; i >= 0; i--) { + writeString(fieldNumber, list.get(i)); + } + } + } + + private void writeLazyString(int fieldNumber, Object value) throws IOException { + if (value instanceof String) { + writeString(fieldNumber, (String) value); + } else { + writeBytes(fieldNumber, (ByteString) value); + } + } + + @Override + public final void writeBytesList(int fieldNumber, List list) throws IOException { + for (int i = list.size() - 1; i >= 0; i--) { + writeBytes(fieldNumber, list.get(i)); + } + } + + @Override + public final void writeUInt32List(int fieldNumber, List list, boolean packed) + throws IOException { + if (list instanceof IntArrayList) { + writeUInt32List_Internal(fieldNumber, (IntArrayList) list, packed); + } else { + writeUInt32List_Internal(fieldNumber, list, packed); + } + } + + private final void writeUInt32List_Internal(int fieldNumber, List list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeVarint32(list.get(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeUInt32(fieldNumber, list.get(i)); + } + } + } + + private final void writeUInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeVarint32(list.getInt(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeUInt32(fieldNumber, list.getInt(i)); + } + } + } + + @Override + public final void writeSFixed32List(int fieldNumber, List list, boolean packed) + throws IOException { + writeFixed32List(fieldNumber, list, packed); + } + + @Override + public final void writeSFixed64List(int fieldNumber, List list, boolean packed) + throws IOException { + writeFixed64List(fieldNumber, list, packed); + } + + @Override + public final void writeSInt32List(int fieldNumber, List list, boolean packed) + throws IOException { + if (list instanceof IntArrayList) { + writeSInt32List_Internal(fieldNumber, (IntArrayList) list, packed); + } else { + writeSInt32List_Internal(fieldNumber, list, packed); + } + } + + private final void writeSInt32List_Internal(int fieldNumber, List list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeSInt32(list.get(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeSInt32(fieldNumber, list.get(i)); + } + } + } + + private final void writeSInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeSInt32(list.getInt(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeSInt32(fieldNumber, list.getInt(i)); + } + } + } + + @Override + public final void writeSInt64List(int fieldNumber, List list, boolean packed) + throws IOException { + if (list instanceof LongArrayList) { + writeSInt64List_Internal(fieldNumber, (LongArrayList) list, packed); + } else { + writeSInt64List_Internal(fieldNumber, list, packed); + } + } + + private static final int MAP_KEY_NUMBER = 1; + private static final int MAP_VALUE_NUMBER = 2; + + @Override + public void writeMap(int fieldNumber, MapEntryLite.Metadata metadata, Map map) + throws IOException { + // TODO(liujisi): Reverse write those entries. + for (Map.Entry entry : map.entrySet()) { + int prevBytes = getTotalBytesWritten(); + writeMapEntryField(this, MAP_VALUE_NUMBER, metadata.valueType, entry.getValue()); + writeMapEntryField(this, MAP_KEY_NUMBER, metadata.keyType, entry.getKey()); + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + } + + static final void writeMapEntryField( + Writer writer, int fieldNumber, WireFormat.FieldType fieldType, Object object) + throws IOException { + switch (fieldType) { + case BOOL: + writer.writeBool(fieldNumber, (Boolean) object); + break; + case FIXED32: + writer.writeFixed32(fieldNumber, (Integer) object); + break; + case FIXED64: + writer.writeFixed64(fieldNumber, (Long) object); + break; + case INT32: + writer.writeInt32(fieldNumber, (Integer) object); + break; + case INT64: + writer.writeInt64(fieldNumber, (Long) object); + break; + case SFIXED32: + writer.writeSFixed32(fieldNumber, (Integer) object); + break; + case SFIXED64: + writer.writeSFixed64(fieldNumber, (Long) object); + break; + case SINT32: + writer.writeSInt32(fieldNumber, (Integer) object); + break; + case SINT64: + writer.writeSInt64(fieldNumber, (Long) object); + break; + case STRING: + writer.writeString(fieldNumber, (String) object); + break; + case UINT32: + writer.writeUInt32(fieldNumber, (Integer) object); + break; + case UINT64: + writer.writeUInt64(fieldNumber, (Long) object); + break; + case FLOAT: + writer.writeFloat(fieldNumber, (Float) object); + break; + case DOUBLE: + writer.writeDouble(fieldNumber, (Double) object); + break; + case MESSAGE: + writer.writeMessage(fieldNumber, object); + break; + case BYTES: + writer.writeBytes(fieldNumber, (ByteString) object); + break; + case ENUM: + if (object instanceof Internal.EnumLite) { + writer.writeEnum(fieldNumber, ((Internal.EnumLite) object).getNumber()); + } else if (object instanceof Integer) { + writer.writeEnum(fieldNumber, (Integer) object); + } else { + throw new IllegalArgumentException("Unexpected type for enum in map."); + } + break; + default: + throw new IllegalArgumentException("Unsupported map value type for: " + fieldType); + } + } + + private final void writeSInt64List_Internal(int fieldNumber, List list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeSInt64(list.get(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeSInt64(fieldNumber, list.get(i)); + } + } + } + + private final void writeSInt64List_Internal(int fieldNumber, LongArrayList list, boolean packed) + throws IOException { + if (packed) { + requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE)); + int prevBytes = getTotalBytesWritten(); + for (int i = list.size() - 1; i >= 0; --i) { + writeSInt64(list.getLong(i)); + } + int length = getTotalBytesWritten() - prevBytes; + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } else { + for (int i = list.size() - 1; i >= 0; --i) { + writeSInt64(fieldNumber, list.getLong(i)); + } + } + } + + @Override + public final void writeMessageList(int fieldNumber, List list) throws IOException { + for (int i = list.size() - 1; i >= 0; i--) { + writeMessage(fieldNumber, list.get(i)); + } + } + + @Override + public final void writeMessageList(int fieldNumber, List list, Schema schema) + throws IOException { + for (int i = list.size() - 1; i >= 0; i--) { + writeMessage(fieldNumber, list.get(i), schema); + } + } + + @Override + public final void writeGroupList(int fieldNumber, List list) throws IOException { + for (int i = list.size() - 1; i >= 0; i--) { + writeGroup(fieldNumber, list.get(i)); + } + } + + @Override + public final void writeGroupList(int fieldNumber, List list, Schema schema) + throws IOException { + for (int i = list.size() - 1; i >= 0; i--) { + writeGroup(fieldNumber, list.get(i), schema); + } + } + + @Override + public final void writeMessageSetItem(int fieldNumber, Object value) throws IOException { + writeTag(MESSAGE_SET_ITEM, WIRETYPE_END_GROUP); + if (value instanceof ByteString) { + writeBytes(MESSAGE_SET_MESSAGE, (ByteString) value); + } else { + writeMessage(MESSAGE_SET_MESSAGE, value); + } + writeUInt32(MESSAGE_SET_TYPE_ID, fieldNumber); + writeTag(MESSAGE_SET_ITEM, WIRETYPE_START_GROUP); + } + + final AllocatedBuffer newHeapBuffer() { + return alloc.allocateHeapBuffer(chunkSize); + } + + final AllocatedBuffer newHeapBuffer(int capacity) { + return alloc.allocateHeapBuffer(Math.max(capacity, chunkSize)); + } + + final AllocatedBuffer newDirectBuffer() { + return alloc.allocateDirectBuffer(chunkSize); + } + + final AllocatedBuffer newDirectBuffer(int capacity) { + return alloc.allocateDirectBuffer(Math.max(capacity, chunkSize)); + } + + /** + * Gets the total number of bytes that have been written. This will not be reset by a call to + * {@link #complete()}. + */ + public abstract int getTotalBytesWritten(); + + abstract void requireSpace(int size); + + abstract void finishCurrentBuffer(); + + abstract void writeTag(int fieldNumber, int wireType); + + abstract void writeVarint32(int value); + + abstract void writeInt32(int value); + + abstract void writeSInt32(int value); + + abstract void writeFixed32(int value); + + abstract void writeVarint64(long value); + + abstract void writeSInt64(long value); + + abstract void writeFixed64(long value); + + abstract void writeBool(boolean value); + + abstract void writeString(String in); + + /** + * Not using the version in CodedOutputStream due to the fact that benchmarks have shown a + * performance improvement when returning a byte (rather than an int). + */ + private static byte computeUInt64SizeNoTag(long value) { + // handle two popular special cases up front ... + if ((value & (~0L << 7)) == 0L) { + // Byte 1 + return 1; + } + if (value < 0L) { + // Byte 10 + return 10; + } + // ... leaving us with 8 remaining, which we can divide and conquer + byte n = 2; + if ((value & (~0L << 35)) != 0L) { + // Byte 6-9 + n += 4; // + (value >>> 63); + value >>>= 28; + } + if ((value & (~0L << 21)) != 0L) { + // Byte 4-5 or 8-9 + n += 2; + value >>>= 14; + } + if ((value & (~0L << 14)) != 0L) { + // Byte 3 or 7 + n += 1; + } + return n; + } + + /** Writer that uses safe operations on target array. */ + private static final class SafeHeapWriter extends BinaryWriter { + private AllocatedBuffer allocatedBuffer; + private byte[] buffer; + private int offset; + private int limit; + private int offsetMinusOne; + private int limitMinusOne; + private int pos; + + SafeHeapWriter(BufferAllocator alloc, int chunkSize) { + super(alloc, chunkSize); + nextBuffer(); + } + + @Override + void finishCurrentBuffer() { + if (allocatedBuffer != null) { + totalDoneBytes += bytesWrittenToCurrentBuffer(); + allocatedBuffer.position((pos - allocatedBuffer.arrayOffset()) + 1); + allocatedBuffer = null; + pos = 0; + limitMinusOne = 0; + } + } + + private void nextBuffer() { + nextBuffer(newHeapBuffer()); + } + + private void nextBuffer(int capacity) { + nextBuffer(newHeapBuffer(capacity)); + } + + private void nextBuffer(AllocatedBuffer allocatedBuffer) { + if (!allocatedBuffer.hasArray()) { + throw new RuntimeException("Allocator returned non-heap buffer"); + } + + finishCurrentBuffer(); + + buffers.addFirst(allocatedBuffer); + + this.allocatedBuffer = allocatedBuffer; + this.buffer = allocatedBuffer.array(); + int arrayOffset = allocatedBuffer.arrayOffset(); + this.limit = arrayOffset + allocatedBuffer.limit(); + this.offset = arrayOffset + allocatedBuffer.position(); + this.offsetMinusOne = offset - 1; + this.limitMinusOne = limit - 1; + this.pos = limitMinusOne; + } + + @Override + public int getTotalBytesWritten() { + return totalDoneBytes + bytesWrittenToCurrentBuffer(); + } + + int bytesWrittenToCurrentBuffer() { + return limitMinusOne - pos; + } + + int spaceLeft() { + return pos - offsetMinusOne; + } + + @Override + public void writeUInt32(int fieldNumber, int value) throws IOException { + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeInt32(int fieldNumber, int value) throws IOException { + requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE); + writeInt32(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeSInt32(int fieldNumber, int value) throws IOException { + requireSpace(MAX_VARINT32_SIZE * 2); + writeSInt32(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeFixed32(int fieldNumber, int value) throws IOException { + requireSpace(MAX_VARINT32_SIZE + FIXED32_SIZE); + writeFixed32(value); + writeTag(fieldNumber, WIRETYPE_FIXED32); + } + + @Override + public void writeUInt64(int fieldNumber, long value) throws IOException { + requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE); + writeVarint64(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeSInt64(int fieldNumber, long value) throws IOException { + requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE); + writeSInt64(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeFixed64(int fieldNumber, long value) throws IOException { + requireSpace(MAX_VARINT32_SIZE + FIXED64_SIZE); + writeFixed64(value); + writeTag(fieldNumber, WIRETYPE_FIXED64); + } + + @Override + public void writeBool(int fieldNumber, boolean value) throws IOException { + requireSpace(MAX_VARINT32_SIZE + 1); + write((byte) (value ? 1 : 0)); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeString(int fieldNumber, String value) throws IOException { + int prevBytes = getTotalBytesWritten(); + writeString(value); + int length = getTotalBytesWritten() - prevBytes; + requireSpace(2 * MAX_VARINT32_SIZE); + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeBytes(int fieldNumber, ByteString value) throws IOException { + try { + value.writeToReverse(this); + } catch (IOException e) { + // Should never happen since the writer does not throw. + throw new RuntimeException(e); + } + + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(value.size()); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeMessage(int fieldNumber, Object value) throws IOException { + int prevBytes = getTotalBytesWritten(); + Protobuf.getInstance().writeTo(value, this); + int length = getTotalBytesWritten() - prevBytes; + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException { + int prevBytes = getTotalBytesWritten(); + schema.writeTo(value, this); + int length = getTotalBytesWritten() - prevBytes; + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeGroup(int fieldNumber, Object value) throws IOException { + writeTag(fieldNumber, WIRETYPE_END_GROUP); + Protobuf.getInstance().writeTo(value, this); + writeTag(fieldNumber, WIRETYPE_START_GROUP); + } + + @Override + public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException { + writeTag(fieldNumber, WIRETYPE_END_GROUP); + schema.writeTo(value, this); + writeTag(fieldNumber, WIRETYPE_START_GROUP); + } + + @Override + public void writeStartGroup(int fieldNumber) { + writeTag(fieldNumber, WIRETYPE_START_GROUP); + } + + @Override + public void writeEndGroup(int fieldNumber) { + writeTag(fieldNumber, WIRETYPE_END_GROUP); + } + + @Override + void writeInt32(int value) { + if (value >= 0) { + writeVarint32(value); + } else { + writeVarint64(value); + } + } + + @Override + void writeSInt32(int value) { + writeVarint32(CodedOutputStream.encodeZigZag32(value)); + } + + @Override + void writeSInt64(long value) { + writeVarint64(CodedOutputStream.encodeZigZag64(value)); + } + + @Override + void writeBool(boolean value) { + write((byte) (value ? 1 : 0)); + } + + @Override + void writeTag(int fieldNumber, int wireType) { + writeVarint32(WireFormat.makeTag(fieldNumber, wireType)); + } + + @Override + void writeVarint32(int value) { + if ((value & (~0 << 7)) == 0) { + writeVarint32OneByte(value); + } else if ((value & (~0 << 14)) == 0) { + writeVarint32TwoBytes(value); + } else if ((value & (~0 << 21)) == 0) { + writeVarint32ThreeBytes(value); + } else if ((value & (~0 << 28)) == 0) { + writeVarint32FourBytes(value); + } else { + writeVarint32FiveBytes(value); + } + } + + private void writeVarint32OneByte(int value) { + buffer[pos--] = (byte) value; + } + + private void writeVarint32TwoBytes(int value) { + buffer[pos--] = (byte) (value >>> 7); + buffer[pos--] = (byte) ((value & 0x7F) | 0x80); + } + + private void writeVarint32ThreeBytes(int value) { + buffer[pos--] = (byte) (value >>> 14); + buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80); + buffer[pos--] = (byte) ((value & 0x7F) | 0x80); + } + + private void writeVarint32FourBytes(int value) { + buffer[pos--] = (byte) (value >>> 21); + buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80); + buffer[pos--] = (byte) ((value & 0x7F) | 0x80); + } + + private void writeVarint32FiveBytes(int value) { + buffer[pos--] = (byte) (value >>> 28); + buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80); + buffer[pos--] = (byte) ((value & 0x7F) | 0x80); + } + + @Override + void writeVarint64(long value) { + switch (computeUInt64SizeNoTag(value)) { + case 1: + writeVarint64OneByte(value); + break; + case 2: + writeVarint64TwoBytes(value); + break; + case 3: + writeVarint64ThreeBytes(value); + break; + case 4: + writeVarint64FourBytes(value); + break; + case 5: + writeVarint64FiveBytes(value); + break; + case 6: + writeVarint64SixBytes(value); + break; + case 7: + writeVarint64SevenBytes(value); + break; + case 8: + writeVarint64EightBytes(value); + break; + case 9: + writeVarint64NineBytes(value); + break; + case 10: + writeVarint64TenBytes(value); + break; + } + } + + private void writeVarint64OneByte(long value) { + buffer[pos--] = (byte) value; + } + + private void writeVarint64TwoBytes(long value) { + buffer[pos--] = (byte) (value >>> 7); + buffer[pos--] = (byte) (((int) value & 0x7F) | 0x80); + } + + private void writeVarint64ThreeBytes(long value) { + buffer[pos--] = (byte) (((int) value) >>> 14); + buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80); + buffer[pos--] = (byte) ((value & 0x7F) | 0x80); + } + + private void writeVarint64FourBytes(long value) { + buffer[pos--] = (byte) (value >>> 21); + buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80); + buffer[pos--] = (byte) ((value & 0x7F) | 0x80); + } + + private void writeVarint64FiveBytes(long value) { + buffer[pos--] = (byte) (value >>> 28); + buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80); + buffer[pos--] = (byte) ((value & 0x7F) | 0x80); + } + + private void writeVarint64SixBytes(long value) { + buffer[pos--] = (byte) (value >>> 35); + buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80); + buffer[pos--] = (byte) ((value & 0x7F) | 0x80); + } + + private void writeVarint64SevenBytes(long value) { + buffer[pos--] = (byte) (value >>> 42); + buffer[pos--] = (byte) (((value >>> 35) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80); + buffer[pos--] = (byte) ((value & 0x7F) | 0x80); + } + + private void writeVarint64EightBytes(long value) { + buffer[pos--] = (byte) (value >>> 49); + buffer[pos--] = (byte) (((value >>> 42) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 35) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80); + buffer[pos--] = (byte) ((value & 0x7F) | 0x80); + } + + private void writeVarint64NineBytes(long value) { + buffer[pos--] = (byte) (value >>> 56); + buffer[pos--] = (byte) (((value >>> 49) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 42) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 35) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80); + buffer[pos--] = (byte) ((value & 0x7F) | 0x80); + } + + private void writeVarint64TenBytes(long value) { + buffer[pos--] = (byte) (value >>> 63); + buffer[pos--] = (byte) (((value >>> 56) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 49) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 42) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 35) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80); + buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80); + buffer[pos--] = (byte) ((value & 0x7F) | 0x80); + } + + @Override + void writeFixed32(int value) { + buffer[pos--] = (byte) ((value >> 24) & 0xFF); + buffer[pos--] = (byte) ((value >> 16) & 0xFF); + buffer[pos--] = (byte) ((value >> 8) & 0xFF); + buffer[pos--] = (byte) (value & 0xFF); + } + + @Override + void writeFixed64(long value) { + buffer[pos--] = (byte) ((int) (value >> 56) & 0xFF); + buffer[pos--] = (byte) ((int) (value >> 48) & 0xFF); + buffer[pos--] = (byte) ((int) (value >> 40) & 0xFF); + buffer[pos--] = (byte) ((int) (value >> 32) & 0xFF); + buffer[pos--] = (byte) ((int) (value >> 24) & 0xFF); + buffer[pos--] = (byte) ((int) (value >> 16) & 0xFF); + buffer[pos--] = (byte) ((int) (value >> 8) & 0xFF); + buffer[pos--] = (byte) ((int) (value) & 0xFF); + } + + @Override + void writeString(String in) { + // Request enough space to write the ASCII string. + requireSpace(in.length()); + + // We know the buffer is big enough... + int i = in.length() - 1; + // Set pos to the start of the ASCII string. + pos -= i; + // Designed to take advantage of + // https://wiki.openjdk.java.net/display/HotSpotInternals/RangeCheckElimination + for (char c; i >= 0 && (c = in.charAt(i)) < 0x80; i--) { + buffer[pos + i] = (byte) c; + } + if (i == -1) { + // Move pos past the String. + pos -= 1; + return; + } + pos += i; + for (char c; i >= 0; i--) { + c = in.charAt(i); + if (c < 0x80 && pos > offsetMinusOne) { + buffer[pos--] = (byte) c; + } else if (c < 0x800 && pos > offset) { // 11 bits, two UTF-8 bytes + buffer[pos--] = (byte) (0x80 | (0x3F & c)); + buffer[pos--] = (byte) ((0xF << 6) | (c >>> 6)); + } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) + && pos > (offset + 1)) { + // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes + buffer[pos--] = (byte) (0x80 | (0x3F & c)); + buffer[pos--] = (byte) (0x80 | (0x3F & (c >>> 6))); + buffer[pos--] = (byte) ((0xF << 5) | (c >>> 12)); + } else if (pos > (offset + 2)) { + // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, + // four UTF-8 bytes + char high = 0; + if (i == 0 || !Character.isSurrogatePair(high = in.charAt(i - 1), c)) { + throw new Utf8.UnpairedSurrogateException(i - 1, i); + } + i--; + int codePoint = Character.toCodePoint(high, c); + buffer[pos--] = (byte) (0x80 | (0x3F & codePoint)); + buffer[pos--] = (byte) (0x80 | (0x3F & (codePoint >>> 6))); + buffer[pos--] = (byte) (0x80 | (0x3F & (codePoint >>> 12))); + buffer[pos--] = (byte) ((0xF << 4) | (codePoint >>> 18)); + } else { + // Buffer is full - allocate a new one and revisit the current character. + requireSpace(i); + i++; + } + } + } + + @Override + public void write(byte value) { + buffer[pos--] = value; + } + + @Override + public void write(byte[] value, int offset, int length) { + if (spaceLeft() < length) { + nextBuffer(length); + } + + pos -= length; + System.arraycopy(value, offset, buffer, pos + 1, length); + } + + @Override + public void writeLazy(byte[] value, int offset, int length) { + if (spaceLeft() < length) { + // We consider the value to be immutable (likely the internals of a ByteString). Just + // wrap it in a Netty buffer and add it to the output buffer. + totalDoneBytes += length; + buffers.addFirst(AllocatedBuffer.wrap(value, offset, length)); + + // Advance the writer to the next buffer. + // TODO(nathanmittler): Consider slicing if space available above some threshold. + nextBuffer(); + return; + } + + pos -= length; + System.arraycopy(value, offset, buffer, pos + 1, length); + } + + @Override + public void write(ByteBuffer value) { + int length = value.remaining(); + if (spaceLeft() < length) { + nextBuffer(length); + } + + pos -= length; + value.get(buffer, pos + 1, length); + } + + @Override + public void writeLazy(ByteBuffer value) { + int length = value.remaining(); + if (spaceLeft() < length) { + // We consider the value to be immutable (likely the internals of a ByteString). Just + // wrap it in a Netty buffer and add it to the output buffer. + totalDoneBytes += length; + buffers.addFirst(AllocatedBuffer.wrap(value)); + + // Advance the writer to the next buffer. + // TODO(nathanmittler): Consider slicing if space available above some threshold. + nextBuffer(); + } + + pos -= length; + value.get(buffer, pos + 1, length); + } + + @Override + void requireSpace(int size) { + if (spaceLeft() < size) { + nextBuffer(size); + } + } + } + + /** Writer that uses unsafe operations on a target array. */ + private static final class UnsafeHeapWriter extends BinaryWriter { + private AllocatedBuffer allocatedBuffer; + private byte[] buffer; + private long offset; + private long limit; + private long offsetMinusOne; + private long limitMinusOne; + private long pos; + + UnsafeHeapWriter(BufferAllocator alloc, int chunkSize) { + super(alloc, chunkSize); + nextBuffer(); + } + + /** Indicates whether the required unsafe operations are supported on this platform. */ + static boolean isSupported() { + return UnsafeUtil.hasUnsafeArrayOperations(); + } + + @Override + void finishCurrentBuffer() { + if (allocatedBuffer != null) { + totalDoneBytes += bytesWrittenToCurrentBuffer(); + allocatedBuffer.position((arrayPos() - allocatedBuffer.arrayOffset()) + 1); + allocatedBuffer = null; + pos = 0; + limitMinusOne = 0; + } + } + + private int arrayPos() { + return (int) pos; + } + + private void nextBuffer() { + nextBuffer(newHeapBuffer()); + } + + private void nextBuffer(int capacity) { + nextBuffer(newHeapBuffer(capacity)); + } + + private void nextBuffer(AllocatedBuffer allocatedBuffer) { + if (!allocatedBuffer.hasArray()) { + throw new RuntimeException("Allocator returned non-heap buffer"); + } + + finishCurrentBuffer(); + buffers.addFirst(allocatedBuffer); + + this.allocatedBuffer = allocatedBuffer; + this.buffer = allocatedBuffer.array(); + int arrayOffset = allocatedBuffer.arrayOffset(); + this.limit = arrayOffset + allocatedBuffer.limit(); + this.offset = arrayOffset + allocatedBuffer.position(); + this.offsetMinusOne = offset - 1; + this.limitMinusOne = limit - 1; + this.pos = limitMinusOne; + } + + @Override + public int getTotalBytesWritten() { + return totalDoneBytes + bytesWrittenToCurrentBuffer(); + } + + int bytesWrittenToCurrentBuffer() { + return (int) (limitMinusOne - pos); + } + + int spaceLeft() { + return (int) (pos - offsetMinusOne); + } + + @Override + public void writeUInt32(int fieldNumber, int value) { + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeInt32(int fieldNumber, int value) { + requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE); + writeInt32(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeSInt32(int fieldNumber, int value) { + requireSpace(MAX_VARINT32_SIZE * 2); + writeSInt32(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeFixed32(int fieldNumber, int value) { + requireSpace(MAX_VARINT32_SIZE + FIXED32_SIZE); + writeFixed32(value); + writeTag(fieldNumber, WIRETYPE_FIXED32); + } + + @Override + public void writeUInt64(int fieldNumber, long value) { + requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE); + writeVarint64(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeSInt64(int fieldNumber, long value) { + requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE); + writeSInt64(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeFixed64(int fieldNumber, long value) { + requireSpace(MAX_VARINT32_SIZE + FIXED64_SIZE); + writeFixed64(value); + writeTag(fieldNumber, WIRETYPE_FIXED64); + } + + @Override + public void writeBool(int fieldNumber, boolean value) { + requireSpace(MAX_VARINT32_SIZE + 1); + write((byte) (value ? 1 : 0)); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeString(int fieldNumber, String value) { + int prevBytes = getTotalBytesWritten(); + writeString(value); + int length = getTotalBytesWritten() - prevBytes; + requireSpace(2 * MAX_VARINT32_SIZE); + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeBytes(int fieldNumber, ByteString value) { + try { + value.writeToReverse(this); + } catch (IOException e) { + // Should never happen since the writer does not throw. + throw new RuntimeException(e); + } + + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(value.size()); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeMessage(int fieldNumber, Object value) throws IOException { + int prevBytes = getTotalBytesWritten(); + Protobuf.getInstance().writeTo(value, this); + int length = getTotalBytesWritten() - prevBytes; + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException { + int prevBytes = getTotalBytesWritten(); + schema.writeTo(value, this); + int length = getTotalBytesWritten() - prevBytes; + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeGroup(int fieldNumber, Object value) throws IOException { + writeTag(fieldNumber, WIRETYPE_END_GROUP); + Protobuf.getInstance().writeTo(value, this); + writeTag(fieldNumber, WIRETYPE_START_GROUP); + } + + @Override + public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException { + writeTag(fieldNumber, WIRETYPE_END_GROUP); + schema.writeTo(value, this); + writeTag(fieldNumber, WIRETYPE_START_GROUP); + } + + @Override + public void writeStartGroup(int fieldNumber) { + writeTag(fieldNumber, WIRETYPE_START_GROUP); + } + + @Override + public void writeEndGroup(int fieldNumber) { + writeTag(fieldNumber, WIRETYPE_END_GROUP); + } + + @Override + void writeInt32(int value) { + if (value >= 0) { + writeVarint32(value); + } else { + writeVarint64(value); + } + } + + @Override + void writeSInt32(int value) { + writeVarint32(CodedOutputStream.encodeZigZag32(value)); + } + + @Override + void writeSInt64(long value) { + writeVarint64(CodedOutputStream.encodeZigZag64(value)); + } + + @Override + void writeBool(boolean value) { + write((byte) (value ? 1 : 0)); + } + + @Override + void writeTag(int fieldNumber, int wireType) { + writeVarint32(WireFormat.makeTag(fieldNumber, wireType)); + } + + @Override + void writeVarint32(int value) { + if ((value & (~0 << 7)) == 0) { + writeVarint32OneByte(value); + } else if ((value & (~0 << 14)) == 0) { + writeVarint32TwoBytes(value); + } else if ((value & (~0 << 21)) == 0) { + writeVarint32ThreeBytes(value); + } else if ((value & (~0 << 28)) == 0) { + writeVarint32FourBytes(value); + } else { + writeVarint32FiveBytes(value); + } + } + + private void writeVarint32OneByte(int value) { + UnsafeUtil.putByte(buffer, pos--, (byte) value); + } + + private void writeVarint32TwoBytes(int value) { + UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 7)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint32ThreeBytes(int value) { + UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 14)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint32FourBytes(int value) { + UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 21)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint32FiveBytes(int value) { + UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 28)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80)); + } + + @Override + void writeVarint64(long value) { + switch (computeUInt64SizeNoTag(value)) { + case 1: + writeVarint64OneByte(value); + break; + case 2: + writeVarint64TwoBytes(value); + break; + case 3: + writeVarint64ThreeBytes(value); + break; + case 4: + writeVarint64FourBytes(value); + break; + case 5: + writeVarint64FiveBytes(value); + break; + case 6: + writeVarint64SixBytes(value); + break; + case 7: + writeVarint64SevenBytes(value); + break; + case 8: + writeVarint64EightBytes(value); + break; + case 9: + writeVarint64NineBytes(value); + break; + case 10: + writeVarint64TenBytes(value); + break; + } + } + + private void writeVarint64OneByte(long value) { + UnsafeUtil.putByte(buffer, pos--, (byte) value); + } + + private void writeVarint64TwoBytes(long value) { + UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 7)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((int) value & 0x7F) | 0x80)); + } + + private void writeVarint64ThreeBytes(long value) { + UnsafeUtil.putByte(buffer, pos--, (byte) (((int) value) >>> 14)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint64FourBytes(long value) { + UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 21)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint64FiveBytes(long value) { + UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 28)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint64SixBytes(long value) { + UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 35)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint64SevenBytes(long value) { + UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 42)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 35) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint64EightBytes(long value) { + UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 49)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 42) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 35) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint64NineBytes(long value) { + UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 56)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 49) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 42) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 35) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint64TenBytes(long value) { + UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 63)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 56) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 49) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 42) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 35) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80)); + } + + @Override + void writeFixed32(int value) { + UnsafeUtil.putByte(buffer, pos--, (byte) ((value >> 24) & 0xFF)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((value >> 16) & 0xFF)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((value >> 8) & 0xFF)); + UnsafeUtil.putByte(buffer, pos--, (byte) (value & 0xFF)); + } + + @Override + void writeFixed64(long value) { + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 56) & 0xFF)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 48) & 0xFF)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 40) & 0xFF)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 32) & 0xFF)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 24) & 0xFF)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 16) & 0xFF)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 8) & 0xFF)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value) & 0xFF)); + } + + @Override + void writeString(String in) { + // Request enough space to write the ASCII string. + requireSpace(in.length()); + + // We know the buffer is big enough... + int i = in.length() - 1; + // Set pos to the start of the ASCII string. + // pos -= i; + // Designed to take advantage of + // https://wiki.openjdk.java.net/display/HotSpotInternals/RangeCheckElimination + for (char c; i >= 0 && (c = in.charAt(i)) < 0x80; i--) { + UnsafeUtil.putByte(buffer, pos--, (byte) c); + } + if (i == -1) { + // Move pos past the String. + return; + } + for (char c; i >= 0; i--) { + c = in.charAt(i); + if (c < 0x80 && pos > offsetMinusOne) { + UnsafeUtil.putByte(buffer, pos--, (byte) c); + } else if (c < 0x800 && pos > offset) { // 11 bits, two UTF-8 bytes + UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & c))); + UnsafeUtil.putByte(buffer, pos--, (byte) ((0xF << 6) | (c >>> 6))); + } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) + && pos > offset + 1) { + // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes + UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & c))); + UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & (c >>> 6)))); + UnsafeUtil.putByte(buffer, pos--, (byte) ((0xF << 5) | (c >>> 12))); + } else if (pos > offset + 2) { + // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, + // four UTF-8 bytes + final char high; + if (i == 0 || !Character.isSurrogatePair(high = in.charAt(i - 1), c)) { + throw new Utf8.UnpairedSurrogateException(i - 1, i); + } + i--; + int codePoint = Character.toCodePoint(high, c); + UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & codePoint))); + UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & (codePoint >>> 6)))); + UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & (codePoint >>> 12)))); + UnsafeUtil.putByte(buffer, pos--, (byte) ((0xF << 4) | (codePoint >>> 18))); + } else { + // Buffer is full - allocate a new one and revisit the current character. + requireSpace(i); + i++; + } + } + } + + @Override + public void write(byte value) { + UnsafeUtil.putByte(buffer, pos--, value); + } + + @Override + public void write(byte[] value, int offset, int length) { + if (offset < 0 || offset + length > value.length) { + throw new ArrayIndexOutOfBoundsException( + String.format("value.length=%d, offset=%d, length=%d", value.length, offset, length)); + } + requireSpace(length); + + pos -= length; + System.arraycopy(value, offset, buffer, arrayPos() + 1, length); + } + + @Override + public void writeLazy(byte[] value, int offset, int length) { + if (offset < 0 || offset + length > value.length) { + throw new ArrayIndexOutOfBoundsException( + String.format("value.length=%d, offset=%d, length=%d", value.length, offset, length)); + } + if (spaceLeft() < length) { + // We consider the value to be immutable (likely the internals of a ByteString). Just + // wrap it in a Netty buffer and add it to the output buffer. + totalDoneBytes += length; + buffers.addFirst(AllocatedBuffer.wrap(value, offset, length)); + + // Advance the writer to the next buffer. + // TODO(nathanmittler): Consider slicing if space available above some threshold. + nextBuffer(); + return; + } + + pos -= length; + System.arraycopy(value, offset, buffer, arrayPos() + 1, length); + } + + @Override + public void write(ByteBuffer value) { + int length = value.remaining(); + requireSpace(length); + + pos -= length; + value.get(buffer, arrayPos() + 1, length); + } + + @Override + public void writeLazy(ByteBuffer value) { + int length = value.remaining(); + if (spaceLeft() < length) { + // We consider the value to be immutable (likely the internals of a ByteString). Just + // wrap it in a Netty buffer and add it to the output buffer. + totalDoneBytes += length; + buffers.addFirst(AllocatedBuffer.wrap(value)); + + // Advance the writer to the next buffer. + // TODO(nathanmittler): Consider slicing if space available above some threshold. + nextBuffer(); + } + + pos -= length; + value.get(buffer, arrayPos() + 1, length); + } + + @Override + void requireSpace(int size) { + if (spaceLeft() < size) { + nextBuffer(size); + } + } + } + + /** Writer that uses safe operations on a target {@link ByteBuffer}. */ + private static final class SafeDirectWriter extends BinaryWriter { + private ByteBuffer buffer; + private int limitMinusOne; + private int pos; + + SafeDirectWriter(BufferAllocator alloc, int chunkSize) { + super(alloc, chunkSize); + nextBuffer(); + } + + private void nextBuffer() { + nextBuffer(newDirectBuffer()); + } + + private void nextBuffer(int capacity) { + nextBuffer(newDirectBuffer(capacity)); + } + + private void nextBuffer(AllocatedBuffer allocatedBuffer) { + if (!allocatedBuffer.hasNioBuffer()) { + throw new RuntimeException("Allocated buffer does not have NIO buffer"); + } + ByteBuffer nioBuffer = allocatedBuffer.nioBuffer(); + if (!nioBuffer.isDirect()) { + throw new RuntimeException("Allocator returned non-direct buffer"); + } + + finishCurrentBuffer(); + buffers.addFirst(allocatedBuffer); + + buffer = nioBuffer; + buffer.limit(buffer.capacity()); + buffer.position(0); + // Set byte order to little endian for fast writing of fixed 32/64. + buffer.order(ByteOrder.LITTLE_ENDIAN); + + limitMinusOne = buffer.limit() - 1; + pos = limitMinusOne; + } + + @Override + public int getTotalBytesWritten() { + return totalDoneBytes + bytesWrittenToCurrentBuffer(); + } + + private int bytesWrittenToCurrentBuffer() { + return limitMinusOne - pos; + } + + private int spaceLeft() { + return pos + 1; + } + + @Override + void finishCurrentBuffer() { + if (buffer != null) { + totalDoneBytes += bytesWrittenToCurrentBuffer(); + // Update the indices on the netty buffer. + buffer.position(pos + 1); + buffer = null; + pos = 0; + limitMinusOne = 0; + } + } + + @Override + public void writeUInt32(int fieldNumber, int value) { + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeInt32(int fieldNumber, int value) { + requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE); + writeInt32(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeSInt32(int fieldNumber, int value) { + requireSpace(MAX_VARINT32_SIZE * 2); + writeSInt32(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeFixed32(int fieldNumber, int value) { + requireSpace(MAX_VARINT32_SIZE + FIXED32_SIZE); + writeFixed32(value); + writeTag(fieldNumber, WIRETYPE_FIXED32); + } + + @Override + public void writeUInt64(int fieldNumber, long value) { + requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE); + writeVarint64(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeSInt64(int fieldNumber, long value) { + requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE); + writeSInt64(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeFixed64(int fieldNumber, long value) { + requireSpace(MAX_VARINT32_SIZE + FIXED64_SIZE); + writeFixed64(value); + writeTag(fieldNumber, WIRETYPE_FIXED64); + } + + @Override + public void writeBool(int fieldNumber, boolean value) { + requireSpace(MAX_VARINT32_SIZE + 1); + write((byte) (value ? 1 : 0)); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeString(int fieldNumber, String value) { + int prevBytes = getTotalBytesWritten(); + writeString(value); + int length = getTotalBytesWritten() - prevBytes; + requireSpace(2 * MAX_VARINT32_SIZE); + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeBytes(int fieldNumber, ByteString value) { + try { + value.writeToReverse(this); + } catch (IOException e) { + // Should never happen since the writer does not throw. + throw new RuntimeException(e); + } + + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(value.size()); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeMessage(int fieldNumber, Object value) throws IOException { + int prevBytes = getTotalBytesWritten(); + Protobuf.getInstance().writeTo(value, this); + int length = getTotalBytesWritten() - prevBytes; + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException { + int prevBytes = getTotalBytesWritten(); + schema.writeTo(value, this); + int length = getTotalBytesWritten() - prevBytes; + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeGroup(int fieldNumber, Object value) throws IOException { + writeTag(fieldNumber, WIRETYPE_END_GROUP); + Protobuf.getInstance().writeTo(value, this); + writeTag(fieldNumber, WIRETYPE_START_GROUP); + } + + @Override + public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException { + writeTag(fieldNumber, WIRETYPE_END_GROUP); + schema.writeTo(value, this); + writeTag(fieldNumber, WIRETYPE_START_GROUP); + } + + @Override + public void writeStartGroup(int fieldNumber) { + writeTag(fieldNumber, WIRETYPE_START_GROUP); + } + + @Override + public void writeEndGroup(int fieldNumber) { + writeTag(fieldNumber, WIRETYPE_END_GROUP); + } + + @Override + void writeInt32(int value) { + if (value >= 0) { + writeVarint32(value); + } else { + writeVarint64(value); + } + } + + @Override + void writeSInt32(int value) { + writeVarint32(CodedOutputStream.encodeZigZag32(value)); + } + + @Override + void writeSInt64(long value) { + writeVarint64(CodedOutputStream.encodeZigZag64(value)); + } + + @Override + void writeBool(boolean value) { + write((byte) (value ? 1 : 0)); + } + + @Override + void writeTag(int fieldNumber, int wireType) { + writeVarint32(WireFormat.makeTag(fieldNumber, wireType)); + } + + @Override + void writeVarint32(int value) { + if ((value & (~0 << 7)) == 0) { + writeVarint32OneByte(value); + } else if ((value & (~0 << 14)) == 0) { + writeVarint32TwoBytes(value); + } else if ((value & (~0 << 21)) == 0) { + writeVarint32ThreeBytes(value); + } else if ((value & (~0 << 28)) == 0) { + writeVarint32FourBytes(value); + } else { + writeVarint32FiveBytes(value); + } + } + + private void writeVarint32OneByte(int value) { + buffer.put(pos--, (byte) value); + } + + private void writeVarint32TwoBytes(int value) { + // Byte order is little-endian. + pos -= 2; + buffer.putShort(pos + 1, (short) (((value & (0x7F << 7)) << 1) | ((value & 0x7F) | 0x80))); + } + + private void writeVarint32ThreeBytes(int value) { + // Byte order is little-endian. + pos -= 3; + buffer.putInt( + pos, + ((value & (0x7F << 14)) << 10) + | (((value & (0x7F << 7)) | (0x80 << 7)) << 9) + | ((value & 0x7F) | 0x80) << 8); + } + + private void writeVarint32FourBytes(int value) { + // Byte order is little-endian. + pos -= 4; + buffer.putInt( + pos + 1, + ((value & (0x7F << 21)) << 3) + | (((value & (0x7F << 14)) | (0x80 << 14)) << 2) + | (((value & (0x7F << 7)) | (0x80 << 7)) << 1) + | ((value & 0x7F) | 0x80)); + } + + private void writeVarint32FiveBytes(int value) { + // Byte order is little-endian. + buffer.put(pos--, (byte) (value >>> 28)); + pos -= 4; + buffer.putInt( + pos + 1, + ((((value >>> 21) & 0x7F) | 0x80) << 24) + | ((((value >>> 14) & 0x7F) | 0x80) << 16) + | ((((value >>> 7) & 0x7F) | 0x80) << 8) + | ((value & 0x7F) | 0x80)); + } + + @Override + void writeVarint64(long value) { + switch (computeUInt64SizeNoTag(value)) { + case 1: + writeVarint64OneByte(value); + break; + case 2: + writeVarint64TwoBytes(value); + break; + case 3: + writeVarint64ThreeBytes(value); + break; + case 4: + writeVarint64FourBytes(value); + break; + case 5: + writeVarint64FiveBytes(value); + break; + case 6: + writeVarint64SixBytes(value); + break; + case 7: + writeVarint64SevenBytes(value); + break; + case 8: + writeVarint64EightBytes(value); + break; + case 9: + writeVarint64NineBytes(value); + break; + case 10: + writeVarint64TenBytes(value); + break; + } + } + + private void writeVarint64OneByte(long value) { + writeVarint32OneByte((int) value); + } + + private void writeVarint64TwoBytes(long value) { + writeVarint32TwoBytes((int) value); + } + + private void writeVarint64ThreeBytes(long value) { + writeVarint32ThreeBytes((int) value); + } + + private void writeVarint64FourBytes(long value) { + writeVarint32FourBytes((int) value); + } + + private void writeVarint64FiveBytes(long value) { + // Byte order is little-endian. + pos -= 5; + buffer.putLong( + pos - 2, + ((value & (0x7FL << 28)) << 28) + | (((value & (0x7F << 21)) | (0x80 << 21)) << 27) + | (((value & (0x7F << 14)) | (0x80 << 14)) << 26) + | (((value & (0x7F << 7)) | (0x80 << 7)) << 25) + | (((value & 0x7F) | 0x80)) << 24); + } + + private void writeVarint64SixBytes(long value) { + // Byte order is little-endian. + pos -= 6; + buffer.putLong( + pos - 1, + ((value & (0x7FL << 35)) << 21) + | (((value & (0x7FL << 28)) | (0x80L << 28)) << 20) + | (((value & (0x7F << 21)) | (0x80 << 21)) << 19) + | (((value & (0x7F << 14)) | (0x80 << 14)) << 18) + | (((value & (0x7F << 7)) | (0x80 << 7)) << 17) + | (((value & 0x7F) | 0x80)) << 16); + } + + private void writeVarint64SevenBytes(long value) { + // Byte order is little-endian. + pos -= 7; + buffer.putLong( + pos, + ((value & (0x7FL << 42)) << 14) + | (((value & (0x7FL << 35)) | (0x80L << 35)) << 13) + | (((value & (0x7FL << 28)) | (0x80L << 28)) << 12) + | (((value & (0x7F << 21)) | (0x80 << 21)) << 11) + | (((value & (0x7F << 14)) | (0x80 << 14)) << 10) + | (((value & (0x7F << 7)) | (0x80 << 7)) << 9) + | (((value & 0x7F) | 0x80)) << 8); + } + + private void writeVarint64EightBytes(long value) { + // Byte order is little-endian. + pos -= 8; + buffer.putLong( + pos + 1, + ((value & (0x7FL << 49)) << 7) + | (((value & (0x7FL << 42)) | (0x80L << 42)) << 6) + | (((value & (0x7FL << 35)) | (0x80L << 35)) << 5) + | (((value & (0x7FL << 28)) | (0x80L << 28)) << 4) + | (((value & (0x7F << 21)) | (0x80 << 21)) << 3) + | (((value & (0x7F << 14)) | (0x80 << 14)) << 2) + | (((value & (0x7F << 7)) | (0x80 << 7)) << 1) + | ((value & 0x7F) | 0x80)); + } + + private void writeVarint64EightBytesWithSign(long value) { + // Byte order is little-endian. + pos -= 8; + buffer.putLong( + pos + 1, + (((value & (0x7FL << 49)) | (0x80L << 49)) << 7) + | (((value & (0x7FL << 42)) | (0x80L << 42)) << 6) + | (((value & (0x7FL << 35)) | (0x80L << 35)) << 5) + | (((value & (0x7FL << 28)) | (0x80L << 28)) << 4) + | (((value & (0x7F << 21)) | (0x80 << 21)) << 3) + | (((value & (0x7F << 14)) | (0x80 << 14)) << 2) + | (((value & (0x7F << 7)) | (0x80 << 7)) << 1) + | ((value & 0x7F) | 0x80)); + } + + private void writeVarint64NineBytes(long value) { + buffer.put(pos--, (byte) (value >>> 56)); + writeVarint64EightBytesWithSign(value & 0xFFFFFFFFFFFFFFL); + } + + private void writeVarint64TenBytes(long value) { + buffer.put(pos--, (byte) (value >>> 63)); + buffer.put(pos--, (byte) (((value >>> 56) & 0x7F) | 0x80)); + writeVarint64EightBytesWithSign(value & 0xFFFFFFFFFFFFFFL); + } + + @Override + void writeFixed32(int value) { + pos -= 4; + buffer.putInt(pos + 1, value); + } + + @Override + void writeFixed64(long value) { + pos -= 8; + buffer.putLong(pos + 1, value); + } + + @Override + void writeString(String in) { + // Request enough space to write the ASCII string. + requireSpace(in.length()); + + // We know the buffer is big enough... + int i = in.length() - 1; + pos -= i; + // Designed to take advantage of + // https://wiki.openjdk.java.net/display/HotSpotInternals/RangeCheckElimination + for (char c; i >= 0 && (c = in.charAt(i)) < 0x80; i--) { + buffer.put(pos + i, (byte) c); + } + if (i == -1) { + // Move the position past the ASCII string. + pos -= 1; + return; + } + pos += i; + for (char c; i >= 0; i--) { + c = in.charAt(i); + if (c < 0x80 && pos >= 0) { + buffer.put(pos--, (byte) c); + } else if (c < 0x800 && pos > 0) { // 11 bits, two UTF-8 bytes + buffer.put(pos--, (byte) (0x80 | (0x3F & c))); + buffer.put(pos--, (byte) ((0xF << 6) | (c >>> 6))); + } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && pos > 1) { + // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes + buffer.put(pos--, (byte) (0x80 | (0x3F & c))); + buffer.put(pos--, (byte) (0x80 | (0x3F & (c >>> 6)))); + buffer.put(pos--, (byte) ((0xF << 5) | (c >>> 12))); + } else if (pos > 2) { + // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, + // four UTF-8 bytes + char high = 0; + if (i == 0 || !Character.isSurrogatePair(high = in.charAt(i - 1), c)) { + throw new Utf8.UnpairedSurrogateException(i - 1, i); + } + i--; + int codePoint = Character.toCodePoint(high, c); + buffer.put(pos--, (byte) (0x80 | (0x3F & codePoint))); + buffer.put(pos--, (byte) (0x80 | (0x3F & (codePoint >>> 6)))); + buffer.put(pos--, (byte) (0x80 | (0x3F & (codePoint >>> 12)))); + buffer.put(pos--, (byte) ((0xF << 4) | (codePoint >>> 18))); + } else { + // Buffer is full - allocate a new one and revisit the current character. + requireSpace(i); + i++; + } + } + } + + @Override + public void write(byte value) { + buffer.put(pos--, value); + } + + @Override + public void write(byte[] value, int offset, int length) { + if (spaceLeft() < length) { + nextBuffer(length); + } + + pos -= length; + buffer.position(pos + 1); + buffer.put(value, offset, length); + } + + @Override + public void writeLazy(byte[] value, int offset, int length) { + if (spaceLeft() < length) { + // We consider the value to be immutable (likely the internals of a ByteString). Just + // wrap it in a Netty buffer and add it to the output buffer. + totalDoneBytes += length; + buffers.addFirst(AllocatedBuffer.wrap(value, offset, length)); + + // Advance the writer to the next buffer. + // TODO(nathanmittler): Consider slicing if space available above some threshold. + nextBuffer(); + return; + } + + pos -= length; + buffer.position(pos + 1); + buffer.put(value, offset, length); + } + + @Override + public void write(ByteBuffer value) { + int length = value.remaining(); + if (spaceLeft() < length) { + nextBuffer(length); + } + + pos -= length; + buffer.position(pos + 1); + buffer.put(value); + } + + @Override + public void writeLazy(ByteBuffer value) { + int length = value.remaining(); + if (spaceLeft() < length) { + // We consider the value to be immutable (likely the internals of a ByteString). Just + // wrap it in a Netty buffer and add it to the output buffer. + totalDoneBytes += length; + buffers.addFirst(AllocatedBuffer.wrap(value)); + + // Advance the writer to the next buffer. + // TODO(nathanmittler): Consider slicing if space available above some threshold. + nextBuffer(); + return; + } + + pos -= length; + buffer.position(pos + 1); + buffer.put(value); + } + + @Override + void requireSpace(int size) { + if (spaceLeft() < size) { + nextBuffer(size); + } + } + } + + /** Writer that uses unsafe operations on a target {@link ByteBuffer}. */ + private static final class UnsafeDirectWriter extends BinaryWriter { + private ByteBuffer buffer; + private long bufferOffset; + private long limitMinusOne; + private long pos; + + UnsafeDirectWriter(BufferAllocator alloc, int chunkSize) { + super(alloc, chunkSize); + nextBuffer(); + } + + /** Indicates whether the required unsafe operations are supported on this platform. */ + private static boolean isSupported() { + return UnsafeUtil.hasUnsafeByteBufferOperations(); + } + + private void nextBuffer() { + nextBuffer(newDirectBuffer()); + } + + private void nextBuffer(int capacity) { + nextBuffer(newDirectBuffer(capacity)); + } + + private void nextBuffer(AllocatedBuffer allocatedBuffer) { + if (!allocatedBuffer.hasNioBuffer()) { + throw new RuntimeException("Allocated buffer does not have NIO buffer"); + } + ByteBuffer nioBuffer = allocatedBuffer.nioBuffer(); + if (!nioBuffer.isDirect()) { + throw new RuntimeException("Allocator returned non-direct buffer"); + } + + finishCurrentBuffer(); + buffers.addFirst(allocatedBuffer); + + buffer = nioBuffer; + buffer.limit(buffer.capacity()); + buffer.position(0); + + bufferOffset = UnsafeUtil.addressOffset(buffer); + limitMinusOne = bufferOffset + (buffer.limit() - 1); + pos = limitMinusOne; + } + + @Override + public int getTotalBytesWritten() { + return totalDoneBytes + bytesWrittenToCurrentBuffer(); + } + + private int bytesWrittenToCurrentBuffer() { + return (int) (limitMinusOne - pos); + } + + private int spaceLeft() { + return bufferPos() + 1; + } + + @Override + void finishCurrentBuffer() { + if (buffer != null) { + totalDoneBytes += bytesWrittenToCurrentBuffer(); + // Update the indices on the netty buffer. + buffer.position(bufferPos() + 1); + buffer = null; + pos = 0; + limitMinusOne = 0; + } + } + + private int bufferPos() { + return (int) (pos - bufferOffset); + } + + @Override + public void writeUInt32(int fieldNumber, int value) { + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeInt32(int fieldNumber, int value) { + requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE); + writeInt32(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeSInt32(int fieldNumber, int value) { + requireSpace(MAX_VARINT32_SIZE * 2); + writeSInt32(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeFixed32(int fieldNumber, int value) { + requireSpace(MAX_VARINT32_SIZE + FIXED32_SIZE); + writeFixed32(value); + writeTag(fieldNumber, WIRETYPE_FIXED32); + } + + @Override + public void writeUInt64(int fieldNumber, long value) { + requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE); + writeVarint64(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeSInt64(int fieldNumber, long value) { + requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE); + writeSInt64(value); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeFixed64(int fieldNumber, long value) { + requireSpace(MAX_VARINT32_SIZE + FIXED64_SIZE); + writeFixed64(value); + writeTag(fieldNumber, WIRETYPE_FIXED64); + } + + @Override + public void writeBool(int fieldNumber, boolean value) { + requireSpace(MAX_VARINT32_SIZE + 1); + write((byte) (value ? 1 : 0)); + writeTag(fieldNumber, WIRETYPE_VARINT); + } + + @Override + public void writeString(int fieldNumber, String value) { + int prevBytes = getTotalBytesWritten(); + writeString(value); + int length = getTotalBytesWritten() - prevBytes; + requireSpace(2 * MAX_VARINT32_SIZE); + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeBytes(int fieldNumber, ByteString value) { + try { + value.writeToReverse(this); + } catch (IOException e) { + // Should never happen since the writer does not throw. + throw new RuntimeException(e); + } + + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(value.size()); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeMessage(int fieldNumber, Object value) throws IOException { + int prevBytes = getTotalBytesWritten(); + Protobuf.getInstance().writeTo(value, this); + int length = getTotalBytesWritten() - prevBytes; + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException { + int prevBytes = getTotalBytesWritten(); + schema.writeTo(value, this); + int length = getTotalBytesWritten() - prevBytes; + requireSpace(MAX_VARINT32_SIZE * 2); + writeVarint32(length); + writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + } + + @Override + public void writeGroup(int fieldNumber, Object value) throws IOException { + writeTag(fieldNumber, WIRETYPE_END_GROUP); + Protobuf.getInstance().writeTo(value, this); + writeTag(fieldNumber, WIRETYPE_START_GROUP); + } + + @Override + public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException { + writeTag(fieldNumber, WIRETYPE_END_GROUP); + schema.writeTo(value, this); + writeTag(fieldNumber, WIRETYPE_START_GROUP); + } + + @Override + public void writeStartGroup(int fieldNumber) { + writeTag(fieldNumber, WIRETYPE_START_GROUP); + } + + @Override + public void writeEndGroup(int fieldNumber) { + writeTag(fieldNumber, WIRETYPE_END_GROUP); + } + + @Override + void writeInt32(int value) { + if (value >= 0) { + writeVarint32(value); + } else { + writeVarint64(value); + } + } + + @Override + void writeSInt32(int value) { + writeVarint32(CodedOutputStream.encodeZigZag32(value)); + } + + @Override + void writeSInt64(long value) { + writeVarint64(CodedOutputStream.encodeZigZag64(value)); + } + + @Override + void writeBool(boolean value) { + write((byte) (value ? 1 : 0)); + } + + @Override + void writeTag(int fieldNumber, int wireType) { + writeVarint32(WireFormat.makeTag(fieldNumber, wireType)); + } + + @Override + void writeVarint32(int value) { + if ((value & (~0 << 7)) == 0) { + writeVarint32OneByte(value); + } else if ((value & (~0 << 14)) == 0) { + writeVarint32TwoBytes(value); + } else if ((value & (~0 << 21)) == 0) { + writeVarint32ThreeBytes(value); + } else if ((value & (~0 << 28)) == 0) { + writeVarint32FourBytes(value); + } else { + writeVarint32FiveBytes(value); + } + } + + private void writeVarint32OneByte(int value) { + UnsafeUtil.putByte(pos--, (byte) value); + } + + private void writeVarint32TwoBytes(int value) { + UnsafeUtil.putByte(pos--, (byte) (value >>> 7)); + UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint32ThreeBytes(int value) { + UnsafeUtil.putByte(pos--, (byte) (value >>> 14)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint32FourBytes(int value) { + UnsafeUtil.putByte(pos--, (byte) (value >>> 21)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint32FiveBytes(int value) { + UnsafeUtil.putByte(pos--, (byte) (value >>> 28)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80)); + } + + @Override + void writeVarint64(long value) { + switch (computeUInt64SizeNoTag(value)) { + case 1: + writeVarint64OneByte(value); + break; + case 2: + writeVarint64TwoBytes(value); + break; + case 3: + writeVarint64ThreeBytes(value); + break; + case 4: + writeVarint64FourBytes(value); + break; + case 5: + writeVarint64FiveBytes(value); + break; + case 6: + writeVarint64SixBytes(value); + break; + case 7: + writeVarint64SevenBytes(value); + break; + case 8: + writeVarint64EightBytes(value); + break; + case 9: + writeVarint64NineBytes(value); + break; + case 10: + writeVarint64TenBytes(value); + break; + } + } + + private void writeVarint64OneByte(long value) { + UnsafeUtil.putByte(pos--, (byte) value); + } + + private void writeVarint64TwoBytes(long value) { + UnsafeUtil.putByte(pos--, (byte) (value >>> 7)); + UnsafeUtil.putByte(pos--, (byte) (((int) value & 0x7F) | 0x80)); + } + + private void writeVarint64ThreeBytes(long value) { + UnsafeUtil.putByte(pos--, (byte) (((int) value) >>> 14)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint64FourBytes(long value) { + UnsafeUtil.putByte(pos--, (byte) (value >>> 21)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint64FiveBytes(long value) { + UnsafeUtil.putByte(pos--, (byte) (value >>> 28)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint64SixBytes(long value) { + UnsafeUtil.putByte(pos--, (byte) (value >>> 35)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint64SevenBytes(long value) { + UnsafeUtil.putByte(pos--, (byte) (value >>> 42)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 35) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint64EightBytes(long value) { + UnsafeUtil.putByte(pos--, (byte) (value >>> 49)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 42) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 35) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint64NineBytes(long value) { + UnsafeUtil.putByte(pos--, (byte) (value >>> 56)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 49) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 42) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 35) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80)); + } + + private void writeVarint64TenBytes(long value) { + UnsafeUtil.putByte(pos--, (byte) (value >>> 63)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 56) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 49) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 42) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 35) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80)); + UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80)); + } + + @Override + void writeFixed32(int value) { + UnsafeUtil.putByte(pos--, (byte) ((value >> 24) & 0xFF)); + UnsafeUtil.putByte(pos--, (byte) ((value >> 16) & 0xFF)); + UnsafeUtil.putByte(pos--, (byte) ((value >> 8) & 0xFF)); + UnsafeUtil.putByte(pos--, (byte) (value & 0xFF)); + } + + @Override + void writeFixed64(long value) { + UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 56) & 0xFF)); + UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 48) & 0xFF)); + UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 40) & 0xFF)); + UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 32) & 0xFF)); + UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 24) & 0xFF)); + UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 16) & 0xFF)); + UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 8) & 0xFF)); + UnsafeUtil.putByte(pos--, (byte) ((int) (value) & 0xFF)); + } + + @Override + void writeString(String in) { + // Request enough space to write the ASCII string. + requireSpace(in.length()); + + // We know the buffer is big enough... + int i = in.length() - 1; + // Designed to take advantage of + // https://wiki.openjdk.java.net/display/HotSpotInternals/RangeCheckElimination + for (char c; i >= 0 && (c = in.charAt(i)) < 0x80; i--) { + UnsafeUtil.putByte(pos--, (byte) c); + } + if (i == -1) { + // ASCII. + return; + } + for (char c; i >= 0; i--) { + c = in.charAt(i); + if (c < 0x80 && pos >= bufferOffset) { + UnsafeUtil.putByte(pos--, (byte) c); + } else if (c < 0x800 && pos > bufferOffset) { // 11 bits, two UTF-8 bytes + UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & c))); + UnsafeUtil.putByte(pos--, (byte) ((0xF << 6) | (c >>> 6))); + } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) + && pos > bufferOffset + 1) { + // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes + UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & c))); + UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & (c >>> 6)))); + UnsafeUtil.putByte(pos--, (byte) ((0xF << 5) | (c >>> 12))); + } else if (pos > bufferOffset + 2) { + // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, + // four UTF-8 bytes + final char high; + if (i == 0 || !Character.isSurrogatePair(high = in.charAt(i - 1), c)) { + throw new Utf8.UnpairedSurrogateException(i - 1, i); + } + i--; + int codePoint = Character.toCodePoint(high, c); + UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & codePoint))); + UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & (codePoint >>> 6)))); + UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & (codePoint >>> 12)))); + UnsafeUtil.putByte(pos--, (byte) ((0xF << 4) | (codePoint >>> 18))); + } else { + // Buffer is full - allocate a new one and revisit the current character. + requireSpace(i); + i++; + } + } + } + + @Override + public void write(byte value) { + UnsafeUtil.putByte(pos--, value); + } + + @Override + public void write(byte[] value, int offset, int length) { + if (spaceLeft() < length) { + nextBuffer(length); + } + + pos -= length; + buffer.position(bufferPos() + 1); + buffer.put(value, offset, length); + } + + @Override + public void writeLazy(byte[] value, int offset, int length) { + if (spaceLeft() < length) { + // We consider the value to be immutable (likely the internals of a ByteString). Just + // wrap it in a Netty buffer and add it to the output buffer. + totalDoneBytes += length; + buffers.addFirst(AllocatedBuffer.wrap(value, offset, length)); + + // Advance the writer to the next buffer. + // TODO(nathanmittler): Consider slicing if space available above some threshold. + nextBuffer(); + return; + } + + pos -= length; + buffer.position(bufferPos() + 1); + buffer.put(value, offset, length); + } + + @Override + public void write(ByteBuffer value) { + int length = value.remaining(); + if (spaceLeft() < length) { + nextBuffer(length); + } + + pos -= length; + buffer.position(bufferPos() + 1); + buffer.put(value); + } + + @Override + public void writeLazy(ByteBuffer value) { + int length = value.remaining(); + if (spaceLeft() < length) { + // We consider the value to be immutable (likely the internals of a ByteString). Just + // wrap it in a Netty buffer and add it to the output buffer. + totalDoneBytes += length; + buffers.addFirst(AllocatedBuffer.wrap(value)); + + // Advance the writer to the next buffer. + // TODO(nathanmittler): Consider slicing if space available above some threshold. + nextBuffer(); + return; + } + + pos -= length; + buffer.position(bufferPos() + 1); + buffer.put(value); + } + + @Override + void requireSpace(int size) { + if (spaceLeft() < size) { + nextBuffer(size); + } + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java b/java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java index d535efb9b6c19..8af80057f362a 100644 --- a/java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java +++ b/java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java @@ -31,21 +31,21 @@ package com.google.protobuf; /** - *

Abstract interface for a blocking RPC channel. {@code BlockingRpcChannel} - * is the blocking equivalent to {@link RpcChannel}. + * Abstract interface for a blocking RPC channel. {@code BlockingRpcChannel} is the blocking + * equivalent to {@link RpcChannel}. * * @author kenton@google.com Kenton Varda * @author cpovirk@google.com Chris Povirk */ public interface BlockingRpcChannel { /** - * Call the given method of the remote service and blocks until it returns. - * {@code callBlockingMethod()} is the blocking equivalent to - * {@link RpcChannel#callMethod}. + * Call the given method of the remote service and blocks until it returns. {@code + * callBlockingMethod()} is the blocking equivalent to {@link RpcChannel#callMethod}. */ Message callBlockingMethod( Descriptors.MethodDescriptor method, RpcController controller, Message request, - Message responsePrototype) throws ServiceException; + Message responsePrototype) + throws ServiceException; } diff --git a/java/core/src/main/java/com/google/protobuf/BlockingService.java b/java/core/src/main/java/com/google/protobuf/BlockingService.java index d01f0b8ff0fa3..e2b99c96c3304 100644 --- a/java/core/src/main/java/com/google/protobuf/BlockingService.java +++ b/java/core/src/main/java/com/google/protobuf/BlockingService.java @@ -37,28 +37,21 @@ * @author cpovirk@google.com Chris Povirk */ public interface BlockingService { - /** - * Equivalent to {@link Service#getDescriptorForType}. - */ + /** Equivalent to {@link Service#getDescriptorForType}. */ Descriptors.ServiceDescriptor getDescriptorForType(); /** - * Equivalent to {@link Service#callMethod}, except that - * {@code callBlockingMethod()} returns the result of the RPC or throws a - * {@link ServiceException} if there is a failure, rather than passing the - * information to a callback. + * Equivalent to {@link Service#callMethod}, except that {@code callBlockingMethod()} returns the + * result of the RPC or throws a {@link ServiceException} if there is a failure, rather than + * passing the information to a callback. */ - Message callBlockingMethod(Descriptors.MethodDescriptor method, - RpcController controller, - Message request) throws ServiceException; + Message callBlockingMethod( + Descriptors.MethodDescriptor method, RpcController controller, Message request) + throws ServiceException; - /** - * Equivalent to {@link Service#getRequestPrototype}. - */ + /** Equivalent to {@link Service#getRequestPrototype}. */ Message getRequestPrototype(Descriptors.MethodDescriptor method); - /** - * Equivalent to {@link Service#getResponsePrototype}. - */ + /** Equivalent to {@link Service#getResponsePrototype}. */ Message getResponsePrototype(Descriptors.MethodDescriptor method); } diff --git a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java index fd4c142b33fed..451fce1e84992 100644 --- a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java @@ -45,7 +45,7 @@ final class BooleanArrayList extends AbstractProtobufList implements BooleanList, RandomAccess, PrimitiveNonBoxingCollection { - private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList(); + private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList(new boolean[0], 0); static { EMPTY_LIST.makeImmutable(); } @@ -54,9 +54,7 @@ public static BooleanArrayList emptyList() { return EMPTY_LIST; } - /** - * The backing store for the list. - */ + /** The backing store for the list. */ private boolean[] array; /** @@ -65,22 +63,32 @@ public static BooleanArrayList emptyList() { */ private int size; - /** - * Constructs a new mutable {@code BooleanArrayList} with default capacity. - */ + /** Constructs a new mutable {@code BooleanArrayList} with default capacity. */ BooleanArrayList() { this(new boolean[DEFAULT_CAPACITY], 0); } /** - * Constructs a new mutable {@code BooleanArrayList} - * containing the same elements as {@code other}. + * Constructs a new mutable {@code BooleanArrayList} containing the same elements as {@code + * other}. */ private BooleanArrayList(boolean[] other, int size) { array = other; this.size = size; } + @Override + protected void removeRange(int fromIndex, int toIndex) { + ensureIsMutable(); + if (toIndex < fromIndex) { + throw new IndexOutOfBoundsException("toIndex < fromIndex"); + } + + System.arraycopy(array, toIndex, array, fromIndex, size - toIndex); + size -= (toIndex - fromIndex); + modCount++; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -132,6 +140,26 @@ public boolean getBoolean(int index) { return array[index]; } + @Override + public int indexOf(Object element) { + if (!(element instanceof Boolean)) { + return -1; + } + boolean unboxedElement = (Boolean) element; + int numElems = size(); + for (int i = 0; i < numElems; i++) { + if (array[i] == unboxedElement) { + return i; + } + } + return -1; + } + + @Override + public boolean contains(Object element) { + return indexOf(element) != -1; + } + @Override public int size() { return size; @@ -151,22 +179,34 @@ public boolean setBoolean(int index, boolean element) { return previousValue; } + @Override + public boolean add(Boolean element) { + addBoolean(element); + return true; + } + @Override public void add(int index, Boolean element) { addBoolean(index, element); } - /** - * Like {@link #add(Boolean)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(Boolean)} but more efficient in that it doesn't box the element. */ @Override public void addBoolean(boolean element) { - addBoolean(size, element); + ensureIsMutable(); + if (size == array.length) { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + boolean[] newArray = new boolean[length]; + + System.arraycopy(array, 0, newArray, 0, size); + array = newArray; + } + + array[size++] = element; } - /** - * Like {@link #add(int, Boolean)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(int, Boolean)} but more efficient in that it doesn't box the element. */ private void addBoolean(int index, boolean element) { ensureIsMutable(); if (index < 0 || index > size) { @@ -227,26 +267,14 @@ public boolean addAll(Collection collection) { return true; } - @Override - public boolean remove(Object o) { - ensureIsMutable(); - for (int i = 0; i < size; i++) { - if (o.equals(array[i])) { - System.arraycopy(array, i + 1, array, i, size - i); - size--; - modCount++; - return true; - } - } - return false; - } - @Override public Boolean remove(int index) { ensureIsMutable(); ensureIndexInRange(index); boolean value = array[index]; - System.arraycopy(array, index + 1, array, index, size - index); + if (index < size - 1) { + System.arraycopy(array, index + 1, array, index, size - index - 1); + } size--; modCount++; return value; diff --git a/java/core/src/main/java/com/google/protobuf/BufferAllocator.java b/java/core/src/main/java/com/google/protobuf/BufferAllocator.java new file mode 100644 index 0000000000000..bfd9c7237c0e2 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/BufferAllocator.java @@ -0,0 +1,64 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.nio.ByteBuffer; + +/** + * An object responsible for allocation of buffers. This is an extension point to enable buffer + * pooling within an application. + */ +@ExperimentalApi +abstract class BufferAllocator { + private static final BufferAllocator UNPOOLED = + new BufferAllocator() { + @Override + public AllocatedBuffer allocateHeapBuffer(int capacity) { + return AllocatedBuffer.wrap(new byte[capacity]); + } + + @Override + public AllocatedBuffer allocateDirectBuffer(int capacity) { + return AllocatedBuffer.wrap(ByteBuffer.allocateDirect(capacity)); + } + }; + + /** Returns an unpooled buffer allocator, which will create a new buffer for each request. */ + public static BufferAllocator unpooled() { + return UNPOOLED; + } + + /** Allocates a buffer with the given capacity that is backed by an array on the heap. */ + public abstract AllocatedBuffer allocateHeapBuffer(int capacity); + + /** Allocates a direct (i.e. non-heap) buffer with the given capacity. */ + public abstract AllocatedBuffer allocateDirectBuffer(int capacity); +} diff --git a/java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java b/java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java index 6157a52f50f58..2cb3ada67fb6b 100644 --- a/java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java +++ b/java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java @@ -40,45 +40,40 @@ import java.nio.ByteBuffer; import java.nio.channels.WritableByteChannel; -/** - * Utility class to provide efficient writing of {@link ByteBuffer}s to {@link OutputStream}s. - */ +/** Utility class to provide efficient writing of {@link ByteBuffer}s to {@link OutputStream}s. */ final class ByteBufferWriter { private ByteBufferWriter() {} /** - * Minimum size for a cached buffer. This prevents us from allocating buffers that are too - * small to be easily reused. + * Minimum size for a cached buffer. This prevents us from allocating buffers that are too small + * to be easily reused. */ // TODO(nathanmittler): tune this property or allow configuration? private static final int MIN_CACHED_BUFFER_SIZE = 1024; /** - * Maximum size for a cached buffer. If a larger buffer is required, it will be allocated - * but not cached. + * Maximum size for a cached buffer. If a larger buffer is required, it will be allocated but not + * cached. */ // TODO(nathanmittler): tune this property or allow configuration? private static final int MAX_CACHED_BUFFER_SIZE = 16 * 1024; - /** - * The fraction of the requested buffer size under which the buffer will be reallocated. - */ + /** The fraction of the requested buffer size under which the buffer will be reallocated. */ // TODO(nathanmittler): tune this property or allow configuration? private static final float BUFFER_REALLOCATION_THRESHOLD = 0.5f; /** - * Keeping a soft reference to a thread-local buffer. This buffer is used for writing a - * {@link ByteBuffer} to an {@link OutputStream} when no zero-copy alternative was available. - * Using a "soft" reference since VMs may keep this reference around longer than "weak" - * (e.g. HotSpot will maintain soft references until memory pressure warrants collection). + * Keeping a soft reference to a thread-local buffer. This buffer is used for writing a {@link + * ByteBuffer} to an {@link OutputStream} when no zero-copy alternative was available. Using a + * "soft" reference since VMs may keep this reference around longer than "weak" (e.g. HotSpot will + * maintain soft references until memory pressure warrants collection). */ private static final ThreadLocal> BUFFER = new ThreadLocal>(); - /** - * This is a hack for GAE, where {@code FileOutputStream} is unavailable. - */ + /** This is a hack for GAE, where {@code FileOutputStream} is unavailable. */ private static final Class FILE_OUTPUT_STREAM_CLASS = safeGetClass("java.io.FileOutputStream"); + private static final long CHANNEL_FIELD_OFFSET = getChannelFieldOffset(FILE_OUTPUT_STREAM_CLASS); /** @@ -100,7 +95,7 @@ static void write(ByteBuffer buffer, OutputStream output) throws IOException { // Optimized write for array-backed buffers. // Note that we're taking the risk that a malicious OutputStream could modify the array. output.write(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining()); - } else if (!writeToChannel(buffer, output)){ + } else if (!writeToChannel(buffer, output)) { // Read all of the data from the buffer to an array. // TODO(nathanmittler): Consider performance improvements for other "known" stream types. final byte[] array = getOrCreateBuffer(buffer.remaining()); @@ -171,6 +166,7 @@ private static Class safeGetClass(String className) { return null; } } + private static long getChannelFieldOffset(Class clazz) { try { if (clazz != null && UnsafeUtil.hasUnsafeArrayOperations()) { diff --git a/java/core/src/main/java/com/google/protobuf/ByteOutput.java b/java/core/src/main/java/com/google/protobuf/ByteOutput.java index ee5887538f58f..dba7a379f8f33 100644 --- a/java/core/src/main/java/com/google/protobuf/ByteOutput.java +++ b/java/core/src/main/java/com/google/protobuf/ByteOutput.java @@ -37,9 +37,9 @@ * An output target for raw bytes. This interface provides semantics that support two types of * writing: * - *

Traditional write operations: - * (as defined by {@link java.io.OutputStream}) where the target method is responsible for either - * copying the data or completing the write before returning from the method call. + *

Traditional write operations: (as defined by {@link java.io.OutputStream}) where the + * target method is responsible for either copying the data or completing the write before returning + * from the method call. * *

Lazy write operations: where the caller guarantees that it will never modify the * provided buffer and it can therefore be considered immutable. The target method is free to @@ -57,9 +57,9 @@ public abstract class ByteOutput { public abstract void write(byte value) throws IOException; /** - * Writes a sequence of bytes. The {@link ByteOutput} must copy {@code value} if it will - * not be processed prior to the return of this method call, since {@code value} may be - * reused/altered by the caller. + * Writes a sequence of bytes. The {@link ByteOutput} must copy {@code value} if it will not be + * processed prior to the return of this method call, since {@code value} may be reused/altered by + * the caller. * *

NOTE: This method MUST NOT modify the {@code value}. Doing so is a * programming error and will lead to data corruption which will be difficult to debug. @@ -87,15 +87,15 @@ public abstract class ByteOutput { public abstract void writeLazy(byte[] value, int offset, int length) throws IOException; /** - * Writes a sequence of bytes. The {@link ByteOutput} must copy {@code value} if it will - * not be processed prior to the return of this method call, since {@code value} may be - * reused/altered by the caller. + * Writes a sequence of bytes. The {@link ByteOutput} must copy {@code value} if it will not be + * processed prior to the return of this method call, since {@code value} may be reused/altered by + * the caller. * *

NOTE: This method MUST NOT modify the {@code value}. Doing so is a * programming error and will lead to data corruption which will be difficult to debug. * * @param value the bytes to be written. Upon returning from this call, the {@code position} of - * this buffer will be set to the {@code limit} + * this buffer will be set to the {@code limit} * @throws IOException thrown if an error occurred while writing */ public abstract void write(ByteBuffer value) throws IOException; @@ -109,7 +109,7 @@ public abstract class ByteOutput { * programming error and will lead to data corruption which will be difficult to debug. * * @param value the bytes to be written. Upon returning from this call, the {@code position} of - * this buffer will be set to the {@code limit} + * this buffer will be set to the {@code limit} * @throws IOException thrown if an error occurred while writing */ public abstract void writeLazy(ByteBuffer value) throws IOException; 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 99a312096d877..17b7c98c99dda 100644 --- a/java/core/src/main/java/com/google/protobuf/ByteString.java +++ b/java/core/src/main/java/com/google/protobuf/ByteString.java @@ -30,6 +30,10 @@ package com.google.protobuf; +import static com.google.protobuf.TextFormatEscaper.escapeBytes; +import static java.lang.Integer.toHexString; +import static java.lang.System.identityHashCode; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -46,18 +50,24 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.NoSuchElementException; /** - * Immutable sequence of bytes. Substring is supported by sharing the reference to the immutable - * underlying bytes. Concatenation is likewise supported without copying (long strings) by building - * a tree of pieces in {@link RopeByteString}. + * Immutable sequence of bytes. Provides conversions to and from {@code byte[]}, {@link + * java.lang.String}, {@link ByteBuffer}, {@link InputStream}, {@link OutputStream}. Also provides a + * conversion to {@link CodedInputStream}. * *

Like {@link String}, the contents of a {@link ByteString} can never be observed to change, not * even in the presence of a data race or incorrect API usage in the client code. * + *

Substring is supported by sharing the reference to the immutable underlying bytes. + * Concatenation is likewise supported without copying (long strings) by building a tree of pieces + * in {@link RopeByteString}. + * * @author crazybob@google.com Bob Lee * @author kenton@google.com Kenton Varda * @author carlanton@google.com Carl Haverl @@ -66,41 +76,36 @@ public abstract class ByteString implements Iterable, Serializable { /** - * When two strings to be concatenated have a combined length shorter than - * this, we just copy their bytes on {@link #concat(ByteString)}. - * The trade-off is copy size versus the overhead of creating tree nodes - * in {@link RopeByteString}. + * When two strings to be concatenated have a combined length shorter than this, we just copy + * their bytes on {@link #concat(ByteString)}. The trade-off is copy size versus the overhead of + * creating tree nodes in {@link RopeByteString}. */ static final int CONCATENATE_BY_COPY_SIZE = 128; /** - * When copying an InputStream into a ByteString with .readFrom(), - * the chunks in the underlying rope start at 256 bytes, but double - * each iteration up to 8192 bytes. + * When copying an InputStream into a ByteString with .readFrom(), the chunks in the underlying + * rope start at 256 bytes, but double each iteration up to 8192 bytes. */ - static final int MIN_READ_FROM_CHUNK_SIZE = 0x100; // 256b - static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000; // 8k + static final int MIN_READ_FROM_CHUNK_SIZE = 0x100; // 256b - /** - * Empty {@code ByteString}. - */ + static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000; // 8k + + /** Empty {@code ByteString}. */ public static final ByteString EMPTY = new LiteralByteString(Internal.EMPTY_BYTE_ARRAY); /** * An interface to efficiently copy {@code byte[]}. * - *

One of the noticeable costs of copying a byte[] into a new array using - * {@code System.arraycopy} is nullification of a new buffer before the copy. It has been shown - * the Hotspot VM is capable to intrisicfy {@code Arrays.copyOfRange} operation to avoid this + *

One of the noticeable costs of copying a byte[] into a new array using {@code + * System.arraycopy} is nullification of a new buffer before the copy. It has been shown the + * Hotspot VM is capable to intrisicfy {@code Arrays.copyOfRange} operation to avoid this * expensive nullification and provide substantial performance gain. Unfortunately this does not - * hold on Android runtimes and could make the copy slightly slower due to additional code in - * the {@code Arrays.copyOfRange}. Thus we provide two different implementation for array copier - * for Hotspot and Android runtimes. + * hold on Android runtimes and could make the copy slightly slower due to additional code in the + * {@code Arrays.copyOfRange}. Thus we provide two different implementation for array copier for + * Hotspot and Android runtimes. */ private interface ByteArrayCopier { - /** - * Copies the specified range of the specified array into a new array - */ + /** Copies the specified range of the specified array into a new array */ byte[] copyFrom(byte[] bytes, int offset, int size); } @@ -123,21 +128,16 @@ public byte[] copyFrom(byte[] bytes, int offset, int size) { } private static final ByteArrayCopier byteArrayCopier; - static { - boolean isAndroid = true; - try { - Class.forName("android.content.Context"); - } catch (ClassNotFoundException e) { - isAndroid = false; - } - byteArrayCopier = isAndroid ? new SystemByteArrayCopier() : new ArraysByteArrayCopier(); + static { + byteArrayCopier = + Android.isOnAndroidDevice() ? new SystemByteArrayCopier() : new ArraysByteArrayCopier(); } /** - * Cached hash value. Intentionally accessed via a data race, which - * is safe because of the Java Memory Model's "no out-of-thin-air values" - * guarantees for ints. A value of 0 implies that the hash has not been set. + * Cached hash value. Intentionally accessed via a data race, which is safe because of the Java + * Memory Model's "no out-of-thin-air values" guarantees for ints. A value of 0 implies that the + * hash has not been set. */ private int hash = 0; @@ -145,10 +145,9 @@ public byte[] copyFrom(byte[] bytes, int offset, int size) { ByteString() {} /** - * Gets the byte at the given index. This method should be used only for - * random access to individual bytes. To access bytes sequentially, use the - * {@link ByteIterator} returned by {@link #iterator()}, and call {@link - * #substring(int, int)} first if necessary. + * Gets the byte at the given index. This method should be used only for random access to + * individual bytes. To access bytes sequentially, use the {@link ByteIterator} returned by {@link + * #iterator()}, and call {@link #substring(int, int)} first if necessary. * * @param index index of byte * @return the value @@ -157,15 +156,23 @@ public byte[] copyFrom(byte[] bytes, int offset, int size) { public abstract byte byteAt(int index); /** - * Return a {@link ByteString.ByteIterator} over the bytes in the ByteString. - * To avoid auto-boxing, you may get the iterator manually and call - * {@link ByteIterator#nextByte()}. + * Gets the byte at the given index, assumes bounds checking has already been performed. + * + * @param index index of byte + * @return the value + * @throws IndexOutOfBoundsException {@code index < 0 or index >= size} + */ + abstract byte internalByteAt(int index); + + /** + * Return a {@link ByteString.ByteIterator} over the bytes in the ByteString. To avoid + * auto-boxing, you may get the iterator manually and call {@link ByteIterator#nextByte()}. * * @return the iterator */ @Override - public final ByteIterator iterator() { - return new ByteIterator() { + public ByteIterator iterator() { + return new AbstractByteIterator() { private int position = 0; private final int limit = size(); @@ -174,36 +181,24 @@ public boolean hasNext() { return position < limit; } - @Override - public Byte next() { - // Boxing calls Byte.valueOf(byte), which does not instantiate. - return nextByte(); - } - @Override public byte nextByte() { - try { - return byteAt(position++); - } catch (IndexOutOfBoundsException e) { - throw new NoSuchElementException(e.getMessage()); + int currentPos = position; + if (currentPos >= limit) { + throw new NoSuchElementException(); } - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); + position = currentPos + 1; + return internalByteAt(currentPos); } }; } /** - * This interface extends {@code Iterator}, so that we can return an - * unboxed {@code byte}. + * This interface extends {@code Iterator}, so that we can return an unboxed {@code byte}. */ public interface ByteIterator extends Iterator { /** - * An alternative to {@link Iterator#next()} that returns an - * unboxed primitive {@code byte}. + * An alternative to {@link Iterator#next()} that returns an unboxed primitive {@code byte}. * * @return the next {@code byte} in the iteration * @throws NoSuchElementException if the iteration has no more elements @@ -211,6 +206,19 @@ public interface ByteIterator extends Iterator { byte nextByte(); } + abstract static class AbstractByteIterator implements ByteIterator { + @Override + public final Byte next() { + // Boxing calls Byte.valueOf(byte), which does not instantiate. + return nextByte(); + } + + @Override + public final void remove() { + throw new UnsupportedOperationException(); + } + } + /** * Gets the number of bytes. * @@ -227,60 +235,114 @@ public final boolean isEmpty() { return size() == 0; } + // ================================================================= + // Comparison + + private static final int UNSIGNED_BYTE_MASK = 0xFF; + + /** + * Returns the value of the given byte as an integer, interpreting the byte as an unsigned value. + * That is, returns {@code value + 256} if {@code value} is negative; {@code value} itself + * otherwise. + * + *

Note: This code was copied from {@link com.google.common.primitives.UnsignedBytes#toInt}, as + * Guava libraries cannot be used in the {@code com.google.protobuf} package. + */ + private static int toInt(byte value) { + return value & UNSIGNED_BYTE_MASK; + } + + /** + * Compares two {@link ByteString}s lexicographically, treating their contents as unsigned byte + * values between 0 and 255 (inclusive). + * + *

For example, {@code (byte) -1} is considered to be greater than {@code (byte) 1} because it + * is interpreted as an unsigned value, {@code 255}. + */ + private static final Comparator UNSIGNED_LEXICOGRAPHICAL_COMPARATOR = + new Comparator() { + @Override + public int compare(ByteString former, ByteString latter) { + ByteIterator formerBytes = former.iterator(); + ByteIterator latterBytes = latter.iterator(); + + while (formerBytes.hasNext() && latterBytes.hasNext()) { + // Note: This code was copied from com.google.common.primitives.UnsignedBytes#compare, + // as Guava libraries cannot be used in the {@code com.google.protobuf} package. + int result = + Integer.compare(toInt(formerBytes.nextByte()), toInt(latterBytes.nextByte())); + if (result != 0) { + return result; + } + } + + return Integer.compare(former.size(), latter.size()); + } + }; + + /** + * Returns a {@link Comparator} which compares {@link ByteString}-s lexicographically + * as sequences of unsigned bytes (i.e. values between 0 and 255, inclusive). + * + *

For example, {@code (byte) -1} is considered to be greater than {@code (byte) 1} because it + * is interpreted as an unsigned value, {@code 255}: + * + *

    + *
  • {@code `-1` -> 0b11111111 (two's complement) -> 255} + *
  • {@code `1` -> 0b00000001 -> 1} + *
+ */ + public static Comparator unsignedLexicographicalComparator() { + return UNSIGNED_LEXICOGRAPHICAL_COMPARATOR; + } + // ================================================================= // ByteString -> substring /** - * Return the substring from {@code beginIndex}, inclusive, to the end of the - * string. + * Return the substring from {@code beginIndex}, inclusive, to the end of the string. * * @param beginIndex start at this index * @return substring sharing underlying data - * @throws IndexOutOfBoundsException if {@code beginIndex < 0} or - * {@code beginIndex > size()}. + * @throws IndexOutOfBoundsException if {@code beginIndex < 0} or {@code beginIndex > size()}. */ public final ByteString substring(int beginIndex) { return substring(beginIndex, size()); } /** - * Return the substring from {@code beginIndex}, inclusive, to {@code - * endIndex}, exclusive. + * Return the substring from {@code beginIndex}, inclusive, to {@code endIndex}, exclusive. * * @param beginIndex start at this index - * @param endIndex the last character is the one before this index + * @param endIndex the last character is the one before this index * @return substring sharing underlying data - * @throws IndexOutOfBoundsException if {@code beginIndex < 0}, - * {@code endIndex > size()}, or {@code beginIndex > endIndex}. + * @throws IndexOutOfBoundsException if {@code beginIndex < 0}, {@code endIndex > size()}, or + * {@code beginIndex > endIndex}. */ public abstract ByteString substring(int beginIndex, int endIndex); /** - * Tests if this bytestring starts with the specified prefix. - * Similar to {@link String#startsWith(String)} + * Tests if this bytestring starts with the specified prefix. Similar to {@link + * String#startsWith(String)} * * @param prefix the prefix. - * @return true if the byte sequence represented by the - * argument is a prefix of the byte sequence represented by - * this string; false otherwise. + * @return true if the byte sequence represented by the argument is a prefix of the + * byte sequence represented by this string; false otherwise. */ public final boolean startsWith(ByteString prefix) { - return size() >= prefix.size() && - substring(0, prefix.size()).equals(prefix); + return size() >= prefix.size() && substring(0, prefix.size()).equals(prefix); } /** - * Tests if this bytestring ends with the specified suffix. - * Similar to {@link String#endsWith(String)} + * Tests if this bytestring ends with the specified suffix. Similar to {@link + * String#endsWith(String)} * * @param suffix the suffix. - * @return true if the byte sequence represented by the - * argument is a suffix of the byte sequence represented by - * this string; false otherwise. + * @return true if the byte sequence represented by the argument is a suffix of the + * byte sequence represented by this string; false otherwise. */ public final boolean endsWith(ByteString suffix) { - return size() >= suffix.size() && - substring(size() - suffix.size()).equals(suffix); + return size() >= suffix.size() && substring(size() - suffix.size()).equals(suffix); } // ================================================================= @@ -293,8 +355,10 @@ public final boolean endsWith(ByteString suffix) { * @param offset offset in source array * @param size number of bytes to copy * @return new {@code ByteString} + * @throws IndexOutOfBoundsException if {@code offset} or {@code size} are out of bounds */ public static ByteString copyFrom(byte[] bytes, int offset, int size) { + checkRange(offset, offset + size, bytes.length); return new LiteralByteString(byteArrayCopier.copyFrom(bytes, offset, size)); } @@ -308,9 +372,7 @@ public static ByteString copyFrom(byte[] bytes) { return copyFrom(bytes, 0, bytes.length); } - /** - * Wraps the given bytes into a {@code ByteString}. Intended for internal only usage. - */ + /** Wraps the given bytes into a {@code ByteString}. Intended for internal only usage. */ static ByteString wrap(ByteBuffer buffer) { if (buffer.hasArray()) { final int offset = buffer.arrayOffset(); @@ -321,8 +383,8 @@ static ByteString wrap(ByteBuffer buffer) { } /** - * Wraps the given bytes into a {@code ByteString}. Intended for internal only - * usage to force a classload of ByteString before LiteralByteString. + * Wraps the given bytes into a {@code ByteString}. Intended for internal only usage to force a + * classload of ByteString before LiteralByteString. */ static ByteString wrap(byte[] bytes) { // TODO(dweis): Return EMPTY when bytes are empty to reduce allocations? @@ -330,31 +392,31 @@ static ByteString wrap(byte[] bytes) { } /** - * Wraps the given bytes into a {@code ByteString}. Intended for internal only - * usage to force a classload of ByteString before BoundedByteString and - * LiteralByteString. + * Wraps the given bytes into a {@code ByteString}. Intended for internal only usage to force a + * classload of ByteString before BoundedByteString and LiteralByteString. */ static ByteString wrap(byte[] bytes, int offset, int length) { return new BoundedByteString(bytes, offset, length); } /** - * Copies the next {@code size} bytes from a {@code java.nio.ByteBuffer} into - * a {@code ByteString}. + * Copies the next {@code size} bytes from a {@code java.nio.ByteBuffer} into a {@code + * ByteString}. * * @param bytes source buffer * @param size number of bytes to copy * @return new {@code ByteString} + * @throws IndexOutOfBoundsException if {@code size > bytes.remaining()} */ public static ByteString copyFrom(ByteBuffer bytes, int size) { + checkRange(0, size, bytes.remaining()); byte[] copy = new byte[size]; bytes.get(copy); return new LiteralByteString(copy); } /** - * Copies the remaining bytes from a {@code java.nio.ByteBuffer} into - * a {@code ByteString}. + * Copies the remaining bytes from a {@code java.nio.ByteBuffer} into a {@code ByteString}. * * @param bytes sourceBuffer * @return new {@code ByteString} @@ -364,8 +426,8 @@ public static ByteString copyFrom(ByteBuffer bytes) { } /** - * Encodes {@code text} into a sequence of bytes using the named charset - * and returns the result as a {@code ByteString}. + * Encodes {@code text} into a sequence of bytes using the named charset and returns the result as + * a {@code ByteString}. * * @param text source string * @param charsetName encoding to use @@ -378,8 +440,8 @@ public static ByteString copyFrom(String text, String charsetName) } /** - * Encodes {@code text} into a sequence of bytes using the named charset - * and returns the result as a {@code ByteString}. + * Encodes {@code text} into a sequence of bytes using the named charset and returns the result as + * a {@code ByteString}. * * @param text source string * @param charset encode using this charset @@ -390,8 +452,8 @@ public static ByteString copyFrom(String text, Charset charset) { } /** - * Encodes {@code text} into a sequence of UTF-8 bytes and returns the - * result as a {@code ByteString}. + * Encodes {@code text} into a sequence of UTF-8 bytes and returns the result as a {@code + * ByteString}. * * @param text source string * @return new {@code ByteString} @@ -404,60 +466,48 @@ public static ByteString copyFromUtf8(String text) { // InputStream -> ByteString /** - * Completely reads the given stream's bytes into a - * {@code ByteString}, blocking if necessary until all bytes are - * read through to the end of the stream. + * Completely reads the given stream's bytes into a {@code ByteString}, blocking if necessary + * until all bytes are read through to the end of the stream. * - * Performance notes: The returned {@code ByteString} is an - * immutable tree of byte arrays ("chunks") of the stream data. The - * first chunk is small, with subsequent chunks each being double - * the size, up to 8K. + *

Performance notes: The returned {@code ByteString} is an immutable tree of byte + * arrays ("chunks") of the stream data. The first chunk is small, with subsequent chunks each + * being double the size, up to 8K. * - *

Each byte read from the input stream will be copied twice to ensure - * that the resulting ByteString is truly immutable. + *

Each byte read from the input stream will be copied twice to ensure that the resulting + * ByteString is truly immutable. * - * @param streamToDrain The source stream, which is read completely - * but not closed. - * @return A new {@code ByteString} which is made up of chunks of - * various sizes, depending on the behavior of the underlying - * stream. - * @throws IOException IOException is thrown if there is a problem - * reading the underlying stream. + * @param streamToDrain The source stream, which is read completely but not closed. + * @return A new {@code ByteString} which is made up of chunks of various sizes, depending on the + * behavior of the underlying stream. + * @throws IOException IOException is thrown if there is a problem reading the underlying stream. */ - public static ByteString readFrom(InputStream streamToDrain) - throws IOException { + public static ByteString readFrom(InputStream streamToDrain) throws IOException { return readFrom(streamToDrain, MIN_READ_FROM_CHUNK_SIZE, MAX_READ_FROM_CHUNK_SIZE); } /** - * Completely reads the given stream's bytes into a - * {@code ByteString}, blocking if necessary until all bytes are - * read through to the end of the stream. + * Completely reads the given stream's bytes into a {@code ByteString}, blocking if necessary + * until all bytes are read through to the end of the stream. * - * Performance notes: The returned {@code ByteString} is an - * immutable tree of byte arrays ("chunks") of the stream data. The - * chunkSize parameter sets the size of these byte arrays. + *

Performance notes: The returned {@code ByteString} is an immutable tree of byte + * arrays ("chunks") of the stream data. The chunkSize parameter sets the size of these byte + * arrays. * - *

Each byte read from the input stream will be copied twice to ensure - * that the resulting ByteString is truly immutable. + *

Each byte read from the input stream will be copied twice to ensure that the resulting + * ByteString is truly immutable. * - * @param streamToDrain The source stream, which is read completely - * but not closed. - * @param chunkSize The size of the chunks in which to read the - * stream. - * @return A new {@code ByteString} which is made up of chunks of - * the given size. - * @throws IOException IOException is thrown if there is a problem - * reading the underlying stream. + * @param streamToDrain The source stream, which is read completely but not closed. + * @param chunkSize The size of the chunks in which to read the stream. + * @return A new {@code ByteString} which is made up of chunks of the given size. + * @throws IOException IOException is thrown if there is a problem reading the underlying stream. */ - public static ByteString readFrom(InputStream streamToDrain, int chunkSize) - throws IOException { + public static ByteString readFrom(InputStream streamToDrain, int chunkSize) throws IOException { return readFrom(streamToDrain, chunkSize, chunkSize); } // Helper method that takes the chunk size range as a parameter. - public static ByteString readFrom(InputStream streamToDrain, int minChunkSize, - int maxChunkSize) throws IOException { + public static ByteString readFrom(InputStream streamToDrain, int minChunkSize, int maxChunkSize) + throws IOException { Collection results = new ArrayList(); // copy the inbound bytes into a list of chunks; the chunk size @@ -476,42 +526,39 @@ public static ByteString readFrom(InputStream streamToDrain, int minChunkSize, } /** - * Blocks until a chunk of the given size can be made from the - * stream, or EOF is reached. Calls read() repeatedly in case the - * given stream implementation doesn't completely fill the given + * Blocks until a chunk of the given size can be made from the stream, or EOF is reached. Calls + * read() repeatedly in case the given stream implementation doesn't completely fill the given * buffer in one read() call. * - * @return A chunk of the desired size, or else a chunk as large as - * was available when end of stream was reached. Returns null if the - * given stream had no more data in it. + * @return A chunk of the desired size, or else a chunk as large as was available when end of + * stream was reached. Returns null if the given stream had no more data in it. */ - private static ByteString readChunk(InputStream in, final int chunkSize) - throws IOException { - final byte[] buf = new byte[chunkSize]; - int bytesRead = 0; - while (bytesRead < chunkSize) { - final int count = in.read(buf, bytesRead, chunkSize - bytesRead); - if (count == -1) { - break; - } - bytesRead += count; + private static ByteString readChunk(InputStream in, final int chunkSize) throws IOException { + final byte[] buf = new byte[chunkSize]; + int bytesRead = 0; + while (bytesRead < chunkSize) { + final int count = in.read(buf, bytesRead, chunkSize - bytesRead); + if (count == -1) { + break; } + bytesRead += count; + } - if (bytesRead == 0) { - return null; - } + if (bytesRead == 0) { + return null; + } - // Always make a copy since InputStream could steal a reference to buf. - return ByteString.copyFrom(buf, 0, bytesRead); + // Always make a copy since InputStream could steal a reference to buf. + return ByteString.copyFrom(buf, 0, bytesRead); } // ================================================================= // Multiple ByteStrings -> One ByteString /** - * Concatenate the given {@code ByteString} to this one. Short concatenations, - * of total size smaller than {@link ByteString#CONCATENATE_BY_COPY_SIZE}, are - * produced by copying the underlying bytes (as per Rope.java, * BAP95 . In general, the concatenate involves no copying. * @@ -520,21 +567,20 @@ private static ByteString readChunk(InputStream in, final int chunkSize) */ public final ByteString concat(ByteString other) { if (Integer.MAX_VALUE - size() < other.size()) { - throw new IllegalArgumentException("ByteString would be too long: " + - size() + "+" + other.size()); + throw new IllegalArgumentException( + "ByteString would be too long: " + size() + "+" + other.size()); } return RopeByteString.concatenate(this, other); } /** - * Concatenates all byte strings in the iterable and returns the result. - * This is designed to run in O(list size), not O(total bytes). + * Concatenates all byte strings in the iterable and returns the result. This is designed to run + * in O(list size), not O(total bytes). * - *

The returned {@code ByteString} is not necessarily a unique object. - * If the list is empty, the returned object is the singleton empty - * {@code ByteString}. If the list has only one element, that - * {@code ByteString} will be returned without copying. + *

The returned {@code ByteString} is not necessarily a unique object. If the list is empty, + * the returned object is the singleton empty {@code ByteString}. If the list has only one + * element, that {@code ByteString} will be returned without copying. * * @param byteStrings strings to be concatenated * @return new {@code ByteString} @@ -544,9 +590,9 @@ public static ByteString copyFrom(Iterable byteStrings) { final int size; if (!(byteStrings instanceof Collection)) { int tempSize = 0; - for (Iterator iter = byteStrings.iterator(); iter.hasNext(); - iter.next(), ++tempSize) { - } + for (Iterator iter = byteStrings.iterator(); + iter.hasNext(); + iter.next(), ++tempSize) {} size = tempSize; } else { size = ((Collection) byteStrings).size(); @@ -584,6 +630,9 @@ private static ByteString balancedConcat(Iterator iterator, int leng /** * Copies bytes into a buffer at the given offset. * + *

To copy a subset of bytes, you call this method on the return value of {@link + * #substring(int, int)}. Example: {@code byteString.substring(start, end).copyTo(target, offset)} + * * @param target buffer to copy into * @param offset in the target buffer * @throws IndexOutOfBoundsException if the offset is negative or too large @@ -595,15 +644,16 @@ public void copyTo(byte[] target, int offset) { /** * Copies bytes into a buffer. * - * @param target buffer to copy into + * @param target buffer to copy into * @param sourceOffset offset within these bytes * @param targetOffset offset within the target buffer * @param numberToCopy number of bytes to copy - * @throws IndexOutOfBoundsException if an offset or size is negative or too - * large + * @throws IndexOutOfBoundsException if an offset or size is negative or too large + * @deprecated Instead, call {@code byteString.substring(sourceOffset, sourceOffset + + * numberToCopy).copyTo(target, targetOffset)} */ - public final void copyTo(byte[] target, int sourceOffset, int targetOffset, - int numberToCopy) { + @Deprecated + public final void copyTo(byte[] target, int sourceOffset, int targetOffset, int numberToCopy) { checkRange(sourceOffset, sourceOffset + numberToCopy, size()); checkRange(targetOffset, targetOffset + numberToCopy, target.length); if (numberToCopy > 0) { @@ -612,21 +662,22 @@ public final void copyTo(byte[] target, int sourceOffset, int targetOffset, } /** - * Internal (package private) implementation of - * {@link #copyTo(byte[],int,int,int)}. - * It assumes that all error checking has already been performed and that - * {@code numberToCopy > 0}. + * Internal (package private) implementation of {@link #copyTo(byte[],int,int,int)}. It assumes + * that all error checking has already been performed and that {@code numberToCopy > 0}. */ - protected abstract void copyToInternal(byte[] target, int sourceOffset, - int targetOffset, int numberToCopy); + protected abstract void copyToInternal( + byte[] target, int sourceOffset, int targetOffset, int numberToCopy); /** * Copies bytes into a ByteBuffer. * + *

To copy a subset of bytes, you call this method on the return value of {@link + * #substring(int, int)}. Example: {@code byteString.substring(start, end).copyTo(target)} + * * @param target ByteBuffer to copy into. * @throws java.nio.ReadOnlyBufferException if the {@code target} is read-only - * @throws java.nio.BufferOverflowException if the {@code target}'s - * remaining() space is not large enough to hold the data. + * @throws java.nio.BufferOverflowException if the {@code target}'s remaining() space is not large + * enough to hold the data. */ public abstract void copyTo(ByteBuffer target); @@ -648,22 +699,21 @@ public final byte[] toByteArray() { /** * Writes a copy of the contents of this byte string to the specified output stream argument. * - * @param out the output stream to which to write the data. - * @throws IOException if an I/O error occurs. + * @param out the output stream to which to write the data. + * @throws IOException if an I/O error occurs. */ public abstract void writeTo(OutputStream out) throws IOException; /** * Writes a specified part of this byte string to an output stream. * - * @param out the output stream to which to write the data. - * @param sourceOffset offset within these bytes - * @param numberToWrite number of bytes to write - * @throws IOException if an I/O error occurs. + * @param out the output stream to which to write the data. + * @param sourceOffset offset within these bytes + * @param numberToWrite number of bytes to write + * @throws IOException if an I/O error occurs. * @throws IndexOutOfBoundsException if an offset or size is negative or too large */ - final void writeTo(OutputStream out, int sourceOffset, int numberToWrite) - throws IOException { + final void writeTo(OutputStream out, int sourceOffset, int numberToWrite) throws IOException { checkRange(sourceOffset, sourceOffset + numberToWrite, size()); if (numberToWrite > 0) { writeToInternal(out, sourceOffset, numberToWrite); @@ -671,59 +721,65 @@ final void writeTo(OutputStream out, int sourceOffset, int numberToWrite) } /** - * Internal version of {@link #writeTo(OutputStream,int,int)} that assumes - * all error checking has already been done. + * Internal version of {@link #writeTo(OutputStream,int,int)} that assumes all error checking has + * already been done. */ abstract void writeToInternal(OutputStream out, int sourceOffset, int numberToWrite) throws IOException; /** - * Writes this {@link ByteString} to the provided {@link ByteOutput}. Calling - * this method may result in multiple operations on the target {@link ByteOutput}. + * Writes this {@link ByteString} to the provided {@link ByteOutput}. Calling this method may + * result in multiple operations on the target {@link ByteOutput}. * *

This method may expose internal backing buffers of the {@link ByteString} to the {@link * ByteOutput} in order to avoid additional copying overhead. It would be possible for a malicious * {@link ByteOutput} to corrupt the {@link ByteString}. Use with caution! * - * @param byteOutput the output target to receive the bytes - * @throws IOException if an I/O error occurs + * @param byteOutput the output target to receive the bytes + * @throws IOException if an I/O error occurs * @see UnsafeByteOperations#unsafeWriteTo(ByteString, ByteOutput) */ abstract void writeTo(ByteOutput byteOutput) throws IOException; + /** + * This method behaves exactly the same as {@link #writeTo(ByteOutput)} unless the {@link + * ByteString} is a rope. For ropes, the leaf nodes are written in reverse order to the {@code + * byteOutput}. + * + * @param byteOutput the output target to receive the bytes + * @throws IOException if an I/O error occurs + * @see UnsafeByteOperations#unsafeWriteToReverse(ByteString, ByteOutput) + */ + abstract void writeToReverse(ByteOutput byteOutput) throws IOException; /** - * Constructs a read-only {@code java.nio.ByteBuffer} whose content - * is equal to the contents of this byte string. - * The result uses the same backing array as the byte string, if possible. + * Constructs a read-only {@code java.nio.ByteBuffer} whose content is equal to the contents of + * this byte string. The result uses the same backing array as the byte string, if possible. * * @return wrapped bytes */ public abstract ByteBuffer asReadOnlyByteBuffer(); /** - * Constructs a list of read-only {@code java.nio.ByteBuffer} objects - * such that the concatenation of their contents is equal to the contents - * of this byte string. The result uses the same backing arrays as the - * byte string. - *

- * By returning a list, implementations of this method may be able to avoid - * copying even when there are multiple backing arrays. + * Constructs a list of read-only {@code java.nio.ByteBuffer} objects such that the concatenation + * of their contents is equal to the contents of this byte string. The result uses the same + * backing arrays as the byte string. + * + *

By returning a list, implementations of this method may be able to avoid copying even when + * there are multiple backing arrays. * * @return a list of wrapped bytes */ public abstract List asReadOnlyByteBufferList(); /** - * Constructs a new {@code String} by decoding the bytes using the - * specified charset. + * Constructs a new {@code String} by decoding the bytes using the specified charset. * * @param charsetName encode using this charset * @return new string * @throws UnsupportedEncodingException if charset isn't recognized */ - public final String toString(String charsetName) - throws UnsupportedEncodingException { + public final String toString(String charsetName) throws UnsupportedEncodingException { try { return toString(Charset.forName(charsetName)); } catch (UnsupportedCharsetException e) { @@ -734,8 +790,8 @@ public final String toString(String charsetName) } /** - * Constructs a new {@code String} by decoding the bytes using the - * specified charset. Returns the same empty String if empty. + * Constructs a new {@code String} by decoding the bytes using the specified charset. Returns the + * same empty String if empty. * * @param charset encode using this charset * @return new string @@ -745,8 +801,7 @@ public final String toString(Charset charset) { } /** - * Constructs a new {@code String} by decoding the bytes using the - * specified charset. + * Constructs a new {@code String} by decoding the bytes using the specified charset. * * @param charset encode using this charset * @return new string @@ -766,50 +821,45 @@ public final String toStringUtf8() { } /** - * Tells whether this {@code ByteString} represents a well-formed UTF-8 - * byte sequence, such that the original bytes can be converted to a - * String object and then round tripped back to bytes without loss. + * Tells whether this {@code ByteString} represents a well-formed UTF-8 byte sequence, such that + * the original bytes can be converted to a String object and then round tripped back to bytes + * without loss. + * + *

More precisely, returns {@code true} whenever: * - *

More precisely, returns {@code true} whenever:

 {@code
+   * 
{@code
    * Arrays.equals(byteString.toByteArray(),
    *     new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
    * }
* - *

This method returns {@code false} for "overlong" byte sequences, - * as well as for 3-byte sequences that would map to a surrogate - * character, in accordance with the restricted definition of UTF-8 - * introduced in Unicode 3.1. Note that the UTF-8 decoder included in - * Oracle's JDK has been modified to also reject "overlong" byte - * sequences, but (as of 2011) still accepts 3-byte surrogate - * character byte sequences. + *

This method returns {@code false} for "overlong" byte sequences, as well as for 3-byte + * sequences that would map to a surrogate character, in accordance with the restricted definition + * of UTF-8 introduced in Unicode 3.1. Note that the UTF-8 decoder included in Oracle's JDK has + * been modified to also reject "overlong" byte sequences, but (as of 2011) still accepts 3-byte + * surrogate character byte sequences. * *

See the Unicode Standard,
* Table 3-6. UTF-8 Bit Distribution,
* Table 3-7. Well Formed UTF-8 Byte Sequences. * - * @return whether the bytes in this {@code ByteString} are a - * well-formed UTF-8 byte sequence + * @return whether the bytes in this {@code ByteString} are a well-formed UTF-8 byte sequence */ public abstract boolean isValidUtf8(); /** - * Tells whether the given byte sequence is a well-formed, malformed, or - * incomplete UTF-8 byte sequence. This method accepts and returns a partial - * state result, allowing the bytes for a complete UTF-8 byte sequence to be - * composed from multiple {@code ByteString} segments. + * Tells whether the given byte sequence is a well-formed, malformed, or incomplete UTF-8 byte + * sequence. This method accepts and returns a partial state result, allowing the bytes for a + * complete UTF-8 byte sequence to be composed from multiple {@code ByteString} segments. * - * @param state either {@code 0} (if this is the initial decoding operation) - * or the value returned from a call to a partial decoding method for the - * previous bytes + * @param state either {@code 0} (if this is the initial decoding operation) or the value returned + * from a call to a partial decoding method for the previous bytes * @param offset offset of the first byte to check * @param length number of bytes to check - * - * @return {@code -1} if the partial byte sequence is definitely malformed, - * {@code 0} if it is well-formed (no additional input needed), or, if the - * byte sequence is "incomplete", i.e. apparently terminated in the middle of - * a character, an opaque integer "state" value containing enough information - * to decode the character when passed to a subsequent invocation of a - * partial decoding method. + * @return {@code -1} if the partial byte sequence is definitely malformed, {@code 0} if it is + * well-formed (no additional input needed), or, if the byte sequence is "incomplete", i.e. + * apparently terminated in the middle of a character, an opaque integer "state" value + * containing enough information to decode the character when passed to a subsequent + * invocation of a partial decoding method. */ protected abstract int partialIsValidUtf8(int state, int offset, int length); @@ -819,9 +869,7 @@ public final String toStringUtf8() { @Override public abstract boolean equals(Object o); - /** - * Base class for leaf {@link ByteString}s (i.e. non-ropes). - */ + /** Base class for leaf {@link ByteString}s (i.e. non-ropes). */ abstract static class LeafByteString extends ByteString { @Override protected final int getTreeDepth() { @@ -833,12 +881,16 @@ protected final boolean isBalanced() { return true; } + @Override + void writeToReverse(ByteOutput byteOutput) throws IOException { + writeTo(byteOutput); + } /** - * Check equality of the substring of given length of this object starting at - * zero with another {@code ByteString} substring starting at offset. + * Check equality of the substring of given length of this object starting at zero with another + * {@code ByteString} substring starting at offset. * - * @param other what to compare a substring in + * @param other what to compare a substring in * @param offset offset into other * @param length number of bytes to compare * @return true for equality of substrings, else false. @@ -847,8 +899,7 @@ protected final boolean isBalanced() { } /** - * Compute the hashCode using the traditional algorithm from {@link - * ByteString}. + * Compute the hashCode using the traditional algorithm from {@link ByteString}. * * @return hashCode value */ @@ -872,26 +923,23 @@ public final int hashCode() { /** * Creates an {@code InputStream} which can be used to read the bytes. - *

- * The {@link InputStream} returned by this method is guaranteed to be - * completely non-blocking. The method {@link InputStream#available()} - * returns the number of bytes remaining in the stream. The methods - * {@link InputStream#read(byte[])}, {@link InputStream#read(byte[],int,int)} - * and {@link InputStream#skip(long)} will read/skip as many bytes as are - * available. The method {@link InputStream#markSupported()} returns - * {@code true}. - *

- * The methods in the returned {@link InputStream} might not be - * thread safe. + * + *

The {@link InputStream} returned by this method is guaranteed to be completely non-blocking. + * The method {@link InputStream#available()} returns the number of bytes remaining in the stream. + * The methods {@link InputStream#read(byte[])}, {@link InputStream#read(byte[],int,int)} and + * {@link InputStream#skip(long)} will read/skip as many bytes as are available. The method {@link + * InputStream#markSupported()} returns {@code true}. + * + *

The methods in the returned {@link InputStream} might not be thread safe. * * @return an input stream that returns the bytes of this byte string. */ public abstract InputStream newInput(); /** - * Creates a {@link CodedInputStream} which can be used to read the bytes. - * Using this is often more efficient than creating a {@link CodedInputStream} - * that wraps the result of {@link #newInput()}. + * Creates a {@link CodedInputStream} which can be used to read the bytes. Using this is often + * more efficient than creating a {@link CodedInputStream} that wraps the result of {@link + * #newInput()}. * * @return stream based on wrapped data */ @@ -903,10 +951,10 @@ public final int hashCode() { /** * Creates a new {@link Output} with the given initial capacity. Call {@link * Output#toByteString()} to create the {@code ByteString} instance. - *

- * A {@link ByteString.Output} offers the same functionality as a - * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString} - * rather than a {@code byte} array. + * + *

A {@link ByteString.Output} offers the same functionality as a {@link + * ByteArrayOutputStream}, except that it returns a {@link ByteString} rather than a {@code byte} + * array. * * @param initialCapacity estimate of number of bytes to be written * @return {@code OutputStream} for building a {@code ByteString} @@ -916,12 +964,12 @@ public static Output newOutput(int initialCapacity) { } /** - * Creates a new {@link Output}. Call {@link Output#toByteString()} to create - * the {@code ByteString} instance. - *

- * A {@link ByteString.Output} offers the same functionality as a - * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString} - * rather than a {@code byte array}. + * Creates a new {@link Output}. Call {@link Output#toByteString()} to create the {@code + * ByteString} instance. + * + *

A {@link ByteString.Output} offers the same functionality as a {@link + * ByteArrayOutputStream}, except that it returns a {@link ByteString} rather than a {@code byte + * array}. * * @return {@code OutputStream} for building a {@code ByteString} */ @@ -930,8 +978,8 @@ public static Output newOutput() { } /** - * Outputs to a {@code ByteString} instance. Call {@link #toByteString()} to - * create the {@code ByteString} instance. + * Outputs to a {@code ByteString} instance. Call {@link #toByteString()} to create the {@code + * ByteString} instance. */ public static final class Output extends OutputStream { // Implementation note. @@ -953,10 +1001,9 @@ public static final class Output extends OutputStream { private int bufferPos; /** - * Creates a new ByteString output stream with the specified - * initial capacity. + * Creates a new ByteString output stream with the specified initial capacity. * - * @param initialCapacity the initial capacity of the output stream. + * @param initialCapacity the initial capacity of the output stream. */ Output(int initialCapacity) { if (initialCapacity < 0) { @@ -972,43 +1019,41 @@ public synchronized void write(int b) { if (bufferPos == buffer.length) { flushFullBuffer(1); } - buffer[bufferPos++] = (byte)b; + buffer[bufferPos++] = (byte) b; } @Override - public synchronized void write(byte[] b, int offset, int length) { + public synchronized void write(byte[] b, int offset, int length) { if (length <= buffer.length - bufferPos) { // The bytes can fit into the current buffer. System.arraycopy(b, offset, buffer, bufferPos, length); bufferPos += length; } else { // Use up the current buffer - int copySize = buffer.length - bufferPos; + int copySize = buffer.length - bufferPos; System.arraycopy(b, offset, buffer, bufferPos, copySize); offset += copySize; length -= copySize; // Flush the buffer, and get a new buffer at least big enough to cover // what we still need to output flushFullBuffer(length); - System.arraycopy(b, offset, buffer, 0 /* count */, length); + System.arraycopy(b, offset, buffer, /* count= */ 0, length); bufferPos = length; } } /** - * Creates a byte string. Its size is the current size of this output - * stream and its output has been copied to it. + * Creates a byte string. Its size is the current size of this output stream and its output has + * been copied to it. * - * @return the current contents of this output stream, as a byte string. + * @return the current contents of this output stream, as a byte string. */ public synchronized ByteString toByteString() { flushLastBuffer(); return ByteString.copyFrom(flushedBuffers); } - /** - * Implement java.util.Arrays.copyOf() for jdk 1.5. - */ + /** Implement java.util.Arrays.copyOf() for jdk 1.5. */ private byte[] copyArray(byte[] buffer, int length) { byte[] result = new byte[length]; System.arraycopy(buffer, 0, result, 0, Math.min(buffer.length, length)); @@ -1016,11 +1061,11 @@ private byte[] copyArray(byte[] buffer, int length) { } /** - * Writes the complete contents of this byte array output stream to - * the specified output stream argument. + * Writes the complete contents of this byte array output stream to the specified output stream + * argument. * * @param out the output stream to which to write the data. - * @throws IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs. */ public void writeTo(OutputStream out) throws IOException { ByteString[] cachedFlushBuffers; @@ -1029,8 +1074,7 @@ public void writeTo(OutputStream out) throws IOException { synchronized (this) { // Copy the information we need into local variables so as to hold // the lock for as short a time as possible. - cachedFlushBuffers = - flushedBuffers.toArray(new ByteString[flushedBuffers.size()]); + cachedFlushBuffers = flushedBuffers.toArray(new ByteString[flushedBuffers.size()]); cachedBuffer = buffer; cachedBufferPos = bufferPos; } @@ -1044,16 +1088,15 @@ public void writeTo(OutputStream out) throws IOException { /** * Returns the current size of the output stream. * - * @return the current size of the output stream + * @return the current size of the output stream */ public synchronized int size() { return flushedBuffersTotalBytes + bufferPos; } /** - * Resets this stream, so that all currently accumulated output in the - * output stream is discarded. The output stream can be used again, - * reusing the already allocated buffer space. + * Resets this stream, so that all currently accumulated output in the output stream is + * discarded. The output stream can be used again, reusing the already allocated buffer space. */ public synchronized void reset() { flushedBuffers.clear(); @@ -1063,32 +1106,31 @@ public synchronized void reset() { @Override public String toString() { - return String.format("", + return String.format( + "", Integer.toHexString(System.identityHashCode(this)), size()); } /** - * Internal function used by writers. The current buffer is full, and the - * writer needs a new buffer whose size is at least the specified minimum - * size. + * Internal function used by writers. The current buffer is full, and the writer needs a new + * buffer whose size is at least the specified minimum size. */ - private void flushFullBuffer(int minSize) { + private void flushFullBuffer(int minSize) { flushedBuffers.add(new LiteralByteString(buffer)); flushedBuffersTotalBytes += buffer.length; // We want to increase our total capacity by 50%, but as a minimum, // the new buffer should also at least be >= minSize and // >= initial Capacity. - int newSize = Math.max(initialCapacity, - Math.max(minSize, flushedBuffersTotalBytes >>> 1)); + int newSize = Math.max(initialCapacity, Math.max(minSize, flushedBuffersTotalBytes >>> 1)); buffer = new byte[newSize]; bufferPos = 0; } /** - * Internal function used by {@link #toByteString()}. The current buffer may - * or may not be full, but it needs to be flushed. + * Internal function used by {@link #toByteString()}. The current buffer may or may not be full, + * but it needs to be flushed. */ - private void flushLastBuffer() { + private void flushLastBuffer() { if (bufferPos < buffer.length) { if (bufferPos > 0) { byte[] bufferCopy = copyArray(buffer, bufferPos); @@ -1111,17 +1153,15 @@ private void flushLastBuffer() { } /** - * Constructs a new {@code ByteString} builder, which allows you to - * efficiently construct a {@code ByteString} by writing to a {@link - * CodedOutputStream}. Using this is much more efficient than calling {@code - * newOutput()} and wrapping that in a {@code CodedOutputStream}. + * Constructs a new {@code ByteString} builder, which allows you to efficiently construct a {@code + * ByteString} by writing to a {@link CodedOutputStream}. Using this is much more efficient than + * calling {@code newOutput()} and wrapping that in a {@code CodedOutputStream}. * - *

This is package-private because it's a somewhat confusing interface. - * Users can call {@link Message#toByteString()} instead of calling this - * directly. + *

This is package-private because it's a somewhat confusing interface. Users can call {@link + * Message#toByteString()} instead of calling this directly. * - * @param size The target byte size of the {@code ByteString}. You must write - * exactly this many bytes before building the result. + * @param size The target byte size of the {@code ByteString}. You must write exactly this many + * bytes before building the result. * @return the builder */ static CodedBuilder newCodedBuilder(int size) { @@ -1157,16 +1197,16 @@ public CodedOutputStream getCodedOutput() { // public API. /** - * Return the depth of the tree representing this {@code ByteString}, if any, - * whose root is this node. If this is a leaf node, return 0. + * Return the depth of the tree representing this {@code ByteString}, if any, whose root is this + * node. If this is a leaf node, return 0. * * @return tree depth or zero */ protected abstract int getTreeDepth(); /** - * Return {@code true} if this ByteString is literal (a leaf node) or a - * flat-enough tree in the sense of {@link RopeByteString}. + * Return {@code true} if this ByteString is literal (a leaf node) or a flat-enough tree in the + * sense of {@link RopeByteString}. * * @return true if the tree is flat enough */ @@ -1182,10 +1222,9 @@ protected final int peekCachedHashCode() { } /** - * Compute the hash across the value bytes starting with the given hash, and - * return the result. This is used to compute the hash across strings - * represented as a set of pieces by allowing the hash computation to be - * continued from piece to piece. + * Compute the hash across the value bytes starting with the given hash, and return the result. + * This is used to compute the hash across strings represented as a set of pieces by allowing the + * hash computation to be continued from piece to piece. * * @param h starting hash value * @param offset offset into this value to start looking at data values @@ -1237,16 +1276,25 @@ static int checkRange(int startIndex, int endIndex, int size) { @Override public final String toString() { - return String.format("", - Integer.toHexString(System.identityHashCode(this)), size()); + return String.format( + Locale.ROOT, + "", + toHexString(identityHashCode(this)), + size(), + truncateAndEscapeForDisplay()); + } + + private String truncateAndEscapeForDisplay() { + final int limit = 50; + + return size() <= limit ? escapeBytes(this) : escapeBytes(substring(0, limit - 3)) + "..."; } /** - * This class implements a {@link com.google.protobuf.ByteString} backed by a - * single array of bytes, contiguous in memory. It supports substring by - * pointing to only a sub-range of the underlying byte array, meaning that a - * substring will reference the full byte-array of the string it's made from, - * exactly as with {@link String}. + * This class implements a {@link com.google.protobuf.ByteString} backed by a single array of + * bytes, contiguous in memory. It supports substring by pointing to only a sub-range of the + * underlying byte array, meaning that a substring will reference the full byte-array of the + * string it's made from, exactly as with {@link String}. * * @author carlanton@google.com (Carl Haverl) */ @@ -1258,12 +1306,14 @@ private static class LiteralByteString extends ByteString.LeafByteString { protected final byte[] bytes; /** - * Creates a {@code LiteralByteString} backed by the given array, without - * copying. + * Creates a {@code LiteralByteString} backed by the given array, without copying. * * @param bytes array to wrap */ LiteralByteString(byte[] bytes) { + if (bytes == null) { + throw new NullPointerException(); + } this.bytes = bytes; } @@ -1275,6 +1325,11 @@ public byte byteAt(int index) { return bytes[index]; } + @Override + byte internalByteAt(int index) { + return bytes[index]; + } + @Override public int size() { return bytes.length; @@ -1394,10 +1449,10 @@ public final boolean equals(Object other) { } /** - * Check equality of the substring of given length of this object starting at - * zero with another {@code LiteralByteString} substring starting at offset. + * Check equality of the substring of given length of this object starting at zero with another + * {@code LiteralByteString} substring starting at offset. * - * @param other what to compare a substring in + * @param other what to compare a substring in * @param offset offset into other * @param length number of bytes to compare * @return true for equality of substrings, else false. @@ -1417,10 +1472,10 @@ final boolean equalsRange(ByteString other, int offset, int length) { byte[] thisBytes = bytes; byte[] otherBytes = lbsOther.bytes; int thisLimit = getOffsetIntoBytes() + length; - for ( - int thisIndex = getOffsetIntoBytes(), + for (int thisIndex = getOffsetIntoBytes(), otherIndex = lbsOther.getOffsetIntoBytes() + offset; - (thisIndex < thisLimit); ++thisIndex, ++otherIndex) { + (thisIndex < thisLimit); + ++thisIndex, ++otherIndex) { if (thisBytes[thisIndex] != otherBytes[otherIndex]) { return false; } @@ -1449,7 +1504,7 @@ public final CodedInputStream newCodedInput() { // We trust CodedInputStream not to modify the bytes, or to give anyone // else access to them. return CodedInputStream.newInstance( - bytes, getOffsetIntoBytes(), size(), true /* bufferIsImmutable */); + bytes, getOffsetIntoBytes(), size(), /* bufferIsImmutable= */ true); } // ================================================================= @@ -1466,14 +1521,12 @@ protected int getOffsetIntoBytes() { } /** - * This class is used to represent the substring of a {@link ByteString} over a - * single byte array. In terms of the public API of {@link ByteString}, you end - * up here by calling {@link ByteString#copyFrom(byte[])} followed by {@link - * ByteString#substring(int, int)}. + * This class is used to represent the substring of a {@link ByteString} over a single byte array. + * In terms of the public API of {@link ByteString}, you end up here by calling {@link + * ByteString#copyFrom(byte[])} followed by {@link ByteString#substring(int, int)}. * - *

This class contains most of the overhead involved in creating a substring - * from a {@link LiteralByteString}. The overhead involves some range-checking - * and two extra fields. + *

This class contains most of the overhead involved in creating a substring from a {@link + * LiteralByteString}. The overhead involves some range-checking and two extra fields. * * @author carlanton@google.com (Carl Haverl) */ @@ -1485,15 +1538,13 @@ private static final class BoundedByteString extends LiteralByteString { private final int bytesLength; /** - * Creates a {@code BoundedByteString} backed by the sub-range of given array, - * without copying. + * Creates a {@code BoundedByteString} backed by the sub-range of given array, without copying. * - * @param bytes array to wrap + * @param bytes array to wrap * @param offset index to first byte to use in bytes * @param length number of bytes to use from bytes - * @throws IllegalArgumentException if {@code offset < 0}, {@code length < 0}, - * or if {@code offset + length > - * bytes.length}. + * @throws IllegalArgumentException if {@code offset < 0}, {@code length < 0}, or if {@code + * offset + length > bytes.length}. */ BoundedByteString(byte[] bytes, int offset, int length) { super(bytes); @@ -1504,10 +1555,9 @@ private static final class BoundedByteString extends LiteralByteString { } /** - * Gets the byte at the given index. - * Throws {@link ArrayIndexOutOfBoundsException} - * for backwards-compatibility reasons although it would more properly be - * {@link IndexOutOfBoundsException}. + * Gets the byte at the given index. Throws {@link ArrayIndexOutOfBoundsException} for + * backwards-compatibility reasons although it would more properly be {@link + * IndexOutOfBoundsException}. * * @param index index of byte * @return the value @@ -1521,6 +1571,11 @@ public byte byteAt(int index) { return bytes[bytesOffset + index]; } + @Override + byte internalByteAt(int index) { + return bytes[bytesOffset + index]; + } + @Override public int size() { return bytesLength; @@ -1535,10 +1590,10 @@ protected int getOffsetIntoBytes() { // ByteString -> byte[] @Override - protected void copyToInternal(byte[] target, int sourceOffset, int targetOffset, - int numberToCopy) { - System.arraycopy(bytes, getOffsetIntoBytes() + sourceOffset, target, - targetOffset, numberToCopy); + protected void copyToInternal( + byte[] target, int sourceOffset, int targetOffset, int numberToCopy) { + System.arraycopy( + bytes, getOffsetIntoBytes() + sourceOffset, target, targetOffset, numberToCopy); } // ================================================================= diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java index d6a941b1c03d9..ff81e0032f81e 100644 --- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java +++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java @@ -41,9 +41,11 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.Buffer; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; +import java.util.Iterator; import java.util.List; /** @@ -71,13 +73,19 @@ public abstract class CodedInputStream { /** Visible for subclasses. See setSizeLimit() */ int sizeLimit = DEFAULT_SIZE_LIMIT; + /** Used to adapt to the experimental {@link Reader} interface. */ + CodedInputStreamReader wrapper; + /** Create a new CodedInputStream wrapping the given InputStream. */ public static CodedInputStream newInstance(final InputStream input) { return newInstance(input, DEFAULT_BUFFER_SIZE); } - /** Create a new CodedInputStream wrapping the given InputStream. */ - static CodedInputStream newInstance(final InputStream input, int bufferSize) { + /** Create a new CodedInputStream wrapping the given InputStream, with a specified buffer size. */ + public static CodedInputStream newInstance(final InputStream input, int bufferSize) { + if (bufferSize <= 0) { + throw new IllegalArgumentException("bufferSize must be > 0"); + } if (input == null) { // TODO(nathanmittler): Ideally we should throw here. This is done for backward compatibility. return newInstance(EMPTY_BYTE_ARRAY); @@ -85,6 +93,43 @@ static CodedInputStream newInstance(final InputStream input, int bufferSize) { return new StreamDecoder(input, bufferSize); } + /** Create a new CodedInputStream wrapping the given {@code Iterable }. */ + public static CodedInputStream newInstance(final Iterable input) { + if (!UnsafeDirectNioDecoder.isSupported()) { + return newInstance(new IterableByteBufferInputStream(input)); + } + return newInstance(input, false); + } + + /** Create a new CodedInputStream wrapping the given {@code Iterable }. */ + static CodedInputStream newInstance( + final Iterable bufs, final boolean bufferIsImmutable) { + // flag is to check the type of input's ByteBuffers. + // flag equals 1: all ByteBuffers have array. + // flag equals 2: all ByteBuffers are direct ByteBuffers. + // flag equals 3: some ByteBuffers are direct and some have array. + // flag greater than 3: other cases. + int flag = 0; + // Total size of the input + int totalSize = 0; + for (ByteBuffer buf : bufs) { + totalSize += buf.remaining(); + if (buf.hasArray()) { + flag |= 1; + } else if (buf.isDirect()) { + flag |= 2; + } else { + flag |= 4; + } + } + if (flag == 2) { + return new IterableDirectByteBufferDecoder(bufs, totalSize, bufferIsImmutable); + } else { + // TODO(yilunchong): add another decoders to deal case 1 and 3. + return newInstance(new IterableByteBufferInputStream(bufs)); + } + } + /** Create a new CodedInputStream wrapping the given byte array. */ public static CodedInputStream newInstance(final byte[] buf) { return newInstance(buf, 0, buf.length); @@ -92,7 +137,7 @@ public static CodedInputStream newInstance(final byte[] buf) { /** Create a new CodedInputStream wrapping the given byte array slice. */ public static CodedInputStream newInstance(final byte[] buf, final int off, final int len) { - return newInstance(buf, off, len, false /* bufferIsImmutable */); + return newInstance(buf, off, len, /* bufferIsImmutable= */ false); } /** Create a new CodedInputStream wrapping the given byte array slice. */ @@ -128,7 +173,7 @@ static CodedInputStream newInstance( * trying to alter the ByteBuffer's status. */ public static CodedInputStream newInstance(ByteBuffer buf) { - return newInstance(buf, false /* bufferIsImmutable */); + return newInstance(buf, /* bufferIsImmutable= */ false); } /** Create a new CodedInputStream wrapping the given buffer. */ @@ -336,7 +381,7 @@ public abstract T readMessage( /** * Set the maximum message recursion depth. In order to prevent malicious messages from causing * stack overflows, {@code CodedInputStream} limits how deeply messages may be nested. The default - * limit is 64. + * limit is 100. * * @return the old limit. */ @@ -372,23 +417,7 @@ public final int setSizeLimit(final int limit) { return oldLimit; } - - private boolean explicitDiscardUnknownFields = false; - - /** TODO(liujisi): flip the default.*/ - private static volatile boolean proto3DiscardUnknownFieldsDefault = true; - - static void setProto3DiscardUnknownsByDefaultForTest() { - proto3DiscardUnknownFieldsDefault = true; - } - - static void setProto3KeepUnknownsByDefaultForTest() { - proto3DiscardUnknownFieldsDefault = false; - } - - static boolean getProto3DiscardUnknownFieldsDefault() { - return proto3DiscardUnknownFieldsDefault; - } + private boolean shouldDiscardUnknownFields = false; /** * Sets this {@code CodedInputStream} to discard unknown fields. Only applies to full runtime @@ -399,7 +428,7 @@ static boolean getProto3DiscardUnknownFieldsDefault() { * runtime. */ final void discardUnknownFields() { - explicitDiscardUnknownFields = true; + shouldDiscardUnknownFields = true; } /** @@ -407,7 +436,7 @@ final void discardUnknownFields() { * default. */ final void unsetDiscardUnknownFields() { - explicitDiscardUnknownFields = false; + shouldDiscardUnknownFields = false; } /** @@ -415,19 +444,7 @@ final void unsetDiscardUnknownFields() { * runtime messages. */ final boolean shouldDiscardUnknownFields() { - return explicitDiscardUnknownFields; - } - - /** - * Whether unknown fields in this input stream should be discarded during parsing for proto3 full - * runtime messages. - * - *

This function was temporarily introduced before proto3 unknown fields behavior is changed. - * TODO(liujisi): remove this and related code in GeneratedMessage after proto3 unknown - * fields migration is done. - */ - final boolean shouldDiscardUnknownFieldsProto3() { - return explicitDiscardUnknownFields ? true : proto3DiscardUnknownFieldsDefault; + return shouldDiscardUnknownFields; } /** @@ -467,7 +484,9 @@ final boolean shouldDiscardUnknownFieldsProto3() { /** * Returns true if the stream has reached the end of the input. This is the case if either the end * of the underlying input source has been reached or if the stream has reached a limit created - * using {@link #pushLimit(int)}. + * using {@link #pushLimit(int)}. This function may get blocked when using StreamDecoder as it + * invokes {@link StreamDecoder#tryRefillBuffer(int)} in this function which will try to read + * bytes from input. */ public abstract boolean isAtEnd() throws IOException; @@ -788,13 +807,9 @@ public String readString() throws IOException { public String readStringRequireUtf8() throws IOException { final int size = readRawVarint32(); if (size > 0 && size <= (limit - pos)) { - // TODO(martinrb): We could save a pass by validating while decoding. - if (!Utf8.isValidUtf8(buffer, pos, pos + size)) { - throw InvalidProtocolBufferException.invalidUtf8(); - } - final int tempPos = pos; + String result = Utf8.decodeUtf8(buffer, pos, size); pos += size; - return new String(buffer, tempPos, size, UTF_8); + return result; } if (size == 0) { @@ -1487,6 +1502,8 @@ public String readString() throws IOException { final int size = readRawVarint32(); if (size > 0 && size <= remaining()) { // TODO(nathanmittler): Is there a way to avoid this copy? + // TODO(anuraaga): It might be possible to share the optimized loop with + // readStringRequireUtf8 by implementing Java replacement logic there. // The same as readBytes' logic byte[] bytes = new byte[size]; UnsafeUtil.copyMemory(pos, bytes, 0, size); @@ -1507,17 +1524,9 @@ public String readString() throws IOException { @Override public String readStringRequireUtf8() throws IOException { final int size = readRawVarint32(); - if (size >= 0 && size <= remaining()) { - // TODO(nathanmittler): Is there a way to avoid this copy? - // The same as readBytes' logic - byte[] bytes = new byte[size]; - UnsafeUtil.copyMemory(pos, bytes, 0, size); - // TODO(martinrb): We could save a pass by validating while decoding. - if (!Utf8.isValidUtf8(bytes)) { - throw InvalidProtocolBufferException.invalidUtf8(); - } - - String result = new String(bytes, UTF_8); + if (size > 0 && size <= remaining()) { + final int bufferPos = bufferPos(pos); + String result = Utf8.decodeUtf8(buffer, bufferPos, size); pos += size; return result; } @@ -2001,14 +2010,14 @@ private ByteBuffer slice(long begin, long end) throws IOException { int prevPos = buffer.position(); int prevLimit = buffer.limit(); try { - buffer.position(bufferPos(begin)); - buffer.limit(bufferPos(end)); + ((Buffer) buffer).position(bufferPos(begin)); + ((Buffer) buffer).limit(bufferPos(end)); return buffer.slice(); } catch (IllegalArgumentException e) { throw InvalidProtocolBufferException.truncatedMessage(); } finally { - buffer.position(prevPos); - buffer.limit(prevLimit); + ((Buffer) buffer).position(prevPos); + ((Buffer) buffer).limit(prevLimit); } } } @@ -2260,7 +2269,7 @@ public String readString() throws IOException { return result; } // Slow path: Build a byte array first then copy it. - return new String(readRawBytesSlowPath(size), UTF_8); + return new String(readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false), UTF_8); } @Override @@ -2284,14 +2293,10 @@ public String readStringRequireUtf8() throws IOException { pos = tempPos + size; } else { // Slow path: Build a byte array first then copy it. - bytes = readRawBytesSlowPath(size); + bytes = readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false); tempPos = 0; } - // TODO(martinrb): We could save a pass by validating while decoding. - if (!Utf8.isValidUtf8(bytes, tempPos, tempPos + size)) { - throw InvalidProtocolBufferException.invalidUtf8(); - } - return new String(bytes, tempPos, size, UTF_8); + return Utf8.decodeUtf8(bytes, tempPos, size); } @Override @@ -2393,7 +2398,8 @@ public byte[] readByteArray() throws IOException { return result; } else { // Slow path: Build a byte array first then copy it. - return readRawBytesSlowPath(size); + // TODO(dweis): Do we want to protect from malicious input streams here? + return readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false); } } @@ -2410,7 +2416,10 @@ public ByteBuffer readByteBuffer() throws IOException { return Internal.EMPTY_BYTE_BUFFER; } // Slow path: Build a byte array first then copy it. - return ByteBuffer.wrap(readRawBytesSlowPath(size)); + + // We must copy as the byte array was handed off to the InputStream and a malicious + // implementation could retain a reference. + return ByteBuffer.wrap(readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ true)); } @Override @@ -2784,7 +2793,8 @@ private boolean tryRefillBuffer(int n) throws IOException { sizeLimit - totalBytesRetired - bufferSize)); if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) { throw new IllegalStateException( - "InputStream#read(byte[]) returned invalid result: " + input.getClass() + + "#read(byte[]) returned invalid result: " + bytesRead + "\nThe InputStream implementation is buggy."); } @@ -2812,19 +2822,24 @@ public byte[] readRawBytes(final int size) throws IOException { pos = tempPos + size; return Arrays.copyOfRange(buffer, tempPos, tempPos + size); } else { - return readRawBytesSlowPath(size); + // TODO(dweis): Do we want to protect from malicious input streams here? + return readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false); } } /** * Exactly like readRawBytes, but caller must have already checked the fast path: (size <= * (bufferSize - pos) && size > 0) + * + * If ensureNoLeakedReferences is true, the value is guaranteed to have not escaped to + * untrusted code. */ - private byte[] readRawBytesSlowPath(final int size) throws IOException { + private byte[] readRawBytesSlowPath( + final int size, boolean ensureNoLeakedReferences) throws IOException { // Attempt to read the data in one byte array when it's safe to do. byte[] result = readRawBytesSlowPathOneChunk(size); if (result != null) { - return result; + return ensureNoLeakedReferences ? result.clone() : result; } final int originalBufferPos = pos; @@ -2862,6 +2877,8 @@ private byte[] readRawBytesSlowPath(final int size) throws IOException { /** * Attempts to read the data in one byte array when it's safe to do. Returns null if the size to * read is too large and needs to be allocated in smaller chunks for security reasons. + * + * Returns a byte[] that may have escaped to user code via InputStream APIs. */ private byte[] readRawBytesSlowPathOneChunk(final int size) throws IOException { if (size == 0) { @@ -2916,7 +2933,11 @@ private byte[] readRawBytesSlowPathOneChunk(final int size) throws IOException { return null; } - /** Reads the remaining data in small chunks from the input stream. */ + /** + * Reads the remaining data in small chunks from the input stream. + * + * Returns a byte[] that may have escaped to user code via InputStream APIs. + */ private List readRawBytesSlowPathRemainingChunks(int sizeLeft) throws IOException { // The size is very large. For security reasons, we can't allocate the // entire byte array yet. The size comes directly from the input, so a @@ -2953,7 +2974,9 @@ private List readRawBytesSlowPathRemainingChunks(int sizeLeft) throws IO private ByteString readBytesSlowPath(final int size) throws IOException { final byte[] result = readRawBytesSlowPathOneChunk(size); if (result != null) { - return ByteString.wrap(result); + // We must copy as the byte array was handed off to the InputStream and a malicious + // implementation could retain a reference. + return ByteString.copyFrom(result); } final int originalBufferPos = pos; @@ -2971,13 +2994,20 @@ private ByteString readBytesSlowPath(final int size) throws IOException { // chunks. List chunks = readRawBytesSlowPathRemainingChunks(sizeLeft); - // Wrap the byte arrays into a single ByteString. - List byteStrings = new ArrayList(1 + chunks.size()); - byteStrings.add(ByteString.copyFrom(buffer, originalBufferPos, bufferedBytes)); - for (byte[] chunk : chunks) { - byteStrings.add(ByteString.wrap(chunk)); + // OK, got everything. Now concatenate it all into one buffer. + final byte[] bytes = new byte[size]; + + // Start by copying the leftover bytes from this.buffer. + System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes); + + // And now all the chunks. + int tempPos = bufferedBytes; + for (final byte[] chunk : chunks) { + System.arraycopy(chunk, 0, bytes, tempPos, chunk.length); + tempPos += chunk.length; } - return ByteString.copyFrom(byteStrings); + + return ByteString.wrap(bytes); } @Override @@ -3006,20 +3036,890 @@ private void skipRawBytesSlowPath(final int size) throws IOException { throw InvalidProtocolBufferException.truncatedMessage(); } - // Skipping more bytes than are in the buffer. First skip what we have. - int tempPos = bufferSize - pos; - pos = bufferSize; + int totalSkipped = 0; + if (refillCallback == null) { + // Skipping more bytes than are in the buffer. First skip what we have. + totalBytesRetired += pos; + totalSkipped = bufferSize - pos; + bufferSize = 0; + pos = 0; - // Keep refilling the buffer until we get to the point we wanted to skip to. - // This has the side effect of ensuring the limits are updated correctly. - refillBuffer(1); - while (size - tempPos > bufferSize) { - tempPos += bufferSize; + try { + while (totalSkipped < size) { + int toSkip = size - totalSkipped; + long skipped = input.skip(toSkip); + if (skipped < 0 || skipped > toSkip) { + throw new IllegalStateException( + input.getClass() + + "#skip returned invalid result: " + + skipped + + "\nThe InputStream implementation is buggy."); + } else if (skipped == 0) { + // The API contract of skip() permits an inputstream to skip zero bytes for any reason + // it wants. In particular, ByteArrayInputStream will just return zero over and over + // when it's at the end of its input. In order to actually confirm that we've hit the + // end of input, we need to issue a read call via the other path. + break; + } + totalSkipped += (int) skipped; + } + } finally { + totalBytesRetired += totalSkipped; + recomputeBufferSizeAfterLimit(); + } + } + if (totalSkipped < size) { + // Skipping more bytes than are in the buffer. First skip what we have. + int tempPos = bufferSize - pos; pos = bufferSize; + + // Keep refilling the buffer until we get to the point we wanted to skip to. + // This has the side effect of ensuring the limits are updated correctly. refillBuffer(1); + while (size - tempPos > bufferSize) { + tempPos += bufferSize; + pos = bufferSize; + refillBuffer(1); + } + + pos = size - tempPos; + } + } + } + + /** + * Implementation of {@link CodedInputStream} that uses an {@link Iterable } as the + * data source. Requires the use of {@code sun.misc.Unsafe} to perform fast reads on the buffer. + */ + private static final class IterableDirectByteBufferDecoder extends CodedInputStream { + /** The object that need to decode. */ + private Iterable input; + /** The {@link Iterator} with type {@link ByteBuffer} of {@code input} */ + private Iterator iterator; + /** The current ByteBuffer; */ + private ByteBuffer currentByteBuffer; + /** + * If {@code true}, indicates that all the buffer are backing a {@link ByteString} and are + * therefore considered to be an immutable input source. + */ + private boolean immutable; + /** + * If {@code true}, indicates that calls to read {@link ByteString} or {@code byte[]} + * may return slices of the underlying buffer, rather than copies. + */ + private boolean enableAliasing; + /** The global total message length limit */ + private int totalBufferSize; + /** The amount of available data in the input beyond {@link #currentLimit}. */ + private int bufferSizeAfterCurrentLimit; + /** The absolute position of the end of the current message. */ + private int currentLimit = Integer.MAX_VALUE; + /** The last tag that was read from this stream. */ + private int lastTag; + /** Total Bytes have been Read from the {@link Iterable} {@link ByteBuffer} */ + private int totalBytesRead; + /** The start position offset of the whole message, used as to reset the totalBytesRead */ + private int startOffset; + /** The current position for current ByteBuffer */ + private long currentByteBufferPos; + + private long currentByteBufferStartPos; + /** + * If the current ByteBuffer is unsafe-direct based, currentAddress is the start address of this + * ByteBuffer; otherwise should be zero. + */ + private long currentAddress; + /** The limit position for current ByteBuffer */ + private long currentByteBufferLimit; + + /** + * The constructor of {@code Iterable} decoder. + * + * @param inputBufs The input data. + * @param size The total size of the input data. + * @param immutableFlag whether the input data is immutable. + */ + private IterableDirectByteBufferDecoder( + Iterable inputBufs, int size, boolean immutableFlag) { + totalBufferSize = size; + input = inputBufs; + iterator = input.iterator(); + immutable = immutableFlag; + startOffset = totalBytesRead = 0; + if (size == 0) { + currentByteBuffer = EMPTY_BYTE_BUFFER; + currentByteBufferPos = 0; + currentByteBufferStartPos = 0; + currentByteBufferLimit = 0; + currentAddress = 0; + } else { + tryGetNextByteBuffer(); + } + } + + /** To get the next ByteBuffer from {@code input}, and then update the parameters */ + private void getNextByteBuffer() throws InvalidProtocolBufferException { + if (!iterator.hasNext()) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + tryGetNextByteBuffer(); + } + + private void tryGetNextByteBuffer() { + currentByteBuffer = iterator.next(); + totalBytesRead += (int) (currentByteBufferPos - currentByteBufferStartPos); + currentByteBufferPos = currentByteBuffer.position(); + currentByteBufferStartPos = currentByteBufferPos; + currentByteBufferLimit = currentByteBuffer.limit(); + currentAddress = UnsafeUtil.addressOffset(currentByteBuffer); + currentByteBufferPos += currentAddress; + currentByteBufferStartPos += currentAddress; + currentByteBufferLimit += currentAddress; + } + + @Override + public int readTag() throws IOException { + if (isAtEnd()) { + lastTag = 0; + return 0; + } + + lastTag = readRawVarint32(); + if (WireFormat.getTagFieldNumber(lastTag) == 0) { + // If we actually read zero (or any tag number corresponding to field + // number zero), that's not a valid tag. + throw InvalidProtocolBufferException.invalidTag(); + } + return lastTag; + } + + @Override + public void checkLastTagWas(final int value) throws InvalidProtocolBufferException { + if (lastTag != value) { + throw InvalidProtocolBufferException.invalidEndTag(); + } + } + + @Override + public int getLastTag() { + return lastTag; + } + + @Override + public boolean skipField(final int tag) throws IOException { + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + skipRawVarint(); + return true; + case WireFormat.WIRETYPE_FIXED64: + skipRawBytes(FIXED64_SIZE); + return true; + case WireFormat.WIRETYPE_LENGTH_DELIMITED: + skipRawBytes(readRawVarint32()); + return true; + case WireFormat.WIRETYPE_START_GROUP: + skipMessage(); + checkLastTagWas( + WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP)); + return true; + case WireFormat.WIRETYPE_END_GROUP: + return false; + case WireFormat.WIRETYPE_FIXED32: + skipRawBytes(FIXED32_SIZE); + return true; + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + + @Override + public boolean skipField(final int tag, final CodedOutputStream output) throws IOException { + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + { + long value = readInt64(); + output.writeRawVarint32(tag); + output.writeUInt64NoTag(value); + return true; + } + case WireFormat.WIRETYPE_FIXED64: + { + long value = readRawLittleEndian64(); + output.writeRawVarint32(tag); + output.writeFixed64NoTag(value); + return true; + } + case WireFormat.WIRETYPE_LENGTH_DELIMITED: + { + ByteString value = readBytes(); + output.writeRawVarint32(tag); + output.writeBytesNoTag(value); + return true; + } + case WireFormat.WIRETYPE_START_GROUP: + { + output.writeRawVarint32(tag); + skipMessage(output); + int endtag = + WireFormat.makeTag( + WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP); + checkLastTagWas(endtag); + output.writeRawVarint32(endtag); + return true; + } + case WireFormat.WIRETYPE_END_GROUP: + { + return false; + } + case WireFormat.WIRETYPE_FIXED32: + { + int value = readRawLittleEndian32(); + output.writeRawVarint32(tag); + output.writeFixed32NoTag(value); + return true; + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + + @Override + public void skipMessage() throws IOException { + while (true) { + final int tag = readTag(); + if (tag == 0 || !skipField(tag)) { + return; + } + } + } + + @Override + public void skipMessage(CodedOutputStream output) throws IOException { + while (true) { + final int tag = readTag(); + if (tag == 0 || !skipField(tag, output)) { + return; + } } + } + + // ----------------------------------------------------------------- + + @Override + public double readDouble() throws IOException { + return Double.longBitsToDouble(readRawLittleEndian64()); + } + + @Override + public float readFloat() throws IOException { + return Float.intBitsToFloat(readRawLittleEndian32()); + } + + @Override + public long readUInt64() throws IOException { + return readRawVarint64(); + } + + @Override + public long readInt64() throws IOException { + return readRawVarint64(); + } + + @Override + public int readInt32() throws IOException { + return readRawVarint32(); + } - pos = size - tempPos; + @Override + public long readFixed64() throws IOException { + return readRawLittleEndian64(); + } + + @Override + public int readFixed32() throws IOException { + return readRawLittleEndian32(); + } + + @Override + public boolean readBool() throws IOException { + return readRawVarint64() != 0; + } + + @Override + public String readString() throws IOException { + final int size = readRawVarint32(); + if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) { + byte[] bytes = new byte[size]; + UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size); + String result = new String(bytes, UTF_8); + currentByteBufferPos += size; + return result; + } else if (size > 0 && size <= remaining()) { + // TODO(yilunchong): To use an underlying bytes[] instead of allocating a new bytes[] + byte[] bytes = new byte[size]; + readRawBytesTo(bytes, 0, size); + String result = new String(bytes, UTF_8); + return result; + } + + if (size == 0) { + return ""; + } + if (size < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } + throw InvalidProtocolBufferException.truncatedMessage(); + } + + @Override + public String readStringRequireUtf8() throws IOException { + final int size = readRawVarint32(); + if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) { + final int bufferPos = (int) (currentByteBufferPos - currentByteBufferStartPos); + String result = Utf8.decodeUtf8(currentByteBuffer, bufferPos, size); + currentByteBufferPos += size; + return result; + } + if (size >= 0 && size <= remaining()) { + byte[] bytes = new byte[size]; + readRawBytesTo(bytes, 0, size); + return Utf8.decodeUtf8(bytes, 0, size); + } + + if (size == 0) { + return ""; + } + if (size <= 0) { + throw InvalidProtocolBufferException.negativeSize(); + } + throw InvalidProtocolBufferException.truncatedMessage(); + } + + @Override + public void readGroup( + final int fieldNumber, + final MessageLite.Builder builder, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + if (recursionDepth >= recursionLimit) { + throw InvalidProtocolBufferException.recursionLimitExceeded(); + } + ++recursionDepth; + builder.mergeFrom(this, extensionRegistry); + checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); + --recursionDepth; + } + + + @Override + public T readGroup( + final int fieldNumber, + final Parser parser, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + if (recursionDepth >= recursionLimit) { + throw InvalidProtocolBufferException.recursionLimitExceeded(); + } + ++recursionDepth; + T result = parser.parsePartialFrom(this, extensionRegistry); + checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); + --recursionDepth; + return result; + } + + @Deprecated + @Override + public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder) + throws IOException { + readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry()); + } + + @Override + public void readMessage( + final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry) + throws IOException { + final int length = readRawVarint32(); + if (recursionDepth >= recursionLimit) { + throw InvalidProtocolBufferException.recursionLimitExceeded(); + } + final int oldLimit = pushLimit(length); + ++recursionDepth; + builder.mergeFrom(this, extensionRegistry); + checkLastTagWas(0); + --recursionDepth; + popLimit(oldLimit); + } + + + @Override + public T readMessage( + final Parser parser, final ExtensionRegistryLite extensionRegistry) throws IOException { + int length = readRawVarint32(); + if (recursionDepth >= recursionLimit) { + throw InvalidProtocolBufferException.recursionLimitExceeded(); + } + final int oldLimit = pushLimit(length); + ++recursionDepth; + T result = parser.parsePartialFrom(this, extensionRegistry); + checkLastTagWas(0); + --recursionDepth; + popLimit(oldLimit); + return result; + } + + @Override + public ByteString readBytes() throws IOException { + final int size = readRawVarint32(); + if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) { + if (immutable && enableAliasing) { + final int idx = (int) (currentByteBufferPos - currentAddress); + final ByteString result = ByteString.wrap(slice(idx, idx + size)); + currentByteBufferPos += size; + return result; + } else { + byte[] bytes; + bytes = new byte[size]; + UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size); + currentByteBufferPos += size; + return ByteString.wrap(bytes); + } + } else if (size > 0 && size <= remaining()) { + byte[] temp = new byte[size]; + readRawBytesTo(temp, 0, size); + return ByteString.wrap(temp); + } + + if (size == 0) { + return ByteString.EMPTY; + } + if (size < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } + throw InvalidProtocolBufferException.truncatedMessage(); + } + + @Override + public byte[] readByteArray() throws IOException { + return readRawBytes(readRawVarint32()); + } + + @Override + public ByteBuffer readByteBuffer() throws IOException { + final int size = readRawVarint32(); + if (size > 0 && size <= currentRemaining()) { + if (!immutable && enableAliasing) { + currentByteBufferPos += size; + return slice( + (int) (currentByteBufferPos - currentAddress - size), + (int) (currentByteBufferPos - currentAddress)); + } else { + byte[] bytes = new byte[size]; + UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size); + currentByteBufferPos += size; + return ByteBuffer.wrap(bytes); + } + } else if (size > 0 && size <= remaining()) { + byte[] temp = new byte[size]; + readRawBytesTo(temp, 0, size); + return ByteBuffer.wrap(temp); + } + + if (size == 0) { + return EMPTY_BYTE_BUFFER; + } + if (size < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } + throw InvalidProtocolBufferException.truncatedMessage(); + } + + @Override + public int readUInt32() throws IOException { + return readRawVarint32(); + } + + @Override + public int readEnum() throws IOException { + return readRawVarint32(); + } + + @Override + public int readSFixed32() throws IOException { + return readRawLittleEndian32(); + } + + @Override + public long readSFixed64() throws IOException { + return readRawLittleEndian64(); + } + + @Override + public int readSInt32() throws IOException { + return decodeZigZag32(readRawVarint32()); + } + + @Override + public long readSInt64() throws IOException { + return decodeZigZag64(readRawVarint64()); + } + + @Override + public int readRawVarint32() throws IOException { + fastpath: + { + long tempPos = currentByteBufferPos; + + if (currentByteBufferLimit == currentByteBufferPos) { + break fastpath; + } + + int x; + if ((x = UnsafeUtil.getByte(tempPos++)) >= 0) { + currentByteBufferPos++; + return x; + } else if (currentByteBufferLimit - currentByteBufferPos < 10) { + break fastpath; + } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) { + x ^= (~0 << 7); + } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) { + x ^= (~0 << 7) ^ (~0 << 14); + } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) { + x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21); + } else { + int y = UnsafeUtil.getByte(tempPos++); + x ^= y << 28; + x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28); + if (y < 0 + && UnsafeUtil.getByte(tempPos++) < 0 + && UnsafeUtil.getByte(tempPos++) < 0 + && UnsafeUtil.getByte(tempPos++) < 0 + && UnsafeUtil.getByte(tempPos++) < 0 + && UnsafeUtil.getByte(tempPos++) < 0) { + break fastpath; // Will throw malformedVarint() + } + } + currentByteBufferPos = tempPos; + return x; + } + return (int) readRawVarint64SlowPath(); + } + + @Override + public long readRawVarint64() throws IOException { + fastpath: + { + long tempPos = currentByteBufferPos; + + if (currentByteBufferLimit == currentByteBufferPos) { + break fastpath; + } + + long x; + int y; + if ((y = UnsafeUtil.getByte(tempPos++)) >= 0) { + currentByteBufferPos++; + return y; + } else if (currentByteBufferLimit - currentByteBufferPos < 10) { + break fastpath; + } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) { + x = y ^ (~0 << 7); + } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) { + x = y ^ ((~0 << 7) ^ (~0 << 14)); + } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) { + x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21)); + } else if ((x = y ^ ((long) UnsafeUtil.getByte(tempPos++) << 28)) >= 0L) { + x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28); + } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 35)) < 0L) { + x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35); + } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 42)) >= 0L) { + x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42); + } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 49)) < 0L) { + x ^= + (~0L << 7) + ^ (~0L << 14) + ^ (~0L << 21) + ^ (~0L << 28) + ^ (~0L << 35) + ^ (~0L << 42) + ^ (~0L << 49); + } else { + x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56); + x ^= + (~0L << 7) + ^ (~0L << 14) + ^ (~0L << 21) + ^ (~0L << 28) + ^ (~0L << 35) + ^ (~0L << 42) + ^ (~0L << 49) + ^ (~0L << 56); + if (x < 0L) { + if (UnsafeUtil.getByte(tempPos++) < 0L) { + break fastpath; // Will throw malformedVarint() + } + } + } + currentByteBufferPos = tempPos; + return x; + } + return readRawVarint64SlowPath(); + } + + @Override + long readRawVarint64SlowPath() throws IOException { + long result = 0; + for (int shift = 0; shift < 64; shift += 7) { + final byte b = readRawByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + } + throw InvalidProtocolBufferException.malformedVarint(); + } + + @Override + public int readRawLittleEndian32() throws IOException { + if (currentRemaining() >= FIXED32_SIZE) { + long tempPos = currentByteBufferPos; + currentByteBufferPos += FIXED32_SIZE; + return (((UnsafeUtil.getByte(tempPos) & 0xff)) + | ((UnsafeUtil.getByte(tempPos + 1) & 0xff) << 8) + | ((UnsafeUtil.getByte(tempPos + 2) & 0xff) << 16) + | ((UnsafeUtil.getByte(tempPos + 3) & 0xff) << 24)); + } + return ((readRawByte() & 0xff) + | ((readRawByte() & 0xff) << 8) + | ((readRawByte() & 0xff) << 16) + | ((readRawByte() & 0xff) << 24)); + } + + @Override + public long readRawLittleEndian64() throws IOException { + if (currentRemaining() >= FIXED64_SIZE) { + long tempPos = currentByteBufferPos; + currentByteBufferPos += FIXED64_SIZE; + return (((UnsafeUtil.getByte(tempPos) & 0xffL)) + | ((UnsafeUtil.getByte(tempPos + 1) & 0xffL) << 8) + | ((UnsafeUtil.getByte(tempPos + 2) & 0xffL) << 16) + | ((UnsafeUtil.getByte(tempPos + 3) & 0xffL) << 24) + | ((UnsafeUtil.getByte(tempPos + 4) & 0xffL) << 32) + | ((UnsafeUtil.getByte(tempPos + 5) & 0xffL) << 40) + | ((UnsafeUtil.getByte(tempPos + 6) & 0xffL) << 48) + | ((UnsafeUtil.getByte(tempPos + 7) & 0xffL) << 56)); + } + return ((readRawByte() & 0xffL) + | ((readRawByte() & 0xffL) << 8) + | ((readRawByte() & 0xffL) << 16) + | ((readRawByte() & 0xffL) << 24) + | ((readRawByte() & 0xffL) << 32) + | ((readRawByte() & 0xffL) << 40) + | ((readRawByte() & 0xffL) << 48) + | ((readRawByte() & 0xffL) << 56)); + } + + @Override + public void enableAliasing(boolean enabled) { + this.enableAliasing = enabled; + } + + @Override + public void resetSizeCounter() { + startOffset = (int) (totalBytesRead + currentByteBufferPos - currentByteBufferStartPos); + } + + @Override + public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { + if (byteLimit < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } + byteLimit += getTotalBytesRead(); + final int oldLimit = currentLimit; + if (byteLimit > oldLimit) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + currentLimit = byteLimit; + + recomputeBufferSizeAfterLimit(); + + return oldLimit; + } + + private void recomputeBufferSizeAfterLimit() { + totalBufferSize += bufferSizeAfterCurrentLimit; + final int bufferEnd = totalBufferSize - startOffset; + if (bufferEnd > currentLimit) { + // Limit is in current buffer. + bufferSizeAfterCurrentLimit = bufferEnd - currentLimit; + totalBufferSize -= bufferSizeAfterCurrentLimit; + } else { + bufferSizeAfterCurrentLimit = 0; + } + } + + @Override + public void popLimit(final int oldLimit) { + currentLimit = oldLimit; + recomputeBufferSizeAfterLimit(); + } + + @Override + public int getBytesUntilLimit() { + if (currentLimit == Integer.MAX_VALUE) { + return -1; + } + + return currentLimit - getTotalBytesRead(); + } + + @Override + public boolean isAtEnd() throws IOException { + return totalBytesRead + currentByteBufferPos - currentByteBufferStartPos == totalBufferSize; + } + + @Override + public int getTotalBytesRead() { + return (int) + (totalBytesRead - startOffset + currentByteBufferPos - currentByteBufferStartPos); + } + + @Override + public byte readRawByte() throws IOException { + if (currentRemaining() == 0) { + getNextByteBuffer(); + } + return UnsafeUtil.getByte(currentByteBufferPos++); + } + + @Override + public byte[] readRawBytes(final int length) throws IOException { + if (length >= 0 && length <= currentRemaining()) { + byte[] bytes = new byte[length]; + UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, length); + currentByteBufferPos += length; + return bytes; + } + if (length >= 0 && length <= remaining()) { + byte[] bytes = new byte[length]; + readRawBytesTo(bytes, 0, length); + return bytes; + } + + if (length <= 0) { + if (length == 0) { + return EMPTY_BYTE_ARRAY; + } else { + throw InvalidProtocolBufferException.negativeSize(); + } + } + + throw InvalidProtocolBufferException.truncatedMessage(); + } + + /** + * Try to get raw bytes from {@code input} with the size of {@code length} and copy to {@code + * bytes} array. If the size is bigger than the number of remaining bytes in the input, then + * throw {@code truncatedMessage} exception. + * + * @param bytes + * @param offset + * @param length + * @throws IOException + */ + private void readRawBytesTo(byte[] bytes, int offset, final int length) throws IOException { + if (length >= 0 && length <= remaining()) { + int l = length; + while (l > 0) { + if (currentRemaining() == 0) { + getNextByteBuffer(); + } + int bytesToCopy = Math.min(l, (int) currentRemaining()); + UnsafeUtil.copyMemory(currentByteBufferPos, bytes, length - l + offset, bytesToCopy); + l -= bytesToCopy; + currentByteBufferPos += bytesToCopy; + } + return; + } + + if (length <= 0) { + if (length == 0) { + return; + } else { + throw InvalidProtocolBufferException.negativeSize(); + } + } + throw InvalidProtocolBufferException.truncatedMessage(); + } + + @Override + public void skipRawBytes(final int length) throws IOException { + if (length >= 0 + && length + <= (totalBufferSize + - totalBytesRead + - currentByteBufferPos + + currentByteBufferStartPos)) { + // We have all the bytes we need already. + int l = length; + while (l > 0) { + if (currentRemaining() == 0) { + getNextByteBuffer(); + } + int rl = Math.min(l, (int) currentRemaining()); + l -= rl; + currentByteBufferPos += rl; + } + return; + } + + if (length < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } + throw InvalidProtocolBufferException.truncatedMessage(); + } + + // TODO: optimize to fastpath + private void skipRawVarint() throws IOException { + for (int i = 0; i < MAX_VARINT_SIZE; i++) { + if (readRawByte() >= 0) { + return; + } + } + throw InvalidProtocolBufferException.malformedVarint(); + } + + /** + * Try to get the number of remaining bytes in {@code input}. + * + * @return the number of remaining bytes in {@code input}. + */ + private int remaining() { + return (int) + (totalBufferSize - totalBytesRead - currentByteBufferPos + currentByteBufferStartPos); + } + + /** + * Try to get the number of remaining bytes in {@code currentByteBuffer}. + * + * @return the number of remaining bytes in {@code currentByteBuffer} + */ + private long currentRemaining() { + return (currentByteBufferLimit - currentByteBufferPos); + } + + private ByteBuffer slice(int begin, int end) throws IOException { + int prevPos = currentByteBuffer.position(); + int prevLimit = currentByteBuffer.limit(); + try { + ((Buffer) currentByteBuffer).position(begin); + ((Buffer) currentByteBuffer).limit(end); + return currentByteBuffer.slice(); + } catch (IllegalArgumentException e) { + throw InvalidProtocolBufferException.truncatedMessage(); + } finally { + ((Buffer) currentByteBuffer).position(prevPos); + ((Buffer) currentByteBuffer).limit(prevLimit); + } } } } diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStreamReader.java b/java/core/src/main/java/com/google/protobuf/CodedInputStreamReader.java new file mode 100644 index 0000000000000..7658f629d3717 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/CodedInputStreamReader.java @@ -0,0 +1,1333 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.WireFormat.FIXED32_SIZE; +import static com.google.protobuf.WireFormat.FIXED64_SIZE; +import static com.google.protobuf.WireFormat.WIRETYPE_END_GROUP; +import static com.google.protobuf.WireFormat.WIRETYPE_FIXED32; +import static com.google.protobuf.WireFormat.WIRETYPE_FIXED64; +import static com.google.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED; +import static com.google.protobuf.WireFormat.WIRETYPE_START_GROUP; +import static com.google.protobuf.WireFormat.WIRETYPE_VARINT; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +/** An adapter between the {@link Reader} interface and {@link CodedInputStream}. */ +@ExperimentalApi +final class CodedInputStreamReader implements Reader { + private static final int FIXED32_MULTIPLE_MASK = FIXED32_SIZE - 1; + private static final int FIXED64_MULTIPLE_MASK = FIXED64_SIZE - 1; + private static final int NEXT_TAG_UNSET = 0; + + private final CodedInputStream input; + private int tag; + private int endGroupTag; + private int nextTag = NEXT_TAG_UNSET; + + public static CodedInputStreamReader forCodedInput(CodedInputStream input) { + if (input.wrapper != null) { + return input.wrapper; + } + return new CodedInputStreamReader(input); + } + + private CodedInputStreamReader(CodedInputStream input) { + this.input = Internal.checkNotNull(input, "input"); + this.input.wrapper = this; + } + + @Override + public boolean shouldDiscardUnknownFields() { + return input.shouldDiscardUnknownFields(); + } + + @Override + public int getFieldNumber() throws IOException { + if (nextTag != NEXT_TAG_UNSET) { + tag = nextTag; + nextTag = NEXT_TAG_UNSET; + } else { + tag = input.readTag(); + } + if (tag == 0 || tag == endGroupTag) { + return Reader.READ_DONE; + } + return WireFormat.getTagFieldNumber(tag); + } + + @Override + public int getTag() { + return tag; + } + + @Override + public boolean skipField() throws IOException { + if (input.isAtEnd() || tag == endGroupTag) { + return false; + } + return input.skipField(tag); + } + + private void requireWireType(int requiredWireType) throws IOException { + if (WireFormat.getTagWireType(tag) != requiredWireType) { + throw InvalidProtocolBufferException.invalidWireType(); + } + } + + @Override + public double readDouble() throws IOException { + requireWireType(WIRETYPE_FIXED64); + return input.readDouble(); + } + + @Override + public float readFloat() throws IOException { + requireWireType(WIRETYPE_FIXED32); + return input.readFloat(); + } + + @Override + public long readUInt64() throws IOException { + requireWireType(WIRETYPE_VARINT); + return input.readUInt64(); + } + + @Override + public long readInt64() throws IOException { + requireWireType(WIRETYPE_VARINT); + return input.readInt64(); + } + + @Override + public int readInt32() throws IOException { + requireWireType(WIRETYPE_VARINT); + return input.readInt32(); + } + + @Override + public long readFixed64() throws IOException { + requireWireType(WIRETYPE_FIXED64); + return input.readFixed64(); + } + + @Override + public int readFixed32() throws IOException { + requireWireType(WIRETYPE_FIXED32); + return input.readFixed32(); + } + + @Override + public boolean readBool() throws IOException { + requireWireType(WIRETYPE_VARINT); + return input.readBool(); + } + + @Override + public String readString() throws IOException { + requireWireType(WIRETYPE_LENGTH_DELIMITED); + return input.readString(); + } + + @Override + public String readStringRequireUtf8() throws IOException { + requireWireType(WIRETYPE_LENGTH_DELIMITED); + return input.readStringRequireUtf8(); + } + + @SuppressWarnings("unchecked") + @Override + public T readMessage(Class clazz, ExtensionRegistryLite extensionRegistry) + throws IOException { + requireWireType(WIRETYPE_LENGTH_DELIMITED); + return readMessage(Protobuf.getInstance().schemaFor(clazz), extensionRegistry); + } + + @SuppressWarnings("unchecked") + @Override + public T readMessageBySchemaWithCheck( + Schema schema, ExtensionRegistryLite extensionRegistry) throws IOException { + requireWireType(WIRETYPE_LENGTH_DELIMITED); + return readMessage(schema, extensionRegistry); + } + + @SuppressWarnings("unchecked") + @Override + public T readGroup(Class clazz, ExtensionRegistryLite extensionRegistry) + throws IOException { + requireWireType(WIRETYPE_START_GROUP); + return readGroup(Protobuf.getInstance().schemaFor(clazz), extensionRegistry); + } + + @SuppressWarnings("unchecked") + @Override + public T readGroupBySchemaWithCheck(Schema schema, ExtensionRegistryLite extensionRegistry) + throws IOException { + requireWireType(WIRETYPE_START_GROUP); + return readGroup(schema, extensionRegistry); + } + + // Should have the same semantics of CodedInputStream#readMessage() + private T readMessage(Schema schema, ExtensionRegistryLite extensionRegistry) + throws IOException { + int size = input.readUInt32(); + if (input.recursionDepth >= input.recursionLimit) { + throw InvalidProtocolBufferException.recursionLimitExceeded(); + } + + // Push the new limit. + final int prevLimit = input.pushLimit(size); + // Allocate and read the message. + T message = schema.newInstance(); + ++input.recursionDepth; + schema.mergeFrom(message, this, extensionRegistry); + schema.makeImmutable(message); + input.checkLastTagWas(0); + --input.recursionDepth; + // Restore the previous limit. + input.popLimit(prevLimit); + return message; + } + + private T readGroup(Schema schema, ExtensionRegistryLite extensionRegistry) + throws IOException { + int prevEndGroupTag = endGroupTag; + endGroupTag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WIRETYPE_END_GROUP); + + try { + // Allocate and read the message. + T message = schema.newInstance(); + schema.mergeFrom(message, this, extensionRegistry); + schema.makeImmutable(message); + + if (tag != endGroupTag) { + throw InvalidProtocolBufferException.parseFailure(); + } + return message; + } finally { + // Restore the old end group tag. + endGroupTag = prevEndGroupTag; + } + } + + @Override + public ByteString readBytes() throws IOException { + requireWireType(WIRETYPE_LENGTH_DELIMITED); + return input.readBytes(); + } + + @Override + public int readUInt32() throws IOException { + requireWireType(WIRETYPE_VARINT); + return input.readUInt32(); + } + + @Override + public int readEnum() throws IOException { + requireWireType(WIRETYPE_VARINT); + return input.readEnum(); + } + + @Override + public int readSFixed32() throws IOException { + requireWireType(WIRETYPE_FIXED32); + return input.readSFixed32(); + } + + @Override + public long readSFixed64() throws IOException { + requireWireType(WIRETYPE_FIXED64); + return input.readSFixed64(); + } + + @Override + public int readSInt32() throws IOException { + requireWireType(WIRETYPE_VARINT); + return input.readSInt32(); + } + + @Override + public long readSInt64() throws IOException { + requireWireType(WIRETYPE_VARINT); + return input.readSInt64(); + } + + @Override + public void readDoubleList(List target) throws IOException { + if (target instanceof DoubleArrayList) { + DoubleArrayList plist = (DoubleArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + verifyPackedFixed64Length(bytes); + int endPos = input.getTotalBytesRead() + bytes; + do { + plist.addDouble(input.readDouble()); + } while (input.getTotalBytesRead() < endPos); + break; + case WIRETYPE_FIXED64: + while (true) { + plist.addDouble(input.readDouble()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + verifyPackedFixed64Length(bytes); + int endPos = input.getTotalBytesRead() + bytes; + do { + target.add(input.readDouble()); + } while (input.getTotalBytesRead() < endPos); + break; + case WIRETYPE_FIXED64: + while (true) { + target.add(input.readDouble()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readFloatList(List target) throws IOException { + if (target instanceof FloatArrayList) { + FloatArrayList plist = (FloatArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + verifyPackedFixed32Length(bytes); + int endPos = input.getTotalBytesRead() + bytes; + do { + plist.addFloat(input.readFloat()); + } while (input.getTotalBytesRead() < endPos); + break; + case WIRETYPE_FIXED32: + while (true) { + plist.addFloat(input.readFloat()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + verifyPackedFixed32Length(bytes); + int endPos = input.getTotalBytesRead() + bytes; + do { + target.add(input.readFloat()); + } while (input.getTotalBytesRead() < endPos); + break; + case WIRETYPE_FIXED32: + while (true) { + target.add(input.readFloat()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readUInt64List(List target) throws IOException { + if (target instanceof LongArrayList) { + LongArrayList plist = (LongArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + plist.addLong(input.readUInt64()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + plist.addLong(input.readUInt64()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + target.add(input.readUInt64()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + target.add(input.readUInt64()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readInt64List(List target) throws IOException { + if (target instanceof LongArrayList) { + LongArrayList plist = (LongArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + plist.addLong(input.readInt64()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + plist.addLong(input.readInt64()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + target.add(input.readInt64()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + target.add(input.readInt64()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readInt32List(List target) throws IOException { + if (target instanceof IntArrayList) { + IntArrayList plist = (IntArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + plist.addInt(input.readInt32()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + plist.addInt(input.readInt32()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + target.add(input.readInt32()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + target.add(input.readInt32()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readFixed64List(List target) throws IOException { + if (target instanceof LongArrayList) { + LongArrayList plist = (LongArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + verifyPackedFixed64Length(bytes); + int endPos = input.getTotalBytesRead() + bytes; + do { + plist.addLong(input.readFixed64()); + } while (input.getTotalBytesRead() < endPos); + break; + case WIRETYPE_FIXED64: + while (true) { + plist.addLong(input.readFixed64()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + verifyPackedFixed64Length(bytes); + int endPos = input.getTotalBytesRead() + bytes; + do { + target.add(input.readFixed64()); + } while (input.getTotalBytesRead() < endPos); + break; + case WIRETYPE_FIXED64: + while (true) { + target.add(input.readFixed64()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readFixed32List(List target) throws IOException { + if (target instanceof IntArrayList) { + IntArrayList plist = (IntArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + verifyPackedFixed32Length(bytes); + int endPos = input.getTotalBytesRead() + bytes; + do { + plist.addInt(input.readFixed32()); + } while (input.getTotalBytesRead() < endPos); + break; + case WIRETYPE_FIXED32: + while (true) { + plist.addInt(input.readFixed32()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + verifyPackedFixed32Length(bytes); + int endPos = input.getTotalBytesRead() + bytes; + do { + target.add(input.readFixed32()); + } while (input.getTotalBytesRead() < endPos); + break; + case WIRETYPE_FIXED32: + while (true) { + target.add(input.readFixed32()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readBoolList(List target) throws IOException { + if (target instanceof BooleanArrayList) { + BooleanArrayList plist = (BooleanArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + plist.addBoolean(input.readBool()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + plist.addBoolean(input.readBool()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + target.add(input.readBool()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + target.add(input.readBool()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readStringList(List target) throws IOException { + readStringListInternal(target, false); + } + + @Override + public void readStringListRequireUtf8(List target) throws IOException { + readStringListInternal(target, true); + } + + public void readStringListInternal(List target, boolean requireUtf8) throws IOException { + if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) { + throw InvalidProtocolBufferException.invalidWireType(); + } + + if (target instanceof LazyStringList && !requireUtf8) { + LazyStringList lazyList = (LazyStringList) target; + while (true) { + lazyList.add(readBytes()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + } else { + while (true) { + target.add(requireUtf8 ? readStringRequireUtf8() : readString()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + } + } + + @Override + public void readMessageList( + List target, Class targetType, ExtensionRegistryLite extensionRegistry) + throws IOException { + final Schema schema = Protobuf.getInstance().schemaFor(targetType); + readMessageList(target, schema, extensionRegistry); + } + + @Override + public void readMessageList( + List target, Schema schema, ExtensionRegistryLite extensionRegistry) + throws IOException { + if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) { + throw InvalidProtocolBufferException.invalidWireType(); + } + final int listTag = tag; + while (true) { + target.add(readMessage(schema, extensionRegistry)); + if (input.isAtEnd() || nextTag != NEXT_TAG_UNSET) { + return; + } + int nextTag = input.readTag(); + if (nextTag != listTag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + } + + @Override + public void readGroupList( + List target, Class targetType, ExtensionRegistryLite extensionRegistry) + throws IOException { + final Schema schema = Protobuf.getInstance().schemaFor(targetType); + readGroupList(target, schema, extensionRegistry); + } + + @Override + public void readGroupList( + List target, Schema schema, ExtensionRegistryLite extensionRegistry) + throws IOException { + if (WireFormat.getTagWireType(tag) != WIRETYPE_START_GROUP) { + throw InvalidProtocolBufferException.invalidWireType(); + } + final int listTag = tag; + while (true) { + target.add(readGroup(schema, extensionRegistry)); + if (input.isAtEnd() || nextTag != NEXT_TAG_UNSET) { + return; + } + int nextTag = input.readTag(); + if (nextTag != listTag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + } + + @Override + public void readBytesList(List target) throws IOException { + if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) { + throw InvalidProtocolBufferException.invalidWireType(); + } + + while (true) { + target.add(readBytes()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + } + + @Override + public void readUInt32List(List target) throws IOException { + if (target instanceof IntArrayList) { + IntArrayList plist = (IntArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + plist.addInt(input.readUInt32()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + plist.addInt(input.readUInt32()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + target.add(input.readUInt32()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + target.add(input.readUInt32()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readEnumList(List target) throws IOException { + if (target instanceof IntArrayList) { + IntArrayList plist = (IntArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + plist.addInt(input.readEnum()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + plist.addInt(input.readEnum()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + target.add(input.readEnum()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + target.add(input.readEnum()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readSFixed32List(List target) throws IOException { + if (target instanceof IntArrayList) { + IntArrayList plist = (IntArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + verifyPackedFixed32Length(bytes); + int endPos = input.getTotalBytesRead() + bytes; + do { + plist.addInt(input.readSFixed32()); + } while (input.getTotalBytesRead() < endPos); + break; + case WIRETYPE_FIXED32: + while (true) { + plist.addInt(input.readSFixed32()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + verifyPackedFixed32Length(bytes); + int endPos = input.getTotalBytesRead() + bytes; + do { + target.add(input.readSFixed32()); + } while (input.getTotalBytesRead() < endPos); + break; + case WIRETYPE_FIXED32: + while (true) { + target.add(input.readSFixed32()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readSFixed64List(List target) throws IOException { + if (target instanceof LongArrayList) { + LongArrayList plist = (LongArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + verifyPackedFixed64Length(bytes); + int endPos = input.getTotalBytesRead() + bytes; + do { + plist.addLong(input.readSFixed64()); + } while (input.getTotalBytesRead() < endPos); + break; + case WIRETYPE_FIXED64: + while (true) { + plist.addLong(input.readSFixed64()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + verifyPackedFixed64Length(bytes); + int endPos = input.getTotalBytesRead() + bytes; + do { + target.add(input.readSFixed64()); + } while (input.getTotalBytesRead() < endPos); + break; + case WIRETYPE_FIXED64: + while (true) { + target.add(input.readSFixed64()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readSInt32List(List target) throws IOException { + if (target instanceof IntArrayList) { + IntArrayList plist = (IntArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + plist.addInt(input.readSInt32()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + plist.addInt(input.readSInt32()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + target.add(input.readSInt32()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + target.add(input.readSInt32()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + @Override + public void readSInt64List(List target) throws IOException { + if (target instanceof LongArrayList) { + LongArrayList plist = (LongArrayList) target; + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + plist.addLong(input.readSInt64()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + plist.addLong(input.readSInt64()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } else { + switch (WireFormat.getTagWireType(tag)) { + case WIRETYPE_LENGTH_DELIMITED: + final int bytes = input.readUInt32(); + int endPos = input.getTotalBytesRead() + bytes; + do { + target.add(input.readSInt64()); + } while (input.getTotalBytesRead() < endPos); + requirePosition(endPos); + break; + case WIRETYPE_VARINT: + while (true) { + target.add(input.readSInt64()); + if (input.isAtEnd()) { + return; + } + int nextTag = input.readTag(); + if (nextTag != tag) { + // We've reached the end of the repeated field. Save the next tag value. + this.nextTag = nextTag; + return; + } + } + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + } + + private void verifyPackedFixed64Length(int bytes) throws IOException { + if ((bytes & FIXED64_MULTIPLE_MASK) != 0) { + // Require that the number of bytes be a multiple of 8. + throw InvalidProtocolBufferException.parseFailure(); + } + } + + @SuppressWarnings("unchecked") + @Override + public void readMap( + Map target, + MapEntryLite.Metadata metadata, + ExtensionRegistryLite extensionRegistry) + throws IOException { + requireWireType(WIRETYPE_LENGTH_DELIMITED); + int size = input.readUInt32(); + final int prevLimit = input.pushLimit(size); + K key = metadata.defaultKey; + V value = metadata.defaultValue; + try { + while (true) { + int number = getFieldNumber(); + if (number == READ_DONE || input.isAtEnd()) { + break; + } + try { + switch (number) { + case 1: + key = (K) readField(metadata.keyType, null, null); + break; + case 2: + value = + (V) + readField( + metadata.valueType, metadata.defaultValue.getClass(), extensionRegistry); + break; + default: + if (!skipField()) { + throw new InvalidProtocolBufferException("Unable to parse map entry."); + } + break; + } + } catch (InvalidProtocolBufferException.InvalidWireTypeException ignore) { + // the type doesn't match, skip the field. + if (!skipField()) { + throw new InvalidProtocolBufferException("Unable to parse map entry."); + } + } + } + target.put(key, value); + } finally { + // Restore the previous limit. + input.popLimit(prevLimit); + } + } + + private Object readField( + WireFormat.FieldType fieldType, Class messageType, ExtensionRegistryLite extensionRegistry) + throws IOException { + switch (fieldType) { + case BOOL: + return readBool(); + case BYTES: + return readBytes(); + case DOUBLE: + return readDouble(); + case ENUM: + return readEnum(); + case FIXED32: + return readFixed32(); + case FIXED64: + return readFixed64(); + case FLOAT: + return readFloat(); + case INT32: + return readInt32(); + case INT64: + return readInt64(); + case MESSAGE: + return readMessage(messageType, extensionRegistry); + case SFIXED32: + return readSFixed32(); + case SFIXED64: + return readSFixed64(); + case SINT32: + return readSInt32(); + case SINT64: + return readSInt64(); + case STRING: + return readStringRequireUtf8(); + case UINT32: + return readUInt32(); + case UINT64: + return readUInt64(); + default: + throw new RuntimeException("unsupported field type."); + } + } + + private void verifyPackedFixed32Length(int bytes) throws IOException { + if ((bytes & FIXED32_MULTIPLE_MASK) != 0) { + // Require that the number of bytes be a multiple of 4. + throw InvalidProtocolBufferException.parseFailure(); + } + } + + private void requirePosition(int expectedPosition) throws IOException { + if (input.getTotalBytesRead() != expectedPosition) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java b/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java index 093a5f616b6bf..a9192d33e44af 100644 --- a/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java +++ b/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java @@ -32,6 +32,7 @@ import static com.google.protobuf.WireFormat.FIXED32_SIZE; import static com.google.protobuf.WireFormat.FIXED64_SIZE; +import static com.google.protobuf.WireFormat.MAX_VARINT32_SIZE; import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE; import static java.lang.Math.max; @@ -47,12 +48,11 @@ /** * Encodes and writes protocol message fields. * - *

This class contains two kinds of methods: methods that write specific - * protocol message constructs and field types (e.g. {@link #writeTag} and - * {@link #writeInt32}) and methods that write low-level values (e.g. - * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are - * writing encoded protocol messages, you should use the former methods, but if - * you are writing some other format of your own design, use the latter. + *

This class contains two kinds of methods: methods that write specific protocol message + * constructs and field types (e.g. {@link #writeTag} and {@link #writeInt32}) and methods that + * write low-level values (e.g. {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are + * writing encoded protocol messages, you should use the former methods, but if you are writing some + * other format of your own design, use the latter. * *

This class is totally unsynchronized. */ @@ -60,23 +60,20 @@ public abstract class CodedOutputStream extends ByteOutput { private static final Logger logger = Logger.getLogger(CodedOutputStream.class.getName()); private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = UnsafeUtil.hasUnsafeArrayOperations(); - /** - * @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead. - */ - @Deprecated - public static final int LITTLE_ENDIAN_32_SIZE = FIXED32_SIZE; + /** Used to adapt to the experimental {@link Writer} interface. */ + CodedOutputStreamWriter wrapper; - /** - * The buffer size used in {@link #newInstance(OutputStream)}. - */ + /** @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead. */ + @Deprecated public static final int LITTLE_ENDIAN_32_SIZE = FIXED32_SIZE; + + /** The buffer size used in {@link #newInstance(OutputStream)}. */ public static final int DEFAULT_BUFFER_SIZE = 4096; /** - * Returns the buffer size to efficiently write dataLength bytes to this - * CodedOutputStream. Used by AbstractMessageLite. + * Returns the buffer size to efficiently write dataLength bytes to this CodedOutputStream. Used + * by AbstractMessageLite. * - * @return the buffer size to efficiently write dataLength bytes to this - * CodedOutputStream. + * @return the buffer size to efficiently write dataLength bytes to this CodedOutputStream. */ static int computePreferredBufferSize(int dataLength) { if (dataLength > DEFAULT_BUFFER_SIZE) { @@ -88,9 +85,9 @@ static int computePreferredBufferSize(int dataLength) { /** * Create a new {@code CodedOutputStream} wrapping the given {@code OutputStream}. * - *

NOTE: The provided {@link OutputStream} MUST NOT retain access or - * modify the provided byte arrays. Doing so may result in corrupted data, which would be - * difficult to debug. + *

NOTE: The provided {@link OutputStream} MUST NOT retain access or modify + * the provided byte arrays. Doing so may result in corrupted data, which would be difficult to + * debug. */ public static CodedOutputStream newInstance(final OutputStream output) { return newInstance(output, DEFAULT_BUFFER_SIZE); @@ -100,30 +97,28 @@ public static CodedOutputStream newInstance(final OutputStream output) { * Create a new {@code CodedOutputStream} wrapping the given {@code OutputStream} with a given * buffer size. * - *

NOTE: The provided {@link OutputStream} MUST NOT retain access or - * modify the provided byte arrays. Doing so may result in corrupted data, which would be - * difficult to debug. + *

NOTE: The provided {@link OutputStream} MUST NOT retain access or modify + * the provided byte arrays. Doing so may result in corrupted data, which would be difficult to + * debug. */ public static CodedOutputStream newInstance(final OutputStream output, final int bufferSize) { return new OutputStreamEncoder(output, bufferSize); } /** - * Create a new {@code CodedOutputStream} that writes directly to the given - * byte array. If more bytes are written than fit in the array, - * {@link OutOfSpaceException} will be thrown. Writing directly to a flat - * array is faster than writing to an {@code OutputStream}. See also - * {@link ByteString#newCodedBuilder}. + * Create a new {@code CodedOutputStream} that writes directly to the given byte array. If more + * bytes are written than fit in the array, {@link OutOfSpaceException} will be thrown. Writing + * directly to a flat array is faster than writing to an {@code OutputStream}. See also {@link + * ByteString#newCodedBuilder}. */ public static CodedOutputStream newInstance(final byte[] flatArray) { return newInstance(flatArray, 0, flatArray.length); } /** - * Create a new {@code CodedOutputStream} that writes directly to the given - * byte array slice. If more bytes are written than fit in the slice, - * {@link OutOfSpaceException} will be thrown. Writing directly to a flat - * array is faster than writing to an {@code OutputStream}. See also + * Create a new {@code CodedOutputStream} that writes directly to the given byte array slice. If + * more bytes are written than fit in the slice, {@link OutOfSpaceException} will be thrown. + * Writing directly to a flat array is faster than writing to an {@code OutputStream}. See also * {@link ByteString#newCodedBuilder}. */ public static CodedOutputStream newInstance( @@ -162,9 +157,9 @@ static CodedOutputStream newSafeInstance(ByteBuffer buffer) { * implies: * *

    - *
  • repeated serialization of a message will return the same bytes - *
  • different processes of the same binary (which may be executing on different machines) will - * serialize equal messages to the same bytes. + *
  • repeated serialization of a message will return the same bytes + *
  • different processes of the same binary (which may be executing on different machines) + * will serialize equal messages to the same bytes. *
* *

Note the deterministic serialization is NOT canonical across languages; it is also unstable @@ -173,14 +168,14 @@ static CodedOutputStream newSafeInstance(ByteBuffer buffer) { * their own canonicalization specification and implement the serializer using reflection APIs * rather than relying on this API. * - *

Once set, the serializer will: (Note this is an implementation detail and may subject to + *

Once set, the serializer will: (Note this is an implementation detail and may subject to * change in the future) * *

    - *
  • sort map entries by keys in lexicographical order or numerical order. Note: For string - * keys, the order is based on comparing the Unicode value of each character in the strings. - * The order may be different from the deterministic serialization in other languages where - * maps are sorted on the lexicographical order of the UTF8 encoded keys. + *
  • sort map entries by keys in lexicographical order or numerical order. Note: For string + * keys, the order is based on comparing the Unicode value of each character in the strings. + * The order may be different from the deterministic serialization in other languages where + * maps are sorted on the lexicographical order of the UTF8 encoded keys. *
*/ public void useDeterministicSerialization() { @@ -190,31 +185,32 @@ public void useDeterministicSerialization() { boolean isSerializationDeterministic() { return serializationDeterministic; } + private boolean serializationDeterministic; /** * Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}. * * @deprecated the size parameter is no longer used since use of an internal buffer is useless - * (and wasteful) when writing to a {@link ByteBuffer}. Use {@link #newInstance(ByteBuffer)} - * instead. + * (and wasteful) when writing to a {@link ByteBuffer}. Use {@link #newInstance(ByteBuffer)} + * instead. */ @Deprecated - public static CodedOutputStream newInstance(ByteBuffer byteBuffer, - @SuppressWarnings("unused") int unused) { + public static CodedOutputStream newInstance( + ByteBuffer byteBuffer, @SuppressWarnings("unused") int unused) { return newInstance(byteBuffer); } /** * Create a new {@code CodedOutputStream} that writes to the provided {@link ByteOutput}. * - *

NOTE: The {@link ByteOutput} MUST NOT modify the provided buffers. Doing - * so may result in corrupted data, which would be difficult to debug. + *

NOTE: The {@link ByteOutput} MUST NOT modify the provided buffers. Doing so + * may result in corrupted data, which would be difficult to debug. * * @param byteOutput the output target for encoded bytes. * @param bufferSize the size of the internal scratch buffer to be used for string encoding. - * Setting this to {@code 0} will disable buffering, requiring an allocation for each encoded - * string. + * Setting this to {@code 0} will disable buffering, requiring an allocation for each encoded + * string. */ static CodedOutputStream newInstance(ByteOutput byteOutput, int bufferSize) { if (bufferSize < 0) { @@ -225,8 +221,7 @@ static CodedOutputStream newInstance(ByteOutput byteOutput, int bufferSize) { } // Disallow construction outside of this class. - private CodedOutputStream() { - } + private CodedOutputStream() {} // ----------------------------------------------------------------- @@ -294,8 +289,8 @@ public final void writeDouble(final int fieldNumber, final double value) throws public abstract void writeBool(int fieldNumber, boolean value) throws IOException; /** - * Write an enum field, including tag, to the stream. The provided value is the numeric - * value used to represent the enum value on the wire (not the enum ordinal value). + * Write an enum field, including tag, to the stream. The provided value is the numeric value used + * to represent the enum value on the wire (not the enum ordinal value). */ public final void writeEnum(final int fieldNumber, final int value) throws IOException { writeInt32(fieldNumber, value); @@ -319,21 +314,17 @@ public abstract void writeByteArray(int fieldNumber, byte[] value, int offset, i throws IOException; /** - * Write a {@code bytes} field, including tag, to the stream. - * This method will write all content of the ByteBuffer regardless of the - * current position and limit (i.e., the number of bytes to be written is - * value.capacity(), not value.remaining()). Furthermore, this method doesn't - * alter the state of the passed-in ByteBuffer. Its position, limit, mark, - * etc. will remain unchanged. If you only want to write the remaining bytes - * of a ByteBuffer, you can call - * {@code writeByteBuffer(fieldNumber, byteBuffer.slice())}. + * Write a {@code bytes} field, including tag, to the stream. This method will write all content + * of the ByteBuffer regardless of the current position and limit (i.e., the number of bytes to be + * written is value.capacity(), not value.remaining()). Furthermore, this method doesn't alter the + * state of the passed-in ByteBuffer. Its position, limit, mark, etc. will remain unchanged. If + * you only want to write the remaining bytes of a ByteBuffer, you can call {@code + * writeByteBuffer(fieldNumber, byteBuffer.slice())}. */ // Abstract to avoid overhead of additional virtual method calls. public abstract void writeByteBuffer(int fieldNumber, ByteBuffer value) throws IOException; - /** - * Write a single byte. - */ + /** Write a single byte. */ public final void writeRawByte(final byte value) throws IOException { write(value); } @@ -348,9 +339,7 @@ public final void writeRawBytes(final byte[] value) throws IOException { write(value, 0, value.length); } - /** - * Write part of an array of bytes. - */ + /** Write part of an array of bytes. */ public final void writeRawBytes(final byte[] value, int offset, int length) throws IOException { write(value, offset, length); } @@ -361,13 +350,11 @@ public final void writeRawBytes(final ByteString value) throws IOException { } /** - * Write a ByteBuffer. This method will write all content of the ByteBuffer - * regardless of the current position and limit (i.e., the number of bytes - * to be written is value.capacity(), not value.remaining()). Furthermore, - * this method doesn't alter the state of the passed-in ByteBuffer. Its - * position, limit, mark, etc. will remain unchanged. If you only want to - * write the remaining bytes of a ByteBuffer, you can call - * {@code writeRawBytes(byteBuffer.slice())}. + * Write a ByteBuffer. This method will write all content of the ByteBuffer regardless of the + * current position and limit (i.e., the number of bytes to be written is value.capacity(), not + * value.remaining()). Furthermore, this method doesn't alter the state of the passed-in + * ByteBuffer. Its position, limit, mark, etc. will remain unchanged. If you only want to write + * the remaining bytes of a ByteBuffer, you can call {@code writeRawBytes(byteBuffer.slice())}. */ // Abstract to avoid overhead of additional virtual method calls. public abstract void writeRawBytes(final ByteBuffer value) throws IOException; @@ -377,17 +364,22 @@ public final void writeRawBytes(final ByteString value) throws IOException { public abstract void writeMessage(final int fieldNumber, final MessageLite value) throws IOException; + /** Write an embedded message field, including tag, to the stream. */ + // Abstract to avoid overhead of additional virtual method calls. + abstract void writeMessage(final int fieldNumber, final MessageLite value, Schema schema) + throws IOException; + /** - * Write a MessageSet extension field to the stream. For historical reasons, - * the wire format differs from normal fields. + * Write a MessageSet extension field to the stream. For historical reasons, the wire format + * differs from normal fields. */ // Abstract to avoid overhead of additional virtual method calls. public abstract void writeMessageSetExtension(final int fieldNumber, final MessageLite value) throws IOException; /** - * Write an unparsed MessageSet extension field to the stream. For - * historical reasons, the wire format differs from normal fields. + * Write an unparsed MessageSet extension field to the stream. For historical reasons, the wire + * format differs from normal fields. */ // Abstract to avoid overhead of additional virtual method calls. public abstract void writeRawMessageSetExtension(final int fieldNumber, final ByteString value) @@ -456,8 +448,8 @@ public final void writeBoolNoTag(final boolean value) throws IOException { } /** - * Write an enum field to the stream. The provided value is the numeric - * value used to represent the enum value on the wire (not the enum ordinal value). + * Write an enum field to the stream. The provided value is the numeric value used to represent + * the enum value on the wire (not the enum ordinal value). */ public final void writeEnumNoTag(final int value) throws IOException { writeInt32NoTag(value); @@ -481,7 +473,11 @@ public final void writeByteArrayNoTag(final byte[] value) throws IOException { // Abstract to avoid overhead of additional virtual method calls. public abstract void writeMessageNoTag(final MessageLite value) throws IOException; - //================================================================= + /** Write an embedded message field to the stream. */ + // Abstract to avoid overhead of additional virtual method calls. + abstract void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException; + + // ================================================================= @ExperimentalApi @Override @@ -506,170 +502,177 @@ public final void writeByteArrayNoTag(final byte[] value) throws IOException { // ================================================================= /** - * Compute the number of bytes that would be needed to encode an - * {@code int32} field, including tag. + * Compute the number of bytes that would be needed to encode an {@code int32} field, including + * tag. */ public static int computeInt32Size(final int fieldNumber, final int value) { return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode a - * {@code uint32} field, including tag. + * Compute the number of bytes that would be needed to encode a {@code uint32} field, including + * tag. */ public static int computeUInt32Size(final int fieldNumber, final int value) { return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode an - * {@code sint32} field, including tag. + * Compute the number of bytes that would be needed to encode an {@code sint32} field, including + * tag. */ public static int computeSInt32Size(final int fieldNumber, final int value) { return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode a - * {@code fixed32} field, including tag. + * Compute the number of bytes that would be needed to encode a {@code fixed32} field, including + * tag. */ public static int computeFixed32Size(final int fieldNumber, final int value) { return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode an - * {@code sfixed32} field, including tag. + * Compute the number of bytes that would be needed to encode an {@code sfixed32} field, including + * tag. */ public static int computeSFixed32Size(final int fieldNumber, final int value) { return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode an - * {@code int64} field, including tag. + * Compute the number of bytes that would be needed to encode an {@code int64} field, including + * tag. */ public static int computeInt64Size(final int fieldNumber, final long value) { return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode a - * {@code uint64} field, including tag. + * Compute the number of bytes that would be needed to encode a {@code uint64} field, including + * tag. */ public static int computeUInt64Size(final int fieldNumber, final long value) { return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode an - * {@code sint64} field, including tag. + * Compute the number of bytes that would be needed to encode an {@code sint64} field, including + * tag. */ public static int computeSInt64Size(final int fieldNumber, final long value) { return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode a - * {@code fixed64} field, including tag. + * Compute the number of bytes that would be needed to encode a {@code fixed64} field, including + * tag. */ public static int computeFixed64Size(final int fieldNumber, final long value) { return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode an - * {@code sfixed64} field, including tag. + * Compute the number of bytes that would be needed to encode an {@code sfixed64} field, including + * tag. */ public static int computeSFixed64Size(final int fieldNumber, final long value) { return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode a - * {@code float} field, including tag. + * Compute the number of bytes that would be needed to encode a {@code float} field, including + * tag. */ public static int computeFloatSize(final int fieldNumber, final float value) { return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode a - * {@code double} field, including tag. + * Compute the number of bytes that would be needed to encode a {@code double} field, including + * tag. */ public static int computeDoubleSize(final int fieldNumber, final double value) { return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode a - * {@code bool} field, including tag. + * Compute the number of bytes that would be needed to encode a {@code bool} field, including tag. */ public static int computeBoolSize(final int fieldNumber, final boolean value) { return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode an - * enum field, including tag. The provided value is the numeric - * value used to represent the enum value on the wire (not the enum ordinal value). + * Compute the number of bytes that would be needed to encode an enum field, including tag. The + * provided value is the numeric value used to represent the enum value on the wire (not the enum + * ordinal value). */ public static int computeEnumSize(final int fieldNumber, final int value) { return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode a - * {@code string} field, including tag. + * Compute the number of bytes that would be needed to encode a {@code string} field, including + * tag. */ public static int computeStringSize(final int fieldNumber, final String value) { return computeTagSize(fieldNumber) + computeStringSizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode a - * {@code bytes} field, including tag. + * Compute the number of bytes that would be needed to encode a {@code bytes} field, including + * tag. */ public static int computeBytesSize(final int fieldNumber, final ByteString value) { return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode a - * {@code bytes} field, including tag. + * Compute the number of bytes that would be needed to encode a {@code bytes} field, including + * tag. */ public static int computeByteArraySize(final int fieldNumber, final byte[] value) { return computeTagSize(fieldNumber) + computeByteArraySizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode a - * {@code bytes} field, including tag. + * Compute the number of bytes that would be needed to encode a {@code bytes} field, including + * tag. */ public static int computeByteBufferSize(final int fieldNumber, final ByteBuffer value) { return computeTagSize(fieldNumber) + computeByteBufferSizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode an - * embedded message in lazy field, including tag. + * Compute the number of bytes that would be needed to encode an embedded message in lazy field, + * including tag. */ public static int computeLazyFieldSize(final int fieldNumber, final LazyFieldLite value) { return computeTagSize(fieldNumber) + computeLazyFieldSizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode an - * embedded message field, including tag. + * Compute the number of bytes that would be needed to encode an embedded message field, including + * tag. */ public static int computeMessageSize(final int fieldNumber, final MessageLite value) { return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode a - * MessageSet extension to the stream. For historical reasons, - * the wire format differs from normal fields. + * Compute the number of bytes that would be needed to encode an embedded message field, including + * tag. + */ + static int computeMessageSize( + final int fieldNumber, final MessageLite value, final Schema schema) { + return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value, schema); + } + + /** + * Compute the number of bytes that would be needed to encode a MessageSet extension to the + * stream. For historical reasons, the wire format differs from normal fields. */ public static int computeMessageSetExtensionSize(final int fieldNumber, final MessageLite value) { return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 @@ -678,9 +681,8 @@ public static int computeMessageSetExtensionSize(final int fieldNumber, final Me } /** - * Compute the number of bytes that would be needed to encode an - * unparsed MessageSet extension field to the stream. For - * historical reasons, the wire format differs from normal fields. + * Compute the number of bytes that would be needed to encode an unparsed MessageSet extension + * field to the stream. For historical reasons, the wire format differs from normal fields. */ public static int computeRawMessageSetExtensionSize( final int fieldNumber, final ByteString value) { @@ -690,9 +692,9 @@ public static int computeRawMessageSetExtensionSize( } /** - * Compute the number of bytes that would be needed to encode an - * lazily parsed MessageSet extension field to the stream. For - * historical reasons, the wire format differs from normal fields. + * Compute the number of bytes that would be needed to encode an lazily parsed MessageSet + * extension field to the stream. For historical reasons, the wire format differs from normal + * fields. */ public static int computeLazyFieldMessageSetExtensionSize( final int fieldNumber, final LazyFieldLite value) { @@ -709,8 +711,8 @@ public static int computeTagSize(final int fieldNumber) { } /** - * Compute the number of bytes that would be needed to encode an - * {@code int32} field, including tag. + * Compute the number of bytes that would be needed to encode an {@code int32} field, including + * tag. */ public static int computeInt32SizeNoTag(final int value) { if (value >= 0) { @@ -721,12 +723,9 @@ public static int computeInt32SizeNoTag(final int value) { } } - /** - * Compute the number of bytes that would be needed to encode a - * {@code uint32} field. - */ + /** Compute the number of bytes that would be needed to encode a {@code uint32} field. */ public static int computeUInt32SizeNoTag(final int value) { - if ((value & (~0 << 7)) == 0) { + if ((value & (~0 << 7)) == 0) { return 1; } if ((value & (~0 << 14)) == 0) { @@ -741,41 +740,32 @@ public static int computeUInt32SizeNoTag(final int value) { return 5; } - /** - * Compute the number of bytes that would be needed to encode an - * {@code sint32} field. - */ + /** Compute the number of bytes that would be needed to encode an {@code sint32} field. */ public static int computeSInt32SizeNoTag(final int value) { return computeUInt32SizeNoTag(encodeZigZag32(value)); } - /** - * Compute the number of bytes that would be needed to encode a - * {@code fixed32} field. - */ + /** Compute the number of bytes that would be needed to encode a {@code fixed32} field. */ public static int computeFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) { return FIXED32_SIZE; } - /** - * Compute the number of bytes that would be needed to encode an - * {@code sfixed32} field. - */ + /** Compute the number of bytes that would be needed to encode an {@code sfixed32} field. */ public static int computeSFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) { return FIXED32_SIZE; } /** - * Compute the number of bytes that would be needed to encode an - * {@code int64} field, including tag. + * Compute the number of bytes that would be needed to encode an {@code int64} field, including + * tag. */ public static int computeInt64SizeNoTag(final long value) { return computeUInt64SizeNoTag(value); } /** - * Compute the number of bytes that would be needed to encode a - * {@code uint64} field, including tag. + * Compute the number of bytes that would be needed to encode a {@code uint64} field, including + * tag. */ public static int computeUInt64SizeNoTag(long value) { // handle two popular special cases up front ... @@ -788,10 +778,12 @@ public static int computeUInt64SizeNoTag(long value) { // ... leaving us with 8 remaining, which we can divide and conquer int n = 2; if ((value & (~0L << 35)) != 0L) { - n += 4; value >>>= 28; + n += 4; + value >>>= 28; } if ((value & (~0L << 21)) != 0L) { - n += 2; value >>>= 14; + n += 2; + value >>>= 14; } if ((value & (~0L << 14)) != 0L) { n += 1; @@ -799,67 +791,51 @@ public static int computeUInt64SizeNoTag(long value) { return n; } - /** - * Compute the number of bytes that would be needed to encode an - * {@code sint64} field. - */ + /** Compute the number of bytes that would be needed to encode an {@code sint64} field. */ public static int computeSInt64SizeNoTag(final long value) { return computeUInt64SizeNoTag(encodeZigZag64(value)); } - /** - * Compute the number of bytes that would be needed to encode a - * {@code fixed64} field. - */ + /** Compute the number of bytes that would be needed to encode a {@code fixed64} field. */ public static int computeFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) { return FIXED64_SIZE; } - /** - * Compute the number of bytes that would be needed to encode an - * {@code sfixed64} field. - */ + /** Compute the number of bytes that would be needed to encode an {@code sfixed64} field. */ public static int computeSFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) { return FIXED64_SIZE; } /** - * Compute the number of bytes that would be needed to encode a - * {@code float} field, including tag. + * Compute the number of bytes that would be needed to encode a {@code float} field, including + * tag. */ public static int computeFloatSizeNoTag(@SuppressWarnings("unused") final float unused) { return FIXED32_SIZE; } /** - * Compute the number of bytes that would be needed to encode a - * {@code double} field, including tag. + * Compute the number of bytes that would be needed to encode a {@code double} field, including + * tag. */ public static int computeDoubleSizeNoTag(@SuppressWarnings("unused") final double unused) { return FIXED64_SIZE; } - /** - * Compute the number of bytes that would be needed to encode a - * {@code bool} field. - */ + /** Compute the number of bytes that would be needed to encode a {@code bool} field. */ public static int computeBoolSizeNoTag(@SuppressWarnings("unused") final boolean unused) { return 1; } /** - * Compute the number of bytes that would be needed to encode an enum field. - * The provided value is the numeric value used to represent the enum value on the wire - * (not the enum ordinal value). + * Compute the number of bytes that would be needed to encode an enum field. The provided value is + * the numeric value used to represent the enum value on the wire (not the enum ordinal value). */ public static int computeEnumSizeNoTag(final int value) { return computeInt32SizeNoTag(value); } - /** - * Compute the number of bytes that would be needed to encode a - * {@code string} field. - */ + /** Compute the number of bytes that would be needed to encode a {@code string} field. */ public static int computeStringSizeNoTag(final String value) { int length; try { @@ -874,58 +850,50 @@ public static int computeStringSizeNoTag(final String value) { } /** - * Compute the number of bytes that would be needed to encode an embedded - * message stored in lazy field. + * Compute the number of bytes that would be needed to encode an embedded message stored in lazy + * field. */ public static int computeLazyFieldSizeNoTag(final LazyFieldLite value) { return computeLengthDelimitedFieldSize(value.getSerializedSize()); } - /** - * Compute the number of bytes that would be needed to encode a - * {@code bytes} field. - */ + /** Compute the number of bytes that would be needed to encode a {@code bytes} field. */ public static int computeBytesSizeNoTag(final ByteString value) { return computeLengthDelimitedFieldSize(value.size()); } - /** - * Compute the number of bytes that would be needed to encode a - * {@code bytes} field. - */ + /** Compute the number of bytes that would be needed to encode a {@code bytes} field. */ public static int computeByteArraySizeNoTag(final byte[] value) { return computeLengthDelimitedFieldSize(value.length); } - /** - * Compute the number of bytes that would be needed to encode a - * {@code bytes} field. - */ + /** Compute the number of bytes that would be needed to encode a {@code bytes} field. */ public static int computeByteBufferSizeNoTag(final ByteBuffer value) { return computeLengthDelimitedFieldSize(value.capacity()); } - /** - * Compute the number of bytes that would be needed to encode an embedded - * message field. - */ + /** Compute the number of bytes that would be needed to encode an embedded message field. */ public static int computeMessageSizeNoTag(final MessageLite value) { return computeLengthDelimitedFieldSize(value.getSerializedSize()); } + /** Compute the number of bytes that would be needed to encode an embedded message field. */ + static int computeMessageSizeNoTag(final MessageLite value, final Schema schema) { + return computeLengthDelimitedFieldSize(((AbstractMessageLite) value).getSerializedSize(schema)); + } + static int computeLengthDelimitedFieldSize(int fieldLength) { return computeUInt32SizeNoTag(fieldLength) + fieldLength; } /** - * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers - * into values that can be efficiently encoded with varint. (Otherwise, - * negative values must be sign-extended to 64 bits to be varint encoded, - * thus always taking 10 bytes on the wire.) + * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers into values that can be + * efficiently encoded with varint. (Otherwise, negative values must be sign-extended to 64 bits + * to be varint encoded, thus always taking 10 bytes on the wire.) * * @param n A signed 32-bit integer. - * @return An unsigned 32-bit integer, stored in a signed int because - * Java has no explicit unsigned support. + * @return An unsigned 32-bit integer, stored in a signed int because Java has no explicit + * unsigned support. */ public static int encodeZigZag32(final int n) { // Note: the right-shift must be arithmetic @@ -933,14 +901,13 @@ public static int encodeZigZag32(final int n) { } /** - * Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers - * into values that can be efficiently encoded with varint. (Otherwise, - * negative values must be sign-extended to 64 bits to be varint encoded, - * thus always taking 10 bytes on the wire.) + * Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers into values that can be + * efficiently encoded with varint. (Otherwise, negative values must be sign-extended to 64 bits + * to be varint encoded, thus always taking 10 bytes on the wire.) * * @param n A signed 64-bit integer. - * @return An unsigned 64-bit integer, stored in a signed int because - * Java has no explicit unsigned support. + * @return An unsigned 64-bit integer, stored in a signed int because Java has no explicit + * unsigned support. */ public static long encodeZigZag64(final long n) { // Note: the right-shift must be arithmetic @@ -950,23 +917,22 @@ public static long encodeZigZag64(final long n) { // ================================================================= /** - * Flushes the stream and forces any buffered bytes to be written. This - * does not flush the underlying OutputStream. + * Flushes the stream and forces any buffered bytes to be written. This does not flush the + * underlying OutputStream. */ public abstract void flush() throws IOException; /** - * If writing to a flat array, return the space left in the array. - * Otherwise, throws {@code UnsupportedOperationException}. + * If writing to a flat array, return the space left in the array. Otherwise, throws {@code + * UnsupportedOperationException}. */ public abstract int spaceLeft(); /** - * Verifies that {@link #spaceLeft()} returns zero. It's common to create - * a byte array that is exactly big enough to hold a message, then write to - * it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()} - * after writing verifies that the message was actually as big as expected, - * which can help catch bugs. + * Verifies that {@link #spaceLeft()} returns zero. It's common to create a byte array that is + * exactly big enough to hold a message, then write to it with a {@code CodedOutputStream}. + * Calling {@code checkNoSpaceLeft()} after writing verifies that the message was actually as big + * as expected, which can help catch bugs. */ public final void checkNoSpaceLeft() { if (spaceLeft() != 0) { @@ -975,9 +941,8 @@ public final void checkNoSpaceLeft() { } /** - * If you create a CodedOutputStream around a simple flat array, you must - * not attempt to write more bytes than the array has space. Otherwise, - * this exception will be thrown. + * If you create a CodedOutputStream around a simple flat array, you must not attempt to write + * more bytes than the array has space. Otherwise, this exception will be thrown. */ public static class OutOfSpaceException extends IOException { private static final long serialVersionUID = -6947486886997889499L; @@ -1003,9 +968,8 @@ public static class OutOfSpaceException extends IOException { } /** - * Get the total number of bytes successfully written to this stream. The - * returned value is not guaranteed to be accurate if exceptions have been - * found in the middle of writing. + * Get the total number of bytes successfully written to this stream. The returned value is not + * guaranteed to be accurate if exceptions have been found in the middle of writing. */ public abstract int getTotalBytesWritten(); @@ -1017,8 +981,10 @@ abstract void writeByteArrayNoTag(final byte[] value, final int offset, final in final void inefficientWriteStringNoTag(String value, UnpairedSurrogateException cause) throws IOException { - logger.log(Level.WARNING, - "Converting ill-formed UTF-16. Your Protocol Buffer will not round trip correctly!", cause); + logger.log( + Level.WARNING, + "Converting ill-formed UTF-16. Your Protocol Buffer will not round trip correctly!", + cause); // Unfortunately there does not appear to be any way to tell Java to encode // UTF-8 directly into our buffer, so we have to let it create its own byte @@ -1049,6 +1015,19 @@ public final void writeGroup(final int fieldNumber, final MessageLite value) thr writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP); } + /** + * Write a {@code group} field, including tag, to the stream. + * + * @deprecated groups are deprecated. + */ + @Deprecated + final void writeGroup(final int fieldNumber, final MessageLite value, Schema schema) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP); + writeGroupNoTag(value, schema); + writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP); + } + /** * Write a {@code group} field to the stream. * @@ -1060,8 +1039,18 @@ public final void writeGroupNoTag(final MessageLite value) throws IOException { } /** - * Compute the number of bytes that would be needed to encode a - * {@code group} field, including tag. + * Write a {@code group} field to the stream. + * + * @deprecated groups are deprecated. + */ + @Deprecated + final void writeGroupNoTag(final MessageLite value, Schema schema) throws IOException { + schema.writeTo(value, wrapper); + } + + /** + * Compute the number of bytes that would be needed to encode a {@code group} field, including + * tag. * * @deprecated groups are deprecated. */ @@ -1071,17 +1060,31 @@ public static int computeGroupSize(final int fieldNumber, final MessageLite valu } /** - * Compute the number of bytes that would be needed to encode a - * {@code group} field. + * Compute the number of bytes that would be needed to encode a {@code group} field, including + * tag. + * + * @deprecated groups are deprecated. */ @Deprecated + static int computeGroupSize(final int fieldNumber, final MessageLite value, Schema schema) { + return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value, schema); + } + + /** Compute the number of bytes that would be needed to encode a {@code group} field. */ + @Deprecated public static int computeGroupSizeNoTag(final MessageLite value) { return value.getSerializedSize(); } + /** Compute the number of bytes that would be needed to encode a {@code group} field. */ + @Deprecated + static int computeGroupSizeNoTag(final MessageLite value, Schema schema) { + return ((AbstractMessageLite) value).getSerializedSize(schema); + } + /** - * Encode and write a varint. {@code value} is treated as - * unsigned, so it won't be sign-extended if negative. + * Encode and write a varint. {@code value} is treated as unsigned, so it won't be sign-extended + * if negative. * * @deprecated use {@link #writeUInt32NoTag} instead. */ @@ -1101,9 +1104,8 @@ public final void writeRawVarint64(long value) throws IOException { } /** - * Compute the number of bytes that would be needed to encode a varint. - * {@code value} is treated as unsigned, so it won't be sign-extended if - * negative. + * Compute the number of bytes that would be needed to encode a varint. {@code value} is treated + * as unsigned, so it won't be sign-extended if negative. * * @deprecated use {@link #computeUInt32SizeNoTag(int)} instead. */ @@ -1144,9 +1146,7 @@ public final void writeRawLittleEndian64(final long value) throws IOException { // ================================================================= - /** - * A {@link CodedOutputStream} that writes directly to a byte array. - */ + /** A {@link CodedOutputStream} that writes directly to a byte array. */ private static class ArrayEncoder extends CodedOutputStream { private final byte[] buffer; private final int offset; @@ -1158,9 +1158,10 @@ private static class ArrayEncoder extends CodedOutputStream { throw new NullPointerException("buffer"); } if ((offset | length | (buffer.length - (offset + length))) < 0) { - throw new IllegalArgumentException(String.format( - "Array range is invalid. Buffer.length=%d, offset=%d, length=%d", - buffer.length, offset, length)); + throw new IllegalArgumentException( + String.format( + "Array range is invalid. Buffer.length=%d, offset=%d, length=%d", + buffer.length, offset, length)); } this.buffer = buffer; this.offset = offset; @@ -1273,6 +1274,14 @@ public final void writeMessage(final int fieldNumber, final MessageLite value) writeMessageNoTag(value); } + @Override + final void writeMessage(final int fieldNumber, final MessageLite value, Schema schema) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema)); + schema.writeTo(value, wrapper); + } + @Override public final void writeMessageSetExtension(final int fieldNumber, final MessageLite value) throws IOException { @@ -1297,6 +1306,12 @@ public final void writeMessageNoTag(final MessageLite value) throws IOException value.writeTo(this); } + @Override + final void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException { + writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema)); + schema.writeTo(value, wrapper); + } + @Override public final void write(byte value) throws IOException { try { @@ -1319,16 +1334,34 @@ public final void writeInt32NoTag(int value) throws IOException { @Override public final void writeUInt32NoTag(int value) throws IOException { - if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) { - while (true) { - if ((value & ~0x7F) == 0) { - UnsafeUtil.putByte(buffer, position++, (byte) value); - return; - } else { - UnsafeUtil.putByte(buffer, position++, (byte) ((value & 0x7F) | 0x80)); - value >>>= 7; - } + if (HAS_UNSAFE_ARRAY_OPERATIONS + && !Android.isOnAndroidDevice() + && spaceLeft() >= MAX_VARINT32_SIZE) { + if ((value & ~0x7F) == 0) { + UnsafeUtil.putByte(buffer, position++, (byte) value); + return; } + UnsafeUtil.putByte(buffer, position++, (byte) (value | 0x80)); + value >>>= 7; + if ((value & ~0x7F) == 0) { + UnsafeUtil.putByte(buffer, position++, (byte) value); + return; + } + UnsafeUtil.putByte(buffer, position++, (byte) (value | 0x80)); + value >>>= 7; + if ((value & ~0x7F) == 0) { + UnsafeUtil.putByte(buffer, position++, (byte) value); + return; + } + UnsafeUtil.putByte(buffer, position++, (byte) (value | 0x80)); + value >>>= 7; + if ((value & ~0x7F) == 0) { + UnsafeUtil.putByte(buffer, position++, (byte) value); + return; + } + UnsafeUtil.putByte(buffer, position++, (byte) (value | 0x80)); + value >>>= 7; + UnsafeUtil.putByte(buffer, position++, (byte) value); } else { try { while (true) { @@ -1491,15 +1524,17 @@ public final int getTotalBytesWritten() { } /** - * A {@link CodedOutputStream} that writes directly to a heap {@link ByteBuffer}. Writes are - * done directly to the underlying array. The buffer position is only updated after a flush. + * A {@link CodedOutputStream} that writes directly to a heap {@link ByteBuffer}. Writes are done + * directly to the underlying array. The buffer position is only updated after a flush. */ private static final class HeapNioEncoder extends ArrayEncoder { private final ByteBuffer byteBuffer; private int initialPosition; HeapNioEncoder(ByteBuffer byteBuffer) { - super(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position(), + super( + byteBuffer.array(), + byteBuffer.arrayOffset() + byteBuffer.position(), byteBuffer.remaining()); this.byteBuffer = byteBuffer; this.initialPosition = byteBuffer.position(); @@ -1594,20 +1629,25 @@ public void writeByteArray( } @Override - public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) - throws IOException { + public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); writeUInt32NoTag(value.capacity()); writeRawBytes(value); } @Override - public void writeMessage(final int fieldNumber, final MessageLite value) - throws IOException { + public void writeMessage(final int fieldNumber, final MessageLite value) throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); writeMessageNoTag(value); } + @Override + void writeMessage(final int fieldNumber, final MessageLite value, Schema schema) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeMessageNoTag(value, schema); + } + @Override public void writeMessageSetExtension(final int fieldNumber, final MessageLite value) throws IOException { @@ -1632,6 +1672,12 @@ public void writeMessageNoTag(final MessageLite value) throws IOException { value.writeTo(this); } + @Override + void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException { + writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema)); + schema.writeTo(value, wrapper); + } + @Override public void write(byte value) throws IOException { try { @@ -1928,6 +1974,12 @@ public void writeMessage(int fieldNumber, MessageLite value) throws IOException writeMessageNoTag(value); } + @Override + void writeMessage(int fieldNumber, MessageLite value, Schema schema) throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeMessageNoTag(value, schema); + } + @Override public void writeMessageSetExtension(int fieldNumber, MessageLite value) throws IOException { writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); @@ -1950,6 +2002,12 @@ public void writeMessageNoTag(MessageLite value) throws IOException { value.writeTo(this); } + @Override + void writeMessageNoTag(MessageLite value, Schema schema) throws IOException { + writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema)); + schema.writeTo(value, wrapper); + } + @Override public void write(byte value) throws IOException { if (position >= limit) { @@ -2172,9 +2230,7 @@ private int bufferPos(long pos) { } } - /** - * Abstract base class for buffered encoders. - */ + /** Abstract base class for buffered encoders. */ private abstract static class AbstractBufferedEncoder extends CodedOutputStream { final byte[] buffer; final int limit; @@ -2332,8 +2388,8 @@ final void bufferFixed64NoTag(long value) { /** * A {@link CodedOutputStream} that decorates a {@link ByteOutput}. It internal buffer only to - * support string encoding operations. All other writes are just passed through to the - * {@link ByteOutput}. + * support string encoding operations. All other writes are just passed through to the {@link + * ByteOutput}. */ private static final class ByteOutputEncoder extends AbstractBufferedEncoder { private final ByteOutput out; @@ -2419,8 +2475,7 @@ public void writeByteArray( } @Override - public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) - throws IOException { + public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); writeUInt32NoTag(value.capacity()); writeRawBytes(value); @@ -2450,12 +2505,18 @@ public void writeRawBytes(final ByteBuffer value) throws IOException { } @Override - public void writeMessage(final int fieldNumber, final MessageLite value) - throws IOException { + public void writeMessage(final int fieldNumber, final MessageLite value) throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); writeMessageNoTag(value); } + @Override + void writeMessage(final int fieldNumber, final MessageLite value, Schema schema) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeMessageNoTag(value, schema); + } + @Override public void writeMessageSetExtension(final int fieldNumber, final MessageLite value) throws IOException { @@ -2480,6 +2541,12 @@ public void writeMessageNoTag(final MessageLite value) throws IOException { value.writeTo(this); } + @Override + void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException { + writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema)); + schema.writeTo(value, wrapper); + } + @Override public void write(byte value) throws IOException { if (position == limit) { @@ -2501,7 +2568,7 @@ public void writeInt32NoTag(int value) throws IOException { @Override public void writeUInt32NoTag(int value) throws IOException { - flushIfNotAvailable(MAX_VARINT_SIZE); + flushIfNotAvailable(MAX_VARINT32_SIZE); bufferUInt32NoTag(value); } @@ -2722,8 +2789,7 @@ public void writeByteArray( } @Override - public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) - throws IOException { + public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); writeUInt32NoTag(value.capacity()); writeRawBytes(value); @@ -2753,12 +2819,18 @@ public void writeRawBytes(final ByteBuffer value) throws IOException { } @Override - public void writeMessage(final int fieldNumber, final MessageLite value) - throws IOException { + public void writeMessage(final int fieldNumber, final MessageLite value) throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); writeMessageNoTag(value); } + @Override + void writeMessage(final int fieldNumber, final MessageLite value, Schema schema) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeMessageNoTag(value, schema); + } + @Override public void writeMessageSetExtension(final int fieldNumber, final MessageLite value) throws IOException { @@ -2783,6 +2855,12 @@ public void writeMessageNoTag(final MessageLite value) throws IOException { value.writeTo(this); } + @Override + void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException { + writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema)); + schema.writeTo(value, wrapper); + } + @Override public void write(byte value) throws IOException { if (position == limit) { @@ -2804,7 +2882,7 @@ public void writeInt32NoTag(int value) throws IOException { @Override public void writeUInt32NoTag(int value) throws IOException { - flushIfNotAvailable(MAX_VARINT_SIZE); + flushIfNotAvailable(MAX_VARINT32_SIZE); bufferUInt32NoTag(value); } @@ -2898,8 +2976,7 @@ public void flush() throws IOException { } @Override - public void write(byte[] value, int offset, int length) - throws IOException { + public void write(byte[] value, int offset, int length) throws IOException { if (limit - position >= length) { // We have room in the current buffer. System.arraycopy(value, offset, buffer, position, length); diff --git a/java/core/src/main/java/com/google/protobuf/CodedOutputStreamWriter.java b/java/core/src/main/java/com/google/protobuf/CodedOutputStreamWriter.java new file mode 100644 index 0000000000000..0d1983cb07b1c --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/CodedOutputStreamWriter.java @@ -0,0 +1,691 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.Internal.checkNotNull; +import static com.google.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** An adapter between the {@link Writer} interface and {@link CodedOutputStream}. */ +@ExperimentalApi +final class CodedOutputStreamWriter implements Writer { + private final CodedOutputStream output; + + public static CodedOutputStreamWriter forCodedOutput(CodedOutputStream output) { + if (output.wrapper != null) { + return output.wrapper; + } + return new CodedOutputStreamWriter(output); + } + + private CodedOutputStreamWriter(CodedOutputStream output) { + this.output = checkNotNull(output, "output"); + this.output.wrapper = this; + } + + @Override + public FieldOrder fieldOrder() { + return FieldOrder.ASCENDING; + } + + public int getTotalBytesWritten() { + return output.getTotalBytesWritten(); + } + + @Override + public void writeSFixed32(int fieldNumber, int value) throws IOException { + output.writeSFixed32(fieldNumber, value); + } + + @Override + public void writeInt64(int fieldNumber, long value) throws IOException { + output.writeInt64(fieldNumber, value); + } + + @Override + public void writeSFixed64(int fieldNumber, long value) throws IOException { + output.writeSFixed64(fieldNumber, value); + } + + @Override + public void writeFloat(int fieldNumber, float value) throws IOException { + output.writeFloat(fieldNumber, value); + } + + @Override + public void writeDouble(int fieldNumber, double value) throws IOException { + output.writeDouble(fieldNumber, value); + } + + @Override + public void writeEnum(int fieldNumber, int value) throws IOException { + output.writeEnum(fieldNumber, value); + } + + @Override + public void writeUInt64(int fieldNumber, long value) throws IOException { + output.writeUInt64(fieldNumber, value); + } + + @Override + public void writeInt32(int fieldNumber, int value) throws IOException { + output.writeInt32(fieldNumber, value); + } + + @Override + public void writeFixed64(int fieldNumber, long value) throws IOException { + output.writeFixed64(fieldNumber, value); + } + + @Override + public void writeFixed32(int fieldNumber, int value) throws IOException { + output.writeFixed32(fieldNumber, value); + } + + @Override + public void writeBool(int fieldNumber, boolean value) throws IOException { + output.writeBool(fieldNumber, value); + } + + @Override + public void writeString(int fieldNumber, String value) throws IOException { + output.writeString(fieldNumber, value); + } + + @Override + public void writeBytes(int fieldNumber, ByteString value) throws IOException { + output.writeBytes(fieldNumber, value); + } + + @Override + public void writeUInt32(int fieldNumber, int value) throws IOException { + output.writeUInt32(fieldNumber, value); + } + + @Override + public void writeSInt32(int fieldNumber, int value) throws IOException { + output.writeSInt32(fieldNumber, value); + } + + @Override + public void writeSInt64(int fieldNumber, long value) throws IOException { + output.writeSInt64(fieldNumber, value); + } + + @Override + public void writeMessage(int fieldNumber, Object value) throws IOException { + output.writeMessage(fieldNumber, (MessageLite) value); + } + + @Override + public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException { + output.writeMessage(fieldNumber, (MessageLite) value, schema); + } + + @Override + public void writeGroup(int fieldNumber, Object value) throws IOException { + output.writeGroup(fieldNumber, (MessageLite) value); + } + + @Override + public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException { + output.writeGroup(fieldNumber, (MessageLite) value, schema); + } + + @Override + public void writeStartGroup(int fieldNumber) throws IOException { + output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP); + } + + @Override + public void writeEndGroup(int fieldNumber) throws IOException { + output.writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP); + } + + @Override + public final void writeMessageSetItem(int fieldNumber, Object value) throws IOException { + if (value instanceof ByteString) { + output.writeRawMessageSetExtension(fieldNumber, (ByteString) value); + } else { + output.writeMessageSetExtension(fieldNumber, (MessageLite) value); + } + } + + @Override + public void writeInt32List(int fieldNumber, List value, boolean packed) + throws IOException { + if (packed) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + + // Compute and write the length of the data. + int dataSize = 0; + for (int i = 0; i < value.size(); ++i) { + dataSize += CodedOutputStream.computeInt32SizeNoTag(value.get(i)); + } + output.writeUInt32NoTag(dataSize); + + // Write the data itself, without any tags. + for (int i = 0; i < value.size(); ++i) { + output.writeInt32NoTag(value.get(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeInt32(fieldNumber, value.get(i)); + } + } + } + + @Override + public void writeFixed32List(int fieldNumber, List value, boolean packed) + throws IOException { + if (packed) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + + // Compute and write the length of the data. + int dataSize = 0; + for (int i = 0; i < value.size(); ++i) { + dataSize += CodedOutputStream.computeFixed32SizeNoTag(value.get(i)); + } + output.writeUInt32NoTag(dataSize); + + // Write the data itself, without any tags. + for (int i = 0; i < value.size(); ++i) { + output.writeFixed32NoTag(value.get(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeFixed32(fieldNumber, value.get(i)); + } + } + } + + @Override + public void writeInt64List(int fieldNumber, List value, boolean packed) throws IOException { + if (packed) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + + // Compute and write the length of the data. + int dataSize = 0; + for (int i = 0; i < value.size(); ++i) { + dataSize += CodedOutputStream.computeInt64SizeNoTag(value.get(i)); + } + output.writeUInt32NoTag(dataSize); + + // Write the data itself, without any tags. + for (int i = 0; i < value.size(); ++i) { + output.writeInt64NoTag(value.get(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeInt64(fieldNumber, value.get(i)); + } + } + } + + @Override + public void writeUInt64List(int fieldNumber, List value, boolean packed) + throws IOException { + if (packed) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + + // Compute and write the length of the data. + int dataSize = 0; + for (int i = 0; i < value.size(); ++i) { + dataSize += CodedOutputStream.computeUInt64SizeNoTag(value.get(i)); + } + output.writeUInt32NoTag(dataSize); + + // Write the data itself, without any tags. + for (int i = 0; i < value.size(); ++i) { + output.writeUInt64NoTag(value.get(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeUInt64(fieldNumber, value.get(i)); + } + } + } + + @Override + public void writeFixed64List(int fieldNumber, List value, boolean packed) + throws IOException { + if (packed) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + + // Compute and write the length of the data. + int dataSize = 0; + for (int i = 0; i < value.size(); ++i) { + dataSize += CodedOutputStream.computeFixed64SizeNoTag(value.get(i)); + } + output.writeUInt32NoTag(dataSize); + + // Write the data itself, without any tags. + for (int i = 0; i < value.size(); ++i) { + output.writeFixed64NoTag(value.get(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeFixed64(fieldNumber, value.get(i)); + } + } + } + + @Override + public void writeFloatList(int fieldNumber, List value, boolean packed) + throws IOException { + if (packed) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + + // Compute and write the length of the data. + int dataSize = 0; + for (int i = 0; i < value.size(); ++i) { + dataSize += CodedOutputStream.computeFloatSizeNoTag(value.get(i)); + } + output.writeUInt32NoTag(dataSize); + + // Write the data itself, without any tags. + for (int i = 0; i < value.size(); ++i) { + output.writeFloatNoTag(value.get(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeFloat(fieldNumber, value.get(i)); + } + } + } + + @Override + public void writeDoubleList(int fieldNumber, List value, boolean packed) + throws IOException { + if (packed) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + + // Compute and write the length of the data. + int dataSize = 0; + for (int i = 0; i < value.size(); ++i) { + dataSize += CodedOutputStream.computeDoubleSizeNoTag(value.get(i)); + } + output.writeUInt32NoTag(dataSize); + + // Write the data itself, without any tags. + for (int i = 0; i < value.size(); ++i) { + output.writeDoubleNoTag(value.get(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeDouble(fieldNumber, value.get(i)); + } + } + } + + @Override + public void writeEnumList(int fieldNumber, List value, boolean packed) + throws IOException { + if (packed) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + + // Compute and write the length of the data. + int dataSize = 0; + for (int i = 0; i < value.size(); ++i) { + dataSize += CodedOutputStream.computeEnumSizeNoTag(value.get(i)); + } + output.writeUInt32NoTag(dataSize); + + // Write the data itself, without any tags. + for (int i = 0; i < value.size(); ++i) { + output.writeEnumNoTag(value.get(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeEnum(fieldNumber, value.get(i)); + } + } + } + + @Override + public void writeBoolList(int fieldNumber, List value, boolean packed) + throws IOException { + if (packed) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + + // Compute and write the length of the data. + int dataSize = 0; + for (int i = 0; i < value.size(); ++i) { + dataSize += CodedOutputStream.computeBoolSizeNoTag(value.get(i)); + } + output.writeUInt32NoTag(dataSize); + + // Write the data itself, without any tags. + for (int i = 0; i < value.size(); ++i) { + output.writeBoolNoTag(value.get(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeBool(fieldNumber, value.get(i)); + } + } + } + + @Override + public void writeStringList(int fieldNumber, List value) throws IOException { + if (value instanceof LazyStringList) { + final LazyStringList lazyList = (LazyStringList) value; + for (int i = 0; i < value.size(); ++i) { + writeLazyString(fieldNumber, lazyList.getRaw(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeString(fieldNumber, value.get(i)); + } + } + } + + private void writeLazyString(int fieldNumber, Object value) throws IOException { + if (value instanceof String) { + output.writeString(fieldNumber, (String) value); + } else { + output.writeBytes(fieldNumber, (ByteString) value); + } + } + + @Override + public void writeBytesList(int fieldNumber, List value) throws IOException { + for (int i = 0; i < value.size(); ++i) { + output.writeBytes(fieldNumber, value.get(i)); + } + } + + @Override + public void writeUInt32List(int fieldNumber, List value, boolean packed) + throws IOException { + if (packed) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + + // Compute and write the length of the data. + int dataSize = 0; + for (int i = 0; i < value.size(); ++i) { + dataSize += CodedOutputStream.computeUInt32SizeNoTag(value.get(i)); + } + output.writeUInt32NoTag(dataSize); + + // Write the data itself, without any tags. + for (int i = 0; i < value.size(); ++i) { + output.writeUInt32NoTag(value.get(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeUInt32(fieldNumber, value.get(i)); + } + } + } + + @Override + public void writeSFixed32List(int fieldNumber, List value, boolean packed) + throws IOException { + if (packed) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + + // Compute and write the length of the data. + int dataSize = 0; + for (int i = 0; i < value.size(); ++i) { + dataSize += CodedOutputStream.computeSFixed32SizeNoTag(value.get(i)); + } + output.writeUInt32NoTag(dataSize); + + // Write the data itself, without any tags. + for (int i = 0; i < value.size(); ++i) { + output.writeSFixed32NoTag(value.get(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeSFixed32(fieldNumber, value.get(i)); + } + } + } + + @Override + public void writeSFixed64List(int fieldNumber, List value, boolean packed) + throws IOException { + if (packed) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + + // Compute and write the length of the data. + int dataSize = 0; + for (int i = 0; i < value.size(); ++i) { + dataSize += CodedOutputStream.computeSFixed64SizeNoTag(value.get(i)); + } + output.writeUInt32NoTag(dataSize); + + // Write the data itself, without any tags. + for (int i = 0; i < value.size(); ++i) { + output.writeSFixed64NoTag(value.get(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeSFixed64(fieldNumber, value.get(i)); + } + } + } + + @Override + public void writeSInt32List(int fieldNumber, List value, boolean packed) + throws IOException { + if (packed) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + + // Compute and write the length of the data. + int dataSize = 0; + for (int i = 0; i < value.size(); ++i) { + dataSize += CodedOutputStream.computeSInt32SizeNoTag(value.get(i)); + } + output.writeUInt32NoTag(dataSize); + + // Write the data itself, without any tags. + for (int i = 0; i < value.size(); ++i) { + output.writeSInt32NoTag(value.get(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeSInt32(fieldNumber, value.get(i)); + } + } + } + + @Override + public void writeSInt64List(int fieldNumber, List value, boolean packed) + throws IOException { + if (packed) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + + // Compute and write the length of the data. + int dataSize = 0; + for (int i = 0; i < value.size(); ++i) { + dataSize += CodedOutputStream.computeSInt64SizeNoTag(value.get(i)); + } + output.writeUInt32NoTag(dataSize); + + // Write the data itself, without any tags. + for (int i = 0; i < value.size(); ++i) { + output.writeSInt64NoTag(value.get(i)); + } + } else { + for (int i = 0; i < value.size(); ++i) { + output.writeSInt64(fieldNumber, value.get(i)); + } + } + } + + @Override + public void writeMessageList(int fieldNumber, List value) throws IOException { + for (int i = 0; i < value.size(); ++i) { + writeMessage(fieldNumber, value.get(i)); + } + } + + @Override + public void writeMessageList(int fieldNumber, List value, Schema schema) throws IOException { + for (int i = 0; i < value.size(); ++i) { + writeMessage(fieldNumber, value.get(i), schema); + } + } + + @Override + public void writeGroupList(int fieldNumber, List value) throws IOException { + for (int i = 0; i < value.size(); ++i) { + writeGroup(fieldNumber, value.get(i)); + } + } + + @Override + public void writeGroupList(int fieldNumber, List value, Schema schema) throws IOException { + for (int i = 0; i < value.size(); ++i) { + writeGroup(fieldNumber, value.get(i), schema); + } + } + + @Override + public void writeMap(int fieldNumber, MapEntryLite.Metadata metadata, Map map) + throws IOException { + if (output.isSerializationDeterministic()) { + writeDeterministicMap(fieldNumber, metadata, map); + return; + } + for (Map.Entry entry : map.entrySet()) { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + output.writeUInt32NoTag( + MapEntryLite.computeSerializedSize(metadata, entry.getKey(), entry.getValue())); + MapEntryLite.writeTo(output, metadata, entry.getKey(), entry.getValue()); + } + } + + @SuppressWarnings("unchecked") + private void writeDeterministicMap( + int fieldNumber, MapEntryLite.Metadata metadata, Map map) throws IOException { + switch (metadata.keyType) { + case BOOL: + V value; + if ((value = map.get(Boolean.FALSE)) != null) { + writeDeterministicBooleanMapEntry( + fieldNumber, /* key= */ false, value, (MapEntryLite.Metadata) metadata); + } + if ((value = map.get(Boolean.TRUE)) != null) { + writeDeterministicBooleanMapEntry( + fieldNumber, /* key= */ true, value, (MapEntryLite.Metadata) metadata); + } + break; + case FIXED32: + case INT32: + case SFIXED32: + case SINT32: + case UINT32: + writeDeterministicIntegerMap( + fieldNumber, (MapEntryLite.Metadata) metadata, (Map) map); + break; + case FIXED64: + case INT64: + case SFIXED64: + case SINT64: + case UINT64: + writeDeterministicLongMap( + fieldNumber, (MapEntryLite.Metadata) metadata, (Map) map); + break; + case STRING: + writeDeterministicStringMap( + fieldNumber, (MapEntryLite.Metadata) metadata, (Map) map); + break; + default: + throw new IllegalArgumentException("does not support key type: " + metadata.keyType); + } + } + + private void writeDeterministicBooleanMapEntry( + int fieldNumber, boolean key, V value, MapEntryLite.Metadata metadata) + throws IOException { + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value)); + MapEntryLite.writeTo(output, metadata, key, value); + } + + private void writeDeterministicIntegerMap( + int fieldNumber, MapEntryLite.Metadata metadata, Map map) + throws IOException { + int[] keys = new int[map.size()]; + int index = 0; + for (int k : map.keySet()) { + keys[index++] = k; + } + Arrays.sort(keys); + for (int key : keys) { + V value = map.get(key); + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value)); + MapEntryLite.writeTo(output, metadata, key, value); + } + } + + private void writeDeterministicLongMap( + int fieldNumber, MapEntryLite.Metadata metadata, Map map) + throws IOException { + long[] keys = new long[map.size()]; + int index = 0; + for (long k : map.keySet()) { + keys[index++] = k; + } + Arrays.sort(keys); + for (long key : keys) { + V value = map.get(key); + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value)); + MapEntryLite.writeTo(output, metadata, key, value); + } + } + + private void writeDeterministicStringMap( + int fieldNumber, MapEntryLite.Metadata metadata, Map map) + throws IOException { + String[] keys = new String[map.size()]; + int index = 0; + for (String k : map.keySet()) { + keys[index++] = k; + } + Arrays.sort(keys); + for (String key : keys) { + V value = map.get(key); + output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); + output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value)); + MapEntryLite.writeTo(output, metadata, key, value); + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java b/java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java new file mode 100644 index 0000000000000..7975136596a85 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java @@ -0,0 +1,690 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.FieldInfo.forField; +import static com.google.protobuf.FieldInfo.forFieldWithEnumVerifier; +import static com.google.protobuf.FieldInfo.forMapField; +import static com.google.protobuf.FieldInfo.forOneofMemberField; +import static com.google.protobuf.FieldInfo.forPackedField; +import static com.google.protobuf.FieldInfo.forPackedFieldWithEnumVerifier; +import static com.google.protobuf.FieldInfo.forProto2OptionalField; +import static com.google.protobuf.FieldInfo.forProto2RequiredField; +import static com.google.protobuf.FieldInfo.forRepeatedMessageField; + +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Descriptors.FieldDescriptor.Type; +import com.google.protobuf.Descriptors.OneofDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Stack; +import java.util.concurrent.ConcurrentHashMap; + +/** A factory for message info based on protobuf descriptors for a {@link GeneratedMessageV3}. */ +@ExperimentalApi +final class DescriptorMessageInfoFactory implements MessageInfoFactory { + private static final String GET_DEFAULT_INSTANCE_METHOD_NAME = "getDefaultInstance"; + private static final DescriptorMessageInfoFactory instance = new DescriptorMessageInfoFactory(); + private static final Set specialFieldNames = + new HashSet<>(Arrays.asList("cached_size", "serialized_size", "class")); + + // Disallow construction - it's a singleton. + private DescriptorMessageInfoFactory() {} + + public static DescriptorMessageInfoFactory getInstance() { + return instance; + } + + @Override + public boolean isSupported(Class messageType) { + return GeneratedMessageV3.class.isAssignableFrom(messageType); + } + + @Override + public MessageInfo messageInfoFor(Class messageType) { + if (!GeneratedMessageV3.class.isAssignableFrom(messageType)) { + throw new IllegalArgumentException("Unsupported message type: " + messageType.getName()); + } + + return convert(messageType, descriptorForType(messageType)); + } + + private static Message getDefaultInstance(Class messageType) { + try { + Method method = messageType.getDeclaredMethod(GET_DEFAULT_INSTANCE_METHOD_NAME); + return (Message) method.invoke(null); + } catch (Exception e) { + throw new IllegalArgumentException( + "Unable to get default instance for message class " + messageType.getName(), e); + } + } + + private static Descriptor descriptorForType(Class messageType) { + return getDefaultInstance(messageType).getDescriptorForType(); + } + + private static MessageInfo convert(Class messageType, Descriptor messageDescriptor) { + switch (messageDescriptor.getFile().getSyntax()) { + case PROTO2: + return convertProto2(messageType, messageDescriptor); + case PROTO3: + return convertProto3(messageType, messageDescriptor); + default: + throw new IllegalArgumentException( + "Unsupported syntax: " + messageDescriptor.getFile().getSyntax()); + } + } + + /** + * A helper class to determine whether a message type needs to implement {@code isInitialized()}. + * + *

If a message type doesn't have any required fields or extensions (directly and + * transitively), it doesn't need to implement isInitialized() and can always return true there. + * It's a bit tricky to determine whether a type has transitive required fields because protobuf + * allows cycle references within the same .proto file (e.g., message Foo has a Bar field, and + * message Bar has a Foo field). For that we use Tarjan's strongly connected components algorithm + * to classify messages into strongly connected groups. Messages in the same group are + * transitively including each other, so they should either all have transitive required fields + * (or extensions), or none have. + * + *

This class is thread-safe. + */ + static class IsInitializedCheckAnalyzer { + + private final Map resultCache = + new ConcurrentHashMap(); + + // The following data members are part of Tarjan's SCC algorithm. See: + // https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm + private int index = 0; + private final Stack stack = new Stack(); + private final Map nodeCache = new HashMap(); + + public boolean needsIsInitializedCheck(Descriptor descriptor) { + Boolean cachedValue = resultCache.get(descriptor); + if (cachedValue != null) { + return cachedValue; + } + synchronized (this) { + // Double-check the cache because some other thread may have updated it while we + // were acquiring the lock. + cachedValue = resultCache.get(descriptor); + if (cachedValue != null) { + return cachedValue; + } + return dfs(descriptor).component.needsIsInitializedCheck; + } + } + + private static class Node { + final Descriptor descriptor; + final int index; + int lowLink; + StronglyConnectedComponent component; // null if the node is still on stack. + + Node(Descriptor descriptor, int index) { + this.descriptor = descriptor; + this.index = index; + this.lowLink = index; + this.component = null; + } + } + + private static class StronglyConnectedComponent { + final List messages = new ArrayList(); + boolean needsIsInitializedCheck = false; + } + + private Node dfs(Descriptor descriptor) { + Node result = new Node(descriptor, index++); + stack.push(result); + nodeCache.put(descriptor, result); + + // Recurse the fields / nodes in graph + for (FieldDescriptor field : descriptor.getFields()) { + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + Node child = nodeCache.get(field.getMessageType()); + if (child == null) { + // Unexplored node + child = dfs(field.getMessageType()); + result.lowLink = Math.min(result.lowLink, child.lowLink); + } else { + if (child.component == null) { + // Still in the stack so we found a back edge. + result.lowLink = Math.min(result.lowLink, child.lowLink); + } + } + } + } + + if (result.index == result.lowLink) { + // This is the root of a strongly connected component. + StronglyConnectedComponent component = new StronglyConnectedComponent(); + while (true) { + Node node = stack.pop(); + node.component = component; + component.messages.add(node.descriptor); + if (node == result) { + break; + } + } + + analyze(component); + } + + return result; + } + + // Determine whether messages in this SCC needs isInitialized check. + private void analyze(StronglyConnectedComponent component) { + boolean needsIsInitializedCheck = false; + loop: + for (Descriptor descriptor : component.messages) { + if (descriptor.isExtendable()) { + needsIsInitializedCheck = true; + break; + } + + for (FieldDescriptor field : descriptor.getFields()) { + if (field.isRequired()) { + needsIsInitializedCheck = true; + break loop; + } + + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + // Since we are analyzing the graph bottom-up, all referenced fields should either be + // in this same component or in a different already-analyzed component. + Node node = nodeCache.get(field.getMessageType()); + if (node.component != component) { + if (node.component.needsIsInitializedCheck) { + needsIsInitializedCheck = true; + break loop; + } + } + } + } + } + + component.needsIsInitializedCheck = needsIsInitializedCheck; + + for (Descriptor descriptor : component.messages) { + resultCache.put(descriptor, component.needsIsInitializedCheck); + } + } + } + + private static IsInitializedCheckAnalyzer isInitializedCheckAnalyzer = + new IsInitializedCheckAnalyzer(); + + private static boolean needsIsInitializedCheck(Descriptor descriptor) { + return isInitializedCheckAnalyzer.needsIsInitializedCheck(descriptor); + } + + private static StructuralMessageInfo convertProto2( + Class messageType, Descriptor messageDescriptor) { + List fieldDescriptors = messageDescriptor.getFields(); + StructuralMessageInfo.Builder builder = + StructuralMessageInfo.newBuilder(fieldDescriptors.size()); + builder.withDefaultInstance(getDefaultInstance(messageType)); + builder.withSyntax(ProtoSyntax.PROTO2); + builder.withMessageSetWireFormat(messageDescriptor.getOptions().getMessageSetWireFormat()); + + OneofState oneofState = new OneofState(); + int bitFieldIndex = 0; + int presenceMask = 1; + Field bitField = null; + + // Fields in the descriptor are ordered by the index position in which they appear in the + // proto file. This is the same order used to determine the presence mask used in the + // bitFields. So to determine the appropriate presence mask to be used for a field, we simply + // need to shift the presence mask whenever a presence-checked field is encountered. + for (int i = 0; i < fieldDescriptors.size(); ++i) { + final FieldDescriptor fd = fieldDescriptors.get(i); + boolean enforceUtf8 = fd.getFile().getOptions().getJavaStringCheckUtf8(); + Internal.EnumVerifier enumVerifier = null; + if (fd.getJavaType() == Descriptors.FieldDescriptor.JavaType.ENUM) { + enumVerifier = + new Internal.EnumVerifier() { + @Override + public boolean isInRange(int number) { + return fd.getEnumType().findValueByNumber(number) != null; + } + }; + } + if (fd.getContainingOneof() != null) { + // Build a oneof member field. + builder.withField(buildOneofMember(messageType, fd, oneofState, enforceUtf8, enumVerifier)); + } else { + Field field = field(messageType, fd); + int number = fd.getNumber(); + FieldType type = getFieldType(fd); + + if (fd.isMapField()) { + // Map field points to an auto-generated message entry type with the definition: + // message MapEntry { + // K key = 1; + // V value = 2; + // } + final FieldDescriptor valueField = fd.getMessageType().findFieldByNumber(2); + if (valueField.getJavaType() == Descriptors.FieldDescriptor.JavaType.ENUM) { + enumVerifier = + new Internal.EnumVerifier() { + @Override + public boolean isInRange(int number) { + return valueField.getEnumType().findValueByNumber(number) != null; + } + }; + } + builder.withField( + forMapField( + field, + number, + SchemaUtil.getMapDefaultEntry(messageType, fd.getName()), + enumVerifier)); + continue; + } + + if (fd.isRepeated()) { + // Repeated fields are not presence-checked. + if (enumVerifier != null) { + if (fd.isPacked()) { + builder.withField( + forPackedFieldWithEnumVerifier( + field, number, type, enumVerifier, cachedSizeField(messageType, fd))); + } else { + builder.withField(forFieldWithEnumVerifier(field, number, type, enumVerifier)); + } + } else if (fd.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + builder.withField( + forRepeatedMessageField( + field, number, type, getTypeForRepeatedMessageField(messageType, fd))); + } else { + if (fd.isPacked()) { + builder.withField( + forPackedField(field, number, type, cachedSizeField(messageType, fd))); + } else { + builder.withField(forField(field, number, type, enforceUtf8)); + } + } + continue; + } + + if (bitField == null) { + // Lazy-create the next bitfield since we know it must exist. + bitField = bitField(messageType, bitFieldIndex); + } + + // It's a presence-checked field. + if (fd.isRequired()) { + builder.withField( + forProto2RequiredField( + field, number, type, bitField, presenceMask, enforceUtf8, enumVerifier)); + } else { + builder.withField( + forProto2OptionalField( + field, number, type, bitField, presenceMask, enforceUtf8, enumVerifier)); + } + } + + // Update the presence mask for the next iteration. If the shift clears out the mask, we will + // go to the next bitField. + presenceMask <<= 1; + if (presenceMask == 0) { + bitField = null; + presenceMask = 1; + bitFieldIndex++; + } + } + + List fieldsToCheckIsInitialized = new ArrayList(); + for (int i = 0; i < fieldDescriptors.size(); ++i) { + FieldDescriptor fd = fieldDescriptors.get(i); + if (fd.isRequired() + || (fd.getJavaType() == FieldDescriptor.JavaType.MESSAGE + && needsIsInitializedCheck(fd.getMessageType()))) { + fieldsToCheckIsInitialized.add(fd.getNumber()); + } + } + int[] numbers = new int[fieldsToCheckIsInitialized.size()]; + for (int i = 0; i < fieldsToCheckIsInitialized.size(); i++) { + numbers[i] = fieldsToCheckIsInitialized.get(i); + } + builder.withCheckInitialized(numbers); + + return builder.build(); + } + + private static StructuralMessageInfo convertProto3( + Class messageType, Descriptor messageDescriptor) { + List fieldDescriptors = messageDescriptor.getFields(); + StructuralMessageInfo.Builder builder = + StructuralMessageInfo.newBuilder(fieldDescriptors.size()); + builder.withDefaultInstance(getDefaultInstance(messageType)); + builder.withSyntax(ProtoSyntax.PROTO3); + + OneofState oneofState = new OneofState(); + boolean enforceUtf8 = true; + for (int i = 0; i < fieldDescriptors.size(); ++i) { + FieldDescriptor fd = fieldDescriptors.get(i); + if (fd.getContainingOneof() != null) { + // Build a oneof member field. + builder.withField(buildOneofMember(messageType, fd, oneofState, enforceUtf8, null)); + continue; + } + if (fd.isMapField()) { + builder.withField( + forMapField( + field(messageType, fd), + fd.getNumber(), + SchemaUtil.getMapDefaultEntry(messageType, fd.getName()), + null)); + continue; + } + if (fd.isRepeated() && fd.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + builder.withField( + forRepeatedMessageField( + field(messageType, fd), + fd.getNumber(), + getFieldType(fd), + getTypeForRepeatedMessageField(messageType, fd))); + continue; + } + if (fd.isPacked()) { + builder.withField( + forPackedField( + field(messageType, fd), + fd.getNumber(), + getFieldType(fd), + cachedSizeField(messageType, fd))); + } else { + builder.withField( + forField(field(messageType, fd), fd.getNumber(), getFieldType(fd), enforceUtf8)); + } + } + + return builder.build(); + } + + /** Builds info for a oneof member field. */ + private static FieldInfo buildOneofMember( + Class messageType, + FieldDescriptor fd, + OneofState oneofState, + boolean enforceUtf8, + Internal.EnumVerifier enumVerifier) { + OneofInfo oneof = oneofState.getOneof(messageType, fd.getContainingOneof()); + FieldType type = getFieldType(fd); + Class oneofStoredType = getOneofStoredType(messageType, fd, type); + return forOneofMemberField( + fd.getNumber(), type, oneof, oneofStoredType, enforceUtf8, enumVerifier); + } + + private static Class getOneofStoredType( + Class messageType, FieldDescriptor fd, FieldType type) { + switch (type.getJavaType()) { + case BOOLEAN: + return Boolean.class; + case BYTE_STRING: + return ByteString.class; + case DOUBLE: + return Double.class; + case FLOAT: + return Float.class; + case ENUM: + case INT: + return Integer.class; + case LONG: + return Long.class; + case STRING: + return String.class; + case MESSAGE: + return getOneofStoredTypeForMessage(messageType, fd); + default: + throw new IllegalArgumentException("Invalid type for oneof: " + type); + } + } + + private static FieldType getFieldType(FieldDescriptor fd) { + switch (fd.getType()) { + case BOOL: + if (!fd.isRepeated()) { + return FieldType.BOOL; + } + return fd.isPacked() ? FieldType.BOOL_LIST_PACKED : FieldType.BOOL_LIST; + case BYTES: + return fd.isRepeated() ? FieldType.BYTES_LIST : FieldType.BYTES; + case DOUBLE: + if (!fd.isRepeated()) { + return FieldType.DOUBLE; + } + return fd.isPacked() ? FieldType.DOUBLE_LIST_PACKED : FieldType.DOUBLE_LIST; + case ENUM: + if (!fd.isRepeated()) { + return FieldType.ENUM; + } + return fd.isPacked() ? FieldType.ENUM_LIST_PACKED : FieldType.ENUM_LIST; + case FIXED32: + if (!fd.isRepeated()) { + return FieldType.FIXED32; + } + return fd.isPacked() ? FieldType.FIXED32_LIST_PACKED : FieldType.FIXED32_LIST; + case FIXED64: + if (!fd.isRepeated()) { + return FieldType.FIXED64; + } + return fd.isPacked() ? FieldType.FIXED64_LIST_PACKED : FieldType.FIXED64_LIST; + case FLOAT: + if (!fd.isRepeated()) { + return FieldType.FLOAT; + } + return fd.isPacked() ? FieldType.FLOAT_LIST_PACKED : FieldType.FLOAT_LIST; + case GROUP: + return fd.isRepeated() ? FieldType.GROUP_LIST : FieldType.GROUP; + case INT32: + if (!fd.isRepeated()) { + return FieldType.INT32; + } + return fd.isPacked() ? FieldType.INT32_LIST_PACKED : FieldType.INT32_LIST; + case INT64: + if (!fd.isRepeated()) { + return FieldType.INT64; + } + return fd.isPacked() ? FieldType.INT64_LIST_PACKED : FieldType.INT64_LIST; + case MESSAGE: + if (fd.isMapField()) { + return FieldType.MAP; + } + return fd.isRepeated() ? FieldType.MESSAGE_LIST : FieldType.MESSAGE; + case SFIXED32: + if (!fd.isRepeated()) { + return FieldType.SFIXED32; + } + return fd.isPacked() ? FieldType.SFIXED32_LIST_PACKED : FieldType.SFIXED32_LIST; + case SFIXED64: + if (!fd.isRepeated()) { + return FieldType.SFIXED64; + } + return fd.isPacked() ? FieldType.SFIXED64_LIST_PACKED : FieldType.SFIXED64_LIST; + case SINT32: + if (!fd.isRepeated()) { + return FieldType.SINT32; + } + return fd.isPacked() ? FieldType.SINT32_LIST_PACKED : FieldType.SINT32_LIST; + case SINT64: + if (!fd.isRepeated()) { + return FieldType.SINT64; + } + return fd.isPacked() ? FieldType.SINT64_LIST_PACKED : FieldType.SINT64_LIST; + case STRING: + return fd.isRepeated() ? FieldType.STRING_LIST : FieldType.STRING; + case UINT32: + if (!fd.isRepeated()) { + return FieldType.UINT32; + } + return fd.isPacked() ? FieldType.UINT32_LIST_PACKED : FieldType.UINT32_LIST; + case UINT64: + if (!fd.isRepeated()) { + return FieldType.UINT64; + } + return fd.isPacked() ? FieldType.UINT64_LIST_PACKED : FieldType.UINT64_LIST; + default: + throw new IllegalArgumentException("Unsupported field type: " + fd.getType()); + } + } + + private static Field bitField(Class messageType, int index) { + return field(messageType, "bitField" + index + "_"); + } + + private static Field field(Class messageType, FieldDescriptor fd) { + return field(messageType, getFieldName(fd)); + } + + private static Field cachedSizeField(Class messageType, FieldDescriptor fd) { + return field(messageType, getCachedSizeFieldName(fd)); + } + + private static Field field(Class messageType, String fieldName) { + try { + return messageType.getDeclaredField(fieldName); + } catch (Exception e) { + throw new IllegalArgumentException( + "Unable to find field " + fieldName + " in message class " + messageType.getName()); + } + } + + static String getFieldName(FieldDescriptor fd) { + String name = (fd.getType() == FieldDescriptor.Type.GROUP) + ? fd.getMessageType().getName() + : fd.getName(); + String suffix = specialFieldNames.contains(name) ? "__" : "_"; + return snakeCaseToCamelCase(name) + suffix; + } + + private static String getCachedSizeFieldName(FieldDescriptor fd) { + return snakeCaseToCamelCase(fd.getName()) + "MemoizedSerializedSize"; + } + + /** + * This method must match exactly with the corresponding function in protocol compiler. See: + * https://github.com/google/protobuf/blob/v3.0.0/src/google/protobuf/compiler/java/java_helpers.cc#L153 + */ + private static String snakeCaseToCamelCase(String snakeCase) { + StringBuilder sb = new StringBuilder(snakeCase.length() + 1); + boolean capNext = false; + for (int ctr = 0; ctr < snakeCase.length(); ctr++) { + char next = snakeCase.charAt(ctr); + if (next == '_') { + capNext = true; + } else if (Character.isDigit(next)) { + sb.append(next); + capNext = true; + } else if (capNext) { + sb.append(Character.toUpperCase(next)); + capNext = false; + } else if (ctr == 0) { + sb.append(Character.toLowerCase(next)); + } else { + sb.append(next); + } + } + return sb.toString(); + } + + /** + * Inspects the message to identify the stored type for a message field that is part of a oneof. + */ + private static Class getOneofStoredTypeForMessage(Class messageType, FieldDescriptor fd) { + try { + String name = fd.getType() == Type.GROUP ? fd.getMessageType().getName() : fd.getName(); + Method getter = messageType.getDeclaredMethod(getterForField(name)); + return getter.getReturnType(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** Inspects the message to identify the message type of a repeated message field. */ + private static Class getTypeForRepeatedMessageField(Class messageType, FieldDescriptor fd) { + try { + String name = fd.getType() == Type.GROUP ? fd.getMessageType().getName() : fd.getName(); + Method getter = messageType.getDeclaredMethod(getterForField(name), int.class); + return getter.getReturnType(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** Constructs the name of the get method for the given field in the proto. */ + private static String getterForField(String snakeCase) { + String camelCase = snakeCaseToCamelCase(snakeCase); + StringBuilder builder = new StringBuilder("get"); + // Capitalize the first character in the field name. + builder.append(Character.toUpperCase(camelCase.charAt(0))); + builder.append(camelCase.substring(1, camelCase.length())); + return builder.toString(); + } + + private static final class OneofState { + private OneofInfo[] oneofs = new OneofInfo[2]; + + OneofInfo getOneof(Class messageType, OneofDescriptor desc) { + int index = desc.getIndex(); + if (index >= oneofs.length) { + // Grow the array. + oneofs = Arrays.copyOf(oneofs, index * 2); + } + OneofInfo info = oneofs[index]; + if (info == null) { + info = newInfo(messageType, desc); + oneofs[index] = info; + } + return info; + } + + private static OneofInfo newInfo(Class messageType, OneofDescriptor desc) { + String camelCase = snakeCaseToCamelCase(desc.getName()); + String valueFieldName = camelCase + "_"; + String caseFieldName = camelCase + "Case_"; + + return new OneofInfo( + desc.getIndex(), field(messageType, caseFieldName), field(messageType, valueFieldName)); + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/Descriptors.java b/java/core/src/main/java/com/google/protobuf/Descriptors.java index 75b16fe30e964..51597fa3db627 100644 --- a/java/core/src/main/java/com/google/protobuf/Descriptors.java +++ b/java/core/src/main/java/com/google/protobuf/Descriptors.java @@ -32,7 +32,22 @@ import static com.google.protobuf.Internal.checkNotNull; -import com.google.protobuf.DescriptorProtos.*; +import com.google.protobuf.DescriptorProtos.DescriptorProto; +import com.google.protobuf.DescriptorProtos.EnumDescriptorProto; +import com.google.protobuf.DescriptorProtos.EnumOptions; +import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto; +import com.google.protobuf.DescriptorProtos.EnumValueOptions; +import com.google.protobuf.DescriptorProtos.FieldDescriptorProto; +import com.google.protobuf.DescriptorProtos.FieldOptions; +import com.google.protobuf.DescriptorProtos.FileDescriptorProto; +import com.google.protobuf.DescriptorProtos.FileOptions; +import com.google.protobuf.DescriptorProtos.MessageOptions; +import com.google.protobuf.DescriptorProtos.MethodDescriptorProto; +import com.google.protobuf.DescriptorProtos.MethodOptions; +import com.google.protobuf.DescriptorProtos.OneofDescriptorProto; +import com.google.protobuf.DescriptorProtos.OneofOptions; +import com.google.protobuf.DescriptorProtos.ServiceDescriptorProto; +import com.google.protobuf.DescriptorProtos.ServiceOptions; import com.google.protobuf.Descriptors.FileDescriptor.Syntax; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -49,29 +64,25 @@ /** * Contains a collection of classes which describe protocol message types. * - * Every message type has a {@link Descriptor}, which lists all - * its fields and other information about a type. You can get a message - * type's descriptor by calling {@code MessageType.getDescriptor()}, or - * (given a message object of the type) {@code message.getDescriptorForType()}. - * Furthermore, each message is associated with a {@link FileDescriptor} for - * a relevant {@code .proto} file. You can obtain it by calling - * {@code Descriptor.getFile()}. A {@link FileDescriptor} contains descriptors - * for all the messages defined in that file, and file descriptors for all the - * imported {@code .proto} files. + *

Every message type has a {@link Descriptor}, which lists all its fields and other information + * about a type. You can get a message type's descriptor by calling {@code + * MessageType.getDescriptor()}, or (given a message object of the type) {@code + * message.getDescriptorForType()}. Furthermore, each message is associated with a {@link + * FileDescriptor} for a relevant {@code .proto} file. You can obtain it by calling {@code + * Descriptor.getFile()}. A {@link FileDescriptor} contains descriptors for all the messages defined + * in that file, and file descriptors for all the imported {@code .proto} files. * - * Descriptors are built from DescriptorProtos, as defined in - * {@code google/protobuf/descriptor.proto}. + *

Descriptors are built from DescriptorProtos, as defined in {@code + * google/protobuf/descriptor.proto}. * * @author kenton@google.com Kenton Varda */ public final class Descriptors { - private static final Logger logger = - Logger.getLogger(Descriptors.class.getName()); + private static final Logger logger = Logger.getLogger(Descriptors.class.getName()); /** - * Describes a {@code .proto} file, including everything defined within. - * That includes, in particular, descriptors for all the messages and - * file descriptors for all other imported {@code .proto} files - * (dependencies). + * Describes a {@code .proto} file, including everything defined within. That includes, in + * particular, descriptors for all the messages and file descriptors for all other imported {@code + * .proto} files (dependencies). */ public static final class FileDescriptor extends GenericDescriptor { /** Convert the descriptor to its protocol message representation. */ @@ -99,14 +110,17 @@ public String getFullName() { } /** - * Get the proto package name. This is the package name given by the - * {@code package} statement in the {@code .proto} file, which differs - * from the Java package. + * Get the proto package name. This is the package name given by the {@code package} statement + * in the {@code .proto} file, which differs from the Java package. */ - public String getPackage() { return proto.getPackage(); } + public String getPackage() { + return proto.getPackage(); + } /** Get the {@code FileOptions}, defined in {@code descriptor.proto}. */ - public FileOptions getOptions() { return proto.getOptions(); } + public FileOptions getOptions() { + return proto.getOptions(); + } /** Get a list of top-level message types declared in this file. */ public List getMessageTypes() { @@ -147,6 +161,7 @@ public enum Syntax { Syntax(String name) { this.name = name; } + private final String name; } @@ -159,7 +174,7 @@ public Syntax getSyntax() { } /** - * Find a message type in the file by name. Does not find nested types. + * Find a message type in the file by name. Does not find nested types. * * @param name The unqualified type name to look for. * @return The message type's descriptor, or {@code null} if not found. @@ -170,20 +185,20 @@ public Descriptor findMessageTypeByName(String name) { if (name.indexOf('.') != -1) { return null; } - if (getPackage().length() > 0) { - name = getPackage() + '.' + name; + final String packageName = getPackage(); + if (!packageName.isEmpty()) { + name = packageName + '.' + name; } final GenericDescriptor result = pool.findSymbol(name); - if (result != null && result instanceof Descriptor && - result.getFile() == this) { - return (Descriptor)result; + if (result instanceof Descriptor && result.getFile() == this) { + return (Descriptor) result; } else { return null; } } /** - * Find an enum type in the file by name. Does not find nested types. + * Find an enum type in the file by name. Does not find nested types. * * @param name The unqualified type name to look for. * @return The enum type's descriptor, or {@code null} if not found. @@ -194,13 +209,13 @@ public EnumDescriptor findEnumTypeByName(String name) { if (name.indexOf('.') != -1) { return null; } - if (getPackage().length() > 0) { - name = getPackage() + '.' + name; + final String packageName = getPackage(); + if (!packageName.isEmpty()) { + name = packageName + '.' + name; } final GenericDescriptor result = pool.findSymbol(name); - if (result != null && result instanceof EnumDescriptor && - result.getFile() == this) { - return (EnumDescriptor)result; + if (result instanceof EnumDescriptor && result.getFile() == this) { + return (EnumDescriptor) result; } else { return null; } @@ -218,21 +233,20 @@ public ServiceDescriptor findServiceByName(String name) { if (name.indexOf('.') != -1) { return null; } - if (getPackage().length() > 0) { - name = getPackage() + '.' + name; + final String packageName = getPackage(); + if (!packageName.isEmpty()) { + name = packageName + '.' + name; } final GenericDescriptor result = pool.findSymbol(name); - if (result != null && result instanceof ServiceDescriptor && - result.getFile() == this) { - return (ServiceDescriptor)result; + if (result instanceof ServiceDescriptor && result.getFile() == this) { + return (ServiceDescriptor) result; } else { return null; } } /** - * Find an extension in the file by name. Does not find extensions nested - * inside message types. + * Find an extension in the file by name. Does not find extensions nested inside message types. * * @param name The unqualified extension name to look for. * @return The extension's descriptor, or {@code null} if not found. @@ -241,13 +255,13 @@ public FieldDescriptor findExtensionByName(String name) { if (name.indexOf('.') != -1) { return null; } - if (getPackage().length() > 0) { - name = getPackage() + '.' + name; + final String packageName = getPackage(); + if (!packageName.isEmpty()) { + name = packageName + '.' + name; } final GenericDescriptor result = pool.findSymbol(name); - if (result != null && result instanceof FieldDescriptor && - result.getFile() == this) { - return (FieldDescriptor)result; + if (result instanceof FieldDescriptor && result.getFile() == this) { + return (FieldDescriptor) result; } else { return null; } @@ -257,36 +271,31 @@ public FieldDescriptor findExtensionByName(String name) { * Construct a {@code FileDescriptor}. * * @param proto The protocol message form of the FileDescriptor. - * @param dependencies {@code FileDescriptor}s corresponding to all of - * the file's dependencies. - * @throws DescriptorValidationException {@code proto} is not a valid - * descriptor. This can occur for a number of reasons, e.g. - * because a field has an undefined type or because two messages - * were defined with the same name. + * @param dependencies {@code FileDescriptor}s corresponding to all of the file's dependencies. + * @throws DescriptorValidationException {@code proto} is not a valid descriptor. This can occur + * for a number of reasons, e.g. because a field has an undefined type or because two + * messages were defined with the same name. */ - public static FileDescriptor buildFrom(final FileDescriptorProto proto, - final FileDescriptor[] dependencies) - throws DescriptorValidationException { + public static FileDescriptor buildFrom( + final FileDescriptorProto proto, final FileDescriptor[] dependencies) + throws DescriptorValidationException { return buildFrom(proto, dependencies, false); } - /** * Construct a {@code FileDescriptor}. * * @param proto The protocol message form of the FileDescriptor. - * @param dependencies {@code FileDescriptor}s corresponding to all of - * the file's dependencies. - * @param allowUnknownDependencies If true, non-exist dependenncies will be - * ignored and undefined message types will be replaced with a - * placeholder type. - * @throws DescriptorValidationException {@code proto} is not a valid - * descriptor. This can occur for a number of reasons, e.g. - * because a field has an undefined type or because two messages - * were defined with the same name. + * @param dependencies {@code FileDescriptor}s corresponding to all of the file's dependencies. + * @param allowUnknownDependencies If true, non-exist dependenncies will be ignored and + * undefined message types will be replaced with a placeholder type. + * @throws DescriptorValidationException {@code proto} is not a valid descriptor. This can occur + * for a number of reasons, e.g. because a field has an undefined type or because two + * messages were defined with the same name. */ public static FileDescriptor buildFrom( - final FileDescriptorProto proto, final FileDescriptor[] dependencies, + final FileDescriptorProto proto, + final FileDescriptor[] dependencies, final boolean allowUnknownDependencies) throws DescriptorValidationException { // Building descriptors involves two steps: translating and linking. @@ -298,23 +307,14 @@ public static FileDescriptor buildFrom( // FieldDescriptor for an embedded message contains a pointer directly // to the Descriptor for that message's type. We also detect undefined // types in the linking step. - final DescriptorPool pool = new DescriptorPool( - dependencies, allowUnknownDependencies); - final FileDescriptor result = new FileDescriptor( - proto, dependencies, pool, allowUnknownDependencies); + final DescriptorPool pool = new DescriptorPool(dependencies, allowUnknownDependencies); + final FileDescriptor result = + new FileDescriptor(proto, dependencies, pool, allowUnknownDependencies); result.crossLink(); return result; } - /** - * This method is to be called by generated code only. It is equivalent - * to {@code buildFrom} except that the {@code FileDescriptorProto} is - * encoded in protocol buffer wire format. - */ - public static void internalBuildGeneratedFileFrom( - final String[] descriptorDataParts, - final FileDescriptor[] dependencies, - final InternalDescriptorAssigner descriptorAssigner) { + private static byte[] latin1Cat(final String[] strings) { // Hack: We can't embed a raw byte array inside generated Java code // (at least, not efficiently), but we can embed Strings. So, the // protocol compiler embeds the FileDescriptorProto as a giant @@ -323,23 +323,52 @@ public static void internalBuildGeneratedFileFrom( // characters, each one representing a byte of the FileDescriptorProto's // serialized form. So, if we convert it to bytes in ISO-8859-1, we // should get the original bytes that we want. - - // descriptorData may contain multiple strings in order to get around the - // Java 64k string literal limit. + // Literal strings are limited to 64k, so it may be split into multiple strings. + if (strings.length == 1) { + return strings[0].getBytes(Internal.ISO_8859_1); + } StringBuilder descriptorData = new StringBuilder(); - for (String part : descriptorDataParts) { + for (String part : strings) { descriptorData.append(part); } + return descriptorData.toString().getBytes(Internal.ISO_8859_1); + } - final byte[] descriptorBytes; - descriptorBytes = descriptorData.toString().getBytes(Internal.ISO_8859_1); + private static FileDescriptor[] findDescriptors( + final Class descriptorOuterClass, + final String[] dependencyClassNames, + final String[] dependencyFileNames) { + List descriptors = new ArrayList<>(); + for (int i = 0; i < dependencyClassNames.length; i++) { + try { + Class clazz = descriptorOuterClass.getClassLoader().loadClass(dependencyClassNames[i]); + descriptors.add((FileDescriptor) clazz.getField("descriptor").get(null)); + } catch (Exception e) { + // We allow unknown dependencies by default. If a dependency cannot + // be found we only generate a warning. + logger.warning("Descriptors for \"" + dependencyFileNames[i] + "\" can not be found."); + } + } + return descriptors.toArray(new FileDescriptor[0]); + } + + /** + * This method is for backward compatibility with generated code which passed an + * InternalDescriptorAssigner. + */ + @Deprecated + public static void internalBuildGeneratedFileFrom( + final String[] descriptorDataParts, + final FileDescriptor[] dependencies, + final InternalDescriptorAssigner descriptorAssigner) { + final byte[] descriptorBytes = latin1Cat(descriptorDataParts); FileDescriptorProto proto; try { proto = FileDescriptorProto.parseFrom(descriptorBytes); } catch (InvalidProtocolBufferException e) { throw new IllegalArgumentException( - "Failed to parse protocol buffer descriptor for generated code.", e); + "Failed to parse protocol buffer descriptor for generated code.", e); } final FileDescriptor result; @@ -349,11 +378,10 @@ public static void internalBuildGeneratedFileFrom( result = buildFrom(proto, dependencies, true); } catch (DescriptorValidationException e) { throw new IllegalArgumentException( - "Invalid embedded descriptor for \"" + proto.getName() + "\".", e); + "Invalid embedded descriptor for \"" + proto.getName() + "\".", e); } - final ExtensionRegistry registry = - descriptorAssigner.assignDescriptors(result); + final ExtensionRegistry registry = descriptorAssigner.assignDescriptors(result); if (registry != null) { // We must re-parse the proto using the registry. @@ -361,8 +389,7 @@ public static void internalBuildGeneratedFileFrom( proto = FileDescriptorProto.parseFrom(descriptorBytes, registry); } catch (InvalidProtocolBufferException e) { throw new IllegalArgumentException( - "Failed to parse protocol buffer descriptor for generated code.", - e); + "Failed to parse protocol buffer descriptor for generated code.", e); } result.setProto(proto); @@ -370,67 +397,94 @@ public static void internalBuildGeneratedFileFrom( } /** - * This method is to be called by generated code only. It uses Java - * reflection to load the dependencies' descriptors. + * This method is to be called by generated code only. It is equivalent to {@code buildFrom} + * except that the {@code FileDescriptorProto} is encoded in protocol buffer wire format. + */ + public static FileDescriptor internalBuildGeneratedFileFrom( + final String[] descriptorDataParts, + final FileDescriptor[] dependencies) { + final byte[] descriptorBytes = latin1Cat(descriptorDataParts); + + FileDescriptorProto proto; + try { + proto = FileDescriptorProto.parseFrom(descriptorBytes); + } catch (InvalidProtocolBufferException e) { + throw new IllegalArgumentException( + "Failed to parse protocol buffer descriptor for generated code.", e); + } + + try { + // When building descriptors for generated code, we allow unknown + // dependencies by default. + return buildFrom(proto, dependencies, true); + } catch (DescriptorValidationException e) { + throw new IllegalArgumentException( + "Invalid embedded descriptor for \"" + proto.getName() + "\".", e); + } + } + + /** + * This method is for backward compatibility with generated code which passed an + * InternalDescriptorAssigner. */ + @Deprecated public static void internalBuildGeneratedFileFrom( final String[] descriptorDataParts, final Class descriptorOuterClass, - final String[] dependencies, + final String[] dependencyClassNames, final String[] dependencyFileNames, final InternalDescriptorAssigner descriptorAssigner) { - List descriptors = new ArrayList(); - for (int i = 0; i < dependencies.length; i++) { - try { - Class clazz = - descriptorOuterClass.getClassLoader().loadClass(dependencies[i]); - descriptors.add( - (FileDescriptor) clazz.getField("descriptor").get(null)); - } catch (Exception e) { - // We allow unknown dependencies by default. If a dependency cannot - // be found we only generate a warning. - logger.warning("Descriptors for \"" + dependencyFileNames[i] + - "\" can not be found."); - } - } - FileDescriptor[] descriptorArray = new FileDescriptor[descriptors.size()]; - descriptors.toArray(descriptorArray); + FileDescriptor[] dependencies = findDescriptors( + descriptorOuterClass, dependencyClassNames, dependencyFileNames); internalBuildGeneratedFileFrom( - descriptorDataParts, descriptorArray, descriptorAssigner); + descriptorDataParts, dependencies, descriptorAssigner); + } + + /** + * This method is to be called by generated code only. It uses Java reflection to load the + * dependencies' descriptors. + */ + public static FileDescriptor internalBuildGeneratedFileFrom( + final String[] descriptorDataParts, + final Class descriptorOuterClass, + final String[] dependencyClassNames, + final String[] dependencyFileNames) { + FileDescriptor[] dependencies = findDescriptors( + descriptorOuterClass, dependencyClassNames, dependencyFileNames); + return internalBuildGeneratedFileFrom(descriptorDataParts, dependencies); } /** - * This method is to be called by generated code only. It is used to - * update the FileDescriptorProto associated with the descriptor by - * parsing it again with the given ExtensionRegistry. This is needed to - * recognize custom options. + * This method is to be called by generated code only. It is used to update the + * FileDescriptorProto associated with the descriptor by parsing it again with the given + * ExtensionRegistry. This is needed to recognize custom options. */ public static void internalUpdateFileDescriptor( - final FileDescriptor descriptor, - final ExtensionRegistry registry) { + final FileDescriptor descriptor, final ExtensionRegistry registry) { ByteString bytes = descriptor.proto.toByteString(); FileDescriptorProto proto; try { proto = FileDescriptorProto.parseFrom(bytes, registry); } catch (InvalidProtocolBufferException e) { throw new IllegalArgumentException( - "Failed to parse protocol buffer descriptor for generated code.", e); + "Failed to parse protocol buffer descriptor for generated code.", e); } descriptor.setProto(proto); } /** - * This class should be used by generated code only. When calling - * {@link FileDescriptor#internalBuildGeneratedFileFrom}, the caller - * provides a callback implementing this interface. The callback is called - * after the FileDescriptor has been constructed, in order to assign all - * the global variables defined in the generated code which point at parts - * of the FileDescriptor. The callback returns an ExtensionRegistry which - * contains any extensions which might be used in the descriptor -- that - * is, extensions of the various "Options" messages defined in - * descriptor.proto. The callback may also return null to indicate that - * no extensions are used in the descriptor. + * This class should be used by generated code only. When calling {@link + * FileDescriptor#internalBuildGeneratedFileFrom}, the caller provides a callback implementing + * this interface. The callback is called after the FileDescriptor has been constructed, in + * order to assign all the global variables defined in the generated code which point at parts + * of the FileDescriptor. The callback returns an ExtensionRegistry which contains any + * extensions which might be used in the descriptor -- that is, extensions of the various + * "Options" messages defined in descriptor.proto. The callback may also return null to indicate + * that no extensions are used in the descriptor. + * + * This interface is deprecated. Use the return value of internalBuildGeneratedFrom() instead. */ + @Deprecated public interface InternalDescriptorAssigner { ExtensionRegistry assignDescriptors(FileDescriptor root); } @@ -444,32 +498,30 @@ public interface InternalDescriptorAssigner { private final FileDescriptor[] publicDependencies; private final DescriptorPool pool; - private FileDescriptor(final FileDescriptorProto proto, - final FileDescriptor[] dependencies, - final DescriptorPool pool, - boolean allowUnknownDependencies) - throws DescriptorValidationException { + private FileDescriptor( + final FileDescriptorProto proto, + final FileDescriptor[] dependencies, + final DescriptorPool pool, + boolean allowUnknownDependencies) + throws DescriptorValidationException { this.pool = pool; this.proto = proto; this.dependencies = dependencies.clone(); - HashMap nameToFileMap = - new HashMap(); + HashMap nameToFileMap = new HashMap<>(); for (FileDescriptor file : dependencies) { nameToFileMap.put(file.getName(), file); } - List publicDependencies = new ArrayList(); + List publicDependencies = new ArrayList<>(); for (int i = 0; i < proto.getPublicDependencyCount(); i++) { int index = proto.getPublicDependency(i); if (index < 0 || index >= proto.getDependencyCount()) { - throw new DescriptorValidationException(this, - "Invalid public dependency index."); + throw new DescriptorValidationException(this, "Invalid public dependency index."); } String name = proto.getDependency(index); FileDescriptor file = nameToFileMap.get(name); if (file == null) { if (!allowUnknownDependencies) { - throw new DescriptorValidationException(this, - "Invalid public dependency: " + name); + throw new DescriptorValidationException(this, "Invalid public dependency: " + name); } // Ignore unknown dependencies. } else { @@ -483,8 +535,7 @@ private FileDescriptor(final FileDescriptorProto proto, messageTypes = new Descriptor[proto.getMessageTypeCount()]; for (int i = 0; i < proto.getMessageTypeCount(); i++) { - messageTypes[i] = - new Descriptor(proto.getMessageType(i), this, null, i); + messageTypes[i] = new Descriptor(proto.getMessageType(i), this, null, i); } enumTypes = new EnumDescriptor[proto.getEnumTypeCount()]; @@ -499,20 +550,19 @@ private FileDescriptor(final FileDescriptorProto proto, extensions = new FieldDescriptor[proto.getExtensionCount()]; for (int i = 0; i < proto.getExtensionCount(); i++) { - extensions[i] = new FieldDescriptor( - proto.getExtension(i), this, null, i, true); + extensions[i] = new FieldDescriptor(proto.getExtension(i), this, null, i, true); } } - /** - * Create a placeholder FileDescriptor for a message Descriptor. - */ - FileDescriptor(String packageName, Descriptor message) - throws DescriptorValidationException { + /** Create a placeholder FileDescriptor for a message Descriptor. */ + FileDescriptor(String packageName, Descriptor message) throws DescriptorValidationException { this.pool = new DescriptorPool(new FileDescriptor[0], true); - this.proto = FileDescriptorProto.newBuilder() - .setName(message.getFullName() + ".placeholder.proto") - .setPackage(packageName).addMessageType(message.toProto()).build(); + this.proto = + FileDescriptorProto.newBuilder() + .setName(message.getFullName() + ".placeholder.proto") + .setPackage(packageName) + .addMessageType(message.toProto()) + .build(); this.dependencies = new FileDescriptor[0]; this.publicDependencies = new FileDescriptor[0]; @@ -541,14 +591,12 @@ private void crossLink() throws DescriptorValidationException { } /** - * Replace our {@link FileDescriptorProto} with the given one, which is - * identical except that it might contain extensions that weren't present - * in the original. This method is needed for bootstrapping when a file - * defines custom options. The options may be defined in the file itself, - * so we can't actually parse them until we've constructed the descriptors, - * but to construct the descriptors we have to have parsed the descriptor - * protos. So, we have to parse the descriptor protos a second time after - * constructing the descriptors. + * Replace our {@link FileDescriptorProto} with the given one, which is identical except that it + * might contain extensions that weren't present in the original. This method is needed for + * bootstrapping when a file defines custom options. The options may be defined in the file + * itself, so we can't actually parse them until we've constructed the descriptors, but to + * construct the descriptors we have to have parsed the descriptor protos. So, we have to parse + * the descriptor protos a second time after constructing the descriptors. */ private void setProto(final FileDescriptorProto proto) { this.proto = proto; @@ -580,19 +628,24 @@ boolean supportsUnknownEnumValue() { /** Describes a message type. */ public static final class Descriptor extends GenericDescriptor { /** - * Get the index of this descriptor within its parent. In other words, - * given a {@link FileDescriptor} {@code file}, the following is true: + * Get the index of this descriptor within its parent. In other words, given a {@link + * FileDescriptor} {@code file}, the following is true: + * *

      *   for all i in [0, file.getMessageTypeCount()):
      *     file.getMessageType(i).getIndex() == i
      * 
+ * * Similarly, for a {@link Descriptor} {@code messageType}: + * *
      *   for all i in [0, messageType.getNestedTypeCount()):
      *     messageType.getNestedType(i).getIndex() == i
      * 
*/ - public int getIndex() { return index; } + public int getIndex() { + return index; + } /** Convert the descriptor to its protocol message representation. */ @Override @@ -607,14 +660,15 @@ public String getName() { } /** - * Get the type's fully-qualified name, within the proto language's - * namespace. This differs from the Java name. For example, given this - * {@code .proto}: + * Get the type's fully-qualified name, within the proto language's namespace. This differs from + * the Java name. For example, given this {@code .proto}: + * *
      *   package foo.bar;
      *   option java_package = "com.example.protos"
      *   message Baz {}
      * 
+ * * {@code Baz}'s full name is "foo.bar.Baz". */ @Override @@ -629,10 +683,14 @@ public FileDescriptor getFile() { } /** If this is a nested type, get the outer descriptor, otherwise null. */ - public Descriptor getContainingType() { return containingType; } + public Descriptor getContainingType() { + return containingType; + } /** Get the {@code MessageOptions}, defined in {@code descriptor.proto}. */ - public MessageOptions getOptions() { return proto.getOptions(); } + public MessageOptions getOptions() { + return proto.getOptions(); + } /** Get a list of this message type's fields. */ public List getFields() { @@ -644,6 +702,11 @@ public List getOneofs() { return Collections.unmodifiableList(Arrays.asList(oneofs)); } + /** Get a list of this message type's real oneofs. */ + public List getRealOneofs() { + return Collections.unmodifiableList(Arrays.asList(oneofs).subList(0, realOneofCount)); + } + /** Get a list of this message type's extensions. */ public List getExtensions() { return Collections.unmodifiableList(Arrays.asList(extensions)); @@ -661,8 +724,7 @@ public List getEnumTypes() { /** Determines if the given field number is an extension. */ public boolean isExtensionNumber(final int number) { - for (final DescriptorProto.ExtensionRange range : - proto.getExtensionRangeList()) { + for (final DescriptorProto.ExtensionRange range : proto.getExtensionRangeList()) { if (range.getStart() <= number && number < range.getEnd()) { return true; } @@ -672,8 +734,7 @@ public boolean isExtensionNumber(final int number) { /** Determines if the given field number is reserved. */ public boolean isReservedNumber(final int number) { - for (final DescriptorProto.ReservedRange range : - proto.getReservedRangeList()) { + for (final DescriptorProto.ReservedRange range : proto.getReservedRangeList()) { if (range.getStart() <= number && number < range.getEnd()) { return true; } @@ -693,23 +754,26 @@ public boolean isReservedName(final String name) { } /** - * Indicates whether the message can be extended. That is, whether it has - * any "extensions x to y" ranges declared on it. + * Indicates whether the message can be extended. That is, whether it has any "extensions x to + * y" ranges declared on it. */ public boolean isExtendable() { - return proto.getExtensionRangeList().size() != 0; + return !proto.getExtensionRangeList().isEmpty(); } /** * Finds a field by name. - * @param name The unqualified name of the field (e.g. "foo"). + * + * @param name The unqualified name of the field (e.g. "foo"). For protocol buffer messages that + * follow Google's + * guidance on naming this will be a snake case string, such as
song_name
. * @return The field's descriptor, or {@code null} if not found. */ public FieldDescriptor findFieldByName(final String name) { - final GenericDescriptor result = - file.pool.findSymbol(fullName + '.' + name); - if (result != null && result instanceof FieldDescriptor) { - return (FieldDescriptor)result; + final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name); + if (result instanceof FieldDescriptor) { + return (FieldDescriptor) result; } else { return null; } @@ -717,24 +781,24 @@ public FieldDescriptor findFieldByName(final String name) { /** * Finds a field by field number. + * * @param number The field number within this message type. * @return The field's descriptor, or {@code null} if not found. */ public FieldDescriptor findFieldByNumber(final int number) { - return file.pool.fieldsByNumber.get( - new DescriptorPool.DescriptorIntPair(this, number)); + return file.pool.fieldsByNumber.get(new DescriptorPool.DescriptorIntPair(this, number)); } /** * Finds a nested message type by name. + * * @param name The unqualified name of the nested type (e.g. "Foo"). * @return The types's descriptor, or {@code null} if not found. */ public Descriptor findNestedTypeByName(final String name) { - final GenericDescriptor result = - file.pool.findSymbol(fullName + '.' + name); - if (result != null && result instanceof Descriptor) { - return (Descriptor)result; + final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name); + if (result instanceof Descriptor) { + return (Descriptor) result; } else { return null; } @@ -742,14 +806,14 @@ public Descriptor findNestedTypeByName(final String name) { /** * Finds a nested enum type by name. + * * @param name The unqualified name of the nested type (e.g. "Foo"). * @return The types's descriptor, or {@code null} if not found. */ public EnumDescriptor findEnumTypeByName(final String name) { - final GenericDescriptor result = - file.pool.findSymbol(fullName + '.' + name); - if (result != null && result instanceof EnumDescriptor) { - return (EnumDescriptor)result; + final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name); + if (result instanceof EnumDescriptor) { + return (EnumDescriptor) result; } else { return null; } @@ -765,6 +829,7 @@ public EnumDescriptor findEnumTypeByName(final String name) { private final FieldDescriptor[] fields; private final FieldDescriptor[] extensions; private final OneofDescriptor[] oneofs; + private final int realOneofCount; // Used to create a placeholder when the type cannot be found. Descriptor(final String fullname) throws DescriptorValidationException { @@ -776,9 +841,12 @@ public EnumDescriptor findEnumTypeByName(final String name) { packageName = fullname.substring(0, pos); } this.index = 0; - this.proto = DescriptorProto.newBuilder().setName(name).addExtensionRange( - DescriptorProto.ExtensionRange.newBuilder().setStart(1) - .setEnd(536870912).build()).build(); + this.proto = + DescriptorProto.newBuilder() + .setName(name) + .addExtensionRange( + DescriptorProto.ExtensionRange.newBuilder().setStart(1).setEnd(536870912).build()) + .build(); this.fullName = fullname; this.containingType = null; @@ -787,16 +855,18 @@ public EnumDescriptor findEnumTypeByName(final String name) { this.fields = new FieldDescriptor[0]; this.extensions = new FieldDescriptor[0]; this.oneofs = new OneofDescriptor[0]; + this.realOneofCount = 0; // Create a placeholder FileDescriptor to hold this message. this.file = new FileDescriptor(packageName, this); } - private Descriptor(final DescriptorProto proto, - final FileDescriptor file, - final Descriptor parent, - final int index) - throws DescriptorValidationException { + private Descriptor( + final DescriptorProto proto, + final FileDescriptor file, + final Descriptor parent, + final int index) + throws DescriptorValidationException { this.index = index; this.proto = proto; fullName = computeFullName(file, parent, proto.getName()); @@ -805,32 +875,27 @@ private Descriptor(final DescriptorProto proto, oneofs = new OneofDescriptor[proto.getOneofDeclCount()]; for (int i = 0; i < proto.getOneofDeclCount(); i++) { - oneofs[i] = new OneofDescriptor( - proto.getOneofDecl(i), file, this, i); + oneofs[i] = new OneofDescriptor(proto.getOneofDecl(i), file, this, i); } nestedTypes = new Descriptor[proto.getNestedTypeCount()]; for (int i = 0; i < proto.getNestedTypeCount(); i++) { - nestedTypes[i] = new Descriptor( - proto.getNestedType(i), file, this, i); + nestedTypes[i] = new Descriptor(proto.getNestedType(i), file, this, i); } enumTypes = new EnumDescriptor[proto.getEnumTypeCount()]; for (int i = 0; i < proto.getEnumTypeCount(); i++) { - enumTypes[i] = new EnumDescriptor( - proto.getEnumType(i), file, this, i); + enumTypes[i] = new EnumDescriptor(proto.getEnumType(i), file, this, i); } fields = new FieldDescriptor[proto.getFieldCount()]; for (int i = 0; i < proto.getFieldCount(); i++) { - fields[i] = new FieldDescriptor( - proto.getField(i), file, this, i, false); + fields[i] = new FieldDescriptor(proto.getField(i), file, this, i, false); } extensions = new FieldDescriptor[proto.getExtensionCount()]; for (int i = 0; i < proto.getExtensionCount(); i++) { - extensions[i] = new FieldDescriptor( - proto.getExtension(i), file, this, i, true); + extensions[i] = new FieldDescriptor(proto.getExtension(i), file, this, i, true); } for (int i = 0; i < proto.getOneofDeclCount(); i++) { @@ -844,6 +909,18 @@ private Descriptor(final DescriptorProto proto, } } + int syntheticOneofCount = 0; + for (OneofDescriptor oneof : this.oneofs) { + if (oneof.isSynthetic()) { + syntheticOneofCount++; + } else { + if (syntheticOneofCount > 0) { + throw new DescriptorValidationException(this, "Synthetic oneofs must come last."); + } + } + } + this.realOneofCount = this.oneofs.length - syntheticOneofCount; + file.pool.addSymbol(this); } @@ -891,15 +968,16 @@ private void setProto(final DescriptorProto proto) { // ================================================================= /** Describes a field of a message type. */ - public static final class FieldDescriptor - extends GenericDescriptor - implements Comparable, - FieldSet.FieldDescriptorLite { + public static final class FieldDescriptor extends GenericDescriptor + implements Comparable, FieldSet.FieldDescriptorLite { /** * Get the index of this descriptor within its parent. + * * @see Descriptors.Descriptor#getIndex() */ - public int getIndex() { return index; } + public int getIndex() { + return index; + } /** Convert the descriptor to its protocol message representation. */ @Override @@ -921,6 +999,7 @@ public int getNumber() { /** * Get the field's fully-qualified name. + * * @see Descriptors.Descriptor#getFullName() */ @Override @@ -934,10 +1013,12 @@ public String getJsonName() { } /** - * Get the field's java type. This is just for convenience. Every - * {@code FieldDescriptorProto.Type} maps to exactly one Java type. + * Get the field's java type. This is just for convenience. Every {@code + * FieldDescriptorProto.Type} maps to exactly one Java type. */ - public JavaType getJavaType() { return type.getJavaType(); } + public JavaType getJavaType() { + return type.getJavaType(); + } /** For internal use only. */ @Override @@ -952,7 +1033,9 @@ public FileDescriptor getFile() { } /** Get the field's declared type. */ - public Type getType() { return type; } + public Type getType() { + return type; + } /** For internal use only. */ @Override @@ -976,15 +1059,15 @@ public boolean needsUtf8Check() { } public boolean isMapField() { - return getType() == Type.MESSAGE && isRepeated() + return getType() == Type.MESSAGE + && isRepeated() && getMessageType().getOptions().getMapEntry(); } // I'm pretty sure values() constructs a new array every time, since there // is nothing stopping the caller from mutating the array. Therefore we // make a static copy here. - private static final WireFormat.FieldType[] table = - WireFormat.FieldType.values(); + private static final WireFormat.FieldType[] table = WireFormat.FieldType.values(); /** Is this field declared required? */ public boolean isRequired() { @@ -1002,8 +1085,9 @@ public boolean isRepeated() { return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED; } - /** Does this field have the {@code [packed = true]} option or is this field - * packable in proto3 and not explicitly setted to unpacked? + /** + * Does this field have the {@code [packed = true]} option or is this field packable in proto3 + * and not explicitly set to unpacked? */ @Override public boolean isPacked() { @@ -1023,42 +1107,84 @@ public boolean isPackable() { } /** Returns true if the field had an explicitly-defined default value. */ - public boolean hasDefaultValue() { return proto.hasDefaultValue(); } + public boolean hasDefaultValue() { + return proto.hasDefaultValue(); + } /** - * Returns the field's default value. Valid for all types except for - * messages and groups. For all other types, the object returned is of - * the same class that would returned by Message.getField(this). + * Returns the field's default value. Valid for all types except for messages and groups. For + * all other types, the object returned is of the same class that would returned by + * Message.getField(this). */ public Object getDefaultValue() { if (getJavaType() == JavaType.MESSAGE) { throw new UnsupportedOperationException( - "FieldDescriptor.getDefaultValue() called on an embedded message " + - "field."); + "FieldDescriptor.getDefaultValue() called on an embedded message field."); } return defaultValue; } /** Get the {@code FieldOptions}, defined in {@code descriptor.proto}. */ - public FieldOptions getOptions() { return proto.getOptions(); } + public FieldOptions getOptions() { + return proto.getOptions(); + } /** Is this field an extension? */ - public boolean isExtension() { return proto.hasExtendee(); } + public boolean isExtension() { + return proto.hasExtendee(); + } /** - * Get the field's containing type. For extensions, this is the type being - * extended, not the location where the extension was defined. See - * {@link #getExtensionScope()}. + * Get the field's containing type. For extensions, this is the type being extended, not the + * location where the extension was defined. See {@link #getExtensionScope()}. */ - public Descriptor getContainingType() { return containingType; } + public Descriptor getContainingType() { + return containingType; + } /** Get the field's containing oneof. */ - public OneofDescriptor getContainingOneof() { return containingOneof; } + public OneofDescriptor getContainingOneof() { + return containingOneof; + } + + /** Get the field's containing oneof, only if non-synthetic. */ + public OneofDescriptor getRealContainingOneof() { + return containingOneof != null && !containingOneof.isSynthetic() ? containingOneof : null; + } + + /** + * Returns true if this field was syntactically written with "optional" in the .proto file. + * Excludes singular proto3 fields that do not have a label. + */ + public boolean hasOptionalKeyword() { + return isProto3Optional + || (file.getSyntax() == Syntax.PROTO2 && isOptional() && getContainingOneof() == null); + } /** - * For extensions defined nested within message types, gets the outer - * type. Not valid for non-extension fields. For example, consider - * this {@code .proto} file: + * Returns true if this field tracks presence, ie. does the field distinguish between "unset" + * and "present with default value." + * + *

This includes required, optional, and oneof fields. It excludes maps, repeated fields, and + * singular proto3 fields without "optional". + * + *

For fields where hasPresence() == true, the return value of msg.hasField() is semantically + * meaningful. + */ + boolean hasPresence() { + if (isRepeated()) { + return false; + } + return getType() == Type.MESSAGE + || getType() == Type.GROUP + || getContainingOneof() != null + || file.getSyntax() == Syntax.PROTO2; + } + + /** + * For extensions defined nested within message types, gets the outer type. Not valid for + * non-extension fields. For example, consider this {@code .proto} file: + * *

      *   message Foo {
      *     extensions 1000 to max;
@@ -1072,14 +1198,14 @@ public Object getDefaultValue() {
      *     }
      *   }
      * 
- * Both {@code baz}'s and {@code qux}'s containing type is {@code Foo}. - * However, {@code baz}'s extension scope is {@code null} while - * {@code qux}'s extension scope is {@code Bar}. + * + * Both {@code baz}'s and {@code qux}'s containing type is {@code Foo}. However, {@code baz}'s + * extension scope is {@code null} while {@code qux}'s extension scope is {@code Bar}. */ public Descriptor getExtensionScope() { if (!isExtension()) { throw new UnsupportedOperationException( - "This field is not an extension."); + String.format("This field is not an extension. (%s)", fullName)); } return extensionScope; } @@ -1088,7 +1214,7 @@ public Descriptor getExtensionScope() { public Descriptor getMessageType() { if (getJavaType() != JavaType.MESSAGE) { throw new UnsupportedOperationException( - "This field is not of message type."); + String.format("This field is not of message type. (%s)", fullName)); } return messageType; } @@ -1098,27 +1224,25 @@ public Descriptor getMessageType() { public EnumDescriptor getEnumType() { if (getJavaType() != JavaType.ENUM) { throw new UnsupportedOperationException( - "This field is not of enum type."); + String.format("This field is not of enum type. (%s)", fullName)); } return enumType; } /** - * Compare with another {@code FieldDescriptor}. This orders fields in - * "canonical" order, which simply means ascending order by field number. - * {@code other} must be a field of the same type -- i.e. - * {@code getContainingType()} must return the same {@code Descriptor} for - * both fields. + * Compare with another {@code FieldDescriptor}. This orders fields in "canonical" order, which + * simply means ascending order by field number. {@code other} must be a field of the same type + * -- i.e. {@code getContainingType()} must return the same {@code Descriptor} for both fields. * - * @return negative, zero, or positive if {@code this} is less than, - * equal to, or greater than {@code other}, respectively. + * @return negative, zero, or positive if {@code this} is less than, equal to, or greater than + * {@code other}, respectively. */ @Override public int compareTo(final FieldDescriptor other) { if (other.containingType != containingType) { throw new IllegalArgumentException( - "FieldDescriptors can only be compared to other FieldDescriptors " + - "for fields of the same message type."); + "FieldDescriptors can only be compared to other FieldDescriptors " + + "for fields of the same message type."); } return getNumber() - other.getNumber(); } @@ -1135,6 +1259,7 @@ public String toString() { private final String jsonName; private final FileDescriptor file; private final Descriptor extensionScope; + private final boolean isProto3Optional; // Possibly initialized during cross-linking. private Type type; @@ -1145,24 +1270,24 @@ public String toString() { private Object defaultValue; public enum Type { - DOUBLE (JavaType.DOUBLE ), - FLOAT (JavaType.FLOAT ), - INT64 (JavaType.LONG ), - UINT64 (JavaType.LONG ), - INT32 (JavaType.INT ), - FIXED64 (JavaType.LONG ), - FIXED32 (JavaType.INT ), - BOOL (JavaType.BOOLEAN ), - STRING (JavaType.STRING ), - GROUP (JavaType.MESSAGE ), - MESSAGE (JavaType.MESSAGE ), - BYTES (JavaType.BYTE_STRING), - UINT32 (JavaType.INT ), - ENUM (JavaType.ENUM ), - SFIXED32(JavaType.INT ), - SFIXED64(JavaType.LONG ), - SINT32 (JavaType.INT ), - SINT64 (JavaType.LONG ); + DOUBLE(JavaType.DOUBLE), + FLOAT(JavaType.FLOAT), + INT64(JavaType.LONG), + UINT64(JavaType.LONG), + INT32(JavaType.INT), + FIXED64(JavaType.LONG), + FIXED32(JavaType.INT), + BOOL(JavaType.BOOLEAN), + STRING(JavaType.STRING), + GROUP(JavaType.MESSAGE), + MESSAGE(JavaType.MESSAGE), + BYTES(JavaType.BYTE_STRING), + UINT32(JavaType.INT), + ENUM(JavaType.ENUM), + SFIXED32(JavaType.INT), + SFIXED64(JavaType.LONG), + SINT32(JavaType.INT), + SINT64(JavaType.LONG); Type(final JavaType javaType) { this.javaType = javaType; @@ -1173,7 +1298,10 @@ public enum Type { public FieldDescriptorProto.Type toProto() { return FieldDescriptorProto.Type.forNumber(ordinal() + 1); } - public JavaType getJavaType() { return javaType; } + + public JavaType getJavaType() { + return javaType; + } public static Type valueOf(final FieldDescriptorProto.Type type) { return values()[type.getNumber() - 1]; @@ -1183,9 +1311,8 @@ public static Type valueOf(final FieldDescriptorProto.Type type) { static { // Refuse to init if someone added a new declared type. if (Type.values().length != FieldDescriptorProto.Type.values().length) { - throw new RuntimeException("" - + "descriptor.proto has a new declared type but Descriptors.java " - + "wasn't updated."); + throw new RuntimeException( + "descriptor.proto has a new declared type but Descriptors.java wasn't updated."); } } @@ -1205,8 +1332,8 @@ public enum JavaType { } /** - * The default default value for fields of this type, if it's a primitive - * type. This is meant for use inside this file only, hence is private. + * The default default value for fields of this type, if it's a primitive type. This is meant + * for use inside this file only, hence is private. */ private final Object defaultDefault; } @@ -1214,14 +1341,20 @@ public enum JavaType { // This method should match exactly with the ToJsonName() function in C++ // descriptor.cc. private static String fieldNameToJsonName(String name) { - StringBuilder result = new StringBuilder(name.length()); + final int length = name.length(); + StringBuilder result = new StringBuilder(length); boolean isNextUpperCase = false; - for (int i = 0; i < name.length(); i++) { - Character ch = name.charAt(i); + for (int i = 0; i < length; i++) { + char ch = name.charAt(i); if (ch == '_') { isNextUpperCase = true; } else if (isNextUpperCase) { - result.append(Character.toUpperCase(ch)); + // This closely matches the logic for ASCII characters in: + // http://google3/google/protobuf/descriptor.cc?l=249-251&rcl=228891689 + if ('a' <= ch && ch <= 'z') { + ch = (char) (ch - 'a' + 'A'); + } + result.append(ch); isNextUpperCase = false; } else { result.append(ch); @@ -1230,12 +1363,13 @@ private static String fieldNameToJsonName(String name) { return result.toString(); } - private FieldDescriptor(final FieldDescriptorProto proto, - final FileDescriptor file, - final Descriptor parent, - final int index, - final boolean isExtension) - throws DescriptorValidationException { + private FieldDescriptor( + final FieldDescriptorProto proto, + final FileDescriptor file, + final Descriptor parent, + final int index, + final boolean isExtension) + throws DescriptorValidationException { this.index = index; this.proto = proto; fullName = computeFullName(file, parent, proto.getName()); @@ -1250,17 +1384,18 @@ private FieldDescriptor(final FieldDescriptorProto proto, type = Type.valueOf(proto.getType()); } + isProto3Optional = proto.getProto3Optional(); + if (getNumber() <= 0) { - throw new DescriptorValidationException(this, - "Field numbers must be positive integers."); + throw new DescriptorValidationException(this, "Field numbers must be positive integers."); } if (isExtension) { if (!proto.hasExtendee()) { - throw new DescriptorValidationException(this, - "FieldDescriptorProto.extendee not set for extension field."); + throw new DescriptorValidationException( + this, "FieldDescriptorProto.extendee not set for extension field."); } - containingType = null; // Will be filled in when cross-linking + containingType = null; // Will be filled in when cross-linking if (parent != null) { extensionScope = parent; } else { @@ -1268,23 +1403,23 @@ private FieldDescriptor(final FieldDescriptorProto proto, } if (proto.hasOneofIndex()) { - throw new DescriptorValidationException(this, - "FieldDescriptorProto.oneof_index set for extension field."); + throw new DescriptorValidationException( + this, "FieldDescriptorProto.oneof_index set for extension field."); } containingOneof = null; } else { if (proto.hasExtendee()) { - throw new DescriptorValidationException(this, - "FieldDescriptorProto.extendee set for non-extension field."); + throw new DescriptorValidationException( + this, "FieldDescriptorProto.extendee set for non-extension field."); } containingType = parent; if (proto.hasOneofIndex()) { - if (proto.getOneofIndex() < 0 || - proto.getOneofIndex() >= parent.toProto().getOneofDeclCount()) { - throw new DescriptorValidationException(this, - "FieldDescriptorProto.oneof_index is out of range for type " - + parent.getName()); + if (proto.getOneofIndex() < 0 + || proto.getOneofIndex() >= parent.toProto().getOneofDeclCount()) { + throw new DescriptorValidationException( + this, + "FieldDescriptorProto.oneof_index is out of range for type " + parent.getName()); } containingOneof = parent.getOneofs().get(proto.getOneofIndex()); containingOneof.fieldCount++; @@ -1301,26 +1436,29 @@ private FieldDescriptor(final FieldDescriptorProto proto, private void crossLink() throws DescriptorValidationException { if (proto.hasExtendee()) { final GenericDescriptor extendee = - file.pool.lookupSymbol(proto.getExtendee(), this, - DescriptorPool.SearchFilter.TYPES_ONLY); + file.pool.lookupSymbol( + proto.getExtendee(), this, DescriptorPool.SearchFilter.TYPES_ONLY); if (!(extendee instanceof Descriptor)) { - throw new DescriptorValidationException(this, - '\"' + proto.getExtendee() + "\" is not a message type."); + throw new DescriptorValidationException( + this, '\"' + proto.getExtendee() + "\" is not a message type."); } - containingType = (Descriptor)extendee; + containingType = (Descriptor) extendee; if (!getContainingType().isExtensionNumber(getNumber())) { - throw new DescriptorValidationException(this, - '\"' + getContainingType().getFullName() + - "\" does not declare " + getNumber() + - " as an extension number."); + throw new DescriptorValidationException( + this, + '\"' + + getContainingType().getFullName() + + "\" does not declare " + + getNumber() + + " as an extension number."); } } if (proto.hasTypeName()) { final GenericDescriptor typeDescriptor = - file.pool.lookupSymbol(proto.getTypeName(), this, - DescriptorPool.SearchFilter.TYPES_ONLY); + file.pool.lookupSymbol( + proto.getTypeName(), this, DescriptorPool.SearchFilter.TYPES_ONLY); if (!proto.hasType()) { // Choose field type based on symbol. @@ -1329,53 +1467,49 @@ private void crossLink() throws DescriptorValidationException { } else if (typeDescriptor instanceof EnumDescriptor) { type = Type.ENUM; } else { - throw new DescriptorValidationException(this, - '\"' + proto.getTypeName() + "\" is not a type."); + throw new DescriptorValidationException( + this, '\"' + proto.getTypeName() + "\" is not a type."); } } if (getJavaType() == JavaType.MESSAGE) { if (!(typeDescriptor instanceof Descriptor)) { - throw new DescriptorValidationException(this, - '\"' + proto.getTypeName() + "\" is not a message type."); + throw new DescriptorValidationException( + this, '\"' + proto.getTypeName() + "\" is not a message type."); } - messageType = (Descriptor)typeDescriptor; + messageType = (Descriptor) typeDescriptor; if (proto.hasDefaultValue()) { - throw new DescriptorValidationException(this, - "Messages can't have default values."); + throw new DescriptorValidationException(this, "Messages can't have default values."); } } else if (getJavaType() == JavaType.ENUM) { if (!(typeDescriptor instanceof EnumDescriptor)) { - throw new DescriptorValidationException(this, - '\"' + proto.getTypeName() + "\" is not an enum type."); + throw new DescriptorValidationException( + this, '\"' + proto.getTypeName() + "\" is not an enum type."); } - enumType = (EnumDescriptor)typeDescriptor; + enumType = (EnumDescriptor) typeDescriptor; } else { - throw new DescriptorValidationException(this, - "Field with primitive type has type_name."); + throw new DescriptorValidationException(this, "Field with primitive type has type_name."); } } else { - if (getJavaType() == JavaType.MESSAGE || - getJavaType() == JavaType.ENUM) { - throw new DescriptorValidationException(this, - "Field with message or enum type missing type_name."); + if (getJavaType() == JavaType.MESSAGE || getJavaType() == JavaType.ENUM) { + throw new DescriptorValidationException( + this, "Field with message or enum type missing type_name."); } } // Only repeated primitive fields may be packed. if (proto.getOptions().getPacked() && !isPackable()) { - throw new DescriptorValidationException(this, - "[packed = true] can only be specified for repeated primitive " + - "fields."); + throw new DescriptorValidationException( + this, "[packed = true] can only be specified for repeated primitive fields."); } // We don't attempt to parse the default value until here because for // enums we need the enum type's descriptor. if (proto.hasDefaultValue()) { if (isRepeated()) { - throw new DescriptorValidationException(this, - "Repeated fields cannot have default values."); + throw new DescriptorValidationException( + this, "Repeated fields cannot have default values."); } try { @@ -1428,30 +1562,26 @@ private void crossLink() throws DescriptorValidationException { break; case BYTES: try { - defaultValue = - TextFormat.unescapeBytes(proto.getDefaultValue()); + defaultValue = TextFormat.unescapeBytes(proto.getDefaultValue()); } catch (TextFormat.InvalidEscapeSequenceException e) { - throw new DescriptorValidationException(this, - "Couldn't parse default value: " + e.getMessage(), e); + throw new DescriptorValidationException( + this, "Couldn't parse default value: " + e.getMessage(), e); } break; case ENUM: defaultValue = enumType.findValueByName(proto.getDefaultValue()); if (defaultValue == null) { - throw new DescriptorValidationException(this, - "Unknown enum default value: \"" + - proto.getDefaultValue() + '\"'); + throw new DescriptorValidationException( + this, "Unknown enum default value: \"" + proto.getDefaultValue() + '\"'); } break; case MESSAGE: case GROUP: - throw new DescriptorValidationException(this, - "Message type had default value."); + throw new DescriptorValidationException(this, "Message type had default value."); } } catch (NumberFormatException e) { - throw new DescriptorValidationException(this, - "Could not parse default value: \"" + - proto.getDefaultValue() + '\"', e); + throw new DescriptorValidationException( + this, "Could not parse default value: \"" + proto.getDefaultValue() + '\"', e); } } else { // Determine the default default for this field. @@ -1478,16 +1608,15 @@ private void crossLink() throws DescriptorValidationException { file.pool.addFieldByNumber(this); } - if (containingType != null && - containingType.getOptions().getMessageSetWireFormat()) { + if (containingType != null && containingType.getOptions().getMessageSetWireFormat()) { if (isExtension()) { if (!isOptional() || getType() != Type.MESSAGE) { - throw new DescriptorValidationException(this, - "Extensions of MessageSets must be optional messages."); + throw new DescriptorValidationException( + this, "Extensions of MessageSets must be optional messages."); } } else { - throw new DescriptorValidationException(this, - "MessageSets cannot have fields, only extensions."); + throw new DescriptorValidationException( + this, "MessageSets cannot have fields, only extensions."); } } } @@ -1497,10 +1626,7 @@ private void setProto(final FieldDescriptorProto proto) { this.proto = proto; } - /** - * For internal use only. This is to satisfy the FieldDescriptorLite - * interface. - */ + /** For internal use only. This is to satisfy the FieldDescriptorLite interface. */ @Override public MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from) { // FieldDescriptors are only used with non-lite messages so we can just @@ -1517,9 +1643,12 @@ public static final class EnumDescriptor extends GenericDescriptor implements Internal.EnumLiteMap { /** * Get the index of this descriptor within its parent. + * * @see Descriptors.Descriptor#getIndex() */ - public int getIndex() { return index; } + public int getIndex() { + return index; + } /** Convert the descriptor to its protocol message representation. */ @Override @@ -1535,6 +1664,7 @@ public String getName() { /** * Get the type's fully-qualified name. + * * @see Descriptors.Descriptor#getFullName() */ @Override @@ -1549,10 +1679,14 @@ public FileDescriptor getFile() { } /** If this is a nested type, get the outer descriptor, otherwise null. */ - public Descriptor getContainingType() { return containingType; } + public Descriptor getContainingType() { + return containingType; + } /** Get the {@code EnumOptions}, defined in {@code descriptor.proto}. */ - public EnumOptions getOptions() { return proto.getOptions(); } + public EnumOptions getOptions() { + return proto.getOptions(); + } /** Get a list of defined values for this enum. */ public List getValues() { @@ -1561,34 +1695,34 @@ public List getValues() { /** * Find an enum value by name. + * * @param name The unqualified name of the value (e.g. "FOO"). * @return the value's descriptor, or {@code null} if not found. */ public EnumValueDescriptor findValueByName(final String name) { - final GenericDescriptor result = - file.pool.findSymbol(fullName + '.' + name); - if (result != null && result instanceof EnumValueDescriptor) { - return (EnumValueDescriptor)result; + final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name); + if (result instanceof EnumValueDescriptor) { + return (EnumValueDescriptor) result; } else { return null; } } /** - * Find an enum value by number. If multiple enum values have the same - * number, this returns the first defined value with that number. + * Find an enum value by number. If multiple enum values have the same number, this returns the + * first defined value with that number. + * * @param number The value's number. * @return the value's descriptor, or {@code null} if not found. */ @Override public EnumValueDescriptor findValueByNumber(final int number) { - return file.pool.enumValuesByNumber.get( - new DescriptorPool.DescriptorIntPair(this, number)); + return file.pool.enumValuesByNumber.get(new DescriptorPool.DescriptorIntPair(this, number)); } /** - * Get the enum value for a number. If no enum value has this number, - * construct an EnumValueDescriptor for it. + * Get the enum value for a number. If no enum value has this number, construct an + * EnumValueDescriptor for it. */ public EnumValueDescriptor findValueByNumberCreatingIfUnknown(final int number) { EnumValueDescriptor result = findValueByNumber(number); @@ -1651,13 +1785,14 @@ int getUnknownEnumValueDescriptorCount() { private final Descriptor containingType; private EnumValueDescriptor[] values; private final WeakHashMap> unknownValues = - new WeakHashMap>(); + new WeakHashMap<>(); - private EnumDescriptor(final EnumDescriptorProto proto, - final FileDescriptor file, - final Descriptor parent, - final int index) - throws DescriptorValidationException { + private EnumDescriptor( + final EnumDescriptorProto proto, + final FileDescriptor file, + final Descriptor parent, + final int index) + throws DescriptorValidationException { this.index = index; this.proto = proto; fullName = computeFullName(file, parent, proto.getName()); @@ -1667,14 +1802,12 @@ private EnumDescriptor(final EnumDescriptorProto proto, if (proto.getValueCount() == 0) { // We cannot allow enums with no values because this would mean there // would be no valid default value for fields of this type. - throw new DescriptorValidationException(this, - "Enums must contain at least one value."); + throw new DescriptorValidationException(this, "Enums must contain at least one value."); } values = new EnumValueDescriptor[proto.getValueCount()]; for (int i = 0; i < proto.getValueCount(); i++) { - values[i] = new EnumValueDescriptor( - proto.getValue(i), file, this, i); + values[i] = new EnumValueDescriptor(proto.getValue(i), file, this, i); } file.pool.addSymbol(this); @@ -1693,18 +1826,20 @@ private void setProto(final EnumDescriptorProto proto) { // ================================================================= /** - * Describes one value within an enum type. Note that multiple defined - * values may have the same number. In generated Java code, all values - * with the same number after the first become aliases of the first. - * However, they still have independent EnumValueDescriptors. + * Describes one value within an enum type. Note that multiple defined values may have the same + * number. In generated Java code, all values with the same number after the first become aliases + * of the first. However, they still have independent EnumValueDescriptors. */ public static final class EnumValueDescriptor extends GenericDescriptor implements Internal.EnumLite { /** * Get the index of this descriptor within its parent. + * * @see Descriptors.Descriptor#getIndex() */ - public int getIndex() { return index; } + public int getIndex() { + return index; + } /** Convert the descriptor to its protocol message representation. */ @Override @@ -1725,10 +1860,13 @@ public int getNumber() { } @Override - public String toString() { return proto.getName(); } + public String toString() { + return proto.getName(); + } /** * Get the value's fully-qualified name. + * * @see Descriptors.Descriptor#getFullName() */ @Override @@ -1743,12 +1881,14 @@ public FileDescriptor getFile() { } /** Get the value's enum type. */ - public EnumDescriptor getType() { return type; } + public EnumDescriptor getType() { + return type; + } - /** - * Get the {@code EnumValueOptions}, defined in {@code descriptor.proto}. - */ - public EnumValueOptions getOptions() { return proto.getOptions(); } + /** Get the {@code EnumValueOptions}, defined in {@code descriptor.proto}. */ + public EnumValueOptions getOptions() { + return proto.getOptions(); + } private final int index; private EnumValueDescriptorProto proto; @@ -1756,11 +1896,12 @@ public FileDescriptor getFile() { private final FileDescriptor file; private final EnumDescriptor type; - private EnumValueDescriptor(final EnumValueDescriptorProto proto, - final FileDescriptor file, - final EnumDescriptor parent, - final int index) - throws DescriptorValidationException { + private EnumValueDescriptor( + final EnumValueDescriptorProto proto, + final FileDescriptor file, + final EnumDescriptor parent, + final int index) + throws DescriptorValidationException { this.index = index; this.proto = proto; this.file = file; @@ -1772,21 +1913,17 @@ private EnumValueDescriptor(final EnumValueDescriptorProto proto, file.pool.addEnumValueByNumber(this); } - private Integer number; // Create an unknown enum value. private EnumValueDescriptor( - final FileDescriptor file, - final EnumDescriptor parent, - final Integer number) { + final FileDescriptor file, final EnumDescriptor parent, final Integer number) { String name = "UNKNOWN_ENUM_VALUE_" + parent.getName() + "_" + number; - EnumValueDescriptorProto proto = EnumValueDescriptorProto - .newBuilder().setName(name).setNumber(number).build(); + EnumValueDescriptorProto proto = + EnumValueDescriptorProto.newBuilder().setName(name).setNumber(number).build(); this.index = -1; this.proto = proto; this.file = file; this.type = parent; this.fullName = parent.getFullName() + '.' + proto.getName(); - this.number = number; // Don't add this descriptor into pool. } @@ -1802,10 +1939,11 @@ private void setProto(final EnumValueDescriptorProto proto) { /** Describes a service type. */ public static final class ServiceDescriptor extends GenericDescriptor { /** - * Get the index of this descriptor within its parent. - * * @see Descriptors.Descriptor#getIndex() + * Get the index of this descriptor within its parent. * @see Descriptors.Descriptor#getIndex() */ - public int getIndex() { return index; } + public int getIndex() { + return index; + } /** Convert the descriptor to its protocol message representation. */ @Override @@ -1821,6 +1959,7 @@ public String getName() { /** * Get the type's fully-qualified name. + * * @see Descriptors.Descriptor#getFullName() */ @Override @@ -1835,7 +1974,9 @@ public FileDescriptor getFile() { } /** Get the {@code ServiceOptions}, defined in {@code descriptor.proto}. */ - public ServiceOptions getOptions() { return proto.getOptions(); } + public ServiceOptions getOptions() { + return proto.getOptions(); + } /** Get a list of methods for this service. */ public List getMethods() { @@ -1844,14 +1985,14 @@ public List getMethods() { /** * Find a method by name. + * * @param name The unqualified name of the method (e.g. "Foo"). * @return the method's descriptor, or {@code null} if not found. */ public MethodDescriptor findMethodByName(final String name) { - final GenericDescriptor result = - file.pool.findSymbol(fullName + '.' + name); - if (result != null && result instanceof MethodDescriptor) { - return (MethodDescriptor)result; + final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name); + if (result instanceof MethodDescriptor) { + return (MethodDescriptor) result; } else { return null; } @@ -1863,10 +2004,9 @@ public MethodDescriptor findMethodByName(final String name) { private final FileDescriptor file; private MethodDescriptor[] methods; - private ServiceDescriptor(final ServiceDescriptorProto proto, - final FileDescriptor file, - final int index) - throws DescriptorValidationException { + private ServiceDescriptor( + final ServiceDescriptorProto proto, final FileDescriptor file, final int index) + throws DescriptorValidationException { this.index = index; this.proto = proto; fullName = computeFullName(file, null, proto.getName()); @@ -1874,8 +2014,7 @@ private ServiceDescriptor(final ServiceDescriptorProto proto, methods = new MethodDescriptor[proto.getMethodCount()]; for (int i = 0; i < proto.getMethodCount(); i++) { - methods[i] = new MethodDescriptor( - proto.getMethod(i), file, this, i); + methods[i] = new MethodDescriptor(proto.getMethod(i), file, this, i); } file.pool.addSymbol(this); @@ -1899,15 +2038,14 @@ private void setProto(final ServiceDescriptorProto proto) { // ================================================================= - /** - * Describes one method within a service type. - */ + /** Describes one method within a service type. */ public static final class MethodDescriptor extends GenericDescriptor { /** - * Get the index of this descriptor within its parent. - * * @see Descriptors.Descriptor#getIndex() + * Get the index of this descriptor within its parent. * @see Descriptors.Descriptor#getIndex() */ - public int getIndex() { return index; } + public int getIndex() { + return index; + } /** Convert the descriptor to its protocol message representation. */ @Override @@ -1923,6 +2061,7 @@ public String getName() { /** * Get the method's fully-qualified name. + * * @see Descriptors.Descriptor#getFullName() */ @Override @@ -1937,18 +2076,34 @@ public FileDescriptor getFile() { } /** Get the method's service type. */ - public ServiceDescriptor getService() { return service; } + public ServiceDescriptor getService() { + return service; + } /** Get the method's input type. */ - public Descriptor getInputType() { return inputType; } + public Descriptor getInputType() { + return inputType; + } /** Get the method's output type. */ - public Descriptor getOutputType() { return outputType; } + public Descriptor getOutputType() { + return outputType; + } - /** - * Get the {@code MethodOptions}, defined in {@code descriptor.proto}. - */ - public MethodOptions getOptions() { return proto.getOptions(); } + /** Get whether or not the inputs are streaming. */ + public boolean isClientStreaming() { + return proto.getClientStreaming(); + } + + /** Get whether or not the outputs are streaming. */ + public boolean isServerStreaming() { + return proto.getServerStreaming(); + } + + /** Get the {@code MethodOptions}, defined in {@code descriptor.proto}. */ + public MethodOptions getOptions() { + return proto.getOptions(); + } private final int index; private MethodDescriptorProto proto; @@ -1960,11 +2115,12 @@ public FileDescriptor getFile() { private Descriptor inputType; private Descriptor outputType; - private MethodDescriptor(final MethodDescriptorProto proto, - final FileDescriptor file, - final ServiceDescriptor parent, - final int index) - throws DescriptorValidationException { + private MethodDescriptor( + final MethodDescriptorProto proto, + final FileDescriptor file, + final ServiceDescriptor parent, + final int index) + throws DescriptorValidationException { this.index = index; this.proto = proto; this.file = file; @@ -1977,22 +2133,22 @@ private MethodDescriptor(final MethodDescriptorProto proto, private void crossLink() throws DescriptorValidationException { final GenericDescriptor input = - file.pool.lookupSymbol(proto.getInputType(), this, - DescriptorPool.SearchFilter.TYPES_ONLY); + file.pool.lookupSymbol( + proto.getInputType(), this, DescriptorPool.SearchFilter.TYPES_ONLY); if (!(input instanceof Descriptor)) { - throw new DescriptorValidationException(this, - '\"' + proto.getInputType() + "\" is not a message type."); + throw new DescriptorValidationException( + this, '\"' + proto.getInputType() + "\" is not a message type."); } - inputType = (Descriptor)input; + inputType = (Descriptor) input; final GenericDescriptor output = - file.pool.lookupSymbol(proto.getOutputType(), this, - DescriptorPool.SearchFilter.TYPES_ONLY); + file.pool.lookupSymbol( + proto.getOutputType(), this, DescriptorPool.SearchFilter.TYPES_ONLY); if (!(output instanceof Descriptor)) { - throw new DescriptorValidationException(this, - '\"' + proto.getOutputType() + "\" is not a message type."); + throw new DescriptorValidationException( + this, '\"' + proto.getOutputType() + "\" is not a message type."); } - outputType = (Descriptor)output; + outputType = (Descriptor) output; } /** See {@link FileDescriptor#setProto}. */ @@ -2003,62 +2159,65 @@ private void setProto(final MethodDescriptorProto proto) { // ================================================================= - private static String computeFullName(final FileDescriptor file, - final Descriptor parent, - final String name) { + private static String computeFullName( + final FileDescriptor file, final Descriptor parent, final String name) { if (parent != null) { return parent.getFullName() + '.' + name; - } else if (file.getPackage().length() > 0) { - return file.getPackage() + '.' + name; - } else { - return name; } + + final String packageName = file.getPackage(); + if (!packageName.isEmpty()) { + return packageName + '.' + name; + } + + return name; } // ================================================================= /** - * All descriptors implement this to make it easier to implement tools like - * {@code DescriptorPool}.

- * - * This class is public so that the methods it exposes can be called from - * outside of this package. However, it should only be subclassed from - * nested classes of Descriptors. + * All descriptors implement this to make it easier to implement tools like {@code + * DescriptorPool}. */ public abstract static class GenericDescriptor { + + // Private constructor to prevent subclasses outside of com.google.protobuf.Descriptors + private GenericDescriptor() {} + public abstract Message toProto(); + public abstract String getName(); + public abstract String getFullName(); + public abstract FileDescriptor getFile(); } - /** - * Thrown when building descriptors fails because the source DescriptorProtos - * are not valid. - */ + /** Thrown when building descriptors fails because the source DescriptorProtos are not valid. */ public static class DescriptorValidationException extends Exception { private static final long serialVersionUID = 5750205775490483148L; /** Gets the full name of the descriptor where the error occurred. */ - public String getProblemSymbolName() { return name; } + public String getProblemSymbolName() { + return name; + } - /** - * Gets the protocol message representation of the invalid descriptor. - */ - public Message getProblemProto() { return proto; } + /** Gets the protocol message representation of the invalid descriptor. */ + public Message getProblemProto() { + return proto; + } - /** - * Gets a human-readable description of the error. - */ - public String getDescription() { return description; } + /** Gets a human-readable description of the error. */ + public String getDescription() { + return description; + } private final String name; private final Message proto; private final String description; private DescriptorValidationException( - final GenericDescriptor problemDescriptor, - final String description) { + final GenericDescriptor problemDescriptor, final String description) { super(problemDescriptor.getFullName() + ": " + description); // Note that problemDescriptor may be partially uninitialized, so we @@ -2078,8 +2237,7 @@ private DescriptorValidationException( } private DescriptorValidationException( - final FileDescriptor problemDescriptor, - final String description) { + final FileDescriptor problemDescriptor, final String description) { super(problemDescriptor.getName() + ": " + description); // Note that problemDescriptor may be partially uninitialized, so we @@ -2094,25 +2252,25 @@ private DescriptorValidationException( // ================================================================= /** - * A private helper class which contains lookup tables containing all the - * descriptors defined in a particular file. + * A private helper class which contains lookup tables containing all the descriptors defined in a + * particular file. */ private static final class DescriptorPool { - /** Defines what subclass of descriptors to search in the descriptor pool. - */ + /** Defines what subclass of descriptors to search in the descriptor pool. */ enum SearchFilter { - TYPES_ONLY, AGGREGATES_ONLY, ALL_SYMBOLS + TYPES_ONLY, + AGGREGATES_ONLY, + ALL_SYMBOLS } - DescriptorPool(final FileDescriptor[] dependencies, - boolean allowUnknownDependencies) { - this.dependencies = new HashSet(); + DescriptorPool(final FileDescriptor[] dependencies, boolean allowUnknownDependencies) { + this.dependencies = new HashSet<>(); this.allowUnknownDependencies = allowUnknownDependencies; - for (int i = 0; i < dependencies.length; i++) { - this.dependencies.add(dependencies[i]); - importPublicDependencies(dependencies[i]); + for (Descriptors.FileDescriptor dependency : dependencies) { + this.dependencies.add(dependency); + importPublicDependencies(dependency); } for (final FileDescriptor dependency : this.dependencies) { @@ -2127,7 +2285,7 @@ enum SearchFilter { } } - /** Find and put public dependencies of the file into dependencies set.*/ + /** Find and put public dependencies of the file into dependencies set. */ private void importPublicDependencies(final FileDescriptor file) { for (FileDescriptor dependency : file.getPublicDependencies()) { if (dependencies.add(dependency)) { @@ -2139,28 +2297,25 @@ private void importPublicDependencies(final FileDescriptor file) { private final Set dependencies; private boolean allowUnknownDependencies; - private final Map descriptorsByName = - new HashMap(); - private final Map fieldsByNumber = - new HashMap(); - private final Map enumValuesByNumber - = new HashMap(); + private final Map descriptorsByName = new HashMap<>(); + private final Map fieldsByNumber = new HashMap<>(); + private final Map enumValuesByNumber = new HashMap<>(); /** Find a generic descriptor by fully-qualified name. */ GenericDescriptor findSymbol(final String fullName) { return findSymbol(fullName, SearchFilter.ALL_SYMBOLS); } - /** Find a descriptor by fully-qualified name and given option to only - * search valid field type descriptors. + /** + * Find a descriptor by fully-qualified name and given option to only search valid field type + * descriptors. */ - GenericDescriptor findSymbol(final String fullName, - final SearchFilter filter) { + GenericDescriptor findSymbol(final String fullName, final SearchFilter filter) { GenericDescriptor result = descriptorsByName.get(fullName); if (result != null) { - if ((filter==SearchFilter.ALL_SYMBOLS) || - ((filter==SearchFilter.TYPES_ONLY) && isType(result)) || - ((filter==SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) { + if ((filter == SearchFilter.ALL_SYMBOLS) + || ((filter == SearchFilter.TYPES_ONLY) && isType(result)) + || ((filter == SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) { return result; } } @@ -2168,9 +2323,9 @@ GenericDescriptor findSymbol(final String fullName, for (final FileDescriptor dependency : dependencies) { result = dependency.pool.descriptorsByName.get(fullName); if (result != null) { - if ((filter==SearchFilter.ALL_SYMBOLS) || - ((filter==SearchFilter.TYPES_ONLY) && isType(result)) || - ((filter==SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) { + if ((filter == SearchFilter.ALL_SYMBOLS) + || ((filter == SearchFilter.TYPES_ONLY) && isType(result)) + || ((filter == SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) { return result; } } @@ -2181,28 +2336,27 @@ GenericDescriptor findSymbol(final String fullName, /** Checks if the descriptor is a valid type for a message field. */ boolean isType(GenericDescriptor descriptor) { - return (descriptor instanceof Descriptor) || - (descriptor instanceof EnumDescriptor); + return (descriptor instanceof Descriptor) || (descriptor instanceof EnumDescriptor); } /** Checks if the descriptor is a valid namespace type. */ boolean isAggregate(GenericDescriptor descriptor) { - return (descriptor instanceof Descriptor) || - (descriptor instanceof EnumDescriptor) || - (descriptor instanceof PackageDescriptor) || - (descriptor instanceof ServiceDescriptor); + return (descriptor instanceof Descriptor) + || (descriptor instanceof EnumDescriptor) + || (descriptor instanceof PackageDescriptor) + || (descriptor instanceof ServiceDescriptor); } /** - * Look up a type descriptor by name, relative to some other descriptor. - * The name may be fully-qualified (with a leading '.'), - * partially-qualified, or unqualified. C++-like name lookup semantics - * are used to search for the matching descriptor. + * Look up a type descriptor by name, relative to some other descriptor. The name may be + * fully-qualified (with a leading '.'), partially-qualified, or unqualified. C++-like name + * lookup semantics are used to search for the matching descriptor. */ - GenericDescriptor lookupSymbol(final String name, - final GenericDescriptor relativeTo, - final DescriptorPool.SearchFilter filter) - throws DescriptorValidationException { + GenericDescriptor lookupSymbol( + final String name, + final GenericDescriptor relativeTo, + final DescriptorPool.SearchFilter filter) + throws DescriptorValidationException { // TODO(kenton): This could be optimized in a number of ways. GenericDescriptor result; @@ -2235,8 +2389,7 @@ GenericDescriptor lookupSymbol(final String name, // We will search each parent scope of "relativeTo" looking for the // symbol. - final StringBuilder scopeToTry = - new StringBuilder(relativeTo.getFullName()); + final StringBuilder scopeToTry = new StringBuilder(relativeTo.getFullName()); while (true) { // Chop off the last component of the scope. @@ -2250,8 +2403,7 @@ GenericDescriptor lookupSymbol(final String name, // Append firstPart and try to find scopeToTry.append(firstPart); - result = findSymbol(scopeToTry.toString(), - DescriptorPool.SearchFilter.AGGREGATES_ONLY); + result = findSymbol(scopeToTry.toString(), DescriptorPool.SearchFilter.AGGREGATES_ONLY); if (result != null) { if (firstPartLength != -1) { @@ -2274,22 +2426,23 @@ GenericDescriptor lookupSymbol(final String name, if (result == null) { if (allowUnknownDependencies && filter == SearchFilter.TYPES_ONLY) { - logger.warning("The descriptor for message type \"" + name + - "\" can not be found and a placeholder is created for it"); + logger.warning( + "The descriptor for message type \"" + + name + + "\" can not be found and a placeholder is created for it"); // We create a dummy message descriptor here regardless of the // expected type. If the type should be message, this dummy // descriptor will work well and if the type should be enum, a // DescriptorValidationException will be thrown latter. In either // case, the code works as expected: we allow unknown message types - // but not unknwon enum types. + // but not unknown enum types. result = new Descriptor(fullname); // Add the placeholder file as a dependency so we can find the // placeholder symbol when resolving other references. this.dependencies.add(result.getFile()); return result; } else { - throw new DescriptorValidationException(relativeTo, - '\"' + name + "\" is not defined."); + throw new DescriptorValidationException(relativeTo, '\"' + name + "\" is not defined."); } } else { return result; @@ -2297,63 +2450,71 @@ GenericDescriptor lookupSymbol(final String name, } /** - * Adds a symbol to the symbol table. If a symbol with the same name - * already exists, throws an error. + * Adds a symbol to the symbol table. If a symbol with the same name already exists, throws an + * error. */ - void addSymbol(final GenericDescriptor descriptor) - throws DescriptorValidationException { + void addSymbol(final GenericDescriptor descriptor) throws DescriptorValidationException { validateSymbolName(descriptor); final String fullName = descriptor.getFullName(); - final int dotpos = fullName.lastIndexOf('.'); final GenericDescriptor old = descriptorsByName.put(fullName, descriptor); if (old != null) { descriptorsByName.put(fullName, old); if (descriptor.getFile() == old.getFile()) { + final int dotpos = fullName.lastIndexOf('.'); if (dotpos == -1) { - throw new DescriptorValidationException(descriptor, - '\"' + fullName + "\" is already defined."); + throw new DescriptorValidationException( + descriptor, '\"' + fullName + "\" is already defined."); } else { - throw new DescriptorValidationException(descriptor, - '\"' + fullName.substring(dotpos + 1) + - "\" is already defined in \"" + - fullName.substring(0, dotpos) + "\"."); + throw new DescriptorValidationException( + descriptor, + '\"' + + fullName.substring(dotpos + 1) + + "\" is already defined in \"" + + fullName.substring(0, dotpos) + + "\"."); } } else { - throw new DescriptorValidationException(descriptor, - '\"' + fullName + "\" is already defined in file \"" + - old.getFile().getName() + "\"."); + throw new DescriptorValidationException( + descriptor, + '\"' + + fullName + + "\" is already defined in file \"" + + old.getFile().getName() + + "\"."); } } } /** - * Represents a package in the symbol table. We use PackageDescriptors - * just as placeholders so that someone cannot define, say, a message type - * that has the same name as an existing package. + * Represents a package in the symbol table. We use PackageDescriptors just as placeholders so + * that someone cannot define, say, a message type that has the same name as an existing + * package. */ private static final class PackageDescriptor extends GenericDescriptor { @Override public Message toProto() { return file.toProto(); } + @Override public String getName() { return name; } + @Override public String getFullName() { return fullName; } + @Override public FileDescriptor getFile() { return file; } - PackageDescriptor(final String name, final String fullName, - final FileDescriptor file) { + PackageDescriptor(final String name, final String fullName, final FileDescriptor file) { this.file = file; this.fullName = fullName; this.name = name; @@ -2365,13 +2526,12 @@ public FileDescriptor getFile() { } /** - * Adds a package to the symbol tables. If a package by the same name - * already exists, that is fine, but if some other kind of symbol exists - * under the same name, an exception is thrown. If the package has - * multiple components, this also adds the parent package(s). + * Adds a package to the symbol tables. If a package by the same name already exists, that is + * fine, but if some other kind of symbol exists under the same name, an exception is thrown. If + * the package has multiple components, this also adds the parent package(s). */ void addPackage(final String fullName, final FileDescriptor file) - throws DescriptorValidationException { + throws DescriptorValidationException { final int dotpos = fullName.lastIndexOf('.'); final String name; if (dotpos == -1) { @@ -2382,14 +2542,18 @@ void addPackage(final String fullName, final FileDescriptor file) } final GenericDescriptor old = - descriptorsByName.put(fullName, - new PackageDescriptor(name, fullName, file)); + descriptorsByName.put(fullName, new PackageDescriptor(name, fullName, file)); if (old != null) { descriptorsByName.put(fullName, old); if (!(old instanceof PackageDescriptor)) { - throw new DescriptorValidationException(file, - '\"' + name + "\" is already defined (as something other than a " - + "package) in file \"" + old.getFile().getName() + "\"."); + throw new DescriptorValidationException( + file, + '\"' + + name + + "\" is already defined (as something other than a " + + "package) in file \"" + + old.getFile().getName() + + "\"."); } } } @@ -2408,43 +2572,46 @@ private static final class DescriptorIntPair { public int hashCode() { return descriptor.hashCode() * ((1 << 16) - 1) + number; } + @Override public boolean equals(final Object obj) { if (!(obj instanceof DescriptorIntPair)) { return false; } - final DescriptorIntPair other = (DescriptorIntPair)obj; + final DescriptorIntPair other = (DescriptorIntPair) obj; return descriptor == other.descriptor && number == other.number; } } /** - * Adds a field to the fieldsByNumber table. Throws an exception if a - * field with the same containing type and number already exists. + * Adds a field to the fieldsByNumber table. Throws an exception if a field with the same + * containing type and number already exists. */ - void addFieldByNumber(final FieldDescriptor field) - throws DescriptorValidationException { + void addFieldByNumber(final FieldDescriptor field) throws DescriptorValidationException { final DescriptorIntPair key = - new DescriptorIntPair(field.getContainingType(), field.getNumber()); + new DescriptorIntPair(field.getContainingType(), field.getNumber()); final FieldDescriptor old = fieldsByNumber.put(key, field); if (old != null) { fieldsByNumber.put(key, old); - throw new DescriptorValidationException(field, - "Field number " + field.getNumber() + - " has already been used in \"" + - field.getContainingType().getFullName() + - "\" by field \"" + old.getName() + "\"."); + throw new DescriptorValidationException( + field, + "Field number " + + field.getNumber() + + " has already been used in \"" + + field.getContainingType().getFullName() + + "\" by field \"" + + old.getName() + + "\"."); } } /** - * Adds an enum value to the enumValuesByNumber table. If an enum value - * with the same type and number already exists, does nothing. (This is - * allowed; the first value define with the number takes precedence.) + * Adds an enum value to the enumValuesByNumber table. If an enum value with the same type and + * number already exists, does nothing. (This is allowed; the first value define with the number + * takes precedence.) */ void addEnumValueByNumber(final EnumValueDescriptor value) { - final DescriptorIntPair key = - new DescriptorIntPair(value.getType(), value.getNumber()); + final DescriptorIntPair key = new DescriptorIntPair(value.getType(), value.getNumber()); final EnumValueDescriptor old = enumValuesByNumber.put(key, value); if (old != null) { enumValuesByNumber.put(key, old); @@ -2454,59 +2621,72 @@ void addEnumValueByNumber(final EnumValueDescriptor value) { } /** - * Verifies that the descriptor's name is valid (i.e. it contains only - * letters, digits, and underscores, and does not start with a digit). + * Verifies that the descriptor's name is valid (i.e. it contains only letters, digits, and + * underscores, and does not start with a digit). */ static void validateSymbolName(final GenericDescriptor descriptor) - throws DescriptorValidationException { + throws DescriptorValidationException { final String name = descriptor.getName(); if (name.length() == 0) { throw new DescriptorValidationException(descriptor, "Missing name."); - } else { - boolean valid = true; - for (int i = 0; i < name.length(); i++) { - final char c = name.charAt(i); - // Non-ASCII characters are not valid in protobuf identifiers, even - // if they are letters or digits. - if (c >= 128) { - valid = false; - } - // First character must be letter or _. Subsequent characters may - // be letters, numbers, or digits. - if (Character.isLetter(c) || c == '_' || - (Character.isDigit(c) && i > 0)) { - // Valid - } else { - valid = false; - } - } - if (!valid) { - throw new DescriptorValidationException(descriptor, - '\"' + name + "\" is not a valid identifier."); + } + + // Non-ASCII characters are not valid in protobuf identifiers, even + // if they are letters or digits. + // The first character must be a letter or '_'. + // Subsequent characters may be letters, numbers, or digits. + for (int i = 0; i < name.length(); i++) { + final char c = name.charAt(i); + if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') + || (c == '_') + || ('0' <= c && c <= '9' && i > 0)) { + // Valid + continue; } + throw new DescriptorValidationException( + descriptor, '\"' + name + "\" is not a valid identifier."); } } } /** Describes an oneof of a message type. */ - public static final class OneofDescriptor { + public static final class OneofDescriptor extends GenericDescriptor { /** Get the index of this descriptor within its parent. */ - public int getIndex() { return index; } + public int getIndex() { + return index; + } - public String getName() { return proto.getName(); } + @Override + public String getName() { + return proto.getName(); + } - public FileDescriptor getFile() { return file; } + @Override + public FileDescriptor getFile() { + return file; + } - public String getFullName() { return fullName; } + @Override + public String getFullName() { + return fullName; + } - public Descriptor getContainingType() { return containingType; } + public Descriptor getContainingType() { + return containingType; + } - public int getFieldCount() { return fieldCount; } + public int getFieldCount() { + return fieldCount; + } public OneofOptions getOptions() { return proto.getOptions(); } + public boolean isSynthetic() { + return fields.length == 1 && fields[0].isProto3Optional; + } + /** Get a list of this message type's fields. */ public List getFields() { return Collections.unmodifiableList(Arrays.asList(fields)); @@ -2516,15 +2696,21 @@ public FieldDescriptor getField(int index) { return fields[index]; } + @Override + public OneofDescriptorProto toProto() { + return proto; + } + private void setProto(final OneofDescriptorProto proto) { this.proto = proto; } - private OneofDescriptor(final OneofDescriptorProto proto, - final FileDescriptor file, - final Descriptor parent, - final int index) - throws DescriptorValidationException { + private OneofDescriptor( + final OneofDescriptorProto proto, + final FileDescriptor file, + final Descriptor parent, + final int index) + throws DescriptorValidationException { this.proto = proto; fullName = computeFullName(file, parent, proto.getName()); this.file = file; diff --git a/java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java b/java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java index 7ae9434906108..c2378adce8478 100644 --- a/java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java +++ b/java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java @@ -30,21 +30,20 @@ package com.google.protobuf; -/** - * Parsers to discard unknown fields during parsing. - */ +/** Parsers to discard unknown fields during parsing. */ public final class DiscardUnknownFieldsParser { /** - * Warps a given {@link Parser} into a new {@link Parser} that discards unknown fields during + * Wraps a given {@link Parser} into a new {@link Parser} that discards unknown fields during * parsing. * *

Usage example: + * *

{@code
-     * private final static Parser FOO_PARSER = DiscardUnknownFieldsParser.wrap(Foo.parser());
-     * Foo parseFooDiscardUnknown(ByteBuffer input) throws IOException {
-     *   return FOO_PARSER.parseFrom(input);
-     * }
+   * private final static Parser FOO_PARSER = DiscardUnknownFieldsParser.wrap(Foo.parser());
+   * Foo parseFooDiscardUnknown(ByteBuffer input) throws IOException {
+   *   return FOO_PARSER.parseFrom(input);
+   * }
    * }
* *

Like all other implementations of {@code Parser}, this parser is stateless and thread-safe. diff --git a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java index 867b85ce8617a..408565343720d 100644 --- a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java @@ -45,7 +45,7 @@ final class DoubleArrayList extends AbstractProtobufList implements DoubleList, RandomAccess, PrimitiveNonBoxingCollection { - private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList(); + private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList(new double[0], 0); static { EMPTY_LIST.makeImmutable(); } @@ -54,9 +54,7 @@ public static DoubleArrayList emptyList() { return EMPTY_LIST; } - /** - * The backing store for the list. - */ + /** The backing store for the list. */ private double[] array; /** @@ -65,22 +63,31 @@ public static DoubleArrayList emptyList() { */ private int size; - /** - * Constructs a new mutable {@code DoubleArrayList} with default capacity. - */ + /** Constructs a new mutable {@code DoubleArrayList} with default capacity. */ DoubleArrayList() { this(new double[DEFAULT_CAPACITY], 0); } /** - * Constructs a new mutable {@code DoubleArrayList} - * containing the same elements as {@code other}. + * Constructs a new mutable {@code DoubleArrayList} containing the same elements as {@code other}. */ private DoubleArrayList(double[] other, int size) { array = other; this.size = size; } + @Override + protected void removeRange(int fromIndex, int toIndex) { + ensureIsMutable(); + if (toIndex < fromIndex) { + throw new IndexOutOfBoundsException("toIndex < fromIndex"); + } + + System.arraycopy(array, toIndex, array, fromIndex, size - toIndex); + size -= (toIndex - fromIndex); + modCount++; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -96,7 +103,7 @@ public boolean equals(Object o) { final double[] arr = other.array; for (int i = 0; i < size; i++) { - if (array[i] != arr[i]) { + if (Double.doubleToLongBits(array[i]) != Double.doubleToLongBits(arr[i])) { return false; } } @@ -133,6 +140,26 @@ public double getDouble(int index) { return array[index]; } + @Override + public int indexOf(Object element) { + if (!(element instanceof Double)) { + return -1; + } + double unboxedElement = (Double) element; + int numElems = size(); + for (int i = 0; i < numElems; i++) { + if (array[i] == unboxedElement) { + return i; + } + } + return -1; + } + + @Override + public boolean contains(Object element) { + return indexOf(element) != -1; + } + @Override public int size() { return size; @@ -152,22 +179,34 @@ public double setDouble(int index, double element) { return previousValue; } + @Override + public boolean add(Double element) { + addDouble(element); + return true; + } + @Override public void add(int index, Double element) { addDouble(index, element); } - /** - * Like {@link #add(Double)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(Double)} but more efficient in that it doesn't box the element. */ @Override public void addDouble(double element) { - addDouble(size, element); + ensureIsMutable(); + if (size == array.length) { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + double[] newArray = new double[length]; + + System.arraycopy(array, 0, newArray, 0, size); + array = newArray; + } + + array[size++] = element; } - /** - * Like {@link #add(int, Double)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(int, Double)} but more efficient in that it doesn't box the element. */ private void addDouble(int index, double element) { ensureIsMutable(); if (index < 0 || index > size) { @@ -228,26 +267,14 @@ public boolean addAll(Collection collection) { return true; } - @Override - public boolean remove(Object o) { - ensureIsMutable(); - for (int i = 0; i < size; i++) { - if (o.equals(array[i])) { - System.arraycopy(array, i + 1, array, i, size - i); - size--; - modCount++; - return true; - } - } - return false; - } - @Override public Double remove(int index) { ensureIsMutable(); ensureIndexInRange(index); double value = array[index]; - System.arraycopy(array, index + 1, array, index, size - index); + if (index < size - 1) { + System.arraycopy(array, index + 1, array, index, size - index - 1); + } size--; modCount++; return value; diff --git a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java index ba5320217d531..8beebba24d65b 100644 --- a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java +++ b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java @@ -43,8 +43,8 @@ import java.util.Map; /** - * An implementation of {@link Message} that can represent arbitrary types, - * given a {@link Descriptors.Descriptor}. + * An implementation of {@link Message} that can represent arbitrary types, given a {@link + * Descriptors.Descriptor}. * * @author kenton@google.com Kenton Varda */ @@ -56,88 +56,83 @@ public final class DynamicMessage extends AbstractMessage { private int memoizedSize = -1; /** - * Construct a {@code DynamicMessage} using the given {@code FieldSet}. - * oneofCases stores the FieldDescriptor for each oneof to indicate - * which field is set. Caller should make sure the array is immutable. + * Construct a {@code DynamicMessage} using the given {@code FieldSet}. oneofCases stores the + * FieldDescriptor for each oneof to indicate which field is set. Caller should make sure the + * array is immutable. * - * This constructor is package private and will be used in - * {@code DynamicMutableMessage} to convert a mutable message to an immutable - * message. + *

This constructor is package private and will be used in {@code DynamicMutableMessage} to + * convert a mutable message to an immutable message. */ - DynamicMessage(Descriptor type, FieldSet fields, - FieldDescriptor[] oneofCases, - UnknownFieldSet unknownFields) { + DynamicMessage( + Descriptor type, + FieldSet fields, + FieldDescriptor[] oneofCases, + UnknownFieldSet unknownFields) { this.type = type; this.fields = fields; this.oneofCases = oneofCases; this.unknownFields = unknownFields; } - /** - * Get a {@code DynamicMessage} representing the default instance of the - * given type. - */ + /** Get a {@code DynamicMessage} representing the default instance of the given type. */ public static DynamicMessage getDefaultInstance(Descriptor type) { int oneofDeclCount = type.toProto().getOneofDeclCount(); FieldDescriptor[] oneofCases = new FieldDescriptor[oneofDeclCount]; - return new DynamicMessage(type, FieldSet.emptySet(), - oneofCases, - UnknownFieldSet.getDefaultInstance()); + return new DynamicMessage( + type, + FieldSet.emptySet(), + oneofCases, + UnknownFieldSet.getDefaultInstance()); } /** Parse a message of the given type from the given input stream. */ - public static DynamicMessage parseFrom(Descriptor type, - CodedInputStream input) - throws IOException { + public static DynamicMessage parseFrom(Descriptor type, CodedInputStream input) + throws IOException { return newBuilder(type).mergeFrom(input).buildParsed(); } /** Parse a message of the given type from the given input stream. */ public static DynamicMessage parseFrom( - Descriptor type, - CodedInputStream input, - ExtensionRegistry extensionRegistry) + Descriptor type, CodedInputStream input, ExtensionRegistry extensionRegistry) throws IOException { return newBuilder(type).mergeFrom(input, extensionRegistry).buildParsed(); } /** Parse {@code data} as a message of the given type and return it. */ public static DynamicMessage parseFrom(Descriptor type, ByteString data) - throws InvalidProtocolBufferException { + throws InvalidProtocolBufferException { return newBuilder(type).mergeFrom(data).buildParsed(); } /** Parse {@code data} as a message of the given type and return it. */ - public static DynamicMessage parseFrom(Descriptor type, ByteString data, - ExtensionRegistry extensionRegistry) - throws InvalidProtocolBufferException { + public static DynamicMessage parseFrom( + Descriptor type, ByteString data, ExtensionRegistry extensionRegistry) + throws InvalidProtocolBufferException { return newBuilder(type).mergeFrom(data, extensionRegistry).buildParsed(); } /** Parse {@code data} as a message of the given type and return it. */ public static DynamicMessage parseFrom(Descriptor type, byte[] data) - throws InvalidProtocolBufferException { + throws InvalidProtocolBufferException { return newBuilder(type).mergeFrom(data).buildParsed(); } /** Parse {@code data} as a message of the given type and return it. */ - public static DynamicMessage parseFrom(Descriptor type, byte[] data, - ExtensionRegistry extensionRegistry) - throws InvalidProtocolBufferException { + public static DynamicMessage parseFrom( + Descriptor type, byte[] data, ExtensionRegistry extensionRegistry) + throws InvalidProtocolBufferException { return newBuilder(type).mergeFrom(data, extensionRegistry).buildParsed(); } /** Parse a message of the given type from {@code input} and return it. */ - public static DynamicMessage parseFrom(Descriptor type, InputStream input) - throws IOException { + public static DynamicMessage parseFrom(Descriptor type, InputStream input) throws IOException { return newBuilder(type).mergeFrom(input).buildParsed(); } /** Parse a message of the given type from {@code input} and return it. */ - public static DynamicMessage parseFrom(Descriptor type, InputStream input, - ExtensionRegistry extensionRegistry) - throws IOException { + public static DynamicMessage parseFrom( + Descriptor type, InputStream input, ExtensionRegistry extensionRegistry) throws IOException { return newBuilder(type).mergeFrom(input, extensionRegistry).buildParsed(); } @@ -147,8 +142,8 @@ public static Builder newBuilder(Descriptor type) { } /** - * Construct a {@link Message.Builder} for a message of the same type as - * {@code prototype}, and initialize it with {@code prototype}'s contents. + * Construct a {@link Message.Builder} for a message of the same type as {@code prototype}, and + * initialize it with {@code prototype}'s contents. */ public static Builder newBuilder(Message prototype) { return new Builder(prototype.getDescriptorForType()).mergeFrom(prototype); @@ -227,8 +222,7 @@ public UnknownFieldSet getUnknownFields() { return unknownFields; } - static boolean isInitialized(Descriptor type, - FieldSet fields) { + static boolean isInitialized(Descriptor type, FieldSet fields) { // Check that all required fields are present. for (final FieldDescriptor field : type.getFields()) { if (field.isRequired()) { @@ -298,8 +292,7 @@ public DynamicMessage parsePartialFrom( } catch (InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(builder.buildPartial()); } catch (IOException e) { - throw new InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); + throw new InvalidProtocolBufferException(e).setUnfinishedMessage(builder.buildPartial()); } return builder.buildPartial(); } @@ -309,24 +302,20 @@ public DynamicMessage parsePartialFrom( /** Verifies that the field is a field of this message. */ private void verifyContainingType(FieldDescriptor field) { if (field.getContainingType() != type) { - throw new IllegalArgumentException( - "FieldDescriptor does not match message type."); + throw new IllegalArgumentException("FieldDescriptor does not match message type."); } } /** Verifies that the oneof is an oneof of this message. */ private void verifyOneofContainingType(OneofDescriptor oneof) { if (oneof.getContainingType() != type) { - throw new IllegalArgumentException( - "OneofDescriptor does not match message type."); + throw new IllegalArgumentException("OneofDescriptor does not match message type."); } } // ================================================================= - /** - * Builder for {@link DynamicMessage}s. - */ + /** Builder for {@link DynamicMessage}s. */ public static final class Builder extends AbstractMessage.Builder { private final Descriptor type; private FieldSet fields; @@ -362,7 +351,7 @@ public Builder mergeFrom(Message other) { DynamicMessage otherDynamicMessage = (DynamicMessage) other; if (otherDynamicMessage.type != type) { throw new IllegalArgumentException( - "mergeFrom(Message) can only merge messages of the same type."); + "mergeFrom(Message) can only merge messages of the same type."); } ensureIsMutable(); fields.mergeFrom(otherDynamicMessage.fields); @@ -388,33 +377,51 @@ public Builder mergeFrom(Message other) { public DynamicMessage build() { if (!isInitialized()) { throw newUninitializedMessageException( - new DynamicMessage(type, fields, - java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields)); + new DynamicMessage( + type, + fields, + java.util.Arrays.copyOf(oneofCases, oneofCases.length), + unknownFields)); } return buildPartial(); } /** - * Helper for DynamicMessage.parseFrom() methods to call. Throws - * {@link InvalidProtocolBufferException} instead of - * {@link UninitializedMessageException}. + * Helper for DynamicMessage.parseFrom() methods to call. Throws {@link + * InvalidProtocolBufferException} instead of {@link UninitializedMessageException}. */ private DynamicMessage buildParsed() throws InvalidProtocolBufferException { if (!isInitialized()) { throw newUninitializedMessageException( - new DynamicMessage(type, fields, - java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields)) - .asInvalidProtocolBufferException(); + new DynamicMessage( + type, + fields, + java.util.Arrays.copyOf(oneofCases, oneofCases.length), + unknownFields)) + .asInvalidProtocolBufferException(); } return buildPartial(); } @Override public DynamicMessage buildPartial() { + // Set default values for all fields in a MapEntry. + if (type.getOptions().getMapEntry()) { + for (FieldDescriptor field : type.getFields()) { + if (field.isOptional() && !fields.hasField(field)) { + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + fields.setField(field, getDefaultInstance(field.getMessageType())); + } else { + fields.setField(field, field.getDefaultValue()); + } + } + } + } + fields.makeImmutable(); DynamicMessage result = - new DynamicMessage(type, fields, - java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields); + new DynamicMessage( + type, fields, java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields); return result; } @@ -423,7 +430,7 @@ public Builder clone() { Builder result = new Builder(type); result.fields.mergeFrom(fields); result.mergeUnknownFields(unknownFields); - System.arraycopy(oneofCases, 0, result.oneofCases, 0 , oneofCases.length); + System.arraycopy(oneofCases, 0, result.oneofCases, 0, oneofCases.length); return result; } @@ -453,7 +460,7 @@ public Builder newBuilderForField(FieldDescriptor field) { if (field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { throw new IllegalArgumentException( - "newBuilderForField is only valid for fields with message type."); + "newBuilderForField is only valid for fields with message type."); } return new Builder(field.getMessageType()); @@ -590,50 +597,37 @@ public UnknownFieldSet getUnknownFields() { @Override public Builder setUnknownFields(UnknownFieldSet unknownFields) { - if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3 - && CodedInputStream.getProto3DiscardUnknownFieldsDefault()) { - return this; - } this.unknownFields = unknownFields; return this; } @Override public Builder mergeUnknownFields(UnknownFieldSet unknownFields) { - if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3 - && CodedInputStream.getProto3DiscardUnknownFieldsDefault()) { - return this; - } this.unknownFields = - UnknownFieldSet.newBuilder(this.unknownFields) - .mergeFrom(unknownFields) - .build(); + UnknownFieldSet.newBuilder(this.unknownFields).mergeFrom(unknownFields).build(); return this; } /** Verifies that the field is a field of this message. */ private void verifyContainingType(FieldDescriptor field) { if (field.getContainingType() != type) { - throw new IllegalArgumentException( - "FieldDescriptor does not match message type."); + throw new IllegalArgumentException("FieldDescriptor does not match message type."); } } /** Verifies that the oneof is an oneof of this message. */ private void verifyOneofContainingType(OneofDescriptor oneof) { if (oneof.getContainingType() != type) { - throw new IllegalArgumentException( - "OneofDescriptor does not match message type."); + throw new IllegalArgumentException("OneofDescriptor does not match message type."); } } /** Verifies that the value is EnumValueDescriptor and matches Enum Type. */ - private void ensureSingularEnumValueDescriptor( - FieldDescriptor field, Object value) { + private void ensureSingularEnumValueDescriptor(FieldDescriptor field, Object value) { checkNotNull(value); if (!(value instanceof EnumValueDescriptor)) { throw new IllegalArgumentException( - "DynamicMessage should use EnumValueDescriptor to set Enum Value."); + "DynamicMessage should use EnumValueDescriptor to set Enum Value."); } // TODO(xiaofeng): Re-enable this check after Orgstore is fixed to not // set incorrect EnumValueDescriptors. @@ -647,14 +641,13 @@ private void ensureSingularEnumValueDescriptor( } /** Verifies the value for an enum field. */ - private void ensureEnumValueDescriptor( - FieldDescriptor field, Object value) { + private void ensureEnumValueDescriptor(FieldDescriptor field, Object value) { if (field.isRepeated()) { for (Object item : (List) value) { ensureSingularEnumValueDescriptor(field, item); } } else { - ensureSingularEnumValueDescriptor(field, value); + ensureSingularEnumValueDescriptor(field, value); } } @@ -668,14 +661,14 @@ private void ensureIsMutable() { public com.google.protobuf.Message.Builder getFieldBuilder(FieldDescriptor field) { // TODO(xiangl): need implementation for dynamic message throw new UnsupportedOperationException( - "getFieldBuilder() called on a dynamic message type."); + "getFieldBuilder() called on a dynamic message type."); } @Override - public com.google.protobuf.Message.Builder getRepeatedFieldBuilder(FieldDescriptor field, - int index) { + public com.google.protobuf.Message.Builder getRepeatedFieldBuilder( + FieldDescriptor field, int index) { throw new UnsupportedOperationException( - "getRepeatedFieldBuilder() called on a dynamic message type."); + "getRepeatedFieldBuilder() called on a dynamic message type."); } } } diff --git a/java/core/src/main/java/com/google/protobuf/ExperimentalApi.java b/java/core/src/main/java/com/google/protobuf/ExperimentalApi.java index 3cd4c88492862..d55b278c3f2c7 100644 --- a/java/core/src/main/java/com/google/protobuf/ExperimentalApi.java +++ b/java/core/src/main/java/com/google/protobuf/ExperimentalApi.java @@ -41,26 +41,25 @@ * backward-compatibility. * *

Usage guidelines: + * *

    - *
  1. This annotation is used only on public API. Internal interfaces should not use it.
  2. - *
  3. This annotation should only be added to new APIs. Adding it to an existing API is - * considered API-breaking.
  4. - *
  5. Removing this annotation from an API gives it stable status.
  6. + *
  7. This annotation is used only on public API. Internal interfaces should not use it. + *
  8. This annotation should only be added to new APIs. Adding it to an existing API is + * considered API-breaking. + *
  9. Removing this annotation from an API gives it stable status. *
*/ @Retention(RetentionPolicy.SOURCE) @Target({ - ElementType.ANNOTATION_TYPE, - ElementType.CONSTRUCTOR, - ElementType.FIELD, - ElementType.METHOD, - ElementType.PACKAGE, - ElementType.TYPE}) + ElementType.ANNOTATION_TYPE, + ElementType.CONSTRUCTOR, + ElementType.FIELD, + ElementType.METHOD, + ElementType.PACKAGE, + ElementType.TYPE +}) @Documented public @interface ExperimentalApi { - /** - * Context information such as links to discussion thread, tracking issue etc. - */ + /** Context information such as links to discussion thread, tracking issue etc. */ String value() default ""; } - diff --git a/java/core/src/main/java/com/google/protobuf/Extension.java b/java/core/src/main/java/com/google/protobuf/Extension.java index 5df12e6422209..30c828e57bdb2 100644 --- a/java/core/src/main/java/com/google/protobuf/Extension.java +++ b/java/core/src/main/java/com/google/protobuf/Extension.java @@ -30,6 +30,7 @@ package com.google.protobuf; +// TODO(chrisn): Change ContainingType to extend Message /** * Interface that generated extensions implement. * @@ -37,6 +38,11 @@ */ public abstract class Extension extends ExtensionLite { + // TODO(chrisn): Add package-private constructor. + + /** {@inheritDoc} Overridden to return {@link Message} instead of {@link MessageLite}. */ + @Override + public abstract Message getMessageDefaultInstance(); /** Returns the descriptor of the extension. */ public abstract Descriptors.FieldDescriptor getDescriptor(); @@ -49,9 +55,7 @@ final boolean isLite() { // All the methods below are extension implementation details. - /** - * The API type that the extension is used for. - */ + /** The API type that the extension is used for. */ protected enum ExtensionType { IMMUTABLE, MUTABLE, @@ -60,24 +64,25 @@ protected enum ExtensionType { protected abstract ExtensionType getExtensionType(); - /** - * Type of a message extension. - */ + /** Type of a message extension. */ public enum MessageType { PROTO1, PROTO2, } /** - * If the extension is a message extension (i.e., getLiteType() == MESSAGE), - * returns the type of the message, otherwise undefined. + * If the extension is a message extension (i.e., getLiteType() == MESSAGE), returns the type of + * the message, otherwise undefined. */ public MessageType getMessageType() { return MessageType.PROTO2; } protected abstract Object fromReflectionType(Object value); + protected abstract Object singularFromReflectionType(Object value); + protected abstract Object toReflectionType(Object value); + protected abstract Object singularToReflectionType(Object value); } diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionLite.java b/java/core/src/main/java/com/google/protobuf/ExtensionLite.java index f8f5bd2c4fd0c..0fb5f49e983c0 100644 --- a/java/core/src/main/java/com/google/protobuf/ExtensionLite.java +++ b/java/core/src/main/java/com/google/protobuf/ExtensionLite.java @@ -32,9 +32,9 @@ /** * Lite interface that generated extensions implement. - *

- * Methods are for use by generated code only. You can hold a reference to - * extensions using this type name. + * + *

Methods are for use by generated code only. You can hold a reference to extensions using this + * type name. */ public abstract class ExtensionLite { @@ -50,12 +50,9 @@ public abstract class ExtensionLite { /** Returns the default value of the extension field. */ public abstract Type getDefaultValue(); - /** - * Returns the default instance of the extension field, if it's a message - * extension. - */ + /** Returns the default instance of the extension field, if it's a message extension. */ public abstract MessageLite getMessageDefaultInstance(); - + /** Returns whether or not this extension is a Lite Extension. */ boolean isLite() { return true; diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java b/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java index a22a74a03caee..aeeaee53e2112 100644 --- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java +++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java @@ -40,11 +40,10 @@ import java.util.Set; /** - * A table of known extensions, searchable by name or field number. When - * parsing a protocol message that might have extensions, you must provide - * an {@code ExtensionRegistry} in which you have registered any extensions - * that you want to be able to parse. Otherwise, those extensions will just - * be treated like unknown fields. + * A table of known extensions, searchable by name or field number. When parsing a protocol message + * that might have extensions, you must provide an {@code ExtensionRegistry} in which you have + * registered any extensions that you want to be able to parse. Otherwise, those extensions will + * just be treated like unknown fields. * *

For example, if you had the {@code .proto} file: * @@ -70,25 +69,22 @@ * *

Background: * - *

You might wonder why this is necessary. Two alternatives might come to - * mind. First, you might imagine a system where generated extensions are - * automatically registered when their containing classes are loaded. This - * is a popular technique, but is bad design; among other things, it creates a - * situation where behavior can change depending on what classes happen to be - * loaded. It also introduces a security vulnerability, because an - * unprivileged class could cause its code to be called unexpectedly from a - * privileged class by registering itself as an extension of the right type. + *

You might wonder why this is necessary. Two alternatives might come to mind. First, you might + * imagine a system where generated extensions are automatically registered when their containing + * classes are loaded. This is a popular technique, but is bad design; among other things, it + * creates a situation where behavior can change depending on what classes happen to be loaded. It + * also introduces a security vulnerability, because an unprivileged class could cause its code to + * be called unexpectedly from a privileged class by registering itself as an extension of the right + * type. * - *

Another option you might consider is lazy parsing: do not parse an - * extension until it is first requested, at which point the caller must - * provide a type to use. This introduces a different set of problems. First, - * it would require a mutex lock any time an extension was accessed, which - * would be slow. Second, corrupt data would not be detected until first - * access, at which point it would be much harder to deal with it. Third, it - * could violate the expectation that message objects are immutable, since the - * type provided could be any arbitrary message class. An unprivileged user - * could take advantage of this to inject a mutable object into a message - * belonging to privileged code and create mischief. + *

Another option you might consider is lazy parsing: do not parse an extension until it is first + * requested, at which point the caller must provide a type to use. This introduces a different set + * of problems. First, it would require a mutex lock any time an extension was accessed, which would + * be slow. Second, corrupt data would not be detected until first access, at which point it would + * be much harder to deal with it. Third, it could violate the expectation that message objects are + * immutable, since the type provided could be any arbitrary message class. An unprivileged user + * could take advantage of this to inject a mutable object into a message belonging to privileged + * code and create mischief. * * @author kenton@google.com Kenton Varda */ @@ -116,8 +112,8 @@ public static final class ExtensionInfo { public final FieldDescriptor descriptor; /** - * A default instance of the extension's type, if it has a message type. - * Otherwise, {@code null}. + * A default instance of the extension's type, if it has a message type. Otherwise, {@code + * null}. */ public final Message defaultInstance; @@ -125,48 +121,41 @@ private ExtensionInfo(final FieldDescriptor descriptor) { this.descriptor = descriptor; defaultInstance = null; } - private ExtensionInfo(final FieldDescriptor descriptor, - final Message defaultInstance) { + + private ExtensionInfo(final FieldDescriptor descriptor, final Message defaultInstance) { this.descriptor = descriptor; this.defaultInstance = defaultInstance; } } - /** - * Deprecated. Use {@link #findImmutableExtensionByName(String)} instead. - */ + /** Deprecated. Use {@link #findImmutableExtensionByName(String)} instead. */ + @Deprecated public ExtensionInfo findExtensionByName(final String fullName) { return findImmutableExtensionByName(fullName); } /** - * Find an extension for immutable APIs by fully-qualified field name, - * in the proto namespace. i.e. {@code result.descriptor.fullName()} will - * match {@code fullName} if a match is found. + * Find an extension for immutable APIs by fully-qualified field name, in the proto namespace. + * i.e. {@code result.descriptor.fullName()} will match {@code fullName} if a match is found. * - * @return Information about the extension if found, or {@code null} - * otherwise. + * @return Information about the extension if found, or {@code null} otherwise. */ public ExtensionInfo findImmutableExtensionByName(final String fullName) { return immutableExtensionsByName.get(fullName); } /** - * Find an extension for mutable APIs by fully-qualified field name, - * in the proto namespace. i.e. {@code result.descriptor.fullName()} will - * match {@code fullName} if a match is found. + * Find an extension for mutable APIs by fully-qualified field name, in the proto namespace. i.e. + * {@code result.descriptor.fullName()} will match {@code fullName} if a match is found. * - * @return Information about the extension if found, or {@code null} - * otherwise. + * @return Information about the extension if found, or {@code null} otherwise. */ public ExtensionInfo findMutableExtensionByName(final String fullName) { return mutableExtensionsByName.get(fullName); } - /** - * Deprecated. Use {@link #findImmutableExtensionByNumber( - * Descriptors.Descriptor, int)} - */ + /** Deprecated. Use {@link #findImmutableExtensionByNumber( Descriptors.Descriptor, int)} */ + @Deprecated public ExtensionInfo findExtensionByNumber( final Descriptor containingType, final int fieldNumber) { return findImmutableExtensionByNumber(containingType, fieldNumber); @@ -175,34 +164,28 @@ public ExtensionInfo findExtensionByNumber( /** * Find an extension by containing type and field number for immutable APIs. * - * @return Information about the extension if found, or {@code null} - * otherwise. + * @return Information about the extension if found, or {@code null} otherwise. */ public ExtensionInfo findImmutableExtensionByNumber( final Descriptor containingType, final int fieldNumber) { - return immutableExtensionsByNumber.get( - new DescriptorIntPair(containingType, fieldNumber)); + return immutableExtensionsByNumber.get(new DescriptorIntPair(containingType, fieldNumber)); } /** * Find an extension by containing type and field number for mutable APIs. * - * @return Information about the extension if found, or {@code null} - * otherwise. + * @return Information about the extension if found, or {@code null} otherwise. */ public ExtensionInfo findMutableExtensionByNumber( final Descriptor containingType, final int fieldNumber) { - return mutableExtensionsByNumber.get( - new DescriptorIntPair(containingType, fieldNumber)); + return mutableExtensionsByNumber.get(new DescriptorIntPair(containingType, fieldNumber)); } /** - * Find all extensions for mutable APIs by fully-qualified name of - * extended class. Note that this method is more computationally expensive - * than getting a single extension by name or number. + * Find all extensions for mutable APIs by fully-qualified name of extended class. Note that this + * method is more computationally expensive than getting a single extension by name or number. * - * @return Information about the extensions found, or {@code null} if there - * are none. + * @return Information about the extensions found, or {@code null} if there are none. */ public Set getAllMutableExtensionsByExtendedType(final String fullName) { HashSet extensions = new HashSet(); @@ -215,12 +198,11 @@ public Set getAllMutableExtensionsByExtendedType(final String ful } /** - * Find all extensions for immutable APIs by fully-qualified name of - * extended class. Note that this method is more computationally expensive - * than getting a single extension by name or number. + * Find all extensions for immutable APIs by fully-qualified name of extended class. Note that + * this method is more computationally expensive than getting a single extension by name or + * number. * - * @return Information about the extensions found, or {@code null} if there - * are none. + * @return Information about the extensions found, or {@code null} if there are none. */ public Set getAllImmutableExtensionsByExtendedType(final String fullName) { HashSet extensions = new HashSet(); @@ -234,8 +216,8 @@ public Set getAllImmutableExtensionsByExtendedType(final String f /** Add an extension from a generated file to the registry. */ public void add(final Extension extension) { - if (extension.getExtensionType() != Extension.ExtensionType.IMMUTABLE && - extension.getExtensionType() != Extension.ExtensionType.MUTABLE) { + if (extension.getExtensionType() != Extension.ExtensionType.IMMUTABLE + && extension.getExtensionType() != Extension.ExtensionType.MUTABLE) { // do not support other extension types. ignore return; } @@ -248,15 +230,14 @@ public void add(final GeneratedMessage.GeneratedExtension extension) { } static ExtensionInfo newExtensionInfo(final Extension extension) { - if (extension.getDescriptor().getJavaType() == - FieldDescriptor.JavaType.MESSAGE) { + if (extension.getDescriptor().getJavaType() == FieldDescriptor.JavaType.MESSAGE) { if (extension.getMessageDefaultInstance() == null) { throw new IllegalStateException( - "Registered message-type extension had null default instance: " + - extension.getDescriptor().getFullName()); + "Registered message-type extension had null default instance: " + + extension.getDescriptor().getFullName()); } - return new ExtensionInfo(extension.getDescriptor(), - (Message) extension.getMessageDefaultInstance()); + return new ExtensionInfo( + extension.getDescriptor(), (Message) extension.getMessageDefaultInstance()); } else { return new ExtensionInfo(extension.getDescriptor(), null); } @@ -266,8 +247,8 @@ static ExtensionInfo newExtensionInfo(final Extension extension) { public void add(final FieldDescriptor type) { if (type.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { throw new IllegalArgumentException( - "ExtensionRegistry.add() must be provided a default instance when " + - "adding an embedded message extension."); + "ExtensionRegistry.add() must be provided a default instance when " + + "adding an embedded message extension."); } ExtensionInfo info = new ExtensionInfo(type, null); add(info, Extension.ExtensionType.IMMUTABLE); @@ -278,11 +259,9 @@ public void add(final FieldDescriptor type) { public void add(final FieldDescriptor type, final Message defaultInstance) { if (type.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { throw new IllegalArgumentException( - "ExtensionRegistry.add() provided a default instance for a " + - "non-message extension."); + "ExtensionRegistry.add() provided a default instance for a non-message extension."); } - add(new ExtensionInfo(type, defaultInstance), - Extension.ExtensionType.IMMUTABLE); + add(new ExtensionInfo(type, defaultInstance), Extension.ExtensionType.IMMUTABLE); } // ================================================================= @@ -291,22 +270,17 @@ public void add(final FieldDescriptor type, final Message defaultInstance) { private ExtensionRegistry() { this.immutableExtensionsByName = new HashMap(); this.mutableExtensionsByName = new HashMap(); - this.immutableExtensionsByNumber = - new HashMap(); - this.mutableExtensionsByNumber = - new HashMap(); + this.immutableExtensionsByNumber = new HashMap(); + this.mutableExtensionsByNumber = new HashMap(); } private ExtensionRegistry(ExtensionRegistry other) { super(other); - this.immutableExtensionsByName = - Collections.unmodifiableMap(other.immutableExtensionsByName); - this.mutableExtensionsByName = - Collections.unmodifiableMap(other.mutableExtensionsByName); + this.immutableExtensionsByName = Collections.unmodifiableMap(other.immutableExtensionsByName); + this.mutableExtensionsByName = Collections.unmodifiableMap(other.mutableExtensionsByName); this.immutableExtensionsByNumber = Collections.unmodifiableMap(other.immutableExtensionsByNumber); - this.mutableExtensionsByNumber = - Collections.unmodifiableMap(other.mutableExtensionsByNumber); + this.mutableExtensionsByNumber = Collections.unmodifiableMap(other.mutableExtensionsByNumber); } private final Map immutableExtensionsByName; @@ -316,24 +290,19 @@ private ExtensionRegistry(ExtensionRegistry other) { ExtensionRegistry(boolean empty) { super(EMPTY_REGISTRY_LITE); - this.immutableExtensionsByName = - Collections.emptyMap(); - this.mutableExtensionsByName = - Collections.emptyMap(); - this.immutableExtensionsByNumber = - Collections.emptyMap(); - this.mutableExtensionsByNumber = - Collections.emptyMap(); + this.immutableExtensionsByName = Collections.emptyMap(); + this.mutableExtensionsByName = Collections.emptyMap(); + this.immutableExtensionsByNumber = Collections.emptyMap(); + this.mutableExtensionsByNumber = Collections.emptyMap(); } + static final ExtensionRegistry EMPTY_REGISTRY = new ExtensionRegistry(true); - private void add( - final ExtensionInfo extension, - final Extension.ExtensionType extensionType) { + private void add(final ExtensionInfo extension, final Extension.ExtensionType extensionType) { if (!extension.descriptor.isExtension()) { throw new IllegalArgumentException( - "ExtensionRegistry.add() was given a FieldDescriptor for a regular " + - "(non-extension) field."); + "ExtensionRegistry.add() was given a FieldDescriptor for a regular " + + "(non-extension) field."); } Map extensionsByName; @@ -354,15 +323,15 @@ private void add( extensionsByName.put(extension.descriptor.getFullName(), extension); extensionsByNumber.put( - new DescriptorIntPair(extension.descriptor.getContainingType(), - extension.descriptor.getNumber()), - extension); + new DescriptorIntPair( + extension.descriptor.getContainingType(), extension.descriptor.getNumber()), + extension); final FieldDescriptor field = extension.descriptor; - if (field.getContainingType().getOptions().getMessageSetWireFormat() && - field.getType() == FieldDescriptor.Type.MESSAGE && - field.isOptional() && - field.getExtensionScope() == field.getMessageType()) { + if (field.getContainingType().getOptions().getMessageSetWireFormat() + && field.getType() == FieldDescriptor.Type.MESSAGE + && field.isOptional() + && field.getExtensionScope() == field.getMessageType()) { // This is an extension of a MessageSet type defined within the extension // type's own scope. For backwards-compatibility, allow it to be looked // up by type name. @@ -384,12 +353,13 @@ private static final class DescriptorIntPair { public int hashCode() { return descriptor.hashCode() * ((1 << 16) - 1) + number; } + @Override public boolean equals(final Object obj) { if (!(obj instanceof DescriptorIntPair)) { return false; } - final DescriptorIntPair other = (DescriptorIntPair)obj; + final DescriptorIntPair other = (DescriptorIntPair) obj; return descriptor == other.descriptor && number == other.number; } } diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java index 89f7ab9b33594..0a63fad187e8a 100644 --- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java +++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java @@ -35,19 +35,17 @@ /** * A factory object to create instances of {@link ExtensionRegistryLite}. * - *

- * This factory detects (via reflection) if the full (non-Lite) protocol buffer libraries - * are available, and if so, the instances returned are actually {@link ExtensionRegistry}. + *

This factory detects (via reflection) if the full (non-Lite) protocol buffer libraries are + * available, and if so, the instances returned are actually {@link ExtensionRegistry}. */ final class ExtensionRegistryFactory { static final String FULL_REGISTRY_CLASS_NAME = "com.google.protobuf.ExtensionRegistry"; /* Visible for Testing - @Nullable */ + @Nullable */ static final Class EXTENSION_REGISTRY_CLASS = reflectExtensionRegistry(); - /* @Nullable */ static Class reflectExtensionRegistry() { try { return Class.forName(FULL_REGISTRY_CLASS_NAME); @@ -60,26 +58,16 @@ static Class reflectExtensionRegistry() { /** Construct a new, empty instance. */ public static ExtensionRegistryLite create() { - if (EXTENSION_REGISTRY_CLASS != null) { - try { - return invokeSubclassFactory("newInstance"); - } catch (Exception e) { - // return a Lite registry. - } - } - return new ExtensionRegistryLite(); + ExtensionRegistryLite result = invokeSubclassFactory("newInstance"); + + return result != null ? result : new ExtensionRegistryLite(); } /** Get the unmodifiable singleton empty instance. */ public static ExtensionRegistryLite createEmpty() { - if (EXTENSION_REGISTRY_CLASS != null) { - try { - return invokeSubclassFactory("getEmptyRegistry"); - } catch (Exception e) { - // return a Lite registry. - } - } - return EMPTY_REGISTRY_LITE; + ExtensionRegistryLite result = invokeSubclassFactory("getEmptyRegistry"); + + return result != null ? result : EMPTY_REGISTRY_LITE; } @@ -88,9 +76,16 @@ static boolean isFullRegistry(ExtensionRegistryLite registry) { && EXTENSION_REGISTRY_CLASS.isAssignableFrom(registry.getClass()); } - private static final ExtensionRegistryLite invokeSubclassFactory(String methodName) - throws Exception { - return (ExtensionRegistryLite) EXTENSION_REGISTRY_CLASS - .getDeclaredMethod(methodName).invoke(null); + private static final ExtensionRegistryLite invokeSubclassFactory(String methodName) { + if (EXTENSION_REGISTRY_CLASS == null) { + return null; + } + + try { + return (ExtensionRegistryLite) + EXTENSION_REGISTRY_CLASS.getDeclaredMethod(methodName).invoke(null); + } catch (Exception e) { + return null; + } } } diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java index f3d48d3af34e7..caa58e1ada67e 100644 --- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java +++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java @@ -36,22 +36,20 @@ /** * Equivalent to {@link ExtensionRegistry} but supports only "lite" types. - *

- * If all of your types are lite types, then you only need to use - * {@code ExtensionRegistryLite}. Similarly, if all your types are regular - * types, then you only need {@link ExtensionRegistry}. Typically it does not - * make sense to mix the two, since if you have any regular types in your - * program, you then require the full runtime and lose all the benefits of - * the lite runtime, so you might as well make all your types be regular types. - * However, in some cases (e.g. when depending on multiple third-party libraries - * where one uses lite types and one uses regular), you may find yourself - * wanting to mix the two. In this case things get more complicated. - *

- * There are three factors to consider: Whether the type being extended is - * lite, whether the embedded type (in the case of a message-typed extension) - * is lite, and whether the extension itself is lite. Since all three are - * declared in different files, they could all be different. Here are all - * the combinations and which type of registry to use: + * + *

If all of your types are lite types, then you only need to use {@code ExtensionRegistryLite}. + * Similarly, if all your types are regular types, then you only need {@link ExtensionRegistry}. + * Typically it does not make sense to mix the two, since if you have any regular types in your + * program, you then require the full runtime and lose all the benefits of the lite runtime, so you + * might as well make all your types be regular types. However, in some cases (e.g. when depending + * on multiple third-party libraries where one uses lite types and one uses regular), you may find + * yourself wanting to mix the two. In this case things get more complicated. + * + *

There are three factors to consider: Whether the type being extended is lite, whether the + * embedded type (in the case of a message-typed extension) is lite, and whether the extension + * itself is lite. Since all three are declared in different files, they could all be different. + * Here are all the combinations and which type of registry to use: + * *

  *   Extended type     Inner type    Extension         Use registry
  *   =======================================================================
@@ -60,13 +58,12 @@
  *   regular           regular       regular           ExtensionRegistry
  *   all other combinations                            not supported
  * 
- *

- * Note that just as regular types are not allowed to contain lite-type fields, - * they are also not allowed to contain lite-type extensions. This is because - * regular types must be fully accessible via reflection, which in turn means - * that all the inner messages must also support reflection. On the other hand, - * since regular types implement the entire lite interface, there is no problem - * with embedding regular types inside lite types. + * + *

Note that just as regular types are not allowed to contain lite-type fields, they are also not + * allowed to contain lite-type extensions. This is because regular types must be fully accessible + * via reflection, which in turn means that all the inner messages must also support reflection. On + * the other hand, since regular types implement the entire lite interface, there is no problem with + * embedding regular types inside lite types. * * @author kenton@google.com Kenton Varda */ @@ -79,22 +76,26 @@ public class ExtensionRegistryLite { // applications. Need to support this feature on smaller granularity. private static volatile boolean eagerlyParseMessageSets = false; + // short circuit the ExtensionRegistryFactory via assumevalues trickery + @SuppressWarnings("JavaOptionalSuggestions") + private static boolean doFullRuntimeInheritanceCheck = true; + // Visible for testing. static final String EXTENSION_CLASS_NAME = "com.google.protobuf.Extension"; - /* @Nullable */ - static Class resolveExtensionClass() { - try { - return Class.forName(EXTENSION_CLASS_NAME); - } catch (ClassNotFoundException e) { - // See comment in ExtensionRegistryFactory on the potential expense of this. - return null; + private static class ExtensionClassHolder { + static final Class INSTANCE = resolveExtensionClass(); + + static Class resolveExtensionClass() { + try { + return Class.forName(EXTENSION_CLASS_NAME); + } catch (ClassNotFoundException e) { + // See comment in ExtensionRegistryFactory on the potential expense of this. + return null; + } } } - /* @Nullable */ - private static final Class extensionClass = resolveExtensionClass(); - public static boolean isEagerlyParseMessageSets() { return eagerlyParseMessageSets; } @@ -110,15 +111,32 @@ public static void setEagerlyParseMessageSets(boolean isEagerlyParse) { * available. */ public static ExtensionRegistryLite newInstance() { - return ExtensionRegistryFactory.create(); + return doFullRuntimeInheritanceCheck + ? ExtensionRegistryFactory.create() + : new ExtensionRegistryLite(); } + private static volatile ExtensionRegistryLite emptyRegistry; + /** - * Get the unmodifiable singleton empty instance of either ExtensionRegistryLite or - * {@code ExtensionRegistry} (if the full (non-Lite) proto libraries are available). + * Get the unmodifiable singleton empty instance of either ExtensionRegistryLite or {@code + * ExtensionRegistry} (if the full (non-Lite) proto libraries are available). */ public static ExtensionRegistryLite getEmptyRegistry() { - return ExtensionRegistryFactory.createEmpty(); + ExtensionRegistryLite result = emptyRegistry; + if (result == null) { + synchronized (ExtensionRegistryLite.class) { + result = emptyRegistry; + if (result == null) { + result = + emptyRegistry = + doFullRuntimeInheritanceCheck + ? ExtensionRegistryFactory.createEmpty() + : EMPTY_REGISTRY_LITE; + } + } + } + return result; } @@ -130,39 +148,34 @@ public ExtensionRegistryLite getUnmodifiable() { /** * Find an extension by containing type and field number. * - * @return Information about the extension if found, or {@code null} - * otherwise. + * @return Information about the extension if found, or {@code null} otherwise. */ @SuppressWarnings("unchecked") public - GeneratedMessageLite.GeneratedExtension - findLiteExtensionByNumber( - final ContainingType containingTypeDefaultInstance, - final int fieldNumber) { + GeneratedMessageLite.GeneratedExtension findLiteExtensionByNumber( + final ContainingType containingTypeDefaultInstance, final int fieldNumber) { return (GeneratedMessageLite.GeneratedExtension) - extensionsByNumber.get( - new ObjectIntPair(containingTypeDefaultInstance, fieldNumber)); + extensionsByNumber.get(new ObjectIntPair(containingTypeDefaultInstance, fieldNumber)); } /** Add an extension from a lite generated file to the registry. */ - public final void add( - final GeneratedMessageLite.GeneratedExtension extension) { + public final void add(final GeneratedMessageLite.GeneratedExtension extension) { extensionsByNumber.put( - new ObjectIntPair(extension.getContainingTypeDefaultInstance(), - extension.getNumber()), - extension); + new ObjectIntPair(extension.getContainingTypeDefaultInstance(), extension.getNumber()), + extension); } /** - * Add an extension from a lite generated file to the registry only if it is - * a non-lite extension i.e. {@link GeneratedMessageLite.GeneratedExtension}. */ + * Add an extension from a lite generated file to the registry only if it is a non-lite extension + * i.e. {@link GeneratedMessageLite.GeneratedExtension}. + */ public final void add(ExtensionLite extension) { if (GeneratedMessageLite.GeneratedExtension.class.isAssignableFrom(extension.getClass())) { add((GeneratedMessageLite.GeneratedExtension) extension); } - if (ExtensionRegistryFactory.isFullRegistry(this)) { + if (doFullRuntimeInheritanceCheck && ExtensionRegistryFactory.isFullRegistry(this)) { try { - this.getClass().getMethod("add", extensionClass).invoke(this, extension); + this.getClass().getMethod("add", ExtensionClassHolder.INSTANCE).invoke(this, extension); } catch (Exception e) { throw new IllegalArgumentException( String.format("Could not invoke ExtensionRegistry#add for %s", extension), e); @@ -178,23 +191,20 @@ public final void add(ExtensionLite extension) { ExtensionRegistryLite() { this.extensionsByNumber = - new HashMap>(); + new HashMap>(); } - static final ExtensionRegistryLite EMPTY_REGISTRY_LITE = - new ExtensionRegistryLite(true); + + static final ExtensionRegistryLite EMPTY_REGISTRY_LITE = new ExtensionRegistryLite(true); ExtensionRegistryLite(ExtensionRegistryLite other) { if (other == EMPTY_REGISTRY_LITE) { this.extensionsByNumber = Collections.emptyMap(); } else { - this.extensionsByNumber = - Collections.unmodifiableMap(other.extensionsByNumber); + this.extensionsByNumber = Collections.unmodifiableMap(other.extensionsByNumber); } } - private final Map> + private final Map> extensionsByNumber; ExtensionRegistryLite(boolean empty) { @@ -215,12 +225,13 @@ private static final class ObjectIntPair { public int hashCode() { return System.identityHashCode(object) * ((1 << 16) - 1) + number; } + @Override public boolean equals(final Object obj) { if (!(obj instanceof ObjectIntPair)) { return false; } - final ObjectIntPair other = (ObjectIntPair)obj; + final ObjectIntPair other = (ObjectIntPair) obj; return object == other.object && number == other.number; } } diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionSchema.java b/java/core/src/main/java/com/google/protobuf/ExtensionSchema.java new file mode 100644 index 0000000000000..2eae22d26a078 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/ExtensionSchema.java @@ -0,0 +1,98 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; +import java.util.Map; + +abstract class ExtensionSchema> { + + /** Returns true for messages that support extensions. */ + abstract boolean hasExtensions(MessageLite prototype); + + /** Returns the extension {@link FieldSet} for the message instance. */ + abstract FieldSet getExtensions(Object message); + + /** Replaces the extension {@link FieldSet} for the message instance. */ + abstract void setExtensions(Object message, FieldSet extensions); + + /** Returns the extension {@link FieldSet} and ensures it's mutable. */ + abstract FieldSet getMutableExtensions(Object message); + + /** Marks the extension {@link FieldSet} as immutable. */ + abstract void makeImmutable(Object message); + + /** + * Parses an extension. Returns the passed-in unknownFields parameter if no unknown enum value is + * found or a modified unknownFields (a new instance if the passed-in unknownFields is null) + * containing unknown enum values found while parsing. + * + * @param The type used to store unknown fields. It's either UnknownFieldSet in full runtime + * or UnknownFieldSetLite in lite runtime. + */ + abstract UB parseExtension( + Reader reader, + Object extension, + ExtensionRegistryLite extensionRegistry, + FieldSet extensions, + UB unknownFields, + UnknownFieldSchema unknownFieldSchema) + throws IOException; + + /** Gets the field number of an extension entry. */ + abstract int extensionNumber(Map.Entry extension); + + /** Serializes one extension entry. */ + abstract void serializeExtension(Writer writer, Map.Entry extension) throws IOException; + + /** Finds an extension by field number. */ + abstract Object findExtensionByNumber( + ExtensionRegistryLite extensionRegistry, MessageLite defaultInstance, int number); + + /** Parses a length-prefixed MessageSet item from the reader. */ + abstract void parseLengthPrefixedMessageSetItem( + Reader reader, + Object extension, + ExtensionRegistryLite extensionRegistry, + FieldSet extensions) + throws IOException; + + /** + * Parses the entire content of a {@link ByteString} as one MessageSet item. Unlike {@link + * #parseLengthPrefixedMessageSetItem}, there isn't a length-prefix. + */ + abstract void parseMessageSetItem( + ByteString data, + Object extension, + ExtensionRegistryLite extensionRegistry, + FieldSet extensions) + throws IOException; +} diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionSchemaFull.java b/java/core/src/main/java/com/google/protobuf/ExtensionSchemaFull.java new file mode 100644 index 0000000000000..90558518b9961 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/ExtensionSchemaFull.java @@ -0,0 +1,547 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.Descriptors.EnumValueDescriptor; +import com.google.protobuf.Descriptors.FieldDescriptor; +import java.io.IOException; +import java.lang.reflect.Field; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@SuppressWarnings("unchecked") +final class ExtensionSchemaFull extends ExtensionSchema { + + private static final long EXTENSION_FIELD_OFFSET = getExtensionsFieldOffset(); + + private static long getExtensionsFieldOffset() { + try { + Field field = GeneratedMessageV3.ExtendableMessage.class.getDeclaredField("extensions"); + return UnsafeUtil.objectFieldOffset(field); + } catch (Throwable e) { + throw new IllegalStateException("Unable to lookup extension field offset"); + } + } + + @Override + boolean hasExtensions(MessageLite prototype) { + return prototype instanceof GeneratedMessageV3.ExtendableMessage; + } + + @Override + public FieldSet getExtensions(Object message) { + return (FieldSet) UnsafeUtil.getObject(message, EXTENSION_FIELD_OFFSET); + } + + @Override + void setExtensions(Object message, FieldSet extensions) { + UnsafeUtil.putObject(message, EXTENSION_FIELD_OFFSET, extensions); + } + + @Override + FieldSet getMutableExtensions(Object message) { + FieldSet extensions = getExtensions(message); + if (extensions.isImmutable()) { + extensions = extensions.clone(); + setExtensions(message, extensions); + } + return extensions; + } + + @Override + void makeImmutable(Object message) { + getExtensions(message).makeImmutable(); + } + + @Override + UB parseExtension( + Reader reader, + Object extensionObject, + ExtensionRegistryLite extensionRegistry, + FieldSet extensions, + UB unknownFields, + UnknownFieldSchema unknownFieldSchema) + throws IOException { + ExtensionRegistry.ExtensionInfo extension = (ExtensionRegistry.ExtensionInfo) extensionObject; + int fieldNumber = extension.descriptor.getNumber(); + + if (extension.descriptor.isRepeated() && extension.descriptor.isPacked()) { + Object value = null; + switch (extension.descriptor.getLiteType()) { + case DOUBLE: + { + List list = new ArrayList(); + reader.readDoubleList(list); + value = list; + break; + } + case FLOAT: + { + List list = new ArrayList(); + reader.readFloatList(list); + value = list; + break; + } + case INT64: + { + List list = new ArrayList(); + reader.readInt64List(list); + value = list; + break; + } + case UINT64: + { + List list = new ArrayList(); + reader.readUInt64List(list); + value = list; + break; + } + case INT32: + { + List list = new ArrayList(); + reader.readInt32List(list); + value = list; + break; + } + case FIXED64: + { + List list = new ArrayList(); + reader.readFixed64List(list); + value = list; + break; + } + case FIXED32: + { + List list = new ArrayList(); + reader.readFixed32List(list); + value = list; + break; + } + case BOOL: + { + List list = new ArrayList(); + reader.readBoolList(list); + value = list; + break; + } + case UINT32: + { + List list = new ArrayList(); + reader.readUInt32List(list); + value = list; + break; + } + case SFIXED32: + { + List list = new ArrayList(); + reader.readSFixed32List(list); + value = list; + break; + } + case SFIXED64: + { + List list = new ArrayList(); + reader.readSFixed64List(list); + value = list; + break; + } + case SINT32: + { + List list = new ArrayList(); + reader.readSInt32List(list); + value = list; + break; + } + case SINT64: + { + List list = new ArrayList(); + reader.readSInt64List(list); + value = list; + break; + } + case ENUM: + { + List list = new ArrayList(); + reader.readEnumList(list); + List enumList = new ArrayList(); + for (int number : list) { + EnumValueDescriptor enumDescriptor = + extension.descriptor.getEnumType().findValueByNumber(number); + if (enumDescriptor != null) { + enumList.add(enumDescriptor); + } else { + unknownFields = + SchemaUtil.storeUnknownEnum( + fieldNumber, number, unknownFields, unknownFieldSchema); + } + } + value = enumList; + break; + } + default: + throw new IllegalStateException( + "Type cannot be packed: " + extension.descriptor.getLiteType()); + } + extensions.setField(extension.descriptor, value); + } else { + Object value = null; + // Enum is a special case because unknown enum values will be put into UnknownFieldSetLite. + if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) { + int number = reader.readInt32(); + Object enumValue = extension.descriptor.getEnumType().findValueByNumber(number); + if (enumValue == null) { + return SchemaUtil.storeUnknownEnum( + fieldNumber, number, unknownFields, unknownFieldSchema); + } + value = enumValue; + } else { + switch (extension.descriptor.getLiteType()) { + case DOUBLE: + value = reader.readDouble(); + break; + case FLOAT: + value = reader.readFloat(); + break; + case INT64: + value = reader.readInt64(); + break; + case UINT64: + value = reader.readUInt64(); + break; + case INT32: + value = reader.readInt32(); + break; + case FIXED64: + value = reader.readFixed64(); + break; + case FIXED32: + value = reader.readFixed32(); + break; + case BOOL: + value = reader.readBool(); + break; + case BYTES: + value = reader.readBytes(); + break; + case UINT32: + value = reader.readUInt32(); + break; + case SFIXED32: + value = reader.readSFixed32(); + break; + case SFIXED64: + value = reader.readSFixed64(); + break; + case SINT32: + value = reader.readSInt32(); + break; + case SINT64: + value = reader.readSInt64(); + break; + + case STRING: + value = reader.readString(); + break; + case GROUP: + value = reader.readGroup(extension.defaultInstance.getClass(), extensionRegistry); + break; + + case MESSAGE: + value = reader.readMessage(extension.defaultInstance.getClass(), extensionRegistry); + break; + + case ENUM: + throw new IllegalStateException("Shouldn't reach here."); + } + } + if (extension.descriptor.isRepeated()) { + extensions.addRepeatedField(extension.descriptor, value); + } else { + switch (extension.descriptor.getLiteType()) { + case MESSAGE: + case GROUP: + Object oldValue = extensions.getField(extension.descriptor); + if (oldValue != null) { + value = Internal.mergeMessage(oldValue, value); + } + break; + default: + break; + } + extensions.setField(extension.descriptor, value); + } + } + return unknownFields; + } + + @Override + int extensionNumber(Map.Entry extension) { + FieldDescriptor descriptor = (FieldDescriptor) extension.getKey(); + return descriptor.getNumber(); + } + + @Override + void serializeExtension(Writer writer, Map.Entry extension) throws IOException { + FieldDescriptor descriptor = (FieldDescriptor) extension.getKey(); + if (descriptor.isRepeated()) { + switch (descriptor.getLiteType()) { + case DOUBLE: + SchemaUtil.writeDoubleList( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case FLOAT: + SchemaUtil.writeFloatList( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case INT64: + SchemaUtil.writeInt64List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case UINT64: + SchemaUtil.writeUInt64List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case INT32: + SchemaUtil.writeInt32List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case FIXED64: + SchemaUtil.writeFixed64List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case FIXED32: + SchemaUtil.writeFixed32List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case BOOL: + SchemaUtil.writeBoolList( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case BYTES: + SchemaUtil.writeBytesList( + descriptor.getNumber(), (List) extension.getValue(), writer); + break; + case UINT32: + SchemaUtil.writeUInt32List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case SFIXED32: + SchemaUtil.writeSFixed32List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case SFIXED64: + SchemaUtil.writeSFixed64List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case SINT32: + SchemaUtil.writeSInt32List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case SINT64: + SchemaUtil.writeSInt64List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case ENUM: + { + List enumList = (List) extension.getValue(); + List list = new ArrayList(); + for (EnumValueDescriptor d : enumList) { + list.add(d.getNumber()); + } + SchemaUtil.writeInt32List(descriptor.getNumber(), list, writer, descriptor.isPacked()); + break; + } + case STRING: + SchemaUtil.writeStringList( + descriptor.getNumber(), (List) extension.getValue(), writer); + break; + case GROUP: + SchemaUtil.writeGroupList(descriptor.getNumber(), (List) extension.getValue(), writer); + break; + case MESSAGE: + SchemaUtil.writeMessageList( + descriptor.getNumber(), (List) extension.getValue(), writer); + break; + } + } else { + switch (descriptor.getLiteType()) { + case DOUBLE: + writer.writeDouble(descriptor.getNumber(), (Double) extension.getValue()); + break; + case FLOAT: + writer.writeFloat(descriptor.getNumber(), (Float) extension.getValue()); + break; + case INT64: + writer.writeInt64(descriptor.getNumber(), (Long) extension.getValue()); + break; + case UINT64: + writer.writeUInt64(descriptor.getNumber(), (Long) extension.getValue()); + break; + case INT32: + writer.writeInt32(descriptor.getNumber(), (Integer) extension.getValue()); + break; + case FIXED64: + writer.writeFixed64(descriptor.getNumber(), (Long) extension.getValue()); + break; + case FIXED32: + writer.writeFixed32(descriptor.getNumber(), (Integer) extension.getValue()); + break; + case BOOL: + writer.writeBool(descriptor.getNumber(), (Boolean) extension.getValue()); + break; + case BYTES: + writer.writeBytes(descriptor.getNumber(), (ByteString) extension.getValue()); + break; + case UINT32: + writer.writeUInt32(descriptor.getNumber(), (Integer) extension.getValue()); + break; + case SFIXED32: + writer.writeSFixed32(descriptor.getNumber(), (Integer) extension.getValue()); + break; + case SFIXED64: + writer.writeSFixed64(descriptor.getNumber(), (Long) extension.getValue()); + break; + case SINT32: + writer.writeSInt32(descriptor.getNumber(), (Integer) extension.getValue()); + break; + case SINT64: + writer.writeSInt64(descriptor.getNumber(), (Long) extension.getValue()); + break; + case ENUM: + writer.writeInt32( + descriptor.getNumber(), ((EnumValueDescriptor) extension.getValue()).getNumber()); + break; + case STRING: + writer.writeString(descriptor.getNumber(), (String) extension.getValue()); + break; + case GROUP: + writer.writeGroup(descriptor.getNumber(), extension.getValue()); + break; + case MESSAGE: + writer.writeMessage(descriptor.getNumber(), extension.getValue()); + break; + } + } + } + + @Override + Object findExtensionByNumber( + ExtensionRegistryLite extensionRegistry, MessageLite defaultInstance, int number) { + return ((ExtensionRegistry) extensionRegistry) + .findExtensionByNumber(((Message) defaultInstance).getDescriptorForType(), number); + } + + @Override + void parseLengthPrefixedMessageSetItem( + Reader reader, + Object extension, + ExtensionRegistryLite extensionRegistry, + FieldSet extensions) + throws IOException { + ExtensionRegistry.ExtensionInfo extensionInfo = (ExtensionRegistry.ExtensionInfo) extension; + + if (ExtensionRegistryLite.isEagerlyParseMessageSets()) { + Object value = + reader.readMessage(extensionInfo.defaultInstance.getClass(), extensionRegistry); + extensions.setField(extensionInfo.descriptor, value); + } else { + extensions.setField( + extensionInfo.descriptor, + new LazyField(extensionInfo.defaultInstance, extensionRegistry, reader.readBytes())); + } + } + + @Override + void parseMessageSetItem( + ByteString data, + Object extension, + ExtensionRegistryLite extensionRegistry, + FieldSet extensions) + throws IOException { + ExtensionRegistry.ExtensionInfo extensionInfo = (ExtensionRegistry.ExtensionInfo) extension; + Object value = extensionInfo.defaultInstance.newBuilderForType().buildPartial(); + + if (ExtensionRegistryLite.isEagerlyParseMessageSets()) { + Reader reader = BinaryReader.newInstance(ByteBuffer.wrap(data.toByteArray()), true); + Protobuf.getInstance().mergeFrom(value, reader, extensionRegistry); + extensions.setField(extensionInfo.descriptor, value); + + if (reader.getFieldNumber() != Reader.READ_DONE) { + throw InvalidProtocolBufferException.invalidEndTag(); + } + } else { + extensions.setField( + extensionInfo.descriptor, + new LazyField(extensionInfo.defaultInstance, extensionRegistry, data)); + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionSchemaLite.java b/java/core/src/main/java/com/google/protobuf/ExtensionSchemaLite.java new file mode 100644 index 0000000000000..437cca2d96bdc --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/ExtensionSchemaLite.java @@ -0,0 +1,541 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.GeneratedMessageLite.ExtensionDescriptor; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@SuppressWarnings("unchecked") +final class ExtensionSchemaLite extends ExtensionSchema { + + @Override + boolean hasExtensions(MessageLite prototype) { + return prototype instanceof GeneratedMessageLite.ExtendableMessage; + } + + @Override + FieldSet getExtensions(Object message) { + return ((GeneratedMessageLite.ExtendableMessage) message).extensions; + } + + @Override + void setExtensions(Object message, FieldSet extensions) { + ((GeneratedMessageLite.ExtendableMessage) message).extensions = extensions; + } + + @Override + FieldSet getMutableExtensions(Object message) { + return ((GeneratedMessageLite.ExtendableMessage) message).ensureExtensionsAreMutable(); + } + + @Override + void makeImmutable(Object message) { + getExtensions(message).makeImmutable(); + } + + @Override + UB parseExtension( + Reader reader, + Object extensionObject, + ExtensionRegistryLite extensionRegistry, + FieldSet extensions, + UB unknownFields, + UnknownFieldSchema unknownFieldSchema) + throws IOException { + GeneratedMessageLite.GeneratedExtension extension = + (GeneratedMessageLite.GeneratedExtension) extensionObject; + int fieldNumber = extension.getNumber(); + + if (extension.descriptor.isRepeated() && extension.descriptor.isPacked()) { + Object value = null; + switch (extension.getLiteType()) { + case DOUBLE: + { + List list = new ArrayList(); + reader.readDoubleList(list); + value = list; + break; + } + case FLOAT: + { + List list = new ArrayList(); + reader.readFloatList(list); + value = list; + break; + } + case INT64: + { + List list = new ArrayList(); + reader.readInt64List(list); + value = list; + break; + } + case UINT64: + { + List list = new ArrayList(); + reader.readUInt64List(list); + value = list; + break; + } + case INT32: + { + List list = new ArrayList(); + reader.readInt32List(list); + value = list; + break; + } + case FIXED64: + { + List list = new ArrayList(); + reader.readFixed64List(list); + value = list; + break; + } + case FIXED32: + { + List list = new ArrayList(); + reader.readFixed32List(list); + value = list; + break; + } + case BOOL: + { + List list = new ArrayList(); + reader.readBoolList(list); + value = list; + break; + } + case UINT32: + { + List list = new ArrayList(); + reader.readUInt32List(list); + value = list; + break; + } + case SFIXED32: + { + List list = new ArrayList(); + reader.readSFixed32List(list); + value = list; + break; + } + case SFIXED64: + { + List list = new ArrayList(); + reader.readSFixed64List(list); + value = list; + break; + } + case SINT32: + { + List list = new ArrayList(); + reader.readSInt32List(list); + value = list; + break; + } + case SINT64: + { + List list = new ArrayList(); + reader.readSInt64List(list); + value = list; + break; + } + case ENUM: + { + List list = new ArrayList(); + reader.readEnumList(list); + unknownFields = + SchemaUtil.filterUnknownEnumList( + fieldNumber, + list, + extension.descriptor.getEnumType(), + unknownFields, + unknownFieldSchema); + value = list; + break; + } + default: + throw new IllegalStateException( + "Type cannot be packed: " + extension.descriptor.getLiteType()); + } + extensions.setField(extension.descriptor, value); + } else { + Object value = null; + // Enum is a special case because unknown enum values will be put into UnknownFieldSetLite. + if (extension.getLiteType() == WireFormat.FieldType.ENUM) { + int number = reader.readInt32(); + Object enumValue = extension.descriptor.getEnumType().findValueByNumber(number); + if (enumValue == null) { + return SchemaUtil.storeUnknownEnum( + fieldNumber, number, unknownFields, unknownFieldSchema); + } + // Note, we store the integer value instead of the actual enum object in FieldSet. + // This is also different from full-runtime where we store EnumValueDescriptor. + value = number; + } else { + switch (extension.getLiteType()) { + case DOUBLE: + value = reader.readDouble(); + break; + case FLOAT: + value = reader.readFloat(); + break; + case INT64: + value = reader.readInt64(); + break; + case UINT64: + value = reader.readUInt64(); + break; + case INT32: + value = reader.readInt32(); + break; + case FIXED64: + value = reader.readFixed64(); + break; + case FIXED32: + value = reader.readFixed32(); + break; + case BOOL: + value = reader.readBool(); + break; + case BYTES: + value = reader.readBytes(); + break; + case UINT32: + value = reader.readUInt32(); + break; + case SFIXED32: + value = reader.readSFixed32(); + break; + case SFIXED64: + value = reader.readSFixed64(); + break; + case SINT32: + value = reader.readSInt32(); + break; + case SINT64: + value = reader.readSInt64(); + break; + + case STRING: + value = reader.readString(); + break; + case GROUP: + value = + reader.readGroup( + extension.getMessageDefaultInstance().getClass(), extensionRegistry); + break; + + case MESSAGE: + value = + reader.readMessage( + extension.getMessageDefaultInstance().getClass(), extensionRegistry); + break; + + case ENUM: + throw new IllegalStateException("Shouldn't reach here."); + } + } + if (extension.isRepeated()) { + extensions.addRepeatedField(extension.descriptor, value); + } else { + switch (extension.getLiteType()) { + case MESSAGE: + case GROUP: + Object oldValue = extensions.getField(extension.descriptor); + if (oldValue != null) { + value = Internal.mergeMessage(oldValue, value); + } + break; + default: + break; + } + extensions.setField(extension.descriptor, value); + } + } + return unknownFields; + } + + @Override + int extensionNumber(Map.Entry extension) { + GeneratedMessageLite.ExtensionDescriptor descriptor = + (GeneratedMessageLite.ExtensionDescriptor) extension.getKey(); + return descriptor.getNumber(); + } + + @Override + void serializeExtension(Writer writer, Map.Entry extension) throws IOException { + GeneratedMessageLite.ExtensionDescriptor descriptor = + (GeneratedMessageLite.ExtensionDescriptor) extension.getKey(); + if (descriptor.isRepeated()) { + switch (descriptor.getLiteType()) { + case DOUBLE: + SchemaUtil.writeDoubleList( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case FLOAT: + SchemaUtil.writeFloatList( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case INT64: + SchemaUtil.writeInt64List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case UINT64: + SchemaUtil.writeUInt64List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case INT32: + SchemaUtil.writeInt32List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case FIXED64: + SchemaUtil.writeFixed64List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case FIXED32: + SchemaUtil.writeFixed32List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case BOOL: + SchemaUtil.writeBoolList( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case BYTES: + SchemaUtil.writeBytesList( + descriptor.getNumber(), (List) extension.getValue(), writer); + break; + case UINT32: + SchemaUtil.writeUInt32List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case SFIXED32: + SchemaUtil.writeSFixed32List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case SFIXED64: + SchemaUtil.writeSFixed64List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case SINT32: + SchemaUtil.writeSInt32List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case SINT64: + SchemaUtil.writeSInt64List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case ENUM: + SchemaUtil.writeInt32List( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + descriptor.isPacked()); + break; + case STRING: + SchemaUtil.writeStringList( + descriptor.getNumber(), (List) extension.getValue(), writer); + break; + case GROUP: + { + List data = (List) extension.getValue(); + if (data != null && !data.isEmpty()) { + SchemaUtil.writeGroupList( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + Protobuf.getInstance().schemaFor(data.get(0).getClass())); + } + } + break; + case MESSAGE: + { + List data = (List) extension.getValue(); + if (data != null && !data.isEmpty()) { + SchemaUtil.writeMessageList( + descriptor.getNumber(), + (List) extension.getValue(), + writer, + Protobuf.getInstance().schemaFor(data.get(0).getClass())); + } + } + break; + } + } else { + switch (descriptor.getLiteType()) { + case DOUBLE: + writer.writeDouble(descriptor.getNumber(), (Double) extension.getValue()); + break; + case FLOAT: + writer.writeFloat(descriptor.getNumber(), (Float) extension.getValue()); + break; + case INT64: + writer.writeInt64(descriptor.getNumber(), (Long) extension.getValue()); + break; + case UINT64: + writer.writeUInt64(descriptor.getNumber(), (Long) extension.getValue()); + break; + case INT32: + writer.writeInt32(descriptor.getNumber(), (Integer) extension.getValue()); + break; + case FIXED64: + writer.writeFixed64(descriptor.getNumber(), (Long) extension.getValue()); + break; + case FIXED32: + writer.writeFixed32(descriptor.getNumber(), (Integer) extension.getValue()); + break; + case BOOL: + writer.writeBool(descriptor.getNumber(), (Boolean) extension.getValue()); + break; + case BYTES: + writer.writeBytes(descriptor.getNumber(), (ByteString) extension.getValue()); + break; + case UINT32: + writer.writeUInt32(descriptor.getNumber(), (Integer) extension.getValue()); + break; + case SFIXED32: + writer.writeSFixed32(descriptor.getNumber(), (Integer) extension.getValue()); + break; + case SFIXED64: + writer.writeSFixed64(descriptor.getNumber(), (Long) extension.getValue()); + break; + case SINT32: + writer.writeSInt32(descriptor.getNumber(), (Integer) extension.getValue()); + break; + case SINT64: + writer.writeSInt64(descriptor.getNumber(), (Long) extension.getValue()); + break; + case ENUM: + writer.writeInt32(descriptor.getNumber(), (Integer) extension.getValue()); + break; + case STRING: + writer.writeString(descriptor.getNumber(), (String) extension.getValue()); + break; + case GROUP: + writer.writeGroup( + descriptor.getNumber(), + extension.getValue(), + Protobuf.getInstance().schemaFor(extension.getValue().getClass())); + break; + case MESSAGE: + writer.writeMessage( + descriptor.getNumber(), + extension.getValue(), + Protobuf.getInstance().schemaFor(extension.getValue().getClass())); + break; + } + } + } + + @Override + Object findExtensionByNumber( + ExtensionRegistryLite extensionRegistry, MessageLite defaultInstance, int number) { + return extensionRegistry.findLiteExtensionByNumber(defaultInstance, number); + } + + @Override + void parseLengthPrefixedMessageSetItem( + Reader reader, + Object extensionObject, + ExtensionRegistryLite extensionRegistry, + FieldSet extensions) + throws IOException { + GeneratedMessageLite.GeneratedExtension extension = + (GeneratedMessageLite.GeneratedExtension) extensionObject; + Object value = + reader.readMessage(extension.getMessageDefaultInstance().getClass(), extensionRegistry); + extensions.setField(extension.descriptor, value); + } + + @Override + void parseMessageSetItem( + ByteString data, + Object extensionObject, + ExtensionRegistryLite extensionRegistry, + FieldSet extensions) + throws IOException { + GeneratedMessageLite.GeneratedExtension extension = + (GeneratedMessageLite.GeneratedExtension) extensionObject; + Object value = extension.getMessageDefaultInstance().newBuilderForType().buildPartial(); + + Reader reader = BinaryReader.newInstance(ByteBuffer.wrap(data.toByteArray()), true); + + Protobuf.getInstance().mergeFrom(value, reader, extensionRegistry); + extensions.setField(extension.descriptor, value); + + if (reader.getFieldNumber() != Reader.READ_DONE) { + throw InvalidProtocolBufferException.invalidEndTag(); + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionSchemas.java b/java/core/src/main/java/com/google/protobuf/ExtensionSchemas.java new file mode 100644 index 0000000000000..46ce327d133e3 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/ExtensionSchemas.java @@ -0,0 +1,56 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +final class ExtensionSchemas { + private static final ExtensionSchema LITE_SCHEMA = new ExtensionSchemaLite(); + private static final ExtensionSchema FULL_SCHEMA = loadSchemaForFullRuntime(); + + private static ExtensionSchema loadSchemaForFullRuntime() { + try { + Class clazz = Class.forName("com.google.protobuf.ExtensionSchemaFull"); + return (ExtensionSchema) clazz.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + return null; + } + } + + static ExtensionSchema lite() { + return LITE_SCHEMA; + } + + static ExtensionSchema full() { + if (FULL_SCHEMA == null) { + throw new IllegalStateException("Protobuf runtime is not correctly loaded."); + } + return FULL_SCHEMA; + } +} diff --git a/java/core/src/main/java/com/google/protobuf/FieldInfo.java b/java/core/src/main/java/com/google/protobuf/FieldInfo.java new file mode 100644 index 0000000000000..71a307a895b60 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/FieldInfo.java @@ -0,0 +1,577 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.Internal.checkNotNull; + +import com.google.protobuf.Internal.EnumVerifier; +import java.lang.reflect.Field; + +/** Information for a single field in a protobuf message class. */ +@ExperimentalApi +final class FieldInfo implements Comparable { + private final Field field; + private final FieldType type; + private final Class messageClass; // The message type for repeated message fields. + private final int fieldNumber; + private final Field presenceField; + private final int presenceMask; + private final boolean required; + private final boolean enforceUtf8; + private final OneofInfo oneof; + private final Field cachedSizeField; + /** + * The actual type stored in the oneof value for this field. Since the oneof value is an {@link + * Object}, primitives will store their boxed type. Only valid in conjunction with {@link #oneof} + * (both must be either null or non-null. + */ + private final Class oneofStoredType; + + // TODO(liujisi): make map default entry lazy? + private final Object mapDefaultEntry; + + private final EnumVerifier enumVerifier; + + /** Constructs a new descriptor for a field. */ + public static FieldInfo forField( + Field field, int fieldNumber, FieldType fieldType, boolean enforceUtf8) { + checkFieldNumber(fieldNumber); + checkNotNull(field, "field"); + checkNotNull(fieldType, "fieldType"); + if (fieldType == FieldType.MESSAGE_LIST || fieldType == FieldType.GROUP_LIST) { + throw new IllegalStateException("Shouldn't be called for repeated message fields."); + } + return new FieldInfo( + field, + fieldNumber, + fieldType, + /* messageClass= */ null, + /* presenceField= */ null, + /* presenceMask= */ 0, + /* required= */ false, + enforceUtf8, + /* oneof= */ null, + /* oneofStoredType= */ null, + /* mapDefaultEntry= */ null, + /* enumVerifier= */ null, + /* cachedSizeField= */ null); + } + + /** Constructs a new descriptor for a packed field. */ + public static FieldInfo forPackedField( + Field field, int fieldNumber, FieldType fieldType, Field cachedSizeField) { + checkFieldNumber(fieldNumber); + checkNotNull(field, "field"); + checkNotNull(fieldType, "fieldType"); + if (fieldType == FieldType.MESSAGE_LIST || fieldType == FieldType.GROUP_LIST) { + throw new IllegalStateException("Shouldn't be called for repeated message fields."); + } + return new FieldInfo( + field, + fieldNumber, + fieldType, + /* messageClass= */ null, + /* presenceField= */ null, + /* presenceMask= */ 0, + /* required= */ false, + /* enforceUtf8= */ false, + /* oneof= */ null, + /* oneofStoredType= */ null, + /* mapDefaultEntry= */ null, + /* enumVerifier= */ null, + cachedSizeField); + } + + /** Constructs a new descriptor for a repeated message field. */ + public static FieldInfo forRepeatedMessageField( + Field field, int fieldNumber, FieldType fieldType, Class messageClass) { + checkFieldNumber(fieldNumber); + checkNotNull(field, "field"); + checkNotNull(fieldType, "fieldType"); + checkNotNull(messageClass, "messageClass"); + return new FieldInfo( + field, + fieldNumber, + fieldType, + messageClass, + /* presenceField= */ null, + /* presenceMask= */ 0, + /* required= */ false, + /* enforceUtf8= */ false, + /* oneof= */ null, + /* oneofStoredType= */ null, + /* mapDefaultEntry= */ null, + /* enumVerifier= */ null, + /* cachedSizeField= */ null); + } + + public static FieldInfo forFieldWithEnumVerifier( + Field field, int fieldNumber, FieldType fieldType, EnumVerifier enumVerifier) { + checkFieldNumber(fieldNumber); + checkNotNull(field, "field"); + return new FieldInfo( + field, + fieldNumber, + fieldType, + /* messageClass= */ null, + /* presenceField= */ null, + /* presenceMask= */ 0, + /* required= */ false, + /* enforceUtf8= */ false, + /* oneof= */ null, + /* oneofStoredType= */ null, + /* mapDefaultEntry= */ null, + enumVerifier, + /* cachedSizeField= */ null); + } + + public static FieldInfo forPackedFieldWithEnumVerifier( + Field field, + int fieldNumber, + FieldType fieldType, + EnumVerifier enumVerifier, + Field cachedSizeField) { + checkFieldNumber(fieldNumber); + checkNotNull(field, "field"); + return new FieldInfo( + field, + fieldNumber, + fieldType, + /* messageClass= */ null, + /* presenceField= */ null, + /* presenceMask= */ 0, + /* required= */ false, + /* enforceUtf8= */ false, + /* oneof= */ null, + /* oneofStoredType= */ null, + /* mapDefaultEntry= */ null, + enumVerifier, + cachedSizeField); + } + + /** Constructor for a proto2 optional field. */ + public static FieldInfo forProto2OptionalField( + Field field, + int fieldNumber, + FieldType fieldType, + Field presenceField, + int presenceMask, + boolean enforceUtf8, + EnumVerifier enumVerifier) { + checkFieldNumber(fieldNumber); + checkNotNull(field, "field"); + checkNotNull(fieldType, "fieldType"); + checkNotNull(presenceField, "presenceField"); + if (presenceField != null && !isExactlyOneBitSet(presenceMask)) { + throw new IllegalArgumentException( + "presenceMask must have exactly one bit set: " + presenceMask); + } + return new FieldInfo( + field, + fieldNumber, + fieldType, + /* messageClass= */ null, + presenceField, + presenceMask, + /* required= */ false, + enforceUtf8, + /* oneof= */ null, + /* oneofStoredType= */ null, + /* mapDefaultEntry= */ null, + enumVerifier, + /* cachedSizeField= */ null); + } + + /** + * Constructor for a field that is part of a oneof. + * + * @param fieldNumber the unique field number for this field within the message. + * @param fieldType the type of the field (must be non-null). + * @param oneof the oneof for which this field is associated (must be non-null). + * @param oneofStoredType the actual type stored in the oneof value for this field. Since the + * oneof value is an {@link Object}, primitives will store their boxed type. Must be non-null. + * @param enforceUtf8 Only used for string fields. If {@code true}, will enforce UTF-8 on a string + * field. + * @return the {@link FieldInfo} describing this field. + */ + public static FieldInfo forOneofMemberField( + int fieldNumber, + FieldType fieldType, + OneofInfo oneof, + Class oneofStoredType, + boolean enforceUtf8, + EnumVerifier enumVerifier) { + checkFieldNumber(fieldNumber); + checkNotNull(fieldType, "fieldType"); + checkNotNull(oneof, "oneof"); + checkNotNull(oneofStoredType, "oneofStoredType"); + if (!fieldType.isScalar()) { + throw new IllegalArgumentException( + "Oneof is only supported for scalar fields. Field " + + fieldNumber + + " is of type " + + fieldType); + } + return new FieldInfo( + /* field= */ null, + fieldNumber, + fieldType, + /* messageClass= */ null, + /* presenceField= */ null, + /* presenceMask= */ 0, + /* required= */ false, + enforceUtf8, + oneof, + oneofStoredType, + /* mapDefaultEntry= */ null, + enumVerifier, + /* cachedSizeField= */ null); + } + + private static void checkFieldNumber(int fieldNumber) { + if (fieldNumber <= 0) { + throw new IllegalArgumentException("fieldNumber must be positive: " + fieldNumber); + } + } + + /** Constructor for a proto2 required field. */ + public static FieldInfo forProto2RequiredField( + Field field, + int fieldNumber, + FieldType fieldType, + Field presenceField, + int presenceMask, + boolean enforceUtf8, + EnumVerifier enumVerifier) { + checkFieldNumber(fieldNumber); + checkNotNull(field, "field"); + checkNotNull(fieldType, "fieldType"); + checkNotNull(presenceField, "presenceField"); + if (presenceField != null && !isExactlyOneBitSet(presenceMask)) { + throw new IllegalArgumentException( + "presenceMask must have exactly one bit set: " + presenceMask); + } + return new FieldInfo( + field, + fieldNumber, + fieldType, + /* messageClass= */ null, + presenceField, + presenceMask, + /* required= */ true, + enforceUtf8, + /* oneof= */ null, + /* oneofStoredType= */ null, + /* mapDefaultEntry= */ null, + /* enumVerifier= */ enumVerifier, + /* cachedSizeField= */ null); + } + + public static FieldInfo forMapField( + Field field, int fieldNumber, Object mapDefaultEntry, EnumVerifier enumVerifier) { + checkNotNull(mapDefaultEntry, "mapDefaultEntry"); + checkFieldNumber(fieldNumber); + checkNotNull(field, "field"); + return new FieldInfo( + field, + fieldNumber, + FieldType.MAP, + /* messageClass= */ null, + /* presenceField= */ null, + /* presenceMask= */ 0, + /* required= */ false, + /* enforceUtf8= */ true, + /* oneof= */ null, + /* oneofStoredType= */ null, + mapDefaultEntry, + enumVerifier, + /* cachedSizeField= */ null); + } + + private FieldInfo( + Field field, + int fieldNumber, + FieldType type, + Class messageClass, + Field presenceField, + int presenceMask, + boolean required, + boolean enforceUtf8, + OneofInfo oneof, + Class oneofStoredType, + Object mapDefaultEntry, + EnumVerifier enumVerifier, + Field cachedSizeField) { + this.field = field; + this.type = type; + this.messageClass = messageClass; + this.fieldNumber = fieldNumber; + this.presenceField = presenceField; + this.presenceMask = presenceMask; + this.required = required; + this.enforceUtf8 = enforceUtf8; + this.oneof = oneof; + this.oneofStoredType = oneofStoredType; + this.mapDefaultEntry = mapDefaultEntry; + this.enumVerifier = enumVerifier; + this.cachedSizeField = cachedSizeField; + } + + /** Gets the field number for the field. */ + public int getFieldNumber() { + return fieldNumber; + } + + /** Gets the subject {@link Field} of this descriptor. */ + public Field getField() { + return field; + } + + /** Gets the type information for the field. */ + public FieldType getType() { + return type; + } + + /** Gets the oneof for which this field is a member, or {@code null} if not part of a oneof. */ + public OneofInfo getOneof() { + return oneof; + } + + /** + * Gets the actual type stored in the oneof value by this field. Since the oneof value is an + * {@link Object}, primitives will store their boxed type. For non-oneof fields, this will always + * be {@code null}. + */ + public Class getOneofStoredType() { + return oneofStoredType; + } + + /** Gets the {@code EnumVerifier} if the field is an enum field. */ + public EnumVerifier getEnumVerifier() { + return enumVerifier; + } + + @Override + public int compareTo(FieldInfo o) { + return fieldNumber - o.fieldNumber; + } + + /** + * For repeated message fields, returns the message type of the field. For other fields, returns + * {@code null}. + */ + public Class getListElementType() { + return messageClass; + } + + /** Gets the presence bit field. Only valid for unary fields. For lists, returns {@code null}. */ + public Field getPresenceField() { + return presenceField; + } + + public Object getMapDefaultEntry() { + return mapDefaultEntry; + } + + /** + * If {@link #getPresenceField()} is non-{@code null}, returns the mask used to identify the + * presence bit for this field in the message. + */ + public int getPresenceMask() { + return presenceMask; + } + + /** Whether this is a required field. */ + public boolean isRequired() { + return required; + } + + /** + * Whether a UTF-8 should be enforced on string fields. Only applies to strings and string lists. + */ + public boolean isEnforceUtf8() { + return enforceUtf8; + } + + public Field getCachedSizeField() { + return cachedSizeField; + } + + /** + * For singular or repeated message fields, returns the message type. For other fields, returns + * {@code null}. + */ + public Class getMessageFieldClass() { + switch (type) { + case MESSAGE: + case GROUP: + return field != null ? field.getType() : oneofStoredType; + case MESSAGE_LIST: + case GROUP_LIST: + return messageClass; + default: + return null; + } + } + + public static Builder newBuilder() { + return new Builder(); + } + + /** A builder for {@link FieldInfo} instances. */ + public static final class Builder { + private Field field; + private FieldType type; + private int fieldNumber; + private Field presenceField; + private int presenceMask; + private boolean required; + private boolean enforceUtf8; + private OneofInfo oneof; + private Class oneofStoredType; + private Object mapDefaultEntry; + private EnumVerifier enumVerifier; + private Field cachedSizeField; + + private Builder() {} + + /** + * Specifies the actual field on the message represented by this field. This should not be + * called for oneof member fields. + */ + public Builder withField(Field field) { + if (oneof != null) { + throw new IllegalStateException("Cannot set field when building a oneof."); + } + this.field = field; + return this; + } + + /** Specifies the type of this field. */ + public Builder withType(FieldType type) { + this.type = type; + return this; + } + + /** Specifies the unique field number for this field within the message. */ + public Builder withFieldNumber(int fieldNumber) { + this.fieldNumber = fieldNumber; + return this; + } + + /** Specifies proto2 presence information. This should not be called for oneof fields. */ + public Builder withPresence(Field presenceField, int presenceMask) { + this.presenceField = checkNotNull(presenceField, "presenceField"); + this.presenceMask = presenceMask; + return this; + } + + /** + * Sets the information for building a oneof member field. This is incompatible with {@link + * #withField(Field)} and {@link #withPresence(Field, int)}. + * + * @param oneof the oneof for which this field is associated. + * @param oneofStoredType the actual type stored in the oneof value for this field. Since the + * oneof value is an {@link Object}, primitives will store their boxed type. + */ + public Builder withOneof(OneofInfo oneof, Class oneofStoredType) { + if (field != null || presenceField != null) { + throw new IllegalStateException( + "Cannot set oneof when field or presenceField have been provided"); + } + this.oneof = oneof; + this.oneofStoredType = oneofStoredType; + return this; + } + + public Builder withRequired(boolean required) { + this.required = required; + return this; + } + + public Builder withMapDefaultEntry(Object mapDefaultEntry) { + this.mapDefaultEntry = mapDefaultEntry; + return this; + } + + public Builder withEnforceUtf8(boolean enforceUtf8) { + this.enforceUtf8 = enforceUtf8; + return this; + } + + public Builder withEnumVerifier(EnumVerifier enumVerifier) { + this.enumVerifier = enumVerifier; + return this; + } + + public Builder withCachedSizeField(Field cachedSizeField) { + this.cachedSizeField = cachedSizeField; + return this; + } + + public FieldInfo build() { + if (oneof != null) { + return forOneofMemberField( + fieldNumber, type, oneof, oneofStoredType, enforceUtf8, enumVerifier); + } + if (mapDefaultEntry != null) { + return forMapField(field, fieldNumber, mapDefaultEntry, enumVerifier); + } + if (presenceField != null) { + if (required) { + return forProto2RequiredField( + field, fieldNumber, type, presenceField, presenceMask, enforceUtf8, enumVerifier); + } else { + return forProto2OptionalField( + field, fieldNumber, type, presenceField, presenceMask, enforceUtf8, enumVerifier); + } + } + if (enumVerifier != null) { + if (cachedSizeField == null) { + return forFieldWithEnumVerifier(field, fieldNumber, type, enumVerifier); + } else { + return forPackedFieldWithEnumVerifier( + field, fieldNumber, type, enumVerifier, cachedSizeField); + } + } else { + if (cachedSizeField == null) { + return forField(field, fieldNumber, type, enforceUtf8); + } else { + return forPackedField(field, fieldNumber, type, cachedSizeField); + } + } + } + } + + private static boolean isExactlyOneBitSet(int value) { + return value != 0 && (value & (value - 1)) == 0; + } +} diff --git a/java/core/src/main/java/com/google/protobuf/FieldSet.java b/java/core/src/main/java/com/google/protobuf/FieldSet.java index 8a9239edefa8f..1d8592f7527c9 100644 --- a/java/core/src/main/java/com/google/protobuf/FieldSet.java +++ b/java/core/src/main/java/com/google/protobuf/FieldSet.java @@ -41,69 +41,84 @@ import java.util.Map; /** - * A class which represents an arbitrary set of fields of some message type. - * This is used to implement {@link DynamicMessage}, and also to represent - * extensions in {@link GeneratedMessage}. This class is package-private, - * since outside users should probably be using {@link DynamicMessage}. + * A class which represents an arbitrary set of fields of some message type. This is used to + * implement {@link DynamicMessage}, and also to represent extensions in {@link GeneratedMessage}. + * This class is package-private, since outside users should probably be using {@link + * DynamicMessage}. * * @author kenton@google.com Kenton Varda */ -final class FieldSet> { +final class FieldSet> { /** - * Interface for a FieldDescriptor or lite extension descriptor. This - * prevents FieldSet from depending on {@link Descriptors.FieldDescriptor}. + * Interface for a FieldDescriptor or lite extension descriptor. This prevents FieldSet from + * depending on {@link Descriptors.FieldDescriptor}. */ - public interface FieldDescriptorLite> - extends Comparable { + public interface FieldDescriptorLite> extends Comparable { int getNumber(); + WireFormat.FieldType getLiteType(); + WireFormat.JavaType getLiteJavaType(); + boolean isRepeated(); + boolean isPacked(); + Internal.EnumLiteMap getEnumType(); // If getLiteJavaType() == MESSAGE, this merges a message object of the // type into a builder of the type. Returns {@code to}. - MessageLite.Builder internalMergeFrom( - MessageLite.Builder to, MessageLite from); + MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from); } - private final SmallSortedMap fields; + private static final int DEFAULT_FIELD_MAP_ARRAY_SIZE = 16; + + private final SmallSortedMap fields; private boolean isImmutable; - private boolean hasLazyField = false; + private boolean hasLazyField; /** Construct a new FieldSet. */ private FieldSet() { - this.fields = SmallSortedMap.newFieldMap(16); + this.fields = SmallSortedMap.newFieldMap(DEFAULT_FIELD_MAP_ARRAY_SIZE); } - /** - * Construct an empty FieldSet. This is only used to initialize - * DEFAULT_INSTANCE. - */ + /** Construct an empty FieldSet. This is only used to initialize DEFAULT_INSTANCE. */ + @SuppressWarnings("unused") private FieldSet(final boolean dummy) { - this.fields = SmallSortedMap.newFieldMap(0); + this(SmallSortedMap.newFieldMap(0)); + makeImmutable(); + } + + private FieldSet(SmallSortedMap fields) { + this.fields = fields; makeImmutable(); } /** Construct a new FieldSet. */ - public static > - FieldSet newFieldSet() { + public static > FieldSet newFieldSet() { return new FieldSet(); } /** Get an immutable empty FieldSet. */ @SuppressWarnings("unchecked") - public static > - FieldSet emptySet() { + public static > FieldSet emptySet() { return DEFAULT_INSTANCE; } + + /** Construct a new Builder. */ + public static > Builder newBuilder() { + return new Builder(); + } + @SuppressWarnings("rawtypes") private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true); + /** Returns {@code true} if empty, {@code false} otherwise. */ + boolean isEmpty() { + return fields.isEmpty(); + } + /** Make this FieldSet immutable from this point forward. */ - @SuppressWarnings("unchecked") public void makeImmutable() { if (isImmutable) { return; @@ -113,8 +128,8 @@ public void makeImmutable() { } /** - * Returns whether the FieldSet is immutable. This is true if it is the - * {@link #emptySet} or if {@link #makeImmutable} were called. + * Returns whether the FieldSet is immutable. This is true if it is the {@link #emptySet} or if + * {@link #makeImmutable} were called. * * @return whether the FieldSet is immutable. */ @@ -142,25 +157,22 @@ public int hashCode() { } /** - * Clones the FieldSet. The returned FieldSet will be mutable even if the - * original FieldSet was immutable. + * Clones the FieldSet. The returned FieldSet will be mutable even if the original FieldSet was + * immutable. * * @return the newly cloned FieldSet */ @Override - public FieldSet clone() { + public FieldSet clone() { // We can't just call fields.clone because List objects in the map // should not be shared. - FieldSet clone = FieldSet.newFieldSet(); + FieldSet clone = FieldSet.newFieldSet(); for (int i = 0; i < fields.getNumArrayEntries(); i++) { - Map.Entry entry = fields.getArrayEntryAt(i); - FieldDescriptorType descriptor = entry.getKey(); - clone.setField(descriptor, entry.getValue()); + Map.Entry entry = fields.getArrayEntryAt(i); + clone.setField(entry.getKey(), entry.getValue()); } - for (Map.Entry entry : - fields.getOverflowEntries()) { - FieldDescriptorType descriptor = entry.getKey(); - clone.setField(descriptor, entry.getValue()); + for (Map.Entry entry : fields.getOverflowEntries()) { + clone.setField(entry.getKey(), entry.getValue()); } clone.hasLazyField = hasLazyField; return clone; @@ -175,20 +187,10 @@ public void clear() { hasLazyField = false; } - /** - * Get a simple map containing all the fields. - */ - public Map getAllFields() { + /** Get a simple map containing all the fields. */ + public Map getAllFields() { if (hasLazyField) { - SmallSortedMap result = - SmallSortedMap.newFieldMap(16); - for (int i = 0; i < fields.getNumArrayEntries(); i++) { - cloneFieldEntry(result, fields.getArrayEntryAt(i)); - } - for (Map.Entry entry : - fields.getOverflowEntries()) { - cloneFieldEntry(result, entry); - } + SmallSortedMap result = cloneAllFieldsMap(fields, /* copyList */ false); if (fields.isImmutable()) { result.makeImmutable(); } @@ -197,51 +199,69 @@ public Map getAllFields() { return fields.isImmutable() ? fields : Collections.unmodifiableMap(fields); } - private void cloneFieldEntry(Map map, - Map.Entry entry) { - FieldDescriptorType key = entry.getKey(); + private static > SmallSortedMap cloneAllFieldsMap( + SmallSortedMap fields, boolean copyList) { + SmallSortedMap result = SmallSortedMap.newFieldMap(DEFAULT_FIELD_MAP_ARRAY_SIZE); + for (int i = 0; i < fields.getNumArrayEntries(); i++) { + cloneFieldEntry(result, fields.getArrayEntryAt(i), copyList); + } + for (Map.Entry entry : fields.getOverflowEntries()) { + cloneFieldEntry(result, entry, copyList); + } + return result; + } + + private static > void cloneFieldEntry( + Map map, Map.Entry entry, boolean copyList) { + T key = entry.getKey(); Object value = entry.getValue(); if (value instanceof LazyField) { map.put(key, ((LazyField) value).getValue()); + } else if (copyList && value instanceof List) { + map.put(key, new ArrayList<>((List) value)); } else { map.put(key, value); } } /** - * Get an iterator to the field map. This iterator should not be leaked out - * of the protobuf library as it is not protected from mutation when fields - * is not immutable. + * Get an iterator to the field map. This iterator should not be leaked out of the protobuf + * library as it is not protected from mutation when fields is not immutable. */ - public Iterator> iterator() { + public Iterator> iterator() { if (hasLazyField) { - return new LazyIterator( - fields.entrySet().iterator()); + return new LazyIterator(fields.entrySet().iterator()); } return fields.entrySet().iterator(); } - /** - * Useful for implementing - * {@link Message#hasField(Descriptors.FieldDescriptor)}. + * Get an iterator over the fields in the map in descending (i.e. reverse) order. This iterator + * should not be leaked out of the protobuf library as it is not protected from mutation when + * fields is not immutable. */ - public boolean hasField(final FieldDescriptorType descriptor) { + Iterator> descendingIterator() { + if (hasLazyField) { + return new LazyIterator(fields.descendingEntrySet().iterator()); + } + return fields.descendingEntrySet().iterator(); + } + + /** Useful for implementing {@link Message#hasField(Descriptors.FieldDescriptor)}. */ + public boolean hasField(final T descriptor) { if (descriptor.isRepeated()) { - throw new IllegalArgumentException( - "hasField() can only be called on non-repeated fields."); + throw new IllegalArgumentException("hasField() can only be called on non-repeated fields."); } return fields.get(descriptor) != null; } /** - * Useful for implementing - * {@link Message#getField(Descriptors.FieldDescriptor)}. This method - * returns {@code null} if the field is not set; in this case it is up - * to the caller to fetch the field's default value. + * Useful for implementing {@link Message#getField(Descriptors.FieldDescriptor)}. This method + * returns {@code null} if the field is not set; in this case it is up to the caller to fetch the + * field's default value. */ - public Object getField(final FieldDescriptorType descriptor) { + public Object getField(final T descriptor) { Object o = fields.get(descriptor); if (o instanceof LazyField) { return ((LazyField) o).getValue(); @@ -250,16 +270,14 @@ public Object getField(final FieldDescriptorType descriptor) { } /** - * Useful for implementing - * {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}. + * Useful for implementing {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}. */ @SuppressWarnings({"unchecked", "rawtypes"}) - public void setField(final FieldDescriptorType descriptor, - Object value) { + public void setField(final T descriptor, Object value) { if (descriptor.isRepeated()) { if (!(value instanceof List)) { throw new IllegalArgumentException( - "Wrong object type used with protocol message reflection."); + "Wrong object type used with protocol message reflection."); } // Wrap the contents in a new list so that the caller cannot change @@ -267,11 +285,11 @@ public void setField(final FieldDescriptorType descriptor, final List newList = new ArrayList(); newList.addAll((List) value); for (final Object element : newList) { - verifyType(descriptor.getLiteType(), element); + verifyType(descriptor, element); } value = newList; } else { - verifyType(descriptor.getLiteType(), value); + verifyType(descriptor, value); } if (value instanceof LazyField) { @@ -280,25 +298,19 @@ public void setField(final FieldDescriptorType descriptor, fields.put(descriptor, value); } - /** - * Useful for implementing - * {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}. - */ - public void clearField(final FieldDescriptorType descriptor) { + /** Useful for implementing {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}. */ + public void clearField(final T descriptor) { fields.remove(descriptor); if (fields.isEmpty()) { hasLazyField = false; } } - /** - * Useful for implementing - * {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}. - */ - public int getRepeatedFieldCount(final FieldDescriptorType descriptor) { + /** Useful for implementing {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}. */ + public int getRepeatedFieldCount(final T descriptor) { if (!descriptor.isRepeated()) { throw new IllegalArgumentException( - "getRepeatedField() can only be called on repeated fields."); + "getRepeatedField() can only be called on repeated fields."); } final Object value = getField(descriptor); @@ -309,15 +321,11 @@ public int getRepeatedFieldCount(final FieldDescriptorType descriptor) { } } - /** - * Useful for implementing - * {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}. - */ - public Object getRepeatedField(final FieldDescriptorType descriptor, - final int index) { + /** Useful for implementing {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}. */ + public Object getRepeatedField(final T descriptor, final int index) { if (!descriptor.isRepeated()) { throw new IllegalArgumentException( - "getRepeatedField() can only be called on repeated fields."); + "getRepeatedField() can only be called on repeated fields."); } final Object value = getField(descriptor); @@ -330,16 +338,14 @@ public Object getRepeatedField(final FieldDescriptorType descriptor, } /** - * Useful for implementing - * {@link Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}. + * Useful for implementing {@link + * Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}. */ @SuppressWarnings("unchecked") - public void setRepeatedField(final FieldDescriptorType descriptor, - final int index, - final Object value) { + public void setRepeatedField(final T descriptor, final int index, final Object value) { if (!descriptor.isRepeated()) { throw new IllegalArgumentException( - "getRepeatedField() can only be called on repeated fields."); + "getRepeatedField() can only be called on repeated fields."); } final Object list = getField(descriptor); @@ -347,23 +353,22 @@ public void setRepeatedField(final FieldDescriptorType descriptor, throw new IndexOutOfBoundsException(); } - verifyType(descriptor.getLiteType(), value); + verifyType(descriptor, value); ((List) list).set(index, value); } /** - * Useful for implementing - * {@link Message.Builder#addRepeatedField(Descriptors.FieldDescriptor,Object)}. + * Useful for implementing {@link + * Message.Builder#addRepeatedField(Descriptors.FieldDescriptor,Object)}. */ @SuppressWarnings("unchecked") - public void addRepeatedField(final FieldDescriptorType descriptor, - final Object value) { + public void addRepeatedField(final T descriptor, final Object value) { if (!descriptor.isRepeated()) { throw new IllegalArgumentException( - "addRepeatedField() can only be called on repeated fields."); + "addRepeatedField() can only be called on repeated fields."); } - verifyType(descriptor.getLiteType(), value); + verifyType(descriptor, value); final Object existingValue = getField(descriptor); List list; @@ -378,40 +383,14 @@ public void addRepeatedField(final FieldDescriptorType descriptor, } /** - * Verifies that the given object is of the correct type to be a valid - * value for the given field. (For repeated fields, this checks if the - * object is the right type to be one element of the field.) + * Verifies that the given object is of the correct type to be a valid value for the given field. + * (For repeated fields, this checks if the object is the right type to be one element of the + * field.) * * @throws IllegalArgumentException The value is not of the right type. */ - private static void verifyType(final WireFormat.FieldType type, - final Object value) { - checkNotNull(value); - - boolean isValid = false; - switch (type.getJavaType()) { - case INT: isValid = value instanceof Integer ; break; - case LONG: isValid = value instanceof Long ; break; - case FLOAT: isValid = value instanceof Float ; break; - case DOUBLE: isValid = value instanceof Double ; break; - case BOOLEAN: isValid = value instanceof Boolean ; break; - case STRING: isValid = value instanceof String ; break; - case BYTE_STRING: - isValid = value instanceof ByteString || value instanceof byte[]; - break; - case ENUM: - // TODO(kenton): Caller must do type checking here, I guess. - isValid = - (value instanceof Integer || value instanceof Internal.EnumLite); - break; - case MESSAGE: - // TODO(kenton): Caller must do type checking here, I guess. - isValid = - (value instanceof MessageLite) || (value instanceof LazyField); - break; - } - - if (!isValid) { + private void verifyType(final T descriptor, final Object value) { + if (!isValidType(descriptor.getLiteType(), value)) { // TODO(kenton): When chaining calls to setField(), it can be hard to // tell from the stack trace which exact call failed, since the whole // chain is considered one line of code. It would be nice to print @@ -420,18 +399,50 @@ private static void verifyType(final WireFormat.FieldType type, // isn't a big deal, though, since it would only really apply when using // reflection and generally people don't chain reflection setters. throw new IllegalArgumentException( - "Wrong object type used with protocol message reflection."); + String.format( + "Wrong object type used with protocol message reflection.\n" + + "Field number: %d, field java type: %s, value type: %s\n", + descriptor.getNumber(), + descriptor.getLiteType().getJavaType(), + value.getClass().getName())); } } + + private static boolean isValidType(final WireFormat.FieldType type, final Object value) { + checkNotNull(value); + switch (type.getJavaType()) { + case INT: + return value instanceof Integer; + case LONG: + return value instanceof Long; + case FLOAT: + return value instanceof Float; + case DOUBLE: + return value instanceof Double; + case BOOLEAN: + return value instanceof Boolean; + case STRING: + return value instanceof String; + case BYTE_STRING: + return value instanceof ByteString || value instanceof byte[]; + case ENUM: + // TODO(kenton): Caller must do type checking here, I guess. + return (value instanceof Integer || value instanceof Internal.EnumLite); + case MESSAGE: + // TODO(kenton): Caller must do type checking here, I guess. + return (value instanceof MessageLite) || (value instanceof LazyField); + } + return false; + } + // ================================================================= // Parsing and serialization /** - * See {@link Message#isInitialized()}. Note: Since {@code FieldSet} - * itself does not have any way of knowing about required fields that - * aren't actually present in the set, it is up to the caller to check - * that all required fields are present. + * See {@link Message#isInitialized()}. Note: Since {@code FieldSet} itself does not have any way + * of knowing about required fields that aren't actually present in the set, it is up to the + * caller to check that all required fields are present. */ public boolean isInitialized() { for (int i = 0; i < fields.getNumArrayEntries(); i++) { @@ -439,8 +450,7 @@ public boolean isInitialized() { return false; } } - for (final Map.Entry entry : - fields.getOverflowEntries()) { + for (final Map.Entry entry : fields.getOverflowEntries()) { if (!isInitialized(entry)) { return false; } @@ -449,13 +459,12 @@ public boolean isInitialized() { } @SuppressWarnings("unchecked") - private boolean isInitialized( - final Map.Entry entry) { - final FieldDescriptorType descriptor = entry.getKey(); + private static > boolean isInitialized( + final Map.Entry entry) { + final T descriptor = entry.getKey(); if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { if (descriptor.isRepeated()) { - for (final MessageLite element: - (List) entry.getValue()) { + for (final MessageLite element : (List) entry.getValue()) { if (!element.isInitialized()) { return false; } @@ -480,11 +489,9 @@ private boolean isInitialized( /** * Given a field type, return the wire type. * - * @returns One of the {@code WIRETYPE_} constants defined in - * {@link WireFormat}. + * @return One of the {@code WIRETYPE_} constants defined in {@link WireFormat}. */ - static int getWireFormatForFieldType(final WireFormat.FieldType type, - boolean isPacked) { + static int getWireFormatForFieldType(final WireFormat.FieldType type, boolean isPacked) { if (isPacked) { return WireFormat.WIRETYPE_LENGTH_DELIMITED; } else { @@ -492,21 +499,17 @@ static int getWireFormatForFieldType(final WireFormat.FieldType type, } } - /** - * Like {@link Message.Builder#mergeFrom(Message)}, but merges from another - * {@link FieldSet}. - */ - public void mergeFrom(final FieldSet other) { + /** Like {@link Message.Builder#mergeFrom(Message)}, but merges from another {@link FieldSet}. */ + public void mergeFrom(final FieldSet other) { for (int i = 0; i < other.fields.getNumArrayEntries(); i++) { mergeFromField(other.fields.getArrayEntryAt(i)); } - for (final Map.Entry entry : - other.fields.getOverflowEntries()) { + for (final Map.Entry entry : other.fields.getOverflowEntries()) { mergeFromField(entry); } } - private Object cloneIfMutable(Object value) { + private static Object cloneIfMutable(Object value) { if (value instanceof byte[]) { byte[] bytes = (byte[]) value; byte[] copy = new byte[bytes.length]; @@ -518,9 +521,8 @@ private Object cloneIfMutable(Object value) { } @SuppressWarnings({"unchecked", "rawtypes"}) - private void mergeFromField( - final Map.Entry entry) { - final FieldDescriptorType descriptor = entry.getKey(); + private void mergeFromField(final Map.Entry entry) { + final T descriptor = entry.getKey(); Object otherValue = entry.getValue(); if (otherValue instanceof LazyField) { otherValue = ((LazyField) otherValue).getValue(); @@ -529,7 +531,7 @@ private void mergeFromField( if (descriptor.isRepeated()) { Object value = getField(descriptor); if (value == null) { - value = new ArrayList(); + value = new ArrayList<>(); } for (Object element : (List) otherValue) { ((List) value).add(cloneIfMutable(element)); @@ -541,10 +543,10 @@ private void mergeFromField( fields.put(descriptor, cloneIfMutable(otherValue)); } else { // Merge the messages. - value = descriptor.internalMergeFrom( - ((MessageLite) value).toBuilder(), (MessageLite) otherValue) - .build(); - + value = + descriptor + .internalMergeFrom(((MessageLite) value).toBuilder(), (MessageLite) otherValue) + .build(); fields.put(descriptor, value); } } else { @@ -556,72 +558,58 @@ private void mergeFromField( // other class. Probably WireFormat. /** - * Read a field of any primitive type for immutable messages from a - * CodedInputStream. Enums, groups, and embedded messages are not handled by - * this method. + * Read a field of any primitive type for immutable messages from a CodedInputStream. Enums, + * groups, and embedded messages are not handled by this method. * * @param input The stream from which to read. * @param type Declared type of the field. * @param checkUtf8 When true, check that the input is valid utf8. - * @return An object representing the field's value, of the exact - * type which would be returned by - * {@link Message#getField(Descriptors.FieldDescriptor)} for - * this field. + * @return An object representing the field's value, of the exact type which would be returned by + * {@link Message#getField(Descriptors.FieldDescriptor)} for this field. */ public static Object readPrimitiveField( - CodedInputStream input, - final WireFormat.FieldType type, - boolean checkUtf8) throws IOException { + CodedInputStream input, final WireFormat.FieldType type, boolean checkUtf8) + throws IOException { if (checkUtf8) { - return WireFormat.readPrimitiveField(input, type, - WireFormat.Utf8Validation.STRICT); + return WireFormat.readPrimitiveField(input, type, WireFormat.Utf8Validation.STRICT); } else { - return WireFormat.readPrimitiveField(input, type, - WireFormat.Utf8Validation.LOOSE); + return WireFormat.readPrimitiveField(input, type, WireFormat.Utf8Validation.LOOSE); } } /** See {@link Message#writeTo(CodedOutputStream)}. */ - public void writeTo(final CodedOutputStream output) - throws IOException { + public void writeTo(final CodedOutputStream output) throws IOException { for (int i = 0; i < fields.getNumArrayEntries(); i++) { - final Map.Entry entry = - fields.getArrayEntryAt(i); + final Map.Entry entry = fields.getArrayEntryAt(i); writeField(entry.getKey(), entry.getValue(), output); } - for (final Map.Entry entry : - fields.getOverflowEntries()) { + for (final Map.Entry entry : fields.getOverflowEntries()) { writeField(entry.getKey(), entry.getValue(), output); } } - /** - * Like {@link #writeTo} but uses MessageSet wire format. - */ - public void writeMessageSetTo(final CodedOutputStream output) - throws IOException { + /** Like {@link #writeTo} but uses MessageSet wire format. */ + public void writeMessageSetTo(final CodedOutputStream output) throws IOException { for (int i = 0; i < fields.getNumArrayEntries(); i++) { writeMessageSetTo(fields.getArrayEntryAt(i), output); } - for (final Map.Entry entry : - fields.getOverflowEntries()) { + for (final Map.Entry entry : fields.getOverflowEntries()) { writeMessageSetTo(entry, output); } } - private void writeMessageSetTo( - final Map.Entry entry, - final CodedOutputStream output) throws IOException { - final FieldDescriptorType descriptor = entry.getKey(); - if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE && - !descriptor.isRepeated() && !descriptor.isPacked()) { + private void writeMessageSetTo(final Map.Entry entry, final CodedOutputStream output) + throws IOException { + final T descriptor = entry.getKey(); + if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE + && !descriptor.isRepeated() + && !descriptor.isPacked()) { Object value = entry.getValue(); if (value instanceof LazyField) { value = ((LazyField) value).getValue(); } - output.writeMessageSetExtension(entry.getKey().getNumber(), - (MessageLite) value); + output.writeMessageSetExtension(entry.getKey().getNumber(), (MessageLite) value); } else { writeField(descriptor, entry.getValue(), output); } @@ -631,18 +619,17 @@ private void writeMessageSetTo( * Write a single tag-value pair to the stream. * * @param output The output stream. - * @param type The field's type. + * @param type The field's type. * @param number The field's number. - * @param value Object representing the field's value. Must be of the exact - * type which would be returned by - * {@link Message#getField(Descriptors.FieldDescriptor)} for - * this field. + * @param value Object representing the field's value. Must be of the exact type which would be + * returned by {@link Message#getField(Descriptors.FieldDescriptor)} for this field. */ static void writeElement( final CodedOutputStream output, final WireFormat.FieldType type, final int number, - final Object value) throws IOException { + final Object value) + throws IOException { // Special case for groups, which need a start and end tag; other fields // can just use writeTag() and writeFieldNoTag(). if (type == WireFormat.FieldType.GROUP) { @@ -658,26 +645,43 @@ static void writeElement( * * @param output The output stream. * @param type The field's type. - * @param value Object representing the field's value. Must be of the exact - * type which would be returned by - * {@link Message#getField(Descriptors.FieldDescriptor)} for - * this field. + * @param value Object representing the field's value. Must be of the exact type which would be + * returned by {@link Message#getField(Descriptors.FieldDescriptor)} for this field. */ static void writeElementNoTag( - final CodedOutputStream output, - final WireFormat.FieldType type, - final Object value) throws IOException { + final CodedOutputStream output, final WireFormat.FieldType type, final Object value) + throws IOException { switch (type) { - case DOUBLE : output.writeDoubleNoTag ((Double ) value); break; - case FLOAT : output.writeFloatNoTag ((Float ) value); break; - case INT64 : output.writeInt64NoTag ((Long ) value); break; - case UINT64 : output.writeUInt64NoTag ((Long ) value); break; - case INT32 : output.writeInt32NoTag ((Integer ) value); break; - case FIXED64 : output.writeFixed64NoTag ((Long ) value); break; - case FIXED32 : output.writeFixed32NoTag ((Integer ) value); break; - case BOOL : output.writeBoolNoTag ((Boolean ) value); break; - case GROUP : output.writeGroupNoTag ((MessageLite) value); break; - case MESSAGE : output.writeMessageNoTag ((MessageLite) value); break; + case DOUBLE: + output.writeDoubleNoTag((Double) value); + break; + case FLOAT: + output.writeFloatNoTag((Float) value); + break; + case INT64: + output.writeInt64NoTag((Long) value); + break; + case UINT64: + output.writeUInt64NoTag((Long) value); + break; + case INT32: + output.writeInt32NoTag((Integer) value); + break; + case FIXED64: + output.writeFixed64NoTag((Long) value); + break; + case FIXED32: + output.writeFixed32NoTag((Integer) value); + break; + case BOOL: + output.writeBoolNoTag((Boolean) value); + break; + case GROUP: + output.writeGroupNoTag((MessageLite) value); + break; + case MESSAGE: + output.writeMessageNoTag((MessageLite) value); + break; case STRING: if (value instanceof ByteString) { output.writeBytesNoTag((ByteString) value); @@ -692,11 +696,21 @@ static void writeElementNoTag( output.writeByteArrayNoTag((byte[]) value); } break; - case UINT32 : output.writeUInt32NoTag ((Integer ) value); break; - case SFIXED32: output.writeSFixed32NoTag((Integer ) value); break; - case SFIXED64: output.writeSFixed64NoTag((Long ) value); break; - case SINT32 : output.writeSInt32NoTag ((Integer ) value); break; - case SINT64 : output.writeSInt64NoTag ((Long ) value); break; + case UINT32: + output.writeUInt32NoTag((Integer) value); + break; + case SFIXED32: + output.writeSFixed32NoTag((Integer) value); + break; + case SFIXED64: + output.writeSFixed64NoTag((Long) value); + break; + case SINT32: + output.writeSInt32NoTag((Integer) value); + break; + case SINT64: + output.writeSInt64NoTag((Long) value); + break; case ENUM: if (value instanceof Internal.EnumLite) { @@ -709,14 +723,13 @@ static void writeElementNoTag( } /** Write a single field. */ - public static void writeField(final FieldDescriptorLite descriptor, - final Object value, - final CodedOutputStream output) - throws IOException { + public static void writeField( + final FieldDescriptorLite descriptor, final Object value, final CodedOutputStream output) + throws IOException { WireFormat.FieldType type = descriptor.getLiteType(); int number = descriptor.getNumber(); if (descriptor.isRepeated()) { - final List valueList = (List)value; + final List valueList = (List) value; if (descriptor.isPacked()) { output.writeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED); // Compute the total data size so the length can be written. @@ -744,44 +757,39 @@ public static void writeField(final FieldDescriptorLite descriptor, } /** - * See {@link Message#getSerializedSize()}. It's up to the caller to cache - * the resulting size if desired. + * See {@link Message#getSerializedSize()}. It's up to the caller to cache the resulting size if + * desired. */ public int getSerializedSize() { int size = 0; for (int i = 0; i < fields.getNumArrayEntries(); i++) { - final Map.Entry entry = - fields.getArrayEntryAt(i); + final Map.Entry entry = fields.getArrayEntryAt(i); size += computeFieldSize(entry.getKey(), entry.getValue()); } - for (final Map.Entry entry : - fields.getOverflowEntries()) { + for (final Map.Entry entry : fields.getOverflowEntries()) { size += computeFieldSize(entry.getKey(), entry.getValue()); } return size; } - /** - * Like {@link #getSerializedSize} but uses MessageSet wire format. - */ + /** Like {@link #getSerializedSize} but uses MessageSet wire format. */ public int getMessageSetSerializedSize() { int size = 0; for (int i = 0; i < fields.getNumArrayEntries(); i++) { size += getMessageSetSerializedSize(fields.getArrayEntryAt(i)); } - for (final Map.Entry entry : - fields.getOverflowEntries()) { + for (final Map.Entry entry : fields.getOverflowEntries()) { size += getMessageSetSerializedSize(entry); } return size; } - private int getMessageSetSerializedSize( - final Map.Entry entry) { - final FieldDescriptorType descriptor = entry.getKey(); + private int getMessageSetSerializedSize(final Map.Entry entry) { + final T descriptor = entry.getKey(); Object value = entry.getValue(); if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE - && !descriptor.isRepeated() && !descriptor.isPacked()) { + && !descriptor.isRepeated() + && !descriptor.isPacked()) { if (value instanceof LazyField) { return CodedOutputStream.computeLazyFieldMessageSetExtensionSize( entry.getKey().getNumber(), (LazyField) value); @@ -795,15 +803,13 @@ private int getMessageSetSerializedSize( } /** - * Compute the number of bytes that would be needed to encode a - * single tag/value pair of arbitrary type. + * Compute the number of bytes that would be needed to encode a single tag/value pair of arbitrary + * type. * - * @param type The field's type. + * @param type The field's type. * @param number The field's number. - * @param value Object representing the field's value. Must be of the exact - * type which would be returned by - * {@link Message#getField(Descriptors.FieldDescriptor)} for - * this field. + * @param value Object representing the field's value. Must be of the exact type which would be + * returned by {@link Message#getField(Descriptors.FieldDescriptor)} for this field. */ static int computeElementSize( final WireFormat.FieldType type, final int number, final Object value) { @@ -817,46 +823,57 @@ static int computeElementSize( } /** - * Compute the number of bytes that would be needed to encode a - * particular value of arbitrary type, excluding tag. + * Compute the number of bytes that would be needed to encode a particular value of arbitrary + * type, excluding tag. * - * @param type The field's type. - * @param value Object representing the field's value. Must be of the exact - * type which would be returned by - * {@link Message#getField(Descriptors.FieldDescriptor)} for - * this field. + * @param type The field's type. + * @param value Object representing the field's value. Must be of the exact type which would be + * returned by {@link Message#getField(Descriptors.FieldDescriptor)} for this field. */ - static int computeElementSizeNoTag( - final WireFormat.FieldType type, final Object value) { + static int computeElementSizeNoTag(final WireFormat.FieldType type, final Object value) { switch (type) { - // Note: Minor violation of 80-char limit rule here because this would - // actually be harder to read if we wrapped the lines. - case DOUBLE : return CodedOutputStream.computeDoubleSizeNoTag ((Double )value); - case FLOAT : return CodedOutputStream.computeFloatSizeNoTag ((Float )value); - case INT64 : return CodedOutputStream.computeInt64SizeNoTag ((Long )value); - case UINT64 : return CodedOutputStream.computeUInt64SizeNoTag ((Long )value); - case INT32 : return CodedOutputStream.computeInt32SizeNoTag ((Integer )value); - case FIXED64 : return CodedOutputStream.computeFixed64SizeNoTag ((Long )value); - case FIXED32 : return CodedOutputStream.computeFixed32SizeNoTag ((Integer )value); - case BOOL : return CodedOutputStream.computeBoolSizeNoTag ((Boolean )value); - case GROUP : return CodedOutputStream.computeGroupSizeNoTag ((MessageLite)value); - case BYTES : + // Note: Minor violation of 80-char limit rule here because this would + // actually be harder to read if we wrapped the lines. + case DOUBLE: + return CodedOutputStream.computeDoubleSizeNoTag((Double) value); + case FLOAT: + return CodedOutputStream.computeFloatSizeNoTag((Float) value); + case INT64: + return CodedOutputStream.computeInt64SizeNoTag((Long) value); + case UINT64: + return CodedOutputStream.computeUInt64SizeNoTag((Long) value); + case INT32: + return CodedOutputStream.computeInt32SizeNoTag((Integer) value); + case FIXED64: + return CodedOutputStream.computeFixed64SizeNoTag((Long) value); + case FIXED32: + return CodedOutputStream.computeFixed32SizeNoTag((Integer) value); + case BOOL: + return CodedOutputStream.computeBoolSizeNoTag((Boolean) value); + case GROUP: + return CodedOutputStream.computeGroupSizeNoTag((MessageLite) value); + case BYTES: if (value instanceof ByteString) { return CodedOutputStream.computeBytesSizeNoTag((ByteString) value); } else { return CodedOutputStream.computeByteArraySizeNoTag((byte[]) value); } - case STRING : + case STRING: if (value instanceof ByteString) { return CodedOutputStream.computeBytesSizeNoTag((ByteString) value); } else { return CodedOutputStream.computeStringSizeNoTag((String) value); } - case UINT32 : return CodedOutputStream.computeUInt32SizeNoTag ((Integer )value); - case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer )value); - case SFIXED64: return CodedOutputStream.computeSFixed64SizeNoTag((Long )value); - case SINT32 : return CodedOutputStream.computeSInt32SizeNoTag ((Integer )value); - case SINT64 : return CodedOutputStream.computeSInt64SizeNoTag ((Long )value); + case UINT32: + return CodedOutputStream.computeUInt32SizeNoTag((Integer) value); + case SFIXED32: + return CodedOutputStream.computeSFixed32SizeNoTag((Integer) value); + case SFIXED64: + return CodedOutputStream.computeSFixed64SizeNoTag((Long) value); + case SINT32: + return CodedOutputStream.computeSInt32SizeNoTag((Integer) value); + case SINT64: + return CodedOutputStream.computeSInt64SizeNoTag((Long) value); case MESSAGE: if (value instanceof LazyField) { @@ -867,36 +884,31 @@ static int computeElementSizeNoTag( case ENUM: if (value instanceof Internal.EnumLite) { - return CodedOutputStream.computeEnumSizeNoTag( - ((Internal.EnumLite) value).getNumber()); + return CodedOutputStream.computeEnumSizeNoTag(((Internal.EnumLite) value).getNumber()); } else { return CodedOutputStream.computeEnumSizeNoTag((Integer) value); } } - throw new RuntimeException( - "There is no way to get here, but the compiler thinks otherwise."); + throw new RuntimeException("There is no way to get here, but the compiler thinks otherwise."); } - /** - * Compute the number of bytes needed to encode a particular field. - */ - public static int computeFieldSize(final FieldDescriptorLite descriptor, - final Object value) { + /** Compute the number of bytes needed to encode a particular field. */ + public static int computeFieldSize(final FieldDescriptorLite descriptor, final Object value) { WireFormat.FieldType type = descriptor.getLiteType(); int number = descriptor.getNumber(); if (descriptor.isRepeated()) { if (descriptor.isPacked()) { int dataSize = 0; - for (final Object element : (List)value) { + for (final Object element : (List) value) { dataSize += computeElementSizeNoTag(type, element); } - return dataSize + - CodedOutputStream.computeTagSize(number) + - CodedOutputStream.computeRawVarint32Size(dataSize); + return dataSize + + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeRawVarint32Size(dataSize); } else { int size = 0; - for (final Object element : (List)value) { + for (final Object element : (List) value) { size += computeElementSize(type, number, element); } return size; @@ -905,4 +917,390 @@ public static int computeFieldSize(final FieldDescriptorLite descriptor, return computeElementSize(type, number, value); } } + + /** + * A FieldSet Builder that accept a {@link MessageLite.Builder} as a field value. This is useful + * for implementing methods in {@link MessageLite.Builder}. + */ + static final class Builder> { + + private SmallSortedMap fields; + private boolean hasLazyField; + private boolean isMutable; + private boolean hasNestedBuilders; + + private Builder() { + this(SmallSortedMap.newFieldMap(DEFAULT_FIELD_MAP_ARRAY_SIZE)); + } + + private Builder(SmallSortedMap fields) { + this.fields = fields; + this.isMutable = true; + } + + /** Creates the FieldSet */ + public FieldSet build() { + if (fields.isEmpty()) { + return FieldSet.emptySet(); + } + isMutable = false; + SmallSortedMap fieldsForBuild = fields; + if (hasNestedBuilders) { + // Make a copy of the fields map with all Builders replaced by Message. + fieldsForBuild = cloneAllFieldsMap(fields, /* copyList */ false); + replaceBuilders(fieldsForBuild); + } + FieldSet fieldSet = new FieldSet<>(fieldsForBuild); + fieldSet.hasLazyField = hasLazyField; + return fieldSet; + } + + private static > void replaceBuilders( + SmallSortedMap fieldMap) { + for (int i = 0; i < fieldMap.getNumArrayEntries(); i++) { + replaceBuilders(fieldMap.getArrayEntryAt(i)); + } + for (Map.Entry entry : fieldMap.getOverflowEntries()) { + replaceBuilders(entry); + } + } + + private static > void replaceBuilders( + Map.Entry entry) { + entry.setValue(replaceBuilders(entry.getKey(), entry.getValue())); + } + + private static > Object replaceBuilders( + T descriptor, Object value) { + if (value == null) { + return value; + } + if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { + if (descriptor.isRepeated()) { + if (!(value instanceof List)) { + throw new IllegalStateException( + "Repeated field should contains a List but actually contains type: " + + value.getClass()); + } + @SuppressWarnings("unchecked") // We just check that value is an instance of List above. + List list = (List) value; + for (int i = 0; i < list.size(); i++) { + Object oldElement = list.get(i); + Object newElement = replaceBuilder(oldElement); + if (newElement != oldElement) { + // If the list contains a Message.Builder, then make a copy of that list and then + // modify the Message.Builder into a Message and return the new list. This way, the + // existing Message.Builder will still be able to modify the inner fields of the + // original FieldSet.Builder. + if (list == value) { + list = new ArrayList<>(list); + } + list.set(i, newElement); + } + } + return list; + } else { + return replaceBuilder(value); + } + } + return value; + } + + private static Object replaceBuilder(Object value) { + return (value instanceof MessageLite.Builder) ? ((MessageLite.Builder) value).build() : value; + } + + /** Returns a new Builder using the fields from {@code fieldSet}. */ + public static > Builder fromFieldSet(FieldSet fieldSet) { + Builder builder = new Builder(cloneAllFieldsMap(fieldSet.fields, /* copyList */ true)); + builder.hasLazyField = fieldSet.hasLazyField; + return builder; + } + + // ================================================================= + + /** Get a simple map containing all the fields. */ + public Map getAllFields() { + if (hasLazyField) { + SmallSortedMap result = cloneAllFieldsMap(fields, /* copyList */ false); + if (fields.isImmutable()) { + result.makeImmutable(); + } else { + replaceBuilders(result); + } + return result; + } + return fields.isImmutable() ? fields : Collections.unmodifiableMap(fields); + } + + /** Useful for implementing {@link Message#hasField(Descriptors.FieldDescriptor)}. */ + public boolean hasField(final T descriptor) { + if (descriptor.isRepeated()) { + throw new IllegalArgumentException("hasField() can only be called on non-repeated fields."); + } + + return fields.get(descriptor) != null; + } + + /** + * Useful for implementing {@link Message#getField(Descriptors.FieldDescriptor)}. This method + * returns {@code null} if the field is not set; in this case it is up to the caller to fetch + * the field's default value. + */ + public Object getField(final T descriptor) { + Object value = getFieldAllowBuilders(descriptor); + return replaceBuilders(descriptor, value); + } + + /** Same as {@link #getField(F)}, but allow a {@link MessageLite.Builder} to be returned. */ + Object getFieldAllowBuilders(final T descriptor) { + Object o = fields.get(descriptor); + if (o instanceof LazyField) { + return ((LazyField) o).getValue(); + } + return o; + } + + private void ensureIsMutable() { + if (!isMutable) { + fields = cloneAllFieldsMap(fields, /* copyList */ true); + isMutable = true; + } + } + + /** + * Useful for implementing {@link Message.Builder#setField(Descriptors.FieldDescriptor, + * Object)}. + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public void setField(final T descriptor, Object value) { + ensureIsMutable(); + if (descriptor.isRepeated()) { + if (!(value instanceof List)) { + throw new IllegalArgumentException( + "Wrong object type used with protocol message reflection."); + } + + // Wrap the contents in a new list so that the caller cannot change + // the list's contents after setting it. + final List newList = new ArrayList(); + newList.addAll((List) value); + for (final Object element : newList) { + verifyType(descriptor, element); + hasNestedBuilders = hasNestedBuilders || element instanceof MessageLite.Builder; + } + value = newList; + } else { + verifyType(descriptor, value); + } + + if (value instanceof LazyField) { + hasLazyField = true; + } + hasNestedBuilders = hasNestedBuilders || value instanceof MessageLite.Builder; + + fields.put(descriptor, value); + } + + /** Useful for implementing {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}. */ + public void clearField(final T descriptor) { + ensureIsMutable(); + fields.remove(descriptor); + if (fields.isEmpty()) { + hasLazyField = false; + } + } + + /** + * Useful for implementing {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}. + */ + public int getRepeatedFieldCount(final T descriptor) { + if (!descriptor.isRepeated()) { + throw new IllegalArgumentException( + "getRepeatedField() can only be called on repeated fields."); + } + + final Object value = getField(descriptor); + if (value == null) { + return 0; + } else { + return ((List) value).size(); + } + } + + /** + * Useful for implementing {@link Message#getRepeatedField(Descriptors.FieldDescriptor, int)}. + */ + public Object getRepeatedField(final T descriptor, final int index) { + if (hasNestedBuilders) { + ensureIsMutable(); + } + Object value = getRepeatedFieldAllowBuilders(descriptor, index); + return replaceBuilder(value); + } + + /** + * Same as {@link #getRepeatedField(F, int)}, but allow a {@link MessageLite.Builder} to be + * returned. + */ + Object getRepeatedFieldAllowBuilders(final T descriptor, final int index) { + if (!descriptor.isRepeated()) { + throw new IllegalArgumentException( + "getRepeatedField() can only be called on repeated fields."); + } + + final Object value = getFieldAllowBuilders(descriptor); + + if (value == null) { + throw new IndexOutOfBoundsException(); + } else { + return ((List) value).get(index); + } + } + + /** + * Useful for implementing {@link Message.Builder#setRepeatedField(Descriptors.FieldDescriptor, + * int, Object)}. + */ + @SuppressWarnings("unchecked") + public void setRepeatedField(final T descriptor, final int index, final Object value) { + ensureIsMutable(); + if (!descriptor.isRepeated()) { + throw new IllegalArgumentException( + "getRepeatedField() can only be called on repeated fields."); + } + + hasNestedBuilders = hasNestedBuilders || value instanceof MessageLite.Builder; + + final Object list = getField(descriptor); + if (list == null) { + throw new IndexOutOfBoundsException(); + } + + verifyType(descriptor, value); + ((List) list).set(index, value); + } + + /** + * Useful for implementing {@link Message.Builder#addRepeatedField(Descriptors.FieldDescriptor, + * Object)}. + */ + @SuppressWarnings("unchecked") + public void addRepeatedField(final T descriptor, final Object value) { + ensureIsMutable(); + if (!descriptor.isRepeated()) { + throw new IllegalArgumentException( + "addRepeatedField() can only be called on repeated fields."); + } + + hasNestedBuilders = hasNestedBuilders || value instanceof MessageLite.Builder; + + verifyType(descriptor, value); + + final Object existingValue = getField(descriptor); + List list; + if (existingValue == null) { + list = new ArrayList<>(); + fields.put(descriptor, list); + } else { + list = (List) existingValue; + } + + list.add(value); + } + + /** + * Verifies that the given object is of the correct type to be a valid value for the given + * field. (For repeated fields, this checks if the object is the right type to be one element of + * the field.) + * + * @throws IllegalArgumentException The value is not of the right type. + */ + private void verifyType(final T descriptor, final Object value) { + if (!FieldSet.isValidType(descriptor.getLiteType(), value)) { + // Builder can accept Message.Builder values even though FieldSet will reject. + if (descriptor.getLiteType().getJavaType() == WireFormat.JavaType.MESSAGE + && value instanceof MessageLite.Builder) { + return; + } + throw new IllegalArgumentException( + String.format( + "Wrong object type used with protocol message reflection.\n" + + "Field number: %d, field java type: %s, value type: %s\n", + descriptor.getNumber(), + descriptor.getLiteType().getJavaType(), + value.getClass().getName())); + } + } + + /** + * See {@link Message#isInitialized()}. Note: Since {@code FieldSet} itself does not have any + * way of knowing about required fields that aren't actually present in the set, it is up to the + * caller to check that all required fields are present. + */ + public boolean isInitialized() { + for (int i = 0; i < fields.getNumArrayEntries(); i++) { + if (!FieldSet.isInitialized(fields.getArrayEntryAt(i))) { + return false; + } + } + for (final Map.Entry entry : fields.getOverflowEntries()) { + if (!FieldSet.isInitialized(entry)) { + return false; + } + } + return true; + } + + /** + * Like {@link Message.Builder#mergeFrom(Message)}, but merges from another {@link FieldSet}. + */ + public void mergeFrom(final FieldSet other) { + ensureIsMutable(); + for (int i = 0; i < other.fields.getNumArrayEntries(); i++) { + mergeFromField(other.fields.getArrayEntryAt(i)); + } + for (final Map.Entry entry : other.fields.getOverflowEntries()) { + mergeFromField(entry); + } + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private void mergeFromField(final Map.Entry entry) { + final T descriptor = entry.getKey(); + Object otherValue = entry.getValue(); + if (otherValue instanceof LazyField) { + otherValue = ((LazyField) otherValue).getValue(); + } + + if (descriptor.isRepeated()) { + Object value = getField(descriptor); + if (value == null) { + value = new ArrayList<>(); + } + for (Object element : (List) otherValue) { + ((List) value).add(FieldSet.cloneIfMutable(element)); + } + fields.put(descriptor, value); + } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { + Object value = getField(descriptor); + if (value == null) { + fields.put(descriptor, FieldSet.cloneIfMutable(otherValue)); + } else { + // Merge the messages. + if (value instanceof MessageLite.Builder) { + descriptor.internalMergeFrom((MessageLite.Builder) value, (MessageLite) otherValue); + } else { + value = + descriptor + .internalMergeFrom(((MessageLite) value).toBuilder(), (MessageLite) otherValue) + .build(); + fields.put(descriptor, value); + } + } + } else { + fields.put(descriptor, cloneIfMutable(otherValue)); + } + } + } } diff --git a/java/core/src/main/java/com/google/protobuf/FieldType.java b/java/core/src/main/java/com/google/protobuf/FieldType.java new file mode 100644 index 0000000000000..72327537fd204 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/FieldType.java @@ -0,0 +1,344 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.List; + +/** Enumeration identifying all relevant type information for a protobuf field. */ +@ExperimentalApi +public enum FieldType { + DOUBLE(0, Collection.SCALAR, JavaType.DOUBLE), + FLOAT(1, Collection.SCALAR, JavaType.FLOAT), + INT64(2, Collection.SCALAR, JavaType.LONG), + UINT64(3, Collection.SCALAR, JavaType.LONG), + INT32(4, Collection.SCALAR, JavaType.INT), + FIXED64(5, Collection.SCALAR, JavaType.LONG), + FIXED32(6, Collection.SCALAR, JavaType.INT), + BOOL(7, Collection.SCALAR, JavaType.BOOLEAN), + STRING(8, Collection.SCALAR, JavaType.STRING), + MESSAGE(9, Collection.SCALAR, JavaType.MESSAGE), + BYTES(10, Collection.SCALAR, JavaType.BYTE_STRING), + UINT32(11, Collection.SCALAR, JavaType.INT), + ENUM(12, Collection.SCALAR, JavaType.ENUM), + SFIXED32(13, Collection.SCALAR, JavaType.INT), + SFIXED64(14, Collection.SCALAR, JavaType.LONG), + SINT32(15, Collection.SCALAR, JavaType.INT), + SINT64(16, Collection.SCALAR, JavaType.LONG), + GROUP(17, Collection.SCALAR, JavaType.MESSAGE), + DOUBLE_LIST(18, Collection.VECTOR, JavaType.DOUBLE), + FLOAT_LIST(19, Collection.VECTOR, JavaType.FLOAT), + INT64_LIST(20, Collection.VECTOR, JavaType.LONG), + UINT64_LIST(21, Collection.VECTOR, JavaType.LONG), + INT32_LIST(22, Collection.VECTOR, JavaType.INT), + FIXED64_LIST(23, Collection.VECTOR, JavaType.LONG), + FIXED32_LIST(24, Collection.VECTOR, JavaType.INT), + BOOL_LIST(25, Collection.VECTOR, JavaType.BOOLEAN), + STRING_LIST(26, Collection.VECTOR, JavaType.STRING), + MESSAGE_LIST(27, Collection.VECTOR, JavaType.MESSAGE), + BYTES_LIST(28, Collection.VECTOR, JavaType.BYTE_STRING), + UINT32_LIST(29, Collection.VECTOR, JavaType.INT), + ENUM_LIST(30, Collection.VECTOR, JavaType.ENUM), + SFIXED32_LIST(31, Collection.VECTOR, JavaType.INT), + SFIXED64_LIST(32, Collection.VECTOR, JavaType.LONG), + SINT32_LIST(33, Collection.VECTOR, JavaType.INT), + SINT64_LIST(34, Collection.VECTOR, JavaType.LONG), + DOUBLE_LIST_PACKED(35, Collection.PACKED_VECTOR, JavaType.DOUBLE), + FLOAT_LIST_PACKED(36, Collection.PACKED_VECTOR, JavaType.FLOAT), + INT64_LIST_PACKED(37, Collection.PACKED_VECTOR, JavaType.LONG), + UINT64_LIST_PACKED(38, Collection.PACKED_VECTOR, JavaType.LONG), + INT32_LIST_PACKED(39, Collection.PACKED_VECTOR, JavaType.INT), + FIXED64_LIST_PACKED(40, Collection.PACKED_VECTOR, JavaType.LONG), + FIXED32_LIST_PACKED(41, Collection.PACKED_VECTOR, JavaType.INT), + BOOL_LIST_PACKED(42, Collection.PACKED_VECTOR, JavaType.BOOLEAN), + UINT32_LIST_PACKED(43, Collection.PACKED_VECTOR, JavaType.INT), + ENUM_LIST_PACKED(44, Collection.PACKED_VECTOR, JavaType.ENUM), + SFIXED32_LIST_PACKED(45, Collection.PACKED_VECTOR, JavaType.INT), + SFIXED64_LIST_PACKED(46, Collection.PACKED_VECTOR, JavaType.LONG), + SINT32_LIST_PACKED(47, Collection.PACKED_VECTOR, JavaType.INT), + SINT64_LIST_PACKED(48, Collection.PACKED_VECTOR, JavaType.LONG), + GROUP_LIST(49, Collection.VECTOR, JavaType.MESSAGE), + MAP(50, Collection.MAP, JavaType.VOID); + + private final JavaType javaType; + private final int id; + private final Collection collection; + private final Class elementType; + private final boolean primitiveScalar; + + FieldType(int id, Collection collection, JavaType javaType) { + this.id = id; + this.collection = collection; + this.javaType = javaType; + + switch (collection) { + case MAP: + elementType = javaType.getBoxedType(); + break; + case VECTOR: + elementType = javaType.getBoxedType(); + break; + case SCALAR: + default: + elementType = null; + break; + } + + boolean primitiveScalar = false; + if (collection == Collection.SCALAR) { + switch (javaType) { + case BYTE_STRING: + case MESSAGE: + case STRING: + break; + default: + primitiveScalar = true; + break; + } + } + this.primitiveScalar = primitiveScalar; + } + + /** A reliable unique identifier for this type. */ + public int id() { + return id; + } + + /** + * Gets the {@link JavaType} for this field. For lists, this identifies the type of the elements + * contained within the list. + */ + public JavaType getJavaType() { + return javaType; + } + + /** Indicates whether a list field should be represented on the wire in packed form. */ + public boolean isPacked() { + return Collection.PACKED_VECTOR.equals(collection); + } + + /** + * Indicates whether this field type represents a primitive scalar value. If this is {@code true}, + * then {@link #isScalar()} will also be {@code true}. + */ + public boolean isPrimitiveScalar() { + return primitiveScalar; + } + + /** Indicates whether this field type represents a scalar value. */ + public boolean isScalar() { + return collection == Collection.SCALAR; + } + + /** Indicates whether this field represents a list of values. */ + public boolean isList() { + return collection.isList(); + } + + /** Indicates whether this field represents a map. */ + public boolean isMap() { + return collection == Collection.MAP; + } + + /** Indicates whether or not this {@link FieldType} can be applied to the given {@link Field}. */ + public boolean isValidForField(Field field) { + if (Collection.VECTOR.equals(collection)) { + return isValidForList(field); + } else { + return javaType.getType().isAssignableFrom(field.getType()); + } + } + + private boolean isValidForList(Field field) { + Class clazz = field.getType(); + if (!javaType.getType().isAssignableFrom(clazz)) { + // The field isn't a List type. + return false; + } + Type[] types = EMPTY_TYPES; + Type genericType = field.getGenericType(); + if (genericType instanceof ParameterizedType) { + types = ((ParameterizedType) field.getGenericType()).getActualTypeArguments(); + } + Type listParameter = getListParameter(clazz, types); + if (!(listParameter instanceof Class)) { + // It's a wildcard, we should allow anything in the list. + return true; + } + return elementType.isAssignableFrom((Class) listParameter); + } + + /** + * Looks up the appropriate {@link FieldType} by it's identifier. + * + * @return the {@link FieldType} or {@code null} if not found. + */ + public static FieldType forId(int id) { + if (id < 0 || id >= VALUES.length) { + return null; + } + return VALUES[id]; + } + + private static final FieldType[] VALUES; + private static final Type[] EMPTY_TYPES = new Type[0]; + + static { + FieldType[] values = values(); + VALUES = new FieldType[values.length]; + for (FieldType type : values) { + VALUES[type.id] = type; + } + } + + /** + * Given a class, finds a generic super class or interface that extends {@link List}. + * + * @return the generic super class/interface, or {@code null} if not found. + */ + private static Type getGenericSuperList(Class clazz) { + // First look at interfaces. + Type[] genericInterfaces = clazz.getGenericInterfaces(); + for (Type genericInterface : genericInterfaces) { + if (genericInterface instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) genericInterface; + Class rawType = (Class) parameterizedType.getRawType(); + if (List.class.isAssignableFrom(rawType)) { + return genericInterface; + } + } + } + + // Try the subclass + Type type = clazz.getGenericSuperclass(); + if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) type; + Class rawType = (Class) parameterizedType.getRawType(); + if (List.class.isAssignableFrom(rawType)) { + return type; + } + } + + // No super class/interface extends List. + return null; + } + + /** + * Inspects the inheritance hierarchy for the given class and finds the generic type parameter for + * {@link List}. + * + * @param clazz the class to begin the search. + * @param realTypes the array of actual type parameters for {@code clazz}. These will be used to + * substitute generic parameters up the inheritance hierarchy. If {@code clazz} does not have + * any generic parameters, this list should be empty. + * @return the {@link List} parameter. + */ + private static Type getListParameter(Class clazz, Type[] realTypes) { + top: + while (clazz != List.class) { + // First look at generic subclass and interfaces. + Type genericType = getGenericSuperList(clazz); + if (genericType instanceof ParameterizedType) { + // Replace any generic parameters with the real values. + ParameterizedType parameterizedType = (ParameterizedType) genericType; + Type[] superArgs = parameterizedType.getActualTypeArguments(); + for (int i = 0; i < superArgs.length; ++i) { + Type superArg = superArgs[i]; + if (superArg instanceof TypeVariable) { + // Get the type variables for this class so that we can match them to the variables + // used on the super class. + TypeVariable[] clazzParams = clazz.getTypeParameters(); + if (realTypes.length != clazzParams.length) { + throw new RuntimeException("Type array mismatch"); + } + + // Replace the variable parameter with the real type. + boolean foundReplacement = false; + for (int j = 0; j < clazzParams.length; ++j) { + if (superArg == clazzParams[j]) { + Type realType = realTypes[j]; + superArgs[i] = realType; + foundReplacement = true; + break; + } + } + if (!foundReplacement) { + throw new RuntimeException("Unable to find replacement for " + superArg); + } + } + } + + Class parent = (Class) parameterizedType.getRawType(); + + realTypes = superArgs; + clazz = parent; + continue; + } + + // None of the parameterized types inherit List. Just continue up the inheritance hierarchy + // toward the List interface until we can identify the parameters. + realTypes = EMPTY_TYPES; + for (Class iface : clazz.getInterfaces()) { + if (List.class.isAssignableFrom(iface)) { + clazz = iface; + continue top; + } + } + clazz = clazz.getSuperclass(); + } + + if (realTypes.length != 1) { + throw new RuntimeException("Unable to identify parameter type for List"); + } + return realTypes[0]; + } + + enum Collection { + SCALAR(false), + VECTOR(true), + PACKED_VECTOR(true), + MAP(false); + + private final boolean isList; + + Collection(boolean isList) { + this.isList = isList; + } + + /** @return the isList */ + public boolean isList() { + return isList; + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java index 76645583ebb1f..e6feba8a354c2 100644 --- a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java @@ -45,7 +45,7 @@ final class FloatArrayList extends AbstractProtobufList implements FloatList, RandomAccess, PrimitiveNonBoxingCollection { - private static final FloatArrayList EMPTY_LIST = new FloatArrayList(); + private static final FloatArrayList EMPTY_LIST = new FloatArrayList(new float[0], 0); static { EMPTY_LIST.makeImmutable(); } @@ -54,9 +54,7 @@ public static FloatArrayList emptyList() { return EMPTY_LIST; } - /** - * The backing store for the list. - */ + /** The backing store for the list. */ private float[] array; /** @@ -65,22 +63,31 @@ public static FloatArrayList emptyList() { */ private int size; - /** - * Constructs a new mutable {@code FloatArrayList} with default capacity. - */ + /** Constructs a new mutable {@code FloatArrayList} with default capacity. */ FloatArrayList() { this(new float[DEFAULT_CAPACITY], 0); } /** - * Constructs a new mutable {@code FloatArrayList} - * containing the same elements as {@code other}. + * Constructs a new mutable {@code FloatArrayList} containing the same elements as {@code other}. */ private FloatArrayList(float[] other, int size) { array = other; this.size = size; } + @Override + protected void removeRange(int fromIndex, int toIndex) { + ensureIsMutable(); + if (toIndex < fromIndex) { + throw new IndexOutOfBoundsException("toIndex < fromIndex"); + } + + System.arraycopy(array, toIndex, array, fromIndex, size - toIndex); + size -= (toIndex - fromIndex); + modCount++; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -96,7 +103,7 @@ public boolean equals(Object o) { final float[] arr = other.array; for (int i = 0; i < size; i++) { - if (array[i] != arr[i]) { + if (Float.floatToIntBits(array[i]) != Float.floatToIntBits(arr[i])) { return false; } } @@ -132,6 +139,26 @@ public float getFloat(int index) { return array[index]; } + @Override + public int indexOf(Object element) { + if (!(element instanceof Float)) { + return -1; + } + float unboxedElement = (Float) element; + int numElems = size(); + for (int i = 0; i < numElems; i++) { + if (array[i] == unboxedElement) { + return i; + } + } + return -1; + } + + @Override + public boolean contains(Object element) { + return indexOf(element) != -1; + } + @Override public int size() { return size; @@ -151,22 +178,34 @@ public float setFloat(int index, float element) { return previousValue; } + @Override + public boolean add(Float element) { + addFloat(element); + return true; + } + @Override public void add(int index, Float element) { addFloat(index, element); } - /** - * Like {@link #add(Float)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(Float)} but more efficient in that it doesn't box the element. */ @Override public void addFloat(float element) { - addFloat(size, element); + ensureIsMutable(); + if (size == array.length) { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + float[] newArray = new float[length]; + + System.arraycopy(array, 0, newArray, 0, size); + array = newArray; + } + + array[size++] = element; } - /** - * Like {@link #add(int, Float)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(int, Float)} but more efficient in that it doesn't box the element. */ private void addFloat(int index, float element) { ensureIsMutable(); if (index < 0 || index > size) { @@ -227,26 +266,14 @@ public boolean addAll(Collection collection) { return true; } - @Override - public boolean remove(Object o) { - ensureIsMutable(); - for (int i = 0; i < size; i++) { - if (o.equals(array[i])) { - System.arraycopy(array, i + 1, array, i, size - i); - size--; - modCount++; - return true; - } - } - return false; - } - @Override public Float remove(int index) { ensureIsMutable(); ensureIndexInRange(index); float value = array[index]; - System.arraycopy(array, index + 1, array, index, size - index); + if (index < size - 1) { + System.arraycopy(array, index + 1, array, index, size - index - 1); + } size--; modCount++; return value; diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java index 60179e371d838..de0ee11b7e469 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java @@ -359,7 +359,7 @@ protected void makeExtensionsImmutable() { * TODO(xiaofeng): remove this after b/29368482 is fixed. We need to move this * interface to AbstractMessage in order to versioning GeneratedMessage but * this move breaks binary compatibility for AppEngine. After AppEngine is - * fixed we can exlude this from google3. + * fixed we can exclude this from google3. */ protected interface BuilderParent extends AbstractMessage.BuilderParent {} @@ -3014,7 +3014,7 @@ Extension checkNotLite( return (Extension) extension; } - + protected static int computeStringSize(final int fieldNumber, final Object value) { if (value instanceof String) { return CodedOutputStream.computeStringSize(fieldNumber, (String) value); @@ -3022,7 +3022,7 @@ protected static int computeStringSize(final int fieldNumber, final Object value return CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) value); } } - + protected static int computeStringSizeNoTag(final Object value) { if (value instanceof String) { return CodedOutputStream.computeStringSizeNoTag((String) value); @@ -3030,7 +3030,7 @@ protected static int computeStringSizeNoTag(final Object value) { return CodedOutputStream.computeBytesSizeNoTag((ByteString) value); } } - + protected static void writeString( CodedOutputStream output, final int fieldNumber, final Object value) throws IOException { if (value instanceof String) { @@ -3039,7 +3039,7 @@ protected static void writeString( output.writeBytes(fieldNumber, (ByteString) value); } } - + protected static void writeStringNoTag( CodedOutputStream output, final Object value) throws IOException { if (value instanceof String) { diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageInfoFactory.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageInfoFactory.java new file mode 100644 index 0000000000000..3e3efb929bc36 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageInfoFactory.java @@ -0,0 +1,65 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** A factory for message info that is generated into the message itself. */ +@ExperimentalApi +class GeneratedMessageInfoFactory implements MessageInfoFactory { + + private static final GeneratedMessageInfoFactory instance = new GeneratedMessageInfoFactory(); + + // Disallow construction - it's a singleton. + private GeneratedMessageInfoFactory() {} + + public static GeneratedMessageInfoFactory getInstance() { + return instance; + } + + @Override + public boolean isSupported(Class messageType) { + return GeneratedMessageLite.class.isAssignableFrom(messageType); + } + + @Override + public MessageInfo messageInfoFor(Class messageType) { + if (!GeneratedMessageLite.class.isAssignableFrom(messageType)) { + throw new IllegalArgumentException("Unsupported message type: " + messageType.getName()); + } + + try { + return (MessageInfo) GeneratedMessageLite.getDefaultInstance( + messageType.asSubclass(GeneratedMessageLite.class)) + .buildMessageInfo(); + } catch (Exception e) { + throw new RuntimeException("Unable to get message info for " + messageType.getName(), e); + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java index 7116ae1c28421..5e3ee0f75549e 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java @@ -31,10 +31,8 @@ package com.google.protobuf; import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream; -import com.google.protobuf.GeneratedMessageLite.EqualsVisitor.NotEqualsException; import com.google.protobuf.Internal.BooleanList; import com.google.protobuf.Internal.DoubleList; -import com.google.protobuf.Internal.EnumLiteMap; import com.google.protobuf.Internal.FloatList; import com.google.protobuf.Internal.IntList; import com.google.protobuf.Internal.LongList; @@ -52,6 +50,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Lite version of {@link GeneratedMessage}. @@ -59,14 +58,14 @@ * @author kenton@google.com Kenton Varda */ public abstract class GeneratedMessageLite< - MessageType extends GeneratedMessageLite, - BuilderType extends GeneratedMessageLite.Builder> - extends AbstractMessageLite { + MessageType extends GeneratedMessageLite, + BuilderType extends GeneratedMessageLite.Builder> + extends AbstractMessageLite { /** For use by generated code only. Lazily initialized to reduce allocations. */ protected UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance(); - /** For use by generated code only. */ + /** For use by generated code only. */ protected int memoizedSerializedSize = -1; @Override @@ -92,11 +91,11 @@ public final BuilderType newBuilderForType() { * binary size down. The first line of the {@code toString()} representation includes a commented * version of {@code super.toString()} to act as an indicator that this should not be relied on * for comparisons. - *

- * NOTE: This method relies on the field getter methods not being stripped or renamed by proguard. - * If they are, the fields will not be included in the returned string representation. - *

- * NOTE: This implementation is liable to change in the future, and should not be relied on in + * + *

NOTE: This method relies on the field getter methods not being stripped or renamed by + * proguard. If they are, the fields will not be included in the returned string representation. + * + *

NOTE: This implementation is liable to change in the future, and should not be relied on in * code. */ @Override @@ -110,68 +109,34 @@ public int hashCode() { if (memoizedHashCode != 0) { return memoizedHashCode; } - HashCodeVisitor visitor = new HashCodeVisitor(); - visit(visitor, (MessageType) this); - memoizedHashCode = visitor.hashCode; - return memoizedHashCode; - } - - @SuppressWarnings("unchecked") // Guaranteed by runtime - int hashCode(HashCodeVisitor visitor) { - if (memoizedHashCode == 0) { - int inProgressHashCode = visitor.hashCode; - visitor.hashCode = 0; - visit(visitor, (MessageType) this); - memoizedHashCode = visitor.hashCode; - visitor.hashCode = inProgressHashCode; - } + memoizedHashCode = Protobuf.getInstance().schemaFor(this).hashCode(this); return memoizedHashCode; } @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime @Override - public boolean equals(Object other) { + public boolean equals( + Object other) { if (this == other) { return true; } - if (!getDefaultInstanceForType().getClass().isInstance(other)) { + if (other == null) { return false; } - - try { - visit(EqualsVisitor.INSTANCE, (MessageType) other); - } catch (NotEqualsException e) { - return false; - } - return true; - } - - /** - * Same as {@link #equals(Object)} but throws {@code NotEqualsException}. - */ - @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime - boolean equals(EqualsVisitor visitor, MessageLite other) { - if (this == other) { - return true; - } - - if (!getDefaultInstanceForType().getClass().isInstance(other)) { + if (this.getClass() != other.getClass()) { return false; } - visit(visitor, (MessageType) other); - return true; + return Protobuf.getInstance().schemaFor(this).equals(this, (MessageType) other); } // The general strategy for unknown fields is to use an UnknownFieldSetLite that is treated as // mutable during the parsing constructor and immutable after. This allows us to avoid // any unnecessary intermediary allocations while reducing the generated code size. - /** - * Lazily initializes unknown fields. - */ + /** Lazily initializes unknown fields. */ private final void ensureUnknownFieldsInitialized() { if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) { unknownFields = UnknownFieldSetLite.newInstance(); @@ -193,34 +158,40 @@ protected boolean parseUnknownField(int tag, CodedInputStream input) throws IOEx return unknownFields.mergeFieldFrom(tag, input); } - /** - * Called by subclasses to parse an unknown field. For use by generated code only. - */ + /** Called by subclasses to parse an unknown field. For use by generated code only. */ protected void mergeVarintField(int tag, int value) { ensureUnknownFieldsInitialized(); unknownFields.mergeVarintField(tag, value); } - /** - * Called by subclasses to parse an unknown field. For use by generated code only. - */ + /** Called by subclasses to parse an unknown field. For use by generated code only. */ protected void mergeLengthDelimitedField(int fieldNumber, ByteString value) { ensureUnknownFieldsInitialized(); unknownFields.mergeLengthDelimitedField(fieldNumber, value); } - /** - * Called by subclasses to complete parsing. For use by generated code only. - */ + /** Called by subclasses to complete parsing. For use by generated code only. */ protected void makeImmutable() { - dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE); + Protobuf.getInstance().schemaFor(this).makeImmutable(this); + } - unknownFields.makeImmutable(); + protected final < + MessageType extends GeneratedMessageLite, + BuilderType extends GeneratedMessageLite.Builder> + BuilderType createBuilder() { + return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER); + } + + protected final < + MessageType extends GeneratedMessageLite, + BuilderType extends GeneratedMessageLite.Builder> + BuilderType createBuilder(MessageType prototype) { + return ((BuilderType) createBuilder()).mergeFrom(prototype); } @Override public final boolean isInitialized() { - return dynamicMethod(MethodToInvoke.IS_INITIALIZED, Boolean.TRUE) != null; + return isInitialized((MessageType) this, Boolean.TRUE); } @Override @@ -234,17 +205,16 @@ public final BuilderType toBuilder() { /** * Defines which method path to invoke in {@link GeneratedMessageLite * #dynamicMethod(MethodToInvoke, Object...)}. - *

- * For use by generated code only. + * + *

For use by generated code only. */ public static enum MethodToInvoke { // Rely on/modify instance state - IS_INITIALIZED, - VISIT, - MERGE_FROM_STREAM, - MAKE_IMMUTABLE, + GET_MEMOIZED_IS_INITIALIZED, + SET_MEMOIZED_IS_INITIALIZED, // Rely on static state + BUILD_MESSAGE_INFO, NEW_MUTABLE_INSTANCE, NEW_BUILDER, GET_DEFAULT_INSTANCE, @@ -253,53 +223,110 @@ public static enum MethodToInvoke { /** * A method that implements different types of operations described in {@link MethodToInvoke}. - * Theses different kinds of operations are required to implement message-level operations for + * These different kinds of operations are required to implement message-level operations for * builders in the runtime. This method bundles those operations to reduce the generated methods * count. + * *

    - *
  • {@code MERGE_FROM_STREAM} is parameterized with an {@link CodedInputStream} and - * {@link ExtensionRegistryLite}. It consumes the input stream, parsing the contents into the - * returned protocol buffer. If parsing throws an {@link InvalidProtocolBufferException}, the - * implementation wraps it in a RuntimeException. - *
  • {@code NEW_INSTANCE} returns a new instance of the protocol buffer that has not yet been - * made immutable. See {@code MAKE_IMMUTABLE}. - *
  • {@code IS_INITIALIZED} is parameterized with a {@code Boolean} detailing whether to - * memoize. It returns {@code null} for false and the default instance for true. We optionally - * memoize to support the Builder case, where memoization is not desired. - *
  • {@code NEW_BUILDER} returns a {@code BuilderType} instance. - *
  • {@code VISIT} is parameterized with a {@code Visitor} and a {@code MessageType} and - * recursively iterates through the fields side by side between this and the instance. - *
  • {@code MAKE_IMMUTABLE} sets all internal fields to an immutable state. + *
  • {@code NEW_INSTANCE} returns a new instance of the protocol buffer that has not yet been + * made immutable. See {@code MAKE_IMMUTABLE}. + *
  • {@code IS_INITIALIZED} returns {@code null} for false and the default instance for true. + * It doesn't use or modify any memoized value. + *
  • {@code GET_MEMOIZED_IS_INITIALIZED} returns the memoized {@code isInitialized} byte + * value. + *
  • {@code SET_MEMOIZED_IS_INITIALIZED} sets the memoized {@code isInitialized} byte value to + * 1 if the first parameter is not null, or to 0 if the first parameter is null. + *
  • {@code NEW_BUILDER} returns a {@code BuilderType} instance. *
+ * * This method, plus the implementation of the Builder, enables the Builder class to be proguarded * away entirely on Android. - *

- * For use by generated code only. + * + *

For use by generated code only. */ protected abstract Object dynamicMethod(MethodToInvoke method, Object arg0, Object arg1); - /** - * Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding. - */ + /** Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding. */ protected Object dynamicMethod(MethodToInvoke method, Object arg0) { return dynamicMethod(method, arg0, null); } - /** - * Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding. - */ + /** Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding. */ protected Object dynamicMethod(MethodToInvoke method) { return dynamicMethod(method, null, null); } - void visit(Visitor visitor, MessageType other) { - dynamicMethod(MethodToInvoke.VISIT, visitor, other); - unknownFields = visitor.visitUnknownFields(unknownFields, other.unknownFields); + @Override + int getMemoizedSerializedSize() { + return memoizedSerializedSize; + } + + @Override + void setMemoizedSerializedSize(int size) { + memoizedSerializedSize = size; + } + + @Override + public void writeTo(CodedOutputStream output) throws IOException { + Protobuf.getInstance() + .schemaFor(this) + .writeTo(this, CodedOutputStreamWriter.forCodedOutput(output)); + } + + @Override + public int getSerializedSize() { + if (memoizedSerializedSize == -1) { + memoizedSerializedSize = Protobuf.getInstance().schemaFor(this).getSerializedSize(this); + } + return memoizedSerializedSize; + } + + /** Constructs a {@link MessageInfo} for this message type. */ + Object buildMessageInfo() throws Exception { + return dynamicMethod(MethodToInvoke.BUILD_MESSAGE_INFO); + } + + private static Map> defaultInstanceMap = + new ConcurrentHashMap>(); + + @SuppressWarnings("unchecked") + static > T getDefaultInstance(Class clazz) { + T result = (T) defaultInstanceMap.get(clazz); + if (result == null) { + // Foo.class does not initialize the class so we need to force the initialization in order to + // get the default instance registered. + try { + Class.forName(clazz.getName(), true, clazz.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Class initialization cannot fail.", e); + } + result = (T) defaultInstanceMap.get(clazz); + } + if (result == null) { + // On some Samsung devices, this still doesn't return a valid value for some reason. We add a + // reflective fallback to keep the device running. See b/114675342. + result = (T) UnsafeUtil.allocateInstance(clazz).getDefaultInstanceForType(); + // A sanity check to ensure that was actually invoked. + if (result == null) { + throw new IllegalStateException(); + } + defaultInstanceMap.put(clazz, result); + } + return result; + } + + protected static > void registerDefaultInstance( + Class clazz, T defaultInstance) { + defaultInstanceMap.put(clazz, defaultInstance); + } + + protected static Object newMessageInfo( + MessageLite defaultInstance, String info, Object[] objects) { + return new RawMessageInfo(defaultInstance, info, objects); } /** - * Merge some unknown fields into the {@link UnknownFieldSetLite} for this - * message. + * Merge some unknown fields into the {@link UnknownFieldSetLite} for this message. * *

For use by generated code only. */ @@ -309,9 +336,9 @@ protected final void mergeUnknownFields(UnknownFieldSetLite unknownFields) { @SuppressWarnings("unchecked") public abstract static class Builder< - MessageType extends GeneratedMessageLite, - BuilderType extends Builder> - extends AbstractMessageLite.Builder { + MessageType extends GeneratedMessageLite, + BuilderType extends Builder> + extends AbstractMessageLite.Builder { private final MessageType defaultInstance; protected MessageType instance; @@ -325,22 +352,26 @@ protected Builder(MessageType defaultInstance) { } /** - * Called before any method that would mutate the builder to ensure that it correctly copies - * any state before the write happens to preserve immutability guarantees. + * Called before any method that would mutate the builder to ensure that it correctly copies any + * state before the write happens to preserve immutability guarantees. */ - protected void copyOnWrite() { + protected final void copyOnWrite() { if (isBuilt) { - MessageType newInstance = - (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE); - mergeFromInstance(newInstance, instance); - instance = newInstance; + copyOnWriteInternal(); isBuilt = false; } } + protected void copyOnWriteInternal() { + MessageType newInstance = + (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE); + mergeFromInstance(newInstance, instance); + instance = newInstance; + } + @Override public final boolean isInitialized() { - return GeneratedMessageLite.isInitialized(instance, false /* shouldMemoize */); + return GeneratedMessageLite.isInitialized(instance, /* shouldMemoize= */ false); } @Override @@ -352,8 +383,7 @@ public final BuilderType clear() { @Override public BuilderType clone() { - BuilderType builder = - (BuilderType) getDefaultInstanceForType().newBuilderForType(); + BuilderType builder = (BuilderType) getDefaultInstanceForType().newBuilderForType(); builder.mergeFrom(buildPartial()); return builder; } @@ -392,7 +422,7 @@ public BuilderType mergeFrom(MessageType message) { } private void mergeFromInstance(MessageType dest, MessageType src) { - dest.visit(MergeFromVisitor.INSTANCE, src); + Protobuf.getInstance().schemaFor(dest).mergeFrom(dest, src); } @Override @@ -400,6 +430,32 @@ public MessageType getDefaultInstanceForType() { return defaultInstance; } + @Override + public BuilderType mergeFrom( + byte[] input, int offset, int length, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + copyOnWrite(); + try { + Protobuf.getInstance().schemaFor(instance).mergeFrom( + instance, input, offset, offset + length, + new ArrayDecoders.Registers(extensionRegistry)); + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IndexOutOfBoundsException e) { + throw InvalidProtocolBufferException.truncatedMessage(); + } catch (IOException e) { + throw new RuntimeException("Reading from byte array should not throw IOException.", e); + } + return (BuilderType) this; + } + + @Override + public BuilderType mergeFrom( + byte[] input, int offset, int length) + throws InvalidProtocolBufferException { + return mergeFrom(input, offset, length, ExtensionRegistryLite.getEmptyRegistry()); + } + @Override public BuilderType mergeFrom( com.google.protobuf.CodedInputStream input, @@ -407,7 +463,10 @@ public BuilderType mergeFrom( throws IOException { copyOnWrite(); try { - instance.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry); + // TODO(yilunchong): Try to make input with type CodedInputStream.ArrayDecoder use + // fast path. + Protobuf.getInstance().schemaFor(instance).mergeFrom( + instance, CodedInputStreamReader.forCodedInput(input), extensionRegistry); } catch (RuntimeException e) { if (e.getCause() instanceof IOException) { throw (IOException) e.getCause(); @@ -422,45 +481,34 @@ public BuilderType mergeFrom( // ================================================================= // Extensions-related stuff - /** - * Lite equivalent of {@link com.google.protobuf.GeneratedMessage.ExtendableMessageOrBuilder}. - */ + /** Lite equivalent of {@link com.google.protobuf.GeneratedMessage.ExtendableMessageOrBuilder}. */ public interface ExtendableMessageOrBuilder< - MessageType extends ExtendableMessage, - BuilderType extends ExtendableBuilder> - extends MessageLiteOrBuilder { + MessageType extends ExtendableMessage, + BuilderType extends ExtendableBuilder> + extends MessageLiteOrBuilder { /** Check if a singular extension is present. */ - boolean hasExtension( - ExtensionLite extension); + boolean hasExtension(ExtensionLite extension); /** Get the number of elements in a repeated extension. */ - int getExtensionCount( - ExtensionLite> extension); + int getExtensionCount(ExtensionLite> extension); /** Get the value of an extension. */ Type getExtension(ExtensionLite extension); /** Get one element of a repeated extension. */ - Type getExtension( - ExtensionLite> extension, - int index); + Type getExtension(ExtensionLite> extension, int index); } - /** - * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}. - */ + /** Lite equivalent of {@link GeneratedMessage.ExtendableMessage}. */ public abstract static class ExtendableMessage< - MessageType extends ExtendableMessage, - BuilderType extends ExtendableBuilder> - extends GeneratedMessageLite - implements ExtendableMessageOrBuilder { + MessageType extends ExtendableMessage, + BuilderType extends ExtendableBuilder> + extends GeneratedMessageLite + implements ExtendableMessageOrBuilder { - /** - * Represents the set of extensions on this message. For use by generated - * code only. - */ - protected FieldSet extensions = FieldSet.newFieldSet(); + /** Represents the set of extensions on this message. For use by generated code only. */ + protected FieldSet extensions = FieldSet.emptySet(); @SuppressWarnings("unchecked") protected final void mergeExtensionFields(final MessageType other) { @@ -470,12 +518,6 @@ protected final void mergeExtensionFields(final MessageType other) { extensions.mergeFrom(((ExtendableMessage) other).extensions); } - @Override - final void visit(Visitor visitor, MessageType other) { - super.visit(visitor, other); - extensions = visitor.visitExtensions(extensions, other.extensions); - } - /** * Parse an unknown field or an extension. For use by generated code only. * @@ -487,13 +529,14 @@ protected boolean parseUnknownField( MessageType defaultInstance, CodedInputStream input, ExtensionRegistryLite extensionRegistry, - int tag) throws IOException { + int tag) + throws IOException { int fieldNumber = WireFormat.getTagFieldNumber(tag); // TODO(dweis): How much bytecode would be saved by not requiring the generated code to // provide the default instance? - GeneratedExtension extension = extensionRegistry.findLiteExtensionByNumber( - defaultInstance, fieldNumber); + GeneratedExtension extension = + extensionRegistry.findLiteExtensionByNumber(defaultInstance, fieldNumber); return parseExtension(input, extensionRegistry, extension, tag, fieldNumber); } @@ -509,47 +552,47 @@ private boolean parseExtension( boolean unknown = false; boolean packed = false; if (extension == null) { - unknown = true; // Unknown field. - } else if (wireType == FieldSet.getWireFormatForFieldType( - extension.descriptor.getLiteType(), - false /* isPacked */)) { - packed = false; // Normal, unpacked value. - } else if (extension.descriptor.isRepeated && - extension.descriptor.type.isPackable() && - wireType == FieldSet.getWireFormatForFieldType( - extension.descriptor.getLiteType(), - true /* isPacked */)) { - packed = true; // Packed value. + unknown = true; // Unknown field. + } else if (wireType + == FieldSet.getWireFormatForFieldType( + extension.descriptor.getLiteType(), /* isPacked= */ false)) { + packed = false; // Normal, unpacked value. + } else if (extension.descriptor.isRepeated + && extension.descriptor.type.isPackable() + && wireType + == FieldSet.getWireFormatForFieldType( + extension.descriptor.getLiteType(), /* isPacked= */ true)) { + packed = true; // Packed value. } else { - unknown = true; // Wrong wire type. + unknown = true; // Wrong wire type. } - if (unknown) { // Unknown field or wrong wire type. Skip. + if (unknown) { // Unknown field or wrong wire type. Skip. return parseUnknownField(tag, input); } - + + ensureExtensionsAreMutable(); + if (packed) { int length = input.readRawVarint32(); int limit = input.pushLimit(length); if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) { while (input.getBytesUntilLimit() > 0) { int rawValue = input.readEnum(); - Object value = - extension.descriptor.getEnumType().findValueByNumber(rawValue); + Object value = extension.descriptor.getEnumType().findValueByNumber(rawValue); if (value == null) { // If the number isn't recognized as a valid value for this // enum, drop it (don't even add it to unknownFields). return true; } - extensions.addRepeatedField(extension.descriptor, - extension.singularToFieldSetType(value)); + extensions.addRepeatedField( + extension.descriptor, extension.singularToFieldSetType(value)); } } else { while (input.getBytesUntilLimit() > 0) { Object value = - FieldSet.readPrimitiveField(input, - extension.descriptor.getLiteType(), - /*checkUtf8=*/ false); + FieldSet.readPrimitiveField( + input, extension.descriptor.getLiteType(), /*checkUtf8=*/ false); extensions.addRepeatedField(extension.descriptor, value); } } @@ -557,33 +600,29 @@ private boolean parseExtension( } else { Object value; switch (extension.descriptor.getLiteJavaType()) { - case MESSAGE: { - MessageLite.Builder subBuilder = null; - if (!extension.descriptor.isRepeated()) { - MessageLite existingValue = - (MessageLite) extensions.getField(extension.descriptor); - if (existingValue != null) { - subBuilder = existingValue.toBuilder(); + case MESSAGE: + { + MessageLite.Builder subBuilder = null; + if (!extension.descriptor.isRepeated()) { + MessageLite existingValue = (MessageLite) extensions.getField(extension.descriptor); + if (existingValue != null) { + subBuilder = existingValue.toBuilder(); + } } + if (subBuilder == null) { + subBuilder = extension.getMessageDefaultInstance().newBuilderForType(); + } + if (extension.descriptor.getLiteType() == WireFormat.FieldType.GROUP) { + input.readGroup(extension.getNumber(), subBuilder, extensionRegistry); + } else { + input.readMessage(subBuilder, extensionRegistry); + } + value = subBuilder.build(); + break; } - if (subBuilder == null) { - subBuilder = extension.getMessageDefaultInstance() - .newBuilderForType(); - } - if (extension.descriptor.getLiteType() == - WireFormat.FieldType.GROUP) { - input.readGroup(extension.getNumber(), - subBuilder, extensionRegistry); - } else { - input.readMessage(subBuilder, extensionRegistry); - } - value = subBuilder.build(); - break; - } case ENUM: int rawValue = input.readEnum(); - value = extension.descriptor.getEnumType() - .findValueByNumber(rawValue); + value = extension.descriptor.getEnumType().findValueByNumber(rawValue); // If the number isn't recognized as a valid value for this enum, // write it to unknown fields object. if (value == null) { @@ -592,23 +631,22 @@ private boolean parseExtension( } break; default: - value = FieldSet.readPrimitiveField(input, - extension.descriptor.getLiteType(), - /*checkUtf8=*/ false); + value = + FieldSet.readPrimitiveField( + input, extension.descriptor.getLiteType(), /*checkUtf8=*/ false); break; } if (extension.descriptor.isRepeated()) { - extensions.addRepeatedField(extension.descriptor, - extension.singularToFieldSetType(value)); + extensions.addRepeatedField( + extension.descriptor, extension.singularToFieldSetType(value)); } else { - extensions.setField(extension.descriptor, - extension.singularToFieldSetType(value)); + extensions.setField(extension.descriptor, extension.singularToFieldSetType(value)); } } return true; } - + /** * Parse an unknown field or an extension. For use by generated code only. * @@ -641,7 +679,7 @@ protected boolean parseUnknownFieldAsMessageSe /** * Merges the message set from the input stream; requires message set wire format. - * + * * @param defaultInstance the default instance of the containing message we are parsing in * @param input the stream to parse from * @param extensionRegistry the registry to use when parsing @@ -742,28 +780,33 @@ private void mergeMessageSetExtensionFromBytes( if (subBuilder == null) { subBuilder = extension.getMessageDefaultInstance().newBuilderForType(); } - rawBytes.newCodedInput().readMessage(subBuilder, extensionRegistry); + subBuilder.mergeFrom(rawBytes, extensionRegistry); MessageLite value = subBuilder.build(); - extensions.setField(extension.descriptor, extension.singularToFieldSetType(value)); + ensureExtensionsAreMutable() + .setField(extension.descriptor, extension.singularToFieldSetType(value)); + } + + FieldSet ensureExtensionsAreMutable() { + if (extensions.isImmutable()) { + extensions = extensions.clone(); + } + return extensions; } - private void verifyExtensionContainingType( - final GeneratedExtension extension) { - if (extension.getContainingTypeDefaultInstance() != - getDefaultInstanceForType()) { + private void verifyExtensionContainingType(final GeneratedExtension extension) { + if (extension.getContainingTypeDefaultInstance() != getDefaultInstanceForType()) { // This can only happen if someone uses unchecked operations. throw new IllegalArgumentException( - "This extension is for a different message type. Please make " + - "sure that you are not suppressing any generics type warnings."); + "This extension is for a different message type. Please make " + + "sure that you are not suppressing any generics type warnings."); } } /** Check if a singular extension is present. */ @Override public final boolean hasExtension(final ExtensionLite extension) { - GeneratedExtension extensionLite = - checkIsLite(extension); + GeneratedExtension extensionLite = checkIsLite(extension); verifyExtensionContainingType(extensionLite); return extensions.hasField(extensionLite.descriptor); @@ -773,8 +816,7 @@ public final boolean hasExtension(final ExtensionLite @Override public final int getExtensionCount( final ExtensionLite> extension) { - GeneratedExtension> extensionLite = - checkIsLite(extension); + GeneratedExtension> extensionLite = checkIsLite(extension); verifyExtensionContainingType(extensionLite); return extensions.getRepeatedFieldCount(extensionLite.descriptor); @@ -784,8 +826,7 @@ public final int getExtensionCount( @Override @SuppressWarnings("unchecked") public final Type getExtension(final ExtensionLite extension) { - GeneratedExtension extensionLite = - checkIsLite(extension); + GeneratedExtension extensionLite = checkIsLite(extension); verifyExtensionContainingType(extensionLite); final Object value = extensions.getField(extensionLite.descriptor); @@ -801,12 +842,12 @@ public final Type getExtension(final ExtensionLite ext @SuppressWarnings("unchecked") public final Type getExtension( final ExtensionLite> extension, final int index) { - GeneratedExtension> extensionLite = - checkIsLite(extension); + GeneratedExtension> extensionLite = checkIsLite(extension); verifyExtensionContainingType(extensionLite); - return (Type) extensionLite.singularFromFieldSetType( - extensions.getRepeatedField(extensionLite.descriptor, index)); + return (Type) + extensionLite.singularFromFieldSetType( + extensions.getRepeatedField(extensionLite.descriptor, index)); } /** Called by subclasses to check if all extensions are initialized. */ @@ -814,25 +855,16 @@ protected boolean extensionsAreInitialized() { return extensions.isInitialized(); } - @Override - protected final void makeImmutable() { - super.makeImmutable(); - - extensions.makeImmutable(); - } - /** - * Used by subclasses to serialize extensions. Extension ranges may be - * interleaved with field numbers, but we must write them in canonical - * (sorted by field number) order. ExtensionWriter helps us write - * individual ranges of extensions at once. + * Used by subclasses to serialize extensions. Extension ranges may be interleaved with field + * numbers, but we must write them in canonical (sorted by field number) order. ExtensionWriter + * helps us write individual ranges of extensions at once. */ protected class ExtensionWriter { // Imagine how much simpler this code would be if Java iterators had // a way to get the next element without advancing the iterator. - private final Iterator> iter = - extensions.iterator(); + private final Iterator> iter = extensions.iterator(); private Map.Entry next; private final boolean messageSetWireFormat; @@ -843,15 +875,13 @@ private ExtensionWriter(boolean messageSetWireFormat) { this.messageSetWireFormat = messageSetWireFormat; } - public void writeUntil(final int end, final CodedOutputStream output) - throws IOException { + public void writeUntil(final int end, final CodedOutputStream output) throws IOException { while (next != null && next.getKey().getNumber() < end) { ExtensionDescriptor extension = next.getKey(); - if (messageSetWireFormat && extension.getLiteJavaType() == - WireFormat.JavaType.MESSAGE && - !extension.isRepeated()) { - output.writeMessageSetExtension(extension.getNumber(), - (MessageLite) next.getValue()); + if (messageSetWireFormat + && extension.getLiteJavaType() == WireFormat.JavaType.MESSAGE + && !extension.isRepeated()) { + output.writeMessageSetExtension(extension.getNumber(), (MessageLite) next.getValue()); } else { FieldSet.writeField(extension, next.getValue(), output); } @@ -867,6 +897,7 @@ public void writeUntil(final int end, final CodedOutputStream output) protected ExtensionWriter newExtensionWriter() { return new ExtensionWriter(false); } + protected ExtensionWriter newMessageSetExtensionWriter() { return new ExtensionWriter(true); } @@ -875,28 +906,21 @@ protected ExtensionWriter newMessageSetExtensionWriter() { protected int extensionsSerializedSize() { return extensions.getSerializedSize(); } + protected int extensionsSerializedSizeAsMessageSet() { return extensions.getMessageSetSerializedSize(); } } - /** - * Lite equivalent of {@link GeneratedMessage.ExtendableBuilder}. - */ + /** Lite equivalent of {@link GeneratedMessage.ExtendableBuilder}. */ @SuppressWarnings("unchecked") public abstract static class ExtendableBuilder< - MessageType extends ExtendableMessage, - BuilderType extends ExtendableBuilder> + MessageType extends ExtendableMessage, + BuilderType extends ExtendableBuilder> extends Builder implements ExtendableMessageOrBuilder { protected ExtendableBuilder(MessageType defaultInstance) { super(defaultInstance); - - // TODO(dweis): This is kind of an unnecessary clone since we construct a - // new instance in the parent constructor which makes the extensions - // immutable. This extra allocation shouldn't matter in practice - // though. - instance.extensions = instance.extensions.clone(); } // For immutable message conversion. @@ -906,15 +930,20 @@ void internalSetExtensionSet(FieldSet extensions) { } @Override - protected void copyOnWrite() { - if (!isBuilt) { - return; - } - - super.copyOnWrite(); + protected void copyOnWriteInternal() { + super.copyOnWriteInternal(); instance.extensions = instance.extensions.clone(); } + private FieldSet ensureExtensionsAreMutable() { + FieldSet extensions = instance.extensions; + if (extensions.isImmutable()) { + extensions = extensions.clone(); + instance.extensions = extensions; + } + return extensions; + } + @Override public final MessageType buildPartial() { if (isBuilt) { @@ -925,14 +954,12 @@ public final MessageType buildPartial() { return super.buildPartial(); } - private void verifyExtensionContainingType( - final GeneratedExtension extension) { - if (extension.getContainingTypeDefaultInstance() != - getDefaultInstanceForType()) { + private void verifyExtensionContainingType(final GeneratedExtension extension) { + if (extension.getContainingTypeDefaultInstance() != getDefaultInstanceForType()) { // This can only happen if someone uses unchecked operations. throw new IllegalArgumentException( - "This extension is for a different message type. Please make " + - "sure that you are not suppressing any generics type warnings."); + "This extension is for a different message type. Please make " + + "sure that you are not suppressing any generics type warnings."); } } @@ -966,53 +993,48 @@ public final Type getExtension( /** Set the value of an extension. */ public final BuilderType setExtension( - final ExtensionLite extension, - final Type value) { - GeneratedExtension extensionLite = - checkIsLite(extension); + final ExtensionLite extension, final Type value) { + GeneratedExtension extensionLite = checkIsLite(extension); verifyExtensionContainingType(extensionLite); copyOnWrite(); - instance.extensions.setField(extensionLite.descriptor, extensionLite.toFieldSetType(value)); + ensureExtensionsAreMutable() + .setField(extensionLite.descriptor, extensionLite.toFieldSetType(value)); return (BuilderType) this; } /** Set the value of one element of a repeated extension. */ public final BuilderType setExtension( - final ExtensionLite> extension, - final int index, final Type value) { - GeneratedExtension> extensionLite = - checkIsLite(extension); + final ExtensionLite> extension, final int index, final Type value) { + GeneratedExtension> extensionLite = checkIsLite(extension); verifyExtensionContainingType(extensionLite); copyOnWrite(); - instance.extensions.setRepeatedField( - extensionLite.descriptor, index, extensionLite.singularToFieldSetType(value)); + ensureExtensionsAreMutable() + .setRepeatedField( + extensionLite.descriptor, index, extensionLite.singularToFieldSetType(value)); return (BuilderType) this; } /** Append a value to a repeated extension. */ public final BuilderType addExtension( - final ExtensionLite> extension, - final Type value) { - GeneratedExtension> extensionLite = - checkIsLite(extension); + final ExtensionLite> extension, final Type value) { + GeneratedExtension> extensionLite = checkIsLite(extension); verifyExtensionContainingType(extensionLite); copyOnWrite(); - instance.extensions.addRepeatedField( - extensionLite.descriptor, extensionLite.singularToFieldSetType(value)); + ensureExtensionsAreMutable() + .addRepeatedField(extensionLite.descriptor, extensionLite.singularToFieldSetType(value)); return (BuilderType) this; } /** Clear an extension. */ - public final BuilderType clearExtension( - final ExtensionLite extension) { + public final BuilderType clearExtension(final ExtensionLite extension) { GeneratedExtension extensionLite = checkIsLite(extension); verifyExtensionContainingType(extensionLite); copyOnWrite(); - instance.extensions.clearField(extensionLite.descriptor); + ensureExtensionsAreMutable().clearField(extensionLite.descriptor); return (BuilderType) this; } } @@ -1021,50 +1043,45 @@ public final BuilderType clearExtension( /** For use by generated code only. */ public static - GeneratedExtension - newSingularGeneratedExtension( - final ContainingType containingTypeDefaultInstance, - final Type defaultValue, - final MessageLite messageDefaultInstance, - final Internal.EnumLiteMap enumTypeMap, - final int number, - final WireFormat.FieldType type, - final Class singularType) { + GeneratedExtension newSingularGeneratedExtension( + final ContainingType containingTypeDefaultInstance, + final Type defaultValue, + final MessageLite messageDefaultInstance, + final Internal.EnumLiteMap enumTypeMap, + final int number, + final WireFormat.FieldType type, + final Class singularType) { return new GeneratedExtension( containingTypeDefaultInstance, defaultValue, messageDefaultInstance, - new ExtensionDescriptor(enumTypeMap, number, type, - false /* isRepeated */, - false /* isPacked */), + new ExtensionDescriptor( + enumTypeMap, number, type, /* isRepeated= */ false, /* isPacked= */ false), singularType); } /** For use by generated code only. */ public static - GeneratedExtension - newRepeatedGeneratedExtension( - final ContainingType containingTypeDefaultInstance, - final MessageLite messageDefaultInstance, - final Internal.EnumLiteMap enumTypeMap, - final int number, - final WireFormat.FieldType type, - final boolean isPacked, - final Class singularType) { - @SuppressWarnings("unchecked") // Subclasses ensure Type is a List + GeneratedExtension newRepeatedGeneratedExtension( + final ContainingType containingTypeDefaultInstance, + final MessageLite messageDefaultInstance, + final Internal.EnumLiteMap enumTypeMap, + final int number, + final WireFormat.FieldType type, + final boolean isPacked, + final Class singularType) { + @SuppressWarnings("unchecked") // Subclasses ensure Type is a List Type emptyList = (Type) Collections.emptyList(); return new GeneratedExtension( containingTypeDefaultInstance, emptyList, messageDefaultInstance, - new ExtensionDescriptor( - enumTypeMap, number, type, true /* isRepeated */, isPacked), + new ExtensionDescriptor(enumTypeMap, number, type, /* isRepeated= */ true, isPacked), singularType); } static final class ExtensionDescriptor - implements FieldSet.FieldDescriptorLite< - ExtensionDescriptor> { + implements FieldSet.FieldDescriptorLite { ExtensionDescriptor( final Internal.EnumLiteMap enumTypeMap, final int number, @@ -1136,8 +1153,8 @@ static Method getMethodOrDie(Class clazz, String name, Class... params) { return clazz.getMethod(name, params); } catch (NoSuchMethodException e) { throw new RuntimeException( - "Generated message class \"" + clazz.getName() + - "\" missing method \"" + name + "\".", e); + "Generated message class \"" + clazz.getName() + "\" missing method \"" + name + "\".", + e); } } @@ -1147,8 +1164,7 @@ static Object invokeOrDie(Method method, Object object, Object... params) { return method.invoke(object, params); } catch (IllegalAccessException e) { throw new RuntimeException( - "Couldn't use Java reflection to implement protocol message " + - "reflection.", e); + "Couldn't use Java reflection to implement protocol message reflection.", e); } catch (InvocationTargetException e) { final Throwable cause = e.getCause(); if (cause instanceof RuntimeException) { @@ -1157,7 +1173,7 @@ static Object invokeOrDie(Method method, Object object, Object... params) { throw (Error) cause; } else { throw new RuntimeException( - "Unexpected exception thrown by generated accessor method.", cause); + "Unexpected exception thrown by generated accessor method.", cause); } } } @@ -1166,20 +1182,18 @@ static Object invokeOrDie(Method method, Object object, Object... params) { /** * Lite equivalent to {@link GeneratedMessage.GeneratedExtension}. * - * Users should ignore the contents of this class and only use objects of - * this type as parameters to extension accessors and ExtensionRegistry.add(). + *

Users should ignore the contents of this class and only use objects of this type as + * parameters to extension accessors and ExtensionRegistry.add(). */ - public static class GeneratedExtension< - ContainingType extends MessageLite, Type> - extends ExtensionLite { + public static class GeneratedExtension + extends ExtensionLite { /** * Create a new instance with the given parameters. * - * The last parameter {@code singularType} is only needed for enum types. - * We store integer values for enum types in a {@link ExtendableMessage} - * and use Java reflection to convert an integer value back into a concrete - * enum object. + *

The last parameter {@code singularType} is only needed for enum types. We store integer + * values for enum types in a {@link ExtendableMessage} and use Java reflection to convert an + * integer value back into a concrete enum object. */ GeneratedExtension( final ContainingType containingTypeDefaultInstance, @@ -1190,13 +1204,11 @@ public static class GeneratedExtension< // Defensive checks to verify the correct initialization order of // GeneratedExtensions and their related GeneratedMessages. if (containingTypeDefaultInstance == null) { - throw new IllegalArgumentException( - "Null containingTypeDefaultInstance"); + throw new IllegalArgumentException("Null containingTypeDefaultInstance"); } - if (descriptor.getLiteType() == WireFormat.FieldType.MESSAGE && - messageDefaultInstance == null) { - throw new IllegalArgumentException( - "Null messageDefaultInstance"); + if (descriptor.getLiteType() == WireFormat.FieldType.MESSAGE + && messageDefaultInstance == null) { + throw new IllegalArgumentException("Null messageDefaultInstance"); } this.containingTypeDefaultInstance = containingTypeDefaultInstance; this.defaultValue = defaultValue; @@ -1209,9 +1221,7 @@ public static class GeneratedExtension< final MessageLite messageDefaultInstance; final ExtensionDescriptor descriptor; - /** - * Default instance of the type being extended, used to identify that type. - */ + /** Default instance of the type being extended, used to identify that type. */ public ContainingType getContainingTypeDefaultInstance() { return containingTypeDefaultInstance; } @@ -1222,10 +1232,9 @@ public int getNumber() { return descriptor.getNumber(); } - /** - * If the extension is an embedded message or group, returns the default - * instance of the message. + * If the extension is an embedded message or group, returns the default instance of the + * message. */ @Override public MessageLite getMessageDefaultInstance() { @@ -1236,7 +1245,7 @@ public MessageLite getMessageDefaultInstance() { Object fromFieldSetType(final Object value) { if (descriptor.isRepeated()) { if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) { - final List result = new ArrayList(); + final List result = new ArrayList<>(); for (final Object element : (List) value) { result.add(singularFromFieldSetType(element)); } @@ -1261,7 +1270,7 @@ Object singularFromFieldSetType(final Object value) { Object toFieldSetType(final Object value) { if (descriptor.isRepeated()) { if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) { - final List result = new ArrayList(); + final List result = new ArrayList<>(); for (final Object element : (List) value) { result.add(singularToFieldSetType(element)); } @@ -1299,8 +1308,8 @@ public Type getDefaultValue() { } /** - * A serialized (serializable) form of the generated message. Stores the - * message as a class name and a byte array. + * A serialized (serializable) form of the generated message. Stores the message as a class name + * and a byte array. */ protected static final class SerializedForm implements Serializable { @@ -1310,34 +1319,38 @@ public static SerializedForm of(MessageLite message) { private static final long serialVersionUID = 0L; + // since v3.6.1 + private final Class messageClass; + // only included for backwards compatibility before messageClass was added private final String messageClassName; private final byte[] asBytes; /** * Creates the serialized form by calling {@link com.google.protobuf.MessageLite#toByteArray}. + * * @param regularForm the message to serialize */ SerializedForm(MessageLite regularForm) { - messageClassName = regularForm.getClass().getName(); + messageClass = regularForm.getClass(); + messageClassName = messageClass.getName(); asBytes = regularForm.toByteArray(); } /** - * When read from an ObjectInputStream, this method converts this object - * back to the regular form. Part of Java's serialization magic. + * When read from an ObjectInputStream, this method converts this object back to the regular + * form. Part of Java's serialization magic. + * * @return a GeneratedMessage of the type that was serialized */ @SuppressWarnings("unchecked") protected Object readResolve() throws ObjectStreamException { try { - Class messageClass = Class.forName(messageClassName); + Class messageClass = resolveMessageClass(); java.lang.reflect.Field defaultInstanceField = messageClass.getDeclaredField("DEFAULT_INSTANCE"); defaultInstanceField.setAccessible(true); MessageLite defaultInstance = (MessageLite) defaultInstanceField.get(null); - return defaultInstance.newBuilderForType() - .mergeFrom(asBytes) - .buildPartial(); + return defaultInstance.newBuilderForType().mergeFrom(asBytes).buildPartial(); } catch (ClassNotFoundException e) { throw new RuntimeException("Unable to find proto buffer class: " + messageClassName, e); } catch (NoSuchFieldException e) { @@ -1357,7 +1370,7 @@ protected Object readResolve() throws ObjectStreamException { @Deprecated private Object readResolveFallback() throws ObjectStreamException { try { - Class messageClass = Class.forName(messageClassName); + Class messageClass = resolveMessageClass(); java.lang.reflect.Field defaultInstanceField = messageClass.getDeclaredField("defaultInstance"); defaultInstanceField.setAccessible(true); @@ -1377,18 +1390,18 @@ private Object readResolveFallback() throws ObjectStreamException { throw new RuntimeException("Unable to understand proto buffer", e); } } + + private Class resolveMessageClass() throws ClassNotFoundException { + return messageClass != null ? messageClass : Class.forName(messageClassName); + } } - /** - * Checks that the {@link Extension} is Lite and returns it as a - * {@link GeneratedExtension}. - */ + /** Checks that the {@link Extension} is Lite and returns it as a {@link GeneratedExtension}. */ private static < - MessageType extends ExtendableMessage, - BuilderType extends ExtendableBuilder, - T> - GeneratedExtension checkIsLite( - ExtensionLite extension) { + MessageType extends ExtendableMessage, + BuilderType extends ExtendableBuilder, + T> + GeneratedExtension checkIsLite(ExtensionLite extension) { if (!extension.isLite()) { throw new IllegalArgumentException("Expected a lite extension."); } @@ -1398,16 +1411,25 @@ GeneratedExtension checkIsLite( /** * A static helper method for checking if a message is initialized, optionally memoizing. - *

- * For use by generated code only. + * + *

For use by generated code only. */ protected static final > boolean isInitialized( T message, boolean shouldMemoize) { - return message.dynamicMethod(MethodToInvoke.IS_INITIALIZED, shouldMemoize) != null; - } - - protected static final > void makeImmutable(T message) { - message.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE); + byte memoizedIsInitialized = + (Byte) message.dynamicMethod(MethodToInvoke.GET_MEMOIZED_IS_INITIALIZED); + if (memoizedIsInitialized == 1) { + return true; + } + if (memoizedIsInitialized == 0) { + return false; + } + boolean isInitialized = Protobuf.getInstance().schemaFor(message).isInitialized(message); + if (shouldMemoize) { + message.dynamicMethod( + MethodToInvoke.SET_MEMOIZED_IS_INITIALIZED, isInitialized ? message : null); + } + return isInitialized; } protected static IntList emptyIntList() { @@ -1472,13 +1494,13 @@ protected static ProtobufList mutableCopy(ProtobufList list) { /** * A {@link Parser} implementation that delegates to the default instance. - *

- * For use by generated code only. + * + *

For use by generated code only. */ protected static class DefaultInstanceBasedParser> extends AbstractParser { - private T defaultInstance; + private final T defaultInstance; public DefaultInstanceBasedParser(T defaultInstance) { this.defaultInstance = defaultInstance; @@ -1489,6 +1511,14 @@ public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensio throws InvalidProtocolBufferException { return GeneratedMessageLite.parsePartialFrom(defaultInstance, input, extensionRegistry); } + + @Override + public T parsePartialFrom( + byte[] input, int offset, int length, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return GeneratedMessageLite.parsePartialFrom( + defaultInstance, input, offset, length, extensionRegistry); + } } /** @@ -1498,12 +1528,20 @@ public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensio // TODO(dweis): Should this verify that the last tag was 0? static > T parsePartialFrom( T instance, CodedInputStream input, ExtensionRegistryLite extensionRegistry) - throws InvalidProtocolBufferException { + throws InvalidProtocolBufferException { @SuppressWarnings("unchecked") // Guaranteed by protoc T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE); try { - result.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry); - result.makeImmutable(); + // TODO(yilunchong): Try to make input with type CodedInpuStream.ArrayDecoder use + // fast path. + Schema schema = Protobuf.getInstance().schemaFor(result); + schema.mergeFrom(result, CodedInputStreamReader.forCodedInput(input), extensionRegistry); + schema.makeImmutable(result); + } catch (IOException e) { + if (e.getCause() instanceof InvalidProtocolBufferException) { + throw (InvalidProtocolBufferException) e.getCause(); + } + throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(result); } catch (RuntimeException e) { if (e.getCause() instanceof InvalidProtocolBufferException) { throw (InvalidProtocolBufferException) e.getCause(); @@ -1513,10 +1551,33 @@ public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensio return result; } - protected static > T parsePartialFrom( - T defaultInstance, - CodedInputStream input) + /** A static helper method for parsing a partial from byte array. */ + static > T parsePartialFrom( + T instance, byte[] input, int offset, int length, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { + @SuppressWarnings("unchecked") // Guaranteed by protoc + T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE); + try { + Schema schema = Protobuf.getInstance().schemaFor(result); + schema.mergeFrom( + result, input, offset, offset + length, new ArrayDecoders.Registers(extensionRegistry)); + schema.makeImmutable(result); + if (result.memoizedHashCode != 0) { + throw new RuntimeException(); + } + } catch (IOException e) { + if (e.getCause() instanceof InvalidProtocolBufferException) { + throw (InvalidProtocolBufferException) e.getCause(); + } + throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(result); + } catch (IndexOutOfBoundsException e) { + throw InvalidProtocolBufferException.truncatedMessage().setUnfinishedMessage(result); + } + return result; + } + + protected static > T parsePartialFrom( + T defaultInstance, CodedInputStream input) throws InvalidProtocolBufferException { return parsePartialFrom(defaultInstance, input, ExtensionRegistryLite.getEmptyRegistry()); } @@ -1529,7 +1590,8 @@ public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensio private static > T checkMessageInitialized(T message) throws InvalidProtocolBufferException { if (message != null && !message.isInitialized()) { - throw message.newUninitializedMessageException() + throw message + .newUninitializedMessageException() .asInvalidProtocolBufferException() .setUnfinishedMessage(message); } @@ -1552,8 +1614,7 @@ public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensio // Validates last tag. protected static > T parseFrom( - T defaultInstance, ByteString data) - throws InvalidProtocolBufferException { + T defaultInstance, ByteString data) throws InvalidProtocolBufferException { return checkMessageInitialized( parseFrom(defaultInstance, data, ExtensionRegistryLite.getEmptyRegistry())); } @@ -1590,42 +1651,32 @@ public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensio private static > T parsePartialFrom( T defaultInstance, byte[] data, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { - T message; - try { - CodedInputStream input = CodedInputStream.newInstance(data); - message = parsePartialFrom(defaultInstance, input, extensionRegistry); - try { - input.checkLastTagWas(0); - } catch (InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(message); - } - return message; - } catch (InvalidProtocolBufferException e) { - throw e; - } + return checkMessageInitialized( + parsePartialFrom(defaultInstance, data, 0, data.length, extensionRegistry)); } // Validates last tag. protected static > T parseFrom( - T defaultInstance, byte[] data) - throws InvalidProtocolBufferException { - return checkMessageInitialized( - parsePartialFrom(defaultInstance, data, ExtensionRegistryLite.getEmptyRegistry())); + T defaultInstance, byte[] data) throws InvalidProtocolBufferException { + return checkMessageInitialized(parsePartialFrom( + defaultInstance, data, 0, data.length, ExtensionRegistryLite.getEmptyRegistry())); } // Validates last tag. protected static > T parseFrom( T defaultInstance, byte[] data, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { - return checkMessageInitialized(parsePartialFrom(defaultInstance, data, extensionRegistry)); + return checkMessageInitialized( + parsePartialFrom(defaultInstance, data, 0, data.length, extensionRegistry)); } // Does not validate last tag. protected static > T parseFrom( - T defaultInstance, InputStream input) - throws InvalidProtocolBufferException { + T defaultInstance, InputStream input) throws InvalidProtocolBufferException { return checkMessageInitialized( - parsePartialFrom(defaultInstance, CodedInputStream.newInstance(input), + parsePartialFrom( + defaultInstance, + CodedInputStream.newInstance(input), ExtensionRegistryLite.getEmptyRegistry())); } @@ -1639,8 +1690,7 @@ public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensio // Does not validate last tag. protected static > T parseFrom( - T defaultInstance, CodedInputStream input) - throws InvalidProtocolBufferException { + T defaultInstance, CodedInputStream input) throws InvalidProtocolBufferException { return parseFrom(defaultInstance, input, ExtensionRegistryLite.getEmptyRegistry()); } @@ -1648,17 +1698,15 @@ public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensio protected static > T parseFrom( T defaultInstance, CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { - return checkMessageInitialized( - parsePartialFrom(defaultInstance, input, extensionRegistry)); + return checkMessageInitialized(parsePartialFrom(defaultInstance, input, extensionRegistry)); } // Validates last tag. protected static > T parseDelimitedFrom( - T defaultInstance, InputStream input) - throws InvalidProtocolBufferException { + T defaultInstance, InputStream input) throws InvalidProtocolBufferException { return checkMessageInitialized( - parsePartialDelimitedFrom(defaultInstance, input, - ExtensionRegistryLite.getEmptyRegistry())); + parsePartialDelimitedFrom( + defaultInstance, input, ExtensionRegistryLite.getEmptyRegistry())); } // Validates last tag. @@ -1670,9 +1718,7 @@ public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensio } private static > T parsePartialDelimitedFrom( - T defaultInstance, - InputStream input, - ExtensionRegistryLite extensionRegistry) + T defaultInstance, InputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { int size; try { @@ -1694,690 +1740,4 @@ public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensio } return message; } - - /** - * An abstract visitor that the generated code calls into that we use to implement various - * features. Fields that are not members of oneofs are always visited. Members of a oneof are only - * visited when they are the set oneof case value on the "other" proto. The visitOneofNotSet - * method is invoked if other's oneof case is not set. - */ - protected interface Visitor { - boolean visitBoolean(boolean minePresent, boolean mine, boolean otherPresent, boolean other); - int visitInt(boolean minePresent, int mine, boolean otherPresent, int other); - double visitDouble(boolean minePresent, double mine, boolean otherPresent, double other); - float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other); - long visitLong(boolean minePresent, long mine, boolean otherPresent, long other); - String visitString(boolean minePresent, String mine, boolean otherPresent, String other); - ByteString visitByteString( - boolean minePresent, ByteString mine, boolean otherPresent, ByteString other); - - Object visitOneofBoolean(boolean minePresent, Object mine, Object other); - Object visitOneofInt(boolean minePresent, Object mine, Object other); - Object visitOneofDouble(boolean minePresent, Object mine, Object other); - Object visitOneofFloat(boolean minePresent, Object mine, Object other); - Object visitOneofLong(boolean minePresent, Object mine, Object other); - Object visitOneofString(boolean minePresent, Object mine, Object other); - Object visitOneofByteString(boolean minePresent, Object mine, Object other); - Object visitOneofMessage(boolean minePresent, Object mine, Object other); - void visitOneofNotSet(boolean minePresent); - - /** - * Message fields use null sentinals. - */ - T visitMessage(T mine, T other); - - ProtobufList visitList(ProtobufList mine, ProtobufList other); - BooleanList visitBooleanList(BooleanList mine, BooleanList other); - IntList visitIntList(IntList mine, IntList other); - DoubleList visitDoubleList(DoubleList mine, DoubleList other); - FloatList visitFloatList(FloatList mine, FloatList other); - LongList visitLongList(LongList mine, LongList other); - FieldSet visitExtensions( - FieldSet mine, FieldSet other); - UnknownFieldSetLite visitUnknownFields(UnknownFieldSetLite mine, UnknownFieldSetLite other); - MapFieldLite visitMap(MapFieldLite mine, MapFieldLite other); - } - - /** - * Implements equals. Throws a {@link NotEqualsException} when not equal. - */ - static class EqualsVisitor implements Visitor { - - static final class NotEqualsException extends RuntimeException {} - - static final EqualsVisitor INSTANCE = new EqualsVisitor(); - - static final NotEqualsException NOT_EQUALS = new NotEqualsException(); - - private EqualsVisitor() {} - - @Override - public boolean visitBoolean( - boolean minePresent, boolean mine, boolean otherPresent, boolean other) { - if (minePresent != otherPresent || mine != other) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) { - if (minePresent != otherPresent || mine != other) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public double visitDouble( - boolean minePresent, double mine, boolean otherPresent, double other) { - if (minePresent != otherPresent || mine != other) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) { - if (minePresent != otherPresent || mine != other) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) { - if (minePresent != otherPresent || mine != other) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public String visitString( - boolean minePresent, String mine, boolean otherPresent, String other) { - if (minePresent != otherPresent || !mine.equals(other)) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public ByteString visitByteString( - boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) { - if (minePresent != otherPresent || !mine.equals(other)) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) { - if (minePresent && mine.equals(other)) { - return mine; - } - throw NOT_EQUALS; - } - - @Override - public Object visitOneofInt(boolean minePresent, Object mine, Object other) { - if (minePresent && mine.equals(other)) { - return mine; - } - throw NOT_EQUALS; - } - - @Override - public Object visitOneofDouble(boolean minePresent, Object mine, Object other) { - if (minePresent && mine.equals(other)) { - return mine; - } - throw NOT_EQUALS; - } - - @Override - public Object visitOneofFloat(boolean minePresent, Object mine, Object other) { - if (minePresent && mine.equals(other)) { - return mine; - } - throw NOT_EQUALS; - } - - @Override - public Object visitOneofLong(boolean minePresent, Object mine, Object other) { - if (minePresent && mine.equals(other)) { - return mine; - } - throw NOT_EQUALS; - } - - @Override - public Object visitOneofString(boolean minePresent, Object mine, Object other) { - if (minePresent && mine.equals(other)) { - return mine; - } - throw NOT_EQUALS; - } - - @Override - public Object visitOneofByteString(boolean minePresent, Object mine, Object other) { - if (minePresent && mine.equals(other)) { - return mine; - } - throw NOT_EQUALS; - } - - @Override - public Object visitOneofMessage(boolean minePresent, Object mine, Object other) { - if (minePresent && ((GeneratedMessageLite) mine).equals(this, (MessageLite) other)) { - return mine; - } - throw NOT_EQUALS; - } - - @Override - public void visitOneofNotSet(boolean minePresent) { - if (minePresent) { - throw NOT_EQUALS; - } - } - - @Override - public T visitMessage(T mine, T other) { - if (mine == null && other == null) { - return null; - } - - if (mine == null || other == null) { - throw NOT_EQUALS; - } - - ((GeneratedMessageLite) mine).equals(this, other); - - return mine; - } - - @Override - public ProtobufList visitList(ProtobufList mine, ProtobufList other) { - if (!mine.equals(other)) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public BooleanList visitBooleanList(BooleanList mine, BooleanList other) { - if (!mine.equals(other)) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public IntList visitIntList(IntList mine, IntList other) { - if (!mine.equals(other)) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public DoubleList visitDoubleList(DoubleList mine, DoubleList other) { - if (!mine.equals(other)) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public FloatList visitFloatList(FloatList mine, FloatList other) { - if (!mine.equals(other)) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public LongList visitLongList(LongList mine, LongList other) { - if (!mine.equals(other)) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public FieldSet visitExtensions( - FieldSet mine, - FieldSet other) { - if (!mine.equals(other)) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public UnknownFieldSetLite visitUnknownFields( - UnknownFieldSetLite mine, - UnknownFieldSetLite other) { - if (!mine.equals(other)) { - throw NOT_EQUALS; - } - return mine; - } - - @Override - public MapFieldLite visitMap(MapFieldLite mine, MapFieldLite other) { - if (!mine.equals(other)) { - throw NOT_EQUALS; - } - return mine; - } - } - - /** - * Implements hashCode by accumulating state. - */ - static class HashCodeVisitor implements Visitor { - - // The caller must ensure that the visitor is invoked parameterized with this and this such that - // other is this. This is required due to how oneof cases are handled. See the class comment - // on Visitor for more information. - - int hashCode = 0; - - @Override - public boolean visitBoolean( - boolean minePresent, boolean mine, boolean otherPresent, boolean other) { - hashCode = (53 * hashCode) + Internal.hashBoolean(mine); - return mine; - } - - @Override - public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) { - hashCode = (53 * hashCode) + mine; - return mine; - } - - @Override - public double visitDouble( - boolean minePresent, double mine, boolean otherPresent, double other) { - hashCode = (53 * hashCode) + Internal.hashLong(Double.doubleToLongBits(mine)); - return mine; - } - - @Override - public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) { - hashCode = (53 * hashCode) + Float.floatToIntBits(mine); - return mine; - } - - @Override - public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) { - hashCode = (53 * hashCode) + Internal.hashLong(mine); - return mine; - } - - @Override - public String visitString( - boolean minePresent, String mine, boolean otherPresent, String other) { - hashCode = (53 * hashCode) + mine.hashCode(); - return mine; - } - - @Override - public ByteString visitByteString( - boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) { - hashCode = (53 * hashCode) + mine.hashCode(); - return mine; - } - - @Override - public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) { - hashCode = (53 * hashCode) + Internal.hashBoolean(((Boolean) mine)); - return mine; - } - - @Override - public Object visitOneofInt(boolean minePresent, Object mine, Object other) { - hashCode = (53 * hashCode) + (Integer) mine; - return mine; - } - - @Override - public Object visitOneofDouble(boolean minePresent, Object mine, Object other) { - hashCode = (53 * hashCode) + Internal.hashLong(Double.doubleToLongBits((Double) mine)); - return mine; - } - - @Override - public Object visitOneofFloat(boolean minePresent, Object mine, Object other) { - hashCode = (53 * hashCode) + Float.floatToIntBits((Float) mine); - return mine; - } - - @Override - public Object visitOneofLong(boolean minePresent, Object mine, Object other) { - hashCode = (53 * hashCode) + Internal.hashLong((Long) mine); - return mine; - } - - @Override - public Object visitOneofString(boolean minePresent, Object mine, Object other) { - hashCode = (53 * hashCode) + mine.hashCode(); - return mine; - } - - @Override - public Object visitOneofByteString(boolean minePresent, Object mine, Object other) { - hashCode = (53 * hashCode) + mine.hashCode(); - return mine; - } - - @Override - public Object visitOneofMessage(boolean minePresent, Object mine, Object other) { - return visitMessage((MessageLite) mine, (MessageLite) other); - } - - @Override - public void visitOneofNotSet(boolean minePresent) { - if (minePresent) { - throw new IllegalStateException(); // Can't happen if other == this. - } - } - - @Override - public T visitMessage(T mine, T other) { - final int protoHash; - if (mine != null) { - if (mine instanceof GeneratedMessageLite) { - protoHash = ((GeneratedMessageLite) mine).hashCode(this); - } else { - protoHash = mine.hashCode(); - } - } else { - protoHash = 37; - } - hashCode = (53 * hashCode) + protoHash; - return mine; - } - - @Override - public ProtobufList visitList(ProtobufList mine, ProtobufList other) { - hashCode = (53 * hashCode) + mine.hashCode(); - return mine; - } - - @Override - public BooleanList visitBooleanList(BooleanList mine, BooleanList other) { - hashCode = (53 * hashCode) + mine.hashCode(); - return mine; - } - - @Override - public IntList visitIntList(IntList mine, IntList other) { - hashCode = (53 * hashCode) + mine.hashCode(); - return mine; - } - - @Override - public DoubleList visitDoubleList(DoubleList mine, DoubleList other) { - hashCode = (53 * hashCode) + mine.hashCode(); - return mine; - } - - @Override - public FloatList visitFloatList(FloatList mine, FloatList other) { - hashCode = (53 * hashCode) + mine.hashCode(); - return mine; - } - - @Override - public LongList visitLongList(LongList mine, LongList other) { - hashCode = (53 * hashCode) + mine.hashCode(); - return mine; - } - - @Override - public FieldSet visitExtensions( - FieldSet mine, - FieldSet other) { - hashCode = (53 * hashCode) + mine.hashCode(); - return mine; - } - - @Override - public UnknownFieldSetLite visitUnknownFields( - UnknownFieldSetLite mine, - UnknownFieldSetLite other) { - hashCode = (53 * hashCode) + mine.hashCode(); - return mine; - } - - @Override - public MapFieldLite visitMap(MapFieldLite mine, MapFieldLite other) { - hashCode = (53 * hashCode) + mine.hashCode(); - return mine; - } - } - - /** - * Implements field merging semantics over the visitor interface. - */ - protected static class MergeFromVisitor implements Visitor { - - public static final MergeFromVisitor INSTANCE = new MergeFromVisitor(); - - private MergeFromVisitor() {} - - @Override - public boolean visitBoolean( - boolean minePresent, boolean mine, boolean otherPresent, boolean other) { - return otherPresent ? other : mine; - } - - @Override - public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) { - return otherPresent ? other : mine; - } - - @Override - public double visitDouble( - boolean minePresent, double mine, boolean otherPresent, double other) { - return otherPresent ? other : mine; - } - - @Override - public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) { - return otherPresent ? other : mine; - } - - @Override - public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) { - return otherPresent ? other : mine; - } - - @Override - public String visitString( - boolean minePresent, String mine, boolean otherPresent, String other) { - return otherPresent ? other : mine; - } - - @Override - public ByteString visitByteString( - boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) { - return otherPresent ? other : mine; - } - - @Override - public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) { - return other; - } - - @Override - public Object visitOneofInt(boolean minePresent, Object mine, Object other) { - return other; - } - - @Override - public Object visitOneofDouble(boolean minePresent, Object mine, Object other) { - return other; - } - - @Override - public Object visitOneofFloat(boolean minePresent, Object mine, Object other) { - return other; - } - - @Override - public Object visitOneofLong(boolean minePresent, Object mine, Object other) { - return other; - } - - @Override - public Object visitOneofString(boolean minePresent, Object mine, Object other) { - return other; - } - - @Override - public Object visitOneofByteString(boolean minePresent, Object mine, Object other) { - return other; - } - - @Override - public Object visitOneofMessage(boolean minePresent, Object mine, Object other) { - if (minePresent) { - return visitMessage((MessageLite) mine, (MessageLite) other); - } - return other; - } - - @Override - public void visitOneofNotSet(boolean minePresent) { - return; - } - - @SuppressWarnings("unchecked") // Guaranteed by runtime. - @Override - public T visitMessage(T mine, T other) { - if (mine != null && other != null) { - return (T) mine.toBuilder().mergeFrom(other).build(); - } - - return mine != null ? mine : other; - } - - @Override - public ProtobufList visitList(ProtobufList mine, ProtobufList other) { - int size = mine.size(); - int otherSize = other.size(); - if (size > 0 && otherSize > 0) { - if (!mine.isModifiable()) { - mine = mine.mutableCopyWithCapacity(size + otherSize); - } - mine.addAll(other); - } - - return size > 0 ? mine : other; - } - - @Override - public BooleanList visitBooleanList(BooleanList mine, BooleanList other) { - int size = mine.size(); - int otherSize = other.size(); - if (size > 0 && otherSize > 0) { - if (!mine.isModifiable()) { - mine = mine.mutableCopyWithCapacity(size + otherSize); - } - mine.addAll(other); - } - - return size > 0 ? mine : other; - } - - @Override - public IntList visitIntList(IntList mine, IntList other) { - int size = mine.size(); - int otherSize = other.size(); - if (size > 0 && otherSize > 0) { - if (!mine.isModifiable()) { - mine = mine.mutableCopyWithCapacity(size + otherSize); - } - mine.addAll(other); - } - - return size > 0 ? mine : other; - } - - @Override - public DoubleList visitDoubleList(DoubleList mine, DoubleList other) { - int size = mine.size(); - int otherSize = other.size(); - if (size > 0 && otherSize > 0) { - if (!mine.isModifiable()) { - mine = mine.mutableCopyWithCapacity(size + otherSize); - } - mine.addAll(other); - } - - return size > 0 ? mine : other; - } - - @Override - public FloatList visitFloatList(FloatList mine, FloatList other) { - int size = mine.size(); - int otherSize = other.size(); - if (size > 0 && otherSize > 0) { - if (!mine.isModifiable()) { - mine = mine.mutableCopyWithCapacity(size + otherSize); - } - mine.addAll(other); - } - - return size > 0 ? mine : other; - } - - @Override - public LongList visitLongList(LongList mine, LongList other) { - int size = mine.size(); - int otherSize = other.size(); - if (size > 0 && otherSize > 0) { - if (!mine.isModifiable()) { - mine = mine.mutableCopyWithCapacity(size + otherSize); - } - mine.addAll(other); - } - - return size > 0 ? mine : other; - } - - @Override - public FieldSet visitExtensions( - FieldSet mine, - FieldSet other) { - if (mine.isImmutable()) { - mine = mine.clone(); - } - mine.mergeFrom(other); - return mine; - } - - @Override - public UnknownFieldSetLite visitUnknownFields( - UnknownFieldSetLite mine, - UnknownFieldSetLite other) { - return other == UnknownFieldSetLite.getDefaultInstance() - ? mine : UnknownFieldSetLite.mutableCopyOf(mine, other); - } - - @Override - public MapFieldLite visitMap(MapFieldLite mine, MapFieldLite other) { - if (!other.isEmpty()) { - if (!mine.isMutable()) { - mine = mine.mutableCopy(); - } - mine.mergeFrom(other); - } - return mine; - } - } } diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java index 592869a1d9a12..86f88a0228f2a 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java @@ -38,6 +38,11 @@ import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.FileDescriptor; import com.google.protobuf.Descriptors.OneofDescriptor; +import com.google.protobuf.Internal.BooleanList; +import com.google.protobuf.Internal.DoubleList; +import com.google.protobuf.Internal.FloatList; +import com.google.protobuf.Internal.IntList; +import com.google.protobuf.Internal.LongList; // In opensource protobuf, we have versioned this GeneratedMessageV3 class to GeneratedMessageV3V3 and // in the future may have GeneratedMessageV3V4 etc. This allows us to change some aspects of this // class without breaking binary compatibility with old generated code that still subclasses @@ -76,9 +81,9 @@ public abstract class GeneratedMessageV3 extends AbstractMessage private static final long serialVersionUID = 1L; /** - * For testing. Allows a test to disable the optimization that avoids using - * field builders for nested messages until they are requested. By disabling - * this optimization, existing tests can be reused to test the field builders. + * For testing. Allows a test to disable the optimization that avoids using field builders for + * nested messages until they are requested. By disabling this optimization, existing tests can be + * reused to test the field builders. */ protected static boolean alwaysUseFieldBuilders = false; @@ -100,13 +105,20 @@ public Parser getParserForType() { } /** - * For testing. Allows a test to disable the optimization that avoids using - * field builders for nested messages until they are requested. By disabling - * this optimization, existing tests can be reused to test the field builders. - * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}. + * @see #setAlwaysUseFieldBuildersForTesting(boolean) */ static void enableAlwaysUseFieldBuildersForTesting() { - alwaysUseFieldBuilders = true; + setAlwaysUseFieldBuildersForTesting(true); + } + + /** + * For testing. Allows a test to disable/re-enable the optimization that avoids + * using field builders for nested messages until they are requested. By disabling + * this optimization, existing tests can be reused to test the field builders. + * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}. + */ + static void setAlwaysUseFieldBuildersForTesting(boolean useBuilders) { + alwaysUseFieldBuilders = useBuilders; } /** @@ -121,9 +133,24 @@ public Descriptor getDescriptorForType() { return internalGetFieldAccessorTable().descriptor; } + protected void mergeFromAndMakeImmutableInternal( + CodedInputStream input, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + Schema schema = + (Schema) Protobuf.getInstance().schemaFor(this); + try { + schema.mergeFrom(this, CodedInputStreamReader.forCodedInput(input), extensionRegistry); + } catch (InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (IOException e) { + throw new InvalidProtocolBufferException(e).setUnfinishedMessage(this); + } + schema.makeImmutable(this); + } + /** * Internal helper to return a modifiable map containing all the fields. - * The returned Map is modifialbe so that the caller can add additional + * The returned Map is modifiable so that the caller can add additional * extension fields to implement {@link #getAllFields()}. * * @param getBytesForString whether to generate ByteString for string fields @@ -293,16 +320,17 @@ protected boolean parseUnknownField( return unknownFields.mergeFieldFrom(tag, input); } + /** + * Delegates to parseUnknownField. This method is obsolete, but we must retain it for + * compatibility with older generated code. + */ protected boolean parseUnknownFieldProto3( CodedInputStream input, UnknownFieldSet.Builder unknownFields, ExtensionRegistryLite extensionRegistry, int tag) throws IOException { - if (input.shouldDiscardUnknownFieldsProto3()) { - return input.skipField(tag); - } - return unknownFields.mergeFieldFrom(tag, input); + return parseUnknownField(input, unknownFields, extensionRegistry, tag); } protected static M parseWithIOException(Parser parser, InputStream input) @@ -359,6 +387,81 @@ protected static M parseDelimitedWithIOException(Parser p } } + protected static boolean canUseUnsafe() { + return UnsafeUtil.hasUnsafeArrayOperations() && UnsafeUtil.hasUnsafeByteBufferOperations(); + } + + protected static IntList emptyIntList() { + return IntArrayList.emptyList(); + } + + protected static IntList newIntList() { + return new IntArrayList(); + } + + protected static IntList mutableCopy(IntList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + } + + protected static LongList emptyLongList() { + return LongArrayList.emptyList(); + } + + protected static LongList newLongList() { + return new LongArrayList(); + } + + protected static LongList mutableCopy(LongList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + } + + protected static FloatList emptyFloatList() { + return FloatArrayList.emptyList(); + } + + protected static FloatList newFloatList() { + return new FloatArrayList(); + } + + protected static FloatList mutableCopy(FloatList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + } + + protected static DoubleList emptyDoubleList() { + return DoubleArrayList.emptyList(); + } + + protected static DoubleList newDoubleList() { + return new DoubleArrayList(); + } + + protected static DoubleList mutableCopy(DoubleList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + } + + protected static BooleanList emptyBooleanList() { + return BooleanArrayList.emptyList(); + } + + protected static BooleanList newBooleanList() { + return new BooleanArrayList(); + } + + protected static BooleanList mutableCopy(BooleanList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + } + + @Override public void writeTo(final CodedOutputStream output) throws IOException { MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false); @@ -378,6 +481,29 @@ public int getSerializedSize() { + /** + * This class is used to make a generated protected method inaccessible from user's code (e.g., + * the {@link #newInstance} method below). When this class is used as a parameter's type in a + * generated protected method, the method is visible to user's code in the same package, but + * since the constructor of this class is private to protobuf runtime, user's code can't obtain + * an instance of this class and as such can't actually make a method call on the protected + * method. + */ + protected static final class UnusedPrivateParameter { + static final UnusedPrivateParameter INSTANCE = new UnusedPrivateParameter(); + + private UnusedPrivateParameter() { + } + } + + /** + * Creates a new instance of this message type. Overridden in the generated code. + */ + @SuppressWarnings({"unused"}) + protected Object newInstance(UnusedPrivateParameter unused) { + throw new UnsupportedOperationException("This method must be overridden by the subclass."); + } + /** * Used by parsing constructors in generated classes. */ @@ -389,7 +515,7 @@ protected void makeExtensionsImmutable() { * TODO(xiaofeng): remove this after b/29368482 is fixed. We need to move this * interface to AbstractMessage in order to versioning GeneratedMessageV3 but * this move breaks binary compatibility for AppEngine. After AppEngine is - * fixed we can exlude this from google3. + * fixed we can exclude this from google3. */ protected interface BuilderParent extends AbstractMessage.BuilderParent {} @@ -630,20 +756,23 @@ public BuilderType addRepeatedField(final FieldDescriptor field, final Object va return (BuilderType) this; } - @Override - public BuilderType setUnknownFields(final UnknownFieldSet unknownFields) { + private BuilderType setUnknownFieldsInternal(final UnknownFieldSet unknownFields) { this.unknownFields = unknownFields; onChanged(); return (BuilderType) this; } + @Override + public BuilderType setUnknownFields(final UnknownFieldSet unknownFields) { + return setUnknownFieldsInternal(unknownFields); + } + + /** + * This method is obsolete, but we must retain it for compatibility with + * older generated code. + */ protected BuilderType setUnknownFieldsProto3(final UnknownFieldSet unknownFields) { - if (CodedInputStream.getProto3DiscardUnknownFieldsDefault()) { - return (BuilderType) this; - } - this.unknownFields = unknownFields; - onChanged(); - return (BuilderType) this; + return setUnknownFieldsInternal(unknownFields); } @Override @@ -655,6 +784,7 @@ public BuilderType mergeUnknownFields( .build()); } + @Override public boolean isInitialized() { for (final FieldDescriptor field : getDescriptorForType().getFields()) { @@ -1004,19 +1134,17 @@ protected boolean parseUnknownField( getDescriptorForType(), new MessageReflection.ExtensionAdapter(extensions), tag); } + /** + * Delegates to parseUnknownField. This method is obsolete, but we must retain it for + * compatibility with older generated code. + */ @Override protected boolean parseUnknownFieldProto3( CodedInputStream input, UnknownFieldSet.Builder unknownFields, ExtensionRegistryLite extensionRegistry, int tag) throws IOException { - return MessageReflection.mergeFieldFrom( - input, - input.shouldDiscardUnknownFieldsProto3() ? null : unknownFields, - extensionRegistry, - getDescriptorForType(), - new MessageReflection.ExtensionAdapter(extensions), - tag); + return parseUnknownField(input, unknownFields, extensionRegistry, tag); } @@ -1227,7 +1355,7 @@ public abstract static class ExtendableBuilder< extends Builder implements ExtendableMessageOrBuilder { - private FieldSet extensions = FieldSet.emptySet(); + private FieldSet.Builder extensions; protected ExtendableBuilder() {} @@ -1238,18 +1366,18 @@ protected ExtendableBuilder( // For immutable message conversion. void internalSetExtensionSet(FieldSet extensions) { - this.extensions = extensions; + this.extensions = FieldSet.Builder.fromFieldSet(extensions); } @Override public BuilderType clear() { - extensions = FieldSet.emptySet(); + extensions = null; return super.clear(); } private void ensureExtensionsIsMutable() { - if (extensions.isImmutable()) { - extensions = extensions.clone(); + if (extensions == null) { + extensions = FieldSet.newBuilder(); } } @@ -1272,7 +1400,7 @@ public final boolean hasExtension(final ExtensionLite Extension extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); - return extensions.hasField(extension.getDescriptor()); + return extensions == null ? false : extensions.hasField(extension.getDescriptor()); } /** Get the number of elements in a repeated extension. */ @@ -1283,7 +1411,7 @@ public final int getExtensionCount( verifyExtensionContainingType(extension); final FieldDescriptor descriptor = extension.getDescriptor(); - return extensions.getRepeatedFieldCount(descriptor); + return extensions == null ? 0 : extensions.getRepeatedFieldCount(descriptor); } /** Get the value of an extension. */ @@ -1293,7 +1421,7 @@ public final Type getExtension(final ExtensionLite ext verifyExtensionContainingType(extension); FieldDescriptor descriptor = extension.getDescriptor(); - final Object value = extensions.getField(descriptor); + final Object value = extensions == null ? null : extensions.getField(descriptor); if (value == null) { if (descriptor.isRepeated()) { return (Type) Collections.emptyList(); @@ -1317,8 +1445,11 @@ public final Type getExtension( verifyExtensionContainingType(extension); FieldDescriptor descriptor = extension.getDescriptor(); - return (Type) extension.singularFromReflectionType( - extensions.getRepeatedField(descriptor, index)); + if (extensions == null) { + throw new IndexOutOfBoundsException(); + } + return (Type) + extension.singularFromReflectionType(extensions.getRepeatedField(descriptor, index)); } /** Set the value of an extension. */ @@ -1367,8 +1498,7 @@ public final BuilderType addExtension( } /** Clear an extension. */ - public final BuilderType clearExtension( - final ExtensionLite extensionLite) { + public final BuilderType clearExtension(final ExtensionLite extensionLite) { Extension extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1469,7 +1599,7 @@ public BuilderType clearExtension( /** Called by subclasses to check if all extensions are initialized. */ protected boolean extensionsAreInitialized() { - return extensions.isInitialized(); + return extensions == null ? true : extensions.isInitialized(); } /** @@ -1477,8 +1607,9 @@ protected boolean extensionsAreInitialized() { * building the message. */ private FieldSet buildExtensions() { - extensions.makeImmutable(); - return extensions; + return extensions == null + ? (FieldSet) FieldSet.emptySet() + : extensions.build(); } @Override @@ -1492,7 +1623,9 @@ public boolean isInitialized() { @Override public Map getAllFields() { final Map result = super.getAllFieldsMutable(); - result.putAll(extensions.getAllFields()); + if (extensions != null) { + result.putAll(extensions.getAllFields()); + } return Collections.unmodifiableMap(result); } @@ -1500,7 +1633,7 @@ public Map getAllFields() { public Object getField(final FieldDescriptor field) { if (field.isExtension()) { verifyContainingType(field); - final Object value = extensions.getField(field); + final Object value = extensions == null ? null : extensions.getField(field); if (value == null) { if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { // Lacking an ExtensionRegistry, we have no way to determine the @@ -1517,11 +1650,44 @@ public Object getField(final FieldDescriptor field) { } } + @Override + public Message.Builder getFieldBuilder(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + if (field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { + throw new UnsupportedOperationException( + "getFieldBuilder() called on a non-Message type."); + } + ensureExtensionsIsMutable(); + final Object value = extensions.getFieldAllowBuilders(field); + if (value == null) { + Message.Builder builder = DynamicMessage.newBuilder(field.getMessageType()); + extensions.setField(field, builder); + onChanged(); + return builder; + } else { + if (value instanceof Message.Builder) { + return (Message.Builder) value; + } else if (value instanceof Message) { + Message.Builder builder = ((Message) value).toBuilder(); + extensions.setField(field, builder); + onChanged(); + return builder; + } else { + throw new UnsupportedOperationException( + "getRepeatedFieldBuilder() called on a non-Message type."); + } + } + } else { + return super.getFieldBuilder(field); + } + } + @Override public int getRepeatedFieldCount(final FieldDescriptor field) { if (field.isExtension()) { verifyContainingType(field); - return extensions.getRepeatedFieldCount(field); + return extensions == null ? 0 : extensions.getRepeatedFieldCount(field); } else { return super.getRepeatedFieldCount(field); } @@ -1532,17 +1698,46 @@ public Object getRepeatedField(final FieldDescriptor field, final int index) { if (field.isExtension()) { verifyContainingType(field); + if (extensions == null) { + throw new IndexOutOfBoundsException(); + } return extensions.getRepeatedField(field, index); } else { return super.getRepeatedField(field, index); } } + @Override + public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, final int index) { + if (field.isExtension()) { + verifyContainingType(field); + ensureExtensionsIsMutable(); + if (field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { + throw new UnsupportedOperationException( + "getRepeatedFieldBuilder() called on a non-Message type."); + } + final Object value = extensions.getRepeatedFieldAllowBuilders(field, index); + if (value instanceof Message.Builder) { + return (Message.Builder) value; + } else if (value instanceof Message) { + Message.Builder builder = ((Message) value).toBuilder(); + extensions.setRepeatedField(field, index, builder); + onChanged(); + return builder; + } else { + throw new UnsupportedOperationException( + "getRepeatedFieldBuilder() called on a non-Message type."); + } + } else { + return super.getRepeatedFieldBuilder(field, index); + } + } + @Override public boolean hasField(final FieldDescriptor field) { if (field.isExtension()) { verifyContainingType(field); - return extensions.hasField(field); + return extensions == null ? false : extensions.hasField(field); } else { return super.hasField(field); } @@ -1603,10 +1798,21 @@ public BuilderType addRepeatedField(final FieldDescriptor field, } } + @Override + public Message.Builder newBuilderForField(final FieldDescriptor field) { + if (field.isExtension()) { + return DynamicMessage.newBuilder(field.getMessageType()); + } else { + return super.newBuilderForField(field); + } + } + protected final void mergeExtensionFields(final ExtendableMessage other) { - ensureExtensionsIsMutable(); - extensions.mergeFrom(other.extensions); - onChanged(); + if (other.extensions != null) { + ensureExtensionsIsMutable(); + extensions.mergeFrom(other.extensions); + onChanged(); + } } private void verifyContainingType(final FieldDescriptor field) { @@ -1666,15 +1872,13 @@ private static Object invokeOrDie( } /** - * Gets the map field with the given field number. This method should be - * overridden in the generated message class if the message contains map - * fields. + * Gets the map field with the given field number. This method should be overridden in the + * generated message class if the message contains map fields. * - * Unlike other field types, reflection support for map fields can't be - * implemented based on generated public API because we need to access a - * map field as a list in reflection API but the generated API only allows - * us to access it as a map. This method returns the underlying map field - * directly and thus enables us to access the map field as a list. + *

Unlike other field types, reflection support for map fields can't be implemented based on + * generated public API because we need to access a map field as a list in reflection API but the + * generated API only allows us to access it as a map. This method returns the underlying map + * field directly and thus enables us to access the map field as a list. */ @SuppressWarnings({"rawtypes", "unused"}) protected MapField internalGetMapField(int fieldNumber) { @@ -1783,9 +1987,9 @@ public FieldAccessorTable ensureFieldAccessorsInitialized( int oneofsSize = oneofs.length; for (int i = 0; i < oneofsSize; i++) { - oneofs[i] = new OneofAccessor( - descriptor, camelCaseNames[i + fieldsSize], - messageClass, builderClass); + oneofs[i] = + new OneofAccessor( + descriptor, i, camelCaseNames[i + fieldsSize], messageClass, builderClass); } initialized = true; camelCaseNames = null; @@ -1853,14 +2057,22 @@ Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, /** OneofAccessor provides access to a single oneof. */ private static class OneofAccessor { OneofAccessor( - final Descriptor descriptor, final String camelCaseName, + final Descriptor descriptor, + final int oneofIndex, + final String camelCaseName, final Class messageClass, final Class builderClass) { this.descriptor = descriptor; - caseMethod = - getMethodOrDie(messageClass, "get" + camelCaseName + "Case"); - caseMethodBuilder = - getMethodOrDie(builderClass, "get" + camelCaseName + "Case"); + OneofDescriptor oneofDescriptor = descriptor.getOneofs().get(oneofIndex); + if (oneofDescriptor.isSynthetic()) { + caseMethod = null; + caseMethodBuilder = null; + fieldDescriptor = oneofDescriptor.getFields().get(0); + } else { + caseMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Case"); + caseMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Case"); + fieldDescriptor = null; + } clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); } @@ -1868,33 +2080,51 @@ private static class OneofAccessor { private final Method caseMethod; private final Method caseMethodBuilder; private final Method clearMethod; + private final FieldDescriptor fieldDescriptor; public boolean has(final GeneratedMessageV3 message) { - if (((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() == 0) { - return false; + if (fieldDescriptor != null) { + return message.hasField(fieldDescriptor); + } else { + if (((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() == 0) { + return false; + } } return true; } public boolean has(GeneratedMessageV3.Builder builder) { - if (((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() == 0) { - return false; + if (fieldDescriptor != null) { + return builder.hasField(fieldDescriptor); + } else { + if (((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() == 0) { + return false; + } } return true; } public FieldDescriptor get(final GeneratedMessageV3 message) { - int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); - if (fieldNumber > 0) { - return descriptor.findFieldByNumber(fieldNumber); + if (fieldDescriptor != null) { + return message.hasField(fieldDescriptor) ? fieldDescriptor : null; + } else { + int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); + if (fieldNumber > 0) { + return descriptor.findFieldByNumber(fieldNumber); + } } return null; } public FieldDescriptor get(GeneratedMessageV3.Builder builder) { - int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); - if (fieldNumber > 0) { - return descriptor.findFieldByNumber(fieldNumber); + if (fieldDescriptor != null) { + return builder.hasField(fieldDescriptor) ? fieldDescriptor : null; + } else { + int fieldNumber = + ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); + if (fieldNumber > 0) { + return descriptor.findFieldByNumber(fieldNumber); + } } return null; } @@ -1904,68 +2134,151 @@ public void clear(final Builder builder) { } } - private static boolean supportFieldPresence(FileDescriptor file) { - return file.getSyntax() == FileDescriptor.Syntax.PROTO2; - } - // --------------------------------------------------------------- private static class SingularFieldAccessor implements FieldAccessor { + private interface MethodInvoker { + Object get(final GeneratedMessageV3 message); + + Object get(GeneratedMessageV3.Builder builder); + + int getOneofFieldNumber(final GeneratedMessageV3 message); + + int getOneofFieldNumber(final GeneratedMessageV3.Builder builder); + + void set(final GeneratedMessageV3.Builder builder, final Object value); + + boolean has(final GeneratedMessageV3 message); + + boolean has(GeneratedMessageV3.Builder builder); + + void clear(final GeneratedMessageV3.Builder builder); + } + + private static final class ReflectionInvoker implements MethodInvoker { + protected final Method getMethod; + protected final Method getMethodBuilder; + protected final Method setMethod; + protected final Method hasMethod; + protected final Method hasMethodBuilder; + protected final Method clearMethod; + protected final Method caseMethod; + protected final Method caseMethodBuilder; + + ReflectionInvoker( + final FieldDescriptor descriptor, + final String camelCaseName, + final Class messageClass, + final Class builderClass, + final String containingOneofCamelCaseName, + boolean isOneofField, + boolean hasHasMethod) { + getMethod = getMethodOrDie(messageClass, "get" + camelCaseName); + getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName); + Class type = getMethod.getReturnType(); + setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type); + hasMethod = hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null; + hasMethodBuilder = + hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null; + clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); + caseMethod = + isOneofField + ? getMethodOrDie(messageClass, "get" + containingOneofCamelCaseName + "Case") + : null; + caseMethodBuilder = + isOneofField + ? getMethodOrDie(builderClass, "get" + containingOneofCamelCaseName + "Case") + : null; + } + + @Override + public Object get(final GeneratedMessageV3 message) { + return invokeOrDie(getMethod, message); + } + + @Override + public Object get(GeneratedMessageV3.Builder builder) { + return invokeOrDie(getMethodBuilder, builder); + } + + @Override + public int getOneofFieldNumber(final GeneratedMessageV3 message) { + return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); + } + + @Override + public int getOneofFieldNumber(final GeneratedMessageV3.Builder builder) { + return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); + } + + @Override + public void set(final GeneratedMessageV3.Builder builder, final Object value) { + invokeOrDie(setMethod, builder, value); + } + + @Override + public boolean has(final GeneratedMessageV3 message) { + return (Boolean) invokeOrDie(hasMethod, message); + } + + @Override + public boolean has(GeneratedMessageV3.Builder builder) { + return (Boolean) invokeOrDie(hasMethodBuilder, builder); + } + + @Override + public void clear(final GeneratedMessageV3.Builder builder) { + invokeOrDie(clearMethod, builder); + } + } + SingularFieldAccessor( - final FieldDescriptor descriptor, final String camelCaseName, + final FieldDescriptor descriptor, + final String camelCaseName, final Class messageClass, final Class builderClass, final String containingOneofCamelCaseName) { + isOneofField = + descriptor.getContainingOneof() != null + && !descriptor.getContainingOneof().isSynthetic(); + hasHasMethod = + descriptor.getFile().getSyntax() == FileDescriptor.Syntax.PROTO2 + || descriptor.hasOptionalKeyword() + || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE); + ReflectionInvoker reflectionInvoker = + new ReflectionInvoker( + descriptor, + camelCaseName, + messageClass, + builderClass, + containingOneofCamelCaseName, + isOneofField, + hasHasMethod); field = descriptor; - isOneofField = descriptor.getContainingOneof() != null; - hasHasMethod = supportFieldPresence(descriptor.getFile()) - || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE); - getMethod = getMethodOrDie(messageClass, "get" + camelCaseName); - getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName); - type = getMethod.getReturnType(); - setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type); - hasMethod = - hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null; - hasMethodBuilder = - hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null; - clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); - caseMethod = isOneofField ? getMethodOrDie( - messageClass, "get" + containingOneofCamelCaseName + "Case") : null; - caseMethodBuilder = isOneofField ? getMethodOrDie( - builderClass, "get" + containingOneofCamelCaseName + "Case") : null; + type = reflectionInvoker.getMethod.getReturnType(); + invoker = getMethodInvoker(reflectionInvoker); + } + + static MethodInvoker getMethodInvoker(ReflectionInvoker accessor) { + return accessor; } // Note: We use Java reflection to call public methods rather than // access private fields directly as this avoids runtime security // checks. protected final Class type; - protected final Method getMethod; - protected final Method getMethodBuilder; - protected final Method setMethod; - protected final Method hasMethod; - protected final Method hasMethodBuilder; - protected final Method clearMethod; - protected final Method caseMethod; - protected final Method caseMethodBuilder; protected final FieldDescriptor field; protected final boolean isOneofField; protected final boolean hasHasMethod; - - private int getOneofFieldNumber(final GeneratedMessageV3 message) { - return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); - } - - private int getOneofFieldNumber(final GeneratedMessageV3.Builder builder) { - return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); - } + protected final MethodInvoker invoker; @Override public Object get(final GeneratedMessageV3 message) { - return invokeOrDie(getMethod, message); + return invoker.get(message); } @Override public Object get(GeneratedMessageV3.Builder builder) { - return invokeOrDie(getMethodBuilder, builder); + return invoker.get(builder); } @Override public Object getRaw(final GeneratedMessageV3 message) { @@ -1977,134 +2290,209 @@ public Object getRaw(GeneratedMessageV3.Builder builder) { } @Override public void set(final Builder builder, final Object value) { - invokeOrDie(setMethod, builder, value); + invoker.set(builder, value); } @Override public Object getRepeated(final GeneratedMessageV3 message, final int index) { - throw new UnsupportedOperationException( - "getRepeatedField() called on a singular field."); + throw new UnsupportedOperationException("getRepeatedField() called on a singular field."); } @Override public Object getRepeatedRaw(final GeneratedMessageV3 message, final int index) { throw new UnsupportedOperationException( - "getRepeatedFieldRaw() called on a singular field."); + "getRepeatedFieldRaw() called on a singular field."); } @Override public Object getRepeated(GeneratedMessageV3.Builder builder, int index) { - throw new UnsupportedOperationException( - "getRepeatedField() called on a singular field."); + throw new UnsupportedOperationException("getRepeatedField() called on a singular field."); } @Override public Object getRepeatedRaw(GeneratedMessageV3.Builder builder, int index) { throw new UnsupportedOperationException( - "getRepeatedFieldRaw() called on a singular field."); + "getRepeatedFieldRaw() called on a singular field."); } @Override public void setRepeated(final Builder builder, final int index, final Object value) { - throw new UnsupportedOperationException( - "setRepeatedField() called on a singular field."); + throw new UnsupportedOperationException("setRepeatedField() called on a singular field."); } @Override public void addRepeated(final Builder builder, final Object value) { - throw new UnsupportedOperationException( - "addRepeatedField() called on a singular field."); + throw new UnsupportedOperationException("addRepeatedField() called on a singular field."); } @Override public boolean has(final GeneratedMessageV3 message) { if (!hasHasMethod) { if (isOneofField) { - return getOneofFieldNumber(message) == field.getNumber(); + return invoker.getOneofFieldNumber(message) == field.getNumber(); } return !get(message).equals(field.getDefaultValue()); } - return (Boolean) invokeOrDie(hasMethod, message); + return invoker.has(message); } @Override public boolean has(GeneratedMessageV3.Builder builder) { if (!hasHasMethod) { if (isOneofField) { - return getOneofFieldNumber(builder) == field.getNumber(); + return invoker.getOneofFieldNumber(builder) == field.getNumber(); } return !get(builder).equals(field.getDefaultValue()); } - return (Boolean) invokeOrDie(hasMethodBuilder, builder); + return invoker.has(builder); } @Override public int getRepeatedCount(final GeneratedMessageV3 message) { throw new UnsupportedOperationException( - "getRepeatedFieldSize() called on a singular field."); + "getRepeatedFieldSize() called on a singular field."); } @Override public int getRepeatedCount(GeneratedMessageV3.Builder builder) { throw new UnsupportedOperationException( - "getRepeatedFieldSize() called on a singular field."); + "getRepeatedFieldSize() called on a singular field."); } @Override public void clear(final Builder builder) { - invokeOrDie(clearMethod, builder); + invoker.clear(builder); } @Override public Message.Builder newBuilder() { throw new UnsupportedOperationException( - "newBuilderForField() called on a non-Message type."); + "newBuilderForField() called on a non-Message type."); } @Override public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) { - throw new UnsupportedOperationException( - "getFieldBuilder() called on a non-Message type."); + throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type."); } @Override public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) { throw new UnsupportedOperationException( - "getRepeatedFieldBuilder() called on a non-Message type."); + "getRepeatedFieldBuilder() called on a non-Message type."); } } private static class RepeatedFieldAccessor implements FieldAccessor { + interface MethodInvoker { + public Object get(final GeneratedMessageV3 message); + + public Object get(GeneratedMessageV3.Builder builder); + + Object getRepeated(final GeneratedMessageV3 message, final int index); + + Object getRepeated(GeneratedMessageV3.Builder builder, int index); + + void setRepeated( + final GeneratedMessageV3.Builder builder, final int index, final Object value); + + void addRepeated(final GeneratedMessageV3.Builder builder, final Object value); + + int getRepeatedCount(final GeneratedMessageV3 message); + + int getRepeatedCount(GeneratedMessageV3.Builder builder); + + void clear(final GeneratedMessageV3.Builder builder); + } + + private static final class ReflectionInvoker implements MethodInvoker { + protected final Method getMethod; + protected final Method getMethodBuilder; + protected final Method getRepeatedMethod; + protected final Method getRepeatedMethodBuilder; + protected final Method setRepeatedMethod; + protected final Method addRepeatedMethod; + protected final Method getCountMethod; + protected final Method getCountMethodBuilder; + protected final Method clearMethod; + + ReflectionInvoker( + final FieldDescriptor descriptor, + final String camelCaseName, + final Class messageClass, + final Class builderClass) { + getMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "List"); + getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "List"); + getRepeatedMethod = getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE); + getRepeatedMethodBuilder = + getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE); + Class type = getRepeatedMethod.getReturnType(); + setRepeatedMethod = + getMethodOrDie(builderClass, "set" + camelCaseName, Integer.TYPE, type); + addRepeatedMethod = getMethodOrDie(builderClass, "add" + camelCaseName, type); + getCountMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Count"); + getCountMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Count"); + clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); + } + + @Override + public Object get(final GeneratedMessageV3 message) { + return invokeOrDie(getMethod, message); + } + + @Override + public Object get(GeneratedMessageV3.Builder builder) { + return invokeOrDie(getMethodBuilder, builder); + } + + @Override + public Object getRepeated( + final GeneratedMessageV3 message, final int index) { + return invokeOrDie(getRepeatedMethod, message, index); + } + + @Override + public Object getRepeated(GeneratedMessageV3.Builder builder, int index) { + return invokeOrDie(getRepeatedMethodBuilder, builder, index); + } + + @Override + public void setRepeated( + final GeneratedMessageV3.Builder builder, final int index, final Object value) { + invokeOrDie(setRepeatedMethod, builder, index, value); + } + + @Override + public void addRepeated( + final GeneratedMessageV3.Builder builder, final Object value) { + invokeOrDie(addRepeatedMethod, builder, value); + } + + @Override + public int getRepeatedCount(final GeneratedMessageV3 message) { + return (Integer) invokeOrDie(getCountMethod, message); + } + + @Override + public int getRepeatedCount(GeneratedMessageV3.Builder builder) { + return (Integer) invokeOrDie(getCountMethodBuilder, builder); + } + + @Override + public void clear(final GeneratedMessageV3.Builder builder) { + invokeOrDie(clearMethod, builder); + } + } + protected final Class type; - protected final Method getMethod; - protected final Method getMethodBuilder; - protected final Method getRepeatedMethod; - protected final Method getRepeatedMethodBuilder; - protected final Method setRepeatedMethod; - protected final Method addRepeatedMethod; - protected final Method getCountMethod; - protected final Method getCountMethodBuilder; - protected final Method clearMethod; + protected final MethodInvoker invoker; RepeatedFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, final Class builderClass) { - getMethod = getMethodOrDie(messageClass, - "get" + camelCaseName + "List"); - getMethodBuilder = getMethodOrDie(builderClass, - "get" + camelCaseName + "List"); - getRepeatedMethod = - getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE); - getRepeatedMethodBuilder = - getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE); - type = getRepeatedMethod.getReturnType(); - setRepeatedMethod = - getMethodOrDie(builderClass, "set" + camelCaseName, - Integer.TYPE, type); - addRepeatedMethod = - getMethodOrDie(builderClass, "add" + camelCaseName, type); - getCountMethod = - getMethodOrDie(messageClass, "get" + camelCaseName + "Count"); - getCountMethodBuilder = - getMethodOrDie(builderClass, "get" + camelCaseName + "Count"); + ReflectionInvoker reflectionInvoker = + new ReflectionInvoker(descriptor, camelCaseName, messageClass, builderClass); + type = reflectionInvoker.getRepeatedMethod.getReturnType(); + invoker = getMethodInvoker(reflectionInvoker); + } - clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); + static MethodInvoker getMethodInvoker(ReflectionInvoker accessor) { + return accessor; } @Override public Object get(final GeneratedMessageV3 message) { - return invokeOrDie(getMethod, message); + return invoker.get(message); } @Override public Object get(GeneratedMessageV3.Builder builder) { - return invokeOrDie(getMethodBuilder, builder); + return invoker.get(builder); } @Override public Object getRaw(final GeneratedMessageV3 message) { @@ -2127,11 +2515,11 @@ public void set(final Builder builder, final Object value) { } @Override public Object getRepeated(final GeneratedMessageV3 message, final int index) { - return invokeOrDie(getRepeatedMethod, message, index); + return invoker.getRepeated(message, index); } @Override public Object getRepeated(GeneratedMessageV3.Builder builder, int index) { - return invokeOrDie(getRepeatedMethodBuilder, builder, index); + return invoker.getRepeated(builder, index); } @Override public Object getRepeatedRaw(GeneratedMessageV3 message, int index) { @@ -2143,48 +2531,45 @@ public Object getRepeatedRaw(GeneratedMessageV3.Builder builder, int index) { } @Override public void setRepeated(final Builder builder, final int index, final Object value) { - invokeOrDie(setRepeatedMethod, builder, index, value); + invoker.setRepeated(builder, index, value); } @Override public void addRepeated(final Builder builder, final Object value) { - invokeOrDie(addRepeatedMethod, builder, value); + invoker.addRepeated(builder, value); } @Override public boolean has(final GeneratedMessageV3 message) { - throw new UnsupportedOperationException( - "hasField() called on a repeated field."); + throw new UnsupportedOperationException("hasField() called on a repeated field."); } @Override public boolean has(GeneratedMessageV3.Builder builder) { - throw new UnsupportedOperationException( - "hasField() called on a repeated field."); + throw new UnsupportedOperationException("hasField() called on a repeated field."); } @Override public int getRepeatedCount(final GeneratedMessageV3 message) { - return (Integer) invokeOrDie(getCountMethod, message); + return invoker.getRepeatedCount(message); } @Override public int getRepeatedCount(GeneratedMessageV3.Builder builder) { - return (Integer) invokeOrDie(getCountMethodBuilder, builder); + return invoker.getRepeatedCount(builder); } @Override public void clear(final Builder builder) { - invokeOrDie(clearMethod, builder); + invoker.clear(builder); } @Override public Message.Builder newBuilder() { throw new UnsupportedOperationException( - "newBuilderForField() called on a non-Message type."); + "newBuilderForField() called on a non-Message type."); } @Override public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) { - throw new UnsupportedOperationException( - "getFieldBuilder() called on a non-Message type."); + throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type."); } @Override public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) { throw new UnsupportedOperationException( - "getRepeatedFieldBuilder() called on a non-Message type."); + "getRepeatedFieldBuilder() called on a non-Message type."); } } @@ -2236,7 +2621,7 @@ private Message coerceType(Message value) { @Override @SuppressWarnings("unchecked") public Object get(GeneratedMessageV3 message) { - List result = new ArrayList(); + List result = new ArrayList<>(); for (int i = 0; i < getRepeatedCount(message); i++) { result.add(getRepeated(message, i)); } @@ -2246,7 +2631,7 @@ public Object get(GeneratedMessageV3 message) { @Override @SuppressWarnings("unchecked") public Object get(Builder builder) { - List result = new ArrayList(); + List result = new ArrayList<>(); for (int i = 0; i < getRepeatedCount(builder); i++) { result.add(getRepeated(builder, i)); } @@ -2359,10 +2744,8 @@ private static final class SingularEnumFieldAccessor enumDescriptor = descriptor.getEnumType(); - valueOfMethod = getMethodOrDie(type, "valueOf", - EnumValueDescriptor.class); - getValueDescriptorMethod = - getMethodOrDie(type, "getValueDescriptor"); + valueOfMethod = getMethodOrDie(type, "valueOf", EnumValueDescriptor.class); + getValueDescriptorMethod = getMethodOrDie(type, "getValueDescriptor"); supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue(); if (supportUnknownEnumValue) { @@ -2424,10 +2807,8 @@ private static final class RepeatedEnumFieldAccessor enumDescriptor = descriptor.getEnumType(); - valueOfMethod = getMethodOrDie(type, "valueOf", - EnumValueDescriptor.class); - getValueDescriptorMethod = - getMethodOrDie(type, "getValueDescriptor"); + valueOfMethod = getMethodOrDie(type, "valueOf", EnumValueDescriptor.class); + getValueDescriptorMethod = getMethodOrDie(type, "getValueDescriptor"); supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue(); if (supportUnknownEnumValue) { @@ -2455,7 +2836,7 @@ private static final class RepeatedEnumFieldAccessor @Override @SuppressWarnings("unchecked") public Object get(final GeneratedMessageV3 message) { - final List newList = new ArrayList(); + final List newList = new ArrayList<>(); final int size = getRepeatedCount(message); for (int i = 0; i < size; i++) { newList.add(getRepeated(message, i)); @@ -2466,7 +2847,7 @@ public Object get(final GeneratedMessageV3 message) { @Override @SuppressWarnings("unchecked") public Object get(final GeneratedMessageV3.Builder builder) { - final List newList = new ArrayList(); + final List newList = new ArrayList<>(); final int size = getRepeatedCount(builder); for (int i = 0; i < size; i++) { newList.add(getRepeated(builder, i)); @@ -2475,35 +2856,31 @@ public Object get(final GeneratedMessageV3.Builder builder) { } @Override - public Object getRepeated(final GeneratedMessageV3 message, - final int index) { + public Object getRepeated(final GeneratedMessageV3 message, final int index) { if (supportUnknownEnumValue) { int value = (Integer) invokeOrDie(getRepeatedValueMethod, message, index); return enumDescriptor.findValueByNumberCreatingIfUnknown(value); } - return invokeOrDie(getValueDescriptorMethod, - super.getRepeated(message, index)); + return invokeOrDie(getValueDescriptorMethod, super.getRepeated(message, index)); } + @Override - public Object getRepeated(final GeneratedMessageV3.Builder builder, - final int index) { + public Object getRepeated(final GeneratedMessageV3.Builder builder, final int index) { if (supportUnknownEnumValue) { int value = (Integer) invokeOrDie(getRepeatedValueMethodBuilder, builder, index); return enumDescriptor.findValueByNumberCreatingIfUnknown(value); } - return invokeOrDie(getValueDescriptorMethod, - super.getRepeated(builder, index)); + return invokeOrDie(getValueDescriptorMethod, super.getRepeated(builder, index)); } + @Override - public void setRepeated(final Builder builder, - final int index, final Object value) { + public void setRepeated(final Builder builder, final int index, final Object value) { if (supportUnknownEnumValue) { invokeOrDie(setRepeatedValueMethod, builder, index, ((EnumValueDescriptor) value).getNumber()); return; } - super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, - value)); + super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, value)); } @Override public void addRepeated(final Builder builder, final Object value) { @@ -2599,7 +2976,8 @@ private Object coerceType(final Object value) { // DynamicMessage -- we should accept it. In this case we can make // a copy of the message. return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) - .mergeFrom((Message) value).buildPartial(); + .mergeFrom((Message) value) + .buildPartial(); } } @@ -2642,13 +3020,13 @@ private Object coerceType(final Object value) { // DynamicMessage -- we should accept it. In this case we can make // a copy of the message. return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) - .mergeFrom((Message) value).build(); + .mergeFrom((Message) value) + .build(); } } @Override - public void setRepeated(final Builder builder, - final int index, final Object value) { + public void setRepeated(final Builder builder, final int index, final Object value) { super.setRepeated(builder, index, coerceType(value)); } @Override @@ -2679,12 +3057,10 @@ protected Object writeReplace() throws ObjectStreamException { } /** - * Checks that the {@link Extension} is non-Lite and returns it as a - * {@link GeneratedExtension}. + * Checks that the {@link Extension} is non-Lite and returns it as a {@link GeneratedExtension}. */ private static , T> - Extension checkNotLite( - ExtensionLite extension) { + Extension checkNotLite(ExtensionLite extension) { if (extension.isLite()) { throw new IllegalArgumentException("Expected non-lite extension."); } @@ -2736,7 +3112,7 @@ protected static void serializeIntegerMapTo( serializeMapTo(out, m, defaultEntry, fieldNumber); return; } - // Sorting the unboxed keys and then look up the values during serialziation is 2x faster + // Sorting the unboxed keys and then look up the values during serialization is 2x faster // than sorting map entries with a custom comparator directly. int[] keys = new int[m.size()]; int index = 0; @@ -2792,7 +3168,7 @@ protected static void serializeStringMapTo( return; } - // Sorting the String keys and then look up the values during serialziation is 25% faster than + // Sorting the String keys and then look up the values during serialization is 25% faster than // sorting map entries with a custom comparator directly. String[] keys = new String[m.size()]; keys = m.keySet().toArray(keys); @@ -2853,3 +3229,4 @@ private static void serializeMapTo( } } } + diff --git a/java/core/src/main/java/com/google/protobuf/IntArrayList.java b/java/core/src/main/java/com/google/protobuf/IntArrayList.java index aff5c21b2603f..9daeebed99236 100644 --- a/java/core/src/main/java/com/google/protobuf/IntArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/IntArrayList.java @@ -45,7 +45,7 @@ final class IntArrayList extends AbstractProtobufList implements IntList, RandomAccess, PrimitiveNonBoxingCollection { - private static final IntArrayList EMPTY_LIST = new IntArrayList(); + private static final IntArrayList EMPTY_LIST = new IntArrayList(new int[0], 0); static { EMPTY_LIST.makeImmutable(); } @@ -54,9 +54,7 @@ public static IntArrayList emptyList() { return EMPTY_LIST; } - /** - * The backing store for the list. - */ + /** The backing store for the list. */ private int[] array; /** @@ -65,22 +63,31 @@ public static IntArrayList emptyList() { */ private int size; - /** - * Constructs a new mutable {@code IntArrayList} with default capacity. - */ + /** Constructs a new mutable {@code IntArrayList} with default capacity. */ IntArrayList() { this(new int[DEFAULT_CAPACITY], 0); } /** - * Constructs a new mutable {@code IntArrayList} - * containing the same elements as {@code other}. + * Constructs a new mutable {@code IntArrayList} containing the same elements as {@code other}. */ private IntArrayList(int[] other, int size) { array = other; this.size = size; } + @Override + protected void removeRange(int fromIndex, int toIndex) { + ensureIsMutable(); + if (toIndex < fromIndex) { + throw new IndexOutOfBoundsException("toIndex < fromIndex"); + } + + System.arraycopy(array, toIndex, array, fromIndex, size - toIndex); + size -= (toIndex - fromIndex); + modCount++; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -132,6 +139,26 @@ public int getInt(int index) { return array[index]; } + @Override + public int indexOf(Object element) { + if (!(element instanceof Integer)) { + return -1; + } + int unboxedElement = (Integer) element; + int numElems = size(); + for (int i = 0; i < numElems; i++) { + if (array[i] == unboxedElement) { + return i; + } + } + return -1; + } + + @Override + public boolean contains(Object element) { + return indexOf(element) != -1; + } + @Override public int size() { return size; @@ -151,22 +178,34 @@ public int setInt(int index, int element) { return previousValue; } + @Override + public boolean add(Integer element) { + addInt(element); + return true; + } + @Override public void add(int index, Integer element) { addInt(index, element); } - /** - * Like {@link #add(Integer)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(Integer)} but more efficient in that it doesn't box the element. */ @Override public void addInt(int element) { - addInt(size, element); + ensureIsMutable(); + if (size == array.length) { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + int[] newArray = new int[length]; + + System.arraycopy(array, 0, newArray, 0, size); + array = newArray; + } + + array[size++] = element; } - /** - * Like {@link #add(int, Integer)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(int, Integer)} but more efficient in that it doesn't box the element. */ private void addInt(int index, int element) { ensureIsMutable(); if (index < 0 || index > size) { @@ -227,26 +266,14 @@ public boolean addAll(Collection collection) { return true; } - @Override - public boolean remove(Object o) { - ensureIsMutable(); - for (int i = 0; i < size; i++) { - if (o.equals(array[i])) { - System.arraycopy(array, i + 1, array, i, size - i); - size--; - modCount++; - return true; - } - } - return false; - } - @Override public Integer remove(int index) { ensureIsMutable(); ensureIndexInRange(index); int value = array[index]; - System.arraycopy(array, index + 1, array, index, size - index); + if (index < size - 1) { + System.arraycopy(array, index + 1, array, index, size - index - 1); + } size--; modCount++; return value; diff --git a/java/core/src/main/java/com/google/protobuf/Internal.java b/java/core/src/main/java/com/google/protobuf/Internal.java index 848cad03fce6f..90643b8abb999 100644 --- a/java/core/src/main/java/com/google/protobuf/Internal.java +++ b/java/core/src/main/java/com/google/protobuf/Internal.java @@ -30,7 +30,6 @@ package com.google.protobuf; -import java.io.IOException; import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.nio.charset.Charset; @@ -45,10 +44,9 @@ import java.util.Set; /** - * The classes contained within are used internally by the Protocol Buffer - * library and generated message implementations. They are public only because - * those generated messages do not reside in the {@code protobuf} package. - * Others should not use this class directly. + * The classes contained within are used internally by the Protocol Buffer library and generated + * message implementations. They are public only because those generated messages do not reside in + * the {@code protobuf} package. Others should not use this class directly. * * @author kenton@google.com (Kenton Varda) */ @@ -59,9 +57,7 @@ private Internal() {} static final Charset UTF_8 = Charset.forName("UTF-8"); static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); - /** - * Throws an appropriate {@link NullPointerException} if the given objects is {@code null}. - */ + /** Throws an appropriate {@link NullPointerException} if the given objects is {@code null}. */ static T checkNotNull(T obj) { if (obj == null) { throw new NullPointerException(); @@ -69,9 +65,7 @@ static T checkNotNull(T obj) { return obj; } - /** - * Throws an appropriate {@link NullPointerException} if the given objects is {@code null}. - */ + /** Throws an appropriate {@link NullPointerException} if the given objects is {@code null}. */ static T checkNotNull(T obj, String message) { if (obj == null) { throw new NullPointerException(message); @@ -80,73 +74,63 @@ static T checkNotNull(T obj, String message) { } /** - * Helper called by generated code to construct default values for string - * fields. - *

- * The protocol compiler does not actually contain a UTF-8 decoder -- it - * just pushes UTF-8-encoded text around without touching it. The one place - * where this presents a problem is when generating Java string literals. - * Unicode characters in the string literal would normally need to be encoded - * using a Unicode escape sequence, which would require decoding them. - * To get around this, protoc instead embeds the UTF-8 bytes into the - * generated code and leaves it to the runtime library to decode them. - *

- * It gets worse, though. If protoc just generated a byte array, like: - * new byte[] {0x12, 0x34, 0x56, 0x78} - * Java actually generates *code* which allocates an array and then fills - * in each value. This is much less efficient than just embedding the bytes - * directly into the bytecode. To get around this, we need another - * work-around. String literals are embedded directly, so protoc actually - * generates a string literal corresponding to the bytes. The easiest way - * to do this is to use the ISO-8859-1 character set, which corresponds to - * the first 256 characters of the Unicode range. Protoc can then use - * good old CEscape to generate the string. - *

- * So we have a string literal which represents a set of bytes which - * represents another string. This function -- stringDefaultValue -- - * converts from the generated string to the string we actually want. The - * generated code calls this automatically. + * Helper called by generated code to construct default values for string fields. + * + *

The protocol compiler does not actually contain a UTF-8 decoder -- it just pushes + * UTF-8-encoded text around without touching it. The one place where this presents a problem is + * when generating Java string literals. Unicode characters in the string literal would normally + * need to be encoded using a Unicode escape sequence, which would require decoding them. To get + * around this, protoc instead embeds the UTF-8 bytes into the generated code and leaves it to the + * runtime library to decode them. + * + *

It gets worse, though. If protoc just generated a byte array, like: new byte[] {0x12, 0x34, + * 0x56, 0x78} Java actually generates *code* which allocates an array and then fills in each + * value. This is much less efficient than just embedding the bytes directly into the bytecode. To + * get around this, we need another work-around. String literals are embedded directly, so protoc + * actually generates a string literal corresponding to the bytes. The easiest way to do this is + * to use the ISO-8859-1 character set, which corresponds to the first 256 characters of the + * Unicode range. Protoc can then use good old CEscape to generate the string. + * + *

So we have a string literal which represents a set of bytes which represents another string. + * This function -- stringDefaultValue -- converts from the generated string to the string we + * actually want. The generated code calls this automatically. */ public static String stringDefaultValue(String bytes) { return new String(bytes.getBytes(ISO_8859_1), UTF_8); } /** - * Helper called by generated code to construct default values for bytes - * fields. - *

- * This is a lot like {@link #stringDefaultValue}, but for bytes fields. - * In this case we only need the second of the two hacks -- allowing us to - * embed raw bytes as a string literal with ISO-8859-1 encoding. + * Helper called by generated code to construct default values for bytes fields. + * + *

This is a lot like {@link #stringDefaultValue}, but for bytes fields. In this case we only + * need the second of the two hacks -- allowing us to embed raw bytes as a string literal with + * ISO-8859-1 encoding. */ public static ByteString bytesDefaultValue(String bytes) { return ByteString.copyFrom(bytes.getBytes(ISO_8859_1)); } /** - * Helper called by generated code to construct default values for bytes - * fields. - *

- * This is like {@link #bytesDefaultValue}, but returns a byte array. + * Helper called by generated code to construct default values for bytes fields. + * + *

This is like {@link #bytesDefaultValue}, but returns a byte array. */ public static byte[] byteArrayDefaultValue(String bytes) { return bytes.getBytes(ISO_8859_1); } /** - * Helper called by generated code to construct default values for bytes - * fields. - *

- * This is like {@link #bytesDefaultValue}, but returns a ByteBuffer. + * Helper called by generated code to construct default values for bytes fields. + * + *

This is like {@link #bytesDefaultValue}, but returns a ByteBuffer. */ public static ByteBuffer byteBufferDefaultValue(String bytes) { return ByteBuffer.wrap(byteArrayDefaultValue(bytes)); } /** - * Create a new ByteBuffer and copy all the content of {@code source} - * ByteBuffer to the new ByteBuffer. The new ByteBuffer's limit and - * capacity will be source.capacity(), and its position will be 0. - * Note that the state of {@code source} ByteBuffer won't be changed. + * Create a new ByteBuffer and copy all the content of {@code source} ByteBuffer to the new + * ByteBuffer. The new ByteBuffer's limit and capacity will be source.capacity(), and its position + * will be 0. Note that the state of {@code source} ByteBuffer won't be changed. */ public static ByteBuffer copyByteBuffer(ByteBuffer source) { // Make a duplicate of the source ByteBuffer and read data from the @@ -162,29 +146,27 @@ public static ByteBuffer copyByteBuffer(ByteBuffer source) { } /** - * Helper called by generated code to determine if a byte array is a valid - * UTF-8 encoded string such that the original bytes can be converted to - * a String object and then back to a byte array round tripping the bytes - * without loss. More precisely, returns {@code true} whenever: - *

   {@code
+   * Helper called by generated code to determine if a byte array is a valid UTF-8 encoded string
+   * such that the original bytes can be converted to a String object and then back to a byte array
+   * round tripping the bytes without loss. More precisely, returns {@code true} whenever:
+   *
+   * 
{@code
    * Arrays.equals(byteString.toByteArray(),
    *     new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
    * }
* - *

This method rejects "overlong" byte sequences, as well as - * 3-byte sequences that would map to a surrogate character, in - * accordance with the restricted definition of UTF-8 introduced in - * Unicode 3.1. Note that the UTF-8 decoder included in Oracle's - * JDK has been modified to also reject "overlong" byte sequences, - * but currently (2011) still accepts 3-byte surrogate character + *

This method rejects "overlong" byte sequences, as well as 3-byte sequences that would map to + * a surrogate character, in accordance with the restricted definition of UTF-8 introduced in + * Unicode 3.1. Note that the UTF-8 decoder included in Oracle's JDK has been modified to also + * reject "overlong" byte sequences, but currently (2011) still accepts 3-byte surrogate character * byte sequences. * *

See the Unicode Standard,
* Table 3-6. UTF-8 Bit Distribution,
* Table 3-7. Well Formed UTF-8 Byte Sequences. * - *

As of 2011-02, this method simply returns the result of {@link - * ByteString#isValidUtf8()}. Calling that method directly is preferred. + *

As of 2011-02, this method simply returns the result of {@link ByteString#isValidUtf8()}. + * Calling that method directly is preferred. * * @param byteString the string to check * @return whether the byte array is round trippable @@ -193,49 +175,49 @@ public static boolean isValidUtf8(ByteString byteString) { return byteString.isValidUtf8(); } - /** - * Like {@link #isValidUtf8(ByteString)} but for byte arrays. - */ + /** Like {@link #isValidUtf8(ByteString)} but for byte arrays. */ public static boolean isValidUtf8(byte[] byteArray) { return Utf8.isValidUtf8(byteArray); } - /** - * Helper method to get the UTF-8 bytes of a string. - */ + /** Helper method to get the UTF-8 bytes of a string. */ public static byte[] toByteArray(String value) { return value.getBytes(UTF_8); } - /** - * Helper method to convert a byte array to a string using UTF-8 encoding. - */ + /** Helper method to convert a byte array to a string using UTF-8 encoding. */ public static String toStringUtf8(byte[] bytes) { return new String(bytes, UTF_8); } /** - * Interface for an enum value or value descriptor, to be used in FieldSet. - * The lite library stores enum values directly in FieldSets but the full - * library stores EnumValueDescriptors in order to better support reflection. + * Interface for an enum value or value descriptor, to be used in FieldSet. The lite library + * stores enum values directly in FieldSets but the full library stores EnumValueDescriptors in + * order to better support reflection. */ public interface EnumLite { int getNumber(); } /** - * Interface for an object which maps integers to {@link EnumLite}s. - * {@link Descriptors.EnumDescriptor} implements this interface by mapping - * numbers to {@link Descriptors.EnumValueDescriptor}s. Additionally, - * every generated enum type has a static method internalGetValueMap() which - * returns an implementation of this type that maps numbers to enum values. + * Interface for an object which maps integers to {@link EnumLite}s. {@link + * Descriptors.EnumDescriptor} implements this interface by mapping numbers to {@link + * Descriptors.EnumValueDescriptor}s. Additionally, every generated enum type has a static method + * internalGetValueMap() which returns an implementation of this type that maps numbers to enum + * values. */ public interface EnumLiteMap { T findValueByNumber(int number); } + /** Interface for an object which verifies integers are in range. */ + public interface EnumVerifier { + boolean isInRange(int number); + } + /** * Helper method for implementing {@link Message#hashCode()} for longs. + * * @see Long#hashCode() */ public static int hashLong(long n) { @@ -243,8 +225,8 @@ public static int hashLong(long n) { } /** - * Helper method for implementing {@link Message#hashCode()} for - * booleans. + * Helper method for implementing {@link Message#hashCode()} for booleans. + * * @see Boolean#hashCode() */ public static int hashBoolean(boolean b) { @@ -253,19 +235,16 @@ public static int hashBoolean(boolean b) { /** * Helper method for implementing {@link Message#hashCode()} for enums. - *

- * This is needed because {@link java.lang.Enum#hashCode()} is final, but we - * need to use the field number as the hash code to ensure compatibility - * between statically and dynamically generated enum objects. + * + *

This is needed because {@link java.lang.Enum#hashCode()} is final, but we need to use the + * field number as the hash code to ensure compatibility between statically and dynamically + * generated enum objects. */ public static int hashEnum(EnumLite e) { return e.getNumber(); } - /** - * Helper method for implementing {@link Message#hashCode()} for - * enum lists. - */ + /** Helper method for implementing {@link Message#hashCode()} for enum lists. */ public static int hashEnumList(List list) { int hash = 1; for (EnumLite e : list) { @@ -274,9 +253,7 @@ public static int hashEnumList(List list) { return hash; } - /** - * Helper method for implementing {@link Message#equals(Object)} for bytes field. - */ + /** Helper method for implementing {@link Message#equals(Object)} for bytes field. */ public static boolean equals(List a, List b) { if (a.size() != b.size()) return false; for (int i = 0; i < a.size(); ++i) { @@ -287,9 +264,7 @@ public static boolean equals(List a, List b) { return true; } - /** - * Helper method for implementing {@link Message#hashCode()} for bytes field. - */ + /** Helper method for implementing {@link Message#hashCode()} for bytes field. */ public static int hashCode(List list) { int hash = 1; for (byte[] bytes : list) { @@ -298,9 +273,7 @@ public static int hashCode(List list) { return hash; } - /** - * Helper method for implementing {@link Message#hashCode()} for bytes field. - */ + /** Helper method for implementing {@link Message#hashCode()} for bytes field. */ public static int hashCode(byte[] bytes) { // The hash code for a byte array should be the same as the hash code for a // ByteString with the same content. This is to ensure that the generated @@ -308,10 +281,8 @@ public static int hashCode(byte[] bytes) { // based hashCode() method. return Internal.hashCode(bytes, 0, bytes.length); } - - /** - * Helper method for implementing {@link LiteralByteString#hashCode()}. - */ + + /** Helper method for implementing {@link LiteralByteString#hashCode()}. */ static int hashCode(byte[] bytes, int offset, int length) { // The hash code for a byte array should be the same as the hash code for a // ByteString with the same content. This is to ensure that the generated @@ -321,20 +292,15 @@ static int hashCode(byte[] bytes, int offset, int length) { return h == 0 ? 1 : h; } - /** - * Helper method for continuously hashing bytes. - */ + /** Helper method for continuously hashing bytes. */ static int partialHash(int h, byte[] bytes, int offset, int length) { for (int i = offset; i < offset + length; i++) { h = h * 31 + bytes[i]; } return h; } - - /** - * Helper method for implementing {@link Message#equals(Object)} for bytes - * field. - */ + + /** Helper method for implementing {@link Message#equals(Object)} for bytes field. */ public static boolean equalsByteBuffer(ByteBuffer a, ByteBuffer b) { if (a.capacity() != b.capacity()) { return false; @@ -344,12 +310,8 @@ public static boolean equalsByteBuffer(ByteBuffer a, ByteBuffer b) { return a.duplicate().clear().equals(b.duplicate().clear()); } - /** - * Helper method for implementing {@link Message#equals(Object)} for bytes - * field. - */ - public static boolean equalsByteBuffer( - List a, List b) { + /** Helper method for implementing {@link Message#equals(Object)} for bytes field. */ + public static boolean equalsByteBuffer(List a, List b) { if (a.size() != b.size()) { return false; } @@ -361,10 +323,7 @@ public static boolean equalsByteBuffer( return true; } - /** - * Helper method for implementing {@link Message#hashCode()} for bytes - * field. - */ + /** Helper method for implementing {@link Message#hashCode()} for bytes field. */ public static int hashCodeByteBuffer(List list) { int hash = 1; for (ByteBuffer bytes : list) { @@ -375,10 +334,7 @@ public static int hashCodeByteBuffer(List list) { private static final int DEFAULT_BUFFER_SIZE = 4096; - /** - * Helper method for implementing {@link Message#hashCode()} for bytes - * field. - */ + /** Helper method for implementing {@link Message#hashCode()} for bytes field. */ public static int hashCodeByteBuffer(ByteBuffer bytes) { if (bytes.hasArray()) { // Fast path. @@ -387,15 +343,15 @@ public static int hashCodeByteBuffer(ByteBuffer bytes) { } else { // Read the data into a temporary byte array before calculating the // hash value. - final int bufferSize = bytes.capacity() > DEFAULT_BUFFER_SIZE - ? DEFAULT_BUFFER_SIZE : bytes.capacity(); + final int bufferSize = + bytes.capacity() > DEFAULT_BUFFER_SIZE ? DEFAULT_BUFFER_SIZE : bytes.capacity(); final byte[] buffer = new byte[bufferSize]; final ByteBuffer duplicated = bytes.duplicate(); duplicated.clear(); int h = bytes.capacity(); while (duplicated.remaining() > 0) { - final int length = duplicated.remaining() <= bufferSize ? - duplicated.remaining() : bufferSize; + final int length = + duplicated.remaining() <= bufferSize ? duplicated.remaining() : bufferSize; duplicated.get(buffer, 0, length); h = partialHash(h, buffer, 0, length); } @@ -409,8 +365,7 @@ public static T getDefaultInstance(Class clazz) { Method method = clazz.getMethod("getDefaultInstance"); return (T) method.invoke(method); } catch (Exception e) { - throw new RuntimeException( - "Failed to get default instance for " + clazz, e); + throw new RuntimeException("Failed to get default instance for " + clazz, e); } } @@ -418,11 +373,8 @@ public static T getDefaultInstance(Class clazz) { /** An empty byte array constant used in generated code. */ public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; - /** - * An empty byte array constant used in generated code. - */ - public static final ByteBuffer EMPTY_BYTE_BUFFER = - ByteBuffer.wrap(EMPTY_BYTE_ARRAY); + /** An empty byte array constant used in generated code. */ + public static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.wrap(EMPTY_BYTE_ARRAY); /** An empty coded input stream constant used in generated code. */ public static final CodedInputStream EMPTY_CODED_INPUT_STREAM = @@ -437,12 +389,10 @@ static Object mergeMessage(Object destination, Object source) { /** * Provides an immutable view of {@code List} around a {@code List}. * - * Protobuf internal. Used in protobuf generated code only. + *

Protobuf internal. Used in protobuf generated code only. */ public static class ListAdapter extends AbstractList { - /** - * Convert individual elements of the List from F to T. - */ + /** Convert individual elements of the List from F to T. */ public interface Converter { T convert(F from); } @@ -466,16 +416,12 @@ public int size() { } } - /** - * Wrap around a {@code Map} and provide a {@code Map} - * interface. - */ + /** Wrap around a {@code Map} and provide a {@code Map} interface. */ public static class MapAdapter extends AbstractMap { - /** - * An interface used to convert between two types. - */ + /** An interface used to convert between two types. */ public interface Converter { B doForward(A object); + A doBackward(B object); } @@ -498,8 +444,7 @@ public Integer doBackward(T value) { private final Map realMap; private final Converter valueConverter; - public MapAdapter(Map realMap, - Converter valueConverter) { + public MapAdapter(Map realMap, Converter valueConverter) { this.realMap = realMap; this.valueConverter = valueConverter; } @@ -530,6 +475,7 @@ public Set> entrySet() { private class SetAdapter extends AbstractSet> { private final Set> realSet; + public SetAdapter(Set> realSet) { this.realSet = realSet; } @@ -548,8 +494,7 @@ public int size() { private class IteratorAdapter implements Iterator> { private final Iterator> realIterator; - public IteratorAdapter( - Iterator> realIterator) { + public IteratorAdapter(Iterator> realIterator) { this.realIterator = realIterator; } @@ -588,27 +533,44 @@ public V getValue() { @Override public V setValue(V value) { - RealValue oldValue = realEntry.setValue( - valueConverter.doBackward(value)); + RealValue oldValue = realEntry.setValue(valueConverter.doBackward(value)); if (oldValue == null) { return null; } return valueConverter.doForward(oldValue); } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof Map.Entry)) { + return false; + } + @SuppressWarnings("unchecked") + Map.Entry other = (Map.Entry) o; + return getKey().equals(other.getKey()) && getValue().equals(getValue()); + } + + @Override + public int hashCode() { + return realEntry.hashCode(); + } } } /** * Extends {@link List} to add the capability to make the list immutable and inspect if it is * modifiable. - *

- * All implementations must support efficient random access. + * + *

All implementations must support efficient random access. */ public static interface ProtobufList extends List, RandomAccess { /** - * Makes this list immutable. All subsequent modifications will throw an - * {@link UnsupportedOperationException}. + * Makes this list immutable. All subsequent modifications will throw an {@link + * UnsupportedOperationException}. */ void makeImmutable(); @@ -617,9 +579,7 @@ public static interface ProtobufList extends List, RandomAccess { */ boolean isModifiable(); - /** - * Returns a mutable clone of this list with the specified capacity. - */ + /** Returns a mutable clone of this list with the specified capacity. */ ProtobufList mutableCopyWithCapacity(int capacity); } @@ -629,24 +589,16 @@ public static interface ProtobufList extends List, RandomAccess { */ public static interface IntList extends ProtobufList { - /** - * Like {@link #get(int)} but more efficient in that it doesn't box the returned value. - */ + /** Like {@link #get(int)} but more efficient in that it doesn't box the returned value. */ int getInt(int index); - /** - * Like {@link #add(Object)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(Object)} but more efficient in that it doesn't box the element. */ void addInt(int element); - /** - * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */ int setInt(int index, int element); - /** - * Returns a mutable clone of this list with the specified capacity. - */ + /** Returns a mutable clone of this list with the specified capacity. */ @Override IntList mutableCopyWithCapacity(int capacity); } @@ -657,52 +609,36 @@ public static interface IntList extends ProtobufList { */ public static interface BooleanList extends ProtobufList { - /** - * Like {@link #get(int)} but more efficient in that it doesn't box the returned value. - */ + /** Like {@link #get(int)} but more efficient in that it doesn't box the returned value. */ boolean getBoolean(int index); - /** - * Like {@link #add(Object)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(Object)} but more efficient in that it doesn't box the element. */ void addBoolean(boolean element); - /** - * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */ boolean setBoolean(int index, boolean element); - /** - * Returns a mutable clone of this list with the specified capacity. - */ + /** Returns a mutable clone of this list with the specified capacity. */ @Override BooleanList mutableCopyWithCapacity(int capacity); } /** - * A {@link java.util.List} implementation that avoids boxing the elements into Longs if - * possible. Does not support null elements. + * A {@link java.util.List} implementation that avoids boxing the elements into Longs if possible. + * Does not support null elements. */ public static interface LongList extends ProtobufList { - /** - * Like {@link #get(int)} but more efficient in that it doesn't box the returned value. - */ + /** Like {@link #get(int)} but more efficient in that it doesn't box the returned value. */ long getLong(int index); - /** - * Like {@link #add(Object)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(Object)} but more efficient in that it doesn't box the element. */ void addLong(long element); - /** - * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */ long setLong(int index, long element); - /** - * Returns a mutable clone of this list with the specified capacity. - */ + /** Returns a mutable clone of this list with the specified capacity. */ @Override LongList mutableCopyWithCapacity(int capacity); } @@ -713,24 +649,16 @@ public static interface LongList extends ProtobufList { */ public static interface DoubleList extends ProtobufList { - /** - * Like {@link #get(int)} but more efficient in that it doesn't box the returned value. - */ + /** Like {@link #get(int)} but more efficient in that it doesn't box the returned value. */ double getDouble(int index); - /** - * Like {@link #add(Object)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(Object)} but more efficient in that it doesn't box the element. */ void addDouble(double element); - /** - * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */ double setDouble(int index, double element); - /** - * Returns a mutable clone of this list with the specified capacity. - */ + /** Returns a mutable clone of this list with the specified capacity. */ @Override DoubleList mutableCopyWithCapacity(int capacity); } @@ -741,25 +669,18 @@ public static interface DoubleList extends ProtobufList { */ public static interface FloatList extends ProtobufList { - /** - * Like {@link #get(int)} but more efficient in that it doesn't box the returned value. - */ + /** Like {@link #get(int)} but more efficient in that it doesn't box the returned value. */ float getFloat(int index); - /** - * Like {@link #add(Object)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(Object)} but more efficient in that it doesn't box the element. */ void addFloat(float element); - /** - * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */ float setFloat(int index, float element); - /** - * Returns a mutable clone of this list with the specified capacity. - */ + /** Returns a mutable clone of this list with the specified capacity. */ @Override FloatList mutableCopyWithCapacity(int capacity); } + } diff --git a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java index 510c6aac74635..22f31bbc0b3b3 100644 --- a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java +++ b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java @@ -33,8 +33,8 @@ import java.io.IOException; /** - * Thrown when a protocol message being parsed is invalid in some way, - * e.g. it contains a malformed varint or a negative byte length. + * Thrown when a protocol message being parsed is invalid in some way, e.g. it contains a malformed + * varint or a negative byte length. * * @author kenton@google.com Kenton Varda */ @@ -55,28 +55,26 @@ public InvalidProtocolBufferException(final String description, IOException e) { } /** - * Attaches an unfinished message to the exception to support best-effort - * parsing in {@code Parser} interface. + * Attaches an unfinished message to the exception to support best-effort parsing in {@code + * Parser} interface. * * @return this */ - public InvalidProtocolBufferException setUnfinishedMessage( - MessageLite unfinishedMessage) { + public InvalidProtocolBufferException setUnfinishedMessage(MessageLite unfinishedMessage) { this.unfinishedMessage = unfinishedMessage; return this; } /** - * Returns the unfinished message attached to the exception, or null if - * no message is attached. + * Returns the unfinished message attached to the exception, or null if no message is attached. */ public MessageLite getUnfinishedMessage() { return unfinishedMessage; } /** - * Unwraps the underlying {@link IOException} if this exception was caused by an I/O - * problem. Otherwise, returns {@code this}. + * Unwraps the underlying {@link IOException} if this exception was caused by an I/O problem. + * Otherwise, returns {@code this}. */ public IOException unwrapIOException() { return getCause() instanceof IOException ? (IOException) getCause() : this; @@ -84,41 +82,36 @@ public IOException unwrapIOException() { static InvalidProtocolBufferException truncatedMessage() { return new InvalidProtocolBufferException( - "While parsing a protocol message, the input ended unexpectedly " + - "in the middle of a field. This could mean either that the " + - "input has been truncated or that an embedded message " + - "misreported its own length."); + "While parsing a protocol message, the input ended unexpectedly " + + "in the middle of a field. This could mean either that the " + + "input has been truncated or that an embedded message " + + "misreported its own length."); } static InvalidProtocolBufferException negativeSize() { return new InvalidProtocolBufferException( - "CodedInputStream encountered an embedded string or message " + - "which claimed to have negative size."); + "CodedInputStream encountered an embedded string or message " + + "which claimed to have negative size."); } static InvalidProtocolBufferException malformedVarint() { - return new InvalidProtocolBufferException( - "CodedInputStream encountered a malformed varint."); + return new InvalidProtocolBufferException("CodedInputStream encountered a malformed varint."); } static InvalidProtocolBufferException invalidTag() { - return new InvalidProtocolBufferException( - "Protocol message contained an invalid tag (zero)."); + return new InvalidProtocolBufferException("Protocol message contained an invalid tag (zero)."); } static InvalidProtocolBufferException invalidEndTag() { return new InvalidProtocolBufferException( - "Protocol message end-group tag did not match expected tag."); + "Protocol message end-group tag did not match expected tag."); } static InvalidWireTypeException invalidWireType() { - return new InvalidWireTypeException( - "Protocol message tag had invalid wire type."); + return new InvalidWireTypeException("Protocol message tag had invalid wire type."); } - /** - * Exception indicating that and unexpected wire type was encountered for a field. - */ + /** Exception indicating that and unexpected wire type was encountered for a field. */ @ExperimentalApi public static class InvalidWireTypeException extends InvalidProtocolBufferException { private static final long serialVersionUID = 3283890091615336259L; @@ -130,14 +123,14 @@ public InvalidWireTypeException(String description) { static InvalidProtocolBufferException recursionLimitExceeded() { return new InvalidProtocolBufferException( - "Protocol message had too many levels of nesting. May be malicious. " + - "Use CodedInputStream.setRecursionLimit() to increase the depth limit."); + "Protocol message had too many levels of nesting. May be malicious. " + + "Use CodedInputStream.setRecursionLimit() to increase the depth limit."); } static InvalidProtocolBufferException sizeLimitExceeded() { return new InvalidProtocolBufferException( - "Protocol message was too large. May be malicious. " + - "Use CodedInputStream.setSizeLimit() to increase the size limit."); + "Protocol message was too large. May be malicious. " + + "Use CodedInputStream.setSizeLimit() to increase the size limit."); } static InvalidProtocolBufferException parseFailure() { diff --git a/java/core/src/main/java/com/google/protobuf/IterableByteBufferInputStream.java b/java/core/src/main/java/com/google/protobuf/IterableByteBufferInputStream.java new file mode 100644 index 0000000000000..713e80646931f --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/IterableByteBufferInputStream.java @@ -0,0 +1,150 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.Internal.EMPTY_BYTE_BUFFER; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.Iterator; + +class IterableByteBufferInputStream extends InputStream { + /** The {@link Iterator} with type {@link ByteBuffer} of {@code input} */ + private Iterator iterator; + /** The current ByteBuffer; */ + private ByteBuffer currentByteBuffer; + /** The number of ByteBuffers in the input data. */ + private int dataSize; + /** + * Current {@code ByteBuffer}'s index + * + *

If index equals dataSize, then all the data in the InputStream has been consumed + */ + private int currentIndex; + /** The current position for current ByteBuffer */ + private int currentByteBufferPos; + /** Whether current ByteBuffer has an array */ + private boolean hasArray; + /** + * If the current ByteBuffer is unsafe-direct based, currentArray is null; otherwise should be the + * array inside ByteBuffer. + */ + private byte[] currentArray; + /** Current ByteBuffer's array offset */ + private int currentArrayOffset; + /** + * If the current ByteBuffer is unsafe-direct based, currentAddress is the start address of this + * ByteBuffer; otherwise should be zero. + */ + private long currentAddress; + + IterableByteBufferInputStream(Iterable data) { + iterator = data.iterator(); + dataSize = 0; + for (ByteBuffer unused : data) { + dataSize++; + } + currentIndex = -1; + + if (!getNextByteBuffer()) { + currentByteBuffer = EMPTY_BYTE_BUFFER; + currentIndex = 0; + currentByteBufferPos = 0; + currentAddress = 0; + } + } + + private boolean getNextByteBuffer() { + currentIndex++; + if (!iterator.hasNext()) { + return false; + } + currentByteBuffer = iterator.next(); + currentByteBufferPos = currentByteBuffer.position(); + if (currentByteBuffer.hasArray()) { + hasArray = true; + currentArray = currentByteBuffer.array(); + currentArrayOffset = currentByteBuffer.arrayOffset(); + } else { + hasArray = false; + currentAddress = UnsafeUtil.addressOffset(currentByteBuffer); + currentArray = null; + } + return true; + } + + private void updateCurrentByteBufferPos(int numberOfBytesRead) { + currentByteBufferPos += numberOfBytesRead; + if (currentByteBufferPos == currentByteBuffer.limit()) { + getNextByteBuffer(); + } + } + + @Override + public int read() throws IOException { + if (currentIndex == dataSize) { + return -1; + } + if (hasArray) { + int result = currentArray[currentByteBufferPos + currentArrayOffset] & 0xFF; + updateCurrentByteBufferPos(1); + return result; + } else { + int result = UnsafeUtil.getByte(currentByteBufferPos + currentAddress) & 0xFF; + updateCurrentByteBufferPos(1); + return result; + } + } + + @Override + public int read(byte[] output, int offset, int length) throws IOException { + if (currentIndex == dataSize) { + return -1; + } + int remaining = currentByteBuffer.limit() - currentByteBufferPos; + if (length > remaining) { + length = remaining; + } + if (hasArray) { + System.arraycopy( + currentArray, currentByteBufferPos + currentArrayOffset, output, offset, length); + updateCurrentByteBufferPos(length); + } else { + int prevPos = currentByteBuffer.position(); + currentByteBuffer.position(currentByteBufferPos); + currentByteBuffer.get(output, offset, length); + currentByteBuffer.position(prevPos); + updateCurrentByteBufferPos(length); + } + return length; + } +} diff --git a/java/core/src/main/java/com/google/protobuf/JavaType.java b/java/core/src/main/java/com/google/protobuf/JavaType.java new file mode 100644 index 0000000000000..770aa9ef1ff5c --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/JavaType.java @@ -0,0 +1,76 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** Enum that identifies the Java types required to store protobuf fields. */ +@ExperimentalApi +public enum JavaType { + VOID(Void.class, Void.class, null), + INT(int.class, Integer.class, 0), + LONG(long.class, Long.class, 0L), + FLOAT(float.class, Float.class, 0F), + DOUBLE(double.class, Double.class, 0D), + BOOLEAN(boolean.class, Boolean.class, false), + STRING(String.class, String.class, ""), + BYTE_STRING(ByteString.class, ByteString.class, ByteString.EMPTY), + ENUM(int.class, Integer.class, null), + MESSAGE(Object.class, Object.class, null); + + private final Class type; + private final Class boxedType; + private final Object defaultDefault; + + JavaType(Class type, Class boxedType, Object defaultDefault) { + this.type = type; + this.boxedType = boxedType; + this.defaultDefault = defaultDefault; + } + + /** The default default value for fields of this type, if it's a primitive type. */ + public Object getDefaultDefault() { + return defaultDefault; + } + + /** Gets the required type for a field that would hold a value of this type. */ + public Class getType() { + return type; + } + + /** @return the boxedType */ + public Class getBoxedType() { + return boxedType; + } + + /** Indicates whether or not this {@link JavaType} can be applied to a field of the given type. */ + public boolean isValidType(Class t) { + return type.isAssignableFrom(t); + } +} diff --git a/java/core/src/main/java/com/google/protobuf/LazyField.java b/java/core/src/main/java/com/google/protobuf/LazyField.java index 98e13ca19902f..891171d7c867a 100644 --- a/java/core/src/main/java/com/google/protobuf/LazyField.java +++ b/java/core/src/main/java/com/google/protobuf/LazyField.java @@ -34,12 +34,12 @@ import java.util.Map.Entry; /** - * LazyField encapsulates the logic of lazily parsing message fields. It stores - * the message in a ByteString initially and then parse it on-demand. + * LazyField encapsulates the logic of lazily parsing message fields. It stores the message in a + * ByteString initially and then parse it on-demand. * - * Most of key methods are implemented in {@link LazyFieldLite} but this class - * can contain default instance of the message to provide {@code hashCode()}, - * {@code euqals()} and {@code toString()}. + *

Most of key methods are implemented in {@link LazyFieldLite} but this class can contain + * default instance of the message to provide {@code hashCode()}, {@code euqals()} and {@code + * toString()}. * * @author xiangl@google.com (Xiang Li) */ @@ -51,8 +51,8 @@ public class LazyField extends LazyFieldLite { */ private final MessageLite defaultInstance; - public LazyField(MessageLite defaultInstance, - ExtensionRegistryLite extensionRegistry, ByteString bytes) { + public LazyField( + MessageLite defaultInstance, ExtensionRegistryLite extensionRegistry, ByteString bytes) { super(extensionRegistry, bytes); this.defaultInstance = defaultInstance; @@ -85,8 +85,8 @@ public String toString() { // ==================================================== /** - * LazyEntry and LazyIterator are used to encapsulate the LazyField, when - * users iterate all fields from FieldSet. + * LazyEntry and LazyIterator are used to encapsulate the LazyField, when users iterate all fields + * from FieldSet. */ static class LazyEntry implements Entry { private Entry entry; @@ -118,7 +118,7 @@ public Object setValue(Object value) { if (!(value instanceof MessageLite)) { throw new IllegalArgumentException( "LazyField now only used for MessageSet, " - + "and the value of MessageSet must be an instance of MessageLite"); + + "and the value of MessageSet must be an instance of MessageLite"); } return entry.getValue().setValue((MessageLite) value); } diff --git a/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java b/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java index 49ecfc0be69b2..6fab26fc53711 100644 --- a/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java +++ b/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java @@ -33,23 +33,23 @@ import java.io.IOException; /** - * LazyFieldLite encapsulates the logic of lazily parsing message fields. It stores - * the message in a ByteString initially and then parses it on-demand. + * LazyFieldLite encapsulates the logic of lazily parsing message fields. It stores the message in a + * ByteString initially and then parses it on-demand. * - * LazyFieldLite is thread-compatible: concurrent reads are safe once the proto that this + *

LazyFieldLite is thread-compatible: concurrent reads are safe once the proto that this * LazyFieldLite is a part of is no longer being mutated by its Builder. However, explicit * synchronization is needed under read/write situations. * - * When a LazyFieldLite is used in the context of a MessageLite object, its behavior is considered - * to be immutable and none of the setter methods in its API are expected to be invoked. All of the - * getters are expected to be thread-safe. When used in the context of a MessageLite.Builder, - * setters can be invoked, but there is no guarantee of thread safety. - * - * TODO(yatin,dweis): Consider splitting this class's functionality and put the mutable methods + *

When a LazyFieldLite is used in the context of a MessageLite object, its behavior is + * considered to be immutable and none of the setter methods in its API are expected to be invoked. + * All of the getters are expected to be thread-safe. When used in the context of a + * MessageLite.Builder, setters can be invoked, but there is no guarantee of thread safety. + * + *

TODO(yatin,dweis): Consider splitting this class's functionality and put the mutable methods * into a separate builder class to allow us to give stronger compile-time guarantees. * - * This class is internal implementation detail of the protobuf library, so you don't need to use it - * directly. + *

This class is internal implementation detail of the protobuf library, so you don't need to use + * it directly. * * @author xiangl@google.com (Xiang Li) */ @@ -57,23 +57,27 @@ public class LazyFieldLite { private static final ExtensionRegistryLite EMPTY_REGISTRY = ExtensionRegistryLite.getEmptyRegistry(); - /** + /* * The value associated with the LazyFieldLite object is stored in one or more of the following * three fields (delayedBytes, value, memoizedBytes). They should together be interpreted as * follows. + * * 1) delayedBytes can be non-null, while value and memoizedBytes is null. The object will be in - * this state while the value for the object has not yet been parsed. + * this state while the value for the object has not yet been parsed. + * * 2) Both delayedBytes and value are non-null. The object transitions to this state as soon as - * some caller needs to access the value (by invoking getValue()). + * some caller needs to access the value (by invoking getValue()). + * * 3) memoizedBytes is merely an optimization for calls to LazyFieldLite.toByteString() to avoid - * recomputing the ByteString representation on each call. Instead, when the value is parsed - * from delayedBytes, we will also assign the contents of delayedBytes to memoizedBytes (since - * that is the ByteString representation of value). + * recomputing the ByteString representation on each call. Instead, when the value is parsed from + * delayedBytes, we will also assign the contents of delayedBytes to memoizedBytes (since that is + * the ByteString representation of value). + * * 4) Finally, if the LazyFieldLite was created directly with a parsed MessageLite value, then - * delayedBytes will be null, and memoizedBytes will be initialized only upon the first call to - * LazyFieldLite.toByteString(). + * delayedBytes will be null, and memoizedBytes will be initialized only upon the first call to + * LazyFieldLite.toByteString(). * - * Given the above conditions, any caller that needs a serialized representation of this object + *

Given the above conditions, any caller that needs a serialized representation of this object * must first check if the memoizedBytes or delayedBytes ByteString is non-null and use it * directly; if both of those are null, it can look at the parsed value field. Similarly, any * caller that needs a parsed value must first check if the value field is already non-null, if @@ -84,16 +88,16 @@ public class LazyFieldLite { * A delayed-parsed version of the contents of this field. When this field is non-null, then the * "value" field is allowed to be null until the time that the value needs to be read. * - * When delayedBytes is non-null then {@code extensionRegistry} is required to also be non-null. - * {@code value} and {@code memoizedBytes} will be initialized lazily. + *

When delayedBytes is non-null then {@code extensionRegistry} is required to also be + * non-null. {@code value} and {@code memoizedBytes} will be initialized lazily. */ private ByteString delayedBytes; /** * An {@code ExtensionRegistryLite} for parsing bytes. It is non-null on a best-effort basis. It - * is only guaranteed to be non-null if this message was initialized using bytes and an - * {@code ExtensionRegistry}. If it directly had a value set then it will be null, unless it has - * been merged with another {@code LazyFieldLite} that had an {@code ExtensionRegistry}. + * is only guaranteed to be non-null if this message was initialized using bytes and an {@code + * ExtensionRegistry}. If it directly had a value set then it will be null, unless it has been + * merged with another {@code LazyFieldLite} that had an {@code ExtensionRegistry}. */ private ExtensionRegistryLite extensionRegistry; @@ -105,25 +109,20 @@ public class LazyFieldLite { /** * The memoized bytes for {@code value}. This is an optimization for the toByteString() method to - * not have to recompute its return-value on each invocation. - * TODO(yatin): Figure out whether this optimization is actually necessary. + * not have to recompute its return-value on each invocation. TODO(yatin): Figure out whether this + * optimization is actually necessary. */ private volatile ByteString memoizedBytes; - /** - * Constructs a LazyFieldLite with bytes that will be parsed lazily. - */ + /** Constructs a LazyFieldLite with bytes that will be parsed lazily. */ public LazyFieldLite(ExtensionRegistryLite extensionRegistry, ByteString bytes) { checkArguments(extensionRegistry, bytes); this.extensionRegistry = extensionRegistry; this.delayedBytes = bytes; } - /** - * Constructs a LazyFieldLite with no contents, and no ability to parse extensions. - */ - public LazyFieldLite() { - } + /** Constructs a LazyFieldLite with no contents, and no ability to parse extensions. */ + public LazyFieldLite() {} /** * Constructs a LazyFieldLite instance with a value. The LazyFieldLite may not be able to parse @@ -140,13 +139,13 @@ public boolean equals(Object o) { if (this == o) { return true; } - + if (!(o instanceof LazyFieldLite)) { return false; } LazyFieldLite other = (LazyFieldLite) o; - + // Lazy fields do not work well with equals... If both are delayedBytes, we do not have a // mechanism to deserialize them so we rely on bytes equality. Otherwise we coerce into an // actual message (if necessary) and call equals on the message itself. This implies that two @@ -163,7 +162,7 @@ public boolean equals(Object o) { return getValue(value2.getDefaultInstanceForType()).equals(value2); } } - + @Override public int hashCode() { // We can't provide a memoizable hash code for lazy fields. The byte strings may have different @@ -171,7 +170,7 @@ public int hashCode() { // a message here if we were not already holding a value. return 1; } - + /** * Determines whether this LazyFieldLite instance represents the default instance of this type. */ @@ -183,8 +182,8 @@ public boolean containsDefaultInstance() { /** * Clears the value state of this instance. * - *

LazyField is not thread-safe for write access. Synchronizations are needed - * under read/write situations. + *

LazyField is not thread-safe for write access. Synchronizations are needed under read/write + * situations. */ public void clear() { // Don't clear the ExtensionRegistry. It might prove useful later on when merging in another @@ -198,8 +197,8 @@ public void clear() { /** * Overrides the contents of this LazyField. * - *

LazyField is not thread-safe for write access. Synchronizations are needed - * under read/write situations. + *

LazyField is not thread-safe for write access. Synchronizations are needed under read/write + * situations. */ public void set(LazyFieldLite other) { this.delayedBytes = other.delayedBytes; @@ -218,7 +217,7 @@ public void set(LazyFieldLite other) { * Returns message instance. It may do some thread-safe delayed parsing of bytes. * * @param defaultInstance its message's default instance. It's also used to get parser for the - * message type. + * message type. */ public MessageLite getValue(MessageLite defaultInstance) { ensureInitialized(defaultInstance); @@ -228,8 +227,8 @@ public MessageLite getValue(MessageLite defaultInstance) { /** * Sets the value of the instance and returns the old value without delay parsing anything. * - *

LazyField is not thread-safe for write access. Synchronizations are needed - * under read/write situations. + *

LazyField is not thread-safe for write access. Synchronizations are needed under read/write + * situations. */ public MessageLite setValue(MessageLite value) { MessageLite originalValue = this.value; @@ -244,8 +243,8 @@ public MessageLite setValue(MessageLite value) { * contain data. If the other field has an {@code ExtensionRegistry} but this does not, then this * field will copy over that {@code ExtensionRegistry}. * - *

LazyField is not thread-safe for write access. Synchronizations are needed - * under read/write situations. + *

LazyField is not thread-safe for write access. Synchronizations are needed under read/write + * situations. */ public void merge(LazyFieldLite other) { if (other.containsDefaultInstance()) { @@ -275,7 +274,7 @@ public void merge(LazyFieldLite other) { // At least one is parsed and both contain data. We won't drop any extensions here directly, but // in the case that the extension registries are not the same then we might in the future if we - // need to serialze and parse a message again. + // need to serialize and parse a message again. if (this.value == null && other.value != null) { setValue(mergeValueAndBytes(other.value, this.delayedBytes, this.extensionRegistry)); return; @@ -287,12 +286,12 @@ public void merge(LazyFieldLite other) { // At this point we have two fully parsed messages. setValue(this.value.toBuilder().mergeFrom(other.value).build()); } - + /** * Merges another instance's contents from a stream. * - *

LazyField is not thread-safe for write access. Synchronizations are needed - * under read/write situations. + *

LazyField is not thread-safe for write access. Synchronizations are needed under read/write + * situations. */ public void mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws IOException { @@ -339,9 +338,7 @@ private static MessageLite mergeValueAndBytes( } } - /** - * Sets this field with bytes to delay-parse. - */ + /** Sets this field with bytes to delay-parse. */ public void setByteString(ByteString bytes, ExtensionRegistryLite extensionRegistry) { checkArguments(extensionRegistry, bytes); this.delayedBytes = bytes; @@ -351,9 +348,8 @@ public void setByteString(ByteString bytes, ExtensionRegistryLite extensionRegis } /** - * Due to the optional field can be duplicated at the end of serialized - * bytes, which will make the serialized size changed after LazyField - * parsed. Be careful when using this method. + * Due to the optional field can be duplicated at the end of serialized bytes, which will make the + * serialized size changed after LazyField parsed. Be careful when using this method. */ public int getSerializedSize() { // We *must* return delayed bytes size if it was ever set because the dependent messages may @@ -369,9 +365,7 @@ public int getSerializedSize() { } } - /** - * Returns a BytesString for this field in a thread-safe way. - */ + /** Returns a BytesString for this field in a thread-safe way. */ public ByteString toByteString() { if (memoizedBytes != null) { return memoizedBytes; @@ -394,10 +388,20 @@ public ByteString toByteString() { } } + /** Writes this lazy field into a {@link Writer}. */ + void writeTo(Writer writer, int fieldNumber) throws IOException { + if (memoizedBytes != null) { + writer.writeBytes(fieldNumber, memoizedBytes); + } else if (delayedBytes != null) { + writer.writeBytes(fieldNumber, delayedBytes); + } else if (value != null) { + writer.writeMessage(fieldNumber, value); + } else { + writer.writeBytes(fieldNumber, ByteString.EMPTY); + } + } - /** - * Might lazily parse the bytes that were previously passed in. Is thread-safe. - */ + /** Might lazily parse the bytes that were previously passed in. Is thread-safe. */ protected void ensureInitialized(MessageLite defaultInstance) { if (value != null) { return; @@ -409,8 +413,8 @@ protected void ensureInitialized(MessageLite defaultInstance) { try { if (delayedBytes != null) { // The extensionRegistry shouldn't be null here since we have delayedBytes. - MessageLite parsedValue = defaultInstance.getParserForType() - .parseFrom(delayedBytes, extensionRegistry); + MessageLite parsedValue = + defaultInstance.getParserForType().parseFrom(delayedBytes, extensionRegistry); this.value = parsedValue; this.memoizedBytes = delayedBytes; } else { @@ -426,7 +430,6 @@ protected void ensureInitialized(MessageLite defaultInstance) { } } - private static void checkArguments(ExtensionRegistryLite extensionRegistry, ByteString bytes) { if (extensionRegistry == null) { throw new NullPointerException("found null ExtensionRegistry"); diff --git a/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java b/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java index d474c51ef1e0b..a2de6f9cfeb0e 100644 --- a/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java @@ -39,26 +39,22 @@ import java.util.RandomAccess; /** - * An implementation of {@link LazyStringList} that wraps an ArrayList. Each - * element is one of String, ByteString, or byte[]. It caches the last one - * requested which is most likely the one needed next. This minimizes memory - * usage while satisfying the most common use cases. - *

- * Note that this implementation is not synchronized. - * If multiple threads access an ArrayList instance concurrently, - * and at least one of the threads modifies the list structurally, it - * must be synchronized externally. (A structural modification is - * any operation that adds or deletes one or more elements, or explicitly - * resizes the backing array; merely setting the value of an element is not - * a structural modification.) This is typically accomplished by - * synchronizing on some object that naturally encapsulates the list. - *

- * If the implementation is accessed via concurrent reads, this is thread safe. - * Conversions are done in a thread safe manner. It's possible that the - * conversion may happen more than once if two threads attempt to access the - * same element and the modifications were not visible to each other, but this - * will not result in any corruption of the list or change in behavior other - * than performance. + * An implementation of {@link LazyStringList} that wraps an ArrayList. Each element is one of + * String, ByteString, or byte[]. It caches the last one requested which is most likely the one + * needed next. This minimizes memory usage while satisfying the most common use cases. + * + *

Note that this implementation is not synchronized. If multiple threads access + * an ArrayList instance concurrently, and at least one of the threads modifies the list + * structurally, it must be synchronized externally. (A structural modification is any + * operation that adds or deletes one or more elements, or explicitly resizes the backing array; + * merely setting the value of an element is not a structural modification.) This is typically + * accomplished by synchronizing on some object that naturally encapsulates the list. + * + *

If the implementation is accessed via concurrent reads, this is thread safe. Conversions are + * done in a thread safe manner. It's possible that the conversion may happen more than once if two + * threads attempt to access the same element and the modifications were not visible to each other, + * but this will not result in any corruption of the list or change in behavior other than + * performance. * * @author jonp@google.com (Jon Perlow) */ @@ -66,10 +62,11 @@ public class LazyStringArrayList extends AbstractProtobufList implements LazyStringList, RandomAccess { private static final LazyStringArrayList EMPTY_LIST = new LazyStringArrayList(); + static { EMPTY_LIST.makeImmutable(); } - + static LazyStringArrayList emptyList() { return EMPTY_LIST; } @@ -83,8 +80,8 @@ public LazyStringArrayList() { this(DEFAULT_CAPACITY); } - public LazyStringArrayList(int intialCapacity) { - this(new ArrayList(intialCapacity)); + public LazyStringArrayList(int initialCapacity) { + this(new ArrayList(initialCapacity)); } public LazyStringArrayList(LazyStringList from) { @@ -95,7 +92,7 @@ public LazyStringArrayList(LazyStringList from) { public LazyStringArrayList(List from) { this(new ArrayList(from)); } - + private LazyStringArrayList(ArrayList list) { this.list = list; } @@ -150,13 +147,13 @@ public void add(int index, String element) { list.add(index, element); modCount++; } - + private void add(int index, ByteString element) { ensureIsMutable(); list.add(index, element); modCount++; } - + private void add(int index, byte[] element) { ensureIsMutable(); list.add(index, element); @@ -177,8 +174,8 @@ public boolean addAll(int index, Collection c) { ensureIsMutable(); // When copying from another LazyStringList, directly copy the underlying // elements rather than forcing each element to be decoded to a String. - Collection collection = c instanceof LazyStringList - ? ((LazyStringList) c).getUnderlyingElements() : c; + Collection collection = + c instanceof LazyStringList ? ((LazyStringList) c).getUnderlyingElements() : c; boolean ret = list.addAll(index, collection); modCount++; return ret; @@ -221,7 +218,7 @@ public void add(ByteString element) { list.add(element); modCount++; } - + @Override public void add(byte[] element) { ensureIsMutable(); @@ -233,7 +230,7 @@ public void add(byte[] element) { public Object getRaw(int index) { return list.get(index); } - + @Override public ByteString getByteString(int index) { Object o = list.get(index); @@ -243,7 +240,7 @@ public ByteString getByteString(int index) { } return b; } - + @Override public byte[] getByteArray(int index) { Object o = list.get(index); @@ -258,7 +255,7 @@ public byte[] getByteArray(int index) { public void set(int index, ByteString s) { setAndReturn(index, s); } - + private Object setAndReturn(int index, ByteString s) { ensureIsMutable(); return list.set(index, s); @@ -268,7 +265,7 @@ private Object setAndReturn(int index, ByteString s) { public void set(int index, byte[] s) { setAndReturn(index, s); } - + private Object setAndReturn(int index, byte[] s) { ensureIsMutable(); return list.set(index, s); @@ -283,7 +280,7 @@ private static String asString(Object o) { return Internal.toStringUtf8((byte[]) o); } } - + private static ByteString asByteString(Object o) { if (o instanceof ByteString) { return (ByteString) o; @@ -293,7 +290,7 @@ private static ByteString asByteString(Object o) { return ByteString.copyFrom((byte[]) o); } } - + private static byte[] asByteArray(Object o) { if (o instanceof byte[]) { return (byte[]) o; @@ -324,14 +321,13 @@ public void mergeFrom(LazyStringList other) { } } - private static class ByteArrayListView extends AbstractList - implements RandomAccess { + private static class ByteArrayListView extends AbstractList implements RandomAccess { private final LazyStringArrayList list; - + ByteArrayListView(LazyStringArrayList list) { this.list = list; } - + @Override public byte[] get(int index) { return list.getByteArray(index); @@ -362,14 +358,13 @@ public byte[] remove(int index) { return asByteArray(o); } } - + @Override public List asByteArrayList() { return new ByteArrayListView(this); } - private static class ByteStringListView extends AbstractList - implements RandomAccess { + private static class ByteStringListView extends AbstractList implements RandomAccess { private final LazyStringArrayList list; ByteStringListView(LazyStringArrayList list) { @@ -419,5 +414,4 @@ public LazyStringList getUnmodifiableView() { } return this; } - } diff --git a/java/core/src/main/java/com/google/protobuf/LazyStringList.java b/java/core/src/main/java/com/google/protobuf/LazyStringList.java index 3eeedca1d3839..6b55022caa4ab 100644 --- a/java/core/src/main/java/com/google/protobuf/LazyStringList.java +++ b/java/core/src/main/java/com/google/protobuf/LazyStringList.java @@ -34,14 +34,12 @@ import java.util.List; /** - * An interface extending {@code List} that also provides access to the - * items of the list as UTF8-encoded ByteString or byte[] objects. This is - * used by the protocol buffer implementation to support lazily converting bytes - * parsed over the wire to String objects until needed and also increases the - * efficiency of serialization if the String was never requested as the - * ByteString or byte[] is already cached. The ByteString methods are used in - * immutable API only and byte[] methods used in mutable API only for they use - * different representations for string/bytes fields. + * An interface extending {@code List} that also provides access to the items of the list as + * UTF8-encoded ByteString or byte[] objects. This is used by the protocol buffer implementation to + * support lazily converting bytes parsed over the wire to String objects until needed and also + * increases the efficiency of serialization if the String was never requested as the ByteString or + * byte[] is already cached. The ByteString methods are used in immutable API only and byte[] + * methods used in mutable API only for they use different representations for string/bytes fields. * * @author jonp@google.com (Jon Perlow) */ @@ -52,19 +50,19 @@ public interface LazyStringList extends ProtocolStringList { * * @param index index of the element to return * @return the element at the specified position in this list - * @throws IndexOutOfBoundsException if the index is out of range - * ({@code index < 0 || index >= size()}) + * @throws IndexOutOfBoundsException if the index is out of range ({@code index < 0 || index >= + * size()}) */ ByteString getByteString(int index); /** - * Returns the element at the specified position in this list as an Object - * that will either be a String or a ByteString. + * Returns the element at the specified position in this list as an Object that will either be a + * String or a ByteString. * * @param index index of the element to return * @return the element at the specified position in this list - * @throws IndexOutOfBoundsException if the index is out of range - * ({@code index < 0 || index >= size()}) + * @throws IndexOutOfBoundsException if the index is out of range ({@code index < 0 || index >= + * size()}) */ Object getRaw(int index); @@ -73,99 +71,91 @@ public interface LazyStringList extends ProtocolStringList { * * @param index index of the element to return * @return the element at the specified position in this list - * @throws IndexOutOfBoundsException if the index is out of range - * ({@code index < 0 || index >= size()}) + * @throws IndexOutOfBoundsException if the index is out of range ({@code index < 0 || index >= + * size()}) */ byte[] getByteArray(int index); /** - * Appends the specified element to the end of this list (optional - * operation). + * Appends the specified element to the end of this list (optional operation). * * @param element element to be appended to this list - * @throws UnsupportedOperationException if the add operation - * is not supported by this list + * @throws UnsupportedOperationException if the add operation is not supported by this + * list */ void add(ByteString element); /** - * Appends the specified element to the end of this list (optional - * operation). + * Appends the specified element to the end of this list (optional operation). * * @param element element to be appended to this list - * @throws UnsupportedOperationException if the add operation - * is not supported by this list + * @throws UnsupportedOperationException if the add operation is not supported by this + * list */ void add(byte[] element); /** - * Replaces the element at the specified position in this list with the - * specified element (optional operation). + * Replaces the element at the specified position in this list with the specified element + * (optional operation). * * @param index index of the element to replace * @param element the element to be stored at the specified position - * @throws UnsupportedOperationException if the set operation - * is not supported by this list - * IndexOutOfBoundsException if the index is out of range - * ({@code index < 0 || index >= size()}) + * @throws UnsupportedOperationException if the set operation is not supported by this + * list IndexOutOfBoundsException if the index is out of range ({@code index < 0 || index >= + * size()}) */ void set(int index, ByteString element); - + /** - * Replaces the element at the specified position in this list with the - * specified element (optional operation). + * Replaces the element at the specified position in this list with the specified element + * (optional operation). * * @param index index of the element to replace * @param element the element to be stored at the specified position - * @throws UnsupportedOperationException if the set operation - * is not supported by this list - * IndexOutOfBoundsException if the index is out of range - * ({@code index < 0 || index >= size()}) + * @throws UnsupportedOperationException if the set operation is not supported by this + * list IndexOutOfBoundsException if the index is out of range ({@code index < 0 || index >= + * size()}) */ void set(int index, byte[] element); /** - * Appends all elements in the specified ByteString collection to the end of - * this list. + * Appends all elements in the specified ByteString collection to the end of this list. * * @param c collection whose elements are to be added to this list * @return true if this list changed as a result of the call - * @throws UnsupportedOperationException if the addAllByteString - * operation is not supported by this list + * @throws UnsupportedOperationException if the addAllByteString operation is not + * supported by this list */ boolean addAllByteString(Collection c); /** - * Appends all elements in the specified byte[] collection to the end of - * this list. + * Appends all elements in the specified byte[] collection to the end of this list. * * @param c collection whose elements are to be added to this list * @return true if this list changed as a result of the call - * @throws UnsupportedOperationException if the addAllByteArray - * operation is not supported by this list + * @throws UnsupportedOperationException if the addAllByteArray operation is not + * supported by this list */ boolean addAllByteArray(Collection c); /** - * Returns an unmodifiable List of the underlying elements, each of which is - * either a {@code String} or its equivalent UTF-8 encoded {@code ByteString} - * or byte[]. It is an error for the caller to modify the returned - * List, and attempting to do so will result in an - * {@link UnsupportedOperationException}. + * Returns an unmodifiable List of the underlying elements, each of which is either a {@code + * String} or its equivalent UTF-8 encoded {@code ByteString} or byte[]. It is an error for the + * caller to modify the returned List, and attempting to do so will result in an {@link + * UnsupportedOperationException}. */ List getUnderlyingElements(); /** - * Merges all elements from another LazyStringList into this one. This method - * differs from {@link #addAll(Collection)} on that underlying byte arrays are - * copied instead of reference shared. Immutable API doesn't need to use this - * method as byte[] is not used there at all. + * Merges all elements from another LazyStringList into this one. This method differs from {@link + * #addAll(Collection)} on that underlying byte arrays are copied instead of reference shared. + * Immutable API doesn't need to use this method as byte[] is not used there at all. */ void mergeFrom(LazyStringList other); /** - * Returns a mutable view of this list. Changes to the view will be made into - * the original list. This method is used in mutable API only. + * Returns a mutable view of this list. Changes to the view will be made into the original list. + * This method is used in mutable API only. */ List asByteArrayList(); diff --git a/java/core/src/main/java/com/google/protobuf/ListFieldSchema.java b/java/core/src/main/java/com/google/protobuf/ListFieldSchema.java new file mode 100644 index 0000000000000..ebc8561a7261d --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/ListFieldSchema.java @@ -0,0 +1,190 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.Internal.ProtobufList; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Utility class that aids in properly manipulating list fields for either the lite or full runtime. + */ +abstract class ListFieldSchema { + // Disallow construction. + private ListFieldSchema() {} + + private static final ListFieldSchema FULL_INSTANCE = new ListFieldSchemaFull(); + private static final ListFieldSchema LITE_INSTANCE = new ListFieldSchemaLite(); + + abstract List mutableListAt(Object msg, long offset); + + abstract void makeImmutableListAt(Object msg, long offset); + + abstract void mergeListsAt(Object msg, Object otherMsg, long offset); + + static ListFieldSchema full() { + return FULL_INSTANCE; + } + + static ListFieldSchema lite() { + return LITE_INSTANCE; + } + + /** Implementation for the full runtime. */ + private static final class ListFieldSchemaFull extends ListFieldSchema { + + private static final Class UNMODIFIABLE_LIST_CLASS = + Collections.unmodifiableList(Collections.emptyList()).getClass(); + + @Override + List mutableListAt(Object message, long offset) { + return mutableListAt(message, offset, AbstractProtobufList.DEFAULT_CAPACITY); + } + + @Override + void makeImmutableListAt(Object message, long offset) { + List list = (List) UnsafeUtil.getObject(message, offset); + Object immutable = null; + if (list instanceof LazyStringList) { + immutable = ((LazyStringList) list).getUnmodifiableView(); + } else if (UNMODIFIABLE_LIST_CLASS.isAssignableFrom(list.getClass())) { + // already immutable + return; + } else if (list instanceof PrimitiveNonBoxingCollection && list instanceof ProtobufList) { + if (((ProtobufList) list).isModifiable()) { + ((ProtobufList) list).makeImmutable(); + } + return; + } else { + immutable = Collections.unmodifiableList((List) list); + } + UnsafeUtil.putObject(message, offset, immutable); + } + + @SuppressWarnings("unchecked") + private static List mutableListAt(Object message, long offset, int additionalCapacity) { + List list = getList(message, offset); + if (list.isEmpty()) { + if (list instanceof LazyStringList) { + list = (List) new LazyStringArrayList(additionalCapacity); + } else if (list instanceof PrimitiveNonBoxingCollection && list instanceof ProtobufList) { + list = ((ProtobufList) list).mutableCopyWithCapacity(additionalCapacity); + } else { + list = new ArrayList(additionalCapacity); + } + UnsafeUtil.putObject(message, offset, list); + } else if (UNMODIFIABLE_LIST_CLASS.isAssignableFrom(list.getClass())) { + ArrayList newList = new ArrayList(list.size() + additionalCapacity); + newList.addAll(list); + list = newList; + UnsafeUtil.putObject(message, offset, list); + } else if (list instanceof UnmodifiableLazyStringList) { + LazyStringArrayList newList = new LazyStringArrayList(list.size() + additionalCapacity); + newList.addAll((UnmodifiableLazyStringList) list); + list = (List) newList; + UnsafeUtil.putObject(message, offset, list); + } else if (list instanceof PrimitiveNonBoxingCollection + && list instanceof ProtobufList + && !((ProtobufList) list).isModifiable()) { + list = ((ProtobufList) list).mutableCopyWithCapacity(list.size() + additionalCapacity); + UnsafeUtil.putObject(message, offset, list); + } + return list; + } + + @Override + void mergeListsAt(Object msg, Object otherMsg, long offset) { + List other = getList(otherMsg, offset); + List mine = mutableListAt(msg, offset, other.size()); + + int size = mine.size(); + int otherSize = other.size(); + if (size > 0 && otherSize > 0) { + mine.addAll(other); + } + + List merged = size > 0 ? mine : other; + UnsafeUtil.putObject(msg, offset, merged); + } + + @SuppressWarnings("unchecked") + static List getList(Object message, long offset) { + return (List) UnsafeUtil.getObject(message, offset); + } + } + + /** Implementation for the lite runtime. */ + private static final class ListFieldSchemaLite extends ListFieldSchema { + + @Override + List mutableListAt(Object message, long offset) { + ProtobufList list = getProtobufList(message, offset); + if (!list.isModifiable()) { + int size = list.size(); + list = + list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + UnsafeUtil.putObject(message, offset, list); + } + return list; + } + + @Override + void makeImmutableListAt(Object message, long offset) { + ProtobufList list = getProtobufList(message, offset); + list.makeImmutable(); + } + + @Override + void mergeListsAt(Object msg, Object otherMsg, long offset) { + ProtobufList mine = getProtobufList(msg, offset); + ProtobufList other = getProtobufList(otherMsg, offset); + + int size = mine.size(); + int otherSize = other.size(); + if (size > 0 && otherSize > 0) { + if (!mine.isModifiable()) { + mine = mine.mutableCopyWithCapacity(size + otherSize); + } + mine.addAll(other); + } + + ProtobufList merged = size > 0 ? mine : other; + UnsafeUtil.putObject(msg, offset, merged); + } + + @SuppressWarnings("unchecked") + static ProtobufList getProtobufList(Object message, long offset) { + return (ProtobufList) UnsafeUtil.getObject(message, offset); + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/LongArrayList.java b/java/core/src/main/java/com/google/protobuf/LongArrayList.java index fc146e232b6e0..bda43a41bb4a1 100644 --- a/java/core/src/main/java/com/google/protobuf/LongArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/LongArrayList.java @@ -45,7 +45,7 @@ final class LongArrayList extends AbstractProtobufList implements LongList, RandomAccess, PrimitiveNonBoxingCollection { - private static final LongArrayList EMPTY_LIST = new LongArrayList(); + private static final LongArrayList EMPTY_LIST = new LongArrayList(new long[0], 0); static { EMPTY_LIST.makeImmutable(); } @@ -54,9 +54,7 @@ public static LongArrayList emptyList() { return EMPTY_LIST; } - /** - * The backing store for the list. - */ + /** The backing store for the list. */ private long[] array; /** @@ -65,22 +63,31 @@ public static LongArrayList emptyList() { */ private int size; - /** - * Constructs a new mutable {@code LongArrayList} with default capacity. - */ + /** Constructs a new mutable {@code LongArrayList} with default capacity. */ LongArrayList() { this(new long[DEFAULT_CAPACITY], 0); } /** - * Constructs a new mutable {@code LongArrayList} - * containing the same elements as {@code other}. + * Constructs a new mutable {@code LongArrayList} containing the same elements as {@code other}. */ private LongArrayList(long[] other, int size) { array = other; this.size = size; } + @Override + protected void removeRange(int fromIndex, int toIndex) { + ensureIsMutable(); + if (toIndex < fromIndex) { + throw new IndexOutOfBoundsException("toIndex < fromIndex"); + } + + System.arraycopy(array, toIndex, array, fromIndex, size - toIndex); + size -= (toIndex - fromIndex); + modCount++; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -132,6 +139,26 @@ public long getLong(int index) { return array[index]; } + @Override + public int indexOf(Object element) { + if (!(element instanceof Long)) { + return -1; + } + long unboxedElement = (Long) element; + int numElems = size(); + for (int i = 0; i < numElems; i++) { + if (array[i] == unboxedElement) { + return i; + } + } + return -1; + } + + @Override + public boolean contains(Object element) { + return indexOf(element) != -1; + } + @Override public int size() { return size; @@ -151,22 +178,34 @@ public long setLong(int index, long element) { return previousValue; } + @Override + public boolean add(Long element) { + addLong(element); + return true; + } + @Override public void add(int index, Long element) { addLong(index, element); } - /** - * Like {@link #add(Long)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(Long)} but more efficient in that it doesn't box the element. */ @Override public void addLong(long element) { - addLong(size, element); + ensureIsMutable(); + if (size == array.length) { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + long[] newArray = new long[length]; + + System.arraycopy(array, 0, newArray, 0, size); + array = newArray; + } + + array[size++] = element; } - /** - * Like {@link #add(int, Long)} but more efficient in that it doesn't box the element. - */ + /** Like {@link #add(int, Long)} but more efficient in that it doesn't box the element. */ private void addLong(int index, long element) { ensureIsMutable(); if (index < 0 || index > size) { @@ -227,26 +266,14 @@ public boolean addAll(Collection collection) { return true; } - @Override - public boolean remove(Object o) { - ensureIsMutable(); - for (int i = 0; i < size; i++) { - if (o.equals(array[i])) { - System.arraycopy(array, i + 1, array, i, size - i); - size--; - modCount++; - return true; - } - } - return false; - } - @Override public Long remove(int index) { ensureIsMutable(); ensureIndexInRange(index); long value = array[index]; - System.arraycopy(array, index + 1, array, index, size - index); + if (index < size - 1) { + System.arraycopy(array, index + 1, array, index, size - index - 1); + } size--; modCount++; return value; diff --git a/java/core/src/main/java/com/google/protobuf/ManifestSchemaFactory.java b/java/core/src/main/java/com/google/protobuf/ManifestSchemaFactory.java new file mode 100644 index 0000000000000..84ca9ae0f7576 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/ManifestSchemaFactory.java @@ -0,0 +1,172 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.Internal.checkNotNull; + +/** + * Dynamically generates a manifest-based (i.e. table-based) schema for a given protobuf message. + */ +@ExperimentalApi +final class ManifestSchemaFactory implements SchemaFactory { + + private final MessageInfoFactory messageInfoFactory; + + public ManifestSchemaFactory() { + this(getDefaultMessageInfoFactory()); + } + + private ManifestSchemaFactory(MessageInfoFactory messageInfoFactory) { + this.messageInfoFactory = checkNotNull(messageInfoFactory, "messageInfoFactory"); + } + + @Override + public Schema createSchema(Class messageType) { + SchemaUtil.requireGeneratedMessage(messageType); + + MessageInfo messageInfo = messageInfoFactory.messageInfoFor(messageType); + + // MessageSet has a special schema. + if (messageInfo.isMessageSetWireFormat()) { + if (GeneratedMessageLite.class.isAssignableFrom(messageType)) { + return MessageSetSchema.newSchema( + SchemaUtil.unknownFieldSetLiteSchema(), + ExtensionSchemas.lite(), + messageInfo.getDefaultInstance()); + } + return MessageSetSchema.newSchema( + SchemaUtil.proto2UnknownFieldSetSchema(), + ExtensionSchemas.full(), + messageInfo.getDefaultInstance()); + } + + return newSchema(messageType, messageInfo); + } + + private static Schema newSchema(Class messageType, MessageInfo messageInfo) { + if (GeneratedMessageLite.class.isAssignableFrom(messageType)) { + return isProto2(messageInfo) + ? MessageSchema.newSchema( + messageType, + messageInfo, + NewInstanceSchemas.lite(), + ListFieldSchema.lite(), + SchemaUtil.unknownFieldSetLiteSchema(), + ExtensionSchemas.lite(), + MapFieldSchemas.lite()) + : MessageSchema.newSchema( + messageType, + messageInfo, + NewInstanceSchemas.lite(), + ListFieldSchema.lite(), + SchemaUtil.unknownFieldSetLiteSchema(), + /* extensionSchema= */ null, + MapFieldSchemas.lite()); + } + return isProto2(messageInfo) + ? MessageSchema.newSchema( + messageType, + messageInfo, + NewInstanceSchemas.full(), + ListFieldSchema.full(), + SchemaUtil.proto2UnknownFieldSetSchema(), + ExtensionSchemas.full(), + MapFieldSchemas.full()) + : MessageSchema.newSchema( + messageType, + messageInfo, + NewInstanceSchemas.full(), + ListFieldSchema.full(), + SchemaUtil.proto3UnknownFieldSetSchema(), + /* extensionSchema= */ null, + MapFieldSchemas.full()); + } + + private static boolean isProto2(MessageInfo messageInfo) { + return messageInfo.getSyntax() == ProtoSyntax.PROTO2; + } + + private static MessageInfoFactory getDefaultMessageInfoFactory() { + return new CompositeMessageInfoFactory( + GeneratedMessageInfoFactory.getInstance(), getDescriptorMessageInfoFactory()); + } + + private static class CompositeMessageInfoFactory implements MessageInfoFactory { + private MessageInfoFactory[] factories; + + CompositeMessageInfoFactory(MessageInfoFactory... factories) { + this.factories = factories; + } + + @Override + public boolean isSupported(Class clazz) { + for (MessageInfoFactory factory : factories) { + if (factory.isSupported(clazz)) { + return true; + } + } + return false; + } + + @Override + public MessageInfo messageInfoFor(Class clazz) { + for (MessageInfoFactory factory : factories) { + if (factory.isSupported(clazz)) { + return factory.messageInfoFor(clazz); + } + } + throw new UnsupportedOperationException( + "No factory is available for message type: " + clazz.getName()); + } + } + + private static final MessageInfoFactory EMPTY_FACTORY = + new MessageInfoFactory() { + @Override + public boolean isSupported(Class clazz) { + return false; + } + + @Override + public MessageInfo messageInfoFor(Class clazz) { + throw new IllegalStateException("This should never be called."); + } + }; + + private static MessageInfoFactory getDescriptorMessageInfoFactory() { + try { + Class clazz = Class.forName("com.google.protobuf.DescriptorMessageInfoFactory"); + return (MessageInfoFactory) clazz.getDeclaredMethod("getInstance").invoke(null); + } catch (Exception e) { + return EMPTY_FACTORY; + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/MapEntry.java b/java/core/src/main/java/com/google/protobuf/MapEntry.java index 0849b821cfd86..ca0678e2f128f 100644 --- a/java/core/src/main/java/com/google/protobuf/MapEntry.java +++ b/java/core/src/main/java/com/google/protobuf/MapEntry.java @@ -41,11 +41,11 @@ /** * Implements MapEntry messages. * - * In reflection API, map fields will be treated as repeated message fields and - * each map entry is accessed as a message. This MapEntry class is used to - * represent these map entry messages in reflection API. + *

In reflection API, map fields will be treated as repeated message fields and each map entry is + * accessed as a message. This MapEntry class is used to represent these map entry messages in + * reflection API. * - * Protobuf internal. Users shouldn't use this class. + *

Protobuf internal. Users shouldn't use this class. */ public final class MapEntry extends AbstractMessage { @@ -61,15 +61,16 @@ public Metadata( WireFormat.FieldType valueType) { super(keyType, defaultInstance.key, valueType, defaultInstance.value); this.descriptor = descriptor; - this.parser = new AbstractParser>() { + this.parser = + new AbstractParser>() { - @Override - public MapEntry parsePartialFrom( - CodedInputStream input, ExtensionRegistryLite extensionRegistry) - throws InvalidProtocolBufferException { - return new MapEntry(Metadata.this, input, extensionRegistry); - } - }; + @Override + public MapEntry parsePartialFrom( + CodedInputStream input, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return new MapEntry(Metadata.this, input, extensionRegistry); + } + }; } } @@ -80,8 +81,10 @@ public MapEntry parsePartialFrom( /** Create a default MapEntry instance. */ private MapEntry( Descriptor descriptor, - WireFormat.FieldType keyType, K defaultKey, - WireFormat.FieldType valueType, V defaultValue) { + WireFormat.FieldType keyType, + K defaultKey, + WireFormat.FieldType valueType, + V defaultValue) { this.key = defaultKey; this.value = defaultValue; this.metadata = new Metadata(descriptor, this, keyType, valueType); @@ -97,9 +100,7 @@ private MapEntry(Metadata metadata, K key, V value) { /** Parsing constructor. */ private MapEntry( - Metadata metadata, - CodedInputStream input, - ExtensionRegistryLite extensionRegistry) + Metadata metadata, CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { try { this.metadata = metadata; @@ -114,17 +115,17 @@ private MapEntry( } /** - * Create a default MapEntry instance. A default MapEntry instance should be - * created only once for each map entry message type. Generated code should - * store the created default instance and use it later to create new MapEntry - * messages of the same type. + * Create a default MapEntry instance. A default MapEntry instance should be created only once for + * each map entry message type. Generated code should store the created default instance and use + * it later to create new MapEntry messages of the same type. */ public static MapEntry newDefaultInstance( Descriptor descriptor, - WireFormat.FieldType keyType, K defaultKey, - WireFormat.FieldType valueType, V defaultValue) { - return new MapEntry( - descriptor, keyType, defaultKey, valueType, defaultValue); + WireFormat.FieldType keyType, + K defaultKey, + WireFormat.FieldType valueType, + V defaultValue) { + return new MapEntry(descriptor, keyType, defaultKey, valueType, defaultValue); } public K getKey() { @@ -197,14 +198,17 @@ public Map getAllFields() { private void checkFieldDescriptor(FieldDescriptor field) { if (field.getContainingType() != metadata.descriptor) { throw new RuntimeException( - "Wrong FieldDescriptor \"" + field.getFullName() - + "\" used in message \"" + metadata.descriptor.getFullName()); + "Wrong FieldDescriptor \"" + + field.getFullName() + + "\" used in message \"" + + metadata.descriptor.getFullName()); } } @Override public boolean hasField(FieldDescriptor field) { - checkFieldDescriptor(field);; + checkFieldDescriptor(field); + ; // A MapEntry always contains two fields. return true; } @@ -215,22 +219,19 @@ public Object getField(FieldDescriptor field) { Object result = field.getNumber() == 1 ? getKey() : getValue(); // Convert enums to EnumValueDescriptor. if (field.getType() == FieldDescriptor.Type.ENUM) { - result = field.getEnumType().findValueByNumberCreatingIfUnknown( - (java.lang.Integer) result); + result = field.getEnumType().findValueByNumberCreatingIfUnknown((java.lang.Integer) result); } return result; } @Override public int getRepeatedFieldCount(FieldDescriptor field) { - throw new RuntimeException( - "There is no repeated field in a map entry message."); + throw new RuntimeException("There is no repeated field in a map entry message."); } @Override public Object getRepeatedField(FieldDescriptor field, int index) { - throw new RuntimeException( - "There is no repeated field in a map entry message."); + throw new RuntimeException("There is no repeated field in a map entry message."); } @Override @@ -238,11 +239,8 @@ public UnknownFieldSet getUnknownFields() { return UnknownFieldSet.getDefaultInstance(); } - /** - * Builder to create {@link MapEntry} messages. - */ - public static class Builder - extends AbstractMessage.Builder> { + /** Builder to create {@link MapEntry} messages. */ + public static class Builder extends AbstractMessage.Builder> { private final Metadata metadata; private K key; private V value; @@ -315,20 +313,21 @@ public Descriptor getDescriptorForType() { private void checkFieldDescriptor(FieldDescriptor field) { if (field.getContainingType() != metadata.descriptor) { throw new RuntimeException( - "Wrong FieldDescriptor \"" + field.getFullName() - + "\" used in message \"" + metadata.descriptor.getFullName()); + "Wrong FieldDescriptor \"" + + field.getFullName() + + "\" used in message \"" + + metadata.descriptor.getFullName()); } } @Override public Message.Builder newBuilderForField(FieldDescriptor field) { - checkFieldDescriptor(field);; + checkFieldDescriptor(field); + ; // This method should be called for message fields and in a MapEntry // message only the value field can possibly be a message field. - if (field.getNumber() != 2 - || field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { - throw new RuntimeException( - "\"" + field.getFullName() + "\" is not a message value field."); + if (field.getNumber() != 2 || field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { + throw new RuntimeException("\"" + field.getFullName() + "\" is not a message value field."); } return ((Message) value).newBuilderForType(); } @@ -369,16 +368,13 @@ public Builder clearField(FieldDescriptor field) { } @Override - public Builder setRepeatedField(FieldDescriptor field, int index, - Object value) { - throw new RuntimeException( - "There is no repeated field in a map entry message."); + public Builder setRepeatedField(FieldDescriptor field, int index, Object value) { + throw new RuntimeException("There is no repeated field in a map entry message."); } @Override public Builder addRepeatedField(FieldDescriptor field, Object value) { - throw new RuntimeException( - "There is no repeated field in a map entry message."); + throw new RuntimeException("There is no repeated field in a map entry message."); } @Override @@ -427,14 +423,12 @@ public Object getField(FieldDescriptor field) { @Override public int getRepeatedFieldCount(FieldDescriptor field) { - throw new RuntimeException( - "There is no repeated field in a map entry message."); + throw new RuntimeException("There is no repeated field in a map entry message."); } @Override public Object getRepeatedField(FieldDescriptor field, int index) { - throw new RuntimeException( - "There is no repeated field in a map entry message."); + throw new RuntimeException("There is no repeated field in a map entry message."); } @Override @@ -445,7 +439,7 @@ public UnknownFieldSet getUnknownFields() { @Override @SuppressWarnings("unchecked") public Builder clone() { - return new Builder(metadata, key, value, hasKey, hasValue); + return new Builder<>(metadata, key, value, hasKey, hasValue); } } @@ -455,7 +449,7 @@ private static boolean isInitialized(Metadata metadata, V value) { } return true; } - + /** Returns the metadata only for experimental runtime. */ final Metadata getMetadata() { return metadata; diff --git a/java/core/src/main/java/com/google/protobuf/MapEntryLite.java b/java/core/src/main/java/com/google/protobuf/MapEntryLite.java index dcb5dfad3df91..81bf4c2b18406 100644 --- a/java/core/src/main/java/com/google/protobuf/MapEntryLite.java +++ b/java/core/src/main/java/com/google/protobuf/MapEntryLite.java @@ -37,11 +37,10 @@ /** * Implements the lite version of map entry messages. * - * This class serves as an utility class to help do serialization/parsing of - * map entries. It's used in generated code and also in the full version - * MapEntry message. + *

This class serves as an utility class to help do serialization/parsing of map entries. It's + * used in generated code and also in the full version MapEntry message. * - * Protobuf internal. Users shouldn't use. + *

Protobuf internal. Users shouldn't use. */ public class MapEntryLite { @@ -52,8 +51,10 @@ static class Metadata { public final V defaultValue; public Metadata( - WireFormat.FieldType keyType, K defaultKey, - WireFormat.FieldType valueType, V defaultValue) { + WireFormat.FieldType keyType, + K defaultKey, + WireFormat.FieldType valueType, + V defaultValue) { this.keyType = keyType; this.defaultKey = defaultKey; this.valueType = valueType; @@ -70,8 +71,7 @@ public Metadata( /** Creates a default MapEntryLite message instance. */ private MapEntryLite( - WireFormat.FieldType keyType, K defaultKey, - WireFormat.FieldType valueType, V defaultValue) { + WireFormat.FieldType keyType, K defaultKey, WireFormat.FieldType valueType, V defaultValue) { this.metadata = new Metadata(keyType, defaultKey, valueType, defaultValue); this.key = defaultKey; this.value = defaultValue; @@ -95,16 +95,13 @@ public V getValue() { /** * Creates a default MapEntryLite message instance. * - * This method is used by generated code to create the default instance for - * a map entry message. The created default instance should be used to create - * new map entry messages of the same type. For each map entry message, only - * one default instance should be created. + *

This method is used by generated code to create the default instance for a map entry + * message. The created default instance should be used to create new map entry messages of the + * same type. For each map entry message, only one default instance should be created. */ public static MapEntryLite newDefaultInstance( - WireFormat.FieldType keyType, K defaultKey, - WireFormat.FieldType valueType, V defaultValue) { - return new MapEntryLite( - keyType, defaultKey, valueType, defaultValue); + WireFormat.FieldType keyType, K defaultKey, WireFormat.FieldType valueType, V defaultValue) { + return new MapEntryLite(keyType, defaultKey, valueType, defaultValue); } static void writeTo(CodedOutputStream output, Metadata metadata, K key, V value) @@ -120,8 +117,11 @@ static int computeSerializedSize(Metadata metadata, K key, V value) @SuppressWarnings("unchecked") static T parseField( - CodedInputStream input, ExtensionRegistryLite extensionRegistry, - WireFormat.FieldType type, T value) throws IOException { + CodedInputStream input, + ExtensionRegistryLite extensionRegistry, + WireFormat.FieldType type, + T value) + throws IOException { switch (type) { case MESSAGE: MessageLite.Builder subBuilder = ((MessageLite) value).toBuilder(); @@ -137,9 +137,9 @@ static T parseField( } /** - * Serializes the provided key and value as though they were wrapped by a {@link MapEntryLite} - * to the output stream. This helper method avoids allocation of a {@link MapEntryLite} - * built with a key and value and is called from generated code directly. + * Serializes the provided key and value as though they were wrapped by a {@link MapEntryLite} to + * the output stream. This helper method avoids allocation of a {@link MapEntryLite} built with a + * key and value and is called from generated code directly. */ public void serializeTo(CodedOutputStream output, int fieldNumber, K key, V value) throws IOException { @@ -149,9 +149,9 @@ public void serializeTo(CodedOutputStream output, int fieldNumber, K key, V valu } /** - * Computes the message size for the provided key and value as though they were wrapped - * by a {@link MapEntryLite}. This helper method avoids allocation of a {@link MapEntryLite} - * built with a key and value and is called from generated code directly. + * Computes the message size for the provided key and value as though they were wrapped by a + * {@link MapEntryLite}. This helper method avoids allocation of a {@link MapEntryLite} built with + * a key and value and is called from generated code directly. */ public int computeMessageSize(int fieldNumber, K key, V value) { return CodedOutputStream.computeTagSize(fieldNumber) @@ -160,8 +160,8 @@ public int computeMessageSize(int fieldNumber, K key, V value) { } /** - * Parses an entry off of the input as a {@link Map.Entry}. This helper requires an allocation - * so using {@link #parseInto} is preferred if possible. + * Parses an entry off of the input as a {@link Map.Entry}. This helper requires an allocation so + * using {@link #parseInto} is preferred if possible. */ public Map.Entry parseEntry(ByteString bytes, ExtensionRegistryLite extensionRegistry) throws IOException { @@ -170,7 +170,7 @@ public Map.Entry parseEntry(ByteString bytes, ExtensionRegistryLite extens static Map.Entry parseEntry( CodedInputStream input, Metadata metadata, ExtensionRegistryLite extensionRegistry) - throws IOException{ + throws IOException { K key = metadata.defaultKey; V value = metadata.defaultValue; while (true) { @@ -192,12 +192,12 @@ static Map.Entry parseEntry( } /** - * Parses an entry off of the input into the map. This helper avoids allocaton of a - * {@link MapEntryLite} by parsing directly into the provided {@link MapFieldLite}. + * Parses an entry off of the input into the map. This helper avoids allocation of a {@link + * MapEntryLite} by parsing directly into the provided {@link MapFieldLite}. */ public void parseInto( MapFieldLite map, CodedInputStream input, ExtensionRegistryLite extensionRegistry) - throws IOException { + throws IOException { int length = input.readRawVarint32(); final int oldLimit = input.pushLimit(length); K key = metadata.defaultKey; diff --git a/java/core/src/main/java/com/google/protobuf/MapField.java b/java/core/src/main/java/com/google/protobuf/MapField.java index ad8ceb02a9161..f487736065f2f 100644 --- a/java/core/src/main/java/com/google/protobuf/MapField.java +++ b/java/core/src/main/java/com/google/protobuf/MapField.java @@ -44,38 +44,44 @@ /** * Internal representation of map fields in generated messages. * - * This class supports accessing the map field as a {@link Map} to be used in - * generated API and also supports accessing the field as a {@link List} to be - * used in reflection API. It keeps track of where the data is currently stored - * and do necessary conversions between map and list. + *

This class supports accessing the map field as a {@link Map} to be used in generated API and + * also supports accessing the field as a {@link List} to be used in reflection API. It keeps track + * of where the data is currently stored and do necessary conversions between map and list. * - * This class is a protobuf implementation detail. Users shouldn't use this - * class directly. + *

This class is a protobuf implementation detail. Users shouldn't use this class directly. * - * THREAD-SAFETY NOTE: Read-only access is thread-safe. Users can call getMap() - * and getList() concurrently in multiple threads. If write-access is needed, - * all access must be synchronized. + *

THREAD-SAFETY NOTE: Read-only access is thread-safe. Users can call getMap() and getList() + * concurrently in multiple threads. If write-access is needed, all access must be synchronized. */ public class MapField implements MutabilityOracle { + /** * Indicates where the data of this map field is currently stored. * - * MAP: Data is stored in mapData. - * LIST: Data is stored in listData. - * BOTH: mapData and listData have the same data. + *

    + *
  • MAP: Data is stored in mapData. + *
  • LIST: Data is stored in listData. + *
  • BOTH: mapData and listData have the same data. + *
* - * When the map field is accessed (through generated API or reflection API), - * it will shift between these 3 modes: + *

When the map field is accessed (through generated API or reflection API), it will shift + * between these 3 modes: * - * getMap() getList() getMutableMap() getMutableList() - * MAP MAP BOTH MAP LIST - * LIST BOTH LIST MAP LIST - * BOTH BOTH BOTH MAP LIST + *

+   *          getMap()   getList()    getMutableMap()   getMutableList()
+   * MAP      MAP        BOTH         MAP               LIST
+   * LIST     BOTH       LIST         MAP               LIST
+   * BOTH     BOTH       BOTH         MAP               LIST
+   * 
* - * As the map field changes its mode, the list/map reference returned in a - * previous method call may be invalidated. + *

As the map field changes its mode, the list/map reference returned in a previous method call + * may be invalidated. */ - private enum StorageMode {MAP, LIST, BOTH} + private enum StorageMode { + MAP, + LIST, + BOTH + } private volatile boolean isMutable; private volatile StorageMode mode; @@ -85,6 +91,7 @@ private enum StorageMode {MAP, LIST, BOTH} // Convert between a map entry Message and a key-value pair. private static interface Converter { Message convertKeyAndValueToMessage(K key, V value); + void convertMessageToKeyAndValue(Message message, Map map); Message getMessageDefaultInstance(); @@ -92,6 +99,7 @@ private static interface Converter { private static class ImmutableMessageConverter implements Converter { private final MapEntry defaultEntry; + public ImmutableMessageConverter(MapEntry defaultEntry) { this.defaultEntry = defaultEntry; } @@ -117,10 +125,7 @@ public Message getMessageDefaultInstance() { private final Converter converter; - private MapField( - Converter converter, - StorageMode mode, - Map mapData) { + private MapField(Converter converter, StorageMode mode, Map mapData) { this.converter = converter; this.isMutable = true; this.mode = mode; @@ -128,26 +133,20 @@ private MapField( this.listData = null; } - private MapField( - MapEntry defaultEntry, - StorageMode mode, - Map mapData) { + private MapField(MapEntry defaultEntry, StorageMode mode, Map mapData) { this(new ImmutableMessageConverter(defaultEntry), mode, mapData); } /** Returns an immutable empty MapField. */ - public static MapField emptyMapField( - MapEntry defaultEntry) { - return new MapField( - defaultEntry, StorageMode.MAP, Collections.emptyMap()); + public static MapField emptyMapField(MapEntry defaultEntry) { + return new MapField(defaultEntry, StorageMode.MAP, Collections.emptyMap()); } /** Creates a new mutable empty MapField. */ public static MapField newMapField(MapEntry defaultEntry) { - return new MapField( - defaultEntry, StorageMode.MAP, new LinkedHashMap()); + return new MapField(defaultEntry, StorageMode.MAP, new LinkedHashMap()); } @@ -163,9 +162,7 @@ private void convertMessageToKeyAndValue(Message message, Map map) { private List convertMapToList(MutatabilityAwareMap mapData) { List listData = new ArrayList(); for (Map.Entry entry : mapData.entrySet()) { - listData.add( - convertKeyAndValueToMessage( - entry.getKey(), entry.getValue())); + listData.add(convertKeyAndValueToMessage(entry.getKey(), entry.getValue())); } return listData; } @@ -229,8 +226,7 @@ public int hashCode() { /** Returns a deep copy of this MapField. */ public MapField copy() { - return new MapField( - converter, StorageMode.MAP, MapFieldLite.copy(getMap())); + return new MapField(converter, StorageMode.MAP, MapFieldLite.copy(getMap())); } /** Gets the content of this MapField as a read-only List. */ @@ -258,25 +254,20 @@ List getMutableList() { return listData; } - /** - * Gets the default instance of the message stored in the list view of this - * map field. - */ + /** Gets the default instance of the message stored in the list view of this map field. */ Message getMapEntryMessageDefaultInstance() { return converter.getMessageDefaultInstance(); } /** - * Makes this list immutable. All subsequent modifications will throw an - * {@link UnsupportedOperationException}. + * Makes this list immutable. All subsequent modifications will throw an {@link + * UnsupportedOperationException}. */ public void makeImmutable() { isMutable = false; } - /** - * Returns whether this field can be modified. - */ + /** Returns whether this field can be modified. */ public boolean isMutable() { return isMutable; } @@ -291,9 +282,7 @@ public void ensureMutable() { } } - /** - * An internal map that checks for mutability before delegating. - */ + /** An internal map that checks for mutability before delegating. */ private static class MutatabilityAwareMap implements Map { private final MutabilityOracle mutabilityOracle; private final Map delegate; @@ -388,9 +377,7 @@ public String toString() { return delegate.toString(); } - /** - * An internal collection that checks for mutability before delegating. - */ + /** An internal collection that checks for mutability before delegating. */ private static class MutatabilityAwareCollection implements Collection { private final MutabilityOracle mutabilityOracle; private final Collection delegate; @@ -487,9 +474,7 @@ public String toString() { } } - /** - * An internal set that checks for mutability before delegating. - */ + /** An internal set that checks for mutability before delegating. */ private static class MutatabilityAwareSet implements Set { private final MutabilityOracle mutabilityOracle; private final Set delegate; @@ -586,9 +571,7 @@ public String toString() { } } - /** - * An internal iterator that checks for mutability before delegating. - */ + /** An internal iterator that checks for mutability before delegating. */ private static class MutatabilityAwareIterator implements Iterator { private final MutabilityOracle mutabilityOracle; private final Iterator delegate; diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldLite.java b/java/core/src/main/java/com/google/protobuf/MapFieldLite.java index a8b3dd8849778..a9fec4d7d72aa 100644 --- a/java/core/src/main/java/com/google/protobuf/MapFieldLite.java +++ b/java/core/src/main/java/com/google/protobuf/MapFieldLite.java @@ -42,8 +42,7 @@ /** * Internal representation of map fields in generated lite-runtime messages. * - * This class is a protobuf implementation detail. Users shouldn't use this - * class directly. + *

This class is a protobuf implementation detail. Users shouldn't use this class directly. */ public final class MapFieldLite extends LinkedHashMap { @@ -59,7 +58,8 @@ private MapFieldLite(Map mapData) { } @SuppressWarnings({"rawtypes", "unchecked"}) - private static final MapFieldLite EMPTY_MAP_FIELD = new MapFieldLite(); + private static final MapFieldLite EMPTY_MAP_FIELD = new MapFieldLite<>(); + static { EMPTY_MAP_FIELD.makeImmutable(); } @@ -78,16 +78,19 @@ public void mergeFrom(MapFieldLite other) { } @SuppressWarnings({"unchecked", "cast"}) - @Override public Set> entrySet() { + @Override + public Set> entrySet() { return isEmpty() ? Collections.>emptySet() : super.entrySet(); } - @Override public void clear() { + @Override + public void clear() { ensureMutable(); super.clear(); } - @Override public V put(K key, V value) { + @Override + public V put(K key, V value) { ensureMutable(); checkNotNull(key); @@ -99,13 +102,15 @@ public V put(Map.Entry entry) { return put(entry.getKey(), entry.getValue()); } - @Override public void putAll(Map m) { + @Override + public void putAll(Map m) { ensureMutable(); checkForNullKeysAndValues(m); super.putAll(m); } - @Override public V remove(Object key) { + @Override + public V remove(Object key) { ensureMutable(); return super.remove(key); } @@ -125,9 +130,8 @@ private static boolean equals(Object a, Object b) { } /** - * Checks whether two {@link Map}s are equal. We don't use the default equals - * method of {@link Map} because it compares by identity not by content for - * byte arrays. + * Checks whether two {@link Map}s are equal. We don't use the default equals method of {@link + * Map} because it compares by identity not by content for byte arrays. */ static boolean equals(Map a, Map b) { if (a == b) { @@ -147,9 +151,7 @@ static boolean equals(Map a, Map b) { return true; } - /** - * Checks whether two map fields are equal. - */ + /** Checks whether two map fields are equal. */ @SuppressWarnings("unchecked") @Override public boolean equals(Object object) { @@ -168,15 +170,14 @@ private static int calculateHashCodeForObject(Object a) { } /** - * Calculates the hash code for a {@link Map}. We don't use the default hash - * code method of {@link Map} because for byte arrays and protobuf enums it - * use {@link Object#hashCode()}. + * Calculates the hash code for a {@link Map}. We don't use the default hash code method of {@link + * Map} because for byte arrays and protobuf enums it use {@link Object#hashCode()}. */ static int calculateHashCodeForMap(Map a) { int result = 0; for (Map.Entry entry : a.entrySet()) { - result += calculateHashCodeForObject(entry.getKey()) - ^ calculateHashCodeForObject(entry.getValue()); + result += + calculateHashCodeForObject(entry.getKey()) ^ calculateHashCodeForObject(entry.getValue()); } return result; } @@ -195,9 +196,9 @@ private static Object copy(Object object) { } /** - * Makes a deep copy of a {@link Map}. Immutable objects in the map will be - * shared (e.g., integers, strings, immutable messages) and mutable ones will - * have a copy (e.g., byte arrays, mutable messages). + * Makes a deep copy of a {@link Map}. Immutable objects in the map will be shared (e.g., + * integers, strings, immutable messages) and mutable ones will have a copy (e.g., byte arrays, + * mutable messages). */ @SuppressWarnings("unchecked") static Map copy(Map map) { @@ -214,16 +215,14 @@ public MapFieldLite mutableCopy() { } /** - * Makes this field immutable. All subsequent modifications will throw an - * {@link UnsupportedOperationException}. + * Makes this field immutable. All subsequent modifications will throw an {@link + * UnsupportedOperationException}. */ public void makeImmutable() { isMutable = false; } - /** - * Returns whether this field can be modified. - */ + /** Returns whether this field can be modified. */ public boolean isMutable() { return isMutable; } diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldSchema.java b/java/core/src/main/java/com/google/protobuf/MapFieldSchema.java new file mode 100644 index 0000000000000..195126e51435f --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/MapFieldSchema.java @@ -0,0 +1,63 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.util.Map; + +interface MapFieldSchema { + /** Returns the map data for mutation. */ + Map forMutableMapData(Object mapField); + + /** Returns the map data for read. */ + Map forMapData(Object mapField); + + /** Whether toImmutable() has been called on this map field. */ + boolean isImmutable(Object mapField); + + /** + * Returns an immutable instance of the map field. It may make the parameter immutable and return + * the parameter, or create an immutable copy. The status of the parameter after the call is + * undefined. + */ + Object toImmutable(Object mapField); + + /** Returns a new instance of the map field given a map default entry. */ + Object newMapField(Object mapDefaultEntry); + + /** Returns the metadata from a default entry. */ + MapEntryLite.Metadata forMapMetadata(Object mapDefaultEntry); + + /** Merges {@code srcMapField} into {@code destMapField}, and returns the merged instance. */ + Object mergeFrom(Object destMapField, Object srcMapField); + + /** Compute the serialized size for the map with a given field number. */ + int getSerializedSize(int fieldNumber, Object mapField, Object mapDefaultEntry); +} diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldSchemaFull.java b/java/core/src/main/java/com/google/protobuf/MapFieldSchemaFull.java new file mode 100644 index 0000000000000..1efaab3bcee85 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/MapFieldSchemaFull.java @@ -0,0 +1,112 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.MapEntryLite.Metadata; +import java.util.Map; + +class MapFieldSchemaFull implements MapFieldSchema { + @Override + public Map forMutableMapData(Object mapField) { + return ((MapField) mapField).getMutableMap(); + } + + @Override + public Map forMapData(Object mapField) { + return ((MapField) mapField).getMap(); + } + + @Override + public boolean isImmutable(Object mapField) { + return !((MapField) mapField).isMutable(); + } + + @Override + public Object toImmutable(Object mapField) { + ((MapField) mapField).makeImmutable(); + return mapField; + } + + @Override + public Object newMapField(Object mapDefaultEntry) { + return MapField.newMapField((MapEntry) mapDefaultEntry); + } + + @Override + public Metadata forMapMetadata(Object mapDefaultEntry) { + return ((MapEntry) mapDefaultEntry).getMetadata(); + } + + @Override + public Object mergeFrom(Object destMapField, Object srcMapField) { + return mergeFromFull(destMapField, srcMapField); + } + + @SuppressWarnings("unchecked") + private static Object mergeFromFull(Object destMapField, Object srcMapField) { + MapField mine = (MapField) destMapField; + MapField other = (MapField) srcMapField; + if (!mine.isMutable()) { + mine.copy(); + } + mine.mergeFrom(other); + return mine; + } + + @Override + public int getSerializedSize(int number, Object mapField, Object mapDefaultEntry) { + return getSerializedSizeFull(number, mapField, mapDefaultEntry); + } + + @SuppressWarnings("unchecked") + private static int getSerializedSizeFull( + int number, Object mapField, Object defaultEntryObject) { + // Full runtime allocates map fields lazily. + if (mapField == null) { + return 0; + } + + Map map = ((MapField) mapField).getMap(); + MapEntry defaultEntry = (MapEntry) defaultEntryObject; + if (map.isEmpty()) { + return 0; + } + int size = 0; + for (Map.Entry entry : map.entrySet()) { + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeLengthDelimitedFieldSize( + MapEntryLite.computeSerializedSize( + defaultEntry.getMetadata(), entry.getKey(), entry.getValue())); + } + return size; + } +} diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldSchemaLite.java b/java/core/src/main/java/com/google/protobuf/MapFieldSchemaLite.java new file mode 100644 index 0000000000000..8a8c78de8aaa6 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/MapFieldSchemaLite.java @@ -0,0 +1,107 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.MapEntryLite.Metadata; +import java.util.Map; + +class MapFieldSchemaLite implements MapFieldSchema { + + @Override + public Map forMutableMapData(Object mapField) { + return (MapFieldLite) mapField; + } + + @Override + public Metadata forMapMetadata(Object mapDefaultEntry) { + return ((MapEntryLite) mapDefaultEntry).getMetadata(); + } + + @Override + public Map forMapData(Object mapField) { + return (MapFieldLite) mapField; + } + + @Override + public boolean isImmutable(Object mapField) { + return !((MapFieldLite) mapField).isMutable(); + } + + @Override + public Object toImmutable(Object mapField) { + ((MapFieldLite) mapField).makeImmutable(); + return mapField; + } + + @Override + public Object newMapField(Object unused) { + return MapFieldLite.emptyMapField().mutableCopy(); + } + + @Override + public Object mergeFrom(Object destMapField, Object srcMapField) { + return mergeFromLite(destMapField, srcMapField); + } + + @SuppressWarnings("unchecked") + private static MapFieldLite mergeFromLite(Object destMapField, Object srcMapField) { + MapFieldLite mine = (MapFieldLite) destMapField; + MapFieldLite other = (MapFieldLite) srcMapField; + if (!other.isEmpty()) { + if (!mine.isMutable()) { + mine = mine.mutableCopy(); + } + mine.mergeFrom(other); + } + return mine; + } + + @Override + public int getSerializedSize(int fieldNumber, Object mapField, Object mapDefaultEntry) { + return getSerializedSizeLite(fieldNumber, mapField, mapDefaultEntry); + } + + @SuppressWarnings("unchecked") + private static int getSerializedSizeLite( + int fieldNumber, Object mapField, Object defaultEntry) { + MapFieldLite mapFieldLite = (MapFieldLite) mapField; + MapEntryLite defaultEntryLite = (MapEntryLite) defaultEntry; + + if (mapFieldLite.isEmpty()) { + return 0; + } + int size = 0; + for (Map.Entry entry : mapFieldLite.entrySet()) { + size += defaultEntryLite.computeMessageSize(fieldNumber, entry.getKey(), entry.getValue()); + } + return size; + } +} diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldSchemas.java b/java/core/src/main/java/com/google/protobuf/MapFieldSchemas.java new file mode 100644 index 0000000000000..b398c61022149 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/MapFieldSchemas.java @@ -0,0 +1,53 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +final class MapFieldSchemas { + private static final MapFieldSchema FULL_SCHEMA = loadSchemaForFullRuntime(); + private static final MapFieldSchema LITE_SCHEMA = new MapFieldSchemaLite(); + + static MapFieldSchema full() { + return FULL_SCHEMA; + } + + static MapFieldSchema lite() { + return LITE_SCHEMA; + } + + private static MapFieldSchema loadSchemaForFullRuntime() { + try { + Class clazz = Class.forName("com.google.protobuf.MapFieldSchemaFull"); + return (MapFieldSchema) clazz.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + return null; + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/Message.java b/java/core/src/main/java/com/google/protobuf/Message.java index 94590fb91b3b5..9b3a015ba9825 100644 --- a/java/core/src/main/java/com/google/protobuf/Message.java +++ b/java/core/src/main/java/com/google/protobuf/Message.java @@ -39,12 +39,11 @@ /** * Abstract interface implemented by Protocol Message objects. - *

- * See also {@link MessageLite}, which defines most of the methods that typical - * users care about. {@link Message} adds to it methods that are not available - * in the "lite" runtime. The biggest added features are introspection and - * reflection -- i.e., getting descriptors for the message type and accessing - * the field values dynamically. + * + *

See also {@link MessageLite}, which defines most of the methods that typical users care about. + * {@link Message} adds to it methods that are not available in the "lite" runtime. The biggest + * added features are introspection and reflection -- i.e., getting descriptors for the message type + * and accessing the field values dynamically. * * @author kenton@google.com Kenton Varda */ @@ -59,11 +58,10 @@ public interface Message extends MessageLite, MessageOrBuilder { // Comparison and hashing /** - * Compares the specified object with this message for equality. Returns - * {@code true} if the given object is a message of the same type (as - * defined by {@code getDescriptorForType()}) and has identical values for - * all of its fields. Subclasses must implement this; inheriting - * {@code Object.equals()} is incorrect. + * Compares the specified object with this message for equality. Returns {@code true} if the given + * object is a message of the same type (as defined by {@code getDescriptorForType()}) and has + * identical values for all of its fields. Subclasses must implement this; inheriting {@code + * Object.equals()} is incorrect. * * @param other object to be compared for equality with this message * @return {@code true} if the specified object is equal to this message @@ -72,10 +70,9 @@ public interface Message extends MessageLite, MessageOrBuilder { boolean equals(Object other); /** - * Returns the hash code value for this message. The hash code of a message - * should mix the message's type (object identity of the descriptor) with its - * contents (known and unknown field values). Subclasses must implement this; - * inheriting {@code Object.hashCode()} is incorrect. + * Returns the hash code value for this message. The hash code of a message should mix the + * message's type (object identity of the descriptor) with its contents (known and unknown field + * values). Subclasses must implement this; inheriting {@code Object.hashCode()} is incorrect. * * @return the hash code value for this message * @see Map#hashCode() @@ -87,9 +84,8 @@ public interface Message extends MessageLite, MessageOrBuilder { // Convenience methods. /** - * Converts the message to a string in protocol buffer text format. This is - * just a trivial wrapper around {@link - * TextFormat#printToString(MessageOrBuilder)}. + * Converts the message to a string in protocol buffer text format. This is just a trivial wrapper + * around {@link TextFormat.Printer#printToString(MessageOrBuilder)}. */ @Override String toString(); @@ -104,9 +100,7 @@ public interface Message extends MessageLite, MessageOrBuilder { @Override Builder toBuilder(); - /** - * Abstract interface implemented by Protocol Message builders. - */ + /** Abstract interface implemented by Protocol Message builders. */ interface Builder extends MessageLite.Builder, MessageOrBuilder { // (From MessageLite.Builder, re-declared here only for return type // covariance.) @@ -114,23 +108,21 @@ interface Builder extends MessageLite.Builder, MessageOrBuilder { Builder clear(); /** - * Merge {@code other} into the message being built. {@code other} must - * have the exact same type as {@code this} (i.e. - * {@code getDescriptorForType() == other.getDescriptorForType()}). + * Merge {@code other} into the message being built. {@code other} must have the exact same type + * as {@code this} (i.e. {@code getDescriptorForType() == other.getDescriptorForType()}). * - * Merging occurs as follows. For each field:
- * * For singular primitive fields, if the field is set in {@code other}, - * then {@code other}'s value overwrites the value in this message.
- * * For singular message fields, if the field is set in {@code other}, - * it is merged into the corresponding sub-message of this message - * using the same merging rules.
- * * For repeated fields, the elements in {@code other} are concatenated - * with the elements in this message. - * * For oneof groups, if the other message has one of the fields set, - * the group of this message is cleared and replaced by the field - * of the other message, so that the oneof constraint is preserved. + *

Merging occurs as follows. For each field:
+ * * For singular primitive fields, if the field is set in {@code other}, then {@code other}'s + * value overwrites the value in this message.
+ * * For singular message fields, if the field is set in {@code other}, it is merged into the + * corresponding sub-message of this message using the same merging rules.
+ * * For repeated fields, the elements in {@code other} are concatenated with the elements in + * this message.
+ * * For oneof groups, if the other message has one of the fields set, the group of this message + * is cleared and replaced by the field of the other message, so that the oneof constraint is + * preserved. * - * This is equivalent to the {@code Message::MergeFrom} method in C++. + *

This is equivalent to the {@code Message::MergeFrom} method in C++. */ Builder mergeFrom(Message other); @@ -152,101 +144,97 @@ interface Builder extends MessageLite.Builder, MessageOrBuilder { Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws IOException; - /** - * Get the message's type's descriptor. - * See {@link Message#getDescriptorForType()}. - */ + /** Get the message's type's descriptor. See {@link Message#getDescriptorForType()}. */ @Override Descriptors.Descriptor getDescriptorForType(); /** - * Create a Builder for messages of the appropriate type for the given - * field. Messages built with this can then be passed to setField(), - * setRepeatedField(), or addRepeatedField(). + * Create a builder for messages of the appropriate type for the given field. The + * builder is NOT nested in the current builder. However, messages built with the + * builder can then be passed to the {@link #setField(Descriptors.FieldDescriptor, Object)}, + * {@link #setRepeatedField(Descriptors.FieldDescriptor, int, Object)}, or + * {@link #addRepeatedField(Descriptors.FieldDescriptor, Object)} + * method of the current builder. + * + *

To obtain a builder nested in the current builder, use + * {@link #getFieldBuilder(Descriptors.FieldDescriptor)} instead. */ Builder newBuilderForField(Descriptors.FieldDescriptor field); /** * Get a nested builder instance for the given field. - *

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

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

- * NOTE: implementations that do not support nested builders will throw - * UnsupportedOperationException. + * + *

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

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

NOTE: implementations that do not support nested builders will throw + * UnsupportedOperationException. */ Builder getFieldBuilder(Descriptors.FieldDescriptor field); /** * Get a nested builder instance for the given repeated field instance. - *

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

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

- * NOTE: implementations that do not support nested builders will throw - * UnsupportedOperationException. + * + *

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

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

NOTE: implementations that do not support nested builders will throw + * UnsupportedOperationException. */ - Builder getRepeatedFieldBuilder(Descriptors.FieldDescriptor field, - int index); + Builder getRepeatedFieldBuilder(Descriptors.FieldDescriptor field, int index); /** - * Sets a field to the given value. The value must be of the correct type - * for this field, i.e. the same type that - * {@link Message#getField(Descriptors.FieldDescriptor)} would return. + * Sets a field to the given value. The value must be of the correct type for this field, i.e. + * the same type that {@link Message#getField(Descriptors.FieldDescriptor)} would return. */ Builder setField(Descriptors.FieldDescriptor field, Object value); /** - * Clears the field. This is exactly equivalent to calling the generated - * "clear" accessor method corresponding to the field. + * Clears the field. This is exactly equivalent to calling the generated "clear" accessor method + * corresponding to the field. */ Builder clearField(Descriptors.FieldDescriptor field); /** - * Clears the oneof. This is exactly equivalent to calling the generated - * "clear" accessor method corresponding to the oneof. + * Clears the oneof. This is exactly equivalent to calling the generated "clear" accessor method + * corresponding to the oneof. */ Builder clearOneof(Descriptors.OneofDescriptor oneof); /** - * Sets an element of a repeated field to the given value. The value must - * be of the correct type for this field, i.e. the same type that - * {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)} would - * return. - * @throws IllegalArgumentException The field is not a repeated field, or - * {@code field.getContainingType() != getDescriptorForType()}. + * Sets an element of a repeated field to the given value. The value must be of the correct type + * for this field, i.e. the same type that {@link + * Message#getRepeatedField(Descriptors.FieldDescriptor,int)} would return. + * + * @throws IllegalArgumentException The field is not a repeated field, or {@code + * field.getContainingType() != getDescriptorForType()}. */ - Builder setRepeatedField(Descriptors.FieldDescriptor field, - int index, Object value); + Builder setRepeatedField(Descriptors.FieldDescriptor field, int index, Object value); /** * Like {@code setRepeatedField}, but appends the value as a new element. - * @throws IllegalArgumentException The field is not a repeated field, or - * {@code field.getContainingType() != getDescriptorForType()}. + * + * @throws IllegalArgumentException The field is not a repeated field, or {@code + * field.getContainingType() != getDescriptorForType()}. */ Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value); /** Set the {@link UnknownFieldSet} for this message. */ Builder setUnknownFields(UnknownFieldSet unknownFields); - /** - * Merge some unknown fields into the {@link UnknownFieldSet} for this - * message. - */ + /** Merge some unknown fields into the {@link UnknownFieldSet} for this message. */ Builder mergeUnknownFields(UnknownFieldSet unknownFields); // --------------------------------------------------------------- diff --git a/java/core/src/main/java/com/google/protobuf/MessageInfo.java b/java/core/src/main/java/com/google/protobuf/MessageInfo.java new file mode 100644 index 0000000000000..69e318696aa33 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/MessageInfo.java @@ -0,0 +1,43 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** A MesageInfo object describes a proto message type. */ +interface MessageInfo { + /** Gets syntax for this type. */ + ProtoSyntax getSyntax(); + + /** Whether this type is MessageSet. */ + boolean isMessageSetWireFormat(); + + /** Gets the default instance of this type. */ + MessageLite getDefaultInstance(); +} diff --git a/java/core/src/main/java/com/google/protobuf/MessageInfoFactory.java b/java/core/src/main/java/com/google/protobuf/MessageInfoFactory.java new file mode 100644 index 0000000000000..005c26d05f7d4 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/MessageInfoFactory.java @@ -0,0 +1,41 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** A factory that creates {@link MessageInfo} instances for message types. */ +@ExperimentalApi +interface MessageInfoFactory { + /** Whether the message class is supported by this factory. */ + boolean isSupported(Class clazz); + + /** Returns a information of the message class. */ + MessageInfo messageInfoFor(Class clazz); +} diff --git a/java/core/src/main/java/com/google/protobuf/MessageLite.java b/java/core/src/main/java/com/google/protobuf/MessageLite.java index 88f531df3e8a6..7d2ef33a17f0e 100644 --- a/java/core/src/main/java/com/google/protobuf/MessageLite.java +++ b/java/core/src/main/java/com/google/protobuf/MessageLite.java @@ -40,91 +40,79 @@ /** * Abstract interface implemented by Protocol Message objects. * - *

This interface is implemented by all protocol message objects. Non-lite - * messages additionally implement the Message interface, which is a subclass - * of MessageLite. Use MessageLite instead when you only need the subset of - * features which it supports -- namely, nothing that uses descriptors or - * reflection. You can instruct the protocol compiler to generate classes - * which implement only MessageLite, not the full Message interface, by adding - * the follow line to the .proto file: + *

This interface is implemented by all protocol message objects. Non-lite messages additionally + * implement the Message interface, which is a subclass of MessageLite. Use MessageLite instead when + * you only need the subset of features which it supports -- namely, nothing that uses descriptors + * or reflection. You can instruct the protocol compiler to generate classes which implement only + * MessageLite, not the full Message interface, by adding the follow line to the .proto file: + * *

  *   option optimize_for = LITE_RUNTIME;
  * 
* - *

This is particularly useful on resource-constrained systems where the - * full protocol buffers runtime library is too big. + *

This is particularly useful on resource-constrained systems where the full protocol buffers + * runtime library is too big. * - *

Note that on non-constrained systems (e.g. servers) when you need to link - * in lots of protocol definitions, a better way to reduce total code footprint - * is to use {@code optimize_for = CODE_SIZE}. This will make the generated - * code smaller while still supporting all the same features (at the expense of - * speed). {@code optimize_for = LITE_RUNTIME} is best when you only have a - * small number of message types linked into your binary, in which case the - * size of the protocol buffers runtime itself is the biggest problem. + *

Note that on non-constrained systems (e.g. servers) when you need to link in lots of protocol + * definitions, a better way to reduce total code footprint is to use {@code optimize_for = + * CODE_SIZE}. This will make the generated code smaller while still supporting all the same + * features (at the expense of speed). {@code optimize_for = LITE_RUNTIME} is best when you only + * have a small number of message types linked into your binary, in which case the size of the + * protocol buffers runtime itself is the biggest problem. * * @author kenton@google.com Kenton Varda */ public interface MessageLite extends MessageLiteOrBuilder { - /** - * Serializes the message and writes it to {@code output}. This does not - * flush or close the stream. + * Serializes the message and writes it to {@code output}. This does not flush or close the + * stream. */ void writeTo(CodedOutputStream output) throws IOException; /** - * Get the number of bytes required to encode this message. The result - * is only computed on the first call and memoized after that. + * Get the number of bytes required to encode this message. The result is only computed on the + * first call and memoized after that. */ int getSerializedSize(); - - /** - * Gets the parser for a message of the same type as this message. - */ + /** Gets the parser for a message of the same type as this message. */ Parser getParserForType(); // ----------------------------------------------------------------- // Convenience methods. /** - * Serializes the message to a {@code ByteString} and returns it. This is - * just a trivial wrapper around - * {@link #writeTo(CodedOutputStream)}. + * Serializes the message to a {@code ByteString} and returns it. This is just a trivial wrapper + * around {@link #writeTo(CodedOutputStream)}. */ ByteString toByteString(); /** - * Serializes the message to a {@code byte} array and returns it. This is - * just a trivial wrapper around - * {@link #writeTo(CodedOutputStream)}. + * Serializes the message to a {@code byte} array and returns it. This is just a trivial wrapper + * around {@link #writeTo(CodedOutputStream)}. */ byte[] toByteArray(); /** - * Serializes the message and writes it to {@code output}. This is just a - * trivial wrapper around {@link #writeTo(CodedOutputStream)}. This does - * not flush or close the stream. - *

- * NOTE: Protocol Buffers are not self-delimiting. Therefore, if you write - * any more data to the stream after the message, you must somehow ensure - * that the parser on the receiving end does not interpret this as being - * part of the protocol message. This can be done e.g. by writing the size - * of the message before the data, then making sure to limit the input to - * that size on the receiving end (e.g. by wrapping the InputStream in one - * which limits the input). Alternatively, just use - * {@link #writeDelimitedTo(OutputStream)}. + * Serializes the message and writes it to {@code output}. This is just a trivial wrapper around + * {@link #writeTo(CodedOutputStream)}. This does not flush or close the stream. + * + *

NOTE: Protocol Buffers are not self-delimiting. Therefore, if you write any more data to the + * stream after the message, you must somehow ensure that the parser on the receiving end does not + * interpret this as being part of the protocol message. This can be done e.g. by writing the size + * of the message before the data, then making sure to limit the input to that size on the + * receiving end (e.g. by wrapping the InputStream in one which limits the input). Alternatively, + * just use {@link #writeDelimitedTo(OutputStream)}. */ void writeTo(OutputStream output) throws IOException; /** - * Like {@link #writeTo(OutputStream)}, but writes the size of the message - * as a varint before writing the data. This allows more data to be written - * to the stream after the message without the need to delimit the message - * data yourself. Use {@link Builder#mergeDelimitedFrom(InputStream)} (or - * the static method {@code YourMessageType.parseDelimitedFrom(InputStream)}) - * to parse messages written by this method. + * Like {@link #writeTo(OutputStream)}, but writes the size of the message as a varint before + * writing the data. This allows more data to be written to the stream after the message without + * the need to delimit the message data yourself. Use {@link + * Builder#mergeDelimitedFrom(InputStream)} (or the static method {@code + * YourMessageType.parseDelimitedFrom(InputStream)}) to parse messages written by this method. */ void writeDelimitedTo(OutputStream output) throws IOException; @@ -132,210 +120,179 @@ public interface MessageLite extends MessageLiteOrBuilder { // ================================================================= // Builders - /** - * Constructs a new builder for a message of the same type as this message. - */ + /** Constructs a new builder for a message of the same type as this message. */ Builder newBuilderForType(); /** - * Constructs a builder initialized with the current message. Use this to - * derive a new message from the current one. + * Constructs a builder initialized with the current message. Use this to derive a new message + * from the current one. */ Builder toBuilder(); - /** - * Abstract interface implemented by Protocol Message builders. - */ + /** Abstract interface implemented by Protocol Message builders. */ interface Builder extends MessageLiteOrBuilder, Cloneable { /** Resets all fields to their default values. */ Builder clear(); /** - * Constructs the message based on the state of the Builder. Subsequent - * changes to the Builder will not affect the returned message. - * @throws UninitializedMessageException The message is missing one or more - * required fields (i.e. {@link #isInitialized()} returns false). - * Use {@link #buildPartial()} to bypass this check. + * Constructs the message based on the state of the Builder. Subsequent changes to the Builder + * will not affect the returned message. + * + * @throws UninitializedMessageException The message is missing one or more required fields + * (i.e. {@link #isInitialized()} returns false). Use {@link #buildPartial()} to bypass this + * check. */ MessageLite build(); /** - * Like {@link #build()}, but does not throw an exception if the message - * is missing required fields. Instead, a partial message is returned. - * Subsequent changes to the Builder will not affect the returned message. + * Like {@link #build()}, but does not throw an exception if the message is missing required + * fields. Instead, a partial message is returned. Subsequent changes to the Builder will not + * affect the returned message. */ MessageLite buildPartial(); /** * Clones the Builder. + * * @see Object#clone() */ Builder clone(); /** - * Parses a message of this type from the input and merges it with this - * message. + * Parses a message of this type from the input and merges it with this message. + * + *

Warning: This does not verify that all required fields are present in the input message. + * If you call {@link #build()} without setting all required fields, it will throw an {@link + * UninitializedMessageException}, which is a {@code RuntimeException} and thus might not be + * caught. There are a few good ways to deal with this: * - *

Warning: This does not verify that all required fields are present in - * the input message. If you call {@link #build()} without setting all - * required fields, it will throw an {@link UninitializedMessageException}, - * which is a {@code RuntimeException} and thus might not be caught. There - * are a few good ways to deal with this: *

    - *
  • Call {@link #isInitialized()} to verify that all required fields - * are set before building. - *
  • Use {@code buildPartial()} to build, which ignores missing - * required fields. + *
  • Call {@link #isInitialized()} to verify that all required fields are set before + * building. + *
  • Use {@code buildPartial()} to build, which ignores missing required fields. *
* - *

Note: The caller should call - * {@link CodedInputStream#checkLastTagWas(int)} after calling this to - * verify that the last tag seen was the appropriate end-group tag, - * or zero for EOF. + *

Note: The caller should call {@link CodedInputStream#checkLastTagWas(int)} after calling + * this to verify that the last tag seen was the appropriate end-group tag, or zero for EOF. */ Builder mergeFrom(CodedInputStream input) throws IOException; /** - * Like {@link Builder#mergeFrom(CodedInputStream)}, but also - * parses extensions. The extensions that you want to be able to parse - * must be registered in {@code extensionRegistry}. Extensions not in - * the registry will be treated as unknown fields. + * Like {@link Builder#mergeFrom(CodedInputStream)}, but also parses extensions. The extensions + * that you want to be able to parse must be registered in {@code extensionRegistry}. Extensions + * not in the registry will be treated as unknown fields. */ - Builder mergeFrom(CodedInputStream input, - ExtensionRegistryLite extensionRegistry) - throws IOException; + Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) + throws IOException; // --------------------------------------------------------------- // Convenience methods. /** - * Parse {@code data} as a message of this type and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream)}. + * Parse {@code data} as a message of this type and merge it with the message being built. This + * is just a small wrapper around {@link #mergeFrom(CodedInputStream)}. * * @return this */ Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException; /** - * Parse {@code data} as a message of this type and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}. + * Parse {@code data} as a message of this type and merge it with the message being built. This + * is just a small wrapper around {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}. * * @return this */ - Builder mergeFrom(ByteString data, - ExtensionRegistryLite extensionRegistry) - throws InvalidProtocolBufferException; + Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; /** - * Parse {@code data} as a message of this type and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream)}. + * Parse {@code data} as a message of this type and merge it with the message being built. This + * is just a small wrapper around {@link #mergeFrom(CodedInputStream)}. * * @return this */ Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException; /** - * Parse {@code data} as a message of this type and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream)}. + * Parse {@code data} as a message of this type and merge it with the message being built. This + * is just a small wrapper around {@link #mergeFrom(CodedInputStream)}. * * @return this */ - Builder mergeFrom(byte[] data, int off, int len) - throws InvalidProtocolBufferException; + Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException; /** - * Parse {@code data} as a message of this type and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}. + * Parse {@code data} as a message of this type and merge it with the message being built. This + * is just a small wrapper around {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}. * * @return this */ - Builder mergeFrom(byte[] data, - ExtensionRegistryLite extensionRegistry) - throws InvalidProtocolBufferException; + Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; /** - * Parse {@code data} as a message of this type and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}. + * Parse {@code data} as a message of this type and merge it with the message being built. This + * is just a small wrapper around {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}. * * @return this */ - Builder mergeFrom(byte[] data, int off, int len, - ExtensionRegistryLite extensionRegistry) - throws InvalidProtocolBufferException; + Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; /** - * Parse a message of this type from {@code input} and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream)}. Note that this method always - * reads the entire input (unless it throws an exception). If you - * want it to stop earlier, you will need to wrap your input in some - * wrapper stream that limits reading. Or, use - * {@link MessageLite#writeDelimitedTo(OutputStream)} to write your message - * and {@link #mergeDelimitedFrom(InputStream)} to read it. - *

- * Despite usually reading the entire input, this does not close the stream. + * Parse a message of this type from {@code input} and merge it with the message being built. + * This is just a small wrapper around {@link #mergeFrom(CodedInputStream)}. Note that this + * method always reads the entire input (unless it throws an exception). If you want it + * to stop earlier, you will need to wrap your input in some wrapper stream that limits reading. + * Or, use {@link MessageLite#writeDelimitedTo(OutputStream)} to write your message and {@link + * #mergeDelimitedFrom(InputStream)} to read it. + * + *

Despite usually reading the entire input, this does not close the stream. * * @return this */ Builder mergeFrom(InputStream input) throws IOException; /** - * Parse a message of this type from {@code input} and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}. + * Parse a message of this type from {@code input} and merge it with the message being built. + * This is just a small wrapper around {@link + * #mergeFrom(CodedInputStream,ExtensionRegistryLite)}. * * @return this */ - Builder mergeFrom(InputStream input, - ExtensionRegistryLite extensionRegistry) - throws IOException; - + Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry) + throws IOException; + /** - * Merge {@code other} into the message being built. {@code other} must - * have the exact same type as {@code this} (i.e. - * {@code getClass().equals(getDefaultInstanceForType().getClass())}). + * Merge {@code other} into the message being built. {@code other} must have the exact same type + * as {@code this} (i.e. {@code getClass().equals(getDefaultInstanceForType().getClass())}). * - * Merging occurs as follows. For each field:
- * * For singular primitive fields, if the field is set in {@code other}, - * then {@code other}'s value overwrites the value in this message.
- * * For singular message fields, if the field is set in {@code other}, - * it is merged into the corresponding sub-message of this message - * using the same merging rules.
- * * For repeated fields, the elements in {@code other} are concatenated - * with the elements in this message. - * * For oneof groups, if the other message has one of the fields set, - * the group of this message is cleared and replaced by the field - * of the other message, so that the oneof constraint is preserved. + *

Merging occurs as follows. For each field:
+ * * For singular primitive fields, if the field is set in {@code other}, then {@code other}'s + * value overwrites the value in this message.
+ * * For singular message fields, if the field is set in {@code other}, it is merged into the + * corresponding sub-message of this message using the same merging rules.
+ * * For repeated fields, the elements in {@code other} are concatenated with the elements in + * this message. * For oneof groups, if the other message has one of the fields set, the group + * of this message is cleared and replaced by the field of the other message, so that the oneof + * constraint is preserved. * - * This is equivalent to the {@code Message::MergeFrom} method in C++. + *

This is equivalent to the {@code Message::MergeFrom} method in C++. */ Builder mergeFrom(MessageLite other); /** - * Like {@link #mergeFrom(InputStream)}, but does not read until EOF. - * Instead, the size of the message (encoded as a varint) is read first, - * then the message data. Use - * {@link MessageLite#writeDelimitedTo(OutputStream)} to write messages in - * this format. + * Like {@link #mergeFrom(InputStream)}, but does not read until EOF. Instead, the size of the + * message (encoded as a varint) is read first, then the message data. Use {@link + * MessageLite#writeDelimitedTo(OutputStream)} to write messages in this format. * - * @return True if successful, or false if the stream is at EOF when the - * method starts. Any other error (including reaching EOF during - * parsing) will cause an exception to be thrown. + * @return True if successful, or false if the stream is at EOF when the method starts. Any + * other error (including reaching EOF during parsing) will cause an exception to be thrown. */ - boolean mergeDelimitedFrom(InputStream input) - throws IOException; + boolean mergeDelimitedFrom(InputStream input) throws IOException; - /** - * Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions. - */ - boolean mergeDelimitedFrom(InputStream input, - ExtensionRegistryLite extensionRegistry) - throws IOException; + /** Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions. */ + boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry) + throws IOException; } } diff --git a/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java b/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java index 818386ce58922..7a5ef3ed518d0 100644 --- a/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java +++ b/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java @@ -31,30 +31,27 @@ package com.google.protobuf; /** - * Base interface for methods common to {@link MessageLite} - * and {@link MessageLite.Builder} to provide type equivalency. + * Base interface for methods common to {@link MessageLite} and {@link MessageLite.Builder} to + * provide type equivalency. * * @author jonp@google.com (Jon Perlow) */ public interface MessageLiteOrBuilder { /** - * Get an instance of the type with no fields set. Because no fields are set, - * all getters for singular fields will return default values and repeated - * fields will appear empty. - * This may or may not be a singleton. This differs from the - * {@code getDefaultInstance()} method of generated message classes in that - * this method is an abstract method of the {@code MessageLite} interface - * whereas {@code getDefaultInstance()} is a static method of a specific - * class. They return the same thing. + * Get an instance of the type with no fields set. Because no fields are set, all getters for + * singular fields will return default values and repeated fields will appear empty. This may or + * may not be a singleton. This differs from the {@code getDefaultInstance()} method of generated + * message classes in that this method is an abstract method of the {@code MessageLite} interface + * whereas {@code getDefaultInstance()} is a static method of a specific class. They return the + * same thing. */ MessageLite getDefaultInstanceForType(); /** - * Returns true if all required fields in the message and all embedded - * messages are set, false otherwise. + * Returns true if all required fields in the message and all embedded messages are set, false + * otherwise. * *

See also: {@link MessageOrBuilder#getInitializationErrorString()} */ boolean isInitialized(); - } diff --git a/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java b/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java index 23373ef4cdc77..4aea9528ac017 100644 --- a/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java +++ b/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java @@ -31,6 +31,7 @@ package com.google.protobuf; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -38,20 +39,18 @@ import java.util.Set; import java.util.TreeSet; -/** - * Helps generate {@link String} representations of {@link MessageLite} protos. - */ -// TODO(dweis): Fix map fields. +/** Helps generate {@link String} representations of {@link MessageLite} protos. */ final class MessageLiteToString { private static final String LIST_SUFFIX = "List"; private static final String BUILDER_LIST_SUFFIX = "OrBuilderList"; + private static final String MAP_SUFFIX = "Map"; private static final String BYTES_SUFFIX = "Bytes"; - + /** - * Returns a {@link String} representation of the {@link MessageLite} object. The first line of + * Returns a {@link String} representation of the {@link MessageLite} object. The first line of * the {@code String} representation representation includes a comment string to uniquely identify - * the objcet instance. This acts as an indicator that this should not be relied on for + * the object instance. This acts as an indicator that this should not be relied on for * comparisons. * *

For use by generated code only. @@ -71,8 +70,9 @@ static String toString(MessageLite messageLite, String commentString) { */ private static void reflectivePrintWithIndent( MessageLite messageLite, StringBuilder buffer, int indent) { - // Build a map of method name to method. We're looking for methods like getFoo(), hasFoo(), and - // getFooList() which might be useful for building an object's string representation. + // Build a map of method name to method. We're looking for methods like getFoo(), hasFoo(), + // getFooList() and getFooMap() which might be useful for building an object's string + // representation. Map nameToNoArgMethod = new HashMap(); Map nameToMethod = new HashMap(); Set getters = new TreeSet(); @@ -88,13 +88,17 @@ private static void reflectivePrintWithIndent( } for (String getter : getters) { - String suffix = getter.replaceFirst("get", ""); - if (suffix.endsWith(LIST_SUFFIX) && !suffix.endsWith(BUILDER_LIST_SUFFIX)) { - String camelCase = suffix.substring(0, 1).toLowerCase() - + suffix.substring(1, suffix.length() - LIST_SUFFIX.length()); + String suffix = getter.startsWith("get") ? getter.substring(3) : getter; + if (suffix.endsWith(LIST_SUFFIX) + && !suffix.endsWith(BUILDER_LIST_SUFFIX) + // Sometimes people have fields named 'list' that aren't repeated. + && !suffix.equals(LIST_SUFFIX)) { + String camelCase = + suffix.substring(0, 1).toLowerCase() + + suffix.substring(1, suffix.length() - LIST_SUFFIX.length()); // Try to reflectively get the value and toString() the field as if it were repeated. This - // only works if the method names have not be proguarded out or renamed. - Method listMethod = nameToNoArgMethod.get("get" + suffix); + // only works if the method names have not been proguarded out or renamed. + Method listMethod = nameToNoArgMethod.get(getter); if (listMethod != null && listMethod.getReturnType().equals(List.class)) { printField( buffer, @@ -104,6 +108,30 @@ private static void reflectivePrintWithIndent( continue; } } + if (suffix.endsWith(MAP_SUFFIX) + // Sometimes people have fields named 'map' that aren't maps. + && !suffix.equals(MAP_SUFFIX)) { + String camelCase = + suffix.substring(0, 1).toLowerCase() + + suffix.substring(1, suffix.length() - MAP_SUFFIX.length()); + // Try to reflectively get the value and toString() the field as if it were a map. This only + // works if the method names have not been proguarded out or renamed. + Method mapMethod = nameToNoArgMethod.get(getter); + if (mapMethod != null + && mapMethod.getReturnType().equals(Map.class) + // Skip the deprecated getter method with no prefix "Map" when the field name ends with + // "map". + && !mapMethod.isAnnotationPresent(Deprecated.class) + // Skip the internal mutable getter method. + && Modifier.isPublic(mapMethod.getModifiers())) { + printField( + buffer, + indent, + camelCaseToSnakeCase(camelCase), + GeneratedMessageLite.invokeOrDie(mapMethod, messageLite)); + continue; + } + } Method setter = nameToMethod.get("set" + suffix); if (setter == null) { @@ -119,22 +147,19 @@ private static void reflectivePrintWithIndent( String camelCase = suffix.substring(0, 1).toLowerCase() + suffix.substring(1); // Try to reflectively get the value and toString() the field as if it were optional. This - // only works if the method names have not be proguarded out or renamed. + // only works if the method names have not been proguarded out or renamed. Method getMethod = nameToNoArgMethod.get("get" + suffix); Method hasMethod = nameToNoArgMethod.get("has" + suffix); // TODO(dweis): Fix proto3 semantics. if (getMethod != null) { Object value = GeneratedMessageLite.invokeOrDie(getMethod, messageLite); - final boolean hasValue = hasMethod == null - ? !isDefaultValue(value) - : (Boolean) GeneratedMessageLite.invokeOrDie(hasMethod, messageLite); - // TODO(dweis): This doesn't stop printing oneof case twice: value and enum style. + final boolean hasValue = + hasMethod == null + ? !isDefaultValue(value) + : (Boolean) GeneratedMessageLite.invokeOrDie(hasMethod, messageLite); + // TODO(dweis): This doesn't stop printing oneof case twice: value and enum style. if (hasValue) { - printField( - buffer, - indent, - camelCaseToSnakeCase(camelCase), - value); + printField(buffer, indent, camelCaseToSnakeCase(camelCase), value); } continue; } @@ -153,7 +178,7 @@ private static void reflectivePrintWithIndent( ((GeneratedMessageLite) messageLite).unknownFields.printWithIndent(buffer, indent); } } - + private static boolean isDefaultValue(Object o) { if (o instanceof Boolean) { return !((Boolean) o); @@ -179,7 +204,7 @@ private static boolean isDefaultValue(Object o) { if (o instanceof java.lang.Enum) { // Catches oneof enums. return ((java.lang.Enum) o).ordinal() == 0; } - + return false; } @@ -201,6 +226,13 @@ static final void printField(StringBuilder buffer, int indent, String name, Obje } return; } + if (object instanceof Map) { + Map map = (Map) object; + for (Map.Entry entry : map.entrySet()) { + printField(buffer, indent, name, entry); + } + return; + } buffer.append('\n'); for (int i = 0; i < indent; i++) { @@ -220,11 +252,21 @@ static final void printField(StringBuilder buffer, int indent, String name, Obje buffer.append(' '); } buffer.append("}"); + } else if (object instanceof Map.Entry) { + buffer.append(" {"); + Map.Entry entry = (Map.Entry) object; + printField(buffer, indent + 2, "key", entry.getKey()); + printField(buffer, indent + 2, "value", entry.getValue()); + buffer.append("\n"); + for (int i = 0; i < indent; i++) { + buffer.append(' '); + } + buffer.append("}"); } else { buffer.append(": ").append(object.toString()); } } - + private static final String camelCaseToSnakeCase(String camelCase) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < camelCase.length(); i++) { diff --git a/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java b/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java index 5e7d78213254a..0254df99ac9aa 100644 --- a/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java +++ b/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java @@ -34,8 +34,8 @@ import java.util.Map; /** - * Base interface for methods common to {@link Message} and - * {@link Message.Builder} to provide type equivalency. + * Base interface for methods common to {@link Message} and {@link Message.Builder} to provide type + * equivalency. * * @author jonp@google.com (Jon Perlow) */ @@ -46,95 +46,85 @@ public interface MessageOrBuilder extends MessageLiteOrBuilder { Message getDefaultInstanceForType(); /** - * Returns a list of field paths (e.g. "foo.bar.baz") of required fields - * which are not set in this message. You should call - * {@link MessageLiteOrBuilder#isInitialized()} first to check if there - * are any missing fields, as that method is likely to be much faster - * than this one even when the message is fully-initialized. + * Returns a list of field paths (e.g. "foo.bar.baz") of required fields which are not set in this + * message. You should call {@link MessageLiteOrBuilder#isInitialized()} first to check if there + * are any missing fields, as that method is likely to be much faster than this one even when the + * message is fully-initialized. */ List findInitializationErrors(); /** - * Returns a comma-delimited list of required fields which are not set - * in this message object. You should call - * {@link MessageLiteOrBuilder#isInitialized()} first to check if there - * are any missing fields, as that method is likely to be much faster - * than this one even when the message is fully-initialized. + * Returns a comma-delimited list of required fields which are not set in this message object. You + * should call {@link MessageLiteOrBuilder#isInitialized()} first to check if there are any + * missing fields, as that method is likely to be much faster than this one even when the message + * is fully-initialized. */ String getInitializationErrorString(); /** - * Get the message's type's descriptor. This differs from the - * {@code getDescriptor()} method of generated message classes in that - * this method is an abstract method of the {@code Message} interface - * whereas {@code getDescriptor()} is a static method of a specific class. - * They return the same thing. + * Get the message's type's descriptor. This differs from the {@code getDescriptor()} method of + * generated message classes in that this method is an abstract method of the {@code Message} + * interface whereas {@code getDescriptor()} is a static method of a specific class. They return + * the same thing. */ Descriptors.Descriptor getDescriptorForType(); /** - * Returns a collection of all the fields in this message which are set - * and their corresponding values. A singular ("required" or "optional") - * field is set iff hasField() returns true for that field. A "repeated" - * field is set iff getRepeatedFieldCount() is greater than zero. The - * values are exactly what would be returned by calling - * {@link #getField(Descriptors.FieldDescriptor)} for each field. The map - * is guaranteed to be a sorted map, so iterating over it will return fields - * in order by field number. - *
- * If this is for a builder, the returned map may or may not reflect future - * changes to the builder. Either way, the returned map is itself - * unmodifiable. + * Returns a collection of all the fields in this message which are set and their corresponding + * values. A singular ("required" or "optional") field is set iff hasField() returns true for that + * field. A "repeated" field is set iff getRepeatedFieldCount() is greater than zero. The values + * are exactly what would be returned by calling {@link #getField(Descriptors.FieldDescriptor)} + * for each field. The map is guaranteed to be a sorted map, so iterating over it will return + * fields in order by field number.
+ * If this is for a builder, the returned map may or may not reflect future changes to the + * builder. Either way, the returned map is itself unmodifiable. */ Map getAllFields(); /** * Returns true if the given oneof is set. - * @throws IllegalArgumentException if - * {@code oneof.getContainingType() != getDescriptorForType()}. + * + * @throws IllegalArgumentException if {@code oneof.getContainingType() != + * getDescriptorForType()}. */ boolean hasOneof(Descriptors.OneofDescriptor oneof); - /** - * Obtains the FieldDescriptor if the given oneof is set. Returns null - * if no field is set. - */ - Descriptors.FieldDescriptor getOneofFieldDescriptor( - Descriptors.OneofDescriptor oneof); + /** Obtains the FieldDescriptor if the given oneof is set. Returns null if no field is set. */ + Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof); /** - * Returns true if the given field is set. This is exactly equivalent to - * calling the generated "has" accessor method corresponding to the field. - * @throws IllegalArgumentException The field is a repeated field, or - * {@code field.getContainingType() != getDescriptorForType()}. + * Returns true if the given field is set. This is exactly equivalent to calling the generated + * "has" accessor method corresponding to the field. + * + * @throws IllegalArgumentException The field is a repeated field, or {@code + * field.getContainingType() != getDescriptorForType()}. */ boolean hasField(Descriptors.FieldDescriptor field); /** - * Obtains the value of the given field, or the default value if it is - * not set. For primitive fields, the boxed primitive value is returned. - * For enum fields, the EnumValueDescriptor for the value is returned. For - * embedded message fields, the sub-message is returned. For repeated + * Obtains the value of the given field, or the default value if it is not set. For primitive + * fields, the boxed primitive value is returned. For enum fields, the EnumValueDescriptor for the + * value is returned. For embedded message fields, the sub-message is returned. For repeated * fields, a java.util.List is returned. */ Object getField(Descriptors.FieldDescriptor field); /** - * Gets the number of elements of a repeated field. This is exactly - * equivalent to calling the generated "Count" accessor method corresponding - * to the field. - * @throws IllegalArgumentException The field is not a repeated field, or - * {@code field.getContainingType() != getDescriptorForType()}. + * Gets the number of elements of a repeated field. This is exactly equivalent to calling the + * generated "Count" accessor method corresponding to the field. + * + * @throws IllegalArgumentException The field is not a repeated field, or {@code + * field.getContainingType() != getDescriptorForType()}. */ int getRepeatedFieldCount(Descriptors.FieldDescriptor field); /** - * Gets an element of a repeated field. For primitive fields, the boxed - * primitive value is returned. For enum fields, the EnumValueDescriptor - * for the value is returned. For embedded message fields, the sub-message - * is returned. - * @throws IllegalArgumentException The field is not a repeated field, or - * {@code field.getContainingType() != getDescriptorForType()}. + * Gets an element of a repeated field. For primitive fields, the boxed primitive value is + * returned. For enum fields, the EnumValueDescriptor for the value is returned. For embedded + * message fields, the sub-message is returned. + * + * @throws IllegalArgumentException The field is not a repeated field, or {@code + * field.getContainingType() != getDescriptorForType()}. */ Object getRepeatedField(Descriptors.FieldDescriptor field, int index); diff --git a/java/core/src/main/java/com/google/protobuf/MessageReflection.java b/java/core/src/main/java/com/google/protobuf/MessageReflection.java index 69ad7ddf94112..6741e1cb9cdf1 100644 --- a/java/core/src/main/java/com/google/protobuf/MessageReflection.java +++ b/java/core/src/main/java/com/google/protobuf/MessageReflection.java @@ -54,20 +54,19 @@ static void writeMessageTo( message.getDescriptorForType().getOptions().getMessageSetWireFormat(); if (alwaysWriteRequiredFields) { fields = new TreeMap(fields); - for (final FieldDescriptor field : - message.getDescriptorForType().getFields()) { + for (final FieldDescriptor field : message.getDescriptorForType().getFields()) { if (field.isRequired() && !fields.containsKey(field)) { fields.put(field, message.getField(field)); } } } - for (final Map.Entry entry : - fields.entrySet()) { + for (final Map.Entry entry : fields.entrySet()) { final Descriptors.FieldDescriptor field = entry.getKey(); final Object value = entry.getValue(); - if (isMessageSet && field.isExtension() && - field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE && - !field.isRepeated()) { + if (isMessageSet + && field.isExtension() + && field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE + && !field.isRepeated()) { output.writeMessageSetExtension(field.getNumber(), (Message) value); } else { FieldSet.writeField(field, value, output); @@ -82,22 +81,20 @@ static void writeMessageTo( } } - static int getSerializedSize( - Message message, - Map fields) { + static int getSerializedSize(Message message, Map fields) { int size = 0; final boolean isMessageSet = message.getDescriptorForType().getOptions().getMessageSetWireFormat(); - for (final Map.Entry entry : - fields.entrySet()) { + for (final Map.Entry entry : fields.entrySet()) { final Descriptors.FieldDescriptor field = entry.getKey(); final Object value = entry.getValue(); - if (isMessageSet && field.isExtension() && - field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE && - !field.isRepeated()) { - size += CodedOutputStream.computeMessageSetExtensionSize( - field.getNumber(), (Message) value); + if (isMessageSet + && field.isExtension() + && field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE + && !field.isRepeated()) { + size += + CodedOutputStream.computeMessageSetExtensionSize(field.getNumber(), (Message) value); } else { size += FieldSet.computeFieldSize(field, value); } @@ -126,9 +123,7 @@ static String delimitWithCommas(List parts) { @SuppressWarnings("unchecked") static boolean isInitialized(MessageOrBuilder message) { // Check that all required fields are present. - for (final Descriptors.FieldDescriptor field : message - .getDescriptorForType() - .getFields()) { + for (final Descriptors.FieldDescriptor field : message.getDescriptorForType().getFields()) { if (field.isRequired()) { if (!message.hasField(field)) { return false; @@ -142,8 +137,7 @@ static boolean isInitialized(MessageOrBuilder message) { final Descriptors.FieldDescriptor field = entry.getKey(); if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) { if (field.isRepeated()) { - for (final Message element - : (List) entry.getValue()) { + for (final Message element : (List) entry.getValue()) { if (!element.isInitialized()) { return false; } @@ -159,31 +153,24 @@ static boolean isInitialized(MessageOrBuilder message) { return true; } - private static String subMessagePrefix(final String prefix, - final Descriptors.FieldDescriptor field, - final int index) { + private static String subMessagePrefix( + final String prefix, final Descriptors.FieldDescriptor field, final int index) { final StringBuilder result = new StringBuilder(prefix); if (field.isExtension()) { - result.append('(') - .append(field.getFullName()) - .append(')'); + result.append('(').append(field.getFullName()).append(')'); } else { result.append(field.getName()); } if (index != -1) { - result.append('[') - .append(index) - .append(']'); + result.append('[').append(index).append(']'); } result.append('.'); return result.toString(); } - private static void findMissingFields(final MessageOrBuilder message, - final String prefix, - final List results) { - for (final Descriptors.FieldDescriptor field : - message.getDescriptorForType().getFields()) { + private static void findMissingFields( + final MessageOrBuilder message, final String prefix, final List results) { + for (final Descriptors.FieldDescriptor field : message.getDescriptorForType().getFields()) { if (field.isRequired() && !message.hasField(field)) { results.add(prefix + field.getName()); } @@ -198,15 +185,13 @@ private static void findMissingFields(final MessageOrBuilder message, if (field.isRepeated()) { int i = 0; for (final Object element : (List) value) { - findMissingFields((MessageOrBuilder) element, - subMessagePrefix(prefix, field, i++), - results); + findMissingFields( + (MessageOrBuilder) element, subMessagePrefix(prefix, field, i++), results); } } else { if (message.hasField(field)) { - findMissingFields((MessageOrBuilder) value, - subMessagePrefix(prefix, field, -1), - results); + findMissingFields( + (MessageOrBuilder) value, subMessagePrefix(prefix, field, -1), results); } } } @@ -214,11 +199,10 @@ private static void findMissingFields(final MessageOrBuilder message, } /** - * Populates {@code this.missingFields} with the full "path" of each missing - * required field in the given message. + * Populates {@code this.missingFields} with the full "path" of each missing required field in the + * given message. */ - static List findMissingFields( - final MessageOrBuilder message) { + static List findMissingFields(final MessageOrBuilder message) { final List results = new ArrayList(); findMissingFields(message, "", results); return results; @@ -226,12 +210,11 @@ static List findMissingFields( static interface MergeTarget { enum ContainerType { - MESSAGE, EXTENSION_SET + MESSAGE, + EXTENSION_SET } - /** - * Returns the descriptor for the target. - */ + /** Returns the descriptor for the target. */ public Descriptors.Descriptor getDescriptorForType(); public ContainerType getContainerType(); @@ -240,21 +223,19 @@ public ExtensionRegistry.ExtensionInfo findExtensionByName( ExtensionRegistry registry, String name); public ExtensionRegistry.ExtensionInfo findExtensionByNumber( - ExtensionRegistry registry, Descriptors.Descriptor containingType, - int fieldNumber); + ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber); /** - * Obtains the value of the given field, or the default value if it is not - * set. For primitive fields, the boxed primitive value is returned. For - * enum fields, the EnumValueDescriptor for the value is returned. For - * embedded message fields, the sub-message is returned. For repeated + * Obtains the value of the given field, or the default value if it is not set. For primitive + * fields, the boxed primitive value is returned. For enum fields, the EnumValueDescriptor for + * the value is returned. For embedded message fields, the sub-message is returned. For repeated * fields, a java.util.List is returned. */ public Object getField(Descriptors.FieldDescriptor field); /** - * Returns true if the given field is set. This is exactly equivalent to - * calling the generated "has" accessor method corresponding to the field. + * Returns true if the given field is set. This is exactly equivalent to calling the generated + * "has" accessor method corresponding to the field. * * @throws IllegalArgumentException The field is a repeated field, or {@code * field.getContainingType() != getDescriptorForType()}. @@ -262,106 +243,106 @@ public ExtensionRegistry.ExtensionInfo findExtensionByNumber( boolean hasField(Descriptors.FieldDescriptor field); /** - * Sets a field to the given value. The value must be of the correct type - * for this field, i.e. the same type that - * {@link Message#getField(Descriptors.FieldDescriptor)} - * would return. + * Sets a field to the given value. The value must be of the correct type for this field, i.e. + * the same type that {@link Message#getField(Descriptors.FieldDescriptor)} would return. */ MergeTarget setField(Descriptors.FieldDescriptor field, Object value); /** - * Clears the field. This is exactly equivalent to calling the generated - * "clear" accessor method corresponding to the field. + * Clears the field. This is exactly equivalent to calling the generated "clear" accessor method + * corresponding to the field. */ MergeTarget clearField(Descriptors.FieldDescriptor field); /** - * Sets an element of a repeated field to the given value. The value must - * be of the correct type for this field, i.e. the same type that {@link + * Sets an element of a repeated field to the given value. The value must be of the correct type + * for this field, i.e. the same type that {@link * Message#getRepeatedField(Descriptors.FieldDescriptor, int)} would return. * - * @throws IllegalArgumentException The field is not a repeated field, or - * {@code field.getContainingType() != - * getDescriptorForType()}. + * @throws IllegalArgumentException The field is not a repeated field, or {@code + * field.getContainingType() != getDescriptorForType()}. */ - MergeTarget setRepeatedField(Descriptors.FieldDescriptor field, - int index, Object value); + MergeTarget setRepeatedField(Descriptors.FieldDescriptor field, int index, Object value); /** * Like {@code setRepeatedField}, but appends the value as a new element. * - * @throws IllegalArgumentException The field is not a repeated field, or - * {@code field.getContainingType() != - * getDescriptorForType()}. + * @throws IllegalArgumentException The field is not a repeated field, or {@code + * field.getContainingType() != getDescriptorForType()}. */ - MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, - Object value); + MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, Object value); /** * Returns true if the given oneof is set. * - * @throws IllegalArgumentException if - * {@code oneof.getContainingType() != getDescriptorForType()}. + * @throws IllegalArgumentException if {@code oneof.getContainingType() != + * getDescriptorForType()}. */ boolean hasOneof(Descriptors.OneofDescriptor oneof); /** - * Clears the oneof. This is exactly equivalent to calling the generated - * "clear" accessor method corresponding to the oneof. + * Clears the oneof. This is exactly equivalent to calling the generated "clear" accessor method + * corresponding to the oneof. */ MergeTarget clearOneof(Descriptors.OneofDescriptor oneof); - /** - * Obtains the FieldDescriptor if the given oneof is set. Returns null - * if no field is set. - */ + /** Obtains the FieldDescriptor if the given oneof is set. Returns null if no field is set. */ Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof); /** - * Parse the input stream into a sub field group defined based on either - * FieldDescriptor or the default instance. + * Parse the input stream into a sub field group defined based on either FieldDescriptor or the + * default instance. */ - Object parseGroup(CodedInputStream input, ExtensionRegistryLite registry, - Descriptors.FieldDescriptor descriptor, Message defaultInstance) + Object parseGroup( + CodedInputStream input, + ExtensionRegistryLite registry, + Descriptors.FieldDescriptor descriptor, + Message defaultInstance) throws IOException; /** - * Parse the input stream into a sub field message defined based on either - * FieldDescriptor or the default instance. + * Parse the input stream into a sub field message defined based on either FieldDescriptor or + * the default instance. */ - Object parseMessage(CodedInputStream input, ExtensionRegistryLite registry, - Descriptors.FieldDescriptor descriptor, Message defaultInstance) + Object parseMessage( + CodedInputStream input, + ExtensionRegistryLite registry, + Descriptors.FieldDescriptor descriptor, + Message defaultInstance) throws IOException; /** - * Parse from a ByteString into a sub field message defined based on either - * FieldDescriptor or the default instance. There isn't a varint indicating - * the length of the message at the beginning of the input ByteString. + * Parse from a ByteString into a sub field message defined based on either FieldDescriptor or + * the default instance. There isn't a varint indicating the length of the message at the + * beginning of the input ByteString. */ Object parseMessageFromBytes( - ByteString bytes, ExtensionRegistryLite registry, - Descriptors.FieldDescriptor descriptor, Message defaultInstance) + ByteString bytes, + ExtensionRegistryLite registry, + Descriptors.FieldDescriptor descriptor, + Message defaultInstance) throws IOException; - /** - * Returns the UTF8 validation level for the field. - */ - WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor - descriptor); + /** Returns the UTF8 validation level for the field. */ + WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor); /** - * Returns a new merge target for a sub-field. When defaultInstance is - * provided, it indicates the descriptor is for an extension type, and - * implementations should create a new instance from the defaultInstance - * prototype directly. + * Returns a new merge target for a sub-field. When defaultInstance is provided, it indicates + * the descriptor is for an extension type, and implementations should create a new instance + * from the defaultInstance prototype directly. */ MergeTarget newMergeTargetForField( - Descriptors.FieldDescriptor descriptor, - Message defaultInstance); + Descriptors.FieldDescriptor descriptor, Message defaultInstance); /** - * Finishes the merge and returns the underlying object. + * Returns an empty merge target for a sub-field. When defaultInstance is provided, it indicates + * the descriptor is for an extension type, and implementations should create a new instance + * from the defaultInstance prototype directly. */ + MergeTarget newEmptyTargetForField( + Descriptors.FieldDescriptor descriptor, Message defaultInstance); + + /** Finishes the merge and returns the underlying object. */ Object finish(); } @@ -443,8 +424,7 @@ public ExtensionRegistry.ExtensionInfo findExtensionByName( @Override public ExtensionRegistry.ExtensionInfo findExtensionByNumber( ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) { - return registry.findImmutableExtensionByNumber(containingType, - fieldNumber); + return registry.findImmutableExtensionByNumber(containingType, fieldNumber); } @Override @@ -522,12 +502,31 @@ public Object parseMessageFromBytes( @Override public MergeTarget newMergeTargetForField( Descriptors.FieldDescriptor field, Message defaultInstance) { + Message.Builder subBuilder; + if (defaultInstance != null) { + subBuilder = defaultInstance.newBuilderForType(); + } else { + subBuilder = builder.newBuilderForField(field); + } + if (!field.isRepeated()) { + Message originalMessage = (Message) getField(field); + if (originalMessage != null) { + subBuilder.mergeFrom(originalMessage); + } + } + return new BuilderAdapter(subBuilder); + } + + @Override + public MergeTarget newEmptyTargetForField( + Descriptors.FieldDescriptor field, Message defaultInstance) { + Message.Builder subBuilder; if (defaultInstance != null) { - return new BuilderAdapter( - defaultInstance.newBuilderForType()); + subBuilder = defaultInstance.newBuilderForType(); } else { - return new BuilderAdapter(builder.newBuilderForField(field)); + subBuilder = builder.newBuilderForField(field); } + return new BuilderAdapter(subBuilder); } @Override @@ -536,8 +535,7 @@ public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor d return WireFormat.Utf8Validation.STRICT; } // TODO(liujisi): support lazy strings for repeated fields. - if (!descriptor.isRepeated() - && builder instanceof GeneratedMessage.Builder) { + if (!descriptor.isRepeated() && builder instanceof GeneratedMessage.Builder) { return WireFormat.Utf8Validation.LAZY; } return WireFormat.Utf8Validation.LOOSE; @@ -560,8 +558,7 @@ static class ExtensionAdapter implements MergeTarget { @Override public Descriptors.Descriptor getDescriptorForType() { - throw new UnsupportedOperationException( - "getDescriptorForType() called on FieldSet object"); + throw new UnsupportedOperationException("getDescriptorForType() called on FieldSet object"); } @Override @@ -629,8 +626,7 @@ public ExtensionRegistry.ExtensionInfo findExtensionByName( @Override public ExtensionRegistry.ExtensionInfo findExtensionByNumber( ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) { - return registry.findImmutableExtensionByNumber(containingType, - fieldNumber); + return registry.findImmutableExtensionByNumber(containingType, fieldNumber); } @Override @@ -640,8 +636,7 @@ public Object parseGroup( Descriptors.FieldDescriptor field, Message defaultInstance) throws IOException { - Message.Builder subBuilder = - defaultInstance.newBuilderForType(); + Message.Builder subBuilder = defaultInstance.newBuilderForType(); if (!field.isRepeated()) { Message originalMessage = (Message) getField(field); if (originalMessage != null) { @@ -659,8 +654,7 @@ public Object parseMessage( Descriptors.FieldDescriptor field, Message defaultInstance) throws IOException { - Message.Builder subBuilder = - defaultInstance.newBuilderForType(); + Message.Builder subBuilder = defaultInstance.newBuilderForType(); if (!field.isRepeated()) { Message originalMessage = (Message) getField(field); if (originalMessage != null) { @@ -678,7 +672,7 @@ public Object parseMessageFromBytes( Descriptors.FieldDescriptor field, Message defaultInstance) throws IOException { - Message.Builder subBuilder = defaultInstance.newBuilderForType(); + Message.Builder subBuilder = defaultInstance.newBuilderForType(); if (!field.isRepeated()) { Message originalMessage = (Message) getField(field); if (originalMessage != null) { @@ -692,8 +686,13 @@ public Object parseMessageFromBytes( @Override public MergeTarget newMergeTargetForField( Descriptors.FieldDescriptor descriptor, Message defaultInstance) { - throw new UnsupportedOperationException( - "newMergeTargetForField() called on FieldSet object"); + throw new UnsupportedOperationException("newMergeTargetForField() called on FieldSet object"); + } + + @Override + public MergeTarget newEmptyTargetForField( + Descriptors.FieldDescriptor descriptor, Message defaultInstance) { + throw new UnsupportedOperationException("newEmptyTargetForField() called on FieldSet object"); } @Override @@ -707,8 +706,7 @@ public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor d @Override public Object finish() { - throw new UnsupportedOperationException( - "finish() called on FieldSet object"); + throw new UnsupportedOperationException("finish() called on FieldSet object"); } } @@ -731,8 +729,7 @@ static boolean mergeFieldFrom( MergeTarget target, int tag) throws IOException { - if (type.getOptions().getMessageSetWireFormat() && - tag == WireFormat.MESSAGE_SET_ITEM_TAG) { + if (type.getOptions().getMessageSetWireFormat() && tag == WireFormat.MESSAGE_SET_ITEM_TAG) { mergeMessageSetExtensionFromCodedStream( input, unknownFields, extensionRegistry, type, target); return true; @@ -752,19 +749,16 @@ static boolean mergeFieldFrom( // were empty. if (extensionRegistry instanceof ExtensionRegistry) { final ExtensionRegistry.ExtensionInfo extension = - target.findExtensionByNumber((ExtensionRegistry) extensionRegistry, - type, fieldNumber); + target.findExtensionByNumber((ExtensionRegistry) extensionRegistry, type, fieldNumber); if (extension == null) { field = null; } else { field = extension.descriptor; defaultInstance = extension.defaultInstance; - if (defaultInstance == null && - field.getJavaType() - == Descriptors.FieldDescriptor.JavaType.MESSAGE) { + if (defaultInstance == null + && field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) { throw new IllegalStateException( - "Message-typed extension lacked default instance: " + - field.getFullName()); + "Message-typed extension lacked default instance: " + field.getFullName()); } } } else { @@ -779,21 +773,19 @@ static boolean mergeFieldFrom( boolean unknown = false; boolean packed = false; if (field == null) { - unknown = true; // Unknown field. - } else if (wireType == FieldSet.getWireFormatForFieldType( - field.getLiteType(), - false /* isPacked */)) { + unknown = true; // Unknown field. + } else if (wireType + == FieldSet.getWireFormatForFieldType(field.getLiteType(), /* isPacked= */ false)) { packed = false; - } else if (field.isPackable() && - wireType == FieldSet.getWireFormatForFieldType( - field.getLiteType(), - true /* isPacked */)) { + } else if (field.isPackable() + && wireType + == FieldSet.getWireFormatForFieldType(field.getLiteType(), /* isPacked= */ true)) { packed = true; } else { - unknown = true; // Unknown wire type. + unknown = true; // Unknown wire type. } - if (unknown) { // Unknown field or wrong wire type. Skip. + if (unknown) { // Unknown field or wrong wire type. Skip. if (unknownFields != null) { return unknownFields.mergeFieldFrom(tag, input); } else { @@ -808,22 +800,26 @@ static boolean mergeFieldFrom( while (input.getBytesUntilLimit() > 0) { final int rawValue = input.readEnum(); if (field.getFile().supportsUnknownEnumValue()) { - target.addRepeatedField(field, - field.getEnumType().findValueByNumberCreatingIfUnknown(rawValue)); + target.addRepeatedField( + field, field.getEnumType().findValueByNumberCreatingIfUnknown(rawValue)); } else { final Object value = field.getEnumType().findValueByNumber(rawValue); + // If the number isn't recognized as a valid value for this enum, + // add it to the unknown fields. if (value == null) { - // If the number isn't recognized as a valid value for this - // enum, drop it (don't even add it to unknownFields). - return true; + if (unknownFields != null) { + unknownFields.mergeVarintField(fieldNumber, rawValue); + } + } else { + target.addRepeatedField(field, value); } - target.addRepeatedField(field, value); } } } else { while (input.getBytesUntilLimit() > 0) { - final Object value = WireFormat.readPrimitiveField( - input, field.getLiteType(), target.getUtf8Validation(field)); + final Object value = + WireFormat.readPrimitiveField( + input, field.getLiteType(), target.getUtf8Validation(field)); target.addRepeatedField(field, value); } } @@ -831,16 +827,16 @@ static boolean mergeFieldFrom( } else { final Object value; switch (field.getType()) { - case GROUP: { - value = target - .parseGroup(input, extensionRegistry, field, defaultInstance); - break; - } - case MESSAGE: { - value = target - .parseMessage(input, extensionRegistry, field, defaultInstance); - break; - } + case GROUP: + { + value = target.parseGroup(input, extensionRegistry, field, defaultInstance); + break; + } + case MESSAGE: + { + value = target.parseMessage(input, extensionRegistry, field, defaultInstance); + break; + } case ENUM: final int rawValue = input.readEnum(); if (field.getFile().supportsUnknownEnumValue()) { @@ -848,7 +844,7 @@ static boolean mergeFieldFrom( } else { value = field.getEnumType().findValueByNumber(rawValue); // If the number isn't recognized as a valid value for this enum, - // drop it. + // add it to the unknown fields. if (value == null) { if (unknownFields != null) { unknownFields.mergeVarintField(fieldNumber, rawValue); @@ -858,8 +854,9 @@ static boolean mergeFieldFrom( } break; default: - value = WireFormat.readPrimitiveField( - input, field.getLiteType(), target.getUtf8Validation(field)); + value = + WireFormat.readPrimitiveField( + input, field.getLiteType(), target.getUtf8Validation(field)); break; } @@ -873,16 +870,14 @@ static boolean mergeFieldFrom( return true; } - /** - * Called by {@code #mergeFieldFrom()} to parse a MessageSet extension into - * MergeTarget. - */ + /** Called by {@code #mergeFieldFrom()} to parse a MessageSet extension into MergeTarget. */ private static void mergeMessageSetExtensionFromCodedStream( CodedInputStream input, UnknownFieldSet.Builder unknownFields, ExtensionRegistryLite extensionRegistry, Descriptors.Descriptor type, - MergeTarget target) throws IOException { + MergeTarget target) + throws IOException { // The wire format for MessageSet is: // message MessageSet { @@ -921,19 +916,17 @@ private static void mergeMessageSetExtensionFromCodedStream( // extensions of it. Otherwise we will treat the registry as if it // were empty. if (extensionRegistry instanceof ExtensionRegistry) { - extension = target.findExtensionByNumber( - (ExtensionRegistry) extensionRegistry, type, typeId); + extension = + target.findExtensionByNumber((ExtensionRegistry) extensionRegistry, type, typeId); } } } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) { if (typeId != 0) { - if (extension != null && - ExtensionRegistryLite.isEagerlyParseMessageSets()) { + if (extension != null && ExtensionRegistryLite.isEagerlyParseMessageSets()) { // We already know the type, so we can parse directly from the // input with no copying. Hooray! - eagerlyMergeMessageSetExtension( - input, extension, extensionRegistry, target); + eagerlyMergeMessageSetExtension(input, extension, extensionRegistry, target); rawBytes = null; continue; } @@ -952,12 +945,11 @@ private static void mergeMessageSetExtensionFromCodedStream( // Process the raw bytes. if (rawBytes != null && typeId != 0) { // Zero is not a valid type ID. if (extension != null) { // We known the type - mergeMessageSetExtensionFromBytes( - rawBytes, extension, extensionRegistry, target); + mergeMessageSetExtensionFromBytes(rawBytes, extension, extensionRegistry, target); } else { // We don't know how to parse this. Ignore it. if (rawBytes != null && unknownFields != null) { - unknownFields.mergeField(typeId, UnknownFieldSet.Field.newBuilder() - .addLengthDelimited(rawBytes).build()); + unknownFields.mergeField( + typeId, UnknownFieldSet.Field.newBuilder().addLengthDelimited(rawBytes).build()); } } } @@ -967,20 +959,21 @@ private static void mergeMessageSetExtensionFromBytes( ByteString rawBytes, ExtensionRegistry.ExtensionInfo extension, ExtensionRegistryLite extensionRegistry, - MergeTarget target) throws IOException { + MergeTarget target) + throws IOException { Descriptors.FieldDescriptor field = extension.descriptor; boolean hasOriginalValue = target.hasField(field); if (hasOriginalValue || ExtensionRegistryLite.isEagerlyParseMessageSets()) { // If the field already exists, we just parse the field. - Object value = target.parseMessageFromBytes( - rawBytes, extensionRegistry,field, extension.defaultInstance); + Object value = + target.parseMessageFromBytes( + rawBytes, extensionRegistry, field, extension.defaultInstance); target.setField(field, value); } else { // Use LazyField to load MessageSet lazily. - LazyField lazyField = new LazyField( - extension.defaultInstance, extensionRegistry, rawBytes); + LazyField lazyField = new LazyField(extension.defaultInstance, extensionRegistry, rawBytes); target.setField(field, lazyField); } } @@ -989,10 +982,10 @@ private static void eagerlyMergeMessageSetExtension( CodedInputStream input, ExtensionRegistry.ExtensionInfo extension, ExtensionRegistryLite extensionRegistry, - MergeTarget target) throws IOException { + MergeTarget target) + throws IOException { Descriptors.FieldDescriptor field = extension.descriptor; - Object value = target.parseMessage(input, extensionRegistry, field, - extension.defaultInstance); + Object value = target.parseMessage(input, extensionRegistry, field, extension.defaultInstance); target.setField(field, value); } } diff --git a/java/core/src/main/java/com/google/protobuf/MessageSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSchema.java new file mode 100644 index 0000000000000..33c8e914b24e1 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/MessageSchema.java @@ -0,0 +1,5930 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.ArrayDecoders.decodeBoolList; +import static com.google.protobuf.ArrayDecoders.decodeBytes; +import static com.google.protobuf.ArrayDecoders.decodeBytesList; +import static com.google.protobuf.ArrayDecoders.decodeDouble; +import static com.google.protobuf.ArrayDecoders.decodeDoubleList; +import static com.google.protobuf.ArrayDecoders.decodeExtensionOrUnknownField; +import static com.google.protobuf.ArrayDecoders.decodeFixed32; +import static com.google.protobuf.ArrayDecoders.decodeFixed32List; +import static com.google.protobuf.ArrayDecoders.decodeFixed64; +import static com.google.protobuf.ArrayDecoders.decodeFixed64List; +import static com.google.protobuf.ArrayDecoders.decodeFloat; +import static com.google.protobuf.ArrayDecoders.decodeFloatList; +import static com.google.protobuf.ArrayDecoders.decodeGroupField; +import static com.google.protobuf.ArrayDecoders.decodeGroupList; +import static com.google.protobuf.ArrayDecoders.decodeMessageField; +import static com.google.protobuf.ArrayDecoders.decodeMessageList; +import static com.google.protobuf.ArrayDecoders.decodePackedBoolList; +import static com.google.protobuf.ArrayDecoders.decodePackedDoubleList; +import static com.google.protobuf.ArrayDecoders.decodePackedFixed32List; +import static com.google.protobuf.ArrayDecoders.decodePackedFixed64List; +import static com.google.protobuf.ArrayDecoders.decodePackedFloatList; +import static com.google.protobuf.ArrayDecoders.decodePackedSInt32List; +import static com.google.protobuf.ArrayDecoders.decodePackedSInt64List; +import static com.google.protobuf.ArrayDecoders.decodePackedVarint32List; +import static com.google.protobuf.ArrayDecoders.decodePackedVarint64List; +import static com.google.protobuf.ArrayDecoders.decodeSInt32List; +import static com.google.protobuf.ArrayDecoders.decodeSInt64List; +import static com.google.protobuf.ArrayDecoders.decodeString; +import static com.google.protobuf.ArrayDecoders.decodeStringList; +import static com.google.protobuf.ArrayDecoders.decodeStringListRequireUtf8; +import static com.google.protobuf.ArrayDecoders.decodeStringRequireUtf8; +import static com.google.protobuf.ArrayDecoders.decodeUnknownField; +import static com.google.protobuf.ArrayDecoders.decodeVarint32; +import static com.google.protobuf.ArrayDecoders.decodeVarint32List; +import static com.google.protobuf.ArrayDecoders.decodeVarint64; +import static com.google.protobuf.ArrayDecoders.decodeVarint64List; +import static com.google.protobuf.ArrayDecoders.skipField; + +import com.google.protobuf.ArrayDecoders.Registers; +import com.google.protobuf.ByteString.CodedBuilder; +import com.google.protobuf.FieldSet.FieldDescriptorLite; +import com.google.protobuf.Internal.EnumVerifier; +import com.google.protobuf.Internal.ProtobufList; +import com.google.protobuf.MapEntryLite.Metadata; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** Schema used for standard messages. */ +final class MessageSchema implements Schema { + private static final int INTS_PER_FIELD = 3; + private static final int OFFSET_BITS = 20; + private static final int OFFSET_MASK = 0XFFFFF; + private static final int FIELD_TYPE_MASK = 0x0FF00000; + private static final int REQUIRED_MASK = 0x10000000; + private static final int ENFORCE_UTF8_MASK = 0x20000000; + private static final int NO_PRESENCE_SENTINEL = -1 & OFFSET_MASK; + private static final int[] EMPTY_INT_ARRAY = new int[0]; + + /** An offset applied to the field type ID for scalar fields that are a member of a oneof. */ + static final int ONEOF_TYPE_OFFSET = 51 /* FieldType.MAP + 1 */; + + /** + * Keep a direct reference to the unsafe object so we don't need to go through the UnsafeUtil + * wrapper for every call. + */ + private static final sun.misc.Unsafe UNSAFE = UnsafeUtil.getUnsafe(); + + /** + * Holds all information for accessing the message fields. The layout is as follows (field + * positions are relative to the offset of the start of the field in the buffer): + * + *

+ * + *

+   * [ 0 -    3] unused
+   * [ 4 -   31] field number
+   * [32 -   33] unused
+   * [34 -   34] whether UTF-8 enforcement should be applied to a string field.
+   * [35 -   35] whether the field is required
+   * [36 -   43] field type / for oneof: field type + {@link #ONEOF_TYPE_OFFSET}
+   * [44 -   63] field offset / oneof value field offset
+   * [64 -   69] unused
+   * [70 -   75] field presence mask shift (unused for oneof/repeated fields)
+   * [76 -   95] presence field offset / oneof case field offset / cached size field offset
+   * 
+ * + * Note that presence field offset can only use 20 bits - 1. All bits set to 1 is the sentinel + * value for non-presence. This is not validated at runtime, we simply assume message layouts + * will not exceed 1MB (assuming ~10 bytes per field, that implies 100k fields which should hit + * other javac limits first). + */ + private final int[] buffer; + + /** + * Holds object references for fields. For each field entry in {@code buffer}, there are two + * corresponding entries in this array. The content is different from different field types: + * + *
+   *   Map fields:
+   *     objects[pos] = map default entry instance
+   *     objects[pos + 1] = EnumVerifier if map value is enum, or message class reference if map
+   *                        value is message.
+   *   Message fields:
+   *     objects[pos] = null or cached message schema
+   *     objects[pos + 1] = message class reference
+   *   Enum fields:
+   *     objects[pos] = null
+   *     objects[pos + 1] = EnumVerifier
+   * 
+ */ + private final Object[] objects; + + private final int minFieldNumber; + private final int maxFieldNumber; + + private final MessageLite defaultInstance; + private final boolean hasExtensions; + private final boolean lite; + private final boolean proto3; + // TODO(xiaofeng): Make both full-runtime and lite-runtime support cached field size. + private final boolean useCachedSizeField; + + /** Represents [checkInitialized positions, map field positions, repeated field offsets]. */ + private final int[] intArray; + + /** + * Values at indices 0 -> checkInitializedCount in intArray are positions to check for + * initialization. + */ + private final int checkInitializedCount; + + /** + * Values at indices checkInitializedCount -> repeatedFieldOffsetStart are map positions. + * Everything after that are repeated field offsets. + */ + private final int repeatedFieldOffsetStart; + + private final NewInstanceSchema newInstanceSchema; + private final ListFieldSchema listFieldSchema; + private final UnknownFieldSchema unknownFieldSchema; + private final ExtensionSchema extensionSchema; + private final MapFieldSchema mapFieldSchema; + + private MessageSchema( + int[] buffer, + Object[] objects, + int minFieldNumber, + int maxFieldNumber, + MessageLite defaultInstance, + boolean proto3, + boolean useCachedSizeField, + int[] intArray, + int checkInitialized, + int mapFieldPositions, + NewInstanceSchema newInstanceSchema, + ListFieldSchema listFieldSchema, + UnknownFieldSchema unknownFieldSchema, + ExtensionSchema extensionSchema, + MapFieldSchema mapFieldSchema) { + this.buffer = buffer; + this.objects = objects; + this.minFieldNumber = minFieldNumber; + this.maxFieldNumber = maxFieldNumber; + + this.lite = defaultInstance instanceof GeneratedMessageLite; + this.proto3 = proto3; + this.hasExtensions = extensionSchema != null && extensionSchema.hasExtensions(defaultInstance); + this.useCachedSizeField = useCachedSizeField; + + this.intArray = intArray; + this.checkInitializedCount = checkInitialized; + this.repeatedFieldOffsetStart = mapFieldPositions; + + this.newInstanceSchema = newInstanceSchema; + this.listFieldSchema = listFieldSchema; + this.unknownFieldSchema = unknownFieldSchema; + this.extensionSchema = extensionSchema; + this.defaultInstance = defaultInstance; + this.mapFieldSchema = mapFieldSchema; + } + + static MessageSchema newSchema( + Class messageClass, + MessageInfo messageInfo, + NewInstanceSchema newInstanceSchema, + ListFieldSchema listFieldSchema, + UnknownFieldSchema unknownFieldSchema, + ExtensionSchema extensionSchema, + MapFieldSchema mapFieldSchema) { + if (messageInfo instanceof RawMessageInfo) { + return newSchemaForRawMessageInfo( + (RawMessageInfo) messageInfo, + newInstanceSchema, + listFieldSchema, + unknownFieldSchema, + extensionSchema, + mapFieldSchema); + + } else { + return newSchemaForMessageInfo( + (StructuralMessageInfo) messageInfo, + newInstanceSchema, + listFieldSchema, + unknownFieldSchema, + extensionSchema, + mapFieldSchema); + } + } + + static MessageSchema newSchemaForRawMessageInfo( + RawMessageInfo messageInfo, + NewInstanceSchema newInstanceSchema, + ListFieldSchema listFieldSchema, + UnknownFieldSchema unknownFieldSchema, + ExtensionSchema extensionSchema, + MapFieldSchema mapFieldSchema) { + final boolean isProto3 = messageInfo.getSyntax() == ProtoSyntax.PROTO3; + + String info = messageInfo.getStringInfo(); + final int length = info.length(); + int i = 0; + + int next = info.charAt(i++); + if (next >= 0xD800) { + int result = next & 0x1FFF; + int shift = 13; + while ((next = info.charAt(i++)) >= 0xD800) { + result |= (next & 0x1FFF) << shift; + shift += 13; + } + next = result | (next << shift); + } + final int unusedFlags = next; + + next = info.charAt(i++); + if (next >= 0xD800) { + int result = next & 0x1FFF; + int shift = 13; + while ((next = info.charAt(i++)) >= 0xD800) { + result |= (next & 0x1FFF) << shift; + shift += 13; + } + next = result | (next << shift); + } + final int fieldCount = next; + + final int oneofCount; + final int hasBitsCount; + final int minFieldNumber; + final int maxFieldNumber; + final int numEntries; + final int mapFieldCount; + final int repeatedFieldCount; + final int checkInitialized; + final int[] intArray; + int objectsPosition; + if (fieldCount == 0) { + oneofCount = 0; + hasBitsCount = 0; + minFieldNumber = 0; + maxFieldNumber = 0; + numEntries = 0; + mapFieldCount = 0; + repeatedFieldCount = 0; + checkInitialized = 0; + intArray = EMPTY_INT_ARRAY; + objectsPosition = 0; + } else { + next = info.charAt(i++); + if (next >= 0xD800) { + int result = next & 0x1FFF; + int shift = 13; + while ((next = info.charAt(i++)) >= 0xD800) { + result |= (next & 0x1FFF) << shift; + shift += 13; + } + next = result | (next << shift); + } + oneofCount = next; + + next = info.charAt(i++); + if (next >= 0xD800) { + int result = next & 0x1FFF; + int shift = 13; + while ((next = info.charAt(i++)) >= 0xD800) { + result |= (next & 0x1FFF) << shift; + shift += 13; + } + next = result | (next << shift); + } + hasBitsCount = next; + + next = info.charAt(i++); + if (next >= 0xD800) { + int result = next & 0x1FFF; + int shift = 13; + while ((next = info.charAt(i++)) >= 0xD800) { + result |= (next & 0x1FFF) << shift; + shift += 13; + } + next = result | (next << shift); + } + minFieldNumber = next; + + next = info.charAt(i++); + if (next >= 0xD800) { + int result = next & 0x1FFF; + int shift = 13; + while ((next = info.charAt(i++)) >= 0xD800) { + result |= (next & 0x1FFF) << shift; + shift += 13; + } + next = result | (next << shift); + } + maxFieldNumber = next; + + next = info.charAt(i++); + if (next >= 0xD800) { + int result = next & 0x1FFF; + int shift = 13; + while ((next = info.charAt(i++)) >= 0xD800) { + result |= (next & 0x1FFF) << shift; + shift += 13; + } + next = result | (next << shift); + } + numEntries = next; + + next = info.charAt(i++); + if (next >= 0xD800) { + int result = next & 0x1FFF; + int shift = 13; + while ((next = info.charAt(i++)) >= 0xD800) { + result |= (next & 0x1FFF) << shift; + shift += 13; + } + next = result | (next << shift); + } + mapFieldCount = next; + + next = info.charAt(i++); + if (next >= 0xD800) { + int result = next & 0x1FFF; + int shift = 13; + while ((next = info.charAt(i++)) >= 0xD800) { + result |= (next & 0x1FFF) << shift; + shift += 13; + } + next = result | (next << shift); + } + repeatedFieldCount = next; + + next = info.charAt(i++); + if (next >= 0xD800) { + int result = next & 0x1FFF; + int shift = 13; + while ((next = info.charAt(i++)) >= 0xD800) { + result |= (next & 0x1FFF) << shift; + shift += 13; + } + next = result | (next << shift); + } + checkInitialized = next; + intArray = new int[checkInitialized + mapFieldCount + repeatedFieldCount]; + // Field objects are after a list of (oneof, oneofCase) pairs + a list of hasbits fields. + objectsPosition = oneofCount * 2 + hasBitsCount; + } + + final sun.misc.Unsafe unsafe = UNSAFE; + final Object[] messageInfoObjects = messageInfo.getObjects(); + int checkInitializedPosition = 0; + final Class messageClass = messageInfo.getDefaultInstance().getClass(); + int[] buffer = new int[numEntries * INTS_PER_FIELD]; + Object[] objects = new Object[numEntries * 2]; + + int mapFieldIndex = checkInitialized; + int repeatedFieldIndex = checkInitialized + mapFieldCount; + + int bufferIndex = 0; + while (i < length) { + final int fieldNumber; + final int fieldTypeWithExtraBits; + final int fieldType; + + next = info.charAt(i++); + if (next >= 0xD800) { + int result = next & 0x1FFF; + int shift = 13; + while ((next = info.charAt(i++)) >= 0xD800) { + result |= (next & 0x1FFF) << shift; + shift += 13; + } + next = result | (next << shift); + } + fieldNumber = next; + + next = info.charAt(i++); + if (next >= 0xD800) { + int result = next & 0x1FFF; + int shift = 13; + while ((next = info.charAt(i++)) >= 0xD800) { + result |= (next & 0x1FFF) << shift; + shift += 13; + } + next = result | (next << shift); + } + fieldTypeWithExtraBits = next; + fieldType = fieldTypeWithExtraBits & 0xFF; + + if ((fieldTypeWithExtraBits & 0x400) != 0) { + intArray[checkInitializedPosition++] = bufferIndex; + } + + final int fieldOffset; + final int presenceMaskShift; + final int presenceFieldOffset; + + // Oneof + if (fieldType >= ONEOF_TYPE_OFFSET) { + next = info.charAt(i++); + if (next >= 0xD800) { + int result = next & 0x1FFF; + int shift = 13; + while ((next = info.charAt(i++)) >= 0xD800) { + result |= (next & 0x1FFF) << shift; + shift += 13; + } + next = result | (next << shift); + } + int oneofIndex = next; + + final int oneofFieldType = fieldType - ONEOF_TYPE_OFFSET; + if (oneofFieldType == 9 /* FieldType.MESSAGE */ + || oneofFieldType == 17 /* FieldType.GROUP */) { + objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++]; + } else if (oneofFieldType == 12 /* FieldType.ENUM */) { + if (!isProto3) { + objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++]; + } + } + + final java.lang.reflect.Field oneofField; + int index = oneofIndex * 2; + Object o = messageInfoObjects[index]; + if (o instanceof java.lang.reflect.Field) { + oneofField = (java.lang.reflect.Field) o; + } else { + oneofField = reflectField(messageClass, (String) o); + // Memoize java.lang.reflect.Field instances for oneof/hasbits fields, since they're + // potentially used for many Protobuf fields. Since there's a 1-1 mapping from the + // Protobuf field to the Java Field for non-oneofs, there's no benefit for memoizing + // those. + messageInfoObjects[index] = oneofField; + } + + fieldOffset = (int) unsafe.objectFieldOffset(oneofField); + + final java.lang.reflect.Field oneofCaseField; + index++; + o = messageInfoObjects[index]; + if (o instanceof java.lang.reflect.Field) { + oneofCaseField = (java.lang.reflect.Field) o; + } else { + oneofCaseField = reflectField(messageClass, (String) o); + messageInfoObjects[index] = oneofCaseField; + } + + presenceFieldOffset = (int) unsafe.objectFieldOffset(oneofCaseField); + presenceMaskShift = 0; + } else { + Field field = reflectField(messageClass, (String) messageInfoObjects[objectsPosition++]); + if (fieldType == 9 /* FieldType.MESSAGE */ || fieldType == 17 /* FieldType.GROUP */) { + objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = field.getType(); + } else if (fieldType == 27 /* FieldType.MESSAGE_LIST */ + || fieldType == 49 /* FieldType.GROUP_LIST */) { + objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++]; + } else if (fieldType == 12 /* FieldType.ENUM */ + || fieldType == 30 /* FieldType.ENUM_LIST */ + || fieldType == 44 /* FieldType.ENUM_LIST_PACKED */) { + if (!isProto3) { + objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++]; + } + } else if (fieldType == 50 /* FieldType.MAP */) { + intArray[mapFieldIndex++] = bufferIndex; + objects[bufferIndex / INTS_PER_FIELD * 2] = messageInfoObjects[objectsPosition++]; + if ((fieldTypeWithExtraBits & 0x800) != 0) { + objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++]; + } + } + + fieldOffset = (int) unsafe.objectFieldOffset(field); + boolean hasHasBit = (fieldTypeWithExtraBits & 0x1000) == 0x1000; + if (hasHasBit && fieldType <= 17 /* FieldType.GROUP */) { + next = info.charAt(i++); + if (next >= 0xD800) { + int result = next & 0x1FFF; + int shift = 13; + while ((next = info.charAt(i++)) >= 0xD800) { + result |= (next & 0x1FFF) << shift; + shift += 13; + } + next = result | (next << shift); + } + int hasBitsIndex = next; + + final java.lang.reflect.Field hasBitsField; + int index = oneofCount * 2 + hasBitsIndex / 32; + Object o = messageInfoObjects[index]; + if (o instanceof java.lang.reflect.Field) { + hasBitsField = (java.lang.reflect.Field) o; + } else { + hasBitsField = reflectField(messageClass, (String) o); + messageInfoObjects[index] = hasBitsField; + } + + presenceFieldOffset = (int) unsafe.objectFieldOffset(hasBitsField); + presenceMaskShift = hasBitsIndex % 32; + } else { + presenceFieldOffset = NO_PRESENCE_SENTINEL; + presenceMaskShift = 0; + } + + if (fieldType >= 18 && fieldType <= 49) { + // Field types of repeated fields are in a consecutive range from 18 (DOUBLE_LIST) to + // 49 (GROUP_LIST). + intArray[repeatedFieldIndex++] = fieldOffset; + } + } + + buffer[bufferIndex++] = fieldNumber; + buffer[bufferIndex++] = + ((fieldTypeWithExtraBits & 0x200) != 0 ? ENFORCE_UTF8_MASK : 0) + | ((fieldTypeWithExtraBits & 0x100) != 0 ? REQUIRED_MASK : 0) + | (fieldType << OFFSET_BITS) + | fieldOffset; + buffer[bufferIndex++] = (presenceMaskShift << OFFSET_BITS) | presenceFieldOffset; + } + + return new MessageSchema( + buffer, + objects, + minFieldNumber, + maxFieldNumber, + messageInfo.getDefaultInstance(), + isProto3, + /* useCachedSizeField= */ false, + intArray, + checkInitialized, + checkInitialized + mapFieldCount, + newInstanceSchema, + listFieldSchema, + unknownFieldSchema, + extensionSchema, + mapFieldSchema); + } + + private static java.lang.reflect.Field reflectField(Class messageClass, String fieldName) { + try { + return messageClass.getDeclaredField(fieldName); + } catch (NoSuchFieldException e) { + // Some Samsung devices lie about what fields are present via the getDeclaredField API so + // we do the for loop properly that they seem to have messed up... + java.lang.reflect.Field[] fields = messageClass.getDeclaredFields(); + for (java.lang.reflect.Field field : fields) { + if (fieldName.equals(field.getName())) { + return field; + } + } + + // If we make it here, the runtime still lies about what we know to be true at compile + // time. We throw to alert server monitoring for further remediation. + throw new RuntimeException( + "Field " + + fieldName + + " for " + + messageClass.getName() + + " not found. Known fields are " + + Arrays.toString(fields)); + } + } + + static MessageSchema newSchemaForMessageInfo( + StructuralMessageInfo messageInfo, + NewInstanceSchema newInstanceSchema, + ListFieldSchema listFieldSchema, + UnknownFieldSchema unknownFieldSchema, + ExtensionSchema extensionSchema, + MapFieldSchema mapFieldSchema) { + final boolean isProto3 = messageInfo.getSyntax() == ProtoSyntax.PROTO3; + FieldInfo[] fis = messageInfo.getFields(); + final int minFieldNumber; + final int maxFieldNumber; + if (fis.length == 0) { + minFieldNumber = 0; + maxFieldNumber = 0; + } else { + minFieldNumber = fis[0].getFieldNumber(); + maxFieldNumber = fis[fis.length - 1].getFieldNumber(); + } + + final int numEntries = fis.length; + + int[] buffer = new int[numEntries * INTS_PER_FIELD]; + Object[] objects = new Object[numEntries * 2]; + + int mapFieldCount = 0; + int repeatedFieldCount = 0; + for (FieldInfo fi : fis) { + if (fi.getType() == FieldType.MAP) { + mapFieldCount++; + } else if (fi.getType().id() >= 18 && fi.getType().id() <= 49) { + // Field types of repeated fields are in a consecutive range from 18 (DOUBLE_LIST) to + // 49 (GROUP_LIST). + repeatedFieldCount++; + } + } + int[] mapFieldPositions = mapFieldCount > 0 ? new int[mapFieldCount] : null; + int[] repeatedFieldOffsets = repeatedFieldCount > 0 ? new int[repeatedFieldCount] : null; + mapFieldCount = 0; + repeatedFieldCount = 0; + + int[] checkInitialized = messageInfo.getCheckInitialized(); + if (checkInitialized == null) { + checkInitialized = EMPTY_INT_ARRAY; + } + int checkInitializedIndex = 0; + // Fill in the manifest data from the descriptors. + int fieldIndex = 0; + for (int bufferIndex = 0; fieldIndex < fis.length; bufferIndex += INTS_PER_FIELD) { + final FieldInfo fi = fis[fieldIndex]; + final int fieldNumber = fi.getFieldNumber(); + + // We found the entry for the next field. Store the entry in the manifest for + // this field and increment the field index. + storeFieldData(fi, buffer, bufferIndex, objects); + + // Convert field number to index + if (checkInitializedIndex < checkInitialized.length + && checkInitialized[checkInitializedIndex] == fieldNumber) { + checkInitialized[checkInitializedIndex++] = bufferIndex; + } + + if (fi.getType() == FieldType.MAP) { + mapFieldPositions[mapFieldCount++] = bufferIndex; + } else if (fi.getType().id() >= 18 && fi.getType().id() <= 49) { + // Field types of repeated fields are in a consecutive range from 18 (DOUBLE_LIST) to + // 49 (GROUP_LIST). + repeatedFieldOffsets[repeatedFieldCount++] = + (int) UnsafeUtil.objectFieldOffset(fi.getField()); + } + + fieldIndex++; + } + + if (mapFieldPositions == null) { + mapFieldPositions = EMPTY_INT_ARRAY; + } + if (repeatedFieldOffsets == null) { + repeatedFieldOffsets = EMPTY_INT_ARRAY; + } + int[] combined = + new int[checkInitialized.length + mapFieldPositions.length + repeatedFieldOffsets.length]; + System.arraycopy(checkInitialized, 0, combined, 0, checkInitialized.length); + System.arraycopy( + mapFieldPositions, 0, combined, checkInitialized.length, mapFieldPositions.length); + System.arraycopy( + repeatedFieldOffsets, + 0, + combined, + checkInitialized.length + mapFieldPositions.length, + repeatedFieldOffsets.length); + + return new MessageSchema( + buffer, + objects, + minFieldNumber, + maxFieldNumber, + messageInfo.getDefaultInstance(), + isProto3, + /* useCachedSizeField= */ true, + combined, + checkInitialized.length, + checkInitialized.length + mapFieldPositions.length, + newInstanceSchema, + listFieldSchema, + unknownFieldSchema, + extensionSchema, + mapFieldSchema); + } + + private static void storeFieldData( + FieldInfo fi, int[] buffer, int bufferIndex, Object[] objects) { + final int fieldOffset; + final int typeId; + final int presenceMaskShift; + final int presenceFieldOffset; + + OneofInfo oneof = fi.getOneof(); + if (oneof != null) { + typeId = fi.getType().id() + ONEOF_TYPE_OFFSET; + fieldOffset = (int) UnsafeUtil.objectFieldOffset(oneof.getValueField()); + presenceFieldOffset = (int) UnsafeUtil.objectFieldOffset(oneof.getCaseField()); + presenceMaskShift = 0; + } else { + FieldType type = fi.getType(); + fieldOffset = (int) UnsafeUtil.objectFieldOffset(fi.getField()); + typeId = type.id(); + if (!type.isList() && !type.isMap()) { + Field presenceField = fi.getPresenceField(); + if (presenceField == null) { + presenceFieldOffset = NO_PRESENCE_SENTINEL; + } else { + presenceFieldOffset = (int) UnsafeUtil.objectFieldOffset(presenceField); + } + presenceMaskShift = Integer.numberOfTrailingZeros(fi.getPresenceMask()); + } else { + if (fi.getCachedSizeField() == null) { + presenceFieldOffset = 0; + presenceMaskShift = 0; + } else { + presenceFieldOffset = (int) UnsafeUtil.objectFieldOffset(fi.getCachedSizeField()); + presenceMaskShift = 0; + } + } + } + + buffer[bufferIndex] = fi.getFieldNumber(); + buffer[bufferIndex + 1] = + (fi.isEnforceUtf8() ? ENFORCE_UTF8_MASK : 0) + | (fi.isRequired() ? REQUIRED_MASK : 0) + | (typeId << OFFSET_BITS) + | fieldOffset; + buffer[bufferIndex + 2] = (presenceMaskShift << OFFSET_BITS) | presenceFieldOffset; + + Object messageFieldClass = fi.getMessageFieldClass(); + if (fi.getMapDefaultEntry() != null) { + objects[bufferIndex / INTS_PER_FIELD * 2] = fi.getMapDefaultEntry(); + if (messageFieldClass != null) { + objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageFieldClass; + } else if (fi.getEnumVerifier() != null) { + objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = fi.getEnumVerifier(); + } + } else { + if (messageFieldClass != null) { + objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageFieldClass; + } else if (fi.getEnumVerifier() != null) { + objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = fi.getEnumVerifier(); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public T newInstance() { + return (T) newInstanceSchema.newInstance(defaultInstance); + } + + @Override + public boolean equals(T message, T other) { + final int bufferLength = buffer.length; + for (int pos = 0; pos < bufferLength; pos += INTS_PER_FIELD) { + if (!equals(message, other, pos)) { + return false; + } + } + + Object messageUnknown = unknownFieldSchema.getFromMessage(message); + Object otherUnknown = unknownFieldSchema.getFromMessage(other); + if (!messageUnknown.equals(otherUnknown)) { + return false; + } + + if (hasExtensions) { + FieldSet messageExtensions = extensionSchema.getExtensions(message); + FieldSet otherExtensions = extensionSchema.getExtensions(other); + return messageExtensions.equals(otherExtensions); + } + return true; + } + + private boolean equals(T message, T other, int pos) { + final int typeAndOffset = typeAndOffsetAt(pos); + final long offset = offset(typeAndOffset); + + switch (type(typeAndOffset)) { + case 0: // DOUBLE: + return arePresentForEquals(message, other, pos) + && Double.doubleToLongBits(UnsafeUtil.getDouble(message, offset)) + == Double.doubleToLongBits(UnsafeUtil.getDouble(other, offset)); + case 1: // FLOAT: + return arePresentForEquals(message, other, pos) + && Float.floatToIntBits(UnsafeUtil.getFloat(message, offset)) + == Float.floatToIntBits(UnsafeUtil.getFloat(other, offset)); + case 2: // INT64: + return arePresentForEquals(message, other, pos) + && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset); + case 3: // UINT64: + return arePresentForEquals(message, other, pos) + && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset); + case 4: // INT32: + return arePresentForEquals(message, other, pos) + && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset); + case 5: // FIXED64: + return arePresentForEquals(message, other, pos) + && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset); + case 6: // FIXED32: + return arePresentForEquals(message, other, pos) + && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset); + case 7: // BOOL: + return arePresentForEquals(message, other, pos) + && UnsafeUtil.getBoolean(message, offset) == UnsafeUtil.getBoolean(other, offset); + case 8: // STRING: + return arePresentForEquals(message, other, pos) + && SchemaUtil.safeEquals( + UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset)); + case 9: // MESSAGE: + return arePresentForEquals(message, other, pos) + && SchemaUtil.safeEquals( + UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset)); + case 10: // BYTES: + return arePresentForEquals(message, other, pos) + && SchemaUtil.safeEquals( + UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset)); + case 11: // UINT32: + return arePresentForEquals(message, other, pos) + && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset); + case 12: // ENUM: + return arePresentForEquals(message, other, pos) + && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset); + case 13: // SFIXED32: + return arePresentForEquals(message, other, pos) + && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset); + case 14: // SFIXED64: + return arePresentForEquals(message, other, pos) + && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset); + case 15: // SINT32: + return arePresentForEquals(message, other, pos) + && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset); + case 16: // SINT64: + return arePresentForEquals(message, other, pos) + && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset); + case 17: // GROUP: + return arePresentForEquals(message, other, pos) + && SchemaUtil.safeEquals( + UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset)); + + case 18: // DOUBLE_LIST: + case 19: // FLOAT_LIST: + case 20: // INT64_LIST: + case 21: // UINT64_LIST: + case 22: // INT32_LIST: + case 23: // FIXED64_LIST: + case 24: // FIXED32_LIST: + case 25: // BOOL_LIST: + case 26: // STRING_LIST: + case 27: // MESSAGE_LIST: + case 28: // BYTES_LIST: + case 29: // UINT32_LIST: + case 30: // ENUM_LIST: + case 31: // SFIXED32_LIST: + case 32: // SFIXED64_LIST: + case 33: // SINT32_LIST: + case 34: // SINT64_LIST: + case 35: // DOUBLE_LIST_PACKED: + case 36: // FLOAT_LIST_PACKED: + case 37: // INT64_LIST_PACKED: + case 38: // UINT64_LIST_PACKED: + case 39: // INT32_LIST_PACKED: + case 40: // FIXED64_LIST_PACKED: + case 41: // FIXED32_LIST_PACKED: + case 42: // BOOL_LIST_PACKED: + case 43: // UINT32_LIST_PACKED: + case 44: // ENUM_LIST_PACKED: + case 45: // SFIXED32_LIST_PACKED: + case 46: // SFIXED64_LIST_PACKED: + case 47: // SINT32_LIST_PACKED: + case 48: // SINT64_LIST_PACKED: + case 49: // GROUP_LIST: + return SchemaUtil.safeEquals( + UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset)); + case 50: // MAP: + return SchemaUtil.safeEquals( + UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset)); + case 51: // ONEOF_DOUBLE: + case 52: // ONEOF_FLOAT: + case 53: // ONEOF_INT64: + case 54: // ONEOF_UINT64: + case 55: // ONEOF_INT32: + case 56: // ONEOF_FIXED64: + case 57: // ONEOF_FIXED32: + case 58: // ONEOF_BOOL: + case 59: // ONEOF_STRING: + case 60: // ONEOF_MESSAGE: + case 61: // ONEOF_BYTES: + case 62: // ONEOF_UINT32: + case 63: // ONEOF_ENUM: + case 64: // ONEOF_SFIXED32: + case 65: // ONEOF_SFIXED64: + case 66: // ONEOF_SINT32: + case 67: // ONEOF_SINT64: + case 68: // ONEOF_GROUP: + return isOneofCaseEqual(message, other, pos) + && SchemaUtil.safeEquals( + UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset)); + default: + // Assume it's an empty entry - just go to the next entry. + return true; + } + } + + @Override + public int hashCode(T message) { + int hashCode = 0; + final int bufferLength = buffer.length; + for (int pos = 0; pos < bufferLength; pos += INTS_PER_FIELD) { + final int typeAndOffset = typeAndOffsetAt(pos); + final int entryNumber = numberAt(pos); + + final long offset = offset(typeAndOffset); + + switch (type(typeAndOffset)) { + case 0: // DOUBLE: + hashCode = + (hashCode * 53) + + Internal.hashLong( + Double.doubleToLongBits(UnsafeUtil.getDouble(message, offset))); + break; + case 1: // FLOAT: + hashCode = (hashCode * 53) + Float.floatToIntBits(UnsafeUtil.getFloat(message, offset)); + break; + case 2: // INT64: + hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset)); + break; + case 3: // UINT64: + hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset)); + break; + case 4: // INT32: + hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset)); + break; + case 5: // FIXED64: + hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset)); + break; + case 6: // FIXED32: + hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset)); + break; + case 7: // BOOL: + hashCode = (hashCode * 53) + Internal.hashBoolean(UnsafeUtil.getBoolean(message, offset)); + break; + case 8: // STRING: + hashCode = (hashCode * 53) + ((String) UnsafeUtil.getObject(message, offset)).hashCode(); + break; + case 9: // MESSAGE: + { + int protoHash = 37; + Object submessage = UnsafeUtil.getObject(message, offset); + if (submessage != null) { + protoHash = submessage.hashCode(); + } + hashCode = (53 * hashCode) + protoHash; + break; + } + case 10: // BYTES: + hashCode = (hashCode * 53) + UnsafeUtil.getObject(message, offset).hashCode(); + break; + case 11: // UINT32: + hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset)); + break; + case 12: // ENUM: + hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset)); + break; + case 13: // SFIXED32: + hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset)); + break; + case 14: // SFIXED64: + hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset)); + break; + case 15: // SINT32: + hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset)); + break; + case 16: // SINT64: + hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset)); + break; + + case 17: // GROUP: + { + int protoHash = 37; + Object submessage = UnsafeUtil.getObject(message, offset); + if (submessage != null) { + protoHash = submessage.hashCode(); + } + hashCode = (53 * hashCode) + protoHash; + break; + } + case 18: // DOUBLE_LIST: + case 19: // FLOAT_LIST: + case 20: // INT64_LIST: + case 21: // UINT64_LIST: + case 22: // INT32_LIST: + case 23: // FIXED64_LIST: + case 24: // FIXED32_LIST: + case 25: // BOOL_LIST: + case 26: // STRING_LIST: + case 27: // MESSAGE_LIST: + case 28: // BYTES_LIST: + case 29: // UINT32_LIST: + case 30: // ENUM_LIST: + case 31: // SFIXED32_LIST: + case 32: // SFIXED64_LIST: + case 33: // SINT32_LIST: + case 34: // SINT64_LIST: + case 35: // DOUBLE_LIST_PACKED: + case 36: // FLOAT_LIST_PACKED: + case 37: // INT64_LIST_PACKED: + case 38: // UINT64_LIST_PACKED: + case 39: // INT32_LIST_PACKED: + case 40: // FIXED64_LIST_PACKED: + case 41: // FIXED32_LIST_PACKED: + case 42: // BOOL_LIST_PACKED: + case 43: // UINT32_LIST_PACKED: + case 44: // ENUM_LIST_PACKED: + case 45: // SFIXED32_LIST_PACKED: + case 46: // SFIXED64_LIST_PACKED: + case 47: // SINT32_LIST_PACKED: + case 48: // SINT64_LIST_PACKED: + case 49: // GROUP_LIST: + hashCode = (hashCode * 53) + UnsafeUtil.getObject(message, offset).hashCode(); + break; + case 50: // MAP: + hashCode = (hashCode * 53) + UnsafeUtil.getObject(message, offset).hashCode(); + break; + case 51: // ONEOF_DOUBLE: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = + (hashCode * 53) + + Internal.hashLong(Double.doubleToLongBits(oneofDoubleAt(message, offset))); + } + break; + case 52: // ONEOF_FLOAT: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = (hashCode * 53) + Float.floatToIntBits(oneofFloatAt(message, offset)); + } + break; + case 53: // ONEOF_INT64: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset)); + } + break; + case 54: // ONEOF_UINT64: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset)); + } + break; + case 55: // ONEOF_INT32: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = (hashCode * 53) + (oneofIntAt(message, offset)); + } + break; + case 56: // ONEOF_FIXED64: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset)); + } + break; + case 57: // ONEOF_FIXED32: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = (hashCode * 53) + (oneofIntAt(message, offset)); + } + break; + case 58: // ONEOF_BOOL: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = (hashCode * 53) + Internal.hashBoolean(oneofBooleanAt(message, offset)); + } + break; + case 59: // ONEOF_STRING: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = + (hashCode * 53) + ((String) UnsafeUtil.getObject(message, offset)).hashCode(); + } + break; + case 60: // ONEOF_MESSAGE: + if (isOneofPresent(message, entryNumber, pos)) { + Object submessage = UnsafeUtil.getObject(message, offset); + hashCode = (53 * hashCode) + submessage.hashCode(); + } + break; + case 61: // ONEOF_BYTES: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = (hashCode * 53) + UnsafeUtil.getObject(message, offset).hashCode(); + } + break; + case 62: // ONEOF_UINT32: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = (hashCode * 53) + (oneofIntAt(message, offset)); + } + break; + case 63: // ONEOF_ENUM: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = (hashCode * 53) + (oneofIntAt(message, offset)); + } + break; + case 64: // ONEOF_SFIXED32: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = (hashCode * 53) + (oneofIntAt(message, offset)); + } + break; + case 65: // ONEOF_SFIXED64: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset)); + } + break; + case 66: // ONEOF_SINT32: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = (hashCode * 53) + (oneofIntAt(message, offset)); + } + break; + case 67: // ONEOF_SINT64: + if (isOneofPresent(message, entryNumber, pos)) { + hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset)); + } + break; + case 68: // ONEOF_GROUP: + if (isOneofPresent(message, entryNumber, pos)) { + Object submessage = UnsafeUtil.getObject(message, offset); + hashCode = (53 * hashCode) + submessage.hashCode(); + } + break; + default: + // Assume it's an empty entry - just go to the next entry. + break; + } + } + + hashCode = (hashCode * 53) + unknownFieldSchema.getFromMessage(message).hashCode(); + + if (hasExtensions) { + hashCode = (hashCode * 53) + extensionSchema.getExtensions(message).hashCode(); + } + + return hashCode; + } + + @Override + public void mergeFrom(T message, T other) { + if (other == null) { + throw new NullPointerException(); + } + for (int i = 0; i < buffer.length; i += INTS_PER_FIELD) { + // A separate method allows for better JIT optimizations + mergeSingleField(message, other, i); + } + + SchemaUtil.mergeUnknownFields(unknownFieldSchema, message, other); + + if (hasExtensions) { + SchemaUtil.mergeExtensions(extensionSchema, message, other); + } + } + + private void mergeSingleField(T message, T other, int pos) { + final int typeAndOffset = typeAndOffsetAt(pos); + final long offset = offset(typeAndOffset); + final int number = numberAt(pos); + + switch (type(typeAndOffset)) { + case 0: // DOUBLE: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putDouble(message, offset, UnsafeUtil.getDouble(other, offset)); + setFieldPresent(message, pos); + } + break; + case 1: // FLOAT: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putFloat(message, offset, UnsafeUtil.getFloat(other, offset)); + setFieldPresent(message, pos); + } + break; + case 2: // INT64: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset)); + setFieldPresent(message, pos); + } + break; + case 3: // UINT64: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset)); + setFieldPresent(message, pos); + } + break; + case 4: // INT32: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset)); + setFieldPresent(message, pos); + } + break; + case 5: // FIXED64: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset)); + setFieldPresent(message, pos); + } + break; + case 6: // FIXED32: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset)); + setFieldPresent(message, pos); + } + break; + case 7: // BOOL: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putBoolean(message, offset, UnsafeUtil.getBoolean(other, offset)); + setFieldPresent(message, pos); + } + break; + case 8: // STRING: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putObject(message, offset, UnsafeUtil.getObject(other, offset)); + setFieldPresent(message, pos); + } + break; + case 9: // MESSAGE: + mergeMessage(message, other, pos); + break; + case 10: // BYTES: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putObject(message, offset, UnsafeUtil.getObject(other, offset)); + setFieldPresent(message, pos); + } + break; + case 11: // UINT32: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset)); + setFieldPresent(message, pos); + } + break; + case 12: // ENUM: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset)); + setFieldPresent(message, pos); + } + break; + case 13: // SFIXED32: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset)); + setFieldPresent(message, pos); + } + break; + case 14: // SFIXED64: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset)); + setFieldPresent(message, pos); + } + break; + case 15: // SINT32: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset)); + setFieldPresent(message, pos); + } + break; + case 16: // SINT64: + if (isFieldPresent(other, pos)) { + UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset)); + setFieldPresent(message, pos); + } + break; + case 17: // GROUP: + mergeMessage(message, other, pos); + break; + case 18: // DOUBLE_LIST: + case 19: // FLOAT_LIST: + case 20: // INT64_LIST: + case 21: // UINT64_LIST: + case 22: // INT32_LIST: + case 23: // FIXED64_LIST: + case 24: // FIXED32_LIST: + case 25: // BOOL_LIST: + case 26: // STRING_LIST: + case 27: // MESSAGE_LIST: + case 28: // BYTES_LIST: + case 29: // UINT32_LIST: + case 30: // ENUM_LIST: + case 31: // SFIXED32_LIST: + case 32: // SFIXED64_LIST: + case 33: // SINT32_LIST: + case 34: // SINT64_LIST: + case 35: // DOUBLE_LIST_PACKED: + case 36: // FLOAT_LIST_PACKED: + case 37: // INT64_LIST_PACKED: + case 38: // UINT64_LIST_PACKED: + case 39: // INT32_LIST_PACKED: + case 40: // FIXED64_LIST_PACKED: + case 41: // FIXED32_LIST_PACKED: + case 42: // BOOL_LIST_PACKED: + case 43: // UINT32_LIST_PACKED: + case 44: // ENUM_LIST_PACKED: + case 45: // SFIXED32_LIST_PACKED: + case 46: // SFIXED64_LIST_PACKED: + case 47: // SINT32_LIST_PACKED: + case 48: // SINT64_LIST_PACKED: + case 49: // GROUP_LIST: + listFieldSchema.mergeListsAt(message, other, offset); + break; + case 50: // MAP: + SchemaUtil.mergeMap(mapFieldSchema, message, other, offset); + break; + case 51: // ONEOF_DOUBLE: + case 52: // ONEOF_FLOAT: + case 53: // ONEOF_INT64: + case 54: // ONEOF_UINT64: + case 55: // ONEOF_INT32: + case 56: // ONEOF_FIXED64: + case 57: // ONEOF_FIXED32: + case 58: // ONEOF_BOOL: + case 59: // ONEOF_STRING: + if (isOneofPresent(other, number, pos)) { + UnsafeUtil.putObject(message, offset, UnsafeUtil.getObject(other, offset)); + setOneofPresent(message, number, pos); + } + break; + + case 60: // ONEOF_MESSAGE: + mergeOneofMessage(message, other, pos); + break; + case 61: // ONEOF_BYTES: + case 62: // ONEOF_UINT32: + case 63: // ONEOF_ENUM: + case 64: // ONEOF_SFIXED32: + case 65: // ONEOF_SFIXED64: + case 66: // ONEOF_SINT32: + case 67: // ONEOF_SINT64: + if (isOneofPresent(other, number, pos)) { + UnsafeUtil.putObject(message, offset, UnsafeUtil.getObject(other, offset)); + setOneofPresent(message, number, pos); + } + break; + case 68: // ONEOF_GROUP: + mergeOneofMessage(message, other, pos); + break; + default: + break; + } + } + + private void mergeMessage(T message, T other, int pos) { + final int typeAndOffset = typeAndOffsetAt(pos); + final long offset = offset(typeAndOffset); + + if (!isFieldPresent(other, pos)) { + return; + } + + Object mine = UnsafeUtil.getObject(message, offset); + Object theirs = UnsafeUtil.getObject(other, offset); + if (mine != null && theirs != null) { + Object merged = Internal.mergeMessage(mine, theirs); + UnsafeUtil.putObject(message, offset, merged); + setFieldPresent(message, pos); + } else if (theirs != null) { + UnsafeUtil.putObject(message, offset, theirs); + setFieldPresent(message, pos); + } + } + + private void mergeOneofMessage(T message, T other, int pos) { + int typeAndOffset = typeAndOffsetAt(pos); + int number = numberAt(pos); + long offset = offset(typeAndOffset); + + if (!isOneofPresent(other, number, pos)) { + return; + } + Object mine = null; + if (isOneofPresent(message, number, pos)) { + mine = UnsafeUtil.getObject(message, offset); + } + Object theirs = UnsafeUtil.getObject(other, offset); + if (mine != null && theirs != null) { + Object merged = Internal.mergeMessage(mine, theirs); + UnsafeUtil.putObject(message, offset, merged); + setOneofPresent(message, number, pos); + } else if (theirs != null) { + UnsafeUtil.putObject(message, offset, theirs); + setOneofPresent(message, number, pos); + } + } + + @Override + public int getSerializedSize(T message) { + return proto3 ? getSerializedSizeProto3(message) : getSerializedSizeProto2(message); + } + + @SuppressWarnings("unchecked") + private int getSerializedSizeProto2(T message) { + int size = 0; + + final sun.misc.Unsafe unsafe = UNSAFE; + int currentPresenceFieldOffset = NO_PRESENCE_SENTINEL; + int currentPresenceField = 0; + for (int i = 0; i < buffer.length; i += INTS_PER_FIELD) { + final int typeAndOffset = typeAndOffsetAt(i); + final int number = numberAt(i); + + int fieldType = type(typeAndOffset); + int presenceMaskAndOffset = 0; + int presenceMask = 0; + if (fieldType <= 17) { + presenceMaskAndOffset = buffer[i + 2]; + final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK; + presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS); + if (presenceFieldOffset != currentPresenceFieldOffset) { + currentPresenceFieldOffset = presenceFieldOffset; + currentPresenceField = unsafe.getInt(message, (long) presenceFieldOffset); + } + } else if (useCachedSizeField + && fieldType >= FieldType.DOUBLE_LIST_PACKED.id() + && fieldType <= FieldType.SINT64_LIST_PACKED.id()) { + presenceMaskAndOffset = buffer[i + 2] & OFFSET_MASK; + } + + final long offset = offset(typeAndOffset); + + switch (fieldType) { + case 0: // DOUBLE: + if ((currentPresenceField & presenceMask) != 0) { + size += CodedOutputStream.computeDoubleSize(number, 0); + } + break; + case 1: // FLOAT: + if ((currentPresenceField & presenceMask) != 0) { + size += CodedOutputStream.computeFloatSize(number, 0); + } + break; + case 2: // INT64: + if ((currentPresenceField & presenceMask) != 0) { + size += CodedOutputStream.computeInt64Size(number, unsafe.getLong(message, offset)); + } + break; + case 3: // UINT64: + if ((currentPresenceField & presenceMask) != 0) { + size += CodedOutputStream.computeUInt64Size(number, unsafe.getLong(message, offset)); + } + break; + case 4: // INT32: + if ((currentPresenceField & presenceMask) != 0) { + size += CodedOutputStream.computeInt32Size(number, unsafe.getInt(message, offset)); + } + break; + case 5: // FIXED64: + if ((currentPresenceField & presenceMask) != 0) { + size += CodedOutputStream.computeFixed64Size(number, 0); + } + break; + case 6: // FIXED32: + if ((currentPresenceField & presenceMask) != 0) { + size += CodedOutputStream.computeFixed32Size(number, 0); + } + break; + case 7: // BOOL: + if ((currentPresenceField & presenceMask) != 0) { + size += CodedOutputStream.computeBoolSize(number, true); + } + break; + case 8: // STRING: + if ((currentPresenceField & presenceMask) != 0) { + Object value = unsafe.getObject(message, offset); + if (value instanceof ByteString) { + size += CodedOutputStream.computeBytesSize(number, (ByteString) value); + } else { + size += CodedOutputStream.computeStringSize(number, (String) value); + } + } + break; + case 9: // MESSAGE: + if ((currentPresenceField & presenceMask) != 0) { + Object value = unsafe.getObject(message, offset); + size += SchemaUtil.computeSizeMessage(number, value, getMessageFieldSchema(i)); + } + break; + case 10: // BYTES: + if ((currentPresenceField & presenceMask) != 0) { + ByteString value = (ByteString) unsafe.getObject(message, offset); + size += CodedOutputStream.computeBytesSize(number, value); + } + break; + case 11: // UINT32: + if ((currentPresenceField & presenceMask) != 0) { + size += CodedOutputStream.computeUInt32Size(number, unsafe.getInt(message, offset)); + } + break; + case 12: // ENUM: + if ((currentPresenceField & presenceMask) != 0) { + size += CodedOutputStream.computeEnumSize(number, unsafe.getInt(message, offset)); + } + break; + case 13: // SFIXED32: + if ((currentPresenceField & presenceMask) != 0) { + size += CodedOutputStream.computeSFixed32Size(number, 0); + } + break; + case 14: // SFIXED64: + if ((currentPresenceField & presenceMask) != 0) { + size += CodedOutputStream.computeSFixed64Size(number, 0); + } + break; + case 15: // SINT32: + if ((currentPresenceField & presenceMask) != 0) { + size += CodedOutputStream.computeSInt32Size(number, unsafe.getInt(message, offset)); + } + break; + case 16: // SINT64: + if ((currentPresenceField & presenceMask) != 0) { + size += CodedOutputStream.computeSInt64Size(number, unsafe.getLong(message, offset)); + } + break; + case 17: // GROUP: + if ((currentPresenceField & presenceMask) != 0) { + size += + CodedOutputStream.computeGroupSize( + number, + (MessageLite) unsafe.getObject(message, offset), + getMessageFieldSchema(i)); + } + break; + case 18: // DOUBLE_LIST: + size += + SchemaUtil.computeSizeFixed64List( + number, (List) unsafe.getObject(message, offset), false); + break; + case 19: // FLOAT_LIST: + size += + SchemaUtil.computeSizeFixed32List( + number, (List) unsafe.getObject(message, offset), false); + break; + case 20: // INT64_LIST: + size += + SchemaUtil.computeSizeInt64List( + number, (List) unsafe.getObject(message, offset), false); + break; + case 21: // UINT64_LIST: + size += + SchemaUtil.computeSizeUInt64List( + number, (List) unsafe.getObject(message, offset), false); + break; + case 22: // INT32_LIST: + size += + SchemaUtil.computeSizeInt32List( + number, (List) unsafe.getObject(message, offset), false); + break; + case 23: // FIXED64_LIST: + size += + SchemaUtil.computeSizeFixed64List( + number, (List) unsafe.getObject(message, offset), false); + break; + case 24: // FIXED32_LIST: + size += + SchemaUtil.computeSizeFixed32List( + number, (List) unsafe.getObject(message, offset), false); + break; + case 25: // BOOL_LIST: + size += + SchemaUtil.computeSizeBoolList( + number, (List) unsafe.getObject(message, offset), false); + break; + case 26: // STRING_LIST: + size += + SchemaUtil.computeSizeStringList(number, (List) unsafe.getObject(message, offset)); + break; + case 27: // MESSAGE_LIST: + size += + SchemaUtil.computeSizeMessageList( + number, (List) unsafe.getObject(message, offset), getMessageFieldSchema(i)); + break; + case 28: // BYTES_LIST: + size += + SchemaUtil.computeSizeByteStringList( + number, (List) unsafe.getObject(message, offset)); + break; + case 29: // UINT32_LIST: + size += + SchemaUtil.computeSizeUInt32List( + number, (List) unsafe.getObject(message, offset), false); + break; + case 30: // ENUM_LIST: + size += + SchemaUtil.computeSizeEnumList( + number, (List) unsafe.getObject(message, offset), false); + break; + case 31: // SFIXED32_LIST: + size += + SchemaUtil.computeSizeFixed32List( + number, (List) unsafe.getObject(message, offset), false); + break; + case 32: // SFIXED64_LIST: + size += + SchemaUtil.computeSizeFixed64List( + number, (List) unsafe.getObject(message, offset), false); + break; + case 33: // SINT32_LIST: + size += + SchemaUtil.computeSizeSInt32List( + number, (List) unsafe.getObject(message, offset), false); + break; + case 34: // SINT64_LIST: + size += + SchemaUtil.computeSizeSInt64List( + number, (List) unsafe.getObject(message, offset), false); + break; + case 35: + { // DOUBLE_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeFixed64ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 36: + { // FLOAT_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeFixed32ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 37: + { // INT64_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeInt64ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 38: + { // UINT64_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeUInt64ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 39: + { // INT32_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeInt32ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 40: + { // FIXED64_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeFixed64ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 41: + { // FIXED32_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeFixed32ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 42: + { // BOOL_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeBoolListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 43: + { // UINT32_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeUInt32ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 44: + { // ENUM_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeEnumListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 45: + { // SFIXED32_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeFixed32ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 46: + { // SFIXED64_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeFixed64ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 47: + { // SINT32_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeSInt32ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 48: + { // SINT64_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeSInt64ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 49: // GROUP_LIST: + size += + SchemaUtil.computeSizeGroupList( + number, + (List) unsafe.getObject(message, offset), + getMessageFieldSchema(i)); + break; + case 50: // MAP: + // TODO(dweis): Use schema cache. + size += + mapFieldSchema.getSerializedSize( + number, unsafe.getObject(message, offset), getMapFieldDefaultEntry(i)); + break; + case 51: // ONEOF_DOUBLE: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeDoubleSize(number, 0); + } + break; + case 52: // ONEOF_FLOAT: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeFloatSize(number, 0); + } + break; + case 53: // ONEOF_INT64: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeInt64Size(number, oneofLongAt(message, offset)); + } + break; + case 54: // ONEOF_UINT64: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeUInt64Size(number, oneofLongAt(message, offset)); + } + break; + case 55: // ONEOF_INT32: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeInt32Size(number, oneofIntAt(message, offset)); + } + break; + case 56: // ONEOF_FIXED64: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeFixed64Size(number, 0); + } + break; + case 57: // ONEOF_FIXED32: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeFixed32Size(number, 0); + } + break; + case 58: // ONEOF_BOOL: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeBoolSize(number, true); + } + break; + case 59: // ONEOF_STRING: + if (isOneofPresent(message, number, i)) { + Object value = unsafe.getObject(message, offset); + if (value instanceof ByteString) { + size += CodedOutputStream.computeBytesSize(number, (ByteString) value); + } else { + size += CodedOutputStream.computeStringSize(number, (String) value); + } + } + break; + case 60: // ONEOF_MESSAGE: + if (isOneofPresent(message, number, i)) { + Object value = unsafe.getObject(message, offset); + size += SchemaUtil.computeSizeMessage(number, value, getMessageFieldSchema(i)); + } + break; + case 61: // ONEOF_BYTES: + if (isOneofPresent(message, number, i)) { + size += + CodedOutputStream.computeBytesSize( + number, (ByteString) unsafe.getObject(message, offset)); + } + break; + case 62: // ONEOF_UINT32: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeUInt32Size(number, oneofIntAt(message, offset)); + } + break; + case 63: // ONEOF_ENUM: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeEnumSize(number, oneofIntAt(message, offset)); + } + break; + case 64: // ONEOF_SFIXED32: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeSFixed32Size(number, 0); + } + break; + case 65: // ONEOF_SFIXED64: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeSFixed64Size(number, 0); + } + break; + case 66: // ONEOF_SINT32: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeSInt32Size(number, oneofIntAt(message, offset)); + } + break; + case 67: // ONEOF_SINT64: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeSInt64Size(number, oneofLongAt(message, offset)); + } + break; + case 68: // ONEOF_GROUP: + if (isOneofPresent(message, number, i)) { + size += + CodedOutputStream.computeGroupSize( + number, + (MessageLite) unsafe.getObject(message, offset), + getMessageFieldSchema(i)); + } + break; + default: + // Assume it's an empty entry. + } + } + + size += getUnknownFieldsSerializedSize(unknownFieldSchema, message); + + if (hasExtensions) { + size += extensionSchema.getExtensions(message).getSerializedSize(); + } + + return size; + } + + private int getSerializedSizeProto3(T message) { + final sun.misc.Unsafe unsafe = UNSAFE; + int size = 0; + for (int i = 0; i < buffer.length; i += INTS_PER_FIELD) { + final int typeAndOffset = typeAndOffsetAt(i); + final int fieldType = type(typeAndOffset); + final int number = numberAt(i); + + final long offset = offset(typeAndOffset); + final int cachedSizeOffset = + fieldType >= FieldType.DOUBLE_LIST_PACKED.id() + && fieldType <= FieldType.SINT64_LIST_PACKED.id() + ? buffer[i + 2] & OFFSET_MASK + : 0; + + switch (fieldType) { + case 0: // DOUBLE: + if (isFieldPresent(message, i)) { + size += CodedOutputStream.computeDoubleSize(number, 0); + } + break; + case 1: // FLOAT: + if (isFieldPresent(message, i)) { + size += CodedOutputStream.computeFloatSize(number, 0); + } + break; + case 2: // INT64: + if (isFieldPresent(message, i)) { + size += CodedOutputStream.computeInt64Size(number, UnsafeUtil.getLong(message, offset)); + } + break; + case 3: // UINT64: + if (isFieldPresent(message, i)) { + size += + CodedOutputStream.computeUInt64Size(number, UnsafeUtil.getLong(message, offset)); + } + break; + case 4: // INT32: + if (isFieldPresent(message, i)) { + size += CodedOutputStream.computeInt32Size(number, UnsafeUtil.getInt(message, offset)); + } + break; + case 5: // FIXED64: + if (isFieldPresent(message, i)) { + size += CodedOutputStream.computeFixed64Size(number, 0); + } + break; + case 6: // FIXED32: + if (isFieldPresent(message, i)) { + size += CodedOutputStream.computeFixed32Size(number, 0); + } + break; + case 7: // BOOL: + if (isFieldPresent(message, i)) { + size += CodedOutputStream.computeBoolSize(number, true); + } + break; + case 8: // STRING: + if (isFieldPresent(message, i)) { + Object value = UnsafeUtil.getObject(message, offset); + if (value instanceof ByteString) { + size += CodedOutputStream.computeBytesSize(number, (ByteString) value); + } else { + size += CodedOutputStream.computeStringSize(number, (String) value); + } + } + break; + case 9: // MESSAGE: + if (isFieldPresent(message, i)) { + Object value = UnsafeUtil.getObject(message, offset); + size += SchemaUtil.computeSizeMessage(number, value, getMessageFieldSchema(i)); + } + break; + case 10: // BYTES: + if (isFieldPresent(message, i)) { + ByteString value = (ByteString) UnsafeUtil.getObject(message, offset); + size += CodedOutputStream.computeBytesSize(number, value); + } + break; + case 11: // UINT32: + if (isFieldPresent(message, i)) { + size += CodedOutputStream.computeUInt32Size(number, UnsafeUtil.getInt(message, offset)); + } + break; + case 12: // ENUM: + if (isFieldPresent(message, i)) { + size += CodedOutputStream.computeEnumSize(number, UnsafeUtil.getInt(message, offset)); + } + break; + case 13: // SFIXED32: + if (isFieldPresent(message, i)) { + size += CodedOutputStream.computeSFixed32Size(number, 0); + } + break; + case 14: // SFIXED64: + if (isFieldPresent(message, i)) { + size += CodedOutputStream.computeSFixed64Size(number, 0); + } + break; + case 15: // SINT32: + if (isFieldPresent(message, i)) { + size += CodedOutputStream.computeSInt32Size(number, UnsafeUtil.getInt(message, offset)); + } + break; + case 16: // SINT64: + if (isFieldPresent(message, i)) { + size += + CodedOutputStream.computeSInt64Size(number, UnsafeUtil.getLong(message, offset)); + } + break; + case 17: // GROUP: + if (isFieldPresent(message, i)) { + size += + CodedOutputStream.computeGroupSize( + number, + (MessageLite) UnsafeUtil.getObject(message, offset), + getMessageFieldSchema(i)); + } + break; + case 18: // DOUBLE_LIST: + size += SchemaUtil.computeSizeFixed64List(number, listAt(message, offset), false); + break; + case 19: // FLOAT_LIST: + size += SchemaUtil.computeSizeFixed32List(number, listAt(message, offset), false); + break; + case 20: // INT64_LIST: + size += + SchemaUtil.computeSizeInt64List(number, (List) listAt(message, offset), false); + break; + case 21: // UINT64_LIST: + size += + SchemaUtil.computeSizeUInt64List(number, (List) listAt(message, offset), false); + break; + case 22: // INT32_LIST: + size += + SchemaUtil.computeSizeInt32List( + number, (List) listAt(message, offset), false); + break; + case 23: // FIXED64_LIST: + size += SchemaUtil.computeSizeFixed64List(number, listAt(message, offset), false); + break; + case 24: // FIXED32_LIST: + size += SchemaUtil.computeSizeFixed32List(number, listAt(message, offset), false); + break; + case 25: // BOOL_LIST: + size += SchemaUtil.computeSizeBoolList(number, listAt(message, offset), false); + break; + case 26: // STRING_LIST: + size += SchemaUtil.computeSizeStringList(number, listAt(message, offset)); + break; + case 27: // MESSAGE_LIST: + size += + SchemaUtil.computeSizeMessageList( + number, listAt(message, offset), getMessageFieldSchema(i)); + break; + case 28: // BYTES_LIST: + size += + SchemaUtil.computeSizeByteStringList( + number, (List) listAt(message, offset)); + break; + case 29: // UINT32_LIST: + size += + SchemaUtil.computeSizeUInt32List( + number, (List) listAt(message, offset), false); + break; + case 30: // ENUM_LIST: + size += + SchemaUtil.computeSizeEnumList( + number, (List) listAt(message, offset), false); + break; + case 31: // SFIXED32_LIST: + size += SchemaUtil.computeSizeFixed32List(number, listAt(message, offset), false); + break; + case 32: // SFIXED64_LIST: + size += SchemaUtil.computeSizeFixed64List(number, listAt(message, offset), false); + break; + case 33: // SINT32_LIST: + size += + SchemaUtil.computeSizeSInt32List( + number, (List) listAt(message, offset), false); + break; + case 34: // SINT64_LIST: + size += + SchemaUtil.computeSizeSInt64List(number, (List) listAt(message, offset), false); + break; + case 35: + { // DOUBLE_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeFixed64ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) cachedSizeOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 36: + { // FLOAT_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeFixed32ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) cachedSizeOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 37: + { // INT64_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeInt64ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) cachedSizeOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 38: + { // UINT64_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeUInt64ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) cachedSizeOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 39: + { // INT32_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeInt32ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) cachedSizeOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 40: + { // FIXED64_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeFixed64ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) cachedSizeOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 41: + { // FIXED32_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeFixed32ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) cachedSizeOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 42: + { // BOOL_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeBoolListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) cachedSizeOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 43: + { // UINT32_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeUInt32ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) cachedSizeOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 44: + { // ENUM_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeEnumListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) cachedSizeOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 45: + { // SFIXED32_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeFixed32ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) cachedSizeOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 46: + { // SFIXED64_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeFixed64ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) cachedSizeOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 47: + { // SINT32_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeSInt32ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) cachedSizeOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 48: + { // SINT64_LIST_PACKED: + int fieldSize = + SchemaUtil.computeSizeSInt64ListNoTag( + (List) unsafe.getObject(message, offset)); + if (fieldSize > 0) { + if (useCachedSizeField) { + unsafe.putInt(message, (long) cachedSizeOffset, fieldSize); + } + size += + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeUInt32SizeNoTag(fieldSize) + + fieldSize; + } + break; + } + case 49: // GROUP_LIST: + size += + SchemaUtil.computeSizeGroupList( + number, (List) listAt(message, offset), getMessageFieldSchema(i)); + break; + case 50: // MAP: + // TODO(dweis): Use schema cache. + size += + mapFieldSchema.getSerializedSize( + number, UnsafeUtil.getObject(message, offset), getMapFieldDefaultEntry(i)); + break; + case 51: // ONEOF_DOUBLE: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeDoubleSize(number, 0); + } + break; + case 52: // ONEOF_FLOAT: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeFloatSize(number, 0); + } + break; + case 53: // ONEOF_INT64: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeInt64Size(number, oneofLongAt(message, offset)); + } + break; + case 54: // ONEOF_UINT64: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeUInt64Size(number, oneofLongAt(message, offset)); + } + break; + case 55: // ONEOF_INT32: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeInt32Size(number, oneofIntAt(message, offset)); + } + break; + case 56: // ONEOF_FIXED64: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeFixed64Size(number, 0); + } + break; + case 57: // ONEOF_FIXED32: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeFixed32Size(number, 0); + } + break; + case 58: // ONEOF_BOOL: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeBoolSize(number, true); + } + break; + case 59: // ONEOF_STRING: + if (isOneofPresent(message, number, i)) { + Object value = UnsafeUtil.getObject(message, offset); + if (value instanceof ByteString) { + size += CodedOutputStream.computeBytesSize(number, (ByteString) value); + } else { + size += CodedOutputStream.computeStringSize(number, (String) value); + } + } + break; + case 60: // ONEOF_MESSAGE: + if (isOneofPresent(message, number, i)) { + Object value = UnsafeUtil.getObject(message, offset); + size += SchemaUtil.computeSizeMessage(number, value, getMessageFieldSchema(i)); + } + break; + case 61: // ONEOF_BYTES: + if (isOneofPresent(message, number, i)) { + size += + CodedOutputStream.computeBytesSize( + number, (ByteString) UnsafeUtil.getObject(message, offset)); + } + break; + case 62: // ONEOF_UINT32: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeUInt32Size(number, oneofIntAt(message, offset)); + } + break; + case 63: // ONEOF_ENUM: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeEnumSize(number, oneofIntAt(message, offset)); + } + break; + case 64: // ONEOF_SFIXED32: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeSFixed32Size(number, 0); + } + break; + case 65: // ONEOF_SFIXED64: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeSFixed64Size(number, 0); + } + break; + case 66: // ONEOF_SINT32: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeSInt32Size(number, oneofIntAt(message, offset)); + } + break; + case 67: // ONEOF_SINT64: + if (isOneofPresent(message, number, i)) { + size += CodedOutputStream.computeSInt64Size(number, oneofLongAt(message, offset)); + } + break; + case 68: // ONEOF_GROUP: + if (isOneofPresent(message, number, i)) { + size += + CodedOutputStream.computeGroupSize( + number, + (MessageLite) UnsafeUtil.getObject(message, offset), + getMessageFieldSchema(i)); + } + break; + default: + // Assume it's an empty entry. + } + } + + size += getUnknownFieldsSerializedSize(unknownFieldSchema, message); + + return size; + } + + private int getUnknownFieldsSerializedSize( + UnknownFieldSchema schema, T message) { + UT unknowns = schema.getFromMessage(message); + return schema.getSerializedSize(unknowns); + } + + private static List listAt(Object message, long offset) { + return (List) UnsafeUtil.getObject(message, offset); + } + + @SuppressWarnings("unchecked") + @Override + // TODO(nathanmittler): Consider serializing oneof fields last so that only one entry per + // oneof is actually serialized. This would mean that we would violate the serialization order + // contract. It should also be noted that Go currently does this. + public void writeTo(T message, Writer writer) throws IOException { + if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) { + writeFieldsInDescendingOrder(message, writer); + } else { + if (proto3) { + writeFieldsInAscendingOrderProto3(message, writer); + } else { + writeFieldsInAscendingOrderProto2(message, writer); + } + } + } + + @SuppressWarnings("unchecked") + private void writeFieldsInAscendingOrderProto2(T message, Writer writer) throws IOException { + Iterator> extensionIterator = null; + Map.Entry nextExtension = null; + if (hasExtensions) { + FieldSet extensions = extensionSchema.getExtensions(message); + if (!extensions.isEmpty()) { + extensionIterator = extensions.iterator(); + nextExtension = extensionIterator.next(); + } + } + int currentPresenceFieldOffset = NO_PRESENCE_SENTINEL; + int currentPresenceField = 0; + final int bufferLength = buffer.length; + final sun.misc.Unsafe unsafe = UNSAFE; + for (int pos = 0; pos < bufferLength; pos += INTS_PER_FIELD) { + final int typeAndOffset = typeAndOffsetAt(pos); + final int number = numberAt(pos); + final int fieldType = type(typeAndOffset); + + int presenceMaskAndOffset = 0; + int presenceMask = 0; + if (fieldType <= 17) { + presenceMaskAndOffset = buffer[pos + 2]; + final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK; + if (presenceFieldOffset != currentPresenceFieldOffset) { + currentPresenceFieldOffset = presenceFieldOffset; + currentPresenceField = unsafe.getInt(message, (long) presenceFieldOffset); + } + presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS); + } + + // Write any extensions that need to be written before the current field. + while (nextExtension != null && extensionSchema.extensionNumber(nextExtension) <= number) { + extensionSchema.serializeExtension(writer, nextExtension); + nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null; + } + final long offset = offset(typeAndOffset); + + switch (fieldType) { + case 0: // DOUBLE: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeDouble(number, doubleAt(message, offset)); + } + break; + case 1: // FLOAT: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeFloat(number, floatAt(message, offset)); + } + break; + case 2: // INT64: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeInt64(number, unsafe.getLong(message, offset)); + } + break; + case 3: // UINT64: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeUInt64(number, unsafe.getLong(message, offset)); + } + break; + case 4: // INT32: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeInt32(number, unsafe.getInt(message, offset)); + } + break; + case 5: // FIXED64: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeFixed64(number, unsafe.getLong(message, offset)); + } + break; + case 6: // FIXED32: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeFixed32(number, unsafe.getInt(message, offset)); + } + break; + case 7: // BOOL: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeBool(number, booleanAt(message, offset)); + } + break; + case 8: // STRING: + if ((currentPresenceField & presenceMask) != 0) { + writeString(number, unsafe.getObject(message, offset), writer); + } + break; + case 9: // MESSAGE: + if ((currentPresenceField & presenceMask) != 0) { + Object value = unsafe.getObject(message, offset); + writer.writeMessage(number, value, getMessageFieldSchema(pos)); + } + break; + case 10: // BYTES: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeBytes(number, (ByteString) unsafe.getObject(message, offset)); + } + break; + case 11: // UINT32: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeUInt32(number, unsafe.getInt(message, offset)); + } + break; + case 12: // ENUM: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeEnum(number, unsafe.getInt(message, offset)); + } + break; + case 13: // SFIXED32: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeSFixed32(number, unsafe.getInt(message, offset)); + } + break; + case 14: // SFIXED64: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeSFixed64(number, unsafe.getLong(message, offset)); + } + break; + case 15: // SINT32: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeSInt32(number, unsafe.getInt(message, offset)); + } + break; + case 16: // SINT64: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeSInt64(number, unsafe.getLong(message, offset)); + } + break; + case 17: // GROUP: + if ((currentPresenceField & presenceMask) != 0) { + writer.writeGroup( + number, unsafe.getObject(message, offset), getMessageFieldSchema(pos)); + } + break; + case 18: // DOUBLE_LIST: + SchemaUtil.writeDoubleList( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, false); + break; + case 19: // FLOAT_LIST: + SchemaUtil.writeFloatList( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, false); + break; + case 20: // INT64_LIST: + SchemaUtil.writeInt64List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, false); + break; + case 21: // UINT64_LIST: + SchemaUtil.writeUInt64List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, false); + break; + case 22: // INT32_LIST: + SchemaUtil.writeInt32List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, false); + break; + case 23: // FIXED64_LIST: + SchemaUtil.writeFixed64List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, false); + break; + case 24: // FIXED32_LIST: + SchemaUtil.writeFixed32List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, false); + break; + case 25: // BOOL_LIST: + SchemaUtil.writeBoolList( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, false); + break; + case 26: // STRING_LIST: + SchemaUtil.writeStringList( + numberAt(pos), (List) unsafe.getObject(message, offset), writer); + break; + case 27: // MESSAGE_LIST: + SchemaUtil.writeMessageList( + numberAt(pos), + (List) unsafe.getObject(message, offset), + writer, + getMessageFieldSchema(pos)); + break; + case 28: // BYTES_LIST: + SchemaUtil.writeBytesList( + numberAt(pos), (List) unsafe.getObject(message, offset), writer); + break; + case 29: // UINT32_LIST: + SchemaUtil.writeUInt32List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, false); + break; + case 30: // ENUM_LIST: + SchemaUtil.writeEnumList( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, false); + break; + case 31: // SFIXED32_LIST: + SchemaUtil.writeSFixed32List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, false); + break; + case 32: // SFIXED64_LIST: + SchemaUtil.writeSFixed64List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, false); + break; + case 33: // SINT32_LIST: + SchemaUtil.writeSInt32List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, false); + break; + case 34: // SINT64_LIST: + SchemaUtil.writeSInt64List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, false); + break; + case 35: // DOUBLE_LIST_PACKED: + // TODO(xiaofeng): Make use of cached field size to speed up serialization. + SchemaUtil.writeDoubleList( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, true); + break; + case 36: // FLOAT_LIST_PACKED: + SchemaUtil.writeFloatList( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, true); + break; + case 37: // INT64_LIST_PACKED: + SchemaUtil.writeInt64List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, true); + break; + case 38: // UINT64_LIST_PACKED: + SchemaUtil.writeUInt64List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, true); + break; + case 39: // INT32_LIST_PACKED: + SchemaUtil.writeInt32List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, true); + break; + case 40: // FIXED64_LIST_PACKED: + SchemaUtil.writeFixed64List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, true); + break; + case 41: // FIXED32_LIST_PACKED: + SchemaUtil.writeFixed32List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, true); + + break; + case 42: // BOOL_LIST_PACKED: + SchemaUtil.writeBoolList( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, true); + break; + case 43: // UINT32_LIST_PACKED: + SchemaUtil.writeUInt32List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, true); + break; + case 44: // ENUM_LIST_PACKED: + SchemaUtil.writeEnumList( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, true); + break; + case 45: // SFIXED32_LIST_PACKED: + SchemaUtil.writeSFixed32List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, true); + break; + case 46: // SFIXED64_LIST_PACKED: + SchemaUtil.writeSFixed64List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, true); + break; + case 47: // SINT32_LIST_PACKED: + SchemaUtil.writeSInt32List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, true); + break; + case 48: // SINT64_LIST_PACKED: + SchemaUtil.writeSInt64List( + numberAt(pos), (List) unsafe.getObject(message, offset), writer, true); + break; + case 49: // GROUP_LIST: + SchemaUtil.writeGroupList( + numberAt(pos), + (List) unsafe.getObject(message, offset), + writer, + getMessageFieldSchema(pos)); + break; + case 50: // MAP: + // TODO(dweis): Use schema cache. + writeMapHelper(writer, number, unsafe.getObject(message, offset), pos); + break; + case 51: // ONEOF_DOUBLE: + if (isOneofPresent(message, number, pos)) { + writer.writeDouble(number, oneofDoubleAt(message, offset)); + } + break; + case 52: // ONEOF_FLOAT: + if (isOneofPresent(message, number, pos)) { + writer.writeFloat(number, oneofFloatAt(message, offset)); + } + break; + case 53: // ONEOF_INT64: + if (isOneofPresent(message, number, pos)) { + writer.writeInt64(number, oneofLongAt(message, offset)); + } + break; + case 54: // ONEOF_UINT64: + if (isOneofPresent(message, number, pos)) { + writer.writeUInt64(number, oneofLongAt(message, offset)); + } + break; + case 55: // ONEOF_INT32: + if (isOneofPresent(message, number, pos)) { + writer.writeInt32(number, oneofIntAt(message, offset)); + } + break; + case 56: // ONEOF_FIXED64: + if (isOneofPresent(message, number, pos)) { + writer.writeFixed64(number, oneofLongAt(message, offset)); + } + break; + case 57: // ONEOF_FIXED32: + if (isOneofPresent(message, number, pos)) { + writer.writeFixed32(number, oneofIntAt(message, offset)); + } + break; + case 58: // ONEOF_BOOL: + if (isOneofPresent(message, number, pos)) { + writer.writeBool(number, oneofBooleanAt(message, offset)); + } + break; + case 59: // ONEOF_STRING: + if (isOneofPresent(message, number, pos)) { + writeString(number, unsafe.getObject(message, offset), writer); + } + break; + case 60: // ONEOF_MESSAGE: + if (isOneofPresent(message, number, pos)) { + Object value = unsafe.getObject(message, offset); + writer.writeMessage(number, value, getMessageFieldSchema(pos)); + } + break; + case 61: // ONEOF_BYTES: + if (isOneofPresent(message, number, pos)) { + writer.writeBytes(number, (ByteString) unsafe.getObject(message, offset)); + } + break; + case 62: // ONEOF_UINT32: + if (isOneofPresent(message, number, pos)) { + writer.writeUInt32(number, oneofIntAt(message, offset)); + } + break; + case 63: // ONEOF_ENUM: + if (isOneofPresent(message, number, pos)) { + writer.writeEnum(number, oneofIntAt(message, offset)); + } + break; + case 64: // ONEOF_SFIXED32: + if (isOneofPresent(message, number, pos)) { + writer.writeSFixed32(number, oneofIntAt(message, offset)); + } + break; + case 65: // ONEOF_SFIXED64: + if (isOneofPresent(message, number, pos)) { + writer.writeSFixed64(number, oneofLongAt(message, offset)); + } + break; + case 66: // ONEOF_SINT32: + if (isOneofPresent(message, number, pos)) { + writer.writeSInt32(number, oneofIntAt(message, offset)); + } + break; + case 67: // ONEOF_SINT64: + if (isOneofPresent(message, number, pos)) { + writer.writeSInt64(number, oneofLongAt(message, offset)); + } + break; + case 68: // ONEOF_GROUP: + if (isOneofPresent(message, number, pos)) { + writer.writeGroup( + number, unsafe.getObject(message, offset), getMessageFieldSchema(pos)); + } + break; + default: + // Assume it's an empty entry - just go to the next entry. + break; + } + } + while (nextExtension != null) { + extensionSchema.serializeExtension(writer, nextExtension); + nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null; + } + writeUnknownInMessageTo(unknownFieldSchema, message, writer); + } + + @SuppressWarnings("unchecked") + private void writeFieldsInAscendingOrderProto3(T message, Writer writer) throws IOException { + Iterator> extensionIterator = null; + Map.Entry nextExtension = null; + if (hasExtensions) { + FieldSet extensions = extensionSchema.getExtensions(message); + if (!extensions.isEmpty()) { + extensionIterator = extensions.iterator(); + nextExtension = extensionIterator.next(); + } + } + final int bufferLength = buffer.length; + for (int pos = 0; pos < bufferLength; pos += INTS_PER_FIELD) { + final int typeAndOffset = typeAndOffsetAt(pos); + final int number = numberAt(pos); + + // Write any extensions that need to be written before the current field. + while (nextExtension != null && extensionSchema.extensionNumber(nextExtension) <= number) { + extensionSchema.serializeExtension(writer, nextExtension); + nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null; + } + + switch (type(typeAndOffset)) { + case 0: // DOUBLE: + if (isFieldPresent(message, pos)) { + writer.writeDouble(number, doubleAt(message, offset(typeAndOffset))); + } + break; + case 1: // FLOAT: + if (isFieldPresent(message, pos)) { + writer.writeFloat(number, floatAt(message, offset(typeAndOffset))); + } + break; + case 2: // INT64: + if (isFieldPresent(message, pos)) { + writer.writeInt64(number, longAt(message, offset(typeAndOffset))); + } + break; + case 3: // UINT64: + if (isFieldPresent(message, pos)) { + writer.writeUInt64(number, longAt(message, offset(typeAndOffset))); + } + break; + case 4: // INT32: + if (isFieldPresent(message, pos)) { + writer.writeInt32(number, intAt(message, offset(typeAndOffset))); + } + break; + case 5: // FIXED64: + if (isFieldPresent(message, pos)) { + writer.writeFixed64(number, longAt(message, offset(typeAndOffset))); + } + break; + case 6: // FIXED32: + if (isFieldPresent(message, pos)) { + writer.writeFixed32(number, intAt(message, offset(typeAndOffset))); + } + break; + case 7: // BOOL: + if (isFieldPresent(message, pos)) { + writer.writeBool(number, booleanAt(message, offset(typeAndOffset))); + } + break; + case 8: // STRING: + if (isFieldPresent(message, pos)) { + writeString(number, UnsafeUtil.getObject(message, offset(typeAndOffset)), writer); + } + break; + case 9: // MESSAGE: + if (isFieldPresent(message, pos)) { + Object value = UnsafeUtil.getObject(message, offset(typeAndOffset)); + writer.writeMessage(number, value, getMessageFieldSchema(pos)); + } + break; + case 10: // BYTES: + if (isFieldPresent(message, pos)) { + writer.writeBytes( + number, (ByteString) UnsafeUtil.getObject(message, offset(typeAndOffset))); + } + break; + case 11: // UINT32: + if (isFieldPresent(message, pos)) { + writer.writeUInt32(number, intAt(message, offset(typeAndOffset))); + } + break; + case 12: // ENUM: + if (isFieldPresent(message, pos)) { + writer.writeEnum(number, intAt(message, offset(typeAndOffset))); + } + break; + case 13: // SFIXED32: + if (isFieldPresent(message, pos)) { + writer.writeSFixed32(number, intAt(message, offset(typeAndOffset))); + } + break; + case 14: // SFIXED64: + if (isFieldPresent(message, pos)) { + writer.writeSFixed64(number, longAt(message, offset(typeAndOffset))); + } + break; + case 15: // SINT32: + if (isFieldPresent(message, pos)) { + writer.writeSInt32(number, intAt(message, offset(typeAndOffset))); + } + break; + case 16: // SINT64: + if (isFieldPresent(message, pos)) { + writer.writeSInt64(number, longAt(message, offset(typeAndOffset))); + } + break; + case 17: // GROUP: + if (isFieldPresent(message, pos)) { + writer.writeGroup( + number, + UnsafeUtil.getObject(message, offset(typeAndOffset)), + getMessageFieldSchema(pos)); + } + break; + case 18: // DOUBLE_LIST: + SchemaUtil.writeDoubleList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 19: // FLOAT_LIST: + SchemaUtil.writeFloatList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 20: // INT64_LIST: + SchemaUtil.writeInt64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 21: // UINT64_LIST: + SchemaUtil.writeUInt64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 22: // INT32_LIST: + SchemaUtil.writeInt32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 23: // FIXED64_LIST: + SchemaUtil.writeFixed64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 24: // FIXED32_LIST: + SchemaUtil.writeFixed32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 25: // BOOL_LIST: + SchemaUtil.writeBoolList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 26: // STRING_LIST: + SchemaUtil.writeStringList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer); + break; + case 27: // MESSAGE_LIST: + SchemaUtil.writeMessageList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + getMessageFieldSchema(pos)); + break; + case 28: // BYTES_LIST: + SchemaUtil.writeBytesList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer); + break; + case 29: // UINT32_LIST: + SchemaUtil.writeUInt32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 30: // ENUM_LIST: + SchemaUtil.writeEnumList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 31: // SFIXED32_LIST: + SchemaUtil.writeSFixed32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 32: // SFIXED64_LIST: + SchemaUtil.writeSFixed64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 33: // SINT32_LIST: + SchemaUtil.writeSInt32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 34: // SINT64_LIST: + SchemaUtil.writeSInt64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 35: // DOUBLE_LIST_PACKED: + // TODO(xiaofeng): Make use of cached field size to speed up serialization. + SchemaUtil.writeDoubleList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 36: // FLOAT_LIST_PACKED: + SchemaUtil.writeFloatList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 37: // INT64_LIST_PACKED: + SchemaUtil.writeInt64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 38: // UINT64_LIST_PACKED: + SchemaUtil.writeUInt64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 39: // INT32_LIST_PACKED: + SchemaUtil.writeInt32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 40: // FIXED64_LIST_PACKED: + SchemaUtil.writeFixed64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 41: // FIXED32_LIST_PACKED: + SchemaUtil.writeFixed32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + + break; + case 42: // BOOL_LIST_PACKED: + SchemaUtil.writeBoolList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 43: // UINT32_LIST_PACKED: + SchemaUtil.writeUInt32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 44: // ENUM_LIST_PACKED: + SchemaUtil.writeEnumList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 45: // SFIXED32_LIST_PACKED: + SchemaUtil.writeSFixed32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 46: // SFIXED64_LIST_PACKED: + SchemaUtil.writeSFixed64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 47: // SINT32_LIST_PACKED: + SchemaUtil.writeSInt32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 48: // SINT64_LIST_PACKED: + SchemaUtil.writeSInt64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 49: // GROUP_LIST: + SchemaUtil.writeGroupList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + getMessageFieldSchema(pos)); + break; + case 50: // MAP: + // TODO(dweis): Use schema cache. + writeMapHelper(writer, number, UnsafeUtil.getObject(message, offset(typeAndOffset)), pos); + break; + case 51: // ONEOF_DOUBLE: + if (isOneofPresent(message, number, pos)) { + writer.writeDouble(number, oneofDoubleAt(message, offset(typeAndOffset))); + } + break; + case 52: // ONEOF_FLOAT: + if (isOneofPresent(message, number, pos)) { + writer.writeFloat(number, oneofFloatAt(message, offset(typeAndOffset))); + } + break; + case 53: // ONEOF_INT64: + if (isOneofPresent(message, number, pos)) { + writer.writeInt64(number, oneofLongAt(message, offset(typeAndOffset))); + } + break; + case 54: // ONEOF_UINT64: + if (isOneofPresent(message, number, pos)) { + writer.writeUInt64(number, oneofLongAt(message, offset(typeAndOffset))); + } + break; + case 55: // ONEOF_INT32: + if (isOneofPresent(message, number, pos)) { + writer.writeInt32(number, oneofIntAt(message, offset(typeAndOffset))); + } + break; + case 56: // ONEOF_FIXED64: + if (isOneofPresent(message, number, pos)) { + writer.writeFixed64(number, oneofLongAt(message, offset(typeAndOffset))); + } + break; + case 57: // ONEOF_FIXED32: + if (isOneofPresent(message, number, pos)) { + writer.writeFixed32(number, oneofIntAt(message, offset(typeAndOffset))); + } + break; + case 58: // ONEOF_BOOL: + if (isOneofPresent(message, number, pos)) { + writer.writeBool(number, oneofBooleanAt(message, offset(typeAndOffset))); + } + break; + case 59: // ONEOF_STRING: + if (isOneofPresent(message, number, pos)) { + writeString(number, UnsafeUtil.getObject(message, offset(typeAndOffset)), writer); + } + break; + case 60: // ONEOF_MESSAGE: + if (isOneofPresent(message, number, pos)) { + Object value = UnsafeUtil.getObject(message, offset(typeAndOffset)); + writer.writeMessage(number, value, getMessageFieldSchema(pos)); + } + break; + case 61: // ONEOF_BYTES: + if (isOneofPresent(message, number, pos)) { + writer.writeBytes( + number, (ByteString) UnsafeUtil.getObject(message, offset(typeAndOffset))); + } + break; + case 62: // ONEOF_UINT32: + if (isOneofPresent(message, number, pos)) { + writer.writeUInt32(number, oneofIntAt(message, offset(typeAndOffset))); + } + break; + case 63: // ONEOF_ENUM: + if (isOneofPresent(message, number, pos)) { + writer.writeEnum(number, oneofIntAt(message, offset(typeAndOffset))); + } + break; + case 64: // ONEOF_SFIXED32: + if (isOneofPresent(message, number, pos)) { + writer.writeSFixed32(number, oneofIntAt(message, offset(typeAndOffset))); + } + break; + case 65: // ONEOF_SFIXED64: + if (isOneofPresent(message, number, pos)) { + writer.writeSFixed64(number, oneofLongAt(message, offset(typeAndOffset))); + } + break; + case 66: // ONEOF_SINT32: + if (isOneofPresent(message, number, pos)) { + writer.writeSInt32(number, oneofIntAt(message, offset(typeAndOffset))); + } + break; + case 67: // ONEOF_SINT64: + if (isOneofPresent(message, number, pos)) { + writer.writeSInt64(number, oneofLongAt(message, offset(typeAndOffset))); + } + break; + case 68: // ONEOF_GROUP: + if (isOneofPresent(message, number, pos)) { + writer.writeGroup( + number, + UnsafeUtil.getObject(message, offset(typeAndOffset)), + getMessageFieldSchema(pos)); + } + break; + default: + // Assume it's an empty entry - just go to the next entry. + break; + } + } + while (nextExtension != null) { + extensionSchema.serializeExtension(writer, nextExtension); + nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null; + } + writeUnknownInMessageTo(unknownFieldSchema, message, writer); + } + + @SuppressWarnings("unchecked") + private void writeFieldsInDescendingOrder(T message, Writer writer) throws IOException { + writeUnknownInMessageTo(unknownFieldSchema, message, writer); + + Iterator> extensionIterator = null; + Map.Entry nextExtension = null; + if (hasExtensions) { + FieldSet extensions = extensionSchema.getExtensions(message); + if (!extensions.isEmpty()) { + extensionIterator = extensions.descendingIterator(); + nextExtension = extensionIterator.next(); + } + } + + for (int pos = buffer.length - INTS_PER_FIELD; pos >= 0; pos -= INTS_PER_FIELD) { + final int typeAndOffset = typeAndOffsetAt(pos); + final int number = numberAt(pos); + + // Write any extensions that need to be written before the current field. + while (nextExtension != null && extensionSchema.extensionNumber(nextExtension) > number) { + extensionSchema.serializeExtension(writer, nextExtension); + nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null; + } + + switch (type(typeAndOffset)) { + case 0: // DOUBLE: + if (isFieldPresent(message, pos)) { + writer.writeDouble(number, doubleAt(message, offset(typeAndOffset))); + } + break; + case 1: // FLOAT: + if (isFieldPresent(message, pos)) { + writer.writeFloat(number, floatAt(message, offset(typeAndOffset))); + } + break; + case 2: // INT64: + if (isFieldPresent(message, pos)) { + writer.writeInt64(number, longAt(message, offset(typeAndOffset))); + } + break; + case 3: // UINT64: + if (isFieldPresent(message, pos)) { + writer.writeUInt64(number, longAt(message, offset(typeAndOffset))); + } + break; + case 4: // INT32: + if (isFieldPresent(message, pos)) { + writer.writeInt32(number, intAt(message, offset(typeAndOffset))); + } + break; + case 5: // FIXED64: + if (isFieldPresent(message, pos)) { + writer.writeFixed64(number, longAt(message, offset(typeAndOffset))); + } + break; + case 6: // FIXED32: + if (isFieldPresent(message, pos)) { + writer.writeFixed32(number, intAt(message, offset(typeAndOffset))); + } + break; + case 7: // BOOL: + if (isFieldPresent(message, pos)) { + writer.writeBool(number, booleanAt(message, offset(typeAndOffset))); + } + break; + case 8: // STRING: + if (isFieldPresent(message, pos)) { + writeString(number, UnsafeUtil.getObject(message, offset(typeAndOffset)), writer); + } + break; + case 9: // MESSAGE: + if (isFieldPresent(message, pos)) { + Object value = UnsafeUtil.getObject(message, offset(typeAndOffset)); + writer.writeMessage(number, value, getMessageFieldSchema(pos)); + } + break; + case 10: // BYTES: + if (isFieldPresent(message, pos)) { + writer.writeBytes( + number, (ByteString) UnsafeUtil.getObject(message, offset(typeAndOffset))); + } + break; + case 11: // UINT32: + if (isFieldPresent(message, pos)) { + writer.writeUInt32(number, intAt(message, offset(typeAndOffset))); + } + break; + case 12: // ENUM: + if (isFieldPresent(message, pos)) { + writer.writeEnum(number, intAt(message, offset(typeAndOffset))); + } + break; + case 13: // SFIXED32: + if (isFieldPresent(message, pos)) { + writer.writeSFixed32(number, intAt(message, offset(typeAndOffset))); + } + break; + case 14: // SFIXED64: + if (isFieldPresent(message, pos)) { + writer.writeSFixed64(number, longAt(message, offset(typeAndOffset))); + } + break; + case 15: // SINT32: + if (isFieldPresent(message, pos)) { + writer.writeSInt32(number, intAt(message, offset(typeAndOffset))); + } + break; + case 16: // SINT64: + if (isFieldPresent(message, pos)) { + writer.writeSInt64(number, longAt(message, offset(typeAndOffset))); + } + break; + case 17: // GROUP: + if (isFieldPresent(message, pos)) { + writer.writeGroup( + number, + UnsafeUtil.getObject(message, offset(typeAndOffset)), + getMessageFieldSchema(pos)); + } + break; + case 18: // DOUBLE_LIST: + SchemaUtil.writeDoubleList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 19: // FLOAT_LIST: + SchemaUtil.writeFloatList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 20: // INT64_LIST: + SchemaUtil.writeInt64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 21: // UINT64_LIST: + SchemaUtil.writeUInt64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 22: // INT32_LIST: + SchemaUtil.writeInt32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 23: // FIXED64_LIST: + SchemaUtil.writeFixed64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 24: // FIXED32_LIST: + SchemaUtil.writeFixed32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 25: // BOOL_LIST: + SchemaUtil.writeBoolList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 26: // STRING_LIST: + SchemaUtil.writeStringList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer); + break; + case 27: // MESSAGE_LIST: + SchemaUtil.writeMessageList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + getMessageFieldSchema(pos)); + break; + case 28: // BYTES_LIST: + SchemaUtil.writeBytesList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer); + break; + case 29: // UINT32_LIST: + SchemaUtil.writeUInt32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 30: // ENUM_LIST: + SchemaUtil.writeEnumList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 31: // SFIXED32_LIST: + SchemaUtil.writeSFixed32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 32: // SFIXED64_LIST: + SchemaUtil.writeSFixed64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 33: // SINT32_LIST: + SchemaUtil.writeSInt32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 34: // SINT64_LIST: + SchemaUtil.writeSInt64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + false); + break; + case 35: // DOUBLE_LIST_PACKED: + SchemaUtil.writeDoubleList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 36: // FLOAT_LIST_PACKED: + SchemaUtil.writeFloatList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 37: // INT64_LIST_PACKED: + SchemaUtil.writeInt64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 38: // UINT64_LIST_PACKED: + SchemaUtil.writeUInt64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 39: // INT32_LIST_PACKED: + SchemaUtil.writeInt32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 40: // FIXED64_LIST_PACKED: + SchemaUtil.writeFixed64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 41: // FIXED32_LIST_PACKED: + SchemaUtil.writeFixed32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + + break; + case 42: // BOOL_LIST_PACKED: + SchemaUtil.writeBoolList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 43: // UINT32_LIST_PACKED: + SchemaUtil.writeUInt32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 44: // ENUM_LIST_PACKED: + SchemaUtil.writeEnumList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 45: // SFIXED32_LIST_PACKED: + SchemaUtil.writeSFixed32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 46: // SFIXED64_LIST_PACKED: + SchemaUtil.writeSFixed64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 47: // SINT32_LIST_PACKED: + SchemaUtil.writeSInt32List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 48: // SINT64_LIST_PACKED: + SchemaUtil.writeSInt64List( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + true); + break; + case 49: // GROUP_LIST: + SchemaUtil.writeGroupList( + numberAt(pos), + (List) UnsafeUtil.getObject(message, offset(typeAndOffset)), + writer, + getMessageFieldSchema(pos)); + break; + case 50: // MAP: + // TODO(dweis): Use schema cache. + writeMapHelper(writer, number, UnsafeUtil.getObject(message, offset(typeAndOffset)), pos); + break; + case 51: // ONEOF_DOUBLE: + if (isOneofPresent(message, number, pos)) { + writer.writeDouble(number, oneofDoubleAt(message, offset(typeAndOffset))); + } + break; + case 52: // ONEOF_FLOAT: + if (isOneofPresent(message, number, pos)) { + writer.writeFloat(number, oneofFloatAt(message, offset(typeAndOffset))); + } + break; + case 53: // ONEOF_INT64: + if (isOneofPresent(message, number, pos)) { + writer.writeInt64(number, oneofLongAt(message, offset(typeAndOffset))); + } + break; + case 54: // ONEOF_UINT64: + if (isOneofPresent(message, number, pos)) { + writer.writeUInt64(number, oneofLongAt(message, offset(typeAndOffset))); + } + break; + case 55: // ONEOF_INT32: + if (isOneofPresent(message, number, pos)) { + writer.writeInt32(number, oneofIntAt(message, offset(typeAndOffset))); + } + break; + case 56: // ONEOF_FIXED64: + if (isOneofPresent(message, number, pos)) { + writer.writeFixed64(number, oneofLongAt(message, offset(typeAndOffset))); + } + break; + case 57: // ONEOF_FIXED32: + if (isOneofPresent(message, number, pos)) { + writer.writeFixed32(number, oneofIntAt(message, offset(typeAndOffset))); + } + break; + case 58: // ONEOF_BOOL: + if (isOneofPresent(message, number, pos)) { + writer.writeBool(number, oneofBooleanAt(message, offset(typeAndOffset))); + } + break; + case 59: // ONEOF_STRING: + if (isOneofPresent(message, number, pos)) { + writeString(number, UnsafeUtil.getObject(message, offset(typeAndOffset)), writer); + } + break; + case 60: // ONEOF_MESSAGE: + if (isOneofPresent(message, number, pos)) { + Object value = UnsafeUtil.getObject(message, offset(typeAndOffset)); + writer.writeMessage(number, value, getMessageFieldSchema(pos)); + } + break; + case 61: // ONEOF_BYTES: + if (isOneofPresent(message, number, pos)) { + writer.writeBytes( + number, (ByteString) UnsafeUtil.getObject(message, offset(typeAndOffset))); + } + break; + case 62: // ONEOF_UINT32: + if (isOneofPresent(message, number, pos)) { + writer.writeUInt32(number, oneofIntAt(message, offset(typeAndOffset))); + } + break; + case 63: // ONEOF_ENUM: + if (isOneofPresent(message, number, pos)) { + writer.writeEnum(number, oneofIntAt(message, offset(typeAndOffset))); + } + break; + case 64: // ONEOF_SFIXED32: + if (isOneofPresent(message, number, pos)) { + writer.writeSFixed32(number, oneofIntAt(message, offset(typeAndOffset))); + } + break; + case 65: // ONEOF_SFIXED64: + if (isOneofPresent(message, number, pos)) { + writer.writeSFixed64(number, oneofLongAt(message, offset(typeAndOffset))); + } + break; + case 66: // ONEOF_SINT32: + if (isOneofPresent(message, number, pos)) { + writer.writeSInt32(number, oneofIntAt(message, offset(typeAndOffset))); + } + break; + case 67: // ONEOF_SINT64: + if (isOneofPresent(message, number, pos)) { + writer.writeSInt64(number, oneofLongAt(message, offset(typeAndOffset))); + } + break; + case 68: // ONEOF_GROUP: + if (isOneofPresent(message, number, pos)) { + writer.writeGroup( + number, + UnsafeUtil.getObject(message, offset(typeAndOffset)), + getMessageFieldSchema(pos)); + } + break; + default: + break; + } + } + while (nextExtension != null) { + extensionSchema.serializeExtension(writer, nextExtension); + nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null; + } + } + + @SuppressWarnings("unchecked") + private void writeMapHelper(Writer writer, int number, Object mapField, int pos) + throws IOException { + if (mapField != null) { + writer.writeMap( + number, + (MapEntryLite.Metadata) mapFieldSchema.forMapMetadata(getMapFieldDefaultEntry(pos)), + (Map) mapFieldSchema.forMapData(mapField)); + } + } + + private void writeUnknownInMessageTo( + UnknownFieldSchema schema, T message, Writer writer) throws IOException { + schema.writeTo(schema.getFromMessage(message), writer); + } + + @Override + public void mergeFrom(T message, Reader reader, ExtensionRegistryLite extensionRegistry) + throws IOException { + if (extensionRegistry == null) { + throw new NullPointerException(); + } + mergeFromHelper(unknownFieldSchema, extensionSchema, message, reader, extensionRegistry); + } + + /** + * A helper method for wildcard capture of {@code unknownFieldSchema}. See: + * https://docs.oracle.com/javase/tutorial/java/generics/capture.html + */ + private > void mergeFromHelper( + UnknownFieldSchema unknownFieldSchema, + ExtensionSchema extensionSchema, + T message, + Reader reader, + ExtensionRegistryLite extensionRegistry) + throws IOException { + UB unknownFields = null; + FieldSet extensions = null; + try { + while (true) { + final int number = reader.getFieldNumber(); + final int pos = positionForFieldNumber(number); + if (pos < 0) { + if (number == Reader.READ_DONE) { + return; + } + // Check if it's an extension. + Object extension = + !hasExtensions + ? null + : extensionSchema.findExtensionByNumber( + extensionRegistry, defaultInstance, number); + if (extension != null) { + if (extensions == null) { + extensions = extensionSchema.getMutableExtensions(message); + } + unknownFields = + extensionSchema.parseExtension( + reader, + extension, + extensionRegistry, + extensions, + unknownFields, + unknownFieldSchema); + continue; + } + if (unknownFieldSchema.shouldDiscardUnknownFields(reader)) { + if (reader.skipField()) { + continue; + } + } else { + if (unknownFields == null) { + unknownFields = unknownFieldSchema.getBuilderFromMessage(message); + } + // Unknown field. + if (unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) { + continue; + } + } + // Done reading. + return; + } + final int typeAndOffset = typeAndOffsetAt(pos); + + try { + switch (type(typeAndOffset)) { + case 0: // DOUBLE: + UnsafeUtil.putDouble(message, offset(typeAndOffset), reader.readDouble()); + setFieldPresent(message, pos); + break; + case 1: // FLOAT: + UnsafeUtil.putFloat(message, offset(typeAndOffset), reader.readFloat()); + setFieldPresent(message, pos); + break; + case 2: // INT64: + UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readInt64()); + setFieldPresent(message, pos); + break; + case 3: // UINT64: + UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readUInt64()); + setFieldPresent(message, pos); + break; + case 4: // INT32: + UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readInt32()); + setFieldPresent(message, pos); + break; + case 5: // FIXED64: + UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readFixed64()); + setFieldPresent(message, pos); + break; + case 6: // FIXED32: + UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readFixed32()); + setFieldPresent(message, pos); + break; + case 7: // BOOL: + UnsafeUtil.putBoolean(message, offset(typeAndOffset), reader.readBool()); + setFieldPresent(message, pos); + break; + case 8: // STRING: + readString(message, typeAndOffset, reader); + setFieldPresent(message, pos); + break; + case 9: + { // MESSAGE: + if (isFieldPresent(message, pos)) { + Object mergedResult = + Internal.mergeMessage( + UnsafeUtil.getObject(message, offset(typeAndOffset)), + reader.readMessageBySchemaWithCheck( + (Schema) getMessageFieldSchema(pos), extensionRegistry)); + UnsafeUtil.putObject(message, offset(typeAndOffset), mergedResult); + } else { + UnsafeUtil.putObject( + message, + offset(typeAndOffset), + reader.readMessageBySchemaWithCheck( + (Schema) getMessageFieldSchema(pos), extensionRegistry)); + setFieldPresent(message, pos); + } + break; + } + case 10: // BYTES: + UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readBytes()); + setFieldPresent(message, pos); + break; + case 11: // UINT32: + UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readUInt32()); + setFieldPresent(message, pos); + break; + case 12: // ENUM: + { + int enumValue = reader.readEnum(); + EnumVerifier enumVerifier = getEnumFieldVerifier(pos); + if (enumVerifier == null || enumVerifier.isInRange(enumValue)) { + UnsafeUtil.putInt(message, offset(typeAndOffset), enumValue); + setFieldPresent(message, pos); + } else { + unknownFields = + SchemaUtil.storeUnknownEnum( + number, enumValue, unknownFields, unknownFieldSchema); + } + break; + } + case 13: // SFIXED32: + UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readSFixed32()); + setFieldPresent(message, pos); + break; + case 14: // SFIXED64: + UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readSFixed64()); + setFieldPresent(message, pos); + break; + case 15: // SINT32: + UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readSInt32()); + setFieldPresent(message, pos); + break; + case 16: // SINT64: + UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readSInt64()); + setFieldPresent(message, pos); + break; + case 17: + { // GROUP: + if (isFieldPresent(message, pos)) { + Object mergedResult = + Internal.mergeMessage( + UnsafeUtil.getObject(message, offset(typeAndOffset)), + reader.readGroupBySchemaWithCheck( + (Schema) getMessageFieldSchema(pos), extensionRegistry)); + UnsafeUtil.putObject(message, offset(typeAndOffset), mergedResult); + } else { + UnsafeUtil.putObject( + message, + offset(typeAndOffset), + reader.readGroupBySchemaWithCheck( + (Schema) getMessageFieldSchema(pos), extensionRegistry)); + setFieldPresent(message, pos); + } + break; + } + case 18: // DOUBLE_LIST: + reader.readDoubleList( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 19: // FLOAT_LIST: + reader.readFloatList( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 20: // INT64_LIST: + reader.readInt64List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 21: // UINT64_LIST: + reader.readUInt64List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 22: // INT32_LIST: + reader.readInt32List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 23: // FIXED64_LIST: + reader.readFixed64List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 24: // FIXED32_LIST: + reader.readFixed32List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 25: // BOOL_LIST: + reader.readBoolList( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 26: // STRING_LIST: + readStringList(message, typeAndOffset, reader); + break; + case 27: + { // MESSAGE_LIST: + readMessageList( + message, + typeAndOffset, + reader, + (Schema) getMessageFieldSchema(pos), + extensionRegistry); + break; + } + case 28: // BYTES_LIST: + reader.readBytesList( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 29: // UINT32_LIST: + reader.readUInt32List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 30: // ENUM_LIST: + { + List enumList = + listFieldSchema.mutableListAt(message, offset(typeAndOffset)); + reader.readEnumList(enumList); + unknownFields = + SchemaUtil.filterUnknownEnumList( + number, + enumList, + getEnumFieldVerifier(pos), + unknownFields, + unknownFieldSchema); + break; + } + case 31: // SFIXED32_LIST: + reader.readSFixed32List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 32: // SFIXED64_LIST: + reader.readSFixed64List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 33: // SINT32_LIST: + reader.readSInt32List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 34: // SINT64_LIST: + reader.readSInt64List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 35: // DOUBLE_LIST_PACKED: + reader.readDoubleList( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 36: // FLOAT_LIST_PACKED: + reader.readFloatList( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 37: // INT64_LIST_PACKED: + reader.readInt64List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 38: // UINT64_LIST_PACKED: + reader.readUInt64List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 39: // INT32_LIST_PACKED: + reader.readInt32List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 40: // FIXED64_LIST_PACKED: + reader.readFixed64List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 41: // FIXED32_LIST_PACKED: + reader.readFixed32List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 42: // BOOL_LIST_PACKED: + reader.readBoolList( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 43: // UINT32_LIST_PACKED: + reader.readUInt32List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 44: // ENUM_LIST_PACKED: + { + List enumList = + listFieldSchema.mutableListAt(message, offset(typeAndOffset)); + reader.readEnumList(enumList); + unknownFields = + SchemaUtil.filterUnknownEnumList( + number, + enumList, + getEnumFieldVerifier(pos), + unknownFields, + unknownFieldSchema); + break; + } + case 45: // SFIXED32_LIST_PACKED: + reader.readSFixed32List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 46: // SFIXED64_LIST_PACKED: + reader.readSFixed64List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 47: // SINT32_LIST_PACKED: + reader.readSInt32List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 48: // SINT64_LIST_PACKED: + reader.readSInt64List( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + break; + case 49: + { // GROUP_LIST: + readGroupList( + message, + offset(typeAndOffset), + reader, + (Schema) getMessageFieldSchema(pos), + extensionRegistry); + break; + } + case 50: // MAP: + mergeMap(message, pos, getMapFieldDefaultEntry(pos), extensionRegistry, reader); + break; + case 51: // ONEOF_DOUBLE: + UnsafeUtil.putObject( + message, offset(typeAndOffset), Double.valueOf(reader.readDouble())); + setOneofPresent(message, number, pos); + break; + case 52: // ONEOF_FLOAT: + UnsafeUtil.putObject( + message, offset(typeAndOffset), Float.valueOf(reader.readFloat())); + setOneofPresent(message, number, pos); + break; + case 53: // ONEOF_INT64: + UnsafeUtil.putObject( + message, offset(typeAndOffset), Long.valueOf(reader.readInt64())); + setOneofPresent(message, number, pos); + break; + case 54: // ONEOF_UINT64: + UnsafeUtil.putObject( + message, offset(typeAndOffset), Long.valueOf(reader.readUInt64())); + setOneofPresent(message, number, pos); + break; + case 55: // ONEOF_INT32: + UnsafeUtil.putObject( + message, offset(typeAndOffset), Integer.valueOf(reader.readInt32())); + setOneofPresent(message, number, pos); + break; + case 56: // ONEOF_FIXED64: + UnsafeUtil.putObject( + message, offset(typeAndOffset), Long.valueOf(reader.readFixed64())); + setOneofPresent(message, number, pos); + break; + case 57: // ONEOF_FIXED32: + UnsafeUtil.putObject( + message, offset(typeAndOffset), Integer.valueOf(reader.readFixed32())); + setOneofPresent(message, number, pos); + break; + case 58: // ONEOF_BOOL: + UnsafeUtil.putObject( + message, offset(typeAndOffset), Boolean.valueOf(reader.readBool())); + setOneofPresent(message, number, pos); + break; + case 59: // ONEOF_STRING: + readString(message, typeAndOffset, reader); + setOneofPresent(message, number, pos); + break; + case 60: // ONEOF_MESSAGE: + if (isOneofPresent(message, number, pos)) { + Object mergedResult = + Internal.mergeMessage( + UnsafeUtil.getObject(message, offset(typeAndOffset)), + reader.readMessageBySchemaWithCheck( + getMessageFieldSchema(pos), extensionRegistry)); + UnsafeUtil.putObject(message, offset(typeAndOffset), mergedResult); + } else { + UnsafeUtil.putObject( + message, + offset(typeAndOffset), + reader.readMessageBySchemaWithCheck( + getMessageFieldSchema(pos), extensionRegistry)); + setFieldPresent(message, pos); + } + setOneofPresent(message, number, pos); + break; + case 61: // ONEOF_BYTES: + UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readBytes()); + setOneofPresent(message, number, pos); + break; + case 62: // ONEOF_UINT32: + UnsafeUtil.putObject( + message, offset(typeAndOffset), Integer.valueOf(reader.readUInt32())); + setOneofPresent(message, number, pos); + break; + case 63: // ONEOF_ENUM: + { + int enumValue = reader.readEnum(); + EnumVerifier enumVerifier = getEnumFieldVerifier(pos); + if (enumVerifier == null || enumVerifier.isInRange(enumValue)) { + UnsafeUtil.putObject(message, offset(typeAndOffset), enumValue); + setOneofPresent(message, number, pos); + } else { + unknownFields = + SchemaUtil.storeUnknownEnum( + number, enumValue, unknownFields, unknownFieldSchema); + } + break; + } + case 64: // ONEOF_SFIXED32: + UnsafeUtil.putObject( + message, offset(typeAndOffset), Integer.valueOf(reader.readSFixed32())); + setOneofPresent(message, number, pos); + break; + case 65: // ONEOF_SFIXED64: + UnsafeUtil.putObject( + message, offset(typeAndOffset), Long.valueOf(reader.readSFixed64())); + setOneofPresent(message, number, pos); + break; + case 66: // ONEOF_SINT32: + UnsafeUtil.putObject( + message, offset(typeAndOffset), Integer.valueOf(reader.readSInt32())); + setOneofPresent(message, number, pos); + break; + case 67: // ONEOF_SINT64: + UnsafeUtil.putObject( + message, offset(typeAndOffset), Long.valueOf(reader.readSInt64())); + setOneofPresent(message, number, pos); + break; + case 68: // ONEOF_GROUP: + UnsafeUtil.putObject( + message, + offset(typeAndOffset), + reader.readGroupBySchemaWithCheck(getMessageFieldSchema(pos), extensionRegistry)); + setOneofPresent(message, number, pos); + break; + default: + // Assume we've landed on an empty entry. Treat it as an unknown field. + if (unknownFields == null) { + unknownFields = unknownFieldSchema.newBuilder(); + } + if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) { + return; + } + break; + } + } catch (InvalidProtocolBufferException.InvalidWireTypeException e) { + // Treat fields with an invalid wire type as unknown fields + // (i.e. same as the default case). + if (unknownFieldSchema.shouldDiscardUnknownFields(reader)) { + if (!reader.skipField()) { + return; + } + } else { + if (unknownFields == null) { + unknownFields = unknownFieldSchema.getBuilderFromMessage(message); + } + if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) { + return; + } + } + } + } + } finally { + for (int i = checkInitializedCount; i < repeatedFieldOffsetStart; i++) { + unknownFields = + filterMapUnknownEnumValues(message, intArray[i], unknownFields, unknownFieldSchema); + } + if (unknownFields != null) { + unknownFieldSchema.setBuilderToMessage(message, unknownFields); + } + } + } + + @SuppressWarnings("ReferenceEquality") + static UnknownFieldSetLite getMutableUnknownFields(Object message) { + UnknownFieldSetLite unknownFields = ((GeneratedMessageLite) message).unknownFields; + if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) { + unknownFields = UnknownFieldSetLite.newInstance(); + ((GeneratedMessageLite) message).unknownFields = unknownFields; + } + return unknownFields; + } + + /** Decodes a map entry key or value. Stores result in registers.object1. */ + private int decodeMapEntryValue( + byte[] data, + int position, + int limit, + WireFormat.FieldType fieldType, + Class messageType, + Registers registers) + throws IOException { + switch (fieldType) { + case BOOL: + position = decodeVarint64(data, position, registers); + registers.object1 = registers.long1 != 0; + break; + case BYTES: + position = decodeBytes(data, position, registers); + break; + case DOUBLE: + registers.object1 = decodeDouble(data, position); + position += 8; + break; + case FIXED32: + case SFIXED32: + registers.object1 = decodeFixed32(data, position); + position += 4; + break; + case FIXED64: + case SFIXED64: + registers.object1 = decodeFixed64(data, position); + position += 8; + break; + case FLOAT: + registers.object1 = decodeFloat(data, position); + position += 4; + break; + case ENUM: + case INT32: + case UINT32: + position = decodeVarint32(data, position, registers); + registers.object1 = registers.int1; + break; + case INT64: + case UINT64: + position = decodeVarint64(data, position, registers); + registers.object1 = registers.long1; + break; + case MESSAGE: + position = + decodeMessageField( + Protobuf.getInstance().schemaFor(messageType), data, position, limit, registers); + break; + case SINT32: + position = decodeVarint32(data, position, registers); + registers.object1 = CodedInputStream.decodeZigZag32(registers.int1); + break; + case SINT64: + position = decodeVarint64(data, position, registers); + registers.object1 = CodedInputStream.decodeZigZag64(registers.long1); + break; + case STRING: + position = decodeStringRequireUtf8(data, position, registers); + break; + default: + throw new RuntimeException("unsupported field type."); + } + return position; + } + + /** Decodes a map entry. */ + private int decodeMapEntry( + byte[] data, + int position, + int limit, + MapEntryLite.Metadata metadata, + Map target, + Registers registers) + throws IOException { + position = decodeVarint32(data, position, registers); + final int length = registers.int1; + if (length < 0 || length > limit - position) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + final int end = position + length; + K key = metadata.defaultKey; + V value = metadata.defaultValue; + while (position < end) { + int tag = data[position++]; + if (tag < 0) { + position = decodeVarint32(tag, data, position, registers); + tag = registers.int1; + } + final int fieldNumber = tag >>> 3; + final int wireType = tag & 0x7; + switch (fieldNumber) { + case 1: + if (wireType == metadata.keyType.getWireType()) { + position = + decodeMapEntryValue(data, position, limit, metadata.keyType, null, registers); + key = (K) registers.object1; + continue; + } + break; + case 2: + if (wireType == metadata.valueType.getWireType()) { + position = + decodeMapEntryValue( + data, + position, + limit, + metadata.valueType, + metadata.defaultValue.getClass(), + registers); + value = (V) registers.object1; + continue; + } + break; + default: + break; + } + position = skipField(tag, data, position, limit, registers); + } + if (position != end) { + throw InvalidProtocolBufferException.parseFailure(); + } + target.put(key, value); + return end; + } + + @SuppressWarnings("ReferenceEquality") + private int parseRepeatedField( + T message, + byte[] data, + int position, + int limit, + int tag, + int number, + int wireType, + int bufferPosition, + long typeAndOffset, + int fieldType, + long fieldOffset, + Registers registers) + throws IOException { + ProtobufList list = (ProtobufList) UNSAFE.getObject(message, fieldOffset); + if (!list.isModifiable()) { + final int size = list.size(); + list = + list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + UNSAFE.putObject(message, fieldOffset, list); + } + switch (fieldType) { + case 18: // DOUBLE_LIST: + case 35: // DOUBLE_LIST_PACKED: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodePackedDoubleList(data, position, list, registers); + } else if (wireType == WireFormat.WIRETYPE_FIXED64) { + position = decodeDoubleList(tag, data, position, limit, list, registers); + } + break; + case 19: // FLOAT_LIST: + case 36: // FLOAT_LIST_PACKED: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodePackedFloatList(data, position, list, registers); + } else if (wireType == WireFormat.WIRETYPE_FIXED32) { + position = decodeFloatList(tag, data, position, limit, list, registers); + } + break; + case 20: // INT64_LIST: + case 21: // UINT64_LIST: + case 37: // INT64_LIST_PACKED: + case 38: // UINT64_LIST_PACKED: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodePackedVarint64List(data, position, list, registers); + } else if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint64List(tag, data, position, limit, list, registers); + } + break; + case 22: // INT32_LIST: + case 29: // UINT32_LIST: + case 39: // INT32_LIST_PACKED: + case 43: // UINT32_LIST_PACKED: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodePackedVarint32List(data, position, list, registers); + } else if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint32List(tag, data, position, limit, list, registers); + } + break; + case 23: // FIXED64_LIST: + case 32: // SFIXED64_LIST: + case 40: // FIXED64_LIST_PACKED: + case 46: // SFIXED64_LIST_PACKED: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodePackedFixed64List(data, position, list, registers); + } else if (wireType == WireFormat.WIRETYPE_FIXED64) { + position = decodeFixed64List(tag, data, position, limit, list, registers); + } + break; + case 24: // FIXED32_LIST: + case 31: // SFIXED32_LIST: + case 41: // FIXED32_LIST_PACKED: + case 45: // SFIXED32_LIST_PACKED: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodePackedFixed32List(data, position, list, registers); + } else if (wireType == WireFormat.WIRETYPE_FIXED32) { + position = decodeFixed32List(tag, data, position, limit, list, registers); + } + break; + case 25: // BOOL_LIST: + case 42: // BOOL_LIST_PACKED: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodePackedBoolList(data, position, list, registers); + } else if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeBoolList(tag, data, position, limit, list, registers); + } + break; + case 26: // STRING_LIST: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + if ((typeAndOffset & ENFORCE_UTF8_MASK) == 0) { + position = decodeStringList(tag, data, position, limit, list, registers); + } else { + position = decodeStringListRequireUtf8(tag, data, position, limit, list, registers); + } + } + break; + case 27: // MESSAGE_LIST: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = + decodeMessageList( + getMessageFieldSchema(bufferPosition), + tag, + data, + position, + limit, + list, + registers); + } + break; + case 28: // BYTES_LIST: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodeBytesList(tag, data, position, limit, list, registers); + } + break; + case 30: // ENUM_LIST: + case 44: // ENUM_LIST_PACKED: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodePackedVarint32List(data, position, list, registers); + } else if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint32List(tag, data, position, limit, list, registers); + } else { + break; + } + UnknownFieldSetLite unknownFields = ((GeneratedMessageLite) message).unknownFields; + if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) { + // filterUnknownEnumList() expects the unknownFields parameter to be mutable or null. + // Since we don't know yet whether there exist unknown enum values, we'd better pass + // null to it instead of allocating a mutable instance. This is also needed to be + // consistent with the behavior of generated parser/builder. + unknownFields = null; + } + unknownFields = + SchemaUtil.filterUnknownEnumList( + number, + (ProtobufList) list, + getEnumFieldVerifier(bufferPosition), + unknownFields, + (UnknownFieldSchema) unknownFieldSchema); + if (unknownFields != null) { + ((GeneratedMessageLite) message).unknownFields = unknownFields; + } + break; + case 33: // SINT32_LIST: + case 47: // SINT32_LIST_PACKED: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodePackedSInt32List(data, position, list, registers); + } else if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeSInt32List(tag, data, position, limit, list, registers); + } + break; + case 34: // SINT64_LIST: + case 48: // SINT64_LIST_PACKED: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodePackedSInt64List(data, position, list, registers); + } else if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeSInt64List(tag, data, position, limit, list, registers); + } + break; + case 49: // GROUP_LIST: + if (wireType == WireFormat.WIRETYPE_START_GROUP) { + position = + decodeGroupList( + getMessageFieldSchema(bufferPosition), + tag, + data, + position, + limit, + list, + registers); + } + break; + default: + break; + } + return position; + } + + private int parseMapField( + T message, + byte[] data, + int position, + int limit, + int bufferPosition, + long fieldOffset, + Registers registers) + throws IOException { + final sun.misc.Unsafe unsafe = UNSAFE; + Object mapDefaultEntry = getMapFieldDefaultEntry(bufferPosition); + Object mapField = unsafe.getObject(message, fieldOffset); + if (mapFieldSchema.isImmutable(mapField)) { + Object oldMapField = mapField; + mapField = mapFieldSchema.newMapField(mapDefaultEntry); + mapFieldSchema.mergeFrom(mapField, oldMapField); + unsafe.putObject(message, fieldOffset, mapField); + } + return decodeMapEntry( + data, + position, + limit, + (Metadata) mapFieldSchema.forMapMetadata(mapDefaultEntry), + (Map) mapFieldSchema.forMutableMapData(mapField), + registers); + } + + private int parseOneofField( + T message, + byte[] data, + int position, + int limit, + int tag, + int number, + int wireType, + int typeAndOffset, + int fieldType, + long fieldOffset, + int bufferPosition, + Registers registers) + throws IOException { + final sun.misc.Unsafe unsafe = UNSAFE; + final long oneofCaseOffset = buffer[bufferPosition + 2] & OFFSET_MASK; + switch (fieldType) { + case 51: // ONEOF_DOUBLE: + if (wireType == WireFormat.WIRETYPE_FIXED64) { + unsafe.putObject(message, fieldOffset, decodeDouble(data, position)); + position += 8; + unsafe.putInt(message, oneofCaseOffset, number); + } + break; + case 52: // ONEOF_FLOAT: + if (wireType == WireFormat.WIRETYPE_FIXED32) { + unsafe.putObject(message, fieldOffset, decodeFloat(data, position)); + position += 4; + unsafe.putInt(message, oneofCaseOffset, number); + } + break; + case 53: // ONEOF_INT64: + case 54: // ONEOF_UINT64: + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint64(data, position, registers); + unsafe.putObject(message, fieldOffset, registers.long1); + unsafe.putInt(message, oneofCaseOffset, number); + } + break; + case 55: // ONEOF_INT32: + case 62: // ONEOF_UINT32: + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint32(data, position, registers); + unsafe.putObject(message, fieldOffset, registers.int1); + unsafe.putInt(message, oneofCaseOffset, number); + } + break; + case 56: // ONEOF_FIXED64: + case 65: // ONEOF_SFIXED64: + if (wireType == WireFormat.WIRETYPE_FIXED64) { + unsafe.putObject(message, fieldOffset, decodeFixed64(data, position)); + position += 8; + unsafe.putInt(message, oneofCaseOffset, number); + } + break; + case 57: // ONEOF_FIXED32: + case 64: // ONEOF_SFIXED32: + if (wireType == WireFormat.WIRETYPE_FIXED32) { + unsafe.putObject(message, fieldOffset, decodeFixed32(data, position)); + position += 4; + unsafe.putInt(message, oneofCaseOffset, number); + } + break; + case 58: // ONEOF_BOOL: + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint64(data, position, registers); + unsafe.putObject(message, fieldOffset, registers.long1 != 0); + unsafe.putInt(message, oneofCaseOffset, number); + } + break; + case 59: // ONEOF_STRING: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodeVarint32(data, position, registers); + final int length = registers.int1; + if (length == 0) { + unsafe.putObject(message, fieldOffset, ""); + } else { + if ((typeAndOffset & ENFORCE_UTF8_MASK) != 0 + && !Utf8.isValidUtf8(data, position, position + length)) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + final String value = new String(data, position, length, Internal.UTF_8); + unsafe.putObject(message, fieldOffset, value); + position += length; + } + unsafe.putInt(message, oneofCaseOffset, number); + } + break; + case 60: // ONEOF_MESSAGE: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = + decodeMessageField( + getMessageFieldSchema(bufferPosition), data, position, limit, registers); + final Object oldValue = + unsafe.getInt(message, oneofCaseOffset) == number + ? unsafe.getObject(message, fieldOffset) + : null; + if (oldValue == null) { + unsafe.putObject(message, fieldOffset, registers.object1); + } else { + unsafe.putObject( + message, fieldOffset, Internal.mergeMessage(oldValue, registers.object1)); + } + unsafe.putInt(message, oneofCaseOffset, number); + } + break; + case 61: // ONEOF_BYTES: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodeBytes(data, position, registers); + unsafe.putObject(message, fieldOffset, registers.object1); + unsafe.putInt(message, oneofCaseOffset, number); + } + break; + case 63: // ONEOF_ENUM: + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint32(data, position, registers); + final int enumValue = registers.int1; + EnumVerifier enumVerifier = getEnumFieldVerifier(bufferPosition); + if (enumVerifier == null || enumVerifier.isInRange(enumValue)) { + unsafe.putObject(message, fieldOffset, enumValue); + unsafe.putInt(message, oneofCaseOffset, number); + } else { + // UnknownFieldSetLite requires varint to be represented as Long. + getMutableUnknownFields(message).storeField(tag, (long) enumValue); + } + } + break; + case 66: // ONEOF_SINT32: + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint32(data, position, registers); + unsafe.putObject(message, fieldOffset, CodedInputStream.decodeZigZag32(registers.int1)); + unsafe.putInt(message, oneofCaseOffset, number); + } + break; + case 67: // ONEOF_SINT64: + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint64(data, position, registers); + unsafe.putObject(message, fieldOffset, CodedInputStream.decodeZigZag64(registers.long1)); + unsafe.putInt(message, oneofCaseOffset, number); + } + break; + case 68: // ONEOF_GROUP: + if (wireType == WireFormat.WIRETYPE_START_GROUP) { + final int endTag = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP; + position = + decodeGroupField( + getMessageFieldSchema(bufferPosition), data, position, limit, endTag, registers); + final Object oldValue = + unsafe.getInt(message, oneofCaseOffset) == number + ? unsafe.getObject(message, fieldOffset) + : null; + if (oldValue == null) { + unsafe.putObject(message, fieldOffset, registers.object1); + } else { + unsafe.putObject( + message, fieldOffset, Internal.mergeMessage(oldValue, registers.object1)); + } + unsafe.putInt(message, oneofCaseOffset, number); + } + break; + default: + break; + } + return position; + } + + private Schema getMessageFieldSchema(int pos) { + final int index = pos / INTS_PER_FIELD * 2; + Schema schema = (Schema) objects[index]; + if (schema != null) { + return schema; + } + schema = Protobuf.getInstance().schemaFor((Class) objects[index + 1]); + objects[index] = schema; + return schema; + } + + private Object getMapFieldDefaultEntry(int pos) { + return objects[pos / INTS_PER_FIELD * 2]; + } + + private EnumVerifier getEnumFieldVerifier(int pos) { + return (EnumVerifier) objects[pos / INTS_PER_FIELD * 2 + 1]; + } + + /** + * Parses a proto2 message or group and returns the position after the message/group. If it's + * parsing a message (endGroup == 0), returns limit if parsing is successful; It it's parsing a + * group (endGroup != 0), parsing ends when a tag == endGroup is encountered and the position + * after that tag is returned. + */ + int parseProto2Message( + T message, byte[] data, int position, int limit, int endGroup, Registers registers) + throws IOException { + final sun.misc.Unsafe unsafe = UNSAFE; + int currentPresenceFieldOffset = NO_PRESENCE_SENTINEL; + int currentPresenceField = 0; + int tag = 0; + int oldNumber = -1; + int pos = 0; + while (position < limit) { + tag = data[position++]; + if (tag < 0) { + position = decodeVarint32(tag, data, position, registers); + tag = registers.int1; + } + final int number = tag >>> 3; + final int wireType = tag & 0x7; + if (number > oldNumber) { + pos = positionForFieldNumber(number, pos / INTS_PER_FIELD); + } else { + pos = positionForFieldNumber(number); + } + oldNumber = number; + if (pos == -1) { + // need to reset + pos = 0; + } else { + final int typeAndOffset = buffer[pos + 1]; + final int fieldType = type(typeAndOffset); + final long fieldOffset = offset(typeAndOffset); + if (fieldType <= 17) { + // Proto2 optional fields have has-bits. + final int presenceMaskAndOffset = buffer[pos + 2]; + final int presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS); + final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK; + // We cache the 32-bit has-bits integer value and only write it back when parsing a field + // using a different has-bits integer. + if (presenceFieldOffset != currentPresenceFieldOffset) { + if (currentPresenceFieldOffset != NO_PRESENCE_SENTINEL) { + unsafe.putInt(message, (long) currentPresenceFieldOffset, currentPresenceField); + } + currentPresenceFieldOffset = presenceFieldOffset; + currentPresenceField = unsafe.getInt(message, (long) presenceFieldOffset); + } + switch (fieldType) { + case 0: // DOUBLE + if (wireType == WireFormat.WIRETYPE_FIXED64) { + UnsafeUtil.putDouble(message, fieldOffset, decodeDouble(data, position)); + position += 8; + currentPresenceField |= presenceMask; + continue; + } + break; + case 1: // FLOAT + if (wireType == WireFormat.WIRETYPE_FIXED32) { + UnsafeUtil.putFloat(message, fieldOffset, decodeFloat(data, position)); + position += 4; + currentPresenceField |= presenceMask; + continue; + } + break; + case 2: // INT64 + case 3: // UINT64 + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint64(data, position, registers); + unsafe.putLong(message, fieldOffset, registers.long1); + currentPresenceField |= presenceMask; + continue; + } + break; + case 4: // INT32 + case 11: // UINT32 + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint32(data, position, registers); + unsafe.putInt(message, fieldOffset, registers.int1); + currentPresenceField |= presenceMask; + continue; + } + break; + case 5: // FIXED64 + case 14: // SFIXED64 + if (wireType == WireFormat.WIRETYPE_FIXED64) { + unsafe.putLong(message, fieldOffset, decodeFixed64(data, position)); + position += 8; + currentPresenceField |= presenceMask; + continue; + } + break; + case 6: // FIXED32 + case 13: // SFIXED32 + if (wireType == WireFormat.WIRETYPE_FIXED32) { + unsafe.putInt(message, fieldOffset, decodeFixed32(data, position)); + position += 4; + currentPresenceField |= presenceMask; + continue; + } + break; + case 7: // BOOL + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint64(data, position, registers); + UnsafeUtil.putBoolean(message, fieldOffset, registers.long1 != 0); + currentPresenceField |= presenceMask; + continue; + } + break; + case 8: // STRING + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + if ((typeAndOffset & ENFORCE_UTF8_MASK) == 0) { + position = decodeString(data, position, registers); + } else { + position = decodeStringRequireUtf8(data, position, registers); + } + unsafe.putObject(message, fieldOffset, registers.object1); + currentPresenceField |= presenceMask; + continue; + } + break; + case 9: // MESSAGE + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = + decodeMessageField( + getMessageFieldSchema(pos), data, position, limit, registers); + if ((currentPresenceField & presenceMask) == 0) { + unsafe.putObject(message, fieldOffset, registers.object1); + } else { + unsafe.putObject( + message, + fieldOffset, + Internal.mergeMessage( + unsafe.getObject(message, fieldOffset), registers.object1)); + } + currentPresenceField |= presenceMask; + continue; + } + break; + case 10: // BYTES + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodeBytes(data, position, registers); + unsafe.putObject(message, fieldOffset, registers.object1); + currentPresenceField |= presenceMask; + continue; + } + break; + case 12: // ENUM + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint32(data, position, registers); + final int enumValue = registers.int1; + EnumVerifier enumVerifier = getEnumFieldVerifier(pos); + if (enumVerifier == null || enumVerifier.isInRange(enumValue)) { + unsafe.putInt(message, fieldOffset, enumValue); + currentPresenceField |= presenceMask; + } else { + // UnknownFieldSetLite requires varint to be represented as Long. + getMutableUnknownFields(message).storeField(tag, (long) enumValue); + } + continue; + } + break; + case 15: // SINT32 + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint32(data, position, registers); + unsafe.putInt( + message, fieldOffset, CodedInputStream.decodeZigZag32(registers.int1)); + currentPresenceField |= presenceMask; + continue; + } + break; + case 16: // SINT64 + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint64(data, position, registers); + unsafe.putLong( + message, fieldOffset, CodedInputStream.decodeZigZag64(registers.long1)); + + currentPresenceField |= presenceMask; + continue; + } + break; + case 17: // GROUP + if (wireType == WireFormat.WIRETYPE_START_GROUP) { + final int endTag = (number << 3) | WireFormat.WIRETYPE_END_GROUP; + position = + decodeGroupField( + getMessageFieldSchema(pos), data, position, limit, endTag, registers); + if ((currentPresenceField & presenceMask) == 0) { + unsafe.putObject(message, fieldOffset, registers.object1); + } else { + unsafe.putObject( + message, + fieldOffset, + Internal.mergeMessage( + unsafe.getObject(message, fieldOffset), registers.object1)); + } + + currentPresenceField |= presenceMask; + continue; + } + break; + default: + break; + } + } else if (fieldType == 27) { + // Handle repeated message fields. + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + ProtobufList list = (ProtobufList) unsafe.getObject(message, fieldOffset); + if (!list.isModifiable()) { + final int size = list.size(); + list = + list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + unsafe.putObject(message, fieldOffset, list); + } + position = + decodeMessageList( + getMessageFieldSchema(pos), tag, data, position, limit, list, registers); + continue; + } + } else if (fieldType <= 49) { + // Handle all other repeated fields. + final int oldPosition = position; + position = + parseRepeatedField( + message, + data, + position, + limit, + tag, + number, + wireType, + pos, + typeAndOffset, + fieldType, + fieldOffset, + registers); + if (position != oldPosition) { + continue; + } + } else if (fieldType == 50) { + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + final int oldPosition = position; + position = parseMapField(message, data, position, limit, pos, fieldOffset, registers); + if (position != oldPosition) { + continue; + } + } + } else { + final int oldPosition = position; + position = + parseOneofField( + message, + data, + position, + limit, + tag, + number, + wireType, + typeAndOffset, + fieldType, + fieldOffset, + pos, + registers); + if (position != oldPosition) { + continue; + } + } + } + if (tag == endGroup && endGroup != 0) { + break; + } + + if (hasExtensions + && registers.extensionRegistry != ExtensionRegistryLite.getEmptyRegistry()) { + position = decodeExtensionOrUnknownField( + tag, data, position, limit, message, defaultInstance, + (UnknownFieldSchema) unknownFieldSchema, + registers); + } else { + position = decodeUnknownField( + tag, data, position, limit, getMutableUnknownFields(message), registers); + } + } + if (currentPresenceFieldOffset != NO_PRESENCE_SENTINEL) { + unsafe.putInt(message, (long) currentPresenceFieldOffset, currentPresenceField); + } + UnknownFieldSetLite unknownFields = null; + for (int i = checkInitializedCount; i < repeatedFieldOffsetStart; i++) { + unknownFields = + filterMapUnknownEnumValues( + message, + intArray[i], + unknownFields, + (UnknownFieldSchema) unknownFieldSchema); + } + if (unknownFields != null) { + ((UnknownFieldSchema) unknownFieldSchema) + .setBuilderToMessage(message, unknownFields); + } + if (endGroup == 0) { + if (position != limit) { + throw InvalidProtocolBufferException.parseFailure(); + } + } else { + if (position > limit || tag != endGroup) { + throw InvalidProtocolBufferException.parseFailure(); + } + } + return position; + } + + /** Parses a proto3 message and returns the limit if parsing is successful. */ + private int parseProto3Message( + T message, byte[] data, int position, int limit, Registers registers) throws IOException { + final sun.misc.Unsafe unsafe = UNSAFE; + int currentPresenceFieldOffset = NO_PRESENCE_SENTINEL; + int currentPresenceField = 0; + int tag = 0; + int oldNumber = -1; + int pos = 0; + while (position < limit) { + tag = data[position++]; + if (tag < 0) { + position = decodeVarint32(tag, data, position, registers); + tag = registers.int1; + } + final int number = tag >>> 3; + final int wireType = tag & 0x7; + if (number > oldNumber) { + pos = positionForFieldNumber(number, pos / INTS_PER_FIELD); + } else { + pos = positionForFieldNumber(number); + } + oldNumber = number; + if (pos == -1) { + // need to reset + pos = 0; + } else { + final int typeAndOffset = buffer[pos + 1]; + final int fieldType = type(typeAndOffset); + final long fieldOffset = offset(typeAndOffset); + if (fieldType <= 17) { + // Proto3 optional fields have has-bits. + final int presenceMaskAndOffset = buffer[pos + 2]; + final int presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS); + final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK; + // We cache the 32-bit has-bits integer value and only write it back when parsing a field + // using a different has-bits integer. + // + // Note that for fields that do not have hasbits, we unconditionally write and discard + // the data. + if (presenceFieldOffset != currentPresenceFieldOffset) { + if (currentPresenceFieldOffset != NO_PRESENCE_SENTINEL) { + unsafe.putInt(message, (long) currentPresenceFieldOffset, currentPresenceField); + } + if (presenceFieldOffset != NO_PRESENCE_SENTINEL) { + currentPresenceField = unsafe.getInt(message, (long) presenceFieldOffset); + } + currentPresenceFieldOffset = presenceFieldOffset; + } + switch (fieldType) { + case 0: // DOUBLE: + if (wireType == WireFormat.WIRETYPE_FIXED64) { + UnsafeUtil.putDouble(message, fieldOffset, decodeDouble(data, position)); + position += 8; + currentPresenceField |= presenceMask; + continue; + } + break; + case 1: // FLOAT: + if (wireType == WireFormat.WIRETYPE_FIXED32) { + UnsafeUtil.putFloat(message, fieldOffset, decodeFloat(data, position)); + position += 4; + currentPresenceField |= presenceMask; + continue; + } + break; + case 2: // INT64: + case 3: // UINT64: + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint64(data, position, registers); + unsafe.putLong(message, fieldOffset, registers.long1); + currentPresenceField |= presenceMask; + continue; + } + break; + case 4: // INT32: + case 11: // UINT32: + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint32(data, position, registers); + unsafe.putInt(message, fieldOffset, registers.int1); + currentPresenceField |= presenceMask; + continue; + } + break; + case 5: // FIXED64: + case 14: // SFIXED64: + if (wireType == WireFormat.WIRETYPE_FIXED64) { + unsafe.putLong(message, fieldOffset, decodeFixed64(data, position)); + position += 8; + currentPresenceField |= presenceMask; + continue; + } + break; + case 6: // FIXED32: + case 13: // SFIXED32: + if (wireType == WireFormat.WIRETYPE_FIXED32) { + unsafe.putInt(message, fieldOffset, decodeFixed32(data, position)); + position += 4; + currentPresenceField |= presenceMask; + continue; + } + break; + case 7: // BOOL: + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint64(data, position, registers); + UnsafeUtil.putBoolean(message, fieldOffset, registers.long1 != 0); + currentPresenceField |= presenceMask; + continue; + } + break; + case 8: // STRING: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + if ((typeAndOffset & ENFORCE_UTF8_MASK) == 0) { + position = decodeString(data, position, registers); + } else { + position = decodeStringRequireUtf8(data, position, registers); + } + unsafe.putObject(message, fieldOffset, registers.object1); + currentPresenceField |= presenceMask; + continue; + } + break; + case 9: // MESSAGE: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = + decodeMessageField( + getMessageFieldSchema(pos), data, position, limit, registers); + final Object oldValue = unsafe.getObject(message, fieldOffset); + if (oldValue == null) { + unsafe.putObject(message, fieldOffset, registers.object1); + } else { + unsafe.putObject( + message, fieldOffset, Internal.mergeMessage(oldValue, registers.object1)); + } + currentPresenceField |= presenceMask; + continue; + } + break; + case 10: // BYTES: + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = decodeBytes(data, position, registers); + unsafe.putObject(message, fieldOffset, registers.object1); + currentPresenceField |= presenceMask; + continue; + } + break; + case 12: // ENUM: + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint32(data, position, registers); + unsafe.putInt(message, fieldOffset, registers.int1); + currentPresenceField |= presenceMask; + continue; + } + break; + case 15: // SINT32: + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint32(data, position, registers); + unsafe.putInt( + message, fieldOffset, CodedInputStream.decodeZigZag32(registers.int1)); + currentPresenceField |= presenceMask; + continue; + } + break; + case 16: // SINT64: + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = decodeVarint64(data, position, registers); + unsafe.putLong( + message, fieldOffset, CodedInputStream.decodeZigZag64(registers.long1)); + currentPresenceField |= presenceMask; + continue; + } + break; + default: + break; + } + } else if (fieldType == 27) { + // Handle repeated message field. + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + ProtobufList list = (ProtobufList) unsafe.getObject(message, fieldOffset); + if (!list.isModifiable()) { + final int size = list.size(); + list = + list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + unsafe.putObject(message, fieldOffset, list); + } + position = + decodeMessageList( + getMessageFieldSchema(pos), tag, data, position, limit, list, registers); + continue; + } + } else if (fieldType <= 49) { + // Handle all other repeated fields. + final int oldPosition = position; + position = + parseRepeatedField( + message, + data, + position, + limit, + tag, + number, + wireType, + pos, + typeAndOffset, + fieldType, + fieldOffset, + registers); + if (position != oldPosition) { + continue; + } + } else if (fieldType == 50) { + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + final int oldPosition = position; + position = parseMapField(message, data, position, limit, pos, fieldOffset, registers); + if (position != oldPosition) { + continue; + } + } + } else { + final int oldPosition = position; + position = + parseOneofField( + message, + data, + position, + limit, + tag, + number, + wireType, + typeAndOffset, + fieldType, + fieldOffset, + pos, + registers); + if (position != oldPosition) { + continue; + } + } + } + position = decodeUnknownField( + tag, data, position, limit, getMutableUnknownFields(message), registers); + } + if (currentPresenceFieldOffset != NO_PRESENCE_SENTINEL) { + unsafe.putInt(message, (long) currentPresenceFieldOffset, currentPresenceField); + } + if (position != limit) { + throw InvalidProtocolBufferException.parseFailure(); + } + return position; + } + + @Override + public void mergeFrom(T message, byte[] data, int position, int limit, Registers registers) + throws IOException { + if (proto3) { + parseProto3Message(message, data, position, limit, registers); + } else { + parseProto2Message(message, data, position, limit, 0, registers); + } + } + + @Override + public void makeImmutable(T message) { + // Make all repeated/map fields immutable. + for (int i = checkInitializedCount; i < repeatedFieldOffsetStart; i++) { + long offset = offset(typeAndOffsetAt(intArray[i])); + Object mapField = UnsafeUtil.getObject(message, offset); + if (mapField == null) { + continue; + } + UnsafeUtil.putObject(message, offset, mapFieldSchema.toImmutable(mapField)); + } + final int length = intArray.length; + for (int i = repeatedFieldOffsetStart; i < length; i++) { + listFieldSchema.makeImmutableListAt(message, intArray[i]); + } + unknownFieldSchema.makeImmutable(message); + if (hasExtensions) { + extensionSchema.makeImmutable(message); + } + } + + @SuppressWarnings("unchecked") + private final void mergeMap( + Object message, + int pos, + Object mapDefaultEntry, + ExtensionRegistryLite extensionRegistry, + Reader reader) + throws IOException { + long offset = offset(typeAndOffsetAt(pos)); + Object mapField = UnsafeUtil.getObject(message, offset); + // TODO(xiaofeng): Consider creating separate implementations for full and lite. In lite + // runtime map field will never be null but here we still need to check null because the + // code is shared by both full and lite. It might be better if full/lite uses different + // schema implementations. + if (mapField == null) { + mapField = mapFieldSchema.newMapField(mapDefaultEntry); + UnsafeUtil.putObject(message, offset, mapField); + } else if (mapFieldSchema.isImmutable(mapField)) { + Object oldMapField = mapField; + mapField = mapFieldSchema.newMapField(mapDefaultEntry); + mapFieldSchema.mergeFrom(mapField, oldMapField); + UnsafeUtil.putObject(message, offset, mapField); + } + reader.readMap( + (Map) mapFieldSchema.forMutableMapData(mapField), + (Metadata) mapFieldSchema.forMapMetadata(mapDefaultEntry), + extensionRegistry); + } + + private final UB filterMapUnknownEnumValues( + Object message, int pos, UB unknownFields, UnknownFieldSchema unknownFieldSchema) { + int fieldNumber = numberAt(pos); + long offset = offset(typeAndOffsetAt(pos)); + Object mapField = UnsafeUtil.getObject(message, offset); + if (mapField == null) { + return unknownFields; + } + EnumVerifier enumVerifier = getEnumFieldVerifier(pos); + if (enumVerifier == null) { + return unknownFields; + } + Map mapData = mapFieldSchema.forMutableMapData(mapField); + // Filter unknown enum values. + unknownFields = + filterUnknownEnumMap( + pos, fieldNumber, mapData, enumVerifier, unknownFields, unknownFieldSchema); + return unknownFields; + } + + @SuppressWarnings("unchecked") + private final UB filterUnknownEnumMap( + int pos, + int number, + Map mapData, + EnumVerifier enumVerifier, + UB unknownFields, + UnknownFieldSchema unknownFieldSchema) { + Metadata metadata = + (Metadata) mapFieldSchema.forMapMetadata(getMapFieldDefaultEntry(pos)); + for (Iterator> it = mapData.entrySet().iterator(); it.hasNext(); ) { + Map.Entry entry = it.next(); + if (!enumVerifier.isInRange((Integer) entry.getValue())) { + if (unknownFields == null) { + unknownFields = unknownFieldSchema.newBuilder(); + } + int entrySize = + MapEntryLite.computeSerializedSize(metadata, entry.getKey(), entry.getValue()); + CodedBuilder codedBuilder = ByteString.newCodedBuilder(entrySize); + CodedOutputStream codedOutput = codedBuilder.getCodedOutput(); + try { + MapEntryLite.writeTo(codedOutput, metadata, entry.getKey(), entry.getValue()); + } catch (IOException e) { + // Writing to ByteString CodedOutputStream should not throw IOException. + throw new RuntimeException(e); + } + unknownFieldSchema.addLengthDelimited(unknownFields, number, codedBuilder.build()); + it.remove(); + } + } + return unknownFields; + } + + @Override + public final boolean isInitialized(T message) { + int currentPresenceFieldOffset = NO_PRESENCE_SENTINEL; + int currentPresenceField = 0; + for (int i = 0; i < checkInitializedCount; i++) { + final int pos = intArray[i]; + final int number = numberAt(pos); + final int typeAndOffset = typeAndOffsetAt(pos); + + int presenceMaskAndOffset = buffer[pos + 2]; + final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK; + int presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS); + if (presenceFieldOffset != currentPresenceFieldOffset) { + currentPresenceFieldOffset = presenceFieldOffset; + if (currentPresenceFieldOffset != NO_PRESENCE_SENTINEL) { + currentPresenceField = UNSAFE.getInt(message, (long) presenceFieldOffset); + } + } + + if (isRequired(typeAndOffset)) { + if (!isFieldPresent( + message, pos, currentPresenceFieldOffset, currentPresenceField, presenceMask)) { + return false; + } + // If a required message field is set but has no required fields of it's own, we still + // proceed and check the message is initialized. It should be fairly cheap to check these + // messages but is worth documenting. + } + // Check nested message and groups. + switch (type(typeAndOffset)) { + case 9: // MESSAGE + case 17: // GROUP + if (isFieldPresent( + message, pos, currentPresenceFieldOffset, currentPresenceField, presenceMask) + && !isInitialized(message, typeAndOffset, getMessageFieldSchema(pos))) { + return false; + } + break; + case 27: // MESSAGE_LIST + case 49: // GROUP_LIST + if (!isListInitialized(message, typeAndOffset, pos)) { + return false; + } + break; + case 60: // ONEOF_MESSAGE + case 68: // ONEOF_GROUP + if (isOneofPresent(message, number, pos) + && !isInitialized(message, typeAndOffset, getMessageFieldSchema(pos))) { + return false; + } + break; + case 50: // MAP + if (!isMapInitialized(message, typeAndOffset, pos)) { + return false; + } + break; + default: + break; + } + } + + if (hasExtensions) { + if (!extensionSchema.getExtensions(message).isInitialized()) { + return false; + } + } + + return true; + } + + private static boolean isInitialized(Object message, int typeAndOffset, Schema schema) { + Object nested = UnsafeUtil.getObject(message, offset(typeAndOffset)); + return schema.isInitialized(nested); + } + + private boolean isListInitialized(Object message, int typeAndOffset, int pos) { + @SuppressWarnings("unchecked") + List list = (List) UnsafeUtil.getObject(message, offset(typeAndOffset)); + if (list.isEmpty()) { + return true; + } + + Schema schema = getMessageFieldSchema(pos); + for (int i = 0; i < list.size(); i++) { + N nested = list.get(i); + if (!schema.isInitialized(nested)) { + return false; + } + } + return true; + } + + private boolean isMapInitialized(T message, int typeAndOffset, int pos) { + Map map = mapFieldSchema.forMapData(UnsafeUtil.getObject(message, offset(typeAndOffset))); + if (map.isEmpty()) { + return true; + } + Object mapDefaultEntry = getMapFieldDefaultEntry(pos); + MapEntryLite.Metadata metadata = mapFieldSchema.forMapMetadata(mapDefaultEntry); + if (metadata.valueType.getJavaType() != WireFormat.JavaType.MESSAGE) { + return true; + } + // TODO(dweis): Use schema cache. + Schema schema = null; + for (Object nested : map.values()) { + if (schema == null) { + schema = Protobuf.getInstance().schemaFor(nested.getClass()); + } + if (!schema.isInitialized(nested)) { + return false; + } + } + return true; + } + + private void writeString(int fieldNumber, Object value, Writer writer) throws IOException { + if (value instanceof String) { + writer.writeString(fieldNumber, (String) value); + } else { + writer.writeBytes(fieldNumber, (ByteString) value); + } + } + + private void readString(Object message, int typeAndOffset, Reader reader) throws IOException { + if (isEnforceUtf8(typeAndOffset)) { + // Enforce valid UTF-8 on the read. + UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readStringRequireUtf8()); + } else if (lite) { + // Lite messages use String fields to store strings. Read a string but do not + // enforce UTF-8 + UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readString()); + } else { + // Full runtime messages use Objects to store either a String or ByteString. Read + // the string as a ByteString and do not enforce UTF-8. + UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readBytes()); + } + } + + private void readStringList(Object message, int typeAndOffset, Reader reader) throws IOException { + if (isEnforceUtf8(typeAndOffset)) { + reader.readStringListRequireUtf8( + listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + } else { + reader.readStringList(listFieldSchema.mutableListAt(message, offset(typeAndOffset))); + } + } + + private void readMessageList( + Object message, + int typeAndOffset, + Reader reader, + Schema schema, + ExtensionRegistryLite extensionRegistry) + throws IOException { + long offset = offset(typeAndOffset); + reader.readMessageList( + listFieldSchema.mutableListAt(message, offset), schema, extensionRegistry); + } + + private void readGroupList( + Object message, + long offset, + Reader reader, + Schema schema, + ExtensionRegistryLite extensionRegistry) + throws IOException { + reader.readGroupList( + listFieldSchema.mutableListAt(message, offset), schema, extensionRegistry); + } + + private int numberAt(int pos) { + return buffer[pos]; + } + + private int typeAndOffsetAt(int pos) { + return buffer[pos + 1]; + } + + private int presenceMaskAndOffsetAt(int pos) { + return buffer[pos + 2]; + } + + private static int type(int value) { + return (value & FIELD_TYPE_MASK) >>> OFFSET_BITS; + } + + private static boolean isRequired(int value) { + return (value & REQUIRED_MASK) != 0; + } + + private static boolean isEnforceUtf8(int value) { + return (value & ENFORCE_UTF8_MASK) != 0; + } + + private static long offset(int value) { + return value & OFFSET_MASK; + } + + private static double doubleAt(T message, long offset) { + return UnsafeUtil.getDouble(message, offset); + } + + private static float floatAt(T message, long offset) { + return UnsafeUtil.getFloat(message, offset); + } + + private static int intAt(T message, long offset) { + return UnsafeUtil.getInt(message, offset); + } + + private static long longAt(T message, long offset) { + return UnsafeUtil.getLong(message, offset); + } + + private static boolean booleanAt(T message, long offset) { + return UnsafeUtil.getBoolean(message, offset); + } + + private static double oneofDoubleAt(T message, long offset) { + return ((Double) UnsafeUtil.getObject(message, offset)).doubleValue(); + } + + private static float oneofFloatAt(T message, long offset) { + return ((Float) UnsafeUtil.getObject(message, offset)).floatValue(); + } + + private static int oneofIntAt(T message, long offset) { + return ((Integer) UnsafeUtil.getObject(message, offset)).intValue(); + } + + private static long oneofLongAt(T message, long offset) { + return ((Long) UnsafeUtil.getObject(message, offset)).longValue(); + } + + private static boolean oneofBooleanAt(T message, long offset) { + return ((Boolean) UnsafeUtil.getObject(message, offset)).booleanValue(); + } + + /** Returns true the field is present in both messages, or neither. */ + private boolean arePresentForEquals(T message, T other, int pos) { + return isFieldPresent(message, pos) == isFieldPresent(other, pos); + } + + private boolean isFieldPresent( + T message, int pos, int presenceFieldOffset, int presenceField, int presenceMask) { + if (presenceFieldOffset == NO_PRESENCE_SENTINEL) { + return isFieldPresent(message, pos); + } else { + return (presenceField & presenceMask) != 0; + } + } + + private boolean isFieldPresent(T message, int pos) { + final int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos); + final long presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK; + if (presenceFieldOffset == NO_PRESENCE_SENTINEL) { + final int typeAndOffset = typeAndOffsetAt(pos); + final long offset = offset(typeAndOffset); + switch (type(typeAndOffset)) { + case 0: // DOUBLE: + return UnsafeUtil.getDouble(message, offset) != 0D; + case 1: // FLOAT: + return UnsafeUtil.getFloat(message, offset) != 0F; + case 2: // INT64: + return UnsafeUtil.getLong(message, offset) != 0L; + case 3: // UINT64: + return UnsafeUtil.getLong(message, offset) != 0L; + case 4: // INT32: + return UnsafeUtil.getInt(message, offset) != 0; + case 5: // FIXED64: + return UnsafeUtil.getLong(message, offset) != 0L; + case 6: // FIXED32: + return UnsafeUtil.getInt(message, offset) != 0; + case 7: // BOOL: + return UnsafeUtil.getBoolean(message, offset); + case 8: // STRING: + Object value = UnsafeUtil.getObject(message, offset); + if (value instanceof String) { + return !((String) value).isEmpty(); + } else if (value instanceof ByteString) { + return !ByteString.EMPTY.equals(value); + } else { + throw new IllegalArgumentException(); + } + case 9: // MESSAGE: + return UnsafeUtil.getObject(message, offset) != null; + case 10: // BYTES: + return !ByteString.EMPTY.equals(UnsafeUtil.getObject(message, offset)); + case 11: // UINT32: + return UnsafeUtil.getInt(message, offset) != 0; + case 12: // ENUM: + return UnsafeUtil.getInt(message, offset) != 0; + case 13: // SFIXED32: + return UnsafeUtil.getInt(message, offset) != 0; + case 14: // SFIXED64: + return UnsafeUtil.getLong(message, offset) != 0L; + case 15: // SINT32: + return UnsafeUtil.getInt(message, offset) != 0; + case 16: // SINT64: + return UnsafeUtil.getLong(message, offset) != 0L; + case 17: // GROUP: + return UnsafeUtil.getObject(message, offset) != null; + default: + throw new IllegalArgumentException(); + } + } else { + final int presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS); + return (UnsafeUtil.getInt(message, presenceMaskAndOffset & OFFSET_MASK) & presenceMask) != 0; + } + } + + private void setFieldPresent(T message, int pos) { + int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos); + final long presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK; + if (presenceFieldOffset == NO_PRESENCE_SENTINEL) { + return; + } + final int presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS); + UnsafeUtil.putInt( + message, + presenceFieldOffset, + UnsafeUtil.getInt(message, presenceFieldOffset) | presenceMask); + } + + private boolean isOneofPresent(T message, int fieldNumber, int pos) { + int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos); + return UnsafeUtil.getInt(message, presenceMaskAndOffset & OFFSET_MASK) == fieldNumber; + } + + private boolean isOneofCaseEqual(T message, T other, int pos) { + int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos); + return UnsafeUtil.getInt(message, presenceMaskAndOffset & OFFSET_MASK) + == UnsafeUtil.getInt(other, presenceMaskAndOffset & OFFSET_MASK); + } + + private void setOneofPresent(T message, int fieldNumber, int pos) { + int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos); + UnsafeUtil.putInt(message, presenceMaskAndOffset & OFFSET_MASK, fieldNumber); + } + + private int positionForFieldNumber(final int number) { + if (number >= minFieldNumber && number <= maxFieldNumber) { + return slowPositionForFieldNumber(number, 0); + } + return -1; + } + + private int positionForFieldNumber(final int number, final int min) { + if (number >= minFieldNumber && number <= maxFieldNumber) { + return slowPositionForFieldNumber(number, min); + } + return -1; + } + + private int slowPositionForFieldNumber(final int number, int min) { + int max = buffer.length / INTS_PER_FIELD - 1; + while (min <= max) { + // Find the midpoint address. + final int mid = (max + min) >>> 1; + final int pos = mid * INTS_PER_FIELD; + final int midFieldNumber = numberAt(pos); + if (number == midFieldNumber) { + // Found the field. + return pos; + } + if (number < midFieldNumber) { + // Search the lower half. + max = mid - 1; + } else { + // Search the upper half. + min = mid + 1; + } + } + return -1; + } + + int getSchemaSize() { + return buffer.length * 3; + } +} diff --git a/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java new file mode 100644 index 0000000000000..187dc8b8a5e13 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java @@ -0,0 +1,392 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; +import java.util.Iterator; +import java.util.Map.Entry; + +/** Schema used for proto2 messages using message_set_wireformat. */ +final class MessageSetSchema implements Schema { + private final MessageLite defaultInstance; + private final UnknownFieldSchema unknownFieldSchema; + private final boolean hasExtensions; + private final ExtensionSchema extensionSchema; + + private MessageSetSchema( + UnknownFieldSchema unknownFieldSchema, + ExtensionSchema extensionSchema, + MessageLite defaultInstance) { + this.unknownFieldSchema = unknownFieldSchema; + this.hasExtensions = extensionSchema.hasExtensions(defaultInstance); + this.extensionSchema = extensionSchema; + this.defaultInstance = defaultInstance; + } + + static MessageSetSchema newSchema( + UnknownFieldSchema unknownFieldSchema, + ExtensionSchema extensionSchema, + MessageLite defaultInstance) { + return new MessageSetSchema(unknownFieldSchema, extensionSchema, defaultInstance); + } + + @SuppressWarnings("unchecked") + @Override + public T newInstance() { + return (T) defaultInstance.newBuilderForType().buildPartial(); + } + + @Override + public boolean equals(T message, T other) { + Object messageUnknown = unknownFieldSchema.getFromMessage(message); + Object otherUnknown = unknownFieldSchema.getFromMessage(other); + if (!messageUnknown.equals(otherUnknown)) { + return false; + } + if (hasExtensions) { + FieldSet messageExtensions = extensionSchema.getExtensions(message); + FieldSet otherExtensions = extensionSchema.getExtensions(other); + return messageExtensions.equals(otherExtensions); + } + return true; + } + + @Override + public int hashCode(T message) { + int hashCode = unknownFieldSchema.getFromMessage(message).hashCode(); + if (hasExtensions) { + FieldSet extensions = extensionSchema.getExtensions(message); + hashCode = (hashCode * 53) + extensions.hashCode(); + } + return hashCode; + } + + @Override + public void mergeFrom(T message, T other) { + SchemaUtil.mergeUnknownFields(unknownFieldSchema, message, other); + if (hasExtensions) { + SchemaUtil.mergeExtensions(extensionSchema, message, other); + } + } + + @SuppressWarnings("unchecked") + @Override + public void writeTo(T message, Writer writer) throws IOException { + FieldSet extensions = extensionSchema.getExtensions(message); + Iterator iterator = extensions.iterator(); + while (iterator.hasNext()) { + Entry extension = (Entry) iterator.next(); + FieldSet.FieldDescriptorLite fd = (FieldSet.FieldDescriptorLite) extension.getKey(); + if (fd.getLiteJavaType() != WireFormat.JavaType.MESSAGE || fd.isRepeated() || fd.isPacked()) { + throw new IllegalStateException("Found invalid MessageSet item."); + } + if (extension instanceof LazyField.LazyEntry) { + writer.writeMessageSetItem( + fd.getNumber(), ((LazyField.LazyEntry) extension).getField().toByteString()); + } else { + writer.writeMessageSetItem(fd.getNumber(), extension.getValue()); + } + } + writeUnknownFieldsHelper(unknownFieldSchema, message, writer); + } + + /** + * A helper method for wildcard capture of {@code unknownFieldSchema}. See: + * https://docs.oracle.com/javase/tutorial/java/generics/capture.html + */ + private void writeUnknownFieldsHelper( + UnknownFieldSchema unknownFieldSchema, T message, Writer writer) throws IOException { + unknownFieldSchema.writeAsMessageSetTo(unknownFieldSchema.getFromMessage(message), writer); + } + + @SuppressWarnings("ReferenceEquality") + @Override + public void mergeFrom( + T message, byte[] data, int position, int limit, ArrayDecoders.Registers registers) + throws IOException { + UnknownFieldSetLite unknownFields = ((GeneratedMessageLite) message).unknownFields; + if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) { + unknownFields = UnknownFieldSetLite.newInstance(); + ((GeneratedMessageLite) message).unknownFields = unknownFields; + } + final FieldSet extensions = + ((GeneratedMessageLite.ExtendableMessage) message).ensureExtensionsAreMutable(); + GeneratedMessageLite.GeneratedExtension extension = null; + while (position < limit) { + position = ArrayDecoders.decodeVarint32(data, position, registers); + final int startTag = registers.int1; + if (startTag != WireFormat.MESSAGE_SET_ITEM_TAG) { + if (WireFormat.getTagWireType(startTag) == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + extension = + (GeneratedMessageLite.GeneratedExtension) extensionSchema.findExtensionByNumber( + registers.extensionRegistry, defaultInstance, + WireFormat.getTagFieldNumber(startTag)); + if (extension != null) { + position = + ArrayDecoders.decodeMessageField( + Protobuf.getInstance().schemaFor( + extension.getMessageDefaultInstance().getClass()), + data, position, limit, registers); + extensions.setField(extension.descriptor, registers.object1); + } else { + position = + ArrayDecoders.decodeUnknownField( + startTag, data, position, limit, unknownFields, registers); + } + } else { + position = ArrayDecoders.skipField(startTag, data, position, limit, registers); + } + continue; + } + + int typeId = 0; + ByteString rawBytes = null; + + while (position < limit) { + position = ArrayDecoders.decodeVarint32(data, position, registers); + final int tag = registers.int1; + final int number = WireFormat.getTagFieldNumber(tag); + final int wireType = WireFormat.getTagWireType(tag); + switch (number) { + case WireFormat.MESSAGE_SET_TYPE_ID: + if (wireType == WireFormat.WIRETYPE_VARINT) { + position = ArrayDecoders.decodeVarint32(data, position, registers); + typeId = registers.int1; + extension = + (GeneratedMessageLite.GeneratedExtension) extensionSchema + .findExtensionByNumber(registers.extensionRegistry, defaultInstance, typeId); + continue; + } + break; + case WireFormat.MESSAGE_SET_MESSAGE: + if (extension != null) { + position = ArrayDecoders.decodeMessageField( + Protobuf.getInstance().schemaFor( + extension.getMessageDefaultInstance().getClass()), + data, position, limit, registers); + extensions.setField(extension.descriptor, registers.object1); + continue; + } else { + if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + position = ArrayDecoders.decodeBytes(data, position, registers); + rawBytes = (ByteString) registers.object1; + continue; + } + break; + } + default: + break; + } + if (tag == WireFormat.MESSAGE_SET_ITEM_END_TAG) { + break; + } + position = ArrayDecoders.skipField(tag, data, position, limit, registers); + } + + if (rawBytes != null) { + unknownFields.storeField( + WireFormat.makeTag(typeId, WireFormat.WIRETYPE_LENGTH_DELIMITED), rawBytes); + } + } + if (position != limit) { + throw InvalidProtocolBufferException.parseFailure(); + } + } + + @Override + public void mergeFrom(T message, Reader reader, ExtensionRegistryLite extensionRegistry) + throws IOException { + mergeFromHelper(unknownFieldSchema, extensionSchema, message, reader, extensionRegistry); + } + + /** + * A helper method for wildcard capture of {@code unknownFieldSchema}. See: + * https://docs.oracle.com/javase/tutorial/java/generics/capture.html + */ + @SuppressWarnings("unchecked") + private > void mergeFromHelper( + UnknownFieldSchema unknownFieldSchema, + ExtensionSchema extensionSchema, + T message, + Reader reader, + ExtensionRegistryLite extensionRegistry) + throws IOException { + UB unknownFields = unknownFieldSchema.getBuilderFromMessage(message); + FieldSet extensions = extensionSchema.getMutableExtensions(message); + try { + while (true) { + final int number = reader.getFieldNumber(); + if (number == Reader.READ_DONE) { + return; + } + if (parseMessageSetItemOrUnknownField( + reader, + extensionRegistry, + extensionSchema, + extensions, + unknownFieldSchema, + unknownFields)) { + continue; + } + // Done reading. + return; + } + } finally { + unknownFieldSchema.setBuilderToMessage(message, unknownFields); + } + } + + @Override + public void makeImmutable(T message) { + unknownFieldSchema.makeImmutable(message); + extensionSchema.makeImmutable(message); + } + + private > + boolean parseMessageSetItemOrUnknownField( + Reader reader, + ExtensionRegistryLite extensionRegistry, + ExtensionSchema extensionSchema, + FieldSet extensions, + UnknownFieldSchema unknownFieldSchema, + UB unknownFields) + throws IOException { + int startTag = reader.getTag(); + if (startTag != WireFormat.MESSAGE_SET_ITEM_TAG) { + if (WireFormat.getTagWireType(startTag) == WireFormat.WIRETYPE_LENGTH_DELIMITED) { + Object extension = + extensionSchema.findExtensionByNumber( + extensionRegistry, defaultInstance, WireFormat.getTagFieldNumber(startTag)); + if (extension != null) { + extensionSchema.parseLengthPrefixedMessageSetItem( + reader, extension, extensionRegistry, extensions); + return true; + } else { + return unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader); + } + } else { + return reader.skipField(); + } + } + + // The wire format for MessageSet is: + // message MessageSet { + // repeated group Item = 1 { + // required int32 typeId = 2; + // required bytes message = 3; + // } + // } + // "typeId" is the extension's field number. The extension can only be + // a message type, where "message" contains the encoded bytes of that + // message. + // + // In practice, we will probably never see a MessageSet item in which + // the message appears before the type ID, or where either field does not + // appear exactly once. However, in theory such cases are valid, so we + // should be prepared to accept them. + + int typeId = 0; + ByteString rawBytes = null; // If we encounter "message" before "typeId" + Object extension = null; + + // Read bytes from input, if we get it's type first then parse it eagerly, + // otherwise we store the raw bytes in a local variable. + loop: + while (true) { + final int number = reader.getFieldNumber(); + if (number == Reader.READ_DONE) { + break; + } + + final int tag = reader.getTag(); + if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) { + typeId = reader.readUInt32(); + extension = + extensionSchema.findExtensionByNumber(extensionRegistry, defaultInstance, typeId); + continue; + } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) { + if (extension != null) { + extensionSchema.parseLengthPrefixedMessageSetItem( + reader, extension, extensionRegistry, extensions); + continue; + } + // We haven't seen a type ID yet or we want parse message lazily. + rawBytes = reader.readBytes(); + continue; + } else { + if (!reader.skipField()) { + break loop; // End of group + } + } + } + + if (reader.getTag() != WireFormat.MESSAGE_SET_ITEM_END_TAG) { + throw InvalidProtocolBufferException.invalidEndTag(); + } + + // If there are any rawBytes left, it means the message content appears before the type ID. + if (rawBytes != null) { + if (extension != null) { // We known the type + // TODO(xiaofeng): Instead of reading into a temporary ByteString, maybe there is a way + // to read directly from Reader to the submessage? + extensionSchema.parseMessageSetItem(rawBytes, extension, extensionRegistry, extensions); + } else { + unknownFieldSchema.addLengthDelimited(unknownFields, typeId, rawBytes); + } + } + return true; + } + + @Override + public final boolean isInitialized(T message) { + FieldSet extensions = extensionSchema.getExtensions(message); + return extensions.isInitialized(); + } + + @Override + public int getSerializedSize(T message) { + int size = 0; + + size += getUnknownFieldsSerializedSize(unknownFieldSchema, message); + + if (hasExtensions) { + size += extensionSchema.getExtensions(message).getMessageSetSerializedSize(); + } + + return size; + } + + private int getUnknownFieldsSerializedSize( + UnknownFieldSchema schema, T message) { + UT unknowns = schema.getFromMessage(message); + return schema.getSerializedSizeAsMessageSet(unknowns); + } +} diff --git a/java/core/src/main/java/com/google/protobuf/MutabilityOracle.java b/java/core/src/main/java/com/google/protobuf/MutabilityOracle.java index 82b723c95df60..7c2f157567543 100644 --- a/java/core/src/main/java/com/google/protobuf/MutabilityOracle.java +++ b/java/core/src/main/java/com/google/protobuf/MutabilityOracle.java @@ -30,19 +30,16 @@ package com.google.protobuf; -/** - * Verifies that an object is mutable, throwing if not. - */ +/** Verifies that an object is mutable, throwing if not. */ interface MutabilityOracle { - static final MutabilityOracle IMMUTABLE = new MutabilityOracle() { - @Override - public void ensureMutable() { - throw new UnsupportedOperationException(); - } - }; + static final MutabilityOracle IMMUTABLE = + new MutabilityOracle() { + @Override + public void ensureMutable() { + throw new UnsupportedOperationException(); + } + }; - /** - * Throws an {@link UnsupportedOperationException} if not mutable. - */ + /** Throws an {@link UnsupportedOperationException} if not mutable. */ void ensureMutable(); } diff --git a/java/core/src/main/java/com/google/protobuf/NewInstanceSchema.java b/java/core/src/main/java/com/google/protobuf/NewInstanceSchema.java new file mode 100644 index 0000000000000..f2dbb8ef9cc11 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/NewInstanceSchema.java @@ -0,0 +1,36 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +interface NewInstanceSchema { + /** Create a new message instance given the default instance of the message type. */ + Object newInstance(Object defaultInstance); +} diff --git a/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaFull.java b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaFull.java new file mode 100644 index 0000000000000..3433b657e6cd1 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaFull.java @@ -0,0 +1,39 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +final class NewInstanceSchemaFull implements NewInstanceSchema { + @Override + public Object newInstance(Object defaultInstance) { + return ((GeneratedMessageV3) defaultInstance) + .newInstance(GeneratedMessageV3.UnusedPrivateParameter.INSTANCE); + } +} diff --git a/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaLite.java b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaLite.java new file mode 100644 index 0000000000000..9b922667638d2 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaLite.java @@ -0,0 +1,39 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +final class NewInstanceSchemaLite implements NewInstanceSchema { + @Override + public Object newInstance(Object defaultInstance) { + return ((GeneratedMessageLite) defaultInstance) + .dynamicMethod(GeneratedMessageLite.MethodToInvoke.NEW_MUTABLE_INSTANCE); + } +} diff --git a/java/core/src/main/java/com/google/protobuf/NewInstanceSchemas.java b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemas.java new file mode 100644 index 0000000000000..eff45f67b9c04 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemas.java @@ -0,0 +1,53 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +final class NewInstanceSchemas { + private static final NewInstanceSchema FULL_SCHEMA = loadSchemaForFullRuntime(); + private static final NewInstanceSchema LITE_SCHEMA = new NewInstanceSchemaLite(); + + static NewInstanceSchema full() { + return FULL_SCHEMA; + } + + static NewInstanceSchema lite() { + return LITE_SCHEMA; + } + + private static NewInstanceSchema loadSchemaForFullRuntime() { + try { + Class clazz = Class.forName("com.google.protobuf.NewInstanceSchemaFull"); + return (NewInstanceSchema) clazz.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + return null; + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/NioByteString.java b/java/core/src/main/java/com/google/protobuf/NioByteString.java index 76594809e8d65..1e594ff878c57 100644 --- a/java/core/src/main/java/com/google/protobuf/NioByteString.java +++ b/java/core/src/main/java/com/google/protobuf/NioByteString.java @@ -37,6 +37,7 @@ import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.OutputStream; +import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.InvalidMarkException; @@ -44,9 +45,7 @@ import java.util.Collections; import java.util.List; -/** - * A {@link ByteString} that wraps around a {@link ByteBuffer}. - */ +/** A {@link ByteString} that wraps around a {@link ByteBuffer}. */ final class NioByteString extends ByteString.LeafByteString { private final ByteBuffer buffer; @@ -60,16 +59,12 @@ final class NioByteString extends ByteString.LeafByteString { // ================================================================= // Serializable - /** - * Magic method that lets us override serialization behavior. - */ + /** Magic method that lets us override serialization behavior. */ private Object writeReplace() { return ByteString.copyFrom(buffer.slice()); } - /** - * Magic method that lets us override deserialization behavior. - */ + /** Magic method that lets us override deserialization behavior. */ private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws IOException { throw new InvalidObjectException("NioByteString instances are not to be serialized directly"); } @@ -87,6 +82,13 @@ public byte byteAt(int index) { } } + @Override + public byte internalByteAt(int index) { + // it isn't possible to avoid the bounds checking inside of ByteBuffer, so just use the default + // implementation. + return byteAt(index); + } + @Override public int size() { return buffer.remaining(); @@ -108,7 +110,7 @@ public ByteString substring(int beginIndex, int endIndex) { protected void copyToInternal( byte[] target, int sourceOffset, int targetOffset, int numberToCopy) { ByteBuffer slice = buffer.slice(); - slice.position(sourceOffset); + ((Buffer) slice).position(sourceOffset); slice.get(target, targetOffset, numberToCopy); } @@ -284,8 +286,8 @@ private ByteBuffer slice(int beginIndex, int endIndex) { } ByteBuffer slice = buffer.slice(); - slice.position(beginIndex - buffer.position()); - slice.limit(endIndex - buffer.position()); + ((Buffer) slice).position(beginIndex - buffer.position()); + ((Buffer) slice).limit(endIndex - buffer.position()); return slice; } } diff --git a/java/core/src/main/java/com/google/protobuf/OneofInfo.java b/java/core/src/main/java/com/google/protobuf/OneofInfo.java new file mode 100644 index 0000000000000..bc518fcadd93f --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/OneofInfo.java @@ -0,0 +1,66 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.lang.reflect.Field; + +/** Information for a oneof within a protobuf message. */ +// TODO(nathanmittler): make this private once all of experimental code is migrated to protobuf. +@ExperimentalApi +final class OneofInfo { + private final int id; + private final Field caseField; + private final Field valueField; + + public OneofInfo(int id, Field caseField, Field valueField) { + this.id = id; + this.caseField = caseField; + this.valueField = valueField; + } + + /** + * Returns the unique identifier of the oneof within the message. This is really just an index + * starting at zero. + */ + public int getId() { + return id; + } + + /** The {@code int} field containing the field number of the currently active member. */ + public Field getCaseField() { + return caseField; + } + + /** The {@link Object} field containing the value of the currently active member. */ + public Field getValueField() { + return valueField; + } +} diff --git a/java/core/src/main/java/com/google/protobuf/Parser.java b/java/core/src/main/java/com/google/protobuf/Parser.java index e07c68959a9af..22ee99b1891ba 100644 --- a/java/core/src/main/java/com/google/protobuf/Parser.java +++ b/java/core/src/main/java/com/google/protobuf/Parser.java @@ -36,7 +36,7 @@ /** * Abstract interface for parsing Protocol Messages. * - * The implementation should be stateless and thread-safe. + *

The implementation should be stateless and thread-safe. * *

All methods may throw {@link InvalidProtocolBufferException}. In the event of invalid data, * like an encoding error, the cause of the thrown exception will be {@code null}. However, if an @@ -55,39 +55,31 @@ public interface Parser { /** * Parses a message of {@code MessageType} from the input. * - *

Note: The caller should call - * {@link CodedInputStream#checkLastTagWas(int)} after calling this to - * verify that the last tag seen was the appropriate end-group tag, - * or zero for EOF. + *

Note: The caller should call {@link CodedInputStream#checkLastTagWas(int)} after calling + * this to verify that the last tag seen was the appropriate end-group tag, or zero for EOF. */ - public MessageType parseFrom(CodedInputStream input) - throws InvalidProtocolBufferException; + public MessageType parseFrom(CodedInputStream input) throws InvalidProtocolBufferException; /** - * Like {@link #parseFrom(CodedInputStream)}, but also parses extensions. - * The extensions that you want to be able to parse must be registered in - * {@code extensionRegistry}. Extensions not in the registry will be treated - * as unknown fields. + * Like {@link #parseFrom(CodedInputStream)}, but also parses extensions. The extensions that you + * want to be able to parse must be registered in {@code extensionRegistry}. Extensions not in the + * registry will be treated as unknown fields. */ - public MessageType parseFrom(CodedInputStream input, - ExtensionRegistryLite extensionRegistry) + public MessageType parseFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; /** - * Like {@link #parseFrom(CodedInputStream)}, but does not throw an - * exception if the message is missing required fields. Instead, a partial - * message is returned. + * Like {@link #parseFrom(CodedInputStream)}, but does not throw an exception if the message is + * missing required fields. Instead, a partial message is returned. */ - public MessageType parsePartialFrom(CodedInputStream input) - throws InvalidProtocolBufferException; + public MessageType parsePartialFrom(CodedInputStream input) throws InvalidProtocolBufferException; /** - * Like {@link #parseFrom(CodedInputStream input, ExtensionRegistryLite)}, - * but does not throw an exception if the message is missing required fields. - * Instead, a partial message is returned. + * Like {@link #parseFrom(CodedInputStream input, ExtensionRegistryLite)}, but does not throw an + * exception if the message is missing required fields. Instead, a partial message is returned. */ - public MessageType parsePartialFrom(CodedInputStream input, - ExtensionRegistryLite extensionRegistry) + public MessageType parsePartialFrom( + CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; // --------------------------------------------------------------- @@ -106,180 +98,145 @@ public MessageType parsePartialFrom(CodedInputStream input, public MessageType parseFrom(ByteBuffer data, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; /** - * Parses {@code data} as a message of {@code MessageType}. - * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}. + * Parses {@code data} as a message of {@code MessageType}. This is just a small wrapper around + * {@link #parseFrom(CodedInputStream)}. */ - public MessageType parseFrom(ByteString data) - throws InvalidProtocolBufferException; + public MessageType parseFrom(ByteString data) throws InvalidProtocolBufferException; /** - * Parses {@code data} as a message of {@code MessageType}. - * This is just a small wrapper around + * Parses {@code data} as a message of {@code MessageType}. This is just a small wrapper around * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}. */ - public MessageType parseFrom(ByteString data, - ExtensionRegistryLite extensionRegistry) + public MessageType parseFrom(ByteString data, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; /** - * Like {@link #parseFrom(ByteString)}, but does not throw an - * exception if the message is missing required fields. Instead, a partial - * message is returned. + * Like {@link #parseFrom(ByteString)}, but does not throw an exception if the message is missing + * required fields. Instead, a partial message is returned. */ - public MessageType parsePartialFrom(ByteString data) - throws InvalidProtocolBufferException; + public MessageType parsePartialFrom(ByteString data) throws InvalidProtocolBufferException; /** - * Like {@link #parseFrom(ByteString, ExtensionRegistryLite)}, - * but does not throw an exception if the message is missing required fields. - * Instead, a partial message is returned. + * Like {@link #parseFrom(ByteString, ExtensionRegistryLite)}, but does not throw an exception if + * the message is missing required fields. Instead, a partial message is returned. */ - public MessageType parsePartialFrom(ByteString data, - ExtensionRegistryLite extensionRegistry) + public MessageType parsePartialFrom(ByteString data, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; /** - * Parses {@code data} as a message of {@code MessageType}. - * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}. + * Parses {@code data} as a message of {@code MessageType}. This is just a small wrapper around + * {@link #parseFrom(CodedInputStream)}. */ - public MessageType parseFrom(byte[] data, int off, int len) - throws InvalidProtocolBufferException; + public MessageType parseFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException; /** - * Parses {@code data} as a message of {@code MessageType}. - * This is just a small wrapper around + * Parses {@code data} as a message of {@code MessageType}. This is just a small wrapper around * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}. */ - public MessageType parseFrom(byte[] data, int off, int len, - ExtensionRegistryLite extensionRegistry) + public MessageType parseFrom( + byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; /** - * Parses {@code data} as a message of {@code MessageType}. - * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}. + * Parses {@code data} as a message of {@code MessageType}. This is just a small wrapper around + * {@link #parseFrom(CodedInputStream)}. */ - public MessageType parseFrom(byte[] data) - throws InvalidProtocolBufferException; + public MessageType parseFrom(byte[] data) throws InvalidProtocolBufferException; /** - * Parses {@code data} as a message of {@code MessageType}. - * This is just a small wrapper around + * Parses {@code data} as a message of {@code MessageType}. This is just a small wrapper around * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}. */ - public MessageType parseFrom(byte[] data, - ExtensionRegistryLite extensionRegistry) + public MessageType parseFrom(byte[] data, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; /** - * Like {@link #parseFrom(byte[], int, int)}, but does not throw an - * exception if the message is missing required fields. Instead, a partial - * message is returned. + * Like {@link #parseFrom(byte[], int, int)}, but does not throw an exception if the message is + * missing required fields. Instead, a partial message is returned. */ public MessageType parsePartialFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException; /** - * Like {@link #parseFrom(ByteString, ExtensionRegistryLite)}, - * but does not throw an exception if the message is missing required fields. - * Instead, a partial message is returned. + * Like {@link #parseFrom(ByteString, ExtensionRegistryLite)}, but does not throw an exception if + * the message is missing required fields. Instead, a partial message is returned. */ - public MessageType parsePartialFrom(byte[] data, int off, int len, - ExtensionRegistryLite extensionRegistry) + public MessageType parsePartialFrom( + byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; /** - * Like {@link #parseFrom(byte[])}, but does not throw an - * exception if the message is missing required fields. Instead, a partial - * message is returned. + * Like {@link #parseFrom(byte[])}, but does not throw an exception if the message is missing + * required fields. Instead, a partial message is returned. */ - public MessageType parsePartialFrom(byte[] data) - throws InvalidProtocolBufferException; + public MessageType parsePartialFrom(byte[] data) throws InvalidProtocolBufferException; /** - * Like {@link #parseFrom(byte[], ExtensionRegistryLite)}, - * but does not throw an exception if the message is missing required fields. - * Instead, a partial message is returned. + * Like {@link #parseFrom(byte[], ExtensionRegistryLite)}, but does not throw an exception if the + * message is missing required fields. Instead, a partial message is returned. */ - public MessageType parsePartialFrom(byte[] data, - ExtensionRegistryLite extensionRegistry) + public MessageType parsePartialFrom(byte[] data, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; /** - * Parse a message of {@code MessageType} from {@code input}. - * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}. - * Note that this method always reads the entire input (unless it - * throws an exception). If you want it to stop earlier, you will need to - * wrap your input in some wrapper stream that limits reading. Or, use - * {@link MessageLite#writeDelimitedTo(java.io.OutputStream)} to write your - * message and {@link #parseDelimitedFrom(InputStream)} to read it. - *

- * Despite usually reading the entire input, this does not close the stream. + * Parse a message of {@code MessageType} from {@code input}. This is just a small wrapper around + * {@link #parseFrom(CodedInputStream)}. Note that this method always reads the entire + * input (unless it throws an exception). If you want it to stop earlier, you will need to wrap + * your input in some wrapper stream that limits reading. Or, use {@link + * MessageLite#writeDelimitedTo(java.io.OutputStream)} to write your message and {@link + * #parseDelimitedFrom(InputStream)} to read it. + * + *

Despite usually reading the entire input, this does not close the stream. */ - public MessageType parseFrom(InputStream input) - throws InvalidProtocolBufferException; + public MessageType parseFrom(InputStream input) throws InvalidProtocolBufferException; /** - * Parses a message of {@code MessageType} from {@code input}. - * This is just a small wrapper around + * Parses a message of {@code MessageType} from {@code input}. This is just a small wrapper around * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}. */ - public MessageType parseFrom(InputStream input, - ExtensionRegistryLite extensionRegistry) + public MessageType parseFrom(InputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; /** - * Like {@link #parseFrom(InputStream)}, but does not throw an - * exception if the message is missing required fields. Instead, a partial - * message is returned. + * Like {@link #parseFrom(InputStream)}, but does not throw an exception if the message is missing + * required fields. Instead, a partial message is returned. */ - public MessageType parsePartialFrom(InputStream input) - throws InvalidProtocolBufferException; + public MessageType parsePartialFrom(InputStream input) throws InvalidProtocolBufferException; /** - * Like {@link #parseFrom(InputStream, ExtensionRegistryLite)}, - * but does not throw an exception if the message is missing required fields. - * Instead, a partial message is returned. + * Like {@link #parseFrom(InputStream, ExtensionRegistryLite)}, but does not throw an exception if + * the message is missing required fields. Instead, a partial message is returned. */ - public MessageType parsePartialFrom(InputStream input, - ExtensionRegistryLite extensionRegistry) + public MessageType parsePartialFrom(InputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; /** - * Like {@link #parseFrom(InputStream)}, but does not read util EOF. - * Instead, the size of message (encoded as a varint) is read first, - * then the message data. Use - * {@link MessageLite#writeDelimitedTo(java.io.OutputStream)} to write - * messages in this format. + * Like {@link #parseFrom(InputStream)}, but does not read until EOF. Instead, the size of message + * (encoded as a varint) is read first, then the message data. Use {@link + * MessageLite#writeDelimitedTo(java.io.OutputStream)} to write messages in this format. * - * @return Parsed message if successful, or null if the stream is at EOF when - * the method starts. Any other error (including reaching EOF during - * parsing) will cause an exception to be thrown. + * @return Parsed message if successful, or null if the stream is at EOF when the method starts. + * Any other error (including reaching EOF during parsing) will cause an exception to be + * thrown. */ - public MessageType parseDelimitedFrom(InputStream input) - throws InvalidProtocolBufferException; + public MessageType parseDelimitedFrom(InputStream input) throws InvalidProtocolBufferException; - /** - * Like {@link #parseDelimitedFrom(InputStream)} but supporting extensions. - */ - public MessageType parseDelimitedFrom(InputStream input, - ExtensionRegistryLite extensionRegistry) + /** Like {@link #parseDelimitedFrom(InputStream)} but supporting extensions. */ + public MessageType parseDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; /** - * Like {@link #parseDelimitedFrom(InputStream)}, but does not throw an - * exception if the message is missing required fields. Instead, a partial - * message is returned. + * Like {@link #parseDelimitedFrom(InputStream)}, but does not throw an exception if the message + * is missing required fields. Instead, a partial message is returned. */ public MessageType parsePartialDelimitedFrom(InputStream input) throws InvalidProtocolBufferException; /** - * Like {@link #parseDelimitedFrom(InputStream, ExtensionRegistryLite)}, - * but does not throw an exception if the message is missing required fields. - * Instead, a partial message is returned. + * Like {@link #parseDelimitedFrom(InputStream, ExtensionRegistryLite)}, but does not throw an + * exception if the message is missing required fields. Instead, a partial message is returned. */ public MessageType parsePartialDelimitedFrom( - InputStream input, - ExtensionRegistryLite extensionRegistry) + InputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; } diff --git a/java/core/src/main/java/com/google/protobuf/ProtoSyntax.java b/java/core/src/main/java/com/google/protobuf/ProtoSyntax.java new file mode 100644 index 0000000000000..851b839f6fbda --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/ProtoSyntax.java @@ -0,0 +1,38 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** Represents the syntax version of the message. */ +@ExperimentalApi +public enum ProtoSyntax { + PROTO2, + PROTO3; +} diff --git a/java/core/src/main/java/com/google/protobuf/Protobuf.java b/java/core/src/main/java/com/google/protobuf/Protobuf.java new file mode 100644 index 0000000000000..0affac5f0a40c --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/Protobuf.java @@ -0,0 +1,149 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.Internal.checkNotNull; + +import java.io.IOException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * Main runtime interface for protobuf. Applications should interact with this interface (rather + * than directly accessing internal APIs) in order to perform operations on protobuf messages. + */ +@ExperimentalApi +final class Protobuf { + private static final Protobuf INSTANCE = new Protobuf(); + + private final SchemaFactory schemaFactory; + + // TODO(nathanmittler): Consider using ClassValue instead. + private final ConcurrentMap, Schema> schemaCache = + new ConcurrentHashMap, Schema>(); + + /** Gets the singleton instance of the Protobuf runtime. */ + public static Protobuf getInstance() { + return INSTANCE; + } + + /** Writes the given message to the target {@link Writer}. */ + public void writeTo(T message, Writer writer) throws IOException { + schemaFor(message).writeTo(message, writer); + } + + /** Reads fields from the given {@link Reader} and merges them into the message. */ + public void mergeFrom(T message, Reader reader) throws IOException { + mergeFrom(message, reader, ExtensionRegistryLite.getEmptyRegistry()); + } + + /** Reads fields from the given {@link Reader} and merges them into the message. */ + public void mergeFrom(T message, Reader reader, ExtensionRegistryLite extensionRegistry) + throws IOException { + schemaFor(message).mergeFrom(message, reader, extensionRegistry); + } + + /** Marks repeated/map/extension/unknown fields as immutable. */ + public void makeImmutable(T message) { + schemaFor(message).makeImmutable(message); + } + + /** Checks if all required fields are set. */ + boolean isInitialized(T message) { + return schemaFor(message).isInitialized(message); + } + + /** Gets the schema for the given message type. */ + public Schema schemaFor(Class messageType) { + checkNotNull(messageType, "messageType"); + @SuppressWarnings("unchecked") + Schema schema = (Schema) schemaCache.get(messageType); + if (schema == null) { + schema = schemaFactory.createSchema(messageType); + @SuppressWarnings("unchecked") + Schema previous = (Schema) registerSchema(messageType, schema); + if (previous != null) { + // A new schema was registered by another thread. + schema = previous; + } + } + return schema; + } + + /** Gets the schema for the given message. */ + @SuppressWarnings("unchecked") + public Schema schemaFor(T message) { + return schemaFor((Class) message.getClass()); + } + + /** + * Registers the given schema for the message type only if a schema was not already registered. + * + * @param messageType the type of message on which the schema operates. + * @param schema the schema for the message type. + * @return the previously registered schema, or {@code null} if the given schema was successfully + * registered. + */ + public Schema registerSchema(Class messageType, Schema schema) { + checkNotNull(messageType, "messageType"); + checkNotNull(schema, "schema"); + return schemaCache.putIfAbsent(messageType, schema); + } + + /** + * Visible for testing only. Registers the given schema for the message type. If a schema was + * previously registered, it will be replaced by the provided schema. + * + * @param messageType the type of message on which the schema operates. + * @param schema the schema for the message type. + * @return the previously registered schema, or {@code null} if no schema was registered + * previously. + */ + public Schema registerSchemaOverride(Class messageType, Schema schema) { + checkNotNull(messageType, "messageType"); + checkNotNull(schema, "schema"); + return schemaCache.put(messageType, schema); + } + + private Protobuf() { + schemaFactory = new ManifestSchemaFactory(); + } + + int getTotalSchemaSize() { + int result = 0; + for (Schema schema : schemaCache.values()) { + if (schema instanceof MessageSchema) { + result += ((MessageSchema) schema).getSchemaSize(); + } + } + return result; + } +} diff --git a/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java b/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java index 81255ec29125b..33e4bd5e35e2d 100644 --- a/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java @@ -31,75 +31,145 @@ package com.google.protobuf; import com.google.protobuf.Internal.ProtobufList; +import java.util.Arrays; +import java.util.RandomAccess; -import java.util.ArrayList; -import java.util.List; +/** Implements {@link ProtobufList} for non-primitive and {@link String} types. */ +final class ProtobufArrayList extends AbstractProtobufList implements RandomAccess { -/** - * Implements {@link ProtobufList} for non-primitive and {@link String} types. - */ -final class ProtobufArrayList extends AbstractProtobufList { + private static final ProtobufArrayList EMPTY_LIST = + new ProtobufArrayList(new Object[0], 0); - private static final ProtobufArrayList EMPTY_LIST = new ProtobufArrayList(); static { EMPTY_LIST.makeImmutable(); } - + @SuppressWarnings("unchecked") // Guaranteed safe by runtime. public static ProtobufArrayList emptyList() { return (ProtobufArrayList) EMPTY_LIST; } - - private final List list; + private E[] array; + private int size; + + @SuppressWarnings("unchecked") ProtobufArrayList() { - this(new ArrayList(DEFAULT_CAPACITY)); + this((E[]) new Object[DEFAULT_CAPACITY], 0); } - - private ProtobufArrayList(List list) { - this.list = list; + + private ProtobufArrayList(E[] array, int size) { + this.array = array; + this.size = size; } @Override public ProtobufArrayList mutableCopyWithCapacity(int capacity) { - if (capacity < size()) { + if (capacity < size) { throw new IllegalArgumentException(); } - List newList = new ArrayList(capacity); - newList.addAll(list); - return new ProtobufArrayList(newList); + + E[] newArray = Arrays.copyOf(array, capacity); + + return new ProtobufArrayList(newArray, size); } - + + @Override + public boolean add(E element) { + ensureIsMutable(); + + if (size == array.length) { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + E[] newArray = Arrays.copyOf(array, length); + + array = newArray; + } + + array[size++] = element; + modCount++; + + return true; + } + @Override public void add(int index, E element) { ensureIsMutable(); - list.add(index, element); + + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); + } + + if (size < array.length) { + // Shift everything over to make room + System.arraycopy(array, index, array, index + 1, size - index); + } else { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + E[] newArray = createArray(length); + + // Copy the first part directly + System.arraycopy(array, 0, newArray, 0, index); + + // Copy the rest shifted over by one to make room + System.arraycopy(array, index, newArray, index + 1, size - index); + array = newArray; + } + + array[index] = element; + size++; modCount++; } @Override public E get(int index) { - return list.get(index); + ensureIndexInRange(index); + return array[index]; } - + @Override public E remove(int index) { ensureIsMutable(); - E toReturn = list.remove(index); + ensureIndexInRange(index); + + E value = array[index]; + if (index < size - 1) { + System.arraycopy(array, index + 1, array, index, size - index - 1); + } + + size--; modCount++; - return toReturn; + return value; } - + @Override public E set(int index, E element) { ensureIsMutable(); - E toReturn = list.set(index, element); + ensureIndexInRange(index); + + E toReturn = array[index]; + array[index] = element; + modCount++; return toReturn; } @Override public int size() { - return list.size(); + return size; + } + + @SuppressWarnings("unchecked") + private static E[] createArray(int capacity) { + return (E[]) new Object[capacity]; + } + + private void ensureIndexInRange(int index) { + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); + } + } + + private String makeOutOfBoundsExceptionMessage(int index) { + return "Index:" + index + ", Size:" + size; } } diff --git a/java/core/src/main/java/com/google/protobuf/ProtobufLists.java b/java/core/src/main/java/com/google/protobuf/ProtobufLists.java new file mode 100644 index 0000000000000..271c849b4d41e --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/ProtobufLists.java @@ -0,0 +1,94 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.Internal.BooleanList; +import com.google.protobuf.Internal.DoubleList; +import com.google.protobuf.Internal.FloatList; +import com.google.protobuf.Internal.IntList; +import com.google.protobuf.Internal.LongList; +import com.google.protobuf.Internal.ProtobufList; + +/** Utility class for construction of lists that extend {@link ProtobufList}. */ +@ExperimentalApi +final class ProtobufLists { + private ProtobufLists() {} + + public static ProtobufList emptyProtobufList() { + return ProtobufArrayList.emptyList(); + } + + public static ProtobufList mutableCopy(ProtobufList list) { + int size = list.size(); + return list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + } + + public static BooleanList emptyBooleanList() { + return BooleanArrayList.emptyList(); + } + + public static BooleanList newBooleanList() { + return new BooleanArrayList(); + } + + public static IntList emptyIntList() { + return IntArrayList.emptyList(); + } + + public static IntList newIntList() { + return new IntArrayList(); + } + + public static LongList emptyLongList() { + return LongArrayList.emptyList(); + } + + public static LongList newLongList() { + return new LongArrayList(); + } + + public static FloatList emptyFloatList() { + return FloatArrayList.emptyList(); + } + + public static FloatList newFloatList() { + return new FloatArrayList(); + } + + public static DoubleList emptyDoubleList() { + return DoubleArrayList.emptyList(); + } + + public static DoubleList newDoubleList() { + return new DoubleArrayList(); + } +} diff --git a/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java b/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java index a596d30190fd4..5d6f5ac442281 100644 --- a/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java +++ b/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java @@ -33,27 +33,20 @@ import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.EnumValueDescriptor; -/** - * Interface of useful methods added to all enums generated by the protocol - * compiler. - */ +/** Interface of useful methods added to all enums generated by the protocol compiler. */ public interface ProtocolMessageEnum extends Internal.EnumLite { - /** - * Return the value's numeric value as defined in the .proto file. - */ + /** Return the value's numeric value as defined in the .proto file. */ @Override int getNumber(); /** - * Return the value's descriptor, which contains information such as - * value name, number, and type. + * Return the value's descriptor, which contains information such as value name, number, and type. */ EnumValueDescriptor getValueDescriptor(); /** - * Return the enum type's descriptor, which contains information - * about each defined value, etc. + * Return the enum type's descriptor, which contains information about each defined value, etc. */ EnumDescriptor getDescriptorForType(); } diff --git a/java/core/src/main/java/com/google/protobuf/ProtocolStringList.java b/java/core/src/main/java/com/google/protobuf/ProtocolStringList.java index d553b41e52bcc..5df3dbdbdaf21 100644 --- a/java/core/src/main/java/com/google/protobuf/ProtocolStringList.java +++ b/java/core/src/main/java/com/google/protobuf/ProtocolStringList.java @@ -33,16 +33,14 @@ import java.util.List; /** - * An interface extending {@code List} used for repeated string fields - * to provide optional access to the data as a list of ByteStrings. The - * underlying implementation stores values as either ByteStrings or Strings - * (see {@link LazyStringArrayList}) depending on how the value was initialized - * or last read, and it is often more efficient to deal with lists of - * ByteStrings when handling protos that have been deserialized from bytes. + * An interface extending {@code List} used for repeated string fields to provide optional + * access to the data as a list of ByteStrings. The underlying implementation stores values as + * either ByteStrings or Strings (see {@link LazyStringArrayList}) depending on how the value was + * initialized or last read, and it is often more efficient to deal with lists of ByteStrings when + * handling protos that have been deserialized from bytes. */ public interface ProtocolStringList extends List { /** Returns a view of the data as a list of ByteStrings. */ List asByteStringList(); - } diff --git a/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java b/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java new file mode 100644 index 0000000000000..d66f5c4796d93 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java @@ -0,0 +1,245 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** + * RawMessageInfo stores the same amount of information as {@link MessageInfo} but in a more compact + * format. + */ +final class RawMessageInfo implements MessageInfo { + + private final MessageLite defaultInstance; + + /** + * The compact format packs everything in a String object and a Object[] array. The String object + * is encoded with field number, field type, hasbits offset, oneof index, etc., whereas the + * Object[] array contains field references, class references, instance references, etc. + * + *

The String object encodes a sequence of integers into UTF-16 characters. For each int, it + * will be encoding into 1 to 3 UTF-16 characters depending on its unsigned value: + * + *

    + *
  • 1 char: [c1: 0x0000 - 0xD7FF] = int of the same value. + *
  • 2 chars: [c1: 0xE000 - 0xFFFF], [c2: 0x0000 - 0xD7FF] = (c2 << 13) | (c1 & 0x1FFF) + *
  • 3 chars: [c1: 0xE000 - 0xFFFF], [c2: 0xE000 - 0xFFFF], [c3: 0x0000 - 0xD7FF] = (c3 << 26) + * | ((c2 & 0x1FFF) << 13) | (c1 & 0x1FFF) + *
+ * + *

Note that we don't use UTF-16 surrogate pairs [0xD800 - 0xDFFF] because they have to come in + * pairs to form a valid UTF-16char sequence and don't help us encode values more efficiently. + * + *

The integer sequence encoded in the String object has the following layout: + * + *

    + *
  • [0]: flags, flags & 0x1 = is proto2?, flags & 0x2 = is message?. + *
  • [1]: field count, if 0, this is the end of the integer sequence and the corresponding + * Object[] array should be null. + *
  • [2]: oneof count + *
  • [3]: hasbits count, how many hasbits integers are generated. + *
  • [4]: min field number + *
  • [5]: max field number + *
  • [6]: total number of entries need to allocate + *
  • [7]: map field count + *
  • [8]: repeated field count, this doesn't include map fields. + *
  • [9]: size of checkInitialized array + *
  • [...]: field entries + *
+ * + *

Each field entry starts with a field number and the field type: + * + *

    + *
  • [0]: field number + *
  • [1]: field type with extra bits: + *
      + *
    • v & 0xFF = field type as defined in the FieldType class + *
    • v & 0x0100 = is required? + *
    • v & 0x0200 = is checkUtf8? + *
    • v & 0x0400 = needs isInitialized check? + *
    • v & 0x0800 = is map field with proto2 enum value? + *
    • v & 0x1000 = supports presence checking? + *
    + *
+ * + * If the (singular) field supports presence checking: + * + *
    + *
  • [2]: hasbits offset + *
+ * + * If the field is in an oneof: + * + *
    + *
  • [2]: oneof index + *
+ * + * For other types, the field entry only has field number and field type. + * + *

The Object[] array has 3 sections: + * + *

    + *
  • ---- oneof section ---- + *
      + *
    • [0]: value field for oneof 1. + *
    • [1]: case field for oneof 1. + *
    • ... + *
    • [.]: value field for oneof n. + *
    • [.]: case field for oneof n. + *
    + *
  • ---- hasbits section ---- + *
      + *
    • [.]: hasbits field 1 + *
    • [.]: hasbits field 2 + *
    • ... + *
    • [.]: hasbits field n + *
    + *
  • ---- field section ---- + *
      + *
    • [...]: field entries + *
    + *
+ * + *

In the Object[] array, field entries are ordered in the same way as field entries in the + * String object. The size of each entry is determined by the field type. + * + *

    + *
  • Oneof field: + *
      + *
    • Oneof message field: + *
        + *
      • [0]: message class reference. + *
      + *
    • Oneof enum fieldin proto2: + *
        + *
      • [0]: EnumLiteMap + *
      + *
    • For all other oneof fields, field entry in the Object[] array is empty. + *
    + *
  • Repeated message field: + *
      + *
    • [0]: field reference + *
    • [1]: message class reference + *
    + *
  • Proto2 singular/repeated enum field: + *
      + *
    • [0]: field reference + *
    • [1]: EnumLiteMap + *
    + *
  • Map field with a proto2 enum value: + *
      + *
    • [0]: field reference + *
    • [1]: map default entry instance + *
    • [2]: EnumLiteMap + *
    + *
  • Map field with other value types: + *
      + *
    • [0]: field reference + *
    • [1]: map default entry instance + *
    + *
  • All other field type: + *
      + *
    • [0]: field reference + *
    + *
+ * + *

In order to read the field info from this compact format, a reader needs to progress through + * the String object and the Object[] array simultaneously. + */ + private final String info; + + private final Object[] objects; + private final int flags; + + RawMessageInfo(MessageLite defaultInstance, String info, Object[] objects) { + this.defaultInstance = defaultInstance; + this.info = info; + this.objects = objects; + int value; + try { + value = (int) info.charAt(0); + } catch (StringIndexOutOfBoundsException e) { + // This is a fix for issues + // that error out on a subset of phones on charAt(0) with an index out of bounds exception. + char[] infoChars = info.toCharArray(); + info = new String(infoChars); + try { + value = (int) info.charAt(0); + } catch (StringIndexOutOfBoundsException e2) { + try { + char[] infoChars2 = new char[info.length()]; + info.getChars(0, info.length(), infoChars2, 0); + info = new String(infoChars2); + value = (int) info.charAt(0); + } catch (StringIndexOutOfBoundsException | ArrayIndexOutOfBoundsException e3) { + throw new IllegalStateException( + String.format( + "Failed parsing '%s' with charArray.length of %d", info, infoChars.length), + e3); + } + } + } + int position = 1; + + if (value < 0xD800) { + flags = value; + } else { + int result = value & 0x1FFF; + int shift = 13; + while ((value = info.charAt(position++)) >= 0xD800) { + result |= (value & 0x1FFF) << shift; + shift += 13; + } + flags = result | (value << shift); + } + } + + String getStringInfo() { + return info; + } + + Object[] getObjects() { + return objects; + } + + @Override + public MessageLite getDefaultInstance() { + return defaultInstance; + } + + @Override + public ProtoSyntax getSyntax() { + return (flags & 0x1) == 0x1 ? ProtoSyntax.PROTO2 : ProtoSyntax.PROTO3; + } + + @Override + public boolean isMessageSetWireFormat() { + return (flags & 0x2) == 0x2; + } +} diff --git a/java/core/src/main/java/com/google/protobuf/Reader.java b/java/core/src/main/java/com/google/protobuf/Reader.java new file mode 100644 index 0000000000000..705096f2d80e2 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/Reader.java @@ -0,0 +1,379 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +/** A reader of fields from a serialized protobuf message. */ +// TODO(nathanmittler): Refactor to allow the reader to allocate properly sized lists. +@ExperimentalApi +interface Reader { + /** Value used to indicate that the end of input has been reached. */ + int READ_DONE = Integer.MAX_VALUE; + + /** Value used to indicate that the reader does not know the tag about the field. */ + int TAG_UNKNOWN = 0; + + boolean shouldDiscardUnknownFields(); + + /** + * Gets the field number for the current field being read. + * + *

TODO(liujisi): Rename it to make it more explicit about the side effect on the underlying + * buffer. + * + * @return the current field number or {@link #READ_DONE} if the end of input has been reached. + */ + int getFieldNumber() throws IOException; + + /** + * Gets the wire tag of the current field. + * + * @return the current wire tag or {@link #TAG_UNKNOWN} if the reader does not know the tag of the + * current field. + */ + int getTag(); + + /** + * Skips the current field and advances the reader to the next field. + * + * @return {@code true} if there are more fields or {@code false} if the end of input has been + * reached. + */ + boolean skipField() throws IOException; + + /** + * Reads and returns the next field of type {@code DOUBLE} and advances the reader to the next + * field. + */ + double readDouble() throws IOException; + + /** + * Reads and returns the next field of type {@code FLOAT} and advances the reader to the next + * field. + */ + float readFloat() throws IOException; + + /** + * Reads and returns the next field of type {@code UINT64} and advances the reader to the next + * field. + */ + long readUInt64() throws IOException; + + /** + * Reads and returns the next field of type {@code INT64} and advances the reader to the next + * field. + */ + long readInt64() throws IOException; + + /** + * Reads and returns the next field of type {@code INT32} and advances the reader to the next + * field. + */ + int readInt32() throws IOException; + + /** + * Reads and returns the next field of type {@code FIXED64} and advances the reader to the next + * field. + */ + long readFixed64() throws IOException; + + /** + * Reads and returns the next field of type {@code FIXED32} and advances the reader to the next + * field. + */ + int readFixed32() throws IOException; + + /** + * Reads and returns the next field of type {@code BOOL} and advances the reader to the next + * field. + */ + boolean readBool() throws IOException; + + /** + * Reads and returns the next field of type {@code STRING} and advances the reader to the next + * field. If the stream contains malformed UTF-8, replace the offending bytes with the standard + * UTF-8 replacement character. + */ + String readString() throws IOException; + + /** + * Reads and returns the next field of type {@code STRING} and advances the reader to the next + * field. If the stream contains malformed UTF-8, throw exception {@link + * InvalidProtocolBufferException}. + */ + String readStringRequireUtf8() throws IOException; + + // TODO(yilunchong): the lack of other opinions for whether to expose this on the interface + T readMessageBySchemaWithCheck(Schema schema, ExtensionRegistryLite extensionRegistry) + throws IOException; + + /** + * Reads and returns the next field of type {@code MESSAGE} and advances the reader to the next + * field. + */ + T readMessage(Class clazz, ExtensionRegistryLite extensionRegistry) throws IOException; + + /** + * Reads and returns the next field of type {@code GROUP} and advances the reader to the next + * field. + * + * @deprecated groups fields are deprecated. + */ + @Deprecated + T readGroup(Class clazz, ExtensionRegistryLite extensionRegistry) throws IOException; + + // TODO(yilunchong): the lack of other opinions for whether to expose this on the interface + @Deprecated + T readGroupBySchemaWithCheck(Schema schema, ExtensionRegistryLite extensionRegistry) + throws IOException; + + /** + * Reads and returns the next field of type {@code BYTES} and advances the reader to the next + * field. + */ + ByteString readBytes() throws IOException; + + /** + * Reads and returns the next field of type {@code UINT32} and advances the reader to the next + * field. + */ + int readUInt32() throws IOException; + + /** + * Reads and returns the next field of type {@code ENUM} and advances the reader to the next + * field. + */ + int readEnum() throws IOException; + + /** + * Reads and returns the next field of type {@code SFIXED32} and advances the reader to the next + * field. + */ + int readSFixed32() throws IOException; + + /** + * Reads and returns the next field of type {@code SFIXED64} and advances the reader to the next + * field. + */ + long readSFixed64() throws IOException; + + /** + * Reads and returns the next field of type {@code SINT32} and advances the reader to the next + * field. + */ + int readSInt32() throws IOException; + + /** + * Reads and returns the next field of type {@code SINT64} and advances the reader to the next + * field. + */ + long readSInt64() throws IOException; + + /** + * Reads the next field of type {@code DOUBLE_LIST} or {@code DOUBLE_LIST_PACKED} and advances the + * reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readDoubleList(List target) throws IOException; + + /** + * Reads the next field of type {@code FLOAT_LIST} or {@code FLOAT_LIST_PACKED} and advances the + * reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readFloatList(List target) throws IOException; + + /** + * Reads the next field of type {@code UINT64_LIST} or {@code UINT64_LIST_PACKED} and advances the + * reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readUInt64List(List target) throws IOException; + + /** + * Reads the next field of type {@code INT64_LIST} or {@code INT64_LIST_PACKED} and advances the + * reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readInt64List(List target) throws IOException; + + /** + * Reads the next field of type {@code INT32_LIST} or {@code INT32_LIST_PACKED} and advances the + * reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readInt32List(List target) throws IOException; + + /** + * Reads the next field of type {@code FIXED64_LIST} or {@code FIXED64_LIST_PACKED} and advances + * the reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readFixed64List(List target) throws IOException; + + /** + * Reads the next field of type {@code FIXED32_LIST} or {@code FIXED32_LIST_PACKED} and advances + * the reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readFixed32List(List target) throws IOException; + + /** + * Reads the next field of type {@code BOOL_LIST} or {@code BOOL_LIST_PACKED} and advances the + * reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readBoolList(List target) throws IOException; + + /** + * Reads the next field of type {@code STRING_LIST} and advances the reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readStringList(List target) throws IOException; + + /** + * Reads the next field of type {@code STRING_LIST} and advances the reader to the next field. If + * the stream contains malformed UTF-8, throw exception {@link InvalidProtocolBufferException}. + * + * @param target the list that will receive the read values. + */ + void readStringListRequireUtf8(List target) throws IOException; + + /** + * Reads the next field of type {@code MESSAGE_LIST} and advances the reader to the next field. + * + * @param target the list that will receive the read values. + * @param targetType the type of the elements stored in the {@code target} list. + */ + void readMessageList( + List target, Schema schema, ExtensionRegistryLite extensionRegistry) throws IOException; + + void readMessageList( + List target, Class targetType, ExtensionRegistryLite extensionRegistry) + throws IOException; + + /** + * Reads the next field of type {@code GROUP_LIST} and advances the reader to the next field. + * + * @param target the list that will receive the read values. + * @param targetType the type of the elements stored in the {@code target} list. + * @deprecated groups fields are deprecated. + */ + @Deprecated + void readGroupList( + List target, Class targetType, ExtensionRegistryLite extensionRegistry) + throws IOException; + + @Deprecated + void readGroupList( + List target, Schema targetType, ExtensionRegistryLite extensionRegistry) + throws IOException; + + /** + * Reads the next field of type {@code BYTES_LIST} and advances the reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readBytesList(List target) throws IOException; + + /** + * Reads the next field of type {@code UINT32_LIST} or {@code UINT32_LIST_PACKED} and advances the + * reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readUInt32List(List target) throws IOException; + + /** + * Reads the next field of type {@code ENUM_LIST} or {@code ENUM_LIST_PACKED} and advances the + * reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readEnumList(List target) throws IOException; + + /** + * Reads the next field of type {@code SFIXED32_LIST} or {@code SFIXED32_LIST_PACKED} and advances + * the reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readSFixed32List(List target) throws IOException; + + /** + * Reads the next field of type {@code SFIXED64_LIST} or {@code SFIXED64_LIST_PACKED} and advances + * the reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readSFixed64List(List target) throws IOException; + + /** + * Reads the next field of type {@code SINT32_LIST} or {@code SINT32_LIST_PACKED} and advances the + * reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readSInt32List(List target) throws IOException; + + /** + * Reads the next field of type {@code SINT64_LIST} or {@code SINT64_LIST_PACKED} and advances the + * reader to the next field. + * + * @param target the list that will receive the read values. + */ + void readSInt64List(List target) throws IOException; + + /** + * Reads the next field of type {@code MAP} and advances the reader to the next field. + * + * @param target the mutable map that will receive the read values. + * @param mapDefaultEntry the default entry of the map field. + * @param extensionRegistry the extension registry for parsing message value fields. + */ + void readMap( + Map target, + MapEntryLite.Metadata mapDefaultEntry, + ExtensionRegistryLite extensionRegistry) + throws IOException; +} diff --git a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java index 29f567dcdec4f..f51436c83d23b 100644 --- a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java +++ b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java @@ -30,6 +30,8 @@ package com.google.protobuf; +import static com.google.protobuf.Internal.checkNotNull; + import java.util.AbstractList; import java.util.ArrayList; import java.util.Collection; @@ -37,36 +39,29 @@ import java.util.List; /** - * {@code RepeatedFieldBuilder} implements a structure that a protocol - * message uses to hold a repeated field of other protocol messages. It supports - * the classical use case of adding immutable {@link Message}'s to the - * repeated field and is highly optimized around this (no extra memory - * allocations and sharing of immutable arrays). - *
- * It also supports the additional use case of adding a {@link Message.Builder} - * to the repeated field and deferring conversion of that {@code Builder} - * to an immutable {@code Message}. In this way, it's possible to maintain - * a tree of {@code Builder}'s that acts as a fully read/write data - * structure. - *
- * Logically, one can think of a tree of builders as converting the entire tree - * to messages when build is called on the root or when any method is called - * that desires a Message instead of a Builder. In terms of the implementation, - * the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder} - * classes cache messages that were created so that messages only need to be - * created when some change occurred in its builder or a builder for one of its - * descendants. + * {@code RepeatedFieldBuilder} implements a structure that a protocol message uses to hold a + * repeated field of other protocol messages. It supports the classical use case of adding immutable + * {@link Message}'s to the repeated field and is highly optimized around this (no extra memory + * allocations and sharing of immutable arrays).
+ * It also supports the additional use case of adding a {@link Message.Builder} to the repeated + * field and deferring conversion of that {@code Builder} to an immutable {@code Message}. In this + * way, it's possible to maintain a tree of {@code Builder}'s that acts as a fully read/write data + * structure.
+ * Logically, one can think of a tree of builders as converting the entire tree to messages when + * build is called on the root or when any method is called that desires a Message instead of a + * Builder. In terms of the implementation, the {@code SingleFieldBuilder} and {@code + * RepeatedFieldBuilder} classes cache messages that were created so that messages only need to be + * created when some change occurred in its builder or a builder for one of its descendants. * * @param the type of message for the field * @param the type of builder for the field * @param the common interface for the message and the builder - * * @author jonp@google.com (Jon Perlow) */ -public class RepeatedFieldBuilder - +public class RepeatedFieldBuilder< + MType extends GeneratedMessage, + BType extends GeneratedMessage.Builder, + IType extends MessageOrBuilder> implements GeneratedMessage.BuilderParent { // Parent to send changes to. @@ -118,8 +113,7 @@ public class RepeatedFieldBuilder // is fully backed by this object and all changes are reflected in it. // Access to any item returns either a builder or message depending on // what is most efficient. - private MessageOrBuilderExternalList - externalMessageOrBuilderList; + private MessageOrBuilderExternalList externalMessageOrBuilderList; /** * Constructs a new builder with an empty list of messages. @@ -146,8 +140,8 @@ public void dispose() { } /** - * Ensures that the list of messages is mutable so it can be updated. If it's - * immutable, a copy is made. + * Ensures that the list of messages is mutable so it can be updated. If it's immutable, a copy is + * made. */ private void ensureMutableMessageList() { if (!isMessagesListMutable) { @@ -157,15 +151,12 @@ private void ensureMutableMessageList() { } /** - * Ensures that the list of builders is not null. If it's null, the list is - * created and initialized to be the same size as the messages list with - * null entries. + * Ensures that the list of builders is not null. If it's null, the list is created and + * initialized to be the same size as the messages list with null entries. */ private void ensureBuilders() { if (this.builders == null) { - this.builders = - new ArrayList>( - messages.size()); + this.builders = new ArrayList>(messages.size()); for (int i = 0; i < messages.size(); i++) { builders.add(null); } @@ -191,9 +182,9 @@ public boolean isEmpty() { } /** - * Get the message at the specified index. If the message is currently stored - * as a {@code Builder}, it is converted to a {@code Message} by - * calling {@link Message.Builder#buildPartial} on it. + * Get the message at the specified index. If the message is currently stored as a {@code + * Builder}, it is converted to a {@code Message} by calling {@link Message.Builder#buildPartial} + * on it. * * @param index the index of the message to get * @return the message for the specified index @@ -203,13 +194,13 @@ public MType getMessage(int index) { } /** - * Get the message at the specified index. If the message is currently stored - * as a {@code Builder}, it is converted to a {@code Message} by - * calling {@link Message.Builder#buildPartial} on it. + * Get the message at the specified index. If the message is currently stored as a {@code + * Builder}, it is converted to a {@code Message} by calling {@link Message.Builder#buildPartial} + * on it. * * @param index the index of the message to get - * @param forBuild this is being called for build so we want to make sure - * we SingleFieldBuilder.build to send dirty invalidations + * @param forBuild this is being called for build so we want to make sure we + * SingleFieldBuilder.build to send dirty invalidations * @return the message for the specified index */ private MType getMessage(int index, boolean forBuild) { @@ -233,9 +224,8 @@ private MType getMessage(int index, boolean forBuild) { } /** - * Gets a builder for the specified index. If no builder has been created for - * that index, a builder is created on demand by calling - * {@link Message#toBuilder}. + * Gets a builder for the specified index. If no builder has been created for that index, a + * builder is created on demand by calling {@link Message#toBuilder}. * * @param index the index of the message to get * @return The builder for that index @@ -245,16 +235,15 @@ public BType getBuilder(int index) { SingleFieldBuilder builder = builders.get(index); if (builder == null) { MType message = messages.get(index); - builder = new SingleFieldBuilder( - message, this, isClean); + builder = new SingleFieldBuilder(message, this, isClean); builders.set(index, builder); } return builder.getBuilder(); } /** - * Gets the base class interface for the specified index. This may either be - * a builder or a message. It will return whatever is more efficient. + * Gets the base class interface for the specified index. This may either be a builder or a + * message. It will return whatever is more efficient. * * @param index the index of the message to get * @return the message or builder for the index as the base class interface @@ -281,23 +270,18 @@ public IType getMessageOrBuilder(int index) { } /** - * Sets a message at the specified index replacing the existing item at - * that index. + * Sets a message at the specified index replacing the existing item at that index. * * @param index the index to set. * @param message the message to set * @return the builder */ - public RepeatedFieldBuilder setMessage( - int index, MType message) { - if (message == null) { - throw new NullPointerException(); - } + public RepeatedFieldBuilder setMessage(int index, MType message) { + checkNotNull(message); ensureMutableMessageList(); messages.set(index, message); if (builders != null) { - SingleFieldBuilder entry = - builders.set(index, null); + SingleFieldBuilder entry = builders.set(index, null); if (entry != null) { entry.dispose(); } @@ -313,11 +297,8 @@ public RepeatedFieldBuilder setMessage( * @param message the message to add * @return the builder */ - public RepeatedFieldBuilder addMessage( - MType message) { - if (message == null) { - throw new NullPointerException(); - } + public RepeatedFieldBuilder addMessage(MType message) { + checkNotNull(message); ensureMutableMessageList(); messages.add(message); if (builders != null) { @@ -329,19 +310,16 @@ public RepeatedFieldBuilder addMessage( } /** - * Inserts the specified message at the specified position in this list. - * Shifts the element currently at that position (if any) and any subsequent - * elements to the right (adds one to their indices). + * Inserts the specified message at the specified position in this list. Shifts the element + * currently at that position (if any) and any subsequent elements to the right (adds one to their + * indices). * * @param index the index at which to insert the message * @param message the message to add * @return the builder */ - public RepeatedFieldBuilder addMessage( - int index, MType message) { - if (message == null) { - throw new NullPointerException(); - } + public RepeatedFieldBuilder addMessage(int index, MType message) { + checkNotNull(message); ensureMutableMessageList(); messages.add(index, message); if (builders != null) { @@ -353,9 +331,8 @@ public RepeatedFieldBuilder addMessage( } /** - * Appends all of the messages in the specified collection to the end of - * this list, in the order that they are returned by the specified - * collection's iterator. + * Appends all of the messages in the specified collection to the end of this list, in the order + * that they are returned by the specified collection's iterator. * * @param values the messages to add * @return the builder @@ -363,17 +340,14 @@ public RepeatedFieldBuilder addMessage( public RepeatedFieldBuilder addAllMessages( Iterable values) { for (final MType value : values) { - if (value == null) { - throw new NullPointerException(); - } + checkNotNull(value); } // If we can inspect the size, we can more efficiently add messages. int size = -1; if (values instanceof Collection) { - @SuppressWarnings("unchecked") final - Collection collection = (Collection) values; - if (collection.size() == 0) { + final Collection collection = (Collection) values; + if (collection.isEmpty()) { return this; } size = collection.size(); @@ -381,8 +355,7 @@ public RepeatedFieldBuilder addAllMessages( ensureMutableMessageList(); if (size >= 0 && messages instanceof ArrayList) { - ((ArrayList) messages) - .ensureCapacity(messages.size() + size); + ((ArrayList) messages).ensureCapacity(messages.size() + size); } for (MType value : values) { @@ -404,8 +377,7 @@ public BType addBuilder(MType message) { ensureMutableMessageList(); ensureBuilders(); SingleFieldBuilder builder = - new SingleFieldBuilder( - message, this, isClean); + new SingleFieldBuilder(message, this, isClean); messages.add(null); builders.add(builder); onChanged(); @@ -414,9 +386,8 @@ public BType addBuilder(MType message) { } /** - * Inserts a new builder at the specified position in this list. - * Shifts the element currently at that position (if any) and any subsequent - * elements to the right (adds one to their indices). + * Inserts a new builder at the specified position in this list. Shifts the element currently at + * that position (if any) and any subsequent elements to the right (adds one to their indices). * * @param index the index at which to insert the builder * @param message the message to add which is the basis of the builder @@ -426,8 +397,7 @@ public BType addBuilder(int index, MType message) { ensureMutableMessageList(); ensureBuilders(); SingleFieldBuilder builder = - new SingleFieldBuilder( - message, this, isClean); + new SingleFieldBuilder(message, this, isClean); messages.add(index, null); builders.add(index, builder); onChanged(); @@ -436,9 +406,8 @@ public BType addBuilder(int index, MType message) { } /** - * Removes the element at the specified position in this list. Shifts any - * subsequent elements to the left (subtracts one from their indices). - * Returns the element that was removed from the list. + * Removes the element at the specified position in this list. Shifts any subsequent elements to + * the left (subtracts one from their indices). * * @param index the index at which to remove the message */ @@ -446,8 +415,7 @@ public void remove(int index) { ensureMutableMessageList(); messages.remove(index); if (builders != null) { - SingleFieldBuilder entry = - builders.remove(index); + SingleFieldBuilder entry = builders.remove(index); if (entry != null) { entry.dispose(); } @@ -456,16 +424,12 @@ public void remove(int index) { incrementModCounts(); } - /** - * Removes all of the elements from this list. - * The list will be empty after this call returns. - */ + /** Removes all of the elements from this list. The list will be empty after this call returns. */ public void clear() { messages = Collections.emptyList(); isMessagesListMutable = false; if (builders != null) { - for (SingleFieldBuilder entry : - builders) { + for (SingleFieldBuilder entry : builders) { if (entry != null) { entry.dispose(); } @@ -525,50 +489,47 @@ public List build() { } /** - * Gets a view of the builder as a list of messages. The returned list is live - * and will reflect any changes to the underlying builder. + * Gets a view of the builder as a list of messages. The returned list is live and will reflect + * any changes to the underlying builder. * * @return the messages in the list */ public List getMessageList() { if (externalMessageList == null) { - externalMessageList = - new MessageExternalList(this); + externalMessageList = new MessageExternalList(this); } return externalMessageList; } /** - * Gets a view of the builder as a list of builders. This returned list is - * live and will reflect any changes to the underlying builder. + * Gets a view of the builder as a list of builders. This returned list is live and will reflect + * any changes to the underlying builder. * * @return the builders in the list */ public List getBuilderList() { if (externalBuilderList == null) { - externalBuilderList = - new BuilderExternalList(this); + externalBuilderList = new BuilderExternalList(this); } return externalBuilderList; } /** - * Gets a view of the builder as a list of MessageOrBuilders. This returned - * list is live and will reflect any changes to the underlying builder. + * Gets a view of the builder as a list of MessageOrBuilders. This returned list is live and will + * reflect any changes to the underlying builder. * * @return the builders in the list */ public List getMessageOrBuilderList() { if (externalMessageOrBuilderList == null) { - externalMessageOrBuilderList = - new MessageOrBuilderExternalList(this); + externalMessageOrBuilderList = new MessageOrBuilderExternalList(this); } return externalMessageOrBuilderList; } /** - * Called when a the builder or one of its nested children has changed - * and any parent should be notified of its invalidation. + * Called when a the builder or one of its nested children has changed and any parent should be + * notified of its invalidation. */ private void onChanged() { if (isClean && parent != null) { @@ -585,9 +546,8 @@ public void markDirty() { } /** - * Increments the mod counts so that an ConcurrentModificationException can - * be thrown if calling code tries to modify the builder while its iterating - * the list. + * Increments the mod counts so that an ConcurrentModificationException can be thrown if calling + * code tries to modify the builder while its iterating the list. */ private void incrementModCounts() { if (externalMessageList != null) { @@ -609,15 +569,14 @@ private void incrementModCounts() { * @param the common interface for the message and the builder */ private static class MessageExternalList< - MType extends GeneratedMessage, - BType extends GeneratedMessage.Builder, - IType extends MessageOrBuilder> + MType extends GeneratedMessage, + BType extends GeneratedMessage.Builder, + IType extends MessageOrBuilder> extends AbstractList implements List { RepeatedFieldBuilder builder; - MessageExternalList( - RepeatedFieldBuilder builder) { + MessageExternalList(RepeatedFieldBuilder builder) { this.builder = builder; } @@ -644,15 +603,14 @@ void incrementModCount() { * @param the common interface for the message and the builder */ private static class BuilderExternalList< - MType extends GeneratedMessage, - BType extends GeneratedMessage.Builder, - IType extends MessageOrBuilder> + MType extends GeneratedMessage, + BType extends GeneratedMessage.Builder, + IType extends MessageOrBuilder> extends AbstractList implements List { RepeatedFieldBuilder builder; - BuilderExternalList( - RepeatedFieldBuilder builder) { + BuilderExternalList(RepeatedFieldBuilder builder) { this.builder = builder; } @@ -679,15 +637,14 @@ void incrementModCount() { * @param the common interface for the message and the builder */ private static class MessageOrBuilderExternalList< - MType extends GeneratedMessage, - BType extends GeneratedMessage.Builder, - IType extends MessageOrBuilder> + MType extends GeneratedMessage, + BType extends GeneratedMessage.Builder, + IType extends MessageOrBuilder> extends AbstractList implements List { RepeatedFieldBuilder builder; - MessageOrBuilderExternalList( - RepeatedFieldBuilder builder) { + MessageOrBuilderExternalList(RepeatedFieldBuilder builder) { this.builder = builder; } diff --git a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java index 30c991d40ba58..91bc3e286dd09 100644 --- a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java +++ b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java @@ -39,36 +39,29 @@ import java.util.List; /** - * {@code RepeatedFieldBuilderV3} implements a structure that a protocol - * message uses to hold a repeated field of other protocol messages. It supports - * the classical use case of adding immutable {@link Message}'s to the - * repeated field and is highly optimized around this (no extra memory - * allocations and sharing of immutable arrays). - *
- * It also supports the additional use case of adding a {@link Message.Builder} - * to the repeated field and deferring conversion of that {@code Builder} - * to an immutable {@code Message}. In this way, it's possible to maintain - * a tree of {@code Builder}'s that acts as a fully read/write data - * structure. - *
- * Logically, one can think of a tree of builders as converting the entire tree - * to messages when build is called on the root or when any method is called - * that desires a Message instead of a Builder. In terms of the implementation, - * the {@code SingleFieldBuilderV3} and {@code RepeatedFieldBuilderV3} - * classes cache messages that were created so that messages only need to be - * created when some change occurred in its builder or a builder for one of its - * descendants. + * {@code RepeatedFieldBuilderV3} implements a structure that a protocol message uses to hold a + * repeated field of other protocol messages. It supports the classical use case of adding immutable + * {@link Message}'s to the repeated field and is highly optimized around this (no extra memory + * allocations and sharing of immutable arrays).
+ * It also supports the additional use case of adding a {@link Message.Builder} to the repeated + * field and deferring conversion of that {@code Builder} to an immutable {@code Message}. In this + * way, it's possible to maintain a tree of {@code Builder}'s that acts as a fully read/write data + * structure.
+ * Logically, one can think of a tree of builders as converting the entire tree to messages when + * build is called on the root or when any method is called that desires a Message instead of a + * Builder. In terms of the implementation, the {@code SingleFieldBuilderV3} and {@code + * RepeatedFieldBuilderV3} classes cache messages that were created so that messages only need to be + * created when some change occurred in its builder or a builder for one of its descendants. * * @param the type of message for the field * @param the type of builder for the field * @param the common interface for the message and the builder - * * @author jonp@google.com (Jon Perlow) */ -public class RepeatedFieldBuilderV3 - +public class RepeatedFieldBuilderV3< + MType extends AbstractMessage, + BType extends AbstractMessage.Builder, + IType extends MessageOrBuilder> implements AbstractMessage.BuilderParent { // Parent to send changes to. @@ -120,8 +113,7 @@ public class RepeatedFieldBuilderV3 // is fully backed by this object and all changes are reflected in it. // Access to any item returns either a builder or message depending on // what is most efficient. - private MessageOrBuilderExternalList - externalMessageOrBuilderList; + private MessageOrBuilderExternalList externalMessageOrBuilderList; /** * Constructs a new builder with an empty list of messages. @@ -148,8 +140,8 @@ public void dispose() { } /** - * Ensures that the list of messages is mutable so it can be updated. If it's - * immutable, a copy is made. + * Ensures that the list of messages is mutable so it can be updated. If it's immutable, a copy is + * made. */ private void ensureMutableMessageList() { if (!isMessagesListMutable) { @@ -159,15 +151,12 @@ private void ensureMutableMessageList() { } /** - * Ensures that the list of builders is not null. If it's null, the list is - * created and initialized to be the same size as the messages list with - * null entries. + * Ensures that the list of builders is not null. If it's null, the list is created and + * initialized to be the same size as the messages list with null entries. */ private void ensureBuilders() { if (this.builders == null) { - this.builders = - new ArrayList>( - messages.size()); + this.builders = new ArrayList>(messages.size()); for (int i = 0; i < messages.size(); i++) { builders.add(null); } @@ -193,9 +182,9 @@ public boolean isEmpty() { } /** - * Get the message at the specified index. If the message is currently stored - * as a {@code Builder}, it is converted to a {@code Message} by - * calling {@link Message.Builder#buildPartial} on it. + * Get the message at the specified index. If the message is currently stored as a {@code + * Builder}, it is converted to a {@code Message} by calling {@link Message.Builder#buildPartial} + * on it. * * @param index the index of the message to get * @return the message for the specified index @@ -205,13 +194,13 @@ public MType getMessage(int index) { } /** - * Get the message at the specified index. If the message is currently stored - * as a {@code Builder}, it is converted to a {@code Message} by - * calling {@link Message.Builder#buildPartial} on it. + * Get the message at the specified index. If the message is currently stored as a {@code + * Builder}, it is converted to a {@code Message} by calling {@link Message.Builder#buildPartial} + * on it. * * @param index the index of the message to get - * @param forBuild this is being called for build so we want to make sure - * we SingleFieldBuilderV3.build to send dirty invalidations + * @param forBuild this is being called for build so we want to make sure we + * SingleFieldBuilderV3.build to send dirty invalidations * @return the message for the specified index */ private MType getMessage(int index, boolean forBuild) { @@ -235,9 +224,8 @@ private MType getMessage(int index, boolean forBuild) { } /** - * Gets a builder for the specified index. If no builder has been created for - * that index, a builder is created on demand by calling - * {@link Message#toBuilder}. + * Gets a builder for the specified index. If no builder has been created for that index, a + * builder is created on demand by calling {@link Message#toBuilder}. * * @param index the index of the message to get * @return The builder for that index @@ -247,16 +235,15 @@ public BType getBuilder(int index) { SingleFieldBuilderV3 builder = builders.get(index); if (builder == null) { MType message = messages.get(index); - builder = new SingleFieldBuilderV3( - message, this, isClean); + builder = new SingleFieldBuilderV3(message, this, isClean); builders.set(index, builder); } return builder.getBuilder(); } /** - * Gets the base class interface for the specified index. This may either be - * a builder or a message. It will return whatever is more efficient. + * Gets the base class interface for the specified index. This may either be a builder or a + * message. It will return whatever is more efficient. * * @param index the index of the message to get * @return the message or builder for the index as the base class interface @@ -283,21 +270,18 @@ public IType getMessageOrBuilder(int index) { } /** - * Sets a message at the specified index replacing the existing item at - * that index. + * Sets a message at the specified index replacing the existing item at that index. * * @param index the index to set. * @param message the message to set * @return the builder */ - public RepeatedFieldBuilderV3 setMessage( - int index, MType message) { + public RepeatedFieldBuilderV3 setMessage(int index, MType message) { checkNotNull(message); ensureMutableMessageList(); messages.set(index, message); if (builders != null) { - SingleFieldBuilderV3 entry = - builders.set(index, null); + SingleFieldBuilderV3 entry = builders.set(index, null); if (entry != null) { entry.dispose(); } @@ -313,8 +297,7 @@ public RepeatedFieldBuilderV3 setMessage( * @param message the message to add * @return the builder */ - public RepeatedFieldBuilderV3 addMessage( - MType message) { + public RepeatedFieldBuilderV3 addMessage(MType message) { checkNotNull(message); ensureMutableMessageList(); messages.add(message); @@ -327,16 +310,15 @@ public RepeatedFieldBuilderV3 addMessage( } /** - * Inserts the specified message at the specified position in this list. - * Shifts the element currently at that position (if any) and any subsequent - * elements to the right (adds one to their indices). + * Inserts the specified message at the specified position in this list. Shifts the element + * currently at that position (if any) and any subsequent elements to the right (adds one to their + * indices). * * @param index the index at which to insert the message * @param message the message to add * @return the builder */ - public RepeatedFieldBuilderV3 addMessage( - int index, MType message) { + public RepeatedFieldBuilderV3 addMessage(int index, MType message) { checkNotNull(message); ensureMutableMessageList(); messages.add(index, message); @@ -349,9 +331,8 @@ public RepeatedFieldBuilderV3 addMessage( } /** - * Appends all of the messages in the specified collection to the end of - * this list, in the order that they are returned by the specified - * collection's iterator. + * Appends all of the messages in the specified collection to the end of this list, in the order + * that they are returned by the specified collection's iterator. * * @param values the messages to add * @return the builder @@ -365,9 +346,8 @@ public RepeatedFieldBuilderV3 addAllMessages( // If we can inspect the size, we can more efficiently add messages. int size = -1; if (values instanceof Collection) { - @SuppressWarnings("unchecked") final - Collection collection = (Collection) values; - if (collection.size() == 0) { + final Collection collection = (Collection) values; + if (collection.isEmpty()) { return this; } size = collection.size(); @@ -375,8 +355,7 @@ public RepeatedFieldBuilderV3 addAllMessages( ensureMutableMessageList(); if (size >= 0 && messages instanceof ArrayList) { - ((ArrayList) messages) - .ensureCapacity(messages.size() + size); + ((ArrayList) messages).ensureCapacity(messages.size() + size); } for (MType value : values) { @@ -398,8 +377,7 @@ public BType addBuilder(MType message) { ensureMutableMessageList(); ensureBuilders(); SingleFieldBuilderV3 builder = - new SingleFieldBuilderV3( - message, this, isClean); + new SingleFieldBuilderV3(message, this, isClean); messages.add(null); builders.add(builder); onChanged(); @@ -408,9 +386,8 @@ public BType addBuilder(MType message) { } /** - * Inserts a new builder at the specified position in this list. - * Shifts the element currently at that position (if any) and any subsequent - * elements to the right (adds one to their indices). + * Inserts a new builder at the specified position in this list. Shifts the element currently at + * that position (if any) and any subsequent elements to the right (adds one to their indices). * * @param index the index at which to insert the builder * @param message the message to add which is the basis of the builder @@ -420,8 +397,7 @@ public BType addBuilder(int index, MType message) { ensureMutableMessageList(); ensureBuilders(); SingleFieldBuilderV3 builder = - new SingleFieldBuilderV3( - message, this, isClean); + new SingleFieldBuilderV3(message, this, isClean); messages.add(index, null); builders.add(index, builder); onChanged(); @@ -430,9 +406,8 @@ public BType addBuilder(int index, MType message) { } /** - * Removes the element at the specified position in this list. Shifts any - * subsequent elements to the left (subtracts one from their indices). - * Returns the element that was removed from the list. + * Removes the element at the specified position in this list. Shifts any subsequent elements to + * the left (subtracts one from their indices). * * @param index the index at which to remove the message */ @@ -440,8 +415,7 @@ public void remove(int index) { ensureMutableMessageList(); messages.remove(index); if (builders != null) { - SingleFieldBuilderV3 entry = - builders.remove(index); + SingleFieldBuilderV3 entry = builders.remove(index); if (entry != null) { entry.dispose(); } @@ -450,16 +424,12 @@ public void remove(int index) { incrementModCounts(); } - /** - * Removes all of the elements from this list. - * The list will be empty after this call returns. - */ + /** Removes all of the elements from this list. The list will be empty after this call returns. */ public void clear() { messages = Collections.emptyList(); isMessagesListMutable = false; if (builders != null) { - for (SingleFieldBuilderV3 entry : - builders) { + for (SingleFieldBuilderV3 entry : builders) { if (entry != null) { entry.dispose(); } @@ -519,50 +489,47 @@ public List build() { } /** - * Gets a view of the builder as a list of messages. The returned list is live - * and will reflect any changes to the underlying builder. + * Gets a view of the builder as a list of messages. The returned list is live and will reflect + * any changes to the underlying builder. * * @return the messages in the list */ public List getMessageList() { if (externalMessageList == null) { - externalMessageList = - new MessageExternalList(this); + externalMessageList = new MessageExternalList(this); } return externalMessageList; } /** - * Gets a view of the builder as a list of builders. This returned list is - * live and will reflect any changes to the underlying builder. + * Gets a view of the builder as a list of builders. This returned list is live and will reflect + * any changes to the underlying builder. * * @return the builders in the list */ public List getBuilderList() { if (externalBuilderList == null) { - externalBuilderList = - new BuilderExternalList(this); + externalBuilderList = new BuilderExternalList(this); } return externalBuilderList; } /** - * Gets a view of the builder as a list of MessageOrBuilders. This returned - * list is live and will reflect any changes to the underlying builder. + * Gets a view of the builder as a list of MessageOrBuilders. This returned list is live and will + * reflect any changes to the underlying builder. * * @return the builders in the list */ public List getMessageOrBuilderList() { if (externalMessageOrBuilderList == null) { - externalMessageOrBuilderList = - new MessageOrBuilderExternalList(this); + externalMessageOrBuilderList = new MessageOrBuilderExternalList(this); } return externalMessageOrBuilderList; } /** - * Called when a the builder or one of its nested children has changed - * and any parent should be notified of its invalidation. + * Called when a the builder or one of its nested children has changed and any parent should be + * notified of its invalidation. */ private void onChanged() { if (isClean && parent != null) { @@ -579,9 +546,8 @@ public void markDirty() { } /** - * Increments the mod counts so that an ConcurrentModificationException can - * be thrown if calling code tries to modify the builder while its iterating - * the list. + * Increments the mod counts so that an ConcurrentModificationException can be thrown if calling + * code tries to modify the builder while its iterating the list. */ private void incrementModCounts() { if (externalMessageList != null) { @@ -603,15 +569,14 @@ private void incrementModCounts() { * @param the common interface for the message and the builder */ private static class MessageExternalList< - MType extends AbstractMessage, - BType extends AbstractMessage.Builder, - IType extends MessageOrBuilder> + MType extends AbstractMessage, + BType extends AbstractMessage.Builder, + IType extends MessageOrBuilder> extends AbstractList implements List { RepeatedFieldBuilderV3 builder; - MessageExternalList( - RepeatedFieldBuilderV3 builder) { + MessageExternalList(RepeatedFieldBuilderV3 builder) { this.builder = builder; } @@ -638,15 +603,14 @@ void incrementModCount() { * @param the common interface for the message and the builder */ private static class BuilderExternalList< - MType extends AbstractMessage, - BType extends AbstractMessage.Builder, - IType extends MessageOrBuilder> + MType extends AbstractMessage, + BType extends AbstractMessage.Builder, + IType extends MessageOrBuilder> extends AbstractList implements List { RepeatedFieldBuilderV3 builder; - BuilderExternalList( - RepeatedFieldBuilderV3 builder) { + BuilderExternalList(RepeatedFieldBuilderV3 builder) { this.builder = builder; } @@ -673,15 +637,14 @@ void incrementModCount() { * @param the common interface for the message and the builder */ private static class MessageOrBuilderExternalList< - MType extends AbstractMessage, - BType extends AbstractMessage.Builder, - IType extends MessageOrBuilder> + MType extends AbstractMessage, + BType extends AbstractMessage.Builder, + IType extends MessageOrBuilder> extends AbstractList implements List { RepeatedFieldBuilderV3 builder; - MessageOrBuilderExternalList( - RepeatedFieldBuilderV3 builder) { + MessageOrBuilderExternalList(RepeatedFieldBuilderV3 builder) { this.builder = builder; } diff --git a/java/core/src/main/java/com/google/protobuf/RopeByteString.java b/java/core/src/main/java/com/google/protobuf/RopeByteString.java index 6fa555df15096..cc6e0445b0d68 100644 --- a/java/core/src/main/java/com/google/protobuf/RopeByteString.java +++ b/java/core/src/main/java/com/google/protobuf/RopeByteString.java @@ -38,81 +38,97 @@ import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.charset.Charset; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; -import java.util.Stack; /** - * Class to represent {@code ByteStrings} formed by concatenation of other - * ByteStrings, without copying the data in the pieces. The concatenation is - * represented as a tree whose leaf nodes are each a - * {@link com.google.protobuf.ByteString.LeafByteString}. + * Class to represent {@code ByteStrings} formed by concatenation of other ByteStrings, without + * copying the data in the pieces. The concatenation is represented as a tree whose leaf nodes are + * each a {@link com.google.protobuf.ByteString.LeafByteString}. * *

Most of the operation here is inspired by the now-famous paper - * BAP95 Ropes: an Alternative to Strings hans-j. boehm, russ atkinson and - * michael plass + * BAP95 Ropes: an Alternative to Strings hans-j. boehm, russ atkinson and michael plass * - *

The algorithms described in the paper have been implemented for character - * strings in {@code com.google.common.string.Rope} and in the c++ class {@code - * cord.cc}. + *

The algorithms described in the paper have been implemented for character strings in {@code + * com.google.common.string.Rope} and in the c++ class {@code cord.cc}. * - *

Fundamentally the Rope algorithm represents the collection of pieces as a - * binary tree. BAP95 uses a Fibonacci bound relating depth to a minimum - * sequence length, sequences that are too short relative to their depth cause a - * tree rebalance. More precisely, a tree of depth d is "balanced" in the - * terminology of BAP95 if its length is at least F(d+2), where F(n) is the - * n-the Fibonacci number. Thus for depths 0, 1, 2, 3, 4, 5,... we have minimum - * lengths 1, 2, 3, 5, 8, 13,... + *

Fundamentally the Rope algorithm represents the collection of pieces as a binary tree. BAP95 + * uses a Fibonacci bound relating depth to a minimum sequence length, sequences that are too short + * relative to their depth cause a tree rebalance. More precisely, a tree of depth d is "balanced" + * in the terminology of BAP95 if its length is at least F(d+2), where F(n) is the n-th Fibonacci + * number. Thus for depths 0, 1, 2, 3, 4, 5,... we have minimum lengths 1, 2, 3, 5, 8, 13,... * * @author carlanton@google.com (Carl Haverl) */ final class RopeByteString extends ByteString { /** - * BAP95. Let Fn be the nth Fibonacci number. A {@link RopeByteString} of - * depth n is "balanced", i.e flat enough, if its length is at least Fn+2, - * e.g. a "balanced" {@link RopeByteString} of depth 1 must have length at - * least 2, of depth 4 must have length >= 8, etc. + * BAP95. Let Fn be the nth Fibonacci number. A {@link RopeByteString} of depth n is "balanced", + * i.e flat enough, if its length is at least Fn+2, e.g. a "balanced" {@link RopeByteString} of + * depth 1 must have length at least 2, of depth 4 must have length >= 8, etc. * - *

There's nothing special about using the Fibonacci numbers for this, but - * they are a reasonable sequence for encapsulating the idea that we are OK - * with longer strings being encoded in deeper binary trees. + *

There's nothing special about using the Fibonacci numbers for this, but they are a + * reasonable sequence for encapsulating the idea that we are OK with longer strings being encoded + * in deeper binary trees. * *

For 32-bit integers, this array has length 46. + * + *

The correctness of this constant array is validated in tests. */ - private static final int[] minLengthByDepth; - - static { - // Dynamically generate the list of Fibonacci numbers the first time this - // class is accessed. - List numbers = new ArrayList(); - - // we skip the first Fibonacci number (1). So instead of: 1 1 2 3 5 8 ... - // we have: 1 2 3 5 8 ... - int f1 = 1; - int f2 = 1; - - // get all the values until we roll over. - while (f2 > 0) { - numbers.add(f2); - int temp = f1 + f2; - f1 = f2; - f2 = temp; - } - - // we include this here so that we can index this array to [x + 1] in the - // loops below. - numbers.add(Integer.MAX_VALUE); - minLengthByDepth = new int[numbers.size()]; - for (int i = 0; i < minLengthByDepth.length; i++) { - // unbox all the values - minLengthByDepth[i] = numbers.get(i); - } - } + static final int[] minLengthByDepth = { + 1, + 1, + 2, + 3, + 5, + 8, + 13, + 21, + 34, + 55, + 89, + 144, + 233, + 377, + 610, + 987, + 1597, + 2584, + 4181, + 6765, + 10946, + 17711, + 28657, + 46368, + 75025, + 121393, + 196418, + 317811, + 514229, + 832040, + 1346269, + 2178309, + 3524578, + 5702887, + 9227465, + 14930352, + 24157817, + 39088169, + 63245986, + 102334155, + 165580141, + 267914296, + 433494437, + 701408733, + 1134903170, + 1836311903, + Integer.MAX_VALUE + }; private final int totalLength; private final ByteString left; @@ -121,13 +137,11 @@ final class RopeByteString extends ByteString { private final int treeDepth; /** - * Create a new RopeByteString, which can be thought of as a new tree node, by - * recording references to the two given strings. + * Create a new RopeByteString, which can be thought of as a new tree node, by recording + * references to the two given strings. * - * @param left string on the left of this node, should have {@code size() > - * 0} - * @param right string on the right of this node, should have {@code size() > - * 0} + * @param left string on the left of this node, should have {@code size() > 0} + * @param right string on the right of this node, should have {@code size() > 0} */ private RopeByteString(ByteString left, ByteString right) { this.left = left; @@ -138,17 +152,15 @@ private RopeByteString(ByteString left, ByteString right) { } /** - * Concatenate the given strings while performing various optimizations to - * slow the growth rate of tree depth and tree node count. The result is - * either a {@link com.google.protobuf.ByteString.LeafByteString} or a - * {@link RopeByteString} depending on which optimizations, if any, were - * applied. + * Concatenate the given strings while performing various optimizations to slow the growth rate of + * tree depth and tree node count. The result is either a {@link + * com.google.protobuf.ByteString.LeafByteString} or a {@link RopeByteString} depending on which + * optimizations, if any, were applied. * - *

Small pieces of length less than {@link - * ByteString#CONCATENATE_BY_COPY_SIZE} may be copied by value here, as in - * BAP95. Large pieces are referenced without copy. + *

Small pieces of length less than {@link ByteString#CONCATENATE_BY_COPY_SIZE} may be copied + * by value here, as in BAP95. Large pieces are referenced without copy. * - * @param left string on the left + * @param left string on the left * @param right string on the right * @return concatenation representing the same sequence as the given strings */ @@ -199,7 +211,7 @@ static ByteString concatenate(ByteString left, ByteString right) { // Fine, we'll add a node and increase the tree depth--unless we rebalance ;^) int newDepth = Math.max(left.getTreeDepth(), right.getTreeDepth()) + 1; - if (newLength >= minLengthByDepth[newDepth]) { + if (newLength >= minLength(newDepth)) { // The tree is shallow enough, so don't rebalance return new RopeByteString(left, right); } @@ -208,31 +220,29 @@ static ByteString concatenate(ByteString left, ByteString right) { } /** - * Concatenates two strings by copying data values. This is called in a few - * cases in order to reduce the growth of the number of tree nodes. + * Concatenates two strings by copying data values. This is called in a few cases in order to + * reduce the growth of the number of tree nodes. * - * @param left string on the left + * @param left string on the left * @param right string on the right * @return string formed by copying data bytes */ - private static ByteString concatenateBytes(ByteString left, - ByteString right) { + private static ByteString concatenateBytes(ByteString left, ByteString right) { int leftSize = left.size(); int rightSize = right.size(); byte[] bytes = new byte[leftSize + rightSize]; left.copyTo(bytes, 0, 0, leftSize); right.copyTo(bytes, 0, leftSize, rightSize); - return ByteString.wrap(bytes); // Constructor wraps bytes + return ByteString.wrap(bytes); // Constructor wraps bytes } /** - * Create a new RopeByteString for testing only while bypassing all the - * defenses of {@link #concatenate(ByteString, ByteString)}. This allows - * testing trees of specific structure. We are also able to insert empty - * leaves, though these are dis-allowed, so that we can make sure the + * Create a new RopeByteString for testing only while bypassing all the defenses of {@link + * #concatenate(ByteString, ByteString)}. This allows testing trees of specific structure. We are + * also able to insert empty leaves, though these are dis-allowed, so that we can make sure the * implementation can withstand their presence. * - * @param left string on the left of this node + * @param left string on the left of this node * @param right string on the right of this node * @return an unsafe instance for testing only */ @@ -241,9 +251,24 @@ static RopeByteString newInstanceForTest(ByteString left, ByteString right) { } /** - * Gets the byte at the given index. - * Throws {@link ArrayIndexOutOfBoundsException} for backwards-compatibility - * reasons although it would more properly be {@link + * Returns the minimum length for which a tree of the given depth is considered balanced according + * to BAP95, which means the tree is flat-enough with respect to the bounds. Defaults to {@code + * Integer.MAX_VALUE} if {@code depth >= minLengthByDepth.length} in order to avoid an {@code + * ArrayIndexOutOfBoundsException}. + * + * @param depth tree depth + * @return minimum balanced length + */ + static int minLength(int depth) { + if (depth >= minLengthByDepth.length) { + return Integer.MAX_VALUE; + } + return minLengthByDepth[depth]; + } + + /** + * Gets the byte at the given index. Throws {@link ArrayIndexOutOfBoundsException} for + * backwards-compatibility reasons although it would more properly be {@link * IndexOutOfBoundsException}. * * @param index index of byte @@ -253,13 +278,17 @@ static RopeByteString newInstanceForTest(ByteString left, ByteString right) { @Override public byte byteAt(int index) { checkIndex(index, totalLength); + return internalByteAt(index); + } + @Override + byte internalByteAt(int index) { // Find the relevant piece by recursive descent if (index < leftLength) { - return left.byteAt(index); + return left.internalByteAt(index); } - return right.byteAt(index - leftLength); + return right.internalByteAt(index - leftLength); } @Override @@ -267,6 +296,37 @@ public int size() { return totalLength; } + @Override + public ByteIterator iterator() { + return new AbstractByteIterator() { + final PieceIterator pieces = new PieceIterator(RopeByteString.this); + ByteIterator current = nextPiece(); + + private ByteIterator nextPiece() { + // NOTE: PieceIterator is guaranteed to return non-empty pieces, so this method will always + // return non-empty iterators (or null) + return pieces.hasNext() ? pieces.next().iterator() : null; + } + + @Override + public boolean hasNext() { + return current != null; + } + + @Override + public byte nextByte() { + if (current == null) { + throw new NoSuchElementException(); + } + byte b = current.nextByte(); + if (!current.hasNext()) { + current = nextPiece(); + } + return b; + } + }; + } + // ================================================================= // Pieces @@ -276,30 +336,28 @@ protected int getTreeDepth() { } /** - * Determines if the tree is balanced according to BAP95, which means the tree - * is flat-enough with respect to the bounds. Note that this definition of - * balanced is one where sub-trees of balanced trees are not necessarily - * balanced. + * Determines if the tree is balanced according to BAP95, which means the tree is flat-enough with + * respect to the bounds. Note that this definition of balanced is one where sub-trees of balanced + * trees are not necessarily balanced. * * @return true if the tree is balanced */ @Override protected boolean isBalanced() { - return totalLength >= minLengthByDepth[treeDepth]; + return totalLength >= minLength(treeDepth); } /** - * Takes a substring of this one. This involves recursive descent along the - * left and right edges of the substring, and referencing any wholly contained - * segments in between. Any leaf nodes entirely uninvolved in the substring - * will not be referenced by the substring. + * Takes a substring of this one. This involves recursive descent along the left and right edges + * of the substring, and referencing any wholly contained segments in between. Any leaf nodes + * entirely uninvolved in the substring will not be referenced by the substring. * - *

Substrings of {@code length < 2} should result in at most a single - * recursive call chain, terminating at a leaf node. Thus the result will be a - * {@link com.google.protobuf.ByteString.LeafByteString}. + *

Substrings of {@code length < 2} should result in at most a single recursive call chain, + * terminating at a leaf node. Thus the result will be a {@link + * com.google.protobuf.ByteString.LeafByteString}. * * @param beginIndex start at this index - * @param endIndex the last character is the one before this index + * @param endIndex the last character is the one before this index * @return substring leaf node or tree */ @Override @@ -340,18 +398,16 @@ public ByteString substring(int beginIndex, int endIndex) { // ByteString -> byte[] @Override - protected void copyToInternal(byte[] target, int sourceOffset, - int targetOffset, int numberToCopy) { - if (sourceOffset + numberToCopy <= leftLength) { + protected void copyToInternal( + byte[] target, int sourceOffset, int targetOffset, int numberToCopy) { + if (sourceOffset + numberToCopy <= leftLength) { left.copyToInternal(target, sourceOffset, targetOffset, numberToCopy); } else if (sourceOffset >= leftLength) { - right.copyToInternal(target, sourceOffset - leftLength, targetOffset, - numberToCopy); + right.copyToInternal(target, sourceOffset - leftLength, targetOffset, numberToCopy); } else { int leftLength = this.leftLength - sourceOffset; left.copyToInternal(target, sourceOffset, targetOffset, leftLength); - right.copyToInternal(target, 0, targetOffset + leftLength, - numberToCopy - leftLength); + right.copyToInternal(target, 0, targetOffset + leftLength, numberToCopy - leftLength); } } @@ -387,8 +443,7 @@ public void writeTo(OutputStream outputStream) throws IOException { } @Override - void writeToInternal(OutputStream out, int sourceOffset, - int numberToWrite) throws IOException { + void writeToInternal(OutputStream out, int sourceOffset, int numberToWrite) throws IOException { if (sourceOffset + numberToWrite <= leftLength) { left.writeToInternal(out, sourceOffset, numberToWrite); } else if (sourceOffset >= leftLength) { @@ -406,6 +461,11 @@ void writeTo(ByteOutput output) throws IOException { right.writeTo(output); } + @Override + void writeToReverse(ByteOutput output) throws IOException { + right.writeToReverse(output); + left.writeToReverse(output); + } @Override protected String toStringInternal(Charset charset) { @@ -471,13 +531,11 @@ public boolean equals(Object other) { } /** - * Determines if this string is equal to another of the same length by - * iterating over the leaf nodes. On each step of the iteration, the - * overlapping segments of the leaves are compared. + * Determines if this string is equal to another of the same length by iterating over the leaf + * nodes. On each step of the iteration, the overlapping segments of the leaves are compared. * * @param other string of the same length as this one - * @return true if the values of this string equals the value of the given - * one + * @return true if the values of this string equals the value of the given one */ private boolean equalsFragments(ByteString other) { int thisOffset = 0; @@ -495,9 +553,10 @@ private boolean equalsFragments(ByteString other) { int bytesToCompare = Math.min(thisRemaining, thatRemaining); // At least one of the offsets will be zero - boolean stillEqual = (thisOffset == 0) - ? thisString.equalsRange(thatString, thatOffset, bytesToCompare) - : thatString.equalsRange(thisString, thisOffset, bytesToCompare); + boolean stillEqual = + (thisOffset == 0) + ? thisString.equalsRange(thatString, thatOffset, bytesToCompare) + : thatString.equalsRange(thisString, thisOffset, bytesToCompare); if (!stillEqual) { return false; } @@ -553,20 +612,19 @@ public InputStream newInput() { } /** - * This class implements the balancing algorithm of BAP95. In the paper the - * authors use an array to keep track of pieces, while here we use a stack. - * The tree is balanced by traversing subtrees in left to right order, and the - * stack always contains the part of the string we've traversed so far. + * This class implements the balancing algorithm of BAP95. In the paper the authors use an array + * to keep track of pieces, while here we use a stack. The tree is balanced by traversing subtrees + * in left to right order, and the stack always contains the part of the string we've traversed so + * far. * - *

One surprising aspect of the algorithm is the result of balancing is not - * necessarily balanced, though it is nearly balanced. For details, see - * BAP95. + *

One surprising aspect of the algorithm is the result of balancing is not necessarily + * balanced, though it is nearly balanced. For details, see BAP95. */ private static class Balancer { // Stack containing the part of the string, starting from the left, that // we've already traversed. The final string should be the equivalent of // concatenating the strings on the stack from bottom to top. - private final Stack prefixesStack = new Stack(); + private final ArrayDeque prefixesStack = new ArrayDeque<>(); private ByteString balance(ByteString left, ByteString right) { doBalance(left); @@ -596,28 +654,25 @@ private void doBalance(ByteString root) { doBalance(rbs.right); } else { throw new IllegalArgumentException( - "Has a new type of ByteString been created? Found " + - root.getClass()); + "Has a new type of ByteString been created? Found " + root.getClass()); } } /** - * Push a string on the balance stack (BAP95). BAP95 uses an array and - * calls the elements in the array 'bins'. We instead use a stack, so the - * 'bins' of lengths are represented by differences between the elements of - * minLengthByDepth. + * Push a string on the balance stack (BAP95). BAP95 uses an array and calls the elements in the + * array 'bins'. We instead use a stack, so the 'bins' of lengths are represented by differences + * between the elements of minLengthByDepth. * - *

If the length bin for our string, and all shorter length bins, are - * empty, we just push it on the stack. Otherwise, we need to start - * concatenating, putting the given string in the "middle" and continuing - * until we land in an empty length bin that matches the length of our + *

If the length bin for our string, and all shorter length bins, are empty, we just push it + * on the stack. Otherwise, we need to start concatenating, putting the given string in the + * "middle" and continuing until we land in an empty length bin that matches the length of our * concatenation. * * @param byteString string to place on the balance stack */ private void insert(ByteString byteString) { int depthBin = getDepthBinForLength(byteString.size()); - int binEnd = minLengthByDepth[depthBin + 1]; + int binEnd = minLength(depthBin + 1); // BAP95: Concatenate all trees occupying bins representing the length of // our new piece or of shorter pieces, to the extent that is possible. @@ -626,12 +681,11 @@ private void insert(ByteString byteString) { if (prefixesStack.isEmpty() || prefixesStack.peek().size() >= binEnd) { prefixesStack.push(byteString); } else { - int binStart = minLengthByDepth[depthBin]; + int binStart = minLength(depthBin); // Concatenate the subtrees of shorter length ByteString newTree = prefixesStack.pop(); - while (!prefixesStack.isEmpty() - && prefixesStack.peek().size() < binStart) { + while (!prefixesStack.isEmpty() && prefixesStack.peek().size() < binStart) { ByteString left = prefixesStack.pop(); newTree = new RopeByteString(left, newTree); } @@ -642,7 +696,7 @@ private void insert(ByteString byteString) { // Continue concatenating until we land in an empty bin while (!prefixesStack.isEmpty()) { depthBin = getDepthBinForLength(newTree.size()); - binEnd = minLengthByDepth[depthBin + 1]; + binEnd = minLength(depthBin + 1); if (prefixesStack.peek().size() < binEnd) { ByteString left = prefixesStack.pop(); newTree = new RopeByteString(left, newTree); @@ -668,22 +722,26 @@ private int getDepthBinForLength(int length) { } /** - * This class is a continuable tree traversal, which keeps the state - * information which would exist on the stack in a recursive traversal instead - * on a stack of "Bread Crumbs". The maximum depth of the stack in this - * iterator is the same as the depth of the tree being traversed. + * This class is a continuable tree traversal, which keeps the state information which would exist + * on the stack in a recursive traversal instead on a stack of "Bread Crumbs". The maximum depth + * of the stack in this iterator is the same as the depth of the tree being traversed. * - *

This iterator is used to implement - * {@link RopeByteString#equalsFragments(ByteString)}. + *

This iterator is used to implement {@link RopeByteString#equalsFragments(ByteString)}. */ - private static class PieceIterator implements Iterator { - - private final Stack breadCrumbs = - new Stack(); + private static final class PieceIterator implements Iterator { + private final ArrayDeque breadCrumbs; private LeafByteString next; private PieceIterator(ByteString root) { - next = getLeafByLeft(root); + if (root instanceof RopeByteString) { + RopeByteString rbs = (RopeByteString) root; + breadCrumbs = new ArrayDeque<>(rbs.getTreeDepth()); + breadCrumbs.push(rbs); + next = getLeafByLeft(rbs.left); + } else { + breadCrumbs = null; + next = (LeafByteString) root; + } } private LeafByteString getLeafByLeft(ByteString root) { @@ -700,7 +758,7 @@ private LeafByteString getNextNonEmptyLeaf() { while (true) { // Almost always, we go through this loop exactly once. However, if // we discover an empty string in the rope, we toss it and try again. - if (breadCrumbs.isEmpty()) { + if (breadCrumbs == null || breadCrumbs.isEmpty()) { return null; } else { LeafByteString result = getLeafByLeft(breadCrumbs.pop().right); @@ -717,8 +775,7 @@ public boolean hasNext() { } /** - * Returns the next item and advances one - * {@link com.google.protobuf.ByteString.LeafByteString}. + * Returns the next item and advances one {@link com.google.protobuf.ByteString.LeafByteString}. * * @return next non-empty LeafByteString or {@code null} */ @@ -748,14 +805,10 @@ Object writeReplace() { } private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws IOException { - throw new InvalidObjectException( - "RopeByteStream instances are not to be serialized directly"); + throw new InvalidObjectException("RopeByteStream instances are not to be serialized directly"); } - /** - * This class is the {@link RopeByteString} equivalent for - * {@link ByteArrayInputStream}. - */ + /** This class is the {@link RopeByteString} equivalent for {@link ByteArrayInputStream}. */ private class RopeInputStream extends InputStream { // Iterates through the pieces of the rope private PieceIterator pieceIterator; @@ -774,14 +827,32 @@ public RopeInputStream() { initialize(); } + /** + * Reads up to {@code len} bytes of data into array {@code b}. + * + *

Note that {@link InputStream#read(byte[], int, int)} and {@link + * ByteArrayInputStream#read(byte[], int, int)} behave inconsistently when reading 0 bytes at + * EOF; the interface defines the return value to be 0 and the latter returns -1. We use the + * latter behavior so that all ByteString streams are consistent. + * + * @return -1 if at EOF, otherwise the actual number of bytes read. + */ @Override - public int read(byte b[], int offset, int length) { + public int read(byte[] b, int offset, int length) { if (b == null) { throw new NullPointerException(); } else if (offset < 0 || length < 0 || length > b.length - offset) { throw new IndexOutOfBoundsException(); } - return readSkipInternal(b, offset, length); + int bytesRead = readSkipInternal(b, offset, length); + if (bytesRead == 0 && (length > 0 || availableInternal() == 0)) { + // Modeling ByteArrayInputStream.read(byte[], int, int) behavior noted above: + // It's ok to read 0 bytes on purpose (length == 0) from a stream that isn't at EOF. + // It's not ok to try to read bytes (even 0 bytes) from a stream that is at EOF. + return -1; + } else { + return bytesRead; + } } @Override @@ -795,24 +866,19 @@ public long skip(long length) { } /** - * Internal implementation of read and skip. If b != null, then read the - * next {@code length} bytes into the buffer {@code b} at - * offset {@code offset}. If b == null, then skip the next {@code length} - * bytes. - *

- * This method assumes that all error checking has already happened. - *

- * Returns the actual number of bytes read or skipped. + * Internal implementation of read and skip. If b != null, then read the next {@code length} + * bytes into the buffer {@code b} at offset {@code offset}. If b == null, then skip the next + * {@code length} bytes. + * + *

This method assumes that all error checking has already happened. + * + *

Returns the actual number of bytes read or skipped. */ - private int readSkipInternal(byte b[], int offset, int length) { + private int readSkipInternal(byte[] b, int offset, int length) { int bytesRemaining = length; while (bytesRemaining > 0) { advanceIfCurrentPieceFullyRead(); if (currentPiece == null) { - if (bytesRemaining == length) { - // We didn't manage to read anything - return -1; - } break; } else { // Copy the bytes from this piece. @@ -826,7 +892,7 @@ private int readSkipInternal(byte b[], int offset, int length) { bytesRemaining -= count; } } - // Return the number of bytes read. + // Return the number of bytes read. return length - bytesRemaining; } @@ -842,8 +908,7 @@ public int read() throws IOException { @Override public int available() throws IOException { - int bytesRead = currentPieceOffsetInRope + currentPieceIndex; - return RopeByteString.this.size() - bytesRead; + return availableInternal(); } @Override @@ -874,9 +939,8 @@ private void initialize() { } /** - * Skips to the next piece if we have read all the data in the current - * piece. Sets currentPiece to null if we have reached the end of the - * input. + * Skips to the next piece if we have read all the data in the current piece. Sets currentPiece + * to null if we have reached the end of the input. */ private void advanceIfCurrentPieceFullyRead() { if (currentPiece != null && currentPieceIndex == currentPieceSize) { @@ -893,5 +957,11 @@ private void advanceIfCurrentPieceFullyRead() { } } } + + /** Computes the number of bytes still available to read. */ + private int availableInternal() { + int bytesRead = currentPieceOffsetInRope + currentPieceIndex; + return RopeByteString.this.size() - bytesRead; + } } } diff --git a/java/core/src/main/java/com/google/protobuf/RpcCallback.java b/java/core/src/main/java/com/google/protobuf/RpcCallback.java index 10752968e27f1..51a34b63d463b 100644 --- a/java/core/src/main/java/com/google/protobuf/RpcCallback.java +++ b/java/core/src/main/java/com/google/protobuf/RpcCallback.java @@ -31,14 +31,13 @@ package com.google.protobuf; /** - * Interface for an RPC callback, normally called when an RPC completes. - * {@code ParameterType} is normally the method's response message type. + * Interface for an RPC callback, normally called when an RPC completes. {@code ParameterType} is + * normally the method's response message type. * - *

Starting with version 2.3.0, RPC implementations should not try to build - * on this, but should instead provide code generator plugins which generate - * code specific to the particular RPC implementation. This way the generated - * code can be more appropriate for the implementation in use and can avoid - * unnecessary layers of indirection. + *

Starting with version 2.3.0, RPC implementations should not try to build on this, but should + * instead provide code generator plugins which generate code specific to the particular RPC + * implementation. This way the generated code can be more appropriate for the implementation in use + * and can avoid unnecessary layers of indirection. * * @author kenton@google.com Kenton Varda */ diff --git a/java/core/src/main/java/com/google/protobuf/RpcChannel.java b/java/core/src/main/java/com/google/protobuf/RpcChannel.java index f272f4ad72bf5..13b5ec165eacb 100644 --- a/java/core/src/main/java/com/google/protobuf/RpcChannel.java +++ b/java/core/src/main/java/com/google/protobuf/RpcChannel.java @@ -31,11 +31,10 @@ package com.google.protobuf; /** - *

Abstract interface for an RPC channel. An {@code RpcChannel} represents a - * communication line to a {@link Service} which can be used to call that - * {@link Service}'s methods. The {@link Service} may be running on another - * machine. Normally, you should not call an {@code RpcChannel} directly, but - * instead construct a stub {@link Service} wrapping it. Example: + * Abstract interface for an RPC channel. An {@code RpcChannel} represents a communication line to a + * {@link Service} which can be used to call that {@link Service}'s methods. The {@link Service} may + * be running on another machine. Normally, you should not call an {@code RpcChannel} directly, but + * instead construct a stub {@link Service} wrapping it. Example: * *

  *   RpcChannel channel = rpcImpl.newChannel("remotehost.example.com:1234");
@@ -44,28 +43,26 @@
  *   service.myMethod(controller, request, callback);
  * 
* - *

Starting with version 2.3.0, RPC implementations should not try to build - * on this, but should instead provide code generator plugins which generate - * code specific to the particular RPC implementation. This way the generated - * code can be more appropriate for the implementation in use and can avoid - * unnecessary layers of indirection. + *

Starting with version 2.3.0, RPC implementations should not try to build on this, but should + * instead provide code generator plugins which generate code specific to the particular RPC + * implementation. This way the generated code can be more appropriate for the implementation in use + * and can avoid unnecessary layers of indirection. * * @author kenton@google.com Kenton Varda */ public interface RpcChannel { /** - * Call the given method of the remote service. This method is similar to - * {@code Service.callMethod()} with one important difference: the caller - * decides the types of the {@code Message} objects, not the callee. The - * request may be of any type as long as - * {@code request.getDescriptor() == method.getInputType()}. - * The response passed to the callback will be of the same type as - * {@code responsePrototype} (which must have - * {@code getDescriptor() == method.getOutputType()}). + * Call the given method of the remote service. This method is similar to {@code + * Service.callMethod()} with one important difference: the caller decides the types of the {@code + * Message} objects, not the callee. The request may be of any type as long as {@code + * request.getDescriptor() == method.getInputType()}. The response passed to the callback will be + * of the same type as {@code responsePrototype} (which must have {@code getDescriptor() == + * method.getOutputType()}). */ - void callMethod(Descriptors.MethodDescriptor method, - RpcController controller, - Message request, - Message responsePrototype, - RpcCallback done); + void callMethod( + Descriptors.MethodDescriptor method, + RpcController controller, + Message request, + Message responsePrototype, + RpcCallback done); } diff --git a/java/core/src/main/java/com/google/protobuf/RpcController.java b/java/core/src/main/java/com/google/protobuf/RpcController.java index a92dd7be6d502..073f27a2aad81 100644 --- a/java/core/src/main/java/com/google/protobuf/RpcController.java +++ b/java/core/src/main/java/com/google/protobuf/RpcController.java @@ -31,20 +31,18 @@ package com.google.protobuf; /** - *

An {@code RpcController} mediates a single method call. The primary - * purpose of the controller is to provide a way to manipulate settings - * specific to the RPC implementation and to find out about RPC-level errors. + * An {@code RpcController} mediates a single method call. The primary purpose of the controller is + * to provide a way to manipulate settings specific to the RPC implementation and to find out about + * RPC-level errors. * - *

Starting with version 2.3.0, RPC implementations should not try to build - * on this, but should instead provide code generator plugins which generate - * code specific to the particular RPC implementation. This way the generated - * code can be more appropriate for the implementation in use and can avoid - * unnecessary layers of indirection. + *

Starting with version 2.3.0, RPC implementations should not try to build on this, but should + * instead provide code generator plugins which generate code specific to the particular RPC + * implementation. This way the generated code can be more appropriate for the implementation in use + * and can avoid unnecessary layers of indirection. * - *

The methods provided by the {@code RpcController} interface are intended - * to be a "least common denominator" set of features which we expect all - * implementations to support. Specific implementations may provide more - * advanced features (e.g. deadline propagation). + *

The methods provided by the {@code RpcController} interface are intended to be a "least common + * denominator" set of features which we expect all implementations to support. Specific + * implementations may provide more advanced features (e.g. deadline propagation). * * @author kenton@google.com Kenton Varda */ @@ -54,31 +52,25 @@ public interface RpcController { // are undefined on the server side (may throw RuntimeExceptions). /** - * Resets the RpcController to its initial state so that it may be reused in - * a new call. This can be called from the client side only. It must not - * be called while an RPC is in progress. + * Resets the RpcController to its initial state so that it may be reused in a new call. This can + * be called from the client side only. It must not be called while an RPC is in progress. */ void reset(); /** - * After a call has finished, returns true if the call failed. The possible - * reasons for failure depend on the RPC implementation. {@code failed()} - * most only be called on the client side, and must not be called before a - * call has finished. + * After a call has finished, returns true if the call failed. The possible reasons for failure + * depend on the RPC implementation. {@code failed()} most only be called on the client side, and + * must not be called before a call has finished. */ boolean failed(); - /** - * If {@code failed()} is {@code true}, returns a human-readable description - * of the error. - */ + /** If {@code failed()} is {@code true}, returns a human-readable description of the error. */ String errorText(); /** - * Advises the RPC system that the caller desires that the RPC call be - * canceled. The RPC system may cancel it immediately, may wait awhile and - * then cancel it, or may not even cancel the call at all. If the call is - * canceled, the "done" callback will still be called and the RpcController + * Advises the RPC system that the caller desires that the RPC call be canceled. The RPC system + * may cancel it immediately, may wait awhile and then cancel it, or may not even cancel the call + * at all. If the call is canceled, the "done" callback will still be called and the RpcController * will indicate that the call failed at that time. */ void startCancel(); @@ -88,31 +80,29 @@ public interface RpcController { // are undefined on the client side (may throw RuntimeExceptions). /** - * Causes {@code failed()} to return true on the client side. {@code reason} - * will be incorporated into the message returned by {@code errorText()}. - * If you find you need to return machine-readable information about - * failures, you should incorporate it into your response protocol buffer - * and should NOT call {@code setFailed()}. + * Causes {@code failed()} to return true on the client side. {@code reason} will be incorporated + * into the message returned by {@code errorText()}. If you find you need to return + * machine-readable information about failures, you should incorporate it into your response + * protocol buffer and should NOT call {@code setFailed()}. */ void setFailed(String reason); /** - * If {@code true}, indicates that the client canceled the RPC, so the server - * may as well give up on replying to it. This method must be called on the - * server side only. The server should still call the final "done" callback. + * If {@code true}, indicates that the client canceled the RPC, so the server may as well give up + * on replying to it. This method must be called on the server side only. The server should still + * call the final "done" callback. */ boolean isCanceled(); /** - * Asks that the given callback be called when the RPC is canceled. The - * parameter passed to the callback will always be {@code null}. The - * callback will always be called exactly once. If the RPC completes without - * being canceled, the callback will be called after completion. If the RPC - * has already been canceled when NotifyOnCancel() is called, the callback - * will be called immediately. + * Asks that the given callback be called when the RPC is canceled. The parameter passed to the + * callback will always be {@code null}. The callback will always be called exactly once. If the + * RPC completes without being canceled, the callback will be called after completion. If the RPC + * has already been canceled when NotifyOnCancel() is called, the callback will be called + * immediately. * - *

{@code notifyOnCancel()} must be called no more than once per request. - * It must be called on the server side only. + *

{@code notifyOnCancel()} must be called no more than once per request. It must be called on + * the server side only. */ void notifyOnCancel(RpcCallback callback); } diff --git a/java/core/src/main/java/com/google/protobuf/RpcUtil.java b/java/core/src/main/java/com/google/protobuf/RpcUtil.java index f7d555ae155f5..7bd056a5329ef 100644 --- a/java/core/src/main/java/com/google/protobuf/RpcUtil.java +++ b/java/core/src/main/java/com/google/protobuf/RpcUtil.java @@ -39,14 +39,13 @@ public final class RpcUtil { private RpcUtil() {} /** - * Take an {@code RpcCallback} and convert it to an - * {@code RpcCallback} accepting a specific message type. This is always - * type-safe (parameter type contravariance). + * Take an {@code RpcCallback} and convert it to an {@code RpcCallback} accepting a + * specific message type. This is always type-safe (parameter type contravariance). */ @SuppressWarnings("unchecked") - public static RpcCallback - specializeCallback(final RpcCallback originalCallback) { - return (RpcCallback)originalCallback; + public static RpcCallback specializeCallback( + final RpcCallback originalCallback) { + return (RpcCallback) originalCallback; // The above cast works, but only due to technical details of the Java // implementation. A more theoretically correct -- but less efficient -- // implementation would be as follows: @@ -58,15 +57,13 @@ private RpcUtil() {} } /** - * Take an {@code RpcCallback} accepting a specific message type and convert - * it to an {@code RpcCallback}. The generalized callback will - * accept any message object which has the same descriptor, and will convert - * it to the correct class before calling the original callback. However, - * if the generalized callback is given a message with a different descriptor, - * an exception will be thrown. + * Take an {@code RpcCallback} accepting a specific message type and convert it to an {@code + * RpcCallback}. The generalized callback will accept any message object which has the + * same descriptor, and will convert it to the correct class before calling the original callback. + * However, if the generalized callback is given a message with a different descriptor, an + * exception will be thrown. */ - public static - RpcCallback generalizeCallback( + public static RpcCallback generalizeCallback( final RpcCallback originalCallback, final Class originalClass, final Type defaultInstance) { @@ -85,25 +82,21 @@ public void run(final Message parameter) { } /** - * Creates a new message of type "Type" which is a copy of "source". "source" - * must have the same descriptor but may be a different class (e.g. - * DynamicMessage). + * Creates a new message of type "Type" which is a copy of "source". "source" must have the same + * descriptor but may be a different class (e.g. DynamicMessage). */ @SuppressWarnings("unchecked") private static Type copyAsType( final Type typeDefaultInstance, final Message source) { - return (Type) typeDefaultInstance - .newBuilderForType().mergeFrom(source).build(); + return (Type) typeDefaultInstance.newBuilderForType().mergeFrom(source).build(); } /** - * Creates a callback which can only be called once. This may be useful for - * security, when passing a callback to untrusted code: most callbacks do - * not expect to be called more than once, so doing so may expose bugs if it - * is not prevented. + * Creates a callback which can only be called once. This may be useful for security, when passing + * a callback to untrusted code: most callbacks do not expect to be called more than once, so + * doing so may expose bugs if it is not prevented. */ - public static - RpcCallback newOneTimeCallback( + public static RpcCallback newOneTimeCallback( final RpcCallback originalCallback) { return new RpcCallback() { private boolean alreadyCalled = false; @@ -122,15 +115,12 @@ public void run(final ParameterType parameter) { }; } - /** - * Exception thrown when a one-time callback is called more than once. - */ + /** Exception thrown when a one-time callback is called more than once. */ public static final class AlreadyCalledException extends RuntimeException { private static final long serialVersionUID = 5469741279507848266L; public AlreadyCalledException() { - super("This RpcCallback was already called and cannot be called " + - "multiple times."); + super("This RpcCallback was already called and cannot be called multiple times."); } } } diff --git a/java/core/src/main/java/com/google/protobuf/Schema.java b/java/core/src/main/java/com/google/protobuf/Schema.java new file mode 100644 index 0000000000000..d0e1e26e5bf78 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/Schema.java @@ -0,0 +1,85 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.ArrayDecoders.Registers; +import java.io.IOException; + +/** + * A runtime schema for a single protobuf message. A schema provides operations on message instances + * such as serialization/deserialization. + */ +@ExperimentalApi +interface Schema { + /** Writes the given message to the target {@link Writer}. */ + void writeTo(T message, Writer writer) throws IOException; + + /** + * Reads fields from the given {@link Reader} and merges them into the message. It doesn't make + * the message immutable after parsing is done. To make the message immutable, use {@link + * #makeImmutable}. + */ + void mergeFrom(T message, Reader reader, ExtensionRegistryLite extensionRegistry) + throws IOException; + + /** + * Like the above but parses from a byte[] without extensions. Entry point of fast path. Note that + * this method may throw IndexOutOfBoundsException if the input data is not valid protobuf wire + * format. Protobuf public API methods should catch and convert that exception to + * InvalidProtocolBufferException. + */ + void mergeFrom(T message, byte[] data, int position, int limit, Registers registers) + throws IOException; + + /** Marks repeated/map/extension/unknown fields as immutable. */ + void makeImmutable(T message); + + /** Checks whether all required fields are set. */ + boolean isInitialized(T message); + + /** Creates a new instance of the message class. */ + T newInstance(); + + /** Determine of the two messages are equal. */ + boolean equals(T message, T other); + + /** Compute a hashCode for the message. */ + int hashCode(T message); + + /** + * Merge values from {@code other} into {@code message}. This method doesn't make the message + * immutable. To make the message immutable after merging, use {@link #makeImmutable}. + */ + void mergeFrom(T message, T other); + + /** Compute the serialized size of the message. */ + int getSerializedSize(T message); +} diff --git a/java/core/src/main/java/com/google/protobuf/SchemaFactory.java b/java/core/src/main/java/com/google/protobuf/SchemaFactory.java new file mode 100644 index 0000000000000..cf38dd69945f7 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/SchemaFactory.java @@ -0,0 +1,38 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** A factory that manufactures {@link Schema} instances for protobuf messages. */ +@ExperimentalApi +interface SchemaFactory { + /** Creates a schema instance for the given protobuf message type. */ + Schema createSchema(Class messageType); +} diff --git a/java/core/src/main/java/com/google/protobuf/SchemaUtil.java b/java/core/src/main/java/com/google/protobuf/SchemaUtil.java new file mode 100644 index 0000000000000..4c8bb06f041c5 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/SchemaUtil.java @@ -0,0 +1,991 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.FieldSet.FieldDescriptorLite; +import com.google.protobuf.Internal.EnumLiteMap; +import com.google.protobuf.Internal.EnumVerifier; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Iterator; +import java.util.List; +import java.util.RandomAccess; + +/** Helper methods used by schemas. */ +@ExperimentalApi +final class SchemaUtil { + private static final Class GENERATED_MESSAGE_CLASS = getGeneratedMessageClass(); + private static final UnknownFieldSchema PROTO2_UNKNOWN_FIELD_SET_SCHEMA = + getUnknownFieldSetSchema(false); + private static final UnknownFieldSchema PROTO3_UNKNOWN_FIELD_SET_SCHEMA = + getUnknownFieldSetSchema(true); + private static final UnknownFieldSchema UNKNOWN_FIELD_SET_LITE_SCHEMA = + new UnknownFieldSetLiteSchema(); + + private static final int DEFAULT_LOOK_UP_START_NUMBER = 40; + + private SchemaUtil() {} + + /** + * Requires that the given message extend {@link com.google.protobuf.GeneratedMessageV3} or {@link + * GeneratedMessageLite}. + */ + public static void requireGeneratedMessage(Class messageType) { + if (!GeneratedMessageLite.class.isAssignableFrom(messageType) + && GENERATED_MESSAGE_CLASS != null + && !GENERATED_MESSAGE_CLASS.isAssignableFrom(messageType)) { + throw new IllegalArgumentException( + "Message classes must extend GeneratedMessage or GeneratedMessageLite"); + } + } + + public static void writeDouble(int fieldNumber, double value, Writer writer) throws IOException { + if (Double.compare(value, 0.0) != 0) { + writer.writeDouble(fieldNumber, value); + } + } + + public static void writeFloat(int fieldNumber, float value, Writer writer) throws IOException { + if (Float.compare(value, 0.0f) != 0) { + writer.writeFloat(fieldNumber, value); + } + } + + public static void writeInt64(int fieldNumber, long value, Writer writer) throws IOException { + if (value != 0) { + writer.writeInt64(fieldNumber, value); + } + } + + public static void writeUInt64(int fieldNumber, long value, Writer writer) throws IOException { + if (value != 0) { + writer.writeUInt64(fieldNumber, value); + } + } + + public static void writeSInt64(int fieldNumber, long value, Writer writer) throws IOException { + if (value != 0) { + writer.writeSInt64(fieldNumber, value); + } + } + + public static void writeFixed64(int fieldNumber, long value, Writer writer) throws IOException { + if (value != 0) { + writer.writeFixed64(fieldNumber, value); + } + } + + public static void writeSFixed64(int fieldNumber, long value, Writer writer) throws IOException { + if (value != 0) { + writer.writeSFixed64(fieldNumber, value); + } + } + + public static void writeInt32(int fieldNumber, int value, Writer writer) throws IOException { + if (value != 0) { + writer.writeInt32(fieldNumber, value); + } + } + + public static void writeUInt32(int fieldNumber, int value, Writer writer) throws IOException { + if (value != 0) { + writer.writeUInt32(fieldNumber, value); + } + } + + public static void writeSInt32(int fieldNumber, int value, Writer writer) throws IOException { + if (value != 0) { + writer.writeSInt32(fieldNumber, value); + } + } + + public static void writeFixed32(int fieldNumber, int value, Writer writer) throws IOException { + if (value != 0) { + writer.writeFixed32(fieldNumber, value); + } + } + + public static void writeSFixed32(int fieldNumber, int value, Writer writer) throws IOException { + if (value != 0) { + writer.writeSFixed32(fieldNumber, value); + } + } + + public static void writeEnum(int fieldNumber, int value, Writer writer) throws IOException { + if (value != 0) { + writer.writeEnum(fieldNumber, value); + } + } + + public static void writeBool(int fieldNumber, boolean value, Writer writer) throws IOException { + if (value) { + writer.writeBool(fieldNumber, true); + } + } + + public static void writeString(int fieldNumber, Object value, Writer writer) throws IOException { + if (value instanceof String) { + writeStringInternal(fieldNumber, (String) value, writer); + } else { + writeBytes(fieldNumber, (ByteString) value, writer); + } + } + + private static void writeStringInternal(int fieldNumber, String value, Writer writer) + throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeString(fieldNumber, value); + } + } + + public static void writeBytes(int fieldNumber, ByteString value, Writer writer) + throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeBytes(fieldNumber, value); + } + } + + public static void writeMessage(int fieldNumber, Object value, Writer writer) throws IOException { + if (value != null) { + writer.writeMessage(fieldNumber, value); + } + } + + public static void writeDoubleList( + int fieldNumber, List value, Writer writer, boolean packed) throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeDoubleList(fieldNumber, value, packed); + } + } + + public static void writeFloatList( + int fieldNumber, List value, Writer writer, boolean packed) throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeFloatList(fieldNumber, value, packed); + } + } + + public static void writeInt64List( + int fieldNumber, List value, Writer writer, boolean packed) throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeInt64List(fieldNumber, value, packed); + } + } + + public static void writeUInt64List( + int fieldNumber, List value, Writer writer, boolean packed) throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeUInt64List(fieldNumber, value, packed); + } + } + + public static void writeSInt64List( + int fieldNumber, List value, Writer writer, boolean packed) throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeSInt64List(fieldNumber, value, packed); + } + } + + public static void writeFixed64List( + int fieldNumber, List value, Writer writer, boolean packed) throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeFixed64List(fieldNumber, value, packed); + } + } + + public static void writeSFixed64List( + int fieldNumber, List value, Writer writer, boolean packed) throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeSFixed64List(fieldNumber, value, packed); + } + } + + public static void writeInt32List( + int fieldNumber, List value, Writer writer, boolean packed) throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeInt32List(fieldNumber, value, packed); + } + } + + public static void writeUInt32List( + int fieldNumber, List value, Writer writer, boolean packed) throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeUInt32List(fieldNumber, value, packed); + } + } + + public static void writeSInt32List( + int fieldNumber, List value, Writer writer, boolean packed) throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeSInt32List(fieldNumber, value, packed); + } + } + + public static void writeFixed32List( + int fieldNumber, List value, Writer writer, boolean packed) throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeFixed32List(fieldNumber, value, packed); + } + } + + public static void writeSFixed32List( + int fieldNumber, List value, Writer writer, boolean packed) throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeSFixed32List(fieldNumber, value, packed); + } + } + + public static void writeEnumList( + int fieldNumber, List value, Writer writer, boolean packed) throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeEnumList(fieldNumber, value, packed); + } + } + + public static void writeBoolList( + int fieldNumber, List value, Writer writer, boolean packed) throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeBoolList(fieldNumber, value, packed); + } + } + + public static void writeStringList(int fieldNumber, List value, Writer writer) + throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeStringList(fieldNumber, value); + } + } + + public static void writeBytesList(int fieldNumber, List value, Writer writer) + throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeBytesList(fieldNumber, value); + } + } + + public static void writeMessageList(int fieldNumber, List value, Writer writer) + throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeMessageList(fieldNumber, value); + } + } + + public static void writeMessageList(int fieldNumber, List value, Writer writer, Schema schema) + throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeMessageList(fieldNumber, value, schema); + } + } + + public static void writeLazyFieldList(int fieldNumber, List value, Writer writer) + throws IOException { + if (value != null && !value.isEmpty()) { + for (Object item : value) { + ((LazyFieldLite) item).writeTo(writer, fieldNumber); + } + } + } + + public static void writeGroupList(int fieldNumber, List value, Writer writer) + throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeGroupList(fieldNumber, value); + } + } + + public static void writeGroupList(int fieldNumber, List value, Writer writer, Schema schema) + throws IOException { + if (value != null && !value.isEmpty()) { + writer.writeGroupList(fieldNumber, value, schema); + } + } + + static int computeSizeInt64ListNoTag(List list) { + final int length = list.size(); + if (length == 0) { + return 0; + } + + int size = 0; + + if (list instanceof LongArrayList) { + final LongArrayList primitiveList = (LongArrayList) list; + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeInt64SizeNoTag(primitiveList.getLong(i)); + } + } else { + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeInt64SizeNoTag(list.get(i)); + } + } + return size; + } + + static int computeSizeInt64List(int fieldNumber, List list, boolean packed) { + final int length = list.size(); + if (length == 0) { + return 0; + } + int size = computeSizeInt64ListNoTag(list); + + if (packed) { + return CodedOutputStream.computeTagSize(fieldNumber) + + CodedOutputStream.computeLengthDelimitedFieldSize(size); + } else { + return size + (list.size() * CodedOutputStream.computeTagSize(fieldNumber)); + } + } + + static int computeSizeUInt64ListNoTag(List list) { + final int length = list.size(); + if (length == 0) { + return 0; + } + + int size = 0; + + if (list instanceof LongArrayList) { + final LongArrayList primitiveList = (LongArrayList) list; + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeUInt64SizeNoTag(primitiveList.getLong(i)); + } + } else { + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeUInt64SizeNoTag(list.get(i)); + } + } + return size; + } + + static int computeSizeUInt64List(int fieldNumber, List list, boolean packed) { + final int length = list.size(); + if (length == 0) { + return 0; + } + int size = computeSizeUInt64ListNoTag(list); + + if (packed) { + return CodedOutputStream.computeTagSize(fieldNumber) + + CodedOutputStream.computeLengthDelimitedFieldSize(size); + } else { + return size + (length * CodedOutputStream.computeTagSize(fieldNumber)); + } + } + + static int computeSizeSInt64ListNoTag(List list) { + final int length = list.size(); + if (length == 0) { + return 0; + } + + int size = 0; + + if (list instanceof LongArrayList) { + final LongArrayList primitiveList = (LongArrayList) list; + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeSInt64SizeNoTag(primitiveList.getLong(i)); + } + } else { + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeSInt64SizeNoTag(list.get(i)); + } + } + return size; + } + + static int computeSizeSInt64List(int fieldNumber, List list, boolean packed) { + final int length = list.size(); + if (length == 0) { + return 0; + } + int size = computeSizeSInt64ListNoTag(list); + + if (packed) { + return CodedOutputStream.computeTagSize(fieldNumber) + + CodedOutputStream.computeLengthDelimitedFieldSize(size); + } else { + return size + (length * CodedOutputStream.computeTagSize(fieldNumber)); + } + } + + static int computeSizeEnumListNoTag(List list) { + final int length = list.size(); + if (length == 0) { + return 0; + } + + int size = 0; + + if (list instanceof IntArrayList) { + final IntArrayList primitiveList = (IntArrayList) list; + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeEnumSizeNoTag(primitiveList.getInt(i)); + } + } else { + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeEnumSizeNoTag(list.get(i)); + } + } + return size; + } + + static int computeSizeEnumList(int fieldNumber, List list, boolean packed) { + final int length = list.size(); + if (length == 0) { + return 0; + } + int size = computeSizeEnumListNoTag(list); + + if (packed) { + return CodedOutputStream.computeTagSize(fieldNumber) + + CodedOutputStream.computeLengthDelimitedFieldSize(size); + } else { + return size + (length * CodedOutputStream.computeTagSize(fieldNumber)); + } + } + + static int computeSizeInt32ListNoTag(List list) { + final int length = list.size(); + if (length == 0) { + return 0; + } + + int size = 0; + + if (list instanceof IntArrayList) { + final IntArrayList primitiveList = (IntArrayList) list; + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeInt32SizeNoTag(primitiveList.getInt(i)); + } + } else { + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeInt32SizeNoTag(list.get(i)); + } + } + return size; + } + + static int computeSizeInt32List(int fieldNumber, List list, boolean packed) { + final int length = list.size(); + if (length == 0) { + return 0; + } + int size = computeSizeInt32ListNoTag(list); + + if (packed) { + return CodedOutputStream.computeTagSize(fieldNumber) + + CodedOutputStream.computeLengthDelimitedFieldSize(size); + } else { + return size + (length * CodedOutputStream.computeTagSize(fieldNumber)); + } + } + + static int computeSizeUInt32ListNoTag(List list) { + final int length = list.size(); + if (length == 0) { + return 0; + } + + int size = 0; + + if (list instanceof IntArrayList) { + final IntArrayList primitiveList = (IntArrayList) list; + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeUInt32SizeNoTag(primitiveList.getInt(i)); + } + } else { + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeUInt32SizeNoTag(list.get(i)); + } + } + return size; + } + + static int computeSizeUInt32List(int fieldNumber, List list, boolean packed) { + final int length = list.size(); + if (length == 0) { + return 0; + } + int size = computeSizeUInt32ListNoTag(list); + + if (packed) { + return CodedOutputStream.computeTagSize(fieldNumber) + + CodedOutputStream.computeLengthDelimitedFieldSize(size); + } else { + return size + (length * CodedOutputStream.computeTagSize(fieldNumber)); + } + } + + static int computeSizeSInt32ListNoTag(List list) { + final int length = list.size(); + if (length == 0) { + return 0; + } + + int size = 0; + + if (list instanceof IntArrayList) { + final IntArrayList primitiveList = (IntArrayList) list; + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeSInt32SizeNoTag(primitiveList.getInt(i)); + } + } else { + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeSInt32SizeNoTag(list.get(i)); + } + } + return size; + } + + static int computeSizeSInt32List(int fieldNumber, List list, boolean packed) { + final int length = list.size(); + if (length == 0) { + return 0; + } + + int size = computeSizeSInt32ListNoTag(list); + + if (packed) { + return CodedOutputStream.computeTagSize(fieldNumber) + + CodedOutputStream.computeLengthDelimitedFieldSize(size); + } else { + return size + (length * CodedOutputStream.computeTagSize(fieldNumber)); + } + } + + static int computeSizeFixed32ListNoTag(List list) { + return list.size() * WireFormat.FIXED32_SIZE; + } + + static int computeSizeFixed32List(int fieldNumber, List list, boolean packed) { + final int length = list.size(); + if (length == 0) { + return 0; + } + if (packed) { + int dataSize = length * WireFormat.FIXED32_SIZE; + return CodedOutputStream.computeTagSize(fieldNumber) + + CodedOutputStream.computeLengthDelimitedFieldSize(dataSize); + } else { + return length * CodedOutputStream.computeFixed32Size(fieldNumber, 0); + } + } + + static int computeSizeFixed64ListNoTag(List list) { + return list.size() * WireFormat.FIXED64_SIZE; + } + + static int computeSizeFixed64List(int fieldNumber, List list, boolean packed) { + final int length = list.size(); + if (length == 0) { + return 0; + } + if (packed) { + final int dataSize = length * WireFormat.FIXED64_SIZE; + return CodedOutputStream.computeTagSize(fieldNumber) + + CodedOutputStream.computeLengthDelimitedFieldSize(dataSize); + } else { + return length * CodedOutputStream.computeFixed64Size(fieldNumber, 0); + } + } + + static int computeSizeBoolListNoTag(List list) { + // bools are 1 byte varints + return list.size(); + } + + static int computeSizeBoolList(int fieldNumber, List list, boolean packed) { + final int length = list.size(); + if (length == 0) { + return 0; + } + if (packed) { + // bools are 1 byte varints + return CodedOutputStream.computeTagSize(fieldNumber) + + CodedOutputStream.computeLengthDelimitedFieldSize(length); + } else { + return length * CodedOutputStream.computeBoolSize(fieldNumber, true); + } + } + + static int computeSizeStringList(int fieldNumber, List list) { + final int length = list.size(); + if (length == 0) { + return 0; + } + int size = length * CodedOutputStream.computeTagSize(fieldNumber); + if (list instanceof LazyStringList) { + LazyStringList lazyList = ((LazyStringList) list); + for (int i = 0; i < length; i++) { + Object value = lazyList.getRaw(i); + if (value instanceof ByteString) { + size += CodedOutputStream.computeBytesSizeNoTag((ByteString) value); + } else { + size += CodedOutputStream.computeStringSizeNoTag((String) value); + } + } + } else { + for (int i = 0; i < length; i++) { + Object value = list.get(i); + if (value instanceof ByteString) { + size += CodedOutputStream.computeBytesSizeNoTag((ByteString) value); + } else { + size += CodedOutputStream.computeStringSizeNoTag((String) value); + } + } + } + return size; + } + + static int computeSizeMessage(int fieldNumber, Object value, Schema schema) { + if (value instanceof LazyFieldLite) { + return CodedOutputStream.computeLazyFieldSize(fieldNumber, (LazyFieldLite) value); + } else { + return CodedOutputStream.computeMessageSize(fieldNumber, (MessageLite) value, schema); + } + } + + static int computeSizeMessageList(int fieldNumber, List list) { + final int length = list.size(); + if (length == 0) { + return 0; + } + int size = length * CodedOutputStream.computeTagSize(fieldNumber); + for (int i = 0; i < length; i++) { + Object value = list.get(i); + if (value instanceof LazyFieldLite) { + size += CodedOutputStream.computeLazyFieldSizeNoTag((LazyFieldLite) value); + } else { + size += CodedOutputStream.computeMessageSizeNoTag((MessageLite) value); + } + } + return size; + } + + static int computeSizeMessageList(int fieldNumber, List list, Schema schema) { + final int length = list.size(); + if (length == 0) { + return 0; + } + int size = length * CodedOutputStream.computeTagSize(fieldNumber); + for (int i = 0; i < length; i++) { + Object value = list.get(i); + if (value instanceof LazyFieldLite) { + size += CodedOutputStream.computeLazyFieldSizeNoTag((LazyFieldLite) value); + } else { + size += CodedOutputStream.computeMessageSizeNoTag((MessageLite) value, schema); + } + } + return size; + } + + static int computeSizeByteStringList(int fieldNumber, List list) { + final int length = list.size(); + if (length == 0) { + return 0; + } + int size = length * CodedOutputStream.computeTagSize(fieldNumber); + for (int i = 0; i < list.size(); i++) { + size += CodedOutputStream.computeBytesSizeNoTag(list.get(i)); + } + return size; + } + + static int computeSizeGroupList(int fieldNumber, List list) { + final int length = list.size(); + if (length == 0) { + return 0; + } + int size = 0; + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeGroupSize(fieldNumber, list.get(i)); + } + return size; + } + + static int computeSizeGroupList(int fieldNumber, List list, Schema schema) { + final int length = list.size(); + if (length == 0) { + return 0; + } + int size = 0; + for (int i = 0; i < length; i++) { + size += CodedOutputStream.computeGroupSize(fieldNumber, list.get(i), schema); + } + return size; + } + + /** + * Determines whether to issue tableswitch or lookupswitch for the mergeFrom method. + * + * @see #shouldUseTableSwitch(int, int, int) + */ + public static boolean shouldUseTableSwitch(FieldInfo[] fields) { + // Determine whether to issue a tableswitch or a lookupswitch + // instruction. + if (fields.length == 0) { + return false; + } + + int lo = fields[0].getFieldNumber(); + int hi = fields[fields.length - 1].getFieldNumber(); + return shouldUseTableSwitch(lo, hi, fields.length); + } + + /** + * Determines whether to issue tableswitch or lookupswitch for the mergeFrom method. This is based + * on the + * logic in the JDK. + * + * @param lo the lowest fieldNumber contained within the message. + * @param hi the highest fieldNumber contained within the message. + * @param numFields the total number of fields in the message. + * @return {@code true} if tableswitch should be used, rather than lookupswitch. + */ + public static boolean shouldUseTableSwitch(int lo, int hi, int numFields) { + if (hi < DEFAULT_LOOK_UP_START_NUMBER) { + return true; + } + long tableSpaceCost = ((long) hi - lo + 1); // words + long tableTimeCost = 3; // comparisons + long lookupSpaceCost = 3 + 2 * (long) numFields; + long lookupTimeCost = 3 + (long) numFields; + return tableSpaceCost + 3 * tableTimeCost <= lookupSpaceCost + 3 * lookupTimeCost; + } + + public static UnknownFieldSchema proto2UnknownFieldSetSchema() { + return PROTO2_UNKNOWN_FIELD_SET_SCHEMA; + } + + public static UnknownFieldSchema proto3UnknownFieldSetSchema() { + return PROTO3_UNKNOWN_FIELD_SET_SCHEMA; + } + + public static UnknownFieldSchema unknownFieldSetLiteSchema() { + return UNKNOWN_FIELD_SET_LITE_SCHEMA; + } + + private static UnknownFieldSchema getUnknownFieldSetSchema(boolean proto3) { + try { + Class clz = getUnknownFieldSetSchemaClass(); + if (clz == null) { + return null; + } + return (UnknownFieldSchema) clz.getConstructor(boolean.class).newInstance(proto3); + } catch (Throwable t) { + return null; + } + } + + private static Class getGeneratedMessageClass() { + try { + return Class.forName("com.google.protobuf.GeneratedMessageV3"); + } catch (Throwable e) { + return null; + } + } + + private static Class getUnknownFieldSetSchemaClass() { + try { + return Class.forName("com.google.protobuf.UnknownFieldSetSchema"); + } catch (Throwable e) { + return null; + } + } + + static Object getMapDefaultEntry(Class clazz, String name) { + try { + Class holder = + Class.forName(clazz.getName() + "$" + toCamelCase(name, true) + "DefaultEntryHolder"); + Field[] fields = holder.getDeclaredFields(); + if (fields.length != 1) { + throw new IllegalStateException( + "Unable to look up map field default entry holder class for " + + name + + " in " + + clazz.getName()); + } + return UnsafeUtil.getStaticObject(fields[0]); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + + static String toCamelCase(String name, boolean capNext) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < name.length(); ++i) { + char c = name.charAt(i); + // Matches protoc field name function: + if ('a' <= c && c <= 'z') { + if (capNext) { + sb.append((char) (c + ('A' - 'a'))); + } else { + sb.append(c); + } + capNext = false; + } else if ('A' <= c && c <= 'Z') { + if (i == 0 && !capNext) { + // Force first letter to lower-case unless explicitly told to capitalize it. + sb.append((char) (c - ('A' - 'a'))); + } else { + sb.append(c); + } + capNext = false; + } else if ('0' <= c && c <= '9') { + sb.append(c); + capNext = true; + } else { + capNext = true; + } + } + return sb.toString(); + } + + /** Returns true if both are null or both are {@link Object#equals}. */ + static boolean safeEquals(Object a, Object b) { + return a == b || (a != null && a.equals(b)); + } + + static void mergeMap(MapFieldSchema mapFieldSchema, T message, T o, long offset) { + Object merged = + mapFieldSchema.mergeFrom( + UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(o, offset)); + UnsafeUtil.putObject(message, offset, merged); + } + + static > void mergeExtensions( + ExtensionSchema schema, T message, T other) { + FieldSet otherExtensions = schema.getExtensions(other); + if (!otherExtensions.isEmpty()) { + FieldSet messageExtensions = schema.getMutableExtensions(message); + messageExtensions.mergeFrom(otherExtensions); + } + } + + static void mergeUnknownFields( + UnknownFieldSchema schema, T message, T other) { + UT messageUnknowns = schema.getFromMessage(message); + UT otherUnknowns = schema.getFromMessage(other); + UT merged = schema.merge(messageUnknowns, otherUnknowns); + schema.setToMessage(message, merged); + } + + /** Filters unrecognized enum values in a list. */ + static UB filterUnknownEnumList( + int number, + List enumList, + EnumLiteMap enumMap, + UB unknownFields, + UnknownFieldSchema unknownFieldSchema) { + if (enumMap == null) { + return unknownFields; + } + // TODO(dweis): Specialize for IntArrayList to avoid boxing. + if (enumList instanceof RandomAccess) { + int writePos = 0; + int size = enumList.size(); + for (int readPos = 0; readPos < size; ++readPos) { + int enumValue = enumList.get(readPos); + if (enumMap.findValueByNumber(enumValue) != null) { + if (readPos != writePos) { + enumList.set(writePos, enumValue); + } + ++writePos; + } else { + unknownFields = storeUnknownEnum(number, enumValue, unknownFields, unknownFieldSchema); + } + } + if (writePos != size) { + enumList.subList(writePos, size).clear(); + } + } else { + for (Iterator it = enumList.iterator(); it.hasNext(); ) { + int enumValue = it.next(); + if (enumMap.findValueByNumber(enumValue) == null) { + unknownFields = storeUnknownEnum(number, enumValue, unknownFields, unknownFieldSchema); + it.remove(); + } + } + } + return unknownFields; + } + + /** Filters unrecognized enum values in a list. */ + static UB filterUnknownEnumList( + int number, + List enumList, + EnumVerifier enumVerifier, + UB unknownFields, + UnknownFieldSchema unknownFieldSchema) { + if (enumVerifier == null) { + return unknownFields; + } + // TODO(dweis): Specialize for IntArrayList to avoid boxing. + if (enumList instanceof RandomAccess) { + int writePos = 0; + int size = enumList.size(); + for (int readPos = 0; readPos < size; ++readPos) { + int enumValue = enumList.get(readPos); + if (enumVerifier.isInRange(enumValue)) { + if (readPos != writePos) { + enumList.set(writePos, enumValue); + } + ++writePos; + } else { + unknownFields = storeUnknownEnum(number, enumValue, unknownFields, unknownFieldSchema); + } + } + if (writePos != size) { + enumList.subList(writePos, size).clear(); + } + } else { + for (Iterator it = enumList.iterator(); it.hasNext(); ) { + int enumValue = it.next(); + if (!enumVerifier.isInRange(enumValue)) { + unknownFields = storeUnknownEnum(number, enumValue, unknownFields, unknownFieldSchema); + it.remove(); + } + } + } + return unknownFields; + } + + /** Stores an unrecognized enum value as an unknown value. */ + static UB storeUnknownEnum( + int number, int enumValue, UB unknownFields, UnknownFieldSchema unknownFieldSchema) { + if (unknownFields == null) { + unknownFields = unknownFieldSchema.newBuilder(); + } + unknownFieldSchema.addVarint(unknownFields, number, enumValue); + return unknownFields; + } +} diff --git a/java/core/src/main/java/com/google/protobuf/Service.java b/java/core/src/main/java/com/google/protobuf/Service.java index ba7b033ed4387..d45cdaec9a00c 100644 --- a/java/core/src/main/java/com/google/protobuf/Service.java +++ b/java/core/src/main/java/com/google/protobuf/Service.java @@ -31,70 +31,63 @@ package com.google.protobuf; /** - * Abstract base interface for protocol-buffer-based RPC services. Services - * themselves are abstract classes (implemented either by servers or as - * stubs), but they subclass this base interface. The methods of this - * interface can be used to call the methods of the service without knowing - * its exact type at compile time (analogous to the Message interface). + * Abstract base interface for protocol-buffer-based RPC services. Services themselves are abstract + * classes (implemented either by servers or as stubs), but they subclass this base interface. The + * methods of this interface can be used to call the methods of the service without knowing its + * exact type at compile time (analogous to the Message interface). * - *

Starting with version 2.3.0, RPC implementations should not try to build - * on this, but should instead provide code generator plugins which generate - * code specific to the particular RPC implementation. This way the generated - * code can be more appropriate for the implementation in use and can avoid - * unnecessary layers of indirection. + *

Starting with version 2.3.0, RPC implementations should not try to build on this, but should + * instead provide code generator plugins which generate code specific to the particular RPC + * implementation. This way the generated code can be more appropriate for the implementation in use + * and can avoid unnecessary layers of indirection. * * @author kenton@google.com Kenton Varda */ public interface Service { - /** - * Get the {@code ServiceDescriptor} describing this service and its methods. - */ + /** Get the {@code ServiceDescriptor} describing this service and its methods. */ Descriptors.ServiceDescriptor getDescriptorForType(); /** - *

Call a method of the service specified by MethodDescriptor. This is - * normally implemented as a simple {@code switch()} that calls the standard - * definitions of the service's methods. + * Call a method of the service specified by MethodDescriptor. This is normally implemented as a + * simple {@code switch()} that calls the standard definitions of the service's methods. * *

Preconditions: + * *

    *
  • {@code method.getService() == getDescriptorForType()} - *
  • {@code request} is of the exact same class as the object returned by - * {@code getRequestPrototype(method)}. - *
  • {@code controller} is of the correct type for the RPC implementation - * being used by this Service. For stubs, the "correct type" depends - * on the RpcChannel which the stub is using. Server-side Service - * implementations are expected to accept whatever type of - * {@code RpcController} the server-side RPC implementation uses. + *
  • {@code request} is of the exact same class as the object returned by {@code + * getRequestPrototype(method)}. + *
  • {@code controller} is of the correct type for the RPC implementation being used by this + * Service. For stubs, the "correct type" depends on the RpcChannel which the stub is using. + * Server-side Service implementations are expected to accept whatever type of {@code + * RpcController} the server-side RPC implementation uses. *
* *

Postconditions: + * *

    - *
  • {@code done} will be called when the method is complete. This may be - * before {@code callMethod()} returns or it may be at some point in - * the future. - *
  • The parameter to {@code done} is the response. It must be of the - * exact same type as would be returned by - * {@code getResponsePrototype(method)}. - *
  • If the RPC failed, the parameter to {@code done} will be - * {@code null}. Further details about the failure can be found by - * querying {@code controller}. + *
  • {@code done} will be called when the method is complete. This may be before {@code + * callMethod()} returns or it may be at some point in the future. + *
  • The parameter to {@code done} is the response. It must be of the exact same type as would + * be returned by {@code getResponsePrototype(method)}. + *
  • If the RPC failed, the parameter to {@code done} will be {@code null}. Further details + * about the failure can be found by querying {@code controller}. *
*/ - void callMethod(Descriptors.MethodDescriptor method, - RpcController controller, - Message request, - RpcCallback done); + void callMethod( + Descriptors.MethodDescriptor method, + RpcController controller, + Message request, + RpcCallback done); /** - *

{@code callMethod()} requires that the request passed in is of a - * particular subclass of {@code Message}. {@code getRequestPrototype()} - * gets the default instances of this type for a given method. You can then - * call {@code Message.newBuilderForType()} on this instance to - * construct a builder to build an object which you can then pass to - * {@code callMethod()}. + * {@code callMethod()} requires that the request passed in is of a particular subclass of {@code + * Message}. {@code getRequestPrototype()} gets the default instances of this type for a given + * method. You can then call {@code Message.newBuilderForType()} on this instance to construct a + * builder to build an object which you can then pass to {@code callMethod()}. * *

Example: + * *

    *   MethodDescriptor method =
    *     service.getDescriptorForType().findMethodByName("Foo");
@@ -107,11 +100,10 @@ void callMethod(Descriptors.MethodDescriptor method,
   Message getRequestPrototype(Descriptors.MethodDescriptor method);
 
   /**
-   * Like {@code getRequestPrototype()}, but gets a prototype of the response
-   * message.  {@code getResponsePrototype()} is generally not needed because
-   * the {@code Service} implementation constructs the response message itself,
-   * but it may be useful in some cases to know ahead of time what type of
-   * object will be returned.
+   * Like {@code getRequestPrototype()}, but gets a prototype of the response message. {@code
+   * getResponsePrototype()} is generally not needed because the {@code Service} implementation
+   * constructs the response message itself, but it may be useful in some cases to know ahead of
+   * time what type of object will be returned.
    */
   Message getResponsePrototype(Descriptors.MethodDescriptor method);
 }
diff --git a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
index 941b5defc955c..acdc1de18315a 100644
--- a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
+++ b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
@@ -30,36 +30,32 @@
 
 package com.google.protobuf;
 
+import static com.google.protobuf.Internal.checkNotNull;
+
 /**
- * {@code SingleFieldBuilder} implements a structure that a protocol
- * message uses to hold a single field of another protocol message. It supports
- * the classical use case of setting an immutable {@link Message} as the value
- * of the field and is highly optimized around this.
- * 
- * It also supports the additional use case of setting a {@link Message.Builder} - * as the field and deferring conversion of that {@code Builder} - * to an immutable {@code Message}. In this way, it's possible to maintain - * a tree of {@code Builder}'s that acts as a fully read/write data - * structure. + * {@code SingleFieldBuilder} implements a structure that a protocol message uses to hold a single + * field of another protocol message. It supports the classical use case of setting an immutable + * {@link Message} as the value of the field and is highly optimized around this. + * + *

It also supports the additional use case of setting a {@link Message.Builder} as the field and + * deferring conversion of that {@code Builder} to an immutable {@code Message}. In this way, it's + * possible to maintain a tree of {@code Builder}'s that acts as a fully read/write data structure. *
- * Logically, one can think of a tree of builders as converting the entire tree - * to messages when build is called on the root or when any method is called - * that desires a Message instead of a Builder. In terms of the implementation, - * the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder} - * classes cache messages that were created so that messages only need to be - * created when some change occurred in its builder or a builder for one of its - * descendants. + * Logically, one can think of a tree of builders as converting the entire tree to messages when + * build is called on the root or when any method is called that desires a Message instead of a + * Builder. In terms of the implementation, the {@code SingleFieldBuilder} and {@code + * RepeatedFieldBuilder} classes cache messages that were created so that messages only need to be + * created when some change occurred in its builder or a builder for one of its descendants. * * @param the type of message for the field * @param the type of builder for the field * @param the common interface for the message and the builder - * * @author jonp@google.com (Jon Perlow) */ -public class SingleFieldBuilder - +public class SingleFieldBuilder< + MType extends GeneratedMessage, + BType extends GeneratedMessage.Builder, + IType extends MessageOrBuilder> implements GeneratedMessage.BuilderParent { // Parent to send changes to. @@ -80,14 +76,8 @@ public class SingleFieldBuilder // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener. private boolean isClean; - public SingleFieldBuilder( - MType message, - GeneratedMessage.BuilderParent parent, - boolean isClean) { - if (message == null) { - throw new NullPointerException(); - } - this.message = message; + public SingleFieldBuilder(MType message, GeneratedMessage.BuilderParent parent, boolean isClean) { + this.message = checkNotNull(message); this.parent = parent; this.isClean = isClean; } @@ -98,10 +88,9 @@ public void dispose() { } /** - * Get the message for the field. If the message is currently stored - * as a {@code Builder}, it is converted to a {@code Message} by - * calling {@link Message.Builder#buildPartial} on it. If no message has - * been set, returns the default instance of the message. + * Get the message for the field. If the message is currently stored as a {@code Builder}, it is + * converted to a {@code Message} by calling {@link Message.Builder#buildPartial} on it. If no + * message has been set, returns the default instance of the message. * * @return the message for the field */ @@ -127,8 +116,8 @@ public MType build() { } /** - * Gets a builder for the field. If no builder has been created yet, a - * builder is created on demand by calling {@link Message#toBuilder}. + * Gets a builder for the field. If no builder has been created yet, a builder is created on + * demand by calling {@link Message#toBuilder}. * * @return The builder for the field */ @@ -147,32 +136,28 @@ public BType getBuilder() { } /** - * Gets the base class interface for the field. This may either be a builder - * or a message. It will return whatever is more efficient. + * Gets the base class interface for the field. This may either be a builder or a message. It will + * return whatever is more efficient. * * @return the message or builder for the field as the base class interface */ @SuppressWarnings("unchecked") public IType getMessageOrBuilder() { if (builder != null) { - return (IType) builder; + return (IType) builder; } else { return (IType) message; } } /** - * Sets a message for the field replacing any existing value. + * Sets a message for the field replacing any existing value. * * @param message the message to set * @return the builder */ - public SingleFieldBuilder setMessage( - MType message) { - if (message == null) { - throw new NullPointerException(); - } - this.message = message; + public SingleFieldBuilder setMessage(MType message) { + this.message = checkNotNull(message); if (builder != null) { builder.dispose(); builder = null; @@ -187,8 +172,7 @@ public SingleFieldBuilder setMessage( * @param value the value to merge from * @return the builder */ - public SingleFieldBuilder mergeFrom( - MType value) { + public SingleFieldBuilder mergeFrom(MType value) { if (builder == null && message == message.getDefaultInstanceForType()) { message = value; } else { @@ -205,9 +189,11 @@ public SingleFieldBuilder mergeFrom( */ @SuppressWarnings("unchecked") public SingleFieldBuilder clear() { - message = (MType) (message != null ? - message.getDefaultInstanceForType() : - builder.getDefaultInstanceForType()); + message = + (MType) + (message != null + ? message.getDefaultInstanceForType() + : builder.getDefaultInstanceForType()); if (builder != null) { builder.dispose(); builder = null; @@ -217,8 +203,8 @@ public SingleFieldBuilder clear() { } /** - * Called when a the builder or one of its nested children has changed - * and any parent should be notified of its invalidation. + * Called when a the builder or one of its nested children has changed and any parent should be + * notified of its invalidation. */ private void onChanged() { // If builder is null, this is the case where onChanged is being called diff --git a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java index 8ab0f26d9058c..78a4a21664b20 100644 --- a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java +++ b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java @@ -33,35 +33,29 @@ import static com.google.protobuf.Internal.checkNotNull; /** - * {@code SingleFieldBuilderV3} implements a structure that a protocol - * message uses to hold a single field of another protocol message. It supports - * the classical use case of setting an immutable {@link Message} as the value - * of the field and is highly optimized around this. - *
- * It also supports the additional use case of setting a {@link Message.Builder} - * as the field and deferring conversion of that {@code Builder} - * to an immutable {@code Message}. In this way, it's possible to maintain - * a tree of {@code Builder}'s that acts as a fully read/write data - * structure. + * {@code SingleFieldBuilderV3} implements a structure that a protocol message uses to hold a single + * field of another protocol message. It supports the classical use case of setting an immutable + * {@link Message} as the value of the field and is highly optimized around this. + * + *

It also supports the additional use case of setting a {@link Message.Builder} as the field and + * deferring conversion of that {@code Builder} to an immutable {@code Message}. In this way, it's + * possible to maintain a tree of {@code Builder}'s that acts as a fully read/write data structure. *
- * Logically, one can think of a tree of builders as converting the entire tree - * to messages when build is called on the root or when any method is called - * that desires a Message instead of a Builder. In terms of the implementation, - * the {@code SingleFieldBuilderV3} and {@code RepeatedFieldBuilderV3} - * classes cache messages that were created so that messages only need to be - * created when some change occurred in its builder or a builder for one of its - * descendants. + * Logically, one can think of a tree of builders as converting the entire tree to messages when + * build is called on the root or when any method is called that desires a Message instead of a + * Builder. In terms of the implementation, the {@code SingleFieldBuilderV3} and {@code + * RepeatedFieldBuilderV3} classes cache messages that were created so that messages only need to be + * created when some change occurred in its builder or a builder for one of its descendants. * * @param the type of message for the field * @param the type of builder for the field * @param the common interface for the message and the builder - * * @author jonp@google.com (Jon Perlow) */ -public class SingleFieldBuilderV3 - +public class SingleFieldBuilderV3< + MType extends AbstractMessage, + BType extends AbstractMessage.Builder, + IType extends MessageOrBuilder> implements AbstractMessage.BuilderParent { // Parent to send changes to. @@ -82,10 +76,7 @@ public class SingleFieldBuilderV3 // to dispatch dirty invalidations. See AbstractMessage.BuilderListener. private boolean isClean; - public SingleFieldBuilderV3( - MType message, - AbstractMessage.BuilderParent parent, - boolean isClean) { + public SingleFieldBuilderV3(MType message, AbstractMessage.BuilderParent parent, boolean isClean) { this.message = checkNotNull(message); this.parent = parent; this.isClean = isClean; @@ -97,10 +88,9 @@ public void dispose() { } /** - * Get the message for the field. If the message is currently stored - * as a {@code Builder}, it is converted to a {@code Message} by - * calling {@link Message.Builder#buildPartial} on it. If no message has - * been set, returns the default instance of the message. + * Get the message for the field. If the message is currently stored as a {@code Builder}, it is + * converted to a {@code Message} by calling {@link Message.Builder#buildPartial} on it. If no + * message has been set, returns the default instance of the message. * * @return the message for the field */ @@ -126,8 +116,8 @@ public MType build() { } /** - * Gets a builder for the field. If no builder has been created yet, a - * builder is created on demand by calling {@link Message#toBuilder}. + * Gets a builder for the field. If no builder has been created yet, a builder is created on + * demand by calling {@link Message#toBuilder}. * * @return The builder for the field */ @@ -146,28 +136,27 @@ public BType getBuilder() { } /** - * Gets the base class interface for the field. This may either be a builder - * or a message. It will return whatever is more efficient. + * Gets the base class interface for the field. This may either be a builder or a message. It will + * return whatever is more efficient. * * @return the message or builder for the field as the base class interface */ @SuppressWarnings("unchecked") public IType getMessageOrBuilder() { if (builder != null) { - return (IType) builder; + return (IType) builder; } else { return (IType) message; } } /** - * Sets a message for the field replacing any existing value. + * Sets a message for the field replacing any existing value. * * @param message the message to set * @return the builder */ - public SingleFieldBuilderV3 setMessage( - MType message) { + public SingleFieldBuilderV3 setMessage(MType message) { this.message = checkNotNull(message); if (builder != null) { builder.dispose(); @@ -183,8 +172,7 @@ public SingleFieldBuilderV3 setMessage( * @param value the value to merge from * @return the builder */ - public SingleFieldBuilderV3 mergeFrom( - MType value) { + public SingleFieldBuilderV3 mergeFrom(MType value) { if (builder == null && message == message.getDefaultInstanceForType()) { message = value; } else { @@ -201,9 +189,11 @@ public SingleFieldBuilderV3 mergeFrom( */ @SuppressWarnings("unchecked") public SingleFieldBuilderV3 clear() { - message = (MType) (message != null ? - message.getDefaultInstanceForType() : - builder.getDefaultInstanceForType()); + message = + (MType) + (message != null + ? message.getDefaultInstanceForType() + : builder.getDefaultInstanceForType()); if (builder != null) { builder.dispose(); builder = null; @@ -213,8 +203,8 @@ public SingleFieldBuilderV3 clear() { } /** - * Called when a the builder or one of its nested children has changed - * and any parent should be notified of its invalidation. + * Called when a the builder or one of its nested children has changed and any parent should be + * notified of its invalidation. */ private void onChanged() { // If builder is null, this is the case where onChanged is being called diff --git a/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java b/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java index 66033f58e5afb..546e56e856130 100644 --- a/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java +++ b/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java @@ -43,15 +43,14 @@ import java.util.TreeMap; /** - * A custom map implementation from FieldDescriptor to Object optimized to - * minimize the number of memory allocations for instances with a small number - * of mappings. The implementation stores the first {@code k} mappings in an - * array for a configurable value of {@code k}, allowing direct access to the - * corresponding {@code Entry}s without the need to create an Iterator. The - * remaining entries are stored in an overflow map. Iteration over the entries - * in the map should be done as follows: + * A custom map implementation from FieldDescriptor to Object optimized to minimize the number of + * memory allocations for instances with a small number of mappings. The implementation stores the + * first {@code k} mappings in an array for a configurable value of {@code k}, allowing direct + * access to the corresponding {@code Entry}s without the need to create an Iterator. The remaining + * entries are stored in an overflow map. Iteration over the entries in the map should be done as + * follows: * - *

   {@code
+ * 
{@code
  * for (int i = 0; i < fieldMap.getNumArrayEntries(); i++) {
  *   process(fieldMap.getArrayEntryAt(i));
  * }
@@ -60,24 +59,21 @@
  * }
  * }
* - * The resulting iteration is in order of ascending field tag number. The - * object returned by {@link #entrySet()} adheres to the same contract but is - * less efficient as it necessarily involves creating an object for iteration. - *

- * The tradeoff for this memory efficiency is that the worst case running time - * of the {@code put()} operation is {@code O(k + lg n)}, which happens when - * entries are added in descending order. {@code k} should be chosen such that - * it covers enough common cases without adversely affecting larger maps. In - * practice, the worst case scenario does not happen for extensions because - * extension fields are serialized and deserialized in order of ascending tag - * number, but the worst case scenario can happen for DynamicMessages. - *

- * The running time for all other operations is similar to that of - * {@code TreeMap}. - *

- * Instances are not thread-safe until {@link #makeImmutable()} is called, - * after which any modifying operation will result in an - * {@link UnsupportedOperationException}. + * The resulting iteration is in order of ascending field tag number. The object returned by {@link + * #entrySet()} adheres to the same contract but is less efficient as it necessarily involves + * creating an object for iteration. + * + *

The tradeoff for this memory efficiency is that the worst case running time of the {@code + * put()} operation is {@code O(k + lg n)}, which happens when entries are added in descending + * order. {@code k} should be chosen such that it covers enough common cases without adversely + * affecting larger maps. In practice, the worst case scenario does not happen for extensions + * because extension fields are serialized and deserialized in order of ascending tag number, but + * the worst case scenario can happen for DynamicMessages. + * + *

The running time for all other operations is similar to that of {@code TreeMap}. + * + *

Instances are not thread-safe until {@link #makeImmutable()} is called, after which any + * modifying operation will result in an {@link UnsupportedOperationException}. * * @author darick@google.com Darick Tong */ @@ -87,15 +83,14 @@ class SmallSortedMap, V> extends AbstractMap { /** - * Creates a new instance for mapping FieldDescriptors to their values. - * The {@link #makeImmutable()} implementation will convert the List values - * of any repeated fields to unmodifiable lists. + * Creates a new instance for mapping FieldDescriptors to their values. The {@link + * #makeImmutable()} implementation will convert the List values of any repeated fields to + * unmodifiable lists. * - * @param arraySize The size of the entry array containing the - * lexicographically smallest mappings. + * @param arraySize The size of the entry array containing the lexicographically smallest + * mappings. */ - static > + static > SmallSortedMap newFieldMap(int arraySize) { return new SmallSortedMap(arraySize) { @Override @@ -103,15 +98,13 @@ SmallSortedMap newFieldMap(int arraySize) { public void makeImmutable() { if (!isImmutable()) { for (int i = 0; i < getNumArrayEntries(); i++) { - final Map.Entry entry = - getArrayEntryAt(i); + final Map.Entry entry = getArrayEntryAt(i); if (entry.getKey().isRepeated()) { final List value = (List) entry.getValue(); entry.setValue(Collections.unmodifiableList(value)); } } - for (Map.Entry entry : - getOverflowEntries()) { + for (Map.Entry entry : getOverflowEntries()) { if (entry.getKey().isRepeated()) { final List value = (List) entry.getValue(); entry.setValue(Collections.unmodifiableList(value)); @@ -126,11 +119,10 @@ public void makeImmutable() { /** * Creates a new instance for testing. * - * @param arraySize The size of the entry array containing the - * lexicographically smallest mappings. + * @param arraySize The size of the entry array containing the lexicographically smallest + * mappings. */ - static , V> SmallSortedMap newInstanceForTest( - int arraySize) { + static , V> SmallSortedMap newInstanceForTest(int arraySize) { return new SmallSortedMap(arraySize); } @@ -144,16 +136,18 @@ static , V> SmallSortedMap newInstanceForTest( // The EntrySet is a stateless view of the Map. It's initialized the first // time it is requested and reused henceforth. private volatile EntrySet lazyEntrySet; + private Map overflowEntriesDescending; + private volatile DescendingEntrySet lazyDescendingEntrySet; /** - * @code arraySize Size of the array in which the lexicographically smallest - * mappings are stored. (i.e. the {@code k} referred to in the class - * documentation). + * @code arraySize Size of the array in which the lexicographically smallest mappings are stored. + * (i.e. the {@code k} referred to in the class documentation). */ private SmallSortedMap(int arraySize) { this.maxArraySize = arraySize; this.entryList = Collections.emptyList(); this.overflowEntries = Collections.emptyMap(); + this.overflowEntriesDescending = Collections.emptyMap(); } /** Make this map immutable from this point forward. */ @@ -163,9 +157,14 @@ public void makeImmutable() { // because none of the list's accessors are exposed. The iterator() of // overflowEntries, on the other hand, is exposed so it must be made // unmodifiable. - overflowEntries = overflowEntries.isEmpty() ? - Collections.emptyMap() : - Collections.unmodifiableMap(overflowEntries); + overflowEntries = + overflowEntries.isEmpty() + ? Collections.emptyMap() + : Collections.unmodifiableMap(overflowEntries); + overflowEntriesDescending = + overflowEntriesDescending.isEmpty() + ? Collections.emptyMap() + : Collections.unmodifiableMap(overflowEntriesDescending); isImmutable = true; } } @@ -192,11 +191,16 @@ public int getNumOverflowEntries() { /** @return An iterable over the overflow entries. */ public Iterable> getOverflowEntries() { - return overflowEntries.isEmpty() ? - EmptySet.>iterable() : - overflowEntries.entrySet(); + return overflowEntries.isEmpty() + ? EmptySet.>iterable() + : overflowEntries.entrySet(); } + Iterable> getOverflowEntriesDescending() { + return overflowEntriesDescending.isEmpty() + ? EmptySet.>iterable() + : overflowEntriesDescending.entrySet(); + } @Override public int size() { @@ -204,10 +208,9 @@ public int size() { } /** - * The implementation throws a {@code ClassCastException} if o is not an - * object of type {@code K}. + * The implementation throws a {@code ClassCastException} if o is not an object of type {@code K}. * - * {@inheritDoc} + *

{@inheritDoc} */ @Override public boolean containsKey(Object o) { @@ -217,10 +220,9 @@ public boolean containsKey(Object o) { } /** - * The implementation throws a {@code ClassCastException} if o is not an - * object of type {@code K}. + * The implementation throws a {@code ClassCastException} if o is not an object of type {@code K}. * - * {@inheritDoc} + *

{@inheritDoc} */ @Override public V get(Object o) { @@ -251,8 +253,7 @@ public V put(K key, V value) { if (entryList.size() == maxArraySize) { // Shift the last array entry into overflow. final Entry lastEntryInArray = entryList.remove(maxArraySize - 1); - getOverflowEntriesMutable().put(lastEntryInArray.getKey(), - lastEntryInArray.getValue()); + getOverflowEntriesMutable().put(lastEntryInArray.getKey(), lastEntryInArray.getValue()); } entryList.add(insertionPoint, new Entry(key, value)); return null; @@ -270,10 +271,9 @@ public void clear() { } /** - * The implementation throws a {@code ClassCastException} if o is not an - * object of type {@code K}. + * The implementation throws a {@code ClassCastException} if o is not an object of type {@code K}. * - * {@inheritDoc} + *

{@inheritDoc} */ @Override public V remove(Object o) { @@ -299,8 +299,7 @@ private V removeArrayEntryAt(int index) { if (!overflowEntries.isEmpty()) { // Shift the first entry in the overflow to be the last entry in the // array. - final Iterator> iterator = - getOverflowEntriesMutable().entrySet().iterator(); + final Iterator> iterator = getOverflowEntriesMutable().entrySet().iterator(); entryList.add(new Entry(iterator.next())); iterator.remove(); } @@ -309,8 +308,8 @@ private V removeArrayEntryAt(int index) { /** * @param key The key to find in the entry array. - * @return The returned integer position follows the same semantics as the - * value returned by {@link java.util.Arrays#binarySearch()}. + * @return The returned integer position follows the same semantics as the value returned by + * {@link java.util.Arrays#binarySearch()}. */ private int binarySearchInArray(K key) { int left = 0; @@ -322,7 +321,7 @@ private int binarySearchInArray(K key) { if (right >= 0) { int cmp = key.compareTo(entryList.get(right).getKey()); if (cmp > 0) { - return -(right + 2); // Insert point is after "right". + return -(right + 2); // Insert point is after "right". } else if (cmp == 0) { return right; } @@ -343,11 +342,11 @@ private int binarySearchInArray(K key) { } /** - * Similar to the AbstractMap implementation of {@code keySet()} and - * {@code values()}, the entry set is created the first time this method is - * called, and returned in response to all subsequent calls. + * Similar to the AbstractMap implementation of {@code keySet()} and {@code values()}, the entry + * set is created the first time this method is called, and returned in response to all subsequent + * calls. * - * {@inheritDoc} + *

{@inheritDoc} */ @Override public Set> entrySet() { @@ -357,11 +356,14 @@ public Set> entrySet() { return lazyEntrySet; } + Set> descendingEntrySet() { + if (lazyDescendingEntrySet == null) { + lazyDescendingEntrySet = new DescendingEntrySet(); + } + return lazyDescendingEntrySet; + } - /** - * @throws UnsupportedOperationException if {@link #makeImmutable()} has - * has been called. - */ + /** @throws UnsupportedOperationException if {@link #makeImmutable()} has has been called. */ private void checkMutable() { if (isImmutable) { throw new UnsupportedOperationException(); @@ -369,24 +371,20 @@ private void checkMutable() { } /** - * @return a {@link SortedMap} to which overflow entries mappings can be - * added or removed. - * @throws UnsupportedOperationException if {@link #makeImmutable()} has been - * called. + * @return a {@link SortedMap} to which overflow entries mappings can be added or removed. + * @throws UnsupportedOperationException if {@link #makeImmutable()} has been called. */ @SuppressWarnings("unchecked") private SortedMap getOverflowEntriesMutable() { checkMutable(); if (overflowEntries.isEmpty() && !(overflowEntries instanceof TreeMap)) { overflowEntries = new TreeMap(); + overflowEntriesDescending = ((TreeMap) overflowEntries).descendingMap(); } return (SortedMap) overflowEntries; } - /** - * Lazily creates the entry list. Any code that adds to the list must first - * call this method. - */ + /** Lazily creates the entry list. Any code that adds to the list must first call this method. */ private void ensureEntryArrayMutable() { checkMutable(); if (entryList.isEmpty() && !(entryList instanceof ArrayList)) { @@ -395,9 +393,8 @@ private void ensureEntryArrayMutable() { } /** - * Entry implementation that implements Comparable in order to support - * binary search within the entry array. Also checks mutability in - * {@link #setValue()}. + * Entry implementation that implements Comparable in order to support binary search within the + * entry array. Also checks mutability in {@link #setValue()}. */ private class Entry implements Map.Entry, Comparable { @@ -451,8 +448,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return (key == null ? 0 : key.hashCode()) ^ - (value == null ? 0 : value.hashCode()); + return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()); } @Override @@ -466,9 +462,7 @@ private boolean equals(Object o1, Object o2) { } } - /** - * Stateless view of the entries in the field map. - */ + /** Stateless view of the entries in the field map. */ private class EntrySet extends AbstractSet> { @Override @@ -484,7 +478,7 @@ public int size() { /** * Throws a {@link ClassCastException} if o is not of the expected type. * - * {@inheritDoc} + *

{@inheritDoc} */ @Override public boolean contains(Object o) { @@ -492,8 +486,7 @@ public boolean contains(Object o) { final Map.Entry entry = (Map.Entry) o; final V existing = get(entry.getKey()); final V value = entry.getValue(); - return existing == value || - (existing != null && existing.equals(value)); + return existing == value || (existing != null && existing.equals(value)); } @Override @@ -508,7 +501,7 @@ public boolean add(Map.Entry entry) { /** * Throws a {@link ClassCastException} if o is not of the expected type. * - * {@inheritDoc} + *

{@inheritDoc} */ @Override public boolean remove(Object o) { @@ -527,10 +520,16 @@ public void clear() { } } + private class DescendingEntrySet extends EntrySet { + @Override + public Iterator> iterator() { + return new DescendingEntryIterator(); + } + } /** - * Iterator implementation that switches from the entry array to the overflow - * entries appropriately. + * Iterator implementation that switches from the entry array to the overflow entries + * appropriately. */ private class EntryIterator implements Iterator> { @@ -540,8 +539,8 @@ private class EntryIterator implements Iterator> { @Override public boolean hasNext() { - return (pos + 1) < entryList.size() || - getOverflowIterator().hasNext(); + return (pos + 1) < entryList.size() + || (!overflowEntries.isEmpty() && getOverflowIterator().hasNext()); } @Override @@ -571,10 +570,9 @@ public void remove() { } /** - * It is important to create the overflow iterator only after the array - * entries have been iterated over because the overflow entry set changes - * when the client calls remove() on the array entries, which invalidates - * any existing iterators. + * It is important to create the overflow iterator only after the array entries have been + * iterated over because the overflow entry set changes when the client calls remove() on the + * array entries, which invalidates any existing iterators. */ private Iterator> getOverflowIterator() { if (lazyOverflowIterator == null) { @@ -585,9 +583,49 @@ private Iterator> getOverflowIterator() { } /** - * Helper class that holds immutable instances of an Iterable/Iterator that - * we return when the overflow entries is empty. This eliminates the creation - * of an Iterator object when there is nothing to iterate over. + * Reverse Iterator implementation that switches from the entry array to the overflow entries + * appropriately. + */ + private class DescendingEntryIterator implements Iterator> { + + private int pos = entryList.size(); + private Iterator> lazyOverflowIterator; + + @Override + public boolean hasNext() { + return (pos > 0 && pos <= entryList.size()) || getOverflowIterator().hasNext(); + } + + @Override + public Map.Entry next() { + if (getOverflowIterator().hasNext()) { + return getOverflowIterator().next(); + } + return entryList.get(--pos); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + /** + * It is important to create the overflow iterator only after the array entries have been + * iterated over because the overflow entry set changes when the client calls remove() on the + * array entries, which invalidates any existing iterators. + */ + private Iterator> getOverflowIterator() { + if (lazyOverflowIterator == null) { + lazyOverflowIterator = overflowEntriesDescending.entrySet().iterator(); + } + return lazyOverflowIterator; + } + } + + /** + * Helper class that holds immutable instances of an Iterable/Iterator that we return when the + * overflow entries is empty. This eliminates the creation of an Iterator object when there is + * nothing to iterate over. */ private static class EmptySet { @@ -597,10 +635,12 @@ private static class EmptySet { public boolean hasNext() { return false; } + @Override public Object next() { throw new NoSuchElementException(); } + @Override public void remove() { throw new UnsupportedOperationException(); @@ -653,7 +693,6 @@ public boolean equals(Object o) { return overflowEntries.equals(other.overflowEntries); } - return true; } diff --git a/java/core/src/main/java/com/google/protobuf/StructuralMessageInfo.java b/java/core/src/main/java/com/google/protobuf/StructuralMessageInfo.java new file mode 100644 index 0000000000000..a32b1430ee115 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/StructuralMessageInfo.java @@ -0,0 +1,167 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.Internal.checkNotNull; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Information for the layout of a protobuf message class. This describes all of the fields + * contained within a message. + */ +@ExperimentalApi +final class StructuralMessageInfo implements MessageInfo { + private final ProtoSyntax syntax; + private final boolean messageSetWireFormat; + private final int[] checkInitialized; + private final FieldInfo[] fields; + private final MessageLite defaultInstance; + + /** + * Constructor. + * + * @param checkInitialized fields to check in isInitialized(). + * @param fields the set of fields for the message, in field number order. + */ + StructuralMessageInfo( + ProtoSyntax syntax, + boolean messageSetWireFormat, + int[] checkInitialized, + FieldInfo[] fields, + Object defaultInstance) { + this.syntax = syntax; + this.messageSetWireFormat = messageSetWireFormat; + this.checkInitialized = checkInitialized; + this.fields = fields; + this.defaultInstance = (MessageLite) checkNotNull(defaultInstance, "defaultInstance"); + } + + /** Gets the syntax for the message (e.g. PROTO2, PROTO3). */ + @Override + public ProtoSyntax getSyntax() { + return syntax; + } + + /** Indicates whether or not the message should be represented with message set wire format. */ + @Override + public boolean isMessageSetWireFormat() { + return messageSetWireFormat; + } + + /** An array of field numbers that need to be checked for isInitialized(). */ + public int[] getCheckInitialized() { + return checkInitialized; + } + + /** + * Gets the information for all fields within this message, sorted in ascending order by their + * field number. + */ + public FieldInfo[] getFields() { + return fields; + } + + @Override + public MessageLite getDefaultInstance() { + return defaultInstance; + } + + /** Helper method for creating a new builder for {@link MessageInfo}. */ + public static Builder newBuilder() { + return new Builder(); + } + + /** Helper method for creating a new builder for {@link MessageInfo}. */ + public static Builder newBuilder(int numFields) { + return new Builder(numFields); + } + + /** A builder of {@link MessageInfo} instances. */ + public static final class Builder { + private final List fields; + private ProtoSyntax syntax; + private boolean wasBuilt; + private boolean messageSetWireFormat; + private int[] checkInitialized = null; + private Object defaultInstance; + + public Builder() { + fields = new ArrayList(); + } + + public Builder(int numFields) { + fields = new ArrayList(numFields); + } + + public void withDefaultInstance(Object defaultInstance) { + this.defaultInstance = defaultInstance; + } + + public void withSyntax(ProtoSyntax syntax) { + this.syntax = checkNotNull(syntax, "syntax"); + } + + public void withMessageSetWireFormat(boolean messageSetWireFormat) { + this.messageSetWireFormat = messageSetWireFormat; + } + + public void withCheckInitialized(int[] checkInitialized) { + this.checkInitialized = checkInitialized; + } + + public void withField(FieldInfo field) { + if (wasBuilt) { + throw new IllegalStateException("Builder can only build once"); + } + fields.add(field); + } + + public StructuralMessageInfo build() { + if (wasBuilt) { + throw new IllegalStateException("Builder can only build once"); + } + if (syntax == null) { + throw new IllegalStateException("Must specify a proto syntax"); + } + wasBuilt = true; + Collections.sort(fields); + return new StructuralMessageInfo( + syntax, + messageSetWireFormat, + checkInitialized, + fields.toArray(new FieldInfo[0]), + defaultInstance); + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/TextFormat.java b/java/core/src/main/java/com/google/protobuf/TextFormat.java index 64094d0918e26..e781df333d10f 100644 --- a/java/core/src/main/java/com/google/protobuf/TextFormat.java +++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java @@ -30,14 +30,18 @@ package com.google.protobuf; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.MessageReflection.MergeTarget; import java.io.IOException; import java.math.BigInteger; import java.nio.CharBuffer; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; @@ -46,8 +50,8 @@ import java.util.regex.Pattern; /** - * Provide text parsing and formatting support for proto2 instances. - * The implementation largely follows google/protobuf/text_format.cc. + * Provide text parsing and formatting support for proto2 instances. The implementation largely + * follows google/protobuf/text_format.cc. * * @author wenboz@google.com Wenbo Zhu * @author kenton@google.com Kenton Varda @@ -57,193 +61,175 @@ private TextFormat() {} private static final Logger logger = Logger.getLogger(TextFormat.class.getName()); + /** - * Outputs a textual representation of the Protocol Message supplied into - * the parameter output. (This representation is the new version of the - * classic "ProtocolPrinter" output from the original Protocol Buffer system) + * Outputs a textual representation of the Protocol Message supplied into the parameter output. + * (This representation is the new version of the classic "ProtocolPrinter" output from the + * original Protocol Buffer system) + * + * @deprecated Use {@code printer().print(MessageOrBuilder, Appendable)} */ - public static void print( - final MessageOrBuilder message, final Appendable output) + @Deprecated + public static void print(final MessageOrBuilder message, final Appendable output) throws IOException { - Printer.DEFAULT.print(message, multiLineOutput(output)); + printer().print(message, output); } - /** Outputs a textual representation of {@code fields} to {@code output}. */ - public static void print(final UnknownFieldSet fields, - final Appendable output) - throws IOException { - Printer.DEFAULT.printUnknownFields(fields, multiLineOutput(output)); + /** + * Outputs a textual representation of {@code fields} to {@code output}. + * + * @deprecated Use {@code printer().print(UnknownFieldSet, Appendable)} + */ + @Deprecated + public static void print(final UnknownFieldSet fields, final Appendable output) + throws IOException { + printer().print(fields, output); } /** - * Same as {@code print()}, except that non-ASCII characters are not - * escaped. + * Same as {@code print()}, except that non-ASCII characters are not escaped. + * + * @deprecated Use {@code printer().escapingNonAscii(false).print(MessageOrBuilder, Appendable)} */ - public static void printUnicode( - final MessageOrBuilder message, final Appendable output) + @Deprecated + public static void printUnicode(final MessageOrBuilder message, final Appendable output) throws IOException { - Printer.UNICODE.print(message, multiLineOutput(output)); + printer().escapingNonAscii(false).print(message, output); } /** - * Same as {@code print()}, except that non-ASCII characters are not - * escaped. + * Same as {@code print()}, except that non-ASCII characters are not escaped. + * + * @deprecated Use {@code printer().escapingNonAscii(false).print(UnknownFieldSet, Appendable)} */ - public static void printUnicode(final UnknownFieldSet fields, - final Appendable output) - throws IOException { - Printer.UNICODE.printUnknownFields(fields, multiLineOutput(output)); + @Deprecated + public static void printUnicode(final UnknownFieldSet fields, final Appendable output) + throws IOException { + printer().escapingNonAscii(false).print(fields, output); } /** - * Generates a human readable form of this message, useful for debugging and - * other purposes, with no newline characters. + * Generates a human readable form of this message, useful for debugging and other purposes, with + * no newline characters. This is just a trivial wrapper around + * {@link TextFormat.Printer#shortDebugString(MessageOrBuilder)}. */ public static String shortDebugString(final MessageOrBuilder message) { - try { - final StringBuilder text = new StringBuilder(); - Printer.DEFAULT.print(message, singleLineOutput(text)); - return text.toString(); - } catch (IOException e) { - throw new IllegalStateException(e); - } + return printer().shortDebugString(message); } /** - * Generates a human readable form of the field, useful for debugging - * and other purposes, with no newline characters. + * Generates a human readable form of the field, useful for debugging and other purposes, with + * no newline characters. + * + * @deprecated Use {@code printer().shortDebugString(FieldDescriptor, Object)} */ - public static String shortDebugString(final FieldDescriptor field, - final Object value) { - try { - final StringBuilder text = new StringBuilder(); - Printer.DEFAULT.printField(field, value, singleLineOutput(text)); - return text.toString(); - } catch (IOException e) { - throw new IllegalStateException(e); - } + @Deprecated + public static String shortDebugString(final FieldDescriptor field, final Object value) { + return printer().shortDebugString(field, value); } - + // /** - * Generates a human readable form of the unknown fields, useful for debugging - * and other purposes, with no newline characters. + * Generates a human readable form of the unknown fields, useful for debugging and other + * purposes, with no newline characters. + * + * @deprecated Use {@code printer().shortDebugString(UnknownFieldSet)} */ + @Deprecated public static String shortDebugString(final UnknownFieldSet fields) { - try { - final StringBuilder text = new StringBuilder(); - Printer.DEFAULT.printUnknownFields(fields, singleLineOutput(text)); - return text.toString(); - } catch (IOException e) { - throw new IllegalStateException(e); - } + return printer().shortDebugString(fields); } /** - * Like {@code print()}, but writes directly to a {@code String} and - * returns it. + * Like {@code print()}, but writes directly to a {@code String} and returns it. + * + * @deprecated Use {@code message.toString()} */ + @Deprecated public static String printToString(final MessageOrBuilder message) { - try { - final StringBuilder text = new StringBuilder(); - print(message, text); - return text.toString(); - } catch (IOException e) { - throw new IllegalStateException(e); - } + return printer().printToString(message); } /** - * Like {@code print()}, but writes directly to a {@code String} and - * returns it. + * Like {@code print()}, but writes directly to a {@code String} and returns it. + * + * @deprecated Use {@link UnknownFieldSet#toString()} */ + @Deprecated public static String printToString(final UnknownFieldSet fields) { - try { - final StringBuilder text = new StringBuilder(); - print(fields, text); - return text.toString(); - } catch (IOException e) { - throw new IllegalStateException(e); - } + return printer().printToString(fields); } /** - * Same as {@code printToString()}, except that non-ASCII characters - * in string type fields are not escaped in backslash+octals. + * Same as {@code printToString()}, except that non-ASCII characters in string type fields are not + * escaped in backslash+octals. + * + * @deprecated Use {@code printer().escapingNonAscii(false).printToString(MessageOrBuilder)} */ + @Deprecated public static String printToUnicodeString(final MessageOrBuilder message) { - try { - final StringBuilder text = new StringBuilder(); - Printer.UNICODE.print(message, multiLineOutput(text)); - return text.toString(); - } catch (IOException e) { - throw new IllegalStateException(e); - } + return printer().escapingNonAscii(false).printToString(message); } /** - * Same as {@code printToString()}, except that non-ASCII characters - * in string type fields are not escaped in backslash+octals. + * Same as {@code printToString()}, except that non-ASCII characters in string type fields are + * not escaped in backslash+octals. + * + * @deprecated Use {@code printer().escapingNonAscii(false).printToString(UnknownFieldSet)} */ + @Deprecated public static String printToUnicodeString(final UnknownFieldSet fields) { - try { - final StringBuilder text = new StringBuilder(); - Printer.UNICODE.printUnknownFields(fields, multiLineOutput(text)); - return text.toString(); - } catch (IOException e) { - throw new IllegalStateException(e); - } + return printer().escapingNonAscii(false).printToString(fields); } - - public static void printField(final FieldDescriptor field, - final Object value, - final Appendable output) - throws IOException { - Printer.DEFAULT.printField(field, value, multiLineOutput(output)); + // + /** @deprecated Use {@code printer().printField(FieldDescriptor, Object, Appendable)} */ + @Deprecated + public static void printField( + final FieldDescriptor field, final Object value, final Appendable output) + throws IOException { + printer().printField(field, value, output); } - - public static String printFieldToString(final FieldDescriptor field, - final Object value) { - try { - final StringBuilder text = new StringBuilder(); - printField(field, value, text); - return text.toString(); - } catch (IOException e) { - throw new IllegalStateException(e); - } + // + /** @deprecated Use {@code printer().printFieldToString(FieldDescriptor, Object)} */ + @Deprecated + public static String printFieldToString(final FieldDescriptor field, final Object value) { + return printer().printFieldToString(field, value); } - + // /** * Outputs a unicode textual representation of the value of given field value. * *

Same as {@code printFieldValue()}, except that non-ASCII characters in string type fields * are not escaped in backslash+octals. * + * @deprecated Use {@code printer().escapingNonAscii(false).printFieldValue(FieldDescriptor, + * Object, Appendable)} * @param field the descriptor of the field * @param value the value of the field * @param output the output to which to append the formatted value * @throws ClassCastException if the value is not appropriate for the given field descriptor * @throws IOException if there is an exception writing to the output */ + @Deprecated public static void printUnicodeFieldValue( - final FieldDescriptor field, final Object value, final Appendable output) throws IOException { - Printer.UNICODE.printFieldValue(field, value, multiLineOutput(output)); + final FieldDescriptor field, final Object value, final Appendable output) + throws IOException { + printer().escapingNonAscii(false).printFieldValue(field, value, output); } /** * Outputs a textual representation of the value of given field value. * + * @deprecated Use {@code printer().printFieldValue(FieldDescriptor, Object, Appendable)} * @param field the descriptor of the field * @param value the value of the field * @param output the output to which to append the formatted value - * @throws ClassCastException if the value is not appropriate for the - * given field descriptor + * @throws ClassCastException if the value is not appropriate for the given field descriptor * @throws IOException if there is an exception writing to the output */ - public static void printFieldValue(final FieldDescriptor field, - final Object value, - final Appendable output) - throws IOException { - Printer.DEFAULT.printFieldValue(field, value, multiLineOutput(output)); + @Deprecated + public static void printFieldValue( + final FieldDescriptor field, final Object value, final Appendable output) throws IOException { + printer().printFieldValue(field, value, output); } /** @@ -252,72 +238,203 @@ public static void printFieldValue(final FieldDescriptor field, * @param tag the field's tag number * @param value the value of the field * @param output the output to which to append the formatted value - * @throws ClassCastException if the value is not appropriate for the - * given field descriptor + * @throws ClassCastException if the value is not appropriate for the given field descriptor * @throws IOException if there is an exception writing to the output */ - public static void printUnknownFieldValue(final int tag, - final Object value, - final Appendable output) - throws IOException { + public static void printUnknownFieldValue( + final int tag, final Object value, final Appendable output) throws IOException { printUnknownFieldValue(tag, value, multiLineOutput(output)); } - private static void printUnknownFieldValue(final int tag, - final Object value, - final TextGenerator generator) - throws IOException { + private static void printUnknownFieldValue( + final int tag, final Object value, final TextGenerator generator) throws IOException { switch (WireFormat.getTagWireType(tag)) { case WireFormat.WIRETYPE_VARINT: generator.print(unsignedToString((Long) value)); break; case WireFormat.WIRETYPE_FIXED32: - generator.print( - String.format((Locale) null, "0x%08x", (Integer) value)); + generator.print(String.format((Locale) null, "0x%08x", (Integer) value)); break; case WireFormat.WIRETYPE_FIXED64: generator.print(String.format((Locale) null, "0x%016x", (Long) value)); break; case WireFormat.WIRETYPE_LENGTH_DELIMITED: - generator.print("\""); - generator.print(escapeBytes((ByteString) value)); - generator.print("\""); + try { + // Try to parse and print the field as an embedded message + UnknownFieldSet message = UnknownFieldSet.parseFrom((ByteString) value); + generator.print("{"); + generator.eol(); + generator.indent(); + Printer.printUnknownFields(message, generator); + generator.outdent(); + generator.print("}"); + } catch (InvalidProtocolBufferException e) { + // If not parseable as a message, print as a String + generator.print("\""); + generator.print(escapeBytes((ByteString) value)); + generator.print("\""); + } break; case WireFormat.WIRETYPE_START_GROUP: - Printer.DEFAULT.printUnknownFields((UnknownFieldSet) value, generator); + Printer.printUnknownFields((UnknownFieldSet) value, generator); break; default: throw new IllegalArgumentException("Bad tag: " + tag); } } + /** Printer instance which escapes non-ASCII characters. */ + public static Printer printer() { + return Printer.DEFAULT; + } + /** Helper class for converting protobufs to text. */ - private static final class Printer { + public static final class Printer { + // Printer instance which escapes non-ASCII characters. - static final Printer DEFAULT = new Printer(true); - // Printer instance which emits Unicode (it still escapes newlines and quotes in strings). - static final Printer UNICODE = new Printer(false); + private static final Printer DEFAULT = new Printer(true, TypeRegistry.getEmptyTypeRegistry()); /** Whether to escape non ASCII characters with backslash and octal. */ private final boolean escapeNonAscii; - private Printer(boolean escapeNonAscii) { + private final TypeRegistry typeRegistry; + + private Printer(boolean escapeNonAscii, TypeRegistry typeRegistry) { this.escapeNonAscii = escapeNonAscii; + this.typeRegistry = typeRegistry; + } + + /** + * Return a new Printer instance with the specified escape mode. + * + * @param escapeNonAscii If true, the new Printer will escape non-ASCII characters (this is the + * default behavior. If false, the new Printer will print non-ASCII characters as is. In + * either case, the new Printer still escapes newlines and quotes in strings. + * @return a new Printer that clones all other configurations from the current {@link Printer}, + * with the escape mode set to the given parameter. + */ + public Printer escapingNonAscii(boolean escapeNonAscii) { + return new Printer(escapeNonAscii, typeRegistry); + } + + /** + * Creates a new {@link Printer} using the given typeRegistry. The new Printer clones all other + * configurations from the current {@link Printer}. + * + * @throws IllegalArgumentException if a registry is already set. + */ + public Printer usingTypeRegistry(TypeRegistry typeRegistry) { + if (this.typeRegistry != TypeRegistry.getEmptyTypeRegistry()) { + throw new IllegalArgumentException("Only one typeRegistry is allowed."); + } + return new Printer(escapeNonAscii, typeRegistry); } - private void print( - final MessageOrBuilder message, final TextGenerator generator) + /** + * Outputs a textual representation of the Protocol Message supplied into the parameter output. + * (This representation is the new version of the classic "ProtocolPrinter" output from the + * original Protocol Buffer system) + */ + public void print(final MessageOrBuilder message, final Appendable output) throws IOException { + print(message, multiLineOutput(output)); + } + + /** Outputs a textual representation of {@code fields} to {@code output}. */ + public void print(final UnknownFieldSet fields, final Appendable output) throws IOException { + printUnknownFields(fields, multiLineOutput(output)); + } + + private void print(final MessageOrBuilder message, final TextGenerator generator) throws IOException { - for (Map.Entry field - : message.getAllFields().entrySet()) { - printField(field.getKey(), field.getValue(), generator); + if (message.getDescriptorForType().getFullName().equals("google.protobuf.Any") + && printAny(message, generator)) { + return; } - printUnknownFields(message.getUnknownFields(), generator); + printMessage(message, generator); } - private void printField(final FieldDescriptor field, final Object value, - final TextGenerator generator) throws IOException { - if (field.isRepeated()) { + /** + * Attempt to print the 'google.protobuf.Any' message in a human-friendly format. Returns false + * if the message isn't a valid 'google.protobuf.Any' message (in which case the message should + * be rendered just like a regular message to help debugging). + */ + private boolean printAny(final MessageOrBuilder message, final TextGenerator generator) + throws IOException { + Descriptor messageType = message.getDescriptorForType(); + FieldDescriptor typeUrlField = messageType.findFieldByNumber(1); + FieldDescriptor valueField = messageType.findFieldByNumber(2); + if (typeUrlField == null + || typeUrlField.getType() != FieldDescriptor.Type.STRING + || valueField == null + || valueField.getType() != FieldDescriptor.Type.BYTES) { + // The message may look like an Any but isn't actually an Any message (might happen if the + // user tries to use DynamicMessage to construct an Any from incomplete Descriptor). + return false; + } + String typeUrl = (String) message.getField(typeUrlField); + // If type_url is not set, we will not be able to decode the content of the value, so just + // print out the Any like a regular message. + if (typeUrl.isEmpty()) { + return false; + } + Object value = message.getField(valueField); + + Message.Builder contentBuilder = null; + try { + Descriptor contentType = typeRegistry.getDescriptorForTypeUrl(typeUrl); + if (contentType == null) { + return false; + } + contentBuilder = DynamicMessage.getDefaultInstance(contentType).newBuilderForType(); + contentBuilder.mergeFrom((ByteString) value); + } catch (InvalidProtocolBufferException e) { + // The value of Any is malformed. We cannot print it out nicely, so fallback to printing out + // the type_url and value as bytes. Note that we fail open here to be consistent with + // text_format.cc, and also to allow a way for users to inspect the content of the broken + // message. + return false; + } + generator.print("["); + generator.print(typeUrl); + generator.print("] {"); + generator.eol(); + generator.indent(); + print(contentBuilder, generator); + generator.outdent(); + generator.print("}"); + generator.eol(); + return true; + } + + public String printFieldToString(final FieldDescriptor field, final Object value) { + try { + final StringBuilder text = new StringBuilder(); + printField(field, value, text); + return text.toString(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public void printField(final FieldDescriptor field, final Object value, final Appendable output) + throws IOException { + printField(field, value, multiLineOutput(output)); + } + + private void printField( + final FieldDescriptor field, final Object value, final TextGenerator generator) + throws IOException { + // Sort map field entries by key + if (field.isMapField()) { + List adapters = new ArrayList<>(); + for (Object entry : (List) value) { + adapters.add(new MapEntryAdapter(entry, field)); + } + Collections.sort(adapters); + for (MapEntryAdapter adapter : adapters) { + printSingleField(field, adapter.getEntry(), generator); + } + } else if (field.isRepeated()) { // Repeated field. Print each element. for (Object element : (List) value) { printSingleField(field, element, generator); @@ -327,53 +444,96 @@ private void printField(final FieldDescriptor field, final Object value, } } - private void printSingleField(final FieldDescriptor field, - final Object value, - final TextGenerator generator) - throws IOException { - if (field.isExtension()) { - generator.print("["); - // We special-case MessageSet elements for compatibility with proto1. - if (field.getContainingType().getOptions().getMessageSetWireFormat() - && (field.getType() == FieldDescriptor.Type.MESSAGE) - && (field.isOptional()) - // object equality - && (field.getExtensionScope() == field.getMessageType())) { - generator.print(field.getMessageType().getFullName()); - } else { - generator.print(field.getFullName()); - } - generator.print("]"); - } else { - if (field.getType() == FieldDescriptor.Type.GROUP) { - // Groups must be serialized with their original capitalization. - generator.print(field.getMessageType().getName()); + /** + * An adapter class that can take a MapEntry or a MutableMapEntry and returns its key and entry. + * This class is created solely for the purpose of sorting map entries by its key and prevent + * duplicated logic by having a separate comparator for MapEntry and MutableMapEntry. + */ + private static class MapEntryAdapter implements Comparable { + private Object entry; + + @SuppressWarnings({"rawtypes"}) + private MapEntry mapEntry; + + + private final FieldDescriptor.JavaType fieldType; + + public MapEntryAdapter(Object entry, FieldDescriptor fieldDescriptor) { + if (entry instanceof MapEntry) { + this.mapEntry = (MapEntry) entry; } else { - generator.print(field.getName()); + this.entry = entry; } + this.fieldType = extractFieldType(fieldDescriptor); } - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - generator.print(" {"); - generator.eol(); - generator.indent(); - } else { - generator.print(": "); + private static FieldDescriptor.JavaType extractFieldType(FieldDescriptor fieldDescriptor) { + return fieldDescriptor.getMessageType().getFields().get(0).getJavaType(); } - printFieldValue(field, value, generator); + public Object getKey() { + if (mapEntry != null) { + return mapEntry.getKey(); + } + return null; + } - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - generator.outdent(); - generator.print("}"); + public Object getEntry() { + if (mapEntry != null) { + return mapEntry; + } + return entry; + } + + @Override + public int compareTo(MapEntryAdapter b) { + if (getKey() == null || b.getKey() == null) { + logger.info("Invalid key for map field."); + return -1; + } + switch (fieldType) { + case BOOLEAN: + return Boolean.compare((boolean) getKey(), (boolean) b.getKey()); + case LONG: + return Long.compare((long) getKey(), (long) b.getKey()); + case INT: + return Integer.compare((int) getKey(), (int) b.getKey()); + case STRING: + String aString = (String) getKey(); + String bString = (String) b.getKey(); + if (aString == null && bString == null) { + return 0; + } else if (aString == null && bString != null) { + return -1; + } else if (aString != null && bString == null) { + return 1; + } else { + return aString.compareTo(bString); + } + default: + return 0; + } } - generator.eol(); } - private void printFieldValue(final FieldDescriptor field, - final Object value, - final TextGenerator generator) - throws IOException { + /** + * Outputs a textual representation of the value of given field value. + * + * @param field the descriptor of the field + * @param value the value of the field + * @param output the output to which to append the formatted value + * @throws ClassCastException if the value is not appropriate for the given field descriptor + * @throws IOException if there is an exception writing to the output + */ + public void printFieldValue( + final FieldDescriptor field, final Object value, final Appendable output) + throws IOException { + printFieldValue(field, value, multiLineOutput(output)); + } + + private void printFieldValue( + final FieldDescriptor field, final Object value, final TextGenerator generator) + throws IOException { switch (field.getType()) { case INT32: case SINT32: @@ -411,10 +571,10 @@ private void printFieldValue(final FieldDescriptor field, case STRING: generator.print("\""); - generator.print(escapeNonAscii - ? TextFormatEscaper.escapeText((String) value) - : escapeDoubleQuotesAndBackslashes((String) value) - .replace("\n", "\\n")); + generator.print( + escapeNonAscii + ? TextFormatEscaper.escapeText((String) value) + : escapeDoubleQuotesAndBackslashes((String) value).replace("\n", "\\n")); generator.print("\""); break; @@ -439,21 +599,169 @@ private void printFieldValue(final FieldDescriptor field, } } - private void printUnknownFields(final UnknownFieldSet unknownFields, - final TextGenerator generator) - throws IOException { - for (Map.Entry entry : - unknownFields.asMap().entrySet()) { + /** Like {@code print()}, but writes directly to a {@code String} and returns it. */ + public String printToString(final MessageOrBuilder message) { + try { + final StringBuilder text = new StringBuilder(); + print(message, text); + return text.toString(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + /** Like {@code print()}, but writes directly to a {@code String} and returns it. */ + public String printToString(final UnknownFieldSet fields) { + try { + final StringBuilder text = new StringBuilder(); + print(fields, text); + return text.toString(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + /** + * Generates a human readable form of this message, useful for debugging and other purposes, + * with no newline characters. + */ + public String shortDebugString(final MessageOrBuilder message) { + try { + final StringBuilder text = new StringBuilder(); + print(message, singleLineOutput(text)); + return text.toString(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + /** + * Generates a human readable form of the field, useful for debugging and other purposes, with + * no newline characters. + */ + public String shortDebugString(final FieldDescriptor field, final Object value) { + try { + final StringBuilder text = new StringBuilder(); + printField(field, value, singleLineOutput(text)); + return text.toString(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + /** + * Generates a human readable form of the unknown fields, useful for debugging and other + * purposes, with no newline characters. + */ + public String shortDebugString(final UnknownFieldSet fields) { + try { + final StringBuilder text = new StringBuilder(); + printUnknownFields(fields, singleLineOutput(text)); + return text.toString(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + private static void printUnknownFieldValue( + final int tag, final Object value, final TextGenerator generator) throws IOException { + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + generator.print(unsignedToString((Long) value)); + break; + case WireFormat.WIRETYPE_FIXED32: + generator.print(String.format((Locale) null, "0x%08x", (Integer) value)); + break; + case WireFormat.WIRETYPE_FIXED64: + generator.print(String.format((Locale) null, "0x%016x", (Long) value)); + break; + case WireFormat.WIRETYPE_LENGTH_DELIMITED: + try { + // Try to parse and print the field as an embedded message + UnknownFieldSet message = UnknownFieldSet.parseFrom((ByteString) value); + generator.print("{"); + generator.eol(); + generator.indent(); + printUnknownFields(message, generator); + generator.outdent(); + generator.print("}"); + } catch (InvalidProtocolBufferException e) { + // If not parseable as a message, print as a String + generator.print("\""); + generator.print(escapeBytes((ByteString) value)); + generator.print("\""); + } + break; + case WireFormat.WIRETYPE_START_GROUP: + printUnknownFields((UnknownFieldSet) value, generator); + break; + default: + throw new IllegalArgumentException("Bad tag: " + tag); + } + } + + private void printMessage(final MessageOrBuilder message, final TextGenerator generator) + throws IOException { + for (Map.Entry field : message.getAllFields().entrySet()) { + printField(field.getKey(), field.getValue(), generator); + } + printUnknownFields(message.getUnknownFields(), generator); + } + + private void printSingleField( + final FieldDescriptor field, final Object value, final TextGenerator generator) + throws IOException { + if (field.isExtension()) { + generator.print("["); + // We special-case MessageSet elements for compatibility with proto1. + if (field.getContainingType().getOptions().getMessageSetWireFormat() + && (field.getType() == FieldDescriptor.Type.MESSAGE) + && (field.isOptional()) + // object equality + && (field.getExtensionScope() == field.getMessageType())) { + generator.print(field.getMessageType().getFullName()); + } else { + generator.print(field.getFullName()); + } + generator.print("]"); + } else { + if (field.getType() == FieldDescriptor.Type.GROUP) { + // Groups must be serialized with their original capitalization. + generator.print(field.getMessageType().getName()); + } else { + generator.print(field.getName()); + } + } + + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + generator.print(" {"); + generator.eol(); + generator.indent(); + } else { + generator.print(": "); + } + + printFieldValue(field, value, generator); + + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + generator.outdent(); + generator.print("}"); + } + generator.eol(); + } + + private static void printUnknownFields( + final UnknownFieldSet unknownFields, final TextGenerator generator) throws IOException { + for (Map.Entry entry : unknownFields.asMap().entrySet()) { final int number = entry.getKey(); final UnknownFieldSet.Field field = entry.getValue(); - printUnknownField(number, WireFormat.WIRETYPE_VARINT, - field.getVarintList(), generator); - printUnknownField(number, WireFormat.WIRETYPE_FIXED32, - field.getFixed32List(), generator); - printUnknownField(number, WireFormat.WIRETYPE_FIXED64, - field.getFixed64List(), generator); - printUnknownField(number, WireFormat.WIRETYPE_LENGTH_DELIMITED, - field.getLengthDelimitedList(), generator); + printUnknownField(number, WireFormat.WIRETYPE_VARINT, field.getVarintList(), generator); + printUnknownField(number, WireFormat.WIRETYPE_FIXED32, field.getFixed32List(), generator); + printUnknownField(number, WireFormat.WIRETYPE_FIXED64, field.getFixed64List(), generator); + printUnknownField( + number, + WireFormat.WIRETYPE_LENGTH_DELIMITED, + field.getLengthDelimitedList(), + generator); for (final UnknownFieldSet value : field.getGroupList()) { generator.print(entry.getKey().toString()); generator.print(" {"); @@ -467,11 +775,9 @@ private void printUnknownFields(final UnknownFieldSet unknownFields, } } - private void printUnknownField(final int number, - final int wireType, - final List values, - final TextGenerator generator) - throws IOException { + private static void printUnknownField( + final int number, final int wireType, final List values, final TextGenerator generator) + throws IOException { for (final Object value : values) { generator.print(String.valueOf(number)); generator.print(": "); @@ -497,8 +803,7 @@ public static String unsignedToString(final long value) { } else { // Pull off the most-significant bit so that BigInteger doesn't think // the number is negative, then set it again using setBit(). - return BigInteger.valueOf(value & 0x7FFFFFFFFFFFFFFFL) - .setBit(63).toString(); + return BigInteger.valueOf(value & 0x7FFFFFFFFFFFFFFFL).setBit(63).toString(); } } @@ -510,9 +815,7 @@ private static TextGenerator singleLineOutput(Appendable output) { return new TextGenerator(output, true); } - /** - * An inner class for writing text to the output stream. - */ + /** An inner class for writing text to the output stream. */ private static final class TextGenerator { private final Appendable output; private final StringBuilder indent = new StringBuilder(); @@ -528,23 +831,19 @@ private TextGenerator(final Appendable output, boolean singleLineMode) { } /** - * Indent text by two spaces. After calling Indent(), two spaces will be - * inserted at the beginning of each line of text. Indent() may be called - * multiple times to produce deeper indents. + * Indent text by two spaces. After calling Indent(), two spaces will be inserted at the + * beginning of each line of text. Indent() may be called multiple times to produce deeper + * indents. */ public void indent() { indent.append(" "); } - /** - * Reduces the current indent level by two spaces, or crashes if the indent - * level is zero. - */ + /** Reduces the current indent level by two spaces, or crashes if the indent level is zero. */ public void outdent() { final int length = indent.length(); if (length == 0) { - throw new IllegalArgumentException( - " Outdent() without matching Indent()."); + throw new IllegalArgumentException(" Outdent() without matching Indent()."); } indent.setLength(length - 2); } @@ -580,30 +879,26 @@ public void eol() throws IOException { /** * Represents a stream of tokens parsed from a {@code String}. * - *

The Java standard library provides many classes that you might think - * would be useful for implementing this, but aren't. For example: + *

The Java standard library provides many classes that you might think would be useful for + * implementing this, but aren't. For example: * *

    - *
  • {@code java.io.StreamTokenizer}: This almost does what we want -- or, - * at least, something that would get us close to what we want -- except - * for one fatal flaw: It automatically un-escapes strings using Java - * escape sequences, which do not include all the escape sequences we - * need to support (e.g. '\x'). - *
  • {@code java.util.Scanner}: This seems like a great way at least to - * parse regular expressions out of a stream (so we wouldn't have to load - * the entire input into a single string before parsing). Sadly, - * {@code Scanner} requires that tokens be delimited with some delimiter. - * Thus, although the text "foo:" should parse to two tokens ("foo" and - * ":"), {@code Scanner} would recognize it only as a single token. - * Furthermore, {@code Scanner} provides no way to inspect the contents - * of delimiters, making it impossible to keep track of line and column - * numbers. + *
  • {@code java.io.StreamTokenizer}: This almost does what we want -- or, at least, something + * that would get us close to what we want -- except for one fatal flaw: It automatically + * un-escapes strings using Java escape sequences, which do not include all the escape + * sequences we need to support (e.g. '\x'). + *
  • {@code java.util.Scanner}: This seems like a great way at least to parse regular + * expressions out of a stream (so we wouldn't have to load the entire input into a single + * string before parsing). Sadly, {@code Scanner} requires that tokens be delimited with + * some delimiter. Thus, although the text "foo:" should parse to two tokens ("foo" and + * ":"), {@code Scanner} would recognize it only as a single token. Furthermore, {@code + * Scanner} provides no way to inspect the contents of delimiters, making it impossible to + * keep track of line and column numbers. *
* - *

Luckily, Java's regular expression support does manage to be useful to - * us. (Barely: We need {@code Matcher.usePattern()}, which is new in - * Java 1.5.) So, we can use that, at least. Unfortunately, this implies - * that we need to have the entire input in one contiguous string. + *

Luckily, Java's regular expression support does manage to be useful to us. (Barely: We need + * {@code Matcher.usePattern()}, which is new in Java 1.5.) So, we can use that, at least. + * Unfortunately, this implies that we need to have the entire input in one contiguous string. */ private static final class Tokenizer { private final CharSequence text; @@ -624,24 +919,20 @@ private static final class Tokenizer { // We use possessive quantifiers (*+ and ++) because otherwise the Java // regex matcher has stack overflows on large inputs. - private static final Pattern WHITESPACE = - Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE); - private static final Pattern TOKEN = Pattern.compile( - "[a-zA-Z_][0-9a-zA-Z_+-]*+|" + // an identifier - "[.]?[0-9+-][0-9a-zA-Z_.+-]*+|" + // a number - "\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" + // a double-quoted string - "\'([^\'\n\\\\]|\\\\.)*+(\'|\\\\?$)", // a single-quoted string - Pattern.MULTILINE); - - private static final Pattern DOUBLE_INFINITY = Pattern.compile( - "-?inf(inity)?", - Pattern.CASE_INSENSITIVE); - private static final Pattern FLOAT_INFINITY = Pattern.compile( - "-?inf(inity)?f?", - Pattern.CASE_INSENSITIVE); - private static final Pattern FLOAT_NAN = Pattern.compile( - "nanf?", - Pattern.CASE_INSENSITIVE); + private static final Pattern WHITESPACE = Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE); + private static final Pattern TOKEN = + Pattern.compile( + "[a-zA-Z_][0-9a-zA-Z_+-]*+|" // an identifier + + "[.]?[0-9+-][0-9a-zA-Z_.+-]*+|" // a number + + "\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" // a double-quoted string + + "\'([^\'\n\\\\]|\\\\.)*+(\'|\\\\?$)", // a single-quoted string + Pattern.MULTILINE); + + private static final Pattern DOUBLE_INFINITY = + Pattern.compile("-?inf(inity)?", Pattern.CASE_INSENSITIVE); + private static final Pattern FLOAT_INFINITY = + Pattern.compile("-?inf(inity)?f?", Pattern.CASE_INSENSITIVE); + private static final Pattern FLOAT_NAN = Pattern.compile("nanf?", Pattern.CASE_INSENSITIVE); /** Construct a tokenizer that parses tokens from the given text. */ private Tokenizer(final CharSequence text) { @@ -707,10 +998,7 @@ public void nextToken() { } } - /** - * Skip over any whitespace so that the matcher region starts at the next - * token. - */ + /** Skip over any whitespace so that the matcher region starts at the next token. */ private void skipWhitespace() { matcher.usePattern(WHITESPACE); if (matcher.lookingAt()) { @@ -719,8 +1007,8 @@ private void skipWhitespace() { } /** - * If the next token exactly matches {@code token}, consume it and return - * {@code true}. Otherwise, return {@code false} without doing anything. + * If the next token exactly matches {@code token}, consume it and return {@code true}. + * Otherwise, return {@code false} without doing anything. */ public boolean tryConsume(final String token) { if (currentToken.equals(token)) { @@ -732,8 +1020,8 @@ public boolean tryConsume(final String token) { } /** - * If the next token exactly matches {@code token}, consume it. Otherwise, - * throw a {@link ParseException}. + * If the next token exactly matches {@code token}, consume it. Otherwise, throw a {@link + * ParseException}. */ public void consume(final String token) throws ParseException { if (!tryConsume(token)) { @@ -741,31 +1029,24 @@ public void consume(final String token) throws ParseException { } } - /** - * Returns {@code true} if the next token is an integer, but does - * not consume it. - */ + /** Returns {@code true} if the next token is an integer, but does not consume it. */ public boolean lookingAtInteger() { if (currentToken.length() == 0) { return false; } final char c = currentToken.charAt(0); - return ('0' <= c && c <= '9') - || c == '-' || c == '+'; + return ('0' <= c && c <= '9') || c == '-' || c == '+'; } - /** - * Returns {@code true} if the current token's text is equal to that - * specified. - */ + /** Returns {@code true} if the current token's text is equal to that specified. */ public boolean lookingAt(String text) { return currentToken.equals(text); } /** - * If the next token is an identifier, consume it and return its value. - * Otherwise, throw a {@link ParseException}. + * If the next token is an identifier, consume it and return its value. Otherwise, throw a + * {@link ParseException}. */ public String consumeIdentifier() throws ParseException { for (int i = 0; i < currentToken.length(); i++) { @@ -773,11 +1054,11 @@ public String consumeIdentifier() throws ParseException { if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') - || (c == '_') || (c == '.')) { + || (c == '_') + || (c == '.')) { // OK } else { - throw parseException( - "Expected identifier. Found '" + currentToken + "'"); + throw parseException("Expected identifier. Found '" + currentToken + "'"); } } @@ -787,8 +1068,8 @@ public String consumeIdentifier() throws ParseException { } /** - * If the next token is an identifier, consume it and return {@code true}. - * Otherwise, return {@code false} without doing anything. + * If the next token is an identifier, consume it and return {@code true}. Otherwise, return + * {@code false} without doing anything. */ public boolean tryConsumeIdentifier() { try { @@ -800,8 +1081,8 @@ public boolean tryConsumeIdentifier() { } /** - * If the next token is a 32-bit signed integer, consume it and return its - * value. Otherwise, throw a {@link ParseException}. + * If the next token is a 32-bit signed integer, consume it and return its value. Otherwise, + * throw a {@link ParseException}. */ public int consumeInt32() throws ParseException { try { @@ -814,8 +1095,8 @@ public int consumeInt32() throws ParseException { } /** - * If the next token is a 32-bit unsigned integer, consume it and return its - * value. Otherwise, throw a {@link ParseException}. + * If the next token is a 32-bit unsigned integer, consume it and return its value. Otherwise, + * throw a {@link ParseException}. */ public int consumeUInt32() throws ParseException { try { @@ -828,8 +1109,8 @@ public int consumeUInt32() throws ParseException { } /** - * If the next token is a 64-bit signed integer, consume it and return its - * value. Otherwise, throw a {@link ParseException}. + * If the next token is a 64-bit signed integer, consume it and return its value. Otherwise, + * throw a {@link ParseException}. */ public long consumeInt64() throws ParseException { try { @@ -842,8 +1123,8 @@ public long consumeInt64() throws ParseException { } /** - * If the next token is a 64-bit signed integer, consume it and return - * {@code true}. Otherwise, return {@code false} without doing anything. + * If the next token is a 64-bit signed integer, consume it and return {@code true}. Otherwise, + * return {@code false} without doing anything. */ public boolean tryConsumeInt64() { try { @@ -855,8 +1136,8 @@ public boolean tryConsumeInt64() { } /** - * If the next token is a 64-bit unsigned integer, consume it and return its - * value. Otherwise, throw a {@link ParseException}. + * If the next token is a 64-bit unsigned integer, consume it and return its value. Otherwise, + * throw a {@link ParseException}. */ public long consumeUInt64() throws ParseException { try { @@ -869,8 +1150,8 @@ public long consumeUInt64() throws ParseException { } /** - * If the next token is a 64-bit unsigned integer, consume it and return - * {@code true}. Otherwise, return {@code false} without doing anything. + * If the next token is a 64-bit unsigned integer, consume it and return {@code true}. + * Otherwise, return {@code false} without doing anything. */ public boolean tryConsumeUInt64() { try { @@ -882,8 +1163,8 @@ public boolean tryConsumeUInt64() { } /** - * If the next token is a double, consume it and return its value. - * Otherwise, throw a {@link ParseException}. + * If the next token is a double, consume it and return its value. Otherwise, throw a {@link + * ParseException}. */ public double consumeDouble() throws ParseException { // We need to parse infinity and nan separately because @@ -907,8 +1188,8 @@ public double consumeDouble() throws ParseException { } /** - * If the next token is a double, consume it and return {@code true}. - * Otherwise, return {@code false} without doing anything. + * If the next token is a double, consume it and return {@code true}. Otherwise, return {@code + * false} without doing anything. */ public boolean tryConsumeDouble() { try { @@ -920,8 +1201,8 @@ public boolean tryConsumeDouble() { } /** - * If the next token is a float, consume it and return its value. - * Otherwise, throw a {@link ParseException}. + * If the next token is a float, consume it and return its value. Otherwise, throw a {@link + * ParseException}. */ public float consumeFloat() throws ParseException { // We need to parse infinity and nan separately because @@ -945,8 +1226,8 @@ public float consumeFloat() throws ParseException { } /** - * If the next token is a float, consume it and return {@code true}. - * Otherwise, return {@code false} without doing anything. + * If the next token is a float, consume it and return {@code true}. Otherwise, return {@code + * false} without doing anything. */ public boolean tryConsumeFloat() { try { @@ -958,8 +1239,8 @@ public boolean tryConsumeFloat() { } /** - * If the next token is a boolean, consume it and return its value. - * Otherwise, throw a {@link ParseException}. + * If the next token is a boolean, consume it and return its value. Otherwise, throw a {@link + * ParseException}. */ public boolean consumeBoolean() throws ParseException { if (currentToken.equals("true") @@ -975,22 +1256,19 @@ public boolean consumeBoolean() throws ParseException { nextToken(); return false; } else { - throw parseException("Expected \"true\" or \"false\"."); + throw parseException("Expected \"true\" or \"false\". Found \"" + currentToken + "\"."); } } /** - * If the next token is a string, consume it and return its (unescaped) - * value. Otherwise, throw a {@link ParseException}. + * If the next token is a string, consume it and return its (unescaped) value. Otherwise, throw + * a {@link ParseException}. */ public String consumeString() throws ParseException { return consumeByteString().toStringUtf8(); } - /** - * If the next token is a string, consume it and return true. Otherwise, - * return false. - */ + /** If the next token is a string, consume it and return true. Otherwise, return false. */ public boolean tryConsumeString() { try { consumeString(); @@ -1001,9 +1279,8 @@ public boolean tryConsumeString() { } /** - * If the next token is a string, consume it, unescape it as a - * {@link ByteString}, and return it. Otherwise, throw a - * {@link ParseException}. + * If the next token is a string, consume it, unescape it as a {@link ByteString}, and return + * it. Otherwise, throw a {@link ParseException}. */ public ByteString consumeByteString() throws ParseException { List list = new ArrayList(); @@ -1015,28 +1292,22 @@ public ByteString consumeByteString() throws ParseException { } /** - * Like {@link #consumeByteString()} but adds each token of the string to - * the given list. String literals (whether bytes or text) may come in - * multiple adjacent tokens which are automatically concatenated, like in - * C or Python. + * Like {@link #consumeByteString()} but adds each token of the string to the given list. String + * literals (whether bytes or text) may come in multiple adjacent tokens which are automatically + * concatenated, like in C or Python. */ - private void consumeByteString(List list) - throws ParseException { - final char quote = currentToken.length() > 0 - ? currentToken.charAt(0) - : '\0'; + private void consumeByteString(List list) throws ParseException { + final char quote = currentToken.length() > 0 ? currentToken.charAt(0) : '\0'; if (quote != '\"' && quote != '\'') { throw parseException("Expected string."); } - if (currentToken.length() < 2 - || currentToken.charAt(currentToken.length() - 1) != quote) { + if (currentToken.length() < 2 || currentToken.charAt(currentToken.length() - 1) != quote) { throw parseException("String missing ending quote."); } try { - final String escaped = - currentToken.substring(1, currentToken.length() - 1); + final String escaped = currentToken.substring(1, currentToken.length() - 1); final ByteString result = unescapeBytes(escaped); nextToken(); list.add(result); @@ -1046,53 +1317,48 @@ private void consumeByteString(List list) } /** - * Returns a {@link ParseException} with the current line and column - * numbers in the description, suitable for throwing. + * Returns a {@link ParseException} with the current line and column numbers in the description, + * suitable for throwing. */ public ParseException parseException(final String description) { // Note: People generally prefer one-based line and column numbers. - return new ParseException( - line + 1, column + 1, description); + return new ParseException(line + 1, column + 1, description); } /** - * Returns a {@link ParseException} with the line and column numbers of - * the previous token in the description, suitable for throwing. + * Returns a {@link ParseException} with the line and column numbers of the previous token in + * the description, suitable for throwing. */ - public ParseException parseExceptionPreviousToken( - final String description) { + public ParseException parseExceptionPreviousToken(final String description) { // Note: People generally prefer one-based line and column numbers. - return new ParseException( - previousLine + 1, previousColumn + 1, description); + return new ParseException(previousLine + 1, previousColumn + 1, description); } /** - * Constructs an appropriate {@link ParseException} for the given - * {@code NumberFormatException} when trying to parse an integer. + * Constructs an appropriate {@link ParseException} for the given {@code NumberFormatException} + * when trying to parse an integer. */ - private ParseException integerParseException( - final NumberFormatException e) { + private ParseException integerParseException(final NumberFormatException e) { return parseException("Couldn't parse integer: " + e.getMessage()); } /** - * Constructs an appropriate {@link ParseException} for the given - * {@code NumberFormatException} when trying to parse a float or double. + * Constructs an appropriate {@link ParseException} for the given {@code NumberFormatException} + * when trying to parse a float or double. */ private ParseException floatParseException(final NumberFormatException e) { return parseException("Couldn't parse number: " + e.getMessage()); } /** - * Returns a {@link UnknownFieldParseException} with the line and column - * numbers of the previous token in the description, and the unknown field - * name, suitable for throwing. + * Returns a {@link UnknownFieldParseException} with the line and column numbers of the previous + * token in the description, and the unknown field name, suitable for throwing. */ public UnknownFieldParseException unknownFieldParseExceptionPreviousToken( final String unknownField, final String description) { // Note: People generally prefer one-based line and column numbers. return new UnknownFieldParseException( - previousLine + 1, previousColumn + 1, unknownField, description); + previousLine + 1, previousColumn + 1, unknownField, description); } } @@ -1111,47 +1377,39 @@ public ParseException(final String message) { /** * Create a new instance * - * @param line the line number where the parse error occurred, - * using 1-offset. - * @param column the column number where the parser error occurred, - * using 1-offset. + * @param line the line number where the parse error occurred, using 1-offset. + * @param column the column number where the parser error occurred, using 1-offset. */ - public ParseException(final int line, final int column, - final String message) { + public ParseException(final int line, final int column, final String message) { super(Integer.toString(line) + ":" + column + ": " + message); this.line = line; this.column = column; } /** - * Return the line where the parse exception occurred, or -1 when - * none is provided. The value is specified as 1-offset, so the first - * line is line 1. + * Return the line where the parse exception occurred, or -1 when none is provided. The value is + * specified as 1-offset, so the first line is line 1. */ public int getLine() { return line; } /** - * Return the column where the parse exception occurred, or -1 when - * none is provided. The value is specified as 1-offset, so the first - * line is line 1. + * Return the column where the parse exception occurred, or -1 when none is provided. The value + * is specified as 1-offset, so the first line is line 1. */ public int getColumn() { return column; } } - /** - * Thrown when encountering an unknown field while parsing - * a text format message. - */ + /** Thrown when encountering an unknown field while parsing a text format message. */ public static class UnknownFieldParseException extends ParseException { private final String unknownField; /** - * Create a new instance, with -1 as the line and column numbers, and an - * empty unknown field name. + * Create a new instance, with -1 as the line and column numbers, and an empty unknown field + * name. */ public UnknownFieldParseException(final String message) { this(-1, -1, "", message); @@ -1160,21 +1418,18 @@ public UnknownFieldParseException(final String message) { /** * Create a new instance * - * @param line the line number where the parse error occurred, - * using 1-offset. - * @param column the column number where the parser error occurred, - * using 1-offset. + * @param line the line number where the parse error occurred, using 1-offset. + * @param column the column number where the parser error occurred, using 1-offset. * @param unknownField the name of the unknown field found while parsing. */ - public UnknownFieldParseException(final int line, final int column, - final String unknownField, final String message) { + public UnknownFieldParseException( + final int line, final int column, final String unknownField, final String message) { super(line, column, message); this.unknownField = unknownField; } /** - * Return the name of the unknown field encountered while parsing the - * protocol buffer string. + * Return the name of the unknown field encountered while parsing the protocol buffer string. */ public String getUnknownField() { return unknownField; @@ -1184,166 +1439,232 @@ public String getUnknownField() { private static final Parser PARSER = Parser.newBuilder().build(); /** - * Return a {@link Parser} instance which can parse text-format - * messages. The returned instance is thread-safe. + * Return a {@link Parser} instance which can parse text-format messages. The returned instance is + * thread-safe. */ public static Parser getParser() { return PARSER; } - /** - * Parse a text-format message from {@code input} and merge the contents - * into {@code builder}. - */ - public static void merge(final Readable input, - final Message.Builder builder) - throws IOException { + /** Parse a text-format message from {@code input} and merge the contents into {@code builder}. */ + public static void merge(final Readable input, final Message.Builder builder) throws IOException { + PARSER.merge(input, builder); + } + + /** Parse a text-format message from {@code input} and merge the contents into {@code builder}. */ + public static void merge(final CharSequence input, final Message.Builder builder) + throws ParseException { PARSER.merge(input, builder); } /** - * Parse a text-format message from {@code input} and merge the contents - * into {@code builder}. + * Parse a text-format message from {@code input}. + * + * @return the parsed message, guaranteed initialized */ - public static void merge(final CharSequence input, - final Message.Builder builder) - throws ParseException { - PARSER.merge(input, builder); + public static T parse(final CharSequence input, final Class protoClass) + throws ParseException { + Message.Builder builder = Internal.getDefaultInstance(protoClass).newBuilderForType(); + merge(input, builder); + @SuppressWarnings("unchecked") + T output = (T) builder.build(); + return output; } /** - * Parse a text-format message from {@code input} and merge the contents - * into {@code builder}. Extensions will be recognized if they are - * registered in {@code extensionRegistry}. + * Parse a text-format message from {@code input} and merge the contents into {@code builder}. + * Extensions will be recognized if they are registered in {@code extensionRegistry}. */ - public static void merge(final Readable input, - final ExtensionRegistry extensionRegistry, - final Message.Builder builder) - throws IOException { + public static void merge( + final Readable input, + final ExtensionRegistry extensionRegistry, + final Message.Builder builder) + throws IOException { PARSER.merge(input, extensionRegistry, builder); } /** - * Parse a text-format message from {@code input} and merge the contents - * into {@code builder}. Extensions will be recognized if they are - * registered in {@code extensionRegistry}. + * Parse a text-format message from {@code input} and merge the contents into {@code builder}. + * Extensions will be recognized if they are registered in {@code extensionRegistry}. */ - public static void merge(final CharSequence input, - final ExtensionRegistry extensionRegistry, - final Message.Builder builder) - throws ParseException { + public static void merge( + final CharSequence input, + final ExtensionRegistry extensionRegistry, + final Message.Builder builder) + throws ParseException { PARSER.merge(input, extensionRegistry, builder); } + /** + * Parse a text-format message from {@code input}. Extensions will be recognized if they are + * registered in {@code extensionRegistry}. + * + * @return the parsed message, guaranteed initialized + */ + public static T parse( + final CharSequence input, + final ExtensionRegistry extensionRegistry, + final Class protoClass) + throws ParseException { + Message.Builder builder = Internal.getDefaultInstance(protoClass).newBuilderForType(); + merge(input, extensionRegistry, builder); + @SuppressWarnings("unchecked") + T output = (T) builder.build(); + return output; + } + /** - * Parser for text-format proto2 instances. This class is thread-safe. - * The implementation largely follows google/protobuf/text_format.cc. + * Parser for text-format proto2 instances. This class is thread-safe. The implementation largely + * follows google/protobuf/text_format.cc. * - *

Use {@link TextFormat#getParser()} to obtain the default parser, or - * {@link Builder} to control the parser behavior. + *

Use {@link TextFormat#getParser()} to obtain the default parser, or {@link Builder} to + * control the parser behavior. */ public static class Parser { /** - * Determines if repeated values for non-repeated fields and - * oneofs are permitted. For example, given required/optional field "foo" - * and a oneof containing "baz" and "qux": + * Determines if repeated values for non-repeated fields and oneofs are permitted. For example, + * given required/optional field "foo" and a oneof containing "baz" and "qux": + * *

    - *
  • "foo: 1 foo: 2" - *
  • "baz: 1 qux: 2" - *
  • merging "foo: 2" into a proto in which foo is already set, or - *
  • merging "qux: 2" into a proto in which baz is already set. + *
  • "foo: 1 foo: 2" + *
  • "baz: 1 qux: 2" + *
  • merging "foo: 2" into a proto in which foo is already set, or + *
  • merging "qux: 2" into a proto in which baz is already set. *
*/ public enum SingularOverwritePolicy { - /** The last value is retained. */ + /** + * Later values are merged with earlier values. For primitive fields or conflicting oneofs, + * the last value is retained. + */ ALLOW_SINGULAR_OVERWRITES, /** An error is issued. */ FORBID_SINGULAR_OVERWRITES } + private final TypeRegistry typeRegistry; private final boolean allowUnknownFields; + private final boolean allowUnknownEnumValues; + private final boolean allowUnknownExtensions; private final SingularOverwritePolicy singularOverwritePolicy; private TextFormatParseInfoTree.Builder parseInfoTreeBuilder; private Parser( - boolean allowUnknownFields, SingularOverwritePolicy singularOverwritePolicy, + TypeRegistry typeRegistry, + boolean allowUnknownFields, + boolean allowUnknownEnumValues, + boolean allowUnknownExtensions, + SingularOverwritePolicy singularOverwritePolicy, TextFormatParseInfoTree.Builder parseInfoTreeBuilder) { + this.typeRegistry = typeRegistry; this.allowUnknownFields = allowUnknownFields; + this.allowUnknownEnumValues = allowUnknownEnumValues; + this.allowUnknownExtensions = allowUnknownExtensions; this.singularOverwritePolicy = singularOverwritePolicy; this.parseInfoTreeBuilder = parseInfoTreeBuilder; } - /** - * Returns a new instance of {@link Builder}. - */ + /** Returns a new instance of {@link Builder}. */ public static Builder newBuilder() { return new Builder(); } - /** - * Builder that can be used to obtain new instances of {@link Parser}. - */ + /** Builder that can be used to obtain new instances of {@link Parser}. */ public static class Builder { private boolean allowUnknownFields = false; + private boolean allowUnknownEnumValues = false; + private boolean allowUnknownExtensions = false; private SingularOverwritePolicy singularOverwritePolicy = SingularOverwritePolicy.ALLOW_SINGULAR_OVERWRITES; private TextFormatParseInfoTree.Builder parseInfoTreeBuilder = null; + private TypeRegistry typeRegistry = TypeRegistry.getEmptyTypeRegistry(); + /** + * Sets the TypeRegistry for resolving Any. If this is not set, TextFormat will not be able to + * parse Any unless Any is write as bytes. + * + * @throws IllegalArgumentException if a registry is already set. + */ + public Builder setTypeRegistry(TypeRegistry typeRegistry) { + this.typeRegistry = typeRegistry; + return this; + } /** - * Sets parser behavior when a non-repeated field appears more than once. + * Set whether this parser will allow unknown fields. By default, an exception is thrown if an + * unknown field is encountered. If this is set, the parser will only log a warning. Allow + * unknown fields will also allow unknown extensions. + * + *

Use of this parameter is discouraged which may hide some errors (e.g. + * spelling error on field name). */ + public Builder setAllowUnknownFields(boolean allowUnknownFields) { + this.allowUnknownFields = allowUnknownFields; + return this; + } + + /** + * Set whether this parser will allow unknown extensions. By default, an + * exception is thrown if unknown extension is encountered. If this is set true, + * the parser will only log a warning. Allow unknown extensions does not mean + * allow normal unknown fields. + */ + public Builder setAllowUnknownExtensions(boolean allowUnknownExtensions) { + this.allowUnknownExtensions = allowUnknownExtensions; + return this; + } + + /** Sets parser behavior when a non-repeated field appears more than once. */ public Builder setSingularOverwritePolicy(SingularOverwritePolicy p) { this.singularOverwritePolicy = p; return this; } - public Builder setParseInfoTreeBuilder( - TextFormatParseInfoTree.Builder parseInfoTreeBuilder) { + public Builder setParseInfoTreeBuilder(TextFormatParseInfoTree.Builder parseInfoTreeBuilder) { this.parseInfoTreeBuilder = parseInfoTreeBuilder; return this; } public Parser build() { return new Parser( - allowUnknownFields, singularOverwritePolicy, parseInfoTreeBuilder); + typeRegistry, + allowUnknownFields, + allowUnknownEnumValues, + allowUnknownExtensions, + singularOverwritePolicy, + parseInfoTreeBuilder); } } /** - * Parse a text-format message from {@code input} and merge the contents - * into {@code builder}. + * Parse a text-format message from {@code input} and merge the contents into {@code builder}. */ - public void merge(final Readable input, - final Message.Builder builder) - throws IOException { + public void merge(final Readable input, final Message.Builder builder) throws IOException { merge(input, ExtensionRegistry.getEmptyRegistry(), builder); } /** - * Parse a text-format message from {@code input} and merge the contents - * into {@code builder}. + * Parse a text-format message from {@code input} and merge the contents into {@code builder}. */ - public void merge(final CharSequence input, - final Message.Builder builder) - throws ParseException { + public void merge(final CharSequence input, final Message.Builder builder) + throws ParseException { merge(input, ExtensionRegistry.getEmptyRegistry(), builder); } /** - * Parse a text-format message from {@code input} and merge the contents - * into {@code builder}. Extensions will be recognized if they are - * registered in {@code extensionRegistry}. + * Parse a text-format message from {@code input} and merge the contents into {@code builder}. + * Extensions will be recognized if they are registered in {@code extensionRegistry}. */ - public void merge(final Readable input, - final ExtensionRegistry extensionRegistry, - final Message.Builder builder) - throws IOException { + public void merge( + final Readable input, + final ExtensionRegistry extensionRegistry, + final Message.Builder builder) + throws IOException { // Read the entire input to a String then parse that. - // If StreamTokenizer were not quite so crippled, or if there were a kind + // If StreamTokenizer was not so limited, or if there were a kind // of Reader that could read in chunks that match some particular regex, // or if we wanted to write a custom Reader to tokenize our stream, then // we would not have to read to one big String. Alas, none of these is @@ -1357,8 +1678,7 @@ public void merge(final Readable input, // TODO(chrisn): See if working around java.io.Reader#read(CharBuffer) // overhead is worthwhile - private static StringBuilder toStringBuilder(final Readable input) - throws IOException { + private static StringBuilder toStringBuilder(final Readable input) throws IOException { final StringBuilder text = new StringBuilder(); final CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE); while (true) { @@ -1372,42 +1692,71 @@ private static StringBuilder toStringBuilder(final Readable input) return text; } - // Check both unknown fields and unknown extensions and log warming messages + static final class UnknownField { + static enum Type { + FIELD, EXTENSION; + } + + final String message; + final Type type; + + UnknownField(String message, Type type) { + this.message = message; + this.type = type; + } + } + + // Check both unknown fields and unknown extensions and log warning messages // or throw exceptions according to the flag. - private void checkUnknownFields(final List unknownFields) - throws ParseException { + private void checkUnknownFields(final List unknownFields) throws ParseException { if (unknownFields.isEmpty()) { return; } StringBuilder msg = new StringBuilder("Input contains unknown fields and/or extensions:"); - for (String field : unknownFields) { - msg.append('\n').append(field); + for (UnknownField field : unknownFields) { + msg.append('\n').append(field.message); } if (allowUnknownFields) { + logger.warning(msg.toString()); + return; + } + + int firstErrorIndex = 0; + if (allowUnknownExtensions) { + boolean allUnknownExtensions = true; + for (UnknownField field : unknownFields) { + if (field.type == UnknownField.Type.FIELD) { + allUnknownExtensions = false; + break; + } + ++firstErrorIndex; + } + if (allUnknownExtensions) { logger.warning(msg.toString()); - } else { - String[] lineColumn = unknownFields.get(0).split(":"); - throw new ParseException(Integer.valueOf(lineColumn[0]), - Integer.valueOf(lineColumn[1]), msg.toString()); + return; + } } + + String[] lineColumn = unknownFields.get(firstErrorIndex).message.split(":"); + throw new ParseException( + Integer.parseInt(lineColumn[0]), Integer.parseInt(lineColumn[1]), msg.toString()); } /** - * Parse a text-format message from {@code input} and merge the contents - * into {@code builder}. Extensions will be recognized if they are - * registered in {@code extensionRegistry}. + * Parse a text-format message from {@code input} and merge the contents into {@code builder}. + * Extensions will be recognized if they are registered in {@code extensionRegistry}. */ - public void merge(final CharSequence input, - final ExtensionRegistry extensionRegistry, - final Message.Builder builder) - throws ParseException { + public void merge( + final CharSequence input, + final ExtensionRegistry extensionRegistry, + final Message.Builder builder) + throws ParseException { final Tokenizer tokenizer = new Tokenizer(input); - MessageReflection.BuilderAdapter target = - new MessageReflection.BuilderAdapter(builder); + MessageReflection.BuilderAdapter target = new MessageReflection.BuilderAdapter(builder); - List unknownFields = new ArrayList(); + List unknownFields = new ArrayList(); while (!tokenizer.atEnd()) { mergeField(tokenizer, extensionRegistry, target, unknownFields); @@ -1417,62 +1766,70 @@ public void merge(final CharSequence input, } - /** - * Parse a single field from {@code tokenizer} and merge it into - * {@code builder}. - */ - private void mergeField(final Tokenizer tokenizer, - final ExtensionRegistry extensionRegistry, - final MessageReflection.MergeTarget target, - List unknownFields) - throws ParseException { - mergeField(tokenizer, extensionRegistry, target, parseInfoTreeBuilder, - unknownFields); + /** Parse a single field from {@code tokenizer} and merge it into {@code builder}. */ + private void mergeField( + final Tokenizer tokenizer, + final ExtensionRegistry extensionRegistry, + final MessageReflection.MergeTarget target, + List unknownFields) + throws ParseException { + mergeField( + tokenizer, + extensionRegistry, + target, + parseInfoTreeBuilder, + unknownFields); } - /** - * Parse a single field from {@code tokenizer} and merge it into - * {@code target}. - */ - private void mergeField(final Tokenizer tokenizer, - final ExtensionRegistry extensionRegistry, - final MessageReflection.MergeTarget target, - TextFormatParseInfoTree.Builder parseTreeBuilder, - List unknownFields) - throws ParseException { + /** Parse a single field from {@code tokenizer} and merge it into {@code target}. */ + private void mergeField( + final Tokenizer tokenizer, + final ExtensionRegistry extensionRegistry, + final MessageReflection.MergeTarget target, + TextFormatParseInfoTree.Builder parseTreeBuilder, + List unknownFields) + throws ParseException { FieldDescriptor field = null; int startLine = tokenizer.getLine(); int startColumn = tokenizer.getColumn(); final Descriptor type = target.getDescriptorForType(); ExtensionRegistry.ExtensionInfo extension = null; + if ("google.protobuf.Any".equals(type.getFullName()) && tokenizer.tryConsume("[")) { + mergeAnyFieldValue(tokenizer, extensionRegistry, target, parseTreeBuilder, unknownFields, + type); + return; + } + if (tokenizer.tryConsume("[")) { // An extension. - final StringBuilder name = - new StringBuilder(tokenizer.consumeIdentifier()); + final StringBuilder name = new StringBuilder(tokenizer.consumeIdentifier()); while (tokenizer.tryConsume(".")) { name.append('.'); name.append(tokenizer.consumeIdentifier()); } - extension = target.findExtensionByName( - extensionRegistry, name.toString()); + extension = target.findExtensionByName(extensionRegistry, name.toString()); if (extension == null) { - unknownFields.add( - (tokenizer.getPreviousLine() + 1) - + ":" - + (tokenizer.getPreviousColumn() + 1) - + ":\t" - + type.getFullName() - + ".[" - + name - + "]"); + String message = + (tokenizer.getPreviousLine() + 1) + + ":" + + (tokenizer.getPreviousColumn() + 1) + + ":\t" + + type.getFullName() + + ".[" + + name + + "]"; + unknownFields.add(new UnknownField(message, UnknownField.Type.EXTENSION)); } else { if (extension.descriptor.getContainingType() != type) { throw tokenizer.parseExceptionPreviousToken( - "Extension \"" + name + "\" does not extend message type \"" - + type.getFullName() + "\"."); + "Extension \"" + + name + + "\" does not extend message type \"" + + type.getFullName() + + "\"."); } field = extension.descriptor; } @@ -1496,20 +1853,21 @@ private void mergeField(final Tokenizer tokenizer, } } // Again, special-case group names as described above. - if (field != null && field.getType() == FieldDescriptor.Type.GROUP + if (field != null + && field.getType() == FieldDescriptor.Type.GROUP && !field.getMessageType().getName().equals(name)) { field = null; } if (field == null) { - unknownFields.add( - (tokenizer.getPreviousLine() + 1) - + ":" - + (tokenizer.getPreviousColumn() + 1) - + ":\t" - + type.getFullName() - + "." - + name); + String message = (tokenizer.getPreviousLine() + 1) + + ":" + + (tokenizer.getPreviousColumn() + 1) + + ":\t" + + type.getFullName() + + "." + + name; + unknownFields.add(new UnknownField(message, UnknownField.Type.FIELD)); } } @@ -1521,9 +1879,7 @@ private void mergeField(final Tokenizer tokenizer, // start with "{" or "<" which indicates the beginning of a message body. // If there is no ":" or there is a "{" or "<" after ":", this field has // to be a message or the input is ill-formed. - if (tokenizer.tryConsume(":") - && !tokenizer.lookingAt("{") - && !tokenizer.lookingAt("<")) { + if (tokenizer.tryConsume(":") && !tokenizer.lookingAt("{") && !tokenizer.lookingAt("<")) { skipFieldValue(tokenizer); } else { skipFieldMessage(tokenizer); @@ -1533,25 +1889,42 @@ private void mergeField(final Tokenizer tokenizer, // Handle potential ':'. if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - tokenizer.tryConsume(":"); // optional + tokenizer.tryConsume(":"); // optional if (parseTreeBuilder != null) { TextFormatParseInfoTree.Builder childParseTreeBuilder = parseTreeBuilder.getBuilderForSubMessageField(field); - consumeFieldValues(tokenizer, extensionRegistry, target, field, extension, - childParseTreeBuilder, unknownFields); + consumeFieldValues( + tokenizer, + extensionRegistry, + target, + field, + extension, + childParseTreeBuilder, + unknownFields); } else { - consumeFieldValues(tokenizer, extensionRegistry, target, field, extension, - parseTreeBuilder, unknownFields); + consumeFieldValues( + tokenizer, + extensionRegistry, + target, + field, + extension, + parseTreeBuilder, + unknownFields); } } else { - tokenizer.consume(":"); // required - consumeFieldValues(tokenizer, extensionRegistry, target, field, - extension, parseTreeBuilder, unknownFields); + tokenizer.consume(":"); // required + consumeFieldValues( + tokenizer, + extensionRegistry, + target, + field, + extension, + parseTreeBuilder, + unknownFields); } if (parseTreeBuilder != null) { - parseTreeBuilder.setLocation( - field, TextFormatParseLocation.create(startLine, startColumn)); + parseTreeBuilder.setLocation(field, TextFormatParseLocation.create(startLine, startColumn)); } // For historical reasons, fields may optionally be separated by commas or @@ -1562,8 +1935,7 @@ private void mergeField(final Tokenizer tokenizer, } /** - * Parse a one or more field values from {@code tokenizer} and merge it into - * {@code builder}. + * Parse a one or more field values from {@code tokenizer} and merge it into {@code builder}. */ private void consumeFieldValues( final Tokenizer tokenizer, @@ -1572,12 +1944,12 @@ private void consumeFieldValues( final FieldDescriptor field, final ExtensionRegistry.ExtensionInfo extension, final TextFormatParseInfoTree.Builder parseTreeBuilder, - List unknownFields) + List unknownFields) throws ParseException { // Support specifying repeated field values as a comma-separated list. // Ex."foo: [1, 2, 3]" if (field.isRepeated() && tokenizer.tryConsume("[")) { - if (!tokenizer.tryConsume("]")) { // Allow "foo: []" to be treated as empty. + if (!tokenizer.tryConsume("]")) { // Allow "foo: []" to be treated as empty. while (true) { consumeFieldValue( tokenizer, @@ -1595,15 +1967,18 @@ private void consumeFieldValues( } } } else { - consumeFieldValue(tokenizer, extensionRegistry, target, field, - extension, parseTreeBuilder, unknownFields); + consumeFieldValue( + tokenizer, + extensionRegistry, + target, + field, + extension, + parseTreeBuilder, + unknownFields); } } - /** - * Parse a single field value from {@code tokenizer} and merge it into - * {@code builder}. - */ + /** Parse a single field value from {@code tokenizer} and merge it into {@code builder}. */ private void consumeFieldValue( final Tokenizer tokenizer, final ExtensionRegistry extensionRegistry, @@ -1611,8 +1986,27 @@ private void consumeFieldValue( final FieldDescriptor field, final ExtensionRegistry.ExtensionInfo extension, final TextFormatParseInfoTree.Builder parseTreeBuilder, - List unknownFields) + List unknownFields) throws ParseException { + if (singularOverwritePolicy == SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES + && !field.isRepeated()) { + if (target.hasField(field)) { + throw tokenizer.parseExceptionPreviousToken( + "Non-repeated field \"" + field.getFullName() + "\" cannot be overwritten."); + } else if (field.getContainingOneof() != null + && target.hasOneof(field.getContainingOneof())) { + Descriptors.OneofDescriptor oneof = field.getContainingOneof(); + throw tokenizer.parseExceptionPreviousToken( + "Field \"" + + field.getFullName() + + "\" is specified along with field \"" + + target.getOneofFieldDescriptor(oneof).getFullName() + + "\", another member of oneof \"" + + oneof.getName() + + "\"."); + } + } + Object value = null; if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { @@ -1624,20 +2018,31 @@ private void consumeFieldValue( endToken = "}"; } - final MessageReflection.MergeTarget subField; - subField = target.newMergeTargetForField(field, - (extension == null) ? null : extension.defaultInstance); + // Try to parse human readable format of Any in the form: [type_url]: { ... } + if (field.getMessageType().getFullName().equals("google.protobuf.Any") + && tokenizer.tryConsume("[")) { + // Use Proto reflection here since depending on Any would intoduce a cyclic dependency + // (java_proto_library for any_java_proto depends on the protobuf_impl). + Message anyBuilder = DynamicMessage.getDefaultInstance(field.getMessageType()); + MessageReflection.MergeTarget anyField = target.newMergeTargetForField(field, anyBuilder); + mergeAnyFieldValue(tokenizer, extensionRegistry, anyField, parseTreeBuilder, + unknownFields, field.getMessageType()); + value = anyField.finish(); + tokenizer.consume(endToken); + } else { + Message defaultInstance = (extension == null) ? null : extension.defaultInstance; + MessageReflection.MergeTarget subField = + target.newMergeTargetForField(field, defaultInstance); - while (!tokenizer.tryConsume(endToken)) { - if (tokenizer.atEnd()) { - throw tokenizer.parseException( - "Expected \"" + endToken + "\"."); + while (!tokenizer.tryConsume(endToken)) { + if (tokenizer.atEnd()) { + throw tokenizer.parseException("Expected \"" + endToken + "\"."); + } + mergeField(tokenizer, extensionRegistry, subField, parseTreeBuilder, unknownFields); } - mergeField(tokenizer, extensionRegistry, subField, parseTreeBuilder, - unknownFields); - } - value = subField.finish(); + value = subField.finish(); + } } else { switch (field.getType()) { @@ -1690,17 +2095,40 @@ private void consumeFieldValue( final int number = tokenizer.consumeInt32(); value = enumType.findValueByNumber(number); if (value == null) { - throw tokenizer.parseExceptionPreviousToken( - "Enum type \"" + enumType.getFullName() - + "\" has no value with number " + number + '.'); + String unknownValueMsg = + "Enum type \"" + + enumType.getFullName() + + "\" has no value with number " + + number + + '.'; + if (allowUnknownEnumValues) { + logger.warning(unknownValueMsg); + return; + } else { + throw tokenizer.parseExceptionPreviousToken( + "Enum type \"" + + enumType.getFullName() + + "\" has no value with number " + + number + + '.'); + } } } else { final String id = tokenizer.consumeIdentifier(); value = enumType.findValueByName(id); if (value == null) { - throw tokenizer.parseExceptionPreviousToken( - "Enum type \"" + enumType.getFullName() - + "\" has no value named \"" + id + "\"."); + String unknownValueMsg = + "Enum type \"" + + enumType.getFullName() + + "\" has no value named \"" + + id + + "\"."; + if (allowUnknownEnumValues) { + logger.warning(unknownValueMsg); + return; + } else { + throw tokenizer.parseExceptionPreviousToken(unknownValueMsg); + } } } @@ -1716,29 +2144,72 @@ private void consumeFieldValue( // TODO(b/29122459): If field.isMapField() and FORBID_SINGULAR_OVERWRITES mode, // check for duplicate map keys here. target.addRepeatedField(field, value); - } else if ((singularOverwritePolicy - == SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES) - && target.hasField(field)) { - throw tokenizer.parseExceptionPreviousToken("Non-repeated field \"" - + field.getFullName() + "\" cannot be overwritten."); - } else if ((singularOverwritePolicy - == SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES) - && field.getContainingOneof() != null - && target.hasOneof(field.getContainingOneof())) { - Descriptors.OneofDescriptor oneof = field.getContainingOneof(); - throw tokenizer.parseExceptionPreviousToken("Field \"" - + field.getFullName() + "\" is specified along with field \"" - + target.getOneofFieldDescriptor(oneof).getFullName() - + "\", another member of oneof \"" + oneof.getName() + "\"."); } else { target.setField(field, value); } } - /** - * Skips the next field including the field's name and value. - */ - private void skipField(Tokenizer tokenizer) throws ParseException { + private void mergeAnyFieldValue( + final Tokenizer tokenizer, + final ExtensionRegistry extensionRegistry, + MergeTarget target, + final TextFormatParseInfoTree.Builder parseTreeBuilder, + List unknownFields, + Descriptor anyDescriptor) + throws ParseException { + // Try to parse human readable format of Any in the form: [type_url]: { ... } + StringBuilder typeUrlBuilder = new StringBuilder(); + // Parse the type_url inside []. + while (true) { + typeUrlBuilder.append(tokenizer.consumeIdentifier()); + if (tokenizer.tryConsume("]")) { + break; + } + if (tokenizer.tryConsume("/")) { + typeUrlBuilder.append("/"); + } else if (tokenizer.tryConsume(".")) { + typeUrlBuilder.append("."); + } else { + throw tokenizer.parseExceptionPreviousToken("Expected a valid type URL."); + } + } + tokenizer.tryConsume(":"); + final String anyEndToken; + if (tokenizer.tryConsume("<")) { + anyEndToken = ">"; + } else { + tokenizer.consume("{"); + anyEndToken = "}"; + } + String typeUrl = typeUrlBuilder.toString(); + Descriptor contentType = null; + try { + contentType = typeRegistry.getDescriptorForTypeUrl(typeUrl); + } catch (InvalidProtocolBufferException e) { + throw tokenizer.parseException("Invalid valid type URL. Found: " + typeUrl); + } + if (contentType == null) { + throw tokenizer.parseException( + "Unable to parse Any of type: " + + typeUrl + + ". Please make sure that the TypeRegistry contains the descriptors for the given" + + " types."); + } + Message.Builder contentBuilder = + DynamicMessage.getDefaultInstance(contentType).newBuilderForType(); + MessageReflection.BuilderAdapter contentTarget = + new MessageReflection.BuilderAdapter(contentBuilder); + while (!tokenizer.tryConsume(anyEndToken)) { + mergeField(tokenizer, extensionRegistry, contentTarget, parseTreeBuilder, unknownFields); + } + + target.setField(anyDescriptor.findFieldByName("type_url"), typeUrlBuilder.toString()); + target.setField( + anyDescriptor.findFieldByName("value"), contentBuilder.build().toByteString()); + } + + /** Skips the next field including the field's name and value. */ + private static void skipField(Tokenizer tokenizer) throws ParseException { if (tokenizer.tryConsume("[")) { // Extension name. do { @@ -1755,9 +2226,7 @@ private void skipField(Tokenizer tokenizer) throws ParseException { // start with "{" or "<" which indicates the beginning of a message body. // If there is no ":" or there is a "{" or "<" after ":", this field has // to be a message or the input is ill-formed. - if (tokenizer.tryConsume(":") - && !tokenizer.lookingAt("<") - && !tokenizer.lookingAt("{")) { + if (tokenizer.tryConsume(":") && !tokenizer.lookingAt("<") && !tokenizer.lookingAt("{")) { skipFieldValue(tokenizer); } else { skipFieldMessage(tokenizer); @@ -1770,10 +2239,9 @@ private void skipField(Tokenizer tokenizer) throws ParseException { } /** - * Skips the whole body of a message including the beginning delimiter and - * the ending delimiter. + * Skips the whole body of a message including the beginning delimiter and the ending delimiter. */ - private void skipFieldMessage(Tokenizer tokenizer) throws ParseException { + private static void skipFieldMessage(Tokenizer tokenizer) throws ParseException { final String delimiter; if (tokenizer.tryConsume("<")) { delimiter = ">"; @@ -1787,21 +2255,18 @@ private void skipFieldMessage(Tokenizer tokenizer) throws ParseException { tokenizer.consume(delimiter); } - /** - * Skips a field value. - */ - private void skipFieldValue(Tokenizer tokenizer) throws ParseException { + /** Skips a field value. */ + private static void skipFieldValue(Tokenizer tokenizer) throws ParseException { if (tokenizer.tryConsumeString()) { while (tokenizer.tryConsumeString()) {} return; } - if (!tokenizer.tryConsumeIdentifier() // includes enum & boolean - && !tokenizer.tryConsumeInt64() // includes int32 - && !tokenizer.tryConsumeUInt64() // includes uint32 + if (!tokenizer.tryConsumeIdentifier() // includes enum & boolean + && !tokenizer.tryConsumeInt64() // includes int32 + && !tokenizer.tryConsumeUInt64() // includes uint32 && !tokenizer.tryConsumeDouble() && !tokenizer.tryConsumeFloat()) { - throw tokenizer.parseException( - "Invalid field value: " + tokenizer.currentToken); + throw tokenizer.parseException("Invalid field value: " + tokenizer.currentToken); } } } @@ -1813,28 +2278,23 @@ private void skipFieldValue(Tokenizer tokenizer) throws ParseException { // them. /** - * Escapes bytes in the format used in protocol buffer text format, which - * is the same as the format used for C string literals. All bytes - * that are not printable 7-bit ASCII characters are escaped, as well as - * backslash, single-quote, and double-quote characters. Characters for - * which no defined short-hand escape sequence is defined will be escaped - * using 3-digit octal sequences. + * Escapes bytes in the format used in protocol buffer text format, which is the same as the + * format used for C string literals. All bytes that are not printable 7-bit ASCII characters are + * escaped, as well as backslash, single-quote, and double-quote characters. Characters for which + * no defined short-hand escape sequence is defined will be escaped using 3-digit octal sequences. */ public static String escapeBytes(ByteString input) { return TextFormatEscaper.escapeBytes(input); } - /** - * Like {@link #escapeBytes(ByteString)}, but used for byte array. - */ + /** Like {@link #escapeBytes(ByteString)}, but used for byte array. */ public static String escapeBytes(byte[] input) { return TextFormatEscaper.escapeBytes(input); } /** - * Un-escape a byte sequence as escaped using - * {@link #escapeBytes(ByteString)}. Two-digit hex escapes (starting with - * "\x") are also recognized. + * Un-escape a byte sequence as escaped using {@link #escapeBytes(ByteString)}. Two-digit hex + * escapes (starting with "\x") are also recognized. */ public static ByteString unescapeBytes(final CharSequence charString) throws InvalidEscapeSequenceException { @@ -1870,16 +2330,36 @@ public static ByteString unescapeBytes(final CharSequence charString) result[pos++] = (byte) code; } else { switch (c) { - case 'a' : result[pos++] = 0x07; break; - case 'b' : result[pos++] = '\b'; break; - case 'f' : result[pos++] = '\f'; break; - case 'n' : result[pos++] = '\n'; break; - case 'r' : result[pos++] = '\r'; break; - case 't' : result[pos++] = '\t'; break; - case 'v' : result[pos++] = 0x0b; break; - case '\\': result[pos++] = '\\'; break; - case '\'': result[pos++] = '\''; break; - case '"' : result[pos++] = '\"'; break; + case 'a': + result[pos++] = 0x07; + break; + case 'b': + result[pos++] = '\b'; + break; + case 'f': + result[pos++] = '\f'; + break; + case 'n': + result[pos++] = '\n'; + break; + case 'r': + result[pos++] = '\r'; + break; + case 't': + result[pos++] = '\t'; + break; + case 'v': + result[pos++] = 0x0b; + break; + case '\\': + result[pos++] = '\\'; + break; + case '\'': + result[pos++] = '\''; + break; + case '"': + result[pos++] = '\"'; + break; case 'x': // hex escape @@ -1898,6 +2378,73 @@ public static ByteString unescapeBytes(final CharSequence charString) result[pos++] = (byte) code; break; + case 'u': + // Unicode escape + ++i; + if (i + 3 < input.size() + && isHex(input.byteAt(i)) + && isHex(input.byteAt(i + 1)) + && isHex(input.byteAt(i + 2)) + && isHex(input.byteAt(i + 3))) { + char ch = + (char) + (digitValue(input.byteAt(i)) << 12 + | digitValue(input.byteAt(i + 1)) << 8 + | digitValue(input.byteAt(i + 2)) << 4 + | digitValue(input.byteAt(i + 3))); + if (Character.isSurrogate(ch)) { + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\u' refers to a surrogate"); + } + byte[] chUtf8 = Character.toString(ch).getBytes(UTF_8); + System.arraycopy(chUtf8, 0, result, pos, chUtf8.length); + pos += chUtf8.length; + i += 3; + } else { + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\u' with too few hex chars"); + } + break; + + case 'U': + // Unicode escape + ++i; + if (i + 7 >= input.size()) { + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\U' with too few hex chars"); + } + int codepoint = 0; + for (int offset = i; offset < i + 8; offset++) { + byte b = input.byteAt(offset); + if (!isHex(b)) { + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\U' with too few hex chars"); + } + codepoint = (codepoint << 4) | digitValue(b); + } + if (!Character.isValidCodePoint(codepoint)) { + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\U" + + input.substring(i, i + 8).toStringUtf8() + + "' is not a valid code point value"); + } + Character.UnicodeBlock unicodeBlock = Character.UnicodeBlock.of(codepoint); + if (unicodeBlock.equals(Character.UnicodeBlock.LOW_SURROGATES) + || unicodeBlock.equals(Character.UnicodeBlock.HIGH_SURROGATES) + || unicodeBlock.equals(Character.UnicodeBlock.HIGH_PRIVATE_USE_SURROGATES)) { + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\U" + + input.substring(i, i + 8).toStringUtf8() + + "' refers to a surrogate code unit"); + } + int[] codepoints = new int[1]; + codepoints[0] = codepoint; + byte[] chUtf8 = new String(codepoints, 0, 1).getBytes(UTF_8); + System.arraycopy(chUtf8, 0, result, pos, chUtf8.length); + pos += chUtf8.length; + i += 7; + break; + default: throw new InvalidEscapeSequenceException( "Invalid escape sequence: '\\" + (char) c + '\''); @@ -1913,13 +2460,13 @@ public static ByteString unescapeBytes(final CharSequence charString) } return result.length == pos - ? ByteString.wrap(result) // This reference has not been out of our control. + ? ByteString.wrap(result) // This reference has not been out of our control. : ByteString.copyFrom(result, 0, pos); } /** - * Thrown by {@link TextFormat#unescapeBytes} and - * {@link TextFormat#unescapeText} when an invalid escape sequence is seen. + * Thrown by {@link TextFormat#unescapeBytes} and {@link TextFormat#unescapeText} when an invalid + * escape sequence is seen. */ public static class InvalidEscapeSequenceException extends IOException { private static final long serialVersionUID = -8164033650142593304L; @@ -1930,27 +2477,24 @@ public static class InvalidEscapeSequenceException extends IOException { } /** - * Like {@link #escapeBytes(ByteString)}, but escapes a text string. - * Non-ASCII characters are first encoded as UTF-8, then each byte is escaped - * individually as a 3-digit octal escape. Yes, it's weird. + * Like {@link #escapeBytes(ByteString)}, but escapes a text string. Non-ASCII characters are + * first encoded as UTF-8, then each byte is escaped individually as a 3-digit octal escape. Yes, + * it's weird. */ static String escapeText(final String input) { return escapeBytes(ByteString.copyFromUtf8(input)); } - /** - * Escape double quotes and backslashes in a String for unicode output of a message. - */ + /** Escape double quotes and backslashes in a String for emittingUnicode output of a message. */ public static String escapeDoubleQuotesAndBackslashes(final String input) { return TextFormatEscaper.escapeDoubleQuotesAndBackslashes(input); } /** - * Un-escape a text string as escaped using {@link #escapeText(String)}. - * Two-digit hex escapes (starting with "\x") are also recognized. + * Un-escape a text string as escaped using {@link #escapeText(String)}. Two-digit hex escapes + * (starting with "\x") are also recognized. */ - static String unescapeText(final String input) - throws InvalidEscapeSequenceException { + static String unescapeText(final String input) throws InvalidEscapeSequenceException { return unescapeBytes(input).toStringUtf8(); } @@ -1961,15 +2505,12 @@ private static boolean isOctal(final byte c) { /** Is this a hex digit? */ private static boolean isHex(final byte c) { - return ('0' <= c && c <= '9') - || ('a' <= c && c <= 'f') - || ('A' <= c && c <= 'F'); + return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); } /** - * Interpret a character as a digit (in any base up to 36) and return the - * numeric value. This is like {@code Character.digit()} but we don't accept - * non-ASCII digits. + * Interpret a character as a digit (in any base up to 36) and return the numeric value. This is + * like {@code Character.digit()} but we don't accept non-ASCII digits. */ private static int digitValue(final byte c) { if ('0' <= c && c <= '9') { @@ -1982,49 +2523,45 @@ private static int digitValue(final byte c) { } /** - * Parse a 32-bit signed integer from the text. Unlike the Java standard - * {@code Integer.parseInt()}, this function recognizes the prefixes "0x" - * and "0" to signify hexadecimal and octal numbers, respectively. + * Parse a 32-bit signed integer from the text. Unlike the Java standard {@code + * Integer.parseInt()}, this function recognizes the prefixes "0x" and "0" to signify hexadecimal + * and octal numbers, respectively. */ static int parseInt32(final String text) throws NumberFormatException { return (int) parseInteger(text, true, false); } /** - * Parse a 32-bit unsigned integer from the text. Unlike the Java standard - * {@code Integer.parseInt()}, this function recognizes the prefixes "0x" - * and "0" to signify hexadecimal and octal numbers, respectively. The - * result is coerced to a (signed) {@code int} when returned since Java has - * no unsigned integer type. + * Parse a 32-bit unsigned integer from the text. Unlike the Java standard {@code + * Integer.parseInt()}, this function recognizes the prefixes "0x" and "0" to signify hexadecimal + * and octal numbers, respectively. The result is coerced to a (signed) {@code int} when returned + * since Java has no unsigned integer type. */ static int parseUInt32(final String text) throws NumberFormatException { return (int) parseInteger(text, false, false); } /** - * Parse a 64-bit signed integer from the text. Unlike the Java standard - * {@code Integer.parseInt()}, this function recognizes the prefixes "0x" - * and "0" to signify hexadecimal and octal numbers, respectively. + * Parse a 64-bit signed integer from the text. Unlike the Java standard {@code + * Integer.parseInt()}, this function recognizes the prefixes "0x" and "0" to signify hexadecimal + * and octal numbers, respectively. */ static long parseInt64(final String text) throws NumberFormatException { return parseInteger(text, true, true); } /** - * Parse a 64-bit unsigned integer from the text. Unlike the Java standard - * {@code Integer.parseInt()}, this function recognizes the prefixes "0x" - * and "0" to signify hexadecimal and octal numbers, respectively. The - * result is coerced to a (signed) {@code long} when returned since Java has - * no unsigned long type. + * Parse a 64-bit unsigned integer from the text. Unlike the Java standard {@code + * Integer.parseInt()}, this function recognizes the prefixes "0x" and "0" to signify hexadecimal + * and octal numbers, respectively. The result is coerced to a (signed) {@code long} when returned + * since Java has no unsigned long type. */ static long parseUInt64(final String text) throws NumberFormatException { return parseInteger(text, false, true); } - private static long parseInteger(final String text, - final boolean isSigned, - final boolean isLong) - throws NumberFormatException { + private static long parseInteger(final String text, final boolean isSigned, final boolean isLong) + throws NumberFormatException { int pos = 0; boolean negative = false; @@ -2061,12 +2598,12 @@ private static long parseInteger(final String text, if (isSigned) { if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) { throw new NumberFormatException( - "Number out of range for 32-bit signed integer: " + text); + "Number out of range for 32-bit signed integer: " + text); } } else { if (result >= (1L << 32) || result < 0) { throw new NumberFormatException( - "Number out of range for 32-bit unsigned integer: " + text); + "Number out of range for 32-bit unsigned integer: " + text); } } } @@ -2081,24 +2618,24 @@ private static long parseInteger(final String text, if (isSigned) { if (bigValue.bitLength() > 31) { throw new NumberFormatException( - "Number out of range for 32-bit signed integer: " + text); + "Number out of range for 32-bit signed integer: " + text); } } else { if (bigValue.bitLength() > 32) { throw new NumberFormatException( - "Number out of range for 32-bit unsigned integer: " + text); + "Number out of range for 32-bit unsigned integer: " + text); } } } else { if (isSigned) { if (bigValue.bitLength() > 63) { throw new NumberFormatException( - "Number out of range for 64-bit signed integer: " + text); + "Number out of range for 64-bit signed integer: " + text); } } else { if (bigValue.bitLength() > 64) { throw new NumberFormatException( - "Number out of range for 64-bit unsigned integer: " + text); + "Number out of range for 64-bit unsigned integer: " + text); } } } diff --git a/java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java b/java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java index da9ceadd16858..2501ec936c631 100644 --- a/java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java +++ b/java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java @@ -30,41 +30,58 @@ package com.google.protobuf; -/** - * Provide text format escaping support for proto2 instances. - */ +/** Provide text format escaping support for proto2 instances. */ final class TextFormatEscaper { private TextFormatEscaper() {} private interface ByteSequence { int size(); + byte byteAt(int offset); } /** - * Escapes bytes in the format used in protocol buffer text format, which - * is the same as the format used for C string literals. All bytes - * that are not printable 7-bit ASCII characters are escaped, as well as - * backslash, single-quote, and double-quote characters. Characters for - * which no defined short-hand escape sequence is defined will be escaped - * using 3-digit octal sequences. + * Escapes bytes in the format used in protocol buffer text format, which is the same as the + * format used for C string literals. All bytes that are not printable 7-bit ASCII characters are + * escaped, as well as backslash, single-quote, and double-quote characters. Characters for which + * no defined short-hand escape sequence is defined will be escaped using 3-digit octal sequences. */ static String escapeBytes(final ByteSequence input) { final StringBuilder builder = new StringBuilder(input.size()); for (int i = 0; i < input.size(); i++) { final byte b = input.byteAt(i); switch (b) { - // Java does not recognize \a or \v, apparently. - case 0x07: builder.append("\\a"); break; - case '\b': builder.append("\\b"); break; - case '\f': builder.append("\\f"); break; - case '\n': builder.append("\\n"); break; - case '\r': builder.append("\\r"); break; - case '\t': builder.append("\\t"); break; - case 0x0b: builder.append("\\v"); break; - case '\\': builder.append("\\\\"); break; - case '\'': builder.append("\\\'"); break; - case '"' : builder.append("\\\""); break; + // Java does not recognize \a or \v, apparently. + case 0x07: + builder.append("\\a"); + break; + case '\b': + builder.append("\\b"); + break; + case '\f': + builder.append("\\f"); + break; + case '\n': + builder.append("\\n"); + break; + case '\r': + builder.append("\\r"); + break; + case '\t': + builder.append("\\t"); + break; + case 0x0b: + builder.append("\\v"); + break; + case '\\': + builder.append("\\\\"); + break; + case '\'': + builder.append("\\\'"); + break; + case '"': + builder.append("\\\""); + break; default: // Only ASCII characters between 0x20 (space) and 0x7e (tilde) are // printable. Other byte values must be escaped. @@ -83,54 +100,52 @@ static String escapeBytes(final ByteSequence input) { } /** - * Escapes bytes in the format used in protocol buffer text format, which - * is the same as the format used for C string literals. All bytes - * that are not printable 7-bit ASCII characters are escaped, as well as - * backslash, single-quote, and double-quote characters. Characters for - * which no defined short-hand escape sequence is defined will be escaped - * using 3-digit octal sequences. + * Escapes bytes in the format used in protocol buffer text format, which is the same as the + * format used for C string literals. All bytes that are not printable 7-bit ASCII characters are + * escaped, as well as backslash, single-quote, and double-quote characters. Characters for which + * no defined short-hand escape sequence is defined will be escaped using 3-digit octal sequences. */ static String escapeBytes(final ByteString input) { - return escapeBytes(new ByteSequence() { - @Override - public int size() { - return input.size(); - } - @Override - public byte byteAt(int offset) { - return input.byteAt(offset); - } - }); + return escapeBytes( + new ByteSequence() { + @Override + public int size() { + return input.size(); + } + + @Override + public byte byteAt(int offset) { + return input.byteAt(offset); + } + }); } - /** - * Like {@link #escapeBytes(ByteString)}, but used for byte array. - */ + /** Like {@link #escapeBytes(ByteString)}, but used for byte array. */ static String escapeBytes(final byte[] input) { - return escapeBytes(new ByteSequence() { - @Override - public int size() { - return input.length; - } - @Override - public byte byteAt(int offset) { - return input[offset]; - } - }); + return escapeBytes( + new ByteSequence() { + @Override + public int size() { + return input.length; + } + + @Override + public byte byteAt(int offset) { + return input[offset]; + } + }); } /** - * Like {@link #escapeBytes(ByteString)}, but escapes a text string. - * Non-ASCII characters are first encoded as UTF-8, then each byte is escaped - * individually as a 3-digit octal escape. Yes, it's weird. + * Like {@link #escapeBytes(ByteString)}, but escapes a text string. Non-ASCII characters are + * first encoded as UTF-8, then each byte is escaped individually as a 3-digit octal escape. Yes, + * it's weird. */ static String escapeText(final String input) { return escapeBytes(ByteString.copyFromUtf8(input)); } - /** - * Escape double quotes and backslashes in a String for unicode output of a message. - */ + /** Escape double quotes and backslashes in a String for unicode output of a message. */ static String escapeDoubleQuotesAndBackslashes(final String input) { return input.replace("\\", "\\\\").replace("\"", "\\\""); } diff --git a/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java b/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java index 0127ce92a3f49..6ce9f783ac246 100644 --- a/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java +++ b/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java @@ -31,7 +31,6 @@ package com.google.protobuf; import com.google.protobuf.Descriptors.FieldDescriptor; - import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -39,14 +38,12 @@ import java.util.Map; import java.util.Map.Entry; - /** * Data structure which is populated with the locations of each field value parsed from the text. * - *

The locations of primary fields values are retrieved by {@code getLocation} or - * {@code getLocations}. The locations of sub message values are within nested - * {@code TextFormatParseInfoTree}s and are retrieve by {@code getNestedTree} or - * {@code getNestedTrees}. + *

The locations of primary fields values are retrieved by {@code getLocation} or {@code + * getLocations}. The locations of sub message values are within nested {@code + * TextFormatParseInfoTree}s and are retrieve by {@code getNestedTree} or {@code getNestedTrees}. * *

The {@code TextFormatParseInfoTree} is created by a Builder. */ @@ -90,13 +87,13 @@ private TextFormatParseInfoTree( this.subtreesFromField = Collections.unmodifiableMap(subs); } - /** - * Retrieve all the locations of a field. - * - * @param fieldDescriptor the the @{link FieldDescriptor} of the desired field - * @return a list of the locations of values of the field. If there are not values - * or the field doesn't exist, an empty list is returned. - */ + /** + * Retrieve all the locations of a field. + * + * @param fieldDescriptor the @{link FieldDescriptor} of the desired field + * @return a list of the locations of values of the field. If there are not values or the field + * doesn't exist, an empty list is returned. + */ public List getLocations(final FieldDescriptor fieldDescriptor) { List result = locationsFromField.get(fieldDescriptor); return (result == null) ? Collections.emptyList() : result; @@ -134,7 +131,7 @@ public List getNestedTrees(final FieldDescriptor fieldD * @param fieldDescriptor the @{link FieldDescriptor} of the desired sub message * @param index the index of message value. * @return the {@code ParseInfoTree} of the message value. {@code null} is returned if the field - * doesn't exist or the index is out of range. + * doesn't exist or the index is out of range. * @throws IllegalArgumentException if index is out of range */ public TextFormatParseInfoTree getNestedTree(final FieldDescriptor fieldDescriptor, int index) { @@ -151,16 +148,16 @@ public static Builder builder() { } private static T getFromList(List list, int index, FieldDescriptor fieldDescriptor) { - if (index >= list.size() || index < 0) { - throw new IllegalArgumentException(String.format("Illegal index field: %s, index %d", - fieldDescriptor == null ? "" : fieldDescriptor.getName(), index)); + if (index >= list.size() || index < 0) { + throw new IllegalArgumentException( + String.format( + "Illegal index field: %s, index %d", + fieldDescriptor == null ? "" : fieldDescriptor.getName(), index)); } return list.get(index); } - /** - * Builder for a {@link TextFormatParseInfoTree}. - */ + /** Builder for a {@link TextFormatParseInfoTree}. */ public static class Builder { private Map> locationsFromField; @@ -169,9 +166,7 @@ public static class Builder { // sub message location information. private Map> subtreeBuildersFromField; - /** - * Create a root level {@ParseInfoTree} builder. - */ + /** Create a root level {@ParseInfoTree} builder. */ private Builder() { locationsFromField = new HashMap>(); subtreeBuildersFromField = new HashMap>(); diff --git a/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java b/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java index cce286e10fb49..eebfb1b54580f 100644 --- a/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java +++ b/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java @@ -39,9 +39,7 @@ */ public final class TextFormatParseLocation { - /** - * The empty location. - */ + /** The empty location. */ public static final TextFormatParseLocation EMPTY = new TextFormatParseLocation(-1, -1); /** @@ -92,8 +90,7 @@ public boolean equals(Object o) { return false; } TextFormatParseLocation that = (TextFormatParseLocation) o; - return (this.line == that.getLine()) - && (this.column == that.getColumn()); + return (this.line == that.getLine()) && (this.column == that.getColumn()); } @Override diff --git a/java/core/src/main/java/com/google/protobuf/TypeRegistry.java b/java/core/src/main/java/com/google/protobuf/TypeRegistry.java new file mode 100644 index 0000000000000..422ff1f870fc5 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/TypeRegistry.java @@ -0,0 +1,159 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.FileDescriptor; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.logging.Logger; + +/** + * A TypeRegistry is used to resolve Any messages. You must provide a TypeRegistry containing all + * message types used in Any message fields. + */ +public class TypeRegistry { + private static final Logger logger = Logger.getLogger(TypeRegistry.class.getName()); + + private static class EmptyTypeRegistryHolder { + private static final TypeRegistry EMPTY = + new TypeRegistry(Collections.emptyMap()); + } + + public static TypeRegistry getEmptyTypeRegistry() { + return EmptyTypeRegistryHolder.EMPTY; + } + + + public static Builder newBuilder() { + return new Builder(); + } + + /** + * Find a type by its full name. Returns null if it cannot be found in this {@link TypeRegistry}. + */ + public Descriptor find(String name) { + return types.get(name); + } + + /** + * Find a type by its typeUrl. Returns null if it cannot be found in this {@link TypeRegistry}. + */ + public final Descriptor getDescriptorForTypeUrl(String typeUrl) + throws InvalidProtocolBufferException { + return find(getTypeName(typeUrl)); + } + + private final Map types; + + TypeRegistry(Map types) { + this.types = types; + } + + private static String getTypeName(String typeUrl) throws InvalidProtocolBufferException { + String[] parts = typeUrl.split("/"); + if (parts.length == 1) { + throw new InvalidProtocolBufferException("Invalid type url found: " + typeUrl); + } + return parts[parts.length - 1]; + } + + /** A Builder is used to build {@link TypeRegistry}. */ + public static final class Builder { + private Builder() {} + + /** + * Adds a message type and all types defined in the same .proto file as well as all transitively + * imported .proto files to this {@link Builder}. + */ + public Builder add(Descriptor messageType) { + if (types == null) { + throw new IllegalStateException("A TypeRegistry.Builder can only be used once."); + } + addFile(messageType.getFile()); + return this; + } + + /** + * Adds message types and all types defined in the same .proto file as well as all transitively + * imported .proto files to this {@link Builder}. + */ + public Builder add(Iterable messageTypes) { + if (types == null) { + throw new IllegalStateException("A TypeRegistry.Builder can only be used once."); + } + for (Descriptor type : messageTypes) { + addFile(type.getFile()); + } + return this; + } + + /** Builds a {@link TypeRegistry}. This method can only be called once for one Builder. */ + public TypeRegistry build() { + TypeRegistry result = new TypeRegistry(types); + // Make sure the built {@link TypeRegistry} is immutable. + types = null; + return result; + } + + private void addFile(FileDescriptor file) { + // Skip the file if it's already added. + if (!files.add(file.getFullName())) { + return; + } + for (FileDescriptor dependency : file.getDependencies()) { + addFile(dependency); + } + for (Descriptor message : file.getMessageTypes()) { + addMessage(message); + } + } + + private void addMessage(Descriptor message) { + for (Descriptor nestedType : message.getNestedTypes()) { + addMessage(nestedType); + } + + if (types.containsKey(message.getFullName())) { + logger.warning("Type " + message.getFullName() + " is added multiple times."); + return; + } + + types.put(message.getFullName(), message); + } + + private final Set files = new HashSet<>(); + private Map types = new HashMap<>(); + } +} diff --git a/java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java b/java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java index 5714c063a97f1..c633a4e8902eb 100644 --- a/java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java +++ b/java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java @@ -34,15 +34,13 @@ import java.util.List; /** - * Thrown when attempting to build a protocol message that is missing required - * fields. This is a {@code RuntimeException} because it normally represents - * a programming error: it happens when some code which constructs a message - * fails to set all the fields. {@code parseFrom()} methods do not - * throw this; they throw an {@link InvalidProtocolBufferException} if - * required fields are missing, because it is not a programming error to - * receive an incomplete message. In other words, - * {@code UninitializedMessageException} should never be thrown by correct - * code, but {@code InvalidProtocolBufferException} might be. + * Thrown when attempting to build a protocol message that is missing required fields. This is a + * {@code RuntimeException} because it normally represents a programming error: it happens when some + * code which constructs a message fails to set all the fields. {@code parseFrom()} methods do + * not throw this; they throw an {@link InvalidProtocolBufferException} if required fields are + * missing, because it is not a programming error to receive an incomplete message. In other words, + * {@code UninitializedMessageException} should never be thrown by correct code, but {@code + * InvalidProtocolBufferException} might be. * * @author kenton@google.com Kenton Varda */ @@ -50,8 +48,9 @@ public class UninitializedMessageException extends RuntimeException { private static final long serialVersionUID = -7466929953374883507L; public UninitializedMessageException(final MessageLite message) { - super("Message was missing required fields. (Lite runtime could not " + - "determine which fields were missing)."); + super( + "Message was missing required fields. (Lite runtime could not " + + "determine which fields were missing)."); missingFields = null; } @@ -63,19 +62,18 @@ public UninitializedMessageException(final List missingFields) { private final List missingFields; /** - * Get a list of human-readable names of required fields missing from this - * message. Each name is a full path to a field, e.g. "foo.bar[5].baz". - * Returns null if the lite runtime was used, since it lacks the ability to - * find missing fields. + * Get a list of human-readable names of required fields missing from this message. Each name is a + * full path to a field, e.g. "foo.bar[5].baz". Returns null if the lite runtime was used, since + * it lacks the ability to find missing fields. */ public List getMissingFields() { return Collections.unmodifiableList(missingFields); } /** - * Converts this exception to an {@link InvalidProtocolBufferException}. - * When a parsed message is missing required fields, this should be thrown - * instead of {@code UninitializedMessageException}. + * Converts this exception to an {@link InvalidProtocolBufferException}. When a parsed message is + * missing required fields, this should be thrown instead of {@code + * UninitializedMessageException}. */ public InvalidProtocolBufferException asInvalidProtocolBufferException() { return new InvalidProtocolBufferException(getMessage()); @@ -83,8 +81,7 @@ public InvalidProtocolBufferException asInvalidProtocolBufferException() { /** Construct the description string for this exception. */ private static String buildDescription(final List missingFields) { - final StringBuilder description = - new StringBuilder("Message missing required fields: "); + final StringBuilder description = new StringBuilder("Message missing required fields: "); boolean first = true; for (final String field : missingFields) { if (first) { diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java new file mode 100644 index 0000000000000..e736d5ce9cdca --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java @@ -0,0 +1,133 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; + +@ExperimentalApi +abstract class UnknownFieldSchema { + + /** Whether unknown fields should be dropped. */ + abstract boolean shouldDiscardUnknownFields(Reader reader); + + /** Adds a varint value to the unknown fields. */ + abstract void addVarint(B fields, int number, long value); + + /** Adds a fixed32 value to the unknown fields. */ + abstract void addFixed32(B fields, int number, int value); + + /** Adds a fixed64 value to the unknown fields. */ + abstract void addFixed64(B fields, int number, long value); + + /** Adds a length delimited value to the unknown fields. */ + abstract void addLengthDelimited(B fields, int number, ByteString value); + + /** Adds a group value to the unknown fields. */ + abstract void addGroup(B fields, int number, T subFieldSet); + + /** Create a new builder for unknown fields. */ + abstract B newBuilder(); + + /** Returns an immutable instance of the field container. */ + abstract T toImmutable(B fields); + + /** + * Sets the unknown fields into the message. Caller must take care of the mutability of the + * fields. + */ + abstract void setToMessage(Object message, T fields); + + /** Get the unknown fields from the message. */ + abstract T getFromMessage(Object message); + + /** Returns a builder for unknown fields in the message. */ + abstract B getBuilderFromMessage(Object message); + + /** Sets an unknown field builder into the message. */ + abstract void setBuilderToMessage(Object message, B builder); + + /** Marks unknown fields as immutable. */ + abstract void makeImmutable(Object message); + + /** Merges one field into the unknown fields. */ + final boolean mergeOneFieldFrom(B unknownFields, Reader reader) throws IOException { + int tag = reader.getTag(); + int fieldNumber = WireFormat.getTagFieldNumber(tag); + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + addVarint(unknownFields, fieldNumber, reader.readInt64()); + return true; + case WireFormat.WIRETYPE_FIXED32: + addFixed32(unknownFields, fieldNumber, reader.readFixed32()); + return true; + case WireFormat.WIRETYPE_FIXED64: + addFixed64(unknownFields, fieldNumber, reader.readFixed64()); + return true; + case WireFormat.WIRETYPE_LENGTH_DELIMITED: + addLengthDelimited(unknownFields, fieldNumber, reader.readBytes()); + return true; + case WireFormat.WIRETYPE_START_GROUP: + final B subFields = newBuilder(); + int endGroupTag = WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP); + mergeFrom(subFields, reader); + if (endGroupTag != reader.getTag()) { + throw InvalidProtocolBufferException.invalidEndTag(); + } + addGroup(unknownFields, fieldNumber, toImmutable(subFields)); + return true; + case WireFormat.WIRETYPE_END_GROUP: + return false; + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + + final void mergeFrom(B unknownFields, Reader reader) throws IOException { + while (true) { + if (reader.getFieldNumber() == Reader.READ_DONE + || !mergeOneFieldFrom(unknownFields, reader)) { + break; + } + } + } + + abstract void writeTo(T unknownFields, Writer writer) throws IOException; + + abstract void writeAsMessageSetTo(T unknownFields, Writer writer) throws IOException; + + /** Merges {@code source} into {@code destination} and returns the merged instance. */ + abstract T merge(T destination, T source); + + /** Get the serialized size for message set serialization. */ + abstract int getSerializedSizeAsMessageSet(T message); + + abstract int getSerializedSize(T unknowns); +} diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java index 37d6463342eb4..ba2f9df08e675 100644 --- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java +++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java @@ -43,14 +43,13 @@ import java.util.TreeMap; /** - * {@code UnknownFieldSet} is used to keep track of fields which were seen when - * parsing a protocol message but whose field numbers or types are unrecognized. - * This most frequently occurs when new fields are added to a message type - * and then messages containing those fields are read by old software that was - * compiled before the new types were added. + * {@code UnknownFieldSet} is used to keep track of fields which were seen when parsing a protocol + * message but whose field numbers or types are unrecognized. This most frequently occurs when new + * fields are added to a message type and then messages containing those fields are read by old + * software that was compiled before the new types were added. * - *

Every {@link Message} contains an {@code UnknownFieldSet} (and every - * {@link Message.Builder} contains an {@link Builder}). + *

Every {@link Message} contains an {@code UnknownFieldSet} (and every {@link Message.Builder} + * contains an {@link Builder}). * *

Most users will never need to use this class. * @@ -60,6 +59,7 @@ public final class UnknownFieldSet implements MessageLite { private UnknownFieldSet() { fields = null; + fieldsDescending = null; } /** Create a new {@link Builder}. */ @@ -67,10 +67,7 @@ public static Builder newBuilder() { return Builder.create(); } - /** - * Create a new {@link Builder} and initialize it to be a copy - * of {@code copyFrom}. - */ + /** Create a new {@link Builder} and initialize it to be a copy of {@code copyFrom}. */ public static Builder newBuilder(final UnknownFieldSet copyFrom) { return newBuilder().mergeFrom(copyFrom); } @@ -79,32 +76,36 @@ public static Builder newBuilder(final UnknownFieldSet copyFrom) { public static UnknownFieldSet getDefaultInstance() { return defaultInstance; } + @Override public UnknownFieldSet getDefaultInstanceForType() { return defaultInstance; } + private static final UnknownFieldSet defaultInstance = - new UnknownFieldSet(Collections.emptyMap(), - Collections.emptyMap()); + new UnknownFieldSet( + Collections.emptyMap(), Collections.emptyMap()); /** - * Construct an {@code UnknownFieldSet} around the given map. The map is - * expected to be immutable. + * Construct an {@code UnknownFieldSet} around the given map. The map is expected to be immutable. */ - UnknownFieldSet(final Map fields, - final Map fieldsDescending) { + UnknownFieldSet(final Map fields, final Map fieldsDescending) { this.fields = fields; + this.fieldsDescending = fieldsDescending; } + private final Map fields; + /** A copy of {@link #fields} who's iterator order is reversed. */ + private final Map fieldsDescending; + @Override public boolean equals(final Object other) { if (this == other) { return true; } - return (other instanceof UnknownFieldSet) && - fields.equals(((UnknownFieldSet) other).fields); + return (other instanceof UnknownFieldSet) && fields.equals(((UnknownFieldSet) other).fields); } @Override @@ -122,10 +123,7 @@ public boolean hasField(final int number) { return fields.containsKey(number); } - /** - * Get a field by number. Returns an empty field if not present. Never - * returns {@code null}. - */ + /** Get a field by number. Returns an empty field if not present. Never returns {@code null}. */ public Field getField(final int number) { final Field result = fields.get(number); return (result == null) ? Field.getDefaultInstance() : result; @@ -141,36 +139,33 @@ public void writeTo(final CodedOutputStream output) throws IOException { } /** - * Converts the set to a string in protocol buffer text format. This is - * just a trivial wrapper around - * {@link TextFormat#printToString(UnknownFieldSet)}. + * Converts the set to a string in protocol buffer text format. This is just a trivial wrapper + * around {@link TextFormat.Printer#printToString(UnknownFieldSet)}. */ @Override public String toString() { - return TextFormat.printToString(this); + return TextFormat.printer().printToString(this); } /** - * Serializes the message to a {@code ByteString} and returns it. This is - * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}. + * Serializes the message to a {@code ByteString} and returns it. This is just a trivial wrapper + * around {@link #writeTo(CodedOutputStream)}. */ @Override public ByteString toByteString() { try { - final ByteString.CodedBuilder out = - ByteString.newCodedBuilder(getSerializedSize()); + final ByteString.CodedBuilder out = ByteString.newCodedBuilder(getSerializedSize()); writeTo(out.getCodedOutput()); return out.build(); } catch (final IOException e) { throw new RuntimeException( - "Serializing to a ByteString threw an IOException (should " + - "never happen).", e); + "Serializing to a ByteString threw an IOException (should never happen).", e); } } /** - * Serializes the message to a {@code byte} array and returns it. This is - * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}. + * Serializes the message to a {@code byte} array and returns it. This is just a trivial wrapper + * around {@link #writeTo(CodedOutputStream)}. */ @Override public byte[] toByteArray() { @@ -182,14 +177,13 @@ public byte[] toByteArray() { return result; } catch (final IOException e) { throw new RuntimeException( - "Serializing to a byte array threw an IOException " + - "(should never happen).", e); + "Serializing to a byte array threw an IOException (should never happen).", e); } } /** - * Serializes the message and writes it to {@code output}. This is just a - * trivial wrapper around {@link #writeTo(CodedOutputStream)}. + * Serializes the message and writes it to {@code output}. This is just a trivial wrapper around + * {@link #writeTo(CodedOutputStream)}. */ @Override public void writeTo(final OutputStream output) throws IOException { @@ -216,25 +210,48 @@ public int getSerializedSize() { return result; } - /** - * Serializes the set and writes it to {@code output} using - * {@code MessageSet} wire format. - */ - public void writeAsMessageSetTo(final CodedOutputStream output) - throws IOException { + /** Serializes the set and writes it to {@code output} using {@code MessageSet} wire format. */ + public void writeAsMessageSetTo(final CodedOutputStream output) throws IOException { for (final Map.Entry entry : fields.entrySet()) { - entry.getValue().writeAsMessageSetExtensionTo( - entry.getKey(), output); + entry.getValue().writeAsMessageSetExtensionTo(entry.getKey(), output); + } + } + + /** Serializes the set and writes it to {@code writer}. */ + void writeTo(Writer writer) throws IOException { + if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) { + // Write fields in descending order. + for (Map.Entry entry : fieldsDescending.entrySet()) { + entry.getValue().writeTo(entry.getKey(), writer); + } + } else { + // Write fields in ascending order. + for (Map.Entry entry : fields.entrySet()) { + entry.getValue().writeTo(entry.getKey(), writer); + } } } + /** Serializes the set and writes it to {@code writer} using {@code MessageSet} wire format. */ + void writeAsMessageSetTo(final Writer writer) throws IOException { + if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) { + // Write fields in descending order. + for (final Map.Entry entry : fieldsDescending.entrySet()) { + entry.getValue().writeAsMessageSetExtensionTo(entry.getKey(), writer); + } + } else { + // Write fields in ascending order. + for (final Map.Entry entry : fields.entrySet()) { + entry.getValue().writeAsMessageSetExtensionTo(entry.getKey(), writer); + } + } + } /** Get the number of bytes required to encode this set using {@code MessageSet} wire format. */ public int getSerializedSizeAsMessageSet() { int result = 0; for (final Map.Entry entry : fields.entrySet()) { - result += entry.getValue().getSerializedSizeAsMessageSetExtension( - entry.getKey()); + result += entry.getValue().getSerializedSizeAsMessageSetExtension(entry.getKey()); } return result; } @@ -247,8 +264,7 @@ public boolean isInitialized() { } /** Parse an {@code UnknownFieldSet} from the given input stream. */ - public static UnknownFieldSet parseFrom(final CodedInputStream input) - throws IOException { + public static UnknownFieldSet parseFrom(final CodedInputStream input) throws IOException { return newBuilder().mergeFrom(input).build(); } @@ -259,14 +275,12 @@ public static UnknownFieldSet parseFrom(final ByteString data) } /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */ - public static UnknownFieldSet parseFrom(final byte[] data) - throws InvalidProtocolBufferException { + public static UnknownFieldSet parseFrom(final byte[] data) throws InvalidProtocolBufferException { return newBuilder().mergeFrom(data).build(); } /** Parse an {@code UnknownFieldSet} from {@code input} and return it. */ - public static UnknownFieldSet parseFrom(final InputStream input) - throws IOException { + public static UnknownFieldSet parseFrom(final InputStream input) throws IOException { return newBuilder().mergeFrom(input).build(); } @@ -283,12 +297,11 @@ public Builder toBuilder() { /** * Builder for {@link UnknownFieldSet}s. * - *

Note that this class maintains {@link Field.Builder}s for all fields - * in the set. Thus, adding one element to an existing {@link Field} does not - * require making a copy. This is important for efficient parsing of - * unknown repeated fields. However, it implies that {@link Field}s cannot - * be constructed independently, nor can two {@link UnknownFieldSet}s share - * the same {@code Field} object. + *

Note that this class maintains {@link Field.Builder}s for all fields in the set. Thus, + * adding one element to an existing {@link Field} does not require making a copy. This is + * important for efficient parsing of unknown repeated fields. However, it implies that {@link + * Field}s cannot be constructed independently, nor can two {@link UnknownFieldSet}s share the + * same {@code Field} object. * *

Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}. */ @@ -311,8 +324,7 @@ private static Builder create() { } /** - * Get a field builder for the given field number which includes any - * values that already exist. + * Get a field builder for the given field number which includes any values that already exist. */ private Field.Builder getFieldBuilder(final int number) { if (lastField != null) { @@ -338,10 +350,9 @@ private Field.Builder getFieldBuilder(final int number) { /** * Build the {@link UnknownFieldSet} and return it. * - *

Once {@code build()} has been called, the {@code Builder} will no - * longer be usable. Calling any method after {@code build()} will result - * in undefined behavior and can cause a {@code NullPointerException} to be - * thrown. + *

Once {@code build()} has been called, the {@code Builder} will no longer be usable. + * Calling any method after {@code build()} will result in undefined behavior and can cause a + * {@code NullPointerException} to be thrown. */ @Override public UnknownFieldSet build() { @@ -351,6 +362,8 @@ public UnknownFieldSet build() { result = getDefaultInstance(); } else { Map descendingFields = null; + descendingFields = + Collections.unmodifiableMap(((TreeMap) fields).descendingMap()); result = new UnknownFieldSet(Collections.unmodifiableMap(fields), descendingFields); } fields = null; @@ -365,10 +378,11 @@ public UnknownFieldSet buildPartial() { @Override public Builder clone() { - getFieldBuilder(0); // Force lastField to be built. + getFieldBuilder(0); // Force lastField to be built. Map descendingFields = null; - return UnknownFieldSet.newBuilder().mergeFrom( - new UnknownFieldSet(fields, descendingFields)); + descendingFields = + Collections.unmodifiableMap(((TreeMap) fields).descendingMap()); + return UnknownFieldSet.newBuilder().mergeFrom(new UnknownFieldSet(fields, descendingFields)); } @Override @@ -388,7 +402,7 @@ public Builder clear() { reinitialize(); return this; } - + /** Clear fields from the set with a given field number. */ public Builder clearField(final int number) { if (number == 0) { @@ -406,9 +420,8 @@ public Builder clearField(final int number) { } /** - * Merge the fields from {@code other} into this set. If a field number - * exists in both sets, {@code other}'s values for that field will be - * appended to the values in this set. + * Merge the fields from {@code other} into this set. If a field number exists in both sets, + * {@code other}'s values for that field will be appended to the values in this set. */ public Builder mergeFrom(final UnknownFieldSet other) { if (other != getDefaultInstance()) { @@ -420,8 +433,8 @@ public Builder mergeFrom(final UnknownFieldSet other) { } /** - * Add a field to the {@code UnknownFieldSet}. If a field with the same - * number already exists, the two are merged. + * Add a field to the {@code UnknownFieldSet}. If a field with the same number already exists, + * the two are merged. */ public Builder mergeField(final int number, final Field field) { if (number == 0) { @@ -439,9 +452,8 @@ public Builder mergeField(final int number, final Field field) { } /** - * Convenience method for merging a new field containing a single varint - * value. This is used in particular when an unknown enum value is - * encountered. + * Convenience method for merging a new field containing a single varint value. This is used in + * particular when an unknown enum value is encountered. */ public Builder mergeVarintField(final int number, final int value) { if (number == 0) { @@ -451,14 +463,12 @@ public Builder mergeVarintField(final int number, final int value) { return this; } - /** * Convenience method for merging a length-delimited field. * *

For use by generated code only. */ - public Builder mergeLengthDelimitedField( - final int number, final ByteString value) { + public Builder mergeLengthDelimitedField(final int number, final ByteString value) { if (number == 0) { throw new IllegalArgumentException("Zero is not a valid field number."); } @@ -475,8 +485,8 @@ public boolean hasField(final int number) { } /** - * Add a field to the {@code UnknownFieldSet}. If a field with the same - * number already exists, it is removed. + * Add a field to the {@code UnknownFieldSet}. If a field with the same number already exists, + * it is removed. */ public Builder addField(final int number, final Field field) { if (number == 0) { @@ -488,25 +498,22 @@ public Builder addField(final int number, final Field field) { lastFieldNumber = 0; } if (fields.isEmpty()) { - fields = new TreeMap(); + fields = new TreeMap(); } fields.put(number, field); return this; } /** - * Get all present {@code Field}s as an immutable {@code Map}. If more - * fields are added, the changes may or may not be reflected in this map. + * Get all present {@code Field}s as an immutable {@code Map}. If more fields are added, the + * changes may or may not be reflected in this map. */ public Map asMap() { - getFieldBuilder(0); // Force lastField to be built. + getFieldBuilder(0); // Force lastField to be built. return Collections.unmodifiableMap(fields); } - /** - * Parse an entire message from {@code input} and merge its fields into - * this set. - */ + /** Parse an entire message from {@code input} and merge its fields into this set. */ @Override public Builder mergeFrom(final CodedInputStream input) throws IOException { while (true) { @@ -520,11 +527,11 @@ public Builder mergeFrom(final CodedInputStream input) throws IOException { /** * Parse a single field from {@code input} and merge it into this set. + * * @param tag The field's tag number, which was already parsed. * @return {@code false} if the tag is an end group tag. */ - public boolean mergeFieldFrom(final int tag, final CodedInputStream input) - throws IOException { + public boolean mergeFieldFrom(final int tag, final CodedInputStream input) throws IOException { final int number = WireFormat.getTagFieldNumber(tag); switch (WireFormat.getTagWireType(tag)) { case WireFormat.WIRETYPE_VARINT: @@ -538,8 +545,7 @@ public boolean mergeFieldFrom(final int tag, final CodedInputStream input) return true; case WireFormat.WIRETYPE_START_GROUP: final Builder subBuilder = newBuilder(); - input.readGroup(number, subBuilder, - ExtensionRegistry.getEmptyRegistry()); + input.readGroup(number, subBuilder, ExtensionRegistry.getEmptyRegistry()); getFieldBuilder(number).addGroup(subBuilder.build()); return true; case WireFormat.WIRETYPE_END_GROUP: @@ -553,9 +559,8 @@ public boolean mergeFieldFrom(final int tag, final CodedInputStream input) } /** - * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the - * set being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream)}. + * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the set being built. This + * is just a small wrapper around {@link #mergeFrom(CodedInputStream)}. */ @Override public Builder mergeFrom(final ByteString data) throws InvalidProtocolBufferException { @@ -568,15 +573,13 @@ public Builder mergeFrom(final ByteString data) throws InvalidProtocolBufferExce throw e; } catch (final IOException e) { throw new RuntimeException( - "Reading from a ByteString threw an IOException (should " + - "never happen).", e); + "Reading from a ByteString threw an IOException (should never happen).", e); } } /** - * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the - * set being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream)}. + * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the set being built. This + * is just a small wrapper around {@link #mergeFrom(CodedInputStream)}. */ @Override public Builder mergeFrom(final byte[] data) throws InvalidProtocolBufferException { @@ -589,15 +592,13 @@ public Builder mergeFrom(final byte[] data) throws InvalidProtocolBufferExceptio throw e; } catch (final IOException e) { throw new RuntimeException( - "Reading from a byte array threw an IOException (should " + - "never happen).", e); + "Reading from a byte array threw an IOException (should never happen).", e); } } /** - * Parse an {@code UnknownFieldSet} from {@code input} and merge it with the - * set being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream)}. + * Parse an {@code UnknownFieldSet} from {@code input} and merge it with the set being built. + * This is just a small wrapper around {@link #mergeFrom(CodedInputStream)}. */ @Override public Builder mergeFrom(final InputStream input) throws IOException { @@ -643,8 +644,7 @@ public Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistr @Override public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException { try { - final CodedInputStream input = - CodedInputStream.newInstance(data, off, len); + final CodedInputStream input = CodedInputStream.newInstance(data, off, len); mergeFrom(input); input.checkLastTagWas(0); return this; @@ -652,8 +652,7 @@ public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBu throw e; } catch (IOException e) { throw new RuntimeException( - "Reading from a byte array threw an IOException (should " + - "never happen).", e); + "Reading from a byte array threw an IOException (should never happen).", e); } } @@ -698,19 +697,15 @@ public boolean isInitialized() { /** * Represents a single field in an {@code UnknownFieldSet}. * - *

A {@code Field} consists of five lists of values. The lists correspond - * to the five "wire types" used in the protocol buffer binary format. - * The wire type of each field can be determined from the encoded form alone, - * without knowing the field's declared type. So, we are able to parse - * unknown values at least this far and separate them. Normally, only one - * of the five lists will contain any values, since it is impossible to - * define a valid message type that declares two different types for the - * same field number. However, the code is designed to allow for the case - * where the same unknown field number is encountered using multiple different - * wire types. + *

A {@code Field} consists of five lists of values. The lists correspond to the five "wire + * types" used in the protocol buffer binary format. The wire type of each field can be determined + * from the encoded form alone, without knowing the field's declared type. So, we are able to + * parse unknown values at least this far and separate them. Normally, only one of the five lists + * will contain any values, since it is impossible to define a valid message type that declares + * two different types for the same field number. However, the code is designed to allow for the + * case where the same unknown field number is encountered using multiple different wire types. * - *

{@code Field} is an immutable class. To construct one, you must use a - * {@link Builder}. + *

{@code Field} is an immutable class. To construct one, you must use a {@link Builder}. * * @see UnknownFieldSet */ @@ -722,10 +717,7 @@ public static Builder newBuilder() { return Builder.create(); } - /** - * Construct a new {@link Builder} and initialize it to a copy of - * {@code copyFrom}. - */ + /** Construct a new {@link Builder} and initialize it to a copy of {@code copyFrom}. */ public static Builder newBuilder(final Field copyFrom) { return newBuilder().mergeFrom(copyFrom); } @@ -734,26 +726,36 @@ public static Builder newBuilder(final Field copyFrom) { public static Field getDefaultInstance() { return fieldDefaultInstance; } + private static final Field fieldDefaultInstance = newBuilder().build(); /** Get the list of varint values for this field. */ - public List getVarintList() { return varint; } + public List getVarintList() { + return varint; + } /** Get the list of fixed32 values for this field. */ - public List getFixed32List() { return fixed32; } + public List getFixed32List() { + return fixed32; + } /** Get the list of fixed64 values for this field. */ - public List getFixed64List() { return fixed64; } + public List getFixed64List() { + return fixed64; + } /** Get the list of length-delimited values for this field. */ - public List getLengthDelimitedList() { return lengthDelimited; } + public List getLengthDelimitedList() { + return lengthDelimited; + } /** - * Get the list of embedded group values for this field. These are - * represented using {@link UnknownFieldSet}s rather than {@link Message}s - * since the group's type is presumably unknown. + * Get the list of embedded group values for this field. These are represented using {@link + * UnknownFieldSet}s rather than {@link Message}s since the group's type is presumably unknown. */ - public List getGroupList() { return group; } + public List getGroupList() { + return group; + } @Override public boolean equals(final Object other) { @@ -763,8 +765,7 @@ public boolean equals(final Object other) { if (!(other instanceof Field)) { return false; } - return Arrays.equals(getIdentityArray(), - ((Field) other).getIdentityArray()); + return Arrays.equals(getIdentityArray(), ((Field) other).getIdentityArray()); } @Override @@ -772,25 +773,30 @@ public int hashCode() { return Arrays.hashCode(getIdentityArray()); } - /** - * Returns the array of objects to be used to uniquely identify this - * {@link Field} instance. - */ + /** Returns the array of objects to be used to uniquely identify this {@link Field} instance. */ private Object[] getIdentityArray() { - return new Object[] { - varint, - fixed32, - fixed64, - lengthDelimited, - group}; + return new Object[] {varint, fixed32, fixed64, lengthDelimited, group}; } /** - * Serializes the field, including field number, and writes it to - * {@code output}. + * Serializes the message to a {@code ByteString} and returns it. This is just a trivial wrapper + * around {@link #writeTo(int, CodedOutputStream)}. */ - public void writeTo(final int fieldNumber, final CodedOutputStream output) - throws IOException { + public ByteString toByteString(int fieldNumber) { + try { + // TODO(lukes): consider caching serialized size in a volatile long + final ByteString.CodedBuilder out = + ByteString.newCodedBuilder(getSerializedSize(fieldNumber)); + writeTo(fieldNumber, out.getCodedOutput()); + return out.build(); + } catch (IOException e) { + throw new RuntimeException( + "Serializing to a ByteString should never fail with an IOException", e); + } + } + + /** Serializes the field, including field number, and writes it to {@code output}. */ + public void writeTo(final int fieldNumber, final CodedOutputStream output) throws IOException { for (final long value : varint) { output.writeUInt64(fieldNumber, value); } @@ -808,10 +814,7 @@ public void writeTo(final int fieldNumber, final CodedOutputStream output) } } - /** - * Get the number of bytes required to encode this field, including field - * number. - */ + /** Get the number of bytes required to encode this field, including field number. */ public int getSerializedSize(final int fieldNumber) { int result = 0; for (final long value : varint) { @@ -833,18 +836,57 @@ public int getSerializedSize(final int fieldNumber) { } /** - * Serializes the field, including field number, and writes it to - * {@code output}, using {@code MessageSet} wire format. + * Serializes the field, including field number, and writes it to {@code output}, using {@code + * MessageSet} wire format. */ - public void writeAsMessageSetExtensionTo( - final int fieldNumber, - final CodedOutputStream output) + public void writeAsMessageSetExtensionTo(final int fieldNumber, final CodedOutputStream output) throws IOException { for (final ByteString value : lengthDelimited) { output.writeRawMessageSetExtension(fieldNumber, value); } } + /** Serializes the field, including field number, and writes it to {@code writer}. */ + void writeTo(final int fieldNumber, final Writer writer) throws IOException { + writer.writeInt64List(fieldNumber, varint, false); + writer.writeFixed32List(fieldNumber, fixed32, false); + writer.writeFixed64List(fieldNumber, fixed64, false); + writer.writeBytesList(fieldNumber, lengthDelimited); + + if (writer.fieldOrder() == Writer.FieldOrder.ASCENDING) { + for (int i = 0; i < group.size(); i++) { + writer.writeStartGroup(fieldNumber); + group.get(i).writeTo(writer); + writer.writeEndGroup(fieldNumber); + } + } else { + for (int i = group.size() - 1; i >= 0; i--) { + writer.writeEndGroup(fieldNumber); + group.get(i).writeTo(writer); + writer.writeStartGroup(fieldNumber); + } + } + } + + /** + * Serializes the field, including field number, and writes it to {@code writer}, using {@code + * MessageSet} wire format. + */ + private void writeAsMessageSetExtensionTo(final int fieldNumber, final Writer writer) + throws IOException { + if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) { + // Write in descending field order. + ListIterator iter = lengthDelimited.listIterator(lengthDelimited.size()); + while (iter.hasPrevious()) { + writer.writeMessageSetItem(fieldNumber, iter.previous()); + } + } else { + // Write in ascending field order. + for (final ByteString value : lengthDelimited) { + writer.writeMessageSetItem(fieldNumber, value); + } + } + } /** * Get the number of bytes required to encode this field, including field number, using {@code @@ -853,8 +895,7 @@ public void writeAsMessageSetExtensionTo( public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) { int result = 0; for (final ByteString value : lengthDelimited) { - result += CodedOutputStream.computeRawMessageSetExtensionSize( - fieldNumber, value); + result += CodedOutputStream.computeRawMessageSetExtensionSize(fieldNumber, value); } return result; } @@ -883,10 +924,9 @@ private static Builder create() { private Field result; /** - * Build the field. After {@code build()} has been called, the - * {@code Builder} is no longer usable. Calling any other method will - * result in undefined behavior and can cause a - * {@code NullPointerException} to be thrown. + * Build the field. After {@code build()} has been called, the {@code Builder} is no longer + * usable. Calling any other method will result in undefined behavior and can cause a {@code + * NullPointerException} to be thrown. */ public Field build() { if (result.varint == null) { @@ -907,8 +947,7 @@ public Field build() { if (result.lengthDelimited == null) { result.lengthDelimited = Collections.emptyList(); } else { - result.lengthDelimited = - Collections.unmodifiableList(result.lengthDelimited); + result.lengthDelimited = Collections.unmodifiableList(result.lengthDelimited); } if (result.group == null) { result.group = Collections.emptyList(); @@ -928,9 +967,8 @@ public Builder clear() { } /** - * Merge the values in {@code other} into this field. For each list - * of values, {@code other}'s values are append to the ones in this - * field. + * Merge the values in {@code other} into this field. For each list of values, {@code other}'s + * values are append to the ones in this field. */ public Builder mergeFrom(final Field other) { if (!other.varint.isEmpty()) { @@ -1013,9 +1051,7 @@ public Builder addGroup(final UnknownFieldSet value) { } } - /** - * Parser to implement MessageLite interface. - */ + /** Parser to implement MessageLite interface. */ public static final class Parser extends AbstractParser { @Override public UnknownFieldSet parsePartialFrom( @@ -1027,14 +1063,14 @@ public UnknownFieldSet parsePartialFrom( } catch (InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(builder.buildPartial()); } catch (IOException e) { - throw new InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); + throw new InvalidProtocolBufferException(e).setUnfinishedMessage(builder.buildPartial()); } return builder.buildPartial(); } } private static final Parser PARSER = new Parser(); + @Override public final Parser getParserForType() { return PARSER; diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java index d6226fc70cda8..b2cb7be4baef7 100644 --- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java +++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java @@ -34,24 +34,23 @@ import java.util.Arrays; /** - * {@code UnknownFieldSetLite} is used to keep track of fields which were seen - * when parsing a protocol message but whose field numbers or types are - * unrecognized. This most frequently occurs when new fields are added to a - * message type and then messages containing those fields are read by old - * software that was compiled before the new types were added. + * {@code UnknownFieldSetLite} is used to keep track of fields which were seen when parsing a + * protocol message but whose field numbers or types are unrecognized. This most frequently occurs + * when new fields are added to a message type and then messages containing those fields are read by + * old software that was compiled before the new types were added. * *

For use by generated code only. * * @author dweis@google.com (Daniel Weis) */ public final class UnknownFieldSetLite { - + // Arbitrarily chosen. // TODO(dweis): Tune this number? private static final int MIN_CAPACITY = 8; private static final UnknownFieldSetLite DEFAULT_INSTANCE = - new UnknownFieldSetLite(0, new int[0], new Object[0], false /* isMutable */); + new UnknownFieldSetLite(0, new int[0], new Object[0], /* isMutable= */ false); /** * Get an empty {@code UnknownFieldSetLite}. @@ -61,17 +60,15 @@ public final class UnknownFieldSetLite { public static UnknownFieldSetLite getDefaultInstance() { return DEFAULT_INSTANCE; } - - /** - * Returns a new mutable instance. - */ + + /** Returns a new mutable instance. */ static UnknownFieldSetLite newInstance() { return new UnknownFieldSetLite(); } /** - * Returns a mutable {@code UnknownFieldSetLite} that is the composite of {@code first} and - * {@code second}. + * Returns a mutable {@code UnknownFieldSetLite} that is the composite of {@code first} and {@code + * second}. */ static UnknownFieldSetLite mutableCopyOf(UnknownFieldSetLite first, UnknownFieldSetLite second) { int count = first.count + second.count; @@ -79,66 +76,50 @@ static UnknownFieldSetLite mutableCopyOf(UnknownFieldSetLite first, UnknownField System.arraycopy(second.tags, 0, tags, first.count, second.count); Object[] objects = Arrays.copyOf(first.objects, count); System.arraycopy(second.objects, 0, objects, first.count, second.count); - return new UnknownFieldSetLite(count, tags, objects, true /* isMutable */); + return new UnknownFieldSetLite(count, tags, objects, /* isMutable= */ true); } - - /** - * The number of elements in the set. - */ + + /** The number of elements in the set. */ private int count; - - /** - * The tag numbers for the elements in the set. - */ + + /** The tag numbers for the elements in the set. */ private int[] tags; - - /** - * The boxed values of the elements in the set. - */ + + /** The boxed values of the elements in the set. */ private Object[] objects; - - /** - * The lazily computed serialized size of the set. - */ + + /** The lazily computed serialized size of the set. */ private int memoizedSerializedSize = -1; - - /** - * Indicates that this object is mutable. - */ + + /** Indicates that this object is mutable. */ private boolean isMutable; - /** - * Constructs a mutable {@code UnknownFieldSetLite}. - */ + /** Constructs a mutable {@code UnknownFieldSetLite}. */ private UnknownFieldSetLite() { - this(0, new int[MIN_CAPACITY], new Object[MIN_CAPACITY], true /* isMutable */); + this(0, new int[MIN_CAPACITY], new Object[MIN_CAPACITY], /* isMutable= */ true); } - - /** - * Constructs the {@code UnknownFieldSetLite}. - */ + + /** Constructs the {@code UnknownFieldSetLite}. */ private UnknownFieldSetLite(int count, int[] tags, Object[] objects, boolean isMutable) { this.count = count; this.tags = tags; this.objects = objects; this.isMutable = isMutable; } - + /** * Marks this object as immutable. - * + * *

Future calls to methods that attempt to modify this object will throw. */ public void makeImmutable() { this.isMutable = false; } - - /** - * Throws an {@link UnsupportedOperationException} if immutable. - */ + + /** Throws an {@link UnsupportedOperationException} if immutable. */ void checkMutable() { if (!isMutable) { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException(); } } @@ -187,6 +168,72 @@ public void writeAsMessageSetTo(CodedOutputStream output) throws IOException { } } + /** Serializes the set and writes it to {@code writer} using {@code MessageSet} wire format. */ + void writeAsMessageSetTo(Writer writer) throws IOException { + if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) { + // Write fields in descending order. + for (int i = count - 1; i >= 0; i--) { + int fieldNumber = WireFormat.getTagFieldNumber(tags[i]); + writer.writeMessageSetItem(fieldNumber, objects[i]); + } + } else { + // Write fields in ascending order. + for (int i = 0; i < count; i++) { + int fieldNumber = WireFormat.getTagFieldNumber(tags[i]); + writer.writeMessageSetItem(fieldNumber, objects[i]); + } + } + } + + /** Serializes the set and writes it to {@code writer}. */ + public void writeTo(Writer writer) throws IOException { + if (count == 0) { + return; + } + + // TODO: tags are not sorted, so there's no write order guarantees + if (writer.fieldOrder() == Writer.FieldOrder.ASCENDING) { + for (int i = 0; i < count; ++i) { + writeField(tags[i], objects[i], writer); + } + } else { + for (int i = count - 1; i >= 0; --i) { + writeField(tags[i], objects[i], writer); + } + } + } + + private static void writeField(int tag, Object object, Writer writer) throws IOException { + int fieldNumber = WireFormat.getTagFieldNumber(tag); + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + writer.writeInt64(fieldNumber, (Long) object); + break; + case WireFormat.WIRETYPE_FIXED32: + writer.writeFixed32(fieldNumber, (Integer) object); + break; + case WireFormat.WIRETYPE_FIXED64: + writer.writeFixed64(fieldNumber, (Long) object); + break; + case WireFormat.WIRETYPE_LENGTH_DELIMITED: + writer.writeBytes(fieldNumber, (ByteString) object); + break; + case WireFormat.WIRETYPE_START_GROUP: + if (writer.fieldOrder() == Writer.FieldOrder.ASCENDING) { + writer.writeStartGroup(fieldNumber); + ((UnknownFieldSetLite) object).writeTo(writer); + writer.writeEndGroup(fieldNumber); + } else { + writer.writeEndGroup(fieldNumber); + ((UnknownFieldSetLite) object).writeTo(writer); + writer.writeStartGroup(fieldNumber); + } + break; + default: + // TODO(liujisi): Change writeTo to throw IOException? + throw new RuntimeException(InvalidProtocolBufferException.invalidWireType()); + } + } /** * Get the number of bytes required to encode this field, including field number, using {@code @@ -197,17 +244,17 @@ public int getSerializedSizeAsMessageSet() { if (size != -1) { return size; } - + size = 0; for (int i = 0; i < count; i++) { int tag = tags[i]; int fieldNumber = WireFormat.getTagFieldNumber(tag); - size += CodedOutputStream.computeRawMessageSetExtensionSize( - fieldNumber, (ByteString) objects[i]); + size += + CodedOutputStream.computeRawMessageSetExtensionSize(fieldNumber, (ByteString) objects[i]); } - + memoizedSerializedSize = size; - + return size; } @@ -221,7 +268,7 @@ public int getSerializedSize() { if (size != -1) { return size; } - + size = 0; for (int i = 0; i < count; i++) { int tag = tags[i]; @@ -240,20 +287,21 @@ public int getSerializedSize() { size += CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) objects[i]); break; case WireFormat.WIRETYPE_START_GROUP: - size += CodedOutputStream.computeTagSize(fieldNumber) * 2 - + ((UnknownFieldSetLite) objects[i]).getSerializedSize(); + size += + CodedOutputStream.computeTagSize(fieldNumber) * 2 + + ((UnknownFieldSetLite) objects[i]).getSerializedSize(); break; default: throw new IllegalStateException(InvalidProtocolBufferException.invalidWireType()); } } - + memoizedSerializedSize = size; - + return size; } - - private static boolean equals(int[] tags1, int[] tags2, int count) { + + private static boolean tagsEquals(int[] tags1, int[] tags2, int count) { for (int i = 0; i < count; ++i) { if (tags1[i] != tags2[i]) { return false; @@ -262,7 +310,7 @@ private static boolean equals(int[] tags1, int[] tags2, int count) { return true; } - private static boolean equals(Object[] objects1, Object[] objects2, int count) { + private static boolean objectsEquals(Object[] objects1, Object[] objects2, int count) { for (int i = 0; i < count; ++i) { if (!objects1[i].equals(objects2[i])) { return false; @@ -284,25 +332,41 @@ public boolean equals(Object obj) { if (!(obj instanceof UnknownFieldSetLite)) { return false; } - - UnknownFieldSetLite other = (UnknownFieldSetLite) obj; + + UnknownFieldSetLite other = (UnknownFieldSetLite) obj; if (count != other.count - || !equals(tags, other.tags, count) - || !equals(objects, other.objects, count)) { + || !tagsEquals(tags, other.tags, count) + || !objectsEquals(objects, other.objects, count)) { return false; } return true; } + private static int hashCode(int[] tags, int count) { + int hashCode = 17; + for (int i = 0; i < count; ++i) { + hashCode = 31 * hashCode + tags[i]; + } + return hashCode; + } + + private static int hashCode(Object[] objects, int count) { + int hashCode = 17; + for (int i = 0; i < count; ++i) { + hashCode = 31 * hashCode + objects[i].hashCode(); + } + return hashCode; + } + @Override public int hashCode() { int hashCode = 17; - + hashCode = 31 * hashCode + count; - hashCode = 31 * hashCode + Arrays.hashCode(tags); - hashCode = 31 * hashCode + Arrays.deepHashCode(objects); - + hashCode = 31 * hashCode + hashCode(tags, count); + hashCode = 31 * hashCode + hashCode(objects, count); + return hashCode; } @@ -323,26 +387,25 @@ final void printWithIndent(StringBuilder buffer, int indent) { // Package private for unsafe experimental runtime. void storeField(int tag, Object value) { + checkMutable(); ensureCapacity(); - + tags[count] = tag; objects[count] = value; count++; } - - /** - * Ensures that our arrays are long enough to store more metadata. - */ + + /** Ensures that our arrays are long enough to store more metadata. */ private void ensureCapacity() { - if (count == tags.length) { + if (count == tags.length) { int increment = count < (MIN_CAPACITY / 2) ? MIN_CAPACITY : count >> 1; int newLength = count + increment; - + tags = Arrays.copyOf(tags, newLength); objects = Arrays.copyOf(objects, newLength); } } - + /** * Parse a single field from {@code input} and merge it into this set. * @@ -370,8 +433,7 @@ boolean mergeFieldFrom(final int tag, final CodedInputStream input) throws IOExc case WireFormat.WIRETYPE_START_GROUP: final UnknownFieldSetLite subFieldSet = new UnknownFieldSetLite(); subFieldSet.mergeFrom(input); - input.checkLastTagWas( - WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); + input.checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); storeField(tag, subFieldSet); return true; case WireFormat.WIRETYPE_END_GROUP: @@ -382,9 +444,8 @@ boolean mergeFieldFrom(final int tag, final CodedInputStream input) throws IOExc } /** - * Convenience method for merging a new field containing a single varint - * value. This is used in particular when an unknown enum value is - * encountered. + * Convenience method for merging a new field containing a single varint value. This is used in + * particular when an unknown enum value is encountered. * *

For use by generated code only. */ @@ -395,7 +456,7 @@ UnknownFieldSetLite mergeVarintField(int fieldNumber, int value) { } storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_VARINT), (long) value); - + return this; } @@ -404,21 +465,18 @@ UnknownFieldSetLite mergeVarintField(int fieldNumber, int value) { * *

For use by generated code only. */ - UnknownFieldSetLite mergeLengthDelimitedField(final int fieldNumber, final ByteString value) { + UnknownFieldSetLite mergeLengthDelimitedField(final int fieldNumber, final ByteString value) { checkMutable(); if (fieldNumber == 0) { throw new IllegalArgumentException("Zero is not a valid field number."); } storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED), value); - + return this; } - - /** - * Parse an entire message from {@code input} and merge its fields into - * this set. - */ + + /** Parse an entire message from {@code input} and merge its fields into this set. */ private UnknownFieldSetLite mergeFrom(final CodedInputStream input) throws IOException { // Ensures initialization in mergeFieldFrom. while (true) { diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java new file mode 100644 index 0000000000000..ffd7232308c4a --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java @@ -0,0 +1,140 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; + +class UnknownFieldSetLiteSchema + extends UnknownFieldSchema { + + UnknownFieldSetLiteSchema() {} + + @Override + boolean shouldDiscardUnknownFields(Reader reader) { + // We never drop unknown fields in lite. + return false; + } + + @Override + UnknownFieldSetLite newBuilder() { + return UnknownFieldSetLite.newInstance(); + } + + @Override + void addVarint(UnknownFieldSetLite fields, int number, long value) { + fields.storeField(WireFormat.makeTag(number, WireFormat.WIRETYPE_VARINT), value); + } + + @Override + void addFixed32(UnknownFieldSetLite fields, int number, int value) { + fields.storeField(WireFormat.makeTag(number, WireFormat.WIRETYPE_FIXED32), value); + } + + @Override + void addFixed64(UnknownFieldSetLite fields, int number, long value) { + fields.storeField(WireFormat.makeTag(number, WireFormat.WIRETYPE_FIXED64), value); + } + + @Override + void addLengthDelimited(UnknownFieldSetLite fields, int number, ByteString value) { + fields.storeField(WireFormat.makeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED), value); + } + + @Override + void addGroup(UnknownFieldSetLite fields, int number, UnknownFieldSetLite subFieldSet) { + fields.storeField(WireFormat.makeTag(number, WireFormat.WIRETYPE_START_GROUP), subFieldSet); + } + + @Override + UnknownFieldSetLite toImmutable(UnknownFieldSetLite fields) { + fields.makeImmutable(); + return fields; + } + + @Override + void setToMessage(Object message, UnknownFieldSetLite fields) { + ((GeneratedMessageLite) message).unknownFields = fields; + } + + @Override + UnknownFieldSetLite getFromMessage(Object message) { + return ((GeneratedMessageLite) message).unknownFields; + } + + @Override + UnknownFieldSetLite getBuilderFromMessage(Object message) { + UnknownFieldSetLite unknownFields = getFromMessage(message); + // When parsing into a lite message object, its UnknownFieldSet is either the default instance + // or mutable. It can't be in a state where it's immutable but not default instance. + if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) { + unknownFields = UnknownFieldSetLite.newInstance(); + setToMessage(message, unknownFields); + } + return unknownFields; + } + + @Override + void setBuilderToMessage(Object message, UnknownFieldSetLite fields) { + setToMessage(message, fields); + } + + @Override + void makeImmutable(Object message) { + getFromMessage(message).makeImmutable(); + } + + @Override + void writeTo(UnknownFieldSetLite fields, Writer writer) throws IOException { + fields.writeTo(writer); + } + + @Override + void writeAsMessageSetTo(UnknownFieldSetLite fields, Writer writer) throws IOException { + fields.writeAsMessageSetTo(writer); + } + + @Override + UnknownFieldSetLite merge(UnknownFieldSetLite message, UnknownFieldSetLite other) { + return other.equals(UnknownFieldSetLite.getDefaultInstance()) + ? message + : UnknownFieldSetLite.mutableCopyOf(message, other); + } + + @Override + int getSerializedSize(UnknownFieldSetLite unknowns) { + return unknowns.getSerializedSize(); + } + + @Override + int getSerializedSizeAsMessageSet(UnknownFieldSetLite unknowns) { + return unknowns.getSerializedSizeAsMessageSet(); + } +} diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetSchema.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetSchema.java new file mode 100644 index 0000000000000..b838c4b54a490 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetSchema.java @@ -0,0 +1,132 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; + +class UnknownFieldSetSchema extends UnknownFieldSchema { + + private final boolean proto3; + + public UnknownFieldSetSchema(boolean proto3) { + this.proto3 = proto3; + } + + @Override + boolean shouldDiscardUnknownFields(Reader reader) { + return reader.shouldDiscardUnknownFields(); + } + + @Override + UnknownFieldSet.Builder newBuilder() { + return UnknownFieldSet.newBuilder(); + } + + @Override + void addVarint(UnknownFieldSet.Builder fields, int number, long value) { + fields.mergeField(number, UnknownFieldSet.Field.newBuilder().addVarint(value).build()); + } + + @Override + void addFixed32(UnknownFieldSet.Builder fields, int number, int value) { + fields.mergeField(number, UnknownFieldSet.Field.newBuilder().addFixed32(value).build()); + } + + @Override + void addFixed64(UnknownFieldSet.Builder fields, int number, long value) { + fields.mergeField(number, UnknownFieldSet.Field.newBuilder().addFixed64(value).build()); + } + + @Override + void addLengthDelimited(UnknownFieldSet.Builder fields, int number, ByteString value) { + fields.mergeField(number, UnknownFieldSet.Field.newBuilder().addLengthDelimited(value).build()); + } + + @Override + void addGroup(UnknownFieldSet.Builder fields, int number, UnknownFieldSet subFieldSet) { + fields.mergeField(number, UnknownFieldSet.Field.newBuilder().addGroup(subFieldSet).build()); + } + + @Override + UnknownFieldSet toImmutable(UnknownFieldSet.Builder fields) { + return fields.build(); + } + + @Override + void writeTo(UnknownFieldSet message, Writer writer) throws IOException { + message.writeTo(writer); + } + + @Override + void writeAsMessageSetTo(UnknownFieldSet message, Writer writer) throws IOException { + message.writeAsMessageSetTo(writer); + } + + @Override + UnknownFieldSet getFromMessage(Object message) { + return ((GeneratedMessageV3) message).unknownFields; + } + + @Override + void setToMessage(Object message, UnknownFieldSet fields) { + ((GeneratedMessageV3) message).unknownFields = fields; + } + + @Override + UnknownFieldSet.Builder getBuilderFromMessage(Object message) { + return ((GeneratedMessageV3) message).unknownFields.toBuilder(); + } + + @Override + void setBuilderToMessage(Object message, UnknownFieldSet.Builder builder) { + ((GeneratedMessageV3) message).unknownFields = builder.build(); + } + + @Override + void makeImmutable(Object message) { + // Already immutable. + } + + @Override + UnknownFieldSet merge(UnknownFieldSet message, UnknownFieldSet other) { + return message.toBuilder().mergeFrom(other).build(); + } + + @Override + int getSerializedSize(UnknownFieldSet message) { + return message.getSerializedSize(); + } + + @Override + int getSerializedSizeAsMessageSet(UnknownFieldSet unknowns) { + return unknowns.getSerializedSizeAsMessageSet(); + } +} diff --git a/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java b/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java index 30e8791178418..415b2cde0de35 100644 --- a/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java +++ b/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java @@ -39,8 +39,8 @@ import java.util.RandomAccess; /** - * An implementation of {@link LazyStringList} that wraps another - * {@link LazyStringList} such that it cannot be modified via the wrapper. + * An implementation of {@link LazyStringList} that wraps another {@link LazyStringList} such that + * it cannot be modified via the wrapper. * * @author jonp@google.com (Jon Perlow) */ @@ -57,7 +57,7 @@ public UnmodifiableLazyStringList(LazyStringList list) { public String get(int index) { return list.get(index); } - + @Override public Object getRaw(int index) { return list.getRaw(index); @@ -97,7 +97,7 @@ public byte[] getByteArray(int index) { public void add(byte[] element) { throw new UnsupportedOperationException(); } - + @Override public void set(int index, byte[] element) { throw new UnsupportedOperationException(); diff --git a/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java b/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java index 878c77581663e..bcaf1d2f33d83 100644 --- a/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java +++ b/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java @@ -39,23 +39,24 @@ * potentially expose the backing buffer of a {@link ByteString} to the application. * *

DISCLAIMER: The methods in this class should only be called if it is - * guaranteed that the buffer backing the {@link ByteString} will never change! Mutation of a - * {@link ByteString} can lead to unexpected and undesirable consequences in your application, - * and will likely be difficult to debug. Proceed with caution! + * guaranteed that the buffer backing the {@link ByteString} will never change! Mutation of a {@link + * ByteString} can lead to unexpected and undesirable consequences in your application, and will + * likely be difficult to debug. Proceed with caution! + * + *

This can have a number of significant side affects that have spooky-action-at-a-distance-like + * behavior. In particular, if the bytes value changes out from under a Protocol Buffer: * - *

This can have a number of significant side affects that have - * spooky-action-at-a-distance-like behavior. In particular, if the bytes value changes out from - * under a Protocol Buffer: *

    - *
  • serialization may throw - *
  • serialization may succeed but the wrong bytes may be written out - *
  • messages are no longer threadsafe - *
  • hashCode may be incorrect - *
      - *
    • can result in a permanent memory leak when used as a key in a long-lived HashMap - *
    • the semantics of many programs may be violated if this is the case - *
    + *
  • serialization may throw + *
  • serialization may succeed but the wrong bytes may be written out + *
  • messages are no longer threadsafe + *
  • hashCode may be incorrect + *
      + *
    • can result in a permanent memory leak when used as a key in a long-lived HashMap + *
    • the semantics of many programs may be violated if this is the case + *
    *
+ * * Each of these issues will occur in parts of the code base that are entirely distinct from the * parts of the code base modifying the buffer. In fact, both parts of the code base may be correct * - it is the bridging with the unsafe operations that was in error! @@ -99,19 +100,19 @@ public static ByteString unsafeWrap(ByteBuffer buffer) { /** * Writes the given {@link ByteString} to the provided {@link ByteOutput}. Calling this method may - * result in multiple operations on the target {@link ByteOutput} - * (i.e. for roped {@link ByteString}s). + * result in multiple operations on the target {@link ByteOutput} (i.e. for roped {@link + * ByteString}s). * *

This method exposes the internal backing buffer(s) of the {@link ByteString} to the {@link * ByteOutput} in order to avoid additional copying overhead. It would be possible for a malicious * {@link ByteOutput} to corrupt the {@link ByteString}. Use with caution! * - *

NOTE: The {@link ByteOutput} MUST NOT modify the provided buffers. Doing - * so may result in corrupted data, which would be difficult to debug. + *

NOTE: The {@link ByteOutput} MUST NOT modify the provided buffers. Doing so + * may result in corrupted data, which would be difficult to debug. * * @param bytes the {@link ByteString} to be written - * @param output the output to receive the bytes - * @throws IOException if an I/O error occurs + * @param output the output to receive the bytes + * @throws IOException if an I/O error occurs */ public static void unsafeWriteTo(ByteString bytes, ByteOutput output) throws IOException { bytes.writeTo(output); diff --git a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java index acc03a7c0fc0d..0acf22e571cb9 100644 --- a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java +++ b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java @@ -41,14 +41,16 @@ /** Utility class for working with unsafe operations. */ final class UnsafeUtil { - private static final Logger logger = Logger.getLogger(UnsafeUtil.class.getName()); private static final sun.misc.Unsafe UNSAFE = getUnsafe(); + private static final Class MEMORY_CLASS = Android.getMemoryClass(); + private static final boolean IS_ANDROID_64 = determineAndroidSupportByAddressSize(long.class); + private static final boolean IS_ANDROID_32 = determineAndroidSupportByAddressSize(int.class); private static final MemoryAccessor MEMORY_ACCESSOR = getMemoryAccessor(); private static final boolean HAS_UNSAFE_BYTEBUFFER_OPERATIONS = supportsUnsafeByteBufferOperations(); private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArrayOperations(); - private static final long BYTE_ARRAY_BASE_OFFSET = arrayBaseOffset(byte[].class); + static final long BYTE_ARRAY_BASE_OFFSET = arrayBaseOffset(byte[].class); // Micro-optimization: we can assume a scale of 1 and skip the multiply // private static final long BYTE_ARRAY_INDEX_SCALE = 1; @@ -72,6 +74,13 @@ final class UnsafeUtil { private static final long BUFFER_ADDRESS_OFFSET = fieldOffset(bufferAddressField()); + private static final int STRIDE = 8; + private static final int STRIDE_ALIGNMENT_MASK = STRIDE - 1; + private static final int BYTE_ARRAY_ALIGNMENT = + (int) (BYTE_ARRAY_BASE_OFFSET & STRIDE_ALIGNMENT_MASK); + + static final boolean IS_BIG_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; + private UnsafeUtil() {} static boolean hasUnsafeArrayOperations() { @@ -82,6 +91,19 @@ static boolean hasUnsafeByteBufferOperations() { return HAS_UNSAFE_BYTEBUFFER_OPERATIONS; } + static boolean isAndroid64() { + return IS_ANDROID_64; + } + + @SuppressWarnings("unchecked") // safe by method contract + static T allocateInstance(Class clazz) { + try { + return (T) UNSAFE.allocateInstance(clazz); + } catch (InstantiationException e) { + throw new IllegalStateException(e); + } + } + static long objectFieldOffset(Field field) { return MEMORY_ACCESSOR.objectFieldOffset(field); } @@ -225,7 +247,7 @@ static void copyMemory(long srcOffset, byte[] target, long targetIndex, long len } static void copyMemory(byte[] src, long srcIndex, byte[] target, long targetIndex, long length) { - System.arraycopy(src, (int) srcIndex, target, (int) targetIndex, (int) length); + System.arraycopy(src, (int) srcIndex, target, (int) targetIndex, (int) length); } static byte getByte(long address) { @@ -252,13 +274,7 @@ static void putLong(long address, long value) { MEMORY_ACCESSOR.putLong(address, value); } - static void copyMemory(long srcAddress, long targetAddress, long length) { - MEMORY_ACCESSOR.copyMemory(srcAddress, targetAddress, length); - } - - /** - * Gets the offset of the {@code address} field of the given direct {@link ByteBuffer}. - */ + /** Gets the offset of the {@code address} field of the given direct {@link ByteBuffer}. */ static long addressOffset(ByteBuffer buffer) { return MEMORY_ACCESSOR.getLong(buffer, BUFFER_ADDRESS_OFFSET); } @@ -270,7 +286,7 @@ static Object getStaticObject(Field field) { /** * Gets the {@code sun.misc.Unsafe} instance, or {@code null} if not available on this platform. */ - private static sun.misc.Unsafe getUnsafe() { + static sun.misc.Unsafe getUnsafe() { sun.misc.Unsafe unsafe = null; try { unsafe = @@ -303,83 +319,139 @@ private static MemoryAccessor getMemoryAccessor() { if (UNSAFE == null) { return null; } + if (Android.isOnAndroidDevice()) { + if (IS_ANDROID_64) { + return new Android64MemoryAccessor(UNSAFE); + } else if (IS_ANDROID_32) { + return new Android32MemoryAccessor(UNSAFE); + } else { + return null; + } + } + return new JvmMemoryAccessor(UNSAFE); } - /** Indicates whether or not unsafe array operations are supported on this platform. */ private static boolean supportsUnsafeArrayOperations() { - if (UNSAFE == null) { + if (MEMORY_ACCESSOR == null) { return false; } - try { - Class clazz = UNSAFE.getClass(); - clazz.getMethod("objectFieldOffset", Field.class); - clazz.getMethod("arrayBaseOffset", Class.class); - clazz.getMethod("arrayIndexScale", Class.class); - clazz.getMethod("getInt", Object.class, long.class); - clazz.getMethod("putInt", Object.class, long.class, int.class); - clazz.getMethod("getLong", Object.class, long.class); - clazz.getMethod("putLong", Object.class, long.class, long.class); - clazz.getMethod("getObject", Object.class, long.class); - clazz.getMethod("putObject", Object.class, long.class, Object.class); - clazz.getMethod("getByte", Object.class, long.class); - clazz.getMethod("putByte", Object.class, long.class, byte.class); - clazz.getMethod("getBoolean", Object.class, long.class); - clazz.getMethod("putBoolean", Object.class, long.class, boolean.class); - clazz.getMethod("getFloat", Object.class, long.class); - clazz.getMethod("putFloat", Object.class, long.class, float.class); - clazz.getMethod("getDouble", Object.class, long.class); - clazz.getMethod("putDouble", Object.class, long.class, double.class); + return MEMORY_ACCESSOR.supportsUnsafeArrayOperations(); + } - return true; - } catch (Throwable e) { - logger.log( - Level.WARNING, - "platform method missing - proto runtime falling back to safer methods: " + e); + private static boolean supportsUnsafeByteBufferOperations() { + if (MEMORY_ACCESSOR == null) { + return false; } - return false; + return MEMORY_ACCESSOR.supportsUnsafeByteBufferOperations(); } - private static boolean supportsUnsafeByteBufferOperations() { - if (UNSAFE == null) { + private static boolean determineAndroidSupportByAddressSize(Class addressClass) { + if (!Android.isOnAndroidDevice()) { return false; } try { - Class clazz = UNSAFE.getClass(); - // Methods for getting direct buffer address. - clazz.getMethod("objectFieldOffset", Field.class); - clazz.getMethod("getLong", Object.class, long.class); - - clazz.getMethod("getByte", long.class); - clazz.getMethod("putByte", long.class, byte.class); - clazz.getMethod("getInt", long.class); - clazz.getMethod("putInt", long.class, int.class); - clazz.getMethod("getLong", long.class); - clazz.getMethod("putLong", long.class, long.class); - clazz.getMethod("copyMemory", long.class, long.class, long.class); - clazz.getMethod("copyMemory", Object.class, long.class, Object.class, long.class, long.class); + Class clazz = MEMORY_CLASS; + clazz.getMethod("peekLong", addressClass, boolean.class); + clazz.getMethod("pokeLong", addressClass, long.class, boolean.class); + clazz.getMethod("pokeInt", addressClass, int.class, boolean.class); + clazz.getMethod("peekInt", addressClass, boolean.class); + clazz.getMethod("pokeByte", addressClass, byte.class); + clazz.getMethod("peekByte", addressClass); + clazz.getMethod("pokeByteArray", addressClass, byte[].class, int.class, int.class); + clazz.getMethod("peekByteArray", addressClass, byte[].class, int.class, int.class); return true; - } catch (Throwable e) { - logger.log( - Level.WARNING, - "platform method missing - proto runtime falling back to safer methods: " + e); + } catch (Throwable t) { + return false; } - return false; } - - @SuppressWarnings("unchecked") - private static Class getClassForName(String name) { - try { - return (Class) Class.forName(name); - } catch (Throwable e) { - return null; + /** Finds the address field within a direct {@link Buffer}. */ + private static Field bufferAddressField() { + if (Android.isOnAndroidDevice()) { + // Old versions of Android had renamed the address field to 'effectiveDirectAddress', but + // recent versions of Android (>M?) use the OpenJDK implementation. Fall through in that case. + Field field = field(Buffer.class, "effectiveDirectAddress"); + if (field != null) { + return field; + } } + Field field = field(Buffer.class, "address"); + return field != null && field.getType() == long.class ? field : null; } - /** Finds the address field within a direct {@link Buffer}. */ - private static Field bufferAddressField() { - return field(Buffer.class, "address"); + /** + * Returns the index of the first byte where left and right differ, in the range [0, 8]. If {@code + * left == right}, the result will be 8, otherwise less than 8. + * + *

This counts from the *first* byte, which may be the most or least significant byte depending + * on the system endianness. + */ + private static int firstDifferingByteIndexNativeEndian(long left, long right) { + int n = + IS_BIG_ENDIAN + ? Long.numberOfLeadingZeros(left ^ right) + : Long.numberOfTrailingZeros(left ^ right); + return n >> 3; + } + + /** + * Returns the lowest {@code index} such that {@code 0 <= index < length} and {@code left[leftOff + * + index] != right[rightOff + index]}. If no such value exists -- if {@code left} and {@code + * right} match up to {@code length} bytes from their respective offsets -- returns -1. + * + *

{@code leftOff + length} must be less than or equal to {@code left.length}, and the same for + * {@code right}. + */ + static int mismatch(byte[] left, int leftOff, byte[] right, int rightOff, int length) { + if (leftOff < 0 + || rightOff < 0 + || length < 0 + || leftOff + length > left.length + || rightOff + length > right.length) { + throw new IndexOutOfBoundsException(); + } + + int index = 0; + if (HAS_UNSAFE_ARRAY_OPERATIONS) { + int leftAlignment = (BYTE_ARRAY_ALIGNMENT + leftOff) & STRIDE_ALIGNMENT_MASK; + + // Most CPUs handle getting chunks of bytes better on addresses that are a multiple of 4 + // or 8. + // We walk one byte at a time until the left address, at least, is a multiple of 8. + // If the right address is, too, so much the better. + for (; + index < length && (leftAlignment & STRIDE_ALIGNMENT_MASK) != 0; + index++, leftAlignment++) { + if (left[leftOff + index] != right[rightOff + index]) { + return index; + } + } + + // Stride! Grab eight bytes at a time from left and right and check them for equality. + + int strideLength = ((length - index) & ~STRIDE_ALIGNMENT_MASK) + index; + // strideLength is the point where we want to stop striding: it differs from index by + // a multiple of STRIDE, and it's the largest such number <= length. + + for (; index < strideLength; index += STRIDE) { + long leftLongWord = getLong(left, BYTE_ARRAY_BASE_OFFSET + leftOff + index); + long rightLongWord = getLong(right, BYTE_ARRAY_BASE_OFFSET + rightOff + index); + if (leftLongWord != rightLongWord) { + // one of these eight bytes differ! use a helper to find out which one + return index + firstDifferingByteIndexNativeEndian(leftLongWord, rightLongWord); + } + } + } + + // If we were able to stride, there are at most STRIDE - 1 bytes left to compare. + // If we weren't, then this loop covers the whole thing. + for (; index < length; index++) { + if (left[leftOff + index] != right[rightOff + index]) { + return index; + } + } + return -1; } /** @@ -391,14 +463,12 @@ private static long fieldOffset(Field field) { } /** - * Gets the field with the given name within the class, or {@code null} if not found. If found, - * the field is made accessible. + * Gets the field with the given name within the class, or {@code null} if not found. */ private static Field field(Class clazz, String fieldName) { Field field; try { field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); } catch (Throwable t) { // Failed to access the fields. field = null; @@ -418,6 +488,43 @@ public final long objectFieldOffset(Field field) { return unsafe.objectFieldOffset(field); } + public final int arrayBaseOffset(Class clazz) { + return unsafe.arrayBaseOffset(clazz); + } + + public final int arrayIndexScale(Class clazz) { + return unsafe.arrayIndexScale(clazz); + } + + public abstract Object getStaticObject(Field field); + + // Relative Address Operations --------------------------------------------- + + // Indicates whether the following relative address operations are supported + // by this memory accessor. + public boolean supportsUnsafeArrayOperations() { + if (unsafe == null) { + return false; + } + try { + Class clazz = unsafe.getClass(); + clazz.getMethod("objectFieldOffset", Field.class); + clazz.getMethod("arrayBaseOffset", Class.class); + clazz.getMethod("arrayIndexScale", Class.class); + clazz.getMethod("getInt", Object.class, long.class); + clazz.getMethod("putInt", Object.class, long.class, int.class); + clazz.getMethod("getLong", Object.class, long.class); + clazz.getMethod("putLong", Object.class, long.class, long.class); + clazz.getMethod("getObject", Object.class, long.class); + clazz.getMethod("putObject", Object.class, long.class, Object.class); + + return true; + } catch (Throwable e) { + logMissingMethod(e); + } + return false; + } + public abstract byte getByte(Object target, long offset); public abstract void putByte(Object target, long offset, byte value); @@ -458,12 +565,29 @@ public final void putObject(Object target, long offset, Object value) { unsafe.putObject(target, offset, value); } - public final int arrayBaseOffset(Class clazz) { - return unsafe.arrayBaseOffset(clazz); - } - - public final int arrayIndexScale(Class clazz) { - return unsafe.arrayIndexScale(clazz); + // Absolute Address Operations -------------------------------------------- + + // Indicates whether the following absolute address operations are + // supported by this memory accessor. + public boolean supportsUnsafeByteBufferOperations() { + if (unsafe == null) { + return false; + } + try { + Class clazz = unsafe.getClass(); + // Methods for getting direct buffer address. + clazz.getMethod("objectFieldOffset", Field.class); + clazz.getMethod("getLong", Object.class, long.class); + + if (bufferAddressField() == null) { + return false; + } + + return true; + } catch (Throwable e) { + logMissingMethod(e); + } + return false; } public abstract byte getByte(long address); @@ -478,12 +602,8 @@ public final int arrayIndexScale(Class clazz) { public abstract void putLong(long address, long value); - public abstract void copyMemory(long srcAddress, long targetAddress, long length); - - public abstract Object getStaticObject(Field field); - public abstract void copyMemory(long srcOffset, byte[] target, long targetIndex, long length); - + public abstract void copyMemory(byte[] src, long srcIndex, long targetOffset, long length); } @@ -493,6 +613,99 @@ private static final class JvmMemoryAccessor extends MemoryAccessor { super(unsafe); } + @Override + public Object getStaticObject(Field field) { + return getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field)); + } + + @Override + public boolean supportsUnsafeArrayOperations() { + if (!super.supportsUnsafeArrayOperations()) { + return false; + } + + try { + Class clazz = unsafe.getClass(); + clazz.getMethod("getByte", Object.class, long.class); + clazz.getMethod("putByte", Object.class, long.class, byte.class); + clazz.getMethod("getBoolean", Object.class, long.class); + clazz.getMethod("putBoolean", Object.class, long.class, boolean.class); + clazz.getMethod("getFloat", Object.class, long.class); + clazz.getMethod("putFloat", Object.class, long.class, float.class); + clazz.getMethod("getDouble", Object.class, long.class); + clazz.getMethod("putDouble", Object.class, long.class, double.class); + + return true; + } catch (Throwable e) { + logMissingMethod(e); + } + return false; + } + + @Override + public byte getByte(Object target, long offset) { + return unsafe.getByte(target, offset); + } + + @Override + public void putByte(Object target, long offset, byte value) { + unsafe.putByte(target, offset, value); + } + + @Override + public boolean getBoolean(Object target, long offset) { + return unsafe.getBoolean(target, offset); + } + + @Override + public void putBoolean(Object target, long offset, boolean value) { + unsafe.putBoolean(target, offset, value); + } + + @Override + public float getFloat(Object target, long offset) { + return unsafe.getFloat(target, offset); + } + + @Override + public void putFloat(Object target, long offset, float value) { + unsafe.putFloat(target, offset, value); + } + + @Override + public double getDouble(Object target, long offset) { + return unsafe.getDouble(target, offset); + } + + @Override + public void putDouble(Object target, long offset, double value) { + unsafe.putDouble(target, offset, value); + } + + @Override + public boolean supportsUnsafeByteBufferOperations() { + if (!super.supportsUnsafeByteBufferOperations()) { + return false; + } + + try { + Class clazz = unsafe.getClass(); + clazz.getMethod("getByte", long.class); + clazz.getMethod("putByte", long.class, byte.class); + clazz.getMethod("getInt", long.class); + clazz.getMethod("putInt", long.class, int.class); + clazz.getMethod("getLong", long.class); + clazz.getMethod("putLong", long.class, long.class); + clazz.getMethod("copyMemory", long.class, long.class, long.class); + clazz.getMethod( + "copyMemory", Object.class, long.class, Object.class, long.class, long.class); + return true; + } catch (Throwable e) { + logMissingMethod(e); + } + return false; + } + @Override public byte getByte(long address) { return unsafe.getByte(address); @@ -523,65 +736,301 @@ public void putLong(long address, long value) { unsafe.putLong(address, value); } + @Override + public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) { + unsafe.copyMemory(null, srcOffset, target, BYTE_ARRAY_BASE_OFFSET + targetIndex, length); + } + + @Override + public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) { + unsafe.copyMemory(src, BYTE_ARRAY_BASE_OFFSET + srcIndex, null, targetOffset, length); + } + } + + private static final class Android64MemoryAccessor extends MemoryAccessor { + + Android64MemoryAccessor(sun.misc.Unsafe unsafe) { + super(unsafe); + } + + @Override + public Object getStaticObject(Field field) { + try { + return field.get(null); + } catch (IllegalAccessException e) { + return null; + } + } + @Override public byte getByte(Object target, long offset) { - return unsafe.getByte(target, offset); + if (IS_BIG_ENDIAN) { + return getByteBigEndian(target, offset); + } else { + return getByteLittleEndian(target, offset); + } } @Override public void putByte(Object target, long offset, byte value) { - unsafe.putByte(target, offset, value); + if (IS_BIG_ENDIAN) { + putByteBigEndian(target, offset, value); + } else { + putByteLittleEndian(target, offset, value); + } } @Override public boolean getBoolean(Object target, long offset) { - return unsafe.getBoolean(target, offset); + if (IS_BIG_ENDIAN) { + return getBooleanBigEndian(target, offset); + } else { + return getBooleanLittleEndian(target, offset); + } } @Override public void putBoolean(Object target, long offset, boolean value) { - unsafe.putBoolean(target, offset, value); + if (IS_BIG_ENDIAN) { + putBooleanBigEndian(target, offset, value); + } else { + putBooleanLittleEndian(target, offset, value); + } } @Override public float getFloat(Object target, long offset) { - return unsafe.getFloat(target, offset); + return Float.intBitsToFloat(getInt(target, offset)); } @Override public void putFloat(Object target, long offset, float value) { - unsafe.putFloat(target, offset, value); + putInt(target, offset, Float.floatToIntBits(value)); } @Override public double getDouble(Object target, long offset) { - return unsafe.getDouble(target, offset); + return Double.longBitsToDouble(getLong(target, offset)); } @Override public void putDouble(Object target, long offset, double value) { - unsafe.putDouble(target, offset, value); + putLong(target, offset, Double.doubleToLongBits(value)); + } + + @Override + public boolean supportsUnsafeByteBufferOperations() { + return false; + } + + @Override + public byte getByte(long address) { + throw new UnsupportedOperationException(); + } + + @Override + public void putByte(long address, byte value) { + throw new UnsupportedOperationException(); + } + + @Override + public int getInt(long address) { + throw new UnsupportedOperationException(); + } + + @Override + public void putInt(long address, int value) { + throw new UnsupportedOperationException(); + } + + @Override + public long getLong(long address) { + throw new UnsupportedOperationException(); } @Override - public void copyMemory(long srcAddress, long targetAddress, long length) { - unsafe.copyMemory(srcAddress, targetAddress, length); + public void putLong(long address, long value) { + throw new UnsupportedOperationException(); } - - @Override + + @Override public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) { - unsafe.copyMemory(null, srcOffset, target, BYTE_ARRAY_BASE_OFFSET + targetIndex, length); + throw new UnsupportedOperationException(); } - + @Override public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) { - unsafe.copyMemory(src, BYTE_ARRAY_BASE_OFFSET + srcIndex, null, targetOffset, length); + throw new UnsupportedOperationException(); + } + } + + private static final class Android32MemoryAccessor extends MemoryAccessor { + + /** Mask used to convert a 64 bit memory address to a 32 bit address. */ + private static final long SMALL_ADDRESS_MASK = 0x00000000FFFFFFFF; + + /** Truncate a {@code long} address into a short {@code int} address. */ + private static int smallAddress(long address) { + return (int) (SMALL_ADDRESS_MASK & address); + } + + Android32MemoryAccessor(sun.misc.Unsafe unsafe) { + super(unsafe); } @Override public Object getStaticObject(Field field) { - return getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field)); + try { + return field.get(null); + } catch (IllegalAccessException e) { + return null; + } + } + + @Override + public byte getByte(Object target, long offset) { + if (IS_BIG_ENDIAN) { + return getByteBigEndian(target, offset); + } else { + return getByteLittleEndian(target, offset); + } + } + + @Override + public void putByte(Object target, long offset, byte value) { + if (IS_BIG_ENDIAN) { + putByteBigEndian(target, offset, value); + } else { + putByteLittleEndian(target, offset, value); + } + } + + @Override + public boolean getBoolean(Object target, long offset) { + if (IS_BIG_ENDIAN) { + return getBooleanBigEndian(target, offset); + } else { + return getBooleanLittleEndian(target, offset); + } + } + + @Override + public void putBoolean(Object target, long offset, boolean value) { + if (IS_BIG_ENDIAN) { + putBooleanBigEndian(target, offset, value); + } else { + putBooleanLittleEndian(target, offset, value); + } + } + + @Override + public float getFloat(Object target, long offset) { + return Float.intBitsToFloat(getInt(target, offset)); + } + + @Override + public void putFloat(Object target, long offset, float value) { + putInt(target, offset, Float.floatToIntBits(value)); + } + + @Override + public double getDouble(Object target, long offset) { + return Double.longBitsToDouble(getLong(target, offset)); + } + + @Override + public void putDouble(Object target, long offset, double value) { + putLong(target, offset, Double.doubleToLongBits(value)); + } + + @Override + public boolean supportsUnsafeByteBufferOperations() { + return false; + } + + @Override + public byte getByte(long address) { + throw new UnsupportedOperationException(); + } + + @Override + public void putByte(long address, byte value) { + throw new UnsupportedOperationException(); + } + + @Override + public int getInt(long address) { + throw new UnsupportedOperationException(); + } + + @Override + public void putInt(long address, int value) { + throw new UnsupportedOperationException(); + } + + @Override + public long getLong(long address) { + throw new UnsupportedOperationException(); + } + + @Override + public void putLong(long address, long value) { + throw new UnsupportedOperationException(); + } + + @Override + public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) { + throw new UnsupportedOperationException(); + } + + @Override + public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) { + throw new UnsupportedOperationException(); } } + private static byte getByteBigEndian(Object target, long offset) { + return (byte) ((getInt(target, offset & ~3) >>> ((~offset & 3) << 3)) & 0xFF); + } + + private static byte getByteLittleEndian(Object target, long offset) { + return (byte) ((getInt(target, offset & ~3) >>> ((offset & 3) << 3)) & 0xFF); + } + + private static void putByteBigEndian(Object target, long offset, byte value) { + int intValue = getInt(target, offset & ~3); + int shift = ((~(int) offset) & 3) << 3; + int output = (intValue & ~(0xFF << shift)) | ((0xFF & value) << shift); + putInt(target, offset & ~3, output); + } + + private static void putByteLittleEndian(Object target, long offset, byte value) { + int intValue = getInt(target, offset & ~3); + int shift = (((int) offset) & 3) << 3; + int output = (intValue & ~(0xFF << shift)) | ((0xFF & value) << shift); + putInt(target, offset & ~3, output); + } + + private static boolean getBooleanBigEndian(Object target, long offset) { + return getByteBigEndian(target, offset) != 0; + } + + private static boolean getBooleanLittleEndian(Object target, long offset) { + return getByteLittleEndian(target, offset) != 0; + } + + private static void putBooleanBigEndian(Object target, long offset, boolean value) { + putByteBigEndian(target, offset, (byte) (value ? 1 : 0)); + } + + private static void putBooleanLittleEndian(Object target, long offset, boolean value) { + putByteLittleEndian(target, offset, (byte) (value ? 1 : 0)); + } + + private static void logMissingMethod(Throwable e) { + Logger.getLogger(UnsafeUtil.class.getName()) + .log( + Level.WARNING, + "platform method missing - proto runtime falling back to safer methods: " + e); + } } diff --git a/java/core/src/main/java/com/google/protobuf/Utf8.java b/java/core/src/main/java/com/google/protobuf/Utf8.java index 4cf79d7b578eb..104ab098325ac 100644 --- a/java/core/src/main/java/com/google/protobuf/Utf8.java +++ b/java/core/src/main/java/com/google/protobuf/Utf8.java @@ -34,6 +34,9 @@ import static com.google.protobuf.UnsafeUtil.hasUnsafeArrayOperations; import static com.google.protobuf.UnsafeUtil.hasUnsafeByteBufferOperations; import static java.lang.Character.MAX_SURROGATE; +import static java.lang.Character.MIN_HIGH_SURROGATE; +import static java.lang.Character.MIN_LOW_SURROGATE; +import static java.lang.Character.MIN_SUPPLEMENTARY_CODE_POINT; import static java.lang.Character.MIN_SURROGATE; import static java.lang.Character.isSurrogatePair; import static java.lang.Character.toCodePoint; @@ -41,36 +44,31 @@ import java.nio.ByteBuffer; /** - * A set of low-level, high-performance static utility methods related - * to the UTF-8 character encoding. This class has no dependencies - * outside of the core JDK libraries. + * A set of low-level, high-performance static utility methods related to the UTF-8 character + * encoding. This class has no dependencies outside of the core JDK libraries. * - *

There are several variants of UTF-8. The one implemented by - * this class is the restricted definition of UTF-8 introduced in - * Unicode 3.1, which mandates the rejection of "overlong" byte - * sequences as well as rejection of 3-byte surrogate codepoint byte - * sequences. Note that the UTF-8 decoder included in Oracle's JDK - * has been modified to also reject "overlong" byte sequences, but (as - * of 2011) still accepts 3-byte surrogate codepoint byte sequences. + *

There are several variants of UTF-8. The one implemented by this class is the restricted + * definition of UTF-8 introduced in Unicode 3.1, which mandates the rejection of "overlong" byte + * sequences as well as rejection of 3-byte surrogate codepoint byte sequences. Note that the UTF-8 + * decoder included in Oracle's JDK has been modified to also reject "overlong" byte sequences, but + * (as of 2011) still accepts 3-byte surrogate codepoint byte sequences. * - *

The byte sequences considered valid by this class are exactly - * those that can be roundtrip converted to Strings and back to bytes - * using the UTF-8 charset, without loss:

 {@code
+ * 

The byte sequences considered valid by this class are exactly those that can be roundtrip + * converted to Strings and back to bytes using the UTF-8 charset, without loss: + * + *

{@code
  * Arrays.equals(bytes, new String(bytes, Internal.UTF_8).getBytes(Internal.UTF_8))
  * }
* - *

See the Unicode Standard,
- * Table 3-6. UTF-8 Bit Distribution,
- * Table 3-7. Well Formed UTF-8 Byte Sequences. + *

See the Unicode Standard,
Table 3-6. UTF-8 Bit Distribution,
Table 3-7. + * Well Formed UTF-8 Byte Sequences. * - *

This class supports decoding of partial byte sequences, so that the - * bytes in a complete UTF-8 byte sequences can be stored in multiple - * segments. Methods typically return {@link #MALFORMED} if the partial - * byte sequence is definitely not well-formed, {@link #COMPLETE} if it is - * well-formed in the absence of additional input, or if the byte sequence - * apparently terminated in the middle of a character, an opaque integer - * "state" value containing enough information to decode the character when - * passed to a subsequent invocation of a partial decoding method. + *

This class supports decoding of partial byte sequences, so that the bytes in a complete UTF-8 + * byte sequences can be stored in multiple segments. Methods typically return {@link #MALFORMED} if + * the partial byte sequence is definitely not well-formed, {@link #COMPLETE} if it is well-formed + * in the absence of additional input, or if the byte sequence apparently terminated in the middle + * of a character, an opaque integer "state" value containing enough information to decode the + * character when passed to a subsequent invocation of a partial decoding method. * * @author martinrb@google.com (Martin Buchholz) */ @@ -83,7 +81,9 @@ final class Utf8 { * delegate for which all methods are delegated directly to. */ private static final Processor processor = - UnsafeProcessor.isAvailable() ? new UnsafeProcessor() : new SafeProcessor(); + (UnsafeProcessor.isAvailable() && !Android.isOnAndroidDevice()) + ? new UnsafeProcessor() + : new SafeProcessor(); /** * A mask used when performing unsafe reads to determine if a long value contains any non-ASCII @@ -93,31 +93,28 @@ final class Utf8 { /** * Maximum number of bytes per Java UTF-16 char in UTF-8. + * * @see java.nio.charset.CharsetEncoder#maxBytesPerChar() */ static final int MAX_BYTES_PER_CHAR = 3; /** - * State value indicating that the byte sequence is well-formed and - * complete (no further bytes are needed to complete a character). + * State value indicating that the byte sequence is well-formed and complete (no further bytes are + * needed to complete a character). */ public static final int COMPLETE = 0; - /** - * State value indicating that the byte sequence is definitely not - * well-formed. - */ + /** State value indicating that the byte sequence is definitely not well-formed. */ public static final int MALFORMED = -1; /** * Used by {@code Unsafe} UTF-8 string validation logic to determine the minimum string length * above which to employ an optimized algorithm for counting ASCII characters. The reason for this * threshold is that for small strings, the optimization may not be beneficial or may even - * negatively impact performance since it requires additional logic to avoid unaligned reads - * (when calling {@code Unsafe.getLong}). This threshold guarantees that even if the initial - * offset is unaligned, we're guaranteed to make at least one call to {@code Unsafe.getLong()} - * which provides a performance improvement that entirely subsumes the cost of the additional - * logic. + * negatively impact performance since it requires additional logic to avoid unaligned reads (when + * calling {@code Unsafe.getLong}). This threshold guarantees that even if the initial offset is + * unaligned, we're guaranteed to make at least one call to {@code Unsafe.getLong()} which + * provides a performance improvement that entirely subsumes the cost of the additional logic. */ private static final int UNSAFE_COUNT_ASCII_THRESHOLD = 16; @@ -141,76 +138,69 @@ final class Utf8 { // are valid trailing bytes. /** - * Returns {@code true} if the given byte array is a well-formed - * UTF-8 byte sequence. + * Returns {@code true} if the given byte array is a well-formed UTF-8 byte sequence. * - *

This is a convenience method, equivalent to a call to {@code - * isValidUtf8(bytes, 0, bytes.length)}. + *

This is a convenience method, equivalent to a call to {@code isValidUtf8(bytes, 0, + * bytes.length)}. */ public static boolean isValidUtf8(byte[] bytes) { return processor.isValidUtf8(bytes, 0, bytes.length); } /** - * Returns {@code true} if the given byte array slice is a - * well-formed UTF-8 byte sequence. The range of bytes to be - * checked extends from index {@code index}, inclusive, to {@code - * limit}, exclusive. + * Returns {@code true} if the given byte array slice is a well-formed UTF-8 byte sequence. The + * range of bytes to be checked extends from index {@code index}, inclusive, to {@code limit}, + * exclusive. * - *

This is a convenience method, equivalent to {@code - * partialIsValidUtf8(bytes, index, limit) == Utf8.COMPLETE}. + *

This is a convenience method, equivalent to {@code partialIsValidUtf8(bytes, index, limit) + * == Utf8.COMPLETE}. */ public static boolean isValidUtf8(byte[] bytes, int index, int limit) { return processor.isValidUtf8(bytes, index, limit); } /** - * Tells whether the given byte array slice is a well-formed, - * malformed, or incomplete UTF-8 byte sequence. The range of bytes - * to be checked extends from index {@code index}, inclusive, to + * Tells whether the given byte array slice is a well-formed, malformed, or incomplete UTF-8 byte + * sequence. The range of bytes to be checked extends from index {@code index}, inclusive, to * {@code limit}, exclusive. * - * @param state either {@link Utf8#COMPLETE} (if this is the initial decoding - * operation) or the value returned from a call to a partial decoding method - * for the previous bytes - * - * @return {@link #MALFORMED} if the partial byte sequence is - * definitely not well-formed, {@link #COMPLETE} if it is well-formed - * (no additional input needed), or if the byte sequence is - * "incomplete", i.e. apparently terminated in the middle of a character, - * an opaque integer "state" value containing enough information to - * decode the character when passed to a subsequent invocation of a - * partial decoding method. + * @param state either {@link Utf8#COMPLETE} (if this is the initial decoding operation) or the + * value returned from a call to a partial decoding method for the previous bytes + * @return {@link #MALFORMED} if the partial byte sequence is definitely not well-formed, {@link + * #COMPLETE} if it is well-formed (no additional input needed), or if the byte sequence is + * "incomplete", i.e. apparently terminated in the middle of a character, an opaque integer + * "state" value containing enough information to decode the character when passed to a + * subsequent invocation of a partial decoding method. */ public static int partialIsValidUtf8(int state, byte[] bytes, int index, int limit) { return processor.partialIsValidUtf8(state, bytes, index, limit); } private static int incompleteStateFor(int byte1) { - return (byte1 > (byte) 0xF4) ? - MALFORMED : byte1; + return (byte1 > (byte) 0xF4) ? MALFORMED : byte1; } private static int incompleteStateFor(int byte1, int byte2) { - return (byte1 > (byte) 0xF4 || - byte2 > (byte) 0xBF) ? - MALFORMED : byte1 ^ (byte2 << 8); + return (byte1 > (byte) 0xF4 || byte2 > (byte) 0xBF) ? MALFORMED : byte1 ^ (byte2 << 8); } private static int incompleteStateFor(int byte1, int byte2, int byte3) { - return (byte1 > (byte) 0xF4 || - byte2 > (byte) 0xBF || - byte3 > (byte) 0xBF) ? - MALFORMED : byte1 ^ (byte2 << 8) ^ (byte3 << 16); + return (byte1 > (byte) 0xF4 || byte2 > (byte) 0xBF || byte3 > (byte) 0xBF) + ? MALFORMED + : byte1 ^ (byte2 << 8) ^ (byte3 << 16); } private static int incompleteStateFor(byte[] bytes, int index, int limit) { int byte1 = bytes[index - 1]; switch (limit - index) { - case 0: return incompleteStateFor(byte1); - case 1: return incompleteStateFor(byte1, bytes[index]); - case 2: return incompleteStateFor(byte1, bytes[index], bytes[index + 1]); - default: throw new AssertionError(); + case 0: + return incompleteStateFor(byte1); + case 1: + return incompleteStateFor(byte1, bytes[index]); + case 2: + return incompleteStateFor(byte1, bytes[index], bytes[index + 1]); + default: + throw new AssertionError(); } } @@ -231,7 +221,7 @@ private static int incompleteStateFor( // These UTF-8 handling methods are copied from Guava's Utf8 class with a modification to throw // a protocol buffer local exception. This exception is then caught in CodedOutputStream so it can // fallback to more lenient behavior. - + static class UnpairedSurrogateException extends IllegalArgumentException { UnpairedSurrogateException(int index, int length) { super("Unpaired surrogate at index " + index + " of " + length); @@ -239,9 +229,9 @@ static class UnpairedSurrogateException extends IllegalArgumentException { } /** - * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string, - * this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in - * both time and space. + * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string, this + * method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in both + * time and space. * * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired * surrogates) @@ -261,7 +251,7 @@ static int encodedLength(CharSequence sequence) { for (; i < utf16Length; i++) { char c = sequence.charAt(i); if (c < 0x800) { - utf8Length += ((0x7f - c) >>> 31); // branch free! + utf8Length += ((0x7f - c) >>> 31); // branch free! } else { utf8Length += encodedLengthGeneral(sequence, i); break; @@ -270,8 +260,8 @@ static int encodedLength(CharSequence sequence) { if (utf8Length < utf16Length) { // Necessary and sufficient condition for overflow because of maximum 3x expansion - throw new IllegalArgumentException("UTF-8 length does not fit in int: " - + (utf8Length + (1L << 32))); + throw new IllegalArgumentException( + "UTF-8 length does not fit in int: " + (utf8Length + (1L << 32))); } return utf8Length; } @@ -289,7 +279,7 @@ private static int encodedLengthGeneral(CharSequence sequence, int start) { if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) { // Check that we have a well-formed surrogate pair. int cp = Character.codePointAt(sequence, i); - if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) { + if (cp < MIN_SUPPLEMENTARY_CODE_POINT) { throw new UnpairedSurrogateException(i, utf16Length); } i++; @@ -330,6 +320,26 @@ static int partialIsValidUtf8(int state, ByteBuffer buffer, int index, int limit return processor.partialIsValidUtf8(state, buffer, index, limit); } + /** + * Decodes the given UTF-8 portion of the {@link ByteBuffer} into a {@link String}. + * + * @throws InvalidProtocolBufferException if the input is not valid UTF-8. + */ + static String decodeUtf8(ByteBuffer buffer, int index, int size) + throws InvalidProtocolBufferException { + return processor.decodeUtf8(buffer, index, size); + } + + /** + * Decodes the given UTF-8 encoded byte array slice into a {@link String}. + * + * @throws InvalidProtocolBufferException if the input is not valid UTF-8. + */ + static String decodeUtf8(byte[] bytes, int index, int size) + throws InvalidProtocolBufferException { + return processor.decodeUtf8(bytes, index, size); + } + /** * Encodes the given characters to the target {@link ByteBuffer} using UTF-8 encoding. * @@ -345,15 +355,15 @@ static void encodeUtf8(CharSequence in, ByteBuffer out) { } /** - * Counts (approximately) the number of consecutive ASCII characters in the given buffer. - * The byte order of the {@link ByteBuffer} does not matter, so performance can be improved if - * native byte order is used (i.e. no byte-swapping in {@link ByteBuffer#getLong(int)}). + * Counts (approximately) the number of consecutive ASCII characters in the given buffer. The byte + * order of the {@link ByteBuffer} does not matter, so performance can be improved if native byte + * order is used (i.e. no byte-swapping in {@link ByteBuffer#getLong(int)}). * * @param buffer the buffer to be scanned for ASCII chars * @param index the starting index of the scan * @param limit the limit within buffer for the scan - * @return the number of ASCII characters found. The stopping position will be at or - * before the first non-ASCII byte. + * @return the number of ASCII characters found. The stopping position will be at or before the + * first non-ASCII byte. */ private static int estimateConsecutiveAscii(ByteBuffer buffer, int index, int limit) { int i = index; @@ -365,52 +375,43 @@ private static int estimateConsecutiveAscii(ByteBuffer buffer, int index, int li return i - index; } - /** - * A processor of UTF-8 strings, providing methods for checking validity and encoding. - */ + /** A processor of UTF-8 strings, providing methods for checking validity and encoding. */ // TODO(nathanmittler): Add support for Memory/MemoryBlock on Android. abstract static class Processor { /** - * Returns {@code true} if the given byte array slice is a - * well-formed UTF-8 byte sequence. The range of bytes to be - * checked extends from index {@code index}, inclusive, to {@code - * limit}, exclusive. + * Returns {@code true} if the given byte array slice is a well-formed UTF-8 byte sequence. The + * range of bytes to be checked extends from index {@code index}, inclusive, to {@code limit}, + * exclusive. * - *

This is a convenience method, equivalent to {@code - * partialIsValidUtf8(bytes, index, limit) == Utf8.COMPLETE}. + *

This is a convenience method, equivalent to {@code partialIsValidUtf8(bytes, index, limit) + * == Utf8.COMPLETE}. */ final boolean isValidUtf8(byte[] bytes, int index, int limit) { return partialIsValidUtf8(COMPLETE, bytes, index, limit) == COMPLETE; } /** - * Tells whether the given byte array slice is a well-formed, - * malformed, or incomplete UTF-8 byte sequence. The range of bytes - * to be checked extends from index {@code index}, inclusive, to - * {@code limit}, exclusive. + * Tells whether the given byte array slice is a well-formed, malformed, or incomplete UTF-8 + * byte sequence. The range of bytes to be checked extends from index {@code index}, inclusive, + * to {@code limit}, exclusive. * - * @param state either {@link Utf8#COMPLETE} (if this is the initial decoding - * operation) or the value returned from a call to a partial decoding method - * for the previous bytes - * - * @return {@link #MALFORMED} if the partial byte sequence is - * definitely not well-formed, {@link #COMPLETE} if it is well-formed - * (no additional input needed), or if the byte sequence is - * "incomplete", i.e. apparently terminated in the middle of a character, - * an opaque integer "state" value containing enough information to - * decode the character when passed to a subsequent invocation of a - * partial decoding method. + * @param state either {@link Utf8#COMPLETE} (if this is the initial decoding operation) or the + * value returned from a call to a partial decoding method for the previous bytes + * @return {@link #MALFORMED} if the partial byte sequence is definitely not well-formed, {@link + * #COMPLETE} if it is well-formed (no additional input needed), or if the byte sequence is + * "incomplete", i.e. apparently terminated in the middle of a character, an opaque integer + * "state" value containing enough information to decode the character when passed to a + * subsequent invocation of a partial decoding method. */ abstract int partialIsValidUtf8(int state, byte[] bytes, int index, int limit); /** - * Returns {@code true} if the given portion of the {@link ByteBuffer} is a - * well-formed UTF-8 byte sequence. The range of bytes to be - * checked extends from index {@code index}, inclusive, to {@code - * limit}, exclusive. + * Returns {@code true} if the given portion of the {@link ByteBuffer} is a well-formed UTF-8 + * byte sequence. The range of bytes to be checked extends from index {@code index}, inclusive, + * to {@code limit}, exclusive. * - *

This is a convenience method, equivalent to {@code - * partialIsValidUtf8(bytes, index, limit) == Utf8.COMPLETE}. + *

This is a convenience method, equivalent to {@code partialIsValidUtf8(bytes, index, limit) + * == Utf8.COMPLETE}. */ final boolean isValidUtf8(ByteBuffer buffer, int index, int limit) { return partialIsValidUtf8(COMPLETE, buffer, index, limit) == COMPLETE; @@ -427,22 +428,20 @@ final int partialIsValidUtf8( if (buffer.hasArray()) { final int offset = buffer.arrayOffset(); return partialIsValidUtf8(state, buffer.array(), offset + index, offset + limit); - } else if (buffer.isDirect()){ + } else if (buffer.isDirect()) { return partialIsValidUtf8Direct(state, buffer, index, limit); } return partialIsValidUtf8Default(state, buffer, index, limit); } - /** - * Performs validation for direct {@link ByteBuffer} instances. - */ + /** Performs validation for direct {@link ByteBuffer} instances. */ abstract int partialIsValidUtf8Direct( final int state, final ByteBuffer buffer, int index, final int limit); /** * Performs validation for {@link ByteBuffer} instances using the {@link ByteBuffer} API rather - * than potentially faster approaches. This first completes validation for the current - * character (provided by {@code state}) and then finishes validation for the sequence. + * than potentially faster approaches. This first completes validation for the current character + * (provided by {@code state}) and then finishes validation for the sequence. */ final int partialIsValidUtf8Default( final int state, final ByteBuffer buffer, int index, final int limit) { @@ -541,7 +540,7 @@ final int partialIsValidUtf8Default( private static int partialIsValidUtf8(final ByteBuffer buffer, int index, final int limit) { index += estimateConsecutiveAscii(buffer, index, limit); - for (;;) { + for (; ; ) { // Optimize for interior runs of ASCII bytes. // TODO(nathanmittler): Consider checking 8 bytes at a time after some threshold? // Maybe after seeing a few in a row that are ASCII, go back to fast mode? @@ -609,24 +608,133 @@ private static int partialIsValidUtf8(final ByteBuffer buffer, int index, final } } + /** + * Decodes the given byte array slice into a {@link String}. + * + * @throws InvalidProtocolBufferException if the byte array slice is not valid UTF-8. + */ + abstract String decodeUtf8(byte[] bytes, int index, int size) + throws InvalidProtocolBufferException; + + /** + * Decodes the given portion of the {@link ByteBuffer} into a {@link String}. + * + * @throws InvalidProtocolBufferException if the portion of the buffer is not valid UTF-8. + */ + final String decodeUtf8(ByteBuffer buffer, int index, int size) + throws InvalidProtocolBufferException { + if (buffer.hasArray()) { + final int offset = buffer.arrayOffset(); + return decodeUtf8(buffer.array(), offset + index, size); + } else if (buffer.isDirect()) { + return decodeUtf8Direct(buffer, index, size); + } + return decodeUtf8Default(buffer, index, size); + } + + /** Decodes direct {@link ByteBuffer} instances into {@link String}. */ + abstract String decodeUtf8Direct(ByteBuffer buffer, int index, int size) + throws InvalidProtocolBufferException; + + /** + * Decodes {@link ByteBuffer} instances using the {@link ByteBuffer} API rather than potentially + * faster approaches. + */ + final String decodeUtf8Default(ByteBuffer buffer, int index, int size) + throws InvalidProtocolBufferException { + // Bitwise OR combines the sign bits so any negative value fails the check. + if ((index | size | buffer.limit() - index - size) < 0) { + throw new ArrayIndexOutOfBoundsException( + String.format("buffer limit=%d, index=%d, limit=%d", buffer.limit(), index, size)); + } + + int offset = index; + final int limit = offset + size; + + // The longest possible resulting String is the same as the number of input bytes, when it is + // all ASCII. For other cases, this over-allocates and we will truncate in the end. + char[] resultArr = new char[size]; + int resultPos = 0; + + // Optimize for 100% ASCII (Hotspot loves small simple top-level loops like this). + // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII). + while (offset < limit) { + byte b = buffer.get(offset); + if (!DecodeUtil.isOneByte(b)) { + break; + } + offset++; + DecodeUtil.handleOneByte(b, resultArr, resultPos++); + } + + while (offset < limit) { + byte byte1 = buffer.get(offset++); + if (DecodeUtil.isOneByte(byte1)) { + DecodeUtil.handleOneByte(byte1, resultArr, resultPos++); + // It's common for there to be multiple ASCII characters in a run mixed in, so add an + // extra optimized loop to take care of these runs. + while (offset < limit) { + byte b = buffer.get(offset); + if (!DecodeUtil.isOneByte(b)) { + break; + } + offset++; + DecodeUtil.handleOneByte(b, resultArr, resultPos++); + } + } else if (DecodeUtil.isTwoBytes(byte1)) { + if (offset >= limit) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + DecodeUtil.handleTwoBytes( + byte1, /* byte2 */ buffer.get(offset++), resultArr, resultPos++); + } else if (DecodeUtil.isThreeBytes(byte1)) { + if (offset >= limit - 1) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + DecodeUtil.handleThreeBytes( + byte1, + /* byte2 */ buffer.get(offset++), + /* byte3 */ buffer.get(offset++), + resultArr, + resultPos++); + } else { + if (offset >= limit - 2) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + DecodeUtil.handleFourBytes( + byte1, + /* byte2 */ buffer.get(offset++), + /* byte3 */ buffer.get(offset++), + /* byte4 */ buffer.get(offset++), + resultArr, + resultPos++); + // 4-byte case requires two chars. + resultPos++; + } + } + + return new String(resultArr, 0, resultPos); + } + /** * Encodes an input character sequence ({@code in}) to UTF-8 in the target array ({@code out}). * For a string, this method is similar to + * *

{@code
      * byte[] a = string.getBytes(UTF_8);
      * System.arraycopy(a, 0, bytes, offset, a.length);
      * return offset + a.length;
      * }
* - * but is more efficient in both time and space. One key difference is that this method - * requires paired surrogates, and therefore does not support chunking. - * While {@code String.getBytes(UTF_8)} replaces unpaired surrogates with the default - * replacement character, this method throws {@link UnpairedSurrogateException}. + * but is more efficient in both time and space. One key difference is that this method requires + * paired surrogates, and therefore does not support chunking. While {@code + * String.getBytes(UTF_8)} replaces unpaired surrogates with the default replacement character, + * this method throws {@link UnpairedSurrogateException}. * *

To ensure sufficient space in the output buffer, either call {@link #encodedLength} to - * compute the exact amount needed, or leave room for - * {@code Utf8.MAX_BYTES_PER_CHAR * sequence.length()}, which is the largest possible number - * of bytes that any input can be encoded to. + * compute the exact amount needed, or leave room for {@code Utf8.MAX_BYTES_PER_CHAR * + * sequence.length()}, which is the largest possible number of bytes that any input can be + * encoded to. * * @param in the input character sequence to be encoded * @param out the target array @@ -643,26 +751,24 @@ private static int partialIsValidUtf8(final ByteBuffer buffer, int index, final /** * Encodes an input character sequence ({@code in}) to UTF-8 in the target buffer ({@code out}). * Upon returning from this method, the {@code out} position will point to the position after - * the last encoded byte. This method requires paired surrogates, and therefore does not - * support chunking. + * the last encoded byte. This method requires paired surrogates, and therefore does not support + * chunking. * *

To ensure sufficient space in the output buffer, either call {@link #encodedLength} to - * compute the exact amount needed, or leave room for - * {@code Utf8.MAX_BYTES_PER_CHAR * in.length()}, which is the largest possible number - * of bytes that any input can be encoded to. + * compute the exact amount needed, or leave room for {@code Utf8.MAX_BYTES_PER_CHAR * + * in.length()}, which is the largest possible number of bytes that any input can be encoded to. * * @param in the source character sequence to be encoded * @param out the target buffer * @throws UnpairedSurrogateException if {@code in} contains ill-formed UTF-16 (unpaired * surrogates) - * @throws ArrayIndexOutOfBoundsException if {@code in} encoded in UTF-8 is longer than - * {@code out.remaining()} + * @throws ArrayIndexOutOfBoundsException if {@code in} encoded in UTF-8 is longer than {@code + * out.remaining()} */ final void encodeUtf8(CharSequence in, ByteBuffer out) { if (out.hasArray()) { final int offset = out.arrayOffset(); - int endIndex = - Utf8.encode(in, out.array(), offset + out.position(), out.remaining()); + int endIndex = Utf8.encode(in, out.array(), offset + out.position(), out.remaining()); out.position(endIndex - offset); } else if (out.isDirect()) { encodeUtf8Direct(in, out); @@ -671,9 +777,7 @@ final void encodeUtf8(CharSequence in, ByteBuffer out) { } } - /** - * Encodes the input character sequence to a direct {@link ByteBuffer} instance. - */ + /** Encodes the input character sequence to a direct {@link ByteBuffer} instance. */ abstract void encodeUtf8Direct(CharSequence in, ByteBuffer out); /** @@ -690,7 +794,7 @@ final void encodeUtf8Default(CharSequence in, ByteBuffer out) { // if it occurs. try { // Designed to take advantage of - // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination + // https://wiki.openjdk.java.net/display/HotSpotInternals/RangeCheckElimination for (char c; inIx < inLength && (c = in.charAt(inIx)) < 0x80; ++inIx) { out.put(outIx + inIx, (byte) c); } @@ -752,9 +856,7 @@ final void encodeUtf8Default(CharSequence in, ByteBuffer out) { } } - /** - * {@link Processor} implementation that does not use any {@code sun.misc.Unsafe} methods. - */ + /** {@link Processor} implementation that does not use any {@code sun.misc.Unsafe} methods. */ static final class SafeProcessor extends Processor { @Override int partialIsValidUtf8(int state, byte[] bytes, int index, int limit) { @@ -766,7 +868,7 @@ int partialIsValidUtf8(int state, byte[] bytes, int index, int limit) { // // We expect such "straddler characters" to be rare. - if (index >= limit) { // No bytes? No progress. + if (index >= limit) { // No bytes? No progress. return state; } int byte1 = (byte) state; @@ -850,6 +952,88 @@ int partialIsValidUtf8Direct(int state, ByteBuffer buffer, int index, int limit) return partialIsValidUtf8Default(state, buffer, index, limit); } + @Override + String decodeUtf8(byte[] bytes, int index, int size) throws InvalidProtocolBufferException { + // Bitwise OR combines the sign bits so any negative value fails the check. + if ((index | size | bytes.length - index - size) < 0) { + throw new ArrayIndexOutOfBoundsException( + String.format("buffer length=%d, index=%d, size=%d", bytes.length, index, size)); + } + + int offset = index; + final int limit = offset + size; + + // The longest possible resulting String is the same as the number of input bytes, when it is + // all ASCII. For other cases, this over-allocates and we will truncate in the end. + char[] resultArr = new char[size]; + int resultPos = 0; + + // Optimize for 100% ASCII (Hotspot loves small simple top-level loops like this). + // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII). + while (offset < limit) { + byte b = bytes[offset]; + if (!DecodeUtil.isOneByte(b)) { + break; + } + offset++; + DecodeUtil.handleOneByte(b, resultArr, resultPos++); + } + + while (offset < limit) { + byte byte1 = bytes[offset++]; + if (DecodeUtil.isOneByte(byte1)) { + DecodeUtil.handleOneByte(byte1, resultArr, resultPos++); + // It's common for there to be multiple ASCII characters in a run mixed in, so add an + // extra optimized loop to take care of these runs. + while (offset < limit) { + byte b = bytes[offset]; + if (!DecodeUtil.isOneByte(b)) { + break; + } + offset++; + DecodeUtil.handleOneByte(b, resultArr, resultPos++); + } + } else if (DecodeUtil.isTwoBytes(byte1)) { + if (offset >= limit) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + DecodeUtil.handleTwoBytes(byte1, /* byte2 */ bytes[offset++], resultArr, resultPos++); + } else if (DecodeUtil.isThreeBytes(byte1)) { + if (offset >= limit - 1) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + DecodeUtil.handleThreeBytes( + byte1, + /* byte2 */ bytes[offset++], + /* byte3 */ bytes[offset++], + resultArr, + resultPos++); + } else { + if (offset >= limit - 2) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + DecodeUtil.handleFourBytes( + byte1, + /* byte2 */ bytes[offset++], + /* byte3 */ bytes[offset++], + /* byte4 */ bytes[offset++], + resultArr, + resultPos++); + // 4-byte case requires two chars. + resultPos++; + } + } + + return new String(resultArr, 0, resultPos); + } + + @Override + String decodeUtf8Direct(ByteBuffer buffer, int index, int size) + throws InvalidProtocolBufferException { + // For safe processing, we have to use the ByteBufferAPI. + return decodeUtf8Default(buffer, index, size); + } + @Override int encodeUtf8(CharSequence in, byte[] out, int offset, int length) { int utf16Length = in.length(); @@ -857,7 +1041,7 @@ int encodeUtf8(CharSequence in, byte[] out, int offset, int length) { int i = 0; int limit = offset + length; // Designed to take advantage of - // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination + // https://wiki.openjdk.java.net/display/HotSpotInternals/RangeCheckElimination for (char c; i < utf16Length && i + j < limit && (c = in.charAt(i)) < 0x80; i++) { out[j + i] = (byte) c; } @@ -881,8 +1065,7 @@ int encodeUtf8(CharSequence in, byte[] out, int offset, int length) { // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, // four UTF-8 bytes final char low; - if (i + 1 == in.length() - || !Character.isSurrogatePair(c, (low = in.charAt(++i)))) { + if (i + 1 == in.length() || !Character.isSurrogatePair(c, (low = in.charAt(++i)))) { throw new UnpairedSurrogateException((i - 1), utf16Length); } int codePoint = Character.toCodePoint(c, low); @@ -894,8 +1077,7 @@ int encodeUtf8(CharSequence in, byte[] out, int offset, int length) { // If we are surrogates and we're not a surrogate pair, always throw an // UnpairedSurrogateException instead of an ArrayOutOfBoundsException. if ((Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) - && (i + 1 == in.length() - || !Character.isSurrogatePair(c, in.charAt(i + 1)))) { + && (i + 1 == in.length() || !Character.isSurrogatePair(c, in.charAt(i + 1)))) { throw new UnpairedSurrogateException(i, utf16Length); } throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j); @@ -921,8 +1103,9 @@ private static int partialIsValidUtf8(byte[] bytes, int index, int limit) { } private static int partialIsValidUtf8NonAscii(byte[] bytes, int index, int limit) { - for (;;) { - int byte1, byte2; + for (; ; ) { + int byte1; + int byte2; // Optimize for interior runs of ASCII bytes. do { @@ -941,8 +1124,7 @@ private static int partialIsValidUtf8NonAscii(byte[] bytes, int index, int limit // Simultaneously checks for illegal trailing-byte in // leading position and overlong 2-byte form. - if (byte1 < (byte) 0xC2 - || bytes[index++] > (byte) 0xBF) { + if (byte1 < (byte) 0xC2 || bytes[index++] > (byte) 0xBF) { return MALFORMED; } } else if (byte1 < (byte) 0xF0) { @@ -963,7 +1145,7 @@ private static int partialIsValidUtf8NonAscii(byte[] bytes, int index, int limit } else { // four-byte form - if (index >= limit - 2) { // incomplete sequence + if (index >= limit - 2) { // incomplete sequence return incompleteStateFor(bytes, index, limit); } if ((byte2 = bytes[index++]) > (byte) 0xBF @@ -983,19 +1165,16 @@ private static int partialIsValidUtf8NonAscii(byte[] bytes, int index, int limit } } - /** - * {@link Processor} that uses {@code sun.misc.Unsafe} where possible to improve performance. - */ + /** {@link Processor} that uses {@code sun.misc.Unsafe} where possible to improve performance. */ static final class UnsafeProcessor extends Processor { - /** - * Indicates whether or not all required unsafe operations are supported on this platform. - */ + /** Indicates whether or not all required unsafe operations are supported on this platform. */ static boolean isAvailable() { return hasUnsafeArrayOperations() && hasUnsafeByteBufferOperations(); } @Override int partialIsValidUtf8(int state, byte[] bytes, final int index, final int limit) { + // Bitwise OR combines the sign bits so any negative value fails the check. if ((index | limit | bytes.length - limit) < 0) { throw new ArrayIndexOutOfBoundsException( String.format("Array length=%d, index=%d, limit=%d", bytes.length, index, limit)); @@ -1010,7 +1189,7 @@ int partialIsValidUtf8(int state, byte[] bytes, final int index, final int limit // // We expect such "straddler characters" to be rare. - if (offset >= offsetLimit) { // No bytes? No progress. + if (offset >= offsetLimit) { // No bytes? No progress. return state; } int byte1 = (byte) state; @@ -1091,6 +1270,7 @@ int partialIsValidUtf8(int state, byte[] bytes, final int index, final int limit @Override int partialIsValidUtf8Direct( final int state, ByteBuffer buffer, final int index, final int limit) { + // Bitwise OR combines the sign bits so any negative value fails the check. if ((index | limit | buffer.limit() - limit) < 0) { throw new ArrayIndexOutOfBoundsException( String.format("buffer limit=%d, index=%d, limit=%d", buffer.limit(), index, limit)); @@ -1184,6 +1364,157 @@ int partialIsValidUtf8Direct( return partialIsValidUtf8(address, (int) (addressLimit - address)); } + @Override + String decodeUtf8(byte[] bytes, int index, int size) throws InvalidProtocolBufferException { + if ((index | size | bytes.length - index - size) < 0) { + throw new ArrayIndexOutOfBoundsException( + String.format("buffer length=%d, index=%d, size=%d", bytes.length, index, size)); + } + + int offset = index; + final int limit = offset + size; + + // The longest possible resulting String is the same as the number of input bytes, when it is + // all ASCII. For other cases, this over-allocates and we will truncate in the end. + char[] resultArr = new char[size]; + int resultPos = 0; + + // Optimize for 100% ASCII (Hotspot loves small simple top-level loops like this). + // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII). + while (offset < limit) { + byte b = UnsafeUtil.getByte(bytes, offset); + if (!DecodeUtil.isOneByte(b)) { + break; + } + offset++; + DecodeUtil.handleOneByte(b, resultArr, resultPos++); + } + + while (offset < limit) { + byte byte1 = UnsafeUtil.getByte(bytes, offset++); + if (DecodeUtil.isOneByte(byte1)) { + DecodeUtil.handleOneByte(byte1, resultArr, resultPos++); + // It's common for there to be multiple ASCII characters in a run mixed in, so add an + // extra optimized loop to take care of these runs. + while (offset < limit) { + byte b = UnsafeUtil.getByte(bytes, offset); + if (!DecodeUtil.isOneByte(b)) { + break; + } + offset++; + DecodeUtil.handleOneByte(b, resultArr, resultPos++); + } + } else if (DecodeUtil.isTwoBytes(byte1)) { + if (offset >= limit) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + DecodeUtil.handleTwoBytes( + byte1, /* byte2 */ UnsafeUtil.getByte(bytes, offset++), resultArr, resultPos++); + } else if (DecodeUtil.isThreeBytes(byte1)) { + if (offset >= limit - 1) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + DecodeUtil.handleThreeBytes( + byte1, + /* byte2 */ UnsafeUtil.getByte(bytes, offset++), + /* byte3 */ UnsafeUtil.getByte(bytes, offset++), + resultArr, + resultPos++); + } else { + if (offset >= limit - 2) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + DecodeUtil.handleFourBytes( + byte1, + /* byte2 */ UnsafeUtil.getByte(bytes, offset++), + /* byte3 */ UnsafeUtil.getByte(bytes, offset++), + /* byte4 */ UnsafeUtil.getByte(bytes, offset++), + resultArr, + resultPos++); + // 4-byte case requires two chars. + resultPos++; + } + } + + return new String(resultArr, 0, resultPos); + } + + @Override + String decodeUtf8Direct(ByteBuffer buffer, int index, int size) + throws InvalidProtocolBufferException { + // Bitwise OR combines the sign bits so any negative value fails the check. + if ((index | size | buffer.limit() - index - size) < 0) { + throw new ArrayIndexOutOfBoundsException( + String.format("buffer limit=%d, index=%d, limit=%d", buffer.limit(), index, size)); + } + long address = UnsafeUtil.addressOffset(buffer) + index; + final long addressLimit = address + size; + + // The longest possible resulting String is the same as the number of input bytes, when it is + // all ASCII. For other cases, this over-allocates and we will truncate in the end. + char[] resultArr = new char[size]; + int resultPos = 0; + + // Optimize for 100% ASCII (Hotspot loves small simple top-level loops like this). + // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII). + while (address < addressLimit) { + byte b = UnsafeUtil.getByte(address); + if (!DecodeUtil.isOneByte(b)) { + break; + } + address++; + DecodeUtil.handleOneByte(b, resultArr, resultPos++); + } + + while (address < addressLimit) { + byte byte1 = UnsafeUtil.getByte(address++); + if (DecodeUtil.isOneByte(byte1)) { + DecodeUtil.handleOneByte(byte1, resultArr, resultPos++); + // It's common for there to be multiple ASCII characters in a run mixed in, so add an + // extra optimized loop to take care of these runs. + while (address < addressLimit) { + byte b = UnsafeUtil.getByte(address); + if (!DecodeUtil.isOneByte(b)) { + break; + } + address++; + DecodeUtil.handleOneByte(b, resultArr, resultPos++); + } + } else if (DecodeUtil.isTwoBytes(byte1)) { + if (address >= addressLimit) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + DecodeUtil.handleTwoBytes( + byte1, /* byte2 */ UnsafeUtil.getByte(address++), resultArr, resultPos++); + } else if (DecodeUtil.isThreeBytes(byte1)) { + if (address >= addressLimit - 1) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + DecodeUtil.handleThreeBytes( + byte1, + /* byte2 */ UnsafeUtil.getByte(address++), + /* byte3 */ UnsafeUtil.getByte(address++), + resultArr, + resultPos++); + } else { + if (address >= addressLimit - 2) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + DecodeUtil.handleFourBytes( + byte1, + /* byte2 */ UnsafeUtil.getByte(address++), + /* byte3 */ UnsafeUtil.getByte(address++), + /* byte4 */ UnsafeUtil.getByte(address++), + resultArr, + resultPos++); + // 4-byte case requires two chars. + resultPos++; + } + } + + return new String(resultArr, 0, resultPos); + } + @Override int encodeUtf8(final CharSequence in, final byte[] out, final int offset, final int length) { long outIx = offset; @@ -1196,7 +1527,7 @@ int encodeUtf8(final CharSequence in, final byte[] out, final int offset, final } // Designed to take advantage of - // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination + // https://wiki.openjdk.java.net/display/HotSpotInternals/RangeCheckElimination int inIx = 0; for (char c; inIx < inLimit && (c = in.charAt(inIx)) < 0x80; ++inIx) { UnsafeUtil.putByte(out, outIx++, (byte) c); @@ -1258,7 +1589,7 @@ void encodeUtf8Direct(CharSequence in, ByteBuffer out) { } // Designed to take advantage of - // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination + // https://wiki.openjdk.java.net/display/HotSpotInternals/RangeCheckElimination int inIx = 0; for (char c; inIx < inLimit && (c = in.charAt(inIx)) < 0x80; ++inIx) { UnsafeUtil.putByte(outIx++, (byte) c); @@ -1315,8 +1646,8 @@ void encodeUtf8Direct(CharSequence in, ByteBuffer out) { * @param bytes the array containing the character sequence * @param offset the offset position of the index (same as index + arrayBaseOffset) * @param maxChars the maximum number of characters to count - * @return the number of ASCII characters found. The stopping position will be at or - * before the first non-ASCII byte. + * @return the number of ASCII characters found. The stopping position will be at or before the + * first non-ASCII byte. */ private static int unsafeEstimateConsecutiveAscii( byte[] bytes, long offset, final int maxChars) { @@ -1347,7 +1678,7 @@ private static int unsafeEstimateConsecutiveAscii(long address, final int maxCha // Read bytes until 8-byte aligned so that we can read longs in the loop below. // We do this by ANDing the address with 7 to determine the number of bytes that need to // be read before we're 8-byte aligned. - final int unaligned = (int) address & 7; + final int unaligned = 8 - ((int) address & 7); for (int j = unaligned; j > 0; j--) { if (UnsafeUtil.getByte(address++) < 0) { return unaligned - j; @@ -1358,24 +1689,24 @@ private static int unsafeEstimateConsecutiveAscii(long address, final int maxCha // To speed things up further, we're reading longs instead of bytes so we use a mask to // determine if any byte in the current long is non-ASCII. remaining -= unaligned; - for (; remaining >= 8 && (UnsafeUtil.getLong(address) & ASCII_MASK_LONG) == 0; + for (; + remaining >= 8 && (UnsafeUtil.getLong(address) & ASCII_MASK_LONG) == 0; address += 8, remaining -= 8) {} return maxChars - remaining; } private static int partialIsValidUtf8(final byte[] bytes, long offset, int remaining) { - // Skip past ASCII characters as quickly as possible. + // Skip past ASCII characters as quickly as possible. final int skipped = unsafeEstimateConsecutiveAscii(bytes, offset, remaining); remaining -= skipped; offset += skipped; - for (;;) { + for (; ; ) { // Optimize for interior runs of ASCII bytes. // TODO(nathanmittler): Consider checking 8 bytes at a time after some threshold? // Maybe after seeing a few in a row that are ASCII, go back to fast mode? int byte1 = 0; - for (; remaining > 0 && (byte1 = UnsafeUtil.getByte(bytes, offset++)) >= 0; --remaining) { - } + for (; remaining > 0 && (byte1 = UnsafeUtil.getByte(bytes, offset++)) >= 0; --remaining) {} if (remaining == 0) { return COMPLETE; } @@ -1392,8 +1723,7 @@ private static int partialIsValidUtf8(final byte[] bytes, long offset, int remai // Simultaneously checks for illegal trailing-byte in // leading position and overlong 2-byte form. - if (byte1 < (byte) 0xC2 - || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) { + if (byte1 < (byte) 0xC2 || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) { return MALFORMED; } } else if (byte1 < (byte) 0xF0) { @@ -1445,13 +1775,12 @@ private static int partialIsValidUtf8(long address, int remaining) { address += skipped; remaining -= skipped; - for (;;) { + for (; ; ) { // Optimize for interior runs of ASCII bytes. // TODO(nathanmittler): Consider checking 8 bytes at a time after some threshold? // Maybe after seeing a few in a row that are ASCII, go back to fast mode? int byte1 = 0; - for (; remaining > 0 && (byte1 = UnsafeUtil.getByte(address++)) >= 0; --remaining) { - } + for (; remaining > 0 && (byte1 = UnsafeUtil.getByte(address++)) >= 0; --remaining) {} if (remaining == 0) { return COMPLETE; } @@ -1516,43 +1845,132 @@ private static int partialIsValidUtf8(long address, int remaining) { } } - private static int unsafeIncompleteStateFor(byte[] bytes, int byte1, long offset, - int remaining) { + private static int unsafeIncompleteStateFor( + byte[] bytes, int byte1, long offset, int remaining) { switch (remaining) { - case 0: { + case 0: return incompleteStateFor(byte1); - } - case 1: { + case 1: return incompleteStateFor(byte1, UnsafeUtil.getByte(bytes, offset)); - } - case 2: { - return incompleteStateFor(byte1, UnsafeUtil.getByte(bytes, offset), - UnsafeUtil.getByte(bytes, offset + 1)); - } - default: { + case 2: + return incompleteStateFor( + byte1, UnsafeUtil.getByte(bytes, offset), UnsafeUtil.getByte(bytes, offset + 1)); + default: throw new AssertionError(); - } } } private static int unsafeIncompleteStateFor(long address, final int byte1, int remaining) { switch (remaining) { - case 0: { + case 0: return incompleteStateFor(byte1); - } - case 1: { + case 1: return incompleteStateFor(byte1, UnsafeUtil.getByte(address)); - } - case 2: { - return incompleteStateFor(byte1, UnsafeUtil.getByte(address), - UnsafeUtil.getByte(address + 1)); - } - default: { + case 2: + return incompleteStateFor( + byte1, UnsafeUtil.getByte(address), UnsafeUtil.getByte(address + 1)); + default: throw new AssertionError(); - } } } } + /** + * Utility methods for decoding bytes into {@link String}. Callers are responsible for extracting + * bytes (possibly using Unsafe methods), and checking remaining bytes. All other UTF-8 validity + * checks and codepoint conversion happen in this class. + */ + private static class DecodeUtil { + + /** Returns whether this is a single-byte codepoint (i.e., ASCII) with the form '0XXXXXXX'. */ + private static boolean isOneByte(byte b) { + return b >= 0; + } + + /** Returns whether this is a two-byte codepoint with the form '10XXXXXX'. */ + private static boolean isTwoBytes(byte b) { + return b < (byte) 0xE0; + } + + /** Returns whether this is a three-byte codepoint with the form '110XXXXX'. */ + private static boolean isThreeBytes(byte b) { + return b < (byte) 0xF0; + } + + private static void handleOneByte(byte byte1, char[] resultArr, int resultPos) { + resultArr[resultPos] = (char) byte1; + } + + private static void handleTwoBytes(byte byte1, byte byte2, char[] resultArr, int resultPos) + throws InvalidProtocolBufferException { + // Simultaneously checks for illegal trailing-byte in leading position (<= '11000000') and + // overlong 2-byte, '11000001'. + if (byte1 < (byte) 0xC2 || isNotTrailingByte(byte2)) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + resultArr[resultPos] = (char) (((byte1 & 0x1F) << 6) | trailingByteValue(byte2)); + } + + private static void handleThreeBytes( + byte byte1, byte byte2, byte byte3, char[] resultArr, int resultPos) + throws InvalidProtocolBufferException { + if (isNotTrailingByte(byte2) + // overlong? 5 most significant bits must not all be zero + || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0) + // check for illegal surrogate codepoints + || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0) + || isNotTrailingByte(byte3)) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + resultArr[resultPos] = + (char) + (((byte1 & 0x0F) << 12) | (trailingByteValue(byte2) << 6) | trailingByteValue(byte3)); + } + + private static void handleFourBytes( + byte byte1, byte byte2, byte byte3, byte byte4, char[] resultArr, int resultPos) + throws InvalidProtocolBufferException { + if (isNotTrailingByte(byte2) + // Check that 1 <= plane <= 16. Tricky optimized form of: + // valid 4-byte leading byte? + // if (byte1 > (byte) 0xF4 || + // overlong? 4 most significant bits must not all be zero + // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 || + // codepoint larger than the highest code point (U+10FFFF)? + // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F) + || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0 + || isNotTrailingByte(byte3) + || isNotTrailingByte(byte4)) { + throw InvalidProtocolBufferException.invalidUtf8(); + } + int codepoint = + ((byte1 & 0x07) << 18) + | (trailingByteValue(byte2) << 12) + | (trailingByteValue(byte3) << 6) + | trailingByteValue(byte4); + resultArr[resultPos] = DecodeUtil.highSurrogate(codepoint); + resultArr[resultPos + 1] = DecodeUtil.lowSurrogate(codepoint); + } + + /** Returns whether the byte is not a valid continuation of the form '10XXXXXX'. */ + private static boolean isNotTrailingByte(byte b) { + return b > (byte) 0xBF; + } + + /** Returns the actual value of the trailing byte (removes the prefix '10') for composition. */ + private static int trailingByteValue(byte b) { + return b & 0x3F; + } + + private static char highSurrogate(int codePoint) { + return (char) + ((MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT >>> 10)) + (codePoint >>> 10)); + } + + private static char lowSurrogate(int codePoint) { + return (char) (MIN_LOW_SURROGATE + (codePoint & 0x3ff)); + } + } + private Utf8() {} } diff --git a/java/core/src/main/java/com/google/protobuf/WireFormat.java b/java/core/src/main/java/com/google/protobuf/WireFormat.java index 8b837ee5e1ab1..3c6e8dda4de1b 100644 --- a/java/core/src/main/java/com/google/protobuf/WireFormat.java +++ b/java/core/src/main/java/com/google/protobuf/WireFormat.java @@ -33,13 +33,12 @@ import java.io.IOException; /** - * This class is used internally by the Protocol Buffer library and generated - * message implementations. It is public only because those generated messages - * do not reside in the {@code protobuf} package. Others should not use this - * class directly. + * This class is used internally by the Protocol Buffer library and generated message + * implementations. It is public only because those generated messages do not reside in the {@code + * protobuf} package. Others should not use this class directly. * - * This class contains constants and helper functions useful for dealing with - * the Protocol Buffer wire format. + *

This class contains constants and helper functions useful for dealing with the Protocol Buffer + * wire format. * * @author kenton@google.com Kenton Varda */ @@ -53,12 +52,12 @@ private WireFormat() {} static final int MAX_VARINT64_SIZE = 10; static final int MAX_VARINT_SIZE = 10; - public static final int WIRETYPE_VARINT = 0; - public static final int WIRETYPE_FIXED64 = 1; + public static final int WIRETYPE_VARINT = 0; + public static final int WIRETYPE_FIXED64 = 1; public static final int WIRETYPE_LENGTH_DELIMITED = 2; - public static final int WIRETYPE_START_GROUP = 3; - public static final int WIRETYPE_END_GROUP = 4; - public static final int WIRETYPE_FIXED32 = 5; + public static final int WIRETYPE_START_GROUP = 3; + public static final int WIRETYPE_END_GROUP = 4; + public static final int WIRETYPE_FIXED32 = 5; static final int TAG_TYPE_BITS = 3; static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1; @@ -79,8 +78,8 @@ static int makeTag(final int fieldNumber, final int wireType) { } /** - * Lite equivalent to {@link Descriptors.FieldDescriptor.JavaType}. This is - * only here to support the lite runtime and should not be used by users. + * Lite equivalent to {@link Descriptors.FieldDescriptor.JavaType}. This is only here to support + * the lite runtime and should not be used by users. */ public enum JavaType { INT(0), @@ -97,10 +96,7 @@ public enum JavaType { this.defaultDefault = defaultDefault; } - /** - * The default default value for fields of this type, if it's a primitive - * type. - */ + /** The default default value for fields of this type, if it's a primitive type. */ Object getDefaultDefault() { return defaultDefault; } @@ -109,44 +105,48 @@ Object getDefaultDefault() { } /** - * Lite equivalent to {@link Descriptors.FieldDescriptor.Type}. This is - * only here to support the lite runtime and should not be used by users. + * Lite equivalent to {@link Descriptors.FieldDescriptor.Type}. This is only here to support the + * lite runtime and should not be used by users. */ public enum FieldType { - DOUBLE (JavaType.DOUBLE , WIRETYPE_FIXED64 ), - FLOAT (JavaType.FLOAT , WIRETYPE_FIXED32 ), - INT64 (JavaType.LONG , WIRETYPE_VARINT ), - UINT64 (JavaType.LONG , WIRETYPE_VARINT ), - INT32 (JavaType.INT , WIRETYPE_VARINT ), - FIXED64 (JavaType.LONG , WIRETYPE_FIXED64 ), - FIXED32 (JavaType.INT , WIRETYPE_FIXED32 ), - BOOL (JavaType.BOOLEAN , WIRETYPE_VARINT ), - STRING (JavaType.STRING , WIRETYPE_LENGTH_DELIMITED) { + DOUBLE(JavaType.DOUBLE, WIRETYPE_FIXED64), + FLOAT(JavaType.FLOAT, WIRETYPE_FIXED32), + INT64(JavaType.LONG, WIRETYPE_VARINT), + UINT64(JavaType.LONG, WIRETYPE_VARINT), + INT32(JavaType.INT, WIRETYPE_VARINT), + FIXED64(JavaType.LONG, WIRETYPE_FIXED64), + FIXED32(JavaType.INT, WIRETYPE_FIXED32), + BOOL(JavaType.BOOLEAN, WIRETYPE_VARINT), + STRING(JavaType.STRING, WIRETYPE_LENGTH_DELIMITED) { @Override public boolean isPackable() { - return false; } + return false; + } }, - GROUP (JavaType.MESSAGE , WIRETYPE_START_GROUP ) { + GROUP(JavaType.MESSAGE, WIRETYPE_START_GROUP) { @Override public boolean isPackable() { - return false; } + return false; + } }, - MESSAGE (JavaType.MESSAGE , WIRETYPE_LENGTH_DELIMITED) { + MESSAGE(JavaType.MESSAGE, WIRETYPE_LENGTH_DELIMITED) { @Override public boolean isPackable() { - return false; } + return false; + } }, - BYTES (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED) { + BYTES(JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED) { @Override public boolean isPackable() { - return false; } + return false; + } }, - UINT32 (JavaType.INT , WIRETYPE_VARINT ), - ENUM (JavaType.ENUM , WIRETYPE_VARINT ), - SFIXED32(JavaType.INT , WIRETYPE_FIXED32 ), - SFIXED64(JavaType.LONG , WIRETYPE_FIXED64 ), - SINT32 (JavaType.INT , WIRETYPE_VARINT ), - SINT64 (JavaType.LONG , WIRETYPE_VARINT ); + UINT32(JavaType.INT, WIRETYPE_VARINT), + ENUM(JavaType.ENUM, WIRETYPE_VARINT), + SFIXED32(JavaType.INT, WIRETYPE_FIXED32), + SFIXED64(JavaType.LONG, WIRETYPE_FIXED64), + SINT32(JavaType.INT, WIRETYPE_VARINT), + SINT64(JavaType.LONG, WIRETYPE_VARINT); FieldType(final JavaType javaType, final int wireType) { this.javaType = javaType; @@ -156,30 +156,34 @@ public boolean isPackable() { private final JavaType javaType; private final int wireType; - public JavaType getJavaType() { return javaType; } - public int getWireType() { return wireType; } + public JavaType getJavaType() { + return javaType; + } - public boolean isPackable() { return true; } + public int getWireType() { + return wireType; + } + + public boolean isPackable() { + return true; + } } // Field numbers for fields in MessageSet wire format. - static final int MESSAGE_SET_ITEM = 1; + static final int MESSAGE_SET_ITEM = 1; static final int MESSAGE_SET_TYPE_ID = 2; static final int MESSAGE_SET_MESSAGE = 3; // Tag numbers. - static final int MESSAGE_SET_ITEM_TAG = - makeTag(MESSAGE_SET_ITEM, WIRETYPE_START_GROUP); - static final int MESSAGE_SET_ITEM_END_TAG = - makeTag(MESSAGE_SET_ITEM, WIRETYPE_END_GROUP); - static final int MESSAGE_SET_TYPE_ID_TAG = - makeTag(MESSAGE_SET_TYPE_ID, WIRETYPE_VARINT); + static final int MESSAGE_SET_ITEM_TAG = makeTag(MESSAGE_SET_ITEM, WIRETYPE_START_GROUP); + static final int MESSAGE_SET_ITEM_END_TAG = makeTag(MESSAGE_SET_ITEM, WIRETYPE_END_GROUP); + static final int MESSAGE_SET_TYPE_ID_TAG = makeTag(MESSAGE_SET_TYPE_ID, WIRETYPE_VARINT); static final int MESSAGE_SET_MESSAGE_TAG = - makeTag(MESSAGE_SET_MESSAGE, WIRETYPE_LENGTH_DELIMITED); + makeTag(MESSAGE_SET_MESSAGE, WIRETYPE_LENGTH_DELIMITED); /** - * Validation level for handling incoming string field data which potentially - * contain non-UTF8 bytes. + * Validation level for handling incoming string field data which potentially contain non-UTF8 + * bytes. */ enum Utf8Validation { /** Eagerly parses to String; silently accepts invalid UTF8 bytes. */ @@ -209,54 +213,59 @@ Object readString(CodedInputStream input) throws IOException { } /** - * Read a field of any primitive type for immutable messages from a - * CodedInputStream. Enums, groups, and embedded messages are not handled by - * this method. + * Read a field of any primitive type for immutable messages from a CodedInputStream. Enums, + * groups, and embedded messages are not handled by this method. * * @param input The stream from which to read. * @param type Declared type of the field. - * @param utf8Validation Different string UTF8 validation level for handling - * string fields. - * @return An object representing the field's value, of the exact - * type which would be returned by - * {@link Message#getField(Descriptors.FieldDescriptor)} for - * this field. + * @param utf8Validation Different string UTF8 validation level for handling string fields. + * @return An object representing the field's value, of the exact type which would be returned by + * {@link Message#getField(Descriptors.FieldDescriptor)} for this field. */ static Object readPrimitiveField( - CodedInputStream input, - FieldType type, - Utf8Validation utf8Validation) throws IOException { + CodedInputStream input, FieldType type, Utf8Validation utf8Validation) throws IOException { switch (type) { - case DOUBLE : return input.readDouble (); - case FLOAT : return input.readFloat (); - case INT64 : return input.readInt64 (); - case UINT64 : return input.readUInt64 (); - case INT32 : return input.readInt32 (); - case FIXED64 : return input.readFixed64 (); - case FIXED32 : return input.readFixed32 (); - case BOOL : return input.readBool (); - case BYTES : return input.readBytes (); - case UINT32 : return input.readUInt32 (); - case SFIXED32: return input.readSFixed32(); - case SFIXED64: return input.readSFixed64(); - case SINT32 : return input.readSInt32 (); - case SINT64 : return input.readSInt64 (); + case DOUBLE: + return input.readDouble(); + case FLOAT: + return input.readFloat(); + case INT64: + return input.readInt64(); + case UINT64: + return input.readUInt64(); + case INT32: + return input.readInt32(); + case FIXED64: + return input.readFixed64(); + case FIXED32: + return input.readFixed32(); + case BOOL: + return input.readBool(); + case BYTES: + return input.readBytes(); + case UINT32: + return input.readUInt32(); + case SFIXED32: + return input.readSFixed32(); + case SFIXED64: + return input.readSFixed64(); + case SINT32: + return input.readSInt32(); + case SINT64: + return input.readSInt64(); - case STRING : return utf8Validation.readString(input); + case STRING: + return utf8Validation.readString(input); case GROUP: - throw new IllegalArgumentException( - "readPrimitiveField() cannot handle nested groups."); + throw new IllegalArgumentException("readPrimitiveField() cannot handle nested groups."); case MESSAGE: - throw new IllegalArgumentException( - "readPrimitiveField() cannot handle embedded messages."); + throw new IllegalArgumentException("readPrimitiveField() cannot handle embedded messages."); case ENUM: // We don't handle enums because we don't know what to do if the // value is not recognized. - throw new IllegalArgumentException( - "readPrimitiveField() cannot handle enums."); + throw new IllegalArgumentException("readPrimitiveField() cannot handle enums."); } - throw new RuntimeException( - "There is no way to get here, but the compiler thinks otherwise."); + throw new RuntimeException("There is no way to get here, but the compiler thinks otherwise."); } } diff --git a/java/core/src/main/java/com/google/protobuf/Writer.java b/java/core/src/main/java/com/google/protobuf/Writer.java new file mode 100644 index 0000000000000..3f95c325de46e --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/Writer.java @@ -0,0 +1,219 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +/** A writer that performs serialization of protobuf message fields. */ +@ExperimentalApi +interface Writer { + + /** The order in which the fields are written by a {@link Writer}. */ + enum FieldOrder { + /** Fields are written in ascending order by field number. */ + ASCENDING, + + /** Fields are written in descending order by field number. */ + DESCENDING + } + + /** Indicates the order in which the fields are written by this {@link Writer}. */ + FieldOrder fieldOrder(); + + /** Writes a field of type {@link FieldType#SFIXED32}. */ + void writeSFixed32(int fieldNumber, int value) throws IOException; + + /** Writes a field of type {@link FieldType#INT64}. */ + void writeInt64(int fieldNumber, long value) throws IOException; + + /** Writes a field of type {@link FieldType#SFIXED64}. */ + void writeSFixed64(int fieldNumber, long value) throws IOException; + + /** Writes a field of type {@link FieldType#FLOAT}. */ + void writeFloat(int fieldNumber, float value) throws IOException; + + /** Writes a field of type {@link FieldType#DOUBLE}. */ + void writeDouble(int fieldNumber, double value) throws IOException; + + /** Writes a field of type {@link FieldType#ENUM}. */ + void writeEnum(int fieldNumber, int value) throws IOException; + + /** Writes a field of type {@link FieldType#UINT64}. */ + void writeUInt64(int fieldNumber, long value) throws IOException; + + /** Writes a field of type {@link FieldType#INT32}. */ + void writeInt32(int fieldNumber, int value) throws IOException; + + /** Writes a field of type {@link FieldType#FIXED64}. */ + void writeFixed64(int fieldNumber, long value) throws IOException; + + /** Writes a field of type {@link FieldType#FIXED32}. */ + void writeFixed32(int fieldNumber, int value) throws IOException; + + /** Writes a field of type {@link FieldType#BOOL}. */ + void writeBool(int fieldNumber, boolean value) throws IOException; + + /** Writes a field of type {@link FieldType#STRING}. */ + void writeString(int fieldNumber, String value) throws IOException; + + /** Writes a field of type {@link FieldType#BYTES}. */ + void writeBytes(int fieldNumber, ByteString value) throws IOException; + + /** Writes a field of type {@link FieldType#UINT32}. */ + void writeUInt32(int fieldNumber, int value) throws IOException; + + /** Writes a field of type {@link FieldType#SINT32}. */ + void writeSInt32(int fieldNumber, int value) throws IOException; + + /** Writes a field of type {@link FieldType#SINT64}. */ + void writeSInt64(int fieldNumber, long value) throws IOException; + + /** Writes a field of type {@link FieldType#MESSAGE}. */ + void writeMessage(int fieldNumber, Object value) throws IOException; + + /** Writes a field of type {@link FieldType#MESSAGE}. */ + void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException; + + /** + * Writes a field of type {@link FieldType#GROUP}. + * + * @deprecated groups fields are deprecated. + */ + @Deprecated + void writeGroup(int fieldNumber, Object value) throws IOException; + + /** + * Writes a field of type {@link FieldType#GROUP}. + * + * @deprecated groups fields are deprecated. + */ + @Deprecated + void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException; + + /** + * Writes a single start group tag. + * + * @deprecated groups fields are deprecated. + */ + @Deprecated + void writeStartGroup(int fieldNumber) throws IOException; + + /** + * Writes a single end group tag. + * + * @deprecated groups fields are deprecated. + */ + @Deprecated + void writeEndGroup(int fieldNumber) throws IOException; + + /** Writes a list field of type {@link FieldType#INT32}. */ + void writeInt32List(int fieldNumber, List value, boolean packed) throws IOException; + + /** Writes a list field of type {@link FieldType#FIXED32}. */ + void writeFixed32List(int fieldNumber, List value, boolean packed) throws IOException; + + /** Writes a list field of type {@link FieldType#INT64}. */ + void writeInt64List(int fieldNumber, List value, boolean packed) throws IOException; + + /** Writes a list field of type {@link FieldType#UINT64}. */ + void writeUInt64List(int fieldNumber, List value, boolean packed) throws IOException; + + /** Writes a list field of type {@link FieldType#FIXED64}. */ + void writeFixed64List(int fieldNumber, List value, boolean packed) throws IOException; + + /** Writes a list field of type {@link FieldType#FLOAT}. */ + void writeFloatList(int fieldNumber, List value, boolean packed) throws IOException; + + /** Writes a list field of type {@link FieldType#DOUBLE}. */ + void writeDoubleList(int fieldNumber, List value, boolean packed) throws IOException; + + /** Writes a list field of type {@link FieldType#ENUM}. */ + void writeEnumList(int fieldNumber, List value, boolean packed) throws IOException; + + /** Writes a list field of type {@link FieldType#BOOL}. */ + void writeBoolList(int fieldNumber, List value, boolean packed) throws IOException; + + /** Writes a list field of type {@link FieldType#STRING}. */ + void writeStringList(int fieldNumber, List value) throws IOException; + + /** Writes a list field of type {@link FieldType#BYTES}. */ + void writeBytesList(int fieldNumber, List value) throws IOException; + + /** Writes a list field of type {@link FieldType#UINT32}. */ + void writeUInt32List(int fieldNumber, List value, boolean packed) throws IOException; + + /** Writes a list field of type {@link FieldType#SFIXED32}. */ + void writeSFixed32List(int fieldNumber, List value, boolean packed) throws IOException; + + /** Writes a list field of type {@link FieldType#SFIXED64}. */ + void writeSFixed64List(int fieldNumber, List value, boolean packed) throws IOException; + + /** Writes a list field of type {@link FieldType#SINT32}. */ + void writeSInt32List(int fieldNumber, List value, boolean packed) throws IOException; + + /** Writes a list field of type {@link FieldType#SINT64}. */ + void writeSInt64List(int fieldNumber, List value, boolean packed) throws IOException; + + /** Writes a list field of type {@link FieldType#MESSAGE}. */ + void writeMessageList(int fieldNumber, List value) throws IOException; + + /** Writes a list field of type {@link FieldType#MESSAGE}. */ + void writeMessageList(int fieldNumber, List value, Schema schema) throws IOException; + + /** + * Writes a list field of type {@link FieldType#GROUP}. + * + * @deprecated groups fields are deprecated. + */ + @Deprecated + void writeGroupList(int fieldNumber, List value) throws IOException; + + /** + * Writes a list field of type {@link FieldType#GROUP}. + * + * @deprecated groups fields are deprecated. + */ + @Deprecated + void writeGroupList(int fieldNumber, List value, Schema schema) throws IOException; + + /** + * Writes a message field in {@code MessageSet} wire-format. + * + * @param value A message instance or an opaque {@link ByteString} for an unknown field. + */ + void writeMessageSetItem(int fieldNumber, Object value) throws IOException; + + /** Writes a map field. */ + void writeMap(int fieldNumber, MapEntryLite.Metadata metadata, Map map) + throws IOException; +} diff --git a/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java b/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java index 622e36a413380..cc979ac513292 100644 --- a/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java +++ b/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java @@ -30,6 +30,9 @@ package com.google.protobuf; +import static com.google.protobuf.TestUtil.TEST_REQUIRED_INITIALIZED; +import static com.google.protobuf.TestUtil.TEST_REQUIRED_UNINITIALIZED; + import com.google.protobuf.Descriptors.FieldDescriptor; import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize; import protobuf_unittest.UnittestProto; @@ -50,10 +53,9 @@ */ public class AbstractMessageTest extends TestCase { /** - * Extends AbstractMessage and wraps some other message object. The methods - * of the Message interface which aren't explicitly implemented by - * AbstractMessage are forwarded to the wrapped object. This allows us to - * test that AbstractMessage's implementations work even if the wrapped + * Extends AbstractMessage and wraps some other message object. The methods of the Message + * interface which aren't explicitly implemented by AbstractMessage are forwarded to the wrapped + * object. This allows us to test that AbstractMessage's implementations work even if the wrapped * object does not use them. */ private static class AbstractMessageWrapper extends AbstractMessage { @@ -67,39 +69,47 @@ public AbstractMessageWrapper(Message wrappedMessage) { public Descriptors.Descriptor getDescriptorForType() { return wrappedMessage.getDescriptorForType(); } + @Override public AbstractMessageWrapper getDefaultInstanceForType() { - return new AbstractMessageWrapper( - wrappedMessage.getDefaultInstanceForType()); + return new AbstractMessageWrapper(wrappedMessage.getDefaultInstanceForType()); } + @Override public Map getAllFields() { return wrappedMessage.getAllFields(); } + @Override public boolean hasField(Descriptors.FieldDescriptor field) { return wrappedMessage.hasField(field); } + @Override public Object getField(Descriptors.FieldDescriptor field) { return wrappedMessage.getField(field); } + @Override public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) { return wrappedMessage.getRepeatedFieldCount(field); } + @Override public Object getRepeatedField(Descriptors.FieldDescriptor field, int index) { return wrappedMessage.getRepeatedField(field, index); } + @Override public UnknownFieldSet getUnknownFields() { return wrappedMessage.getUnknownFields(); } + @Override public Builder newBuilderForType() { return new Builder(wrappedMessage.newBuilderForType()); } + @Override public Builder toBuilder() { return new Builder(wrappedMessage.toBuilder()); @@ -116,85 +126,103 @@ public Builder(Message.Builder wrappedBuilder) { public AbstractMessageWrapper build() { return new AbstractMessageWrapper(wrappedBuilder.build()); } + @Override public AbstractMessageWrapper buildPartial() { return new AbstractMessageWrapper(wrappedBuilder.buildPartial()); } + @Override public Builder clone() { return new Builder(wrappedBuilder.clone()); } + @Override public boolean isInitialized() { return clone().buildPartial().isInitialized(); } + @Override public Descriptors.Descriptor getDescriptorForType() { return wrappedBuilder.getDescriptorForType(); } + @Override public AbstractMessageWrapper getDefaultInstanceForType() { - return new AbstractMessageWrapper( - wrappedBuilder.getDefaultInstanceForType()); + return new AbstractMessageWrapper(wrappedBuilder.getDefaultInstanceForType()); } + @Override public Map getAllFields() { return wrappedBuilder.getAllFields(); } + @Override public Builder newBuilderForField(Descriptors.FieldDescriptor field) { return new Builder(wrappedBuilder.newBuilderForField(field)); } + @Override public boolean hasField(Descriptors.FieldDescriptor field) { return wrappedBuilder.hasField(field); } + @Override public Object getField(Descriptors.FieldDescriptor field) { return wrappedBuilder.getField(field); } + @Override public Builder setField(Descriptors.FieldDescriptor field, Object value) { wrappedBuilder.setField(field, value); return this; } + @Override public Builder clearField(Descriptors.FieldDescriptor field) { wrappedBuilder.clearField(field); return this; } + @Override public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) { return wrappedBuilder.getRepeatedFieldCount(field); } + @Override public Object getRepeatedField(Descriptors.FieldDescriptor field, int index) { return wrappedBuilder.getRepeatedField(field, index); } + @Override public Builder setRepeatedField(Descriptors.FieldDescriptor field, int index, Object value) { wrappedBuilder.setRepeatedField(field, index, value); return this; } + @Override public Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value) { wrappedBuilder.addRepeatedField(field, value); return this; } + @Override public UnknownFieldSet getUnknownFields() { return wrappedBuilder.getUnknownFields(); } + @Override public Builder setUnknownFields(UnknownFieldSet unknownFields) { wrappedBuilder.setUnknownFields(unknownFields); return this; } + @Override public Message.Builder getFieldBuilder(FieldDescriptor field) { return wrappedBuilder.getFieldBuilder(field); } } + @Override public Parser getParserForType() { return wrappedMessage.getParserForType(); @@ -204,24 +232,25 @@ public Parser getParserForType() { // ================================================================= TestUtil.ReflectionTester reflectionTester = - new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null); + new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null); TestUtil.ReflectionTester extensionsReflectionTester = - new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(), - TestUtil.getExtensionRegistry()); + new TestUtil.ReflectionTester( + TestAllExtensions.getDescriptor(), TestUtil.getFullExtensionRegistry()); public void testClear() throws Exception { AbstractMessageWrapper message = - new AbstractMessageWrapper.Builder( - TestAllTypes.newBuilder(TestUtil.getAllSet())) - .clear().build(); + new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder(TestUtil.getAllSet())) + .clear() + .build(); TestUtil.assertClear((TestAllTypes) message.wrappedMessage); } public void testCopy() throws Exception { AbstractMessageWrapper message = - new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder()) - .mergeFrom(TestUtil.getAllSet()).build(); + new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder()) + .mergeFrom(TestUtil.getAllSet()) + .build(); TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage); } @@ -229,25 +258,21 @@ public void testSerializedSize() throws Exception { TestAllTypes message = TestUtil.getAllSet(); Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet()); - assertEquals(message.getSerializedSize(), - abstractMessage.getSerializedSize()); + assertEquals(message.getSerializedSize(), abstractMessage.getSerializedSize()); } public void testSerialization() throws Exception { Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet()); - TestUtil.assertAllFieldsSet( - TestAllTypes.parseFrom(abstractMessage.toByteString())); + TestUtil.assertAllFieldsSet(TestAllTypes.parseFrom(abstractMessage.toByteString())); - assertEquals(TestUtil.getAllSet().toByteString(), - abstractMessage.toByteString()); + assertEquals(TestUtil.getAllSet().toByteString(), abstractMessage.toByteString()); } public void testParsing() throws Exception { AbstractMessageWrapper.Builder builder = - new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder()); - AbstractMessageWrapper message = - builder.mergeFrom(TestUtil.getAllSet().toByteString()).build(); + new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder()); + AbstractMessageWrapper message = builder.mergeFrom(TestUtil.getAllSet().toByteString()).build(); TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage); } @@ -267,8 +292,8 @@ public void testParsingUninitialized() throws Exception { } // test DynamicMessage directly. - Message.Builder dynamicMessageBuilder = DynamicMessage.newBuilder( - TestRequiredForeign.getDescriptor()); + Message.Builder dynamicMessageBuilder = + DynamicMessage.newBuilder(TestRequiredForeign.getDescriptor()); // mergeFrom() should not throw initialization error. dynamicMessageBuilder.mergeFrom(bytes).buildPartial(); try { @@ -280,65 +305,56 @@ public void testParsingUninitialized() throws Exception { } public void testPackedSerialization() throws Exception { - Message abstractMessage = - new AbstractMessageWrapper(TestUtil.getPackedSet()); + Message abstractMessage = new AbstractMessageWrapper(TestUtil.getPackedSet()); - TestUtil.assertPackedFieldsSet( - TestPackedTypes.parseFrom(abstractMessage.toByteString())); + TestUtil.assertPackedFieldsSet(TestPackedTypes.parseFrom(abstractMessage.toByteString())); - assertEquals(TestUtil.getPackedSet().toByteString(), - abstractMessage.toByteString()); + assertEquals(TestUtil.getPackedSet().toByteString(), abstractMessage.toByteString()); } public void testPackedParsing() throws Exception { AbstractMessageWrapper.Builder builder = - new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder()); + new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder()); AbstractMessageWrapper message = - builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build(); + builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build(); TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage); } public void testUnpackedSerialization() throws Exception { - Message abstractMessage = - new AbstractMessageWrapper(TestUtil.getUnpackedSet()); + Message abstractMessage = new AbstractMessageWrapper(TestUtil.getUnpackedSet()); - TestUtil.assertUnpackedFieldsSet( - TestUnpackedTypes.parseFrom(abstractMessage.toByteString())); + TestUtil.assertUnpackedFieldsSet(TestUnpackedTypes.parseFrom(abstractMessage.toByteString())); - assertEquals(TestUtil.getUnpackedSet().toByteString(), - abstractMessage.toByteString()); + assertEquals(TestUtil.getUnpackedSet().toByteString(), abstractMessage.toByteString()); } public void testParsePackedToUnpacked() throws Exception { AbstractMessageWrapper.Builder builder = - new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder()); + new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder()); AbstractMessageWrapper message = - builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build(); - TestUtil.assertUnpackedFieldsSet( - (TestUnpackedTypes) message.wrappedMessage); + builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build(); + TestUtil.assertUnpackedFieldsSet((TestUnpackedTypes) message.wrappedMessage); } public void testParseUnpackedToPacked() throws Exception { AbstractMessageWrapper.Builder builder = - new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder()); + new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder()); AbstractMessageWrapper message = - builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build(); + builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build(); TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage); } public void testUnpackedParsing() throws Exception { AbstractMessageWrapper.Builder builder = - new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder()); + new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder()); AbstractMessageWrapper message = - builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build(); - TestUtil.assertUnpackedFieldsSet( - (TestUnpackedTypes) message.wrappedMessage); + builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build(); + TestUtil.assertUnpackedFieldsSet((TestUnpackedTypes) message.wrappedMessage); } public void testOptimizedForSize() throws Exception { // We're mostly only checking that this class was compiled successfully. - TestOptimizedForSize message = - TestOptimizedForSize.newBuilder().setI(1).build(); + TestOptimizedForSize message = TestOptimizedForSize.newBuilder().setI(1).build(); message = TestOptimizedForSize.parseFrom(message.toByteString()); assertEquals(2, message.getSerializedSize()); } @@ -346,15 +362,9 @@ public void testOptimizedForSize() throws Exception { // ----------------------------------------------------------------- // Tests for isInitialized(). - private static final TestRequired TEST_REQUIRED_UNINITIALIZED = - TestRequired.getDefaultInstance(); - private static final TestRequired TEST_REQUIRED_INITIALIZED = - TestRequired.newBuilder().setA(1).setB(2).setC(3).build(); - public void testIsInitialized() throws Exception { TestRequired.Builder builder = TestRequired.newBuilder(); - AbstractMessageWrapper.Builder abstractBuilder = - new AbstractMessageWrapper.Builder(builder); + AbstractMessageWrapper.Builder abstractBuilder = new AbstractMessageWrapper.Builder(builder); assertFalse(abstractBuilder.isInitialized()); assertEquals("a, b, c", abstractBuilder.getInitializationErrorString()); @@ -371,8 +381,7 @@ public void testIsInitialized() throws Exception { public void testForeignIsInitialized() throws Exception { TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder(); - AbstractMessageWrapper.Builder abstractBuilder = - new AbstractMessageWrapper.Builder(builder); + AbstractMessageWrapper.Builder abstractBuilder = new AbstractMessageWrapper.Builder(builder); assertTrue(abstractBuilder.isInitialized()); assertEquals("", abstractBuilder.getInitializationErrorString()); @@ -380,8 +389,7 @@ public void testForeignIsInitialized() throws Exception { builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED); assertFalse(abstractBuilder.isInitialized()); assertEquals( - "optional_message.a, optional_message.b, optional_message.c", - abstractBuilder.getInitializationErrorString()); + "optional_message.b, optional_message.c", abstractBuilder.getInitializationErrorString()); builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED); assertTrue(abstractBuilder.isInitialized()); @@ -390,7 +398,7 @@ public void testForeignIsInitialized() throws Exception { builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED); assertFalse(abstractBuilder.isInitialized()); assertEquals( - "repeated_message[0].a, repeated_message[0].b, repeated_message[0].c", + "repeated_message[0].b, repeated_message[0].c", abstractBuilder.getInitializationErrorString()); builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED); @@ -402,36 +410,37 @@ public void testForeignIsInitialized() throws Exception { // Tests for mergeFrom static final TestAllTypes MERGE_SOURCE = - TestAllTypes.newBuilder() - .setOptionalInt32(1) - .setOptionalString("foo") - .setOptionalForeignMessage(ForeignMessage.getDefaultInstance()) - .addRepeatedString("bar") - .build(); + TestAllTypes.newBuilder() + .setOptionalInt32(1) + .setOptionalString("foo") + .setOptionalForeignMessage(ForeignMessage.getDefaultInstance()) + .addRepeatedString("bar") + .build(); static final TestAllTypes MERGE_DEST = - TestAllTypes.newBuilder() - .setOptionalInt64(2) - .setOptionalString("baz") - .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build()) - .addRepeatedString("qux") - .build(); + TestAllTypes.newBuilder() + .setOptionalInt64(2) + .setOptionalString("baz") + .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build()) + .addRepeatedString("qux") + .build(); static final String MERGE_RESULT_TEXT = - "optional_int32: 1\n" + - "optional_int64: 2\n" + - "optional_string: \"foo\"\n" + - "optional_foreign_message {\n" + - " c: 3\n" + - "}\n" + - "repeated_string: \"qux\"\n" + - "repeated_string: \"bar\"\n"; + "" + + "optional_int32: 1\n" + + "optional_int64: 2\n" + + "optional_string: \"foo\"\n" + + "optional_foreign_message {\n" + + " c: 3\n" + + "}\n" + + "repeated_string: \"qux\"\n" + + "repeated_string: \"bar\"\n"; public void testMergeFrom() throws Exception { AbstractMessageWrapper result = - new AbstractMessageWrapper.Builder( - TestAllTypes.newBuilder(MERGE_DEST)) - .mergeFrom(MERGE_SOURCE).build(); + new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder(MERGE_DEST)) + .mergeFrom(MERGE_SOURCE) + .build(); assertEquals(MERGE_RESULT_TEXT, result.toString()); } @@ -445,8 +454,10 @@ public void testEqualsAndHashCode() throws Exception { TestAllTypes c = TestAllTypes.newBuilder(b).addRepeatedString("x").build(); TestAllTypes d = TestAllTypes.newBuilder(c).addRepeatedString("y").build(); TestAllExtensions e = TestUtil.getAllExtensionsSet(); - TestAllExtensions f = TestAllExtensions.newBuilder(e) - .addExtension(UnittestProto.repeatedInt32Extension, 999).build(); + TestAllExtensions f = + TestAllExtensions.newBuilder(e) + .addExtension(UnittestProto.repeatedInt32Extension, 999) + .build(); checkEqualsIsConsistent(a); checkEqualsIsConsistent(b); @@ -491,9 +502,7 @@ public void testEqualsAndHashCode() throws Exception { checkEqualsIsConsistent(eUnknownFields, eUnknownFields2); } - /** - * Asserts that the given proto has symmetric equals and hashCode methods. - */ + /** Asserts that the given proto has symmetric equals and hashCode methods. */ private void checkEqualsIsConsistent(Message message) { // Object should be equal to itself. assertEquals(message, message); @@ -503,9 +512,7 @@ private void checkEqualsIsConsistent(Message message) { checkEqualsIsConsistent(message, dynamic); } - /** - * Asserts that the given protos are equal and have the same hash code. - */ + /** Asserts that the given protos are equal and have the same hash code. */ private void checkEqualsIsConsistent(Message message1, Message message2) { assertEquals(message1, message2); assertEquals(message2, message1); @@ -515,9 +522,8 @@ private void checkEqualsIsConsistent(Message message1, Message message2) { /** * Asserts that the given protos are not equal and have different hash codes. * - * @warning It's valid for non-equal objects to have the same hash code, so - * this test is stricter than it needs to be. However, this should happen - * relatively rarely. + *

Note: It's valid for non-equal objects to have the same hash code, so this test is + * stricter than it needs to be. However, this should happen relatively rarely. */ private void checkNotEqual(Message m1, Message m2) { String equalsError = String.format("%s should not be equal to %s", m1, m2); @@ -537,7 +543,7 @@ public void testCheckByteStringIsUtf8OnUtf8() { public void testCheckByteStringIsUtf8OnNonUtf8() { ByteString byteString = - ByteString.copyFrom(new byte[]{(byte) 0x80}); // A lone continuation byte. + ByteString.copyFrom(new byte[] {(byte) 0x80}); // A lone continuation byte. try { AbstractMessageLite.checkByteStringIsUtf8(byteString); fail("Expected AbstractMessageLite.checkByteStringIsUtf8 to throw IllegalArgumentException"); @@ -545,5 +551,4 @@ public void testCheckByteStringIsUtf8OnNonUtf8() { assertEquals("Byte string is not UTF-8.", exception.getMessage()); } } - } diff --git a/java/core/src/test/java/com/google/protobuf/AbstractProto2LiteSchemaTest.java b/java/core/src/test/java/com/google/protobuf/AbstractProto2LiteSchemaTest.java new file mode 100644 index 0000000000000..5d3fd3bd696cb --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/AbstractProto2LiteSchemaTest.java @@ -0,0 +1,199 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; + +import com.google.protobuf.testing.Proto2TestingLite.Proto2EmptyLite; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.TestEnum; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLiteWithMaps; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.List; +import org.junit.Test; + +/** Base class for tests using {@link Proto2MessageLite}. */ +public abstract class AbstractProto2LiteSchemaTest extends AbstractSchemaTest { + + @Override + protected Proto2MessageLiteFactory messageFactory() { + return new Proto2MessageLiteFactory(10, 20, 2, 2); + } + + @Test + public void mergeOptionalMessageFields() throws Exception { + Proto2MessageLite message1 = + newBuilder() + .setFieldMessage10(newBuilder().setFieldInt643(123).clearFieldInt325().build()) + .build(); + Proto2MessageLite message2 = + newBuilder() + .setFieldMessage10(newBuilder().clearFieldInt643().setFieldInt325(456).build()) + .build(); + Proto2MessageLite message3 = + newBuilder() + .setFieldMessage10(newBuilder().setFieldInt643(789).clearFieldInt325().build()) + .build(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + message1.writeTo(output); + message2.writeTo(output); + message3.writeTo(output); + byte[] data = output.toByteArray(); + + Proto2MessageLite merged = + ExperimentalSerializationUtil.fromByteArray(data, Proto2MessageLite.class); + assertEquals(789, merged.getFieldMessage10().getFieldInt643()); + assertEquals(456, merged.getFieldMessage10().getFieldInt325()); + } + + @Test + public void oneofFieldsShouldRoundtrip() throws IOException { + roundtrip("Field 53", newBuilder().setFieldDouble53(100).build()); + roundtrip("Field 54", newBuilder().setFieldFloat54(100).build()); + roundtrip("Field 55", newBuilder().setFieldInt6455(100).build()); + roundtrip("Field 56", newBuilder().setFieldUint6456(100L).build()); + roundtrip("Field 57", newBuilder().setFieldInt3257(100).build()); + roundtrip("Field 58", newBuilder().setFieldFixed6458(100).build()); + roundtrip("Field 59", newBuilder().setFieldFixed3259(100).build()); + roundtrip("Field 60", newBuilder().setFieldBool60(true).build()); + roundtrip("Field 61", newBuilder().setFieldString61(data().getString()).build()); + roundtrip( + "Field 62", newBuilder().setFieldMessage62(newBuilder().setFieldDouble1(100)).build()); + roundtrip("Field 63", newBuilder().setFieldBytes63(data().getBytes()).build()); + roundtrip("Field 64", newBuilder().setFieldUint3264(100).build()); + roundtrip("Field 65", newBuilder().setFieldSfixed3265(100).build()); + roundtrip("Field 66", newBuilder().setFieldSfixed6466(100).build()); + roundtrip("Field 67", newBuilder().setFieldSint3267(100).build()); + roundtrip("Field 68", newBuilder().setFieldSint6468(100).build()); + roundtrip( + "Field 69", + newBuilder() + .setFieldGroup69( + Proto2MessageLite.FieldGroup69.newBuilder().setFieldInt3270(data().getInt())) + .build()); + } + + private Proto2MessageLite.Builder newBuilder() { + return messageFactory().newMessage().toBuilder(); + } + + @Override + protected List newMessagesMissingRequiredFields() { + return messageFactory().newMessagesMissingRequiredFields(); + } + + @Test + public void mapsShouldRoundtrip() throws IOException { + roundtrip( + "Proto2MessageLiteWithMaps", + new Proto2MessageLiteFactory(2, 10, 2, 2).newMessageWithMaps(), + Protobuf.getInstance().schemaFor(Proto2MessageLiteWithMaps.class)); + } + + @Test + public void unknownFieldsUnrecognized() throws Exception { + Proto2MessageLite expectedMessage = messageFactory().newMessage(); + byte[] serializedBytes = expectedMessage.toByteArray(); + Proto2EmptyLite empty = + ExperimentalSerializationUtil.fromByteArray(serializedBytes, Proto2EmptyLite.class); + + // Merge serialized bytes into an empty message, then reserialize and merge it to a new + // Proto2Message. Make sure the two messages equal. + byte[] roundtripBytes = ExperimentalSerializationUtil.toByteArray(empty); + Proto2MessageLite roundtripMessage = + ExperimentalSerializationUtil.fromByteArray(roundtripBytes, Proto2MessageLite.class); + assertEquals(expectedMessage, roundtripMessage); + } + + @Test + public void unknownEnum() throws IOException { + // Use unknown fields to hold invalid enum values. + UnknownFieldSetLite unknowns = UnknownFieldSetLite.newInstance(); + final int outOfRange = 1000; + assertNull(TestEnum.forNumber(outOfRange)); + unknowns.storeField( + WireFormat.makeTag( + Proto2MessageLite.FIELD_ENUM_13_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), + (long) outOfRange); + unknowns.storeField( + WireFormat.makeTag( + Proto2MessageLite.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), + (long) TestEnum.ONE_VALUE); + unknowns.storeField( + WireFormat.makeTag( + Proto2MessageLite.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), + (long) outOfRange); + unknowns.storeField( + WireFormat.makeTag( + Proto2MessageLite.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), + (long) TestEnum.TWO_VALUE); + + { + // Construct a packed enum list. + int packedSize = + CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE) + + CodedOutputStream.computeUInt32SizeNoTag(outOfRange) + + CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE); + ByteString.CodedBuilder packedBuilder = ByteString.newCodedBuilder(packedSize); + CodedOutputStream packedOut = packedBuilder.getCodedOutput(); + packedOut.writeEnumNoTag(TestEnum.ONE_VALUE); + packedOut.writeEnumNoTag(outOfRange); + packedOut.writeEnumNoTag(TestEnum.TWO_VALUE); + unknowns.storeField( + WireFormat.makeTag( + Proto2MessageLite.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER, + WireFormat.WIRETYPE_LENGTH_DELIMITED), + packedBuilder.build()); + } + int size = unknowns.getSerializedSize(); + byte[] output = new byte[size]; + CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); + unknowns.writeTo(codedOutput); + codedOutput.flush(); + + Proto2MessageLite parsed = + ExperimentalSerializationUtil.fromByteArray(output, Proto2MessageLite.class); + assertFalse("out-of-range singular enum should not be in message", parsed.hasFieldEnum13()); + assertEquals( + "out-of-range repeated enum should not be in message", 2, parsed.getFieldEnumList30Count()); + assertEquals(TestEnum.ONE, parsed.getFieldEnumList30(0)); + assertEquals(TestEnum.TWO, parsed.getFieldEnumList30(1)); + assertEquals( + "out-of-range packed repeated enum should not be in message", + 2, + parsed.getFieldEnumListPacked44Count()); + assertEquals(TestEnum.ONE, parsed.getFieldEnumListPacked44(0)); + assertEquals(TestEnum.TWO, parsed.getFieldEnumListPacked44(1)); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/AbstractProto2SchemaTest.java b/java/core/src/test/java/com/google/protobuf/AbstractProto2SchemaTest.java new file mode 100644 index 0000000000000..0c16818666ff7 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/AbstractProto2SchemaTest.java @@ -0,0 +1,224 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; + +import com.google.protobuf.testing.Proto2Testing.Proto2Empty; +import com.google.protobuf.testing.Proto2Testing.Proto2Message; +import com.google.protobuf.testing.Proto2Testing.Proto2Message.TestEnum; +import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithMaps; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.List; +import org.junit.Test; + +/** Base class for tests using {@link Proto2Message}. */ +public abstract class AbstractProto2SchemaTest extends AbstractSchemaTest { + + @Override + protected Proto2MessageFactory messageFactory() { + return new Proto2MessageFactory(10, 20, 2, 2); + } + + @Test + public void mergeOptionalMessageFields() throws Exception { + Proto2Message message1 = + newBuilder() + .setFieldMessage10(newBuilder().setFieldInt643(123).clearFieldInt325().build()) + .build(); + Proto2Message message2 = + newBuilder() + .setFieldMessage10(newBuilder().clearFieldInt643().setFieldInt325(456).build()) + .build(); + Proto2Message message3 = + newBuilder() + .setFieldMessage10(newBuilder().setFieldInt643(789).clearFieldInt325().build()) + .build(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + message1.writeTo(output); + message2.writeTo(output); + message3.writeTo(output); + byte[] data = output.toByteArray(); + + Proto2Message merged = ExperimentalSerializationUtil.fromByteArray(data, Proto2Message.class); + assertEquals(789, merged.getFieldMessage10().getFieldInt643()); + assertEquals(456, merged.getFieldMessage10().getFieldInt325()); + } + + @Test + public void oneofFieldsShouldRoundtrip() throws IOException { + roundtrip("Field 53", newBuilder().setFieldDouble53(100).build()); + roundtrip("Field 54", newBuilder().setFieldFloat54(100).build()); + roundtrip("Field 55", newBuilder().setFieldInt6455(100).build()); + roundtrip("Field 56", newBuilder().setFieldUint6456(100L).build()); + roundtrip("Field 57", newBuilder().setFieldInt3257(100).build()); + roundtrip("Field 58", newBuilder().setFieldFixed6458(100).build()); + roundtrip("Field 59", newBuilder().setFieldFixed3259(100).build()); + roundtrip("Field 60", newBuilder().setFieldBool60(true).build()); + roundtrip("Field 61", newBuilder().setFieldString61(data().getString()).build()); + roundtrip( + "Field 62", newBuilder().setFieldMessage62(newBuilder().setFieldDouble1(100)).build()); + roundtrip("Field 63", newBuilder().setFieldBytes63(data().getBytes()).build()); + roundtrip("Field 64", newBuilder().setFieldUint3264(100).build()); + roundtrip("Field 65", newBuilder().setFieldSfixed3265(100).build()); + roundtrip("Field 66", newBuilder().setFieldSfixed6466(100).build()); + roundtrip("Field 67", newBuilder().setFieldSint3267(100).build()); + roundtrip("Field 68", newBuilder().setFieldSint6468(100).build()); + roundtrip( + "Field 69", + newBuilder() + .setFieldGroup69( + Proto2Message.FieldGroup69.newBuilder().setFieldInt3270(data().getInt())) + .build()); + } + + private Proto2Message.Builder newBuilder() { + return messageFactory().newMessage().toBuilder(); + } + + @Test + public void mapsShouldRoundtrip() throws IOException { + roundtrip( + "Proto2MessageWithMaps", + new Proto2MessageFactory(2, 10, 2, 2).newMessageWithMaps(), + Protobuf.getInstance().schemaFor(Proto2MessageWithMaps.class)); + } + + @Test + public void unknownFieldsUnrecognized() throws Exception { + Proto2Message expectedMessage = messageFactory().newMessage(); + byte[] serializedBytes = expectedMessage.toByteArray(); + Proto2Empty empty = + ExperimentalSerializationUtil.fromByteArray(serializedBytes, Proto2Empty.class); + + // Merge serialized bytes into an empty message, then reserialize and merge it to a new + // Proto2Message. Make sure the two messages equal. + byte[] roundtripBytes = ExperimentalSerializationUtil.toByteArray(empty); + assertEquals(serializedBytes.length, roundtripBytes.length); + Proto2Message roundtripMessage = + ExperimentalSerializationUtil.fromByteArray(roundtripBytes, Proto2Message.class); + assertEquals(expectedMessage, roundtripMessage); + } + + @Test + public void unknownEnum() throws IOException { + // Use unknown fields to hold invalid enum values. + UnknownFieldSetLite unknowns = UnknownFieldSetLite.newInstance(); + final int outOfRange = 1000; + assertNull(TestEnum.forNumber(outOfRange)); + unknowns.storeField( + WireFormat.makeTag(Proto2Message.FIELD_ENUM_13_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), + (long) outOfRange); + unknowns.storeField( + WireFormat.makeTag( + Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), + (long) TestEnum.ONE_VALUE); + unknowns.storeField( + WireFormat.makeTag( + Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), + (long) outOfRange); + unknowns.storeField( + WireFormat.makeTag( + Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), + (long) TestEnum.TWO_VALUE); + + { + // Construct a packed enum list. + int packedSize = + CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE) + + CodedOutputStream.computeUInt32SizeNoTag(outOfRange) + + CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE); + ByteString.CodedBuilder packedBuilder = ByteString.newCodedBuilder(packedSize); + CodedOutputStream packedOut = packedBuilder.getCodedOutput(); + packedOut.writeEnumNoTag(TestEnum.ONE_VALUE); + packedOut.writeEnumNoTag(outOfRange); + packedOut.writeEnumNoTag(TestEnum.TWO_VALUE); + unknowns.storeField( + WireFormat.makeTag( + Proto2Message.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER, + WireFormat.WIRETYPE_LENGTH_DELIMITED), + packedBuilder.build()); + } + int size = unknowns.getSerializedSize(); + byte[] output = new byte[size]; + CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); + unknowns.writeTo(codedOutput); + codedOutput.flush(); + + Proto2Message parsed = ExperimentalSerializationUtil.fromByteArray(output, Proto2Message.class); + assertFalse("out-of-range singular enum should not be in message", parsed.hasFieldEnum13()); + { + List singularEnum = + parsed + .getUnknownFields() + .getField(Proto2Message.FIELD_ENUM_13_FIELD_NUMBER) + .getVarintList(); + assertEquals(1, singularEnum.size()); + assertEquals((Long) (long) outOfRange, singularEnum.get(0)); + } + { + List repeatedEnum = + parsed + .getUnknownFields() + .getField(Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER) + .getVarintList(); + assertEquals(1, repeatedEnum.size()); + assertEquals((Long) (long) outOfRange, repeatedEnum.get(0)); + } + { + List packedRepeatedEnum = + parsed + .getUnknownFields() + .getField(Proto2Message.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER) + .getVarintList(); + assertEquals(1, packedRepeatedEnum.size()); + assertEquals((Long) (long) outOfRange, packedRepeatedEnum.get(0)); + } + assertEquals( + "out-of-range repeated enum should not be in message", 2, parsed.getFieldEnumList30Count()); + assertEquals(TestEnum.ONE, parsed.getFieldEnumList30(0)); + assertEquals(TestEnum.TWO, parsed.getFieldEnumList30(1)); + assertEquals( + "out-of-range packed repeated enum should not be in message", + 2, + parsed.getFieldEnumListPacked44Count()); + assertEquals(TestEnum.ONE, parsed.getFieldEnumListPacked44(0)); + assertEquals(TestEnum.TWO, parsed.getFieldEnumListPacked44(1)); + } + + @Override + protected List newMessagesMissingRequiredFields() { + return messageFactory().newMessagesMissingRequiredFields(); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/AbstractProto3LiteSchemaTest.java b/java/core/src/test/java/com/google/protobuf/AbstractProto3LiteSchemaTest.java new file mode 100644 index 0000000000000..9cc04ec7ced77 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/AbstractProto3LiteSchemaTest.java @@ -0,0 +1,143 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static org.junit.Assert.assertEquals; + +import com.google.protobuf.testing.Proto3TestingLite.Proto3EmptyLite; +import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLite; +import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLiteWithMaps; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import org.junit.Test; + +/** Base class for tests using {@link Proto3MessageLite}. */ +public abstract class AbstractProto3LiteSchemaTest extends AbstractSchemaTest { + @Override + protected Proto3MessageLiteFactory messageFactory() { + return new Proto3MessageLiteFactory(10, 20, 2, 2); + } + + @Override + protected List serializedBytesWithInvalidUtf8() throws IOException { + List invalidBytes = new ArrayList<>(); + byte[] invalid = new byte[] {(byte) 0x80}; + { + ByteBuffer buffer = ByteBuffer.allocate(100); + CodedOutputStream codedOutput = CodedOutputStream.newInstance(buffer); + codedOutput.writeByteArray(Proto3MessageLite.FIELD_STRING_9_FIELD_NUMBER, invalid); + codedOutput.flush(); + buffer.flip(); + invalidBytes.add(buffer); + } + { + ByteBuffer buffer = ByteBuffer.allocate(100); + CodedOutputStream codedOutput = CodedOutputStream.newInstance(buffer); + codedOutput.writeByteArray(Proto3MessageLite.FIELD_STRING_LIST_26_FIELD_NUMBER, invalid); + codedOutput.flush(); + buffer.flip(); + invalidBytes.add(buffer); + } + return invalidBytes; + } + + @Test + public void mergeOptionalMessageFields() throws Exception { + Proto3MessageLite message1 = + newBuilder() + .setFieldMessage10(newBuilder().setFieldInt643(123).clearFieldInt325().build()) + .build(); + Proto3MessageLite message2 = + newBuilder() + .setFieldMessage10(newBuilder().clearFieldInt643().setFieldInt325(456).build()) + .build(); + Proto3MessageLite message3 = + newBuilder() + .setFieldMessage10(newBuilder().setFieldInt643(789).clearFieldInt325().build()) + .build(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + message1.writeTo(output); + message2.writeTo(output); + message3.writeTo(output); + byte[] data = output.toByteArray(); + + Proto3MessageLite merged = + ExperimentalSerializationUtil.fromByteArray(data, Proto3MessageLite.class); + assertEquals(789, merged.getFieldMessage10().getFieldInt643()); + assertEquals(456, merged.getFieldMessage10().getFieldInt325()); + } + + @Test + public void oneofFieldsShouldRoundtrip() throws IOException { + roundtrip("Field 53", newBuilder().setFieldDouble53(100).build()); + roundtrip("Field 54", newBuilder().setFieldFloat54(100).build()); + roundtrip("Field 55", newBuilder().setFieldInt6455(100).build()); + roundtrip("Field 56", newBuilder().setFieldUint6456(100L).build()); + roundtrip("Field 57", newBuilder().setFieldInt3257(100).build()); + roundtrip("Field 58", newBuilder().setFieldFixed6458(100).build()); + roundtrip("Field 59", newBuilder().setFieldFixed3259(100).build()); + roundtrip("Field 60", newBuilder().setFieldBool60(true).build()); + roundtrip("Field 61", newBuilder().setFieldString61(data().getString()).build()); + roundtrip( + "Field 62", newBuilder().setFieldMessage62(newBuilder().setFieldDouble1(100)).build()); + roundtrip("Field 63", newBuilder().setFieldBytes63(data().getBytes()).build()); + roundtrip("Field 64", newBuilder().setFieldUint3264(100).build()); + roundtrip("Field 65", newBuilder().setFieldSfixed3265(100).build()); + roundtrip("Field 66", newBuilder().setFieldSfixed6466(100).build()); + roundtrip("Field 67", newBuilder().setFieldSint3267(100).build()); + roundtrip("Field 68", newBuilder().setFieldSint6468(100).build()); + } + + @Test + public void retainUnknownFields() { + // Unknown fields are retained in lite runtime. + Proto3MessageLite expectedMessage = messageFactory().newMessage(); + Proto3EmptyLite empty = + ExperimentalSerializationUtil.fromByteArray( + expectedMessage.toByteArray(), Proto3EmptyLite.class); + assertEquals(expectedMessage.getSerializedSize(), empty.getSerializedSize()); + } + + @Test + public void mapsShouldRoundtrip() throws IOException { + roundtrip( + "Proto3MessageLiteWithMaps", + new Proto3MessageLiteFactory(2, 10, 2, 2).newMessageWithMaps(), + Protobuf.getInstance().schemaFor(Proto3MessageLiteWithMaps.class)); + } + + private static Proto3MessageLite.Builder newBuilder() { + return Proto3MessageLite.newBuilder(); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/AbstractProto3SchemaTest.java b/java/core/src/test/java/com/google/protobuf/AbstractProto3SchemaTest.java new file mode 100644 index 0000000000000..358f1e3b14beb --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/AbstractProto3SchemaTest.java @@ -0,0 +1,151 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static org.junit.Assert.assertEquals; + +import com.google.protobuf.testing.Proto3Testing.Proto3Empty; +import com.google.protobuf.testing.Proto3Testing.Proto3Message; +import com.google.protobuf.testing.Proto3Testing.Proto3MessageWithMaps; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import org.junit.Test; + +/** Base class for tests using {@link Proto3Message}. */ +public abstract class AbstractProto3SchemaTest extends AbstractSchemaTest { + @Override + protected Proto3MessageFactory messageFactory() { + return new Proto3MessageFactory(10, 20, 2, 2); + } + + @Override + protected List serializedBytesWithInvalidUtf8() throws IOException { + List invalidBytes = new ArrayList<>(); + byte[] invalid = new byte[] {(byte) 0x80}; + { + ByteBuffer buffer = ByteBuffer.allocate(100); + CodedOutputStream codedOutput = CodedOutputStream.newInstance(buffer); + codedOutput.writeByteArray(Proto3Message.FIELD_STRING_9_FIELD_NUMBER, invalid); + codedOutput.flush(); + buffer.flip(); + invalidBytes.add(buffer); + } + { + ByteBuffer buffer = ByteBuffer.allocate(100); + CodedOutputStream codedOutput = CodedOutputStream.newInstance(buffer); + codedOutput.writeByteArray(Proto3Message.FIELD_STRING_LIST_26_FIELD_NUMBER, invalid); + codedOutput.flush(); + buffer.flip(); + invalidBytes.add(buffer); + } + return invalidBytes; + } + + @Test + public void mergeOptionalMessageFields() throws Exception { + Proto3Message message1 = + newBuilder() + .setFieldMessage10(newBuilder().setFieldInt643(123).clearFieldInt325().build()) + .build(); + Proto3Message message2 = + newBuilder() + .setFieldMessage10(newBuilder().clearFieldInt643().setFieldInt325(456).build()) + .build(); + Proto3Message message3 = + newBuilder() + .setFieldMessage10(newBuilder().setFieldInt643(789).clearFieldInt325().build()) + .build(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + message1.writeTo(output); + message2.writeTo(output); + message3.writeTo(output); + byte[] data = output.toByteArray(); + + Proto3Message merged = ExperimentalSerializationUtil.fromByteArray(data, Proto3Message.class); + assertEquals(789, merged.getFieldMessage10().getFieldInt643()); + assertEquals(456, merged.getFieldMessage10().getFieldInt325()); + } + + @Test + public void oneofFieldsShouldRoundtrip() throws IOException { + roundtrip("Field 53", newBuilder().setFieldDouble53(100).build()); + roundtrip("Field 54", newBuilder().setFieldFloat54(100).build()); + roundtrip("Field 55", newBuilder().setFieldInt6455(100).build()); + roundtrip("Field 56", newBuilder().setFieldUint6456(100L).build()); + roundtrip("Field 57", newBuilder().setFieldInt3257(100).build()); + roundtrip("Field 58", newBuilder().setFieldFixed6458(100).build()); + roundtrip("Field 59", newBuilder().setFieldFixed3259(100).build()); + roundtrip("Field 60", newBuilder().setFieldBool60(true).build()); + roundtrip("Field 61", newBuilder().setFieldString61(data().getString()).build()); + roundtrip( + "Field 62", newBuilder().setFieldMessage62(newBuilder().setFieldDouble1(100)).build()); + roundtrip("Field 63", newBuilder().setFieldBytes63(data().getBytes()).build()); + roundtrip("Field 64", newBuilder().setFieldUint3264(100).build()); + roundtrip("Field 65", newBuilder().setFieldSfixed3265(100).build()); + roundtrip("Field 66", newBuilder().setFieldSfixed6466(100).build()); + roundtrip("Field 67", newBuilder().setFieldSint3267(100).build()); + roundtrip("Field 68", newBuilder().setFieldSint6468(100).build()); + } + + @Test + public void preserveUnknownFields() { + Proto3Message expectedMessage = messageFactory().newMessage(); + Proto3Empty empty = + ExperimentalSerializationUtil.fromByteArray( + expectedMessage.toByteArray(), Proto3Empty.class); + assertEquals(expectedMessage.getSerializedSize(), empty.getSerializedSize()); + assertEquals(expectedMessage.toByteString(), empty.toByteString()); + } + + @Test + public void preserveUnknownFieldsProto2() { + // Make sure we will be able to preserve valid proto2 wireformat, including those that are not + // supported in proto3, e.g. groups. + byte[] payload = new Proto2MessageFactory(10, 20, 2, 2).newMessage().toByteArray(); + Proto3Empty empty = ExperimentalSerializationUtil.fromByteArray(payload, Proto3Empty.class); + assertEquals(payload.length, empty.getSerializedSize()); + } + + @Test + public void mapsShouldRoundtrip() throws IOException { + roundtrip( + "Proto3MessageWithMaps", + new Proto3MessageFactory(2, 10, 2, 2).newMessageWithMaps(), + Protobuf.getInstance().schemaFor(Proto3MessageWithMaps.class)); + } + + private static Proto3Message.Builder newBuilder() { + return Proto3Message.newBuilder(); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/AbstractSchemaTest.java b/java/core/src/test/java/com/google/protobuf/AbstractSchemaTest.java new file mode 100644 index 0000000000000..c69a4fd25436b --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/AbstractSchemaTest.java @@ -0,0 +1,157 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.Before; +import org.junit.Test; + +public abstract class AbstractSchemaTest { + private Schema schema; + + @Before + public void setup() { + schema = schema(); + registerSchemas(); + } + + // Subclass should override this method if it needs to register more than one schemas. + protected void registerSchemas() { + // Register this schema with the runtime to support processing of nested messages. + Protobuf.getInstance().registerSchemaOverride(schema.newInstance().getClass(), schema); + } + + protected abstract Schema schema(); + + protected abstract ExperimentalMessageFactory messageFactory(); + + @SuppressWarnings("unused") + protected List serializedBytesWithInvalidUtf8() throws IOException { + return Collections.emptyList(); + } + + @Test + public void randomMessageShouldRoundtrip() throws IOException { + roundtrip("", messageFactory().newMessage()); + } + + @Test + public void invalidUtf8StringParsing() throws IOException { + for (ByteBuffer invalidUtf8Bytes : serializedBytesWithInvalidUtf8()) { + Reader reader = BinaryReader.newInstance(invalidUtf8Bytes, /* bufferIsImmutable= */ true); + + T newMsg = schema.newInstance(); + try { + schema.mergeFrom(newMsg, reader, ExtensionRegistryLite.getEmptyRegistry()); + fail("should throw invalid "); + } catch (InvalidProtocolBufferException expected) { + } + } + } + + @Test + public void mergeFromByteArrayFastPathMayThrowIndexOutOfBoundsException() throws IOException { + if (!Android.isOnAndroidDevice()) { + // Skip this test if not on Android. + return; + } + byte[] data = messageFactory().newMessage().toByteArray(); + int exceptionCount = 0; + for (int i = 0; i <= data.length; i++) { + byte[] truncatedData = Arrays.copyOf(data, i); + try { + T message = schema.newInstance(); + // Test that this method throws the expected exceptions. + schema.mergeFrom(message, truncatedData, 0, i, new ArrayDecoders.Registers()); + } catch (InvalidProtocolBufferException e) { + // Ignore expected exceptions. + } catch (IndexOutOfBoundsException e) { + exceptionCount += 1; + } + } + assertNotEquals(0, exceptionCount); + } + + protected static final void roundtrip( + String failureMessage, M msg, Schema schema) throws IOException { + byte[] serializedBytes = ExperimentalSerializationUtil.toByteArray(msg, schema); + assertEquals(failureMessage, msg.getSerializedSize(), serializedBytes.length); + + // Now read it back in and verify it matches the original. + if (Android.isOnAndroidDevice()) { + // Test the fast path on Android. + M newMsg = schema.newInstance(); + schema.mergeFrom( + newMsg, serializedBytes, 0, serializedBytes.length, new ArrayDecoders.Registers()); + schema.makeImmutable(newMsg); + assertEquals(failureMessage, msg, newMsg); + } + M newMsg = schema.newInstance(); + Reader reader = BinaryReader.newInstance(ByteBuffer.wrap(serializedBytes), true); + schema.mergeFrom(newMsg, reader, ExtensionRegistryLite.getEmptyRegistry()); + schema.makeImmutable(newMsg); + + assertEquals(failureMessage, msg, newMsg); + } + + protected final void roundtrip(String failureMessage, T msg) throws IOException { + roundtrip(failureMessage, msg, schema); + } + + protected final ExperimentalTestDataProvider data() { + return messageFactory().dataProvider(); + } + + protected List newMessagesMissingRequiredFields() { + return Collections.emptyList(); + } + + @SuppressWarnings("unchecked") + @Test + public void testRequiredFields() throws Exception { + for (T msg : newMessagesMissingRequiredFields()) { + if (schema.isInitialized(msg)) { + assertEquals("", msg.toString()); + msg = (T) msg.toBuilder().build(); + } + assertFalse(schema.isInitialized(msg)); + } + } +} diff --git a/java/core/src/test/java/com/google/protobuf/AnyTest.java b/java/core/src/test/java/com/google/protobuf/AnyTest.java index cf91ed91c61d7..d660ca7372c8b 100644 --- a/java/core/src/test/java/com/google/protobuf/AnyTest.java +++ b/java/core/src/test/java/com/google/protobuf/AnyTest.java @@ -32,20 +32,17 @@ import any_test.AnyTestProto.TestAny; import protobuf_unittest.UnittestProto.TestAllTypes; - +import java.util.Objects; import junit.framework.TestCase; -/** - * Unit tests for Any message. - */ +/** Unit tests for Any message. */ public class AnyTest extends TestCase { public void testAnyGeneratedApi() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TestUtil.setAllFields(builder); TestAllTypes message = builder.build(); - TestAny container = TestAny.newBuilder() - .setValue(Any.pack(message)).build(); + TestAny container = TestAny.newBuilder().setValue(Any.pack(message)).build(); assertTrue(container.getValue().is(TestAllTypes.class)); assertFalse(container.getValue().is(TestAny.class)); @@ -56,7 +53,7 @@ public void testAnyGeneratedApi() throws Exception { // Unpacking to a wrong type will throw an exception. try { - TestAny wrongMessage = container.getValue().unpack(TestAny.class); + container.getValue().unpack(TestAny.class); fail("Exception is expected."); } catch (InvalidProtocolBufferException e) { // expected. @@ -64,11 +61,10 @@ public void testAnyGeneratedApi() throws Exception { // Test that unpacking throws an exception if parsing fails. TestAny.Builder containerBuilder = container.toBuilder(); - containerBuilder.getValueBuilder().setValue( - ByteString.copyFrom(new byte[]{0x11})); + containerBuilder.getValueBuilder().setValue(ByteString.copyFrom(new byte[] {0x11})); container = containerBuilder.build(); try { - TestAllTypes parsingFailed = container.getValue().unpack(TestAllTypes.class); + container.getValue().unpack(TestAllTypes.class); fail("Exception is expected."); } catch (InvalidProtocolBufferException e) { // expected. @@ -80,12 +76,10 @@ public void testCustomTypeUrls() throws Exception { TestUtil.setAllFields(builder); TestAllTypes message = builder.build(); - TestAny container = TestAny.newBuilder() - .setValue(Any.pack(message, "xxx.com")).build(); + TestAny container = TestAny.newBuilder().setValue(Any.pack(message, "xxx.com")).build(); assertEquals( - "xxx.com/" + TestAllTypes.getDescriptor().getFullName(), - container.getValue().getTypeUrl()); + "xxx.com/" + TestAllTypes.getDescriptor().getFullName(), container.getValue().getTypeUrl()); assertTrue(container.getValue().is(TestAllTypes.class)); assertFalse(container.getValue().is(TestAny.class)); @@ -93,12 +87,10 @@ public void testCustomTypeUrls() throws Exception { TestAllTypes result = container.getValue().unpack(TestAllTypes.class); TestUtil.assertAllFieldsSet(result); - container = TestAny.newBuilder() - .setValue(Any.pack(message, "yyy.com/")).build(); + container = TestAny.newBuilder().setValue(Any.pack(message, "yyy.com/")).build(); assertEquals( - "yyy.com/" + TestAllTypes.getDescriptor().getFullName(), - container.getValue().getTypeUrl()); + "yyy.com/" + TestAllTypes.getDescriptor().getFullName(), container.getValue().getTypeUrl()); assertTrue(container.getValue().is(TestAllTypes.class)); assertFalse(container.getValue().is(TestAny.class)); @@ -106,12 +98,10 @@ public void testCustomTypeUrls() throws Exception { result = container.getValue().unpack(TestAllTypes.class); TestUtil.assertAllFieldsSet(result); - container = TestAny.newBuilder() - .setValue(Any.pack(message, "")).build(); + container = TestAny.newBuilder().setValue(Any.pack(message, "")).build(); assertEquals( - "/" + TestAllTypes.getDescriptor().getFullName(), - container.getValue().getTypeUrl()); + "/" + TestAllTypes.getDescriptor().getFullName(), container.getValue().getTypeUrl()); assertTrue(container.getValue().is(TestAllTypes.class)); assertFalse(container.getValue().is(TestAny.class)); @@ -125,13 +115,12 @@ public void testCachedUnpackResult() throws Exception { TestUtil.setAllFields(builder); TestAllTypes message = builder.build(); - TestAny container = TestAny.newBuilder() - .setValue(Any.pack(message)).build(); + TestAny container = TestAny.newBuilder().setValue(Any.pack(message)).build(); assertTrue(container.getValue().is(TestAllTypes.class)); TestAllTypes result1 = container.getValue().unpack(TestAllTypes.class); TestAllTypes result2 = container.getValue().unpack(TestAllTypes.class); - assertTrue(result1 == result2); + assertTrue(Objects.equals(result1, result2)); } } diff --git a/java/core/src/test/java/com/google/protobuf/ArrayDecodersTest.java b/java/core/src/test/java/com/google/protobuf/ArrayDecodersTest.java new file mode 100644 index 0000000000000..037173b667433 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/ArrayDecodersTest.java @@ -0,0 +1,236 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.ArrayDecoders.Registers; +import java.io.IOException; +import junit.framework.TestCase; + +public class ArrayDecodersTest extends TestCase { + + private static final int TAG = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED); + private static final ByteString NEGATIVE_SIZE_0 = generateNegativeLength(0); + private static final ByteString NEGATIVE_SIZE_1 = generateNegativeLength(1); + + private Registers registers; + + @Override + public void setUp() { + registers = new Registers(); + registers.int1 = TAG; + } + + public void testException_decodeString() { + try { + ArrayDecoders.decodeString(NEGATIVE_SIZE_0.toByteArray(), 0, registers); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + } + + public void testException_decodeStringRequireUtf8() { + try { + ArrayDecoders.decodeStringRequireUtf8(NEGATIVE_SIZE_0.toByteArray(), 0, registers); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + } + + public void testException_decodeBytes() { + try { + ArrayDecoders.decodeBytes(NEGATIVE_SIZE_0.toByteArray(), 0, registers); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + } + + public void testException_decodeStringList_first() { + try { + ArrayDecoders.decodeStringList( + TAG, + NEGATIVE_SIZE_0.toByteArray(), + 0, + NEGATIVE_SIZE_0.size(), + new ProtobufArrayList(), + registers); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + } + + public void testException_decodeStringList_second() { + try { + ArrayDecoders.decodeStringList( + TAG, + NEGATIVE_SIZE_1.toByteArray(), + 0, + NEGATIVE_SIZE_1.size(), + new ProtobufArrayList(), + registers); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + } + + public void testException_decodeStringListRequireUtf8_first() { + try { + ArrayDecoders.decodeStringListRequireUtf8( + TAG, + NEGATIVE_SIZE_0.toByteArray(), + 0, + NEGATIVE_SIZE_0.size(), + new ProtobufArrayList(), + registers); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + } + + public void testException_decodeStringListRequireUtf8_second() { + try { + ArrayDecoders.decodeStringListRequireUtf8( + TAG, + NEGATIVE_SIZE_1.toByteArray(), + 0, + NEGATIVE_SIZE_1.size(), + new ProtobufArrayList(), + registers); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + } + + public void testException_decodeBytesList_first() { + try { + ArrayDecoders.decodeBytesList( + TAG, + NEGATIVE_SIZE_0.toByteArray(), + 0, + NEGATIVE_SIZE_0.size(), + new ProtobufArrayList(), + registers); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + } + + public void testException_decodeBytesList_second() { + try { + ArrayDecoders.decodeBytesList( + TAG, + NEGATIVE_SIZE_1.toByteArray(), + 0, + NEGATIVE_SIZE_1.size(), + new ProtobufArrayList(), + registers); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + } + + public void testException_decodeUnknownField() { + try { + ArrayDecoders.decodeUnknownField( + TAG, + NEGATIVE_SIZE_0.toByteArray(), + 0, + NEGATIVE_SIZE_0.size(), + UnknownFieldSetLite.newInstance(), + registers); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + } + + public void testException_decodeHugeField() { + byte[] badBytes = + new byte[] { + (byte) 0x80, (byte) 0xFF, (byte) 0xFF, (byte) 0xEF, 0x73, 0x74, 0x69, 0x6E, 0x67 + }; + try { + ArrayDecoders.decodeUnknownField( + TAG, badBytes, 0, badBytes.length, UnknownFieldSetLite.newInstance(), registers); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + + try { + ArrayDecoders.decodeBytes(badBytes, 0, registers); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + + byte[] badBytesList = + new byte[] { + 0x01, + 0x77, + 0x0A, + (byte) 0x80, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xEF, + 0x73, + 0x74, + 0x69, + 0x6E, + 0x67 + }; + try { + ArrayDecoders.decodeBytesList( + TAG, badBytesList, 0, badBytes.length, new ProtobufArrayList<>(), registers); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + } + + private static ByteString generateNegativeLength(int count) { + try { + ByteString.Output byteStringOutput = ByteString.newOutput(); + CodedOutputStream codedOutput = CodedOutputStream.newInstance(byteStringOutput); + + // Write out count - 1 valid 0 length fields; we only write out tags after the field since + // ArrayDecoders expects the first tag to already have been parsed. + for (int i = 0; i < count; i++) { + codedOutput.writeInt32NoTag(0); + codedOutput.writeInt32NoTag(TAG); + } + + // Write out a negative length + codedOutput.writeInt32NoTag(-1); + + codedOutput.flush(); + + return byteStringOutput.toByteString(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/java/core/src/test/java/com/google/protobuf/BinaryProtocolTest.java b/java/core/src/test/java/com/google/protobuf/BinaryProtocolTest.java new file mode 100644 index 0000000000000..cda2998f5d8b3 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/BinaryProtocolTest.java @@ -0,0 +1,90 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static org.junit.Assert.assertEquals; + +import com.google.protobuf.testing.Proto2Testing.Proto2Message; +import com.google.protobuf.testing.Proto3Testing.Proto3Message; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public final class BinaryProtocolTest { + @Before + public void setup() { + TestSchemas.registerGenericProto2Schemas(); + + Protobuf.getInstance() + .registerSchemaOverride(Proto3Message.class, TestSchemas.genericProto3Schema); + } + + @Test + public void proto3Roundtrip() throws Exception { + Proto3Message expected = new Proto3MessageFactory(5, 10, 2, 2).newMessage(); + byte[] expectedBytes = expected.toByteArray(); + + // Deserialize with BinaryReader and verify that the message matches the original. + Proto3Message result = + ExperimentalSerializationUtil.fromByteArray(expectedBytes, Proto3Message.class); + assertEquals(expected, result); + + // Now write it back out using BinaryWriter and verify the output length. + byte[] actualBytes = ExperimentalSerializationUtil.toByteArray(result); + Assert.assertEquals(expectedBytes.length, actualBytes.length); + + // Read back in the bytes and verify that it matches the original message. + Proto3Message actual = Proto3Message.parseFrom(actualBytes); + assertEquals(expected, actual); + } + + @Test + public void proto2Roundtrip() throws Exception { + Proto2Message expected = new Proto2MessageFactory(5, 10, 2, 2).newMessage(); + byte[] expectedBytes = expected.toByteArray(); + + // Deserialize with BinaryReader and verify that the message matches the original. + Proto2Message result = + ExperimentalSerializationUtil.fromByteArray(expectedBytes, Proto2Message.class); + assertEquals(expected, result); + + // Now write it back out using BinaryWriter and verify the output length. + byte[] actualBytes = ExperimentalSerializationUtil.toByteArray(result); + Assert.assertEquals(expectedBytes.length, actualBytes.length); + + // Read back in the bytes and verify that it matches the original message. + Proto2Message actual = Proto2Message.parseFrom(actualBytes); + assertEquals(expected, actual); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java b/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java index 18132e9e036b7..805b7b042f25b 100644 --- a/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java @@ -32,6 +32,7 @@ import static java.util.Arrays.asList; +import com.google.protobuf.Internal.BooleanList; import java.util.Collections; import java.util.ConcurrentModificationException; import java.util.Iterator; @@ -44,8 +45,7 @@ */ public class BooleanArrayListTest extends TestCase { - private static final BooleanArrayList UNARY_LIST = - newImmutableBooleanArrayList(true); + private static final BooleanArrayList UNARY_LIST = newImmutableBooleanArrayList(true); private static final BooleanArrayList TERTIARY_LIST = newImmutableBooleanArrayList(true, false, true); @@ -140,6 +140,68 @@ public void testGetBoolean() { } } + public void testIndexOf_nullElement() { + assertEquals(-1, TERTIARY_LIST.indexOf(null)); + } + + public void testIndexOf_incompatibleElementType() { + assertEquals(-1, TERTIARY_LIST.indexOf(new Object())); + } + + public void testIndexOf_notInList() { + assertEquals(-1, UNARY_LIST.indexOf(false)); + } + + public void testIndexOf_notInListWithDuplicates() { + BooleanArrayList listWithDupes = newImmutableBooleanArrayList(true, true); + assertEquals(-1, listWithDupes.indexOf(false)); + } + + public void testIndexOf_inList() { + assertEquals(1, TERTIARY_LIST.indexOf(false)); + } + + public void testIndexOf_inListWithDuplicates_matchAtHead() { + BooleanArrayList listWithDupes = newImmutableBooleanArrayList(true, true, false); + assertEquals(0, listWithDupes.indexOf(true)); + } + + public void testIndexOf_inListWithDuplicates_matchMidList() { + BooleanArrayList listWithDupes = newImmutableBooleanArrayList(false, true, true, false); + assertEquals(1, listWithDupes.indexOf(true)); + } + + public void testContains_nullElement() { + assertEquals(false, TERTIARY_LIST.contains(null)); + } + + public void testContains_incompatibleElementType() { + assertEquals(false, TERTIARY_LIST.contains(new Object())); + } + + public void testContains_notInList() { + assertEquals(false, UNARY_LIST.contains(false)); + } + + public void testContains_notInListWithDuplicates() { + BooleanArrayList listWithDupes = newImmutableBooleanArrayList(true, true); + assertEquals(false, listWithDupes.contains(false)); + } + + public void testContains_inList() { + assertEquals(true, TERTIARY_LIST.contains(false)); + } + + public void testContains_inListWithDuplicates_matchAtHead() { + BooleanArrayList listWithDupes = newImmutableBooleanArrayList(true, true, false); + assertEquals(true, listWithDupes.contains(true)); + } + + public void testContains_inListWithDuplicates_matchMidList() { + BooleanArrayList listWithDupes = newImmutableBooleanArrayList(false, true, true, false); + assertEquals(true, listWithDupes.contains(true)); + } + public void testSize() { assertEquals(0, BooleanArrayList.emptyList().size()); assertEquals(1, UNARY_LIST.size()); @@ -225,8 +287,7 @@ public void testAdd() { list.add(i % 2 == 0); } assertEquals( - asList(false, true, false, false, true, true, false, true, false, true, false), - list); + asList(false, true, false, false, true, true, false, true, false, true, false), list); try { list.add(-1, true); @@ -269,6 +330,13 @@ public void testAddAll() { assertFalse(list.addAll(BooleanArrayList.emptyList())); } + public void testEquals() { + BooleanArrayList list1 = new BooleanArrayList(); + BooleanArrayList list2 = new BooleanArrayList(); + + assertEquals(list1, list2); + } + public void testRemove() { list.addAll(TERTIARY_LIST); assertEquals(true, (boolean) list.remove(0)); @@ -297,7 +365,30 @@ public void testRemove() { } } - private void assertImmutable(BooleanArrayList list) { + public void testRemoveEnd_listAtCapacity() { + BooleanList toRemove = BooleanArrayList.emptyList().mutableCopyWithCapacity(1); + toRemove.addBoolean(true); + toRemove.remove(0); + assertEquals(0, toRemove.size()); + } + + public void testRemove_listAtCapacity() { + BooleanList toRemove = BooleanArrayList.emptyList().mutableCopyWithCapacity(2); + toRemove.addBoolean(true); + toRemove.addBoolean(false); + toRemove.remove(0); + assertEquals(1, toRemove.size()); + assertEquals(false, (boolean) toRemove.get(0)); + } + + public void testSublistRemoveEndOfCapacity() { + BooleanList toRemove = BooleanArrayList.emptyList().mutableCopyWithCapacity(1); + toRemove.addBoolean(true); + toRemove.subList(0, 1).clear(); + assertEquals(0, toRemove.size()); + } + + private void assertImmutable(BooleanList list) { try { list.add(true); diff --git a/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java b/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java index db10ee748304d..654d62bc3552b 100644 --- a/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java +++ b/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java @@ -38,9 +38,9 @@ import java.io.UnsupportedEncodingException; /** - * This class tests {@link BoundedByteString}, which extends {@link LiteralByteString}, - * by inheriting the tests from {@link LiteralByteStringTest}. The only method which - * is strange enough that it needs to be overridden here is {@link #testToString()}. + * This class tests {@link BoundedByteString}, which extends {@link LiteralByteString}, by + * inheriting the tests from {@link LiteralByteStringTest}. The only method which is strange enough + * that it needs to be overridden here is {@link #testToString()}. * * @author carlanton@google.com (Carl Haverl) */ @@ -63,12 +63,16 @@ public void testToString() throws UnsupportedEncodingException { String testString = "I love unicode \u1234\u5678 characters"; ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8)); ByteString chopped = unicode.substring(2, unicode.size() - 6); - assertEquals(classUnderTest + ".substring() must have the expected type", - classUnderTest, getActualClassName(chopped)); + assertEquals( + classUnderTest + ".substring() must have the expected type", + classUnderTest, + getActualClassName(chopped)); String roundTripString = chopped.toString(UTF_8); - assertEquals(classUnderTest + " unicode bytes must match", - testString.substring(2, testString.length() - 6), roundTripString); + assertEquals( + classUnderTest + " unicode bytes must match", + testString.substring(2, testString.length() - 6), + roundTripString); } @Override @@ -76,12 +80,16 @@ public void testCharsetToString() { String testString = "I love unicode \u1234\u5678 characters"; ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8)); ByteString chopped = unicode.substring(2, unicode.size() - 6); - assertEquals(classUnderTest + ".substring() must have the expected type", - classUnderTest, getActualClassName(chopped)); + assertEquals( + classUnderTest + ".substring() must have the expected type", + classUnderTest, + getActualClassName(chopped)); String roundTripString = chopped.toString(Internal.UTF_8); - assertEquals(classUnderTest + " unicode bytes must match", - testString.substring(2, testString.length() - 6), roundTripString); + assertEquals( + classUnderTest + " unicode bytes must match", + testString.substring(2, testString.length() - 6), + roundTripString); } @Override diff --git a/java/core/src/test/java/com/google/protobuf/ByteBufferWriterTest.java b/java/core/src/test/java/com/google/protobuf/ByteBufferWriterTest.java index 6b1cfe78c1e50..5f0ef62028333 100644 --- a/java/core/src/test/java/com/google/protobuf/ByteBufferWriterTest.java +++ b/java/core/src/test/java/com/google/protobuf/ByteBufferWriterTest.java @@ -37,9 +37,7 @@ import java.util.Random; import junit.framework.TestCase; -/** - * Tests for {@link ByteBufferWriter}. - */ +/** Tests for {@link ByteBufferWriter}. */ public class ByteBufferWriterTest extends TestCase { public void testHeapBuffer() throws IOException { diff --git a/java/core/src/test/java/com/google/protobuf/ByteStringTest.java b/java/core/src/test/java/com/google/protobuf/ByteStringTest.java index be71f1f5a3b96..1b1a786bfb3fa 100644 --- a/java/core/src/test/java/com/google/protobuf/ByteStringTest.java +++ b/java/core/src/test/java/com/google/protobuf/ByteStringTest.java @@ -41,6 +41,7 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; @@ -86,25 +87,61 @@ private boolean isArray(byte[] left, byte[] right) { return left.length == right.length && isArrayRange(left, right, 0, left.length); } + public void testCompare_equalByteStrings_compareEqual() throws Exception { + byte[] referenceBytes = getTestBytes(); + ByteString string1 = ByteString.copyFrom(referenceBytes); + ByteString string2 = ByteString.copyFrom(referenceBytes); + + assertEquals( + "ByteString instances containing the same data must compare equal.", + 0, + ByteString.unsignedLexicographicalComparator().compare(string1, string2)); + } + + public void testCompare_byteStringsSortLexicographically() throws Exception { + ByteString app = ByteString.copyFromUtf8("app"); + ByteString apple = ByteString.copyFromUtf8("apple"); + ByteString banana = ByteString.copyFromUtf8("banana"); + + Comparator comparator = ByteString.unsignedLexicographicalComparator(); + + assertTrue("ByteString(app) < ByteString(apple)", comparator.compare(app, apple) < 0); + assertTrue("ByteString(app) < ByteString(banana)", comparator.compare(app, banana) < 0); + assertTrue("ByteString(apple) < ByteString(banana)", comparator.compare(apple, banana) < 0); + } + + public void testCompare_interpretsByteValuesAsUnsigned() throws Exception { + // Two's compliment of `-1` == 0b11111111 == 255 + ByteString twoHundredFiftyFive = ByteString.copyFrom(new byte[] {-1}); + // 0b00000001 == 1 + ByteString one = ByteString.copyFrom(new byte[] {1}); + + assertTrue( + "ByteString comparison treats bytes as unsigned values", + ByteString.unsignedLexicographicalComparator().compare(one, twoHundredFiftyFive) < 0); + } + public void testSubstring_BeginIndex() { byte[] bytes = getTestBytes(); ByteString substring = ByteString.copyFrom(bytes).substring(500); - assertTrue("substring must contain the tail of the string", + assertTrue( + "substring must contain the tail of the string", isArrayRange(substring.toByteArray(), bytes, 500, bytes.length - 500)); } public void testCopyFrom_BytesOffsetSize() { byte[] bytes = getTestBytes(); ByteString byteString = ByteString.copyFrom(bytes, 500, 200); - assertTrue("copyFrom sub-range must contain the expected bytes", + assertTrue( + "copyFrom sub-range must contain the expected bytes", isArrayRange(byteString.toByteArray(), bytes, 500, 200)); } public void testCopyFrom_Bytes() { byte[] bytes = getTestBytes(); ByteString byteString = ByteString.copyFrom(bytes); - assertTrue("copyFrom must contain the expected bytes", - isArray(byteString.toByteArray(), bytes)); + assertTrue( + "copyFrom must contain the expected bytes", isArray(byteString.toByteArray(), bytes)); } public void testCopyFrom_ByteBufferSize() { @@ -113,7 +150,8 @@ public void testCopyFrom_ByteBufferSize() { byteBuffer.put(bytes); byteBuffer.position(500); ByteString byteString = ByteString.copyFrom(byteBuffer, 200); - assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes", + assertTrue( + "copyFrom byteBuffer sub-range must contain the expected bytes", isArrayRange(byteString.toByteArray(), bytes, 500, 200)); } @@ -123,7 +161,8 @@ public void testCopyFrom_ByteBuffer() { byteBuffer.put(bytes); byteBuffer.position(500); ByteString byteString = ByteString.copyFrom(byteBuffer); - assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes", + assertTrue( + "copyFrom byteBuffer sub-range must contain the expected bytes", isArrayRange(byteString.toByteArray(), bytes, 500, bytes.length - 500)); } @@ -131,7 +170,8 @@ public void testCopyFrom_StringEncoding() { String testString = "I love unicode \u1234\u5678 characters"; ByteString byteString = ByteString.copyFrom(testString, UTF_16); byte[] testBytes = testString.getBytes(UTF_16); - assertTrue("copyFrom string must respect the charset", + assertTrue( + "copyFrom string must respect the charset", isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length)); } @@ -139,7 +179,8 @@ public void testCopyFrom_Utf8() { String testString = "I love unicode \u1234\u5678 characters"; ByteString byteString = ByteString.copyFromUtf8(testString); byte[] testBytes = testString.getBytes(Internal.UTF_8); - assertTrue("copyFromUtf8 string must respect the charset", + assertTrue( + "copyFromUtf8 string must respect the charset", isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length)); } @@ -148,17 +189,48 @@ public void testCopyFrom_Iterable() { final List pieces = makeConcretePieces(testBytes); // Call copyFrom() on a Collection ByteString byteString = ByteString.copyFrom(pieces); - assertTrue("copyFrom a List must contain the expected bytes", + assertTrue( + "copyFrom a List must contain the expected bytes", isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length)); // Call copyFrom on an iteration that's not a collection - ByteString byteStringAlt = ByteString.copyFrom(new Iterable() { - @Override - public Iterator iterator() { - return pieces.iterator(); - } - }); - assertEquals("copyFrom from an Iteration must contain the expected bytes", - byteString, byteStringAlt); + ByteString byteStringAlt = + ByteString.copyFrom( + new Iterable() { + @Override + public Iterator iterator() { + return pieces.iterator(); + } + }); + assertEquals( + "copyFrom from an Iteration must contain the expected bytes", byteString, byteStringAlt); + } + + public void testCopyFrom_LengthTooBig() { + byte[] testBytes = getTestBytes(100); + try { + ByteString.copyFrom(testBytes, 0, 200); + fail("Should throw"); + } catch (IndexOutOfBoundsException expected) { + } + + try { + ByteString.copyFrom(testBytes, 99, 2); + fail(); + } catch (IndexOutOfBoundsException expected) { + } + + ByteBuffer buf = ByteBuffer.wrap(testBytes); + try { + ByteString.copyFrom(buf, 101); + fail(); + } catch (IndexOutOfBoundsException expected) { + } + + try { + ByteString.copyFrom(testBytes, -1, 10); + fail("Should throw"); + } catch (IndexOutOfBoundsException expected) { + } } public void testCopyTo_TargetOffset() { @@ -166,15 +238,17 @@ public void testCopyTo_TargetOffset() { ByteString byteString = ByteString.copyFrom(bytes); byte[] target = new byte[bytes.length + 1000]; byteString.copyTo(target, 400); - assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes", + assertTrue( + "copyFrom byteBuffer sub-range must contain the expected bytes", isArrayRange(bytes, target, 400, bytes.length)); } public void testReadFrom_emptyStream() throws IOException { - ByteString byteString = - ByteString.readFrom(new ByteArrayInputStream(new byte[0])); - assertSame("reading an empty stream must result in the EMPTY constant " - + "byte string", ByteString.EMPTY, byteString); + ByteString byteString = ByteString.readFrom(new ByteArrayInputStream(new byte[0])); + assertSame( + "reading an empty stream must result in the EMPTY constant byte string", + ByteString.EMPTY, + byteString); } public void testReadFrom_smallStream() throws IOException { @@ -182,18 +256,18 @@ public void testReadFrom_smallStream() throws IOException { } public void testReadFrom_mutating() throws IOException { - byte[] capturedArray = null; EvilInputStream eis = new EvilInputStream(); ByteString byteString = ByteString.readFrom(eis); + byte[] capturedArray = eis.capturedArray; - capturedArray = eis.capturedArray; byte[] originalValue = byteString.toByteArray(); for (int x = 0; x < capturedArray.length; ++x) { capturedArray[x] = (byte) 0; } byte[] newValue = byteString.toByteArray(); - assertTrue("copyFrom byteBuffer must not grant access to underlying array", + assertTrue( + "copyFrom byteBuffer must not grant access to underlying array", Arrays.equals(originalValue, newValue)); } @@ -255,8 +329,8 @@ public void testReadFrom_IOExceptions() { fail("readFrom must throw the underlying IOException"); } catch (IOException e) { - assertEquals("readFrom must throw the expected exception", - "synthetic failure", e.getMessage()); + assertEquals( + "readFrom must throw the expected exception", "synthetic failure", e.getMessage()); } } @@ -266,7 +340,8 @@ public void testReadFrom_reluctantStream() throws IOException { final byte[] data = getTestBytes(0x1000); ByteString byteString = ByteString.readFrom(new ReluctantStream(data)); - assertTrue("readFrom byte stream must contain the expected bytes", + assertTrue( + "readFrom byte stream must contain the expected bytes", isArray(byteString.toByteArray(), data)); // Same test as above, but with some specific chunk sizes. @@ -281,11 +356,10 @@ public void testReadFrom_reluctantStream() throws IOException { // Fails unless ByteString.readFrom reads the bytes correctly from a // reluctant stream with the given chunkSize parameter. - private void assertReadFromReluctantStream(byte[] bytes, int chunkSize) - throws IOException { + private void assertReadFromReluctantStream(byte[] bytes, int chunkSize) throws IOException { ByteString b = ByteString.readFrom(new ReluctantStream(bytes), chunkSize); - assertTrue("readFrom byte stream must contain the expected bytes", - isArray(b.toByteArray(), bytes)); + assertTrue( + "readFrom byte stream must contain the expected bytes", isArray(b.toByteArray(), bytes)); } // Tests that ByteString.readFrom works with streams that implement @@ -294,21 +368,23 @@ public void testReadFrom_available() throws IOException { final byte[] data = getTestBytes(0x1001); ByteString byteString = ByteString.readFrom(new AvailableStream(data)); - assertTrue("readFrom byte stream must contain the expected bytes", + assertTrue( + "readFrom byte stream must contain the expected bytes", isArray(byteString.toByteArray(), data)); } // Fails unless ByteString.readFrom reads the bytes correctly. private void assertReadFrom(byte[] bytes) throws IOException { - ByteString byteString = - ByteString.readFrom(new ByteArrayInputStream(bytes)); - assertTrue("readFrom byte stream must contain the expected bytes", + ByteString byteString = ByteString.readFrom(new ByteArrayInputStream(bytes)); + assertTrue( + "readFrom byte stream must contain the expected bytes", isArray(byteString.toByteArray(), bytes)); } // A stream that fails when read. private static final class FailStream extends InputStream { - @Override public int read() throws IOException { + @Override + public int read() throws IOException { throw new IOException("synthetic failure"); } } @@ -323,7 +399,8 @@ public ReluctantStream(byte[] data) { this.data = data; } - @Override public int read() { + @Override + public int read() { if (pos == data.length) { return -1; } else { @@ -331,11 +408,13 @@ public ReluctantStream(byte[] data) { } } - @Override public int read(byte[] buf) { + @Override + public int read(byte[] buf) { return read(buf, 0, buf.length); } - @Override public int read(byte[] buf, int offset, int size) { + @Override + public int read(byte[] buf, int offset, int size) { if (pos == data.length) { return -1; } @@ -352,7 +431,8 @@ public AvailableStream(byte[] data) { super(data); } - @Override public int available() { + @Override + public int available() { return Math.min(250, data.length - pos); } } @@ -402,8 +482,27 @@ public void testToStringUtf8() { String testString = "I love unicode \u1234\u5678 characters"; byte[] testBytes = testString.getBytes(Internal.UTF_8); ByteString byteString = ByteString.copyFrom(testBytes); - assertEquals("copyToStringUtf8 must respect the charset", - testString, byteString.toStringUtf8()); + assertEquals( + "copyToStringUtf8 must respect the charset", testString, byteString.toStringUtf8()); + } + + public void testToString() { + String toString = + ByteString.copyFrom("Here are some bytes: \t\u00a1".getBytes(Internal.UTF_8)).toString(); + assertTrue(toString, toString.contains("size=24")); + assertTrue(toString, toString.contains("contents=\"Here are some bytes: \\t\\302\\241\"")); + } + + public void testToString_long() { + String toString = + ByteString.copyFrom( + "123456789012345678901234567890123456789012345678901234567890" + .getBytes(Internal.UTF_8)) + .toString(); + assertTrue(toString, toString.contains("size=60")); + assertTrue( + toString, + toString.contains("contents=\"12345678901234567890123456789012345678901234567...\"")); } public void testNewOutput_InitialCapacity() throws IOException { @@ -421,8 +520,9 @@ public void testNewOutput_InitialCapacity() throws IOException { public void testNewOutput_ArrayWrite() { byte[] bytes = getTestBytes(); int length = bytes.length; - int[] bufferSizes = {128, 256, length / 2, length - 1, length, length + 1, - 2 * length, 3 * length}; + int[] bufferSizes = { + 128, 256, length / 2, length - 1, length, length + 1, 2 * length, 3 * length + }; int[] writeSizes = {1, 4, 5, 7, 23, bytes.length}; for (int bufferSize : bufferSizes) { @@ -433,7 +533,8 @@ public void testNewOutput_ArrayWrite() { output.write(bytes, i, Math.min(writeSize, length - i)); } ByteString byteString = output.toByteString(); - assertTrue("String built from newOutput() must contain the expected bytes", + assertTrue( + "String built from newOutput() must contain the expected bytes", isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length)); } } @@ -444,16 +545,17 @@ public void testNewOutput_ArrayWrite() { public void testNewOutput_WriteChar() { byte[] bytes = getTestBytes(); int length = bytes.length; - int[] bufferSizes = {0, 1, 128, 256, length / 2, - length - 1, length, length + 1, - 2 * length, 3 * length}; + int[] bufferSizes = { + 0, 1, 128, 256, length / 2, length - 1, length, length + 1, 2 * length, 3 * length + }; for (int bufferSize : bufferSizes) { ByteString.Output output = ByteString.newOutput(bufferSize); for (byte byteValue : bytes) { output.write(byteValue); } ByteString byteString = output.toByteString(); - assertTrue("String built from newOutput() must contain the expected bytes", + assertTrue( + "String built from newOutput() must contain the expected bytes", isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length)); } } @@ -464,9 +566,9 @@ public void testNewOutput_Mixed() { Random rng = new Random(1); byte[] bytes = getTestBytes(); int length = bytes.length; - int[] bufferSizes = {0, 1, 128, 256, length / 2, - length - 1, length, length + 1, - 2 * length, 3 * length}; + int[] bufferSizes = { + 0, 1, 128, 256, length / 2, length - 1, length, length + 1, 2 * length, 3 * length + }; for (int bufferSize : bufferSizes) { // Test writing the entire output using a mixture of write sizes and @@ -483,12 +585,13 @@ public void testNewOutput_Mixed() { position++; } assertEquals("size() returns the right value", position, output.size()); - assertTrue("newOutput() substring must have correct bytes", - isArrayRange(output.toByteString().toByteArray(), - bytes, 0, position)); + assertTrue( + "newOutput() substring must have correct bytes", + isArrayRange(output.toByteString().toByteArray(), bytes, 0, position)); } ByteString byteString = output.toByteString(); - assertTrue("String built from newOutput() must contain the expected bytes", + assertTrue( + "String built from newOutput() must contain the expected bytes", isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length)); } } @@ -509,7 +612,8 @@ public void testNewOutput_Mutating() throws IOException { byte[] oldValue = byteString.toByteArray(); Arrays.fill(capturedArray, (byte) 0); byte[] newValue = byteString.toByteArray(); - assertTrue("Output must not provide access to the underlying byte array", + assertTrue( + "Output must not provide access to the underlying byte array", Arrays.equals(oldValue, newValue)); } @@ -518,14 +622,15 @@ public void testNewCodedBuilder() throws IOException { ByteString.CodedBuilder builder = ByteString.newCodedBuilder(bytes.length); builder.getCodedOutput().writeRawBytes(bytes); ByteString byteString = builder.build(); - assertTrue("String built from newCodedBuilder() must contain the expected bytes", + assertTrue( + "String built from newCodedBuilder() must contain the expected bytes", isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length)); } public void testSubstringParity() { byte[] bigBytes = getTestBytes(2048 * 1024, 113344L); int start = 512 * 1024 - 3333; - int end = 512 * 1024 + 7777; + int end = 512 * 1024 + 7777; ByteString concreteSubstring = ByteString.copyFrom(bigBytes).substring(start, end); boolean ok = true; for (int i = start; ok && i < end; ++i) { @@ -534,10 +639,11 @@ public void testSubstringParity() { assertTrue("Concrete substring didn't capture the right bytes", ok); ByteString literalString = ByteString.copyFrom(bigBytes, start, end - start); - assertTrue("Substring must be equal to literal string", - concreteSubstring.equals(literalString)); - assertEquals("Substring must have same hashcode as literal string", - literalString.hashCode(), concreteSubstring.hashCode()); + assertEquals("Substring must be equal to literal string", literalString, concreteSubstring); + assertEquals( + "Substring must have same hashcode as literal string", + literalString.hashCode(), + concreteSubstring.hashCode()); } public void testCompositeSubstring() { @@ -563,15 +669,22 @@ public void testCompositeSubstring() { assertTrue("Substring must support byteAt() correctly", stillEqual); ByteString literalSubstring = ByteString.copyFrom(referenceBytes, from, to - from); - assertTrue("Composite substring must equal a literal substring over the same bytes", - compositeSubstring.equals(literalSubstring)); - assertTrue("Literal substring must equal a composite substring over the same bytes", - literalSubstring.equals(compositeSubstring)); - - assertEquals("We must get the same hashcodes for composite and literal substrings", - literalSubstring.hashCode(), compositeSubstring.hashCode()); - - assertFalse("We can't be equal to a proper substring", + assertEquals( + "Composite substring must equal a literal substring over the same bytes", + literalSubstring, + compositeSubstring); + assertEquals( + "Literal substring must equal a composite substring over the same bytes", + compositeSubstring, + literalSubstring); + + assertEquals( + "We must get the same hashcodes for composite and literal substrings", + literalSubstring.hashCode(), + compositeSubstring.hashCode()); + + assertFalse( + "We can't be equal to a proper substring", compositeSubstring.equals(literalSubstring.substring(0, literalSubstring.size() - 1))); } @@ -582,10 +695,11 @@ public void testCopyFromList() { List pieces = makeConcretePieces(referenceBytes); ByteString listString = ByteString.copyFrom(pieces); - assertTrue("Composite string must be equal to literal string", - listString.equals(literalString)); - assertEquals("Composite string must have same hashcode as literal string", - literalString.hashCode(), listString.hashCode()); + assertEquals("Composite string must be equal to literal string", literalString, listString); + assertEquals( + "Composite string must have same hashcode as literal string", + literalString.hashCode(), + listString.hashCode()); } public void testConcat() { @@ -600,30 +714,34 @@ public void testConcat() { concatenatedString = concatenatedString.concat(iter.next()); } - assertTrue("Concatenated string must be equal to literal string", - concatenatedString.equals(literalString)); - assertEquals("Concatenated string must have same hashcode as literal string", - literalString.hashCode(), concatenatedString.hashCode()); + assertEquals( + "Concatenated string must be equal to literal string", literalString, concatenatedString); + assertEquals( + "Concatenated string must have same hashcode as literal string", + literalString.hashCode(), + concatenatedString.hashCode()); } /** - * Test the Rope implementation can deal with Empty nodes, even though we - * guard against them. See also {@link LiteralByteStringTest#testConcat_empty()}. + * Test the Rope implementation can deal with Empty nodes, even though we guard against them. See + * also {@link LiteralByteStringTest#testConcat_empty()}. */ public void testConcat_empty() { byte[] referenceBytes = getTestBytes(7748, 113344L); ByteString literalString = ByteString.copyFrom(referenceBytes); ByteString duo = RopeByteString.newInstanceForTest(literalString, literalString); - ByteString temp = RopeByteString.newInstanceForTest( - RopeByteString.newInstanceForTest(literalString, ByteString.EMPTY), - RopeByteString.newInstanceForTest(ByteString.EMPTY, literalString)); + ByteString temp = + RopeByteString.newInstanceForTest( + RopeByteString.newInstanceForTest(literalString, ByteString.EMPTY), + RopeByteString.newInstanceForTest(ByteString.EMPTY, literalString)); ByteString quintet = RopeByteString.newInstanceForTest(temp, ByteString.EMPTY); - assertTrue("String with concatenated nulls must equal simple concatenate", - duo.equals(quintet)); - assertEquals("String with concatenated nulls have same hashcode as simple concatenate", - duo.hashCode(), quintet.hashCode()); + assertEquals("String with concatenated nulls must equal simple concatenate", quintet, duo); + assertEquals( + "String with concatenated nulls have same hashcode as simple concatenate", + duo.hashCode(), + quintet.hashCode()); ByteString.ByteIterator duoIter = duo.iterator(); ByteString.ByteIterator quintetIter = quintet.iterator(); @@ -653,11 +771,13 @@ public void testConcat_empty() { // It is possible, using the testing factory method to create deeply nested // trees of empty leaves, to make a string that will fail this test. for (int i = 1; i < duo.size(); ++i) { - assertTrue("Substrings of size() < 2 must not be RopeByteStrings", + assertTrue( + "Substrings of size() < 2 must not be RopeByteStrings", duo.substring(i - 1, i) instanceof ByteString.LeafByteString); } for (int i = 1; i < quintet.size(); ++i) { - assertTrue("Substrings of size() < 2 must not be RopeByteStrings", + assertTrue( + "Substrings of size() < 2 must not be RopeByteStrings", quintet.substring(i - 1, i) instanceof ByteString.LeafByteString); } } @@ -706,8 +826,7 @@ static List makeConcretePieces(byte[] referenceBytes) { return pieces; } - private byte[] substringUsingWriteTo( - ByteString data, int offset, int length) throws IOException { + private byte[] substringUsingWriteTo(ByteString data, int offset, int length) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); data.writeTo(output, offset, length); return output.toByteArray(); @@ -718,9 +837,7 @@ public void testWriteToOutputStream() throws Exception { // won't be merged into one byte array due to some optimizations. final int dataSize = ByteString.CONCATENATE_BY_COPY_SIZE + 1; byte[] data1 = new byte[dataSize]; - for (int i = 0; i < data1.length; i++) { - data1[i] = (byte) 1; - } + Arrays.fill(data1, (byte) 1); data1[1] = (byte) 11; // Test LiteralByteString.writeTo(OutputStream,int,int) ByteString left = ByteString.wrap(data1); @@ -729,9 +846,7 @@ public void testWriteToOutputStream() throws Exception { assertEquals((byte) 11, result[0]); byte[] data2 = new byte[dataSize]; - for (int i = 0; i < data1.length; i++) { - data2[i] = (byte) 2; - } + Arrays.fill(data2, 0, data1.length, (byte) 2); ByteString right = ByteString.wrap(data2); // Concatenate two ByteStrings to create a RopeByteString. ByteString root = left.concat(right); @@ -756,11 +871,12 @@ public void testWriteToOutputStream() throws Exception { assertEquals((byte) 2, result[dataSize - dataSize / 2]); assertEquals((byte) 2, result[dataSize - 1]); } - - /** - * Tests ByteString uses Arrays based byte copier when running under Hotstop VM. - */ + + /** Tests ByteString uses Arrays based byte copier when running under Hotstop VM. */ public void testByteArrayCopier() throws Exception { + if (Android.isOnAndroidDevice()) { + return; + } Field field = ByteString.class.getDeclaredField("byteArrayCopier"); field.setAccessible(true); Object byteArrayCopier = field.get(null); diff --git a/java/core/src/test/java/com/google/protobuf/CachedFieldSizeTest.java b/java/core/src/test/java/com/google/protobuf/CachedFieldSizeTest.java new file mode 100644 index 0000000000000..96319d93c597f --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/CachedFieldSizeTest.java @@ -0,0 +1,65 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static org.junit.Assert.assertEquals; + +import protobuf_unittest.UnittestProto.TestPackedTypes; +import proto3_unittest.UnittestProto3; +import protobuf_unittest.TestCachedFieldSizeMessage; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public final class CachedFieldSizeTest { + // Regression test for b/74087933 + @Test + public void testCachedFieldSize() throws Exception { + TestCachedFieldSizeMessage.Builder builder = TestCachedFieldSizeMessage.newBuilder(); + builder.setProto2Child(TestUtil.getPackedSet()); + builder.setProto3Child( + UnittestProto3.TestPackedTypes.parseFrom(TestUtil.getPackedSet().toByteArray())); + TestCachedFieldSizeMessage message = builder.build(); + + // Serialize once to cache all field sizes. This will use the experimental runtime because + // the proto has optimize_for = CODE_SIZE. + message.toByteArray(); + // Serialize individual submessages. This will use the generated implementation. If the + // experimental runtime hasn't set the correct cached size, this will throw an exception. + byte[] data2 = message.getProto2Child().toByteArray(); + byte[] data3 = message.getProto3Child().toByteArray(); + + // Make sure the serialized data is correct. + assertEquals(message.getProto2Child(), TestPackedTypes.parseFrom(data2)); + assertEquals(message.getProto3Child(), UnittestProto3.TestPackedTypes.parseFrom(data3)); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java b/java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java index cc65d19ab7471..e276225e7ad99 100644 --- a/java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java +++ b/java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java @@ -34,26 +34,25 @@ import proto2_test_check_utf8.TestCheckUtf8.StringWrapper; import proto2_test_check_utf8_size.TestCheckUtf8Size.BytesWrapperSize; import proto2_test_check_utf8_size.TestCheckUtf8Size.StringWrapperSize; - +import java.io.ByteArrayInputStream; import junit.framework.TestCase; /** - * Test that protos generated with file option java_string_check_utf8 do in - * fact perform appropriate UTF-8 checks. + * Test that protos generated with file option java_string_check_utf8 do in fact perform appropriate + * UTF-8 checks. * * @author jbaum@google.com (Jacob Butcher) */ public class CheckUtf8Test extends TestCase { private static final String UTF8_BYTE_STRING_TEXT = "some text"; - private static final ByteString UTF8_BYTE_STRING = - ByteString.copyFromUtf8(UTF8_BYTE_STRING_TEXT); + private static final ByteString UTF8_BYTE_STRING = ByteString.copyFromUtf8(UTF8_BYTE_STRING_TEXT); private static final ByteString NON_UTF8_BYTE_STRING = - ByteString.copyFrom(new byte[]{(byte) 0x80}); // A lone continuation byte. + ByteString.copyFrom(new byte[] {(byte) 0x80}); // A lone continuation byte. public void testBuildRequiredStringWithGoodUtf8() throws Exception { - assertEquals(UTF8_BYTE_STRING_TEXT, - StringWrapper.newBuilder().setReqBytes(UTF8_BYTE_STRING).getReq()); + assertEquals( + UTF8_BYTE_STRING_TEXT, StringWrapper.newBuilder().setReqBytes(UTF8_BYTE_STRING).getReq()); } public void testParseRequiredStringWithGoodUtf8() throws Exception { @@ -90,14 +89,9 @@ public void testBuildRepeatedStringWithBadUtf8() throws Exception { } public void testParseRequiredStringWithBadUtf8() throws Exception { - ByteString serialized = - BytesWrapper.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString(); - try { - StringWrapper.parser().parseFrom(serialized); - fail("Expected InvalidProtocolBufferException for non UTF-8 byte string."); - } catch (InvalidProtocolBufferException exception) { - assertEquals("Protocol message had invalid UTF-8.", exception.getMessage()); - } + byte[] serialized = + BytesWrapper.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteArray(); + assertParseBadUtf8(StringWrapper.getDefaultInstance(), serialized); } public void testBuildRequiredStringWithBadUtf8Size() throws Exception { @@ -128,14 +122,36 @@ public void testBuildRepeatedStringWithBadUtf8Size() throws Exception { } public void testParseRequiredStringWithBadUtf8Size() throws Exception { - ByteString serialized = - BytesWrapperSize.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString(); + byte[] serialized = + BytesWrapperSize.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteArray(); + assertParseBadUtf8(StringWrapperSize.getDefaultInstance(), serialized); + } + + private void assertParseBadUtf8(MessageLite defaultInstance, byte[] data) throws Exception { + // Check combinations of (parser vs. builder) x (byte[] vs. InputStream) + try { + defaultInstance.getParserForType().parseFrom(data); + fail("Expected InvalidProtocolBufferException for non UTF-8 byte string."); + } catch (InvalidProtocolBufferException exception) { + assertEquals("Protocol message had invalid UTF-8.", exception.getMessage()); + } + try { + defaultInstance.newBuilderForType().mergeFrom(data); + fail("Expected InvalidProtocolBufferException for non UTF-8 byte string."); + } catch (InvalidProtocolBufferException exception) { + assertEquals("Protocol message had invalid UTF-8.", exception.getMessage()); + } try { - StringWrapperSize.parser().parseFrom(serialized); + defaultInstance.getParserForType().parseFrom(new ByteArrayInputStream(data)); + fail("Expected InvalidProtocolBufferException for non UTF-8 byte string."); + } catch (InvalidProtocolBufferException exception) { + assertEquals("Protocol message had invalid UTF-8.", exception.getMessage()); + } + try { + defaultInstance.newBuilderForType().mergeFrom(new ByteArrayInputStream(data)); fail("Expected InvalidProtocolBufferException for non UTF-8 byte string."); } catch (InvalidProtocolBufferException exception) { assertEquals("Protocol message had invalid UTF-8.", exception.getMessage()); } } - } diff --git a/java/core/src/test/java/com/google/protobuf/CodedAdapterTest.java b/java/core/src/test/java/com/google/protobuf/CodedAdapterTest.java new file mode 100644 index 0000000000000..a24b48b51e22a --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/CodedAdapterTest.java @@ -0,0 +1,110 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static org.junit.Assert.assertEquals; + +import com.google.protobuf.testing.Proto2Testing.Proto2Message; +import com.google.protobuf.testing.Proto3Testing.Proto3Message; +import java.io.IOException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public final class CodedAdapterTest { + @Before + public void setup() { + TestSchemas.registerGenericProto2Schemas(); + + Protobuf.getInstance() + .registerSchemaOverride(Proto3Message.class, TestSchemas.genericProto3Schema); + } + + @Test + public void proto3Roundtrip() throws Exception { + Proto3Message expected = new Proto3MessageFactory(5, 10, 2, 2).newMessage(); + byte[] expectedBytes = expected.toByteArray(); + + // Deserialize with BinaryReader and verify that the message matches the original. + Proto3Message result = fromByteArray(expectedBytes, Proto3Message.class); + assertEquals(expected, result); + + // Now write it back out using BinaryWriter and verify the output length. + byte[] actualBytes = toByteArray(result, expectedBytes.length); + + // Read back in the bytes and verify that it matches the original message. + Proto3Message actual = Proto3Message.parseFrom(actualBytes); + assertEquals(expected, actual); + } + + @Test + public void proto2Roundtrip() throws Exception { + Proto2Message expected = new Proto2MessageFactory(5, 10, 2, 2).newMessage(); + byte[] expectedBytes = expected.toByteArray(); + + // Deserialize with BinaryReader and verify that the message matches the original. + Proto2Message result = fromByteArray(expectedBytes, Proto2Message.class); + assertEquals(expected, result); + + // Now write it back out using BinaryWriter and verify the output length. + byte[] actualBytes = toByteArray(result, expectedBytes.length); + + // Read back in the bytes and verify that it matches the original message. + Proto2Message actual = Proto2Message.parseFrom(actualBytes); + assertEquals(expected, actual); + } + + public static byte[] toByteArray(T msg, int size) throws Exception { + Schema schema = Protobuf.getInstance().schemaFor(msg); + byte[] out = new byte[size]; + CodedOutputStreamWriter writer = + CodedOutputStreamWriter.forCodedOutput(CodedOutputStream.newInstance(out)); + schema.writeTo(msg, writer); + assertEquals(out.length, writer.getTotalBytesWritten()); + return out; + } + + public static T fromByteArray(byte[] data, Class messageType) { + Schema schema = Protobuf.getInstance().schemaFor(messageType); + try { + T msg = schema.newInstance(); + schema.mergeFrom( + msg, + CodedInputStreamReader.forCodedInput(CodedInputStream.newInstance(data)), + ExtensionRegistryLite.EMPTY_REGISTRY_LITE); + return msg; + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java index da2c067ebb1c7..532052cdb35a4 100644 --- a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java +++ b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java @@ -30,6 +30,7 @@ package com.google.protobuf; +import static org.junit.Assert.assertArrayEquals; import protobuf_unittest.UnittestProto.BoolMessage; import protobuf_unittest.UnittestProto.Int32Message; import protobuf_unittest.UnittestProto.Int64Message; @@ -41,7 +42,9 @@ import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import junit.framework.TestCase; /** @@ -50,6 +53,9 @@ * @author kenton@google.com Kenton Varda */ public class CodedInputStreamTest extends TestCase { + + private static final int DEFAULT_BLOCK_SIZE = 4096; + private enum InputType { ARRAY { @Override @@ -77,6 +83,40 @@ CodedInputStream newDecoder(byte[] data, int blockSize) { CodedInputStream newDecoder(byte[] data, int blockSize) { return CodedInputStream.newInstance(new SmallBlockInputStream(data, blockSize)); } + }, + ITER_DIRECT { + @Override + CodedInputStream newDecoder(byte[] data, int blockSize) { + if (blockSize > DEFAULT_BLOCK_SIZE) { + blockSize = DEFAULT_BLOCK_SIZE; + } + ArrayList input = new ArrayList(); + for (int i = 0; i < data.length; i += blockSize) { + int rl = Math.min(blockSize, data.length - i); + ByteBuffer rb = ByteBuffer.allocateDirect(rl); + rb.put(data, i, rl); + rb.flip(); + input.add(rb); + } + return CodedInputStream.newInstance(input); + } + }, + STREAM_ITER_DIRECT { + @Override + CodedInputStream newDecoder(byte[] data, int blockSize) { + if (blockSize > DEFAULT_BLOCK_SIZE) { + blockSize = DEFAULT_BLOCK_SIZE; + } + ArrayList input = new ArrayList(); + for (int i = 0; i < data.length; i += blockSize) { + int rl = Math.min(blockSize, data.length - i); + ByteBuffer rb = ByteBuffer.allocateDirect(rl); + rb.put(data, i, rl); + rb.flip(); + input.add(rb); + } + return CodedInputStream.newInstance(new IterableByteBufferInputStream(input)); + } }; CodedInputStream newDecoder(byte[] data) { @@ -104,21 +144,37 @@ private byte[] bytes(int... bytesAsInts) { */ private static final class SmallBlockInputStream extends FilterInputStream { private final int blockSize; + private int skipCalls; + private int readCalls; public SmallBlockInputStream(byte[] data, int blockSize) { super(new ByteArrayInputStream(data)); this.blockSize = blockSize; } + @Override + public int read() throws IOException { + readCalls++; + return super.read(); + } + @Override public int read(byte[] b) throws IOException { + readCalls++; return super.read(b, 0, Math.min(b.length, blockSize)); } @Override public int read(byte[] b, int off, int len) throws IOException { + readCalls++; return super.read(b, off, Math.min(len, blockSize)); } + + @Override + public long skip(long len) throws IOException { + skipCalls++; + return super.skip(Math.min(len, blockSize)); + } } private void assertDataConsumed(String msg, byte[] data, CodedInputStream input) @@ -390,6 +446,41 @@ public void testSkipRawBytesPastEndOfBufferWithLimit() throws Exception { } } + /** + * Test that calling skipRawBytes (when not merging a message) actually skips from the underlying + * inputstream, regardless of the buffer size used. + */ + public void testSkipRawBytesActuallySkips() throws Exception { + SmallBlockInputStream bytes = new SmallBlockInputStream(new byte[] {1, 2, 3, 4, 5}, 3); + CodedInputStream input = CodedInputStream.newInstance(bytes, 1); // Tiny buffer + input.skipRawBytes(3); + input.skipRawBytes(2); + assertEquals(2, bytes.skipCalls); + assertEquals(0, bytes.readCalls); + } + + public void testSkipHugeBlob() throws Exception { + // Allocate and initialize a 1MB blob. + int blobSize = 1 << 20; + byte[] blob = new byte[blobSize]; + for (int i = 0; i < blob.length; i++) { + blob[i] = (byte) i; + } + + for (InputType inputType : InputType.values()) { + CodedInputStream decoder = inputType.newDecoder(blob); + decoder.skipRawBytes(blobSize - 10); + byte[] remaining = decoder.readRawBytes(10); + assertArrayEquals(Arrays.copyOfRange(blob, blobSize - 10, blobSize), remaining); + } + } + + /** Skipping a huge blob should not allocate excessive memory, so there should be no limit */ + public void testSkipMaliciouslyHugeBlob() throws Exception { + InputStream is = new RepeatingInputStream(new byte[]{1}, Integer.MAX_VALUE); + CodedInputStream.newInstance(is).skipRawBytes(Integer.MAX_VALUE); + } + public void testReadHugeBlob() throws Exception { // Allocate and initialize a 1MB blob. byte[] blob = new byte[1 << 20]; @@ -445,8 +536,9 @@ public void testReadMaliciouslyLargeBlob() throws Exception { } /** - * Test we can do messages that are up to CodedInputStream#DEFAULT_SIZE_LIMIT - * in size (2G or Integer#MAX_SIZE). + * Test we can do messages that are up to CodedInputStream#DEFAULT_SIZE_LIMIT in size (2G or + * Integer#MAX_SIZE). + * * @throws IOException */ public void testParseMessagesCloseTo2G() throws IOException { @@ -461,8 +553,9 @@ public void testParseMessagesCloseTo2G() throws IOException { } /** - * Test there is an exception if a message exceeds - * CodedInputStream#DEFAULT_SIZE_LIMIT in size (2G or Integer#MAX_SIZE). + * Test there is an exception if a message exceeds CodedInputStream#DEFAULT_SIZE_LIMIT in size (2G + * or Integer#MAX_SIZE). + * * @throws IOException */ public void testParseMessagesOver2G() throws IOException { @@ -486,7 +579,7 @@ public void testParseMessagesOver2G() throws IOException { * @return A serialized big message. */ private static byte[] getBigSerializedMessage() { - byte[] value = new byte[16 * 1024 * 1024]; + byte[] value = new byte[16 * 1024 * 1024]; ByteString bsValue = ByteString.wrap(value); return TestAllTypes.newBuilder().setOptionalBytes(bsValue).build().toByteArray(); } @@ -614,7 +707,7 @@ public void testResetSizeCounter() throws Exception { checkSizeLimitExceeded(expected); } } - + public void testRefillBufferWithCorrectSize() throws Exception { // NOTE: refillBuffer only applies to the stream-backed CIS. byte[] bytes = "123456789".getBytes("UTF-8"); @@ -632,14 +725,15 @@ public void testRefillBufferWithCorrectSize() throws Exception { output.flush(); // Input is two string with length 9 and one raw byte. - byte[] rawInput = rawOutput.toByteArray(); - for (int inputStreamBufferLength = 8; - inputStreamBufferLength <= rawInput.length + 1; inputStreamBufferLength++) { - CodedInputStream input = CodedInputStream.newInstance( - new ByteArrayInputStream(rawInput), inputStreamBufferLength); + byte[] rawInput = rawOutput.toByteArray(); + for (int inputStreamBufferLength = 8; + inputStreamBufferLength <= rawInput.length + 1; + inputStreamBufferLength++) { + CodedInputStream input = + CodedInputStream.newInstance(new ByteArrayInputStream(rawInput), inputStreamBufferLength); input.setSizeLimit(rawInput.length - 1); input.readString(); - input.readString(); + input.readString(); try { input.readRawByte(); // Hits limit. fail("Should have thrown an exception!"); @@ -650,16 +744,15 @@ public void testRefillBufferWithCorrectSize() throws Exception { } public void testIsAtEnd() throws Exception { - CodedInputStream input = CodedInputStream.newInstance( - new ByteArrayInputStream(new byte[5])); - try { + CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(new byte[5])); + try { for (int i = 0; i < 5; i++) { assertEquals(false, input.isAtEnd()); input.readRawByte(); } assertEquals(true, input.isAtEnd()); } catch (Exception e) { - fail("Catch exception in the testIsAtEnd"); + throw new AssertionError("Catch exception in the testIsAtEnd", e); } } @@ -675,19 +768,18 @@ public void testCurrentLimitExceeded() throws Exception { output.flush(); byte[] rawInput = rawOutput.toByteArray(); - CodedInputStream input = CodedInputStream.newInstance( - new ByteArrayInputStream(rawInput)); + CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(rawInput)); // The length of the whole rawInput input.setSizeLimit(11); // Some number that is smaller than the rawInput's length - // but larger than 2 + // but larger than 2 input.pushLimit(5); try { input.readString(); fail("Should have thrown an exception"); } catch (InvalidProtocolBufferException expected) { - assertEquals(expected.getMessage(), - InvalidProtocolBufferException.truncatedMessage().getMessage()); + assertEquals( + expected.getMessage(), InvalidProtocolBufferException.truncatedMessage().getMessage()); } } @@ -896,13 +988,14 @@ public void testReadLargeByteStringFromInputStream() throws Exception { output.flush(); byte[] data = rawOutput.toByteString().toByteArray(); - CodedInputStream input = CodedInputStream.newInstance( - new ByteArrayInputStream(data) { - @Override - public synchronized int available() { - return 0; - } - }); + CodedInputStream input = + CodedInputStream.newInstance( + new ByteArrayInputStream(data) { + @Override + public synchronized int available() { + return 0; + } + }); ByteString result = input.readBytes(); assertEquals(ByteString.copyFrom(bytes), result); } @@ -919,13 +1012,14 @@ public void testReadLargeByteArrayFromInputStream() throws Exception { output.flush(); byte[] data = rawOutput.toByteString().toByteArray(); - CodedInputStream input = CodedInputStream.newInstance( - new ByteArrayInputStream(data) { - @Override - public synchronized int available() { - return 0; - } - }); + CodedInputStream input = + CodedInputStream.newInstance( + new ByteArrayInputStream(data) { + @Override + public synchronized int available() { + return 0; + } + }); byte[] result = input.readByteArray(); assertTrue(Arrays.equals(bytes, result)); } @@ -994,7 +1088,9 @@ public void testReadByteBufferAliasing() throws Exception { byte[] data = byteArrayStream.toByteArray(); for (InputType inputType : InputType.values()) { - if (inputType == InputType.STREAM) { + if (inputType == InputType.STREAM + || inputType == InputType.STREAM_ITER_DIRECT + || inputType == InputType.ITER_DIRECT) { // Aliasing doesn't apply to stream-backed CIS. continue; } @@ -1019,7 +1115,7 @@ public void testReadByteBufferAliasing() throws Exception { assertEquals(inputType.name(), (byte) 89, result.get()); // Enable aliasing - inputStream = inputType.newDecoder(data); + inputStream = inputType.newDecoder(data, data.length); inputStream.enableAliasing(true); result = inputStream.readByteBuffer(); assertEquals(inputType.name(), 0, result.capacity()); @@ -1091,4 +1187,68 @@ public void testSkipInvalidVarint_SlowPath() throws Exception { } } } + + public void testSkipPastEndOfByteArrayInput() throws Exception { + try { + CodedInputStream.newInstance(new ByteArrayInputStream(new byte[100])).skipRawBytes(101); + fail(); + } catch (InvalidProtocolBufferException e) { + // Expected + } + } + + public void testMaliciousInputStream() throws Exception { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + CodedOutputStream codedOutputStream = CodedOutputStream.newInstance(outputStream); + codedOutputStream.writeByteArrayNoTag(new byte[] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5 }); + codedOutputStream.flush(); + final List maliciousCapture = new ArrayList<>(); + InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()) { + @Override + public synchronized int read(byte[] b, int off, int len) { + maliciousCapture.add(b); + return super.read(b, off, len); + } + }; + + // test ByteString + + CodedInputStream codedInputStream = CodedInputStream.newInstance(inputStream, 1); + ByteString byteString = codedInputStream.readBytes(); + assertEquals(0x0, byteString.byteAt(0)); + maliciousCapture.get(1)[0] = 0x9; + assertEquals(0x0, byteString.byteAt(0)); + + // test ByteBuffer + + inputStream.reset(); + maliciousCapture.clear(); + codedInputStream = CodedInputStream.newInstance(inputStream, 1); + ByteBuffer byteBuffer = codedInputStream.readByteBuffer(); + assertEquals(0x0, byteBuffer.get(0)); + maliciousCapture.get(1)[0] = 0x9; + assertEquals(0x0, byteBuffer.get(0)); + + + // test byte[] + + inputStream.reset(); + maliciousCapture.clear(); + codedInputStream = CodedInputStream.newInstance(inputStream, 1); + byte[] byteArray = codedInputStream.readByteArray(); + assertEquals(0x0, byteArray[0]); + maliciousCapture.get(1)[0] = 0x9; + assertEquals(0x9, byteArray[0]); // MODIFICATION! Should we fix? + + // test rawBytes + + inputStream.reset(); + maliciousCapture.clear(); + codedInputStream = CodedInputStream.newInstance(inputStream, 1); + int length = codedInputStream.readRawVarint32(); + byteArray = codedInputStream.readRawBytes(length); + assertEquals(0x0, byteArray[0]); + maliciousCapture.get(1)[0] = 0x9; + assertEquals(0x9, byteArray[0]); // MODIFICATION! Should we fix? + } } diff --git a/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java b/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java index 78f415c254dfc..8dc3e4ce7a4ae 100644 --- a/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java +++ b/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java @@ -257,13 +257,27 @@ public void testWriteVarint() throws Exception { // 41256202580718336 assertWriteVarint( bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49), - (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) | (0x43L << 28) | (0x49L << 35) - | (0x24L << 42) | (0x49L << 49)); + (0x00 << 0) + | (0x66 << 7) + | (0x6b << 14) + | (0x1c << 21) + | (0x43L << 28) + | (0x49L << 35) + | (0x24L << 42) + | (0x49L << 49)); // 11964378330978735131 assertWriteVarint( bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01), - (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) | (0x3bL << 28) | (0x56L << 35) - | (0x00L << 42) | (0x05L << 49) | (0x26L << 56) | (0x01L << 63)); + (0x1b << 0) + | (0x28 << 7) + | (0x79 << 14) + | (0x42 << 21) + | (0x3bL << 28) + | (0x56L << 35) + | (0x00L << 42) + | (0x05L << 49) + | (0x26L << 56) + | (0x01L << 63)); } /** Tests writeRawLittleEndian32() and writeRawLittleEndian64(). */ @@ -344,8 +358,8 @@ public void testWriteWholeMessage() throws Exception { } /** - * Tests writing a whole message with every packed field type. Ensures the - * wire format of packed fields is compatible with C++. + * Tests writing a whole message with every packed field type. Ensures the wire format of packed + * fields is compatible with C++. */ public void testWriteWholePackedFieldsMessage() throws Exception { byte[] expectedBytes = TestUtil.getGoldenPackedFieldsMessage().toByteArray(); @@ -361,8 +375,8 @@ public void testWriteWholePackedFieldsMessage() throws Exception { } /** - * Test writing a message containing a negative enum value. This used to - * fail because the size was not properly computed as a sign-extended varint. + * Test writing a message containing a negative enum value. This used to fail because the size was + * not properly computed as a sign-extended varint. */ public void testWriteMessageWithNegativeEnumValue() throws Exception { SparseEnumMessage message = @@ -394,8 +408,9 @@ public void testGetTotalBytesWritten() throws Exception { String string = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"; // Ensure we take the slower fast path. - assertTrue(CodedOutputStream.computeUInt32SizeNoTag(string.length()) - != CodedOutputStream.computeUInt32SizeNoTag(string.length() * Utf8.MAX_BYTES_PER_CHAR)); + assertTrue( + CodedOutputStream.computeUInt32SizeNoTag(string.length()) + != CodedOutputStream.computeUInt32SizeNoTag(string.length() * Utf8.MAX_BYTES_PER_CHAR)); coder.stream().writeStringNoTag(string); coder.stream().flush(); @@ -438,9 +453,7 @@ public void testWriteToByteBuffer() throws Exception { } final int length2 = 8 * 1024; byte[] data = new byte[length2]; - for (int i = 0; i < length2; i++) { - data[i] = (byte) 2; - } + Arrays.fill(data, 0, length2, (byte) 2); codedStream.writeRawBytes(data); final int length3 = bufferSize - length1 - length2; for (int i = 0; i < length3; i++) { @@ -521,10 +534,14 @@ public void testSerializeUtf8_MultipleSmallWrites() throws Exception { } public void testSerializeInvalidUtf8() throws Exception { - String[] invalidStrings = new String[] {newString(Character.MIN_HIGH_SURROGATE), - "foobar" + newString(Character.MIN_HIGH_SURROGATE), newString(Character.MIN_LOW_SURROGATE), - "foobar" + newString(Character.MIN_LOW_SURROGATE), - newString(Character.MIN_HIGH_SURROGATE, Character.MIN_HIGH_SURROGATE)}; + String[] invalidStrings = + new String[] { + newString(Character.MIN_HIGH_SURROGATE), + "foobar" + newString(Character.MIN_HIGH_SURROGATE), + newString(Character.MIN_LOW_SURROGATE), + "foobar" + newString(Character.MIN_LOW_SURROGATE), + newString(Character.MIN_HIGH_SURROGATE, Character.MIN_HIGH_SURROGATE) + }; CodedOutputStream outputWithStream = CodedOutputStream.newInstance(new ByteArrayOutputStream()); CodedOutputStream outputWithArray = CodedOutputStream.newInstance(new byte[10000]); @@ -562,7 +579,7 @@ public void testSerializeInvalidUtf8FollowedByOutOfSpace() throws Exception { } } - /** Regression test for https://github.com/google/protobuf/issues/292 */ + /** Regression test for https://github.com/protocolbuffers/protobuf/issues/292 */ public void testCorrectExceptionThrowWhenEncodingStringsWithoutEnoughSpace() throws Exception { String testCase = "Foooooooo"; assertEquals( @@ -594,16 +611,17 @@ public void testDifferentStringLengths() throws Exception { // with ASCII and Unicode characters requiring different UTF-8 byte counts per // char, hence causing the length delimiter varint to sometimes require more // bytes for the Unicode strings than the ASCII string of the same length. - int[] lengths = new int[] { - 0, - 1, - (1 << 4) - 1, // 1 byte for ASCII and Unicode - (1 << 7) - 1, // 1 byte for ASCII, 2 bytes for Unicode - (1 << 11) - 1, // 2 bytes for ASCII and Unicode - (1 << 14) - 1, // 2 bytes for ASCII, 3 bytes for Unicode - (1 << 17) - 1, - // 3 bytes for ASCII and Unicode - }; + int[] lengths = + new int[] { + 0, + 1, + (1 << 4) - 1, // 1 byte for ASCII and Unicode + (1 << 7) - 1, // 1 byte for ASCII, 2 bytes for Unicode + (1 << 11) - 1, // 2 bytes for ASCII and Unicode + (1 << 14) - 1, // 2 bytes for ASCII, 3 bytes for Unicode + (1 << 17) - 1, + // 3 bytes for ASCII and Unicode + }; for (OutputType outputType : OutputType.values()) { for (int i : lengths) { testEncodingOfString(outputType, 'q', i); // 1 byte per char @@ -626,8 +644,8 @@ public void testNioEncodersWithInitialOffsets() throws Exception { } /** - * Parses the given bytes using writeRawLittleEndian32() and checks - * that the result matches the given value. + * Parses the given bytes using writeRawLittleEndian32() and checks that the result matches the + * given value. */ private static void assertWriteLittleEndian32(byte[] data, int value) throws Exception { for (OutputType outputType : OutputType.values()) { @@ -647,8 +665,8 @@ private static void assertWriteLittleEndian32(byte[] data, int value) throws Exc } /** - * Parses the given bytes using writeRawLittleEndian64() and checks - * that the result matches the given value. + * Parses the given bytes using writeRawLittleEndian64() and checks that the result matches the + * given value. */ private static void assertWriteLittleEndian64(byte[] data, long value) throws Exception { for (OutputType outputType : OutputType.values()) { @@ -691,9 +709,8 @@ private static String fullString(char c, int length) { } /** - * Helper to construct a byte array from a bunch of bytes. The inputs are - * actually ints so that I can use hex notation and not get stupid errors - * about precision. + * Helper to construct a byte array from a bunch of bytes. The inputs are actually ints so that I + * can use hex notation and not get stupid errors about precision. */ private static byte[] bytes(int... bytesAsInts) { byte[] bytes = new byte[bytesAsInts.length]; @@ -703,7 +720,7 @@ private static byte[] bytes(int... bytesAsInts) { return bytes; } - /** Arrays.asList() does not work with arrays of primitives. :( */ + /** Arrays.asList() does not work with arrays of primitives. :( */ private static List toList(byte[] bytes) { List result = new ArrayList(); for (byte b : bytes) { @@ -717,8 +734,8 @@ private static void assertEqualBytes(OutputType outputType, byte[] a, byte[] b) } /** - * Writes the given value using writeRawVarint32() and writeRawVarint64() and - * checks that the result matches the given bytes. + * Writes the given value using writeRawVarint32() and writeRawVarint64() and checks that the + * result matches the given bytes. */ private static void assertWriteVarint(byte[] data, long value) throws Exception { for (OutputType outputType : OutputType.values()) { diff --git a/java/core/src/test/java/com/google/protobuf/DecodeUtf8Test.java b/java/core/src/test/java/com/google/protobuf/DecodeUtf8Test.java new file mode 100644 index 0000000000000..359d4d74c02be --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/DecodeUtf8Test.java @@ -0,0 +1,325 @@ +package com.google.protobuf; + +import com.google.protobuf.Utf8.Processor; +import com.google.protobuf.Utf8.SafeProcessor; +import com.google.protobuf.Utf8.UnsafeProcessor; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; +import junit.framework.TestCase; + +public class DecodeUtf8Test extends TestCase { + private static Logger logger = Logger.getLogger(DecodeUtf8Test.class.getName()); + + private static final Processor SAFE_PROCESSOR = new SafeProcessor(); + private static final Processor UNSAFE_PROCESSOR = new UnsafeProcessor(); + + public void testRoundTripAllValidChars() throws Exception { + for (int i = Character.MIN_CODE_POINT; i < Character.MAX_CODE_POINT; i++) { + if (i < Character.MIN_SURROGATE || i > Character.MAX_SURROGATE) { + String str = new String(Character.toChars(i)); + assertRoundTrips(str); + } + } + } + + // Test all 1, 2, 3 invalid byte combinations. Valid ones would have been covered above. + + public void testOneByte() throws Exception { + int valid = 0; + for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { + ByteString bs = ByteString.copyFrom(new byte[] { (byte) i }); + if (!bs.isValidUtf8()) { + assertInvalid(bs.toByteArray()); + } else { + valid++; + } + } + assertEquals(IsValidUtf8TestUtil.EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, valid); + } + + public void testTwoBytes() throws Exception { + int valid = 0; + for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { + for (int j = Byte.MIN_VALUE; j <= Byte.MAX_VALUE; j++) { + ByteString bs = ByteString.copyFrom(new byte[]{(byte) i, (byte) j}); + if (!bs.isValidUtf8()) { + assertInvalid(bs.toByteArray()); + } else { + valid++; + } + } + } + assertEquals(IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT, valid); + } + + public void testThreeBytes() throws Exception { + // Travis' OOM killer doesn't like this test + if (System.getenv("TRAVIS") == null) { + int count = 0; + int valid = 0; + for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { + for (int j = Byte.MIN_VALUE; j <= Byte.MAX_VALUE; j++) { + for (int k = Byte.MIN_VALUE; k <= Byte.MAX_VALUE; k++) { + byte[] bytes = new byte[]{(byte) i, (byte) j, (byte) k}; + ByteString bs = ByteString.copyFrom(bytes); + if (!bs.isValidUtf8()) { + assertInvalid(bytes); + } else { + valid++; + } + count++; + if (count % 1000000L == 0) { + logger.info("Processed " + (count / 1000000L) + " million characters"); + } + } + } + } + assertEquals(IsValidUtf8TestUtil.EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT, valid); + } + } + + /** + * Tests that round tripping of a sample of four byte permutations work. + */ + public void testInvalid_4BytesSamples() throws Exception { + // Bad trailing bytes + assertInvalid(0xF0, 0xA4, 0xAD, 0x7F); + assertInvalid(0xF0, 0xA4, 0xAD, 0xC0); + + // Special cases for byte2 + assertInvalid(0xF0, 0x8F, 0xAD, 0xA2); + assertInvalid(0xF4, 0x90, 0xAD, 0xA2); + } + + public void testRealStrings() throws Exception { + // English + assertRoundTrips("The quick brown fox jumps over the lazy dog"); + // German + assertRoundTrips("Quizdeltagerne spiste jordb\u00e6r med fl\u00f8de, mens cirkusklovnen"); + // Japanese + assertRoundTrips( + "\u3044\u308d\u306f\u306b\u307b\u3078\u3068\u3061\u308a\u306c\u308b\u3092"); + // Hebrew + assertRoundTrips( + "\u05d3\u05d2 \u05e1\u05e7\u05e8\u05df \u05e9\u05d8 \u05d1\u05d9\u05dd " + + "\u05de\u05d0\u05d5\u05db\u05d6\u05d1 \u05d5\u05dc\u05e4\u05ea\u05e2" + + " \u05de\u05e6\u05d0 \u05dc\u05d5 \u05d7\u05d1\u05e8\u05d4 " + + "\u05d0\u05d9\u05da \u05d4\u05e7\u05dc\u05d9\u05d8\u05d4"); + // Thai + assertRoundTrips( + " \u0e08\u0e07\u0e1d\u0e48\u0e32\u0e1f\u0e31\u0e19\u0e1e\u0e31\u0e12" + + "\u0e19\u0e32\u0e27\u0e34\u0e0a\u0e32\u0e01\u0e32\u0e23"); + // Chinese + assertRoundTrips( + "\u8fd4\u56de\u94fe\u4e2d\u7684\u4e0b\u4e00\u4e2a\u4ee3\u7406\u9879\u9009\u62e9\u5668"); + // Chinese with 4-byte chars + assertRoundTrips("\uD841\uDF0E\uD841\uDF31\uD841\uDF79\uD843\uDC53\uD843\uDC78" + + "\uD843\uDC96\uD843\uDCCF\uD843\uDCD5\uD843\uDD15\uD843\uDD7C\uD843\uDD7F" + + "\uD843\uDE0E\uD843\uDE0F\uD843\uDE77\uD843\uDE9D\uD843\uDEA2"); + // Mixed + assertRoundTrips( + "The quick brown \u3044\u308d\u306f\u306b\u307b\u3078\u8fd4\u56de\u94fe" + + "\u4e2d\u7684\u4e0b\u4e00"); + } + + public void testOverlong() throws Exception { + assertInvalid(0xc0, 0xaf); + assertInvalid(0xe0, 0x80, 0xaf); + assertInvalid(0xf0, 0x80, 0x80, 0xaf); + + // Max overlong + assertInvalid(0xc1, 0xbf); + assertInvalid(0xe0, 0x9f, 0xbf); + assertInvalid(0xf0 ,0x8f, 0xbf, 0xbf); + + // null overlong + assertInvalid(0xc0, 0x80); + assertInvalid(0xe0, 0x80, 0x80); + assertInvalid(0xf0, 0x80, 0x80, 0x80); + } + + public void testIllegalCodepoints() throws Exception { + // Single surrogate + assertInvalid(0xed, 0xa0, 0x80); + assertInvalid(0xed, 0xad, 0xbf); + assertInvalid(0xed, 0xae, 0x80); + assertInvalid(0xed, 0xaf, 0xbf); + assertInvalid(0xed, 0xb0, 0x80); + assertInvalid(0xed, 0xbe, 0x80); + assertInvalid(0xed, 0xbf, 0xbf); + + // Paired surrogates + assertInvalid(0xed, 0xa0, 0x80, 0xed, 0xb0, 0x80); + assertInvalid(0xed, 0xa0, 0x80, 0xed, 0xbf, 0xbf); + assertInvalid(0xed, 0xad, 0xbf, 0xed, 0xb0, 0x80); + assertInvalid(0xed, 0xad, 0xbf, 0xed, 0xbf, 0xbf); + assertInvalid(0xed, 0xae, 0x80, 0xed, 0xb0, 0x80); + assertInvalid(0xed, 0xae, 0x80, 0xed, 0xbf, 0xbf); + assertInvalid(0xed, 0xaf, 0xbf, 0xed, 0xb0, 0x80); + assertInvalid(0xed, 0xaf, 0xbf, 0xed, 0xbf, 0xbf); + } + + public void testBufferSlice() throws Exception { + String str = "The quick brown fox jumps over the lazy dog"; + assertRoundTrips(str, 10, 4); + assertRoundTrips(str, str.length(), 0); + } + + public void testInvalidBufferSlice() throws Exception { + byte[] bytes = "The quick brown fox jumps over the lazy dog".getBytes(Internal.UTF_8); + assertInvalidSlice(bytes, bytes.length - 3, 4); + assertInvalidSlice(bytes, bytes.length, 1); + assertInvalidSlice(bytes, bytes.length + 1, 0); + assertInvalidSlice(bytes, 0, bytes.length + 1); + } + + private void assertInvalid(int... bytesAsInt) throws Exception { + byte[] bytes = new byte[bytesAsInt.length]; + for (int i = 0; i < bytesAsInt.length; i++) { + bytes[i] = (byte) bytesAsInt[i]; + } + assertInvalid(bytes); + } + + private void assertInvalid(byte[] bytes) throws Exception { + try { + UNSAFE_PROCESSOR.decodeUtf8(bytes, 0, bytes.length); + fail(); + } catch (InvalidProtocolBufferException e) { + // Expected. + } + try { + SAFE_PROCESSOR.decodeUtf8(bytes, 0, bytes.length); + fail(); + } catch (InvalidProtocolBufferException e) { + // Expected. + } + + ByteBuffer direct = ByteBuffer.allocateDirect(bytes.length); + direct.put(bytes); + direct.flip(); + try { + UNSAFE_PROCESSOR.decodeUtf8(direct, 0, bytes.length); + fail(); + } catch (InvalidProtocolBufferException e) { + // Expected. + } + try { + SAFE_PROCESSOR.decodeUtf8(direct, 0, bytes.length); + fail(); + } catch (InvalidProtocolBufferException e) { + // Expected. + } + + ByteBuffer heap = ByteBuffer.allocate(bytes.length); + heap.put(bytes); + heap.flip(); + try { + UNSAFE_PROCESSOR.decodeUtf8(heap, 0, bytes.length); + fail(); + } catch (InvalidProtocolBufferException e) { + // Expected. + } + try { + SAFE_PROCESSOR.decodeUtf8(heap, 0, bytes.length); + fail(); + } catch (InvalidProtocolBufferException e) { + // Expected. + } + } + + private void assertInvalidSlice(byte[] bytes, int index, int size) throws Exception { + try { + UNSAFE_PROCESSOR.decodeUtf8(bytes, index, size); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected. + } + try { + SAFE_PROCESSOR.decodeUtf8(bytes, index, size); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected. + } + + ByteBuffer direct = ByteBuffer.allocateDirect(bytes.length); + direct.put(bytes); + direct.flip(); + try { + UNSAFE_PROCESSOR.decodeUtf8(direct, index, size); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected. + } + try { + SAFE_PROCESSOR.decodeUtf8(direct, index, size); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected. + } + + ByteBuffer heap = ByteBuffer.allocate(bytes.length); + heap.put(bytes); + heap.flip(); + try { + UNSAFE_PROCESSOR.decodeUtf8(heap, index, size); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected. + } + try { + SAFE_PROCESSOR.decodeUtf8(heap, index, size); + fail(); + } catch (ArrayIndexOutOfBoundsException e) { + // Expected. + } + } + + private void assertRoundTrips(String str) throws Exception { + assertRoundTrips(str, 0, -1); + } + + private void assertRoundTrips(String str, int index, int size) throws Exception { + byte[] bytes = str.getBytes(Internal.UTF_8); + if (size == -1) { + size = bytes.length; + } + assertDecode(new String(bytes, index, size, Internal.UTF_8), + UNSAFE_PROCESSOR.decodeUtf8(bytes, index, size)); + assertDecode(new String(bytes, index, size, Internal.UTF_8), + SAFE_PROCESSOR.decodeUtf8(bytes, index, size)); + + ByteBuffer direct = ByteBuffer.allocateDirect(bytes.length); + direct.put(bytes); + direct.flip(); + assertDecode(new String(bytes, index, size, Internal.UTF_8), + UNSAFE_PROCESSOR.decodeUtf8(direct, index, size)); + assertDecode(new String(bytes, index, size, Internal.UTF_8), + SAFE_PROCESSOR.decodeUtf8(direct, index, size)); + + ByteBuffer heap = ByteBuffer.allocate(bytes.length); + heap.put(bytes); + heap.flip(); + assertDecode(new String(bytes, index, size, Internal.UTF_8), + UNSAFE_PROCESSOR.decodeUtf8(heap, index, size)); + assertDecode(new String(bytes, index, size, Internal.UTF_8), + SAFE_PROCESSOR.decodeUtf8(heap, index, size)); + } + + private void assertDecode(String expected, String actual) { + if (!expected.equals(actual)) { + fail("Failure: Expected (" + codepoints(expected) + ") Actual (" + codepoints(actual) + ")"); + } + } + + private List codepoints(String str) { + List codepoints = new ArrayList(); + for (int i = 0; i < str.length(); i++) { + codepoints.add(Long.toHexString(str.charAt(i))); + } + return codepoints; + } + +} diff --git a/java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java b/java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java index 2c272a734773b..2addde8428301 100644 --- a/java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java +++ b/java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java @@ -37,42 +37,42 @@ /** * Test field deprecation - * + * * @author birdo@google.com (Roberto Scaramuzzi) */ public class DeprecatedFieldTest extends TestCase { - private String[] deprecatedGetterNames = { - "hasDeprecatedInt32", - "getDeprecatedInt32"}; - + private String[] deprecatedGetterNames = {"hasDeprecatedInt32", "getDeprecatedInt32"}; + private String[] deprecatedBuilderGetterNames = { - "hasDeprecatedInt32", - "getDeprecatedInt32", - "clearDeprecatedInt32"}; - - private String[] deprecatedBuilderSetterNames = { - "setDeprecatedInt32"}; - + "hasDeprecatedInt32", "getDeprecatedInt32", "clearDeprecatedInt32" + }; + + private String[] deprecatedBuilderSetterNames = {"setDeprecatedInt32"}; + public void testDeprecatedField() throws Exception { Class deprecatedFields = TestDeprecatedFields.class; Class deprecatedFieldsBuilder = TestDeprecatedFields.Builder.class; for (String name : deprecatedGetterNames) { Method method = deprecatedFields.getMethod(name); - assertTrue("Method " + name + " should be deprecated", - isDeprecated(method)); + assertTrue("Method " + name + " should be deprecated", isDeprecated(method)); } for (String name : deprecatedBuilderGetterNames) { Method method = deprecatedFieldsBuilder.getMethod(name); - assertTrue("Method " + name + " should be deprecated", - isDeprecated(method)); + assertTrue("Method " + name + " should be deprecated", isDeprecated(method)); } for (String name : deprecatedBuilderSetterNames) { Method method = deprecatedFieldsBuilder.getMethod(name, int.class); - assertTrue("Method " + name + " should be deprecated", - isDeprecated(method)); + assertTrue("Method " + name + " should be deprecated", isDeprecated(method)); } } - + + public void testDeprecatedFieldInOneof() throws Exception { + Class oneofCase = TestDeprecatedFields.OneofFieldsCase.class; + String name = "DEPRECATED_INT32_IN_ONEOF"; + java.lang.reflect.Field enumValue = oneofCase.getField(name); + assertTrue("Enum value " + name + " should be deprecated.", isDeprecated(enumValue)); + } + private boolean isDeprecated(AnnotatedElement annotated) { return annotated.isAnnotationPresent(Deprecated.class); } 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 b60cd6208859d..74d42c67022db 100644 --- a/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java +++ b/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java @@ -30,6 +30,11 @@ package com.google.protobuf; +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +import protobuf_unittest.NestedExtension; +import protobuf_unittest.NonNestedExtension; import com.google.protobuf.DescriptorProtos.DescriptorProto; import com.google.protobuf.DescriptorProtos.EnumDescriptorProto; import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto; @@ -79,8 +84,7 @@ public class DescriptorsTest extends TestCase { private static final Object STATIC_INIT_TEST = FieldDescriptor.Type.BOOL; public void testFieldTypeEnumMapping() throws Exception { - assertEquals(FieldDescriptor.Type.values().length, - FieldDescriptorProto.Type.values().length); + assertEquals(FieldDescriptor.Type.values().length, FieldDescriptorProto.Type.values().length); for (FieldDescriptor.Type type : FieldDescriptor.Type.values()) { FieldDescriptorProto.Type protoType = type.toProto(); assertEquals("TYPE_" + type.name(), protoType.name()); @@ -95,11 +99,9 @@ public void testFileDescriptor() throws Exception { assertEquals("protobuf_unittest", file.getPackage()); assertEquals("UnittestProto", file.getOptions().getJavaOuterClassname()); - assertEquals("google/protobuf/unittest.proto", - file.toProto().getName()); + assertEquals("google/protobuf/unittest.proto", file.toProto().getName()); - assertEquals(Arrays.asList(UnittestImport.getDescriptor()), - file.getDependencies()); + assertEquals(Arrays.asList(UnittestImport.getDescriptor()), file.getDependencies()); Descriptor messageType = TestAllTypes.getDescriptor(); assertEquals(messageType, file.getMessageTypes().get(0)); @@ -115,9 +117,9 @@ public void testFileDescriptor() throws Exception { assertEquals(enumType, file.findEnumTypeByName("ForeignEnum")); assertNull(file.findEnumTypeByName("NoSuchType")); assertNull(file.findEnumTypeByName("protobuf_unittest.ForeignEnum")); - assertEquals(Arrays.asList(ImportEnum.getDescriptor(), - ImportEnumForMap.getDescriptor()), - UnittestImport.getDescriptor().getEnumTypes()); + assertEquals( + Arrays.asList(ImportEnum.getDescriptor(), ImportEnumForMap.getDescriptor()), + UnittestImport.getDescriptor().getEnumTypes()); for (int i = 0; i < file.getEnumTypes().size(); i++) { assertEquals(i, file.getEnumTypes().get(i).getIndex()); } @@ -127,22 +129,17 @@ public void testFileDescriptor() throws Exception { assertEquals(service, file.findServiceByName("TestService")); assertNull(file.findServiceByName("NoSuchType")); assertNull(file.findServiceByName("protobuf_unittest.TestService")); - assertEquals(Collections.emptyList(), - UnittestImport.getDescriptor().getServices()); + assertEquals(Collections.emptyList(), UnittestImport.getDescriptor().getServices()); for (int i = 0; i < file.getServices().size(); i++) { assertEquals(i, file.getServices().get(i).getIndex()); } - FieldDescriptor extension = - UnittestProto.optionalInt32Extension.getDescriptor(); + FieldDescriptor extension = UnittestProto.optionalInt32Extension.getDescriptor(); assertEquals(extension, file.getExtensions().get(0)); - assertEquals(extension, - file.findExtensionByName("optional_int32_extension")); + assertEquals(extension, file.findExtensionByName("optional_int32_extension")); assertNull(file.findExtensionByName("no_such_ext")); - assertNull(file.findExtensionByName( - "protobuf_unittest.optional_int32_extension")); - assertEquals(Collections.emptyList(), - UnittestImport.getDescriptor().getExtensions()); + assertNull(file.findExtensionByName("protobuf_unittest.optional_int32_extension")); + assertEquals(Collections.emptyList(), UnittestImport.getDescriptor().getExtensions()); for (int i = 0; i < file.getExtensions().size(); i++) { assertEquals(i, file.getExtensions().get(i).getIndex()); } @@ -156,13 +153,11 @@ public void testDescriptor() throws Exception { assertEquals("protobuf_unittest.TestAllTypes", messageType.getFullName()); assertEquals(UnittestProto.getDescriptor(), messageType.getFile()); assertNull(messageType.getContainingType()); - assertEquals(DescriptorProtos.MessageOptions.getDefaultInstance(), - messageType.getOptions()); + assertEquals(DescriptorProtos.MessageOptions.getDefaultInstance(), messageType.getOptions()); assertEquals("TestAllTypes", messageType.toProto().getName()); assertEquals("NestedMessage", nestedType.getName()); - assertEquals("protobuf_unittest.TestAllTypes.NestedMessage", - nestedType.getFullName()); + assertEquals("protobuf_unittest.TestAllTypes.NestedMessage", nestedType.getFullName()); assertEquals(UnittestProto.getDescriptor(), nestedType.getFile()); assertEquals(messageType, nestedType.getContainingType()); @@ -194,36 +189,28 @@ public void testDescriptor() throws Exception { public void testFieldDescriptor() throws Exception { Descriptor messageType = TestAllTypes.getDescriptor(); - FieldDescriptor primitiveField = - messageType.findFieldByName("optional_int32"); - FieldDescriptor enumField = - messageType.findFieldByName("optional_nested_enum"); - FieldDescriptor messageField = - messageType.findFieldByName("optional_foreign_message"); - FieldDescriptor cordField = - messageType.findFieldByName("optional_cord"); - FieldDescriptor extension = - UnittestProto.optionalInt32Extension.getDescriptor(); + FieldDescriptor primitiveField = messageType.findFieldByName("optional_int32"); + FieldDescriptor enumField = messageType.findFieldByName("optional_nested_enum"); + FieldDescriptor messageField = messageType.findFieldByName("optional_foreign_message"); + FieldDescriptor cordField = messageType.findFieldByName("optional_cord"); + FieldDescriptor extension = UnittestProto.optionalInt32Extension.getDescriptor(); FieldDescriptor nestedExtension = TestRequired.single.getDescriptor(); assertEquals("optional_int32", primitiveField.getName()); - assertEquals("protobuf_unittest.TestAllTypes.optional_int32", - primitiveField.getFullName()); + assertEquals("protobuf_unittest.TestAllTypes.optional_int32", primitiveField.getFullName()); assertEquals(1, primitiveField.getNumber()); assertEquals(messageType, primitiveField.getContainingType()); assertEquals(UnittestProto.getDescriptor(), primitiveField.getFile()); assertEquals(FieldDescriptor.Type.INT32, primitiveField.getType()); assertEquals(FieldDescriptor.JavaType.INT, primitiveField.getJavaType()); - assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(), - primitiveField.getOptions()); + assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(), primitiveField.getOptions()); assertFalse(primitiveField.isExtension()); assertEquals("optional_int32", primitiveField.toProto().getName()); assertEquals("optional_nested_enum", enumField.getName()); assertEquals(FieldDescriptor.Type.ENUM, enumField.getType()); assertEquals(FieldDescriptor.JavaType.ENUM, enumField.getJavaType()); - assertEquals(TestAllTypes.NestedEnum.getDescriptor(), - enumField.getEnumType()); + assertEquals(TestAllTypes.NestedEnum.getDescriptor(), enumField.getEnumType()); assertEquals("optional_foreign_message", messageField.getName()); assertEquals(FieldDescriptor.Type.MESSAGE, messageField.getType()); @@ -233,38 +220,29 @@ public void testFieldDescriptor() throws Exception { assertEquals("optional_cord", cordField.getName()); assertEquals(FieldDescriptor.Type.STRING, cordField.getType()); assertEquals(FieldDescriptor.JavaType.STRING, cordField.getJavaType()); - assertEquals(DescriptorProtos.FieldOptions.CType.CORD, - cordField.getOptions().getCtype()); + assertEquals(DescriptorProtos.FieldOptions.CType.CORD, cordField.getOptions().getCtype()); assertEquals("optional_int32_extension", extension.getName()); - assertEquals("protobuf_unittest.optional_int32_extension", - extension.getFullName()); + assertEquals("protobuf_unittest.optional_int32_extension", extension.getFullName()); assertEquals(1, extension.getNumber()); - assertEquals(TestAllExtensions.getDescriptor(), - extension.getContainingType()); + assertEquals(TestAllExtensions.getDescriptor(), extension.getContainingType()); assertEquals(UnittestProto.getDescriptor(), extension.getFile()); assertEquals(FieldDescriptor.Type.INT32, extension.getType()); assertEquals(FieldDescriptor.JavaType.INT, extension.getJavaType()); - assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(), - extension.getOptions()); + assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(), extension.getOptions()); assertTrue(extension.isExtension()); assertEquals(null, extension.getExtensionScope()); assertEquals("optional_int32_extension", extension.toProto().getName()); assertEquals("single", nestedExtension.getName()); - assertEquals("protobuf_unittest.TestRequired.single", - nestedExtension.getFullName()); - assertEquals(TestRequired.getDescriptor(), - nestedExtension.getExtensionScope()); + assertEquals("protobuf_unittest.TestRequired.single", nestedExtension.getFullName()); + assertEquals(TestRequired.getDescriptor(), nestedExtension.getExtensionScope()); } public void testFieldDescriptorLabel() throws Exception { - FieldDescriptor requiredField = - TestRequired.getDescriptor().findFieldByName("a"); - FieldDescriptor optionalField = - TestAllTypes.getDescriptor().findFieldByName("optional_int32"); - FieldDescriptor repeatedField = - TestAllTypes.getDescriptor().findFieldByName("repeated_int32"); + FieldDescriptor requiredField = TestRequired.getDescriptor().findFieldByName("a"); + FieldDescriptor optionalField = TestAllTypes.getDescriptor().findFieldByName("optional_int32"); + FieldDescriptor repeatedField = TestAllTypes.getDescriptor().findFieldByName("repeated_int32"); assertTrue(requiredField.isRequired()); assertFalse(requiredField.isRepeated()); @@ -273,7 +251,7 @@ public void testFieldDescriptorLabel() throws Exception { assertFalse(repeatedField.isRequired()); assertTrue(repeatedField.isRepeated()); } - + public void testFieldDescriptorJsonName() throws Exception { FieldDescriptor requiredField = TestRequired.getDescriptor().findFieldByName("a"); FieldDescriptor optionalField = TestAllTypes.getDescriptor().findFieldByName("optional_int32"); @@ -292,9 +270,8 @@ public void testFieldDescriptorDefault() throws Exception { d = TestExtremeDefaultValues.getDescriptor(); assertEquals( - ByteString.copyFrom( - "\0\001\007\b\f\n\r\t\013\\\'\"\u00fe".getBytes(Internal.ISO_8859_1)), - d.findFieldByName("escaped_bytes").getDefaultValue()); + ByteString.copyFrom("\0\001\007\b\f\n\r\t\013\\\'\"\u00fe".getBytes(Internal.ISO_8859_1)), + d.findFieldByName("escaped_bytes").getDefaultValue()); assertEquals(-1, d.findFieldByName("large_uint32").getDefaultValue()); assertEquals(-1L, d.findFieldByName("large_uint64").getDefaultValue()); } @@ -307,12 +284,10 @@ public void testEnumDescriptor() throws Exception { assertEquals("protobuf_unittest.ForeignEnum", enumType.getFullName()); assertEquals(UnittestProto.getDescriptor(), enumType.getFile()); assertNull(enumType.getContainingType()); - assertEquals(DescriptorProtos.EnumOptions.getDefaultInstance(), - enumType.getOptions()); + assertEquals(DescriptorProtos.EnumOptions.getDefaultInstance(), enumType.getOptions()); assertEquals("NestedEnum", nestedType.getName()); - assertEquals("protobuf_unittest.TestAllTypes.NestedEnum", - nestedType.getFullName()); + assertEquals("protobuf_unittest.TestAllTypes.NestedEnum", nestedType.getFullName()); assertEquals(UnittestProto.getDescriptor(), nestedType.getFile()); assertEquals(TestAllTypes.getDescriptor(), nestedType.getContainingType()); @@ -339,20 +314,17 @@ public void testServiceDescriptor() throws Exception { MethodDescriptor fooMethod = service.getMethods().get(0); assertEquals("Foo", fooMethod.getName()); - assertEquals(UnittestProto.FooRequest.getDescriptor(), - fooMethod.getInputType()); - assertEquals(UnittestProto.FooResponse.getDescriptor(), - fooMethod.getOutputType()); + assertEquals(UnittestProto.FooRequest.getDescriptor(), fooMethod.getInputType()); + assertEquals(UnittestProto.FooResponse.getDescriptor(), fooMethod.getOutputType()); assertEquals(fooMethod, service.findMethodByName("Foo")); MethodDescriptor barMethod = service.getMethods().get(1); assertEquals("Bar", barMethod.getName()); - assertEquals(UnittestProto.BarRequest.getDescriptor(), - barMethod.getInputType()); - assertEquals(UnittestProto.BarResponse.getDescriptor(), - barMethod.getOutputType()); + assertEquals(UnittestProto.BarRequest.getDescriptor(), barMethod.getInputType()); + assertEquals(UnittestProto.BarResponse.getDescriptor(), barMethod.getOutputType()); assertEquals(barMethod, service.findMethodByName("Bar")); + assertNull(service.findMethodByName("NoSuchMethod")); for (int i = 0; i < service.getMethods().size(); i++) { @@ -367,58 +339,53 @@ public void testCustomOptions() throws Exception { // dependencies are also properly initialized. Descriptor descriptor = TestCustomOptions.TestMessageWithCustomOptionsContainer.getDescriptor() - .findFieldByName("field").getMessageType(); + .findFieldByName("field") + .getMessageType(); - assertTrue( - descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1)); - assertEquals(Integer.valueOf(-56), - descriptor.getOptions().getExtension(UnittestCustomOptions.messageOpt1)); + assertTrue(descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1)); + assertEquals( + Integer.valueOf(-56), + descriptor.getOptions().getExtension(UnittestCustomOptions.messageOpt1)); FieldDescriptor field = descriptor.findFieldByName("field1"); assertNotNull(field); - assertTrue( - field.getOptions().hasExtension(UnittestCustomOptions.fieldOpt1)); - assertEquals(Long.valueOf(8765432109L), - field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1)); + assertTrue(field.getOptions().hasExtension(UnittestCustomOptions.fieldOpt1)); + assertEquals( + Long.valueOf(8765432109L), + field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1)); OneofDescriptor oneof = descriptor.getOneofs().get(0); assertNotNull(oneof); - assertTrue( - oneof.getOptions().hasExtension(UnittestCustomOptions.oneofOpt1)); - assertEquals(Integer.valueOf(-99), - oneof.getOptions().getExtension(UnittestCustomOptions.oneofOpt1)); + assertTrue(oneof.getOptions().hasExtension(UnittestCustomOptions.oneofOpt1)); + assertEquals( + Integer.valueOf(-99), oneof.getOptions().getExtension(UnittestCustomOptions.oneofOpt1)); EnumDescriptor enumType = - UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor(); + UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor(); - assertTrue( - enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1)); - assertEquals(Integer.valueOf(-789), - enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1)); + assertTrue(enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1)); + assertEquals( + Integer.valueOf(-789), enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1)); - ServiceDescriptor service = - UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor(); + ServiceDescriptor service = UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor(); - assertTrue( - service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1)); - assertEquals(Long.valueOf(-9876543210L), - service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1)); + assertTrue(service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1)); + assertEquals( + Long.valueOf(-9876543210L), + service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1)); MethodDescriptor method = service.findMethodByName("Foo"); assertNotNull(method); - assertTrue( - method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1)); - assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2, - method.getOptions().getExtension(UnittestCustomOptions.methodOpt1)); + assertTrue(method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1)); + assertEquals( + UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2, + method.getOptions().getExtension(UnittestCustomOptions.methodOpt1)); } - /** - * Test that the FieldDescriptor.Type enum is the same as the - * WireFormat.FieldType enum. - */ + /** Test that the FieldDescriptor.Type enum is the same as the WireFormat.FieldType enum. */ public void testFieldTypeTablesMatch() throws Exception { FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values(); WireFormat.FieldType[] values2 = WireFormat.FieldType.values(); @@ -430,10 +397,7 @@ public void testFieldTypeTablesMatch() throws Exception { } } - /** - * Test that the FieldDescriptor.JavaType enum is the same as the - * WireFormat.JavaType enum. - */ + /** Test that the FieldDescriptor.JavaType enum is the same as the WireFormat.JavaType enum. */ public void testJavaTypeTablesMatch() throws Exception { FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values(); WireFormat.JavaType[] values2 = WireFormat.JavaType.values(); @@ -448,31 +412,29 @@ public void testJavaTypeTablesMatch() throws Exception { public void testEnormousDescriptor() throws Exception { // The descriptor for this file is larger than 64k, yet it did not cause // a compiler error due to an over-long string literal. - assertTrue( - UnittestEnormousDescriptor.getDescriptor() - .toProto().getSerializedSize() > 65536); + assertTrue(UnittestEnormousDescriptor.getDescriptor().toProto().getSerializedSize() > 65536); } - /** - * Tests that the DescriptorValidationException works as intended. - */ + /** Tests that the DescriptorValidationException works as intended. */ public void testDescriptorValidatorException() throws Exception { - FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder() - .setName("foo.proto") - .addMessageType(DescriptorProto.newBuilder() - .setName("Foo") - .addField(FieldDescriptorProto.newBuilder() - .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) - .setType(FieldDescriptorProto.Type.TYPE_INT32) - .setName("foo") - .setNumber(1) - .setDefaultValue("invalid") - .build()) - .build()) - .build(); + FileDescriptorProto fileDescriptorProto = + FileDescriptorProto.newBuilder() + .setName("foo.proto") + .addMessageType( + DescriptorProto.newBuilder() + .setName("Foo") + .addField( + FieldDescriptorProto.newBuilder() + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setType(FieldDescriptorProto.Type.TYPE_INT32) + .setName("foo") + .setNumber(1) + .setDefaultValue("invalid") + .build()) + .build()) + .build(); try { - Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, - new FileDescriptor[0]); + Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]); fail("DescriptorValidationException expected"); } catch (DescriptorValidationException e) { // Expected; check that the error message contains some useful hints @@ -485,35 +447,39 @@ public void testDescriptorValidatorException() throws Exception { } /** - * Tests the translate/crosslink for an example where a message field's name - * and type name are the same. + * Tests the translate/crosslink for an example where a message field's name and type name are the + * same. */ public void testDescriptorComplexCrosslink() throws Exception { - FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder() - .setName("foo.proto") - .addMessageType(DescriptorProto.newBuilder() - .setName("Foo") - .addField(FieldDescriptorProto.newBuilder() - .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) - .setType(FieldDescriptorProto.Type.TYPE_INT32) - .setName("foo") - .setNumber(1) - .build()) - .build()) - .addMessageType(DescriptorProto.newBuilder() - .setName("Bar") - .addField(FieldDescriptorProto.newBuilder() - .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) - .setTypeName("Foo") - .setName("Foo") - .setNumber(1) - .build()) - .build()) - .build(); + FileDescriptorProto fileDescriptorProto = + FileDescriptorProto.newBuilder() + .setName("foo.proto") + .addMessageType( + DescriptorProto.newBuilder() + .setName("Foo") + .addField( + FieldDescriptorProto.newBuilder() + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setType(FieldDescriptorProto.Type.TYPE_INT32) + .setName("foo") + .setNumber(1) + .build()) + .build()) + .addMessageType( + DescriptorProto.newBuilder() + .setName("Bar") + .addField( + FieldDescriptorProto.newBuilder() + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setTypeName("Foo") + .setName("Foo") + .setNumber(1) + .build()) + .build()) + .build(); // translate and crosslink FileDescriptor file = - Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, - new FileDescriptor[0]); + Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]); // verify resulting descriptors assertNotNull(file); List msglist = file.getMessageTypes(); @@ -535,62 +501,57 @@ public void testDescriptorComplexCrosslink() throws Exception { } public void testDependencyOrder() throws Exception { - FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() - .setName("foo.proto").build(); - FileDescriptorProto barProto = FileDescriptorProto.newBuilder() - .setName("bar.proto") - .addDependency("foo.proto") - .build(); - FileDescriptorProto bazProto = FileDescriptorProto.newBuilder() - .setName("baz.proto") - .addDependency("foo.proto") - .addDependency("bar.proto") - .addPublicDependency(0) - .addPublicDependency(1) - .build(); - FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, - new FileDescriptor[0]); - FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(barProto, - new FileDescriptor[] {fooFile}); + FileDescriptorProto fooProto = FileDescriptorProto.newBuilder().setName("foo.proto").build(); + FileDescriptorProto barProto = + FileDescriptorProto.newBuilder().setName("bar.proto").addDependency("foo.proto").build(); + FileDescriptorProto bazProto = + FileDescriptorProto.newBuilder() + .setName("baz.proto") + .addDependency("foo.proto") + .addDependency("bar.proto") + .addPublicDependency(0) + .addPublicDependency(1) + .build(); + FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]); + FileDescriptor barFile = + Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[] {fooFile}); // Items in the FileDescriptor array can be in any order. - Descriptors.FileDescriptor.buildFrom(bazProto, - new FileDescriptor[] {fooFile, barFile}); - Descriptors.FileDescriptor.buildFrom(bazProto, - new FileDescriptor[] {barFile, fooFile}); + Descriptors.FileDescriptor.buildFrom(bazProto, new FileDescriptor[] {fooFile, barFile}); + Descriptors.FileDescriptor.buildFrom(bazProto, new FileDescriptor[] {barFile, fooFile}); } public void testInvalidPublicDependency() throws Exception { - FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() - .setName("foo.proto").build(); - FileDescriptorProto barProto = FileDescriptorProto.newBuilder() - .setName("boo.proto") - .addDependency("foo.proto") - .addPublicDependency(1) // Error, should be 0. - .build(); - FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, - new FileDescriptor[0]); + FileDescriptorProto fooProto = FileDescriptorProto.newBuilder().setName("foo.proto").build(); + FileDescriptorProto barProto = + FileDescriptorProto.newBuilder() + .setName("boo.proto") + .addDependency("foo.proto") + .addPublicDependency(1) // Error, should be 0. + .build(); + FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]); try { - Descriptors.FileDescriptor.buildFrom(barProto, - new FileDescriptor[] {fooFile}); + Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[] {fooFile}); fail("DescriptorValidationException expected"); } catch (DescriptorValidationException e) { - assertTrue( - e.getMessage().indexOf("Invalid public dependency index.") != -1); + assertTrue(e.getMessage().indexOf("Invalid public dependency index.") != -1); } } public void testUnknownFieldsDenied() throws Exception { - FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() - .setName("foo.proto") - .addMessageType(DescriptorProto.newBuilder() - .setName("Foo") - .addField(FieldDescriptorProto.newBuilder() - .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) - .setTypeName("Bar") - .setName("bar") - .setNumber(1))) - .build(); + FileDescriptorProto fooProto = + FileDescriptorProto.newBuilder() + .setName("foo.proto") + .addMessageType( + DescriptorProto.newBuilder() + .setName("Foo") + .addField( + FieldDescriptorProto.newBuilder() + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setTypeName("Bar") + .setName("bar") + .setNumber(1))) + .build(); try { Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]); @@ -602,48 +563,54 @@ public void testUnknownFieldsDenied() throws Exception { } public void testUnknownFieldsAllowed() throws Exception { - FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() - .setName("foo.proto") - .addDependency("bar.proto") - .addMessageType(DescriptorProto.newBuilder() - .setName("Foo") - .addField(FieldDescriptorProto.newBuilder() - .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) - .setTypeName("Bar") - .setName("bar") - .setNumber(1))) - .build(); + FileDescriptorProto fooProto = + FileDescriptorProto.newBuilder() + .setName("foo.proto") + .addDependency("bar.proto") + .addMessageType( + DescriptorProto.newBuilder() + .setName("Foo") + .addField( + FieldDescriptorProto.newBuilder() + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setTypeName("Bar") + .setName("bar") + .setNumber(1))) + .build(); Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0], true); } public void testHiddenDependency() throws Exception { - FileDescriptorProto barProto = FileDescriptorProto.newBuilder() - .setName("bar.proto") - .addMessageType(DescriptorProto.newBuilder().setName("Bar")) - .build(); - FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder() - .setName("forward.proto") - .addDependency("bar.proto") - .build(); - FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() - .setName("foo.proto") - .addDependency("forward.proto") - .addMessageType(DescriptorProto.newBuilder() - .setName("Foo") - .addField(FieldDescriptorProto.newBuilder() - .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) - .setTypeName("Bar") - .setName("bar") - .setNumber(1))) - .build(); - FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom( - barProto, new FileDescriptor[0]); - FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom( - forwardProto, new FileDescriptor[] {barFile}); + FileDescriptorProto barProto = + FileDescriptorProto.newBuilder() + .setName("bar.proto") + .addMessageType(DescriptorProto.newBuilder().setName("Bar")) + .build(); + FileDescriptorProto forwardProto = + FileDescriptorProto.newBuilder() + .setName("forward.proto") + .addDependency("bar.proto") + .build(); + FileDescriptorProto fooProto = + FileDescriptorProto.newBuilder() + .setName("foo.proto") + .addDependency("forward.proto") + .addMessageType( + DescriptorProto.newBuilder() + .setName("Foo") + .addField( + FieldDescriptorProto.newBuilder() + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setTypeName("Bar") + .setName("bar") + .setNumber(1))) + .build(); + FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[0]); + FileDescriptor forwardFile = + Descriptors.FileDescriptor.buildFrom(forwardProto, new FileDescriptor[] {barFile}); try { - Descriptors.FileDescriptor.buildFrom( - fooProto, new FileDescriptor[] {forwardFile}); + Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[] {forwardFile}); fail("DescriptorValidationException expected"); } catch (DescriptorValidationException e) { assertTrue(e.getMessage().indexOf("Bar") != -1); @@ -652,65 +619,67 @@ public void testHiddenDependency() throws Exception { } public void testPublicDependency() throws Exception { - FileDescriptorProto barProto = FileDescriptorProto.newBuilder() - .setName("bar.proto") - .addMessageType(DescriptorProto.newBuilder().setName("Bar")) - .build(); - FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder() - .setName("forward.proto") - .addDependency("bar.proto") - .addPublicDependency(0) - .build(); - FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() - .setName("foo.proto") - .addDependency("forward.proto") - .addMessageType(DescriptorProto.newBuilder() - .setName("Foo") - .addField(FieldDescriptorProto.newBuilder() - .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) - .setTypeName("Bar") - .setName("bar") - .setNumber(1))) - .build(); - FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom( - barProto, new FileDescriptor[0]); - FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom( - forwardProto, new FileDescriptor[]{barFile}); - Descriptors.FileDescriptor.buildFrom( - fooProto, new FileDescriptor[] {forwardFile}); + FileDescriptorProto barProto = + FileDescriptorProto.newBuilder() + .setName("bar.proto") + .addMessageType(DescriptorProto.newBuilder().setName("Bar")) + .build(); + FileDescriptorProto forwardProto = + FileDescriptorProto.newBuilder() + .setName("forward.proto") + .addDependency("bar.proto") + .addPublicDependency(0) + .build(); + FileDescriptorProto fooProto = + FileDescriptorProto.newBuilder() + .setName("foo.proto") + .addDependency("forward.proto") + .addMessageType( + DescriptorProto.newBuilder() + .setName("Foo") + .addField( + FieldDescriptorProto.newBuilder() + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setTypeName("Bar") + .setName("bar") + .setNumber(1))) + .build(); + FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[0]); + FileDescriptor forwardFile = + Descriptors.FileDescriptor.buildFrom(forwardProto, new FileDescriptor[] {barFile}); + Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[] {forwardFile}); } - /** - * Tests the translate/crosslink for an example with a more complex namespace - * referencing. - */ + /** Tests the translate/crosslink for an example with a more complex namespace referencing. */ public void testComplexNamespacePublicDependency() throws Exception { - FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() - .setName("bar.proto") - .setPackage("a.b.c.d.bar.shared") - .addEnumType(EnumDescriptorProto.newBuilder() - .setName("MyEnum") - .addValue(EnumValueDescriptorProto.newBuilder() - .setName("BLAH") - .setNumber(1))) - .build(); - FileDescriptorProto barProto = FileDescriptorProto.newBuilder() - .setName("foo.proto") - .addDependency("bar.proto") - .setPackage("a.b.c.d.foo.shared") - .addMessageType(DescriptorProto.newBuilder() - .setName("MyMessage") - .addField(FieldDescriptorProto.newBuilder() - .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED) - .setTypeName("bar.shared.MyEnum") - .setName("MyField") - .setNumber(1))) - .build(); + FileDescriptorProto fooProto = + FileDescriptorProto.newBuilder() + .setName("bar.proto") + .setPackage("a.b.c.d.bar.shared") + .addEnumType( + EnumDescriptorProto.newBuilder() + .setName("MyEnum") + .addValue(EnumValueDescriptorProto.newBuilder().setName("BLAH").setNumber(1))) + .build(); + FileDescriptorProto barProto = + FileDescriptorProto.newBuilder() + .setName("foo.proto") + .addDependency("bar.proto") + .setPackage("a.b.c.d.foo.shared") + .addMessageType( + DescriptorProto.newBuilder() + .setName("MyMessage") + .addField( + FieldDescriptorProto.newBuilder() + .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED) + .setTypeName("bar.shared.MyEnum") + .setName("MyField") + .setNumber(1))) + .build(); // translate and crosslink - FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom( - fooProto, new FileDescriptor[0]); - FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom( - barProto, new FileDescriptor[]{fooFile}); + FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]); + FileDescriptor barFile = + Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[] {fooFile}); // verify resulting descriptors assertNotNull(barFile); List msglist = barFile.getMessageTypes(); @@ -726,15 +695,13 @@ public void testComplexNamespacePublicDependency() throws Exception { assertTrue(field.getType() == FieldDescriptor.Type.ENUM); assertTrue(field.getEnumType().getName().equals("MyEnum")); assertTrue(field.getEnumType().getFile().getName().equals("bar.proto")); - assertTrue(field.getEnumType().getFile().getPackage().equals( - "a.b.c.d.bar.shared")); + assertTrue(field.getEnumType().getFile().getPackage().equals("a.b.c.d.bar.shared")); } } public void testOneofDescriptor() throws Exception { Descriptor messageType = TestAllTypes.getDescriptor(); - FieldDescriptor field = - messageType.findFieldByName("oneof_nested_message"); + FieldDescriptor field = messageType.findFieldByName("oneof_nested_message"); OneofDescriptor oneofDescriptor = field.getContainingOneof(); assertNotNull(oneofDescriptor); assertSame(oneofDescriptor, messageType.getOneofs().get(0)); @@ -774,36 +741,38 @@ public void testReservedFields() { } public void testToString() { - assertEquals("protobuf_unittest.TestAllTypes.optional_uint64", - UnittestProto.TestAllTypes.getDescriptor().findFieldByNumber( - UnittestProto.TestAllTypes.OPTIONAL_UINT64_FIELD_NUMBER).toString()); + assertEquals( + "protobuf_unittest.TestAllTypes.optional_uint64", + UnittestProto.TestAllTypes.getDescriptor() + .findFieldByNumber(UnittestProto.TestAllTypes.OPTIONAL_UINT64_FIELD_NUMBER) + .toString()); } public void testPackedEnumField() throws Exception { - FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder() - .setName("foo.proto") - .addEnumType(EnumDescriptorProto.newBuilder() - .setName("Enum") - .addValue(EnumValueDescriptorProto.newBuilder() - .setName("FOO") - .setNumber(1) - .build()) - .build()) - .addMessageType(DescriptorProto.newBuilder() - .setName("Message") - .addField(FieldDescriptorProto.newBuilder() - .setName("foo") - .setTypeName("Enum") - .setNumber(1) - .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED) - .setOptions(DescriptorProtos.FieldOptions.newBuilder() - .setPacked(true) - .build()) - .build()) - .build()) - .build(); - Descriptors.FileDescriptor.buildFrom( - fileDescriptorProto, new FileDescriptor[0]); + FileDescriptorProto fileDescriptorProto = + FileDescriptorProto.newBuilder() + .setName("foo.proto") + .addEnumType( + EnumDescriptorProto.newBuilder() + .setName("Enum") + .addValue( + EnumValueDescriptorProto.newBuilder().setName("FOO").setNumber(1).build()) + .build()) + .addMessageType( + DescriptorProto.newBuilder() + .setName("Message") + .addField( + FieldDescriptorProto.newBuilder() + .setName("foo") + .setTypeName("Enum") + .setNumber(1) + .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED) + .setOptions( + DescriptorProtos.FieldOptions.newBuilder().setPacked(true).build()) + .build()) + .build()) + .build(); + Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]); } public void testFieldJsonName() throws Exception { @@ -816,4 +785,23 @@ public void testFieldJsonName() throws Exception { assertEquals("FIELDNAME5", d.getFields().get(4).getJsonName()); assertEquals("@type", d.getFields().get(5).getJsonName()); } + + public void testExtensionRenamesKeywords() { + assertTrue(NonNestedExtension.if_ instanceof GeneratedMessage.GeneratedExtension); + assertTrue( + NestedExtension.MyNestedExtension.default_ + instanceof GeneratedMessage.GeneratedExtension); + + NonNestedExtension.MessageToBeExtended msg = + NonNestedExtension.MessageToBeExtended.newBuilder() + .setExtension(NonNestedExtension.if_, "!fi") + .build(); + assertEquals("!fi", msg.getExtension(NonNestedExtension.if_)); + + msg = + NonNestedExtension.MessageToBeExtended.newBuilder() + .setExtension(NestedExtension.MyNestedExtension.default_, 8) + .build(); + assertEquals(8, msg.getExtension(NestedExtension.MyNestedExtension.default_).intValue()); + } } diff --git a/java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java b/java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java index 0f09a51b2ea0b..01a96ba550e06 100644 --- a/java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java +++ b/java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java @@ -43,15 +43,13 @@ public class DiscardUnknownFieldsTest { @Test public void testProto2() throws Exception { + testProto2Message(UnittestProto.TestEmptyMessage.getDefaultInstance()); + testProto2Message(UnittestProto.TestEmptyMessageWithExtensions.getDefaultInstance()); testProto2Message( - UnittestProto.TestEmptyMessage.getDefaultInstance()); + DynamicMessage.getDefaultInstance(UnittestProto.TestEmptyMessage.getDescriptor())); testProto2Message( - UnittestProto.TestEmptyMessageWithExtensions.getDefaultInstance()); - testProto2Message( - DynamicMessage.getDefaultInstance(UnittestProto.TestEmptyMessage.getDescriptor())); - testProto2Message( - DynamicMessage.getDefaultInstance( - UnittestProto.TestEmptyMessageWithExtensions.getDescriptor())); + DynamicMessage.getDefaultInstance( + UnittestProto.TestEmptyMessageWithExtensions.getDescriptor())); } @Test @@ -62,22 +60,17 @@ public void testProto3() throws Exception { } private static void testProto2Message(Message message) throws Exception { - assertUnknownFieldsDefaultPreserved(message); + assertUnknownFieldsPreserved(message); assertUnknownFieldsExplicitlyDiscarded(message); assertReuseCodedInputStreamPreserve(message); assertUnknownFieldsInUnknownFieldSetArePreserve(message); } private static void testProto3Message(Message message) throws Exception { - CodedInputStream.setProto3KeepUnknownsByDefaultForTest(); - assertUnknownFieldsDefaultPreserved(message); + assertUnknownFieldsPreserved(message); assertUnknownFieldsExplicitlyDiscarded(message); assertReuseCodedInputStreamPreserve(message); assertUnknownFieldsInUnknownFieldSetArePreserve(message); - CodedInputStream.setProto3DiscardUnknownsByDefaultForTest(); - assertUnknownFieldsDefaultDiscarded(message); - assertUnknownFieldsExplicitlyDiscarded(message); - assertUnknownFieldsInUnknownFieldSetAreDiscarded(message); } private static void assertReuseCodedInputStreamPreserve(Message message) throws Exception { @@ -86,18 +79,16 @@ private static void assertReuseCodedInputStreamPreserve(Message message) throws payload.copyTo(copied, 0); payload.copyTo(copied, messageSize); CodedInputStream input = CodedInputStream.newInstance(copied); - { - // Use DiscardUnknownFieldsParser to parse the first payload. - int oldLimit = input.pushLimit(messageSize); - Message parsed = DiscardUnknownFieldsParser.wrap(message.getParserForType()).parseFrom(input); - assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize()); - input.popLimit(oldLimit); - } - { - // Use the normal parser to parse the remaining payload should have unknown fields preserved. - Message parsed = message.getParserForType().parseFrom(input); - assertEquals(message.getClass().getName(), payload, parsed.toByteString()); - } + + // Use DiscardUnknownFieldsParser to parse the first payload. + int oldLimit = input.pushLimit(messageSize); + Message parsed = DiscardUnknownFieldsParser.wrap(message.getParserForType()).parseFrom(input); + assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize()); + input.popLimit(oldLimit); + + // Use the normal parser to parse the remaining payload should have unknown fields preserved. + parsed = message.getParserForType().parseFrom(input); + assertEquals(message.getClass().getName(), payload, parsed.toByteString()); } /** @@ -109,46 +100,18 @@ private static void assertUnknownFieldsInUnknownFieldSetArePreserve(Message mess UnknownFieldSet unknownFields = UnknownFieldSet.newBuilder().mergeFrom(payload).build(); Message built = message.newBuilderForType().setUnknownFields(unknownFields).build(); assertEquals(message.getClass().getName(), payload, built.toByteString()); - - } - /** - * {@link Message.Builder#setUnknownFields(UnknownFieldSet)} and {@link - * Message.Builder#mergeUnknownFields(UnknownFieldSet)} should discard the unknown fields. - */ - private static void assertUnknownFieldsInUnknownFieldSetAreDiscarded(Message message) - throws Exception { - UnknownFieldSet unknownFields = UnknownFieldSet.newBuilder().mergeFrom(payload).build(); - Message built = message.newBuilderForType().setUnknownFields(unknownFields).build(); - assertEquals(message.getClass().getName(), 0, built.getSerializedSize()); - } - - private static void assertUnknownFieldsDefaultPreserved(MessageLite message) throws Exception { - { - MessageLite parsed = message.getParserForType().parseFrom(payload); - assertEquals(message.getClass().getName(), payload, parsed.toByteString()); - } - - { - MessageLite parsed = message.newBuilderForType().mergeFrom(payload).build(); - assertEquals(message.getClass().getName(), payload, parsed.toByteString()); - } } - private static void assertUnknownFieldsDefaultDiscarded(MessageLite message) throws Exception { - { - MessageLite parsed = message.getParserForType().parseFrom(payload); - assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize()); - } + private static void assertUnknownFieldsPreserved(MessageLite message) throws Exception { + MessageLite parsed = message.getParserForType().parseFrom(payload); + assertEquals(message.getClass().getName(), payload, parsed.toByteString()); - { - MessageLite parsed = message.newBuilderForType().mergeFrom(payload).build(); - assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize()); - } + parsed = message.newBuilderForType().mergeFrom(payload).build(); + assertEquals(message.getClass().getName(), payload, parsed.toByteString()); } private static void assertUnknownFieldsExplicitlyDiscarded(Message message) throws Exception { - Message parsed = - DiscardUnknownFieldsParser.wrap(message.getParserForType()).parseFrom(payload); + Message parsed = DiscardUnknownFieldsParser.wrap(message.getParserForType()).parseFrom(payload); assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize()); } diff --git a/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java b/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java index d894279297b03..019b5a14444f5 100644 --- a/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java @@ -32,6 +32,7 @@ import static java.util.Arrays.asList; +import com.google.protobuf.Internal.DoubleList; import java.util.Collections; import java.util.ConcurrentModificationException; import java.util.Iterator; @@ -44,10 +45,8 @@ */ public class DoubleArrayListTest extends TestCase { - private static final DoubleArrayList UNARY_LIST = - newImmutableDoubleArrayList(1); - private static final DoubleArrayList TERTIARY_LIST = - newImmutableDoubleArrayList(1, 2, 3); + private static final DoubleArrayList UNARY_LIST = newImmutableDoubleArrayList(1); + private static final DoubleArrayList TERTIARY_LIST = newImmutableDoubleArrayList(1, 2, 3); private DoubleArrayList list; @@ -77,10 +76,10 @@ public void testModificationWithIteration() { list.addAll(asList(1D, 2D, 3D, 4D)); Iterator iterator = list.iterator(); assertEquals(4, list.size()); - assertEquals(1D, (double) list.get(0)); - assertEquals(1D, (double) iterator.next()); + assertEquals(1D, (double) list.get(0), 0.0); + assertEquals(1D, (double) iterator.next(), 0.0); list.set(0, 1D); - assertEquals(2D, (double) iterator.next()); + assertEquals(2D, (double) iterator.next(), 0.0); list.remove(0); try { @@ -101,9 +100,9 @@ public void testModificationWithIteration() { } public void testGet() { - assertEquals(1D, (double) TERTIARY_LIST.get(0)); - assertEquals(2D, (double) TERTIARY_LIST.get(1)); - assertEquals(3D, (double) TERTIARY_LIST.get(2)); + assertEquals(1D, (double) TERTIARY_LIST.get(0), 0.0); + assertEquals(2D, (double) TERTIARY_LIST.get(1), 0.0); + assertEquals(3D, (double) TERTIARY_LIST.get(2), 0.0); try { TERTIARY_LIST.get(-1); @@ -121,9 +120,9 @@ public void testGet() { } public void testGetDouble() { - assertEquals(1D, TERTIARY_LIST.getDouble(0)); - assertEquals(2D, TERTIARY_LIST.getDouble(1)); - assertEquals(3D, TERTIARY_LIST.getDouble(2)); + assertEquals(1D, TERTIARY_LIST.getDouble(0), 0.0); + assertEquals(2D, TERTIARY_LIST.getDouble(1), 0.0); + assertEquals(3D, TERTIARY_LIST.getDouble(2), 0.0); try { TERTIARY_LIST.get(-1); @@ -140,6 +139,68 @@ public void testGetDouble() { } } + public void testIndexOf_nullElement() { + assertEquals(-1, TERTIARY_LIST.indexOf(null)); + } + + public void testIndexOf_incompatibleElementType() { + assertEquals(-1, TERTIARY_LIST.indexOf(new Object())); + } + + public void testIndexOf_notInList() { + assertEquals(-1, UNARY_LIST.indexOf(2D)); + } + + public void testIndexOf_notInListWithDuplicates() { + DoubleArrayList listWithDupes = newImmutableDoubleArrayList(1D, 1D); + assertEquals(-1, listWithDupes.indexOf(2D)); + } + + public void testIndexOf_inList() { + assertEquals(1, TERTIARY_LIST.indexOf(2D)); + } + + public void testIndexOf_inListWithDuplicates_matchAtHead() { + DoubleArrayList listWithDupes = newImmutableDoubleArrayList(1D, 1D, 2D); + assertEquals(0, listWithDupes.indexOf(1D)); + } + + public void testIndexOf_inListWithDuplicates_matchMidList() { + DoubleArrayList listWithDupes = newImmutableDoubleArrayList(2D, 1D, 1D, 2D); + assertEquals(1, listWithDupes.indexOf(1D)); + } + + public void testContains_nullElement() { + assertEquals(false, TERTIARY_LIST.contains(null)); + } + + public void testContains_incompatibleElementType() { + assertEquals(false, TERTIARY_LIST.contains(new Object())); + } + + public void testContains_notInList() { + assertEquals(false, UNARY_LIST.contains(2D)); + } + + public void testContains_notInListWithDuplicates() { + DoubleArrayList listWithDupes = newImmutableDoubleArrayList(1D, 1D); + assertEquals(false, listWithDupes.contains(2D)); + } + + public void testContains_inList() { + assertEquals(true, TERTIARY_LIST.contains(2D)); + } + + public void testContains_inListWithDuplicates_matchAtHead() { + DoubleArrayList listWithDupes = newImmutableDoubleArrayList(1D, 1D, 2D); + assertEquals(true, listWithDupes.contains(1D)); + } + + public void testContains_inListWithDuplicates_matchMidList() { + DoubleArrayList listWithDupes = newImmutableDoubleArrayList(2D, 1D, 1D, 2D); + assertEquals(true, listWithDupes.contains(1D)); + } + public void testSize() { assertEquals(0, DoubleArrayList.emptyList().size()); assertEquals(1, UNARY_LIST.size()); @@ -162,11 +223,11 @@ public void testSet() { list.addDouble(2); list.addDouble(4); - assertEquals(2D, (double) list.set(0, 3D)); - assertEquals(3D, list.getDouble(0)); + assertEquals(2D, (double) list.set(0, 3D), 0.0); + assertEquals(3D, list.getDouble(0), 0.0); - assertEquals(4D, (double) list.set(1, 0D)); - assertEquals(0D, list.getDouble(1)); + assertEquals(4D, (double) list.set(1, 0D), 0.0); + assertEquals(0D, list.getDouble(1), 0.0); try { list.set(-1, 0D); @@ -187,11 +248,11 @@ public void testSetDouble() { list.addDouble(1); list.addDouble(3); - assertEquals(1D, list.setDouble(0, 0)); - assertEquals(0D, list.getDouble(0)); + assertEquals(1D, list.setDouble(0, 0), 0.0); + assertEquals(0D, list.getDouble(0), 0.0); - assertEquals(3D, list.setDouble(1, 0)); - assertEquals(0D, list.getDouble(1)); + assertEquals(3D, list.setDouble(1, 0), 0.0); + assertEquals(0D, list.getDouble(1), 0.0); try { list.setDouble(-1, 0); @@ -224,9 +285,7 @@ public void testAdd() { for (int i = 0; i < 6; i++) { list.add(Double.valueOf(5 + i)); } - assertEquals( - asList(0D, 1D, 4D, 2D, 3D, 5D, 6D, 7D, 8D, 9D, 10D), - list); + assertEquals(asList(0D, 1D, 4D, 2D, 3D, 5D, 6D, 7D, 8D, 9D, 10D), list); try { list.add(-1, 5D); @@ -256,8 +315,8 @@ public void testAddAll() { assertTrue(list.addAll(Collections.singleton(1D))); assertEquals(1, list.size()); - assertEquals(1D, (double) list.get(0)); - assertEquals(1D, list.getDouble(0)); + assertEquals(1D, (double) list.get(0), 0.0); + assertEquals(1D, list.getDouble(0), 0.0); assertTrue(list.addAll(asList(2D, 3D, 4D, 5D, 6D))); assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D), list); @@ -269,9 +328,18 @@ public void testAddAll() { assertFalse(list.addAll(DoubleArrayList.emptyList())); } + public void testEquals() { + DoubleArrayList list1 = new DoubleArrayList(); + DoubleArrayList list2 = new DoubleArrayList(); + + list1.addDouble(Double.longBitsToDouble(0x7ff0000000000001L)); + list2.addDouble(Double.longBitsToDouble(0x7ff0000000000002L)); + assertEquals(list1, list2); + } + public void testRemove() { list.addAll(TERTIARY_LIST); - assertEquals(1D, (double) list.remove(0)); + assertEquals(1D, (double) list.remove(0), 0.0); assertEquals(asList(2D, 3D), list); assertTrue(list.remove(Double.valueOf(3))); @@ -280,7 +348,7 @@ public void testRemove() { assertFalse(list.remove(Double.valueOf(3))); assertEquals(asList(2D), list); - assertEquals(2D, (double) list.remove(0)); + assertEquals(2D, (double) list.remove(0), 0.0); assertEquals(asList(), list); try { @@ -297,7 +365,30 @@ public void testRemove() { } } - private void assertImmutable(DoubleArrayList list) { + public void testRemoveEnd_listAtCapacity() { + DoubleList toRemove = DoubleArrayList.emptyList().mutableCopyWithCapacity(1); + toRemove.addDouble(3); + toRemove.remove(0); + assertEquals(0, toRemove.size()); + } + + public void testRemove_listAtCapacity() { + DoubleList toRemove = DoubleArrayList.emptyList().mutableCopyWithCapacity(2); + toRemove.addDouble(3); + toRemove.addDouble(4); + toRemove.remove(0); + assertEquals(1, toRemove.size()); + assertEquals(4D, (double) toRemove.get(0)); + } + + public void testSublistRemoveEndOfCapacity() { + DoubleList toRemove = DoubleArrayList.emptyList().mutableCopyWithCapacity(1); + toRemove.addDouble(3); + toRemove.subList(0, 1).clear(); + assertEquals(0, toRemove.size()); + } + + private void assertImmutable(DoubleList list) { if (list.contains(1D)) { throw new RuntimeException("Cannot test the immutability of lists that contain 1."); } diff --git a/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java b/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java index 77d14f6b3a15f..fe37ea808746a 100644 --- a/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java +++ b/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java @@ -33,40 +33,40 @@ import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.OneofDescriptor; +import protobuf_unittest.UnittestProto; import protobuf_unittest.UnittestProto.TestAllExtensions; import protobuf_unittest.UnittestProto.TestAllTypes; +import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage; import protobuf_unittest.UnittestProto.TestEmptyMessage; import protobuf_unittest.UnittestProto.TestPackedTypes; import java.util.Arrays; import junit.framework.TestCase; /** - * Unit test for {@link DynamicMessage}. See also {@link MessageTest}, which - * tests some {@link DynamicMessage} functionality. + * Unit test for {@link DynamicMessage}. See also {@link MessageTest}, which tests some {@link + * DynamicMessage} functionality. * * @author kenton@google.com Kenton Varda */ public class DynamicMessageTest extends TestCase { TestUtil.ReflectionTester reflectionTester = - new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null); + new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null); TestUtil.ReflectionTester extensionsReflectionTester = - new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(), - TestUtil.getExtensionRegistry()); + new TestUtil.ReflectionTester( + TestAllExtensions.getDescriptor(), TestUtil.getFullExtensionRegistry()); TestUtil.ReflectionTester packedReflectionTester = - new TestUtil.ReflectionTester(TestPackedTypes.getDescriptor(), null); + new TestUtil.ReflectionTester(TestPackedTypes.getDescriptor(), null); public void testDynamicMessageAccessors() throws Exception { - Message.Builder builder = - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); reflectionTester.setAllFieldsViaReflection(builder); Message message = builder.build(); reflectionTester.assertAllFieldsSetViaReflection(message); } public void testSettersAfterBuild() throws Exception { - Message.Builder builder = - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); Message firstMessage = builder.build(); // double build() builder.build(); @@ -85,12 +85,12 @@ public void testSettersAfterBuild() throws Exception { } public void testUnknownFields() throws Exception { - Message.Builder builder = - DynamicMessage.newBuilder(TestEmptyMessage.getDescriptor()); - builder.setUnknownFields(UnknownFieldSet.newBuilder() - .addField(1, UnknownFieldSet.Field.newBuilder().addVarint(1).build()) - .addField(2, UnknownFieldSet.Field.newBuilder().addFixed32(1).build()) - .build()); + Message.Builder builder = DynamicMessage.newBuilder(TestEmptyMessage.getDescriptor()); + builder.setUnknownFields( + UnknownFieldSet.newBuilder() + .addField(1, UnknownFieldSet.Field.newBuilder().addVarint(1).build()) + .addField(2, UnknownFieldSet.Field.newBuilder().addFixed32(1).build()) + .build()); Message message = builder.build(); assertEquals(2, message.getUnknownFields().asMap().size()); // clone() with unknown fields @@ -105,8 +105,7 @@ public void testUnknownFields() throws Exception { } public void testDynamicMessageSettersRejectNull() throws Exception { - Message.Builder builder = - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); reflectionTester.assertReflectionSettersRejectNull(builder); } @@ -114,22 +113,19 @@ public void testDynamicMessageExtensionAccessors() throws Exception { // We don't need to extensively test DynamicMessage's handling of // extensions because, frankly, it doesn't do anything special with them. // It treats them just like any other fields. - Message.Builder builder = - DynamicMessage.newBuilder(TestAllExtensions.getDescriptor()); + Message.Builder builder = DynamicMessage.newBuilder(TestAllExtensions.getDescriptor()); extensionsReflectionTester.setAllFieldsViaReflection(builder); Message message = builder.build(); extensionsReflectionTester.assertAllFieldsSetViaReflection(message); } public void testDynamicMessageExtensionSettersRejectNull() throws Exception { - Message.Builder builder = - DynamicMessage.newBuilder(TestAllExtensions.getDescriptor()); + Message.Builder builder = DynamicMessage.newBuilder(TestAllExtensions.getDescriptor()); extensionsReflectionTester.assertReflectionSettersRejectNull(builder); } public void testDynamicMessageRepeatedSetters() throws Exception { - Message.Builder builder = - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); reflectionTester.setAllFieldsViaReflection(builder); reflectionTester.modifyRepeatedFieldsViaReflection(builder); Message message = builder.build(); @@ -137,33 +133,29 @@ public void testDynamicMessageRepeatedSetters() throws Exception { } public void testDynamicMessageRepeatedSettersRejectNull() throws Exception { - Message.Builder builder = - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); reflectionTester.assertReflectionRepeatedSettersRejectNull(builder); } public void testDynamicMessageDefaults() throws Exception { reflectionTester.assertClearViaReflection( - DynamicMessage.getDefaultInstance(TestAllTypes.getDescriptor())); + DynamicMessage.getDefaultInstance(TestAllTypes.getDescriptor())); reflectionTester.assertClearViaReflection( - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()).build()); + DynamicMessage.newBuilder(TestAllTypes.getDescriptor()).build()); } public void testDynamicMessageSerializedSize() throws Exception { TestAllTypes message = TestUtil.getAllSet(); - Message.Builder dynamicBuilder = - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + Message.Builder dynamicBuilder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); reflectionTester.setAllFieldsViaReflection(dynamicBuilder); Message dynamicMessage = dynamicBuilder.build(); - assertEquals(message.getSerializedSize(), - dynamicMessage.getSerializedSize()); + assertEquals(message.getSerializedSize(), dynamicMessage.getSerializedSize()); } public void testDynamicMessageSerialization() throws Exception { - Message.Builder builder = - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); reflectionTester.setAllFieldsViaReflection(builder); Message message = builder.build(); @@ -183,8 +175,7 @@ public void testDynamicMessageParsing() throws Exception { ByteString rawBytes = message.toByteString(); - Message message2 = - DynamicMessage.parseFrom(TestAllTypes.getDescriptor(), rawBytes); + Message message2 = DynamicMessage.parseFrom(TestAllTypes.getDescriptor(), rawBytes); reflectionTester.assertAllFieldsSetViaReflection(message2); // Test Parser interface. @@ -194,20 +185,19 @@ public void testDynamicMessageParsing() throws Exception { public void testDynamicMessageExtensionParsing() throws Exception { ByteString rawBytes = TestUtil.getAllExtensionsSet().toByteString(); - Message message = DynamicMessage.parseFrom( - TestAllExtensions.getDescriptor(), rawBytes, - TestUtil.getExtensionRegistry()); + Message message = + DynamicMessage.parseFrom( + TestAllExtensions.getDescriptor(), rawBytes, TestUtil.getFullExtensionRegistry()); extensionsReflectionTester.assertAllFieldsSetViaReflection(message); // Test Parser interface. - Message message2 = message.getParserForType().parseFrom( - rawBytes, TestUtil.getExtensionRegistry()); + Message message2 = + message.getParserForType().parseFrom(rawBytes, TestUtil.getExtensionRegistry()); extensionsReflectionTester.assertAllFieldsSetViaReflection(message2); } public void testDynamicMessagePackedSerialization() throws Exception { - Message.Builder builder = - DynamicMessage.newBuilder(TestPackedTypes.getDescriptor()); + Message.Builder builder = DynamicMessage.newBuilder(TestPackedTypes.getDescriptor()); packedReflectionTester.setPackedFieldsViaReflection(builder); Message message = builder.build(); @@ -227,8 +217,7 @@ public void testDynamicMessagePackedParsing() throws Exception { ByteString rawBytes = message.toByteString(); - Message message2 = - DynamicMessage.parseFrom(TestPackedTypes.getDescriptor(), rawBytes); + Message message2 = DynamicMessage.parseFrom(TestPackedTypes.getDescriptor(), rawBytes); packedReflectionTester.assertPackedFieldsSetViaReflection(message2); // Test Parser interface. @@ -236,6 +225,17 @@ public void testDynamicMessagePackedParsing() throws Exception { packedReflectionTester.assertPackedFieldsSetViaReflection(message3); } + public void testGetBuilderForExtensionField() { + DynamicMessage.Builder builder = DynamicMessage.newBuilder(TestAllExtensions.getDescriptor()); + Message.Builder fieldBuilder = + builder.newBuilderForField(UnittestProto.optionalNestedMessageExtension.getDescriptor()); + final int expected = 7432; + FieldDescriptor field = + NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER); + fieldBuilder.setField(field, expected); + assertEquals(expected, fieldBuilder.build().getField(field)); + } + public void testDynamicMessageCopy() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TestUtil.setAllFields(builder); @@ -245,41 +245,38 @@ public void testDynamicMessageCopy() throws Exception { reflectionTester.assertAllFieldsSetViaReflection(copy); // Test oneof behavior - FieldDescriptor bytesField = - TestAllTypes.getDescriptor().findFieldByName("oneof_bytes"); - FieldDescriptor uint32Field = - TestAllTypes.getDescriptor().findFieldByName("oneof_uint32"); + FieldDescriptor bytesField = TestAllTypes.getDescriptor().findFieldByName("oneof_bytes"); + FieldDescriptor uint32Field = TestAllTypes.getDescriptor().findFieldByName("oneof_uint32"); assertTrue(copy.hasField(bytesField)); assertFalse(copy.hasField(uint32Field)); - DynamicMessage copy2 = - DynamicMessage.newBuilder(message).setField(uint32Field, 123).build(); + DynamicMessage copy2 = DynamicMessage.newBuilder(message).setField(uint32Field, 123).build(); assertFalse(copy2.hasField(bytesField)); assertTrue(copy2.hasField(uint32Field)); assertEquals(123, copy2.getField(uint32Field)); } public void testToBuilder() throws Exception { - DynamicMessage.Builder builder = - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + DynamicMessage.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); reflectionTester.setAllFieldsViaReflection(builder); int unknownFieldNum = 9; long unknownFieldVal = 90; - builder.setUnknownFields(UnknownFieldSet.newBuilder() - .addField(unknownFieldNum, - UnknownFieldSet.Field.newBuilder() - .addVarint(unknownFieldVal).build()) - .build()); + builder.setUnknownFields( + UnknownFieldSet.newBuilder() + .addField( + unknownFieldNum, + UnknownFieldSet.Field.newBuilder().addVarint(unknownFieldVal).build()) + .build()); DynamicMessage message = builder.build(); DynamicMessage derived = message.toBuilder().build(); reflectionTester.assertAllFieldsSetViaReflection(derived); - assertEquals(Arrays.asList(unknownFieldVal), + assertEquals( + Arrays.asList(unknownFieldVal), derived.getUnknownFields().getField(unknownFieldNum).getVarintList()); } public void testDynamicOneofMessage() throws Exception { - DynamicMessage.Builder builder = - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + DynamicMessage.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); OneofDescriptor oneof = TestAllTypes.getDescriptor().getOneofs().get(0); assertFalse(builder.hasOneof(oneof)); assertSame(null, builder.getOneofFieldDescriptor(oneof)); @@ -292,8 +289,7 @@ public void testDynamicOneofMessage() throws Exception { DynamicMessage message = builder.buildPartial(); assertTrue(message.hasOneof(oneof)); - DynamicMessage.Builder mergedBuilder = - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + DynamicMessage.Builder mergedBuilder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); FieldDescriptor mergedField = oneof.getField(0); mergedBuilder.setField(mergedField, 123); assertTrue(mergedBuilder.hasField(mergedField)); @@ -310,15 +306,12 @@ public void testDynamicOneofMessage() throws Exception { // Regression test for a bug that makes setField() not work for repeated // enum fields. public void testSettersForRepeatedEnumField() throws Exception { - DynamicMessage.Builder builder = - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + DynamicMessage.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); FieldDescriptor repeatedEnumField = - TestAllTypes.getDescriptor().findFieldByName( - "repeated_nested_enum"); + TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum"); EnumDescriptor enumDescriptor = TestAllTypes.NestedEnum.getDescriptor(); builder.setField(repeatedEnumField, enumDescriptor.getValues()); DynamicMessage message = builder.build(); - assertEquals( - enumDescriptor.getValues(), message.getField(repeatedEnumField)); + assertEquals(enumDescriptor.getValues(), message.getField(repeatedEnumField)); } } diff --git a/java/core/src/test/java/com/google/protobuf/EnumTest.java b/java/core/src/test/java/com/google/protobuf/EnumTest.java index 14c7406b3d6ba..80c176a771318 100644 --- a/java/core/src/test/java/com/google/protobuf/EnumTest.java +++ b/java/core/src/test/java/com/google/protobuf/EnumTest.java @@ -34,43 +34,43 @@ import com.google.protobuf.UnittestLite.TestAllTypesLite; import protobuf_unittest.UnittestProto.ForeignEnum; import protobuf_unittest.UnittestProto.TestAllTypes; - import junit.framework.TestCase; public class EnumTest extends TestCase { - + public void testForNumber() { ForeignEnum e = ForeignEnum.forNumber(ForeignEnum.FOREIGN_BAR.getNumber()); assertEquals(ForeignEnum.FOREIGN_BAR, e); e = ForeignEnum.forNumber(1000); - assertEquals(null, e); + assertNull(e); } - + public void testForNumber_oneof() { - TestAllTypes.OneofFieldCase e = TestAllTypes.OneofFieldCase.forNumber( - TestAllTypes.OneofFieldCase.ONEOF_NESTED_MESSAGE.getNumber()); + TestAllTypes.OneofFieldCase e = + TestAllTypes.OneofFieldCase.forNumber( + TestAllTypes.OneofFieldCase.ONEOF_NESTED_MESSAGE.getNumber()); assertEquals(TestAllTypes.OneofFieldCase.ONEOF_NESTED_MESSAGE, e); e = TestAllTypes.OneofFieldCase.forNumber(1000); - assertEquals(null, e); + assertNull(e); } - + public void testForNumberLite() { ForeignEnumLite e = ForeignEnumLite.forNumber(ForeignEnumLite.FOREIGN_LITE_BAR.getNumber()); assertEquals(ForeignEnumLite.FOREIGN_LITE_BAR, e); e = ForeignEnumLite.forNumber(1000); - assertEquals(null, e); + assertNull(e); } - + public void testForNumberLite_oneof() { - TestAllTypesLite.OneofFieldCase e = TestAllTypesLite.OneofFieldCase.forNumber( - TestAllTypesLite.OneofFieldCase.ONEOF_NESTED_MESSAGE.getNumber()); + TestAllTypesLite.OneofFieldCase e = + TestAllTypesLite.OneofFieldCase.forNumber( + TestAllTypesLite.OneofFieldCase.ONEOF_NESTED_MESSAGE.getNumber()); assertEquals(TestAllTypesLite.OneofFieldCase.ONEOF_NESTED_MESSAGE, e); e = TestAllTypesLite.OneofFieldCase.forNumber(1000); - assertEquals(null, e); + assertNull(e); } } - diff --git a/java/core/src/test/java/com/google/protobuf/ExperimentalMessageFactory.java b/java/core/src/test/java/com/google/protobuf/ExperimentalMessageFactory.java new file mode 100644 index 0000000000000..60c8609cf42d4 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/ExperimentalMessageFactory.java @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** Interface for a test factory for messages. */ +public interface ExperimentalMessageFactory { + /** Creates a new random message instance. */ + T newMessage(); + + /** Gets the underlying data provider. */ + ExperimentalTestDataProvider dataProvider(); +} diff --git a/java/core/src/test/java/com/google/protobuf/ExperimentalSerializationUtil.java b/java/core/src/test/java/com/google/protobuf/ExperimentalSerializationUtil.java new file mode 100644 index 0000000000000..05aaa67521f27 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/ExperimentalSerializationUtil.java @@ -0,0 +1,113 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Queue; + +/** Utilities for serialization. */ +public class ExperimentalSerializationUtil { + + /** + * Serializes the given message to a byte array using {@link com.google.protobuf.BinaryWriter}. + */ + public static byte[] toByteArray(T msg) throws IOException { + return toByteArray(msg, Protobuf.getInstance().schemaFor(msg)); + } + + /** + * Serializes the given message to a byte array using {@link com.google.protobuf.BinaryWriter} + * with a customized Schema. + */ + public static byte[] toByteArray(T msg, Schema schema) throws IOException { + BinaryWriter writer = BinaryWriter.newHeapInstance(BufferAllocator.unpooled()); + schema.writeTo(msg, writer); + + byte[] out = new byte[writer.getTotalBytesWritten()]; + int outPos = 0; + Queue buffers = writer.complete(); + while (true) { + AllocatedBuffer buffer = buffers.poll(); + if (buffer == null) { + break; + } + int length = buffer.limit() - buffer.position(); + System.arraycopy( + buffer.array(), buffer.arrayOffset() + buffer.position(), out, outPos, length); + outPos += length; + } + if (out.length != outPos) { + throw new IllegalArgumentException("Failed to serialize test message"); + } + return out; + } + + /** Deserializes a message from the given byte array. */ + public static T fromByteArray(byte[] data, Class messageType) { + if (Android.isOnAndroidDevice()) { + return fromByteArrayFastPath(data, messageType); + } else { + return fromByteArray(data, messageType, ExtensionRegistryLite.getEmptyRegistry()); + } + } + + /** + * Deserializes a message from the given byte array using {@link com.google.protobuf.BinaryReader} + * with an extension registry and a customized Schema. + */ + public static T fromByteArray( + byte[] data, Class messageType, ExtensionRegistryLite extensionRegistry) { + try { + Schema schema = Protobuf.getInstance().schemaFor(messageType); + T msg = schema.newInstance(); + schema.mergeFrom( + msg, BinaryReader.newInstance(ByteBuffer.wrap(data), true), extensionRegistry); + schema.makeImmutable(msg); + return msg; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** Deserializes a lite message from the given byte array using fast path. */ + private static T fromByteArrayFastPath(byte[] data, Class messageType) { + try { + Schema schema = Protobuf.getInstance().schemaFor(messageType); + T msg = schema.newInstance(); + schema.mergeFrom(msg, data, 0, data.length, new ArrayDecoders.Registers()); + schema.makeImmutable(msg); + return msg; + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/java/core/src/test/java/com/google/protobuf/ExperimentalTestDataProvider.java b/java/core/src/test/java/com/google/protobuf/ExperimentalTestDataProvider.java new file mode 100644 index 0000000000000..3ef93ac9f855a --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/ExperimentalTestDataProvider.java @@ -0,0 +1,189 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.util.Random; + +/** Utility class that provides data primitives for filling out protobuf messages. */ +public final class ExperimentalTestDataProvider { + private static final Random RANDOM = new Random(100); + + private final Varint32Provider varint32s = new Varint32Provider(); + private final Varint64Provider varint64s = new Varint64Provider(); + private final int stringLength; + + public ExperimentalTestDataProvider(int stringLength) { + this.stringLength = stringLength; + } + + public double getDouble() { + double value = 0.0; + while (Double.compare(0.0, value) == 0) { + value = RANDOM.nextDouble(); + } + return value; + } + + public float getFloat() { + float value = 0.0f; + while (Float.compare(0.0f, value) == 0) { + value = RANDOM.nextFloat(); + } + return value; + } + + public long getLong() { + return varint64s.getLong(); + } + + public int getInt() { + return varint32s.getInt(); + } + + public boolean getBool() { + return true; + } + + public int getEnum() { + return Math.abs(getInt()) % 3; + } + + public String getString() { + StringBuilder builder = new StringBuilder(stringLength); + for (int i = 0; i < stringLength; ++i) { + builder.append((char) (RANDOM.nextInt('z' - 'a') + 'a')); + } + return builder.toString(); + } + + public ByteString getBytes() { + return ByteString.copyFromUtf8(getString()); + } + + /** + * Iterator over integer values. Uses a simple distribution over 32-bit varints (generally + * favoring smaller values). + */ + private static final class Varint32Provider { + private static final int[][] VALUES = { + new int[] {1, 50, 100, 127}, // 1 byte values + new int[] {128, 500, 10000, 16383}, // 2 bytes values + new int[] {16384, 50000, 1000000, 2097151}, // 3 bytes values + new int[] {2097152, 10000000, 200000000, 268435455}, // 4 bytes values + new int[] {268435456, 0x30000000, 0x7FFFFFFF, 0xFFFFFFFF} // 5 bytes values + }; + + /** Number of samples that should be taken from each value array. */ + private static final int[] NUM_SAMPLES = {3, 2, 1, 1, 2}; + + /** + * The index into the {@link #VALUES} array that identifies the list of samples currently being + * iterated over. + */ + private int listIndex; + + /** The index of the next sample within a list. */ + private int sampleIndex; + + /** The number of successive samples that have been taken from the current list. */ + private int samplesTaken; + + public int getInt() { + if (samplesTaken++ > NUM_SAMPLES[listIndex]) { + // Done taking samples from this list. Go to the next one. + listIndex = (listIndex + 1) % VALUES.length; + sampleIndex = 0; + samplesTaken = 0; + } + + int value = VALUES[listIndex][sampleIndex]; + + // All lists are exactly 4 long (i.e. power of 2), so we can optimize the mod operation + // with masking. + sampleIndex = (sampleIndex + 1) & 3; + + return value; + } + } + + /** + * Iterator over integer values. Uses a simple distribution over 64-bit varints (generally + * favoring smaller values). + */ + private static final class Varint64Provider { + private static final long[][] VALUES = { + new long[] {1, 50, 100, 127}, + new long[] {128, 500, 10000, 16383}, + new long[] {16384, 50000, 1000000, 2097151}, + new long[] {2097152, 10000000, 200000000, 268435455}, + new long[] {268435456, 0x30000000, 0x7FFFFFFF, 34359738367L}, + new long[] {34359738368L, 2000000000000L, 4000000000000L, 4398046511103L}, + new long[] {4398046511104L, 200000000000000L, 500000000000000L, 562949953421311L}, + new long[] {0x4000000000000L, 0x5000000000000L, 0x6000000000000L, 0x0FFFFFFFFFFFFFFL}, + new long[] {0x100000000000000L, 0x3FFFFFFFFFFFFFFFL, 0x5FFFFFFFFFFFFFFL, 0x7FFFFFFFFFFFFFFFL}, + new long[] { + 0xFFFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFFFFFFL + } + }; + + /** Number of samples that should be taken from each value array. */ + private static final int[] NUM_SAMPLES = {4, 2, 2, 1, 1, 1, 1, 2, 2, 4}; + + /** + * The index into the {@link #VALUES} array that identifies the list of samples currently being + * iterated over. + */ + private int listIndex; + + /** The index of the next sample within a list. */ + private int sampleIndex; + + /** The number of successive samples that have been taken from the current list. */ + private int samplesTaken; + + public long getLong() { + if (samplesTaken++ > NUM_SAMPLES[listIndex]) { + // Done taking samples from this list. Go to the next one. + listIndex = (listIndex + 1) % VALUES.length; + sampleIndex = 0; + samplesTaken = 0; + } + + long value = VALUES[listIndex][sampleIndex]; + + // All lists are exactly 4 long (i.e. power of 2), so we can optimize the mod operation + // with masking. + sampleIndex = (sampleIndex + 1) & 3; + + return value; + } + } +} diff --git a/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java b/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java index 6157e58966bca..70466ba2e7ac3 100644 --- a/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java +++ b/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java @@ -41,37 +41,44 @@ import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; +import org.junit.Ignore; /** * Tests for {@link ExtensionRegistryFactory} and the {@link ExtensionRegistry} instances it * creates. * *

This test simulates the runtime behaviour of the ExtensionRegistryFactory by delegating test - * definitions to two inner classes {@link InnerTest} and {@link InnerLiteTest}, the latter of - * which is executed using a custom ClassLoader, simulating the ProtoLite environment. + * definitions to two inner classes {@link InnerTest} and {@link InnerLiteTest}, the latter of which + * is executed using a custom ClassLoader, simulating the ProtoLite environment. * - *

The test mechanism employed here is based on the pattern in - * {@code com.google.common.util.concurrent.AbstractFutureFallbackAtomicHelperTest} + *

The test mechanism employed here is based on the pattern in {@code + * com.google.common.util.concurrent.AbstractFutureFallbackAtomicHelperTest} + * + *

This test is temporarily disabled due to what appears to be a subtle change to class loading + * behavior in Java 11. That seems to have broken the way the test uses a custom ClassLoader to + * exercise Lite functionality. */ +@SuppressWarnings("JUnit4ClassUsedInJUnit3") +@Ignore public class ExtensionRegistryFactoryTest extends TestCase { // A classloader which blacklists some non-Lite classes. private static final ClassLoader LITE_CLASS_LOADER = getLiteOnlyClassLoader(); - /** - * Defines the set of test methods which will be run. - */ + /** Defines the set of test methods which will be run. */ static interface RegistryTests { void testCreate(); + void testEmpty(); + void testIsFullRegistry(); + void testAdd(); + void testAdd_immutable(); } - /** - * Test implementations for the non-Lite usage of ExtensionRegistryFactory. - */ + /** Test implementations for the non-Lite usage of ExtensionRegistryFactory. */ public static class InnerTest implements RegistryTests { @Override @@ -108,20 +115,24 @@ public void testAdd() { ExtensionRegistry fullRegistry1 = (ExtensionRegistry) registry1; ExtensionRegistry fullRegistry2 = (ExtensionRegistry) registry2; - assertTrue("Test is using a non-lite extension", + assertTrue( + "Test is using a non-lite extension", GeneratedMessageLite.GeneratedExtension.class.isAssignableFrom( NonNestedExtensionLite.nonNestedExtensionLite.getClass())); - assertNull("Extension is not registered in masqueraded full registry", + assertNull( + "Extension is not registered in masqueraded full registry", fullRegistry1.findImmutableExtensionByName("protobuf_unittest.nonNestedExtension")); GeneratedMessageLite.GeneratedExtension - extension = registry1.findLiteExtensionByNumber( - NonNestedExtensionLite.MessageLiteToBeExtended.getDefaultInstance(), 1); + extension = + registry1.findLiteExtensionByNumber( + NonNestedExtensionLite.MessageLiteToBeExtended.getDefaultInstance(), 1); assertNotNull("Extension registered in lite registry", extension); - assertTrue("Test is using a non-lite extension", - GeneratedMessage.GeneratedExtension.class.isAssignableFrom( - NonNestedExtension.nonNestedExtension.getClass())); - assertNotNull("Extension is registered in masqueraded full registry", + assertTrue( + "Test is using a non-lite extension", + Extension.class.isAssignableFrom(NonNestedExtension.nonNestedExtension.getClass())); + assertNotNull( + "Extension is registered in masqueraded full registry", fullRegistry2.findImmutableExtensionByName("protobuf_unittest.nonNestedExtension")); } @@ -131,27 +142,29 @@ public void testAdd_immutable() { try { NonNestedExtensionLite.registerAllExtensions(registry1); fail(); - } catch (UnsupportedOperationException expected) {} + } catch (UnsupportedOperationException expected) { + } try { registry1.add(NonNestedExtensionLite.nonNestedExtensionLite); fail(); - } catch (UnsupportedOperationException expected) {} + } catch (UnsupportedOperationException expected) { + } ExtensionRegistryLite registry2 = ExtensionRegistryLite.newInstance().getUnmodifiable(); try { NonNestedExtension.registerAllExtensions((ExtensionRegistry) registry2); fail(); - } catch (IllegalArgumentException expected) {} + } catch (IllegalArgumentException expected) { + } try { registry2.add(NonNestedExtension.nonNestedExtension); fail(); - } catch (IllegalArgumentException expected) {} + } catch (IllegalArgumentException expected) { + } } } - /** - * Test implementations for the Lite usage of ExtensionRegistryFactory. - */ + /** Test implementations for the Lite usage of ExtensionRegistryFactory. */ public static final class InnerLiteTest implements RegistryTests { @Override @@ -180,8 +193,9 @@ public void testAdd() { ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); NonNestedExtensionLite.registerAllExtensions(registry); GeneratedMessageLite.GeneratedExtension - extension = registry.findLiteExtensionByNumber( - NonNestedExtensionLite.MessageLiteToBeExtended.getDefaultInstance(), 1); + extension = + registry.findLiteExtensionByNumber( + NonNestedExtensionLite.MessageLiteToBeExtended.getDefaultInstance(), 1); assertNotNull("Extension is registered in Lite registry", extension); } @@ -191,13 +205,12 @@ public void testAdd_immutable() { try { NonNestedExtensionLite.registerAllExtensions(registry); fail(); - } catch (UnsupportedOperationException expected) {} + } catch (UnsupportedOperationException expected) { + } } } - /** - * Defines a suite of tests which the JUnit3 runner retrieves by reflection. - */ + /** Defines a suite of tests which the JUnit3 runner retrieves by reflection. */ public static Test suite() { TestSuite suite = new TestSuite(); for (Method method : RegistryTests.class.getMethods()) { @@ -231,12 +244,12 @@ private void runTestMethod(ClassLoader classLoader, Class test = classLoader.loadClass(testClass.getName()); String testName = getName(); - test.getMethod(testName).invoke(test.newInstance()); + test.getMethod(testName).invoke(test.getDeclaredConstructor().newInstance()); } /** - * Constructs a custom ClassLoader blacklisting the classes which are inspected in the SUT - * to determine the Lite/non-Lite runtime. + * Constructs a custom ClassLoader blacklisting the classes which are inspected in the SUT to + * determine the Lite/non-Lite runtime. */ private static ClassLoader getLiteOnlyClassLoader() { ClassLoader testClassLoader = ExtensionRegistryFactoryTest.class.getClassLoader(); @@ -250,8 +263,8 @@ private static ClassLoader getLiteOnlyClassLoader() { // Construct a URLClassLoader delegating to the system ClassLoader, and looking up classes // in jar files based on the URLs already configured for this test's UrlClassLoader. // Certain classes throw a ClassNotFoundException by design. - return new URLClassLoader(((URLClassLoader) testClassLoader).getURLs(), - ClassLoader.getSystemClassLoader()) { + return new URLClassLoader( + ((URLClassLoader) testClassLoader).getURLs(), ClassLoader.getSystemClassLoader()) { @Override public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { if (classNamesNotInLite.contains(name)) { @@ -266,7 +279,10 @@ public Class loadClass(String name, boolean resolve) throws ClassNotFoundExce resolveClass(loadedClass); } } - } catch (ClassNotFoundException e) { + } catch (ClassNotFoundException | SecurityException e) { + // Java 8+ would throw a SecurityException if we attempt to find a loaded class from + // java.lang.* package. We don't really care about those anyway, so just delegate to the + // parent class loader. loadedClass = super.loadClass(name, resolve); } return loadedClass; diff --git a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java index ff686a0cdfd46..726672980cd23 100644 --- a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java +++ b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java @@ -34,16 +34,16 @@ import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Descriptors.OneofDescriptor; import com.google.protobuf.FieldPresenceTestProto.TestAllTypes; import com.google.protobuf.FieldPresenceTestProto.TestOptionalFieldsOnly; import com.google.protobuf.FieldPresenceTestProto.TestRepeatedFieldsOnly; +import com.google.protobuf.testing.proto.TestProto3Optional; import protobuf_unittest.UnittestProto; - import junit.framework.TestCase; /** - * Unit tests for protos that doesn't support field presence test for optional - * non-message fields. + * Unit tests for protos that doesn't support field presence test for optional non-message fields. */ public class FieldPresenceTest extends TestCase { private static boolean hasMethod(Class clazz, String name) { @@ -59,89 +59,163 @@ private static boolean hasMethod(Class clazz, String name) { } private static void assertHasMethodRemoved( - Class classWithFieldPresence, - Class classWithoutFieldPresence, - String camelName) { + Class classWithFieldPresence, Class classWithoutFieldPresence, String camelName) { assertTrue(hasMethod(classWithFieldPresence, "get" + camelName)); assertTrue(hasMethod(classWithFieldPresence, "has" + camelName)); assertTrue(hasMethod(classWithoutFieldPresence, "get" + camelName)); assertFalse(hasMethod(classWithoutFieldPresence, "has" + camelName)); } + private static void assertHasMethodExisting(Class clazz, String camelName) { + assertTrue(hasMethod(clazz, "get" + camelName)); + assertTrue(hasMethod(clazz, "has" + camelName)); + } + public void testHasMethod() { // Optional non-message fields don't have a hasFoo() method generated. + assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OptionalInt32"); + assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OptionalString"); + assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OptionalBytes"); assertHasMethodRemoved( - UnittestProto.TestAllTypes.class, - TestAllTypes.class, - "OptionalInt32"); - assertHasMethodRemoved( - UnittestProto.TestAllTypes.class, - TestAllTypes.class, - "OptionalString"); - assertHasMethodRemoved( - UnittestProto.TestAllTypes.class, - TestAllTypes.class, - "OptionalBytes"); - assertHasMethodRemoved( - UnittestProto.TestAllTypes.class, - TestAllTypes.class, - "OptionalNestedEnum"); + UnittestProto.TestAllTypes.class, TestAllTypes.class, "OptionalNestedEnum"); assertHasMethodRemoved( - UnittestProto.TestAllTypes.Builder.class, - TestAllTypes.Builder.class, - "OptionalInt32"); + UnittestProto.TestAllTypes.Builder.class, TestAllTypes.Builder.class, "OptionalInt32"); assertHasMethodRemoved( - UnittestProto.TestAllTypes.Builder.class, - TestAllTypes.Builder.class, - "OptionalString"); + UnittestProto.TestAllTypes.Builder.class, TestAllTypes.Builder.class, "OptionalString"); assertHasMethodRemoved( - UnittestProto.TestAllTypes.Builder.class, - TestAllTypes.Builder.class, - "OptionalBytes"); + UnittestProto.TestAllTypes.Builder.class, TestAllTypes.Builder.class, "OptionalBytes"); assertHasMethodRemoved( - UnittestProto.TestAllTypes.Builder.class, - TestAllTypes.Builder.class, - "OptionalNestedEnum"); + UnittestProto.TestAllTypes.Builder.class, TestAllTypes.Builder.class, "OptionalNestedEnum"); // message fields still have the hasFoo() method generated. - assertFalse(TestAllTypes.newBuilder().build().hasOptionalNestedMessage()); + assertFalse(TestAllTypes.getDefaultInstance().hasOptionalNestedMessage()); assertFalse(TestAllTypes.newBuilder().hasOptionalNestedMessage()); - // oneof fields don't have hasFoo() methods for non-message types. - assertHasMethodRemoved( - UnittestProto.TestAllTypes.class, - TestAllTypes.class, - "OneofUint32"); - assertHasMethodRemoved( - UnittestProto.TestAllTypes.class, - TestAllTypes.class, - "OneofString"); - assertHasMethodRemoved( - UnittestProto.TestAllTypes.class, - TestAllTypes.class, - "OneofBytes"); - assertFalse(TestAllTypes.newBuilder().build().hasOneofNestedMessage()); + // oneof fields support hasFoo() methods for non-message types. + assertHasMethodExisting(TestAllTypes.class, "OneofUint32"); + assertHasMethodExisting(TestAllTypes.class, "OneofString"); + assertHasMethodExisting(TestAllTypes.class, "OneofBytes"); + assertFalse(TestAllTypes.getDefaultInstance().hasOneofNestedMessage()); assertFalse(TestAllTypes.newBuilder().hasOneofNestedMessage()); - assertHasMethodRemoved( - UnittestProto.TestAllTypes.Builder.class, - TestAllTypes.Builder.class, - "OneofUint32"); - assertHasMethodRemoved( - UnittestProto.TestAllTypes.Builder.class, - TestAllTypes.Builder.class, - "OneofString"); - assertHasMethodRemoved( - UnittestProto.TestAllTypes.Builder.class, - TestAllTypes.Builder.class, - "OneofBytes"); + assertHasMethodExisting(TestAllTypes.Builder.class, "OneofUint32"); + assertHasMethodExisting(TestAllTypes.Builder.class, "OneofString"); + assertHasMethodExisting(TestAllTypes.Builder.class, "OneofBytes"); + } + + public void testHasMethodForProto3Optional() throws Exception { + assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalInt32()); + assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalInt64()); + assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalUint32()); + assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalUint64()); + assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalSint32()); + assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalSint64()); + assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalFixed32()); + assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalFixed64()); + assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalFloat()); + assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalDouble()); + assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalBool()); + assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalString()); + assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalBytes()); + + TestProto3Optional.Builder builder = TestProto3Optional.newBuilder().setOptionalInt32(0); + assertTrue(builder.hasOptionalInt32()); + assertTrue(builder.build().hasOptionalInt32()); + + TestProto3Optional.Builder otherBuilder = TestProto3Optional.newBuilder().setOptionalInt32(1); + otherBuilder.mergeFrom(builder.build()); + assertTrue(otherBuilder.hasOptionalInt32()); + assertEquals(0, otherBuilder.getOptionalInt32()); + + TestProto3Optional.Builder builder3 = + TestProto3Optional.newBuilder().setOptionalNestedEnumValue(5); + assertTrue(builder3.hasOptionalNestedEnum()); + + TestProto3Optional.Builder builder4 = + TestProto3Optional.newBuilder().setOptionalNestedEnum(TestProto3Optional.NestedEnum.FOO); + assertTrue(builder4.hasOptionalNestedEnum()); + + TestProto3Optional proto = TestProto3Optional.parseFrom(builder.build().toByteArray()); + assertTrue(proto.hasOptionalInt32()); + assertTrue(proto.toBuilder().hasOptionalInt32()); + } + + private static void assertProto3OptionalReflection(String name) throws Exception { + FieldDescriptor fieldDescriptor = TestProto3Optional.getDescriptor().findFieldByName(name); + OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof(); + assertNotNull(fieldDescriptor.getContainingOneof()); + assertTrue(fieldDescriptor.hasOptionalKeyword()); + assertTrue(fieldDescriptor.hasPresence()); + + assertFalse(TestProto3Optional.getDefaultInstance().hasOneof(oneofDescriptor)); + assertNull(TestProto3Optional.getDefaultInstance().getOneofFieldDescriptor(oneofDescriptor)); + + TestProto3Optional.Builder builder = TestProto3Optional.newBuilder(); + builder.setField(fieldDescriptor, fieldDescriptor.getDefaultValue()); + assertTrue(builder.hasField(fieldDescriptor)); + assertEquals(fieldDescriptor.getDefaultValue(), builder.getField(fieldDescriptor)); + assertTrue(builder.build().hasField(fieldDescriptor)); + assertEquals(fieldDescriptor.getDefaultValue(), builder.build().getField(fieldDescriptor)); + assertTrue(builder.hasOneof(oneofDescriptor)); + assertEquals(fieldDescriptor, builder.getOneofFieldDescriptor(oneofDescriptor)); + assertTrue(builder.build().hasOneof(oneofDescriptor)); + assertEquals(fieldDescriptor, builder.build().getOneofFieldDescriptor(oneofDescriptor)); + + TestProto3Optional.Builder otherBuilder = TestProto3Optional.newBuilder(); + otherBuilder.mergeFrom(builder.build()); + assertTrue(otherBuilder.hasField(fieldDescriptor)); + assertEquals(fieldDescriptor.getDefaultValue(), otherBuilder.getField(fieldDescriptor)); + + TestProto3Optional proto = TestProto3Optional.parseFrom(builder.build().toByteArray()); + assertTrue(proto.hasField(fieldDescriptor)); + assertTrue(proto.toBuilder().hasField(fieldDescriptor)); + + DynamicMessage.Builder dynamicBuilder = + DynamicMessage.newBuilder(TestProto3Optional.getDescriptor()); + dynamicBuilder.setField(fieldDescriptor, fieldDescriptor.getDefaultValue()); + assertTrue(dynamicBuilder.hasField(fieldDescriptor)); + assertEquals(fieldDescriptor.getDefaultValue(), dynamicBuilder.getField(fieldDescriptor)); + assertTrue(dynamicBuilder.build().hasField(fieldDescriptor)); + assertEquals( + fieldDescriptor.getDefaultValue(), dynamicBuilder.build().getField(fieldDescriptor)); + assertTrue(dynamicBuilder.hasOneof(oneofDescriptor)); + assertEquals(fieldDescriptor, dynamicBuilder.getOneofFieldDescriptor(oneofDescriptor)); + assertTrue(dynamicBuilder.build().hasOneof(oneofDescriptor)); + assertEquals(fieldDescriptor, dynamicBuilder.build().getOneofFieldDescriptor(oneofDescriptor)); + + DynamicMessage.Builder otherDynamicBuilder = + DynamicMessage.newBuilder(TestProto3Optional.getDescriptor()); + otherDynamicBuilder.mergeFrom(dynamicBuilder.build()); + assertTrue(otherDynamicBuilder.hasField(fieldDescriptor)); + assertEquals(fieldDescriptor.getDefaultValue(), otherDynamicBuilder.getField(fieldDescriptor)); + + DynamicMessage dynamicProto = + DynamicMessage.parseFrom(TestProto3Optional.getDescriptor(), builder.build().toByteArray()); + assertTrue(dynamicProto.hasField(fieldDescriptor)); + assertTrue(dynamicProto.toBuilder().hasField(fieldDescriptor)); + } + + public void testProto3Optional_reflection() throws Exception { + assertProto3OptionalReflection("optional_int32"); + assertProto3OptionalReflection("optional_int64"); + assertProto3OptionalReflection("optional_uint32"); + assertProto3OptionalReflection("optional_uint64"); + assertProto3OptionalReflection("optional_sint32"); + assertProto3OptionalReflection("optional_sint64"); + assertProto3OptionalReflection("optional_fixed32"); + assertProto3OptionalReflection("optional_fixed64"); + assertProto3OptionalReflection("optional_float"); + assertProto3OptionalReflection("optional_double"); + assertProto3OptionalReflection("optional_bool"); + assertProto3OptionalReflection("optional_string"); + assertProto3OptionalReflection("optional_bytes"); } public void testOneofEquals() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TestAllTypes message1 = builder.build(); - // Set message2's oneof_uint32 field to defalut value. The two + // Set message2's oneof_uint32 field to default value. The two // messages should be different when check with oneof case. builder.setOneofUint32(0); TestAllTypes message2 = builder.build(); @@ -200,10 +274,10 @@ public void testFieldPresence() { assertEquals(TestAllTypes.NestedEnum.BAR, message.getOptionalNestedEnum()); // equals()/hashCode() should produce the same results. - TestAllTypes empty = TestAllTypes.newBuilder().build(); + TestAllTypes empty = TestAllTypes.getDefaultInstance(); message = builder.build(); - assertTrue(empty.equals(message)); - assertTrue(message.equals(empty)); + assertEquals(message, empty); + assertEquals(empty, message); assertEquals(empty.hashCode(), message.hashCode()); } @@ -215,7 +289,7 @@ public void testFieldPresenceByReflection() { FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum"); // Field not present. - TestAllTypes message = TestAllTypes.newBuilder().build(); + TestAllTypes message = TestAllTypes.getDefaultInstance(); assertFalse(message.hasField(optionalInt32Field)); assertFalse(message.hasField(optionalStringField)); assertFalse(message.hasField(optionalBytesField)); @@ -223,12 +297,13 @@ public void testFieldPresenceByReflection() { assertEquals(0, message.getAllFields().size()); // Field set to default value is seen as not present. - message = TestAllTypes.newBuilder() - .setOptionalInt32(0) - .setOptionalString("") - .setOptionalBytes(ByteString.EMPTY) - .setOptionalNestedEnum(TestAllTypes.NestedEnum.FOO) - .build(); + message = + TestAllTypes.newBuilder() + .setOptionalInt32(0) + .setOptionalString("") + .setOptionalBytes(ByteString.EMPTY) + .setOptionalNestedEnum(TestAllTypes.NestedEnum.FOO) + .build(); assertFalse(message.hasField(optionalInt32Field)); assertFalse(message.hasField(optionalStringField)); assertFalse(message.hasField(optionalBytesField)); @@ -236,12 +311,13 @@ public void testFieldPresenceByReflection() { assertEquals(0, message.getAllFields().size()); // Field set to non-default value is seen as present. - message = TestAllTypes.newBuilder() - .setOptionalInt32(1) - .setOptionalString("x") - .setOptionalBytes(ByteString.copyFromUtf8("y")) - .setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR) - .build(); + message = + TestAllTypes.newBuilder() + .setOptionalInt32(1) + .setOptionalString("x") + .setOptionalBytes(ByteString.copyFromUtf8("y")) + .setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR) + .build(); assertTrue(message.hasField(optionalInt32Field)); assertTrue(message.hasField(optionalStringField)); assertTrue(message.hasField(optionalBytesField)); @@ -284,7 +360,9 @@ public void testFieldPresenceDynamicMessage() { assertEquals(4, message.getAllFields().size()); // Field set to default value is seen as not present. - message = message.toBuilder() + message = + message + .toBuilder() .setField(optionalInt32Field, 0) .setField(optionalStringField, "") .setField(optionalBytesField, ByteString.EMPTY) @@ -302,8 +380,7 @@ public void testMessageField() { assertFalse(builder.hasOptionalNestedMessage()); assertFalse(builder.build().hasOptionalNestedMessage()); - TestAllTypes.NestedMessage.Builder nestedBuilder = - builder.getOptionalNestedMessageBuilder(); + TestAllTypes.NestedMessage.Builder nestedBuilder = builder.getOptionalNestedMessageBuilder(); assertTrue(builder.hasOptionalNestedMessage()); assertTrue(builder.build().hasOptionalNestedMessage()); @@ -341,8 +418,7 @@ public void testSerializeAndParse() throws Exception { assertTrue(message.hasOptionalNestedMessage()); assertEquals(0, message.getOptionalNestedMessage().getValue()); // The oneof field set to its default value is also present. - assertEquals( - TestAllTypes.OneofFieldCase.ONEOF_INT32, message.getOneofFieldCase()); + assertEquals(TestAllTypes.OneofFieldCase.ONEOF_INT32, message.getOneofFieldCase()); } // Regression test for b/16173397 @@ -376,8 +452,7 @@ public void testIsInitialized() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); // Test optional proto2 message fields. - UnittestProto.TestRequired.Builder proto2Builder = - builder.getOptionalProto2MessageBuilder(); + UnittestProto.TestRequired.Builder proto2Builder = builder.getOptionalProto2MessageBuilder(); assertFalse(builder.isInitialized()); assertFalse(builder.buildPartial().isInitialized()); @@ -404,34 +479,4 @@ public void testIsInitialized() throws Exception { assertTrue(builder.buildPartial().isInitialized()); } - - // Test that unknown fields are dropped. - public void testUnknownFields() throws Exception { - TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - builder.setOptionalInt32(1234); - builder.addRepeatedInt32(5678); - TestAllTypes message = builder.build(); - ByteString data = message.toByteString(); - - TestOptionalFieldsOnly optionalOnlyMessage = - TestOptionalFieldsOnly.parseFrom(data); - // UnknownFieldSet should be empty. - assertEquals( - 0, optionalOnlyMessage.getUnknownFields().toByteString().size()); - assertEquals(1234, optionalOnlyMessage.getOptionalInt32()); - message = TestAllTypes.parseFrom(optionalOnlyMessage.toByteString()); - assertEquals(1234, message.getOptionalInt32()); - // The repeated field is discarded because it's unknown to the optional-only - // message. - assertEquals(0, message.getRepeatedInt32Count()); - - DynamicMessage dynamicOptionalOnlyMessage = - DynamicMessage.getDefaultInstance( - TestOptionalFieldsOnly.getDescriptor()) - .getParserForType().parseFrom(data); - assertEquals( - 0, dynamicOptionalOnlyMessage.getUnknownFields().toByteString().size()); - assertEquals(optionalOnlyMessage.toByteString(), - dynamicOptionalOnlyMessage.toByteString()); - } } diff --git a/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java b/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java index aa36be4977efe..091ac5bb784ed 100644 --- a/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java @@ -32,6 +32,7 @@ import static java.util.Arrays.asList; +import com.google.protobuf.Internal.FloatList; import java.util.Collections; import java.util.ConcurrentModificationException; import java.util.Iterator; @@ -44,10 +45,8 @@ */ public class FloatArrayListTest extends TestCase { - private static final FloatArrayList UNARY_LIST = - newImmutableFloatArrayList(1); - private static final FloatArrayList TERTIARY_LIST = - newImmutableFloatArrayList(1, 2, 3); + private static final FloatArrayList UNARY_LIST = newImmutableFloatArrayList(1); + private static final FloatArrayList TERTIARY_LIST = newImmutableFloatArrayList(1, 2, 3); private FloatArrayList list; @@ -77,10 +76,10 @@ public void testModificationWithIteration() { list.addAll(asList(1F, 2F, 3F, 4F)); Iterator iterator = list.iterator(); assertEquals(4, list.size()); - assertEquals(1F, (float) list.get(0)); - assertEquals(1F, (float) iterator.next()); + assertEquals(1F, (float) list.get(0), 0.0f); + assertEquals(1F, (float) iterator.next(), 0.0f); list.set(0, 1F); - assertEquals(2F, (float) iterator.next()); + assertEquals(2F, (float) iterator.next(), 0.0f); list.remove(0); try { @@ -101,9 +100,9 @@ public void testModificationWithIteration() { } public void testGet() { - assertEquals(1F, (float) TERTIARY_LIST.get(0)); - assertEquals(2F, (float) TERTIARY_LIST.get(1)); - assertEquals(3F, (float) TERTIARY_LIST.get(2)); + assertEquals(1F, (float) TERTIARY_LIST.get(0), 0.0f); + assertEquals(2F, (float) TERTIARY_LIST.get(1), 0.0f); + assertEquals(3F, (float) TERTIARY_LIST.get(2), 0.0f); try { TERTIARY_LIST.get(-1); @@ -121,9 +120,9 @@ public void testGet() { } public void testGetFloat() { - assertEquals(1F, TERTIARY_LIST.getFloat(0)); - assertEquals(2F, TERTIARY_LIST.getFloat(1)); - assertEquals(3F, TERTIARY_LIST.getFloat(2)); + assertEquals(1F, TERTIARY_LIST.getFloat(0), 0.0f); + assertEquals(2F, TERTIARY_LIST.getFloat(1), 0.0f); + assertEquals(3F, TERTIARY_LIST.getFloat(2), 0.0f); try { TERTIARY_LIST.get(-1); @@ -140,6 +139,68 @@ public void testGetFloat() { } } + public void testIndexOf_nullElement() { + assertEquals(-1, TERTIARY_LIST.indexOf(null)); + } + + public void testIndexOf_incompatibleElementType() { + assertEquals(-1, TERTIARY_LIST.indexOf(new Object())); + } + + public void testIndexOf_notInList() { + assertEquals(-1, UNARY_LIST.indexOf(2F)); + } + + public void testIndexOf_notInListWithDuplicates() { + FloatArrayList listWithDupes = newImmutableFloatArrayList(1F, 1F); + assertEquals(-1, listWithDupes.indexOf(2F)); + } + + public void testIndexOf_inList() { + assertEquals(1, TERTIARY_LIST.indexOf(2F)); + } + + public void testIndexOf_inListWithDuplicates_matchAtHead() { + FloatArrayList listWithDupes = newImmutableFloatArrayList(1F, 1F, 2F); + assertEquals(0, listWithDupes.indexOf(1F)); + } + + public void testIndexOf_inListWithDuplicates_matchMidList() { + FloatArrayList listWithDupes = newImmutableFloatArrayList(2F, 1F, 1F, 2F); + assertEquals(1, listWithDupes.indexOf(1F)); + } + + public void testContains_nullElement() { + assertEquals(false, TERTIARY_LIST.contains(null)); + } + + public void testContains_incompatibleElementType() { + assertEquals(false, TERTIARY_LIST.contains(new Object())); + } + + public void testContains_notInList() { + assertEquals(false, UNARY_LIST.contains(2F)); + } + + public void testContains_notInListWithDuplicates() { + FloatArrayList listWithDupes = newImmutableFloatArrayList(1F, 1F); + assertEquals(false, listWithDupes.contains(2F)); + } + + public void testContains_inList() { + assertEquals(true, TERTIARY_LIST.contains(2F)); + } + + public void testContains_inListWithDuplicates_matchAtHead() { + FloatArrayList listWithDupes = newImmutableFloatArrayList(1F, 1F, 2F); + assertEquals(true, listWithDupes.contains(1F)); + } + + public void testContains_inListWithDuplicates_matchMidList() { + FloatArrayList listWithDupes = newImmutableFloatArrayList(2F, 1F, 1F, 2F); + assertEquals(true, listWithDupes.contains(1F)); + } + public void testSize() { assertEquals(0, FloatArrayList.emptyList().size()); assertEquals(1, UNARY_LIST.size()); @@ -162,11 +223,11 @@ public void testSet() { list.addFloat(2); list.addFloat(4); - assertEquals(2F, (float) list.set(0, 3F)); - assertEquals(3F, list.getFloat(0)); + assertEquals(2F, (float) list.set(0, 3F), 0.0f); + assertEquals(3F, list.getFloat(0), 0.0f); - assertEquals(4F, (float) list.set(1, 0F)); - assertEquals(0F, list.getFloat(1)); + assertEquals(4F, (float) list.set(1, 0F), 0.0f); + assertEquals(0F, list.getFloat(1), 0.0f); try { list.set(-1, 0F); @@ -187,11 +248,11 @@ public void testSetFloat() { list.addFloat(1); list.addFloat(3); - assertEquals(1F, list.setFloat(0, 0)); - assertEquals(0F, list.getFloat(0)); + assertEquals(1F, list.setFloat(0, 0), 0.0f); + assertEquals(0F, list.getFloat(0), 0.0f); - assertEquals(3F, list.setFloat(1, 0)); - assertEquals(0F, list.getFloat(1)); + assertEquals(3F, list.setFloat(1, 0), 0.0f); + assertEquals(0F, list.getFloat(1), 0.0f); try { list.setFloat(-1, 0); @@ -224,9 +285,7 @@ public void testAdd() { for (int i = 0; i < 6; i++) { list.add(Float.valueOf(5 + i)); } - assertEquals( - asList(0F, 1F, 4F, 2F, 3F, 5F, 6F, 7F, 8F, 9F, 10F), - list); + assertEquals(asList(0F, 1F, 4F, 2F, 3F, 5F, 6F, 7F, 8F, 9F, 10F), list); try { list.add(-1, 5F); @@ -256,8 +315,8 @@ public void testAddAll() { assertTrue(list.addAll(Collections.singleton(1F))); assertEquals(1, list.size()); - assertEquals(1F, (float) list.get(0)); - assertEquals(1F, list.getFloat(0)); + assertEquals(1F, (float) list.get(0), 0.0f); + assertEquals(1F, list.getFloat(0), 0.0f); assertTrue(list.addAll(asList(2F, 3F, 4F, 5F, 6F))); assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F), list); @@ -269,9 +328,18 @@ public void testAddAll() { assertFalse(list.addAll(FloatArrayList.emptyList())); } + public void testEquals() { + FloatArrayList list1 = new FloatArrayList(); + FloatArrayList list2 = new FloatArrayList(); + + list1.addFloat(Float.intBitsToFloat(0xff800001)); + list2.addFloat(Float.intBitsToFloat(0xff800002)); + assertEquals(list1, list2); + } + public void testRemove() { list.addAll(TERTIARY_LIST); - assertEquals(1F, (float) list.remove(0)); + assertEquals(1F, (float) list.remove(0), 0.0f); assertEquals(asList(2F, 3F), list); assertTrue(list.remove(Float.valueOf(3))); @@ -280,7 +348,7 @@ public void testRemove() { assertFalse(list.remove(Float.valueOf(3))); assertEquals(asList(2F), list); - assertEquals(2F, (float) list.remove(0)); + assertEquals(2F, (float) list.remove(0), 0.0f); assertEquals(asList(), list); try { @@ -297,7 +365,30 @@ public void testRemove() { } } - private void assertImmutable(FloatArrayList list) { + public void testRemoveEnd_listAtCapacity() { + FloatList toRemove = FloatArrayList.emptyList().mutableCopyWithCapacity(1); + toRemove.addFloat(3); + toRemove.remove(0); + assertEquals(0, toRemove.size()); + } + + public void testRemove_listAtCapacity() { + FloatList toRemove = FloatArrayList.emptyList().mutableCopyWithCapacity(2); + toRemove.addFloat(3); + toRemove.addFloat(4); + toRemove.remove(0); + assertEquals(1, toRemove.size()); + assertEquals(4F, (float) toRemove.get(0)); + } + + public void testSublistRemoveEndOfCapacity() { + FloatList toRemove = FloatArrayList.emptyList().mutableCopyWithCapacity(1); + toRemove.addFloat(3); + toRemove.subList(0, 1).clear(); + assertEquals(0, toRemove.size()); + } + + private void assertImmutable(FloatList list) { if (list.contains(1F)) { throw new RuntimeException("Cannot test the immutability of lists that contain 1."); } diff --git a/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java b/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java index b7eaebf5e28fb..baa6d0867012c 100644 --- a/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java +++ b/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java @@ -31,11 +31,10 @@ package com.google.protobuf; /** - * A prerun for a test suite that allows running the full protocol buffer - * tests in a mode that disables the optimization for not using - * {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder} until they are - * requested. This allows us to run all the tests through both code paths - * and ensures that both code paths produce identical results. + * A prerun for a test suite that allows running the full protocol buffer tests in a mode that + * disables the optimization for not using {@link RepeatedFieldBuilder} and {@link + * SingleFieldBuilder} until they are requested. This allows us to run all the tests through both + * code paths and ensures that both code paths produce identical results. * * @author jonp@google.com (Jon Perlow) */ 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 a4311d17dbe32..9261a36122088 100644 --- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java +++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java @@ -32,19 +32,14 @@ import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; -import com.google.protobuf.UnittestLite.TestAllExtensionsLite; import com.google.protobuf.test.UnittestImport; import protobuf_unittest.EnumWithNoOuter; import protobuf_unittest.MessageWithNoOuter; import protobuf_unittest.MultipleFilesTestProto; import protobuf_unittest.NestedExtension.MyNestedExtension; -import protobuf_unittest.NestedExtensionLite.MyNestedExtensionLite; import protobuf_unittest.NonNestedExtension; import protobuf_unittest.NonNestedExtension.MessageToBeExtended; import protobuf_unittest.NonNestedExtension.MyNonNestedExtension; -import protobuf_unittest.NonNestedExtensionLite; -import protobuf_unittest.NonNestedExtensionLite.MessageLiteToBeExtended; -import protobuf_unittest.NonNestedExtensionLite.MyNonNestedExtensionLite; import protobuf_unittest.OuterClassNameTest2OuterClass; import protobuf_unittest.OuterClassNameTest3OuterClass; import protobuf_unittest.OuterClassNameTestOuterClass; @@ -76,20 +71,180 @@ import junit.framework.TestCase; /** - * Unit test for generated messages and generated code. See also - * {@link MessageTest}, which tests some generated message functionality. + * Unit test for generated messages and generated code. See also {@link MessageTest}, which tests + * some generated message functionality. * * @author kenton@google.com Kenton Varda */ public class GeneratedMessageTest extends TestCase { TestUtil.ReflectionTester reflectionTester = - new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null); + new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null); + + @Override + public void tearDown() { + GeneratedMessageV3.setAlwaysUseFieldBuildersForTesting(false); + } + + public void testGetFieldBuilderForExtensionField() { + TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); + Message.Builder fieldBuilder = + builder.getFieldBuilder(UnittestProto.optionalNestedMessageExtension.getDescriptor()); + int expected = 7432; + FieldDescriptor field = + NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER); + fieldBuilder.setField(field, expected); + assertEquals( + expected, + builder.build().getExtension(UnittestProto.optionalNestedMessageExtension).getBb()); + + // fieldBuilder still updates the builder after builder build() has been called. + expected += 100; + fieldBuilder.setField(field, expected); + assertEquals( + expected, + builder.build().getExtension(UnittestProto.optionalNestedMessageExtension).getBb()); + } + + public void testGetFieldBuilderWithExistingMessage() { + TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); + builder.setExtension( + UnittestProto.optionalNestedMessageExtension, + NestedMessage.newBuilder().setBb(123).build()); + Message.Builder fieldBuilder = + builder.getFieldBuilder(UnittestProto.optionalNestedMessageExtension.getDescriptor()); + int expected = 7432; + FieldDescriptor field = + NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER); + fieldBuilder.setField(field, expected); + assertEquals( + expected, + builder.build().getExtension(UnittestProto.optionalNestedMessageExtension).getBb()); + + // fieldBuilder still updates the builder after builder build() has been called. + expected += 100; + fieldBuilder.setField(field, expected); + assertEquals( + expected, + builder.build().getExtension(UnittestProto.optionalNestedMessageExtension).getBb()); + } + + public void testGetFieldBuilderWithExistingBuilder() { + TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); + NestedMessage.Builder nestedMessageBuilder = NestedMessage.newBuilder().setBb(123); + builder.setField( + UnittestProto.optionalNestedMessageExtension.getDescriptor(), nestedMessageBuilder); + Message.Builder fieldBuilder = + builder.getFieldBuilder(UnittestProto.optionalNestedMessageExtension.getDescriptor()); + int expected = 7432; + FieldDescriptor field = + NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER); + fieldBuilder.setField(field, expected); + assertEquals( + expected, + builder.build().getExtension(UnittestProto.optionalNestedMessageExtension).getBb()); + + // Existing nestedMessageBuilder will also update builder. + expected += 100; + nestedMessageBuilder.setBb(expected); + assertEquals( + expected, + builder.build().getExtension(UnittestProto.optionalNestedMessageExtension).getBb()); + + // fieldBuilder still updates the builder. + expected += 100; + fieldBuilder.setField(field, expected); + assertEquals( + expected, + builder.build().getExtension(UnittestProto.optionalNestedMessageExtension).getBb()); + } + + public void testGetRepeatedFieldBuilderForExtensionField() { + TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); + builder.addExtension( + UnittestProto.repeatedNestedMessageExtension, + NestedMessage.newBuilder().setBb(123).build()); + Message.Builder fieldBuilder = + builder.getRepeatedFieldBuilder( + UnittestProto.repeatedNestedMessageExtension.getDescriptor(), 0); + int expected = 7432; + FieldDescriptor field = + NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER); + fieldBuilder.setField(field, expected); + assertEquals( + expected, + builder.build().getExtension(UnittestProto.repeatedNestedMessageExtension, 0).getBb()); + + // fieldBuilder still updates the builder after builder build() has been called. + expected += 100; + fieldBuilder.setField(field, expected); + assertEquals( + expected, + builder.build().getExtension(UnittestProto.repeatedNestedMessageExtension, 0).getBb()); + } + + public void testGetRepeatedFieldBuilderForExistingBuilder() { + TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); + NestedMessage.Builder nestedMessageBuilder = NestedMessage.newBuilder().setBb(123); + builder.addRepeatedField( + UnittestProto.repeatedNestedMessageExtension.getDescriptor(), nestedMessageBuilder); + Message.Builder fieldBuilder = + builder.getRepeatedFieldBuilder( + UnittestProto.repeatedNestedMessageExtension.getDescriptor(), 0); + int expected = 7432; + FieldDescriptor field = + NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER); + fieldBuilder.setField(field, expected); + assertEquals( + expected, + builder.build().getExtension(UnittestProto.repeatedNestedMessageExtension, 0).getBb()); + + // Existing nestedMessageBuilder will also update builder. + expected += 100; + nestedMessageBuilder.setBb(expected); + assertEquals( + expected, + builder.build().getExtension(UnittestProto.repeatedNestedMessageExtension, 0).getBb()); + + // fieldBuilder still updates the builder. + expected += 100; + fieldBuilder.setField(field, expected); + assertEquals( + expected, + builder.build().getExtension(UnittestProto.repeatedNestedMessageExtension, 0).getBb()); + } + + public void testGetExtensionFieldOutOfBound() { + TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); + try { + builder.getRepeatedField(UnittestProto.repeatedNestedMessageExtension.getDescriptor(), 0); + fail("Expected IndexOutOfBoundsException to be thrown"); + } catch (IndexOutOfBoundsException expected) { + } + try { + builder.getExtension(UnittestProto.repeatedNestedMessageExtension, 0); + fail("Expected IndexOutOfBoundsException to be thrown"); + } catch (IndexOutOfBoundsException expected) { + } + TestAllExtensions extensionsMessage = builder.build(); + try { + extensionsMessage.getRepeatedField( + UnittestProto.repeatedNestedMessageExtension.getDescriptor(), 0); + fail("Expected IndexOutOfBoundsException to be thrown"); + } catch (IndexOutOfBoundsException expected) { + } + try { + extensionsMessage.getExtension(UnittestProto.repeatedNestedMessageExtension, 0); + fail("Expected IndexOutOfBoundsException to be thrown"); + } catch (IndexOutOfBoundsException expected) { + } + } public void testDefaultInstance() throws Exception { - assertSame(TestAllTypes.getDefaultInstance(), - TestAllTypes.getDefaultInstance().getDefaultInstanceForType()); - assertSame(TestAllTypes.getDefaultInstance(), - TestAllTypes.newBuilder().getDefaultInstanceForType()); + assertSame( + TestAllTypes.getDefaultInstance(), + TestAllTypes.getDefaultInstance().getDefaultInstanceForType()); + assertSame( + TestAllTypes.getDefaultInstance(), TestAllTypes.newBuilder().getDefaultInstanceForType()); } public void testMessageOrBuilder() throws Exception { @@ -115,10 +270,8 @@ public void testUsingBuilderMultipleTimes() throws Exception { assertEquals(100, value1.getOptionalSfixed64()); assertEquals(100, value1.getRepeatedInt32(0)); - assertEquals(UnittestImport.ImportEnum.IMPORT_BAR, - value1.getOptionalImportEnum()); - assertEquals(UnittestImport.ImportEnum.IMPORT_BAR, - value1.getRepeatedImportEnum(0)); + assertEquals(UnittestImport.ImportEnum.IMPORT_BAR, value1.getOptionalImportEnum()); + assertEquals(UnittestImport.ImportEnum.IMPORT_BAR, value1.getRepeatedImportEnum(0)); assertEquals(1, value1.getOptionalForeignMessage().getC()); assertEquals(1, value1.getRepeatedForeignMessage(0).getC()); @@ -135,20 +288,16 @@ public void testUsingBuilderMultipleTimes() throws Exception { // Make sure value1 didn't change. assertEquals(100, value1.getOptionalSfixed64()); assertEquals(100, value1.getRepeatedInt32(0)); - assertEquals(UnittestImport.ImportEnum.IMPORT_BAR, - value1.getOptionalImportEnum()); - assertEquals(UnittestImport.ImportEnum.IMPORT_BAR, - value1.getRepeatedImportEnum(0)); + assertEquals(UnittestImport.ImportEnum.IMPORT_BAR, value1.getOptionalImportEnum()); + assertEquals(UnittestImport.ImportEnum.IMPORT_BAR, value1.getRepeatedImportEnum(0)); assertEquals(1, value1.getOptionalForeignMessage().getC()); assertEquals(1, value1.getRepeatedForeignMessage(0).getC()); // Make sure value2 is correct assertEquals(200, value2.getOptionalSfixed64()); assertEquals(200, value2.getRepeatedInt32(0)); - assertEquals(UnittestImport.ImportEnum.IMPORT_FOO, - value2.getOptionalImportEnum()); - assertEquals(UnittestImport.ImportEnum.IMPORT_FOO, - value2.getRepeatedImportEnum(0)); + assertEquals(UnittestImport.ImportEnum.IMPORT_FOO, value2.getOptionalImportEnum()); + assertEquals(UnittestImport.ImportEnum.IMPORT_FOO, value2.getRepeatedImportEnum(0)); assertEquals(2, value2.getOptionalForeignMessage().getC()); assertEquals(2, value2.getRepeatedForeignMessage(0).getC()); } @@ -162,8 +311,7 @@ public void testProtosShareRepeatedArraysIfDidntChange() throws Exception { TestAllTypes value2 = value1.toBuilder().build(); assertSame(value1.getRepeatedInt32List(), value2.getRepeatedInt32List()); - assertSame(value1.getRepeatedForeignMessageList(), - value2.getRepeatedForeignMessageList()); + assertSame(value1.getRepeatedForeignMessageList(), value2.getRepeatedForeignMessageList()); } public void testRepeatedArraysAreImmutable() throws Exception { @@ -176,7 +324,6 @@ public void testRepeatedArraysAreImmutable() throws Exception { assertIsUnmodifiable(builder.getRepeatedForeignMessageList()); assertIsUnmodifiable(builder.getRepeatedFloatList()); - TestAllTypes value = builder.build(); assertIsUnmodifiable(value.getRepeatedInt32List()); assertIsUnmodifiable(value.getRepeatedImportEnumList()); @@ -244,8 +391,7 @@ public void testSettersRejectNull() throws Exception { // We expect this exception. } try { - builder.setOptionalNestedMessage( - (TestAllTypes.NestedMessage.Builder) null); + builder.setOptionalNestedMessage((TestAllTypes.NestedMessage.Builder) null); fail("Exception was not thrown"); } catch (NullPointerException e) { // We expect this exception. @@ -275,8 +421,7 @@ public void testSettersRejectNull() throws Exception { // We expect this exception. } try { - builder.addRepeatedNestedMessage( - (TestAllTypes.NestedMessage.Builder) null); + builder.addRepeatedNestedMessage((TestAllTypes.NestedMessage.Builder) null); fail("Exception was not thrown"); } catch (NullPointerException e) { // We expect this exception. @@ -318,10 +463,8 @@ public void testRepeatedSettersRejectNull() throws Exception { // We expect this exception. } - builder.addRepeatedNestedMessage( - TestAllTypes.NestedMessage.newBuilder().setBb(218).build()); - builder.addRepeatedNestedMessage( - TestAllTypes.NestedMessage.newBuilder().setBb(456).build()); + builder.addRepeatedNestedMessage(TestAllTypes.NestedMessage.newBuilder().setBb(218).build()); + builder.addRepeatedNestedMessage(TestAllTypes.NestedMessage.newBuilder().setBb(456).build()); try { builder.setRepeatedNestedMessage(1, (TestAllTypes.NestedMessage) null); fail("Exception was not thrown"); @@ -329,8 +472,7 @@ public void testRepeatedSettersRejectNull() throws Exception { // We expect this exception. } try { - builder.setRepeatedNestedMessage( - 1, (TestAllTypes.NestedMessage.Builder) null); + builder.setRepeatedNestedMessage(1, (TestAllTypes.NestedMessage.Builder) null); fail("Exception was not thrown"); } catch (NullPointerException e) { // We expect this exception. @@ -352,14 +494,12 @@ public void testRepeatedAppend() throws Exception { builder.addAllRepeatedInt32(Arrays.asList(1, 2, 3, 4)); builder.addAllRepeatedForeignEnum(Arrays.asList(ForeignEnum.FOREIGN_BAZ)); - ForeignMessage foreignMessage = - ForeignMessage.newBuilder().setC(12).build(); + ForeignMessage foreignMessage = ForeignMessage.newBuilder().setC(12).build(); builder.addAllRepeatedForeignMessage(Arrays.asList(foreignMessage)); TestAllTypes message = builder.build(); assertEquals(message.getRepeatedInt32List(), Arrays.asList(1, 2, 3, 4)); - assertEquals(message.getRepeatedForeignEnumList(), - Arrays.asList(ForeignEnum.FOREIGN_BAZ)); + assertEquals(message.getRepeatedForeignEnumList(), Arrays.asList(ForeignEnum.FOREIGN_BAZ)); assertEquals(1, message.getRepeatedForeignMessageCount()); assertEquals(12, message.getRepeatedForeignMessage(0).getC()); } @@ -367,19 +507,16 @@ public void testRepeatedAppend() throws Exception { public void testRepeatedAppendRejectsNull() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - ForeignMessage foreignMessage = - ForeignMessage.newBuilder().setC(12).build(); + ForeignMessage foreignMessage = ForeignMessage.newBuilder().setC(12).build(); try { - builder.addAllRepeatedForeignMessage( - Arrays.asList(foreignMessage, (ForeignMessage) null)); + builder.addAllRepeatedForeignMessage(Arrays.asList(foreignMessage, (ForeignMessage) null)); fail("Exception was not thrown"); } catch (NullPointerException e) { // We expect this exception. } try { - builder.addAllRepeatedForeignEnum( - Arrays.asList(ForeignEnum.FOREIGN_BAZ, null)); + builder.addAllRepeatedForeignEnum(Arrays.asList(ForeignEnum.FOREIGN_BAZ, null)); fail("Exception was not thrown"); } catch (NullPointerException e) { // We expect this exception. @@ -399,20 +536,22 @@ public void testRepeatedAppendRejectsNull() throws Exception { // We expect this exception. } } - + public void testRepeatedAppendIterateOnlyOnce() throws Exception { // Create a Iterable that can only be iterated once. - Iterable stringIterable = new Iterable() { - private boolean called = false; - @Override - public Iterator iterator() { - if (called) { - throw new IllegalStateException(); - } - called = true; - return Arrays.asList("one", "two", "three").iterator(); - } - }; + Iterable stringIterable = + new Iterable() { + private boolean called = false; + + @Override + public Iterator iterator() { + if (called) { + throw new IllegalStateException(); + } + called = true; + return Arrays.asList("one", "two", "three").iterator(); + } + }; TestAllTypes.Builder builder = TestAllTypes.newBuilder(); builder.addAllRepeatedString(stringIterable); assertEquals(3, builder.getRepeatedStringCount()); @@ -439,29 +578,31 @@ public void testMergeFromOtherRejectsNull() throws Exception { } public void testSettingForeignMessageUsingBuilder() throws Exception { - TestAllTypes message = TestAllTypes.newBuilder() - // Pass builder for foreign message instance. - .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(123)) - .build(); - TestAllTypes expectedMessage = TestAllTypes.newBuilder() - // Create expected version passing foreign message instance explicitly. - .setOptionalForeignMessage( - ForeignMessage.newBuilder().setC(123).build()) - .build(); + TestAllTypes message = + TestAllTypes.newBuilder() + // Pass builder for foreign message instance. + .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(123)) + .build(); + TestAllTypes expectedMessage = + TestAllTypes.newBuilder() + // Create expected version passing foreign message instance explicitly. + .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(123).build()) + .build(); // TODO(ngd): Upgrade to using real #equals method once implemented assertEquals(expectedMessage.toString(), message.toString()); } public void testSettingRepeatedForeignMessageUsingBuilder() throws Exception { - TestAllTypes message = TestAllTypes.newBuilder() - // Pass builder for foreign message instance. - .addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(456)) - .build(); - TestAllTypes expectedMessage = TestAllTypes.newBuilder() - // Create expected version passing foreign message instance explicitly. - .addRepeatedForeignMessage( - ForeignMessage.newBuilder().setC(456).build()) - .build(); + TestAllTypes message = + TestAllTypes.newBuilder() + // Pass builder for foreign message instance. + .addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(456)) + .build(); + TestAllTypes expectedMessage = + TestAllTypes.newBuilder() + // Create expected version passing foreign message instance explicitly. + .addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(456).build()) + .build(); assertEquals(expectedMessage.toString(), message.toString()); } @@ -469,14 +610,13 @@ public void testDefaults() throws Exception { TestUtil.assertClear(TestAllTypes.getDefaultInstance()); TestUtil.assertClear(TestAllTypes.newBuilder().build()); - TestExtremeDefaultValues message = - TestExtremeDefaultValues.getDefaultInstance(); + TestExtremeDefaultValues message = TestExtremeDefaultValues.getDefaultInstance(); assertEquals("\u1234", message.getUtf8String()); - assertEquals(Double.POSITIVE_INFINITY, message.getInfDouble()); - assertEquals(Double.NEGATIVE_INFINITY, message.getNegInfDouble()); + assertEquals(Double.POSITIVE_INFINITY, message.getInfDouble(), 0.0); + assertEquals(Double.NEGATIVE_INFINITY, message.getNegInfDouble(), 0.0); assertTrue(Double.isNaN(message.getNanDouble())); - assertEquals(Float.POSITIVE_INFINITY, message.getInfFloat()); - assertEquals(Float.NEGATIVE_INFINITY, message.getNegInfFloat()); + assertEquals(Float.POSITIVE_INFINITY, message.getInfFloat(), 0.0f); + assertEquals(Float.NEGATIVE_INFINITY, message.getNegInfFloat(), 0.0f); assertTrue(Float.isNaN(message.getNanFloat())); assertEquals("? ? ?? ?? ??? ??/ ??-", message.getCppTrigraph()); } @@ -528,19 +668,15 @@ public void testReflectionRepeatedSettersRejectNull() throws Exception { } public void testReflectionDefaults() throws Exception { - reflectionTester.assertClearViaReflection( - TestAllTypes.getDefaultInstance()); - reflectionTester.assertClearViaReflection( - TestAllTypes.newBuilder().build()); + reflectionTester.assertClearViaReflection(TestAllTypes.getDefaultInstance()); + reflectionTester.assertClearViaReflection(TestAllTypes.newBuilder().build()); } public void testReflectionGetOneof() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); reflectionTester.setAllFieldsViaReflection(builder); - Descriptors.OneofDescriptor oneof = - TestAllTypes.getDescriptor().getOneofs().get(0); - Descriptors.FieldDescriptor field = - TestAllTypes.getDescriptor().findFieldByName("oneof_bytes"); + Descriptors.OneofDescriptor oneof = TestAllTypes.getDescriptor().getOneofs().get(0); + Descriptors.FieldDescriptor field = TestAllTypes.getDescriptor().findFieldByName("oneof_bytes"); assertSame(field, builder.getOneofFieldDescriptor(oneof)); TestAllTypes message = builder.build(); @@ -550,10 +686,8 @@ public void testReflectionGetOneof() throws Exception { public void testReflectionClearOneof() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); reflectionTester.setAllFieldsViaReflection(builder); - Descriptors.OneofDescriptor oneof = - TestAllTypes.getDescriptor().getOneofs().get(0); - Descriptors.FieldDescriptor field = - TestAllTypes.getDescriptor().findFieldByName("oneof_bytes"); + Descriptors.OneofDescriptor oneof = TestAllTypes.getDescriptor().getOneofs().get(0); + Descriptors.FieldDescriptor field = TestAllTypes.getDescriptor().findFieldByName("oneof_bytes"); assertTrue(builder.hasOneof(oneof)); assertTrue(builder.hasField(field)); @@ -563,8 +697,8 @@ public void testReflectionClearOneof() throws Exception { } public void testEnumInterface() throws Exception { - assertTrue(TestAllTypes.getDefaultInstance().getDefaultNestedEnum() - instanceof ProtocolMessageEnum); + assertTrue( + TestAllTypes.getDefaultInstance().getDefaultNestedEnum() instanceof ProtocolMessageEnum); } public void testEnumMap() throws Exception { @@ -579,15 +713,13 @@ public void testEnumMap() throws Exception { public void testParsePackedToUnpacked() throws Exception { TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder(); - TestUnpackedTypes message = - builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build(); + TestUnpackedTypes message = builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build(); TestUtil.assertUnpackedFieldsSet(message); } public void testParseUnpackedToPacked() throws Exception { TestPackedTypes.Builder builder = TestPackedTypes.newBuilder(); - TestPackedTypes message = - builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build(); + TestPackedTypes message = builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build(); TestUtil.assertPackedFieldsSet(message); } @@ -595,8 +727,8 @@ public void testParseUnpackedToPacked() throws Exception { // Extensions. TestUtil.ReflectionTester extensionsReflectionTester = - new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(), - TestUtil.getExtensionRegistry()); + new TestUtil.ReflectionTester( + TestAllExtensions.getDescriptor(), TestUtil.getFullExtensionRegistry()); public void testExtensionMessageOrBuilder() throws Exception { TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); @@ -605,6 +737,29 @@ public void testExtensionMessageOrBuilder() throws Exception { TestUtil.assertAllExtensionsSet(message); } + public void testGetBuilderForExtensionField() { + TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); + Message.Builder fieldBuilder = + builder.newBuilderForField(UnittestProto.optionalNestedMessageExtension.getDescriptor()); + final int expected = 7432; + FieldDescriptor field = + NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER); + fieldBuilder.setField(field, expected); + assertEquals(expected, fieldBuilder.build().getField(field)); + } + + + public void testGetBuilderForNonMessageExtensionField() { + TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); + try { + // This should throw an exception because the extension field is not a message. + builder.newBuilderForField(UnittestProto.optionalInt32Extension.getDescriptor()); + fail("Exception was not thrown"); + } catch (UnsupportedOperationException e) { + // This exception is expected. + } + } + public void testExtensionRepeatedSetters() throws Exception { TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); TestUtil.setAllExtensions(builder); @@ -666,32 +821,29 @@ public void testExtensionReflectionRepeatedSetters() throws Exception { TestUtil.assertRepeatedExtensionsModified(message); } - public void testExtensionReflectionRepeatedSettersRejectNull() - throws Exception { + public void testExtensionReflectionRepeatedSettersRejectNull() throws Exception { TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); - extensionsReflectionTester.assertReflectionRepeatedSettersRejectNull( - builder); + extensionsReflectionTester.assertReflectionRepeatedSettersRejectNull(builder); } public void testExtensionReflectionDefaults() throws Exception { - extensionsReflectionTester.assertClearViaReflection( - TestAllExtensions.getDefaultInstance()); - extensionsReflectionTester.assertClearViaReflection( - TestAllExtensions.newBuilder().build()); + extensionsReflectionTester.assertClearViaReflection(TestAllExtensions.getDefaultInstance()); + extensionsReflectionTester.assertClearViaReflection(TestAllExtensions.newBuilder().build()); } public void testClearExtension() throws Exception { // clearExtension() is not actually used in TestUtil, so try it manually. assertFalse( - TestAllExtensions.newBuilder() - .setExtension(UnittestProto.optionalInt32Extension, 1) - .clearExtension(UnittestProto.optionalInt32Extension) - .hasExtension(UnittestProto.optionalInt32Extension)); - assertEquals(0, - TestAllExtensions.newBuilder() - .addExtension(UnittestProto.repeatedInt32Extension, 1) - .clearExtension(UnittestProto.repeatedInt32Extension) - .getExtensionCount(UnittestProto.repeatedInt32Extension)); + TestAllExtensions.newBuilder() + .setExtension(UnittestProto.optionalInt32Extension, 1) + .clearExtension(UnittestProto.optionalInt32Extension) + .hasExtension(UnittestProto.optionalInt32Extension)); + assertEquals( + 0, + TestAllExtensions.newBuilder() + .addExtension(UnittestProto.repeatedInt32Extension, 1) + .clearExtension(UnittestProto.repeatedInt32Extension) + .getExtensionCount(UnittestProto.repeatedInt32Extension)); } public void testExtensionCopy() throws Exception { @@ -702,77 +854,12 @@ public void testExtensionCopy() throws Exception { public void testExtensionMergeFrom() throws Exception { TestAllExtensions original = - TestAllExtensions.newBuilder() - .setExtension(UnittestProto.optionalInt32Extension, 1).build(); - TestAllExtensions merged = - TestAllExtensions.newBuilder().mergeFrom(original).build(); + TestAllExtensions.newBuilder() + .setExtension(UnittestProto.optionalInt32Extension, 1) + .build(); + TestAllExtensions merged = TestAllExtensions.newBuilder().mergeFrom(original).build(); assertTrue(merged.hasExtension(UnittestProto.optionalInt32Extension)); - assertEquals( - 1, (int) merged.getExtension(UnittestProto.optionalInt32Extension)); - } - - // ================================================================= - // Lite Extensions. - - // We test lite extensions directly because they have a separate - // implementation from full extensions. In contrast, we do not test - // lite fields directly since they are implemented exactly the same as - // regular fields. - - public void testLiteExtensionMessageOrBuilder() throws Exception { - TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder(); - TestUtilLite.setAllExtensions(builder); - TestUtil.assertAllExtensionsSet(builder); - - TestAllExtensionsLite message = builder.build(); - TestUtil.assertAllExtensionsSet(message); - } - - public void testLiteExtensionRepeatedSetters() throws Exception { - TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder(); - TestUtilLite.setAllExtensions(builder); - TestUtilLite.modifyRepeatedExtensions(builder); - TestUtil.assertRepeatedExtensionsModified(builder); - - TestAllExtensionsLite message = builder.build(); - TestUtil.assertRepeatedExtensionsModified(message); - } - - public void testLiteExtensionDefaults() throws Exception { - TestUtil.assertExtensionsClear(TestAllExtensionsLite.getDefaultInstance()); - TestUtil.assertExtensionsClear(TestAllExtensionsLite.newBuilder().build()); - } - - public void testClearLiteExtension() throws Exception { - // clearExtension() is not actually used in TestUtil, so try it manually. - assertFalse( - TestAllExtensionsLite.newBuilder() - .setExtension(UnittestLite.optionalInt32ExtensionLite, 1) - .clearExtension(UnittestLite.optionalInt32ExtensionLite) - .hasExtension(UnittestLite.optionalInt32ExtensionLite)); - assertEquals(0, - TestAllExtensionsLite.newBuilder() - .addExtension(UnittestLite.repeatedInt32ExtensionLite, 1) - .clearExtension(UnittestLite.repeatedInt32ExtensionLite) - .getExtensionCount(UnittestLite.repeatedInt32ExtensionLite)); - } - - public void testLiteExtensionCopy() throws Exception { - TestAllExtensionsLite original = TestUtilLite.getAllLiteExtensionsSet(); - TestAllExtensionsLite copy = - TestAllExtensionsLite.newBuilder(original).build(); - TestUtil.assertAllExtensionsSet(copy); - } - - public void testLiteExtensionMergeFrom() throws Exception { - TestAllExtensionsLite original = - TestAllExtensionsLite.newBuilder() - .setExtension(UnittestLite.optionalInt32ExtensionLite, 1).build(); - TestAllExtensionsLite merged = - TestAllExtensionsLite.newBuilder().mergeFrom(original).build(); - assertTrue(merged.hasExtension(UnittestLite.optionalInt32ExtensionLite)); - assertEquals( - 1, (int) merged.getExtension(UnittestLite.optionalInt32ExtensionLite)); + assertEquals(1, (int) merged.getExtension(UnittestProto.optionalInt32Extension)); } // ================================================================= @@ -783,64 +870,69 @@ public void testLiteExtensionMergeFrom() throws Exception { // or messages defined in multiple_files_test.proto because the class loading // order affects initialization process of custom options. public void testEnumValueOptionsInMultipleFilesMode() throws Exception { - assertEquals(12345, EnumWithNoOuter.FOO.getValueDescriptor().getOptions() - .getExtension(MultipleFilesTestProto.enumValueOption).intValue()); + assertEquals( + 12345, + EnumWithNoOuter.FOO + .getValueDescriptor() + .getOptions() + .getExtension(MultipleFilesTestProto.enumValueOption) + .intValue()); } public void testMultipleFilesOption() throws Exception { // We mostly just want to check that things compile. MessageWithNoOuter message = - MessageWithNoOuter.newBuilder() - .setNested(MessageWithNoOuter.NestedMessage.newBuilder().setI(1)) - .addForeign(TestAllTypes.newBuilder().setOptionalInt32(1)) - .setNestedEnum(MessageWithNoOuter.NestedEnum.BAZ) - .setForeignEnum(EnumWithNoOuter.BAR) - .build(); + MessageWithNoOuter.newBuilder() + .setNested(MessageWithNoOuter.NestedMessage.newBuilder().setI(1)) + .addForeign(TestAllTypes.newBuilder().setOptionalInt32(1)) + .setNestedEnum(MessageWithNoOuter.NestedEnum.BAZ) + .setForeignEnum(EnumWithNoOuter.BAR) + .build(); assertEquals(message, MessageWithNoOuter.parseFrom(message.toByteString())); - assertEquals(MultipleFilesTestProto.getDescriptor(), - MessageWithNoOuter.getDescriptor().getFile()); + assertEquals( + MultipleFilesTestProto.getDescriptor(), MessageWithNoOuter.getDescriptor().getFile()); Descriptors.FieldDescriptor field = - MessageWithNoOuter.getDescriptor().findFieldByName("foreign_enum"); - assertEquals(EnumWithNoOuter.BAR.getValueDescriptor(), - message.getField(field)); + MessageWithNoOuter.getDescriptor().findFieldByName("foreign_enum"); + assertEquals(EnumWithNoOuter.BAR.getValueDescriptor(), message.getField(field)); - assertEquals(MultipleFilesTestProto.getDescriptor(), - ServiceWithNoOuter.getDescriptor().getFile()); + assertEquals( + MultipleFilesTestProto.getDescriptor(), ServiceWithNoOuter.getDescriptor().getFile()); assertFalse( - TestAllExtensions.getDefaultInstance().hasExtension( - MultipleFilesTestProto.extensionWithOuter)); + TestAllExtensions.getDefaultInstance() + .hasExtension(MultipleFilesTestProto.extensionWithOuter)); } - public void testOptionalFieldWithRequiredSubfieldsOptimizedForSize() - throws Exception { - TestOptionalOptimizedForSize message = - TestOptionalOptimizedForSize.getDefaultInstance(); + public void testOptionalFieldWithRequiredSubfieldsOptimizedForSize() throws Exception { + TestOptionalOptimizedForSize message = TestOptionalOptimizedForSize.getDefaultInstance(); assertTrue(message.isInitialized()); - message = TestOptionalOptimizedForSize.newBuilder().setO( - TestRequiredOptimizedForSize.newBuilder().buildPartial() - ).buildPartial(); + message = + TestOptionalOptimizedForSize.newBuilder() + .setO(TestRequiredOptimizedForSize.newBuilder().buildPartial()) + .buildPartial(); assertFalse(message.isInitialized()); - message = TestOptionalOptimizedForSize.newBuilder().setO( - TestRequiredOptimizedForSize.newBuilder().setX(5).buildPartial() - ).buildPartial(); + message = + TestOptionalOptimizedForSize.newBuilder() + .setO(TestRequiredOptimizedForSize.newBuilder().setX(5).buildPartial()) + .buildPartial(); assertTrue(message.isInitialized()); } - public void testUninitializedExtensionInOptimizedForSize() - throws Exception { + public void testUninitializedExtensionInOptimizedForSize() throws Exception { TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder(); - builder.setExtension(TestOptimizedForSize.testExtension2, + builder.setExtension( + TestOptimizedForSize.testExtension2, TestRequiredOptimizedForSize.newBuilder().buildPartial()); assertFalse(builder.isInitialized()); assertFalse(builder.buildPartial().isInitialized()); builder = TestOptimizedForSize.newBuilder(); - builder.setExtension(TestOptimizedForSize.testExtension2, + builder.setExtension( + TestOptimizedForSize.testExtension2, TestRequiredOptimizedForSize.newBuilder().setX(10).buildPartial()); assertTrue(builder.isInitialized()); assertTrue(builder.buildPartial().isInitialized()); @@ -871,13 +963,11 @@ public void testExtensionConstantValues() throws Exception { assertEquals(UnittestProto.TestRequired.MULTI_FIELD_NUMBER, 1001); assertEquals(UnittestProto.OPTIONAL_INT32_EXTENSION_FIELD_NUMBER, 1); assertEquals(UnittestProto.OPTIONALGROUP_EXTENSION_FIELD_NUMBER, 16); - assertEquals( - UnittestProto.OPTIONAL_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 18); + assertEquals(UnittestProto.OPTIONAL_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 18); assertEquals(UnittestProto.OPTIONAL_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 21); assertEquals(UnittestProto.REPEATED_INT32_EXTENSION_FIELD_NUMBER, 31); assertEquals(UnittestProto.REPEATEDGROUP_EXTENSION_FIELD_NUMBER, 46); - assertEquals( - UnittestProto.REPEATED_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 48); + assertEquals(UnittestProto.REPEATED_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 48); assertEquals(UnittestProto.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 51); } @@ -886,7 +976,7 @@ public void testRecursiveMessageDefaultInstance() throws Exception { UnittestProto.TestRecursiveMessage.getDefaultInstance(); assertTrue(message != null); assertNotNull(message.getA()); - assertTrue(message.getA() == message); + assertTrue(message.getA().equals(message)); } public void testSerialize() throws Exception { @@ -922,6 +1012,67 @@ public void testSerializePartial() throws Exception { assertEquals(expected, actual); } + public void testDeserializeWithoutClassField() throws Exception { + // serialized form for version <=3.6.0 + // just includes messageClassName and asBytes + + // Int32Value.newBuilder().setValue(123).build() + byte[] int32ValueBytes = + new byte[] { + -84, -19, 0, 5, 115, 114, 0, 55, 99, 111, 109, 46, 103, 111, 111, 103, 108, 101, 46, 112, + 114, 111, 116, 111, 98, 117, 102, 46, 71, 101, 110, 101, 114, 97, 116, 101, 100, 77, 101, + 115, 115, 97, 103, 101, 76, 105, 116, 101, 36, 83, 101, 114, 105, 97, 108, 105, 122, 101, + 100, 70, 111, 114, 109, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 91, 0, 7, 97, 115, 66, 121, 116, + 101, 115, 116, 0, 2, 91, 66, 76, 0, 16, 109, 101, 115, 115, 97, 103, 101, 67, 108, 97, + 115, 115, 78, 97, 109, 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, + 83, 116, 114, 105, 110, 103, 59, 120, 112, 117, 114, 0, 2, 91, 66, -84, -13, 23, -8, 6, 8, + 84, -32, 2, 0, 0, 120, 112, 0, 0, 0, 2, 8, 123, 116, 0, 30, 99, 111, 109, 46, 103, 111, + 111, 103, 108, 101, 46, 112, 114, 111, 116, 111, 98, 117, 102, 46, 73, 110, 116, 51, 50, + 86, 97, 108, 117, 101 + }; + + ByteArrayInputStream bais = new ByteArrayInputStream(int32ValueBytes); + ObjectInputStream in = new ObjectInputStream(bais); + Int32Value int32Value = (Int32Value) in.readObject(); + assertEquals(123, int32Value.getValue()); + } + + public void testDeserializeWithClassField() throws Exception { + // serialized form for version > 3.6.0 + // includes messageClass, messageClassName (for compatibility), and asBytes + + // Int32Value.newBuilder().setValue(123).build() + byte[] int32ValueBytes = + new byte[] { + -84, -19, 0, 5, 115, 114, 0, 55, 99, 111, 109, 46, 103, 111, 111, 103, 108, 101, 46, 112, + 114, 111, 116, 111, 98, 117, 102, 46, 71, 101, 110, 101, 114, 97, 116, 101, 100, 77, 101, + 115, 115, 97, 103, 101, 76, 105, 116, 101, 36, 83, 101, 114, 105, 97, 108, 105, 122, 101, + 100, 70, 111, 114, 109, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 91, 0, 7, 97, 115, 66, 121, 116, + 101, 115, 116, 0, 2, 91, 66, 76, 0, 12, 109, 101, 115, 115, 97, 103, 101, 67, 108, 97, + 115, 115, 116, 0, 17, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 67, 108, 97, 115, + 115, 59, 76, 0, 16, 109, 101, 115, 115, 97, 103, 101, 67, 108, 97, 115, 115, 78, 97, 109, + 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, + 103, 59, 120, 112, 117, 114, 0, 2, 91, 66, -84, -13, 23, -8, 6, 8, 84, -32, 2, 0, 0, 120, + 112, 0, 0, 0, 2, 8, 123, 118, 114, 0, 30, 99, 111, 109, 46, 103, 111, 111, 103, 108, 101, + 46, 112, 114, 111, 116, 111, 98, 117, 102, 46, 73, 110, 116, 51, 50, 86, 97, 108, 117, + 101, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 66, 0, 21, 109, 101, 109, 111, 105, 122, 101, 100, + 73, 115, 73, 110, 105, 116, 105, 97, 108, 105, 122, 101, 100, 73, 0, 6, 118, 97, 108, 117, + 101, 95, 120, 114, 0, 38, 99, 111, 109, 46, 103, 111, 111, 103, 108, 101, 46, 112, 114, + 111, 116, 111, 98, 117, 102, 46, 71, 101, 110, 101, 114, 97, 116, 101, 100, 77, 101, 115, + 115, 97, 103, 101, 86, 51, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 76, 0, 13, 117, 110, 107, 110, + 111, 119, 110, 70, 105, 101, 108, 100, 115, 116, 0, 37, 76, 99, 111, 109, 47, 103, 111, + 111, 103, 108, 101, 47, 112, 114, 111, 116, 111, 98, 117, 102, 47, 85, 110, 107, 110, 111, + 119, 110, 70, 105, 101, 108, 100, 83, 101, 116, 59, 120, 112, 116, 0, 30, 99, 111, 109, + 46, 103, 111, 111, 103, 108, 101, 46, 112, 114, 111, 116, 111, 98, 117, 102, 46, 73, 110, + 116, 51, 50, 86, 97, 108, 117, 101 + }; + + ByteArrayInputStream bais = new ByteArrayInputStream(int32ValueBytes); + ObjectInputStream in = new ObjectInputStream(bais); + Int32Value int32Value = (Int32Value) in.readObject(); + assertEquals(123, int32Value.getValue()); + } + public void testEnumValues() { assertEquals(TestAllTypes.NestedEnum.BAR_VALUE, TestAllTypes.NestedEnum.BAR.getNumber()); assertEquals(TestAllTypes.NestedEnum.BAZ_VALUE, TestAllTypes.NestedEnum.BAZ.getNumber()); @@ -929,43 +1080,33 @@ public void testEnumValues() { } public void testNonNestedExtensionInitialization() { - assertTrue(NonNestedExtension.nonNestedExtension - .getMessageDefaultInstance() instanceof MyNonNestedExtension); - assertEquals("nonNestedExtension", - NonNestedExtension.nonNestedExtension.getDescriptor().getName()); + assertTrue( + NonNestedExtension.nonNestedExtension.getMessageDefaultInstance() + instanceof MyNonNestedExtension); + assertEquals( + "nonNestedExtension", NonNestedExtension.nonNestedExtension.getDescriptor().getName()); } public void testNestedExtensionInitialization() { - assertTrue(MyNestedExtension.recursiveExtension.getMessageDefaultInstance() - instanceof MessageToBeExtended); - assertEquals("recursiveExtension", - MyNestedExtension.recursiveExtension.getDescriptor().getName()); - } - - public void testNonNestedExtensionLiteInitialization() { - assertTrue(NonNestedExtensionLite.nonNestedExtensionLite - .getMessageDefaultInstance() instanceof MyNonNestedExtensionLite); - } - - public void testNestedExtensionLiteInitialization() { - assertTrue(MyNestedExtensionLite.recursiveExtensionLite - .getMessageDefaultInstance() instanceof MessageLiteToBeExtended); + assertTrue( + MyNestedExtension.recursiveExtension.getMessageDefaultInstance() + instanceof MessageToBeExtended); + assertEquals( + "recursiveExtension", MyNestedExtension.recursiveExtension.getDescriptor().getName()); } public void testInvalidations() throws Exception { - GeneratedMessage.enableAlwaysUseFieldBuildersForTesting(); - TestAllTypes.NestedMessage nestedMessage1 = - TestAllTypes.NestedMessage.newBuilder().build(); - TestAllTypes.NestedMessage nestedMessage2 = - TestAllTypes.NestedMessage.newBuilder().build(); + GeneratedMessageV3.setAlwaysUseFieldBuildersForTesting(true); + TestAllTypes.NestedMessage nestedMessage1 = TestAllTypes.NestedMessage.newBuilder().build(); + TestAllTypes.NestedMessage nestedMessage2 = TestAllTypes.NestedMessage.newBuilder().build(); // Set all three flavors (enum, primitive, message and singular/repeated) // and verify no invalidations fired TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - TestAllTypes.Builder builder = (TestAllTypes.Builder) - ((AbstractMessage) TestAllTypes.getDefaultInstance()). - newBuilderForType(mockParent); + TestAllTypes.Builder builder = + (TestAllTypes.Builder) + ((AbstractMessage) TestAllTypes.getDefaultInstance()).newBuilderForType(mockParent); builder.setOptionalInt32(1); builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR); builder.setOptionalNestedMessage(nestedMessage1); @@ -1012,15 +1153,15 @@ public void testInvalidations() throws Exception { builder.addRepeatedNestedMessage(nestedMessage2); builder.addRepeatedNestedMessage(nestedMessage1); assertEquals(6, mockParent.getInvalidationCount()); - } public void testInvalidations_Extensions() throws Exception { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - TestAllExtensions.Builder builder = (TestAllExtensions.Builder) - ((AbstractMessage) TestAllExtensions.getDefaultInstance()). - newBuilderForType(mockParent); + TestAllExtensions.Builder builder = + (TestAllExtensions.Builder) + ((AbstractMessage) TestAllExtensions.getDefaultInstance()) + .newBuilderForType(mockParent); builder.addExtension(UnittestProto.repeatedInt32Extension, 1); builder.setExtension(UnittestProto.repeatedInt32Extension, 0, 2); @@ -1048,25 +1189,19 @@ public void testBaseMessageOrBuilder() { // Mostly just makes sure the base interface exists and has some methods. TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TestAllTypes message = builder.buildPartial(); - TestAllTypesOrBuilder builderAsInterface = (TestAllTypesOrBuilder) builder; TestAllTypesOrBuilder messageAsInterface = (TestAllTypesOrBuilder) message; + assertEquals(messageAsInterface.getDefaultBool(), messageAsInterface.getDefaultBool()); assertEquals( - messageAsInterface.getDefaultBool(), - messageAsInterface.getDefaultBool()); - assertEquals( - messageAsInterface.getOptionalDouble(), - messageAsInterface.getOptionalDouble()); + messageAsInterface.getOptionalDouble(), messageAsInterface.getOptionalDouble(), 0.0); } public void testMessageOrBuilderGetters() { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); // single fields - assertSame(ForeignMessage.getDefaultInstance(), - builder.getOptionalForeignMessageOrBuilder()); - ForeignMessage.Builder subBuilder = - builder.getOptionalForeignMessageBuilder(); + assertSame(ForeignMessage.getDefaultInstance(), builder.getOptionalForeignMessageOrBuilder()); + ForeignMessage.Builder subBuilder = builder.getOptionalForeignMessageBuilder(); assertSame(subBuilder, builder.getOptionalForeignMessageOrBuilder()); // repeated fields @@ -1095,36 +1230,37 @@ public void testMessageOrBuilderGetters() { public void testGetFieldBuilder() { Descriptor descriptor = TestAllTypes.getDescriptor(); - FieldDescriptor fieldDescriptor = - descriptor.findFieldByName("optional_nested_message"); - FieldDescriptor foreignFieldDescriptor = - descriptor.findFieldByName("optional_foreign_message"); - FieldDescriptor importFieldDescriptor = - descriptor.findFieldByName("optional_import_message"); + FieldDescriptor fieldDescriptor = descriptor.findFieldByName("optional_nested_message"); + FieldDescriptor foreignFieldDescriptor = descriptor.findFieldByName("optional_foreign_message"); + FieldDescriptor importFieldDescriptor = descriptor.findFieldByName("optional_import_message"); // Mutate the message with new field builder // Mutate nested message TestAllTypes.Builder builder1 = TestAllTypes.newBuilder(); - Message.Builder fieldBuilder1 = builder1.newBuilderForField(fieldDescriptor) - .mergeFrom((Message) builder1.getField(fieldDescriptor)); + Message.Builder fieldBuilder1 = + builder1 + .newBuilderForField(fieldDescriptor) + .mergeFrom((Message) builder1.getField(fieldDescriptor)); FieldDescriptor subFieldDescriptor1 = fieldBuilder1.getDescriptorForType().findFieldByName("bb"); fieldBuilder1.setField(subFieldDescriptor1, 1); builder1.setField(fieldDescriptor, fieldBuilder1.build()); // Mutate foreign message - Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField( - foreignFieldDescriptor) - .mergeFrom((Message) builder1.getField(foreignFieldDescriptor)); + Message.Builder foreignFieldBuilder1 = + builder1 + .newBuilderForField(foreignFieldDescriptor) + .mergeFrom((Message) builder1.getField(foreignFieldDescriptor)); FieldDescriptor subForeignFieldDescriptor1 = foreignFieldBuilder1.getDescriptorForType().findFieldByName("c"); foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2); builder1.setField(foreignFieldDescriptor, foreignFieldBuilder1.build()); // Mutate import message - Message.Builder importFieldBuilder1 = builder1.newBuilderForField( - importFieldDescriptor) - .mergeFrom((Message) builder1.getField(importFieldDescriptor)); + Message.Builder importFieldBuilder1 = + builder1 + .newBuilderForField(importFieldDescriptor) + .mergeFrom((Message) builder1.getField(importFieldDescriptor)); FieldDescriptor subImportFieldDescriptor1 = importFieldBuilder1.getDescriptorForType().findFieldByName("d"); importFieldBuilder1.setField(subImportFieldDescriptor1, 3); @@ -1142,18 +1278,20 @@ public void testGetFieldBuilder() { builder2.setField(fieldDescriptor, fieldBuilder2.build()); // Mutate foreign message - Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField( - foreignFieldDescriptor) - .mergeFrom((Message) builder2.getField(foreignFieldDescriptor)); + Message.Builder foreignFieldBuilder2 = + builder2 + .newBuilderForField(foreignFieldDescriptor) + .mergeFrom((Message) builder2.getField(foreignFieldDescriptor)); FieldDescriptor subForeignFieldDescriptor2 = foreignFieldBuilder2.getDescriptorForType().findFieldByName("c"); foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2); builder2.setField(foreignFieldDescriptor, foreignFieldBuilder2.build()); // Mutate import message - Message.Builder importFieldBuilder2 = builder2.newBuilderForField( - importFieldDescriptor) - .mergeFrom((Message) builder2.getField(importFieldDescriptor)); + Message.Builder importFieldBuilder2 = + builder2 + .newBuilderForField(importFieldDescriptor) + .mergeFrom((Message) builder2.getField(importFieldDescriptor)); FieldDescriptor subImportFieldDescriptor2 = importFieldBuilder2.getDescriptorForType().findFieldByName("d"); importFieldBuilder2.setField(subImportFieldDescriptor2, 3); @@ -1167,10 +1305,9 @@ public void testGetFieldBuilder() { public void testGetFieldBuilderWithInitializedValue() { Descriptor descriptor = TestAllTypes.getDescriptor(); - FieldDescriptor fieldDescriptor = - descriptor.findFieldByName("optional_nested_message"); + FieldDescriptor fieldDescriptor = descriptor.findFieldByName("optional_nested_message"); - // Before setting field, builder is initialized by default value. + // Before setting field, builder is initialized by default value. TestAllTypes.Builder builder = TestAllTypes.newBuilder(); NestedMessage.Builder fieldBuilder = (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor); @@ -1178,12 +1315,10 @@ public void testGetFieldBuilderWithInitializedValue() { // Setting field value with new field builder instance. builder = TestAllTypes.newBuilder(); - NestedMessage.Builder newFieldBuilder = - builder.getOptionalNestedMessageBuilder(); + NestedMessage.Builder newFieldBuilder = builder.getOptionalNestedMessageBuilder(); newFieldBuilder.setBb(2); // Then get the field builder instance by getFieldBuilder(). - fieldBuilder = - (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor); + fieldBuilder = (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor); // It should contain new value. assertEquals(2, fieldBuilder.getBb()); // These two builder should be equal. @@ -1200,8 +1335,7 @@ public void testGetFieldBuilderNotSupportedException() { // We expect this exception. } try { - builder.getFieldBuilder( - descriptor.findFieldByName("optional_nested_enum")); + builder.getFieldBuilder(descriptor.findFieldByName("optional_nested_enum")); fail("Exception was not thrown"); } catch (UnsupportedOperationException e) { // We expect this exception. @@ -1213,15 +1347,13 @@ public void testGetFieldBuilderNotSupportedException() { // We expect this exception. } try { - builder.getFieldBuilder( - descriptor.findFieldByName("repeated_nested_enum")); + builder.getFieldBuilder(descriptor.findFieldByName("repeated_nested_enum")); fail("Exception was not thrown"); } catch (UnsupportedOperationException e) { // We expect this exception. } try { - builder.getFieldBuilder( - descriptor.findFieldByName("repeated_nested_message")); + builder.getFieldBuilder(descriptor.findFieldByName("repeated_nested_message")); fail("Exception was not thrown"); } catch (UnsupportedOperationException e) { // We expect this exception. @@ -1236,25 +1368,25 @@ public void testConflictingOuterClassName() { // expected name. There is nothing else to test. OuterClassNameTestOuterClass.OuterClassNameTest message = OuterClassNameTestOuterClass.OuterClassNameTest.newBuilder().build(); - assertTrue(message.getDescriptorForType() == - OuterClassNameTestOuterClass.OuterClassNameTest.getDescriptor()); + assertTrue( + message.getDescriptorForType() + == OuterClassNameTestOuterClass.OuterClassNameTest.getDescriptor()); - OuterClassNameTest2OuterClass.TestMessage2.NestedMessage.OuterClassNameTest2 - message2 = OuterClassNameTest2OuterClass.TestMessage2.NestedMessage - .OuterClassNameTest2.newBuilder().build(); + OuterClassNameTest2OuterClass.TestMessage2.NestedMessage.OuterClassNameTest2 message2 = + OuterClassNameTest2OuterClass.TestMessage2.NestedMessage.OuterClassNameTest2.newBuilder() + .build(); assertEquals(0, message2.getSerializedSize()); - OuterClassNameTest3OuterClass.TestMessage3.NestedMessage.OuterClassNameTest3 - enumValue = OuterClassNameTest3OuterClass.TestMessage3.NestedMessage - .OuterClassNameTest3.DUMMY_VALUE; + OuterClassNameTest3OuterClass.TestMessage3.NestedMessage.OuterClassNameTest3 enumValue = + OuterClassNameTest3OuterClass.TestMessage3.NestedMessage.OuterClassNameTest3.DUMMY_VALUE; assertEquals(1, enumValue.getNumber()); } // ================================================================= // oneof generated code test public void testOneofEnumCase() throws Exception { - TestOneof2 message = TestOneof2.newBuilder() - .setFooInt(123).setFooString("foo").setFooCord("bar").build(); + TestOneof2 message = + TestOneof2.newBuilder().setFooInt(123).setFooString("foo").setFooCord("bar").build(); TestUtil.assertAtMostOneFieldSetOneof(message); } @@ -1267,8 +1399,7 @@ public void testClearOneof() throws Exception { public void testSetOneofClearsOthers() throws Exception { TestOneof2.Builder builder = TestOneof2.newBuilder(); - TestOneof2 message = - builder.setFooInt(123).setFooString("foo").buildPartial(); + TestOneof2 message = builder.setFooInt(123).setFooString("foo").buildPartial(); assertTrue(message.hasFooString()); TestUtil.assertAtMostOneFieldSetOneof(message); @@ -1288,8 +1419,10 @@ public void testSetOneofClearsOthers() throws Exception { assertTrue(message.hasFooEnum()); TestUtil.assertAtMostOneFieldSetOneof(message); - message = builder.setFooMessage( - TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).buildPartial(); + message = + builder + .setFooMessage(TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()) + .buildPartial(); assertTrue(message.hasFooMessage()); TestUtil.assertAtMostOneFieldSetOneof(message); @@ -1405,8 +1538,7 @@ public void testOneofTypes() throws Exception { // set TestOneof2.Builder builder = TestOneof2.newBuilder(); assertEquals(0, builder.getFooMessage().getQuxInt()); - builder.setFooMessage( - TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()); + builder.setFooMessage(TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()); assertTrue(builder.hasFooMessage()); assertEquals(234, builder.getFooMessage().getQuxInt()); TestOneof2 message = builder.buildPartial(); @@ -1421,8 +1553,7 @@ public void testOneofTypes() throws Exception { // nested builder builder = TestOneof2.newBuilder(); - assertSame(builder.getFooMessageOrBuilder(), - TestOneof2.NestedMessage.getDefaultInstance()); + assertSame(builder.getFooMessageOrBuilder(), TestOneof2.NestedMessage.getDefaultInstance()); assertFalse(builder.hasFooMessage()); builder.getFooMessageBuilder().setQuxInt(123); assertTrue(builder.hasFooMessage()); @@ -1466,8 +1597,10 @@ public void testOneofMerge() throws Exception { // Message { TestOneof2.Builder builder = TestOneof2.newBuilder(); - TestOneof2 message = builder.setFooMessage( - TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).build(); + TestOneof2 message = + builder + .setFooMessage(TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()) + .build(); TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build(); assertTrue(message2.hasFooMessage()); assertEquals(234, message2.getFooMessage().getQuxInt()); @@ -1508,8 +1641,10 @@ public void testOneofSerialization() throws Exception { // Message { TestOneof2.Builder builder = TestOneof2.newBuilder(); - TestOneof2 message = builder.setFooMessage( - TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).build(); + TestOneof2 message = + builder + .setFooMessage(TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()) + .build(); ByteString serialized = message.toByteString(); TestOneof2 message2 = TestOneof2.parseFrom(serialized); assertTrue(message2.hasFooMessage()); @@ -1531,40 +1666,32 @@ public void testOneofNestedBuilderOnChangePropagation() { public void testGetRepeatedFieldBuilder() { Descriptor descriptor = TestAllTypes.getDescriptor(); - FieldDescriptor fieldDescriptor = - descriptor.findFieldByName("repeated_nested_message"); - FieldDescriptor foreignFieldDescriptor = - descriptor.findFieldByName("repeated_foreign_message"); - FieldDescriptor importFieldDescriptor = - descriptor.findFieldByName("repeated_import_message"); + FieldDescriptor fieldDescriptor = descriptor.findFieldByName("repeated_nested_message"); + FieldDescriptor foreignFieldDescriptor = descriptor.findFieldByName("repeated_foreign_message"); + FieldDescriptor importFieldDescriptor = descriptor.findFieldByName("repeated_import_message"); // Mutate the message with new field builder // Mutate nested message TestAllTypes.Builder builder1 = TestAllTypes.newBuilder(); - Message.Builder fieldBuilder1 = builder1.newBuilderForField( - fieldDescriptor); + Message.Builder fieldBuilder1 = builder1.newBuilderForField(fieldDescriptor); FieldDescriptor subFieldDescriptor1 = fieldBuilder1.getDescriptorForType().findFieldByName("bb"); fieldBuilder1.setField(subFieldDescriptor1, 1); builder1.addRepeatedField(fieldDescriptor, fieldBuilder1.build()); // Mutate foreign message - Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField( - foreignFieldDescriptor); + Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField(foreignFieldDescriptor); FieldDescriptor subForeignFieldDescriptor1 = foreignFieldBuilder1.getDescriptorForType().findFieldByName("c"); foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2); - builder1.addRepeatedField(foreignFieldDescriptor, - foreignFieldBuilder1.build()); + builder1.addRepeatedField(foreignFieldDescriptor, foreignFieldBuilder1.build()); // Mutate import message - Message.Builder importFieldBuilder1 = builder1.newBuilderForField( - importFieldDescriptor); + Message.Builder importFieldBuilder1 = builder1.newBuilderForField(importFieldDescriptor); FieldDescriptor subImportFieldDescriptor1 = importFieldBuilder1.getDescriptorForType().findFieldByName("d"); importFieldBuilder1.setField(subImportFieldDescriptor1, 3); - builder1.addRepeatedField(importFieldDescriptor, - importFieldBuilder1.build()); + builder1.addRepeatedField(importFieldDescriptor, importFieldBuilder1.build()); Message newMessage1 = builder1.build(); @@ -1572,29 +1699,24 @@ public void testGetRepeatedFieldBuilder() { // Mutate nested message TestAllTypes.Builder builder2 = TestAllTypes.newBuilder(); builder2.addRepeatedNestedMessageBuilder(); - Message.Builder fieldBuilder2 = builder2.getRepeatedFieldBuilder( - fieldDescriptor, 0); + Message.Builder fieldBuilder2 = builder2.getRepeatedFieldBuilder(fieldDescriptor, 0); FieldDescriptor subFieldDescriptor2 = fieldBuilder2.getDescriptorForType().findFieldByName("bb"); fieldBuilder2.setField(subFieldDescriptor2, 1); // Mutate foreign message - Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField( - foreignFieldDescriptor); + Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField(foreignFieldDescriptor); FieldDescriptor subForeignFieldDescriptor2 = foreignFieldBuilder2.getDescriptorForType().findFieldByName("c"); foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2); - builder2.addRepeatedField(foreignFieldDescriptor, - foreignFieldBuilder2.build()); + builder2.addRepeatedField(foreignFieldDescriptor, foreignFieldBuilder2.build()); // Mutate import message - Message.Builder importFieldBuilder2 = builder2.newBuilderForField( - importFieldDescriptor); + Message.Builder importFieldBuilder2 = builder2.newBuilderForField(importFieldDescriptor); FieldDescriptor subImportFieldDescriptor2 = importFieldBuilder2.getDescriptorForType().findFieldByName("d"); importFieldBuilder2.setField(subImportFieldDescriptor2, 3); - builder2.addRepeatedField(importFieldDescriptor, - importFieldBuilder2.build()); + builder2.addRepeatedField(importFieldDescriptor, importFieldBuilder2.build()); Message newMessage2 = builder2.build(); @@ -1604,10 +1726,9 @@ public void testGetRepeatedFieldBuilder() { public void testGetRepeatedFieldBuilderWithInitializedValue() { Descriptor descriptor = TestAllTypes.getDescriptor(); - FieldDescriptor fieldDescriptor = - descriptor.findFieldByName("repeated_nested_message"); + FieldDescriptor fieldDescriptor = descriptor.findFieldByName("repeated_nested_message"); - // Before setting field, builder is initialized by default value. + // Before setting field, builder is initialized by default value. TestAllTypes.Builder builder = TestAllTypes.newBuilder(); builder.addRepeatedNestedMessageBuilder(); NestedMessage.Builder fieldBuilder = @@ -1616,12 +1737,10 @@ public void testGetRepeatedFieldBuilderWithInitializedValue() { // Setting field value with new field builder instance. builder = TestAllTypes.newBuilder(); - NestedMessage.Builder newFieldBuilder = - builder.addRepeatedNestedMessageBuilder(); + NestedMessage.Builder newFieldBuilder = builder.addRepeatedNestedMessageBuilder(); newFieldBuilder.setBb(2); // Then get the field builder instance by getRepeatedFieldBuilder(). - fieldBuilder = - (NestedMessage.Builder) builder.getRepeatedFieldBuilder(fieldDescriptor, 0); + fieldBuilder = (NestedMessage.Builder) builder.getRepeatedFieldBuilder(fieldDescriptor, 0); // It should contain new value. assertEquals(2, fieldBuilder.getBb()); // These two builder should be equal. @@ -1638,8 +1757,7 @@ public void testGetRepeatedFieldBuilderNotSupportedException() { // We expect this exception. } try { - builder.getRepeatedFieldBuilder( - descriptor.findFieldByName("repeated_nested_enum"), 0); + builder.getRepeatedFieldBuilder(descriptor.findFieldByName("repeated_nested_enum"), 0); fail("Exception was not thrown"); } catch (UnsupportedOperationException e) { // We expect this exception. @@ -1651,15 +1769,13 @@ public void testGetRepeatedFieldBuilderNotSupportedException() { // We expect this exception. } try { - builder.getRepeatedFieldBuilder( - descriptor.findFieldByName("optional_nested_enum"), 0); + builder.getRepeatedFieldBuilder(descriptor.findFieldByName("optional_nested_enum"), 0); fail("Exception was not thrown"); } catch (UnsupportedOperationException e) { // We expect this exception. } try { - builder.getRepeatedFieldBuilder( - descriptor.findFieldByName("optional_nested_message"), 0); + builder.getRepeatedFieldBuilder(descriptor.findFieldByName("optional_nested_message"), 0); fail("Exception was not thrown"); } catch (UnsupportedOperationException e) { // We expect this exception. diff --git a/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java b/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java index 60c85450c3c7c..2ad94f83de732 100644 --- a/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java @@ -32,6 +32,7 @@ import static java.util.Arrays.asList; +import com.google.protobuf.Internal.IntList; import java.util.Collections; import java.util.ConcurrentModificationException; import java.util.Iterator; @@ -44,10 +45,8 @@ */ public class IntArrayListTest extends TestCase { - private static final IntArrayList UNARY_LIST = - newImmutableIntArrayList(1); - private static final IntArrayList TERTIARY_LIST = - newImmutableIntArrayList(1, 2, 3); + private static final IntArrayList UNARY_LIST = newImmutableIntArrayList(1); + private static final IntArrayList TERTIARY_LIST = newImmutableIntArrayList(1, 2, 3); private IntArrayList list; @@ -140,6 +139,68 @@ public void testGetInt() { } } + public void testIndexOf_nullElement() { + assertEquals(-1, TERTIARY_LIST.indexOf(null)); + } + + public void testIndexOf_incompatibleElementType() { + assertEquals(-1, TERTIARY_LIST.indexOf(new Object())); + } + + public void testIndexOf_notInList() { + assertEquals(-1, UNARY_LIST.indexOf(2)); + } + + public void testIndexOf_notInListWithDuplicates() { + IntArrayList listWithDupes = newImmutableIntArrayList(1, 1); + assertEquals(-1, listWithDupes.indexOf(2)); + } + + public void testIndexOf_inList() { + assertEquals(1, TERTIARY_LIST.indexOf(2)); + } + + public void testIndexOf_inListWithDuplicates_matchAtHead() { + IntArrayList listWithDupes = newImmutableIntArrayList(1, 1, 2); + assertEquals(0, listWithDupes.indexOf(1)); + } + + public void testIndexOf_inListWithDuplicates_matchMidList() { + IntArrayList listWithDupes = newImmutableIntArrayList(2, 1, 1, 2); + assertEquals(1, listWithDupes.indexOf(1)); + } + + public void testContains_nullElement() { + assertEquals(false, TERTIARY_LIST.contains(null)); + } + + public void testContains_incompatibleElementType() { + assertEquals(false, TERTIARY_LIST.contains(new Object())); + } + + public void testContains_notInList() { + assertEquals(false, UNARY_LIST.contains(2)); + } + + public void testContains_notInListWithDuplicates() { + IntArrayList listWithDupes = newImmutableIntArrayList(1, 1); + assertEquals(false, listWithDupes.contains(2)); + } + + public void testContains_inList() { + assertEquals(true, TERTIARY_LIST.contains(2)); + } + + public void testContains_inListWithDuplicates_matchAtHead() { + IntArrayList listWithDupes = newImmutableIntArrayList(1, 1, 2); + assertEquals(true, listWithDupes.contains(1)); + } + + public void testContains_inListWithDuplicates_matchMidList() { + IntArrayList listWithDupes = newImmutableIntArrayList(2, 1, 1, 2); + assertEquals(true, listWithDupes.contains(1)); + } + public void testSize() { assertEquals(0, IntArrayList.emptyList().size()); assertEquals(1, UNARY_LIST.size()); @@ -224,9 +285,7 @@ public void testAdd() { for (int i = 0; i < 6; i++) { list.add(Integer.valueOf(5 + i)); } - assertEquals( - asList(0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10), - list); + assertEquals(asList(0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10), list); try { list.add(-1, 5); @@ -269,6 +328,13 @@ public void testAddAll() { assertFalse(list.addAll(IntArrayList.emptyList())); } + public void testEquals() { + IntArrayList list1 = new IntArrayList(); + IntArrayList list2 = new IntArrayList(); + + assertEquals(list1, list2); + } + public void testRemove() { list.addAll(TERTIARY_LIST); assertEquals(1, (int) list.remove(0)); @@ -297,7 +363,30 @@ public void testRemove() { } } - private void assertImmutable(IntArrayList list) { + public void testRemoveEnd_listAtCapacity() { + IntList toRemove = IntArrayList.emptyList().mutableCopyWithCapacity(1); + toRemove.addInt(3); + toRemove.remove(0); + assertEquals(0, toRemove.size()); + } + + public void testRemove_listAtCapacity() { + IntList toRemove = IntArrayList.emptyList().mutableCopyWithCapacity(2); + toRemove.addInt(3); + toRemove.addInt(4); + toRemove.remove(0); + assertEquals(1, toRemove.size()); + assertEquals(4, (int) toRemove.get(0)); + } + + public void testSublistRemoveEndOfCapacity() { + IntList toRemove = IntArrayList.emptyList().mutableCopyWithCapacity(1); + toRemove.addInt(3); + toRemove.subList(0, 1).clear(); + assertEquals(0, toRemove.size()); + } + + private void assertImmutable(IntList list) { if (list.contains(1)) { throw new RuntimeException("Cannot test the immutability of lists that contain 1."); } diff --git a/java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java b/java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java index 756049b41fd1c..6a737f16217d6 100644 --- a/java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java +++ b/java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java @@ -39,45 +39,36 @@ import com.google.protobuf.IsValidUtf8TestUtil.ByteStringFactory; import com.google.protobuf.IsValidUtf8TestUtil.Shard; - import junit.framework.TestCase; /** - * Tests cases for {@link ByteString#isValidUtf8()}. This includes three - * brute force tests that actually test every permutation of one byte, two byte, - * and three byte sequences to ensure that the method produces the right result - * for every possible byte encoding where "right" means it's consistent with - * java's UTF-8 string encoding/decoding such that the method returns true for - * any sequence that will round trip when converted to a String and then back to - * bytes and will return false for any sequence that will not round trip. - * See also {@link IsValidUtf8FourByteTest}. It also includes some - * other more targeted tests. + * Tests cases for {@link ByteString#isValidUtf8()}. This includes three brute force tests that + * actually test every permutation of one byte, two byte, and three byte sequences to ensure that + * the method produces the right result for every possible byte encoding where "right" means it's + * consistent with java's UTF-8 string encoding/decoding such that the method returns true for any + * sequence that will round trip when converted to a String and then back to bytes and will return + * false for any sequence that will not round trip. See also {@link IsValidUtf8FourByteTest}. It + * also includes some other more targeted tests. * * @author jonp@google.com (Jon Perlow) * @author martinrb@google.com (Martin Buchholz) */ public class IsValidUtf8Test extends TestCase { - /** - * Tests that round tripping of all two byte permutations work. - */ + /** Tests that round tripping of all two byte permutations work. */ public void testIsValidUtf8_1Byte() { testBytes(LITERAL_FACTORY, 1, EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT); testBytes(HEAP_NIO_FACTORY, 1, EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT); testBytes(DIRECT_NIO_FACTORY, 1, EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT); } - /** - * Tests that round tripping of all two byte permutations work. - */ + /** Tests that round tripping of all two byte permutations work. */ public void testIsValidUtf8_2Bytes() { testBytes(LITERAL_FACTORY, 2, IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT); testBytes(HEAP_NIO_FACTORY, 2, IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT); testBytes(DIRECT_NIO_FACTORY, 2, IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT); } - /** - * Tests that round tripping of all three byte permutations work. - */ + /** Tests that round tripping of all three byte permutations work. */ public void testIsValidUtf8_3Bytes() { // Travis' OOM killer doesn't like this test if (System.getenv("TRAVIS") == null) { @@ -88,10 +79,9 @@ public void testIsValidUtf8_3Bytes() { } /** - * Tests that round tripping of a sample of four byte permutations work. - * All permutations are prohibitively expensive to test for automated runs; - * {@link IsValidUtf8FourByteTest} is used for full coverage. This method - * tests specific four-byte cases. + * Tests that round tripping of a sample of four byte permutations work. All permutations are + * prohibitively expensive to test for automated runs; {@link IsValidUtf8FourByteTest} is used for + * full coverage. This method tests specific four-byte cases. */ public void testIsValidUtf8_4BytesSamples() { // Valid 4 byte. @@ -106,9 +96,7 @@ public void testIsValidUtf8_4BytesSamples() { assertInvalidUtf8(0xF4, 0x90, 0xAD, 0xA2); } - /** - * Tests some hard-coded test cases. - */ + /** Tests some hard-coded test cases. */ public void testSomeSequences() { // Empty assertTrue(asBytes("").isValidUtf8()); @@ -149,11 +137,12 @@ private void assertValidUtf8(ByteStringFactory factory, int[] bytes, boolean not assertTrue(not ^ leaf.isValidUtf8()); assertTrue(not ^ sub.isValidUtf8()); ByteString[] ropes = { - RopeByteString.newInstanceForTest(ByteString.EMPTY, leaf), - RopeByteString.newInstanceForTest(ByteString.EMPTY, sub), - RopeByteString.newInstanceForTest(leaf, ByteString.EMPTY), - RopeByteString.newInstanceForTest(sub, ByteString.EMPTY), - RopeByteString.newInstanceForTest(sub, leaf)}; + RopeByteString.newInstanceForTest(ByteString.EMPTY, leaf), + RopeByteString.newInstanceForTest(ByteString.EMPTY, sub), + RopeByteString.newInstanceForTest(leaf, ByteString.EMPTY), + RopeByteString.newInstanceForTest(sub, ByteString.EMPTY), + RopeByteString.newInstanceForTest(sub, leaf) + }; for (ByteString rope : ropes) { assertTrue(not ^ rope.isValidUtf8()); } @@ -179,7 +168,7 @@ public void testShardsHaveExpectedRoundTrippables() { // A sanity check. int actual = 0; for (Shard shard : IsValidUtf8TestUtil.FOUR_BYTE_SHARDS) { - actual += shard.expected; + actual = (int) (actual + shard.expected); } assertEquals(IsValidUtf8TestUtil.EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT, actual); } diff --git a/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java b/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java index 16a808bf31b89..67d2f5961d304 100644 --- a/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java +++ b/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java @@ -50,8 +50,7 @@ import java.util.logging.Logger; /** - * Shared testing code for {@link IsValidUtf8Test} and - * {@link IsValidUtf8FourByteTest}. + * Shared testing code for {@link IsValidUtf8Test} and {@link IsValidUtf8FourByteTest}. * * @author jonp@google.com (Jon Perlow) * @author martinrb@google.com (Martin Buchholz) @@ -65,44 +64,47 @@ static interface ByteStringFactory { ByteString newByteString(byte[] bytes); } - static final ByteStringFactory LITERAL_FACTORY = new ByteStringFactory() { - @Override - public ByteString newByteString(byte[] bytes) { - return ByteString.wrap(bytes); - } - }; + static final ByteStringFactory LITERAL_FACTORY = + new ByteStringFactory() { + @Override + public ByteString newByteString(byte[] bytes) { + return ByteString.wrap(bytes); + } + }; - static final ByteStringFactory HEAP_NIO_FACTORY = new ByteStringFactory() { - @Override - public ByteString newByteString(byte[] bytes) { - return new NioByteString(ByteBuffer.wrap(bytes)); - } - }; + static final ByteStringFactory HEAP_NIO_FACTORY = + new ByteStringFactory() { + @Override + public ByteString newByteString(byte[] bytes) { + return new NioByteString(ByteBuffer.wrap(bytes)); + } + }; private static ThreadLocal> directBuffer = new ThreadLocal>(); /** - * Factory for direct {@link ByteBuffer} instances. To reduce direct memory usage, this - * uses a thread local direct buffer. This means that each call will overwrite the buffer's - * contents from the previous call, so the calling code must be careful not to continue using - * a buffer returned from a previous invocation. + * Factory for direct {@link ByteBuffer} instances. To reduce direct memory usage, this uses a + * thread local direct buffer. This means that each call will overwrite the buffer's contents from + * the previous call, so the calling code must be careful not to continue using a buffer returned + * from a previous invocation. */ - static final ByteStringFactory DIRECT_NIO_FACTORY = new ByteStringFactory() { - @Override - public ByteString newByteString(byte[] bytes) { - SoftReference ref = directBuffer.get(); - ByteBuffer buffer = ref == null ? null : ref.get(); - if (buffer == null || buffer.capacity() < bytes.length) { - buffer = ByteBuffer.allocateDirect(bytes.length); - directBuffer.set(new SoftReference(buffer)); - } - buffer.clear(); - buffer.put(bytes); - buffer.flip(); - return new NioByteString(buffer); - } - }; + static final ByteStringFactory DIRECT_NIO_FACTORY = + new ByteStringFactory() { + @Override + public ByteString newByteString(byte[] bytes) { + SoftReference ref = directBuffer.get(); + ByteBuffer buffer = ref == null ? null : ref.get(); + if (buffer == null || buffer.capacity() < bytes.length) { + buffer = ByteBuffer.allocateDirect(bytes.length); + directBuffer.set(new SoftReference(buffer)); + } + buffer.clear(); + buffer.put(bytes); + buffer.flip(); + return new NioByteString(buffer); + } + }; // 128 - [chars 0x0000 to 0x007f] static final long ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x007f - 0x0000 + 1; @@ -116,9 +118,10 @@ public ByteString newByteString(byte[] bytes) { // 18,304 static final long EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT = // Both bytes are one byte characters - (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 2) + - // The possible number of two byte characters - TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS; + (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 2) + + + // The possible number of two byte characters + TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS; // 2048 static final long THREE_BYTE_SURROGATES = 2 * 1024; @@ -130,11 +133,13 @@ public ByteString newByteString(byte[] bytes) { // 2,650,112 static final long EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT = // All one byte characters - (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 3) + - // One two byte character and a one byte character - 2 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS + - // Three byte characters - THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS; + (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 3) + + + // One two byte character and a one byte character + 2 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS + + + // Three byte characters + THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS; // 1,048,576 [chars 0x10000L to 0x10FFFF] static final long FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x10FFFF - 0x10000L + 1; @@ -142,17 +147,22 @@ public ByteString newByteString(byte[] bytes) { // 289,571,839 static final long EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT = // All one byte characters - (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 4) + - // One and three byte characters - 2 * THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS + - // Two two byte characters - TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS + - // Permutations of one and two byte characters - 3 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS - * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS - + - // Four byte characters - FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS; + (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 4) + + + // One and three byte characters + 2 * THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS + + + // Two two byte characters + TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS + + + // Permutations of one and two byte characters + 3 + * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS + * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS + * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS + + + // Four byte characters + FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS; static final class Shard { final long index; @@ -160,7 +170,6 @@ static final class Shard { final long lim; final long expected; - public Shard(long index, long start, long lim, long expected) { assertTrue(start < lim); this.index = index; @@ -206,13 +215,12 @@ private static long[] generateFourByteShardsExpectedRunnables() { static final List FOUR_BYTE_SHARDS = generateFourByteShards(128, FOUR_BYTE_SHARDS_EXPECTED_ROUNTRIPPABLES); - private static List generateFourByteShards(int numShards, long[] expected) { assertEquals(numShards, expected.length); List shards = new ArrayList(numShards); - long LIM = 1L << 32; - long increment = LIM / numShards; - assertTrue(LIM % numShards == 0); + long lim = 1L << 32; + long increment = lim / numShards; + assertTrue(lim % numShards == 0); for (int i = 0; i < numShards; i++) { shards.add(new Shard(i, increment * i, increment * (i + 1), expected[i])); } @@ -220,8 +228,7 @@ private static List generateFourByteShards(int numShards, long[] expected } /** - * Helper to run the loop to test all the permutations for the number of bytes - * specified. + * Helper to run the loop to test all the permutations for the number of bytes specified. * * @param factory the factory for {@link ByteString} instances. * @param numBytes the number of bytes in the byte array @@ -232,16 +239,15 @@ static void testBytes(ByteStringFactory factory, int numBytes, long expectedCoun } /** - * Helper to run the loop to test all the permutations for the number of bytes - * specified. This overload is useful for debugging to get the loop to start - * at a certain character. + * Helper to run the loop to test all the permutations for the number of bytes specified. This + * overload is useful for debugging to get the loop to start at a certain character. * * @param factory the factory for {@link ByteString} instances. * @param numBytes the number of bytes in the byte array * @param expectedCount the expected number of roundtrippable permutations * @param start the starting bytes encoded as a long as big-endian - * @param lim the limit of bytes to process encoded as a long as big-endian, - * or -1 to mean the max limit for numBytes + * @param lim the limit of bytes to process encoded as a long as big-endian, or -1 to mean the max + * limit for numBytes */ static void testBytes( ByteStringFactory factory, int numBytes, long expectedCount, long start, long lim) { @@ -273,6 +279,15 @@ static void testBytes( assertEquals(isRoundTrippable, Utf8.isValidUtf8(bytes)); assertEquals(isRoundTrippable, Utf8.isValidUtf8(bytes, 0, numBytes)); + try { + assertEquals(s, Utf8.decodeUtf8(bytes, 0, numBytes)); + } catch (InvalidProtocolBufferException e) { + if (isRoundTrippable) { + System.out.println("Could not decode utf-8"); + outputFailure(byteChar, bytes, bytesReencoded); + } + } + // Test partial sequences. // Partition numBytes into three segments (not necessarily non-empty). int i = rnd.nextInt(numBytes); @@ -292,9 +307,10 @@ static void testBytes( assertEquals(isRoundTrippable, (state3 == Utf8.COMPLETE)); // Test ropes built out of small partial sequences - ByteString rope = RopeByteString.newInstanceForTest( - bs.substring(0, i), - RopeByteString.newInstanceForTest(bs.substring(i, j), bs.substring(j, numBytes))); + ByteString rope = + RopeByteString.newInstanceForTest( + bs.substring(0, i), + RopeByteString.newInstanceForTest(bs.substring(i, j), bs.substring(j, numBytes))); assertSame(RopeByteString.class, rope.getClass()); ByteString[] byteStrings = {bs, bs.substring(0, numBytes), rope}; @@ -327,27 +343,28 @@ static void testBytes( } /** - * Variation of {@link #testBytes} that does less allocation using the - * low-level encoders/decoders directly. Checked in because it's useful for - * debugging when trying to process bytes faster, but since it doesn't use the - * actual String class, it's possible for incompatibilities to develop + * Variation of {@link #testBytes} that does less allocation using the low-level encoders/decoders + * directly. Checked in because it's useful for debugging when trying to process bytes faster, but + * since it doesn't use the actual String class, it's possible for incompatibilities to develop * (although unlikely). * * @param factory the factory for {@link ByteString} instances. * @param numBytes the number of bytes in the byte array * @param expectedCount the expected number of roundtrippable permutations * @param start the starting bytes encoded as a long as big-endian - * @param lim the limit of bytes to process encoded as a long as big-endian, - * or -1 to mean the max limit for numBytes + * @param lim the limit of bytes to process encoded as a long as big-endian, or -1 to mean the max + * limit for numBytes */ static void testBytesUsingByteBuffers( ByteStringFactory factory, int numBytes, long expectedCount, long start, long lim) { CharsetDecoder decoder = - Internal.UTF_8.newDecoder() + Internal.UTF_8 + .newDecoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE); CharsetEncoder encoder = - Internal.UTF_8.newEncoder() + Internal.UTF_8 + .newEncoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE); byte[] bytes = new byte[numBytes]; @@ -425,8 +442,10 @@ private static void outputFailure(long byteChar, byte[] bytes, byte[] after) { } private static void outputFailure(long byteChar, byte[] bytes, byte[] after, int len) { - fail("Failure: (" + Long.toHexString(byteChar) + ") " + toHexString(bytes) + " => " - + toHexString(after, len)); + fail( + String.format( + "Failure: (%s) %s => %s", + Long.toHexString(byteChar), toHexString(bytes), toHexString(after, len))); } private static String toHexString(byte[] b) { diff --git a/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java b/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java index 813fe6bc69688..8c13acae42993 100644 --- a/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java +++ b/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java @@ -117,8 +117,8 @@ public void testMergeExtensions() throws Exception { LazyFieldLite original = createLazyFieldLiteFromMessage(message); LazyFieldLite merged = new LazyFieldLite(); merged.merge(original); - TestAllExtensions value = (TestAllExtensions) merged.getValue( - TestAllExtensions.getDefaultInstance()); + TestAllExtensions value = + (TestAllExtensions) merged.getValue(TestAllExtensions.getDefaultInstance()); assertEquals(message, value); } @@ -130,8 +130,8 @@ public void testEmptyLazyField() throws Exception { public void testInvalidProto() throws Exception { // Silently fails and uses the default instance. - LazyFieldLite field = new LazyFieldLite( - TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid")); + LazyFieldLite field = + new LazyFieldLite(TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid")); assertEquals( TestAllTypes.getDefaultInstance(), field.getValue(TestAllTypes.getDefaultInstance())); assertEquals(0, field.getSerializedSize()); @@ -158,7 +158,7 @@ public void testMergeOneNotParsed() throws Exception { TestAllTypes.newBuilder().setOptionalInt32(1).setOptionalInt64(2).build(); LazyFieldLite field1 = LazyFieldLite.fromValue(message1); - field1.getValue(TestAllTypes.getDefaultInstance()); // Force parsing. + field1.getValue(TestAllTypes.getDefaultInstance()); // Force parsing. LazyFieldLite field2 = createLazyFieldLiteFromMessage(message2); field1.merge(field2); assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance())); @@ -166,7 +166,7 @@ public void testMergeOneNotParsed() throws Exception { // Now reverse which one is parsed first. field1 = LazyFieldLite.fromValue(message1); field2 = createLazyFieldLiteFromMessage(message2); - field2.getValue(TestAllTypes.getDefaultInstance()); // Force parsing. + field2.getValue(TestAllTypes.getDefaultInstance()); // Force parsing. field1.merge(field2); assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance())); } @@ -175,8 +175,8 @@ public void testMergeInvalid() throws Exception { // Test a few different paths that involve one message that was not parsed. TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(1).build(); LazyFieldLite valid = LazyFieldLite.fromValue(message); - LazyFieldLite invalid = new LazyFieldLite( - TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid")); + LazyFieldLite invalid = + new LazyFieldLite(TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid")); invalid.merge(valid); // We swallow the exception and just use the set field. @@ -206,13 +206,13 @@ public void testMergeKeepsExtensionsWhenPossible() throws Exception { // Now try parsing the empty field first. field = LazyFieldLite.fromValue(messageWithExtensions); LazyFieldLite other = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage); - other.getValue(TestAllExtensions.getDefaultInstance()); // Force parsing. + other.getValue(TestAllExtensions.getDefaultInstance()); // Force parsing. field.merge(other); assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance())); // And again reverse. field = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage); - field.getValue(TestAllExtensions.getDefaultInstance()); // Force parsing. + field.getValue(TestAllExtensions.getDefaultInstance()); // Force parsing. other = LazyFieldLite.fromValue(messageWithExtensions); field.merge(other); assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance())); @@ -239,8 +239,7 @@ private void changeValue(LazyFieldLite lazyField) { } private void assertNotEqual(Object unexpected, Object actual) { - assertFalse(unexpected == actual - || (unexpected != null && unexpected.equals(actual))); + assertFalse(unexpected == actual || (unexpected != null && unexpected.equals(actual))); } } diff --git a/java/core/src/test/java/com/google/protobuf/LazyFieldTest.java b/java/core/src/test/java/com/google/protobuf/LazyFieldTest.java index f27e8e51b2378..a3901e91b9bdb 100644 --- a/java/core/src/test/java/com/google/protobuf/LazyFieldTest.java +++ b/java/core/src/test/java/com/google/protobuf/LazyFieldTest.java @@ -42,8 +42,7 @@ public class LazyFieldTest extends TestCase { public void testHashCode() { MessageLite message = TestUtil.getAllSet(); - LazyField lazyField = - createLazyFieldFromMessage(message); + LazyField lazyField = createLazyFieldFromMessage(message); assertEquals(message.hashCode(), lazyField.hashCode()); lazyField.getValue(); assertEquals(message.hashCode(), lazyField.hashCode()); @@ -102,8 +101,8 @@ public void testEqualsObjectEx() throws Exception { private LazyField createLazyFieldFromMessage(MessageLite message) { ByteString bytes = message.toByteString(); - return new LazyField(message.getDefaultInstanceForType(), - TestUtil.getExtensionRegistry(), bytes); + return new LazyField( + message.getDefaultInstanceForType(), TestUtil.getExtensionRegistry(), bytes); } private void changeValue(LazyField lazyField) { @@ -114,7 +113,6 @@ private void changeValue(LazyField lazyField) { } private void assertNotEqual(Object unexpected, Object actual) { - assertFalse(unexpected == actual - || (unexpected != null && unexpected.equals(actual))); + assertFalse(unexpected == actual || (unexpected != null && unexpected.equals(actual))); } } 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 968ca2065cdab..c5880d50657ad 100644 --- a/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java +++ b/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java @@ -44,8 +44,6 @@ */ public class LazyMessageLiteTest extends TestCase { - private Parser originalLazyInnerMessageLiteParser; - @Override protected void setUp() throws Exception { super.setUp(); @@ -57,19 +55,16 @@ protected void tearDown() throws Exception { } public void testSetValues() { - LazyNestedInnerMessageLite nested = LazyNestedInnerMessageLite.newBuilder() - .setNum(3) - .build(); - LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder() - .setNum(2) - .setNested(nested) - .build(); - LazyMessageLite outer = LazyMessageLite.newBuilder() - .setNum(1) - .setInner(inner) - .setOneofNum(123) - .setOneofInner(inner) - .build(); + LazyNestedInnerMessageLite nested = LazyNestedInnerMessageLite.newBuilder().setNum(3).build(); + LazyInnerMessageLite inner = + LazyInnerMessageLite.newBuilder().setNum(2).setNested(nested).build(); + LazyMessageLite outer = + LazyMessageLite.newBuilder() + .setNum(1) + .setInner(inner) + .setOneofNum(123) + .setOneofInner(inner) + .build(); assertEquals(1, outer.getNum()); assertEquals(421, outer.getNumWithDefault()); @@ -90,44 +85,43 @@ public void testSetValues() { } public void testSetRepeatedValues() { - LazyMessageLite outer = LazyMessageLite.newBuilder() - .setNum(1) - .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119)) - .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122)) - .build(); + LazyMessageLite outer = + LazyMessageLite.newBuilder() + .setNum(1) + .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119)) + .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122)) + .build(); assertEquals(1, outer.getNum()); assertEquals(2, outer.getRepeatedInnerCount()); assertEquals(119, outer.getRepeatedInner(0).getNum()); assertEquals(122, outer.getRepeatedInner(1).getNum()); } - + public void testRepeatedMutability() throws Exception { - LazyMessageLite outer = LazyMessageLite.newBuilder() - .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119)) - .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122)) - .build(); - + LazyMessageLite outer = + LazyMessageLite.newBuilder() + .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119)) + .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122)) + .build(); + outer = LazyMessageLite.parseFrom(outer.toByteArray()); try { outer.getRepeatedInnerList().set(1, null); fail(); - } catch (UnsupportedOperationException expected) {} + } catch (UnsupportedOperationException expected) { + } } public void testAddAll() { - ArrayList inners = new ArrayList(); + ArrayList inners = new ArrayList<>(); int count = 4; for (int i = 0; i < count; i++) { - LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder() - .setNum(i) - .build(); + LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder().setNum(i).build(); inners.add(inner); } - LazyMessageLite outer = LazyMessageLite.newBuilder() - .addAllRepeatedInner(inners) - .build(); + LazyMessageLite outer = LazyMessageLite.newBuilder().addAllRepeatedInner(inners).build(); assertEquals(count, outer.getRepeatedInnerCount()); for (int i = 0; i < count; i++) { assertEquals(i, outer.getRepeatedInner(i).getNum()); @@ -135,8 +129,7 @@ public void testAddAll() { } public void testGetDefaultValues() { - LazyMessageLite outer = LazyMessageLite.newBuilder() - .build(); + LazyMessageLite outer = LazyMessageLite.getDefaultInstance(); assertEquals(0, outer.getNum()); assertEquals(421, outer.getNumWithDefault()); @@ -156,15 +149,12 @@ public void testGetDefaultValues() { } public void testClearValues() { - LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder() - .setNum(115) - .build(); + LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder().setNum(115).build(); LazyMessageLite.Builder outerBuilder = LazyMessageLite.newBuilder(); assertEquals(0, outerBuilder.build().getNum()); - // Set/Clear num outerBuilder.setNum(100); @@ -178,9 +168,9 @@ public void testClearValues() { assertEquals(421, outerBuilder.build().getNumWithDefault()); assertFalse(outerBuilder.build().hasInner()); - // Set/Clear all - outerBuilder.setNum(100) + outerBuilder + .setNum(100) .setInner(inner) .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119)) .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122)) @@ -210,23 +200,17 @@ public void testClearValues() { } public void testMergeValues() { - LazyMessageLite outerBase = LazyMessageLite.newBuilder() - .setNumWithDefault(122) - .build(); - - LazyInnerMessageLite innerMerging = LazyInnerMessageLite.newBuilder() - .setNum(115) - .build(); - LazyMessageLite outerMerging = LazyMessageLite.newBuilder() - .setNum(119) - .setInner(innerMerging) - .setOneofInner(innerMerging) - .build(); - - LazyMessageLite merged = LazyMessageLite - .newBuilder(outerBase) - .mergeFrom(outerMerging) - .build(); + LazyMessageLite outerBase = LazyMessageLite.newBuilder().setNumWithDefault(122).build(); + + LazyInnerMessageLite innerMerging = LazyInnerMessageLite.newBuilder().setNum(115).build(); + LazyMessageLite outerMerging = + LazyMessageLite.newBuilder() + .setNum(119) + .setInner(innerMerging) + .setOneofInner(innerMerging) + .build(); + + LazyMessageLite merged = LazyMessageLite.newBuilder(outerBase).mergeFrom(outerMerging).build(); assertEquals(119, merged.getNum()); assertEquals(122, merged.getNumWithDefault()); assertEquals(115, merged.getInner().getNum()); @@ -236,23 +220,18 @@ public void testMergeValues() { } public void testMergeDefaultValues() { - LazyInnerMessageLite innerBase = LazyInnerMessageLite.newBuilder() - .setNum(115) - .build(); - LazyMessageLite outerBase = LazyMessageLite.newBuilder() - .setNum(119) - .setNumWithDefault(122) - .setInner(innerBase) - .setOneofInner(innerBase) - .build(); - - LazyMessageLite outerMerging = LazyMessageLite.newBuilder() - .build(); - - LazyMessageLite merged = LazyMessageLite - .newBuilder(outerBase) - .mergeFrom(outerMerging) - .build(); + LazyInnerMessageLite innerBase = LazyInnerMessageLite.newBuilder().setNum(115).build(); + LazyMessageLite outerBase = + LazyMessageLite.newBuilder() + .setNum(119) + .setNumWithDefault(122) + .setInner(innerBase) + .setOneofInner(innerBase) + .build(); + + LazyMessageLite outerMerging = LazyMessageLite.getDefaultInstance(); + + LazyMessageLite merged = LazyMessageLite.newBuilder(outerBase).mergeFrom(outerMerging).build(); // Merging default-instance shouldn't overwrite values in the base message. assertEquals(119, merged.getNum()); assertEquals(122, merged.getNumWithDefault()); @@ -264,7 +243,7 @@ public void testMergeDefaultValues() { // Regression test for b/28198805. public void testMergeOneofMessages() throws Exception { - LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder().build(); + LazyInnerMessageLite inner = LazyInnerMessageLite.getDefaultInstance(); LazyMessageLite outer = LazyMessageLite.newBuilder().setOneofInner(inner).build(); ByteString data1 = outer.toByteString(); @@ -280,18 +259,11 @@ public void testMergeOneofMessages() throws Exception { } public void testSerialize() throws InvalidProtocolBufferException { - LazyNestedInnerMessageLite nested = LazyNestedInnerMessageLite.newBuilder() - .setNum(3) - .build(); - LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder() - .setNum(2) - .setNested(nested) - .build(); - LazyMessageLite outer = LazyMessageLite.newBuilder() - .setNum(1) - .setInner(inner) - .setOneofInner(inner) - .build(); + LazyNestedInnerMessageLite nested = LazyNestedInnerMessageLite.newBuilder().setNum(3).build(); + LazyInnerMessageLite inner = + LazyInnerMessageLite.newBuilder().setNum(2).setNested(nested).build(); + LazyMessageLite outer = + LazyMessageLite.newBuilder().setNum(1).setInner(inner).setOneofInner(inner).build(); ByteString bytes = outer.toByteString(); assertEquals(bytes.size(), outer.getSerializedSize()); @@ -299,18 +271,18 @@ public void testSerialize() throws InvalidProtocolBufferException { LazyMessageLite deserialized = LazyMessageLite.parseFrom(bytes); assertEquals(1, deserialized.getNum()); - assertEquals(421, deserialized.getNumWithDefault()); + assertEquals(421, deserialized.getNumWithDefault()); - assertEquals(2, deserialized.getInner().getNum()); - assertEquals(42, deserialized.getInner().getNumWithDefault()); + assertEquals(2, deserialized.getInner().getNum()); + assertEquals(42, deserialized.getInner().getNumWithDefault()); - assertEquals(3, deserialized.getInner().getNested().getNum()); - assertEquals(4, deserialized.getInner().getNested().getNumWithDefault()); + assertEquals(3, deserialized.getInner().getNested().getNum()); + assertEquals(4, deserialized.getInner().getNested().getNumWithDefault()); - assertEquals(2, deserialized.getOneofInner().getNum()); - assertEquals(42, deserialized.getOneofInner().getNumWithDefault()); - assertEquals(3, deserialized.getOneofInner().getNested().getNum()); - assertEquals(4, deserialized.getOneofInner().getNested().getNumWithDefault()); + assertEquals(2, deserialized.getOneofInner().getNum()); + assertEquals(42, deserialized.getOneofInner().getNumWithDefault()); + assertEquals(3, deserialized.getOneofInner().getNested().getNum()); + assertEquals(4, deserialized.getOneofInner().getNested().getNumWithDefault()); assertEquals(bytes, deserialized.toByteString()); } @@ -318,8 +290,7 @@ public void testSerialize() throws InvalidProtocolBufferException { public void testExtensions() throws Exception { LazyInnerMessageLite.Builder innerBuilder = LazyInnerMessageLite.newBuilder(); innerBuilder.setExtension( - LazyExtension.extension, LazyExtension.newBuilder() - .setName("name").build()); + LazyExtension.extension, LazyExtension.newBuilder().setName("name").build()); assertTrue(innerBuilder.hasExtension(LazyExtension.extension)); assertEquals("name", innerBuilder.getExtension(LazyExtension.extension).getName()); @@ -327,8 +298,7 @@ public void testExtensions() throws Exception { assertTrue(innerMessage.hasExtension(LazyExtension.extension)); assertEquals("name", innerMessage.getExtension(LazyExtension.extension).getName()); - LazyMessageLite lite = LazyMessageLite.newBuilder() - .setInner(innerMessage).build(); + LazyMessageLite lite = LazyMessageLite.newBuilder().setInner(innerMessage).build(); assertTrue(lite.getInner().hasExtension(LazyExtension.extension)); assertEquals("name", lite.getInner().getExtension(LazyExtension.extension).getName()); } diff --git a/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java b/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java index 2fc3124d4c70e..24d0038b3d4f2 100644 --- a/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java @@ -46,13 +46,13 @@ */ public class LazyStringArrayListTest extends TestCase { - private static String STRING_A = "A"; - private static String STRING_B = "B"; - private static String STRING_C = "C"; + private static final String STRING_A = "A"; + private static final String STRING_B = "B"; + private static final String STRING_C = "C"; - private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A"); - private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B"); - private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C"); + private static final ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A"); + private static final ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B"); + private static final ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C"); public void testJustStrings() { LazyStringArrayList list = new LazyStringArrayList(); @@ -175,7 +175,7 @@ public void testAddAllCopiesByReferenceIfPossible() { assertSame(BYTE_STRING_B, list2.getByteString(1)); assertSame(BYTE_STRING_C, list2.getByteString(2)); } - + public void testModificationWithIteration() { LazyStringArrayList list = new LazyStringArrayList(); list.addAll(asList(STRING_A, STRING_B, STRING_C)); @@ -183,12 +183,12 @@ public void testModificationWithIteration() { assertEquals(3, list.size()); assertEquals(STRING_A, list.get(0)); assertEquals(STRING_A, iterator.next()); - + // Does not structurally modify. iterator = list.iterator(); list.set(0, STRING_B); iterator.next(); - + list.remove(0); try { iterator.next(); @@ -196,7 +196,7 @@ public void testModificationWithIteration() { } catch (ConcurrentModificationException e) { // expected } - + iterator = list.iterator(); list.add(0, STRING_C); try { @@ -206,7 +206,7 @@ public void testModificationWithIteration() { // expected } } - + public void testMakeImmutable() { LazyStringArrayList list = new LazyStringArrayList(); list.add(STRING_A); @@ -214,52 +214,52 @@ public void testMakeImmutable() { list.add(STRING_C); list.makeImmutable(); assertGenericListImmutable(list, STRING_A); - + // LazyStringArrayList has extra methods not covered in the generic // assertion. - + try { list.add(BYTE_STRING_A.toByteArray()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.add(BYTE_STRING_A); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAllByteArray(Collections.singletonList(BYTE_STRING_A.toByteArray())); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAllByteString(asList(BYTE_STRING_A)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.mergeFrom(new LazyStringArrayList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.set(0, BYTE_STRING_A.toByteArray()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.set(0, BYTE_STRING_A); fail(); @@ -267,20 +267,20 @@ public void testMakeImmutable() { // expected } } - + public void testImmutabilityPropagation() { LazyStringArrayList list = new LazyStringArrayList(); list.add(STRING_A); list.makeImmutable(); assertGenericListImmutable(list.asByteStringList(), BYTE_STRING_A); - + // Arrays use reference equality so need to retrieve the underlying value // to properly test deep immutability. List byteArrayList = list.asByteArrayList(); assertGenericListImmutable(byteArrayList, byteArrayList.get(0)); } - + @SuppressWarnings("unchecked") private static void assertGenericListImmutable(List list, T value) { try { @@ -289,21 +289,21 @@ private static void assertGenericListImmutable(List list, T value) { } catch (UnsupportedOperationException e) { // expected } - + try { list.add(0, value); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(asList(value)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, asList(value)); fail(); @@ -317,42 +317,42 @@ private static void assertGenericListImmutable(List list, T value) { } catch (UnsupportedOperationException e) { // expected } - + try { list.remove(0); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.remove(value); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(asList(value)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(asList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(asList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.set(0, value); fail(); diff --git a/java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java b/java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java index 006e493366344..18c9c74ec327e 100644 --- a/java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java +++ b/java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java @@ -30,44 +30,42 @@ package com.google.protobuf; - import protobuf_unittest.UnittestProto; import java.io.IOException; import junit.framework.TestCase; /** - * Tests to make sure the lazy conversion of UTF8-encoded byte arrays to - * strings works correctly. + * Tests to make sure the lazy conversion of UTF8-encoded byte arrays to strings works correctly. * * @author jonp@google.com (Jon Perlow) */ public class LazyStringEndToEndTest extends TestCase { - private static ByteString TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8 = - ByteString.copyFrom(new byte[] { - 114, 4, -1, 0, -1, 0, -30, 2, 4, -1, - 0, -1, 0, -30, 2, 4, -1, 0, -1, 0, }); + private static final ByteString TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8 = + ByteString.copyFrom( + new byte[] { + 114, 4, -1, 0, -1, 0, -30, 2, 4, -1, + 0, -1, 0, -30, 2, 4, -1, 0, -1, 0, + }); private ByteString encodedTestAllTypes; @Override protected void setUp() throws Exception { super.setUp(); - this.encodedTestAllTypes = UnittestProto.TestAllTypes.newBuilder() - .setOptionalString("foo") - .addRepeatedString("bar") - .addRepeatedString("baz") - .build() - .toByteString(); + this.encodedTestAllTypes = + UnittestProto.TestAllTypes.newBuilder() + .setOptionalString("foo") + .addRepeatedString("bar") + .addRepeatedString("baz") + .build() + .toByteString(); } - /** - * Tests that an invalid UTF8 string will roundtrip through a parse - * and serialization. - */ + /** Tests that an invalid UTF8 string will roundtrip through a parse and serialization. */ public void testParseAndSerialize() throws InvalidProtocolBufferException { - UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom( - TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8); + UnittestProto.TestAllTypes tV2 = + UnittestProto.TestAllTypes.parseFrom(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8); ByteString bytes = tV2.toByteString(); assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes); @@ -77,33 +75,31 @@ public void testParseAndSerialize() throws InvalidProtocolBufferException { } public void testParseAndWrite() throws IOException { - UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom( - TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8); + UnittestProto.TestAllTypes tV2 = + UnittestProto.TestAllTypes.parseFrom(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8); byte[] sink = new byte[TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8.size()]; CodedOutputStream outputStream = CodedOutputStream.newInstance(sink); tV2.writeTo(outputStream); outputStream.flush(); - assertEquals( - TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, - ByteString.copyFrom(sink)); + assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, ByteString.copyFrom(sink)); } - + public void testCaching() { String a = "a"; String b = "b"; String c = "c"; - UnittestProto.TestAllTypes proto = UnittestProto.TestAllTypes.newBuilder() - .setOptionalString(a) - .addRepeatedString(b) - .addRepeatedString(c) - .build(); + UnittestProto.TestAllTypes proto = + UnittestProto.TestAllTypes.newBuilder() + .setOptionalString(a) + .addRepeatedString(b) + .addRepeatedString(c) + .build(); // String should be the one we passed it. assertSame(a, proto.getOptionalString()); assertSame(b, proto.getRepeatedString(0)); assertSame(c, proto.getRepeatedString(1)); - // Ensure serialization keeps strings cached. proto.toByteString(); @@ -114,8 +110,7 @@ public void testCaching() { } public void testNoStringCachingIfOnlyBytesAccessed() throws Exception { - UnittestProto.TestAllTypes proto = - UnittestProto.TestAllTypes.parseFrom(encodedTestAllTypes); + UnittestProto.TestAllTypes proto = UnittestProto.TestAllTypes.parseFrom(encodedTestAllTypes); ByteString optional = proto.getOptionalStringBytes(); assertSame(optional, proto.getOptionalStringBytes()); assertSame(optional, proto.toBuilder().getOptionalStringBytes()); diff --git a/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java b/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java index 4764ca1bbcbcc..1270ef06ee4da 100644 --- a/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java +++ b/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java @@ -75,7 +75,7 @@ public void testEquals() throws Exception { assertEquals(foo1a, foo1b); assertEquals(foo1a.hashCode(), foo1b.hashCode()); - // Check that a diffeent object is not equal. + // Check that a different object is not equal. assertFalse(foo1a.equals(foo2)); // Check that two objects which have different types but the same field values are not diff --git a/java/core/src/test/java/com/google/protobuf/LiteTest.java b/java/core/src/test/java/com/google/protobuf/LiteTest.java deleted file mode 100644 index ba8bcb1c24197..0000000000000 --- a/java/core/src/test/java/com/google/protobuf/LiteTest.java +++ /dev/null @@ -1,2595 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf; - -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; - -import com.google.protobuf.FieldPresenceTestProto.TestAllTypes; -import com.google.protobuf.UnittestImportLite.ImportEnumLite; -import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite; -import com.google.protobuf.UnittestLite.ForeignEnumLite; -import com.google.protobuf.UnittestLite.ForeignMessageLite; -import com.google.protobuf.UnittestLite.TestAllExtensionsLite; -import com.google.protobuf.UnittestLite.TestAllTypesLite; -import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedEnum; -import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedMessage; -import com.google.protobuf.UnittestLite.TestAllTypesLite.OneofFieldCase; -import com.google.protobuf.UnittestLite.TestAllTypesLite.OptionalGroup; -import com.google.protobuf.UnittestLite.TestAllTypesLite.RepeatedGroup; -import com.google.protobuf.UnittestLite.TestAllTypesLiteOrBuilder; -import com.google.protobuf.UnittestLite.TestHugeFieldNumbersLite; -import com.google.protobuf.UnittestLite.TestNestedExtensionLite; -import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar; -import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.BarPrime; -import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo; -import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestOneofEquals; -import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestRecursiveOneof; -import java.lang.reflect.Field; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import junit.framework.TestCase; - -/** - * Test lite runtime. - * - * @author kenton@google.com Kenton Varda - */ -public class LiteTest extends TestCase { - @Override - public void setUp() throws Exception { - // Test that nested extensions are initialized correctly even if the outer - // class has not been accessed directly. This was once a bug with lite - // messages. - // - // We put this in setUp() rather than in its own test method because we - // need to make sure it runs before any actual tests. - assertTrue(TestNestedExtensionLite.nestedExtension != null); - } - - public void testLite() throws Exception { - // Since lite messages are a subset of regular messages, we can mostly - // assume that the functionality of lite messages is already thoroughly - // tested by the regular tests. All this test really verifies is that - // a proto with optimize_for = LITE_RUNTIME compiles correctly when - // linked only against the lite library. That is all tested at compile - // time, leaving not much to do in this method. Let's just do some random - // stuff to make sure the lite message is actually here and usable. - - TestAllTypesLite message = - TestAllTypesLite.newBuilder() - .setOptionalInt32(123) - .addRepeatedString("hello") - .setOptionalNestedMessage( - TestAllTypesLite.NestedMessage.newBuilder().setBb(7)) - .build(); - - ByteString data = message.toByteString(); - - TestAllTypesLite message2 = TestAllTypesLite.parseFrom(data); - - assertEquals(123, message2.getOptionalInt32()); - assertEquals(1, message2.getRepeatedStringCount()); - assertEquals("hello", message2.getRepeatedString(0)); - assertEquals(7, message2.getOptionalNestedMessage().getBb()); - } - - public void testLiteExtensions() throws Exception { - // TODO(kenton): Unlike other features of the lite library, extensions are - // implemented completely differently from the regular library. We - // should probably test them more thoroughly. - - TestAllExtensionsLite message = - TestAllExtensionsLite.newBuilder() - .setExtension(UnittestLite.optionalInt32ExtensionLite, 123) - .addExtension(UnittestLite.repeatedStringExtensionLite, "hello") - .setExtension(UnittestLite.optionalNestedEnumExtensionLite, - TestAllTypesLite.NestedEnum.BAZ) - .setExtension(UnittestLite.optionalNestedMessageExtensionLite, - TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build()) - .build(); - - // Test copying a message, since coping extensions actually does use a - // different code path between lite and regular libraries, and as of this - // writing, parsing hasn't been implemented yet. - TestAllExtensionsLite message2 = message.toBuilder().build(); - - assertEquals(123, (int) message2.getExtension( - UnittestLite.optionalInt32ExtensionLite)); - assertEquals(1, message2.getExtensionCount( - UnittestLite.repeatedStringExtensionLite)); - assertEquals(1, message2.getExtension( - UnittestLite.repeatedStringExtensionLite).size()); - assertEquals("hello", message2.getExtension( - UnittestLite.repeatedStringExtensionLite, 0)); - assertEquals(TestAllTypesLite.NestedEnum.BAZ, message2.getExtension( - UnittestLite.optionalNestedEnumExtensionLite)); - assertEquals(7, message2.getExtension( - UnittestLite.optionalNestedMessageExtensionLite).getBb()); - } - - public void testClone() { - TestAllTypesLite.Builder expected = TestAllTypesLite.newBuilder() - .setOptionalInt32(123); - assertEquals( - expected.getOptionalInt32(), expected.clone().getOptionalInt32()); - - TestAllExtensionsLite.Builder expected2 = TestAllExtensionsLite.newBuilder() - .setExtension(UnittestLite.optionalInt32ExtensionLite, 123); - assertEquals( - expected2.getExtension(UnittestLite.optionalInt32ExtensionLite), - expected2.clone().getExtension(UnittestLite.optionalInt32ExtensionLite)); - } - - public void testAddAll() { - try { - TestAllTypesLite.newBuilder() - .addAllRepeatedBytes(null); - fail(); - } catch (NullPointerException e) { - // expected. - } - } - - public void testMemoization() throws Exception { - TestAllExtensionsLite message = TestUtilLite.getAllLiteExtensionsSet(); - - // Test serialized size is memoized - message.memoizedSerializedSize = -1; - int size = message.getSerializedSize(); - assertTrue(size > 0); - assertEquals(size, message.memoizedSerializedSize); - - // Test hashCode is memoized - assertEquals(0, message.memoizedHashCode); - int hashCode = message.hashCode(); - assertTrue(hashCode != 0); - assertEquals(hashCode, message.memoizedHashCode); - - // Test isInitialized is memoized - Field memo = message.getClass().getDeclaredField("memoizedIsInitialized"); - memo.setAccessible(true); - memo.set(message, (byte) -1); - boolean initialized = message.isInitialized(); - assertTrue(initialized); - // We have to cast to Byte first. Casting to byte causes a type error - assertEquals(1, ((Byte) memo.get(message)).intValue()); - } - - public void testSanityCopyOnWrite() throws InvalidProtocolBufferException { - // Since builders are implemented as a thin wrapper around a message - // instance, we attempt to verify that we can't cause the builder to modify - // a produced message. - - TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder(); - TestAllTypesLite message = builder.build(); - TestAllTypesLite messageAfterBuild; - builder.setOptionalBool(true); - assertEquals(false, message.getOptionalBool()); - assertEquals(true, builder.getOptionalBool()); - messageAfterBuild = builder.build(); - assertEquals(true, messageAfterBuild.getOptionalBool()); - assertEquals(false, message.getOptionalBool()); - builder.clearOptionalBool(); - assertEquals(false, builder.getOptionalBool()); - assertEquals(true, messageAfterBuild.getOptionalBool()); - - message = builder.build(); - builder.setOptionalBytes(ByteString.copyFromUtf8("hi")); - assertEquals(ByteString.EMPTY, message.getOptionalBytes()); - assertEquals(ByteString.copyFromUtf8("hi"), builder.getOptionalBytes()); - messageAfterBuild = builder.build(); - assertEquals( - ByteString.copyFromUtf8("hi"), messageAfterBuild.getOptionalBytes()); - assertEquals(ByteString.EMPTY, message.getOptionalBytes()); - builder.clearOptionalBytes(); - assertEquals(ByteString.EMPTY, builder.getOptionalBytes()); - assertEquals( - ByteString.copyFromUtf8("hi"), messageAfterBuild.getOptionalBytes()); - - message = builder.build(); - builder.setOptionalCord("hi"); - assertEquals("", message.getOptionalCord()); - assertEquals("hi", builder.getOptionalCord()); - messageAfterBuild = builder.build(); - assertEquals("hi", messageAfterBuild.getOptionalCord()); - assertEquals("", message.getOptionalCord()); - builder.clearOptionalCord(); - assertEquals("", builder.getOptionalCord()); - assertEquals("hi", messageAfterBuild.getOptionalCord()); - - message = builder.build(); - builder.setOptionalCordBytes(ByteString.copyFromUtf8("no")); - assertEquals(ByteString.EMPTY, message.getOptionalCordBytes()); - assertEquals(ByteString.copyFromUtf8("no"), builder.getOptionalCordBytes()); - messageAfterBuild = builder.build(); - assertEquals( - ByteString.copyFromUtf8("no"), - messageAfterBuild.getOptionalCordBytes()); - assertEquals(ByteString.EMPTY, message.getOptionalCordBytes()); - builder.clearOptionalCord(); - assertEquals(ByteString.EMPTY, builder.getOptionalCordBytes()); - assertEquals( - ByteString.copyFromUtf8("no"), - messageAfterBuild.getOptionalCordBytes()); - - message = builder.build(); - builder.setOptionalDouble(1); - assertEquals(0D, message.getOptionalDouble()); - assertEquals(1D, builder.getOptionalDouble()); - messageAfterBuild = builder.build(); - assertEquals(1D, messageAfterBuild.getOptionalDouble()); - assertEquals(0D, message.getOptionalDouble()); - builder.clearOptionalDouble(); - assertEquals(0D, builder.getOptionalDouble()); - assertEquals(1D, messageAfterBuild.getOptionalDouble()); - - message = builder.build(); - builder.setOptionalFixed32(1); - assertEquals(0, message.getOptionalFixed32()); - assertEquals(1, builder.getOptionalFixed32()); - messageAfterBuild = builder.build(); - assertEquals(1, messageAfterBuild.getOptionalFixed32()); - assertEquals(0, message.getOptionalFixed32()); - builder.clearOptionalFixed32(); - assertEquals(0, builder.getOptionalFixed32()); - assertEquals(1, messageAfterBuild.getOptionalFixed32()); - - message = builder.build(); - builder.setOptionalFixed64(1); - assertEquals(0L, message.getOptionalFixed64()); - assertEquals(1L, builder.getOptionalFixed64()); - messageAfterBuild = builder.build(); - assertEquals(1L, messageAfterBuild.getOptionalFixed64()); - assertEquals(0L, message.getOptionalFixed64()); - builder.clearOptionalFixed64(); - assertEquals(0L, builder.getOptionalFixed64()); - assertEquals(1L, messageAfterBuild.getOptionalFixed64()); - - message = builder.build(); - builder.setOptionalFloat(1); - assertEquals(0F, message.getOptionalFloat()); - assertEquals(1F, builder.getOptionalFloat()); - messageAfterBuild = builder.build(); - assertEquals(1F, messageAfterBuild.getOptionalFloat()); - assertEquals(0F, message.getOptionalFloat()); - builder.clearOptionalFloat(); - assertEquals(0F, builder.getOptionalFloat()); - assertEquals(1F, messageAfterBuild.getOptionalFloat()); - - message = builder.build(); - builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR); - assertEquals( - ForeignEnumLite.FOREIGN_LITE_FOO, message.getOptionalForeignEnum()); - assertEquals( - ForeignEnumLite.FOREIGN_LITE_BAR, builder.getOptionalForeignEnum()); - messageAfterBuild = builder.build(); - assertEquals( - ForeignEnumLite.FOREIGN_LITE_BAR, - messageAfterBuild.getOptionalForeignEnum()); - assertEquals( - ForeignEnumLite.FOREIGN_LITE_FOO, message.getOptionalForeignEnum()); - builder.clearOptionalForeignEnum(); - assertEquals( - ForeignEnumLite.FOREIGN_LITE_FOO, builder.getOptionalForeignEnum()); - assertEquals( - ForeignEnumLite.FOREIGN_LITE_BAR, - messageAfterBuild.getOptionalForeignEnum()); - - message = builder.build(); - ForeignMessageLite foreignMessage = ForeignMessageLite.newBuilder() - .setC(1) - .build(); - builder.setOptionalForeignMessage(foreignMessage); - assertEquals( - ForeignMessageLite.getDefaultInstance(), - message.getOptionalForeignMessage()); - assertEquals(foreignMessage, builder.getOptionalForeignMessage()); - messageAfterBuild = builder.build(); - assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage()); - assertEquals( - ForeignMessageLite.getDefaultInstance(), - message.getOptionalForeignMessage()); - builder.clearOptionalForeignMessage(); - assertEquals( - ForeignMessageLite.getDefaultInstance(), - builder.getOptionalForeignMessage()); - assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage()); - - message = builder.build(); - ForeignMessageLite.Builder foreignMessageBuilder = - ForeignMessageLite.newBuilder() - .setC(3); - builder.setOptionalForeignMessage(foreignMessageBuilder); - assertEquals( - ForeignMessageLite.getDefaultInstance(), - message.getOptionalForeignMessage()); - assertEquals(foreignMessageBuilder.build(), builder.getOptionalForeignMessage()); - messageAfterBuild = builder.build(); - assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getOptionalForeignMessage()); - assertEquals( - ForeignMessageLite.getDefaultInstance(), - message.getOptionalForeignMessage()); - builder.clearOptionalForeignMessage(); - assertEquals( - ForeignMessageLite.getDefaultInstance(), - builder.getOptionalForeignMessage()); - assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getOptionalForeignMessage()); - - message = builder.build(); - OptionalGroup optionalGroup = OptionalGroup.newBuilder() - .setA(1) - .build(); - builder.setOptionalGroup(optionalGroup); - assertEquals( - OptionalGroup.getDefaultInstance(), message.getOptionalGroup()); - assertEquals(optionalGroup, builder.getOptionalGroup()); - messageAfterBuild = builder.build(); - assertEquals(optionalGroup, messageAfterBuild.getOptionalGroup()); - assertEquals( - OptionalGroup.getDefaultInstance(), message.getOptionalGroup()); - builder.clearOptionalGroup(); - assertEquals( - OptionalGroup.getDefaultInstance(), builder.getOptionalGroup()); - assertEquals(optionalGroup, messageAfterBuild.getOptionalGroup()); - - message = builder.build(); - OptionalGroup.Builder optionalGroupBuilder = OptionalGroup.newBuilder() - .setA(3); - builder.setOptionalGroup(optionalGroupBuilder); - assertEquals( - OptionalGroup.getDefaultInstance(), message.getOptionalGroup()); - assertEquals(optionalGroupBuilder.build(), builder.getOptionalGroup()); - messageAfterBuild = builder.build(); - assertEquals(optionalGroupBuilder.build(), messageAfterBuild.getOptionalGroup()); - assertEquals( - OptionalGroup.getDefaultInstance(), message.getOptionalGroup()); - builder.clearOptionalGroup(); - assertEquals( - OptionalGroup.getDefaultInstance(), builder.getOptionalGroup()); - assertEquals(optionalGroupBuilder.build(), messageAfterBuild.getOptionalGroup()); - - message = builder.build(); - builder.setOptionalInt32(1); - assertEquals(0, message.getOptionalInt32()); - assertEquals(1, builder.getOptionalInt32()); - messageAfterBuild = builder.build(); - assertEquals(1, messageAfterBuild.getOptionalInt32()); - assertEquals(0, message.getOptionalInt32()); - builder.clearOptionalInt32(); - assertEquals(0, builder.getOptionalInt32()); - assertEquals(1, messageAfterBuild.getOptionalInt32()); - - message = builder.build(); - builder.setOptionalInt64(1); - assertEquals(0L, message.getOptionalInt64()); - assertEquals(1L, builder.getOptionalInt64()); - messageAfterBuild = builder.build(); - assertEquals(1L, messageAfterBuild.getOptionalInt64()); - assertEquals(0L, message.getOptionalInt64()); - builder.clearOptionalInt64(); - assertEquals(0L, builder.getOptionalInt64()); - assertEquals(1L, messageAfterBuild.getOptionalInt64()); - - message = builder.build(); - NestedMessage nestedMessage = NestedMessage.newBuilder() - .setBb(1) - .build(); - builder.setOptionalLazyMessage(nestedMessage); - assertEquals( - NestedMessage.getDefaultInstance(), - message.getOptionalLazyMessage()); - assertEquals(nestedMessage, builder.getOptionalLazyMessage()); - messageAfterBuild = builder.build(); - assertEquals(nestedMessage, messageAfterBuild.getOptionalLazyMessage()); - assertEquals( - NestedMessage.getDefaultInstance(), - message.getOptionalLazyMessage()); - builder.clearOptionalLazyMessage(); - assertEquals( - NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage()); - assertEquals(nestedMessage, messageAfterBuild.getOptionalLazyMessage()); - - message = builder.build(); - NestedMessage.Builder nestedMessageBuilder = - NestedMessage.newBuilder() - .setBb(3); - builder.setOptionalLazyMessage(nestedMessageBuilder); - assertEquals( - NestedMessage.getDefaultInstance(), - message.getOptionalLazyMessage()); - assertEquals(nestedMessageBuilder.build(), builder.getOptionalLazyMessage()); - messageAfterBuild = builder.build(); - assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getOptionalLazyMessage()); - assertEquals( - NestedMessage.getDefaultInstance(), - message.getOptionalLazyMessage()); - builder.clearOptionalLazyMessage(); - assertEquals( - NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage()); - assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getOptionalLazyMessage()); - - message = builder.build(); - builder.setOptionalSfixed32(1); - assertEquals(0, message.getOptionalSfixed32()); - assertEquals(1, builder.getOptionalSfixed32()); - messageAfterBuild = builder.build(); - assertEquals(1, messageAfterBuild.getOptionalSfixed32()); - assertEquals(0, message.getOptionalSfixed32()); - builder.clearOptionalSfixed32(); - assertEquals(0, builder.getOptionalSfixed32()); - assertEquals(1, messageAfterBuild.getOptionalSfixed32()); - - message = builder.build(); - builder.setOptionalSfixed64(1); - assertEquals(0L, message.getOptionalSfixed64()); - assertEquals(1L, builder.getOptionalSfixed64()); - messageAfterBuild = builder.build(); - assertEquals(1L, messageAfterBuild.getOptionalSfixed64()); - assertEquals(0L, message.getOptionalSfixed64()); - builder.clearOptionalSfixed64(); - assertEquals(0L, builder.getOptionalSfixed64()); - assertEquals(1L, messageAfterBuild.getOptionalSfixed64()); - - message = builder.build(); - builder.setOptionalSint32(1); - assertEquals(0, message.getOptionalSint32()); - assertEquals(1, builder.getOptionalSint32()); - messageAfterBuild = builder.build(); - assertEquals(1, messageAfterBuild.getOptionalSint32()); - builder.clearOptionalSint32(); - assertEquals(0, builder.getOptionalSint32()); - assertEquals(1, messageAfterBuild.getOptionalSint32()); - - message = builder.build(); - builder.setOptionalSint64(1); - assertEquals(0L, message.getOptionalSint64()); - assertEquals(1L, builder.getOptionalSint64()); - messageAfterBuild = builder.build(); - assertEquals(1L, messageAfterBuild.getOptionalSint64()); - assertEquals(0L, message.getOptionalSint64()); - builder.clearOptionalSint64(); - assertEquals(0L, builder.getOptionalSint64()); - assertEquals(1L, messageAfterBuild.getOptionalSint64()); - - message = builder.build(); - builder.setOptionalString("hi"); - assertEquals("", message.getOptionalString()); - assertEquals("hi", builder.getOptionalString()); - messageAfterBuild = builder.build(); - assertEquals("hi", messageAfterBuild.getOptionalString()); - assertEquals("", message.getOptionalString()); - builder.clearOptionalString(); - assertEquals("", builder.getOptionalString()); - assertEquals("hi", messageAfterBuild.getOptionalString()); - - message = builder.build(); - builder.setOptionalStringBytes(ByteString.copyFromUtf8("no")); - assertEquals(ByteString.EMPTY, message.getOptionalStringBytes()); - assertEquals( - ByteString.copyFromUtf8("no"), builder.getOptionalStringBytes()); - messageAfterBuild = builder.build(); - assertEquals( - ByteString.copyFromUtf8("no"), - messageAfterBuild.getOptionalStringBytes()); - assertEquals(ByteString.EMPTY, message.getOptionalStringBytes()); - builder.clearOptionalString(); - assertEquals(ByteString.EMPTY, builder.getOptionalStringBytes()); - assertEquals( - ByteString.copyFromUtf8("no"), - messageAfterBuild.getOptionalStringBytes()); - - message = builder.build(); - builder.setOptionalStringPiece("hi"); - assertEquals("", message.getOptionalStringPiece()); - assertEquals("hi", builder.getOptionalStringPiece()); - messageAfterBuild = builder.build(); - assertEquals("hi", messageAfterBuild.getOptionalStringPiece()); - assertEquals("", message.getOptionalStringPiece()); - builder.clearOptionalStringPiece(); - assertEquals("", builder.getOptionalStringPiece()); - assertEquals("hi", messageAfterBuild.getOptionalStringPiece()); - - message = builder.build(); - builder.setOptionalStringPieceBytes(ByteString.copyFromUtf8("no")); - assertEquals(ByteString.EMPTY, message.getOptionalStringPieceBytes()); - assertEquals( - ByteString.copyFromUtf8("no"), builder.getOptionalStringPieceBytes()); - messageAfterBuild = builder.build(); - assertEquals( - ByteString.copyFromUtf8("no"), - messageAfterBuild.getOptionalStringPieceBytes()); - assertEquals(ByteString.EMPTY, message.getOptionalStringPieceBytes()); - builder.clearOptionalStringPiece(); - assertEquals(ByteString.EMPTY, builder.getOptionalStringPieceBytes()); - assertEquals( - ByteString.copyFromUtf8("no"), - messageAfterBuild.getOptionalStringPieceBytes()); - - message = builder.build(); - builder.setOptionalUint32(1); - assertEquals(0, message.getOptionalUint32()); - assertEquals(1, builder.getOptionalUint32()); - messageAfterBuild = builder.build(); - assertEquals(1, messageAfterBuild.getOptionalUint32()); - assertEquals(0, message.getOptionalUint32()); - builder.clearOptionalUint32(); - assertEquals(0, builder.getOptionalUint32()); - assertEquals(1, messageAfterBuild.getOptionalUint32()); - - message = builder.build(); - builder.setOptionalUint64(1); - assertEquals(0L, message.getOptionalUint64()); - assertEquals(1L, builder.getOptionalUint64()); - messageAfterBuild = builder.build(); - assertEquals(1L, messageAfterBuild.getOptionalUint64()); - assertEquals(0L, message.getOptionalUint64()); - builder.clearOptionalUint64(); - assertEquals(0L, builder.getOptionalUint64()); - assertEquals(1L, messageAfterBuild.getOptionalUint64()); - - message = builder.build(); - builder.addAllRepeatedBool(singletonList(true)); - assertEquals(emptyList(), message.getRepeatedBoolList()); - assertEquals(singletonList(true), builder.getRepeatedBoolList()); - assertEquals(emptyList(), message.getRepeatedBoolList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedBool(); - assertEquals(emptyList(), builder.getRepeatedBoolList()); - assertEquals(singletonList(true), messageAfterBuild.getRepeatedBoolList()); - - message = builder.build(); - builder.addAllRepeatedBytes(singletonList(ByteString.copyFromUtf8("hi"))); - assertEquals(emptyList(), message.getRepeatedBytesList()); - assertEquals( - singletonList(ByteString.copyFromUtf8("hi")), - builder.getRepeatedBytesList()); - assertEquals(emptyList(), message.getRepeatedBytesList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedBytes(); - assertEquals(emptyList(), builder.getRepeatedBytesList()); - assertEquals( - singletonList(ByteString.copyFromUtf8("hi")), - messageAfterBuild.getRepeatedBytesList()); - - message = builder.build(); - builder.addAllRepeatedCord(singletonList("hi")); - assertEquals(emptyList(), message.getRepeatedCordList()); - assertEquals(singletonList("hi"), builder.getRepeatedCordList()); - assertEquals(emptyList(), message.getRepeatedCordList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedCord(); - assertEquals(emptyList(), builder.getRepeatedCordList()); - assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedCordList()); - - message = builder.build(); - builder.addAllRepeatedDouble(singletonList(1D)); - assertEquals(emptyList(), message.getRepeatedDoubleList()); - assertEquals(singletonList(1D), builder.getRepeatedDoubleList()); - assertEquals(emptyList(), message.getRepeatedDoubleList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedDouble(); - assertEquals(emptyList(), builder.getRepeatedDoubleList()); - assertEquals(singletonList(1D), messageAfterBuild.getRepeatedDoubleList()); - - message = builder.build(); - builder.addAllRepeatedFixed32(singletonList(1)); - assertEquals(emptyList(), message.getRepeatedFixed32List()); - assertEquals(singletonList(1), builder.getRepeatedFixed32List()); - assertEquals(emptyList(), message.getRepeatedFixed32List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedFixed32(); - assertEquals(emptyList(), builder.getRepeatedFixed32List()); - assertEquals(singletonList(1), messageAfterBuild.getRepeatedFixed32List()); - - message = builder.build(); - builder.addAllRepeatedFixed64(singletonList(1L)); - assertEquals(emptyList(), message.getRepeatedFixed64List()); - assertEquals(singletonList(1L), builder.getRepeatedFixed64List()); - assertEquals(emptyList(), message.getRepeatedFixed64List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedFixed64(); - assertEquals(emptyList(), builder.getRepeatedFixed64List()); - assertEquals(singletonList(1L), messageAfterBuild.getRepeatedFixed64List()); - - message = builder.build(); - builder.addAllRepeatedFloat(singletonList(1F)); - assertEquals(emptyList(), message.getRepeatedFloatList()); - assertEquals(singletonList(1F), builder.getRepeatedFloatList()); - assertEquals(emptyList(), message.getRepeatedFloatList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedFloat(); - assertEquals(emptyList(), builder.getRepeatedFloatList()); - assertEquals(singletonList(1F), messageAfterBuild.getRepeatedFloatList()); - - message = builder.build(); - builder.addAllRepeatedForeignEnum( - singletonList(ForeignEnumLite.FOREIGN_LITE_BAR)); - assertEquals(emptyList(), message.getRepeatedForeignEnumList()); - assertEquals( - singletonList(ForeignEnumLite.FOREIGN_LITE_BAR), - builder.getRepeatedForeignEnumList()); - assertEquals(emptyList(), message.getRepeatedForeignEnumList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedForeignEnum(); - assertEquals(emptyList(), builder.getRepeatedForeignEnumList()); - assertEquals( - singletonList(ForeignEnumLite.FOREIGN_LITE_BAR), - messageAfterBuild.getRepeatedForeignEnumList()); - - message = builder.build(); - builder.addAllRepeatedForeignMessage(singletonList(foreignMessage)); - assertEquals(emptyList(), message.getRepeatedForeignMessageList()); - assertEquals( - singletonList(foreignMessage), builder.getRepeatedForeignMessageList()); - assertEquals(emptyList(), message.getRepeatedForeignMessageList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedForeignMessage(); - assertEquals(emptyList(), builder.getRepeatedForeignMessageList()); - assertEquals( - singletonList(foreignMessage), - messageAfterBuild.getRepeatedForeignMessageList()); - - message = builder.build(); - builder.addAllRepeatedGroup( - singletonList(RepeatedGroup.getDefaultInstance())); - assertEquals(emptyList(), message.getRepeatedGroupList()); - assertEquals( - singletonList(RepeatedGroup.getDefaultInstance()), - builder.getRepeatedGroupList()); - assertEquals(emptyList(), message.getRepeatedGroupList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedGroup(); - assertEquals(emptyList(), builder.getRepeatedGroupList()); - assertEquals( - singletonList(RepeatedGroup.getDefaultInstance()), - messageAfterBuild.getRepeatedGroupList()); - - message = builder.build(); - builder.addAllRepeatedInt32(singletonList(1)); - assertEquals(emptyList(), message.getRepeatedInt32List()); - assertEquals(singletonList(1), builder.getRepeatedInt32List()); - assertEquals(emptyList(), message.getRepeatedInt32List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedInt32(); - assertEquals(emptyList(), builder.getRepeatedInt32List()); - assertEquals(singletonList(1), messageAfterBuild.getRepeatedInt32List()); - - message = builder.build(); - builder.addAllRepeatedInt64(singletonList(1L)); - assertEquals(emptyList(), message.getRepeatedInt64List()); - assertEquals(singletonList(1L), builder.getRepeatedInt64List()); - assertEquals(emptyList(), message.getRepeatedInt64List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedInt64(); - assertEquals(emptyList(), builder.getRepeatedInt64List()); - assertEquals(singletonList(1L), messageAfterBuild.getRepeatedInt64List()); - - message = builder.build(); - builder.addAllRepeatedLazyMessage(singletonList(nestedMessage)); - assertEquals(emptyList(), message.getRepeatedLazyMessageList()); - assertEquals( - singletonList(nestedMessage), builder.getRepeatedLazyMessageList()); - assertEquals(emptyList(), message.getRepeatedLazyMessageList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedLazyMessage(); - assertEquals(emptyList(), builder.getRepeatedLazyMessageList()); - assertEquals( - singletonList(nestedMessage), - messageAfterBuild.getRepeatedLazyMessageList()); - - message = builder.build(); - builder.addAllRepeatedSfixed32(singletonList(1)); - assertEquals(emptyList(), message.getRepeatedSfixed32List()); - assertEquals(singletonList(1), builder.getRepeatedSfixed32List()); - assertEquals(emptyList(), message.getRepeatedSfixed32List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedSfixed32(); - assertEquals(emptyList(), builder.getRepeatedSfixed32List()); - assertEquals(singletonList(1), messageAfterBuild.getRepeatedSfixed32List()); - - message = builder.build(); - builder.addAllRepeatedSfixed64(singletonList(1L)); - assertEquals(emptyList(), message.getRepeatedSfixed64List()); - assertEquals(singletonList(1L), builder.getRepeatedSfixed64List()); - assertEquals(emptyList(), message.getRepeatedSfixed64List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedSfixed64(); - assertEquals(emptyList(), builder.getRepeatedSfixed64List()); - assertEquals( - singletonList(1L), messageAfterBuild.getRepeatedSfixed64List()); - - message = builder.build(); - builder.addAllRepeatedSint32(singletonList(1)); - assertEquals(emptyList(), message.getRepeatedSint32List()); - assertEquals(singletonList(1), builder.getRepeatedSint32List()); - assertEquals(emptyList(), message.getRepeatedSint32List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedSint32(); - assertEquals(emptyList(), builder.getRepeatedSint32List()); - assertEquals(singletonList(1), messageAfterBuild.getRepeatedSint32List()); - - message = builder.build(); - builder.addAllRepeatedSint64(singletonList(1L)); - assertEquals(emptyList(), message.getRepeatedSint64List()); - assertEquals(singletonList(1L), builder.getRepeatedSint64List()); - assertEquals(emptyList(), message.getRepeatedSint64List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedSint64(); - assertEquals(emptyList(), builder.getRepeatedSint64List()); - assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSint64List()); - - message = builder.build(); - builder.addAllRepeatedString(singletonList("hi")); - assertEquals(emptyList(), message.getRepeatedStringList()); - assertEquals(singletonList("hi"), builder.getRepeatedStringList()); - assertEquals(emptyList(), message.getRepeatedStringList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedString(); - assertEquals(emptyList(), builder.getRepeatedStringList()); - assertEquals( - singletonList("hi"), messageAfterBuild.getRepeatedStringList()); - - message = builder.build(); - builder.addAllRepeatedStringPiece(singletonList("hi")); - assertEquals(emptyList(), message.getRepeatedStringPieceList()); - assertEquals(singletonList("hi"), builder.getRepeatedStringPieceList()); - assertEquals(emptyList(), message.getRepeatedStringPieceList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedStringPiece(); - assertEquals(emptyList(), builder.getRepeatedStringPieceList()); - assertEquals( - singletonList("hi"), messageAfterBuild.getRepeatedStringPieceList()); - - message = builder.build(); - builder.addAllRepeatedUint32(singletonList(1)); - assertEquals(emptyList(), message.getRepeatedUint32List()); - assertEquals(singletonList(1), builder.getRepeatedUint32List()); - assertEquals(emptyList(), message.getRepeatedUint32List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedUint32(); - assertEquals(emptyList(), builder.getRepeatedUint32List()); - assertEquals(singletonList(1), messageAfterBuild.getRepeatedUint32List()); - - message = builder.build(); - builder.addAllRepeatedUint64(singletonList(1L)); - assertEquals(emptyList(), message.getRepeatedUint64List()); - assertEquals(singletonList(1L), builder.getRepeatedUint64List()); - assertEquals(emptyList(), message.getRepeatedUint64List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedUint64(); - assertEquals(emptyList(), builder.getRepeatedUint64List()); - assertEquals(singletonList(1L), messageAfterBuild.getRepeatedUint64List()); - - message = builder.build(); - builder.addRepeatedBool(true); - assertEquals(emptyList(), message.getRepeatedBoolList()); - assertEquals(singletonList(true), builder.getRepeatedBoolList()); - assertEquals(emptyList(), message.getRepeatedBoolList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedBool(); - assertEquals(emptyList(), builder.getRepeatedBoolList()); - assertEquals(singletonList(true), messageAfterBuild.getRepeatedBoolList()); - - message = builder.build(); - builder.addRepeatedBytes(ByteString.copyFromUtf8("hi")); - assertEquals(emptyList(), message.getRepeatedBytesList()); - assertEquals( - singletonList(ByteString.copyFromUtf8("hi")), - builder.getRepeatedBytesList()); - assertEquals(emptyList(), message.getRepeatedBytesList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedBytes(); - assertEquals(emptyList(), builder.getRepeatedBytesList()); - assertEquals( - singletonList(ByteString.copyFromUtf8("hi")), - messageAfterBuild.getRepeatedBytesList()); - - message = builder.build(); - builder.addRepeatedCord("hi"); - assertEquals(emptyList(), message.getRepeatedCordList()); - assertEquals(singletonList("hi"), builder.getRepeatedCordList()); - assertEquals(emptyList(), message.getRepeatedCordList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedCord(); - assertEquals(emptyList(), builder.getRepeatedCordList()); - assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedCordList()); - - message = builder.build(); - builder.addRepeatedDouble(1D); - assertEquals(emptyList(), message.getRepeatedDoubleList()); - assertEquals(singletonList(1D), builder.getRepeatedDoubleList()); - assertEquals(emptyList(), message.getRepeatedDoubleList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedDouble(); - assertEquals(emptyList(), builder.getRepeatedDoubleList()); - assertEquals(singletonList(1D), messageAfterBuild.getRepeatedDoubleList()); - - message = builder.build(); - builder.addRepeatedFixed32(1); - assertEquals(emptyList(), message.getRepeatedFixed32List()); - assertEquals(singletonList(1), builder.getRepeatedFixed32List()); - assertEquals(emptyList(), message.getRepeatedFixed32List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedFixed32(); - assertEquals(emptyList(), builder.getRepeatedFixed32List()); - assertEquals(singletonList(1), messageAfterBuild.getRepeatedFixed32List()); - - message = builder.build(); - builder.addRepeatedFixed64(1L); - assertEquals(emptyList(), message.getRepeatedFixed64List()); - assertEquals(singletonList(1L), builder.getRepeatedFixed64List()); - assertEquals(emptyList(), message.getRepeatedFixed64List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedFixed64(); - assertEquals(emptyList(), builder.getRepeatedFixed64List()); - assertEquals(singletonList(1L), messageAfterBuild.getRepeatedFixed64List()); - - message = builder.build(); - builder.addRepeatedFloat(1F); - assertEquals(emptyList(), message.getRepeatedFloatList()); - assertEquals(singletonList(1F), builder.getRepeatedFloatList()); - assertEquals(emptyList(), message.getRepeatedFloatList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedFloat(); - assertEquals(emptyList(), builder.getRepeatedFloatList()); - assertEquals(singletonList(1F), messageAfterBuild.getRepeatedFloatList()); - - message = builder.build(); - builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR); - assertEquals(emptyList(), message.getRepeatedForeignEnumList()); - assertEquals( - singletonList(ForeignEnumLite.FOREIGN_LITE_BAR), - builder.getRepeatedForeignEnumList()); - assertEquals(emptyList(), message.getRepeatedForeignEnumList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedForeignEnum(); - assertEquals(emptyList(), builder.getRepeatedForeignEnumList()); - assertEquals( - singletonList(ForeignEnumLite.FOREIGN_LITE_BAR), - messageAfterBuild.getRepeatedForeignEnumList()); - - message = builder.build(); - builder.addRepeatedForeignMessage(foreignMessage); - assertEquals(emptyList(), message.getRepeatedForeignMessageList()); - assertEquals( - singletonList(foreignMessage), builder.getRepeatedForeignMessageList()); - assertEquals(emptyList(), message.getRepeatedForeignMessageList()); - messageAfterBuild = builder.build(); - builder.removeRepeatedForeignMessage(0); - assertEquals(emptyList(), builder.getRepeatedForeignMessageList()); - assertEquals( - singletonList(foreignMessage), - messageAfterBuild.getRepeatedForeignMessageList()); - - message = builder.build(); - builder.addRepeatedGroup(RepeatedGroup.getDefaultInstance()); - assertEquals(emptyList(), message.getRepeatedGroupList()); - assertEquals( - singletonList(RepeatedGroup.getDefaultInstance()), - builder.getRepeatedGroupList()); - assertEquals(emptyList(), message.getRepeatedGroupList()); - messageAfterBuild = builder.build(); - builder.removeRepeatedGroup(0); - assertEquals(emptyList(), builder.getRepeatedGroupList()); - assertEquals( - singletonList(RepeatedGroup.getDefaultInstance()), - messageAfterBuild.getRepeatedGroupList()); - - message = builder.build(); - builder.addRepeatedInt32(1); - assertEquals(emptyList(), message.getRepeatedInt32List()); - assertEquals(singletonList(1), builder.getRepeatedInt32List()); - assertEquals(emptyList(), message.getRepeatedInt32List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedInt32(); - assertEquals(emptyList(), builder.getRepeatedInt32List()); - assertEquals(singletonList(1), messageAfterBuild.getRepeatedInt32List()); - - message = builder.build(); - builder.addRepeatedInt64(1L); - assertEquals(emptyList(), message.getRepeatedInt64List()); - assertEquals(singletonList(1L), builder.getRepeatedInt64List()); - assertEquals(emptyList(), message.getRepeatedInt64List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedInt64(); - assertEquals(emptyList(), builder.getRepeatedInt64List()); - assertEquals(singletonList(1L), messageAfterBuild.getRepeatedInt64List()); - - message = builder.build(); - builder.addRepeatedLazyMessage(nestedMessage); - assertEquals(emptyList(), message.getRepeatedLazyMessageList()); - assertEquals( - singletonList(nestedMessage), builder.getRepeatedLazyMessageList()); - assertEquals(emptyList(), message.getRepeatedLazyMessageList()); - messageAfterBuild = builder.build(); - builder.removeRepeatedLazyMessage(0); - assertEquals(emptyList(), builder.getRepeatedLazyMessageList()); - assertEquals( - singletonList(nestedMessage), - messageAfterBuild.getRepeatedLazyMessageList()); - - message = builder.build(); - builder.addRepeatedSfixed32(1); - assertEquals(emptyList(), message.getRepeatedSfixed32List()); - assertEquals(singletonList(1), builder.getRepeatedSfixed32List()); - assertEquals(emptyList(), message.getRepeatedSfixed32List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedSfixed32(); - assertEquals(emptyList(), builder.getRepeatedSfixed32List()); - assertEquals(singletonList(1), messageAfterBuild.getRepeatedSfixed32List()); - - message = builder.build(); - builder.addRepeatedSfixed64(1L); - assertEquals(emptyList(), message.getRepeatedSfixed64List()); - assertEquals(singletonList(1L), builder.getRepeatedSfixed64List()); - assertEquals(emptyList(), message.getRepeatedSfixed64List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedSfixed64(); - assertEquals(emptyList(), builder.getRepeatedSfixed64List()); - assertEquals( - singletonList(1L), messageAfterBuild.getRepeatedSfixed64List()); - - message = builder.build(); - builder.addRepeatedSint32(1); - assertEquals(emptyList(), message.getRepeatedSint32List()); - assertEquals(singletonList(1), builder.getRepeatedSint32List()); - assertEquals(emptyList(), message.getRepeatedSint32List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedSint32(); - assertEquals(emptyList(), builder.getRepeatedSint32List()); - assertEquals(singletonList(1), messageAfterBuild.getRepeatedSint32List()); - - message = builder.build(); - builder.addRepeatedSint64(1L); - assertEquals(emptyList(), message.getRepeatedSint64List()); - assertEquals(singletonList(1L), builder.getRepeatedSint64List()); - assertEquals(emptyList(), message.getRepeatedSint64List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedSint64(); - assertEquals(emptyList(), builder.getRepeatedSint64List()); - assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSint64List()); - - message = builder.build(); - builder.addRepeatedString("hi"); - assertEquals(emptyList(), message.getRepeatedStringList()); - assertEquals(singletonList("hi"), builder.getRepeatedStringList()); - assertEquals(emptyList(), message.getRepeatedStringList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedString(); - assertEquals(emptyList(), builder.getRepeatedStringList()); - assertEquals( - singletonList("hi"), messageAfterBuild.getRepeatedStringList()); - - message = builder.build(); - builder.addRepeatedStringPiece("hi"); - assertEquals(emptyList(), message.getRepeatedStringPieceList()); - assertEquals(singletonList("hi"), builder.getRepeatedStringPieceList()); - assertEquals(emptyList(), message.getRepeatedStringPieceList()); - messageAfterBuild = builder.build(); - builder.clearRepeatedStringPiece(); - assertEquals(emptyList(), builder.getRepeatedStringPieceList()); - assertEquals( - singletonList("hi"), messageAfterBuild.getRepeatedStringPieceList()); - - message = builder.build(); - builder.addRepeatedUint32(1); - assertEquals(emptyList(), message.getRepeatedUint32List()); - assertEquals(singletonList(1), builder.getRepeatedUint32List()); - assertEquals(emptyList(), message.getRepeatedUint32List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedUint32(); - assertEquals(emptyList(), builder.getRepeatedUint32List()); - assertEquals(singletonList(1), messageAfterBuild.getRepeatedUint32List()); - - message = builder.build(); - builder.addRepeatedUint64(1L); - assertEquals(emptyList(), message.getRepeatedUint64List()); - assertEquals(singletonList(1L), builder.getRepeatedUint64List()); - assertEquals(emptyList(), message.getRepeatedUint64List()); - messageAfterBuild = builder.build(); - builder.clearRepeatedUint64(); - assertEquals(emptyList(), builder.getRepeatedUint64List()); - assertEquals(singletonList(1L), messageAfterBuild.getRepeatedUint64List()); - - message = builder.build(); - builder.addRepeatedBool(true); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedBoolCount()); - builder.setRepeatedBool(0, false); - assertEquals(true, messageAfterBuild.getRepeatedBool(0)); - assertEquals(false, builder.getRepeatedBool(0)); - builder.clearRepeatedBool(); - - message = builder.build(); - builder.addRepeatedBytes(ByteString.copyFromUtf8("hi")); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedBytesCount()); - builder.setRepeatedBytes(0, ByteString.EMPTY); - assertEquals( - ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedBytes(0)); - assertEquals(ByteString.EMPTY, builder.getRepeatedBytes(0)); - builder.clearRepeatedBytes(); - - message = builder.build(); - builder.addRepeatedCord("hi"); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedCordCount()); - builder.setRepeatedCord(0, ""); - assertEquals("hi", messageAfterBuild.getRepeatedCord(0)); - assertEquals("", builder.getRepeatedCord(0)); - builder.clearRepeatedCord(); - message = builder.build(); - - builder.addRepeatedCordBytes(ByteString.copyFromUtf8("hi")); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedCordCount()); - builder.setRepeatedCord(0, ""); - assertEquals( - ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedCordBytes(0)); - assertEquals(ByteString.EMPTY, builder.getRepeatedCordBytes(0)); - builder.clearRepeatedCord(); - - message = builder.build(); - builder.addRepeatedDouble(1D); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedDoubleCount()); - builder.setRepeatedDouble(0, 0D); - assertEquals(1D, messageAfterBuild.getRepeatedDouble(0)); - assertEquals(0D, builder.getRepeatedDouble(0)); - builder.clearRepeatedDouble(); - - message = builder.build(); - builder.addRepeatedFixed32(1); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedFixed32Count()); - builder.setRepeatedFixed32(0, 0); - assertEquals(1, messageAfterBuild.getRepeatedFixed32(0)); - assertEquals(0, builder.getRepeatedFixed32(0)); - builder.clearRepeatedFixed32(); - - message = builder.build(); - builder.addRepeatedFixed64(1L); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedFixed64Count()); - builder.setRepeatedFixed64(0, 0L); - assertEquals(1L, messageAfterBuild.getRepeatedFixed64(0)); - assertEquals(0L, builder.getRepeatedFixed64(0)); - builder.clearRepeatedFixed64(); - - message = builder.build(); - builder.addRepeatedFloat(1F); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedFloatCount()); - builder.setRepeatedFloat(0, 0F); - assertEquals(1F, messageAfterBuild.getRepeatedFloat(0)); - assertEquals(0F, builder.getRepeatedFloat(0)); - builder.clearRepeatedFloat(); - - message = builder.build(); - builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedForeignEnumCount()); - builder.setRepeatedForeignEnum(0, ForeignEnumLite.FOREIGN_LITE_FOO); - assertEquals( - ForeignEnumLite.FOREIGN_LITE_BAR, - messageAfterBuild.getRepeatedForeignEnum(0)); - assertEquals( - ForeignEnumLite.FOREIGN_LITE_FOO, builder.getRepeatedForeignEnum(0)); - builder.clearRepeatedForeignEnum(); - - message = builder.build(); - builder.addRepeatedForeignMessage(foreignMessage); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedForeignMessageCount()); - builder.setRepeatedForeignMessage( - 0, ForeignMessageLite.getDefaultInstance()); - assertEquals( - foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0)); - assertEquals( - ForeignMessageLite.getDefaultInstance(), - builder.getRepeatedForeignMessage(0)); - builder.clearRepeatedForeignMessage(); - - message = builder.build(); - builder.addRepeatedForeignMessage(foreignMessageBuilder); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedForeignMessageCount()); - builder.setRepeatedForeignMessage( - 0, ForeignMessageLite.getDefaultInstance()); - assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getRepeatedForeignMessage(0)); - assertEquals( - ForeignMessageLite.getDefaultInstance(), - builder.getRepeatedForeignMessage(0)); - builder.clearRepeatedForeignMessage(); - - message = builder.build(); - builder.addRepeatedForeignMessage(0, foreignMessage); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedForeignMessageCount()); - builder.setRepeatedForeignMessage(0, foreignMessageBuilder); - assertEquals( - foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0)); - assertEquals(foreignMessageBuilder.build(), builder.getRepeatedForeignMessage(0)); - builder.clearRepeatedForeignMessage(); - - message = builder.build(); - RepeatedGroup repeatedGroup = RepeatedGroup.newBuilder() - .setA(1) - .build(); - builder.addRepeatedGroup(repeatedGroup); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedGroupCount()); - builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance()); - assertEquals(repeatedGroup, messageAfterBuild.getRepeatedGroup(0)); - assertEquals( - RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0)); - builder.clearRepeatedGroup(); - - message = builder.build(); - builder.addRepeatedGroup(0, repeatedGroup); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedGroupCount()); - builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance()); - assertEquals(repeatedGroup, messageAfterBuild.getRepeatedGroup(0)); - assertEquals( - RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0)); - builder.clearRepeatedGroup(); - - message = builder.build(); - RepeatedGroup.Builder repeatedGroupBuilder = RepeatedGroup.newBuilder() - .setA(3); - builder.addRepeatedGroup(repeatedGroupBuilder); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedGroupCount()); - builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance()); - assertEquals(repeatedGroupBuilder.build(), messageAfterBuild.getRepeatedGroup(0)); - assertEquals( - RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0)); - builder.clearRepeatedGroup(); - - message = builder.build(); - builder.addRepeatedGroup(0, repeatedGroupBuilder); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedGroupCount()); - builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance()); - assertEquals(repeatedGroupBuilder.build(), messageAfterBuild.getRepeatedGroup(0)); - assertEquals( - RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0)); - builder.clearRepeatedGroup(); - - message = builder.build(); - builder.addRepeatedInt32(1); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedInt32Count()); - builder.setRepeatedInt32(0, 0); - assertEquals(1, messageAfterBuild.getRepeatedInt32(0)); - assertEquals(0, builder.getRepeatedInt32(0)); - builder.clearRepeatedInt32(); - - message = builder.build(); - builder.addRepeatedInt64(1L); - messageAfterBuild = builder.build(); - assertEquals(0L, message.getRepeatedInt64Count()); - builder.setRepeatedInt64(0, 0L); - assertEquals(1L, messageAfterBuild.getRepeatedInt64(0)); - assertEquals(0L, builder.getRepeatedInt64(0)); - builder.clearRepeatedInt64(); - - message = builder.build(); - builder.addRepeatedLazyMessage(nestedMessage); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedLazyMessageCount()); - builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance()); - assertEquals(nestedMessage, messageAfterBuild.getRepeatedLazyMessage(0)); - assertEquals( - NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0)); - builder.clearRepeatedLazyMessage(); - - message = builder.build(); - builder.addRepeatedLazyMessage(0, nestedMessage); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedLazyMessageCount()); - builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance()); - assertEquals(nestedMessage, messageAfterBuild.getRepeatedLazyMessage(0)); - assertEquals( - NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0)); - builder.clearRepeatedLazyMessage(); - - message = builder.build(); - builder.addRepeatedLazyMessage(nestedMessageBuilder); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedLazyMessageCount()); - builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance()); - assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getRepeatedLazyMessage(0)); - assertEquals( - NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0)); - builder.clearRepeatedLazyMessage(); - - message = builder.build(); - builder.addRepeatedLazyMessage(0, nestedMessageBuilder); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedLazyMessageCount()); - builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance()); - assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getRepeatedLazyMessage(0)); - assertEquals( - NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0)); - builder.clearRepeatedLazyMessage(); - - message = builder.build(); - builder.addRepeatedSfixed32(1); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedSfixed32Count()); - builder.setRepeatedSfixed32(0, 0); - assertEquals(1, messageAfterBuild.getRepeatedSfixed32(0)); - assertEquals(0, builder.getRepeatedSfixed32(0)); - builder.clearRepeatedSfixed32(); - - message = builder.build(); - builder.addRepeatedSfixed64(1L); - messageAfterBuild = builder.build(); - assertEquals(0L, message.getRepeatedSfixed64Count()); - builder.setRepeatedSfixed64(0, 0L); - assertEquals(1L, messageAfterBuild.getRepeatedSfixed64(0)); - assertEquals(0L, builder.getRepeatedSfixed64(0)); - builder.clearRepeatedSfixed64(); - - message = builder.build(); - builder.addRepeatedSint32(1); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedSint32Count()); - builder.setRepeatedSint32(0, 0); - assertEquals(1, messageAfterBuild.getRepeatedSint32(0)); - assertEquals(0, builder.getRepeatedSint32(0)); - builder.clearRepeatedSint32(); - - message = builder.build(); - builder.addRepeatedSint64(1L); - messageAfterBuild = builder.build(); - assertEquals(0L, message.getRepeatedSint64Count()); - builder.setRepeatedSint64(0, 0L); - assertEquals(1L, messageAfterBuild.getRepeatedSint64(0)); - assertEquals(0L, builder.getRepeatedSint64(0)); - builder.clearRepeatedSint64(); - - message = builder.build(); - builder.addRepeatedString("hi"); - messageAfterBuild = builder.build(); - assertEquals(0L, message.getRepeatedStringCount()); - builder.setRepeatedString(0, ""); - assertEquals("hi", messageAfterBuild.getRepeatedString(0)); - assertEquals("", builder.getRepeatedString(0)); - builder.clearRepeatedString(); - - message = builder.build(); - builder.addRepeatedStringBytes(ByteString.copyFromUtf8("hi")); - messageAfterBuild = builder.build(); - assertEquals(0L, message.getRepeatedStringCount()); - builder.setRepeatedString(0, ""); - assertEquals( - ByteString.copyFromUtf8("hi"), - messageAfterBuild.getRepeatedStringBytes(0)); - assertEquals(ByteString.EMPTY, builder.getRepeatedStringBytes(0)); - builder.clearRepeatedString(); - - message = builder.build(); - builder.addRepeatedStringPiece("hi"); - messageAfterBuild = builder.build(); - assertEquals(0L, message.getRepeatedStringPieceCount()); - builder.setRepeatedStringPiece(0, ""); - assertEquals("hi", messageAfterBuild.getRepeatedStringPiece(0)); - assertEquals("", builder.getRepeatedStringPiece(0)); - builder.clearRepeatedStringPiece(); - - message = builder.build(); - builder.addRepeatedStringPieceBytes(ByteString.copyFromUtf8("hi")); - messageAfterBuild = builder.build(); - assertEquals(0L, message.getRepeatedStringPieceCount()); - builder.setRepeatedStringPiece(0, ""); - assertEquals( - ByteString.copyFromUtf8("hi"), - messageAfterBuild.getRepeatedStringPieceBytes(0)); - assertEquals(ByteString.EMPTY, builder.getRepeatedStringPieceBytes(0)); - builder.clearRepeatedStringPiece(); - - message = builder.build(); - builder.addRepeatedUint32(1); - messageAfterBuild = builder.build(); - assertEquals(0, message.getRepeatedUint32Count()); - builder.setRepeatedUint32(0, 0); - assertEquals(1, messageAfterBuild.getRepeatedUint32(0)); - assertEquals(0, builder.getRepeatedUint32(0)); - builder.clearRepeatedUint32(); - - message = builder.build(); - builder.addRepeatedUint64(1L); - messageAfterBuild = builder.build(); - assertEquals(0L, message.getRepeatedUint64Count()); - builder.setRepeatedUint64(0, 0L); - assertEquals(1L, messageAfterBuild.getRepeatedUint64(0)); - assertEquals(0L, builder.getRepeatedUint64(0)); - builder.clearRepeatedUint64(); - - message = builder.build(); - assertEquals(0, message.getSerializedSize()); - builder.mergeFrom(TestAllTypesLite.newBuilder() - .setOptionalBool(true) - .build()); - assertEquals(0, message.getSerializedSize()); - assertEquals(true, builder.build().getOptionalBool()); - builder.clearOptionalBool(); - - message = builder.build(); - assertEquals(0, message.getSerializedSize()); - builder.mergeFrom(TestAllTypesLite.newBuilder() - .setOptionalBool(true) - .build()); - assertEquals(0, message.getSerializedSize()); - assertEquals(true, builder.build().getOptionalBool()); - builder.clear(); - assertEquals(0, builder.build().getSerializedSize()); - - message = builder.build(); - assertEquals(0, message.getSerializedSize()); - builder.mergeOptionalForeignMessage(foreignMessage); - assertEquals(0, message.getSerializedSize()); - assertEquals( - foreignMessage.getC(), - builder.build().getOptionalForeignMessage().getC()); - builder.clearOptionalForeignMessage(); - - message = builder.build(); - assertEquals(0, message.getSerializedSize()); - builder.mergeOptionalLazyMessage(nestedMessage); - assertEquals(0, message.getSerializedSize()); - assertEquals( - nestedMessage.getBb(), - builder.build().getOptionalLazyMessage().getBb()); - builder.clearOptionalLazyMessage(); - - message = builder.build(); - builder.setOneofString("hi"); - assertEquals( - OneofFieldCase.ONEOFFIELD_NOT_SET, message.getOneofFieldCase()); - assertEquals(OneofFieldCase.ONEOF_STRING, builder.getOneofFieldCase()); - assertEquals("hi", builder.getOneofString()); - messageAfterBuild = builder.build(); - assertEquals( - OneofFieldCase.ONEOF_STRING, messageAfterBuild.getOneofFieldCase()); - assertEquals("hi", messageAfterBuild.getOneofString()); - builder.setOneofUint32(1); - assertEquals( - OneofFieldCase.ONEOF_STRING, messageAfterBuild.getOneofFieldCase()); - assertEquals("hi", messageAfterBuild.getOneofString()); - assertEquals(OneofFieldCase.ONEOF_UINT32, builder.getOneofFieldCase()); - assertEquals(1, builder.getOneofUint32()); - TestAllTypesLiteOrBuilder messageOrBuilder = builder; - assertEquals(OneofFieldCase.ONEOF_UINT32, messageOrBuilder.getOneofFieldCase()); - - TestAllExtensionsLite.Builder extendableMessageBuilder = - TestAllExtensionsLite.newBuilder(); - TestAllExtensionsLite extendableMessage = extendableMessageBuilder.build(); - extendableMessageBuilder.setExtension( - UnittestLite.optionalInt32ExtensionLite, 1); - assertFalse(extendableMessage.hasExtension( - UnittestLite.optionalInt32ExtensionLite)); - extendableMessage = extendableMessageBuilder.build(); - assertEquals( - 1, (int) extendableMessageBuilder.getExtension( - UnittestLite.optionalInt32ExtensionLite)); - assertEquals( - 1, (int) extendableMessage.getExtension( - UnittestLite.optionalInt32ExtensionLite)); - extendableMessageBuilder.setExtension( - UnittestLite.optionalInt32ExtensionLite, 3); - assertEquals( - 3, (int) extendableMessageBuilder.getExtension( - UnittestLite.optionalInt32ExtensionLite)); - assertEquals( - 1, (int) extendableMessage.getExtension( - UnittestLite.optionalInt32ExtensionLite)); - extendableMessage = extendableMessageBuilder.build(); - assertEquals( - 3, (int) extendableMessageBuilder.getExtension( - UnittestLite.optionalInt32ExtensionLite)); - assertEquals( - 3, (int) extendableMessage.getExtension( - UnittestLite.optionalInt32ExtensionLite)); - - // No extension registry, so it should be in unknown fields. - extendableMessage = - TestAllExtensionsLite.parseFrom(extendableMessage.toByteArray()); - assertFalse(extendableMessage.hasExtension( - UnittestLite.optionalInt32ExtensionLite)); - - extendableMessageBuilder = extendableMessage.toBuilder(); - extendableMessageBuilder.mergeFrom(TestAllExtensionsLite.newBuilder() - .setExtension(UnittestLite.optionalFixed32ExtensionLite, 11) - .build()); - - extendableMessage = extendableMessageBuilder.build(); - ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); - UnittestLite.registerAllExtensions(registry); - extendableMessage = TestAllExtensionsLite.parseFrom( - extendableMessage.toByteArray(), registry); - - // The unknown field was preserved. - assertEquals( - 3, (int) extendableMessage.getExtension( - UnittestLite.optionalInt32ExtensionLite)); - assertEquals( - 11, (int) extendableMessage.getExtension( - UnittestLite.optionalFixed32ExtensionLite)); - } - - public void testToStringDefaultInstance() throws Exception { - assertToStringEquals("", TestAllTypesLite.getDefaultInstance()); - } - - public void testToStringScalarFieldsSuffixedWithList() throws Exception { - assertToStringEquals("deceptively_named_list: 7", TestAllTypesLite.newBuilder() - .setDeceptivelyNamedList(7) - .build()); - } - - public void testToStringPrimitives() throws Exception { - TestAllTypesLite proto = TestAllTypesLite.newBuilder() - .setOptionalInt32(1) - .setOptionalInt64(9223372036854775807L) - .build(); - assertToStringEquals("optional_int32: 1\noptional_int64: 9223372036854775807", proto); - - proto = TestAllTypesLite.newBuilder() - .setOptionalBool(true) - .setOptionalNestedEnum(TestAllTypesLite.NestedEnum.BAZ) - .build(); - assertToStringEquals("optional_bool: true\noptional_nested_enum: BAZ", proto); - - proto = TestAllTypesLite.newBuilder() - .setOptionalFloat(2.72f) - .setOptionalDouble(3.14) - .build(); - assertToStringEquals("optional_double: 3.14\noptional_float: 2.72", proto); - } - - public void testToStringStringFields() throws Exception { - TestAllTypesLite proto = TestAllTypesLite.newBuilder() - .setOptionalString("foo\"bar\nbaz\\") - .build(); - assertToStringEquals("optional_string: \"foo\\\"bar\\nbaz\\\\\"", proto); - - proto = TestAllTypesLite.newBuilder() - .setOptionalString("\u6587") - .build(); - assertToStringEquals("optional_string: \"\\346\\226\\207\"", proto); - } - - public void testToStringNestedMessage() throws Exception { - TestAllTypesLite proto = TestAllTypesLite.newBuilder() - .setOptionalNestedMessage(TestAllTypesLite.NestedMessage.getDefaultInstance()) - .build(); - assertToStringEquals("optional_nested_message {\n}", proto); - - proto = TestAllTypesLite.newBuilder() - .setOptionalNestedMessage( - TestAllTypesLite.NestedMessage.newBuilder().setBb(7)) - .build(); - assertToStringEquals("optional_nested_message {\n bb: 7\n}", proto); - } - - public void testToStringRepeatedFields() throws Exception { - TestAllTypesLite proto = TestAllTypesLite.newBuilder() - .addRepeatedInt32(32) - .addRepeatedInt32(32) - .addRepeatedInt64(64) - .build(); - assertToStringEquals("repeated_int32: 32\nrepeated_int32: 32\nrepeated_int64: 64", proto); - - proto = TestAllTypesLite.newBuilder() - .addRepeatedLazyMessage( - TestAllTypesLite.NestedMessage.newBuilder().setBb(7)) - .addRepeatedLazyMessage( - TestAllTypesLite.NestedMessage.newBuilder().setBb(8)) - .build(); - assertToStringEquals( - "repeated_lazy_message {\n bb: 7\n}\nrepeated_lazy_message {\n bb: 8\n}", - proto); - } - - public void testToStringForeignFields() throws Exception { - TestAllTypesLite proto = TestAllTypesLite.newBuilder() - .setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR) - .setOptionalForeignMessage( - ForeignMessageLite.newBuilder() - .setC(3)) - .build(); - assertToStringEquals( - "optional_foreign_enum: FOREIGN_LITE_BAR\noptional_foreign_message {\n c: 3\n}", - proto); - } - - public void testToStringExtensions() throws Exception { - TestAllExtensionsLite message = TestAllExtensionsLite.newBuilder() - .setExtension(UnittestLite.optionalInt32ExtensionLite, 123) - .addExtension(UnittestLite.repeatedStringExtensionLite, "spam") - .addExtension(UnittestLite.repeatedStringExtensionLite, "eggs") - .setExtension(UnittestLite.optionalNestedEnumExtensionLite, - TestAllTypesLite.NestedEnum.BAZ) - .setExtension(UnittestLite.optionalNestedMessageExtensionLite, - TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build()) - .build(); - assertToStringEquals( - "[1]: 123\n[18] {\n bb: 7\n}\n[21]: 3\n[44]: \"spam\"\n[44]: \"eggs\"", - message); - } - - public void testToStringUnknownFields() throws Exception { - TestAllExtensionsLite messageWithExtensions = TestAllExtensionsLite.newBuilder() - .setExtension(UnittestLite.optionalInt32ExtensionLite, 123) - .addExtension(UnittestLite.repeatedStringExtensionLite, "spam") - .addExtension(UnittestLite.repeatedStringExtensionLite, "eggs") - .setExtension(UnittestLite.optionalNestedEnumExtensionLite, - TestAllTypesLite.NestedEnum.BAZ) - .setExtension(UnittestLite.optionalNestedMessageExtensionLite, - TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build()) - .build(); - TestAllExtensionsLite messageWithUnknownFields = TestAllExtensionsLite.parseFrom( - messageWithExtensions.toByteArray()); - assertToStringEquals( - "1: 123\n18: \"\\b\\a\"\n21: 3\n44: \"spam\"\n44: \"eggs\"", - messageWithUnknownFields); - } - - public void testToStringLazyMessage() throws Exception { - TestAllTypesLite message = TestAllTypesLite.newBuilder() - .setOptionalLazyMessage(NestedMessage.newBuilder().setBb(1).build()) - .build(); - assertToStringEquals("optional_lazy_message {\n bb: 1\n}", message); - } - - public void testToStringGroup() throws Exception { - TestAllTypesLite message = TestAllTypesLite.newBuilder() - .setOptionalGroup(OptionalGroup.newBuilder().setA(1).build()) - .build(); - assertToStringEquals("optional_group {\n a: 1\n}", message); - } - - public void testToStringOneof() throws Exception { - TestAllTypesLite message = TestAllTypesLite.newBuilder() - .setOneofString("hello") - .build(); - assertToStringEquals("oneof_string: \"hello\"", message); - } - - // Asserts that the toString() representation of the message matches the expected. This verifies - // the first line starts with a comment; but, does not factor in said comment as part of the - // comparison as it contains unstable addresses. - private static void assertToStringEquals(String expected, MessageLite message) { - String toString = message.toString(); - assertEquals('#', toString.charAt(0)); - if (toString.indexOf("\n") >= 0) { - toString = toString.substring(toString.indexOf("\n") + 1); - } else { - toString = ""; - } - assertEquals(expected, toString); - } - - public void testParseLazy() throws Exception { - ByteString bb = TestAllTypesLite.newBuilder() - .setOptionalLazyMessage(NestedMessage.newBuilder() - .setBb(11) - .build()) - .build().toByteString(); - ByteString cc = TestAllTypesLite.newBuilder() - .setOptionalLazyMessage(NestedMessage.newBuilder() - .setCc(22) - .build()) - .build().toByteString(); - - ByteString concat = bb.concat(cc); - TestAllTypesLite message = TestAllTypesLite.parseFrom(concat); - - assertEquals(11, message.getOptionalLazyMessage().getBb()); - assertEquals(22L, message.getOptionalLazyMessage().getCc()); - } - - public void testParseLazy_oneOf() throws Exception { - ByteString bb = TestAllTypesLite.newBuilder() - .setOneofLazyNestedMessage(NestedMessage.newBuilder() - .setBb(11) - .build()) - .build().toByteString(); - ByteString cc = TestAllTypesLite.newBuilder() - .setOneofLazyNestedMessage(NestedMessage.newBuilder() - .setCc(22) - .build()) - .build().toByteString(); - - ByteString concat = bb.concat(cc); - TestAllTypesLite message = TestAllTypesLite.parseFrom(concat); - - assertEquals(11, message.getOneofLazyNestedMessage().getBb()); - assertEquals(22L, message.getOneofLazyNestedMessage().getCc()); - } - - public void testMergeFromStream_repeatedField() throws Exception { - TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder() - .addRepeatedString("hello"); - builder.mergeFrom(CodedInputStream.newInstance(builder.build().toByteArray())); - - assertEquals(2, builder.getRepeatedStringCount()); - } - - public void testMergeFromStream_invalidBytes() throws Exception { - TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder() - .setDefaultBool(true); - try { - builder.mergeFrom(CodedInputStream.newInstance("Invalid bytes".getBytes(Internal.UTF_8))); - fail(); - } catch (InvalidProtocolBufferException expected) {} - } - - public void testMergeFrom_sanity() throws Exception { - TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build(); - byte[] bytes = one.toByteArray(); - TestAllTypesLite two = TestAllTypesLite.parseFrom(bytes); - - one = one.toBuilder().mergeFrom(one).build(); - two = two.toBuilder().mergeFrom(bytes).build(); - assertEquals(one, two); - assertEquals(two, one); - assertEquals(one.hashCode(), two.hashCode()); - } - - public void testMergeFromNoLazyFieldSharing() throws Exception { - TestAllTypesLite.Builder sourceBuilder = TestAllTypesLite.newBuilder().setOptionalLazyMessage( - TestAllTypesLite.NestedMessage.newBuilder().setBb(1)); - TestAllTypesLite.Builder targetBuilder = - TestAllTypesLite.newBuilder().mergeFrom(sourceBuilder.build()); - assertEquals(1, sourceBuilder.getOptionalLazyMessage().getBb()); - // now change the sourceBuilder, and target value shouldn't be affected. - sourceBuilder.setOptionalLazyMessage( - TestAllTypesLite.NestedMessage.newBuilder().setBb(2)); - assertEquals(1, targetBuilder.getOptionalLazyMessage().getBb()); - } - - public void testEquals_notEqual() throws Exception { - TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build(); - byte[] bytes = one.toByteArray(); - TestAllTypesLite two = one.toBuilder().mergeFrom(one).mergeFrom(bytes).build(); - - assertFalse(one.equals(two)); - assertFalse(two.equals(one)); - - assertFalse(one.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(one)); - - TestAllTypesLite oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultBool(true) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultBytes(ByteString.EMPTY) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultCord("") - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultCordBytes(ByteString.EMPTY) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultDouble(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultFixed32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultFixed64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultFloat(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultImportEnum(ImportEnumLite.IMPORT_LITE_BAR) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultInt32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultInt64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultNestedEnum(NestedEnum.BAR) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultSfixed32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultSfixed64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultSint32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultSint64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultString("") - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultStringBytes(ByteString.EMPTY) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultStringPiece("") - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultStringPieceBytes(ByteString.EMPTY) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultUint32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setDefaultUint64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedBool(true) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedBytes(ByteString.EMPTY) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedCord("") - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedCordBytes(ByteString.EMPTY) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedDouble(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedFixed32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedFixed64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedFloat(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedImportEnum(ImportEnumLite.IMPORT_LITE_BAR) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedInt32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedInt64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedNestedEnum(NestedEnum.BAR) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedSfixed32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedSfixed64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedSint32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedSint64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedString("") - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedStringBytes(ByteString.EMPTY) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedStringPiece("") - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedStringPieceBytes(ByteString.EMPTY) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedUint32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedUint64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalBool(true) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalBytes(ByteString.EMPTY) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalCord("") - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalCordBytes(ByteString.EMPTY) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalDouble(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalFixed32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalFixed64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalFloat(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalImportEnum(ImportEnumLite.IMPORT_LITE_BAR) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalInt32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalInt64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalNestedEnum(NestedEnum.BAR) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalSfixed32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalSfixed64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalSint32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalSint64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalString("") - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalStringBytes(ByteString.EMPTY) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalStringPiece("") - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalStringPieceBytes(ByteString.EMPTY) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalUint32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalUint64(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOneofBytes(ByteString.EMPTY) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOneofLazyNestedMessage(NestedMessage.getDefaultInstance()) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOneofNestedMessage(NestedMessage.getDefaultInstance()) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOneofString("") - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOneofStringBytes(ByteString.EMPTY) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOneofUint32(0) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalForeignMessage(ForeignMessageLite.getDefaultInstance()) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalGroup(OptionalGroup.getDefaultInstance()) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalPublicImportMessage(PublicImportMessageLite.getDefaultInstance()) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - - oneFieldSet = TestAllTypesLite.newBuilder() - .setOptionalLazyMessage(NestedMessage.getDefaultInstance()) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - oneFieldSet = TestAllTypesLite.newBuilder() - .addRepeatedLazyMessage(NestedMessage.getDefaultInstance()) - .build(); - assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); - assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); - } - - public void testEquals() throws Exception { - // Check that two identical objs are equal. - Foo foo1a = Foo.newBuilder() - .setValue(1) - .addBar(Bar.newBuilder().setName("foo1")) - .build(); - Foo foo1b = Foo.newBuilder() - .setValue(1) - .addBar(Bar.newBuilder().setName("foo1")) - .build(); - Foo foo2 = Foo.newBuilder() - .setValue(1) - .addBar(Bar.newBuilder().setName("foo2")) - .build(); - - // Check that equals is doing value rather than object equality. - assertEquals(foo1a, foo1b); - assertEquals(foo1a.hashCode(), foo1b.hashCode()); - - // Check that a diffeent object is not equal. - assertFalse(foo1a.equals(foo2)); - - // Check that two objects which have different types but the same field values are not - // considered to be equal. - Bar bar = Bar.newBuilder().setName("bar").build(); - BarPrime barPrime = BarPrime.newBuilder().setName("bar").build(); - assertFalse(bar.equals(barPrime)); - } - - public void testEqualsAndHashCodeForTrickySchemaTypes() { - Foo foo1 = Foo.newBuilder() - .build(); - Foo foo2 = Foo.newBuilder() - .setSint64(1) - .build(); - Foo foo3 = Foo.newBuilder() - .putMyMap("key", "value2") - .build(); - Foo foo4 = Foo.newBuilder() - .setMyGroup(Foo.MyGroup.newBuilder().setValue(4).build()) - .build(); - - assertEqualsAndHashCodeAreFalse(foo1, foo2); - assertEqualsAndHashCodeAreFalse(foo1, foo3); - assertEqualsAndHashCodeAreFalse(foo1, foo4); - } - - public void testOneofEquals() throws Exception { - TestOneofEquals.Builder builder = TestOneofEquals.newBuilder(); - TestOneofEquals message1 = builder.build(); - // Set message2's name field to default value. The two messages should be different when we - // check with the oneof case. - builder.setName(""); - TestOneofEquals message2 = builder.build(); - assertFalse(message1.equals(message2)); - } - - public void testEquals_sanity() throws Exception { - TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build(); - TestAllTypesLite two = TestAllTypesLite.parseFrom(one.toByteArray()); - assertEquals(one, two); - assertEquals(one.hashCode(), two.hashCode()); - - assertEquals( - one.toBuilder().mergeFrom(two).build(), - two.toBuilder().mergeFrom(two.toByteArray()).build()); - } - - public void testEqualsAndHashCodeWithUnknownFields() throws InvalidProtocolBufferException { - Foo fooWithOnlyValue = Foo.newBuilder() - .setValue(1) - .build(); - - Foo fooWithValueAndExtension = fooWithOnlyValue.toBuilder() - .setValue(1) - .setExtension(Bar.fooExt, Bar.newBuilder() - .setName("name") - .build()) - .build(); - - Foo fooWithValueAndUnknownFields = Foo.parseFrom(fooWithValueAndExtension.toByteArray()); - - assertEqualsAndHashCodeAreFalse(fooWithOnlyValue, fooWithValueAndUnknownFields); - assertEqualsAndHashCodeAreFalse(fooWithValueAndExtension, fooWithValueAndUnknownFields); - } - - public void testEqualsAndHashCodeWithExtensions() throws InvalidProtocolBufferException { - Foo fooWithOnlyValue = Foo.newBuilder() - .setValue(1) - .build(); - - Foo fooWithValueAndExtension = fooWithOnlyValue.toBuilder() - .setValue(1) - .setExtension(Bar.fooExt, Bar.newBuilder() - .setName("name") - .build()) - .build(); - - assertEqualsAndHashCodeAreFalse(fooWithOnlyValue, fooWithValueAndExtension); - } - - // Test to ensure we avoid a class cast exception with oneofs. - public void testEquals_oneOfMessages() { - TestAllTypesLite mine = TestAllTypesLite.newBuilder() - .setOneofString("Hello") - .build(); - - TestAllTypesLite other = TestAllTypesLite.newBuilder() - .setOneofNestedMessage(NestedMessage.getDefaultInstance()) - .build(); - - assertFalse(mine.equals(other)); - assertFalse(other.equals(mine)); - } - - public void testHugeFieldNumbers() throws InvalidProtocolBufferException { - TestHugeFieldNumbersLite message = - TestHugeFieldNumbersLite.newBuilder() - .setOptionalInt32(1) - .addRepeatedInt32(2) - .setOptionalEnum(ForeignEnumLite.FOREIGN_LITE_FOO) - .setOptionalString("xyz") - .setOptionalMessage(ForeignMessageLite.newBuilder().setC(3).build()) - .build(); - - TestHugeFieldNumbersLite parsedMessage = - TestHugeFieldNumbersLite.parseFrom(message.toByteArray()); - assertEquals(1, parsedMessage.getOptionalInt32()); - assertEquals(2, parsedMessage.getRepeatedInt32(0)); - assertEquals(ForeignEnumLite.FOREIGN_LITE_FOO, parsedMessage.getOptionalEnum()); - assertEquals("xyz", parsedMessage.getOptionalString()); - assertEquals(3, parsedMessage.getOptionalMessage().getC()); - } - - private void assertEqualsAndHashCodeAreFalse(Object o1, Object o2) { - assertFalse(o1.equals(o2)); - assertFalse(o1.hashCode() == o2.hashCode()); - } - - public void testRecursiveHashcode() { - // This tests that we don't infinite loop. - TestRecursiveOneof.getDefaultInstance().hashCode(); - } - - public void testParseFromByteBuffer() throws Exception { - TestAllTypesLite message = - TestAllTypesLite.newBuilder() - .setOptionalInt32(123) - .addRepeatedString("hello") - .setOptionalNestedMessage(TestAllTypesLite.NestedMessage.newBuilder().setBb(7)) - .build(); - - TestAllTypesLite copy = - TestAllTypesLite.parseFrom(message.toByteString().asReadOnlyByteBuffer()); - - assertEquals(message, copy); - } - - public void testParseFromByteBufferThrows() { - try { - TestAllTypesLite.parseFrom(ByteBuffer.wrap(new byte[] { 0x5 })); - fail(); - } catch (InvalidProtocolBufferException expected) { - } - - TestAllTypesLite message = - TestAllTypesLite.newBuilder() - .setOptionalInt32(123) - .addRepeatedString("hello") - .build(); - - ByteBuffer buffer = ByteBuffer.wrap(message.toByteArray(), 0, message.getSerializedSize() - 1); - try { - TestAllTypesLite.parseFrom(buffer); - fail(); - } catch (InvalidProtocolBufferException expected) { - assertEquals( - TestAllTypesLite.newBuilder() - .setOptionalInt32(123) - .build(), - expected.getUnfinishedMessage()); - } - } - - public void testParseFromByteBuffer_extensions() throws Exception { - TestAllExtensionsLite message = - TestAllExtensionsLite.newBuilder() - .setExtension(UnittestLite.optionalInt32ExtensionLite, 123) - .addExtension(UnittestLite.repeatedStringExtensionLite, "hello") - .setExtension( - UnittestLite.optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ) - .setExtension( - UnittestLite.optionalNestedMessageExtensionLite, - TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build()) - .build(); - - ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); - UnittestLite.registerAllExtensions(registry); - - TestAllExtensionsLite copy = - TestAllExtensionsLite.parseFrom(message.toByteString().asReadOnlyByteBuffer(), registry); - - assertEquals(message, copy); - } - - public void testParseFromByteBufferThrows_extensions() { - ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); - UnittestLite.registerAllExtensions(registry); - try { - TestAllExtensionsLite.parseFrom(ByteBuffer.wrap(new byte[] { 0x5 }), registry); - fail(); - } catch (InvalidProtocolBufferException expected) { - } - - TestAllExtensionsLite message = - TestAllExtensionsLite.newBuilder() - .setExtension(UnittestLite.optionalInt32ExtensionLite, 123) - .addExtension(UnittestLite.repeatedStringExtensionLite, "hello") - .build(); - - ByteBuffer buffer = ByteBuffer.wrap(message.toByteArray(), 0, message.getSerializedSize() - 1); - try { - TestAllExtensionsLite.parseFrom(buffer, registry); - fail(); - } catch (InvalidProtocolBufferException expected) { - assertEquals( - TestAllExtensionsLite.newBuilder() - .setExtension(UnittestLite.optionalInt32ExtensionLite, 123) - .build(), - expected.getUnfinishedMessage()); - } - } - - // Make sure we haven't screwed up the code generation for packing fields by default. - public void testPackedSerialization() throws Exception { - TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - builder.addRepeatedInt32(4321); - builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ); - TestAllTypes message = builder.build(); - - CodedInputStream in = CodedInputStream.newInstance(message.toByteArray()); - - while (!in.isAtEnd()) { - int tag = in.readTag(); - assertEquals(WireFormat.WIRETYPE_LENGTH_DELIMITED, WireFormat.getTagWireType(tag)); - in.skipField(tag); - } - } - - public void testAddAllIteratesOnce() { - TestAllTypesLite message = - TestAllTypesLite.newBuilder() - .addAllRepeatedBool(new OneTimeIterableList(false)) - .addAllRepeatedInt32(new OneTimeIterableList(0)) - .addAllRepeatedInt64(new OneTimeIterableList(0L)) - .addAllRepeatedFloat(new OneTimeIterableList(0f)) - .addAllRepeatedDouble(new OneTimeIterableList(0d)) - .addAllRepeatedBytes(new OneTimeIterableList(ByteString.EMPTY)) - .addAllRepeatedString(new OneTimeIterableList("")) - .addAllRepeatedNestedMessage( - new OneTimeIterableList(NestedMessage.getDefaultInstance())) - .addAllRepeatedBool(new OneTimeIterable(false)) - .addAllRepeatedInt32(new OneTimeIterable(0)) - .addAllRepeatedInt64(new OneTimeIterable(0L)) - .addAllRepeatedFloat(new OneTimeIterable(0f)) - .addAllRepeatedDouble(new OneTimeIterable(0d)) - .addAllRepeatedBytes(new OneTimeIterable(ByteString.EMPTY)) - .addAllRepeatedString(new OneTimeIterable("")) - .addAllRepeatedNestedMessage(new OneTimeIterable(NestedMessage.getDefaultInstance())) - .build(); - } - - public void testAddAllIteratesOnce_throwsOnNull() { - TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder(); - try { - builder.addAllRepeatedBool(new OneTimeIterableList(true, false, (Boolean) null)); - fail(); - } catch (NullPointerException expected) { - assertEquals("Element at index 2 is null.", expected.getMessage()); - assertEquals(0, builder.getRepeatedBoolCount()); - } - - try { - builder.addAllRepeatedBool(new OneTimeIterable(true, false, (Boolean) null)); - fail(); - } catch (NullPointerException expected) { - assertEquals("Element at index 2 is null.", expected.getMessage()); - assertEquals(0, builder.getRepeatedBoolCount()); - } - - try { - builder = TestAllTypesLite.newBuilder(); - builder.addAllRepeatedBool(new OneTimeIterableList((Boolean) null)); - fail(); - } catch (NullPointerException expected) { - assertEquals("Element at index 0 is null.", expected.getMessage()); - assertEquals(0, builder.getRepeatedBoolCount()); - } - - try { - builder = TestAllTypesLite.newBuilder(); - builder.addAllRepeatedInt32(new OneTimeIterableList((Integer) null)); - fail(); - } catch (NullPointerException expected) { - assertEquals("Element at index 0 is null.", expected.getMessage()); - assertEquals(0, builder.getRepeatedInt32Count()); - } - - try { - builder = TestAllTypesLite.newBuilder(); - builder.addAllRepeatedInt64(new OneTimeIterableList((Long) null)); - fail(); - } catch (NullPointerException expected) { - assertEquals("Element at index 0 is null.", expected.getMessage()); - assertEquals(0, builder.getRepeatedInt64Count()); - } - - try { - builder = TestAllTypesLite.newBuilder(); - builder.addAllRepeatedFloat(new OneTimeIterableList((Float) null)); - fail(); - } catch (NullPointerException expected) { - assertEquals("Element at index 0 is null.", expected.getMessage()); - assertEquals(0, builder.getRepeatedFloatCount()); - } - - try { - builder = TestAllTypesLite.newBuilder(); - builder.addAllRepeatedDouble(new OneTimeIterableList((Double) null)); - fail(); - } catch (NullPointerException expected) { - assertEquals("Element at index 0 is null.", expected.getMessage()); - assertEquals(0, builder.getRepeatedDoubleCount()); - } - - try { - builder = TestAllTypesLite.newBuilder(); - builder.addAllRepeatedBytes(new OneTimeIterableList((ByteString) null)); - fail(); - } catch (NullPointerException expected) { - assertEquals("Element at index 0 is null.", expected.getMessage()); - assertEquals(0, builder.getRepeatedBytesCount()); - } - - try { - builder = TestAllTypesLite.newBuilder(); - builder.addAllRepeatedString(new OneTimeIterableList("", "", (String) null, "")); - fail(); - } catch (NullPointerException expected) { - assertEquals("Element at index 2 is null.", expected.getMessage()); - assertEquals(0, builder.getRepeatedStringCount()); - } - - try { - builder = TestAllTypesLite.newBuilder(); - builder.addAllRepeatedString(new OneTimeIterable("", "", (String) null, "")); - fail(); - } catch (NullPointerException expected) { - assertEquals("Element at index 2 is null.", expected.getMessage()); - assertEquals(0, builder.getRepeatedStringCount()); - } - - try { - builder = TestAllTypesLite.newBuilder(); - builder.addAllRepeatedString(new OneTimeIterableList((String) null)); - fail(); - } catch (NullPointerException expected) { - assertEquals("Element at index 0 is null.", expected.getMessage()); - assertEquals(0, builder.getRepeatedStringCount()); - } - - try { - builder = TestAllTypesLite.newBuilder(); - builder.addAllRepeatedNestedMessage(new OneTimeIterableList((NestedMessage) null)); - fail(); - } catch (NullPointerException expected) { - assertEquals("Element at index 0 is null.", expected.getMessage()); - assertEquals(0, builder.getRepeatedNestedMessageCount()); - } - } - - private static final class OneTimeIterableList extends ArrayList { - private boolean wasIterated = false; - - OneTimeIterableList(T... contents) { - addAll(Arrays.asList(contents)); - } - - @Override - public Iterator iterator() { - if (wasIterated) { - fail(); - } - wasIterated = true; - return super.iterator(); - } - } - - private static final class OneTimeIterable implements Iterable { - private final List list; - private boolean wasIterated = false; - - OneTimeIterable(T... contents) { - list = Arrays.asList(contents); - } - - @Override - public Iterator iterator() { - if (wasIterated) { - fail(); - } - wasIterated = true; - return list.iterator(); - } - } -} diff --git a/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java index eac47448e0506..4177a47e67f28 100644 --- a/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java +++ b/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java @@ -30,6 +30,8 @@ package com.google.protobuf; +import static com.google.common.truth.Truth.assertThat; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.EOFException; @@ -46,9 +48,9 @@ import junit.framework.TestCase; /** - * Test {@code LiteralByteString} by setting up a reference string in {@link #setUp()}. - * This class is designed to be extended for testing extensions of {@code LiteralByteString} - * such as {@code BoundedByteString}, see {@link BoundedByteStringTest}. + * Test {@code LiteralByteString} by setting up a reference string in {@link #setUp()}. This class + * is designed to be extended for testing extensions of {@code LiteralByteString} such as {@code + * BoundedByteString}, see {@link BoundedByteStringTest}. * * @author carlanton@google.com (Carl Haverl) */ @@ -92,7 +94,7 @@ public void testByteIterator() { stillEqual = (iter.hasNext() && referenceBytes[i] == iter.nextByte()); } assertTrue(classUnderTest + " must capture the right bytes", stillEqual); - assertFalse(classUnderTest + " must have exhausted the itertor", iter.hasNext()); + assertFalse(classUnderTest + " must have exhausted the iterator", iter.hasNext()); try { iter.nextByte(); @@ -114,7 +116,9 @@ public void testByteIterable() { } public void testSize() { - assertEquals(classUnderTest + " must have the expected size", referenceBytes.length, + assertEquals( + classUnderTest + " must have the expected size", + referenceBytes.length, stringUnderTest.size()); } @@ -146,10 +150,9 @@ public void testCopyTo_ByteArrayOffsetLengthErrors() { try { // Copy one too many bytes - stringUnderTest.copyTo(destination, stringUnderTest.size() + 1 - length, - destinationOffset, length); - fail("Should have thrown an exception when copying too many bytes of a " - + classUnderTest); + stringUnderTest.copyTo( + destination, stringUnderTest.size() + 1 - length, destinationOffset, length); + fail("Should have thrown an exception when copying too many bytes of a " + classUnderTest); } catch (IndexOutOfBoundsException expected) { // This is success } @@ -157,8 +160,9 @@ public void testCopyTo_ByteArrayOffsetLengthErrors() { try { // Copy with illegal negative sourceOffset stringUnderTest.copyTo(destination, -1, destinationOffset, length); - fail("Should have thrown an exception when given a negative sourceOffset in " - + classUnderTest); + fail( + "Should have thrown an exception when given a negative sourceOffset in " + + classUnderTest); } catch (IndexOutOfBoundsException expected) { // This is success } @@ -166,8 +170,9 @@ public void testCopyTo_ByteArrayOffsetLengthErrors() { try { // Copy with illegal negative destinationOffset stringUnderTest.copyTo(destination, 0, -1, length); - fail("Should have thrown an exception when given a negative destinationOffset in " - + classUnderTest); + fail( + "Should have thrown an exception when given a negative destinationOffset in " + + classUnderTest); } catch (IndexOutOfBoundsException expected) { // This is success } @@ -175,8 +180,7 @@ public void testCopyTo_ByteArrayOffsetLengthErrors() { try { // Copy with illegal negative size stringUnderTest.copyTo(destination, 0, 0, -1); - fail("Should have thrown an exception when given a negative size in " - + classUnderTest); + fail("Should have thrown an exception when given a negative size in " + classUnderTest); } catch (IndexOutOfBoundsException expected) { // This is success } @@ -184,8 +188,9 @@ public void testCopyTo_ByteArrayOffsetLengthErrors() { try { // Copy with illegal too-large sourceOffset stringUnderTest.copyTo(destination, 2 * stringUnderTest.size(), 0, length); - fail("Should have thrown an exception when the destinationOffset is too large in " - + classUnderTest); + fail( + "Should have thrown an exception when the destinationOffset is too large in " + + classUnderTest); } catch (IndexOutOfBoundsException expected) { // This is success } @@ -193,8 +198,9 @@ public void testCopyTo_ByteArrayOffsetLengthErrors() { try { // Copy with illegal too-large destinationOffset stringUnderTest.copyTo(destination, 0, 2 * destination.length, length); - fail("Should have thrown an exception when the destinationOffset is too large in " - + classUnderTest); + fail( + "Should have thrown an exception when the destinationOffset is too large in " + + classUnderTest); } catch (IndexOutOfBoundsException expected) { // This is success } @@ -203,7 +209,8 @@ public void testCopyTo_ByteArrayOffsetLengthErrors() { public void testCopyTo_ByteBuffer() { ByteBuffer myBuffer = ByteBuffer.allocate(referenceBytes.length); stringUnderTest.copyTo(myBuffer); - assertTrue(classUnderTest + ".copyTo(ByteBuffer) must give back the same bytes", + assertTrue( + classUnderTest + ".copyTo(ByteBuffer) must give back the same bytes", Arrays.equals(referenceBytes, myBuffer.array())); } @@ -233,17 +240,15 @@ public void testMarkAndReset() throws IOException { } /** - * Discards {@code n} bytes of data from the input stream. This method - * will block until the full amount has been skipped. Does not close the - * stream. + * Discards {@code n} bytes of data from the input stream. This method will block until the full + * amount has been skipped. Does not close the stream. + * *

Copied from com.google.common.io.ByteStreams to avoid adding dependency. * * @param in the input stream to read from * @param n the number of bytes to skip - * @throws EOFException if this stream reaches the end before skipping all - * the bytes - * @throws IOException if an I/O error occurs, or the stream does not - * support skipping + * @throws EOFException if this stream reaches the end before skipping all the bytes + * @throws IOException if an I/O error occurs, or the stream does not support skipping */ static void skipFully(InputStream in, long n) throws IOException { long toSkip = n; @@ -253,8 +258,12 @@ static void skipFully(InputStream in, long n) throws IOException { // Force a blocking read to avoid infinite loop if (in.read() == -1) { long skipped = toSkip - n; - throw new EOFException("reached end of stream after skipping " - + skipped + " bytes; " + toSkip + " bytes expected"); + throw new EOFException( + "reached end of stream after skipping " + + skipped + + " bytes; " + + toSkip + + " bytes expected"); } n--; } else { @@ -269,7 +278,8 @@ public void testAsReadOnlyByteBuffer() { assertTrue(byteBuffer.remaining() == referenceBytes.length); assertTrue(byteBuffer.isReadOnly()); byteBuffer.get(roundTripBytes); - assertTrue(classUnderTest + ".asReadOnlyByteBuffer() must give back the same bytes", + assertTrue( + classUnderTest + ".asReadOnlyByteBuffer() must give back the same bytes", Arrays.equals(referenceBytes, roundTripBytes)); } @@ -285,13 +295,15 @@ public void testAsReadOnlyByteBufferList() { bytesSeen += thisLength; } assertTrue(bytesSeen == referenceBytes.length); - assertTrue(classUnderTest + ".asReadOnlyByteBufferTest() must give back the same bytes", + assertTrue( + classUnderTest + ".asReadOnlyByteBufferTest() must give back the same bytes", Arrays.equals(referenceBytes, roundTripBytes)); } public void testToByteArray() { byte[] roundTripBytes = stringUnderTest.toByteArray(); - assertTrue(classUnderTest + ".toByteArray() must give back the same bytes", + assertTrue( + classUnderTest + ".toByteArray() must give back the same bytes", Arrays.equals(referenceBytes, roundTripBytes)); } @@ -299,78 +311,85 @@ public void testWriteTo() throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); stringUnderTest.writeTo(bos); byte[] roundTripBytes = bos.toByteArray(); - assertTrue(classUnderTest + ".writeTo() must give back the same bytes", + assertTrue( + classUnderTest + ".writeTo() must give back the same bytes", Arrays.equals(referenceBytes, roundTripBytes)); } public void testWriteToShouldNotExposeInternalBufferToOutputStream() throws IOException { - OutputStream os = new OutputStream() { - @Override - public void write(byte[] b, int off, int len) { - Arrays.fill(b, off, off + len, (byte) 0); - } - - @Override - public void write(int b) { - throw new UnsupportedOperationException(); - } - }; + OutputStream os = + new OutputStream() { + @Override + public void write(byte[] b, int off, int len) { + Arrays.fill(b, off, off + len, (byte) 0); + } + + @Override + public void write(int b) { + throw new UnsupportedOperationException(); + } + }; stringUnderTest.writeTo(os); - assertTrue(classUnderTest + ".writeTo() must not grant access to underlying array", + assertTrue( + classUnderTest + ".writeTo() must not grant access to underlying array", Arrays.equals(referenceBytes, stringUnderTest.toByteArray())); } public void testWriteToInternalShouldExposeInternalBufferToOutputStream() throws IOException { - OutputStream os = new OutputStream() { - @Override - public void write(byte[] b, int off, int len) { - Arrays.fill(b, off, off + len, (byte) 0); - } - - @Override - public void write(int b) { - throw new UnsupportedOperationException(); - } - }; + OutputStream os = + new OutputStream() { + @Override + public void write(byte[] b, int off, int len) { + Arrays.fill(b, off, off + len, (byte) 0); + } + + @Override + public void write(int b) { + throw new UnsupportedOperationException(); + } + }; stringUnderTest.writeToInternal(os, 0, stringUnderTest.size()); byte[] allZeros = new byte[stringUnderTest.size()]; - assertTrue(classUnderTest + ".writeToInternal() must grant access to underlying array", + assertTrue( + classUnderTest + ".writeToInternal() must grant access to underlying array", Arrays.equals(allZeros, stringUnderTest.toByteArray())); } public void testWriteToShouldExposeInternalBufferToByteOutput() throws IOException { - ByteOutput out = new ByteOutput() { - @Override - public void write(byte value) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public void write(byte[] value, int offset, int length) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public void writeLazy(byte[] value, int offset, int length) throws IOException { - Arrays.fill(value, offset, offset + length, (byte) 0); - } - - @Override - public void write(ByteBuffer value) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public void writeLazy(ByteBuffer value) throws IOException { - throw new UnsupportedOperationException(); - } - }; + ByteOutput out = + new ByteOutput() { + @Override + public void write(byte value) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void write(byte[] value, int offset, int length) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void write(ByteBuffer value) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void writeLazy(byte[] value, int offset, int length) throws IOException { + Arrays.fill(value, offset, offset + length, (byte) 0); + } + + @Override + public void writeLazy(ByteBuffer value) throws IOException { + throw new UnsupportedOperationException(); + } + }; stringUnderTest.writeTo(out); byte[] allZeros = new byte[stringUnderTest.size()]; - assertTrue(classUnderTest + ".writeToInternal() must grant access to underlying array", + assertTrue( + classUnderTest + ".writeToInternal() must grant access to underlying array", Arrays.equals(allZeros, stringUnderTest.toByteArray())); } @@ -378,21 +397,22 @@ public void testNewOutput() throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteString.Output output = ByteString.newOutput(); stringUnderTest.writeTo(output); - assertEquals("Output Size returns correct result", - output.size(), stringUnderTest.size()); + assertEquals("Output Size returns correct result", output.size(), stringUnderTest.size()); output.writeTo(bos); - assertTrue("Output.writeTo() must give back the same bytes", + assertTrue( + "Output.writeTo() must give back the same bytes", Arrays.equals(referenceBytes, bos.toByteArray())); // write the output stream to itself! This should cause it to double output.writeTo(output); - assertEquals("Writing an output stream to itself is successful", - stringUnderTest.concat(stringUnderTest), output.toByteString()); + assertEquals( + "Writing an output stream to itself is successful", + stringUnderTest.concat(stringUnderTest), + output.toByteString()); output.reset(); assertEquals("Output.reset() resets the output", 0, output.size()); - assertEquals("Output.reset() resets the output", - ByteString.EMPTY, output.toByteString()); + assertEquals("Output.reset() resets the output", ByteString.EMPTY, output.toByteString()); } public void testToString() throws UnsupportedEncodingException { @@ -410,9 +430,10 @@ public void testCharsetToString() { } public void testToString_returnsCanonicalEmptyString() { - assertSame(classUnderTest + " must be the same string references", + assertSame( + classUnderTest + " must be the same string references", ByteString.EMPTY.toString(Internal.UTF_8), - ByteString.wrap(new byte[]{}).toString(Internal.UTF_8)); + ByteString.wrap(new byte[] {}).toString(Internal.UTF_8)); } public void testToString_raisesException() { @@ -434,17 +455,23 @@ public void testToString_raisesException() { public void testEquals() { assertEquals(classUnderTest + " must not equal null", false, stringUnderTest.equals(null)); assertEquals(classUnderTest + " must equal self", stringUnderTest, stringUnderTest); - assertFalse(classUnderTest + " must not equal the empty string", + assertFalse( + classUnderTest + " must not equal the empty string", stringUnderTest.equals(ByteString.EMPTY)); - assertEquals(classUnderTest + " empty strings must be equal", - ByteString.wrap(new byte[]{}), stringUnderTest.substring(55, 55)); - assertEquals(classUnderTest + " must equal another string with the same value", - stringUnderTest, ByteString.wrap(referenceBytes)); + assertEquals( + classUnderTest + " empty strings must be equal", + ByteString.wrap(new byte[] {}), + stringUnderTest.substring(55, 55)); + assertEquals( + classUnderTest + " must equal another string with the same value", + stringUnderTest, + ByteString.wrap(referenceBytes)); byte[] mungedBytes = new byte[referenceBytes.length]; System.arraycopy(referenceBytes, 0, mungedBytes, 0, referenceBytes.length); mungedBytes[mungedBytes.length - 5] = (byte) (mungedBytes[mungedBytes.length - 5] ^ 0xFF); - assertFalse(classUnderTest + " must not equal every string with the same length", + assertFalse( + classUnderTest + " must not equal every string with the same length", stringUnderTest.equals(ByteString.wrap(mungedBytes))); } @@ -454,79 +481,102 @@ public void testHashCode() { } public void testPeekCachedHashCode() { - assertEquals(classUnderTest + ".peekCachedHashCode() should return zero at first", 0, + assertEquals( + classUnderTest + ".peekCachedHashCode() should return zero at first", + 0, stringUnderTest.peekCachedHashCode()); stringUnderTest.hashCode(); - assertEquals(classUnderTest + ".peekCachedHashCode should return zero at first", - expectedHashCode, stringUnderTest.peekCachedHashCode()); + assertEquals( + classUnderTest + ".peekCachedHashCode should return zero at first", + expectedHashCode, + stringUnderTest.peekCachedHashCode()); } public void testPartialHash() { // partialHash() is more strenuously tested elsewhere by testing hashes of substrings. // This test would fail if the expected hash were 1. It's not. int hash = stringUnderTest.partialHash(stringUnderTest.size(), 0, stringUnderTest.size()); - assertEquals(classUnderTest + ".partialHash() must yield expected hashCode", - expectedHashCode, hash); + assertEquals( + classUnderTest + ".partialHash() must yield expected hashCode", expectedHashCode, hash); } public void testNewInput() throws IOException { InputStream input = stringUnderTest.newInput(); - assertEquals("InputStream.available() returns correct value", - stringUnderTest.size(), input.available()); + assertEquals( + "InputStream.available() returns correct value", stringUnderTest.size(), input.available()); boolean stillEqual = true; for (byte referenceByte : referenceBytes) { int expectedInt = (referenceByte & 0xFF); stillEqual = (expectedInt == input.read()); } - assertEquals("InputStream.available() returns correct value", - 0, input.available()); + assertEquals("InputStream.available() returns correct value", 0, input.available()); assertTrue(classUnderTest + " must give the same bytes from the InputStream", stillEqual); assertEquals(classUnderTest + " InputStream must now be exhausted", -1, input.read()); } + public void testNewInput_readZeroBytes() throws IOException { + InputStream input = stringUnderTest.newInput(); + assertEquals( + classUnderTest + " InputStream.read() returns 0 when told to read 0 bytes and not at EOF", + 0, + input.read(new byte[0])); + + input.skip(input.available()); + assertEquals( + classUnderTest + " InputStream.read() returns -1 when told to read 0 bytes at EOF", + -1, + input.read(new byte[0])); + } + public void testNewInput_skip() throws IOException { InputStream input = stringUnderTest.newInput(); int stringSize = stringUnderTest.size(); int nearEndIndex = stringSize * 2 / 3; + long skipped1 = input.skip(nearEndIndex); assertEquals("InputStream.skip()", skipped1, nearEndIndex); - assertEquals("InputStream.available()", - stringSize - skipped1, input.available()); + assertEquals("InputStream.available()", stringSize - skipped1, input.available()); assertTrue("InputStream.mark() is available", input.markSupported()); input.mark(0); - assertEquals("InputStream.skip(), read()", - stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read()); - assertEquals("InputStream.available()", - stringSize - skipped1 - 1, input.available()); + assertEquals( + "InputStream.skip(), read()", stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read()); + assertEquals("InputStream.available()", stringSize - skipped1 - 1, input.available()); + long skipped2 = input.skip(stringSize); - assertEquals("InputStream.skip() incomplete", - skipped2, stringSize - skipped1 - 1); + assertEquals("InputStream.skip() incomplete", skipped2, stringSize - skipped1 - 1); assertEquals("InputStream.skip(), no more input", 0, input.available()); assertEquals("InputStream.skip(), no more input", -1, input.read()); + assertThat(input.skip(1)).isEqualTo(0); + assertThat(input.read(new byte[1], /* off= */ 0, /*len=*/ 0)).isEqualTo(-1); + input.reset(); - assertEquals("InputStream.reset() succeded", - stringSize - skipped1, input.available()); - assertEquals("InputStream.reset(), read()", - stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read()); + assertEquals("InputStream.reset() succeeded", stringSize - skipped1, input.available()); + assertEquals( + "InputStream.reset(), read()", stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read()); } public void testNewCodedInput() throws IOException { CodedInputStream cis = stringUnderTest.newCodedInput(); byte[] roundTripBytes = cis.readRawBytes(referenceBytes.length); - assertTrue(classUnderTest + " must give the same bytes back from the CodedInputStream", + assertTrue( + classUnderTest + " must give the same bytes back from the CodedInputStream", Arrays.equals(referenceBytes, roundTripBytes)); assertTrue(classUnderTest + " CodedInputStream must now be exhausted", cis.isAtEnd()); } /** - * Make sure we keep things simple when concatenating with empty. See also - * {@link ByteStringTest#testConcat_empty()}. + * Make sure we keep things simple when concatenating with empty. See also {@link + * ByteStringTest#testConcat_empty()}. */ public void testConcat_empty() { - assertSame(classUnderTest + " concatenated with empty must give " + classUnderTest, - stringUnderTest.concat(ByteString.EMPTY), stringUnderTest); - assertSame("empty concatenated with " + classUnderTest + " must give " + classUnderTest, - ByteString.EMPTY.concat(stringUnderTest), stringUnderTest); + assertSame( + classUnderTest + " concatenated with empty must give " + classUnderTest, + stringUnderTest.concat(ByteString.EMPTY), + stringUnderTest); + assertSame( + "empty concatenated with " + classUnderTest + " must give " + classUnderTest, + ByteString.EMPTY.concat(stringUnderTest), + stringUnderTest); } public void testJavaSerialization() throws Exception { diff --git a/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java b/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java index 6bbdfcaa32abf..d6fbaf9d9506c 100644 --- a/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java @@ -32,6 +32,7 @@ import static java.util.Arrays.asList; +import com.google.protobuf.Internal.LongList; import java.util.Collections; import java.util.ConcurrentModificationException; import java.util.Iterator; @@ -44,10 +45,8 @@ */ public class LongArrayListTest extends TestCase { - private static final LongArrayList UNARY_LIST = - newImmutableLongArrayList(1); - private static final LongArrayList TERTIARY_LIST = - newImmutableLongArrayList(1, 2, 3); + private static final LongArrayList UNARY_LIST = newImmutableLongArrayList(1); + private static final LongArrayList TERTIARY_LIST = newImmutableLongArrayList(1, 2, 3); private LongArrayList list; @@ -140,6 +139,68 @@ public void testGetLong() { } } + public void testIndexOf_nullElement() { + assertEquals(-1, TERTIARY_LIST.indexOf(null)); + } + + public void testIndexOf_incompatibleElementType() { + assertEquals(-1, TERTIARY_LIST.indexOf(new Object())); + } + + public void testIndexOf_notInList() { + assertEquals(-1, UNARY_LIST.indexOf(2L)); + } + + public void testIndexOf_notInListWithDuplicates() { + LongArrayList listWithDupes = newImmutableLongArrayList(1L, 1L); + assertEquals(-1, listWithDupes.indexOf(2L)); + } + + public void testIndexOf_inList() { + assertEquals(1, TERTIARY_LIST.indexOf(2L)); + } + + public void testIndexOf_inListWithDuplicates_matchAtHead() { + LongArrayList listWithDupes = newImmutableLongArrayList(1L, 1L, 2L); + assertEquals(0, listWithDupes.indexOf(1L)); + } + + public void testIndexOf_inListWithDuplicates_matchMidList() { + LongArrayList listWithDupes = newImmutableLongArrayList(2L, 1L, 1L, 2L); + assertEquals(1, listWithDupes.indexOf(1L)); + } + + public void testContains_nullElement() { + assertEquals(false, TERTIARY_LIST.contains(null)); + } + + public void testContains_incompatibleElementType() { + assertEquals(false, TERTIARY_LIST.contains(new Object())); + } + + public void testContains_notInList() { + assertEquals(false, UNARY_LIST.contains(2L)); + } + + public void testContains_notInListWithDuplicates() { + LongArrayList listWithDupes = newImmutableLongArrayList(1L, 1L); + assertEquals(false, listWithDupes.contains(2L)); + } + + public void testContains_inList() { + assertEquals(true, TERTIARY_LIST.contains(2L)); + } + + public void testContains_inListWithDuplicates_matchAtHead() { + LongArrayList listWithDupes = newImmutableLongArrayList(1L, 1L, 2L); + assertEquals(true, listWithDupes.contains(1L)); + } + + public void testContains_inListWithDuplicates_matchMidList() { + LongArrayList listWithDupes = newImmutableLongArrayList(2L, 1L, 1L, 2L); + assertEquals(true, listWithDupes.contains(1L)); + } + public void testSize() { assertEquals(0, LongArrayList.emptyList().size()); assertEquals(1, UNARY_LIST.size()); @@ -224,9 +285,7 @@ public void testAdd() { for (int i = 0; i < 6; i++) { list.add(Long.valueOf(5 + i)); } - assertEquals( - asList(0L, 1L, 4L, 2L, 3L, 5L, 6L, 7L, 8L, 9L, 10L), - list); + assertEquals(asList(0L, 1L, 4L, 2L, 3L, 5L, 6L, 7L, 8L, 9L, 10L), list); try { list.add(-1, 5L); @@ -269,6 +328,13 @@ public void testAddAll() { assertFalse(list.addAll(LongArrayList.emptyList())); } + public void testEquals() { + LongArrayList list1 = new LongArrayList(); + LongArrayList list2 = new LongArrayList(); + + assertEquals(list1, list2); + } + public void testRemove() { list.addAll(TERTIARY_LIST); assertEquals(1L, (long) list.remove(0)); @@ -297,7 +363,30 @@ public void testRemove() { } } - private void assertImmutable(LongArrayList list) { + public void testRemoveEnd_listAtCapacity() { + LongList toRemove = LongArrayList.emptyList().mutableCopyWithCapacity(1); + toRemove.addLong(3); + toRemove.remove(0); + assertEquals(0, toRemove.size()); + } + + public void testRemove_listAtCapacity() { + LongList toRemove = LongArrayList.emptyList().mutableCopyWithCapacity(2); + toRemove.addLong(3); + toRemove.addLong(4); + toRemove.remove(0); + assertEquals(1, toRemove.size()); + assertEquals(4L, (long) toRemove.get(0)); + } + + public void testSublistRemoveEndOfCapacity() { + LongList toRemove = LongArrayList.emptyList().mutableCopyWithCapacity(1); + toRemove.addLong(3); + toRemove.subList(0, 1).clear(); + assertEquals(0, toRemove.size()); + } + + private void assertImmutable(LongList list) { if (list.contains(1L)) { throw new RuntimeException("Cannot test the immutability of lists that contain 1."); } diff --git a/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java b/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java index da9195f933d3b..4de09cd1619ab 100644 --- a/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java +++ b/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java @@ -43,9 +43,7 @@ import java.util.Map; import junit.framework.TestCase; -/** - * Unit tests for map fields. - */ +/** Unit tests for map fields. */ public final class MapForProto2LiteTest extends TestCase { private void setMapValues(TestMap.Builder builder) { @@ -53,23 +51,18 @@ private void setMapValues(TestMap.Builder builder) { .putInt32ToInt32Field(1, 11) .putInt32ToInt32Field(2, 22) .putInt32ToInt32Field(3, 33) - .putInt32ToStringField(1, "11") .putInt32ToStringField(2, "22") .putInt32ToStringField(3, "33") - .putInt32ToBytesField(1, TestUtil.toBytes("11")) .putInt32ToBytesField(2, TestUtil.toBytes("22")) .putInt32ToBytesField(3, TestUtil.toBytes("33")) - .putInt32ToEnumField(1, TestMap.EnumValue.FOO) .putInt32ToEnumField(2, TestMap.EnumValue.BAR) .putInt32ToEnumField(3, TestMap.EnumValue.BAZ) - .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(11).build()) .putInt32ToMessageField(2, MessageValue.newBuilder().setValue(22).build()) .putInt32ToMessageField(3, MessageValue.newBuilder().setValue(33).build()) - .putStringToInt32Field("1", 11) .putStringToInt32Field("2", 22) .putStringToInt32Field("3", 33); @@ -84,44 +77,44 @@ public void testSetMapValues() { private void copyMapValues(TestMap source, TestMap.Builder destination) { destination - .putAllInt32ToInt32Field(source.getInt32ToInt32Field()) - .putAllInt32ToStringField(source.getInt32ToStringField()) - .putAllInt32ToBytesField(source.getInt32ToBytesField()) - .putAllInt32ToEnumField(source.getInt32ToEnumField()) - .putAllInt32ToMessageField(source.getInt32ToMessageField()) - .putAllStringToInt32Field(source.getStringToInt32Field()); + .putAllInt32ToInt32Field(source.getInt32ToInt32FieldMap()) + .putAllInt32ToStringField(source.getInt32ToStringFieldMap()) + .putAllInt32ToBytesField(source.getInt32ToBytesFieldMap()) + .putAllInt32ToEnumField(source.getInt32ToEnumFieldMap()) + .putAllInt32ToMessageField(source.getInt32ToMessageFieldMap()) + .putAllStringToInt32Field(source.getStringToInt32FieldMap()); } private void assertMapValuesSet(TestMap message) { - assertEquals(3, message.getInt32ToInt32Field().size()); - assertEquals(11, message.getInt32ToInt32Field().get(1).intValue()); - assertEquals(22, message.getInt32ToInt32Field().get(2).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(3).intValue()); + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(11, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(22, message.getInt32ToInt32FieldMap().get(2).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); - assertEquals(3, message.getInt32ToStringField().size()); - assertEquals("11", message.getInt32ToStringField().get(1)); - assertEquals("22", message.getInt32ToStringField().get(2)); - assertEquals("33", message.getInt32ToStringField().get(3)); + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("11", message.getInt32ToStringFieldMap().get(1)); + assertEquals("22", message.getInt32ToStringFieldMap().get(2)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); - assertEquals(3, message.getInt32ToBytesField().size()); - assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1)); - assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2)); - assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesFieldMap().get(2)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); - assertEquals(3, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2)); - assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(2)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); - assertEquals(3, message.getInt32ToMessageField().size()); - assertEquals(11, message.getInt32ToMessageField().get(1).getValue()); - assertEquals(22, message.getInt32ToMessageField().get(2).getValue()); - assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(11, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(22, message.getInt32ToMessageFieldMap().get(2).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); - assertEquals(3, message.getStringToInt32Field().size()); - assertEquals(11, message.getStringToInt32Field().get("1").intValue()); - assertEquals(22, message.getStringToInt32Field().get("2").intValue()); - assertEquals(33, message.getStringToInt32Field().get("3").intValue()); + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(11, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(22, message.getStringToInt32FieldMap().get("2").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); } private void updateMapValues(TestMap.Builder builder) { @@ -129,23 +122,18 @@ private void updateMapValues(TestMap.Builder builder) { .putInt32ToInt32Field(1, 111) .removeInt32ToInt32Field(2) .putInt32ToInt32Field(4, 44) - .putInt32ToStringField(1, "111") .removeInt32ToStringField(2) .putInt32ToStringField(4, "44") - .putInt32ToBytesField(1, TestUtil.toBytes("111")) .removeInt32ToBytesField(2) .putInt32ToBytesField(4, TestUtil.toBytes("44")) - .putInt32ToEnumField(1, TestMap.EnumValue.BAR) .removeInt32ToEnumField(2) .putInt32ToEnumField(4, TestMap.EnumValue.QUX) - .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(111).build()) .removeInt32ToMessageField(2) .putInt32ToMessageField(4, MessageValue.newBuilder().setValue(44).build()) - .putStringToInt32Field("1", 111) .removeStringToInt32Field("2") .putStringToInt32Field("4", 44); @@ -164,49 +152,49 @@ public void testUpdateMapValues() { } private void assertMapValuesUpdated(TestMap message) { - assertEquals(3, message.getInt32ToInt32Field().size()); - assertEquals(111, message.getInt32ToInt32Field().get(1).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(3).intValue()); - assertEquals(44, message.getInt32ToInt32Field().get(4).intValue()); + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(111, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); + assertEquals(44, message.getInt32ToInt32FieldMap().get(4).intValue()); - assertEquals(3, message.getInt32ToStringField().size()); - assertEquals("111", message.getInt32ToStringField().get(1)); - assertEquals("33", message.getInt32ToStringField().get(3)); - assertEquals("44", message.getInt32ToStringField().get(4)); + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("111", message.getInt32ToStringFieldMap().get(1)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); + assertEquals("44", message.getInt32ToStringFieldMap().get(4)); - assertEquals(3, message.getInt32ToBytesField().size()); - assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1)); - assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); - assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4)); + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); + assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesFieldMap().get(4)); - assertEquals(3, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); - assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4)); + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); + assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumFieldMap().get(4)); - assertEquals(3, message.getInt32ToMessageField().size()); - assertEquals(111, message.getInt32ToMessageField().get(1).getValue()); - assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); - assertEquals(44, message.getInt32ToMessageField().get(4).getValue()); + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(111, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); + assertEquals(44, message.getInt32ToMessageFieldMap().get(4).getValue()); - assertEquals(3, message.getStringToInt32Field().size()); - assertEquals(111, message.getStringToInt32Field().get("1").intValue()); - assertEquals(33, message.getStringToInt32Field().get("3").intValue()); - assertEquals(44, message.getStringToInt32Field().get("4").intValue()); + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(111, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); + assertEquals(44, message.getStringToInt32FieldMap().get("4").intValue()); } private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) { - assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size()); + assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount()); - assertEquals(0, testMapOrBuilder.getInt32ToStringField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToStringFieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount()); - assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount()); - assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount()); - assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount()); - assertEquals(0, testMapOrBuilder.getStringToInt32Field().size()); + assertEquals(0, testMapOrBuilder.getStringToInt32FieldMap().size()); assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount()); } @@ -218,13 +206,13 @@ public void testSanityCopyOnWrite() throws InvalidProtocolBufferException { TestMap.Builder builder = TestMap.newBuilder(); TestMap message = builder.build(); builder.putInt32ToInt32Field(1, 2); - assertTrue(message.getInt32ToInt32Field().isEmpty()); + assertTrue(message.getInt32ToInt32FieldMap().isEmpty()); message = builder.build(); - assertEquals(newMap(1, 2), message.getInt32ToInt32Field()); - assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); + assertEquals(newMap(1, 2), message.getInt32ToInt32FieldMap()); + assertEquals(newMap(1, 2), builder.getInt32ToInt32FieldMap()); builder.putInt32ToInt32Field(2, 3); - assertEquals(newMap(1, 2), message.getInt32ToInt32Field()); - assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field()); + assertEquals(newMap(1, 2), message.getInt32ToInt32FieldMap()); + assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32FieldMap()); } public void testGetMapIsImmutable() { @@ -238,13 +226,13 @@ public void testGetMapIsImmutable() { } private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) { - assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2); - assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2"); - assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2")); - assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO); + assertImmutable(testMapOrBuilder.getInt32ToInt32FieldMap(), 1, 2); + assertImmutable(testMapOrBuilder.getInt32ToStringFieldMap(), 1, "2"); + assertImmutable(testMapOrBuilder.getInt32ToBytesFieldMap(), 1, TestUtil.toBytes("2")); + assertImmutable(testMapOrBuilder.getInt32ToEnumFieldMap(), 1, TestMap.EnumValue.FOO); assertImmutable( - testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance()); - assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2); + testMapOrBuilder.getInt32ToMessageFieldMap(), 1, MessageValue.getDefaultInstance()); + assertImmutable(testMapOrBuilder.getStringToInt32FieldMap(), "1", 2); } private void assertImmutable(Map map, K key, V value) { @@ -265,37 +253,40 @@ private void assertImmutable(Map map, K key, V value) { } public void testMutableMapLifecycle() { - TestMap.Builder builder = TestMap.newBuilder() - .putInt32ToInt32Field(1, 2); - assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); - assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); + TestMap.Builder builder = TestMap.newBuilder().putInt32ToInt32Field(1, 2); + assertEquals(newMap(1, 2), builder.build().getInt32ToInt32FieldMap()); + assertEquals(newMap(1, 2), builder.getInt32ToInt32FieldMap()); builder.putInt32ToInt32Field(2, 3); - assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field()); + assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32FieldMap()); builder.putInt32ToEnumField(1, TestMap.EnumValue.BAR); - assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField()); - assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField()); + assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumFieldMap()); + assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumFieldMap()); builder.putInt32ToEnumField(2, TestMap.EnumValue.FOO); assertEquals( newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), - builder.getInt32ToEnumField()); + builder.getInt32ToEnumFieldMap()); builder.putInt32ToStringField(1, "1"); - assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField()); - assertEquals(newMap(1, "1"), builder.getInt32ToStringField()); + assertEquals(newMap(1, "1"), builder.build().getInt32ToStringFieldMap()); + assertEquals(newMap(1, "1"), builder.getInt32ToStringFieldMap()); builder.putInt32ToStringField(2, "2"); - assertEquals(newMap(1, "1", 2, "2"), builder.getInt32ToStringField()); + assertEquals(newMap(1, "1", 2, "2"), builder.getInt32ToStringFieldMap()); builder.putInt32ToMessageField(1, TestMap.MessageValue.getDefaultInstance()); - assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()), - builder.build().getInt32ToMessageField()); - assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()), - builder.getInt32ToMessageField()); + assertEquals( + newMap(1, TestMap.MessageValue.getDefaultInstance()), + builder.build().getInt32ToMessageFieldMap()); + assertEquals( + newMap(1, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageFieldMap()); builder.putInt32ToMessageField(2, TestMap.MessageValue.getDefaultInstance()); assertEquals( - newMap(1, TestMap.MessageValue.getDefaultInstance(), - 2, TestMap.MessageValue.getDefaultInstance()), - builder.getInt32ToMessageField()); + newMap( + 1, + TestMap.MessageValue.getDefaultInstance(), + 2, + TestMap.MessageValue.getDefaultInstance()), + builder.getInt32ToMessageFieldMap()); } public void testGettersAndSetters() throws Exception { @@ -405,40 +396,32 @@ public void testParseError() throws Exception { ByteString bytes = TestUtil.toBytes("SOME BYTES"); String stringKey = "a string key"; - TestMap map = tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToInt32Field(5, bytes) - .build()); + TestMap map = + tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToInt32Field(5, bytes).build()); assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1)); - map = tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToStringField(stringKey, 5) - .build()); + map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToStringField(stringKey, 5).build()); assertEquals("", map.getInt32ToStringFieldOrDefault(0, null)); - map = tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToBytesField(stringKey, 5) - .build()); + map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToBytesField(stringKey, 5).build()); assertEquals(map.getInt32ToBytesFieldOrDefault(0, null), ByteString.EMPTY); - map = tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToEnumField(stringKey, bytes) - .build()); + map = + tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToEnumField(stringKey, bytes).build()); assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null)); try { - tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToMessageField(stringKey, bytes) - .build()); + tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToMessageField(stringKey, bytes).build()); fail(); } catch (InvalidProtocolBufferException expected) { assertTrue(expected.getUnfinishedMessage() instanceof TestMap); map = (TestMap) expected.getUnfinishedMessage(); - assertTrue(map.getInt32ToMessageField().isEmpty()); + assertTrue(map.getInt32ToMessageFieldMap().isEmpty()); } - map = tryParseTestMap(BizarroTestMap.newBuilder() - .putStringToInt32Field(stringKey, bytes) - .build()); + map = + tryParseTestMap( + BizarroTestMap.newBuilder().putStringToInt32Field(stringKey, bytes).build()); assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1)); } @@ -458,16 +441,18 @@ public void testEqualsAndHashCode() throws Exception { // We can't control the order of elements in a HashMap. The best we can do // here is to add elements in different order. - TestMap.Builder b1 = TestMap.newBuilder() - .putInt32ToInt32Field(1, 2) - .putInt32ToInt32Field(3, 4) - .putInt32ToInt32Field(5, 6); - TestMap m1 = b1.build(); - - TestMap.Builder b2 = TestMap.newBuilder() - .putInt32ToInt32Field(5, 6) - .putInt32ToInt32Field(1, 2) - .putInt32ToInt32Field(3, 4); + TestMap m1 = + TestMap.newBuilder() + .putInt32ToInt32Field(1, 2) + .putInt32ToInt32Field(3, 4) + .putInt32ToInt32Field(5, 6) + .build(); + + TestMap.Builder b2 = + TestMap.newBuilder() + .putInt32ToInt32Field(5, 6) + .putInt32ToInt32Field(1, 2) + .putInt32ToInt32Field(3, 4); TestMap m2 = b2.build(); assertEquals(m1, m2); @@ -482,23 +467,24 @@ public void testEqualsAndHashCode() throws Exception { } public void testUnknownEnumValues() throws Exception { - TestUnknownEnumValue.Builder builder = TestUnknownEnumValue.newBuilder() - .putInt32ToInt32Field(1, 1) - .putInt32ToInt32Field(2, 54321); - ByteString data = builder.build().toByteString(); + ByteString data = + TestUnknownEnumValue.newBuilder() + .putInt32ToInt32Field(1, 1) + .putInt32ToInt32Field(2, 54321) + .build() + .toByteString(); TestMap message = TestMap.parseFrom(data); // Entries with unknown enum values will be stored into UnknownFieldSet so // there is only one entry in the map. - assertEquals(1, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); + assertEquals(1, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); // Serializing and parsing should preserve the unknown entry. data = message.toByteString(); - TestUnknownEnumValue messageWithUnknownEnums = - TestUnknownEnumValue.parseFrom(data); - assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size()); - assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue()); - assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue()); + TestUnknownEnumValue messageWithUnknownEnums = TestUnknownEnumValue.parseFrom(data); + assertEquals(2, messageWithUnknownEnums.getInt32ToInt32FieldMap().size()); + assertEquals(1, messageWithUnknownEnums.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32FieldMap().get(2).intValue()); } public void testIterationOrder() throws Exception { @@ -506,18 +492,19 @@ public void testIterationOrder() throws Exception { setMapValues(builder); TestMap message = builder.build(); - assertEquals(Arrays.asList("1", "2", "3"), - new ArrayList(message.getStringToInt32Field().keySet())); + assertEquals( + Arrays.asList("1", "2", "3"), + new ArrayList(message.getStringToInt32FieldMap().keySet())); } private static Map newMap(K key1, V value1) { - Map map = new HashMap(); + Map map = new HashMap<>(); map.put(key1, value1); return map; } private static Map newMap(K key1, V value1, K key2, V value2) { - Map map = new HashMap(); + Map map = new HashMap<>(); map.put(key1, value1); map.put(key2, value2); return map; @@ -527,18 +514,10 @@ public void testGetMap() { TestMap.Builder builder = TestMap.newBuilder(); setMapValues(builder); TestMap message = builder.build(); - assertEquals( - message.getStringToInt32Field(), - message.getStringToInt32FieldMap()); - assertEquals( - message.getInt32ToBytesField(), - message.getInt32ToBytesFieldMap()); - assertEquals( - message.getInt32ToEnumField(), - message.getInt32ToEnumFieldMap()); - assertEquals( - message.getInt32ToMessageField(), - message.getInt32ToMessageFieldMap()); + assertEquals(message.getStringToInt32FieldMap(), message.getStringToInt32FieldMap()); + assertEquals(message.getInt32ToBytesFieldMap(), message.getInt32ToBytesFieldMap()); + assertEquals(message.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap()); + assertEquals(message.getInt32ToMessageFieldMap(), message.getInt32ToMessageFieldMap()); } public void testContains() { @@ -629,7 +608,8 @@ public void doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder) { assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrDefault(1, null)); assertNull(testMapOrBuilder.getInt32ToEnumFieldOrDefault(-1, null)); - assertEquals(MessageValue.newBuilder().setValue(11).build(), + assertEquals( + MessageValue.newBuilder().setValue(11).build(), testMapOrBuilder.getInt32ToMessageFieldOrDefault(1, null)); assertNull(testMapOrBuilder.getInt32ToMessageFieldOrDefault(-1, null)); @@ -687,7 +667,8 @@ public void doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder) { // expected } - assertEquals(MessageValue.newBuilder().setValue(11).build(), + assertEquals( + MessageValue.newBuilder().setValue(11).build(), testMapOrBuilder.getInt32ToMessageFieldOrThrow(1)); try { testMapOrBuilder.getInt32ToMessageFieldOrThrow(-1); diff --git a/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java index 37827f768af27..d2565ca157017 100644 --- a/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java +++ b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java @@ -49,9 +49,7 @@ import java.util.Map; import junit.framework.TestCase; -/** - * Unit tests for map fields in proto2 protos. - */ +/** Unit tests for map fields in proto2 protos. */ public class MapForProto2Test extends TestCase { private void setMapValuesUsingMutableMap(TestMap.Builder builder) { @@ -88,23 +86,18 @@ private void setMapValuesUsingAccessors(TestMap.Builder builder) { .putInt32ToInt32Field(1, 11) .putInt32ToInt32Field(2, 22) .putInt32ToInt32Field(3, 33) - .putInt32ToStringField(1, "11") .putInt32ToStringField(2, "22") .putInt32ToStringField(3, "33") - .putInt32ToBytesField(1, TestUtil.toBytes("11")) .putInt32ToBytesField(2, TestUtil.toBytes("22")) .putInt32ToBytesField(3, TestUtil.toBytes("33")) - .putInt32ToEnumField(1, TestMap.EnumValue.FOO) .putInt32ToEnumField(2, TestMap.EnumValue.BAR) .putInt32ToEnumField(3, TestMap.EnumValue.BAZ) - .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(11).build()) .putInt32ToMessageField(2, MessageValue.newBuilder().setValue(22).build()) .putInt32ToMessageField(3, MessageValue.newBuilder().setValue(33).build()) - .putStringToInt32Field("1", 11) .putStringToInt32Field("2", 22) .putStringToInt32Field("3", 33); @@ -126,44 +119,44 @@ public void testSetMapValues() { private void copyMapValues(TestMap source, TestMap.Builder destination) { destination - .putAllInt32ToInt32Field(source.getInt32ToInt32Field()) - .putAllInt32ToStringField(source.getInt32ToStringField()) - .putAllInt32ToBytesField(source.getInt32ToBytesField()) - .putAllInt32ToEnumField(source.getInt32ToEnumField()) - .putAllInt32ToMessageField(source.getInt32ToMessageField()) - .putAllStringToInt32Field(source.getStringToInt32Field()); + .putAllInt32ToInt32Field(source.getInt32ToInt32FieldMap()) + .putAllInt32ToStringField(source.getInt32ToStringFieldMap()) + .putAllInt32ToBytesField(source.getInt32ToBytesFieldMap()) + .putAllInt32ToEnumField(source.getInt32ToEnumFieldMap()) + .putAllInt32ToMessageField(source.getInt32ToMessageFieldMap()) + .putAllStringToInt32Field(source.getStringToInt32FieldMap()); } private void assertMapValuesSet(TestMapOrBuilder message) { - assertEquals(3, message.getInt32ToInt32Field().size()); - assertEquals(11, message.getInt32ToInt32Field().get(1).intValue()); - assertEquals(22, message.getInt32ToInt32Field().get(2).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(3).intValue()); - - assertEquals(3, message.getInt32ToStringField().size()); - assertEquals("11", message.getInt32ToStringField().get(1)); - assertEquals("22", message.getInt32ToStringField().get(2)); - assertEquals("33", message.getInt32ToStringField().get(3)); - - assertEquals(3, message.getInt32ToBytesField().size()); - assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1)); - assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2)); - assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); - - assertEquals(3, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2)); - assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); - - assertEquals(3, message.getInt32ToMessageField().size()); - assertEquals(11, message.getInt32ToMessageField().get(1).getValue()); - assertEquals(22, message.getInt32ToMessageField().get(2).getValue()); - assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); - - assertEquals(3, message.getStringToInt32Field().size()); - assertEquals(11, message.getStringToInt32Field().get("1").intValue()); - assertEquals(22, message.getStringToInt32Field().get("2").intValue()); - assertEquals(33, message.getStringToInt32Field().get("3").intValue()); + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(11, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(22, message.getInt32ToInt32FieldMap().get(2).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); + + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("11", message.getInt32ToStringFieldMap().get(1)); + assertEquals("22", message.getInt32ToStringFieldMap().get(2)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); + + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesFieldMap().get(2)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); + + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(2)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); + + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(11, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(22, message.getInt32ToMessageFieldMap().get(2).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); + + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(11, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(22, message.getStringToInt32FieldMap().get("2").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); } private void updateMapValuesUsingMutableMap(TestMap.Builder builder) { @@ -199,23 +192,18 @@ private void updateMapValuesUsingAccessors(TestMap.Builder builder) { .putInt32ToInt32Field(1, 111) .removeInt32ToInt32Field(2) .putInt32ToInt32Field(4, 44) - .putInt32ToStringField(1, "111") .removeInt32ToStringField(2) .putInt32ToStringField(4, "44") - .putInt32ToBytesField(1, TestUtil.toBytes("111")) .removeInt32ToBytesField(2) .putInt32ToBytesField(4, TestUtil.toBytes("44")) - .putInt32ToEnumField(1, TestMap.EnumValue.BAR) .removeInt32ToEnumField(2) .putInt32ToEnumField(4, TestMap.EnumValue.QUX) - .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(111).build()) .removeInt32ToMessageField(2) .putInt32ToMessageField(4, MessageValue.newBuilder().setValue(44).build()) - .putStringToInt32Field("1", 111) .removeStringToInt32Field("2") .putStringToInt32Field("4", 44); @@ -248,49 +236,49 @@ public void testUpdateMapValues() { } private void assertMapValuesUpdated(TestMap message) { - assertEquals(3, message.getInt32ToInt32Field().size()); - assertEquals(111, message.getInt32ToInt32Field().get(1).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(3).intValue()); - assertEquals(44, message.getInt32ToInt32Field().get(4).intValue()); - - assertEquals(3, message.getInt32ToStringField().size()); - assertEquals("111", message.getInt32ToStringField().get(1)); - assertEquals("33", message.getInt32ToStringField().get(3)); - assertEquals("44", message.getInt32ToStringField().get(4)); - - assertEquals(3, message.getInt32ToBytesField().size()); - assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1)); - assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); - assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4)); - - assertEquals(3, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); - assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4)); - - assertEquals(3, message.getInt32ToMessageField().size()); - assertEquals(111, message.getInt32ToMessageField().get(1).getValue()); - assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); - assertEquals(44, message.getInt32ToMessageField().get(4).getValue()); - - assertEquals(3, message.getStringToInt32Field().size()); - assertEquals(111, message.getStringToInt32Field().get("1").intValue()); - assertEquals(33, message.getStringToInt32Field().get("3").intValue()); - assertEquals(44, message.getStringToInt32Field().get("4").intValue()); + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(111, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); + assertEquals(44, message.getInt32ToInt32FieldMap().get(4).intValue()); + + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("111", message.getInt32ToStringFieldMap().get(1)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); + assertEquals("44", message.getInt32ToStringFieldMap().get(4)); + + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); + assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesFieldMap().get(4)); + + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); + assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumFieldMap().get(4)); + + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(111, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); + assertEquals(44, message.getInt32ToMessageFieldMap().get(4).getValue()); + + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(111, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); + assertEquals(44, message.getStringToInt32FieldMap().get("4").intValue()); } private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) { - assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size()); + assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount()); - assertEquals(0, testMapOrBuilder.getInt32ToStringField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToStringFieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount()); - assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount()); - assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount()); - assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount()); - assertEquals(0, testMapOrBuilder.getStringToInt32Field().size()); + assertEquals(0, testMapOrBuilder.getStringToInt32FieldMap().size()); assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount()); } @@ -305,13 +293,13 @@ public void testGetMapIsImmutable() { } private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) { - assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2); - assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2"); - assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2")); - assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO); + assertImmutable(testMapOrBuilder.getInt32ToInt32FieldMap(), 1, 2); + assertImmutable(testMapOrBuilder.getInt32ToStringFieldMap(), 1, "2"); + assertImmutable(testMapOrBuilder.getInt32ToBytesFieldMap(), 1, TestUtil.toBytes("2")); + assertImmutable(testMapOrBuilder.getInt32ToEnumFieldMap(), 1, TestMap.EnumValue.FOO); assertImmutable( - testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance()); - assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2); + testMapOrBuilder.getInt32ToMessageFieldMap(), 1, MessageValue.getDefaultInstance()); + assertImmutable(testMapOrBuilder.getStringToInt32FieldMap(), "1", 2); } private void assertImmutable(Map map, K key, V value) { @@ -337,7 +325,7 @@ public void testMutableMapLifecycle() { assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); builder.getMutableInt32ToInt32Field().put(2, 3); assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field()); - // + // Map enumMap = builder.getMutableInt32ToEnumField(); enumMap.put(1, TestMap.EnumValue.BAR); assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField()); @@ -432,7 +420,19 @@ public void testMutableMapLifecycle_collections() { assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); } - + // + private static Map newMap(K key1, V value1) { + Map map = new HashMap(); + map.put(key1, value1); + return map; + } + // + private static Map newMap(K key1, V value1, K key2, V value2) { + Map map = new HashMap(); + map.put(key1, value1); + map.put(key2, value2); + return map; + } public void testGettersAndSetters() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); @@ -543,40 +543,32 @@ public void testParseError() throws Exception { ByteString bytes = TestUtil.toBytes("SOME BYTES"); String stringKey = "a string key"; - TestMap map = tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToInt32Field(5, bytes) - .build()); + TestMap map = + tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToInt32Field(5, bytes).build()); assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1)); - map = tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToStringField(stringKey, 5) - .build()); + map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToStringField(stringKey, 5).build()); assertEquals("", map.getInt32ToStringFieldOrDefault(0, null)); - map = tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToBytesField(stringKey, 5) - .build()); + map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToBytesField(stringKey, 5).build()); assertEquals(map.getInt32ToBytesFieldOrDefault(0, null), ByteString.EMPTY); - map = tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToEnumField(stringKey, bytes) - .build()); + map = + tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToEnumField(stringKey, bytes).build()); assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null)); try { - tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToMessageField(stringKey, bytes) - .build()); + tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToMessageField(stringKey, bytes).build()); fail(); } catch (InvalidProtocolBufferException expected) { assertTrue(expected.getUnfinishedMessage() instanceof TestMap); map = (TestMap) expected.getUnfinishedMessage(); - assertTrue(map.getInt32ToMessageField().isEmpty()); + assertTrue(map.getInt32ToMessageFieldMap().isEmpty()); } - map = tryParseTestMap(BizarroTestMap.newBuilder() - .putStringToInt32Field(stringKey, bytes) - .build()); + map = + tryParseTestMap( + BizarroTestMap.newBuilder().putStringToInt32Field(stringKey, bytes).build()); assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1)); } @@ -657,8 +649,7 @@ private static void assertHasMapValues(Message message, String name, Map v } } - private static - Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) { + private static Message newMapEntry(Message.Builder builder, String name, K key, V value) { FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name); Message.Builder entryBuilder = builder.newBuilderForField(field); FieldDescriptor keyField = entryBuilder.getDescriptorForType().findFieldByName("key"); @@ -677,9 +668,8 @@ private static void setMapValues(Message.Builder builder, String name, Map builder.setField(field, entryList); } - private static Map mapForValues( - KeyType key1, ValueType value1, KeyType key2, ValueType value2) { - Map map = new HashMap(); + private static Map mapForValues(K key1, V value1, K key2, V value2) { + Map map = new HashMap(); map.put(key1, value1); map.put(key2, value2); return map; @@ -687,17 +677,19 @@ private static Map mapForValues( public void testReflectionApi() throws Exception { // In reflection API, map fields are just repeated message fields. - TestMap.Builder builder = TestMap.newBuilder() - .putInt32ToInt32Field(1, 2) - .putInt32ToInt32Field(3, 4) - .putInt32ToMessageField(11, MessageValue.newBuilder().setValue(22).build()) - .putInt32ToMessageField(33, MessageValue.newBuilder().setValue(44).build()); + TestMap.Builder builder = + TestMap.newBuilder() + .putInt32ToInt32Field(1, 2) + .putInt32ToInt32Field(3, 4) + .putInt32ToMessageField(11, MessageValue.newBuilder().setValue(22).build()) + .putInt32ToMessageField(33, MessageValue.newBuilder().setValue(44).build()); TestMap message = builder.build(); // Test getField(), getRepeatedFieldCount(), getRepeatedField(). - assertHasMapValues(message, "int32_to_int32_field", - mapForValues(1, 2, 3, 4)); - assertHasMapValues(message, "int32_to_message_field", + assertHasMapValues(message, "int32_to_int32_field", mapForValues(1, 2, 3, 4)); + assertHasMapValues( + message, + "int32_to_message_field", mapForValues( 11, MessageValue.newBuilder().setValue(22).build(), 33, MessageValue.newBuilder().setValue(44).build())); @@ -706,41 +698,50 @@ public void testReflectionApi() throws Exception { builder.clearField(f("int32_to_int32_field")); builder.clearField(f("int32_to_message_field")); message = builder.build(); - assertEquals(0, message.getInt32ToInt32Field().size()); - assertEquals(0, message.getInt32ToMessageField().size()); + assertEquals(0, message.getInt32ToInt32FieldMap().size()); + assertEquals(0, message.getInt32ToMessageFieldMap().size()); // Test setField() - setMapValues(builder, "int32_to_int32_field", - mapForValues(11, 22, 33, 44)); - setMapValues(builder, "int32_to_message_field", + setMapValues(builder, "int32_to_int32_field", mapForValues(11, 22, 33, 44)); + setMapValues( + builder, + "int32_to_message_field", mapForValues( 111, MessageValue.newBuilder().setValue(222).build(), 333, MessageValue.newBuilder().setValue(444).build())); message = builder.build(); - assertEquals(22, message.getInt32ToInt32Field().get(11).intValue()); - assertEquals(44, message.getInt32ToInt32Field().get(33).intValue()); - assertEquals(222, message.getInt32ToMessageField().get(111).getValue()); - assertEquals(444, message.getInt32ToMessageField().get(333).getValue()); + assertEquals(22, message.getInt32ToInt32FieldMap().get(11).intValue()); + assertEquals(44, message.getInt32ToInt32FieldMap().get(33).intValue()); + assertEquals(222, message.getInt32ToMessageFieldMap().get(111).getValue()); + assertEquals(444, message.getInt32ToMessageFieldMap().get(333).getValue()); // Test addRepeatedField - builder.addRepeatedField(f("int32_to_int32_field"), - newMapEntry(builder, "int32_to_int32_field", 55, 66)); - builder.addRepeatedField(f("int32_to_message_field"), - newMapEntry(builder, "int32_to_message_field", 555, + builder.addRepeatedField( + f("int32_to_int32_field"), newMapEntry(builder, "int32_to_int32_field", 55, 66)); + builder.addRepeatedField( + f("int32_to_message_field"), + newMapEntry( + builder, + "int32_to_message_field", + 555, MessageValue.newBuilder().setValue(666).build())); message = builder.build(); - assertEquals(66, message.getInt32ToInt32Field().get(55).intValue()); - assertEquals(666, message.getInt32ToMessageField().get(555).getValue()); + assertEquals(66, message.getInt32ToInt32FieldMap().get(55).intValue()); + assertEquals(666, message.getInt32ToMessageFieldMap().get(555).getValue()); // Test addRepeatedField (overriding existing values) - builder.addRepeatedField(f("int32_to_int32_field"), - newMapEntry(builder, "int32_to_int32_field", 55, 55)); - builder.addRepeatedField(f("int32_to_message_field"), - newMapEntry(builder, "int32_to_message_field", 555, + builder.addRepeatedField( + f("int32_to_int32_field"), newMapEntry(builder, "int32_to_int32_field", 55, 55)); + builder.addRepeatedField( + f("int32_to_message_field"), + newMapEntry( + builder, + "int32_to_message_field", + 555, MessageValue.newBuilder().setValue(555).build())); message = builder.build(); - assertEquals(55, message.getInt32ToInt32Field().get(55).intValue()); - assertEquals(555, message.getInt32ToMessageField().get(555).getValue()); + assertEquals(55, message.getInt32ToInt32FieldMap().get(55).intValue()); + assertEquals(555, message.getInt32ToMessageFieldMap().get(555).getValue()); // Test setRepeatedField for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) { @@ -754,9 +755,9 @@ public void testReflectionApi() throws Exception { builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build()); } message = builder.build(); - assertEquals(11, message.getInt32ToInt32Field().get(22).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(44).intValue()); - assertEquals(55, message.getInt32ToInt32Field().get(55).intValue()); + assertEquals(11, message.getInt32ToInt32FieldMap().get(22).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(44).intValue()); + assertEquals(55, message.getInt32ToInt32FieldMap().get(55).intValue()); } // See additional coverage in TextFormatTest.java. @@ -765,7 +766,7 @@ public void testTextFormat() throws Exception { setMapValuesUsingAccessors(builder); TestMap message = builder.build(); - String textData = TextFormat.printToString(message); + String textData = TextFormat.printer().printToString(message); builder = TestMap.newBuilder(); TextFormat.merge(textData, builder); @@ -779,22 +780,37 @@ public void testDynamicMessage() throws Exception { setMapValuesUsingAccessors(builder); TestMap message = builder.build(); - Message dynamicDefaultInstance = - DynamicMessage.getDefaultInstance(TestMap.getDescriptor()); - Message dynamicMessage = dynamicDefaultInstance - .newBuilderForType().mergeFrom(message.toByteString()).build(); + Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor()); + Message dynamicMessage = + dynamicDefaultInstance.newBuilderForType().mergeFrom(message.toByteString()).build(); assertEquals(message, dynamicMessage); assertEquals(message.hashCode(), dynamicMessage.hashCode()); } + // Check that DynamicMessage handles map field serialization the same way as generated code + // regarding unset key and value field in a map entry. + public void testDynamicMessageUnsetKeyAndValue() throws Exception { + FieldDescriptor field = f("int32_to_int32_field"); + + Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor()); + Message.Builder builder = dynamicDefaultInstance.newBuilderForType(); + // Add an entry without key and value. + builder.addRepeatedField(field, builder.newBuilderForField(field).build()); + Message message = builder.build(); + ByteString bytes = message.toByteString(); + // Parse it back to the same generated type. + Message generatedMessage = TestMap.parseFrom(bytes); + // Assert the serialized bytes are equivalent. + assertEquals(generatedMessage.toByteString(), bytes); + } + public void testReflectionEqualsAndHashCode() throws Exception { // Test that generated equals() and hashCode() will disregard the order // of map entries when comparing/hashing map fields. // We use DynamicMessage to test reflection based equals()/hashCode(). - Message dynamicDefaultInstance = - DynamicMessage.getDefaultInstance(TestMap.getDescriptor()); + Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor()); FieldDescriptor field = f("int32_to_int32_field"); Message.Builder b1 = dynamicDefaultInstance.newBuilderForType(); @@ -821,25 +837,23 @@ public void testReflectionEqualsAndHashCode() throws Exception { } public void testUnknownEnumValues() throws Exception { - TestUnknownEnumValue.Builder builder = TestUnknownEnumValue.newBuilder() - .putInt32ToInt32Field(1, 1) - .putInt32ToInt32Field(2, 54321); + TestUnknownEnumValue.Builder builder = + TestUnknownEnumValue.newBuilder().putInt32ToInt32Field(1, 1).putInt32ToInt32Field(2, 54321); ByteString data = builder.build().toByteString(); TestMap message = TestMap.parseFrom(data); // Entries with unknown enum values will be stored into UnknownFieldSet so // there is only one entry in the map. - assertEquals(1, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); + assertEquals(1, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); // UnknownFieldSet should not be empty. assertFalse(message.getUnknownFields().asMap().isEmpty()); // Serializing and parsing should preserve the unknown entry. data = message.toByteString(); - TestUnknownEnumValue messageWithUnknownEnums = - TestUnknownEnumValue.parseFrom(data); - assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size()); - assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue()); - assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue()); + TestUnknownEnumValue messageWithUnknownEnums = TestUnknownEnumValue.parseFrom(data); + assertEquals(2, messageWithUnknownEnums.getInt32ToInt32FieldMap().size()); + assertEquals(1, messageWithUnknownEnums.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32FieldMap().get(2).intValue()); } public void testRequiredMessage() throws Exception { @@ -860,8 +874,8 @@ public void testRecursiveMap() throws Exception { ByteString data = builder.build().toByteString(); TestRecursiveMap message = TestRecursiveMap.parseFrom(data); - assertEquals(2, message.getRecursiveMapField().get(1).getValue()); - assertEquals(4, message.getRecursiveMapField().get(3).getValue()); + assertEquals(2, message.getRecursiveMapFieldMap().get(1).getValue()); + assertEquals(4, message.getRecursiveMapFieldMap().get(3).getValue()); } public void testIterationOrder() throws Exception { @@ -869,8 +883,9 @@ public void testIterationOrder() throws Exception { setMapValuesUsingAccessors(builder); TestMap message = builder.build(); - assertEquals(Arrays.asList("1", "2", "3"), - new ArrayList(message.getStringToInt32Field().keySet())); + assertEquals( + Arrays.asList("1", "2", "3"), + new ArrayList(message.getStringToInt32FieldMap().keySet())); } public void testContains() { @@ -961,7 +976,8 @@ public void doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder) { assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrDefault(1, null)); assertNull(testMapOrBuilder.getInt32ToEnumFieldOrDefault(-1, null)); - assertEquals(MessageValue.newBuilder().setValue(11).build(), + assertEquals( + MessageValue.newBuilder().setValue(11).build(), testMapOrBuilder.getInt32ToMessageFieldOrDefault(1, null)); assertNull(testMapOrBuilder.getInt32ToMessageFieldOrDefault(-1, null)); @@ -1019,7 +1035,8 @@ public void doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder) { // expected } - assertEquals(MessageValue.newBuilder().setValue(11).build(), + assertEquals( + MessageValue.newBuilder().setValue(11).build(), testMapOrBuilder.getInt32ToMessageFieldOrThrow(1)); try { testMapOrBuilder.getInt32ToMessageFieldOrThrow(-1); @@ -1128,15 +1145,20 @@ public void testRemove() { // Regression test for b/20494788 public void testMapInitializationOrder() throws Exception { - assertEquals("RedactAllTypes", map_test.RedactAllTypes - .getDefaultInstance().getDescriptorForType().getName()); + assertEquals( + "RedactAllTypes", + map_test.RedactAllTypes.getDefaultInstance() + .getDescriptorForType() + .getName()); map_test.Message1.Builder builder = map_test.Message1.newBuilder(); builder.putMapField("key", true); map_test.Message1 message = builder.build(); - Message mapEntry = (Message) message.getRepeatedField( - message.getDescriptorForType().findFieldByName("map_field"), 0); + Message mapEntry = + (Message) + message.getRepeatedField( + message.getDescriptorForType().findFieldByName("map_field"), 0); assertEquals(2, mapEntry.getAllFields().size()); } @@ -1145,35 +1167,14 @@ public void testReservedWordsFieldNames() { ReservedAsMapFieldWithEnumValue.newBuilder().build(); } - private static Map newMap(K key1, V value1) { - Map map = new HashMap(); - map.put(key1, value1); - return map; - } - - private static Map newMap(K key1, V value1, K key2, V value2) { - Map map = new HashMap(); - map.put(key1, value1); - map.put(key2, value2); - return map; - } - public void testGetMap() { TestMap.Builder builder = TestMap.newBuilder(); setMapValuesUsingAccessors(builder); assertMapValuesSet(builder); TestMap message = builder.build(); - assertEquals( - message.getStringToInt32Field(), - message.getStringToInt32FieldMap()); - assertEquals( - message.getInt32ToBytesField(), - message.getInt32ToBytesFieldMap()); - assertEquals( - message.getInt32ToEnumField(), - message.getInt32ToEnumFieldMap()); - assertEquals( - message.getInt32ToMessageField(), - message.getInt32ToMessageFieldMap()); + assertEquals(message.getStringToInt32FieldMap(), message.getStringToInt32FieldMap()); + assertEquals(message.getInt32ToBytesFieldMap(), message.getInt32ToBytesFieldMap()); + assertEquals(message.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap()); + assertEquals(message.getInt32ToMessageFieldMap(), message.getInt32ToMessageFieldMap()); } } diff --git a/java/core/src/test/java/com/google/protobuf/MapLiteTest.java b/java/core/src/test/java/com/google/protobuf/MapLiteTest.java new file mode 100644 index 0000000000000..33282add80d0c --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/MapLiteTest.java @@ -0,0 +1,895 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static org.junit.Assert.assertArrayEquals; + +import map_lite_test.MapTestProto.BizarroTestMap; +import map_lite_test.MapTestProto.TestMap; +import map_lite_test.MapTestProto.TestMap.MessageValue; +import map_lite_test.MapTestProto.TestMapOrBuilder; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import junit.framework.TestCase; + +/** Unit tests for map fields. */ +public final class MapLiteTest extends TestCase { + + private void setMapValues(TestMap.Builder builder) { + builder + .putInt32ToInt32Field(1, 11) + .putInt32ToInt32Field(2, 22) + .putInt32ToInt32Field(3, 33) + .putInt32ToStringField(1, "11") + .putInt32ToStringField(2, "22") + .putInt32ToStringField(3, "33") + .putInt32ToBytesField(1, TestUtil.toBytes("11")) + .putInt32ToBytesField(2, TestUtil.toBytes("22")) + .putInt32ToBytesField(3, TestUtil.toBytes("33")) + .putInt32ToEnumField(1, TestMap.EnumValue.FOO) + .putInt32ToEnumField(2, TestMap.EnumValue.BAR) + .putInt32ToEnumField(3, TestMap.EnumValue.BAZ) + .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(11).build()) + .putInt32ToMessageField(2, MessageValue.newBuilder().setValue(22).build()) + .putInt32ToMessageField(3, MessageValue.newBuilder().setValue(33).build()) + .putStringToInt32Field("1", 11) + .putStringToInt32Field("2", 22) + .putStringToInt32Field("3", 33); + } + + public void testSetMapValues() { + TestMap.Builder usingMutableMapBuilder = TestMap.newBuilder(); + setMapValues(usingMutableMapBuilder); + TestMap usingMutableMap = usingMutableMapBuilder.build(); + assertMapValuesSet(usingMutableMap); + + TestMap.Builder usingAccessorsBuilder = TestMap.newBuilder(); + setMapValues(usingAccessorsBuilder); + TestMap usingAccessors = usingAccessorsBuilder.build(); + assertMapValuesSet(usingAccessors); + assertEquals(usingAccessors, usingMutableMap); + } + + private void copyMapValues(TestMap source, TestMap.Builder destination) { + destination + .putAllInt32ToInt32Field(source.getInt32ToInt32FieldMap()) + .putAllInt32ToStringField(source.getInt32ToStringFieldMap()) + .putAllInt32ToBytesField(source.getInt32ToBytesFieldMap()) + .putAllInt32ToEnumField(source.getInt32ToEnumFieldMap()) + .putAllInt32ToMessageField(source.getInt32ToMessageFieldMap()) + .putAllStringToInt32Field(source.getStringToInt32FieldMap()); + } + + private void assertMapValuesSet(TestMap message) { + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(11, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(22, message.getInt32ToInt32FieldMap().get(2).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); + + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("11", message.getInt32ToStringFieldMap().get(1)); + assertEquals("22", message.getInt32ToStringFieldMap().get(2)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); + + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesFieldMap().get(2)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); + + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(2)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); + + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(11, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(22, message.getInt32ToMessageFieldMap().get(2).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); + + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(11, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(22, message.getStringToInt32FieldMap().get("2").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); + } + + private void updateMapValues(TestMap.Builder builder) { + builder + .putInt32ToInt32Field(1, 111) + .removeInt32ToInt32Field(2) + .putInt32ToInt32Field(4, 44) + .putInt32ToStringField(1, "111") + .removeInt32ToStringField(2) + .putInt32ToStringField(4, "44") + .putInt32ToBytesField(1, TestUtil.toBytes("111")) + .removeInt32ToBytesField(2) + .putInt32ToBytesField(4, TestUtil.toBytes("44")) + .putInt32ToEnumField(1, TestMap.EnumValue.BAR) + .removeInt32ToEnumField(2) + .putInt32ToEnumField(4, TestMap.EnumValue.QUX) + .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(111).build()) + .removeInt32ToMessageField(2) + .putInt32ToMessageField(4, MessageValue.newBuilder().setValue(44).build()) + .putStringToInt32Field("1", 111) + .removeStringToInt32Field("2") + .putStringToInt32Field("4", 44); + } + + public void testUpdateMapValues() { + TestMap.Builder mapBuilder = TestMap.newBuilder(); + setMapValues(mapBuilder); + TestMap map = mapBuilder.build(); + assertMapValuesSet(map); + + mapBuilder = map.toBuilder(); + updateMapValues(mapBuilder); + map = mapBuilder.build(); + assertMapValuesUpdated(map); + } + + private void assertMapValuesUpdated(TestMap message) { + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(111, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); + assertEquals(44, message.getInt32ToInt32FieldMap().get(4).intValue()); + + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("111", message.getInt32ToStringFieldMap().get(1)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); + assertEquals("44", message.getInt32ToStringFieldMap().get(4)); + + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); + assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesFieldMap().get(4)); + + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); + assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumFieldMap().get(4)); + + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(111, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); + assertEquals(44, message.getInt32ToMessageFieldMap().get(4).getValue()); + + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(111, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); + assertEquals(44, message.getStringToInt32FieldMap().get("4").intValue()); + } + + private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) { + assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldMap().size()); + assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToStringFieldMap().size()); + assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldMap().size()); + assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldMap().size()); + assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount()); + assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldMap().size()); + assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount()); + assertEquals(0, testMapOrBuilder.getStringToInt32FieldMap().size()); + assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount()); + } + + public void testSanityCopyOnWrite() throws InvalidProtocolBufferException { + // Since builders are implemented as a thin wrapper around a message + // instance, we attempt to verify that we can't cause the builder to modify + // a produced message. + + TestMap.Builder builder = TestMap.newBuilder(); + TestMap message = builder.build(); + builder.putInt32ToInt32Field(1, 2); + assertTrue(message.getInt32ToInt32FieldMap().isEmpty()); + assertEquals(newMap(1, 2), builder.getInt32ToInt32FieldMap()); + message = builder.build(); + builder.putInt32ToInt32Field(2, 3); + assertEquals(newMap(1, 2), message.getInt32ToInt32FieldMap()); + assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32FieldMap()); + } + + public void testGetMapIsImmutable() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapsAreImmutable(builder); + assertMapsAreImmutable(builder.build()); + + setMapValues(builder); + assertMapsAreImmutable(builder); + assertMapsAreImmutable(builder.build()); + } + + private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) { + assertImmutable(testMapOrBuilder.getInt32ToInt32FieldMap(), 1, 2); + assertImmutable(testMapOrBuilder.getInt32ToStringFieldMap(), 1, "2"); + assertImmutable(testMapOrBuilder.getInt32ToBytesFieldMap(), 1, TestUtil.toBytes("2")); + assertImmutable(testMapOrBuilder.getInt32ToEnumFieldMap(), 1, TestMap.EnumValue.FOO); + assertImmutable( + testMapOrBuilder.getInt32ToMessageFieldMap(), 1, MessageValue.getDefaultInstance()); + assertImmutable(testMapOrBuilder.getStringToInt32FieldMap(), "1", 2); + } + + private void assertImmutable(Map map, K key, V value) { + try { + map.put(key, value); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + if (!map.isEmpty()) { + try { + map.entrySet().remove(map.entrySet().iterator().next()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } + } + + public void testMapFieldClear() { + TestMap.Builder builder = TestMap.newBuilder().putInt32ToInt32Field(1, 2); + builder.clearInt32ToInt32Field(); + assertEquals(0, builder.getInt32ToInt32FieldCount()); + } + + public void testMutableMapLifecycle() { + TestMap.Builder builder = TestMap.newBuilder().putInt32ToInt32Field(1, 2); + assertEquals(newMap(1, 2), builder.build().getInt32ToInt32FieldMap()); + assertEquals(newMap(1, 2), builder.getInt32ToInt32FieldMap()); + builder.putInt32ToInt32Field(2, 3); + assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32FieldMap()); + + builder.putInt32ToEnumField(1, TestMap.EnumValue.BAR); + assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumFieldMap()); + assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumFieldMap()); + builder.putInt32ToEnumField(2, TestMap.EnumValue.FOO); + assertEquals( + newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), + builder.getInt32ToEnumFieldMap()); + + builder.putInt32ToStringField(1, "1"); + assertEquals(newMap(1, "1"), builder.build().getInt32ToStringFieldMap()); + assertEquals(newMap(1, "1"), builder.getInt32ToStringFieldMap()); + builder.putInt32ToStringField(2, "2"); + assertEquals(newMap(1, "1", 2, "2"), builder.getInt32ToStringFieldMap()); + + builder.putInt32ToMessageField(1, TestMap.MessageValue.getDefaultInstance()); + assertEquals( + newMap(1, TestMap.MessageValue.getDefaultInstance()), + builder.build().getInt32ToMessageFieldMap()); + assertEquals( + newMap(1, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageFieldMap()); + builder.putInt32ToMessageField(2, TestMap.MessageValue.getDefaultInstance()); + assertEquals( + newMap( + 1, + TestMap.MessageValue.getDefaultInstance(), + 2, + TestMap.MessageValue.getDefaultInstance()), + builder.getInt32ToMessageFieldMap()); + } + + public void testGettersAndSetters() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + TestMap message = builder.build(); + assertMapValuesCleared(message); + + builder = message.toBuilder(); + setMapValues(builder); + message = builder.build(); + assertMapValuesSet(message); + + builder = message.toBuilder(); + updateMapValues(builder); + message = builder.build(); + assertMapValuesUpdated(message); + + builder = message.toBuilder(); + builder.clear(); + assertMapValuesCleared(builder); + message = builder.build(); + assertMapValuesCleared(message); + } + + public void testPutAll() throws Exception { + TestMap.Builder sourceBuilder = TestMap.newBuilder(); + setMapValues(sourceBuilder); + TestMap source = sourceBuilder.build(); + assertMapValuesSet(source); + + TestMap.Builder destination = TestMap.newBuilder(); + copyMapValues(source, destination); + assertMapValuesSet(destination.build()); + } + + public void testPutAllForUnknownEnumValues() throws Exception { + TestMap.Builder sourceBuilder = + TestMap.newBuilder() + .putInt32ToEnumFieldValue(0, 0) + .putInt32ToEnumFieldValue(1, 1) + .putAllInt32ToEnumFieldValue(newMap(2, 1000)); // unknown value. + TestMap source = sourceBuilder.build(); + + TestMap.Builder destinationBuilder = TestMap.newBuilder(); + destinationBuilder.putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValueMap()); + TestMap destination = destinationBuilder.build(); + + assertEquals(0, destination.getInt32ToEnumFieldValueMap().get(0).intValue()); + assertEquals(1, destination.getInt32ToEnumFieldValueMap().get(1).intValue()); + assertEquals(1000, destination.getInt32ToEnumFieldValueMap().get(2).intValue()); + assertEquals(3, destination.getInt32ToEnumFieldCount()); + } + + public void testPutForUnknownEnumValues() throws Exception { + TestMap.Builder builder = + TestMap.newBuilder() + .putInt32ToEnumFieldValue(0, 0) + .putInt32ToEnumFieldValue(1, 1) + .putInt32ToEnumFieldValue(2, 1000); // unknown value. + TestMap message = builder.build(); + + assertEquals(0, message.getInt32ToEnumFieldValueOrThrow(0)); + assertEquals(1, message.getInt32ToEnumFieldValueOrThrow(1)); + assertEquals(1000, message.getInt32ToEnumFieldValueOrThrow(2)); + assertEquals(3, message.getInt32ToEnumFieldCount()); + } + + public void testPutChecksNullKeysAndValues() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + + try { + builder.putInt32ToStringField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putInt32ToBytesField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putInt32ToEnumField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putInt32ToMessageField(1, null); + fail(); + } catch (NullPointerException e) { + // expected. + } + + try { + builder.putStringToInt32Field(null, 1); + fail(); + } catch (NullPointerException e) { + // expected. + } + } + + public void testSerializeAndParse() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValues(builder); + TestMap message = builder.build(); + assertEquals(message.getSerializedSize(), message.toByteString().size()); + message = TestMap.parser().parseFrom(message.toByteString()); + assertMapValuesSet(message); + + builder = message.toBuilder(); + updateMapValues(builder); + message = builder.build(); + assertEquals(message.getSerializedSize(), message.toByteString().size()); + message = TestMap.parser().parseFrom(message.toByteString()); + assertMapValuesUpdated(message); + + builder = message.toBuilder(); + builder.clear(); + message = builder.build(); + assertEquals(message.getSerializedSize(), message.toByteString().size()); + message = TestMap.parser().parseFrom(message.toByteString()); + assertMapValuesCleared(message); + } + + private TestMap tryParseTestMap(BizarroTestMap bizarroMap) throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream); + bizarroMap.writeTo(output); + output.flush(); + return TestMap.parser().parseFrom(ByteString.copyFrom(byteArrayOutputStream.toByteArray())); + } + + public void testParseError() throws Exception { + ByteString bytes = TestUtil.toBytes("SOME BYTES"); + String stringKey = "a string key"; + + TestMap map = + tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToInt32Field(5, bytes).build()); + assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1)); + + map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToStringField(stringKey, 5).build()); + assertEquals("", map.getInt32ToStringFieldOrDefault(0, null)); + + map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToBytesField(stringKey, 5).build()); + assertEquals(map.getInt32ToBytesFieldOrDefault(0, null), ByteString.EMPTY); + + map = + tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToEnumField(stringKey, bytes).build()); + assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null)); + + try { + tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToMessageField(stringKey, bytes).build()); + fail(); + } catch (InvalidProtocolBufferException expected) { + assertTrue(expected.getUnfinishedMessage() instanceof TestMap); + map = (TestMap) expected.getUnfinishedMessage(); + assertTrue(map.getInt32ToMessageFieldMap().isEmpty()); + } + + map = + tryParseTestMap( + BizarroTestMap.newBuilder().putStringToInt32Field(stringKey, bytes).build()); + assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1)); + } + + public void testMergeFrom() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValues(builder); + TestMap message = builder.build(); + + TestMap.Builder other = TestMap.newBuilder(); + other.mergeFrom(message); + assertMapValuesSet(other.build()); + } + + public void testEqualsAndHashCode() throws Exception { + // Test that generated equals() and hashCode() will disregard the order + // of map entries when comparing/hashing map fields. + + // We can't control the order of elements in a HashMap. The best we can do + // here is to add elements in different order. + TestMap.Builder b1 = + TestMap.newBuilder() + .putInt32ToInt32Field(1, 2) + .putInt32ToInt32Field(3, 4) + .putInt32ToInt32Field(5, 6); + TestMap m1 = b1.build(); + + TestMap.Builder b2 = + TestMap.newBuilder() + .putInt32ToInt32Field(5, 6) + .putInt32ToInt32Field(1, 2) + .putInt32ToInt32Field(3, 4); + TestMap m2 = b2.build(); + + assertEquals(m1, m2); + assertEquals(m1.hashCode(), m2.hashCode()); + + // Make sure we did compare map fields. + b2.putInt32ToInt32Field(1, 0); + m2 = b2.build(); + assertFalse(m1.equals(m2)); + // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed + // to be different. + + // Regression test for b/18549190: if a map is a subset of the other map, + // equals() should return false. + b2.removeInt32ToInt32Field(1); + m2 = b2.build(); + assertFalse(m1.equals(m2)); + assertFalse(m2.equals(m1)); + } + + public void testUnknownEnumValues() throws Exception { + TestMap.Builder builder = + TestMap.newBuilder() + .putInt32ToEnumFieldValue(0, 0) + .putInt32ToEnumFieldValue(1, 1) + .putInt32ToEnumFieldValue(2, 1000); // unknown value. + TestMap message = builder.build(); + + assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(0)); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumFieldMap().get(2)); + + builder.putAllInt32ToEnumFieldValue(newMap(2, 1000)); // unknown value. + message = builder.build(); + assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumFieldMap().get(2)); + + // Unknown enum values should be preserved after: + // 1. Serialization and parsing. + // 2. toBuild(). + // 3. mergeFrom(). + message = TestMap.parseFrom(message.toByteString()); + assertEquals(1000, message.getInt32ToEnumFieldValueMap().get(2).intValue()); + builder = message.toBuilder(); + assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue()); + builder = TestMap.newBuilder().mergeFrom(message); + assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue()); + + // hashCode()/equals() should take unknown enum values into account. + builder.putAllInt32ToEnumFieldValue(newMap(2, 1001)); + TestMap message2 = builder.build(); + assertFalse(message.hashCode() == message2.hashCode()); + assertFalse(message.equals(message2)); + // Unknown values will be converted to UNRECOGNIZED so the resulted enum map + // should be the same. + assertEquals(message2.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap()); + } + + public void testIterationOrder() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValues(builder); + TestMap message = builder.build(); + + assertEquals( + Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32FieldMap().keySet())); + } + + public void testGetMap() { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValues(builder); + TestMap message = builder.build(); + assertEquals(message.getStringToInt32FieldMap(), message.getStringToInt32FieldMap()); + assertEquals(message.getInt32ToBytesFieldMap(), message.getInt32ToBytesFieldMap()); + assertEquals(message.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap()); + assertEquals(message.getInt32ToEnumFieldValueMap(), message.getInt32ToEnumFieldValueMap()); + assertEquals(message.getInt32ToMessageFieldMap(), message.getInt32ToMessageFieldMap()); + } + + public void testContains() { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValues(builder); + assertMapContainsSetValues(builder); + assertMapContainsSetValues(builder.build()); + } + + private void assertMapContainsSetValues(TestMapOrBuilder testMapOrBuilder) { + assertTrue(testMapOrBuilder.containsInt32ToInt32Field(1)); + assertTrue(testMapOrBuilder.containsInt32ToInt32Field(2)); + assertTrue(testMapOrBuilder.containsInt32ToInt32Field(3)); + assertFalse(testMapOrBuilder.containsInt32ToInt32Field(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToStringField(1)); + assertTrue(testMapOrBuilder.containsInt32ToStringField(2)); + assertTrue(testMapOrBuilder.containsInt32ToStringField(3)); + assertFalse(testMapOrBuilder.containsInt32ToStringField(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToBytesField(1)); + assertTrue(testMapOrBuilder.containsInt32ToBytesField(2)); + assertTrue(testMapOrBuilder.containsInt32ToBytesField(3)); + assertFalse(testMapOrBuilder.containsInt32ToBytesField(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToEnumField(1)); + assertTrue(testMapOrBuilder.containsInt32ToEnumField(2)); + assertTrue(testMapOrBuilder.containsInt32ToEnumField(3)); + assertFalse(testMapOrBuilder.containsInt32ToEnumField(-1)); + + assertTrue(testMapOrBuilder.containsInt32ToMessageField(1)); + assertTrue(testMapOrBuilder.containsInt32ToMessageField(2)); + assertTrue(testMapOrBuilder.containsInt32ToMessageField(3)); + assertFalse(testMapOrBuilder.containsInt32ToMessageField(-1)); + + assertTrue(testMapOrBuilder.containsStringToInt32Field("1")); + assertTrue(testMapOrBuilder.containsStringToInt32Field("2")); + assertTrue(testMapOrBuilder.containsStringToInt32Field("3")); + assertFalse(testMapOrBuilder.containsStringToInt32Field("-1")); + } + + public void testCount() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapCounts(0, builder); + + setMapValues(builder); + assertMapCounts(3, builder); + + TestMap message = builder.build(); + assertMapCounts(3, message); + + builder = message.toBuilder().putInt32ToInt32Field(4, 44); + assertEquals(4, builder.getInt32ToInt32FieldCount()); + assertEquals(4, builder.build().getInt32ToInt32FieldCount()); + + // already present - should be unchanged + builder.putInt32ToInt32Field(4, 44); + assertEquals(4, builder.getInt32ToInt32FieldCount()); + } + + private void assertMapCounts(int expectedCount, TestMapOrBuilder testMapOrBuilder) { + assertEquals(expectedCount, testMapOrBuilder.getInt32ToInt32FieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToStringFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToBytesFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToEnumFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getInt32ToMessageFieldCount()); + assertEquals(expectedCount, testMapOrBuilder.getStringToInt32FieldCount()); + } + + public void testGetOrDefault() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapCounts(0, builder); + setMapValues(builder); + doTestGetOrDefault(builder); + doTestGetOrDefault(builder.build()); + } + + public void doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder) { + assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(1, -11)); + assertEquals(-11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(-1, -11)); + + assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrDefault(1, "-11")); + assertNull("-11", testMapOrBuilder.getInt32ToStringFieldOrDefault(-1, null)); + + assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrDefault(1, null)); + assertNull(testMapOrBuilder.getInt32ToBytesFieldOrDefault(-1, null)); + + assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrDefault(1, null)); + assertNull(testMapOrBuilder.getInt32ToEnumFieldOrDefault(-1, null)); + + assertEquals( + TestMap.EnumValue.BAR.getNumber(), + testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(2, -1)); + assertEquals(-1, testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(-1000, -1)); + + assertEquals( + MessageValue.newBuilder().setValue(11).build(), + testMapOrBuilder.getInt32ToMessageFieldOrDefault(1, null)); + assertNull(testMapOrBuilder.getInt32ToMessageFieldOrDefault(-1, null)); + + assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrDefault("1", -11)); + assertEquals(-11, testMapOrBuilder.getStringToInt32FieldOrDefault("-1", -11)); + + try { + testMapOrBuilder.getStringToInt32FieldOrDefault(null, -11); + fail(); + } catch (NullPointerException e) { + // expected + } + } + + public void testGetOrThrow() { + TestMap.Builder builder = TestMap.newBuilder(); + assertMapCounts(0, builder); + setMapValues(builder); + doTestGetOrDefault(builder); + doTestGetOrDefault(builder.build()); + } + + public void doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder) { + assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrThrow(1)); + try { + testMapOrBuilder.getInt32ToInt32FieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrThrow(1)); + + try { + testMapOrBuilder.getInt32ToStringFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrThrow(1)); + + try { + testMapOrBuilder.getInt32ToBytesFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrThrow(1)); + try { + testMapOrBuilder.getInt32ToEnumFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals( + TestMap.EnumValue.BAR.getNumber(), testMapOrBuilder.getInt32ToEnumFieldValueOrThrow(2)); + try { + testMapOrBuilder.getInt32ToEnumFieldValueOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals( + MessageValue.newBuilder().setValue(11).build(), + testMapOrBuilder.getInt32ToMessageFieldOrThrow(1)); + try { + testMapOrBuilder.getInt32ToMessageFieldOrThrow(-1); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrThrow("1")); + try { + testMapOrBuilder.getStringToInt32FieldOrThrow("-1"); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + try { + testMapOrBuilder.getStringToInt32FieldOrThrow(null); + fail(); + } catch (NullPointerException e) { + // expected + } + } + + public void testPut() { + TestMap.Builder builder = TestMap.newBuilder(); + builder.putInt32ToInt32Field(1, 11); + assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1)); + + builder.putInt32ToStringField(1, "a"); + assertEquals("a", builder.getInt32ToStringFieldOrThrow(1)); + try { + builder.putInt32ToStringField(1, null); + fail(); + } catch (NullPointerException e) { + // expected + } + + builder.putInt32ToBytesField(1, TestUtil.toBytes("11")); + assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1)); + try { + builder.putInt32ToBytesField(1, null); + fail(); + } catch (NullPointerException e) { + // expected + } + + builder.putInt32ToEnumField(1, TestMap.EnumValue.FOO); + assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1)); + try { + builder.putInt32ToEnumField(1, null); + fail(); + } catch (NullPointerException e) { + // expected + } + + builder.putStringToInt32Field("a", 1); + assertEquals(1, builder.getStringToInt32FieldOrThrow("a")); + try { + builder.putStringToInt32Field(null, -1); + } catch (NullPointerException e) { + // expected + } + } + + public void testRemove() { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValues(builder); + assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToInt32Field(1); + assertEquals(-1, builder.getInt32ToInt32FieldOrDefault(1, -1)); + } + + assertEquals("11", builder.getInt32ToStringFieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToStringField(1); + assertNull(builder.getInt32ToStringFieldOrDefault(1, null)); + } + + assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToBytesField(1); + assertNull(builder.getInt32ToBytesFieldOrDefault(1, null)); + } + + assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1)); + for (int times = 0; times < 2; times++) { + builder.removeInt32ToEnumField(1); + assertNull(builder.getInt32ToEnumFieldOrDefault(1, null)); + } + + assertEquals(11, builder.getStringToInt32FieldOrThrow("1")); + for (int times = 0; times < 2; times++) { + builder.removeStringToInt32Field("1"); + assertEquals(-1, builder.getStringToInt32FieldOrDefault("1", -1)); + } + + try { + builder.removeStringToInt32Field(null); + fail(); + } catch (NullPointerException e) { + // expected + } + } + + private static Map newMap(K key1, V value1) { + Map map = new HashMap<>(); + map.put(key1, value1); + return map; + } + + private static Map newMap(K key1, V value1, K key2, V value2) { + Map map = new HashMap<>(); + map.put(key1, value1); + map.put(key2, value2); + return map; + } + + public void testMap_withNulls() { + TestMap.Builder builder = TestMap.newBuilder(); + + try { + builder.putStringToInt32Field(null, 3); + fail(); + } catch (NullPointerException expected) { + } + + try { + builder.putAllStringToInt32Field(newMap(null, 3, "hi", 4)); + fail(); + } catch (NullPointerException expected) { + } + + try { + builder.putInt32ToMessageField(3, null); + fail(); + } catch (NullPointerException expected) { + } + + try { + builder.putAllInt32ToMessageField( + MapLiteTest.newMap(4, null, 5, null)); + fail(); + } catch (NullPointerException expected) { + } + + try { + builder.putAllInt32ToMessageField(null); + fail(); + } catch (NullPointerException expected) { + } + + assertArrayEquals(new byte[0], builder.build().toByteArray()); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/MapTest.java b/java/core/src/test/java/com/google/protobuf/MapTest.java index 64ae4435d06f3..2f55328b5105f 100644 --- a/java/core/src/test/java/com/google/protobuf/MapTest.java +++ b/java/core/src/test/java/com/google/protobuf/MapTest.java @@ -31,6 +31,7 @@ package com.google.protobuf; import static org.junit.Assert.assertArrayEquals; + import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.EnumValueDescriptor; @@ -51,9 +52,7 @@ import java.util.Map; import junit.framework.TestCase; -/** - * Unit tests for map fields. - */ +/** Unit tests for map fields. */ public class MapTest extends TestCase { private void setMapValuesUsingMutableMap(TestMap.Builder builder) { @@ -90,23 +89,18 @@ private void setMapValuesUsingAccessors(TestMap.Builder builder) { .putInt32ToInt32Field(1, 11) .putInt32ToInt32Field(2, 22) .putInt32ToInt32Field(3, 33) - .putInt32ToStringField(1, "11") .putInt32ToStringField(2, "22") .putInt32ToStringField(3, "33") - .putInt32ToBytesField(1, TestUtil.toBytes("11")) .putInt32ToBytesField(2, TestUtil.toBytes("22")) .putInt32ToBytesField(3, TestUtil.toBytes("33")) - .putInt32ToEnumField(1, TestMap.EnumValue.FOO) .putInt32ToEnumField(2, TestMap.EnumValue.BAR) .putInt32ToEnumField(3, TestMap.EnumValue.BAZ) - .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(11).build()) .putInt32ToMessageField(2, MessageValue.newBuilder().setValue(22).build()) .putInt32ToMessageField(3, MessageValue.newBuilder().setValue(33).build()) - .putStringToInt32Field("1", 11) .putStringToInt32Field("2", 22) .putStringToInt32Field("3", 33); @@ -128,44 +122,44 @@ public void testSetMapValues() { private void copyMapValues(TestMap source, TestMap.Builder destination) { destination - .putAllInt32ToInt32Field(source.getInt32ToInt32Field()) - .putAllInt32ToStringField(source.getInt32ToStringField()) - .putAllInt32ToBytesField(source.getInt32ToBytesField()) - .putAllInt32ToEnumField(source.getInt32ToEnumField()) - .putAllInt32ToMessageField(source.getInt32ToMessageField()) - .putAllStringToInt32Field(source.getStringToInt32Field()); + .putAllInt32ToInt32Field(source.getInt32ToInt32FieldMap()) + .putAllInt32ToStringField(source.getInt32ToStringFieldMap()) + .putAllInt32ToBytesField(source.getInt32ToBytesFieldMap()) + .putAllInt32ToEnumField(source.getInt32ToEnumFieldMap()) + .putAllInt32ToMessageField(source.getInt32ToMessageFieldMap()) + .putAllStringToInt32Field(source.getStringToInt32FieldMap()); } private void assertMapValuesSet(TestMap message) { - assertEquals(3, message.getInt32ToInt32Field().size()); - assertEquals(11, message.getInt32ToInt32Field().get(1).intValue()); - assertEquals(22, message.getInt32ToInt32Field().get(2).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(3).intValue()); - - assertEquals(3, message.getInt32ToStringField().size()); - assertEquals("11", message.getInt32ToStringField().get(1)); - assertEquals("22", message.getInt32ToStringField().get(2)); - assertEquals("33", message.getInt32ToStringField().get(3)); - - assertEquals(3, message.getInt32ToBytesField().size()); - assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1)); - assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2)); - assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); - - assertEquals(3, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2)); - assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); - - assertEquals(3, message.getInt32ToMessageField().size()); - assertEquals(11, message.getInt32ToMessageField().get(1).getValue()); - assertEquals(22, message.getInt32ToMessageField().get(2).getValue()); - assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); - - assertEquals(3, message.getStringToInt32Field().size()); - assertEquals(11, message.getStringToInt32Field().get("1").intValue()); - assertEquals(22, message.getStringToInt32Field().get("2").intValue()); - assertEquals(33, message.getStringToInt32Field().get("3").intValue()); + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(11, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(22, message.getInt32ToInt32FieldMap().get(2).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); + + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("11", message.getInt32ToStringFieldMap().get(1)); + assertEquals("22", message.getInt32ToStringFieldMap().get(2)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); + + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesFieldMap().get(2)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); + + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(2)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); + + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(11, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(22, message.getInt32ToMessageFieldMap().get(2).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); + + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(11, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(22, message.getStringToInt32FieldMap().get("2").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); } private void updateMapValuesUsingMutableMap(TestMap.Builder builder) { @@ -201,23 +195,18 @@ private void updateMapValuesUsingAccessors(TestMap.Builder builder) { .putInt32ToInt32Field(1, 111) .removeInt32ToInt32Field(2) .putInt32ToInt32Field(4, 44) - .putInt32ToStringField(1, "111") .removeInt32ToStringField(2) .putInt32ToStringField(4, "44") - .putInt32ToBytesField(1, TestUtil.toBytes("111")) .removeInt32ToBytesField(2) .putInt32ToBytesField(4, TestUtil.toBytes("44")) - .putInt32ToEnumField(1, TestMap.EnumValue.BAR) .removeInt32ToEnumField(2) .putInt32ToEnumField(4, TestMap.EnumValue.QUX) - .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(111).build()) .removeInt32ToMessageField(2) .putInt32ToMessageField(4, MessageValue.newBuilder().setValue(44).build()) - .putStringToInt32Field("1", 111) .removeStringToInt32Field("2") .putStringToInt32Field("4", 44); @@ -250,49 +239,49 @@ public void testUpdateMapValues() { } private void assertMapValuesUpdated(TestMap message) { - assertEquals(3, message.getInt32ToInt32Field().size()); - assertEquals(111, message.getInt32ToInt32Field().get(1).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(3).intValue()); - assertEquals(44, message.getInt32ToInt32Field().get(4).intValue()); - - assertEquals(3, message.getInt32ToStringField().size()); - assertEquals("111", message.getInt32ToStringField().get(1)); - assertEquals("33", message.getInt32ToStringField().get(3)); - assertEquals("44", message.getInt32ToStringField().get(4)); - - assertEquals(3, message.getInt32ToBytesField().size()); - assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1)); - assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); - assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4)); - - assertEquals(3, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); - assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4)); - - assertEquals(3, message.getInt32ToMessageField().size()); - assertEquals(111, message.getInt32ToMessageField().get(1).getValue()); - assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); - assertEquals(44, message.getInt32ToMessageField().get(4).getValue()); - - assertEquals(3, message.getStringToInt32Field().size()); - assertEquals(111, message.getStringToInt32Field().get("1").intValue()); - assertEquals(33, message.getStringToInt32Field().get("3").intValue()); - assertEquals(44, message.getStringToInt32Field().get("4").intValue()); + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(111, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); + assertEquals(44, message.getInt32ToInt32FieldMap().get(4).intValue()); + + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("111", message.getInt32ToStringFieldMap().get(1)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); + assertEquals("44", message.getInt32ToStringFieldMap().get(4)); + + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); + assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesFieldMap().get(4)); + + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); + assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumFieldMap().get(4)); + + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(111, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); + assertEquals(44, message.getInt32ToMessageFieldMap().get(4).getValue()); + + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(111, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); + assertEquals(44, message.getStringToInt32FieldMap().get("4").intValue()); } private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) { - assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size()); + assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount()); - assertEquals(0, testMapOrBuilder.getInt32ToStringField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToStringFieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount()); - assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount()); - assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount()); - assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size()); + assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldMap().size()); assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount()); - assertEquals(0, testMapOrBuilder.getStringToInt32Field().size()); + assertEquals(0, testMapOrBuilder.getStringToInt32FieldMap().size()); assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount()); } @@ -307,13 +296,13 @@ public void testGetMapIsImmutable() { } private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) { - assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2); - assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2"); - assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2")); - assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO); + assertImmutable(testMapOrBuilder.getInt32ToInt32FieldMap(), 1, 2); + assertImmutable(testMapOrBuilder.getInt32ToStringFieldMap(), 1, "2"); + assertImmutable(testMapOrBuilder.getInt32ToBytesFieldMap(), 1, TestUtil.toBytes("2")); + assertImmutable(testMapOrBuilder.getInt32ToEnumFieldMap(), 1, TestMap.EnumValue.FOO); assertImmutable( - testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance()); - assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2); + testMapOrBuilder.getInt32ToMessageFieldMap(), 1, MessageValue.getDefaultInstance()); + assertImmutable(testMapOrBuilder.getStringToInt32FieldMap(), "1", 2); } private void assertImmutable(Map map, K key, V value) { @@ -435,7 +424,6 @@ public void testMutableMapLifecycle_collections() { assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); } - public void testGettersAndSetters() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); TestMap message = builder.build(); @@ -470,29 +458,33 @@ public void testPutAll() throws Exception { } public void testPutAllForUnknownEnumValues() throws Exception { - TestMap source = TestMap.newBuilder() - .putAllInt32ToEnumFieldValue(newMap( - 0, 0, - 1, 1, - 2, 1000)) // unknown value. - .build(); + TestMap source = + TestMap.newBuilder() + .putAllInt32ToEnumFieldValue( + newMap( + 0, 0, + 1, 1, + 2, 1000)) // unknown value. + .build(); - TestMap destination = TestMap.newBuilder() - .putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue()) - .build(); + TestMap destination = + TestMap.newBuilder() + .putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValueMap()) + .build(); - assertEquals(0, destination.getInt32ToEnumFieldValue().get(0).intValue()); - assertEquals(1, destination.getInt32ToEnumFieldValue().get(1).intValue()); - assertEquals(1000, destination.getInt32ToEnumFieldValue().get(2).intValue()); + assertEquals(0, destination.getInt32ToEnumFieldValueMap().get(0).intValue()); + assertEquals(1, destination.getInt32ToEnumFieldValueMap().get(1).intValue()); + assertEquals(1000, destination.getInt32ToEnumFieldValueMap().get(2).intValue()); assertEquals(3, destination.getInt32ToEnumFieldCount()); } public void testPutForUnknownEnumValues() throws Exception { - TestMap.Builder builder = TestMap.newBuilder() - .putInt32ToEnumFieldValue(0, 0) - .putInt32ToEnumFieldValue(1, 1) - .putInt32ToEnumFieldValue(2, 1000); // unknown value. - TestMap message = builder.build(); + TestMap message = + TestMap.newBuilder() + .putInt32ToEnumFieldValue(0, 0) + .putInt32ToEnumFieldValue(1, 1) + .putInt32ToEnumFieldValue(2, 1000) // unknown value. + .build(); assertEquals(0, message.getInt32ToEnumFieldValueOrThrow(0)); assertEquals(1, message.getInt32ToEnumFieldValueOrThrow(1)); assertEquals(1000, message.getInt32ToEnumFieldValueOrThrow(2)); @@ -573,40 +565,32 @@ public void testParseError() throws Exception { ByteString bytes = TestUtil.toBytes("SOME BYTES"); String stringKey = "a string key"; - TestMap map = tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToInt32Field(5, bytes) - .build()); + TestMap map = + tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToInt32Field(5, bytes).build()); assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1)); - map = tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToStringField(stringKey, 5) - .build()); + map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToStringField(stringKey, 5).build()); assertEquals("", map.getInt32ToStringFieldOrDefault(0, null)); - map = tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToBytesField(stringKey, 5) - .build()); + map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToBytesField(stringKey, 5).build()); assertEquals(map.getInt32ToBytesFieldOrDefault(0, null), ByteString.EMPTY); - map = tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToEnumField(stringKey, bytes) - .build()); + map = + tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToEnumField(stringKey, bytes).build()); assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null)); try { - tryParseTestMap(BizarroTestMap.newBuilder() - .putInt32ToMessageField(stringKey, bytes) - .build()); + tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToMessageField(stringKey, bytes).build()); fail(); } catch (InvalidProtocolBufferException expected) { assertTrue(expected.getUnfinishedMessage() instanceof TestMap); map = (TestMap) expected.getUnfinishedMessage(); - assertTrue(map.getInt32ToMessageField().isEmpty()); + assertTrue(map.getInt32ToMessageFieldMap().isEmpty()); } - map = tryParseTestMap(BizarroTestMap.newBuilder() - .putStringToInt32Field(stringKey, bytes) - .build()); + map = + tryParseTestMap( + BizarroTestMap.newBuilder().putStringToInt32Field(stringKey, bytes).build()); assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1)); } @@ -626,16 +610,18 @@ public void testEqualsAndHashCode() throws Exception { // We can't control the order of elements in a HashMap. The best we can do // here is to add elements in different order. - TestMap.Builder b1 = TestMap.newBuilder() - .putInt32ToInt32Field(1, 2) - .putInt32ToInt32Field(3, 4) - .putInt32ToInt32Field(5, 6); - TestMap m1 = b1.build(); - - TestMap.Builder b2 = TestMap.newBuilder() - .putInt32ToInt32Field(5, 6) - .putInt32ToInt32Field(1, 2) - .putInt32ToInt32Field(3, 4); + TestMap m1 = + TestMap.newBuilder() + .putInt32ToInt32Field(1, 2) + .putInt32ToInt32Field(3, 4) + .putInt32ToInt32Field(5, 6) + .build(); + + TestMap.Builder b2 = + TestMap.newBuilder() + .putInt32ToInt32Field(5, 6) + .putInt32ToInt32Field(1, 2) + .putInt32ToInt32Field(3, 4); TestMap m2 = b2.build(); assertEquals(m1, m2); @@ -657,63 +643,58 @@ public void testEqualsAndHashCode() throws Exception { } public void testNestedBuilderOnChangeEventPropagation() { - TestOnChangeEventPropagation.Builder parent = - TestOnChangeEventPropagation.newBuilder(); + TestOnChangeEventPropagation.Builder parent = TestOnChangeEventPropagation.newBuilder(); parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 2); TestOnChangeEventPropagation message = parent.build(); - assertEquals(2, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue()); + assertEquals(2, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue()); // Make a change using nested builder. parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 3); // Should be able to observe the change. message = parent.build(); - assertEquals(3, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue()); + assertEquals(3, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue()); // Make another change using mergeFrom() - TestMap.Builder other = TestMap.newBuilder().putInt32ToInt32Field(1, 4); - parent.getOptionalMessageBuilder().mergeFrom(other.build()); + TestMap other = TestMap.newBuilder().putInt32ToInt32Field(1, 4).build(); + parent.getOptionalMessageBuilder().mergeFrom(other); // Should be able to observe the change. message = parent.build(); - assertEquals(4, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue()); + assertEquals(4, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue()); // Make yet another change by clearing the nested builder. parent.getOptionalMessageBuilder().clear(); // Should be able to observe the change. message = parent.build(); - assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size()); + assertEquals(0, message.getOptionalMessage().getInt32ToInt32FieldMap().size()); } public void testNestedBuilderOnChangeEventPropagationReflection() { FieldDescriptor intMapField = f("int32_to_int32_field"); // Create an outer message builder with nested builder. - TestOnChangeEventPropagation.Builder parentBuilder = - TestOnChangeEventPropagation.newBuilder(); + TestOnChangeEventPropagation.Builder parentBuilder = TestOnChangeEventPropagation.newBuilder(); TestMap.Builder testMapBuilder = parentBuilder.getOptionalMessageBuilder(); // Create a map entry message. TestMap.Builder entryBuilder = TestMap.newBuilder().putInt32ToInt32Field(1, 1); // Put the entry into the nested builder. - testMapBuilder.addRepeatedField( - intMapField, entryBuilder.getRepeatedField(intMapField, 0)); + testMapBuilder.addRepeatedField(intMapField, entryBuilder.getRepeatedField(intMapField, 0)); // Should be able to observe the change. TestOnChangeEventPropagation message = parentBuilder.build(); - assertEquals(1, message.getOptionalMessage().getInt32ToInt32Field().size()); + assertEquals(1, message.getOptionalMessage().getInt32ToInt32FieldMap().size()); // Change the entry value. entryBuilder.putInt32ToInt32Field(1, 4); testMapBuilder = parentBuilder.getOptionalMessageBuilder(); - testMapBuilder.setRepeatedField( - intMapField, 0, entryBuilder.getRepeatedField(intMapField, 0)); + testMapBuilder.setRepeatedField(intMapField, 0, entryBuilder.getRepeatedField(intMapField, 0)); // Should be able to observe the change. message = parentBuilder.build(); - assertEquals(4, - message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue()); + assertEquals(4, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue()); // Clear the nested builder. testMapBuilder = parentBuilder.getOptionalMessageBuilder(); @@ -721,7 +702,7 @@ public void testNestedBuilderOnChangeEventPropagationReflection() { // Should be able to observe the change. message = parentBuilder.build(); - assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size()); + assertEquals(0, message.getOptionalMessage().getInt32ToInt32FieldMap().size()); } // The following methods are used to test reflection API. @@ -761,8 +742,7 @@ private static void assertHasMapValues(Message message, String name, Map v } } - private static - Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) { + private static Message newMapEntry(Message.Builder builder, String name, K key, V value) { FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name); Message.Builder entryBuilder = builder.newBuilderForField(field); FieldDescriptor keyField = entryBuilder.getDescriptorForType().findFieldByName("key"); @@ -773,7 +753,7 @@ Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType } private static void setMapValues(Message.Builder builder, String name, Map values) { - List entryList = new ArrayList(); + List entryList = new ArrayList<>(); for (Map.Entry entry : values.entrySet()) { entryList.add(newMapEntry(builder, name, entry.getKey(), entry.getValue())); } @@ -781,10 +761,8 @@ private static void setMapValues(Message.Builder builder, String name, Map builder.setField(field, entryList); } - private static - Map mapForValues( - KeyType key1, ValueType value1, KeyType key2, ValueType value2) { - Map map = new HashMap(); + private static Map mapForValues(K key1, V value1, K key2, V value2) { + Map map = new HashMap<>(); map.put(key1, value1); map.put(key2, value2); return map; @@ -792,17 +770,19 @@ Map mapForValues( public void testReflectionApi() throws Exception { // In reflection API, map fields are just repeated message fields. - TestMap.Builder builder = TestMap.newBuilder() - .putInt32ToInt32Field(1, 2) - .putInt32ToInt32Field(3, 4) - .putInt32ToMessageField(11, MessageValue.newBuilder().setValue(22).build()) - .putInt32ToMessageField(33, MessageValue.newBuilder().setValue(44).build()); + TestMap.Builder builder = + TestMap.newBuilder() + .putInt32ToInt32Field(1, 2) + .putInt32ToInt32Field(3, 4) + .putInt32ToMessageField(11, MessageValue.newBuilder().setValue(22).build()) + .putInt32ToMessageField(33, MessageValue.newBuilder().setValue(44).build()); TestMap message = builder.build(); // Test getField(), getRepeatedFieldCount(), getRepeatedField(). - assertHasMapValues(message, "int32_to_int32_field", - mapForValues(1, 2, 3, 4)); - assertHasMapValues(message, "int32_to_message_field", + assertHasMapValues(message, "int32_to_int32_field", mapForValues(1, 2, 3, 4)); + assertHasMapValues( + message, + "int32_to_message_field", mapForValues( 11, MessageValue.newBuilder().setValue(22).build(), 33, MessageValue.newBuilder().setValue(44).build())); @@ -811,41 +791,50 @@ public void testReflectionApi() throws Exception { builder.clearField(f("int32_to_int32_field")); builder.clearField(f("int32_to_message_field")); message = builder.build(); - assertEquals(0, message.getInt32ToInt32Field().size()); - assertEquals(0, message.getInt32ToMessageField().size()); + assertEquals(0, message.getInt32ToInt32FieldMap().size()); + assertEquals(0, message.getInt32ToMessageFieldMap().size()); // Test setField() - setMapValues(builder, "int32_to_int32_field", - mapForValues(11, 22, 33, 44)); - setMapValues(builder, "int32_to_message_field", + setMapValues(builder, "int32_to_int32_field", mapForValues(11, 22, 33, 44)); + setMapValues( + builder, + "int32_to_message_field", mapForValues( 111, MessageValue.newBuilder().setValue(222).build(), 333, MessageValue.newBuilder().setValue(444).build())); message = builder.build(); - assertEquals(22, message.getInt32ToInt32Field().get(11).intValue()); - assertEquals(44, message.getInt32ToInt32Field().get(33).intValue()); - assertEquals(222, message.getInt32ToMessageField().get(111).getValue()); - assertEquals(444, message.getInt32ToMessageField().get(333).getValue()); + assertEquals(22, message.getInt32ToInt32FieldMap().get(11).intValue()); + assertEquals(44, message.getInt32ToInt32FieldMap().get(33).intValue()); + assertEquals(222, message.getInt32ToMessageFieldMap().get(111).getValue()); + assertEquals(444, message.getInt32ToMessageFieldMap().get(333).getValue()); // Test addRepeatedField - builder.addRepeatedField(f("int32_to_int32_field"), - newMapEntry(builder, "int32_to_int32_field", 55, 66)); - builder.addRepeatedField(f("int32_to_message_field"), - newMapEntry(builder, "int32_to_message_field", 555, + builder.addRepeatedField( + f("int32_to_int32_field"), newMapEntry(builder, "int32_to_int32_field", 55, 66)); + builder.addRepeatedField( + f("int32_to_message_field"), + newMapEntry( + builder, + "int32_to_message_field", + 555, MessageValue.newBuilder().setValue(666).build())); message = builder.build(); - assertEquals(66, message.getInt32ToInt32Field().get(55).intValue()); - assertEquals(666, message.getInt32ToMessageField().get(555).getValue()); + assertEquals(66, message.getInt32ToInt32FieldMap().get(55).intValue()); + assertEquals(666, message.getInt32ToMessageFieldMap().get(555).getValue()); // Test addRepeatedField (overriding existing values) - builder.addRepeatedField(f("int32_to_int32_field"), - newMapEntry(builder, "int32_to_int32_field", 55, 55)); - builder.addRepeatedField(f("int32_to_message_field"), - newMapEntry(builder, "int32_to_message_field", 555, + builder.addRepeatedField( + f("int32_to_int32_field"), newMapEntry(builder, "int32_to_int32_field", 55, 55)); + builder.addRepeatedField( + f("int32_to_message_field"), + newMapEntry( + builder, + "int32_to_message_field", + 555, MessageValue.newBuilder().setValue(555).build())); message = builder.build(); - assertEquals(55, message.getInt32ToInt32Field().get(55).intValue()); - assertEquals(555, message.getInt32ToMessageField().get(555).getValue()); + assertEquals(55, message.getInt32ToInt32FieldMap().get(55).intValue()); + assertEquals(555, message.getInt32ToMessageFieldMap().get(555).getValue()); // Test setRepeatedField for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) { @@ -859,9 +848,9 @@ public void testReflectionApi() throws Exception { builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build()); } message = builder.build(); - assertEquals(11, message.getInt32ToInt32Field().get(22).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(44).intValue()); - assertEquals(55, message.getInt32ToInt32Field().get(55).intValue()); + assertEquals(11, message.getInt32ToInt32FieldMap().get(22).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(44).intValue()); + assertEquals(55, message.getInt32ToInt32FieldMap().get(55).intValue()); } // See additional coverage in TextFormatTest.java. @@ -870,7 +859,7 @@ public void testTextFormat() throws Exception { setMapValuesUsingAccessors(builder); TestMap message = builder.build(); - String textData = TextFormat.printToString(message); + String textData = TextFormat.printer().printToString(message); builder = TestMap.newBuilder(); TextFormat.merge(textData, builder); @@ -884,22 +873,37 @@ public void testDynamicMessage() throws Exception { setMapValuesUsingAccessors(builder); TestMap message = builder.build(); - Message dynamicDefaultInstance = - DynamicMessage.getDefaultInstance(TestMap.getDescriptor()); - Message dynamicMessage = dynamicDefaultInstance - .newBuilderForType().mergeFrom(message.toByteString()).build(); + Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor()); + Message dynamicMessage = + dynamicDefaultInstance.newBuilderForType().mergeFrom(message.toByteString()).build(); assertEquals(message, dynamicMessage); assertEquals(message.hashCode(), dynamicMessage.hashCode()); } + // Check that DynamicMessage handles map field serialization the same way as generated code + // regarding unset key and value field in a map entry. + public void testDynamicMessageUnsetKeyAndValue() throws Exception { + FieldDescriptor field = f("int32_to_int32_field"); + + Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor()); + Message.Builder builder = dynamicDefaultInstance.newBuilderForType(); + // Add an entry without key and value. + builder.addRepeatedField(field, builder.newBuilderForField(field).build()); + Message message = builder.build(); + ByteString bytes = message.toByteString(); + // Parse it back to the same generated type. + Message generatedMessage = TestMap.parseFrom(bytes); + // Assert the serialized bytes are equivalent. + assertEquals(generatedMessage.toByteString(), bytes); + } + public void testReflectionEqualsAndHashCode() throws Exception { // Test that generated equals() and hashCode() will disregard the order // of map entries when comparing/hashing map fields. // We use DynamicMessage to test reflection based equals()/hashCode(). - Message dynamicDefaultInstance = - DynamicMessage.getDefaultInstance(TestMap.getDescriptor()); + Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor()); FieldDescriptor field = f("int32_to_int32_field"); Message.Builder b1 = dynamicDefaultInstance.newBuilderForType(); @@ -926,31 +930,30 @@ public void testReflectionEqualsAndHashCode() throws Exception { } public void testUnknownEnumValues() throws Exception { - TestMap.Builder builder = TestMap.newBuilder() - .putAllInt32ToEnumFieldValue(newMap( - 0, 0, - 1, 1, - 2, 1000)); // unknown value. + TestMap.Builder builder = + TestMap.newBuilder() + .putAllInt32ToEnumFieldValue( + newMap( + 0, 0, + 1, 1, + 2, 1000)); // unknown value. TestMap message = builder.build(); - assertEquals(TestMap.EnumValue.FOO, - message.getInt32ToEnumField().get(0)); - assertEquals(TestMap.EnumValue.BAR, - message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.UNRECOGNIZED, - message.getInt32ToEnumField().get(2)); - assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue()); + assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(0)); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumFieldMap().get(2)); + assertEquals(1000, message.getInt32ToEnumFieldValueMap().get(2).intValue()); // Unknown enum values should be preserved after: // 1. Serialization and parsing. // 2. toBuild(). // 3. mergeFrom(). message = TestMap.parseFrom(message.toByteString()); - assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue()); + assertEquals(1000, message.getInt32ToEnumFieldValueMap().get(2).intValue()); builder = message.toBuilder(); - assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue()); + assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue()); builder = TestMap.newBuilder().mergeFrom(message); - assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue()); + assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue()); // hashCode()/equals() should take unknown enum values into account. builder.putAllInt32ToEnumFieldValue(newMap(2, 1001)); @@ -959,7 +962,7 @@ public void testUnknownEnumValues() throws Exception { assertFalse(message.equals(message2)); // Unknown values will be converted to UNRECOGNIZED so the resulted enum map // should be the same. - assertTrue(message.getInt32ToEnumField().equals(message2.getInt32ToEnumField())); + assertEquals(message2.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap()); } public void testUnknownEnumValuesInReflectionApi() throws Exception { @@ -967,13 +970,13 @@ public void testUnknownEnumValuesInReflectionApi() throws Exception { EnumDescriptor enumDescriptor = TestMap.EnumValue.getDescriptor(); FieldDescriptor field = descriptor.findFieldByName("int32_to_enum_field"); - Map data = newMap( - 0, 0, - 1, 1, - 2, 1000); // unknown value + Map data = + newMap( + 0, 0, + 1, 1, + 2, 1000); // unknown value - TestMap.Builder builder = TestMap.newBuilder() - .putAllInt32ToEnumFieldValue(data); + TestMap.Builder builder = TestMap.newBuilder().putAllInt32ToEnumFieldValue(data); // Try to read unknown enum values using reflection API. for (int i = 0; i < builder.getRepeatedFieldCount(field); i++) { @@ -983,14 +986,14 @@ public void testUnknownEnumValuesInReflectionApi() throws Exception { assertEquals(data.get(key).intValue(), value); Message.Builder mapEntryBuilder = mapEntry.toBuilder(); // Increase the value by 1. - setFieldValue(mapEntryBuilder, "value", - enumDescriptor.findValueByNumberCreatingIfUnknown(value + 1)); + setFieldValue( + mapEntryBuilder, "value", enumDescriptor.findValueByNumberCreatingIfUnknown(value + 1)); builder.setRepeatedField(field, i, mapEntryBuilder.build()); } // Verify that enum values have been successfully updated. TestMap message = builder.build(); - for (Map.Entry entry : message.getInt32ToEnumFieldValue().entrySet()) { + for (Map.Entry entry : message.getInt32ToEnumFieldValueMap().entrySet()) { assertEquals(data.get(entry.getKey()) + 1, entry.getValue().intValue()); } } @@ -1000,29 +1003,19 @@ public void testIterationOrder() throws Exception { setMapValuesUsingAccessors(builder); TestMap message = builder.build(); - assertEquals(Arrays.asList("1", "2", "3"), - new ArrayList(message.getStringToInt32Field().keySet())); + assertEquals( + Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32FieldMap().keySet())); } public void testGetMap() { TestMap.Builder builder = TestMap.newBuilder(); setMapValuesUsingAccessors(builder); TestMap message = builder.build(); - assertEquals( - message.getStringToInt32Field(), - message.getStringToInt32FieldMap()); - assertEquals( - message.getInt32ToBytesField(), - message.getInt32ToBytesFieldMap()); - assertEquals( - message.getInt32ToEnumField(), - message.getInt32ToEnumFieldMap()); - assertEquals( - message.getInt32ToEnumFieldValue(), - message.getInt32ToEnumFieldValueMap()); - assertEquals( - message.getInt32ToMessageField(), - message.getInt32ToMessageFieldMap()); + assertEquals(message.getStringToInt32FieldMap(), message.getStringToInt32FieldMap()); + assertEquals(message.getInt32ToBytesFieldMap(), message.getInt32ToBytesFieldMap()); + assertEquals(message.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap()); + assertEquals(message.getInt32ToEnumFieldValueMap(), message.getInt32ToEnumFieldValueMap()); + assertEquals(message.getInt32ToMessageFieldMap(), message.getInt32ToMessageFieldMap()); } public void testContains() { @@ -1115,10 +1108,11 @@ public void doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder) { assertEquals( TestMap.EnumValue.BAR.getNumber(), - (int) testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(2, -1)); + testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(2, -1)); assertEquals(-1, testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(-1000, -1)); - assertEquals(MessageValue.newBuilder().setValue(11).build(), + assertEquals( + MessageValue.newBuilder().setValue(11).build(), testMapOrBuilder.getInt32ToMessageFieldOrDefault(1, null)); assertNull(testMapOrBuilder.getInt32ToMessageFieldOrDefault(-1, null)); @@ -1185,7 +1179,8 @@ public void doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder) { // expected } - assertEquals(MessageValue.newBuilder().setValue(11).build(), + assertEquals( + MessageValue.newBuilder().setValue(11).build(), testMapOrBuilder.getInt32ToMessageFieldOrThrow(1)); try { testMapOrBuilder.getInt32ToMessageFieldOrThrow(-1); @@ -1243,8 +1238,7 @@ public void testPut() { } builder.putInt32ToEnumFieldValue(1, TestMap.EnumValue.BAR.getNumber()); - assertEquals( - TestMap.EnumValue.BAR.getNumber(), builder.getInt32ToEnumFieldValueOrThrow(1)); + assertEquals(TestMap.EnumValue.BAR.getNumber(), builder.getInt32ToEnumFieldValueOrThrow(1)); builder.putInt32ToEnumFieldValue(1, -1); assertEquals(-1, builder.getInt32ToEnumFieldValueOrThrow(1)); assertEquals(TestMap.EnumValue.UNRECOGNIZED, builder.getInt32ToEnumFieldOrThrow(1)); @@ -1343,10 +1337,10 @@ public void testDeterministicSerialziation() throws Exception { output.flush(); CodedInputStream input = CodedInputStream.newInstance(serialized); - List int32Keys = new ArrayList(); - List uint32Keys = new ArrayList(); - List int64Keys = new ArrayList(); - List stringKeys = new ArrayList(); + List int32Keys = new ArrayList<>(); + List uint32Keys = new ArrayList<>(); + List int64Keys = new ArrayList<>(); + List stringKeys = new ArrayList<>(); int tag; while (true) { tag = input.readTag(); @@ -1373,18 +1367,10 @@ public void testDeterministicSerialziation() throws Exception { } input.popLimit(oldLimit); } - assertEquals( - Arrays.asList(-2, 0, 1, 4, 5), - int32Keys); - assertEquals( - Arrays.asList(-2, 0, 1, 4, 5), - uint32Keys); - assertEquals( - Arrays.asList(-2L, 0L, 1L, 4L, 5L), - int64Keys); - assertEquals( - Arrays.asList("", "bar", "baz", "foo", "hello", "world"), - stringKeys); + assertEquals(Arrays.asList(-2, 0, 1, 4, 5), int32Keys); + assertEquals(Arrays.asList(-2, 0, 1, 4, 5), uint32Keys); + assertEquals(Arrays.asList(-2L, 0L, 1L, 4L, 5L), int64Keys); + assertEquals(Arrays.asList("", "bar", "baz", "foo", "hello", "world"), stringKeys); } public void testInitFromPartialDynamicMessage() { @@ -1465,20 +1451,20 @@ private String readMapStringKey(CodedInputStream input) throws IOException { } private static Map newMap(K key1, V value1) { - Map map = new HashMap(); + Map map = new HashMap<>(); map.put(key1, value1); return map; } private static Map newMap(K key1, V value1, K key2, V value2) { - Map map = new HashMap(); + Map map = new HashMap<>(); map.put(key1, value1); map.put(key2, value2); return map; } private static Map newMap(K key1, V value1, K key2, V value2, K key3, V value3) { - Map map = new HashMap(); + Map map = new HashMap<>(); map.put(key1, value1); map.put(key2, value2); map.put(key3, value3); @@ -1507,8 +1493,7 @@ public void testMap_withNulls() { } try { - builder.putAllInt32ToMessageField( - MapTest.newMap(4, null, 5, null)); + builder.putAllInt32ToMessageField(MapTest.newMap(4, null, 5, null)); fail(); } catch (NullPointerException expected) { } diff --git a/java/core/src/test/java/com/google/protobuf/MessageTest.java b/java/core/src/test/java/com/google/protobuf/MessageTest.java index 9d55d0ddcedc0..760511b635f2f 100644 --- a/java/core/src/test/java/com/google/protobuf/MessageTest.java +++ b/java/core/src/test/java/com/google/protobuf/MessageTest.java @@ -39,8 +39,7 @@ import junit.framework.TestCase; /** - * Misc. unit tests for message operations that apply to both generated - * and dynamic messages. + * Misc. unit tests for message operations that apply to both generated and dynamic messages. * * @author kenton@google.com Kenton Varda */ @@ -49,49 +48,55 @@ public class MessageTest extends TestCase { // Message-merging tests. static final TestAllTypes MERGE_SOURCE = - TestAllTypes.newBuilder() - .setOptionalInt32(1) - .setOptionalString("foo") - .setOptionalForeignMessage(ForeignMessage.getDefaultInstance()) - .addRepeatedString("bar") - .build(); + TestAllTypes.newBuilder() + .setOptionalInt32(1) + .setOptionalString("foo") + .setOptionalForeignMessage(ForeignMessage.getDefaultInstance()) + .addRepeatedString("bar") + .build(); static final TestAllTypes MERGE_DEST = - TestAllTypes.newBuilder() - .setOptionalInt64(2) - .setOptionalString("baz") - .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build()) - .addRepeatedString("qux") - .build(); + TestAllTypes.newBuilder() + .setOptionalInt64(2) + .setOptionalString("baz") + .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build()) + .addRepeatedString("qux") + .build(); static final String MERGE_RESULT_TEXT = - "optional_int32: 1\n" + - "optional_int64: 2\n" + - "optional_string: \"foo\"\n" + - "optional_foreign_message {\n" + - " c: 3\n" + - "}\n" + - "repeated_string: \"qux\"\n" + - "repeated_string: \"bar\"\n"; + "" + + "optional_int32: 1\n" + + "optional_int64: 2\n" + + "optional_string: \"foo\"\n" + + "optional_foreign_message {\n" + + " c: 3\n" + + "}\n" + + "repeated_string: \"qux\"\n" + + "repeated_string: \"bar\"\n"; + + public void testParsingWithNullExtensionRegistry() throws Exception { + try { + TestAllTypes.parseFrom(new byte[] {}, null); + fail(); + } catch (NullPointerException expected) { + } + } public void testMergeFrom() throws Exception { - TestAllTypes result = - TestAllTypes.newBuilder(MERGE_DEST) - .mergeFrom(MERGE_SOURCE).build(); + TestAllTypes result = TestAllTypes.newBuilder(MERGE_DEST).mergeFrom(MERGE_SOURCE).build(); assertEquals(MERGE_RESULT_TEXT, result.toString()); } /** - * Test merging a DynamicMessage into a GeneratedMessage. As long as they - * have the same descriptor, this should work, but it is an entirely different - * code path. + * Test merging a DynamicMessage into a GeneratedMessage. As long as they have the same + * descriptor, this should work, but it is an entirely different code path. */ public void testMergeFromDynamic() throws Exception { TestAllTypes result = - TestAllTypes.newBuilder(MERGE_DEST) - .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build()) - .build(); + TestAllTypes.newBuilder(MERGE_DEST) + .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build()) + .build(); assertEquals(MERGE_RESULT_TEXT, result.toString()); } @@ -99,9 +104,9 @@ public void testMergeFromDynamic() throws Exception { /** Test merging two DynamicMessages. */ public void testDynamicMergeFrom() throws Exception { DynamicMessage result = - DynamicMessage.newBuilder(MERGE_DEST) - .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build()) - .build(); + DynamicMessage.newBuilder(MERGE_DEST) + .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build()) + .build(); assertEquals(MERGE_RESULT_TEXT, result.toString()); } @@ -109,10 +114,9 @@ public void testDynamicMergeFrom() throws Exception { // ================================================================= // Required-field-related tests. - private static final TestRequired TEST_REQUIRED_UNINITIALIZED = - TestRequired.getDefaultInstance(); + private static final TestRequired TEST_REQUIRED_UNINITIALIZED = TestRequired.getDefaultInstance(); private static final TestRequired TEST_REQUIRED_INITIALIZED = - TestRequired.newBuilder().setA(1).setB(2).setC(3).build(); + TestRequired.newBuilder().setA(1).setB(2).setC(3).build(); public void testRequired() throws Exception { TestRequired.Builder builder = TestRequired.newBuilder(); @@ -181,20 +185,18 @@ public void testRequiredDynamicForeign() throws Exception { assertTrue(builder.isInitialized()); - builder.setField(descriptor.findFieldByName("optional_message"), - TEST_REQUIRED_UNINITIALIZED); + builder.setField(descriptor.findFieldByName("optional_message"), TEST_REQUIRED_UNINITIALIZED); assertFalse(builder.isInitialized()); - builder.setField(descriptor.findFieldByName("optional_message"), - TEST_REQUIRED_INITIALIZED); + builder.setField(descriptor.findFieldByName("optional_message"), TEST_REQUIRED_INITIALIZED); assertTrue(builder.isInitialized()); - builder.addRepeatedField(descriptor.findFieldByName("repeated_message"), - TEST_REQUIRED_UNINITIALIZED); + builder.addRepeatedField( + descriptor.findFieldByName("repeated_message"), TEST_REQUIRED_UNINITIALIZED); assertFalse(builder.isInitialized()); - builder.setRepeatedField(descriptor.findFieldByName("repeated_message"), 0, - TEST_REQUIRED_INITIALIZED); + builder.setRepeatedField( + descriptor.findFieldByName("repeated_message"), 0, TEST_REQUIRED_INITIALIZED); assertTrue(builder.isInitialized()); } @@ -216,35 +218,35 @@ public void testBuildPartial() throws Exception { public void testNestedUninitializedException() throws Exception { try { TestRequiredForeign.newBuilder() - .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED) - .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) - .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) - .build(); + .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED) + .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) + .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) + .build(); fail("Should have thrown an exception."); } catch (UninitializedMessageException e) { assertEquals( - "Message missing required fields: " + - "optional_message.a, " + - "optional_message.b, " + - "optional_message.c, " + - "repeated_message[0].a, " + - "repeated_message[0].b, " + - "repeated_message[0].c, " + - "repeated_message[1].a, " + - "repeated_message[1].b, " + - "repeated_message[1].c", - e.getMessage()); + "Message missing required fields: " + + "optional_message.a, " + + "optional_message.b, " + + "optional_message.c, " + + "repeated_message[0].a, " + + "repeated_message[0].b, " + + "repeated_message[0].c, " + + "repeated_message[1].a, " + + "repeated_message[1].b, " + + "repeated_message[1].c", + e.getMessage()); } } public void testBuildNestedPartial() throws Exception { // We're mostly testing that no exception is thrown. TestRequiredForeign message = - TestRequiredForeign.newBuilder() - .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED) - .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) - .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) - .buildPartial(); + TestRequiredForeign.newBuilder() + .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED) + .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) + .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) + .buildPartial(); assertFalse(message.isInitialized()); } @@ -259,28 +261,29 @@ public void testParseUnititialized() throws Exception { public void testParseNestedUnititialized() throws Exception { ByteString data = - TestRequiredForeign.newBuilder() - .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED) - .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) - .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) - .buildPartial().toByteString(); + TestRequiredForeign.newBuilder() + .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED) + .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) + .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) + .buildPartial() + .toByteString(); try { TestRequiredForeign.parseFrom(data); fail("Should have thrown an exception."); } catch (InvalidProtocolBufferException e) { assertEquals( - "Message missing required fields: " + - "optional_message.a, " + - "optional_message.b, " + - "optional_message.c, " + - "repeated_message[0].a, " + - "repeated_message[0].b, " + - "repeated_message[0].c, " + - "repeated_message[1].a, " + - "repeated_message[1].b, " + - "repeated_message[1].c", - e.getMessage()); + "Message missing required fields: " + + "optional_message.a, " + + "optional_message.b, " + + "optional_message.c, " + + "repeated_message[0].a, " + + "repeated_message[0].b, " + + "repeated_message[0].c, " + + "repeated_message[1].a, " + + "repeated_message[1].b, " + + "repeated_message[1].c", + e.getMessage()); } } @@ -295,9 +298,7 @@ public void testDynamicUninitializedException() throws Exception { public void testDynamicBuildPartial() throws Exception { // We're mostly testing that no exception is thrown. - DynamicMessage message = - DynamicMessage.newBuilder(TestRequired.getDescriptor()) - .buildPartial(); + DynamicMessage message = DynamicMessage.newBuilder(TestRequired.getDescriptor()).buildPartial(); assertFalse(message.isInitialized()); } @@ -310,43 +311,44 @@ public void testDynamicParseUnititialized() throws Exception { assertEquals("Message missing required fields: a, b, c", e.getMessage()); } } - + /** Test reading unset repeated message from DynamicMessage. */ public void testDynamicRepeatedMessageNull() throws Exception { - Descriptors.Descriptor descriptor = TestRequired.getDescriptor(); + TestRequired.getDescriptor(); DynamicMessage result = - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()) - .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build()) - .build(); + DynamicMessage.newBuilder(TestAllTypes.getDescriptor()) + .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build()) + .build(); - assertTrue(result.getField(result.getDescriptorForType() - .findFieldByName("repeated_foreign_message")) instanceof List); + assertTrue( + result.getField(result.getDescriptorForType().findFieldByName("repeated_foreign_message")) + instanceof List); assertEquals( 0, result.getRepeatedFieldCount( result.getDescriptorForType().findFieldByName("repeated_foreign_message"))); } - + /** Test reading repeated message from DynamicMessage. */ public void testDynamicRepeatedMessageNotNull() throws Exception { - - TestAllTypes REPEATED_NESTED = - TestAllTypes.newBuilder() - .setOptionalInt32(1) - .setOptionalString("foo") - .setOptionalForeignMessage(ForeignMessage.getDefaultInstance()) - .addRepeatedString("bar") - .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance()) - .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance()) - .build(); - Descriptors.Descriptor descriptor = TestRequired.getDescriptor(); + TestAllTypes repeatedNested = + TestAllTypes.newBuilder() + .setOptionalInt32(1) + .setOptionalString("foo") + .setOptionalForeignMessage(ForeignMessage.getDefaultInstance()) + .addRepeatedString("bar") + .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance()) + .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance()) + .build(); + TestRequired.getDescriptor(); DynamicMessage result = - DynamicMessage.newBuilder(TestAllTypes.getDescriptor()) - .mergeFrom(DynamicMessage.newBuilder(REPEATED_NESTED).build()) - .build(); + DynamicMessage.newBuilder(TestAllTypes.getDescriptor()) + .mergeFrom(DynamicMessage.newBuilder(repeatedNested).build()) + .build(); - assertTrue(result.getField(result.getDescriptorForType() - .findFieldByName("repeated_foreign_message")) instanceof List); + assertTrue( + result.getField(result.getDescriptorForType().findFieldByName("repeated_foreign_message")) + instanceof List); assertEquals( 2, result.getRepeatedFieldCount( diff --git a/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java b/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java index 03ed65a550187..1af3f93c86b8e 100644 --- a/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java +++ b/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java @@ -30,6 +30,7 @@ package com.google.protobuf; +import protobuf_unittest.Engine; import protobuf_unittest.Vehicle; import protobuf_unittest.Wheel; import java.util.ArrayList; @@ -37,8 +38,8 @@ import junit.framework.TestCase; /** - * Test cases that exercise end-to-end use cases involving - * {@link SingleFieldBuilder} and {@link RepeatedFieldBuilder}. + * Test cases that exercise end-to-end use cases involving {@link SingleFieldBuilder} and {@link + * RepeatedFieldBuilder}. * * @author jonp@google.com (Jon Perlow) */ @@ -46,20 +47,11 @@ public class NestedBuildersTest extends TestCase { public void testMessagesAndBuilders() { Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); - vehicleBuilder.addWheelBuilder() - .setRadius(4) - .setWidth(1); - vehicleBuilder.addWheelBuilder() - .setRadius(4) - .setWidth(2); - vehicleBuilder.addWheelBuilder() - .setRadius(4) - .setWidth(3); - vehicleBuilder.addWheelBuilder() - .setRadius(4) - .setWidth(4); - vehicleBuilder.getEngineBuilder() - .setLiters(10); + vehicleBuilder.addWheelBuilder().setRadius(4).setWidth(1); + vehicleBuilder.addWheelBuilder().setRadius(4).setWidth(2); + vehicleBuilder.addWheelBuilder().setRadius(4).setWidth(3); + vehicleBuilder.addWheelBuilder().setRadius(4).setWidth(4); + vehicleBuilder.getEngineBuilder().setLiters(10); Vehicle vehicle = vehicleBuilder.build(); assertEquals(4, vehicle.getWheelCount()); @@ -71,11 +63,9 @@ public void testMessagesAndBuilders() { assertEquals(10, vehicle.getEngine().getLiters()); for (int i = 0; i < 4; i++) { - vehicleBuilder.getWheelBuilder(i) - .setRadius(5) - .setWidth(i + 10); + vehicleBuilder.getWheelBuilder(i).setRadius(5).setWidth(i + 10); } - vehicleBuilder.getEngineBuilder().setLiters(20); + Engine.Builder engineBuilder = vehicleBuilder.getEngineBuilder().setLiters(20); vehicle = vehicleBuilder.build(); for (int i = 0; i < 4; i++) { @@ -85,22 +75,17 @@ public void testMessagesAndBuilders() { } assertEquals(20, vehicle.getEngine().getLiters()); assertTrue(vehicle.hasEngine()); + + engineBuilder.setLiters(50); + assertEquals(50, vehicleBuilder.getEngine().getLiters()); } public void testMessagesAreCached() { Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); - vehicleBuilder.addWheelBuilder() - .setRadius(1) - .setWidth(2); - vehicleBuilder.addWheelBuilder() - .setRadius(3) - .setWidth(4); - vehicleBuilder.addWheelBuilder() - .setRadius(5) - .setWidth(6); - vehicleBuilder.addWheelBuilder() - .setRadius(7) - .setWidth(8); + vehicleBuilder.addWheelBuilder().setRadius(1).setWidth(2); + vehicleBuilder.addWheelBuilder().setRadius(3).setWidth(4); + vehicleBuilder.addWheelBuilder().setRadius(5).setWidth(6); + vehicleBuilder.addWheelBuilder().setRadius(7).setWidth(8); // Make sure messages are cached. List wheels = new ArrayList(vehicleBuilder.getWheelList()); @@ -117,8 +102,7 @@ public void testMessagesAreCached() { } // Change just one - vehicleBuilder.getWheelBuilder(3) - .setRadius(20).setWidth(20); + vehicleBuilder.getWheelBuilder(3).setRadius(20).setWidth(20); // Now get wheels and check that only that one changed for (int i = 0; i < wheels.size(); i++) { @@ -132,12 +116,8 @@ public void testMessagesAreCached() { public void testRemove_WithNestedBuilders() { Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); - vehicleBuilder.addWheelBuilder() - .setRadius(1) - .setWidth(1); - vehicleBuilder.addWheelBuilder() - .setRadius(2) - .setWidth(2); + vehicleBuilder.addWheelBuilder().setRadius(1).setWidth(1); + vehicleBuilder.addWheelBuilder().setRadius(2).setWidth(2); vehicleBuilder.removeWheel(0); assertEquals(1, vehicleBuilder.getWheelCount()); @@ -146,12 +126,8 @@ public void testRemove_WithNestedBuilders() { public void testRemove_WithNestedMessages() { Vehicle.Builder vehicleBuilder = Vehicle.newBuilder(); - vehicleBuilder.addWheel(Wheel.newBuilder() - .setRadius(1) - .setWidth(1)); - vehicleBuilder.addWheel(Wheel.newBuilder() - .setRadius(2) - .setWidth(2)); + vehicleBuilder.addWheel(Wheel.newBuilder().setRadius(1).setWidth(1)); + vehicleBuilder.addWheel(Wheel.newBuilder().setRadius(2).setWidth(2)); vehicleBuilder.removeWheel(0); assertEquals(1, vehicleBuilder.getWheelCount()); @@ -159,14 +135,13 @@ public void testRemove_WithNestedMessages() { } public void testMerge() { - Vehicle vehicle1 = Vehicle.newBuilder() - .addWheel(Wheel.newBuilder().setRadius(1).build()) - .addWheel(Wheel.newBuilder().setRadius(2).build()) - .build(); - - Vehicle vehicle2 = Vehicle.newBuilder() - .mergeFrom(vehicle1) - .build(); + Vehicle vehicle1 = + Vehicle.newBuilder() + .addWheel(Wheel.newBuilder().setRadius(1).build()) + .addWheel(Wheel.newBuilder().setRadius(2).build()) + .build(); + + Vehicle vehicle2 = Vehicle.newBuilder().mergeFrom(vehicle1).build(); // List should be the same -- no allocation assertSame(vehicle1.getWheelList(), vehicle2.getWheelList()); diff --git a/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java b/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java index c388bd0561f78..489bb7c10283c 100644 --- a/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java +++ b/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java @@ -48,9 +48,7 @@ import java.util.NoSuchElementException; import junit.framework.TestCase; -/** - * Tests for {@link NioByteString}. - */ +/** Tests for {@link NioByteString}. */ public class NioByteStringTest extends TestCase { private static final ByteString EMPTY = new NioByteString(ByteBuffer.wrap(new byte[0])); private static final String CLASSNAME = NioByteString.class.getSimpleName(); @@ -86,7 +84,7 @@ public void testByteIterator() { stillEqual = (iter.hasNext() && BYTES[i] == iter.nextByte()); } assertTrue(CLASSNAME + " must capture the right bytes", stillEqual); - assertFalse(CLASSNAME + " must have exhausted the itertor", iter.hasNext()); + assertFalse(CLASSNAME + " must have exhausted the iterator", iter.hasNext()); try { iter.nextByte(); @@ -108,8 +106,7 @@ public void testByteIterable() { } public void testSize() { - assertEquals(CLASSNAME + " must have the expected size", BYTES.length, - testString.size()); + assertEquals(CLASSNAME + " must have the expected size", BYTES.length, testString.size()); } public void testGetTreeDepth() { @@ -140,10 +137,8 @@ public void testCopyTo_ByteArrayOffsetLengthErrors() { try { // Copy one too many bytes - testString.copyTo(destination, testString.size() + 1 - length, - destinationOffset, length); - fail("Should have thrown an exception when copying too many bytes of a " - + CLASSNAME); + testString.copyTo(destination, testString.size() + 1 - length, destinationOffset, length); + fail("Should have thrown an exception when copying too many bytes of a " + CLASSNAME); } catch (IndexOutOfBoundsException expected) { // This is success } @@ -151,8 +146,7 @@ public void testCopyTo_ByteArrayOffsetLengthErrors() { try { // Copy with illegal negative sourceOffset testString.copyTo(destination, -1, destinationOffset, length); - fail("Should have thrown an exception when given a negative sourceOffset in " - + CLASSNAME); + fail("Should have thrown an exception when given a negative sourceOffset in " + CLASSNAME); } catch (IndexOutOfBoundsException expected) { // This is success } @@ -160,8 +154,9 @@ public void testCopyTo_ByteArrayOffsetLengthErrors() { try { // Copy with illegal negative destinationOffset testString.copyTo(destination, 0, -1, length); - fail("Should have thrown an exception when given a negative destinationOffset in " - + CLASSNAME); + fail( + "Should have thrown an exception when given a negative destinationOffset in " + + CLASSNAME); } catch (IndexOutOfBoundsException expected) { // This is success } @@ -169,8 +164,7 @@ public void testCopyTo_ByteArrayOffsetLengthErrors() { try { // Copy with illegal negative size testString.copyTo(destination, 0, 0, -1); - fail("Should have thrown an exception when given a negative size in " - + CLASSNAME); + fail("Should have thrown an exception when given a negative size in " + CLASSNAME); } catch (IndexOutOfBoundsException expected) { // This is success } @@ -178,8 +172,9 @@ public void testCopyTo_ByteArrayOffsetLengthErrors() { try { // Copy with illegal too-large sourceOffset testString.copyTo(destination, 2 * testString.size(), 0, length); - fail("Should have thrown an exception when the destinationOffset is too large in " - + CLASSNAME); + fail( + "Should have thrown an exception when the destinationOffset is too large in " + + CLASSNAME); } catch (IndexOutOfBoundsException expected) { // This is success } @@ -187,8 +182,9 @@ public void testCopyTo_ByteArrayOffsetLengthErrors() { try { // Copy with illegal too-large destinationOffset testString.copyTo(destination, 0, 2 * destination.length, length); - fail("Should have thrown an exception when the destinationOffset is too large in " - + CLASSNAME); + fail( + "Should have thrown an exception when the destinationOffset is too large in " + + CLASSNAME); } catch (IndexOutOfBoundsException expected) { // This is success } @@ -199,8 +195,8 @@ public void testCopyTo_ByteBuffer() { ByteBuffer myBuffer = ByteBuffer.allocate(BYTES.length); testString.copyTo(myBuffer); myBuffer.flip(); - assertEquals(CLASSNAME + ".copyTo(ByteBuffer) must give back the same bytes", - backingBuffer, myBuffer); + assertEquals( + CLASSNAME + ".copyTo(ByteBuffer) must give back the same bytes", backingBuffer, myBuffer); // Target buffer bigger than required. myBuffer = ByteBuffer.allocate(testString.size() + 1); @@ -241,30 +237,31 @@ public void testMarkAndReset() throws IOException { skipFully(stream, fraction); // Skip a large fraction, but not all. assertEquals( CLASSNAME + ": after skipping to the 'middle', half the bytes are available", - (testString.size() - fraction), stream.available()); + (testString.size() - fraction), + stream.available()); stream.reset(); assertEquals( CLASSNAME + ": after resetting, all bytes are available", - testString.size(), stream.available()); + testString.size(), + stream.available()); skipFully(stream, testString.size()); // Skip to the end. assertEquals( CLASSNAME + ": after skipping to the end, no more bytes are available", - 0, stream.available()); + 0, + stream.available()); } /** - * Discards {@code n} bytes of data from the input stream. This method - * will block until the full amount has been skipped. Does not close the - * stream. + * Discards {@code n} bytes of data from the input stream. This method will block until the full + * amount has been skipped. Does not close the stream. + * *

Copied from com.google.common.io.ByteStreams to avoid adding dependency. * * @param in the input stream to read from * @param n the number of bytes to skip - * @throws EOFException if this stream reaches the end before skipping all - * the bytes - * @throws IOException if an I/O error occurs, or the stream does not - * support skipping + * @throws EOFException if this stream reaches the end before skipping all the bytes + * @throws IOException if an I/O error occurs, or the stream does not support skipping */ static void skipFully(InputStream in, long n) throws IOException { long toSkip = n; @@ -274,8 +271,12 @@ static void skipFully(InputStream in, long n) throws IOException { // Force a blocking read to avoid infinite loop if (in.read() == -1) { long skipped = toSkip - n; - throw new EOFException("reached end of stream after skipping " - + skipped + " bytes; " + toSkip + " bytes expected"); + throw new EOFException( + "reached end of stream after skipping " + + skipped + + " bytes; " + + toSkip + + " bytes expected"); } n--; } else { @@ -290,7 +291,8 @@ public void testAsReadOnlyByteBuffer() { assertTrue(byteBuffer.remaining() == BYTES.length); assertTrue(byteBuffer.isReadOnly()); byteBuffer.get(roundTripBytes); - assertTrue(CLASSNAME + ".asReadOnlyByteBuffer() must give back the same bytes", + assertTrue( + CLASSNAME + ".asReadOnlyByteBuffer() must give back the same bytes", Arrays.equals(BYTES, roundTripBytes)); } @@ -306,13 +308,15 @@ public void testAsReadOnlyByteBufferList() { bytesSeen += thisLength; } assertTrue(bytesSeen == BYTES.length); - assertTrue(CLASSNAME + ".asReadOnlyByteBufferTest() must give back the same bytes", + assertTrue( + CLASSNAME + ".asReadOnlyByteBufferTest() must give back the same bytes", Arrays.equals(BYTES, roundTripBytes)); } public void testToByteArray() { byte[] roundTripBytes = testString.toByteArray(); - assertTrue(CLASSNAME + ".toByteArray() must give back the same bytes", + assertTrue( + CLASSNAME + ".toByteArray() must give back the same bytes", Arrays.equals(BYTES, roundTripBytes)); } @@ -320,80 +324,87 @@ public void testWriteTo() throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); testString.writeTo(bos); byte[] roundTripBytes = bos.toByteArray(); - assertTrue(CLASSNAME + ".writeTo() must give back the same bytes", + assertTrue( + CLASSNAME + ".writeTo() must give back the same bytes", Arrays.equals(BYTES, roundTripBytes)); } public void testWriteToShouldNotExposeInternalBufferToOutputStream() throws IOException { - OutputStream os = new OutputStream() { - @Override - public void write(byte[] b, int off, int len) { - Arrays.fill(b, off, off + len, (byte) 0); - } - - @Override - public void write(int b) { - throw new UnsupportedOperationException(); - } - }; + OutputStream os = + new OutputStream() { + @Override + public void write(byte[] b, int off, int len) { + Arrays.fill(b, off, off + len, (byte) 0); + } + + @Override + public void write(int b) { + throw new UnsupportedOperationException(); + } + }; byte[] original = Arrays.copyOf(BYTES, BYTES.length); testString.writeTo(os); - assertTrue(CLASSNAME + ".writeTo() must NOT grant access to underlying buffer", + assertTrue( + CLASSNAME + ".writeTo() must NOT grant access to underlying buffer", Arrays.equals(original, BYTES)); } public void testWriteToInternalShouldExposeInternalBufferToOutputStream() throws IOException { - OutputStream os = new OutputStream() { - @Override - public void write(byte[] b, int off, int len) { - Arrays.fill(b, off, off + len, (byte) 0); - } - - @Override - public void write(int b) { - throw new UnsupportedOperationException(); - } - }; + OutputStream os = + new OutputStream() { + @Override + public void write(byte[] b, int off, int len) { + Arrays.fill(b, off, off + len, (byte) 0); + } + + @Override + public void write(int b) { + throw new UnsupportedOperationException(); + } + }; testString.writeToInternal(os, 0, testString.size()); byte[] allZeros = new byte[testString.size()]; - assertTrue(CLASSNAME + ".writeToInternal() must grant access to underlying buffer", + assertTrue( + CLASSNAME + ".writeToInternal() must grant access to underlying buffer", Arrays.equals(allZeros, backingBuffer.array())); } public void testWriteToShouldExposeInternalBufferToByteOutput() throws IOException { - ByteOutput out = new ByteOutput() { - @Override - public void write(byte value) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public void write(byte[] value, int offset, int length) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public void writeLazy(byte[] value, int offset, int length) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public void write(ByteBuffer value) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public void writeLazy(ByteBuffer value) throws IOException { - Arrays.fill(value.array(), value.arrayOffset(), value.arrayOffset() + value.limit(), - (byte) 0); - } - }; + ByteOutput out = + new ByteOutput() { + @Override + public void write(byte value) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void write(byte[] value, int offset, int length) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void write(ByteBuffer value) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void writeLazy(byte[] value, int offset, int length) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void writeLazy(ByteBuffer value) throws IOException { + Arrays.fill( + value.array(), value.arrayOffset(), value.arrayOffset() + value.limit(), (byte) 0); + } + }; testString.writeTo(out); byte[] allZeros = new byte[testString.size()]; - assertTrue(CLASSNAME + ".writeTo() must grant access to underlying buffer", + assertTrue( + CLASSNAME + ".writeTo() must grant access to underlying buffer", Arrays.equals(allZeros, backingBuffer.array())); } @@ -401,21 +412,21 @@ public void testNewOutput() throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteString.Output output = ByteString.newOutput(); testString.writeTo(output); - assertEquals("Output Size returns correct result", - output.size(), testString.size()); + assertEquals("Output Size returns correct result", output.size(), testString.size()); output.writeTo(bos); - assertTrue("Output.writeTo() must give back the same bytes", - Arrays.equals(BYTES, bos.toByteArray())); + assertTrue( + "Output.writeTo() must give back the same bytes", Arrays.equals(BYTES, bos.toByteArray())); // write the output stream to itself! This should cause it to double output.writeTo(output); - assertEquals("Writing an output stream to itself is successful", - testString.concat(testString), output.toByteString()); + assertEquals( + "Writing an output stream to itself is successful", + testString.concat(testString), + output.toByteString()); output.reset(); assertEquals("Output.reset() resets the output", 0, output.size()); - assertEquals("Output.reset() resets the output", - EMPTY, output.toByteString()); + assertEquals("Output.reset() resets the output", EMPTY, output.toByteString()); } public void testToString() { @@ -433,7 +444,8 @@ public void testCharsetToString() { } public void testToString_returnsCanonicalEmptyString() { - assertSame(CLASSNAME + " must be the same string references", + assertSame( + CLASSNAME + " must be the same string references", EMPTY.toString(UTF_8), new NioByteString(ByteBuffer.wrap(new byte[0])).toString(UTF_8)); } @@ -457,33 +469,34 @@ public void testToString_raisesException() { public void testEquals() { assertEquals(CLASSNAME + " must not equal null", false, testString.equals(null)); assertEquals(CLASSNAME + " must equal self", testString, testString); - assertFalse(CLASSNAME + " must not equal the empty string", - testString.equals(EMPTY)); - assertEquals(CLASSNAME + " empty strings must be equal", - EMPTY, testString.substring(55, 55)); - assertEquals(CLASSNAME + " must equal another string with the same value", - testString, new NioByteString(backingBuffer)); + assertFalse(CLASSNAME + " must not equal the empty string", testString.equals(EMPTY)); + assertEquals(CLASSNAME + " empty strings must be equal", EMPTY, testString.substring(55, 55)); + assertEquals( + CLASSNAME + " must equal another string with the same value", + testString, + new NioByteString(backingBuffer)); byte[] mungedBytes = mungedBytes(); - assertFalse(CLASSNAME + " must not equal every string with the same length", + assertFalse( + CLASSNAME + " must not equal every string with the same length", testString.equals(new NioByteString(ByteBuffer.wrap(mungedBytes)))); } public void testEqualsLiteralByteString() { ByteString literal = ByteString.copyFrom(BYTES); - assertEquals(CLASSNAME + " must equal LiteralByteString with same value", literal, - testString); - assertEquals(CLASSNAME + " must equal LiteralByteString with same value", testString, - literal); - assertFalse(CLASSNAME + " must not equal the empty string", - testString.equals(ByteString.EMPTY)); - assertEquals(CLASSNAME + " empty strings must be equal", - ByteString.EMPTY, testString.substring(55, 55)); + assertEquals(CLASSNAME + " must equal LiteralByteString with same value", literal, testString); + assertEquals(CLASSNAME + " must equal LiteralByteString with same value", testString, literal); + assertFalse( + CLASSNAME + " must not equal the empty string", testString.equals(ByteString.EMPTY)); + assertEquals( + CLASSNAME + " empty strings must be equal", ByteString.EMPTY, testString.substring(55, 55)); literal = ByteString.copyFrom(mungedBytes()); - assertFalse(CLASSNAME + " must not equal every LiteralByteString with the same length", + assertFalse( + CLASSNAME + " must not equal every LiteralByteString with the same length", testString.equals(literal)); - assertFalse(CLASSNAME + " must not equal every LiteralByteString with the same length", + assertFalse( + CLASSNAME + " must not equal every LiteralByteString with the same length", literal.equals(testString)); } @@ -492,22 +505,25 @@ public void testEqualsRopeByteString() { ByteString p2 = ByteString.copyFrom(BYTES, 5, BYTES.length - 5); ByteString rope = p1.concat(p2); - assertEquals(CLASSNAME + " must equal RopeByteString with same value", rope, - testString); - assertEquals(CLASSNAME + " must equal RopeByteString with same value", testString, - rope); - assertFalse(CLASSNAME + " must not equal the empty string", + assertEquals(CLASSNAME + " must equal RopeByteString with same value", rope, testString); + assertEquals(CLASSNAME + " must equal RopeByteString with same value", testString, rope); + assertFalse( + CLASSNAME + " must not equal the empty string", testString.equals(ByteString.EMPTY.concat(ByteString.EMPTY))); - assertEquals(CLASSNAME + " empty strings must be equal", - ByteString.EMPTY.concat(ByteString.EMPTY), testString.substring(55, 55)); + assertEquals( + CLASSNAME + " empty strings must be equal", + ByteString.EMPTY.concat(ByteString.EMPTY), + testString.substring(55, 55)); byte[] mungedBytes = mungedBytes(); p1 = ByteString.copyFrom(mungedBytes, 0, 5); p2 = ByteString.copyFrom(mungedBytes, 5, mungedBytes.length - 5); rope = p1.concat(p2); - assertFalse(CLASSNAME + " must not equal every RopeByteString with the same length", + assertFalse( + CLASSNAME + " must not equal every RopeByteString with the same length", testString.equals(rope)); - assertFalse(CLASSNAME + " must not equal every RopeByteString with the same length", + assertFalse( + CLASSNAME + " must not equal every RopeByteString with the same length", rope.equals(testString)); } @@ -525,32 +541,34 @@ public void testHashCode() { public void testPeekCachedHashCode() { ByteString newString = new NioByteString(backingBuffer); - assertEquals(CLASSNAME + ".peekCachedHashCode() should return zero at first", 0, + assertEquals( + CLASSNAME + ".peekCachedHashCode() should return zero at first", + 0, newString.peekCachedHashCode()); newString.hashCode(); - assertEquals(CLASSNAME + ".peekCachedHashCode should return zero at first", - EXPECTED_HASH, newString.peekCachedHashCode()); + assertEquals( + CLASSNAME + ".peekCachedHashCode should return zero at first", + EXPECTED_HASH, + newString.peekCachedHashCode()); } public void testPartialHash() { // partialHash() is more strenuously tested elsewhere by testing hashes of substrings. // This test would fail if the expected hash were 1. It's not. int hash = testString.partialHash(testString.size(), 0, testString.size()); - assertEquals(CLASSNAME + ".partialHash() must yield expected hashCode", - EXPECTED_HASH, hash); + assertEquals(CLASSNAME + ".partialHash() must yield expected hashCode", EXPECTED_HASH, hash); } public void testNewInput() throws IOException { InputStream input = testString.newInput(); - assertEquals("InputStream.available() returns correct value", - testString.size(), input.available()); + assertEquals( + "InputStream.available() returns correct value", testString.size(), input.available()); boolean stillEqual = true; for (byte referenceByte : BYTES) { int expectedInt = (referenceByte & 0xFF); stillEqual = (expectedInt == input.read()); } - assertEquals("InputStream.available() returns correct value", - 0, input.available()); + assertEquals("InputStream.available() returns correct value", 0, input.available()); assertTrue(CLASSNAME + " must give the same bytes from the InputStream", stillEqual); assertEquals(CLASSNAME + " InputStream must now be exhausted", -1, input.read()); } @@ -561,43 +579,44 @@ public void testNewInput_skip() throws IOException { int nearEndIndex = stringSize * 2 / 3; long skipped1 = input.skip(nearEndIndex); assertEquals("InputStream.skip()", skipped1, nearEndIndex); - assertEquals("InputStream.available()", - stringSize - skipped1, input.available()); + assertEquals("InputStream.available()", stringSize - skipped1, input.available()); assertTrue("InputStream.mark() is available", input.markSupported()); input.mark(0); - assertEquals("InputStream.skip(), read()", - testString.byteAt(nearEndIndex) & 0xFF, input.read()); - assertEquals("InputStream.available()", - stringSize - skipped1 - 1, input.available()); + assertEquals( + "InputStream.skip(), read()", testString.byteAt(nearEndIndex) & 0xFF, input.read()); + assertEquals("InputStream.available()", stringSize - skipped1 - 1, input.available()); long skipped2 = input.skip(stringSize); - assertEquals("InputStream.skip() incomplete", - skipped2, stringSize - skipped1 - 1); + assertEquals("InputStream.skip() incomplete", skipped2, stringSize - skipped1 - 1); assertEquals("InputStream.skip(), no more input", 0, input.available()); assertEquals("InputStream.skip(), no more input", -1, input.read()); input.reset(); - assertEquals("InputStream.reset() succeded", - stringSize - skipped1, input.available()); - assertEquals("InputStream.reset(), read()", - testString.byteAt(nearEndIndex) & 0xFF, input.read()); + assertEquals("InputStream.reset() succeeded", stringSize - skipped1, input.available()); + assertEquals( + "InputStream.reset(), read()", testString.byteAt(nearEndIndex) & 0xFF, input.read()); } public void testNewCodedInput() throws IOException { CodedInputStream cis = testString.newCodedInput(); byte[] roundTripBytes = cis.readRawBytes(BYTES.length); - assertTrue(CLASSNAME + " must give the same bytes back from the CodedInputStream", + assertTrue( + CLASSNAME + " must give the same bytes back from the CodedInputStream", Arrays.equals(BYTES, roundTripBytes)); assertTrue(CLASSNAME + " CodedInputStream must now be exhausted", cis.isAtEnd()); } /** - * Make sure we keep things simple when concatenating with empty. See also - * {@link ByteStringTest#testConcat_empty()}. + * Make sure we keep things simple when concatenating with empty. See also {@link + * ByteStringTest#testConcat_empty()}. */ public void testConcat_empty() { - assertSame(CLASSNAME + " concatenated with empty must give " + CLASSNAME, - testString.concat(EMPTY), testString); - assertSame("empty concatenated with " + CLASSNAME + " must give " + CLASSNAME, - EMPTY.concat(testString), testString); + assertSame( + CLASSNAME + " concatenated with empty must give " + CLASSNAME, + testString.concat(EMPTY), + testString); + assertSame( + "empty concatenated with " + CLASSNAME + " must give " + CLASSNAME, + EMPTY.concat(testString), + testString); } public void testJavaSerialization() throws Exception { diff --git a/java/core/src/test/java/com/google/protobuf/PackedFieldTest.java b/java/core/src/test/java/com/google/protobuf/PackedFieldTest.java new file mode 100644 index 0000000000000..2397d2ebc354c --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/PackedFieldTest.java @@ -0,0 +1,232 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.PackedFieldTestProto.TestAllTypes; +import com.google.protobuf.PackedFieldTestProto.TestAllTypes.NestedEnum; +import com.google.protobuf.PackedFieldTestProto.TestUnpackedTypes; +import junit.framework.TestCase; + +/** Tests primitive repeated fields in proto3 are packed in wire format. */ +public class PackedFieldTest extends TestCase { + static final ByteString expectedPackedRawBytes = + ByteString.copyFrom( + new byte[] { + (byte) 0xFA, + 0x01, + 0x01, + 0x01, // repeated int32 + (byte) 0x82, + 0x02, + 0x01, + 0x01, // repeated int64 + (byte) 0x8A, + 0x02, + 0x01, + 0x01, // repeated uint32 + (byte) 0x92, + 0x02, + 0x01, + 0x01, // repeated uint64 + (byte) 0x9A, + 0x02, + 0x01, + 0x02, // repeated sint32 + (byte) 0xA2, + 0x02, + 0x01, + 0x02, // repeated sint64 + (byte) 0xAA, + 0x02, + 0x04, + 0x01, + 0x00, + 0x00, + 0x00, // repeated fixed32 + (byte) 0xB2, + 0x02, + 0x08, + 0x01, + 0x00, + 0x00, + 0x00, // repeated fixed64 + 0x00, + 0x00, + 0x00, + 0x00, + (byte) 0xBA, + 0x02, + 0x04, + 0x01, + 0x00, + 0x00, + 0x00, // repeated sfixed32 + (byte) 0xC2, + 0x02, + 0x08, + 0x01, + 0x00, + 0x00, + 0x00, // repeated sfixed64 + 0x00, + 0x00, + 0x00, + 0x00, + (byte) 0xCA, + 0x02, + 0x04, + 0x00, + 0x00, + (byte) 0x80, + 0x3f, // repeated float + (byte) 0xD2, + 0x02, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, // repeated double + 0x00, + 0x00, + (byte) 0xf0, + 0x3f, + (byte) 0xDA, + 0x02, + 0x01, + 0x01, // repeated bool + (byte) 0x9A, + 0x03, + 0x01, + 0x01 // repeated nested enum + }); + + static final ByteString expectedUnpackedRawBytes = + ByteString.copyFrom( + new byte[] { + 0x08, + 0x01, // repeated int32 + 0x10, + 0x01, // repeated int64 + 0x18, + 0x01, // repeated uint32 + 0x20, + 0x01, // repeated uint64 + 0x28, + 0x02, // repeated sint32 + 0x30, + 0x02, // repeated sint64 + 0x3D, + 0x01, + 0x00, + 0x00, + 0x00, // repeated fixed32 + 0x41, + 0x01, + 0x00, + 0x00, + 0x00, // repeated fixed64 + 0x00, + 0x00, + 0x00, + 0x00, + 0x4D, + 0x01, + 0x00, + 0x00, + 0x00, // repeated sfixed32 + 0x51, + 0x01, + 0x00, + 0x00, + 0x00, // repeated sfixed64 + 0x00, + 0x00, + 0x00, + 0x00, + 0x5D, + 0x00, + 0x00, + (byte) 0x80, + 0x3f, // repeated float + 0x61, + 0x00, + 0x00, + 0x00, + 0x00, // repeated double + 0x00, + 0x00, + (byte) 0xf0, + 0x3f, + 0x68, + 0x01, // repeated bool + 0x70, + 0x01, // repeated nested enum + }); + + public void testPackedGeneratedMessage() throws Exception { + TestAllTypes message = TestAllTypes.parseFrom(expectedPackedRawBytes); + assertEquals(expectedPackedRawBytes, message.toByteString()); + } + + public void testPackedDynamicMessageSerialize() throws Exception { + DynamicMessage message = + DynamicMessage.parseFrom(TestAllTypes.getDescriptor(), expectedPackedRawBytes); + assertEquals(expectedPackedRawBytes, message.toByteString()); + } + + public void testUnpackedGeneratedMessage() throws Exception { + TestUnpackedTypes message = TestUnpackedTypes.parseFrom(expectedUnpackedRawBytes); + assertEquals(expectedUnpackedRawBytes, message.toByteString()); + } + + public void testUnPackedDynamicMessageSerialize() throws Exception { + DynamicMessage message = + DynamicMessage.parseFrom(TestUnpackedTypes.getDescriptor(), expectedUnpackedRawBytes); + assertEquals(expectedUnpackedRawBytes, message.toByteString()); + } + + // Make sure we haven't screwed up the code generation for packing fields by default. + public void testPackedSerialization() throws Exception { + TestAllTypes message = + TestAllTypes.newBuilder() + .addRepeatedInt32(1234) + .addRepeatedNestedEnum(NestedEnum.BAR) + .build(); + + CodedInputStream in = CodedInputStream.newInstance(message.toByteArray()); + + while (!in.isAtEnd()) { + int tag = in.readTag(); + assertEquals(WireFormat.WIRETYPE_LENGTH_DELIMITED, WireFormat.getTagWireType(tag)); + in.skipField(tag); + } + } +} diff --git a/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java b/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java index e376b1cd721ae..4e63ee76ae2d1 100644 --- a/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java +++ b/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java @@ -48,9 +48,9 @@ /** * Tests the exceptions thrown when parsing from a stream. The methods on the {@link Parser} * interface are specified to only throw {@link InvalidProtocolBufferException}. But we really want - * to distinguish between invalid protos vs. actual I/O errors (like failures reading from a - * socket, etc.). So, when we're not using the parser directly, an {@link IOException} should be - * thrown where appropriate, instead of always an {@link InvalidProtocolBufferException}. + * to distinguish between invalid protos vs. actual I/O errors (like failures reading from a socket, + * etc.). So, when we're not using the parser directly, an {@link IOException} should be thrown + * where appropriate, instead of always an {@link InvalidProtocolBufferException}. * * @author jh@squareup.com (Joshua Humphries) */ @@ -61,7 +61,7 @@ private interface ParseTester { DescriptorProto parse(InputStream in) throws IOException; } - private byte serializedProto[]; + private byte[] serializedProto; private void setup() { serializedProto = DescriptorProto.getDescriptor().toProto().toByteArray(); @@ -77,7 +77,8 @@ private void setupDelimited() { serializedProto = bos.toByteArray(); } - @Test public void message_parseFrom_InputStream() { + @Test + public void message_parseFrom_InputStream() { setup(); verifyExceptions( new ParseTester() { @@ -88,7 +89,8 @@ public DescriptorProto parse(InputStream in) throws IOException { }); } - @Test public void message_parseFrom_InputStreamAndExtensionRegistry() { + @Test + public void message_parseFrom_InputStreamAndExtensionRegistry() { setup(); verifyExceptions( new ParseTester() { @@ -99,7 +101,8 @@ public DescriptorProto parse(InputStream in) throws IOException { }); } - @Test public void message_parseFrom_CodedInputStream() { + @Test + public void message_parseFrom_CodedInputStream() { setup(); verifyExceptions( new ParseTester() { @@ -110,7 +113,8 @@ public DescriptorProto parse(InputStream in) throws IOException { }); } - @Test public void message_parseFrom_CodedInputStreamAndExtensionRegistry() { + @Test + public void message_parseFrom_CodedInputStreamAndExtensionRegistry() { setup(); verifyExceptions( new ParseTester() { @@ -122,7 +126,8 @@ public DescriptorProto parse(InputStream in) throws IOException { }); } - @Test public void message_parseDelimitedFrom_InputStream() { + @Test + public void message_parseDelimitedFrom_InputStream() { setupDelimited(); verifyExceptions( new ParseTester() { @@ -133,7 +138,8 @@ public DescriptorProto parse(InputStream in) throws IOException { }); } - @Test public void message_parseDelimitedFrom_InputStreamAndExtensionRegistry() { + @Test + public void message_parseDelimitedFrom_InputStreamAndExtensionRegistry() { setupDelimited(); verifyExceptions( new ParseTester() { @@ -144,7 +150,8 @@ public DescriptorProto parse(InputStream in) throws IOException { }); } - @Test public void messageBuilder_mergeFrom_InputStream() { + @Test + public void messageBuilder_mergeFrom_InputStream() { setup(); verifyExceptions( new ParseTester() { @@ -155,7 +162,8 @@ public DescriptorProto parse(InputStream in) throws IOException { }); } - @Test public void messageBuilder_mergeFrom_InputStreamAndExtensionRegistry() { + @Test + public void messageBuilder_mergeFrom_InputStreamAndExtensionRegistry() { setup(); verifyExceptions( new ParseTester() { @@ -168,7 +176,8 @@ public DescriptorProto parse(InputStream in) throws IOException { }); } - @Test public void messageBuilder_mergeFrom_CodedInputStream() { + @Test + public void messageBuilder_mergeFrom_CodedInputStream() { setup(); verifyExceptions( new ParseTester() { @@ -179,7 +188,8 @@ public DescriptorProto parse(InputStream in) throws IOException { }); } - @Test public void messageBuilder_mergeFrom_CodedInputStreamAndExtensionRegistry() { + @Test + public void messageBuilder_mergeFrom_CodedInputStreamAndExtensionRegistry() { setup(); verifyExceptions( new ParseTester() { @@ -192,7 +202,8 @@ public DescriptorProto parse(InputStream in) throws IOException { }); } - @Test public void messageBuilder_mergeDelimitedFrom_InputStream() { + @Test + public void messageBuilder_mergeDelimitedFrom_InputStream() { setupDelimited(); verifyExceptions( new ParseTester() { @@ -205,7 +216,25 @@ public DescriptorProto parse(InputStream in) throws IOException { }); } - @Test public void messageBuilder_mergeDelimitedFrom_InputStreamAndExtensionRegistry() { + @Test + public void messageBuilder_mergeDelimitedFrom_InputStream_malformed() throws Exception { + byte[] body = new byte[80]; + CodedOutputStream cos = CodedOutputStream.newInstance(body); + cos.writeRawVarint32(90); // Greater than bytes in stream + cos.writeTag(DescriptorProto.ENUM_TYPE_FIELD_NUMBER, WireFormat.WIRETYPE_LENGTH_DELIMITED); + cos.writeRawVarint32(98); // Nested message with size larger than parent + cos.writeTag(1000, WireFormat.WIRETYPE_LENGTH_DELIMITED); + cos.writeRawVarint32(100); // Unknown field with size larger than parent + ByteArrayInputStream bais = new ByteArrayInputStream(body); + try { + DescriptorProto.parseDelimitedFrom(bais); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + } + + @Test + public void messageBuilder_mergeDelimitedFrom_InputStreamAndExtensionRegistry() { setupDelimited(); verifyExceptions( new ParseTester() { @@ -221,7 +250,8 @@ public DescriptorProto parse(InputStream in) throws IOException { private void verifyExceptions(ParseTester parseTester) { // No exception try { - assertEquals(DescriptorProto.getDescriptor().toProto(), + assertEquals( + DescriptorProto.getDescriptor().toProto(), parseTester.parse(new ByteArrayInputStream(serializedProto))); } catch (IOException e) { fail("No exception expected: " + e); @@ -253,14 +283,16 @@ private InputStream broken(InputStream i) { return new FilterInputStream(i) { int count = 0; - @Override public int read() throws IOException { + @Override + public int read() throws IOException { if (count++ >= 50) { throw new IOException("I'm broken!"); } return super.read(); } - @Override public int read(byte b[], int off, int len) throws IOException { + @Override + public int read(byte[] b, int off, int len) throws IOException { if ((count += len) >= 50) { throw new IOException("I'm broken!"); } diff --git a/java/core/src/test/java/com/google/protobuf/ParserLiteTest.java b/java/core/src/test/java/com/google/protobuf/ParserLiteTest.java new file mode 100644 index 0000000000000..eb2dc3dd24b04 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/ParserLiteTest.java @@ -0,0 +1,191 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.UnittestLite.TestAllTypesLite; +import com.google.protobuf.UnittestLite.TestPackedExtensionsLite; +import com.google.protobuf.UnittestLite.TestParsingMergeLite; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import junit.framework.TestCase; + +public class ParserLiteTest extends TestCase { + private void assertRoundTripEquals(MessageLite message, ExtensionRegistryLite registry) + throws Exception { + final byte[] data = message.toByteArray(); + final int offset = 20; + final int length = data.length; + final int padding = 30; + Parser parser = message.getParserForType(); + assertEquals(message, parser.parseFrom(data, registry)); + assertEquals( + message, + parser.parseFrom(generatePaddingArray(data, offset, padding), offset, length, registry)); + assertEquals(message, parser.parseFrom(message.toByteString(), registry)); + assertEquals(message, parser.parseFrom(new ByteArrayInputStream(data), registry)); + assertEquals(message, parser.parseFrom(CodedInputStream.newInstance(data), registry)); + assertEquals( + message, parser.parseFrom(message.toByteString().asReadOnlyByteBuffer(), registry)); + } + + @SuppressWarnings("unchecked") + private void assertRoundTripEquals(MessageLite message) throws Exception { + final byte[] data = message.toByteArray(); + final int offset = 20; + final int length = data.length; + final int padding = 30; + + Parser parser = (Parser) message.getParserForType(); + assertEquals(message, parser.parseFrom(data)); + assertEquals( + message, parser.parseFrom(generatePaddingArray(data, offset, padding), offset, length)); + assertEquals(message, parser.parseFrom(message.toByteString())); + assertEquals(message, parser.parseFrom(new ByteArrayInputStream(data))); + assertEquals(message, parser.parseFrom(CodedInputStream.newInstance(data))); + assertEquals(message, parser.parseFrom(message.toByteString().asReadOnlyByteBuffer())); + } + + private byte[] generatePaddingArray(byte[] data, int offset, int padding) { + byte[] result = new byte[offset + data.length + padding]; + System.arraycopy(data, 0, result, offset, data.length); + return result; + } + + public void testParseExtensionsLite() throws Exception { + assertRoundTripEquals( + TestUtilLite.getAllLiteExtensionsSet(), TestUtilLite.getExtensionRegistryLite()); + } + + public void testParsePacked() throws Exception { + assertRoundTripEquals(TestUtil.getPackedSet()); + assertRoundTripEquals(TestUtil.getPackedExtensionsSet(), TestUtil.getExtensionRegistry()); + } + + public void testParsePackedLite() throws Exception { + assertRoundTripEquals( + TestUtilLite.getLitePackedExtensionsSet(), TestUtilLite.getExtensionRegistryLite()); + } + + public void testParseDelimitedToLite() throws Exception { + // Write MessageLite with packed extension fields. + TestPackedExtensionsLite packedMessage = TestUtilLite.getLitePackedExtensionsSet(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + packedMessage.writeDelimitedTo(output); + packedMessage.writeDelimitedTo(output); + + InputStream input = new ByteArrayInputStream(output.toByteArray()); + assertEquals( + packedMessage, + packedMessage + .getParserForType() + .parseDelimitedFrom(input, TestUtilLite.getExtensionRegistryLite())); + assertEquals( + packedMessage, + packedMessage + .getParserForType() + .parseDelimitedFrom(input, TestUtilLite.getExtensionRegistryLite())); + } + + /** Helper method for {@link #testParsingMergeLite()}. */ + private void assertMessageMerged(TestAllTypesLite allTypes) throws Exception { + assertEquals(3, allTypes.getOptionalInt32()); + assertEquals(2, allTypes.getOptionalInt64()); + assertEquals("hello", allTypes.getOptionalString()); + } + + public void testParsingMergeLite() throws Exception { + // Build messages. + TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder(); + TestAllTypesLite msg1 = builder.setOptionalInt32(1).build(); + builder.clear(); + TestAllTypesLite msg2 = builder.setOptionalInt64(2).build(); + builder.clear(); + TestAllTypesLite msg3 = builder.setOptionalInt32(3).setOptionalString("hello").build(); + + // Build groups. + TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG1 = + TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder().setField1(msg1).build(); + TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG2 = + TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder().setField1(msg2).build(); + TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG3 = + TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder().setField1(msg3).build(); + TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG1 = + TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder().setField1(msg1).build(); + TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG2 = + TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder().setField1(msg2).build(); + TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG3 = + TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder().setField1(msg3).build(); + + // Assign and serialize RepeatedFieldsGenerator. + ByteString data = + TestParsingMergeLite.RepeatedFieldsGenerator.newBuilder() + .addField1(msg1) + .addField1(msg2) + .addField1(msg3) + .addField2(msg1) + .addField2(msg2) + .addField2(msg3) + .addField3(msg1) + .addField3(msg2) + .addField3(msg3) + .addGroup1(optionalG1) + .addGroup1(optionalG2) + .addGroup1(optionalG3) + .addGroup2(repeatedG1) + .addGroup2(repeatedG2) + .addGroup2(repeatedG3) + .addExt1(msg1) + .addExt1(msg2) + .addExt1(msg3) + .addExt2(msg1) + .addExt2(msg2) + .addExt2(msg3) + .build() + .toByteString(); + + // Parse TestParsingMergeLite. + ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); + UnittestLite.registerAllExtensions(registry); + TestParsingMergeLite parsingMerge = TestParsingMergeLite.parser().parseFrom(data, registry); + + // Required and optional fields should be merged. + assertMessageMerged(parsingMerge.getRequiredAllTypes()); + assertMessageMerged(parsingMerge.getOptionalAllTypes()); + assertMessageMerged(parsingMerge.getOptionalGroup().getOptionalGroupAllTypes()); + assertMessageMerged(parsingMerge.getExtension(TestParsingMergeLite.optionalExt)); + + // Repeated fields should not be merged. + assertEquals(3, parsingMerge.getRepeatedAllTypesCount()); + assertEquals(3, parsingMerge.getRepeatedGroupCount()); + assertEquals(3, parsingMerge.getExtensionCount(TestParsingMergeLite.repeatedExt)); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/ParserTest.java b/java/core/src/test/java/com/google/protobuf/ParserTest.java index 4bd34112d6524..983caec76946a 100644 --- a/java/core/src/test/java/com/google/protobuf/ParserTest.java +++ b/java/core/src/test/java/com/google/protobuf/ParserTest.java @@ -30,9 +30,6 @@ package com.google.protobuf; -import com.google.protobuf.UnittestLite.TestAllTypesLite; -import com.google.protobuf.UnittestLite.TestPackedExtensionsLite; -import com.google.protobuf.UnittestLite.TestParsingMergeLite; import protobuf_unittest.UnittestOptimizeFor; import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize; import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize; @@ -61,8 +58,7 @@ public void testGeneratedMessageParserSingleton() throws Exception { } } - private void assertRoundTripEquals(MessageLite message, - ExtensionRegistryLite registry) + private void assertRoundTripEquals(MessageLite message, ExtensionRegistryLite registry) throws Exception { final byte[] data = message.toByteArray(); final int offset = 20; @@ -70,15 +66,12 @@ private void assertRoundTripEquals(MessageLite message, final int padding = 30; Parser parser = message.getParserForType(); assertMessageEquals(message, parser.parseFrom(data, registry)); - assertMessageEquals(message, parser.parseFrom( - generatePaddingArray(data, offset, padding), - offset, length, registry)); - assertMessageEquals(message, parser.parseFrom( - message.toByteString(), registry)); - assertMessageEquals(message, parser.parseFrom( - new ByteArrayInputStream(data), registry)); - assertMessageEquals(message, parser.parseFrom( - CodedInputStream.newInstance(data), registry)); + assertMessageEquals( + message, + parser.parseFrom(generatePaddingArray(data, offset, padding), offset, length, registry)); + assertMessageEquals(message, parser.parseFrom(message.toByteString(), registry)); + assertMessageEquals(message, parser.parseFrom(new ByteArrayInputStream(data), registry)); + assertMessageEquals(message, parser.parseFrom(CodedInputStream.newInstance(data), registry)); assertMessageEquals( message, parser.parseFrom(message.toByteString().asReadOnlyByteBuffer(), registry)); } @@ -90,23 +83,17 @@ private void assertRoundTripEquals(MessageLite message) throws Exception { final int length = data.length; final int padding = 30; - Parser parser = - (Parser) message.getParserForType(); + Parser parser = (Parser) message.getParserForType(); assertMessageEquals(message, parser.parseFrom(data)); - assertMessageEquals(message, parser.parseFrom( - generatePaddingArray(data, offset, padding), - offset, length)); + assertMessageEquals( + message, parser.parseFrom(generatePaddingArray(data, offset, padding), offset, length)); assertMessageEquals(message, parser.parseFrom(message.toByteString())); - assertMessageEquals(message, parser.parseFrom( - new ByteArrayInputStream(data))); - assertMessageEquals(message, parser.parseFrom( - CodedInputStream.newInstance(data))); + assertMessageEquals(message, parser.parseFrom(new ByteArrayInputStream(data))); + assertMessageEquals(message, parser.parseFrom(CodedInputStream.newInstance(data))); assertMessageEquals(message, parser.parseFrom(message.toByteString().asReadOnlyByteBuffer())); } - private void assertMessageEquals( - MessageLite expected, MessageLite actual) - throws Exception { + private void assertMessageEquals(MessageLite expected, MessageLite actual) throws Exception { if (expected instanceof Message) { assertEquals(expected, actual); } else { @@ -129,20 +116,16 @@ public void testParsePartial() throws Exception { assertParsePartial(TestRequired.parser(), TestRequired.newBuilder().setA(1).buildPartial()); } - private void assertParsePartial( - Parser parser, T partialMessage) throws Exception { - final String errorString = - "Should throw exceptions when the parsed message isn't initialized."; + private void assertParsePartial(Parser parser, T partialMessage) + throws Exception { + final String errorString = "Should throw exceptions when the parsed message isn't initialized."; // parsePartialFrom should pass. byte[] data = partialMessage.toByteArray(); assertEquals(partialMessage, parser.parsePartialFrom(data)); - assertEquals(partialMessage, parser.parsePartialFrom( - partialMessage.toByteString())); - assertEquals(partialMessage, parser.parsePartialFrom( - new ByteArrayInputStream(data))); - assertEquals(partialMessage, parser.parsePartialFrom( - CodedInputStream.newInstance(data))); + assertEquals(partialMessage, parser.parsePartialFrom(partialMessage.toByteString())); + assertEquals(partialMessage, parser.parsePartialFrom(new ByteArrayInputStream(data))); + assertEquals(partialMessage, parser.parsePartialFrom(CodedInputStream.newInstance(data))); // parseFrom(ByteArray) try { @@ -170,8 +153,7 @@ private void assertParsePartial( // parseFrom(CodedInputStream) try { - parser.parseFrom(CodedInputStream.newInstance( - partialMessage.toByteArray())); + parser.parseFrom(CodedInputStream.newInstance(partialMessage.toByteArray())); fail(errorString); } catch (IOException e) { // pass. @@ -179,24 +161,12 @@ private void assertParsePartial( } public void testParseExtensions() throws Exception { - assertRoundTripEquals(TestUtil.getAllExtensionsSet(), - TestUtil.getExtensionRegistry()); - } - - public void testParseExtensionsLite() throws Exception { - assertRoundTripEquals( - TestUtilLite.getAllLiteExtensionsSet(), TestUtilLite.getExtensionRegistryLite()); + assertRoundTripEquals(TestUtil.getAllExtensionsSet(), TestUtil.getExtensionRegistry()); } public void testParsePacked() throws Exception { assertRoundTripEquals(TestUtil.getPackedSet()); - assertRoundTripEquals(TestUtil.getPackedExtensionsSet(), - TestUtil.getExtensionRegistry()); - } - - public void testParsePackedLite() throws Exception { - assertRoundTripEquals( - TestUtilLite.getLitePackedExtensionsSet(), TestUtilLite.getExtensionRegistryLite()); + assertRoundTripEquals(TestUtil.getPackedExtensionsSet(), TestUtil.getExtensionRegistry()); } public void testParseDelimitedTo() throws Exception { @@ -211,33 +181,11 @@ public void testParseDelimitedTo() throws Exception { assertMessageEquals(normalMessage, normalMessage.getParserForType().parseDelimitedFrom(input)); } - public void testParseDelimitedToLite() throws Exception { - // Write MessageLite with packed extension fields. - TestPackedExtensionsLite packedMessage = TestUtilLite.getLitePackedExtensionsSet(); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - packedMessage.writeDelimitedTo(output); - packedMessage.writeDelimitedTo(output); - - InputStream input = new ByteArrayInputStream(output.toByteArray()); - assertMessageEquals( - packedMessage, - packedMessage - .getParserForType() - .parseDelimitedFrom(input, TestUtilLite.getExtensionRegistryLite())); - assertMessageEquals( - packedMessage, - packedMessage - .getParserForType() - .parseDelimitedFrom(input, TestUtilLite.getExtensionRegistryLite())); - } - public void testParseUnknownFields() throws Exception { // All fields will be treated as unknown fields in emptyMessage. TestEmptyMessage emptyMessage = TestEmptyMessage.parser().parseFrom(TestUtil.getAllSet().toByteString()); - assertEquals( - TestUtil.getAllSet().toByteString(), - emptyMessage.toByteString()); + assertEquals(TestUtil.getAllSet().toByteString(), emptyMessage.toByteString()); } @@ -245,7 +193,8 @@ public void testOptimizeForSize() throws Exception { TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder(); builder.setI(12).setMsg(ForeignMessage.newBuilder().setC(34).build()); builder.setExtension(TestOptimizedForSize.testExtension, 56); - builder.setExtension(TestOptimizedForSize.testExtension2, + builder.setExtension( + TestOptimizedForSize.testExtension2, TestRequiredOptimizedForSize.newBuilder().setX(78).build()); TestOptimizedForSize message = builder.build(); @@ -255,17 +204,8 @@ public void testOptimizeForSize() throws Exception { assertRoundTripEquals(message, registry); } - /** Helper method for {@link #testParsingMerge()}.*/ - private void assertMessageMerged(TestAllTypes allTypes) - throws Exception { - assertEquals(3, allTypes.getOptionalInt32()); - assertEquals(2, allTypes.getOptionalInt64()); - assertEquals("hello", allTypes.getOptionalString()); - } - - /** Helper method for {@link #testParsingMergeLite()}.*/ - private void assertMessageMerged(TestAllTypesLite allTypes) - throws Exception { + /** Helper method for {@link #testParsingMerge()}. */ + private void assertMessageMerged(TestAllTypes allTypes) throws Exception { assertEquals(3, allTypes.getOptionalInt32()); assertEquals(2, allTypes.getOptionalInt64()); assertEquals("hello", allTypes.getOptionalString()); @@ -278,39 +218,48 @@ public void testParsingMerge() throws Exception { builder.clear(); TestAllTypes msg2 = builder.setOptionalInt64(2).build(); builder.clear(); - TestAllTypes msg3 = builder.setOptionalInt32(3) - .setOptionalString("hello").build(); + TestAllTypes msg3 = builder.setOptionalInt32(3).setOptionalString("hello").build(); // Build groups. TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG1 = - TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder() - .setField1(msg1).build(); + TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder().setField1(msg1).build(); TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG2 = - TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder() - .setField1(msg2).build(); + TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder().setField1(msg2).build(); TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG3 = - TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder() - .setField1(msg3).build(); + TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder().setField1(msg3).build(); TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG1 = - TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder() - .setField1(msg1).build(); + TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder().setField1(msg1).build(); TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG2 = - TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder() - .setField1(msg2).build(); + TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder().setField1(msg2).build(); TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG3 = - TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder() - .setField1(msg3).build(); + TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder().setField1(msg3).build(); // Assign and serialize RepeatedFieldsGenerator. - ByteString data = TestParsingMerge.RepeatedFieldsGenerator.newBuilder() - .addField1(msg1).addField1(msg2).addField1(msg3) - .addField2(msg1).addField2(msg2).addField2(msg3) - .addField3(msg1).addField3(msg2).addField3(msg3) - .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3) - .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3) - .addExt1(msg1).addExt1(msg2).addExt1(msg3) - .addExt2(msg1).addExt2(msg2).addExt2(msg3) - .build().toByteString(); + ByteString data = + TestParsingMerge.RepeatedFieldsGenerator.newBuilder() + .addField1(msg1) + .addField1(msg2) + .addField1(msg3) + .addField2(msg1) + .addField2(msg2) + .addField2(msg3) + .addField3(msg1) + .addField3(msg2) + .addField3(msg3) + .addGroup1(optionalG1) + .addGroup1(optionalG2) + .addGroup1(optionalG3) + .addGroup2(repeatedG1) + .addGroup2(repeatedG2) + .addGroup2(repeatedG3) + .addExt1(msg1) + .addExt1(msg2) + .addExt1(msg3) + .addExt2(msg1) + .addExt2(msg2) + .addExt2(msg3) + .build() + .toByteString(); // Parse TestParsingMerge. ExtensionRegistry registry = ExtensionRegistry.newInstance(); @@ -320,82 +269,18 @@ public void testParsingMerge() throws Exception { // Required and optional fields should be merged. assertMessageMerged(parsingMerge.getRequiredAllTypes()); assertMessageMerged(parsingMerge.getOptionalAllTypes()); - assertMessageMerged( - parsingMerge.getOptionalGroup().getOptionalGroupAllTypes()); - assertMessageMerged(parsingMerge.getExtension( - TestParsingMerge.optionalExt)); - - // Repeated fields should not be merged. - assertEquals(3, parsingMerge.getRepeatedAllTypesCount()); - assertEquals(3, parsingMerge.getRepeatedGroupCount()); - assertEquals(3, parsingMerge.getExtensionCount( - TestParsingMerge.repeatedExt)); - } - - public void testParsingMergeLite() throws Exception { - // Build messages. - TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder(); - TestAllTypesLite msg1 = builder.setOptionalInt32(1).build(); - builder.clear(); - TestAllTypesLite msg2 = builder.setOptionalInt64(2).build(); - builder.clear(); - TestAllTypesLite msg3 = builder.setOptionalInt32(3) - .setOptionalString("hello").build(); - - // Build groups. - TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG1 = - TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder() - .setField1(msg1).build(); - TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG2 = - TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder() - .setField1(msg2).build(); - TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG3 = - TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder() - .setField1(msg3).build(); - TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG1 = - TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder() - .setField1(msg1).build(); - TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG2 = - TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder() - .setField1(msg2).build(); - TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG3 = - TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder() - .setField1(msg3).build(); - - // Assign and serialize RepeatedFieldsGenerator. - ByteString data = TestParsingMergeLite.RepeatedFieldsGenerator.newBuilder() - .addField1(msg1).addField1(msg2).addField1(msg3) - .addField2(msg1).addField2(msg2).addField2(msg3) - .addField3(msg1).addField3(msg2).addField3(msg3) - .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3) - .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3) - .addExt1(msg1).addExt1(msg2).addExt1(msg3) - .addExt2(msg1).addExt2(msg2).addExt2(msg3) - .build().toByteString(); - - // Parse TestParsingMergeLite. - ExtensionRegistry registry = ExtensionRegistry.newInstance(); - UnittestLite.registerAllExtensions(registry); - TestParsingMergeLite parsingMerge = TestParsingMergeLite.parser().parseFrom(data, registry); - - // Required and optional fields should be merged. - assertMessageMerged(parsingMerge.getRequiredAllTypes()); - assertMessageMerged(parsingMerge.getOptionalAllTypes()); - assertMessageMerged( - parsingMerge.getOptionalGroup().getOptionalGroupAllTypes()); - assertMessageMerged(parsingMerge.getExtension( - TestParsingMergeLite.optionalExt)); + assertMessageMerged(parsingMerge.getOptionalGroup().getOptionalGroupAllTypes()); + assertMessageMerged(parsingMerge.getExtension(TestParsingMerge.optionalExt)); // Repeated fields should not be merged. assertEquals(3, parsingMerge.getRepeatedAllTypesCount()); assertEquals(3, parsingMerge.getRepeatedGroupCount()); - assertEquals(3, parsingMerge.getExtensionCount( - TestParsingMergeLite.repeatedExt)); + assertEquals(3, parsingMerge.getExtensionCount(TestParsingMerge.repeatedExt)); } public void testParseDelimitedFrom_firstByteInterrupted_preservesCause() { try { - TestUtil.getAllSet().parseDelimitedFrom( + TestAllTypes.parseDelimitedFrom( new InputStream() { @Override public int read() throws IOException { @@ -410,7 +295,7 @@ public int read() throws IOException { public void testParseDelimitedFrom_secondByteInterrupted_preservesCause() { try { - TestUtil.getAllSet().parseDelimitedFrom( + TestAllTypes.parseDelimitedFrom( new InputStream() { private int i; diff --git a/java/core/src/test/java/com/google/protobuf/Proto2ExtensionLookupSchemaTest.java b/java/core/src/test/java/com/google/protobuf/Proto2ExtensionLookupSchemaTest.java new file mode 100644 index 0000000000000..dfda4b3cbdd9d --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Proto2ExtensionLookupSchemaTest.java @@ -0,0 +1,171 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; + +import com.google.protobuf.testing.Proto2Testing; +import com.google.protobuf.testing.Proto2Testing.Proto2Message; +import com.google.protobuf.testing.Proto2Testing.Proto2Message.TestEnum; +import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithExtensions; +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class Proto2ExtensionLookupSchemaTest { + private byte[] data; + private ExtensionRegistry extensionRegistry; + + @Before + public void setup() { + TestSchemas.registerGenericProto2Schemas(); + + Protobuf.getInstance().schemaFor(Proto2MessageWithExtensions.class); + data = new Proto2MessageFactory(10, 20, 1, 1).newMessage().toByteArray(); + extensionRegistry = ExtensionRegistry.newInstance(); + Proto2Testing.registerAllExtensions(extensionRegistry); + } + + @Test + public void testExtensions() throws Exception { + Proto2MessageWithExtensions base = + Proto2MessageWithExtensions.parseFrom(data, extensionRegistry); + + Proto2MessageWithExtensions message = + ExperimentalSerializationUtil.fromByteArray( + data, Proto2MessageWithExtensions.class, extensionRegistry); + assertEquals(base, message); + + Proto2MessageWithExtensions roundtripMessage = + ExperimentalSerializationUtil.fromByteArray( + ExperimentalSerializationUtil.toByteArray(message), + Proto2MessageWithExtensions.class, + extensionRegistry); + assertEquals(base, roundtripMessage); + } + + @Test + public void testUnknownEnum() throws Exception { + // Use unknown fields to hold invalid enum values. + UnknownFieldSetLite unknowns = UnknownFieldSetLite.newInstance(); + final int outOfRange = 1000; + assertNull(TestEnum.forNumber(outOfRange)); + unknowns.storeField( + WireFormat.makeTag(Proto2Message.FIELD_ENUM_13_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), + (long) outOfRange); + unknowns.storeField( + WireFormat.makeTag( + Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), + (long) TestEnum.ONE_VALUE); + unknowns.storeField( + WireFormat.makeTag( + Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), + (long) outOfRange); + unknowns.storeField( + WireFormat.makeTag( + Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), + (long) TestEnum.TWO_VALUE); + + { + // Construct a packed enum list. + int packedSize = + CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE) + + CodedOutputStream.computeUInt32SizeNoTag(outOfRange) + + CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE); + ByteString.CodedBuilder packedBuilder = ByteString.newCodedBuilder(packedSize); + CodedOutputStream packedOut = packedBuilder.getCodedOutput(); + packedOut.writeEnumNoTag(TestEnum.ONE_VALUE); + packedOut.writeEnumNoTag(outOfRange); + packedOut.writeEnumNoTag(TestEnum.TWO_VALUE); + unknowns.storeField( + WireFormat.makeTag( + Proto2Message.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER, + WireFormat.WIRETYPE_LENGTH_DELIMITED), + packedBuilder.build()); + } + int size = unknowns.getSerializedSize(); + byte[] output = new byte[size]; + CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); + unknowns.writeTo(codedOutput); + codedOutput.flush(); + + Proto2MessageWithExtensions parsed = + ExperimentalSerializationUtil.fromByteArray( + output, Proto2MessageWithExtensions.class, extensionRegistry); + assertFalse( + "out-of-range singular enum should not be in message", + parsed.hasExtension(Proto2Testing.fieldEnum13)); + { + List singularEnum = + parsed + .getUnknownFields() + .getField(Proto2Message.FIELD_ENUM_13_FIELD_NUMBER) + .getVarintList(); + assertEquals(1, singularEnum.size()); + assertEquals((Long) (long) outOfRange, singularEnum.get(0)); + } + { + List repeatedEnum = + parsed + .getUnknownFields() + .getField(Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER) + .getVarintList(); + assertEquals(1, repeatedEnum.size()); + assertEquals((Long) (long) outOfRange, repeatedEnum.get(0)); + } + { + List packedRepeatedEnum = + parsed + .getUnknownFields() + .getField(Proto2Message.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER) + .getVarintList(); + assertEquals(1, packedRepeatedEnum.size()); + assertEquals((Long) (long) outOfRange, packedRepeatedEnum.get(0)); + } + assertEquals( + "out-of-range repeated enum should not be in message", + 2, + parsed.getExtension(Proto2Testing.fieldEnumList30).size()); + assertEquals(TestEnum.ONE, parsed.getExtension(Proto2Testing.fieldEnumList30, 0)); + assertEquals(TestEnum.TWO, parsed.getExtension(Proto2Testing.fieldEnumList30, 1)); + assertEquals( + "out-of-range packed repeated enum should not be in message", + 2, + parsed.getExtension(Proto2Testing.fieldEnumListPacked44).size()); + assertEquals(TestEnum.ONE, parsed.getExtension(Proto2Testing.fieldEnumListPacked44, 0)); + assertEquals(TestEnum.TWO, parsed.getExtension(Proto2Testing.fieldEnumListPacked44, 1)); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/Proto2LiteSchemaTest.java b/java/core/src/test/java/com/google/protobuf/Proto2LiteSchemaTest.java new file mode 100644 index 0000000000000..8242f847ee5f7 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Proto2LiteSchemaTest.java @@ -0,0 +1,49 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class Proto2LiteSchemaTest extends AbstractProto2LiteSchemaTest { + + @Override + protected Schema schema() { + return TestSchemasLite.genericProto2LiteSchema; + } + + @Override + protected void registerSchemas() { + TestSchemasLite.registerGenericProto2LiteSchemas(); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/Proto2MessageFactory.java b/java/core/src/test/java/com/google/protobuf/Proto2MessageFactory.java new file mode 100644 index 0000000000000..b5c61ed998532 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Proto2MessageFactory.java @@ -0,0 +1,555 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.testing.Proto2Testing.Proto2Message; +import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithMaps; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** Creates instances of {@link Proto2Message} based on the tree configuration. */ +public final class Proto2MessageFactory implements ExperimentalMessageFactory { + private final int numRepeatedFields; + private final int branchingFactor; + private final Proto2MessageFactory nextLevel; + private final ExperimentalTestDataProvider data; + + public Proto2MessageFactory( + int numRepeatedFields, int stringLength, int branchingFactor, int treeDepth) { + this( + new ExperimentalTestDataProvider(stringLength), + numRepeatedFields, + branchingFactor, + treeDepth); + } + + private Proto2MessageFactory( + ExperimentalTestDataProvider data, + int numRepeatedFields, + int branchingFactor, + int treeDepth) { + this.numRepeatedFields = numRepeatedFields; + this.branchingFactor = branchingFactor; + this.data = data; + if (treeDepth > 0) { + nextLevel = new Proto2MessageFactory(data, numRepeatedFields, branchingFactor, treeDepth - 1); + } else { + nextLevel = null; + } + } + + @Override + public ExperimentalTestDataProvider dataProvider() { + return data; + } + + @Override + public Proto2Message newMessage() { + Proto2Message.Builder builder = Proto2Message.newBuilder(); + builder.setFieldDouble1(data.getDouble()); + builder.setFieldFloat2(data.getFloat()); + builder.setFieldInt643(data.getLong()); + builder.setFieldUint644(data.getLong()); + builder.setFieldInt325(data.getInt()); + builder.setFieldFixed646(data.getLong()); + builder.setFieldFixed327(data.getInt()); + builder.setFieldBool8(data.getBool()); + builder.setFieldString9(data.getString()); + // We don't populate the message field. Instead we apply the branching factor to the + // repeated message field below. + builder.setFieldBytes11(data.getBytes()); + builder.setFieldUint3212(data.getInt()); + builder.setFieldEnum13(Proto2Message.TestEnum.forNumber(data.getEnum())); + builder.setFieldSfixed3214(data.getInt()); + builder.setFieldSfixed6415(data.getLong()); + builder.setFieldSint3216(data.getInt()); + builder.setFieldSint6417(data.getLong()); + + for (int i = 0; i < numRepeatedFields; ++i) { + builder.addFieldDoubleList18(data.getDouble()); + builder.addFieldFloatList19(data.getFloat()); + builder.addFieldInt64List20(data.getLong()); + builder.addFieldUint64List21(data.getLong()); + builder.addFieldInt32List22(data.getInt()); + builder.addFieldFixed64List23(data.getLong()); + builder.addFieldFixed32List24(data.getInt()); + builder.addFieldBoolList25(data.getBool()); + builder.addFieldStringList26(data.getString()); + // Repeated message field is controlled by the branching factor below. + builder.addFieldBytesList28(data.getBytes()); + builder.addFieldUint32List29(data.getInt()); + builder.addFieldEnumList30(Proto2Message.TestEnum.forNumber(data.getEnum())); + builder.addFieldSfixed32List31(data.getInt()); + builder.addFieldSfixed64List32(data.getLong()); + builder.addFieldSint32List33(data.getInt()); + builder.addFieldSint64List34(data.getLong()); + + builder.addFieldDoubleListPacked35(data.getDouble()); + builder.addFieldFloatListPacked36(data.getFloat()); + builder.addFieldInt64ListPacked37(data.getLong()); + builder.addFieldUint64ListPacked38(data.getLong()); + builder.addFieldInt32ListPacked39(data.getInt()); + builder.addFieldFixed64ListPacked40(data.getLong()); + builder.addFieldFixed32ListPacked41(data.getInt()); + builder.addFieldBoolListPacked42(data.getBool()); + builder.addFieldUint32ListPacked43(data.getInt()); + builder.addFieldEnumListPacked44(Proto2Message.TestEnum.forNumber(data.getEnum())); + builder.addFieldSfixed32ListPacked45(data.getInt()); + builder.addFieldSfixed64ListPacked46(data.getLong()); + builder.addFieldSint32ListPacked47(data.getInt()); + builder.addFieldSint64ListPacked48(data.getLong()); + } + + builder.setFieldGroup49(Proto2Message.FieldGroup49.newBuilder().setFieldInt3250(data.getInt())); + + for (int i = 0; i < branchingFactor; ++i) { + builder.addFieldGroupList51( + Proto2Message.FieldGroupList51.newBuilder().setFieldInt3252(data.getInt())); + } + + // Set all required fields. + populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS); + + // Handle the branching factor. + if (nextLevel != null) { + for (int i = 0; i < branchingFactor; ++i) { + builder.addFieldMessageList27(nextLevel.newMessage()); + } + } + + return builder.build(); + } + + private interface MapValueProvider { + public T getValue(); + } + + private final MapValueProvider integerProvider = + new MapValueProvider() { + @Override + public Integer getValue() { + return data.getInt(); + } + }; + private final MapValueProvider longProvider = + new MapValueProvider() { + @Override + public Long getValue() { + return data.getLong(); + } + }; + private final MapValueProvider stringProvider = + new MapValueProvider() { + @Override + public String getValue() { + return data.getString(); + } + }; + private final MapValueProvider bytesProvider = + new MapValueProvider() { + @Override + public ByteString getValue() { + return data.getBytes(); + } + }; + private final MapValueProvider booleanProvider = + new MapValueProvider() { + @Override + public Boolean getValue() { + return data.getBool(); + } + }; + private final MapValueProvider floatProvider = + new MapValueProvider() { + @Override + public Float getValue() { + return data.getFloat(); + } + }; + private final MapValueProvider doubleProvider = + new MapValueProvider() { + @Override + public Double getValue() { + return data.getDouble(); + } + }; + private final MapValueProvider messageProvider = + new MapValueProvider() { + @Override + public Proto2Message getValue() { + return newMessage(); + } + }; + private final MapValueProvider enumProvider = + new MapValueProvider() { + @Override + public Proto2Message.TestEnum getValue() { + return Proto2Message.TestEnum.forNumber(data.getEnum()); + } + }; + + private Map populateIntegerMap(MapValueProvider provider) { + Map map = new HashMap<>(); + for (int i = 0; i < numRepeatedFields; ++i) { + map.put(data.getInt(), provider.getValue()); + } + return map; + } + + private Map populateLongMap(MapValueProvider provider) { + Map map = new HashMap<>(); + for (int i = 0; i < numRepeatedFields; ++i) { + map.put(data.getLong(), provider.getValue()); + } + return map; + } + + private Map populateStringMap(MapValueProvider provider) { + Map map = new HashMap<>(); + for (int i = 0; i < numRepeatedFields; ++i) { + map.put(data.getString(), provider.getValue()); + } + return map; + } + + private Map populateBooleanMap(MapValueProvider provider) { + Map map = new HashMap<>(); + map.put(false, provider.getValue()); + map.put(true, provider.getValue()); + return map; + } + + public Proto2MessageWithMaps newMessageWithMaps() { + Proto2MessageWithMaps.Builder builder = Proto2MessageWithMaps.newBuilder(); + + builder.putAllFieldMapBoolBool1(populateBooleanMap(booleanProvider)); + builder.putAllFieldMapBoolBytes2(populateBooleanMap(bytesProvider)); + builder.putAllFieldMapBoolDouble3(populateBooleanMap(doubleProvider)); + builder.putAllFieldMapBoolEnum4(populateBooleanMap(enumProvider)); + builder.putAllFieldMapBoolFixed325(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolFixed646(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolFloat7(populateBooleanMap(floatProvider)); + builder.putAllFieldMapBoolInt328(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolInt649(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolMessage10(populateBooleanMap(messageProvider)); + builder.putAllFieldMapBoolSfixed3211(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolSfixed6412(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolSint3213(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolSint6414(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolString15(populateBooleanMap(stringProvider)); + builder.putAllFieldMapBoolUint3216(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolUint6417(populateBooleanMap(longProvider)); + builder.putAllFieldMapFixed32Bool18(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapFixed32Bytes19(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapFixed32Double20(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapFixed32Enum21(populateIntegerMap(enumProvider)); + builder.putAllFieldMapFixed32Fixed3222(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Fixed6423(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32Float24(populateIntegerMap(floatProvider)); + builder.putAllFieldMapFixed32Int3225(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Int6426(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32Message27(populateIntegerMap(messageProvider)); + builder.putAllFieldMapFixed32Sfixed3228(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Sfixed6429(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32Sint3230(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Sint6431(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32String32(populateIntegerMap(stringProvider)); + builder.putAllFieldMapFixed32Uint3233(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Uint6434(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed64Bool35(populateLongMap(booleanProvider)); + builder.putAllFieldMapFixed64Bytes36(populateLongMap(bytesProvider)); + builder.putAllFieldMapFixed64Double37(populateLongMap(doubleProvider)); + builder.putAllFieldMapFixed64Enum38(populateLongMap(enumProvider)); + builder.putAllFieldMapFixed64Fixed3239(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Fixed6440(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64Float41(populateLongMap(floatProvider)); + builder.putAllFieldMapFixed64Int3242(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Int6443(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64Message44(populateLongMap(messageProvider)); + builder.putAllFieldMapFixed64Sfixed3245(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Sfixed6446(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64Sint3247(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Sint6448(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64String49(populateLongMap(stringProvider)); + builder.putAllFieldMapFixed64Uint3250(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Uint6451(populateLongMap(longProvider)); + builder.putAllFieldMapInt32Bool52(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapInt32Bytes53(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapInt32Double54(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapInt32Enum55(populateIntegerMap(enumProvider)); + builder.putAllFieldMapInt32Fixed3256(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Fixed6457(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32Float58(populateIntegerMap(floatProvider)); + builder.putAllFieldMapInt32Int3259(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Int6460(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32Message61(populateIntegerMap(messageProvider)); + builder.putAllFieldMapInt32Sfixed3262(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Sfixed6463(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32Sint3264(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Sint6465(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32String66(populateIntegerMap(stringProvider)); + builder.putAllFieldMapInt32Uint3267(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Uint6468(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt64Bool69(populateLongMap(booleanProvider)); + builder.putAllFieldMapInt64Bytes70(populateLongMap(bytesProvider)); + builder.putAllFieldMapInt64Double71(populateLongMap(doubleProvider)); + builder.putAllFieldMapInt64Enum72(populateLongMap(enumProvider)); + builder.putAllFieldMapInt64Fixed3273(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Fixed6474(populateLongMap(longProvider)); + builder.putAllFieldMapInt64Float75(populateLongMap(floatProvider)); + builder.putAllFieldMapInt64Int3276(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Int6477(populateLongMap(longProvider)); + builder.putAllFieldMapInt64Message78(populateLongMap(messageProvider)); + builder.putAllFieldMapInt64Sfixed3279(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Sfixed6480(populateLongMap(longProvider)); + builder.putAllFieldMapInt64Sint3281(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Sint6482(populateLongMap(longProvider)); + builder.putAllFieldMapInt64String83(populateLongMap(stringProvider)); + builder.putAllFieldMapInt64Uint3284(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Uint6485(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed32Bool86(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapSfixed32Bytes87(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapSfixed32Double88(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapSfixed32Enum89(populateIntegerMap(enumProvider)); + builder.putAllFieldMapSfixed32Fixed3290(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Fixed6491(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32Float92(populateIntegerMap(floatProvider)); + builder.putAllFieldMapSfixed32Int3293(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Int6494(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32Message95(populateIntegerMap(messageProvider)); + builder.putAllFieldMapSfixed32Sfixed3296(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Sfixed6497(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32Sint3298(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Sint6499(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32String100(populateIntegerMap(stringProvider)); + builder.putAllFieldMapSfixed32Uint32101(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Uint64102(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed64Bool103(populateLongMap(booleanProvider)); + builder.putAllFieldMapSfixed64Bytes104(populateLongMap(bytesProvider)); + builder.putAllFieldMapSfixed64Double105(populateLongMap(doubleProvider)); + builder.putAllFieldMapSfixed64Enum106(populateLongMap(enumProvider)); + builder.putAllFieldMapSfixed64Fixed32107(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Fixed64108(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64Float109(populateLongMap(floatProvider)); + builder.putAllFieldMapSfixed64Int32110(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Int64111(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64Message112(populateLongMap(messageProvider)); + builder.putAllFieldMapSfixed64Sfixed32113(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Sfixed64114(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64Sint32115(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Sint64116(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64String117(populateLongMap(stringProvider)); + builder.putAllFieldMapSfixed64Uint32118(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Uint64119(populateLongMap(longProvider)); + builder.putAllFieldMapSint32Bool120(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapSint32Bytes121(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapSint32Double122(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapSint32Enum123(populateIntegerMap(enumProvider)); + builder.putAllFieldMapSint32Fixed32124(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Fixed64125(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32Float126(populateIntegerMap(floatProvider)); + builder.putAllFieldMapSint32Int32127(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Int64128(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32Message129(populateIntegerMap(messageProvider)); + builder.putAllFieldMapSint32Sfixed32130(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Sfixed64131(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32Sint32132(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Sint64133(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32String134(populateIntegerMap(stringProvider)); + builder.putAllFieldMapSint32Uint32135(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Uint64136(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint64Bool137(populateLongMap(booleanProvider)); + builder.putAllFieldMapSint64Bytes138(populateLongMap(bytesProvider)); + builder.putAllFieldMapSint64Double139(populateLongMap(doubleProvider)); + builder.putAllFieldMapSint64Enum140(populateLongMap(enumProvider)); + builder.putAllFieldMapSint64Fixed32141(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Fixed64142(populateLongMap(longProvider)); + builder.putAllFieldMapSint64Float143(populateLongMap(floatProvider)); + builder.putAllFieldMapSint64Int32144(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Int64145(populateLongMap(longProvider)); + builder.putAllFieldMapSint64Message146(populateLongMap(messageProvider)); + builder.putAllFieldMapSint64Sfixed32147(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Sfixed64148(populateLongMap(longProvider)); + builder.putAllFieldMapSint64Sint32149(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Sint64150(populateLongMap(longProvider)); + builder.putAllFieldMapSint64String151(populateLongMap(stringProvider)); + builder.putAllFieldMapSint64Uint32152(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Uint64153(populateLongMap(longProvider)); + builder.putAllFieldMapStringBool154(populateStringMap(booleanProvider)); + builder.putAllFieldMapStringBytes155(populateStringMap(bytesProvider)); + builder.putAllFieldMapStringDouble156(populateStringMap(doubleProvider)); + builder.putAllFieldMapStringEnum157(populateStringMap(enumProvider)); + builder.putAllFieldMapStringFixed32158(populateStringMap(integerProvider)); + builder.putAllFieldMapStringFixed64159(populateStringMap(longProvider)); + builder.putAllFieldMapStringFloat160(populateStringMap(floatProvider)); + builder.putAllFieldMapStringInt32161(populateStringMap(integerProvider)); + builder.putAllFieldMapStringInt64162(populateStringMap(longProvider)); + builder.putAllFieldMapStringMessage163(populateStringMap(messageProvider)); + builder.putAllFieldMapStringSfixed32164(populateStringMap(integerProvider)); + builder.putAllFieldMapStringSfixed64165(populateStringMap(longProvider)); + builder.putAllFieldMapStringSint32166(populateStringMap(integerProvider)); + builder.putAllFieldMapStringSint64167(populateStringMap(longProvider)); + builder.putAllFieldMapStringString168(populateStringMap(stringProvider)); + builder.putAllFieldMapStringUint32169(populateStringMap(integerProvider)); + builder.putAllFieldMapStringUint64170(populateStringMap(longProvider)); + builder.putAllFieldMapUint32Bool171(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapUint32Bytes172(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapUint32Double173(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapUint32Enum174(populateIntegerMap(enumProvider)); + builder.putAllFieldMapUint32Fixed32175(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Fixed64176(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32Float177(populateIntegerMap(floatProvider)); + builder.putAllFieldMapUint32Int32178(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Int64179(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32Message180(populateIntegerMap(messageProvider)); + builder.putAllFieldMapUint32Sfixed32181(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Sfixed64182(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32Sint32183(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Sint64184(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32String185(populateIntegerMap(stringProvider)); + builder.putAllFieldMapUint32Uint32186(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Uint64187(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint64Bool188(populateLongMap(booleanProvider)); + builder.putAllFieldMapUint64Bytes189(populateLongMap(bytesProvider)); + builder.putAllFieldMapUint64Double190(populateLongMap(doubleProvider)); + builder.putAllFieldMapUint64Enum191(populateLongMap(enumProvider)); + builder.putAllFieldMapUint64Fixed32192(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Fixed64193(populateLongMap(longProvider)); + builder.putAllFieldMapUint64Float194(populateLongMap(floatProvider)); + builder.putAllFieldMapUint64Int32195(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Int64196(populateLongMap(longProvider)); + builder.putAllFieldMapUint64Message197(populateLongMap(messageProvider)); + builder.putAllFieldMapUint64Sfixed32198(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Sfixed64199(populateLongMap(longProvider)); + builder.putAllFieldMapUint64Sint32200(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Sint64201(populateLongMap(longProvider)); + builder.putAllFieldMapUint64String202(populateLongMap(stringProvider)); + builder.putAllFieldMapUint64Uint32203(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Uint64204(populateLongMap(longProvider)); + + return builder.build(); + } + + public List newMessagesMissingRequiredFields() { + List results = new ArrayList<>(); + for (int i = 71; i <= 88; ++i) { + Proto2Message.Builder builder = Proto2Message.newBuilder(); + populateRequiredFields(builder, i); + results.add(builder.buildPartial()); + } + { + // A nested optional message field is missing required fields. + Proto2Message.Builder builder = Proto2Message.newBuilder(); + populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS); + builder.setFieldMessage10(Proto2Message.getDefaultInstance()); + results.add(builder.buildPartial()); + } + { + // A nested repeated message field is missing required fields. + Proto2Message.Builder builder = Proto2Message.newBuilder(); + populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS); + builder.addFieldMessageList27(Proto2Message.getDefaultInstance()); + results.add(builder.buildPartial()); + } + { + // A nested oneof message field is missing required fields. + Proto2Message.Builder builder = Proto2Message.newBuilder(); + populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS); + builder.setFieldMessage62(Proto2Message.getDefaultInstance()); + results.add(builder.buildPartial()); + } + return results; + } + + // 0 is not a valid field number so we use it to mean no fields are excluded. + private static final int INCLUDE_ALL_REQUIRED_FIELDS = 0; + + private void populateRequiredFields(Proto2Message.Builder builder, int excludedFieldNumber) { + if (excludedFieldNumber != 71) { + builder.setFieldRequiredDouble71(data.getDouble()); + } + if (excludedFieldNumber != 72) { + builder.setFieldRequiredFloat72(data.getFloat()); + } + if (excludedFieldNumber != 73) { + builder.setFieldRequiredInt6473(data.getLong()); + } + if (excludedFieldNumber != 74) { + builder.setFieldRequiredUint6474(data.getLong()); + } + if (excludedFieldNumber != 75) { + builder.setFieldRequiredInt3275(data.getInt()); + } + if (excludedFieldNumber != 76) { + builder.setFieldRequiredFixed6476(data.getLong()); + } + if (excludedFieldNumber != 77) { + builder.setFieldRequiredFixed3277(data.getInt()); + } + if (excludedFieldNumber != 78) { + builder.setFieldRequiredBool78(data.getBool()); + } + if (excludedFieldNumber != 79) { + builder.setFieldRequiredString79(data.getString()); + } + if (excludedFieldNumber != 80) { + builder.setFieldRequiredMessage80( + Proto2Message.RequiredNestedMessage.newBuilder().setValue(data.getInt())); + } + if (excludedFieldNumber != 81) { + builder.setFieldRequiredBytes81(data.getBytes()); + } + if (excludedFieldNumber != 82) { + builder.setFieldRequiredUint3282(data.getInt()); + } + if (excludedFieldNumber != 83) { + builder.setFieldRequiredEnum83(Proto2Message.TestEnum.forNumber(data.getEnum())); + } + if (excludedFieldNumber != 84) { + builder.setFieldRequiredSfixed3284(data.getInt()); + } + if (excludedFieldNumber != 85) { + builder.setFieldRequiredSfixed6485(data.getLong()); + } + if (excludedFieldNumber != 86) { + builder.setFieldRequiredSint3286(data.getInt()); + } + if (excludedFieldNumber != 87) { + builder.setFieldRequiredSint6487(data.getLong()); + } + if (excludedFieldNumber != 88) { + builder.setFieldRequiredGroup88( + Proto2Message.FieldRequiredGroup88.newBuilder().setFieldInt3289(data.getInt())); + } + } +} diff --git a/java/core/src/test/java/com/google/protobuf/Proto2MessageInfoFactory.java b/java/core/src/test/java/com/google/protobuf/Proto2MessageInfoFactory.java new file mode 100644 index 0000000000000..af671b22e47b8 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Proto2MessageInfoFactory.java @@ -0,0 +1,892 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.FieldInfo.forField; +import static com.google.protobuf.FieldInfo.forFieldWithEnumVerifier; +import static com.google.protobuf.FieldInfo.forMapField; +import static com.google.protobuf.FieldInfo.forOneofMemberField; +import static com.google.protobuf.FieldInfo.forProto2OptionalField; +import static com.google.protobuf.FieldInfo.forProto2RequiredField; +import static com.google.protobuf.FieldInfo.forRepeatedMessageField; + +import com.google.protobuf.testing.Proto2Testing; +import com.google.protobuf.testing.Proto2Testing.Proto2Empty; +import com.google.protobuf.testing.Proto2Testing.Proto2Message; +import com.google.protobuf.testing.Proto2Testing.Proto2Message.FieldGroup49; +import com.google.protobuf.testing.Proto2Testing.Proto2Message.FieldGroup69; +import com.google.protobuf.testing.Proto2Testing.Proto2Message.FieldGroupList51; +import com.google.protobuf.testing.Proto2Testing.Proto2Message.FieldRequiredGroup88; +import com.google.protobuf.testing.Proto2Testing.Proto2Message.RequiredNestedMessage; +import com.google.protobuf.testing.Proto2Testing.Proto2Message.TestEnum; +import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithExtensions; +import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithMaps; +import java.lang.reflect.Field; + +/** A factory that generates a hard-coded message info for {@link Proto2Message}. */ +public final class Proto2MessageInfoFactory implements MessageInfoFactory { + private static final Proto2MessageInfoFactory INSTANCE = new Proto2MessageInfoFactory(); + + private Proto2MessageInfoFactory() {} + + public static Proto2MessageInfoFactory getInstance() { + return INSTANCE; + } + + @Override + public boolean isSupported(Class clazz) { + return true; + } + + @Override + public MessageInfo messageInfoFor(Class clazz) { + if (Proto2Message.class.isAssignableFrom(clazz)) { + return newMessageInfoForProto2Message(); + } else if (FieldGroup49.class.isAssignableFrom(clazz)) { + return newMessageInfoForFieldGroup49(); + } else if (FieldGroupList51.class.isAssignableFrom(clazz)) { + return newMessageInfoForFieldGroupList51(); + } else if (FieldGroup69.class.isAssignableFrom(clazz)) { + return newMessageInfoForFieldGroup69(); + } else if (FieldRequiredGroup88.class.isAssignableFrom(clazz)) { + return newMessageInfoForFieldRequiredGroup88(); + } else if (RequiredNestedMessage.class.isAssignableFrom(clazz)) { + return newMessageInfoForRequiredNestedMessage(); + } else if (Proto2Empty.class.isAssignableFrom(clazz)) { + return newMessageInfoForProto2Empty(); + } else if (Proto2MessageWithExtensions.class.isAssignableFrom(clazz)) { + return newMessageInfoForProto2MessageWithExtensions(); + } else if (Proto2Testing.FieldGroup49.class.isAssignableFrom(clazz)) { + return newMessageInfoForExtensionFieldGroup49(); + } else if (Proto2Testing.FieldGroupList51.class.isAssignableFrom(clazz)) { + return newMessageInfoForExtensionFieldGroupList51(); + } else if (Proto2Testing.Proto2MessageWithMaps.class.isAssignableFrom(clazz)) { + return newMessageInfoForProto2MessageWithMaps(); + } else { + throw new IllegalArgumentException("Unsupported class: " + clazz.getName()); + } + } + + /** + * Creates a new hard-coded info for {@link Proto2Message}. Each time this is called, we manually + * go through the entire process of what a message would do if it self-registered its own info, + * including looking up each field by name. This is done for benchmarking purposes, so that we get + * a more accurate representation of the time it takes to perform this process. + */ + private static StructuralMessageInfo newMessageInfoForProto2Message() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(50); + builder.withCheckInitialized( + new int[] { + 10, 27, 62, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + }); + lookupFieldsByName(builder); + return builder.build(); + } + + private static void lookupFieldsByName(StructuralMessageInfo.Builder builder) { + Field bitField0 = field("bitField0_"); + + builder.withDefaultInstance(Proto2Message.getDefaultInstance()); + builder.withSyntax(ProtoSyntax.PROTO2); + builder.withField( + forProto2OptionalField( + field("fieldDouble1_"), 1, FieldType.DOUBLE, bitField0, 0x00000001, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldFloat2_"), 2, FieldType.FLOAT, bitField0, 0x00000002, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldInt643_"), 3, FieldType.INT64, bitField0, 0x00000004, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldUint644_"), 4, FieldType.UINT64, bitField0, 0x00000008, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldInt325_"), 5, FieldType.INT32, bitField0, 0x00000010, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldFixed646_"), 6, FieldType.FIXED64, bitField0, 0x00000020, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldFixed327_"), 7, FieldType.FIXED32, bitField0, 0x00000040, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldBool8_"), 8, FieldType.BOOL, bitField0, 0x00000080, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldString9_"), 9, FieldType.STRING, bitField0, 0x00000100, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldMessage10_"), 10, FieldType.MESSAGE, bitField0, 0x00000200, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldBytes11_"), 11, FieldType.BYTES, bitField0, 0x00000400, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldUint3212_"), 12, FieldType.UINT32, bitField0, 0x00000800, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldEnum13_"), + 13, + FieldType.ENUM, + bitField0, + 0x00001000, + false, + asVerifier(TestEnum.internalGetValueMap()))); + builder.withField( + forProto2OptionalField( + field("fieldSfixed3214_"), 14, FieldType.SFIXED32, bitField0, 0x00002000, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldSfixed6415_"), 15, FieldType.SFIXED64, bitField0, 0x00004000, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldSint3216_"), 16, FieldType.SINT32, bitField0, 0x00008000, false, null)); + builder.withField( + forProto2OptionalField( + field("fieldSint6417_"), 17, FieldType.SINT64, bitField0, 0x00010000, false, null)); + builder.withField(forField(field("fieldDoubleList18_"), 18, FieldType.DOUBLE_LIST, false)); + builder.withField(forField(field("fieldFloatList19_"), 19, FieldType.FLOAT_LIST, false)); + builder.withField(forField(field("fieldInt64List20_"), 20, FieldType.INT64_LIST, false)); + builder.withField(forField(field("fieldUint64List21_"), 21, FieldType.UINT64_LIST, false)); + builder.withField(forField(field("fieldInt32List22_"), 22, FieldType.INT32_LIST, false)); + builder.withField(forField(field("fieldFixed64List23_"), 23, FieldType.FIXED64_LIST, false)); + builder.withField(forField(field("fieldFixed32List24_"), 24, FieldType.FIXED32_LIST, false)); + builder.withField(forField(field("fieldBoolList25_"), 25, FieldType.BOOL_LIST, false)); + builder.withField(forField(field("fieldStringList26_"), 26, FieldType.STRING_LIST, false)); + builder.withField( + forRepeatedMessageField( + field("fieldMessageList27_"), 27, FieldType.MESSAGE_LIST, Proto2Message.class)); + builder.withField(forField(field("fieldBytesList28_"), 28, FieldType.BYTES_LIST, false)); + builder.withField(forField(field("fieldUint32List29_"), 29, FieldType.UINT32_LIST, false)); + builder.withField( + forFieldWithEnumVerifier( + field("fieldEnumList30_"), + 30, + FieldType.ENUM_LIST, + asVerifier(TestEnum.internalGetValueMap()))); + builder.withField(forField(field("fieldSfixed32List31_"), 31, FieldType.SFIXED32_LIST, false)); + builder.withField(forField(field("fieldSfixed64List32_"), 32, FieldType.SFIXED64_LIST, false)); + builder.withField(forField(field("fieldSint32List33_"), 33, FieldType.SINT32_LIST, false)); + builder.withField(forField(field("fieldSint64List34_"), 34, FieldType.SINT64_LIST, false)); + builder.withField( + forField(field("fieldDoubleListPacked35_"), 35, FieldType.DOUBLE_LIST_PACKED, false)); + builder.withField( + forField(field("fieldFloatListPacked36_"), 36, FieldType.FLOAT_LIST_PACKED, false)); + builder.withField( + forField(field("fieldInt64ListPacked37_"), 37, FieldType.INT64_LIST_PACKED, false)); + builder.withField( + forField(field("fieldUint64ListPacked38_"), 38, FieldType.UINT64_LIST_PACKED, false)); + builder.withField( + forField(field("fieldInt32ListPacked39_"), 39, FieldType.INT32_LIST_PACKED, false)); + builder.withField( + forField(field("fieldFixed64ListPacked40_"), 40, FieldType.FIXED64_LIST_PACKED, false)); + builder.withField( + forField(field("fieldFixed32ListPacked41_"), 41, FieldType.FIXED32_LIST_PACKED, false)); + builder.withField( + forField(field("fieldBoolListPacked42_"), 42, FieldType.BOOL_LIST_PACKED, false)); + builder.withField( + forField(field("fieldUint32ListPacked43_"), 43, FieldType.UINT32_LIST_PACKED, false)); + builder.withField( + forFieldWithEnumVerifier( + field("fieldEnumListPacked44_"), + 44, + FieldType.ENUM_LIST_PACKED, + asVerifier(TestEnum.internalGetValueMap()))); + builder.withField( + forField(field("fieldSfixed32ListPacked45_"), 45, FieldType.SFIXED32_LIST_PACKED, false)); + builder.withField( + forField(field("fieldSfixed64ListPacked46_"), 46, FieldType.SFIXED64_LIST_PACKED, false)); + builder.withField( + forField(field("fieldSint32ListPacked47_"), 47, FieldType.SINT32_LIST_PACKED, false)); + builder.withField( + forField(field("fieldSint64ListPacked48_"), 48, FieldType.SINT64_LIST_PACKED, false)); + + builder.withField( + forProto2OptionalField( + field("fieldGroup49_"), 49, FieldType.GROUP, bitField0, 0x00020000, false, null)); + builder.withField( + forRepeatedMessageField( + field("fieldGroupList51_"), + 51, + FieldType.GROUP_LIST, + Proto2Message.FieldGroupList51.class)); + + OneofInfo oneof = new OneofInfo(0, field("testOneofCase_"), field("testOneof_")); + builder.withField(forOneofMemberField(53, FieldType.DOUBLE, oneof, Double.class, false, null)); + builder.withField(forOneofMemberField(54, FieldType.FLOAT, oneof, Float.class, false, null)); + builder.withField(forOneofMemberField(55, FieldType.INT64, oneof, Long.class, false, null)); + builder.withField(forOneofMemberField(56, FieldType.UINT64, oneof, Long.class, false, null)); + builder.withField(forOneofMemberField(57, FieldType.INT32, oneof, Integer.class, false, null)); + builder.withField(forOneofMemberField(58, FieldType.FIXED64, oneof, Long.class, false, null)); + builder.withField( + forOneofMemberField(59, FieldType.FIXED32, oneof, Integer.class, false, null)); + builder.withField(forOneofMemberField(60, FieldType.BOOL, oneof, Boolean.class, false, null)); + builder.withField(forOneofMemberField(61, FieldType.STRING, oneof, String.class, false, null)); + builder.withField( + forOneofMemberField(62, FieldType.MESSAGE, oneof, Proto2Message.class, false, null)); + builder.withField( + forOneofMemberField(63, FieldType.BYTES, oneof, ByteString.class, false, null)); + builder.withField(forOneofMemberField(64, FieldType.UINT32, oneof, Integer.class, false, null)); + builder.withField( + forOneofMemberField(65, FieldType.SFIXED32, oneof, Integer.class, false, null)); + builder.withField(forOneofMemberField(66, FieldType.SFIXED64, oneof, Long.class, false, null)); + builder.withField(forOneofMemberField(67, FieldType.SINT32, oneof, Integer.class, false, null)); + builder.withField(forOneofMemberField(68, FieldType.SINT64, oneof, Long.class, false, null)); + builder.withField( + forOneofMemberField( + 69, FieldType.GROUP, oneof, Proto2Message.FieldGroup69.class, false, null)); + + Field bitField1 = field("bitField1_"); + builder.withField( + forProto2RequiredField( + field("fieldRequiredDouble71_"), + 71, + FieldType.DOUBLE, + bitField1, + 0x00000008, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredFloat72_"), + 72, + FieldType.FLOAT, + bitField1, + 0x00000010, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredInt6473_"), + 73, + FieldType.INT64, + bitField1, + 0x00000020, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredUint6474_"), + 74, + FieldType.UINT64, + bitField1, + 0x00000040, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredInt3275_"), + 75, + FieldType.INT32, + bitField1, + 0x00000080, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredFixed6476_"), + 76, + FieldType.FIXED64, + bitField1, + 0x00000100, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredFixed3277_"), + 77, + FieldType.FIXED32, + bitField1, + 0x00000200, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredBool78_"), 78, FieldType.BOOL, bitField1, 0x00000400, false, null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredString79_"), + 79, + FieldType.STRING, + bitField1, + 0x00000800, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredMessage80_"), + 80, + FieldType.MESSAGE, + bitField1, + 0x00001000, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredBytes81_"), + 81, + FieldType.BYTES, + bitField1, + 0x00002000, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredUint3282_"), + 82, + FieldType.UINT32, + bitField1, + 0x00004000, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredEnum83_"), + 83, + FieldType.ENUM, + bitField1, + 0x00008000, + false, + asVerifier(TestEnum.internalGetValueMap()))); + builder.withField( + forProto2RequiredField( + field("fieldRequiredSfixed3284_"), + 84, + FieldType.SFIXED32, + bitField1, + 0x00010000, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredSfixed6485_"), + 85, + FieldType.SFIXED64, + bitField1, + 0x00020000, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredSint3286_"), + 86, + FieldType.SINT32, + bitField1, + 0x00040000, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredSint6487_"), + 87, + FieldType.SINT64, + bitField1, + 0x00080000, + false, + null)); + builder.withField( + forProto2RequiredField( + field("fieldRequiredGroup88_"), + 88, + FieldType.GROUP, + bitField1, + 0x00100000, + false, + null)); + } + + private static StructuralMessageInfo newMessageInfoForFieldGroup49() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + Field bitField0 = field(FieldGroup49.class, "bitField0_"); + builder.withField( + forProto2OptionalField( + field(FieldGroup49.class, "fieldInt3250_"), + 50, + FieldType.INT32, + bitField0, + 0x00000001, + false, + null)); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForFieldGroupList51() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + Field bitField0 = field(FieldGroupList51.class, "bitField0_"); + builder.withField( + forProto2OptionalField( + field(FieldGroupList51.class, "fieldInt3252_"), + 52, + FieldType.INT32, + bitField0, + 0x00000001, + false, + null)); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForFieldGroup69() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + Field bitField0 = field(FieldGroup69.class, "bitField0_"); + builder.withField( + forProto2OptionalField( + field(FieldGroup69.class, "fieldInt3270_"), + 70, + FieldType.INT32, + bitField0, + 0x00000001, + false, + null)); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForRequiredNestedMessage() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + Field bitField0 = field(RequiredNestedMessage.class, "bitField0_"); + builder.withField( + forProto2OptionalField( + field(RequiredNestedMessage.class, "value_"), + 1, + FieldType.INT32, + bitField0, + 0x00000001, + false, + null)); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForFieldRequiredGroup88() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + Field bitField0 = field(FieldRequiredGroup88.class, "bitField0_"); + builder.withField( + forProto2OptionalField( + field(FieldRequiredGroup88.class, "fieldInt3289_"), + 89, + FieldType.INT32, + bitField0, + 0x00000001, + false, + null)); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForProto2Empty() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForProto2MessageWithExtensions() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(0); + builder.withSyntax(ProtoSyntax.PROTO2); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForExtensionFieldGroup49() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + Field bitField0 = field(Proto2Testing.FieldGroup49.class, "bitField0_"); + builder.withField( + forProto2OptionalField( + field(Proto2Testing.FieldGroup49.class, "fieldInt3250_"), + 50, + FieldType.INT32, + bitField0, + 0x00000001, + false, + null)); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForExtensionFieldGroupList51() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + Field bitField0 = field(Proto2Testing.FieldGroupList51.class, "bitField0_"); + builder.withField( + forProto2OptionalField( + field(Proto2Testing.FieldGroupList51.class, "fieldInt3252_"), + 52, + FieldType.INT32, + bitField0, + 0x00000001, + false, + null)); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForProto2MessageWithMaps() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(); + builder.withCheckInitialized( + new int[] { + 10, 27, 44, 61, 78, 95, 112, 129, 146, 163, 180, 197, + }); + builder.withSyntax(ProtoSyntax.PROTO2); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_bool_1", 1)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_bytes_2", 2)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_double_3", 3)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_enum_4", 4)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_fixed32_5", 5)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_fixed64_6", 6)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_float_7", 7)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_int32_8", 8)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_int64_9", 9)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_message_10", 10)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_sfixed32_11", 11)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_sfixed64_12", 12)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_sint32_13", 13)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_sint64_14", 14)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_string_15", 15)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_uint32_16", 16)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_uint64_17", 17)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_bool_18", 18)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_bytes_19", 19)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_double_20", 20)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_enum_21", 21)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_fixed32_22", 22)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_fixed64_23", 23)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_float_24", 24)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_int32_25", 25)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_int64_26", 26)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_message_27", 27)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_sfixed32_28", 28)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_sfixed64_29", 29)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_sint32_30", 30)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_sint64_31", 31)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_string_32", 32)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_uint32_33", 33)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_uint64_34", 34)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_bool_35", 35)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_bytes_36", 36)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_double_37", 37)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_enum_38", 38)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_fixed32_39", 39)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_fixed64_40", 40)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_float_41", 41)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_int32_42", 42)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_int64_43", 43)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_message_44", 44)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_sfixed32_45", 45)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_sfixed64_46", 46)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_sint32_47", 47)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_sint64_48", 48)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_string_49", 49)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_uint32_50", 50)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_uint64_51", 51)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_bool_52", 52)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_bytes_53", 53)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_double_54", 54)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_enum_55", 55)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_fixed32_56", 56)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_fixed64_57", 57)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_float_58", 58)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_int32_59", 59)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_int64_60", 60)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_message_61", 61)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_sfixed32_62", 62)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_sfixed64_63", 63)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_sint32_64", 64)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_sint64_65", 65)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_string_66", 66)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_uint32_67", 67)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_uint64_68", 68)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_bool_69", 69)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_bytes_70", 70)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_double_71", 71)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_enum_72", 72)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_fixed32_73", 73)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_fixed64_74", 74)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_float_75", 75)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_int32_76", 76)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_int64_77", 77)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_message_78", 78)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_sfixed32_79", 79)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_sfixed64_80", 80)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_sint32_81", 81)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_sint64_82", 82)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_string_83", 83)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_uint32_84", 84)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_uint64_85", 85)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_bool_86", 86)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_bytes_87", 87)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_double_88", 88)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_enum_89", 89)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_fixed32_90", 90)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_fixed64_91", 91)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_float_92", 92)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_int32_93", 93)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_int64_94", 94)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_message_95", 95)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_sfixed32_96", 96)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_sfixed64_97", 97)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_sint32_98", 98)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_sint64_99", 99)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_string_100", 100)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_uint32_101", 101)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_uint64_102", 102)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_bool_103", 103)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_bytes_104", 104)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_double_105", 105)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_enum_106", 106)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_fixed32_107", 107)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_fixed64_108", 108)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_float_109", 109)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_int32_110", 110)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_int64_111", 111)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_message_112", 112)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_sfixed32_113", 113)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_sfixed64_114", 114)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_sint32_115", 115)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_sint64_116", 116)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_string_117", 117)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_uint32_118", 118)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_uint64_119", 119)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_bool_120", 120)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_bytes_121", 121)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_double_122", 122)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_enum_123", 123)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_fixed32_124", 124)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_fixed64_125", 125)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_float_126", 126)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_int32_127", 127)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_int64_128", 128)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_message_129", 129)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_sfixed32_130", 130)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_sfixed64_131", 131)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_sint32_132", 132)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_sint64_133", 133)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_string_134", 134)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_uint32_135", 135)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_uint64_136", 136)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_bool_137", 137)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_bytes_138", 138)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_double_139", 139)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_enum_140", 140)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_fixed32_141", 141)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_fixed64_142", 142)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_float_143", 143)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_int32_144", 144)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_int64_145", 145)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_message_146", 146)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_sfixed32_147", 147)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_sfixed64_148", 148)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_sint32_149", 149)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_sint64_150", 150)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_string_151", 151)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_uint32_152", 152)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_uint64_153", 153)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_bool_154", 154)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_bytes_155", 155)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_double_156", 156)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_enum_157", 157)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_fixed32_158", 158)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_fixed64_159", 159)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_float_160", 160)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_int32_161", 161)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_int64_162", 162)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_message_163", 163)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_sfixed32_164", 164)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_sfixed64_165", 165)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_sint32_166", 166)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_sint64_167", 167)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_string_168", 168)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_uint32_169", 169)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_uint64_170", 170)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_bool_171", 171)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_bytes_172", 172)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_double_173", 173)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_enum_174", 174)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_fixed32_175", 175)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_fixed64_176", 176)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_float_177", 177)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_int32_178", 178)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_int64_179", 179)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_message_180", 180)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_sfixed32_181", 181)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_sfixed64_182", 182)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_sint32_183", 183)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_sint64_184", 184)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_string_185", 185)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_uint32_186", 186)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_uint64_187", 187)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_bool_188", 188)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_bytes_189", 189)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_double_190", 190)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_enum_191", 191)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_fixed32_192", 192)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_fixed64_193", 193)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_float_194", 194)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_int32_195", 195)); + builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_int64_196", 196)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_message_197", 197)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_sfixed32_198", 198)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_sfixed64_199", 199)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_sint32_200", 200)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_sint64_201", 201)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_string_202", 202)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_uint32_203", 203)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_uint64_204", 204)); + + return builder.build(); + } + + private static FieldInfo mapFieldInfo(Class clazz, String fieldName, int fieldNumber) { + try { + return forMapField( + field(clazz, SchemaUtil.toCamelCase(fieldName, false) + "_"), + fieldNumber, + SchemaUtil.getMapDefaultEntry(clazz, fieldName), + fieldName.contains("_enum_") ? asVerifier(TestEnum.internalGetValueMap()) : null); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + + + private static Field field(String name) { + return field(Proto2Message.class, name); + } + + private static Field field(Class clazz, String name) { + try { + return clazz.getDeclaredField(name); + } catch (NoSuchFieldException | SecurityException e) { + throw new RuntimeException(e); + } + } + + private static Internal.EnumVerifier asVerifier(final Internal.EnumLiteMap map) { + return new Internal.EnumVerifier() { + @Override + public boolean isInRange(int number) { + return map.findValueByNumber(number) != null; + } + }; + } +} diff --git a/java/core/src/test/java/com/google/protobuf/Proto2MessageLiteFactory.java b/java/core/src/test/java/com/google/protobuf/Proto2MessageLiteFactory.java new file mode 100644 index 0000000000000..2da349424edc3 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Proto2MessageLiteFactory.java @@ -0,0 +1,558 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLiteWithMaps; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** Creates instances of {@link Proto2MessageLite} based on the tree configuration. */ +public final class Proto2MessageLiteFactory + implements ExperimentalMessageFactory { + private final int numRepeatedFields; + private final int branchingFactor; + private final Proto2MessageLiteFactory nextLevel; + private final ExperimentalTestDataProvider data; + + public Proto2MessageLiteFactory( + int numRepeatedFields, int stringLength, int branchingFactor, int treeDepth) { + this( + new ExperimentalTestDataProvider(stringLength), + numRepeatedFields, + branchingFactor, + treeDepth); + } + + private Proto2MessageLiteFactory( + ExperimentalTestDataProvider data, + int numRepeatedFields, + int branchingFactor, + int treeDepth) { + this.numRepeatedFields = numRepeatedFields; + this.branchingFactor = branchingFactor; + this.data = data; + if (treeDepth > 0) { + nextLevel = + new Proto2MessageLiteFactory(data, numRepeatedFields, branchingFactor, treeDepth - 1); + } else { + nextLevel = null; + } + } + + @Override + public ExperimentalTestDataProvider dataProvider() { + return data; + } + + @Override + public Proto2MessageLite newMessage() { + Proto2MessageLite.Builder builder = Proto2MessageLite.newBuilder(); + builder.setFieldDouble1(data.getDouble()); + builder.setFieldFloat2(data.getFloat()); + builder.setFieldInt643(data.getLong()); + builder.setFieldUint644(data.getLong()); + builder.setFieldInt325(data.getInt()); + builder.setFieldFixed646(data.getLong()); + builder.setFieldFixed327(data.getInt()); + builder.setFieldBool8(data.getBool()); + builder.setFieldString9(data.getString()); + // We don't populate the message field. Instead we apply the branching factor to the + // repeated message field below. + builder.setFieldBytes11(data.getBytes()); + builder.setFieldUint3212(data.getInt()); + builder.setFieldEnum13(Proto2MessageLite.TestEnum.forNumber(data.getEnum())); + builder.setFieldSfixed3214(data.getInt()); + builder.setFieldSfixed6415(data.getLong()); + builder.setFieldSint3216(data.getInt()); + builder.setFieldSint6417(data.getLong()); + + for (int i = 0; i < numRepeatedFields; ++i) { + builder.addFieldDoubleList18(data.getDouble()); + builder.addFieldFloatList19(data.getFloat()); + builder.addFieldInt64List20(data.getLong()); + builder.addFieldUint64List21(data.getLong()); + builder.addFieldInt32List22(data.getInt()); + builder.addFieldFixed64List23(data.getLong()); + builder.addFieldFixed32List24(data.getInt()); + builder.addFieldBoolList25(data.getBool()); + builder.addFieldStringList26(data.getString()); + // Repeated message field is controlled by the branching factor below. + builder.addFieldBytesList28(data.getBytes()); + builder.addFieldUint32List29(data.getInt()); + builder.addFieldEnumList30(Proto2MessageLite.TestEnum.forNumber(data.getEnum())); + builder.addFieldSfixed32List31(data.getInt()); + builder.addFieldSfixed64List32(data.getLong()); + builder.addFieldSint32List33(data.getInt()); + builder.addFieldSint64List34(data.getLong()); + + builder.addFieldDoubleListPacked35(data.getDouble()); + builder.addFieldFloatListPacked36(data.getFloat()); + builder.addFieldInt64ListPacked37(data.getLong()); + builder.addFieldUint64ListPacked38(data.getLong()); + builder.addFieldInt32ListPacked39(data.getInt()); + builder.addFieldFixed64ListPacked40(data.getLong()); + builder.addFieldFixed32ListPacked41(data.getInt()); + builder.addFieldBoolListPacked42(data.getBool()); + builder.addFieldUint32ListPacked43(data.getInt()); + builder.addFieldEnumListPacked44(Proto2MessageLite.TestEnum.forNumber(data.getEnum())); + builder.addFieldSfixed32ListPacked45(data.getInt()); + builder.addFieldSfixed64ListPacked46(data.getLong()); + builder.addFieldSint32ListPacked47(data.getInt()); + builder.addFieldSint64ListPacked48(data.getLong()); + } + + builder.setFieldGroup49( + Proto2MessageLite.FieldGroup49.newBuilder().setFieldInt3250(data.getInt())); + + for (int i = 0; i < branchingFactor; ++i) { + builder.addFieldGroupList51( + Proto2MessageLite.FieldGroupList51.newBuilder().setFieldInt3252(data.getInt())); + } + + // Set all required fields. + populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS); + + // Handle the branching factor. + if (nextLevel != null) { + for (int i = 0; i < branchingFactor; ++i) { + builder.addFieldMessageList27(nextLevel.newMessage()); + } + } + + return builder.build(); + } + + private interface MapValueProvider { + public T getValue(); + } + + private final MapValueProvider integerProvider = + new MapValueProvider() { + @Override + public Integer getValue() { + return data.getInt(); + } + }; + private final MapValueProvider longProvider = + new MapValueProvider() { + @Override + public Long getValue() { + return data.getLong(); + } + }; + private final MapValueProvider stringProvider = + new MapValueProvider() { + @Override + public String getValue() { + return data.getString(); + } + }; + private final MapValueProvider bytesProvider = + new MapValueProvider() { + @Override + public ByteString getValue() { + return data.getBytes(); + } + }; + private final MapValueProvider booleanProvider = + new MapValueProvider() { + @Override + public Boolean getValue() { + return data.getBool(); + } + }; + private final MapValueProvider floatProvider = + new MapValueProvider() { + @Override + public Float getValue() { + return data.getFloat(); + } + }; + private final MapValueProvider doubleProvider = + new MapValueProvider() { + @Override + public Double getValue() { + return data.getDouble(); + } + }; + private final MapValueProvider messageProvider = + new MapValueProvider() { + @Override + public Proto2MessageLite getValue() { + return newMessage(); + } + }; + private final MapValueProvider enumProvider = + new MapValueProvider() { + @Override + public Proto2MessageLite.TestEnum getValue() { + return Proto2MessageLite.TestEnum.forNumber(data.getEnum()); + } + }; + + private Map populateIntegerMap(MapValueProvider provider) { + Map map = new HashMap<>(); + for (int i = 0; i < numRepeatedFields; ++i) { + map.put(data.getInt(), provider.getValue()); + } + return map; + } + + private Map populateLongMap(MapValueProvider provider) { + Map map = new HashMap<>(); + for (int i = 0; i < numRepeatedFields; ++i) { + map.put(data.getLong(), provider.getValue()); + } + return map; + } + + private Map populateStringMap(MapValueProvider provider) { + Map map = new HashMap<>(); + for (int i = 0; i < numRepeatedFields; ++i) { + map.put(data.getString(), provider.getValue()); + } + return map; + } + + private Map populateBooleanMap(MapValueProvider provider) { + Map map = new HashMap<>(); + map.put(false, provider.getValue()); + map.put(true, provider.getValue()); + return map; + } + + public Proto2MessageLiteWithMaps newMessageWithMaps() { + Proto2MessageLiteWithMaps.Builder builder = Proto2MessageLiteWithMaps.newBuilder(); + + builder.putAllFieldMapBoolBool1(populateBooleanMap(booleanProvider)); + builder.putAllFieldMapBoolBytes2(populateBooleanMap(bytesProvider)); + builder.putAllFieldMapBoolDouble3(populateBooleanMap(doubleProvider)); + builder.putAllFieldMapBoolEnum4(populateBooleanMap(enumProvider)); + builder.putAllFieldMapBoolFixed325(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolFixed646(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolFloat7(populateBooleanMap(floatProvider)); + builder.putAllFieldMapBoolInt328(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolInt649(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolMessage10(populateBooleanMap(messageProvider)); + builder.putAllFieldMapBoolSfixed3211(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolSfixed6412(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolSint3213(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolSint6414(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolString15(populateBooleanMap(stringProvider)); + builder.putAllFieldMapBoolUint3216(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolUint6417(populateBooleanMap(longProvider)); + builder.putAllFieldMapFixed32Bool18(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapFixed32Bytes19(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapFixed32Double20(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapFixed32Enum21(populateIntegerMap(enumProvider)); + builder.putAllFieldMapFixed32Fixed3222(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Fixed6423(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32Float24(populateIntegerMap(floatProvider)); + builder.putAllFieldMapFixed32Int3225(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Int6426(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32Message27(populateIntegerMap(messageProvider)); + builder.putAllFieldMapFixed32Sfixed3228(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Sfixed6429(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32Sint3230(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Sint6431(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32String32(populateIntegerMap(stringProvider)); + builder.putAllFieldMapFixed32Uint3233(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Uint6434(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed64Bool35(populateLongMap(booleanProvider)); + builder.putAllFieldMapFixed64Bytes36(populateLongMap(bytesProvider)); + builder.putAllFieldMapFixed64Double37(populateLongMap(doubleProvider)); + builder.putAllFieldMapFixed64Enum38(populateLongMap(enumProvider)); + builder.putAllFieldMapFixed64Fixed3239(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Fixed6440(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64Float41(populateLongMap(floatProvider)); + builder.putAllFieldMapFixed64Int3242(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Int6443(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64Message44(populateLongMap(messageProvider)); + builder.putAllFieldMapFixed64Sfixed3245(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Sfixed6446(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64Sint3247(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Sint6448(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64String49(populateLongMap(stringProvider)); + builder.putAllFieldMapFixed64Uint3250(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Uint6451(populateLongMap(longProvider)); + builder.putAllFieldMapInt32Bool52(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapInt32Bytes53(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapInt32Double54(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapInt32Enum55(populateIntegerMap(enumProvider)); + builder.putAllFieldMapInt32Fixed3256(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Fixed6457(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32Float58(populateIntegerMap(floatProvider)); + builder.putAllFieldMapInt32Int3259(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Int6460(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32Message61(populateIntegerMap(messageProvider)); + builder.putAllFieldMapInt32Sfixed3262(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Sfixed6463(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32Sint3264(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Sint6465(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32String66(populateIntegerMap(stringProvider)); + builder.putAllFieldMapInt32Uint3267(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Uint6468(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt64Bool69(populateLongMap(booleanProvider)); + builder.putAllFieldMapInt64Bytes70(populateLongMap(bytesProvider)); + builder.putAllFieldMapInt64Double71(populateLongMap(doubleProvider)); + builder.putAllFieldMapInt64Enum72(populateLongMap(enumProvider)); + builder.putAllFieldMapInt64Fixed3273(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Fixed6474(populateLongMap(longProvider)); + builder.putAllFieldMapInt64Float75(populateLongMap(floatProvider)); + builder.putAllFieldMapInt64Int3276(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Int6477(populateLongMap(longProvider)); + builder.putAllFieldMapInt64Message78(populateLongMap(messageProvider)); + builder.putAllFieldMapInt64Sfixed3279(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Sfixed6480(populateLongMap(longProvider)); + builder.putAllFieldMapInt64Sint3281(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Sint6482(populateLongMap(longProvider)); + builder.putAllFieldMapInt64String83(populateLongMap(stringProvider)); + builder.putAllFieldMapInt64Uint3284(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Uint6485(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed32Bool86(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapSfixed32Bytes87(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapSfixed32Double88(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapSfixed32Enum89(populateIntegerMap(enumProvider)); + builder.putAllFieldMapSfixed32Fixed3290(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Fixed6491(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32Float92(populateIntegerMap(floatProvider)); + builder.putAllFieldMapSfixed32Int3293(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Int6494(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32Message95(populateIntegerMap(messageProvider)); + builder.putAllFieldMapSfixed32Sfixed3296(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Sfixed6497(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32Sint3298(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Sint6499(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32String100(populateIntegerMap(stringProvider)); + builder.putAllFieldMapSfixed32Uint32101(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Uint64102(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed64Bool103(populateLongMap(booleanProvider)); + builder.putAllFieldMapSfixed64Bytes104(populateLongMap(bytesProvider)); + builder.putAllFieldMapSfixed64Double105(populateLongMap(doubleProvider)); + builder.putAllFieldMapSfixed64Enum106(populateLongMap(enumProvider)); + builder.putAllFieldMapSfixed64Fixed32107(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Fixed64108(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64Float109(populateLongMap(floatProvider)); + builder.putAllFieldMapSfixed64Int32110(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Int64111(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64Message112(populateLongMap(messageProvider)); + builder.putAllFieldMapSfixed64Sfixed32113(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Sfixed64114(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64Sint32115(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Sint64116(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64String117(populateLongMap(stringProvider)); + builder.putAllFieldMapSfixed64Uint32118(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Uint64119(populateLongMap(longProvider)); + builder.putAllFieldMapSint32Bool120(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapSint32Bytes121(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapSint32Double122(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapSint32Enum123(populateIntegerMap(enumProvider)); + builder.putAllFieldMapSint32Fixed32124(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Fixed64125(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32Float126(populateIntegerMap(floatProvider)); + builder.putAllFieldMapSint32Int32127(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Int64128(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32Message129(populateIntegerMap(messageProvider)); + builder.putAllFieldMapSint32Sfixed32130(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Sfixed64131(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32Sint32132(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Sint64133(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32String134(populateIntegerMap(stringProvider)); + builder.putAllFieldMapSint32Uint32135(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Uint64136(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint64Bool137(populateLongMap(booleanProvider)); + builder.putAllFieldMapSint64Bytes138(populateLongMap(bytesProvider)); + builder.putAllFieldMapSint64Double139(populateLongMap(doubleProvider)); + builder.putAllFieldMapSint64Enum140(populateLongMap(enumProvider)); + builder.putAllFieldMapSint64Fixed32141(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Fixed64142(populateLongMap(longProvider)); + builder.putAllFieldMapSint64Float143(populateLongMap(floatProvider)); + builder.putAllFieldMapSint64Int32144(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Int64145(populateLongMap(longProvider)); + builder.putAllFieldMapSint64Message146(populateLongMap(messageProvider)); + builder.putAllFieldMapSint64Sfixed32147(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Sfixed64148(populateLongMap(longProvider)); + builder.putAllFieldMapSint64Sint32149(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Sint64150(populateLongMap(longProvider)); + builder.putAllFieldMapSint64String151(populateLongMap(stringProvider)); + builder.putAllFieldMapSint64Uint32152(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Uint64153(populateLongMap(longProvider)); + builder.putAllFieldMapStringBool154(populateStringMap(booleanProvider)); + builder.putAllFieldMapStringBytes155(populateStringMap(bytesProvider)); + builder.putAllFieldMapStringDouble156(populateStringMap(doubleProvider)); + builder.putAllFieldMapStringEnum157(populateStringMap(enumProvider)); + builder.putAllFieldMapStringFixed32158(populateStringMap(integerProvider)); + builder.putAllFieldMapStringFixed64159(populateStringMap(longProvider)); + builder.putAllFieldMapStringFloat160(populateStringMap(floatProvider)); + builder.putAllFieldMapStringInt32161(populateStringMap(integerProvider)); + builder.putAllFieldMapStringInt64162(populateStringMap(longProvider)); + builder.putAllFieldMapStringMessage163(populateStringMap(messageProvider)); + builder.putAllFieldMapStringSfixed32164(populateStringMap(integerProvider)); + builder.putAllFieldMapStringSfixed64165(populateStringMap(longProvider)); + builder.putAllFieldMapStringSint32166(populateStringMap(integerProvider)); + builder.putAllFieldMapStringSint64167(populateStringMap(longProvider)); + builder.putAllFieldMapStringString168(populateStringMap(stringProvider)); + builder.putAllFieldMapStringUint32169(populateStringMap(integerProvider)); + builder.putAllFieldMapStringUint64170(populateStringMap(longProvider)); + builder.putAllFieldMapUint32Bool171(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapUint32Bytes172(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapUint32Double173(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapUint32Enum174(populateIntegerMap(enumProvider)); + builder.putAllFieldMapUint32Fixed32175(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Fixed64176(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32Float177(populateIntegerMap(floatProvider)); + builder.putAllFieldMapUint32Int32178(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Int64179(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32Message180(populateIntegerMap(messageProvider)); + builder.putAllFieldMapUint32Sfixed32181(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Sfixed64182(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32Sint32183(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Sint64184(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32String185(populateIntegerMap(stringProvider)); + builder.putAllFieldMapUint32Uint32186(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Uint64187(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint64Bool188(populateLongMap(booleanProvider)); + builder.putAllFieldMapUint64Bytes189(populateLongMap(bytesProvider)); + builder.putAllFieldMapUint64Double190(populateLongMap(doubleProvider)); + builder.putAllFieldMapUint64Enum191(populateLongMap(enumProvider)); + builder.putAllFieldMapUint64Fixed32192(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Fixed64193(populateLongMap(longProvider)); + builder.putAllFieldMapUint64Float194(populateLongMap(floatProvider)); + builder.putAllFieldMapUint64Int32195(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Int64196(populateLongMap(longProvider)); + builder.putAllFieldMapUint64Message197(populateLongMap(messageProvider)); + builder.putAllFieldMapUint64Sfixed32198(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Sfixed64199(populateLongMap(longProvider)); + builder.putAllFieldMapUint64Sint32200(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Sint64201(populateLongMap(longProvider)); + builder.putAllFieldMapUint64String202(populateLongMap(stringProvider)); + builder.putAllFieldMapUint64Uint32203(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Uint64204(populateLongMap(longProvider)); + + return builder.build(); + } + + public List newMessagesMissingRequiredFields() { + List results = new ArrayList<>(); + for (int i = 71; i <= 88; ++i) { + Proto2MessageLite.Builder builder = Proto2MessageLite.newBuilder(); + populateRequiredFields(builder, i); + results.add(builder.buildPartial()); + } + { + // A nested optional message field is missing required fields. + Proto2MessageLite.Builder builder = Proto2MessageLite.newBuilder(); + populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS); + builder.setFieldMessage10(Proto2MessageLite.getDefaultInstance()); + results.add(builder.buildPartial()); + } + { + // A nested repeated message field is missing required fields. + Proto2MessageLite.Builder builder = Proto2MessageLite.newBuilder(); + populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS); + builder.addFieldMessageList27(Proto2MessageLite.getDefaultInstance()); + results.add(builder.buildPartial()); + } + { + // A nested oneof message field is missing required fields. + Proto2MessageLite.Builder builder = Proto2MessageLite.newBuilder(); + populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS); + builder.setFieldMessage62(Proto2MessageLite.getDefaultInstance()); + results.add(builder.buildPartial()); + } + return results; + } + + // 0 is not a valid field number so we use it to mean no fields are excluded. + private static final int INCLUDE_ALL_REQUIRED_FIELDS = 0; + + private void populateRequiredFields(Proto2MessageLite.Builder builder, int excludedFieldNumber) { + if (excludedFieldNumber != 71) { + builder.setFieldRequiredDouble71(data.getDouble()); + } + if (excludedFieldNumber != 72) { + builder.setFieldRequiredFloat72(data.getFloat()); + } + if (excludedFieldNumber != 73) { + builder.setFieldRequiredInt6473(data.getLong()); + } + if (excludedFieldNumber != 74) { + builder.setFieldRequiredUint6474(data.getLong()); + } + if (excludedFieldNumber != 75) { + builder.setFieldRequiredInt3275(data.getInt()); + } + if (excludedFieldNumber != 76) { + builder.setFieldRequiredFixed6476(data.getLong()); + } + if (excludedFieldNumber != 77) { + builder.setFieldRequiredFixed3277(data.getInt()); + } + if (excludedFieldNumber != 78) { + builder.setFieldRequiredBool78(data.getBool()); + } + if (excludedFieldNumber != 79) { + builder.setFieldRequiredString79(data.getString()); + } + if (excludedFieldNumber != 80) { + builder.setFieldRequiredMessage80( + Proto2MessageLite.RequiredNestedMessage.newBuilder().setValue(data.getInt())); + } + if (excludedFieldNumber != 81) { + builder.setFieldRequiredBytes81(data.getBytes()); + } + if (excludedFieldNumber != 82) { + builder.setFieldRequiredUint3282(data.getInt()); + } + if (excludedFieldNumber != 83) { + builder.setFieldRequiredEnum83(Proto2MessageLite.TestEnum.forNumber(data.getEnum())); + } + if (excludedFieldNumber != 84) { + builder.setFieldRequiredSfixed3284(data.getInt()); + } + if (excludedFieldNumber != 85) { + builder.setFieldRequiredSfixed6485(data.getLong()); + } + if (excludedFieldNumber != 86) { + builder.setFieldRequiredSint3286(data.getInt()); + } + if (excludedFieldNumber != 87) { + builder.setFieldRequiredSint6487(data.getLong()); + } + if (excludedFieldNumber != 88) { + builder.setFieldRequiredGroup88( + Proto2MessageLite.FieldRequiredGroup88.newBuilder().setFieldInt3289(data.getInt())); + } + } +} diff --git a/java/core/src/test/java/com/google/protobuf/Proto2SchemaTest.java b/java/core/src/test/java/com/google/protobuf/Proto2SchemaTest.java new file mode 100644 index 0000000000000..098e7fe1829b6 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Proto2SchemaTest.java @@ -0,0 +1,49 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.testing.Proto2Testing.Proto2Message; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class Proto2SchemaTest extends AbstractProto2SchemaTest { + + @Override + protected Schema schema() { + return TestSchemas.genericProto2Schema; + } + + @Override + protected void registerSchemas() { + TestSchemas.registerGenericProto2Schemas(); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/Proto2UnknownEnumValueTest.java b/java/core/src/test/java/com/google/protobuf/Proto2UnknownEnumValueTest.java new file mode 100644 index 0000000000000..57ac0695e4c30 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Proto2UnknownEnumValueTest.java @@ -0,0 +1,111 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.Descriptors.FieldDescriptor; +import protobuf_unittest.UnittestProto; +import protobuf_unittest.UnittestProto.TestAllExtensions; +import protobuf_unittest.UnittestProto.TestAllTypes; +import junit.framework.TestCase; + +/** Unit tests for proto2 that treats unknown enum values as unknown fields. */ +public class Proto2UnknownEnumValueTest extends TestCase { + FieldDescriptor singularField = + TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum"); + FieldDescriptor repeatedField = + TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum"); + byte[] payload = buildPayloadWithUnknownEnumValues(); + + private byte[] buildPayloadWithUnknownEnumValues() { + // Builds a payload with unknown enum values. + UnknownFieldSet.Builder builder = UnknownFieldSet.newBuilder(); + builder.addField( + singularField.getNumber(), + UnknownFieldSet.Field.newBuilder() + .addVarint(TestAllTypes.NestedEnum.BAR.getNumber()) + .addVarint(1901 /* unknown enum value */) + .build()); + builder.addField( + repeatedField.getNumber(), + UnknownFieldSet.Field.newBuilder() + .addVarint(TestAllTypes.NestedEnum.FOO.getNumber()) + .addVarint(1902 /* unknown enum value */) + .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber()) + .addVarint(1903 /* unknown enum value */) + .build()); + return builder.build().toByteArray(); + } + + public void testUnknownEnumValues() throws Exception { + TestAllTypes message = TestAllTypes.parseFrom(payload); + + // Known enum values should be preserved. + assertEquals(TestAllTypes.NestedEnum.BAR, message.getOptionalNestedEnum()); + assertEquals(2, message.getRepeatedNestedEnumList().size()); + assertEquals(TestAllTypes.NestedEnum.FOO, message.getRepeatedNestedEnum(0)); + assertEquals(TestAllTypes.NestedEnum.BAZ, message.getRepeatedNestedEnum(1)); + + // Unknown enum values should be found in UnknownFieldSet. + UnknownFieldSet unknown = message.getUnknownFields(); + assertEquals( + 1901, unknown.getField(singularField.getNumber()).getVarintList().get(0).longValue()); + assertEquals( + 1902, unknown.getField(repeatedField.getNumber()).getVarintList().get(0).longValue()); + assertEquals( + 1903, unknown.getField(repeatedField.getNumber()).getVarintList().get(1).longValue()); + } + + public void testExtensionUnknownEnumValues() throws Exception { + ExtensionRegistry registry = ExtensionRegistry.newInstance(); + UnittestProto.registerAllExtensions(registry); + TestAllExtensions message = TestAllExtensions.parseFrom(payload, registry); + + assertEquals( + TestAllTypes.NestedEnum.BAR, + message.getExtension(UnittestProto.optionalNestedEnumExtension)); + assertEquals(2, message.getExtension(UnittestProto.repeatedNestedEnumExtension).size()); + assertEquals( + TestAllTypes.NestedEnum.FOO, + message.getExtension(UnittestProto.repeatedNestedEnumExtension, 0)); + assertEquals( + TestAllTypes.NestedEnum.BAZ, + message.getExtension(UnittestProto.repeatedNestedEnumExtension, 1)); + + // Unknown enum values should be found in UnknownFieldSet. + UnknownFieldSet unknown = message.getUnknownFields(); + assertEquals( + 1901, unknown.getField(singularField.getNumber()).getVarintList().get(0).longValue()); + assertEquals( + 1902, unknown.getField(repeatedField.getNumber()).getVarintList().get(0).longValue()); + assertEquals( + 1903, unknown.getField(repeatedField.getNumber()).getVarintList().get(1).longValue()); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/Proto3LiteSchemaTest.java b/java/core/src/test/java/com/google/protobuf/Proto3LiteSchemaTest.java new file mode 100644 index 0000000000000..ac9d6df70ebae --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Proto3LiteSchemaTest.java @@ -0,0 +1,49 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLite; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class Proto3LiteSchemaTest extends AbstractProto3LiteSchemaTest { + + @Override + protected Schema schema() { + return TestSchemasLite.genericProto3LiteSchema; + } + + @Override + protected void registerSchemas() { + TestSchemasLite.registerGenericProto3LiteSchemas(); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/Proto3MessageFactory.java b/java/core/src/test/java/com/google/protobuf/Proto3MessageFactory.java new file mode 100644 index 0000000000000..33d5fe0fccae7 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Proto3MessageFactory.java @@ -0,0 +1,450 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.testing.Proto3Testing.Proto3Message; +import com.google.protobuf.testing.Proto3Testing.Proto3MessageWithMaps; +import java.util.HashMap; +import java.util.Map; + +/** Creates instances of {@link Proto3Message} based on the tree configuration. */ +public final class Proto3MessageFactory implements ExperimentalMessageFactory { + private final int numRepeatedFields; + private final int branchingFactor; + private final Proto3MessageFactory nextLevel; + private final ExperimentalTestDataProvider data; + + public Proto3MessageFactory( + int numRepeatedFields, int stringLength, int branchingFactor, int treeDepth) { + this( + new ExperimentalTestDataProvider(stringLength), + numRepeatedFields, + branchingFactor, + treeDepth); + } + + private Proto3MessageFactory( + ExperimentalTestDataProvider data, + int numRepeatedFields, + int branchingFactor, + int treeDepth) { + this.numRepeatedFields = numRepeatedFields; + this.branchingFactor = branchingFactor; + this.data = data; + if (treeDepth > 0) { + nextLevel = new Proto3MessageFactory(data, numRepeatedFields, branchingFactor, treeDepth - 1); + } else { + nextLevel = null; + } + } + + @Override + public ExperimentalTestDataProvider dataProvider() { + return data; + } + + @Override + public Proto3Message newMessage() { + Proto3Message.Builder builder = Proto3Message.newBuilder(); + builder.setFieldDouble1(data.getDouble()); + builder.setFieldFloat2(data.getFloat()); + builder.setFieldInt643(data.getLong()); + builder.setFieldUint644(data.getLong()); + builder.setFieldInt325(data.getInt()); + builder.setFieldFixed646(data.getLong()); + builder.setFieldFixed327(data.getInt()); + builder.setFieldBool8(data.getBool()); + builder.setFieldString9(data.getString()); + // We don't populate the message field. Instead we apply the branching factor to the + // repeated message field below. + builder.setFieldBytes11(data.getBytes()); + builder.setFieldUint3212(data.getInt()); + builder.setFieldEnum13Value(data.getEnum()); + builder.setFieldSfixed3214(data.getInt()); + builder.setFieldSfixed6415(data.getLong()); + builder.setFieldSint3216(data.getInt()); + builder.setFieldSint6417(data.getLong()); + + for (int i = 0; i < numRepeatedFields; ++i) { + builder.addFieldDoubleList18(data.getDouble()); + builder.addFieldFloatList19(data.getFloat()); + builder.addFieldInt64List20(data.getLong()); + builder.addFieldUint64List21(data.getLong()); + builder.addFieldInt32List22(data.getInt()); + builder.addFieldFixed64List23(data.getLong()); + builder.addFieldFixed32List24(data.getInt()); + builder.addFieldBoolList25(data.getBool()); + builder.addFieldStringList26(data.getString()); + // Repeated message field is controlled by the branching factor below. + builder.addFieldBytesList28(data.getBytes()); + builder.addFieldUint32List29(data.getInt()); + builder.addFieldEnumList30Value(data.getEnum()); + builder.addFieldSfixed32List31(data.getInt()); + builder.addFieldSfixed64List32(data.getLong()); + builder.addFieldSint32List33(data.getInt()); + builder.addFieldSint64List34(data.getLong()); + + builder.addFieldDoubleListPacked35(data.getDouble()); + builder.addFieldFloatListPacked36(data.getFloat()); + builder.addFieldInt64ListPacked37(data.getLong()); + builder.addFieldUint64ListPacked38(data.getLong()); + builder.addFieldInt32ListPacked39(data.getInt()); + builder.addFieldFixed64ListPacked40(data.getLong()); + builder.addFieldFixed32ListPacked41(data.getInt()); + builder.addFieldBoolListPacked42(data.getBool()); + builder.addFieldUint32ListPacked43(data.getInt()); + builder.addFieldEnumListPacked44Value(data.getEnum()); + builder.addFieldSfixed32ListPacked45(data.getInt()); + builder.addFieldSfixed64ListPacked46(data.getLong()); + builder.addFieldSint32ListPacked47(data.getInt()); + builder.addFieldSint64ListPacked48(data.getLong()); + } + + // Handle the branching factor. + if (nextLevel != null) { + for (int i = 0; i < branchingFactor; ++i) { + builder.addFieldMessageList27(nextLevel.newMessage()); + } + } + + return builder.build(); + } + + private interface MapValueProvider { + public T getValue(); + } + + private final MapValueProvider integerProvider = + new MapValueProvider() { + @Override + public Integer getValue() { + return data.getInt(); + } + }; + private final MapValueProvider longProvider = + new MapValueProvider() { + @Override + public Long getValue() { + return data.getLong(); + } + }; + private final MapValueProvider stringProvider = + new MapValueProvider() { + @Override + public String getValue() { + return data.getString(); + } + }; + private final MapValueProvider bytesProvider = + new MapValueProvider() { + @Override + public ByteString getValue() { + return data.getBytes(); + } + }; + private final MapValueProvider booleanProvider = + new MapValueProvider() { + @Override + public Boolean getValue() { + return data.getBool(); + } + }; + private final MapValueProvider floatProvider = + new MapValueProvider() { + @Override + public Float getValue() { + return data.getFloat(); + } + }; + private final MapValueProvider doubleProvider = + new MapValueProvider() { + @Override + public Double getValue() { + return data.getDouble(); + } + }; + private final MapValueProvider messageProvider = + new MapValueProvider() { + @Override + public Proto3Message getValue() { + return newMessage(); + } + }; + private final MapValueProvider enumProvider = + new MapValueProvider() { + @Override + public Proto3Message.TestEnum getValue() { + return Proto3Message.TestEnum.forNumber(data.getEnum()); + } + }; + + private Map populateIntegerMap(MapValueProvider provider) { + Map map = new HashMap<>(); + for (int i = 0; i < numRepeatedFields; ++i) { + map.put(data.getInt(), provider.getValue()); + } + return map; + } + + private Map populateLongMap(MapValueProvider provider) { + Map map = new HashMap<>(); + for (int i = 0; i < numRepeatedFields; ++i) { + map.put(data.getLong(), provider.getValue()); + } + return map; + } + + private Map populateStringMap(MapValueProvider provider) { + Map map = new HashMap<>(); + for (int i = 0; i < numRepeatedFields; ++i) { + map.put(data.getString(), provider.getValue()); + } + return map; + } + + private Map populateBooleanMap(MapValueProvider provider) { + Map map = new HashMap<>(); + map.put(false, provider.getValue()); + map.put(true, provider.getValue()); + return map; + } + + public Proto3MessageWithMaps newMessageWithMaps() { + Proto3MessageWithMaps.Builder builder = Proto3MessageWithMaps.newBuilder(); + + builder.putAllFieldMapBoolBool1(populateBooleanMap(booleanProvider)); + builder.putAllFieldMapBoolBytes2(populateBooleanMap(bytesProvider)); + builder.putAllFieldMapBoolDouble3(populateBooleanMap(doubleProvider)); + builder.putAllFieldMapBoolEnum4(populateBooleanMap(enumProvider)); + builder.putAllFieldMapBoolFixed325(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolFixed646(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolFloat7(populateBooleanMap(floatProvider)); + builder.putAllFieldMapBoolInt328(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolInt649(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolMessage10(populateBooleanMap(messageProvider)); + builder.putAllFieldMapBoolSfixed3211(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolSfixed6412(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolSint3213(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolSint6414(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolString15(populateBooleanMap(stringProvider)); + builder.putAllFieldMapBoolUint3216(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolUint6417(populateBooleanMap(longProvider)); + builder.putAllFieldMapFixed32Bool18(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapFixed32Bytes19(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapFixed32Double20(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapFixed32Enum21(populateIntegerMap(enumProvider)); + builder.putAllFieldMapFixed32Fixed3222(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Fixed6423(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32Float24(populateIntegerMap(floatProvider)); + builder.putAllFieldMapFixed32Int3225(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Int6426(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32Message27(populateIntegerMap(messageProvider)); + builder.putAllFieldMapFixed32Sfixed3228(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Sfixed6429(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32Sint3230(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Sint6431(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32String32(populateIntegerMap(stringProvider)); + builder.putAllFieldMapFixed32Uint3233(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Uint6434(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed64Bool35(populateLongMap(booleanProvider)); + builder.putAllFieldMapFixed64Bytes36(populateLongMap(bytesProvider)); + builder.putAllFieldMapFixed64Double37(populateLongMap(doubleProvider)); + builder.putAllFieldMapFixed64Enum38(populateLongMap(enumProvider)); + builder.putAllFieldMapFixed64Fixed3239(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Fixed6440(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64Float41(populateLongMap(floatProvider)); + builder.putAllFieldMapFixed64Int3242(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Int6443(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64Message44(populateLongMap(messageProvider)); + builder.putAllFieldMapFixed64Sfixed3245(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Sfixed6446(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64Sint3247(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Sint6448(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64String49(populateLongMap(stringProvider)); + builder.putAllFieldMapFixed64Uint3250(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Uint6451(populateLongMap(longProvider)); + builder.putAllFieldMapInt32Bool52(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapInt32Bytes53(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapInt32Double54(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapInt32Enum55(populateIntegerMap(enumProvider)); + builder.putAllFieldMapInt32Fixed3256(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Fixed6457(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32Float58(populateIntegerMap(floatProvider)); + builder.putAllFieldMapInt32Int3259(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Int6460(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32Message61(populateIntegerMap(messageProvider)); + builder.putAllFieldMapInt32Sfixed3262(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Sfixed6463(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32Sint3264(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Sint6465(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32String66(populateIntegerMap(stringProvider)); + builder.putAllFieldMapInt32Uint3267(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Uint6468(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt64Bool69(populateLongMap(booleanProvider)); + builder.putAllFieldMapInt64Bytes70(populateLongMap(bytesProvider)); + builder.putAllFieldMapInt64Double71(populateLongMap(doubleProvider)); + builder.putAllFieldMapInt64Enum72(populateLongMap(enumProvider)); + builder.putAllFieldMapInt64Fixed3273(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Fixed6474(populateLongMap(longProvider)); + builder.putAllFieldMapInt64Float75(populateLongMap(floatProvider)); + builder.putAllFieldMapInt64Int3276(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Int6477(populateLongMap(longProvider)); + builder.putAllFieldMapInt64Message78(populateLongMap(messageProvider)); + builder.putAllFieldMapInt64Sfixed3279(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Sfixed6480(populateLongMap(longProvider)); + builder.putAllFieldMapInt64Sint3281(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Sint6482(populateLongMap(longProvider)); + builder.putAllFieldMapInt64String83(populateLongMap(stringProvider)); + builder.putAllFieldMapInt64Uint3284(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Uint6485(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed32Bool86(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapSfixed32Bytes87(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapSfixed32Double88(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapSfixed32Enum89(populateIntegerMap(enumProvider)); + builder.putAllFieldMapSfixed32Fixed3290(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Fixed6491(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32Float92(populateIntegerMap(floatProvider)); + builder.putAllFieldMapSfixed32Int3293(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Int6494(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32Message95(populateIntegerMap(messageProvider)); + builder.putAllFieldMapSfixed32Sfixed3296(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Sfixed6497(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32Sint3298(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Sint6499(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32String100(populateIntegerMap(stringProvider)); + builder.putAllFieldMapSfixed32Uint32101(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Uint64102(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed64Bool103(populateLongMap(booleanProvider)); + builder.putAllFieldMapSfixed64Bytes104(populateLongMap(bytesProvider)); + builder.putAllFieldMapSfixed64Double105(populateLongMap(doubleProvider)); + builder.putAllFieldMapSfixed64Enum106(populateLongMap(enumProvider)); + builder.putAllFieldMapSfixed64Fixed32107(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Fixed64108(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64Float109(populateLongMap(floatProvider)); + builder.putAllFieldMapSfixed64Int32110(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Int64111(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64Message112(populateLongMap(messageProvider)); + builder.putAllFieldMapSfixed64Sfixed32113(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Sfixed64114(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64Sint32115(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Sint64116(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64String117(populateLongMap(stringProvider)); + builder.putAllFieldMapSfixed64Uint32118(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Uint64119(populateLongMap(longProvider)); + builder.putAllFieldMapSint32Bool120(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapSint32Bytes121(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapSint32Double122(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapSint32Enum123(populateIntegerMap(enumProvider)); + builder.putAllFieldMapSint32Fixed32124(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Fixed64125(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32Float126(populateIntegerMap(floatProvider)); + builder.putAllFieldMapSint32Int32127(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Int64128(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32Message129(populateIntegerMap(messageProvider)); + builder.putAllFieldMapSint32Sfixed32130(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Sfixed64131(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32Sint32132(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Sint64133(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32String134(populateIntegerMap(stringProvider)); + builder.putAllFieldMapSint32Uint32135(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Uint64136(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint64Bool137(populateLongMap(booleanProvider)); + builder.putAllFieldMapSint64Bytes138(populateLongMap(bytesProvider)); + builder.putAllFieldMapSint64Double139(populateLongMap(doubleProvider)); + builder.putAllFieldMapSint64Enum140(populateLongMap(enumProvider)); + builder.putAllFieldMapSint64Fixed32141(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Fixed64142(populateLongMap(longProvider)); + builder.putAllFieldMapSint64Float143(populateLongMap(floatProvider)); + builder.putAllFieldMapSint64Int32144(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Int64145(populateLongMap(longProvider)); + builder.putAllFieldMapSint64Message146(populateLongMap(messageProvider)); + builder.putAllFieldMapSint64Sfixed32147(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Sfixed64148(populateLongMap(longProvider)); + builder.putAllFieldMapSint64Sint32149(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Sint64150(populateLongMap(longProvider)); + builder.putAllFieldMapSint64String151(populateLongMap(stringProvider)); + builder.putAllFieldMapSint64Uint32152(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Uint64153(populateLongMap(longProvider)); + builder.putAllFieldMapStringBool154(populateStringMap(booleanProvider)); + builder.putAllFieldMapStringBytes155(populateStringMap(bytesProvider)); + builder.putAllFieldMapStringDouble156(populateStringMap(doubleProvider)); + builder.putAllFieldMapStringEnum157(populateStringMap(enumProvider)); + builder.putAllFieldMapStringFixed32158(populateStringMap(integerProvider)); + builder.putAllFieldMapStringFixed64159(populateStringMap(longProvider)); + builder.putAllFieldMapStringFloat160(populateStringMap(floatProvider)); + builder.putAllFieldMapStringInt32161(populateStringMap(integerProvider)); + builder.putAllFieldMapStringInt64162(populateStringMap(longProvider)); + builder.putAllFieldMapStringMessage163(populateStringMap(messageProvider)); + builder.putAllFieldMapStringSfixed32164(populateStringMap(integerProvider)); + builder.putAllFieldMapStringSfixed64165(populateStringMap(longProvider)); + builder.putAllFieldMapStringSint32166(populateStringMap(integerProvider)); + builder.putAllFieldMapStringSint64167(populateStringMap(longProvider)); + builder.putAllFieldMapStringString168(populateStringMap(stringProvider)); + builder.putAllFieldMapStringUint32169(populateStringMap(integerProvider)); + builder.putAllFieldMapStringUint64170(populateStringMap(longProvider)); + builder.putAllFieldMapUint32Bool171(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapUint32Bytes172(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapUint32Double173(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapUint32Enum174(populateIntegerMap(enumProvider)); + builder.putAllFieldMapUint32Fixed32175(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Fixed64176(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32Float177(populateIntegerMap(floatProvider)); + builder.putAllFieldMapUint32Int32178(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Int64179(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32Message180(populateIntegerMap(messageProvider)); + builder.putAllFieldMapUint32Sfixed32181(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Sfixed64182(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32Sint32183(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Sint64184(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32String185(populateIntegerMap(stringProvider)); + builder.putAllFieldMapUint32Uint32186(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Uint64187(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint64Bool188(populateLongMap(booleanProvider)); + builder.putAllFieldMapUint64Bytes189(populateLongMap(bytesProvider)); + builder.putAllFieldMapUint64Double190(populateLongMap(doubleProvider)); + builder.putAllFieldMapUint64Enum191(populateLongMap(enumProvider)); + builder.putAllFieldMapUint64Fixed32192(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Fixed64193(populateLongMap(longProvider)); + builder.putAllFieldMapUint64Float194(populateLongMap(floatProvider)); + builder.putAllFieldMapUint64Int32195(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Int64196(populateLongMap(longProvider)); + builder.putAllFieldMapUint64Message197(populateLongMap(messageProvider)); + builder.putAllFieldMapUint64Sfixed32198(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Sfixed64199(populateLongMap(longProvider)); + builder.putAllFieldMapUint64Sint32200(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Sint64201(populateLongMap(longProvider)); + builder.putAllFieldMapUint64String202(populateLongMap(stringProvider)); + builder.putAllFieldMapUint64Uint32203(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Uint64204(populateLongMap(longProvider)); + + return builder.build(); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/Proto3MessageInfoFactory.java b/java/core/src/test/java/com/google/protobuf/Proto3MessageInfoFactory.java new file mode 100644 index 0000000000000..364071b35da00 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Proto3MessageInfoFactory.java @@ -0,0 +1,506 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.FieldInfo.forField; +import static com.google.protobuf.FieldInfo.forMapField; +import static com.google.protobuf.FieldInfo.forOneofMemberField; +import static com.google.protobuf.FieldInfo.forRepeatedMessageField; + +import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithMaps; +import com.google.protobuf.testing.Proto3Testing.Proto3Empty; +import com.google.protobuf.testing.Proto3Testing.Proto3Message; +import com.google.protobuf.testing.Proto3Testing.Proto3MessageWithMaps; +import java.lang.reflect.Field; + +/** A factory that generates a hard-coded info for {@link Proto3Message}. */ +public final class Proto3MessageInfoFactory implements MessageInfoFactory { + private static final Proto3MessageInfoFactory INSTANCE = new Proto3MessageInfoFactory(); + + private Proto3MessageInfoFactory() {} + + public static Proto3MessageInfoFactory getInstance() { + return INSTANCE; + } + + @Override + public boolean isSupported(Class clazz) { + return true; + } + + @Override + public MessageInfo messageInfoFor(Class clazz) { + if (Proto3Message.class.isAssignableFrom(clazz)) { + return newMessageInfoForProto3Message(); + } else if (Proto3Empty.class.isAssignableFrom(clazz)) { + return newMessageInfoForProto3Empty(); + } else if (Proto3MessageWithMaps.class.isAssignableFrom(clazz)) { + return newMessageInfoForProto3MessageWithMaps(); + } else { + throw new IllegalArgumentException("Unsupported class: " + clazz.getName()); + } + } + + /** + * Creates a new hard-coded info for {@link Proto3Message}. Each time this is called, we manually + * go through the entire process of what a message would do if it self-registered its own info, + * including looking up each field by name. This is done for benchmarking purposes, so that we get + * a more accurate representation of the time it takes to perform this process. + */ + private static StructuralMessageInfo newMessageInfoForProto3Message() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(48); + lookupFieldsByName(builder); + return builder.build(); + } + + private static void lookupFieldsByName(StructuralMessageInfo.Builder builder) { + builder.withDefaultInstance(Proto3Message.getDefaultInstance()); + builder.withSyntax(ProtoSyntax.PROTO3); + builder.withField(forField(field("fieldDouble1_"), 1, FieldType.DOUBLE, true)); + builder.withField(forField(field("fieldFloat2_"), 2, FieldType.FLOAT, true)); + builder.withField(forField(field("fieldInt643_"), 3, FieldType.INT64, true)); + builder.withField(forField(field("fieldUint644_"), 4, FieldType.UINT64, true)); + builder.withField(forField(field("fieldInt325_"), 5, FieldType.INT32, true)); + builder.withField(forField(field("fieldFixed646_"), 6, FieldType.FIXED64, true)); + builder.withField(forField(field("fieldFixed327_"), 7, FieldType.FIXED32, true)); + builder.withField(forField(field("fieldBool8_"), 8, FieldType.BOOL, true)); + builder.withField(forField(field("fieldString9_"), 9, FieldType.STRING, true)); + builder.withField(forField(field("fieldMessage10_"), 10, FieldType.MESSAGE, true)); + builder.withField(forField(field("fieldBytes11_"), 11, FieldType.BYTES, true)); + builder.withField(forField(field("fieldUint3212_"), 12, FieldType.UINT32, true)); + builder.withField(forField(field("fieldEnum13_"), 13, FieldType.ENUM, true)); + builder.withField(forField(field("fieldSfixed3214_"), 14, FieldType.SFIXED32, true)); + builder.withField(forField(field("fieldSfixed6415_"), 15, FieldType.SFIXED64, true)); + builder.withField(forField(field("fieldSint3216_"), 16, FieldType.SINT32, true)); + builder.withField(forField(field("fieldSint6417_"), 17, FieldType.SINT64, true)); + builder.withField(forField(field("fieldDoubleList18_"), 18, FieldType.DOUBLE_LIST, true)); + builder.withField(forField(field("fieldFloatList19_"), 19, FieldType.FLOAT_LIST, true)); + builder.withField(forField(field("fieldInt64List20_"), 20, FieldType.INT64_LIST, true)); + builder.withField(forField(field("fieldUint64List21_"), 21, FieldType.UINT64_LIST, true)); + builder.withField(forField(field("fieldInt32List22_"), 22, FieldType.INT32_LIST, true)); + builder.withField(forField(field("fieldFixed64List23_"), 23, FieldType.FIXED64_LIST, true)); + builder.withField(forField(field("fieldFixed32List24_"), 24, FieldType.FIXED32_LIST, true)); + builder.withField(forField(field("fieldBoolList25_"), 25, FieldType.BOOL_LIST, true)); + builder.withField(forField(field("fieldStringList26_"), 26, FieldType.STRING_LIST, true)); + builder.withField( + forRepeatedMessageField( + field("fieldMessageList27_"), 27, FieldType.MESSAGE_LIST, Proto3Message.class)); + builder.withField(forField(field("fieldBytesList28_"), 28, FieldType.BYTES_LIST, true)); + builder.withField(forField(field("fieldUint32List29_"), 29, FieldType.UINT32_LIST, true)); + builder.withField(forField(field("fieldEnumList30_"), 30, FieldType.ENUM_LIST, true)); + builder.withField(forField(field("fieldSfixed32List31_"), 31, FieldType.SFIXED32_LIST, true)); + builder.withField(forField(field("fieldSfixed64List32_"), 32, FieldType.SFIXED64_LIST, true)); + builder.withField(forField(field("fieldSint32List33_"), 33, FieldType.SINT32_LIST, true)); + builder.withField(forField(field("fieldSint64List34_"), 34, FieldType.SINT64_LIST, true)); + builder.withField( + forField(field("fieldDoubleListPacked35_"), 35, FieldType.DOUBLE_LIST_PACKED, true)); + builder.withField( + forField(field("fieldFloatListPacked36_"), 36, FieldType.FLOAT_LIST_PACKED, true)); + builder.withField( + forField(field("fieldInt64ListPacked37_"), 37, FieldType.INT64_LIST_PACKED, true)); + builder.withField( + forField(field("fieldUint64ListPacked38_"), 38, FieldType.UINT64_LIST_PACKED, true)); + builder.withField( + forField(field("fieldInt32ListPacked39_"), 39, FieldType.INT32_LIST_PACKED, true)); + builder.withField( + forField(field("fieldFixed64ListPacked40_"), 40, FieldType.FIXED64_LIST_PACKED, true)); + builder.withField( + forField(field("fieldFixed32ListPacked41_"), 41, FieldType.FIXED32_LIST_PACKED, true)); + builder.withField( + forField(field("fieldBoolListPacked42_"), 42, FieldType.BOOL_LIST_PACKED, true)); + builder.withField( + forField(field("fieldUint32ListPacked43_"), 43, FieldType.UINT32_LIST_PACKED, true)); + builder.withField( + forField(field("fieldEnumListPacked44_"), 44, FieldType.ENUM_LIST_PACKED, true)); + builder.withField( + forField(field("fieldSfixed32ListPacked45_"), 45, FieldType.SFIXED32_LIST_PACKED, true)); + builder.withField( + forField(field("fieldSfixed64ListPacked46_"), 46, FieldType.SFIXED64_LIST_PACKED, true)); + builder.withField( + forField(field("fieldSint32ListPacked47_"), 47, FieldType.SINT32_LIST_PACKED, true)); + builder.withField( + forField(field("fieldSint64ListPacked48_"), 48, FieldType.SINT64_LIST_PACKED, true)); + + OneofInfo oneof = new OneofInfo(0, field("testOneofCase_"), field("testOneof_")); + builder.withField(forOneofMemberField(53, FieldType.DOUBLE, oneof, Double.class, true, null)); + builder.withField(forOneofMemberField(54, FieldType.FLOAT, oneof, Float.class, true, null)); + builder.withField(forOneofMemberField(55, FieldType.INT64, oneof, Long.class, true, null)); + builder.withField(forOneofMemberField(56, FieldType.UINT64, oneof, Long.class, true, null)); + builder.withField(forOneofMemberField(57, FieldType.INT32, oneof, Integer.class, true, null)); + builder.withField(forOneofMemberField(58, FieldType.FIXED64, oneof, Long.class, true, null)); + builder.withField(forOneofMemberField(59, FieldType.FIXED32, oneof, Integer.class, true, null)); + builder.withField(forOneofMemberField(60, FieldType.BOOL, oneof, Boolean.class, true, null)); + builder.withField(forOneofMemberField(61, FieldType.STRING, oneof, String.class, true, null)); + builder.withField( + forOneofMemberField(62, FieldType.MESSAGE, oneof, Proto3Message.class, true, null)); + builder.withField( + forOneofMemberField(63, FieldType.BYTES, oneof, ByteString.class, true, null)); + builder.withField(forOneofMemberField(64, FieldType.UINT32, oneof, Integer.class, true, null)); + builder.withField( + forOneofMemberField(65, FieldType.SFIXED32, oneof, Integer.class, true, null)); + builder.withField(forOneofMemberField(66, FieldType.SFIXED64, oneof, Long.class, true, null)); + builder.withField(forOneofMemberField(67, FieldType.SINT32, oneof, Integer.class, true, null)); + builder.withField(forOneofMemberField(68, FieldType.SINT64, oneof, Long.class, true, null)); + } + + private StructuralMessageInfo newMessageInfoForProto3Empty() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO3); + return builder.build(); + } + + private StructuralMessageInfo newMessageInfoForProto3MessageWithMaps() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(); + builder.withSyntax(ProtoSyntax.PROTO3); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_bool_1", 1)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_bytes_2", 2)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_double_3", 3)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_enum_4", 4)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_fixed32_5", 5)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_fixed64_6", 6)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_float_7", 7)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_int32_8", 8)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_int64_9", 9)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_message_10", 10)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_sfixed32_11", 11)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_sfixed64_12", 12)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_sint32_13", 13)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_sint64_14", 14)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_string_15", 15)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_uint32_16", 16)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_uint64_17", 17)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_bool_18", 18)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_bytes_19", 19)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_double_20", 20)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_enum_21", 21)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_fixed32_22", 22)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_fixed64_23", 23)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_float_24", 24)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_int32_25", 25)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_int64_26", 26)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_message_27", 27)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_sfixed32_28", 28)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_sfixed64_29", 29)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_sint32_30", 30)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_sint64_31", 31)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_string_32", 32)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_uint32_33", 33)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_uint64_34", 34)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_bool_35", 35)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_bytes_36", 36)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_double_37", 37)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_enum_38", 38)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_fixed32_39", 39)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_fixed64_40", 40)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_float_41", 41)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_int32_42", 42)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_int64_43", 43)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_message_44", 44)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_sfixed32_45", 45)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_sfixed64_46", 46)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_sint32_47", 47)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_sint64_48", 48)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_string_49", 49)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_uint32_50", 50)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_uint64_51", 51)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_bool_52", 52)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_bytes_53", 53)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_double_54", 54)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_enum_55", 55)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_fixed32_56", 56)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_fixed64_57", 57)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_float_58", 58)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_int32_59", 59)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_int64_60", 60)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_message_61", 61)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_sfixed32_62", 62)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_sfixed64_63", 63)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_sint32_64", 64)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_sint64_65", 65)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_string_66", 66)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_uint32_67", 67)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_uint64_68", 68)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_bool_69", 69)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_bytes_70", 70)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_double_71", 71)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_enum_72", 72)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_fixed32_73", 73)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_fixed64_74", 74)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_float_75", 75)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_int32_76", 76)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_int64_77", 77)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_message_78", 78)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_sfixed32_79", 79)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_sfixed64_80", 80)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_sint32_81", 81)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_sint64_82", 82)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_string_83", 83)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_uint32_84", 84)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_uint64_85", 85)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_bool_86", 86)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_bytes_87", 87)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_double_88", 88)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_enum_89", 89)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_fixed32_90", 90)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_fixed64_91", 91)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_float_92", 92)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_int32_93", 93)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_int64_94", 94)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_message_95", 95)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_sfixed32_96", 96)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_sfixed64_97", 97)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_sint32_98", 98)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_sint64_99", 99)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_string_100", 100)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_uint32_101", 101)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_uint64_102", 102)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_bool_103", 103)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_bytes_104", 104)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_double_105", 105)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_enum_106", 106)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_fixed32_107", 107)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_fixed64_108", 108)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_float_109", 109)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_int32_110", 110)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_int64_111", 111)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_message_112", 112)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_sfixed32_113", 113)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_sfixed64_114", 114)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_sint32_115", 115)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_sint64_116", 116)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_string_117", 117)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_uint32_118", 118)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_uint64_119", 119)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_bool_120", 120)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_bytes_121", 121)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_double_122", 122)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_enum_123", 123)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_fixed32_124", 124)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_fixed64_125", 125)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_float_126", 126)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_int32_127", 127)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_int64_128", 128)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_message_129", 129)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_sfixed32_130", 130)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_sfixed64_131", 131)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_sint32_132", 132)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_sint64_133", 133)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_string_134", 134)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_uint32_135", 135)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_uint64_136", 136)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_bool_137", 137)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_bytes_138", 138)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_double_139", 139)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_enum_140", 140)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_fixed32_141", 141)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_fixed64_142", 142)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_float_143", 143)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_int32_144", 144)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_int64_145", 145)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_message_146", 146)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_sfixed32_147", 147)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_sfixed64_148", 148)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_sint32_149", 149)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_sint64_150", 150)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_string_151", 151)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_uint32_152", 152)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_uint64_153", 153)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_bool_154", 154)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_bytes_155", 155)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_double_156", 156)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_enum_157", 157)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_fixed32_158", 158)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_fixed64_159", 159)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_float_160", 160)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_int32_161", 161)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_int64_162", 162)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_message_163", 163)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_sfixed32_164", 164)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_sfixed64_165", 165)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_sint32_166", 166)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_sint64_167", 167)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_string_168", 168)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_uint32_169", 169)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_uint64_170", 170)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_bool_171", 171)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_bytes_172", 172)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_double_173", 173)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_enum_174", 174)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_fixed32_175", 175)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_fixed64_176", 176)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_float_177", 177)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_int32_178", 178)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_int64_179", 179)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_message_180", 180)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_sfixed32_181", 181)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_sfixed64_182", 182)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_sint32_183", 183)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_sint64_184", 184)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_string_185", 185)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_uint32_186", 186)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_uint64_187", 187)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_bool_188", 188)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_bytes_189", 189)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_double_190", 190)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_enum_191", 191)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_fixed32_192", 192)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_fixed64_193", 193)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_float_194", 194)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_int32_195", 195)); + builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_int64_196", 196)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_message_197", 197)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_sfixed32_198", 198)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_sfixed64_199", 199)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_sint32_200", 200)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_sint64_201", 201)); + builder.withField( + mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_string_202", 202)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_uint32_203", 203)); + builder.withField( + mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_uint64_204", 204)); + return builder.build(); + } + + private static Field field(String name) { + return field(Proto3Message.class, name); + } + + private static Field field(Class clazz, String name) { + try { + return clazz.getDeclaredField(name); + } catch (NoSuchFieldException | SecurityException e) { + throw new RuntimeException(e); + } + } + + private static FieldInfo mapFieldInfo(Class clazz, String fieldName, int fieldNumber) { + try { + return forMapField( + field(clazz, SchemaUtil.toCamelCase(fieldName, false) + "_"), + fieldNumber, + SchemaUtil.getMapDefaultEntry(clazz, fieldName), + null); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } +} diff --git a/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteFactory.java b/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteFactory.java new file mode 100644 index 0000000000000..2f6947da4f746 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteFactory.java @@ -0,0 +1,452 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLite; +import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLiteWithMaps; +import java.util.HashMap; +import java.util.Map; + +/** Creates instances of {@link Proto3MessageLite} based on the tree configuration. */ +public final class Proto3MessageLiteFactory + implements ExperimentalMessageFactory { + private final int numRepeatedFields; + private final int branchingFactor; + private final Proto3MessageLiteFactory nextLevel; + private final ExperimentalTestDataProvider data; + + public Proto3MessageLiteFactory( + int numRepeatedFields, int stringLength, int branchingFactor, int treeDepth) { + this( + new ExperimentalTestDataProvider(stringLength), + numRepeatedFields, + branchingFactor, + treeDepth); + } + + private Proto3MessageLiteFactory( + ExperimentalTestDataProvider data, + int numRepeatedFields, + int branchingFactor, + int treeDepth) { + this.numRepeatedFields = numRepeatedFields; + this.branchingFactor = branchingFactor; + this.data = data; + if (treeDepth > 0) { + nextLevel = + new Proto3MessageLiteFactory(data, numRepeatedFields, branchingFactor, treeDepth - 1); + } else { + nextLevel = null; + } + } + + @Override + public ExperimentalTestDataProvider dataProvider() { + return data; + } + + @Override + public Proto3MessageLite newMessage() { + Proto3MessageLite.Builder builder = Proto3MessageLite.newBuilder(); + builder.setFieldDouble1(data.getDouble()); + builder.setFieldFloat2(data.getFloat()); + builder.setFieldInt643(data.getLong()); + builder.setFieldUint644(data.getLong()); + builder.setFieldInt325(data.getInt()); + builder.setFieldFixed646(data.getLong()); + builder.setFieldFixed327(data.getInt()); + builder.setFieldBool8(data.getBool()); + builder.setFieldString9(data.getString()); + // We don't populate the message field. Instead we apply the branching factor to the + // repeated message field below. + builder.setFieldBytes11(data.getBytes()); + builder.setFieldUint3212(data.getInt()); + builder.setFieldEnum13Value(data.getEnum()); + builder.setFieldSfixed3214(data.getInt()); + builder.setFieldSfixed6415(data.getLong()); + builder.setFieldSint3216(data.getInt()); + builder.setFieldSint6417(data.getLong()); + + for (int i = 0; i < numRepeatedFields; ++i) { + builder.addFieldDoubleList18(data.getDouble()); + builder.addFieldFloatList19(data.getFloat()); + builder.addFieldInt64List20(data.getLong()); + builder.addFieldUint64List21(data.getLong()); + builder.addFieldInt32List22(data.getInt()); + builder.addFieldFixed64List23(data.getLong()); + builder.addFieldFixed32List24(data.getInt()); + builder.addFieldBoolList25(data.getBool()); + builder.addFieldStringList26(data.getString()); + // Repeated message field is controlled by the branching factor below. + builder.addFieldBytesList28(data.getBytes()); + builder.addFieldUint32List29(data.getInt()); + builder.addFieldEnumList30Value(data.getEnum()); + builder.addFieldSfixed32List31(data.getInt()); + builder.addFieldSfixed64List32(data.getLong()); + builder.addFieldSint32List33(data.getInt()); + builder.addFieldSint64List34(data.getLong()); + + builder.addFieldDoubleListPacked35(data.getDouble()); + builder.addFieldFloatListPacked36(data.getFloat()); + builder.addFieldInt64ListPacked37(data.getLong()); + builder.addFieldUint64ListPacked38(data.getLong()); + builder.addFieldInt32ListPacked39(data.getInt()); + builder.addFieldFixed64ListPacked40(data.getLong()); + builder.addFieldFixed32ListPacked41(data.getInt()); + builder.addFieldBoolListPacked42(data.getBool()); + builder.addFieldUint32ListPacked43(data.getInt()); + builder.addFieldEnumListPacked44Value(data.getEnum()); + builder.addFieldSfixed32ListPacked45(data.getInt()); + builder.addFieldSfixed64ListPacked46(data.getLong()); + builder.addFieldSint32ListPacked47(data.getInt()); + builder.addFieldSint64ListPacked48(data.getLong()); + } + + // Handle the branching factor. + if (nextLevel != null) { + for (int i = 0; i < branchingFactor; ++i) { + builder.addFieldMessageList27(nextLevel.newMessage()); + } + } + + return builder.build(); + } + + private interface MapValueProvider { + public T getValue(); + } + + private final MapValueProvider integerProvider = + new MapValueProvider() { + @Override + public Integer getValue() { + return data.getInt(); + } + }; + private final MapValueProvider longProvider = + new MapValueProvider() { + @Override + public Long getValue() { + return data.getLong(); + } + }; + private final MapValueProvider stringProvider = + new MapValueProvider() { + @Override + public String getValue() { + return data.getString(); + } + }; + private final MapValueProvider bytesProvider = + new MapValueProvider() { + @Override + public ByteString getValue() { + return data.getBytes(); + } + }; + private final MapValueProvider booleanProvider = + new MapValueProvider() { + @Override + public Boolean getValue() { + return data.getBool(); + } + }; + private final MapValueProvider floatProvider = + new MapValueProvider() { + @Override + public Float getValue() { + return data.getFloat(); + } + }; + private final MapValueProvider doubleProvider = + new MapValueProvider() { + @Override + public Double getValue() { + return data.getDouble(); + } + }; + private final MapValueProvider messageProvider = + new MapValueProvider() { + @Override + public Proto3MessageLite getValue() { + return newMessage(); + } + }; + private final MapValueProvider enumProvider = + new MapValueProvider() { + @Override + public Proto3MessageLite.TestEnum getValue() { + return Proto3MessageLite.TestEnum.forNumber(data.getEnum()); + } + }; + + private Map populateIntegerMap(MapValueProvider provider) { + Map map = new HashMap<>(); + for (int i = 0; i < numRepeatedFields; ++i) { + map.put(data.getInt(), provider.getValue()); + } + return map; + } + + private Map populateLongMap(MapValueProvider provider) { + Map map = new HashMap<>(); + for (int i = 0; i < numRepeatedFields; ++i) { + map.put(data.getLong(), provider.getValue()); + } + return map; + } + + private Map populateStringMap(MapValueProvider provider) { + Map map = new HashMap<>(); + for (int i = 0; i < numRepeatedFields; ++i) { + map.put(data.getString(), provider.getValue()); + } + return map; + } + + private Map populateBooleanMap(MapValueProvider provider) { + Map map = new HashMap<>(); + map.put(false, provider.getValue()); + map.put(true, provider.getValue()); + return map; + } + + public Proto3MessageLiteWithMaps newMessageWithMaps() { + Proto3MessageLiteWithMaps.Builder builder = Proto3MessageLiteWithMaps.newBuilder(); + + builder.putAllFieldMapBoolBool1(populateBooleanMap(booleanProvider)); + builder.putAllFieldMapBoolBytes2(populateBooleanMap(bytesProvider)); + builder.putAllFieldMapBoolDouble3(populateBooleanMap(doubleProvider)); + builder.putAllFieldMapBoolEnum4(populateBooleanMap(enumProvider)); + builder.putAllFieldMapBoolFixed325(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolFixed646(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolFloat7(populateBooleanMap(floatProvider)); + builder.putAllFieldMapBoolInt328(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolInt649(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolMessage10(populateBooleanMap(messageProvider)); + builder.putAllFieldMapBoolSfixed3211(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolSfixed6412(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolSint3213(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolSint6414(populateBooleanMap(longProvider)); + builder.putAllFieldMapBoolString15(populateBooleanMap(stringProvider)); + builder.putAllFieldMapBoolUint3216(populateBooleanMap(integerProvider)); + builder.putAllFieldMapBoolUint6417(populateBooleanMap(longProvider)); + builder.putAllFieldMapFixed32Bool18(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapFixed32Bytes19(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapFixed32Double20(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapFixed32Enum21(populateIntegerMap(enumProvider)); + builder.putAllFieldMapFixed32Fixed3222(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Fixed6423(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32Float24(populateIntegerMap(floatProvider)); + builder.putAllFieldMapFixed32Int3225(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Int6426(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32Message27(populateIntegerMap(messageProvider)); + builder.putAllFieldMapFixed32Sfixed3228(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Sfixed6429(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32Sint3230(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Sint6431(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed32String32(populateIntegerMap(stringProvider)); + builder.putAllFieldMapFixed32Uint3233(populateIntegerMap(integerProvider)); + builder.putAllFieldMapFixed32Uint6434(populateIntegerMap(longProvider)); + builder.putAllFieldMapFixed64Bool35(populateLongMap(booleanProvider)); + builder.putAllFieldMapFixed64Bytes36(populateLongMap(bytesProvider)); + builder.putAllFieldMapFixed64Double37(populateLongMap(doubleProvider)); + builder.putAllFieldMapFixed64Enum38(populateLongMap(enumProvider)); + builder.putAllFieldMapFixed64Fixed3239(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Fixed6440(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64Float41(populateLongMap(floatProvider)); + builder.putAllFieldMapFixed64Int3242(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Int6443(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64Message44(populateLongMap(messageProvider)); + builder.putAllFieldMapFixed64Sfixed3245(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Sfixed6446(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64Sint3247(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Sint6448(populateLongMap(longProvider)); + builder.putAllFieldMapFixed64String49(populateLongMap(stringProvider)); + builder.putAllFieldMapFixed64Uint3250(populateLongMap(integerProvider)); + builder.putAllFieldMapFixed64Uint6451(populateLongMap(longProvider)); + builder.putAllFieldMapInt32Bool52(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapInt32Bytes53(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapInt32Double54(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapInt32Enum55(populateIntegerMap(enumProvider)); + builder.putAllFieldMapInt32Fixed3256(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Fixed6457(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32Float58(populateIntegerMap(floatProvider)); + builder.putAllFieldMapInt32Int3259(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Int6460(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32Message61(populateIntegerMap(messageProvider)); + builder.putAllFieldMapInt32Sfixed3262(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Sfixed6463(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32Sint3264(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Sint6465(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt32String66(populateIntegerMap(stringProvider)); + builder.putAllFieldMapInt32Uint3267(populateIntegerMap(integerProvider)); + builder.putAllFieldMapInt32Uint6468(populateIntegerMap(longProvider)); + builder.putAllFieldMapInt64Bool69(populateLongMap(booleanProvider)); + builder.putAllFieldMapInt64Bytes70(populateLongMap(bytesProvider)); + builder.putAllFieldMapInt64Double71(populateLongMap(doubleProvider)); + builder.putAllFieldMapInt64Enum72(populateLongMap(enumProvider)); + builder.putAllFieldMapInt64Fixed3273(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Fixed6474(populateLongMap(longProvider)); + builder.putAllFieldMapInt64Float75(populateLongMap(floatProvider)); + builder.putAllFieldMapInt64Int3276(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Int6477(populateLongMap(longProvider)); + builder.putAllFieldMapInt64Message78(populateLongMap(messageProvider)); + builder.putAllFieldMapInt64Sfixed3279(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Sfixed6480(populateLongMap(longProvider)); + builder.putAllFieldMapInt64Sint3281(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Sint6482(populateLongMap(longProvider)); + builder.putAllFieldMapInt64String83(populateLongMap(stringProvider)); + builder.putAllFieldMapInt64Uint3284(populateLongMap(integerProvider)); + builder.putAllFieldMapInt64Uint6485(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed32Bool86(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapSfixed32Bytes87(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapSfixed32Double88(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapSfixed32Enum89(populateIntegerMap(enumProvider)); + builder.putAllFieldMapSfixed32Fixed3290(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Fixed6491(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32Float92(populateIntegerMap(floatProvider)); + builder.putAllFieldMapSfixed32Int3293(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Int6494(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32Message95(populateIntegerMap(messageProvider)); + builder.putAllFieldMapSfixed32Sfixed3296(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Sfixed6497(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32Sint3298(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Sint6499(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed32String100(populateIntegerMap(stringProvider)); + builder.putAllFieldMapSfixed32Uint32101(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSfixed32Uint64102(populateIntegerMap(longProvider)); + builder.putAllFieldMapSfixed64Bool103(populateLongMap(booleanProvider)); + builder.putAllFieldMapSfixed64Bytes104(populateLongMap(bytesProvider)); + builder.putAllFieldMapSfixed64Double105(populateLongMap(doubleProvider)); + builder.putAllFieldMapSfixed64Enum106(populateLongMap(enumProvider)); + builder.putAllFieldMapSfixed64Fixed32107(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Fixed64108(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64Float109(populateLongMap(floatProvider)); + builder.putAllFieldMapSfixed64Int32110(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Int64111(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64Message112(populateLongMap(messageProvider)); + builder.putAllFieldMapSfixed64Sfixed32113(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Sfixed64114(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64Sint32115(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Sint64116(populateLongMap(longProvider)); + builder.putAllFieldMapSfixed64String117(populateLongMap(stringProvider)); + builder.putAllFieldMapSfixed64Uint32118(populateLongMap(integerProvider)); + builder.putAllFieldMapSfixed64Uint64119(populateLongMap(longProvider)); + builder.putAllFieldMapSint32Bool120(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapSint32Bytes121(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapSint32Double122(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapSint32Enum123(populateIntegerMap(enumProvider)); + builder.putAllFieldMapSint32Fixed32124(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Fixed64125(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32Float126(populateIntegerMap(floatProvider)); + builder.putAllFieldMapSint32Int32127(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Int64128(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32Message129(populateIntegerMap(messageProvider)); + builder.putAllFieldMapSint32Sfixed32130(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Sfixed64131(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32Sint32132(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Sint64133(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint32String134(populateIntegerMap(stringProvider)); + builder.putAllFieldMapSint32Uint32135(populateIntegerMap(integerProvider)); + builder.putAllFieldMapSint32Uint64136(populateIntegerMap(longProvider)); + builder.putAllFieldMapSint64Bool137(populateLongMap(booleanProvider)); + builder.putAllFieldMapSint64Bytes138(populateLongMap(bytesProvider)); + builder.putAllFieldMapSint64Double139(populateLongMap(doubleProvider)); + builder.putAllFieldMapSint64Enum140(populateLongMap(enumProvider)); + builder.putAllFieldMapSint64Fixed32141(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Fixed64142(populateLongMap(longProvider)); + builder.putAllFieldMapSint64Float143(populateLongMap(floatProvider)); + builder.putAllFieldMapSint64Int32144(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Int64145(populateLongMap(longProvider)); + builder.putAllFieldMapSint64Message146(populateLongMap(messageProvider)); + builder.putAllFieldMapSint64Sfixed32147(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Sfixed64148(populateLongMap(longProvider)); + builder.putAllFieldMapSint64Sint32149(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Sint64150(populateLongMap(longProvider)); + builder.putAllFieldMapSint64String151(populateLongMap(stringProvider)); + builder.putAllFieldMapSint64Uint32152(populateLongMap(integerProvider)); + builder.putAllFieldMapSint64Uint64153(populateLongMap(longProvider)); + builder.putAllFieldMapStringBool154(populateStringMap(booleanProvider)); + builder.putAllFieldMapStringBytes155(populateStringMap(bytesProvider)); + builder.putAllFieldMapStringDouble156(populateStringMap(doubleProvider)); + builder.putAllFieldMapStringEnum157(populateStringMap(enumProvider)); + builder.putAllFieldMapStringFixed32158(populateStringMap(integerProvider)); + builder.putAllFieldMapStringFixed64159(populateStringMap(longProvider)); + builder.putAllFieldMapStringFloat160(populateStringMap(floatProvider)); + builder.putAllFieldMapStringInt32161(populateStringMap(integerProvider)); + builder.putAllFieldMapStringInt64162(populateStringMap(longProvider)); + builder.putAllFieldMapStringMessage163(populateStringMap(messageProvider)); + builder.putAllFieldMapStringSfixed32164(populateStringMap(integerProvider)); + builder.putAllFieldMapStringSfixed64165(populateStringMap(longProvider)); + builder.putAllFieldMapStringSint32166(populateStringMap(integerProvider)); + builder.putAllFieldMapStringSint64167(populateStringMap(longProvider)); + builder.putAllFieldMapStringString168(populateStringMap(stringProvider)); + builder.putAllFieldMapStringUint32169(populateStringMap(integerProvider)); + builder.putAllFieldMapStringUint64170(populateStringMap(longProvider)); + builder.putAllFieldMapUint32Bool171(populateIntegerMap(booleanProvider)); + builder.putAllFieldMapUint32Bytes172(populateIntegerMap(bytesProvider)); + builder.putAllFieldMapUint32Double173(populateIntegerMap(doubleProvider)); + builder.putAllFieldMapUint32Enum174(populateIntegerMap(enumProvider)); + builder.putAllFieldMapUint32Fixed32175(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Fixed64176(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32Float177(populateIntegerMap(floatProvider)); + builder.putAllFieldMapUint32Int32178(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Int64179(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32Message180(populateIntegerMap(messageProvider)); + builder.putAllFieldMapUint32Sfixed32181(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Sfixed64182(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32Sint32183(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Sint64184(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint32String185(populateIntegerMap(stringProvider)); + builder.putAllFieldMapUint32Uint32186(populateIntegerMap(integerProvider)); + builder.putAllFieldMapUint32Uint64187(populateIntegerMap(longProvider)); + builder.putAllFieldMapUint64Bool188(populateLongMap(booleanProvider)); + builder.putAllFieldMapUint64Bytes189(populateLongMap(bytesProvider)); + builder.putAllFieldMapUint64Double190(populateLongMap(doubleProvider)); + builder.putAllFieldMapUint64Enum191(populateLongMap(enumProvider)); + builder.putAllFieldMapUint64Fixed32192(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Fixed64193(populateLongMap(longProvider)); + builder.putAllFieldMapUint64Float194(populateLongMap(floatProvider)); + builder.putAllFieldMapUint64Int32195(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Int64196(populateLongMap(longProvider)); + builder.putAllFieldMapUint64Message197(populateLongMap(messageProvider)); + builder.putAllFieldMapUint64Sfixed32198(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Sfixed64199(populateLongMap(longProvider)); + builder.putAllFieldMapUint64Sint32200(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Sint64201(populateLongMap(longProvider)); + builder.putAllFieldMapUint64String202(populateLongMap(stringProvider)); + builder.putAllFieldMapUint64Uint32203(populateLongMap(integerProvider)); + builder.putAllFieldMapUint64Uint64204(populateLongMap(longProvider)); + + return builder.build(); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java b/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java new file mode 100644 index 0000000000000..3c0c629c20dec --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java @@ -0,0 +1,816 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.FieldInfo.forField; +import static com.google.protobuf.FieldInfo.forMapField; +import static com.google.protobuf.FieldInfo.forOneofMemberField; +import static com.google.protobuf.FieldInfo.forRepeatedMessageField; + +import com.google.protobuf.testing.Proto3TestingLite.Proto3EmptyLite; +import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLite; +import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLiteWithMaps; +import java.lang.reflect.Field; + +/** A factory that generates a hard-coded info for {@link Proto3MessageLite}. */ +public final class Proto3MessageLiteInfoFactory implements MessageInfoFactory { + private static final Proto3MessageLiteInfoFactory instanceForRawMessageInfo = + new Proto3MessageLiteInfoFactory(true); + private static final Proto3MessageLiteInfoFactory instanceForStructuralMessageInfo = + new Proto3MessageLiteInfoFactory(false); + + public static Proto3MessageLiteInfoFactory getInstanceForRawMessageInfo() { + return instanceForRawMessageInfo; + } + + public static Proto3MessageLiteInfoFactory getInstanceForStructuralMessageInfo() { + return instanceForStructuralMessageInfo; + } + + private final boolean produceRawMessageInfo; + + private Proto3MessageLiteInfoFactory(boolean produceRawMessageInfo) { + this.produceRawMessageInfo = produceRawMessageInfo; + } + + @Override + public boolean isSupported(Class clazz) { + return true; + } + + @Override + public MessageInfo messageInfoFor(Class clazz) { + return produceRawMessageInfo ? rawMessageInfoFor(clazz) : structuralMessageInfoFor(clazz); + } + + private MessageInfo rawMessageInfoFor(Class clazz) { + if (Proto3MessageLite.class.isAssignableFrom(clazz)) { + return newRawMessageInfoForProto3MessageLite(); + } else { + throw new IllegalArgumentException("Unsupported class: " + clazz.getName()); + } + } + + private MessageInfo newRawMessageInfoForProto3MessageLite() { + java.lang.Object[] objects = + new java.lang.Object[] { + "testOneof_", + "testOneofCase_", + "fieldDouble1_", + "fieldFloat2_", + "fieldInt643_", + "fieldUint644_", + "fieldInt325_", + "fieldFixed646_", + "fieldFixed327_", + "fieldBool8_", + "fieldString9_", + "fieldMessage10_", + "fieldBytes11_", + "fieldUint3212_", + "fieldEnum13_", + "fieldSfixed3214_", + "fieldSfixed6415_", + "fieldSint3216_", + "fieldSint6417_", + "fieldDoubleList18_", + "fieldFloatList19_", + "fieldInt64List20_", + "fieldUint64List21_", + "fieldInt32List22_", + "fieldFixed64List23_", + "fieldFixed32List24_", + "fieldBoolList25_", + "fieldStringList26_", + "fieldMessageList27_", + Proto3MessageLite.class, + "fieldBytesList28_", + "fieldUint32List29_", + "fieldEnumList30_", + "fieldSfixed32List31_", + "fieldSfixed64List32_", + "fieldSint32List33_", + "fieldSint64List34_", + "fieldDoubleListPacked35_", + "fieldFloatListPacked36_", + "fieldInt64ListPacked37_", + "fieldUint64ListPacked38_", + "fieldInt32ListPacked39_", + "fieldFixed64ListPacked40_", + "fieldFixed32ListPacked41_", + "fieldBoolListPacked42_", + "fieldUint32ListPacked43_", + "fieldEnumListPacked44_", + "fieldSfixed32ListPacked45_", + "fieldSfixed64ListPacked46_", + "fieldSint32ListPacked47_", + "fieldSint64ListPacked48_", + Proto3MessageLite.class, + }; + // To update this after a proto change, run protoc on proto3_message_lite.proto and copy over + // the content of the generated buildMessageInfo() method here. + java.lang.String info = + "\u0000@\u0001\u0000\u0001D@\u0000\u001f\u0000\u0001\u0000\u0002\u0001\u0003\u0002" + + "\u0004\u0003\u0005\u0004\u0006\u0005\u0007\u0006\b\u0007\t\u0208\n\t\u000b\n\f\u000b" + + "\r\f\u000e\r\u000f\u000e\u0010\u000f\u0011\u0010\u0012\u0012\u0013\u0013\u0014\u0014" + + "\u0015\u0015\u0016\u0016\u0017\u0017\u0018\u0018\u0019\u0019\u001a\u021a\u001b\u001b" + + "\u001c\u001c\u001d\u001d\u001e\u001e\u001f\u001f !!\"\"##$$%%&&\'\'(())**++,,--" + + "..//0053\u000064\u000075\u000086\u000097\u0000:8\u0000;9\u0000<:\u0000=\u023b\u0000" + + "><\u0000?=\u0000@>\u0000A@\u0000BA\u0000CB\u0000DC\u0000"; + return new RawMessageInfo(Proto3MessageLite.getDefaultInstance(), info, objects); + } + + private MessageInfo structuralMessageInfoFor(Class clazz) { + if (Proto3MessageLite.class.isAssignableFrom(clazz)) { + return newMessageInfoForProto3MessageLite(); + } else if (Proto3EmptyLite.class.isAssignableFrom(clazz)) { + return newMessageInfoForProto3EmptyLite(); + } else if (Proto3MessageLiteWithMaps.class.isAssignableFrom(clazz)) { + return newMessageInfoForProto3MessageLiteWithMaps(); + } else { + throw new IllegalArgumentException("Unsupported class: " + clazz.getName()); + } + } + + /** + * Creates a new hard-coded info for {@link Proto3MessageLite}. Each time this is called, we + * manually go through the entire process of what a message would do if it self-registered its own + * info, including looking up each field by name. This is done for benchmarking purposes, so that + * we get a more accurate representation of the time it takes to perform this process. + */ + private static StructuralMessageInfo newMessageInfoForProto3MessageLite() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(48); + lookupFieldsByName(builder); + return builder.build(); + } + + private static void lookupFieldsByName(StructuralMessageInfo.Builder builder) { + builder.withDefaultInstance(Proto3MessageLite.getDefaultInstance()); + builder.withSyntax(ProtoSyntax.PROTO3); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldDouble1_"), 1, FieldType.DOUBLE, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldFloat2_"), 2, FieldType.FLOAT, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldInt643_"), 3, FieldType.INT64, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldUint644_"), 4, FieldType.UINT64, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldInt325_"), 5, FieldType.INT32, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldFixed646_"), 6, FieldType.FIXED64, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldFixed327_"), 7, FieldType.FIXED32, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldBool8_"), 8, FieldType.BOOL, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldString9_"), 9, FieldType.STRING, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldMessage10_"), 10, FieldType.MESSAGE, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldBytes11_"), 11, FieldType.BYTES, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldUint3212_"), 12, FieldType.UINT32, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldEnum13_"), 13, FieldType.ENUM, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldSfixed3214_"), 14, FieldType.SFIXED32, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldSfixed6415_"), 15, FieldType.SFIXED64, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldSint3216_"), 16, FieldType.SINT32, true)); + builder.withField( + forField(field(Proto3MessageLite.class, "fieldSint6417_"), 17, FieldType.SINT64, true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldDoubleList18_"), 18, FieldType.DOUBLE_LIST, true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldFloatList19_"), 19, FieldType.FLOAT_LIST, true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldInt64List20_"), 20, FieldType.INT64_LIST, true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldUint64List21_"), 21, FieldType.UINT64_LIST, true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldInt32List22_"), 22, FieldType.INT32_LIST, true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldFixed64List23_"), + 23, + FieldType.FIXED64_LIST, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldFixed32List24_"), + 24, + FieldType.FIXED32_LIST, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldBoolList25_"), 25, FieldType.BOOL_LIST, true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldStringList26_"), 26, FieldType.STRING_LIST, true)); + builder.withField( + forRepeatedMessageField( + field(Proto3MessageLite.class, "fieldMessageList27_"), + 27, + FieldType.MESSAGE_LIST, + Proto3MessageLite.class)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldBytesList28_"), 28, FieldType.BYTES_LIST, true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldUint32List29_"), 29, FieldType.UINT32_LIST, true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldEnumList30_"), 30, FieldType.ENUM_LIST, true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldSfixed32List31_"), + 31, + FieldType.SFIXED32_LIST, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldSfixed64List32_"), + 32, + FieldType.SFIXED64_LIST, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldSint32List33_"), 33, FieldType.SINT32_LIST, true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldSint64List34_"), 34, FieldType.SINT64_LIST, true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldDoubleListPacked35_"), + 35, + FieldType.DOUBLE_LIST_PACKED, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldFloatListPacked36_"), + 36, + FieldType.FLOAT_LIST_PACKED, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldInt64ListPacked37_"), + 37, + FieldType.INT64_LIST_PACKED, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldUint64ListPacked38_"), + 38, + FieldType.UINT64_LIST_PACKED, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldInt32ListPacked39_"), + 39, + FieldType.INT32_LIST_PACKED, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldFixed64ListPacked40_"), + 40, + FieldType.FIXED64_LIST_PACKED, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldFixed32ListPacked41_"), + 41, + FieldType.FIXED32_LIST_PACKED, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldBoolListPacked42_"), + 42, + FieldType.BOOL_LIST_PACKED, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldUint32ListPacked43_"), + 43, + FieldType.UINT32_LIST_PACKED, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldEnumListPacked44_"), + 44, + FieldType.ENUM_LIST_PACKED, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldSfixed32ListPacked45_"), + 45, + FieldType.SFIXED32_LIST_PACKED, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldSfixed64ListPacked46_"), + 46, + FieldType.SFIXED64_LIST_PACKED, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldSint32ListPacked47_"), + 47, + FieldType.SINT32_LIST_PACKED, + true)); + builder.withField( + forField( + field(Proto3MessageLite.class, "fieldSint64ListPacked48_"), + 48, + FieldType.SINT64_LIST_PACKED, + true)); + + OneofInfo oneof = + new OneofInfo( + 0, + field(Proto3MessageLite.class, "testOneofCase_"), + field(Proto3MessageLite.class, "testOneof_")); + builder.withField(forOneofMemberField(53, FieldType.DOUBLE, oneof, Double.class, true, null)); + builder.withField(forOneofMemberField(54, FieldType.FLOAT, oneof, Float.class, true, null)); + builder.withField(forOneofMemberField(55, FieldType.INT64, oneof, Long.class, true, null)); + builder.withField(forOneofMemberField(56, FieldType.UINT64, oneof, Long.class, true, null)); + builder.withField(forOneofMemberField(57, FieldType.INT32, oneof, Integer.class, true, null)); + builder.withField(forOneofMemberField(58, FieldType.FIXED64, oneof, Long.class, true, null)); + builder.withField(forOneofMemberField(59, FieldType.FIXED32, oneof, Integer.class, true, null)); + builder.withField(forOneofMemberField(60, FieldType.BOOL, oneof, Boolean.class, true, null)); + builder.withField(forOneofMemberField(61, FieldType.STRING, oneof, String.class, true, null)); + builder.withField( + forOneofMemberField(62, FieldType.MESSAGE, oneof, Proto3MessageLite.class, true, null)); + builder.withField( + forOneofMemberField(63, FieldType.BYTES, oneof, ByteString.class, true, null)); + builder.withField(forOneofMemberField(64, FieldType.UINT32, oneof, Integer.class, true, null)); + builder.withField( + forOneofMemberField(65, FieldType.SFIXED32, oneof, Integer.class, true, null)); + builder.withField(forOneofMemberField(66, FieldType.SFIXED64, oneof, Long.class, true, null)); + builder.withField(forOneofMemberField(67, FieldType.SINT32, oneof, Integer.class, true, null)); + builder.withField(forOneofMemberField(68, FieldType.SINT64, oneof, Long.class, true, null)); + } + + private StructuralMessageInfo newMessageInfoForProto3EmptyLite() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO3); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForProto3MessageLiteWithMaps() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(); + builder.withSyntax(ProtoSyntax.PROTO2); + builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_bool_1", 1)); + builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_bytes_2", 2)); + builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_double_3", 3)); + builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_enum_4", 4)); + builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_fixed32_5", 5)); + builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_fixed64_6", 6)); + builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_float_7", 7)); + builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_int32_8", 8)); + builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_int64_9", 9)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_message_10", 10)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_sfixed32_11", 11)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_sfixed64_12", 12)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_sint32_13", 13)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_sint64_14", 14)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_string_15", 15)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_uint32_16", 16)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_uint64_17", 17)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_bool_18", 18)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_bytes_19", 19)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_double_20", 20)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_enum_21", 21)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_fixed32_22", 22)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_fixed64_23", 23)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_float_24", 24)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_int32_25", 25)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_int64_26", 26)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_message_27", 27)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_sfixed32_28", 28)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_sfixed64_29", 29)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_sint32_30", 30)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_sint64_31", 31)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_string_32", 32)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_uint32_33", 33)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_uint64_34", 34)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_bool_35", 35)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_bytes_36", 36)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_double_37", 37)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_enum_38", 38)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_fixed32_39", 39)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_fixed64_40", 40)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_float_41", 41)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_int32_42", 42)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_int64_43", 43)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_message_44", 44)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_sfixed32_45", 45)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_sfixed64_46", 46)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_sint32_47", 47)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_sint64_48", 48)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_string_49", 49)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_uint32_50", 50)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_uint64_51", 51)); + builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_bool_52", 52)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_bytes_53", 53)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_double_54", 54)); + builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_enum_55", 55)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_fixed32_56", 56)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_fixed64_57", 57)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_float_58", 58)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_int32_59", 59)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_int64_60", 60)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_message_61", 61)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_sfixed32_62", 62)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_sfixed64_63", 63)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_sint32_64", 64)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_sint64_65", 65)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_string_66", 66)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_uint32_67", 67)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_uint64_68", 68)); + builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_bool_69", 69)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_bytes_70", 70)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_double_71", 71)); + builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_enum_72", 72)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_fixed32_73", 73)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_fixed64_74", 74)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_float_75", 75)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_int32_76", 76)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_int64_77", 77)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_message_78", 78)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_sfixed32_79", 79)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_sfixed64_80", 80)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_sint32_81", 81)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_sint64_82", 82)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_string_83", 83)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_uint32_84", 84)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_uint64_85", 85)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_bool_86", 86)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_bytes_87", 87)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_double_88", 88)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_enum_89", 89)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_fixed32_90", 90)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_fixed64_91", 91)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_float_92", 92)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_int32_93", 93)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_int64_94", 94)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_message_95", 95)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_sfixed32_96", 96)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_sfixed64_97", 97)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_sint32_98", 98)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_sint64_99", 99)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_string_100", 100)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_uint32_101", 101)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_uint64_102", 102)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_bool_103", 103)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_bytes_104", 104)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_double_105", 105)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_enum_106", 106)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_fixed32_107", 107)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_fixed64_108", 108)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_float_109", 109)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_int32_110", 110)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_int64_111", 111)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_message_112", 112)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_sfixed32_113", 113)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_sfixed64_114", 114)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_sint32_115", 115)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_sint64_116", 116)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_string_117", 117)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_uint32_118", 118)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_uint64_119", 119)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_bool_120", 120)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_bytes_121", 121)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_double_122", 122)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_enum_123", 123)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_fixed32_124", 124)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_fixed64_125", 125)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_float_126", 126)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_int32_127", 127)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_int64_128", 128)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_message_129", 129)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_sfixed32_130", 130)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_sfixed64_131", 131)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_sint32_132", 132)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_sint64_133", 133)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_string_134", 134)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_uint32_135", 135)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_uint64_136", 136)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_bool_137", 137)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_bytes_138", 138)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_double_139", 139)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_enum_140", 140)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_fixed32_141", 141)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_fixed64_142", 142)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_float_143", 143)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_int32_144", 144)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_int64_145", 145)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_message_146", 146)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_sfixed32_147", 147)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_sfixed64_148", 148)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_sint32_149", 149)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_sint64_150", 150)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_string_151", 151)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_uint32_152", 152)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_uint64_153", 153)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_bool_154", 154)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_bytes_155", 155)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_double_156", 156)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_enum_157", 157)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_fixed32_158", 158)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_fixed64_159", 159)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_float_160", 160)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_int32_161", 161)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_int64_162", 162)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_message_163", 163)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_sfixed32_164", 164)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_sfixed64_165", 165)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_sint32_166", 166)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_sint64_167", 167)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_string_168", 168)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_uint32_169", 169)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_uint64_170", 170)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_bool_171", 171)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_bytes_172", 172)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_double_173", 173)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_enum_174", 174)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_fixed32_175", 175)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_fixed64_176", 176)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_float_177", 177)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_int32_178", 178)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_int64_179", 179)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_message_180", 180)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_sfixed32_181", 181)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_sfixed64_182", 182)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_sint32_183", 183)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_sint64_184", 184)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_string_185", 185)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_uint32_186", 186)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_uint64_187", 187)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_bool_188", 188)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_bytes_189", 189)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_double_190", 190)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_enum_191", 191)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_fixed32_192", 192)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_fixed64_193", 193)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_float_194", 194)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_int32_195", 195)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_int64_196", 196)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_message_197", 197)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_sfixed32_198", 198)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_sfixed64_199", 199)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_sint32_200", 200)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_sint64_201", 201)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_string_202", 202)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_uint32_203", 203)); + builder.withField( + mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_uint64_204", 204)); + + return builder.build(); + } + + private static Field field(Class clazz, String name) { + try { + return clazz.getDeclaredField(name); + } catch (NoSuchFieldException | SecurityException e) { + throw new RuntimeException(e); + } + } + + private static FieldInfo mapFieldInfo(Class clazz, String fieldName, int fieldNumber) { + try { + return forMapField( + field(clazz, SchemaUtil.toCamelCase(fieldName, false) + "_"), + fieldNumber, + SchemaUtil.getMapDefaultEntry(clazz, fieldName), + null); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } +} diff --git a/java/core/src/test/java/com/google/protobuf/Proto3SchemaTest.java b/java/core/src/test/java/com/google/protobuf/Proto3SchemaTest.java new file mode 100644 index 0000000000000..5cd145be74a51 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Proto3SchemaTest.java @@ -0,0 +1,48 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.testing.Proto3Testing.Proto3Message; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class Proto3SchemaTest extends AbstractProto3SchemaTest { + @Override + protected void registerSchemas() { + TestSchemas.registerGenericProto3Schemas(); + } + + @Override + protected Schema schema() { + return TestSchemas.genericProto3Schema; + } +} diff --git a/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java b/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java index af717bfd20145..67b2881a436d8 100644 --- a/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java +++ b/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java @@ -38,37 +38,35 @@ import java.util.List; import junit.framework.TestCase; -/** - * Tests for {@link ProtobufArrayList}. - */ +/** Tests for {@link ProtobufArrayList}. */ public class ProtobufArrayListTest extends TestCase { - + private static final ProtobufArrayList UNARY_LIST = newImmutableProtoArrayList(1); private static final ProtobufArrayList TERTIARY_LIST = newImmutableProtoArrayList(1, 2, 3); - + private ProtobufArrayList list; - + @Override protected void setUp() throws Exception { list = new ProtobufArrayList(); } - + public void testEmptyListReturnsSameInstance() { assertSame(ProtobufArrayList.emptyList(), ProtobufArrayList.emptyList()); } - + public void testEmptyListIsImmutable() { assertImmutable(ProtobufArrayList.emptyList()); } - + public void testModificationWithIteration() { list.addAll(asList(1, 2, 3, 4)); Iterator iterator = list.iterator(); assertEquals(4, list.size()); assertEquals(1, (int) list.get(0)); assertEquals(1, (int) iterator.next()); - + list.remove(0); try { iterator.next(); @@ -76,7 +74,7 @@ public void testModificationWithIteration() { } catch (ConcurrentModificationException e) { // expected } - + iterator = list.iterator(); list.set(0, 1); try { @@ -85,7 +83,7 @@ public void testModificationWithIteration() { } catch (ConcurrentModificationException e) { // expected } - + iterator = list.iterator(); list.add(0, 0); try { @@ -95,7 +93,7 @@ public void testModificationWithIteration() { // expected } } - + public void testMakeImmutable() { list.add(2); list.add(4); @@ -104,107 +102,213 @@ public void testMakeImmutable() { list.makeImmutable(); assertImmutable(list); } - + public void testRemove() { - list.add(2); - list.add(4); - list.add(6); + list.addAll(TERTIARY_LIST); + assertEquals(1, (int) list.remove(0)); + assertEquals(asList(2, 3), list); - list.remove(1); - assertEquals(asList(2, 6), list); + assertTrue(list.remove(Integer.valueOf(3))); + assertEquals(asList(2), list); - list.remove(1); + assertFalse(list.remove(Integer.valueOf(3))); assertEquals(asList(2), list); - list.remove(0); + assertEquals(2, (int) list.remove(0)); assertEquals(asList(), list); + + try { + list.remove(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.remove(0); + } catch (IndexOutOfBoundsException e) { + // expected + } } - + public void testGet() { - list.add(2); - list.add(6); - - assertEquals(2, (int) list.get(0)); - assertEquals(6, (int) list.get(1)); + assertEquals(1, (int) TERTIARY_LIST.get(0)); + assertEquals(2, (int) TERTIARY_LIST.get(1)); + assertEquals(3, (int) TERTIARY_LIST.get(2)); + + try { + TERTIARY_LIST.get(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + TERTIARY_LIST.get(3); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } } - + public void testSet() { list.add(2); - list.add(6); - - list.set(0, 1); + list.add(4); + + assertEquals(2, (int) list.set(0, 3)); + assertEquals(3, (int) list.get(0)); + + assertEquals(4, (int) list.set(1, 0)); + assertEquals(0, (int) list.get(1)); + + try { + list.set(-1, 0); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.set(2, 0); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testAdd() { + assertEquals(0, list.size()); + + assertTrue(list.add(2)); + assertEquals(asList(2), list); + + assertTrue(list.add(3)); + list.add(0, 4); + assertEquals(asList(4, 2, 3), list); + + list.add(0, 1); + list.add(0, 0); + // Force a resize by getting up to 11 elements. + for (int i = 0; i < 6; i++) { + list.add(Integer.valueOf(5 + i)); + } + assertEquals(asList(0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10), list); + + try { + list.add(-1, 5); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.add(4, 5); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testAddAll() { + assertEquals(0, list.size()); + + assertTrue(list.addAll(Collections.singleton(1))); + assertEquals(1, list.size()); assertEquals(1, (int) list.get(0)); - list.set(1, 2); - assertEquals(2, (int) list.get(1)); + + assertTrue(list.addAll(asList(2, 3, 4, 5, 6))); + assertEquals(asList(1, 2, 3, 4, 5, 6), list); + + assertTrue(list.addAll(TERTIARY_LIST)); + assertEquals(asList(1, 2, 3, 4, 5, 6, 1, 2, 3), list); + + assertFalse(list.addAll(Collections.emptyList())); + assertFalse(list.addAll(IntArrayList.emptyList())); + } + + public void testSize() { + assertEquals(0, ProtobufArrayList.emptyList().size()); + assertEquals(1, UNARY_LIST.size()); + assertEquals(3, TERTIARY_LIST.size()); + + list.add(3); + list.add(4); + list.add(6); + list.add(8); + assertEquals(4, list.size()); + + list.remove(0); + assertEquals(3, list.size()); + + list.add(17); + assertEquals(4, list.size()); } private void assertImmutable(List list) { if (list.contains(1)) { throw new RuntimeException("Cannot test the immutability of lists that contain 1."); } - + try { list.add(1); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.add(0, 1); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(Collections.emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(Collections.singletonList(1)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(new ProtobufArrayList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, Collections.singleton(1)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.addAll(0, Collections.emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected - } + } try { list.clear(); @@ -219,56 +323,56 @@ private void assertImmutable(List list) { } catch (UnsupportedOperationException e) { // expected } - + try { list.remove(new Object()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(Collections.emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(Collections.singleton(1)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.removeAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(Collections.emptyList()); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(Collections.singleton(1)); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.retainAll(UNARY_LIST); fail(); } catch (UnsupportedOperationException e) { // expected } - + try { list.set(0, 0); fail(); @@ -276,7 +380,7 @@ private void assertImmutable(List list) { // expected } } - + private static ProtobufArrayList newImmutableProtoArrayList(int... elements) { ProtobufArrayList list = new ProtobufArrayList(); for (int element : elements) { diff --git a/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java b/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java index edbd0afd75bd4..c42813c8080b6 100644 --- a/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java +++ b/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java @@ -37,9 +37,8 @@ import junit.framework.TestCase; /** - * Tests for {@link RepeatedFieldBuilderV3}. This tests basic functionality. - * More extensive testing is provided via other tests that exercise the - * builder. + * Tests for {@link RepeatedFieldBuilderV3}. This tests basic functionality. More extensive testing is + * provided via other tests that exercise the builder. * * @author jonp@google.com (Jon Perlow) */ @@ -47,8 +46,8 @@ public class RepeatedFieldBuilderV3Test extends TestCase { public void testBasicUse() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - RepeatedFieldBuilderV3 builder = newRepeatedFieldBuilderV3(mockParent); + RepeatedFieldBuilderV3 builder = + newRepeatedFieldBuilderV3(mockParent); builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); assertEquals(0, builder.getMessage(0).getOptionalInt32()); @@ -68,8 +67,8 @@ public void testBasicUse() { public void testGoingBackAndForth() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - RepeatedFieldBuilderV3 builder = newRepeatedFieldBuilderV3(mockParent); + RepeatedFieldBuilderV3 builder = + newRepeatedFieldBuilderV3(mockParent); builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); assertEquals(0, builder.getMessage(0).getOptionalInt32()); @@ -89,7 +88,7 @@ public void testGoingBackAndForth() { list = builder.build(); assertEquals(2, list.size()); assertEquals(0, list.get(0).getOptionalInt32()); - assertEquals("foo", list.get(0).getOptionalString()); + assertEquals("foo", list.get(0).getOptionalString()); assertEquals(1, list.get(1).getOptionalInt32()); assertIsUnmodifiable(list); assertEquals(1, mockParent.getInvalidationCount()); @@ -97,12 +96,11 @@ public void testGoingBackAndForth() { public void testVariousMethods() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - RepeatedFieldBuilderV3 builder = newRepeatedFieldBuilderV3(mockParent); + RepeatedFieldBuilderV3 builder = + newRepeatedFieldBuilderV3(mockParent); builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(2).build()); - builder.addBuilder(0, TestAllTypes.getDefaultInstance()) - .setOptionalInt32(0); + builder.addBuilder(0, TestAllTypes.getDefaultInstance()).setOptionalInt32(0); builder.addBuilder(TestAllTypes.getDefaultInstance()).setOptionalInt32(3); assertEquals(0, builder.getMessage(0).getOptionalInt32()); @@ -139,11 +137,10 @@ public void testVariousMethods() { public void testLists() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - RepeatedFieldBuilderV3 builder = newRepeatedFieldBuilderV3(mockParent); + RepeatedFieldBuilderV3 builder = + newRepeatedFieldBuilderV3(mockParent); builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); - builder.addMessage(0, - TestAllTypes.newBuilder().setOptionalInt32(0).build()); + builder.addMessage(0, TestAllTypes.newBuilder().setOptionalInt32(0).build()); assertEquals(0, builder.getMessage(0).getOptionalInt32()); assertEquals(1, builder.getMessage(1).getOptionalInt32()); @@ -178,11 +175,9 @@ private void assertIsUnmodifiable(List list) { } } - private RepeatedFieldBuilderV3 + private RepeatedFieldBuilderV3 newRepeatedFieldBuilderV3(GeneratedMessage.BuilderParent parent) { - return new RepeatedFieldBuilderV3(Collections.emptyList(), false, - parent, false); + return new RepeatedFieldBuilderV3( + Collections.emptyList(), false, parent, false); } } diff --git a/java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java b/java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java index dc56f2e9ac2ac..d7262161ddb6c 100644 --- a/java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java +++ b/java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java @@ -34,8 +34,8 @@ import java.util.Iterator; /** - * This class tests {@link RopeByteString#substring(int, int)} by inheriting the tests from - * {@link LiteralByteStringTest}. Only a couple of methods are overridden. + * This class tests {@link RopeByteString#substring(int, int)} by inheriting the tests from {@link + * LiteralByteStringTest}. Only a couple of methods are overridden. * * @author carlanton@google.com (Carl Haverl) */ @@ -61,8 +61,8 @@ protected void setUp() throws Exception { @Override public void testGetTreeDepth() { - assertEquals(classUnderTest + " must have the expected tree depth", - 3, stringUnderTest.getTreeDepth()); + assertEquals( + classUnderTest + " must have the expected tree depth", 3, stringUnderTest.getTreeDepth()); } @Override @@ -84,15 +84,18 @@ public void testToString() throws UnsupportedEncodingException { testString = testString.substring(2, testString.length() - 6); unicode = unicode.substring(2, unicode.size() - 6); - assertEquals(classUnderTest + " from string must have the expected type", - classUnderTest, getActualClassName(unicode)); + assertEquals( + classUnderTest + " from string must have the expected type", + classUnderTest, + getActualClassName(unicode)); String roundTripString = unicode.toString(UTF_8); - assertEquals(classUnderTest + " unicode bytes must match", - testString, roundTripString); + assertEquals(classUnderTest + " unicode bytes must match", testString, roundTripString); ByteString flatString = ByteString.copyFromUtf8(testString); assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode); - assertEquals(classUnderTest + " string must must have same hashCode as the flat string", - flatString.hashCode(), unicode.hashCode()); + assertEquals( + classUnderTest + " string must must have same hashCode as the flat string", + flatString.hashCode(), + unicode.hashCode()); } @Override @@ -114,14 +117,17 @@ public void testCharsetToString() { testString = testString.substring(2, testString.length() - 6); unicode = unicode.substring(2, unicode.size() - 6); - assertEquals(classUnderTest + " from string must have the expected type", - classUnderTest, getActualClassName(unicode)); + assertEquals( + classUnderTest + " from string must have the expected type", + classUnderTest, + getActualClassName(unicode)); String roundTripString = unicode.toString(Internal.UTF_8); - assertEquals(classUnderTest + " unicode bytes must match", - testString, roundTripString); + assertEquals(classUnderTest + " unicode bytes must match", testString, roundTripString); ByteString flatString = ByteString.copyFromUtf8(testString); assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode); - assertEquals(classUnderTest + " string must must have same hashCode as the flat string", - flatString.hashCode(), unicode.hashCode()); + assertEquals( + classUnderTest + " string must must have same hashCode as the flat string", + flatString.hashCode(), + unicode.hashCode()); } } diff --git a/java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java b/java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java index 4ec3a409882cd..46c2d8678a47b 100644 --- a/java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java +++ b/java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java @@ -40,8 +40,8 @@ import java.util.Iterator; /** - * This class tests {@link RopeByteString} by inheriting the tests from - * {@link LiteralByteStringTest}. Only a couple of methods are overridden. + * This class tests {@link RopeByteString} by inheriting the tests from {@link + * LiteralByteStringTest}. Only a couple of methods are overridden. * *

A full test of the result of {@link RopeByteString#substring(int, int)} is found in the * separate class {@link RopeByteStringSubstringTest}. @@ -62,10 +62,26 @@ protected void setUp() throws Exception { expectedHashCode = -1214197238; } + public void testMinLength() { + // minLength should match the Fibonacci sequence + int a = 1; + int b = 1; + int i; + for (i = 0; a > 0; i++) { + assertEquals(a, RopeByteString.minLength(i)); + int c = a + b; + a = b; + b = c; + } + assertEquals(Integer.MAX_VALUE, RopeByteString.minLength(i)); + assertEquals(Integer.MAX_VALUE, RopeByteString.minLength(i + 1)); + assertEquals(i + 1, RopeByteString.minLengthByDepth.length); + } + @Override public void testGetTreeDepth() { - assertEquals(classUnderTest + " must have the expected tree depth", - 4, stringUnderTest.getTreeDepth()); + assertEquals( + classUnderTest + " must have the expected tree depth", 4, stringUnderTest.getTreeDepth()); } public void testBalance() { @@ -79,17 +95,22 @@ public void testBalance() { concatenated = concatenated.concat(ByteString.copyFrom(testBytes, i * pieceSize, pieceSize)); } - assertEquals(classUnderTest + " from string must have the expected type", - classUnderTest, getActualClassName(concatenated)); - assertTrue(classUnderTest + " underlying bytes must match after balancing", + assertEquals( + classUnderTest + " from string must have the expected type", + classUnderTest, + getActualClassName(concatenated)); + assertTrue( + classUnderTest + " underlying bytes must match after balancing", Arrays.equals(testBytes, concatenated.toByteArray())); ByteString testString = ByteString.copyFrom(testBytes); - assertTrue(classUnderTest + " balanced string must equal flat string", - concatenated.equals(testString)); - assertTrue(classUnderTest + " flat string must equal balanced string", - testString.equals(concatenated)); - assertEquals(classUnderTest + " balanced string must have same hash code as flat string", - testString.hashCode(), concatenated.hashCode()); + assertEquals( + classUnderTest + " balanced string must equal flat string", testString, concatenated); + assertEquals( + classUnderTest + " flat string must equal balanced string", concatenated, testString); + assertEquals( + classUnderTest + " balanced string must have same hash code as flat string", + testString.hashCode(), + concatenated.hashCode()); } @Override @@ -107,15 +128,18 @@ public void testToString() throws UnsupportedEncodingException { } String testString = builder.toString(); - assertEquals(classUnderTest + " from string must have the expected type", - classUnderTest, getActualClassName(unicode)); + assertEquals( + classUnderTest + " from string must have the expected type", + classUnderTest, + getActualClassName(unicode)); String roundTripString = unicode.toString(UTF_8); - assertEquals(classUnderTest + " unicode bytes must match", - testString, roundTripString); + assertEquals(classUnderTest + " unicode bytes must match", testString, roundTripString); ByteString flatString = ByteString.copyFromUtf8(testString); assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode); - assertEquals(classUnderTest + " string must must have same hashCode as the flat string", - flatString.hashCode(), unicode.hashCode()); + assertEquals( + classUnderTest + " string must must have same hashCode as the flat string", + flatString.hashCode(), + unicode.hashCode()); } @Override @@ -133,30 +157,34 @@ public void testCharsetToString() { } String testString = builder.toString(); - assertEquals(classUnderTest + " from string must have the expected type", - classUnderTest, getActualClassName(unicode)); + assertEquals( + classUnderTest + " from string must have the expected type", + classUnderTest, + getActualClassName(unicode)); String roundTripString = unicode.toString(Internal.UTF_8); - assertEquals(classUnderTest + " unicode bytes must match", - testString, roundTripString); + assertEquals(classUnderTest + " unicode bytes must match", testString, roundTripString); ByteString flatString = ByteString.copyFromUtf8(testString); assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode); - assertEquals(classUnderTest + " string must must have same hashCode as the flat string", - flatString.hashCode(), unicode.hashCode()); + assertEquals( + classUnderTest + " string must must have same hashCode as the flat string", + flatString.hashCode(), + unicode.hashCode()); } @Override public void testToString_returnsCanonicalEmptyString() { RopeByteString ropeByteString = RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY); - assertSame(classUnderTest + " must be the same string references", - ByteString.EMPTY.toString(Internal.UTF_8), ropeByteString.toString(Internal.UTF_8)); + assertSame( + classUnderTest + " must be the same string references", + ByteString.EMPTY.toString(Internal.UTF_8), + ropeByteString.toString(Internal.UTF_8)); } @Override public void testToString_raisesException() { try { - ByteString byteString = - RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY); + ByteString byteString = RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY); byteString.toString("invalid"); fail("Should have thrown an exception."); } catch (UnsupportedEncodingException expected) { @@ -164,8 +192,9 @@ public void testToString_raisesException() { } try { - ByteString byteString = RopeByteString.concatenate(ByteString.copyFromUtf8("foo"), - ByteString.copyFromUtf8("bar")); + ByteString byteString = + RopeByteString.concatenate( + ByteString.copyFromUtf8("foo"), ByteString.copyFromUtf8("bar")); byteString.toString("invalid"); fail("Should have thrown an exception."); } catch (UnsupportedEncodingException expected) { diff --git a/java/core/src/test/java/com/google/protobuf/ServiceTest.java b/java/core/src/test/java/com/google/protobuf/ServiceTest.java index b895ad8d365d0..1592433c2f310 100644 --- a/java/core/src/test/java/com/google/protobuf/ServiceTest.java +++ b/java/core/src/test/java/com/google/protobuf/ServiceTest.java @@ -32,7 +32,6 @@ import com.google.protobuf.Descriptors.FileDescriptor; import com.google.protobuf.Descriptors.MethodDescriptor; -import google.protobuf.no_generic_services_test.UnittestNoGenericServices; import protobuf_unittest.MessageWithNoOuter; import protobuf_unittest.ServiceWithNoOuter; import protobuf_unittest.UnittestProto.BarRequest; @@ -41,7 +40,7 @@ import protobuf_unittest.UnittestProto.FooResponse; import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestService; - +import protobuf_unittest.no_generic_services_test.UnittestNoGenericServices; import java.util.HashSet; import java.util.Set; import junit.framework.TestCase; @@ -59,9 +58,9 @@ public class ServiceTest extends TestCase { private RpcController mockController; private final Descriptors.MethodDescriptor fooDescriptor = - TestService.getDescriptor().getMethods().get(0); + TestService.getDescriptor().getMethods().get(0); private final Descriptors.MethodDescriptor barDescriptor = - TestService.getDescriptor().getMethods().get(1); + TestService.getDescriptor().getMethods().get(1); @Override protected void setUp() throws Exception { @@ -80,16 +79,22 @@ public void testCallMethod() throws Exception { MockCallback barCallback = new MockCallback(); TestService mockService = control.createMock(TestService.class); - mockService.foo(EasyMock.same(mockController), EasyMock.same(fooRequest), - this.wrapsCallback(fooCallback)); - mockService.bar(EasyMock.same(mockController), EasyMock.same(barRequest), - this.wrapsCallback(barCallback)); + mockService.foo( + EasyMock.same(mockController), + EasyMock.same(fooRequest), + this.wrapsCallback(fooCallback)); + mockService.bar( + EasyMock.same(mockController), + EasyMock.same(barRequest), + this.wrapsCallback(barCallback)); control.replay(); - mockService.callMethod(fooDescriptor, mockController, - fooRequest, fooCallback); - mockService.callMethod(barDescriptor, mockController, - barRequest, barCallback); + mockService.callMethod( + fooDescriptor, mockController, + fooRequest, fooCallback); + mockService.callMethod( + barDescriptor, mockController, + barRequest, barCallback); control.verify(); } @@ -97,14 +102,10 @@ public void testCallMethod() throws Exception { public void testGetPrototype() throws Exception { TestService mockService = control.createMock(TestService.class); - assertSame(mockService.getRequestPrototype(fooDescriptor), - FooRequest.getDefaultInstance()); - assertSame(mockService.getResponsePrototype(fooDescriptor), - FooResponse.getDefaultInstance()); - assertSame(mockService.getRequestPrototype(barDescriptor), - BarRequest.getDefaultInstance()); - assertSame(mockService.getResponsePrototype(barDescriptor), - BarResponse.getDefaultInstance()); + assertSame(mockService.getRequestPrototype(fooDescriptor), FooRequest.getDefaultInstance()); + assertSame(mockService.getResponsePrototype(fooDescriptor), FooResponse.getDefaultInstance()); + assertSame(mockService.getRequestPrototype(barDescriptor), BarRequest.getDefaultInstance()); + assertSame(mockService.getResponsePrototype(barDescriptor), BarResponse.getDefaultInstance()); } /** Tests generated stubs. */ @@ -117,17 +118,17 @@ public void testStub() throws Exception { TestService stub = TestService.newStub(mockChannel); mockChannel.callMethod( - EasyMock.same(fooDescriptor), - EasyMock.same(mockController), - EasyMock.same(fooRequest), - EasyMock.same(FooResponse.getDefaultInstance()), - this.wrapsCallback(fooCallback)); + EasyMock.same(fooDescriptor), + EasyMock.same(mockController), + EasyMock.same(fooRequest), + EasyMock.same(FooResponse.getDefaultInstance()), + this.wrapsCallback(fooCallback)); mockChannel.callMethod( - EasyMock.same(barDescriptor), - EasyMock.same(mockController), - EasyMock.same(barRequest), - EasyMock.same(BarResponse.getDefaultInstance()), - this.wrapsCallback(barCallback)); + EasyMock.same(barDescriptor), + EasyMock.same(mockController), + EasyMock.same(barRequest), + EasyMock.same(BarResponse.getDefaultInstance()), + this.wrapsCallback(barCallback)); control.replay(); stub.foo(mockController, fooRequest, fooCallback); @@ -139,24 +140,26 @@ public void testStub() throws Exception { public void testBlockingStub() throws Exception { FooRequest fooRequest = FooRequest.newBuilder().build(); BarRequest barRequest = BarRequest.newBuilder().build(); - BlockingRpcChannel mockChannel = - control.createMock(BlockingRpcChannel.class); - TestService.BlockingInterface stub = - TestService.newBlockingStub(mockChannel); + BlockingRpcChannel mockChannel = control.createMock(BlockingRpcChannel.class); + TestService.BlockingInterface stub = TestService.newBlockingStub(mockChannel); FooResponse fooResponse = FooResponse.newBuilder().build(); BarResponse barResponse = BarResponse.newBuilder().build(); - EasyMock.expect(mockChannel.callBlockingMethod( - EasyMock.same(fooDescriptor), - EasyMock.same(mockController), - EasyMock.same(fooRequest), - EasyMock.same(FooResponse.getDefaultInstance()))).andReturn(fooResponse); - EasyMock.expect(mockChannel.callBlockingMethod( - EasyMock.same(barDescriptor), - EasyMock.same(mockController), - EasyMock.same(barRequest), - EasyMock.same(BarResponse.getDefaultInstance()))).andReturn(barResponse); + EasyMock.expect( + mockChannel.callBlockingMethod( + EasyMock.same(fooDescriptor), + EasyMock.same(mockController), + EasyMock.same(fooRequest), + EasyMock.same(FooResponse.getDefaultInstance()))) + .andReturn(fooResponse); + EasyMock.expect( + mockChannel.callBlockingMethod( + EasyMock.same(barDescriptor), + EasyMock.same(mockController), + EasyMock.same(barRequest), + EasyMock.same(BarResponse.getDefaultInstance()))) + .andReturn(barResponse); control.replay(); assertSame(fooResponse, stub.foo(mockController, fooRequest)); @@ -165,13 +168,11 @@ public void testBlockingStub() throws Exception { } public void testNewReflectiveService() { - ServiceWithNoOuter.Interface impl = - control.createMock(ServiceWithNoOuter.Interface.class); + ServiceWithNoOuter.Interface impl = control.createMock(ServiceWithNoOuter.Interface.class); RpcController controller = control.createMock(RpcController.class); Service service = ServiceWithNoOuter.newReflectiveService(impl); - MethodDescriptor fooMethod = - ServiceWithNoOuter.getDescriptor().findMethodByName("Foo"); + MethodDescriptor fooMethod = ServiceWithNoOuter.getDescriptor().findMethodByName("Foo"); MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance(); RpcCallback callback = new RpcCallback() { @@ -181,11 +182,9 @@ public void run(Message parameter) { fail(); } }; - RpcCallback specializedCallback = - RpcUtil.specializeCallback(callback); + RpcCallback specializedCallback = RpcUtil.specializeCallback(callback); - impl.foo(EasyMock.same(controller), EasyMock.same(request), - EasyMock.same(specializedCallback)); + impl.foo(EasyMock.same(controller), EasyMock.same(request), EasyMock.same(specializedCallback)); EasyMock.expectLastCall(); control.replay(); @@ -199,11 +198,9 @@ public void testNewReflectiveBlockingService() throws ServiceException { ServiceWithNoOuter.BlockingInterface impl = control.createMock(ServiceWithNoOuter.BlockingInterface.class); RpcController controller = control.createMock(RpcController.class); - BlockingService service = - ServiceWithNoOuter.newReflectiveBlockingService(impl); + BlockingService service = ServiceWithNoOuter.newReflectiveBlockingService(impl); - MethodDescriptor fooMethod = - ServiceWithNoOuter.getDescriptor().findMethodByName("Foo"); + MethodDescriptor fooMethod = ServiceWithNoOuter.getDescriptor().findMethodByName("Foo"); MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance(); TestAllTypes expectedResponse = TestAllTypes.getDefaultInstance(); @@ -212,8 +209,7 @@ public void testNewReflectiveBlockingService() throws ServiceException { control.replay(); - Message response = - service.callBlockingMethod(fooMethod, controller, request); + Message response = service.callBlockingMethod(fooMethod, controller, request); assertEquals(expectedResponse, response); control.verify(); @@ -222,16 +218,16 @@ public void testNewReflectiveBlockingService() throws ServiceException { public void testNoGenericServices() throws Exception { // Non-services should be usable. UnittestNoGenericServices.TestMessage message = - UnittestNoGenericServices.TestMessage.newBuilder() - .setA(123) - .setExtension(UnittestNoGenericServices.testExtension, 456) - .build(); + UnittestNoGenericServices.TestMessage.newBuilder() + .setA(123) + .setExtension(UnittestNoGenericServices.testExtension, 456) + .build(); assertEquals(123, message.getA()); assertEquals(1, UnittestNoGenericServices.TestEnum.FOO.getNumber()); // Build a list of the class names nested in UnittestNoGenericServices. - String outerName = "google.protobuf.no_generic_services_test." + - "UnittestNoGenericServices"; + String outerName = + "protobuf_unittest.no_generic_services_test.UnittestNoGenericServices"; Class outerClass = Class.forName(outerName); Set innerClassNames = new HashSet(); @@ -245,9 +241,9 @@ public void testNoGenericServices() throws Exception { // separator. assertTrue(fullName.startsWith(outerName)); - if (!Service.class.isAssignableFrom(innerClass) && - !Message.class.isAssignableFrom(innerClass) && - !ProtocolMessageEnum.class.isAssignableFrom(innerClass)) { + if (!Service.class.isAssignableFrom(innerClass) + && !Message.class.isAssignableFrom(innerClass) + && !ProtocolMessageEnum.class.isAssignableFrom(innerClass)) { // Ignore any classes not generated by the base code generator. continue; } @@ -265,36 +261,37 @@ public void testNoGenericServices() throws Exception { assertEquals(1, file.getServices().size()); assertEquals("TestService", file.getServices().get(0).getName()); assertEquals(1, file.getServices().get(0).getMethods().size()); - assertEquals("Foo", - file.getServices().get(0).getMethods().get(0).getName()); + assertEquals("Foo", file.getServices().get(0).getMethods().get(0).getName()); } - // ================================================================= /** - * wrapsCallback() is an EasyMock argument predicate. wrapsCallback(c) - * matches a callback if calling that callback causes c to be called. - * In other words, c wraps the given callback. + * wrapsCallback() is an EasyMock argument predicate. wrapsCallback(c) matches a callback if + * calling that callback causes c to be called. In other words, c wraps the given callback. */ - private RpcCallback wrapsCallback( - MockCallback callback) { + private RpcCallback wrapsCallback(MockCallback callback) { EasyMock.reportMatcher(new WrapsCallback(callback)); return null; } /** The parameter to wrapsCallback() must be a MockCallback. */ - private static class MockCallback - implements RpcCallback { + private static class MockCallback implements RpcCallback { private boolean called = false; - public boolean isCalled() { return called; } + public boolean isCalled() { + return called; + } + + public void reset() { + called = false; + } - public void reset() { called = false; } @Override - public void run(Type message) { - called = true; } + public void run(T message) { + called = true; + } } /** Implementation of the wrapsCallback() argument matcher. */ @@ -311,7 +308,7 @@ public boolean matches(Object actual) { if (!(actual instanceof RpcCallback)) { return false; } - RpcCallback actualCallback = (RpcCallback)actual; + RpcCallback actualCallback = (RpcCallback) actual; callback.reset(); actualCallback.run(null); diff --git a/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java b/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java index e3a8d4f408718..f2ae8f9bca44c 100644 --- a/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java +++ b/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java @@ -32,13 +32,11 @@ import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder; - import junit.framework.TestCase; /** - * Tests for {@link SingleFieldBuilderV3}. This tests basic functionality. - * More extensive testing is provided via other tests that exercise the - * builder. + * Tests for {@link SingleFieldBuilderV3}. This tests basic functionality. More extensive testing is + * provided via other tests that exercise the builder. * * @author jonp@google.com (Jon Perlow) */ @@ -46,16 +44,11 @@ public class SingleFieldBuilderV3Test extends TestCase { public void testBasicUseAndInvalidations() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - SingleFieldBuilderV3 builder = - new SingleFieldBuilderV3( - TestAllTypes.getDefaultInstance(), - mockParent, - false); + SingleFieldBuilderV3 builder = + new SingleFieldBuilderV3( + TestAllTypes.getDefaultInstance(), mockParent, false); assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage()); - assertEquals(TestAllTypes.getDefaultInstance(), - builder.getBuilder().buildPartial()); + assertEquals(TestAllTypes.getDefaultInstance(), builder.getBuilder().buildPartial()); assertEquals(0, mockParent.getInvalidationCount()); builder.getBuilder().setOptionalInt32(10); @@ -71,18 +64,13 @@ public void testBasicUseAndInvalidations() { // Test that we don't keep getting invalidations on every change builder.getBuilder().setOptionalInt32(30); assertEquals(1, mockParent.getInvalidationCount()); - } public void testSetMessage() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - SingleFieldBuilderV3 builder = - new SingleFieldBuilderV3( - TestAllTypes.getDefaultInstance(), - mockParent, - false); + SingleFieldBuilderV3 builder = + new SingleFieldBuilderV3( + TestAllTypes.getDefaultInstance(), mockParent, false); builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); assertEquals(0, builder.getMessage().getOptionalInt32()); @@ -102,13 +90,9 @@ public void testSetMessage() { public void testClear() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - SingleFieldBuilderV3 builder = - new SingleFieldBuilderV3( - TestAllTypes.getDefaultInstance(), - mockParent, - false); + SingleFieldBuilderV3 builder = + new SingleFieldBuilderV3( + TestAllTypes.getDefaultInstance(), mockParent, false); builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage()); builder.clear(); @@ -122,13 +106,9 @@ public void testClear() { public void testMerge() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - SingleFieldBuilderV3 builder = - new SingleFieldBuilderV3( - TestAllTypes.getDefaultInstance(), - mockParent, - false); + SingleFieldBuilderV3 builder = + new SingleFieldBuilderV3( + TestAllTypes.getDefaultInstance(), mockParent, false); // Merge into default field. builder.mergeFrom(TestAllTypes.getDefaultInstance()); @@ -136,20 +116,14 @@ public void testMerge() { // Merge into non-default field on existing builder. builder.getBuilder().setOptionalInt32(2); - builder.mergeFrom(TestAllTypes.newBuilder() - .setOptionalDouble(4.0) - .buildPartial()); + builder.mergeFrom(TestAllTypes.newBuilder().setOptionalDouble(4.0).buildPartial()); assertEquals(2, builder.getMessage().getOptionalInt32()); - assertEquals(4.0, builder.getMessage().getOptionalDouble()); + assertEquals(4.0, builder.getMessage().getOptionalDouble(), 0.0); // Merge into non-default field on existing message - builder.setMessage(TestAllTypes.newBuilder() - .setOptionalInt32(10) - .buildPartial()); - builder.mergeFrom(TestAllTypes.newBuilder() - .setOptionalDouble(5.0) - .buildPartial()); + builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(10).buildPartial()); + builder.mergeFrom(TestAllTypes.newBuilder().setOptionalDouble(5.0).buildPartial()); assertEquals(10, builder.getMessage().getOptionalInt32()); - assertEquals(5.0, builder.getMessage().getOptionalDouble()); + assertEquals(5.0, builder.getMessage().getOptionalDouble(), 0.0); } } diff --git a/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java b/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java index a7f8342d13282..a1a7194b433f9 100644 --- a/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java +++ b/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java @@ -40,9 +40,7 @@ import java.util.TreeSet; import junit.framework.TestCase; -/** - * @author darick@google.com Darick Tong - */ +/** @author darick@google.com Darick Tong */ public class SmallSortedMapTest extends TestCase { // java.util.AbstractMap.SimpleEntry is private in JDK 1.5. We re-implement it // here for JDK 1.5 users. @@ -78,16 +76,16 @@ private static boolean eq(Object o1, Object o2) { @Override public boolean equals(Object o) { - if (!(o instanceof Map.Entry)) + if (!(o instanceof Map.Entry)) { return false; + } Map.Entry e = (Map.Entry) o; return eq(key, e.getKey()) && eq(value, e.getValue()); } @Override public int hashCode() { - return ((key == null) ? 0 : key.hashCode()) ^ - ((value == null) ? 0 : value.hashCode()); + return ((key == null) ? 0 : key.hashCode()) ^ ((value == null) ? 0 : value.hashCode()); } } @@ -101,14 +99,10 @@ public void testPutAndGetOverflowEntries() { private void runPutAndGetTest(int numElements) { // Test with even and odd arraySize - SmallSortedMap map1 = - SmallSortedMap.newInstanceForTest(3); - SmallSortedMap map2 = - SmallSortedMap.newInstanceForTest(4); - SmallSortedMap map3 = - SmallSortedMap.newInstanceForTest(3); - SmallSortedMap map4 = - SmallSortedMap.newInstanceForTest(4); + SmallSortedMap map1 = SmallSortedMap.newInstanceForTest(3); + SmallSortedMap map2 = SmallSortedMap.newInstanceForTest(4); + SmallSortedMap map3 = SmallSortedMap.newInstanceForTest(3); + SmallSortedMap map4 = SmallSortedMap.newInstanceForTest(4); // Test with puts in ascending order. for (int i = 0; i < numElements; i++) { @@ -136,7 +130,7 @@ private void runPutAndGetTest(int numElements) { for (SmallSortedMap map : allMaps) { assertEquals(numElements, map.size()); for (int i = 0; i < numElements; i++) { - assertEquals(new Integer(i + 1), map.get(i)); + assertEquals(Integer.valueOf(i + 1), map.get(i)); } } @@ -152,7 +146,7 @@ public void testReplacingPut() { assertNull(map.remove(i + 1)); } for (int i = 0; i < 6; i++) { - assertEquals(new Integer(i + 1), map.put(i, i + 2)); + assertEquals(Integer.valueOf(i + 1), map.put(i, i + 2)); } } @@ -165,22 +159,22 @@ public void testRemove() { assertEquals(3, map.getNumArrayEntries()); assertEquals(3, map.getNumOverflowEntries()); - assertEquals(6, map.size()); + assertEquals(6, map.size()); assertEquals(makeSortedKeySet(0, 1, 2, 3, 4, 5), map.keySet()); - assertEquals(new Integer(2), map.remove(1)); + assertEquals(Integer.valueOf(2), map.remove(1)); assertEquals(3, map.getNumArrayEntries()); assertEquals(2, map.getNumOverflowEntries()); - assertEquals(5, map.size()); + assertEquals(5, map.size()); assertEquals(makeSortedKeySet(0, 2, 3, 4, 5), map.keySet()); - assertEquals(new Integer(5), map.remove(4)); + assertEquals(Integer.valueOf(5), map.remove(4)); assertEquals(3, map.getNumArrayEntries()); assertEquals(1, map.getNumOverflowEntries()); - assertEquals(4, map.size()); + assertEquals(4, map.size()); assertEquals(makeSortedKeySet(0, 2, 3, 5), map.keySet()); - assertEquals(new Integer(4), map.remove(3)); + assertEquals(Integer.valueOf(4), map.remove(3)); assertEquals(3, map.getNumArrayEntries()); assertEquals(0, map.getNumOverflowEntries()); assertEquals(3, map.size()); @@ -191,7 +185,7 @@ public void testRemove() { assertEquals(0, map.getNumOverflowEntries()); assertEquals(3, map.size()); - assertEquals(new Integer(1), map.remove(0)); + assertEquals(Integer.valueOf(1), map.remove(0)); assertEquals(2, map.getNumArrayEntries()); assertEquals(0, map.getNumOverflowEntries()); assertEquals(2, map.size()); @@ -216,16 +210,15 @@ public void testGetArrayEntryAndOverflowEntries() { assertEquals(3, map.getNumArrayEntries()); for (int i = 0; i < 3; i++) { Map.Entry entry = map.getArrayEntryAt(i); - assertEquals(new Integer(i), entry.getKey()); - assertEquals(new Integer(i + 1), entry.getValue()); + assertEquals(Integer.valueOf(i), entry.getKey()); + assertEquals(Integer.valueOf(i + 1), entry.getValue()); } - Iterator> it = - map.getOverflowEntries().iterator(); + Iterator> it = map.getOverflowEntries().iterator(); for (int i = 3; i < 6; i++) { assertTrue(it.hasNext()); Map.Entry entry = it.next(); - assertEquals(new Integer(i), entry.getKey()); - assertEquals(new Integer(i + 1), entry.getValue()); + assertEquals(Integer.valueOf(i), entry.getKey()); + assertEquals(Integer.valueOf(i + 1), entry.getValue()); } assertFalse(it.hasNext()); } @@ -237,10 +230,8 @@ public void testEntrySetContains() { } Set> entrySet = map.entrySet(); for (int i = 0; i < 6; i++) { - assertTrue( - entrySet.contains(new SimpleEntry(i, i + 1))); - assertFalse( - entrySet.contains(new SimpleEntry(i, i))); + assertTrue(entrySet.contains(new SimpleEntry(i, i + 1))); + assertFalse(entrySet.contains(new SimpleEntry(i, i))); } } @@ -248,13 +239,12 @@ public void testEntrySetAdd() { SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); Set> entrySet = map.entrySet(); for (int i = 0; i < 6; i++) { - Map.Entry entry = - new SimpleEntry(i, i + 1); + Map.Entry entry = new SimpleEntry(i, i + 1); assertTrue(entrySet.add(entry)); assertFalse(entrySet.add(entry)); } for (int i = 0; i < 6; i++) { - assertEquals(new Integer(i + 1), map.get(i)); + assertEquals(Integer.valueOf(i + 1), map.get(i)); } assertEquals(3, map.getNumArrayEntries()); assertEquals(3, map.getNumOverflowEntries()); @@ -268,8 +258,7 @@ public void testEntrySetRemove() { assertNull(map.put(i, i + 1)); } for (int i = 0; i < 6; i++) { - Map.Entry entry = - new SimpleEntry(i, i + 1); + Map.Entry entry = new SimpleEntry(i, i + 1); assertTrue(entrySet.remove(entry)); assertFalse(entrySet.remove(entry)); } @@ -284,7 +273,7 @@ public void testEntrySetClear() { for (int i = 0; i < 6; i++) { assertNull(map.put(i, i + 1)); } - map.entrySet().clear(); + map.clear(); assertTrue(map.isEmpty()); assertEquals(0, map.getNumArrayEntries()); assertEquals(0, map.getNumOverflowEntries()); @@ -300,8 +289,8 @@ public void testEntrySetIteratorNext() { for (int i = 0; i < 6; i++) { assertTrue(it.hasNext()); Map.Entry entry = it.next(); - assertEquals(new Integer(i), entry.getKey()); - assertEquals(new Integer(i + 1), entry.getValue()); + assertEquals(Integer.valueOf(i), entry.getKey()); + assertEquals(Integer.valueOf(i + 1), entry.getValue()); } assertFalse(it.hasNext()); } @@ -332,7 +321,7 @@ public void testMapEntryModification() { entry.setValue(i + 23); } for (int i = 0; i < 6; i++) { - assertEquals(new Integer(i + 23), map.get(i)); + assertEquals(Integer.valueOf(i + 23), map.get(i)); } } @@ -342,7 +331,7 @@ public void testMakeImmutable() { assertNull(map.put(i, i + 1)); } map.makeImmutable(); - assertEquals(new Integer(1), map.get(0)); + assertEquals(Integer.valueOf(1), map.get(0)); assertEquals(6, map.size()); try { diff --git a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java index 4af5542912fb0..3d82c5f9affc3 100644 --- a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java +++ b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java @@ -33,9 +33,9 @@ import junit.framework.TestCase; /** - * Tests that proto2 api generation doesn't cause compile errors when - * compiling protocol buffers that have names that would otherwise conflict - * if not fully qualified (like @Deprecated and @Override). + * Tests that proto2 api generation doesn't cause compile errors when compiling protocol buffers + * that have names that would otherwise conflict if not fully qualified (like @Deprecated + * and @Override). * * @author jonp@google.com (Jon Perlow) */ @@ -48,17 +48,11 @@ public void testCompilation() { } public void testGetDescriptor() { - Descriptors.FileDescriptor fileDescriptor = - TestBadIdentifiersProto.getDescriptor(); - String descriptorField = TestBadIdentifiersProto.Descriptor - .getDefaultInstance().getDescriptor(); - Descriptors.Descriptor protoDescriptor = TestBadIdentifiersProto.Descriptor - .getDefaultInstance().getDescriptorForType(); - String nestedDescriptorField = TestBadIdentifiersProto.Descriptor - .NestedDescriptor.getDefaultInstance().getDescriptor(); - Descriptors.Descriptor nestedProtoDescriptor = TestBadIdentifiersProto - .Descriptor.NestedDescriptor.getDefaultInstance() - .getDescriptorForType(); + TestBadIdentifiersProto.getDescriptor(); + TestBadIdentifiersProto.Descriptor.getDefaultInstance().getDescriptor(); + TestBadIdentifiersProto.Descriptor.getDefaultInstance().getDescriptorForType(); + TestBadIdentifiersProto.Descriptor.NestedDescriptor.getDefaultInstance().getDescriptor(); + TestBadIdentifiersProto.Descriptor.NestedDescriptor.getDefaultInstance().getDescriptorForType(); } public void testConflictingFieldNames() throws Exception { @@ -87,10 +81,16 @@ public void testConflictingFieldNames() throws Exception { assertEquals(0, message.getInt32FieldList31()); assertEquals(0, message.getInt64FieldCount()); - assertEquals(0L, message.getExtension( - TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldCount).longValue()); - assertEquals(0L, message.getExtension( - TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldList).longValue()); + assertEquals( + 0L, + message + .getExtension(TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldCount) + .longValue()); + assertEquals( + 0L, + message + .getExtension(TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldList) + .longValue()); assertEquals("", message.getFieldName32()); assertEquals("", message.getFieldName33()); diff --git a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java index 37f94c03bce58..798d7ca612016 100644 --- a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java +++ b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java @@ -75,9 +75,15 @@ public void testConflictingFieldNames() throws Exception { assertEquals(0, message.getInt32FieldList31()); assertEquals(0, message.getInt64FieldCount()); - assertEquals(0L, message.getExtension( - TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldCount).longValue()); - assertEquals(0L, message.getExtension( - TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldList).longValue()); + assertEquals( + 0L, + message + .getExtension(TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldCount) + .longValue()); + assertEquals( + 0L, + message + .getExtension(TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldList) + .longValue()); } } diff --git a/java/core/src/test/java/com/google/protobuf/TestSchemas.java b/java/core/src/test/java/com/google/protobuf/TestSchemas.java new file mode 100644 index 0000000000000..ab0ced4cdc7b8 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/TestSchemas.java @@ -0,0 +1,94 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.testing.Proto2Testing; +import com.google.protobuf.testing.Proto2Testing.Proto2Empty; +import com.google.protobuf.testing.Proto2Testing.Proto2Message; +import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithExtensions; +import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithMaps; +import com.google.protobuf.testing.Proto3Testing.Proto3Empty; +import com.google.protobuf.testing.Proto3Testing.Proto3Message; +import com.google.protobuf.testing.Proto3Testing.Proto3MessageWithMaps; + +/** Schemas to support testing. */ +public class TestSchemas { + public static final Schema genericProto2Schema = + new ManifestSchemaFactory().createSchema(Proto2Message.class); + public static final Schema genericProto3Schema = + new ManifestSchemaFactory().createSchema(Proto3Message.class); + + public static void registerGenericProto2Schemas() { + registerProto2Schemas(); + } + + public static void registerGenericProto3Schemas() { + registerProto3Schemas(); + } + + private static void registerProto2Schemas() { + Protobuf protobuf = Protobuf.getInstance(); + ManifestSchemaFactory factory = new ManifestSchemaFactory(); + protobuf.registerSchemaOverride(Proto2Message.class, factory.createSchema(Proto2Message.class)); + protobuf.registerSchemaOverride( + Proto2Message.FieldGroup49.class, factory.createSchema(Proto2Message.FieldGroup49.class)); + protobuf.registerSchemaOverride( + Proto2Message.FieldGroupList51.class, + factory.createSchema(Proto2Message.FieldGroupList51.class)); + protobuf.registerSchemaOverride( + Proto2Message.FieldGroup69.class, factory.createSchema(Proto2Message.FieldGroup69.class)); + protobuf.registerSchemaOverride( + Proto2Message.RequiredNestedMessage.class, + factory.createSchema(Proto2Message.RequiredNestedMessage.class)); + protobuf.registerSchemaOverride( + Proto2Message.FieldRequiredGroup88.class, + factory.createSchema(Proto2Message.FieldRequiredGroup88.class)); + protobuf.registerSchemaOverride(Proto2Empty.class, factory.createSchema(Proto2Empty.class)); + protobuf.registerSchemaOverride( + Proto2MessageWithExtensions.class, factory.createSchema(Proto2MessageWithExtensions.class)); + protobuf.registerSchemaOverride( + Proto2Testing.FieldGroup49.class, factory.createSchema(Proto2Testing.FieldGroup49.class)); + protobuf.registerSchemaOverride( + Proto2Testing.FieldGroupList51.class, + factory.createSchema(Proto2Testing.FieldGroupList51.class)); + protobuf.registerSchemaOverride( + Proto2MessageWithMaps.class, factory.createSchema(Proto2MessageWithMaps.class)); + } + + private static void registerProto3Schemas() { + Protobuf protobuf = Protobuf.getInstance(); + ManifestSchemaFactory factory = new ManifestSchemaFactory(); + protobuf.registerSchemaOverride(Proto3Message.class, factory.createSchema(Proto3Message.class)); + protobuf.registerSchemaOverride(Proto3Empty.class, factory.createSchema(Proto3Empty.class)); + protobuf.registerSchemaOverride( + Proto3MessageWithMaps.class, factory.createSchema(Proto3MessageWithMaps.class)); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/TestSchemasLite.java b/java/core/src/test/java/com/google/protobuf/TestSchemasLite.java new file mode 100644 index 0000000000000..28a89d72a14d9 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/TestSchemasLite.java @@ -0,0 +1,103 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.testing.Proto2TestingLite; +import com.google.protobuf.testing.Proto2TestingLite.Proto2EmptyLite; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLiteWithExtensions; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLiteWithMaps; +import com.google.protobuf.testing.Proto3TestingLite.Proto3EmptyLite; +import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLite; +import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLiteWithMaps; + +/** Schemas to support testing. */ +public final class TestSchemasLite { + + public static final Schema genericProto2LiteSchema = + new ManifestSchemaFactory().createSchema(Proto2MessageLite.class); + public static final Schema genericProto3LiteSchema = + new ManifestSchemaFactory().createSchema(Proto3MessageLite.class); + + public static void registerGenericProto2LiteSchemas() { + registerProto2LiteSchemas(); + } + + public static void registerGenericProto3LiteSchemas() { + registerProto3LiteSchemas(); + } + + private static void registerProto2LiteSchemas() { + Protobuf protobuf = Protobuf.getInstance(); + ManifestSchemaFactory factory = new ManifestSchemaFactory(); + protobuf.registerSchemaOverride( + Proto2MessageLite.class, factory.createSchema(Proto2MessageLite.class)); + protobuf.registerSchemaOverride( + Proto2MessageLite.FieldGroup49.class, + factory.createSchema(Proto2MessageLite.FieldGroup49.class)); + protobuf.registerSchemaOverride( + Proto2MessageLite.FieldGroupList51.class, + factory.createSchema(Proto2MessageLite.FieldGroupList51.class)); + protobuf.registerSchemaOverride( + Proto2MessageLite.FieldGroup69.class, + factory.createSchema(Proto2MessageLite.FieldGroup69.class)); + protobuf.registerSchemaOverride( + Proto2MessageLite.RequiredNestedMessage.class, + factory.createSchema(Proto2MessageLite.RequiredNestedMessage.class)); + protobuf.registerSchemaOverride( + Proto2MessageLite.FieldRequiredGroup88.class, + factory.createSchema(Proto2MessageLite.FieldRequiredGroup88.class)); + protobuf.registerSchemaOverride( + Proto2EmptyLite.class, factory.createSchema(Proto2EmptyLite.class)); + protobuf.registerSchemaOverride( + Proto2MessageLiteWithExtensions.class, + factory.createSchema(Proto2MessageLiteWithExtensions.class)); + protobuf.registerSchemaOverride( + Proto2TestingLite.FieldGroup49.class, + factory.createSchema(Proto2TestingLite.FieldGroup49.class)); + protobuf.registerSchemaOverride( + Proto2TestingLite.FieldGroupList51.class, + factory.createSchema(Proto2TestingLite.FieldGroupList51.class)); + protobuf.registerSchemaOverride( + Proto2MessageLiteWithMaps.class, factory.createSchema(Proto2MessageLiteWithMaps.class)); + } + + private static void registerProto3LiteSchemas() { + Protobuf protobuf = Protobuf.getInstance(); + ManifestSchemaFactory factory = new ManifestSchemaFactory(); + protobuf.registerSchemaOverride( + Proto3MessageLite.class, factory.createSchema(Proto3MessageLite.class)); + protobuf.registerSchemaOverride( + Proto3EmptyLite.class, factory.createSchema(Proto3EmptyLite.class)); + protobuf.registerSchemaOverride( + Proto3MessageLiteWithMaps.class, factory.createSchema(Proto3MessageLiteWithMaps.class)); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/TestUtil.java b/java/core/src/test/java/com/google/protobuf/TestUtil.java index e96adf076395b..d3f0b0eda9684 100644 --- a/java/core/src/test/java/com/google/protobuf/TestUtil.java +++ b/java/core/src/test/java/com/google/protobuf/TestUtil.java @@ -119,8 +119,6 @@ import static com.google.protobuf.UnittestLite.repeatedStringPieceExtensionLite; import static com.google.protobuf.UnittestLite.repeatedUint32ExtensionLite; import static com.google.protobuf.UnittestLite.repeatedUint64ExtensionLite; -import static protobuf_unittest.UnittestProto.OptionalGroup_extension; -import static protobuf_unittest.UnittestProto.RepeatedGroup_extension; import static protobuf_unittest.UnittestProto.defaultBoolExtension; import static protobuf_unittest.UnittestProto.defaultBytesExtension; import static protobuf_unittest.UnittestProto.defaultCordExtension; @@ -130,8 +128,6 @@ import static protobuf_unittest.UnittestProto.defaultFloatExtension; import static protobuf_unittest.UnittestProto.defaultForeignEnumExtension; import static protobuf_unittest.UnittestProto.defaultImportEnumExtension; -// The static imports are to avoid 100+ char lines. The following is roughly equivalent to -// import static protobuf_unittest.UnittestProto.*; import static protobuf_unittest.UnittestProto.defaultInt32Extension; import static protobuf_unittest.UnittestProto.defaultInt64Extension; import static protobuf_unittest.UnittestProto.defaultNestedEnumExtension; @@ -224,6 +220,8 @@ import protobuf_unittest.UnittestProto; import protobuf_unittest.UnittestProto.ForeignEnum; import protobuf_unittest.UnittestProto.ForeignMessage; +import protobuf_unittest.UnittestProto.OptionalGroup_extension; +import protobuf_unittest.UnittestProto.RepeatedGroup_extension; import protobuf_unittest.UnittestProto.TestAllExtensions; import protobuf_unittest.UnittestProto.TestAllExtensionsOrBuilder; import protobuf_unittest.UnittestProto.TestAllTypes; @@ -231,42 +229,51 @@ import protobuf_unittest.UnittestProto.TestOneof2; import protobuf_unittest.UnittestProto.TestPackedExtensions; import protobuf_unittest.UnittestProto.TestPackedTypes; +import protobuf_unittest.UnittestProto.TestRequired; import protobuf_unittest.UnittestProto.TestUnpackedTypes; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.logging.Handler; +import java.util.logging.LogRecord; import junit.framework.Assert; /** - * Contains methods for setting all fields of {@code TestAllTypes} to - * some values as well as checking that all the fields are set to those values. - * These are useful for testing various protocol message features, e.g. - * set all fields of a message, serialize it, parse it, and check that all - * fields are set. + * Contains methods for setting all fields of {@code TestAllTypes} to some values as well as + * checking that all the fields are set to those values. These are useful for testing various + * protocol message features, e.g. set all fields of a message, serialize it, parse it, and check + * that all fields are set. * - *

This code is not to be used outside of {@code com.google.protobuf} and - * subpackages. + *

This code is not to be used outside of {@code com.google.protobuf} and subpackages. * * @author kenton@google.com Kenton Varda */ public final class TestUtil { private TestUtil() {} + public static final TestRequired TEST_REQUIRED_UNINITIALIZED = + TestRequired.newBuilder().setA(1).buildPartial(); + public static final TestRequired TEST_REQUIRED_INITIALIZED = + TestRequired.newBuilder().setA(1).setB(2).setC(3).build(); + /** Helper to convert a String to ByteString. */ - static ByteString toBytes(String str) { - return ByteString.copyFrom(str.getBytes(Internal.UTF_8)); + public static ByteString toBytes(String str) { + return ByteString.copyFromUtf8(str); } - /** - * Dirties the message by resetting the momoized serialized size. - */ + // BEGIN FULL-RUNTIME + /** Dirties the message by resetting the momoized serialized size. */ public static void resetMemoizedSize(AbstractMessage message) { message.memoizedSize = -1; } + // END FULL-RUNTIME /** - * Get a {@code TestAllTypes} with all fields set as they would be by - * {@link #setAllFields(TestAllTypes.Builder)}. + * Get a {@code TestAllTypes} with all fields set as they would be by {@link + * #setAllFields(TestAllTypes.Builder)}. */ public static TestAllTypes getAllSet() { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); @@ -275,8 +282,8 @@ public static TestAllTypes getAllSet() { } /** - * Get a {@code TestAllTypes.Builder} with all fields set as they would be by - * {@link #setAllFields(TestAllTypes.Builder)}. + * Get a {@code TestAllTypes.Builder} with all fields set as they would be by {@link + * #setAllFields(TestAllTypes.Builder)}. */ public static TestAllTypes.Builder getAllSetBuilder() { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); @@ -285,8 +292,8 @@ public static TestAllTypes.Builder getAllSetBuilder() { } /** - * Get a {@code TestAllExtensions} with all fields set as they would be by - * {@link #setAllExtensions(TestAllExtensions.Builder)}. + * Get a {@code TestAllExtensions} with all fields set as they would be by {@link + * #setAllExtensions(TestAllExtensions.Builder)}. */ public static TestAllExtensions getAllExtensionsSet() { TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); @@ -312,146 +319,126 @@ public static TestPackedExtensions getPackedExtensionsSet() { return builder.build(); } - /** - * Set every field of {@code message} to the values expected by - * {@code assertAllFieldsSet()}. - */ + /** Set every field of {@code message} to the values expected by {@code assertAllFieldsSet()}. */ public static void setAllFields(TestAllTypes.Builder message) { - message.setOptionalInt32 (101); - message.setOptionalInt64 (102); - message.setOptionalUint32 (103); - message.setOptionalUint64 (104); - message.setOptionalSint32 (105); - message.setOptionalSint64 (106); - message.setOptionalFixed32 (107); - message.setOptionalFixed64 (108); + message.setOptionalInt32(101); + message.setOptionalInt64(102); + message.setOptionalUint32(103); + message.setOptionalUint64(104); + message.setOptionalSint32(105); + message.setOptionalSint64(106); + message.setOptionalFixed32(107); + message.setOptionalFixed64(108); message.setOptionalSfixed32(109); message.setOptionalSfixed64(110); - message.setOptionalFloat (111); - message.setOptionalDouble (112); - message.setOptionalBool (true); - message.setOptionalString ("115"); - message.setOptionalBytes (toBytes("116")); - - message.setOptionalGroup( - TestAllTypes.OptionalGroup.newBuilder().setA(117).build()); - message.setOptionalNestedMessage( - TestAllTypes.NestedMessage.newBuilder().setBb(118).build()); - message.setOptionalForeignMessage( - ForeignMessage.newBuilder().setC(119).build()); - message.setOptionalImportMessage( - ImportMessage.newBuilder().setD(120).build()); - message.setOptionalPublicImportMessage( - PublicImportMessage.newBuilder().setE(126).build()); - message.setOptionalLazyMessage( - TestAllTypes.NestedMessage.newBuilder().setBb(127).build()); - - message.setOptionalNestedEnum (TestAllTypes.NestedEnum.BAZ); + message.setOptionalFloat(111); + message.setOptionalDouble(112); + message.setOptionalBool(true); + message.setOptionalString("115"); + message.setOptionalBytes(toBytes("116")); + + message.setOptionalGroup(TestAllTypes.OptionalGroup.newBuilder().setA(117).build()); + message.setOptionalNestedMessage(TestAllTypes.NestedMessage.newBuilder().setBb(118).build()); + message.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(119).build()); + message.setOptionalImportMessage(ImportMessage.newBuilder().setD(120).build()); + message.setOptionalPublicImportMessage(PublicImportMessage.newBuilder().setE(126).build()); + message.setOptionalLazyMessage(TestAllTypes.NestedMessage.newBuilder().setBb(127).build()); + + message.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAZ); message.setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ); - message.setOptionalImportEnum (ImportEnum.IMPORT_BAZ); + message.setOptionalImportEnum(ImportEnum.IMPORT_BAZ); message.setOptionalStringPiece("124"); message.setOptionalCord("125"); // ----------------------------------------------------------------- - message.addRepeatedInt32 (201); - message.addRepeatedInt64 (202); - message.addRepeatedUint32 (203); - message.addRepeatedUint64 (204); - message.addRepeatedSint32 (205); - message.addRepeatedSint64 (206); - message.addRepeatedFixed32 (207); - message.addRepeatedFixed64 (208); + message.addRepeatedInt32(201); + message.addRepeatedInt64(202); + message.addRepeatedUint32(203); + message.addRepeatedUint64(204); + message.addRepeatedSint32(205); + message.addRepeatedSint64(206); + message.addRepeatedFixed32(207); + message.addRepeatedFixed64(208); message.addRepeatedSfixed32(209); message.addRepeatedSfixed64(210); - message.addRepeatedFloat (211); - message.addRepeatedDouble (212); - message.addRepeatedBool (true); - message.addRepeatedString ("215"); - message.addRepeatedBytes (toBytes("216")); - - message.addRepeatedGroup( - TestAllTypes.RepeatedGroup.newBuilder().setA(217).build()); - message.addRepeatedNestedMessage( - TestAllTypes.NestedMessage.newBuilder().setBb(218).build()); - message.addRepeatedForeignMessage( - ForeignMessage.newBuilder().setC(219).build()); - message.addRepeatedImportMessage( - ImportMessage.newBuilder().setD(220).build()); - message.addRepeatedLazyMessage( - TestAllTypes.NestedMessage.newBuilder().setBb(227).build()); - - message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAR); + message.addRepeatedFloat(211); + message.addRepeatedDouble(212); + message.addRepeatedBool(true); + message.addRepeatedString("215"); + message.addRepeatedBytes(toBytes("216")); + + message.addRepeatedGroup(TestAllTypes.RepeatedGroup.newBuilder().setA(217).build()); + message.addRepeatedNestedMessage(TestAllTypes.NestedMessage.newBuilder().setBb(218).build()); + message.addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(219).build()); + message.addRepeatedImportMessage(ImportMessage.newBuilder().setD(220).build()); + message.addRepeatedLazyMessage(TestAllTypes.NestedMessage.newBuilder().setBb(227).build()); + + message.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAR); message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAR); - message.addRepeatedImportEnum (ImportEnum.IMPORT_BAR); + message.addRepeatedImportEnum(ImportEnum.IMPORT_BAR); message.addRepeatedStringPiece("224"); message.addRepeatedCord("225"); // Add a second one of each field. - message.addRepeatedInt32 (301); - message.addRepeatedInt64 (302); - message.addRepeatedUint32 (303); - message.addRepeatedUint64 (304); - message.addRepeatedSint32 (305); - message.addRepeatedSint64 (306); - message.addRepeatedFixed32 (307); - message.addRepeatedFixed64 (308); + message.addRepeatedInt32(301); + message.addRepeatedInt64(302); + message.addRepeatedUint32(303); + message.addRepeatedUint64(304); + message.addRepeatedSint32(305); + message.addRepeatedSint64(306); + message.addRepeatedFixed32(307); + message.addRepeatedFixed64(308); message.addRepeatedSfixed32(309); message.addRepeatedSfixed64(310); - message.addRepeatedFloat (311); - message.addRepeatedDouble (312); - message.addRepeatedBool (false); - message.addRepeatedString ("315"); - message.addRepeatedBytes (toBytes("316")); - - message.addRepeatedGroup( - TestAllTypes.RepeatedGroup.newBuilder().setA(317).build()); - message.addRepeatedNestedMessage( - TestAllTypes.NestedMessage.newBuilder().setBb(318).build()); - message.addRepeatedForeignMessage( - ForeignMessage.newBuilder().setC(319).build()); - message.addRepeatedImportMessage( - ImportMessage.newBuilder().setD(320).build()); - message.addRepeatedLazyMessage( - TestAllTypes.NestedMessage.newBuilder().setBb(327).build()); - - message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAZ); + message.addRepeatedFloat(311); + message.addRepeatedDouble(312); + message.addRepeatedBool(false); + message.addRepeatedString("315"); + message.addRepeatedBytes(toBytes("316")); + + message.addRepeatedGroup(TestAllTypes.RepeatedGroup.newBuilder().setA(317).build()); + message.addRepeatedNestedMessage(TestAllTypes.NestedMessage.newBuilder().setBb(318).build()); + message.addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(319).build()); + message.addRepeatedImportMessage(ImportMessage.newBuilder().setD(320).build()); + message.addRepeatedLazyMessage(TestAllTypes.NestedMessage.newBuilder().setBb(327).build()); + + message.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ); message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAZ); - message.addRepeatedImportEnum (ImportEnum.IMPORT_BAZ); + message.addRepeatedImportEnum(ImportEnum.IMPORT_BAZ); message.addRepeatedStringPiece("324"); message.addRepeatedCord("325"); // ----------------------------------------------------------------- - message.setDefaultInt32 (401); - message.setDefaultInt64 (402); - message.setDefaultUint32 (403); - message.setDefaultUint64 (404); - message.setDefaultSint32 (405); - message.setDefaultSint64 (406); - message.setDefaultFixed32 (407); - message.setDefaultFixed64 (408); + message.setDefaultInt32(401); + message.setDefaultInt64(402); + message.setDefaultUint32(403); + message.setDefaultUint64(404); + message.setDefaultSint32(405); + message.setDefaultSint64(406); + message.setDefaultFixed32(407); + message.setDefaultFixed64(408); message.setDefaultSfixed32(409); message.setDefaultSfixed64(410); - message.setDefaultFloat (411); - message.setDefaultDouble (412); - message.setDefaultBool (false); - message.setDefaultString ("415"); - message.setDefaultBytes (toBytes("416")); + message.setDefaultFloat(411); + message.setDefaultDouble(412); + message.setDefaultBool(false); + message.setDefaultString("415"); + message.setDefaultBytes(toBytes("416")); - message.setDefaultNestedEnum (TestAllTypes.NestedEnum.FOO); + message.setDefaultNestedEnum(TestAllTypes.NestedEnum.FOO); message.setDefaultForeignEnum(ForeignEnum.FOREIGN_FOO); - message.setDefaultImportEnum (ImportEnum.IMPORT_FOO); + message.setDefaultImportEnum(ImportEnum.IMPORT_FOO); message.setDefaultStringPiece("424"); message.setDefaultCord("425"); message.setOneofUint32(601); - message.setOneofNestedMessage( - TestAllTypes.NestedMessage.newBuilder().setBb(602).build()); + message.setOneofNestedMessage(TestAllTypes.NestedMessage.newBuilder().setBb(602).build()); message.setOneofString("603"); message.setOneofBytes(toBytes("604")); } @@ -459,40 +446,35 @@ public static void setAllFields(TestAllTypes.Builder message) { // ------------------------------------------------------------------- /** - * Modify the repeated fields of {@code message} to contain the values - * expected by {@code assertRepeatedFieldsModified()}. + * Modify the repeated fields of {@code message} to contain the values expected by {@code + * assertRepeatedFieldsModified()}. */ public static void modifyRepeatedFields(TestAllTypes.Builder message) { - message.setRepeatedInt32 (1, 501); - message.setRepeatedInt64 (1, 502); - message.setRepeatedUint32 (1, 503); - message.setRepeatedUint64 (1, 504); - message.setRepeatedSint32 (1, 505); - message.setRepeatedSint64 (1, 506); - message.setRepeatedFixed32 (1, 507); - message.setRepeatedFixed64 (1, 508); + message.setRepeatedInt32(1, 501); + message.setRepeatedInt64(1, 502); + message.setRepeatedUint32(1, 503); + message.setRepeatedUint64(1, 504); + message.setRepeatedSint32(1, 505); + message.setRepeatedSint64(1, 506); + message.setRepeatedFixed32(1, 507); + message.setRepeatedFixed64(1, 508); message.setRepeatedSfixed32(1, 509); message.setRepeatedSfixed64(1, 510); - message.setRepeatedFloat (1, 511); - message.setRepeatedDouble (1, 512); - message.setRepeatedBool (1, true); - message.setRepeatedString (1, "515"); - message.setRepeatedBytes (1, toBytes("516")); - - message.setRepeatedGroup(1, - TestAllTypes.RepeatedGroup.newBuilder().setA(517).build()); - message.setRepeatedNestedMessage(1, - TestAllTypes.NestedMessage.newBuilder().setBb(518).build()); - message.setRepeatedForeignMessage(1, - ForeignMessage.newBuilder().setC(519).build()); - message.setRepeatedImportMessage(1, - ImportMessage.newBuilder().setD(520).build()); - message.setRepeatedLazyMessage(1, - TestAllTypes.NestedMessage.newBuilder().setBb(527).build()); - - message.setRepeatedNestedEnum (1, TestAllTypes.NestedEnum.FOO); + message.setRepeatedFloat(1, 511); + message.setRepeatedDouble(1, 512); + message.setRepeatedBool(1, true); + message.setRepeatedString(1, "515"); + message.setRepeatedBytes(1, toBytes("516")); + + message.setRepeatedGroup(1, TestAllTypes.RepeatedGroup.newBuilder().setA(517).build()); + message.setRepeatedNestedMessage(1, TestAllTypes.NestedMessage.newBuilder().setBb(518).build()); + message.setRepeatedForeignMessage(1, ForeignMessage.newBuilder().setC(519).build()); + message.setRepeatedImportMessage(1, ImportMessage.newBuilder().setD(520).build()); + message.setRepeatedLazyMessage(1, TestAllTypes.NestedMessage.newBuilder().setBb(527).build()); + + message.setRepeatedNestedEnum(1, TestAllTypes.NestedEnum.FOO); message.setRepeatedForeignEnum(1, ForeignEnum.FOREIGN_FOO); - message.setRepeatedImportEnum (1, ImportEnum.IMPORT_FOO); + message.setRepeatedImportEnum(1, ImportEnum.IMPORT_FOO); message.setRepeatedStringPiece(1, "524"); message.setRepeatedCord(1, "525"); @@ -501,65 +483,65 @@ public static void modifyRepeatedFields(TestAllTypes.Builder message) { // ------------------------------------------------------------------- /** - * Assert (using {@code junit.framework.Assert}} that all fields of - * {@code message} are set to the values assigned by {@code setAllFields}. + * Assert (using {@code junit.framework.Assert}} that all fields of {@code message} are set to the + * values assigned by {@code setAllFields}. */ public static void assertAllFieldsSet(TestAllTypesOrBuilder message) { - Assert.assertTrue(message.hasOptionalInt32 ()); - Assert.assertTrue(message.hasOptionalInt64 ()); - Assert.assertTrue(message.hasOptionalUint32 ()); - Assert.assertTrue(message.hasOptionalUint64 ()); - Assert.assertTrue(message.hasOptionalSint32 ()); - Assert.assertTrue(message.hasOptionalSint64 ()); - Assert.assertTrue(message.hasOptionalFixed32 ()); - Assert.assertTrue(message.hasOptionalFixed64 ()); + Assert.assertTrue(message.hasOptionalInt32()); + Assert.assertTrue(message.hasOptionalInt64()); + Assert.assertTrue(message.hasOptionalUint32()); + Assert.assertTrue(message.hasOptionalUint64()); + Assert.assertTrue(message.hasOptionalSint32()); + Assert.assertTrue(message.hasOptionalSint64()); + Assert.assertTrue(message.hasOptionalFixed32()); + Assert.assertTrue(message.hasOptionalFixed64()); Assert.assertTrue(message.hasOptionalSfixed32()); Assert.assertTrue(message.hasOptionalSfixed64()); - Assert.assertTrue(message.hasOptionalFloat ()); - Assert.assertTrue(message.hasOptionalDouble ()); - Assert.assertTrue(message.hasOptionalBool ()); - Assert.assertTrue(message.hasOptionalString ()); - Assert.assertTrue(message.hasOptionalBytes ()); - - Assert.assertTrue(message.hasOptionalGroup ()); - Assert.assertTrue(message.hasOptionalNestedMessage ()); + Assert.assertTrue(message.hasOptionalFloat()); + Assert.assertTrue(message.hasOptionalDouble()); + Assert.assertTrue(message.hasOptionalBool()); + Assert.assertTrue(message.hasOptionalString()); + Assert.assertTrue(message.hasOptionalBytes()); + + Assert.assertTrue(message.hasOptionalGroup()); + Assert.assertTrue(message.hasOptionalNestedMessage()); Assert.assertTrue(message.hasOptionalForeignMessage()); - Assert.assertTrue(message.hasOptionalImportMessage ()); + Assert.assertTrue(message.hasOptionalImportMessage()); - Assert.assertTrue(message.getOptionalGroup ().hasA()); - Assert.assertTrue(message.getOptionalNestedMessage ().hasBb()); + Assert.assertTrue(message.getOptionalGroup().hasA()); + Assert.assertTrue(message.getOptionalNestedMessage().hasBb()); Assert.assertTrue(message.getOptionalForeignMessage().hasC()); - Assert.assertTrue(message.getOptionalImportMessage ().hasD()); + Assert.assertTrue(message.getOptionalImportMessage().hasD()); - Assert.assertTrue(message.hasOptionalNestedEnum ()); + Assert.assertTrue(message.hasOptionalNestedEnum()); Assert.assertTrue(message.hasOptionalForeignEnum()); - Assert.assertTrue(message.hasOptionalImportEnum ()); + Assert.assertTrue(message.hasOptionalImportEnum()); Assert.assertTrue(message.hasOptionalStringPiece()); Assert.assertTrue(message.hasOptionalCord()); - Assert.assertEquals(101 , message.getOptionalInt32 ()); - Assert.assertEquals(102 , message.getOptionalInt64 ()); - Assert.assertEquals(103 , message.getOptionalUint32 ()); - Assert.assertEquals(104 , message.getOptionalUint64 ()); - Assert.assertEquals(105 , message.getOptionalSint32 ()); - Assert.assertEquals(106 , message.getOptionalSint64 ()); - Assert.assertEquals(107 , message.getOptionalFixed32 ()); - Assert.assertEquals(108 , message.getOptionalFixed64 ()); - Assert.assertEquals(109 , message.getOptionalSfixed32()); - Assert.assertEquals(110 , message.getOptionalSfixed64()); - Assert.assertEquals(111 , message.getOptionalFloat (), 0.0); - Assert.assertEquals(112 , message.getOptionalDouble (), 0.0); - Assert.assertEquals(true , message.getOptionalBool ()); - Assert.assertEquals("115", message.getOptionalString ()); + Assert.assertEquals(101, message.getOptionalInt32()); + Assert.assertEquals(102, message.getOptionalInt64()); + Assert.assertEquals(103, message.getOptionalUint32()); + Assert.assertEquals(104, message.getOptionalUint64()); + Assert.assertEquals(105, message.getOptionalSint32()); + Assert.assertEquals(106, message.getOptionalSint64()); + Assert.assertEquals(107, message.getOptionalFixed32()); + Assert.assertEquals(108, message.getOptionalFixed64()); + Assert.assertEquals(109, message.getOptionalSfixed32()); + Assert.assertEquals(110, message.getOptionalSfixed64()); + Assert.assertEquals(111, message.getOptionalFloat(), 0.0); + Assert.assertEquals(112, message.getOptionalDouble(), 0.0); + Assert.assertEquals(true, message.getOptionalBool()); + Assert.assertEquals("115", message.getOptionalString()); Assert.assertEquals(toBytes("116"), message.getOptionalBytes()); - Assert.assertEquals(117, message.getOptionalGroup ().getA()); - Assert.assertEquals(118, message.getOptionalNestedMessage ().getBb()); - Assert.assertEquals(119, message.getOptionalForeignMessage ().getC()); - Assert.assertEquals(120, message.getOptionalImportMessage ().getD()); + Assert.assertEquals(117, message.getOptionalGroup().getA()); + Assert.assertEquals(118, message.getOptionalNestedMessage().getBb()); + Assert.assertEquals(119, message.getOptionalForeignMessage().getC()); + Assert.assertEquals(120, message.getOptionalImportMessage().getD()); Assert.assertEquals(126, message.getOptionalPublicImportMessage().getE()); - Assert.assertEquals(127, message.getOptionalLazyMessage ().getBb()); + Assert.assertEquals(127, message.getOptionalLazyMessage().getBb()); Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getOptionalNestedEnum()); Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getOptionalForeignEnum()); @@ -570,86 +552,86 @@ public static void assertAllFieldsSet(TestAllTypesOrBuilder message) { // ----------------------------------------------------------------- - Assert.assertEquals(2, message.getRepeatedInt32Count ()); - Assert.assertEquals(2, message.getRepeatedInt64Count ()); - Assert.assertEquals(2, message.getRepeatedUint32Count ()); - Assert.assertEquals(2, message.getRepeatedUint64Count ()); - Assert.assertEquals(2, message.getRepeatedSint32Count ()); - Assert.assertEquals(2, message.getRepeatedSint64Count ()); - Assert.assertEquals(2, message.getRepeatedFixed32Count ()); - Assert.assertEquals(2, message.getRepeatedFixed64Count ()); + Assert.assertEquals(2, message.getRepeatedInt32Count()); + Assert.assertEquals(2, message.getRepeatedInt64Count()); + Assert.assertEquals(2, message.getRepeatedUint32Count()); + Assert.assertEquals(2, message.getRepeatedUint64Count()); + Assert.assertEquals(2, message.getRepeatedSint32Count()); + Assert.assertEquals(2, message.getRepeatedSint64Count()); + Assert.assertEquals(2, message.getRepeatedFixed32Count()); + Assert.assertEquals(2, message.getRepeatedFixed64Count()); Assert.assertEquals(2, message.getRepeatedSfixed32Count()); Assert.assertEquals(2, message.getRepeatedSfixed64Count()); - Assert.assertEquals(2, message.getRepeatedFloatCount ()); - Assert.assertEquals(2, message.getRepeatedDoubleCount ()); - Assert.assertEquals(2, message.getRepeatedBoolCount ()); - Assert.assertEquals(2, message.getRepeatedStringCount ()); - Assert.assertEquals(2, message.getRepeatedBytesCount ()); - - Assert.assertEquals(2, message.getRepeatedGroupCount ()); - Assert.assertEquals(2, message.getRepeatedNestedMessageCount ()); + Assert.assertEquals(2, message.getRepeatedFloatCount()); + Assert.assertEquals(2, message.getRepeatedDoubleCount()); + Assert.assertEquals(2, message.getRepeatedBoolCount()); + Assert.assertEquals(2, message.getRepeatedStringCount()); + Assert.assertEquals(2, message.getRepeatedBytesCount()); + + Assert.assertEquals(2, message.getRepeatedGroupCount()); + Assert.assertEquals(2, message.getRepeatedNestedMessageCount()); Assert.assertEquals(2, message.getRepeatedForeignMessageCount()); - Assert.assertEquals(2, message.getRepeatedImportMessageCount ()); - Assert.assertEquals(2, message.getRepeatedLazyMessageCount ()); - Assert.assertEquals(2, message.getRepeatedNestedEnumCount ()); - Assert.assertEquals(2, message.getRepeatedForeignEnumCount ()); - Assert.assertEquals(2, message.getRepeatedImportEnumCount ()); + Assert.assertEquals(2, message.getRepeatedImportMessageCount()); + Assert.assertEquals(2, message.getRepeatedLazyMessageCount()); + Assert.assertEquals(2, message.getRepeatedNestedEnumCount()); + Assert.assertEquals(2, message.getRepeatedForeignEnumCount()); + Assert.assertEquals(2, message.getRepeatedImportEnumCount()); Assert.assertEquals(2, message.getRepeatedStringPieceCount()); Assert.assertEquals(2, message.getRepeatedCordCount()); - Assert.assertEquals(201 , message.getRepeatedInt32 (0)); - Assert.assertEquals(202 , message.getRepeatedInt64 (0)); - Assert.assertEquals(203 , message.getRepeatedUint32 (0)); - Assert.assertEquals(204 , message.getRepeatedUint64 (0)); - Assert.assertEquals(205 , message.getRepeatedSint32 (0)); - Assert.assertEquals(206 , message.getRepeatedSint64 (0)); - Assert.assertEquals(207 , message.getRepeatedFixed32 (0)); - Assert.assertEquals(208 , message.getRepeatedFixed64 (0)); - Assert.assertEquals(209 , message.getRepeatedSfixed32(0)); - Assert.assertEquals(210 , message.getRepeatedSfixed64(0)); - Assert.assertEquals(211 , message.getRepeatedFloat (0), 0.0); - Assert.assertEquals(212 , message.getRepeatedDouble (0), 0.0); - Assert.assertEquals(true , message.getRepeatedBool (0)); - Assert.assertEquals("215", message.getRepeatedString (0)); + Assert.assertEquals(201, message.getRepeatedInt32(0)); + Assert.assertEquals(202, message.getRepeatedInt64(0)); + Assert.assertEquals(203, message.getRepeatedUint32(0)); + Assert.assertEquals(204, message.getRepeatedUint64(0)); + Assert.assertEquals(205, message.getRepeatedSint32(0)); + Assert.assertEquals(206, message.getRepeatedSint64(0)); + Assert.assertEquals(207, message.getRepeatedFixed32(0)); + Assert.assertEquals(208, message.getRepeatedFixed64(0)); + Assert.assertEquals(209, message.getRepeatedSfixed32(0)); + Assert.assertEquals(210, message.getRepeatedSfixed64(0)); + Assert.assertEquals(211, message.getRepeatedFloat(0), 0.0); + Assert.assertEquals(212, message.getRepeatedDouble(0), 0.0); + Assert.assertEquals(true, message.getRepeatedBool(0)); + Assert.assertEquals("215", message.getRepeatedString(0)); Assert.assertEquals(toBytes("216"), message.getRepeatedBytes(0)); - Assert.assertEquals(217, message.getRepeatedGroup (0).getA()); - Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb()); + Assert.assertEquals(217, message.getRepeatedGroup(0).getA()); + Assert.assertEquals(218, message.getRepeatedNestedMessage(0).getBb()); Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC()); - Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD()); - Assert.assertEquals(227, message.getRepeatedLazyMessage (0).getBb()); + Assert.assertEquals(220, message.getRepeatedImportMessage(0).getD()); + Assert.assertEquals(227, message.getRepeatedLazyMessage(0).getBb()); - Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0)); + Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum(0)); Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0)); Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getRepeatedImportEnum(0)); Assert.assertEquals("224", message.getRepeatedStringPiece(0)); Assert.assertEquals("225", message.getRepeatedCord(0)); - Assert.assertEquals(301 , message.getRepeatedInt32 (1)); - Assert.assertEquals(302 , message.getRepeatedInt64 (1)); - Assert.assertEquals(303 , message.getRepeatedUint32 (1)); - Assert.assertEquals(304 , message.getRepeatedUint64 (1)); - Assert.assertEquals(305 , message.getRepeatedSint32 (1)); - Assert.assertEquals(306 , message.getRepeatedSint64 (1)); - Assert.assertEquals(307 , message.getRepeatedFixed32 (1)); - Assert.assertEquals(308 , message.getRepeatedFixed64 (1)); - Assert.assertEquals(309 , message.getRepeatedSfixed32(1)); - Assert.assertEquals(310 , message.getRepeatedSfixed64(1)); - Assert.assertEquals(311 , message.getRepeatedFloat (1), 0.0); - Assert.assertEquals(312 , message.getRepeatedDouble (1), 0.0); - Assert.assertEquals(false, message.getRepeatedBool (1)); - Assert.assertEquals("315", message.getRepeatedString (1)); + Assert.assertEquals(301, message.getRepeatedInt32(1)); + Assert.assertEquals(302, message.getRepeatedInt64(1)); + Assert.assertEquals(303, message.getRepeatedUint32(1)); + Assert.assertEquals(304, message.getRepeatedUint64(1)); + Assert.assertEquals(305, message.getRepeatedSint32(1)); + Assert.assertEquals(306, message.getRepeatedSint64(1)); + Assert.assertEquals(307, message.getRepeatedFixed32(1)); + Assert.assertEquals(308, message.getRepeatedFixed64(1)); + Assert.assertEquals(309, message.getRepeatedSfixed32(1)); + Assert.assertEquals(310, message.getRepeatedSfixed64(1)); + Assert.assertEquals(311, message.getRepeatedFloat(1), 0.0); + Assert.assertEquals(312, message.getRepeatedDouble(1), 0.0); + Assert.assertEquals(false, message.getRepeatedBool(1)); + Assert.assertEquals("315", message.getRepeatedString(1)); Assert.assertEquals(toBytes("316"), message.getRepeatedBytes(1)); - Assert.assertEquals(317, message.getRepeatedGroup (1).getA()); - Assert.assertEquals(318, message.getRepeatedNestedMessage (1).getBb()); + Assert.assertEquals(317, message.getRepeatedGroup(1).getA()); + Assert.assertEquals(318, message.getRepeatedNestedMessage(1).getBb()); Assert.assertEquals(319, message.getRepeatedForeignMessage(1).getC()); - Assert.assertEquals(320, message.getRepeatedImportMessage (1).getD()); - Assert.assertEquals(327, message.getRepeatedLazyMessage (1).getBb()); + Assert.assertEquals(320, message.getRepeatedImportMessage(1).getD()); + Assert.assertEquals(327, message.getRepeatedLazyMessage(1).getBb()); - Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getRepeatedNestedEnum (1)); + Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getRepeatedNestedEnum(1)); Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getRepeatedForeignEnum(1)); Assert.assertEquals(ImportEnum.IMPORT_BAZ, message.getRepeatedImportEnum(1)); @@ -658,46 +640,46 @@ public static void assertAllFieldsSet(TestAllTypesOrBuilder message) { // ----------------------------------------------------------------- - Assert.assertTrue(message.hasDefaultInt32 ()); - Assert.assertTrue(message.hasDefaultInt64 ()); - Assert.assertTrue(message.hasDefaultUint32 ()); - Assert.assertTrue(message.hasDefaultUint64 ()); - Assert.assertTrue(message.hasDefaultSint32 ()); - Assert.assertTrue(message.hasDefaultSint64 ()); - Assert.assertTrue(message.hasDefaultFixed32 ()); - Assert.assertTrue(message.hasDefaultFixed64 ()); + Assert.assertTrue(message.hasDefaultInt32()); + Assert.assertTrue(message.hasDefaultInt64()); + Assert.assertTrue(message.hasDefaultUint32()); + Assert.assertTrue(message.hasDefaultUint64()); + Assert.assertTrue(message.hasDefaultSint32()); + Assert.assertTrue(message.hasDefaultSint64()); + Assert.assertTrue(message.hasDefaultFixed32()); + Assert.assertTrue(message.hasDefaultFixed64()); Assert.assertTrue(message.hasDefaultSfixed32()); Assert.assertTrue(message.hasDefaultSfixed64()); - Assert.assertTrue(message.hasDefaultFloat ()); - Assert.assertTrue(message.hasDefaultDouble ()); - Assert.assertTrue(message.hasDefaultBool ()); - Assert.assertTrue(message.hasDefaultString ()); - Assert.assertTrue(message.hasDefaultBytes ()); + Assert.assertTrue(message.hasDefaultFloat()); + Assert.assertTrue(message.hasDefaultDouble()); + Assert.assertTrue(message.hasDefaultBool()); + Assert.assertTrue(message.hasDefaultString()); + Assert.assertTrue(message.hasDefaultBytes()); - Assert.assertTrue(message.hasDefaultNestedEnum ()); + Assert.assertTrue(message.hasDefaultNestedEnum()); Assert.assertTrue(message.hasDefaultForeignEnum()); - Assert.assertTrue(message.hasDefaultImportEnum ()); + Assert.assertTrue(message.hasDefaultImportEnum()); Assert.assertTrue(message.hasDefaultStringPiece()); Assert.assertTrue(message.hasDefaultCord()); - Assert.assertEquals(401 , message.getDefaultInt32 ()); - Assert.assertEquals(402 , message.getDefaultInt64 ()); - Assert.assertEquals(403 , message.getDefaultUint32 ()); - Assert.assertEquals(404 , message.getDefaultUint64 ()); - Assert.assertEquals(405 , message.getDefaultSint32 ()); - Assert.assertEquals(406 , message.getDefaultSint64 ()); - Assert.assertEquals(407 , message.getDefaultFixed32 ()); - Assert.assertEquals(408 , message.getDefaultFixed64 ()); - Assert.assertEquals(409 , message.getDefaultSfixed32()); - Assert.assertEquals(410 , message.getDefaultSfixed64()); - Assert.assertEquals(411 , message.getDefaultFloat (), 0.0); - Assert.assertEquals(412 , message.getDefaultDouble (), 0.0); - Assert.assertEquals(false, message.getDefaultBool ()); - Assert.assertEquals("415", message.getDefaultString ()); + Assert.assertEquals(401, message.getDefaultInt32()); + Assert.assertEquals(402, message.getDefaultInt64()); + Assert.assertEquals(403, message.getDefaultUint32()); + Assert.assertEquals(404, message.getDefaultUint64()); + Assert.assertEquals(405, message.getDefaultSint32()); + Assert.assertEquals(406, message.getDefaultSint64()); + Assert.assertEquals(407, message.getDefaultFixed32()); + Assert.assertEquals(408, message.getDefaultFixed64()); + Assert.assertEquals(409, message.getDefaultSfixed32()); + Assert.assertEquals(410, message.getDefaultSfixed64()); + Assert.assertEquals(411, message.getDefaultFloat(), 0.0); + Assert.assertEquals(412, message.getDefaultDouble(), 0.0); + Assert.assertEquals(false, message.getDefaultBool()); + Assert.assertEquals("415", message.getDefaultString()); Assert.assertEquals(toBytes("416"), message.getDefaultBytes()); - Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getDefaultNestedEnum ()); + Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getDefaultNestedEnum()); Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getDefaultForeignEnum()); Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getDefaultImportEnum()); @@ -715,74 +697,73 @@ public static void assertAllFieldsSet(TestAllTypesOrBuilder message) { // ------------------------------------------------------------------- /** - * Assert (using {@code junit.framework.Assert}} that all fields of - * {@code message} are cleared, and that getting the fields returns their - * default values. + * Assert (using {@code junit.framework.Assert}} that all fields of {@code message} are cleared, + * and that getting the fields returns their default values. */ public static void assertClear(TestAllTypesOrBuilder message) { // hasBlah() should initially be false for all optional fields. - Assert.assertFalse(message.hasOptionalInt32 ()); - Assert.assertFalse(message.hasOptionalInt64 ()); - Assert.assertFalse(message.hasOptionalUint32 ()); - Assert.assertFalse(message.hasOptionalUint64 ()); - Assert.assertFalse(message.hasOptionalSint32 ()); - Assert.assertFalse(message.hasOptionalSint64 ()); - Assert.assertFalse(message.hasOptionalFixed32 ()); - Assert.assertFalse(message.hasOptionalFixed64 ()); + Assert.assertFalse(message.hasOptionalInt32()); + Assert.assertFalse(message.hasOptionalInt64()); + Assert.assertFalse(message.hasOptionalUint32()); + Assert.assertFalse(message.hasOptionalUint64()); + Assert.assertFalse(message.hasOptionalSint32()); + Assert.assertFalse(message.hasOptionalSint64()); + Assert.assertFalse(message.hasOptionalFixed32()); + Assert.assertFalse(message.hasOptionalFixed64()); Assert.assertFalse(message.hasOptionalSfixed32()); Assert.assertFalse(message.hasOptionalSfixed64()); - Assert.assertFalse(message.hasOptionalFloat ()); - Assert.assertFalse(message.hasOptionalDouble ()); - Assert.assertFalse(message.hasOptionalBool ()); - Assert.assertFalse(message.hasOptionalString ()); - Assert.assertFalse(message.hasOptionalBytes ()); - - Assert.assertFalse(message.hasOptionalGroup ()); - Assert.assertFalse(message.hasOptionalNestedMessage ()); + Assert.assertFalse(message.hasOptionalFloat()); + Assert.assertFalse(message.hasOptionalDouble()); + Assert.assertFalse(message.hasOptionalBool()); + Assert.assertFalse(message.hasOptionalString()); + Assert.assertFalse(message.hasOptionalBytes()); + + Assert.assertFalse(message.hasOptionalGroup()); + Assert.assertFalse(message.hasOptionalNestedMessage()); Assert.assertFalse(message.hasOptionalForeignMessage()); - Assert.assertFalse(message.hasOptionalImportMessage ()); + Assert.assertFalse(message.hasOptionalImportMessage()); - Assert.assertFalse(message.hasOptionalNestedEnum ()); + Assert.assertFalse(message.hasOptionalNestedEnum()); Assert.assertFalse(message.hasOptionalForeignEnum()); - Assert.assertFalse(message.hasOptionalImportEnum ()); + Assert.assertFalse(message.hasOptionalImportEnum()); Assert.assertFalse(message.hasOptionalStringPiece()); Assert.assertFalse(message.hasOptionalCord()); // Optional fields without defaults are set to zero or something like it. - Assert.assertEquals(0 , message.getOptionalInt32 ()); - Assert.assertEquals(0 , message.getOptionalInt64 ()); - Assert.assertEquals(0 , message.getOptionalUint32 ()); - Assert.assertEquals(0 , message.getOptionalUint64 ()); - Assert.assertEquals(0 , message.getOptionalSint32 ()); - Assert.assertEquals(0 , message.getOptionalSint64 ()); - Assert.assertEquals(0 , message.getOptionalFixed32 ()); - Assert.assertEquals(0 , message.getOptionalFixed64 ()); - Assert.assertEquals(0 , message.getOptionalSfixed32()); - Assert.assertEquals(0 , message.getOptionalSfixed64()); - Assert.assertEquals(0 , message.getOptionalFloat (), 0.0); - Assert.assertEquals(0 , message.getOptionalDouble (), 0.0); - Assert.assertEquals(false, message.getOptionalBool ()); - Assert.assertEquals("" , message.getOptionalString ()); + Assert.assertEquals(0, message.getOptionalInt32()); + Assert.assertEquals(0, message.getOptionalInt64()); + Assert.assertEquals(0, message.getOptionalUint32()); + Assert.assertEquals(0, message.getOptionalUint64()); + Assert.assertEquals(0, message.getOptionalSint32()); + Assert.assertEquals(0, message.getOptionalSint64()); + Assert.assertEquals(0, message.getOptionalFixed32()); + Assert.assertEquals(0, message.getOptionalFixed64()); + Assert.assertEquals(0, message.getOptionalSfixed32()); + Assert.assertEquals(0, message.getOptionalSfixed64()); + Assert.assertEquals(0, message.getOptionalFloat(), 0.0); + Assert.assertEquals(0, message.getOptionalDouble(), 0.0); + Assert.assertEquals(false, message.getOptionalBool()); + Assert.assertEquals("", message.getOptionalString()); Assert.assertEquals(ByteString.EMPTY, message.getOptionalBytes()); // Embedded messages should also be clear. - Assert.assertFalse(message.getOptionalGroup ().hasA()); - Assert.assertFalse(message.getOptionalNestedMessage ().hasBb()); - Assert.assertFalse(message.getOptionalForeignMessage ().hasC()); - Assert.assertFalse(message.getOptionalImportMessage ().hasD()); + Assert.assertFalse(message.getOptionalGroup().hasA()); + Assert.assertFalse(message.getOptionalNestedMessage().hasBb()); + Assert.assertFalse(message.getOptionalForeignMessage().hasC()); + Assert.assertFalse(message.getOptionalImportMessage().hasD()); Assert.assertFalse(message.getOptionalPublicImportMessage().hasE()); - Assert.assertFalse(message.getOptionalLazyMessage ().hasBb()); + Assert.assertFalse(message.getOptionalLazyMessage().hasBb()); - Assert.assertEquals(0, message.getOptionalGroup ().getA()); - Assert.assertEquals(0, message.getOptionalNestedMessage ().getBb()); - Assert.assertEquals(0, message.getOptionalForeignMessage ().getC()); - Assert.assertEquals(0, message.getOptionalImportMessage ().getD()); + Assert.assertEquals(0, message.getOptionalGroup().getA()); + Assert.assertEquals(0, message.getOptionalNestedMessage().getBb()); + Assert.assertEquals(0, message.getOptionalForeignMessage().getC()); + Assert.assertEquals(0, message.getOptionalImportMessage().getD()); Assert.assertEquals(0, message.getOptionalPublicImportMessage().getE()); - Assert.assertEquals(0, message.getOptionalLazyMessage ().getBb()); + Assert.assertEquals(0, message.getOptionalLazyMessage().getBb()); // Enums without defaults are set to the first value in the enum. - Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum ()); + Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum()); Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getOptionalForeignEnum()); Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getOptionalImportEnum()); @@ -790,76 +771,76 @@ public static void assertClear(TestAllTypesOrBuilder message) { Assert.assertEquals("", message.getOptionalCord()); // Repeated fields are empty. - Assert.assertEquals(0, message.getRepeatedInt32Count ()); - Assert.assertEquals(0, message.getRepeatedInt64Count ()); - Assert.assertEquals(0, message.getRepeatedUint32Count ()); - Assert.assertEquals(0, message.getRepeatedUint64Count ()); - Assert.assertEquals(0, message.getRepeatedSint32Count ()); - Assert.assertEquals(0, message.getRepeatedSint64Count ()); - Assert.assertEquals(0, message.getRepeatedFixed32Count ()); - Assert.assertEquals(0, message.getRepeatedFixed64Count ()); + Assert.assertEquals(0, message.getRepeatedInt32Count()); + Assert.assertEquals(0, message.getRepeatedInt64Count()); + Assert.assertEquals(0, message.getRepeatedUint32Count()); + Assert.assertEquals(0, message.getRepeatedUint64Count()); + Assert.assertEquals(0, message.getRepeatedSint32Count()); + Assert.assertEquals(0, message.getRepeatedSint64Count()); + Assert.assertEquals(0, message.getRepeatedFixed32Count()); + Assert.assertEquals(0, message.getRepeatedFixed64Count()); Assert.assertEquals(0, message.getRepeatedSfixed32Count()); Assert.assertEquals(0, message.getRepeatedSfixed64Count()); - Assert.assertEquals(0, message.getRepeatedFloatCount ()); - Assert.assertEquals(0, message.getRepeatedDoubleCount ()); - Assert.assertEquals(0, message.getRepeatedBoolCount ()); - Assert.assertEquals(0, message.getRepeatedStringCount ()); - Assert.assertEquals(0, message.getRepeatedBytesCount ()); - - Assert.assertEquals(0, message.getRepeatedGroupCount ()); - Assert.assertEquals(0, message.getRepeatedNestedMessageCount ()); + Assert.assertEquals(0, message.getRepeatedFloatCount()); + Assert.assertEquals(0, message.getRepeatedDoubleCount()); + Assert.assertEquals(0, message.getRepeatedBoolCount()); + Assert.assertEquals(0, message.getRepeatedStringCount()); + Assert.assertEquals(0, message.getRepeatedBytesCount()); + + Assert.assertEquals(0, message.getRepeatedGroupCount()); + Assert.assertEquals(0, message.getRepeatedNestedMessageCount()); Assert.assertEquals(0, message.getRepeatedForeignMessageCount()); - Assert.assertEquals(0, message.getRepeatedImportMessageCount ()); - Assert.assertEquals(0, message.getRepeatedLazyMessageCount ()); - Assert.assertEquals(0, message.getRepeatedNestedEnumCount ()); - Assert.assertEquals(0, message.getRepeatedForeignEnumCount ()); - Assert.assertEquals(0, message.getRepeatedImportEnumCount ()); + Assert.assertEquals(0, message.getRepeatedImportMessageCount()); + Assert.assertEquals(0, message.getRepeatedLazyMessageCount()); + Assert.assertEquals(0, message.getRepeatedNestedEnumCount()); + Assert.assertEquals(0, message.getRepeatedForeignEnumCount()); + Assert.assertEquals(0, message.getRepeatedImportEnumCount()); Assert.assertEquals(0, message.getRepeatedStringPieceCount()); Assert.assertEquals(0, message.getRepeatedCordCount()); // hasBlah() should also be false for all default fields. - Assert.assertFalse(message.hasDefaultInt32 ()); - Assert.assertFalse(message.hasDefaultInt64 ()); - Assert.assertFalse(message.hasDefaultUint32 ()); - Assert.assertFalse(message.hasDefaultUint64 ()); - Assert.assertFalse(message.hasDefaultSint32 ()); - Assert.assertFalse(message.hasDefaultSint64 ()); - Assert.assertFalse(message.hasDefaultFixed32 ()); - Assert.assertFalse(message.hasDefaultFixed64 ()); + Assert.assertFalse(message.hasDefaultInt32()); + Assert.assertFalse(message.hasDefaultInt64()); + Assert.assertFalse(message.hasDefaultUint32()); + Assert.assertFalse(message.hasDefaultUint64()); + Assert.assertFalse(message.hasDefaultSint32()); + Assert.assertFalse(message.hasDefaultSint64()); + Assert.assertFalse(message.hasDefaultFixed32()); + Assert.assertFalse(message.hasDefaultFixed64()); Assert.assertFalse(message.hasDefaultSfixed32()); Assert.assertFalse(message.hasDefaultSfixed64()); - Assert.assertFalse(message.hasDefaultFloat ()); - Assert.assertFalse(message.hasDefaultDouble ()); - Assert.assertFalse(message.hasDefaultBool ()); - Assert.assertFalse(message.hasDefaultString ()); - Assert.assertFalse(message.hasDefaultBytes ()); + Assert.assertFalse(message.hasDefaultFloat()); + Assert.assertFalse(message.hasDefaultDouble()); + Assert.assertFalse(message.hasDefaultBool()); + Assert.assertFalse(message.hasDefaultString()); + Assert.assertFalse(message.hasDefaultBytes()); - Assert.assertFalse(message.hasDefaultNestedEnum ()); + Assert.assertFalse(message.hasDefaultNestedEnum()); Assert.assertFalse(message.hasDefaultForeignEnum()); - Assert.assertFalse(message.hasDefaultImportEnum ()); + Assert.assertFalse(message.hasDefaultImportEnum()); Assert.assertFalse(message.hasDefaultStringPiece()); Assert.assertFalse(message.hasDefaultCord()); // Fields with defaults have their default values (duh). - Assert.assertEquals( 41 , message.getDefaultInt32 ()); - Assert.assertEquals( 42 , message.getDefaultInt64 ()); - Assert.assertEquals( 43 , message.getDefaultUint32 ()); - Assert.assertEquals( 44 , message.getDefaultUint64 ()); - Assert.assertEquals(-45 , message.getDefaultSint32 ()); - Assert.assertEquals( 46 , message.getDefaultSint64 ()); - Assert.assertEquals( 47 , message.getDefaultFixed32 ()); - Assert.assertEquals( 48 , message.getDefaultFixed64 ()); - Assert.assertEquals( 49 , message.getDefaultSfixed32()); - Assert.assertEquals(-50 , message.getDefaultSfixed64()); - Assert.assertEquals( 51.5 , message.getDefaultFloat (), 0.0); - Assert.assertEquals( 52e3 , message.getDefaultDouble (), 0.0); - Assert.assertEquals(true , message.getDefaultBool ()); - Assert.assertEquals("hello", message.getDefaultString ()); + Assert.assertEquals(41, message.getDefaultInt32()); + Assert.assertEquals(42, message.getDefaultInt64()); + Assert.assertEquals(43, message.getDefaultUint32()); + Assert.assertEquals(44, message.getDefaultUint64()); + Assert.assertEquals(-45, message.getDefaultSint32()); + Assert.assertEquals(46, message.getDefaultSint64()); + Assert.assertEquals(47, message.getDefaultFixed32()); + Assert.assertEquals(48, message.getDefaultFixed64()); + Assert.assertEquals(49, message.getDefaultSfixed32()); + Assert.assertEquals(-50, message.getDefaultSfixed64()); + Assert.assertEquals(51.5, message.getDefaultFloat(), 0.0); + Assert.assertEquals(52e3, message.getDefaultDouble(), 0.0); + Assert.assertEquals(true, message.getDefaultBool()); + Assert.assertEquals("hello", message.getDefaultString()); Assert.assertEquals(toBytes("world"), message.getDefaultBytes()); - Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getDefaultNestedEnum ()); + Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getDefaultNestedEnum()); Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getDefaultForeignEnum()); Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getDefaultImportEnum()); @@ -875,66 +856,64 @@ public static void assertClear(TestAllTypesOrBuilder message) { // ------------------------------------------------------------------- /** - * Assert (using {@code junit.framework.Assert}} that all fields of - * {@code message} are set to the values assigned by {@code setAllFields} - * followed by {@code modifyRepeatedFields}. + * Assert (using {@code junit.framework.Assert}} that all fields of {@code message} are set to the + * values assigned by {@code setAllFields} followed by {@code modifyRepeatedFields}. */ - public static void assertRepeatedFieldsModified( - TestAllTypesOrBuilder message) { + public static void assertRepeatedFieldsModified(TestAllTypesOrBuilder message) { // ModifyRepeatedFields only sets the second repeated element of each // field. In addition to verifying this, we also verify that the first // element and size were *not* modified. - Assert.assertEquals(2, message.getRepeatedInt32Count ()); - Assert.assertEquals(2, message.getRepeatedInt64Count ()); - Assert.assertEquals(2, message.getRepeatedUint32Count ()); - Assert.assertEquals(2, message.getRepeatedUint64Count ()); - Assert.assertEquals(2, message.getRepeatedSint32Count ()); - Assert.assertEquals(2, message.getRepeatedSint64Count ()); - Assert.assertEquals(2, message.getRepeatedFixed32Count ()); - Assert.assertEquals(2, message.getRepeatedFixed64Count ()); + Assert.assertEquals(2, message.getRepeatedInt32Count()); + Assert.assertEquals(2, message.getRepeatedInt64Count()); + Assert.assertEquals(2, message.getRepeatedUint32Count()); + Assert.assertEquals(2, message.getRepeatedUint64Count()); + Assert.assertEquals(2, message.getRepeatedSint32Count()); + Assert.assertEquals(2, message.getRepeatedSint64Count()); + Assert.assertEquals(2, message.getRepeatedFixed32Count()); + Assert.assertEquals(2, message.getRepeatedFixed64Count()); Assert.assertEquals(2, message.getRepeatedSfixed32Count()); Assert.assertEquals(2, message.getRepeatedSfixed64Count()); - Assert.assertEquals(2, message.getRepeatedFloatCount ()); - Assert.assertEquals(2, message.getRepeatedDoubleCount ()); - Assert.assertEquals(2, message.getRepeatedBoolCount ()); - Assert.assertEquals(2, message.getRepeatedStringCount ()); - Assert.assertEquals(2, message.getRepeatedBytesCount ()); - - Assert.assertEquals(2, message.getRepeatedGroupCount ()); - Assert.assertEquals(2, message.getRepeatedNestedMessageCount ()); + Assert.assertEquals(2, message.getRepeatedFloatCount()); + Assert.assertEquals(2, message.getRepeatedDoubleCount()); + Assert.assertEquals(2, message.getRepeatedBoolCount()); + Assert.assertEquals(2, message.getRepeatedStringCount()); + Assert.assertEquals(2, message.getRepeatedBytesCount()); + + Assert.assertEquals(2, message.getRepeatedGroupCount()); + Assert.assertEquals(2, message.getRepeatedNestedMessageCount()); Assert.assertEquals(2, message.getRepeatedForeignMessageCount()); - Assert.assertEquals(2, message.getRepeatedImportMessageCount ()); - Assert.assertEquals(2, message.getRepeatedLazyMessageCount ()); - Assert.assertEquals(2, message.getRepeatedNestedEnumCount ()); - Assert.assertEquals(2, message.getRepeatedForeignEnumCount ()); - Assert.assertEquals(2, message.getRepeatedImportEnumCount ()); + Assert.assertEquals(2, message.getRepeatedImportMessageCount()); + Assert.assertEquals(2, message.getRepeatedLazyMessageCount()); + Assert.assertEquals(2, message.getRepeatedNestedEnumCount()); + Assert.assertEquals(2, message.getRepeatedForeignEnumCount()); + Assert.assertEquals(2, message.getRepeatedImportEnumCount()); Assert.assertEquals(2, message.getRepeatedStringPieceCount()); Assert.assertEquals(2, message.getRepeatedCordCount()); - Assert.assertEquals(201 , message.getRepeatedInt32 (0)); - Assert.assertEquals(202L , message.getRepeatedInt64 (0)); - Assert.assertEquals(203 , message.getRepeatedUint32 (0)); - Assert.assertEquals(204L , message.getRepeatedUint64 (0)); - Assert.assertEquals(205 , message.getRepeatedSint32 (0)); - Assert.assertEquals(206L , message.getRepeatedSint64 (0)); - Assert.assertEquals(207 , message.getRepeatedFixed32 (0)); - Assert.assertEquals(208L , message.getRepeatedFixed64 (0)); - Assert.assertEquals(209 , message.getRepeatedSfixed32(0)); - Assert.assertEquals(210L , message.getRepeatedSfixed64(0)); - Assert.assertEquals(211F , message.getRepeatedFloat (0)); - Assert.assertEquals(212D , message.getRepeatedDouble (0)); - Assert.assertEquals(true , message.getRepeatedBool (0)); - Assert.assertEquals("215", message.getRepeatedString (0)); + Assert.assertEquals(201, message.getRepeatedInt32(0)); + Assert.assertEquals(202L, message.getRepeatedInt64(0)); + Assert.assertEquals(203, message.getRepeatedUint32(0)); + Assert.assertEquals(204L, message.getRepeatedUint64(0)); + Assert.assertEquals(205, message.getRepeatedSint32(0)); + Assert.assertEquals(206L, message.getRepeatedSint64(0)); + Assert.assertEquals(207, message.getRepeatedFixed32(0)); + Assert.assertEquals(208L, message.getRepeatedFixed64(0)); + Assert.assertEquals(209, message.getRepeatedSfixed32(0)); + Assert.assertEquals(210L, message.getRepeatedSfixed64(0)); + Assert.assertEquals(211F, message.getRepeatedFloat(0)); + Assert.assertEquals(212D, message.getRepeatedDouble(0)); + Assert.assertEquals(true, message.getRepeatedBool(0)); + Assert.assertEquals("215", message.getRepeatedString(0)); Assert.assertEquals(toBytes("216"), message.getRepeatedBytes(0)); - Assert.assertEquals(217, message.getRepeatedGroup (0).getA()); - Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb()); + Assert.assertEquals(217, message.getRepeatedGroup(0).getA()); + Assert.assertEquals(218, message.getRepeatedNestedMessage(0).getBb()); Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC()); - Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD()); - Assert.assertEquals(227, message.getRepeatedLazyMessage (0).getBb()); + Assert.assertEquals(220, message.getRepeatedImportMessage(0).getD()); + Assert.assertEquals(227, message.getRepeatedLazyMessage(0).getBb()); - Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0)); + Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum(0)); Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0)); Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getRepeatedImportEnum(0)); @@ -942,29 +921,29 @@ public static void assertRepeatedFieldsModified( Assert.assertEquals("225", message.getRepeatedCord(0)); // Actually verify the second (modified) elements now. - Assert.assertEquals(501 , message.getRepeatedInt32 (1)); - Assert.assertEquals(502L , message.getRepeatedInt64 (1)); - Assert.assertEquals(503 , message.getRepeatedUint32 (1)); - Assert.assertEquals(504L , message.getRepeatedUint64 (1)); - Assert.assertEquals(505 , message.getRepeatedSint32 (1)); - Assert.assertEquals(506L , message.getRepeatedSint64 (1)); - Assert.assertEquals(507 , message.getRepeatedFixed32 (1)); - Assert.assertEquals(508L , message.getRepeatedFixed64 (1)); - Assert.assertEquals(509 , message.getRepeatedSfixed32(1)); - Assert.assertEquals(510L , message.getRepeatedSfixed64(1)); - Assert.assertEquals(511F , message.getRepeatedFloat (1)); - Assert.assertEquals(512D , message.getRepeatedDouble (1)); - Assert.assertEquals(true , message.getRepeatedBool (1)); - Assert.assertEquals("515", message.getRepeatedString (1)); + Assert.assertEquals(501, message.getRepeatedInt32(1)); + Assert.assertEquals(502L, message.getRepeatedInt64(1)); + Assert.assertEquals(503, message.getRepeatedUint32(1)); + Assert.assertEquals(504L, message.getRepeatedUint64(1)); + Assert.assertEquals(505, message.getRepeatedSint32(1)); + Assert.assertEquals(506L, message.getRepeatedSint64(1)); + Assert.assertEquals(507, message.getRepeatedFixed32(1)); + Assert.assertEquals(508L, message.getRepeatedFixed64(1)); + Assert.assertEquals(509, message.getRepeatedSfixed32(1)); + Assert.assertEquals(510L, message.getRepeatedSfixed64(1)); + Assert.assertEquals(511F, message.getRepeatedFloat(1)); + Assert.assertEquals(512D, message.getRepeatedDouble(1)); + Assert.assertEquals(true, message.getRepeatedBool(1)); + Assert.assertEquals("515", message.getRepeatedString(1)); Assert.assertEquals(toBytes("516"), message.getRepeatedBytes(1)); - Assert.assertEquals(517, message.getRepeatedGroup (1).getA()); - Assert.assertEquals(518, message.getRepeatedNestedMessage (1).getBb()); + Assert.assertEquals(517, message.getRepeatedGroup(1).getA()); + Assert.assertEquals(518, message.getRepeatedNestedMessage(1).getBb()); Assert.assertEquals(519, message.getRepeatedForeignMessage(1).getC()); - Assert.assertEquals(520, message.getRepeatedImportMessage (1).getD()); - Assert.assertEquals(527, message.getRepeatedLazyMessage (1).getBb()); + Assert.assertEquals(520, message.getRepeatedImportMessage(1).getD()); + Assert.assertEquals(527, message.getRepeatedLazyMessage(1).getBb()); - Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getRepeatedNestedEnum (1)); + Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getRepeatedNestedEnum(1)); Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getRepeatedForeignEnum(1)); Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getRepeatedImportEnum(1)); @@ -972,172 +951,170 @@ public static void assertRepeatedFieldsModified( Assert.assertEquals("525", message.getRepeatedCord(1)); } - /** - * Set every field of {@code message} to a unique value. - */ + /** Set every field of {@code message} to a unique value. */ public static void setPackedFields(TestPackedTypes.Builder message) { - message.addPackedInt32 (601); - message.addPackedInt64 (602); - message.addPackedUint32 (603); - message.addPackedUint64 (604); - message.addPackedSint32 (605); - message.addPackedSint64 (606); - message.addPackedFixed32 (607); - message.addPackedFixed64 (608); + message.addPackedInt32(601); + message.addPackedInt64(602); + message.addPackedUint32(603); + message.addPackedUint64(604); + message.addPackedSint32(605); + message.addPackedSint64(606); + message.addPackedFixed32(607); + message.addPackedFixed64(608); message.addPackedSfixed32(609); message.addPackedSfixed64(610); - message.addPackedFloat (611); - message.addPackedDouble (612); - message.addPackedBool (true); - message.addPackedEnum (ForeignEnum.FOREIGN_BAR); + message.addPackedFloat(611); + message.addPackedDouble(612); + message.addPackedBool(true); + message.addPackedEnum(ForeignEnum.FOREIGN_BAR); // Add a second one of each field. - message.addPackedInt32 (701); - message.addPackedInt64 (702); - message.addPackedUint32 (703); - message.addPackedUint64 (704); - message.addPackedSint32 (705); - message.addPackedSint64 (706); - message.addPackedFixed32 (707); - message.addPackedFixed64 (708); + message.addPackedInt32(701); + message.addPackedInt64(702); + message.addPackedUint32(703); + message.addPackedUint64(704); + message.addPackedSint32(705); + message.addPackedSint64(706); + message.addPackedFixed32(707); + message.addPackedFixed64(708); message.addPackedSfixed32(709); message.addPackedSfixed64(710); - message.addPackedFloat (711); - message.addPackedDouble (712); - message.addPackedBool (false); - message.addPackedEnum (ForeignEnum.FOREIGN_BAZ); + message.addPackedFloat(711); + message.addPackedDouble(712); + message.addPackedBool(false); + message.addPackedEnum(ForeignEnum.FOREIGN_BAZ); } /** - * Set every field of {@code message} to a unique value. Must correspond with - * the values applied by {@code setPackedFields}. + * Set every field of {@code message} to a unique value. Must correspond with the values applied + * by {@code setPackedFields}. */ public static void setUnpackedFields(TestUnpackedTypes.Builder message) { - message.addUnpackedInt32 (601); - message.addUnpackedInt64 (602); - message.addUnpackedUint32 (603); - message.addUnpackedUint64 (604); - message.addUnpackedSint32 (605); - message.addUnpackedSint64 (606); - message.addUnpackedFixed32 (607); - message.addUnpackedFixed64 (608); + message.addUnpackedInt32(601); + message.addUnpackedInt64(602); + message.addUnpackedUint32(603); + message.addUnpackedUint64(604); + message.addUnpackedSint32(605); + message.addUnpackedSint64(606); + message.addUnpackedFixed32(607); + message.addUnpackedFixed64(608); message.addUnpackedSfixed32(609); message.addUnpackedSfixed64(610); - message.addUnpackedFloat (611); - message.addUnpackedDouble (612); - message.addUnpackedBool (true); - message.addUnpackedEnum (ForeignEnum.FOREIGN_BAR); + message.addUnpackedFloat(611); + message.addUnpackedDouble(612); + message.addUnpackedBool(true); + message.addUnpackedEnum(ForeignEnum.FOREIGN_BAR); // Add a second one of each field. - message.addUnpackedInt32 (701); - message.addUnpackedInt64 (702); - message.addUnpackedUint32 (703); - message.addUnpackedUint64 (704); - message.addUnpackedSint32 (705); - message.addUnpackedSint64 (706); - message.addUnpackedFixed32 (707); - message.addUnpackedFixed64 (708); + message.addUnpackedInt32(701); + message.addUnpackedInt64(702); + message.addUnpackedUint32(703); + message.addUnpackedUint64(704); + message.addUnpackedSint32(705); + message.addUnpackedSint64(706); + message.addUnpackedFixed32(707); + message.addUnpackedFixed64(708); message.addUnpackedSfixed32(709); message.addUnpackedSfixed64(710); - message.addUnpackedFloat (711); - message.addUnpackedDouble (712); - message.addUnpackedBool (false); - message.addUnpackedEnum (ForeignEnum.FOREIGN_BAZ); + message.addUnpackedFloat(711); + message.addUnpackedDouble(712); + message.addUnpackedBool(false); + message.addUnpackedEnum(ForeignEnum.FOREIGN_BAZ); } /** - * Assert (using {@code junit.framework.Assert}} that all fields of - * {@code message} are set to the values assigned by {@code setPackedFields}. + * Assert (using {@code junit.framework.Assert}} that all fields of {@code message} are set to the + * values assigned by {@code setPackedFields}. */ public static void assertPackedFieldsSet(TestPackedTypes message) { - Assert.assertEquals(2, message.getPackedInt32Count ()); - Assert.assertEquals(2, message.getPackedInt64Count ()); - Assert.assertEquals(2, message.getPackedUint32Count ()); - Assert.assertEquals(2, message.getPackedUint64Count ()); - Assert.assertEquals(2, message.getPackedSint32Count ()); - Assert.assertEquals(2, message.getPackedSint64Count ()); - Assert.assertEquals(2, message.getPackedFixed32Count ()); - Assert.assertEquals(2, message.getPackedFixed64Count ()); + Assert.assertEquals(2, message.getPackedInt32Count()); + Assert.assertEquals(2, message.getPackedInt64Count()); + Assert.assertEquals(2, message.getPackedUint32Count()); + Assert.assertEquals(2, message.getPackedUint64Count()); + Assert.assertEquals(2, message.getPackedSint32Count()); + Assert.assertEquals(2, message.getPackedSint64Count()); + Assert.assertEquals(2, message.getPackedFixed32Count()); + Assert.assertEquals(2, message.getPackedFixed64Count()); Assert.assertEquals(2, message.getPackedSfixed32Count()); Assert.assertEquals(2, message.getPackedSfixed64Count()); - Assert.assertEquals(2, message.getPackedFloatCount ()); - Assert.assertEquals(2, message.getPackedDoubleCount ()); - Assert.assertEquals(2, message.getPackedBoolCount ()); - Assert.assertEquals(2, message.getPackedEnumCount ()); - Assert.assertEquals(601 , message.getPackedInt32 (0)); - Assert.assertEquals(602 , message.getPackedInt64 (0)); - Assert.assertEquals(603 , message.getPackedUint32 (0)); - Assert.assertEquals(604 , message.getPackedUint64 (0)); - Assert.assertEquals(605 , message.getPackedSint32 (0)); - Assert.assertEquals(606 , message.getPackedSint64 (0)); - Assert.assertEquals(607 , message.getPackedFixed32 (0)); - Assert.assertEquals(608 , message.getPackedFixed64 (0)); - Assert.assertEquals(609 , message.getPackedSfixed32(0)); - Assert.assertEquals(610 , message.getPackedSfixed64(0)); - Assert.assertEquals(611 , message.getPackedFloat (0), 0.0); - Assert.assertEquals(612 , message.getPackedDouble (0), 0.0); - Assert.assertEquals(true , message.getPackedBool (0)); + Assert.assertEquals(2, message.getPackedFloatCount()); + Assert.assertEquals(2, message.getPackedDoubleCount()); + Assert.assertEquals(2, message.getPackedBoolCount()); + Assert.assertEquals(2, message.getPackedEnumCount()); + Assert.assertEquals(601, message.getPackedInt32(0)); + Assert.assertEquals(602, message.getPackedInt64(0)); + Assert.assertEquals(603, message.getPackedUint32(0)); + Assert.assertEquals(604, message.getPackedUint64(0)); + Assert.assertEquals(605, message.getPackedSint32(0)); + Assert.assertEquals(606, message.getPackedSint64(0)); + Assert.assertEquals(607, message.getPackedFixed32(0)); + Assert.assertEquals(608, message.getPackedFixed64(0)); + Assert.assertEquals(609, message.getPackedSfixed32(0)); + Assert.assertEquals(610, message.getPackedSfixed64(0)); + Assert.assertEquals(611, message.getPackedFloat(0), 0.0); + Assert.assertEquals(612, message.getPackedDouble(0), 0.0); + Assert.assertEquals(true, message.getPackedBool(0)); Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getPackedEnum(0)); - Assert.assertEquals(701 , message.getPackedInt32 (1)); - Assert.assertEquals(702 , message.getPackedInt64 (1)); - Assert.assertEquals(703 , message.getPackedUint32 (1)); - Assert.assertEquals(704 , message.getPackedUint64 (1)); - Assert.assertEquals(705 , message.getPackedSint32 (1)); - Assert.assertEquals(706 , message.getPackedSint64 (1)); - Assert.assertEquals(707 , message.getPackedFixed32 (1)); - Assert.assertEquals(708 , message.getPackedFixed64 (1)); - Assert.assertEquals(709 , message.getPackedSfixed32(1)); - Assert.assertEquals(710 , message.getPackedSfixed64(1)); - Assert.assertEquals(711 , message.getPackedFloat (1), 0.0); - Assert.assertEquals(712 , message.getPackedDouble (1), 0.0); - Assert.assertEquals(false, message.getPackedBool (1)); + Assert.assertEquals(701, message.getPackedInt32(1)); + Assert.assertEquals(702, message.getPackedInt64(1)); + Assert.assertEquals(703, message.getPackedUint32(1)); + Assert.assertEquals(704, message.getPackedUint64(1)); + Assert.assertEquals(705, message.getPackedSint32(1)); + Assert.assertEquals(706, message.getPackedSint64(1)); + Assert.assertEquals(707, message.getPackedFixed32(1)); + Assert.assertEquals(708, message.getPackedFixed64(1)); + Assert.assertEquals(709, message.getPackedSfixed32(1)); + Assert.assertEquals(710, message.getPackedSfixed64(1)); + Assert.assertEquals(711, message.getPackedFloat(1), 0.0); + Assert.assertEquals(712, message.getPackedDouble(1), 0.0); + Assert.assertEquals(false, message.getPackedBool(1)); Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1)); } /** - * Assert (using {@code junit.framework.Assert}} that all fields of - * {@code message} are set to the values assigned by {@code setUnpackedFields}. + * Assert (using {@code junit.framework.Assert}} that all fields of {@code message} are set to the + * values assigned by {@code setUnpackedFields}. */ public static void assertUnpackedFieldsSet(TestUnpackedTypes message) { - Assert.assertEquals(2, message.getUnpackedInt32Count ()); - Assert.assertEquals(2, message.getUnpackedInt64Count ()); - Assert.assertEquals(2, message.getUnpackedUint32Count ()); - Assert.assertEquals(2, message.getUnpackedUint64Count ()); - Assert.assertEquals(2, message.getUnpackedSint32Count ()); - Assert.assertEquals(2, message.getUnpackedSint64Count ()); - Assert.assertEquals(2, message.getUnpackedFixed32Count ()); - Assert.assertEquals(2, message.getUnpackedFixed64Count ()); + Assert.assertEquals(2, message.getUnpackedInt32Count()); + Assert.assertEquals(2, message.getUnpackedInt64Count()); + Assert.assertEquals(2, message.getUnpackedUint32Count()); + Assert.assertEquals(2, message.getUnpackedUint64Count()); + Assert.assertEquals(2, message.getUnpackedSint32Count()); + Assert.assertEquals(2, message.getUnpackedSint64Count()); + Assert.assertEquals(2, message.getUnpackedFixed32Count()); + Assert.assertEquals(2, message.getUnpackedFixed64Count()); Assert.assertEquals(2, message.getUnpackedSfixed32Count()); Assert.assertEquals(2, message.getUnpackedSfixed64Count()); - Assert.assertEquals(2, message.getUnpackedFloatCount ()); - Assert.assertEquals(2, message.getUnpackedDoubleCount ()); - Assert.assertEquals(2, message.getUnpackedBoolCount ()); - Assert.assertEquals(2, message.getUnpackedEnumCount ()); - Assert.assertEquals(601 , message.getUnpackedInt32 (0)); - Assert.assertEquals(602 , message.getUnpackedInt64 (0)); - Assert.assertEquals(603 , message.getUnpackedUint32 (0)); - Assert.assertEquals(604 , message.getUnpackedUint64 (0)); - Assert.assertEquals(605 , message.getUnpackedSint32 (0)); - Assert.assertEquals(606 , message.getUnpackedSint64 (0)); - Assert.assertEquals(607 , message.getUnpackedFixed32 (0)); - Assert.assertEquals(608 , message.getUnpackedFixed64 (0)); - Assert.assertEquals(609 , message.getUnpackedSfixed32(0)); - Assert.assertEquals(610 , message.getUnpackedSfixed64(0)); - Assert.assertEquals(611 , message.getUnpackedFloat (0), 0.0); - Assert.assertEquals(612 , message.getUnpackedDouble (0), 0.0); - Assert.assertEquals(true , message.getUnpackedBool (0)); + Assert.assertEquals(2, message.getUnpackedFloatCount()); + Assert.assertEquals(2, message.getUnpackedDoubleCount()); + Assert.assertEquals(2, message.getUnpackedBoolCount()); + Assert.assertEquals(2, message.getUnpackedEnumCount()); + Assert.assertEquals(601, message.getUnpackedInt32(0)); + Assert.assertEquals(602, message.getUnpackedInt64(0)); + Assert.assertEquals(603, message.getUnpackedUint32(0)); + Assert.assertEquals(604, message.getUnpackedUint64(0)); + Assert.assertEquals(605, message.getUnpackedSint32(0)); + Assert.assertEquals(606, message.getUnpackedSint64(0)); + Assert.assertEquals(607, message.getUnpackedFixed32(0)); + Assert.assertEquals(608, message.getUnpackedFixed64(0)); + Assert.assertEquals(609, message.getUnpackedSfixed32(0)); + Assert.assertEquals(610, message.getUnpackedSfixed64(0)); + Assert.assertEquals(611, message.getUnpackedFloat(0), 0.0); + Assert.assertEquals(612, message.getUnpackedDouble(0), 0.0); + Assert.assertEquals(true, message.getUnpackedBool(0)); Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getUnpackedEnum(0)); - Assert.assertEquals(701 , message.getUnpackedInt32 (1)); - Assert.assertEquals(702 , message.getUnpackedInt64 (1)); - Assert.assertEquals(703 , message.getUnpackedUint32 (1)); - Assert.assertEquals(704 , message.getUnpackedUint64 (1)); - Assert.assertEquals(705 , message.getUnpackedSint32 (1)); - Assert.assertEquals(706 , message.getUnpackedSint64 (1)); - Assert.assertEquals(707 , message.getUnpackedFixed32 (1)); - Assert.assertEquals(708 , message.getUnpackedFixed64 (1)); - Assert.assertEquals(709 , message.getUnpackedSfixed32(1)); - Assert.assertEquals(710 , message.getUnpackedSfixed64(1)); - Assert.assertEquals(711 , message.getUnpackedFloat (1), 0.0); - Assert.assertEquals(712 , message.getUnpackedDouble (1), 0.0); - Assert.assertEquals(false, message.getUnpackedBool (1)); + Assert.assertEquals(701, message.getUnpackedInt32(1)); + Assert.assertEquals(702, message.getUnpackedInt64(1)); + Assert.assertEquals(703, message.getUnpackedUint32(1)); + Assert.assertEquals(704, message.getUnpackedUint64(1)); + Assert.assertEquals(705, message.getUnpackedSint32(1)); + Assert.assertEquals(706, message.getUnpackedSint64(1)); + Assert.assertEquals(707, message.getUnpackedFixed32(1)); + Assert.assertEquals(708, message.getUnpackedFixed64(1)); + Assert.assertEquals(709, message.getUnpackedSfixed32(1)); + Assert.assertEquals(710, message.getUnpackedSfixed64(1)); + Assert.assertEquals(711, message.getUnpackedFloat(1), 0.0); + Assert.assertEquals(712, message.getUnpackedDouble(1), 0.0); + Assert.assertEquals(false, message.getUnpackedBool(1)); Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getUnpackedEnum(1)); } @@ -1150,99 +1127,119 @@ public static void assertUnpackedFieldsSet(TestUnpackedTypes message) { private static void assertEqualsExactType(int a, int b) { Assert.assertEquals(a, b); } + private static void assertEqualsExactType(long a, long b) { Assert.assertEquals(a, b); } + private static void assertEqualsExactType(float a, float b) { Assert.assertEquals(a, b, 0.0); } + private static void assertEqualsExactType(double a, double b) { Assert.assertEquals(a, b, 0.0); } + private static void assertEqualsExactType(boolean a, boolean b) { Assert.assertEquals(a, b); } + private static void assertEqualsExactType(String a, String b) { Assert.assertEquals(a, b); } + private static void assertEqualsExactType(ByteString a, ByteString b) { Assert.assertEquals(a, b); } - private static void assertEqualsExactType(TestAllTypes.NestedEnum a, - TestAllTypes.NestedEnum b) { + + private static void assertEqualsExactType(TestAllTypes.NestedEnum a, TestAllTypes.NestedEnum b) { Assert.assertEquals(a, b); } + private static void assertEqualsExactType(ForeignEnum a, ForeignEnum b) { Assert.assertEquals(a, b); } + private static void assertEqualsExactType(ImportEnum a, ImportEnum b) { Assert.assertEquals(a, b); } - private static void assertEqualsExactType(TestAllTypesLite.NestedEnum a, - TestAllTypesLite.NestedEnum b) { + + private static void assertEqualsExactType( + TestAllTypesLite.NestedEnum a, TestAllTypesLite.NestedEnum b) { Assert.assertEquals(a, b); } - private static void assertEqualsExactType(ForeignEnumLite a, - ForeignEnumLite b) { + + private static void assertEqualsExactType(ForeignEnumLite a, ForeignEnumLite b) { Assert.assertEquals(a, b); } - private static void assertEqualsExactType(ImportEnumLite a, - ImportEnumLite b) { + + private static void assertEqualsExactType(ImportEnumLite a, ImportEnumLite b) { Assert.assertEquals(a, b); } /** - * Get an unmodifiable {@link ExtensionRegistry} containing all the - * extensions of {@code TestAllExtensions}. + * Get an unmodifiable {@link ExtensionRegistry} containing all the extensions of {@code + * TestAllExtensions}. */ - public static ExtensionRegistry getExtensionRegistry() { + public static ExtensionRegistryLite getExtensionRegistry() { + ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); + registerAllExtensions(registry); + return registry.getUnmodifiable(); + } + + // BEGIN FULL-RUNTIME + /** + * Get an unmodifiable {@link ExtensionRegistry} containing all the extensions of {@code + * TestAllExtensions}. + */ + public static ExtensionRegistry getFullExtensionRegistry() { ExtensionRegistry registry = ExtensionRegistry.newInstance(); registerAllExtensions(registry); return registry.getUnmodifiable(); } + // END FULL-RUNTIME /** - * Register all of {@code TestAllExtensions}'s extensions with the - * given {@link ExtensionRegistry}. + * Register all of {@code TestAllExtensions}'s extensions with the given {@link + * ExtensionRegistry}. */ - public static void registerAllExtensions(ExtensionRegistry registry) { + public static void registerAllExtensions(ExtensionRegistryLite registry) { UnittestProto.registerAllExtensions(registry); TestUtilLite.registerAllExtensionsLite(registry); } /** - * Set every field of {@code message} to the values expected by - * {@code assertAllExtensionsSet()}. + * Set every field of {@code message} to the values expected by {@code assertAllExtensionsSet()}. */ public static void setAllExtensions(TestAllExtensions.Builder message) { - message.setExtension(optionalInt32Extension , 101); - message.setExtension(optionalInt64Extension , 102L); - message.setExtension(optionalUint32Extension , 103); - message.setExtension(optionalUint64Extension , 104L); - message.setExtension(optionalSint32Extension , 105); - message.setExtension(optionalSint64Extension , 106L); - message.setExtension(optionalFixed32Extension , 107); - message.setExtension(optionalFixed64Extension , 108L); + message.setExtension(optionalInt32Extension, 101); + message.setExtension(optionalInt64Extension, 102L); + message.setExtension(optionalUint32Extension, 103); + message.setExtension(optionalUint64Extension, 104L); + message.setExtension(optionalSint32Extension, 105); + message.setExtension(optionalSint64Extension, 106L); + message.setExtension(optionalFixed32Extension, 107); + message.setExtension(optionalFixed64Extension, 108L); message.setExtension(optionalSfixed32Extension, 109); message.setExtension(optionalSfixed64Extension, 110L); - message.setExtension(optionalFloatExtension , 111F); - message.setExtension(optionalDoubleExtension , 112D); - message.setExtension(optionalBoolExtension , true); - message.setExtension(optionalStringExtension , "115"); - message.setExtension(optionalBytesExtension , toBytes("116")); - - message.setExtension(optionalGroupExtension, - OptionalGroup_extension.newBuilder().setA(117).build()); - message.setExtension(optionalNestedMessageExtension, - TestAllTypes.NestedMessage.newBuilder().setBb(118).build()); - message.setExtension(optionalForeignMessageExtension, - ForeignMessage.newBuilder().setC(119).build()); - message.setExtension(optionalImportMessageExtension, - ImportMessage.newBuilder().setD(120).build()); - message.setExtension(optionalPublicImportMessageExtension, - PublicImportMessage.newBuilder().setE(126).build()); - message.setExtension(optionalLazyMessageExtension, - TestAllTypes.NestedMessage.newBuilder().setBb(127).build()); + message.setExtension(optionalFloatExtension, 111F); + message.setExtension(optionalDoubleExtension, 112D); + message.setExtension(optionalBoolExtension, true); + message.setExtension(optionalStringExtension, "115"); + message.setExtension(optionalBytesExtension, toBytes("116")); + + message.setExtension( + optionalGroupExtension, OptionalGroup_extension.newBuilder().setA(117).build()); + message.setExtension( + optionalNestedMessageExtension, TestAllTypes.NestedMessage.newBuilder().setBb(118).build()); + message.setExtension( + optionalForeignMessageExtension, ForeignMessage.newBuilder().setC(119).build()); + message.setExtension( + optionalImportMessageExtension, ImportMessage.newBuilder().setD(120).build()); + message.setExtension( + optionalPublicImportMessageExtension, PublicImportMessage.newBuilder().setE(126).build()); + message.setExtension( + optionalLazyMessageExtension, TestAllTypes.NestedMessage.newBuilder().setBb(127).build()); message.setExtension(optionalNestedEnumExtension, TestAllTypes.NestedEnum.BAZ); message.setExtension(optionalForeignEnumExtension, ForeignEnum.FOREIGN_BAZ); @@ -1253,32 +1250,32 @@ public static void setAllExtensions(TestAllExtensions.Builder message) { // ----------------------------------------------------------------- - message.addExtension(repeatedInt32Extension , 201); - message.addExtension(repeatedInt64Extension , 202L); - message.addExtension(repeatedUint32Extension , 203); - message.addExtension(repeatedUint64Extension , 204L); - message.addExtension(repeatedSint32Extension , 205); - message.addExtension(repeatedSint64Extension , 206L); - message.addExtension(repeatedFixed32Extension , 207); - message.addExtension(repeatedFixed64Extension , 208L); + message.addExtension(repeatedInt32Extension, 201); + message.addExtension(repeatedInt64Extension, 202L); + message.addExtension(repeatedUint32Extension, 203); + message.addExtension(repeatedUint64Extension, 204L); + message.addExtension(repeatedSint32Extension, 205); + message.addExtension(repeatedSint64Extension, 206L); + message.addExtension(repeatedFixed32Extension, 207); + message.addExtension(repeatedFixed64Extension, 208L); message.addExtension(repeatedSfixed32Extension, 209); message.addExtension(repeatedSfixed64Extension, 210L); - message.addExtension(repeatedFloatExtension , 211F); - message.addExtension(repeatedDoubleExtension , 212D); - message.addExtension(repeatedBoolExtension , true); - message.addExtension(repeatedStringExtension , "215"); - message.addExtension(repeatedBytesExtension , toBytes("216")); - - message.addExtension(repeatedGroupExtension, - RepeatedGroup_extension.newBuilder().setA(217).build()); - message.addExtension(repeatedNestedMessageExtension, - TestAllTypes.NestedMessage.newBuilder().setBb(218).build()); - message.addExtension(repeatedForeignMessageExtension, - ForeignMessage.newBuilder().setC(219).build()); - message.addExtension(repeatedImportMessageExtension, - ImportMessage.newBuilder().setD(220).build()); - message.addExtension(repeatedLazyMessageExtension, - TestAllTypes.NestedMessage.newBuilder().setBb(227).build()); + message.addExtension(repeatedFloatExtension, 211F); + message.addExtension(repeatedDoubleExtension, 212D); + message.addExtension(repeatedBoolExtension, true); + message.addExtension(repeatedStringExtension, "215"); + message.addExtension(repeatedBytesExtension, toBytes("216")); + + message.addExtension( + repeatedGroupExtension, RepeatedGroup_extension.newBuilder().setA(217).build()); + message.addExtension( + repeatedNestedMessageExtension, TestAllTypes.NestedMessage.newBuilder().setBb(218).build()); + message.addExtension( + repeatedForeignMessageExtension, ForeignMessage.newBuilder().setC(219).build()); + message.addExtension( + repeatedImportMessageExtension, ImportMessage.newBuilder().setD(220).build()); + message.addExtension( + repeatedLazyMessageExtension, TestAllTypes.NestedMessage.newBuilder().setBb(227).build()); message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAR); message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAR); @@ -1288,32 +1285,32 @@ public static void setAllExtensions(TestAllExtensions.Builder message) { message.addExtension(repeatedCordExtension, "225"); // Add a second one of each field. - message.addExtension(repeatedInt32Extension , 301); - message.addExtension(repeatedInt64Extension , 302L); - message.addExtension(repeatedUint32Extension , 303); - message.addExtension(repeatedUint64Extension , 304L); - message.addExtension(repeatedSint32Extension , 305); - message.addExtension(repeatedSint64Extension , 306L); - message.addExtension(repeatedFixed32Extension , 307); - message.addExtension(repeatedFixed64Extension , 308L); + message.addExtension(repeatedInt32Extension, 301); + message.addExtension(repeatedInt64Extension, 302L); + message.addExtension(repeatedUint32Extension, 303); + message.addExtension(repeatedUint64Extension, 304L); + message.addExtension(repeatedSint32Extension, 305); + message.addExtension(repeatedSint64Extension, 306L); + message.addExtension(repeatedFixed32Extension, 307); + message.addExtension(repeatedFixed64Extension, 308L); message.addExtension(repeatedSfixed32Extension, 309); message.addExtension(repeatedSfixed64Extension, 310L); - message.addExtension(repeatedFloatExtension , 311F); - message.addExtension(repeatedDoubleExtension , 312D); - message.addExtension(repeatedBoolExtension , false); - message.addExtension(repeatedStringExtension , "315"); - message.addExtension(repeatedBytesExtension , toBytes("316")); - - message.addExtension(repeatedGroupExtension, - RepeatedGroup_extension.newBuilder().setA(317).build()); - message.addExtension(repeatedNestedMessageExtension, - TestAllTypes.NestedMessage.newBuilder().setBb(318).build()); - message.addExtension(repeatedForeignMessageExtension, - ForeignMessage.newBuilder().setC(319).build()); - message.addExtension(repeatedImportMessageExtension, - ImportMessage.newBuilder().setD(320).build()); - message.addExtension(repeatedLazyMessageExtension, - TestAllTypes.NestedMessage.newBuilder().setBb(327).build()); + message.addExtension(repeatedFloatExtension, 311F); + message.addExtension(repeatedDoubleExtension, 312D); + message.addExtension(repeatedBoolExtension, false); + message.addExtension(repeatedStringExtension, "315"); + message.addExtension(repeatedBytesExtension, toBytes("316")); + + message.addExtension( + repeatedGroupExtension, RepeatedGroup_extension.newBuilder().setA(317).build()); + message.addExtension( + repeatedNestedMessageExtension, TestAllTypes.NestedMessage.newBuilder().setBb(318).build()); + message.addExtension( + repeatedForeignMessageExtension, ForeignMessage.newBuilder().setC(319).build()); + message.addExtension( + repeatedImportMessageExtension, ImportMessage.newBuilder().setD(320).build()); + message.addExtension( + repeatedLazyMessageExtension, TestAllTypes.NestedMessage.newBuilder().setBb(327).build()); message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAZ); message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAZ); @@ -1324,21 +1321,21 @@ public static void setAllExtensions(TestAllExtensions.Builder message) { // ----------------------------------------------------------------- - message.setExtension(defaultInt32Extension , 401); - message.setExtension(defaultInt64Extension , 402L); - message.setExtension(defaultUint32Extension , 403); - message.setExtension(defaultUint64Extension , 404L); - message.setExtension(defaultSint32Extension , 405); - message.setExtension(defaultSint64Extension , 406L); - message.setExtension(defaultFixed32Extension , 407); - message.setExtension(defaultFixed64Extension , 408L); + message.setExtension(defaultInt32Extension, 401); + message.setExtension(defaultInt64Extension, 402L); + message.setExtension(defaultUint32Extension, 403); + message.setExtension(defaultUint64Extension, 404L); + message.setExtension(defaultSint32Extension, 405); + message.setExtension(defaultSint64Extension, 406L); + message.setExtension(defaultFixed32Extension, 407); + message.setExtension(defaultFixed64Extension, 408L); message.setExtension(defaultSfixed32Extension, 409); message.setExtension(defaultSfixed64Extension, 410L); - message.setExtension(defaultFloatExtension , 411F); - message.setExtension(defaultDoubleExtension , 412D); - message.setExtension(defaultBoolExtension , false); - message.setExtension(defaultStringExtension , "415"); - message.setExtension(defaultBytesExtension , toBytes("416")); + message.setExtension(defaultFloatExtension, 411F); + message.setExtension(defaultDoubleExtension, 412D); + message.setExtension(defaultBoolExtension, false); + message.setExtension(defaultStringExtension, "415"); + message.setExtension(defaultBytesExtension, toBytes("416")); message.setExtension(defaultNestedEnumExtension, TestAllTypes.NestedEnum.FOO); message.setExtension(defaultForeignEnumExtension, ForeignEnum.FOREIGN_FOO); @@ -1348,8 +1345,8 @@ public static void setAllExtensions(TestAllExtensions.Builder message) { message.setExtension(defaultCordExtension, "425"); message.setExtension(oneofUint32Extension, 601); - message.setExtension(oneofNestedMessageExtension, - TestAllTypes.NestedMessage.newBuilder().setBb(602).build()); + message.setExtension( + oneofNestedMessageExtension, TestAllTypes.NestedMessage.newBuilder().setBb(602).build()); message.setExtension(oneofStringExtension, "603"); message.setExtension(oneofBytesExtension, toBytes("604")); } @@ -1357,41 +1354,44 @@ public static void setAllExtensions(TestAllExtensions.Builder message) { // ------------------------------------------------------------------- /** - * Modify the repeated extensions of {@code message} to contain the values - * expected by {@code assertRepeatedExtensionsModified()}. + * Modify the repeated extensions of {@code message} to contain the values expected by {@code + * assertRepeatedExtensionsModified()}. */ - public static void modifyRepeatedExtensions( - TestAllExtensions.Builder message) { - message.setExtension(repeatedInt32Extension , 1, 501); - message.setExtension(repeatedInt64Extension , 1, 502L); - message.setExtension(repeatedUint32Extension , 1, 503); - message.setExtension(repeatedUint64Extension , 1, 504L); - message.setExtension(repeatedSint32Extension , 1, 505); - message.setExtension(repeatedSint64Extension , 1, 506L); - message.setExtension(repeatedFixed32Extension , 1, 507); - message.setExtension(repeatedFixed64Extension , 1, 508L); + public static void modifyRepeatedExtensions(TestAllExtensions.Builder message) { + message.setExtension(repeatedInt32Extension, 1, 501); + message.setExtension(repeatedInt64Extension, 1, 502L); + message.setExtension(repeatedUint32Extension, 1, 503); + message.setExtension(repeatedUint64Extension, 1, 504L); + message.setExtension(repeatedSint32Extension, 1, 505); + message.setExtension(repeatedSint64Extension, 1, 506L); + message.setExtension(repeatedFixed32Extension, 1, 507); + message.setExtension(repeatedFixed64Extension, 1, 508L); message.setExtension(repeatedSfixed32Extension, 1, 509); message.setExtension(repeatedSfixed64Extension, 1, 510L); - message.setExtension(repeatedFloatExtension , 1, 511F); - message.setExtension(repeatedDoubleExtension , 1, 512D); - message.setExtension(repeatedBoolExtension , 1, true); - message.setExtension(repeatedStringExtension , 1, "515"); - message.setExtension(repeatedBytesExtension , 1, toBytes("516")); - - message.setExtension(repeatedGroupExtension, 1, - RepeatedGroup_extension.newBuilder().setA(517).build()); - message.setExtension(repeatedNestedMessageExtension, 1, - TestAllTypes.NestedMessage.newBuilder().setBb(518).build()); - message.setExtension(repeatedForeignMessageExtension, 1, - ForeignMessage.newBuilder().setC(519).build()); - message.setExtension(repeatedImportMessageExtension, 1, - ImportMessage.newBuilder().setD(520).build()); - message.setExtension(repeatedLazyMessageExtension, 1, - TestAllTypes.NestedMessage.newBuilder().setBb(527).build()); - - message.setExtension(repeatedNestedEnumExtension , 1, TestAllTypes.NestedEnum.FOO); + message.setExtension(repeatedFloatExtension, 1, 511F); + message.setExtension(repeatedDoubleExtension, 1, 512D); + message.setExtension(repeatedBoolExtension, 1, true); + message.setExtension(repeatedStringExtension, 1, "515"); + message.setExtension(repeatedBytesExtension, 1, toBytes("516")); + + message.setExtension( + repeatedGroupExtension, 1, RepeatedGroup_extension.newBuilder().setA(517).build()); + message.setExtension( + repeatedNestedMessageExtension, + 1, + TestAllTypes.NestedMessage.newBuilder().setBb(518).build()); + message.setExtension( + repeatedForeignMessageExtension, 1, ForeignMessage.newBuilder().setC(519).build()); + message.setExtension( + repeatedImportMessageExtension, 1, ImportMessage.newBuilder().setD(520).build()); + message.setExtension( + repeatedLazyMessageExtension, + 1, + TestAllTypes.NestedMessage.newBuilder().setBb(527).build()); + + message.setExtension(repeatedNestedEnumExtension, 1, TestAllTypes.NestedEnum.FOO); message.setExtension(repeatedForeignEnumExtension, 1, ForeignEnum.FOREIGN_FOO); - message.setExtension(repeatedImportEnumExtension , 1, ImportEnum.IMPORT_FOO); + message.setExtension(repeatedImportEnumExtension, 1, ImportEnum.IMPORT_FOO); message.setExtension(repeatedStringPieceExtension, 1, "524"); message.setExtension(repeatedCordExtension, 1, "525"); @@ -1400,218 +1400,215 @@ public static void modifyRepeatedExtensions( // ------------------------------------------------------------------- /** - * Assert (using {@code junit.framework.Assert}} that all extensions of - * {@code message} are set to the values assigned by {@code setAllExtensions}. + * Assert (using {@code junit.framework.Assert}} that all extensions of {@code message} are set to + * the values assigned by {@code setAllExtensions}. */ - public static void assertAllExtensionsSet( - TestAllExtensionsOrBuilder message) { - Assert.assertTrue(message.hasExtension(optionalInt32Extension )); - Assert.assertTrue(message.hasExtension(optionalInt64Extension )); - Assert.assertTrue(message.hasExtension(optionalUint32Extension )); - Assert.assertTrue(message.hasExtension(optionalUint64Extension )); - Assert.assertTrue(message.hasExtension(optionalSint32Extension )); - Assert.assertTrue(message.hasExtension(optionalSint64Extension )); - Assert.assertTrue(message.hasExtension(optionalFixed32Extension )); - Assert.assertTrue(message.hasExtension(optionalFixed64Extension )); + public static void assertAllExtensionsSet(TestAllExtensionsOrBuilder message) { + Assert.assertTrue(message.hasExtension(optionalInt32Extension)); + Assert.assertTrue(message.hasExtension(optionalInt64Extension)); + Assert.assertTrue(message.hasExtension(optionalUint32Extension)); + Assert.assertTrue(message.hasExtension(optionalUint64Extension)); + Assert.assertTrue(message.hasExtension(optionalSint32Extension)); + Assert.assertTrue(message.hasExtension(optionalSint64Extension)); + Assert.assertTrue(message.hasExtension(optionalFixed32Extension)); + Assert.assertTrue(message.hasExtension(optionalFixed64Extension)); Assert.assertTrue(message.hasExtension(optionalSfixed32Extension)); Assert.assertTrue(message.hasExtension(optionalSfixed64Extension)); - Assert.assertTrue(message.hasExtension(optionalFloatExtension )); - Assert.assertTrue(message.hasExtension(optionalDoubleExtension )); - Assert.assertTrue(message.hasExtension(optionalBoolExtension )); - Assert.assertTrue(message.hasExtension(optionalStringExtension )); - Assert.assertTrue(message.hasExtension(optionalBytesExtension )); - - Assert.assertTrue(message.hasExtension(optionalGroupExtension )); - Assert.assertTrue(message.hasExtension(optionalNestedMessageExtension )); + Assert.assertTrue(message.hasExtension(optionalFloatExtension)); + Assert.assertTrue(message.hasExtension(optionalDoubleExtension)); + Assert.assertTrue(message.hasExtension(optionalBoolExtension)); + Assert.assertTrue(message.hasExtension(optionalStringExtension)); + Assert.assertTrue(message.hasExtension(optionalBytesExtension)); + + Assert.assertTrue(message.hasExtension(optionalGroupExtension)); + Assert.assertTrue(message.hasExtension(optionalNestedMessageExtension)); Assert.assertTrue(message.hasExtension(optionalForeignMessageExtension)); - Assert.assertTrue(message.hasExtension(optionalImportMessageExtension )); + Assert.assertTrue(message.hasExtension(optionalImportMessageExtension)); - Assert.assertTrue(message.getExtension(optionalGroupExtension ).hasA()); - Assert.assertTrue(message.getExtension(optionalNestedMessageExtension ).hasBb()); + Assert.assertTrue(message.getExtension(optionalGroupExtension).hasA()); + Assert.assertTrue(message.getExtension(optionalNestedMessageExtension).hasBb()); Assert.assertTrue(message.getExtension(optionalForeignMessageExtension).hasC()); - Assert.assertTrue(message.getExtension(optionalImportMessageExtension ).hasD()); + Assert.assertTrue(message.getExtension(optionalImportMessageExtension).hasD()); - Assert.assertTrue(message.hasExtension(optionalNestedEnumExtension )); + Assert.assertTrue(message.hasExtension(optionalNestedEnumExtension)); Assert.assertTrue(message.hasExtension(optionalForeignEnumExtension)); - Assert.assertTrue(message.hasExtension(optionalImportEnumExtension )); + Assert.assertTrue(message.hasExtension(optionalImportEnumExtension)); Assert.assertTrue(message.hasExtension(optionalStringPieceExtension)); Assert.assertTrue(message.hasExtension(optionalCordExtension)); - assertEqualsExactType(101 , message.getExtension(optionalInt32Extension )); - assertEqualsExactType(102L , message.getExtension(optionalInt64Extension )); - assertEqualsExactType(103 , message.getExtension(optionalUint32Extension )); - assertEqualsExactType(104L , message.getExtension(optionalUint64Extension )); - assertEqualsExactType(105 , message.getExtension(optionalSint32Extension )); - assertEqualsExactType(106L , message.getExtension(optionalSint64Extension )); - assertEqualsExactType(107 , message.getExtension(optionalFixed32Extension )); - assertEqualsExactType(108L , message.getExtension(optionalFixed64Extension )); - assertEqualsExactType(109 , message.getExtension(optionalSfixed32Extension)); - assertEqualsExactType(110L , message.getExtension(optionalSfixed64Extension)); - assertEqualsExactType(111F , message.getExtension(optionalFloatExtension )); - assertEqualsExactType(112D , message.getExtension(optionalDoubleExtension )); - assertEqualsExactType(true , message.getExtension(optionalBoolExtension )); - assertEqualsExactType("115", message.getExtension(optionalStringExtension )); + assertEqualsExactType(101, message.getExtension(optionalInt32Extension)); + assertEqualsExactType(102L, message.getExtension(optionalInt64Extension)); + assertEqualsExactType(103, message.getExtension(optionalUint32Extension)); + assertEqualsExactType(104L, message.getExtension(optionalUint64Extension)); + assertEqualsExactType(105, message.getExtension(optionalSint32Extension)); + assertEqualsExactType(106L, message.getExtension(optionalSint64Extension)); + assertEqualsExactType(107, message.getExtension(optionalFixed32Extension)); + assertEqualsExactType(108L, message.getExtension(optionalFixed64Extension)); + assertEqualsExactType(109, message.getExtension(optionalSfixed32Extension)); + assertEqualsExactType(110L, message.getExtension(optionalSfixed64Extension)); + assertEqualsExactType(111F, message.getExtension(optionalFloatExtension)); + assertEqualsExactType(112D, message.getExtension(optionalDoubleExtension)); + assertEqualsExactType(true, message.getExtension(optionalBoolExtension)); + assertEqualsExactType("115", message.getExtension(optionalStringExtension)); assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtension)); - assertEqualsExactType(117, message.getExtension(optionalGroupExtension ).getA()); - assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtension ).getBb()); - assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtension ).getC()); - assertEqualsExactType(120, message.getExtension(optionalImportMessageExtension ).getD()); + assertEqualsExactType(117, message.getExtension(optionalGroupExtension).getA()); + assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtension).getBb()); + assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtension).getC()); + assertEqualsExactType(120, message.getExtension(optionalImportMessageExtension).getD()); assertEqualsExactType(126, message.getExtension(optionalPublicImportMessageExtension).getE()); - assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtension ).getBb()); + assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtension).getBb()); - assertEqualsExactType(TestAllTypes.NestedEnum.BAZ, - message.getExtension(optionalNestedEnumExtension)); - assertEqualsExactType(ForeignEnum.FOREIGN_BAZ, - message.getExtension(optionalForeignEnumExtension)); - assertEqualsExactType(ImportEnum.IMPORT_BAZ, - message.getExtension(optionalImportEnumExtension)); + assertEqualsExactType( + TestAllTypes.NestedEnum.BAZ, message.getExtension(optionalNestedEnumExtension)); + assertEqualsExactType( + ForeignEnum.FOREIGN_BAZ, message.getExtension(optionalForeignEnumExtension)); + assertEqualsExactType(ImportEnum.IMPORT_BAZ, message.getExtension(optionalImportEnumExtension)); assertEqualsExactType("124", message.getExtension(optionalStringPieceExtension)); assertEqualsExactType("125", message.getExtension(optionalCordExtension)); // ----------------------------------------------------------------- - Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension )); + Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension)); Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32Extension)); Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64Extension)); - Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension )); - - Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension )); + Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension)); + + Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension)); Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension)); - Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension )); + Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension)); Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtension)); Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtension)); - assertEqualsExactType(201 , message.getExtension(repeatedInt32Extension , 0)); - assertEqualsExactType(202L , message.getExtension(repeatedInt64Extension , 0)); - assertEqualsExactType(203 , message.getExtension(repeatedUint32Extension , 0)); - assertEqualsExactType(204L , message.getExtension(repeatedUint64Extension , 0)); - assertEqualsExactType(205 , message.getExtension(repeatedSint32Extension , 0)); - assertEqualsExactType(206L , message.getExtension(repeatedSint64Extension , 0)); - assertEqualsExactType(207 , message.getExtension(repeatedFixed32Extension , 0)); - assertEqualsExactType(208L , message.getExtension(repeatedFixed64Extension , 0)); - assertEqualsExactType(209 , message.getExtension(repeatedSfixed32Extension, 0)); - assertEqualsExactType(210L , message.getExtension(repeatedSfixed64Extension, 0)); - assertEqualsExactType(211F , message.getExtension(repeatedFloatExtension , 0)); - assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtension , 0)); - assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 0)); - assertEqualsExactType("215", message.getExtension(repeatedStringExtension , 0)); + assertEqualsExactType(201, message.getExtension(repeatedInt32Extension, 0)); + assertEqualsExactType(202L, message.getExtension(repeatedInt64Extension, 0)); + assertEqualsExactType(203, message.getExtension(repeatedUint32Extension, 0)); + assertEqualsExactType(204L, message.getExtension(repeatedUint64Extension, 0)); + assertEqualsExactType(205, message.getExtension(repeatedSint32Extension, 0)); + assertEqualsExactType(206L, message.getExtension(repeatedSint64Extension, 0)); + assertEqualsExactType(207, message.getExtension(repeatedFixed32Extension, 0)); + assertEqualsExactType(208L, message.getExtension(repeatedFixed64Extension, 0)); + assertEqualsExactType(209, message.getExtension(repeatedSfixed32Extension, 0)); + assertEqualsExactType(210L, message.getExtension(repeatedSfixed64Extension, 0)); + assertEqualsExactType(211F, message.getExtension(repeatedFloatExtension, 0)); + assertEqualsExactType(212D, message.getExtension(repeatedDoubleExtension, 0)); + assertEqualsExactType(true, message.getExtension(repeatedBoolExtension, 0)); + assertEqualsExactType("215", message.getExtension(repeatedStringExtension, 0)); assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtension, 0)); - assertEqualsExactType(217, message.getExtension(repeatedGroupExtension , 0).getA()); - assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb()); + assertEqualsExactType(217, message.getExtension(repeatedGroupExtension, 0).getA()); + assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension, 0).getBb()); assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC()); - assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD()); - assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension , 0).getBb()); + assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension, 0).getD()); + assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension, 0).getBb()); - assertEqualsExactType(TestAllTypes.NestedEnum.BAR, - message.getExtension(repeatedNestedEnumExtension, 0)); - assertEqualsExactType(ForeignEnum.FOREIGN_BAR, - message.getExtension(repeatedForeignEnumExtension, 0)); - assertEqualsExactType(ImportEnum.IMPORT_BAR, - message.getExtension(repeatedImportEnumExtension, 0)); + assertEqualsExactType( + TestAllTypes.NestedEnum.BAR, message.getExtension(repeatedNestedEnumExtension, 0)); + assertEqualsExactType( + ForeignEnum.FOREIGN_BAR, message.getExtension(repeatedForeignEnumExtension, 0)); + assertEqualsExactType( + ImportEnum.IMPORT_BAR, message.getExtension(repeatedImportEnumExtension, 0)); assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtension, 0)); assertEqualsExactType("225", message.getExtension(repeatedCordExtension, 0)); - assertEqualsExactType(301 , message.getExtension(repeatedInt32Extension , 1)); - assertEqualsExactType(302L , message.getExtension(repeatedInt64Extension , 1)); - assertEqualsExactType(303 , message.getExtension(repeatedUint32Extension , 1)); - assertEqualsExactType(304L , message.getExtension(repeatedUint64Extension , 1)); - assertEqualsExactType(305 , message.getExtension(repeatedSint32Extension , 1)); - assertEqualsExactType(306L , message.getExtension(repeatedSint64Extension , 1)); - assertEqualsExactType(307 , message.getExtension(repeatedFixed32Extension , 1)); - assertEqualsExactType(308L , message.getExtension(repeatedFixed64Extension , 1)); - assertEqualsExactType(309 , message.getExtension(repeatedSfixed32Extension, 1)); - assertEqualsExactType(310L , message.getExtension(repeatedSfixed64Extension, 1)); - assertEqualsExactType(311F , message.getExtension(repeatedFloatExtension , 1)); - assertEqualsExactType(312D , message.getExtension(repeatedDoubleExtension , 1)); - assertEqualsExactType(false, message.getExtension(repeatedBoolExtension , 1)); - assertEqualsExactType("315", message.getExtension(repeatedStringExtension , 1)); + assertEqualsExactType(301, message.getExtension(repeatedInt32Extension, 1)); + assertEqualsExactType(302L, message.getExtension(repeatedInt64Extension, 1)); + assertEqualsExactType(303, message.getExtension(repeatedUint32Extension, 1)); + assertEqualsExactType(304L, message.getExtension(repeatedUint64Extension, 1)); + assertEqualsExactType(305, message.getExtension(repeatedSint32Extension, 1)); + assertEqualsExactType(306L, message.getExtension(repeatedSint64Extension, 1)); + assertEqualsExactType(307, message.getExtension(repeatedFixed32Extension, 1)); + assertEqualsExactType(308L, message.getExtension(repeatedFixed64Extension, 1)); + assertEqualsExactType(309, message.getExtension(repeatedSfixed32Extension, 1)); + assertEqualsExactType(310L, message.getExtension(repeatedSfixed64Extension, 1)); + assertEqualsExactType(311F, message.getExtension(repeatedFloatExtension, 1)); + assertEqualsExactType(312D, message.getExtension(repeatedDoubleExtension, 1)); + assertEqualsExactType(false, message.getExtension(repeatedBoolExtension, 1)); + assertEqualsExactType("315", message.getExtension(repeatedStringExtension, 1)); assertEqualsExactType(toBytes("316"), message.getExtension(repeatedBytesExtension, 1)); - assertEqualsExactType(317, message.getExtension(repeatedGroupExtension , 1).getA()); - assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtension , 1).getBb()); + assertEqualsExactType(317, message.getExtension(repeatedGroupExtension, 1).getA()); + assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtension, 1).getBb()); assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtension, 1).getC()); - assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtension , 1).getD()); - assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtension , 1).getBb()); + assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtension, 1).getD()); + assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtension, 1).getBb()); - assertEqualsExactType(TestAllTypes.NestedEnum.BAZ, - message.getExtension(repeatedNestedEnumExtension, 1)); - assertEqualsExactType(ForeignEnum.FOREIGN_BAZ, - message.getExtension(repeatedForeignEnumExtension, 1)); - assertEqualsExactType(ImportEnum.IMPORT_BAZ, - message.getExtension(repeatedImportEnumExtension, 1)); + assertEqualsExactType( + TestAllTypes.NestedEnum.BAZ, message.getExtension(repeatedNestedEnumExtension, 1)); + assertEqualsExactType( + ForeignEnum.FOREIGN_BAZ, message.getExtension(repeatedForeignEnumExtension, 1)); + assertEqualsExactType( + ImportEnum.IMPORT_BAZ, message.getExtension(repeatedImportEnumExtension, 1)); assertEqualsExactType("324", message.getExtension(repeatedStringPieceExtension, 1)); assertEqualsExactType("325", message.getExtension(repeatedCordExtension, 1)); // ----------------------------------------------------------------- - Assert.assertTrue(message.hasExtension(defaultInt32Extension )); - Assert.assertTrue(message.hasExtension(defaultInt64Extension )); - Assert.assertTrue(message.hasExtension(defaultUint32Extension )); - Assert.assertTrue(message.hasExtension(defaultUint64Extension )); - Assert.assertTrue(message.hasExtension(defaultSint32Extension )); - Assert.assertTrue(message.hasExtension(defaultSint64Extension )); - Assert.assertTrue(message.hasExtension(defaultFixed32Extension )); - Assert.assertTrue(message.hasExtension(defaultFixed64Extension )); + Assert.assertTrue(message.hasExtension(defaultInt32Extension)); + Assert.assertTrue(message.hasExtension(defaultInt64Extension)); + Assert.assertTrue(message.hasExtension(defaultUint32Extension)); + Assert.assertTrue(message.hasExtension(defaultUint64Extension)); + Assert.assertTrue(message.hasExtension(defaultSint32Extension)); + Assert.assertTrue(message.hasExtension(defaultSint64Extension)); + Assert.assertTrue(message.hasExtension(defaultFixed32Extension)); + Assert.assertTrue(message.hasExtension(defaultFixed64Extension)); Assert.assertTrue(message.hasExtension(defaultSfixed32Extension)); Assert.assertTrue(message.hasExtension(defaultSfixed64Extension)); - Assert.assertTrue(message.hasExtension(defaultFloatExtension )); - Assert.assertTrue(message.hasExtension(defaultDoubleExtension )); - Assert.assertTrue(message.hasExtension(defaultBoolExtension )); - Assert.assertTrue(message.hasExtension(defaultStringExtension )); - Assert.assertTrue(message.hasExtension(defaultBytesExtension )); + Assert.assertTrue(message.hasExtension(defaultFloatExtension)); + Assert.assertTrue(message.hasExtension(defaultDoubleExtension)); + Assert.assertTrue(message.hasExtension(defaultBoolExtension)); + Assert.assertTrue(message.hasExtension(defaultStringExtension)); + Assert.assertTrue(message.hasExtension(defaultBytesExtension)); - Assert.assertTrue(message.hasExtension(defaultNestedEnumExtension )); + Assert.assertTrue(message.hasExtension(defaultNestedEnumExtension)); Assert.assertTrue(message.hasExtension(defaultForeignEnumExtension)); - Assert.assertTrue(message.hasExtension(defaultImportEnumExtension )); + Assert.assertTrue(message.hasExtension(defaultImportEnumExtension)); Assert.assertTrue(message.hasExtension(defaultStringPieceExtension)); Assert.assertTrue(message.hasExtension(defaultCordExtension)); - assertEqualsExactType(401 , message.getExtension(defaultInt32Extension )); - assertEqualsExactType(402L , message.getExtension(defaultInt64Extension )); - assertEqualsExactType(403 , message.getExtension(defaultUint32Extension )); - assertEqualsExactType(404L , message.getExtension(defaultUint64Extension )); - assertEqualsExactType(405 , message.getExtension(defaultSint32Extension )); - assertEqualsExactType(406L , message.getExtension(defaultSint64Extension )); - assertEqualsExactType(407 , message.getExtension(defaultFixed32Extension )); - assertEqualsExactType(408L , message.getExtension(defaultFixed64Extension )); - assertEqualsExactType(409 , message.getExtension(defaultSfixed32Extension)); - assertEqualsExactType(410L , message.getExtension(defaultSfixed64Extension)); - assertEqualsExactType(411F , message.getExtension(defaultFloatExtension )); - assertEqualsExactType(412D , message.getExtension(defaultDoubleExtension )); - assertEqualsExactType(false, message.getExtension(defaultBoolExtension )); - assertEqualsExactType("415", message.getExtension(defaultStringExtension )); + assertEqualsExactType(401, message.getExtension(defaultInt32Extension)); + assertEqualsExactType(402L, message.getExtension(defaultInt64Extension)); + assertEqualsExactType(403, message.getExtension(defaultUint32Extension)); + assertEqualsExactType(404L, message.getExtension(defaultUint64Extension)); + assertEqualsExactType(405, message.getExtension(defaultSint32Extension)); + assertEqualsExactType(406L, message.getExtension(defaultSint64Extension)); + assertEqualsExactType(407, message.getExtension(defaultFixed32Extension)); + assertEqualsExactType(408L, message.getExtension(defaultFixed64Extension)); + assertEqualsExactType(409, message.getExtension(defaultSfixed32Extension)); + assertEqualsExactType(410L, message.getExtension(defaultSfixed64Extension)); + assertEqualsExactType(411F, message.getExtension(defaultFloatExtension)); + assertEqualsExactType(412D, message.getExtension(defaultDoubleExtension)); + assertEqualsExactType(false, message.getExtension(defaultBoolExtension)); + assertEqualsExactType("415", message.getExtension(defaultStringExtension)); assertEqualsExactType(toBytes("416"), message.getExtension(defaultBytesExtension)); - assertEqualsExactType(TestAllTypes.NestedEnum.FOO, - message.getExtension(defaultNestedEnumExtension )); - assertEqualsExactType(ForeignEnum.FOREIGN_FOO, - message.getExtension(defaultForeignEnumExtension)); - assertEqualsExactType(ImportEnum.IMPORT_FOO, - message.getExtension(defaultImportEnumExtension)); + assertEqualsExactType( + TestAllTypes.NestedEnum.FOO, message.getExtension(defaultNestedEnumExtension)); + assertEqualsExactType( + ForeignEnum.FOREIGN_FOO, message.getExtension(defaultForeignEnumExtension)); + assertEqualsExactType(ImportEnum.IMPORT_FOO, message.getExtension(defaultImportEnumExtension)); assertEqualsExactType("424", message.getExtension(defaultStringPieceExtension)); assertEqualsExactType("425", message.getExtension(defaultCordExtension)); @@ -1624,184 +1621,181 @@ public static void assertAllExtensionsSet( // ------------------------------------------------------------------- /** - * Assert (using {@code junit.framework.Assert}} that all extensions of - * {@code message} are cleared, and that getting the extensions returns their - * default values. + * Assert (using {@code junit.framework.Assert}} that all extensions of {@code message} are + * cleared, and that getting the extensions returns their default values. */ public static void assertExtensionsClear(TestAllExtensionsOrBuilder message) { // hasBlah() should initially be false for all optional fields. - Assert.assertFalse(message.hasExtension(optionalInt32Extension )); - Assert.assertFalse(message.hasExtension(optionalInt64Extension )); - Assert.assertFalse(message.hasExtension(optionalUint32Extension )); - Assert.assertFalse(message.hasExtension(optionalUint64Extension )); - Assert.assertFalse(message.hasExtension(optionalSint32Extension )); - Assert.assertFalse(message.hasExtension(optionalSint64Extension )); - Assert.assertFalse(message.hasExtension(optionalFixed32Extension )); - Assert.assertFalse(message.hasExtension(optionalFixed64Extension )); + Assert.assertFalse(message.hasExtension(optionalInt32Extension)); + Assert.assertFalse(message.hasExtension(optionalInt64Extension)); + Assert.assertFalse(message.hasExtension(optionalUint32Extension)); + Assert.assertFalse(message.hasExtension(optionalUint64Extension)); + Assert.assertFalse(message.hasExtension(optionalSint32Extension)); + Assert.assertFalse(message.hasExtension(optionalSint64Extension)); + Assert.assertFalse(message.hasExtension(optionalFixed32Extension)); + Assert.assertFalse(message.hasExtension(optionalFixed64Extension)); Assert.assertFalse(message.hasExtension(optionalSfixed32Extension)); Assert.assertFalse(message.hasExtension(optionalSfixed64Extension)); - Assert.assertFalse(message.hasExtension(optionalFloatExtension )); - Assert.assertFalse(message.hasExtension(optionalDoubleExtension )); - Assert.assertFalse(message.hasExtension(optionalBoolExtension )); - Assert.assertFalse(message.hasExtension(optionalStringExtension )); - Assert.assertFalse(message.hasExtension(optionalBytesExtension )); - - Assert.assertFalse(message.hasExtension(optionalGroupExtension )); - Assert.assertFalse(message.hasExtension(optionalNestedMessageExtension )); + Assert.assertFalse(message.hasExtension(optionalFloatExtension)); + Assert.assertFalse(message.hasExtension(optionalDoubleExtension)); + Assert.assertFalse(message.hasExtension(optionalBoolExtension)); + Assert.assertFalse(message.hasExtension(optionalStringExtension)); + Assert.assertFalse(message.hasExtension(optionalBytesExtension)); + + Assert.assertFalse(message.hasExtension(optionalGroupExtension)); + Assert.assertFalse(message.hasExtension(optionalNestedMessageExtension)); Assert.assertFalse(message.hasExtension(optionalForeignMessageExtension)); - Assert.assertFalse(message.hasExtension(optionalImportMessageExtension )); + Assert.assertFalse(message.hasExtension(optionalImportMessageExtension)); - Assert.assertFalse(message.hasExtension(optionalNestedEnumExtension )); + Assert.assertFalse(message.hasExtension(optionalNestedEnumExtension)); Assert.assertFalse(message.hasExtension(optionalForeignEnumExtension)); - Assert.assertFalse(message.hasExtension(optionalImportEnumExtension )); + Assert.assertFalse(message.hasExtension(optionalImportEnumExtension)); Assert.assertFalse(message.hasExtension(optionalStringPieceExtension)); Assert.assertFalse(message.hasExtension(optionalCordExtension)); // Optional fields without defaults are set to zero or something like it. - assertEqualsExactType(0 , message.getExtension(optionalInt32Extension )); - assertEqualsExactType(0L , message.getExtension(optionalInt64Extension )); - assertEqualsExactType(0 , message.getExtension(optionalUint32Extension )); - assertEqualsExactType(0L , message.getExtension(optionalUint64Extension )); - assertEqualsExactType(0 , message.getExtension(optionalSint32Extension )); - assertEqualsExactType(0L , message.getExtension(optionalSint64Extension )); - assertEqualsExactType(0 , message.getExtension(optionalFixed32Extension )); - assertEqualsExactType(0L , message.getExtension(optionalFixed64Extension )); - assertEqualsExactType(0 , message.getExtension(optionalSfixed32Extension)); - assertEqualsExactType(0L , message.getExtension(optionalSfixed64Extension)); - assertEqualsExactType(0F , message.getExtension(optionalFloatExtension )); - assertEqualsExactType(0D , message.getExtension(optionalDoubleExtension )); - assertEqualsExactType(false, message.getExtension(optionalBoolExtension )); - assertEqualsExactType("" , message.getExtension(optionalStringExtension )); + assertEqualsExactType(0, message.getExtension(optionalInt32Extension)); + assertEqualsExactType(0L, message.getExtension(optionalInt64Extension)); + assertEqualsExactType(0, message.getExtension(optionalUint32Extension)); + assertEqualsExactType(0L, message.getExtension(optionalUint64Extension)); + assertEqualsExactType(0, message.getExtension(optionalSint32Extension)); + assertEqualsExactType(0L, message.getExtension(optionalSint64Extension)); + assertEqualsExactType(0, message.getExtension(optionalFixed32Extension)); + assertEqualsExactType(0L, message.getExtension(optionalFixed64Extension)); + assertEqualsExactType(0, message.getExtension(optionalSfixed32Extension)); + assertEqualsExactType(0L, message.getExtension(optionalSfixed64Extension)); + assertEqualsExactType(0F, message.getExtension(optionalFloatExtension)); + assertEqualsExactType(0D, message.getExtension(optionalDoubleExtension)); + assertEqualsExactType(false, message.getExtension(optionalBoolExtension)); + assertEqualsExactType("", message.getExtension(optionalStringExtension)); assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtension)); // Embedded messages should also be clear. - Assert.assertFalse(message.getExtension(optionalGroupExtension ).hasA()); - Assert.assertFalse(message.getExtension(optionalNestedMessageExtension ).hasBb()); + Assert.assertFalse(message.getExtension(optionalGroupExtension).hasA()); + Assert.assertFalse(message.getExtension(optionalNestedMessageExtension).hasBb()); Assert.assertFalse(message.getExtension(optionalForeignMessageExtension).hasC()); - Assert.assertFalse(message.getExtension(optionalImportMessageExtension ).hasD()); + Assert.assertFalse(message.getExtension(optionalImportMessageExtension).hasD()); - assertEqualsExactType(0, message.getExtension(optionalGroupExtension ).getA()); - assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtension ).getBb()); + assertEqualsExactType(0, message.getExtension(optionalGroupExtension).getA()); + assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtension).getBb()); assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtension).getC()); - assertEqualsExactType(0, message.getExtension(optionalImportMessageExtension ).getD()); + assertEqualsExactType(0, message.getExtension(optionalImportMessageExtension).getD()); // Enums without defaults are set to the first value in the enum. - assertEqualsExactType(TestAllTypes.NestedEnum.FOO, - message.getExtension(optionalNestedEnumExtension )); - assertEqualsExactType(ForeignEnum.FOREIGN_FOO, - message.getExtension(optionalForeignEnumExtension)); - assertEqualsExactType(ImportEnum.IMPORT_FOO, - message.getExtension(optionalImportEnumExtension)); + assertEqualsExactType( + TestAllTypes.NestedEnum.FOO, message.getExtension(optionalNestedEnumExtension)); + assertEqualsExactType( + ForeignEnum.FOREIGN_FOO, message.getExtension(optionalForeignEnumExtension)); + assertEqualsExactType(ImportEnum.IMPORT_FOO, message.getExtension(optionalImportEnumExtension)); assertEqualsExactType("", message.getExtension(optionalStringPieceExtension)); assertEqualsExactType("", message.getExtension(optionalCordExtension)); // Repeated fields are empty. - Assert.assertEquals(0, message.getExtensionCount(repeatedInt32Extension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedInt64Extension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedUint32Extension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedUint64Extension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedSint32Extension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedSint64Extension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32Extension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64Extension )); + Assert.assertEquals(0, message.getExtensionCount(repeatedInt32Extension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedInt64Extension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedUint32Extension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedUint64Extension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedSint32Extension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedSint64Extension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32Extension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64Extension)); Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed32Extension)); Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed64Extension)); - Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtension )); - - Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtension )); + Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtension)); + + Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtension)); Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtension)); - Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtension )); - Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtension )); + Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtension)); + Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtension)); Assert.assertEquals(0, message.getExtensionCount(repeatedStringPieceExtension)); Assert.assertEquals(0, message.getExtensionCount(repeatedCordExtension)); // Repeated fields are empty via getExtension().size(). - Assert.assertEquals(0, message.getExtension(repeatedInt32Extension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedInt64Extension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedUint32Extension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedUint64Extension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedSint32Extension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedSint64Extension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedFixed32Extension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedFixed64Extension ).size()); + Assert.assertEquals(0, message.getExtension(repeatedInt32Extension).size()); + Assert.assertEquals(0, message.getExtension(repeatedInt64Extension).size()); + Assert.assertEquals(0, message.getExtension(repeatedUint32Extension).size()); + Assert.assertEquals(0, message.getExtension(repeatedUint64Extension).size()); + Assert.assertEquals(0, message.getExtension(repeatedSint32Extension).size()); + Assert.assertEquals(0, message.getExtension(repeatedSint64Extension).size()); + Assert.assertEquals(0, message.getExtension(repeatedFixed32Extension).size()); + Assert.assertEquals(0, message.getExtension(repeatedFixed64Extension).size()); Assert.assertEquals(0, message.getExtension(repeatedSfixed32Extension).size()); Assert.assertEquals(0, message.getExtension(repeatedSfixed64Extension).size()); - Assert.assertEquals(0, message.getExtension(repeatedFloatExtension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedDoubleExtension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedBoolExtension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedStringExtension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedBytesExtension ).size()); - - Assert.assertEquals(0, message.getExtension(repeatedGroupExtension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedNestedMessageExtension ).size()); + Assert.assertEquals(0, message.getExtension(repeatedFloatExtension).size()); + Assert.assertEquals(0, message.getExtension(repeatedDoubleExtension).size()); + Assert.assertEquals(0, message.getExtension(repeatedBoolExtension).size()); + Assert.assertEquals(0, message.getExtension(repeatedStringExtension).size()); + Assert.assertEquals(0, message.getExtension(repeatedBytesExtension).size()); + + Assert.assertEquals(0, message.getExtension(repeatedGroupExtension).size()); + Assert.assertEquals(0, message.getExtension(repeatedNestedMessageExtension).size()); Assert.assertEquals(0, message.getExtension(repeatedForeignMessageExtension).size()); - Assert.assertEquals(0, message.getExtension(repeatedImportMessageExtension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedLazyMessageExtension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedNestedEnumExtension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedForeignEnumExtension ).size()); - Assert.assertEquals(0, message.getExtension(repeatedImportEnumExtension ).size()); + Assert.assertEquals(0, message.getExtension(repeatedImportMessageExtension).size()); + Assert.assertEquals(0, message.getExtension(repeatedLazyMessageExtension).size()); + Assert.assertEquals(0, message.getExtension(repeatedNestedEnumExtension).size()); + Assert.assertEquals(0, message.getExtension(repeatedForeignEnumExtension).size()); + Assert.assertEquals(0, message.getExtension(repeatedImportEnumExtension).size()); Assert.assertEquals(0, message.getExtension(repeatedStringPieceExtension).size()); Assert.assertEquals(0, message.getExtension(repeatedCordExtension).size()); // hasBlah() should also be false for all default fields. - Assert.assertFalse(message.hasExtension(defaultInt32Extension )); - Assert.assertFalse(message.hasExtension(defaultInt64Extension )); - Assert.assertFalse(message.hasExtension(defaultUint32Extension )); - Assert.assertFalse(message.hasExtension(defaultUint64Extension )); - Assert.assertFalse(message.hasExtension(defaultSint32Extension )); - Assert.assertFalse(message.hasExtension(defaultSint64Extension )); - Assert.assertFalse(message.hasExtension(defaultFixed32Extension )); - Assert.assertFalse(message.hasExtension(defaultFixed64Extension )); + Assert.assertFalse(message.hasExtension(defaultInt32Extension)); + Assert.assertFalse(message.hasExtension(defaultInt64Extension)); + Assert.assertFalse(message.hasExtension(defaultUint32Extension)); + Assert.assertFalse(message.hasExtension(defaultUint64Extension)); + Assert.assertFalse(message.hasExtension(defaultSint32Extension)); + Assert.assertFalse(message.hasExtension(defaultSint64Extension)); + Assert.assertFalse(message.hasExtension(defaultFixed32Extension)); + Assert.assertFalse(message.hasExtension(defaultFixed64Extension)); Assert.assertFalse(message.hasExtension(defaultSfixed32Extension)); Assert.assertFalse(message.hasExtension(defaultSfixed64Extension)); - Assert.assertFalse(message.hasExtension(defaultFloatExtension )); - Assert.assertFalse(message.hasExtension(defaultDoubleExtension )); - Assert.assertFalse(message.hasExtension(defaultBoolExtension )); - Assert.assertFalse(message.hasExtension(defaultStringExtension )); - Assert.assertFalse(message.hasExtension(defaultBytesExtension )); + Assert.assertFalse(message.hasExtension(defaultFloatExtension)); + Assert.assertFalse(message.hasExtension(defaultDoubleExtension)); + Assert.assertFalse(message.hasExtension(defaultBoolExtension)); + Assert.assertFalse(message.hasExtension(defaultStringExtension)); + Assert.assertFalse(message.hasExtension(defaultBytesExtension)); - Assert.assertFalse(message.hasExtension(defaultNestedEnumExtension )); + Assert.assertFalse(message.hasExtension(defaultNestedEnumExtension)); Assert.assertFalse(message.hasExtension(defaultForeignEnumExtension)); - Assert.assertFalse(message.hasExtension(defaultImportEnumExtension )); + Assert.assertFalse(message.hasExtension(defaultImportEnumExtension)); Assert.assertFalse(message.hasExtension(defaultStringPieceExtension)); Assert.assertFalse(message.hasExtension(defaultCordExtension)); // Fields with defaults have their default values (duh). - assertEqualsExactType( 41 , message.getExtension(defaultInt32Extension )); - assertEqualsExactType( 42L , message.getExtension(defaultInt64Extension )); - assertEqualsExactType( 43 , message.getExtension(defaultUint32Extension )); - assertEqualsExactType( 44L , message.getExtension(defaultUint64Extension )); - assertEqualsExactType(-45 , message.getExtension(defaultSint32Extension )); - assertEqualsExactType( 46L , message.getExtension(defaultSint64Extension )); - assertEqualsExactType( 47 , message.getExtension(defaultFixed32Extension )); - assertEqualsExactType( 48L , message.getExtension(defaultFixed64Extension )); - assertEqualsExactType( 49 , message.getExtension(defaultSfixed32Extension)); - assertEqualsExactType(-50L , message.getExtension(defaultSfixed64Extension)); - assertEqualsExactType( 51.5F , message.getExtension(defaultFloatExtension )); - assertEqualsExactType( 52e3D , message.getExtension(defaultDoubleExtension )); - assertEqualsExactType(true , message.getExtension(defaultBoolExtension )); - assertEqualsExactType("hello", message.getExtension(defaultStringExtension )); + assertEqualsExactType(41, message.getExtension(defaultInt32Extension)); + assertEqualsExactType(42L, message.getExtension(defaultInt64Extension)); + assertEqualsExactType(43, message.getExtension(defaultUint32Extension)); + assertEqualsExactType(44L, message.getExtension(defaultUint64Extension)); + assertEqualsExactType(-45, message.getExtension(defaultSint32Extension)); + assertEqualsExactType(46L, message.getExtension(defaultSint64Extension)); + assertEqualsExactType(47, message.getExtension(defaultFixed32Extension)); + assertEqualsExactType(48L, message.getExtension(defaultFixed64Extension)); + assertEqualsExactType(49, message.getExtension(defaultSfixed32Extension)); + assertEqualsExactType(-50L, message.getExtension(defaultSfixed64Extension)); + assertEqualsExactType(51.5F, message.getExtension(defaultFloatExtension)); + assertEqualsExactType(52e3D, message.getExtension(defaultDoubleExtension)); + assertEqualsExactType(true, message.getExtension(defaultBoolExtension)); + assertEqualsExactType("hello", message.getExtension(defaultStringExtension)); assertEqualsExactType(toBytes("world"), message.getExtension(defaultBytesExtension)); - assertEqualsExactType(TestAllTypes.NestedEnum.BAR, - message.getExtension(defaultNestedEnumExtension )); - assertEqualsExactType(ForeignEnum.FOREIGN_BAR, - message.getExtension(defaultForeignEnumExtension)); - assertEqualsExactType(ImportEnum.IMPORT_BAR, - message.getExtension(defaultImportEnumExtension)); + assertEqualsExactType( + TestAllTypes.NestedEnum.BAR, message.getExtension(defaultNestedEnumExtension)); + assertEqualsExactType( + ForeignEnum.FOREIGN_BAR, message.getExtension(defaultForeignEnumExtension)); + assertEqualsExactType(ImportEnum.IMPORT_BAR, message.getExtension(defaultImportEnumExtension)); assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtension)); assertEqualsExactType("123", message.getExtension(defaultCordExtension)); @@ -1815,405 +1809,402 @@ public static void assertExtensionsClear(TestAllExtensionsOrBuilder message) { // ------------------------------------------------------------------- /** - * Assert (using {@code junit.framework.Assert}} that all extensions of - * {@code message} are set to the values assigned by {@code setAllExtensions} - * followed by {@code modifyRepeatedExtensions}. + * Assert (using {@code junit.framework.Assert}} that all extensions of {@code message} are set to + * the values assigned by {@code setAllExtensions} followed by {@code modifyRepeatedExtensions}. */ - public static void assertRepeatedExtensionsModified( - TestAllExtensionsOrBuilder message) { + public static void assertRepeatedExtensionsModified(TestAllExtensionsOrBuilder message) { // ModifyRepeatedFields only sets the second repeated element of each // field. In addition to verifying this, we also verify that the first // element and size were *not* modified. - Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension )); + Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension)); Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32Extension)); Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64Extension)); - Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension )); - - Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension )); + Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension)); + + Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension)); Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension)); - Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension )); - Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension )); + Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension)); + Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension)); Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtension)); Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtension)); - assertEqualsExactType(201 , message.getExtension(repeatedInt32Extension , 0)); - assertEqualsExactType(202L , message.getExtension(repeatedInt64Extension , 0)); - assertEqualsExactType(203 , message.getExtension(repeatedUint32Extension , 0)); - assertEqualsExactType(204L , message.getExtension(repeatedUint64Extension , 0)); - assertEqualsExactType(205 , message.getExtension(repeatedSint32Extension , 0)); - assertEqualsExactType(206L , message.getExtension(repeatedSint64Extension , 0)); - assertEqualsExactType(207 , message.getExtension(repeatedFixed32Extension , 0)); - assertEqualsExactType(208L , message.getExtension(repeatedFixed64Extension , 0)); - assertEqualsExactType(209 , message.getExtension(repeatedSfixed32Extension, 0)); - assertEqualsExactType(210L , message.getExtension(repeatedSfixed64Extension, 0)); - assertEqualsExactType(211F , message.getExtension(repeatedFloatExtension , 0)); - assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtension , 0)); - assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 0)); - assertEqualsExactType("215", message.getExtension(repeatedStringExtension , 0)); + assertEqualsExactType(201, message.getExtension(repeatedInt32Extension, 0)); + assertEqualsExactType(202L, message.getExtension(repeatedInt64Extension, 0)); + assertEqualsExactType(203, message.getExtension(repeatedUint32Extension, 0)); + assertEqualsExactType(204L, message.getExtension(repeatedUint64Extension, 0)); + assertEqualsExactType(205, message.getExtension(repeatedSint32Extension, 0)); + assertEqualsExactType(206L, message.getExtension(repeatedSint64Extension, 0)); + assertEqualsExactType(207, message.getExtension(repeatedFixed32Extension, 0)); + assertEqualsExactType(208L, message.getExtension(repeatedFixed64Extension, 0)); + assertEqualsExactType(209, message.getExtension(repeatedSfixed32Extension, 0)); + assertEqualsExactType(210L, message.getExtension(repeatedSfixed64Extension, 0)); + assertEqualsExactType(211F, message.getExtension(repeatedFloatExtension, 0)); + assertEqualsExactType(212D, message.getExtension(repeatedDoubleExtension, 0)); + assertEqualsExactType(true, message.getExtension(repeatedBoolExtension, 0)); + assertEqualsExactType("215", message.getExtension(repeatedStringExtension, 0)); assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtension, 0)); - assertEqualsExactType(217, message.getExtension(repeatedGroupExtension , 0).getA()); - assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb()); + assertEqualsExactType(217, message.getExtension(repeatedGroupExtension, 0).getA()); + assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension, 0).getBb()); assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC()); - assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD()); - assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension , 0).getBb()); + assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension, 0).getD()); + assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension, 0).getBb()); - assertEqualsExactType(TestAllTypes.NestedEnum.BAR, - message.getExtension(repeatedNestedEnumExtension, 0)); - assertEqualsExactType(ForeignEnum.FOREIGN_BAR, - message.getExtension(repeatedForeignEnumExtension, 0)); - assertEqualsExactType(ImportEnum.IMPORT_BAR, - message.getExtension(repeatedImportEnumExtension, 0)); + assertEqualsExactType( + TestAllTypes.NestedEnum.BAR, message.getExtension(repeatedNestedEnumExtension, 0)); + assertEqualsExactType( + ForeignEnum.FOREIGN_BAR, message.getExtension(repeatedForeignEnumExtension, 0)); + assertEqualsExactType( + ImportEnum.IMPORT_BAR, message.getExtension(repeatedImportEnumExtension, 0)); assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtension, 0)); assertEqualsExactType("225", message.getExtension(repeatedCordExtension, 0)); // Actually verify the second (modified) elements now. - assertEqualsExactType(501 , message.getExtension(repeatedInt32Extension , 1)); - assertEqualsExactType(502L , message.getExtension(repeatedInt64Extension , 1)); - assertEqualsExactType(503 , message.getExtension(repeatedUint32Extension , 1)); - assertEqualsExactType(504L , message.getExtension(repeatedUint64Extension , 1)); - assertEqualsExactType(505 , message.getExtension(repeatedSint32Extension , 1)); - assertEqualsExactType(506L , message.getExtension(repeatedSint64Extension , 1)); - assertEqualsExactType(507 , message.getExtension(repeatedFixed32Extension , 1)); - assertEqualsExactType(508L , message.getExtension(repeatedFixed64Extension , 1)); - assertEqualsExactType(509 , message.getExtension(repeatedSfixed32Extension, 1)); - assertEqualsExactType(510L , message.getExtension(repeatedSfixed64Extension, 1)); - assertEqualsExactType(511F , message.getExtension(repeatedFloatExtension , 1)); - assertEqualsExactType(512D , message.getExtension(repeatedDoubleExtension , 1)); - assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 1)); - assertEqualsExactType("515", message.getExtension(repeatedStringExtension , 1)); + assertEqualsExactType(501, message.getExtension(repeatedInt32Extension, 1)); + assertEqualsExactType(502L, message.getExtension(repeatedInt64Extension, 1)); + assertEqualsExactType(503, message.getExtension(repeatedUint32Extension, 1)); + assertEqualsExactType(504L, message.getExtension(repeatedUint64Extension, 1)); + assertEqualsExactType(505, message.getExtension(repeatedSint32Extension, 1)); + assertEqualsExactType(506L, message.getExtension(repeatedSint64Extension, 1)); + assertEqualsExactType(507, message.getExtension(repeatedFixed32Extension, 1)); + assertEqualsExactType(508L, message.getExtension(repeatedFixed64Extension, 1)); + assertEqualsExactType(509, message.getExtension(repeatedSfixed32Extension, 1)); + assertEqualsExactType(510L, message.getExtension(repeatedSfixed64Extension, 1)); + assertEqualsExactType(511F, message.getExtension(repeatedFloatExtension, 1)); + assertEqualsExactType(512D, message.getExtension(repeatedDoubleExtension, 1)); + assertEqualsExactType(true, message.getExtension(repeatedBoolExtension, 1)); + assertEqualsExactType("515", message.getExtension(repeatedStringExtension, 1)); assertEqualsExactType(toBytes("516"), message.getExtension(repeatedBytesExtension, 1)); - assertEqualsExactType(517, message.getExtension(repeatedGroupExtension , 1).getA()); - assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtension , 1).getBb()); + assertEqualsExactType(517, message.getExtension(repeatedGroupExtension, 1).getA()); + assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtension, 1).getBb()); assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtension, 1).getC()); - assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtension , 1).getD()); - assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtension , 1).getBb()); + assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtension, 1).getD()); + assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtension, 1).getBb()); - assertEqualsExactType(TestAllTypes.NestedEnum.FOO, - message.getExtension(repeatedNestedEnumExtension, 1)); - assertEqualsExactType(ForeignEnum.FOREIGN_FOO, - message.getExtension(repeatedForeignEnumExtension, 1)); - assertEqualsExactType(ImportEnum.IMPORT_FOO, - message.getExtension(repeatedImportEnumExtension, 1)); + assertEqualsExactType( + TestAllTypes.NestedEnum.FOO, message.getExtension(repeatedNestedEnumExtension, 1)); + assertEqualsExactType( + ForeignEnum.FOREIGN_FOO, message.getExtension(repeatedForeignEnumExtension, 1)); + assertEqualsExactType( + ImportEnum.IMPORT_FOO, message.getExtension(repeatedImportEnumExtension, 1)); assertEqualsExactType("524", message.getExtension(repeatedStringPieceExtension, 1)); assertEqualsExactType("525", message.getExtension(repeatedCordExtension, 1)); } public static void setPackedExtensions(TestPackedExtensions.Builder message) { - message.addExtension(packedInt32Extension , 601); - message.addExtension(packedInt64Extension , 602L); - message.addExtension(packedUint32Extension , 603); - message.addExtension(packedUint64Extension , 604L); - message.addExtension(packedSint32Extension , 605); - message.addExtension(packedSint64Extension , 606L); - message.addExtension(packedFixed32Extension , 607); - message.addExtension(packedFixed64Extension , 608L); + message.addExtension(packedInt32Extension, 601); + message.addExtension(packedInt64Extension, 602L); + message.addExtension(packedUint32Extension, 603); + message.addExtension(packedUint64Extension, 604L); + message.addExtension(packedSint32Extension, 605); + message.addExtension(packedSint64Extension, 606L); + message.addExtension(packedFixed32Extension, 607); + message.addExtension(packedFixed64Extension, 608L); message.addExtension(packedSfixed32Extension, 609); message.addExtension(packedSfixed64Extension, 610L); - message.addExtension(packedFloatExtension , 611F); - message.addExtension(packedDoubleExtension , 612D); - message.addExtension(packedBoolExtension , true); + message.addExtension(packedFloatExtension, 611F); + message.addExtension(packedDoubleExtension, 612D); + message.addExtension(packedBoolExtension, true); message.addExtension(packedEnumExtension, ForeignEnum.FOREIGN_BAR); // Add a second one of each field. - message.addExtension(packedInt32Extension , 701); - message.addExtension(packedInt64Extension , 702L); - message.addExtension(packedUint32Extension , 703); - message.addExtension(packedUint64Extension , 704L); - message.addExtension(packedSint32Extension , 705); - message.addExtension(packedSint64Extension , 706L); - message.addExtension(packedFixed32Extension , 707); - message.addExtension(packedFixed64Extension , 708L); + message.addExtension(packedInt32Extension, 701); + message.addExtension(packedInt64Extension, 702L); + message.addExtension(packedUint32Extension, 703); + message.addExtension(packedUint64Extension, 704L); + message.addExtension(packedSint32Extension, 705); + message.addExtension(packedSint64Extension, 706L); + message.addExtension(packedFixed32Extension, 707); + message.addExtension(packedFixed64Extension, 708L); message.addExtension(packedSfixed32Extension, 709); message.addExtension(packedSfixed64Extension, 710L); - message.addExtension(packedFloatExtension , 711F); - message.addExtension(packedDoubleExtension , 712D); - message.addExtension(packedBoolExtension , false); + message.addExtension(packedFloatExtension, 711F); + message.addExtension(packedDoubleExtension, 712D); + message.addExtension(packedBoolExtension, false); message.addExtension(packedEnumExtension, ForeignEnum.FOREIGN_BAZ); } public static void assertPackedExtensionsSet(TestPackedExtensions message) { - Assert.assertEquals(2, message.getExtensionCount(packedInt32Extension )); - Assert.assertEquals(2, message.getExtensionCount(packedInt64Extension )); - Assert.assertEquals(2, message.getExtensionCount(packedUint32Extension )); - Assert.assertEquals(2, message.getExtensionCount(packedUint64Extension )); - Assert.assertEquals(2, message.getExtensionCount(packedSint32Extension )); - Assert.assertEquals(2, message.getExtensionCount(packedSint64Extension )); - Assert.assertEquals(2, message.getExtensionCount(packedFixed32Extension )); - Assert.assertEquals(2, message.getExtensionCount(packedFixed64Extension )); + Assert.assertEquals(2, message.getExtensionCount(packedInt32Extension)); + Assert.assertEquals(2, message.getExtensionCount(packedInt64Extension)); + Assert.assertEquals(2, message.getExtensionCount(packedUint32Extension)); + Assert.assertEquals(2, message.getExtensionCount(packedUint64Extension)); + Assert.assertEquals(2, message.getExtensionCount(packedSint32Extension)); + Assert.assertEquals(2, message.getExtensionCount(packedSint64Extension)); + Assert.assertEquals(2, message.getExtensionCount(packedFixed32Extension)); + Assert.assertEquals(2, message.getExtensionCount(packedFixed64Extension)); Assert.assertEquals(2, message.getExtensionCount(packedSfixed32Extension)); Assert.assertEquals(2, message.getExtensionCount(packedSfixed64Extension)); - Assert.assertEquals(2, message.getExtensionCount(packedFloatExtension )); - Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtension )); - Assert.assertEquals(2, message.getExtensionCount(packedBoolExtension )); + Assert.assertEquals(2, message.getExtensionCount(packedFloatExtension)); + Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtension)); + Assert.assertEquals(2, message.getExtensionCount(packedBoolExtension)); Assert.assertEquals(2, message.getExtensionCount(packedEnumExtension)); - assertEqualsExactType(601 , message.getExtension(packedInt32Extension , 0)); - assertEqualsExactType(602L , message.getExtension(packedInt64Extension , 0)); - assertEqualsExactType(603 , message.getExtension(packedUint32Extension , 0)); - assertEqualsExactType(604L , message.getExtension(packedUint64Extension , 0)); - assertEqualsExactType(605 , message.getExtension(packedSint32Extension , 0)); - assertEqualsExactType(606L , message.getExtension(packedSint64Extension , 0)); - assertEqualsExactType(607 , message.getExtension(packedFixed32Extension , 0)); - assertEqualsExactType(608L , message.getExtension(packedFixed64Extension , 0)); - assertEqualsExactType(609 , message.getExtension(packedSfixed32Extension, 0)); - assertEqualsExactType(610L , message.getExtension(packedSfixed64Extension, 0)); - assertEqualsExactType(611F , message.getExtension(packedFloatExtension , 0)); - assertEqualsExactType(612D , message.getExtension(packedDoubleExtension , 0)); - assertEqualsExactType(true , message.getExtension(packedBoolExtension , 0)); - assertEqualsExactType(ForeignEnum.FOREIGN_BAR, - message.getExtension(packedEnumExtension, 0)); - assertEqualsExactType(701 , message.getExtension(packedInt32Extension , 1)); - assertEqualsExactType(702L , message.getExtension(packedInt64Extension , 1)); - assertEqualsExactType(703 , message.getExtension(packedUint32Extension , 1)); - assertEqualsExactType(704L , message.getExtension(packedUint64Extension , 1)); - assertEqualsExactType(705 , message.getExtension(packedSint32Extension , 1)); - assertEqualsExactType(706L , message.getExtension(packedSint64Extension , 1)); - assertEqualsExactType(707 , message.getExtension(packedFixed32Extension , 1)); - assertEqualsExactType(708L , message.getExtension(packedFixed64Extension , 1)); - assertEqualsExactType(709 , message.getExtension(packedSfixed32Extension, 1)); - assertEqualsExactType(710L , message.getExtension(packedSfixed64Extension, 1)); - assertEqualsExactType(711F , message.getExtension(packedFloatExtension , 1)); - assertEqualsExactType(712D , message.getExtension(packedDoubleExtension , 1)); - assertEqualsExactType(false, message.getExtension(packedBoolExtension , 1)); - assertEqualsExactType(ForeignEnum.FOREIGN_BAZ, - message.getExtension(packedEnumExtension, 1)); + assertEqualsExactType(601, message.getExtension(packedInt32Extension, 0)); + assertEqualsExactType(602L, message.getExtension(packedInt64Extension, 0)); + assertEqualsExactType(603, message.getExtension(packedUint32Extension, 0)); + assertEqualsExactType(604L, message.getExtension(packedUint64Extension, 0)); + assertEqualsExactType(605, message.getExtension(packedSint32Extension, 0)); + assertEqualsExactType(606L, message.getExtension(packedSint64Extension, 0)); + assertEqualsExactType(607, message.getExtension(packedFixed32Extension, 0)); + assertEqualsExactType(608L, message.getExtension(packedFixed64Extension, 0)); + assertEqualsExactType(609, message.getExtension(packedSfixed32Extension, 0)); + assertEqualsExactType(610L, message.getExtension(packedSfixed64Extension, 0)); + assertEqualsExactType(611F, message.getExtension(packedFloatExtension, 0)); + assertEqualsExactType(612D, message.getExtension(packedDoubleExtension, 0)); + assertEqualsExactType(true, message.getExtension(packedBoolExtension, 0)); + assertEqualsExactType(ForeignEnum.FOREIGN_BAR, message.getExtension(packedEnumExtension, 0)); + assertEqualsExactType(701, message.getExtension(packedInt32Extension, 1)); + assertEqualsExactType(702L, message.getExtension(packedInt64Extension, 1)); + assertEqualsExactType(703, message.getExtension(packedUint32Extension, 1)); + assertEqualsExactType(704L, message.getExtension(packedUint64Extension, 1)); + assertEqualsExactType(705, message.getExtension(packedSint32Extension, 1)); + assertEqualsExactType(706L, message.getExtension(packedSint64Extension, 1)); + assertEqualsExactType(707, message.getExtension(packedFixed32Extension, 1)); + assertEqualsExactType(708L, message.getExtension(packedFixed64Extension, 1)); + assertEqualsExactType(709, message.getExtension(packedSfixed32Extension, 1)); + assertEqualsExactType(710L, message.getExtension(packedSfixed64Extension, 1)); + assertEqualsExactType(711F, message.getExtension(packedFloatExtension, 1)); + assertEqualsExactType(712D, message.getExtension(packedDoubleExtension, 1)); + assertEqualsExactType(false, message.getExtension(packedBoolExtension, 1)); + assertEqualsExactType(ForeignEnum.FOREIGN_BAZ, message.getExtension(packedEnumExtension, 1)); } // =================================================================== // Lite extensions /** - * Assert (using {@code junit.framework.Assert}} that all extensions of - * {@code message} are set to the values assigned by {@code setAllExtensions}. + * Assert (using {@code junit.framework.Assert}} that all extensions of {@code message} are set to + * the values assigned by {@code setAllExtensions}. */ - public static void assertAllExtensionsSet( - TestAllExtensionsLiteOrBuilder message) { - Assert.assertTrue(message.hasExtension(optionalInt32ExtensionLite )); - Assert.assertTrue(message.hasExtension(optionalInt64ExtensionLite )); - Assert.assertTrue(message.hasExtension(optionalUint32ExtensionLite )); - Assert.assertTrue(message.hasExtension(optionalUint64ExtensionLite )); - Assert.assertTrue(message.hasExtension(optionalSint32ExtensionLite )); - Assert.assertTrue(message.hasExtension(optionalSint64ExtensionLite )); - Assert.assertTrue(message.hasExtension(optionalFixed32ExtensionLite )); - Assert.assertTrue(message.hasExtension(optionalFixed64ExtensionLite )); + public static void assertAllExtensionsSet(TestAllExtensionsLiteOrBuilder message) { + Assert.assertTrue(message.hasExtension(optionalInt32ExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalInt64ExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalUint32ExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalUint64ExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalSint32ExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalSint64ExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalFixed32ExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalFixed64ExtensionLite)); Assert.assertTrue(message.hasExtension(optionalSfixed32ExtensionLite)); Assert.assertTrue(message.hasExtension(optionalSfixed64ExtensionLite)); - Assert.assertTrue(message.hasExtension(optionalFloatExtensionLite )); - Assert.assertTrue(message.hasExtension(optionalDoubleExtensionLite )); - Assert.assertTrue(message.hasExtension(optionalBoolExtensionLite )); - Assert.assertTrue(message.hasExtension(optionalStringExtensionLite )); - Assert.assertTrue(message.hasExtension(optionalBytesExtensionLite )); - - Assert.assertTrue(message.hasExtension(optionalGroupExtensionLite )); - Assert.assertTrue(message.hasExtension(optionalNestedMessageExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalFloatExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalDoubleExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalBoolExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalStringExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalBytesExtensionLite)); + + Assert.assertTrue(message.hasExtension(optionalGroupExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalNestedMessageExtensionLite)); Assert.assertTrue(message.hasExtension(optionalForeignMessageExtensionLite)); - Assert.assertTrue(message.hasExtension(optionalImportMessageExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalImportMessageExtensionLite)); - Assert.assertTrue(message.getExtension(optionalGroupExtensionLite ).hasA()); - Assert.assertTrue(message.getExtension(optionalNestedMessageExtensionLite ).hasBb()); + Assert.assertTrue(message.getExtension(optionalGroupExtensionLite).hasA()); + Assert.assertTrue(message.getExtension(optionalNestedMessageExtensionLite).hasBb()); Assert.assertTrue(message.getExtension(optionalForeignMessageExtensionLite).hasC()); - Assert.assertTrue(message.getExtension(optionalImportMessageExtensionLite ).hasD()); + Assert.assertTrue(message.getExtension(optionalImportMessageExtensionLite).hasD()); - Assert.assertTrue(message.hasExtension(optionalNestedEnumExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalNestedEnumExtensionLite)); Assert.assertTrue(message.hasExtension(optionalForeignEnumExtensionLite)); - Assert.assertTrue(message.hasExtension(optionalImportEnumExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalImportEnumExtensionLite)); Assert.assertTrue(message.hasExtension(optionalStringPieceExtensionLite)); Assert.assertTrue(message.hasExtension(optionalCordExtensionLite)); - assertEqualsExactType(101 , message.getExtension(optionalInt32ExtensionLite )); - assertEqualsExactType(102L , message.getExtension(optionalInt64ExtensionLite )); - assertEqualsExactType(103 , message.getExtension(optionalUint32ExtensionLite )); - assertEqualsExactType(104L , message.getExtension(optionalUint64ExtensionLite )); - assertEqualsExactType(105 , message.getExtension(optionalSint32ExtensionLite )); - assertEqualsExactType(106L , message.getExtension(optionalSint64ExtensionLite )); - assertEqualsExactType(107 , message.getExtension(optionalFixed32ExtensionLite )); - assertEqualsExactType(108L , message.getExtension(optionalFixed64ExtensionLite )); - assertEqualsExactType(109 , message.getExtension(optionalSfixed32ExtensionLite)); - assertEqualsExactType(110L , message.getExtension(optionalSfixed64ExtensionLite)); - assertEqualsExactType(111F , message.getExtension(optionalFloatExtensionLite )); - assertEqualsExactType(112D , message.getExtension(optionalDoubleExtensionLite )); - assertEqualsExactType(true , message.getExtension(optionalBoolExtensionLite )); - assertEqualsExactType("115", message.getExtension(optionalStringExtensionLite )); + assertEqualsExactType(101, message.getExtension(optionalInt32ExtensionLite)); + assertEqualsExactType(102L, message.getExtension(optionalInt64ExtensionLite)); + assertEqualsExactType(103, message.getExtension(optionalUint32ExtensionLite)); + assertEqualsExactType(104L, message.getExtension(optionalUint64ExtensionLite)); + assertEqualsExactType(105, message.getExtension(optionalSint32ExtensionLite)); + assertEqualsExactType(106L, message.getExtension(optionalSint64ExtensionLite)); + assertEqualsExactType(107, message.getExtension(optionalFixed32ExtensionLite)); + assertEqualsExactType(108L, message.getExtension(optionalFixed64ExtensionLite)); + assertEqualsExactType(109, message.getExtension(optionalSfixed32ExtensionLite)); + assertEqualsExactType(110L, message.getExtension(optionalSfixed64ExtensionLite)); + assertEqualsExactType(111F, message.getExtension(optionalFloatExtensionLite)); + assertEqualsExactType(112D, message.getExtension(optionalDoubleExtensionLite)); + assertEqualsExactType(true, message.getExtension(optionalBoolExtensionLite)); + assertEqualsExactType("115", message.getExtension(optionalStringExtensionLite)); assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtensionLite)); - assertEqualsExactType(117, message.getExtension(optionalGroupExtensionLite ).getA()); - assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtensionLite ).getBb()); + assertEqualsExactType(117, message.getExtension(optionalGroupExtensionLite).getA()); + assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtensionLite).getBb()); assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtensionLite).getC()); - assertEqualsExactType(120, message.getExtension(optionalImportMessageExtensionLite ).getD()); - assertEqualsExactType(126, message.getExtension( - optionalPublicImportMessageExtensionLite).getE()); + assertEqualsExactType(120, message.getExtension(optionalImportMessageExtensionLite).getD()); + assertEqualsExactType( + 126, message.getExtension(optionalPublicImportMessageExtensionLite).getE()); assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtensionLite).getBb()); - assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ, - message.getExtension(optionalNestedEnumExtensionLite)); - assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ, - message.getExtension(optionalForeignEnumExtensionLite)); - assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAZ, - message.getExtension(optionalImportEnumExtensionLite)); + assertEqualsExactType( + TestAllTypesLite.NestedEnum.BAZ, message.getExtension(optionalNestedEnumExtensionLite)); + assertEqualsExactType( + ForeignEnumLite.FOREIGN_LITE_BAZ, message.getExtension(optionalForeignEnumExtensionLite)); + assertEqualsExactType( + ImportEnumLite.IMPORT_LITE_BAZ, message.getExtension(optionalImportEnumExtensionLite)); assertEqualsExactType("124", message.getExtension(optionalStringPieceExtensionLite)); assertEqualsExactType("125", message.getExtension(optionalCordExtensionLite)); // ----------------------------------------------------------------- - Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32ExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64ExtensionLite)); - Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite )); - - Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite)); + + Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite)); - Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtensionLite)); - assertEqualsExactType(201 , message.getExtension(repeatedInt32ExtensionLite , 0)); - assertEqualsExactType(202L , message.getExtension(repeatedInt64ExtensionLite , 0)); - assertEqualsExactType(203 , message.getExtension(repeatedUint32ExtensionLite , 0)); - assertEqualsExactType(204L , message.getExtension(repeatedUint64ExtensionLite , 0)); - assertEqualsExactType(205 , message.getExtension(repeatedSint32ExtensionLite , 0)); - assertEqualsExactType(206L , message.getExtension(repeatedSint64ExtensionLite , 0)); - assertEqualsExactType(207 , message.getExtension(repeatedFixed32ExtensionLite , 0)); - assertEqualsExactType(208L , message.getExtension(repeatedFixed64ExtensionLite , 0)); - assertEqualsExactType(209 , message.getExtension(repeatedSfixed32ExtensionLite, 0)); - assertEqualsExactType(210L , message.getExtension(repeatedSfixed64ExtensionLite, 0)); - assertEqualsExactType(211F , message.getExtension(repeatedFloatExtensionLite , 0)); - assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtensionLite , 0)); - assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 0)); - assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite , 0)); + assertEqualsExactType(201, message.getExtension(repeatedInt32ExtensionLite, 0)); + assertEqualsExactType(202L, message.getExtension(repeatedInt64ExtensionLite, 0)); + assertEqualsExactType(203, message.getExtension(repeatedUint32ExtensionLite, 0)); + assertEqualsExactType(204L, message.getExtension(repeatedUint64ExtensionLite, 0)); + assertEqualsExactType(205, message.getExtension(repeatedSint32ExtensionLite, 0)); + assertEqualsExactType(206L, message.getExtension(repeatedSint64ExtensionLite, 0)); + assertEqualsExactType(207, message.getExtension(repeatedFixed32ExtensionLite, 0)); + assertEqualsExactType(208L, message.getExtension(repeatedFixed64ExtensionLite, 0)); + assertEqualsExactType(209, message.getExtension(repeatedSfixed32ExtensionLite, 0)); + assertEqualsExactType(210L, message.getExtension(repeatedSfixed64ExtensionLite, 0)); + assertEqualsExactType(211F, message.getExtension(repeatedFloatExtensionLite, 0)); + assertEqualsExactType(212D, message.getExtension(repeatedDoubleExtensionLite, 0)); + assertEqualsExactType(true, message.getExtension(repeatedBoolExtensionLite, 0)); + assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite, 0)); assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtensionLite, 0)); - assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite ,0).getA()); - assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb()); - assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC()); - assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD()); - assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite ,0).getBb()); + assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite, 0).getA()); + assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite, 0).getBb()); + assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite, 0).getC()); + assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite, 0).getD()); + assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite, 0).getBb()); - assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR, - message.getExtension(repeatedNestedEnumExtensionLite, 0)); - assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR, - message.getExtension(repeatedForeignEnumExtensionLite, 0)); - assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR, - message.getExtension(repeatedImportEnumExtensionLite, 0)); + assertEqualsExactType( + TestAllTypesLite.NestedEnum.BAR, message.getExtension(repeatedNestedEnumExtensionLite, 0)); + assertEqualsExactType( + ForeignEnumLite.FOREIGN_LITE_BAR, + message.getExtension(repeatedForeignEnumExtensionLite, 0)); + assertEqualsExactType( + ImportEnumLite.IMPORT_LITE_BAR, message.getExtension(repeatedImportEnumExtensionLite, 0)); assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtensionLite, 0)); assertEqualsExactType("225", message.getExtension(repeatedCordExtensionLite, 0)); - assertEqualsExactType(301 , message.getExtension(repeatedInt32ExtensionLite , 1)); - assertEqualsExactType(302L , message.getExtension(repeatedInt64ExtensionLite , 1)); - assertEqualsExactType(303 , message.getExtension(repeatedUint32ExtensionLite , 1)); - assertEqualsExactType(304L , message.getExtension(repeatedUint64ExtensionLite , 1)); - assertEqualsExactType(305 , message.getExtension(repeatedSint32ExtensionLite , 1)); - assertEqualsExactType(306L , message.getExtension(repeatedSint64ExtensionLite , 1)); - assertEqualsExactType(307 , message.getExtension(repeatedFixed32ExtensionLite , 1)); - assertEqualsExactType(308L , message.getExtension(repeatedFixed64ExtensionLite , 1)); - assertEqualsExactType(309 , message.getExtension(repeatedSfixed32ExtensionLite, 1)); - assertEqualsExactType(310L , message.getExtension(repeatedSfixed64ExtensionLite, 1)); - assertEqualsExactType(311F , message.getExtension(repeatedFloatExtensionLite , 1)); - assertEqualsExactType(312D , message.getExtension(repeatedDoubleExtensionLite , 1)); - assertEqualsExactType(false, message.getExtension(repeatedBoolExtensionLite , 1)); - assertEqualsExactType("315", message.getExtension(repeatedStringExtensionLite , 1)); + assertEqualsExactType(301, message.getExtension(repeatedInt32ExtensionLite, 1)); + assertEqualsExactType(302L, message.getExtension(repeatedInt64ExtensionLite, 1)); + assertEqualsExactType(303, message.getExtension(repeatedUint32ExtensionLite, 1)); + assertEqualsExactType(304L, message.getExtension(repeatedUint64ExtensionLite, 1)); + assertEqualsExactType(305, message.getExtension(repeatedSint32ExtensionLite, 1)); + assertEqualsExactType(306L, message.getExtension(repeatedSint64ExtensionLite, 1)); + assertEqualsExactType(307, message.getExtension(repeatedFixed32ExtensionLite, 1)); + assertEqualsExactType(308L, message.getExtension(repeatedFixed64ExtensionLite, 1)); + assertEqualsExactType(309, message.getExtension(repeatedSfixed32ExtensionLite, 1)); + assertEqualsExactType(310L, message.getExtension(repeatedSfixed64ExtensionLite, 1)); + assertEqualsExactType(311F, message.getExtension(repeatedFloatExtensionLite, 1)); + assertEqualsExactType(312D, message.getExtension(repeatedDoubleExtensionLite, 1)); + assertEqualsExactType(false, message.getExtension(repeatedBoolExtensionLite, 1)); + assertEqualsExactType("315", message.getExtension(repeatedStringExtensionLite, 1)); assertEqualsExactType(toBytes("316"), message.getExtension(repeatedBytesExtensionLite, 1)); - assertEqualsExactType(317, message.getExtension(repeatedGroupExtensionLite ,1).getA()); - assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb()); - assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtensionLite,1).getC()); - assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtensionLite ,1).getD()); - assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtensionLite ,1).getBb()); + assertEqualsExactType(317, message.getExtension(repeatedGroupExtensionLite, 1).getA()); + assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtensionLite, 1).getBb()); + assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtensionLite, 1).getC()); + assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtensionLite, 1).getD()); + assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtensionLite, 1).getBb()); - assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ, - message.getExtension(repeatedNestedEnumExtensionLite, 1)); - assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ, - message.getExtension(repeatedForeignEnumExtensionLite, 1)); - assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAZ, - message.getExtension(repeatedImportEnumExtensionLite, 1)); + assertEqualsExactType( + TestAllTypesLite.NestedEnum.BAZ, message.getExtension(repeatedNestedEnumExtensionLite, 1)); + assertEqualsExactType( + ForeignEnumLite.FOREIGN_LITE_BAZ, + message.getExtension(repeatedForeignEnumExtensionLite, 1)); + assertEqualsExactType( + ImportEnumLite.IMPORT_LITE_BAZ, message.getExtension(repeatedImportEnumExtensionLite, 1)); assertEqualsExactType("324", message.getExtension(repeatedStringPieceExtensionLite, 1)); assertEqualsExactType("325", message.getExtension(repeatedCordExtensionLite, 1)); // ----------------------------------------------------------------- - Assert.assertTrue(message.hasExtension(defaultInt32ExtensionLite )); - Assert.assertTrue(message.hasExtension(defaultInt64ExtensionLite )); - Assert.assertTrue(message.hasExtension(defaultUint32ExtensionLite )); - Assert.assertTrue(message.hasExtension(defaultUint64ExtensionLite )); - Assert.assertTrue(message.hasExtension(defaultSint32ExtensionLite )); - Assert.assertTrue(message.hasExtension(defaultSint64ExtensionLite )); - Assert.assertTrue(message.hasExtension(defaultFixed32ExtensionLite )); - Assert.assertTrue(message.hasExtension(defaultFixed64ExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultInt32ExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultInt64ExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultUint32ExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultUint64ExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultSint32ExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultSint64ExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultFixed32ExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultFixed64ExtensionLite)); Assert.assertTrue(message.hasExtension(defaultSfixed32ExtensionLite)); Assert.assertTrue(message.hasExtension(defaultSfixed64ExtensionLite)); - Assert.assertTrue(message.hasExtension(defaultFloatExtensionLite )); - Assert.assertTrue(message.hasExtension(defaultDoubleExtensionLite )); - Assert.assertTrue(message.hasExtension(defaultBoolExtensionLite )); - Assert.assertTrue(message.hasExtension(defaultStringExtensionLite )); - Assert.assertTrue(message.hasExtension(defaultBytesExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultFloatExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultDoubleExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultBoolExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultStringExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultBytesExtensionLite)); - Assert.assertTrue(message.hasExtension(defaultNestedEnumExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultNestedEnumExtensionLite)); Assert.assertTrue(message.hasExtension(defaultForeignEnumExtensionLite)); - Assert.assertTrue(message.hasExtension(defaultImportEnumExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultImportEnumExtensionLite)); Assert.assertTrue(message.hasExtension(defaultStringPieceExtensionLite)); Assert.assertTrue(message.hasExtension(defaultCordExtensionLite)); - assertEqualsExactType(401 , message.getExtension(defaultInt32ExtensionLite )); - assertEqualsExactType(402L , message.getExtension(defaultInt64ExtensionLite )); - assertEqualsExactType(403 , message.getExtension(defaultUint32ExtensionLite )); - assertEqualsExactType(404L , message.getExtension(defaultUint64ExtensionLite )); - assertEqualsExactType(405 , message.getExtension(defaultSint32ExtensionLite )); - assertEqualsExactType(406L , message.getExtension(defaultSint64ExtensionLite )); - assertEqualsExactType(407 , message.getExtension(defaultFixed32ExtensionLite )); - assertEqualsExactType(408L , message.getExtension(defaultFixed64ExtensionLite )); - assertEqualsExactType(409 , message.getExtension(defaultSfixed32ExtensionLite)); - assertEqualsExactType(410L , message.getExtension(defaultSfixed64ExtensionLite)); - assertEqualsExactType(411F , message.getExtension(defaultFloatExtensionLite )); - assertEqualsExactType(412D , message.getExtension(defaultDoubleExtensionLite )); - assertEqualsExactType(false, message.getExtension(defaultBoolExtensionLite )); - assertEqualsExactType("415", message.getExtension(defaultStringExtensionLite )); + assertEqualsExactType(401, message.getExtension(defaultInt32ExtensionLite)); + assertEqualsExactType(402L, message.getExtension(defaultInt64ExtensionLite)); + assertEqualsExactType(403, message.getExtension(defaultUint32ExtensionLite)); + assertEqualsExactType(404L, message.getExtension(defaultUint64ExtensionLite)); + assertEqualsExactType(405, message.getExtension(defaultSint32ExtensionLite)); + assertEqualsExactType(406L, message.getExtension(defaultSint64ExtensionLite)); + assertEqualsExactType(407, message.getExtension(defaultFixed32ExtensionLite)); + assertEqualsExactType(408L, message.getExtension(defaultFixed64ExtensionLite)); + assertEqualsExactType(409, message.getExtension(defaultSfixed32ExtensionLite)); + assertEqualsExactType(410L, message.getExtension(defaultSfixed64ExtensionLite)); + assertEqualsExactType(411F, message.getExtension(defaultFloatExtensionLite)); + assertEqualsExactType(412D, message.getExtension(defaultDoubleExtensionLite)); + assertEqualsExactType(false, message.getExtension(defaultBoolExtensionLite)); + assertEqualsExactType("415", message.getExtension(defaultStringExtensionLite)); assertEqualsExactType(toBytes("416"), message.getExtension(defaultBytesExtensionLite)); - assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO, - message.getExtension(defaultNestedEnumExtensionLite )); - assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO, - message.getExtension(defaultForeignEnumExtensionLite)); - assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO, - message.getExtension(defaultImportEnumExtensionLite)); + assertEqualsExactType( + TestAllTypesLite.NestedEnum.FOO, message.getExtension(defaultNestedEnumExtensionLite)); + assertEqualsExactType( + ForeignEnumLite.FOREIGN_LITE_FOO, message.getExtension(defaultForeignEnumExtensionLite)); + assertEqualsExactType( + ImportEnumLite.IMPORT_LITE_FOO, message.getExtension(defaultImportEnumExtensionLite)); assertEqualsExactType("424", message.getExtension(defaultStringPieceExtensionLite)); assertEqualsExactType("425", message.getExtension(defaultCordExtensionLite)); @@ -2226,163 +2217,160 @@ public static void assertAllExtensionsSet( // ------------------------------------------------------------------- /** - * Assert (using {@code junit.framework.Assert}} that all extensions of - * {@code message} are cleared, and that getting the extensions returns their - * default values. + * Assert (using {@code junit.framework.Assert}} that all extensions of {@code message} are + * cleared, and that getting the extensions returns their default values. */ - public static void assertExtensionsClear( - TestAllExtensionsLiteOrBuilder message) { + public static void assertExtensionsClear(TestAllExtensionsLiteOrBuilder message) { // hasBlah() should initially be false for all optional fields. - Assert.assertFalse(message.hasExtension(optionalInt32ExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalInt64ExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalUint32ExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalUint64ExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalSint32ExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalSint64ExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalFixed32ExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalFixed64ExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalInt32ExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalInt64ExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalUint32ExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalUint64ExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalSint32ExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalSint64ExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalFixed32ExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalFixed64ExtensionLite)); Assert.assertFalse(message.hasExtension(optionalSfixed32ExtensionLite)); Assert.assertFalse(message.hasExtension(optionalSfixed64ExtensionLite)); - Assert.assertFalse(message.hasExtension(optionalFloatExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalDoubleExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalBoolExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalStringExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalBytesExtensionLite )); - - Assert.assertFalse(message.hasExtension(optionalGroupExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalNestedMessageExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalForeignMessageExtensionLite )); - Assert.assertFalse(message.hasExtension(optionalImportMessageExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalFloatExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalDoubleExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalBoolExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalStringExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalBytesExtensionLite)); + + Assert.assertFalse(message.hasExtension(optionalGroupExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalNestedMessageExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalForeignMessageExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalImportMessageExtensionLite)); Assert.assertFalse(message.hasExtension(optionalPublicImportMessageExtensionLite)); - Assert.assertFalse(message.hasExtension(optionalLazyMessageExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalLazyMessageExtensionLite)); - Assert.assertFalse(message.hasExtension(optionalNestedEnumExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalNestedEnumExtensionLite)); Assert.assertFalse(message.hasExtension(optionalForeignEnumExtensionLite)); - Assert.assertFalse(message.hasExtension(optionalImportEnumExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalImportEnumExtensionLite)); Assert.assertFalse(message.hasExtension(optionalStringPieceExtensionLite)); Assert.assertFalse(message.hasExtension(optionalCordExtensionLite)); // Optional fields without defaults are set to zero or something like it. - assertEqualsExactType(0 , message.getExtension(optionalInt32ExtensionLite )); - assertEqualsExactType(0L , message.getExtension(optionalInt64ExtensionLite )); - assertEqualsExactType(0 , message.getExtension(optionalUint32ExtensionLite )); - assertEqualsExactType(0L , message.getExtension(optionalUint64ExtensionLite )); - assertEqualsExactType(0 , message.getExtension(optionalSint32ExtensionLite )); - assertEqualsExactType(0L , message.getExtension(optionalSint64ExtensionLite )); - assertEqualsExactType(0 , message.getExtension(optionalFixed32ExtensionLite )); - assertEqualsExactType(0L , message.getExtension(optionalFixed64ExtensionLite )); - assertEqualsExactType(0 , message.getExtension(optionalSfixed32ExtensionLite)); - assertEqualsExactType(0L , message.getExtension(optionalSfixed64ExtensionLite)); - assertEqualsExactType(0F , message.getExtension(optionalFloatExtensionLite )); - assertEqualsExactType(0D , message.getExtension(optionalDoubleExtensionLite )); - assertEqualsExactType(false, message.getExtension(optionalBoolExtensionLite )); - assertEqualsExactType("" , message.getExtension(optionalStringExtensionLite )); + assertEqualsExactType(0, message.getExtension(optionalInt32ExtensionLite)); + assertEqualsExactType(0L, message.getExtension(optionalInt64ExtensionLite)); + assertEqualsExactType(0, message.getExtension(optionalUint32ExtensionLite)); + assertEqualsExactType(0L, message.getExtension(optionalUint64ExtensionLite)); + assertEqualsExactType(0, message.getExtension(optionalSint32ExtensionLite)); + assertEqualsExactType(0L, message.getExtension(optionalSint64ExtensionLite)); + assertEqualsExactType(0, message.getExtension(optionalFixed32ExtensionLite)); + assertEqualsExactType(0L, message.getExtension(optionalFixed64ExtensionLite)); + assertEqualsExactType(0, message.getExtension(optionalSfixed32ExtensionLite)); + assertEqualsExactType(0L, message.getExtension(optionalSfixed64ExtensionLite)); + assertEqualsExactType(0F, message.getExtension(optionalFloatExtensionLite)); + assertEqualsExactType(0D, message.getExtension(optionalDoubleExtensionLite)); + assertEqualsExactType(false, message.getExtension(optionalBoolExtensionLite)); + assertEqualsExactType("", message.getExtension(optionalStringExtensionLite)); assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtensionLite)); // Embedded messages should also be clear. - Assert.assertFalse(message.getExtension(optionalGroupExtensionLite ).hasA()); - Assert.assertFalse(message.getExtension(optionalNestedMessageExtensionLite ).hasBb()); - Assert.assertFalse(message.getExtension(optionalForeignMessageExtensionLite ).hasC()); - Assert.assertFalse(message.getExtension(optionalImportMessageExtensionLite ).hasD()); + Assert.assertFalse(message.getExtension(optionalGroupExtensionLite).hasA()); + Assert.assertFalse(message.getExtension(optionalNestedMessageExtensionLite).hasBb()); + Assert.assertFalse(message.getExtension(optionalForeignMessageExtensionLite).hasC()); + Assert.assertFalse(message.getExtension(optionalImportMessageExtensionLite).hasD()); Assert.assertFalse(message.getExtension(optionalPublicImportMessageExtensionLite).hasE()); - Assert.assertFalse(message.getExtension(optionalLazyMessageExtensionLite ).hasBb()); + Assert.assertFalse(message.getExtension(optionalLazyMessageExtensionLite).hasBb()); - assertEqualsExactType(0, message.getExtension(optionalGroupExtensionLite ).getA()); - assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtensionLite ).getBb()); + assertEqualsExactType(0, message.getExtension(optionalGroupExtensionLite).getA()); + assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtensionLite).getBb()); assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtensionLite).getC()); - assertEqualsExactType(0, message.getExtension(optionalImportMessageExtensionLite ).getD()); - assertEqualsExactType(0, message.getExtension( - optionalPublicImportMessageExtensionLite).getE()); - assertEqualsExactType(0, message.getExtension(optionalLazyMessageExtensionLite ).getBb()); + assertEqualsExactType(0, message.getExtension(optionalImportMessageExtensionLite).getD()); + assertEqualsExactType(0, message.getExtension(optionalPublicImportMessageExtensionLite).getE()); + assertEqualsExactType(0, message.getExtension(optionalLazyMessageExtensionLite).getBb()); // Enums without defaults are set to the first value in the enum. - assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO, - message.getExtension(optionalNestedEnumExtensionLite )); - assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO, - message.getExtension(optionalForeignEnumExtensionLite)); - assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO, - message.getExtension(optionalImportEnumExtensionLite)); + assertEqualsExactType( + TestAllTypesLite.NestedEnum.FOO, message.getExtension(optionalNestedEnumExtensionLite)); + assertEqualsExactType( + ForeignEnumLite.FOREIGN_LITE_FOO, message.getExtension(optionalForeignEnumExtensionLite)); + assertEqualsExactType( + ImportEnumLite.IMPORT_LITE_FOO, message.getExtension(optionalImportEnumExtensionLite)); assertEqualsExactType("", message.getExtension(optionalStringPieceExtensionLite)); assertEqualsExactType("", message.getExtension(optionalCordExtensionLite)); // Repeated fields are empty. - Assert.assertEquals(0, message.getExtensionCount(repeatedInt32ExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedInt64ExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedUint32ExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedUint64ExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedSint32ExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedSint64ExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32ExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64ExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedInt32ExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedInt64ExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedUint32ExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedUint64ExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedSint32ExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedSint64ExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32ExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64ExtensionLite)); Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed32ExtensionLite)); Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed64ExtensionLite)); - Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtensionLite )); - - Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtensionLite)); + + Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtensionLite)); Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtensionLite)); - Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtensionLite )); - Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtensionLite)); Assert.assertEquals(0, message.getExtensionCount(repeatedStringPieceExtensionLite)); Assert.assertEquals(0, message.getExtensionCount(repeatedCordExtensionLite)); // hasBlah() should also be false for all default fields. - Assert.assertFalse(message.hasExtension(defaultInt32ExtensionLite )); - Assert.assertFalse(message.hasExtension(defaultInt64ExtensionLite )); - Assert.assertFalse(message.hasExtension(defaultUint32ExtensionLite )); - Assert.assertFalse(message.hasExtension(defaultUint64ExtensionLite )); - Assert.assertFalse(message.hasExtension(defaultSint32ExtensionLite )); - Assert.assertFalse(message.hasExtension(defaultSint64ExtensionLite )); - Assert.assertFalse(message.hasExtension(defaultFixed32ExtensionLite )); - Assert.assertFalse(message.hasExtension(defaultFixed64ExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultInt32ExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultInt64ExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultUint32ExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultUint64ExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultSint32ExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultSint64ExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultFixed32ExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultFixed64ExtensionLite)); Assert.assertFalse(message.hasExtension(defaultSfixed32ExtensionLite)); Assert.assertFalse(message.hasExtension(defaultSfixed64ExtensionLite)); - Assert.assertFalse(message.hasExtension(defaultFloatExtensionLite )); - Assert.assertFalse(message.hasExtension(defaultDoubleExtensionLite )); - Assert.assertFalse(message.hasExtension(defaultBoolExtensionLite )); - Assert.assertFalse(message.hasExtension(defaultStringExtensionLite )); - Assert.assertFalse(message.hasExtension(defaultBytesExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultFloatExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultDoubleExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultBoolExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultStringExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultBytesExtensionLite)); - Assert.assertFalse(message.hasExtension(defaultNestedEnumExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultNestedEnumExtensionLite)); Assert.assertFalse(message.hasExtension(defaultForeignEnumExtensionLite)); - Assert.assertFalse(message.hasExtension(defaultImportEnumExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultImportEnumExtensionLite)); Assert.assertFalse(message.hasExtension(defaultStringPieceExtensionLite)); Assert.assertFalse(message.hasExtension(defaultCordExtensionLite)); // Fields with defaults have their default values (duh). - assertEqualsExactType( 41 , message.getExtension(defaultInt32ExtensionLite )); - assertEqualsExactType( 42L , message.getExtension(defaultInt64ExtensionLite )); - assertEqualsExactType( 43 , message.getExtension(defaultUint32ExtensionLite )); - assertEqualsExactType( 44L , message.getExtension(defaultUint64ExtensionLite )); - assertEqualsExactType(-45 , message.getExtension(defaultSint32ExtensionLite )); - assertEqualsExactType( 46L , message.getExtension(defaultSint64ExtensionLite )); - assertEqualsExactType( 47 , message.getExtension(defaultFixed32ExtensionLite )); - assertEqualsExactType( 48L , message.getExtension(defaultFixed64ExtensionLite )); - assertEqualsExactType( 49 , message.getExtension(defaultSfixed32ExtensionLite)); - assertEqualsExactType(-50L , message.getExtension(defaultSfixed64ExtensionLite)); - assertEqualsExactType( 51.5F , message.getExtension(defaultFloatExtensionLite )); - assertEqualsExactType( 52e3D , message.getExtension(defaultDoubleExtensionLite )); - assertEqualsExactType(true , message.getExtension(defaultBoolExtensionLite )); - assertEqualsExactType("hello", message.getExtension(defaultStringExtensionLite )); + assertEqualsExactType(41, message.getExtension(defaultInt32ExtensionLite)); + assertEqualsExactType(42L, message.getExtension(defaultInt64ExtensionLite)); + assertEqualsExactType(43, message.getExtension(defaultUint32ExtensionLite)); + assertEqualsExactType(44L, message.getExtension(defaultUint64ExtensionLite)); + assertEqualsExactType(-45, message.getExtension(defaultSint32ExtensionLite)); + assertEqualsExactType(46L, message.getExtension(defaultSint64ExtensionLite)); + assertEqualsExactType(47, message.getExtension(defaultFixed32ExtensionLite)); + assertEqualsExactType(48L, message.getExtension(defaultFixed64ExtensionLite)); + assertEqualsExactType(49, message.getExtension(defaultSfixed32ExtensionLite)); + assertEqualsExactType(-50L, message.getExtension(defaultSfixed64ExtensionLite)); + assertEqualsExactType(51.5F, message.getExtension(defaultFloatExtensionLite)); + assertEqualsExactType(52e3D, message.getExtension(defaultDoubleExtensionLite)); + assertEqualsExactType(true, message.getExtension(defaultBoolExtensionLite)); + assertEqualsExactType("hello", message.getExtension(defaultStringExtensionLite)); assertEqualsExactType(toBytes("world"), message.getExtension(defaultBytesExtensionLite)); - assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR, - message.getExtension(defaultNestedEnumExtensionLite )); - assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR, - message.getExtension(defaultForeignEnumExtensionLite)); - assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR, - message.getExtension(defaultImportEnumExtensionLite)); + assertEqualsExactType( + TestAllTypesLite.NestedEnum.BAR, message.getExtension(defaultNestedEnumExtensionLite)); + assertEqualsExactType( + ForeignEnumLite.FOREIGN_LITE_BAR, message.getExtension(defaultForeignEnumExtensionLite)); + assertEqualsExactType( + ImportEnumLite.IMPORT_LITE_BAR, message.getExtension(defaultImportEnumExtensionLite)); assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtensionLite)); assertEqualsExactType("123", message.getExtension(defaultCordExtensionLite)); @@ -2396,200 +2384,229 @@ public static void assertExtensionsClear( // ------------------------------------------------------------------- /** - * Assert (using {@code junit.framework.Assert}} that all extensions of - * {@code message} are set to the values assigned by {@code setAllExtensions} - * followed by {@code modifyRepeatedExtensions}. + * Assert (using {@code junit.framework.Assert}} that all extensions of {@code message} are set to + * the values assigned by {@code setAllExtensions} followed by {@code modifyRepeatedExtensions}. */ - public static void assertRepeatedExtensionsModified( - TestAllExtensionsLiteOrBuilder message) { + public static void assertRepeatedExtensionsModified(TestAllExtensionsLiteOrBuilder message) { // ModifyRepeatedFields only sets the second repeated element of each // field. In addition to verifying this, we also verify that the first // element and size were *not* modified. - Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32ExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64ExtensionLite)); - Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite )); - - Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite)); + + Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite)); - Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtensionLite)); - assertEqualsExactType(201 , message.getExtension(repeatedInt32ExtensionLite , 0)); - assertEqualsExactType(202L , message.getExtension(repeatedInt64ExtensionLite , 0)); - assertEqualsExactType(203 , message.getExtension(repeatedUint32ExtensionLite , 0)); - assertEqualsExactType(204L , message.getExtension(repeatedUint64ExtensionLite , 0)); - assertEqualsExactType(205 , message.getExtension(repeatedSint32ExtensionLite , 0)); - assertEqualsExactType(206L , message.getExtension(repeatedSint64ExtensionLite , 0)); - assertEqualsExactType(207 , message.getExtension(repeatedFixed32ExtensionLite , 0)); - assertEqualsExactType(208L , message.getExtension(repeatedFixed64ExtensionLite , 0)); - assertEqualsExactType(209 , message.getExtension(repeatedSfixed32ExtensionLite, 0)); - assertEqualsExactType(210L , message.getExtension(repeatedSfixed64ExtensionLite, 0)); - assertEqualsExactType(211F , message.getExtension(repeatedFloatExtensionLite , 0)); - assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtensionLite , 0)); - assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 0)); - assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite , 0)); + assertEqualsExactType(201, message.getExtension(repeatedInt32ExtensionLite, 0)); + assertEqualsExactType(202L, message.getExtension(repeatedInt64ExtensionLite, 0)); + assertEqualsExactType(203, message.getExtension(repeatedUint32ExtensionLite, 0)); + assertEqualsExactType(204L, message.getExtension(repeatedUint64ExtensionLite, 0)); + assertEqualsExactType(205, message.getExtension(repeatedSint32ExtensionLite, 0)); + assertEqualsExactType(206L, message.getExtension(repeatedSint64ExtensionLite, 0)); + assertEqualsExactType(207, message.getExtension(repeatedFixed32ExtensionLite, 0)); + assertEqualsExactType(208L, message.getExtension(repeatedFixed64ExtensionLite, 0)); + assertEqualsExactType(209, message.getExtension(repeatedSfixed32ExtensionLite, 0)); + assertEqualsExactType(210L, message.getExtension(repeatedSfixed64ExtensionLite, 0)); + assertEqualsExactType(211F, message.getExtension(repeatedFloatExtensionLite, 0)); + assertEqualsExactType(212D, message.getExtension(repeatedDoubleExtensionLite, 0)); + assertEqualsExactType(true, message.getExtension(repeatedBoolExtensionLite, 0)); + assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite, 0)); assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtensionLite, 0)); - assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite ,0).getA()); - assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb()); - assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC()); - assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD()); - assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite ,0).getBb()); + assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite, 0).getA()); + assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite, 0).getBb()); + assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite, 0).getC()); + assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite, 0).getD()); + assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite, 0).getBb()); - assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR, - message.getExtension(repeatedNestedEnumExtensionLite, 0)); - assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR, - message.getExtension(repeatedForeignEnumExtensionLite, 0)); - assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR, - message.getExtension(repeatedImportEnumExtensionLite, 0)); + assertEqualsExactType( + TestAllTypesLite.NestedEnum.BAR, message.getExtension(repeatedNestedEnumExtensionLite, 0)); + assertEqualsExactType( + ForeignEnumLite.FOREIGN_LITE_BAR, + message.getExtension(repeatedForeignEnumExtensionLite, 0)); + assertEqualsExactType( + ImportEnumLite.IMPORT_LITE_BAR, message.getExtension(repeatedImportEnumExtensionLite, 0)); assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtensionLite, 0)); assertEqualsExactType("225", message.getExtension(repeatedCordExtensionLite, 0)); // Actually verify the second (modified) elements now. - assertEqualsExactType(501 , message.getExtension(repeatedInt32ExtensionLite , 1)); - assertEqualsExactType(502L , message.getExtension(repeatedInt64ExtensionLite , 1)); - assertEqualsExactType(503 , message.getExtension(repeatedUint32ExtensionLite , 1)); - assertEqualsExactType(504L , message.getExtension(repeatedUint64ExtensionLite , 1)); - assertEqualsExactType(505 , message.getExtension(repeatedSint32ExtensionLite , 1)); - assertEqualsExactType(506L , message.getExtension(repeatedSint64ExtensionLite , 1)); - assertEqualsExactType(507 , message.getExtension(repeatedFixed32ExtensionLite , 1)); - assertEqualsExactType(508L , message.getExtension(repeatedFixed64ExtensionLite , 1)); - assertEqualsExactType(509 , message.getExtension(repeatedSfixed32ExtensionLite, 1)); - assertEqualsExactType(510L , message.getExtension(repeatedSfixed64ExtensionLite, 1)); - assertEqualsExactType(511F , message.getExtension(repeatedFloatExtensionLite , 1)); - assertEqualsExactType(512D , message.getExtension(repeatedDoubleExtensionLite , 1)); - assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 1)); - assertEqualsExactType("515", message.getExtension(repeatedStringExtensionLite , 1)); + assertEqualsExactType(501, message.getExtension(repeatedInt32ExtensionLite, 1)); + assertEqualsExactType(502L, message.getExtension(repeatedInt64ExtensionLite, 1)); + assertEqualsExactType(503, message.getExtension(repeatedUint32ExtensionLite, 1)); + assertEqualsExactType(504L, message.getExtension(repeatedUint64ExtensionLite, 1)); + assertEqualsExactType(505, message.getExtension(repeatedSint32ExtensionLite, 1)); + assertEqualsExactType(506L, message.getExtension(repeatedSint64ExtensionLite, 1)); + assertEqualsExactType(507, message.getExtension(repeatedFixed32ExtensionLite, 1)); + assertEqualsExactType(508L, message.getExtension(repeatedFixed64ExtensionLite, 1)); + assertEqualsExactType(509, message.getExtension(repeatedSfixed32ExtensionLite, 1)); + assertEqualsExactType(510L, message.getExtension(repeatedSfixed64ExtensionLite, 1)); + assertEqualsExactType(511F, message.getExtension(repeatedFloatExtensionLite, 1)); + assertEqualsExactType(512D, message.getExtension(repeatedDoubleExtensionLite, 1)); + assertEqualsExactType(true, message.getExtension(repeatedBoolExtensionLite, 1)); + assertEqualsExactType("515", message.getExtension(repeatedStringExtensionLite, 1)); assertEqualsExactType(toBytes("516"), message.getExtension(repeatedBytesExtensionLite, 1)); - assertEqualsExactType(517, message.getExtension(repeatedGroupExtensionLite ,1).getA()); - assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb()); - assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtensionLite,1).getC()); - assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtensionLite ,1).getD()); - assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtensionLite ,1).getBb()); + assertEqualsExactType(517, message.getExtension(repeatedGroupExtensionLite, 1).getA()); + assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtensionLite, 1).getBb()); + assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtensionLite, 1).getC()); + assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtensionLite, 1).getD()); + assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtensionLite, 1).getBb()); - assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO, - message.getExtension(repeatedNestedEnumExtensionLite, 1)); - assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO, - message.getExtension(repeatedForeignEnumExtensionLite, 1)); - assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO, - message.getExtension(repeatedImportEnumExtensionLite, 1)); + assertEqualsExactType( + TestAllTypesLite.NestedEnum.FOO, message.getExtension(repeatedNestedEnumExtensionLite, 1)); + assertEqualsExactType( + ForeignEnumLite.FOREIGN_LITE_FOO, + message.getExtension(repeatedForeignEnumExtensionLite, 1)); + assertEqualsExactType( + ImportEnumLite.IMPORT_LITE_FOO, message.getExtension(repeatedImportEnumExtensionLite, 1)); assertEqualsExactType("524", message.getExtension(repeatedStringPieceExtensionLite, 1)); assertEqualsExactType("525", message.getExtension(repeatedCordExtensionLite, 1)); } public static void assertPackedExtensionsSet(TestPackedExtensionsLite message) { - Assert.assertEquals(2, message.getExtensionCount(packedInt32ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(packedInt64ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(packedUint32ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(packedUint64ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(packedSint32ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(packedSint64ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(packedFixed32ExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(packedFixed64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(packedInt32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(packedInt64ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(packedUint32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(packedUint64ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(packedSint32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(packedSint64ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(packedFixed32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(packedFixed64ExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(packedSfixed32ExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(packedSfixed64ExtensionLite)); - Assert.assertEquals(2, message.getExtensionCount(packedFloatExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtensionLite )); - Assert.assertEquals(2, message.getExtensionCount(packedBoolExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(packedFloatExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(packedBoolExtensionLite)); Assert.assertEquals(2, message.getExtensionCount(packedEnumExtensionLite)); - assertEqualsExactType(601 , message.getExtension(packedInt32ExtensionLite , 0)); - assertEqualsExactType(602L , message.getExtension(packedInt64ExtensionLite , 0)); - assertEqualsExactType(603 , message.getExtension(packedUint32ExtensionLite , 0)); - assertEqualsExactType(604L , message.getExtension(packedUint64ExtensionLite , 0)); - assertEqualsExactType(605 , message.getExtension(packedSint32ExtensionLite , 0)); - assertEqualsExactType(606L , message.getExtension(packedSint64ExtensionLite , 0)); - assertEqualsExactType(607 , message.getExtension(packedFixed32ExtensionLite , 0)); - assertEqualsExactType(608L , message.getExtension(packedFixed64ExtensionLite , 0)); - assertEqualsExactType(609 , message.getExtension(packedSfixed32ExtensionLite, 0)); - assertEqualsExactType(610L , message.getExtension(packedSfixed64ExtensionLite, 0)); - assertEqualsExactType(611F , message.getExtension(packedFloatExtensionLite , 0)); - assertEqualsExactType(612D , message.getExtension(packedDoubleExtensionLite , 0)); - assertEqualsExactType(true , message.getExtension(packedBoolExtensionLite , 0)); - assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR, - message.getExtension(packedEnumExtensionLite, 0)); - assertEqualsExactType(701 , message.getExtension(packedInt32ExtensionLite , 1)); - assertEqualsExactType(702L , message.getExtension(packedInt64ExtensionLite , 1)); - assertEqualsExactType(703 , message.getExtension(packedUint32ExtensionLite , 1)); - assertEqualsExactType(704L , message.getExtension(packedUint64ExtensionLite , 1)); - assertEqualsExactType(705 , message.getExtension(packedSint32ExtensionLite , 1)); - assertEqualsExactType(706L , message.getExtension(packedSint64ExtensionLite , 1)); - assertEqualsExactType(707 , message.getExtension(packedFixed32ExtensionLite , 1)); - assertEqualsExactType(708L , message.getExtension(packedFixed64ExtensionLite , 1)); - assertEqualsExactType(709 , message.getExtension(packedSfixed32ExtensionLite, 1)); - assertEqualsExactType(710L , message.getExtension(packedSfixed64ExtensionLite, 1)); - assertEqualsExactType(711F , message.getExtension(packedFloatExtensionLite , 1)); - assertEqualsExactType(712D , message.getExtension(packedDoubleExtensionLite , 1)); - assertEqualsExactType(false, message.getExtension(packedBoolExtensionLite , 1)); - assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ, - message.getExtension(packedEnumExtensionLite, 1)); + assertEqualsExactType(601, message.getExtension(packedInt32ExtensionLite, 0)); + assertEqualsExactType(602L, message.getExtension(packedInt64ExtensionLite, 0)); + assertEqualsExactType(603, message.getExtension(packedUint32ExtensionLite, 0)); + assertEqualsExactType(604L, message.getExtension(packedUint64ExtensionLite, 0)); + assertEqualsExactType(605, message.getExtension(packedSint32ExtensionLite, 0)); + assertEqualsExactType(606L, message.getExtension(packedSint64ExtensionLite, 0)); + assertEqualsExactType(607, message.getExtension(packedFixed32ExtensionLite, 0)); + assertEqualsExactType(608L, message.getExtension(packedFixed64ExtensionLite, 0)); + assertEqualsExactType(609, message.getExtension(packedSfixed32ExtensionLite, 0)); + assertEqualsExactType(610L, message.getExtension(packedSfixed64ExtensionLite, 0)); + assertEqualsExactType(611F, message.getExtension(packedFloatExtensionLite, 0)); + assertEqualsExactType(612D, message.getExtension(packedDoubleExtensionLite, 0)); + assertEqualsExactType(true, message.getExtension(packedBoolExtensionLite, 0)); + assertEqualsExactType( + ForeignEnumLite.FOREIGN_LITE_BAR, message.getExtension(packedEnumExtensionLite, 0)); + assertEqualsExactType(701, message.getExtension(packedInt32ExtensionLite, 1)); + assertEqualsExactType(702L, message.getExtension(packedInt64ExtensionLite, 1)); + assertEqualsExactType(703, message.getExtension(packedUint32ExtensionLite, 1)); + assertEqualsExactType(704L, message.getExtension(packedUint64ExtensionLite, 1)); + assertEqualsExactType(705, message.getExtension(packedSint32ExtensionLite, 1)); + assertEqualsExactType(706L, message.getExtension(packedSint64ExtensionLite, 1)); + assertEqualsExactType(707, message.getExtension(packedFixed32ExtensionLite, 1)); + assertEqualsExactType(708L, message.getExtension(packedFixed64ExtensionLite, 1)); + assertEqualsExactType(709, message.getExtension(packedSfixed32ExtensionLite, 1)); + assertEqualsExactType(710L, message.getExtension(packedSfixed64ExtensionLite, 1)); + assertEqualsExactType(711F, message.getExtension(packedFloatExtensionLite, 1)); + assertEqualsExactType(712D, message.getExtension(packedDoubleExtensionLite, 1)); + assertEqualsExactType(false, message.getExtension(packedBoolExtensionLite, 1)); + assertEqualsExactType( + ForeignEnumLite.FOREIGN_LITE_BAZ, message.getExtension(packedEnumExtensionLite, 1)); } // =================================================================== // oneof public static void setOneof(TestOneof2.Builder message) { - message.setFooLazyMessage( - TestOneof2.NestedMessage.newBuilder().setQuxInt(100).build()); + message.setFooLazyMessage(TestOneof2.NestedMessage.newBuilder().setQuxInt(100).build()); message.setBarString("101"); message.setBazInt(102); message.setBazString("103"); } public static void assertOneofSet(TestOneof2 message) { - Assert.assertTrue(message.hasFooLazyMessage ()); + Assert.assertTrue(message.hasFooLazyMessage()); Assert.assertTrue(message.getFooLazyMessage().hasQuxInt()); Assert.assertTrue(message.hasBarString()); - Assert.assertTrue(message.hasBazInt ()); + Assert.assertTrue(message.hasBazInt()); Assert.assertTrue(message.hasBazString()); - Assert.assertEquals(100 , message.getFooLazyMessage().getQuxInt()); - Assert.assertEquals("101", message.getBarString ()); - Assert.assertEquals(102 , message.getBazInt ()); - Assert.assertEquals("103", message.getBazString ()); + Assert.assertEquals(100, message.getFooLazyMessage().getQuxInt()); + Assert.assertEquals("101", message.getBarString()); + Assert.assertEquals(102, message.getBazInt()); + Assert.assertEquals("103", message.getBazString()); } public static void assertAtMostOneFieldSetOneof(TestOneof2 message) { int count = 0; - if (message.hasFooInt()) { ++count; } - if (message.hasFooString()) { ++count; } - if (message.hasFooCord()) { ++count; } - if (message.hasFooStringPiece()) { ++count; } - if (message.hasFooBytes()) { ++count; } - if (message.hasFooEnum()) { ++count; } - if (message.hasFooMessage()) { ++count; } - if (message.hasFooGroup()) { ++count; } - if (message.hasFooLazyMessage()) { ++count; } + if (message.hasFooInt()) { + ++count; + } + if (message.hasFooString()) { + ++count; + } + if (message.hasFooCord()) { + ++count; + } + if (message.hasFooStringPiece()) { + ++count; + } + if (message.hasFooBytes()) { + ++count; + } + if (message.hasFooEnum()) { + ++count; + } + if (message.hasFooMessage()) { + ++count; + } + if (message.hasFooGroup()) { + ++count; + } + if (message.hasFooLazyMessage()) { + ++count; + } Assert.assertTrue(count <= 1); count = 0; - if (message.hasBarInt()) { ++count; } - if (message.hasBarString()) { ++count; } - if (message.hasBarCord()) { ++count; } - if (message.hasBarStringPiece()) { ++count; } - if (message.hasBarBytes()) { ++count; } - if (message.hasBarEnum()) { ++count; } + if (message.hasBarInt()) { + ++count; + } + if (message.hasBarString()) { + ++count; + } + if (message.hasBarCord()) { + ++count; + } + if (message.hasBarStringPiece()) { + ++count; + } + if (message.hasBarBytes()) { + ++count; + } + if (message.hasBarEnum()) { + ++count; + } Assert.assertTrue(count <= 1); switch (message.getFooCase()) { @@ -2622,17 +2639,16 @@ public static void assertAtMostOneFieldSetOneof(TestOneof2 message) { break; case FOO_NOT_SET: break; - default: // TODO(b/18683919): go/enum-switch-lsc } } // ================================================================= + // BEGIN FULL-RUNTIME /** - * Performs the same things that the methods of {@code TestUtil} do, but - * via the reflection interface. This is its own class because it needs - * to know what descriptor to use. + * Performs the same things that the methods of {@code TestUtil} do, but via the reflection + * interface. This is its own class because it needs to know what descriptor to use. */ public static class ReflectionTester { private final Descriptors.Descriptor baseDescriptor; @@ -2671,20 +2687,16 @@ public static class ReflectionTester { private final Descriptors.EnumValueDescriptor importBaz; /** - * Construct a {@code ReflectionTester} that will expect messages using - * the given descriptor. + * Construct a {@code ReflectionTester} that will expect messages using the given descriptor. * - * Normally {@code baseDescriptor} should be a descriptor for the type - * {@code TestAllTypes}, defined in - * {@code google/protobuf/unittest.proto}. However, if - * {@code extensionRegistry} is non-null, then {@code baseDescriptor} should - * be for {@code TestAllExtensions} instead, and instead of reading and - * writing normal fields, the tester will read and write extensions. - * All of {@code TestAllExtensions}' extensions must be registered in the - * registry. + *

Normally {@code baseDescriptor} should be a descriptor for the type {@code TestAllTypes}, + * defined in {@code google/protobuf/unittest.proto}. However, if {@code extensionRegistry} + * is non-null, then {@code baseDescriptor} should be for {@code TestAllExtensions} instead, and + * instead of reading and writing normal fields, the tester will read and write extensions. All + * of {@code TestAllExtensions}' extensions must be registered in the registry. */ - public ReflectionTester(Descriptors.Descriptor baseDescriptor, - ExtensionRegistry extensionRegistry) { + public ReflectionTester( + Descriptors.Descriptor baseDescriptor, ExtensionRegistry extensionRegistry) { this.baseDescriptor = baseDescriptor; this.extensionRegistry = extensionRegistry; @@ -2694,7 +2706,7 @@ public ReflectionTester(Descriptors.Descriptor baseDescriptor, this.publicImportFile = importFile.getDependencies().get(0); Descriptors.Descriptor testAllTypes; - if (baseDescriptor.getName() == "TestAllTypes") { + if ("TestAllTypes".equals(baseDescriptor.getName())) { testAllTypes = baseDescriptor; } else { testAllTypes = file.findMessageTypeByName("TestAllTypes"); @@ -2705,39 +2717,34 @@ public ReflectionTester(Descriptors.Descriptor baseDescriptor, // Use testAllTypes, rather than baseDescriptor, to allow // initialization using TestPackedTypes descriptors. These objects // won't be used by the methods for packed fields. - this.optionalGroup = - testAllTypes.findNestedTypeByName("OptionalGroup"); - this.repeatedGroup = - testAllTypes.findNestedTypeByName("RepeatedGroup"); + this.optionalGroup = testAllTypes.findNestedTypeByName("OptionalGroup"); + this.repeatedGroup = testAllTypes.findNestedTypeByName("RepeatedGroup"); } else { - this.optionalGroup = - file.findMessageTypeByName("OptionalGroup_extension"); - this.repeatedGroup = - file.findMessageTypeByName("RepeatedGroup_extension"); + this.optionalGroup = file.findMessageTypeByName("OptionalGroup_extension"); + this.repeatedGroup = file.findMessageTypeByName("RepeatedGroup_extension"); } this.nestedMessage = testAllTypes.findNestedTypeByName("NestedMessage"); this.foreignMessage = file.findMessageTypeByName("ForeignMessage"); this.importMessage = importFile.findMessageTypeByName("ImportMessage"); - this.publicImportMessage = publicImportFile.findMessageTypeByName( - "PublicImportMessage"); + this.publicImportMessage = publicImportFile.findMessageTypeByName("PublicImportMessage"); this.nestedEnum = testAllTypes.findEnumTypeByName("NestedEnum"); this.foreignEnum = file.findEnumTypeByName("ForeignEnum"); this.importEnum = importFile.findEnumTypeByName("ImportEnum"); - Assert.assertNotNull(optionalGroup ); - Assert.assertNotNull(repeatedGroup ); - Assert.assertNotNull(nestedMessage ); + Assert.assertNotNull(optionalGroup); + Assert.assertNotNull(repeatedGroup); + Assert.assertNotNull(nestedMessage); Assert.assertNotNull(foreignMessage); - Assert.assertNotNull(importMessage ); - Assert.assertNotNull(nestedEnum ); - Assert.assertNotNull(foreignEnum ); - Assert.assertNotNull(importEnum ); + Assert.assertNotNull(importMessage); + Assert.assertNotNull(nestedEnum); + Assert.assertNotNull(foreignEnum); + Assert.assertNotNull(importEnum); - this.nestedB = nestedMessage .findFieldByName("bb"); + this.nestedB = nestedMessage.findFieldByName("bb"); this.foreignC = foreignMessage.findFieldByName("c"); - this.importD = importMessage .findFieldByName("d"); - this.importE = publicImportMessage.findFieldByName("e"); + this.importD = importMessage.findFieldByName("d"); + this.importE = publicImportMessage.findFieldByName("e"); this.nestedFoo = nestedEnum.findValueByName("FOO"); this.nestedBar = nestedEnum.findValueByName("BAR"); this.nestedBaz = nestedEnum.findValueByName("BAZ"); @@ -2751,27 +2758,25 @@ public ReflectionTester(Descriptors.Descriptor baseDescriptor, this.groupA = optionalGroup.findFieldByName("a"); this.repeatedGroupA = repeatedGroup.findFieldByName("a"); - Assert.assertNotNull(groupA ); + Assert.assertNotNull(groupA); Assert.assertNotNull(repeatedGroupA); - Assert.assertNotNull(nestedB ); - Assert.assertNotNull(foreignC ); - Assert.assertNotNull(importD ); - Assert.assertNotNull(importE ); - Assert.assertNotNull(nestedFoo ); - Assert.assertNotNull(nestedBar ); - Assert.assertNotNull(nestedBaz ); - Assert.assertNotNull(foreignFoo ); - Assert.assertNotNull(foreignBar ); - Assert.assertNotNull(foreignBaz ); - Assert.assertNotNull(importFoo ); - Assert.assertNotNull(importBar ); - Assert.assertNotNull(importBaz ); + Assert.assertNotNull(nestedB); + Assert.assertNotNull(foreignC); + Assert.assertNotNull(importD); + Assert.assertNotNull(importE); + Assert.assertNotNull(nestedFoo); + Assert.assertNotNull(nestedBar); + Assert.assertNotNull(nestedBaz); + Assert.assertNotNull(foreignFoo); + Assert.assertNotNull(foreignBar); + Assert.assertNotNull(foreignBaz); + Assert.assertNotNull(importFoo); + Assert.assertNotNull(importBar); + Assert.assertNotNull(importBaz); } - /** - * Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes. - */ - private Descriptors.FieldDescriptor f(String name) { + /** Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes. */ + Descriptors.FieldDescriptor f(String name) { Descriptors.FieldDescriptor result; if (extensionRegistry == null) { result = baseDescriptor.findFieldByName(name); @@ -2783,9 +2788,8 @@ private Descriptors.FieldDescriptor f(String name) { } /** - * Calls {@code parent.newBuilderForField()} or uses the - * {@code ExtensionRegistry} to find an appropriate builder, depending - * on what type is being tested. + * Calls {@code parent.newBuilderForField()} or uses the {@code ExtensionRegistry} to find an + * appropriate builder, depending on what type is being tested. */ private Message.Builder newBuilderForField( Message.Builder parent, Descriptors.FieldDescriptor field) { @@ -2793,8 +2797,8 @@ private Message.Builder newBuilderForField( return parent.newBuilderForField(field); } else { ExtensionRegistry.ExtensionInfo extension = - extensionRegistry.findImmutableExtensionByNumber( - field.getContainingType(), field.getNumber()); + extensionRegistry.findImmutableExtensionByNumber( + field.getContainingType(), field.getNumber()); Assert.assertNotNull(extension); Assert.assertNotNull(extension.defaultInstance); return extension.defaultInstance.newBuilderForType(); @@ -2804,210 +2808,223 @@ private Message.Builder newBuilderForField( // ------------------------------------------------------------------- /** - * Set every field of {@code message} to the values expected by - * {@code assertAllFieldsSet()}, using the {@link Message.Builder} - * reflection interface. + * Set every field of {@code message} to the values expected by {@code assertAllFieldsSet()}, + * using the {@link Message.Builder} reflection interface. */ void setAllFieldsViaReflection(Message.Builder message) { - message.setField(f("optional_int32" ), 101 ); - message.setField(f("optional_int64" ), 102L); - message.setField(f("optional_uint32" ), 103 ); - message.setField(f("optional_uint64" ), 104L); - message.setField(f("optional_sint32" ), 105 ); - message.setField(f("optional_sint64" ), 106L); - message.setField(f("optional_fixed32" ), 107 ); - message.setField(f("optional_fixed64" ), 108L); - message.setField(f("optional_sfixed32"), 109 ); + message.setField(f("optional_int32"), 101); + message.setField(f("optional_int64"), 102L); + message.setField(f("optional_uint32"), 103); + message.setField(f("optional_uint64"), 104L); + message.setField(f("optional_sint32"), 105); + message.setField(f("optional_sint64"), 106L); + message.setField(f("optional_fixed32"), 107); + message.setField(f("optional_fixed64"), 108L); + message.setField(f("optional_sfixed32"), 109); message.setField(f("optional_sfixed64"), 110L); - message.setField(f("optional_float" ), 111F); - message.setField(f("optional_double" ), 112D); - message.setField(f("optional_bool" ), true); - message.setField(f("optional_string" ), "115"); - message.setField(f("optional_bytes" ), toBytes("116")); - - message.setField(f("optionalgroup"), - newBuilderForField(message, f("optionalgroup")) - .setField(groupA, 117).build()); - message.setField(f("optional_nested_message"), - newBuilderForField(message, f("optional_nested_message")) - .setField(nestedB, 118).build()); - message.setField(f("optional_foreign_message"), - newBuilderForField(message, f("optional_foreign_message")) - .setField(foreignC, 119).build()); - message.setField(f("optional_import_message"), - newBuilderForField(message, f("optional_import_message")) - .setField(importD, 120).build()); - message.setField(f("optional_public_import_message"), - newBuilderForField(message, f("optional_public_import_message")) - .setField(importE, 126).build()); - message.setField(f("optional_lazy_message"), - newBuilderForField(message, f("optional_lazy_message")) - .setField(nestedB, 127).build()); - - message.setField(f("optional_nested_enum" ), nestedBaz); + message.setField(f("optional_float"), 111F); + message.setField(f("optional_double"), 112D); + message.setField(f("optional_bool"), true); + message.setField(f("optional_string"), "115"); + message.setField(f("optional_bytes"), toBytes("116")); + + message.setField( + f("optionalgroup"), + newBuilderForField(message, f("optionalgroup")).setField(groupA, 117).build()); + message.setField( + f("optional_nested_message"), + newBuilderForField(message, f("optional_nested_message")).setField(nestedB, 118).build()); + message.setField( + f("optional_foreign_message"), + newBuilderForField(message, f("optional_foreign_message")) + .setField(foreignC, 119) + .build()); + message.setField( + f("optional_import_message"), + newBuilderForField(message, f("optional_import_message")).setField(importD, 120).build()); + message.setField( + f("optional_public_import_message"), + newBuilderForField(message, f("optional_public_import_message")) + .setField(importE, 126) + .build()); + message.setField( + f("optional_lazy_message"), + newBuilderForField(message, f("optional_lazy_message")).setField(nestedB, 127).build()); + + message.setField(f("optional_nested_enum"), nestedBaz); message.setField(f("optional_foreign_enum"), foreignBaz); - message.setField(f("optional_import_enum" ), importBaz); + message.setField(f("optional_import_enum"), importBaz); - message.setField(f("optional_string_piece" ), "124"); - message.setField(f("optional_cord" ), "125"); + message.setField(f("optional_string_piece"), "124"); + message.setField(f("optional_cord"), "125"); // ----------------------------------------------------------------- - message.addRepeatedField(f("repeated_int32" ), 201 ); - message.addRepeatedField(f("repeated_int64" ), 202L); - message.addRepeatedField(f("repeated_uint32" ), 203 ); - message.addRepeatedField(f("repeated_uint64" ), 204L); - message.addRepeatedField(f("repeated_sint32" ), 205 ); - message.addRepeatedField(f("repeated_sint64" ), 206L); - message.addRepeatedField(f("repeated_fixed32" ), 207 ); - message.addRepeatedField(f("repeated_fixed64" ), 208L); - message.addRepeatedField(f("repeated_sfixed32"), 209 ); + message.addRepeatedField(f("repeated_int32"), 201); + message.addRepeatedField(f("repeated_int64"), 202L); + message.addRepeatedField(f("repeated_uint32"), 203); + message.addRepeatedField(f("repeated_uint64"), 204L); + message.addRepeatedField(f("repeated_sint32"), 205); + message.addRepeatedField(f("repeated_sint64"), 206L); + message.addRepeatedField(f("repeated_fixed32"), 207); + message.addRepeatedField(f("repeated_fixed64"), 208L); + message.addRepeatedField(f("repeated_sfixed32"), 209); message.addRepeatedField(f("repeated_sfixed64"), 210L); - message.addRepeatedField(f("repeated_float" ), 211F); - message.addRepeatedField(f("repeated_double" ), 212D); - message.addRepeatedField(f("repeated_bool" ), true); - message.addRepeatedField(f("repeated_string" ), "215"); - message.addRepeatedField(f("repeated_bytes" ), toBytes("216")); - - message.addRepeatedField(f("repeatedgroup"), - newBuilderForField(message, f("repeatedgroup")) - .setField(repeatedGroupA, 217).build()); - message.addRepeatedField(f("repeated_nested_message"), - newBuilderForField(message, f("repeated_nested_message")) - .setField(nestedB, 218).build()); - message.addRepeatedField(f("repeated_foreign_message"), - newBuilderForField(message, f("repeated_foreign_message")) - .setField(foreignC, 219).build()); - message.addRepeatedField(f("repeated_import_message"), - newBuilderForField(message, f("repeated_import_message")) - .setField(importD, 220).build()); - message.addRepeatedField(f("repeated_lazy_message"), - newBuilderForField(message, f("repeated_lazy_message")) - .setField(nestedB, 227).build()); - - message.addRepeatedField(f("repeated_nested_enum" ), nestedBar); + message.addRepeatedField(f("repeated_float"), 211F); + message.addRepeatedField(f("repeated_double"), 212D); + message.addRepeatedField(f("repeated_bool"), true); + message.addRepeatedField(f("repeated_string"), "215"); + message.addRepeatedField(f("repeated_bytes"), toBytes("216")); + + message.addRepeatedField( + f("repeatedgroup"), + newBuilderForField(message, f("repeatedgroup")).setField(repeatedGroupA, 217).build()); + message.addRepeatedField( + f("repeated_nested_message"), + newBuilderForField(message, f("repeated_nested_message")).setField(nestedB, 218).build()); + message.addRepeatedField( + f("repeated_foreign_message"), + newBuilderForField(message, f("repeated_foreign_message")) + .setField(foreignC, 219) + .build()); + message.addRepeatedField( + f("repeated_import_message"), + newBuilderForField(message, f("repeated_import_message")).setField(importD, 220).build()); + message.addRepeatedField( + f("repeated_lazy_message"), + newBuilderForField(message, f("repeated_lazy_message")).setField(nestedB, 227).build()); + + message.addRepeatedField(f("repeated_nested_enum"), nestedBar); message.addRepeatedField(f("repeated_foreign_enum"), foreignBar); - message.addRepeatedField(f("repeated_import_enum" ), importBar); + message.addRepeatedField(f("repeated_import_enum"), importBar); - message.addRepeatedField(f("repeated_string_piece" ), "224"); - message.addRepeatedField(f("repeated_cord" ), "225"); + message.addRepeatedField(f("repeated_string_piece"), "224"); + message.addRepeatedField(f("repeated_cord"), "225"); // Add a second one of each field. - message.addRepeatedField(f("repeated_int32" ), 301 ); - message.addRepeatedField(f("repeated_int64" ), 302L); - message.addRepeatedField(f("repeated_uint32" ), 303 ); - message.addRepeatedField(f("repeated_uint64" ), 304L); - message.addRepeatedField(f("repeated_sint32" ), 305 ); - message.addRepeatedField(f("repeated_sint64" ), 306L); - message.addRepeatedField(f("repeated_fixed32" ), 307 ); - message.addRepeatedField(f("repeated_fixed64" ), 308L); - message.addRepeatedField(f("repeated_sfixed32"), 309 ); + message.addRepeatedField(f("repeated_int32"), 301); + message.addRepeatedField(f("repeated_int64"), 302L); + message.addRepeatedField(f("repeated_uint32"), 303); + message.addRepeatedField(f("repeated_uint64"), 304L); + message.addRepeatedField(f("repeated_sint32"), 305); + message.addRepeatedField(f("repeated_sint64"), 306L); + message.addRepeatedField(f("repeated_fixed32"), 307); + message.addRepeatedField(f("repeated_fixed64"), 308L); + message.addRepeatedField(f("repeated_sfixed32"), 309); message.addRepeatedField(f("repeated_sfixed64"), 310L); - message.addRepeatedField(f("repeated_float" ), 311F); - message.addRepeatedField(f("repeated_double" ), 312D); - message.addRepeatedField(f("repeated_bool" ), false); - message.addRepeatedField(f("repeated_string" ), "315"); - message.addRepeatedField(f("repeated_bytes" ), toBytes("316")); - - message.addRepeatedField(f("repeatedgroup"), - newBuilderForField(message, f("repeatedgroup")) - .setField(repeatedGroupA, 317).build()); - message.addRepeatedField(f("repeated_nested_message"), - newBuilderForField(message, f("repeated_nested_message")) - .setField(nestedB, 318).build()); - message.addRepeatedField(f("repeated_foreign_message"), - newBuilderForField(message, f("repeated_foreign_message")) - .setField(foreignC, 319).build()); - message.addRepeatedField(f("repeated_import_message"), - newBuilderForField(message, f("repeated_import_message")) - .setField(importD, 320).build()); - message.addRepeatedField(f("repeated_lazy_message"), - newBuilderForField(message, f("repeated_lazy_message")) - .setField(nestedB, 327).build()); - - message.addRepeatedField(f("repeated_nested_enum" ), nestedBaz); + message.addRepeatedField(f("repeated_float"), 311F); + message.addRepeatedField(f("repeated_double"), 312D); + message.addRepeatedField(f("repeated_bool"), false); + message.addRepeatedField(f("repeated_string"), "315"); + message.addRepeatedField(f("repeated_bytes"), toBytes("316")); + + message.addRepeatedField( + f("repeatedgroup"), + newBuilderForField(message, f("repeatedgroup")).setField(repeatedGroupA, 317).build()); + message.addRepeatedField( + f("repeated_nested_message"), + newBuilderForField(message, f("repeated_nested_message")).setField(nestedB, 318).build()); + message.addRepeatedField( + f("repeated_foreign_message"), + newBuilderForField(message, f("repeated_foreign_message")) + .setField(foreignC, 319) + .build()); + message.addRepeatedField( + f("repeated_import_message"), + newBuilderForField(message, f("repeated_import_message")).setField(importD, 320).build()); + message.addRepeatedField( + f("repeated_lazy_message"), + newBuilderForField(message, f("repeated_lazy_message")).setField(nestedB, 327).build()); + + message.addRepeatedField(f("repeated_nested_enum"), nestedBaz); message.addRepeatedField(f("repeated_foreign_enum"), foreignBaz); - message.addRepeatedField(f("repeated_import_enum" ), importBaz); + message.addRepeatedField(f("repeated_import_enum"), importBaz); - message.addRepeatedField(f("repeated_string_piece" ), "324"); - message.addRepeatedField(f("repeated_cord" ), "325"); + message.addRepeatedField(f("repeated_string_piece"), "324"); + message.addRepeatedField(f("repeated_cord"), "325"); // ----------------------------------------------------------------- - message.setField(f("default_int32" ), 401 ); - message.setField(f("default_int64" ), 402L); - message.setField(f("default_uint32" ), 403 ); - message.setField(f("default_uint64" ), 404L); - message.setField(f("default_sint32" ), 405 ); - message.setField(f("default_sint64" ), 406L); - message.setField(f("default_fixed32" ), 407 ); - message.setField(f("default_fixed64" ), 408L); - message.setField(f("default_sfixed32"), 409 ); + message.setField(f("default_int32"), 401); + message.setField(f("default_int64"), 402L); + message.setField(f("default_uint32"), 403); + message.setField(f("default_uint64"), 404L); + message.setField(f("default_sint32"), 405); + message.setField(f("default_sint64"), 406L); + message.setField(f("default_fixed32"), 407); + message.setField(f("default_fixed64"), 408L); + message.setField(f("default_sfixed32"), 409); message.setField(f("default_sfixed64"), 410L); - message.setField(f("default_float" ), 411F); - message.setField(f("default_double" ), 412D); - message.setField(f("default_bool" ), false); - message.setField(f("default_string" ), "415"); - message.setField(f("default_bytes" ), toBytes("416")); + message.setField(f("default_float"), 411F); + message.setField(f("default_double"), 412D); + message.setField(f("default_bool"), false); + message.setField(f("default_string"), "415"); + message.setField(f("default_bytes"), toBytes("416")); - message.setField(f("default_nested_enum" ), nestedFoo); + message.setField(f("default_nested_enum"), nestedFoo); message.setField(f("default_foreign_enum"), foreignFoo); - message.setField(f("default_import_enum" ), importFoo); + message.setField(f("default_import_enum"), importFoo); - message.setField(f("default_string_piece" ), "424"); - message.setField(f("default_cord" ), "425"); + message.setField(f("default_string_piece"), "424"); + message.setField(f("default_cord"), "425"); - message.setField(f("oneof_uint32" ), 601); - message.setField(f("oneof_nested_message"), - newBuilderForField(message, f("oneof_nested_message")) - .setField(nestedB, 602).build()); - message.setField(f("oneof_string" ), "603"); - message.setField(f("oneof_bytes" ), toBytes("604")); + message.setField(f("oneof_uint32"), 601); + message.setField( + f("oneof_nested_message"), + newBuilderForField(message, f("oneof_nested_message")).setField(nestedB, 602).build()); + message.setField(f("oneof_string"), "603"); + message.setField(f("oneof_bytes"), toBytes("604")); } // ------------------------------------------------------------------- /** - * Modify the repeated fields of {@code message} to contain the values - * expected by {@code assertRepeatedFieldsModified()}, using the - * {@link Message.Builder} reflection interface. + * Modify the repeated fields of {@code message} to contain the values expected by {@code + * assertRepeatedFieldsModified()}, using the {@link Message.Builder} reflection interface. */ void modifyRepeatedFieldsViaReflection(Message.Builder message) { - message.setRepeatedField(f("repeated_int32" ), 1, 501 ); - message.setRepeatedField(f("repeated_int64" ), 1, 502L); - message.setRepeatedField(f("repeated_uint32" ), 1, 503 ); - message.setRepeatedField(f("repeated_uint64" ), 1, 504L); - message.setRepeatedField(f("repeated_sint32" ), 1, 505 ); - message.setRepeatedField(f("repeated_sint64" ), 1, 506L); - message.setRepeatedField(f("repeated_fixed32" ), 1, 507 ); - message.setRepeatedField(f("repeated_fixed64" ), 1, 508L); - message.setRepeatedField(f("repeated_sfixed32"), 1, 509 ); + message.setRepeatedField(f("repeated_int32"), 1, 501); + message.setRepeatedField(f("repeated_int64"), 1, 502L); + message.setRepeatedField(f("repeated_uint32"), 1, 503); + message.setRepeatedField(f("repeated_uint64"), 1, 504L); + message.setRepeatedField(f("repeated_sint32"), 1, 505); + message.setRepeatedField(f("repeated_sint64"), 1, 506L); + message.setRepeatedField(f("repeated_fixed32"), 1, 507); + message.setRepeatedField(f("repeated_fixed64"), 1, 508L); + message.setRepeatedField(f("repeated_sfixed32"), 1, 509); message.setRepeatedField(f("repeated_sfixed64"), 1, 510L); - message.setRepeatedField(f("repeated_float" ), 1, 511F); - message.setRepeatedField(f("repeated_double" ), 1, 512D); - message.setRepeatedField(f("repeated_bool" ), 1, true); - message.setRepeatedField(f("repeated_string" ), 1, "515"); - message.setRepeatedField(f("repeated_bytes" ), 1, toBytes("516")); - - message.setRepeatedField(f("repeatedgroup"), 1, - newBuilderForField(message, f("repeatedgroup")) - .setField(repeatedGroupA, 517).build()); - message.setRepeatedField(f("repeated_nested_message"), 1, - newBuilderForField(message, f("repeated_nested_message")) - .setField(nestedB, 518).build()); - message.setRepeatedField(f("repeated_foreign_message"), 1, - newBuilderForField(message, f("repeated_foreign_message")) - .setField(foreignC, 519).build()); - message.setRepeatedField(f("repeated_import_message"), 1, - newBuilderForField(message, f("repeated_import_message")) - .setField(importD, 520).build()); - message.setRepeatedField(f("repeated_lazy_message"), 1, - newBuilderForField(message, f("repeated_lazy_message")) - .setField(nestedB, 527).build()); - - message.setRepeatedField(f("repeated_nested_enum" ), 1, nestedFoo); + message.setRepeatedField(f("repeated_float"), 1, 511F); + message.setRepeatedField(f("repeated_double"), 1, 512D); + message.setRepeatedField(f("repeated_bool"), 1, true); + message.setRepeatedField(f("repeated_string"), 1, "515"); + message.setRepeatedField(f("repeated_bytes"), 1, toBytes("516")); + + message.setRepeatedField( + f("repeatedgroup"), + 1, + newBuilderForField(message, f("repeatedgroup")).setField(repeatedGroupA, 517).build()); + message.setRepeatedField( + f("repeated_nested_message"), + 1, + newBuilderForField(message, f("repeated_nested_message")).setField(nestedB, 518).build()); + message.setRepeatedField( + f("repeated_foreign_message"), + 1, + newBuilderForField(message, f("repeated_foreign_message")) + .setField(foreignC, 519) + .build()); + message.setRepeatedField( + f("repeated_import_message"), + 1, + newBuilderForField(message, f("repeated_import_message")).setField(importD, 520).build()); + message.setRepeatedField( + f("repeated_lazy_message"), + 1, + newBuilderForField(message, f("repeated_lazy_message")).setField(nestedB, 527).build()); + + message.setRepeatedField(f("repeated_nested_enum"), 1, nestedFoo); message.setRepeatedField(f("repeated_foreign_enum"), 1, foreignFoo); - message.setRepeatedField(f("repeated_import_enum" ), 1, importFoo); + message.setRepeatedField(f("repeated_import_enum"), 1, importFoo); message.setRepeatedField(f("repeated_string_piece"), 1, "524"); message.setRepeatedField(f("repeated_cord"), 1, "525"); @@ -3016,244 +3033,235 @@ void modifyRepeatedFieldsViaReflection(Message.Builder message) { // ------------------------------------------------------------------- /** - * Assert (using {@code junit.framework.Assert}} that all fields of - * {@code message} are set to the values assigned by {@code setAllFields}, - * using the {@link Message} reflection interface. + * Assert (using {@code junit.framework.Assert}} that all fields of {@code message} are set to + * the values assigned by {@code setAllFields}, using the {@link Message} reflection interface. */ public void assertAllFieldsSetViaReflection(MessageOrBuilder message) { - Assert.assertTrue(message.hasField(f("optional_int32" ))); - Assert.assertTrue(message.hasField(f("optional_int64" ))); - Assert.assertTrue(message.hasField(f("optional_uint32" ))); - Assert.assertTrue(message.hasField(f("optional_uint64" ))); - Assert.assertTrue(message.hasField(f("optional_sint32" ))); - Assert.assertTrue(message.hasField(f("optional_sint64" ))); - Assert.assertTrue(message.hasField(f("optional_fixed32" ))); - Assert.assertTrue(message.hasField(f("optional_fixed64" ))); + Assert.assertTrue(message.hasField(f("optional_int32"))); + Assert.assertTrue(message.hasField(f("optional_int64"))); + Assert.assertTrue(message.hasField(f("optional_uint32"))); + Assert.assertTrue(message.hasField(f("optional_uint64"))); + Assert.assertTrue(message.hasField(f("optional_sint32"))); + Assert.assertTrue(message.hasField(f("optional_sint64"))); + Assert.assertTrue(message.hasField(f("optional_fixed32"))); + Assert.assertTrue(message.hasField(f("optional_fixed64"))); Assert.assertTrue(message.hasField(f("optional_sfixed32"))); Assert.assertTrue(message.hasField(f("optional_sfixed64"))); - Assert.assertTrue(message.hasField(f("optional_float" ))); - Assert.assertTrue(message.hasField(f("optional_double" ))); - Assert.assertTrue(message.hasField(f("optional_bool" ))); - Assert.assertTrue(message.hasField(f("optional_string" ))); - Assert.assertTrue(message.hasField(f("optional_bytes" ))); - - Assert.assertTrue(message.hasField(f("optionalgroup" ))); - Assert.assertTrue(message.hasField(f("optional_nested_message" ))); + Assert.assertTrue(message.hasField(f("optional_float"))); + Assert.assertTrue(message.hasField(f("optional_double"))); + Assert.assertTrue(message.hasField(f("optional_bool"))); + Assert.assertTrue(message.hasField(f("optional_string"))); + Assert.assertTrue(message.hasField(f("optional_bytes"))); + + Assert.assertTrue(message.hasField(f("optionalgroup"))); + Assert.assertTrue(message.hasField(f("optional_nested_message"))); Assert.assertTrue(message.hasField(f("optional_foreign_message"))); - Assert.assertTrue(message.hasField(f("optional_import_message" ))); + Assert.assertTrue(message.hasField(f("optional_import_message"))); + Assert.assertTrue(((Message) message.getField(f("optionalgroup"))).hasField(groupA)); Assert.assertTrue( - ((Message)message.getField(f("optionalgroup"))).hasField(groupA)); + ((Message) message.getField(f("optional_nested_message"))).hasField(nestedB)); Assert.assertTrue( - ((Message)message.getField(f("optional_nested_message"))) - .hasField(nestedB)); + ((Message) message.getField(f("optional_foreign_message"))).hasField(foreignC)); Assert.assertTrue( - ((Message)message.getField(f("optional_foreign_message"))) - .hasField(foreignC)); - Assert.assertTrue( - ((Message)message.getField(f("optional_import_message"))) - .hasField(importD)); + ((Message) message.getField(f("optional_import_message"))).hasField(importD)); - Assert.assertTrue(message.hasField(f("optional_nested_enum" ))); + Assert.assertTrue(message.hasField(f("optional_nested_enum"))); Assert.assertTrue(message.hasField(f("optional_foreign_enum"))); - Assert.assertTrue(message.hasField(f("optional_import_enum" ))); + Assert.assertTrue(message.hasField(f("optional_import_enum"))); Assert.assertTrue(message.hasField(f("optional_string_piece"))); Assert.assertTrue(message.hasField(f("optional_cord"))); - Assert.assertEquals(101 , message.getField(f("optional_int32" ))); - Assert.assertEquals(102L , message.getField(f("optional_int64" ))); - Assert.assertEquals(103 , message.getField(f("optional_uint32" ))); - Assert.assertEquals(104L , message.getField(f("optional_uint64" ))); - Assert.assertEquals(105 , message.getField(f("optional_sint32" ))); - Assert.assertEquals(106L , message.getField(f("optional_sint64" ))); - Assert.assertEquals(107 , message.getField(f("optional_fixed32" ))); - Assert.assertEquals(108L , message.getField(f("optional_fixed64" ))); - Assert.assertEquals(109 , message.getField(f("optional_sfixed32"))); - Assert.assertEquals(110L , message.getField(f("optional_sfixed64"))); - Assert.assertEquals(111F , message.getField(f("optional_float" ))); - Assert.assertEquals(112D , message.getField(f("optional_double" ))); - Assert.assertEquals(true , message.getField(f("optional_bool" ))); - Assert.assertEquals("115", message.getField(f("optional_string" ))); + Assert.assertEquals(101, message.getField(f("optional_int32"))); + Assert.assertEquals(102L, message.getField(f("optional_int64"))); + Assert.assertEquals(103, message.getField(f("optional_uint32"))); + Assert.assertEquals(104L, message.getField(f("optional_uint64"))); + Assert.assertEquals(105, message.getField(f("optional_sint32"))); + Assert.assertEquals(106L, message.getField(f("optional_sint64"))); + Assert.assertEquals(107, message.getField(f("optional_fixed32"))); + Assert.assertEquals(108L, message.getField(f("optional_fixed64"))); + Assert.assertEquals(109, message.getField(f("optional_sfixed32"))); + Assert.assertEquals(110L, message.getField(f("optional_sfixed64"))); + Assert.assertEquals(111F, message.getField(f("optional_float"))); + Assert.assertEquals(112D, message.getField(f("optional_double"))); + Assert.assertEquals(true, message.getField(f("optional_bool"))); + Assert.assertEquals("115", message.getField(f("optional_string"))); Assert.assertEquals(toBytes("116"), message.getField(f("optional_bytes"))); - Assert.assertEquals(117, - ((Message)message.getField(f("optionalgroup"))).getField(groupA)); - Assert.assertEquals(118, - ((Message)message.getField(f("optional_nested_message"))) - .getField(nestedB)); - Assert.assertEquals(119, - ((Message)message.getField(f("optional_foreign_message"))) - .getField(foreignC)); - Assert.assertEquals(120, - ((Message)message.getField(f("optional_import_message"))) - .getField(importD)); - Assert.assertEquals(126, - ((Message)message.getField(f("optional_public_import_message"))) - .getField(importE)); - Assert.assertEquals(127, - ((Message)message.getField(f("optional_lazy_message"))) - .getField(nestedB)); - - Assert.assertEquals( nestedBaz, message.getField(f("optional_nested_enum" ))); + Assert.assertEquals(117, ((Message) message.getField(f("optionalgroup"))).getField(groupA)); + Assert.assertEquals( + 118, ((Message) message.getField(f("optional_nested_message"))).getField(nestedB)); + Assert.assertEquals( + 119, ((Message) message.getField(f("optional_foreign_message"))).getField(foreignC)); + Assert.assertEquals( + 120, ((Message) message.getField(f("optional_import_message"))).getField(importD)); + Assert.assertEquals( + 126, ((Message) message.getField(f("optional_public_import_message"))).getField(importE)); + Assert.assertEquals( + 127, ((Message) message.getField(f("optional_lazy_message"))).getField(nestedB)); + + Assert.assertEquals(nestedBaz, message.getField(f("optional_nested_enum"))); Assert.assertEquals(foreignBaz, message.getField(f("optional_foreign_enum"))); - Assert.assertEquals( importBaz, message.getField(f("optional_import_enum" ))); + Assert.assertEquals(importBaz, message.getField(f("optional_import_enum"))); Assert.assertEquals("124", message.getField(f("optional_string_piece"))); Assert.assertEquals("125", message.getField(f("optional_cord"))); // ----------------------------------------------------------------- - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int32" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int64" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint32" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint64" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint32" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint64" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed32" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed64" ))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int32"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int64"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint32"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint64"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint32"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint64"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed32"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed64"))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed32"))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed64"))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_float" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_double" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bool" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bytes" ))); - - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeatedgroup" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" ))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_float"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_double"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bool"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bytes"))); + + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeatedgroup"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message"))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message"))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum" ))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum"))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string_piece"))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_cord"))); - Assert.assertEquals(201 , message.getRepeatedField(f("repeated_int32" ), 0)); - Assert.assertEquals(202L , message.getRepeatedField(f("repeated_int64" ), 0)); - Assert.assertEquals(203 , message.getRepeatedField(f("repeated_uint32" ), 0)); - Assert.assertEquals(204L , message.getRepeatedField(f("repeated_uint64" ), 0)); - Assert.assertEquals(205 , message.getRepeatedField(f("repeated_sint32" ), 0)); - Assert.assertEquals(206L , message.getRepeatedField(f("repeated_sint64" ), 0)); - Assert.assertEquals(207 , message.getRepeatedField(f("repeated_fixed32" ), 0)); - Assert.assertEquals(208L , message.getRepeatedField(f("repeated_fixed64" ), 0)); - Assert.assertEquals(209 , message.getRepeatedField(f("repeated_sfixed32"), 0)); - Assert.assertEquals(210L , message.getRepeatedField(f("repeated_sfixed64"), 0)); - Assert.assertEquals(211F , message.getRepeatedField(f("repeated_float" ), 0)); - Assert.assertEquals(212D , message.getRepeatedField(f("repeated_double" ), 0)); - Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool" ), 0)); - Assert.assertEquals("215", message.getRepeatedField(f("repeated_string" ), 0)); + Assert.assertEquals(201, message.getRepeatedField(f("repeated_int32"), 0)); + Assert.assertEquals(202L, message.getRepeatedField(f("repeated_int64"), 0)); + Assert.assertEquals(203, message.getRepeatedField(f("repeated_uint32"), 0)); + Assert.assertEquals(204L, message.getRepeatedField(f("repeated_uint64"), 0)); + Assert.assertEquals(205, message.getRepeatedField(f("repeated_sint32"), 0)); + Assert.assertEquals(206L, message.getRepeatedField(f("repeated_sint64"), 0)); + Assert.assertEquals(207, message.getRepeatedField(f("repeated_fixed32"), 0)); + Assert.assertEquals(208L, message.getRepeatedField(f("repeated_fixed64"), 0)); + Assert.assertEquals(209, message.getRepeatedField(f("repeated_sfixed32"), 0)); + Assert.assertEquals(210L, message.getRepeatedField(f("repeated_sfixed64"), 0)); + Assert.assertEquals(211F, message.getRepeatedField(f("repeated_float"), 0)); + Assert.assertEquals(212D, message.getRepeatedField(f("repeated_double"), 0)); + Assert.assertEquals(true, message.getRepeatedField(f("repeated_bool"), 0)); + Assert.assertEquals("215", message.getRepeatedField(f("repeated_string"), 0)); Assert.assertEquals(toBytes("216"), message.getRepeatedField(f("repeated_bytes"), 0)); - Assert.assertEquals(217, - ((Message)message.getRepeatedField(f("repeatedgroup"), 0)) - .getField(repeatedGroupA)); - Assert.assertEquals(218, - ((Message)message.getRepeatedField(f("repeated_nested_message"), 0)) - .getField(nestedB)); - Assert.assertEquals(219, - ((Message)message.getRepeatedField(f("repeated_foreign_message"), 0)) - .getField(foreignC)); - Assert.assertEquals(220, - ((Message)message.getRepeatedField(f("repeated_import_message"), 0)) - .getField(importD)); - Assert.assertEquals(227, - ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0)) - .getField(nestedB)); - - Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0)); - Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0)); - Assert.assertEquals( importBar, message.getRepeatedField(f("repeated_import_enum" ),0)); + Assert.assertEquals( + 217, + ((Message) message.getRepeatedField(f("repeatedgroup"), 0)).getField(repeatedGroupA)); + Assert.assertEquals( + 218, + ((Message) message.getRepeatedField(f("repeated_nested_message"), 0)).getField(nestedB)); + Assert.assertEquals( + 219, + ((Message) message.getRepeatedField(f("repeated_foreign_message"), 0)) + .getField(foreignC)); + Assert.assertEquals( + 220, + ((Message) message.getRepeatedField(f("repeated_import_message"), 0)).getField(importD)); + Assert.assertEquals( + 227, + ((Message) message.getRepeatedField(f("repeated_lazy_message"), 0)).getField(nestedB)); + + Assert.assertEquals(nestedBar, message.getRepeatedField(f("repeated_nested_enum"), 0)); + Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"), 0)); + Assert.assertEquals(importBar, message.getRepeatedField(f("repeated_import_enum"), 0)); Assert.assertEquals("224", message.getRepeatedField(f("repeated_string_piece"), 0)); Assert.assertEquals("225", message.getRepeatedField(f("repeated_cord"), 0)); - Assert.assertEquals(301 , message.getRepeatedField(f("repeated_int32" ), 1)); - Assert.assertEquals(302L , message.getRepeatedField(f("repeated_int64" ), 1)); - Assert.assertEquals(303 , message.getRepeatedField(f("repeated_uint32" ), 1)); - Assert.assertEquals(304L , message.getRepeatedField(f("repeated_uint64" ), 1)); - Assert.assertEquals(305 , message.getRepeatedField(f("repeated_sint32" ), 1)); - Assert.assertEquals(306L , message.getRepeatedField(f("repeated_sint64" ), 1)); - Assert.assertEquals(307 , message.getRepeatedField(f("repeated_fixed32" ), 1)); - Assert.assertEquals(308L , message.getRepeatedField(f("repeated_fixed64" ), 1)); - Assert.assertEquals(309 , message.getRepeatedField(f("repeated_sfixed32"), 1)); - Assert.assertEquals(310L , message.getRepeatedField(f("repeated_sfixed64"), 1)); - Assert.assertEquals(311F , message.getRepeatedField(f("repeated_float" ), 1)); - Assert.assertEquals(312D , message.getRepeatedField(f("repeated_double" ), 1)); - Assert.assertEquals(false, message.getRepeatedField(f("repeated_bool" ), 1)); - Assert.assertEquals("315", message.getRepeatedField(f("repeated_string" ), 1)); + Assert.assertEquals(301, message.getRepeatedField(f("repeated_int32"), 1)); + Assert.assertEquals(302L, message.getRepeatedField(f("repeated_int64"), 1)); + Assert.assertEquals(303, message.getRepeatedField(f("repeated_uint32"), 1)); + Assert.assertEquals(304L, message.getRepeatedField(f("repeated_uint64"), 1)); + Assert.assertEquals(305, message.getRepeatedField(f("repeated_sint32"), 1)); + Assert.assertEquals(306L, message.getRepeatedField(f("repeated_sint64"), 1)); + Assert.assertEquals(307, message.getRepeatedField(f("repeated_fixed32"), 1)); + Assert.assertEquals(308L, message.getRepeatedField(f("repeated_fixed64"), 1)); + Assert.assertEquals(309, message.getRepeatedField(f("repeated_sfixed32"), 1)); + Assert.assertEquals(310L, message.getRepeatedField(f("repeated_sfixed64"), 1)); + Assert.assertEquals(311F, message.getRepeatedField(f("repeated_float"), 1)); + Assert.assertEquals(312D, message.getRepeatedField(f("repeated_double"), 1)); + Assert.assertEquals(false, message.getRepeatedField(f("repeated_bool"), 1)); + Assert.assertEquals("315", message.getRepeatedField(f("repeated_string"), 1)); Assert.assertEquals(toBytes("316"), message.getRepeatedField(f("repeated_bytes"), 1)); - Assert.assertEquals(317, - ((Message)message.getRepeatedField(f("repeatedgroup"), 1)) - .getField(repeatedGroupA)); - Assert.assertEquals(318, - ((Message)message.getRepeatedField(f("repeated_nested_message"), 1)) - .getField(nestedB)); - Assert.assertEquals(319, - ((Message)message.getRepeatedField(f("repeated_foreign_message"), 1)) - .getField(foreignC)); - Assert.assertEquals(320, - ((Message)message.getRepeatedField(f("repeated_import_message"), 1)) - .getField(importD)); - Assert.assertEquals(327, - ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1)) - .getField(nestedB)); - - Assert.assertEquals( nestedBaz, message.getRepeatedField(f("repeated_nested_enum" ),1)); - Assert.assertEquals(foreignBaz, message.getRepeatedField(f("repeated_foreign_enum"),1)); - Assert.assertEquals( importBaz, message.getRepeatedField(f("repeated_import_enum" ),1)); + Assert.assertEquals( + 317, + ((Message) message.getRepeatedField(f("repeatedgroup"), 1)).getField(repeatedGroupA)); + Assert.assertEquals( + 318, + ((Message) message.getRepeatedField(f("repeated_nested_message"), 1)).getField(nestedB)); + Assert.assertEquals( + 319, + ((Message) message.getRepeatedField(f("repeated_foreign_message"), 1)) + .getField(foreignC)); + Assert.assertEquals( + 320, + ((Message) message.getRepeatedField(f("repeated_import_message"), 1)).getField(importD)); + Assert.assertEquals( + 327, + ((Message) message.getRepeatedField(f("repeated_lazy_message"), 1)).getField(nestedB)); + + Assert.assertEquals(nestedBaz, message.getRepeatedField(f("repeated_nested_enum"), 1)); + Assert.assertEquals(foreignBaz, message.getRepeatedField(f("repeated_foreign_enum"), 1)); + Assert.assertEquals(importBaz, message.getRepeatedField(f("repeated_import_enum"), 1)); Assert.assertEquals("324", message.getRepeatedField(f("repeated_string_piece"), 1)); Assert.assertEquals("325", message.getRepeatedField(f("repeated_cord"), 1)); // ----------------------------------------------------------------- - Assert.assertTrue(message.hasField(f("default_int32" ))); - Assert.assertTrue(message.hasField(f("default_int64" ))); - Assert.assertTrue(message.hasField(f("default_uint32" ))); - Assert.assertTrue(message.hasField(f("default_uint64" ))); - Assert.assertTrue(message.hasField(f("default_sint32" ))); - Assert.assertTrue(message.hasField(f("default_sint64" ))); - Assert.assertTrue(message.hasField(f("default_fixed32" ))); - Assert.assertTrue(message.hasField(f("default_fixed64" ))); + Assert.assertTrue(message.hasField(f("default_int32"))); + Assert.assertTrue(message.hasField(f("default_int64"))); + Assert.assertTrue(message.hasField(f("default_uint32"))); + Assert.assertTrue(message.hasField(f("default_uint64"))); + Assert.assertTrue(message.hasField(f("default_sint32"))); + Assert.assertTrue(message.hasField(f("default_sint64"))); + Assert.assertTrue(message.hasField(f("default_fixed32"))); + Assert.assertTrue(message.hasField(f("default_fixed64"))); Assert.assertTrue(message.hasField(f("default_sfixed32"))); Assert.assertTrue(message.hasField(f("default_sfixed64"))); - Assert.assertTrue(message.hasField(f("default_float" ))); - Assert.assertTrue(message.hasField(f("default_double" ))); - Assert.assertTrue(message.hasField(f("default_bool" ))); - Assert.assertTrue(message.hasField(f("default_string" ))); - Assert.assertTrue(message.hasField(f("default_bytes" ))); + Assert.assertTrue(message.hasField(f("default_float"))); + Assert.assertTrue(message.hasField(f("default_double"))); + Assert.assertTrue(message.hasField(f("default_bool"))); + Assert.assertTrue(message.hasField(f("default_string"))); + Assert.assertTrue(message.hasField(f("default_bytes"))); - Assert.assertTrue(message.hasField(f("default_nested_enum" ))); + Assert.assertTrue(message.hasField(f("default_nested_enum"))); Assert.assertTrue(message.hasField(f("default_foreign_enum"))); - Assert.assertTrue(message.hasField(f("default_import_enum" ))); + Assert.assertTrue(message.hasField(f("default_import_enum"))); Assert.assertTrue(message.hasField(f("default_string_piece"))); Assert.assertTrue(message.hasField(f("default_cord"))); - Assert.assertEquals(401 , message.getField(f("default_int32" ))); - Assert.assertEquals(402L , message.getField(f("default_int64" ))); - Assert.assertEquals(403 , message.getField(f("default_uint32" ))); - Assert.assertEquals(404L , message.getField(f("default_uint64" ))); - Assert.assertEquals(405 , message.getField(f("default_sint32" ))); - Assert.assertEquals(406L , message.getField(f("default_sint64" ))); - Assert.assertEquals(407 , message.getField(f("default_fixed32" ))); - Assert.assertEquals(408L , message.getField(f("default_fixed64" ))); - Assert.assertEquals(409 , message.getField(f("default_sfixed32"))); - Assert.assertEquals(410L , message.getField(f("default_sfixed64"))); - Assert.assertEquals(411F , message.getField(f("default_float" ))); - Assert.assertEquals(412D , message.getField(f("default_double" ))); - Assert.assertEquals(false, message.getField(f("default_bool" ))); - Assert.assertEquals("415", message.getField(f("default_string" ))); + Assert.assertEquals(401, message.getField(f("default_int32"))); + Assert.assertEquals(402L, message.getField(f("default_int64"))); + Assert.assertEquals(403, message.getField(f("default_uint32"))); + Assert.assertEquals(404L, message.getField(f("default_uint64"))); + Assert.assertEquals(405, message.getField(f("default_sint32"))); + Assert.assertEquals(406L, message.getField(f("default_sint64"))); + Assert.assertEquals(407, message.getField(f("default_fixed32"))); + Assert.assertEquals(408L, message.getField(f("default_fixed64"))); + Assert.assertEquals(409, message.getField(f("default_sfixed32"))); + Assert.assertEquals(410L, message.getField(f("default_sfixed64"))); + Assert.assertEquals(411F, message.getField(f("default_float"))); + Assert.assertEquals(412D, message.getField(f("default_double"))); + Assert.assertEquals(false, message.getField(f("default_bool"))); + Assert.assertEquals("415", message.getField(f("default_string"))); Assert.assertEquals(toBytes("416"), message.getField(f("default_bytes"))); - Assert.assertEquals( nestedFoo, message.getField(f("default_nested_enum" ))); + Assert.assertEquals(nestedFoo, message.getField(f("default_nested_enum"))); Assert.assertEquals(foreignFoo, message.getField(f("default_foreign_enum"))); - Assert.assertEquals( importFoo, message.getField(f("default_import_enum" ))); + Assert.assertEquals(importFoo, message.getField(f("default_import_enum"))); Assert.assertEquals("424", message.getField(f("default_string_piece"))); Assert.assertEquals("425", message.getField(f("default_cord"))); @@ -3270,9 +3278,9 @@ public void assertAllFieldsSetViaReflection(MessageOrBuilder message) { Assert.assertTrue(message.hasField(f("oneof_nested_message"))); Assert.assertTrue(message.hasField(f("oneof_string"))); Assert.assertEquals(601, message.getField(f("oneof_uint32"))); - Assert.assertEquals(602, - ((MessageOrBuilder) message.getField(f("oneof_nested_message"))) - .getField(nestedB)); + Assert.assertEquals( + 602, + ((MessageOrBuilder) message.getField(f("oneof_nested_message"))).getField(nestedB)); Assert.assertEquals("603", message.getField(f("oneof_string"))); } } @@ -3280,175 +3288,163 @@ public void assertAllFieldsSetViaReflection(MessageOrBuilder message) { // ------------------------------------------------------------------- /** - * Assert (using {@code junit.framework.Assert}} that all fields of - * {@code message} are cleared, and that getting the fields returns their - * default values, using the {@link Message} reflection interface. + * Assert (using {@code junit.framework.Assert}} that all fields of {@code message} are cleared, + * and that getting the fields returns their default values, using the {@link Message} + * reflection interface. */ public void assertClearViaReflection(MessageOrBuilder message) { // has_blah() should initially be false for all optional fields. - Assert.assertFalse(message.hasField(f("optional_int32" ))); - Assert.assertFalse(message.hasField(f("optional_int64" ))); - Assert.assertFalse(message.hasField(f("optional_uint32" ))); - Assert.assertFalse(message.hasField(f("optional_uint64" ))); - Assert.assertFalse(message.hasField(f("optional_sint32" ))); - Assert.assertFalse(message.hasField(f("optional_sint64" ))); - Assert.assertFalse(message.hasField(f("optional_fixed32" ))); - Assert.assertFalse(message.hasField(f("optional_fixed64" ))); + Assert.assertFalse(message.hasField(f("optional_int32"))); + Assert.assertFalse(message.hasField(f("optional_int64"))); + Assert.assertFalse(message.hasField(f("optional_uint32"))); + Assert.assertFalse(message.hasField(f("optional_uint64"))); + Assert.assertFalse(message.hasField(f("optional_sint32"))); + Assert.assertFalse(message.hasField(f("optional_sint64"))); + Assert.assertFalse(message.hasField(f("optional_fixed32"))); + Assert.assertFalse(message.hasField(f("optional_fixed64"))); Assert.assertFalse(message.hasField(f("optional_sfixed32"))); Assert.assertFalse(message.hasField(f("optional_sfixed64"))); - Assert.assertFalse(message.hasField(f("optional_float" ))); - Assert.assertFalse(message.hasField(f("optional_double" ))); - Assert.assertFalse(message.hasField(f("optional_bool" ))); - Assert.assertFalse(message.hasField(f("optional_string" ))); - Assert.assertFalse(message.hasField(f("optional_bytes" ))); - - Assert.assertFalse(message.hasField(f("optionalgroup" ))); - Assert.assertFalse(message.hasField(f("optional_nested_message" ))); + Assert.assertFalse(message.hasField(f("optional_float"))); + Assert.assertFalse(message.hasField(f("optional_double"))); + Assert.assertFalse(message.hasField(f("optional_bool"))); + Assert.assertFalse(message.hasField(f("optional_string"))); + Assert.assertFalse(message.hasField(f("optional_bytes"))); + + Assert.assertFalse(message.hasField(f("optionalgroup"))); + Assert.assertFalse(message.hasField(f("optional_nested_message"))); Assert.assertFalse(message.hasField(f("optional_foreign_message"))); - Assert.assertFalse(message.hasField(f("optional_import_message" ))); + Assert.assertFalse(message.hasField(f("optional_import_message"))); - Assert.assertFalse(message.hasField(f("optional_nested_enum" ))); + Assert.assertFalse(message.hasField(f("optional_nested_enum"))); Assert.assertFalse(message.hasField(f("optional_foreign_enum"))); - Assert.assertFalse(message.hasField(f("optional_import_enum" ))); + Assert.assertFalse(message.hasField(f("optional_import_enum"))); Assert.assertFalse(message.hasField(f("optional_string_piece"))); Assert.assertFalse(message.hasField(f("optional_cord"))); // Optional fields without defaults are set to zero or something like it. - Assert.assertEquals(0 , message.getField(f("optional_int32" ))); - Assert.assertEquals(0L , message.getField(f("optional_int64" ))); - Assert.assertEquals(0 , message.getField(f("optional_uint32" ))); - Assert.assertEquals(0L , message.getField(f("optional_uint64" ))); - Assert.assertEquals(0 , message.getField(f("optional_sint32" ))); - Assert.assertEquals(0L , message.getField(f("optional_sint64" ))); - Assert.assertEquals(0 , message.getField(f("optional_fixed32" ))); - Assert.assertEquals(0L , message.getField(f("optional_fixed64" ))); - Assert.assertEquals(0 , message.getField(f("optional_sfixed32"))); - Assert.assertEquals(0L , message.getField(f("optional_sfixed64"))); - Assert.assertEquals(0F , message.getField(f("optional_float" ))); - Assert.assertEquals(0D , message.getField(f("optional_double" ))); - Assert.assertEquals(false, message.getField(f("optional_bool" ))); - Assert.assertEquals("" , message.getField(f("optional_string" ))); + Assert.assertEquals(0, message.getField(f("optional_int32"))); + Assert.assertEquals(0L, message.getField(f("optional_int64"))); + Assert.assertEquals(0, message.getField(f("optional_uint32"))); + Assert.assertEquals(0L, message.getField(f("optional_uint64"))); + Assert.assertEquals(0, message.getField(f("optional_sint32"))); + Assert.assertEquals(0L, message.getField(f("optional_sint64"))); + Assert.assertEquals(0, message.getField(f("optional_fixed32"))); + Assert.assertEquals(0L, message.getField(f("optional_fixed64"))); + Assert.assertEquals(0, message.getField(f("optional_sfixed32"))); + Assert.assertEquals(0L, message.getField(f("optional_sfixed64"))); + Assert.assertEquals(0F, message.getField(f("optional_float"))); + Assert.assertEquals(0D, message.getField(f("optional_double"))); + Assert.assertEquals(false, message.getField(f("optional_bool"))); + Assert.assertEquals("", message.getField(f("optional_string"))); Assert.assertEquals(ByteString.EMPTY, message.getField(f("optional_bytes"))); // Embedded messages should also be clear. + Assert.assertFalse(((Message) message.getField(f("optionalgroup"))).hasField(groupA)); Assert.assertFalse( - ((Message)message.getField(f("optionalgroup"))).hasField(groupA)); + ((Message) message.getField(f("optional_nested_message"))).hasField(nestedB)); Assert.assertFalse( - ((Message)message.getField(f("optional_nested_message"))) - .hasField(nestedB)); + ((Message) message.getField(f("optional_foreign_message"))).hasField(foreignC)); Assert.assertFalse( - ((Message)message.getField(f("optional_foreign_message"))) - .hasField(foreignC)); + ((Message) message.getField(f("optional_import_message"))).hasField(importD)); Assert.assertFalse( - ((Message)message.getField(f("optional_import_message"))) - .hasField(importD)); + ((Message) message.getField(f("optional_public_import_message"))).hasField(importE)); Assert.assertFalse( - ((Message)message.getField(f("optional_public_import_message"))) - .hasField(importE)); - Assert.assertFalse( - ((Message)message.getField(f("optional_lazy_message"))) - .hasField(nestedB)); - - Assert.assertEquals(0, - ((Message)message.getField(f("optionalgroup"))).getField(groupA)); - Assert.assertEquals(0, - ((Message)message.getField(f("optional_nested_message"))) - .getField(nestedB)); - Assert.assertEquals(0, - ((Message)message.getField(f("optional_foreign_message"))) - .getField(foreignC)); - Assert.assertEquals(0, - ((Message)message.getField(f("optional_import_message"))) - .getField(importD)); - Assert.assertEquals(0, - ((Message)message.getField(f("optional_public_import_message"))) - .getField(importE)); - Assert.assertEquals(0, - ((Message)message.getField(f("optional_lazy_message"))) - .getField(nestedB)); + ((Message) message.getField(f("optional_lazy_message"))).hasField(nestedB)); + + Assert.assertEquals(0, ((Message) message.getField(f("optionalgroup"))).getField(groupA)); + Assert.assertEquals( + 0, ((Message) message.getField(f("optional_nested_message"))).getField(nestedB)); + Assert.assertEquals( + 0, ((Message) message.getField(f("optional_foreign_message"))).getField(foreignC)); + Assert.assertEquals( + 0, ((Message) message.getField(f("optional_import_message"))).getField(importD)); + Assert.assertEquals( + 0, ((Message) message.getField(f("optional_public_import_message"))).getField(importE)); + Assert.assertEquals( + 0, ((Message) message.getField(f("optional_lazy_message"))).getField(nestedB)); // Enums without defaults are set to the first value in the enum. - Assert.assertEquals( nestedFoo, message.getField(f("optional_nested_enum" ))); + Assert.assertEquals(nestedFoo, message.getField(f("optional_nested_enum"))); Assert.assertEquals(foreignFoo, message.getField(f("optional_foreign_enum"))); - Assert.assertEquals( importFoo, message.getField(f("optional_import_enum" ))); + Assert.assertEquals(importFoo, message.getField(f("optional_import_enum"))); Assert.assertEquals("", message.getField(f("optional_string_piece"))); Assert.assertEquals("", message.getField(f("optional_cord"))); // Repeated fields are empty. - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_int32" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_int64" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_uint32" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_uint64" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sint32" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sint64" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_fixed32" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_fixed64" ))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_int32"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_int64"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_uint32"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_uint64"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sint32"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sint64"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_fixed32"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_fixed64"))); Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sfixed32"))); Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sfixed64"))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_float" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_double" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_bool" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_string" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_bytes" ))); - - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeatedgroup" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_message" ))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_float"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_double"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_bool"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_string"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_bytes"))); + + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeatedgroup"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_message"))); Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_message"))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_message" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_lazy_message" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_enum" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_enum" ))); - Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_enum" ))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_message"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_lazy_message"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_enum"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_enum"))); + Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_enum"))); Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_string_piece"))); Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_cord"))); // has_blah() should also be false for all default fields. - Assert.assertFalse(message.hasField(f("default_int32" ))); - Assert.assertFalse(message.hasField(f("default_int64" ))); - Assert.assertFalse(message.hasField(f("default_uint32" ))); - Assert.assertFalse(message.hasField(f("default_uint64" ))); - Assert.assertFalse(message.hasField(f("default_sint32" ))); - Assert.assertFalse(message.hasField(f("default_sint64" ))); - Assert.assertFalse(message.hasField(f("default_fixed32" ))); - Assert.assertFalse(message.hasField(f("default_fixed64" ))); + Assert.assertFalse(message.hasField(f("default_int32"))); + Assert.assertFalse(message.hasField(f("default_int64"))); + Assert.assertFalse(message.hasField(f("default_uint32"))); + Assert.assertFalse(message.hasField(f("default_uint64"))); + Assert.assertFalse(message.hasField(f("default_sint32"))); + Assert.assertFalse(message.hasField(f("default_sint64"))); + Assert.assertFalse(message.hasField(f("default_fixed32"))); + Assert.assertFalse(message.hasField(f("default_fixed64"))); Assert.assertFalse(message.hasField(f("default_sfixed32"))); Assert.assertFalse(message.hasField(f("default_sfixed64"))); - Assert.assertFalse(message.hasField(f("default_float" ))); - Assert.assertFalse(message.hasField(f("default_double" ))); - Assert.assertFalse(message.hasField(f("default_bool" ))); - Assert.assertFalse(message.hasField(f("default_string" ))); - Assert.assertFalse(message.hasField(f("default_bytes" ))); + Assert.assertFalse(message.hasField(f("default_float"))); + Assert.assertFalse(message.hasField(f("default_double"))); + Assert.assertFalse(message.hasField(f("default_bool"))); + Assert.assertFalse(message.hasField(f("default_string"))); + Assert.assertFalse(message.hasField(f("default_bytes"))); - Assert.assertFalse(message.hasField(f("default_nested_enum" ))); + Assert.assertFalse(message.hasField(f("default_nested_enum"))); Assert.assertFalse(message.hasField(f("default_foreign_enum"))); - Assert.assertFalse(message.hasField(f("default_import_enum" ))); + Assert.assertFalse(message.hasField(f("default_import_enum"))); - Assert.assertFalse(message.hasField(f("default_string_piece" ))); - Assert.assertFalse(message.hasField(f("default_cord" ))); + Assert.assertFalse(message.hasField(f("default_string_piece"))); + Assert.assertFalse(message.hasField(f("default_cord"))); // Fields with defaults have their default values (duh). - Assert.assertEquals( 41 , message.getField(f("default_int32" ))); - Assert.assertEquals( 42L , message.getField(f("default_int64" ))); - Assert.assertEquals( 43 , message.getField(f("default_uint32" ))); - Assert.assertEquals( 44L , message.getField(f("default_uint64" ))); - Assert.assertEquals(-45 , message.getField(f("default_sint32" ))); - Assert.assertEquals( 46L , message.getField(f("default_sint64" ))); - Assert.assertEquals( 47 , message.getField(f("default_fixed32" ))); - Assert.assertEquals( 48L , message.getField(f("default_fixed64" ))); - Assert.assertEquals( 49 , message.getField(f("default_sfixed32"))); - Assert.assertEquals(-50L , message.getField(f("default_sfixed64"))); - Assert.assertEquals( 51.5F , message.getField(f("default_float" ))); - Assert.assertEquals( 52e3D , message.getField(f("default_double" ))); - Assert.assertEquals(true , message.getField(f("default_bool" ))); - Assert.assertEquals("hello", message.getField(f("default_string" ))); + Assert.assertEquals(41, message.getField(f("default_int32"))); + Assert.assertEquals(42L, message.getField(f("default_int64"))); + Assert.assertEquals(43, message.getField(f("default_uint32"))); + Assert.assertEquals(44L, message.getField(f("default_uint64"))); + Assert.assertEquals(-45, message.getField(f("default_sint32"))); + Assert.assertEquals(46L, message.getField(f("default_sint64"))); + Assert.assertEquals(47, message.getField(f("default_fixed32"))); + Assert.assertEquals(48L, message.getField(f("default_fixed64"))); + Assert.assertEquals(49, message.getField(f("default_sfixed32"))); + Assert.assertEquals(-50L, message.getField(f("default_sfixed64"))); + Assert.assertEquals(51.5F, message.getField(f("default_float"))); + Assert.assertEquals(52e3D, message.getField(f("default_double"))); + Assert.assertEquals(true, message.getField(f("default_bool"))); + Assert.assertEquals("hello", message.getField(f("default_string"))); Assert.assertEquals(toBytes("world"), message.getField(f("default_bytes"))); - Assert.assertEquals( nestedBar, message.getField(f("default_nested_enum" ))); + Assert.assertEquals(nestedBar, message.getField(f("default_nested_enum"))); Assert.assertEquals(foreignBar, message.getField(f("default_foreign_enum"))); - Assert.assertEquals( importBar, message.getField(f("default_import_enum" ))); + Assert.assertEquals(importBar, message.getField(f("default_import_enum"))); Assert.assertEquals("abc", message.getField(f("default_string_piece"))); Assert.assertEquals("123", message.getField(f("default_cord"))); @@ -3463,205 +3459,204 @@ public void assertClearViaReflection(MessageOrBuilder message) { Assert.assertEquals(toBytes(""), message.getField(f("oneof_bytes"))); } - // --------------------------------------------------------------- - public void assertRepeatedFieldsModifiedViaReflection( - MessageOrBuilder message) { + public void assertRepeatedFieldsModifiedViaReflection(MessageOrBuilder message) { // ModifyRepeatedFields only sets the second repeated element of each // field. In addition to verifying this, we also verify that the first // element and size were *not* modified. - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int32" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int64" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint32" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint64" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint32" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint64" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed32" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed64" ))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int32"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int64"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint32"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint64"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint32"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint64"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed32"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed64"))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed32"))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed64"))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_float" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_double" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bool" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bytes" ))); - - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeatedgroup" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" ))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_float"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_double"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bool"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bytes"))); + + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeatedgroup"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message"))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message"))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum" ))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum"))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string_piece"))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_cord"))); - Assert.assertEquals(201 , message.getRepeatedField(f("repeated_int32" ), 0)); - Assert.assertEquals(202L , message.getRepeatedField(f("repeated_int64" ), 0)); - Assert.assertEquals(203 , message.getRepeatedField(f("repeated_uint32" ), 0)); - Assert.assertEquals(204L , message.getRepeatedField(f("repeated_uint64" ), 0)); - Assert.assertEquals(205 , message.getRepeatedField(f("repeated_sint32" ), 0)); - Assert.assertEquals(206L , message.getRepeatedField(f("repeated_sint64" ), 0)); - Assert.assertEquals(207 , message.getRepeatedField(f("repeated_fixed32" ), 0)); - Assert.assertEquals(208L , message.getRepeatedField(f("repeated_fixed64" ), 0)); - Assert.assertEquals(209 , message.getRepeatedField(f("repeated_sfixed32"), 0)); - Assert.assertEquals(210L , message.getRepeatedField(f("repeated_sfixed64"), 0)); - Assert.assertEquals(211F , message.getRepeatedField(f("repeated_float" ), 0)); - Assert.assertEquals(212D , message.getRepeatedField(f("repeated_double" ), 0)); - Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool" ), 0)); - Assert.assertEquals("215", message.getRepeatedField(f("repeated_string" ), 0)); + Assert.assertEquals(201, message.getRepeatedField(f("repeated_int32"), 0)); + Assert.assertEquals(202L, message.getRepeatedField(f("repeated_int64"), 0)); + Assert.assertEquals(203, message.getRepeatedField(f("repeated_uint32"), 0)); + Assert.assertEquals(204L, message.getRepeatedField(f("repeated_uint64"), 0)); + Assert.assertEquals(205, message.getRepeatedField(f("repeated_sint32"), 0)); + Assert.assertEquals(206L, message.getRepeatedField(f("repeated_sint64"), 0)); + Assert.assertEquals(207, message.getRepeatedField(f("repeated_fixed32"), 0)); + Assert.assertEquals(208L, message.getRepeatedField(f("repeated_fixed64"), 0)); + Assert.assertEquals(209, message.getRepeatedField(f("repeated_sfixed32"), 0)); + Assert.assertEquals(210L, message.getRepeatedField(f("repeated_sfixed64"), 0)); + Assert.assertEquals(211F, message.getRepeatedField(f("repeated_float"), 0)); + Assert.assertEquals(212D, message.getRepeatedField(f("repeated_double"), 0)); + Assert.assertEquals(true, message.getRepeatedField(f("repeated_bool"), 0)); + Assert.assertEquals("215", message.getRepeatedField(f("repeated_string"), 0)); Assert.assertEquals(toBytes("216"), message.getRepeatedField(f("repeated_bytes"), 0)); - Assert.assertEquals(217, - ((Message)message.getRepeatedField(f("repeatedgroup"), 0)) - .getField(repeatedGroupA)); - Assert.assertEquals(218, - ((Message)message.getRepeatedField(f("repeated_nested_message"), 0)) - .getField(nestedB)); - Assert.assertEquals(219, - ((Message)message.getRepeatedField(f("repeated_foreign_message"), 0)) - .getField(foreignC)); - Assert.assertEquals(220, - ((Message)message.getRepeatedField(f("repeated_import_message"), 0)) - .getField(importD)); - Assert.assertEquals(227, - ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0)) - .getField(nestedB)); - - Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0)); - Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0)); - Assert.assertEquals( importBar, message.getRepeatedField(f("repeated_import_enum" ),0)); + Assert.assertEquals( + 217, + ((Message) message.getRepeatedField(f("repeatedgroup"), 0)).getField(repeatedGroupA)); + Assert.assertEquals( + 218, + ((Message) message.getRepeatedField(f("repeated_nested_message"), 0)).getField(nestedB)); + Assert.assertEquals( + 219, + ((Message) message.getRepeatedField(f("repeated_foreign_message"), 0)) + .getField(foreignC)); + Assert.assertEquals( + 220, + ((Message) message.getRepeatedField(f("repeated_import_message"), 0)).getField(importD)); + Assert.assertEquals( + 227, + ((Message) message.getRepeatedField(f("repeated_lazy_message"), 0)).getField(nestedB)); + + Assert.assertEquals(nestedBar, message.getRepeatedField(f("repeated_nested_enum"), 0)); + Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"), 0)); + Assert.assertEquals(importBar, message.getRepeatedField(f("repeated_import_enum"), 0)); Assert.assertEquals("224", message.getRepeatedField(f("repeated_string_piece"), 0)); Assert.assertEquals("225", message.getRepeatedField(f("repeated_cord"), 0)); - Assert.assertEquals(501 , message.getRepeatedField(f("repeated_int32" ), 1)); - Assert.assertEquals(502L , message.getRepeatedField(f("repeated_int64" ), 1)); - Assert.assertEquals(503 , message.getRepeatedField(f("repeated_uint32" ), 1)); - Assert.assertEquals(504L , message.getRepeatedField(f("repeated_uint64" ), 1)); - Assert.assertEquals(505 , message.getRepeatedField(f("repeated_sint32" ), 1)); - Assert.assertEquals(506L , message.getRepeatedField(f("repeated_sint64" ), 1)); - Assert.assertEquals(507 , message.getRepeatedField(f("repeated_fixed32" ), 1)); - Assert.assertEquals(508L , message.getRepeatedField(f("repeated_fixed64" ), 1)); - Assert.assertEquals(509 , message.getRepeatedField(f("repeated_sfixed32"), 1)); - Assert.assertEquals(510L , message.getRepeatedField(f("repeated_sfixed64"), 1)); - Assert.assertEquals(511F , message.getRepeatedField(f("repeated_float" ), 1)); - Assert.assertEquals(512D , message.getRepeatedField(f("repeated_double" ), 1)); - Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool" ), 1)); - Assert.assertEquals("515", message.getRepeatedField(f("repeated_string" ), 1)); + Assert.assertEquals(501, message.getRepeatedField(f("repeated_int32"), 1)); + Assert.assertEquals(502L, message.getRepeatedField(f("repeated_int64"), 1)); + Assert.assertEquals(503, message.getRepeatedField(f("repeated_uint32"), 1)); + Assert.assertEquals(504L, message.getRepeatedField(f("repeated_uint64"), 1)); + Assert.assertEquals(505, message.getRepeatedField(f("repeated_sint32"), 1)); + Assert.assertEquals(506L, message.getRepeatedField(f("repeated_sint64"), 1)); + Assert.assertEquals(507, message.getRepeatedField(f("repeated_fixed32"), 1)); + Assert.assertEquals(508L, message.getRepeatedField(f("repeated_fixed64"), 1)); + Assert.assertEquals(509, message.getRepeatedField(f("repeated_sfixed32"), 1)); + Assert.assertEquals(510L, message.getRepeatedField(f("repeated_sfixed64"), 1)); + Assert.assertEquals(511F, message.getRepeatedField(f("repeated_float"), 1)); + Assert.assertEquals(512D, message.getRepeatedField(f("repeated_double"), 1)); + Assert.assertEquals(true, message.getRepeatedField(f("repeated_bool"), 1)); + Assert.assertEquals("515", message.getRepeatedField(f("repeated_string"), 1)); Assert.assertEquals(toBytes("516"), message.getRepeatedField(f("repeated_bytes"), 1)); - Assert.assertEquals(517, - ((Message)message.getRepeatedField(f("repeatedgroup"), 1)) - .getField(repeatedGroupA)); - Assert.assertEquals(518, - ((Message)message.getRepeatedField(f("repeated_nested_message"), 1)) - .getField(nestedB)); - Assert.assertEquals(519, - ((Message)message.getRepeatedField(f("repeated_foreign_message"), 1)) - .getField(foreignC)); - Assert.assertEquals(520, - ((Message)message.getRepeatedField(f("repeated_import_message"), 1)) - .getField(importD)); - Assert.assertEquals(527, - ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1)) - .getField(nestedB)); - - Assert.assertEquals( nestedFoo, message.getRepeatedField(f("repeated_nested_enum" ),1)); - Assert.assertEquals(foreignFoo, message.getRepeatedField(f("repeated_foreign_enum"),1)); - Assert.assertEquals( importFoo, message.getRepeatedField(f("repeated_import_enum" ),1)); + Assert.assertEquals( + 517, + ((Message) message.getRepeatedField(f("repeatedgroup"), 1)).getField(repeatedGroupA)); + Assert.assertEquals( + 518, + ((Message) message.getRepeatedField(f("repeated_nested_message"), 1)).getField(nestedB)); + Assert.assertEquals( + 519, + ((Message) message.getRepeatedField(f("repeated_foreign_message"), 1)) + .getField(foreignC)); + Assert.assertEquals( + 520, + ((Message) message.getRepeatedField(f("repeated_import_message"), 1)).getField(importD)); + Assert.assertEquals( + 527, + ((Message) message.getRepeatedField(f("repeated_lazy_message"), 1)).getField(nestedB)); + + Assert.assertEquals(nestedFoo, message.getRepeatedField(f("repeated_nested_enum"), 1)); + Assert.assertEquals(foreignFoo, message.getRepeatedField(f("repeated_foreign_enum"), 1)); + Assert.assertEquals(importFoo, message.getRepeatedField(f("repeated_import_enum"), 1)); Assert.assertEquals("524", message.getRepeatedField(f("repeated_string_piece"), 1)); Assert.assertEquals("525", message.getRepeatedField(f("repeated_cord"), 1)); } public void setPackedFieldsViaReflection(Message.Builder message) { - message.addRepeatedField(f("packed_int32" ), 601 ); - message.addRepeatedField(f("packed_int64" ), 602L); - message.addRepeatedField(f("packed_uint32" ), 603 ); - message.addRepeatedField(f("packed_uint64" ), 604L); - message.addRepeatedField(f("packed_sint32" ), 605 ); - message.addRepeatedField(f("packed_sint64" ), 606L); - message.addRepeatedField(f("packed_fixed32" ), 607 ); - message.addRepeatedField(f("packed_fixed64" ), 608L); - message.addRepeatedField(f("packed_sfixed32"), 609 ); + message.addRepeatedField(f("packed_int32"), 601); + message.addRepeatedField(f("packed_int64"), 602L); + message.addRepeatedField(f("packed_uint32"), 603); + message.addRepeatedField(f("packed_uint64"), 604L); + message.addRepeatedField(f("packed_sint32"), 605); + message.addRepeatedField(f("packed_sint64"), 606L); + message.addRepeatedField(f("packed_fixed32"), 607); + message.addRepeatedField(f("packed_fixed64"), 608L); + message.addRepeatedField(f("packed_sfixed32"), 609); message.addRepeatedField(f("packed_sfixed64"), 610L); - message.addRepeatedField(f("packed_float" ), 611F); - message.addRepeatedField(f("packed_double" ), 612D); - message.addRepeatedField(f("packed_bool" ), true); - message.addRepeatedField(f("packed_enum" ), foreignBar); + message.addRepeatedField(f("packed_float"), 611F); + message.addRepeatedField(f("packed_double"), 612D); + message.addRepeatedField(f("packed_bool"), true); + message.addRepeatedField(f("packed_enum"), foreignBar); // Add a second one of each field. - message.addRepeatedField(f("packed_int32" ), 701 ); - message.addRepeatedField(f("packed_int64" ), 702L); - message.addRepeatedField(f("packed_uint32" ), 703 ); - message.addRepeatedField(f("packed_uint64" ), 704L); - message.addRepeatedField(f("packed_sint32" ), 705 ); - message.addRepeatedField(f("packed_sint64" ), 706L); - message.addRepeatedField(f("packed_fixed32" ), 707 ); - message.addRepeatedField(f("packed_fixed64" ), 708L); - message.addRepeatedField(f("packed_sfixed32"), 709 ); + message.addRepeatedField(f("packed_int32"), 701); + message.addRepeatedField(f("packed_int64"), 702L); + message.addRepeatedField(f("packed_uint32"), 703); + message.addRepeatedField(f("packed_uint64"), 704L); + message.addRepeatedField(f("packed_sint32"), 705); + message.addRepeatedField(f("packed_sint64"), 706L); + message.addRepeatedField(f("packed_fixed32"), 707); + message.addRepeatedField(f("packed_fixed64"), 708L); + message.addRepeatedField(f("packed_sfixed32"), 709); message.addRepeatedField(f("packed_sfixed64"), 710L); - message.addRepeatedField(f("packed_float" ), 711F); - message.addRepeatedField(f("packed_double" ), 712D); - message.addRepeatedField(f("packed_bool" ), false); - message.addRepeatedField(f("packed_enum" ), foreignBaz); + message.addRepeatedField(f("packed_float"), 711F); + message.addRepeatedField(f("packed_double"), 712D); + message.addRepeatedField(f("packed_bool"), false); + message.addRepeatedField(f("packed_enum"), foreignBaz); } public void assertPackedFieldsSetViaReflection(MessageOrBuilder message) { - Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int32" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int64" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint32" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint64" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint32" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint64" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed32" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed64" ))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int32"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int64"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint32"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint64"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint32"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint64"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed32"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed64"))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sfixed32"))); Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sfixed64"))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_float" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_double" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_bool" ))); - Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_enum" ))); - Assert.assertEquals(601 , message.getRepeatedField(f("packed_int32" ), 0)); - Assert.assertEquals(602L , message.getRepeatedField(f("packed_int64" ), 0)); - Assert.assertEquals(603 , message.getRepeatedField(f("packed_uint32" ), 0)); - Assert.assertEquals(604L , message.getRepeatedField(f("packed_uint64" ), 0)); - Assert.assertEquals(605 , message.getRepeatedField(f("packed_sint32" ), 0)); - Assert.assertEquals(606L , message.getRepeatedField(f("packed_sint64" ), 0)); - Assert.assertEquals(607 , message.getRepeatedField(f("packed_fixed32" ), 0)); - Assert.assertEquals(608L , message.getRepeatedField(f("packed_fixed64" ), 0)); - Assert.assertEquals(609 , message.getRepeatedField(f("packed_sfixed32"), 0)); - Assert.assertEquals(610L , message.getRepeatedField(f("packed_sfixed64"), 0)); - Assert.assertEquals(611F , message.getRepeatedField(f("packed_float" ), 0)); - Assert.assertEquals(612D , message.getRepeatedField(f("packed_double" ), 0)); - Assert.assertEquals(true , message.getRepeatedField(f("packed_bool" ), 0)); - Assert.assertEquals(foreignBar, message.getRepeatedField(f("packed_enum" ),0)); - Assert.assertEquals(701 , message.getRepeatedField(f("packed_int32" ), 1)); - Assert.assertEquals(702L , message.getRepeatedField(f("packed_int64" ), 1)); - Assert.assertEquals(703 , message.getRepeatedField(f("packed_uint32" ), 1)); - Assert.assertEquals(704L , message.getRepeatedField(f("packed_uint64" ), 1)); - Assert.assertEquals(705 , message.getRepeatedField(f("packed_sint32" ), 1)); - Assert.assertEquals(706L , message.getRepeatedField(f("packed_sint64" ), 1)); - Assert.assertEquals(707 , message.getRepeatedField(f("packed_fixed32" ), 1)); - Assert.assertEquals(708L , message.getRepeatedField(f("packed_fixed64" ), 1)); - Assert.assertEquals(709 , message.getRepeatedField(f("packed_sfixed32"), 1)); - Assert.assertEquals(710L , message.getRepeatedField(f("packed_sfixed64"), 1)); - Assert.assertEquals(711F , message.getRepeatedField(f("packed_float" ), 1)); - Assert.assertEquals(712D , message.getRepeatedField(f("packed_double" ), 1)); - Assert.assertEquals(false, message.getRepeatedField(f("packed_bool" ), 1)); - Assert.assertEquals(foreignBaz, message.getRepeatedField(f("packed_enum" ),1)); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_float"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_double"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_bool"))); + Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_enum"))); + Assert.assertEquals(601, message.getRepeatedField(f("packed_int32"), 0)); + Assert.assertEquals(602L, message.getRepeatedField(f("packed_int64"), 0)); + Assert.assertEquals(603, message.getRepeatedField(f("packed_uint32"), 0)); + Assert.assertEquals(604L, message.getRepeatedField(f("packed_uint64"), 0)); + Assert.assertEquals(605, message.getRepeatedField(f("packed_sint32"), 0)); + Assert.assertEquals(606L, message.getRepeatedField(f("packed_sint64"), 0)); + Assert.assertEquals(607, message.getRepeatedField(f("packed_fixed32"), 0)); + Assert.assertEquals(608L, message.getRepeatedField(f("packed_fixed64"), 0)); + Assert.assertEquals(609, message.getRepeatedField(f("packed_sfixed32"), 0)); + Assert.assertEquals(610L, message.getRepeatedField(f("packed_sfixed64"), 0)); + Assert.assertEquals(611F, message.getRepeatedField(f("packed_float"), 0)); + Assert.assertEquals(612D, message.getRepeatedField(f("packed_double"), 0)); + Assert.assertEquals(true, message.getRepeatedField(f("packed_bool"), 0)); + Assert.assertEquals(foreignBar, message.getRepeatedField(f("packed_enum"), 0)); + Assert.assertEquals(701, message.getRepeatedField(f("packed_int32"), 1)); + Assert.assertEquals(702L, message.getRepeatedField(f("packed_int64"), 1)); + Assert.assertEquals(703, message.getRepeatedField(f("packed_uint32"), 1)); + Assert.assertEquals(704L, message.getRepeatedField(f("packed_uint64"), 1)); + Assert.assertEquals(705, message.getRepeatedField(f("packed_sint32"), 1)); + Assert.assertEquals(706L, message.getRepeatedField(f("packed_sint64"), 1)); + Assert.assertEquals(707, message.getRepeatedField(f("packed_fixed32"), 1)); + Assert.assertEquals(708L, message.getRepeatedField(f("packed_fixed64"), 1)); + Assert.assertEquals(709, message.getRepeatedField(f("packed_sfixed32"), 1)); + Assert.assertEquals(710L, message.getRepeatedField(f("packed_sfixed64"), 1)); + Assert.assertEquals(711F, message.getRepeatedField(f("packed_float"), 1)); + Assert.assertEquals(712D, message.getRepeatedField(f("packed_double"), 1)); + Assert.assertEquals(false, message.getRepeatedField(f("packed_bool"), 1)); + Assert.assertEquals(foreignBaz, message.getRepeatedField(f("packed_enum"), 1)); } /** * Verifies that the reflection setters for the given.Builder object throw a - * NullPointerException if they are passed a null value. Uses Assert to throw an - * appropriate assertion failure, if the condition is not verified. + * NullPointerException if they are passed a null value. Uses Assert to throw an appropriate + * assertion failure, if the condition is not verified. */ - public void assertReflectionSettersRejectNull(Message.Builder builder) - throws Exception { + public void assertReflectionSettersRejectNull(Message.Builder builder) throws Exception { try { builder.setField(f("optional_string"), null); Assert.fail("Exception was not thrown"); @@ -3681,15 +3676,13 @@ public void assertReflectionSettersRejectNull(Message.Builder builder) // We expect this exception. } try { - builder.setField(f("optional_nested_message"), - (TestAllTypes.NestedMessage) null); + builder.setField(f("optional_nested_message"), (TestAllTypes.NestedMessage) null); Assert.fail("Exception was not thrown"); } catch (NullPointerException e) { // We expect this exception. } try { - builder.setField(f("optional_nested_message"), - (TestAllTypes.NestedMessage.Builder) null); + builder.setField(f("optional_nested_message"), (TestAllTypes.NestedMessage.Builder) null); Assert.fail("Exception was not thrown"); } catch (NullPointerException e) { // We expect this exception. @@ -3723,7 +3716,7 @@ public void assertReflectionSettersRejectNull(Message.Builder builder) /** * Verifies that the reflection repeated setters for the given Builder object throw a - * NullPointerException if they are passed a null value. Uses Assert to throw an appropriate + * NullPointerException if they are passed a null value. Uses Assert to throw an appropriate * assertion failure, if the condition is not verified. */ public void assertReflectionRepeatedSettersRejectNull(Message.Builder builder) @@ -3753,8 +3746,7 @@ public void assertReflectionRepeatedSettersRejectNull(Message.Builder builder) } builder.addRepeatedField( - f("repeated_nested_message"), - TestAllTypes.NestedMessage.newBuilder().setBb(218).build()); + f("repeated_nested_message"), TestAllTypes.NestedMessage.newBuilder().setBb(218).build()); try { builder.setRepeatedField(f("repeated_nested_message"), 0, null); Assert.fail("Exception was not thrown"); @@ -3764,10 +3756,7 @@ public void assertReflectionRepeatedSettersRejectNull(Message.Builder builder) } } - /** - * @param filePath The path relative to - * {@link #getTestDataDir}. - */ + /** @param filePath The path relative to {@link #getTestDataDir}. */ public static String readTextFromFile(String filePath) { return readBytesFromFile(filePath).toStringUtf8(); } @@ -3779,8 +3768,7 @@ private static File getTestDataDir() { try { ancestor = ancestor.getCanonicalFile(); } catch (IOException e) { - throw new RuntimeException( - "Couldn't get canonical name of working directory.", e); + throw new RuntimeException("Couldn't get canonical name of working directory.", e); } while (ancestor != null && ancestor.exists()) { if (new File(ancestor, "src/google/protobuf").exists()) { @@ -3790,15 +3778,13 @@ private static File getTestDataDir() { } throw new RuntimeException( - "Could not find golden files. This test must be run from within the " + - "protobuf source package so that it can read test data files from the " + - "C++ source tree: " + initialPath); + "Could not find golden files. This test must be run from within the " + + "protobuf source package so that it can read test data files from the " + + "C++ source tree: " + + initialPath); } - /** - * @param filename The path relative to - * {@link #getTestDataDir}. - */ + /** @param filename The path relative to {@link #getTestDataDir}. */ public static ByteString readBytesFromFile(String filename) { File fullPath = new File(getTestDataDir(), filename); try { @@ -3809,50 +3795,59 @@ public static ByteString readBytesFromFile(String filename) { } catch (IOException e) { // Throw a RuntimeException here so that we can call this function from // static initializers. - throw new IllegalArgumentException( - "Couldn't read file: " + fullPath.getPath(), e); + throw new IllegalArgumentException("Couldn't read file: " + fullPath.getPath(), e); + } + } + // END FULL-RUNTIME + + private static ByteString readBytesFromResource(String name) { + try { + return ByteString.copyFrom( + com.google.common.io.ByteStreams.toByteArray(TestUtil.class.getResourceAsStream(name))); + } catch (IOException e) { + throw new RuntimeException(e); } } /** - * Get the bytes of the "golden message". This is a serialized TestAllTypes - * with all fields set as they would be by - * {@link #setAllFields(TestAllTypes.Builder)}, but it is loaded from a file - * on disk rather than generated dynamically. The file is actually generated - * by C++ code, so testing against it verifies compatibility with C++. + * Get the bytes of the "golden message". This is a serialized TestAllTypes with all fields set as + * they would be by {@link #setAllFields(TestAllTypes.Builder)}, but it is loaded from a file on + * disk rather than generated dynamically. The file is actually generated by C++ code, so testing + * against it verifies compatibility with C++. */ public static ByteString getGoldenMessage() { if (goldenMessage == null) { - goldenMessage = readBytesFromFile("golden_message_oneof_implemented"); + goldenMessage = + readBytesFromResource("/google/protobuf/testdata/golden_message_oneof_implemented"); } return goldenMessage; } + private static ByteString goldenMessage = null; /** - * Get the bytes of the "golden packed fields message". This is a serialized - * TestPackedTypes with all fields set as they would be by - * {@link #setPackedFields(TestPackedTypes.Builder)}, but it is loaded from a - * file on disk rather than generated dynamically. The file is actually - * generated by C++ code, so testing against it verifies compatibility with - * C++. + * Get the bytes of the "golden packed fields message". This is a serialized TestPackedTypes with + * all fields set as they would be by {@link #setPackedFields(TestPackedTypes.Builder)}, but it is + * loaded from a file on disk rather than generated dynamically. The file is actually generated by + * C++ code, so testing against it verifies compatibility with C++. */ public static ByteString getGoldenPackedFieldsMessage() { if (goldenPackedFieldsMessage == null) { goldenPackedFieldsMessage = - readBytesFromFile("golden_packed_fields_message"); + readBytesFromResource("/google/protobuf/testdata/golden_packed_fields_message"); } return goldenPackedFieldsMessage; } + private static ByteString goldenPackedFieldsMessage = null; + // BEGIN FULL-RUNTIME /** * Mock implementation of {@link GeneratedMessage.BuilderParent} for testing. * * @author jonp@google.com (Jon Perlow) */ - public static class MockBuilderParent - implements GeneratedMessage.BuilderParent { + public static class MockBuilderParent implements GeneratedMessage.BuilderParent { private int invalidations; @@ -3865,4 +3860,29 @@ public int getInvalidationCount() { return invalidations; } } + // END FULL-RUNTIME + + /** Helper class to test logged messages */ + public static class TestLogHandler extends Handler { + /** We will keep a private list of all logged records */ + private final List list = new ArrayList<>(); + + /** Adds the most recently logged record to our list. */ + @Override + public synchronized void publish(LogRecord record) { + list.add(record); + } + + @Override + public void flush() {} + + @Override + public void close() {} + + /** Returns a snapshot of the logged records. */ + public synchronized List getStoredLogRecords() { + List result = new ArrayList<>(list); + return Collections.unmodifiableList(result); + } + } } diff --git a/java/core/src/test/java/com/google/protobuf/TestUtilLite.java b/java/core/src/test/java/com/google/protobuf/TestUtilLite.java index 8f33fa14ab2ce..993dd9defb2c7 100644 --- a/java/core/src/test/java/com/google/protobuf/TestUtilLite.java +++ b/java/core/src/test/java/com/google/protobuf/TestUtilLite.java @@ -30,8 +30,6 @@ package com.google.protobuf; -import static com.google.protobuf.UnittestLite.OptionalGroup_extension_lite; -import static com.google.protobuf.UnittestLite.RepeatedGroup_extension_lite; import static com.google.protobuf.UnittestLite.defaultBoolExtensionLite; import static com.google.protobuf.UnittestLite.defaultBytesExtensionLite; import static com.google.protobuf.UnittestLite.defaultCordExtensionLite; @@ -127,6 +125,8 @@ import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite; import com.google.protobuf.UnittestLite.ForeignEnumLite; import com.google.protobuf.UnittestLite.ForeignMessageLite; +import com.google.protobuf.UnittestLite.OptionalGroup_extension_lite; +import com.google.protobuf.UnittestLite.RepeatedGroup_extension_lite; import com.google.protobuf.UnittestLite.TestAllExtensionsLite; import com.google.protobuf.UnittestLite.TestAllTypesLite; import com.google.protobuf.UnittestLite.TestPackedExtensionsLite; @@ -136,20 +136,19 @@ * and {@code TestPackedExtensionsLite}. This is analogous to the functionality in TestUtil.java but * does not depend on the presence of any non-lite protos. * - *

This code is not to be used outside of {@code com.google.protobuf} and - * subpackages. + *

This code is not to be used outside of {@code com.google.protobuf} and subpackages. */ public final class TestUtilLite { private TestUtilLite() {} /** Helper to convert a String to ByteString. */ - static ByteString toBytes(String str) { - return ByteString.copyFrom(str.getBytes(Internal.UTF_8)); + public static ByteString toBytes(String str) { + return ByteString.copyFromUtf8(str); } /** - * Get a {@code TestAllTypesLite.Builder} with all fields set as they would be by - * {@link #setAllFields(TestAllTypesLite.Builder)}. + * Get a {@code TestAllTypesLite.Builder} with all fields set as they would be by {@link + * #setAllFields(TestAllTypesLite.Builder)}. */ public static TestAllTypesLite.Builder getAllLiteSetBuilder() { TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder(); @@ -158,8 +157,8 @@ public static TestAllTypesLite.Builder getAllLiteSetBuilder() { } /** - * Get a {@code TestAllExtensionsLite} with all fields set as they would be by - * {@link #setAllExtensions(TestAllExtensionsLite.Builder)}. + * Get a {@code TestAllExtensionsLite} with all fields set as they would be by {@link + * #setAllExtensions(TestAllExtensionsLite.Builder)}. */ public static TestAllExtensionsLite getAllLiteExtensionsSet() { TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder(); @@ -172,154 +171,137 @@ public static TestPackedExtensionsLite getLitePackedExtensionsSet() { setPackedExtensions(builder); return builder.build(); } - - /** - * Set every field of {@code builder} to the values expected by - * {@code assertAllFieldsSet()}. - */ + + /** Set every field of {@code builder} to the values expected by {@code assertAllFieldsSet()}. */ public static void setAllFields(TestAllTypesLite.Builder builder) { - builder.setOptionalInt32 (101); - builder.setOptionalInt64 (102); - builder.setOptionalUint32 (103); - builder.setOptionalUint64 (104); - builder.setOptionalSint32 (105); - builder.setOptionalSint64 (106); - builder.setOptionalFixed32 (107); - builder.setOptionalFixed64 (108); + builder.setOptionalInt32(101); + builder.setOptionalInt64(102); + builder.setOptionalUint32(103); + builder.setOptionalUint64(104); + builder.setOptionalSint32(105); + builder.setOptionalSint64(106); + builder.setOptionalFixed32(107); + builder.setOptionalFixed64(108); builder.setOptionalSfixed32(109); builder.setOptionalSfixed64(110); - builder.setOptionalFloat (111); - builder.setOptionalDouble (112); - builder.setOptionalBool (true); - builder.setOptionalString ("115"); - builder.setOptionalBytes (toBytes("116")); - - builder.setOptionalGroup( - TestAllTypesLite.OptionalGroup.newBuilder().setA(117).build()); + builder.setOptionalFloat(111); + builder.setOptionalDouble(112); + builder.setOptionalBool(true); + builder.setOptionalString("115"); + builder.setOptionalBytes(toBytes("116")); + + builder.setOptionalGroup(TestAllTypesLite.OptionalGroup.newBuilder().setA(117).build()); builder.setOptionalNestedMessage( TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build()); - builder.setOptionalForeignMessage( - ForeignMessageLite.newBuilder().setC(119).build()); - builder.setOptionalImportMessage( - ImportMessageLite.newBuilder().setD(120).build()); - builder.setOptionalPublicImportMessage( - PublicImportMessageLite.newBuilder().setE(126).build()); - builder.setOptionalLazyMessage( - TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build()); + builder.setOptionalForeignMessage(ForeignMessageLite.newBuilder().setC(119).build()); + builder.setOptionalImportMessage(ImportMessageLite.newBuilder().setD(120).build()); + builder.setOptionalPublicImportMessage(PublicImportMessageLite.newBuilder().setE(126).build()); + builder.setOptionalLazyMessage(TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build()); - builder.setOptionalNestedEnum (TestAllTypesLite.NestedEnum.BAZ); + builder.setOptionalNestedEnum(TestAllTypesLite.NestedEnum.BAZ); builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAZ); - builder.setOptionalImportEnum (ImportEnumLite.IMPORT_LITE_BAZ); + builder.setOptionalImportEnum(ImportEnumLite.IMPORT_LITE_BAZ); builder.setOptionalStringPiece("124"); builder.setOptionalCord("125"); // ----------------------------------------------------------------- - builder.addRepeatedInt32 (201); - builder.addRepeatedInt64 (202); - builder.addRepeatedUint32 (203); - builder.addRepeatedUint64 (204); - builder.addRepeatedSint32 (205); - builder.addRepeatedSint64 (206); - builder.addRepeatedFixed32 (207); - builder.addRepeatedFixed64 (208); + builder.addRepeatedInt32(201); + builder.addRepeatedInt64(202); + builder.addRepeatedUint32(203); + builder.addRepeatedUint64(204); + builder.addRepeatedSint32(205); + builder.addRepeatedSint64(206); + builder.addRepeatedFixed32(207); + builder.addRepeatedFixed64(208); builder.addRepeatedSfixed32(209); builder.addRepeatedSfixed64(210); - builder.addRepeatedFloat (211); - builder.addRepeatedDouble (212); - builder.addRepeatedBool (true); - builder.addRepeatedString ("215"); - builder.addRepeatedBytes (toBytes("216")); - - builder.addRepeatedGroup( - TestAllTypesLite.RepeatedGroup.newBuilder().setA(217).build()); + builder.addRepeatedFloat(211); + builder.addRepeatedDouble(212); + builder.addRepeatedBool(true); + builder.addRepeatedString("215"); + builder.addRepeatedBytes(toBytes("216")); + + builder.addRepeatedGroup(TestAllTypesLite.RepeatedGroup.newBuilder().setA(217).build()); builder.addRepeatedNestedMessage( TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build()); - builder.addRepeatedForeignMessage( - ForeignMessageLite.newBuilder().setC(219).build()); - builder.addRepeatedImportMessage( - ImportMessageLite.newBuilder().setD(220).build()); - builder.addRepeatedLazyMessage( - TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build()); + builder.addRepeatedForeignMessage(ForeignMessageLite.newBuilder().setC(219).build()); + builder.addRepeatedImportMessage(ImportMessageLite.newBuilder().setD(220).build()); + builder.addRepeatedLazyMessage(TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build()); - builder.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAR); + builder.addRepeatedNestedEnum(TestAllTypesLite.NestedEnum.BAR); builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR); - builder.addRepeatedImportEnum (ImportEnumLite.IMPORT_LITE_BAR); + builder.addRepeatedImportEnum(ImportEnumLite.IMPORT_LITE_BAR); builder.addRepeatedStringPiece("224"); builder.addRepeatedCord("225"); // Add a second one of each field. - builder.addRepeatedInt32 (301); - builder.addRepeatedInt64 (302); - builder.addRepeatedUint32 (303); - builder.addRepeatedUint64 (304); - builder.addRepeatedSint32 (305); - builder.addRepeatedSint64 (306); - builder.addRepeatedFixed32 (307); - builder.addRepeatedFixed64 (308); + builder.addRepeatedInt32(301); + builder.addRepeatedInt64(302); + builder.addRepeatedUint32(303); + builder.addRepeatedUint64(304); + builder.addRepeatedSint32(305); + builder.addRepeatedSint64(306); + builder.addRepeatedFixed32(307); + builder.addRepeatedFixed64(308); builder.addRepeatedSfixed32(309); builder.addRepeatedSfixed64(310); - builder.addRepeatedFloat (311); - builder.addRepeatedDouble (312); - builder.addRepeatedBool (false); - builder.addRepeatedString ("315"); - builder.addRepeatedBytes (toBytes("316")); - - builder.addRepeatedGroup( - TestAllTypesLite.RepeatedGroup.newBuilder().setA(317).build()); + builder.addRepeatedFloat(311); + builder.addRepeatedDouble(312); + builder.addRepeatedBool(false); + builder.addRepeatedString("315"); + builder.addRepeatedBytes(toBytes("316")); + + builder.addRepeatedGroup(TestAllTypesLite.RepeatedGroup.newBuilder().setA(317).build()); builder.addRepeatedNestedMessage( TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build()); - builder.addRepeatedForeignMessage( - ForeignMessageLite.newBuilder().setC(319).build()); - builder.addRepeatedImportMessage( - ImportMessageLite.newBuilder().setD(320).build()); - builder.addRepeatedLazyMessage( - TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build()); + builder.addRepeatedForeignMessage(ForeignMessageLite.newBuilder().setC(319).build()); + builder.addRepeatedImportMessage(ImportMessageLite.newBuilder().setD(320).build()); + builder.addRepeatedLazyMessage(TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build()); - builder.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAZ); + builder.addRepeatedNestedEnum(TestAllTypesLite.NestedEnum.BAZ); builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAZ); - builder.addRepeatedImportEnum (ImportEnumLite.IMPORT_LITE_BAZ); + builder.addRepeatedImportEnum(ImportEnumLite.IMPORT_LITE_BAZ); builder.addRepeatedStringPiece("324"); builder.addRepeatedCord("325"); // ----------------------------------------------------------------- - builder.setDefaultInt32 (401); - builder.setDefaultInt64 (402); - builder.setDefaultUint32 (403); - builder.setDefaultUint64 (404); - builder.setDefaultSint32 (405); - builder.setDefaultSint64 (406); - builder.setDefaultFixed32 (407); - builder.setDefaultFixed64 (408); + builder.setDefaultInt32(401); + builder.setDefaultInt64(402); + builder.setDefaultUint32(403); + builder.setDefaultUint64(404); + builder.setDefaultSint32(405); + builder.setDefaultSint64(406); + builder.setDefaultFixed32(407); + builder.setDefaultFixed64(408); builder.setDefaultSfixed32(409); builder.setDefaultSfixed64(410); - builder.setDefaultFloat (411); - builder.setDefaultDouble (412); - builder.setDefaultBool (false); - builder.setDefaultString ("415"); - builder.setDefaultBytes (toBytes("416")); + builder.setDefaultFloat(411); + builder.setDefaultDouble(412); + builder.setDefaultBool(false); + builder.setDefaultString("415"); + builder.setDefaultBytes(toBytes("416")); - builder.setDefaultNestedEnum (TestAllTypesLite.NestedEnum.FOO); + builder.setDefaultNestedEnum(TestAllTypesLite.NestedEnum.FOO); builder.setDefaultForeignEnum(ForeignEnumLite.FOREIGN_LITE_FOO); - builder.setDefaultImportEnum (ImportEnumLite.IMPORT_LITE_FOO); + builder.setDefaultImportEnum(ImportEnumLite.IMPORT_LITE_FOO); builder.setDefaultStringPiece("424"); builder.setDefaultCord("425"); builder.setOneofUint32(601); - builder.setOneofNestedMessage( - TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build()); + builder.setOneofNestedMessage(TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build()); builder.setOneofString("603"); builder.setOneofBytes(toBytes("604")); } /** - * Get an unmodifiable {@link ExtensionRegistryLite} containing all the - * extensions of {@code TestAllExtensionsLite}. + * Get an unmodifiable {@link ExtensionRegistryLite} containing all the extensions of {@code + * TestAllExtensionsLite}. */ public static ExtensionRegistryLite getExtensionRegistryLite() { ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); @@ -328,8 +310,8 @@ public static ExtensionRegistryLite getExtensionRegistryLite() { } /** - * Register all of {@code TestAllExtensionsLite}'s extensions with the - * given {@link ExtensionRegistryLite}. + * Register all of {@code TestAllExtensionsLite}'s extensions with the given {@link + * ExtensionRegistryLite}. */ public static void registerAllExtensionsLite(ExtensionRegistryLite registry) { UnittestLite.registerAllExtensions(registry); @@ -339,38 +321,40 @@ public static void registerAllExtensionsLite(ExtensionRegistryLite registry) { // Lite extensions /** - * Set every field of {@code message} to the values expected by - * {@code assertAllExtensionsSet()}. + * Set every field of {@code message} to the values expected by {@code assertAllExtensionsSet()}. */ public static void setAllExtensions(TestAllExtensionsLite.Builder message) { - message.setExtension(optionalInt32ExtensionLite , 101); - message.setExtension(optionalInt64ExtensionLite , 102L); - message.setExtension(optionalUint32ExtensionLite , 103); - message.setExtension(optionalUint64ExtensionLite , 104L); - message.setExtension(optionalSint32ExtensionLite , 105); - message.setExtension(optionalSint64ExtensionLite , 106L); - message.setExtension(optionalFixed32ExtensionLite , 107); - message.setExtension(optionalFixed64ExtensionLite , 108L); + message.setExtension(optionalInt32ExtensionLite, 101); + message.setExtension(optionalInt64ExtensionLite, 102L); + message.setExtension(optionalUint32ExtensionLite, 103); + message.setExtension(optionalUint64ExtensionLite, 104L); + message.setExtension(optionalSint32ExtensionLite, 105); + message.setExtension(optionalSint64ExtensionLite, 106L); + message.setExtension(optionalFixed32ExtensionLite, 107); + message.setExtension(optionalFixed64ExtensionLite, 108L); message.setExtension(optionalSfixed32ExtensionLite, 109); message.setExtension(optionalSfixed64ExtensionLite, 110L); - message.setExtension(optionalFloatExtensionLite , 111F); - message.setExtension(optionalDoubleExtensionLite , 112D); - message.setExtension(optionalBoolExtensionLite , true); - message.setExtension(optionalStringExtensionLite , "115"); - message.setExtension(optionalBytesExtensionLite , toBytes("116")); - - message.setExtension(optionalGroupExtensionLite, - OptionalGroup_extension_lite.newBuilder().setA(117).build()); - message.setExtension(optionalNestedMessageExtensionLite, - TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build()); - message.setExtension(optionalForeignMessageExtensionLite, - ForeignMessageLite.newBuilder().setC(119).build()); - message.setExtension(optionalImportMessageExtensionLite, - ImportMessageLite.newBuilder().setD(120).build()); - message.setExtension(optionalPublicImportMessageExtensionLite, - PublicImportMessageLite.newBuilder().setE(126).build()); - message.setExtension(optionalLazyMessageExtensionLite, - TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build()); + message.setExtension(optionalFloatExtensionLite, 111F); + message.setExtension(optionalDoubleExtensionLite, 112D); + message.setExtension(optionalBoolExtensionLite, true); + message.setExtension(optionalStringExtensionLite, "115"); + message.setExtension(optionalBytesExtensionLite, toBytes("116")); + + message.setExtension( + optionalGroupExtensionLite, OptionalGroup_extension_lite.newBuilder().setA(117).build()); + message.setExtension( + optionalNestedMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build()); + message.setExtension( + optionalForeignMessageExtensionLite, ForeignMessageLite.newBuilder().setC(119).build()); + message.setExtension( + optionalImportMessageExtensionLite, ImportMessageLite.newBuilder().setD(120).build()); + message.setExtension( + optionalPublicImportMessageExtensionLite, + PublicImportMessageLite.newBuilder().setE(126).build()); + message.setExtension( + optionalLazyMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build()); message.setExtension(optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ); message.setExtension(optionalForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ); @@ -381,32 +365,34 @@ public static void setAllExtensions(TestAllExtensionsLite.Builder message) { // ----------------------------------------------------------------- - message.addExtension(repeatedInt32ExtensionLite , 201); - message.addExtension(repeatedInt64ExtensionLite , 202L); - message.addExtension(repeatedUint32ExtensionLite , 203); - message.addExtension(repeatedUint64ExtensionLite , 204L); - message.addExtension(repeatedSint32ExtensionLite , 205); - message.addExtension(repeatedSint64ExtensionLite , 206L); - message.addExtension(repeatedFixed32ExtensionLite , 207); - message.addExtension(repeatedFixed64ExtensionLite , 208L); + message.addExtension(repeatedInt32ExtensionLite, 201); + message.addExtension(repeatedInt64ExtensionLite, 202L); + message.addExtension(repeatedUint32ExtensionLite, 203); + message.addExtension(repeatedUint64ExtensionLite, 204L); + message.addExtension(repeatedSint32ExtensionLite, 205); + message.addExtension(repeatedSint64ExtensionLite, 206L); + message.addExtension(repeatedFixed32ExtensionLite, 207); + message.addExtension(repeatedFixed64ExtensionLite, 208L); message.addExtension(repeatedSfixed32ExtensionLite, 209); message.addExtension(repeatedSfixed64ExtensionLite, 210L); - message.addExtension(repeatedFloatExtensionLite , 211F); - message.addExtension(repeatedDoubleExtensionLite , 212D); - message.addExtension(repeatedBoolExtensionLite , true); - message.addExtension(repeatedStringExtensionLite , "215"); - message.addExtension(repeatedBytesExtensionLite , toBytes("216")); - - message.addExtension(repeatedGroupExtensionLite, - RepeatedGroup_extension_lite.newBuilder().setA(217).build()); - message.addExtension(repeatedNestedMessageExtensionLite, - TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build()); - message.addExtension(repeatedForeignMessageExtensionLite, - ForeignMessageLite.newBuilder().setC(219).build()); - message.addExtension(repeatedImportMessageExtensionLite, - ImportMessageLite.newBuilder().setD(220).build()); - message.addExtension(repeatedLazyMessageExtensionLite, - TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build()); + message.addExtension(repeatedFloatExtensionLite, 211F); + message.addExtension(repeatedDoubleExtensionLite, 212D); + message.addExtension(repeatedBoolExtensionLite, true); + message.addExtension(repeatedStringExtensionLite, "215"); + message.addExtension(repeatedBytesExtensionLite, toBytes("216")); + + message.addExtension( + repeatedGroupExtensionLite, RepeatedGroup_extension_lite.newBuilder().setA(217).build()); + message.addExtension( + repeatedNestedMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build()); + message.addExtension( + repeatedForeignMessageExtensionLite, ForeignMessageLite.newBuilder().setC(219).build()); + message.addExtension( + repeatedImportMessageExtensionLite, ImportMessageLite.newBuilder().setD(220).build()); + message.addExtension( + repeatedLazyMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build()); message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAR); message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR); @@ -416,32 +402,34 @@ public static void setAllExtensions(TestAllExtensionsLite.Builder message) { message.addExtension(repeatedCordExtensionLite, "225"); // Add a second one of each field. - message.addExtension(repeatedInt32ExtensionLite , 301); - message.addExtension(repeatedInt64ExtensionLite , 302L); - message.addExtension(repeatedUint32ExtensionLite , 303); - message.addExtension(repeatedUint64ExtensionLite , 304L); - message.addExtension(repeatedSint32ExtensionLite , 305); - message.addExtension(repeatedSint64ExtensionLite , 306L); - message.addExtension(repeatedFixed32ExtensionLite , 307); - message.addExtension(repeatedFixed64ExtensionLite , 308L); + message.addExtension(repeatedInt32ExtensionLite, 301); + message.addExtension(repeatedInt64ExtensionLite, 302L); + message.addExtension(repeatedUint32ExtensionLite, 303); + message.addExtension(repeatedUint64ExtensionLite, 304L); + message.addExtension(repeatedSint32ExtensionLite, 305); + message.addExtension(repeatedSint64ExtensionLite, 306L); + message.addExtension(repeatedFixed32ExtensionLite, 307); + message.addExtension(repeatedFixed64ExtensionLite, 308L); message.addExtension(repeatedSfixed32ExtensionLite, 309); message.addExtension(repeatedSfixed64ExtensionLite, 310L); - message.addExtension(repeatedFloatExtensionLite , 311F); - message.addExtension(repeatedDoubleExtensionLite , 312D); - message.addExtension(repeatedBoolExtensionLite , false); - message.addExtension(repeatedStringExtensionLite , "315"); - message.addExtension(repeatedBytesExtensionLite , toBytes("316")); - - message.addExtension(repeatedGroupExtensionLite, - RepeatedGroup_extension_lite.newBuilder().setA(317).build()); - message.addExtension(repeatedNestedMessageExtensionLite, - TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build()); - message.addExtension(repeatedForeignMessageExtensionLite, - ForeignMessageLite.newBuilder().setC(319).build()); - message.addExtension(repeatedImportMessageExtensionLite, - ImportMessageLite.newBuilder().setD(320).build()); - message.addExtension(repeatedLazyMessageExtensionLite, - TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build()); + message.addExtension(repeatedFloatExtensionLite, 311F); + message.addExtension(repeatedDoubleExtensionLite, 312D); + message.addExtension(repeatedBoolExtensionLite, false); + message.addExtension(repeatedStringExtensionLite, "315"); + message.addExtension(repeatedBytesExtensionLite, toBytes("316")); + + message.addExtension( + repeatedGroupExtensionLite, RepeatedGroup_extension_lite.newBuilder().setA(317).build()); + message.addExtension( + repeatedNestedMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build()); + message.addExtension( + repeatedForeignMessageExtensionLite, ForeignMessageLite.newBuilder().setC(319).build()); + message.addExtension( + repeatedImportMessageExtensionLite, ImportMessageLite.newBuilder().setD(320).build()); + message.addExtension( + repeatedLazyMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build()); message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ); message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ); @@ -452,21 +440,21 @@ public static void setAllExtensions(TestAllExtensionsLite.Builder message) { // ----------------------------------------------------------------- - message.setExtension(defaultInt32ExtensionLite , 401); - message.setExtension(defaultInt64ExtensionLite , 402L); - message.setExtension(defaultUint32ExtensionLite , 403); - message.setExtension(defaultUint64ExtensionLite , 404L); - message.setExtension(defaultSint32ExtensionLite , 405); - message.setExtension(defaultSint64ExtensionLite , 406L); - message.setExtension(defaultFixed32ExtensionLite , 407); - message.setExtension(defaultFixed64ExtensionLite , 408L); + message.setExtension(defaultInt32ExtensionLite, 401); + message.setExtension(defaultInt64ExtensionLite, 402L); + message.setExtension(defaultUint32ExtensionLite, 403); + message.setExtension(defaultUint64ExtensionLite, 404L); + message.setExtension(defaultSint32ExtensionLite, 405); + message.setExtension(defaultSint64ExtensionLite, 406L); + message.setExtension(defaultFixed32ExtensionLite, 407); + message.setExtension(defaultFixed64ExtensionLite, 408L); message.setExtension(defaultSfixed32ExtensionLite, 409); message.setExtension(defaultSfixed64ExtensionLite, 410L); - message.setExtension(defaultFloatExtensionLite , 411F); - message.setExtension(defaultDoubleExtensionLite , 412D); - message.setExtension(defaultBoolExtensionLite , false); - message.setExtension(defaultStringExtensionLite , "415"); - message.setExtension(defaultBytesExtensionLite , toBytes("416")); + message.setExtension(defaultFloatExtensionLite, 411F); + message.setExtension(defaultDoubleExtensionLite, 412D); + message.setExtension(defaultBoolExtensionLite, false); + message.setExtension(defaultStringExtensionLite, "415"); + message.setExtension(defaultBytesExtensionLite, toBytes("416")); message.setExtension(defaultNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.FOO); message.setExtension(defaultForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_FOO); @@ -476,8 +464,9 @@ public static void setAllExtensions(TestAllExtensionsLite.Builder message) { message.setExtension(defaultCordExtensionLite, "425"); message.setExtension(oneofUint32ExtensionLite, 601); - message.setExtension(oneofNestedMessageExtensionLite, - TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build()); + message.setExtension( + oneofNestedMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build()); message.setExtension(oneofStringExtensionLite, "603"); message.setExtension(oneofBytesExtensionLite, toBytes("604")); } @@ -485,75 +474,78 @@ public static void setAllExtensions(TestAllExtensionsLite.Builder message) { // ------------------------------------------------------------------- /** - * Modify the repeated extensions of {@code message} to contain the values - * expected by {@code assertRepeatedExtensionsModified()}. + * Modify the repeated extensions of {@code message} to contain the values expected by {@code + * assertRepeatedExtensionsModified()}. */ - public static void modifyRepeatedExtensions( - TestAllExtensionsLite.Builder message) { - message.setExtension(repeatedInt32ExtensionLite , 1, 501); - message.setExtension(repeatedInt64ExtensionLite , 1, 502L); - message.setExtension(repeatedUint32ExtensionLite , 1, 503); - message.setExtension(repeatedUint64ExtensionLite , 1, 504L); - message.setExtension(repeatedSint32ExtensionLite , 1, 505); - message.setExtension(repeatedSint64ExtensionLite , 1, 506L); - message.setExtension(repeatedFixed32ExtensionLite , 1, 507); - message.setExtension(repeatedFixed64ExtensionLite , 1, 508L); + public static void modifyRepeatedExtensions(TestAllExtensionsLite.Builder message) { + message.setExtension(repeatedInt32ExtensionLite, 1, 501); + message.setExtension(repeatedInt64ExtensionLite, 1, 502L); + message.setExtension(repeatedUint32ExtensionLite, 1, 503); + message.setExtension(repeatedUint64ExtensionLite, 1, 504L); + message.setExtension(repeatedSint32ExtensionLite, 1, 505); + message.setExtension(repeatedSint64ExtensionLite, 1, 506L); + message.setExtension(repeatedFixed32ExtensionLite, 1, 507); + message.setExtension(repeatedFixed64ExtensionLite, 1, 508L); message.setExtension(repeatedSfixed32ExtensionLite, 1, 509); message.setExtension(repeatedSfixed64ExtensionLite, 1, 510L); - message.setExtension(repeatedFloatExtensionLite , 1, 511F); - message.setExtension(repeatedDoubleExtensionLite , 1, 512D); - message.setExtension(repeatedBoolExtensionLite , 1, true); - message.setExtension(repeatedStringExtensionLite , 1, "515"); - message.setExtension(repeatedBytesExtensionLite , 1, toBytes("516")); - - message.setExtension(repeatedGroupExtensionLite, 1, - RepeatedGroup_extension_lite.newBuilder().setA(517).build()); - message.setExtension(repeatedNestedMessageExtensionLite, 1, - TestAllTypesLite.NestedMessage.newBuilder().setBb(518).build()); - message.setExtension(repeatedForeignMessageExtensionLite, 1, - ForeignMessageLite.newBuilder().setC(519).build()); - message.setExtension(repeatedImportMessageExtensionLite, 1, - ImportMessageLite.newBuilder().setD(520).build()); - message.setExtension(repeatedLazyMessageExtensionLite, 1, - TestAllTypesLite.NestedMessage.newBuilder().setBb(527).build()); - - message.setExtension(repeatedNestedEnumExtensionLite , 1, TestAllTypesLite.NestedEnum.FOO); + message.setExtension(repeatedFloatExtensionLite, 1, 511F); + message.setExtension(repeatedDoubleExtensionLite, 1, 512D); + message.setExtension(repeatedBoolExtensionLite, 1, true); + message.setExtension(repeatedStringExtensionLite, 1, "515"); + message.setExtension(repeatedBytesExtensionLite, 1, toBytes("516")); + + message.setExtension( + repeatedGroupExtensionLite, 1, RepeatedGroup_extension_lite.newBuilder().setA(517).build()); + message.setExtension( + repeatedNestedMessageExtensionLite, + 1, + TestAllTypesLite.NestedMessage.newBuilder().setBb(518).build()); + message.setExtension( + repeatedForeignMessageExtensionLite, 1, ForeignMessageLite.newBuilder().setC(519).build()); + message.setExtension( + repeatedImportMessageExtensionLite, 1, ImportMessageLite.newBuilder().setD(520).build()); + message.setExtension( + repeatedLazyMessageExtensionLite, + 1, + TestAllTypesLite.NestedMessage.newBuilder().setBb(527).build()); + + message.setExtension(repeatedNestedEnumExtensionLite, 1, TestAllTypesLite.NestedEnum.FOO); message.setExtension(repeatedForeignEnumExtensionLite, 1, ForeignEnumLite.FOREIGN_LITE_FOO); - message.setExtension(repeatedImportEnumExtensionLite , 1, ImportEnumLite.IMPORT_LITE_FOO); + message.setExtension(repeatedImportEnumExtensionLite, 1, ImportEnumLite.IMPORT_LITE_FOO); message.setExtension(repeatedStringPieceExtensionLite, 1, "524"); message.setExtension(repeatedCordExtensionLite, 1, "525"); } public static void setPackedExtensions(TestPackedExtensionsLite.Builder message) { - message.addExtension(packedInt32ExtensionLite , 601); - message.addExtension(packedInt64ExtensionLite , 602L); - message.addExtension(packedUint32ExtensionLite , 603); - message.addExtension(packedUint64ExtensionLite , 604L); - message.addExtension(packedSint32ExtensionLite , 605); - message.addExtension(packedSint64ExtensionLite , 606L); - message.addExtension(packedFixed32ExtensionLite , 607); - message.addExtension(packedFixed64ExtensionLite , 608L); + message.addExtension(packedInt32ExtensionLite, 601); + message.addExtension(packedInt64ExtensionLite, 602L); + message.addExtension(packedUint32ExtensionLite, 603); + message.addExtension(packedUint64ExtensionLite, 604L); + message.addExtension(packedSint32ExtensionLite, 605); + message.addExtension(packedSint64ExtensionLite, 606L); + message.addExtension(packedFixed32ExtensionLite, 607); + message.addExtension(packedFixed64ExtensionLite, 608L); message.addExtension(packedSfixed32ExtensionLite, 609); message.addExtension(packedSfixed64ExtensionLite, 610L); - message.addExtension(packedFloatExtensionLite , 611F); - message.addExtension(packedDoubleExtensionLite , 612D); - message.addExtension(packedBoolExtensionLite , true); + message.addExtension(packedFloatExtensionLite, 611F); + message.addExtension(packedDoubleExtensionLite, 612D); + message.addExtension(packedBoolExtensionLite, true); message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR); // Add a second one of each field. - message.addExtension(packedInt32ExtensionLite , 701); - message.addExtension(packedInt64ExtensionLite , 702L); - message.addExtension(packedUint32ExtensionLite , 703); - message.addExtension(packedUint64ExtensionLite , 704L); - message.addExtension(packedSint32ExtensionLite , 705); - message.addExtension(packedSint64ExtensionLite , 706L); - message.addExtension(packedFixed32ExtensionLite , 707); - message.addExtension(packedFixed64ExtensionLite , 708L); + message.addExtension(packedInt32ExtensionLite, 701); + message.addExtension(packedInt64ExtensionLite, 702L); + message.addExtension(packedUint32ExtensionLite, 703); + message.addExtension(packedUint64ExtensionLite, 704L); + message.addExtension(packedSint32ExtensionLite, 705); + message.addExtension(packedSint64ExtensionLite, 706L); + message.addExtension(packedFixed32ExtensionLite, 707); + message.addExtension(packedFixed64ExtensionLite, 708L); message.addExtension(packedSfixed32ExtensionLite, 709); message.addExtension(packedSfixed64ExtensionLite, 710L); - message.addExtension(packedFloatExtensionLite , 711F); - message.addExtension(packedDoubleExtensionLite , 712D); - message.addExtension(packedBoolExtensionLite , false); + message.addExtension(packedFloatExtensionLite, 711F); + message.addExtension(packedDoubleExtensionLite, 712D); + message.addExtension(packedBoolExtensionLite, false); message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ); } } diff --git a/java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java index e338af2112827..ff413720b779a 100644 --- a/java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java +++ b/java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java @@ -33,12 +33,9 @@ import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import protobuf_unittest.UnittestProto.TestAllTypes; - import junit.framework.TestCase; -/** - * Test @{link TextFormatParseInfoTree}. - */ +/** Test @{link TextFormatParseInfoTree}. */ public class TextFormatParseInfoTreeTest extends TestCase { private static final Descriptor DESCRIPTOR = TestAllTypes.getDescriptor(); @@ -75,7 +72,7 @@ public void testGetLocationReturnsSingleLocation() { TextFormatParseInfoTree root = rootBuilder.build(); assertEquals(LOC0, root.getLocation(OPTIONAL_INT32, 0)); assertEquals(1, root.getLocations(OPTIONAL_INT32).size()); - } + } public void testGetLocationsReturnsNoParseLocationsForUnknownField() { assertTrue(rootBuilder.build().getLocations(OPTIONAL_INT32).isEmpty()); diff --git a/java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java index c42bfa6e71aef..19abc3f88fa8b 100644 --- a/java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java +++ b/java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java @@ -32,9 +32,7 @@ import junit.framework.TestCase; -/** - * Test @{link TextFormatParseLocation}. - */ +/** Test @{link TextFormatParseLocation}. */ public class TextFormatParseLocationTest extends TestCase { public void testCreateEmpty() { diff --git a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java index 910f360f097d6..a919f3b9ff6ab 100644 --- a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java +++ b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java @@ -30,9 +30,20 @@ package com.google.protobuf; +import static com.google.common.truth.Truth.assertThat; +import static com.google.protobuf.TestUtil.TEST_REQUIRED_INITIALIZED; +import static com.google.protobuf.TestUtil.TEST_REQUIRED_UNINITIALIZED; + +import com.google.protobuf.DescriptorProtos.DescriptorProto; +import com.google.protobuf.DescriptorProtos.FieldDescriptorProto; +import com.google.protobuf.DescriptorProtos.FileDescriptorProto; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Descriptors.FileDescriptor; import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy; +import com.google.protobuf.testing.proto.TestProto3Optional; +import com.google.protobuf.testing.proto.TestProto3Optional.NestedEnum; +import any_test.AnyTestProto.TestAny; import map_test.MapTestProto.TestMap; import protobuf_unittest.UnittestMset.TestMessageSetExtension1; import protobuf_unittest.UnittestMset.TestMessageSetExtension2; @@ -42,97 +53,110 @@ import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage; import protobuf_unittest.UnittestProto.TestEmptyMessage; import protobuf_unittest.UnittestProto.TestOneof2; +import protobuf_unittest.UnittestProto.TestRequired; import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet; import java.io.StringReader; +import java.util.Arrays; import java.util.List; +import java.util.logging.Logger; import junit.framework.TestCase; /** * Test case for {@link TextFormat}. * - * TODO(wenboz): ExtensionTest and rest of text_format_unittest.cc. + *

TODO(wenboz): ExtensionTest and rest of text_format_unittest.cc. * * @author wenboz@google.com (Wenbo Zhu) */ public class TextFormatTest extends TestCase { // A basic string with different escapable characters for testing. - private final static String kEscapeTestString = - "\"A string with ' characters \n and \r newlines and \t tabs and \001 " - + "slashes \\"; + private static final String ESCAPE_TEST_STRING = + "\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\"; // A representation of the above string with all the characters escaped. - private final static String kEscapeTestStringEscaped = + private static final String ESCAPE_TEST_STRING_ESCAPED = "\\\"A string with \\' characters \\n and \\r newlines " + "and \\t tabs and \\001 slashes \\\\"; - private static String allFieldsSetText = TestUtil.readTextFromFile( - "text_format_unittest_data_oneof_implemented.txt"); - private static String allExtensionsSetText = TestUtil.readTextFromFile( - "text_format_unittest_extensions_data.txt"); + private static String allFieldsSetText = + TestUtil.readTextFromFile("text_format_unittest_data_oneof_implemented.txt"); + private static String allExtensionsSetText = + TestUtil.readTextFromFile("text_format_unittest_extensions_data.txt"); private static String exoticText = - "repeated_int32: -1\n" + - "repeated_int32: -2147483648\n" + - "repeated_int64: -1,\n" + - "repeated_int64: -9223372036854775808\n" + - "repeated_uint32: 4294967295\n" + - "repeated_uint32: 2147483648\n" + - "repeated_uint64: 18446744073709551615\n" + - "repeated_uint64: 9223372036854775808\n" + - "repeated_double: 123.0\n" + - "repeated_double: 123.5\n" + - "repeated_double: 0.125\n" + - "repeated_double: .125\n" + - "repeated_double: -.125\n" + - "repeated_double: 1.23E17\n" + - "repeated_double: 1.23E+17\n" + - "repeated_double: -1.23e-17\n" + - "repeated_double: .23e+17\n" + - "repeated_double: -.23E17\n" + - "repeated_double: 1.235E22\n" + - "repeated_double: 1.235E-18\n" + - "repeated_double: 123.456789\n" + - "repeated_double: Infinity\n" + - "repeated_double: -Infinity\n" + - "repeated_double: NaN\n" + - "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"" + - "\\341\\210\\264\"\n" + - "repeated_bytes: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\376\"\n"; + "" + + "repeated_int32: -1\n" + + "repeated_int32: -2147483648\n" + + "repeated_int64: -1,\n" + + "repeated_int64: -9223372036854775808\n" + + "repeated_uint32: 4294967295\n" + + "repeated_uint32: 2147483648\n" + + "repeated_uint64: 18446744073709551615\n" + + "repeated_uint64: 9223372036854775808\n" + + "repeated_double: 123.0\n" + + "repeated_double: 123.5\n" + + "repeated_double: 0.125\n" + + "repeated_double: .125\n" + + "repeated_double: -.125\n" + + "repeated_double: 1.23E17\n" + + "repeated_double: 1.23E+17\n" + + "repeated_double: -1.23e-17\n" + + "repeated_double: .23e+17\n" + + "repeated_double: -.23E17\n" + + "repeated_double: 1.235E22\n" + + "repeated_double: 1.235E-18\n" + + "repeated_double: 123.456789\n" + + "repeated_double: Infinity\n" + + "repeated_double: -Infinity\n" + + "repeated_double: NaN\n" + + "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"" + + "\\341\\210\\264\"\n" + + "repeated_bytes: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\376\"\n"; private static String canonicalExoticText = - exoticText.replace(": .", ": 0.").replace(": -.", ": -0.") // short-form double - .replace("23e", "23E").replace("E+", "E").replace("0.23E17", "2.3E16").replace(",", ""); + exoticText + .replace(": .", ": 0.") + .replace(": -.", ": -0.") // short-form double + .replace("23e", "23E") + .replace("E+", "E") + .replace("0.23E17", "2.3E16") + .replace(",", ""); private String messageSetText = - "[protobuf_unittest.TestMessageSetExtension1] {\n" + - " i: 123\n" + - "}\n" + - "[protobuf_unittest.TestMessageSetExtension2] {\n" + - " str: \"foo\"\n" + - "}\n"; + "" + + "[protobuf_unittest.TestMessageSetExtension1] {\n" + + " i: 123\n" + + "}\n" + + "[protobuf_unittest.TestMessageSetExtension2] {\n" + + " str: \"foo\"\n" + + "}\n"; private String messageSetTextWithRepeatedExtension = - "[protobuf_unittest.TestMessageSetExtension1] {\n" + - " i: 123\n" + - "}\n" + - "[protobuf_unittest.TestMessageSetExtension1] {\n" + - " i: 456\n" + - "}\n"; + "" + + "[protobuf_unittest.TestMessageSetExtension1] {\n" + + " i: 123\n" + + "}\n" + + "[protobuf_unittest.TestMessageSetExtension1] {\n" + + " i: 456\n" + + "}\n"; + + private final TextFormat.Parser parserAllowingUnknownFields = + TextFormat.Parser.newBuilder().setAllowUnknownFields(true).build(); + private final TextFormat.Parser parserAllowingUnknownExtensions = + TextFormat.Parser.newBuilder().setAllowUnknownExtensions(true).build(); private final TextFormat.Parser parserWithOverwriteForbidden = TextFormat.Parser.newBuilder() - .setSingularOverwritePolicy( - SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES) + .setSingularOverwritePolicy(SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES) .build(); - private final TextFormat.Parser defaultParser = - TextFormat.Parser.newBuilder().build(); + private final TextFormat.Parser defaultParser = TextFormat.Parser.newBuilder().build(); /** Print TestAllTypes and compare with golden file. */ public void testPrintMessage() throws Exception { - String javaText = TextFormat.printToString(TestUtil.getAllSet()); + String javaText = TextFormat.printer().printToString(TestUtil.getAllSet()); // Java likes to add a trailing ".0" to floats and doubles. C printf // (with %g format) does not. Our golden files are used for both @@ -144,7 +168,7 @@ public void testPrintMessage() throws Exception { /** Print TestAllTypes as Builder and compare with golden file. */ public void testPrintMessageBuilder() throws Exception { - String javaText = TextFormat.printToString(TestUtil.getAllSetBuilder()); + String javaText = TextFormat.printer().printToString(TestUtil.getAllSetBuilder()); // Java likes to add a trailing ".0" to floats and doubles. C printf // (with %g format) does not. Our golden files are used for both @@ -156,7 +180,7 @@ public void testPrintMessageBuilder() throws Exception { /** Print TestAllExtensions and compare with golden file. */ public void testPrintExtensions() throws Exception { - String javaText = TextFormat.printToString(TestUtil.getAllExtensionsSet()); + String javaText = TextFormat.printer().printToString(TestUtil.getAllExtensionsSet()); // Java likes to add a trailing ".0" to floats and doubles. C printf // (with %g format) does not. Our golden files are used for both @@ -168,33 +192,34 @@ public void testPrintExtensions() throws Exception { // Creates an example unknown field set. private UnknownFieldSet makeUnknownFieldSet() { + return UnknownFieldSet.newBuilder() - .addField(5, + .addField( + 5, UnknownFieldSet.Field.newBuilder() - .addVarint(1) - .addFixed32(2) - .addFixed64(3) - .addLengthDelimited(ByteString.copyFromUtf8("4")) - .addGroup( - UnknownFieldSet.newBuilder() - .addField(10, - UnknownFieldSet.Field.newBuilder() - .addVarint(5) - .build()) + .addVarint(1) + .addFixed32(2) + .addFixed64(3) + .addLengthDelimited(ByteString.copyFromUtf8("4")) + .addLengthDelimited( + UnknownFieldSet.newBuilder() + .addField(12, UnknownFieldSet.Field.newBuilder().addVarint(6).build()) + .build() + .toByteString()) + .addGroup( + UnknownFieldSet.newBuilder() + .addField(10, UnknownFieldSet.Field.newBuilder().addVarint(5).build()) + .build()) .build()) - .build()) - .addField(8, - UnknownFieldSet.Field.newBuilder() - .addVarint(1) - .addVarint(2) - .addVarint(3) - .build()) - .addField(15, + .addField( + 8, UnknownFieldSet.Field.newBuilder().addVarint(1).addVarint(2).addVarint(3).build()) + .addField( + 15, UnknownFieldSet.Field.newBuilder() - .addVarint(0xABCDEF1234567890L) - .addFixed32(0xABCD1234) - .addFixed64(0xABCDEF1234567890L) - .build()) + .addVarint(0xABCDEF1234567890L) + .addFixed32(0xABCD1234) + .addFixed64(0xABCDEF1234567890L) + .build()) .build(); } @@ -202,56 +227,53 @@ public void testPrintUnknownFields() throws Exception { // Test printing of unknown fields in a message. TestEmptyMessage message = - TestEmptyMessage.newBuilder() - .setUnknownFields(makeUnknownFieldSet()) - .build(); + TestEmptyMessage.newBuilder().setUnknownFields(makeUnknownFieldSet()).build(); assertEquals( - "5: 1\n" + - "5: 0x00000002\n" + - "5: 0x0000000000000003\n" + - "5: \"4\"\n" + - "5 {\n" + - " 10: 5\n" + - "}\n" + - "8: 1\n" + - "8: 2\n" + - "8: 3\n" + - "15: 12379813812177893520\n" + - "15: 0xabcd1234\n" + - "15: 0xabcdef1234567890\n", - TextFormat.printToString(message)); + "5: 1\n" + + "5: 0x00000002\n" + + "5: 0x0000000000000003\n" + + "5: \"4\"\n" + + "5: {\n" + + " 12: 6\n" + + "}\n" + + "5 {\n" + + " 10: 5\n" + + "}\n" + + "8: 1\n" + + "8: 2\n" + + "8: 3\n" + + "15: 12379813812177893520\n" + + "15: 0xabcd1234\n" + + "15: 0xabcdef1234567890\n", + TextFormat.printer().printToString(message)); } public void testPrintField() throws Exception { - final FieldDescriptor dataField = - OneString.getDescriptor().findFieldByName("data"); + final FieldDescriptor dataField = OneString.getDescriptor().findFieldByName("data"); assertEquals( - "data: \"test data\"\n", - TextFormat.printFieldToString(dataField, "test data")); + "data: \"test data\"\n", TextFormat.printer().printFieldToString(dataField, "test data")); final FieldDescriptor optionalField = - TestAllTypes.getDescriptor().findFieldByName("optional_nested_message"); + TestAllTypes.getDescriptor().findFieldByName("optional_nested_message"); final Object value = NestedMessage.newBuilder().setBb(42).build(); assertEquals( - "optional_nested_message {\n bb: 42\n}\n", - TextFormat.printFieldToString(optionalField, value)); + "optional_nested_message {\n bb: 42\n}\n", + TextFormat.printer().printFieldToString(optionalField, value)); } /** - * Helper to construct a ByteString from a String containing only 8-bit - * characters. The characters are converted directly to bytes, *not* - * encoded using UTF-8. + * Helper to construct a ByteString from a String containing only 8-bit characters. The characters + * are converted directly to bytes, *not* encoded using UTF-8. */ private ByteString bytes(String str) { return ByteString.copyFrom(str.getBytes(Internal.ISO_8859_1)); } /** - * Helper to construct a ByteString from a bunch of bytes. The inputs are - * actually ints so that I can use hex notation and not get stupid errors - * about precision. + * Helper to construct a ByteString from a bunch of bytes. The inputs are actually ints so that I + * can use hex notation and not get stupid errors about precision. */ private ByteString bytes(int... bytesAsInts) { byte[] bytes = new byte[bytesAsInts.length]; @@ -262,120 +284,184 @@ private ByteString bytes(int... bytesAsInts) { } public void testPrintExotic() throws Exception { - Message message = TestAllTypes.newBuilder() - // Signed vs. unsigned numbers. - .addRepeatedInt32 (-1) - .addRepeatedUint32(-1) - .addRepeatedInt64 (-1) - .addRepeatedUint64(-1) - - .addRepeatedInt32 (1 << 31) - .addRepeatedUint32(1 << 31) - .addRepeatedInt64 (1L << 63) - .addRepeatedUint64(1L << 63) - - // Floats of various precisions and exponents. - .addRepeatedDouble(123) - .addRepeatedDouble(123.5) - .addRepeatedDouble(0.125) - .addRepeatedDouble(.125) - .addRepeatedDouble(-.125) - .addRepeatedDouble(123e15) - .addRepeatedDouble(123e15) - .addRepeatedDouble(-1.23e-17) - .addRepeatedDouble(.23e17) - .addRepeatedDouble(-23e15) - .addRepeatedDouble(123.5e20) - .addRepeatedDouble(123.5e-20) - .addRepeatedDouble(123.456789) - .addRepeatedDouble(Double.POSITIVE_INFINITY) - .addRepeatedDouble(Double.NEGATIVE_INFINITY) - .addRepeatedDouble(Double.NaN) - - // Strings and bytes that needing escaping. - .addRepeatedString("\0\001\007\b\f\n\r\t\013\\\'\"\u1234") - .addRepeatedBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\u00fe")) - .build(); + Message message = + TestAllTypes.newBuilder() + // Signed vs. unsigned numbers. + .addRepeatedInt32(-1) + .addRepeatedUint32(-1) + .addRepeatedInt64(-1) + .addRepeatedUint64(-1) + .addRepeatedInt32(1 << 31) + .addRepeatedUint32(1 << 31) + .addRepeatedInt64(1L << 63) + .addRepeatedUint64(1L << 63) + + // Floats of various precisions and exponents. + .addRepeatedDouble(123) + .addRepeatedDouble(123.5) + .addRepeatedDouble(0.125) + .addRepeatedDouble(.125) + .addRepeatedDouble(-.125) + .addRepeatedDouble(123e15) + .addRepeatedDouble(123e15) + .addRepeatedDouble(-1.23e-17) + .addRepeatedDouble(.23e17) + .addRepeatedDouble(-23e15) + .addRepeatedDouble(123.5e20) + .addRepeatedDouble(123.5e-20) + .addRepeatedDouble(123.456789) + .addRepeatedDouble(Double.POSITIVE_INFINITY) + .addRepeatedDouble(Double.NEGATIVE_INFINITY) + .addRepeatedDouble(Double.NaN) + + // Strings and bytes that needing escaping. + .addRepeatedString("\0\001\007\b\f\n\r\t\013\\\'\"\u1234") + .addRepeatedBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\u00fe")) + .build(); assertEquals(canonicalExoticText, message.toString()); } + public void testRoundtripProto3Optional() throws Exception { + Message message = + TestProto3Optional.newBuilder() + .setOptionalInt32(1) + .setOptionalInt64(2) + .setOptionalNestedEnum(NestedEnum.BAZ) + .build(); + TestProto3Optional.Builder message2 = TestProto3Optional.newBuilder(); + TextFormat.merge(message.toString(), message2); + + assertTrue(message2.hasOptionalInt32()); + assertTrue(message2.hasOptionalInt64()); + assertTrue(message2.hasOptionalNestedEnum()); + assertEquals(1, message2.getOptionalInt32()); + assertEquals(2, message2.getOptionalInt64()); + assertEquals(NestedEnum.BAZ, message2.getOptionalNestedEnum()); + } + public void testPrintMessageSet() throws Exception { TestMessageSet messageSet = - TestMessageSet.newBuilder() - .setExtension( - TestMessageSetExtension1.messageSetExtension, - TestMessageSetExtension1.newBuilder().setI(123).build()) - .setExtension( - TestMessageSetExtension2.messageSetExtension, - TestMessageSetExtension2.newBuilder().setStr("foo").build()) - .build(); + TestMessageSet.newBuilder() + .setExtension( + TestMessageSetExtension1.messageSetExtension, + TestMessageSetExtension1.newBuilder().setI(123).build()) + .setExtension( + TestMessageSetExtension2.messageSetExtension, + TestMessageSetExtension2.newBuilder().setStr("foo").build()) + .build(); assertEquals(messageSetText, messageSet.toString()); } // ================================================================= - public void testParse() throws Exception { + public void testMerge() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TextFormat.merge(allFieldsSetText, builder); TestUtil.assertAllFieldsSet(builder.build()); } - public void testParseReader() throws Exception { + public void testParse() throws Exception { + TestUtil.assertAllFieldsSet(TextFormat.parse(allFieldsSetText, TestAllTypes.class)); + } + + public void testMergeInitialized() throws Exception { + TestRequired.Builder builder = TestRequired.newBuilder(); + TextFormat.merge(TEST_REQUIRED_INITIALIZED.toString(), builder); + assertEquals(TEST_REQUIRED_INITIALIZED.toString(), builder.buildPartial().toString()); + assertTrue(builder.isInitialized()); + } + + public void testParseInitialized() throws Exception { + TestRequired parsed = + TextFormat.parse(TEST_REQUIRED_INITIALIZED.toString(), TestRequired.class); + assertEquals(TEST_REQUIRED_INITIALIZED.toString(), parsed.toString()); + assertTrue(parsed.isInitialized()); + } + + public void testMergeUninitialized() throws Exception { + TestRequired.Builder builder = TestRequired.newBuilder(); + TextFormat.merge(TEST_REQUIRED_UNINITIALIZED.toString(), builder); + assertEquals(TEST_REQUIRED_UNINITIALIZED.toString(), builder.buildPartial().toString()); + assertFalse(builder.isInitialized()); + } + + public void testParseUninitialized() throws Exception { + try { + TextFormat.parse(TEST_REQUIRED_UNINITIALIZED.toString(), TestRequired.class); + fail("Expected UninitializedMessageException."); + } catch (UninitializedMessageException e) { + assertEquals("Message missing required fields: b, c", e.getMessage()); + } + } + + public void testMergeReader() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TextFormat.merge(new StringReader(allFieldsSetText), builder); TestUtil.assertAllFieldsSet(builder.build()); } - public void testParseExtensions() throws Exception { + public void testMergeExtensions() throws Exception { TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); - TextFormat.merge(allExtensionsSetText, - TestUtil.getExtensionRegistry(), - builder); + TextFormat.merge(allExtensionsSetText, TestUtil.getFullExtensionRegistry(), builder); TestUtil.assertAllExtensionsSet(builder.build()); } - public void testParseCompatibility() throws Exception { - String original = "repeated_float: inf\n" + - "repeated_float: -inf\n" + - "repeated_float: nan\n" + - "repeated_float: inff\n" + - "repeated_float: -inff\n" + - "repeated_float: nanf\n" + - "repeated_float: 1.0f\n" + - "repeated_float: infinityf\n" + - "repeated_float: -Infinityf\n" + - "repeated_double: infinity\n" + - "repeated_double: -infinity\n" + - "repeated_double: nan\n"; - String canonical = "repeated_float: Infinity\n" + - "repeated_float: -Infinity\n" + - "repeated_float: NaN\n" + - "repeated_float: Infinity\n" + - "repeated_float: -Infinity\n" + - "repeated_float: NaN\n" + - "repeated_float: 1.0\n" + - "repeated_float: Infinity\n" + - "repeated_float: -Infinity\n" + - "repeated_double: Infinity\n" + - "repeated_double: -Infinity\n" + - "repeated_double: NaN\n"; + public void testParseExtensions() throws Exception { + TestUtil.assertAllExtensionsSet( + TextFormat.parse( + allExtensionsSetText, TestUtil.getFullExtensionRegistry(), TestAllExtensions.class)); + } + + public void testMergeAndParseCompatibility() throws Exception { + String original = + "repeated_float: inf\n" + + "repeated_float: -inf\n" + + "repeated_float: nan\n" + + "repeated_float: inff\n" + + "repeated_float: -inff\n" + + "repeated_float: nanf\n" + + "repeated_float: 1.0f\n" + + "repeated_float: infinityf\n" + + "repeated_float: -Infinityf\n" + + "repeated_double: infinity\n" + + "repeated_double: -infinity\n" + + "repeated_double: nan\n"; + String canonical = + "repeated_float: Infinity\n" + + "repeated_float: -Infinity\n" + + "repeated_float: NaN\n" + + "repeated_float: Infinity\n" + + "repeated_float: -Infinity\n" + + "repeated_float: NaN\n" + + "repeated_float: 1.0\n" + + "repeated_float: Infinity\n" + + "repeated_float: -Infinity\n" + + "repeated_double: Infinity\n" + + "repeated_double: -Infinity\n" + + "repeated_double: NaN\n"; + + // Test merge(). TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TextFormat.merge(original, builder); assertEquals(canonical, builder.build().toString()); + + // Test parse(). + assertEquals(canonical, TextFormat.parse(original, TestAllTypes.class).toString()); } - public void testParseExotic() throws Exception { + public void testMergeAndParseExotic() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TextFormat.merge(exoticText, builder); // Too lazy to check things individually. Don't try to debug this // if testPrintExotic() is failing. assertEquals(canonicalExoticText, builder.build().toString()); + assertEquals(canonicalExoticText, TextFormat.parse(exoticText, TestAllTypes.class).toString()); } - public void testParseMessageSet() throws Exception { + public void testMergeMessageSet() throws Exception { ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); extensionRegistry.add(TestMessageSetExtension2.messageSetExtension); @@ -384,36 +470,29 @@ public void testParseMessageSet() throws Exception { TextFormat.merge(messageSetText, extensionRegistry, builder); TestMessageSet messageSet = builder.build(); - assertTrue(messageSet.hasExtension( - TestMessageSetExtension1.messageSetExtension)); - assertEquals(123, messageSet.getExtension( - TestMessageSetExtension1.messageSetExtension).getI()); - assertTrue(messageSet.hasExtension( - TestMessageSetExtension2.messageSetExtension)); - assertEquals("foo", messageSet.getExtension( - TestMessageSetExtension2.messageSetExtension).getStr()); + assertTrue(messageSet.hasExtension(TestMessageSetExtension1.messageSetExtension)); + assertEquals(123, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()); + assertTrue(messageSet.hasExtension(TestMessageSetExtension2.messageSetExtension)); + assertEquals( + "foo", messageSet.getExtension(TestMessageSetExtension2.messageSetExtension).getStr()); builder = TestMessageSet.newBuilder(); - TextFormat.merge(messageSetTextWithRepeatedExtension, extensionRegistry, - builder); + TextFormat.merge(messageSetTextWithRepeatedExtension, extensionRegistry, builder); messageSet = builder.build(); - assertEquals(456, messageSet.getExtension( - TestMessageSetExtension1.messageSetExtension).getI()); + assertEquals(456, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()); } - public void testParseMessageSetWithOverwriteForbidden() throws Exception { + public void testMergeMessageSetWithOverwriteForbidden() throws Exception { ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); extensionRegistry.add(TestMessageSetExtension2.messageSetExtension); TestMessageSet.Builder builder = TestMessageSet.newBuilder(); - parserWithOverwriteForbidden.merge( - messageSetText, extensionRegistry, builder); + parserWithOverwriteForbidden.merge(messageSetText, extensionRegistry, builder); TestMessageSet messageSet = builder.build(); - assertEquals(123, messageSet.getExtension( - TestMessageSetExtension1.messageSetExtension).getI()); - assertEquals("foo", messageSet.getExtension( - TestMessageSetExtension2.messageSetExtension).getStr()); + assertEquals(123, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()); + assertEquals( + "foo", messageSet.getExtension(TestMessageSetExtension2.messageSetExtension).getStr()); builder = TestMessageSet.newBuilder(); try { @@ -421,175 +500,379 @@ public void testParseMessageSetWithOverwriteForbidden() throws Exception { messageSetTextWithRepeatedExtension, extensionRegistry, builder); fail("expected parse exception"); } catch (TextFormat.ParseException e) { - assertEquals("6:1: Non-repeated field " - + "\"protobuf_unittest.TestMessageSetExtension1.message_set_extension\"" - + " cannot be overwritten.", + assertEquals( + "4:44: Non-repeated field " + + "\"protobuf_unittest.TestMessageSetExtension1.message_set_extension\"" + + " cannot be overwritten.", e.getMessage()); } } - public void testParseNumericEnum() throws Exception { + public void testMergeNumericEnum() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TextFormat.merge("optional_nested_enum: 2", builder); assertEquals(TestAllTypes.NestedEnum.BAR, builder.getOptionalNestedEnum()); } - public void testParseAngleBrackets() throws Exception { + public void testMergeAngleBrackets() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TextFormat.merge("OptionalGroup: < a: 1 >", builder); assertTrue(builder.hasOptionalGroup()); assertEquals(1, builder.getOptionalGroup().getA()); } - public void testParseComment() throws Exception { + public void testMergeComment() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TextFormat.merge( - "# this is a comment\n" + - "optional_int32: 1 # another comment\n" + - "optional_int64: 2\n" + - "# EOF comment", builder); + "# this is a comment\n" + + "optional_int32: 1 # another comment\n" + + "optional_int64: 2\n" + + "# EOF comment", + builder); assertEquals(1, builder.getOptionalInt32()); assertEquals(2, builder.getOptionalInt64()); } + public void testPrintAny_customBuiltTypeRegistry() throws Exception { + TestAny testAny = + TestAny.newBuilder() + .setValue( + Any.newBuilder() + .setTypeUrl("type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName()) + .setValue( + TestAllTypes.newBuilder().setOptionalInt32(12345).build().toByteString()) + .build()) + .build(); + String actual = + TextFormat.printer() + .usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) + .printToString(testAny); + String expected = + "value {\n" + + " [type.googleapis.com/protobuf_unittest.TestAllTypes] {\n" + + " optional_int32: 12345\n" + + " }\n" + + "}\n"; + assertEquals(expected, actual); + } + + private static Descriptor createDescriptorForAny(FieldDescriptorProto... fields) + throws Exception { + FileDescriptor fileDescriptor = + FileDescriptor.buildFrom( + FileDescriptorProto.newBuilder() + .setName("any.proto") + .setPackage("google.protobuf") + .setSyntax("proto3") + .addMessageType( + DescriptorProto.newBuilder() + .setName("Any") + .addAllField(Arrays.asList(fields))) + .build(), + new FileDescriptor[0]); + return fileDescriptor.getMessageTypes().get(0); + } + + public void testPrintAny_anyWithDynamicMessage() throws Exception { + Descriptor descriptor = + createDescriptorForAny( + FieldDescriptorProto.newBuilder() + .setName("type_url") + .setNumber(1) + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setType(FieldDescriptorProto.Type.TYPE_STRING) + .build(), + FieldDescriptorProto.newBuilder() + .setName("value") + .setNumber(2) + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setType(FieldDescriptorProto.Type.TYPE_BYTES) + .build()); + DynamicMessage testAny = + DynamicMessage.newBuilder(descriptor) + .setField( + descriptor.findFieldByNumber(1), + "type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName()) + .setField( + descriptor.findFieldByNumber(2), + TestAllTypes.newBuilder().setOptionalInt32(12345).build().toByteString()) + .build(); + String actual = + TextFormat.printer() + .usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) + .printToString(testAny); + String expected = + "[type.googleapis.com/protobuf_unittest.TestAllTypes] {\n" + + " optional_int32: 12345\n" + + "}\n"; + assertEquals(expected, actual); + } + + public void testPrintAny_anyFromWithNoValueField() throws Exception { + Descriptor descriptor = + createDescriptorForAny( + FieldDescriptorProto.newBuilder() + .setName("type_url") + .setNumber(1) + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setType(FieldDescriptorProto.Type.TYPE_STRING) + .build()); + DynamicMessage testAny = + DynamicMessage.newBuilder(descriptor) + .setField( + descriptor.findFieldByNumber(1), + "type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName()) + .build(); + String actual = + TextFormat.printer() + .usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) + .printToString(testAny); + String expected = "type_url: \"type.googleapis.com/protobuf_unittest.TestAllTypes\"\n"; + assertEquals(expected, actual); + } + + public void testPrintAny_anyFromWithNoTypeUrlField() throws Exception { + Descriptor descriptor = + createDescriptorForAny( + FieldDescriptorProto.newBuilder() + .setName("value") + .setNumber(2) + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setType(FieldDescriptorProto.Type.TYPE_BYTES) + .build()); + DynamicMessage testAny = + DynamicMessage.newBuilder(descriptor) + .setField( + descriptor.findFieldByNumber(2), + TestAllTypes.newBuilder().setOptionalInt32(12345).build().toByteString()) + .build(); + String actual = + TextFormat.printer() + .usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) + .printToString(testAny); + String expected = "value: \"\\b\\271`\"\n"; + assertEquals(expected, actual); + } + + public void testPrintAny_anyWithInvalidFieldType() throws Exception { + Descriptor descriptor = + createDescriptorForAny( + FieldDescriptorProto.newBuilder() + .setName("type_url") + .setNumber(1) + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setType(FieldDescriptorProto.Type.TYPE_STRING) + .build(), + FieldDescriptorProto.newBuilder() + .setName("value") + .setNumber(2) + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setType(FieldDescriptorProto.Type.TYPE_STRING) + .build()); + DynamicMessage testAny = + DynamicMessage.newBuilder(descriptor) + .setField( + descriptor.findFieldByNumber(1), + "type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName()) + .setField(descriptor.findFieldByNumber(2), "test") + .build(); + String actual = + TextFormat.printer() + .usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) + .printToString(testAny); + String expected = + "type_url: \"type.googleapis.com/protobuf_unittest.TestAllTypes\"\n" + "value: \"test\"\n"; + assertEquals(expected, actual); + } + + + public void testMergeAny_customBuiltTypeRegistry() throws Exception { + TestAny.Builder builder = TestAny.newBuilder(); + TextFormat.Parser.newBuilder() + .setTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) + .build() + .merge( + "value: {\n" + + "[type.googleapis.com/protobuf_unittest.TestAllTypes] {\n" + + "optional_int32: 12345\n" + + "optional_nested_message {\n" + + " bb: 123\n" + + "}\n" + + "}\n" + + "}", + builder); + assertEquals( + TestAny.newBuilder() + .setValue( + Any.newBuilder() + .setTypeUrl("type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName()) + .setValue( + TestAllTypes.newBuilder() + .setOptionalInt32(12345) + .setOptionalNestedMessage( + TestAllTypes.NestedMessage.newBuilder().setBb(123)) + .build() + .toByteString()) + .build()) + .build(), + builder.build()); + } + + private void assertParseError(String error, String text) { + // Test merge(). + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + try { + TextFormat.merge(text, TestUtil.getFullExtensionRegistry(), builder); + fail("Expected parse exception."); + } catch (TextFormat.ParseException e) { + assertEquals(error, e.getMessage()); + } + + // Test parse(). + try { + TextFormat.parse(text, TestUtil.getFullExtensionRegistry(), TestAllTypes.class); + fail("Expected parse exception."); + } catch (TextFormat.ParseException e) { + assertEquals(error, e.getMessage()); + } + } + + private void assertParseErrorWithUnknownFields(String error, String text) { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); try { - TextFormat.merge(text, TestUtil.getExtensionRegistry(), builder); + parserAllowingUnknownFields.merge(text, TestUtil.getFullExtensionRegistry(), builder); fail("Expected parse exception."); } catch (TextFormat.ParseException e) { assertEquals(error, e.getMessage()); } } + private TestAllTypes assertParseSuccessWithUnknownFields(String text) + throws TextFormat.ParseException { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + parserAllowingUnknownFields.merge(text, TestUtil.getFullExtensionRegistry(), builder); + return builder.build(); + } - private void assertParseErrorWithOverwriteForbidden(String error, - String text) { + private void assertParseErrorWithUnknownExtensions(String error, String text) { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); try { - parserWithOverwriteForbidden.merge( - text, TestUtil.getExtensionRegistry(), builder); + parserAllowingUnknownExtensions.merge(text, builder); fail("Expected parse exception."); } catch (TextFormat.ParseException e) { assertEquals(error, e.getMessage()); } } - private TestAllTypes assertParseSuccessWithOverwriteForbidden( - String text) throws TextFormat.ParseException { + private TestAllTypes assertParseSuccessWithUnknownExtensions(String text) + throws TextFormat.ParseException { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - parserWithOverwriteForbidden.merge( - text, TestUtil.getExtensionRegistry(), builder); + parserAllowingUnknownExtensions.merge(text, builder); + return builder.build(); + } + + private void assertParseErrorWithOverwriteForbidden(String error, String text) { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + try { + parserWithOverwriteForbidden.merge(text, TestUtil.getFullExtensionRegistry(), builder); + fail("Expected parse exception."); + } catch (TextFormat.ParseException e) { + assertEquals(error, e.getMessage()); + } + } + + private TestAllTypes assertParseSuccessWithOverwriteForbidden(String text) + throws TextFormat.ParseException { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + parserWithOverwriteForbidden.merge(text, TestUtil.getFullExtensionRegistry(), builder); return builder.build(); } public void testParseErrors() throws Exception { + assertParseError("1:16: Expected \":\".", "optional_int32 123"); + assertParseError("1:23: Expected identifier. Found '?'", "optional_nested_enum: ?"); assertParseError( - "1:16: Expected \":\".", - "optional_int32 123"); - assertParseError( - "1:23: Expected identifier. Found '?'", - "optional_nested_enum: ?"); - assertParseError( - "1:18: Couldn't parse integer: Number must be positive: -1", - "optional_uint32: -1"); + "1:18: Couldn't parse integer: Number must be positive: -1", "optional_uint32: -1"); assertParseError( - "1:17: Couldn't parse integer: Number out of range for 32-bit signed " + - "integer: 82301481290849012385230157", - "optional_int32: 82301481290849012385230157"); + "1:17: Couldn't parse integer: Number out of range for 32-bit signed " + + "integer: 82301481290849012385230157", + "optional_int32: 82301481290849012385230157"); assertParseError( - "1:16: Expected \"true\" or \"false\".", - "optional_bool: maybe"); + "1:16: Expected \"true\" or \"false\". Found \"maybe\".", "optional_bool: maybe"); + assertParseError("1:16: Expected \"true\" or \"false\". Found \"2\".", "optional_bool: 2"); + assertParseError("1:18: Expected string.", "optional_string: 123"); + assertParseError("1:18: String missing ending quote.", "optional_string: \"ueoauaoe"); assertParseError( - "1:16: Expected \"true\" or \"false\".", - "optional_bool: 2"); + "1:18: String missing ending quote.", "optional_string: \"ueoauaoe\noptional_int32: 123"); + assertParseError("1:18: Invalid escape sequence: '\\z'", "optional_string: \"\\z\""); assertParseError( - "1:18: Expected string.", - "optional_string: 123"); + "1:18: String missing ending quote.", "optional_string: \"ueoauaoe\noptional_int32: 123"); assertParseError( - "1:18: String missing ending quote.", - "optional_string: \"ueoauaoe"); + "1:2: Input contains unknown fields and/or extensions:\n" + + "1:2:\tprotobuf_unittest.TestAllTypes.[nosuchext]", + "[nosuchext]: 123"); assertParseError( - "1:18: String missing ending quote.", - "optional_string: \"ueoauaoe\n" + - "optional_int32: 123"); + "1:20: Extension \"protobuf_unittest.optional_int32_extension\" does " + + "not extend message type \"protobuf_unittest.TestAllTypes\".", + "[protobuf_unittest.optional_int32_extension]: 123"); assertParseError( - "1:18: Invalid escape sequence: '\\z'", - "optional_string: \"\\z\""); + "1:1: Input contains unknown fields and/or extensions:\n" + + "1:1:\tprotobuf_unittest.TestAllTypes.nosuchfield", + "nosuchfield: 123"); + assertParseError("1:21: Expected \">\".", "OptionalGroup < a: 1"); assertParseError( - "1:18: String missing ending quote.", - "optional_string: \"ueoauaoe\n" + - "optional_int32: 123"); + "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " + + "value named \"NO_SUCH_VALUE\".", + "optional_nested_enum: NO_SUCH_VALUE"); assertParseError( - "1:2: Input contains unknown fields and/or extensions:\n" + - "1:2:\tprotobuf_unittest.TestAllTypes.[nosuchext]", - "[nosuchext]: 123"); - assertParseError( - "1:20: Extension \"protobuf_unittest.optional_int32_extension\" does " + - "not extend message type \"protobuf_unittest.TestAllTypes\".", - "[protobuf_unittest.optional_int32_extension]: 123"); - assertParseError( - "1:1: Input contains unknown fields and/or extensions:\n" + - "1:1:\tprotobuf_unittest.TestAllTypes.nosuchfield", - "nosuchfield: 123"); - assertParseError( - "1:21: Expected \">\".", - "OptionalGroup < a: 1"); - assertParseError( - "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " + - "value named \"NO_SUCH_VALUE\".", - "optional_nested_enum: NO_SUCH_VALUE"); - assertParseError( - "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " + - "value with number 123.", - "optional_nested_enum: 123"); + "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " + + "value with number 123.", + "optional_nested_enum: 123"); // Delimiters must match. - assertParseError( - "1:22: Expected identifier. Found '}'", - "OptionalGroup < a: 1 }"); - assertParseError( - "1:22: Expected identifier. Found '>'", - "OptionalGroup { a: 1 >"); + assertParseError("1:22: Expected identifier. Found '}'", "OptionalGroup < a: 1 }"); + assertParseError("1:22: Expected identifier. Found '>'", "OptionalGroup { a: 1 >"); } // ================================================================= public void testEscape() throws Exception { // Escape sequences. - assertEquals("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\177", - TextFormat.escapeBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\177"))); - assertEquals("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\177", - TextFormat.escapeText("\0\001\007\b\f\n\r\t\013\\\'\"\177")); - assertEquals(bytes("\0\001\007\b\f\n\r\t\013\\\'\""), - TextFormat.unescapeBytes("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"")); - assertEquals("\0\001\007\b\f\n\r\t\013\\\'\"", - TextFormat.unescapeText("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"")); - assertEquals(kEscapeTestStringEscaped, - TextFormat.escapeText(kEscapeTestString)); - assertEquals(kEscapeTestString, - TextFormat.unescapeText(kEscapeTestStringEscaped)); + assertEquals( + "\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\177", + TextFormat.escapeBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\177"))); + assertEquals( + "\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\177", + TextFormat.escapeText("\0\001\007\b\f\n\r\t\013\\\'\"\177")); + assertEquals( + bytes("\0\001\007\b\f\n\r\t\013\\\'\""), + TextFormat.unescapeBytes("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"")); + assertEquals( + "\0\001\007\b\f\n\r\t\013\\\'\"", + TextFormat.unescapeText("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"")); + assertEquals(ESCAPE_TEST_STRING_ESCAPED, TextFormat.escapeText(ESCAPE_TEST_STRING)); + assertEquals(ESCAPE_TEST_STRING, TextFormat.unescapeText(ESCAPE_TEST_STRING_ESCAPED)); // Invariant - assertEquals("hello", - TextFormat.escapeBytes(bytes("hello"))); - assertEquals("hello", - TextFormat.escapeText("hello")); - assertEquals(bytes("hello"), - TextFormat.unescapeBytes("hello")); - assertEquals("hello", - TextFormat.unescapeText("hello")); + assertEquals("hello", TextFormat.escapeBytes(bytes("hello"))); + assertEquals("hello", TextFormat.escapeText("hello")); + assertEquals(bytes("hello"), TextFormat.unescapeBytes("hello")); + assertEquals("hello", TextFormat.unescapeText("hello")); // Unicode handling. assertEquals("\\341\\210\\264", TextFormat.escapeText("\u1234")); - assertEquals("\\341\\210\\264", - TextFormat.escapeBytes(bytes(0xe1, 0x88, 0xb4))); + assertEquals("\\341\\210\\264", TextFormat.escapeBytes(bytes(0xe1, 0x88, 0xb4))); assertEquals("\u1234", TextFormat.unescapeText("\\341\\210\\264")); - assertEquals(bytes(0xe1, 0x88, 0xb4), - TextFormat.unescapeBytes("\\341\\210\\264")); + assertEquals(bytes(0xe1, 0x88, 0xb4), TextFormat.unescapeBytes("\\341\\210\\264")); assertEquals("\u1234", TextFormat.unescapeText("\\xe1\\x88\\xb4")); - assertEquals(bytes(0xe1, 0x88, 0xb4), - TextFormat.unescapeBytes("\\xe1\\x88\\xb4")); + assertEquals(bytes(0xe1, 0x88, 0xb4), TextFormat.unescapeBytes("\\xe1\\x88\\xb4")); + assertEquals("\u1234", TextFormat.unescapeText("\\u1234")); + assertEquals(bytes(0xe1, 0x88, 0xb4), TextFormat.unescapeBytes("\\u1234")); + assertEquals(bytes(0xe1, 0x88, 0xb4), TextFormat.unescapeBytes("\\U00001234")); + assertEquals( + new String(new int[] {0x10437}, 0, 1), TextFormat.unescapeText("\\xf0\\x90\\x90\\xb7")); + assertEquals(bytes(0xf0, 0x90, 0x90, 0xb7), TextFormat.unescapeBytes("\\U00010437")); // Handling of strings with unescaped Unicode characters > 255. final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c"; @@ -617,56 +900,132 @@ public void testEscape() throws Exception { } catch (TextFormat.InvalidEscapeSequenceException e) { // success } + + try { + TextFormat.unescapeText("\\u"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\u' with too few hex chars"); + } + + try { + TextFormat.unescapeText("\\ud800"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate"); + } + + try { + TextFormat.unescapeText("\\ud800\\u1234"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate"); + } + + try { + TextFormat.unescapeText("\\udc00"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate"); + } + + try { + TextFormat.unescapeText("\\ud801\\udc37"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate"); + } + + try { + TextFormat.unescapeText("\\U1234"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\U' with too few hex chars"); + } + + try { + TextFormat.unescapeText("\\U1234no more hex"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\U' with too few hex chars"); + } + + try { + TextFormat.unescapeText("\\U00110000"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\U00110000' is not a valid code point value"); + } + + try { + TextFormat.unescapeText("\\U0000d801\\U00000dc37"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\U0000d801' refers to a surrogate code unit"); + } } public void testParseInteger() throws Exception { - assertEquals( 0, TextFormat.parseInt32( "0")); - assertEquals( 1, TextFormat.parseInt32( "1")); - assertEquals( -1, TextFormat.parseInt32( "-1")); - assertEquals( 12345, TextFormat.parseInt32( "12345")); - assertEquals( -12345, TextFormat.parseInt32( "-12345")); - assertEquals( 2147483647, TextFormat.parseInt32( "2147483647")); + assertEquals(0, TextFormat.parseInt32("0")); + assertEquals(1, TextFormat.parseInt32("1")); + assertEquals(-1, TextFormat.parseInt32("-1")); + assertEquals(12345, TextFormat.parseInt32("12345")); + assertEquals(-12345, TextFormat.parseInt32("-12345")); + assertEquals(2147483647, TextFormat.parseInt32("2147483647")); assertEquals(-2147483648, TextFormat.parseInt32("-2147483648")); - assertEquals( 0, TextFormat.parseUInt32( "0")); - assertEquals( 1, TextFormat.parseUInt32( "1")); - assertEquals( 12345, TextFormat.parseUInt32( "12345")); - assertEquals( 2147483647, TextFormat.parseUInt32("2147483647")); + assertEquals(0, TextFormat.parseUInt32("0")); + assertEquals(1, TextFormat.parseUInt32("1")); + assertEquals(12345, TextFormat.parseUInt32("12345")); + assertEquals(2147483647, TextFormat.parseUInt32("2147483647")); assertEquals((int) 2147483648L, TextFormat.parseUInt32("2147483648")); assertEquals((int) 4294967295L, TextFormat.parseUInt32("4294967295")); - assertEquals( 0L, TextFormat.parseInt64( "0")); - assertEquals( 1L, TextFormat.parseInt64( "1")); - assertEquals( -1L, TextFormat.parseInt64( "-1")); - assertEquals( 12345L, TextFormat.parseInt64( "12345")); - assertEquals( -12345L, TextFormat.parseInt64( "-12345")); - assertEquals( 2147483647L, TextFormat.parseInt64( "2147483647")); + assertEquals(0L, TextFormat.parseInt64("0")); + assertEquals(1L, TextFormat.parseInt64("1")); + assertEquals(-1L, TextFormat.parseInt64("-1")); + assertEquals(12345L, TextFormat.parseInt64("12345")); + assertEquals(-12345L, TextFormat.parseInt64("-12345")); + assertEquals(2147483647L, TextFormat.parseInt64("2147483647")); assertEquals(-2147483648L, TextFormat.parseInt64("-2147483648")); - assertEquals( 4294967295L, TextFormat.parseInt64( "4294967295")); - assertEquals( 4294967296L, TextFormat.parseInt64( "4294967296")); - assertEquals(9223372036854775807L, - TextFormat.parseInt64("9223372036854775807")); - assertEquals(-9223372036854775808L, - TextFormat.parseInt64("-9223372036854775808")); - - assertEquals( 0L, TextFormat.parseUInt64( "0")); - assertEquals( 1L, TextFormat.parseUInt64( "1")); - assertEquals( 12345L, TextFormat.parseUInt64( "12345")); - assertEquals( 2147483647L, TextFormat.parseUInt64( "2147483647")); - assertEquals( 4294967295L, TextFormat.parseUInt64( "4294967295")); - assertEquals( 4294967296L, TextFormat.parseUInt64( "4294967296")); - assertEquals(9223372036854775807L, - TextFormat.parseUInt64("9223372036854775807")); - assertEquals(-9223372036854775808L, - TextFormat.parseUInt64("9223372036854775808")); + assertEquals(4294967295L, TextFormat.parseInt64("4294967295")); + assertEquals(4294967296L, TextFormat.parseInt64("4294967296")); + assertEquals(9223372036854775807L, TextFormat.parseInt64("9223372036854775807")); + assertEquals(-9223372036854775808L, TextFormat.parseInt64("-9223372036854775808")); + + assertEquals(0L, TextFormat.parseUInt64("0")); + assertEquals(1L, TextFormat.parseUInt64("1")); + assertEquals(12345L, TextFormat.parseUInt64("12345")); + assertEquals(2147483647L, TextFormat.parseUInt64("2147483647")); + assertEquals(4294967295L, TextFormat.parseUInt64("4294967295")); + assertEquals(4294967296L, TextFormat.parseUInt64("4294967296")); + assertEquals(9223372036854775807L, TextFormat.parseUInt64("9223372036854775807")); + assertEquals(-9223372036854775808L, TextFormat.parseUInt64("9223372036854775808")); assertEquals(-1L, TextFormat.parseUInt64("18446744073709551615")); // Hex assertEquals(0x1234abcd, TextFormat.parseInt32("0x1234abcd")); assertEquals(-0x1234abcd, TextFormat.parseInt32("-0x1234abcd")); assertEquals(-1, TextFormat.parseUInt64("0xffffffffffffffff")); - assertEquals(0x7fffffffffffffffL, - TextFormat.parseInt64("0x7fffffffffffffff")); + assertEquals(0x7fffffffffffffffL, TextFormat.parseInt64("0x7fffffffffffffff")); // Octal assertEquals(01234567, TextFormat.parseInt32("01234567")); @@ -746,26 +1105,26 @@ public void testParseString() throws Exception { public void testParseLongString() throws Exception { String longText = - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890" + - "123456789012345678901234567890123456789012345678901234567890"; + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890"; TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TextFormat.merge("optional_string: \"" + longText + "\"", builder); @@ -774,16 +1133,16 @@ public void testParseLongString() throws Exception { public void testParseBoolean() throws Exception { String goodText = - "repeated_bool: t repeated_bool : 0\n" + - "repeated_bool :f repeated_bool:1\n" + - "repeated_bool: False repeated_bool: True"; + "repeated_bool: t repeated_bool : 0\n" + + "repeated_bool :f repeated_bool:1\n" + + "repeated_bool: False repeated_bool: True"; String goodTextCanonical = - "repeated_bool: true\n" + - "repeated_bool: false\n" + - "repeated_bool: false\n" + - "repeated_bool: true\n" + - "repeated_bool: false\n" + - "repeated_bool: true\n"; + "repeated_bool: true\n" + + "repeated_bool: false\n" + + "repeated_bool: false\n" + + "repeated_bool: true\n" + + "repeated_bool: false\n" + + "repeated_bool: true\n"; TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TextFormat.merge(goodText, builder); assertEquals(goodTextCanonical, builder.build().toString()); @@ -812,178 +1171,231 @@ public void testParseAdjacentStringLiterals() throws Exception { public void testPrintFieldValue() throws Exception { assertPrintFieldValue("\"Hello\"", "Hello", "repeated_string"); - assertPrintFieldValue("123.0", 123f, "repeated_float"); - assertPrintFieldValue("123.0", 123d, "repeated_double"); - assertPrintFieldValue("123", 123, "repeated_int32"); - assertPrintFieldValue("123", 123L, "repeated_int64"); - assertPrintFieldValue("true", true, "repeated_bool"); + assertPrintFieldValue("123.0", 123f, "repeated_float"); + assertPrintFieldValue("123.0", 123d, "repeated_double"); + assertPrintFieldValue("123", 123, "repeated_int32"); + assertPrintFieldValue("123", 123L, "repeated_int64"); + assertPrintFieldValue("true", true, "repeated_bool"); assertPrintFieldValue("4294967295", 0xFFFFFFFF, "repeated_uint32"); - assertPrintFieldValue("18446744073709551615", 0xFFFFFFFFFFFFFFFFL, - "repeated_uint64"); - assertPrintFieldValue("\"\\001\\002\\003\"", - ByteString.copyFrom(new byte[] {1, 2, 3}), "repeated_bytes"); + assertPrintFieldValue("18446744073709551615", 0xFFFFFFFFFFFFFFFFL, "repeated_uint64"); + assertPrintFieldValue( + "\"\\001\\002\\003\"", ByteString.copyFrom(new byte[] {1, 2, 3}), "repeated_bytes"); } - private void assertPrintFieldValue(String expect, Object value, - String fieldName) throws Exception { + private void assertPrintFieldValue(String expect, Object value, String fieldName) + throws Exception { StringBuilder sb = new StringBuilder(); - TextFormat.printFieldValue( - TestAllTypes.getDescriptor().findFieldByName(fieldName), - value, sb); + TextFormat.printer() + .printFieldValue(TestAllTypes.getDescriptor().findFieldByName(fieldName), value, sb); assertEquals(expect, sb.toString()); } public void testShortDebugString() { - assertEquals("optional_nested_message { bb: 42 } repeated_int32: 1" - + " repeated_uint32: 2", - TextFormat.shortDebugString(TestAllTypes.newBuilder() - .addRepeatedInt32(1) - .addRepeatedUint32(2) - .setOptionalNestedMessage( - NestedMessage.newBuilder().setBb(42).build()) - .build())); + assertEquals( + "optional_nested_message { bb: 42 } repeated_int32: 1 repeated_uint32: 2", + TextFormat.shortDebugString( + TestAllTypes.newBuilder() + .addRepeatedInt32(1) + .addRepeatedUint32(2) + .setOptionalNestedMessage(NestedMessage.newBuilder().setBb(42).build()) + .build())); } public void testShortDebugString_field() { - final FieldDescriptor dataField = - OneString.getDescriptor().findFieldByName("data"); + final FieldDescriptor dataField = OneString.getDescriptor().findFieldByName("data"); assertEquals( - "data: \"test data\"", - TextFormat.shortDebugString(dataField, "test data")); + "data: \"test data\"", + TextFormat.printer().shortDebugString(dataField, "test data")); final FieldDescriptor optionalField = - TestAllTypes.getDescriptor().findFieldByName("optional_nested_message"); + TestAllTypes.getDescriptor().findFieldByName("optional_nested_message"); final Object value = NestedMessage.newBuilder().setBb(42).build(); assertEquals( - "optional_nested_message { bb: 42 }", - TextFormat.shortDebugString(optionalField, value)); + "optional_nested_message { bb: 42 }", + TextFormat.printer().shortDebugString(optionalField, value)); } public void testShortDebugString_unknown() { - assertEquals("5: 1 5: 0x00000002 5: 0x0000000000000003 5: \"4\" 5 { 10: 5 }" - + " 8: 1 8: 2 8: 3 15: 12379813812177893520 15: 0xabcd1234 15:" - + " 0xabcdef1234567890", - TextFormat.shortDebugString(makeUnknownFieldSet())); + assertEquals( + "5: 1 5: 0x00000002 5: 0x0000000000000003 5: \"4\" 5: { 12: 6 } 5 { 10: 5 }" + + " 8: 1 8: 2 8: 3 15: 12379813812177893520 15: 0xabcd1234 15:" + + " 0xabcdef1234567890", + TextFormat.printer().shortDebugString(makeUnknownFieldSet())); } public void testPrintToUnicodeString() throws Exception { assertEquals( - "optional_string: \"abc\u3042efg\"\n" + - "optional_bytes: \"\\343\\201\\202\"\n" + - "repeated_string: \"\u3093XYZ\"\n", - TextFormat.printToUnicodeString(TestAllTypes.newBuilder() - .setOptionalString("abc\u3042efg") - .setOptionalBytes(bytes(0xe3, 0x81, 0x82)) - .addRepeatedString("\u3093XYZ") - .build())); + "optional_string: \"abc\u3042efg\"\n" + + "optional_bytes: \"\\343\\201\\202\"\n" + + "repeated_string: \"\u3093XYZ\"\n", + TextFormat.printer() + .escapingNonAscii(false) + .printToString( + TestAllTypes.newBuilder() + .setOptionalString("abc\u3042efg") + .setOptionalBytes(bytes(0xe3, 0x81, 0x82)) + .addRepeatedString("\u3093XYZ") + .build())); // Double quotes and backslashes should be escaped assertEquals( "optional_string: \"a\\\\bc\\\"ef\\\"g\"\n", - TextFormat.printToUnicodeString(TestAllTypes.newBuilder() - .setOptionalString("a\\bc\"ef\"g") - .build())); + TextFormat.printer() + .escapingNonAscii(false) + .printToString(TestAllTypes.newBuilder().setOptionalString("a\\bc\"ef\"g").build())); // Test escaping roundtrip - TestAllTypes message = TestAllTypes.newBuilder() - .setOptionalString("a\\bc\\\"ef\"g") - .build(); + TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("a\\bc\\\"ef\"g").build(); TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - TextFormat.merge(TextFormat.printToUnicodeString(message), builder); + TextFormat.merge(TextFormat.printer().escapingNonAscii(false).printToString(message), builder); assertEquals(message.getOptionalString(), builder.getOptionalString()); } public void testPrintToUnicodeStringWithNewlines() throws Exception { // No newlines at start and end - assertEquals("optional_string: \"test newlines\\n\\nin\\nstring\"\n", - TextFormat.printToUnicodeString(TestAllTypes.newBuilder() - .setOptionalString("test newlines\n\nin\nstring") - .build())); + assertEquals( + "optional_string: \"test newlines\\n\\nin\\nstring\"\n", + TextFormat.printer() + .escapingNonAscii(false) + .printToString( + TestAllTypes.newBuilder() + .setOptionalString("test newlines\n\nin\nstring") + .build())); // Newlines at start and end - assertEquals("optional_string: \"\\ntest\\nnewlines\\n\\nin\\nstring\\n\"\n", - TextFormat.printToUnicodeString(TestAllTypes.newBuilder() - .setOptionalString("\ntest\nnewlines\n\nin\nstring\n") - .build())); + assertEquals( + "optional_string: \"\\ntest\\nnewlines\\n\\nin\\nstring\\n\"\n", + TextFormat.printer() + .escapingNonAscii(false) + .printToString( + TestAllTypes.newBuilder() + .setOptionalString("\ntest\nnewlines\n\nin\nstring\n") + .build())); // Strings with 0, 1 and 2 newlines. - assertEquals("optional_string: \"\"\n", - TextFormat.printToUnicodeString(TestAllTypes.newBuilder() - .setOptionalString("") - .build())); - assertEquals("optional_string: \"\\n\"\n", - TextFormat.printToUnicodeString(TestAllTypes.newBuilder() - .setOptionalString("\n") - .build())); - assertEquals("optional_string: \"\\n\\n\"\n", - TextFormat.printToUnicodeString(TestAllTypes.newBuilder() - .setOptionalString("\n\n") - .build())); + assertEquals( + "optional_string: \"\"\n", + TextFormat.printer() + .escapingNonAscii(false) + .printToString(TestAllTypes.newBuilder().setOptionalString("").build())); + assertEquals( + "optional_string: \"\\n\"\n", + TextFormat.printer() + .escapingNonAscii(false) + .printToString(TestAllTypes.newBuilder().setOptionalString("\n").build())); + assertEquals( + "optional_string: \"\\n\\n\"\n", + TextFormat.printer() + .escapingNonAscii(false) + .printToString(TestAllTypes.newBuilder().setOptionalString("\n\n").build())); // Test escaping roundtrip - TestAllTypes message = TestAllTypes.newBuilder() - .setOptionalString("\ntest\nnewlines\n\nin\nstring\n") - .build(); + TestAllTypes message = + TestAllTypes.newBuilder().setOptionalString("\ntest\nnewlines\n\nin\nstring\n").build(); TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - TextFormat.merge(TextFormat.printToUnicodeString(message), builder); + TextFormat.merge(TextFormat.printer().escapingNonAscii(false).printToString(message), builder); assertEquals(message.getOptionalString(), builder.getOptionalString()); } public void testPrintToUnicodeString_unknown() { assertEquals( "1: \"\\343\\201\\202\"\n", - TextFormat.printToUnicodeString(UnknownFieldSet.newBuilder() - .addField(1, - UnknownFieldSet.Field.newBuilder() - .addLengthDelimited(bytes(0xe3, 0x81, 0x82)).build()) - .build())); + TextFormat.printer() + .escapingNonAscii(false) + .printToString( + UnknownFieldSet.newBuilder() + .addField( + 1, + UnknownFieldSet.Field.newBuilder() + .addLengthDelimited(bytes(0xe3, 0x81, 0x82)) + .build()) + .build())); } + public void testParseUnknownExtensions() throws Exception { + TestUtil.TestLogHandler logHandler = new TestUtil.TestLogHandler(); + Logger logger = Logger.getLogger(TextFormat.class.getName()); + logger.addHandler(logHandler); + // Test unknown extension can pass. + assertParseSuccessWithUnknownExtensions("[unknown_extension]: 123"); + assertParseSuccessWithUnknownExtensions( + "[unknown_extension]: 123\n" + "[unknown_ext]: inf\n" + "[unknown]: 1.234"); + // Test warning messages. + assertEquals( + "Input contains unknown fields and/or extensions:\n" + + "1:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension]", + logHandler.getStoredLogRecords().get(0).getMessage()); + assertEquals( + "Input contains unknown fields and/or extensions:\n" + + "1:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension]\n" + + "2:2:\tprotobuf_unittest.TestAllTypes.[unknown_ext]\n" + + "3:2:\tprotobuf_unittest.TestAllTypes.[unknown]", + logHandler.getStoredLogRecords().get(1).getMessage()); + + // Test unknown field can not pass. + assertParseErrorWithUnknownExtensions( + "2:1: Input contains unknown fields and/or extensions:\n" + + "1:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension]\n" + + "2:1:\tprotobuf_unittest.TestAllTypes.unknown_field", + "[unknown_extension]: 1\n" + "unknown_field: 12345"); + assertParseErrorWithUnknownExtensions( + "3:1: Input contains unknown fields and/or extensions:\n" + + "1:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension1]\n" + + "2:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension2]\n" + + "3:1:\tprotobuf_unittest.TestAllTypes.unknown_field\n" + + "4:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension3]", + "[unknown_extension1]: 1\n" + + "[unknown_extension2]: 2\n" + + "unknown_field: 12345\n" + + "[unknown_extension3]: 3\n"); + assertParseErrorWithUnknownExtensions( + "1:1: Input contains unknown fields and/or extensions:\n" + + "1:1:\tprotobuf_unittest.TestAllTypes.unknown_field1\n" + + "2:1:\tprotobuf_unittest.TestAllTypes.unknown_field2\n" + + "3:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension]\n" + + "4:1:\tprotobuf_unittest.TestAllTypes.unknown_field3", + "unknown_field1: 1\n" + + "unknown_field2: 2\n" + + "[unknown_extension]: 12345\n" + + "unknown_field3: 3\n"); + } + // See additional coverage in testOneofOverwriteForbidden and testMapOverwriteForbidden. public void testParseNonRepeatedFields() throws Exception { + assertParseSuccessWithOverwriteForbidden("repeated_int32: 1\nrepeated_int32: 2\n"); + assertParseSuccessWithOverwriteForbidden("RepeatedGroup { a: 1 }\nRepeatedGroup { a: 2 }\n"); assertParseSuccessWithOverwriteForbidden( - "repeated_int32: 1\n" + - "repeated_int32: 2\n"); - assertParseSuccessWithOverwriteForbidden( - "RepeatedGroup { a: 1 }\n" + - "RepeatedGroup { a: 2 }\n"); - assertParseSuccessWithOverwriteForbidden( - "repeated_nested_message { bb: 1 }\n" + - "repeated_nested_message { bb: 2 }\n"); + "repeated_nested_message { bb: 1 }\nrepeated_nested_message { bb: 2 }\n"); assertParseErrorWithOverwriteForbidden( - "3:17: Non-repeated field " + - "\"protobuf_unittest.TestAllTypes.optional_int32\" " + - "cannot be overwritten.", - "optional_int32: 1\n" + - "optional_bool: true\n" + - "optional_int32: 1\n"); + "3:15: Non-repeated field " + + "\"protobuf_unittest.TestAllTypes.optional_int32\" " + + "cannot be overwritten.", + "optional_int32: 1\noptional_bool: true\noptional_int32: 1\n"); assertParseErrorWithOverwriteForbidden( - "2:17: Non-repeated field " + - "\"protobuf_unittest.TestAllTypes.optionalgroup\" " + - "cannot be overwritten.", - "OptionalGroup { a: 1 }\n" + - "OptionalGroup { }\n"); + "2:1: Non-repeated field " + + "\"protobuf_unittest.TestAllTypes.optionalgroup\" " + + "cannot be overwritten.", + "OptionalGroup { a: 1 }\nOptionalGroup { }\n"); assertParseErrorWithOverwriteForbidden( - "2:33: Non-repeated field " + - "\"protobuf_unittest.TestAllTypes.optional_nested_message\" " + - "cannot be overwritten.", - "optional_nested_message { }\n" + - "optional_nested_message { bb: 3 }\n"); + "2:1: Non-repeated field " + + "\"protobuf_unittest.TestAllTypes.optional_nested_message\" " + + "cannot be overwritten.", + "optional_nested_message { }\noptional_nested_message { bb: 3 }\n"); assertParseErrorWithOverwriteForbidden( - "2:16: Non-repeated field " + - "\"protobuf_unittest.TestAllTypes.default_int32\" " + - "cannot be overwritten.", - "default_int32: 41\n" + // the default value - "default_int32: 41\n"); + "2:14: Non-repeated field " + + "\"protobuf_unittest.TestAllTypes.default_int32\" " + + "cannot be overwritten.", + "default_int32: 41\n" + + // the default value + "default_int32: 41\n"); assertParseErrorWithOverwriteForbidden( - "2:17: Non-repeated field " + - "\"protobuf_unittest.TestAllTypes.default_string\" " + - "cannot be overwritten.", - "default_string: \"zxcv\"\n" + - "default_string: \"asdf\"\n"); + "2:15: Non-repeated field " + + "\"protobuf_unittest.TestAllTypes.default_string\" " + + "cannot be overwritten.", + "default_string: \"zxcv\"\ndefault_string: \"asdf\"\n"); } public void testParseShortRepeatedFormOfRepeatedFields() throws Exception { @@ -1004,27 +1416,20 @@ public void testParseShortRepeatedFormOfEmptyRepeatedFields() throws Exception { public void testParseShortRepeatedFormWithTrailingComma() throws Exception { assertParseErrorWithOverwriteForbidden( - "1:38: Expected identifier. Found \']\'", - "repeated_foreign_enum: [FOREIGN_FOO, ]\n"); - assertParseErrorWithOverwriteForbidden( - "1:22: Couldn't parse integer: For input string: \"]\"", - "repeated_int32: [ 1, ]\n"); + "1:38: Expected identifier. Found \']\'", "repeated_foreign_enum: [FOREIGN_FOO, ]\n"); assertParseErrorWithOverwriteForbidden( - "1:25: Expected \"{\".", - "RepeatedGroup [{ a: 1 },]\n"); + "1:22: Couldn't parse integer: For input string: \"]\"", "repeated_int32: [ 1, ]\n"); + assertParseErrorWithOverwriteForbidden("1:25: Expected \"{\".", "RepeatedGroup [{ a: 1 },]\n"); assertParseErrorWithOverwriteForbidden( - "1:37: Expected \"{\".", - "repeated_nested_message [{ bb: 1 }, ]\n"); + "1:37: Expected \"{\".", "repeated_nested_message [{ bb: 1 }, ]\n"); // See also testMapShortFormTrailingComma. } public void testParseShortRepeatedFormOfNonRepeatedFields() throws Exception { assertParseErrorWithOverwriteForbidden( - "1:17: Couldn't parse integer: For input string: \"[\"", - "optional_int32: [1]\n"); + "1:17: Couldn't parse integer: For input string: \"[\"", "optional_int32: [1]\n"); assertParseErrorWithOverwriteForbidden( - "1:17: Couldn't parse integer: For input string: \"[\"", - "optional_int32: []\n"); + "1:17: Couldn't parse integer: For input string: \"[\"", "optional_int32: []\n"); } // ======================================================================= @@ -1035,7 +1440,7 @@ public void testOneofTextFormat() throws Exception { TestUtil.setOneof(builder); TestOneof2 message = builder.build(); TestOneof2.Builder dest = TestOneof2.newBuilder(); - TextFormat.merge(TextFormat.printToUnicodeString(message), dest); + TextFormat.merge(TextFormat.printer().escapingNonAscii(false).printToString(message), dest); TestUtil.assertOneofSet(dest.build()); } @@ -1043,20 +1448,21 @@ public void testOneofOverwriteForbidden() throws Exception { String input = "foo_string: \"stringvalue\" foo_int: 123"; TestOneof2.Builder builder = TestOneof2.newBuilder(); try { - parserWithOverwriteForbidden.merge( - input, TestUtil.getExtensionRegistry(), builder); + parserWithOverwriteForbidden.merge(input, TestUtil.getFullExtensionRegistry(), builder); fail("Expected parse exception."); } catch (TextFormat.ParseException e) { - assertEquals("1:36: Field \"protobuf_unittest.TestOneof2.foo_int\"" - + " is specified along with field \"protobuf_unittest.TestOneof2.foo_string\"," - + " another member of oneof \"foo\".", e.getMessage()); + assertEquals( + "1:34: Field \"protobuf_unittest.TestOneof2.foo_int\"" + + " is specified along with field \"protobuf_unittest.TestOneof2.foo_string\"," + + " another member of oneof \"foo\".", + e.getMessage()); } } public void testOneofOverwriteAllowed() throws Exception { String input = "foo_string: \"stringvalue\" foo_int: 123"; TestOneof2.Builder builder = TestOneof2.newBuilder(); - defaultParser.merge(input, TestUtil.getExtensionRegistry(), builder); + defaultParser.merge(input, TestUtil.getFullExtensionRegistry(), builder); // Only the last value sticks. TestOneof2 oneof = builder.build(); assertFalse(oneof.hasFooString()); @@ -1073,7 +1479,7 @@ public void testMapTextFormat() throws Exception { .putInt32ToStringField(20, "banana") .putInt32ToStringField(30, "cherry") .build(); - String text = TextFormat.printToUnicodeString(message); + String text = TextFormat.printer().escapingNonAscii(false).printToString(message); { TestMap.Builder dest = TestMap.newBuilder(); TextFormat.merge(text, dest); @@ -1086,28 +1492,48 @@ public void testMapTextFormat() throws Exception { } } + public void testMapDuplicateKeys() throws Exception { + String input = + "int32_to_int32_field: {\n" + + " key: 1\n" + + " value: 1\n" + + "}\n" + + "int32_to_int32_field: {\n" + + " key: -2147483647\n" + + " value: 5\n" + + "}\n" + + "int32_to_int32_field: {\n" + + " key: 1\n" + + " value: -1\n" + + "}\n"; + TestMap msg = TextFormat.parse(input, TestMap.class); + int i1 = msg.getInt32ToInt32FieldMap().get(1); + TestMap msg2 = TextFormat.parse(msg.toString(), TestMap.class); + int i2 = msg2.getInt32ToInt32FieldMap().get(1); + assertEquals(i1, i2); + } + public void testMapShortForm() throws Exception { String text = "string_to_int32_field [{ key: 'x' value: 10 }, { key: 'y' value: 20 }]\n" - + "int32_to_message_field " - + "[{ key: 1 value { value: 100 } }, { key: 2 value: { value: 200 } }]\n"; + + "int32_to_message_field " + + "[{ key: 1 value { value: 100 } }, { key: 2 value: { value: 200 } }]\n"; TestMap.Builder dest = TestMap.newBuilder(); parserWithOverwriteForbidden.merge(text, dest); TestMap message = dest.build(); - assertEquals(2, message.getStringToInt32Field().size()); - assertEquals(2, message.getInt32ToMessageField().size()); - assertEquals(10, message.getStringToInt32Field().get("x").intValue()); - assertEquals(200, message.getInt32ToMessageField().get(2).getValue()); + assertEquals(2, message.getStringToInt32FieldMap().size()); + assertEquals(2, message.getInt32ToMessageFieldMap().size()); + assertEquals(10, message.getStringToInt32FieldMap().get("x").intValue()); + assertEquals(200, message.getInt32ToMessageFieldMap().get(2).getValue()); } public void testMapShortFormEmpty() throws Exception { - String text = "string_to_int32_field []\n" - + "int32_to_message_field: []\n"; + String text = "string_to_int32_field []\nint32_to_message_field: []\n"; TestMap.Builder dest = TestMap.newBuilder(); parserWithOverwriteForbidden.merge(text, dest); TestMap message = dest.build(); - assertEquals(0, message.getStringToInt32Field().size()); - assertEquals(0, message.getInt32ToMessageField().size()); + assertEquals(0, message.getStringToInt32FieldMap().size()); + assertEquals(0, message.getInt32ToMessageFieldMap().size()); } public void testMapShortFormTrailingComma() throws Exception { @@ -1132,18 +1558,30 @@ public void testMapOverwrite() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); defaultParser.merge(text, builder); TestMap map = builder.build(); - assertEquals(2, map.getInt32ToInt32Field().size()); - assertEquals(30, map.getInt32ToInt32Field().get(1).intValue()); + assertEquals(2, map.getInt32ToInt32FieldMap().size()); + assertEquals(30, map.getInt32ToInt32FieldMap().get(1).intValue()); } { // With overwrite forbidden, same behavior. // TODO(b/29122459): Expect parse exception here. TestMap.Builder builder = TestMap.newBuilder(); - defaultParser.merge(text, builder); + parserWithOverwriteForbidden.merge(text, builder); TestMap map = builder.build(); - assertEquals(2, map.getInt32ToInt32Field().size()); - assertEquals(30, map.getInt32ToInt32Field().get(1).intValue()); + assertEquals(2, map.getInt32ToInt32FieldMap().size()); + assertEquals(30, map.getInt32ToInt32FieldMap().get(1).intValue()); + } + + { + // With overwrite forbidden and a dynamic message, same behavior. + // TODO(b/29122459): Expect parse exception here. + Message.Builder builder = DynamicMessage.newBuilder(TestMap.getDescriptor()); + parserWithOverwriteForbidden.merge(text, builder); + TestMap map = + TestMap.parseFrom( + builder.build().toByteString(), ExtensionRegistryLite.getEmptyRegistry()); + assertEquals(2, map.getInt32ToInt32FieldMap().size()); + assertEquals(30, map.getInt32ToInt32FieldMap().get(1).intValue()); } } @@ -1158,24 +1596,25 @@ public void testParseInfoTreeBuilding() throws Exception { // Set to allow unknown fields TextFormat.Parser parser = TextFormat.Parser.newBuilder() + .setAllowUnknownFields(true) .setParseInfoTreeBuilder(treeBuilder) .build(); final String stringData = "optional_int32: 1\n" - + "optional_int64: 2\n" - + " optional_double: 2.4\n" - + "repeated_int32: 5\n" - + "repeated_int32: 10\n" - + "optional_nested_message <\n" - + " bb: 78\n" - + ">\n" - + "repeated_nested_message <\n" - + " bb: 79\n" - + ">\n" - + "repeated_nested_message <\n" - + " bb: 80\n" - + ">"; + + "optional_int64: 2\n" + + " optional_double: 2.4\n" + + "repeated_int32: 5\n" + + "repeated_int32: 10\n" + + "optional_nested_message <\n" + + " bb: 78\n" + + ">\n" + + "repeated_nested_message <\n" + + " bb: 79\n" + + ">\n" + + "repeated_nested_message <\n" + + " bb: 80\n" + + ">"; parser.merge(stringData, builder); TextFormatParseInfoTree tree = treeBuilder.build(); @@ -1235,9 +1674,45 @@ private void assertLocation( fail( String.format( "Tree/descriptor/fieldname did not contain index %d, line %d column %d expected", - index, - line, - column)); + index, line, column)); } } + + public void testSortMapFields() throws Exception { + TestMap message = + TestMap.newBuilder() + .putStringToInt32Field("cherry", 30) + .putStringToInt32Field("banana", 20) + .putStringToInt32Field("apple", 10) + .putInt32ToStringField(30, "cherry") + .putInt32ToStringField(20, "banana") + .putInt32ToStringField(10, "apple") + .build(); + String text = + "int32_to_string_field {\n" + + " key: 10\n" + + " value: \"apple\"\n" + + "}\n" + + "int32_to_string_field {\n" + + " key: 20\n" + + " value: \"banana\"\n" + + "}\n" + + "int32_to_string_field {\n" + + " key: 30\n" + + " value: \"cherry\"\n" + + "}\n" + + "string_to_int32_field {\n" + + " key: \"apple\"\n" + + " value: 10\n" + + "}\n" + + "string_to_int32_field {\n" + + " key: \"banana\"\n" + + " value: 20\n" + + "}\n" + + "string_to_int32_field {\n" + + " key: \"cherry\"\n" + + " value: 30\n" + + "}\n"; + assertEquals(text, TextFormat.printer().printToString(message)); + } } diff --git a/java/core/src/test/java/com/google/protobuf/TypeRegistryTest.java b/java/core/src/test/java/com/google/protobuf/TypeRegistryTest.java new file mode 100644 index 0000000000000..0cd9677726df5 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/TypeRegistryTest.java @@ -0,0 +1,70 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +import com.google.protobuf.Descriptors.Descriptor; +import protobuf_unittest.UnittestProto; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public final class TypeRegistryTest { + + @Test + public void findDescriptorByFullName() throws Exception { + Descriptor descriptor = UnittestProto.TestAllTypes.getDescriptor(); + assertNull(TypeRegistry.getEmptyTypeRegistry().find(descriptor.getFullName())); + + assertSame( + descriptor, + TypeRegistry.newBuilder().add(descriptor).build().find(descriptor.getFullName())); + } + + @Test + public void findDescriptorByTypeUrl() throws Exception { + Descriptor descriptor = UnittestProto.TestAllTypes.getDescriptor(); + assertNull( + TypeRegistry.getEmptyTypeRegistry() + .getDescriptorForTypeUrl("type.googleapis.com/" + descriptor.getFullName())); + + assertSame( + descriptor, + TypeRegistry.newBuilder() + .add(descriptor) + .build() + .getDescriptorForTypeUrl("type.googleapis.com/" + descriptor.getFullName())); + } + +} diff --git a/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java b/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java index 88cbbf862c218..7daef026dc93e 100644 --- a/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java +++ b/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java @@ -35,14 +35,18 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.FieldPresenceTestProto.TestAllTypes; +import com.google.protobuf.Proto2UnknownEnumValuesTestProto.Proto2EnumMessage; +import com.google.protobuf.Proto2UnknownEnumValuesTestProto.Proto2EnumMessageWithEnumSubset; +import com.google.protobuf.Proto2UnknownEnumValuesTestProto.Proto2TestEnum; +import com.google.protobuf.Proto2UnknownEnumValuesTestProto.Proto2TestEnumSubset; import com.google.protobuf.TextFormat.ParseException; import junit.framework.TestCase; /** - * Unit tests for protos that keep unknown enum values rather than discard - * them as unknown fields. + * Unit tests for protos that keep unknown enum values rather than discard them as unknown fields. */ public class UnknownEnumValueTest extends TestCase { + public void testUnknownEnumValues() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); builder.setOptionalNestedEnumValue(4321); @@ -58,7 +62,7 @@ public void testUnknownEnumValues() throws Exception { assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnum(0)); assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnumList().get(0)); assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getPackedNestedEnum(0)); - + // Test serialization and parsing. ByteString data = message.toByteString(); message = TestAllTypes.parseFrom(data); @@ -71,19 +75,19 @@ public void testUnknownEnumValues() throws Exception { assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnum(0)); assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnumList().get(0)); assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getPackedNestedEnum(0)); - + // Test toBuilder(). builder = message.toBuilder(); assertEquals(4321, builder.getOptionalNestedEnumValue()); assertEquals(5432, builder.getRepeatedNestedEnumValue(0)); assertEquals(5432, builder.getRepeatedNestedEnumValueList().get(0).intValue()); - assertEquals(6543, builder.getPackedNestedEnumValue(0)); + assertEquals(6543, builder.getPackedNestedEnumValue(0)); // Returns UNRECOGNIZED if an enum type is requested. assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getOptionalNestedEnum()); assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnum(0)); assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnumList().get(0)); assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getPackedNestedEnum(0)); - + // Test mergeFrom(). builder = TestAllTypes.newBuilder().mergeFrom(message); assertEquals(4321, builder.getOptionalNestedEnumValue()); @@ -95,7 +99,7 @@ public void testUnknownEnumValues() throws Exception { assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnum(0)); assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnumList().get(0)); assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getPackedNestedEnum(0)); - + // Test equals() and hashCode() TestAllTypes sameMessage = builder.build(); assertEquals(message, sameMessage); @@ -123,7 +127,7 @@ public void testUnknownEnumValues() throws Exception { // Expected. } } - + public void testUnknownEnumValueInReflectionApi() throws Exception { Descriptor descriptor = TestAllTypes.getDescriptor(); FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum"); @@ -132,14 +136,13 @@ public void testUnknownEnumValueInReflectionApi() throws Exception { EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor(); TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - builder.setField(optionalNestedEnumField, - enumType.findValueByNumberCreatingIfUnknown(4321)); - builder.addRepeatedField(repeatedNestedEnumField, - enumType.findValueByNumberCreatingIfUnknown(5432)); - builder.addRepeatedField(packedNestedEnumField, - enumType.findValueByNumberCreatingIfUnknown(6543)); + builder.setField(optionalNestedEnumField, enumType.findValueByNumberCreatingIfUnknown(4321)); + builder.addRepeatedField( + repeatedNestedEnumField, enumType.findValueByNumberCreatingIfUnknown(5432)); + builder.addRepeatedField( + packedNestedEnumField, enumType.findValueByNumberCreatingIfUnknown(6543)); TestAllTypes message = builder.build(); - + // Getters will return unknown enum values as EnumValueDescriptor. EnumValueDescriptor unknown4321 = (EnumValueDescriptor) message.getField(optionalNestedEnumField); @@ -166,79 +169,78 @@ public void testUnknownEnumValueInReflectionApi() throws Exception { message = builder.build(); // Like other descriptors, unknown EnumValueDescriptor can be compared by // object identity. - assertTrue(unknown6543 == message.getField(optionalNestedEnumField)); - assertTrue(unknown4321 == message.getRepeatedField(repeatedNestedEnumField, 0)); - assertTrue(unknown5432 == message.getRepeatedField(packedNestedEnumField, 0)); + assertSame(message.getField(optionalNestedEnumField), unknown6543); + assertSame(message.getRepeatedField(repeatedNestedEnumField, 0), unknown4321); + assertSame(message.getRepeatedField(packedNestedEnumField, 0), unknown5432); } - + public void testUnknownEnumValueWithDynamicMessage() throws Exception { Descriptor descriptor = TestAllTypes.getDescriptor(); FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum"); FieldDescriptor repeatedNestedEnumField = descriptor.findFieldByName("repeated_nested_enum"); FieldDescriptor packedNestedEnumField = descriptor.findFieldByName("packed_nested_enum"); EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor(); - + Message dynamicMessageDefaultInstance = DynamicMessage.getDefaultInstance(descriptor); Message.Builder builder = dynamicMessageDefaultInstance.newBuilderForType(); - builder.setField(optionalNestedEnumField, - enumType.findValueByNumberCreatingIfUnknown(4321)); - builder.addRepeatedField(repeatedNestedEnumField, - enumType.findValueByNumberCreatingIfUnknown(5432)); - builder.addRepeatedField(packedNestedEnumField, - enumType.findValueByNumberCreatingIfUnknown(6543)); + builder.setField(optionalNestedEnumField, enumType.findValueByNumberCreatingIfUnknown(4321)); + builder.addRepeatedField( + repeatedNestedEnumField, enumType.findValueByNumberCreatingIfUnknown(5432)); + builder.addRepeatedField( + packedNestedEnumField, enumType.findValueByNumberCreatingIfUnknown(6543)); Message message = builder.build(); - assertEquals(4321, - ((EnumValueDescriptor) message.getField(optionalNestedEnumField)).getNumber()); - assertEquals(5432, + assertEquals( + 4321, ((EnumValueDescriptor) message.getField(optionalNestedEnumField)).getNumber()); + assertEquals( + 5432, ((EnumValueDescriptor) message.getRepeatedField(repeatedNestedEnumField, 0)).getNumber()); - assertEquals(6543, + assertEquals( + 6543, ((EnumValueDescriptor) message.getRepeatedField(packedNestedEnumField, 0)).getNumber()); - + // Test reflection based serialization/parsing implementation. ByteString data = message.toByteString(); - message = dynamicMessageDefaultInstance - .newBuilderForType() - .mergeFrom(data) - .build(); - assertEquals(4321, - ((EnumValueDescriptor) message.getField(optionalNestedEnumField)).getNumber()); - assertEquals(5432, + message = dynamicMessageDefaultInstance.newBuilderForType().mergeFrom(data).build(); + assertEquals( + 4321, ((EnumValueDescriptor) message.getField(optionalNestedEnumField)).getNumber()); + assertEquals( + 5432, ((EnumValueDescriptor) message.getRepeatedField(repeatedNestedEnumField, 0)).getNumber()); - assertEquals(6543, + assertEquals( + 6543, ((EnumValueDescriptor) message.getRepeatedField(packedNestedEnumField, 0)).getNumber()); - + // Test reflection based equals()/hashCode(). builder = dynamicMessageDefaultInstance.newBuilderForType(); - builder.setField(optionalNestedEnumField, - enumType.findValueByNumberCreatingIfUnknown(4321)); - builder.addRepeatedField(repeatedNestedEnumField, - enumType.findValueByNumberCreatingIfUnknown(5432)); - builder.addRepeatedField(packedNestedEnumField, - enumType.findValueByNumberCreatingIfUnknown(6543)); + builder.setField(optionalNestedEnumField, enumType.findValueByNumberCreatingIfUnknown(4321)); + builder.addRepeatedField( + repeatedNestedEnumField, enumType.findValueByNumberCreatingIfUnknown(5432)); + builder.addRepeatedField( + packedNestedEnumField, enumType.findValueByNumberCreatingIfUnknown(6543)); Message sameMessage = builder.build(); assertEquals(message, sameMessage); assertEquals(message.hashCode(), sameMessage.hashCode()); - builder.setField(optionalNestedEnumField, - enumType.findValueByNumberCreatingIfUnknown(0)); + builder.setField(optionalNestedEnumField, enumType.findValueByNumberCreatingIfUnknown(0)); Message differentMessage = builder.build(); assertFalse(message.equals(differentMessage)); } - + public void testUnknownEnumValuesInTextFormat() { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); builder.setOptionalNestedEnumValue(4321); builder.addRepeatedNestedEnumValue(5432); builder.addPackedNestedEnumValue(6543); TestAllTypes message = builder.build(); - + // We can print a message with unknown enum values. - String textData = TextFormat.printToString(message); + String textData = TextFormat.printer().printToString(message); assertEquals( "optional_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_4321\n" - + "repeated_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_5432\n" - + "packed_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_6543\n", textData); - + + "repeated_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_5432\n" + + "packed_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_6543\n", + textData); + // Parsing unknown enum values will fail just like parsing other kinds of // unknown fields. try { @@ -248,4 +250,61 @@ public void testUnknownEnumValuesInTextFormat() { // expected. } } + + public void testUnknownEnumValuesInProto2() throws Exception { + Proto2EnumMessage.Builder sourceMessage = Proto2EnumMessage.newBuilder(); + sourceMessage + .addRepeatedPackedEnum(Proto2TestEnum.ZERO) + .addRepeatedPackedEnum(Proto2TestEnum.TWO) // Unknown in parsed proto + .addRepeatedPackedEnum(Proto2TestEnum.ONE); + + Proto2EnumMessageWithEnumSubset destMessage = + Proto2EnumMessageWithEnumSubset.parseFrom(sourceMessage.build().toByteArray()); + + // Known enum values should be preserved. + assertEquals(2, destMessage.getRepeatedPackedEnumCount()); + assertEquals(Proto2TestEnumSubset.TESTENUM_SUBSET_ZERO, destMessage.getRepeatedPackedEnum(0)); + assertEquals(Proto2TestEnumSubset.TESTENUM_SUBSET_ONE, destMessage.getRepeatedPackedEnum(1)); + + // Unknown enum values should be found in UnknownFieldSet. + UnknownFieldSet unknown = destMessage.getUnknownFields(); + assertEquals( + Proto2TestEnum.TWO_VALUE, + unknown + .getField(Proto2EnumMessageWithEnumSubset.REPEATED_PACKED_ENUM_FIELD_NUMBER) + .getVarintList() + .get(0) + .longValue()); + } + + public void testUnknownEnumValuesInProto2WithDynamicMessage() throws Exception { + Descriptor descriptor = Proto2EnumMessageWithEnumSubset.getDescriptor(); + FieldDescriptor repeatedPackedField = descriptor.findFieldByName("repeated_packed_enum"); + + Proto2EnumMessage.Builder sourceMessage = Proto2EnumMessage.newBuilder(); + sourceMessage + .addRepeatedPackedEnum(Proto2TestEnum.ZERO) + .addRepeatedPackedEnum(Proto2TestEnum.TWO) // Unknown in parsed proto + .addRepeatedPackedEnum(Proto2TestEnum.ONE); + + DynamicMessage message = + DynamicMessage.parseFrom( + Proto2EnumMessageWithEnumSubset.getDescriptor(), sourceMessage.build().toByteArray()); + + // Known enum values should be preserved. + assertEquals(2, message.getRepeatedFieldCount(repeatedPackedField)); + EnumValueDescriptor enumValue0 = + (EnumValueDescriptor) message.getRepeatedField(repeatedPackedField, 0); + EnumValueDescriptor enumValue1 = + (EnumValueDescriptor) message.getRepeatedField(repeatedPackedField, 1); + + assertEquals(Proto2TestEnumSubset.TESTENUM_SUBSET_ZERO_VALUE, enumValue0.getNumber()); + assertEquals(Proto2TestEnumSubset.TESTENUM_SUBSET_ONE_VALUE, enumValue1.getNumber()); + + // Unknown enum values should be found in UnknownFieldSet. + UnknownFieldSet unknown = message.getUnknownFields(); + assertEquals( + Proto2TestEnum.TWO_VALUE, + unknown.getField(repeatedPackedField.getNumber()).getVarintList().get(0).longValue()); + } } diff --git a/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java deleted file mode 100644 index f8cb0aabbcff8..0000000000000 --- a/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java +++ /dev/null @@ -1,334 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf; - -import com.google.protobuf.UnittestLite.TestAllExtensionsLite; -import com.google.protobuf.UnittestLite.TestAllTypesLite; -import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash; -import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar; -import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import junit.framework.TestCase; - -/** - * Tests for {@link UnknownFieldSetLite}. - * - * @author dweis@google.com (Daniel Weis) - */ -public class UnknownFieldSetLiteTest extends TestCase { - - public void testDefaultInstance() { - UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance(); - - assertEquals(0, unknownFields.getSerializedSize()); - assertEquals(ByteString.EMPTY, toByteString(unknownFields)); - } - - public void testEmptyInstance() { - UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance(); - - assertEquals(0, instance.getSerializedSize()); - assertEquals(ByteString.EMPTY, toByteString(instance)); - assertEquals(UnknownFieldSetLite.getDefaultInstance(), instance); - } - - public void testMergeFieldFrom() throws IOException { - Foo foo = Foo.newBuilder() - .setValue(2) - .build(); - - CodedInputStream input = CodedInputStream.newInstance(foo.toByteArray()); - - UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance(); - instance.mergeFieldFrom(input.readTag(), input); - - assertEquals(foo.toByteString(), toByteString(instance)); - } - - public void testSerializedSize() throws IOException { - Foo foo = Foo.newBuilder() - .setValue(2) - .build(); - - CodedInputStream input = CodedInputStream.newInstance(foo.toByteArray()); - - UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance(); - instance.mergeFieldFrom(input.readTag(), input); - - assertEquals(foo.toByteString().size(), instance.getSerializedSize()); - } - - public void testMergeVarintField() throws IOException { - UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance(); - unknownFields.mergeVarintField(10, 2); - - CodedInputStream input = - CodedInputStream.newInstance(toByteString(unknownFields).toByteArray()); - - int tag = input.readTag(); - assertEquals(10, WireFormat.getTagFieldNumber(tag)); - assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag)); - assertEquals(2, input.readUInt64()); - assertTrue(input.isAtEnd()); - } - - public void testMergeVarintField_negative() throws IOException { - UnknownFieldSetLite builder = UnknownFieldSetLite.newInstance(); - builder.mergeVarintField(10, -6); - - CodedInputStream input = - CodedInputStream.newInstance(toByteString(builder).toByteArray()); - - int tag = input.readTag(); - assertEquals(10, WireFormat.getTagFieldNumber(tag)); - assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag)); - assertEquals(-6, input.readUInt64()); - assertTrue(input.isAtEnd()); - } - - public void testEqualsAndHashCode() { - UnknownFieldSetLite unknownFields1 = UnknownFieldSetLite.newInstance(); - unknownFields1.mergeVarintField(10, 2); - - UnknownFieldSetLite unknownFields2 = UnknownFieldSetLite.newInstance(); - unknownFields2.mergeVarintField(10, 2); - - assertEquals(unknownFields1, unknownFields2); - assertEquals(unknownFields1.hashCode(), unknownFields2.hashCode()); - assertFalse(unknownFields1.equals(UnknownFieldSetLite.getDefaultInstance())); - assertFalse(unknownFields1.hashCode() == UnknownFieldSetLite.getDefaultInstance().hashCode()); - } - - public void testMutableCopyOf() throws IOException { - UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance(); - unknownFields.mergeVarintField(10, 2); - unknownFields = UnknownFieldSetLite.mutableCopyOf(unknownFields, unknownFields); - unknownFields.checkMutable(); - - CodedInputStream input = - CodedInputStream.newInstance(toByteString(unknownFields).toByteArray()); - - int tag = input.readTag(); - assertEquals(10, WireFormat.getTagFieldNumber(tag)); - assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag)); - assertEquals(2, input.readUInt64()); - assertFalse(input.isAtEnd()); - input.readTag(); - assertEquals(10, WireFormat.getTagFieldNumber(tag)); - assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag)); - assertEquals(2, input.readUInt64()); - assertTrue(input.isAtEnd()); - } - - public void testMutableCopyOf_empty() { - UnknownFieldSetLite unknownFields = UnknownFieldSetLite.mutableCopyOf( - UnknownFieldSetLite.getDefaultInstance(), UnknownFieldSetLite.getDefaultInstance()); - unknownFields.checkMutable(); - - assertEquals(0, unknownFields.getSerializedSize()); - assertEquals(ByteString.EMPTY, toByteString(unknownFields)); - } - - public void testRoundTrips() throws InvalidProtocolBufferException { - Foo foo = Foo.newBuilder() - .setValue(1) - .setExtension(Bar.fooExt, Bar.newBuilder() - .setName("name") - .build()) - .setExtension(LiteEqualsAndHash.varint, 22) - .setExtension(LiteEqualsAndHash.fixed32, 44) - .setExtension(LiteEqualsAndHash.fixed64, 66L) - .setExtension(LiteEqualsAndHash.myGroup, LiteEqualsAndHash.MyGroup.newBuilder() - .setGroupValue("value") - .build()) - .build(); - - Foo copy = Foo.parseFrom(foo.toByteArray()); - - assertEquals(foo.getSerializedSize(), copy.getSerializedSize()); - assertFalse(foo.equals(copy)); - - Foo secondCopy = Foo.parseFrom(foo.toByteArray()); - assertEquals(copy, secondCopy); - - ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance(); - LiteEqualsAndHash.registerAllExtensions(extensionRegistry); - Foo copyOfCopy = Foo.parseFrom(copy.toByteArray(), extensionRegistry); - - assertEquals(foo, copyOfCopy); - } - - public void testMalformedBytes() throws Exception { - try { - Foo.parseFrom("this is a malformed protocol buffer".getBytes(Internal.UTF_8)); - fail(); - } catch (InvalidProtocolBufferException e) { - // Expected. - } - } - - public void testMissingStartGroupTag() throws IOException { - ByteString.Output byteStringOutput = ByteString.newOutput(); - CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput); - output.writeGroupNoTag(Foo.newBuilder().setValue(11).build()); - output.writeTag(100, WireFormat.WIRETYPE_END_GROUP); - output.flush(); - - try { - Foo.parseFrom(byteStringOutput.toByteString()); - fail(); - } catch (InvalidProtocolBufferException e) { - // Expected. - } - } - - public void testMissingEndGroupTag() throws IOException { - ByteString.Output byteStringOutput = ByteString.newOutput(); - CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput); - output.writeTag(100, WireFormat.WIRETYPE_START_GROUP); - output.writeGroupNoTag(Foo.newBuilder().setValue(11).build()); - output.flush(); - - try { - Foo.parseFrom(byteStringOutput.toByteString()); - fail(); - } catch (InvalidProtocolBufferException e) { - // Expected. - } - } - - public void testMismatchingGroupTags() throws IOException { - ByteString.Output byteStringOutput = ByteString.newOutput(); - CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput); - output.writeTag(100, WireFormat.WIRETYPE_START_GROUP); - output.writeGroupNoTag(Foo.newBuilder().setValue(11).build()); - output.writeTag(101, WireFormat.WIRETYPE_END_GROUP); - output.flush(); - - try { - Foo.parseFrom(byteStringOutput.toByteString()); - fail(); - } catch (InvalidProtocolBufferException e) { - // Expected. - } - } - - public void testTruncatedInput() { - Foo foo = Foo.newBuilder() - .setValue(1) - .setExtension(Bar.fooExt, Bar.newBuilder() - .setName("name") - .build()) - .setExtension(LiteEqualsAndHash.varint, 22) - .setExtension(LiteEqualsAndHash.myGroup, LiteEqualsAndHash.MyGroup.newBuilder() - .setGroupValue("value") - .build()) - .build(); - - try { - Foo.parseFrom(foo.toByteString().substring(0, foo.toByteString().size() - 10)); - fail(); - } catch (InvalidProtocolBufferException e) { - // Expected. - } - } - - public void testMakeImmutable() throws Exception { - UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance(); - unknownFields.makeImmutable(); - - try { - unknownFields.mergeVarintField(1, 1); - fail(); - } catch (UnsupportedOperationException expected) {} - - try { - unknownFields.mergeLengthDelimitedField(2, ByteString.copyFromUtf8("hello")); - fail(); - } catch (UnsupportedOperationException expected) {} - - try { - unknownFields.mergeFieldFrom(1, CodedInputStream.newInstance(new byte[0])); - fail(); - } catch (UnsupportedOperationException expected) {} - } - - public void testEndToEnd() throws Exception { - TestAllTypesLite testAllTypes = TestAllTypesLite.getDefaultInstance(); - try { - testAllTypes.unknownFields.checkMutable(); - fail(); - } catch (UnsupportedOperationException expected) {} - - testAllTypes = TestAllTypesLite.parseFrom(new byte[0]); - try { - testAllTypes.unknownFields.checkMutable(); - fail(); - } catch (UnsupportedOperationException expected) {} - - testAllTypes = TestAllTypesLite.newBuilder().build(); - try { - testAllTypes.unknownFields.checkMutable(); - fail(); - } catch (UnsupportedOperationException expected) {} - - testAllTypes = TestAllTypesLite.newBuilder() - .setDefaultBool(true) - .build(); - try { - testAllTypes.unknownFields.checkMutable(); - fail(); - } catch (UnsupportedOperationException expected) {} - - TestAllExtensionsLite testAllExtensions = TestAllExtensionsLite.newBuilder() - .mergeFrom(TestAllExtensionsLite.newBuilder() - .setExtension(UnittestLite.optionalInt32ExtensionLite, 2) - .build().toByteArray()) - .build(); - try { - testAllExtensions.unknownFields.checkMutable(); - fail(); - } catch (UnsupportedOperationException expected) {} - } - - private ByteString toByteString(UnknownFieldSetLite unknownFields) { - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream); - try { - unknownFields.writeTo(output); - output.flush(); - } catch (IOException e) { - throw new RuntimeException(e); - } - return ByteString.copyFrom(byteArrayOutputStream.toByteArray()); - } -} diff --git a/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java index f81e90b459295..c7eb57c63d4c0 100644 --- a/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java +++ b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java @@ -38,6 +38,7 @@ import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions; import protobuf_unittest.UnittestProto.TestPackedExtensions; import protobuf_unittest.UnittestProto.TestPackedTypes; +import proto3_unittest.UnittestProto3; import java.util.Arrays; import java.util.Map; import junit.framework.TestCase; @@ -69,13 +70,10 @@ UnknownFieldSet.Field getField(String name) { ByteString getBizarroData() throws Exception { UnknownFieldSet.Builder bizarroFields = UnknownFieldSet.newBuilder(); - UnknownFieldSet.Field varintField = - UnknownFieldSet.Field.newBuilder().addVarint(1).build(); - UnknownFieldSet.Field fixed32Field = - UnknownFieldSet.Field.newBuilder().addFixed32(1).build(); + UnknownFieldSet.Field varintField = UnknownFieldSet.Field.newBuilder().addVarint(1).build(); + UnknownFieldSet.Field fixed32Field = UnknownFieldSet.Field.newBuilder().addFixed32(1).build(); - for (Map.Entry entry : - unknownFields.asMap().entrySet()) { + for (Map.Entry entry : unknownFields.asMap().entrySet()) { if (entry.getValue().getVarintList().isEmpty()) { // Original field is not a varint, so use a varint. bizarroFields.addField(entry.getKey(), varintField); @@ -102,34 +100,30 @@ ByteString getBizarroData() throws Exception { public void testVarint() throws Exception { UnknownFieldSet.Field field = getField("optional_int32"); assertEquals(1, field.getVarintList().size()); - assertEquals(allFields.getOptionalInt32(), - (long) field.getVarintList().get(0)); + assertEquals(allFields.getOptionalInt32(), (long) field.getVarintList().get(0)); } public void testFixed32() throws Exception { UnknownFieldSet.Field field = getField("optional_fixed32"); assertEquals(1, field.getFixed32List().size()); - assertEquals(allFields.getOptionalFixed32(), - (int) field.getFixed32List().get(0)); + assertEquals(allFields.getOptionalFixed32(), (int) field.getFixed32List().get(0)); } public void testFixed64() throws Exception { UnknownFieldSet.Field field = getField("optional_fixed64"); assertEquals(1, field.getFixed64List().size()); - assertEquals(allFields.getOptionalFixed64(), - (long) field.getFixed64List().get(0)); + assertEquals(allFields.getOptionalFixed64(), (long) field.getFixed64List().get(0)); } public void testLengthDelimited() throws Exception { UnknownFieldSet.Field field = getField("optional_bytes"); assertEquals(1, field.getLengthDelimitedList().size()); - assertEquals(allFields.getOptionalBytes(), - field.getLengthDelimitedList().get(0)); + assertEquals(allFields.getOptionalBytes(), field.getLengthDelimitedList().get(0)); } public void testGroup() throws Exception { Descriptors.FieldDescriptor nestedFieldDescriptor = - TestAllTypes.OptionalGroup.getDescriptor().findFieldByName("a"); + TestAllTypes.OptionalGroup.getDescriptor().findFieldByName("a"); assertNotNull(nestedFieldDescriptor); UnknownFieldSet.Field field = getField("optionalgroup"); @@ -139,11 +133,9 @@ public void testGroup() throws Exception { assertEquals(1, group.asMap().size()); assertTrue(group.hasField(nestedFieldDescriptor.getNumber())); - UnknownFieldSet.Field nestedField = - group.getField(nestedFieldDescriptor.getNumber()); + UnknownFieldSet.Field nestedField = group.getField(nestedFieldDescriptor.getNumber()); assertEquals(1, nestedField.getVarintList().size()); - assertEquals(allFields.getOptionalGroup().getA(), - (long) nestedField.getVarintList().get(0)); + assertEquals(allFields.getOptionalGroup().getA(), (long) nestedField.getVarintList().get(0)); } public void testSerialize() throws Exception { @@ -154,59 +146,44 @@ public void testSerialize() throws Exception { } public void testCopyFrom() throws Exception { - TestEmptyMessage message = - TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).build(); + TestEmptyMessage message = TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).build(); assertEquals(emptyMessage.toString(), message.toString()); } public void testMergeFrom() throws Exception { TestEmptyMessage source = - TestEmptyMessage.newBuilder() - .setUnknownFields( - UnknownFieldSet.newBuilder() - .addField(2, - UnknownFieldSet.Field.newBuilder() - .addVarint(2).build()) - .addField(3, - UnknownFieldSet.Field.newBuilder() - .addVarint(4).build()) - .build()) - .build(); + TestEmptyMessage.newBuilder() + .setUnknownFields( + UnknownFieldSet.newBuilder() + .addField(2, UnknownFieldSet.Field.newBuilder().addVarint(2).build()) + .addField(3, UnknownFieldSet.Field.newBuilder().addVarint(4).build()) + .build()) + .build(); TestEmptyMessage destination = - TestEmptyMessage.newBuilder() - .setUnknownFields( - UnknownFieldSet.newBuilder() - .addField(1, - UnknownFieldSet.Field.newBuilder() - .addVarint(1).build()) - .addField(3, - UnknownFieldSet.Field.newBuilder() - .addVarint(3).build()) - .build()) - .mergeFrom(source) - .build(); + TestEmptyMessage.newBuilder() + .setUnknownFields( + UnknownFieldSet.newBuilder() + .addField(1, UnknownFieldSet.Field.newBuilder().addVarint(1).build()) + .addField(3, UnknownFieldSet.Field.newBuilder().addVarint(3).build()) + .build()) + .mergeFrom(source) + .build(); - assertEquals( - "1: 1\n" + - "2: 2\n" + - "3: 3\n" + - "3: 4\n", - destination.toString()); + assertEquals("1: 1\n2: 2\n3: 3\n3: 4\n", destination.toString()); } public void testClear() throws Exception { - UnknownFieldSet fields = - UnknownFieldSet.newBuilder().mergeFrom(unknownFields).clear().build(); + UnknownFieldSet fields = UnknownFieldSet.newBuilder().mergeFrom(unknownFields).clear().build(); assertTrue(fields.asMap().isEmpty()); } public void testClearMessage() throws Exception { TestEmptyMessage message = - TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).clear().build(); + TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).clear().build(); assertEquals(0, message.getSerializedSize()); } - + public void testClearField() throws Exception { int fieldNumber = unknownFields.asMap().keySet().iterator().next(); UnknownFieldSet fields = @@ -218,10 +195,9 @@ public void testParseKnownAndUnknown() throws Exception { // Test mixing known and unknown fields when parsing. UnknownFieldSet fields = - UnknownFieldSet.newBuilder(unknownFields) - .addField(123456, - UnknownFieldSet.Field.newBuilder().addVarint(654321).build()) - .build(); + UnknownFieldSet.newBuilder(unknownFields) + .addField(123456, UnknownFieldSet.Field.newBuilder().addVarint(654321).build()) + .build(); ByteString data = fields.toByteString(); TestAllTypes destination = TestAllTypes.parseFrom(data); @@ -229,8 +205,7 @@ public void testParseKnownAndUnknown() throws Exception { TestUtil.assertAllFieldsSet(destination); assertEquals(1, destination.getUnknownFields().asMap().size()); - UnknownFieldSet.Field field = - destination.getUnknownFields().getField(123456); + UnknownFieldSet.Field field = destination.getUnknownFields().getField(123456); assertEquals(1, field.getVarintList().size()); assertEquals(654321, (long) field.getVarintList().get(0)); } @@ -253,10 +228,9 @@ public void testUnknownExtensions() throws Exception { // they are declared as extension numbers. TestEmptyMessageWithExtensions message = - TestEmptyMessageWithExtensions.parseFrom(allFieldsData); + TestEmptyMessageWithExtensions.parseFrom(allFieldsData); - assertEquals(unknownFields.asMap().size(), - message.getUnknownFields().asMap().size()); + assertEquals(unknownFields.asMap().size(), message.getUnknownFields().asMap().size()); assertEquals(allFieldsData, message.toByteString()); } @@ -265,134 +239,99 @@ public void testWrongExtensionTypeTreatedAsUnknown() throws Exception { // when parsing extensions. ByteString bizarroData = getBizarroData(); - TestAllExtensions allExtensionsMessage = - TestAllExtensions.parseFrom(bizarroData); + TestAllExtensions allExtensionsMessage = TestAllExtensions.parseFrom(bizarroData); TestEmptyMessage emptyMessage = TestEmptyMessage.parseFrom(bizarroData); // All fields should have been interpreted as unknown, so the debug strings // should be the same. - assertEquals(emptyMessage.toString(), - allExtensionsMessage.toString()); + assertEquals(emptyMessage.toString(), allExtensionsMessage.toString()); } public void testParseUnknownEnumValue() throws Exception { Descriptors.FieldDescriptor singularField = - TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum"); + TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum"); Descriptors.FieldDescriptor repeatedField = - TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum"); + TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum"); assertNotNull(singularField); assertNotNull(repeatedField); ByteString data = - UnknownFieldSet.newBuilder() - .addField(singularField.getNumber(), - UnknownFieldSet.Field.newBuilder() - .addVarint(TestAllTypes.NestedEnum.BAR.getNumber()) - .addVarint(5) // not valid - .build()) - .addField(repeatedField.getNumber(), - UnknownFieldSet.Field.newBuilder() - .addVarint(TestAllTypes.NestedEnum.FOO.getNumber()) - .addVarint(4) // not valid - .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber()) - .addVarint(6) // not valid - .build()) - .build() - .toByteString(); + UnknownFieldSet.newBuilder() + .addField( + singularField.getNumber(), + UnknownFieldSet.Field.newBuilder() + .addVarint(TestAllTypes.NestedEnum.BAR.getNumber()) + .addVarint(5) // not valid + .build()) + .addField( + repeatedField.getNumber(), + UnknownFieldSet.Field.newBuilder() + .addVarint(TestAllTypes.NestedEnum.FOO.getNumber()) + .addVarint(4) // not valid + .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber()) + .addVarint(6) // not valid + .build()) + .build() + .toByteString(); { TestAllTypes message = TestAllTypes.parseFrom(data); - assertEquals(TestAllTypes.NestedEnum.BAR, - message.getOptionalNestedEnum()); + assertEquals(TestAllTypes.NestedEnum.BAR, message.getOptionalNestedEnum()); + assertEquals( + Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ), + message.getRepeatedNestedEnumList()); assertEquals( - Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ), - message.getRepeatedNestedEnumList()); - assertEquals(Arrays.asList(5L), - message.getUnknownFields() - .getField(singularField.getNumber()) - .getVarintList()); - assertEquals(Arrays.asList(4L, 6L), - message.getUnknownFields() - .getField(repeatedField.getNumber()) - .getVarintList()); + Arrays.asList(5L), + message.getUnknownFields().getField(singularField.getNumber()).getVarintList()); + assertEquals( + Arrays.asList(4L, 6L), + message.getUnknownFields().getField(repeatedField.getNumber()).getVarintList()); } { TestAllExtensions message = - TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry()); - assertEquals(TestAllTypes.NestedEnum.BAR, - message.getExtension(UnittestProto.optionalNestedEnumExtension)); + TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry()); + assertEquals( + TestAllTypes.NestedEnum.BAR, + message.getExtension(UnittestProto.optionalNestedEnumExtension)); assertEquals( - Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ), - message.getExtension(UnittestProto.repeatedNestedEnumExtension)); - assertEquals(Arrays.asList(5L), - message.getUnknownFields() - .getField(singularField.getNumber()) - .getVarintList()); - assertEquals(Arrays.asList(4L, 6L), - message.getUnknownFields() - .getField(repeatedField.getNumber()) - .getVarintList()); + Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ), + message.getExtension(UnittestProto.repeatedNestedEnumExtension)); + assertEquals( + Arrays.asList(5L), + message.getUnknownFields().getField(singularField.getNumber()).getVarintList()); + assertEquals( + Arrays.asList(4L, 6L), + message.getUnknownFields().getField(repeatedField.getNumber()).getVarintList()); } } public void testLargeVarint() throws Exception { ByteString data = - UnknownFieldSet.newBuilder() - .addField(1, - UnknownFieldSet.Field.newBuilder() - .addVarint(0x7FFFFFFFFFFFFFFFL) - .build()) - .build() - .toByteString(); + UnknownFieldSet.newBuilder() + .addField(1, UnknownFieldSet.Field.newBuilder().addVarint(0x7FFFFFFFFFFFFFFFL).build()) + .build() + .toByteString(); UnknownFieldSet parsed = UnknownFieldSet.parseFrom(data); UnknownFieldSet.Field field = parsed.getField(1); assertEquals(1, field.getVarintList().size()); - assertEquals(0x7FFFFFFFFFFFFFFFL, (long)field.getVarintList().get(0)); + assertEquals(0x7FFFFFFFFFFFFFFFL, (long) field.getVarintList().get(0)); } public void testEqualsAndHashCode() { - UnknownFieldSet.Field fixed32Field = - UnknownFieldSet.Field.newBuilder() - .addFixed32(1) - .build(); - UnknownFieldSet.Field fixed64Field = - UnknownFieldSet.Field.newBuilder() - .addFixed64(1) - .build(); - UnknownFieldSet.Field varIntField = - UnknownFieldSet.Field.newBuilder() - .addVarint(1) - .build(); + UnknownFieldSet.Field fixed32Field = UnknownFieldSet.Field.newBuilder().addFixed32(1).build(); + UnknownFieldSet.Field fixed64Field = UnknownFieldSet.Field.newBuilder().addFixed64(1).build(); + UnknownFieldSet.Field varIntField = UnknownFieldSet.Field.newBuilder().addVarint(1).build(); UnknownFieldSet.Field lengthDelimitedField = - UnknownFieldSet.Field.newBuilder() - .addLengthDelimited(ByteString.EMPTY) - .build(); + UnknownFieldSet.Field.newBuilder().addLengthDelimited(ByteString.EMPTY).build(); UnknownFieldSet.Field groupField = - UnknownFieldSet.Field.newBuilder() - .addGroup(unknownFields) - .build(); + UnknownFieldSet.Field.newBuilder().addGroup(unknownFields).build(); - UnknownFieldSet a = - UnknownFieldSet.newBuilder() - .addField(1, fixed32Field) - .build(); - UnknownFieldSet b = - UnknownFieldSet.newBuilder() - .addField(1, fixed64Field) - .build(); - UnknownFieldSet c = - UnknownFieldSet.newBuilder() - .addField(1, varIntField) - .build(); - UnknownFieldSet d = - UnknownFieldSet.newBuilder() - .addField(1, lengthDelimitedField) - .build(); - UnknownFieldSet e = - UnknownFieldSet.newBuilder() - .addField(1, groupField) - .build(); + UnknownFieldSet a = UnknownFieldSet.newBuilder().addField(1, fixed32Field).build(); + UnknownFieldSet b = UnknownFieldSet.newBuilder().addField(1, fixed64Field).build(); + UnknownFieldSet c = UnknownFieldSet.newBuilder().addField(1, varIntField).build(); + UnknownFieldSet d = UnknownFieldSet.newBuilder().addField(1, lengthDelimitedField).build(); + UnknownFieldSet e = UnknownFieldSet.newBuilder().addField(1, groupField).build(); checkEqualsIsConsistent(a); checkEqualsIsConsistent(b); @@ -413,12 +352,10 @@ public void testEqualsAndHashCode() { } /** - * Asserts that the given field sets are not equal and have different - * hash codes. + * Asserts that the given field sets are not equal and have different hash codes. * - * @warning It's valid for non-equal objects to have the same hash code, so - * this test is stricter than it needs to be. However, this should happen - * relatively rarely. + *

Note: It's valid for non-equal objects to have the same hash code, so this test is + * stricter than it needs to be. However, this should happen relatively rarely. */ private void checkNotEqual(UnknownFieldSet s1, UnknownFieldSet s2) { String equalsError = String.format("%s should not be equal to %s", s1, s2); @@ -430,9 +367,7 @@ private void checkNotEqual(UnknownFieldSet s1, UnknownFieldSet s2) { s1.hashCode() == s2.hashCode()); } - /** - * Asserts that the given field sets are equal and have identical hash codes. - */ + /** Asserts that the given field sets are equal and have identical hash codes. */ private void checkEqualsIsConsistent(UnknownFieldSet set) { // Object should be equal to itself. assertEquals(set, set); @@ -446,207 +381,27 @@ private void checkEqualsIsConsistent(UnknownFieldSet set) { // ================================================================= - public void testSerializeLite() throws Exception { - UnittestLite.TestEmptyMessageLite emptyMessageLite = - UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData); - assertEquals(allFieldsData.size(), emptyMessageLite.getSerializedSize()); - ByteString data = emptyMessageLite.toByteString(); - TestAllTypes message = TestAllTypes.parseFrom(data); - TestUtil.assertAllFieldsSet(message); - assertEquals(allFieldsData, data); - } - - public void testAllExtensionsLite() throws Exception { - TestAllExtensions allExtensions = TestUtil.getAllExtensionsSet(); - ByteString allExtensionsData = allExtensions.toByteString(); - UnittestLite.TestEmptyMessageLite emptyMessageLite = - UnittestLite.TestEmptyMessageLite.parser().parseFrom(allExtensionsData); - ByteString data = emptyMessageLite.toByteString(); - TestAllExtensions message = - TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry()); - TestUtil.assertAllExtensionsSet(message); - assertEquals(allExtensionsData, data); - } - - public void testAllPackedFieldsLite() throws Exception { - TestPackedTypes allPackedFields = TestUtil.getPackedSet(); - ByteString allPackedData = allPackedFields.toByteString(); - UnittestLite.TestEmptyMessageLite emptyMessageLite = - UnittestLite.TestEmptyMessageLite.parseFrom(allPackedData); - ByteString data = emptyMessageLite.toByteString(); - TestPackedTypes message = - TestPackedTypes.parseFrom(data, TestUtil.getExtensionRegistry()); - TestUtil.assertPackedFieldsSet(message); - assertEquals(allPackedData, data); - } - - public void testAllPackedExtensionsLite() throws Exception { - TestPackedExtensions allPackedExtensions = TestUtil.getPackedExtensionsSet(); - ByteString allPackedExtensionsData = allPackedExtensions.toByteString(); - UnittestLite.TestEmptyMessageLite emptyMessageLite = - UnittestLite.TestEmptyMessageLite.parseFrom(allPackedExtensionsData); - ByteString data = emptyMessageLite.toByteString(); - TestPackedExtensions message = - TestPackedExtensions.parseFrom(data, TestUtil.getExtensionRegistry()); - TestUtil.assertPackedExtensionsSet(message); - assertEquals(allPackedExtensionsData, data); - } - - public void testCopyFromLite() throws Exception { - UnittestLite.TestEmptyMessageLite emptyMessageLite = - UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData); - UnittestLite.TestEmptyMessageLite emptyMessageLite2 = - UnittestLite.TestEmptyMessageLite.newBuilder() - .mergeFrom(emptyMessageLite).build(); - assertEquals(emptyMessageLite.toByteString(), emptyMessageLite2.toByteString()); - } - - public void testMergeFromLite() throws Exception { - TestAllTypes message1 = TestAllTypes.newBuilder() - .setOptionalInt32(1) - .setOptionalString("foo") - .addRepeatedString("bar") - .setOptionalNestedEnum(TestAllTypes.NestedEnum.BAZ) - .build(); - - TestAllTypes message2 = TestAllTypes.newBuilder() - .setOptionalInt64(2) - .setOptionalString("baz") - .addRepeatedString("qux") - .setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ) - .build(); - - ByteString data1 = message1.toByteString(); - UnittestLite.TestEmptyMessageLite emptyMessageLite1 = - UnittestLite.TestEmptyMessageLite.parseFrom(data1); - ByteString data2 = message2.toByteString(); - UnittestLite.TestEmptyMessageLite emptyMessageLite2 = - UnittestLite.TestEmptyMessageLite.parseFrom(data2); - - message1 = TestAllTypes.newBuilder(message1).mergeFrom(message2).build(); - emptyMessageLite1 = UnittestLite.TestEmptyMessageLite.newBuilder(emptyMessageLite1) - .mergeFrom(emptyMessageLite2).build(); - - data1 = emptyMessageLite1.toByteString(); - message2 = TestAllTypes.parseFrom(data1); - - assertEquals(message1, message2); - } - - public void testWrongTypeTreatedAsUnknownLite() throws Exception { - // Test that fields of the wrong wire type are treated like unknown fields - // when parsing. - - ByteString bizarroData = getBizarroData(); - TestAllTypes allTypesMessage = TestAllTypes.parseFrom(bizarroData); - UnittestLite.TestEmptyMessageLite emptyMessageLite = - UnittestLite.TestEmptyMessageLite.parseFrom(bizarroData); - ByteString data = emptyMessageLite.toByteString(); - TestAllTypes allTypesMessage2 = TestAllTypes.parseFrom(data); - - assertEquals(allTypesMessage.toString(), allTypesMessage2.toString()); - } - - public void testUnknownExtensionsLite() throws Exception { - // Make sure fields are properly parsed to the UnknownFieldSet even when - // they are declared as extension numbers. - - UnittestLite.TestEmptyMessageWithExtensionsLite message = - UnittestLite.TestEmptyMessageWithExtensionsLite.parseFrom(allFieldsData); - - assertEquals(allFieldsData, message.toByteString()); - } - - public void testWrongExtensionTypeTreatedAsUnknownLite() throws Exception { - // Test that fields of the wrong wire type are treated like unknown fields - // when parsing extensions. - - ByteString bizarroData = getBizarroData(); - TestAllExtensions allExtensionsMessage = - TestAllExtensions.parseFrom(bizarroData); - UnittestLite.TestEmptyMessageLite emptyMessageLite = - UnittestLite.TestEmptyMessageLite.parseFrom(bizarroData); + public void testProto3RoundTrip() throws Exception { + ByteString data = getBizarroData(); - // All fields should have been interpreted as unknown, so the byte strings - // should be the same. - assertEquals(emptyMessageLite.toByteString(), - allExtensionsMessage.toByteString()); - } + UnittestProto3.TestEmptyMessage message = + UnittestProto3.TestEmptyMessage.parseFrom(data, ExtensionRegistryLite.getEmptyRegistry()); + assertEquals(data, message.toByteString()); - public void testParseUnknownEnumValueLite() throws Exception { - Descriptors.FieldDescriptor singularField = - TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum"); - Descriptors.FieldDescriptor repeatedField = - TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum"); - assertNotNull(singularField); - assertNotNull(repeatedField); + message = UnittestProto3.TestEmptyMessage.newBuilder().mergeFrom(message).build(); + assertEquals(data, message.toByteString()); - ByteString data = - UnknownFieldSet.newBuilder() - .addField(singularField.getNumber(), - UnknownFieldSet.Field.newBuilder() - .addVarint(TestAllTypes.NestedEnum.BAR.getNumber()) - .addVarint(5) // not valid - .build()) - .addField(repeatedField.getNumber(), - UnknownFieldSet.Field.newBuilder() - .addVarint(TestAllTypes.NestedEnum.FOO.getNumber()) - .addVarint(4) // not valid - .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber()) - .addVarint(6) // not valid - .build()) - .build() - .toByteString(); - - UnittestLite.TestEmptyMessageLite emptyMessageLite = - UnittestLite.TestEmptyMessageLite.parseFrom(data); - data = emptyMessageLite.toByteString(); - - { - TestAllTypes message = TestAllTypes.parseFrom(data); - assertEquals(TestAllTypes.NestedEnum.BAR, - message.getOptionalNestedEnum()); - assertEquals( - Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ), - message.getRepeatedNestedEnumList()); - assertEquals(Arrays.asList(5L), - message.getUnknownFields() - .getField(singularField.getNumber()) - .getVarintList()); - assertEquals(Arrays.asList(4L, 6L), - message.getUnknownFields() - .getField(repeatedField.getNumber()) - .getVarintList()); - } - - { - TestAllExtensions message = - TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry()); - assertEquals(TestAllTypes.NestedEnum.BAR, - message.getExtension(UnittestProto.optionalNestedEnumExtension)); - assertEquals( - Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ), - message.getExtension(UnittestProto.repeatedNestedEnumExtension)); - assertEquals(Arrays.asList(5L), - message.getUnknownFields() - .getField(singularField.getNumber()) - .getVarintList()); - assertEquals(Arrays.asList(4L, 6L), - message.getUnknownFields() - .getField(repeatedField.getNumber()) - .getVarintList()); - } - } - - public void testClearLite() throws Exception { - UnittestLite.TestEmptyMessageLite emptyMessageLite1 = - UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData); - UnittestLite.TestEmptyMessageLite emptyMessageLite2 = - UnittestLite.TestEmptyMessageLite.newBuilder() - .mergeFrom(emptyMessageLite1).clear().build(); - assertEquals(0, emptyMessageLite2.getSerializedSize()); - ByteString data = emptyMessageLite2.toByteString(); - assertEquals(0, data.size()); + assertEquals( + data, + UnittestProto3.TestMessageWithDummy.parseFrom( + data, ExtensionRegistryLite.getEmptyRegistry()) + .toBuilder() + // force copy-on-write + .setDummy(true) + .build() + .toBuilder() + .clearDummy() + .build() + .toByteString()); } - } diff --git a/java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java b/java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java index 00f201ca588aa..bc73cc97839dc 100644 --- a/java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java +++ b/java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java @@ -42,13 +42,13 @@ */ public class UnmodifiableLazyStringListTest extends TestCase { - private static String STRING_A = "A"; - private static String STRING_B = "B"; - private static String STRING_C = "C"; + private static final String STRING_A = "A"; + private static final String STRING_B = "B"; + private static final String STRING_C = "C"; - private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A"); - private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B"); - private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C"); + private static final ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A"); + private static final ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B"); + private static final ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C"); public void testReadOnlyMethods() { LazyStringArrayList rawList = createSampleList(); diff --git a/java/core/src/test/java/com/google/protobuf/Utf8Test.java b/java/core/src/test/java/com/google/protobuf/Utf8Test.java new file mode 100644 index 0000000000000..bc3c985104a58 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Utf8Test.java @@ -0,0 +1,232 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Random; +import java.util.regex.Pattern; +import junit.framework.TestCase; + +/** Unit tests for {@link Utf8}. */ +public class Utf8Test extends TestCase { + private static final int NUM_CHARS = 16384; + + private static final Utf8.Processor safeProcessor = new Utf8.SafeProcessor(); + private static final Utf8.Processor unsafeProcessor = new Utf8.UnsafeProcessor(); + + public void testEncode() { + assertEncoding(randomString(0x80)); + assertEncoding(randomString(0x90)); + assertEncoding(randomString(0x800)); + assertEncoding(randomString(0x10000)); + assertEncoding(randomString(0x10ffff)); + } + + public void testEncode_insufficientSpace() { + assertEncoding_insufficientSpace(randomString(0x80)); + assertEncoding_insufficientSpace(randomString(0x90)); + assertEncoding_insufficientSpace(randomString(0x800)); + assertEncoding_insufficientSpace(randomString(0x10000)); + assertEncoding_insufficientSpace(randomString(0x10ffff)); + } + + public void testValid() { + assertIsValid(new byte[] {(byte) 0xE0, (byte) 0xB9, (byte) 0x96}, true); + assertIsValid(new byte[] {(byte) 0xF0, (byte) 0xB2, (byte) 0x83, (byte) 0xBC}, true); + } + + public void testOverlongIsInvalid() { + assertIsValid(new byte[] {(byte) 0xC0, (byte) 0x81}, false); + assertIsValid(new byte[] {(byte) 0xE0, (byte) 0x81, (byte) 0x81}, false); + assertIsValid(new byte[] {(byte) 0xF0, (byte) 0x81, (byte) 0x81, (byte) 0x81}, false); + } + + public void testMaxCodepointExceeded() { + // byte1 > 0xF4 + assertIsValid(new byte[] {(byte) 0xF5, (byte) 0x81, (byte) 0x81, (byte) 0x81}, false); + } + + public void testInvalidSurrogateCodepoint() { + assertIsValid(new byte[] {(byte) 0xED, (byte) 0xA1, (byte) 0x81}, false); + + // byte1 == 0xF0 && byte2 < 0x90 + assertIsValid(new byte[] {(byte) 0xF0, (byte) 0x81, (byte) 0x81, (byte) 0x81}, false); + // byte1 == 0xF4 && byte2 > 0x8F + assertIsValid(new byte[] {(byte) 0xF4, (byte) 0x90, (byte) 0x81, (byte) 0x81}, false); + } + + private static String randomString(int maxCodePoint) { + final long seed = 99; + final Random rnd = new Random(seed); + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < NUM_CHARS; j++) { + int codePoint; + do { + codePoint = rnd.nextInt(maxCodePoint); + } while (Utf8Utils.isSurrogate(codePoint)); + sb.appendCodePoint(codePoint); + } + return sb.toString(); + } + + private static void assertIsValid(byte[] data, boolean valid) { + assertEquals("isValidUtf8[ARRAY]", valid, safeProcessor.isValidUtf8(data, 0, data.length)); + assertEquals( + "isValidUtf8[ARRAY_UNSAFE]", valid, unsafeProcessor.isValidUtf8(data, 0, data.length)); + + ByteBuffer buffer = ByteBuffer.wrap(data); + assertEquals( + "isValidUtf8[NIO_HEAP]", + valid, + safeProcessor.isValidUtf8(buffer, buffer.position(), buffer.remaining())); + + // Direct buffers. + buffer = ByteBuffer.allocateDirect(data.length); + buffer.put(data); + buffer.flip(); + assertEquals( + "isValidUtf8[NIO_DEFAULT]", + valid, + safeProcessor.isValidUtf8(buffer, buffer.position(), buffer.remaining())); + assertEquals( + "isValidUtf8[NIO_UNSAFE]", + valid, + unsafeProcessor.isValidUtf8(buffer, buffer.position(), buffer.remaining())); + } + + private static void assertEncoding(String message) { + byte[] expected = message.getBytes(Internal.UTF_8); + byte[] output = encodeToByteArray(message, expected.length, safeProcessor); + assertTrue("encodeUtf8[ARRAY]", Arrays.equals(expected, output)); + + output = encodeToByteArray(message, expected.length, unsafeProcessor); + assertTrue("encodeUtf8[ARRAY_UNSAFE]", Arrays.equals(expected, output)); + + output = encodeToByteBuffer(message, expected.length, false, safeProcessor); + assertTrue("encodeUtf8[NIO_HEAP]", Arrays.equals(expected, output)); + + output = encodeToByteBuffer(message, expected.length, true, safeProcessor); + assertTrue("encodeUtf8[NIO_DEFAULT]", Arrays.equals(expected, output)); + + output = encodeToByteBuffer(message, expected.length, true, unsafeProcessor); + assertTrue("encodeUtf8[NIO_UNSAFE]", Arrays.equals(expected, output)); + } + + private void assertEncoding_insufficientSpace(String message) { + final int length = message.length() - 1; + Class clazz = ArrayIndexOutOfBoundsException.class; + + try { + encodeToByteArray(message, length, safeProcessor); + fail("Expected " + clazz.getSimpleName()); + } catch (Throwable t) { + // Expected + assertExceptionType(t, clazz); + // byte[] + safeProcessor will not exit early. We can't match the message since we don't + // know which char/index due to random input. + } + + try { + encodeToByteArray(message, length, unsafeProcessor); + fail("Expected " + clazz.getSimpleName()); + } catch (Throwable t) { + assertExceptionType(t, clazz); + // byte[] + unsafeProcessor will exit early, so we have can match the message. + assertExceptionMessage(t, length); + } + + try { + encodeToByteBuffer(message, length, false, safeProcessor); + fail("Expected " + clazz.getSimpleName()); + } catch (Throwable t) { + // Expected + assertExceptionType(t, clazz); + // ByteBuffer + safeProcessor will not exit early. We can't match the message since we don't + // know which char/index due to random input. + } + + try { + encodeToByteBuffer(message, length, true, safeProcessor); + fail("Expected " + clazz.getSimpleName()); + } catch (Throwable t) { + // Expected + assertExceptionType(t, clazz); + // ByteBuffer + safeProcessor will not exit early. We can't match the message since we don't + // know which char/index due to random input. + } + + try { + encodeToByteBuffer(message, length, true, unsafeProcessor); + fail("Expected " + clazz.getSimpleName()); + } catch (Throwable t) { + // Expected + assertExceptionType(t, clazz); + // Direct ByteBuffer + unsafeProcessor will exit early if it's not on Android, so we can + // match the message. On Android, a direct ByteBuffer will have hasArray() being true and + // it will take a different code path and produces a different message. + if (!Android.isOnAndroidDevice()) { + assertExceptionMessage(t, length); + } + } + } + + private static byte[] encodeToByteArray(String message, int length, Utf8.Processor processor) { + byte[] output = new byte[length]; + processor.encodeUtf8(message, output, 0, output.length); + return output; + } + + private static byte[] encodeToByteBuffer( + String message, int length, boolean direct, Utf8.Processor processor) { + ByteBuffer buffer = direct ? ByteBuffer.allocateDirect(length) : ByteBuffer.allocate(length); + + processor.encodeUtf8(message, buffer); + buffer.flip(); + + byte[] output = new byte[buffer.remaining()]; + buffer.get(output); + return output; + } + + private void assertExceptionType(Throwable t, Class expected) { + if (!expected.isAssignableFrom(t.getClass())) { + fail("Expected " + expected.getSimpleName() + ", but found " + t.getClass().getSimpleName()); + } + } + + private void assertExceptionMessage(Throwable t, int index) { + String pattern = "Failed writing (.) at index " + index; + assertTrue( + t.getMessage() + " does not match pattern " + pattern, + Pattern.matches(pattern, t.getMessage())); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/Utf8Utils.java b/java/core/src/test/java/com/google/protobuf/Utf8Utils.java new file mode 100644 index 0000000000000..dbd3d3961a461 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/Utf8Utils.java @@ -0,0 +1,193 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static java.lang.Character.MIN_HIGH_SURROGATE; +import static java.lang.Character.MIN_LOW_SURROGATE; +import static java.lang.Character.MIN_SURROGATE; + +import java.util.Random; + +/** Utilities for benchmarking UTF-8. */ +final class Utf8Utils { + private Utf8Utils() {} + + static class MaxCodePoint { + final int value; + + /** + * Convert the input string to a code point. Accepts regular decimal numerals, hex strings, and + * some symbolic names meaningful to humans. + */ + private static int decode(String userFriendly) { + try { + return Integer.decode(userFriendly); + } catch (NumberFormatException ignored) { + if (userFriendly.matches("(?i)(?:American|English|ASCII)")) { + // 1-byte UTF-8 sequences - "American" ASCII text + return 0x80; + } else if (userFriendly.matches("(?i)(?:Danish|Latin|Western.*European)")) { + // Mostly 1-byte UTF-8 sequences, mixed with occasional 2-byte + // sequences - "Western European" text + return 0x90; + } else if (userFriendly.matches("(?i)(?:Greek|Cyrillic|European|ISO.?8859)")) { + // Mostly 2-byte UTF-8 sequences - "European" text + return 0x800; + } else if (userFriendly.matches("(?i)(?:Chinese|Han|Asian|BMP)")) { + // Mostly 3-byte UTF-8 sequences - "Asian" text + return Character.MIN_SUPPLEMENTARY_CODE_POINT; + } else if (userFriendly.matches("(?i)(?:Cuneiform|rare|exotic|supplementary.*)")) { + // Mostly 4-byte UTF-8 sequences - "rare exotic" text + return Character.MAX_CODE_POINT; + } else { + throw new IllegalArgumentException("Can't decode codepoint " + userFriendly); + } + } + } + + public static MaxCodePoint valueOf(String userFriendly) { + return new MaxCodePoint(userFriendly); + } + + public MaxCodePoint(String userFriendly) { + value = decode(userFriendly); + } + } + + /** + * The Utf8 distribution of real data. The distribution is an array with length 4. + * "distribution[i]" means the total number of characters who are encoded with (i + 1) bytes. + * + *

GMM_UTF8_DISTRIBUTION is the distribution of gmm data set. GSR_UTF8_DISTRIBUTION is the + * distribution of gsreq/gsresp data set + */ + public enum Utf8Distribution { + GMM_UTF8_DISTRIBUTION { + @Override + public int[] getDistribution() { + return new int[] {53059, 104, 0, 0}; + } + }, + GSR_UTF8_DISTRIBUTION { + @Override + public int[] getDistribution() { + return new int[] {119458, 74, 2706, 0}; + } + }; + + public abstract int[] getDistribution(); + } + + /** + * Creates an array of random strings. + * + * @param stringCount the number of strings to be created. + * @param charCount the number of characters per string. + * @param maxCodePoint the maximum code point for the characters in the strings. + * @return an array of random strings. + */ + static String[] randomStrings(int stringCount, int charCount, MaxCodePoint maxCodePoint) { + final long seed = 99; + final Random rnd = new Random(seed); + String[] strings = new String[stringCount]; + for (int i = 0; i < stringCount; i++) { + strings[i] = randomString(rnd, charCount, maxCodePoint); + } + return strings; + } + + /** + * Creates a random string + * + * @param rnd the random generator. + * @param charCount the number of characters per string. + * @param maxCodePoint the maximum code point for the characters in the strings. + */ + static String randomString(Random rnd, int charCount, MaxCodePoint maxCodePoint) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < charCount; i++) { + int codePoint; + do { + codePoint = rnd.nextInt(maxCodePoint.value); + } while (Utf8Utils.isSurrogate(codePoint)); + sb.appendCodePoint(codePoint); + } + return sb.toString(); + } + + /** Character.isSurrogate was added in Java SE 7. */ + static boolean isSurrogate(int c) { + return Character.MIN_HIGH_SURROGATE <= c && c <= Character.MAX_LOW_SURROGATE; + } + + /** + * Creates an array of random strings according to UTF8 distribution. + * + * @param stringCount the number of strings to be created. + * @param charCount the number of characters per string. + */ + static String[] randomStringsWithDistribution( + int stringCount, int charCount, Utf8Distribution utf8Distribution) { + final int[] distribution = utf8Distribution.getDistribution(); + for (int i = 0; i < 3; i++) { + distribution[i + 1] += distribution[i]; + } + final long seed = 99; + final Random rnd = new Random(seed); + String[] strings = new String[stringCount]; + for (int i = 0; i < stringCount; i++) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < charCount; j++) { + int codePoint; + do { + codePoint = rnd.nextInt(distribution[3]); + if (codePoint < distribution[0]) { + // 1 bytes + sb.append(0x7F); + } else if (codePoint < distribution[1]) { + // 2 bytes + sb.append(0x7FF); + } else if (codePoint < distribution[2]) { + // 3 bytes + sb.append(MIN_SURROGATE - 1); + } else { + // 4 bytes + sb.append(MIN_HIGH_SURROGATE); + sb.append(MIN_LOW_SURROGATE); + } + } while (Utf8Utils.isSurrogate(codePoint)); + sb.appendCodePoint(codePoint); + } + strings[i] = sb.toString(); + } + return strings; + } +} diff --git a/java/core/src/test/java/com/google/protobuf/WireFormatLiteTest.java b/java/core/src/test/java/com/google/protobuf/WireFormatLiteTest.java new file mode 100644 index 0000000000000..a725d413ff5ec --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/WireFormatLiteTest.java @@ -0,0 +1,1023 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite; + +import com.google.protobuf.UnittestLite.ForeignEnumLite; +import com.google.protobuf.UnittestLite.TestAllExtensionsLite; +import com.google.protobuf.UnittestLite.TestPackedExtensionsLite; +import map_test.MapForProto2TestProto; +import map_test.MapTestProto.TestMap; +import protobuf_unittest.UnittestMset.RawMessageSet; +import protobuf_unittest.UnittestMset.TestMessageSetExtension1; +import protobuf_unittest.UnittestMset.TestMessageSetExtension2; +import protobuf_unittest.UnittestProto; +import protobuf_unittest.UnittestProto.TestAllExtensions; +import protobuf_unittest.UnittestProto.TestAllTypes; +import protobuf_unittest.UnittestProto.TestExtensionInsideTable; +import protobuf_unittest.UnittestProto.TestFieldOrderings; +import protobuf_unittest.UnittestProto.TestOneof2; +import protobuf_unittest.UnittestProto.TestOneofBackwardsCompatible; +import protobuf_unittest.UnittestProto.TestPackedExtensions; +import protobuf_unittest.UnittestProto.TestPackedTypes; +import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet; +import proto3_unittest.UnittestProto3; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; +import junit.framework.TestCase; + +public class WireFormatLiteTest extends TestCase { + public void testSerializeExtensionsLite() throws Exception { + // TestAllTypes and TestAllExtensions should have compatible wire formats, + // so if we serialize a TestAllExtensions then parse it as TestAllTypes + // it should work. + + TestAllExtensionsLite message = TestUtilLite.getAllLiteExtensionsSet(); + ByteString rawBytes = message.toByteString(); + assertEquals(rawBytes.size(), message.getSerializedSize()); + + TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes); + + TestUtil.assertAllFieldsSet(message2); + } + + public void testSerializePackedExtensionsLite() throws Exception { + // TestPackedTypes and TestPackedExtensions should have compatible wire + // formats; check that they serialize to the same string. + TestPackedExtensionsLite message = TestUtilLite.getLitePackedExtensionsSet(); + ByteString rawBytes = message.toByteString(); + + TestPackedTypes message2 = TestUtil.getPackedSet(); + ByteString rawBytes2 = message2.toByteString(); + + assertEquals(rawBytes, rawBytes2); + } + + public void testParseExtensionsLite() throws Exception { + // TestAllTypes and TestAllExtensions should have compatible wire formats, + // so if we serialize a TestAllTypes then parse it as TestAllExtensions + // it should work. + + TestAllTypes message = TestUtil.getAllSet(); + ByteString rawBytes = message.toByteString(); + + ExtensionRegistryLite registryLite = TestUtilLite.getExtensionRegistryLite(); + + TestAllExtensionsLite message2 = TestAllExtensionsLite.parseFrom(rawBytes, registryLite); + TestUtil.assertAllExtensionsSet(message2); + message2 = TestAllExtensionsLite.parseFrom(message.toByteArray(), registryLite); + TestUtil.assertAllExtensionsSet(message2); + } + + public void testParsePackedExtensionsLite() throws Exception { + // Ensure that packed extensions can be properly parsed. + TestPackedExtensionsLite message = TestUtilLite.getLitePackedExtensionsSet(); + ByteString rawBytes = message.toByteString(); + + ExtensionRegistryLite registry = TestUtilLite.getExtensionRegistryLite(); + + TestPackedExtensionsLite message2 = TestPackedExtensionsLite.parseFrom(rawBytes, registry); + TestUtil.assertPackedExtensionsSet(message2); + message2 = TestPackedExtensionsLite.parseFrom(message.toByteArray(), registry); + TestUtil.assertPackedExtensionsSet(message2); + } + + public void testSerialization() throws Exception { + TestAllTypes message = TestUtil.getAllSet(); + + ByteString rawBytes = message.toByteString(); + assertEquals(rawBytes.size(), message.getSerializedSize()); + + TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes); + + TestUtil.assertAllFieldsSet(message2); + } + + public void testSerializationPacked() throws Exception { + TestPackedTypes message = TestUtil.getPackedSet(); + + ByteString rawBytes = message.toByteString(); + assertEquals(rawBytes.size(), message.getSerializedSize()); + + TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes); + + TestUtil.assertPackedFieldsSet(message2); + } + + public void testSerializeExtensions() throws Exception { + // TestAllTypes and TestAllExtensions should have compatible wire formats, + // so if we serialize a TestAllExtensions then parse it as TestAllTypes + // it should work. + + TestAllExtensions message = TestUtil.getAllExtensionsSet(); + ByteString rawBytes = message.toByteString(); + assertEquals(rawBytes.size(), message.getSerializedSize()); + + TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes); + + TestUtil.assertAllFieldsSet(message2); + } + + public void testSerializePackedExtensions() throws Exception { + // TestPackedTypes and TestPackedExtensions should have compatible wire + // formats; check that they serialize to the same string. + TestPackedExtensions message = TestUtil.getPackedExtensionsSet(); + ByteString rawBytes = message.toByteString(); + + TestPackedTypes message2 = TestUtil.getPackedSet(); + ByteString rawBytes2 = message2.toByteString(); + + assertEquals(rawBytes, rawBytes2); + } + + public void testSerializationPackedWithoutGetSerializedSize() throws Exception { + // Write directly to an OutputStream, without invoking getSerializedSize() + // This used to be a bug where the size of a packed field was incorrect, + // since getSerializedSize() was never invoked. + TestPackedTypes message = TestUtil.getPackedSet(); + + // Directly construct a CodedOutputStream around the actual OutputStream, + // in case writeTo(OutputStream output) invokes getSerializedSize(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + CodedOutputStream codedOutput = CodedOutputStream.newInstance(outputStream); + + message.writeTo(codedOutput); + + codedOutput.flush(); + + TestPackedTypes message2 = TestPackedTypes.parseFrom(outputStream.toByteArray()); + + TestUtil.assertPackedFieldsSet(message2); + } + + public void testParseExtensions() throws Exception { + // TestAllTypes and TestAllExtensions should have compatible wire formats, + // so if we serialize a TestAllTypes then parse it as TestAllExtensions + // it should work. + + TestAllTypes message = TestUtil.getAllSet(); + ByteString rawBytes = message.toByteString(); + + ExtensionRegistryLite registry = TestUtil.getExtensionRegistry(); + + TestAllExtensions message2 = TestAllExtensions.parseFrom(rawBytes, registry); + + TestUtil.assertAllExtensionsSet(message2); + } + + public void testParsePackedExtensions() throws Exception { + // Ensure that packed extensions can be properly parsed. + TestPackedExtensions message = TestUtil.getPackedExtensionsSet(); + ByteString rawBytes = message.toByteString(); + + ExtensionRegistryLite registry = TestUtil.getExtensionRegistry(); + + TestPackedExtensions message2 = TestPackedExtensions.parseFrom(rawBytes, registry); + + TestUtil.assertPackedExtensionsSet(message2); + } + + public void testSerializeDelimited() throws Exception { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + TestUtil.getAllSet().writeDelimitedTo(output); + output.write(12); + TestUtil.getPackedSet().writeDelimitedTo(output); + output.write(34); + + ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray()); + + TestUtil.assertAllFieldsSet(TestAllTypes.parseDelimitedFrom(input)); + assertEquals(12, input.read()); + TestUtil.assertPackedFieldsSet(TestPackedTypes.parseDelimitedFrom(input)); + assertEquals(34, input.read()); + assertEquals(-1, input.read()); + + // We're at EOF, so parsing again should return null. + assertNull(TestAllTypes.parseDelimitedFrom(input)); + } + + private ExtensionRegistryLite getTestFieldOrderingsRegistry() { + ExtensionRegistryLite result = ExtensionRegistryLite.newInstance(); + result.add(UnittestProto.myExtensionInt); + result.add(UnittestProto.myExtensionString); + return result; + } + + public void testParseMultipleExtensionRanges() throws Exception { + // Make sure we can parse a message that contains multiple extensions + // ranges. + TestFieldOrderings source = + TestFieldOrderings.newBuilder() + .setMyInt(1) + .setMyString("foo") + .setMyFloat(1.0F) + .setExtension(UnittestProto.myExtensionInt, 23) + .setExtension(UnittestProto.myExtensionString, "bar") + .build(); + TestFieldOrderings dest = + TestFieldOrderings.parseFrom(source.toByteString(), getTestFieldOrderingsRegistry()); + assertEquals(source, dest); + } + + private static ExtensionRegistryLite getTestExtensionInsideTableRegistry() { + ExtensionRegistryLite result = ExtensionRegistryLite.newInstance(); + result.add(UnittestProto.testExtensionInsideTableExtension); + return result; + } + + public void testExtensionInsideTable() throws Exception { + // Make sure the extension within the range of table is parsed correctly in experimental + // runtime. + TestExtensionInsideTable source = + TestExtensionInsideTable.newBuilder() + .setField1(1) + .setExtension(UnittestProto.testExtensionInsideTableExtension, 23) + .build(); + TestExtensionInsideTable dest = + TestExtensionInsideTable.parseFrom( + source.toByteString(), getTestExtensionInsideTableRegistry()); + assertEquals(source, dest); + } + + private static final int UNKNOWN_TYPE_ID = 1550055; + private static final int TYPE_ID_1 = 1545008; + private static final int TYPE_ID_2 = 1547769; + + public void testSerializeMessageSetEagerly() throws Exception { + testSerializeMessageSetWithFlag(true); + } + + public void testSerializeMessageSetNotEagerly() throws Exception { + testSerializeMessageSetWithFlag(false); + } + + private void testSerializeMessageSetWithFlag(boolean eagerParsing) throws Exception { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream); + output.writeRawMessageSetExtension(UNKNOWN_TYPE_ID, ByteString.copyFromUtf8("bar")); + output.flush(); + byte[] messageSetBytes = byteArrayOutputStream.toByteArray(); + + ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); + // Set up a TestMessageSet with two known messages and an unknown one. + TestMessageSet messageSet = + TestMessageSet.newBuilder() + .setExtension( + TestMessageSetExtension1.messageSetExtension, + TestMessageSetExtension1.newBuilder().setI(123).build()) + .setExtension( + TestMessageSetExtension2.messageSetExtension, + TestMessageSetExtension2.newBuilder().setStr("foo").build()) + .mergeFrom(messageSetBytes) + .build(); + + ByteString data = messageSet.toByteString(); + + // Parse back using RawMessageSet and check the contents. + RawMessageSet raw = RawMessageSet.parseFrom(data); + + assertEquals(3, raw.getItemCount()); + assertEquals(TYPE_ID_1, raw.getItem(0).getTypeId()); + assertEquals(TYPE_ID_2, raw.getItem(1).getTypeId()); + assertEquals(UNKNOWN_TYPE_ID, raw.getItem(2).getTypeId()); + + TestMessageSetExtension1 message1 = + TestMessageSetExtension1.parseFrom(raw.getItem(0).getMessage()); + assertEquals(123, message1.getI()); + + TestMessageSetExtension2 message2 = + TestMessageSetExtension2.parseFrom(raw.getItem(1).getMessage()); + assertEquals("foo", message2.getStr()); + + assertEquals("bar", raw.getItem(2).getMessage().toStringUtf8()); + } + + public void testParseMessageSetEagerly() throws Exception { + testParseMessageSetWithFlag(true); + } + + public void testParseMessageSetNotEagerly() throws Exception { + testParseMessageSetWithFlag(false); + } + + private void testParseMessageSetWithFlag(boolean eagerParsing) throws Exception { + ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); + ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance(); + extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); + extensionRegistry.add(TestMessageSetExtension2.messageSetExtension); + + // Set up a RawMessageSet with two known messages and an unknown one. + RawMessageSet raw = + RawMessageSet.newBuilder() + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(TYPE_ID_1) + .setMessage( + TestMessageSetExtension1.newBuilder().setI(123).build().toByteString()) + .build()) + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(TYPE_ID_2) + .setMessage( + TestMessageSetExtension2.newBuilder().setStr("foo").build().toByteString()) + .build()) + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(UNKNOWN_TYPE_ID) + .setMessage(ByteString.copyFromUtf8("bar")) + .build()) + .build(); + + ByteString data = raw.toByteString(); + + // Parse as a TestMessageSet and check the contents. + TestMessageSet messageSet = TestMessageSet.parseFrom(data, extensionRegistry); + + assertEquals(123, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()); + assertEquals( + "foo", messageSet.getExtension(TestMessageSetExtension2.messageSetExtension).getStr()); + } + + public void testParseMessageSetExtensionEagerly() throws Exception { + testParseMessageSetExtensionWithFlag(true); + } + + public void testParseMessageSetExtensionNotEagerly() throws Exception { + testParseMessageSetExtensionWithFlag(false); + } + + private void testParseMessageSetExtensionWithFlag(boolean eagerParsing) throws Exception { + ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); + ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance(); + extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); + + // Set up a RawMessageSet with a known messages. + int typeId1 = 1545008; + RawMessageSet raw = + RawMessageSet.newBuilder() + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(typeId1) + .setMessage( + TestMessageSetExtension1.newBuilder().setI(123).build().toByteString()) + .build()) + .build(); + + ByteString data = raw.toByteString(); + + // Parse as a TestMessageSet and check the contents. + TestMessageSet messageSet = TestMessageSet.parseFrom(data, extensionRegistry); + assertEquals(123, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()); + } + + public void testMergeLazyMessageSetExtensionEagerly() throws Exception { + testMergeLazyMessageSetExtensionWithFlag(true); + } + + public void testMergeLazyMessageSetExtensionNotEagerly() throws Exception { + testMergeLazyMessageSetExtensionWithFlag(false); + } + + private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing) throws Exception { + ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); + ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance(); + extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); + + // Set up a RawMessageSet with a known messages. + int typeId1 = 1545008; + RawMessageSet raw = + RawMessageSet.newBuilder() + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(typeId1) + .setMessage( + TestMessageSetExtension1.newBuilder().setI(123).build().toByteString()) + .build()) + .build(); + + ByteString data = raw.toByteString(); + + // Parse as a TestMessageSet and store value into lazy field + TestMessageSet messageSet = TestMessageSet.parseFrom(data, extensionRegistry); + // Merge lazy field check the contents. + messageSet = messageSet.toBuilder().mergeFrom(data, extensionRegistry).build(); + assertEquals(123, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()); + } + + public void testMergeMessageSetExtensionEagerly() throws Exception { + testMergeMessageSetExtensionWithFlag(true); + } + + public void testMergeMessageSetExtensionNotEagerly() throws Exception { + testMergeMessageSetExtensionWithFlag(false); + } + + private void testMergeMessageSetExtensionWithFlag(boolean eagerParsing) throws Exception { + ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); + ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance(); + extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); + + // Set up a RawMessageSet with a known messages. + int typeId1 = 1545008; + RawMessageSet raw = + RawMessageSet.newBuilder() + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(typeId1) + .setMessage( + TestMessageSetExtension1.newBuilder().setI(123).build().toByteString()) + .build()) + .build(); + + // Serialize RawMessageSet unnormally (message value before type id) + ByteString.CodedBuilder out = ByteString.newCodedBuilder(raw.getSerializedSize()); + CodedOutputStream output = out.getCodedOutput(); + List items = raw.getItemList(); + for (RawMessageSet.Item item : items) { + output.writeTag(1, WireFormat.WIRETYPE_START_GROUP); + output.writeBytes(3, item.getMessage()); + output.writeInt32(2, item.getTypeId()); + output.writeTag(1, WireFormat.WIRETYPE_END_GROUP); + } + ByteString data = out.build(); + + // Merge bytes into TestMessageSet and check the contents. + TestMessageSet messageSet = + TestMessageSet.newBuilder().mergeFrom(data, extensionRegistry).build(); + assertEquals(123, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()); + } + + // ================================================================ + // oneof + public void testOneofWireFormat() throws Exception { + TestOneof2.Builder builder = TestOneof2.newBuilder(); + TestUtil.setOneof(builder); + TestOneof2 message = builder.build(); + ByteString rawBytes = message.toByteString(); + + assertEquals(rawBytes.size(), message.getSerializedSize()); + + TestOneof2 message2 = TestOneof2.parseFrom(rawBytes); + TestUtil.assertOneofSet(message2); + } + + public void testOneofOnlyLastSet() throws Exception { + TestOneofBackwardsCompatible source = + TestOneofBackwardsCompatible.newBuilder().setFooInt(100).setFooString("101").build(); + + ByteString rawBytes = source.toByteString(); + TestOneof2 message = TestOneof2.parseFrom(rawBytes); + assertFalse(message.hasFooInt()); + assertTrue(message.hasFooString()); + } + + private void assertInvalidWireFormat( + MessageLite defaultInstance, byte[] data, int offset, int length) { + // Test all combinations: (builder vs parser) x (byte[] vs. InputStream). + try { + defaultInstance.newBuilderForType().mergeFrom(data, offset, length); + fail("Expected exception"); + } catch (InvalidProtocolBufferException e) { + // Pass. + } + try { + defaultInstance.getParserForType().parseFrom(data, offset, length); + fail("Expected exception"); + } catch (InvalidProtocolBufferException e) { + // Pass. + } + try { + InputStream input = new ByteArrayInputStream(data, offset, length); + defaultInstance.newBuilderForType().mergeFrom(input); + fail("Expected exception"); + } catch (IOException e) { + // Pass. + } + try { + InputStream input = new ByteArrayInputStream(data, offset, length); + defaultInstance.getParserForType().parseFrom(input); + fail("Expected exception"); + } catch (IOException e) { + // Pass. + } + } + + private void assertInvalidWireFormat(MessageLite defaultInstance, byte[] data) { + assertInvalidWireFormat(defaultInstance, data, 0, data.length); + } + + private void assertInvalidWireFormat(byte[] data) { + assertInvalidWireFormat(TestAllTypes.getDefaultInstance(), data); + assertInvalidWireFormat(UnittestProto3.TestAllTypes.getDefaultInstance(), data); + } + + public void testParserRejectInvalidTag() throws Exception { + byte[] invalidTags = + new byte[] { + // Zero tag is not allowed. + 0, + // Invalid wire types. + (byte) WireFormat.makeTag(1, 6), + (byte) WireFormat.makeTag(1, 7), + // Field number 0 is not allowed. + (byte) WireFormat.makeTag(0, WireFormat.WIRETYPE_VARINT), + }; + for (byte invalidTag : invalidTags) { + // Add a trailing 0 to make sure the parsing actually fails on the tag. + byte[] data = new byte[] {invalidTag, 0}; + assertInvalidWireFormat(data); + + // Invalid tag in an unknown group field. + data = + new byte[] { + (byte) WireFormat.makeTag(1, WireFormat.WIRETYPE_START_GROUP), + invalidTag, + 0, + (byte) WireFormat.makeTag(1, WireFormat.WIRETYPE_END_GROUP), + }; + assertInvalidWireFormat(data); + + // Invalid tag in a MessageSet item. + data = + new byte[] { + (byte) WireFormat.MESSAGE_SET_ITEM_TAG, + (byte) WireFormat.MESSAGE_SET_TYPE_ID_TAG, + 100, // TYPE_ID = 100 + (byte) WireFormat.MESSAGE_SET_MESSAGE_TAG, + 0, // empty payload + invalidTag, + 0, + (byte) WireFormat.MESSAGE_SET_ITEM_END_TAG, + }; + assertInvalidWireFormat(TestMessageSet.getDefaultInstance(), data); + + // Invalid tag inside a MessageSet item's unknown group. + data = + new byte[] { + (byte) WireFormat.MESSAGE_SET_ITEM_TAG, + (byte) WireFormat.MESSAGE_SET_TYPE_ID_TAG, + 100, // TYPE_ID = 100 + (byte) WireFormat.MESSAGE_SET_MESSAGE_TAG, + 0, // empty payload + (byte) WireFormat.makeTag(4, WireFormat.WIRETYPE_START_GROUP), + invalidTag, + 0, + (byte) WireFormat.makeTag(4, WireFormat.WIRETYPE_END_GROUP), + (byte) WireFormat.MESSAGE_SET_ITEM_END_TAG, + }; + assertInvalidWireFormat(TestMessageSet.getDefaultInstance(), data); + + // Invalid tag inside a map field. + data = + new byte[] { + (byte) WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED), 2, invalidTag, 0, + }; + assertInvalidWireFormat(TestMap.getDefaultInstance(), data); + } + } + + public void testUnmatchedGroupTag() throws Exception { + int startTag = WireFormat.makeTag(16, WireFormat.WIRETYPE_START_GROUP); + byte[] data = + new byte[] { + (byte) ((startTag & 0x7F) | 0x80), (byte) ((startTag >>> 7) & 0x7F), + }; + assertInvalidWireFormat(data); + + // Unmatched group tags inside a MessageSet item. + data = + new byte[] { + (byte) WireFormat.MESSAGE_SET_ITEM_TAG, + (byte) WireFormat.MESSAGE_SET_TYPE_ID_TAG, + 100, // TYPE_ID = 100 + (byte) WireFormat.MESSAGE_SET_MESSAGE_TAG, + 0, // empty payload + (byte) WireFormat.makeTag(4, WireFormat.WIRETYPE_START_GROUP), + }; + assertInvalidWireFormat(TestMessageSet.getDefaultInstance(), data); + } + + private void assertAccepted(MessageLite defaultInstance, byte[] data) throws Exception { + MessageLite message1 = defaultInstance.newBuilderForType().mergeFrom(data).build(); + MessageLite message2 = defaultInstance.getParserForType().parseFrom(data); + MessageLite message3 = + defaultInstance.newBuilderForType().mergeFrom(new ByteArrayInputStream(data)).build(); + MessageLite message4 = + defaultInstance.getParserForType().parseFrom(new ByteArrayInputStream(data)); + assertEquals(message1, message2); + assertEquals(message2, message3); + assertEquals(message3, message4); + } + + public void testUnmatchedWireType() throws Exception { + // Build a payload with all fields from 1 to 128 being varints. Parsing it into TestAllTypes + // or other message types should succeed even though the wire type doesn't match for some + // fields. + ByteArrayOutputStream output = new ByteArrayOutputStream(); + CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); + for (int i = 1; i <= 128; i++) { + codedOutput.writeInt32(i, 0); + } + codedOutput.flush(); + byte[] data = output.toByteArray(); + // It can be parsed into any message type that doesn't have required fields. + assertAccepted(TestAllTypes.getDefaultInstance(), data); + assertAccepted(UnittestProto3.TestAllTypes.getDefaultInstance(), data); + assertAccepted(TestMap.getDefaultInstance(), data); + assertAccepted(MapForProto2TestProto.TestMap.getDefaultInstance(), data); + } + + public void testParseTruncatedPackedFields() throws Exception { + TestPackedTypes all = TestUtil.getPackedSet(); + TestPackedTypes[] messages = + new TestPackedTypes[] { + TestPackedTypes.newBuilder().addAllPackedInt32(all.getPackedInt32List()).build(), + TestPackedTypes.newBuilder().addAllPackedInt64(all.getPackedInt64List()).build(), + TestPackedTypes.newBuilder().addAllPackedUint32(all.getPackedUint32List()).build(), + TestPackedTypes.newBuilder().addAllPackedUint64(all.getPackedUint64List()).build(), + TestPackedTypes.newBuilder().addAllPackedSint32(all.getPackedSint32List()).build(), + TestPackedTypes.newBuilder().addAllPackedSint64(all.getPackedSint64List()).build(), + TestPackedTypes.newBuilder().addAllPackedFixed32(all.getPackedFixed32List()).build(), + TestPackedTypes.newBuilder().addAllPackedFixed64(all.getPackedFixed64List()).build(), + TestPackedTypes.newBuilder().addAllPackedSfixed32(all.getPackedSfixed32List()).build(), + TestPackedTypes.newBuilder().addAllPackedSfixed64(all.getPackedSfixed64List()).build(), + TestPackedTypes.newBuilder().addAllPackedFloat(all.getPackedFloatList()).build(), + TestPackedTypes.newBuilder().addAllPackedDouble(all.getPackedDoubleList()).build(), + TestPackedTypes.newBuilder().addAllPackedEnum(all.getPackedEnumList()).build(), + }; + for (TestPackedTypes message : messages) { + byte[] data = message.toByteArray(); + // Parsing truncated payload should fail. + for (int i = 1; i < data.length; i++) { + assertInvalidWireFormat(TestPackedTypes.getDefaultInstance(), data, 0, i); + } + } + } + + public void testParsePackedFieldsWithIncorrectLength() throws Exception { + // Set the length-prefix to 1 with a 4-bytes payload to test what happens when reading a packed + // element moves the reading position past the given length limit. It should result in an + // InvalidProtocolBufferException but an implementation may forget to check it especially for + // packed varint fields. + byte[] data = + new byte[] { + 0, + 0, // first two bytes is reserved for the tag. + 1, // length is 1 + (byte) 0x80, + (byte) 0x80, + (byte) 0x80, + (byte) 0x01, // a 4-bytes varint + }; + // All fields that can read a 4-bytes varint (all varint fields and fixed 32-bit fields). + int[] fieldNumbers = + new int[] { + TestPackedTypes.PACKED_INT32_FIELD_NUMBER, + TestPackedTypes.PACKED_INT64_FIELD_NUMBER, + TestPackedTypes.PACKED_UINT32_FIELD_NUMBER, + TestPackedTypes.PACKED_UINT64_FIELD_NUMBER, + TestPackedTypes.PACKED_SINT32_FIELD_NUMBER, + TestPackedTypes.PACKED_SINT64_FIELD_NUMBER, + TestPackedTypes.PACKED_FIXED32_FIELD_NUMBER, + TestPackedTypes.PACKED_SFIXED32_FIELD_NUMBER, + TestPackedTypes.PACKED_FLOAT_FIELD_NUMBER, + TestPackedTypes.PACKED_BOOL_FIELD_NUMBER, + TestPackedTypes.PACKED_ENUM_FIELD_NUMBER, + }; + for (int number : fieldNumbers) { + // Set the tag. + data[0] = + (byte) ((WireFormat.makeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED) & 0x7F) | 0x80); + data[1] = + (byte) ((WireFormat.makeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED) >>> 7) & 0x7F); + assertInvalidWireFormat(TestPackedTypes.getDefaultInstance(), data); + } + + // Data with 8-bytes payload to test some fixed 64-bit fields. + byte[] data8Bytes = + new byte[] { + 0, + 0, // first two bytes is reserved for the tag. + 1, // length is 1 + (byte) 0x80, + (byte) 0x80, + (byte) 0x80, + (byte) 0x80, + (byte) 0x80, + (byte) 0x80, + (byte) 0x80, + (byte) 0x01, // a 8-bytes varint + }; + // All fields that can only read 8-bytes data. + int[] fieldNumbers8Bytes = + new int[] { + TestPackedTypes.PACKED_FIXED64_FIELD_NUMBER, + TestPackedTypes.PACKED_SFIXED64_FIELD_NUMBER, + TestPackedTypes.PACKED_DOUBLE_FIELD_NUMBER, + }; + for (int number : fieldNumbers8Bytes) { + // Set the tag. + data8Bytes[0] = + (byte) ((WireFormat.makeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED) & 0x7F) | 0x80); + data8Bytes[1] = + (byte) ((WireFormat.makeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED) >>> 7) & 0x7F); + assertInvalidWireFormat(TestPackedTypes.getDefaultInstance(), data8Bytes); + } + } + + public void testParseVarintMinMax() throws Exception { + TestAllTypes message = + TestAllTypes.newBuilder() + .setOptionalInt32(Integer.MIN_VALUE) + .addRepeatedInt32(Integer.MAX_VALUE) + .setOptionalInt64(Long.MIN_VALUE) + .addRepeatedInt64(Long.MAX_VALUE) + .build(); + TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); + assertEquals(Integer.MIN_VALUE, parsed.getOptionalInt32()); + assertEquals(Integer.MAX_VALUE, parsed.getRepeatedInt32(0)); + assertEquals(Long.MIN_VALUE, parsed.getOptionalInt64()); + assertEquals(Long.MAX_VALUE, parsed.getRepeatedInt64(0)); + } + + public void testParseAllVarintBits() throws Exception { + for (int i = 0; i < 32; i++) { + final int value = 1 << i; + TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(value).build(); + TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); + assertEquals(value, parsed.getOptionalInt32()); + } + for (int i = 0; i < 64; i++) { + final long value = 1L << i; + TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt64(value).build(); + TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); + assertEquals(value, parsed.getOptionalInt64()); + } + } + + public void testParseEmptyUnknownLengthDelimitedField() throws Exception { + byte[] data = + new byte[] {(byte) WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED), 0}; + TestAllTypes parsed = TestAllTypes.parseFrom(data); + assertTrue(Arrays.equals(data, parsed.toByteArray())); + } + + public void testParseEmptyString() throws Exception { + TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("").build(); + TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); + assertEquals("", parsed.getOptionalString()); + } + + public void testParseEmptyStringProto3() throws Exception { + TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("").build(); + // Note that we are parsing from a proto2 proto to a proto3 proto because empty string field is + // not serialized in proto3. + UnittestProto3.TestAllTypes parsed = + UnittestProto3.TestAllTypes.parseFrom(message.toByteArray()); + assertEquals("", parsed.getOptionalString()); + } + + public void testParseEmptyBytes() throws Exception { + TestAllTypes message = TestAllTypes.newBuilder().setOptionalBytes(ByteString.EMPTY).build(); + TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); + assertEquals(ByteString.EMPTY, parsed.getOptionalBytes()); + } + + public void testParseEmptyRepeatedStringField() throws Exception { + TestAllTypes message = + TestAllTypes.newBuilder() + .addRepeatedString("") + .addRepeatedString("") + .addRepeatedString("0") + .build(); + TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); + assertEquals(3, parsed.getRepeatedStringCount()); + assertEquals("", parsed.getRepeatedString(0)); + assertEquals("", parsed.getRepeatedString(1)); + assertEquals("0", parsed.getRepeatedString(2)); + } + + public void testParseEmptyRepeatedStringFieldProto3() throws Exception { + TestAllTypes message = + TestAllTypes.newBuilder() + .addRepeatedString("") + .addRepeatedString("") + .addRepeatedString("0") + .addRepeatedBytes(ByteString.EMPTY) + .build(); + UnittestProto3.TestAllTypes parsed = + UnittestProto3.TestAllTypes.parseFrom(message.toByteArray()); + assertEquals(3, parsed.getRepeatedStringCount()); + assertEquals("", parsed.getRepeatedString(0)); + assertEquals("", parsed.getRepeatedString(1)); + assertEquals("0", parsed.getRepeatedString(2)); + } + + public void testParseEmptyRepeatedBytesField() throws Exception { + ByteString oneByte = ByteString.copyFrom(new byte[] {1}); + TestAllTypes message = + TestAllTypes.newBuilder() + .addRepeatedBytes(ByteString.EMPTY) + .addRepeatedBytes(ByteString.EMPTY) + .addRepeatedBytes(oneByte) + .build(); + TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); + assertEquals(3, parsed.getRepeatedBytesCount()); + assertEquals(ByteString.EMPTY, parsed.getRepeatedBytes(0)); + assertEquals(ByteString.EMPTY, parsed.getRepeatedBytes(1)); + assertEquals(oneByte, parsed.getRepeatedBytes(2)); + } + + public void testSkipUnknownFieldInMessageSetItem() throws Exception { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + // MessageSet item's start tag. + output.write((byte) WireFormat.MESSAGE_SET_ITEM_TAG); + // Put all field types into the item. + TestUtil.getAllSet().writeTo(output); + // Closing the item with the real payload and closing tag. + output.write( + new byte[] { + (byte) WireFormat.MESSAGE_SET_TYPE_ID_TAG, + 100, // TYPE_ID = 100 + (byte) WireFormat.MESSAGE_SET_MESSAGE_TAG, + 0, // empty payload + (byte) WireFormat.MESSAGE_SET_ITEM_END_TAG, + }); + byte[] data = output.toByteArray(); + TestMessageSet parsed = TestMessageSet.parseFrom(data); + + // Convert to RawMessageSet for inspection. + RawMessageSet raw = RawMessageSet.parseFrom(parsed.toByteArray()); + assertEquals(1, raw.getItemCount()); + assertEquals(100, raw.getItem(0).getTypeId()); + assertEquals(0, raw.getItem(0).getMessage().size()); + } + + public void testProto2UnknownEnumValuesInOptionalField() throws Exception { + // Proto2 doesn't allow setting unknown enum values so we use proto3 to build a message with + // unknown enum values + UnittestProto3.TestAllTypes message = + UnittestProto3.TestAllTypes.newBuilder().setOptionalNestedEnumValue(4321).build(); + TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); + assertFalse(parsed.hasOptionalNestedEnum()); + // Make sure unknown enum values are preserved. + UnittestProto3.TestAllTypes actual = + UnittestProto3.TestAllTypes.parseFrom(parsed.toByteArray()); + assertEquals(4321, actual.getOptionalNestedEnumValue()); + } + + public void testProto2UnknownEnumValuesInRepeatedField() throws Exception { + // Proto2 doesn't allow setting unknown enum values so we use proto3 to build a message with + // unknown enum values + UnittestProto3.TestAllTypes message = + UnittestProto3.TestAllTypes.newBuilder().addRepeatedNestedEnumValue(5432).build(); + TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); + assertEquals(0, parsed.getRepeatedNestedEnumCount()); + // Make sure unknown enum values are preserved. + UnittestProto3.TestAllTypes actual = + UnittestProto3.TestAllTypes.parseFrom(parsed.toByteArray()); + assertEquals(1, actual.getRepeatedNestedEnumCount()); + assertEquals(5432, actual.getRepeatedNestedEnumValue(0)); + } + + public void testProto2UnknownEnumValuesInMapField() throws Exception { + // Proto2 doesn't allow setting unknown enum values so we use proto3 to build a message with + // unknown enum values + TestMap message = TestMap.newBuilder().putInt32ToEnumFieldValue(1, 4321).build(); + MapForProto2TestProto.TestMap parsed = + MapForProto2TestProto.TestMap.parseFrom(message.toByteArray()); + assertEquals(0, parsed.getInt32ToEnumFieldMap().size()); + // Make sure unknown enum values are preserved. + TestMap actual = TestMap.parseFrom(parsed.toByteArray()); + assertEquals(1, actual.getInt32ToEnumFieldMap().size()); + assertEquals(4321, actual.getInt32ToEnumFieldValueOrThrow(1)); + } + + public void testProto2UnknownEnumValuesInOneof() throws Exception { + // Proto2 doesn't allow setting unknown enum values so we use proto3 to build a message with + // unknown enum values + UnittestProto3.TestOneof2 message = + UnittestProto3.TestOneof2.newBuilder().setFooEnumValue(1234).build(); + TestOneof2 parsed = TestOneof2.parseFrom(message.toByteArray()); + assertFalse(parsed.hasFooEnum()); + // Make sure unknown enum values are preserved. + UnittestProto3.TestOneof2 actual = UnittestProto3.TestOneof2.parseFrom(parsed.toByteArray()); + assertEquals(1234, actual.getFooEnumValue()); + } + + public void testProto2UnknownEnumValuesInExtension() throws Exception { + ExtensionRegistryLite extensionRegistry = TestUtilLite.getExtensionRegistryLite(); + // Raw bytes for "[.optional_foreign_enum_extension_lite]: 10" + final byte[] rawBytes = new byte[]{-80, 1, 10}; + TestAllExtensionsLite testAllExtensionsLite = + TestAllExtensionsLite.parseFrom(rawBytes, extensionRegistry); + assertEquals(ForeignEnumLite.FOREIGN_LITE_FOO, + testAllExtensionsLite.getExtension(optionalForeignEnumExtensionLite)); + final byte[] resultRawBytes = testAllExtensionsLite.toByteArray(); + assertEquals(rawBytes.length, resultRawBytes.length); + for (int i = 0; i < rawBytes.length; i++) { + assertEquals(rawBytes[i], resultRawBytes[i]); + } + } + + public void testProto3UnknownEnumValuesInOptionalField() throws Exception { + UnittestProto3.TestAllTypes message = + UnittestProto3.TestAllTypes.newBuilder().setOptionalNestedEnumValue(4321).build(); + UnittestProto3.TestAllTypes parsed = + UnittestProto3.TestAllTypes.parseFrom(message.toByteArray()); + assertEquals(4321, parsed.getOptionalNestedEnumValue()); + } + + public void testProto3UnknownEnumValuesInRepeatedField() throws Exception { + UnittestProto3.TestAllTypes message = + UnittestProto3.TestAllTypes.newBuilder().addRepeatedNestedEnumValue(5432).build(); + UnittestProto3.TestAllTypes parsed = + UnittestProto3.TestAllTypes.parseFrom(message.toByteArray()); + assertEquals(1, parsed.getRepeatedNestedEnumCount()); + assertEquals(5432, parsed.getRepeatedNestedEnumValue(0)); + } + + public void testProto3UnknownEnumValuesInMapField() throws Exception { + TestMap message = TestMap.newBuilder().putInt32ToEnumFieldValue(1, 4321).build(); + TestMap parsed = TestMap.parseFrom(message.toByteArray()); + assertEquals(1, parsed.getInt32ToEnumFieldMap().size()); + assertEquals(4321, parsed.getInt32ToEnumFieldValueOrThrow(1)); + } + + public void testProto3UnknownEnumValuesInOneof() throws Exception { + UnittestProto3.TestOneof2 message = + UnittestProto3.TestOneof2.newBuilder().setFooEnumValue(1234).build(); + UnittestProto3.TestOneof2 parsed = UnittestProto3.TestOneof2.parseFrom(message.toByteArray()); + assertEquals(1234, parsed.getFooEnumValue()); + } + + public void testProto3MessageFieldMergeBehavior() throws Exception { + UnittestProto3.NestedTestAllTypes message1 = + UnittestProto3.NestedTestAllTypes.newBuilder() + .setPayload( + UnittestProto3.TestAllTypes.newBuilder() + .setOptionalInt32(1234) + .setOptionalInt64(5678)) + .build(); + UnittestProto3.NestedTestAllTypes message2 = + UnittestProto3.NestedTestAllTypes.newBuilder() + .setPayload( + UnittestProto3.TestAllTypes.newBuilder() + .setOptionalInt32(4321) + .setOptionalUint32(8765)) + .build(); + + UnittestProto3.NestedTestAllTypes merged = + UnittestProto3.NestedTestAllTypes.newBuilder() + .mergeFrom(message1.toByteArray()) + .mergeFrom(message2.toByteArray()) + .build(); + // Field values coming later in the stream override earlier values. + assertEquals(4321, merged.getPayload().getOptionalInt32()); + // Field values present in either message should be present in the merged result. + assertEquals(5678, merged.getPayload().getOptionalInt64()); + assertEquals(8765, merged.getPayload().getOptionalUint32()); + } + + public void testMergeFromPartialByteArray() throws Exception { + byte[] data = TestUtil.getAllSet().toByteArray(); + byte[] dataWithPaddings = new byte[data.length + 2]; + System.arraycopy(data, 0, dataWithPaddings, 1, data.length); + // Parsing will fail if the builder (or parser) interprets offset or length incorrectly. + TestAllTypes.newBuilder().mergeFrom(dataWithPaddings, 1, data.length); + TestAllTypes.parser().parseFrom(dataWithPaddings, 1, data.length); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/WireFormatTest.java b/java/core/src/test/java/com/google/protobuf/WireFormatTest.java index 370860c2f8aa8..45a396acd8e77 100644 --- a/java/core/src/test/java/com/google/protobuf/WireFormatTest.java +++ b/java/core/src/test/java/com/google/protobuf/WireFormatTest.java @@ -30,14 +30,13 @@ package com.google.protobuf; -import com.google.protobuf.UnittestLite.TestAllExtensionsLite; -import com.google.protobuf.UnittestLite.TestPackedExtensionsLite; import protobuf_unittest.UnittestMset.RawMessageSet; import protobuf_unittest.UnittestMset.TestMessageSetExtension1; import protobuf_unittest.UnittestMset.TestMessageSetExtension2; import protobuf_unittest.UnittestProto; import protobuf_unittest.UnittestProto.TestAllExtensions; import protobuf_unittest.UnittestProto.TestAllTypes; +import protobuf_unittest.UnittestProto.TestExtensionInsideTable; import protobuf_unittest.UnittestProto.TestFieldOrderings; import protobuf_unittest.UnittestProto.TestOneof2; import protobuf_unittest.UnittestProto.TestOneofBackwardsCompatible; @@ -55,6 +54,13 @@ * @author kenton@google.com (Kenton Varda) */ public class WireFormatTest extends TestCase { + + private static final int TYPE_ID_1 = + TestMessageSetExtension1.getDescriptor().getExtensions().get(0).getNumber(); + private static final int TYPE_ID_2 = + TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber(); + private static final int UNKNOWN_TYPE_ID = 1550055; + public void testSerialization() throws Exception { TestAllTypes message = TestUtil.getAllSet(); @@ -103,8 +109,7 @@ public void testSerializePackedExtensions() throws Exception { assertEquals(rawBytes, rawBytes2); } - public void testSerializationPackedWithoutGetSerializedSize() - throws Exception { + public void testSerializationPackedWithoutGetSerializedSize() throws Exception { // Write directly to an OutputStream, without invoking getSerializedSize() // This used to be a bug where the size of a packed field was incorrect, // since getSerializedSize() was never invoked. @@ -119,38 +124,11 @@ public void testSerializationPackedWithoutGetSerializedSize() codedOutput.flush(); - TestPackedTypes message2 = TestPackedTypes.parseFrom( - outputStream.toByteArray()); + TestPackedTypes message2 = TestPackedTypes.parseFrom(outputStream.toByteArray()); TestUtil.assertPackedFieldsSet(message2); } - public void testSerializeExtensionsLite() throws Exception { - // TestAllTypes and TestAllExtensions should have compatible wire formats, - // so if we serialize a TestAllExtensions then parse it as TestAllTypes - // it should work. - - TestAllExtensionsLite message = TestUtilLite.getAllLiteExtensionsSet(); - ByteString rawBytes = message.toByteString(); - assertEquals(rawBytes.size(), message.getSerializedSize()); - - TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes); - - TestUtil.assertAllFieldsSet(message2); - } - - public void testSerializePackedExtensionsLite() throws Exception { - // TestPackedTypes and TestPackedExtensions should have compatible wire - // formats; check that they serialize to the same string. - TestPackedExtensionsLite message = TestUtilLite.getLitePackedExtensionsSet(); - ByteString rawBytes = message.toByteString(); - - TestPackedTypes message2 = TestUtil.getPackedSet(); - ByteString rawBytes2 = message2.toByteString(); - - assertEquals(rawBytes, rawBytes2); - } - public void testParseExtensions() throws Exception { // TestAllTypes and TestAllExtensions should have compatible wire formats, // so if we serialize a TestAllTypes then parse it as TestAllExtensions @@ -159,10 +137,9 @@ public void testParseExtensions() throws Exception { TestAllTypes message = TestUtil.getAllSet(); ByteString rawBytes = message.toByteString(); - ExtensionRegistry registry = TestUtil.getExtensionRegistry(); + ExtensionRegistryLite registry = TestUtil.getExtensionRegistry(); - TestAllExtensions message2 = - TestAllExtensions.parseFrom(rawBytes, registry); + TestAllExtensions message2 = TestAllExtensions.parseFrom(rawBytes, registry); TestUtil.assertAllExtensionsSet(message2); } @@ -172,56 +149,13 @@ public void testParsePackedExtensions() throws Exception { TestPackedExtensions message = TestUtil.getPackedExtensionsSet(); ByteString rawBytes = message.toByteString(); - ExtensionRegistry registry = TestUtil.getExtensionRegistry(); - - TestPackedExtensions message2 = - TestPackedExtensions.parseFrom(rawBytes, registry); - - TestUtil.assertPackedExtensionsSet(message2); - } - - public void testParseExtensionsLite() throws Exception { - // TestAllTypes and TestAllExtensions should have compatible wire formats, - // so if we serialize a TestAllTypes then parse it as TestAllExtensions - // it should work. - - TestAllTypes message = TestUtil.getAllSet(); - ByteString rawBytes = message.toByteString(); - - ExtensionRegistryLite registry_lite = TestUtilLite.getExtensionRegistryLite(); - - TestAllExtensionsLite message2 = - TestAllExtensionsLite.parseFrom(rawBytes, registry_lite); - - TestUtil.assertAllExtensionsSet(message2); - - // Try again using a full extension registry. - ExtensionRegistry registry = TestUtil.getExtensionRegistry(); - - TestAllExtensionsLite message3 = - TestAllExtensionsLite.parseFrom(rawBytes, registry); - - TestUtil.assertAllExtensionsSet(message3); - } - - public void testParsePackedExtensionsLite() throws Exception { - // Ensure that packed extensions can be properly parsed. - TestPackedExtensionsLite message = TestUtilLite.getLitePackedExtensionsSet(); - ByteString rawBytes = message.toByteString(); - - ExtensionRegistryLite registry = TestUtilLite.getExtensionRegistryLite(); + ExtensionRegistryLite registry = TestUtil.getExtensionRegistry(); - TestPackedExtensionsLite message2 = - TestPackedExtensionsLite.parseFrom(rawBytes, registry); + TestPackedExtensions message2 = TestPackedExtensions.parseFrom(rawBytes, registry); TestUtil.assertPackedExtensionsSet(message2); } - public void testExtensionsSerializedSize() throws Exception { - assertNotSame(TestUtil.getAllSet().getSerializedSize(), - TestUtil.getAllExtensionsSet().getSerializedSize()); - } - public void testSerializeDelimited() throws Exception { ByteArrayOutputStream output = new ByteArrayOutputStream(); TestUtil.getAllSet().writeDelimitedTo(output); @@ -261,25 +195,27 @@ public void testInterleavedFieldsAndExtensions() throws Exception { // Tests that fields are written in order even when extension ranges // are interleaved with field numbers. ByteString data = - TestFieldOrderings.newBuilder() - .setMyInt(1) - .setMyString("foo") - .setMyFloat(1.0F) - .setExtension(UnittestProto.myExtensionInt, 23) - .setExtension(UnittestProto.myExtensionString, "bar") - .build().toByteString(); + TestFieldOrderings.newBuilder() + .setMyInt(1) + .setMyString("foo") + .setMyFloat(1.0F) + .setExtension(UnittestProto.myExtensionInt, 23) + .setExtension(UnittestProto.myExtensionString, "bar") + .build() + .toByteString(); assertFieldsInOrder(data); Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor(); - ByteString dynamic_data = - DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor()) - .setField(descriptor.findFieldByName("my_int"), 1L) - .setField(descriptor.findFieldByName("my_string"), "foo") - .setField(descriptor.findFieldByName("my_float"), 1.0F) - .setField(UnittestProto.myExtensionInt.getDescriptor(), 23) - .setField(UnittestProto.myExtensionString.getDescriptor(), "bar") - .build().toByteString(); - assertFieldsInOrder(dynamic_data); + ByteString dynamicData = + DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor()) + .setField(descriptor.findFieldByName("my_int"), 1L) + .setField(descriptor.findFieldByName("my_string"), "foo") + .setField(descriptor.findFieldByName("my_float"), 1.0F) + .setField(UnittestProto.myExtensionInt.getDescriptor(), 23) + .setField(UnittestProto.myExtensionString.getDescriptor(), "bar") + .build() + .toByteString(); + assertFieldsInOrder(dynamicData); } private ExtensionRegistry getTestFieldOrderingsRegistry() { @@ -293,16 +229,35 @@ public void testParseMultipleExtensionRanges() throws Exception { // Make sure we can parse a message that contains multiple extensions // ranges. TestFieldOrderings source = - TestFieldOrderings.newBuilder() - .setMyInt(1) - .setMyString("foo") - .setMyFloat(1.0F) - .setExtension(UnittestProto.myExtensionInt, 23) - .setExtension(UnittestProto.myExtensionString, "bar") - .build(); + TestFieldOrderings.newBuilder() + .setMyInt(1) + .setMyString("foo") + .setMyFloat(1.0F) + .setExtension(UnittestProto.myExtensionInt, 23) + .setExtension(UnittestProto.myExtensionString, "bar") + .build(); TestFieldOrderings dest = - TestFieldOrderings.parseFrom(source.toByteString(), - getTestFieldOrderingsRegistry()); + TestFieldOrderings.parseFrom(source.toByteString(), getTestFieldOrderingsRegistry()); + assertEquals(source, dest); + } + + private static ExtensionRegistry getTestExtensionInsideTableRegistry() { + ExtensionRegistry result = ExtensionRegistry.newInstance(); + result.add(UnittestProto.testExtensionInsideTableExtension); + return result; + } + + public void testExtensionInsideTable() throws Exception { + // Make sure the extension within the range of table is parsed correctly in experimental + // runtime. + TestExtensionInsideTable source = + TestExtensionInsideTable.newBuilder() + .setField1(1) + .setExtension(UnittestProto.testExtensionInsideTableExtension, 23) + .build(); + TestExtensionInsideTable dest = + TestExtensionInsideTable.parseFrom( + source.toByteString(), getTestExtensionInsideTableRegistry()); assertEquals(source, dest); } @@ -310,25 +265,19 @@ public void testParseMultipleExtensionRangesDynamic() throws Exception { // Same as above except with DynamicMessage. Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor(); DynamicMessage source = - DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor()) - .setField(descriptor.findFieldByName("my_int"), 1L) - .setField(descriptor.findFieldByName("my_string"), "foo") - .setField(descriptor.findFieldByName("my_float"), 1.0F) - .setField(UnittestProto.myExtensionInt.getDescriptor(), 23) - .setField(UnittestProto.myExtensionString.getDescriptor(), "bar") - .build(); + DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor()) + .setField(descriptor.findFieldByName("my_int"), 1L) + .setField(descriptor.findFieldByName("my_string"), "foo") + .setField(descriptor.findFieldByName("my_float"), 1.0F) + .setField(UnittestProto.myExtensionInt.getDescriptor(), 23) + .setField(UnittestProto.myExtensionString.getDescriptor(), "bar") + .build(); DynamicMessage dest = - DynamicMessage.parseFrom(descriptor, source.toByteString(), - getTestFieldOrderingsRegistry()); + DynamicMessage.parseFrom( + descriptor, source.toByteString(), getTestFieldOrderingsRegistry()); assertEquals(source, dest); } - private static final int UNKNOWN_TYPE_ID = 1550055; - private static final int TYPE_ID_1 = - TestMessageSetExtension1.getDescriptor().getExtensions().get(0).getNumber(); - private static final int TYPE_ID_2 = - TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber(); - public void testSerializeMessageSetEagerly() throws Exception { testSerializeMessageSetWithFlag(true); } @@ -337,26 +286,26 @@ public void testSerializeMessageSetNotEagerly() throws Exception { testSerializeMessageSetWithFlag(false); } - private void testSerializeMessageSetWithFlag(boolean eagerParsing) - throws Exception { + private void testSerializeMessageSetWithFlag(boolean eagerParsing) throws Exception { ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); // Set up a TestMessageSet with two known messages and an unknown one. TestMessageSet messageSet = - TestMessageSet.newBuilder() - .setExtension( - TestMessageSetExtension1.messageSetExtension, - TestMessageSetExtension1.newBuilder().setI(123).build()) - .setExtension( - TestMessageSetExtension2.messageSetExtension, - TestMessageSetExtension2.newBuilder().setStr("foo").build()) - .setUnknownFields( - UnknownFieldSet.newBuilder() - .addField(UNKNOWN_TYPE_ID, - UnknownFieldSet.Field.newBuilder() - .addLengthDelimited(ByteString.copyFromUtf8("bar")) - .build()) - .build()) - .build(); + TestMessageSet.newBuilder() + .setExtension( + TestMessageSetExtension1.messageSetExtension, + TestMessageSetExtension1.newBuilder().setI(123).build()) + .setExtension( + TestMessageSetExtension2.messageSetExtension, + TestMessageSetExtension2.newBuilder().setStr("foo").build()) + .setUnknownFields( + UnknownFieldSet.newBuilder() + .addField( + UNKNOWN_TYPE_ID, + UnknownFieldSet.Field.newBuilder() + .addLengthDelimited(ByteString.copyFromUtf8("bar")) + .build()) + .build()) + .build(); ByteString data = messageSet.toByteString(); @@ -371,13 +320,11 @@ private void testSerializeMessageSetWithFlag(boolean eagerParsing) assertEquals(UNKNOWN_TYPE_ID, raw.getItem(2).getTypeId()); TestMessageSetExtension1 message1 = - TestMessageSetExtension1.parseFrom( - raw.getItem(0).getMessage().toByteArray()); + TestMessageSetExtension1.parseFrom(raw.getItem(0).getMessage()); assertEquals(123, message1.getI()); TestMessageSetExtension2 message2 = - TestMessageSetExtension2.parseFrom( - raw.getItem(1).getMessage().toByteArray()); + TestMessageSetExtension2.parseFrom(raw.getItem(1).getMessage()); assertEquals("foo", message2.getStr()); assertEquals("bar", raw.getItem(2).getMessage().toStringUtf8()); @@ -387,12 +334,11 @@ public void testParseMessageSetEagerly() throws Exception { testParseMessageSetWithFlag(true); } - public void testParseMessageSetNotEagerly()throws Exception { + public void testParseMessageSetNotEagerly() throws Exception { testParseMessageSetWithFlag(false); } - private void testParseMessageSetWithFlag(boolean eagerParsing) - throws Exception { + private void testParseMessageSetWithFlag(boolean eagerParsing) throws Exception { ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); @@ -400,40 +346,34 @@ private void testParseMessageSetWithFlag(boolean eagerParsing) // Set up a RawMessageSet with two known messages and an unknown one. RawMessageSet raw = - RawMessageSet.newBuilder() - .addItem( - RawMessageSet.Item.newBuilder() - .setTypeId(TYPE_ID_1) - .setMessage( - TestMessageSetExtension1.newBuilder() - .setI(123) - .build().toByteString()) - .build()) - .addItem( - RawMessageSet.Item.newBuilder() - .setTypeId(TYPE_ID_2) - .setMessage( - TestMessageSetExtension2.newBuilder() - .setStr("foo") - .build().toByteString()) - .build()) - .addItem( - RawMessageSet.Item.newBuilder() - .setTypeId(UNKNOWN_TYPE_ID) - .setMessage(ByteString.copyFromUtf8("bar")) - .build()) - .build(); + RawMessageSet.newBuilder() + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(TYPE_ID_1) + .setMessage( + TestMessageSetExtension1.newBuilder().setI(123).build().toByteString()) + .build()) + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(TYPE_ID_2) + .setMessage( + TestMessageSetExtension2.newBuilder().setStr("foo").build().toByteString()) + .build()) + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(UNKNOWN_TYPE_ID) + .setMessage(ByteString.copyFromUtf8("bar")) + .build()) + .build(); ByteString data = raw.toByteString(); // Parse as a TestMessageSet and check the contents. - TestMessageSet messageSet = - TestMessageSet.parseFrom(data, extensionRegistry); + TestMessageSet messageSet = TestMessageSet.parseFrom(data, extensionRegistry); - assertEquals(123, messageSet.getExtension( - TestMessageSetExtension1.messageSetExtension).getI()); - assertEquals("foo", messageSet.getExtension( - TestMessageSetExtension2.messageSetExtension).getStr()); + assertEquals(123, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()); + assertEquals( + "foo", messageSet.getExtension(TestMessageSetExtension2.messageSetExtension).getStr()); // Check for unknown field with type LENGTH_DELIMITED, // number UNKNOWN_TYPE_ID, and contents "bar". @@ -454,35 +394,27 @@ public void testParseMessageSetExtensionNotEagerly() throws Exception { testParseMessageSetExtensionWithFlag(false); } - private void testParseMessageSetExtensionWithFlag(boolean eagerParsing) - throws Exception { + private void testParseMessageSetExtensionWithFlag(boolean eagerParsing) throws Exception { ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); // Set up a RawMessageSet with a known messages. - int TYPE_ID_1 = - TestMessageSetExtension1 - .getDescriptor().getExtensions().get(0).getNumber(); RawMessageSet raw = - RawMessageSet.newBuilder() - .addItem( - RawMessageSet.Item.newBuilder() - .setTypeId(TYPE_ID_1) - .setMessage( - TestMessageSetExtension1.newBuilder() - .setI(123) - .build().toByteString()) - .build()) - .build(); + RawMessageSet.newBuilder() + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(TYPE_ID_1) + .setMessage( + TestMessageSetExtension1.newBuilder().setI(123).build().toByteString()) + .build()) + .build(); ByteString data = raw.toByteString(); // Parse as a TestMessageSet and check the contents. - TestMessageSet messageSet = - TestMessageSet.parseFrom(data, extensionRegistry); - assertEquals(123, messageSet.getExtension( - TestMessageSetExtension1.messageSetExtension).getI()); + TestMessageSet messageSet = TestMessageSet.parseFrom(data, extensionRegistry); + assertEquals(123, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()); } public void testMergeLazyMessageSetExtensionEagerly() throws Exception { @@ -493,38 +425,29 @@ public void testMergeLazyMessageSetExtensionNotEagerly() throws Exception { testMergeLazyMessageSetExtensionWithFlag(false); } - private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing) - throws Exception { + private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing) throws Exception { ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); // Set up a RawMessageSet with a known messages. - int TYPE_ID_1 = - TestMessageSetExtension1 - .getDescriptor().getExtensions().get(0).getNumber(); RawMessageSet raw = - RawMessageSet.newBuilder() - .addItem( - RawMessageSet.Item.newBuilder() - .setTypeId(TYPE_ID_1) - .setMessage( - TestMessageSetExtension1.newBuilder() - .setI(123) - .build().toByteString()) - .build()) - .build(); + RawMessageSet.newBuilder() + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(TYPE_ID_1) + .setMessage( + TestMessageSetExtension1.newBuilder().setI(123).build().toByteString()) + .build()) + .build(); ByteString data = raw.toByteString(); // Parse as a TestMessageSet and store value into lazy field - TestMessageSet messageSet = - TestMessageSet.parseFrom(data, extensionRegistry); + TestMessageSet messageSet = TestMessageSet.parseFrom(data, extensionRegistry); // Merge lazy field check the contents. - messageSet = - messageSet.toBuilder().mergeFrom(data, extensionRegistry).build(); - assertEquals(123, messageSet.getExtension( - TestMessageSetExtension1.messageSetExtension).getI()); + messageSet = messageSet.toBuilder().mergeFrom(data, extensionRegistry).build(); + assertEquals(123, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()); } public void testMergeMessageSetExtensionEagerly() throws Exception { @@ -535,31 +458,24 @@ public void testMergeMessageSetExtensionNotEagerly() throws Exception { testMergeMessageSetExtensionWithFlag(false); } - private void testMergeMessageSetExtensionWithFlag(boolean eagerParsing) - throws Exception { + private void testMergeMessageSetExtensionWithFlag(boolean eagerParsing) throws Exception { ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); // Set up a RawMessageSet with a known messages. - int TYPE_ID_1 = - TestMessageSetExtension1 - .getDescriptor().getExtensions().get(0).getNumber(); RawMessageSet raw = - RawMessageSet.newBuilder() - .addItem( - RawMessageSet.Item.newBuilder() - .setTypeId(TYPE_ID_1) - .setMessage( - TestMessageSetExtension1.newBuilder() - .setI(123) - .build().toByteString()) - .build()) - .build(); + RawMessageSet.newBuilder() + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(TYPE_ID_1) + .setMessage( + TestMessageSetExtension1.newBuilder().setI(123).build().toByteString()) + .build()) + .build(); // Serialize RawMessageSet unnormally (message value before type id) - ByteString.CodedBuilder out = ByteString.newCodedBuilder( - raw.getSerializedSize()); + ByteString.CodedBuilder out = ByteString.newCodedBuilder(raw.getSerializedSize()); CodedOutputStream output = out.getCodedOutput(); List items = raw.getItemList(); for (int i = 0; i < items.size(); i++) { @@ -574,8 +490,7 @@ private void testMergeMessageSetExtensionWithFlag(boolean eagerParsing) // Merge bytes into TestMessageSet and check the contents. TestMessageSet messageSet = TestMessageSet.newBuilder().mergeFrom(data, extensionRegistry).build(); - assertEquals(123, messageSet.getExtension( - TestMessageSetExtension1.messageSetExtension).getI()); + assertEquals(123, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()); } // ================================================================ @@ -593,8 +508,8 @@ public void testOneofWireFormat() throws Exception { } public void testOneofOnlyLastSet() throws Exception { - TestOneofBackwardsCompatible source = TestOneofBackwardsCompatible - .newBuilder().setFooInt(100).setFooString("101").build(); + TestOneofBackwardsCompatible source = + TestOneofBackwardsCompatible.newBuilder().setFooInt(100).setFooString("101").build(); ByteString rawBytes = source.toByteString(); TestOneof2 message = TestOneof2.parseFrom(rawBytes); diff --git a/java/core/src/test/java/com/google/protobuf/WrappersLiteOfMethodTest.java b/java/core/src/test/java/com/google/protobuf/WrappersLiteOfMethodTest.java new file mode 100644 index 0000000000000..4a3c7647f1048 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/WrappersLiteOfMethodTest.java @@ -0,0 +1,61 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.wrapperstest.WrappersTestProto.TopLevelMessage; +import junit.framework.TestCase; + +public class WrappersLiteOfMethodTest extends TestCase { + + public void testOf() throws Exception { + TopLevelMessage.Builder builder = TopLevelMessage.newBuilder(); + builder.setFieldDouble(DoubleValue.of(2.333)); + builder.setFieldFloat(FloatValue.of(2.333f)); + builder.setFieldInt32(Int32Value.of(2333)); + builder.setFieldInt64(Int64Value.of(23333333333333L)); + builder.setFieldUint32(UInt32Value.of(2333)); + builder.setFieldUint64(UInt64Value.of(23333333333333L)); + builder.setFieldBool(BoolValue.of(true)); + builder.setFieldString(StringValue.of("23333")); + builder.setFieldBytes(BytesValue.of(ByteString.wrap("233".getBytes(Internal.UTF_8)))); + + TopLevelMessage message = builder.build(); + assertTrue(2.333 == message.getFieldDouble().getValue()); + assertTrue(2.333f == message.getFieldFloat().getValue()); + assertTrue(2333 == message.getFieldInt32().getValue()); + assertTrue(23333333333333L == message.getFieldInt64().getValue()); + assertTrue(2333 == message.getFieldUint32().getValue()); + assertTrue(23333333333333L == message.getFieldUint64().getValue()); + assertTrue(true == message.getFieldBool().getValue()); + assertTrue(message.getFieldString().getValue().equals("23333")); + assertTrue(message.getFieldBytes().getValue().toStringUtf8().equals("233")); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/WrappersOfMethodTest.java b/java/core/src/test/java/com/google/protobuf/WrappersOfMethodTest.java new file mode 100644 index 0000000000000..f0d662d0c618b --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/WrappersOfMethodTest.java @@ -0,0 +1,61 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.wrapperstest.WrappersTestProto.TopLevelMessage; +import junit.framework.TestCase; + +public class WrappersOfMethodTest extends TestCase { + + public void testOf() throws Exception { + TopLevelMessage.Builder builder = TopLevelMessage.newBuilder(); + builder.setFieldDouble(DoubleValue.of(2.333)); + builder.setFieldFloat(FloatValue.of(2.333f)); + builder.setFieldInt32(Int32Value.of(2333)); + builder.setFieldInt64(Int64Value.of(23333333333333L)); + builder.setFieldUint32(UInt32Value.of(2333)); + builder.setFieldUint64(UInt64Value.of(23333333333333L)); + builder.setFieldBool(BoolValue.of(true)); + builder.setFieldString(StringValue.of("23333")); + builder.setFieldBytes(BytesValue.of(ByteString.wrap("233".getBytes(Internal.UTF_8)))); + + TopLevelMessage message = builder.build(); + assertTrue(2.333 == message.getFieldDouble().getValue()); + assertTrue(2.333f == message.getFieldFloat().getValue()); + assertTrue(2333 == message.getFieldInt32().getValue()); + assertTrue(23333333333333L == message.getFieldInt64().getValue()); + assertTrue(2333 == message.getFieldUint32().getValue()); + assertTrue(23333333333333L == message.getFieldUint64().getValue()); + assertTrue(true == message.getFieldBool().getValue()); + assertTrue(message.getFieldString().getValue().equals("23333")); + assertTrue(message.getFieldBytes().getValue().toStringUtf8().equals("233")); + } +} 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 80173d8a0e422..99d52b75c8102 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 @@ -32,11 +32,11 @@ syntax = "proto3"; package any_test; +import "google/protobuf/any.proto"; + option java_package = "any_test"; option java_outer_classname = "AnyTestProto"; -import "google/protobuf/any.proto"; - message TestAny { google.protobuf.Any value = 1; } 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 new file mode 100644 index 0000000000000..9579a0a5057db --- /dev/null +++ b/java/core/src/test/proto/com/google/protobuf/cached_field_size_test.proto @@ -0,0 +1,45 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// A regression test for b/74087933 +syntax = "proto2"; + +package protobuf_unittest; + +import "google/protobuf/unittest.proto"; +import "google/protobuf/unittest_proto3.proto"; + +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; +} diff --git a/java/core/src/test/proto/com/google/protobuf/deprecated_file.proto b/java/core/src/test/proto/com/google/protobuf/deprecated_file.proto new file mode 100644 index 0000000000000..ca90e927cde31 --- /dev/null +++ b/java/core/src/test/proto/com/google/protobuf/deprecated_file.proto @@ -0,0 +1,38 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package deprecated_file; + +option deprecated = true; + +// TODO (liujisi): Add deprecation options on messages, enums fields as well and +// add tests to verify those annotations are actually generated. 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 2367bd8bd0136..28f3658354c3a 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 @@ -53,7 +53,7 @@ message TestAllTypes { NestedEnum optional_nested_enum = 4; NestedMessage optional_nested_message = 5; protobuf_unittest.TestRequired optional_proto2_message = 6; - NestedMessage optional_lazy_message = 7 [lazy=true]; + NestedMessage optional_lazy_message = 7 [lazy = true]; oneof oneof_field { int32 oneof_int32 = 11; @@ -81,7 +81,7 @@ message TestOptionalFieldsOnly { TestAllTypes.NestedEnum optional_nested_enum = 4; TestAllTypes.NestedMessage optional_nested_message = 5; protobuf_unittest.TestRequired optional_proto2_message = 6; - TestAllTypes.NestedMessage optional_lazy_message = 7 [lazy=true]; + TestAllTypes.NestedMessage optional_lazy_message = 7 [lazy = true]; } message TestRepeatedFieldsOnly { 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 5580f72d990d7..736a344f14859 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 @@ -36,8 +36,6 @@ syntax = "proto2"; package protobuf_unittest; -option optimize_for = LITE_RUNTIME; - message LazyMessageLite { optional int32 num = 1; optional int32 num_with_default = 2 [default = 421]; 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 b18b0d79f223e..080c5192ba21e 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 @@ -34,7 +34,6 @@ syntax = "proto2"; package protobuf_unittest.lite_equals_and_hash; -option optimize_for = LITE_RUNTIME; message TestOneofEquals { oneof oneof_field { @@ -70,8 +69,7 @@ message BarPrime { optional string name = 1; } -message Empty { -} +message Empty {} extend Foo { optional int32 varint = 101; 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 2ca0251ca22de..4ec968819b566 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 @@ -44,12 +44,12 @@ message TestMap { QUX = 3; } - map int32_to_int32_field = 1; - map int32_to_string_field = 2; - map int32_to_bytes_field = 3; - map int32_to_enum_field = 4; - map int32_to_message_field = 5; - map string_to_int32_field = 6; + map int32_to_int32_field = 1; + map int32_to_string_field = 2; + map int32_to_bytes_field = 3; + map int32_to_enum_field = 4; + map int32_to_message_field = 5; + map string_to_int32_field = 6; message MessageWithRequiredFields { required int32 value = 1; @@ -70,15 +70,20 @@ message TestRecursiveMap { map recursive_map_field = 2; } - // a decoy of TestMap for testing parsing errors message BizarroTestMap { - map int32_to_int32_field = 1; // same key type, different value - map int32_to_string_field = 2; // different key and value types - map int32_to_bytes_field = 3; // different key types, same value - map int32_to_enum_field = 4; // different key and value types - map int32_to_message_field = 5; // different key and value types - map string_to_int32_field = 6; // same key type, different value + // 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; } // Used to test that java reserved words can be used as protobuf field names @@ -92,11 +97,13 @@ message ReservedAsMapField { map class = 4; map int = 5; map void = 6; - map string = 7; // These are also proto keywords + // These are also proto keywords + map string = 7; map package = 8; - map enum = 9; // Most recent Java reserved word - map null = 10; + // 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; } message ReservedAsMapFieldWithEnumValue { @@ -110,11 +117,13 @@ message ReservedAsMapFieldWithEnumValue { map class = 4; map int = 5; map void = 6; - map string = 7; // These are also proto keywords + // These are also proto keywords + map string = 7; map package = 8; - map enum = 9; // Most recent Java reserved word - map null = 10; + // 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; } package map_for_proto2_lite_test; option java_package = "map_lite_test"; 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 974f8a2c7446f..f73bd6375b3be 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 @@ -46,12 +46,12 @@ message TestMap { QUX = 3; } - map int32_to_int32_field = 1; - map int32_to_string_field = 2; - map int32_to_bytes_field = 3; - map int32_to_enum_field = 4; - map int32_to_message_field = 5; - map string_to_int32_field = 6; + map int32_to_int32_field = 1; + map int32_to_string_field = 2; + map int32_to_bytes_field = 3; + map int32_to_enum_field = 4; + map int32_to_message_field = 5; + map string_to_int32_field = 6; message MessageWithRequiredFields { required int32 value = 1; @@ -72,15 +72,20 @@ message TestRecursiveMap { map recursive_map_field = 2; } - // a decoy of TestMap for testing parsing errors message BizarroTestMap { - map int32_to_int32_field = 1; // same key type, different value - map int32_to_string_field = 2; // different key and value types - map int32_to_bytes_field = 3; // different key types, same value - map int32_to_enum_field = 4; // different key and value types - map int32_to_message_field = 5; // different key and value types - map string_to_int32_field = 6; // same key type, different value + // 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; } // Used to test that java reserved words can be used as protobuf field names @@ -94,11 +99,13 @@ message ReservedAsMapField { map class = 4; map int = 5; map void = 6; - map string = 7; // These are also proto keywords + // These are also proto keywords + map string = 7; map package = 8; - map enum = 9; // Most recent Java reserved word - map null = 10; + // 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; } message ReservedAsMapFieldWithEnumValue { @@ -112,9 +119,11 @@ message ReservedAsMapFieldWithEnumValue { map class = 4; map int = 5; map void = 6; - map string = 7; // These are also proto keywords + // These are also proto keywords + map string = 7; map package = 8; - map enum = 9; // Most recent Java reserved word - map null = 10; + // 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 b02ac599a5ed6..ab99e5f006d53 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 @@ -28,7 +28,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Regression test for a map initilaization order bug. The bug only manifests +// Regression test for a map initialization order bug. The bug only manifests // when: // 1. A message contains map fields and is also extendable. // 2. There is a file-level extension defined in the same file referencing @@ -57,5 +57,4 @@ extend Message1 { optional Message1 recursive_extension = 1001; } -message RedactAllTypes { -} +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 new file mode 100644 index 0000000000000..7324653f81c59 --- /dev/null +++ b/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto @@ -0,0 +1,121 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package map_lite_test; + +option optimize_for = LITE_RUNTIME; +option java_package = "map_lite_test"; +option java_outer_classname = "MapTestProto"; + +message TestMap { + message MessageValue { + int32 value = 1; + } + enum EnumValue { + FOO = 0; + BAR = 1; + BAZ = 2; + QUX = 3; + } + + map int32_to_int32_field = 1; + map int32_to_string_field = 2; + map int32_to_bytes_field = 3; + map int32_to_enum_field = 4; + map int32_to_message_field = 5; + map string_to_int32_field = 6; + map uint32_to_int32_field = 7; + map int64_to_int32_field = 8; +} + +// Used to test that a nested builder containing map fields will properly +// propagate the onChange event and mark its parent dirty when a change +// is made to a map field. +message TestOnChangeEventPropagation { + TestMap optional_message = 1; +} + +// a decoy of TestMap for testing parsing errors +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; +} + +// Used to test that java reserved words can be used as protobuf field names +// Not all reserved words are tested (to avoid bloat) but instead an arbitrary +// subset of them chosen to cover various keyword categories like +// type, modifier, declaration, etc. +message ReservedAsMapField { + 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; +} + +message ReservedAsMapFieldWithEnumValue { + enum SampleEnum { + 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_test.proto b/java/core/src/test/proto/com/google/protobuf/map_test.proto index bc2105e50ff6c..240600f2def9d 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 @@ -46,14 +46,14 @@ message TestMap { QUX = 3; } - map int32_to_int32_field = 1; - map int32_to_string_field = 2; - map int32_to_bytes_field = 3; - map int32_to_enum_field = 4; + map int32_to_int32_field = 1; + map int32_to_string_field = 2; + map int32_to_bytes_field = 3; + map int32_to_enum_field = 4; map int32_to_message_field = 5; - map string_to_int32_field = 6; - map uint32_to_int32_field = 7; - map int64_to_int32_field = 8; + map string_to_int32_field = 6; + map uint32_to_int32_field = 7; + map int64_to_int32_field = 8; } // Used to test that a nested builder containing map fields will properly @@ -65,12 +65,18 @@ message TestOnChangeEventPropagation { // a decoy of TestMap for testing parsing errors message BizarroTestMap { - map int32_to_int32_field = 1; // same key type, different value - map int32_to_string_field = 2; // different key and value types - map int32_to_bytes_field = 3; // different key types, same value - map int32_to_enum_field = 4; // different key and value types - map int32_to_message_field = 5; // different key and value types - map string_to_int32_field = 6; // same key type, different value + // 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; } // Used to test that java reserved words can be used as protobuf field names @@ -84,11 +90,13 @@ message ReservedAsMapField { map class = 4; map int = 5; map void = 6; - map string = 7; // These are also proto keywords + // These are also proto keywords + map string = 7; map package = 8; - map enum = 9; // Most recent Java reserved word - map null = 10; + // 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; } message ReservedAsMapFieldWithEnumValue { @@ -102,9 +110,11 @@ message ReservedAsMapFieldWithEnumValue { map class = 4; map int = 5; map void = 6; - map string = 7; // These are also proto keywords + // These are also proto keywords + map string = 7; map package = 8; - map enum = 9; // Most recent Java reserved word - map null = 10; + // 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/message_lite_extension_util_test.proto b/java/core/src/test/proto/com/google/protobuf/message_lite_extension_util_test.proto new file mode 100644 index 0000000000000..9baf948d2e0a6 --- /dev/null +++ b/java/core/src/test/proto/com/google/protobuf/message_lite_extension_util_test.proto @@ -0,0 +1,48 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Proto definitions used to test MessageLiteExtensionUtil +syntax = "proto2"; + +package protobuf_unittest; + +option java_outer_classname = "MessageLiteExtensionTestProtos"; + +message Car { + optional string make = 1; + extensions 1000 to max; +} + +extend Car { + optional bool turbo = 1001; + optional bool self_driving = 1002; + optional bool flies = 1003; + optional string plate = 9999; +} 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 92790506f022c..0de6f7b868bb5 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 @@ -36,24 +36,20 @@ syntax = "proto2"; // Some generic_services option(s) added automatically. // See: http://go/proto2-generic-services-default -option java_generic_services = true; // auto-added +package protobuf_unittest; import "google/protobuf/unittest.proto"; import "google/protobuf/descriptor.proto"; -package protobuf_unittest; - +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; } - enum NestedEnum { - BAZ = 3; - } + enum NestedEnum { BAZ = 3; } optional NestedMessage nested = 1; repeated TestAllTypes foreign = 2; optional NestedEnum nested_enum = 3; @@ -70,7 +66,7 @@ enum EnumWithNoOuter { } service ServiceWithNoOuter { - rpc Foo(MessageWithNoOuter) returns(TestAllTypes); + rpc Foo(MessageWithNoOuter) returns (TestAllTypes); } extend TestAllExtensions { 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 a5dd66d889464..07933ed449494 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 @@ -37,7 +37,6 @@ package protobuf_unittest; option java_multiple_files = true; option java_outer_classname = "NestedBuilders"; - message Vehicle { optional Engine engine = 1; repeated Wheel wheel = 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 704e649e020b3..2da6d08e3acc2 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 @@ -35,13 +35,14 @@ syntax = "proto2"; -import "com/google/protobuf/non_nested_extension.proto"; - package protobuf_unittest; +import "com/google/protobuf/non_nested_extension.proto"; + message MyNestedExtension { extend MessageToBeExtended { optional MessageToBeExtended recursiveExtension = 2; + optional 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 a95c38b234f2f..024097cb5eeb8 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 @@ -38,12 +38,13 @@ syntax = "proto2"; package protobuf_unittest; -option optimize_for = LITE_RUNTIME; - import "com/google/protobuf/non_nested_extension_lite.proto"; +option optimize_for = LITE_RUNTIME; + message MyNestedExtensionLite { extend MessageLiteToBeExtended { optional MessageLiteToBeExtended recursiveExtensionLite = 3; + optional 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 31fac55295999..45395a353a7ec 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 @@ -41,10 +41,9 @@ message MessageToBeExtended { extensions 1 to max; } -message MyNonNestedExtension { -} +message MyNonNestedExtension {} extend MessageToBeExtended { optional MyNonNestedExtension nonNestedExtension = 1; + optional 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 37c369edaa194..782a1e66d4b78 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 @@ -42,10 +42,9 @@ message MessageLiteToBeExtended { extensions 1 to max; } -message MyNonNestedExtensionLite { -} +message MyNonNestedExtensionLite {} extend MessageLiteToBeExtended { optional MyNonNestedExtensionLite nonNestedExtensionLite = 1; + optional 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 4208368146921..28b8bb568797e 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 @@ -36,5 +36,4 @@ package protobuf_unittest; // This message'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. -message OuterClassNameTest { -} +message OuterClassNameTest {} 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 3e5956b0d4282..b475510e745be 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 @@ -38,7 +38,6 @@ message TestMessage2 { // This message'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. - message OuterClassNameTest2 { - } + message OuterClassNameTest2 {} } } 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 74a8ba3c3dddd..e5ef2f0534ef7 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 @@ -38,8 +38,6 @@ 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 { 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 new file mode 100644 index 0000000000000..7935322b72eef --- /dev/null +++ b/java/core/src/test/proto/com/google/protobuf/packed_field_test.proto @@ -0,0 +1,76 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package packed_field_test; + +option java_package = "com.google.protobuf"; +option java_outer_classname = "PackedFieldTestProto"; + +message TestAllTypes { + enum NestedEnum { + FOO = 0; + BAR = 1; + BAZ = 2; + } + + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated NestedEnum repeated_nested_enum = 51; +} + +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]; +} 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 new file mode 100644 index 0000000000000..86c48b098636d --- /dev/null +++ b/java/core/src/test/proto/com/google/protobuf/proto2_message.proto @@ -0,0 +1,430 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// LINT: ALLOW_GROUPS +syntax = "proto2"; + +package protobuf.experimental; + +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; +} + +message Proto2Message { + + enum TestEnum { + 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; + } + repeated group FieldGroupList51 = 51 { + optional int32 field_int32_52 = 52; + } + oneof test_oneof { + double field_double_53 = 53; + float field_float_54 = 54; + int64 field_int64_55 = 55; + uint64 field_uint64_56 = 56; + int32 field_int32_57 = 57; + fixed64 field_fixed64_58 = 58; + fixed32 field_fixed32_59 = 59; + bool field_bool_60 = 60; + string field_string_61 = 61; + Proto2Message field_message_62 = 62; + bytes field_bytes_63 = 63; + uint32 field_uint32_64 = 64; + sfixed32 field_sfixed32_65 = 65; + sfixed64 field_sfixed64_66 = 66; + sint32 field_sint32_67 = 67; + sint64 field_sint64_68 = 68; + group FieldGroup69 = 69 { + optional int32 field_int32_70 = 70; + } + } + + message RequiredNestedMessage { + optional 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; + } +} + +message Proto2Empty {} + +message Proto2MessageWithExtensions { + extensions 1 to 10000; +} + +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; + } + + repeated group FieldGroupList51 = 51 { + optional int32 field_int32_52 = 52; + } +} + +message Proto2MessageWithMaps { + map field_map_bool_bool_1 = 1; + map field_map_bool_bytes_2 = 2; + map field_map_bool_double_3 = 3; + map field_map_bool_enum_4 = 4; + map field_map_bool_fixed32_5 = 5; + map field_map_bool_fixed64_6 = 6; + map field_map_bool_float_7 = 7; + map field_map_bool_int32_8 = 8; + map field_map_bool_int64_9 = 9; + map field_map_bool_message_10 = 10; + map field_map_bool_sfixed32_11 = 11; + map field_map_bool_sfixed64_12 = 12; + map field_map_bool_sint32_13 = 13; + map field_map_bool_sint64_14 = 14; + map field_map_bool_string_15 = 15; + map field_map_bool_uint32_16 = 16; + map field_map_bool_uint64_17 = 17; + map field_map_fixed32_bool_18 = 18; + map field_map_fixed32_bytes_19 = 19; + map field_map_fixed32_double_20 = 20; + map field_map_fixed32_enum_21 = 21; + map field_map_fixed32_fixed32_22 = 22; + map field_map_fixed32_fixed64_23 = 23; + map field_map_fixed32_float_24 = 24; + map field_map_fixed32_int32_25 = 25; + map field_map_fixed32_int64_26 = 26; + map field_map_fixed32_message_27 = 27; + map field_map_fixed32_sfixed32_28 = 28; + map field_map_fixed32_sfixed64_29 = 29; + map field_map_fixed32_sint32_30 = 30; + map field_map_fixed32_sint64_31 = 31; + map field_map_fixed32_string_32 = 32; + map field_map_fixed32_uint32_33 = 33; + map field_map_fixed32_uint64_34 = 34; + map field_map_fixed64_bool_35 = 35; + map field_map_fixed64_bytes_36 = 36; + map field_map_fixed64_double_37 = 37; + map field_map_fixed64_enum_38 = 38; + map field_map_fixed64_fixed32_39 = 39; + map field_map_fixed64_fixed64_40 = 40; + map field_map_fixed64_float_41 = 41; + map field_map_fixed64_int32_42 = 42; + map field_map_fixed64_int64_43 = 43; + map field_map_fixed64_message_44 = 44; + map field_map_fixed64_sfixed32_45 = 45; + map field_map_fixed64_sfixed64_46 = 46; + map field_map_fixed64_sint32_47 = 47; + map field_map_fixed64_sint64_48 = 48; + map field_map_fixed64_string_49 = 49; + map field_map_fixed64_uint32_50 = 50; + map field_map_fixed64_uint64_51 = 51; + map field_map_int32_bool_52 = 52; + map field_map_int32_bytes_53 = 53; + map field_map_int32_double_54 = 54; + map field_map_int32_enum_55 = 55; + map field_map_int32_fixed32_56 = 56; + map field_map_int32_fixed64_57 = 57; + map field_map_int32_float_58 = 58; + map field_map_int32_int32_59 = 59; + map field_map_int32_int64_60 = 60; + map field_map_int32_message_61 = 61; + map field_map_int32_sfixed32_62 = 62; + map field_map_int32_sfixed64_63 = 63; + map field_map_int32_sint32_64 = 64; + map field_map_int32_sint64_65 = 65; + map field_map_int32_string_66 = 66; + map field_map_int32_uint32_67 = 67; + map field_map_int32_uint64_68 = 68; + map field_map_int64_bool_69 = 69; + map field_map_int64_bytes_70 = 70; + map field_map_int64_double_71 = 71; + map field_map_int64_enum_72 = 72; + map field_map_int64_fixed32_73 = 73; + map field_map_int64_fixed64_74 = 74; + map field_map_int64_float_75 = 75; + map field_map_int64_int32_76 = 76; + map field_map_int64_int64_77 = 77; + map field_map_int64_message_78 = 78; + map field_map_int64_sfixed32_79 = 79; + map field_map_int64_sfixed64_80 = 80; + map field_map_int64_sint32_81 = 81; + map field_map_int64_sint64_82 = 82; + map field_map_int64_string_83 = 83; + map field_map_int64_uint32_84 = 84; + map field_map_int64_uint64_85 = 85; + map field_map_sfixed32_bool_86 = 86; + map field_map_sfixed32_bytes_87 = 87; + map field_map_sfixed32_double_88 = 88; + map field_map_sfixed32_enum_89 = 89; + map field_map_sfixed32_fixed32_90 = 90; + map field_map_sfixed32_fixed64_91 = 91; + map field_map_sfixed32_float_92 = 92; + map field_map_sfixed32_int32_93 = 93; + map field_map_sfixed32_int64_94 = 94; + map field_map_sfixed32_message_95 = 95; + map field_map_sfixed32_sfixed32_96 = 96; + map field_map_sfixed32_sfixed64_97 = 97; + map field_map_sfixed32_sint32_98 = 98; + map field_map_sfixed32_sint64_99 = 99; + map field_map_sfixed32_string_100 = 100; + map field_map_sfixed32_uint32_101 = 101; + map field_map_sfixed32_uint64_102 = 102; + map field_map_sfixed64_bool_103 = 103; + map field_map_sfixed64_bytes_104 = 104; + map field_map_sfixed64_double_105 = 105; + map field_map_sfixed64_enum_106 = 106; + map field_map_sfixed64_fixed32_107 = 107; + map field_map_sfixed64_fixed64_108 = 108; + map field_map_sfixed64_float_109 = 109; + map field_map_sfixed64_int32_110 = 110; + map field_map_sfixed64_int64_111 = 111; + map field_map_sfixed64_message_112 = 112; + map field_map_sfixed64_sfixed32_113 = 113; + map field_map_sfixed64_sfixed64_114 = 114; + map field_map_sfixed64_sint32_115 = 115; + map field_map_sfixed64_sint64_116 = 116; + map field_map_sfixed64_string_117 = 117; + map field_map_sfixed64_uint32_118 = 118; + map field_map_sfixed64_uint64_119 = 119; + map field_map_sint32_bool_120 = 120; + map field_map_sint32_bytes_121 = 121; + map field_map_sint32_double_122 = 122; + map field_map_sint32_enum_123 = 123; + map field_map_sint32_fixed32_124 = 124; + map field_map_sint32_fixed64_125 = 125; + map field_map_sint32_float_126 = 126; + map field_map_sint32_int32_127 = 127; + map field_map_sint32_int64_128 = 128; + map field_map_sint32_message_129 = 129; + map field_map_sint32_sfixed32_130 = 130; + map field_map_sint32_sfixed64_131 = 131; + map field_map_sint32_sint32_132 = 132; + map field_map_sint32_sint64_133 = 133; + map field_map_sint32_string_134 = 134; + map field_map_sint32_uint32_135 = 135; + map field_map_sint32_uint64_136 = 136; + map field_map_sint64_bool_137 = 137; + map field_map_sint64_bytes_138 = 138; + map field_map_sint64_double_139 = 139; + map field_map_sint64_enum_140 = 140; + map field_map_sint64_fixed32_141 = 141; + map field_map_sint64_fixed64_142 = 142; + map field_map_sint64_float_143 = 143; + map field_map_sint64_int32_144 = 144; + map field_map_sint64_int64_145 = 145; + map field_map_sint64_message_146 = 146; + map field_map_sint64_sfixed32_147 = 147; + map field_map_sint64_sfixed64_148 = 148; + map field_map_sint64_sint32_149 = 149; + map field_map_sint64_sint64_150 = 150; + map field_map_sint64_string_151 = 151; + map field_map_sint64_uint32_152 = 152; + map field_map_sint64_uint64_153 = 153; + map field_map_string_bool_154 = 154; + map field_map_string_bytes_155 = 155; + map field_map_string_double_156 = 156; + map field_map_string_enum_157 = 157; + map field_map_string_fixed32_158 = 158; + map field_map_string_fixed64_159 = 159; + map field_map_string_float_160 = 160; + map field_map_string_int32_161 = 161; + map field_map_string_int64_162 = 162; + map field_map_string_message_163 = 163; + map field_map_string_sfixed32_164 = 164; + map field_map_string_sfixed64_165 = 165; + map field_map_string_sint32_166 = 166; + map field_map_string_sint64_167 = 167; + map field_map_string_string_168 = 168; + map field_map_string_uint32_169 = 169; + map field_map_string_uint64_170 = 170; + map field_map_uint32_bool_171 = 171; + map field_map_uint32_bytes_172 = 172; + map field_map_uint32_double_173 = 173; + map field_map_uint32_enum_174 = 174; + map field_map_uint32_fixed32_175 = 175; + map field_map_uint32_fixed64_176 = 176; + map field_map_uint32_float_177 = 177; + map field_map_uint32_int32_178 = 178; + map field_map_uint32_int64_179 = 179; + map field_map_uint32_message_180 = 180; + map field_map_uint32_sfixed32_181 = 181; + map field_map_uint32_sfixed64_182 = 182; + map field_map_uint32_sint32_183 = 183; + map field_map_uint32_sint64_184 = 184; + map field_map_uint32_string_185 = 185; + map field_map_uint32_uint32_186 = 186; + map field_map_uint32_uint64_187 = 187; + map field_map_uint64_bool_188 = 188; + map field_map_uint64_bytes_189 = 189; + map field_map_uint64_double_190 = 190; + map field_map_uint64_enum_191 = 191; + map field_map_uint64_fixed32_192 = 192; + map field_map_uint64_fixed64_193 = 193; + map field_map_uint64_float_194 = 194; + map field_map_uint64_int32_195 = 195; + map field_map_uint64_int64_196 = 196; + map field_map_uint64_message_197 = 197; + map field_map_uint64_sfixed32_198 = 198; + map field_map_uint64_sfixed64_199 = 199; + map field_map_uint64_sint32_200 = 200; + map field_map_uint64_sint64_201 = 201; + map field_map_uint64_string_202 = 202; + map field_map_uint64_uint32_203 = 203; + map field_map_uint64_uint64_204 = 204; +} 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 new file mode 100644 index 0000000000000..7dfd40eea34cd --- /dev/null +++ b/java/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto @@ -0,0 +1,423 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// LINT: ALLOW_GROUPS +syntax = "proto2"; + +package protobuf.experimental.lite; + +option java_package = "com.google.protobuf.testing"; +option java_outer_classname = "Proto2TestingLite"; + + +message Proto2MessageLite { + + enum TestEnum { + 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; + } + repeated group FieldGroupList51 = 51 { + optional int32 field_int32_52 = 52; + } + oneof test_oneof { + double field_double_53 = 53; + float field_float_54 = 54; + int64 field_int64_55 = 55; + uint64 field_uint64_56 = 56; + int32 field_int32_57 = 57; + fixed64 field_fixed64_58 = 58; + fixed32 field_fixed32_59 = 59; + bool field_bool_60 = 60; + string field_string_61 = 61; + Proto2MessageLite field_message_62 = 62; + bytes field_bytes_63 = 63; + uint32 field_uint32_64 = 64; + sfixed32 field_sfixed32_65 = 65; + sfixed64 field_sfixed64_66 = 66; + sint32 field_sint32_67 = 67; + sint64 field_sint64_68 = 68; + group FieldGroup69 = 69 { + optional int32 field_int32_70 = 70; + } + } + + message RequiredNestedMessage { + optional 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; + } +} + +message Proto2EmptyLite {} + +message Proto2MessageLiteWithExtensions { + extensions 1 to max; +} + +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; + } + + repeated group FieldGroupList51 = 51 { + optional int32 field_int32_52 = 52; + } +} + +message Proto2MessageLiteWithMaps { + map field_map_bool_bool_1 = 1; + map field_map_bool_bytes_2 = 2; + map field_map_bool_double_3 = 3; + map field_map_bool_enum_4 = 4; + map field_map_bool_fixed32_5 = 5; + map field_map_bool_fixed64_6 = 6; + map field_map_bool_float_7 = 7; + map field_map_bool_int32_8 = 8; + map field_map_bool_int64_9 = 9; + map field_map_bool_message_10 = 10; + map field_map_bool_sfixed32_11 = 11; + map field_map_bool_sfixed64_12 = 12; + map field_map_bool_sint32_13 = 13; + map field_map_bool_sint64_14 = 14; + map field_map_bool_string_15 = 15; + map field_map_bool_uint32_16 = 16; + map field_map_bool_uint64_17 = 17; + map field_map_fixed32_bool_18 = 18; + map field_map_fixed32_bytes_19 = 19; + map field_map_fixed32_double_20 = 20; + map field_map_fixed32_enum_21 = 21; + map field_map_fixed32_fixed32_22 = 22; + map field_map_fixed32_fixed64_23 = 23; + map field_map_fixed32_float_24 = 24; + map field_map_fixed32_int32_25 = 25; + map field_map_fixed32_int64_26 = 26; + map field_map_fixed32_message_27 = 27; + map field_map_fixed32_sfixed32_28 = 28; + map field_map_fixed32_sfixed64_29 = 29; + map field_map_fixed32_sint32_30 = 30; + map field_map_fixed32_sint64_31 = 31; + map field_map_fixed32_string_32 = 32; + map field_map_fixed32_uint32_33 = 33; + map field_map_fixed32_uint64_34 = 34; + map field_map_fixed64_bool_35 = 35; + map field_map_fixed64_bytes_36 = 36; + map field_map_fixed64_double_37 = 37; + map field_map_fixed64_enum_38 = 38; + map field_map_fixed64_fixed32_39 = 39; + map field_map_fixed64_fixed64_40 = 40; + map field_map_fixed64_float_41 = 41; + map field_map_fixed64_int32_42 = 42; + map field_map_fixed64_int64_43 = 43; + map field_map_fixed64_message_44 = 44; + map field_map_fixed64_sfixed32_45 = 45; + map field_map_fixed64_sfixed64_46 = 46; + map field_map_fixed64_sint32_47 = 47; + map field_map_fixed64_sint64_48 = 48; + map field_map_fixed64_string_49 = 49; + map field_map_fixed64_uint32_50 = 50; + map field_map_fixed64_uint64_51 = 51; + map field_map_int32_bool_52 = 52; + map field_map_int32_bytes_53 = 53; + map field_map_int32_double_54 = 54; + map field_map_int32_enum_55 = 55; + map field_map_int32_fixed32_56 = 56; + map field_map_int32_fixed64_57 = 57; + map field_map_int32_float_58 = 58; + map field_map_int32_int32_59 = 59; + map field_map_int32_int64_60 = 60; + map field_map_int32_message_61 = 61; + map field_map_int32_sfixed32_62 = 62; + map field_map_int32_sfixed64_63 = 63; + map field_map_int32_sint32_64 = 64; + map field_map_int32_sint64_65 = 65; + map field_map_int32_string_66 = 66; + map field_map_int32_uint32_67 = 67; + map field_map_int32_uint64_68 = 68; + map field_map_int64_bool_69 = 69; + map field_map_int64_bytes_70 = 70; + map field_map_int64_double_71 = 71; + map field_map_int64_enum_72 = 72; + map field_map_int64_fixed32_73 = 73; + map field_map_int64_fixed64_74 = 74; + map field_map_int64_float_75 = 75; + map field_map_int64_int32_76 = 76; + map field_map_int64_int64_77 = 77; + map field_map_int64_message_78 = 78; + map field_map_int64_sfixed32_79 = 79; + map field_map_int64_sfixed64_80 = 80; + map field_map_int64_sint32_81 = 81; + map field_map_int64_sint64_82 = 82; + map field_map_int64_string_83 = 83; + map field_map_int64_uint32_84 = 84; + map field_map_int64_uint64_85 = 85; + map field_map_sfixed32_bool_86 = 86; + map field_map_sfixed32_bytes_87 = 87; + map field_map_sfixed32_double_88 = 88; + map field_map_sfixed32_enum_89 = 89; + map field_map_sfixed32_fixed32_90 = 90; + map field_map_sfixed32_fixed64_91 = 91; + map field_map_sfixed32_float_92 = 92; + map field_map_sfixed32_int32_93 = 93; + map field_map_sfixed32_int64_94 = 94; + map field_map_sfixed32_message_95 = 95; + map field_map_sfixed32_sfixed32_96 = 96; + map field_map_sfixed32_sfixed64_97 = 97; + map field_map_sfixed32_sint32_98 = 98; + map field_map_sfixed32_sint64_99 = 99; + map field_map_sfixed32_string_100 = 100; + map field_map_sfixed32_uint32_101 = 101; + map field_map_sfixed32_uint64_102 = 102; + map field_map_sfixed64_bool_103 = 103; + map field_map_sfixed64_bytes_104 = 104; + map field_map_sfixed64_double_105 = 105; + map field_map_sfixed64_enum_106 = 106; + map field_map_sfixed64_fixed32_107 = 107; + map field_map_sfixed64_fixed64_108 = 108; + map field_map_sfixed64_float_109 = 109; + map field_map_sfixed64_int32_110 = 110; + map field_map_sfixed64_int64_111 = 111; + map field_map_sfixed64_message_112 = 112; + map field_map_sfixed64_sfixed32_113 = 113; + map field_map_sfixed64_sfixed64_114 = 114; + map field_map_sfixed64_sint32_115 = 115; + map field_map_sfixed64_sint64_116 = 116; + map field_map_sfixed64_string_117 = 117; + map field_map_sfixed64_uint32_118 = 118; + map field_map_sfixed64_uint64_119 = 119; + map field_map_sint32_bool_120 = 120; + map field_map_sint32_bytes_121 = 121; + map field_map_sint32_double_122 = 122; + map field_map_sint32_enum_123 = 123; + map field_map_sint32_fixed32_124 = 124; + map field_map_sint32_fixed64_125 = 125; + map field_map_sint32_float_126 = 126; + map field_map_sint32_int32_127 = 127; + map field_map_sint32_int64_128 = 128; + map field_map_sint32_message_129 = 129; + map field_map_sint32_sfixed32_130 = 130; + map field_map_sint32_sfixed64_131 = 131; + map field_map_sint32_sint32_132 = 132; + map field_map_sint32_sint64_133 = 133; + map field_map_sint32_string_134 = 134; + map field_map_sint32_uint32_135 = 135; + map field_map_sint32_uint64_136 = 136; + map field_map_sint64_bool_137 = 137; + map field_map_sint64_bytes_138 = 138; + map field_map_sint64_double_139 = 139; + map field_map_sint64_enum_140 = 140; + map field_map_sint64_fixed32_141 = 141; + map field_map_sint64_fixed64_142 = 142; + map field_map_sint64_float_143 = 143; + map field_map_sint64_int32_144 = 144; + map field_map_sint64_int64_145 = 145; + map field_map_sint64_message_146 = 146; + map field_map_sint64_sfixed32_147 = 147; + map field_map_sint64_sfixed64_148 = 148; + map field_map_sint64_sint32_149 = 149; + map field_map_sint64_sint64_150 = 150; + map field_map_sint64_string_151 = 151; + map field_map_sint64_uint32_152 = 152; + map field_map_sint64_uint64_153 = 153; + map field_map_string_bool_154 = 154; + map field_map_string_bytes_155 = 155; + map field_map_string_double_156 = 156; + map field_map_string_enum_157 = 157; + map field_map_string_fixed32_158 = 158; + map field_map_string_fixed64_159 = 159; + map field_map_string_float_160 = 160; + map field_map_string_int32_161 = 161; + map field_map_string_int64_162 = 162; + map field_map_string_message_163 = 163; + map field_map_string_sfixed32_164 = 164; + map field_map_string_sfixed64_165 = 165; + map field_map_string_sint32_166 = 166; + map field_map_string_sint64_167 = 167; + map field_map_string_string_168 = 168; + map field_map_string_uint32_169 = 169; + map field_map_string_uint64_170 = 170; + map field_map_uint32_bool_171 = 171; + map field_map_uint32_bytes_172 = 172; + map field_map_uint32_double_173 = 173; + map field_map_uint32_enum_174 = 174; + map field_map_uint32_fixed32_175 = 175; + map field_map_uint32_fixed64_176 = 176; + map field_map_uint32_float_177 = 177; + map field_map_uint32_int32_178 = 178; + map field_map_uint32_int64_179 = 179; + map field_map_uint32_message_180 = 180; + map field_map_uint32_sfixed32_181 = 181; + map field_map_uint32_sfixed64_182 = 182; + map field_map_uint32_sint32_183 = 183; + map field_map_uint32_sint64_184 = 184; + map field_map_uint32_string_185 = 185; + map field_map_uint32_uint32_186 = 186; + map field_map_uint32_uint64_187 = 187; + map field_map_uint64_bool_188 = 188; + map field_map_uint64_bytes_189 = 189; + map field_map_uint64_double_190 = 190; + map field_map_uint64_enum_191 = 191; + map field_map_uint64_fixed32_192 = 192; + map field_map_uint64_fixed64_193 = 193; + map field_map_uint64_float_194 = 194; + map field_map_uint64_int32_195 = 195; + map field_map_uint64_int64_196 = 196; + map field_map_uint64_message_197 = 197; + map field_map_uint64_sfixed32_198 = 198; + map field_map_uint64_sfixed64_199 = 199; + map field_map_uint64_sint32_200 = 200; + map field_map_uint64_sint64_201 = 201; + map field_map_uint64_string_202 = 202; + map field_map_uint64_uint32_203 = 203; + map field_map_uint64_uint64_204 = 204; +} 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 new file mode 100644 index 0000000000000..5d470ac0e37fe --- /dev/null +++ b/java/core/src/test/proto/com/google/protobuf/proto2_unknown_enum_values.proto @@ -0,0 +1,60 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package proto2_unknown_enum_values; + +option java_package = "com.google.protobuf"; +option java_outer_classname = "Proto2UnknownEnumValuesTestProto"; + +enum Proto2TestEnum { + ZERO = 0; + ONE = 1; + TWO = 2; +} + +message Proto2EnumMessage { + repeated Proto2TestEnum repeated_packed_enum = 1 [packed = true]; +} + +// An enum containing a subset of the values of Proto2TestEnum, to test +// parsing unknown packed enum values +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]; +} 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 new file mode 100644 index 0000000000000..bcf32e1965c14 --- /dev/null +++ b/java/core/src/test/proto/com/google/protobuf/proto3_message.proto @@ -0,0 +1,327 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package protobuf.experimental; + +option java_package = "com.google.protobuf.testing"; +option java_outer_classname = "Proto3Testing"; + +message Proto3SpecialFieldName { + double regular_name = 1; + int32 cached_size = 2; + int64 serialized_size = 3; + string class = 4; +} + +message Proto3Message { + enum TestEnum { + ZERO = 0; + ONE = 1; + TWO = 2; + } + + 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; + Proto3Message 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 [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]; + oneof test_oneof { + double field_double_53 = 53; + float field_float_54 = 54; + int64 field_int64_55 = 55; + uint64 field_uint64_56 = 56; + int32 field_int32_57 = 57; + fixed64 field_fixed64_58 = 58; + fixed32 field_fixed32_59 = 59; + bool field_bool_60 = 60; + string field_string_61 = 61; + Proto3Message field_message_62 = 62; + bytes field_bytes_63 = 63; + uint32 field_uint32_64 = 64; + sfixed32 field_sfixed32_65 = 65; + sfixed64 field_sfixed64_66 = 66; + sint32 field_sint32_67 = 67; + sint64 field_sint64_68 = 68; + } +} + +message Proto3Empty {} + +message Proto3MessageWithMaps { + map field_map_bool_bool_1 = 1; + map field_map_bool_bytes_2 = 2; + map field_map_bool_double_3 = 3; + map field_map_bool_enum_4 = 4; + map field_map_bool_fixed32_5 = 5; + map field_map_bool_fixed64_6 = 6; + map field_map_bool_float_7 = 7; + map field_map_bool_int32_8 = 8; + map field_map_bool_int64_9 = 9; + map field_map_bool_message_10 = 10; + map field_map_bool_sfixed32_11 = 11; + map field_map_bool_sfixed64_12 = 12; + map field_map_bool_sint32_13 = 13; + map field_map_bool_sint64_14 = 14; + map field_map_bool_string_15 = 15; + map field_map_bool_uint32_16 = 16; + map field_map_bool_uint64_17 = 17; + map field_map_fixed32_bool_18 = 18; + map field_map_fixed32_bytes_19 = 19; + map field_map_fixed32_double_20 = 20; + map field_map_fixed32_enum_21 = 21; + map field_map_fixed32_fixed32_22 = 22; + map field_map_fixed32_fixed64_23 = 23; + map field_map_fixed32_float_24 = 24; + map field_map_fixed32_int32_25 = 25; + map field_map_fixed32_int64_26 = 26; + map field_map_fixed32_message_27 = 27; + map field_map_fixed32_sfixed32_28 = 28; + map field_map_fixed32_sfixed64_29 = 29; + map field_map_fixed32_sint32_30 = 30; + map field_map_fixed32_sint64_31 = 31; + map field_map_fixed32_string_32 = 32; + map field_map_fixed32_uint32_33 = 33; + map field_map_fixed32_uint64_34 = 34; + map field_map_fixed64_bool_35 = 35; + map field_map_fixed64_bytes_36 = 36; + map field_map_fixed64_double_37 = 37; + map field_map_fixed64_enum_38 = 38; + map field_map_fixed64_fixed32_39 = 39; + map field_map_fixed64_fixed64_40 = 40; + map field_map_fixed64_float_41 = 41; + map field_map_fixed64_int32_42 = 42; + map field_map_fixed64_int64_43 = 43; + map field_map_fixed64_message_44 = 44; + map field_map_fixed64_sfixed32_45 = 45; + map field_map_fixed64_sfixed64_46 = 46; + map field_map_fixed64_sint32_47 = 47; + map field_map_fixed64_sint64_48 = 48; + map field_map_fixed64_string_49 = 49; + map field_map_fixed64_uint32_50 = 50; + map field_map_fixed64_uint64_51 = 51; + map field_map_int32_bool_52 = 52; + map field_map_int32_bytes_53 = 53; + map field_map_int32_double_54 = 54; + map field_map_int32_enum_55 = 55; + map field_map_int32_fixed32_56 = 56; + map field_map_int32_fixed64_57 = 57; + map field_map_int32_float_58 = 58; + map field_map_int32_int32_59 = 59; + map field_map_int32_int64_60 = 60; + map field_map_int32_message_61 = 61; + map field_map_int32_sfixed32_62 = 62; + map field_map_int32_sfixed64_63 = 63; + map field_map_int32_sint32_64 = 64; + map field_map_int32_sint64_65 = 65; + map field_map_int32_string_66 = 66; + map field_map_int32_uint32_67 = 67; + map field_map_int32_uint64_68 = 68; + map field_map_int64_bool_69 = 69; + map field_map_int64_bytes_70 = 70; + map field_map_int64_double_71 = 71; + map field_map_int64_enum_72 = 72; + map field_map_int64_fixed32_73 = 73; + map field_map_int64_fixed64_74 = 74; + map field_map_int64_float_75 = 75; + map field_map_int64_int32_76 = 76; + map field_map_int64_int64_77 = 77; + map field_map_int64_message_78 = 78; + map field_map_int64_sfixed32_79 = 79; + map field_map_int64_sfixed64_80 = 80; + map field_map_int64_sint32_81 = 81; + map field_map_int64_sint64_82 = 82; + map field_map_int64_string_83 = 83; + map field_map_int64_uint32_84 = 84; + map field_map_int64_uint64_85 = 85; + map field_map_sfixed32_bool_86 = 86; + map field_map_sfixed32_bytes_87 = 87; + map field_map_sfixed32_double_88 = 88; + map field_map_sfixed32_enum_89 = 89; + map field_map_sfixed32_fixed32_90 = 90; + map field_map_sfixed32_fixed64_91 = 91; + map field_map_sfixed32_float_92 = 92; + map field_map_sfixed32_int32_93 = 93; + map field_map_sfixed32_int64_94 = 94; + map field_map_sfixed32_message_95 = 95; + map field_map_sfixed32_sfixed32_96 = 96; + map field_map_sfixed32_sfixed64_97 = 97; + map field_map_sfixed32_sint32_98 = 98; + map field_map_sfixed32_sint64_99 = 99; + map field_map_sfixed32_string_100 = 100; + map field_map_sfixed32_uint32_101 = 101; + map field_map_sfixed32_uint64_102 = 102; + map field_map_sfixed64_bool_103 = 103; + map field_map_sfixed64_bytes_104 = 104; + map field_map_sfixed64_double_105 = 105; + map field_map_sfixed64_enum_106 = 106; + map field_map_sfixed64_fixed32_107 = 107; + map field_map_sfixed64_fixed64_108 = 108; + map field_map_sfixed64_float_109 = 109; + map field_map_sfixed64_int32_110 = 110; + map field_map_sfixed64_int64_111 = 111; + map field_map_sfixed64_message_112 = 112; + map field_map_sfixed64_sfixed32_113 = 113; + map field_map_sfixed64_sfixed64_114 = 114; + map field_map_sfixed64_sint32_115 = 115; + map field_map_sfixed64_sint64_116 = 116; + map field_map_sfixed64_string_117 = 117; + map field_map_sfixed64_uint32_118 = 118; + map field_map_sfixed64_uint64_119 = 119; + map field_map_sint32_bool_120 = 120; + map field_map_sint32_bytes_121 = 121; + map field_map_sint32_double_122 = 122; + map field_map_sint32_enum_123 = 123; + map field_map_sint32_fixed32_124 = 124; + map field_map_sint32_fixed64_125 = 125; + map field_map_sint32_float_126 = 126; + map field_map_sint32_int32_127 = 127; + map field_map_sint32_int64_128 = 128; + map field_map_sint32_message_129 = 129; + map field_map_sint32_sfixed32_130 = 130; + map field_map_sint32_sfixed64_131 = 131; + map field_map_sint32_sint32_132 = 132; + map field_map_sint32_sint64_133 = 133; + map field_map_sint32_string_134 = 134; + map field_map_sint32_uint32_135 = 135; + map field_map_sint32_uint64_136 = 136; + map field_map_sint64_bool_137 = 137; + map field_map_sint64_bytes_138 = 138; + map field_map_sint64_double_139 = 139; + map field_map_sint64_enum_140 = 140; + map field_map_sint64_fixed32_141 = 141; + map field_map_sint64_fixed64_142 = 142; + map field_map_sint64_float_143 = 143; + map field_map_sint64_int32_144 = 144; + map field_map_sint64_int64_145 = 145; + map field_map_sint64_message_146 = 146; + map field_map_sint64_sfixed32_147 = 147; + map field_map_sint64_sfixed64_148 = 148; + map field_map_sint64_sint32_149 = 149; + map field_map_sint64_sint64_150 = 150; + map field_map_sint64_string_151 = 151; + map field_map_sint64_uint32_152 = 152; + map field_map_sint64_uint64_153 = 153; + map field_map_string_bool_154 = 154; + map field_map_string_bytes_155 = 155; + map field_map_string_double_156 = 156; + map field_map_string_enum_157 = 157; + map field_map_string_fixed32_158 = 158; + map field_map_string_fixed64_159 = 159; + map field_map_string_float_160 = 160; + map field_map_string_int32_161 = 161; + map field_map_string_int64_162 = 162; + map field_map_string_message_163 = 163; + map field_map_string_sfixed32_164 = 164; + map field_map_string_sfixed64_165 = 165; + map field_map_string_sint32_166 = 166; + map field_map_string_sint64_167 = 167; + map field_map_string_string_168 = 168; + map field_map_string_uint32_169 = 169; + map field_map_string_uint64_170 = 170; + map field_map_uint32_bool_171 = 171; + map field_map_uint32_bytes_172 = 172; + map field_map_uint32_double_173 = 173; + map field_map_uint32_enum_174 = 174; + map field_map_uint32_fixed32_175 = 175; + map field_map_uint32_fixed64_176 = 176; + map field_map_uint32_float_177 = 177; + map field_map_uint32_int32_178 = 178; + map field_map_uint32_int64_179 = 179; + map field_map_uint32_message_180 = 180; + map field_map_uint32_sfixed32_181 = 181; + map field_map_uint32_sfixed64_182 = 182; + map field_map_uint32_sint32_183 = 183; + map field_map_uint32_sint64_184 = 184; + map field_map_uint32_string_185 = 185; + map field_map_uint32_uint32_186 = 186; + map field_map_uint32_uint64_187 = 187; + map field_map_uint64_bool_188 = 188; + map field_map_uint64_bytes_189 = 189; + map field_map_uint64_double_190 = 190; + map field_map_uint64_enum_191 = 191; + map field_map_uint64_fixed32_192 = 192; + map field_map_uint64_fixed64_193 = 193; + map field_map_uint64_float_194 = 194; + map field_map_uint64_int32_195 = 195; + map field_map_uint64_int64_196 = 196; + map field_map_uint64_message_197 = 197; + map field_map_uint64_sfixed32_198 = 198; + map field_map_uint64_sfixed64_199 = 199; + map field_map_uint64_sint32_200 = 200; + map field_map_uint64_sint64_201 = 201; + map field_map_uint64_string_202 = 202; + map field_map_uint64_uint32_203 = 203; + map field_map_uint64_uint64_204 = 204; +} 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 new file mode 100644 index 0000000000000..4a378b5bd3baa --- /dev/null +++ b/java/core/src/test/proto/com/google/protobuf/proto3_message_lite.proto @@ -0,0 +1,320 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package protobuf.experimental; + +option java_package = "com.google.protobuf.testing"; +option java_outer_classname = "Proto3TestingLite"; + +message Proto3MessageLite { + enum TestEnum { + ZERO = 0; + ONE = 1; + TWO = 2; + } + + 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; + Proto3MessageLite 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 [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]; + oneof test_oneof { + double field_double_53 = 53; + float field_float_54 = 54; + int64 field_int64_55 = 55; + uint64 field_uint64_56 = 56; + int32 field_int32_57 = 57; + fixed64 field_fixed64_58 = 58; + fixed32 field_fixed32_59 = 59; + bool field_bool_60 = 60; + string field_string_61 = 61; + Proto3MessageLite field_message_62 = 62; + bytes field_bytes_63 = 63; + uint32 field_uint32_64 = 64; + sfixed32 field_sfixed32_65 = 65; + sfixed64 field_sfixed64_66 = 66; + sint32 field_sint32_67 = 67; + sint64 field_sint64_68 = 68; + } +} + +message Proto3EmptyLite {} + +message Proto3MessageLiteWithMaps { + map field_map_bool_bool_1 = 1; + map field_map_bool_bytes_2 = 2; + map field_map_bool_double_3 = 3; + map field_map_bool_enum_4 = 4; + map field_map_bool_fixed32_5 = 5; + map field_map_bool_fixed64_6 = 6; + map field_map_bool_float_7 = 7; + map field_map_bool_int32_8 = 8; + map field_map_bool_int64_9 = 9; + map field_map_bool_message_10 = 10; + map field_map_bool_sfixed32_11 = 11; + map field_map_bool_sfixed64_12 = 12; + map field_map_bool_sint32_13 = 13; + map field_map_bool_sint64_14 = 14; + map field_map_bool_string_15 = 15; + map field_map_bool_uint32_16 = 16; + map field_map_bool_uint64_17 = 17; + map field_map_fixed32_bool_18 = 18; + map field_map_fixed32_bytes_19 = 19; + map field_map_fixed32_double_20 = 20; + map field_map_fixed32_enum_21 = 21; + map field_map_fixed32_fixed32_22 = 22; + map field_map_fixed32_fixed64_23 = 23; + map field_map_fixed32_float_24 = 24; + map field_map_fixed32_int32_25 = 25; + map field_map_fixed32_int64_26 = 26; + map field_map_fixed32_message_27 = 27; + map field_map_fixed32_sfixed32_28 = 28; + map field_map_fixed32_sfixed64_29 = 29; + map field_map_fixed32_sint32_30 = 30; + map field_map_fixed32_sint64_31 = 31; + map field_map_fixed32_string_32 = 32; + map field_map_fixed32_uint32_33 = 33; + map field_map_fixed32_uint64_34 = 34; + map field_map_fixed64_bool_35 = 35; + map field_map_fixed64_bytes_36 = 36; + map field_map_fixed64_double_37 = 37; + map field_map_fixed64_enum_38 = 38; + map field_map_fixed64_fixed32_39 = 39; + map field_map_fixed64_fixed64_40 = 40; + map field_map_fixed64_float_41 = 41; + map field_map_fixed64_int32_42 = 42; + map field_map_fixed64_int64_43 = 43; + map field_map_fixed64_message_44 = 44; + map field_map_fixed64_sfixed32_45 = 45; + map field_map_fixed64_sfixed64_46 = 46; + map field_map_fixed64_sint32_47 = 47; + map field_map_fixed64_sint64_48 = 48; + map field_map_fixed64_string_49 = 49; + map field_map_fixed64_uint32_50 = 50; + map field_map_fixed64_uint64_51 = 51; + map field_map_int32_bool_52 = 52; + map field_map_int32_bytes_53 = 53; + map field_map_int32_double_54 = 54; + map field_map_int32_enum_55 = 55; + map field_map_int32_fixed32_56 = 56; + map field_map_int32_fixed64_57 = 57; + map field_map_int32_float_58 = 58; + map field_map_int32_int32_59 = 59; + map field_map_int32_int64_60 = 60; + map field_map_int32_message_61 = 61; + map field_map_int32_sfixed32_62 = 62; + map field_map_int32_sfixed64_63 = 63; + map field_map_int32_sint32_64 = 64; + map field_map_int32_sint64_65 = 65; + map field_map_int32_string_66 = 66; + map field_map_int32_uint32_67 = 67; + map field_map_int32_uint64_68 = 68; + map field_map_int64_bool_69 = 69; + map field_map_int64_bytes_70 = 70; + map field_map_int64_double_71 = 71; + map field_map_int64_enum_72 = 72; + map field_map_int64_fixed32_73 = 73; + map field_map_int64_fixed64_74 = 74; + map field_map_int64_float_75 = 75; + map field_map_int64_int32_76 = 76; + map field_map_int64_int64_77 = 77; + map field_map_int64_message_78 = 78; + map field_map_int64_sfixed32_79 = 79; + map field_map_int64_sfixed64_80 = 80; + map field_map_int64_sint32_81 = 81; + map field_map_int64_sint64_82 = 82; + map field_map_int64_string_83 = 83; + map field_map_int64_uint32_84 = 84; + map field_map_int64_uint64_85 = 85; + map field_map_sfixed32_bool_86 = 86; + map field_map_sfixed32_bytes_87 = 87; + map field_map_sfixed32_double_88 = 88; + map field_map_sfixed32_enum_89 = 89; + map field_map_sfixed32_fixed32_90 = 90; + map field_map_sfixed32_fixed64_91 = 91; + map field_map_sfixed32_float_92 = 92; + map field_map_sfixed32_int32_93 = 93; + map field_map_sfixed32_int64_94 = 94; + map field_map_sfixed32_message_95 = 95; + map field_map_sfixed32_sfixed32_96 = 96; + map field_map_sfixed32_sfixed64_97 = 97; + map field_map_sfixed32_sint32_98 = 98; + map field_map_sfixed32_sint64_99 = 99; + map field_map_sfixed32_string_100 = 100; + map field_map_sfixed32_uint32_101 = 101; + map field_map_sfixed32_uint64_102 = 102; + map field_map_sfixed64_bool_103 = 103; + map field_map_sfixed64_bytes_104 = 104; + map field_map_sfixed64_double_105 = 105; + map field_map_sfixed64_enum_106 = 106; + map field_map_sfixed64_fixed32_107 = 107; + map field_map_sfixed64_fixed64_108 = 108; + map field_map_sfixed64_float_109 = 109; + map field_map_sfixed64_int32_110 = 110; + map field_map_sfixed64_int64_111 = 111; + map field_map_sfixed64_message_112 = 112; + map field_map_sfixed64_sfixed32_113 = 113; + map field_map_sfixed64_sfixed64_114 = 114; + map field_map_sfixed64_sint32_115 = 115; + map field_map_sfixed64_sint64_116 = 116; + map field_map_sfixed64_string_117 = 117; + map field_map_sfixed64_uint32_118 = 118; + map field_map_sfixed64_uint64_119 = 119; + map field_map_sint32_bool_120 = 120; + map field_map_sint32_bytes_121 = 121; + map field_map_sint32_double_122 = 122; + map field_map_sint32_enum_123 = 123; + map field_map_sint32_fixed32_124 = 124; + map field_map_sint32_fixed64_125 = 125; + map field_map_sint32_float_126 = 126; + map field_map_sint32_int32_127 = 127; + map field_map_sint32_int64_128 = 128; + map field_map_sint32_message_129 = 129; + map field_map_sint32_sfixed32_130 = 130; + map field_map_sint32_sfixed64_131 = 131; + map field_map_sint32_sint32_132 = 132; + map field_map_sint32_sint64_133 = 133; + map field_map_sint32_string_134 = 134; + map field_map_sint32_uint32_135 = 135; + map field_map_sint32_uint64_136 = 136; + map field_map_sint64_bool_137 = 137; + map field_map_sint64_bytes_138 = 138; + map field_map_sint64_double_139 = 139; + map field_map_sint64_enum_140 = 140; + map field_map_sint64_fixed32_141 = 141; + map field_map_sint64_fixed64_142 = 142; + map field_map_sint64_float_143 = 143; + map field_map_sint64_int32_144 = 144; + map field_map_sint64_int64_145 = 145; + map field_map_sint64_message_146 = 146; + map field_map_sint64_sfixed32_147 = 147; + map field_map_sint64_sfixed64_148 = 148; + map field_map_sint64_sint32_149 = 149; + map field_map_sint64_sint64_150 = 150; + map field_map_sint64_string_151 = 151; + map field_map_sint64_uint32_152 = 152; + map field_map_sint64_uint64_153 = 153; + map field_map_string_bool_154 = 154; + map field_map_string_bytes_155 = 155; + map field_map_string_double_156 = 156; + map field_map_string_enum_157 = 157; + map field_map_string_fixed32_158 = 158; + map field_map_string_fixed64_159 = 159; + map field_map_string_float_160 = 160; + map field_map_string_int32_161 = 161; + map field_map_string_int64_162 = 162; + map field_map_string_message_163 = 163; + map field_map_string_sfixed32_164 = 164; + map field_map_string_sfixed64_165 = 165; + map field_map_string_sint32_166 = 166; + map field_map_string_sint64_167 = 167; + map field_map_string_string_168 = 168; + map field_map_string_uint32_169 = 169; + map field_map_string_uint64_170 = 170; + map field_map_uint32_bool_171 = 171; + map field_map_uint32_bytes_172 = 172; + map field_map_uint32_double_173 = 173; + map field_map_uint32_enum_174 = 174; + map field_map_uint32_fixed32_175 = 175; + map field_map_uint32_fixed64_176 = 176; + map field_map_uint32_float_177 = 177; + map field_map_uint32_int32_178 = 178; + map field_map_uint32_int64_179 = 179; + map field_map_uint32_message_180 = 180; + map field_map_uint32_sfixed32_181 = 181; + map field_map_uint32_sfixed64_182 = 182; + map field_map_uint32_sint32_183 = 183; + map field_map_uint32_sint64_184 = 184; + map field_map_uint32_string_185 = 185; + map field_map_uint32_uint32_186 = 186; + map field_map_uint32_uint64_187 = 187; + map field_map_uint64_bool_188 = 188; + map field_map_uint64_bytes_189 = 189; + map field_map_uint64_double_190 = 190; + map field_map_uint64_enum_191 = 191; + map field_map_uint64_fixed32_192 = 192; + map field_map_uint64_fixed64_193 = 193; + map field_map_uint64_float_194 = 194; + map field_map_uint64_int32_195 = 195; + map field_map_uint64_int64_196 = 196; + map field_map_uint64_message_197 = 197; + map field_map_uint64_sfixed32_198 = 198; + map field_map_uint64_sfixed64_199 = 199; + map field_map_uint64_sint32_200 = 200; + map field_map_uint64_sint64_201 = 201; + map field_map_uint64_string_202 = 202; + map field_map_uint64_uint32_203 = 203; + map field_map_uint64_uint64_204 = 204; +} 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 ff5bf3ae21a0e..8bf16914313e5 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 @@ -37,10 +37,9 @@ syntax = "proto2"; // Some generic_services option(s) added automatically. // See: http://go/proto2-generic-services-default -option java_generic_services = true; // auto-added - package io_protocol_tests; +option java_generic_services = true; // auto-added option java_package = "com.google.protobuf"; option java_outer_classname = "TestBadIdentifiersProto"; @@ -52,9 +51,11 @@ message TestMessage { message Descriptor { option no_standard_descriptor_accessor = true; + optional string descriptor = 1; message NestedDescriptor { option no_standard_descriptor_accessor = true; + optional string descriptor = 1; } optional NestedDescriptor nested_descriptor = 2; @@ -78,12 +79,12 @@ message Deprecated { FOO = 1; // Test if @Deprecated annotation conflicts with Deprecated message name. - BAR = 2 [ deprecated = true ]; + BAR = 2 [deprecated = true]; } - optional int32 field1 = 1 [deprecated=true]; - optional TestEnum field2 = 2 [deprecated=true]; - optional TestMessage field3 = 3 [deprecated=true]; + optional int32 field1 = 1 [deprecated = true]; + optional TestEnum field2 = 2 [deprecated = true]; + optional TestMessage field3 = 3 [deprecated = true]; } message Override { @@ -124,8 +125,7 @@ message TestConflictingFieldNames { UNKNOWN = 0; FOO = 1; } - message TestMessage { - } + message TestMessage {} repeated int32 int32_field = 1; repeated TestEnum enum_field = 2; repeated string string_field = 3; @@ -138,10 +138,10 @@ message TestConflictingFieldNames { optional bytes bytes_field_count = 14; optional TestMessage message_field_count = 15; - repeated int32 Int32Field = 21; // NO_PROTO3 - repeated TestEnum EnumField = 22; // NO_PROTO3 - repeated string StringField = 23; // NO_PROTO3 - repeated bytes BytesField = 24; // NO_PROTO3 + repeated int32 Int32Field = 21; // NO_PROTO3 + repeated TestEnum EnumField = 22; // NO_PROTO3 + repeated string StringField = 23; // NO_PROTO3 + repeated bytes BytesField = 24; // NO_PROTO3 repeated TestMessage MessageField = 25; // NO_PROTO3 // This field conflicts with "int32_field" as they both generate @@ -149,9 +149,9 @@ message TestConflictingFieldNames { required int32 int32_field_list = 31; // 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 string field_name = 32; // NO_PROTO3 + optional string field__name = 33; // NO_PROTO3 + optional int32 _2conflict = 34; // NO_PROTO3 optional int32 __2conflict = 35; extensions 1000 to max; // NO_PROTO3 @@ -161,8 +161,8 @@ message TestConflictingFieldNames { // 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 + optional int64 int64_field_list = 1002; // NO_PROTO3 + } // NO_PROTO3 } message TestMapField { diff --git a/java/core/src/test/proto/com/google/protobuf/test_custom_options.proto b/java/core/src/test/proto/com/google/protobuf/test_custom_options.proto index f8efd455a1eb2..dde4ca5616b09 100644 --- a/java/core/src/test/proto/com/google/protobuf/test_custom_options.proto +++ b/java/core/src/test/proto/com/google/protobuf/test_custom_options.proto @@ -36,9 +36,9 @@ syntax = "proto2"; package protobuf_unittest; - import "google/protobuf/unittest_custom_options.proto"; + message TestMessageWithCustomOptionsContainer { optional TestMessageWithCustomOptions field = 1; } diff --git a/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto b/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto index 645f57b4bb43f..d41b7a11ccdce 100644 --- a/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto +++ b/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto @@ -36,13 +36,8 @@ package protobuf_unittest; message Proto1 { option experimental_java_message_interface = "com.google.protobuf.ExtraInterfaces.HasBoolValue"; - - option experimental_java_interface_extends = - "com.google.protobuf.ExtraInterfaces.HasByteValue"; - option experimental_java_message_interface = "com.google.protobuf.ExtraInterfaces.HasStringValue"; - option experimental_java_builder_interface = "com.google.protobuf.ExtraInterfaces.HasStringValueBuilder" ""; 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 new file mode 100644 index 0000000000000..60f49e08c7c55 --- /dev/null +++ b/java/core/src/test/proto/com/google/protobuf/wrappers_test.proto @@ -0,0 +1,51 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package wrappers_test; + +import "google/protobuf/wrappers.proto"; + +option java_package = "com.google.protobuf.wrapperstest"; +option java_outer_classname = "WrappersTestProto"; + +message TopLevelMessage { + int32 field1 = 1; + .google.protobuf.DoubleValue field_double = 2; + .google.protobuf.FloatValue field_float = 3; + .google.protobuf.Int64Value field_int64 = 4; + .google.protobuf.UInt64Value field_uint64 = 5; + .google.protobuf.Int32Value field_int32 = 6; + .google.protobuf.UInt32Value field_uint32 = 7; + .google.protobuf.BoolValue field_bool = 8; + .google.protobuf.StringValue field_string = 9; + .google.protobuf.BytesValue field_bytes = 10; +} diff --git a/java/lite.md b/java/lite.md new file mode 100644 index 0000000000000..f248ff6c3e82d --- /dev/null +++ b/java/lite.md @@ -0,0 +1,55 @@ +# Protocol Buffers - Google's data interchange format + +Copyright 2008 Google Inc. + +https://developers.google.com/protocol-buffers/ + +## Use Protobuf Java Lite Runtime + +Protobuf Java Lite runtime is separated from the main Java runtime because +it's designed/implemented with different constraints. In particular, Java +Lite runtime has a much smaller code size which makes it more suitable to +be used on Android. + +Note that in order to achieve maximum performance and code size, we will +NOT guarantee API/ABI stability for Java Lite. If this is not acceptable +for your use-case, please use the full Java runtime instead. Note that +the latest version of Java Lite is not compatible with the 3.0.0 version. + +You can generate Java Lite code for your .proto files: + + $ protoc --java_out=lite:${OUTPUT_DIR} path/to/your/proto/file + +Note that "optimize_for = LITE_RUNTIME" option in proto file is deprecated +and will not have any effect any more. + +Include the generated Java files in your project and add a dependency on the +protobuf Java runtime. If you are using Maven, use the following: + +```xml + + com.google.protobuf + protobuf-javalite + 3.9.1 + +``` + +## R8 rule to make production app builds work + +The Lite runtime internally uses reflection to avoid generating hashCode/equals/(de)serialization methods. +R8 by default obfuscates the field names, which makes the reflection fail causing exceptions of the form +`java.lang.RuntimeException: Field {NAME}_ for {CLASS} not found. Known fields are [ {FIELDS} ]` in MessageSchema.java. + +There are open issues for this on the [protobuf Github project](https://github.com/protocolbuffers/protobuf/issues/6463) and [R8](https://issuetracker.google.com/issues/144631039). + +Until the issues is resolved you need to add the following line to your `proguard-rules.pro` file inside your project: + +``` +-keep class * extends com.google.protobuf.GeneratedMessageLite { *; } +``` + +## Older versions + +For the older version of Java Lite (v3.0.0), please refer to: + + https://github.com/protocolbuffers/protobuf/blob/javalite/java/lite.md diff --git a/java/lite/BUILD b/java/lite/BUILD new file mode 100644 index 0000000000000..22840ec48c8a3 --- /dev/null +++ b/java/lite/BUILD @@ -0,0 +1,14 @@ +load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain") + +alias( + name = "lite", + actual = "//java/core:lite", + visibility = ["//visibility:public"], +) + +proto_lang_toolchain( + name = "toolchain", + command_line = "--java_out=lite:$(OUT)", + runtime = ":lite", + visibility = ["//visibility:public"], +) diff --git a/java/lite/generate-sources-build.xml b/java/lite/generate-sources-build.xml index 89c21c131555e..74d96a2f10538 100644 --- a/java/lite/generate-sources-build.xml +++ b/java/lite/generate-sources-build.xml @@ -1,12 +1,11 @@ - + - + - @@ -15,6 +14,6 @@ - + diff --git a/java/lite/generate-test-sources-build.xml b/java/lite/generate-test-sources-build.xml index cdd1ee89a7119..62bca93c86f9f 100644 --- a/java/lite/generate-test-sources-build.xml +++ b/java/lite/generate-test-sources-build.xml @@ -1,43 +1,51 @@ - + - + - + + + + - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/lite/lite.awk b/java/lite/lite.awk new file mode 100644 index 0000000000000..b22d965b6fd02 --- /dev/null +++ b/java/lite/lite.awk @@ -0,0 +1,25 @@ +# Remove code enclosed by "BEGIN FULL-RUNTIME" and "END FULL-RUNTIME" to +# create the lite-only version of a test file. + +BEGIN { + in_full_runtime = 0; +} + +/BEGIN FULL-RUNTIME/ { + in_full_runtime = 1; + next; +} + +/END FULL-RUNTIME/ { + in_full_runtime = 0; + next; +} + +in_full_runtime { + # Skip full runtime code path. + next; +} + +{ + print; +} diff --git a/java/lite/pom.xml b/java/lite/pom.xml index c902f8192a191..fd313daf51bc6 100644 --- a/java/lite/pom.xml +++ b/java/lite/pom.xml @@ -1,45 +1,249 @@ - + 4.0.0 com.google.protobuf protobuf-parent - 3.0.0 + 3.15.0 - protobuf-lite + protobuf-javalite bundle Protocol Buffers [Lite] - A trimmed-down version of the Protocol Buffers library. + + Lite version of Protocol Buffers library. This version is optimized for code size, but does + not guarantee API/ABI stability. + junit junit + test org.easymock easymock + test org.easymock easymockclassextension + test + + + com.google.guava + guava + test + + + com.google.truth + truth + test - - ../core - ${core.root}/src/test/proto - - - ${core.root}/src/main/java - ${core.root}/src/test/java + + + + ${protobuf.source.dir} + + google/protobuf/any.proto + google/protobuf/api.proto + google/protobuf/duration.proto + google/protobuf/empty.proto + google/protobuf/field_mask.proto + google/protobuf/source_context.proto + google/protobuf/struct.proto + google/protobuf/timestamp.proto + google/protobuf/type.proto + google/protobuf/wrappers.proto + + + + + + ${protobuf.source.dir} + + google/protobuf/testdata/golden_message_oneof_implemented + google/protobuf/testdata/golden_packed_fields_message + + + + + maven-resources-plugin + 3.1.0 + + + copy-source-files + generate-sources + + copy-resources + + + ${generated.sources.dir}/com/google/protobuf + + + ${basedir}/../core/src/main/java/com/google/protobuf + + + AbstractMessageLite.java + AbstractParser.java + AbstractProtobufList.java + AllocatedBuffer.java + Android.java + ArrayDecoders.java + BinaryReader.java + BinaryWriter.java + BooleanArrayList.java + BufferAllocator.java + ByteBufferWriter.java + ByteOutput.java + ByteString.java + CodedInputStream.java + CodedInputStreamReader.java + CodedOutputStream.java + CodedOutputStreamWriter.java + DoubleArrayList.java + ExperimentalApi.java + ExtensionLite.java + ExtensionRegistryFactory.java + ExtensionRegistryLite.java + ExtensionSchema.java + ExtensionSchemaLite.java + ExtensionSchemas.java + FieldInfo.java + FieldSet.java + FieldType.java + FloatArrayList.java + GeneratedMessageInfoFactory.java + GeneratedMessageLite.java + IntArrayList.java + Internal.java + InvalidProtocolBufferException.java + IterableByteBufferInputStream.java + JavaType.java + LazyField.java + LazyFieldLite.java + LazyStringArrayList.java + LazyStringList.java + ListFieldSchema.java + LongArrayList.java + ManifestSchemaFactory.java + MapEntryLite.java + MapFieldLite.java + MapFieldSchema.java + MapFieldSchemaLite.java + MapFieldSchemas.java + MessageInfo.java + MessageInfoFactory.java + MessageLite.java + MessageLiteOrBuilder.java + MessageLiteToString.java + MessageSchema.java + MessageSetSchema.java + MutabilityOracle.java + NewInstanceSchema.java + NewInstanceSchemaLite.java + NewInstanceSchemas.java + NioByteString.java + OneofInfo.java + Parser.java + PrimitiveNonBoxingCollection.java + ProtoSyntax.java + Protobuf.java + ProtobufArrayList.java + ProtobufLists.java + ProtocolStringList.java + RawMessageInfo.java + Reader.java + RopeByteString.java + Schema.java + SchemaFactory.java + SchemaUtil.java + SmallSortedMap.java + StructuralMessageInfo.java + TextFormatEscaper.java + UninitializedMessageException.java + UnknownFieldSchema.java + UnknownFieldSetLite.java + UnknownFieldSetLiteSchema.java + UnmodifiableLazyStringList.java + UnsafeUtil.java + Utf8.java + WireFormat.java + Writer.java + + + + + + + copy-test-source-files + generate-test-sources + + copy-resources + + + ${generated.testsources.dir}/com/google/protobuf + + + ${basedir}/../core/src/test/java/com/google/protobuf + + + AbstractMessageTest.java + AbstractProto2SchemaTest.java + AnyTest.java + CodedInputStreamTest.java + DeprecatedFieldTest.java + DescriptorsTest.java + DiscardUnknownFieldsTest.java + DynamicMessageTest.java + ExtensionRegistryFactoryTest.java + FieldPresenceTest.java + ForceFieldBuildersPreRun.java + GeneratedMessageTest.java + LazyFieldTest.java + LazyStringEndToEndTest.java + MapForProto2Test.java + MapTest.java + MessageTest.java + NestedBuildersTest.java + PackedFieldTest.java + ParserTest.java + ParseExceptionsTest.java + Proto2ExtensionLookupSchemaTest.java + Proto2SchemaTest.java + Proto2UnknownEnumValueTest.java + RepeatedFieldBuilderV3Test.java + ServiceTest.java + SingleFieldBuilderV3Test.java + TestBadIdentifiers.java + TextFormatParseInfoTreeTest.java + TextFormatParseLocationTest.java + TextFormatTest.java + TestUtil.java + TypeRegistryTest.java + UnknownEnumValueTest.java + UnknownFieldSetLiteTest.java + UnknownFieldSetTest.java + WellKnownTypesTest.java + WireFormatTest.java + + + + + + + + maven-antrun-plugin @@ -71,10 +275,22 @@ run + + + process-lite-sources + generate-test-sources + + + + + + + run + + - org.codehaus.mojo build-helper-maven-plugin @@ -87,10 +303,11 @@ - ${generated.sources.lite.dir} + ${generated.sources.dir} + add-generated-test-sources generate-test-sources @@ -99,72 +316,12 @@ - ${generated.testsources.lite.dir} + ${generated.testsources.dir} - - maven-compiler-plugin - - - **/AbstractMessageLite.java - **/AbstractParser.java - **/AbstractProtobufList.java - **/BooleanArrayList.java - **/ByteString.java - **/CodedInputStream.java - **/CodedOutputStream.java - **/DoubleArrayList.java - **/ExtensionLite.java - **/ExtensionRegistryLite.java - **/FieldSet.java - **/FloatArrayList.java - **/GeneratedMessageLite.java - **/IntArrayList.java - **/Internal.java - **/InvalidProtocolBufferException.java - **/LazyFieldLite.java - **/LazyStringArrayList.java - **/LazyStringList.java - **/LongArrayList.java - **/MapEntryLite.java - **/MapFieldLite.java - **/MessageLite.java - **/MessageLiteOrBuilder.java - **/MessageLiteToString.java - **/MutabilityOracle.java - **/NioByteString.java - **/Parser.java - **/PrimitiveNonBoxingCollection.java - **/ProtobufArrayList.java - **/ProtocolStringList.java - **/RopeByteString.java - **/SmallSortedMap.java - **/TextFormatEscaper.java - **/UninitializedMessageException.java - **/UnknownFieldSetLite.java - **/UnmodifiableLazyStringList.java - **/UnsafeByteOperations.java - **/Utf8.java - **/WireFormat.java - - - **/*Lite.java - **/BooleanArrayListTest.java - **/DoubleArrayListTest.java - **/FloatArrayListTest.java - **/IntArrayListTest.java - **/LazyMessageLiteTest.java - **/LiteTest.java - **/LongArrayListTest.java - **/NioByteStringTest.java - **/ProtobufArrayListTest.java - **/UnknownFieldSetLiteTest.java - - - @@ -173,9 +330,11 @@ true + com.google.protobuf https://developers.google.com/protocol-buffers/ com.google.protobuf - com.google.${project.artifactId};version=${project.version} + com.google.protobuf;version=${project.version} + sun.misc;resolution:=optional,* diff --git a/java/lite/process-lite-sources-build.xml b/java/lite/process-lite-sources-build.xml new file mode 100644 index 0000000000000..d49cf3aac03f1 --- /dev/null +++ b/java/lite/process-lite-sources-build.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/java/lite/proguard.pgcfg b/java/lite/proguard.pgcfg new file mode 100644 index 0000000000000..54c798c87d71c --- /dev/null +++ b/java/lite/proguard.pgcfg @@ -0,0 +1,8 @@ + +# Skip runtime check for isOnAndroidDevice(). +# One line to make it easy to remove with sed. +-assumevalues class com.google.protobuf.Android { static boolean ASSUME_ANDROID return true; } + +-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite { + ; +} diff --git a/java/lite/src/test/java/com/google/protobuf/LiteTest.java b/java/lite/src/test/java/com/google/protobuf/LiteTest.java new file mode 100644 index 0000000000000..140df7270fc25 --- /dev/null +++ b/java/lite/src/test/java/com/google/protobuf/LiteTest.java @@ -0,0 +1,2503 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; + +import com.google.protobuf.FieldPresenceTestProto.TestAllTypes; +import com.google.protobuf.UnittestImportLite.ImportEnumLite; +import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite; +import com.google.protobuf.UnittestLite.ForeignEnumLite; +import com.google.protobuf.UnittestLite.ForeignMessageLite; +import com.google.protobuf.UnittestLite.TestAllExtensionsLite; +import com.google.protobuf.UnittestLite.TestAllTypesLite; +import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedEnum; +import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedMessage; +import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedMessage2; +import com.google.protobuf.UnittestLite.TestAllTypesLite.OneofFieldCase; +import com.google.protobuf.UnittestLite.TestAllTypesLite.OptionalGroup; +import com.google.protobuf.UnittestLite.TestAllTypesLite.RepeatedGroup; +import com.google.protobuf.UnittestLite.TestAllTypesLiteOrBuilder; +import com.google.protobuf.UnittestLite.TestHugeFieldNumbersLite; +import com.google.protobuf.UnittestLite.TestNestedExtensionLite; +import map_lite_test.MapTestProto.TestMap; +import map_lite_test.MapTestProto.TestMap.MessageValue; +import protobuf_unittest.NestedExtensionLite; +import protobuf_unittest.NonNestedExtensionLite; +import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar; +import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.BarPrime; +import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo; +import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestOneofEquals; +import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestRecursiveOneof; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import junit.framework.TestCase; + +/** + * Test lite runtime. + * + * @author kenton@google.com Kenton Varda + */ +public class LiteTest extends TestCase { + @Override + public void setUp() throws Exception { + // Test that nested extensions are initialized correctly even if the outer + // class has not been accessed directly. This was once a bug with lite + // messages. + // + // We put this in setUp() rather than in its own test method because we + // need to make sure it runs before any actual tests. + assertNotNull(TestNestedExtensionLite.nestedExtension); + } + + public void testLite() throws Exception { + // Since lite messages are a subset of regular messages, we can mostly + // assume that the functionality of lite messages is already thoroughly + // tested by the regular tests. All this test really verifies is that + // a proto with optimize_for = LITE_RUNTIME compiles correctly when + // linked only against the lite library. That is all tested at compile + // time, leaving not much to do in this method. Let's just do some random + // stuff to make sure the lite message is actually here and usable. + + TestAllTypesLite message = + TestAllTypesLite.newBuilder() + .setOptionalInt32(123) + .addRepeatedString("hello") + .setOptionalNestedMessage(NestedMessage.newBuilder().setBb(7)) + .build(); + + ByteString data = message.toByteString(); + + TestAllTypesLite message2 = TestAllTypesLite.parseFrom(data); + + assertEquals(123, message2.getOptionalInt32()); + assertEquals(1, message2.getRepeatedStringCount()); + assertEquals("hello", message2.getRepeatedString(0)); + assertEquals(7, message2.getOptionalNestedMessage().getBb()); + } + + public void testLite_unknownEnumAtListBoundary() throws Exception { + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + CodedOutputStream output = CodedOutputStream.newInstance(byteStream); + for (int i = 0; i < AbstractProtobufList.DEFAULT_CAPACITY; i++) { + output.writeInt32(TestAllTypesLite.REPEATED_NESTED_ENUM_FIELD_NUMBER, 1); + } + // 0 is not a valid enum value for NestedEnum + output.writeInt32(TestAllTypesLite.REPEATED_NESTED_ENUM_FIELD_NUMBER, 0); + output.flush(); + // This tests a bug we had once with removal right at the boundary of the array. It would throw + // at runtime so no need to assert. + TestAllTypesLite.parseFrom(new ByteArrayInputStream(byteStream.toByteArray())); + } + + public void testLiteExtensions() throws Exception { + // TODO(kenton): Unlike other features of the lite library, extensions are + // implemented completely differently from the regular library. We + // should probably test them more thoroughly. + + TestAllExtensionsLite message = + TestAllExtensionsLite.newBuilder() + .setExtension(UnittestLite.optionalInt32ExtensionLite, 123) + .addExtension(UnittestLite.repeatedStringExtensionLite, "hello") + .setExtension(UnittestLite.optionalNestedEnumExtensionLite, NestedEnum.BAZ) + .setExtension( + UnittestLite.optionalNestedMessageExtensionLite, + NestedMessage.newBuilder().setBb(7).build()) + .build(); + + // Test copying a message, since coping extensions actually does use a + // different code path between lite and regular libraries, and as of this + // writing, parsing hasn't been implemented yet. + TestAllExtensionsLite message2 = message.toBuilder().build(); + + assertEquals(123, (int) message2.getExtension(UnittestLite.optionalInt32ExtensionLite)); + assertEquals(1, message2.getExtensionCount(UnittestLite.repeatedStringExtensionLite)); + assertEquals(1, message2.getExtension(UnittestLite.repeatedStringExtensionLite).size()); + assertEquals("hello", message2.getExtension(UnittestLite.repeatedStringExtensionLite, 0)); + assertEquals( + NestedEnum.BAZ, message2.getExtension(UnittestLite.optionalNestedEnumExtensionLite)); + assertEquals(7, message2.getExtension(UnittestLite.optionalNestedMessageExtensionLite).getBb()); + } + + public void testClone() { + TestAllTypesLite.Builder expected = TestAllTypesLite.newBuilder().setOptionalInt32(123); + assertEquals(expected.getOptionalInt32(), expected.clone().getOptionalInt32()); + + TestAllExtensionsLite.Builder expected2 = + TestAllExtensionsLite.newBuilder() + .setExtension(UnittestLite.optionalInt32ExtensionLite, 123); + assertEquals( + expected2.getExtension(UnittestLite.optionalInt32ExtensionLite), + expected2.clone().getExtension(UnittestLite.optionalInt32ExtensionLite)); + } + + public void testAddAll() { + try { + TestAllTypesLite.newBuilder().addAllRepeatedBytes(null); + fail(); + } catch (NullPointerException e) { + // expected. + } + } + + public void testMemoization() throws Exception { + TestAllExtensionsLite message = TestUtilLite.getAllLiteExtensionsSet(); + + // Test serialized size is memoized + message.memoizedSerializedSize = -1; + int size = message.getSerializedSize(); + assertTrue(size > 0); + assertEquals(size, message.memoizedSerializedSize); + + // Test hashCode is memoized + assertEquals(0, message.memoizedHashCode); + int hashCode = message.hashCode(); + assertTrue(hashCode != 0); + assertEquals(hashCode, message.memoizedHashCode); + + // Test isInitialized is memoized + Field memo = message.getClass().getDeclaredField("memoizedIsInitialized"); + memo.setAccessible(true); + memo.set(message, (byte) -1); + boolean initialized = message.isInitialized(); + assertTrue(initialized); + // We have to cast to Byte first. Casting to byte causes a type error + assertEquals(1, ((Byte) memo.get(message)).intValue()); + } + + public void testSanityCopyOnWrite() throws InvalidProtocolBufferException { + // Since builders are implemented as a thin wrapper around a message + // instance, we attempt to verify that we can't cause the builder to modify + // a produced message. + + TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder(); + TestAllTypesLite message = builder.build(); + TestAllTypesLite messageAfterBuild; + builder.setOptionalBool(true); + assertEquals(false, message.getOptionalBool()); + assertEquals(true, builder.getOptionalBool()); + messageAfterBuild = builder.build(); + assertEquals(true, messageAfterBuild.getOptionalBool()); + assertEquals(false, message.getOptionalBool()); + builder.clearOptionalBool(); + assertEquals(false, builder.getOptionalBool()); + assertEquals(true, messageAfterBuild.getOptionalBool()); + + message = builder.build(); + builder.setOptionalBytes(ByteString.copyFromUtf8("hi")); + assertEquals(ByteString.EMPTY, message.getOptionalBytes()); + assertEquals(ByteString.copyFromUtf8("hi"), builder.getOptionalBytes()); + messageAfterBuild = builder.build(); + assertEquals(ByteString.copyFromUtf8("hi"), messageAfterBuild.getOptionalBytes()); + assertEquals(ByteString.EMPTY, message.getOptionalBytes()); + builder.clearOptionalBytes(); + assertEquals(ByteString.EMPTY, builder.getOptionalBytes()); + assertEquals(ByteString.copyFromUtf8("hi"), messageAfterBuild.getOptionalBytes()); + + message = builder.build(); + builder.setOptionalCord("hi"); + assertEquals("", message.getOptionalCord()); + assertEquals("hi", builder.getOptionalCord()); + messageAfterBuild = builder.build(); + assertEquals("hi", messageAfterBuild.getOptionalCord()); + assertEquals("", message.getOptionalCord()); + builder.clearOptionalCord(); + assertEquals("", builder.getOptionalCord()); + assertEquals("hi", messageAfterBuild.getOptionalCord()); + + message = builder.build(); + builder.setOptionalCordBytes(ByteString.copyFromUtf8("no")); + assertEquals(ByteString.EMPTY, message.getOptionalCordBytes()); + assertEquals(ByteString.copyFromUtf8("no"), builder.getOptionalCordBytes()); + messageAfterBuild = builder.build(); + assertEquals(ByteString.copyFromUtf8("no"), messageAfterBuild.getOptionalCordBytes()); + assertEquals(ByteString.EMPTY, message.getOptionalCordBytes()); + builder.clearOptionalCord(); + assertEquals(ByteString.EMPTY, builder.getOptionalCordBytes()); + assertEquals(ByteString.copyFromUtf8("no"), messageAfterBuild.getOptionalCordBytes()); + + message = builder.build(); + builder.setOptionalDouble(1); + assertEquals(0D, message.getOptionalDouble(), 0.0); + assertEquals(1D, builder.getOptionalDouble(), 0.0); + messageAfterBuild = builder.build(); + assertEquals(1D, messageAfterBuild.getOptionalDouble(), 0.0); + assertEquals(0D, message.getOptionalDouble(), 0.0); + builder.clearOptionalDouble(); + assertEquals(0D, builder.getOptionalDouble(), 0.0); + assertEquals(1D, messageAfterBuild.getOptionalDouble(), 0.0); + + message = builder.build(); + builder.setOptionalFixed32(1); + assertEquals(0, message.getOptionalFixed32()); + assertEquals(1, builder.getOptionalFixed32()); + messageAfterBuild = builder.build(); + assertEquals(1, messageAfterBuild.getOptionalFixed32()); + assertEquals(0, message.getOptionalFixed32()); + builder.clearOptionalFixed32(); + assertEquals(0, builder.getOptionalFixed32()); + assertEquals(1, messageAfterBuild.getOptionalFixed32()); + + message = builder.build(); + builder.setOptionalFixed64(1); + assertEquals(0L, message.getOptionalFixed64()); + assertEquals(1L, builder.getOptionalFixed64()); + messageAfterBuild = builder.build(); + assertEquals(1L, messageAfterBuild.getOptionalFixed64()); + assertEquals(0L, message.getOptionalFixed64()); + builder.clearOptionalFixed64(); + assertEquals(0L, builder.getOptionalFixed64()); + assertEquals(1L, messageAfterBuild.getOptionalFixed64()); + + message = builder.build(); + builder.setOptionalFloat(1); + assertEquals(0F, message.getOptionalFloat(), 0.0f); + assertEquals(1F, builder.getOptionalFloat(), 0.0f); + messageAfterBuild = builder.build(); + assertEquals(1F, messageAfterBuild.getOptionalFloat(), 0.0f); + assertEquals(0F, message.getOptionalFloat(), 0.0f); + builder.clearOptionalFloat(); + assertEquals(0F, builder.getOptionalFloat(), 0.0f); + assertEquals(1F, messageAfterBuild.getOptionalFloat(), 0.0f); + + message = builder.build(); + builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR); + assertEquals(ForeignEnumLite.FOREIGN_LITE_FOO, message.getOptionalForeignEnum()); + assertEquals(ForeignEnumLite.FOREIGN_LITE_BAR, builder.getOptionalForeignEnum()); + messageAfterBuild = builder.build(); + assertEquals(ForeignEnumLite.FOREIGN_LITE_BAR, messageAfterBuild.getOptionalForeignEnum()); + assertEquals(ForeignEnumLite.FOREIGN_LITE_FOO, message.getOptionalForeignEnum()); + builder.clearOptionalForeignEnum(); + assertEquals(ForeignEnumLite.FOREIGN_LITE_FOO, builder.getOptionalForeignEnum()); + assertEquals(ForeignEnumLite.FOREIGN_LITE_BAR, messageAfterBuild.getOptionalForeignEnum()); + + message = builder.build(); + ForeignMessageLite foreignMessage = ForeignMessageLite.newBuilder().setC(1).build(); + builder.setOptionalForeignMessage(foreignMessage); + assertEquals(ForeignMessageLite.getDefaultInstance(), message.getOptionalForeignMessage()); + assertEquals(foreignMessage, builder.getOptionalForeignMessage()); + messageAfterBuild = builder.build(); + assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage()); + assertEquals(ForeignMessageLite.getDefaultInstance(), message.getOptionalForeignMessage()); + builder.clearOptionalForeignMessage(); + assertEquals(ForeignMessageLite.getDefaultInstance(), builder.getOptionalForeignMessage()); + assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage()); + + message = builder.build(); + ForeignMessageLite foreignMessageC3 = ForeignMessageLite.newBuilder().setC(3).build(); + builder.setOptionalForeignMessage(foreignMessageC3); + assertEquals(ForeignMessageLite.getDefaultInstance(), message.getOptionalForeignMessage()); + assertEquals(foreignMessageC3, builder.getOptionalForeignMessage()); + messageAfterBuild = builder.build(); + assertEquals(foreignMessageC3, messageAfterBuild.getOptionalForeignMessage()); + assertEquals(ForeignMessageLite.getDefaultInstance(), message.getOptionalForeignMessage()); + builder.clearOptionalForeignMessage(); + assertEquals(ForeignMessageLite.getDefaultInstance(), builder.getOptionalForeignMessage()); + assertEquals(foreignMessageC3, messageAfterBuild.getOptionalForeignMessage()); + + message = builder.build(); + OptionalGroup optionalGroup = OptionalGroup.newBuilder().setA(1).build(); + builder.setOptionalGroup(optionalGroup); + assertEquals(OptionalGroup.getDefaultInstance(), message.getOptionalGroup()); + assertEquals(optionalGroup, builder.getOptionalGroup()); + messageAfterBuild = builder.build(); + assertEquals(optionalGroup, messageAfterBuild.getOptionalGroup()); + assertEquals(OptionalGroup.getDefaultInstance(), message.getOptionalGroup()); + builder.clearOptionalGroup(); + assertEquals(OptionalGroup.getDefaultInstance(), builder.getOptionalGroup()); + assertEquals(optionalGroup, messageAfterBuild.getOptionalGroup()); + + message = builder.build(); + OptionalGroup.Builder optionalGroupBuilder = OptionalGroup.newBuilder().setA(3); + builder.setOptionalGroup(optionalGroupBuilder); + assertEquals(OptionalGroup.getDefaultInstance(), message.getOptionalGroup()); + assertEquals(optionalGroupBuilder.build(), builder.getOptionalGroup()); + messageAfterBuild = builder.build(); + assertEquals(optionalGroupBuilder.build(), messageAfterBuild.getOptionalGroup()); + assertEquals(OptionalGroup.getDefaultInstance(), message.getOptionalGroup()); + builder.clearOptionalGroup(); + assertEquals(OptionalGroup.getDefaultInstance(), builder.getOptionalGroup()); + assertEquals(optionalGroupBuilder.build(), messageAfterBuild.getOptionalGroup()); + + message = builder.build(); + builder.setOptionalInt32(1); + assertEquals(0, message.getOptionalInt32()); + assertEquals(1, builder.getOptionalInt32()); + messageAfterBuild = builder.build(); + assertEquals(1, messageAfterBuild.getOptionalInt32()); + assertEquals(0, message.getOptionalInt32()); + builder.clearOptionalInt32(); + assertEquals(0, builder.getOptionalInt32()); + assertEquals(1, messageAfterBuild.getOptionalInt32()); + + message = builder.build(); + builder.setOptionalInt64(1); + assertEquals(0L, message.getOptionalInt64()); + assertEquals(1L, builder.getOptionalInt64()); + messageAfterBuild = builder.build(); + assertEquals(1L, messageAfterBuild.getOptionalInt64()); + assertEquals(0L, message.getOptionalInt64()); + builder.clearOptionalInt64(); + assertEquals(0L, builder.getOptionalInt64()); + assertEquals(1L, messageAfterBuild.getOptionalInt64()); + + message = builder.build(); + NestedMessage nestedMessage = NestedMessage.newBuilder().setBb(1).build(); + builder.setOptionalLazyMessage(nestedMessage); + assertEquals(NestedMessage.getDefaultInstance(), message.getOptionalLazyMessage()); + assertEquals(nestedMessage, builder.getOptionalLazyMessage()); + messageAfterBuild = builder.build(); + assertEquals(nestedMessage, messageAfterBuild.getOptionalLazyMessage()); + assertEquals(NestedMessage.getDefaultInstance(), message.getOptionalLazyMessage()); + builder.clearOptionalLazyMessage(); + assertEquals(NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage()); + assertEquals(nestedMessage, messageAfterBuild.getOptionalLazyMessage()); + + message = builder.build(); + NestedMessage.Builder nestedMessageBuilder = NestedMessage.newBuilder().setBb(3); + builder.setOptionalLazyMessage(nestedMessageBuilder); + assertEquals(NestedMessage.getDefaultInstance(), message.getOptionalLazyMessage()); + assertEquals(nestedMessageBuilder.build(), builder.getOptionalLazyMessage()); + messageAfterBuild = builder.build(); + assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getOptionalLazyMessage()); + assertEquals(NestedMessage.getDefaultInstance(), message.getOptionalLazyMessage()); + builder.clearOptionalLazyMessage(); + assertEquals(NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage()); + assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getOptionalLazyMessage()); + + message = builder.build(); + builder.setOptionalSfixed32(1); + assertEquals(0, message.getOptionalSfixed32()); + assertEquals(1, builder.getOptionalSfixed32()); + messageAfterBuild = builder.build(); + assertEquals(1, messageAfterBuild.getOptionalSfixed32()); + assertEquals(0, message.getOptionalSfixed32()); + builder.clearOptionalSfixed32(); + assertEquals(0, builder.getOptionalSfixed32()); + assertEquals(1, messageAfterBuild.getOptionalSfixed32()); + + message = builder.build(); + builder.setOptionalSfixed64(1); + assertEquals(0L, message.getOptionalSfixed64()); + assertEquals(1L, builder.getOptionalSfixed64()); + messageAfterBuild = builder.build(); + assertEquals(1L, messageAfterBuild.getOptionalSfixed64()); + assertEquals(0L, message.getOptionalSfixed64()); + builder.clearOptionalSfixed64(); + assertEquals(0L, builder.getOptionalSfixed64()); + assertEquals(1L, messageAfterBuild.getOptionalSfixed64()); + + message = builder.build(); + builder.setOptionalSint32(1); + assertEquals(0, message.getOptionalSint32()); + assertEquals(1, builder.getOptionalSint32()); + messageAfterBuild = builder.build(); + assertEquals(1, messageAfterBuild.getOptionalSint32()); + builder.clearOptionalSint32(); + assertEquals(0, builder.getOptionalSint32()); + assertEquals(1, messageAfterBuild.getOptionalSint32()); + + message = builder.build(); + builder.setOptionalSint64(1); + assertEquals(0L, message.getOptionalSint64()); + assertEquals(1L, builder.getOptionalSint64()); + messageAfterBuild = builder.build(); + assertEquals(1L, messageAfterBuild.getOptionalSint64()); + assertEquals(0L, message.getOptionalSint64()); + builder.clearOptionalSint64(); + assertEquals(0L, builder.getOptionalSint64()); + assertEquals(1L, messageAfterBuild.getOptionalSint64()); + + message = builder.build(); + builder.setOptionalString("hi"); + assertEquals("", message.getOptionalString()); + assertEquals("hi", builder.getOptionalString()); + messageAfterBuild = builder.build(); + assertEquals("hi", messageAfterBuild.getOptionalString()); + assertEquals("", message.getOptionalString()); + builder.clearOptionalString(); + assertEquals("", builder.getOptionalString()); + assertEquals("hi", messageAfterBuild.getOptionalString()); + + message = builder.build(); + builder.setOptionalStringBytes(ByteString.copyFromUtf8("no")); + assertEquals(ByteString.EMPTY, message.getOptionalStringBytes()); + assertEquals(ByteString.copyFromUtf8("no"), builder.getOptionalStringBytes()); + messageAfterBuild = builder.build(); + assertEquals(ByteString.copyFromUtf8("no"), messageAfterBuild.getOptionalStringBytes()); + assertEquals(ByteString.EMPTY, message.getOptionalStringBytes()); + builder.clearOptionalString(); + assertEquals(ByteString.EMPTY, builder.getOptionalStringBytes()); + assertEquals(ByteString.copyFromUtf8("no"), messageAfterBuild.getOptionalStringBytes()); + + message = builder.build(); + builder.setOptionalStringPiece("hi"); + assertEquals("", message.getOptionalStringPiece()); + assertEquals("hi", builder.getOptionalStringPiece()); + messageAfterBuild = builder.build(); + assertEquals("hi", messageAfterBuild.getOptionalStringPiece()); + assertEquals("", message.getOptionalStringPiece()); + builder.clearOptionalStringPiece(); + assertEquals("", builder.getOptionalStringPiece()); + assertEquals("hi", messageAfterBuild.getOptionalStringPiece()); + + message = builder.build(); + builder.setOptionalStringPieceBytes(ByteString.copyFromUtf8("no")); + assertEquals(ByteString.EMPTY, message.getOptionalStringPieceBytes()); + assertEquals(ByteString.copyFromUtf8("no"), builder.getOptionalStringPieceBytes()); + messageAfterBuild = builder.build(); + assertEquals(ByteString.copyFromUtf8("no"), messageAfterBuild.getOptionalStringPieceBytes()); + assertEquals(ByteString.EMPTY, message.getOptionalStringPieceBytes()); + builder.clearOptionalStringPiece(); + assertEquals(ByteString.EMPTY, builder.getOptionalStringPieceBytes()); + assertEquals(ByteString.copyFromUtf8("no"), messageAfterBuild.getOptionalStringPieceBytes()); + + message = builder.build(); + builder.setOptionalUint32(1); + assertEquals(0, message.getOptionalUint32()); + assertEquals(1, builder.getOptionalUint32()); + messageAfterBuild = builder.build(); + assertEquals(1, messageAfterBuild.getOptionalUint32()); + assertEquals(0, message.getOptionalUint32()); + builder.clearOptionalUint32(); + assertEquals(0, builder.getOptionalUint32()); + assertEquals(1, messageAfterBuild.getOptionalUint32()); + + message = builder.build(); + builder.setOptionalUint64(1); + assertEquals(0L, message.getOptionalUint64()); + assertEquals(1L, builder.getOptionalUint64()); + messageAfterBuild = builder.build(); + assertEquals(1L, messageAfterBuild.getOptionalUint64()); + assertEquals(0L, message.getOptionalUint64()); + builder.clearOptionalUint64(); + assertEquals(0L, builder.getOptionalUint64()); + assertEquals(1L, messageAfterBuild.getOptionalUint64()); + + message = builder.build(); + builder.addAllRepeatedBool(singletonList(true)); + assertEquals(emptyList(), message.getRepeatedBoolList()); + assertEquals(singletonList(true), builder.getRepeatedBoolList()); + assertEquals(emptyList(), message.getRepeatedBoolList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedBool(); + assertEquals(emptyList(), builder.getRepeatedBoolList()); + assertEquals(singletonList(true), messageAfterBuild.getRepeatedBoolList()); + + message = builder.build(); + builder.addAllRepeatedBytes(singletonList(ByteString.copyFromUtf8("hi"))); + assertEquals(emptyList(), message.getRepeatedBytesList()); + assertEquals(singletonList(ByteString.copyFromUtf8("hi")), builder.getRepeatedBytesList()); + assertEquals(emptyList(), message.getRepeatedBytesList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedBytes(); + assertEquals(emptyList(), builder.getRepeatedBytesList()); + assertEquals( + singletonList(ByteString.copyFromUtf8("hi")), messageAfterBuild.getRepeatedBytesList()); + + message = builder.build(); + builder.addAllRepeatedCord(singletonList("hi")); + assertEquals(emptyList(), message.getRepeatedCordList()); + assertEquals(singletonList("hi"), builder.getRepeatedCordList()); + assertEquals(emptyList(), message.getRepeatedCordList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedCord(); + assertEquals(emptyList(), builder.getRepeatedCordList()); + assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedCordList()); + + message = builder.build(); + builder.addAllRepeatedDouble(singletonList(1D)); + assertEquals(emptyList(), message.getRepeatedDoubleList()); + assertEquals(singletonList(1D), builder.getRepeatedDoubleList()); + assertEquals(emptyList(), message.getRepeatedDoubleList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedDouble(); + assertEquals(emptyList(), builder.getRepeatedDoubleList()); + assertEquals(singletonList(1D), messageAfterBuild.getRepeatedDoubleList()); + + message = builder.build(); + builder.addAllRepeatedFixed32(singletonList(1)); + assertEquals(emptyList(), message.getRepeatedFixed32List()); + assertEquals(singletonList(1), builder.getRepeatedFixed32List()); + assertEquals(emptyList(), message.getRepeatedFixed32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedFixed32(); + assertEquals(emptyList(), builder.getRepeatedFixed32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedFixed32List()); + + message = builder.build(); + builder.addAllRepeatedFixed64(singletonList(1L)); + assertEquals(emptyList(), message.getRepeatedFixed64List()); + assertEquals(singletonList(1L), builder.getRepeatedFixed64List()); + assertEquals(emptyList(), message.getRepeatedFixed64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedFixed64(); + assertEquals(emptyList(), builder.getRepeatedFixed64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedFixed64List()); + + message = builder.build(); + builder.addAllRepeatedFloat(singletonList(1F)); + assertEquals(emptyList(), message.getRepeatedFloatList()); + assertEquals(singletonList(1F), builder.getRepeatedFloatList()); + assertEquals(emptyList(), message.getRepeatedFloatList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedFloat(); + assertEquals(emptyList(), builder.getRepeatedFloatList()); + assertEquals(singletonList(1F), messageAfterBuild.getRepeatedFloatList()); + + message = builder.build(); + builder.addAllRepeatedForeignEnum(singletonList(ForeignEnumLite.FOREIGN_LITE_BAR)); + assertEquals(emptyList(), message.getRepeatedForeignEnumList()); + assertEquals( + singletonList(ForeignEnumLite.FOREIGN_LITE_BAR), builder.getRepeatedForeignEnumList()); + assertEquals(emptyList(), message.getRepeatedForeignEnumList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedForeignEnum(); + assertEquals(emptyList(), builder.getRepeatedForeignEnumList()); + assertEquals( + singletonList(ForeignEnumLite.FOREIGN_LITE_BAR), + messageAfterBuild.getRepeatedForeignEnumList()); + + message = builder.build(); + builder.addAllRepeatedForeignMessage(singletonList(foreignMessage)); + assertEquals(emptyList(), message.getRepeatedForeignMessageList()); + assertEquals(singletonList(foreignMessage), builder.getRepeatedForeignMessageList()); + assertEquals(emptyList(), message.getRepeatedForeignMessageList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedForeignMessage(); + assertEquals(emptyList(), builder.getRepeatedForeignMessageList()); + assertEquals(singletonList(foreignMessage), messageAfterBuild.getRepeatedForeignMessageList()); + + message = builder.build(); + builder.addAllRepeatedGroup(singletonList(RepeatedGroup.getDefaultInstance())); + assertEquals(emptyList(), message.getRepeatedGroupList()); + assertEquals(singletonList(RepeatedGroup.getDefaultInstance()), builder.getRepeatedGroupList()); + assertEquals(emptyList(), message.getRepeatedGroupList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedGroup(); + assertEquals(emptyList(), builder.getRepeatedGroupList()); + assertEquals( + singletonList(RepeatedGroup.getDefaultInstance()), + messageAfterBuild.getRepeatedGroupList()); + + message = builder.build(); + builder.addAllRepeatedInt32(singletonList(1)); + assertEquals(emptyList(), message.getRepeatedInt32List()); + assertEquals(singletonList(1), builder.getRepeatedInt32List()); + assertEquals(emptyList(), message.getRepeatedInt32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedInt32(); + assertEquals(emptyList(), builder.getRepeatedInt32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedInt32List()); + + message = builder.build(); + builder.addAllRepeatedInt64(singletonList(1L)); + assertEquals(emptyList(), message.getRepeatedInt64List()); + assertEquals(singletonList(1L), builder.getRepeatedInt64List()); + assertEquals(emptyList(), message.getRepeatedInt64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedInt64(); + assertEquals(emptyList(), builder.getRepeatedInt64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedInt64List()); + + message = builder.build(); + builder.addAllRepeatedLazyMessage(singletonList(nestedMessage)); + assertEquals(emptyList(), message.getRepeatedLazyMessageList()); + assertEquals(singletonList(nestedMessage), builder.getRepeatedLazyMessageList()); + assertEquals(emptyList(), message.getRepeatedLazyMessageList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedLazyMessage(); + assertEquals(emptyList(), builder.getRepeatedLazyMessageList()); + assertEquals(singletonList(nestedMessage), messageAfterBuild.getRepeatedLazyMessageList()); + + message = builder.build(); + builder.addAllRepeatedSfixed32(singletonList(1)); + assertEquals(emptyList(), message.getRepeatedSfixed32List()); + assertEquals(singletonList(1), builder.getRepeatedSfixed32List()); + assertEquals(emptyList(), message.getRepeatedSfixed32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSfixed32(); + assertEquals(emptyList(), builder.getRepeatedSfixed32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedSfixed32List()); + + message = builder.build(); + builder.addAllRepeatedSfixed64(singletonList(1L)); + assertEquals(emptyList(), message.getRepeatedSfixed64List()); + assertEquals(singletonList(1L), builder.getRepeatedSfixed64List()); + assertEquals(emptyList(), message.getRepeatedSfixed64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSfixed64(); + assertEquals(emptyList(), builder.getRepeatedSfixed64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSfixed64List()); + + message = builder.build(); + builder.addAllRepeatedSint32(singletonList(1)); + assertEquals(emptyList(), message.getRepeatedSint32List()); + assertEquals(singletonList(1), builder.getRepeatedSint32List()); + assertEquals(emptyList(), message.getRepeatedSint32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSint32(); + assertEquals(emptyList(), builder.getRepeatedSint32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedSint32List()); + + message = builder.build(); + builder.addAllRepeatedSint64(singletonList(1L)); + assertEquals(emptyList(), message.getRepeatedSint64List()); + assertEquals(singletonList(1L), builder.getRepeatedSint64List()); + assertEquals(emptyList(), message.getRepeatedSint64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSint64(); + assertEquals(emptyList(), builder.getRepeatedSint64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSint64List()); + + message = builder.build(); + builder.addAllRepeatedString(singletonList("hi")); + assertEquals(emptyList(), message.getRepeatedStringList()); + assertEquals(singletonList("hi"), builder.getRepeatedStringList()); + assertEquals(emptyList(), message.getRepeatedStringList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedString(); + assertEquals(emptyList(), builder.getRepeatedStringList()); + assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedStringList()); + + message = builder.build(); + builder.addAllRepeatedStringPiece(singletonList("hi")); + assertEquals(emptyList(), message.getRepeatedStringPieceList()); + assertEquals(singletonList("hi"), builder.getRepeatedStringPieceList()); + assertEquals(emptyList(), message.getRepeatedStringPieceList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedStringPiece(); + assertEquals(emptyList(), builder.getRepeatedStringPieceList()); + assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedStringPieceList()); + + message = builder.build(); + builder.addAllRepeatedUint32(singletonList(1)); + assertEquals(emptyList(), message.getRepeatedUint32List()); + assertEquals(singletonList(1), builder.getRepeatedUint32List()); + assertEquals(emptyList(), message.getRepeatedUint32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedUint32(); + assertEquals(emptyList(), builder.getRepeatedUint32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedUint32List()); + + message = builder.build(); + builder.addAllRepeatedUint64(singletonList(1L)); + assertEquals(emptyList(), message.getRepeatedUint64List()); + assertEquals(singletonList(1L), builder.getRepeatedUint64List()); + assertEquals(emptyList(), message.getRepeatedUint64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedUint64(); + assertEquals(emptyList(), builder.getRepeatedUint64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedUint64List()); + + message = builder.build(); + builder.addRepeatedBool(true); + assertEquals(emptyList(), message.getRepeatedBoolList()); + assertEquals(singletonList(true), builder.getRepeatedBoolList()); + assertEquals(emptyList(), message.getRepeatedBoolList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedBool(); + assertEquals(emptyList(), builder.getRepeatedBoolList()); + assertEquals(singletonList(true), messageAfterBuild.getRepeatedBoolList()); + + message = builder.build(); + builder.addRepeatedBytes(ByteString.copyFromUtf8("hi")); + assertEquals(emptyList(), message.getRepeatedBytesList()); + assertEquals(singletonList(ByteString.copyFromUtf8("hi")), builder.getRepeatedBytesList()); + assertEquals(emptyList(), message.getRepeatedBytesList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedBytes(); + assertEquals(emptyList(), builder.getRepeatedBytesList()); + assertEquals( + singletonList(ByteString.copyFromUtf8("hi")), messageAfterBuild.getRepeatedBytesList()); + + message = builder.build(); + builder.addRepeatedCord("hi"); + assertEquals(emptyList(), message.getRepeatedCordList()); + assertEquals(singletonList("hi"), builder.getRepeatedCordList()); + assertEquals(emptyList(), message.getRepeatedCordList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedCord(); + assertEquals(emptyList(), builder.getRepeatedCordList()); + assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedCordList()); + + message = builder.build(); + builder.addRepeatedDouble(1D); + assertEquals(emptyList(), message.getRepeatedDoubleList()); + assertEquals(singletonList(1D), builder.getRepeatedDoubleList()); + assertEquals(emptyList(), message.getRepeatedDoubleList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedDouble(); + assertEquals(emptyList(), builder.getRepeatedDoubleList()); + assertEquals(singletonList(1D), messageAfterBuild.getRepeatedDoubleList()); + + message = builder.build(); + builder.addRepeatedFixed32(1); + assertEquals(emptyList(), message.getRepeatedFixed32List()); + assertEquals(singletonList(1), builder.getRepeatedFixed32List()); + assertEquals(emptyList(), message.getRepeatedFixed32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedFixed32(); + assertEquals(emptyList(), builder.getRepeatedFixed32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedFixed32List()); + + message = builder.build(); + builder.addRepeatedFixed64(1L); + assertEquals(emptyList(), message.getRepeatedFixed64List()); + assertEquals(singletonList(1L), builder.getRepeatedFixed64List()); + assertEquals(emptyList(), message.getRepeatedFixed64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedFixed64(); + assertEquals(emptyList(), builder.getRepeatedFixed64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedFixed64List()); + + message = builder.build(); + builder.addRepeatedFloat(1F); + assertEquals(emptyList(), message.getRepeatedFloatList()); + assertEquals(singletonList(1F), builder.getRepeatedFloatList()); + assertEquals(emptyList(), message.getRepeatedFloatList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedFloat(); + assertEquals(emptyList(), builder.getRepeatedFloatList()); + assertEquals(singletonList(1F), messageAfterBuild.getRepeatedFloatList()); + + message = builder.build(); + builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR); + assertEquals(emptyList(), message.getRepeatedForeignEnumList()); + assertEquals( + singletonList(ForeignEnumLite.FOREIGN_LITE_BAR), builder.getRepeatedForeignEnumList()); + assertEquals(emptyList(), message.getRepeatedForeignEnumList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedForeignEnum(); + assertEquals(emptyList(), builder.getRepeatedForeignEnumList()); + assertEquals( + singletonList(ForeignEnumLite.FOREIGN_LITE_BAR), + messageAfterBuild.getRepeatedForeignEnumList()); + + message = builder.build(); + builder.addRepeatedForeignMessage(foreignMessage); + assertEquals(emptyList(), message.getRepeatedForeignMessageList()); + assertEquals(singletonList(foreignMessage), builder.getRepeatedForeignMessageList()); + assertEquals(emptyList(), message.getRepeatedForeignMessageList()); + messageAfterBuild = builder.build(); + builder.removeRepeatedForeignMessage(0); + assertEquals(emptyList(), builder.getRepeatedForeignMessageList()); + assertEquals(singletonList(foreignMessage), messageAfterBuild.getRepeatedForeignMessageList()); + + message = builder.build(); + builder.addRepeatedGroup(RepeatedGroup.getDefaultInstance()); + assertEquals(emptyList(), message.getRepeatedGroupList()); + assertEquals(singletonList(RepeatedGroup.getDefaultInstance()), builder.getRepeatedGroupList()); + assertEquals(emptyList(), message.getRepeatedGroupList()); + messageAfterBuild = builder.build(); + builder.removeRepeatedGroup(0); + assertEquals(emptyList(), builder.getRepeatedGroupList()); + assertEquals( + singletonList(RepeatedGroup.getDefaultInstance()), + messageAfterBuild.getRepeatedGroupList()); + + message = builder.build(); + builder.addRepeatedInt32(1); + assertEquals(emptyList(), message.getRepeatedInt32List()); + assertEquals(singletonList(1), builder.getRepeatedInt32List()); + assertEquals(emptyList(), message.getRepeatedInt32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedInt32(); + assertEquals(emptyList(), builder.getRepeatedInt32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedInt32List()); + + message = builder.build(); + builder.addRepeatedInt64(1L); + assertEquals(emptyList(), message.getRepeatedInt64List()); + assertEquals(singletonList(1L), builder.getRepeatedInt64List()); + assertEquals(emptyList(), message.getRepeatedInt64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedInt64(); + assertEquals(emptyList(), builder.getRepeatedInt64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedInt64List()); + + message = builder.build(); + builder.addRepeatedLazyMessage(nestedMessage); + assertEquals(emptyList(), message.getRepeatedLazyMessageList()); + assertEquals(singletonList(nestedMessage), builder.getRepeatedLazyMessageList()); + assertEquals(emptyList(), message.getRepeatedLazyMessageList()); + messageAfterBuild = builder.build(); + builder.removeRepeatedLazyMessage(0); + assertEquals(emptyList(), builder.getRepeatedLazyMessageList()); + assertEquals(singletonList(nestedMessage), messageAfterBuild.getRepeatedLazyMessageList()); + + message = builder.build(); + builder.addRepeatedSfixed32(1); + assertEquals(emptyList(), message.getRepeatedSfixed32List()); + assertEquals(singletonList(1), builder.getRepeatedSfixed32List()); + assertEquals(emptyList(), message.getRepeatedSfixed32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSfixed32(); + assertEquals(emptyList(), builder.getRepeatedSfixed32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedSfixed32List()); + + message = builder.build(); + builder.addRepeatedSfixed64(1L); + assertEquals(emptyList(), message.getRepeatedSfixed64List()); + assertEquals(singletonList(1L), builder.getRepeatedSfixed64List()); + assertEquals(emptyList(), message.getRepeatedSfixed64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSfixed64(); + assertEquals(emptyList(), builder.getRepeatedSfixed64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSfixed64List()); + + message = builder.build(); + builder.addRepeatedSint32(1); + assertEquals(emptyList(), message.getRepeatedSint32List()); + assertEquals(singletonList(1), builder.getRepeatedSint32List()); + assertEquals(emptyList(), message.getRepeatedSint32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSint32(); + assertEquals(emptyList(), builder.getRepeatedSint32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedSint32List()); + + message = builder.build(); + builder.addRepeatedSint64(1L); + assertEquals(emptyList(), message.getRepeatedSint64List()); + assertEquals(singletonList(1L), builder.getRepeatedSint64List()); + assertEquals(emptyList(), message.getRepeatedSint64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSint64(); + assertEquals(emptyList(), builder.getRepeatedSint64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSint64List()); + + message = builder.build(); + builder.addRepeatedString("hi"); + assertEquals(emptyList(), message.getRepeatedStringList()); + assertEquals(singletonList("hi"), builder.getRepeatedStringList()); + assertEquals(emptyList(), message.getRepeatedStringList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedString(); + assertEquals(emptyList(), builder.getRepeatedStringList()); + assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedStringList()); + + message = builder.build(); + builder.addRepeatedStringPiece("hi"); + assertEquals(emptyList(), message.getRepeatedStringPieceList()); + assertEquals(singletonList("hi"), builder.getRepeatedStringPieceList()); + assertEquals(emptyList(), message.getRepeatedStringPieceList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedStringPiece(); + assertEquals(emptyList(), builder.getRepeatedStringPieceList()); + assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedStringPieceList()); + + message = builder.build(); + builder.addRepeatedUint32(1); + assertEquals(emptyList(), message.getRepeatedUint32List()); + assertEquals(singletonList(1), builder.getRepeatedUint32List()); + assertEquals(emptyList(), message.getRepeatedUint32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedUint32(); + assertEquals(emptyList(), builder.getRepeatedUint32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedUint32List()); + + message = builder.build(); + builder.addRepeatedUint64(1L); + assertEquals(emptyList(), message.getRepeatedUint64List()); + assertEquals(singletonList(1L), builder.getRepeatedUint64List()); + assertEquals(emptyList(), message.getRepeatedUint64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedUint64(); + assertEquals(emptyList(), builder.getRepeatedUint64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedUint64List()); + + message = builder.build(); + builder.addRepeatedBool(true); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedBoolCount()); + builder.setRepeatedBool(0, false); + assertEquals(true, messageAfterBuild.getRepeatedBool(0)); + assertEquals(false, builder.getRepeatedBool(0)); + builder.clearRepeatedBool(); + + message = builder.build(); + builder.addRepeatedBytes(ByteString.copyFromUtf8("hi")); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedBytesCount()); + builder.setRepeatedBytes(0, ByteString.EMPTY); + assertEquals(ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedBytes(0)); + assertEquals(ByteString.EMPTY, builder.getRepeatedBytes(0)); + builder.clearRepeatedBytes(); + + message = builder.build(); + builder.addRepeatedCord("hi"); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedCordCount()); + builder.setRepeatedCord(0, ""); + assertEquals("hi", messageAfterBuild.getRepeatedCord(0)); + assertEquals("", builder.getRepeatedCord(0)); + builder.clearRepeatedCord(); + message = builder.build(); + + builder.addRepeatedCordBytes(ByteString.copyFromUtf8("hi")); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedCordCount()); + builder.setRepeatedCord(0, ""); + assertEquals(ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedCordBytes(0)); + assertEquals(ByteString.EMPTY, builder.getRepeatedCordBytes(0)); + builder.clearRepeatedCord(); + + message = builder.build(); + builder.addRepeatedDouble(1D); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedDoubleCount()); + builder.setRepeatedDouble(0, 0D); + assertEquals(1D, messageAfterBuild.getRepeatedDouble(0), 0.0); + assertEquals(0D, builder.getRepeatedDouble(0), 0.0); + builder.clearRepeatedDouble(); + + message = builder.build(); + builder.addRepeatedFixed32(1); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedFixed32Count()); + builder.setRepeatedFixed32(0, 0); + assertEquals(1, messageAfterBuild.getRepeatedFixed32(0)); + assertEquals(0, builder.getRepeatedFixed32(0)); + builder.clearRepeatedFixed32(); + + message = builder.build(); + builder.addRepeatedFixed64(1L); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedFixed64Count()); + builder.setRepeatedFixed64(0, 0L); + assertEquals(1L, messageAfterBuild.getRepeatedFixed64(0)); + assertEquals(0L, builder.getRepeatedFixed64(0)); + builder.clearRepeatedFixed64(); + + message = builder.build(); + builder.addRepeatedFloat(1F); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedFloatCount()); + builder.setRepeatedFloat(0, 0F); + assertEquals(1F, messageAfterBuild.getRepeatedFloat(0), 0.0f); + assertEquals(0F, builder.getRepeatedFloat(0), 0.0f); + builder.clearRepeatedFloat(); + + message = builder.build(); + builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedForeignEnumCount()); + builder.setRepeatedForeignEnum(0, ForeignEnumLite.FOREIGN_LITE_FOO); + assertEquals(ForeignEnumLite.FOREIGN_LITE_BAR, messageAfterBuild.getRepeatedForeignEnum(0)); + assertEquals(ForeignEnumLite.FOREIGN_LITE_FOO, builder.getRepeatedForeignEnum(0)); + builder.clearRepeatedForeignEnum(); + + message = builder.build(); + builder.addRepeatedForeignMessage(foreignMessage); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedForeignMessageCount()); + builder.setRepeatedForeignMessage(0, ForeignMessageLite.getDefaultInstance()); + assertEquals(foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0)); + assertEquals(ForeignMessageLite.getDefaultInstance(), builder.getRepeatedForeignMessage(0)); + builder.clearRepeatedForeignMessage(); + + message = builder.build(); + builder.addRepeatedForeignMessage(foreignMessageC3); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedForeignMessageCount()); + builder.setRepeatedForeignMessage(0, ForeignMessageLite.getDefaultInstance()); + assertEquals(foreignMessageC3, messageAfterBuild.getRepeatedForeignMessage(0)); + assertEquals(ForeignMessageLite.getDefaultInstance(), builder.getRepeatedForeignMessage(0)); + builder.clearRepeatedForeignMessage(); + + message = builder.build(); + builder.addRepeatedForeignMessage(0, foreignMessage); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedForeignMessageCount()); + builder.setRepeatedForeignMessage(0, foreignMessageC3); + assertEquals(foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0)); + assertEquals(foreignMessageC3, builder.getRepeatedForeignMessage(0)); + builder.clearRepeatedForeignMessage(); + + message = builder.build(); + RepeatedGroup repeatedGroup = RepeatedGroup.newBuilder().setA(1).build(); + builder.addRepeatedGroup(repeatedGroup); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedGroupCount()); + builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance()); + assertEquals(repeatedGroup, messageAfterBuild.getRepeatedGroup(0)); + assertEquals(RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0)); + builder.clearRepeatedGroup(); + + message = builder.build(); + builder.addRepeatedGroup(0, repeatedGroup); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedGroupCount()); + builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance()); + assertEquals(repeatedGroup, messageAfterBuild.getRepeatedGroup(0)); + assertEquals(RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0)); + builder.clearRepeatedGroup(); + + message = builder.build(); + RepeatedGroup.Builder repeatedGroupBuilder = RepeatedGroup.newBuilder().setA(3); + builder.addRepeatedGroup(repeatedGroupBuilder); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedGroupCount()); + builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance()); + assertEquals(repeatedGroupBuilder.build(), messageAfterBuild.getRepeatedGroup(0)); + assertEquals(RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0)); + builder.clearRepeatedGroup(); + + message = builder.build(); + builder.addRepeatedGroup(0, repeatedGroupBuilder); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedGroupCount()); + builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance()); + assertEquals(repeatedGroupBuilder.build(), messageAfterBuild.getRepeatedGroup(0)); + assertEquals(RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0)); + builder.clearRepeatedGroup(); + + message = builder.build(); + builder.addRepeatedInt32(1); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedInt32Count()); + builder.setRepeatedInt32(0, 0); + assertEquals(1, messageAfterBuild.getRepeatedInt32(0)); + assertEquals(0, builder.getRepeatedInt32(0)); + builder.clearRepeatedInt32(); + + message = builder.build(); + builder.addRepeatedInt64(1L); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedInt64Count()); + builder.setRepeatedInt64(0, 0L); + assertEquals(1L, messageAfterBuild.getRepeatedInt64(0)); + assertEquals(0L, builder.getRepeatedInt64(0)); + builder.clearRepeatedInt64(); + + message = builder.build(); + builder.addRepeatedLazyMessage(nestedMessage); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedLazyMessageCount()); + builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance()); + assertEquals(nestedMessage, messageAfterBuild.getRepeatedLazyMessage(0)); + assertEquals(NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0)); + builder.clearRepeatedLazyMessage(); + + message = builder.build(); + builder.addRepeatedLazyMessage(0, nestedMessage); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedLazyMessageCount()); + builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance()); + assertEquals(nestedMessage, messageAfterBuild.getRepeatedLazyMessage(0)); + assertEquals(NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0)); + builder.clearRepeatedLazyMessage(); + + message = builder.build(); + builder.addRepeatedLazyMessage(nestedMessageBuilder); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedLazyMessageCount()); + builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance()); + assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getRepeatedLazyMessage(0)); + assertEquals(NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0)); + builder.clearRepeatedLazyMessage(); + + message = builder.build(); + builder.addRepeatedLazyMessage(0, nestedMessageBuilder); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedLazyMessageCount()); + builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance()); + assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getRepeatedLazyMessage(0)); + assertEquals(NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0)); + builder.clearRepeatedLazyMessage(); + + message = builder.build(); + builder.addRepeatedSfixed32(1); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedSfixed32Count()); + builder.setRepeatedSfixed32(0, 0); + assertEquals(1, messageAfterBuild.getRepeatedSfixed32(0)); + assertEquals(0, builder.getRepeatedSfixed32(0)); + builder.clearRepeatedSfixed32(); + + message = builder.build(); + builder.addRepeatedSfixed64(1L); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedSfixed64Count()); + builder.setRepeatedSfixed64(0, 0L); + assertEquals(1L, messageAfterBuild.getRepeatedSfixed64(0)); + assertEquals(0L, builder.getRepeatedSfixed64(0)); + builder.clearRepeatedSfixed64(); + + message = builder.build(); + builder.addRepeatedSint32(1); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedSint32Count()); + builder.setRepeatedSint32(0, 0); + assertEquals(1, messageAfterBuild.getRepeatedSint32(0)); + assertEquals(0, builder.getRepeatedSint32(0)); + builder.clearRepeatedSint32(); + + message = builder.build(); + builder.addRepeatedSint64(1L); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedSint64Count()); + builder.setRepeatedSint64(0, 0L); + assertEquals(1L, messageAfterBuild.getRepeatedSint64(0)); + assertEquals(0L, builder.getRepeatedSint64(0)); + builder.clearRepeatedSint64(); + + message = builder.build(); + builder.addRepeatedString("hi"); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedStringCount()); + builder.setRepeatedString(0, ""); + assertEquals("hi", messageAfterBuild.getRepeatedString(0)); + assertEquals("", builder.getRepeatedString(0)); + builder.clearRepeatedString(); + + message = builder.build(); + builder.addRepeatedStringBytes(ByteString.copyFromUtf8("hi")); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedStringCount()); + builder.setRepeatedString(0, ""); + assertEquals(ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedStringBytes(0)); + assertEquals(ByteString.EMPTY, builder.getRepeatedStringBytes(0)); + builder.clearRepeatedString(); + + message = builder.build(); + builder.addRepeatedStringPiece("hi"); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedStringPieceCount()); + builder.setRepeatedStringPiece(0, ""); + assertEquals("hi", messageAfterBuild.getRepeatedStringPiece(0)); + assertEquals("", builder.getRepeatedStringPiece(0)); + builder.clearRepeatedStringPiece(); + + message = builder.build(); + builder.addRepeatedStringPieceBytes(ByteString.copyFromUtf8("hi")); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedStringPieceCount()); + builder.setRepeatedStringPiece(0, ""); + assertEquals(ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedStringPieceBytes(0)); + assertEquals(ByteString.EMPTY, builder.getRepeatedStringPieceBytes(0)); + builder.clearRepeatedStringPiece(); + + message = builder.build(); + builder.addRepeatedUint32(1); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedUint32Count()); + builder.setRepeatedUint32(0, 0); + assertEquals(1, messageAfterBuild.getRepeatedUint32(0)); + assertEquals(0, builder.getRepeatedUint32(0)); + builder.clearRepeatedUint32(); + + message = builder.build(); + builder.addRepeatedUint64(1L); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedUint64Count()); + builder.setRepeatedUint64(0, 0L); + assertEquals(1L, messageAfterBuild.getRepeatedUint64(0)); + assertEquals(0L, builder.getRepeatedUint64(0)); + builder.clearRepeatedUint64(); + + message = builder.build(); + assertEquals(0, message.getSerializedSize()); + builder.mergeFrom(TestAllTypesLite.newBuilder().setOptionalBool(true).build()); + assertEquals(0, message.getSerializedSize()); + assertEquals(true, builder.build().getOptionalBool()); + builder.clearOptionalBool(); + + message = builder.build(); + assertEquals(0, message.getSerializedSize()); + builder.mergeFrom(TestAllTypesLite.newBuilder().setOptionalBool(true).build()); + assertEquals(0, message.getSerializedSize()); + assertEquals(true, builder.build().getOptionalBool()); + builder.clear(); + assertEquals(0, builder.build().getSerializedSize()); + + message = builder.build(); + assertEquals(0, message.getSerializedSize()); + builder.mergeOptionalForeignMessage(foreignMessage); + assertEquals(0, message.getSerializedSize()); + assertEquals(foreignMessage.getC(), builder.build().getOptionalForeignMessage().getC()); + builder.clearOptionalForeignMessage(); + + message = builder.build(); + assertEquals(0, message.getSerializedSize()); + builder.mergeOptionalLazyMessage(nestedMessage); + assertEquals(0, message.getSerializedSize()); + assertEquals(nestedMessage.getBb(), builder.build().getOptionalLazyMessage().getBb()); + builder.clearOptionalLazyMessage(); + + message = builder.build(); + builder.setOneofString("hi"); + assertEquals(OneofFieldCase.ONEOFFIELD_NOT_SET, message.getOneofFieldCase()); + assertEquals(OneofFieldCase.ONEOF_STRING, builder.getOneofFieldCase()); + assertEquals("hi", builder.getOneofString()); + messageAfterBuild = builder.build(); + assertEquals(OneofFieldCase.ONEOF_STRING, messageAfterBuild.getOneofFieldCase()); + assertEquals("hi", messageAfterBuild.getOneofString()); + builder.setOneofUint32(1); + assertEquals(OneofFieldCase.ONEOF_STRING, messageAfterBuild.getOneofFieldCase()); + assertEquals("hi", messageAfterBuild.getOneofString()); + assertEquals(OneofFieldCase.ONEOF_UINT32, builder.getOneofFieldCase()); + assertEquals(1, builder.getOneofUint32()); + TestAllTypesLiteOrBuilder messageOrBuilder = builder; + assertEquals(OneofFieldCase.ONEOF_UINT32, messageOrBuilder.getOneofFieldCase()); + + TestAllExtensionsLite.Builder extendableMessageBuilder = TestAllExtensionsLite.newBuilder(); + TestAllExtensionsLite extendableMessage = extendableMessageBuilder.build(); + extendableMessageBuilder.setExtension(UnittestLite.optionalInt32ExtensionLite, 1); + assertFalse(extendableMessage.hasExtension(UnittestLite.optionalInt32ExtensionLite)); + extendableMessage = extendableMessageBuilder.build(); + assertEquals( + 1, (int) extendableMessageBuilder.getExtension(UnittestLite.optionalInt32ExtensionLite)); + assertEquals(1, (int) extendableMessage.getExtension(UnittestLite.optionalInt32ExtensionLite)); + extendableMessageBuilder.setExtension(UnittestLite.optionalInt32ExtensionLite, 3); + assertEquals( + 3, (int) extendableMessageBuilder.getExtension(UnittestLite.optionalInt32ExtensionLite)); + assertEquals(1, (int) extendableMessage.getExtension(UnittestLite.optionalInt32ExtensionLite)); + extendableMessage = extendableMessageBuilder.build(); + assertEquals( + 3, (int) extendableMessageBuilder.getExtension(UnittestLite.optionalInt32ExtensionLite)); + assertEquals(3, (int) extendableMessage.getExtension(UnittestLite.optionalInt32ExtensionLite)); + + // No extension registry, so it should be in unknown fields. + extendableMessage = TestAllExtensionsLite.parseFrom(extendableMessage.toByteArray()); + assertFalse(extendableMessage.hasExtension(UnittestLite.optionalInt32ExtensionLite)); + + extendableMessageBuilder = extendableMessage.toBuilder(); + extendableMessageBuilder.mergeFrom( + TestAllExtensionsLite.newBuilder() + .setExtension(UnittestLite.optionalFixed32ExtensionLite, 11) + .build()); + + extendableMessage = extendableMessageBuilder.build(); + ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); + UnittestLite.registerAllExtensions(registry); + extendableMessage = TestAllExtensionsLite.parseFrom(extendableMessage.toByteArray(), registry); + + // The unknown field was preserved. + assertEquals(3, (int) extendableMessage.getExtension(UnittestLite.optionalInt32ExtensionLite)); + assertEquals( + 11, (int) extendableMessage.getExtension(UnittestLite.optionalFixed32ExtensionLite)); + } + + public void testBuilderMergeFromNull() throws Exception { + try { + TestAllTypesLite.newBuilder().mergeFrom((TestAllTypesLite) null); + fail("Expected exception"); + } catch (NullPointerException e) { + // Pass. + } + } + + // Builder.mergeFrom() should keep existing extensions. + public void testBuilderMergeFromWithExtensions() throws Exception { + TestAllExtensionsLite message = + TestAllExtensionsLite.newBuilder() + .addExtension(UnittestLite.repeatedInt32ExtensionLite, 12) + .build(); + + ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); + UnittestLite.registerAllExtensions(registry); + + TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder(); + builder.mergeFrom(message.toByteArray(), registry); + builder.mergeFrom(message.toByteArray(), registry); + TestAllExtensionsLite result = builder.build(); + assertEquals(2, result.getExtensionCount(UnittestLite.repeatedInt32ExtensionLite)); + assertEquals(12, result.getExtension(UnittestLite.repeatedInt32ExtensionLite, 0).intValue()); + assertEquals(12, result.getExtension(UnittestLite.repeatedInt32ExtensionLite, 1).intValue()); + } + + // Builder.mergeFrom() should keep existing unknown fields. + public void testBuilderMergeFromWithUnknownFields() throws Exception { + TestAllTypesLite message = TestAllTypesLite.newBuilder().addRepeatedInt32(1).build(); + + NestedMessage.Builder builder = NestedMessage.newBuilder(); + builder.mergeFrom(message.toByteArray()); + builder.mergeFrom(message.toByteArray()); + NestedMessage result = builder.build(); + assertEquals(message.getSerializedSize() * 2, result.getSerializedSize()); + } + + public void testMergeFrom_differentFieldsSetWithinOneField() throws Exception { + TestAllTypesLite result = + TestAllTypesLite.newBuilder() + .setOneofNestedMessage(NestedMessage.newBuilder().setBb(2)) + .mergeFrom( + TestAllTypesLite.newBuilder() + .setOneofNestedMessage2(NestedMessage2.newBuilder().setDd(3)) + .build()) + .build(); + + assertToStringEquals("oneof_nested_message2 {\n dd: 3\n}", result); + } + + public void testMergeFrom_differentFieldsOfSameTypeSetWithinOneField() throws Exception { + TestAllTypesLite result = + TestAllTypesLite.newBuilder() + .setOneofNestedMessage(NestedMessage.newBuilder().setBb(2)) + .mergeFrom( + TestAllTypesLite.newBuilder() + .setOneofLazyNestedMessage(NestedMessage.newBuilder().setCc(3)) + .build()) + .build(); + + assertToStringEquals("oneof_lazy_nested_message {\n cc: 3\n}", result); + } + + public void testMergeFrom_sameFieldSetWithinOneofField() throws Exception { + TestAllTypesLite result = + TestAllTypesLite.newBuilder() + .setOneofNestedMessage(NestedMessage.newBuilder().setBb(2)) + .mergeFrom( + TestAllTypesLite.newBuilder() + .setOneofNestedMessage(NestedMessage.newBuilder().setCc(4)) + .build()) + .build(); + + assertToStringEquals("oneof_nested_message {\n bb: 2\n cc: 4\n}", result); + } + + public void testToStringDefaultInstance() throws Exception { + assertToStringEquals("", TestAllTypesLite.getDefaultInstance()); + } + + public void testToStringScalarFieldsSuffixedWithList() throws Exception { + assertToStringEquals( + "deceptively_named_list: 7", + TestAllTypesLite.newBuilder().setDeceptivelyNamedList(7).build()); + } + + public void testToStringPrimitives() throws Exception { + TestAllTypesLite proto = + TestAllTypesLite.newBuilder() + .setOptionalInt32(1) + .setOptionalInt64(9223372036854775807L) + .build(); + assertToStringEquals("optional_int32: 1\noptional_int64: 9223372036854775807", proto); + + proto = + TestAllTypesLite.newBuilder() + .setOptionalBool(true) + .setOptionalNestedEnum(NestedEnum.BAZ) + .build(); + assertToStringEquals( + "optional_bool: true\noptional_nested_enum: " + NestedEnum.BAZ.toString(), proto); + + proto = TestAllTypesLite.newBuilder().setOptionalFloat(2.72f).setOptionalDouble(3.14).build(); + assertToStringEquals("optional_double: 3.14\noptional_float: 2.72", proto); + } + + + public void testToStringStringFields() throws Exception { + TestAllTypesLite proto = + TestAllTypesLite.newBuilder().setOptionalString("foo\"bar\nbaz\\").build(); + assertToStringEquals("optional_string: \"foo\\\"bar\\nbaz\\\\\"", proto); + + proto = TestAllTypesLite.newBuilder().setOptionalString("\u6587").build(); + assertToStringEquals("optional_string: \"\\346\\226\\207\"", proto); + } + + public void testToStringNestedMessage() throws Exception { + TestAllTypesLite proto = + TestAllTypesLite.newBuilder() + .setOptionalNestedMessage(NestedMessage.getDefaultInstance()) + .build(); + assertToStringEquals("optional_nested_message {\n}", proto); + + proto = + TestAllTypesLite.newBuilder() + .setOptionalNestedMessage(NestedMessage.newBuilder().setBb(7)) + .build(); + assertToStringEquals("optional_nested_message {\n bb: 7\n}", proto); + } + + public void testToStringRepeatedFields() throws Exception { + TestAllTypesLite proto = + TestAllTypesLite.newBuilder() + .addRepeatedInt32(32) + .addRepeatedInt32(32) + .addRepeatedInt64(64) + .build(); + assertToStringEquals("repeated_int32: 32\nrepeated_int32: 32\nrepeated_int64: 64", proto); + + proto = + TestAllTypesLite.newBuilder() + .addRepeatedLazyMessage(NestedMessage.newBuilder().setBb(7)) + .addRepeatedLazyMessage(NestedMessage.newBuilder().setBb(8)) + .build(); + assertToStringEquals( + "repeated_lazy_message {\n bb: 7\n}\nrepeated_lazy_message {\n bb: 8\n}", proto); + } + + public void testToStringForeignFields() throws Exception { + TestAllTypesLite proto = + TestAllTypesLite.newBuilder() + .setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR) + .setOptionalForeignMessage(ForeignMessageLite.newBuilder().setC(3)) + .build(); + assertToStringEquals( + "optional_foreign_enum: " + + ForeignEnumLite.FOREIGN_LITE_BAR + + "\noptional_foreign_message {\n c: 3\n}", + proto); + } + + public void testToStringExtensions() throws Exception { + TestAllExtensionsLite message = + TestAllExtensionsLite.newBuilder() + .setExtension(UnittestLite.optionalInt32ExtensionLite, 123) + .addExtension(UnittestLite.repeatedStringExtensionLite, "spam") + .addExtension(UnittestLite.repeatedStringExtensionLite, "eggs") + .setExtension(UnittestLite.optionalNestedEnumExtensionLite, NestedEnum.BAZ) + .setExtension( + UnittestLite.optionalNestedMessageExtensionLite, + NestedMessage.newBuilder().setBb(7).build()) + .build(); + assertToStringEquals( + "[1]: 123\n[18] {\n bb: 7\n}\n[21]: 3\n[44]: \"spam\"\n[44]: \"eggs\"", message); + } + + public void testToStringUnknownFields() throws Exception { + TestAllExtensionsLite messageWithExtensions = + TestAllExtensionsLite.newBuilder() + .setExtension(UnittestLite.optionalInt32ExtensionLite, 123) + .addExtension(UnittestLite.repeatedStringExtensionLite, "spam") + .addExtension(UnittestLite.repeatedStringExtensionLite, "eggs") + .setExtension(UnittestLite.optionalNestedEnumExtensionLite, NestedEnum.BAZ) + .setExtension( + UnittestLite.optionalNestedMessageExtensionLite, + NestedMessage.newBuilder().setBb(7).build()) + .build(); + TestAllExtensionsLite messageWithUnknownFields = + TestAllExtensionsLite.parseFrom(messageWithExtensions.toByteArray()); + assertToStringEquals( + "1: 123\n18: \"\\b\\a\"\n21: 3\n44: \"spam\"\n44: \"eggs\"", messageWithUnknownFields); + } + + public void testToStringLazyMessage() throws Exception { + TestAllTypesLite message = + TestAllTypesLite.newBuilder() + .setOptionalLazyMessage(NestedMessage.newBuilder().setBb(1).build()) + .build(); + assertToStringEquals("optional_lazy_message {\n bb: 1\n}", message); + } + + public void testToStringGroup() throws Exception { + TestAllTypesLite message = + TestAllTypesLite.newBuilder() + .setOptionalGroup(OptionalGroup.newBuilder().setA(1).build()) + .build(); + assertToStringEquals("optional_group {\n a: 1\n}", message); + } + + public void testToStringOneof() throws Exception { + TestAllTypesLite message = TestAllTypesLite.newBuilder().setOneofString("hello").build(); + assertToStringEquals("oneof_string: \"hello\"", message); + } + + public void testToStringMapFields() throws Exception { + TestMap message1 = + TestMap.newBuilder() + .putInt32ToStringField(1, "alpha") + .putInt32ToStringField(2, "beta") + .build(); + assertToStringEquals( + "int32_to_string_field {\n" + + " key: 1\n" + + " value: \"alpha\"\n" + + "}\n" + + "int32_to_string_field {\n" + + " key: 2\n" + + " value: \"beta\"\n" + + "}", + message1); + + TestMap message2 = + TestMap.newBuilder() + .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(10).build()) + .putInt32ToMessageField(2, MessageValue.newBuilder().setValue(20).build()) + .build(); + assertToStringEquals( + "int32_to_message_field {\n" + + " key: 1\n" + + " value {\n" + + " value: 10\n" + + " }\n" + + "}\n" + + "int32_to_message_field {\n" + + " key: 2\n" + + " value {\n" + + " value: 20\n" + + " }\n" + + "}", + message2); + } + + // Asserts that the toString() representation of the message matches the expected. This verifies + // the first line starts with a comment; but, does not factor in said comment as part of the + // comparison as it contains unstable addresses. + private static void assertToStringEquals(String expected, MessageLite message) { + String toString = message.toString(); + assertEquals('#', toString.charAt(0)); + if (toString.contains("\n")) { + toString = toString.substring(toString.indexOf("\n") + 1); + } else { + toString = ""; + } + assertEquals(expected, toString); + } + + public void testParseLazy() throws Exception { + ByteString bb = + TestAllTypesLite.newBuilder() + .setOptionalLazyMessage(NestedMessage.newBuilder().setBb(11).build()) + .build() + .toByteString(); + ByteString cc = + TestAllTypesLite.newBuilder() + .setOptionalLazyMessage(NestedMessage.newBuilder().setCc(22).build()) + .build() + .toByteString(); + + ByteString concat = bb.concat(cc); + TestAllTypesLite message = TestAllTypesLite.parseFrom(concat); + + assertEquals(11, message.getOptionalLazyMessage().getBb()); + assertEquals(22L, message.getOptionalLazyMessage().getCc()); + } + + public void testParseLazy_oneOf() throws Exception { + ByteString bb = + TestAllTypesLite.newBuilder() + .setOneofLazyNestedMessage(NestedMessage.newBuilder().setBb(11).build()) + .build() + .toByteString(); + ByteString cc = + TestAllTypesLite.newBuilder() + .setOneofLazyNestedMessage(NestedMessage.newBuilder().setCc(22).build()) + .build() + .toByteString(); + + ByteString concat = bb.concat(cc); + TestAllTypesLite message = TestAllTypesLite.parseFrom(concat); + + assertEquals(11, message.getOneofLazyNestedMessage().getBb()); + assertEquals(22L, message.getOneofLazyNestedMessage().getCc()); + } + + public void testMergeFromStream_repeatedField() throws Exception { + TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder().addRepeatedString("hello"); + builder.mergeFrom(CodedInputStream.newInstance(builder.build().toByteArray())); + + assertEquals(2, builder.getRepeatedStringCount()); + } + + public void testMergeFromStream_invalidBytes() throws Exception { + TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder().setDefaultBool(true); + try { + builder.mergeFrom(CodedInputStream.newInstance("Invalid bytes".getBytes(Internal.UTF_8))); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + } + + public void testMergeFrom_sanity() throws Exception { + TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build(); + byte[] bytes = one.toByteArray(); + TestAllTypesLite two = TestAllTypesLite.parseFrom(bytes); + + one = one.toBuilder().mergeFrom(one).build(); + two = two.toBuilder().mergeFrom(bytes).build(); + assertEquals(one, two); + assertEquals(two, one); + assertEquals(one.hashCode(), two.hashCode()); + } + + public void testMergeFromNoLazyFieldSharing() throws Exception { + TestAllTypesLite.Builder sourceBuilder = + TestAllTypesLite.newBuilder().setOptionalLazyMessage(NestedMessage.newBuilder().setBb(1)); + TestAllTypesLite.Builder targetBuilder = + TestAllTypesLite.newBuilder().mergeFrom(sourceBuilder.build()); + assertEquals(1, sourceBuilder.getOptionalLazyMessage().getBb()); + // now change the sourceBuilder, and target value shouldn't be affected. + sourceBuilder.setOptionalLazyMessage(NestedMessage.newBuilder().setBb(2)); + assertEquals(1, targetBuilder.getOptionalLazyMessage().getBb()); + } + + public void testEquals_notEqual() throws Exception { + TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build(); + byte[] bytes = one.toByteArray(); + TestAllTypesLite two = one.toBuilder().mergeFrom(one).mergeFrom(bytes).build(); + + assertFalse(one.equals(two)); + assertFalse(two.equals(one)); + + assertFalse(one.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(one)); + + TestAllTypesLite oneFieldSet = TestAllTypesLite.newBuilder().setDefaultBool(true).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultBytes(ByteString.EMPTY).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultCord("").build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultCordBytes(ByteString.EMPTY).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultDouble(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultFixed32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultFixed64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultFloat(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder() + .setDefaultForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR) + .build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder().setDefaultImportEnum(ImportEnumLite.IMPORT_LITE_BAR).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultInt32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultInt64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultNestedEnum(NestedEnum.BAR).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultSfixed32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultSfixed64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultSint32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultSint64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultString("").build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultStringBytes(ByteString.EMPTY).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultStringPiece("").build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder().setDefaultStringPieceBytes(ByteString.EMPTY).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultUint32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setDefaultUint64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedBool(true).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedBytes(ByteString.EMPTY).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedCord("").build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedCordBytes(ByteString.EMPTY).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedDouble(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedFixed32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedFixed64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedFloat(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder() + .addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR) + .build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder().addRepeatedImportEnum(ImportEnumLite.IMPORT_LITE_BAR).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedInt32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedInt64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedNestedEnum(NestedEnum.BAR).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedSfixed32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedSfixed64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedSint32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedSint64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedString("").build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedStringBytes(ByteString.EMPTY).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedStringPiece("").build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder().addRepeatedStringPieceBytes(ByteString.EMPTY).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedUint32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().addRepeatedUint64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalBool(true).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalBytes(ByteString.EMPTY).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalCord("").build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalCordBytes(ByteString.EMPTY).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalDouble(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalFixed32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalFixed64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalFloat(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder() + .setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR) + .build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder().setOptionalImportEnum(ImportEnumLite.IMPORT_LITE_BAR).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalInt32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalInt64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalNestedEnum(NestedEnum.BAR).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalSfixed32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalSfixed64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalSint32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalSint64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalString("").build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalStringBytes(ByteString.EMPTY).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalStringPiece("").build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder().setOptionalStringPieceBytes(ByteString.EMPTY).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalUint32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOptionalUint64(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOneofBytes(ByteString.EMPTY).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder() + .setOneofLazyNestedMessage(NestedMessage.getDefaultInstance()) + .build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder() + .setOneofNestedMessage(NestedMessage.getDefaultInstance()) + .build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOneofString("").build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOneofStringBytes(ByteString.EMPTY).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = TestAllTypesLite.newBuilder().setOneofUint32(0).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder() + .setOptionalForeignMessage(ForeignMessageLite.getDefaultInstance()) + .build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder().setOptionalGroup(OptionalGroup.getDefaultInstance()).build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder() + .setOptionalPublicImportMessage(PublicImportMessageLite.getDefaultInstance()) + .build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + + oneFieldSet = + TestAllTypesLite.newBuilder() + .setOptionalLazyMessage(NestedMessage.getDefaultInstance()) + .build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + oneFieldSet = + TestAllTypesLite.newBuilder() + .addRepeatedLazyMessage(NestedMessage.getDefaultInstance()) + .build(); + assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance())); + assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet)); + } + + public void testEquals() throws Exception { + // Check that two identical objs are equal. + Foo foo1a = Foo.newBuilder().setValue(1).addBar(Bar.newBuilder().setName("foo1")).build(); + Foo foo1b = Foo.newBuilder().setValue(1).addBar(Bar.newBuilder().setName("foo1")).build(); + Foo foo2 = Foo.newBuilder().setValue(1).addBar(Bar.newBuilder().setName("foo2")).build(); + + // Check that equals is doing value rather than object equality. + assertEquals(foo1a, foo1b); + assertEquals(foo1a.hashCode(), foo1b.hashCode()); + + // Check that a different object is not equal. + assertFalse(foo1a.equals(foo2)); + + // Check that two objects which have different types but the same field values are not + // considered to be equal. + Bar bar = Bar.newBuilder().setName("bar").build(); + BarPrime barPrime = BarPrime.newBuilder().setName("bar").build(); + assertFalse(bar.equals(barPrime)); + } + + public void testEqualsAndHashCodeForTrickySchemaTypes() { + Foo foo1 = Foo.getDefaultInstance(); + Foo foo2 = Foo.newBuilder().setSint64(1).build(); + Foo foo3 = Foo.newBuilder().putMyMap("key", "value2").build(); + Foo foo4 = Foo.newBuilder().setMyGroup(Foo.MyGroup.newBuilder().setValue(4).build()).build(); + + assertEqualsAndHashCodeAreFalse(foo1, foo2); + assertEqualsAndHashCodeAreFalse(foo1, foo3); + assertEqualsAndHashCodeAreFalse(foo1, foo4); + } + + public void testOneofEquals() throws Exception { + TestOneofEquals.Builder builder = TestOneofEquals.newBuilder(); + TestOneofEquals message1 = builder.build(); + // Set message2's name field to default value. The two messages should be different when we + // check with the oneof case. + builder.setName(""); + TestOneofEquals message2 = builder.build(); + assertFalse(message1.equals(message2)); + } + + public void testEquals_sanity() throws Exception { + TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build(); + TestAllTypesLite two = TestAllTypesLite.parseFrom(one.toByteArray()); + assertEquals(one, two); + assertEquals(one.hashCode(), two.hashCode()); + + assertEquals( + one.toBuilder().mergeFrom(two).build(), + two.toBuilder().mergeFrom(two.toByteArray()).build()); + } + + public void testEqualsAndHashCodeWithUnknownFields() throws InvalidProtocolBufferException { + Foo fooWithOnlyValue = Foo.newBuilder().setValue(1).build(); + + Foo fooWithValueAndExtension = + fooWithOnlyValue + .toBuilder() + .setValue(1) + .setExtension(Bar.fooExt, Bar.newBuilder().setName("name").build()) + .build(); + + Foo fooWithValueAndUnknownFields = Foo.parseFrom(fooWithValueAndExtension.toByteArray()); + + assertEqualsAndHashCodeAreFalse(fooWithOnlyValue, fooWithValueAndUnknownFields); + assertEqualsAndHashCodeAreFalse(fooWithValueAndExtension, fooWithValueAndUnknownFields); + } + + public void testEqualsAndHashCodeWithExtensions() throws InvalidProtocolBufferException { + Foo fooWithOnlyValue = Foo.newBuilder().setValue(1).build(); + + Foo fooWithValueAndExtension = + fooWithOnlyValue + .toBuilder() + .setValue(1) + .setExtension(Bar.fooExt, Bar.newBuilder().setName("name").build()) + .build(); + + assertEqualsAndHashCodeAreFalse(fooWithOnlyValue, fooWithValueAndExtension); + } + + // Test to ensure we avoid a class cast exception with oneofs. + public void testEquals_oneOfMessages() { + TestAllTypesLite mine = TestAllTypesLite.newBuilder().setOneofString("Hello").build(); + + TestAllTypesLite other = + TestAllTypesLite.newBuilder() + .setOneofNestedMessage(NestedMessage.getDefaultInstance()) + .build(); + + assertFalse(mine.equals(other)); + assertFalse(other.equals(mine)); + } + + public void testHugeFieldNumbers() throws InvalidProtocolBufferException { + TestHugeFieldNumbersLite message = + TestHugeFieldNumbersLite.newBuilder() + .setOptionalInt32(1) + .addRepeatedInt32(2) + .setOptionalEnum(ForeignEnumLite.FOREIGN_LITE_FOO) + .setOptionalString("xyz") + .setOptionalMessage(ForeignMessageLite.newBuilder().setC(3).build()) + .build(); + + TestHugeFieldNumbersLite parsedMessage = + TestHugeFieldNumbersLite.parseFrom(message.toByteArray()); + assertEquals(1, parsedMessage.getOptionalInt32()); + assertEquals(2, parsedMessage.getRepeatedInt32(0)); + assertEquals(ForeignEnumLite.FOREIGN_LITE_FOO, parsedMessage.getOptionalEnum()); + assertEquals("xyz", parsedMessage.getOptionalString()); + assertEquals(3, parsedMessage.getOptionalMessage().getC()); + } + + private void assertEqualsAndHashCodeAreFalse(Object o1, Object o2) { + assertFalse(o1.equals(o2)); + assertFalse(o1.hashCode() == o2.hashCode()); + } + + public void testRecursiveHashcode() { + // This tests that we don't infinite loop. + TestRecursiveOneof.getDefaultInstance().hashCode(); + } + + public void testParseFromByteBuffer() throws Exception { + TestAllTypesLite message = + TestAllTypesLite.newBuilder() + .setOptionalInt32(123) + .addRepeatedString("hello") + .setOptionalNestedMessage(NestedMessage.newBuilder().setBb(7)) + .build(); + + TestAllTypesLite copy = + TestAllTypesLite.parseFrom(message.toByteString().asReadOnlyByteBuffer()); + + assertEquals(message, copy); + } + + public void testParseFromByteBufferThrows() { + try { + TestAllTypesLite.parseFrom(ByteBuffer.wrap(new byte[] {0x5})); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + + TestAllTypesLite message = + TestAllTypesLite.newBuilder().setOptionalInt32(123).addRepeatedString("hello").build(); + + ByteBuffer buffer = ByteBuffer.wrap(message.toByteArray(), 0, message.getSerializedSize() - 1); + try { + TestAllTypesLite.parseFrom(buffer); + fail(); + } catch (InvalidProtocolBufferException expected) { + assertEquals( + TestAllTypesLite.newBuilder().setOptionalInt32(123).build(), + expected.getUnfinishedMessage()); + } + } + + public void testParseFromByteBuffer_extensions() throws Exception { + TestAllExtensionsLite message = + TestAllExtensionsLite.newBuilder() + .setExtension(UnittestLite.optionalInt32ExtensionLite, 123) + .addExtension(UnittestLite.repeatedStringExtensionLite, "hello") + .setExtension(UnittestLite.optionalNestedEnumExtensionLite, NestedEnum.BAZ) + .setExtension( + UnittestLite.optionalNestedMessageExtensionLite, + NestedMessage.newBuilder().setBb(7).build()) + .build(); + + ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); + UnittestLite.registerAllExtensions(registry); + + TestAllExtensionsLite copy = + TestAllExtensionsLite.parseFrom(message.toByteString().asReadOnlyByteBuffer(), registry); + + assertEquals(message, copy); + } + + public void testParseFromByteBufferThrows_extensions() { + ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); + UnittestLite.registerAllExtensions(registry); + try { + TestAllExtensionsLite.parseFrom(ByteBuffer.wrap(new byte[] {0x5}), registry); + fail(); + } catch (InvalidProtocolBufferException expected) { + } + + TestAllExtensionsLite message = + TestAllExtensionsLite.newBuilder() + .setExtension(UnittestLite.optionalInt32ExtensionLite, 123) + .addExtension(UnittestLite.repeatedStringExtensionLite, "hello") + .build(); + + ByteBuffer buffer = ByteBuffer.wrap(message.toByteArray(), 0, message.getSerializedSize() - 1); + try { + TestAllExtensionsLite.parseFrom(buffer, registry); + fail(); + } catch (InvalidProtocolBufferException expected) { + assertEquals( + TestAllExtensionsLite.newBuilder() + .setExtension(UnittestLite.optionalInt32ExtensionLite, 123) + .build(), + expected.getUnfinishedMessage()); + } + } + + // Make sure we haven't screwed up the code generation for packing fields by default. + public void testPackedSerialization() throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + builder.addRepeatedInt32(4321); + builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ); + TestAllTypes message = builder.build(); + + CodedInputStream in = CodedInputStream.newInstance(message.toByteArray()); + + while (!in.isAtEnd()) { + int tag = in.readTag(); + assertEquals(WireFormat.WIRETYPE_LENGTH_DELIMITED, WireFormat.getTagWireType(tag)); + in.skipField(tag); + } + } + + public void testAddAllIteratesOnce() { + TestAllTypesLite.newBuilder() + .addAllRepeatedBool(new OneTimeIterableList<>(false)) + .addAllRepeatedInt32(new OneTimeIterableList<>(0)) + .addAllRepeatedInt64(new OneTimeIterableList<>(0L)) + .addAllRepeatedFloat(new OneTimeIterableList<>(0f)) + .addAllRepeatedDouble(new OneTimeIterableList<>(0d)) + .addAllRepeatedBytes(new OneTimeIterableList<>(ByteString.EMPTY)) + .addAllRepeatedString(new OneTimeIterableList<>("")) + .addAllRepeatedNestedMessage(new OneTimeIterableList<>(NestedMessage.getDefaultInstance())) + .addAllRepeatedBool(new OneTimeIterable<>(false)) + .addAllRepeatedInt32(new OneTimeIterable<>(0)) + .addAllRepeatedInt64(new OneTimeIterable<>(0L)) + .addAllRepeatedFloat(new OneTimeIterable<>(0f)) + .addAllRepeatedDouble(new OneTimeIterable<>(0d)) + .addAllRepeatedBytes(new OneTimeIterable<>(ByteString.EMPTY)) + .addAllRepeatedString(new OneTimeIterable<>("")) + .addAllRepeatedNestedMessage(new OneTimeIterable<>(NestedMessage.getDefaultInstance())) + .build(); + } + + public void testAddAllIteratesOnce_throwsOnNull() { + TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder(); + try { + builder.addAllRepeatedBool(new OneTimeIterableList<>(true, false, null)); + fail(); + } catch (NullPointerException expected) { + assertEquals("Element at index 2 is null.", expected.getMessage()); + assertEquals(0, builder.getRepeatedBoolCount()); + } + + try { + builder.addAllRepeatedBool(new OneTimeIterable<>(true, false, null)); + fail(); + } catch (NullPointerException expected) { + assertEquals("Element at index 2 is null.", expected.getMessage()); + assertEquals(0, builder.getRepeatedBoolCount()); + } + + try { + builder = TestAllTypesLite.newBuilder(); + builder.addAllRepeatedBool(new OneTimeIterableList<>((Boolean) null)); + fail(); + } catch (NullPointerException expected) { + assertEquals("Element at index 0 is null.", expected.getMessage()); + assertEquals(0, builder.getRepeatedBoolCount()); + } + + try { + builder = TestAllTypesLite.newBuilder(); + builder.addAllRepeatedInt32(new OneTimeIterableList<>((Integer) null)); + fail(); + } catch (NullPointerException expected) { + assertEquals("Element at index 0 is null.", expected.getMessage()); + assertEquals(0, builder.getRepeatedInt32Count()); + } + + try { + builder = TestAllTypesLite.newBuilder(); + builder.addAllRepeatedInt64(new OneTimeIterableList<>((Long) null)); + fail(); + } catch (NullPointerException expected) { + assertEquals("Element at index 0 is null.", expected.getMessage()); + assertEquals(0, builder.getRepeatedInt64Count()); + } + + try { + builder = TestAllTypesLite.newBuilder(); + builder.addAllRepeatedFloat(new OneTimeIterableList<>((Float) null)); + fail(); + } catch (NullPointerException expected) { + assertEquals("Element at index 0 is null.", expected.getMessage()); + assertEquals(0, builder.getRepeatedFloatCount()); + } + + try { + builder = TestAllTypesLite.newBuilder(); + builder.addAllRepeatedDouble(new OneTimeIterableList<>((Double) null)); + fail(); + } catch (NullPointerException expected) { + assertEquals("Element at index 0 is null.", expected.getMessage()); + assertEquals(0, builder.getRepeatedDoubleCount()); + } + + try { + builder = TestAllTypesLite.newBuilder(); + builder.addAllRepeatedBytes(new OneTimeIterableList<>((ByteString) null)); + fail(); + } catch (NullPointerException expected) { + assertEquals("Element at index 0 is null.", expected.getMessage()); + assertEquals(0, builder.getRepeatedBytesCount()); + } + + try { + builder = TestAllTypesLite.newBuilder(); + builder.addAllRepeatedString(new OneTimeIterableList<>("", "", null, "")); + fail(); + } catch (NullPointerException expected) { + assertEquals("Element at index 2 is null.", expected.getMessage()); + assertEquals(0, builder.getRepeatedStringCount()); + } + + try { + builder = TestAllTypesLite.newBuilder(); + builder.addAllRepeatedString(new OneTimeIterable<>("", "", null, "")); + fail(); + } catch (NullPointerException expected) { + assertEquals("Element at index 2 is null.", expected.getMessage()); + assertEquals(0, builder.getRepeatedStringCount()); + } + + try { + builder = TestAllTypesLite.newBuilder(); + builder.addAllRepeatedString(new OneTimeIterableList<>((String) null)); + fail(); + } catch (NullPointerException expected) { + assertEquals("Element at index 0 is null.", expected.getMessage()); + assertEquals(0, builder.getRepeatedStringCount()); + } + + try { + builder = TestAllTypesLite.newBuilder(); + builder.addAllRepeatedNestedMessage(new OneTimeIterableList<>((NestedMessage) null)); + fail(); + } catch (NullPointerException expected) { + assertEquals("Element at index 0 is null.", expected.getMessage()); + assertEquals(0, builder.getRepeatedNestedMessageCount()); + } + } + + public void testExtensionRenamesKeywords() { + assertTrue(NonNestedExtensionLite.package_ instanceof GeneratedMessageLite.GeneratedExtension); + assertTrue( + NestedExtensionLite.MyNestedExtensionLite.private_ + instanceof GeneratedMessageLite.GeneratedExtension); + + NonNestedExtensionLite.MessageLiteToBeExtended msg = + NonNestedExtensionLite.MessageLiteToBeExtended.newBuilder() + .setExtension(NonNestedExtensionLite.package_, true) + .build(); + assertTrue(msg.getExtension(NonNestedExtensionLite.package_)); + + msg = + NonNestedExtensionLite.MessageLiteToBeExtended.newBuilder() + .setExtension(NestedExtensionLite.MyNestedExtensionLite.private_, 2.4) + .build(); + assertEquals( + 2.4, msg.getExtension(NestedExtensionLite.MyNestedExtensionLite.private_), 0.001); + } + + private static final class OneTimeIterableList extends ArrayList { + private boolean wasIterated = false; + + OneTimeIterableList(T... contents) { + addAll(Arrays.asList(contents)); + } + + @Override + public Iterator iterator() { + if (wasIterated) { + fail(); + } + wasIterated = true; + return super.iterator(); + } + } + + private static final class OneTimeIterable implements Iterable { + private final List list; + private boolean wasIterated = false; + + OneTimeIterable(T... contents) { + list = Arrays.asList(contents); + } + + @Override + public Iterator iterator() { + if (wasIterated) { + fail(); + } + wasIterated = true; + return list.iterator(); + } + } + + public void testNullExtensionRegistry() throws Exception { + try { + TestAllTypesLite.parseFrom(new byte[] {}, null); + fail(); + } catch (NullPointerException expected) { + } + } + + public void testSerializeToOutputStreamThrowsIOException() { + try { + TestAllTypesLite.newBuilder() + .setOptionalBytes(ByteString.copyFromUtf8("hello")) + .build() + .writeTo( + new OutputStream() { + + @Override + public void write(int b) throws IOException { + throw new IOException(); + } + }); + fail(); + } catch (IOException expected) { + } + } + + public void testUnpairedSurrogatesReplacedByQuestionMark() throws InvalidProtocolBufferException { + String testString = "foo \ud83d bar"; + String expectedString = "foo ? bar"; + + TestAllTypesLite testMessage = + TestAllTypesLite.newBuilder().setOptionalString(testString).build(); + ByteString serializedMessage = testMessage.toByteString(); + + // Behavior is compatible with String.getBytes("UTF-8"), which replaces + // unpaired surrogates with a question mark. + TestAllTypesLite parsedMessage = TestAllTypesLite.parseFrom(serializedMessage); + assertEquals(expectedString, parsedMessage.getOptionalString()); + + // Conversion happens during serialization. + ByteString expectedBytes = ByteString.copyFromUtf8(expectedString); + assertTrue( + String.format( + "Expected serializedMessage (%s) to contain \"%s\" (%s).", + encodeHex(serializedMessage), expectedString, encodeHex(expectedBytes)), + contains(serializedMessage, expectedBytes)); + } + + private String encodeHex(ByteString bytes) { + String hexDigits = "0123456789abcdef"; + StringBuilder stringBuilder = new StringBuilder(bytes.size() * 2); + for (byte b : bytes) { + stringBuilder.append(hexDigits.charAt((b & 0xf0) >> 4)); + stringBuilder.append(hexDigits.charAt(b & 0x0f)); + } + return stringBuilder.toString(); + } + + private boolean contains(ByteString a, ByteString b) { + for (int i = 0; i <= a.size() - b.size(); ++i) { + if (a.substring(i, i + b.size()).equals(b)) { + return true; + } + } + return false; + } +} diff --git a/java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java b/java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java new file mode 100644 index 0000000000000..a17dda5c1f173 --- /dev/null +++ b/java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java @@ -0,0 +1,1332 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.FieldInfo.forField; +import static com.google.protobuf.FieldInfo.forFieldWithEnumVerifier; +import static com.google.protobuf.FieldInfo.forMapField; +import static com.google.protobuf.FieldInfo.forOneofMemberField; +import static com.google.protobuf.FieldInfo.forProto2OptionalField; +import static com.google.protobuf.FieldInfo.forProto2RequiredField; +import static com.google.protobuf.FieldInfo.forRepeatedMessageField; + +import com.google.protobuf.testing.Proto2TestingLite; +import com.google.protobuf.testing.Proto2TestingLite.Proto2EmptyLite; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.FieldGroup49; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.FieldGroup69; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.FieldGroupList51; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.FieldRequiredGroup88; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.RequiredNestedMessage; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.TestEnum; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLiteWithExtensions; +import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLiteWithMaps; +import java.lang.reflect.Field; + +/** A factory that generates a hard-coded info for {@link Proto2MessageLite}. */ +public final class Proto2MessageLiteInfoFactory implements MessageInfoFactory { + private static final Proto2MessageLiteInfoFactory instanceForRawMessageInfo = + new Proto2MessageLiteInfoFactory(true); + private static final Proto2MessageLiteInfoFactory instanceForStructuralMessageInfo = + new Proto2MessageLiteInfoFactory(false); + + public static Proto2MessageLiteInfoFactory getInstanceForRawMessageInfo() { + return instanceForRawMessageInfo; + } + + public static Proto2MessageLiteInfoFactory getInstanceForStructuralMessageInfo() { + return instanceForStructuralMessageInfo; + } + + private final boolean produceRawMessageInfo; + + private Proto2MessageLiteInfoFactory(boolean produceRawMessageInfo) { + this.produceRawMessageInfo = produceRawMessageInfo; + } + + @Override + public boolean isSupported(Class clazz) { + return true; + } + + @Override + public MessageInfo messageInfoFor(Class clazz) { + return produceRawMessageInfo ? rawMessageInfoFor(clazz) : structuralMessageInfoFor(clazz); + } + + private MessageInfo rawMessageInfoFor(Class clazz) { + if (Proto2MessageLite.class.isAssignableFrom(clazz)) { + return newRawMessageInfoForProto2MessageLite(); + } else { + throw new IllegalArgumentException("Unsupported class: " + clazz.getName()); + } + } + + private MessageInfo newRawMessageInfoForProto2MessageLite() { + java.lang.Object[] objects = + new java.lang.Object[] { + "testOneof_", + "testOneofCase_", + "bitField0_", + "bitField1_", + "fieldDouble1_", + "fieldFloat2_", + "fieldInt643_", + "fieldUint644_", + "fieldInt325_", + "fieldFixed646_", + "fieldFixed327_", + "fieldBool8_", + "fieldString9_", + "fieldMessage10_", + "fieldBytes11_", + "fieldUint3212_", + "fieldEnum13_", + Proto2MessageLite.TestEnum.internalGetVerifier(), + "fieldSfixed3214_", + "fieldSfixed6415_", + "fieldSint3216_", + "fieldSint6417_", + "fieldDoubleList18_", + "fieldFloatList19_", + "fieldInt64List20_", + "fieldUint64List21_", + "fieldInt32List22_", + "fieldFixed64List23_", + "fieldFixed32List24_", + "fieldBoolList25_", + "fieldStringList26_", + "fieldMessageList27_", + Proto2MessageLite.class, + "fieldBytesList28_", + "fieldUint32List29_", + "fieldEnumList30_", + Proto2MessageLite.TestEnum.internalGetVerifier(), + "fieldSfixed32List31_", + "fieldSfixed64List32_", + "fieldSint32List33_", + "fieldSint64List34_", + "fieldDoubleListPacked35_", + "fieldFloatListPacked36_", + "fieldInt64ListPacked37_", + "fieldUint64ListPacked38_", + "fieldInt32ListPacked39_", + "fieldFixed64ListPacked40_", + "fieldFixed32ListPacked41_", + "fieldBoolListPacked42_", + "fieldUint32ListPacked43_", + "fieldEnumListPacked44_", + Proto2MessageLite.TestEnum.internalGetVerifier(), + "fieldSfixed32ListPacked45_", + "fieldSfixed64ListPacked46_", + "fieldSint32ListPacked47_", + "fieldSint64ListPacked48_", + "fieldGroup49_", + "fieldGroupList51_", + Proto2MessageLite.FieldGroupList51.class, + Proto2MessageLite.class, + Proto2MessageLite.FieldGroup69.class, + "fieldRequiredDouble71_", + "fieldRequiredFloat72_", + "fieldRequiredInt6473_", + "fieldRequiredUint6474_", + "fieldRequiredInt3275_", + "fieldRequiredFixed6476_", + "fieldRequiredFixed3277_", + "fieldRequiredBool78_", + "fieldRequiredString79_", + "fieldRequiredMessage80_", + "fieldRequiredBytes81_", + "fieldRequiredUint3282_", + "fieldRequiredEnum83_", + Proto2MessageLite.TestEnum.internalGetVerifier(), + "fieldRequiredSfixed3284_", + "fieldRequiredSfixed6485_", + "fieldRequiredSint3286_", + "fieldRequiredSint6487_", + "fieldRequiredGroup88_", + }; + // To update this after a proto change, run blaze build on proto2_message_lite.proto and copy + // over the String info from the proto2_message_lite_proto-lite-src.jar file in the + // blaze-genfiles directory. + java.lang.String info = + "\u0001U\u0001\u0002\u0001XU\u0000 \u0015\u0001\u1000\u0000\u0002\u1001\u0001\u0003" + + "\u1002\u0002\u0004\u1003\u0003\u0005\u1004\u0004\u0006\u1005\u0005\u0007\u1006\u0006\b\u1007\u0007" + + "\t\u1008\b\n" + + "\u1409\t\u000b\u100a\n" + + "\f\u100b\u000b\r" + + "\u100c\f\u000e\u100d\r" + + "\u000f\u100e\u000e\u0010\u100f\u000f\u0011\u1010\u0010\u0012\u0012\u0013\u0013" + + "\u0014\u0014\u0015\u0015\u0016\u0016\u0017\u0017\u0018\u0018\u0019\u0019\u001a\u001a\u001b\u041b\u001c\u001c\u001d\u001d\u001e\u001e\u001f\u001f" + + " !!\"\"##$$%%&&\'\'" + + "(())**++,,--..//001\u1011\u0011315\u1033\u00006\u1034\u00007\u1035\u00008\u1036\u0000" + + "9\u1037\u0000:\u1038\u0000;\u1039\u0000<\u103a\u0000=\u103b\u0000>\u143c\u0000?\u103d" + + "\u0000@\u103e\u0000A\u1040\u0000B\u1041\u0000C\u1042\u0000D\u1043\u0000E\u1044\u0000" + + "G\u1500#H\u1501$I\u1502%J\u1503&K\u1504\'L\u1505(M\u1506)N\u1507*O\u1508+P\u1509" + + ",Q\u150a-R\u150b.S\u150c/T\u150d0U\u150e1V\u150f2W\u15103X\u15114"; + return new RawMessageInfo(Proto2MessageLite.getDefaultInstance(), info, objects); + } + + private MessageInfo structuralMessageInfoFor(Class clazz) { + if (Proto2MessageLite.class.isAssignableFrom(clazz)) { + return newMessageInfoForProto2MessageLite(); + } else if (FieldGroup49.class.isAssignableFrom(clazz)) { + return newMessageInfoForFieldGroup49(); + } else if (FieldGroupList51.class.isAssignableFrom(clazz)) { + return newMessageInfoForFieldGroupList51(); + } else if (FieldGroup69.class.isAssignableFrom(clazz)) { + return newMessageInfoForFieldGroup69(); + } else if (FieldRequiredGroup88.class.isAssignableFrom(clazz)) { + return newMessageInfoForFieldRequiredGroup88(); + } else if (RequiredNestedMessage.class.isAssignableFrom(clazz)) { + return newMessageInfoForRequiredNestedMessage(); + } else if (Proto2EmptyLite.class.isAssignableFrom(clazz)) { + return newMessageInfoForProto2EmptyLite(); + } else if (Proto2MessageLiteWithExtensions.class.isAssignableFrom(clazz)) { + return newMessageInfoForProto2MessageLiteWithExtensions(); + } else if (Proto2TestingLite.FieldGroup49.class.isAssignableFrom(clazz)) { + return newMessageInfoForExtensionFieldGroup49(); + } else if (Proto2TestingLite.FieldGroupList51.class.isAssignableFrom(clazz)) { + return newMessageInfoForExtensionFieldGroupList51(); + } else if (Proto2TestingLite.Proto2MessageLiteWithMaps.class.isAssignableFrom(clazz)) { + return newMessageInfoForProto2MessageLiteWithMaps(); + } else { + throw new IllegalArgumentException("Unsupported class: " + clazz.getName()); + } + } + + /** + * Creates a new hard-coded info for {@link Proto2MessageLite}. Each time this is called, we + * manually go through the entire process of what a message would do if it self-registered its own + * info, including looking up each field by name. This is done for benchmarking purposes, so that + * we get a more accurate representation of the time it takes to perform this process. + */ + private static StructuralMessageInfo newMessageInfoForProto2MessageLite() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(48); + builder.withCheckInitialized( + new int[] { + 10, 27, 62, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + }); + lookupFieldsByName(builder); + return builder.build(); + } + + private static void lookupFieldsByName(StructuralMessageInfo.Builder builder) { + Field bitField0 = field(Proto2MessageLite.class, "bitField0_"); + + builder.withDefaultInstance(Proto2MessageLite.getDefaultInstance()); + builder.withSyntax(ProtoSyntax.PROTO2); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldDouble1_"), + 1, + FieldType.DOUBLE, + bitField0, + 0x00000001, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldFloat2_"), + 2, + FieldType.FLOAT, + bitField0, + 0x00000002, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldInt643_"), + 3, + FieldType.INT64, + bitField0, + 0x00000004, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldUint644_"), + 4, + FieldType.UINT64, + bitField0, + 0x00000008, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldInt325_"), + 5, + FieldType.INT32, + bitField0, + 0x00000010, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldFixed646_"), + 6, + FieldType.FIXED64, + bitField0, + 0x00000020, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldFixed327_"), + 7, + FieldType.FIXED32, + bitField0, + 0x00000040, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldBool8_"), + 8, + FieldType.BOOL, + bitField0, + 0x00000080, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldString9_"), + 9, + FieldType.STRING, + bitField0, + 0x00000100, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldMessage10_"), + 10, + FieldType.MESSAGE, + bitField0, + 0x00000200, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldBytes11_"), + 11, + FieldType.BYTES, + bitField0, + 0x00000400, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldUint3212_"), + 12, + FieldType.UINT32, + bitField0, + 0x00000800, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldEnum13_"), + 13, + FieldType.ENUM, + bitField0, + 0x00001000, + false, + TestEnum.internalGetVerifier())); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldSfixed3214_"), + 14, + FieldType.SFIXED32, + bitField0, + 0x00002000, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldSfixed6415_"), + 15, + FieldType.SFIXED64, + bitField0, + 0x00004000, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldSint3216_"), + 16, + FieldType.SINT32, + bitField0, + 0x00008000, + false, + null)); + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldSint6417_"), + 17, + FieldType.SINT64, + bitField0, + 0x00010000, + false, + null)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldDoubleList18_"), + 18, + FieldType.DOUBLE_LIST, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldFloatList19_"), 19, FieldType.FLOAT_LIST, false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldInt64List20_"), 20, FieldType.INT64_LIST, false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldUint64List21_"), + 21, + FieldType.UINT64_LIST, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldInt32List22_"), 22, FieldType.INT32_LIST, false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldFixed64List23_"), + 23, + FieldType.FIXED64_LIST, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldFixed32List24_"), + 24, + FieldType.FIXED32_LIST, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldBoolList25_"), 25, FieldType.BOOL_LIST, false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldStringList26_"), + 26, + FieldType.STRING_LIST, + false)); + builder.withField( + forRepeatedMessageField( + field(Proto2MessageLite.class, "fieldMessageList27_"), + 27, + FieldType.MESSAGE_LIST, + Proto2MessageLite.class)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldBytesList28_"), 28, FieldType.BYTES_LIST, false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldUint32List29_"), + 29, + FieldType.UINT32_LIST, + false)); + builder.withField( + forFieldWithEnumVerifier( + field(Proto2MessageLite.class, "fieldEnumList30_"), + 30, + FieldType.ENUM_LIST, + TestEnum.internalGetVerifier())); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldSfixed32List31_"), + 31, + FieldType.SFIXED32_LIST, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldSfixed64List32_"), + 32, + FieldType.SFIXED64_LIST, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldSint32List33_"), + 33, + FieldType.SINT32_LIST, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldSint64List34_"), + 34, + FieldType.SINT64_LIST, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldDoubleListPacked35_"), + 35, + FieldType.DOUBLE_LIST_PACKED, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldFloatListPacked36_"), + 36, + FieldType.FLOAT_LIST_PACKED, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldInt64ListPacked37_"), + 37, + FieldType.INT64_LIST_PACKED, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldUint64ListPacked38_"), + 38, + FieldType.UINT64_LIST_PACKED, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldInt32ListPacked39_"), + 39, + FieldType.INT32_LIST_PACKED, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldFixed64ListPacked40_"), + 40, + FieldType.FIXED64_LIST_PACKED, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldFixed32ListPacked41_"), + 41, + FieldType.FIXED32_LIST_PACKED, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldBoolListPacked42_"), + 42, + FieldType.BOOL_LIST_PACKED, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldUint32ListPacked43_"), + 43, + FieldType.UINT32_LIST_PACKED, + false)); + builder.withField( + forFieldWithEnumVerifier( + field(Proto2MessageLite.class, "fieldEnumListPacked44_"), + 44, + FieldType.ENUM_LIST_PACKED, + TestEnum.internalGetVerifier())); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldSfixed32ListPacked45_"), + 45, + FieldType.SFIXED32_LIST_PACKED, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldSfixed64ListPacked46_"), + 46, + FieldType.SFIXED64_LIST_PACKED, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldSint32ListPacked47_"), + 47, + FieldType.SINT32_LIST_PACKED, + false)); + builder.withField( + forField( + field(Proto2MessageLite.class, "fieldSint64ListPacked48_"), + 48, + FieldType.SINT64_LIST_PACKED, + false)); + + builder.withField( + forProto2OptionalField( + field(Proto2MessageLite.class, "fieldGroup49_"), + 49, + FieldType.GROUP, + bitField0, + 0x00020000, + false, + null)); + builder.withField( + forRepeatedMessageField( + field(Proto2MessageLite.class, "fieldGroupList51_"), + 51, + FieldType.GROUP_LIST, + Proto2MessageLite.FieldGroupList51.class)); + + OneofInfo oneof = + new OneofInfo( + 0, + field(Proto2MessageLite.class, "testOneofCase_"), + field(Proto2MessageLite.class, "testOneof_")); + builder.withField(forOneofMemberField(53, FieldType.DOUBLE, oneof, Double.class, false, null)); + builder.withField(forOneofMemberField(54, FieldType.FLOAT, oneof, Float.class, false, null)); + builder.withField(forOneofMemberField(55, FieldType.INT64, oneof, Long.class, false, null)); + builder.withField(forOneofMemberField(56, FieldType.UINT64, oneof, Long.class, false, null)); + builder.withField(forOneofMemberField(57, FieldType.INT32, oneof, Integer.class, false, null)); + builder.withField(forOneofMemberField(58, FieldType.FIXED64, oneof, Long.class, false, null)); + builder.withField( + forOneofMemberField(59, FieldType.FIXED32, oneof, Integer.class, false, null)); + builder.withField(forOneofMemberField(60, FieldType.BOOL, oneof, Boolean.class, false, null)); + builder.withField(forOneofMemberField(61, FieldType.STRING, oneof, String.class, false, null)); + builder.withField( + forOneofMemberField(62, FieldType.MESSAGE, oneof, Proto2MessageLite.class, false, null)); + builder.withField( + forOneofMemberField(63, FieldType.BYTES, oneof, ByteString.class, false, null)); + builder.withField(forOneofMemberField(64, FieldType.UINT32, oneof, Integer.class, false, null)); + builder.withField( + forOneofMemberField(65, FieldType.SFIXED32, oneof, Integer.class, false, null)); + builder.withField(forOneofMemberField(66, FieldType.SFIXED64, oneof, Long.class, false, null)); + builder.withField(forOneofMemberField(67, FieldType.SINT32, oneof, Integer.class, false, null)); + builder.withField(forOneofMemberField(68, FieldType.SINT64, oneof, Long.class, false, null)); + builder.withField( + forOneofMemberField( + 69, FieldType.GROUP, oneof, Proto2MessageLite.FieldGroup69.class, false, null)); + + Field bitField1 = field(Proto2MessageLite.class, "bitField1_"); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredDouble71_"), + 71, + FieldType.DOUBLE, + bitField1, + 0x00000008, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredFloat72_"), + 72, + FieldType.FLOAT, + bitField1, + 0x00000010, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredInt6473_"), + 73, + FieldType.INT64, + bitField1, + 0x00000020, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredUint6474_"), + 74, + FieldType.UINT64, + bitField1, + 0x00000040, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredInt3275_"), + 75, + FieldType.INT32, + bitField1, + 0x00000080, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredFixed6476_"), + 76, + FieldType.FIXED64, + bitField1, + 0x00000100, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredFixed3277_"), + 77, + FieldType.FIXED32, + bitField1, + 0x00000200, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredBool78_"), + 78, + FieldType.BOOL, + bitField1, + 0x00000400, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredString79_"), + 79, + FieldType.STRING, + bitField1, + 0x00000800, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredMessage80_"), + 80, + FieldType.MESSAGE, + bitField1, + 0x00001000, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredBytes81_"), + 81, + FieldType.BYTES, + bitField1, + 0x00002000, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredUint3282_"), + 82, + FieldType.UINT32, + bitField1, + 0x00004000, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredEnum83_"), + 83, + FieldType.ENUM, + bitField1, + 0x00008000, + false, + TestEnum.internalGetVerifier())); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredSfixed3284_"), + 84, + FieldType.SFIXED32, + bitField1, + 0x00010000, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredSfixed6485_"), + 85, + FieldType.SFIXED64, + bitField1, + 0x00020000, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredSint3286_"), + 86, + FieldType.SINT32, + bitField1, + 0x00040000, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredSint6487_"), + 87, + FieldType.SINT64, + bitField1, + 0x00080000, + false, + null)); + builder.withField( + forProto2RequiredField( + field(Proto2MessageLite.class, "fieldRequiredGroup88_"), + 88, + FieldType.GROUP, + bitField1, + 0x00100000, + false, + null)); + } + + private static StructuralMessageInfo newMessageInfoForFieldGroup49() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + Field bitField0 = field(FieldGroup49.class, "bitField0_"); + builder.withField( + forProto2OptionalField( + field(FieldGroup49.class, "fieldInt3250_"), + 50, + FieldType.INT32, + bitField0, + 0x00000001, + false, + null)); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForFieldGroupList51() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + Field bitField0 = field(FieldGroup49.class, "bitField0_"); + builder.withField( + forProto2OptionalField( + field(FieldGroupList51.class, "fieldInt3252_"), + 52, + FieldType.INT32, + bitField0, + 0x00000001, + false, + null)); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForFieldGroup69() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + Field bitField0 = field(FieldGroup69.class, "bitField0_"); + builder.withField( + forProto2OptionalField( + field(FieldGroup69.class, "fieldInt3270_"), + 70, + FieldType.INT32, + bitField0, + 0x00000001, + false, + null)); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForRequiredNestedMessage() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + Field bitField0 = field(RequiredNestedMessage.class, "bitField0_"); + builder.withField( + forProto2OptionalField( + field(RequiredNestedMessage.class, "value_"), + 1, + FieldType.INT32, + bitField0, + 0x00000001, + false, + null)); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForFieldRequiredGroup88() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + Field bitField0 = field(FieldRequiredGroup88.class, "bitField0_"); + builder.withField( + forProto2OptionalField( + field(FieldRequiredGroup88.class, "fieldInt3289_"), + 89, + FieldType.INT32, + bitField0, + 0x00000001, + false, + null)); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForProto2EmptyLite() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForProto2MessageLiteWithExtensions() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(0); + builder.withSyntax(ProtoSyntax.PROTO2); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForExtensionFieldGroup49() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + Field bitField0 = field(Proto2TestingLite.FieldGroup49.class, "bitField0_"); + builder.withField( + forProto2OptionalField( + field(Proto2TestingLite.FieldGroup49.class, "fieldInt3250_"), + 50, + FieldType.INT32, + bitField0, + 0x00000001, + false, + null)); + return builder.build(); + } + + private static StructuralMessageInfo newMessageInfoForExtensionFieldGroupList51() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1); + builder.withSyntax(ProtoSyntax.PROTO2); + Field bitField0 = field(Proto2TestingLite.FieldGroup49.class, "bitField0_"); + builder.withField( + forProto2OptionalField( + field(Proto2TestingLite.FieldGroupList51.class, "fieldInt3252_"), + 52, + FieldType.INT32, + bitField0, + 0x00000001, + false, + null)); + return builder.build(); + } + + + private static StructuralMessageInfo newMessageInfoForProto2MessageLiteWithMaps() { + StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(); + builder.withCheckInitialized( + new int[] { + 10, 27, 44, 61, 78, 95, 112, 129, 146, 163, 180, 197, + }); + builder.withSyntax(ProtoSyntax.PROTO2); + builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_bool_1", 1)); + builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_bytes_2", 2)); + builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_double_3", 3)); + builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_enum_4", 4)); + builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_fixed32_5", 5)); + builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_fixed64_6", 6)); + builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_float_7", 7)); + builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_int32_8", 8)); + builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_int64_9", 9)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_message_10", 10)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_sfixed32_11", 11)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_sfixed64_12", 12)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_sint32_13", 13)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_sint64_14", 14)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_string_15", 15)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_uint32_16", 16)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_uint64_17", 17)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_bool_18", 18)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_bytes_19", 19)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_double_20", 20)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_enum_21", 21)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_fixed32_22", 22)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_fixed64_23", 23)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_float_24", 24)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_int32_25", 25)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_int64_26", 26)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_message_27", 27)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_sfixed32_28", 28)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_sfixed64_29", 29)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_sint32_30", 30)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_sint64_31", 31)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_string_32", 32)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_uint32_33", 33)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_uint64_34", 34)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_bool_35", 35)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_bytes_36", 36)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_double_37", 37)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_enum_38", 38)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_fixed32_39", 39)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_fixed64_40", 40)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_float_41", 41)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_int32_42", 42)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_int64_43", 43)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_message_44", 44)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_sfixed32_45", 45)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_sfixed64_46", 46)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_sint32_47", 47)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_sint64_48", 48)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_string_49", 49)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_uint32_50", 50)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_uint64_51", 51)); + builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_bool_52", 52)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_bytes_53", 53)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_double_54", 54)); + builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_enum_55", 55)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_fixed32_56", 56)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_fixed64_57", 57)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_float_58", 58)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_int32_59", 59)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_int64_60", 60)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_message_61", 61)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_sfixed32_62", 62)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_sfixed64_63", 63)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_sint32_64", 64)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_sint64_65", 65)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_string_66", 66)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_uint32_67", 67)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_uint64_68", 68)); + builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_bool_69", 69)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_bytes_70", 70)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_double_71", 71)); + builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_enum_72", 72)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_fixed32_73", 73)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_fixed64_74", 74)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_float_75", 75)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_int32_76", 76)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_int64_77", 77)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_message_78", 78)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_sfixed32_79", 79)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_sfixed64_80", 80)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_sint32_81", 81)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_sint64_82", 82)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_string_83", 83)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_uint32_84", 84)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_uint64_85", 85)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_bool_86", 86)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_bytes_87", 87)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_double_88", 88)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_enum_89", 89)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_fixed32_90", 90)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_fixed64_91", 91)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_float_92", 92)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_int32_93", 93)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_int64_94", 94)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_message_95", 95)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_sfixed32_96", 96)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_sfixed64_97", 97)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_sint32_98", 98)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_sint64_99", 99)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_string_100", 100)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_uint32_101", 101)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_uint64_102", 102)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_bool_103", 103)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_bytes_104", 104)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_double_105", 105)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_enum_106", 106)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_fixed32_107", 107)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_fixed64_108", 108)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_float_109", 109)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_int32_110", 110)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_int64_111", 111)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_message_112", 112)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_sfixed32_113", 113)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_sfixed64_114", 114)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_sint32_115", 115)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_sint64_116", 116)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_string_117", 117)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_uint32_118", 118)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_uint64_119", 119)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_bool_120", 120)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_bytes_121", 121)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_double_122", 122)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_enum_123", 123)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_fixed32_124", 124)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_fixed64_125", 125)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_float_126", 126)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_int32_127", 127)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_int64_128", 128)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_message_129", 129)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_sfixed32_130", 130)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_sfixed64_131", 131)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_sint32_132", 132)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_sint64_133", 133)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_string_134", 134)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_uint32_135", 135)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_uint64_136", 136)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_bool_137", 137)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_bytes_138", 138)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_double_139", 139)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_enum_140", 140)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_fixed32_141", 141)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_fixed64_142", 142)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_float_143", 143)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_int32_144", 144)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_int64_145", 145)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_message_146", 146)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_sfixed32_147", 147)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_sfixed64_148", 148)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_sint32_149", 149)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_sint64_150", 150)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_string_151", 151)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_uint32_152", 152)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_uint64_153", 153)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_bool_154", 154)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_bytes_155", 155)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_double_156", 156)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_enum_157", 157)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_fixed32_158", 158)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_fixed64_159", 159)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_float_160", 160)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_int32_161", 161)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_int64_162", 162)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_message_163", 163)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_sfixed32_164", 164)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_sfixed64_165", 165)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_sint32_166", 166)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_sint64_167", 167)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_string_168", 168)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_uint32_169", 169)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_uint64_170", 170)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_bool_171", 171)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_bytes_172", 172)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_double_173", 173)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_enum_174", 174)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_fixed32_175", 175)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_fixed64_176", 176)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_float_177", 177)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_int32_178", 178)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_int64_179", 179)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_message_180", 180)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_sfixed32_181", 181)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_sfixed64_182", 182)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_sint32_183", 183)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_sint64_184", 184)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_string_185", 185)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_uint32_186", 186)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_uint64_187", 187)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_bool_188", 188)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_bytes_189", 189)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_double_190", 190)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_enum_191", 191)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_fixed32_192", 192)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_fixed64_193", 193)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_float_194", 194)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_int32_195", 195)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_int64_196", 196)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_message_197", 197)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_sfixed32_198", 198)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_sfixed64_199", 199)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_sint32_200", 200)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_sint64_201", 201)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_string_202", 202)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_uint32_203", 203)); + builder.withField( + mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_uint64_204", 204)); + + return builder.build(); + } + + private static Field field(Class clazz, String name) { + try { + return clazz.getDeclaredField(name); + } catch (NoSuchFieldException | SecurityException e) { + throw new RuntimeException(e); + } + } + + private static FieldInfo mapFieldInfo(Class clazz, String fieldName, int fieldNumber) { + try { + return forMapField( + field(clazz, SchemaUtil.toCamelCase(fieldName, false) + "_"), + fieldNumber, + SchemaUtil.getMapDefaultEntry(clazz, fieldName), + fieldName.contains("_enum_") ? TestEnum.internalGetVerifier() : null); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } +} diff --git a/java/pom.xml b/java/pom.xml index dd3ba3b88ecb2..550737829bcd1 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -1,17 +1,10 @@ - + 4.0.0 - - com.google - google - 1 - com.google.protobuf protobuf-parent - 3.4.0 + 3.15.0 pom Protocol Buffers [Parent] @@ -22,6 +15,17 @@ extensible format. + + + haon + Hao Nguyen + haon@google.com + Google + https://cloud.google.com + America/Los_Angeles + + + UTF-8 UTF-8 @@ -33,8 +37,6 @@ src/test/proto ${project.build.directory}/generated-sources ${project.build.directory}/generated-test-sources - ${project.build.directory}/generated-sources-lite - ${project.build.directory}/generated-test-sources-lite @@ -46,8 +48,8 @@ - https://github.com/google/protobuf - scm:git:https://github.com/google/protobuf.git + https://github.com/protocolbuffers/protobuf + scm:git:https://github.com/protocolbuffers/protobuf.git @@ -63,10 +65,17 @@ + + com.google.protobuf + protobuf-bom + ${project.version} + pom + import + junit junit - 4.12 + 4.13.1 test @@ -84,7 +93,19 @@ com.google.guava guava - 19.0 + 30.0-android + + + com.google.guava + guava-testlib + 30.0-android + test + + + com.google.truth + truth + 1.0.1 + test @@ -94,10 +115,10 @@ maven-compiler-plugin - 3.6.0 + 3.6.1 - 1.6 - 1.6 + 1.7 + 1.7 @@ -121,6 +142,9 @@ jar + + false + @@ -167,13 +191,16 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.9.1 + 2.10.3 attach-javadocs jar + + false + @@ -207,8 +234,9 @@ + bom + lite core - util diff --git a/java/util/BUILD b/java/util/BUILD new file mode 100644 index 0000000000000..71f73bab10dcf --- /dev/null +++ b/java/util/BUILD @@ -0,0 +1,16 @@ +load("@rules_java//java:defs.bzl", "java_library") + +java_library( + name = "util", + srcs = glob([ + "src/main/java/com/google/protobuf/util/*.java", + ]), + visibility = ["//visibility:public"], + deps = [ + "//external:error_prone_annotations", + "//external:gson", + "//external:guava", + "//java/core", + "//java/lite", + ], +) diff --git a/java/util/pom.xml b/java/util/pom.xml index 61abd14623195..9c089dfb72695 100644 --- a/java/util/pom.xml +++ b/java/util/pom.xml @@ -1,12 +1,10 @@ - + 4.0.0 com.google.protobuf protobuf-parent - 3.4.0 + 3.15.0 protobuf-java-util @@ -19,16 +17,25 @@ ${project.groupId} protobuf-java - ${project.version} com.google.guava guava + + com.google.errorprone + error_prone_annotations + 2.3.4 + + + com.google.guava + guava-testlib + test + com.google.code.gson gson - 2.7 + 2.8.6 junit @@ -42,6 +49,11 @@ org.easymock easymockclassextension + + com.google.truth + truth + test + @@ -65,10 +77,10 @@ - - - - + + + + @@ -106,6 +118,7 @@ true + com.google.protobuf.util https://developers.google.com/protocol-buffers/ com.google.protobuf.util com.google.protobuf.util;version=${project.version} diff --git a/java/util/src/main/java/com/google/protobuf/util/Durations.java b/java/util/src/main/java/com/google/protobuf/util/Durations.java index fb7f43433843f..7470960821760 100644 --- a/java/util/src/main/java/com/google/protobuf/util/Durations.java +++ b/java/util/src/main/java/com/google/protobuf/util/Durations.java @@ -30,6 +30,7 @@ package com.google.protobuf.util; +import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.math.IntMath.checkedAdd; import static com.google.common.math.IntMath.checkedSubtract; import static com.google.common.math.LongMath.checkedAdd; @@ -41,7 +42,9 @@ import static com.google.protobuf.util.Timestamps.NANOS_PER_MILLISECOND; import static com.google.protobuf.util.Timestamps.NANOS_PER_SECOND; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Duration; +import java.io.Serializable; import java.text.ParseException; import java.util.Comparator; @@ -53,6 +56,10 @@ public final class Durations { static final long DURATION_SECONDS_MIN = -315576000000L; static final long DURATION_SECONDS_MAX = 315576000000L; + private static final long SECONDS_PER_MINUTE = 60L; + private static final long SECONDS_PER_HOUR = SECONDS_PER_MINUTE * 60; + private static final long SECONDS_PER_DAY = SECONDS_PER_HOUR * 24; + /** A constant holding the minimum valid {@link Duration}, approximately {@code -10,000} years. */ public static final Duration MIN_VALUE = Duration.newBuilder().setSeconds(DURATION_SECONDS_MIN).setNanos(-999999999).build(); @@ -61,36 +68,41 @@ public final class Durations { public static final Duration MAX_VALUE = Duration.newBuilder().setSeconds(DURATION_SECONDS_MAX).setNanos(999999999).build(); + /** A constant holding the duration of zero. */ + public static final Duration ZERO = Duration.newBuilder().setSeconds(0L).setNanos(0).build(); + private Durations() {} - private static final Comparator COMPARATOR = - new Comparator() { - @Override - public int compare(Duration d1, Duration d2) { - checkValid(d1); - checkValid(d2); - int secDiff = Long.compare(d1.getSeconds(), d2.getSeconds()); - return (secDiff != 0) ? secDiff : Integer.compare(d1.getNanos(), d2.getNanos()); - } - }; + private static enum DurationComparator implements Comparator, Serializable { + INSTANCE; + + @Override + public int compare(Duration d1, Duration d2) { + checkValid(d1); + checkValid(d2); + int secDiff = Long.compare(d1.getSeconds(), d2.getSeconds()); + return (secDiff != 0) ? secDiff : Integer.compare(d1.getNanos(), d2.getNanos()); + } + } /** * Returns a {@link Comparator} for {@link Duration}s which sorts in increasing chronological - * order. Nulls and invalid {@link Duration}s are not allowed (see {@link #isValid}). + * order. Nulls and invalid {@link Duration}s are not allowed (see {@link #isValid}). The returned + * comparator is serializable. */ public static Comparator comparator() { - return COMPARATOR; + return DurationComparator.INSTANCE; } /** - * Compares two durations. The value returned is identical to what would be returned by: - * {@code Durations.comparator().compare(x, y)}. + * Compares two durations. The value returned is identical to what would be returned by: {@code + * Durations.comparator().compare(x, y)}. * * @return the value {@code 0} if {@code x == y}; a value less than {@code 0} if {@code x < y}; * and a value greater than {@code 0} if {@code x > y} */ public static int compare(Duration x, Duration y) { - return COMPARATOR.compare(x, y); + return DurationComparator.INSTANCE.compare(x, y); } /** @@ -115,6 +127,7 @@ public static boolean isValid(Duration duration) { * and a positive or negative {@code nanos} field. For durations of one second or more, a non-zero * value for the {@code nanos} field must be of the same sign as the {@code seconds} field. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static boolean isValid(long seconds, int nanos) { if (seconds < DURATION_SECONDS_MIN || seconds > DURATION_SECONDS_MAX) { return false; @@ -130,20 +143,68 @@ public static boolean isValid(long seconds, int nanos) { return true; } + /** Returns whether the given {@link Duration} is negative or not. */ + public static boolean isNegative(Duration duration) { + checkValid(duration); + return (duration.getSeconds() == 0) ? duration.getNanos() < 0 : duration.getSeconds() < 0; + } + + /** + * Ensures that the given {@link Duration} is not negative. + * + * @throws IllegalArgumentException if {@code duration} is negative or invalid + * @throws NullPointerException if {@code duration} is {@code null} + */ + @CanIgnoreReturnValue + public static Duration checkNotNegative(Duration duration) { + checkValid(duration); + checkArgument(!isNegative(duration), "duration (%s) must not be negative", toString(duration)); + return duration; + } + + /** + * Ensures that the given {@link Duration} is positive. + * + * @throws IllegalArgumentException if {@code duration} is negative, {@code ZERO}, or invalid + * @throws NullPointerException if {@code duration} is {@code null} + */ + @CanIgnoreReturnValue + public static Duration checkPositive(Duration duration) { + checkValid(duration); + checkArgument( + !isNegative(duration) && !duration.equals(ZERO), + "duration (%s) must be positive", + toString(duration)); + return duration; + } + /** Throws an {@link IllegalArgumentException} if the given {@link Duration} is not valid. */ + @CanIgnoreReturnValue public static Duration checkValid(Duration duration) { long seconds = duration.getSeconds(); int nanos = duration.getNanos(); if (!isValid(seconds, nanos)) { - throw new IllegalArgumentException(String.format( - "Duration is not valid. See proto definition for valid values. " - + "Seconds (%s) must be in range [-315,576,000,000, +315,576,000,000]. " - + "Nanos (%s) must be in range [-999,999,999, +999,999,999]. " - + "Nanos must have the same sign as seconds", seconds, nanos)); + throw new IllegalArgumentException( + String.format( + "Duration is not valid. See proto definition for valid values. " + + "Seconds (%s) must be in range [-315,576,000,000, +315,576,000,000]. " + + "Nanos (%s) must be in range [-999,999,999, +999,999,999]. " + + "Nanos must have the same sign as seconds", + seconds, nanos)); } return duration; } + /** + * Builds the given builder and throws an {@link IllegalArgumentException} if it is not valid. See + * {@link #checkValid(Duration)}. + * + * @return A valid, built {@link Duration}. + */ + public static Duration checkValid(Duration.Builder durationBuilder) { + return checkValid(durationBuilder.build()); + } + /** * Convert Duration to string format. The string format will contains 3, 6, or 9 fractional digits * depending on the precision required to represent the exact Duration value. For example: "1s", @@ -213,30 +274,125 @@ public static Duration parse(String value) throws ParseException { } } + // Static factories + + /** Create a Duration from the number of days. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API + public static Duration fromDays(long days) { + return Duration.newBuilder() + .setSeconds(checkedMultiply(days, SECONDS_PER_DAY)) + .setNanos(0) + .build(); + } + + /** Create a Duration from the number of hours. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API + public static Duration fromHours(long hours) { + return Duration.newBuilder() + .setSeconds(checkedMultiply(hours, SECONDS_PER_HOUR)) + .setNanos(0) + .build(); + } + + /** Create a Duration from the number of minutes. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API + public static Duration fromMinutes(long minutes) { + return Duration.newBuilder() + .setSeconds(checkedMultiply(minutes, SECONDS_PER_MINUTE)) + .setNanos(0) + .build(); + } + /** Create a Duration from the number of seconds. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static Duration fromSeconds(long seconds) { return normalizedDuration(seconds, 0); } + /** Create a Duration from the number of milliseconds. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API + public static Duration fromMillis(long milliseconds) { + return normalizedDuration( + milliseconds / MILLIS_PER_SECOND, + (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND)); + } + + /** Create a Duration from the number of microseconds. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API + public static Duration fromMicros(long microseconds) { + return normalizedDuration( + microseconds / MICROS_PER_SECOND, + (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND)); + } + + /** Create a Duration from the number of nanoseconds. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API + public static Duration fromNanos(long nanoseconds) { + return normalizedDuration( + nanoseconds / NANOS_PER_SECOND, (int) (nanoseconds % NANOS_PER_SECOND)); + } + + // Conversion APIs + + /** + * Convert a Duration to the number of days. The result will be rounded towards 0 to the nearest + * day. + */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API + public static long toDays(Duration duration) { + return checkValid(duration).getSeconds() / SECONDS_PER_DAY; + } + + /** + * Convert a Duration to the number of hours. The result will be rounded towards 0 to the nearest + * hour. + */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API + public static long toHours(Duration duration) { + return checkValid(duration).getSeconds() / SECONDS_PER_HOUR; + } + + /** + * Convert a Duration to the number of minutes. The result will be rounded towards 0 to the + * nearest minute. + */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API + public static long toMinutes(Duration duration) { + return checkValid(duration).getSeconds() / SECONDS_PER_MINUTE; + } + /** * Convert a Duration to the number of seconds. The result will be rounded towards 0 to the * nearest second. E.g., if the duration represents -1 nanosecond, it will be rounded to 0. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static long toSeconds(Duration duration) { return checkValid(duration).getSeconds(); } - /** Create a Duration from the number of milliseconds. */ - public static Duration fromMillis(long milliseconds) { - return normalizedDuration( - milliseconds / MILLIS_PER_SECOND, - (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND)); + /** + * Returns the number of seconds of the given duration as a {@code double}. This method should be + * used to accommodate APIs that only accept durations as {@code double} values. + * + *

This conversion may lose precision. + * + *

If you need the number of seconds in this duration as a {@code long} (not a {@code double}), + * simply use {@code duration.getSeconds()} or {@link #toSeconds} (which includes validation). + */ + @SuppressWarnings({ + "DurationSecondsToDouble", // that's the whole point of this method + "GoodTime" // this is a legacy conversion API + }) + public static double toSecondsAsDouble(Duration duration) { + checkValid(duration); + return duration.getSeconds() + duration.getNanos() / 1e9; } /** * Convert a Duration to the number of milliseconds. The result will be rounded towards 0 to the * nearest millisecond. E.g., if the duration represents -1 nanosecond, it will be rounded to 0. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static long toMillis(Duration duration) { checkValid(duration); return checkedAdd( @@ -244,17 +400,11 @@ public static long toMillis(Duration duration) { duration.getNanos() / NANOS_PER_MILLISECOND); } - /** Create a Duration from the number of microseconds. */ - public static Duration fromMicros(long microseconds) { - return normalizedDuration( - microseconds / MICROS_PER_SECOND, - (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND)); - } - /** * Convert a Duration to the number of microseconds. The result will be rounded towards 0 to the * nearest microseconds. E.g., if the duration represents -1 nanosecond, it will be rounded to 0. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static long toMicros(Duration duration) { checkValid(duration); return checkedAdd( @@ -262,19 +412,16 @@ public static long toMicros(Duration duration) { duration.getNanos() / NANOS_PER_MICROSECOND); } - /** Create a Duration from the number of nanoseconds. */ - public static Duration fromNanos(long nanoseconds) { - return normalizedDuration( - nanoseconds / NANOS_PER_SECOND, (int) (nanoseconds % NANOS_PER_SECOND)); - } - /** Convert a Duration to the number of nanoseconds. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static long toNanos(Duration duration) { checkValid(duration); return checkedAdd( checkedMultiply(duration.getSeconds(), NANOS_PER_SECOND), duration.getNanos()); } + // Math operations + /** Add two durations. */ public static Duration add(Duration d1, Duration d2) { checkValid(d1); diff --git a/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java index b192b53edf5ab..352376e015093 100644 --- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java +++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java @@ -30,11 +30,12 @@ package com.google.protobuf.util; +import com.google.common.base.Splitter; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.FieldMask; import com.google.protobuf.Message; - import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; @@ -66,7 +67,7 @@ final class FieldMaskTree { private static final String FIELD_PATH_SEPARATOR_REGEX = "\\."; private static final class Node { - final SortedMap children = new TreeMap(); + final SortedMap children = new TreeMap<>(); } private final Node root = new Node(); @@ -89,15 +90,15 @@ public String toString() { } /** - * Adds a field path to the tree. In a FieldMask, every field path matches the - * specified field as well as all its sub-fields. For example, a field path - * "foo.bar" matches field "foo.bar" and also "foo.bar.baz", etc. When adding - * a field path to the tree, redundant sub-paths will be removed. That is, - * after adding "foo.bar" to the tree, "foo.bar.baz" will be removed if it - * exists, which will turn the tree node for "foo.bar" to a leaf node. - * Likewise, if the field path to add is a sub-path of an existing leaf node, - * nothing will be changed in the tree. + * Adds a field path to the tree. In a FieldMask, every field path matches the specified field as + * well as all its sub-fields. For example, a field path "foo.bar" matches field "foo.bar" and + * also "foo.bar.baz", etc. When adding a field path to the tree, redundant sub-paths will be + * removed. That is, after adding "foo.bar" to the tree, "foo.bar.baz" will be removed if it + * exists, which will turn the tree node for "foo.bar" to a leaf node. Likewise, if the field path + * to add is a sub-path of an existing leaf node, nothing will be changed in the tree. */ + @CanIgnoreReturnValue + @SuppressWarnings("StringSplitter") FieldMaskTree addFieldPath(String path) { String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX); if (parts.length == 0) { @@ -126,9 +127,8 @@ FieldMaskTree addFieldPath(String path) { return this; } - /** - * Merges all field paths in a FieldMask into this tree. - */ + /** Merges all field paths in a FieldMask into this tree. */ + @CanIgnoreReturnValue FieldMaskTree mergeFromFieldMask(FieldMask mask) { for (String path : mask.getPathsList()) { addFieldPath(path); @@ -136,6 +136,65 @@ FieldMaskTree mergeFromFieldMask(FieldMask mask) { return this; } + /** + * Removes {@code path} from the tree. + * + *

    + * When removing a field path from the tree: + *
  • All sub-paths will be removed. That is, after removing "foo.bar" from the tree, + * "foo.bar.baz" will be removed. + *
  • If all children of a node has been removed, the node itself will be removed as well. + * That is, if "foo" only has one child "bar" and "foo.bar" only has one child "baz", + * removing "foo.bar.barz" would remove both "foo" and "foo.bar". + * If "foo" has both "bar" and "qux" as children, removing "foo.bar" would leave the path + * "foo.qux" intact. + *
  • If the field path to remove is a non-exist sub-path, nothing will be changed. + *
+ */ + @CanIgnoreReturnValue + FieldMaskTree removeFieldPath(String path) { + List parts = Splitter.onPattern(FIELD_PATH_SEPARATOR_REGEX).splitToList(path); + if (parts.isEmpty()) { + return this; + } + removeFieldPath(root, parts, 0); + return this; + } + + /** + * Removes {@code parts} from {@code node} recursively. + * + * @return a boolean value indicating whether current {@code node} should be removed. + */ + @CanIgnoreReturnValue + private static boolean removeFieldPath(Node node, List parts, int index) { + String key = parts.get(index); + + // Base case 1: path not match. + if (!node.children.containsKey(key)) { + return false; + } + // Base case 2: last element in parts. + if (index == parts.size() - 1) { + node.children.remove(key); + return node.children.isEmpty(); + } + // Recursive remove sub-path. + if (removeFieldPath(node.children.get(key), parts, index + 1)) { + node.children.remove(key); + } + return node.children.isEmpty(); + } + + /** Removes all field paths in {@code mask} from this tree. */ + @CanIgnoreReturnValue + FieldMaskTree removeFromFieldMask(FieldMask mask) { + for (String path : mask.getPathsList()) { + removeFieldPath(path); + } + return this; + } + /** * Converts this tree to a FieldMask. */ @@ -143,15 +202,13 @@ FieldMask toFieldMask() { if (root.children.isEmpty()) { return FieldMask.getDefaultInstance(); } - List paths = new ArrayList(); + List paths = new ArrayList<>(); getFieldPaths(root, "", paths); return FieldMask.newBuilder().addAllPaths(paths).build(); } - /** - * Gathers all field paths in a sub-tree. - */ - private void getFieldPaths(Node node, String path, List paths) { + /** Gathers all field paths in a sub-tree. */ + private static void getFieldPaths(Node node, String path, List paths) { if (node.children.isEmpty()) { paths.add(path); return; @@ -188,7 +245,7 @@ void intersectFieldPath(String path, FieldMaskTree output) { } // We found a matching node for the path. All leaf children of this matching // node is in the intersection. - List paths = new ArrayList(); + List paths = new ArrayList<>(); getFieldPaths(node, path, paths); for (String value : paths) { output.addFieldPath(value); @@ -208,10 +265,8 @@ void merge(Message source, Message.Builder destination, FieldMaskUtil.MergeOptio merge(root, "", source, destination, options); } - /** - * Merges all fields specified by a sub-tree from {@code source} to {@code destination}. - */ - private void merge( + /** Merges all fields specified by a sub-tree from {@code source} to {@code destination}. */ + private static void merge( Node node, String path, Message source, @@ -241,16 +296,18 @@ private void merge( "Field \"" + field.getFullName() + "\" is not a " - + "singluar message field and cannot have sub-fields."); + + "singular message field and cannot have sub-fields."); + continue; + } + if (!source.hasField(field) && !destination.hasField(field)) { + // If the message field is not present in both source and destination, skip recursing + // so we don't create unnecessary empty messages. continue; } String childPath = path.isEmpty() ? entry.getKey() : path + "." + entry.getKey(); - merge( - entry.getValue(), - childPath, - (Message) source.getField(field), - destination.getFieldBuilder(field), - options); + Message.Builder childBuilder = ((Message) destination.getField(field)).toBuilder(); + merge(entry.getValue(), childPath, (Message) source.getField(field), childBuilder, options); + destination.setField(field, childBuilder.buildPartial()); continue; } if (field.isRepeated()) { @@ -271,7 +328,12 @@ private void merge( } } else { if (source.hasField(field)) { - destination.getFieldBuilder(field).mergeFrom((Message) source.getField(field)); + destination.setField( + field, + ((Message) destination.getField(field)) + .toBuilder() + .mergeFrom((Message) source.getField(field)) + .build()); } } } else { diff --git a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java index b2f849c491828..c32d10a2639c2 100644 --- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java +++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java @@ -34,14 +34,15 @@ import com.google.common.base.CaseFormat; import com.google.common.base.Joiner; +import com.google.common.base.Optional; import com.google.common.base.Splitter; import com.google.common.primitives.Ints; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.FieldMask; import com.google.protobuf.Internal; import com.google.protobuf.Message; - import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -49,7 +50,7 @@ /** * Utility helper functions to work with {@link com.google.protobuf.FieldMask}. */ -public class FieldMaskUtil { +public final class FieldMaskUtil { private static final String FIELD_PATH_SEPARATOR = ","; private static final String FIELD_PATH_SEPARATOR_REGEX = ","; private static final String FIELD_SEPARATOR_REGEX = "\\."; @@ -83,7 +84,7 @@ public static String toString(FieldMask fieldMask) { */ public static FieldMask fromString(String value) { // TODO(xiaofeng): Consider using com.google.common.base.Splitter here instead. - return fromStringList(null, Arrays.asList(value.split(FIELD_PATH_SEPARATOR_REGEX))); + return fromStringList(Arrays.asList(value.split(FIELD_PATH_SEPARATOR_REGEX))); } /** @@ -103,14 +104,36 @@ public static FieldMask fromString(Class type, String value) */ // TODO(xiaofeng): Consider renaming fromStrings() public static FieldMask fromStringList(Class type, Iterable paths) { + return fromStringList(Internal.getDefaultInstance(type).getDescriptorForType(), paths); + } + + /** + * Constructs a FieldMask for a list of field paths in a certain type. + * + * @throws IllegalArgumentException if any of the field path is not valid. + */ + public static FieldMask fromStringList(Descriptor descriptor, Iterable paths) { + return fromStringList(Optional.of(descriptor), paths); + } + + /** + * Constructs a FieldMask for a list of field paths in a certain type. Does not validate the given + * paths. + */ + public static FieldMask fromStringList(Iterable paths) { + return fromStringList(Optional.absent(), paths); + } + + private static FieldMask fromStringList(Optional descriptor, Iterable paths) { FieldMask.Builder builder = FieldMask.newBuilder(); for (String path : paths) { if (path.isEmpty()) { // Ignore empty field paths. continue; } - if (type != null && !isValid(type, path)) { - throw new IllegalArgumentException(path + " is not a valid path for " + type); + if (descriptor.isPresent() && !isValid(descriptor.get(), path)) { + throw new IllegalArgumentException( + path + " is not a valid path for " + descriptor.get().getFullName()); } builder.addPaths(path); } @@ -235,7 +258,7 @@ public static boolean isValid(Descriptor descriptor, String path) { /** * Converts a FieldMask to its canonical form. In the canonical form of a * FieldMask, all field paths are sorted alphabetically and redundant field - * paths are moved. + * paths are removed. */ public static FieldMask normalize(FieldMask mask) { return new FieldMaskTree(mask).toFieldMask(); @@ -253,6 +276,22 @@ public static FieldMask union( return maskTree.toFieldMask(); } + /** + * Subtracts {@code secondMask} and {@code otherMasks} from {@code firstMask}. + * + *

This method disregards proto structure. That is, if {@code firstMask} is "foo" and {@code + * secondMask} is "foo.bar", the response will always be "foo" without considering the internal + * proto structure of message "foo". + */ + public static FieldMask subtract( + FieldMask firstMask, FieldMask secondMask, FieldMask... otherMasks) { + FieldMaskTree maskTree = new FieldMaskTree(firstMask).removeFromFieldMask(secondMask); + for (FieldMask mask : otherMasks) { + maskTree.removeFromFieldMask(mask); + } + return maskTree.toFieldMask(); + } + /** * Calculates the intersection of two FieldMasks. */ @@ -277,9 +316,7 @@ public static final class MergeOptions { /** * Whether to replace message fields (i.e., discard existing content in - * destination message fields) when merging. - * Default behavior is to merge the source message field into the - * destination message field. + * destination message fields). */ public boolean replaceMessageFields() { return replaceMessageFields; @@ -287,9 +324,7 @@ public boolean replaceMessageFields() { /** * Whether to replace repeated fields (i.e., discard existing content in - * destination repeated fields) when merging. - * Default behavior is to append elements from source repeated field to the - * destination repeated field. + * destination repeated fields). */ public boolean replaceRepeatedFields() { return replaceRepeatedFields; @@ -297,30 +332,51 @@ public boolean replaceRepeatedFields() { /** * Whether to replace primitive (non-repeated and non-message) fields in - * destination message fields with the source primitive fields (i.e., if the - * field is set in the source, the value is copied to the - * destination; if the field is unset in the source, the field is cleared - * from the destination) when merging. - * - *

Default behavior is to always set the value of the source primitive - * field to the destination primitive field, and if the source field is - * unset, the default value of the source field is copied to the - * destination. + * destination message fields with the source primitive fields (i.e., clear + * destination field if source field is not set). */ public boolean replacePrimitiveFields() { return replacePrimitiveFields; } + /** + * Specify whether to replace message fields. Defaults to false. + * + *

If true, discard existing content in destination message fields when merging. + * + *

If false, merge the source message field into the destination message field. + */ + @CanIgnoreReturnValue public MergeOptions setReplaceMessageFields(boolean value) { replaceMessageFields = value; return this; } + /** + * Specify whether to replace repeated fields. Defaults to false. + * + *

If true, discard existing content in destination repeated fields) when merging. + * + *

If false, append elements from source repeated field to the destination repeated field. + */ + @CanIgnoreReturnValue public MergeOptions setReplaceRepeatedFields(boolean value) { replaceRepeatedFields = value; return this; } + /** + * Specify whether to replace primitive (non-repeated and non-message) fields in destination + * message fields with the source primitive fields. Defaults to false. + * + *

If true, set the value of the destination primitive field to the source primitive field if + * the source field is set, but clear the destination field otherwise. + * + *

If false, always set the value of the destination primitive field to the source primitive + * field, and if the source field is unset, the default value of the source field is copied to + * the destination. + */ + @CanIgnoreReturnValue public MergeOptions setReplacePrimitiveFields(boolean value) { replacePrimitiveFields = value; return this; @@ -328,8 +384,8 @@ public MergeOptions setReplacePrimitiveFields(boolean value) { } /** - * Merges fields specified by a FieldMask from one message to another with the - * specified merge options. + * Merges fields specified by a FieldMask from one message to another with the specified merge + * options. The destination will remain unchanged if an empty FieldMask is provided. */ public static void merge( FieldMask mask, Message source, Message.Builder destination, MergeOptions options) { diff --git a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java index a603d96aac7a3..4f2fe3fcfa4b7 100644 --- a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java +++ b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java @@ -32,6 +32,7 @@ import com.google.common.base.Preconditions; import com.google.common.io.BaseEncoding; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; @@ -50,6 +51,7 @@ import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Descriptors.FieldDescriptor.Type; import com.google.protobuf.Descriptors.FileDescriptor; import com.google.protobuf.Descriptors.OneofDescriptor; import com.google.protobuf.DoubleValue; @@ -76,7 +78,9 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.text.ParseException; +import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -104,15 +108,22 @@ private JsonFormat() {} */ public static Printer printer() { return new Printer( - TypeRegistry.getEmptyTypeRegistry(), false, Collections.emptySet(), - false, false); + com.google.protobuf.TypeRegistry.getEmptyTypeRegistry(), + TypeRegistry.getEmptyTypeRegistry(), + /* alwaysOutputDefaultValueFields */ false, + /* includingDefaultValueFields */ Collections.emptySet(), + /* preservingProtoFieldNames */ false, + /* omittingInsignificantWhitespace */ false, + /* printingEnumsAsInts */ false, + /* sortingMapKeys */ false); } /** * A Printer converts protobuf message to JSON format. */ public static class Printer { - private final TypeRegistry registry; + private final com.google.protobuf.TypeRegistry registry; + private final TypeRegistry oldRegistry; // NOTE: There are 3 states for these *defaultValueFields variables: // 1) Default - alwaysOutput is false & including is empty set. Fields only output if they are // set to non-default values. @@ -125,36 +136,70 @@ public static class Printer { private Set includingDefaultValueFields; private final boolean preservingProtoFieldNames; private final boolean omittingInsignificantWhitespace; + private final boolean printingEnumsAsInts; + private final boolean sortingMapKeys; private Printer( - TypeRegistry registry, + com.google.protobuf.TypeRegistry registry, + TypeRegistry oldRegistry, boolean alwaysOutputDefaultValueFields, Set includingDefaultValueFields, boolean preservingProtoFieldNames, - boolean omittingInsignificantWhitespace) { + boolean omittingInsignificantWhitespace, + boolean printingEnumsAsInts, + boolean sortingMapKeys) { this.registry = registry; + this.oldRegistry = oldRegistry; this.alwaysOutputDefaultValueFields = alwaysOutputDefaultValueFields; this.includingDefaultValueFields = includingDefaultValueFields; this.preservingProtoFieldNames = preservingProtoFieldNames; this.omittingInsignificantWhitespace = omittingInsignificantWhitespace; + this.printingEnumsAsInts = printingEnumsAsInts; + this.sortingMapKeys = sortingMapKeys; } /** - * Creates a new {@link Printer} using the given registry. The new Printer - * clones all other configurations from the current {@link Printer}. + * Creates a new {@link Printer} using the given registry. The new Printer clones all other + * configurations from the current {@link Printer}. * * @throws IllegalArgumentException if a registry is already set. */ - public Printer usingTypeRegistry(TypeRegistry registry) { - if (this.registry != TypeRegistry.getEmptyTypeRegistry()) { + public Printer usingTypeRegistry(TypeRegistry oldRegistry) { + if (this.oldRegistry != TypeRegistry.getEmptyTypeRegistry() + || this.registry != com.google.protobuf.TypeRegistry.getEmptyTypeRegistry()) { + throw new IllegalArgumentException("Only one registry is allowed."); + } + return new Printer( + com.google.protobuf.TypeRegistry.getEmptyTypeRegistry(), + oldRegistry, + alwaysOutputDefaultValueFields, + includingDefaultValueFields, + preservingProtoFieldNames, + omittingInsignificantWhitespace, + printingEnumsAsInts, + sortingMapKeys); + } + + /** + * Creates a new {@link Printer} using the given registry. The new Printer clones all other + * configurations from the current {@link Printer}. + * + * @throws IllegalArgumentException if a registry is already set. + */ + public Printer usingTypeRegistry(com.google.protobuf.TypeRegistry registry) { + if (this.oldRegistry != TypeRegistry.getEmptyTypeRegistry() + || this.registry != com.google.protobuf.TypeRegistry.getEmptyTypeRegistry()) { throw new IllegalArgumentException("Only one registry is allowed."); } return new Printer( registry, + oldRegistry, alwaysOutputDefaultValueFields, includingDefaultValueFields, preservingProtoFieldNames, - omittingInsignificantWhitespace); + omittingInsignificantWhitespace, + printingEnumsAsInts, + sortingMapKeys); } /** @@ -167,10 +212,38 @@ public Printer includingDefaultValueFields() { checkUnsetIncludingDefaultValueFields(); return new Printer( registry, + oldRegistry, true, Collections.emptySet(), preservingProtoFieldNames, - omittingInsignificantWhitespace); + omittingInsignificantWhitespace, + printingEnumsAsInts, + sortingMapKeys); + } + + /** + * Creates a new {@link Printer} that will print enum field values as integers instead of as + * string. + * The new Printer clones all other configurations from the current + * {@link Printer}. + */ + public Printer printingEnumsAsInts() { + checkUnsetPrintingEnumsAsInts(); + return new Printer( + registry, + oldRegistry, + alwaysOutputDefaultValueFields, + includingDefaultValueFields, + preservingProtoFieldNames, + omittingInsignificantWhitespace, + true, + sortingMapKeys); + } + + private void checkUnsetPrintingEnumsAsInts() { + if (printingEnumsAsInts) { + throw new IllegalStateException("JsonFormat printingEnumsAsInts has already been set."); + } } /** @@ -188,10 +261,13 @@ public Printer includingDefaultValueFields(Set fieldsToAlwaysOu checkUnsetIncludingDefaultValueFields(); return new Printer( registry, + oldRegistry, false, - fieldsToAlwaysOutput, + Collections.unmodifiableSet(new HashSet<>(fieldsToAlwaysOutput)), preservingProtoFieldNames, - omittingInsignificantWhitespace); + omittingInsignificantWhitespace, + printingEnumsAsInts, + sortingMapKeys); } private void checkUnsetIncludingDefaultValueFields() { @@ -210,10 +286,13 @@ private void checkUnsetIncludingDefaultValueFields() { public Printer preservingProtoFieldNames() { return new Printer( registry, + oldRegistry, alwaysOutputDefaultValueFields, includingDefaultValueFields, true, - omittingInsignificantWhitespace); + omittingInsignificantWhitespace, + printingEnumsAsInts, + sortingMapKeys); } @@ -237,9 +316,35 @@ public Printer preservingProtoFieldNames() { public Printer omittingInsignificantWhitespace() { return new Printer( registry, + oldRegistry, + alwaysOutputDefaultValueFields, + includingDefaultValueFields, + preservingProtoFieldNames, + true, + printingEnumsAsInts, + sortingMapKeys); + } + + /** + * Create a new {@link Printer} that will sort the map keys in the JSON output. + * + *

Use of this modifier is discouraged, the generated JSON messages are equivalent with and + * without this option set, but there are some corner use cases that demand a stable output, + * while order of map keys is otherwise arbitrary. + * + *

The generated order is not well-defined and should not be depended on, but it's stable. + * + *

This new Printer clones all other configurations from the current {@link Printer}. + */ + public Printer sortingMapKeys() { + return new Printer( + registry, + oldRegistry, alwaysOutputDefaultValueFields, includingDefaultValueFields, preservingProtoFieldNames, + omittingInsignificantWhitespace, + printingEnumsAsInts, true); } @@ -255,11 +360,14 @@ public void appendTo(MessageOrBuilder message, Appendable output) throws IOExcep // mobile. new PrinterImpl( registry, + oldRegistry, alwaysOutputDefaultValueFields, includingDefaultValueFields, preservingProtoFieldNames, output, - omittingInsignificantWhitespace) + omittingInsignificantWhitespace, + printingEnumsAsInts, + sortingMapKeys) .print(message); } @@ -285,37 +393,66 @@ public String print(MessageOrBuilder message) throws InvalidProtocolBufferExcept * Creates a {@link Parser} with default configuration. */ public static Parser parser() { - return new Parser(TypeRegistry.getEmptyTypeRegistry(), false, Parser.DEFAULT_RECURSION_LIMIT); + return new Parser( + com.google.protobuf.TypeRegistry.getEmptyTypeRegistry(), + TypeRegistry.getEmptyTypeRegistry(), + false, + Parser.DEFAULT_RECURSION_LIMIT); } /** * A Parser parses JSON to protobuf message. */ public static class Parser { - private final TypeRegistry registry; + private final com.google.protobuf.TypeRegistry registry; + private final TypeRegistry oldRegistry; private final boolean ignoringUnknownFields; private final int recursionLimit; // The default parsing recursion limit is aligned with the proto binary parser. private static final int DEFAULT_RECURSION_LIMIT = 100; - private Parser(TypeRegistry registry, boolean ignoreUnknownFields, int recursionLimit) { + private Parser( + com.google.protobuf.TypeRegistry registry, + TypeRegistry oldRegistry, + boolean ignoreUnknownFields, + int recursionLimit) { this.registry = registry; + this.oldRegistry = oldRegistry; this.ignoringUnknownFields = ignoreUnknownFields; this.recursionLimit = recursionLimit; } /** - * Creates a new {@link Parser} using the given registry. The new Parser - * clones all other configurations from this Parser. + * Creates a new {@link Parser} using the given registry. The new Parser clones all other + * configurations from this Parser. * * @throws IllegalArgumentException if a registry is already set. */ - public Parser usingTypeRegistry(TypeRegistry registry) { - if (this.registry != TypeRegistry.getEmptyTypeRegistry()) { + public Parser usingTypeRegistry(TypeRegistry oldRegistry) { + if (this.oldRegistry != TypeRegistry.getEmptyTypeRegistry() + || this.registry != com.google.protobuf.TypeRegistry.getEmptyTypeRegistry()) { throw new IllegalArgumentException("Only one registry is allowed."); } - return new Parser(registry, ignoringUnknownFields, recursionLimit); + return new Parser( + com.google.protobuf.TypeRegistry.getEmptyTypeRegistry(), + oldRegistry, + ignoringUnknownFields, + recursionLimit); + } + + /** + * Creates a new {@link Parser} using the given registry. The new Parser clones all other + * configurations from this Parser. + * + * @throws IllegalArgumentException if a registry is already set. + */ + public Parser usingTypeRegistry(com.google.protobuf.TypeRegistry registry) { + if (this.oldRegistry != TypeRegistry.getEmptyTypeRegistry() + || this.registry != com.google.protobuf.TypeRegistry.getEmptyTypeRegistry()) { + throw new IllegalArgumentException("Only one registry is allowed."); + } + return new Parser(registry, oldRegistry, ignoringUnknownFields, recursionLimit); } /** @@ -323,7 +460,7 @@ public Parser usingTypeRegistry(TypeRegistry registry) { * encountered. The new Parser clones all other configurations from this Parser. */ public Parser ignoringUnknownFields() { - return new Parser(this.registry, true, recursionLimit); + return new Parser(this.registry, oldRegistry, true, recursionLimit); } /** @@ -335,7 +472,8 @@ public Parser ignoringUnknownFields() { public void merge(String json, Message.Builder builder) throws InvalidProtocolBufferException { // TODO(xiaofeng): Investigate the allocation overhead and optimize for // mobile. - new ParserImpl(registry, ignoringUnknownFields, recursionLimit).merge(json, builder); + new ParserImpl(registry, oldRegistry, ignoringUnknownFields, recursionLimit) + .merge(json, builder); } /** @@ -348,12 +486,13 @@ public void merge(String json, Message.Builder builder) throws InvalidProtocolBu public void merge(Reader json, Message.Builder builder) throws IOException { // TODO(xiaofeng): Investigate the allocation overhead and optimize for // mobile. - new ParserImpl(registry, ignoringUnknownFields, recursionLimit).merge(json, builder); + new ParserImpl(registry, oldRegistry, ignoringUnknownFields, recursionLimit) + .merge(json, builder); } // For testing only. Parser usingRecursionLimit(int recursionLimit) { - return new Parser(registry, ignoringUnknownFields, recursionLimit); + return new Parser(registry, oldRegistry, ignoringUnknownFields, recursionLimit); } } @@ -379,44 +518,49 @@ public static Builder newBuilder() { } /** - * Find a type by its full name. Returns null if it cannot be found in - * this {@link TypeRegistry}. + * Find a type by its full name. Returns null if it cannot be found in this {@link + * TypeRegistry}. */ public Descriptor find(String name) { return types.get(name); } + Descriptor getDescriptorForTypeUrl(String typeUrl) throws InvalidProtocolBufferException { + return find(getTypeName(typeUrl)); + } + private final Map types; private TypeRegistry(Map types) { this.types = types; } - /** - * A Builder is used to build {@link TypeRegistry}. - */ + + /** A Builder is used to build {@link TypeRegistry}. */ public static class Builder { private Builder() {} /** - * Adds a message type and all types defined in the same .proto file as - * well as all transitively imported .proto files to this {@link Builder}. + * Adds a message type and all types defined in the same .proto file as well as all + * transitively imported .proto files to this {@link Builder}. */ + @CanIgnoreReturnValue public Builder add(Descriptor messageType) { if (types == null) { - throw new IllegalStateException("A TypeRegistry.Builer can only be used once."); + throw new IllegalStateException("A TypeRegistry.Builder can only be used once."); } addFile(messageType.getFile()); return this; } /** - * Adds message types and all types defined in the same .proto file as - * well as all transitively imported .proto files to this {@link Builder}. + * Adds message types and all types defined in the same .proto file as well as all + * transitively imported .proto files to this {@link Builder}. */ + @CanIgnoreReturnValue public Builder add(Iterable messageTypes) { if (types == null) { - throw new IllegalStateException("A TypeRegistry.Builer can only be used once."); + throw new IllegalStateException("A TypeRegistry.Builder can only be used once."); } for (Descriptor type : messageTypes) { addFile(type.getFile()); @@ -566,10 +710,13 @@ private void write(final CharSequence data) throws IOException { * A Printer converts protobuf messages to JSON format. */ private static final class PrinterImpl { - private final TypeRegistry registry; + private final com.google.protobuf.TypeRegistry registry; + private final TypeRegistry oldRegistry; private final boolean alwaysOutputDefaultValueFields; private final Set includingDefaultValueFields; private final boolean preservingProtoFieldNames; + private final boolean printingEnumsAsInts; + private final boolean sortingMapKeys; private final TextGenerator generator; // We use Gson to help handle string escapes. private final Gson gson; @@ -577,20 +724,26 @@ private static final class PrinterImpl { private final CharSequence blankOrNewLine; private static class GsonHolder { - private static final Gson DEFAULT_GSON = new GsonBuilder().disableHtmlEscaping().create(); + private static final Gson DEFAULT_GSON = new GsonBuilder().create(); } PrinterImpl( - TypeRegistry registry, + com.google.protobuf.TypeRegistry registry, + TypeRegistry oldRegistry, boolean alwaysOutputDefaultValueFields, Set includingDefaultValueFields, boolean preservingProtoFieldNames, Appendable jsonOutput, - boolean omittingInsignificantWhitespace) { + boolean omittingInsignificantWhitespace, + boolean printingEnumsAsInts, + boolean sortingMapKeys) { this.registry = registry; + this.oldRegistry = oldRegistry; this.alwaysOutputDefaultValueFields = alwaysOutputDefaultValueFields; this.includingDefaultValueFields = includingDefaultValueFields; this.preservingProtoFieldNames = preservingProtoFieldNames; + this.printingEnumsAsInts = printingEnumsAsInts; + this.sortingMapKeys = sortingMapKeys; this.gson = GsonHolder.DEFAULT_GSON; // json format related properties, determined by printerType if (omittingInsignificantWhitespace) { @@ -724,15 +877,17 @@ private void printAny(MessageOrBuilder message) throws IOException { throw new InvalidProtocolBufferException("Invalid Any type."); } String typeUrl = (String) message.getField(typeUrlField); - String typeName = getTypeName(typeUrl); - Descriptor type = registry.find(typeName); + Descriptor type = registry.getDescriptorForTypeUrl(typeUrl); if (type == null) { - throw new InvalidProtocolBufferException("Cannot find type for url: " + typeUrl); + type = oldRegistry.getDescriptorForTypeUrl(typeUrl); + if (type == null) { + throw new InvalidProtocolBufferException("Cannot find type for url: " + typeUrl); + } } ByteString content = (ByteString) message.getField(valueField); Message contentMessage = DynamicMessage.getDefaultInstance(type).getParserForType().parseFrom(content); - WellKnownTypePrinter printer = wellKnownTypePrinters.get(typeName); + WellKnownTypePrinter printer = wellKnownTypePrinters.get(getTypeName(typeUrl)); if (printer != null) { // If the type is one of the well-known types, we use a special // formatting. @@ -921,8 +1076,32 @@ private void printMapFieldValue(FieldDescriptor field, Object value) throws IOEx } generator.print("{" + blankOrNewLine); generator.indent(); + + @SuppressWarnings("unchecked") // Object guaranteed to be a List for a map field. + Collection elements = (List) value; + if (sortingMapKeys && !elements.isEmpty()) { + Comparator cmp = null; + if (keyField.getType() == FieldDescriptor.Type.STRING) { + cmp = new Comparator() { + @Override + public int compare(final Object o1, final Object o2) { + ByteString s1 = ByteString.copyFromUtf8((String) o1); + ByteString s2 = ByteString.copyFromUtf8((String) o2); + return ByteString.unsignedLexicographicalComparator().compare(s1, s2); + } + }; + } + TreeMap tm = new TreeMap(cmp); + for (Object element : elements) { + Message entry = (Message) element; + Object entryKey = entry.getField(keyField); + tm.put(entryKey, element); + } + elements = tm.values(); + } + boolean printedElement = false; - for (Object element : (List) value) { + for (Object element : elements) { Message entry = (Message) element; Object entryKey = entry.getField(keyField); Object entryValue = entry.getField(valueField); @@ -1069,7 +1248,7 @@ private void printSingleFieldValue( generator.print("\""); } } else { - if (((EnumValueDescriptor) value).getIndex() == -1) { + if (printingEnumsAsInts || ((EnumValueDescriptor) value).getIndex() == -1) { generator.print(String.valueOf(((EnumValueDescriptor) value).getNumber())); } else { generator.print("\"" + ((EnumValueDescriptor) value).getName() + "\""); @@ -1114,14 +1293,20 @@ private static String getTypeName(String typeUrl) throws InvalidProtocolBufferEx } private static class ParserImpl { - private final TypeRegistry registry; + private final com.google.protobuf.TypeRegistry registry; + private final TypeRegistry oldRegistry; private final JsonParser jsonParser; private final boolean ignoringUnknownFields; private final int recursionLimit; private int currentDepth; - ParserImpl(TypeRegistry registry, boolean ignoreUnknownFields, int recursionLimit) { + ParserImpl( + com.google.protobuf.TypeRegistry registry, + TypeRegistry oldRegistry, + boolean ignoreUnknownFields, + int recursionLimit) { this.registry = registry; + this.oldRegistry = oldRegistry; this.ignoringUnknownFields = ignoreUnknownFields; this.jsonParser = new JsonParser(); this.recursionLimit = recursionLimit; @@ -1342,9 +1527,12 @@ private void mergeAny(JsonElement json, Message.Builder builder) throw new InvalidProtocolBufferException("Missing type url when parsing: " + json); } String typeUrl = typeUrlElement.getAsString(); - Descriptor contentType = registry.find(getTypeName(typeUrl)); + Descriptor contentType = registry.getDescriptorForTypeUrl(typeUrl); if (contentType == null) { - throw new InvalidProtocolBufferException("Cannot resolve type: " + typeUrl); + contentType = oldRegistry.getDescriptorForTypeUrl(typeUrl); + if (contentType == null) { + throw new InvalidProtocolBufferException("Cannot resolve type: " + typeUrl); + } } builder.setField(typeUrlField, typeUrl); Message.Builder contentBuilder = @@ -1459,16 +1647,6 @@ private void mergeField(FieldDescriptor field, JsonElement json, Message.Builder throw new InvalidProtocolBufferException( "Field " + field.getFullName() + " has already been set."); } - if (field.getContainingOneof() != null - && builder.getOneofFieldDescriptor(field.getContainingOneof()) != null) { - FieldDescriptor other = builder.getOneofFieldDescriptor(field.getContainingOneof()); - throw new InvalidProtocolBufferException( - "Cannot set field " - + field.getFullName() - + " because another field " - + other.getFullName() - + " belonging to the same oneof has already been set "); - } } if (field.isRepeated() && json instanceof JsonNull) { // We allow "null" as value for all field types and treat it as if the @@ -1479,9 +1657,12 @@ private void mergeField(FieldDescriptor field, JsonElement json, Message.Builder mergeMapField(field, json, builder); } else if (field.isRepeated()) { mergeRepeatedField(field, json, builder); + } else if (field.getContainingOneof() != null) { + mergeOneofField(field, json, builder); } else { Object value = parseFieldValue(field, json, builder); if (value != null) { + // A field interpreted as "null" is means it's treated as absent. builder.setField(field, value); } } @@ -1504,7 +1685,11 @@ private void mergeMapField(FieldDescriptor field, JsonElement json, Message.Buil Object key = parseFieldValue(keyField, new JsonPrimitive(entry.getKey()), entryBuilder); Object value = parseFieldValue(valueField, entry.getValue(), entryBuilder); if (value == null) { - throw new InvalidProtocolBufferException("Map value cannot be null."); + if (ignoringUnknownFields && valueField.getType() == Type.ENUM) { + continue; + } else { + throw new InvalidProtocolBufferException("Map value cannot be null."); + } } entryBuilder.setField(keyField, key); entryBuilder.setField(valueField, value); @@ -1512,6 +1697,24 @@ private void mergeMapField(FieldDescriptor field, JsonElement json, Message.Buil } } + private void mergeOneofField(FieldDescriptor field, JsonElement json, Message.Builder builder) + throws InvalidProtocolBufferException { + Object value = parseFieldValue(field, json, builder); + if (value == null) { + // A field interpreted as "null" is means it's treated as absent. + return; + } + if (builder.getOneofFieldDescriptor(field.getContainingOneof()) != null) { + throw new InvalidProtocolBufferException( + "Cannot set field " + + field.getFullName() + + " because another field " + + builder.getOneofFieldDescriptor(field.getContainingOneof()).getFullName() + + " belonging to the same oneof has already been set "); + } + builder.setField(field, value); + } + private void mergeRepeatedField( FieldDescriptor field, JsonElement json, Message.Builder builder) throws InvalidProtocolBufferException { @@ -1522,7 +1725,12 @@ private void mergeRepeatedField( for (int i = 0; i < array.size(); ++i) { Object value = parseFieldValue(field, array.get(i), builder); if (value == null) { - throw new InvalidProtocolBufferException("Repeated field elements cannot be null"); + if (ignoringUnknownFields && field.getType() == Type.ENUM) { + continue; + } else { + throw new InvalidProtocolBufferException( + "Repeated field elements cannot be null in field: " + field.getFullName()); + } } builder.addRepeatedField(field, value); } @@ -1712,7 +1920,7 @@ private EnumValueDescriptor parseEnum(EnumDescriptor enumDescriptor, JsonElement // an exception later. } - if (result == null) { + if (result == null && !ignoringUnknownFields) { throw new InvalidProtocolBufferException( "Invalid enum value: " + value + " for enum type: " + enumDescriptor.getFullName()); } @@ -1735,6 +1943,14 @@ private Object parseFieldValue(FieldDescriptor field, JsonElement json, Message. return field.getEnumType().findValueByNumber(0); } return null; + } else if (json instanceof JsonObject) { + if (field.getType() != FieldDescriptor.Type.MESSAGE + && field.getType() != FieldDescriptor.Type.GROUP) { + // If the field type is primitive, but the json type is JsonObject rather than + // JsonElement, throw a type mismatch error. + throw new InvalidProtocolBufferException( + String.format("Invalid value: %s for expected type: %s", json, field.getType())); + } } switch (field.getType()) { case INT32: diff --git a/java/util/src/main/java/com/google/protobuf/util/Structs.java b/java/util/src/main/java/com/google/protobuf/util/Structs.java new file mode 100644 index 0000000000000..b1696ecdbcec4 --- /dev/null +++ b/java/util/src/main/java/com/google/protobuf/util/Structs.java @@ -0,0 +1,65 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf.util; + +import com.google.protobuf.Struct; +import com.google.protobuf.Value; + +/** Utilities to help create {@code google.protobuf.Struct} messages. */ +public final class Structs { + + /** + * Returns a struct containing the key-value pair. + */ + public static Struct of(String k1, Value v1) { + return Struct.newBuilder().putFields(k1, v1).build(); + } + + /** + * Returns a struct containing each of the key-value pairs. + * + *

Providing duplicate keys is undefined behavior. + */ + public static Struct of(String k1, Value v1, String k2, Value v2) { + return Struct.newBuilder().putFields(k1, v1).putFields(k2, v2).build(); + } + + /** + * Returns a struct containing each of the key-value pairs. + * + *

Providing duplicate keys is undefined behavior. + */ + public static Struct of(String k1, Value v1, String k2, Value v2, String k3, Value v3) { + return Struct.newBuilder().putFields(k1, v1).putFields(k2, v2).putFields(k3, v3).build(); + } + + private Structs() {} +} diff --git a/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java b/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java index 0475847349861..4ffb410fbb78f 100644 --- a/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java +++ b/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java @@ -325,6 +325,7 @@ public static Duration subtract(Duration d1, Duration d2) { // Multiplications and divisions. // TODO(kak): Delete this. + @SuppressWarnings("DurationSecondsToDouble") public static Duration multiply(Duration duration, double times) { double result = duration.getSeconds() * times + duration.getNanos() * times / 1000000000.0; if (result < Long.MIN_VALUE || result > Long.MAX_VALUE) { diff --git a/java/util/src/main/java/com/google/protobuf/util/Timestamps.java b/java/util/src/main/java/com/google/protobuf/util/Timestamps.java index 7a1f20149d595..fe9b9a50b838d 100644 --- a/java/util/src/main/java/com/google/protobuf/util/Timestamps.java +++ b/java/util/src/main/java/com/google/protobuf/util/Timestamps.java @@ -36,8 +36,10 @@ import static com.google.common.math.LongMath.checkedMultiply; import static com.google.common.math.LongMath.checkedSubtract; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Duration; import com.google.protobuf.Timestamp; +import java.io.Serializable; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Comparator; @@ -74,6 +76,11 @@ public final class Timestamps { public static final Timestamp MAX_VALUE = Timestamp.newBuilder().setSeconds(TIMESTAMP_SECONDS_MAX).setNanos(999999999).build(); + /** + * A constant holding the {@link Timestamp} of epoch time, {@code 1970-01-01T00:00:00.000000000Z}. + */ + public static final Timestamp EPOCH = Timestamp.newBuilder().setSeconds(0).setNanos(0).build(); + private static final ThreadLocal timestampFormat = new ThreadLocal() { @Override @@ -86,7 +93,7 @@ private static SimpleDateFormat createTimestampFormat() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH); GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC")); // We use Proleptic Gregorian Calendar (i.e., Gregorian calendar extends - // backwards to year one) for timestamp formating. + // backwards to year one) for timestamp formatting. calendar.setGregorianChange(new Date(Long.MIN_VALUE)); sdf.setCalendar(calendar); return sdf; @@ -94,34 +101,36 @@ private static SimpleDateFormat createTimestampFormat() { private Timestamps() {} - private static final Comparator COMPARATOR = - new Comparator() { - @Override - public int compare(Timestamp t1, Timestamp t2) { - checkValid(t1); - checkValid(t2); - int secDiff = Long.compare(t1.getSeconds(), t2.getSeconds()); - return (secDiff != 0) ? secDiff : Integer.compare(t1.getNanos(), t2.getNanos()); - } - }; + private static enum TimestampComparator implements Comparator, Serializable { + INSTANCE; + + @Override + public int compare(Timestamp t1, Timestamp t2) { + checkValid(t1); + checkValid(t2); + int secDiff = Long.compare(t1.getSeconds(), t2.getSeconds()); + return (secDiff != 0) ? secDiff : Integer.compare(t1.getNanos(), t2.getNanos()); + } + } /** - * Returns a {@link Comparator} for {@link Timestamp}s which sorts in increasing chronological - * order. Nulls and invalid {@link Timestamp}s are not allowed (see {@link #isValid}). + * Returns a {@link Comparator} for {@link Timestamp Timestamps} which sorts in increasing + * chronological order. Nulls and invalid {@link Timestamp Timestamps} are not allowed (see + * {@link #isValid}). The returned comparator is serializable. */ public static Comparator comparator() { - return COMPARATOR; + return TimestampComparator.INSTANCE; } /** - * Compares two timestamps. The value returned is identical to what would be returned by: - * {@code Timestamps.comparator().compare(x, y)}. + * Compares two timestamps. The value returned is identical to what would be returned by: {@code + * Timestamps.comparator().compare(x, y)}. * * @return the value {@code 0} if {@code x == y}; a value less than {@code 0} if {@code x < y}; * and a value greater than {@code 0} if {@code x > y} */ public static int compare(Timestamp x, Timestamp y) { - return COMPARATOR.compare(x, y); + return TimestampComparator.INSTANCE.compare(x, y); } /** @@ -145,6 +154,7 @@ public static boolean isValid(Timestamp timestamp) { *

Note: Negative second values with fractional seconds must still have non-negative * nanos values that count forward in time. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static boolean isValid(long seconds, int nanos) { if (seconds < TIMESTAMP_SECONDS_MIN || seconds > TIMESTAMP_SECONDS_MAX) { return false; @@ -156,18 +166,31 @@ public static boolean isValid(long seconds, int nanos) { } /** Throws an {@link IllegalArgumentException} if the given {@link Timestamp} is not valid. */ + @CanIgnoreReturnValue public static Timestamp checkValid(Timestamp timestamp) { long seconds = timestamp.getSeconds(); int nanos = timestamp.getNanos(); if (!isValid(seconds, nanos)) { - throw new IllegalArgumentException(String.format( - "Timestamp is not valid. See proto definition for valid values. " - + "Seconds (%s) must be in range [-62,135,596,800, +253,402,300,799]. " - + "Nanos (%s) must be in range [0, +999,999,999].", seconds, nanos)); + throw new IllegalArgumentException( + String.format( + "Timestamp is not valid. See proto definition for valid values. " + + "Seconds (%s) must be in range [-62,135,596,800, +253,402,300,799]. " + + "Nanos (%s) must be in range [0, +999,999,999].", + seconds, nanos)); } return timestamp; } + /** + * Builds the given builder and throws an {@link IllegalArgumentException} if it is not valid. See + * {@link #checkValid(Timestamp)}. + * + * @return A valid, built {@link Timestamp}. + */ + public static Timestamp checkValid(Timestamp.Builder timestampBuilder) { + return checkValid(timestampBuilder.build()); + } + /** * Convert Timestamp to RFC 3339 date string format. The output will always be Z-normalized and * uses 3, 6 or 9 fractional digits as required to represent the exact value. Note that Timestamp @@ -261,6 +284,7 @@ public static Timestamp parse(String value) throws ParseException { } /** Create a Timestamp from the number of seconds elapsed from the epoch. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static Timestamp fromSeconds(long seconds) { return normalizedTimestamp(seconds, 0); } @@ -271,11 +295,13 @@ public static Timestamp fromSeconds(long seconds) { *

The result will be rounded down to the nearest second. E.g., if the timestamp represents * "1969-12-31T23:59:59.999999999Z", it will be rounded to -1 second. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static long toSeconds(Timestamp timestamp) { return checkValid(timestamp).getSeconds(); } /** Create a Timestamp from the number of milliseconds elapsed from the epoch. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static Timestamp fromMillis(long milliseconds) { return normalizedTimestamp( milliseconds / MILLIS_PER_SECOND, @@ -288,6 +314,7 @@ public static Timestamp fromMillis(long milliseconds) { *

The result will be rounded down to the nearest millisecond. E.g., if the timestamp * represents "1969-12-31T23:59:59.999999999Z", it will be rounded to -1 millisecond. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static long toMillis(Timestamp timestamp) { checkValid(timestamp); return checkedAdd( @@ -296,6 +323,7 @@ public static long toMillis(Timestamp timestamp) { } /** Create a Timestamp from the number of microseconds elapsed from the epoch. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static Timestamp fromMicros(long microseconds) { return normalizedTimestamp( microseconds / MICROS_PER_SECOND, @@ -308,6 +336,7 @@ public static Timestamp fromMicros(long microseconds) { *

The result will be rounded down to the nearest microsecond. E.g., if the timestamp * represents "1969-12-31T23:59:59.999999999Z", it will be rounded to -1 microsecond. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static long toMicros(Timestamp timestamp) { checkValid(timestamp); return checkedAdd( @@ -316,12 +345,14 @@ public static long toMicros(Timestamp timestamp) { } /** Create a Timestamp from the number of nanoseconds elapsed from the epoch. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static Timestamp fromNanos(long nanoseconds) { return normalizedTimestamp( nanoseconds / NANOS_PER_SECOND, (int) (nanoseconds % NANOS_PER_SECOND)); } /** Convert a Timestamp to the number of nanoseconds elapsed from the epoch. */ + @SuppressWarnings("GoodTime") // this is a legacy conversion API public static long toNanos(Timestamp timestamp) { checkValid(timestamp); return checkedAdd( @@ -358,10 +389,12 @@ public static Timestamp subtract(Timestamp start, Duration length) { static Timestamp normalizedTimestamp(long seconds, int nanos) { if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) { seconds = checkedAdd(seconds, nanos / NANOS_PER_SECOND); - nanos %= NANOS_PER_SECOND; + nanos = (int) (nanos % NANOS_PER_SECOND); } if (nanos < 0) { - nanos += NANOS_PER_SECOND; // no overflow since nanos is negative (and we're adding) + nanos = + (int) + (nanos + NANOS_PER_SECOND); // no overflow since nanos is negative (and we're adding) seconds = checkedSubtract(seconds, 1); } Timestamp timestamp = Timestamp.newBuilder().setSeconds(seconds).setNanos(nanos).build(); diff --git a/java/util/src/main/java/com/google/protobuf/util/Values.java b/java/util/src/main/java/com/google/protobuf/util/Values.java new file mode 100644 index 0000000000000..f03d70e0dcd34 --- /dev/null +++ b/java/util/src/main/java/com/google/protobuf/util/Values.java @@ -0,0 +1,85 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf.util; + +import com.google.protobuf.ListValue; +import com.google.protobuf.NullValue; +import com.google.protobuf.Struct; +import com.google.protobuf.Value; + +/** Utilities to help create {@code google.protobuf.Value} messages. */ +public final class Values { + + private static final Value NULL_VALUE = + Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build(); + + public static Value ofNull() { + return NULL_VALUE; + } + + /** Returns a Value object with number set to value. */ + public static Value of(boolean value) { + return Value.newBuilder().setBoolValue(value).build(); + } + + /** Returns a Value object with number set to value. */ + public static Value of(double value) { + return Value.newBuilder().setNumberValue(value).build(); + } + + /** Returns a Value object with string set to value. */ + public static Value of(String value) { + return Value.newBuilder().setStringValue(value).build(); + } + + /** Returns a Value object with struct set to value. */ + public static Value of(Struct value) { + return Value.newBuilder().setStructValue(value).build(); + } + + /** Returns a Value with ListValue set to value. */ + public static Value of(ListValue value) { + return Value.newBuilder().setListValue(value).build(); + } + + /** + * Returns a Value with ListValue set to the appending the result of calling {@link #of} on each + * element in the iterable. + */ + public static Value of(Iterable values) { + Value.Builder valueBuilder = Value.newBuilder(); + ListValue.Builder listValue = valueBuilder.getListValueBuilder(); + listValue.addAllValues(values); + return valueBuilder.build(); + } + + private Values() {} +} diff --git a/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java b/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java index 3ee0fc6e6aaf4..c8297226f77a4 100644 --- a/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java +++ b/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java @@ -30,18 +30,24 @@ package com.google.protobuf.util; +import static com.google.common.truth.Truth.assertThat; + +import com.google.protobuf.DynamicMessage; +import com.google.protobuf.Message; +import com.google.protobuf.UninitializedMessageException; import protobuf_unittest.UnittestProto.NestedTestAllTypes; import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage; - +import protobuf_unittest.UnittestProto.TestRequired; +import protobuf_unittest.UnittestProto.TestRequiredMessage; import junit.framework.TestCase; public class FieldMaskTreeTest extends TestCase { public void testAddFieldPath() throws Exception { FieldMaskTree tree = new FieldMaskTree(); - assertEquals("", tree.toString()); + assertThat(tree.toString()).isEmpty(); tree.addFieldPath(""); - assertEquals("", tree.toString()); + assertThat(tree.toString()).isEmpty(); // New branch. tree.addFieldPath("foo"); assertEquals("foo", tree.toString()); @@ -69,15 +75,57 @@ public void testMergeFromFieldMask() throws Exception { assertEquals("bar,foo", tree.toString()); } + public void testRemoveFieldPath() throws Exception { + String initialTreeString = "bar.baz,bar.quz.bar,foo"; + FieldMaskTree tree; + + // Empty path. + tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString)); + tree.removeFieldPath(""); + assertEquals(initialTreeString, tree.toString()); + + // Non-exist sub-path of an existing leaf. + tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString)); + tree.removeFieldPath("foo.bar"); + assertEquals(initialTreeString, tree.toString()); + + // Non-exist path. + tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString)); + tree.removeFieldPath("bar.foo"); + assertEquals(initialTreeString, tree.toString()); + + // Match an existing leaf node -> remove leaf node. + tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString)); + tree.removeFieldPath("foo"); + assertEquals("bar.baz,bar.quz.bar", tree.toString()); + + // Match sub-path of an existing leaf node -> recursive removal. + tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString)); + tree.removeFieldPath("bar.quz.bar"); + assertEquals("bar.baz,foo", tree.toString()); + + // Match a non-leaf node -> remove all children. + tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString)); + tree.removeFieldPath("bar"); + assertEquals("foo", tree.toString()); + } + + public void testRemoveFromFieldMask() throws Exception { + FieldMaskTree tree = new FieldMaskTree(FieldMaskUtil.fromString("foo,bar.baz,bar.quz")); + assertEquals("bar.baz,bar.quz,foo", tree.toString()); + tree.removeFromFieldMask(FieldMaskUtil.fromString("foo.bar,bar")); + assertEquals("foo", tree.toString()); + } + public void testIntersectFieldPath() throws Exception { FieldMaskTree tree = new FieldMaskTree(FieldMaskUtil.fromString("foo,bar.baz,bar.quz")); FieldMaskTree result = new FieldMaskTree(); // Empty path. tree.intersectFieldPath("", result); - assertEquals("", result.toString()); + assertThat(result.toString()).isEmpty(); // Non-exist path. tree.intersectFieldPath("quz", result); - assertEquals("", result.toString()); + assertThat(result.toString()).isEmpty(); // Sub-path of an existing leaf. tree.intersectFieldPath("foo.bar", result); assertEquals("foo.bar", result.toString()); @@ -93,6 +141,66 @@ public void testIntersectFieldPath() throws Exception { } public void testMerge() throws Exception { + testMergeImpl(true); + testMergeImpl(false); + testMergeRequire(false); + testMergeRequire(true); + } + + private void merge( + FieldMaskTree tree, + Message source, + Message.Builder builder, + FieldMaskUtil.MergeOptions options, + boolean useDynamicMessage) + throws Exception { + if (useDynamicMessage) { + Message.Builder newBuilder = + DynamicMessage.newBuilder(source.getDescriptorForType()) + .mergeFrom(builder.buildPartial().toByteArray()); + tree.merge( + DynamicMessage.newBuilder(source.getDescriptorForType()) + .mergeFrom(source.toByteArray()) + .build(), + newBuilder, + options); + builder.clear(); + builder.mergeFrom(newBuilder.buildPartial()); + } else { + tree.merge(source, builder, options); + } + } + + private void testMergeRequire(boolean useDynamicMessage) throws Exception { + TestRequired value = TestRequired.newBuilder().setA(4321).setB(8765).setC(233333).build(); + TestRequiredMessage source = TestRequiredMessage.newBuilder().setRequiredMessage(value).build(); + + FieldMaskUtil.MergeOptions options = new FieldMaskUtil.MergeOptions(); + TestRequiredMessage.Builder builder = TestRequiredMessage.newBuilder(); + merge( + new FieldMaskTree().addFieldPath("required_message.a"), + source, + builder, + options, + useDynamicMessage); + assertTrue(builder.hasRequiredMessage()); + assertTrue(builder.getRequiredMessage().hasA()); + assertFalse(builder.getRequiredMessage().hasB()); + assertFalse(builder.getRequiredMessage().hasC()); + merge( + new FieldMaskTree().addFieldPath("required_message.b").addFieldPath("required_message.c"), + source, + builder, + options, + useDynamicMessage); + try { + assertEquals(builder.build(), source); + } catch (UninitializedMessageException e) { + throw new AssertionError("required field isn't set", e); + } + } + + private void testMergeImpl(boolean useDynamicMessage) throws Exception { TestAllTypes value = TestAllTypes.newBuilder() .setOptionalInt32(1234) @@ -118,47 +226,61 @@ public void testMerge() throws Exception { FieldMaskUtil.MergeOptions options = new FieldMaskUtil.MergeOptions(); - // Test merging each individual field. + // Test merging with an empty FieldMask. NestedTestAllTypes.Builder builder = NestedTestAllTypes.newBuilder(); - new FieldMaskTree().addFieldPath("payload.optional_int32").merge(source, builder, options); + builder.getPayloadBuilder().addRepeatedInt32(1000); + merge(new FieldMaskTree(), source, builder, options, useDynamicMessage); NestedTestAllTypes.Builder expected = NestedTestAllTypes.newBuilder(); + expected.getPayloadBuilder().addRepeatedInt32(1000); + assertEquals(expected.build(), builder.build()); + + // Test merging each individual field. + builder = NestedTestAllTypes.newBuilder(); + merge(new FieldMaskTree().addFieldPath("payload.optional_int32"), + source, builder, options, useDynamicMessage); + expected = NestedTestAllTypes.newBuilder(); expected.getPayloadBuilder().setOptionalInt32(1234); assertEquals(expected.build(), builder.build()); builder = NestedTestAllTypes.newBuilder(); - new FieldMaskTree() - .addFieldPath("payload.optional_nested_message") - .merge(source, builder, options); + merge(new FieldMaskTree().addFieldPath("payload.optional_nested_message"), + source, builder, options, useDynamicMessage); expected = NestedTestAllTypes.newBuilder(); expected.getPayloadBuilder().setOptionalNestedMessage(NestedMessage.newBuilder().setBb(5678)); assertEquals(expected.build(), builder.build()); builder = NestedTestAllTypes.newBuilder(); - new FieldMaskTree().addFieldPath("payload.repeated_int32").merge(source, builder, options); + merge(new FieldMaskTree().addFieldPath("payload.repeated_int32"), + source, builder, options, useDynamicMessage); expected = NestedTestAllTypes.newBuilder(); expected.getPayloadBuilder().addRepeatedInt32(4321); assertEquals(expected.build(), builder.build()); builder = NestedTestAllTypes.newBuilder(); - new FieldMaskTree() - .addFieldPath("payload.repeated_nested_message") - .merge(source, builder, options); + merge(new FieldMaskTree().addFieldPath("payload.repeated_nested_message"), + source, builder, options, useDynamicMessage); expected = NestedTestAllTypes.newBuilder(); expected.getPayloadBuilder().addRepeatedNestedMessage(NestedMessage.newBuilder().setBb(8765)); assertEquals(expected.build(), builder.build()); builder = NestedTestAllTypes.newBuilder(); - new FieldMaskTree() - .addFieldPath("child.payload.optional_int32") - .merge(source, builder, options); + merge( + new FieldMaskTree().addFieldPath("child.payload.optional_int32"), + source, + builder, + options, + useDynamicMessage); expected = NestedTestAllTypes.newBuilder(); expected.getChildBuilder().getPayloadBuilder().setOptionalInt32(1234); assertEquals(expected.build(), builder.build()); builder = NestedTestAllTypes.newBuilder(); - new FieldMaskTree() - .addFieldPath("child.payload.optional_nested_message") - .merge(source, builder, options); + merge( + new FieldMaskTree().addFieldPath("child.payload.optional_nested_message"), + source, + builder, + options, + useDynamicMessage); expected = NestedTestAllTypes.newBuilder(); expected .getChildBuilder() @@ -167,17 +289,15 @@ public void testMerge() throws Exception { assertEquals(expected.build(), builder.build()); builder = NestedTestAllTypes.newBuilder(); - new FieldMaskTree() - .addFieldPath("child.payload.repeated_int32") - .merge(source, builder, options); + merge(new FieldMaskTree().addFieldPath("child.payload.repeated_int32"), + source, builder, options, useDynamicMessage); expected = NestedTestAllTypes.newBuilder(); expected.getChildBuilder().getPayloadBuilder().addRepeatedInt32(4321); assertEquals(expected.build(), builder.build()); builder = NestedTestAllTypes.newBuilder(); - new FieldMaskTree() - .addFieldPath("child.payload.repeated_nested_message") - .merge(source, builder, options); + merge(new FieldMaskTree().addFieldPath("child.payload.repeated_nested_message"), + source, builder, options, useDynamicMessage); expected = NestedTestAllTypes.newBuilder(); expected .getChildBuilder() @@ -187,23 +307,23 @@ public void testMerge() throws Exception { // Test merging all fields. builder = NestedTestAllTypes.newBuilder(); - new FieldMaskTree() - .addFieldPath("child") - .addFieldPath("payload") - .merge(source, builder, options); + merge(new FieldMaskTree().addFieldPath("child").addFieldPath("payload"), + source, builder, options, useDynamicMessage); assertEquals(source, builder.build()); // Test repeated options. builder = NestedTestAllTypes.newBuilder(); builder.getPayloadBuilder().addRepeatedInt32(1000); - new FieldMaskTree().addFieldPath("payload.repeated_int32").merge(source, builder, options); + merge(new FieldMaskTree().addFieldPath("payload.repeated_int32"), + source, builder, options, useDynamicMessage); // Default behavior is to append repeated fields. assertEquals(2, builder.getPayload().getRepeatedInt32Count()); assertEquals(1000, builder.getPayload().getRepeatedInt32(0)); assertEquals(4321, builder.getPayload().getRepeatedInt32(1)); // Change to replace repeated fields. options.setReplaceRepeatedFields(true); - new FieldMaskTree().addFieldPath("payload.repeated_int32").merge(source, builder, options); + merge(new FieldMaskTree().addFieldPath("payload.repeated_int32"), + source, builder, options, useDynamicMessage); assertEquals(1, builder.getPayload().getRepeatedInt32Count()); assertEquals(4321, builder.getPayload().getRepeatedInt32(0)); @@ -211,7 +331,8 @@ public void testMerge() throws Exception { builder = NestedTestAllTypes.newBuilder(); builder.getPayloadBuilder().setOptionalInt32(1000); builder.getPayloadBuilder().setOptionalUint32(2000); - new FieldMaskTree().addFieldPath("payload").merge(source, builder, options); + merge(new FieldMaskTree().addFieldPath("payload"), + source, builder, options, useDynamicMessage); // Default behavior is to merge message fields. assertEquals(1234, builder.getPayload().getOptionalInt32()); assertEquals(2000, builder.getPayload().getOptionalUint32()); @@ -219,7 +340,14 @@ public void testMerge() throws Exception { // Test merging unset message fields. NestedTestAllTypes clearedSource = source.toBuilder().clearPayload().build(); builder = NestedTestAllTypes.newBuilder(); - new FieldMaskTree().addFieldPath("payload").merge(clearedSource, builder, options); + merge(new FieldMaskTree().addFieldPath("payload"), + clearedSource, builder, options, useDynamicMessage); + assertEquals(false, builder.hasPayload()); + + // Skip a message field if they are unset in both source and target. + builder = NestedTestAllTypes.newBuilder(); + merge(new FieldMaskTree().addFieldPath("payload.optional_int32"), + clearedSource, builder, options, useDynamicMessage); assertEquals(false, builder.hasPayload()); // Change to replace message fields. @@ -227,7 +355,8 @@ public void testMerge() throws Exception { builder = NestedTestAllTypes.newBuilder(); builder.getPayloadBuilder().setOptionalInt32(1000); builder.getPayloadBuilder().setOptionalUint32(2000); - new FieldMaskTree().addFieldPath("payload").merge(source, builder, options); + merge(new FieldMaskTree().addFieldPath("payload"), + source, builder, options, useDynamicMessage); assertEquals(1234, builder.getPayload().getOptionalInt32()); assertEquals(0, builder.getPayload().getOptionalUint32()); @@ -235,7 +364,8 @@ public void testMerge() throws Exception { builder = NestedTestAllTypes.newBuilder(); builder.getPayloadBuilder().setOptionalInt32(1000); builder.getPayloadBuilder().setOptionalUint32(2000); - new FieldMaskTree().addFieldPath("payload").merge(clearedSource, builder, options); + merge(new FieldMaskTree().addFieldPath("payload"), + clearedSource, builder, options, useDynamicMessage); assertEquals(false, builder.hasPayload()); // Test merging unset primitive fields. @@ -243,18 +373,16 @@ public void testMerge() throws Exception { builder.getPayloadBuilder().clearOptionalInt32(); NestedTestAllTypes sourceWithPayloadInt32Unset = builder.build(); builder = source.toBuilder(); - new FieldMaskTree() - .addFieldPath("payload.optional_int32") - .merge(sourceWithPayloadInt32Unset, builder, options); + merge(new FieldMaskTree().addFieldPath("payload.optional_int32"), + sourceWithPayloadInt32Unset, builder, options, useDynamicMessage); assertEquals(true, builder.getPayload().hasOptionalInt32()); assertEquals(0, builder.getPayload().getOptionalInt32()); // Change to clear unset primitive fields. options.setReplacePrimitiveFields(true); builder = source.toBuilder(); - new FieldMaskTree() - .addFieldPath("payload.optional_int32") - .merge(sourceWithPayloadInt32Unset, builder, options); + merge(new FieldMaskTree().addFieldPath("payload.optional_int32"), + sourceWithPayloadInt32Unset, builder, options, useDynamicMessage); assertEquals(true, builder.hasPayload()); assertEquals(false, builder.getPayload().hasOptionalInt32()); } diff --git a/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java b/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java index 1a998570532b9..28e43a7bf77b3 100644 --- a/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java +++ b/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java @@ -30,10 +30,12 @@ package com.google.protobuf.util; +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.ImmutableList; import com.google.protobuf.FieldMask; import protobuf_unittest.UnittestProto.NestedTestAllTypes; import protobuf_unittest.UnittestProto.TestAllTypes; - import junit.framework.TestCase; /** Unit tests for {@link FieldMaskUtil}. */ @@ -172,6 +174,38 @@ public void testFromJsonString() throws Exception { assertEquals("bar_baz", mask.getPaths(1)); } + public void testFromStringList() throws Exception { + FieldMask mask = + FieldMaskUtil.fromStringList( + NestedTestAllTypes.class, ImmutableList.of("payload.repeated_nested_message", "child")); + assertThat(mask) + .isEqualTo( + FieldMask.newBuilder() + .addPaths("payload.repeated_nested_message") + .addPaths("child") + .build()); + + mask = + FieldMaskUtil.fromStringList( + NestedTestAllTypes.getDescriptor(), + ImmutableList.of("payload.repeated_nested_message", "child")); + assertThat(mask) + .isEqualTo( + FieldMask.newBuilder() + .addPaths("payload.repeated_nested_message") + .addPaths("child") + .build()); + + mask = + FieldMaskUtil.fromStringList(ImmutableList.of("payload.repeated_nested_message", "child")); + assertThat(mask) + .isEqualTo( + FieldMask.newBuilder() + .addPaths("payload.repeated_nested_message") + .addPaths("child") + .build()); + } + public void testUnion() throws Exception { // Only test a simple case here and expect // {@link FieldMaskTreeTest#testAddFieldPath} to cover all scenarios. @@ -190,6 +224,24 @@ public void testUnion_usingVarArgs() throws Exception { assertEquals("bar,foo", FieldMaskUtil.toString(result)); } + public void testSubstract() throws Exception { + // Only test a simple case here and expect + // {@link FieldMaskTreeTest#testRemoveFieldPath} to cover all scenarios. + FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz"); + FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar"); + FieldMask result = FieldMaskUtil.subtract(mask1, mask2); + assertEquals("foo", FieldMaskUtil.toString(result)); + } + + public void testSubstract_usingVarArgs() throws Exception { + FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz.bar"); + FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar.baz.quz"); + FieldMask mask3 = FieldMaskUtil.fromString("bar.quz"); + FieldMask mask4 = FieldMaskUtil.fromString("foo,bar.baz"); + FieldMask result = FieldMaskUtil.subtract(mask1, mask2, mask3, mask4); + assertThat(FieldMaskUtil.toString(result)).isEmpty(); + } + public void testIntersection() throws Exception { // Only test a simple case here and expect // {@link FieldMaskTreeTest#testIntersectFieldPath} to cover all scenarios. diff --git a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java index e4c5387af76d3..6133bb49a83c5 100644 --- a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java +++ b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java @@ -30,10 +30,12 @@ package com.google.protobuf.util; +import com.google.common.collect.ImmutableSet; import com.google.protobuf.Any; import com.google.protobuf.BoolValue; import com.google.protobuf.ByteString; import com.google.protobuf.BytesValue; +import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.DoubleValue; import com.google.protobuf.FloatValue; @@ -49,19 +51,20 @@ import com.google.protobuf.UInt64Value; import com.google.protobuf.Value; import com.google.protobuf.util.JsonFormat.TypeRegistry; -import com.google.protobuf.util.JsonTestProto.TestAllTypes; -import com.google.protobuf.util.JsonTestProto.TestAllTypes.NestedEnum; -import com.google.protobuf.util.JsonTestProto.TestAllTypes.NestedMessage; -import com.google.protobuf.util.JsonTestProto.TestAny; -import com.google.protobuf.util.JsonTestProto.TestCustomJsonName; -import com.google.protobuf.util.JsonTestProto.TestDuration; -import com.google.protobuf.util.JsonTestProto.TestFieldMask; -import com.google.protobuf.util.JsonTestProto.TestMap; -import com.google.protobuf.util.JsonTestProto.TestOneof; -import com.google.protobuf.util.JsonTestProto.TestRecursive; -import com.google.protobuf.util.JsonTestProto.TestStruct; -import com.google.protobuf.util.JsonTestProto.TestTimestamp; -import com.google.protobuf.util.JsonTestProto.TestWrappers; +import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes; +import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes.AliasedEnum; +import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes.NestedEnum; +import com.google.protobuf.util.proto.JsonTestProto.TestAllTypes.NestedMessage; +import com.google.protobuf.util.proto.JsonTestProto.TestAny; +import com.google.protobuf.util.proto.JsonTestProto.TestCustomJsonName; +import com.google.protobuf.util.proto.JsonTestProto.TestDuration; +import com.google.protobuf.util.proto.JsonTestProto.TestFieldMask; +import com.google.protobuf.util.proto.JsonTestProto.TestMap; +import com.google.protobuf.util.proto.JsonTestProto.TestOneof; +import com.google.protobuf.util.proto.JsonTestProto.TestRecursive; +import com.google.protobuf.util.proto.JsonTestProto.TestStruct; +import com.google.protobuf.util.proto.JsonTestProto.TestTimestamp; +import com.google.protobuf.util.proto.JsonTestProto.TestWrappers; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -70,7 +73,6 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Locale; import java.util.Set; @@ -151,17 +153,35 @@ private void assertRoundTripEquals(Message message, TypeRegistry registry) throw assertEquals(message.toString(), parsedMessage.toString()); } + private void assertRoundTripEquals(Message message, com.google.protobuf.TypeRegistry registry) + throws Exception { + JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry); + JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(registry); + Message.Builder builder = message.newBuilderForType(); + parser.merge(printer.print(message), builder); + Message parsedMessage = builder.build(); + assertEquals(message.toString(), parsedMessage.toString()); + } + private String toJsonString(Message message) throws IOException { return JsonFormat.printer().print(message); } private String toCompactJsonString(Message message) throws IOException { return JsonFormat.printer().omittingInsignificantWhitespace().print(message); } + private String toSortedJsonString(Message message) throws IOException { + return JsonFormat.printer().sortingMapKeys().print(message); + } private void mergeFromJson(String json, Message.Builder builder) throws IOException { JsonFormat.parser().merge(json, builder); } + private void mergeFromJsonIgnoringUnknownFields(String json, Message.Builder builder) + throws IOException { + JsonFormat.parser().ignoringUnknownFields().merge(json, builder); + } + public void testAllFields() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); setAllFields(builder); @@ -455,6 +475,20 @@ public void testNullInOneof() throws Exception { assertEquals(NullValue.NULL_VALUE, message.getOneofNullValue()); } + public void testNullFirstInDuplicateOneof() throws Exception { + TestOneof.Builder builder = TestOneof.newBuilder(); + mergeFromJson("{\"oneofNestedMessage\": null, \"oneofInt32\": 1}", builder); + TestOneof message = builder.build(); + assertEquals(1, message.getOneofInt32()); + } + + public void testNullLastInDuplicateOneof() throws Exception { + TestOneof.Builder builder = TestOneof.newBuilder(); + mergeFromJson("{\"oneofInt32\": 1, \"oneofNestedMessage\": null}", builder); + TestOneof message = builder.build(); + assertEquals(1, message.getOneofInt32()); + } + public void testParserRejectDuplicatedFields() throws Exception { // TODO(xiaofeng): The parser we are currently using (GSON) will accept and keep the last // one if multiple entries have the same name. This is not the desired behavior but it can @@ -669,18 +703,27 @@ public void testMapNullValueIsRejected() throws Exception { + "}", builder); fail(); + } catch (InvalidProtocolBufferException e) { // Exception expected. } } + public void testMapEnumNullValueIsIgnored() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + mergeFromJsonIgnoringUnknownFields( + "{\n" + " \"int32ToEnumMap\": {\"1\": null}\n" + "}", builder); + TestMap map = builder.build(); + assertEquals(0, map.getInt32ToEnumMapMap().size()); + } + public void testParserAcceptNonQuotedObjectKey() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); mergeFromJson( "{\n" + " int32ToInt32Map: {1: 2},\n" + " stringToInt32Map: {hello: 3}\n" + "}", builder); TestMap message = builder.build(); - assertEquals(2, message.getInt32ToInt32Map().get(1).intValue()); - assertEquals(3, message.getStringToInt32Map().get("hello").intValue()); + assertEquals(2, message.getInt32ToInt32MapMap().get(1).intValue()); + assertEquals(3, message.getStringToInt32MapMap().get("hello").intValue()); } public void testWrappers() throws Exception { @@ -817,6 +860,46 @@ public void testStruct() throws Exception { assertRoundTripEquals(message); } + + public void testAnyFieldsWithCustomAddedTypeRegistry() throws Exception { + TestAllTypes content = TestAllTypes.newBuilder().setOptionalInt32(1234).build(); + TestAny message = TestAny.newBuilder().setAnyValue(Any.pack(content)).build(); + + com.google.protobuf.TypeRegistry registry = + com.google.protobuf.TypeRegistry.newBuilder().add(content.getDescriptorForType()).build(); + JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry); + + assertEquals( + "{\n" + + " \"anyValue\": {\n" + + " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n" + + " \"optionalInt32\": 1234\n" + + " }\n" + + "}", + printer.print(message)); + assertRoundTripEquals(message, registry); + + TestAny messageWithDefaultAnyValue = + TestAny.newBuilder().setAnyValue(Any.getDefaultInstance()).build(); + assertEquals("{\n" + " \"anyValue\": {}\n" + "}", printer.print(messageWithDefaultAnyValue)); + assertRoundTripEquals(messageWithDefaultAnyValue, registry); + + // Well-known types have a special formatting when embedded in Any. + // + // 1. Any in Any. + Any anyMessage = Any.pack(Any.pack(content)); + assertEquals( + "{\n" + + " \"@type\": \"type.googleapis.com/google.protobuf.Any\",\n" + + " \"value\": {\n" + + " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n" + + " \"optionalInt32\": 1234\n" + + " }\n" + + "}", + printer.print(anyMessage)); + assertRoundTripEquals(anyMessage, registry); + } + public void testAnyFields() throws Exception { TestAllTypes content = TestAllTypes.newBuilder().setOptionalInt32(1234).build(); TestAny message = TestAny.newBuilder().setAnyValue(Any.pack(content)).build(); @@ -1103,7 +1186,7 @@ public void testParserUnexpectedTypeUrl() throws Exception { Any.Builder builder = Any.newBuilder(); mergeFromJson( "{\n" - + " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n" + + " \"@type\": \"type.googleapis.com/json_test.UnexpectedTypes\",\n" + " \"optionalInt32\": 12345\n" + "}", builder); @@ -1143,8 +1226,8 @@ public void testParserRejectInvalidBase64() throws Exception { } public void testParserAcceptBase64Variants() throws Exception { - assertAccepts("optionalBytes", "AQI"); // No padding - assertAccepts("optionalBytes", "-_w"); // base64Url, no padding + assertAccepts("optionalBytes", "AQI"); // No padding + assertAccepts("optionalBytes", "-_w"); // base64Url, no padding } public void testParserRejectInvalidEnumValue() throws Exception { @@ -1174,16 +1257,74 @@ public void testParserIgnoringUnknownFields() throws Exception { JsonFormat.parser().ignoringUnknownFields().merge(json, builder); } + public void testParserIgnoringUnknownEnums() throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + String json = "{\n" + " \"optionalNestedEnum\": \"XXX\"\n" + "}"; + JsonFormat.parser().ignoringUnknownFields().merge(json, builder); + assertEquals(0, builder.getOptionalNestedEnumValue()); + } + + public void testParserSupportAliasEnums() throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + String json = "{\n" + " \"optionalAliasedEnum\": \"QUX\"\n" + "}"; + JsonFormat.parser().merge(json, builder); + assertEquals(AliasedEnum.ALIAS_BAZ, builder.getOptionalAliasedEnum()); + + builder = TestAllTypes.newBuilder(); + json = "{\n" + " \"optionalAliasedEnum\": \"qux\"\n" + "}"; + JsonFormat.parser().merge(json, builder); + assertEquals(AliasedEnum.ALIAS_BAZ, builder.getOptionalAliasedEnum()); + + builder = TestAllTypes.newBuilder(); + json = "{\n" + " \"optionalAliasedEnum\": \"bAz\"\n" + "}"; + JsonFormat.parser().merge(json, builder); + assertEquals(AliasedEnum.ALIAS_BAZ, builder.getOptionalAliasedEnum()); + } + + public void testUnknownEnumMap() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + JsonFormat.parser() + .ignoringUnknownFields() + .merge("{\n" + " \"int32ToEnumMap\": {1: XXX, 2: FOO}" + "}", builder); + + assertEquals(NestedEnum.FOO, builder.getInt32ToEnumMapMap().get(2)); + assertEquals(1, builder.getInt32ToEnumMapMap().size()); + } + + public void testRepeatedUnknownEnum() throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + JsonFormat.parser() + .ignoringUnknownFields() + .merge("{\n" + " \"repeatedNestedEnum\": [XXX, FOO, BAR, BAZ]" + "}", builder); + + assertEquals(NestedEnum.FOO, builder.getRepeatedNestedEnum(0)); + assertEquals(NestedEnum.BAR, builder.getRepeatedNestedEnum(1)); + assertEquals(NestedEnum.BAZ, builder.getRepeatedNestedEnum(2)); + assertEquals(3, builder.getRepeatedNestedEnumList().size()); + } + + public void testParserIntegerEnumValue() throws Exception { + TestAllTypes.Builder actualBuilder = TestAllTypes.newBuilder(); + mergeFromJson("{\n" + " \"optionalNestedEnum\": 2\n" + "}", actualBuilder); + + TestAllTypes expected = TestAllTypes.newBuilder().setOptionalNestedEnum(NestedEnum.BAZ).build(); + assertEquals(expected, actualBuilder.build()); + } + public void testCustomJsonName() throws Exception { TestCustomJsonName message = TestCustomJsonName.newBuilder().setValue(12345).build(); assertEquals("{\n" + " \"@value\": 12345\n" + "}", JsonFormat.printer().print(message)); assertRoundTripEquals(message); } - public void testDefaultGsonDoesNotHtmlEscape() throws Exception { - TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("=").build(); - assertEquals( - "{\n" + " \"optionalString\": \"=\"" + "\n}", JsonFormat.printer().print(message)); + // Regression test for b/73832901. Make sure html tags are escaped. + public void testHtmlEscape() throws Exception { + TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("").build(); + assertEquals("{\n \"optionalString\": \"\\u003c/script\\u003e\"\n}", toJsonString(message)); + + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + JsonFormat.parser().merge(toJsonString(message), builder); + assertEquals(message.getOptionalString(), builder.getOptionalString()); } public void testIncludingDefaultValueFields() throws Exception { @@ -1223,7 +1364,8 @@ public void testIncludingDefaultValueFields() throws Exception { + " \"repeatedString\": [],\n" + " \"repeatedBytes\": [],\n" + " \"repeatedNestedMessage\": [],\n" - + " \"repeatedNestedEnum\": []\n" + + " \"repeatedNestedEnum\": [],\n" + + " \"optionalAliasedEnum\": \"ALIAS_FOO\"\n" + "}", JsonFormat.printer().includingDefaultValueFields().print(message)); @@ -1441,6 +1583,13 @@ public void testPreservingProtoFieldNames() throws Exception { assertEquals(54321, builder.getOptionalInt32()); } + public void testPrintingEnumsAsInts() throws Exception { + TestAllTypes message = TestAllTypes.newBuilder().setOptionalNestedEnum(NestedEnum.BAR).build(); + assertEquals( + "{\n" + " \"optionalNestedEnum\": 1\n" + "}", + JsonFormat.printer().printingEnumsAsInts().print(message)); + } + public void testOmittingInsignificantWhiteSpace() throws Exception { TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(12345).build(); assertEquals( @@ -1548,6 +1697,7 @@ public void testRecursionLimit() throws Exception { public void testJsonException() throws Exception { InputStream throwingInputStream = new InputStream() { + @Override public int read() throws IOException { throw new IOException("12345"); } @@ -1574,4 +1724,78 @@ public int read() throws IOException { // Expected. } } + + // Test that an error is thrown if a nested JsonObject is parsed as a primitive field. + public void testJsonObjectForPrimitiveField() throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + try { + mergeFromJson( + "{\n" + + " \"optionalString\": {\n" + + " \"invalidNestedString\": \"Hello world\"\n" + + " }\n" + + "}\n", + builder); + } catch (InvalidProtocolBufferException e) { + // Expected. + } + } + + public void testSortedMapKeys() throws Exception { + TestMap.Builder mapBuilder = TestMap.newBuilder(); + mapBuilder.putStringToInt32Map("\ud834\udd20", 3); // utf-8 F0 9D 84 A0 + mapBuilder.putStringToInt32Map("foo", 99); + mapBuilder.putStringToInt32Map("xxx", 123); + mapBuilder.putStringToInt32Map("\u20ac", 1); // utf-8 E2 82 AC + mapBuilder.putStringToInt32Map("abc", 20); + mapBuilder.putStringToInt32Map("19", 19); + mapBuilder.putStringToInt32Map("8", 8); + mapBuilder.putStringToInt32Map("\ufb00", 2); // utf-8 EF AC 80 + mapBuilder.putInt32ToInt32Map(3, 3); + mapBuilder.putInt32ToInt32Map(10, 10); + mapBuilder.putInt32ToInt32Map(5, 5); + mapBuilder.putInt32ToInt32Map(4, 4); + mapBuilder.putInt32ToInt32Map(1, 1); + mapBuilder.putInt32ToInt32Map(2, 2); + mapBuilder.putInt32ToInt32Map(-3, -3); + TestMap mapMessage = mapBuilder.build(); + assertEquals( + "{\n" + + " \"int32ToInt32Map\": {\n" + + " \"-3\": -3,\n" + + " \"1\": 1,\n" + + " \"2\": 2,\n" + + " \"3\": 3,\n" + + " \"4\": 4,\n" + + " \"5\": 5,\n" + + " \"10\": 10\n" + + " },\n" + + " \"stringToInt32Map\": {\n" + + " \"19\": 19,\n" + + " \"8\": 8,\n" + + " \"abc\": 20,\n" + + " \"foo\": 99,\n" + + " \"xxx\": 123,\n" + + " \"\u20ac\": 1,\n" + + " \"\ufb00\": 2,\n" + + " \"\ud834\udd20\": 3\n" + + " }\n" + + "}", + toSortedJsonString(mapMessage)); + + TestMap emptyMap = TestMap.getDefaultInstance(); + assertEquals("{\n}", toSortedJsonString(emptyMap)); + } + + public void testPrintingEnumsAsIntsChainedAfterIncludingDefaultValueFields() throws Exception { + TestAllTypes message = TestAllTypes.newBuilder().setOptionalBool(false).build(); + + assertEquals( + "{\n" + " \"optionalBool\": false\n" + "}", + JsonFormat.printer() + .includingDefaultValueFields( + ImmutableSet.of(message.getDescriptorForType().findFieldByName("optional_bool"))) + .printingEnumsAsInts() + .print(message)); + } } diff --git a/java/util/src/test/java/com/google/protobuf/util/StructsTest.java b/java/util/src/test/java/com/google/protobuf/util/StructsTest.java new file mode 100644 index 0000000000000..265aff57761d4 --- /dev/null +++ b/java/util/src/test/java/com/google/protobuf/util/StructsTest.java @@ -0,0 +1,59 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf.util; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.protobuf.Struct; +import junit.framework.TestCase; + +public final class StructsTest extends TestCase { + + public void test1pair_constructsObject() throws Exception { + Struct.Builder expected = Struct.newBuilder(); + JsonFormat.parser().merge("{\"k1\": 1}", expected); + assertThat(Structs.of("k1", Values.of(1))).isEqualTo(expected.build()); + } + + public void test2pair_constructsObject() throws Exception { + Struct.Builder expected = Struct.newBuilder(); + JsonFormat.parser().merge("{\"k1\": 1, \"k2\": 2}", expected); + assertThat(Structs.of("k1", Values.of(1), "k2", Values.of(2))).isEqualTo(expected.build()); + } + + public void test3pair_constructsObject() throws Exception { + Struct.Builder expected = Struct.newBuilder(); + JsonFormat.parser().merge("{\"k1\": 1, \"k2\": 2, \"k3\": 3}", expected); + assertThat(Structs.of("k1", Values.of(1), "k2", Values.of(2), "k3", Values.of(3))) + .isEqualTo(expected.build()); + } + +} diff --git a/java/util/src/test/java/com/google/protobuf/util/ValuesTest.java b/java/util/src/test/java/com/google/protobuf/util/ValuesTest.java new file mode 100644 index 0000000000000..d646e9728264d --- /dev/null +++ b/java/util/src/test/java/com/google/protobuf/util/ValuesTest.java @@ -0,0 +1,102 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf.util; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.protobuf.ListValue; +import com.google.protobuf.NullValue; +import com.google.protobuf.Struct; +import com.google.protobuf.Value; +import java.util.ArrayList; +import java.util.List; +import junit.framework.TestCase; + +public final class ValuesTest extends TestCase { + public void testOfNull_IsNullValue() throws Exception { + assertThat(Values.ofNull()) + .isEqualTo(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()); + } + + public void testOfBoolean_ConstructsValue() { + assertThat(Values.of(true)).isEqualTo(Value.newBuilder().setBoolValue(true).build()); + assertThat(Values.of(false)).isEqualTo(Value.newBuilder().setBoolValue(false).build()); + } + + public void testOfNumeric_ConstructsValue() { + assertThat(Values.of(100)).isEqualTo(Value.newBuilder().setNumberValue(100).build()); + assertThat(Values.of(1000L)).isEqualTo(Value.newBuilder().setNumberValue(1000).build()); + assertThat(Values.of(1000.23f)).isEqualTo(Value.newBuilder().setNumberValue(1000.23f).build()); + assertThat(Values.of(10000.23)).isEqualTo(Value.newBuilder().setNumberValue(10000.23).build()); + } + + public void testOfString_ConstructsValue() { + assertThat(Values.of("")).isEqualTo(Value.newBuilder().setStringValue("").build()); + assertThat(Values.of("foo")).isEqualTo(Value.newBuilder().setStringValue("foo").build()); + } + + public void testOfStruct_ConstructsValue() { + Struct.Builder builder = Struct.newBuilder(); + builder.putFields("a", Values.of("a")); + builder.putFields("b", Values.of("b")); + + assertThat(Values.of(builder.build())) + .isEqualTo(Value.newBuilder().setStructValue(builder.build()).build()); + } + + public void testOfListValue_ConstructsInstance() { + ListValue.Builder builder = ListValue.newBuilder(); + builder.addValues(Values.of(1)); + builder.addValues(Values.of(2)); + + assertThat(Values.of(builder.build())) + .isEqualTo(Value.newBuilder().setListValue(builder.build()).build()); + } + + public void testOfIterable_ReturnsTheValue() { + ListValue.Builder builder = ListValue.newBuilder(); + builder.addValues(Values.of(1)); + builder.addValues(Values.of(2)); + builder.addValues(Values.of(true)); + builder.addValues(Value.newBuilder().setListValue(builder.build()).build()); + + List list = new ArrayList<>(); + list.add(Values.of(1)); + list.add(Values.of(2)); + list.add(Values.of(true)); + List copyList = new ArrayList<>(list); + list.add(Values.of(copyList)); + + assertThat(Values.of(list)).isEqualTo(Value.newBuilder().setListValue(builder).build()); + assertThat(Values.of(new ArrayList())) + .isEqualTo(Value.newBuilder().setListValue(ListValue.getDefaultInstance()).build()); + } +} diff --git a/java/util/src/test/proto/com/google/protobuf/util/json_test.proto b/java/util/src/test/proto/com/google/protobuf/util/json_test.proto index d1248cfb719a1..ba4fe0386092f 100644 --- a/java/util/src/test/proto/com/google/protobuf/util/json_test.proto +++ b/java/util/src/test/proto/com/google/protobuf/util/json_test.proto @@ -32,15 +32,15 @@ syntax = "proto3"; package json_test; -option java_package = "com.google.protobuf.util"; -option java_outer_classname = "JsonTestProto"; - import "google/protobuf/any.proto"; -import "google/protobuf/wrappers.proto"; -import "google/protobuf/timestamp.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/field_mask.proto"; import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; + +option java_package = "com.google.protobuf.util.proto"; +option java_outer_classname = "JsonTestProto"; message TestAllTypes { enum NestedEnum { @@ -48,6 +48,17 @@ message TestAllTypes { BAR = 1; BAZ = 2; } + + enum AliasedEnum { + option allow_alias = true; + + ALIAS_FOO = 0; + ALIAS_BAR = 1; + ALIAS_BAZ = 2; + QUX = 2; + qux = 2; + bAz = 2; + } message NestedMessage { int32 value = 1; } @@ -69,6 +80,7 @@ message TestAllTypes { bytes optional_bytes = 15; NestedMessage optional_nested_message = 18; NestedEnum optional_nested_enum = 21; + AliasedEnum optional_aliased_enum = 52; // Repeated repeated int32 repeated_int32 = 31; diff --git a/javanano/README.md b/javanano/README.md deleted file mode 100644 index 6b13ecea7cf8b..0000000000000 --- a/javanano/README.md +++ /dev/null @@ -1,401 +0,0 @@ -Protocol Buffers - Google's data interchange format -=================================================== - -[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) - -Copyright 2008 Google Inc. - -This directory contains the Java Protocol Buffers Nano runtime library. - -**Nano is no longer supported by protobuf team. We recommend Android users to -use protobuf lite runtime instead.** - -Installation - With Maven -------------------------- - -The Protocol Buffers build is managed using Maven. If you would -rather build without Maven, see below. - -1) Install Apache Maven if you don't have it: - - http://maven.apache.org/ - -2) Build the C++ code, or obtain a binary distribution of protoc. If - you install a binary distribution, make sure that it is the same - version as this package. If in doubt, run: - - $ protoc --version - - You will need to place the protoc executable in ../src. (If you - built it yourself, it should already be there.) - -3) Run the tests: - - $ mvn test - - If some tests fail, this library may not work correctly on your - system. Continue at your own risk. - -4) Install the library into your Maven repository: - - $ mvn install - -5) If you do not use Maven to manage your own build, you can build a - .jar file to use: - - $ mvn package - - The .jar will be placed in the "target" directory. - -Installation - Without Maven ----------------------------- - -If you would rather not install Maven to build the library, you may -follow these instructions instead. Note that these instructions skip -running unit tests. - -1) Build the C++ code, or obtain a binary distribution of protoc. If - you install a binary distribution, make sure that it is the same - version as this package. If in doubt, run: - - $ protoc --version - - If you built the C++ code without installing, the compiler binary - should be located in ../src. - -2) Invoke protoc to build DescriptorProtos.java: - - $ protoc --java_out=src/main/java -I../src \ - ../src/google/protobuf/descriptor.proto - -3) Compile the code in src/main/java using whatever means you prefer. - -4) Install the classes wherever you prefer. - -Nano version ------------- - -JavaNano is a special code generator and runtime library designed specially for -resource-restricted systems, like Android. It is very resource-friendly in both -the amount of code and the runtime overhead. Here is an overview of JavaNano -features compared with the official Java protobuf: - -- No descriptors or message builders. -- All messages are mutable; fields are public Java fields. -- For optional fields only, encapsulation behind setter/getter/hazzer/ - clearer functions is opt-in, which provide proper 'has' state support. -- For proto2, if not opted in, has state (field presence) is not available. - Serialization outputs all fields not equal to their defaults - (see important implications below). - The behavior is consistent with proto3 semantics. -- Required fields (proto2 only) are always serialized. -- Enum constants are integers; protection against invalid values only - when parsing from the wire. -- Enum constants can be generated into container interfaces bearing - the enum's name (so the referencing code is in Java style). -- CodedInputByteBufferNano can only take byte[] (not InputStream). -- Similarly CodedOutputByteBufferNano can only write to byte[]. -- Repeated fields are in arrays, not ArrayList or Vector. Null array - elements are allowed and silently ignored. -- Full support for serializing/deserializing repeated packed fields. -- Support extensions (in proto2). -- Unset messages/groups are null, not an immutable empty default - instance. -- toByteArray(...) and mergeFrom(...) are now static functions of - MessageNano. -- The 'bytes' type translates to the Java type byte[]. - -The generated messages are not thread-safe for writes, but may be -used simultaneously from multiple threads in a read-only manner. -In other words, an appropriate synchronization mechanism (such as -a ReadWriteLock) must be used to ensure that a message, its -ancestors, and descendants are not accessed by any other threads -while the message is being modified. Field reads, getter methods -(but not getExtension(...)), toByteArray(...), writeTo(...), -getCachedSize(), and getSerializedSize() are all considered read-only -operations. - -IMPORTANT: If you have fields with defaults and opt out of accessors - -How fields with defaults are serialized has changed. Because we don't -keep "has" state, any field equal to its default is assumed to be not -set and therefore is not serialized. Consider the situation where we -change the default value of a field. Senders compiled against an older -version of the proto continue to match against the old default, and -don't send values to the receiver even though the receiver assumes the -new default value. Therefore, think carefully about the implications -of changing the default value. Alternatively, turn on accessors and -enjoy the benefit of the explicit has() checks. - -IMPORTANT: If you have "bytes" fields with non-empty defaults - -Because the byte buffer is now of mutable type byte[], the default -static final cannot be exposed through a public field. Each time a -message's constructor or clear() function is called, the default value -(kept in a private byte[]) is cloned. This causes a small memory -penalty. This is not a problem if the field has no default or is an -empty default. - -Nano Generator options ----------------------- - -``` -java_package -> | -java_outer_classname -> | -java_multiple_files -> true or false -java_nano_generate_has -> true or false [DEPRECATED] -optional_field_style -> default or accessors -enum_style -> c or java -ignore_services -> true or false -parcelable_messages -> true or false -generate_intdefs -> true or false -``` - -**java_package=\|\** (no default) - - This allows overriding the 'java_package' option value - for the given file from the command line. Use multiple - java_package options to override the option for multiple - files. The final Java package for each file is the value - of this command line option if present, or the value of - the same option defined in the file if present, or the - proto package if present, or the default Java package. - -**java_outer_classname=\|\** (no default) - - This allows overriding the 'java_outer_classname' option - for the given file from the command line. Use multiple - java_outer_classname options to override the option for - multiple files. The final Java outer class name for each - file is the value of this command line option if present, - or the value of the same option defined in the file if - present, or the file name converted to CamelCase. This - outer class will nest all classes and integer constants - generated from file-scope messages and enums. - -**java_multiple_files={true,false}** (no default) - - This allows overriding the 'java_multiple_files' option - in all source files and their imported files from the - command line. The final value of this option for each - file is the value defined in this command line option, or - the value of the same option defined in the file if - present, or false. This specifies whether to generate - package-level classes for the file-scope messages in the - same Java package as the outer class (instead of nested - classes in the outer class). File-scope enum constants - are still generated as integer constants in the outer - class. This affects the fully qualified references in the - Java code. NOTE: because the command line option - overrides the value for all files and their imported - files, using this option inconsistently may result in - incorrect references to the imported messages and enum - constants. - -**java_nano_generate_has={true,false}** (default: false) - - DEPRECATED. Use optional_field_style=accessors. - - If true, generates a public boolean variable has\ - accompanying each optional or required field (not present for - repeated fields, groups or messages). It is set to false initially - and upon clear(). If parseFrom(...) reads the field from the wire, - it is set to true. This is a way for clients to inspect the "has" - value upon parse. If it is set to true, writeTo(...) will ALWAYS - output that field (even if field value is equal to its - default). - - IMPORTANT: This option costs an extra 4 bytes per primitive field in - the message. Think carefully about whether you really need this. In - many cases reading the default works and determining whether the - field was received over the wire is irrelevant. - -**optional_field_style={default,accessors,reftypes}** (default: default) - - Defines the style of the generated code for fields. - - * default - - In the default style, optional fields translate into public mutable - Java fields, and the serialization process is as discussed in the - "IMPORTANT" section above. - - * accessors - - When set to 'accessors', each optional field is encapsulated behind - 4 accessors, namely get\(), set\(), has\() - and clear\() methods, with the standard semantics. The hazzer's - return value determines whether a field is serialized, so this style is - useful when you need to serialize a field with the default value, or check - if a field has been explicitly set to its default value from the wire. - - In the 'accessors' style, required and nested message fields are still - translated to one public mutable Java field each, repeated fields are still - translated to arrays. No accessors are generated for them. - - IMPORTANT: When using the 'accessors' style, ProGuard should always - be enabled with optimization (don't use -dontoptimize) and allowing - access modification (use -allowaccessmodification). This removes the - unused accessors and maybe inline the rest at the call sites, - reducing the final code size. - TODO(maxtroy): find ProGuard config that would work the best. - - * reftypes - - When set to 'reftypes', each proto field is generated as a public Java - field. For primitive types, these fields use the Java reference types - such as java.lang.Integer instead of primitive types such as int. - - In the 'reftypes' style, fields are initialized to null (or empty - arrays for repeated fields), and their default values are not available. - They are serialized over the wire based on equality to null. - - The 'reftypes' mode has some additional cost due to autoboxing and usage - of reference types. In practice, many boxed types are cached, and so don't - result in object creation. However, references do take slightly more memory - than primitives. - - The 'reftypes' mode is useful when you want to be able to serialize fields - with default values, or check if a field has been explicitly set to the - default over the wire without paying the extra method cost of the - 'accessors' mode. - - Note that if you attempt to write null to a required field in the reftypes - mode, serialization of the proto will cause a NullPointerException. This is - an intentional indicator that you must set required fields. - - NOTE - optional_field_style=accessors or reftypes cannot be used together with - java_nano_generate_has=true. If you need the 'has' flag for any - required field (you have no reason to), you can only use - java_nano_generate_has=true. - -**enum_style={c,java}** (default: c) - - Defines where to put the int constants generated from enum members. - - * c - - Use C-style, so the enum constants are available at the scope where - the enum is defined. A file-scope enum's members are referenced like - 'FileOuterClass.ENUM_VALUE'; a message-scope enum's members are - referenced as 'Message.ENUM_VALUE'. The enum name is unavailable. - This complies with the Micro code generator's behavior. - - * java - - Use Java-style, so the enum constants are available under the enum - name and referenced like 'EnumName.ENUM_VALUE' (they are still int - constants). The enum name becomes the name of a public interface, at - the scope where the enum is defined. If the enum is file-scope and - the java_multiple_files option is on, the interface will be defined - in its own file. To reduce code size, this interface should not be - implemented and ProGuard shrinking should be used, so after the Java - compiler inlines all referenced enum constants into the call sites, - the interface remains unused and can be removed by ProGuard. - -**ignore_services={true,false}** (default: false) - - Skips services definitions. - - Nano doesn't support services. By default, if a service is defined - it will generate a compilation error. If this flag is set to true, - services will be silently ignored, instead. - -**parcelable_messages={true,false}** (default: false) - - Android-specific option to generate Parcelable messages. - -**generate_intdefs={true,false}** (default: false) - Android-specific option to generate @IntDef annotations for enums. - - If turned on, an '@IntDef' annotation (a public @interface) will be - generated for each enum, and every integer parameter and return - value in the generated code meant for this enum will be annotated - with it. This interface is generated with the same name and at the - same place as the enum members' container interfaces described - above under 'enum_style=java', regardless of the enum_style option - used. When this is combined with enum_style=java, the interface - will be both the '@IntDef' annotation and the container of the enum - members; otherwise the interface has an empty body. - - Your app must declare a compile-time dependency on the - android-support-annotations library. - - For more information on how these @IntDef annotations help with - compile-time type safety, see: - https://sites.google.com/a/android.com/tools/tech-docs/support-annotations - and - https://developer.android.com/reference/android/support/annotation/IntDef.html - - -To use nano protobufs within the Android repo: ----------------------------------------------- - -- Set 'LOCAL_PROTOC_OPTIMIZE_TYPE := nano' in your local .mk file. - When building a Java library or an app (package) target, the build - system will add the Java nano runtime library to the - LOCAL_STATIC_JAVA_LIBRARIES variable, so you don't need to. -- Set 'LOCAL_PROTO_JAVA_OUTPUT_PARAMS := ...' in your local .mk file - for any command-line options you need. Use commas to join multiple - options. In the nano flavor only, whitespace surrounding the option - names and values are ignored, so you can use backslash-newline or - '+=' to structure your make files nicely. -- The options will be applied to *all* proto files in LOCAL_SRC_FILES - when you build a Java library or package. In case different options - are needed for different proto files, build separate Java libraries - and reference them in your main target. Note: you should make sure - that, for each separate target, all proto files imported from any - proto file in LOCAL_SRC_FILES are included in LOCAL_SRC_FILES. This - is because the generator has to assume that the imported files are - built using the same options, and will generate code that reference - the fields and enums from the imported files using the same code - style. -- Hint: 'include $(CLEAR_VARS)' resets all LOCAL_ variables, including - the two above. - -To use nano protobufs outside of Android repo: ----------------------------------------------- - -- Link with the generated jar file - \java/target/protobuf-java-2.3.0-nano.jar. -- Invoke with --javanano_out, e.g.: -``` -./protoc '--javanano_out=\ - java_package=src/proto/simple-data.proto|my_package,\ - java_outer_classname=src/proto/simple-data.proto|OuterName\ - :.' src/proto/simple-data.proto -``` - -Contributing to nano: ---------------------- - -Please add/edit tests in NanoTest.java. - -Please run the following steps to test: - -- cd external/protobuf -- ./configure -- Run "make -j12 check" and verify all tests pass. -- cd java -- Run "mvn test" and verify all tests pass. -- cd ../../.. -- . build/envsetup.sh -- lunch 1 -- "make -j12 aprotoc libprotobuf-java-2.3.0-nano aprotoc-test-nano-params NanoAndroidTest" and - check for build errors. -- Plug in an Android device or start an emulator. -- adb install -r out/target/product/generic/data/app/NanoAndroidTest.apk -- Run: - "adb shell am instrument -w com.google.protobuf.nano.test/android.test.InstrumentationTestRunner" - and verify all tests pass. -- repo sync -c -j256 -- "make -j12" and check for build errors - -Usage ------ - -The complete documentation for Protocol Buffers is available via the -web at: - - https://developers.google.com/protocol-buffers/ diff --git a/javanano/pom.xml b/javanano/pom.xml deleted file mode 100644 index 0395e8f2dc9ab..0000000000000 --- a/javanano/pom.xml +++ /dev/null @@ -1,244 +0,0 @@ - - - 4.0.0 - - com.google - google - 1 - - com.google.protobuf.nano - protobuf-javanano - 3.2.0 - bundle - Protocol Buffer JavaNano API - - Protocol Buffers are a way of encoding structured data in an efficient yet - extensible format. - - 2008 - https://developers.google.com/protocol-buffers/ - - - 3-Clause BSD License - https://opensource.org/licenses/BSD-3-Clause - repo - - - - https://github.com/google/protobuf - - scm:git:https://github.com/google/protobuf.git - - - - UTF-8 - - - - junit - junit - 4.4 - test - - - org.easymock - easymock - 2.2 - test - - - org.easymock - easymockclassextension - 2.2.1 - test - - - - - - maven-compiler-plugin - - 1.5 - 1.5 - - - - maven-surefire-plugin - - - **/*Test.java - - - - - maven-antrun-plugin - - - generate-test-sources - generate-test-sources - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - target/generated-test-sources - - - run - - - - - - org.apache.felix - maven-bundle-plugin - true - - - https://developers.google.com/protocol-buffers/ - com.google.protobuf.nano - com.google.protobuf.nano;version=3.0.0-alpha-7 - - - - - - - - release - - - sonatype-nexus-staging - https://oss.sonatype.org/content/repositories/snapshots - - - sonatype-nexus-staging - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - sign-artifacts - verify - - sign - - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.3 - true - - sonatype-nexus-staging - https://oss.sonatype.org/ - false - - - - - - - diff --git a/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java b/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java deleted file mode 100644 index f39931551128b..0000000000000 --- a/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java +++ /dev/null @@ -1,683 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 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.nano; - -import java.io.IOException; - -/** - * Reads and decodes protocol message fields. - * - * This class contains two kinds of methods: methods that read specific - * protocol message constructs and field types (e.g. {@link #readTag()} and - * {@link #readInt32()}) and methods that read low-level values (e.g. - * {@link #readRawVarint32()} and {@link #readRawBytes}). If you are reading - * encoded protocol messages, you should use the former methods, but if you are - * reading some other format of your own design, use the latter. - * - * @author kenton@google.com Kenton Varda - */ -public final class CodedInputByteBufferNano { - /** - * Create a new CodedInputStream wrapping the given byte array. - */ - public static CodedInputByteBufferNano newInstance(final byte[] buf) { - return newInstance(buf, 0, buf.length); - } - - /** - * Create a new CodedInputStream wrapping the given byte array slice. - */ - public static CodedInputByteBufferNano newInstance(final byte[] buf, final int off, - final int len) { - return new CodedInputByteBufferNano(buf, off, len); - } - - // ----------------------------------------------------------------- - - /** - * Attempt to read a field tag, returning zero if we have reached EOF. - * Protocol message parsers use this to read tags, since a protocol message - * may legally end wherever a tag occurs, and zero is not a valid tag number. - */ - public int readTag() throws IOException { - if (isAtEnd()) { - lastTag = 0; - return 0; - } - - lastTag = readRawVarint32(); - if (lastTag == 0) { - // If we actually read zero, that's not a valid tag. - throw InvalidProtocolBufferNanoException.invalidTag(); - } - return lastTag; - } - - /** - * Verifies that the last call to readTag() returned the given tag value. - * This is used to verify that a nested group ended with the correct - * end tag. - * - * @throws InvalidProtocolBufferNanoException {@code value} does not match the - * last tag. - */ - public void checkLastTagWas(final int value) - throws InvalidProtocolBufferNanoException { - if (lastTag != value) { - throw InvalidProtocolBufferNanoException.invalidEndTag(); - } - } - - /** - * Reads and discards a single field, given its tag value. - * - * @return {@code false} if the tag is an endgroup tag, in which case - * nothing is skipped. Otherwise, returns {@code true}. - */ - public boolean skipField(final int tag) throws IOException { - switch (WireFormatNano.getTagWireType(tag)) { - case WireFormatNano.WIRETYPE_VARINT: - readInt32(); - return true; - case WireFormatNano.WIRETYPE_FIXED64: - readRawLittleEndian64(); - return true; - case WireFormatNano.WIRETYPE_LENGTH_DELIMITED: - skipRawBytes(readRawVarint32()); - return true; - case WireFormatNano.WIRETYPE_START_GROUP: - skipMessage(); - checkLastTagWas( - WireFormatNano.makeTag(WireFormatNano.getTagFieldNumber(tag), - WireFormatNano.WIRETYPE_END_GROUP)); - return true; - case WireFormatNano.WIRETYPE_END_GROUP: - return false; - case WireFormatNano.WIRETYPE_FIXED32: - readRawLittleEndian32(); - return true; - default: - throw InvalidProtocolBufferNanoException.invalidWireType(); - } - } - - /** - * Reads and discards an entire message. This will read either until EOF - * or until an endgroup tag, whichever comes first. - */ - public void skipMessage() throws IOException { - while (true) { - final int tag = readTag(); - if (tag == 0 || !skipField(tag)) { - return; - } - } - } - - // ----------------------------------------------------------------- - - /** Read a {@code double} field value from the stream. */ - public double readDouble() throws IOException { - return Double.longBitsToDouble(readRawLittleEndian64()); - } - - /** Read a {@code float} field value from the stream. */ - public float readFloat() throws IOException { - return Float.intBitsToFloat(readRawLittleEndian32()); - } - - /** Read a {@code uint64} field value from the stream. */ - public long readUInt64() throws IOException { - return readRawVarint64(); - } - - /** Read an {@code int64} field value from the stream. */ - public long readInt64() throws IOException { - return readRawVarint64(); - } - - /** Read an {@code int32} field value from the stream. */ - public int readInt32() throws IOException { - return readRawVarint32(); - } - - /** Read a {@code fixed64} field value from the stream. */ - public long readFixed64() throws IOException { - return readRawLittleEndian64(); - } - - /** Read a {@code fixed32} field value from the stream. */ - public int readFixed32() throws IOException { - return readRawLittleEndian32(); - } - - /** Read a {@code bool} field value from the stream. */ - public boolean readBool() throws IOException { - return readRawVarint32() != 0; - } - - /** Read a {@code string} field value from the stream. */ - public String readString() throws IOException { - final int size = readRawVarint32(); - if (size <= (bufferSize - bufferPos) && size > 0) { - // Fast path: We already have the bytes in a contiguous buffer, so - // just copy directly from it. - final String result = new String(buffer, bufferPos, size, InternalNano.UTF_8); - bufferPos += size; - return result; - } else { - // Slow path: Build a byte array first then copy it. - return new String(readRawBytes(size), InternalNano.UTF_8); - } - } - - /** Read a {@code group} field value from the stream. */ - public void readGroup(final MessageNano msg, final int fieldNumber) - throws IOException { - if (recursionDepth >= recursionLimit) { - throw InvalidProtocolBufferNanoException.recursionLimitExceeded(); - } - ++recursionDepth; - msg.mergeFrom(this); - checkLastTagWas( - WireFormatNano.makeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP)); - --recursionDepth; - } - - public void readMessage(final MessageNano msg) - throws IOException { - final int length = readRawVarint32(); - if (recursionDepth >= recursionLimit) { - throw InvalidProtocolBufferNanoException.recursionLimitExceeded(); - } - final int oldLimit = pushLimit(length); - ++recursionDepth; - msg.mergeFrom(this); - checkLastTagWas(0); - --recursionDepth; - popLimit(oldLimit); - } - - /** Read a {@code bytes} field value from the stream. */ - public byte[] readBytes() throws IOException { - final int size = readRawVarint32(); - if (size <= (bufferSize - bufferPos) && size > 0) { - // Fast path: We already have the bytes in a contiguous buffer, so - // just copy directly from it. - final byte[] result = new byte[size]; - System.arraycopy(buffer, bufferPos, result, 0, size); - bufferPos += size; - return result; - } else if (size == 0) { - return WireFormatNano.EMPTY_BYTES; - } else { - // Slow path: Build a byte array first then copy it. - return readRawBytes(size); - } - } - - /** Read a {@code uint32} field value from the stream. */ - public int readUInt32() throws IOException { - return readRawVarint32(); - } - - /** - * Read an enum field value from the stream. Caller is responsible - * for converting the numeric value to an actual enum. - */ - public int readEnum() throws IOException { - return readRawVarint32(); - } - - /** Read an {@code sfixed32} field value from the stream. */ - public int readSFixed32() throws IOException { - return readRawLittleEndian32(); - } - - /** Read an {@code sfixed64} field value from the stream. */ - public long readSFixed64() throws IOException { - return readRawLittleEndian64(); - } - - /** Read an {@code sint32} field value from the stream. */ - public int readSInt32() throws IOException { - return decodeZigZag32(readRawVarint32()); - } - - /** Read an {@code sint64} field value from the stream. */ - public long readSInt64() throws IOException { - return decodeZigZag64(readRawVarint64()); - } - - // ================================================================= - - /** - * Read a raw Varint from the stream. If larger than 32 bits, discard the - * upper bits. - */ - public int readRawVarint32() throws IOException { - byte tmp = readRawByte(); - if (tmp >= 0) { - return tmp; - } - int result = tmp & 0x7f; - if ((tmp = readRawByte()) >= 0) { - result |= tmp << 7; - } else { - result |= (tmp & 0x7f) << 7; - if ((tmp = readRawByte()) >= 0) { - result |= tmp << 14; - } else { - result |= (tmp & 0x7f) << 14; - if ((tmp = readRawByte()) >= 0) { - result |= tmp << 21; - } else { - result |= (tmp & 0x7f) << 21; - result |= (tmp = readRawByte()) << 28; - if (tmp < 0) { - // Discard upper 32 bits. - for (int i = 0; i < 5; i++) { - if (readRawByte() >= 0) { - return result; - } - } - throw InvalidProtocolBufferNanoException.malformedVarint(); - } - } - } - } - return result; - } - - /** Read a raw Varint from the stream. */ - public long readRawVarint64() throws IOException { - int shift = 0; - long result = 0; - while (shift < 64) { - final byte b = readRawByte(); - result |= (long)(b & 0x7F) << shift; - if ((b & 0x80) == 0) { - return result; - } - shift += 7; - } - throw InvalidProtocolBufferNanoException.malformedVarint(); - } - - /** Read a 32-bit little-endian integer from the stream. */ - public int readRawLittleEndian32() throws IOException { - final byte b1 = readRawByte(); - final byte b2 = readRawByte(); - final byte b3 = readRawByte(); - final byte b4 = readRawByte(); - return ((b1 & 0xff) ) | - ((b2 & 0xff) << 8) | - ((b3 & 0xff) << 16) | - ((b4 & 0xff) << 24); - } - - /** Read a 64-bit little-endian integer from the stream. */ - public long readRawLittleEndian64() throws IOException { - final byte b1 = readRawByte(); - final byte b2 = readRawByte(); - final byte b3 = readRawByte(); - final byte b4 = readRawByte(); - final byte b5 = readRawByte(); - final byte b6 = readRawByte(); - final byte b7 = readRawByte(); - final byte b8 = readRawByte(); - return (((long)b1 & 0xff) ) | - (((long)b2 & 0xff) << 8) | - (((long)b3 & 0xff) << 16) | - (((long)b4 & 0xff) << 24) | - (((long)b5 & 0xff) << 32) | - (((long)b6 & 0xff) << 40) | - (((long)b7 & 0xff) << 48) | - (((long)b8 & 0xff) << 56); - } - - /** - * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers - * into values that can be efficiently encoded with varint. (Otherwise, - * negative values must be sign-extended to 64 bits to be varint encoded, - * thus always taking 10 bytes on the wire.) - * - * @param n An unsigned 32-bit integer, stored in a signed int because - * Java has no explicit unsigned support. - * @return A signed 32-bit integer. - */ - public static int decodeZigZag32(final int n) { - return (n >>> 1) ^ -(n & 1); - } - - /** - * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers - * into values that can be efficiently encoded with varint. (Otherwise, - * negative values must be sign-extended to 64 bits to be varint encoded, - * thus always taking 10 bytes on the wire.) - * - * @param n An unsigned 64-bit integer, stored in a signed int because - * Java has no explicit unsigned support. - * @return A signed 64-bit integer. - */ - public static long decodeZigZag64(final long n) { - return (n >>> 1) ^ -(n & 1); - } - - // ----------------------------------------------------------------- - - private final byte[] buffer; - private int bufferStart; - private int bufferSize; - private int bufferSizeAfterLimit; - private int bufferPos; - private int lastTag; - - /** The absolute position of the end of the current message. */ - private int currentLimit = Integer.MAX_VALUE; - - /** See setRecursionLimit() */ - private int recursionDepth; - private int recursionLimit = DEFAULT_RECURSION_LIMIT; - - /** See setSizeLimit() */ - private int sizeLimit = DEFAULT_SIZE_LIMIT; - - private static final int DEFAULT_RECURSION_LIMIT = 64; - private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB - - private CodedInputByteBufferNano(final byte[] buffer, final int off, final int len) { - this.buffer = buffer; - bufferStart = off; - bufferSize = off + len; - bufferPos = off; - } - - /** - * Set the maximum message recursion depth. In order to prevent malicious - * messages from causing stack overflows, {@code CodedInputStream} limits - * how deeply messages may be nested. The default limit is 64. - * - * @return the old limit. - */ - public int setRecursionLimit(final int limit) { - if (limit < 0) { - throw new IllegalArgumentException( - "Recursion limit cannot be negative: " + limit); - } - final int oldLimit = recursionLimit; - recursionLimit = limit; - return oldLimit; - } - - /** - * Set the maximum message size. In order to prevent malicious - * messages from exhausting memory or causing integer overflows, - * {@code CodedInputStream} limits how large a message may be. - * The default limit is 64MB. You should set this limit as small - * as you can without harming your app's functionality. Note that - * size limits only apply when reading from an {@code InputStream}, not - * when constructed around a raw byte array. - *

- * If you want to read several messages from a single CodedInputStream, you - * could call {@link #resetSizeCounter()} after each one to avoid hitting the - * size limit. - * - * @return the old limit. - */ - public int setSizeLimit(final int limit) { - if (limit < 0) { - throw new IllegalArgumentException( - "Size limit cannot be negative: " + limit); - } - final int oldLimit = sizeLimit; - sizeLimit = limit; - return oldLimit; - } - - /** - * Resets the current size counter to zero (see {@link #setSizeLimit(int)}). - */ - public void resetSizeCounter() { - } - - /** - * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This - * is called when descending into a length-delimited embedded message. - * - * @return the old limit. - */ - public int pushLimit(int byteLimit) throws InvalidProtocolBufferNanoException { - if (byteLimit < 0) { - throw InvalidProtocolBufferNanoException.negativeSize(); - } - byteLimit += bufferPos; - final int oldLimit = currentLimit; - if (byteLimit > oldLimit) { - throw InvalidProtocolBufferNanoException.truncatedMessage(); - } - currentLimit = byteLimit; - - recomputeBufferSizeAfterLimit(); - - return oldLimit; - } - - private void recomputeBufferSizeAfterLimit() { - bufferSize += bufferSizeAfterLimit; - final int bufferEnd = bufferSize; - if (bufferEnd > currentLimit) { - // Limit is in current buffer. - bufferSizeAfterLimit = bufferEnd - currentLimit; - bufferSize -= bufferSizeAfterLimit; - } else { - bufferSizeAfterLimit = 0; - } - } - - /** - * Discards the current limit, returning to the previous limit. - * - * @param oldLimit The old limit, as returned by {@code pushLimit}. - */ - public void popLimit(final int oldLimit) { - currentLimit = oldLimit; - recomputeBufferSizeAfterLimit(); - } - - /** - * Returns the number of bytes to be read before the current limit. - * If no limit is set, returns -1. - */ - public int getBytesUntilLimit() { - if (currentLimit == Integer.MAX_VALUE) { - return -1; - } - - final int currentAbsolutePosition = bufferPos; - return currentLimit - currentAbsolutePosition; - } - - /** - * Returns true if the stream has reached the end of the input. This is the - * case if either the end of the underlying input source has been reached or - * if the stream has reached a limit created using {@link #pushLimit(int)}. - */ - public boolean isAtEnd() { - return bufferPos == bufferSize; - } - - /** - * Get current position in buffer relative to beginning offset. - */ - public int getPosition() { - return bufferPos - bufferStart; - } - - /** - * Retrieves a subset of data in the buffer. The returned array is not backed by the original - * buffer array. - * - * @param offset the position (relative to the buffer start position) to start at. - * @param length the number of bytes to retrieve. - */ - public byte[] getData(int offset, int length) { - if (length == 0) { - return WireFormatNano.EMPTY_BYTES; - } - byte[] copy = new byte[length]; - int start = bufferStart + offset; - System.arraycopy(buffer, start, copy, 0, length); - return copy; - } - - /** - * Rewind to previous position. Cannot go forward. - */ - public void rewindToPosition(int position) { - if (position > bufferPos - bufferStart) { - throw new IllegalArgumentException( - "Position " + position + " is beyond current " + (bufferPos - bufferStart)); - } - if (position < 0) { - throw new IllegalArgumentException("Bad position " + position); - } - bufferPos = bufferStart + position; - } - - /** - * Read one byte from the input. - * - * @throws InvalidProtocolBufferNanoException The end of the stream or the current - * limit was reached. - */ - public byte readRawByte() throws IOException { - if (bufferPos == bufferSize) { - throw InvalidProtocolBufferNanoException.truncatedMessage(); - } - return buffer[bufferPos++]; - } - - /** - * Read a fixed size of bytes from the input. - * - * @throws InvalidProtocolBufferNanoException The end of the stream or the current - * limit was reached. - */ - public byte[] readRawBytes(final int size) throws IOException { - if (size < 0) { - throw InvalidProtocolBufferNanoException.negativeSize(); - } - - if (bufferPos + size > currentLimit) { - // Read to the end of the stream anyway. - skipRawBytes(currentLimit - bufferPos); - // Then fail. - throw InvalidProtocolBufferNanoException.truncatedMessage(); - } - - if (size <= bufferSize - bufferPos) { - // We have all the bytes we need already. - final byte[] bytes = new byte[size]; - System.arraycopy(buffer, bufferPos, bytes, 0, size); - bufferPos += size; - return bytes; - } else { - throw InvalidProtocolBufferNanoException.truncatedMessage(); - } - } - - /** - * Reads and discards {@code size} bytes. - * - * @throws InvalidProtocolBufferNanoException The end of the stream or the current - * limit was reached. - */ - public void skipRawBytes(final int size) throws IOException { - if (size < 0) { - throw InvalidProtocolBufferNanoException.negativeSize(); - } - - if (bufferPos + size > currentLimit) { - // Read to the end of the stream anyway. - skipRawBytes(currentLimit - bufferPos); - // Then fail. - throw InvalidProtocolBufferNanoException.truncatedMessage(); - } - - if (size <= bufferSize - bufferPos) { - // We have all the bytes we need already. - bufferPos += size; - } else { - throw InvalidProtocolBufferNanoException.truncatedMessage(); - } - } - - // Read a primitive type. - Object readPrimitiveField(int type) throws IOException { - switch (type) { - case InternalNano.TYPE_DOUBLE: - return readDouble(); - case InternalNano.TYPE_FLOAT: - return readFloat(); - case InternalNano.TYPE_INT64: - return readInt64(); - case InternalNano.TYPE_UINT64: - return readUInt64(); - case InternalNano.TYPE_INT32: - return readInt32(); - case InternalNano.TYPE_FIXED64: - return readFixed64(); - case InternalNano.TYPE_FIXED32: - return readFixed32(); - case InternalNano.TYPE_BOOL: - return readBool(); - case InternalNano.TYPE_STRING: - return readString(); - case InternalNano.TYPE_BYTES: - return readBytes(); - case InternalNano.TYPE_UINT32: - return readUInt32(); - case InternalNano.TYPE_ENUM: - return readEnum(); - case InternalNano.TYPE_SFIXED32: - return readSFixed32(); - case InternalNano.TYPE_SFIXED64: - return readSFixed64(); - case InternalNano.TYPE_SINT32: - return readSInt32(); - case InternalNano.TYPE_SINT64: - return readSInt64(); - default: - throw new IllegalArgumentException("Unknown type " + type); - } - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java b/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java deleted file mode 100644 index 322ada8e1f823..0000000000000 --- a/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java +++ /dev/null @@ -1,1214 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 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.nano; - -import java.io.IOException; -import java.nio.BufferOverflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ReadOnlyBufferException; - -/** - * Encodes and writes protocol message fields. - * - *

This class contains two kinds of methods: methods that write specific - * protocol message constructs and field types (e.g. {@link #writeTag} and - * {@link #writeInt32}) and methods that write low-level values (e.g. - * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are - * writing encoded protocol messages, you should use the former methods, but if - * you are writing some other format of your own design, use the latter. - * - *

This class is totally unsynchronized. - * - * @author kneton@google.com Kenton Varda - */ -public final class CodedOutputByteBufferNano { - /* max bytes per java UTF-16 char in UTF-8 */ - private static final int MAX_UTF8_EXPANSION = 3; - private final ByteBuffer buffer; - - private CodedOutputByteBufferNano(final byte[] buffer, final int offset, - final int length) { - this(ByteBuffer.wrap(buffer, offset, length)); - } - - private CodedOutputByteBufferNano(final ByteBuffer buffer) { - this.buffer = buffer; - this.buffer.order(ByteOrder.LITTLE_ENDIAN); - } - - /** - * Create a new {@code CodedOutputStream} that writes directly to the given - * byte array. If more bytes are written than fit in the array, - * {@link OutOfSpaceException} will be thrown. Writing directly to a flat - * array is faster than writing to an {@code OutputStream}. - */ - public static CodedOutputByteBufferNano newInstance(final byte[] flatArray) { - return newInstance(flatArray, 0, flatArray.length); - } - - /** - * Create a new {@code CodedOutputStream} that writes directly to the given - * byte array slice. If more bytes are written than fit in the slice, - * {@link OutOfSpaceException} will be thrown. Writing directly to a flat - * array is faster than writing to an {@code OutputStream}. - */ - public static CodedOutputByteBufferNano newInstance(final byte[] flatArray, - final int offset, - final int length) { - return new CodedOutputByteBufferNano(flatArray, offset, length); - } - - // ----------------------------------------------------------------- - - /** Write a {@code double} field, including tag, to the stream. */ - public void writeDouble(final int fieldNumber, final double value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); - writeDoubleNoTag(value); - } - - /** Write a {@code float} field, including tag, to the stream. */ - public void writeFloat(final int fieldNumber, final float value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); - writeFloatNoTag(value); - } - - /** Write a {@code uint64} field, including tag, to the stream. */ - public void writeUInt64(final int fieldNumber, final long value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeUInt64NoTag(value); - } - - /** Write an {@code int64} field, including tag, to the stream. */ - public void writeInt64(final int fieldNumber, final long value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeInt64NoTag(value); - } - - /** Write an {@code int32} field, including tag, to the stream. */ - public void writeInt32(final int fieldNumber, final int value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeInt32NoTag(value); - } - - /** Write a {@code fixed64} field, including tag, to the stream. */ - public void writeFixed64(final int fieldNumber, final long value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); - writeFixed64NoTag(value); - } - - /** Write a {@code fixed32} field, including tag, to the stream. */ - public void writeFixed32(final int fieldNumber, final int value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); - writeFixed32NoTag(value); - } - - /** Write a {@code bool} field, including tag, to the stream. */ - public void writeBool(final int fieldNumber, final boolean value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeBoolNoTag(value); - } - - /** Write a {@code string} field, including tag, to the stream. */ - public void writeString(final int fieldNumber, final String value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); - writeStringNoTag(value); - } - - /** Write a {@code group} field, including tag, to the stream. */ - public void writeGroup(final int fieldNumber, final MessageNano value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_START_GROUP); - writeGroupNoTag(value); - writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP); - } - - /** Write an embedded message field, including tag, to the stream. */ - public void writeMessage(final int fieldNumber, final MessageNano value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); - writeMessageNoTag(value); - } - - /** Write a {@code bytes} field, including tag, to the stream. */ - public void writeBytes(final int fieldNumber, final byte[] value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); - writeBytesNoTag(value); - } - - /** Write a {@code uint32} field, including tag, to the stream. */ - public void writeUInt32(final int fieldNumber, final int value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeUInt32NoTag(value); - } - - /** - * Write an enum field, including tag, to the stream. Caller is responsible - * for converting the enum value to its numeric value. - */ - public void writeEnum(final int fieldNumber, final int value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeEnumNoTag(value); - } - - /** Write an {@code sfixed32} field, including tag, to the stream. */ - public void writeSFixed32(final int fieldNumber, final int value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); - writeSFixed32NoTag(value); - } - - /** Write an {@code sfixed64} field, including tag, to the stream. */ - public void writeSFixed64(final int fieldNumber, final long value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); - writeSFixed64NoTag(value); - } - - /** Write an {@code sint32} field, including tag, to the stream. */ - public void writeSInt32(final int fieldNumber, final int value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeSInt32NoTag(value); - } - - /** Write an {@code sint64} field, including tag, to the stream. */ - public void writeSInt64(final int fieldNumber, final long value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeSInt64NoTag(value); - } - - /** - * Write a MessageSet extension field to the stream. For historical reasons, - * the wire format differs from normal fields. - */ -// public void writeMessageSetExtension(final int fieldNumber, -// final MessageMicro value) -// throws IOException { -// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP); -// writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber); -// writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value); -// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP); -// } - - /** - * Write an unparsed MessageSet extension field to the stream. For - * historical reasons, the wire format differs from normal fields. - */ -// public void writeRawMessageSetExtension(final int fieldNumber, -// final ByteStringMicro value) -// throws IOException { -// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP); -// writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber); -// writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value); -// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP); -// } - - // ----------------------------------------------------------------- - - /** Write a {@code double} field to the stream. */ - public void writeDoubleNoTag(final double value) throws IOException { - writeRawLittleEndian64(Double.doubleToLongBits(value)); - } - - /** Write a {@code float} field to the stream. */ - public void writeFloatNoTag(final float value) throws IOException { - writeRawLittleEndian32(Float.floatToIntBits(value)); - } - - /** Write a {@code uint64} field to the stream. */ - public void writeUInt64NoTag(final long value) throws IOException { - writeRawVarint64(value); - } - - /** Write an {@code int64} field to the stream. */ - public void writeInt64NoTag(final long value) throws IOException { - writeRawVarint64(value); - } - - /** Write an {@code int32} field to the stream. */ - public void writeInt32NoTag(final int value) throws IOException { - if (value >= 0) { - writeRawVarint32(value); - } else { - // Must sign-extend. - writeRawVarint64(value); - } - } - - /** Write a {@code fixed64} field to the stream. */ - public void writeFixed64NoTag(final long value) throws IOException { - writeRawLittleEndian64(value); - } - - /** Write a {@code fixed32} field to the stream. */ - public void writeFixed32NoTag(final int value) throws IOException { - writeRawLittleEndian32(value); - } - - /** Write a {@code bool} field to the stream. */ - public void writeBoolNoTag(final boolean value) throws IOException { - writeRawByte(value ? 1 : 0); - } - - /** Write a {@code string} field to the stream. */ - public void writeStringNoTag(final String value) throws IOException { - // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()), - // and at most 3 times of it. Optimize for the case where we know this length results in a - // constant varint length - saves measuring length of the string. - try { - final int minLengthVarIntSize = computeRawVarint32Size(value.length()); - final int maxLengthVarIntSize = computeRawVarint32Size(value.length() * MAX_UTF8_EXPANSION); - if (minLengthVarIntSize == maxLengthVarIntSize) { - int oldPosition = buffer.position(); - // Buffer.position, when passed a position that is past its limit, throws - // IllegalArgumentException, and this class is documented to throw - // OutOfSpaceException instead. - if (buffer.remaining() < minLengthVarIntSize) { - throw new OutOfSpaceException(oldPosition + minLengthVarIntSize, buffer.limit()); - } - buffer.position(oldPosition + minLengthVarIntSize); - encode(value, buffer); - int newPosition = buffer.position(); - buffer.position(oldPosition); - writeRawVarint32(newPosition - oldPosition - minLengthVarIntSize); - buffer.position(newPosition); - } else { - writeRawVarint32(encodedLength(value)); - encode(value, buffer); - } - } catch (BufferOverflowException e) { - final OutOfSpaceException outOfSpaceException = new OutOfSpaceException(buffer.position(), - buffer.limit()); - outOfSpaceException.initCause(e); - throw outOfSpaceException; - } - } - - // These UTF-8 handling methods are copied from Guava's Utf8 class. - /** - * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string, - * this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in - * both time and space. - * - * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired - * surrogates) - */ - private static int encodedLength(CharSequence sequence) { - // Warning to maintainers: this implementation is highly optimized. - int utf16Length = sequence.length(); - int utf8Length = utf16Length; - int i = 0; - - // This loop optimizes for pure ASCII. - while (i < utf16Length && sequence.charAt(i) < 0x80) { - i++; - } - - // This loop optimizes for chars less than 0x800. - for (; i < utf16Length; i++) { - char c = sequence.charAt(i); - if (c < 0x800) { - utf8Length += ((0x7f - c) >>> 31); // branch free! - } else { - utf8Length += encodedLengthGeneral(sequence, i); - break; - } - } - - if (utf8Length < utf16Length) { - // Necessary and sufficient condition for overflow because of maximum 3x expansion - throw new IllegalArgumentException("UTF-8 length does not fit in int: " - + (utf8Length + (1L << 32))); - } - return utf8Length; - } - - private static int encodedLengthGeneral(CharSequence sequence, int start) { - int utf16Length = sequence.length(); - int utf8Length = 0; - for (int i = start; i < utf16Length; i++) { - char c = sequence.charAt(i); - if (c < 0x800) { - utf8Length += (0x7f - c) >>> 31; // branch free! - } else { - utf8Length += 2; - // jdk7+: if (Character.isSurrogate(c)) { - if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) { - // Check that we have a well-formed surrogate pair. - int cp = Character.codePointAt(sequence, i); - if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) { - throw new IllegalArgumentException("Unpaired surrogate at index " + i); - } - i++; - } - } - } - return utf8Length; - } - - /** - * Encodes {@code sequence} into UTF-8, in {@code byteBuffer}. For a string, this method is - * equivalent to {@code buffer.put(string.getBytes(UTF_8))}, but is more efficient in both time - * and space. Bytes are written starting at the current position. This method requires paired - * surrogates, and therefore does not support chunking. - * - *

To ensure sufficient space in the output buffer, either call {@link #encodedLength} to - * compute the exact amount needed, or leave room for {@code 3 * sequence.length()}, which is the - * largest possible number of bytes that any input can be encoded to. - * - * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired - * surrogates) - * @throws BufferOverflowException if {@code sequence} encoded in UTF-8 does not fit in - * {@code byteBuffer}'s remaining space. - * @throws ReadOnlyBufferException if {@code byteBuffer} is a read-only buffer. - */ - private static void encode(CharSequence sequence, ByteBuffer byteBuffer) { - if (byteBuffer.isReadOnly()) { - throw new ReadOnlyBufferException(); - } else if (byteBuffer.hasArray()) { - try { - int encoded = encode(sequence, - byteBuffer.array(), - byteBuffer.arrayOffset() + byteBuffer.position(), - byteBuffer.remaining()); - byteBuffer.position(encoded - byteBuffer.arrayOffset()); - } catch (ArrayIndexOutOfBoundsException e) { - BufferOverflowException boe = new BufferOverflowException(); - boe.initCause(e); - throw boe; - } - } else { - encodeDirect(sequence, byteBuffer); - } - } - - private static void encodeDirect(CharSequence sequence, ByteBuffer byteBuffer) { - int utf16Length = sequence.length(); - for (int i = 0; i < utf16Length; i++) { - final char c = sequence.charAt(i); - if (c < 0x80) { // ASCII - byteBuffer.put((byte) c); - } else if (c < 0x800) { // 11 bits, two UTF-8 bytes - byteBuffer.put((byte) ((0xF << 6) | (c >>> 6))); - byteBuffer.put((byte) (0x80 | (0x3F & c))); - } else if (c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) { - // Maximium single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes - byteBuffer.put((byte) ((0xF << 5) | (c >>> 12))); - byteBuffer.put((byte) (0x80 | (0x3F & (c >>> 6)))); - byteBuffer.put((byte) (0x80 | (0x3F & c))); - } else { - final char low; - if (i + 1 == sequence.length() - || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) { - throw new IllegalArgumentException("Unpaired surrogate at index " + (i - 1)); - } - int codePoint = Character.toCodePoint(c, low); - byteBuffer.put((byte) ((0xF << 4) | (codePoint >>> 18))); - byteBuffer.put((byte) (0x80 | (0x3F & (codePoint >>> 12)))); - byteBuffer.put((byte) (0x80 | (0x3F & (codePoint >>> 6)))); - byteBuffer.put((byte) (0x80 | (0x3F & codePoint))); - } - } - } - - private static int encode(CharSequence sequence, byte[] bytes, int offset, int length) { - int utf16Length = sequence.length(); - int j = offset; - int i = 0; - int limit = offset + length; - // Designed to take advantage of - // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination - for (char c; i < utf16Length && i + j < limit && (c = sequence.charAt(i)) < 0x80; i++) { - bytes[j + i] = (byte) c; - } - if (i == utf16Length) { - return j + utf16Length; - } - j += i; - for (char c; i < utf16Length; i++) { - c = sequence.charAt(i); - if (c < 0x80 && j < limit) { - bytes[j++] = (byte) c; - } else if (c < 0x800 && j <= limit - 2) { // 11 bits, two UTF-8 bytes - bytes[j++] = (byte) ((0xF << 6) | (c >>> 6)); - bytes[j++] = (byte) (0x80 | (0x3F & c)); - } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && j <= limit - 3) { - // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes - bytes[j++] = (byte) ((0xF << 5) | (c >>> 12)); - bytes[j++] = (byte) (0x80 | (0x3F & (c >>> 6))); - bytes[j++] = (byte) (0x80 | (0x3F & c)); - } else if (j <= limit - 4) { - // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8 bytes - final char low; - if (i + 1 == sequence.length() - || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) { - throw new IllegalArgumentException("Unpaired surrogate at index " + (i - 1)); - } - int codePoint = Character.toCodePoint(c, low); - bytes[j++] = (byte) ((0xF << 4) | (codePoint >>> 18)); - bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 12))); - bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 6))); - bytes[j++] = (byte) (0x80 | (0x3F & codePoint)); - } else { - throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j); - } - } - return j; - } - - // End guava UTF-8 methods - - - /** Write a {@code group} field to the stream. */ - public void writeGroupNoTag(final MessageNano value) throws IOException { - value.writeTo(this); - } - - /** Write an embedded message field to the stream. */ - public void writeMessageNoTag(final MessageNano value) throws IOException { - writeRawVarint32(value.getCachedSize()); - value.writeTo(this); - } - - /** Write a {@code bytes} field to the stream. */ - public void writeBytesNoTag(final byte[] value) throws IOException { - writeRawVarint32(value.length); - writeRawBytes(value); - } - - /** Write a {@code uint32} field to the stream. */ - public void writeUInt32NoTag(final int value) throws IOException { - writeRawVarint32(value); - } - - /** - * Write an enum field to the stream. Caller is responsible - * for converting the enum value to its numeric value. - */ - public void writeEnumNoTag(final int value) throws IOException { - writeRawVarint32(value); - } - - /** Write an {@code sfixed32} field to the stream. */ - public void writeSFixed32NoTag(final int value) throws IOException { - writeRawLittleEndian32(value); - } - - /** Write an {@code sfixed64} field to the stream. */ - public void writeSFixed64NoTag(final long value) throws IOException { - writeRawLittleEndian64(value); - } - - /** Write an {@code sint32} field to the stream. */ - public void writeSInt32NoTag(final int value) throws IOException { - writeRawVarint32(encodeZigZag32(value)); - } - - /** Write an {@code sint64} field to the stream. */ - public void writeSInt64NoTag(final long value) throws IOException { - writeRawVarint64(encodeZigZag64(value)); - } - - // ================================================================= - - /** - * Compute the number of bytes that would be needed to encode a - * {@code double} field, including tag. - */ - public static int computeDoubleSize(final int fieldNumber, - final double value) { - return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code float} field, including tag. - */ - public static int computeFloatSize(final int fieldNumber, final float value) { - return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code uint64} field, including tag. - */ - public static int computeUInt64Size(final int fieldNumber, final long value) { - return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code int64} field, including tag. - */ - public static int computeInt64Size(final int fieldNumber, final long value) { - return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code int32} field, including tag. - */ - public static int computeInt32Size(final int fieldNumber, final int value) { - return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code fixed64} field, including tag. - */ - public static int computeFixed64Size(final int fieldNumber, - final long value) { - return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code fixed32} field, including tag. - */ - public static int computeFixed32Size(final int fieldNumber, - final int value) { - return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code bool} field, including tag. - */ - public static int computeBoolSize(final int fieldNumber, - final boolean value) { - return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code string} field, including tag. - */ - public static int computeStringSize(final int fieldNumber, - final String value) { - return computeTagSize(fieldNumber) + computeStringSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code group} field, including tag. - */ - public static int computeGroupSize(final int fieldNumber, - final MessageNano value) { - return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * embedded message field, including tag. - */ - public static int computeMessageSize(final int fieldNumber, - final MessageNano value) { - return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code bytes} field, including tag. - */ - public static int computeBytesSize(final int fieldNumber, - final byte[] value) { - return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code uint32} field, including tag. - */ - public static int computeUInt32Size(final int fieldNumber, final int value) { - return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * enum field, including tag. Caller is responsible for converting the - * enum value to its numeric value. - */ - public static int computeEnumSize(final int fieldNumber, final int value) { - return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sfixed32} field, including tag. - */ - public static int computeSFixed32Size(final int fieldNumber, - final int value) { - return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sfixed64} field, including tag. - */ - public static int computeSFixed64Size(final int fieldNumber, - final long value) { - return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sint32} field, including tag. - */ - public static int computeSInt32Size(final int fieldNumber, final int value) { - return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sint64} field, including tag. - */ - public static int computeSInt64Size(final int fieldNumber, final long value) { - return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * MessageSet extension to the stream. For historical reasons, - * the wire format differs from normal fields. - */ -// public static int computeMessageSetExtensionSize( -// final int fieldNumber, final MessageMicro value) { -// return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 + -// computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) + -// computeMessageSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value); -// } - - /** - * Compute the number of bytes that would be needed to encode an - * unparsed MessageSet extension field to the stream. For - * historical reasons, the wire format differs from normal fields. - */ -// public static int computeRawMessageSetExtensionSize( -// final int fieldNumber, final ByteStringMicro value) { -// return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 + -// computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) + -// computeBytesSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value); -// } - - // ----------------------------------------------------------------- - - /** - * Compute the number of bytes that would be needed to encode a - * {@code double} field, including tag. - */ - public static int computeDoubleSizeNoTag(final double value) { - return LITTLE_ENDIAN_64_SIZE; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code float} field, including tag. - */ - public static int computeFloatSizeNoTag(final float value) { - return LITTLE_ENDIAN_32_SIZE; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code uint64} field, including tag. - */ - public static int computeUInt64SizeNoTag(final long value) { - return computeRawVarint64Size(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code int64} field, including tag. - */ - public static int computeInt64SizeNoTag(final long value) { - return computeRawVarint64Size(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code int32} field, including tag. - */ - public static int computeInt32SizeNoTag(final int value) { - if (value >= 0) { - return computeRawVarint32Size(value); - } else { - // Must sign-extend. - return 10; - } - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code fixed64} field. - */ - public static int computeFixed64SizeNoTag(final long value) { - return LITTLE_ENDIAN_64_SIZE; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code fixed32} field. - */ - public static int computeFixed32SizeNoTag(final int value) { - return LITTLE_ENDIAN_32_SIZE; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code bool} field. - */ - public static int computeBoolSizeNoTag(final boolean value) { - return 1; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code string} field. - */ - public static int computeStringSizeNoTag(final String value) { - final int length = encodedLength(value); - return computeRawVarint32Size(length) + length; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code group} field. - */ - public static int computeGroupSizeNoTag(final MessageNano value) { - return value.getSerializedSize(); - } - - /** - * Compute the number of bytes that would be needed to encode an embedded - * message field. - */ - public static int computeMessageSizeNoTag(final MessageNano value) { - final int size = value.getSerializedSize(); - return computeRawVarint32Size(size) + size; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code bytes} field. - */ - public static int computeBytesSizeNoTag(final byte[] value) { - return computeRawVarint32Size(value.length) + value.length; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code uint32} field. - */ - public static int computeUInt32SizeNoTag(final int value) { - return computeRawVarint32Size(value); - } - - /** - * Compute the number of bytes that would be needed to encode an enum field. - * Caller is responsible for converting the enum value to its numeric value. - */ - public static int computeEnumSizeNoTag(final int value) { - return computeRawVarint32Size(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sfixed32} field. - */ - public static int computeSFixed32SizeNoTag(final int value) { - return LITTLE_ENDIAN_32_SIZE; - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sfixed64} field. - */ - public static int computeSFixed64SizeNoTag(final long value) { - return LITTLE_ENDIAN_64_SIZE; - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sint32} field. - */ - public static int computeSInt32SizeNoTag(final int value) { - return computeRawVarint32Size(encodeZigZag32(value)); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sint64} field. - */ - public static int computeSInt64SizeNoTag(final long value) { - return computeRawVarint64Size(encodeZigZag64(value)); - } - - // ================================================================= - - /** - * If writing to a flat array, return the space left in the array. - * Otherwise, throws {@code UnsupportedOperationException}. - */ - public int spaceLeft() { - return buffer.remaining(); - } - - /** - * Verifies that {@link #spaceLeft()} returns zero. It's common to create - * a byte array that is exactly big enough to hold a message, then write to - * it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()} - * after writing verifies that the message was actually as big as expected, - * which can help catch bugs. - */ - public void checkNoSpaceLeft() { - if (spaceLeft() != 0) { - throw new IllegalStateException( - "Did not write as much data as expected."); - } - } - - /** - * Returns the position within the internal buffer. - */ - public int position() { - return buffer.position(); - } - - /** - * Resets the position within the internal buffer to zero. - * - * @see #position - * @see #spaceLeft - */ - public void reset() { - buffer.clear(); - } - - /** - * If you create a CodedOutputStream around a simple flat array, you must - * not attempt to write more bytes than the array has space. Otherwise, - * this exception will be thrown. - */ - public static class OutOfSpaceException extends IOException { - private static final long serialVersionUID = -6947486886997889499L; - - OutOfSpaceException(int position, int limit) { - super("CodedOutputStream was writing to a flat byte array and ran " + - "out of space (pos " + position + " limit " + limit + ")."); - } - } - - /** Write a single byte. */ - public void writeRawByte(final byte value) throws IOException { - if (!buffer.hasRemaining()) { - // We're writing to a single buffer. - throw new OutOfSpaceException(buffer.position(), buffer.limit()); - } - - buffer.put(value); - } - - /** Write a single byte, represented by an integer value. */ - public void writeRawByte(final int value) throws IOException { - writeRawByte((byte) value); - } - - /** Write an array of bytes. */ - public void writeRawBytes(final byte[] value) throws IOException { - writeRawBytes(value, 0, value.length); - } - - /** Write part of an array of bytes. */ - public void writeRawBytes(final byte[] value, int offset, int length) - throws IOException { - if (buffer.remaining() >= length) { - buffer.put(value, offset, length); - } else { - // We're writing to a single buffer. - throw new OutOfSpaceException(buffer.position(), buffer.limit()); - } - } - - /** Encode and write a tag. */ - public void writeTag(final int fieldNumber, final int wireType) - throws IOException { - writeRawVarint32(WireFormatNano.makeTag(fieldNumber, wireType)); - } - - /** Compute the number of bytes that would be needed to encode a tag. */ - public static int computeTagSize(final int fieldNumber) { - return computeRawVarint32Size(WireFormatNano.makeTag(fieldNumber, 0)); - } - - /** - * Encode and write a varint. {@code value} is treated as - * unsigned, so it won't be sign-extended if negative. - */ - public void writeRawVarint32(int value) throws IOException { - while (true) { - if ((value & ~0x7F) == 0) { - writeRawByte(value); - return; - } else { - writeRawByte((value & 0x7F) | 0x80); - value >>>= 7; - } - } - } - - /** - * Compute the number of bytes that would be needed to encode a varint. - * {@code value} is treated as unsigned, so it won't be sign-extended if - * negative. - */ - public static int computeRawVarint32Size(final int value) { - if ((value & (0xffffffff << 7)) == 0) return 1; - if ((value & (0xffffffff << 14)) == 0) return 2; - if ((value & (0xffffffff << 21)) == 0) return 3; - if ((value & (0xffffffff << 28)) == 0) return 4; - return 5; - } - - /** Encode and write a varint. */ - public void writeRawVarint64(long value) throws IOException { - while (true) { - if ((value & ~0x7FL) == 0) { - writeRawByte((int)value); - return; - } else { - writeRawByte(((int)value & 0x7F) | 0x80); - value >>>= 7; - } - } - } - - /** Compute the number of bytes that would be needed to encode a varint. */ - public static int computeRawVarint64Size(final long value) { - if ((value & (0xffffffffffffffffL << 7)) == 0) return 1; - if ((value & (0xffffffffffffffffL << 14)) == 0) return 2; - if ((value & (0xffffffffffffffffL << 21)) == 0) return 3; - if ((value & (0xffffffffffffffffL << 28)) == 0) return 4; - if ((value & (0xffffffffffffffffL << 35)) == 0) return 5; - if ((value & (0xffffffffffffffffL << 42)) == 0) return 6; - if ((value & (0xffffffffffffffffL << 49)) == 0) return 7; - if ((value & (0xffffffffffffffffL << 56)) == 0) return 8; - if ((value & (0xffffffffffffffffL << 63)) == 0) return 9; - return 10; - } - - /** Write a little-endian 32-bit integer. */ - public void writeRawLittleEndian32(final int value) throws IOException { - if (buffer.remaining() < 4) { - throw new OutOfSpaceException(buffer.position(), buffer.limit()); - } - buffer.putInt(value); - } - - public static final int LITTLE_ENDIAN_32_SIZE = 4; - - /** Write a little-endian 64-bit integer. */ - public void writeRawLittleEndian64(final long value) throws IOException { - if (buffer.remaining() < 8) { - throw new OutOfSpaceException(buffer.position(), buffer.limit()); - } - buffer.putLong(value); - } - - public static final int LITTLE_ENDIAN_64_SIZE = 8; - - /** - * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers - * into values that can be efficiently encoded with varint. (Otherwise, - * negative values must be sign-extended to 64 bits to be varint encoded, - * thus always taking 10 bytes on the wire.) - * - * @param n A signed 32-bit integer. - * @return An unsigned 32-bit integer, stored in a signed int because - * Java has no explicit unsigned support. - */ - public static int encodeZigZag32(final int n) { - // Note: the right-shift must be arithmetic - return (n << 1) ^ (n >> 31); - } - - /** - * Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers - * into values that can be efficiently encoded with varint. (Otherwise, - * negative values must be sign-extended to 64 bits to be varint encoded, - * thus always taking 10 bytes on the wire.) - * - * @param n A signed 64-bit integer. - * @return An unsigned 64-bit integer, stored in a signed int because - * Java has no explicit unsigned support. - */ - public static long encodeZigZag64(final long n) { - // Note: the right-shift must be arithmetic - return (n << 1) ^ (n >> 63); - } - - static int computeFieldSize(int number, int type, Object object) { - switch (type) { - case InternalNano.TYPE_BOOL: - return computeBoolSize(number, (Boolean) object); - case InternalNano.TYPE_BYTES: - return computeBytesSize(number, (byte[]) object); - case InternalNano.TYPE_STRING: - return computeStringSize(number, (String) object); - case InternalNano.TYPE_FLOAT: - return computeFloatSize(number, (Float) object); - case InternalNano.TYPE_DOUBLE: - return computeDoubleSize(number, (Double) object); - case InternalNano.TYPE_ENUM: - return computeEnumSize(number, (Integer) object); - case InternalNano.TYPE_FIXED32: - return computeFixed32Size(number, (Integer) object); - case InternalNano.TYPE_INT32: - return computeInt32Size(number, (Integer) object); - case InternalNano.TYPE_UINT32: - return computeUInt32Size(number, (Integer) object); - case InternalNano.TYPE_SINT32: - return computeSInt32Size(number, (Integer) object); - case InternalNano.TYPE_SFIXED32: - return computeSFixed32Size(number, (Integer) object); - case InternalNano.TYPE_INT64: - return computeInt64Size(number, (Long) object); - case InternalNano.TYPE_UINT64: - return computeUInt64Size(number, (Long) object); - case InternalNano.TYPE_SINT64: - return computeSInt64Size(number, (Long) object); - case InternalNano.TYPE_FIXED64: - return computeFixed64Size(number, (Long) object); - case InternalNano.TYPE_SFIXED64: - return computeSFixed64Size(number, (Long) object); - case InternalNano.TYPE_MESSAGE: - return computeMessageSize(number, (MessageNano) object); - case InternalNano.TYPE_GROUP: - return computeGroupSize(number, (MessageNano) object); - default: - throw new IllegalArgumentException("Unknown type: " + type); - } - } - - void writeField(int number, int type, Object value) - throws IOException { - switch (type) { - case InternalNano.TYPE_DOUBLE: - Double doubleValue = (Double) value; - writeDouble(number, doubleValue); - break; - case InternalNano.TYPE_FLOAT: - Float floatValue = (Float) value; - writeFloat(number, floatValue); - break; - case InternalNano.TYPE_INT64: - Long int64Value = (Long) value; - writeInt64(number, int64Value); - break; - case InternalNano.TYPE_UINT64: - Long uint64Value = (Long) value; - writeUInt64(number, uint64Value); - break; - case InternalNano.TYPE_INT32: - Integer int32Value = (Integer) value; - writeInt32(number, int32Value); - break; - case InternalNano.TYPE_FIXED64: - Long fixed64Value = (Long) value; - writeFixed64(number, fixed64Value); - break; - case InternalNano.TYPE_FIXED32: - Integer fixed32Value = (Integer) value; - writeFixed32(number, fixed32Value); - break; - case InternalNano.TYPE_BOOL: - Boolean boolValue = (Boolean) value; - writeBool(number, boolValue); - break; - case InternalNano.TYPE_STRING: - String stringValue = (String) value; - writeString(number, stringValue); - break; - case InternalNano.TYPE_BYTES: - byte[] bytesValue = (byte[]) value; - writeBytes(number, bytesValue); - break; - case InternalNano.TYPE_UINT32: - Integer uint32Value = (Integer) value; - writeUInt32(number, uint32Value); - break; - case InternalNano.TYPE_ENUM: - Integer enumValue = (Integer) value; - writeEnum(number, enumValue); - break; - case InternalNano.TYPE_SFIXED32: - Integer sfixed32Value = (Integer) value; - writeSFixed32(number, sfixed32Value); - break; - case InternalNano.TYPE_SFIXED64: - Long sfixed64Value = (Long) value; - writeSFixed64(number, sfixed64Value); - break; - case InternalNano.TYPE_SINT32: - Integer sint32Value = (Integer) value; - writeSInt32(number, sint32Value); - break; - case InternalNano.TYPE_SINT64: - Long sint64Value = (Long) value; - writeSInt64(number, sint64Value); - break; - case InternalNano.TYPE_MESSAGE: - MessageNano messageValue = (MessageNano) value; - writeMessage(number, messageValue); - break; - case InternalNano.TYPE_GROUP: - MessageNano groupValue = (MessageNano) value; - writeGroup(number, groupValue); - break; - default: - throw new IOException("Unknown type: " + type); - } - } - -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java b/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java deleted file mode 100644 index 87973d76f0703..0000000000000 --- a/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java +++ /dev/null @@ -1,169 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 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.nano; - -import java.io.IOException; - -/** - * Base class of those Protocol Buffer messages that need to store unknown fields, - * such as extensions. - */ -public abstract class ExtendableMessageNano> - extends MessageNano { - /** - * A container for fields unknown to the message, including extensions. Extension fields can - * can be accessed through the {@link #getExtension} and {@link #setExtension} methods. - */ - protected FieldArray unknownFieldData; - - @Override - protected int computeSerializedSize() { - int size = 0; - if (unknownFieldData != null) { - for (int i = 0; i < unknownFieldData.size(); i++) { - FieldData field = unknownFieldData.dataAt(i); - size += field.computeSerializedSize(); - } - } - return size; - } - - @Override - public void writeTo(CodedOutputByteBufferNano output) throws IOException { - if (unknownFieldData == null) { - return; - } - for (int i = 0; i < unknownFieldData.size(); i++) { - FieldData field = unknownFieldData.dataAt(i); - field.writeTo(output); - } - } - - /** - * Checks if there is a value stored for the specified extension in this - * message. - */ - public final boolean hasExtension(Extension extension) { - if (unknownFieldData == null) { - return false; - } - FieldData field = unknownFieldData.get(WireFormatNano.getTagFieldNumber(extension.tag)); - return field != null; - } - - /** - * Gets the value stored in the specified extension of this message. - */ - public final T getExtension(Extension extension) { - if (unknownFieldData == null) { - return null; - } - FieldData field = unknownFieldData.get(WireFormatNano.getTagFieldNumber(extension.tag)); - return field == null ? null : field.getValue(extension); - } - - /** - * Sets the value of the specified extension of this message. - */ - public final M setExtension(Extension extension, T value) { - int fieldNumber = WireFormatNano.getTagFieldNumber(extension.tag); - if (value == null) { - if (unknownFieldData != null) { - unknownFieldData.remove(fieldNumber); - if (unknownFieldData.isEmpty()) { - unknownFieldData = null; - } - } - } else { - FieldData field = null; - if (unknownFieldData == null) { - unknownFieldData = new FieldArray(); - } else { - field = unknownFieldData.get(fieldNumber); - } - if (field == null) { - unknownFieldData.put(fieldNumber, new FieldData(extension, value)); - } else { - field.setValue(extension, value); - } - } - - @SuppressWarnings("unchecked") // Generated code should guarantee type safety - M typedThis = (M) this; - return typedThis; - } - - /** - * Stores the binary data of an unknown field. - * - *

Generated messages will call this for unknown fields if the store_unknown_fields - * option is on. - * - *

Note that the tag might be a end-group tag (rather than the start of an unknown field) in - * which case we do not want to add an unknown field entry. - * - * @param input the input buffer. - * @param tag the tag of the field. - - * @return {@literal true} unless the tag is an end-group tag. - */ - protected final boolean storeUnknownField(CodedInputByteBufferNano input, int tag) - throws IOException { - int startPos = input.getPosition(); - if (!input.skipField(tag)) { - return false; // This wasn't an unknown field, it's an end-group tag. - } - int fieldNumber = WireFormatNano.getTagFieldNumber(tag); - int endPos = input.getPosition(); - byte[] bytes = input.getData(startPos, endPos - startPos); - UnknownFieldData unknownField = new UnknownFieldData(tag, bytes); - - FieldData field = null; - if (unknownFieldData == null) { - unknownFieldData = new FieldArray(); - } else { - field = unknownFieldData.get(fieldNumber); - } - if (field == null) { - field = new FieldData(); - unknownFieldData.put(fieldNumber, field); - } - field.addUnknownField(unknownField); - return true; - } - - @Override - public M clone() throws CloneNotSupportedException { - M cloned = (M) super.clone(); - InternalNano.cloneUnknownFieldData(this, cloned); - return cloned; - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/Extension.java b/javanano/src/main/java/com/google/protobuf/nano/Extension.java deleted file mode 100644 index c458f9b1fc80f..0000000000000 --- a/javanano/src/main/java/com/google/protobuf/nano/Extension.java +++ /dev/null @@ -1,706 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 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.nano; - -import java.io.IOException; -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.List; - -/** - * Represents an extension. - * - * @author bduff@google.com (Brian Duff) - * @author maxtroy@google.com (Max Cai) - * @param the type of the extendable message this extension is for. - * @param the Java type of the extension; see {@link #clazz}. - */ -public class Extension, T> { - - /* - * Because we typically only define message-typed extensions, the Extension class hierarchy is - * designed as follows, to allow a big amount of code in this file to be removed by ProGuard: - * - * Extension // ready to use for message/group typed extensions - * Δ - * | - * PrimitiveExtension // for primitive/enum typed extensions - */ - - public static final int TYPE_DOUBLE = InternalNano.TYPE_DOUBLE; - public static final int TYPE_FLOAT = InternalNano.TYPE_FLOAT; - public static final int TYPE_INT64 = InternalNano.TYPE_INT64; - public static final int TYPE_UINT64 = InternalNano.TYPE_UINT64; - public static final int TYPE_INT32 = InternalNano.TYPE_INT32; - public static final int TYPE_FIXED64 = InternalNano.TYPE_FIXED64; - public static final int TYPE_FIXED32 = InternalNano.TYPE_FIXED32; - public static final int TYPE_BOOL = InternalNano.TYPE_BOOL; - public static final int TYPE_STRING = InternalNano.TYPE_STRING; - public static final int TYPE_GROUP = InternalNano.TYPE_GROUP; - public static final int TYPE_MESSAGE = InternalNano.TYPE_MESSAGE; - public static final int TYPE_BYTES = InternalNano.TYPE_BYTES; - public static final int TYPE_UINT32 = InternalNano.TYPE_UINT32; - public static final int TYPE_ENUM = InternalNano.TYPE_ENUM; - public static final int TYPE_SFIXED32 = InternalNano.TYPE_SFIXED32; - public static final int TYPE_SFIXED64 = InternalNano.TYPE_SFIXED64; - public static final int TYPE_SINT32 = InternalNano.TYPE_SINT32; - public static final int TYPE_SINT64 = InternalNano.TYPE_SINT64; - - /** - * Creates an {@code Extension} of the given message type and tag number. - * Should be used by the generated code only. - * - * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP} - * @deprecated use {@link #createMessageTyped(int, Class, long)} instead. - */ - @Deprecated - public static , T extends MessageNano> - Extension createMessageTyped(int type, Class clazz, int tag) { - return new Extension(type, clazz, tag, false); - } - - // Note: these create...() methods take a long for the tag parameter, - // because tags are represented as unsigned ints, and these values exist - // in generated code as long values. However, they can fit in 32-bits, so - // it's safe to cast them to int without loss of precision. - - /** - * Creates an {@code Extension} of the given message type and tag number. - * Should be used by the generated code only. - * - * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP} - */ - public static , T extends MessageNano> - Extension createMessageTyped(int type, Class clazz, long tag) { - return new Extension(type, clazz, (int) tag, false); - } - - /** - * Creates a repeated {@code Extension} of the given message type and tag number. - * Should be used by the generated code only. - * - * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP} - */ - public static , T extends MessageNano> - Extension createRepeatedMessageTyped(int type, Class clazz, long tag) { - return new Extension(type, clazz, (int) tag, true); - } - - /** - * Creates an {@code Extension} of the given primitive type and tag number. - * Should be used by the generated code only. - * - * @param type one of {@code TYPE_*}, except {@link #TYPE_MESSAGE} and {@link #TYPE_GROUP} - * @param clazz the boxed Java type of this extension - */ - public static , T> - Extension createPrimitiveTyped(int type, Class clazz, long tag) { - return new PrimitiveExtension(type, clazz, (int) tag, false, 0, 0); - } - - /** - * Creates a repeated {@code Extension} of the given primitive type and tag number. - * Should be used by the generated code only. - * - * @param type one of {@code TYPE_*}, except {@link #TYPE_MESSAGE} and {@link #TYPE_GROUP} - * @param clazz the Java array type of this extension, with an unboxed component type - */ - public static , T> - Extension createRepeatedPrimitiveTyped( - int type, Class clazz, long tag, long nonPackedTag, long packedTag) { - return new PrimitiveExtension(type, clazz, (int) tag, true, - (int) nonPackedTag, (int) packedTag); - } - - /** - * Protocol Buffer type of this extension; one of the {@code TYPE_} constants. - */ - protected final int type; - - /** - * Java type of this extension. For a singular extension, this is the boxed Java type for the - * Protocol Buffer {@link #type}; for a repeated extension, this is an array type whose - * component type is the unboxed Java type for {@link #type}. For example, for a singular - * {@code int32}/{@link #TYPE_INT32} extension, this equals {@code Integer.class}; for a - * repeated {@code int32} extension, this equals {@code int[].class}. - */ - protected final Class clazz; - - /** - * Tag number of this extension. The data should be viewed as an unsigned 32-bit value. - */ - public final int tag; - - /** - * Whether this extension is repeated. - */ - protected final boolean repeated; - - private Extension(int type, Class clazz, int tag, boolean repeated) { - this.type = type; - this.clazz = clazz; - this.tag = tag; - this.repeated = repeated; - } - - /** - * Returns the value of this extension stored in the given list of unknown fields, or - * {@code null} if no unknown fields matches this extension. - * - * @param unknownFields a list of {@link UnknownFieldData}. All of the elements must have a tag - * that matches this Extension's tag. - * - */ - final T getValueFrom(List unknownFields) { - if (unknownFields == null) { - return null; - } - return repeated ? getRepeatedValueFrom(unknownFields) : getSingularValueFrom(unknownFields); - } - - private T getRepeatedValueFrom(List unknownFields) { - // For repeated extensions, read all matching unknown fields in their original order. - List resultList = new ArrayList(); - for (int i = 0; i < unknownFields.size(); i++) { - UnknownFieldData data = unknownFields.get(i); - if (data.bytes.length != 0) { - readDataInto(data, resultList); - } - } - - int resultSize = resultList.size(); - if (resultSize == 0) { - return null; - } else { - T result = clazz.cast(Array.newInstance(clazz.getComponentType(), resultSize)); - for (int i = 0; i < resultSize; i++) { - Array.set(result, i, resultList.get(i)); - } - return result; - } - } - - private T getSingularValueFrom(List unknownFields) { - // For singular extensions, get the last piece of data stored under this extension. - if (unknownFields.isEmpty()) { - return null; - } - UnknownFieldData lastData = unknownFields.get(unknownFields.size() - 1); - return clazz.cast(readData(CodedInputByteBufferNano.newInstance(lastData.bytes))); - } - - protected Object readData(CodedInputByteBufferNano input) { - // This implementation is for message/group extensions. - Class messageType = repeated ? clazz.getComponentType() : clazz; - try { - switch (type) { - case TYPE_GROUP: - MessageNano group = (MessageNano) messageType.newInstance(); - input.readGroup(group, WireFormatNano.getTagFieldNumber(tag)); - return group; - case TYPE_MESSAGE: - MessageNano message = (MessageNano) messageType.newInstance(); - input.readMessage(message); - return message; - default: - throw new IllegalArgumentException("Unknown type " + type); - } - } catch (InstantiationException e) { - throw new IllegalArgumentException( - "Error creating instance of class " + messageType, e); - } catch (IllegalAccessException e) { - throw new IllegalArgumentException( - "Error creating instance of class " + messageType, e); - } catch (IOException e) { - throw new IllegalArgumentException("Error reading extension field", e); - } - } - - protected void readDataInto(UnknownFieldData data, List resultList) { - // This implementation is for message/group extensions. - resultList.add(readData(CodedInputByteBufferNano.newInstance(data.bytes))); - } - - void writeTo(Object value, CodedOutputByteBufferNano output) throws IOException { - if (repeated) { - writeRepeatedData(value, output); - } else { - writeSingularData(value, output); - } - } - - protected void writeSingularData(Object value, CodedOutputByteBufferNano out) { - // This implementation is for message/group extensions. - try { - out.writeRawVarint32(tag); - switch (type) { - case TYPE_GROUP: - MessageNano groupValue = (MessageNano) value; - int fieldNumber = WireFormatNano.getTagFieldNumber(tag); - out.writeGroupNoTag(groupValue); - // The endgroup tag must be included in the data payload. - out.writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP); - break; - case TYPE_MESSAGE: - MessageNano messageValue = (MessageNano) value; - out.writeMessageNoTag(messageValue); - break; - default: - throw new IllegalArgumentException("Unknown type " + type); - } - } catch (IOException e) { - // Should not happen - throw new IllegalStateException(e); - } - } - - protected void writeRepeatedData(Object array, CodedOutputByteBufferNano output) { - // This implementation is for non-packed extensions. - int arrayLength = Array.getLength(array); - for (int i = 0; i < arrayLength; i++) { - Object element = Array.get(array, i); - if (element != null) { - writeSingularData(element, output); - } - } - } - - int computeSerializedSize(Object value) { - if (repeated) { - return computeRepeatedSerializedSize(value); - } else { - return computeSingularSerializedSize(value); - } - } - - protected int computeRepeatedSerializedSize(Object array) { - // This implementation is for non-packed extensions. - int size = 0; - int arrayLength = Array.getLength(array); - for (int i = 0; i < arrayLength; i++) { - Object element = Array.get(array, i); - if (element != null) { - size += computeSingularSerializedSize(Array.get(array, i)); - } - } - return size; - } - - protected int computeSingularSerializedSize(Object value) { - // This implementation is for message/group extensions. - int fieldNumber = WireFormatNano.getTagFieldNumber(tag); - switch (type) { - case TYPE_GROUP: - MessageNano groupValue = (MessageNano) value; - return CodedOutputByteBufferNano.computeGroupSize(fieldNumber, groupValue); - case TYPE_MESSAGE: - MessageNano messageValue = (MessageNano) value; - return CodedOutputByteBufferNano.computeMessageSize(fieldNumber, messageValue); - default: - throw new IllegalArgumentException("Unknown type " + type); - } - } - - /** - * Represents an extension of a primitive (including enum) type. If there is no primitive - * extensions, this subclass will be removable by ProGuard. - */ - private static class PrimitiveExtension, T> - extends Extension { - - /** - * Tag of a piece of non-packed data from the wire compatible with this extension. - */ - private final int nonPackedTag; - - /** - * Tag of a piece of packed data from the wire compatible with this extension. - * 0 if the type of this extension is not packable. - */ - private final int packedTag; - - public PrimitiveExtension(int type, Class clazz, int tag, boolean repeated, - int nonPackedTag, int packedTag) { - super(type, clazz, tag, repeated); - this.nonPackedTag = nonPackedTag; - this.packedTag = packedTag; - } - - @Override - protected Object readData(CodedInputByteBufferNano input) { - try { - return input.readPrimitiveField(type); - } catch (IOException e) { - throw new IllegalArgumentException("Error reading extension field", e); - } - } - - @Override - protected void readDataInto(UnknownFieldData data, List resultList) { - // This implementation is for primitive typed extensions, - // which can read both packed and non-packed data. - if (data.tag == nonPackedTag) { - resultList.add(readData(CodedInputByteBufferNano.newInstance(data.bytes))); - } else { - CodedInputByteBufferNano buffer = - CodedInputByteBufferNano.newInstance(data.bytes); - try { - buffer.pushLimit(buffer.readRawVarint32()); // length limit - } catch (IOException e) { - throw new IllegalArgumentException("Error reading extension field", e); - } - while (!buffer.isAtEnd()) { - resultList.add(readData(buffer)); - } - } - } - - @Override - protected final void writeSingularData(Object value, CodedOutputByteBufferNano output) { - try { - output.writeRawVarint32(tag); - switch (type) { - case TYPE_DOUBLE: - Double doubleValue = (Double) value; - output.writeDoubleNoTag(doubleValue); - break; - case TYPE_FLOAT: - Float floatValue = (Float) value; - output.writeFloatNoTag(floatValue); - break; - case TYPE_INT64: - Long int64Value = (Long) value; - output.writeInt64NoTag(int64Value); - break; - case TYPE_UINT64: - Long uint64Value = (Long) value; - output.writeUInt64NoTag(uint64Value); - break; - case TYPE_INT32: - Integer int32Value = (Integer) value; - output.writeInt32NoTag(int32Value); - break; - case TYPE_FIXED64: - Long fixed64Value = (Long) value; - output.writeFixed64NoTag(fixed64Value); - break; - case TYPE_FIXED32: - Integer fixed32Value = (Integer) value; - output.writeFixed32NoTag(fixed32Value); - break; - case TYPE_BOOL: - Boolean boolValue = (Boolean) value; - output.writeBoolNoTag(boolValue); - break; - case TYPE_STRING: - String stringValue = (String) value; - output.writeStringNoTag(stringValue); - break; - case TYPE_BYTES: - byte[] bytesValue = (byte[]) value; - output.writeBytesNoTag(bytesValue); - break; - case TYPE_UINT32: - Integer uint32Value = (Integer) value; - output.writeUInt32NoTag(uint32Value); - break; - case TYPE_ENUM: - Integer enumValue = (Integer) value; - output.writeEnumNoTag(enumValue); - break; - case TYPE_SFIXED32: - Integer sfixed32Value = (Integer) value; - output.writeSFixed32NoTag(sfixed32Value); - break; - case TYPE_SFIXED64: - Long sfixed64Value = (Long) value; - output.writeSFixed64NoTag(sfixed64Value); - break; - case TYPE_SINT32: - Integer sint32Value = (Integer) value; - output.writeSInt32NoTag(sint32Value); - break; - case TYPE_SINT64: - Long sint64Value = (Long) value; - output.writeSInt64NoTag(sint64Value); - break; - default: - throw new IllegalArgumentException("Unknown type " + type); - } - } catch (IOException e) { - // Should not happen - throw new IllegalStateException(e); - } - } - - @Override - protected void writeRepeatedData(Object array, CodedOutputByteBufferNano output) { - if (tag == nonPackedTag) { - // Use base implementation for non-packed data - super.writeRepeatedData(array, output); - } else if (tag == packedTag) { - // Packed. Note that the array element type is guaranteed to be primitive, so there - // won't be any null elements, so no null check in this block. - int arrayLength = Array.getLength(array); - int dataSize = computePackedDataSize(array); - - try { - output.writeRawVarint32(tag); - output.writeRawVarint32(dataSize); - switch (type) { - case TYPE_BOOL: - for (int i = 0; i < arrayLength; i++) { - output.writeBoolNoTag(Array.getBoolean(array, i)); - } - break; - case TYPE_FIXED32: - for (int i = 0; i < arrayLength; i++) { - output.writeFixed32NoTag(Array.getInt(array, i)); - } - break; - case TYPE_SFIXED32: - for (int i = 0; i < arrayLength; i++) { - output.writeSFixed32NoTag(Array.getInt(array, i)); - } - break; - case TYPE_FLOAT: - for (int i = 0; i < arrayLength; i++) { - output.writeFloatNoTag(Array.getFloat(array, i)); - } - break; - case TYPE_FIXED64: - for (int i = 0; i < arrayLength; i++) { - output.writeFixed64NoTag(Array.getLong(array, i)); - } - break; - case TYPE_SFIXED64: - for (int i = 0; i < arrayLength; i++) { - output.writeSFixed64NoTag(Array.getLong(array, i)); - } - break; - case TYPE_DOUBLE: - for (int i = 0; i < arrayLength; i++) { - output.writeDoubleNoTag(Array.getDouble(array, i)); - } - break; - case TYPE_INT32: - for (int i = 0; i < arrayLength; i++) { - output.writeInt32NoTag(Array.getInt(array, i)); - } - break; - case TYPE_SINT32: - for (int i = 0; i < arrayLength; i++) { - output.writeSInt32NoTag(Array.getInt(array, i)); - } - break; - case TYPE_UINT32: - for (int i = 0; i < arrayLength; i++) { - output.writeUInt32NoTag(Array.getInt(array, i)); - } - break; - case TYPE_INT64: - for (int i = 0; i < arrayLength; i++) { - output.writeInt64NoTag(Array.getLong(array, i)); - } - break; - case TYPE_SINT64: - for (int i = 0; i < arrayLength; i++) { - output.writeSInt64NoTag(Array.getLong(array, i)); - } - break; - case TYPE_UINT64: - for (int i = 0; i < arrayLength; i++) { - output.writeUInt64NoTag(Array.getLong(array, i)); - } - break; - case TYPE_ENUM: - for (int i = 0; i < arrayLength; i++) { - output.writeEnumNoTag(Array.getInt(array, i)); - } - break; - default: - throw new IllegalArgumentException("Unpackable type " + type); - } - } catch (IOException e) { - // Should not happen. - throw new IllegalStateException(e); - } - } else { - throw new IllegalArgumentException("Unexpected repeated extension tag " + tag - + ", unequal to both non-packed variant " + nonPackedTag - + " and packed variant " + packedTag); - } - } - - private int computePackedDataSize(Object array) { - int dataSize = 0; - int arrayLength = Array.getLength(array); - switch (type) { - case TYPE_BOOL: - // Bools are stored as int32 but just as 0 or 1, so 1 byte each. - dataSize = arrayLength; - break; - case TYPE_FIXED32: - case TYPE_SFIXED32: - case TYPE_FLOAT: - dataSize = arrayLength * CodedOutputByteBufferNano.LITTLE_ENDIAN_32_SIZE; - break; - case TYPE_FIXED64: - case TYPE_SFIXED64: - case TYPE_DOUBLE: - dataSize = arrayLength * CodedOutputByteBufferNano.LITTLE_ENDIAN_64_SIZE; - break; - case TYPE_INT32: - for (int i = 0; i < arrayLength; i++) { - dataSize += CodedOutputByteBufferNano.computeInt32SizeNoTag( - Array.getInt(array, i)); - } - break; - case TYPE_SINT32: - for (int i = 0; i < arrayLength; i++) { - dataSize += CodedOutputByteBufferNano.computeSInt32SizeNoTag( - Array.getInt(array, i)); - } - break; - case TYPE_UINT32: - for (int i = 0; i < arrayLength; i++) { - dataSize += CodedOutputByteBufferNano.computeUInt32SizeNoTag( - Array.getInt(array, i)); - } - break; - case TYPE_INT64: - for (int i = 0; i < arrayLength; i++) { - dataSize += CodedOutputByteBufferNano.computeInt64SizeNoTag( - Array.getLong(array, i)); - } - break; - case TYPE_SINT64: - for (int i = 0; i < arrayLength; i++) { - dataSize += CodedOutputByteBufferNano.computeSInt64SizeNoTag( - Array.getLong(array, i)); - } - break; - case TYPE_UINT64: - for (int i = 0; i < arrayLength; i++) { - dataSize += CodedOutputByteBufferNano.computeUInt64SizeNoTag( - Array.getLong(array, i)); - } - break; - case TYPE_ENUM: - for (int i = 0; i < arrayLength; i++) { - dataSize += CodedOutputByteBufferNano.computeEnumSizeNoTag( - Array.getInt(array, i)); - } - break; - default: - throw new IllegalArgumentException("Unexpected non-packable type " + type); - } - return dataSize; - } - - @Override - protected int computeRepeatedSerializedSize(Object array) { - if (tag == nonPackedTag) { - // Use base implementation for non-packed data - return super.computeRepeatedSerializedSize(array); - } else if (tag == packedTag) { - // Packed. - int dataSize = computePackedDataSize(array); - int payloadSize = - dataSize + CodedOutputByteBufferNano.computeRawVarint32Size(dataSize); - return payloadSize + CodedOutputByteBufferNano.computeRawVarint32Size(tag); - } else { - throw new IllegalArgumentException("Unexpected repeated extension tag " + tag - + ", unequal to both non-packed variant " + nonPackedTag - + " and packed variant " + packedTag); - } - } - - @Override - protected final int computeSingularSerializedSize(Object value) { - int fieldNumber = WireFormatNano.getTagFieldNumber(tag); - switch (type) { - case TYPE_DOUBLE: - Double doubleValue = (Double) value; - return CodedOutputByteBufferNano.computeDoubleSize(fieldNumber, doubleValue); - case TYPE_FLOAT: - Float floatValue = (Float) value; - return CodedOutputByteBufferNano.computeFloatSize(fieldNumber, floatValue); - case TYPE_INT64: - Long int64Value = (Long) value; - return CodedOutputByteBufferNano.computeInt64Size(fieldNumber, int64Value); - case TYPE_UINT64: - Long uint64Value = (Long) value; - return CodedOutputByteBufferNano.computeUInt64Size(fieldNumber, uint64Value); - case TYPE_INT32: - Integer int32Value = (Integer) value; - return CodedOutputByteBufferNano.computeInt32Size(fieldNumber, int32Value); - case TYPE_FIXED64: - Long fixed64Value = (Long) value; - return CodedOutputByteBufferNano.computeFixed64Size(fieldNumber, fixed64Value); - case TYPE_FIXED32: - Integer fixed32Value = (Integer) value; - return CodedOutputByteBufferNano.computeFixed32Size(fieldNumber, fixed32Value); - case TYPE_BOOL: - Boolean boolValue = (Boolean) value; - return CodedOutputByteBufferNano.computeBoolSize(fieldNumber, boolValue); - case TYPE_STRING: - String stringValue = (String) value; - return CodedOutputByteBufferNano.computeStringSize(fieldNumber, stringValue); - case TYPE_BYTES: - byte[] bytesValue = (byte[]) value; - return CodedOutputByteBufferNano.computeBytesSize(fieldNumber, bytesValue); - case TYPE_UINT32: - Integer uint32Value = (Integer) value; - return CodedOutputByteBufferNano.computeUInt32Size(fieldNumber, uint32Value); - case TYPE_ENUM: - Integer enumValue = (Integer) value; - return CodedOutputByteBufferNano.computeEnumSize(fieldNumber, enumValue); - case TYPE_SFIXED32: - Integer sfixed32Value = (Integer) value; - return CodedOutputByteBufferNano.computeSFixed32Size(fieldNumber, - sfixed32Value); - case TYPE_SFIXED64: - Long sfixed64Value = (Long) value; - return CodedOutputByteBufferNano.computeSFixed64Size(fieldNumber, - sfixed64Value); - case TYPE_SINT32: - Integer sint32Value = (Integer) value; - return CodedOutputByteBufferNano.computeSInt32Size(fieldNumber, sint32Value); - case TYPE_SINT64: - Long sint64Value = (Long) value; - return CodedOutputByteBufferNano.computeSInt64Size(fieldNumber, sint64Value); - default: - throw new IllegalArgumentException("Unknown type " + type); - } - } - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java b/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java deleted file mode 100644 index b49a97fa5abe9..0000000000000 --- a/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java +++ /dev/null @@ -1,291 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2014 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf.nano; - - -/** - * A custom version of {@code android.util.SparseArray} with the minimal API - * for storing {@link FieldData} objects. - * - *

This class is an internal implementation detail of nano and should not - * be called directly by clients. - * - * Based on {@code android.support.v4.util.SpareArrayCompat}. - */ -public final class FieldArray implements Cloneable { - private static final FieldData DELETED = new FieldData(); - private boolean mGarbage = false; - - private int[] mFieldNumbers; - private FieldData[] mData; - private int mSize; - - /** - * Creates a new FieldArray containing no fields. - */ - FieldArray() { - this(10); - } - - /** - * Creates a new FieldArray containing no mappings that will not - * require any additional memory allocation to store the specified - * number of mappings. - */ - FieldArray(int initialCapacity) { - initialCapacity = idealIntArraySize(initialCapacity); - mFieldNumbers = new int[initialCapacity]; - mData = new FieldData[initialCapacity]; - mSize = 0; - } - - /** - * Gets the FieldData mapped from the specified fieldNumber, or null - * if no such mapping has been made. - */ - FieldData get(int fieldNumber) { - int i = binarySearch(fieldNumber); - - if (i < 0 || mData[i] == DELETED) { - return null; - } else { - return mData[i]; - } - } - - /** - * Removes the data from the specified fieldNumber, if there was any. - */ - void remove(int fieldNumber) { - int i = binarySearch(fieldNumber); - - if (i >= 0 && mData[i] != DELETED) { - mData[i] = DELETED; - mGarbage = true; - } - } - - private void gc() { - int n = mSize; - int o = 0; - int[] keys = mFieldNumbers; - FieldData[] values = mData; - - for (int i = 0; i < n; i++) { - FieldData val = values[i]; - - if (val != DELETED) { - if (i != o) { - keys[o] = keys[i]; - values[o] = val; - values[i] = null; - } - - o++; - } - } - - mGarbage = false; - mSize = o; - } - - /** - * Adds a mapping from the specified fieldNumber to the specified data, - * replacing the previous mapping if there was one. - */ - void put(int fieldNumber, FieldData data) { - int i = binarySearch(fieldNumber); - - if (i >= 0) { - mData[i] = data; - } else { - i = ~i; - - if (i < mSize && mData[i] == DELETED) { - mFieldNumbers[i] = fieldNumber; - mData[i] = data; - return; - } - - if (mGarbage && mSize >= mFieldNumbers.length) { - gc(); - - // Search again because indices may have changed. - i = ~ binarySearch(fieldNumber); - } - - if (mSize >= mFieldNumbers.length) { - int n = idealIntArraySize(mSize + 1); - - int[] nkeys = new int[n]; - FieldData[] nvalues = new FieldData[n]; - - System.arraycopy(mFieldNumbers, 0, nkeys, 0, mFieldNumbers.length); - System.arraycopy(mData, 0, nvalues, 0, mData.length); - - mFieldNumbers = nkeys; - mData = nvalues; - } - - if (mSize - i != 0) { - System.arraycopy(mFieldNumbers, i, mFieldNumbers, i + 1, mSize - i); - System.arraycopy(mData, i, mData, i + 1, mSize - i); - } - - mFieldNumbers[i] = fieldNumber; - mData[i] = data; - mSize++; - } - } - - /** - * Returns the number of key-value mappings that this FieldArray - * currently stores. - */ - int size() { - if (mGarbage) { - gc(); - } - - return mSize; - } - - public boolean isEmpty() { - return size() == 0; - } - - /** - * Given an index in the range 0...size()-1, returns - * the value from the indexth key-value mapping that this - * FieldArray stores. - */ - FieldData dataAt(int index) { - if (mGarbage) { - gc(); - } - - return mData[index]; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof FieldArray)) { - return false; - } - - FieldArray other = (FieldArray) o; - if (size() != other.size()) { // size() will call gc() if necessary. - return false; - } - return arrayEquals(mFieldNumbers, other.mFieldNumbers, mSize) && - arrayEquals(mData, other.mData, mSize); - } - - @Override - public int hashCode() { - if (mGarbage) { - gc(); - } - int result = 17; - for (int i = 0; i < mSize; i++) { - result = 31 * result + mFieldNumbers[i]; - result = 31 * result + mData[i].hashCode(); - } - return result; - } - - private int idealIntArraySize(int need) { - return idealByteArraySize(need * 4) / 4; - } - - private int idealByteArraySize(int need) { - for (int i = 4; i < 32; i++) - if (need <= (1 << i) - 12) - return (1 << i) - 12; - - return need; - } - - private int binarySearch(int value) { - int lo = 0; - int hi = mSize - 1; - - while (lo <= hi) { - int mid = (lo + hi) >>> 1; - int midVal = mFieldNumbers[mid]; - - if (midVal < value) { - lo = mid + 1; - } else if (midVal > value) { - hi = mid - 1; - } else { - return mid; // value found - } - } - return ~lo; // value not present - } - - private boolean arrayEquals(int[] a, int[] b, int size) { - for (int i = 0; i < size; i++) { - if (a[i] != b[i]) { - return false; - } - } - return true; - } - - private boolean arrayEquals(FieldData[] a, FieldData[] b, int size) { - for (int i = 0; i < size; i++) { - if (!a[i].equals(b[i])) { - return false; - } - } - return true; - } - - @Override - public final FieldArray clone() { - // Trigger GC so we compact and don't copy DELETED elements. - int size = size(); - FieldArray clone = new FieldArray(size); - System.arraycopy(mFieldNumbers, 0, clone.mFieldNumbers, 0, size); - for (int i = 0; i < size; i++) { - if (mData[i] != null) { - clone.mData[i] = mData[i].clone(); - } - } - clone.mSize = size; - return clone; - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/FieldData.java b/javanano/src/main/java/com/google/protobuf/nano/FieldData.java deleted file mode 100644 index ebebabc8e5c19..0000000000000 --- a/javanano/src/main/java/com/google/protobuf/nano/FieldData.java +++ /dev/null @@ -1,240 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2014 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf.nano; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Stores unknown fields. These might be extensions or fields that the generated API doesn't - * know about yet. - */ -class FieldData implements Cloneable { - private Extension cachedExtension; - private Object value; - /** The serialised values for this object. Will be cleared if getValue is called */ - private List unknownFieldData; - - FieldData(Extension extension, T newValue) { - cachedExtension = extension; - value = newValue; - } - - FieldData() { - unknownFieldData = new ArrayList(); - } - - void addUnknownField(UnknownFieldData unknownField) { - unknownFieldData.add(unknownField); - } - - UnknownFieldData getUnknownField(int index) { - if (unknownFieldData == null) { - return null; - } - if (index < unknownFieldData.size()) { - return unknownFieldData.get(index); - } - return null; - } - - int getUnknownFieldSize() { - if (unknownFieldData == null) { - return 0; - } - return unknownFieldData.size(); - } - - T getValue(Extension extension) { - if (value != null){ - if (cachedExtension != extension) { // Extension objects are singletons. - throw new IllegalStateException( - "Tried to getExtension with a differernt Extension."); - } - } else { - cachedExtension = extension; - value = extension.getValueFrom(unknownFieldData); - unknownFieldData = null; - } - return (T) value; - } - - void setValue(Extension extension, T newValue) { - cachedExtension = extension; - value = newValue; - unknownFieldData = null; - } - - int computeSerializedSize() { - int size = 0; - if (value != null) { - size = cachedExtension.computeSerializedSize(value); - } else { - for (UnknownFieldData unknownField : unknownFieldData) { - size += unknownField.computeSerializedSize(); - } - } - return size; - } - - void writeTo(CodedOutputByteBufferNano output) throws IOException { - if (value != null) { - cachedExtension.writeTo(value, output); - } else { - for (UnknownFieldData unknownField : unknownFieldData) { - unknownField.writeTo(output); - } - } - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof FieldData)) { - return false; - } - - FieldData other = (FieldData) o; - if (value != null && other.value != null) { - // If both objects have deserialized values, compare those. - // Since unknown fields are only compared if messages have generated equals methods - // we know this will be a meaningful comparison (not identity) for all values. - if (cachedExtension != other.cachedExtension) { // Extension objects are singletons. - return false; - } - if (!cachedExtension.clazz.isArray()) { - // Can't test (!cachedExtension.repeated) due to 'bytes' -> 'byte[]' - return value.equals(other.value); - } - if (value instanceof byte[]) { - return Arrays.equals((byte[]) value, (byte[]) other.value); - } else if (value instanceof int[]) { - return Arrays.equals((int[]) value, (int[]) other.value); - } else if (value instanceof long[]) { - return Arrays.equals((long[]) value, (long[]) other.value); - } else if (value instanceof float[]) { - return Arrays.equals((float[]) value, (float[]) other.value); - } else if (value instanceof double[]) { - return Arrays.equals((double[]) value, (double[]) other.value); - } else if (value instanceof boolean[]) { - return Arrays.equals((boolean[]) value, (boolean[]) other.value); - } else { - return Arrays.deepEquals((Object[]) value, (Object[]) other.value); - } - } - if (unknownFieldData != null && other.unknownFieldData != null) { - // If both objects have byte arrays compare those directly. - return unknownFieldData.equals(other.unknownFieldData); - } - try { - // As a last resort, serialize and compare the resulting byte arrays. - return Arrays.equals(toByteArray(), other.toByteArray()); - } catch (IOException e) { - // Should not happen. - throw new IllegalStateException(e); - } - } - - @Override - public int hashCode() { - int result = 17; - try { - // The only way to generate a consistent hash is to use the serialized form. - result = 31 * result + Arrays.hashCode(toByteArray()); - } catch (IOException e) { - // Should not happen. - throw new IllegalStateException(e); - } - return result; - } - - private byte[] toByteArray() throws IOException { - byte[] result = new byte[computeSerializedSize()]; - CodedOutputByteBufferNano output = CodedOutputByteBufferNano.newInstance(result); - writeTo(output); - return result; - } - - @Override - public final FieldData clone() { - FieldData clone = new FieldData(); - try { - clone.cachedExtension = cachedExtension; - if (unknownFieldData == null) { - clone.unknownFieldData = null; - } else { - clone.unknownFieldData.addAll(unknownFieldData); - } - - // Whether we need to deep clone value depends on its type. Primitive reference types - // (e.g. Integer, Long etc.) are ok, since they're immutable. We need to clone arrays - // and messages. - if (value == null) { - // No cloning required. - } else if (value instanceof MessageNano) { - clone.value = ((MessageNano) value).clone(); - } else if (value instanceof byte[]) { - clone.value = ((byte[]) value).clone(); - } else if (value instanceof byte[][]) { - byte[][] valueArray = (byte[][]) value; - byte[][] cloneArray = new byte[valueArray.length][]; - clone.value = cloneArray; - for (int i = 0; i < valueArray.length; i++) { - cloneArray[i] = valueArray[i].clone(); - } - } else if (value instanceof boolean[]) { - clone.value = ((boolean[]) value).clone(); - } else if (value instanceof int[]) { - clone.value = ((int[]) value).clone(); - } else if (value instanceof long[]) { - clone.value = ((long[]) value).clone(); - } else if (value instanceof float[]) { - clone.value = ((float[]) value).clone(); - } else if (value instanceof double[]) { - clone.value = ((double[]) value).clone(); - } else if (value instanceof MessageNano[]) { - MessageNano[] valueArray = (MessageNano[]) value; - MessageNano[] cloneArray = new MessageNano[valueArray.length]; - clone.value = cloneArray; - for (int i = 0; i < valueArray.length; i++) { - cloneArray[i] = valueArray[i].clone(); - } - } - return clone; - } catch (CloneNotSupportedException e) { - throw new AssertionError(e); - } - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java deleted file mode 100644 index 278368a08b2d5..0000000000000 --- a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java +++ /dev/null @@ -1,547 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf.nano; - -import com.google.protobuf.nano.MapFactories.MapFactory; - -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.Arrays; -import java.util.Map; -import java.util.Map.Entry; - -/** - * The classes contained within are used internally by the Protocol Buffer - * library and generated message implementations. They are public only because - * those generated messages do not reside in the {@code protobuf} package. - * Others should not use this class directly. - * - * @author kenton@google.com (Kenton Varda) - */ -public final class InternalNano { - - public static final int TYPE_DOUBLE = 1; - public static final int TYPE_FLOAT = 2; - public static final int TYPE_INT64 = 3; - public static final int TYPE_UINT64 = 4; - public static final int TYPE_INT32 = 5; - public static final int TYPE_FIXED64 = 6; - public static final int TYPE_FIXED32 = 7; - public static final int TYPE_BOOL = 8; - public static final int TYPE_STRING = 9; - public static final int TYPE_GROUP = 10; - public static final int TYPE_MESSAGE = 11; - public static final int TYPE_BYTES = 12; - public static final int TYPE_UINT32 = 13; - public static final int TYPE_ENUM = 14; - public static final int TYPE_SFIXED32 = 15; - public static final int TYPE_SFIXED64 = 16; - public static final int TYPE_SINT32 = 17; - public static final int TYPE_SINT64 = 18; - - static final Charset UTF_8 = Charset.forName("UTF-8"); - static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); - - private InternalNano() {} - - /** - * An object to provide synchronization when lazily initializing static fields - * of {@link MessageNano} subclasses. - *

- * To enable earlier versions of ProGuard to inline short methods from a - * generated MessageNano subclass to the call sites, that class must not have - * a class initializer, which will be created if there is any static variable - * initializers. To lazily initialize the static variables in a thread-safe - * manner, the initialization code will synchronize on this object. - */ - public static final Object LAZY_INIT_LOCK = new Object(); - - /** - * Helper called by generated code to construct default values for string - * fields. - *

- * The protocol compiler does not actually contain a UTF-8 decoder -- it - * just pushes UTF-8-encoded text around without touching it. The one place - * where this presents a problem is when generating Java string literals. - * Unicode characters in the string literal would normally need to be encoded - * using a Unicode escape sequence, which would require decoding them. - * To get around this, protoc instead embeds the UTF-8 bytes into the - * generated code and leaves it to the runtime library to decode them. - *

- * It gets worse, though. If protoc just generated a byte array, like: - * new byte[] {0x12, 0x34, 0x56, 0x78} - * Java actually generates *code* which allocates an array and then fills - * in each value. This is much less efficient than just embedding the bytes - * directly into the bytecode. To get around this, we need another - * work-around. String literals are embedded directly, so protoc actually - * generates a string literal corresponding to the bytes. The easiest way - * to do this is to use the ISO-8859-1 character set, which corresponds to - * the first 256 characters of the Unicode range. Protoc can then use - * good old CEscape to generate the string. - *

- * So we have a string literal which represents a set of bytes which - * represents another string. This function -- stringDefaultValue -- - * converts from the generated string to the string we actually want. The - * generated code calls this automatically. - */ - public static String stringDefaultValue(String bytes) { - return new String(bytes.getBytes(ISO_8859_1), InternalNano.UTF_8); - } - - /** - * Helper called by generated code to construct default values for bytes - * fields. - *

- * This is a lot like {@link #stringDefaultValue}, but for bytes fields. - * In this case we only need the second of the two hacks -- allowing us to - * embed raw bytes as a string literal with ISO-8859-1 encoding. - */ - public static byte[] bytesDefaultValue(String bytes) { - return bytes.getBytes(ISO_8859_1); - } - - /** - * Helper function to convert a string into UTF-8 while turning the - * UnsupportedEncodingException to a RuntimeException. - */ - public static byte[] copyFromUtf8(final String text) { - return text.getBytes(InternalNano.UTF_8); - } - - /** - * Checks repeated int field equality; null-value and 0-length fields are - * considered equal. - */ - public static boolean equals(int[] field1, int[] field2) { - if (field1 == null || field1.length == 0) { - return field2 == null || field2.length == 0; - } else { - return Arrays.equals(field1, field2); - } - } - - /** - * Checks repeated long field equality; null-value and 0-length fields are - * considered equal. - */ - public static boolean equals(long[] field1, long[] field2) { - if (field1 == null || field1.length == 0) { - return field2 == null || field2.length == 0; - } else { - return Arrays.equals(field1, field2); - } - } - - /** - * Checks repeated float field equality; null-value and 0-length fields are - * considered equal. - */ - public static boolean equals(float[] field1, float[] field2) { - if (field1 == null || field1.length == 0) { - return field2 == null || field2.length == 0; - } else { - return Arrays.equals(field1, field2); - } - } - - /** - * Checks repeated double field equality; null-value and 0-length fields are - * considered equal. - */ - public static boolean equals(double[] field1, double[] field2) { - if (field1 == null || field1.length == 0) { - return field2 == null || field2.length == 0; - } else { - return Arrays.equals(field1, field2); - } - } - - /** - * Checks repeated boolean field equality; null-value and 0-length fields are - * considered equal. - */ - public static boolean equals(boolean[] field1, boolean[] field2) { - if (field1 == null || field1.length == 0) { - return field2 == null || field2.length == 0; - } else { - return Arrays.equals(field1, field2); - } - } - - /** - * Checks repeated bytes field equality. Only non-null elements are tested. - * Returns true if the two fields have the same sequence of non-null - * elements. Null-value fields and fields of any length with only null - * elements are considered equal. - */ - public static boolean equals(byte[][] field1, byte[][] field2) { - int index1 = 0; - int length1 = field1 == null ? 0 : field1.length; - int index2 = 0; - int length2 = field2 == null ? 0 : field2.length; - while (true) { - while (index1 < length1 && field1[index1] == null) { - index1++; - } - while (index2 < length2 && field2[index2] == null) { - index2++; - } - boolean atEndOf1 = index1 >= length1; - boolean atEndOf2 = index2 >= length2; - if (atEndOf1 && atEndOf2) { - // no more non-null elements to test in both arrays - return true; - } else if (atEndOf1 != atEndOf2) { - // one of the arrays have extra non-null elements - return false; - } else if (!Arrays.equals(field1[index1], field2[index2])) { - // element mismatch - return false; - } - index1++; - index2++; - } - } - - /** - * Checks repeated string/message field equality. Only non-null elements are - * tested. Returns true if the two fields have the same sequence of non-null - * elements. Null-value fields and fields of any length with only null - * elements are considered equal. - */ - public static boolean equals(Object[] field1, Object[] field2) { - int index1 = 0; - int length1 = field1 == null ? 0 : field1.length; - int index2 = 0; - int length2 = field2 == null ? 0 : field2.length; - while (true) { - while (index1 < length1 && field1[index1] == null) { - index1++; - } - while (index2 < length2 && field2[index2] == null) { - index2++; - } - boolean atEndOf1 = index1 >= length1; - boolean atEndOf2 = index2 >= length2; - if (atEndOf1 && atEndOf2) { - // no more non-null elements to test in both arrays - return true; - } else if (atEndOf1 != atEndOf2) { - // one of the arrays have extra non-null elements - return false; - } else if (!field1[index1].equals(field2[index2])) { - // element mismatch - return false; - } - index1++; - index2++; - } - } - - /** - * Computes the hash code of a repeated int field. Null-value and 0-length - * fields have the same hash code. - */ - public static int hashCode(int[] field) { - return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); - } - - /** - * Computes the hash code of a repeated long field. Null-value and 0-length - * fields have the same hash code. - */ - public static int hashCode(long[] field) { - return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); - } - - /** - * Computes the hash code of a repeated float field. Null-value and 0-length - * fields have the same hash code. - */ - public static int hashCode(float[] field) { - return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); - } - - /** - * Computes the hash code of a repeated double field. Null-value and 0-length - * fields have the same hash code. - */ - public static int hashCode(double[] field) { - return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); - } - - /** - * Computes the hash code of a repeated boolean field. Null-value and 0-length - * fields have the same hash code. - */ - public static int hashCode(boolean[] field) { - return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); - } - - /** - * Computes the hash code of a repeated bytes field. Only the sequence of all - * non-null elements are used in the computation. Null-value fields and fields - * of any length with only null elements have the same hash code. - */ - public static int hashCode(byte[][] field) { - int result = 0; - for (int i = 0, size = field == null ? 0 : field.length; i < size; i++) { - byte[] element = field[i]; - if (element != null) { - result = 31 * result + Arrays.hashCode(element); - } - } - return result; - } - - /** - * Computes the hash code of a repeated string/message field. Only the - * sequence of all non-null elements are used in the computation. Null-value - * fields and fields of any length with only null elements have the same hash - * code. - */ - public static int hashCode(Object[] field) { - int result = 0; - for (int i = 0, size = field == null ? 0 : field.length; i < size; i++) { - Object element = field[i]; - if (element != null) { - result = 31 * result + element.hashCode(); - } - } - return result; - } - private static Object primitiveDefaultValue(int type) { - switch (type) { - case TYPE_BOOL: - return Boolean.FALSE; - case TYPE_BYTES: - return WireFormatNano.EMPTY_BYTES; - case TYPE_STRING: - return ""; - case TYPE_FLOAT: - return Float.valueOf(0); - case TYPE_DOUBLE: - return Double.valueOf(0); - case TYPE_ENUM: - case TYPE_FIXED32: - case TYPE_INT32: - case TYPE_UINT32: - case TYPE_SINT32: - case TYPE_SFIXED32: - return Integer.valueOf(0); - case TYPE_INT64: - case TYPE_UINT64: - case TYPE_SINT64: - case TYPE_FIXED64: - case TYPE_SFIXED64: - return Long.valueOf(0L); - case TYPE_MESSAGE: - case TYPE_GROUP: - default: - throw new IllegalArgumentException( - "Type: " + type + " is not a primitive type."); - } - } - - /** - * Merges the map entry into the map field. Note this is only supposed to - * be called by generated messages. - * - * @param map the map field; may be null, in which case a map will be - * instantiated using the {@link MapFactories.MapFactory} - * @param input the input byte buffer - * @param keyType key type, as defined in InternalNano.TYPE_* - * @param valueType value type, as defined in InternalNano.TYPE_* - * @param value an new instance of the value, if the value is a TYPE_MESSAGE; - * otherwise this parameter can be null and will be ignored. - * @param keyTag wire tag for the key - * @param valueTag wire tag for the value - * @return the map field - * @throws IOException - */ - @SuppressWarnings("unchecked") - public static final Map mergeMapEntry( - CodedInputByteBufferNano input, - Map map, - MapFactory mapFactory, - int keyType, - int valueType, - V value, - int keyTag, - int valueTag) throws IOException { - map = mapFactory.forMap(map); - final int length = input.readRawVarint32(); - final int oldLimit = input.pushLimit(length); - K key = null; - while (true) { - int tag = input.readTag(); - if (tag == 0) { - break; - } - if (tag == keyTag) { - key = (K) input.readPrimitiveField(keyType); - } else if (tag == valueTag) { - if (valueType == TYPE_MESSAGE) { - input.readMessage((MessageNano) value); - } else { - value = (V) input.readPrimitiveField(valueType); - } - } else { - if (!input.skipField(tag)) { - break; - } - } - } - input.checkLastTagWas(0); - input.popLimit(oldLimit); - - if (key == null) { - // key can only be primitive types. - key = (K) primitiveDefaultValue(keyType); - } - - if (value == null) { - // message type value will be initialized by code-gen. - value = (V) primitiveDefaultValue(valueType); - } - - map.put(key, value); - return map; - } - - public static void serializeMapField( - CodedOutputByteBufferNano output, - Map map, int number, int keyType, int valueType) - throws IOException { - for (Entry entry: map.entrySet()) { - K key = entry.getKey(); - V value = entry.getValue(); - if (key == null || value == null) { - throw new IllegalStateException( - "keys and values in maps cannot be null"); - } - int entrySize = - CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) + - CodedOutputByteBufferNano.computeFieldSize(2, valueType, value); - output.writeTag(number, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); - output.writeRawVarint32(entrySize); - output.writeField(1, keyType, key); - output.writeField(2, valueType, value); - } - } - - public static int computeMapFieldSize( - Map map, int number, int keyType, int valueType) { - int size = 0; - int tagSize = CodedOutputByteBufferNano.computeTagSize(number); - for (Entry entry: map.entrySet()) { - K key = entry.getKey(); - V value = entry.getValue(); - if (key == null || value == null) { - throw new IllegalStateException( - "keys and values in maps cannot be null"); - } - int entrySize = - CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) + - CodedOutputByteBufferNano.computeFieldSize(2, valueType, value); - size += tagSize + entrySize - + CodedOutputByteBufferNano.computeRawVarint32Size(entrySize); - } - return size; - } - - /** - * Checks whether two {@link Map} are equal. We don't use the default equals - * method of {@link Map} because it compares by identity not by content for - * byte arrays. - */ - public static boolean equals(Map a, Map b) { - if (a == b) { - return true; - } - if (a == null) { - return b.size() == 0; - } - if (b == null) { - return a.size() == 0; - } - if (a.size() != b.size()) { - return false; - } - for (Entry entry : a.entrySet()) { - if (!b.containsKey(entry.getKey())) { - return false; - } - if (!equalsMapValue(entry.getValue(), b.get(entry.getKey()))) { - return false; - } - } - return true; - } - - private static boolean equalsMapValue(Object a, Object b) { - if (a == null || b == null) { - throw new IllegalStateException( - "keys and values in maps cannot be null"); - } - if (a instanceof byte[] && b instanceof byte[]) { - return Arrays.equals((byte[]) a, (byte[]) b); - } - return a.equals(b); - } - - public static int hashCode(Map map) { - if (map == null) { - return 0; - } - int result = 0; - for (Entry entry : map.entrySet()) { - result += hashCodeForMap(entry.getKey()) - ^ hashCodeForMap(entry.getValue()); - } - return result; - } - - private static int hashCodeForMap(Object o) { - if (o instanceof byte[]) { - return Arrays.hashCode((byte[]) o); - } - return o.hashCode(); - } - - // This avoids having to make FieldArray public. - public static void cloneUnknownFieldData(ExtendableMessageNano original, - ExtendableMessageNano cloned) { - if (original.unknownFieldData != null) { - cloned.unknownFieldData = (FieldArray) original.unknownFieldData.clone(); - } - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java b/javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java deleted file mode 100644 index 9a83d6d37c110..0000000000000 --- a/javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java +++ /dev/null @@ -1,93 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 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.nano; - -import java.io.IOException; - -/** - * Thrown when a protocol message being parsed is invalid in some way, - * e.g. it contains a malformed varint or a negative byte length. - * - * @author kenton@google.com Kenton Varda - */ -public class InvalidProtocolBufferNanoException extends IOException { - private static final long serialVersionUID = -1616151763072450476L; - - public InvalidProtocolBufferNanoException(final String description) { - super(description); - } - - static InvalidProtocolBufferNanoException truncatedMessage() { - return new InvalidProtocolBufferNanoException( - "While parsing a protocol message, the input ended unexpectedly " + - "in the middle of a field. This could mean either that the " + - "input has been truncated or that an embedded message " + - "misreported its own length."); - } - - static InvalidProtocolBufferNanoException negativeSize() { - return new InvalidProtocolBufferNanoException( - "CodedInputStream encountered an embedded string or message " + - "which claimed to have negative size."); - } - - static InvalidProtocolBufferNanoException malformedVarint() { - return new InvalidProtocolBufferNanoException( - "CodedInputStream encountered a malformed varint."); - } - - static InvalidProtocolBufferNanoException invalidTag() { - return new InvalidProtocolBufferNanoException( - "Protocol message contained an invalid tag (zero)."); - } - - static InvalidProtocolBufferNanoException invalidEndTag() { - return new InvalidProtocolBufferNanoException( - "Protocol message end-group tag did not match expected tag."); - } - - static InvalidProtocolBufferNanoException invalidWireType() { - return new InvalidProtocolBufferNanoException( - "Protocol message tag had invalid wire type."); - } - - static InvalidProtocolBufferNanoException recursionLimitExceeded() { - return new InvalidProtocolBufferNanoException( - "Protocol message had too many levels of nesting. May be malicious. " + - "Use CodedInputStream.setRecursionLimit() to increase the depth limit."); - } - - static InvalidProtocolBufferNanoException sizeLimitExceeded() { - return new InvalidProtocolBufferNanoException( - "Protocol message was too large. May be malicious. " + - "Use CodedInputStream.setSizeLimit() to increase the size limit."); - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java b/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java deleted file mode 100644 index 98fa4877bc404..0000000000000 --- a/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java +++ /dev/null @@ -1,67 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 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.nano; - -import java.util.HashMap; -import java.util.Map; - -/** - * Utility class for maps support. - */ -public final class MapFactories { - public static interface MapFactory { - Map forMap(Map oldMap); - } - - // NOTE(liujisi): The factory setter is temporarily marked as package private. - // The way to provide customized implementations of maps for different - // platforms are still under discussion. Mark it as private to avoid exposing - // the API in proto3 alpha release. - /* public */ static void setMapFactory(MapFactory newMapFactory) { - mapFactory = newMapFactory; - } - - public static MapFactory getMapFactory() { - return mapFactory; - } - - private static class DefaultMapFactory implements MapFactory { - public Map forMap(Map oldMap) { - if (oldMap == null) { - return new HashMap(); - } - return oldMap; - } - } - private static volatile MapFactory mapFactory = new DefaultMapFactory(); - - private MapFactories() {} -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java b/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java deleted file mode 100644 index 2347502702d06..0000000000000 --- a/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java +++ /dev/null @@ -1,198 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 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.nano; - -import java.io.IOException; -import java.util.Arrays; - -/** - * Abstract interface implemented by Protocol Message objects. - * - * @author wink@google.com Wink Saville - */ -public abstract class MessageNano { - protected volatile int cachedSize = -1; - - /** - * Get the number of bytes required to encode this message. - * Returns the cached size or calls getSerializedSize which - * sets the cached size. This is used internally when serializing - * so the size is only computed once. If a member is modified - * then this could be stale call getSerializedSize if in doubt. - */ - public int getCachedSize() { - if (cachedSize < 0) { - // getSerializedSize sets cachedSize - getSerializedSize(); - } - return cachedSize; - } - - /** - * Computes the number of bytes required to encode this message. - * The size is cached and the cached result can be retrieved - * using getCachedSize(). - */ - public int getSerializedSize() { - int size = computeSerializedSize(); - cachedSize = size; - return size; - } - - /** - * Computes the number of bytes required to encode this message. This does not update the - * cached size. - */ - protected int computeSerializedSize() { - // This is overridden if the generated message has serialized fields. - return 0; - } - - /** - * Serializes the message and writes it to {@code output}. - * - * @param output the output to receive the serialized form. - * @throws IOException if an error occurred writing to {@code output}. - */ - public void writeTo(CodedOutputByteBufferNano output) throws IOException { - // Does nothing by default. Overridden by subclasses which have data to write. - } - - /** - * Parse {@code input} as a message of this type and merge it with the - * message being built. - */ - public abstract MessageNano mergeFrom(CodedInputByteBufferNano input) throws IOException; - - /** - * Serialize to a byte array. - * @return byte array with the serialized data. - */ - public static final byte[] toByteArray(MessageNano msg) { - final byte[] result = new byte[msg.getSerializedSize()]; - toByteArray(msg, result, 0, result.length); - return result; - } - - /** - * Serialize to a byte array starting at offset through length. The - * method getSerializedSize must have been called prior to calling - * this method so the proper length is know. If an attempt to - * write more than length bytes OutOfSpaceException will be thrown - * and if length bytes are not written then IllegalStateException - * is thrown. - */ - public static final void toByteArray(MessageNano msg, byte[] data, int offset, int length) { - try { - final CodedOutputByteBufferNano output = - CodedOutputByteBufferNano.newInstance(data, offset, length); - msg.writeTo(output); - output.checkNoSpaceLeft(); - } catch (IOException e) { - throw new RuntimeException("Serializing to a byte array threw an IOException " - + "(should never happen).", e); - } - } - - /** - * Parse {@code data} as a message of this type and merge it with the - * message being built. - */ - public static final T mergeFrom(T msg, final byte[] data) - throws InvalidProtocolBufferNanoException { - return mergeFrom(msg, data, 0, data.length); - } - - /** - * Parse {@code data} as a message of this type and merge it with the - * message being built. - */ - public static final T mergeFrom(T msg, final byte[] data, - final int off, final int len) throws InvalidProtocolBufferNanoException { - try { - final CodedInputByteBufferNano input = - CodedInputByteBufferNano.newInstance(data, off, len); - msg.mergeFrom(input); - input.checkLastTagWas(0); - return msg; - } catch (InvalidProtocolBufferNanoException e) { - throw e; - } catch (IOException e) { - throw new RuntimeException("Reading from a byte array threw an IOException (should " - + "never happen)."); - } - } - - /** - * Compares two {@code MessageNano}s and returns true if the message's are the same class and - * have serialized form equality (i.e. all of the field values are the same). - */ - public static final boolean messageNanoEquals(MessageNano a, MessageNano b) { - if (a == b) { - return true; - } - if (a == null || b == null) { - return false; - } - if (a.getClass() != b.getClass()) { - return false; - } - final int serializedSize = a.getSerializedSize(); - if (b.getSerializedSize() != serializedSize) { - return false; - } - final byte[] aByteArray = new byte[serializedSize]; - final byte[] bByteArray = new byte[serializedSize]; - toByteArray(a, aByteArray, 0, serializedSize); - toByteArray(b, bByteArray, 0, serializedSize); - return Arrays.equals(aByteArray, bByteArray); - } - - /** - * Returns a string that is (mostly) compatible with ProtoBuffer's TextFormat. Note that groups - * (which are deprecated) are not serialized with the correct field name. - * - *

This is implemented using reflection, so it is not especially fast nor is it guaranteed - * to find all fields if you have method removal turned on for proguard. - */ - @Override - public String toString() { - return MessageNanoPrinter.print(this); - } - - /** - * Provides support for cloning. This only works if you specify the generate_clone method. - */ - @Override - public MessageNano clone() throws CloneNotSupportedException { - return (MessageNano) super.clone(); - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java b/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java deleted file mode 100644 index 5f329f02fbfc6..0000000000000 --- a/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java +++ /dev/null @@ -1,275 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 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.nano; - -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Map; - -/** - * Static helper methods for printing nano protos. - * - * @author flynn@google.com Andrew Flynn - */ -public final class MessageNanoPrinter { - // Do not allow instantiation - private MessageNanoPrinter() {} - - private static final String INDENT = " "; - private static final int MAX_STRING_LEN = 200; - - /** - * Returns an text representation of a MessageNano suitable for debugging. The returned string - * is mostly compatible with Protocol Buffer's TextFormat (as provided by non-nano protocol - * buffers) -- groups (which are deprecated) are output with an underscore name (e.g. foo_bar - * instead of FooBar) and will thus not parse. - * - *

Employs Java reflection on the given object and recursively prints primitive fields, - * groups, and messages.

- */ - public static String print(T message) { - if (message == null) { - return ""; - } - - StringBuffer buf = new StringBuffer(); - try { - print(null, message, new StringBuffer(), buf); - } catch (IllegalAccessException e) { - return "Error printing proto: " + e.getMessage(); - } catch (InvocationTargetException e) { - return "Error printing proto: " + e.getMessage(); - } - return buf.toString(); - } - - /** - * Function that will print the given message/field into the StringBuffer. - * Meant to be called recursively. - * - * @param identifier the identifier to use, or {@code null} if this is the root message to - * print. - * @param object the value to print. May in fact be a primitive value or byte array and not a - * message. - * @param indentBuf the indentation each line should begin with. - * @param buf the output buffer. - */ - private static void print(String identifier, Object object, - StringBuffer indentBuf, StringBuffer buf) throws IllegalAccessException, - InvocationTargetException { - if (object == null) { - // This can happen if... - // - we're about to print a message, String, or byte[], but it not present; - // - we're about to print a primitive, but "reftype" optional style is enabled, and - // the field is unset. - // In both cases the appropriate behavior is to output nothing. - } else if (object instanceof MessageNano) { // Nano proto message - int origIndentBufLength = indentBuf.length(); - if (identifier != null) { - buf.append(indentBuf).append(deCamelCaseify(identifier)).append(" <\n"); - indentBuf.append(INDENT); - } - Class clazz = object.getClass(); - - // Proto fields follow one of two formats: - // - // 1) Public, non-static variables that do not begin or end with '_' - // Find and print these using declared public fields - for (Field field : clazz.getFields()) { - int modifiers = field.getModifiers(); - String fieldName = field.getName(); - if ("cachedSize".equals(fieldName)) { - // TODO(bduff): perhaps cachedSize should have a more obscure name. - continue; - } - - if ((modifiers & Modifier.PUBLIC) == Modifier.PUBLIC - && (modifiers & Modifier.STATIC) != Modifier.STATIC - && !fieldName.startsWith("_") - && !fieldName.endsWith("_")) { - Class fieldType = field.getType(); - Object value = field.get(object); - - if (fieldType.isArray()) { - Class arrayType = fieldType.getComponentType(); - - // bytes is special since it's not repeated, but is represented by an array - if (arrayType == byte.class) { - print(fieldName, value, indentBuf, buf); - } else { - int len = value == null ? 0 : Array.getLength(value); - for (int i = 0; i < len; i++) { - Object elem = Array.get(value, i); - print(fieldName, elem, indentBuf, buf); - } - } - } else { - print(fieldName, value, indentBuf, buf); - } - } - } - - // 2) Fields that are accessed via getter methods (when accessors - // mode is turned on) - // Find and print these using getter methods. - for (Method method : clazz.getMethods()) { - String name = method.getName(); - // Check for the setter accessor method since getters and hazzers both have - // non-proto-field name collisions (hashCode() and getSerializedSize()) - if (name.startsWith("set")) { - String subfieldName = name.substring(3); - - Method hazzer = null; - try { - hazzer = clazz.getMethod("has" + subfieldName); - } catch (NoSuchMethodException e) { - continue; - } - // If hazzer doesn't exist or returns false, no need to continue - if (!(Boolean) hazzer.invoke(object)) { - continue; - } - - Method getter = null; - try { - getter = clazz.getMethod("get" + subfieldName); - } catch (NoSuchMethodException e) { - continue; - } - - print(subfieldName, getter.invoke(object), indentBuf, buf); - } - } - if (identifier != null) { - indentBuf.setLength(origIndentBufLength); - buf.append(indentBuf).append(">\n"); - } - } else if (object instanceof Map) { - Map map = (Map) object; - identifier = deCamelCaseify(identifier); - - for (Map.Entry entry : map.entrySet()) { - buf.append(indentBuf).append(identifier).append(" <\n"); - int origIndentBufLength = indentBuf.length(); - indentBuf.append(INDENT); - print("key", entry.getKey(), indentBuf, buf); - print("value", entry.getValue(), indentBuf, buf); - indentBuf.setLength(origIndentBufLength); - buf.append(indentBuf).append(">\n"); - } - } else { - // Non-null primitive value - identifier = deCamelCaseify(identifier); - buf.append(indentBuf).append(identifier).append(": "); - if (object instanceof String) { - String stringMessage = sanitizeString((String) object); - buf.append("\"").append(stringMessage).append("\""); - } else if (object instanceof byte[]) { - appendQuotedBytes((byte[]) object, buf); - } else { - buf.append(object); - } - buf.append("\n"); - } - } - - /** - * Converts an identifier of the format "FieldName" into "field_name". - */ - private static String deCamelCaseify(String identifier) { - StringBuffer out = new StringBuffer(); - for (int i = 0; i < identifier.length(); i++) { - char currentChar = identifier.charAt(i); - if (i == 0) { - out.append(Character.toLowerCase(currentChar)); - } else if (Character.isUpperCase(currentChar)) { - out.append('_').append(Character.toLowerCase(currentChar)); - } else { - out.append(currentChar); - } - } - return out.toString(); - } - - /** - * Shortens and escapes the given string. - */ - private static String sanitizeString(String str) { - if (!str.startsWith("http") && str.length() > MAX_STRING_LEN) { - // Trim non-URL strings. - str = str.substring(0, MAX_STRING_LEN) + "[...]"; - } - return escapeString(str); - } - - /** - * Escape everything except for low ASCII code points. - */ - private static String escapeString(String str) { - int strLen = str.length(); - StringBuilder b = new StringBuilder(strLen); - for (int i = 0; i < strLen; i++) { - char original = str.charAt(i); - if (original >= ' ' && original <= '~' && original != '"' && original != '\'') { - b.append(original); - } else { - b.append(String.format("\\u%04x", (int) original)); - } - } - return b.toString(); - } - - /** - * Appends a quoted byte array to the provided {@code StringBuffer}. - */ - private static void appendQuotedBytes(byte[] bytes, StringBuffer builder) { - if (bytes == null) { - builder.append("\"\""); - return; - } - - builder.append('"'); - for (int i = 0; i < bytes.length; ++i) { - int ch = bytes[i] & 0xff; - if (ch == '\\' || ch == '"') { - builder.append('\\').append((char) ch); - } else if (ch >= 32 && ch < 127) { - builder.append((char) ch); - } else { - builder.append(String.format("\\%03o", ch)); - } - } - builder.append('"'); - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java b/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java deleted file mode 100644 index b1678d1b93a0b..0000000000000 --- a/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java +++ /dev/null @@ -1,88 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 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.nano; - -import java.io.IOException; -import java.util.Arrays; - -/** - * Stores unknown fields. These might be extensions or fields that the generated - * API doesn't know about yet. - * - * @author bduff@google.com (Brian Duff) - */ -final class UnknownFieldData { - - final int tag; - /** - * Important: this should be treated as immutable, even though it's possible - * to change the array values. - */ - final byte[] bytes; - - UnknownFieldData(int tag, byte[] bytes) { - this.tag = tag; - this.bytes = bytes; - } - - int computeSerializedSize() { - int size = 0; - size += CodedOutputByteBufferNano.computeRawVarint32Size(tag); - size += bytes.length; - return size; - } - - void writeTo(CodedOutputByteBufferNano output) throws IOException { - output.writeRawVarint32(tag); - output.writeRawBytes(bytes); - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof UnknownFieldData)) { - return false; - } - - UnknownFieldData other = (UnknownFieldData) o; - return tag == other.tag && Arrays.equals(bytes, other.bytes); - } - - @Override - public int hashCode() { - int result = 17; - result = 31 * result + tag; - result = 31 * result + Arrays.hashCode(bytes); - return result; - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/WireFormatNano.java b/javanano/src/main/java/com/google/protobuf/nano/WireFormatNano.java deleted file mode 100644 index bbb6370a3e605..0000000000000 --- a/javanano/src/main/java/com/google/protobuf/nano/WireFormatNano.java +++ /dev/null @@ -1,124 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 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.nano; - -import java.io.IOException; - -/** - * This class is used internally by the Protocol Buffer library and generated - * message implementations. It is public only because those generated messages - * do not reside in the {@code protobuf} package. Others should not use this - * class directly. - * - * This class contains constants and helper functions useful for dealing with - * the Protocol Buffer wire format. - * - * @author kenton@google.com Kenton Varda - */ -public final class WireFormatNano { - // Do not allow instantiation. - private WireFormatNano() {} - - static final int WIRETYPE_VARINT = 0; - static final int WIRETYPE_FIXED64 = 1; - static final int WIRETYPE_LENGTH_DELIMITED = 2; - static final int WIRETYPE_START_GROUP = 3; - static final int WIRETYPE_END_GROUP = 4; - static final int WIRETYPE_FIXED32 = 5; - - static final int TAG_TYPE_BITS = 3; - static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1; - - /** Given a tag value, determines the wire type (the lower 3 bits). */ - static int getTagWireType(final int tag) { - return tag & TAG_TYPE_MASK; - } - - /** Given a tag value, determines the field number (the upper 29 bits). */ - public static int getTagFieldNumber(final int tag) { - return tag >>> TAG_TYPE_BITS; - } - - /** Makes a tag value given a field number and wire type. */ - static int makeTag(final int fieldNumber, final int wireType) { - return (fieldNumber << TAG_TYPE_BITS) | wireType; - } - - public static final int EMPTY_INT_ARRAY[] = {}; - public static final long EMPTY_LONG_ARRAY[] = {}; - public static final float EMPTY_FLOAT_ARRAY[] = {}; - public static final double EMPTY_DOUBLE_ARRAY[] = {}; - public static final boolean EMPTY_BOOLEAN_ARRAY[] = {}; - public static final String EMPTY_STRING_ARRAY[] = {}; - public static final byte[] EMPTY_BYTES_ARRAY[] = {}; - public static final byte[] EMPTY_BYTES = {}; - - /** - * Parses an unknown field. This implementation skips the field. - * - *

Generated messages will call this for unknown fields if the store_unknown_fields - * option is off. - * - * @return {@literal true} unless the tag is an end-group tag. - */ - public static boolean parseUnknownField( - final CodedInputByteBufferNano input, - final int tag) throws IOException { - return input.skipField(tag); - } - - /** - * Computes the array length of a repeated field. We assume that in the common case repeated - * fields are contiguously serialized but we still correctly handle interspersed values of a - * repeated field (but with extra allocations). - * - * Rewinds to current input position before returning. - * - * @param input stream input, pointing to the byte after the first tag - * @param tag repeated field tag just read - * @return length of array - * @throws IOException - */ - public static final int getRepeatedFieldArrayLength( - final CodedInputByteBufferNano input, - final int tag) throws IOException { - int arrayLength = 1; - int startPos = input.getPosition(); - input.skipField(tag); - while (input.readTag() == tag) { - input.skipField(tag); - arrayLength++; - } - input.rewindToPosition(startPos); - return arrayLength; - } - -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java deleted file mode 100644 index 4d6e7f09034dd..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java +++ /dev/null @@ -1,4471 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 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.nano; - -import com.google.protobuf.nano.CodedOutputByteBufferNano; -import com.google.protobuf.nano.EnumClassNanos.EnumClassNano; -import com.google.protobuf.nano.EnumClassNanos.EnumClassNano.MessageScopeEnum; -import com.google.protobuf.nano.EnumClassNanos.FileScopeEnum; -import com.google.protobuf.nano.MapTestProto.TestMap; -import com.google.protobuf.nano.MapTestProto.TestMap.MessageValue; -import com.google.protobuf.nano.NanoAccessorsOuterClass.TestNanoAccessors; -import com.google.protobuf.nano.NanoHasOuterClass.TestAllTypesNanoHas; -import com.google.protobuf.nano.NanoOuterClass.TestAllTypesNano; -import com.google.protobuf.nano.UnittestRecursiveNano.RecursiveMessageNano; -import com.google.protobuf.nano.NanoReferenceTypesCompat; -import com.google.protobuf.nano.UnittestSimpleNano.SimpleMessageNano; -import com.google.protobuf.nano.UnittestSingleNano.SingleMessageNano; -import com.google.protobuf.nano.testext.nano.Extensions; -import com.google.protobuf.nano.testext.nano.Extensions.AnotherMessage; -import com.google.protobuf.nano.testext.nano.Extensions.MessageWithGroup; -import com.google.protobuf.nano.testimport.nano.UnittestImportNano; - -import junit.framework.TestCase; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; - -/** - * Test nano runtime. - * - * @author ulas@google.com Ulas Kirazci - */ -public class NanoTest extends TestCase { - @Override - public void setUp() throws Exception { - } - - public void testSimpleMessageNano() throws Exception { - SimpleMessageNano msg = new SimpleMessageNano(); - assertEquals(123, msg.d); - assertEquals(null, msg.nestedMsg); - assertEquals(SimpleMessageNano.BAZ, msg.defaultNestedEnum); - - msg.d = 456; - assertEquals(456, msg.d); - - SimpleMessageNano.NestedMessage nestedMsg = new SimpleMessageNano.NestedMessage(); - nestedMsg.bb = 2; - assertEquals(2, nestedMsg.bb); - msg.nestedMsg = nestedMsg; - assertEquals(2, msg.nestedMsg.bb); - - msg.defaultNestedEnum = SimpleMessageNano.BAR; - assertEquals(SimpleMessageNano.BAR, msg.defaultNestedEnum); - - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 9); - assertEquals(result.length, msgSerializedSize); - - SimpleMessageNano newMsg = SimpleMessageNano.parseFrom(result); - assertEquals(456, newMsg.d); - assertEquals(2, msg.nestedMsg.bb); - assertEquals(SimpleMessageNano.BAR, msg.defaultNestedEnum); - - msg.nestedMsg = null; - assertTrue(msgSerializedSize != msg.getSerializedSize()); - - msg.clear(); - assertEquals(0, msg.getSerializedSize()); - } - - public void testRecursiveMessageNano() throws Exception { - RecursiveMessageNano msg = new RecursiveMessageNano(); - assertTrue(msg.repeatedRecursiveMessageNano.length == 0); - - RecursiveMessageNano msg1 = new RecursiveMessageNano(); - msg1.id = 1; - assertEquals(1, msg1.id); - RecursiveMessageNano msg2 = new RecursiveMessageNano(); - msg2.id = 2; - RecursiveMessageNano msg3 = new RecursiveMessageNano(); - msg3.id = 3; - - RecursiveMessageNano.NestedMessage nestedMsg = new RecursiveMessageNano.NestedMessage(); - nestedMsg.a = msg1; - assertEquals(1, nestedMsg.a.id); - - msg.id = 0; - msg.nestedMessage = nestedMsg; - msg.optionalRecursiveMessageNano = msg2; - msg.repeatedRecursiveMessageNano = new RecursiveMessageNano[] { msg3 }; - - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 16); - assertEquals(result.length, msgSerializedSize); - - RecursiveMessageNano newMsg = RecursiveMessageNano.parseFrom(result); - assertEquals(1, newMsg.repeatedRecursiveMessageNano.length); - - assertEquals(0, newMsg.id); - assertEquals(1, newMsg.nestedMessage.a.id); - assertEquals(2, newMsg.optionalRecursiveMessageNano.id); - assertEquals(3, newMsg.repeatedRecursiveMessageNano[0].id); - } - - public void testMessageNoFields() { - SingleMessageNano msg = new SingleMessageNano(); - assertEquals(0, msg.getSerializedSize()); - assertEquals(0, MessageNano.toByteArray(msg).length); - } - - public void testNanoRequiredInt32() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.id = 123; - assertEquals(123, msg.id); - msg.clear().id = 456; - assertEquals(456, msg.id); - msg.clear(); - - msg.id = 123; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 3); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(123, newMsg.id); - } - - public void testNanoOptionalInt32() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalInt32 = 123; - assertEquals(123, msg.optionalInt32); - msg.clear() - .optionalInt32 = 456; - assertEquals(456, msg.optionalInt32); - msg.clear(); - - msg.optionalInt32 = 123; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 5); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(123, newMsg.optionalInt32); - } - - public void testNanoOptionalInt64() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalInt64 = 123; - assertEquals(123, msg.optionalInt64); - msg.clear() - .optionalInt64 = 456; - assertEquals(456, msg.optionalInt64); - msg.clear(); - assertEquals(0, msg.optionalInt64); - - msg.optionalInt64 = 123; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 5); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(123, newMsg.optionalInt64); - } - - public void testNanoOptionalUint32() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalUint32 = 123; - assertEquals(123, msg.optionalUint32); - msg.clear() - .optionalUint32 = 456; - assertEquals(456, msg.optionalUint32); - msg.clear(); - assertEquals(0, msg.optionalUint32); - - msg.optionalUint32 = 123; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 5); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(123, newMsg.optionalUint32); - } - - public void testNanoOptionalUint64() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalUint64 = 123; - assertEquals(123, msg.optionalUint64); - msg.clear() - .optionalUint64 = 456; - assertEquals(456, msg.optionalUint64); - msg.clear(); - assertEquals(0, msg.optionalUint64); - - msg.optionalUint64 = 123; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 5); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(123, newMsg.optionalUint64); - } - - public void testNanoOptionalSint32() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalSint32 = 123; - assertEquals(123, msg.optionalSint32); - msg.clear() - .optionalSint32 = 456; - assertEquals(456, msg.optionalSint32); - msg.clear(); - assertEquals(0, msg.optionalSint32); - - msg.optionalSint32 = -123; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(-123, newMsg.optionalSint32); - } - - public void testNanoOptionalSint64() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalSint64 = 123; - assertEquals(123, msg.optionalSint64); - msg.clear() - .optionalSint64 = 456; - assertEquals(456, msg.optionalSint64); - msg.clear(); - assertEquals(0, msg.optionalSint64); - - msg.optionalSint64 = -123; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(-123, newMsg.optionalSint64); - } - - public void testNanoOptionalFixed32() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalFixed32 = 123; - assertEquals(123, msg.optionalFixed32); - msg.clear() - .optionalFixed32 = 456; - assertEquals(456, msg.optionalFixed32); - msg.clear(); - assertEquals(0, msg.optionalFixed32); - - msg.optionalFixed32 = 123; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 8); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(123, newMsg.optionalFixed32); - } - - public void testNanoOptionalFixed64() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalFixed64 = 123; - assertEquals(123, msg.optionalFixed64); - msg.clear() - .optionalFixed64 = 456; - assertEquals(456, msg.optionalFixed64); - msg.clear(); - assertEquals(0, msg.optionalFixed64); - - msg.optionalFixed64 = 123; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 12); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(123, newMsg.optionalFixed64); - } - - public void testNanoOptionalSfixed32() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalSfixed32 = 123; - assertEquals(123, msg.optionalSfixed32); - msg.clear() - .optionalSfixed32 = 456; - assertEquals(456, msg.optionalSfixed32); - msg.clear(); - assertEquals(0, msg.optionalSfixed32); - - msg.optionalSfixed32 = 123; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 8); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(123, newMsg.optionalSfixed32); - } - - public void testNanoOptionalSfixed64() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalSfixed64 = 123; - assertEquals(123, msg.optionalSfixed64); - msg.clear() - .optionalSfixed64 = 456; - assertEquals(456, msg.optionalSfixed64); - msg.clear(); - assertEquals(0, msg.optionalSfixed64); - - msg.optionalSfixed64 = -123; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 12); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(-123, newMsg.optionalSfixed64); - } - - public void testNanoOptionalFloat() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalFloat = 123f; - assertTrue(123.0f == msg.optionalFloat); - msg.clear() - .optionalFloat = 456.0f; - assertTrue(456.0f == msg.optionalFloat); - msg.clear(); - assertTrue(0.0f == msg.optionalFloat); - - msg.optionalFloat = -123.456f; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 8); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertTrue(-123.456f == newMsg.optionalFloat); - } - - public void testNanoOptionalDouble() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalDouble = 123; - assertTrue(123.0 == msg.optionalDouble); - msg.clear() - .optionalDouble = 456.0; - assertTrue(456.0 == msg.optionalDouble); - msg.clear(); - assertTrue(0.0 == msg.optionalDouble); - - msg.optionalDouble = -123.456; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 12); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertTrue(-123.456 == newMsg.optionalDouble); - } - - public void testNanoOptionalBool() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalBool = true; - assertTrue(msg.optionalBool); - msg.clear() - .optionalBool = true; - assertTrue(msg.optionalBool); - msg.clear(); - assertFalse(msg.optionalBool); - - msg.optionalBool = true; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 5); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertTrue(newMsg.optionalBool); - } - - public void testNanoOptionalString() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalString = "hello"; - assertEquals("hello", msg.optionalString); - msg.clear(); - assertTrue(msg.optionalString.isEmpty()); - msg.clear() - .optionalString = "hello2"; - assertEquals("hello2", msg.optionalString); - msg.clear(); - assertTrue(msg.optionalString.isEmpty()); - - msg.optionalString = "bye"; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 8); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertTrue(newMsg.optionalString != null); - assertEquals("bye", newMsg.optionalString); - } - - public void testNanoOptionalBytes() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertFalse(msg.optionalBytes.length > 0); - msg.optionalBytes = InternalNano.copyFromUtf8("hello"); - assertTrue(msg.optionalBytes.length > 0); - assertEquals("hello", new String(msg.optionalBytes, InternalNano.UTF_8)); - msg.clear(); - assertFalse(msg.optionalBytes.length > 0); - msg.clear() - .optionalBytes = InternalNano.copyFromUtf8("hello"); - assertTrue(msg.optionalBytes.length > 0); - msg.clear(); - assertFalse(msg.optionalBytes.length > 0); - - msg.optionalBytes = InternalNano.copyFromUtf8("bye"); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 8); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertTrue(newMsg.optionalBytes.length > 0); - assertEquals("bye", new String(newMsg.optionalBytes, InternalNano.UTF_8)); - } - - public void testNanoOptionalGroup() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - TestAllTypesNano.OptionalGroup grp = new TestAllTypesNano.OptionalGroup(); - grp.a = 1; - assertFalse(msg.optionalGroup != null); - msg.optionalGroup = grp; - assertTrue(msg.optionalGroup != null); - assertEquals(1, msg.optionalGroup.a); - msg.clear(); - assertFalse(msg.optionalGroup != null); - msg.clear() - .optionalGroup = new TestAllTypesNano.OptionalGroup(); - msg.optionalGroup.a = 2; - assertTrue(msg.optionalGroup != null); - msg.clear(); - assertFalse(msg.optionalGroup != null); - - msg.optionalGroup = grp; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 10); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertTrue(newMsg.optionalGroup != null); - assertEquals(1, newMsg.optionalGroup.a); - } - - public void testNanoOptionalGroupWithUnknownFieldsEnabled() throws Exception { - MessageWithGroup msg = new MessageWithGroup(); - MessageWithGroup.Group grp = new MessageWithGroup.Group(); - grp.a = 1; - msg.group = grp; - byte [] serialized = MessageNano.toByteArray(msg); - - MessageWithGroup parsed = MessageWithGroup.parseFrom(serialized); - assertEquals(1, parsed.group.a); - - byte [] serialized2 = MessageNano.toByteArray(parsed); - assertEquals(serialized.length, serialized2.length); - MessageWithGroup parsed2 = MessageWithGroup.parseFrom(serialized2); - assertEquals(1, parsed2.group.a); - } - - public void testNanoOptionalNestedMessage() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - TestAllTypesNano.NestedMessage nestedMsg = new TestAllTypesNano.NestedMessage(); - nestedMsg.bb = 1; - assertFalse(msg.optionalNestedMessage != null); - msg.optionalNestedMessage = nestedMsg; - assertTrue(msg.optionalNestedMessage != null); - assertEquals(1, msg.optionalNestedMessage.bb); - msg.clear(); - assertFalse(msg.optionalNestedMessage != null); - msg.clear() - .optionalNestedMessage = new TestAllTypesNano.NestedMessage(); - msg.optionalNestedMessage.bb = 2; - assertTrue(msg.optionalNestedMessage != null); - msg.clear(); - assertFalse(msg.optionalNestedMessage != null); - - msg.optionalNestedMessage = nestedMsg; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 8); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertTrue(newMsg.optionalNestedMessage != null); - assertEquals(1, newMsg.optionalNestedMessage.bb); - } - - public void testNanoOptionalForeignMessage() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - NanoOuterClass.ForeignMessageNano nestedMsg = new NanoOuterClass.ForeignMessageNano(); - nestedMsg.c = 1; - assertFalse(msg.optionalForeignMessage != null); - msg.optionalForeignMessage = nestedMsg; - assertTrue(msg.optionalForeignMessage != null); - assertEquals(1, msg.optionalForeignMessage.c); - msg.clear(); - assertFalse(msg.optionalForeignMessage != null); - msg.clear() - .optionalForeignMessage = new NanoOuterClass.ForeignMessageNano(); - msg.optionalForeignMessage.c = 2; - assertTrue(msg.optionalForeignMessage != null); - msg.clear(); - assertFalse(msg.optionalForeignMessage != null); - - msg.optionalForeignMessage = nestedMsg; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 8); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertTrue(newMsg.optionalForeignMessage != null); - assertEquals(1, newMsg.optionalForeignMessage.c); - } - - public void testNanoOptionalImportMessage() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - UnittestImportNano.ImportMessageNano nestedMsg = new UnittestImportNano.ImportMessageNano(); - nestedMsg.d = 1; - assertFalse(msg.optionalImportMessage != null); - msg.optionalImportMessage = nestedMsg; - assertTrue(msg.optionalImportMessage != null); - assertEquals(1, msg.optionalImportMessage.d); - msg.clear(); - assertFalse(msg.optionalImportMessage != null); - msg.clear() - .optionalImportMessage = new UnittestImportNano.ImportMessageNano(); - msg.optionalImportMessage.d = 2; - assertTrue(msg.optionalImportMessage != null); - msg.clear(); - assertFalse(msg.optionalImportMessage != null); - - msg.optionalImportMessage = nestedMsg; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 8); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertTrue(newMsg.optionalImportMessage != null); - assertEquals(1, newMsg.optionalImportMessage.d); - } - - public void testNanoOptionalNestedEnum() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalNestedEnum = TestAllTypesNano.BAR; - assertEquals(TestAllTypesNano.BAR, msg.optionalNestedEnum); - msg.clear() - .optionalNestedEnum = TestAllTypesNano.BAZ; - assertEquals(TestAllTypesNano.BAZ, msg.optionalNestedEnum); - msg.clear(); - assertEquals(TestAllTypesNano.FOO, msg.optionalNestedEnum); - - msg.optionalNestedEnum = TestAllTypesNano.BAR; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(TestAllTypesNano.BAR, newMsg.optionalNestedEnum); - } - - public void testNanoOptionalForeignEnum() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalForeignEnum = NanoOuterClass.FOREIGN_NANO_BAR; - assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.optionalForeignEnum); - msg.clear() - .optionalForeignEnum = NanoOuterClass.FOREIGN_NANO_BAZ; - assertEquals(NanoOuterClass.FOREIGN_NANO_BAZ, msg.optionalForeignEnum); - msg.clear(); - assertEquals(NanoOuterClass.FOREIGN_NANO_FOO, msg.optionalForeignEnum); - - msg.optionalForeignEnum = NanoOuterClass.FOREIGN_NANO_BAR; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, newMsg.optionalForeignEnum); - } - - public void testNanoOptionalImportEnum() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalImportEnum = UnittestImportNano.IMPORT_NANO_BAR; - assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.optionalImportEnum); - msg.clear() - .optionalImportEnum = UnittestImportNano.IMPORT_NANO_BAZ; - assertEquals(UnittestImportNano.IMPORT_NANO_BAZ, msg.optionalImportEnum); - msg.clear(); - assertEquals(UnittestImportNano.IMPORT_NANO_FOO, msg.optionalImportEnum); - - msg.optionalImportEnum = UnittestImportNano.IMPORT_NANO_BAR; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(UnittestImportNano.IMPORT_NANO_BAR, newMsg.optionalImportEnum); - } - - public void testNanoOptionalStringPiece() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalStringPiece = "hello"; - assertEquals("hello", msg.optionalStringPiece); - msg.clear(); - assertTrue(msg.optionalStringPiece.isEmpty()); - msg.clear() - .optionalStringPiece = "hello2"; - assertEquals("hello2", msg.optionalStringPiece); - msg.clear(); - assertTrue(msg.optionalStringPiece.isEmpty()); - - msg.optionalStringPiece = "bye"; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 9); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertTrue(newMsg.optionalStringPiece != null); - assertEquals("bye", newMsg.optionalStringPiece); - } - - public void testNanoOptionalCord() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalCord = "hello"; - assertEquals("hello", msg.optionalCord); - msg.clear(); - assertTrue(msg.optionalCord.isEmpty()); - msg.clear() - .optionalCord = "hello2"; - assertEquals("hello2", msg.optionalCord); - msg.clear(); - assertTrue(msg.optionalCord.isEmpty()); - - msg.optionalCord = "bye"; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 9); - assertEquals(result.length, msgSerializedSize); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertTrue(newMsg.optionalCord != null); - assertEquals("bye", newMsg.optionalCord); - } - - public void testNanoRepeatedInt32() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedInt32.length); - msg.repeatedInt32 = new int[] { 123, 789, 456 }; - assertEquals(789, msg.repeatedInt32[1]); - assertEquals(456, msg.repeatedInt32[2]); - msg.clear(); - assertEquals(0, msg.repeatedInt32.length); - msg.clear() - .repeatedInt32 = new int[] { 456 }; - assertEquals(1, msg.repeatedInt32.length); - assertEquals(456, msg.repeatedInt32[0]); - msg.clear(); - assertEquals(0, msg.repeatedInt32.length); - - // Test 1 entry - msg.clear() - .repeatedInt32 = new int[] { 123 }; - assertEquals(1, msg.repeatedInt32.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedInt32.length); - assertEquals(123, newMsg.repeatedInt32[0]); - - // Test 2 entries - msg.clear() - .repeatedInt32 = new int[] { 123, 456 }; - assertEquals(2, msg.repeatedInt32.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 10); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedInt32.length); - assertEquals(123, newMsg.repeatedInt32[0]); - assertEquals(456, newMsg.repeatedInt32[1]); - } - - public void testNanoRepeatedInt64() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedInt64.length); - msg.repeatedInt64 = new long[] { 123, 789, 456 }; - assertEquals(789, msg.repeatedInt64[1]); - assertEquals(456, msg.repeatedInt64[2]); - msg.clear(); - assertEquals(0, msg.repeatedInt64.length); - msg.clear() - .repeatedInt64 = new long[] { 456 }; - assertEquals(1, msg.repeatedInt64.length); - assertEquals(456, msg.repeatedInt64[0]); - msg.clear(); - assertEquals(0, msg.repeatedInt64.length); - - // Test 1 entry - msg.clear() - .repeatedInt64 = new long[] { 123 }; - assertEquals(1, msg.repeatedInt64.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedInt64.length); - assertEquals(123, newMsg.repeatedInt64[0]); - - // Test 2 entries - msg.clear() - .repeatedInt64 = new long[] { 123, 456 }; - assertEquals(2, msg.repeatedInt64.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 10); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedInt64.length); - assertEquals(123, newMsg.repeatedInt64[0]); - assertEquals(456, newMsg.repeatedInt64[1]); - } - - public void testNanoRepeatedUint32() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedUint32.length); - msg.repeatedUint32 = new int[] { 123, 789, 456 }; - assertEquals(789, msg.repeatedUint32[1]); - assertEquals(456, msg.repeatedUint32[2]); - msg.clear(); - assertEquals(0, msg.repeatedUint32.length); - msg.clear() - .repeatedUint32 = new int[] { 456 }; - assertEquals(1, msg.repeatedUint32.length); - assertEquals(456, msg.repeatedUint32[0]); - msg.clear(); - assertEquals(0, msg.repeatedUint32.length); - - // Test 1 entry - msg.clear() - .repeatedUint32 = new int[] { 123 }; - assertEquals(1, msg.repeatedUint32.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedUint32.length); - assertEquals(123, newMsg.repeatedUint32[0]); - - // Test 2 entries - msg.clear() - .repeatedUint32 = new int[] { 123, 456 }; - assertEquals(2, msg.repeatedUint32.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 10); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedUint32.length); - assertEquals(123, newMsg.repeatedUint32[0]); - assertEquals(456, newMsg.repeatedUint32[1]); - } - - public void testNanoRepeatedUint64() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedUint64.length); - msg.repeatedUint64 = new long[] { 123, 789, 456 }; - assertEquals(789, msg.repeatedUint64[1]); - assertEquals(456, msg.repeatedUint64[2]); - msg.clear(); - assertEquals(0, msg.repeatedUint64.length); - msg.clear() - .repeatedUint64 = new long[] { 456 }; - assertEquals(1, msg.repeatedUint64.length); - assertEquals(456, msg.repeatedUint64[0]); - msg.clear(); - assertEquals(0, msg.repeatedUint64.length); - - // Test 1 entry - msg.clear() - .repeatedUint64 = new long[] { 123 }; - assertEquals(1, msg.repeatedUint64.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedUint64.length); - assertEquals(123, newMsg.repeatedUint64[0]); - - // Test 2 entries - msg.clear() - .repeatedUint64 = new long[] { 123, 456 }; - assertEquals(2, msg.repeatedUint64.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 10); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedUint64.length); - assertEquals(123, newMsg.repeatedUint64[0]); - assertEquals(456, newMsg.repeatedUint64[1]); - } - - public void testNanoRepeatedSint32() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedSint32.length); - msg.repeatedSint32 = new int[] { 123, 789, 456 }; - assertEquals(789, msg.repeatedSint32[1]); - assertEquals(456, msg.repeatedSint32[2]); - msg.clear(); - assertEquals(0, msg.repeatedSint32.length); - msg.clear() - .repeatedSint32 = new int[] { 456 }; - assertEquals(1, msg.repeatedSint32.length); - assertEquals(456, msg.repeatedSint32[0]); - msg.clear(); - assertEquals(0, msg.repeatedSint32.length); - - // Test 1 entry - msg.clear() - .repeatedSint32 = new int[] { 123 }; - assertEquals(1, msg.repeatedSint32.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 7); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedSint32.length); - assertEquals(123, newMsg.repeatedSint32[0]); - - // Test 2 entries - msg.clear() - .repeatedSint32 = new int[] { 123, 456 }; - assertEquals(2, msg.repeatedSint32.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 11); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedSint32.length); - assertEquals(123, newMsg.repeatedSint32[0]); - assertEquals(456, newMsg.repeatedSint32[1]); - } - - public void testNanoRepeatedSint64() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedSint64.length); - msg.repeatedSint64 = new long[] { 123, 789, 456 }; - assertEquals(789, msg.repeatedSint64[1]); - assertEquals(456, msg.repeatedSint64[2]); - msg.clear(); - assertEquals(0, msg.repeatedSint64.length); - msg.clear() - .repeatedSint64 = new long[] { 456 }; - assertEquals(1, msg.repeatedSint64.length); - assertEquals(456, msg.repeatedSint64[0]); - msg.clear(); - assertEquals(0, msg.repeatedSint64.length); - - // Test 1 entry - msg.clear() - .repeatedSint64 = new long[] { 123 }; - assertEquals(1, msg.repeatedSint64.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 7); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedSint64.length); - assertEquals(123, newMsg.repeatedSint64[0]); - - // Test 2 entries - msg.clear() - .repeatedSint64 = new long[] { 123, 456 }; - assertEquals(2, msg.repeatedSint64.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 11); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedSint64.length); - assertEquals(123, newMsg.repeatedSint64[0]); - assertEquals(456, newMsg.repeatedSint64[1]); - } - - public void testNanoRepeatedFixed32() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedFixed32.length); - msg.repeatedFixed32 = new int[] { 123, 789, 456 }; - assertEquals(789, msg.repeatedFixed32[1]); - assertEquals(456, msg.repeatedFixed32[2]); - msg.clear(); - assertEquals(0, msg.repeatedFixed32.length); - msg.clear() - .repeatedFixed32 = new int[] { 456 }; - assertEquals(1, msg.repeatedFixed32.length); - assertEquals(456, msg.repeatedFixed32[0]); - msg.clear(); - assertEquals(0, msg.repeatedFixed32.length); - - // Test 1 entry - msg.clear() - .repeatedFixed32 = new int[] { 123 }; - assertEquals(1, msg.repeatedFixed32.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 9); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedFixed32.length); - assertEquals(123, newMsg.repeatedFixed32[0]); - - // Test 2 entries - msg.clear() - .repeatedFixed32 = new int[] { 123, 456 }; - assertEquals(2, msg.repeatedFixed32.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 15); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedFixed32.length); - assertEquals(123, newMsg.repeatedFixed32[0]); - assertEquals(456, newMsg.repeatedFixed32[1]); - } - - public void testNanoRepeatedFixed64() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedFixed64.length); - msg.repeatedFixed64 = new long[] { 123, 789, 456 }; - assertEquals(789, msg.repeatedFixed64[1]); - assertEquals(456, msg.repeatedFixed64[2]); - msg.clear(); - assertEquals(0, msg.repeatedFixed64.length); - msg.clear() - .repeatedFixed64 = new long[] { 456 }; - assertEquals(1, msg.repeatedFixed64.length); - assertEquals(456, msg.repeatedFixed64[0]); - msg.clear(); - assertEquals(0, msg.repeatedFixed64.length); - - // Test 1 entry - msg.clear() - .repeatedFixed64 = new long[] { 123 }; - assertEquals(1, msg.repeatedFixed64.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 13); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedFixed64.length); - assertEquals(123, newMsg.repeatedFixed64[0]); - - // Test 2 entries - msg.clear() - .repeatedFixed64 = new long[] { 123, 456 }; - assertEquals(2, msg.repeatedFixed64.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 23); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedFixed64.length); - assertEquals(123, newMsg.repeatedFixed64[0]); - assertEquals(456, newMsg.repeatedFixed64[1]); - } - - public void testNanoRepeatedSfixed32() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedSfixed32.length); - msg.repeatedSfixed32 = new int[] { 123, 789, 456 }; - assertEquals(789, msg.repeatedSfixed32[1]); - assertEquals(456, msg.repeatedSfixed32[2]); - msg.clear(); - assertEquals(0, msg.repeatedSfixed32.length); - msg.clear() - .repeatedSfixed32 = new int[] { 456 }; - assertEquals(1, msg.repeatedSfixed32.length); - assertEquals(456, msg.repeatedSfixed32[0]); - msg.clear(); - assertEquals(0, msg.repeatedSfixed32.length); - - // Test 1 entry - msg.clear() - .repeatedSfixed32 = new int[] { 123 }; - assertEquals(1, msg.repeatedSfixed32.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 9); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedSfixed32.length); - assertEquals(123, newMsg.repeatedSfixed32[0]); - - // Test 2 entries - msg.clear() - .repeatedSfixed32 = new int[] { 123, 456 }; - assertEquals(2, msg.repeatedSfixed32.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 15); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedSfixed32.length); - assertEquals(123, newMsg.repeatedSfixed32[0]); - assertEquals(456, newMsg.repeatedSfixed32[1]); - } - - public void testNanoRepeatedSfixed64() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedSfixed64.length); - msg.repeatedSfixed64 = new long[] { 123, 789, 456 }; - assertEquals(789, msg.repeatedSfixed64[1]); - assertEquals(456, msg.repeatedSfixed64[2]); - msg.clear(); - assertEquals(0, msg.repeatedSfixed64.length); - msg.clear() - .repeatedSfixed64 = new long[] { 456 }; - assertEquals(1, msg.repeatedSfixed64.length); - assertEquals(456, msg.repeatedSfixed64[0]); - msg.clear(); - assertEquals(0, msg.repeatedSfixed64.length); - - // Test 1 entry - msg.clear() - .repeatedSfixed64 = new long[] { 123 }; - assertEquals(1, msg.repeatedSfixed64.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 13); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedSfixed64.length); - assertEquals(123, newMsg.repeatedSfixed64[0]); - - // Test 2 entries - msg.clear() - .repeatedSfixed64 = new long[] { 123, 456 }; - assertEquals(2, msg.repeatedSfixed64.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 23); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedSfixed64.length); - assertEquals(123, newMsg.repeatedSfixed64[0]); - assertEquals(456, newMsg.repeatedSfixed64[1]); - } - - public void testNanoRepeatedFloat() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedFloat.length); - msg.repeatedFloat = new float[] { 123f, 789f, 456f }; - assertEquals(789f, msg.repeatedFloat[1]); - assertEquals(456f, msg.repeatedFloat[2]); - msg.clear(); - assertEquals(0, msg.repeatedFloat.length); - msg.clear() - .repeatedFloat = new float[] { 456f }; - assertEquals(1, msg.repeatedFloat.length); - assertEquals(456f, msg.repeatedFloat[0]); - msg.clear(); - assertEquals(0, msg.repeatedFloat.length); - - // Test 1 entry - msg.clear() - .repeatedFloat = new float[] { 123f }; - assertEquals(1, msg.repeatedFloat.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 9); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedFloat.length); - assertEquals(123f, newMsg.repeatedFloat[0]); - - // Test 2 entries - msg.clear() - .repeatedFloat = new float[] { 123f, 456f }; - assertEquals(2, msg.repeatedFloat.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 15); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedFloat.length); - assertEquals(123f, newMsg.repeatedFloat[0]); - assertEquals(456f, newMsg.repeatedFloat[1]); - } - - public void testNanoRepeatedDouble() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedDouble.length); - msg.repeatedDouble = new double[] { 123.0, 789.0, 456.0 }; - assertEquals(789.0, msg.repeatedDouble[1]); - assertEquals(456.0, msg.repeatedDouble[2]); - msg.clear(); - assertEquals(0, msg.repeatedDouble.length); - msg.clear() - .repeatedDouble = new double[] { 456.0 }; - assertEquals(1, msg.repeatedDouble.length); - assertEquals(456.0, msg.repeatedDouble[0]); - msg.clear(); - assertEquals(0, msg.repeatedDouble.length); - - // Test 1 entry - msg.clear() - .repeatedDouble = new double[] { 123.0 }; - assertEquals(1, msg.repeatedDouble.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 13); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedDouble.length); - assertEquals(123.0, newMsg.repeatedDouble[0]); - - // Test 2 entries - msg.clear() - .repeatedDouble = new double[] { 123.0, 456.0 }; - assertEquals(2, msg.repeatedDouble.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 23); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedDouble.length); - assertEquals(123.0, newMsg.repeatedDouble[0]); - assertEquals(456.0, newMsg.repeatedDouble[1]); - } - - public void testNanoRepeatedBool() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedBool.length); - msg.repeatedBool = new boolean[] { false, true, false }; - assertTrue(msg.repeatedBool[1]); - assertFalse(msg.repeatedBool[2]); - msg.clear(); - assertEquals(0, msg.repeatedBool.length); - msg.clear() - .repeatedBool = new boolean[] { true }; - assertEquals(1, msg.repeatedBool.length); - assertTrue(msg.repeatedBool[0]); - msg.clear(); - assertEquals(0, msg.repeatedBool.length); - - // Test 1 entry - msg.clear() - .repeatedBool = new boolean[] { false }; - assertEquals(1, msg.repeatedBool.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedBool.length); - assertFalse(newMsg.repeatedBool[0]); - - // Test 2 entries - msg.clear() - .repeatedBool = new boolean[] { true, false }; - assertEquals(2, msg.repeatedBool.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 9); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedBool.length); - assertTrue(newMsg.repeatedBool[0]); - assertFalse(newMsg.repeatedBool[1]); - } - - public void testNanoRepeatedString() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedString.length); - msg.repeatedString = new String[] { "hello", "bye", "boo" }; - assertEquals("bye", msg.repeatedString[1]); - assertEquals("boo", msg.repeatedString[2]); - msg.clear(); - assertEquals(0, msg.repeatedString.length); - msg.clear() - .repeatedString = new String[] { "boo" }; - assertEquals(1, msg.repeatedString.length); - assertEquals("boo", msg.repeatedString[0]); - msg.clear(); - assertEquals(0, msg.repeatedString.length); - - // Test 1 entry - msg.clear() - .repeatedString = new String[] { "" }; - assertEquals(1, msg.repeatedString.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedString.length); - assertTrue(newMsg.repeatedString[0].isEmpty()); - - // Test 2 entries - msg.clear() - .repeatedString = new String[] { "hello", "world" }; - assertEquals(2, msg.repeatedString.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 19); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedString.length); - assertEquals("hello", newMsg.repeatedString[0]); - assertEquals("world", newMsg.repeatedString[1]); - } - - public void testNanoRepeatedBytes() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedBytes.length); - msg.repeatedBytes = new byte[][] { - InternalNano.copyFromUtf8("hello"), - InternalNano.copyFromUtf8("bye"), - InternalNano.copyFromUtf8("boo") - }; - assertEquals("bye", new String(msg.repeatedBytes[1], InternalNano.UTF_8)); - assertEquals("boo", new String(msg.repeatedBytes[2], InternalNano.UTF_8)); - msg.clear(); - assertEquals(0, msg.repeatedBytes.length); - msg.clear() - .repeatedBytes = new byte[][] { InternalNano.copyFromUtf8("boo") }; - assertEquals(1, msg.repeatedBytes.length); - assertEquals("boo", new String(msg.repeatedBytes[0], InternalNano.UTF_8)); - msg.clear(); - assertEquals(0, msg.repeatedBytes.length); - - // Test 1 entry - msg.clear() - .repeatedBytes = new byte[][] { InternalNano.copyFromUtf8("") }; - assertEquals(1, msg.repeatedBytes.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedBytes.length); - assertTrue(newMsg.repeatedBytes[0].length == 0); - - // Test 2 entries - msg.clear() - .repeatedBytes = new byte[][] { - InternalNano.copyFromUtf8("hello"), - InternalNano.copyFromUtf8("world") - }; - assertEquals(2, msg.repeatedBytes.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 19); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedBytes.length); - assertEquals("hello", new String(newMsg.repeatedBytes[0], InternalNano.UTF_8)); - assertEquals("world", new String(newMsg.repeatedBytes[1], InternalNano.UTF_8)); - } - - public void testNanoRepeatedGroup() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - TestAllTypesNano.RepeatedGroup group0 = - new TestAllTypesNano.RepeatedGroup(); - group0.a = 0; - TestAllTypesNano.RepeatedGroup group1 = - new TestAllTypesNano.RepeatedGroup(); - group1.a = 1; - TestAllTypesNano.RepeatedGroup group2 = - new TestAllTypesNano.RepeatedGroup(); - group2.a = 2; - - msg.repeatedGroup = new TestAllTypesNano.RepeatedGroup[] { group0, group1, group2 }; - assertEquals(3, msg.repeatedGroup.length); - assertEquals(0, msg.repeatedGroup[0].a); - assertEquals(1, msg.repeatedGroup[1].a); - assertEquals(2, msg.repeatedGroup[2].a); - msg.clear(); - assertEquals(0, msg.repeatedGroup.length); - msg.clear() - .repeatedGroup = new TestAllTypesNano.RepeatedGroup[] { group1 }; - assertEquals(1, msg.repeatedGroup.length); - assertEquals(1, msg.repeatedGroup[0].a); - msg.clear(); - assertEquals(0, msg.repeatedGroup.length); - - // Test 1 entry - msg.clear() - .repeatedGroup = new TestAllTypesNano.RepeatedGroup[] { group0 }; - assertEquals(1, msg.repeatedGroup.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 7); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedGroup.length); - assertEquals(0, newMsg.repeatedGroup[0].a); - - // Test 2 entries - msg.clear() - .repeatedGroup = new TestAllTypesNano.RepeatedGroup[] { group0, group1 }; - assertEquals(2, msg.repeatedGroup.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 14); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedGroup.length); - assertEquals(0, newMsg.repeatedGroup[0].a); - assertEquals(1, newMsg.repeatedGroup[1].a); - } - - public void testNanoRepeatedNestedMessage() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - TestAllTypesNano.NestedMessage nestedMsg0 = - new TestAllTypesNano.NestedMessage(); - nestedMsg0.bb = 0; - TestAllTypesNano.NestedMessage nestedMsg1 = - new TestAllTypesNano.NestedMessage(); - nestedMsg1.bb = 1; - TestAllTypesNano.NestedMessage nestedMsg2 = - new TestAllTypesNano.NestedMessage(); - nestedMsg2.bb = 2; - - msg.repeatedNestedMessage = - new TestAllTypesNano.NestedMessage[] { nestedMsg0, nestedMsg1, nestedMsg2 }; - assertEquals(3, msg.repeatedNestedMessage.length); - assertEquals(0, msg.repeatedNestedMessage[0].bb); - assertEquals(1, msg.repeatedNestedMessage[1].bb); - assertEquals(2, msg.repeatedNestedMessage[2].bb); - msg.clear(); - assertEquals(0, msg.repeatedNestedMessage.length); - msg.clear() - .repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { nestedMsg1 }; - assertEquals(1, msg.repeatedNestedMessage.length); - assertEquals(1, msg.repeatedNestedMessage[0].bb); - msg.clear(); - assertEquals(0, msg.repeatedNestedMessage.length); - - // Test 1 entry - msg.clear() - .repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { nestedMsg0 }; - assertEquals(1, msg.repeatedNestedMessage.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedNestedMessage.length); - assertEquals(0, newMsg.repeatedNestedMessage[0].bb); - - // Test 2 entries - msg.clear() - .repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { nestedMsg0, nestedMsg1 }; - assertEquals(2, msg.repeatedNestedMessage.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 11); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedNestedMessage.length); - assertEquals(0, newMsg.repeatedNestedMessage[0].bb); - assertEquals(1, newMsg.repeatedNestedMessage[1].bb); - } - - public void testNanoRepeatedForeignMessage() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - NanoOuterClass.ForeignMessageNano foreignMsg0 = - new NanoOuterClass.ForeignMessageNano(); - foreignMsg0.c = 0; - NanoOuterClass.ForeignMessageNano foreignMsg1 = - new NanoOuterClass.ForeignMessageNano(); - foreignMsg1.c = 1; - NanoOuterClass.ForeignMessageNano foreignMsg2 = - new NanoOuterClass.ForeignMessageNano(); - foreignMsg2.c = 2; - - msg.repeatedForeignMessage = - new NanoOuterClass.ForeignMessageNano[] { foreignMsg0, foreignMsg1, foreignMsg2 }; - assertEquals(3, msg.repeatedForeignMessage.length); - assertEquals(0, msg.repeatedForeignMessage[0].c); - assertEquals(1, msg.repeatedForeignMessage[1].c); - assertEquals(2, msg.repeatedForeignMessage[2].c); - msg.clear(); - assertEquals(0, msg.repeatedForeignMessage.length); - msg.clear() - .repeatedForeignMessage = new NanoOuterClass.ForeignMessageNano[] { foreignMsg1 }; - assertEquals(1, msg.repeatedForeignMessage.length); - assertEquals(1, msg.repeatedForeignMessage[0].c); - msg.clear(); - assertEquals(0, msg.repeatedForeignMessage.length); - - // Test 1 entry - msg.clear() - .repeatedForeignMessage = new NanoOuterClass.ForeignMessageNano[] { foreignMsg0 }; - assertEquals(1, msg.repeatedForeignMessage.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedForeignMessage.length); - assertEquals(0, newMsg.repeatedForeignMessage[0].c); - - // Test 2 entries - msg.clear() - .repeatedForeignMessage = new NanoOuterClass.ForeignMessageNano[] { foreignMsg0, foreignMsg1 }; - assertEquals(2, msg.repeatedForeignMessage.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 11); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedForeignMessage.length); - assertEquals(0, newMsg.repeatedForeignMessage[0].c); - assertEquals(1, newMsg.repeatedForeignMessage[1].c); - } - - public void testNanoRepeatedImportMessage() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - UnittestImportNano.ImportMessageNano foreignMsg0 = - new UnittestImportNano.ImportMessageNano(); - foreignMsg0.d = 0; - UnittestImportNano.ImportMessageNano foreignMsg1 = - new UnittestImportNano.ImportMessageNano(); - foreignMsg1.d = 1; - UnittestImportNano.ImportMessageNano foreignMsg2 = - new UnittestImportNano.ImportMessageNano(); - foreignMsg2.d = 2; - - msg.repeatedImportMessage = - new UnittestImportNano.ImportMessageNano[] { foreignMsg0, foreignMsg1, foreignMsg2 }; - assertEquals(3, msg.repeatedImportMessage.length); - assertEquals(0, msg.repeatedImportMessage[0].d); - assertEquals(1, msg.repeatedImportMessage[1].d); - assertEquals(2, msg.repeatedImportMessage[2].d); - msg.clear(); - assertEquals(0, msg.repeatedImportMessage.length); - msg.clear() - .repeatedImportMessage = new UnittestImportNano.ImportMessageNano[] { foreignMsg1 }; - assertEquals(1, msg.repeatedImportMessage.length); - assertEquals(1, msg.repeatedImportMessage[0].d); - msg.clear(); - assertEquals(0, msg.repeatedImportMessage.length); - - // Test 1 entry - msg.clear() - .repeatedImportMessage = new UnittestImportNano.ImportMessageNano[] { foreignMsg0 }; - assertEquals(1, msg.repeatedImportMessage.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedImportMessage.length); - assertEquals(0, newMsg.repeatedImportMessage[0].d); - - // Test 2 entries - msg.clear() - .repeatedImportMessage = new UnittestImportNano.ImportMessageNano[] { foreignMsg0, foreignMsg1 }; - assertEquals(2, msg.repeatedImportMessage.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 11); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedImportMessage.length); - assertEquals(0, newMsg.repeatedImportMessage[0].d); - assertEquals(1, newMsg.repeatedImportMessage[1].d); - } - - public void testNanoRepeatedNestedEnum() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.repeatedNestedEnum = new int[] { - TestAllTypesNano.FOO, - TestAllTypesNano.BAR, - TestAllTypesNano.BAZ - }; - assertEquals(3, msg.repeatedNestedEnum.length); - assertEquals(TestAllTypesNano.FOO, msg.repeatedNestedEnum[0]); - assertEquals(TestAllTypesNano.BAR, msg.repeatedNestedEnum[1]); - assertEquals(TestAllTypesNano.BAZ, msg.repeatedNestedEnum[2]); - msg.clear(); - assertEquals(0, msg.repeatedNestedEnum.length); - msg.clear() - .repeatedNestedEnum = new int[] { TestAllTypesNano.BAR }; - assertEquals(1, msg.repeatedNestedEnum.length); - assertEquals(TestAllTypesNano.BAR, msg.repeatedNestedEnum[0]); - msg.clear(); - assertEquals(0, msg.repeatedNestedEnum.length); - - // Test 1 entry - msg.clear() - .repeatedNestedEnum = new int[] { TestAllTypesNano.FOO }; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedNestedEnum.length); - assertEquals(TestAllTypesNano.FOO, msg.repeatedNestedEnum[0]); - - // Test 2 entries - msg.clear() - .repeatedNestedEnum = new int[] { TestAllTypesNano.FOO, TestAllTypesNano.BAR }; - assertEquals(2, msg.repeatedNestedEnum.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 9); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedNestedEnum.length); - assertEquals(TestAllTypesNano.FOO, msg.repeatedNestedEnum[0]); - assertEquals(TestAllTypesNano.BAR, msg.repeatedNestedEnum[1]); - } - - public void testNanoRepeatedForeignEnum() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.repeatedForeignEnum = new int[] { - NanoOuterClass.FOREIGN_NANO_FOO, - NanoOuterClass.FOREIGN_NANO_BAR, - NanoOuterClass.FOREIGN_NANO_BAZ - }; - assertEquals(3, msg.repeatedForeignEnum.length); - assertEquals(NanoOuterClass.FOREIGN_NANO_FOO, msg.repeatedForeignEnum[0]); - assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.repeatedForeignEnum[1]); - assertEquals(NanoOuterClass.FOREIGN_NANO_BAZ, msg.repeatedForeignEnum[2]); - msg.clear(); - assertEquals(0, msg.repeatedForeignEnum.length); - msg.clear() - .repeatedForeignEnum = new int[] { NanoOuterClass.FOREIGN_NANO_BAR }; - assertEquals(1, msg.repeatedForeignEnum.length); - assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.repeatedForeignEnum[0]); - msg.clear(); - assertEquals(0, msg.repeatedForeignEnum.length); - - // Test 1 entry - msg.clear() - .repeatedForeignEnum = new int[] { NanoOuterClass.FOREIGN_NANO_FOO }; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedForeignEnum.length); - assertEquals(NanoOuterClass.FOREIGN_NANO_FOO, msg.repeatedForeignEnum[0]); - - // Test 2 entries - msg.clear() - .repeatedForeignEnum = new int[] { - NanoOuterClass.FOREIGN_NANO_FOO, - NanoOuterClass.FOREIGN_NANO_BAR - }; - assertEquals(2, msg.repeatedForeignEnum.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 9); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedForeignEnum.length); - assertEquals(NanoOuterClass.FOREIGN_NANO_FOO, msg.repeatedForeignEnum[0]); - assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.repeatedForeignEnum[1]); - } - - public void testNanoRepeatedImportEnum() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.repeatedImportEnum = new int[] { - UnittestImportNano.IMPORT_NANO_FOO, - UnittestImportNano.IMPORT_NANO_BAR, - UnittestImportNano.IMPORT_NANO_BAZ - }; - assertEquals(3, msg.repeatedImportEnum.length); - assertEquals(UnittestImportNano.IMPORT_NANO_FOO, msg.repeatedImportEnum[0]); - assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.repeatedImportEnum[1]); - assertEquals(UnittestImportNano.IMPORT_NANO_BAZ, msg.repeatedImportEnum[2]); - msg.clear(); - assertEquals(0, msg.repeatedImportEnum.length); - msg.clear() - .repeatedImportEnum = new int[] { UnittestImportNano.IMPORT_NANO_BAR }; - assertEquals(1, msg.repeatedImportEnum.length); - assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.repeatedImportEnum[0]); - msg.clear(); - assertEquals(0, msg.repeatedImportEnum.length); - - // Test 1 entry - msg.clear() - .repeatedImportEnum = new int[] { UnittestImportNano.IMPORT_NANO_FOO }; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedImportEnum.length); - assertEquals(UnittestImportNano.IMPORT_NANO_FOO, msg.repeatedImportEnum[0]); - - // Test 2 entries - msg.clear() - .repeatedImportEnum = new int[] { - UnittestImportNano.IMPORT_NANO_FOO, - UnittestImportNano.IMPORT_NANO_BAR - }; - assertEquals(2, msg.repeatedImportEnum.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 9); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedImportEnum.length); - assertEquals(UnittestImportNano.IMPORT_NANO_FOO, msg.repeatedImportEnum[0]); - assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.repeatedImportEnum[1]); - } - - public void testNanoRepeatedStringPiece() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedStringPiece.length); - msg.repeatedStringPiece = new String[] { "hello", "bye", "boo" }; - assertEquals("bye", msg.repeatedStringPiece[1]); - assertEquals("boo", msg.repeatedStringPiece[2]); - msg.clear(); - assertEquals(0, msg.repeatedStringPiece.length); - msg.clear() - .repeatedStringPiece = new String[] { "boo" }; - assertEquals(1, msg.repeatedStringPiece.length); - assertEquals("boo", msg.repeatedStringPiece[0]); - msg.clear(); - assertEquals(0, msg.repeatedStringPiece.length); - - // Test 1 entry - msg.clear() - .repeatedStringPiece = new String[] { "" }; - assertEquals(1, msg.repeatedStringPiece.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedStringPiece.length); - assertTrue(newMsg.repeatedStringPiece[0].isEmpty()); - - // Test 2 entries - msg.clear() - .repeatedStringPiece = new String[] { "hello", "world" }; - assertEquals(2, msg.repeatedStringPiece.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 19); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedStringPiece.length); - assertEquals("hello", newMsg.repeatedStringPiece[0]); - assertEquals("world", newMsg.repeatedStringPiece[1]); - } - - public void testNanoRepeatedCord() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedCord.length); - msg.repeatedCord = new String[] { "hello", "bye", "boo" }; - assertEquals("bye", msg.repeatedCord[1]); - assertEquals("boo", msg.repeatedCord[2]); - msg.clear(); - assertEquals(0, msg.repeatedCord.length); - msg.clear() - .repeatedCord = new String[] { "boo" }; - assertEquals(1, msg.repeatedCord.length); - assertEquals("boo", msg.repeatedCord[0]); - msg.clear(); - assertEquals(0, msg.repeatedCord.length); - - // Test 1 entry - msg.clear() - .repeatedCord = new String[] { "" }; - assertEquals(1, msg.repeatedCord.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 6); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedCord.length); - assertTrue(newMsg.repeatedCord[0].isEmpty()); - - // Test 2 entries - msg.clear() - .repeatedCord = new String[] { "hello", "world" }; - assertEquals(2, msg.repeatedCord.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 19); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedCord.length); - assertEquals("hello", newMsg.repeatedCord[0]); - assertEquals("world", newMsg.repeatedCord[1]); - } - - public void testNanoRepeatedPackedInt32() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedPackedInt32.length); - msg.repeatedPackedInt32 = new int[] { 123, 789, 456 }; - assertEquals(789, msg.repeatedPackedInt32[1]); - assertEquals(456, msg.repeatedPackedInt32[2]); - msg.clear(); - assertEquals(0, msg.repeatedPackedInt32.length); - msg.clear() - .repeatedPackedInt32 = new int[] { 456 }; - assertEquals(1, msg.repeatedPackedInt32.length); - assertEquals(456, msg.repeatedPackedInt32[0]); - msg.clear(); - assertEquals(0, msg.repeatedPackedInt32.length); - - // Test 1 entry - msg.clear() - .repeatedPackedInt32 = new int[] { 123 }; - assertEquals(1, msg.repeatedPackedInt32.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 7); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedPackedInt32.length); - assertEquals(123, newMsg.repeatedPackedInt32[0]); - - // Test 2 entries - msg.clear() - .repeatedPackedInt32 = new int[] { 123, 456 }; - assertEquals(2, msg.repeatedPackedInt32.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 9); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedPackedInt32.length); - assertEquals(123, newMsg.repeatedPackedInt32[0]); - assertEquals(456, newMsg.repeatedPackedInt32[1]); - } - - public void testNanoRepeatedPackedSfixed64() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - assertEquals(0, msg.repeatedPackedSfixed64.length); - msg.repeatedPackedSfixed64 = new long[] { 123, 789, 456 }; - assertEquals(789, msg.repeatedPackedSfixed64[1]); - assertEquals(456, msg.repeatedPackedSfixed64[2]); - msg.clear(); - assertEquals(0, msg.repeatedPackedSfixed64.length); - msg.clear() - .repeatedPackedSfixed64 = new long[] { 456 }; - assertEquals(1, msg.repeatedPackedSfixed64.length); - assertEquals(456, msg.repeatedPackedSfixed64[0]); - msg.clear(); - assertEquals(0, msg.repeatedPackedSfixed64.length); - - // Test 1 entry - msg.clear() - .repeatedPackedSfixed64 = new long[] { 123 }; - assertEquals(1, msg.repeatedPackedSfixed64.length); - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 14); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedPackedSfixed64.length); - assertEquals(123, newMsg.repeatedPackedSfixed64[0]); - - // Test 2 entries - msg.clear() - .repeatedPackedSfixed64 = new long[] { 123, 456 }; - assertEquals(2, msg.repeatedPackedSfixed64.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 22); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedPackedSfixed64.length); - assertEquals(123, newMsg.repeatedPackedSfixed64[0]); - assertEquals(456, newMsg.repeatedPackedSfixed64[1]); - } - - public void testNanoRepeatedPackedNestedEnum() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.repeatedPackedNestedEnum = new int[] { - TestAllTypesNano.FOO, - TestAllTypesNano.BAR, - TestAllTypesNano.BAZ - }; - assertEquals(3, msg.repeatedPackedNestedEnum.length); - assertEquals(TestAllTypesNano.FOO, msg.repeatedPackedNestedEnum[0]); - assertEquals(TestAllTypesNano.BAR, msg.repeatedPackedNestedEnum[1]); - assertEquals(TestAllTypesNano.BAZ, msg.repeatedPackedNestedEnum[2]); - msg.clear(); - assertEquals(0, msg.repeatedPackedNestedEnum.length); - msg.clear() - .repeatedPackedNestedEnum = new int[] { TestAllTypesNano.BAR }; - assertEquals(1, msg.repeatedPackedNestedEnum.length); - assertEquals(TestAllTypesNano.BAR, msg.repeatedPackedNestedEnum[0]); - msg.clear(); - assertEquals(0, msg.repeatedPackedNestedEnum.length); - - // Test 1 entry - msg.clear() - .repeatedPackedNestedEnum = new int[] { TestAllTypesNano.FOO }; - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 7); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(1, newMsg.repeatedPackedNestedEnum.length); - assertEquals(TestAllTypesNano.FOO, msg.repeatedPackedNestedEnum[0]); - - // Test 2 entries - msg.clear() - .repeatedPackedNestedEnum = new int[] { TestAllTypesNano.FOO, TestAllTypesNano.BAR }; - assertEquals(2, msg.repeatedPackedNestedEnum.length); - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 8); - assertEquals(result.length, msgSerializedSize); - - newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(2, newMsg.repeatedPackedNestedEnum.length); - assertEquals(TestAllTypesNano.FOO, msg.repeatedPackedNestedEnum[0]); - assertEquals(TestAllTypesNano.BAR, msg.repeatedPackedNestedEnum[1]); - } - - public void testNanoRepeatedPackedSerializedSize() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.repeatedPackedInt32 = new int[] { 123, 789, 456 }; - int msgSerializedSize = msg.getSerializedSize(); - byte [] result = MessageNano.toByteArray(msg); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 11); - assertEquals(result.length, msgSerializedSize); - TestAllTypesNano msg2 = new TestAllTypesNano(); - msg2.repeatedPackedInt32 = new int[] { 123, 789, 456 }; - byte [] result2 = new byte[msgSerializedSize]; - MessageNano.toByteArray(msg2, result2, 0, msgSerializedSize); - - // Check equal size and content. - assertEquals(msgSerializedSize, msg2.getSerializedSize()); - assertTrue(Arrays.equals(result, result2)); - } - - public void testNanoRepeatedInt32ReMerge() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.repeatedInt32 = new int[] { 234 }; - byte [] result1 = MessageNano.toByteArray(msg); - - msg.clear().optionalInt32 = 789; - byte [] result2 = MessageNano.toByteArray(msg); - - msg.clear().repeatedInt32 = new int[] { 123, 456 }; - byte [] result3 = MessageNano.toByteArray(msg); - - // Concatenate the three serializations and read as one message. - byte [] result = new byte[result1.length + result2.length + result3.length]; - System.arraycopy(result1, 0, result, 0, result1.length); - System.arraycopy(result2, 0, result, result1.length, result2.length); - System.arraycopy(result3, 0, result, result1.length + result2.length, result3.length); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(789, newMsg.optionalInt32); - assertEquals(3, newMsg.repeatedInt32.length); - assertEquals(234, newMsg.repeatedInt32[0]); - assertEquals(123, newMsg.repeatedInt32[1]); - assertEquals(456, newMsg.repeatedInt32[2]); - } - - public void testNanoRepeatedNestedEnumReMerge() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.repeatedNestedEnum = new int[] { TestAllTypesNano.FOO }; - byte [] result1 = MessageNano.toByteArray(msg); - - msg.clear().optionalInt32 = 789; - byte [] result2 = MessageNano.toByteArray(msg); - - msg.clear().repeatedNestedEnum = new int[] { TestAllTypesNano.BAR, TestAllTypesNano.FOO }; - byte [] result3 = MessageNano.toByteArray(msg); - - // Concatenate the three serializations and read as one message. - byte [] result = new byte[result1.length + result2.length + result3.length]; - System.arraycopy(result1, 0, result, 0, result1.length); - System.arraycopy(result2, 0, result, result1.length, result2.length); - System.arraycopy(result3, 0, result, result1.length + result2.length, result3.length); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(789, newMsg.optionalInt32); - assertEquals(3, newMsg.repeatedNestedEnum.length); - assertEquals(TestAllTypesNano.FOO, newMsg.repeatedNestedEnum[0]); - assertEquals(TestAllTypesNano.BAR, newMsg.repeatedNestedEnum[1]); - assertEquals(TestAllTypesNano.FOO, newMsg.repeatedNestedEnum[2]); - } - - public void testNanoRepeatedNestedMessageReMerge() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - TestAllTypesNano.NestedMessage nestedMsg0 = - new TestAllTypesNano.NestedMessage(); - nestedMsg0.bb = 0; - TestAllTypesNano.NestedMessage nestedMsg1 = - new TestAllTypesNano.NestedMessage(); - nestedMsg1.bb = 1; - TestAllTypesNano.NestedMessage nestedMsg2 = - new TestAllTypesNano.NestedMessage(); - nestedMsg2.bb = 2; - - msg.repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { nestedMsg0 }; - byte [] result1 = MessageNano.toByteArray(msg); - - msg.clear().optionalInt32 = 789; - byte [] result2 = MessageNano.toByteArray(msg); - - msg.clear().repeatedNestedMessage = - new TestAllTypesNano.NestedMessage[] { nestedMsg1, nestedMsg2 }; - byte [] result3 = MessageNano.toByteArray(msg); - - // Concatenate the three serializations and read as one message. - byte [] result = new byte[result1.length + result2.length + result3.length]; - System.arraycopy(result1, 0, result, 0, result1.length); - System.arraycopy(result2, 0, result, result1.length, result2.length); - System.arraycopy(result3, 0, result, result1.length + result2.length, result3.length); - - TestAllTypesNano newMsg = TestAllTypesNano.parseFrom(result); - assertEquals(789, newMsg.optionalInt32); - assertEquals(3, newMsg.repeatedNestedMessage.length); - assertEquals(nestedMsg0.bb, newMsg.repeatedNestedMessage[0].bb); - assertEquals(nestedMsg1.bb, newMsg.repeatedNestedMessage[1].bb); - assertEquals(nestedMsg2.bb, newMsg.repeatedNestedMessage[2].bb); - } - - /** - * Tests that invalid enum values from the wire are not accepted. - */ - public void testNanoEnumValidity() throws Exception { - final int invalid = 120; - final int alsoInvalid = 121; - - EnumValidity.M m = new EnumValidity.M(); - // Sanity check & baseline of the assertions for the first case below. - assertEquals(EnumValidity.E.default_, m.optionalE); - assertEquals(EnumValidity.E.BAZ, m.defaultE); - - m.optionalE = invalid; - m.defaultE = invalid; - // E contains all valid values - m.repeatedE = new int[] {EnumValidity.E.FOO, EnumValidity.E.BAR}; - m.packedE = new int[] {EnumValidity.E.FOO, EnumValidity.E.BAZ}; - // E2 contains some invalid values - m.repeatedE2 = new int[] {invalid, EnumValidity.E.BAR, alsoInvalid}; - m.packedE2 = new int[] {EnumValidity.E.FOO, invalid, alsoInvalid}; - // E3 contains all invalid values - m.repeatedE3 = new int[] {invalid, invalid}; - m.packedE3 = new int[] {alsoInvalid, alsoInvalid}; - byte[] serialized = MessageNano.toByteArray(m); - // Sanity check that we do have all data in the byte array. - assertEquals(31, serialized.length); - - // Test 1: tests that invalid values aren't included in the deserialized message. - EnumValidity.M deserialized = MessageNano.mergeFrom(new EnumValidity.M(), serialized); - assertEquals(EnumValidity.E.default_, deserialized.optionalE); - assertEquals(EnumValidity.E.BAZ, deserialized.defaultE); - assertTrue(Arrays.equals( - new int[] {EnumValidity.E.FOO, EnumValidity.E.BAR}, deserialized.repeatedE)); - assertTrue(Arrays.equals( - new int[] {EnumValidity.E.FOO, EnumValidity.E.BAZ}, deserialized.packedE)); - assertTrue(Arrays.equals( - new int[] {EnumValidity.E.BAR}, deserialized.repeatedE2)); - assertTrue(Arrays.equals( - new int[] {EnumValidity.E.FOO}, deserialized.packedE2)); - assertEquals(0, deserialized.repeatedE3.length); - assertEquals(0, deserialized.packedE3.length); - - // Test 2: tests that invalid values do not override previous values in the field, including - // arrays, including pre-existing invalid values. - deserialized.optionalE = EnumValidity.E.BAR; - deserialized.defaultE = alsoInvalid; - deserialized.repeatedE = new int[] {EnumValidity.E.BAZ}; - deserialized.packedE = new int[] {EnumValidity.E.BAZ, alsoInvalid}; - deserialized.repeatedE2 = new int[] {invalid, alsoInvalid}; - deserialized.packedE2 = null; - deserialized.repeatedE3 = null; - deserialized.packedE3 = new int[0]; - MessageNano.mergeFrom(deserialized, serialized); - assertEquals(EnumValidity.E.BAR, deserialized.optionalE); - assertEquals(alsoInvalid, deserialized.defaultE); - assertTrue(Arrays.equals( - new int[] {EnumValidity.E.BAZ, /* + */ EnumValidity.E.FOO, EnumValidity.E.BAR}, - deserialized.repeatedE)); - assertTrue(Arrays.equals( - new int[] {EnumValidity.E.BAZ, alsoInvalid, /* + */ EnumValidity.E.FOO, EnumValidity.E.BAZ}, - deserialized.packedE)); - assertTrue(Arrays.equals( - new int[] {invalid, alsoInvalid, /* + */ EnumValidity.E.BAR}, - deserialized.repeatedE2)); - assertTrue(Arrays.equals( - new int[] {/* + */ EnumValidity.E.FOO}, - deserialized.packedE2)); - assertNull(deserialized.repeatedE3); // null + all invalid == null - assertEquals(0, deserialized.packedE3.length); // empty + all invalid == empty - - // Test 3: reading by alternative forms - EnumValidity.Alt alt = MessageNano.mergeFrom(new EnumValidity.Alt(), serialized); - assertEquals(EnumValidity.E.BAR, // last valid value in m.repeatedE2 - alt.repeatedE2AsOptional); - assertTrue(Arrays.equals(new int[] {EnumValidity.E.FOO}, alt.packedE2AsNonPacked)); - assertEquals(0, alt.nonPackedE3AsPacked.length); - } - - /** - * Tests the same as {@link #testNanoEnumValidity()} with accessor style. Repeated fields are - * not re-tested here because they are not affected by the accessor style. - */ - public void testNanoEnumValidityAccessors() throws Exception { - final int invalid = 120; - final int alsoInvalid = 121; - - EnumValidityAccessors.M m = new EnumValidityAccessors.M(); - // Sanity check & baseline of the assertions for the first case below. - assertEquals(EnumValidityAccessors.default_, m.getOptionalE()); - assertEquals(EnumValidityAccessors.BAZ, m.getDefaultE()); - - m.setOptionalE(invalid); - m.setDefaultE(invalid); - // Set repeatedE2 for Alt.repeatedE2AsOptional - m.repeatedE2 = new int[] {invalid, EnumValidityAccessors.BAR, alsoInvalid}; - byte[] serialized = MessageNano.toByteArray(m); - // Sanity check that we do have all data in the byte array. - assertEquals(10, serialized.length); - - // Test 1: tests that invalid values aren't included in the deserialized message. - EnumValidityAccessors.M deserialized = - MessageNano.mergeFrom(new EnumValidityAccessors.M(), serialized); - assertEquals(EnumValidityAccessors.default_, deserialized.getOptionalE()); - assertEquals(EnumValidityAccessors.BAZ, deserialized.getDefaultE()); - - // Test 2: tests that invalid values do not override previous values in the field, including - // pre-existing invalid values. - deserialized.setOptionalE(EnumValidityAccessors.BAR); - deserialized.setDefaultE(alsoInvalid); - MessageNano.mergeFrom(deserialized, serialized); - assertEquals(EnumValidityAccessors.BAR, deserialized.getOptionalE()); - assertEquals(alsoInvalid, deserialized.getDefaultE()); - - // Test 3: reading by alternative forms - EnumValidityAccessors.Alt alt = - MessageNano.mergeFrom(new EnumValidityAccessors.Alt(), serialized); - assertEquals(EnumValidityAccessors.BAR, // last valid value in m.repeatedE2 - alt.getRepeatedE2AsOptional()); - } - - /** - * Tests that code generation correctly wraps a single message into its outer - * class. The class {@code SingleMessageNano} is imported from the outer - * class {@code UnittestSingleNano}, whose name is implicit. Any error would - * cause this method to fail compilation. - */ - public void testNanoSingle() throws Exception { - SingleMessageNano msg = new SingleMessageNano(); - assertNotNull(msg); - } - - /** - * Tests that code generation correctly skips generating the outer class if - * unnecessary, letting a file-scope entity have the same name. The class - * {@code MultipleNameClashNano} shares the same name with the file's outer - * class defined explicitly, but the file contains no other entities and has - * java_multiple_files set. Any error would cause this method to fail - * compilation. - */ - public void testNanoMultipleNameClash() throws Exception { - MultipleNameClashNano msg = new MultipleNameClashNano(); - msg.field = 0; - } - - /** - * Tests that code generation correctly handles enums in different scopes in - * a source file with the option java_multiple_files set to true. Any error - * would cause this method to fail compilation. - */ - public void testNanoMultipleEnumScoping() throws Exception { - FileScopeEnumRefNano msg1 = new FileScopeEnumRefNano(); - msg1.enumField = UnittestMultipleNano.ONE; - MessageScopeEnumRefNano msg2 = new MessageScopeEnumRefNano(); - msg2.enumField = MessageScopeEnumRefNano.TWO; - } - - /** - * Tests that code generation with mixed values of the java_multiple_files - * options between the main source file and the imported source files would - * generate correct references. Any error would cause this method to fail - * compilation. - */ - public void testNanoMultipleImportingNonMultiple() throws Exception { - UnittestImportNano.ImportMessageNano importMsg = new UnittestImportNano.ImportMessageNano(); - MultipleImportingNonMultipleNano1 nano1 = new MultipleImportingNonMultipleNano1(); - nano1.field = importMsg; - MultipleImportingNonMultipleNano2 nano2 = new MultipleImportingNonMultipleNano2(); - nano2.nano1 = nano1; - } - - public void testNanoDefaults() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - for (int i = 0; i < 2; i++) { - assertEquals(41, msg.defaultInt32); - assertEquals(42, msg.defaultInt64); - assertEquals(43, msg.defaultUint32); - assertEquals(44, msg.defaultUint64); - assertEquals(-45, msg.defaultSint32); - assertEquals(46, msg.defaultSint64); - assertEquals(47, msg.defaultFixed32); - assertEquals(48, msg.defaultFixed64); - assertEquals(49, msg.defaultSfixed32); - assertEquals(-50, msg.defaultSfixed64); - assertTrue(51.5f == msg.defaultFloat); - assertTrue(52.0e3 == msg.defaultDouble); - assertEquals(true, msg.defaultBool); - assertEquals("hello", msg.defaultString); - assertEquals("world", new String(msg.defaultBytes, InternalNano.UTF_8)); - assertEquals("dünya", msg.defaultStringNonascii); - assertEquals("dünyab", new String(msg.defaultBytesNonascii, InternalNano.UTF_8)); - assertEquals(TestAllTypesNano.BAR, msg.defaultNestedEnum); - assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.defaultForeignEnum); - assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.defaultImportEnum); - assertEquals(Float.POSITIVE_INFINITY, msg.defaultFloatInf); - assertEquals(Float.NEGATIVE_INFINITY, msg.defaultFloatNegInf); - assertEquals(Float.NaN, msg.defaultFloatNan); - assertEquals(Double.POSITIVE_INFINITY, msg.defaultDoubleInf); - assertEquals(Double.NEGATIVE_INFINITY, msg.defaultDoubleNegInf); - assertEquals(Double.NaN, msg.defaultDoubleNan); - - // Default values are not output, except for required fields. - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 3); - assertEquals(result.length, msgSerializedSize); - msg.clear(); - } - } - - public void testDifferentStringLengthsNano() throws Exception { - // Test string serialization roundtrip using strings of the following lengths, - // with ASCII and Unicode characters requiring different UTF-8 byte counts per - // char, hence causing the length delimiter varint to sometimes require more - // bytes for the Unicode strings than the ASCII string of the same length. - int[] lengths = new int[] { - 0, - 1, - (1 << 4) - 1, // 1 byte for ASCII and Unicode - (1 << 7) - 1, // 1 byte for ASCII, 2 bytes for Unicode - (1 << 11) - 1, // 2 bytes for ASCII and Unicode - (1 << 14) - 1, // 2 bytes for ASCII, 3 bytes for Unicode - (1 << 17) - 1, // 3 bytes for ASCII and Unicode - }; - for (int i : lengths) { - testEncodingOfString('q', i); // 1 byte per char - testEncodingOfString('\u07FF', i); // 2 bytes per char - testEncodingOfString('\u0981', i); // 3 bytes per char - } - } - - /** Regression test for https://github.com/google/protobuf/issues/292 */ - public void testCorrectExceptionThrowWhenEncodingStringsWithoutEnoughSpace() throws Exception { - String testCase = "Foooooooo"; - assertEquals(CodedOutputByteBufferNano.computeRawVarint32Size(testCase.length()), - CodedOutputByteBufferNano.computeRawVarint32Size(testCase.length() * 3)); - assertEquals(11, CodedOutputByteBufferNano.computeStringSize(1, testCase)); - // Tag is one byte, varint describing string length is 1 byte, string length is 9 bytes. - // An array of size 1 will cause a failure when trying to write the varint. - for (int i = 0; i < 11; i++) { - CodedOutputByteBufferNano bufferNano = CodedOutputByteBufferNano.newInstance(new byte[i]); - try { - bufferNano.writeString(1, testCase); - fail("Should have thrown an out of space exception"); - } catch (CodedOutputByteBufferNano.OutOfSpaceException expected) {} - } - } - - private void testEncodingOfString(char c, int length) throws InvalidProtocolBufferNanoException { - TestAllTypesNano testAllTypesNano = new TestAllTypesNano(); - final String fullString = fullString(c, length); - testAllTypesNano.optionalString = fullString; - final TestAllTypesNano resultNano = new TestAllTypesNano(); - MessageNano.mergeFrom(resultNano, MessageNano.toByteArray(testAllTypesNano)); - assertEquals(fullString, resultNano.optionalString); - } - - private String fullString(char c, int length) { - char[] result = new char[length]; - Arrays.fill(result, c); - return new String(result); - } - - public void testNanoWithHasParseFrom() throws Exception { - TestAllTypesNanoHas msg = null; - // Test false on creation, after clear and upon empty parse. - for (int i = 0; i < 3; i++) { - if (i == 0) { - msg = new TestAllTypesNanoHas(); - } else if (i == 1) { - msg.clear(); - } else if (i == 2) { - msg = TestAllTypesNanoHas.parseFrom(new byte[0]); - } - assertFalse(msg.hasOptionalInt32); - assertFalse(msg.hasOptionalString); - assertFalse(msg.hasOptionalBytes); - assertFalse(msg.hasOptionalNestedEnum); - assertFalse(msg.hasDefaultInt32); - assertFalse(msg.hasDefaultString); - assertFalse(msg.hasDefaultBytes); - assertFalse(msg.hasDefaultFloatNan); - assertFalse(msg.hasDefaultNestedEnum); - assertFalse(msg.hasId); - assertFalse(msg.hasRequiredEnum); - msg.optionalInt32 = 123; - msg.optionalNestedMessage = new TestAllTypesNanoHas.NestedMessage(); - msg.optionalNestedMessage.bb = 2; - msg.optionalNestedEnum = TestAllTypesNano.BAZ; - } - - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 10); - assertEquals(result.length, msgSerializedSize); - - // Has fields true upon parse. - TestAllTypesNanoHas newMsg = TestAllTypesNanoHas.parseFrom(result); - assertEquals(123, newMsg.optionalInt32); - assertTrue(newMsg.hasOptionalInt32); - assertEquals(2, newMsg.optionalNestedMessage.bb); - assertTrue(newMsg.optionalNestedMessage.hasBb); - assertEquals(TestAllTypesNanoHas.BAZ, newMsg.optionalNestedEnum); - assertTrue(newMsg.hasOptionalNestedEnum); - } - - public void testNanoWithHasSerialize() throws Exception { - TestAllTypesNanoHas msg = new TestAllTypesNanoHas(); - msg.hasOptionalInt32 = true; - msg.hasOptionalString = true; - msg.hasOptionalBytes = true; - msg.optionalNestedMessage = new TestAllTypesNanoHas.NestedMessage(); - msg.optionalNestedMessage.hasBb = true; - msg.hasOptionalNestedEnum = true; - msg.hasDefaultInt32 = true; - msg.hasDefaultString = true; - msg.hasDefaultBytes = true; - msg.hasDefaultFloatNan = true; - msg.hasDefaultNestedEnum = true; - msg.hasId = true; - msg.hasRequiredEnum = true; - - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - assertEquals(result.length, msgSerializedSize); - - // Now deserialize and find that all fields are set and equal to their defaults. - TestAllTypesNanoHas newMsg = TestAllTypesNanoHas.parseFrom(result); - assertTrue(newMsg.hasOptionalInt32); - assertTrue(newMsg.hasOptionalString); - assertTrue(newMsg.hasOptionalBytes); - assertTrue(newMsg.optionalNestedMessage.hasBb); - assertTrue(newMsg.hasOptionalNestedEnum); - assertTrue(newMsg.hasDefaultInt32); - assertTrue(newMsg.hasDefaultString); - assertTrue(newMsg.hasDefaultBytes); - assertTrue(newMsg.hasDefaultFloatNan); - assertTrue(newMsg.hasDefaultNestedEnum); - assertTrue(newMsg.hasId); - assertTrue(newMsg.hasRequiredEnum); - assertEquals(0, newMsg.optionalInt32); - assertEquals(0, newMsg.optionalString.length()); - assertEquals(0, newMsg.optionalBytes.length); - assertEquals(0, newMsg.optionalNestedMessage.bb); - assertEquals(TestAllTypesNanoHas.FOO, newMsg.optionalNestedEnum); - assertEquals(41, newMsg.defaultInt32); - assertEquals("hello", newMsg.defaultString); - assertEquals("world", new String(newMsg.defaultBytes, InternalNano.UTF_8)); - assertEquals(TestAllTypesNanoHas.BAR, newMsg.defaultNestedEnum); - assertEquals(Float.NaN, newMsg.defaultFloatNan); - assertEquals(0, newMsg.id); - assertEquals(TestAllTypesNanoHas.FOO, newMsg.requiredEnum); - } - - public void testNanoWithAccessorsBasic() throws Exception { - TestNanoAccessors msg = new TestNanoAccessors(); - - // Makes sure required, repeated, and message fields are still public - msg.id = 3; - msg.repeatedBytes = new byte[2][3]; - msg.optionalNestedMessage = null; - - // Test accessors - assertEquals(0, msg.getOptionalInt32()); - assertFalse(msg.hasOptionalInt32()); - msg.setOptionalInt32(135); - assertEquals(135, msg.getOptionalInt32()); - assertTrue(msg.hasOptionalInt32()); - msg.clearOptionalInt32(); - assertFalse(msg.hasOptionalInt32()); - msg.setOptionalInt32(0); // default value - assertTrue(msg.hasOptionalInt32()); - - // Test NPE - try { - msg.setOptionalBytes(null); - fail(); - } catch (NullPointerException expected) {} - try { - msg.setOptionalString(null); - fail(); - } catch (NullPointerException expected) {} - - // Test has bit on bytes field with defaults and clear() re-clones the default array - assertFalse(msg.hasDefaultBytes()); - byte[] defaultBytes = msg.getDefaultBytes(); - msg.setDefaultBytes(defaultBytes); - assertTrue(msg.hasDefaultBytes()); - msg.clearDefaultBytes(); - assertFalse(msg.hasDefaultBytes()); - defaultBytes[0]++; // modify original array - assertFalse(Arrays.equals(defaultBytes, msg.getDefaultBytes())); - - // Test has bits that require additional bit fields - assertFalse(msg.hasBitFieldCheck()); - msg.setBitFieldCheck(0); - assertTrue(msg.hasBitFieldCheck()); - assertFalse(msg.hasBeforeBitFieldCheck()); // checks bit field does not leak - assertFalse(msg.hasAfterBitFieldCheck()); - - // Test clear() clears has bits - msg.setOptionalString("hi"); - msg.setDefaultString("there"); - msg.clear(); - assertFalse(msg.hasOptionalString()); - assertFalse(msg.hasDefaultString()); - assertFalse(msg.hasBitFieldCheck()); - - // Test set() and clear() returns itself (compiles = success) - msg.clear() - .setOptionalInt32(3) - .clearDefaultBytes() - .setOptionalString("4"); - } - - public void testNanoWithAccessorsParseFrom() throws Exception { - TestNanoAccessors msg = null; - // Test false on creation, after clear and upon empty parse. - for (int i = 0; i < 3; i++) { - if (i == 0) { - msg = new TestNanoAccessors(); - } else if (i == 1) { - msg.clear(); - } else if (i == 2) { - msg = TestNanoAccessors.parseFrom(new byte[0]); - } - assertFalse(msg.hasOptionalInt32()); - assertFalse(msg.hasOptionalString()); - assertFalse(msg.hasOptionalBytes()); - assertFalse(msg.hasOptionalNestedEnum()); - assertFalse(msg.hasDefaultInt32()); - assertFalse(msg.hasDefaultString()); - assertFalse(msg.hasDefaultBytes()); - assertFalse(msg.hasDefaultFloatNan()); - assertFalse(msg.hasDefaultNestedEnum()); - msg.optionalNestedMessage = new TestNanoAccessors.NestedMessage(); - msg.optionalNestedMessage.setBb(2); - msg.setOptionalNestedEnum(TestNanoAccessors.BAZ); - msg.setDefaultInt32(msg.getDefaultInt32()); - } - - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length); - assertTrue(msgSerializedSize == 14); - assertEquals(result.length, msgSerializedSize); - - // Has fields true upon parse. - TestNanoAccessors newMsg = TestNanoAccessors.parseFrom(result); - assertEquals(2, newMsg.optionalNestedMessage.getBb()); - assertTrue(newMsg.optionalNestedMessage.hasBb()); - assertEquals(TestNanoAccessors.BAZ, newMsg.getOptionalNestedEnum()); - assertTrue(newMsg.hasOptionalNestedEnum()); - - // Has field true on fields with explicit default values from wire. - assertTrue(newMsg.hasDefaultInt32()); - assertEquals(41, newMsg.getDefaultInt32()); - } - - public void testNanoWithAccessorsPublicFieldTypes() throws Exception { - TestNanoAccessors msg = new TestNanoAccessors(); - assertNull(msg.optionalNestedMessage); - assertEquals(0, msg.id); - assertEquals(0, msg.repeatedNestedEnum.length); - - TestNanoAccessors newMsg = TestNanoAccessors.parseFrom(MessageNano.toByteArray(msg)); - assertNull(newMsg.optionalNestedMessage); - assertEquals(0, newMsg.id); - assertEquals(0, newMsg.repeatedNestedEnum.length); - - TestNanoAccessors.NestedMessage nestedMessage = new TestNanoAccessors.NestedMessage(); - nestedMessage.setBb(5); - newMsg.optionalNestedMessage = nestedMessage; - newMsg.id = -1; - newMsg.repeatedNestedEnum = new int[] { TestAllTypesNano.FOO }; - - TestNanoAccessors newMsg2 = TestNanoAccessors.parseFrom(MessageNano.toByteArray(newMsg)); - assertEquals(nestedMessage.getBb(), newMsg2.optionalNestedMessage.getBb()); - assertEquals(-1, newMsg2.id); - assertEquals(TestAllTypesNano.FOO, newMsg2.repeatedNestedEnum[0]); - - newMsg2.optionalNestedMessage = null; - newMsg2.id = 0; - newMsg2.repeatedNestedEnum = null; - - TestNanoAccessors newMsg3 = TestNanoAccessors.parseFrom(MessageNano.toByteArray(newMsg2)); - assertNull(newMsg3.optionalNestedMessage); - assertEquals(0, newMsg3.id); - assertEquals(0, newMsg3.repeatedNestedEnum.length); - } - - public void testNanoWithAccessorsSerialize() throws Exception { - TestNanoAccessors msg = new TestNanoAccessors(); - msg.setOptionalInt32(msg.getOptionalInt32()); - msg.setOptionalString(msg.getOptionalString()); - msg.setOptionalBytes(msg.getOptionalBytes()); - TestNanoAccessors.NestedMessage nestedMessage = new TestNanoAccessors.NestedMessage(); - nestedMessage.setBb(nestedMessage.getBb()); - msg.optionalNestedMessage = nestedMessage; - msg.setOptionalNestedEnum(msg.getOptionalNestedEnum()); - msg.setDefaultInt32(msg.getDefaultInt32()); - msg.setDefaultString(msg.getDefaultString()); - msg.setDefaultBytes(msg.getDefaultBytes()); - msg.setDefaultFloatNan(msg.getDefaultFloatNan()); - msg.setDefaultNestedEnum(msg.getDefaultNestedEnum()); - - byte [] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - assertEquals(result.length, msgSerializedSize); - - // Now deserialize and find that all fields are set and equal to their defaults. - TestNanoAccessors newMsg = TestNanoAccessors.parseFrom(result); - assertTrue(newMsg.hasOptionalInt32()); - assertTrue(newMsg.hasOptionalString()); - assertTrue(newMsg.hasOptionalBytes()); - assertTrue(newMsg.optionalNestedMessage.hasBb()); - assertTrue(newMsg.hasOptionalNestedEnum()); - assertTrue(newMsg.hasDefaultInt32()); - assertTrue(newMsg.hasDefaultString()); - assertTrue(newMsg.hasDefaultBytes()); - assertTrue(newMsg.hasDefaultFloatNan()); - assertTrue(newMsg.hasDefaultNestedEnum()); - assertEquals(0, newMsg.getOptionalInt32()); - assertEquals(0, newMsg.getOptionalString().length()); - assertEquals(0, newMsg.getOptionalBytes().length); - assertEquals(0, newMsg.optionalNestedMessage.getBb()); - assertEquals(TestNanoAccessors.FOO, newMsg.getOptionalNestedEnum()); - assertEquals(41, newMsg.getDefaultInt32()); - assertEquals("hello", newMsg.getDefaultString()); - assertEquals("world", new String(newMsg.getDefaultBytes(), InternalNano.UTF_8)); - assertEquals(TestNanoAccessors.BAR, newMsg.getDefaultNestedEnum()); - assertEquals(Float.NaN, newMsg.getDefaultFloatNan()); - assertEquals(0, newMsg.id); - } - - public void testNanoJavaEnumStyle() throws Exception { - EnumClassNanos.EnumClassNano msg = new EnumClassNanos.EnumClassNano(); - assertEquals(EnumClassNanos.FileScopeEnum.ONE, msg.one); - assertEquals(EnumClassNanos.EnumClassNano.MessageScopeEnum.TWO, msg.two); - - EnumClassNanoMultiple msg2 = new EnumClassNanoMultiple(); - assertEquals(FileScopeEnumMultiple.THREE, msg2.three); - assertEquals(EnumClassNanoMultiple.MessageScopeEnumMultiple.FOUR, msg2.four); - } - - /** - * Tests that fields with a default value of NaN are not serialized when - * set to NaN. This is a special case as NaN != NaN, so normal equality - * checks don't work. - */ - public void testNanoNotANumberDefaults() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.defaultDoubleNan = 0; - msg.defaultFloatNan = 0; - byte[] result = MessageNano.toByteArray(msg); - int msgSerializedSize = msg.getSerializedSize(); - assertTrue(result.length == msgSerializedSize); - assertTrue(msgSerializedSize > 3); - - msg.defaultDoubleNan = Double.NaN; - msg.defaultFloatNan = Float.NaN; - result = MessageNano.toByteArray(msg); - msgSerializedSize = msg.getSerializedSize(); - assertEquals(3, result.length); - assertEquals(3, msgSerializedSize); - } - - /** - * Test that a bug in skipRawBytes() has been fixed: if the skip skips - * exactly up to a limit, this should not break things. - */ - public void testSkipRawBytesBug() throws Exception { - byte[] rawBytes = new byte[] { 1, 2 }; - CodedInputByteBufferNano input = CodedInputByteBufferNano.newInstance(rawBytes); - - int limit = input.pushLimit(1); - input.skipRawBytes(1); - input.popLimit(limit); - assertEquals(2, input.readRawByte()); - } - - /** - * Test that a bug in skipRawBytes() has been fixed: if the skip skips - * past the end of a buffer with a limit that has been set past the end of - * that buffer, this should not break things. - */ - public void testSkipRawBytesPastEndOfBufferWithLimit() throws Exception { - byte[] rawBytes = new byte[] { 1, 2, 3, 4, 5 }; - CodedInputByteBufferNano input = CodedInputByteBufferNano.newInstance(rawBytes); - - int limit = input.pushLimit(4); - // In order to expose the bug we need to read at least one byte to prime the - // buffer inside the CodedInputStream. - assertEquals(1, input.readRawByte()); - // Skip to the end of the limit. - input.skipRawBytes(3); - assertTrue(input.isAtEnd()); - input.popLimit(limit); - assertEquals(5, input.readRawByte()); - } - - // Test a smattering of various proto types for printing - public void testMessageNanoPrinter() { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.optionalInt32 = 14; - msg.optionalFloat = 42.3f; - msg.optionalString = "String \"with' both quotes"; - msg.optionalBytes = new byte[] {'"', '\0', 1, 8}; - msg.optionalGroup = new TestAllTypesNano.OptionalGroup(); - msg.optionalGroup.a = 15; - msg.repeatedInt64 = new long[2]; - msg.repeatedInt64[0] = 1L; - msg.repeatedInt64[1] = -1L; - msg.repeatedBytes = new byte[2][]; - msg.repeatedBytes[1] = new byte[] {'h', 'e', 'l', 'l', 'o'}; - msg.repeatedGroup = new TestAllTypesNano.RepeatedGroup[2]; - msg.repeatedGroup[0] = new TestAllTypesNano.RepeatedGroup(); - msg.repeatedGroup[0].a = -27; - msg.repeatedGroup[1] = new TestAllTypesNano.RepeatedGroup(); - msg.repeatedGroup[1].a = -72; - msg.optionalNestedMessage = new TestAllTypesNano.NestedMessage(); - msg.optionalNestedMessage.bb = 7; - msg.repeatedNestedMessage = new TestAllTypesNano.NestedMessage[2]; - msg.repeatedNestedMessage[0] = new TestAllTypesNano.NestedMessage(); - msg.repeatedNestedMessage[0].bb = 77; - msg.repeatedNestedMessage[1] = new TestAllTypesNano.NestedMessage(); - msg.repeatedNestedMessage[1].bb = 88; - msg.optionalNestedEnum = TestAllTypesNano.BAZ; - msg.repeatedNestedEnum = new int[2]; - msg.repeatedNestedEnum[0] = TestAllTypesNano.BAR; - msg.repeatedNestedEnum[1] = TestAllTypesNano.FOO; - msg.repeatedStringPiece = new String[] {null, "world"}; - msg.setOneofString("hello"); - - String protoPrint = msg.toString(); - assertTrue(protoPrint.contains("optional_int32: 14")); - assertTrue(protoPrint.contains("optional_float: 42.3")); - assertTrue(protoPrint.contains("optional_double: 0.0")); - assertTrue(protoPrint.contains("optional_string: \"String \\u0022with\\u0027 both quotes\"")); - assertTrue(protoPrint.contains("optional_bytes: \"\\\"\\000\\001\\010\"")); - assertTrue(protoPrint.contains("optional_group <\n a: 15\n>")); - - assertTrue(protoPrint.contains("repeated_int64: 1\nrepeated_int64: -1")); - assertFalse(protoPrint.contains("repeated_bytes: \"\"")); // null should be dropped - assertTrue(protoPrint.contains("repeated_bytes: \"hello\"")); - assertTrue(protoPrint.contains("repeated_group <\n a: -27\n>\n" - + "repeated_group <\n a: -72\n>")); - assertTrue(protoPrint.contains("optional_nested_message <\n bb: 7\n>")); - assertTrue(protoPrint.contains("repeated_nested_message <\n bb: 77\n>\n" - + "repeated_nested_message <\n bb: 88\n>")); - assertTrue(protoPrint.contains("optional_nested_enum: 3")); - assertTrue(protoPrint.contains("repeated_nested_enum: 2\nrepeated_nested_enum: 1")); - assertTrue(protoPrint.contains("default_int32: 41")); - assertTrue(protoPrint.contains("default_string: \"hello\"")); - assertFalse(protoPrint.contains("repeated_string_piece: \"\"")); // null should be dropped - assertTrue(protoPrint.contains("repeated_string_piece: \"world\"")); - assertTrue(protoPrint.contains("oneof_string: \"hello\"")); - } - - public void testMessageNanoPrinterAccessors() throws Exception { - TestNanoAccessors msg = new TestNanoAccessors(); - msg.setOptionalInt32(13); - msg.setOptionalString("foo"); - msg.setOptionalBytes(new byte[] {'"', '\0', 1, 8}); - msg.optionalNestedMessage = new TestNanoAccessors.NestedMessage(); - msg.optionalNestedMessage.setBb(7); - msg.setOptionalNestedEnum(TestNanoAccessors.BAZ); - msg.repeatedInt32 = new int[] { 1, -1 }; - msg.repeatedString = new String[] { "Hello", "world" }; - msg.repeatedBytes = new byte[2][]; - msg.repeatedBytes[1] = new byte[] {'h', 'e', 'l', 'l', 'o'}; - msg.repeatedNestedMessage = new TestNanoAccessors.NestedMessage[2]; - msg.repeatedNestedMessage[0] = new TestNanoAccessors.NestedMessage(); - msg.repeatedNestedMessage[0].setBb(5); - msg.repeatedNestedMessage[1] = new TestNanoAccessors.NestedMessage(); - msg.repeatedNestedMessage[1].setBb(6); - msg.repeatedNestedEnum = new int[] { TestNanoAccessors.FOO, TestNanoAccessors.BAR }; - msg.id = 33; - - String protoPrint = msg.toString(); - assertTrue(protoPrint.contains("optional_int32: 13")); - assertTrue(protoPrint.contains("optional_string: \"foo\"")); - assertTrue(protoPrint.contains("optional_bytes: \"\\\"\\000\\001\\010\"")); - assertTrue(protoPrint.contains("optional_nested_message <\n bb: 7\n>")); - assertTrue(protoPrint.contains("optional_nested_enum: 3")); - assertTrue(protoPrint.contains("repeated_int32: 1\nrepeated_int32: -1")); - assertTrue(protoPrint.contains("repeated_string: \"Hello\"\nrepeated_string: \"world\"")); - assertFalse(protoPrint.contains("repeated_bytes: \"\"")); // null should be dropped - assertTrue(protoPrint.contains("repeated_bytes: \"hello\"")); - assertTrue(protoPrint.contains("repeated_nested_message <\n bb: 5\n>\n" - + "repeated_nested_message <\n bb: 6\n>")); - assertTrue(protoPrint.contains("repeated_nested_enum: 1\nrepeated_nested_enum: 2")); - assertTrue(protoPrint.contains("id: 33")); - } - - public void testMessageNanoPrinterForMaps() throws Exception { - TestMap msg = new TestMap(); - MessageValue msgValues[] = new MessageValue[] { - new MessageValue(), new MessageValue() - }; - msgValues[0].value = 1; - msgValues[1].value = 2; - msg.int32ToBytesField = new HashMap(); - msg.int32ToBytesField.put(1, new byte[] {'"', '\0'}); - msg.int32ToBytesField.put(2, new byte[] {1, 8}); - msg.stringToInt32Field = new HashMap(); - msg.stringToInt32Field.put("hello", 1); - msg.stringToInt32Field.put("world", 2); - msg.int32ToMessageField = new HashMap(); - msg.int32ToMessageField.put(0, msgValues[0]); - msg.int32ToMessageField.put(1, msgValues[1]); - msg.int32ToEnumField = new HashMap(); - msg.int32ToEnumField.put(1, 2); - msg.int32ToEnumField.put(2, 3); - String protoPrint = msg.toString(); - - assertTrue(protoPrint.contains( - "int32_to_bytes_field <\n key: 1\n value: \"\\\"\\000\"\n>")); - assertTrue(protoPrint.contains( - "int32_to_bytes_field <\n key: 2\n value: \"\\001\\010\"\n>")); - assertTrue(protoPrint.contains( - "string_to_int32_field <\n key: \"hello\"\n value: 1\n>")); - assertTrue(protoPrint.contains( - "string_to_int32_field <\n key: \"world\"\n value: 2\n>")); - assertTrue(protoPrint.contains( - "int32_to_message_field <\n key: 0\n value <\n value: 1\n")); - assertTrue(protoPrint.contains( - "int32_to_message_field <\n key: 1\n value <\n value: 2\n")); - assertTrue(protoPrint.contains( - "int32_to_enum_field <\n key: 1\n value: 2\n>")); - assertTrue(protoPrint.contains( - "int32_to_enum_field <\n key: 2\n value: 3\n>")); - } - - public void testExtensions() throws Exception { - Extensions.ExtendableMessage message = new Extensions.ExtendableMessage(); - message.field = 5; - int[] int32s = {1, 2}; - int[] uint32s = {3, 4}; - int[] sint32s = {-5, -6}; - long[] int64s = {7, 8}; - long[] uint64s = {9, 10}; - long[] sint64s = {-11, -12}; - int[] fixed32s = {13, 14}; - int[] sfixed32s = {-15, -16}; - long[] fixed64s = {17, 18}; - long[] sfixed64s = {-19, -20}; - boolean[] bools = {true, false}; - float[] floats = {2.1f, 2.2f}; - double[] doubles = {2.3, 2.4}; - int[] enums = {Extensions.SECOND_VALUE, Extensions.FIRST_VALUE}; - String[] strings = {"vijfentwintig", "twenty-six"}; - byte[][] bytess = {{2, 7}, {2, 8}}; - AnotherMessage another1 = new AnotherMessage(); - another1.string = "er shi jiu"; - another1.value = false; - AnotherMessage another2 = new AnotherMessage(); - another2.string = "trente"; - another2.value = true; - AnotherMessage[] messages = {another1, another2}; - RepeatedExtensions.RepeatedGroup group1 = new RepeatedExtensions.RepeatedGroup(); - group1.a = 31; - RepeatedExtensions.RepeatedGroup group2 = new RepeatedExtensions.RepeatedGroup(); - group2.a = 32; - RepeatedExtensions.RepeatedGroup[] groups = {group1, group2}; - assertFalse(message.hasExtension(RepeatedExtensions.repeatedInt32)); - message.setExtension(RepeatedExtensions.repeatedInt32, int32s); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedInt32)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedUint32)); - message.setExtension(RepeatedExtensions.repeatedUint32, uint32s); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedUint32)); - message.setExtension(RepeatedExtensions.repeatedSint32, sint32s); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedInt64)); - message.setExtension(RepeatedExtensions.repeatedInt64, int64s); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedInt64)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedUint64)); - message.setExtension(RepeatedExtensions.repeatedUint64, uint64s); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedUint64)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedSint64)); - message.setExtension(RepeatedExtensions.repeatedSint64, sint64s); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedSint64)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedFixed32)); - message.setExtension(RepeatedExtensions.repeatedFixed32, fixed32s); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedFixed32)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedSfixed32)); - message.setExtension(RepeatedExtensions.repeatedSfixed32, sfixed32s); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedSfixed32)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedFixed64)); - message.setExtension(RepeatedExtensions.repeatedFixed64, fixed64s); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedFixed64)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedSfixed64)); - message.setExtension(RepeatedExtensions.repeatedSfixed64, sfixed64s); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedSfixed64)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedBool)); - message.setExtension(RepeatedExtensions.repeatedBool, bools); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedBool)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedFloat)); - message.setExtension(RepeatedExtensions.repeatedFloat, floats); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedFloat)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedDouble)); - message.setExtension(RepeatedExtensions.repeatedDouble, doubles); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedDouble)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedEnum)); - message.setExtension(RepeatedExtensions.repeatedEnum, enums); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedEnum)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedString)); - message.setExtension(RepeatedExtensions.repeatedString, strings); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedString)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedBytes)); - message.setExtension(RepeatedExtensions.repeatedBytes, bytess); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedBytes)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedMessage)); - message.setExtension(RepeatedExtensions.repeatedMessage, messages); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedMessage)); - assertFalse(message.hasExtension(RepeatedExtensions.repeatedGroup)); - message.setExtension(RepeatedExtensions.repeatedGroup, groups); - assertTrue(message.hasExtension(RepeatedExtensions.repeatedGroup)); - - byte[] data = MessageNano.toByteArray(message); - message = Extensions.ExtendableMessage.parseFrom(data); - assertEquals(5, message.field); - - // Test reading back using SingularExtensions: the retrieved value should equal the last - // in each array. - assertEquals(int32s[1], (int) message.getExtension(SingularExtensions.someInt32)); - assertEquals(uint32s[1], (int) message.getExtension(SingularExtensions.someUint32)); - assertEquals(sint32s[1], (int) message.getExtension(SingularExtensions.someSint32)); - assertEquals(int64s[1], (long) message.getExtension(SingularExtensions.someInt64)); - assertEquals(uint64s[1], (long) message.getExtension(SingularExtensions.someUint64)); - assertEquals(sint64s[1], (long) message.getExtension(SingularExtensions.someSint64)); - assertEquals(fixed32s[1], (int) message.getExtension(SingularExtensions.someFixed32)); - assertEquals(sfixed32s[1], (int) message.getExtension(SingularExtensions.someSfixed32)); - assertEquals(fixed64s[1], (long) message.getExtension(SingularExtensions.someFixed64)); - assertEquals(sfixed64s[1], (long) message.getExtension(SingularExtensions.someSfixed64)); - assertEquals(bools[1], (boolean) message.getExtension(SingularExtensions.someBool)); - assertEquals(floats[1], (float) message.getExtension(SingularExtensions.someFloat)); - assertEquals(doubles[1], (double) message.getExtension(SingularExtensions.someDouble)); - assertEquals(enums[1], (int) message.getExtension(SingularExtensions.someEnum)); - assertEquals(strings[1], message.getExtension(SingularExtensions.someString)); - assertTrue(Arrays.equals(bytess[1], message.getExtension(SingularExtensions.someBytes))); - AnotherMessage deserializedMessage = message.getExtension(SingularExtensions.someMessage); - assertEquals(another2.string, deserializedMessage.string); - assertEquals(another2.value, deserializedMessage.value); - assertEquals(group2.a, message.getExtension(SingularExtensions.someGroup).a); - - // Test reading back using RepeatedExtensions: the arrays should be equal. - message = Extensions.ExtendableMessage.parseFrom(data); - assertEquals(5, message.field); - assertTrue(Arrays.equals(int32s, message.getExtension(RepeatedExtensions.repeatedInt32))); - assertTrue(Arrays.equals(uint32s, message.getExtension(RepeatedExtensions.repeatedUint32))); - assertTrue(Arrays.equals(sint32s, message.getExtension(RepeatedExtensions.repeatedSint32))); - assertTrue(Arrays.equals(int64s, message.getExtension(RepeatedExtensions.repeatedInt64))); - assertTrue(Arrays.equals(uint64s, message.getExtension(RepeatedExtensions.repeatedUint64))); - assertTrue(Arrays.equals(sint64s, message.getExtension(RepeatedExtensions.repeatedSint64))); - assertTrue(Arrays.equals(fixed32s, message.getExtension(RepeatedExtensions.repeatedFixed32))); - assertTrue(Arrays.equals(sfixed32s, message.getExtension(RepeatedExtensions.repeatedSfixed32))); - assertTrue(Arrays.equals(fixed64s, message.getExtension(RepeatedExtensions.repeatedFixed64))); - assertTrue(Arrays.equals(sfixed64s, message.getExtension(RepeatedExtensions.repeatedSfixed64))); - assertTrue(Arrays.equals(bools, message.getExtension(RepeatedExtensions.repeatedBool))); - assertTrue(Arrays.equals(floats, message.getExtension(RepeatedExtensions.repeatedFloat))); - assertTrue(Arrays.equals(doubles, message.getExtension(RepeatedExtensions.repeatedDouble))); - assertTrue(Arrays.equals(enums, message.getExtension(RepeatedExtensions.repeatedEnum))); - assertTrue(Arrays.equals(strings, message.getExtension(RepeatedExtensions.repeatedString))); - byte[][] deserializedRepeatedBytes = message.getExtension(RepeatedExtensions.repeatedBytes); - assertEquals(2, deserializedRepeatedBytes.length); - assertTrue(Arrays.equals(bytess[0], deserializedRepeatedBytes[0])); - assertTrue(Arrays.equals(bytess[1], deserializedRepeatedBytes[1])); - AnotherMessage[] deserializedRepeatedMessage = - message.getExtension(RepeatedExtensions.repeatedMessage); - assertEquals(2, deserializedRepeatedMessage.length); - assertEquals(another1.string, deserializedRepeatedMessage[0].string); - assertEquals(another1.value, deserializedRepeatedMessage[0].value); - assertEquals(another2.string, deserializedRepeatedMessage[1].string); - assertEquals(another2.value, deserializedRepeatedMessage[1].value); - RepeatedExtensions.RepeatedGroup[] deserializedRepeatedGroup = - message.getExtension(RepeatedExtensions.repeatedGroup); - assertEquals(2, deserializedRepeatedGroup.length); - assertEquals(group1.a, deserializedRepeatedGroup[0].a); - assertEquals(group2.a, deserializedRepeatedGroup[1].a); - - message = Extensions.ExtendableMessage.parseFrom(data); - assertEquals(5, message.field); - // Test hasExtension using PackedExtensions. - assertTrue(message.hasExtension(PackedExtensions.packedInt32)); - assertTrue(message.hasExtension(PackedExtensions.packedUint32)); - assertTrue(message.hasExtension(PackedExtensions.packedSint32)); - assertTrue(message.hasExtension(PackedExtensions.packedInt64)); - assertTrue(message.hasExtension(PackedExtensions.packedUint64)); - assertTrue(message.hasExtension(PackedExtensions.packedSint64)); - assertTrue(message.hasExtension(PackedExtensions.packedFixed32)); - assertTrue(message.hasExtension(PackedExtensions.packedSfixed32)); - assertTrue(message.hasExtension(PackedExtensions.packedFixed64)); - assertTrue(message.hasExtension(PackedExtensions.packedSfixed64)); - assertTrue(message.hasExtension(PackedExtensions.packedBool)); - assertTrue(message.hasExtension(PackedExtensions.packedFloat)); - assertTrue(message.hasExtension(PackedExtensions.packedDouble)); - assertTrue(message.hasExtension(PackedExtensions.packedEnum)); - - // Test reading back using PackedExtensions: the arrays should be equal, even the fields - // are non-packed. - assertTrue(Arrays.equals(int32s, message.getExtension(PackedExtensions.packedInt32))); - assertTrue(Arrays.equals(uint32s, message.getExtension(PackedExtensions.packedUint32))); - assertTrue(Arrays.equals(sint32s, message.getExtension(PackedExtensions.packedSint32))); - assertTrue(Arrays.equals(int64s, message.getExtension(PackedExtensions.packedInt64))); - assertTrue(Arrays.equals(uint64s, message.getExtension(PackedExtensions.packedUint64))); - assertTrue(Arrays.equals(sint64s, message.getExtension(PackedExtensions.packedSint64))); - assertTrue(Arrays.equals(fixed32s, message.getExtension(PackedExtensions.packedFixed32))); - assertTrue(Arrays.equals(sfixed32s, message.getExtension(PackedExtensions.packedSfixed32))); - assertTrue(Arrays.equals(fixed64s, message.getExtension(PackedExtensions.packedFixed64))); - assertTrue(Arrays.equals(sfixed64s, message.getExtension(PackedExtensions.packedSfixed64))); - assertTrue(Arrays.equals(bools, message.getExtension(PackedExtensions.packedBool))); - assertTrue(Arrays.equals(floats, message.getExtension(PackedExtensions.packedFloat))); - assertTrue(Arrays.equals(doubles, message.getExtension(PackedExtensions.packedDouble))); - assertTrue(Arrays.equals(enums, message.getExtension(PackedExtensions.packedEnum))); - - // Now set the packable extension values using PackedExtensions so they're serialized packed. - message.setExtension(PackedExtensions.packedInt32, int32s); - message.setExtension(PackedExtensions.packedUint32, uint32s); - message.setExtension(PackedExtensions.packedSint32, sint32s); - message.setExtension(PackedExtensions.packedInt64, int64s); - message.setExtension(PackedExtensions.packedUint64, uint64s); - message.setExtension(PackedExtensions.packedSint64, sint64s); - message.setExtension(PackedExtensions.packedFixed32, fixed32s); - message.setExtension(PackedExtensions.packedSfixed32, sfixed32s); - message.setExtension(PackedExtensions.packedFixed64, fixed64s); - message.setExtension(PackedExtensions.packedSfixed64, sfixed64s); - message.setExtension(PackedExtensions.packedBool, bools); - message.setExtension(PackedExtensions.packedFloat, floats); - message.setExtension(PackedExtensions.packedDouble, doubles); - message.setExtension(PackedExtensions.packedEnum, enums); - - // And read back using non-packed RepeatedExtensions. - byte[] data2 = MessageNano.toByteArray(message); - message = MessageNano.mergeFrom(new Extensions.ExtendableMessage(), data2); - assertTrue(Arrays.equals(int32s, message.getExtension(RepeatedExtensions.repeatedInt32))); - assertTrue(Arrays.equals(uint32s, message.getExtension(RepeatedExtensions.repeatedUint32))); - assertTrue(Arrays.equals(sint32s, message.getExtension(RepeatedExtensions.repeatedSint32))); - assertTrue(Arrays.equals(int64s, message.getExtension(RepeatedExtensions.repeatedInt64))); - assertTrue(Arrays.equals(uint64s, message.getExtension(RepeatedExtensions.repeatedUint64))); - assertTrue(Arrays.equals(sint64s, message.getExtension(RepeatedExtensions.repeatedSint64))); - assertTrue(Arrays.equals(fixed32s, message.getExtension(RepeatedExtensions.repeatedFixed32))); - assertTrue(Arrays.equals(sfixed32s, message.getExtension(RepeatedExtensions.repeatedSfixed32))); - assertTrue(Arrays.equals(fixed64s, message.getExtension(RepeatedExtensions.repeatedFixed64))); - assertTrue(Arrays.equals(sfixed64s, message.getExtension(RepeatedExtensions.repeatedSfixed64))); - assertTrue(Arrays.equals(bools, message.getExtension(RepeatedExtensions.repeatedBool))); - assertTrue(Arrays.equals(floats, message.getExtension(RepeatedExtensions.repeatedFloat))); - assertTrue(Arrays.equals(doubles, message.getExtension(RepeatedExtensions.repeatedDouble))); - assertTrue(Arrays.equals(enums, message.getExtension(RepeatedExtensions.repeatedEnum))); - - // Clone the message and ensure it's still equal. - Extensions.ExtendableMessage clone = message.clone(); - assertEquals(clone, message); - } - - public void testNullExtensions() throws Exception { - // Check that clearing the extension on an empty message is a no-op. - Extensions.ExtendableMessage message = new Extensions.ExtendableMessage(); - assertFalse(message.hasExtension(SingularExtensions.someMessage)); - message.setExtension(SingularExtensions.someMessage, null); - assertFalse(message.hasExtension(SingularExtensions.someMessage)); - assertEquals(0, MessageNano.toByteArray(message).length); - - // Check that the message is empty after setting and clearing an extension. - AnotherMessage another = new AnotherMessage(); - assertFalse(message.hasExtension(SingularExtensions.someMessage)); - message.setExtension(SingularExtensions.someMessage, another); - assertTrue(message.hasExtension(SingularExtensions.someMessage)); - assertTrue(MessageNano.toByteArray(message).length > 0); - message.setExtension(SingularExtensions.someMessage, null); - assertFalse(message.hasExtension(SingularExtensions.someMessage)); - assertEquals(0, MessageNano.toByteArray(message).length); - } - - public void testExtensionsMutation() { - Extensions.ExtendableMessage extendableMessage = new Extensions.ExtendableMessage(); - extendableMessage.setExtension(SingularExtensions.someMessage, - new Extensions.AnotherMessage()); - - extendableMessage.getExtension(SingularExtensions.someMessage).string = "not empty"; - - assertEquals("not empty", - extendableMessage.getExtension(SingularExtensions.someMessage).string); - } - - public void testExtensionsMutation_Equals() throws InvalidProtocolBufferNanoException { - Extensions.ExtendableMessage extendableMessage = new Extensions.ExtendableMessage(); - extendableMessage.field = 5; - int int32 = 42; - int[] uint32s = {3, 4}; - int[] sint32s = {-5, -6}; - long[] int64s = {7, 8}; - long[] uint64s = {9, 10}; - long[] sint64s = {-11, -12}; - int[] fixed32s = {13, 14}; - int[] sfixed32s = {-15, -16}; - long[] fixed64s = {17, 18}; - long[] sfixed64s = {-19, -20}; - boolean[] bools = {true, false}; - float[] floats = {2.1f, 2.2f}; - double[] doubles = {2.3, 2.4}; - int[] enums = {Extensions.SECOND_VALUE, Extensions.FIRST_VALUE}; - String[] strings = {"vijfentwintig", "twenty-six"}; - byte[][] bytess = {{2, 7}, {2, 8}}; - AnotherMessage another1 = new AnotherMessage(); - another1.string = "er shi jiu"; - another1.value = false; - AnotherMessage another2 = new AnotherMessage(); - another2.string = "trente"; - another2.value = true; - AnotherMessage[] messages = {another1, another2}; - RepeatedExtensions.RepeatedGroup group1 = new RepeatedExtensions.RepeatedGroup(); - group1.a = 31; - RepeatedExtensions.RepeatedGroup group2 = new RepeatedExtensions.RepeatedGroup(); - group2.a = 32; - RepeatedExtensions.RepeatedGroup[] groups = {group1, group2}; - extendableMessage.setExtension(SingularExtensions.someInt32, int32); - extendableMessage.setExtension(RepeatedExtensions.repeatedUint32, uint32s); - extendableMessage.setExtension(RepeatedExtensions.repeatedSint32, sint32s); - extendableMessage.setExtension(RepeatedExtensions.repeatedInt64, int64s); - extendableMessage.setExtension(RepeatedExtensions.repeatedUint64, uint64s); - extendableMessage.setExtension(RepeatedExtensions.repeatedSint64, sint64s); - extendableMessage.setExtension(RepeatedExtensions.repeatedFixed32, fixed32s); - extendableMessage.setExtension(RepeatedExtensions.repeatedSfixed32, sfixed32s); - extendableMessage.setExtension(RepeatedExtensions.repeatedFixed64, fixed64s); - extendableMessage.setExtension(RepeatedExtensions.repeatedSfixed64, sfixed64s); - extendableMessage.setExtension(RepeatedExtensions.repeatedBool, bools); - extendableMessage.setExtension(RepeatedExtensions.repeatedFloat, floats); - extendableMessage.setExtension(RepeatedExtensions.repeatedDouble, doubles); - extendableMessage.setExtension(RepeatedExtensions.repeatedEnum, enums); - extendableMessage.setExtension(RepeatedExtensions.repeatedString, strings); - extendableMessage.setExtension(RepeatedExtensions.repeatedBytes, bytess); - extendableMessage.setExtension(RepeatedExtensions.repeatedMessage, messages); - extendableMessage.setExtension(RepeatedExtensions.repeatedGroup, groups); - - byte[] data = MessageNano.toByteArray(extendableMessage); - - extendableMessage = Extensions.ExtendableMessage.parseFrom(data); - Extensions.ExtendableMessage messageCopy = Extensions.ExtendableMessage.parseFrom(data); - - // Without deserialising. - assertEquals(extendableMessage, messageCopy); - assertEquals(extendableMessage.hashCode(), messageCopy.hashCode()); - - // Only one deserialized. - extendableMessage.getExtension(SingularExtensions.someInt32); - extendableMessage.getExtension(RepeatedExtensions.repeatedUint32); - extendableMessage.getExtension(RepeatedExtensions.repeatedSint32); - extendableMessage.getExtension(RepeatedExtensions.repeatedInt64); - extendableMessage.getExtension(RepeatedExtensions.repeatedUint64); - extendableMessage.getExtension(RepeatedExtensions.repeatedSint64); - extendableMessage.getExtension(RepeatedExtensions.repeatedFixed32); - extendableMessage.getExtension(RepeatedExtensions.repeatedSfixed32); - extendableMessage.getExtension(RepeatedExtensions.repeatedFixed64); - extendableMessage.getExtension(RepeatedExtensions.repeatedSfixed64); - extendableMessage.getExtension(RepeatedExtensions.repeatedBool); - extendableMessage.getExtension(RepeatedExtensions.repeatedFloat); - extendableMessage.getExtension(RepeatedExtensions.repeatedDouble); - extendableMessage.getExtension(RepeatedExtensions.repeatedEnum); - extendableMessage.getExtension(RepeatedExtensions.repeatedString); - extendableMessage.getExtension(RepeatedExtensions.repeatedBytes); - extendableMessage.getExtension(RepeatedExtensions.repeatedMessage); - extendableMessage.getExtension(RepeatedExtensions.repeatedGroup); - assertEquals(extendableMessage, messageCopy); - assertEquals(extendableMessage.hashCode(), messageCopy.hashCode()); - - // Both deserialized. - messageCopy.getExtension(SingularExtensions.someInt32); - messageCopy.getExtension(RepeatedExtensions.repeatedUint32); - messageCopy.getExtension(RepeatedExtensions.repeatedSint32); - messageCopy.getExtension(RepeatedExtensions.repeatedInt64); - messageCopy.getExtension(RepeatedExtensions.repeatedUint64); - messageCopy.getExtension(RepeatedExtensions.repeatedSint64); - messageCopy.getExtension(RepeatedExtensions.repeatedFixed32); - messageCopy.getExtension(RepeatedExtensions.repeatedSfixed32); - messageCopy.getExtension(RepeatedExtensions.repeatedFixed64); - messageCopy.getExtension(RepeatedExtensions.repeatedSfixed64); - messageCopy.getExtension(RepeatedExtensions.repeatedBool); - messageCopy.getExtension(RepeatedExtensions.repeatedFloat); - messageCopy.getExtension(RepeatedExtensions.repeatedDouble); - messageCopy.getExtension(RepeatedExtensions.repeatedEnum); - messageCopy.getExtension(RepeatedExtensions.repeatedString); - messageCopy.getExtension(RepeatedExtensions.repeatedBytes); - messageCopy.getExtension(RepeatedExtensions.repeatedMessage); - messageCopy.getExtension(RepeatedExtensions.repeatedGroup); - assertEquals(extendableMessage, messageCopy); - assertEquals(extendableMessage.hashCode(), messageCopy.hashCode()); - - // Change one, make sure they are still different. - messageCopy.getExtension(RepeatedExtensions.repeatedMessage)[0].string = "not empty"; - assertFalse(extendableMessage.equals(messageCopy)); - - // Even if the extension hasn't been deserialized. - extendableMessage = Extensions.ExtendableMessage.parseFrom(data); - assertFalse(extendableMessage.equals(messageCopy)); - } - - public void testExtensionsCaching() { - Extensions.ExtendableMessage extendableMessage = new Extensions.ExtendableMessage(); - extendableMessage.setExtension(SingularExtensions.someMessage, - new Extensions.AnotherMessage()); - assertSame("Consecutive calls to getExtensions should return the same object", - extendableMessage.getExtension(SingularExtensions.someMessage), - extendableMessage.getExtension(SingularExtensions.someMessage)); - } - - public void testUnknownFields() throws Exception { - // Check that we roundtrip (serialize and deserialize) unrecognized fields. - AnotherMessage message = new AnotherMessage(); - message.string = "Hello World"; - message.value = false; - - byte[] bytes = MessageNano.toByteArray(message); - int extraFieldSize = CodedOutputByteBufferNano.computeStringSize( - 1001, "This is an unknown field"); - byte[] newBytes = new byte[bytes.length + extraFieldSize]; - System.arraycopy(bytes, 0, newBytes, 0, bytes.length); - CodedOutputByteBufferNano.newInstance(newBytes, bytes.length, extraFieldSize) - .writeString(1001, "This is an unknown field"); - - // Deserialize with an unknown field. - AnotherMessage deserialized = AnotherMessage.parseFrom(newBytes); - byte[] serialized = MessageNano.toByteArray(deserialized); - - assertEquals(newBytes.length, serialized.length); - - // Clear, and make sure it clears everything. - deserialized.clear(); - assertEquals(0, MessageNano.toByteArray(deserialized).length); - } - - public void testMergeFrom() throws Exception { - SimpleMessageNano message = new SimpleMessageNano(); - message.d = 123; - byte[] bytes = MessageNano.toByteArray(message); - - SimpleMessageNano newMessage = MessageNano.mergeFrom(new SimpleMessageNano(), bytes); - assertEquals(message.d, newMessage.d); - } - - public void testJavaKeyword() throws Exception { - TestAllTypesNano msg = new TestAllTypesNano(); - msg.synchronized_ = 123; - assertEquals(123, msg.synchronized_); - } - - public void testReferenceTypesForPrimitives() throws Exception { - NanoReferenceTypes.TestAllTypesNano message = new NanoReferenceTypes.TestAllTypesNano(); - - // Base check - when nothing is set, we serialize nothing. - assertHasWireData(message, false); - - message.defaultBool = true; - assertHasWireData(message, true); - - message.defaultBool = false; - assertHasWireData(message, true); - - message.defaultBool = null; - assertHasWireData(message, false); - - message.defaultInt32 = 5; - assertHasWireData(message, true); - - message.defaultInt32 = null; - assertHasWireData(message, false); - - message.defaultInt64 = 123456L; - assertHasWireData(message, true); - - message.defaultInt64 = null; - assertHasWireData(message, false); - - message.defaultFloat = 1f; - assertHasWireData(message, true); - - message.defaultFloat = null; - assertHasWireData(message, false); - - message.defaultDouble = 2.1; - assertHasWireData(message, true); - - message.defaultDouble = null; - assertHasWireData(message, false); - - message.defaultString = "hello"; - assertHasWireData(message, true); - - message.defaultString = null; - assertHasWireData(message, false); - - message.defaultBytes = new byte[] { 1, 2, 3 }; - assertHasWireData(message, true); - - message.defaultBytes = null; - assertHasWireData(message, false); - } - - public void testHashCodeEquals() throws Exception { - // Complete equality: - TestAllTypesNano a = createMessageForHashCodeEqualsTest(); - TestAllTypesNano aEquivalent = createMessageForHashCodeEqualsTest(); - - assertTrue(MessageNano.messageNanoEquals(a, aEquivalent)); - assertFalse(MessageNano.messageNanoEquals(a, new TestAllTypesNano())); - - // Null and empty array for repeated fields equality: - TestAllTypesNano b = createMessageForHashCodeEqualsTest(); - b.repeatedBool = null; - b.repeatedFloat = new float[0]; - TestAllTypesNano bEquivalent = createMessageForHashCodeEqualsTest(); - bEquivalent.repeatedBool = new boolean[0]; - bEquivalent.repeatedFloat = null; - - // Ref-element-type repeated fields use non-null subsequence equality: - TestAllTypesNano c = createMessageForHashCodeEqualsTest(); - c.repeatedString = null; - c.repeatedStringPiece = new String[] {null, "one", null, "two"}; - c.repeatedBytes = new byte[][] {{3, 4}, null}; - TestAllTypesNano cEquivalent = createMessageForHashCodeEqualsTest(); - cEquivalent.repeatedString = new String[3]; - cEquivalent.repeatedStringPiece = new String[] {"one", "two", null}; - cEquivalent.repeatedBytes = new byte[][] {{3, 4}}; - - // Complete equality for messages with has fields: - TestAllTypesNanoHas d = createMessageWithHasForHashCodeEqualsTest(); - TestAllTypesNanoHas dEquivalent = createMessageWithHasForHashCodeEqualsTest(); - - // If has-fields exist, fields with the same default values but - // different has-field values are different. - TestAllTypesNanoHas e = createMessageWithHasForHashCodeEqualsTest(); - e.optionalInt32++; // make different from d - e.hasDefaultString = false; - TestAllTypesNanoHas eDifferent = createMessageWithHasForHashCodeEqualsTest(); - eDifferent.optionalInt32 = e.optionalInt32; - eDifferent.hasDefaultString = true; - - // Complete equality for messages with accessors: - TestNanoAccessors f = createMessageWithAccessorsForHashCodeEqualsTest(); - TestNanoAccessors fEquivalent = createMessageWithAccessorsForHashCodeEqualsTest(); - - // If using accessors, explicitly setting a field to its default value - // should make the message different. - TestNanoAccessors g = createMessageWithAccessorsForHashCodeEqualsTest(); - g.setOptionalInt32(g.getOptionalInt32() + 1); // make different from f - g.clearDefaultString(); - TestNanoAccessors gDifferent = createMessageWithAccessorsForHashCodeEqualsTest(); - gDifferent.setOptionalInt32(g.getOptionalInt32()); - gDifferent.setDefaultString(g.getDefaultString()); - - // Complete equality for reference typed messages: - NanoReferenceTypes.TestAllTypesNano h = createRefTypedMessageForHashCodeEqualsTest(); - NanoReferenceTypes.TestAllTypesNano hEquivalent = createRefTypedMessageForHashCodeEqualsTest(); - - // Inequality of null and default value for reference typed messages: - NanoReferenceTypes.TestAllTypesNano i = createRefTypedMessageForHashCodeEqualsTest(); - i.optionalInt32 = 1; // make different from h - i.optionalFloat = null; - NanoReferenceTypes.TestAllTypesNano iDifferent = createRefTypedMessageForHashCodeEqualsTest(); - iDifferent.optionalInt32 = i.optionalInt32; - iDifferent.optionalFloat = 0.0f; - - HashMap hashMap = new HashMap(); - hashMap.put(a, "a"); - hashMap.put(b, "b"); - hashMap.put(c, "c"); - hashMap.put(d, "d"); - hashMap.put(e, "e"); - hashMap.put(f, "f"); - hashMap.put(g, "g"); - hashMap.put(h, "h"); - hashMap.put(i, "i"); - - assertEquals(9, hashMap.size()); // a-i should be different from each other. - - assertEquals("a", hashMap.get(a)); - assertEquals("a", hashMap.get(aEquivalent)); - - assertEquals("b", hashMap.get(b)); - assertEquals("b", hashMap.get(bEquivalent)); - - assertEquals("c", hashMap.get(c)); - assertEquals("c", hashMap.get(cEquivalent)); - - assertEquals("d", hashMap.get(d)); - assertEquals("d", hashMap.get(dEquivalent)); - - assertEquals("e", hashMap.get(e)); - assertNull(hashMap.get(eDifferent)); - - assertEquals("f", hashMap.get(f)); - assertEquals("f", hashMap.get(fEquivalent)); - - assertEquals("g", hashMap.get(g)); - assertNull(hashMap.get(gDifferent)); - - assertEquals("h", hashMap.get(h)); - assertEquals("h", hashMap.get(hEquivalent)); - - assertEquals("i", hashMap.get(i)); - assertNull(hashMap.get(iDifferent)); - } - - private TestAllTypesNano createMessageForHashCodeEqualsTest() { - TestAllTypesNano message = new TestAllTypesNano(); - message.optionalInt32 = 5; - message.optionalInt64 = 777; - message.optionalFloat = 1.0f; - message.optionalDouble = 2.0; - message.optionalBool = true; - message.optionalString = "Hello"; - message.optionalBytes = new byte[] { 1, 2, 3 }; - message.optionalNestedMessage = new TestAllTypesNano.NestedMessage(); - message.optionalNestedMessage.bb = 27; - message.optionalNestedEnum = TestAllTypesNano.BAR; - message.repeatedInt32 = new int[] { 5, 6, 7, 8 }; - message.repeatedInt64 = new long[] { 27L, 28L, 29L }; - message.repeatedFloat = new float[] { 5.0f, 6.0f }; - message.repeatedDouble = new double[] { 99.1, 22.5 }; - message.repeatedBool = new boolean[] { true, false, true }; - message.repeatedString = new String[] { "One", "Two" }; - message.repeatedBytes = new byte[][] { { 2, 7 }, { 2, 7 } }; - message.repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { - message.optionalNestedMessage, - message.optionalNestedMessage - }; - message.repeatedNestedEnum = new int[] { - TestAllTypesNano.BAR, - TestAllTypesNano.BAZ - }; - message.setOneofUint32(3); - return message; - } - - private TestAllTypesNanoHas createMessageWithHasForHashCodeEqualsTest() { - TestAllTypesNanoHas message = new TestAllTypesNanoHas(); - message.optionalInt32 = 5; - message.optionalString = "Hello"; - message.optionalBytes = new byte[] { 1, 2, 3 }; - message.optionalNestedMessage = new TestAllTypesNanoHas.NestedMessage(); - message.optionalNestedMessage.bb = 27; - message.optionalNestedEnum = TestAllTypesNano.BAR; - message.repeatedInt32 = new int[] { 5, 6, 7, 8 }; - message.repeatedString = new String[] { "One", "Two" }; - message.repeatedBytes = new byte[][] { { 2, 7 }, { 2, 7 } }; - message.repeatedNestedMessage = new TestAllTypesNanoHas.NestedMessage[] { - message.optionalNestedMessage, - message.optionalNestedMessage - }; - message.repeatedNestedEnum = new int[] { - TestAllTypesNano.BAR, - TestAllTypesNano.BAZ - }; - return message; - } - - private TestNanoAccessors createMessageWithAccessorsForHashCodeEqualsTest() { - TestNanoAccessors message = new TestNanoAccessors() - .setOptionalInt32(5) - .setOptionalString("Hello") - .setOptionalBytes(new byte[] {1, 2, 3}) - .setOptionalNestedEnum(TestNanoAccessors.BAR); - message.optionalNestedMessage = new TestNanoAccessors.NestedMessage().setBb(27); - message.repeatedInt32 = new int[] { 5, 6, 7, 8 }; - message.repeatedString = new String[] { "One", "Two" }; - message.repeatedBytes = new byte[][] { { 2, 7 }, { 2, 7 } }; - message.repeatedNestedMessage = new TestNanoAccessors.NestedMessage[] { - message.optionalNestedMessage, - message.optionalNestedMessage - }; - message.repeatedNestedEnum = new int[] { - TestAllTypesNano.BAR, - TestAllTypesNano.BAZ - }; - return message; - } - - private NanoReferenceTypes.TestAllTypesNano createRefTypedMessageForHashCodeEqualsTest() { - NanoReferenceTypes.TestAllTypesNano message = new NanoReferenceTypes.TestAllTypesNano(); - message.optionalInt32 = 5; - message.optionalInt64 = 777L; - message.optionalFloat = 1.0f; - message.optionalDouble = 2.0; - message.optionalBool = true; - message.optionalString = "Hello"; - message.optionalBytes = new byte[] { 1, 2, 3 }; - message.optionalNestedMessage = - new NanoReferenceTypes.TestAllTypesNano.NestedMessage(); - message.optionalNestedMessage.foo = 27; - message.optionalNestedEnum = NanoReferenceTypes.TestAllTypesNano.BAR; - message.repeatedInt32 = new int[] { 5, 6, 7, 8 }; - message.repeatedInt64 = new long[] { 27L, 28L, 29L }; - message.repeatedFloat = new float[] { 5.0f, 6.0f }; - message.repeatedDouble = new double[] { 99.1, 22.5 }; - message.repeatedBool = new boolean[] { true, false, true }; - message.repeatedString = new String[] { "One", "Two" }; - message.repeatedBytes = new byte[][] { { 2, 7 }, { 2, 7 } }; - message.repeatedNestedMessage = - new NanoReferenceTypes.TestAllTypesNano.NestedMessage[] { - message.optionalNestedMessage, - message.optionalNestedMessage - }; - message.repeatedNestedEnum = new int[] { - NanoReferenceTypes.TestAllTypesNano.BAR, - NanoReferenceTypes.TestAllTypesNano.BAZ - }; - return message; - } - - public void testEqualsWithSpecialFloatingPointValues() throws Exception { - // Checks that the nano implementation complies with Object.equals() when treating - // floating point numbers, i.e. NaN == NaN and +0.0 != -0.0. - // This test assumes that the generated equals() implementations are symmetric, so - // there will only be one direction for each equality check. - - TestAllTypesNano m1 = new TestAllTypesNano(); - m1.optionalFloat = Float.NaN; - m1.optionalDouble = Double.NaN; - TestAllTypesNano m2 = new TestAllTypesNano(); - m2.optionalFloat = Float.NaN; - m2.optionalDouble = Double.NaN; - assertTrue(m1.equals(m2)); - assertTrue(m1.equals( - MessageNano.mergeFrom(new TestAllTypesNano(), MessageNano.toByteArray(m1)))); - - m1.optionalFloat = +0f; - m2.optionalFloat = -0f; - assertFalse(m1.equals(m2)); - - m1.optionalFloat = -0f; - m1.optionalDouble = +0d; - m2.optionalDouble = -0d; - assertFalse(m1.equals(m2)); - - m1.optionalDouble = -0d; - assertTrue(m1.equals(m2)); - assertFalse(m1.equals(new TestAllTypesNano())); // -0 does not equals() the default +0 - assertTrue(m1.equals( - MessageNano.mergeFrom(new TestAllTypesNano(), MessageNano.toByteArray(m1)))); - - // ------- - - TestAllTypesNanoHas m3 = new TestAllTypesNanoHas(); - m3.optionalFloat = Float.NaN; - m3.hasOptionalFloat = true; - m3.optionalDouble = Double.NaN; - m3.hasOptionalDouble = true; - TestAllTypesNanoHas m4 = new TestAllTypesNanoHas(); - m4.optionalFloat = Float.NaN; - m4.hasOptionalFloat = true; - m4.optionalDouble = Double.NaN; - m4.hasOptionalDouble = true; - assertTrue(m3.equals(m4)); - assertTrue(m3.equals( - MessageNano.mergeFrom(new TestAllTypesNanoHas(), MessageNano.toByteArray(m3)))); - - m3.optionalFloat = +0f; - m4.optionalFloat = -0f; - assertFalse(m3.equals(m4)); - - m3.optionalFloat = -0f; - m3.optionalDouble = +0d; - m4.optionalDouble = -0d; - assertFalse(m3.equals(m4)); - - m3.optionalDouble = -0d; - m3.hasOptionalFloat = false; // -0 does not equals() the default +0, - m3.hasOptionalDouble = false; // so these incorrect 'has' flags should be disregarded. - assertTrue(m3.equals(m4)); // note: m4 has the 'has' flags set. - assertFalse(m3.equals(new TestAllTypesNanoHas())); // note: the new message has +0 defaults - assertTrue(m3.equals( - MessageNano.mergeFrom(new TestAllTypesNanoHas(), MessageNano.toByteArray(m3)))); - // note: the deserialized message has the 'has' flags set. - - // ------- - - TestNanoAccessors m5 = new TestNanoAccessors(); - m5.setOptionalFloat(Float.NaN); - m5.setOptionalDouble(Double.NaN); - TestNanoAccessors m6 = new TestNanoAccessors(); - m6.setOptionalFloat(Float.NaN); - m6.setOptionalDouble(Double.NaN); - assertTrue(m5.equals(m6)); - assertTrue(m5.equals( - MessageNano.mergeFrom(new TestNanoAccessors(), MessageNano.toByteArray(m6)))); - - m5.setOptionalFloat(+0f); - m6.setOptionalFloat(-0f); - assertFalse(m5.equals(m6)); - - m5.setOptionalFloat(-0f); - m5.setOptionalDouble(+0d); - m6.setOptionalDouble(-0d); - assertFalse(m5.equals(m6)); - - m5.setOptionalDouble(-0d); - assertTrue(m5.equals(m6)); - assertFalse(m5.equals(new TestNanoAccessors())); - assertTrue(m5.equals( - MessageNano.mergeFrom(new TestNanoAccessors(), MessageNano.toByteArray(m6)))); - - // ------- - - NanoReferenceTypes.TestAllTypesNano m7 = new NanoReferenceTypes.TestAllTypesNano(); - m7.optionalFloat = Float.NaN; - m7.optionalDouble = Double.NaN; - NanoReferenceTypes.TestAllTypesNano m8 = new NanoReferenceTypes.TestAllTypesNano(); - m8.optionalFloat = Float.NaN; - m8.optionalDouble = Double.NaN; - assertTrue(m7.equals(m8)); - assertTrue(m7.equals(MessageNano.mergeFrom( - new NanoReferenceTypes.TestAllTypesNano(), MessageNano.toByteArray(m7)))); - - m7.optionalFloat = +0f; - m8.optionalFloat = -0f; - assertFalse(m7.equals(m8)); - - m7.optionalFloat = -0f; - m7.optionalDouble = +0d; - m8.optionalDouble = -0d; - assertFalse(m7.equals(m8)); - - m7.optionalDouble = -0d; - assertTrue(m7.equals(m8)); - assertFalse(m7.equals(new NanoReferenceTypes.TestAllTypesNano())); - assertTrue(m7.equals(MessageNano.mergeFrom( - new NanoReferenceTypes.TestAllTypesNano(), MessageNano.toByteArray(m7)))); - } - - private static TestAllTypesNano generateMessageForOneof(int caseNumber) { - TestAllTypesNano result = new TestAllTypesNano(); - TestAllTypesNano.NestedMessage nested = - new TestAllTypesNano.NestedMessage(); - nested.bb = 2; - switch (caseNumber) { - case TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER: - result.setOneofUint32(1); - break; - case TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER: - result.setOneofEnum(TestAllTypesNano.BAR); - break; - case TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER: - result.setOneofNestedMessage(nested); - break; - case TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER: - result.setOneofBytes(new byte[] {1, 2}); - break; - case TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER: - result.setOneofString("hello"); - break; - case TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER: - result.setOneofFixed64(-1L); - break; - default: - throw new RuntimeException("unexpected case number: " + caseNumber); - } - return result; - } - - public void testOneofHashCodeEquals() throws Exception { - TestAllTypesNano m1 = generateMessageForOneof( - TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER); - assertEquals(m1, generateMessageForOneof( - TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER)); - assertFalse(m1.equals(new TestAllTypesNano())); - - TestAllTypesNano m2 = generateMessageForOneof( - TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER); - assertEquals(m2, generateMessageForOneof( - TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER)); - assertFalse(m2.equals(new TestAllTypesNano())); - - TestAllTypesNano m3 = generateMessageForOneof( - TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER); - assertEquals(m3, generateMessageForOneof( - TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER)); - assertFalse(m3.equals(new TestAllTypesNano())); - - TestAllTypesNano m4 = generateMessageForOneof( - TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER); - assertEquals(m4, generateMessageForOneof( - TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER)); - assertFalse(m4.equals(new TestAllTypesNano())); - - TestAllTypesNano m5 = generateMessageForOneof( - TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER); - assertEquals(m5, generateMessageForOneof( - TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER)); - assertFalse(m5.equals(new TestAllTypesNano())); - - TestAllTypesNano m6 = generateMessageForOneof( - TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER); - assertEquals(m6, generateMessageForOneof( - TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER)); - assertFalse(m6.equals(new TestAllTypesNano())); - - Map map = - new HashMap(); - map.put(m1, 1); - map.put(m2, 2); - map.put(m3, 3); - map.put(m4, 4); - map.put(m5, 5); - map.put(m6, 6); - - assertEquals(6, map.size()); - } - - private void checkOneofCase(TestAllTypesNano nano, int field) - throws Exception { - assertEquals(field, nano.getOneofFieldCase()); - assertEquals( - field == TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER, - nano.hasOneofBytes()); - assertEquals( - field == TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER, - nano.hasOneofEnum()); - assertEquals( - field == TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER, - nano.hasOneofFixed64()); - assertEquals( - field == TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER, - nano.hasOneofNestedMessage()); - assertEquals( - field == TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER, - nano.hasOneofString()); - assertEquals( - field == TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER, - nano.hasOneofUint32()); - - } - - public void testOneofDefault() throws Exception { - TestAllTypesNano m1 = new TestAllTypesNano(); - checkOneofCase(m1, 0); - assertEquals(WireFormatNano.EMPTY_BYTES, m1.getOneofBytes()); - assertEquals(TestAllTypesNano.FOO, m1.getOneofEnum()); - assertEquals(0L, m1.getOneofFixed64()); - assertEquals(null, m1.getOneofNestedMessage()); - assertEquals("", m1.getOneofString()); - assertEquals(0, m1.getOneofUint32()); - } - - public void testOneofExclusiveness() throws Exception { - TestAllTypesNano m = new TestAllTypesNano(); - checkOneofCase(m, 0); - - m.setOneofBytes(new byte[]{0, 1}); - checkOneofCase(m, TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER); - assertTrue(Arrays.equals(new byte[]{0, 1}, m.getOneofBytes())); - - m.setOneofEnum(TestAllTypesNano.BAZ); - checkOneofCase(m, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER); - assertEquals(TestAllTypesNano.BAZ, m.getOneofEnum()); - assertEquals(WireFormatNano.EMPTY_BYTES, m.getOneofBytes()); - - m.setOneofFixed64(-1L); - checkOneofCase(m, TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER); - assertEquals(-1L, m.getOneofFixed64()); - assertEquals(TestAllTypesNano.FOO, m.getOneofEnum()); - - m.setOneofNestedMessage(new TestAllTypesNano.NestedMessage()); - checkOneofCase(m, TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER); - assertEquals( - new TestAllTypesNano.NestedMessage(), m.getOneofNestedMessage()); - assertEquals(0L, m.getOneofFixed64()); - - m.setOneofString("hello"); - checkOneofCase(m, TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER); - assertEquals("hello", m.getOneofString()); - assertNull(m.getOneofNestedMessage()); - - m.setOneofUint32(10); - checkOneofCase(m, TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER); - assertEquals(10, m.getOneofUint32()); - assertEquals("", m.getOneofString()); - - m.setOneofBytes(new byte[]{0, 1}); - checkOneofCase(m, TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER); - assertTrue(Arrays.equals(new byte[]{0, 1}, m.getOneofBytes())); - assertEquals(0, m.getOneofUint32()); - } - - public void testOneofClear() throws Exception { - TestAllTypesNano m = new TestAllTypesNano(); - m.setOneofBytes(new byte[]{0, 1}); - m.clearOneofField(); - checkOneofCase(m, 0); - - m.setOneofEnum(TestAllTypesNano.BAZ); - m.clearOneofField(); - checkOneofCase(m, 0); - - m.setOneofFixed64(-1L); - m.clearOneofField(); - checkOneofCase(m, 0); - - m.setOneofNestedMessage(new TestAllTypesNano.NestedMessage()); - m.clearOneofField(); - checkOneofCase(m, 0); - - m.setOneofString("hello"); - m.clearOneofField(); - checkOneofCase(m, 0); - - m.setOneofUint32(10); - m.clearOneofField(); - checkOneofCase(m, 0); - } - - public void testOneofMarshaling() throws Exception { - TestAllTypesNano m = new TestAllTypesNano(); - TestAllTypesNano parsed = new TestAllTypesNano(); - { - m.setOneofBytes(new byte[]{0, 1}); - byte[] serialized = MessageNano.toByteArray(m); - MessageNano.mergeFrom(parsed, serialized); - checkOneofCase(parsed, TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER); - assertTrue(Arrays.equals(new byte[]{0, 1}, parsed.getOneofBytes())); - } - { - m.setOneofEnum(TestAllTypesNano.BAZ); - byte[] serialized = MessageNano.toByteArray(m); - MessageNano.mergeFrom(parsed, serialized); - checkOneofCase(m, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER); - assertEquals(TestAllTypesNano.BAZ, m.getOneofEnum()); - } - { - m.setOneofEnum(TestAllTypesNano.BAZ); - byte[] serialized = MessageNano.toByteArray(m); - MessageNano.mergeFrom(parsed, serialized); - checkOneofCase(m, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER); - assertEquals(TestAllTypesNano.BAZ, m.getOneofEnum()); - } - { - m.setOneofFixed64(-1L); - byte[] serialized = MessageNano.toByteArray(m); - MessageNano.mergeFrom(parsed, serialized); - checkOneofCase(m, TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER); - assertEquals(-1L, m.getOneofFixed64()); - } - { - m.setOneofNestedMessage(new TestAllTypesNano.NestedMessage()); - byte[] serialized = MessageNano.toByteArray(m); - MessageNano.mergeFrom(parsed, serialized); - checkOneofCase(m, TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER); - assertEquals( - new TestAllTypesNano.NestedMessage(), m.getOneofNestedMessage()); - } - { - m.setOneofString("hello"); - byte[] serialized = MessageNano.toByteArray(m); - MessageNano.mergeFrom(parsed, serialized); - assertEquals("hello", m.getOneofString()); - assertNull(m.getOneofNestedMessage()); - } - { - m.setOneofUint32(10); - byte[] serialized = MessageNano.toByteArray(m); - MessageNano.mergeFrom(parsed, serialized); - checkOneofCase(m, TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER); - assertEquals(10, m.getOneofUint32()); - } - } - - public void testOneofSerializedConcat() throws Exception { - TestAllTypesNano m1 = new TestAllTypesNano(); - m1.setOneofBytes(new byte[] {0, 1}); - byte[] b1 = MessageNano.toByteArray(m1); - TestAllTypesNano m2 = new TestAllTypesNano(); - m2.setOneofEnum(TestAllTypesNano.BAZ); - byte[] b2 = MessageNano.toByteArray(m2); - byte[] b3 = new byte[b1.length + b2.length]; - System.arraycopy(b1, 0, b3, 0, b1.length); - System.arraycopy(b2, 0, b3, b1.length, b2.length); - TestAllTypesNano parsed = new TestAllTypesNano(); - MessageNano.mergeFrom(parsed, b3); - // the last on the wire wins. - checkOneofCase(parsed, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER); - assertEquals(TestAllTypesNano.BAZ, parsed.getOneofEnum()); - } - - public void testNullRepeatedFields() throws Exception { - // Check that serialization after explicitly setting a repeated field - // to null doesn't NPE. - TestAllTypesNano message = new TestAllTypesNano(); - message.repeatedInt32 = null; - MessageNano.toByteArray(message); // should not NPE - message.toString(); // should not NPE - - message.repeatedNestedEnum = null; - MessageNano.toByteArray(message); // should not NPE - message.toString(); // should not NPE - - message.repeatedBytes = null; - MessageNano.toByteArray(message); // should not NPE - message.toString(); // should not NPE - - message.repeatedNestedMessage = null; - MessageNano.toByteArray(message); // should not NPE - message.toString(); // should not NPE - - message.repeatedPackedInt32 = null; - MessageNano.toByteArray(message); // should not NPE - message.toString(); // should not NPE - - message.repeatedPackedNestedEnum = null; - MessageNano.toByteArray(message); // should not NPE - message.toString(); // should not NPE - - // Create a second message to merge into message. - TestAllTypesNano secondMessage = new TestAllTypesNano(); - secondMessage.repeatedInt32 = new int[] {1, 2, 3}; - secondMessage.repeatedNestedEnum = new int[] { - TestAllTypesNano.FOO, TestAllTypesNano.BAR - }; - secondMessage.repeatedBytes = new byte[][] {{1, 2}, {3, 4}}; - TestAllTypesNano.NestedMessage nested = - new TestAllTypesNano.NestedMessage(); - nested.bb = 55; - secondMessage.repeatedNestedMessage = - new TestAllTypesNano.NestedMessage[] {nested}; - secondMessage.repeatedPackedInt32 = new int[] {1, 2, 3}; - secondMessage.repeatedPackedNestedEnum = new int[] { - TestAllTypesNano.FOO, TestAllTypesNano.BAR - }; - - // Should not NPE - message.mergeFrom(CodedInputByteBufferNano.newInstance( - MessageNano.toByteArray(secondMessage))); - assertEquals(3, message.repeatedInt32.length); - assertEquals(3, message.repeatedInt32[2]); - assertEquals(2, message.repeatedNestedEnum.length); - assertEquals(TestAllTypesNano.FOO, message.repeatedNestedEnum[0]); - assertEquals(2, message.repeatedBytes.length); - assertEquals(4, message.repeatedBytes[1][1]); - assertEquals(1, message.repeatedNestedMessage.length); - assertEquals(55, message.repeatedNestedMessage[0].bb); - assertEquals(3, message.repeatedPackedInt32.length); - assertEquals(2, message.repeatedPackedInt32[1]); - assertEquals(2, message.repeatedPackedNestedEnum.length); - assertEquals(TestAllTypesNano.BAR, message.repeatedPackedNestedEnum[1]); - } - - public void testNullRepeatedFieldElements() throws Exception { - // Check that serialization with null array elements doesn't NPE. - String string1 = "1"; - String string2 = "2"; - byte[] bytes1 = {3, 4}; - byte[] bytes2 = {5, 6}; - TestAllTypesNano.NestedMessage msg1 = new TestAllTypesNano.NestedMessage(); - msg1.bb = 7; - TestAllTypesNano.NestedMessage msg2 = new TestAllTypesNano.NestedMessage(); - msg2.bb = 8; - - TestAllTypesNano message = new TestAllTypesNano(); - message.repeatedString = new String[] {null, string1, string2}; - message.repeatedBytes = new byte[][] {bytes1, null, bytes2}; - message.repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] {msg1, msg2, null}; - message.repeatedGroup = new TestAllTypesNano.RepeatedGroup[] {null, null, null}; - - byte[] serialized = MessageNano.toByteArray(message); // should not NPE - TestAllTypesNano deserialized = MessageNano.mergeFrom(new TestAllTypesNano(), serialized); - assertEquals(2, deserialized.repeatedString.length); - assertEquals(string1, deserialized.repeatedString[0]); - assertEquals(string2, deserialized.repeatedString[1]); - assertEquals(2, deserialized.repeatedBytes.length); - assertTrue(Arrays.equals(bytes1, deserialized.repeatedBytes[0])); - assertTrue(Arrays.equals(bytes2, deserialized.repeatedBytes[1])); - assertEquals(2, deserialized.repeatedNestedMessage.length); - assertEquals(msg1.bb, deserialized.repeatedNestedMessage[0].bb); - assertEquals(msg2.bb, deserialized.repeatedNestedMessage[1].bb); - assertEquals(0, deserialized.repeatedGroup.length); - } - - public void testRepeatedMerge() throws Exception { - // Check that merging repeated fields cause the arrays to expand with - // new data. - TestAllTypesNano first = new TestAllTypesNano(); - first.repeatedInt32 = new int[] {1, 2, 3}; - TestAllTypesNano second = new TestAllTypesNano(); - second.repeatedInt32 = new int[] {4, 5}; - MessageNano.mergeFrom(first, MessageNano.toByteArray(second)); - assertEquals(5, first.repeatedInt32.length); - assertEquals(1, first.repeatedInt32[0]); - assertEquals(4, first.repeatedInt32[3]); - - first = new TestAllTypesNano(); - first.repeatedNestedEnum = new int[] {TestAllTypesNano.BAR}; - second = new TestAllTypesNano(); - second.repeatedNestedEnum = new int[] {TestAllTypesNano.FOO}; - MessageNano.mergeFrom(first, MessageNano.toByteArray(second)); - assertEquals(2, first.repeatedNestedEnum.length); - assertEquals(TestAllTypesNano.BAR, first.repeatedNestedEnum[0]); - assertEquals(TestAllTypesNano.FOO, first.repeatedNestedEnum[1]); - - first = new TestAllTypesNano(); - first.repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { - new TestAllTypesNano.NestedMessage() - }; - first.repeatedNestedMessage[0].bb = 3; - second = new TestAllTypesNano(); - second.repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] { - new TestAllTypesNano.NestedMessage() - }; - second.repeatedNestedMessage[0].bb = 5; - MessageNano.mergeFrom(first, MessageNano.toByteArray(second)); - assertEquals(2, first.repeatedNestedMessage.length); - assertEquals(3, first.repeatedNestedMessage[0].bb); - assertEquals(5, first.repeatedNestedMessage[1].bb); - - first = new TestAllTypesNano(); - first.repeatedPackedSfixed64 = new long[] {-1, -2, -3}; - second = new TestAllTypesNano(); - second.repeatedPackedSfixed64 = new long[] {-4, -5}; - MessageNano.mergeFrom(first, MessageNano.toByteArray(second)); - assertEquals(5, first.repeatedPackedSfixed64.length); - assertEquals(-1, first.repeatedPackedSfixed64[0]); - assertEquals(-4, first.repeatedPackedSfixed64[3]); - - first = new TestAllTypesNano(); - first.repeatedPackedNestedEnum = new int[] {TestAllTypesNano.BAR}; - second = new TestAllTypesNano(); - second.repeatedPackedNestedEnum = new int[] {TestAllTypesNano.FOO}; - MessageNano.mergeFrom(first, MessageNano.toByteArray(second)); - assertEquals(2, first.repeatedPackedNestedEnum.length); - assertEquals(TestAllTypesNano.BAR, first.repeatedPackedNestedEnum[0]); - assertEquals(TestAllTypesNano.FOO, first.repeatedPackedNestedEnum[1]); - - // Now test repeated merging in a nested scope - TestRepeatedMergeNano firstContainer = new TestRepeatedMergeNano(); - firstContainer.contained = new TestAllTypesNano(); - firstContainer.contained.repeatedInt32 = new int[] {10, 20}; - TestRepeatedMergeNano secondContainer = new TestRepeatedMergeNano(); - secondContainer.contained = new TestAllTypesNano(); - secondContainer.contained.repeatedInt32 = new int[] {30}; - MessageNano.mergeFrom(firstContainer, MessageNano.toByteArray(secondContainer)); - assertEquals(3, firstContainer.contained.repeatedInt32.length); - assertEquals(20, firstContainer.contained.repeatedInt32[1]); - assertEquals(30, firstContainer.contained.repeatedInt32[2]); - } - - public void testRepeatedPackables() throws Exception { - // Check that repeated fields with packable types can accept both packed and unpacked - // serialized forms. - NanoRepeatedPackables.NonPacked nonPacked = new NanoRepeatedPackables.NonPacked(); - // Exaggerates the first values of varint-typed arrays. This is to test that the parsing code - // of packed fields handles non-packed data correctly. If the code incorrectly thinks it is - // reading from a packed tag, it will read the first value as the byte length of the field, - // and the large number will cause the input to go out of bounds, thus capturing the error. - nonPacked.int32S = new int[] {1000, 2, 3}; - nonPacked.int64S = new long[] {4000, 5, 6}; - nonPacked.uint32S = new int[] {7000, 8, 9}; - nonPacked.uint64S = new long[] {10000, 11, 12}; - nonPacked.sint32S = new int[] {13000, 14, 15}; - nonPacked.sint64S = new long[] {16000, 17, 18}; - nonPacked.fixed32S = new int[] {19, 20, 21}; - nonPacked.fixed64S = new long[] {22, 23, 24}; - nonPacked.sfixed32S = new int[] {25, 26, 27}; - nonPacked.sfixed64S = new long[] {28, 29, 30}; - nonPacked.floats = new float[] {31, 32, 33}; - nonPacked.doubles = new double[] {34, 35, 36}; - nonPacked.bools = new boolean[] {false, true}; - nonPacked.enums = new int[] { - NanoRepeatedPackables.Enum.OPTION_ONE, - NanoRepeatedPackables.Enum.OPTION_TWO, - }; - nonPacked.noise = 13579; - - byte[] nonPackedSerialized = MessageNano.toByteArray(nonPacked); - - NanoRepeatedPackables.Packed packed = - MessageNano.mergeFrom(new NanoRepeatedPackables.Packed(), nonPackedSerialized); - assertRepeatedPackablesEqual(nonPacked, packed); - - byte[] packedSerialized = MessageNano.toByteArray(packed); - // Just a cautious check that the two serialized forms are different, - // to make sure the remaining of this test is useful: - assertFalse(Arrays.equals(nonPackedSerialized, packedSerialized)); - - nonPacked = MessageNano.mergeFrom(new NanoRepeatedPackables.NonPacked(), packedSerialized); - assertRepeatedPackablesEqual(nonPacked, packed); - - // Test mixed serialized form. - byte[] mixedSerialized = new byte[nonPackedSerialized.length + packedSerialized.length]; - System.arraycopy(nonPackedSerialized, 0, mixedSerialized, 0, nonPackedSerialized.length); - System.arraycopy(packedSerialized, 0, - mixedSerialized, nonPackedSerialized.length, packedSerialized.length); - - nonPacked = MessageNano.mergeFrom(new NanoRepeatedPackables.NonPacked(), mixedSerialized); - packed = MessageNano.mergeFrom(new NanoRepeatedPackables.Packed(), mixedSerialized); - assertRepeatedPackablesEqual(nonPacked, packed); - assertTrue(Arrays.equals(new int[] {1000, 2, 3, 1000, 2, 3}, nonPacked.int32S)); - assertTrue(Arrays.equals(new int[] {13000, 14, 15, 13000, 14, 15}, nonPacked.sint32S)); - assertTrue(Arrays.equals(new int[] {25, 26, 27, 25, 26, 27}, nonPacked.sfixed32S)); - assertTrue(Arrays.equals(new boolean[] {false, true, false, true}, nonPacked.bools)); - } - - public void testMapsSerializeAndParse() throws Exception { - TestMap origin = new TestMap(); - setMapMessage(origin); - assertMapMessageSet(origin); - - byte[] output = MessageNano.toByteArray(origin); - TestMap parsed = new TestMap(); - MessageNano.mergeFrom(parsed, output); - } - - public void testMapSerializeRejectNull() throws Exception { - TestMap primitiveMap = new TestMap(); - primitiveMap.int32ToInt32Field = new HashMap(); - primitiveMap.int32ToInt32Field.put(null, 1); - try { - MessageNano.toByteArray(primitiveMap); - fail("should reject null keys"); - } catch (IllegalStateException e) { - // pass. - } - - TestMap messageMap = new TestMap(); - messageMap.int32ToMessageField = - new HashMap(); - messageMap.int32ToMessageField.put(0, null); - try { - MessageNano.toByteArray(messageMap); - fail("should reject null values"); - } catch (IllegalStateException e) { - // pass. - } - } - - /** - * Tests that merging bytes containing conflicting keys with override the - * message value instead of merging the message value into the existing entry. - */ - public void testMapMergeOverrideMessageValues() throws Exception { - TestMap.MessageValue origValue = new TestMap.MessageValue(); - origValue.value = 1; - origValue.value2 = 2; - TestMap.MessageValue newValue = new TestMap.MessageValue(); - newValue.value = 3; - - TestMap origMessage = new TestMap(); - origMessage.int32ToMessageField = - new HashMap(); - origMessage.int32ToMessageField.put(1, origValue); - - TestMap newMessage = new TestMap(); - newMessage.int32ToMessageField = - new HashMap(); - newMessage.int32ToMessageField.put(1, newValue); - MessageNano.mergeFrom(origMessage, - MessageNano.toByteArray(newMessage)); - TestMap.MessageValue mergedValue = origMessage.int32ToMessageField.get(1); - assertEquals(3, mergedValue.value); - assertEquals(0, mergedValue.value2); - } - - /** - * Tests that when merging with empty entries, - * we will use default for the key and value, instead of null. - */ - public void testMapMergeEmptyEntry() throws Exception { - TestMap testMap = new TestMap(); - byte[] buffer = new byte[1024]; - CodedOutputByteBufferNano output = - CodedOutputByteBufferNano.newInstance(buffer); - // An empty entry for int32_to_int32 map. - output.writeTag(1, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); - output.writeRawVarint32(0); - // An empty entry for int32_to_message map. - output.writeTag(5, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); - output.writeRawVarint32(0); - - CodedInputByteBufferNano input = CodedInputByteBufferNano.newInstance( - buffer, 0, buffer.length - output.spaceLeft()); - testMap.mergeFrom(input); - assertNotNull(testMap.int32ToInt32Field);; - assertEquals(1, testMap.int32ToInt32Field.size()); - assertEquals(Integer.valueOf(0), testMap.int32ToInt32Field.get(0)); - assertNotNull(testMap.int32ToMessageField); - assertEquals(1, testMap.int32ToMessageField.size()); - TestMap.MessageValue messageValue = testMap.int32ToMessageField.get(0); - assertNotNull(messageValue); - assertEquals(0, messageValue.value); - assertEquals(0, messageValue.value2); - } - - public void testMapEquals() throws Exception { - TestMap a = new TestMap(); - TestMap b = new TestMap(); - - // empty and null map fields are equal. - assertTestMapEqual(a, b); - a.int32ToBytesField = new HashMap(); - assertTestMapEqual(a, b); - - a.int32ToInt32Field = new HashMap(); - b.int32ToInt32Field = new HashMap(); - setMap(a.int32ToInt32Field, deepCopy(int32Values), deepCopy(int32Values)); - setMap(b.int32ToInt32Field, deepCopy(int32Values), deepCopy(int32Values)); - assertTestMapEqual(a, b); - - a.int32ToMessageField = - new HashMap(); - b.int32ToMessageField = - new HashMap(); - setMap(a.int32ToMessageField, - deepCopy(int32Values), deepCopy(messageValues)); - setMap(b.int32ToMessageField, - deepCopy(int32Values), deepCopy(messageValues)); - assertTestMapEqual(a, b); - - a.stringToInt32Field = new HashMap(); - b.stringToInt32Field = new HashMap(); - setMap(a.stringToInt32Field, deepCopy(stringValues), deepCopy(int32Values)); - setMap(b.stringToInt32Field, deepCopy(stringValues), deepCopy(int32Values)); - assertTestMapEqual(a, b); - - a.int32ToBytesField = new HashMap(); - b.int32ToBytesField = new HashMap(); - setMap(a.int32ToBytesField, deepCopy(int32Values), deepCopy(bytesValues)); - setMap(b.int32ToBytesField, deepCopy(int32Values), deepCopy(bytesValues)); - assertTestMapEqual(a, b); - - // Make sure the map implementation does not matter. - a.int32ToStringField = new TreeMap(); - b.int32ToStringField = new HashMap(); - setMap(a.int32ToStringField, deepCopy(int32Values), deepCopy(stringValues)); - setMap(b.int32ToStringField, deepCopy(int32Values), deepCopy(stringValues)); - assertTestMapEqual(a, b); - - a.clear(); - b.clear(); - - // unequal cases: different value - a.int32ToInt32Field = new HashMap(); - b.int32ToInt32Field = new HashMap(); - a.int32ToInt32Field.put(1, 1); - b.int32ToInt32Field.put(1, 2); - assertTestMapUnequal(a, b); - // unequal case: additional entry - b.int32ToInt32Field.put(1, 1); - b.int32ToInt32Field.put(2, 1); - assertTestMapUnequal(a, b); - a.int32ToInt32Field.put(2, 1); - assertTestMapEqual(a, b); - - // unequal case: different message value. - a.int32ToMessageField = - new HashMap(); - b.int32ToMessageField = - new HashMap(); - MessageValue va = new MessageValue(); - va.value = 1; - MessageValue vb = new MessageValue(); - vb.value = 1; - a.int32ToMessageField.put(1, va); - b.int32ToMessageField.put(1, vb); - assertTestMapEqual(a, b); - vb.value = 2; - assertTestMapUnequal(a, b); - } - - private static void assertTestMapEqual(TestMap a, TestMap b) - throws Exception { - assertEquals(a.hashCode(), b.hashCode()); - assertTrue(a.equals(b)); - assertTrue(b.equals(a)); - } - - private static void assertTestMapUnequal(TestMap a, TestMap b) - throws Exception { - assertFalse(a.equals(b)); - assertFalse(b.equals(a)); - } - - private static final Integer[] int32Values = new Integer[] { - 0, 1, -1, Integer.MAX_VALUE, Integer.MIN_VALUE, - }; - - private static final Long[] int64Values = new Long[] { - 0L, 1L, -1L, Long.MAX_VALUE, Long.MIN_VALUE, - }; - - private static final String[] stringValues = new String[] { - "", "hello", "world", "foo", "bar", - }; - - private static final byte[][] bytesValues = new byte[][] { - new byte[] {}, - new byte[] {0}, - new byte[] {1, -1}, - new byte[] {127, -128}, - new byte[] {'a', 'b', '0', '1'}, - }; - - private static final Boolean[] boolValues = new Boolean[] { - false, true, - }; - - private static final Integer[] enumValues = new Integer[] { - TestMap.FOO, TestMap.BAR, TestMap.BAZ, TestMap.QUX, - Integer.MAX_VALUE /* unknown */, - }; - - private static final TestMap.MessageValue[] messageValues = - new TestMap.MessageValue[] { - newMapValueMessage(0), - newMapValueMessage(1), - newMapValueMessage(-1), - newMapValueMessage(Integer.MAX_VALUE), - newMapValueMessage(Integer.MIN_VALUE), - }; - - private static TestMap.MessageValue newMapValueMessage(int value) { - TestMap.MessageValue result = new TestMap.MessageValue(); - result.value = value; - return result; - } - - @SuppressWarnings("unchecked") - private static T[] deepCopy(T[] orig) throws Exception { - if (orig instanceof MessageValue[]) { - MessageValue[] result = new MessageValue[orig.length]; - for (int i = 0; i < orig.length; i++) { - result[i] = new MessageValue(); - MessageNano.mergeFrom( - result[i], MessageNano.toByteArray((MessageValue) orig[i])); - } - return (T[]) result; - } - if (orig instanceof byte[][]) { - byte[][] result = new byte[orig.length][]; - for (int i = 0; i < orig.length; i++) { - byte[] origBytes = (byte[]) orig[i]; - result[i] = Arrays.copyOf(origBytes, origBytes.length); - } - } - return Arrays.copyOf(orig, orig.length); - } - - private void setMap(Map map, K[] keys, V[] values) { - assert(keys.length == values.length); - for (int i = 0; i < keys.length; i++) { - map.put(keys[i], values[i]); - } - } - - private void assertMapSet( - Map map, K[] keys, V[] values) throws Exception { - assert(keys.length == values.length); - for (int i = 0; i < values.length; i++) { - assertEquals(values[i], map.get(keys[i])); - } - assertEquals(keys.length, map.size()); - } - - private void setMapMessage(TestMap testMap) { - testMap.int32ToInt32Field = new HashMap(); - testMap.int32ToBytesField = new HashMap(); - testMap.int32ToEnumField = new HashMap(); - testMap.int32ToMessageField = - new HashMap(); - testMap.int32ToStringField = new HashMap(); - testMap.stringToInt32Field = new HashMap(); - testMap.boolToBoolField = new HashMap(); - testMap.uint32ToUint32Field = new HashMap(); - testMap.sint32ToSint32Field = new HashMap(); - testMap.fixed32ToFixed32Field = new HashMap(); - testMap.sfixed32ToSfixed32Field = new HashMap(); - testMap.int64ToInt64Field = new HashMap(); - testMap.uint64ToUint64Field = new HashMap(); - testMap.sint64ToSint64Field = new HashMap(); - testMap.fixed64ToFixed64Field = new HashMap(); - testMap.sfixed64ToSfixed64Field = new HashMap(); - setMap(testMap.int32ToInt32Field, int32Values, int32Values); - setMap(testMap.int32ToBytesField, int32Values, bytesValues); - setMap(testMap.int32ToEnumField, int32Values, enumValues); - setMap(testMap.int32ToMessageField, int32Values, messageValues); - setMap(testMap.int32ToStringField, int32Values, stringValues); - setMap(testMap.stringToInt32Field, stringValues, int32Values); - setMap(testMap.boolToBoolField, boolValues, boolValues); - setMap(testMap.uint32ToUint32Field, int32Values, int32Values); - setMap(testMap.sint32ToSint32Field, int32Values, int32Values); - setMap(testMap.fixed32ToFixed32Field, int32Values, int32Values); - setMap(testMap.sfixed32ToSfixed32Field, int32Values, int32Values); - setMap(testMap.int64ToInt64Field, int64Values, int64Values); - setMap(testMap.uint64ToUint64Field, int64Values, int64Values); - setMap(testMap.sint64ToSint64Field, int64Values, int64Values); - setMap(testMap.fixed64ToFixed64Field, int64Values, int64Values); - setMap(testMap.sfixed64ToSfixed64Field, int64Values, int64Values); - } - private void assertMapMessageSet(TestMap testMap) throws Exception { - assertMapSet(testMap.int32ToInt32Field, int32Values, int32Values); - assertMapSet(testMap.int32ToBytesField, int32Values, bytesValues); - assertMapSet(testMap.int32ToEnumField, int32Values, enumValues); - assertMapSet(testMap.int32ToMessageField, int32Values, messageValues); - assertMapSet(testMap.int32ToStringField, int32Values, stringValues); - assertMapSet(testMap.stringToInt32Field, stringValues, int32Values); - assertMapSet(testMap.boolToBoolField, boolValues, boolValues); - assertMapSet(testMap.uint32ToUint32Field, int32Values, int32Values); - assertMapSet(testMap.sint32ToSint32Field, int32Values, int32Values); - assertMapSet(testMap.fixed32ToFixed32Field, int32Values, int32Values); - assertMapSet(testMap.sfixed32ToSfixed32Field, int32Values, int32Values); - assertMapSet(testMap.int64ToInt64Field, int64Values, int64Values); - assertMapSet(testMap.uint64ToUint64Field, int64Values, int64Values); - assertMapSet(testMap.sint64ToSint64Field, int64Values, int64Values); - assertMapSet(testMap.fixed64ToFixed64Field, int64Values, int64Values); - assertMapSet(testMap.sfixed64ToSfixed64Field, int64Values, int64Values); - } - - public void testRepeatedFieldInitializedInReftypesCompatMode() { - NanoReferenceTypesCompat.TestAllTypesNano proto = new NanoReferenceTypesCompat.TestAllTypesNano(); - assertNotNull(proto.repeatedString); - } - - private void assertRepeatedPackablesEqual( - NanoRepeatedPackables.NonPacked nonPacked, NanoRepeatedPackables.Packed packed) { - // Not using MessageNano.equals() -- that belongs to a separate test. - assertTrue(Arrays.equals(nonPacked.int32S, packed.int32S)); - assertTrue(Arrays.equals(nonPacked.int64S, packed.int64S)); - assertTrue(Arrays.equals(nonPacked.uint32S, packed.uint32S)); - assertTrue(Arrays.equals(nonPacked.uint64S, packed.uint64S)); - assertTrue(Arrays.equals(nonPacked.sint32S, packed.sint32S)); - assertTrue(Arrays.equals(nonPacked.sint64S, packed.sint64S)); - assertTrue(Arrays.equals(nonPacked.fixed32S, packed.fixed32S)); - assertTrue(Arrays.equals(nonPacked.fixed64S, packed.fixed64S)); - assertTrue(Arrays.equals(nonPacked.sfixed32S, packed.sfixed32S)); - assertTrue(Arrays.equals(nonPacked.sfixed64S, packed.sfixed64S)); - assertTrue(Arrays.equals(nonPacked.floats, packed.floats)); - assertTrue(Arrays.equals(nonPacked.doubles, packed.doubles)); - assertTrue(Arrays.equals(nonPacked.bools, packed.bools)); - assertTrue(Arrays.equals(nonPacked.enums, packed.enums)); - } - - public void testClone() throws Exception { - // A simple message. - AnotherMessage anotherMessage = new AnotherMessage(); - anotherMessage.string = "Hello"; - anotherMessage.value = true; - anotherMessage.integers = new int[] { 1, 2, 3 }; - - AnotherMessage clone = anotherMessage.clone(); - assertEquals(clone, anotherMessage); - - // Verify it was a deep clone - changes to the clone shouldn't affect the - // original. - clone.integers[1] = 100; - assertFalse(clone.equals(anotherMessage)); - } - - private void assertHasWireData(MessageNano message, boolean expected) { - byte[] bytes = MessageNano.toByteArray(message); - int wireLength = bytes.length; - if (expected) { - assertFalse(wireLength == 0); - } else { - if (wireLength != 0) { - fail("Expected no wire data for message \n" + message - + "\nBut got:\n" - + hexDump(bytes)); - } - } - } - - private static String hexDump(byte[] bytes) { - StringBuilder sb = new StringBuilder(); - for (byte b : bytes) { - sb.append(String.format("%02x ", b)); - } - return sb.toString(); - } -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/map_test.proto b/javanano/src/test/java/com/google/protobuf/nano/map_test.proto deleted file mode 100644 index 51498a4925713..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/map_test.proto +++ /dev/null @@ -1,70 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto3"; - -package map_test; - -option java_package = "com.google.protobuf"; -option java_outer_classname = "MapTestProto"; - -message TestMap { - message MessageValue { - int32 value = 1; - int32 value2 = 2; - } - enum EnumValue { - FOO = 0; - BAR = 1; - BAZ = 2; - QUX = 3; - } - - map int32_to_int32_field = 1; - map int32_to_string_field = 2; - map int32_to_bytes_field = 3; - map int32_to_enum_field = 4; - map int32_to_message_field = 5; - map string_to_int32_field = 6; - map bool_to_bool_field = 7; - - // Test all the other primitive types. As the key and value are not coupled in - // the implementation, we do not test all the combinations of key/value pairs, - // so that we can keep the number of test cases manageable - map uint32_to_uint32_field = 11; - map sint32_to_sint32_field = 12; - map fixed32_to_fixed32_field = 13; - map sfixed32_to_sfixed32_field = 14; - map int64_to_int64_field = 15; - map uint64_to_uint64_field = 16; - map sint64_to_sint64_field = 17; - map fixed64_to_fixed64_field = 18; - map sfixed64_to_sfixed64_field = 19; -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_accessors_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_accessors_nano.proto deleted file mode 100644 index 6511e4703b37e..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_accessors_nano.proto +++ /dev/null @@ -1,118 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: maxtroy@google.com (Max Cai) - -package protobuf_unittest; - -option java_package = "com.google.protobuf"; -option java_outer_classname = "NanoAccessorsOuterClass"; - -message TestNanoAccessors { - - message NestedMessage { - optional int32 bb = 1; - } - - enum NestedEnum { - FOO = 1; - BAR = 2; - BAZ = 3; - } - - // Singular - optional int32 optional_int32 = 1; - optional float optional_float = 11; - optional double optional_double = 12; - optional string optional_string = 14; - optional bytes optional_bytes = 15; - - optional NestedMessage optional_nested_message = 18; - - optional NestedEnum optional_nested_enum = 21; - - // Repeated - repeated int32 repeated_int32 = 31; - repeated string repeated_string = 44; - repeated bytes repeated_bytes = 45; - - repeated NestedMessage repeated_nested_message = 48; - - repeated NestedEnum repeated_nested_enum = 51; - - // Singular with defaults - optional int32 default_int32 = 61 [default = 41 ]; - optional string default_string = 74 [default = "hello"]; - optional bytes default_bytes = 75 [default = "world"]; - - optional float default_float_nan = 99 [default = nan]; - - optional NestedEnum default_nested_enum = 81 [default = BAR]; - - // Required - required int32 id = 86; - - // Add enough optional fields to make 2 bit fields in total - optional int32 filler100 = 100; - optional int32 filler101 = 101; - optional int32 filler102 = 102; - optional int32 filler103 = 103; - optional int32 filler104 = 104; - optional int32 filler105 = 105; - optional int32 filler106 = 106; - optional int32 filler107 = 107; - optional int32 filler108 = 108; - optional int32 filler109 = 109; - optional int32 filler110 = 110; - optional int32 filler111 = 111; - optional int32 filler112 = 112; - optional int32 filler113 = 113; - optional int32 filler114 = 114; - optional int32 filler115 = 115; - optional int32 filler116 = 116; - optional int32 filler117 = 117; - optional int32 filler118 = 118; - optional int32 filler119 = 119; - optional int32 filler120 = 120; - optional int32 filler121 = 121; - optional int32 filler122 = 122; - optional int32 filler123 = 123; - optional int32 filler124 = 124; - optional int32 filler125 = 125; - optional int32 filler126 = 126; - optional int32 filler127 = 127; - optional int32 filler128 = 128; - optional int32 filler129 = 129; - optional int32 filler130 = 130; - - optional int32 before_bit_field_check = 139; - optional int32 bit_field_check = 140; - optional int32 after_bit_field_check = 141; -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_multiple_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_multiple_nano.proto deleted file mode 100644 index 958e1f17caf6e..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_multiple_nano.proto +++ /dev/null @@ -1,48 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: maxtroy@google.com (Max Cai) - -package protobuf_unittest; - -option java_package = "com.google.protobuf"; -option java_multiple_files = true; - -enum FileScopeEnumMultiple { - THREE = 3; -} - -message EnumClassNanoMultiple { - enum MessageScopeEnumMultiple { - FOUR = 4; - } - optional FileScopeEnumMultiple three = 3 [ default = THREE ]; - optional MessageScopeEnumMultiple four = 4 [ default = FOUR ]; -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto deleted file mode 100644 index 3a1e07f6d9d32..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto +++ /dev/null @@ -1,48 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: maxtroy@google.com (Max Cai) - -package protobuf_unittest; - -option java_package = "com.google.protobuf"; -option java_outer_classname = "EnumClassNanos"; - -enum FileScopeEnum { - ONE = 1; -} - -message EnumClassNano { - enum MessageScopeEnum { - TWO = 2; - } - optional FileScopeEnum one = 1 [ default = ONE ]; - optional MessageScopeEnum two = 2 [ default = TWO ]; -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto deleted file mode 100644 index c0da8b422ee69..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto +++ /dev/null @@ -1,28 +0,0 @@ -package protobuf_unittest; - -option java_package = "com.google.protobuf"; -option java_outer_classname = "EnumValidity"; - -enum E { - default = 1; // test java keyword renaming - FOO = 2; - BAR = 3; - BAZ = 4; -} - -message M { - optional E optional_e = 1; - optional E default_e = 2 [ default = BAZ ]; - repeated E repeated_e = 3; - repeated E packed_e = 4 [ packed = true ]; - repeated E repeated_e2 = 5; - repeated E packed_e2 = 6 [ packed = true ]; - repeated E repeated_e3 = 7; - repeated E packed_e3 = 8 [ packed = true ]; -} - -message Alt { - optional E repeated_e2_as_optional = 5; - repeated E packed_e2_as_non_packed = 6; - repeated E non_packed_e3_as_packed = 7 [ packed = true ]; -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto deleted file mode 100644 index ca56b3dd45477..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto +++ /dev/null @@ -1,37 +0,0 @@ -syntax = "proto2"; - -option java_outer_classname = "Extensions"; -option java_package = "com.google.protobuf.nano.testext"; - -message ExtendableMessage { - optional int32 field = 1; - extensions 10 to max; -} - -enum AnEnum { - FIRST_VALUE = 1; - SECOND_VALUE = 2; -} - -message AnotherMessage { - optional string string = 1; - optional bool value = 2; - repeated int32 integers = 3; -} - -message ContainerMessage { - extend ExtendableMessage { - optional bool another_thing = 100; - // The largest permitted field number, per - // https://developers.google.com/protocol-buffers/docs/proto#simple - optional bool large_field_number = 536870911; - } -} - -// For testNanoOptionalGroupWithUnknownFieldsEnabled; -// not part of the extensions tests. -message MessageWithGroup { - optional group Group = 1 { - optional int32 a = 2; - } -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto deleted file mode 100644 index 3b7a004c9e2b1..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto +++ /dev/null @@ -1,29 +0,0 @@ -syntax = "proto2"; - -option java_multiple_files = true; -option java_package = "com.google.protobuf"; - -import "google/protobuf/nano/unittest_extension_nano.proto"; - -// Must be compiled separately due to extension number reuse. -// The reuse is deliberate, for testing wire compatibility. - -message PackedExtensions { - extend ExtendableMessage { - repeated int32 packed_int32 = 10 [ packed = true ]; - repeated uint32 packed_uint32 = 11 [ packed = true ]; - repeated sint32 packed_sint32 = 12 [ packed = true ]; - repeated int64 packed_int64 = 13 [ packed = true ]; - repeated uint64 packed_uint64 = 14 [ packed = true ]; - repeated sint64 packed_sint64 = 15 [ packed = true ]; - repeated fixed32 packed_fixed32 = 16 [ packed = true ]; - repeated sfixed32 packed_sfixed32 = 17 [ packed = true ]; - repeated fixed64 packed_fixed64 = 18 [ packed = true ]; - repeated sfixed64 packed_sfixed64 = 19 [ packed = true ]; - repeated bool packed_bool = 20 [ packed = true ]; - repeated float packed_float = 21 [ packed = true ]; - repeated double packed_double = 22 [ packed = true ]; - repeated AnEnum packed_enum = 23 [ packed = true ]; - // Non-packable types omitted. - } -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_repeated_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_repeated_nano.proto deleted file mode 100644 index e533c65b43c02..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_repeated_nano.proto +++ /dev/null @@ -1,34 +0,0 @@ -syntax = "proto2"; - -option java_multiple_files = true; -option java_package = "com.google.protobuf"; - -import "google/protobuf/nano/unittest_extension_nano.proto"; - -// Must be compiled separately due to extension number reuse. -// The reuse is deliberate, for testing wire compatibility. - -message RepeatedExtensions { - extend ExtendableMessage { - repeated int32 repeated_int32 = 10; - repeated uint32 repeated_uint32 = 11; - repeated sint32 repeated_sint32 = 12; - repeated int64 repeated_int64 = 13; - repeated uint64 repeated_uint64 = 14; - repeated sint64 repeated_sint64 = 15; - repeated fixed32 repeated_fixed32 = 16; - repeated sfixed32 repeated_sfixed32 = 17; - repeated fixed64 repeated_fixed64 = 18; - repeated sfixed64 repeated_sfixed64 = 19; - repeated bool repeated_bool = 20; - repeated float repeated_float = 21; - repeated double repeated_double = 22; - repeated AnEnum repeated_enum = 23; - repeated string repeated_string = 24; - repeated bytes repeated_bytes = 25; - repeated AnotherMessage repeated_message = 26; - repeated group RepeatedGroup = 27 { - optional int32 a = 1; - } - } -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_singular_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_singular_nano.proto deleted file mode 100644 index 8b2d9658880af..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_singular_nano.proto +++ /dev/null @@ -1,34 +0,0 @@ -syntax = "proto2"; - -option java_multiple_files = true; -option java_package = "com.google.protobuf"; - -import "google/protobuf/nano/unittest_extension_nano.proto"; - -// Must be compiled separately due to extension number reuse. -// The reuse is deliberate, for testing wire compatibility. - -message SingularExtensions { - extend ExtendableMessage { - optional int32 some_int32 = 10; - optional uint32 some_uint32 = 11; - optional sint32 some_sint32 = 12; - optional int64 some_int64 = 13; - optional uint64 some_uint64 = 14; - optional sint64 some_sint64 = 15; - optional fixed32 some_fixed32 = 16; - optional sfixed32 some_sfixed32 = 17; - optional fixed64 some_fixed64 = 18; - optional sfixed64 some_sfixed64 = 19; - optional bool some_bool = 20; - optional float some_float = 21; - optional double some_double = 22; - optional AnEnum some_enum = 23; - optional string some_string = 24; - optional bytes some_bytes = 25; - optional AnotherMessage some_message = 26; - optional group SomeGroup = 27 { - optional int32 a = 1; - } - } -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_has_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_has_nano.proto deleted file mode 100644 index fe7d1794a7680..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_has_nano.proto +++ /dev/null @@ -1,82 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: ulas@google.com (Ulas Kirazci) - -package protobuf_unittest; - -option java_package = "com.google.protobuf"; -option java_outer_classname = "NanoHasOuterClass"; - -message TestAllTypesNanoHas { - - message NestedMessage { - optional int32 bb = 1; - } - - enum NestedEnum { - FOO = 1; - BAR = 2; - BAZ = 3; - } - - // Singular - optional int32 optional_int32 = 1; - optional float optional_float = 11; - optional double optional_double = 12; - optional string optional_string = 14; - optional bytes optional_bytes = 15; - - optional NestedMessage optional_nested_message = 18; - - optional NestedEnum optional_nested_enum = 21; - - // Repeated - repeated int32 repeated_int32 = 31; - repeated string repeated_string = 44; - repeated bytes repeated_bytes = 45; - - repeated NestedMessage repeated_nested_message = 48; - - repeated NestedEnum repeated_nested_enum = 51; - - // Singular with defaults - optional int32 default_int32 = 61 [default = 41 ]; - optional string default_string = 74 [default = "hello"]; - optional bytes default_bytes = 75 [default = "world"]; - - optional float default_float_nan = 99 [default = nan]; - - optional NestedEnum default_nested_enum = 81 [default = BAR]; - - required int32 id = 86; - required NestedEnum required_enum = 87; - -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_import_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_import_nano.proto deleted file mode 100644 index 1a3ddc57ea898..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_import_nano.proto +++ /dev/null @@ -1,48 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// -// This is like unittest_import.proto but with optimize_for = NANO_RUNTIME. - -package protobuf_unittest_import; - -option java_package = "com.google.protobuf.nano.testimport"; -option java_outer_classname = "UnittestImportNano"; - -message ImportMessageNano { - optional int32 d = 1; -} - -enum ImportEnumNano { - IMPORT_NANO_FOO = 7; - IMPORT_NANO_BAR = 8; - IMPORT_NANO_BAZ = 9; -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto deleted file mode 100644 index b31c43994c9e8..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto +++ /dev/null @@ -1,41 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: maxtroy@google.com (Max Cai) - -package protobuf_unittest_import; - -option java_package = "com.google.protobuf"; -option java_outer_classname = "MultipleNameClashNano"; -option java_multiple_files = true; - -message MultipleNameClashNano { - optional int32 field = 1; -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nano.proto deleted file mode 100644 index 406ab7741c01a..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nano.proto +++ /dev/null @@ -1,63 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: maxtroy@google.com (Max Cai) - -package protobuf_unittest_import; - -import "google/protobuf/nano/unittest_import_nano.proto"; - -option java_package = "com.google.protobuf"; -option java_multiple_files = true; - -enum FileScopeEnum { - ONE = 1; - TWO = 2; -} - -message FileScopeEnumRefNano { - optional FileScopeEnum enum_field = 1; -} - -message MessageScopeEnumRefNano { - enum MessageScopeEnum { - ONE = 1; - TWO = 2; - } - optional MessageScopeEnum enum_field = 1; -} - -message MultipleImportingNonMultipleNano1 { - optional ImportMessageNano field = 1; -} - -message MultipleImportingNonMultipleNano2 { - optional MultipleImportingNonMultipleNano1 nano1 = 1; -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto deleted file mode 100644 index 3fff24c0c4e0d..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto +++ /dev/null @@ -1,195 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: wink@google.com (Wink Saville) - -package protobuf_unittest; - -import "google/protobuf/nano/unittest_import_nano.proto"; - -option java_package = "com.google.protobuf"; -option java_outer_classname = "NanoOuterClass"; - -// Same as TestAllTypes but with the nano runtime. -message TestAllTypesNano { - - message NestedMessage { - optional int32 bb = 1; - } - - enum NestedEnum { - FOO = 1; - BAR = 2; - BAZ = 3; - } - - // Singular - optional int32 optional_int32 = 1; - optional int64 optional_int64 = 2; - optional uint32 optional_uint32 = 3; - optional uint64 optional_uint64 = 4; - optional sint32 optional_sint32 = 5; - optional sint64 optional_sint64 = 6; - optional fixed32 optional_fixed32 = 7; - optional fixed64 optional_fixed64 = 8; - optional sfixed32 optional_sfixed32 = 9; - optional sfixed64 optional_sfixed64 = 10; - optional float optional_float = 11; - optional double optional_double = 12; - optional bool optional_bool = 13; - optional string optional_string = 14; - optional bytes optional_bytes = 15; - - optional group OptionalGroup = 16 { - optional int32 a = 17; - } - - optional NestedMessage optional_nested_message = 18; - optional ForeignMessageNano optional_foreign_message = 19; - optional protobuf_unittest_import.ImportMessageNano - optional_import_message = 20; - - optional NestedEnum optional_nested_enum = 21; - optional ForeignEnumNano optional_foreign_enum = 22; - optional protobuf_unittest_import.ImportEnumNano optional_import_enum = 23; - - optional string optional_string_piece = 24 [ctype=STRING_PIECE]; - optional string optional_cord = 25 [ctype=CORD]; - - // Repeated - repeated int32 repeated_int32 = 31; - repeated int64 repeated_int64 = 32; - repeated uint32 repeated_uint32 = 33; - repeated uint64 repeated_uint64 = 34; - repeated sint32 repeated_sint32 = 35; - repeated sint64 repeated_sint64 = 36; - repeated fixed32 repeated_fixed32 = 37; - repeated fixed64 repeated_fixed64 = 38; - repeated sfixed32 repeated_sfixed32 = 39; - repeated sfixed64 repeated_sfixed64 = 40; - repeated float repeated_float = 41; - repeated double repeated_double = 42; - repeated bool repeated_bool = 43; - repeated string repeated_string = 44; - repeated bytes repeated_bytes = 45; - - repeated group RepeatedGroup = 46 { - optional int32 a = 47; - } - - repeated NestedMessage repeated_nested_message = 48; - repeated ForeignMessageNano repeated_foreign_message = 49; - repeated protobuf_unittest_import.ImportMessageNano - repeated_import_message = 50; - - repeated NestedEnum repeated_nested_enum = 51; - repeated ForeignEnumNano repeated_foreign_enum = 52; - repeated protobuf_unittest_import.ImportEnumNano repeated_import_enum = 53; - - repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; - repeated string repeated_cord = 55 [ctype=CORD]; - - // Repeated packed - repeated int32 repeated_packed_int32 = 87 [packed=true]; - repeated sfixed64 repeated_packed_sfixed64 = 88 [packed=true]; - - repeated NestedEnum repeated_packed_nested_enum = 89 [packed=true]; - - // Singular with defaults - optional int32 default_int32 = 61 [default = 41 ]; - optional int64 default_int64 = 62 [default = 42 ]; - optional uint32 default_uint32 = 63 [default = 43 ]; - optional uint64 default_uint64 = 64 [default = 44 ]; - optional sint32 default_sint32 = 65 [default = -45 ]; - optional sint64 default_sint64 = 66 [default = 46 ]; - optional fixed32 default_fixed32 = 67 [default = 47 ]; - optional fixed64 default_fixed64 = 68 [default = 48 ]; - optional sfixed32 default_sfixed32 = 69 [default = 49 ]; - optional sfixed64 default_sfixed64 = 70 [default = -50 ]; - optional float default_float = 71 [default = 51.5 ]; - optional double default_double = 72 [default = 52e3 ]; - optional bool default_bool = 73 [default = true ]; - optional string default_string = 74 [default = "hello"]; - optional bytes default_bytes = 75 [default = "world"]; - - optional string default_string_nonascii = 76 [default = "dünya"]; - optional bytes default_bytes_nonascii = 77 [default = "dünyab"]; - - optional float default_float_inf = 97 [default = inf]; - optional float default_float_neg_inf = 98 [default = -inf]; - optional float default_float_nan = 99 [default = nan]; - optional double default_double_inf = 100 [default = inf]; - optional double default_double_neg_inf = 101 [default = -inf]; - optional double default_double_nan = 102 [default = nan]; - - optional NestedEnum default_nested_enum = 81 [default = BAR]; - optional ForeignEnumNano default_foreign_enum = 82 - [default = FOREIGN_NANO_BAR]; - optional protobuf_unittest_import.ImportEnumNano - default_import_enum = 83 [default = IMPORT_NANO_BAR]; - - optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"]; - optional string default_cord = 85 [ctype=CORD,default="123"]; - - required int32 id = 86; - - // Try to cause conflicts. - optional int32 tag = 93; - optional int32 get_serialized_size = 94; - optional int32 write_to = 95; - - // Try to fail with java reserved keywords - optional int32 synchronized = 96; - - oneof oneof_field { - uint32 oneof_uint32 = 111; - NestedMessage oneof_nested_message = 112; - string oneof_string = 123; - bytes oneof_bytes = 124; - fixed64 oneof_fixed64 = 115; - NestedEnum oneof_enum = 116; - } -} - -message ForeignMessageNano { - optional int32 c = 1; -} - -enum ForeignEnumNano { - FOREIGN_NANO_FOO = 4; - FOREIGN_NANO_BAR = 5; - FOREIGN_NANO_BAZ = 6; -} - -// Test that deprecated fields work. We only verify that they compile (at one -// point this failed). -message TestDeprecatedNano { - optional int32 deprecated_field = 1 [deprecated = true]; -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_recursive_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_recursive_nano.proto deleted file mode 100644 index 29b944f01fd7b..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_recursive_nano.proto +++ /dev/null @@ -1,49 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: wink@google.com (Wink Saville) -// - -package protobuf_unittest_import; - -option java_package = "com.google.protobuf"; -// Explicit outer classname to suppress legacy info. -option java_outer_classname = "UnittestRecursiveNano"; - -message RecursiveMessageNano { - message NestedMessage { - optional RecursiveMessageNano a = 1; - } - - required int32 id = 1; - optional NestedMessage nested_message = 2; - optional RecursiveMessageNano optional_recursive_message_nano = 3; - repeated RecursiveMessageNano repeated_recursive_message_nano = 4; -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto deleted file mode 100644 index 82eb8d1175c00..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto +++ /dev/null @@ -1,116 +0,0 @@ -package protobuf_unittest; - -option java_package = "com.google.protobuf"; -option java_outer_classname = "NanoReferenceTypes"; - -message TestAllTypesNano { - - enum NestedEnum { - FOO = 1; - BAR = 2; - BAZ = 3; - } - - message NestedMessage { - optional int32 foo = 1; - } - - // Singular - optional int32 optional_int32 = 1; - optional int64 optional_int64 = 2; - optional uint32 optional_uint32 = 3; - optional uint64 optional_uint64 = 4; - optional sint32 optional_sint32 = 5; - optional sint64 optional_sint64 = 6; - optional fixed32 optional_fixed32 = 7; - optional fixed64 optional_fixed64 = 8; - optional sfixed32 optional_sfixed32 = 9; - optional sfixed64 optional_sfixed64 = 10; - optional float optional_float = 11; - optional double optional_double = 12; - optional bool optional_bool = 13; - optional string optional_string = 14; - optional bytes optional_bytes = 15; - - optional group OptionalGroup = 16 { - optional int32 a = 17; - } - - optional NestedMessage optional_nested_message = 18; - - optional NestedEnum optional_nested_enum = 21; - - optional string optional_string_piece = 24 [ctype=STRING_PIECE]; - optional string optional_cord = 25 [ctype=CORD]; - - // Repeated - repeated int32 repeated_int32 = 31; - repeated int64 repeated_int64 = 32; - repeated uint32 repeated_uint32 = 33; - repeated uint64 repeated_uint64 = 34; - repeated sint32 repeated_sint32 = 35; - repeated sint64 repeated_sint64 = 36; - repeated fixed32 repeated_fixed32 = 37; - repeated fixed64 repeated_fixed64 = 38; - repeated sfixed32 repeated_sfixed32 = 39; - repeated sfixed64 repeated_sfixed64 = 40; - repeated float repeated_float = 41; - repeated double repeated_double = 42; - repeated bool repeated_bool = 43; - repeated string repeated_string = 44; - repeated bytes repeated_bytes = 45; - - repeated group RepeatedGroup = 46 { - optional int32 a = 47; - } - - repeated NestedMessage repeated_nested_message = 48; - - repeated NestedEnum repeated_nested_enum = 51; - - repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; - repeated string repeated_cord = 55 [ctype=CORD]; - - // Repeated packed - repeated int32 repeated_packed_int32 = 87 [packed=true]; - repeated sfixed64 repeated_packed_sfixed64 = 88 [packed=true]; - - repeated NestedEnum repeated_packed_nested_enum = 89 [packed=true]; - - // Singular with defaults - optional int32 default_int32 = 61 [default = 41 ]; - optional int64 default_int64 = 62 [default = 42 ]; - optional uint32 default_uint32 = 63 [default = 43 ]; - optional uint64 default_uint64 = 64 [default = 44 ]; - optional sint32 default_sint32 = 65 [default = -45 ]; - optional sint64 default_sint64 = 66 [default = 46 ]; - optional fixed32 default_fixed32 = 67 [default = 47 ]; - optional fixed64 default_fixed64 = 68 [default = 48 ]; - optional sfixed32 default_sfixed32 = 69 [default = 49 ]; - optional sfixed64 default_sfixed64 = 70 [default = -50 ]; - optional float default_float = 71 [default = 51.5 ]; - optional double default_double = 72 [default = 52e3 ]; - optional bool default_bool = 73 [default = true ]; - optional string default_string = 74 [default = "hello"]; - optional bytes default_bytes = 75 [default = "world"]; - - - optional float default_float_inf = 97 [default = inf]; - optional float default_float_neg_inf = 98 [default = -inf]; - optional float default_float_nan = 99 [default = nan]; - optional double default_double_inf = 100 [default = inf]; - optional double default_double_neg_inf = 101 [default = -inf]; - optional double default_double_nan = 102 [default = nan]; - -} - -message ForeignMessageNano { - optional int32 c = 1; -} - -enum ForeignEnumNano { - FOREIGN_NANO_FOO = 4; - FOREIGN_NANO_BAR = 5; - FOREIGN_NANO_BAZ = 6; -} - diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto deleted file mode 100644 index ef4e2d2f65ffb..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto +++ /dev/null @@ -1,47 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: maxtroy@google.com (Max Cai) - -package protobuf_unittest; - -import "google/protobuf/nano/unittest_nano.proto"; - -option java_package = "com.google.protobuf"; -option java_multiple_files = true; - -// A container message for testing the merging of repeated fields at a -// nested level. Other tests will be done using the repeated fields in -// TestAllTypesNano. -message TestRepeatedMergeNano { - - optional TestAllTypesNano contained = 1; - -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_packables_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_packables_nano.proto deleted file mode 100644 index 96af8856cfb44..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_packables_nano.proto +++ /dev/null @@ -1,95 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: maxtroy@google.com (Max Cai) - -package protobuf_unittest; - -option java_package = "com.google.protobuf"; -option java_outer_classname = "NanoRepeatedPackables"; - -enum Enum { - OPTION_ONE = 1; - OPTION_TWO = 2; -} - -// Two almost identical messages with all packable repeated field types. -// One with none marked as packed and the other all packed. For -// compatibility, they should be able to parse each other's serialized -// forms. - -message NonPacked { - - // All packable types, none marked as packed. - - repeated int32 int32s = 1; - repeated int64 int64s = 2; - repeated uint32 uint32s = 3; - repeated uint64 uint64s = 4; - repeated sint32 sint32s = 5; - repeated sint64 sint64s = 6; - repeated fixed32 fixed32s = 7; - repeated fixed64 fixed64s = 8; - repeated sfixed32 sfixed32s = 9; - repeated sfixed64 sfixed64s = 10; - repeated float floats = 11; - repeated double doubles = 12; - repeated bool bools = 13; - repeated Enum enums = 14; - - // Noise for testing merged deserialization. - optional int32 noise = 15; - -} - -message Packed { - - // All packable types, all matching the field numbers in NonPacked, - // all marked as packed. - - repeated int32 int32s = 1 [ packed = true ]; - repeated int64 int64s = 2 [ packed = true ]; - repeated uint32 uint32s = 3 [ packed = true ]; - repeated uint64 uint64s = 4 [ packed = true ]; - repeated sint32 sint32s = 5 [ packed = true ]; - repeated sint64 sint64s = 6 [ packed = true ]; - repeated fixed32 fixed32s = 7 [ packed = true ]; - repeated fixed64 fixed64s = 8 [ packed = true ]; - repeated sfixed32 sfixed32s = 9 [ packed = true ]; - repeated sfixed64 sfixed64s = 10 [ packed = true ]; - repeated float floats = 11 [ packed = true ]; - repeated double doubles = 12 [ packed = true ]; - repeated bool bools = 13 [ packed = true ]; - repeated Enum enums = 14 [ packed = true ]; - - // Noise for testing merged deserialization. - optional int32 noise = 15; - -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_simple_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_simple_nano.proto deleted file mode 100644 index 25786cc227cbb..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_simple_nano.proto +++ /dev/null @@ -1,54 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: wink@google.com (Wink Saville) -// - -package protobuf_unittest_import; - -option java_package = "com.google.protobuf"; -// Explicit outer classname to suppress legacy info. -option java_outer_classname = "UnittestSimpleNano"; - -message SimpleMessageNano { - message NestedMessage { - optional int32 bb = 1; - } - - enum NestedEnum { - FOO = 1; - BAR = 2; - BAZ = 3; - } - - optional int32 d = 1 [default = 123]; - optional NestedMessage nested_msg = 2; - optional NestedEnum default_nested_enum = 3 [default = BAZ]; -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_single_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_single_nano.proto deleted file mode 100644 index 7de30c877d2d6..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_single_nano.proto +++ /dev/null @@ -1,38 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: maxtroy@google.com (Max Cai) - -package protobuf_unittest_import; - -option java_package = "com.google.protobuf"; - -message SingleMessageNano { -} diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_stringutf8_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_stringutf8_nano.proto deleted file mode 100644 index bbd677cfd6f00..0000000000000 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_stringutf8_nano.proto +++ /dev/null @@ -1,43 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: wink@google.com (Wink Saville) -// - -package protobuf_unittest_import; - -option java_package = "com.google.protobuf"; -// Explicit outer classname to suppress legacy info. -option java_outer_classname = "UnittestStringutf8Nano"; - -message StringUtf8 { - optional string id = 1; - repeated string rs = 2; -} diff --git a/jenkins/README.md b/jenkins/README.md deleted file mode 100644 index 29f664f299b8e..0000000000000 --- a/jenkins/README.md +++ /dev/null @@ -1,6 +0,0 @@ - -Jenkins Infrastructure ----------------------- - -The scripts in this directory serve as plumbing for running the protobuf -tests under Jenkins. diff --git a/jenkins/build_and_run_docker.sh b/jenkins/build_and_run_docker.sh deleted file mode 100755 index 50e1e8c684329..0000000000000 --- a/jenkins/build_and_run_docker.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash -# -# Builds docker image and runs a command under it. -# This is a generic script that is configured with the following variables: -# -# DOCKERFILE_DIR - Directory in which Dockerfile file is located. -# DOCKER_RUN_SCRIPT - Script to run under docker (relative to protobuf repo root) -# OUTPUT_DIR - Directory that will be copied from inside docker after finishing. -# $@ - Extra args to pass to docker run - - -set -ex - -cd $(dirname $0)/.. -git_root=$(pwd) -cd - - -# Use image name based on Dockerfile location checksum -DOCKER_IMAGE_NAME=$(basename $DOCKERFILE_DIR)_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ ) - -# Make sure docker image has been built. Should be instantaneous if so. -docker build -t $DOCKER_IMAGE_NAME $DOCKERFILE_DIR - -# Ensure existence of ccache directory -CCACHE_DIR=/tmp/protobuf-ccache -mkdir -p $CCACHE_DIR - -# Choose random name for docker container -CONTAINER_NAME="build_and_run_docker_$(uuidgen)" - -# Run command inside docker -docker run \ - "$@" \ - -e CCACHE_DIR=$CCACHE_DIR \ - -e EXTERNAL_GIT_ROOT="/var/local/jenkins/protobuf" \ - -e TEST_SET="$TEST_SET" \ - -e THIS_IS_REALLY_NEEDED='see https://github.com/docker/docker/issues/14203 for why docker is awful' \ - -v "$git_root:/var/local/jenkins/protobuf:ro" \ - -v $CCACHE_DIR:$CCACHE_DIR \ - -w /var/local/git/protobuf \ - --name=$CONTAINER_NAME \ - $DOCKER_IMAGE_NAME \ - bash -l "/var/local/jenkins/protobuf/$DOCKER_RUN_SCRIPT" || FAILED="true" - -# Copy output artifacts -if [ "$OUTPUT_DIR" != "" ] -then - docker cp "$CONTAINER_NAME:/var/local/git/protobuf/$OUTPUT_DIR" "$git_root" || FAILED="true" -fi - -# remove the container, possibly killing it first -docker rm -f $CONTAINER_NAME || true - -if [ "$FAILED" != "" ] -then - exit 1 -fi diff --git a/jenkins/buildcmds/README.md b/jenkins/buildcmds/README.md deleted file mode 100644 index 7a48f2d5c96bd..0000000000000 --- a/jenkins/buildcmds/README.md +++ /dev/null @@ -1,6 +0,0 @@ - -Jenkins Build Commands ----------------------- - -The scripts in this directory are designed to be top-level entry points for -Jenkins projects. diff --git a/jenkins/buildcmds/pull_request.sh b/jenkins/buildcmds/pull_request.sh deleted file mode 100755 index 51e4bfa48c939..0000000000000 --- a/jenkins/buildcmds/pull_request.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -# -# This is the top-level script we give to Jenkins as the entry point for -# running the "pull request" project: -# -# https://grpc-testing.appspot.com/view/Protocol%20Buffers/job/protobuf_pull_request/ -# -# This script selects a specific Dockerfile (for building a Docker image) and -# a script to run inside that image. Then we delegate to the general -# build_and_run_docker.sh script. - -export DOCKERFILE_DIR=jenkins/docker -export DOCKER_RUN_SCRIPT=jenkins/pull_request_in_docker.sh -export OUTPUT_DIR=testoutput -export TEST_SET="csharp java_jdk7 javanano_jdk7 java_oracle7 javanano_oracle7 python python_cpp ruby_all javascript golang php_all" -./jenkins/build_and_run_docker.sh diff --git a/jenkins/buildcmds/pull_request_32.sh b/jenkins/buildcmds/pull_request_32.sh deleted file mode 100755 index bf0fb7ffe3c8c..0000000000000 --- a/jenkins/buildcmds/pull_request_32.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -# -# This is the top-level script we give to Jenkins as the entry point for -# running the "pull request 32" project: -# -# https://grpc-testing.appspot.com/view/Protocol%20Buffers/job/Protocol%20Buffers%20Pull%20Request%2032/ -# -# This script selects a specific Dockerfile (for building a Docker image) and -# a script to run inside that image. Then we delegate to the general -# build_and_run_docker.sh script. - -export DOCKERFILE_DIR=jenkins/docker32 -export DOCKER_RUN_SCRIPT=jenkins/pull_request_in_docker.sh -export OUTPUT_DIR=testoutput -export TEST_SET="php_all_32" -./jenkins/build_and_run_docker.sh diff --git a/jenkins/docker/Dockerfile b/jenkins/docker/Dockerfile deleted file mode 100644 index 8faba4c66725d..0000000000000 --- a/jenkins/docker/Dockerfile +++ /dev/null @@ -1,237 +0,0 @@ -# This Dockerfile specifies the recipe for creating an image for the tests -# to run in. -# -# We install as many test dependencies here as we can, because these setup -# steps can be cached. They do *not* run every time we run the build. -# The Docker image is only rebuilt when the Dockerfile (ie. this file) -# changes. - -# Base Dockerfile for gRPC dev images -FROM debian:latest - -# Apt source for old Python versions. -RUN echo 'deb http://ppa.launchpad.net/fkrull/deadsnakes/ubuntu trusty main' > /etc/apt/sources.list.d/deadsnakes.list && \ - apt-key adv --keyserver keyserver.ubuntu.com --recv-keys DB82666C - -# Apt source for Oracle Java. -RUN echo 'deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main' > /etc/apt/sources.list.d/webupd8team-java-trusty.list && \ - apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EEA14886 && \ - echo "oracle-java7-installer shared/accepted-oracle-license-v1-1 select true" | debconf-set-selections - -# Apt source for Mono -RUN echo "deb http://download.mono-project.com/repo/debian wheezy main" | tee /etc/apt/sources.list.d/mono-xamarin.list && \ - echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list && \ - apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF - -# Apt source for php -RUN echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu trusty main" | tee /etc/apt/sources.list.d/various-php.list && \ - apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F4FCBB07 - -# Install dotnet SDK based on https://www.microsoft.com/net/core#debian -# (Ubuntu instructions need apt to support https) -RUN apt-get update && apt-get install -y --force-yes curl libunwind8 gettext && \ - curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?LinkID=847105 && \ - mkdir -p /opt/dotnet && tar zxf dotnet.tar.gz -C /opt/dotnet && \ - ln -s /opt/dotnet/dotnet /usr/local/bin - -# Install dependencies. We start with the basic ones require to build protoc -# and the C++ build -RUN apt-get clean && apt-get update && apt-get install -y --force-yes \ - autoconf \ - autotools-dev \ - build-essential \ - bzip2 \ - ccache \ - curl \ - gcc \ - git \ - libc6 \ - libc6-dbg \ - libc6-dev \ - libgtest-dev \ - libtool \ - make \ - parallel \ - time \ - wget \ - # -- For csharp -- - mono-devel \ - referenceassemblies-pcl \ - nunit \ - # -- For all Java builds -- \ - maven \ - # -- For java_jdk6 -- \ - # oops! not in jessie. too old? openjdk-6-jdk \ - # -- For java_jdk7 -- \ - openjdk-7-jdk \ - # -- For java_oracle7 -- \ - oracle-java7-installer \ - # -- For python / python_cpp -- \ - python-setuptools \ - python-pip \ - python-dev \ - python2.6-dev \ - python3.3-dev \ - python3.4-dev \ - # -- For Ruby -- - ruby \ - # -- For C++ benchmarks -- - cmake \ - # -- For PHP -- - php5.6 \ - php5.6-dev \ - php5.6-xml \ - php7.0 \ - php7.0-dev \ - php7.0-xml \ - phpunit \ - valgrind \ - libxml2-dev \ - && apt-get clean - -################## -# C# dependencies - -RUN wget www.nuget.org/NuGet.exe -O /usr/local/bin/nuget.exe - -################## -# Python dependencies - -# These packages exist in apt-get, but their versions are too old, so we have -# to get updates from pip. - -RUN pip install pip --upgrade -RUN pip install virtualenv tox yattag - -################## -# Ruby dependencies - -# Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 -RUN \curl -sSL https://get.rvm.io | bash -s stable - -# Install Ruby 2.1, Ruby 2.2 and JRuby 1.7 -RUN /bin/bash -l -c "rvm install ruby-2.1" -RUN /bin/bash -l -c "rvm install ruby-2.2" -RUN /bin/bash -l -c "rvm install jruby-1.7" -RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" -RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" -RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc" - -################## -# Java dependencies - -# This step requires compiling protoc. :( - -ENV MAVEN_REPO /var/maven_local_repository -ENV MVN mvn --batch-mode - -RUN cd /tmp && \ - git clone https://github.com/google/protobuf.git && \ - cd protobuf && \ - git reset --hard 129a6e2aca95dcfb6c3e717d7b9cca1f104fde39 && \ - ./autogen.sh && \ - ./configure && \ - make -j4 && \ - cd java && \ - $MVN install dependency:go-offline -Dmaven.repo.local=$MAVEN_REPO && \ - cd ../javanano && \ - $MVN install dependency:go-offline -Dmaven.repo.local=$MAVEN_REPO - -################## -# PHP dependencies. -RUN wget http://am1.php.net/get/php-5.5.38.tar.bz2/from/this/mirror -RUN mv mirror php-5.5.38.tar.bz2 -RUN tar -xvf php-5.5.38.tar.bz2 -RUN cd php-5.5.38 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-5.5-zts && \ - make && make install && cd .. -RUN cd php-5.5.38 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-5.5 && \ - make && make install && cd .. - -RUN wget http://am1.php.net/get/php-5.6.30.tar.bz2/from/this/mirror -RUN mv mirror php-5.6.30.tar.bz2 -RUN tar -xvf php-5.6.30.tar.bz2 -RUN cd php-5.6.30 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-5.6-zts && \ - make && make install && cd .. -RUN cd php-5.6.30 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-5.6 && \ - make && make install && cd .. - -RUN wget http://am1.php.net/get/php-7.0.18.tar.bz2/from/this/mirror -RUN mv mirror php-7.0.18.tar.bz2 -RUN tar -xvf php-7.0.18.tar.bz2 -RUN cd php-7.0.18 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-7.0-zts && \ - make && make install && cd .. -RUN cd php-7.0.18 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-7.0 && \ - make && make install && cd .. - -RUN wget http://am1.php.net/get/php-7.1.4.tar.bz2/from/this/mirror -RUN mv mirror php-7.1.4.tar.bz2 -RUN tar -xvf php-7.1.4.tar.bz2 -RUN cd php-7.1.4 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-7.1-zts && \ - make && make install && cd .. -RUN cd php-7.1.4 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-7.1 && \ - make && make install && cd .. - -RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" -RUN php composer-setup.php -RUN mv composer.phar /usr/bin/composer -RUN php -r "unlink('composer-setup.php');" -RUN composer config -g -- disable-tls true -RUN composer config -g -- secure-http false -RUN cd /tmp && \ - rm -rf protobuf && \ - git clone https://github.com/google/protobuf.git && \ - cd protobuf && \ - git reset --hard 49b44bff2b6257a119f9c6a342d6151c736586b8 && \ - cd php && \ - ln -sfn /usr/local/php-5.5/bin/php /usr/bin/php && \ - ln -sfn /usr/local/php-5.5/bin/php-config /usr/bin/php-config && \ - ln -sfn /usr/local/php-5.5/bin/phpize /usr/bin/phpize && \ - composer install && \ - mv vendor /usr/local/vendor-5.5 && \ - ln -sfn /usr/local/php-5.6/bin/php /usr/bin/php && \ - ln -sfn /usr/local/php-5.6/bin/php-config /usr/bin/php-config && \ - ln -sfn /usr/local/php-5.6/bin/phpize /usr/bin/phpize && \ - composer install && \ - mv vendor /usr/local/vendor-5.6 && \ - ln -sfn /usr/local/php-7.0/bin/php /usr/bin/php && \ - ln -sfn /usr/local/php-7.0/bin/php-config /usr/bin/php-config && \ - ln -sfn /usr/local/php-7.0/bin/phpize /usr/bin/phpize && \ - composer install && \ - mv vendor /usr/local/vendor-7.0 && \ - ln -sfn /usr/local/php-7.1/bin/php /usr/bin/php && \ - ln -sfn /usr/local/php-7.1/bin/php-config /usr/bin/php-config && \ - ln -sfn /usr/local/php-7.1/bin/phpize /usr/bin/phpize && \ - composer install && \ - mv vendor /usr/local/vendor-7.1 - -################## -# Go dependencies. -RUN apt-get install -y \ - # -- For go -- \ - golang - -################## -# Javascript dependencies. -RUN apt-get install -y \ - # -- For javascript -- \ - npm - -# On Debian/Ubuntu, nodejs binary is named 'nodejs' because the name 'node' -# is taken by another legacy binary. We don't have that legacy binary and -# npm expects the binary to be named 'node', so we just create a symbol -# link here. -RUN ln -s `which nodejs` /usr/bin/node - -################## -# Prepare ccache - -RUN ln -s /usr/bin/ccache /usr/local/bin/gcc -RUN ln -s /usr/bin/ccache /usr/local/bin/g++ -RUN ln -s /usr/bin/ccache /usr/local/bin/cc -RUN ln -s /usr/bin/ccache /usr/local/bin/c++ -RUN ln -s /usr/bin/ccache /usr/local/bin/clang -RUN ln -s /usr/bin/ccache /usr/local/bin/clang++ - -# Define the default command. -CMD ["bash"] diff --git a/jenkins/pull_request_in_docker.sh b/jenkins/pull_request_in_docker.sh deleted file mode 100755 index 10daf0a593f7b..0000000000000 --- a/jenkins/pull_request_in_docker.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash -# -# This is the script that runs inside Docker, once the image has been built, -# to execute all tests for the "pull request" project. - -WORKSPACE_BASE=`pwd` -MY_DIR="$(dirname "$0")" -TEST_SCRIPT=$MY_DIR/../tests.sh -BUILD_DIR=/tmp/protobuf - -set -e # exit immediately on error -set -x # display all commands - -# The protobuf repository is mounted into our Docker image, but read-only. -# We clone into a directory inside Docker (this is faster than cp). -rm -rf $BUILD_DIR -mkdir -p $BUILD_DIR -cd $BUILD_DIR -git clone /var/local/jenkins/protobuf -cd protobuf - -# Set up the directory where our test output is going to go. -OUTPUT_DIR=`mktemp -d` -LOG_OUTPUT_DIR=$OUTPUT_DIR/logs -mkdir -p $LOG_OUTPUT_DIR/1/cpp - -################################################################################ -# cpp build needs to run first, non-parallelized, so that protoc is available -# for other builds. - -# Output filenames to follow the overall scheme used by parallel, ie: -# $DIR/logs/1/cpp/stdout -# $DIR/logs/1/cpp/stderr -# $DIR/logs/1/csharp/stdout -# $DIR/logs/1/csharp/stderr -# $DIR/logs/1/java_jdk7/stdout -# $DIR/logs/1/java_jdk7/stderr -CPP_STDOUT=$LOG_OUTPUT_DIR/1/cpp/stdout -CPP_STDERR=$LOG_OUTPUT_DIR/1/cpp/stderr - -# Time the C++ build, so we can put this info in the test output. -# It's important that we get /usr/bin/time (which supports -f and -o) and not -# the bash builtin "time" which doesn't. -TIME_CMD="/usr/bin/time -f %e -o $LOG_OUTPUT_DIR/1/cpp/build_time" - -$TIME_CMD $TEST_SCRIPT cpp > >(tee $CPP_STDOUT) 2> >(tee $CPP_STDERR >&2) - -# Other tests are run in parallel. TEST_SET is defined in -# buildcmds/pull_request{_32}.sh - -parallel --results $LOG_OUTPUT_DIR --joblog $OUTPUT_DIR/joblog $TEST_SCRIPT ::: \ - $TEST_SET \ - || true # Process test results even if tests fail. - -cat $OUTPUT_DIR/joblog - -# The directory that is copied from Docker back into the Jenkins workspace. -COPY_FROM_DOCKER=/var/local/git/protobuf/testoutput -mkdir -p $COPY_FROM_DOCKER -TESTOUTPUT_XML_FILE=$COPY_FROM_DOCKER/testresults.xml - -# Process all the output files from "parallel" and package them into a single -# .xml file with detailed, broken-down test output. -python $MY_DIR/make_test_output.py $OUTPUT_DIR > $TESTOUTPUT_XML_FILE - -ls -l $TESTOUTPUT_XML_FILE diff --git a/js/README.md b/js/README.md index 24386dc7d526e..3635028fd5d7d 100644 --- a/js/README.md +++ b/js/README.md @@ -1,7 +1,7 @@ Protocol Buffers - Google's data interchange format =================================================== -[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) +[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjavascript%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fjavascript%2Fcontinuous) Copyright 2008 Google Inc. @@ -19,13 +19,13 @@ resolve imports at compile time. To use Protocol Buffers with JavaScript, you need two main components: 1. The protobuf runtime library. You can install this with - `npm install google-protobuf`, or use the files in this directory. - If npm is not being used, as of 3.3.0, the files needed are located in binary subdirectory; + `npm install google-protobuf`, or use the files in this directory. + If npm is not being used, as of 3.3.0, the files needed are located in binary subdirectory; arith.js, constants.js, decoder.js, encoder.js, map.js, message.js, reader.js, utils.js, writer.js 2. The Protocol Compiler `protoc`. This translates `.proto` files into `.js` files. The compiler is not currently available via npm, but you can download a pre-built binary - [on GitHub](https://github.com/google/protobuf/releases) + [on GitHub](https://github.com/protocolbuffers/protobuf/releases) (look for the `protoc-*.zip` files under **Downloads**). @@ -33,11 +33,11 @@ Setup ===== First, obtain the Protocol Compiler. The easiest way is to download -a pre-built binary from [https://github.com/google/protobuf/releases](https://github.com/google/protobuf/releases). +a pre-built binary from [https://github.com/protocolbuffers/protobuf/releases](https://github.com/protocolbuffers/protobuf/releases). If you want, you can compile `protoc` from source instead. To do this follow the instructions in [the top-level -README](https://github.com/google/protobuf/blob/master/src/README.md). +README](https://github.com/protocolbuffers/protobuf/blob/master/src/README.md). Once you have `protoc` compiled, you can run the tests by typing: @@ -135,7 +135,7 @@ The syntax of the `--js_out` flag is: Where `OPTIONS` are separated by commas. Options are either `opt=val` or just `opt` (for options that don't take a value). The available options are specified and documented in the `GeneratorOptions` struct in -[src/google/protobuf/compiler/js/js_generator.h](https://github.com/google/protobuf/blob/master/src/google/protobuf/compiler/js/js_generator.h#L53). +[src/google/protobuf/compiler/js/js_generator.h](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/compiler/js/js_generator.h#L53). Some examples: @@ -144,6 +144,7 @@ Some examples: The `import_style` option is left to the default, which is `closure`. - `--js_out=import_style=commonjs,binary:protos`: this contains the options `import_style=commonjs` and `binary` and outputs to the directory `protos`. + `import_style=commonjs_strict` doesn't expose the output on the global scope. API === @@ -158,7 +159,7 @@ idea of how the library generally works: message.setPhoneNumbers(["800-555-1212", "800-555-0000"]); // Serializes to a UInt8Array. - bytes = message.serializeBinary(); + var bytes = message.serializeBinary(); var message2 = MyMessage.deserializeBinary(bytes); diff --git a/js/binary/arith.js b/js/binary/arith.js index 70257de7169f0..62528a263a9ab 100644 --- a/js/binary/arith.js +++ b/js/binary/arith.js @@ -221,7 +221,7 @@ jspb.arith.UInt64.prototype.mul = function(a) { * Divide a 64-bit number by a 32-bit number to produce a * 64-bit quotient and a 32-bit remainder. * @param {number} _divisor - * @return {Array.} array of [quotient, remainder], + * @return {Array} array of [quotient, remainder], * unless divisor is 0, in which case an empty array is returned. */ jspb.arith.UInt64.prototype.div = function(_divisor) { diff --git a/js/binary/arith_test.js b/js/binary/arith_test.js index 89796bf795079..dd5791a7bb89e 100644 --- a/js/binary/arith_test.js +++ b/js/binary/arith_test.js @@ -36,7 +36,6 @@ * @author cfallin@google.com (Chris Fallin) */ -goog.require('goog.testing.asserts'); goog.require('jspb.arith.Int64'); goog.require('jspb.arith.UInt64'); @@ -48,30 +47,30 @@ describe('binaryArithTest', function() { it('testCompare', function() { var a = new jspb.arith.UInt64(1234, 5678); var b = new jspb.arith.UInt64(1234, 5678); - assertEquals(a.cmp(b), 0); - assertEquals(b.cmp(a), 0); + expect(a.cmp(b)).toEqual(0); + expect(b.cmp(a)).toEqual(0); b.lo -= 1; - assertEquals(a.cmp(b), 1); - assertEquals(b.cmp(a), -1); + expect(a.cmp(b)).toEqual(1); + expect(b.cmp(a)).toEqual(-1); b.lo += 2; - assertEquals(a.cmp(b), -1); - assertEquals(b.cmp(a), 1); + expect(a.cmp(b)).toEqual(-1); + expect(b.cmp(a)).toEqual(1); b.lo = a.lo; b.hi = a.hi - 1; - assertEquals(a.cmp(b), 1); - assertEquals(b.cmp(a), -1); + expect(a.cmp(b)).toEqual(1); + expect(b.cmp(a)).toEqual(-1); - assertEquals(a.zero(), false); - assertEquals(a.msb(), false); - assertEquals(a.lsb(), false); + expect(a.zero()).toEqual(false); + expect(a.msb()).toEqual(false); + expect(a.lsb()).toEqual(false); a.hi = 0; a.lo = 0; - assertEquals(a.zero(), true); + expect(a.zero()).toEqual(true); a.hi = 0x80000000; - assertEquals(a.zero(), false); - assertEquals(a.msb(), true); + expect(a.zero()).toEqual(false); + expect(a.msb()).toEqual(true); a.lo = 0x00000001; - assertEquals(a.lsb(), true); + expect(a.lsb()).toEqual(true); }); @@ -80,35 +79,35 @@ describe('binaryArithTest', function() { */ it('testShifts', function() { var a = new jspb.arith.UInt64(1, 0); - assertEquals(a.lo, 1); - assertEquals(a.hi, 0); + expect(a.lo).toEqual(1); + expect(a.hi).toEqual(0); var orig = a; a = a.leftShift(); - assertEquals(orig.lo, 1); // original unmodified. - assertEquals(orig.hi, 0); - assertEquals(a.lo, 2); - assertEquals(a.hi, 0); + expect(orig.lo).toEqual(1); // original unmodified. + expect(orig.hi).toEqual(0); + expect(a.lo).toEqual(2); + expect(a.hi).toEqual(0); a = a.leftShift(); - assertEquals(a.lo, 4); - assertEquals(a.hi, 0); + expect(a.lo).toEqual(4); + expect(a.hi).toEqual(0); for (var i = 0; i < 29; i++) { a = a.leftShift(); } - assertEquals(a.lo, 0x80000000); - assertEquals(a.hi, 0); + expect(a.lo).toEqual(0x80000000); + expect(a.hi).toEqual(0); a = a.leftShift(); - assertEquals(a.lo, 0); - assertEquals(a.hi, 1); + expect(a.lo).toEqual(0); + expect(a.hi).toEqual(1); a = a.leftShift(); - assertEquals(a.lo, 0); - assertEquals(a.hi, 2); + expect(a.lo).toEqual(0); + expect(a.hi).toEqual(2); a = a.rightShift(); a = a.rightShift(); - assertEquals(a.lo, 0x80000000); - assertEquals(a.hi, 0); + expect(a.lo).toEqual(0x80000000); + expect(a.hi).toEqual(0); a = a.rightShift(); - assertEquals(a.lo, 0x40000000); - assertEquals(a.hi, 0); + expect(a.lo).toEqual(0x40000000); + expect(a.hi).toEqual(0); }); @@ -122,12 +121,12 @@ describe('binaryArithTest', function() { /* hi = */ 0x92fa2123); // Addition with carry. var c = a.add(b); - assertEquals(a.lo, 0x89abcdef); // originals unmodified. - assertEquals(a.hi, 0x01234567); - assertEquals(b.lo, 0xff52ab91); - assertEquals(b.hi, 0x92fa2123); - assertEquals(c.lo, 0x88fe7980); - assertEquals(c.hi, 0x941d668b); + expect(a.lo).toEqual(0x89abcdef); // originals unmodified. + expect(a.hi).toEqual(0x01234567); + expect(b.lo).toEqual(0xff52ab91); + expect(b.hi).toEqual(0x92fa2123); + expect(c.lo).toEqual(0x88fe7980); + expect(c.hi).toEqual(0x941d668b); // Simple addition without carry. a.lo = 2; @@ -135,8 +134,8 @@ describe('binaryArithTest', function() { b.lo = 3; b.hi = 0; c = a.add(b); - assertEquals(c.lo, 5); - assertEquals(c.hi, 0); + expect(c.lo).toEqual(5); + expect(c.hi).toEqual(0); }); @@ -170,8 +169,8 @@ describe('binaryArithTest', function() { var a = new jspb.arith.UInt64(loValues[i], hiValues[j]); var b = new jspb.arith.UInt64(loValues[j], hiValues[i]); var c = a.add(b).sub(b); - assertEquals(c.hi, a.hi); - assertEquals(c.lo, a.lo); + expect(c.hi).toEqual(a.hi); + expect(c.lo).toEqual(a.lo); } } }); @@ -201,8 +200,8 @@ describe('binaryArithTest', function() { var cLow = testData[i][2] >>> 0; var cHigh = testData[i][3] >>> 0; var c = jspb.arith.UInt64.mul32x32(a, b); - assertEquals(c.lo, cLow); - assertEquals(c.hi, cHigh); + expect(c.lo).toEqual(cLow); + expect(c.hi).toEqual(cHigh); } }); @@ -231,8 +230,8 @@ describe('binaryArithTest', function() { for (var i = 0; i < testData.length; i++) { var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]); var prod = a.mul(testData[i][2]); - assertEquals(prod.lo, testData[i][3]); - assertEquals(prod.hi, testData[i][4]); + expect(prod.lo).toEqual(testData[i][3]); + expect(prod.hi).toEqual(testData[i][4]); } }); @@ -274,9 +273,9 @@ describe('binaryArithTest', function() { var result = a.div(testData[i][2]); var quotient = result[0]; var remainder = result[1]; - assertEquals(quotient.lo, testData[i][3]); - assertEquals(quotient.hi, testData[i][4]); - assertEquals(remainder.lo, testData[i][5]); + expect(quotient.lo).toEqual(testData[i][3]); + expect(quotient.hi).toEqual(testData[i][4]); + expect(remainder.lo).toEqual(testData[i][5]); } }); @@ -311,9 +310,9 @@ describe('binaryArithTest', function() { for (var i = 0; i < testData.length; i++) { var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]); var roundtrip = jspb.arith.UInt64.fromString(a.toString()); - assertEquals(roundtrip.lo, a.lo); - assertEquals(roundtrip.hi, a.hi); - assertEquals(a.toString(), testData[i][2]); + expect(roundtrip.lo).toEqual(a.lo); + expect(roundtrip.hi).toEqual(a.hi); + expect(a.toString()).toEqual(testData[i][2]); } }); @@ -349,7 +348,7 @@ describe('binaryArithTest', function() { for (var i = 0; i < testStrings.length; i++) { var roundtrip = jspb.arith.Int64.fromString(testStrings[i]).toString(); - assertEquals(roundtrip, testStrings[i]); + expect(roundtrip).toEqual(testStrings[i]); } }); }); diff --git a/js/binary/constants.js b/js/binary/constants.js index ef5fecddc5040..d2e62e5b0f6cf 100644 --- a/js/binary/constants.js +++ b/js/binary/constants.js @@ -31,6 +31,7 @@ /** * @fileoverview This file contains constants and typedefs used by * jspb.BinaryReader and BinaryWriter. + * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * * @author aappleby@google.com (Austin Appleby) */ @@ -51,20 +52,34 @@ goog.provide('jspb.ScalarFieldType'); goog.provide('jspb.WriterFunction'); +goog.forwardDeclare('jspb.BinaryMessage'); +goog.forwardDeclare('jspb.BinaryReader'); +goog.forwardDeclare('jspb.BinaryWriter'); goog.forwardDeclare('jspb.Message'); -goog.forwardDeclare('jsproto.BinaryExtension'); +goog.forwardDeclare('jsprotolib.BinaryExtension'); /** - * Base interface class for all const messages. Does __not__ define any - * methods, as doing so on a widely-used interface defeats dead-code - * elimination. + * Base interface class for all const messages. * @interface */ jspb.ConstBinaryMessage = function() {}; +/** + * Generate a debug string for this proto that is in proto2 text format. + * @return {string} The debug string. + */ +jspb.ConstBinaryMessage.prototype.toDebugString; +/** + * Helper to generate a debug string for this proto at some indent level. The + * first line is not indented. + * @param {number} indentLevel The number of spaces by which to indent lines. + * @return {string} The debug string. + * @protected + */ +jspb.ConstBinaryMessage.prototype.toDebugStringInternal; /** * Base interface class for all messages. Does __not__ define any methods, as @@ -94,6 +109,7 @@ jspb.ScalarFieldType; * A repeated field in jspb is an array of scalars, blobs, or messages. * @typedef {!Array| !Array| + !Array| !Array} */ jspb.RepeatedFieldType; @@ -105,8 +121,9 @@ jspb.RepeatedFieldType; * @typedef {jspb.ScalarFieldType| jspb.RepeatedFieldType| !Uint8Array| + !jspb.ConstBinaryMessage| !jspb.BinaryMessage| - !jsproto.BinaryExtension} + !jsprotolib.BinaryExtension} */ jspb.AnyFieldType; @@ -158,7 +175,7 @@ jspb.PrunerFunction; /** * A comparer function returns true if two protos are equal. - * @typedef {!function(?jspb.ConstBinaryMessage, + * @typedef {function(?jspb.ConstBinaryMessage, * ?jspb.ConstBinaryMessage):boolean} */ jspb.ComparerFunction; diff --git a/js/binary/decoder.js b/js/binary/decoder.js index 6db28e7c33129..fb40ec99e3f08 100644 --- a/js/binary/decoder.js +++ b/js/binary/decoder.js @@ -40,175 +40,18 @@ * intact, you _must_ read them using one of the Hash64 methods, which return * an 8-character string. * + * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * @author aappleby@google.com (Austin Appleby) */ goog.provide('jspb.BinaryDecoder'); -goog.provide('jspb.BinaryIterator'); goog.require('goog.asserts'); +goog.require('goog.crypt'); goog.require('jspb.utils'); -/** - * Simple helper class for traversing the contents of repeated scalar fields. - * that may or may not have been packed into a wire-format blob. - * @param {?jspb.BinaryDecoder=} opt_decoder - * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=} - * opt_next The decoder method to use for next(). - * @param {?Array.=} opt_elements - * @constructor - * @struct - */ -jspb.BinaryIterator = function(opt_decoder, opt_next, opt_elements) { - /** @private {jspb.BinaryDecoder} */ - this.decoder_ = null; - - /** - * The BinaryDecoder member function used when iterating over packed data. - * @private {?function(this:jspb.BinaryDecoder):(number|boolean|string)} - */ - this.nextMethod_ = null; - - /** @private {?Array} */ - this.elements_ = null; - - /** @private {number} */ - this.cursor_ = 0; - - /** @private {number|boolean|string|null} */ - this.nextValue_ = null; - - /** @private {boolean} */ - this.atEnd_ = true; - - this.init_(opt_decoder, opt_next, opt_elements); -}; - - -/** - * @param {?jspb.BinaryDecoder=} opt_decoder - * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=} - * opt_next The decoder method to use for next(). - * @param {?Array.=} opt_elements - * @private - */ -jspb.BinaryIterator.prototype.init_ = - function(opt_decoder, opt_next, opt_elements) { - if (opt_decoder && opt_next) { - this.decoder_ = opt_decoder; - this.nextMethod_ = opt_next; - } - this.elements_ = opt_elements || null; - this.cursor_ = 0; - this.nextValue_ = null; - this.atEnd_ = !this.decoder_ && !this.elements_; - - this.next(); -}; - - -/** - * Global pool of BinaryIterator instances. - * @private {!Array.} - */ -jspb.BinaryIterator.instanceCache_ = []; - - -/** - * Allocates a BinaryIterator from the cache, creating a new one if the cache - * is empty. - * @param {?jspb.BinaryDecoder=} opt_decoder - * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=} - * opt_next The decoder method to use for next(). - * @param {?Array.=} opt_elements - * @return {!jspb.BinaryIterator} - */ -jspb.BinaryIterator.alloc = function(opt_decoder, opt_next, opt_elements) { - if (jspb.BinaryIterator.instanceCache_.length) { - var iterator = jspb.BinaryIterator.instanceCache_.pop(); - iterator.init_(opt_decoder, opt_next, opt_elements); - return iterator; - } else { - return new jspb.BinaryIterator(opt_decoder, opt_next, opt_elements); - } -}; - - -/** - * Puts this instance back in the instance cache. - */ -jspb.BinaryIterator.prototype.free = function() { - this.clear(); - if (jspb.BinaryIterator.instanceCache_.length < 100) { - jspb.BinaryIterator.instanceCache_.push(this); - } -}; - - -/** - * Clears the iterator. - */ -jspb.BinaryIterator.prototype.clear = function() { - if (this.decoder_) { - this.decoder_.free(); - } - this.decoder_ = null; - this.nextMethod_ = null; - this.elements_ = null; - this.cursor_ = 0; - this.nextValue_ = null; - this.atEnd_ = true; -}; - - -/** - * Returns the element at the iterator, or null if the iterator is invalid or - * past the end of the decoder/array. - * @return {number|boolean|string|null} - */ -jspb.BinaryIterator.prototype.get = function() { - return this.nextValue_; -}; - - -/** - * Returns true if the iterator is at the end of the decoder/array. - * @return {boolean} - */ -jspb.BinaryIterator.prototype.atEnd = function() { - return this.atEnd_; -}; - - -/** - * Returns the element at the iterator and steps to the next element, - * equivalent to '*pointer++' in C. - * @return {number|boolean|string|null} - */ -jspb.BinaryIterator.prototype.next = function() { - var lastValue = this.nextValue_; - if (this.decoder_) { - if (this.decoder_.atEnd()) { - this.nextValue_ = null; - this.atEnd_ = true; - } else { - this.nextValue_ = this.nextMethod_.call(this.decoder_); - } - } else if (this.elements_) { - if (this.cursor_ == this.elements_.length) { - this.nextValue_ = null; - this.atEnd_ = true; - } else { - this.nextValue_ = this.elements_[this.cursor_++]; - } - } - return lastValue; -}; - - - /** * BinaryDecoder implements the decoders for all the wire types specified in * https://developers.google.com/protocol-buffers/docs/encoding. @@ -245,20 +88,6 @@ jspb.BinaryDecoder = function(opt_bytes, opt_start, opt_length) { */ this.cursor_ = 0; - /** - * Temporary storage for the low 32 bits of 64-bit data types that we're - * decoding. - * @private {number} - */ - this.tempLow_ = 0; - - /** - * Temporary storage for the high 32 bits of 64-bit data types that we're - * decoding. - * @private {number} - */ - this.tempHigh_ = 0; - /** * Set to true if this decoder encountered an error due to corrupt data. * @private {boolean} @@ -273,7 +102,7 @@ jspb.BinaryDecoder = function(opt_bytes, opt_start, opt_length) { /** * Global pool of BinaryDecoder instances. - * @private {!Array.} + * @private {!Array} */ jspb.BinaryDecoder.instanceCache_ = []; @@ -352,9 +181,9 @@ jspb.BinaryDecoder.prototype.getBuffer = function() { jspb.BinaryDecoder.prototype.setBlock = function(data, opt_start, opt_length) { this.bytes_ = jspb.utils.byteSourceToUint8Array(data); - this.start_ = goog.isDef(opt_start) ? opt_start : 0; - this.end_ = - goog.isDef(opt_length) ? this.start_ + opt_length : this.bytes_.length; + this.start_ = (opt_start !== undefined) ? opt_start : 0; + this.end_ = (opt_length !== undefined) ? this.start_ + opt_length : + this.bytes_.length; this.cursor_ = this.start_; }; @@ -441,9 +270,9 @@ jspb.BinaryDecoder.prototype.getError = function() { /** - * Reads an unsigned varint from the binary stream and stores it as a split - * 64-bit integer. Since this does not convert the value to a number, no - * precision is lost. + * Reads an unsigned varint from the binary stream and invokes the conversion + * function with the value in two signed 32 bit integers to produce the result. + * Since this does not convert the value to a number, no precision is lost. * * It's possible for an unsigned varint to be incorrectly encoded - more than * 64 bits' worth of data could be present. If this happens, this method will @@ -453,52 +282,98 @@ jspb.BinaryDecoder.prototype.getError = function() { * details on the format, see * https://developers.google.com/protocol-buffers/docs/encoding * - * @private + * @param {function(number, number): T} convert Conversion function to produce + * the result value, takes parameters (lowBits, highBits). + * @return {T} + * @template T */ -jspb.BinaryDecoder.prototype.readSplitVarint64_ = function() { - var temp; +jspb.BinaryDecoder.prototype.readSplitVarint64 = function(convert) { + var temp = 128; var lowBits = 0; var highBits = 0; // Read the first four bytes of the varint, stopping at the terminator if we // see it. - for (var i = 0; i < 4; i++) { + for (var i = 0; i < 4 && temp >= 128; i++) { temp = this.bytes_[this.cursor_++]; lowBits |= (temp & 0x7F) << (i * 7); - if (temp < 128) { - this.tempLow_ = lowBits >>> 0; - this.tempHigh_ = 0; - return; - } } - // Read the fifth byte, which straddles the low and high dwords. - temp = this.bytes_[this.cursor_++]; - lowBits |= (temp & 0x7F) << 28; - highBits |= (temp & 0x7F) >> 4; - if (temp < 128) { - this.tempLow_ = lowBits >>> 0; - this.tempHigh_ = highBits >>> 0; - return; + if (temp >= 128) { + // Read the fifth byte, which straddles the low and high dwords. + temp = this.bytes_[this.cursor_++]; + lowBits |= (temp & 0x7F) << 28; + highBits |= (temp & 0x7F) >> 4; } - // Read the sixth through tenth byte. - for (var i = 0; i < 5; i++) { - temp = this.bytes_[this.cursor_++]; - highBits |= (temp & 0x7F) << (i * 7 + 3); - if (temp < 128) { - this.tempLow_ = lowBits >>> 0; - this.tempHigh_ = highBits >>> 0; - return; + if (temp >= 128) { + // Read the sixth through tenth byte. + for (var i = 0; i < 5 && temp >= 128; i++) { + temp = this.bytes_[this.cursor_++]; + highBits |= (temp & 0x7F) << (i * 7 + 3); } } + if (temp < 128) { + return convert(lowBits >>> 0, highBits >>> 0); + } + // If we did not see the terminator, the encoding was invalid. goog.asserts.fail('Failed to read varint, encoding is invalid.'); this.error_ = true; }; +/** + * Reads a signed zigzag encoded varint from the binary stream and invokes + * the conversion function with the value in two signed 32 bit integers to + * produce the result. Since this does not convert the value to a number, no + * precision is lost. + * + * It's possible for an unsigned varint to be incorrectly encoded - more than + * 64 bits' worth of data could be present. If this happens, this method will + * throw an error. + * + * Zigzag encoding is a modification of varint encoding that reduces the + * storage overhead for small negative integers - for more details on the + * format, see https://developers.google.com/protocol-buffers/docs/encoding + * + * @param {function(number, number): T} convert Conversion function to produce + * the result value, takes parameters (lowBits, highBits). + * @return {T} + * @template T + */ +jspb.BinaryDecoder.prototype.readSplitZigzagVarint64 = function(convert) { + return this.readSplitVarint64(function(low, high) { + return jspb.utils.fromZigzag64(low, high, convert); + }); +}; + + +/** + * Reads a 64-bit fixed-width value from the stream and invokes the conversion + * function with the value in two signed 32 bit integers to produce the result. + * Since this does not convert the value to a number, no precision is lost. + * + * @param {function(number, number): T} convert Conversion function to produce + * the result value, takes parameters (lowBits, highBits). + * @return {T} + * @template T + */ +jspb.BinaryDecoder.prototype.readSplitFixed64 = function(convert) { + var bytes = this.bytes_; + var cursor = this.cursor_; + this.cursor_ += 8; + var lowBits = 0; + var highBits = 0; + for (var i = cursor + 7; i >= cursor; i--) { + lowBits = (lowBits << 8) | bytes[i]; + highBits = (highBits << 8) | bytes[i + 4]; + } + return convert(lowBits, highBits); +}; + + /** * Skips over a varint in the block without decoding it. */ @@ -582,27 +457,24 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { x |= (temp & 0x0F) << 28; if (temp < 128) { // We're reading the high bits of an unsigned varint. The byte we just read - // also contains bits 33 through 35, which we're going to discard. Those - // bits _must_ be zero, or the encoding is invalid. - goog.asserts.assert((temp & 0xF0) == 0); + // also contains bits 33 through 35, which we're going to discard. this.cursor_ += 5; goog.asserts.assert(this.cursor_ <= this.end_); return x >>> 0; } - // If we get here, we're reading the sign extension of a negative 32-bit int. - // We can skip these bytes, as we know in advance that they have to be all - // 1's if the varint is correctly encoded. Since we also know the value is - // negative, we don't have to coerce it to unsigned before we return it. - - goog.asserts.assert((temp & 0xF0) == 0xF0); - goog.asserts.assert(bytes[this.cursor_ + 5] == 0xFF); - goog.asserts.assert(bytes[this.cursor_ + 6] == 0xFF); - goog.asserts.assert(bytes[this.cursor_ + 7] == 0xFF); - goog.asserts.assert(bytes[this.cursor_ + 8] == 0xFF); - goog.asserts.assert(bytes[this.cursor_ + 9] == 0x01); + // If we get here, we need to truncate coming bytes. However we need to make + // sure cursor place is correct. + this.cursor_ += 5; + if (bytes[this.cursor_++] >= 128 && + bytes[this.cursor_++] >= 128 && + bytes[this.cursor_++] >= 128 && + bytes[this.cursor_++] >= 128 && + bytes[this.cursor_++] >= 128) { + // If we get here, the varint is too long. + goog.asserts.assert(false); + } - this.cursor_ += 10; goog.asserts.assert(this.cursor_ <= this.end_); return x; }; @@ -670,8 +542,7 @@ jspb.BinaryDecoder.prototype.readZigzagVarint32 = function() { * integer exceeds 2^53. */ jspb.BinaryDecoder.prototype.readUnsignedVarint64 = function() { - this.readSplitVarint64_(); - return jspb.utils.joinUint64(this.tempLow_, this.tempHigh_); + return this.readSplitVarint64(jspb.utils.joinUint64); }; @@ -682,8 +553,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint64 = function() { * @return {string} The decoded unsigned varint as a decimal string. */ jspb.BinaryDecoder.prototype.readUnsignedVarint64String = function() { - this.readSplitVarint64_(); - return jspb.utils.joinUnsignedDecimalString(this.tempLow_, this.tempHigh_); + return this.readSplitVarint64(jspb.utils.joinUnsignedDecimalString); }; @@ -696,8 +566,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint64String = function() { * integer exceeds 2^53. */ jspb.BinaryDecoder.prototype.readSignedVarint64 = function() { - this.readSplitVarint64_(); - return jspb.utils.joinInt64(this.tempLow_, this.tempHigh_); + return this.readSplitVarint64(jspb.utils.joinInt64); }; @@ -708,8 +577,7 @@ jspb.BinaryDecoder.prototype.readSignedVarint64 = function() { * @return {string} The decoded signed varint as a decimal string. */ jspb.BinaryDecoder.prototype.readSignedVarint64String = function() { - this.readSplitVarint64_(); - return jspb.utils.joinSignedDecimalString(this.tempLow_, this.tempHigh_); + return this.readSplitVarint64(jspb.utils.joinSignedDecimalString); }; @@ -727,14 +595,29 @@ jspb.BinaryDecoder.prototype.readSignedVarint64String = function() { * integer exceeds 2^53. */ jspb.BinaryDecoder.prototype.readZigzagVarint64 = function() { - this.readSplitVarint64_(); - return jspb.utils.joinZigzag64(this.tempLow_, this.tempHigh_); + return this.readSplitVarint64(jspb.utils.joinZigzag64); +}; + + +/** + * Reads a signed, zigzag-encoded 64-bit varint from the binary stream + * losslessly and returns it as an 8-character Unicode string for use as a hash + * table key. + * + * Zigzag encoding is a modification of varint encoding that reduces the + * storage overhead for small negative integers - for more details on the + * format, see https://developers.google.com/protocol-buffers/docs/encoding + * + * @return {string} The decoded zigzag varint in hash64 format. + */ +jspb.BinaryDecoder.prototype.readZigzagVarintHash64 = function() { + return this.readSplitZigzagVarint64(jspb.utils.joinHash64); }; /** * Reads a signed, zigzag-encoded 64-bit varint from the binary stream and - * returns its valud as a string. + * returns its value as a string. * * Zigzag encoding is a modification of varint encoding that reduces the * storage overhead for small negative integers - for more details on the @@ -744,9 +627,7 @@ jspb.BinaryDecoder.prototype.readZigzagVarint64 = function() { * string. */ jspb.BinaryDecoder.prototype.readZigzagVarint64String = function() { - // TODO(haberman): write lossless 64-bit zig-zag math. - var value = this.readZigzagVarint64(); - return value.toString(); + return this.readSplitZigzagVarint64(jspb.utils.joinSignedDecimalString); }; @@ -868,7 +749,7 @@ jspb.BinaryDecoder.prototype.readInt32 = function() { /** * Reads a raw signed 64-bit integer from the binary stream. Note that since * Javascript represents all numbers as double-precision floats, there will be - * precision lost if the absolute vlaue of the integer is larger than 2^53. + * precision lost if the absolute value of the integer is larger than 2^53. * * @return {number} The signed 64-bit integer read from the binary stream. * Precision will be lost if the integer exceeds 2^53. @@ -988,7 +869,7 @@ jspb.BinaryDecoder.prototype.readString = function(length) { codeUnits.push(high, low); } - // Avoid exceeding the maximum stack size when calling {@code apply}. + // Avoid exceeding the maximum stack size when calling `apply`. if (codeUnits.length >= 8192) { result += String.fromCharCode.apply(null, codeUnits); codeUnits.length = 0; @@ -1041,8 +922,7 @@ jspb.BinaryDecoder.prototype.readBytes = function(length) { * @return {string} The hash value. */ jspb.BinaryDecoder.prototype.readVarintHash64 = function() { - this.readSplitVarint64_(); - return jspb.utils.joinHash64(this.tempLow_, this.tempHigh_); + return this.readSplitVarint64(jspb.utils.joinHash64); }; diff --git a/js/binary/decoder_test.js b/js/binary/decoder_test.js index d0139e293a61d..0fddc4b3445a6 100644 --- a/js/binary/decoder_test.js +++ b/js/binary/decoder_test.js @@ -45,6 +45,7 @@ goog.require('goog.testing.asserts'); goog.require('jspb.BinaryConstants'); goog.require('jspb.BinaryDecoder'); goog.require('jspb.BinaryEncoder'); +goog.require('jspb.utils'); /** @@ -140,8 +141,14 @@ function doTestSignedValue(readValue, } // Encoding values outside the valid range should assert. - assertThrows(function() {writeValue.call(encoder, lowerLimit * 1.1);}); - assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);}); + var pastLowerLimit = lowerLimit * 1.1; + var pastUpperLimit = upperLimit * 1.1; + if (pastLowerLimit !== -Infinity) { + expect(() => void writeValue.call(encoder, pastLowerLimit)).toThrow(); + } + if (pastUpperLimit !== Infinity) { + expect(() => void writeValue.call(encoder, pastUpperLimit)).toThrow(); + } } describe('binaryDecoderTest', function() { @@ -172,11 +179,9 @@ describe('binaryDecoderTest', function() { }); - /** - * Tests reading 64-bit integers as hash strings. - */ - it('testHashStrings', function() { - var encoder = new jspb.BinaryEncoder(); + describe('varint64', function() { + var /** !jspb.BinaryEncoder */ encoder; + var /** !jspb.BinaryDecoder */ decoder; var hashA = String.fromCharCode(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); @@ -186,28 +191,146 @@ describe('binaryDecoderTest', function() { 0x87, 0x65, 0x43, 0x21); var hashD = String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + beforeEach(function() { + encoder = new jspb.BinaryEncoder(); + + encoder.writeVarintHash64(hashA); + encoder.writeVarintHash64(hashB); + encoder.writeVarintHash64(hashC); + encoder.writeVarintHash64(hashD); + + encoder.writeFixedHash64(hashA); + encoder.writeFixedHash64(hashB); + encoder.writeFixedHash64(hashC); + encoder.writeFixedHash64(hashD); + + decoder = jspb.BinaryDecoder.alloc(encoder.end()); + }); + + it('reads 64-bit integers as hash strings', function() { + assertEquals(hashA, decoder.readVarintHash64()); + assertEquals(hashB, decoder.readVarintHash64()); + assertEquals(hashC, decoder.readVarintHash64()); + assertEquals(hashD, decoder.readVarintHash64()); + + assertEquals(hashA, decoder.readFixedHash64()); + assertEquals(hashB, decoder.readFixedHash64()); + assertEquals(hashC, decoder.readFixedHash64()); + assertEquals(hashD, decoder.readFixedHash64()); + }); + + it('reads split 64 bit integers', function() { + function hexJoin(bitsLow, bitsHigh) { + return `0x${(bitsHigh >>> 0).toString(16)}:0x${ + (bitsLow >>> 0).toString(16)}`; + } + function hexJoinHash(hash64) { + jspb.utils.splitHash64(hash64); + return hexJoin(jspb.utils.split64Low, jspb.utils.split64High); + } + + expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashA)); + expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashB)); + expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashC)); + expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashD)); + + expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashA)); + expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashB)); + expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashC)); + expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashD)); + }); + }); - encoder.writeVarintHash64(hashA); - encoder.writeVarintHash64(hashB); - encoder.writeVarintHash64(hashC); - encoder.writeVarintHash64(hashD); - - encoder.writeFixedHash64(hashA); - encoder.writeFixedHash64(hashB); - encoder.writeFixedHash64(hashC); - encoder.writeFixedHash64(hashD); - - var decoder = jspb.BinaryDecoder.alloc(encoder.end()); - - assertEquals(hashA, decoder.readVarintHash64()); - assertEquals(hashB, decoder.readVarintHash64()); - assertEquals(hashC, decoder.readVarintHash64()); - assertEquals(hashD, decoder.readVarintHash64()); - - assertEquals(hashA, decoder.readFixedHash64()); - assertEquals(hashB, decoder.readFixedHash64()); - assertEquals(hashC, decoder.readFixedHash64()); - assertEquals(hashD, decoder.readFixedHash64()); + describe('sint64', function() { + var /** !jspb.BinaryDecoder */ decoder; + + var hashA = + String.fromCharCode(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + var hashB = + String.fromCharCode(0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + var hashC = + String.fromCharCode(0x12, 0x34, 0x56, 0x78, 0x87, 0x65, 0x43, 0x21); + var hashD = + String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + beforeEach(function() { + var encoder = new jspb.BinaryEncoder(); + + encoder.writeZigzagVarintHash64(hashA); + encoder.writeZigzagVarintHash64(hashB); + encoder.writeZigzagVarintHash64(hashC); + encoder.writeZigzagVarintHash64(hashD); + + decoder = jspb.BinaryDecoder.alloc(encoder.end()); + }); + + it('reads 64-bit integers as decimal strings', function() { + const signed = true; + expect(decoder.readZigzagVarint64String()) + .toEqual(jspb.utils.hash64ToDecimalString(hashA, signed)); + expect(decoder.readZigzagVarint64String()) + .toEqual(jspb.utils.hash64ToDecimalString(hashB, signed)); + expect(decoder.readZigzagVarint64String()) + .toEqual(jspb.utils.hash64ToDecimalString(hashC, signed)); + expect(decoder.readZigzagVarint64String()) + .toEqual(jspb.utils.hash64ToDecimalString(hashD, signed)); + }); + + it('reads 64-bit integers as hash strings', function() { + expect(decoder.readZigzagVarintHash64()).toEqual(hashA); + expect(decoder.readZigzagVarintHash64()).toEqual(hashB); + expect(decoder.readZigzagVarintHash64()).toEqual(hashC); + expect(decoder.readZigzagVarintHash64()).toEqual(hashD); + }); + + it('reads split 64 bit zigzag integers', function() { + function hexJoin(bitsLow, bitsHigh) { + return `0x${(bitsHigh >>> 0).toString(16)}:0x${ + (bitsLow >>> 0).toString(16)}`; + } + function hexJoinHash(hash64) { + jspb.utils.splitHash64(hash64); + return hexJoin(jspb.utils.split64Low, jspb.utils.split64High); + } + + expect(decoder.readSplitZigzagVarint64(hexJoin)) + .toEqual(hexJoinHash(hashA)); + expect(decoder.readSplitZigzagVarint64(hexJoin)) + .toEqual(hexJoinHash(hashB)); + expect(decoder.readSplitZigzagVarint64(hexJoin)) + .toEqual(hexJoinHash(hashC)); + expect(decoder.readSplitZigzagVarint64(hexJoin)) + .toEqual(hexJoinHash(hashD)); + }); + + it('does zigzag encoding properly', function() { + // Test cases directly from the protobuf dev guide. + // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types + var testCases = [ + {original: '0', zigzag: '0'}, + {original: '-1', zigzag: '1'}, + {original: '1', zigzag: '2'}, + {original: '-2', zigzag: '3'}, + {original: '2147483647', zigzag: '4294967294'}, + {original: '-2147483648', zigzag: '4294967295'}, + // 64-bit extremes, not in dev guide. + {original: '9223372036854775807', zigzag: '18446744073709551614'}, + {original: '-9223372036854775808', zigzag: '18446744073709551615'}, + // None of the above catch: bitsLow < 0 && bitsHigh > 0 && bitsHigh < + // 0x1FFFFF. The following used to be broken. + {original: '72000000000', zigzag: '144000000000'}, + ]; + var encoder = new jspb.BinaryEncoder(); + testCases.forEach(function(c) { + encoder.writeZigzagVarint64String(c.original); + }); + var buffer = encoder.end(); + var zigzagDecoder = jspb.BinaryDecoder.alloc(buffer); + var varintDecoder = jspb.BinaryDecoder.alloc(buffer); + testCases.forEach(function(c) { + expect(zigzagDecoder.readZigzagVarint64String()).toEqual(c.original); + expect(varintDecoder.readUnsignedVarint64String()).toEqual(c.zigzag); + }); + }); }); /** @@ -255,7 +378,6 @@ describe('binaryDecoderTest', function() { /** * Verifies that misuse of the decoder class triggers assertions. - * @suppress {checkTypes|visibility} */ it('testDecodeErrors', function() { // Reading a value past the end of the stream should trigger an assertion. @@ -270,24 +392,7 @@ describe('binaryDecoderTest', function() { assertThrows(function() {decoder.readSignedVarint64()}); decoder.reset(); assertThrows(function() {decoder.readZigzagVarint64()}); - - // Positive 32-bit varints encoded with 1 bits in positions 33 through 35 - // should trigger assertions. - decoder.setBlock([255, 255, 255, 255, 0x1F]); - assertThrows(function() {decoder.readUnsignedVarint32()}); - - decoder.setBlock([255, 255, 255, 255, 0x2F]); - assertThrows(function() {decoder.readUnsignedVarint32()}); - - decoder.setBlock([255, 255, 255, 255, 0x4F]); - assertThrows(function() {decoder.readUnsignedVarint32()}); - - // Negative 32-bit varints encoded with non-1 bits in the high dword should - // trigger assertions. - decoder.setBlock([255, 255, 255, 255, 255, 255, 0, 255, 255, 1]); - assertThrows(function() {decoder.readUnsignedVarint32()}); - - decoder.setBlock([255, 255, 255, 255, 255, 255, 255, 255, 255, 0]); + decoder.reset(); assertThrows(function() {decoder.readUnsignedVarint32()}); }); diff --git a/js/binary/encoder.js b/js/binary/encoder.js index 8e9f5bbc349b6..726481b2c1c3b 100644 --- a/js/binary/encoder.js +++ b/js/binary/encoder.js @@ -51,7 +51,7 @@ goog.require('jspb.utils'); * @struct */ jspb.BinaryEncoder = function() { - /** @private {!Array.} */ + /** @private {!Array} */ this.buffer_ = []; }; @@ -65,7 +65,7 @@ jspb.BinaryEncoder.prototype.length = function() { /** - * @return {!Array.} + * @return {!Array} */ jspb.BinaryEncoder.prototype.end = function() { var buffer = this.buffer_; @@ -232,13 +232,27 @@ jspb.BinaryEncoder.prototype.writeZigzagVarint64 = function(value) { * @param {string} value The integer to convert. */ jspb.BinaryEncoder.prototype.writeZigzagVarint64String = function(value) { - // TODO(haberman): write lossless 64-bit zig-zag math. - this.writeZigzagVarint64(parseInt(value, 10)); + this.writeZigzagVarintHash64(jspb.utils.decimalStringToHash64(value)); }; /** - * Writes a 8-bit unsigned integer to the buffer. Numbers outside the range + * Writes a 64-bit hash string (8 characters @ 8 bits of data each) to the + * buffer as a zigzag varint. + * @param {string} hash The hash to write. + */ +jspb.BinaryEncoder.prototype.writeZigzagVarintHash64 = function(hash) { + var self = this; + jspb.utils.splitHash64(hash); + jspb.utils.toZigzag64( + jspb.utils.split64Low, jspb.utils.split64High, function(lo, hi) { + self.writeSplitVarint64(lo >>> 0, hi >>> 0); + }); +}; + + +/** + * Writes an 8-bit unsigned integer to the buffer. Numbers outside the range * [0,2^8) will be truncated. * @param {number} value The value to write. */ @@ -294,7 +308,7 @@ jspb.BinaryEncoder.prototype.writeUint64 = function(value) { /** - * Writes a 8-bit integer to the buffer. Numbers outside the range + * Writes an 8-bit integer to the buffer. Numbers outside the range * [-2^7,2^7) will be truncated. * @param {number} value The value to write. */ @@ -368,8 +382,10 @@ jspb.BinaryEncoder.prototype.writeInt64String = function(value) { * @param {number} value The value to write. */ jspb.BinaryEncoder.prototype.writeFloat = function(value) { - goog.asserts.assert((value >= -jspb.BinaryConstants.FLOAT32_MAX) && - (value <= jspb.BinaryConstants.FLOAT32_MAX)); + goog.asserts.assert( + value === Infinity || value === -Infinity || isNaN(value) || + ((value >= -jspb.BinaryConstants.FLOAT32_MAX) && + (value <= jspb.BinaryConstants.FLOAT32_MAX))); jspb.utils.splitFloat32(value); this.writeUint32(jspb.utils.split64Low); }; @@ -381,8 +397,10 @@ jspb.BinaryEncoder.prototype.writeFloat = function(value) { * @param {number} value The value to write. */ jspb.BinaryEncoder.prototype.writeDouble = function(value) { - goog.asserts.assert((value >= -jspb.BinaryConstants.FLOAT64_MAX) && - (value <= jspb.BinaryConstants.FLOAT64_MAX)); + goog.asserts.assert( + value === Infinity || value === -Infinity || isNaN(value) || + ((value >= -jspb.BinaryConstants.FLOAT64_MAX) && + (value <= jspb.BinaryConstants.FLOAT64_MAX))); jspb.utils.splitFloat64(value); this.writeUint32(jspb.utils.split64Low); this.writeUint32(jspb.utils.split64High); @@ -396,7 +414,7 @@ jspb.BinaryEncoder.prototype.writeDouble = function(value) { * @param {boolean|number} value The value to write. */ jspb.BinaryEncoder.prototype.writeBool = function(value) { - goog.asserts.assert(goog.isBoolean(value) || goog.isNumber(value)); + goog.asserts.assert(typeof value === 'boolean' || typeof value === 'number'); this.buffer_.push(value ? 1 : 0); }; diff --git a/js/binary/proto_test.js b/js/binary/proto_test.js index f5e1b6bbf0172..aee327a8ea278 100644 --- a/js/binary/proto_test.js +++ b/js/binary/proto_test.js @@ -176,7 +176,7 @@ function fillAllFields(msg) { * @return {boolean} */ function bytesCompare(arr, expected) { - if (goog.isString(arr)) { + if (typeof arr === 'string') { arr = goog.crypt.base64.decodeStringToUint8Array(arr); } if (arr.length != expected.length) { @@ -481,8 +481,8 @@ describe('protoBinaryTest', function() { var msg = new proto.jspb.test.TestAllTypes(); function assertGetters() { - assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[0])); - assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[1])); + assertTrue(typeof msg.getRepeatedBytesList_asB64()[0] === 'string'); + assertTrue(typeof msg.getRepeatedBytesList_asB64()[1] === 'string'); assertTrue(msg.getRepeatedBytesList_asU8()[0] instanceof Uint8Array); assertTrue(msg.getRepeatedBytesList_asU8()[1] instanceof Uint8Array); @@ -659,5 +659,7 @@ describe('protoBinaryTest', function() { 'jspb.test.TestAllTypes'); checkAllFields(msg, msg2); + }); + }); diff --git a/js/binary/reader.js b/js/binary/reader.js index d5d698f79d8b8..31bbfda438859 100644 --- a/js/binary/reader.js +++ b/js/binary/reader.js @@ -41,6 +41,7 @@ * using the typed jspb code generator, but if you bypass that you'll need * to keep things in sync by hand. * + * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * @author aappleby@google.com (Austin Appleby) */ @@ -49,6 +50,7 @@ goog.provide('jspb.BinaryReader'); goog.require('goog.asserts'); goog.require('jspb.BinaryConstants'); goog.require('jspb.BinaryDecoder'); +goog.require('jspb.utils'); @@ -97,7 +99,7 @@ jspb.BinaryReader = function(opt_bytes, opt_start, opt_length) { /** * User-defined reader callbacks. - * @private {Object.} + * @private {?Object} */ this.readCallbacks_ = null; }; @@ -105,7 +107,7 @@ jspb.BinaryReader = function(opt_bytes, opt_start, opt_length) { /** * Global pool of BinaryReader instances. - * @private {!Array.} + * @private {!Array} */ jspb.BinaryReader.instanceCache_ = []; @@ -205,6 +207,15 @@ jspb.BinaryReader.prototype.getWireType = function() { }; +/** + * @return {boolean} Whether the current wire type is a delimited field. Used to + * conditionally parse packed repeated fields. + */ +jspb.BinaryReader.prototype.isDelimited = function() { + return this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED; +}; + + /** * @return {boolean} Whether the current wire type is an end-group tag. Used as * an exit condition in decoder loops in generated code. @@ -290,7 +301,9 @@ jspb.BinaryReader.prototype.nextField = function() { nextWireType != jspb.BinaryConstants.WireType.DELIMITED && nextWireType != jspb.BinaryConstants.WireType.START_GROUP && nextWireType != jspb.BinaryConstants.WireType.END_GROUP) { - goog.asserts.fail('Invalid wire type'); + goog.asserts.fail( + 'Invalid wire type: %s (at position %s)', nextWireType, + this.fieldCursor_); this.error_ = true; return false; } @@ -388,8 +401,7 @@ jspb.BinaryReader.prototype.skipFixed64Field = function() { * Skips over the next group field in the binary stream. */ jspb.BinaryReader.prototype.skipGroup = function() { - // Keep a stack of start-group tags that must be matched by end-group tags. - var nestedGroups = [this.nextField_]; + var previousField = this.nextField_; do { if (!this.nextField()) { goog.asserts.fail('Unmatched start-group tag: stream EOF'); @@ -397,19 +409,17 @@ jspb.BinaryReader.prototype.skipGroup = function() { return; } if (this.nextWireType_ == - jspb.BinaryConstants.WireType.START_GROUP) { - // Nested group start. - nestedGroups.push(this.nextField_); - } else if (this.nextWireType_ == jspb.BinaryConstants.WireType.END_GROUP) { // Group end: check that it matches top-of-stack. - if (this.nextField_ != nestedGroups.pop()) { + if (this.nextField_ != previousField) { goog.asserts.fail('Unmatched end-group tag'); this.error_ = true; return; } + return; } - } while (nestedGroups.length > 0); + this.skipField(); + } while (true); }; @@ -445,9 +455,9 @@ jspb.BinaryReader.prototype.skipField = function() { * @param {string} callbackName * @param {function(!jspb.BinaryReader):*} callback */ -jspb.BinaryReader.prototype.registerReadCallback = - function(callbackName, callback) { - if (goog.isNull(this.readCallbacks_)) { +jspb.BinaryReader.prototype.registerReadCallback = function( + callbackName, callback) { + if (this.readCallbacks_ === null) { this.readCallbacks_ = {}; } goog.asserts.assert(!this.readCallbacks_[callbackName]); @@ -461,7 +471,7 @@ jspb.BinaryReader.prototype.registerReadCallback = * @return {*} The value returned by the callback. */ jspb.BinaryReader.prototype.runReadCallback = function(callbackName) { - goog.asserts.assert(!goog.isNull(this.readCallbacks_)); + goog.asserts.assert(this.readCallbacks_ !== null); var callback = this.readCallbacks_[callbackName]; goog.asserts.assert(callback); return callback(this); @@ -942,7 +952,7 @@ jspb.BinaryReader.prototype.readBytes = function() { /** - * Reads a 64-bit varint or fixed64 field from the stream and returns it as a + * Reads a 64-bit varint or fixed64 field from the stream and returns it as an * 8-character Unicode string for use as a hash table key, or throws an error * if the next field in the stream is not of the correct wire type. * @@ -955,6 +965,56 @@ jspb.BinaryReader.prototype.readVarintHash64 = function() { }; +/** + * Reads an sint64 field from the stream and returns it as an 8-character + * Unicode string for use as a hash table key, or throws an error if the next + * field in the stream is not of the correct wire type. + * + * @return {string} The hash value. + */ +jspb.BinaryReader.prototype.readSintHash64 = function() { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readZigzagVarintHash64(); +}; + + +/** + * Reads a 64-bit varint field from the stream and invokes `convert` to produce + * the return value, or throws an error if the next field in the stream is not + * of the correct wire type. + * + * @param {function(number, number): T} convert Conversion function to produce + * the result value, takes parameters (lowBits, highBits). + * @return {T} + * @template T + */ +jspb.BinaryReader.prototype.readSplitVarint64 = function(convert) { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readSplitVarint64(convert); +}; + + +/** + * Reads a 64-bit zig-zag varint field from the stream and invokes `convert` to + * produce the return value, or throws an error if the next field in the stream + * is not of the correct wire type. + * + * @param {function(number, number): T} convert Conversion function to produce + * the result value, takes parameters (lowBits, highBits). + * @return {T} + * @template T + */ +jspb.BinaryReader.prototype.readSplitZigzagVarint64 = function(convert) { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); + return this.decoder_.readSplitVarint64(function(lowBits, highBits) { + return jspb.utils.fromZigzag64(lowBits, highBits, convert); + }); +}; + + /** * Reads a 64-bit varint or fixed64 field from the stream and returns it as a * 8-character Unicode string for use as a hash table key, or throws an error @@ -969,6 +1029,23 @@ jspb.BinaryReader.prototype.readFixedHash64 = function() { }; +/** + * Reads a 64-bit fixed64 field from the stream and invokes `convert` + * to produce the return value, or throws an error if the next field in the + * stream is not of the correct wire type. + * + * @param {function(number, number): T} convert Conversion function to produce + * the result value, takes parameters (lowBits, highBits). + * @return {T} + * @template T + */ +jspb.BinaryReader.prototype.readSplitFixed64 = function(convert) { + goog.asserts.assert( + this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); + return this.decoder_.readSplitFixed64(convert); +}; + + /** * Reads a packed scalar field using the supplied raw reader function. * @param {function(this:jspb.BinaryDecoder)} decodeMethod @@ -992,7 +1069,7 @@ jspb.BinaryReader.prototype.readPackedField_ = function(decodeMethod) { /** * Reads a packed int32 field, which consists of a length header and a list of * signed varints. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedInt32 = function() { return this.readPackedField_(this.decoder_.readSignedVarint32); @@ -1002,7 +1079,7 @@ jspb.BinaryReader.prototype.readPackedInt32 = function() { /** * Reads a packed int32 field, which consists of a length header and a list of * signed varints. Returns a list of strings. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedInt32String = function() { return this.readPackedField_(this.decoder_.readSignedVarint32String); @@ -1012,7 +1089,7 @@ jspb.BinaryReader.prototype.readPackedInt32String = function() { /** * Reads a packed int64 field, which consists of a length header and a list of * signed varints. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedInt64 = function() { return this.readPackedField_(this.decoder_.readSignedVarint64); @@ -1022,7 +1099,7 @@ jspb.BinaryReader.prototype.readPackedInt64 = function() { /** * Reads a packed int64 field, which consists of a length header and a list of * signed varints. Returns a list of strings. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedInt64String = function() { return this.readPackedField_(this.decoder_.readSignedVarint64String); @@ -1032,7 +1109,7 @@ jspb.BinaryReader.prototype.readPackedInt64String = function() { /** * Reads a packed uint32 field, which consists of a length header and a list of * unsigned varints. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedUint32 = function() { return this.readPackedField_(this.decoder_.readUnsignedVarint32); @@ -1042,7 +1119,7 @@ jspb.BinaryReader.prototype.readPackedUint32 = function() { /** * Reads a packed uint32 field, which consists of a length header and a list of * unsigned varints. Returns a list of strings. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedUint32String = function() { return this.readPackedField_(this.decoder_.readUnsignedVarint32String); @@ -1052,7 +1129,7 @@ jspb.BinaryReader.prototype.readPackedUint32String = function() { /** * Reads a packed uint64 field, which consists of a length header and a list of * unsigned varints. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedUint64 = function() { return this.readPackedField_(this.decoder_.readUnsignedVarint64); @@ -1062,7 +1139,7 @@ jspb.BinaryReader.prototype.readPackedUint64 = function() { /** * Reads a packed uint64 field, which consists of a length header and a list of * unsigned varints. Returns a list of strings. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedUint64String = function() { return this.readPackedField_(this.decoder_.readUnsignedVarint64String); @@ -1072,7 +1149,7 @@ jspb.BinaryReader.prototype.readPackedUint64String = function() { /** * Reads a packed sint32 field, which consists of a length header and a list of * zigzag varints. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedSint32 = function() { return this.readPackedField_(this.decoder_.readZigzagVarint32); @@ -1082,7 +1159,7 @@ jspb.BinaryReader.prototype.readPackedSint32 = function() { /** * Reads a packed sint64 field, which consists of a length header and a list of * zigzag varints. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedSint64 = function() { return this.readPackedField_(this.decoder_.readZigzagVarint64); @@ -1092,7 +1169,7 @@ jspb.BinaryReader.prototype.readPackedSint64 = function() { /** * Reads a packed sint64 field, which consists of a length header and a list of * zigzag varints. Returns a list of strings. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedSint64String = function() { return this.readPackedField_(this.decoder_.readZigzagVarint64String); @@ -1102,7 +1179,7 @@ jspb.BinaryReader.prototype.readPackedSint64String = function() { /** * Reads a packed fixed32 field, which consists of a length header and a list * of unsigned 32-bit ints. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedFixed32 = function() { return this.readPackedField_(this.decoder_.readUint32); @@ -1112,7 +1189,7 @@ jspb.BinaryReader.prototype.readPackedFixed32 = function() { /** * Reads a packed fixed64 field, which consists of a length header and a list * of unsigned 64-bit ints. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedFixed64 = function() { return this.readPackedField_(this.decoder_.readUint64); @@ -1122,7 +1199,7 @@ jspb.BinaryReader.prototype.readPackedFixed64 = function() { /** * Reads a packed fixed64 field, which consists of a length header and a list * of unsigned 64-bit ints. Returns a list of strings. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedFixed64String = function() { return this.readPackedField_(this.decoder_.readUint64String); @@ -1132,7 +1209,7 @@ jspb.BinaryReader.prototype.readPackedFixed64String = function() { /** * Reads a packed sfixed32 field, which consists of a length header and a list * of 32-bit ints. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedSfixed32 = function() { return this.readPackedField_(this.decoder_.readInt32); @@ -1142,7 +1219,7 @@ jspb.BinaryReader.prototype.readPackedSfixed32 = function() { /** * Reads a packed sfixed64 field, which consists of a length header and a list * of 64-bit ints. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedSfixed64 = function() { return this.readPackedField_(this.decoder_.readInt64); @@ -1152,7 +1229,7 @@ jspb.BinaryReader.prototype.readPackedSfixed64 = function() { /** * Reads a packed sfixed64 field, which consists of a length header and a list * of 64-bit ints. Returns a list of strings. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedSfixed64String = function() { return this.readPackedField_(this.decoder_.readInt64String); @@ -1162,7 +1239,7 @@ jspb.BinaryReader.prototype.readPackedSfixed64String = function() { /** * Reads a packed float field, which consists of a length header and a list of * floats. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedFloat = function() { return this.readPackedField_(this.decoder_.readFloat); @@ -1172,7 +1249,7 @@ jspb.BinaryReader.prototype.readPackedFloat = function() { /** * Reads a packed double field, which consists of a length header and a list of * doubles. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedDouble = function() { return this.readPackedField_(this.decoder_.readDouble); @@ -1182,7 +1259,7 @@ jspb.BinaryReader.prototype.readPackedDouble = function() { /** * Reads a packed bool field, which consists of a length header and a list of * unsigned varints. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedBool = function() { return this.readPackedField_(this.decoder_.readBool); @@ -1192,7 +1269,7 @@ jspb.BinaryReader.prototype.readPackedBool = function() { /** * Reads a packed enum field, which consists of a length header and a list of * unsigned varints. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedEnum = function() { return this.readPackedField_(this.decoder_.readEnum); @@ -1202,7 +1279,7 @@ jspb.BinaryReader.prototype.readPackedEnum = function() { /** * Reads a packed varint hash64 field, which consists of a length header and a * list of varint hash64s. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedVarintHash64 = function() { return this.readPackedField_(this.decoder_.readVarintHash64); @@ -1212,7 +1289,7 @@ jspb.BinaryReader.prototype.readPackedVarintHash64 = function() { /** * Reads a packed fixed hash64 field, which consists of a length header and a * list of fixed hash64s. - * @return {!Array.} + * @return {!Array} */ jspb.BinaryReader.prototype.readPackedFixedHash64 = function() { return this.readPackedField_(this.decoder_.readFixedHash64); diff --git a/js/binary/reader_test.js b/js/binary/reader_test.js index 957113859e5d2..7e4682885d7ac 100644 --- a/js/binary/reader_test.js +++ b/js/binary/reader_test.js @@ -46,7 +46,8 @@ goog.require('jspb.BinaryConstants'); goog.require('jspb.BinaryDecoder'); goog.require('jspb.BinaryReader'); goog.require('jspb.BinaryWriter'); - +goog.require('jspb.utils'); +goog.requireType('jspb.BinaryMessage'); describe('binaryReaderTest', function() { @@ -55,7 +56,7 @@ describe('binaryReaderTest', function() { */ it('testInstanceCaches', /** @suppress {visibility} */ function() { var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeMessage(1, dummyMessage, goog.nullFunction); writer.writeMessage(2, dummyMessage, goog.nullFunction); @@ -135,7 +136,7 @@ describe('binaryReaderTest', function() { // Calling readMessage on a non-delimited field should trigger an // assertion. var reader = jspb.BinaryReader.alloc([8, 1]); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); reader.nextField(); assertThrows(function() { reader.readMessage(dummyMessage, goog.nullFunction); @@ -144,47 +145,91 @@ describe('binaryReaderTest', function() { // Reading past the end of the stream should trigger an assertion. reader = jspb.BinaryReader.alloc([9, 1]); reader.nextField(); - assertThrows(function() {reader.readFixed64()}); + assertThrows(function() { + reader.readFixed64() + }); // Reading past the end of a submessage should trigger an assertion. reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]); reader.nextField(); reader.readMessage(dummyMessage, function() { reader.nextField(); - assertThrows(function() {reader.readFixed32()}); + assertThrows(function() { + reader.readFixed32() + }); }); // Skipping an invalid field should trigger an assertion. reader = jspb.BinaryReader.alloc([12, 1]); reader.nextWireType_ = 1000; - assertThrows(function() {reader.skipField()}); + assertThrows(function() { + reader.skipField() + }); // Reading fields with the wrong wire type should assert. reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]); reader.nextField(); - assertThrows(function() {reader.readInt32()}); - assertThrows(function() {reader.readInt32String()}); - assertThrows(function() {reader.readInt64()}); - assertThrows(function() {reader.readInt64String()}); - assertThrows(function() {reader.readUint32()}); - assertThrows(function() {reader.readUint32String()}); - assertThrows(function() {reader.readUint64()}); - assertThrows(function() {reader.readUint64String()}); - assertThrows(function() {reader.readSint32()}); - assertThrows(function() {reader.readBool()}); - assertThrows(function() {reader.readEnum()}); + assertThrows(function() { + reader.readInt32() + }); + assertThrows(function() { + reader.readInt32String() + }); + assertThrows(function() { + reader.readInt64() + }); + assertThrows(function() { + reader.readInt64String() + }); + assertThrows(function() { + reader.readUint32() + }); + assertThrows(function() { + reader.readUint32String() + }); + assertThrows(function() { + reader.readUint64() + }); + assertThrows(function() { + reader.readUint64String() + }); + assertThrows(function() { + reader.readSint32() + }); + assertThrows(function() { + reader.readBool() + }); + assertThrows(function() { + reader.readEnum() + }); reader = jspb.BinaryReader.alloc([8, 1]); reader.nextField(); - assertThrows(function() {reader.readFixed32()}); - assertThrows(function() {reader.readFixed64()}); - assertThrows(function() {reader.readSfixed32()}); - assertThrows(function() {reader.readSfixed64()}); - assertThrows(function() {reader.readFloat()}); - assertThrows(function() {reader.readDouble()}); + assertThrows(function() { + reader.readFixed32() + }); + assertThrows(function() { + reader.readFixed64() + }); + assertThrows(function() { + reader.readSfixed32() + }); + assertThrows(function() { + reader.readSfixed64() + }); + assertThrows(function() { + reader.readFloat() + }); + assertThrows(function() { + reader.readDouble() + }); - assertThrows(function() {reader.readString()}); - assertThrows(function() {reader.readBytes()}); + assertThrows(function() { + reader.readString() + }); + assertThrows(function() { + reader.readBytes() + }); }); @@ -198,8 +243,8 @@ describe('binaryReaderTest', function() { * @private * @suppress {missingProperties} */ - var doTestUnsignedField_ = function(readField, - writeField, epsilon, upperLimit, filter) { + var doTestUnsignedField_ = function( + readField, writeField, epsilon, upperLimit, filter) { assertNotNull(readField); assertNotNull(writeField); @@ -250,8 +295,8 @@ describe('binaryReaderTest', function() { * @private * @suppress {missingProperties} */ - var doTestSignedField_ = function(readField, - writeField, epsilon, lowerLimit, upperLimit, filter) { + var doTestSignedField_ = function( + readField, writeField, epsilon, lowerLimit, upperLimit, filter) { var writer = new jspb.BinaryWriter(); // Encode zero and limits. @@ -267,20 +312,14 @@ describe('binaryReaderTest', function() { for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) { var val = filter(cursor); writeField.call(writer, 6, val); - inputValues.push({ - fieldNumber: 6, - value: val - }); + inputValues.push({fieldNumber: 6, value: val}); } // Encode positive values. for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { var val = filter(cursor); writeField.call(writer, 7, val); - inputValues.push({ - fieldNumber: 7, - value: val - }); + inputValues.push({fieldNumber: 7, value: val}); } var reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); @@ -327,33 +366,34 @@ describe('binaryReaderTest', function() { assertNotUndefined(jspb.BinaryWriter.prototype.writeBool); doTestUnsignedField_( jspb.BinaryReader.prototype.readUint32, - jspb.BinaryWriter.prototype.writeUint32, - 1, Math.pow(2, 32) - 1, Math.round); + jspb.BinaryWriter.prototype.writeUint32, 1, Math.pow(2, 32) - 1, + Math.round); doTestUnsignedField_( jspb.BinaryReader.prototype.readUint64, - jspb.BinaryWriter.prototype.writeUint64, - 1, Math.pow(2, 64) - 1025, Math.round); + jspb.BinaryWriter.prototype.writeUint64, 1, Math.pow(2, 64) - 1025, + Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readInt32, - jspb.BinaryWriter.prototype.writeInt32, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeInt32, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readInt64, - jspb.BinaryWriter.prototype.writeInt64, - 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); + jspb.BinaryWriter.prototype.writeInt64, 1, -Math.pow(2, 63), + Math.pow(2, 63) - 513, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readEnum, - jspb.BinaryWriter.prototype.writeEnum, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeEnum, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestUnsignedField_( jspb.BinaryReader.prototype.readBool, - jspb.BinaryWriter.prototype.writeBool, - 1, 1, function(x) { return !!x; }); + jspb.BinaryWriter.prototype.writeBool, 1, 1, function(x) { + return !!x; + }); }); @@ -387,26 +427,49 @@ describe('binaryReaderTest', function() { // uint32 and sint32 take no more than 5 bytes // 08 - field prefix (type = 0 means varint) doTestHexStringVarint_( - jspb.BinaryReader.prototype.readUint32, - 12, '08 8C 80 80 80 00'); + jspb.BinaryReader.prototype.readUint32, 12, '08 8C 80 80 80 00'); // 11 stands for -6 in zigzag encoding doTestHexStringVarint_( - jspb.BinaryReader.prototype.readSint32, - -6, '08 8B 80 80 80 00'); + jspb.BinaryReader.prototype.readSint32, -6, '08 8B 80 80 80 00'); // uint64 and sint64 take no more than 10 bytes // 08 - field prefix (type = 0 means varint) doTestHexStringVarint_( - jspb.BinaryReader.prototype.readUint64, - 12, '08 8C 80 80 80 80 80 80 80 80 00'); + jspb.BinaryReader.prototype.readUint64, 12, + '08 8C 80 80 80 80 80 80 80 80 00'); // 11 stands for -6 in zigzag encoding doTestHexStringVarint_( - jspb.BinaryReader.prototype.readSint64, - -6, '08 8B 80 80 80 80 80 80 80 80 00'); + jspb.BinaryReader.prototype.readSint64, -6, + '08 8B 80 80 80 80 80 80 80 80 00'); }); + /** + * Tests reading 64-bit integers as split values. + */ + it('handles split 64 fields', function() { + var writer = new jspb.BinaryWriter(); + writer.writeInt64String(1, '4294967296'); + writer.writeSfixed64String(2, '4294967298'); + writer.writeInt64String(3, '3'); // 3 is the zig-zag encoding of -2. + var reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + + function rejoin(lowBits, highBits) { + return highBits * 2 ** 32 + (lowBits >>> 0); + } + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(1); + expect(reader.readSplitVarint64(rejoin)).toEqual(0x100000000); + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(2); + expect(reader.readSplitFixed64(rejoin)).toEqual(0x100000002); + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(3); + expect(reader.readSplitZigzagVarint64(rejoin)).toEqual(-2); + }); /** * Tests 64-bit fields that are handled as strings. @@ -415,27 +478,15 @@ describe('binaryReaderTest', function() { var writer = new jspb.BinaryWriter(); var testSignedData = [ - '2730538252207801776', - '-2688470994844604560', - '3398529779486536359', - '3568577411627971000', - '272477188847484900', - '-6649058714086158188', - '-7695254765712060806', - '-4525541438037104029', - '-4993706538836508568', + '2730538252207801776', '-2688470994844604560', '3398529779486536359', + '3568577411627971000', '272477188847484900', '-6649058714086158188', + '-7695254765712060806', '-4525541438037104029', '-4993706538836508568', '4990160321893729138' ]; var testUnsignedData = [ - '7822732630241694882', - '6753602971916687352', - '2399935075244442116', - '8724292567325338867', - '16948784802625696584', - '4136275908516066934', - '3575388346793700364', - '5167142028379259461', - '1557573948689737699', + '7822732630241694882', '6753602971916687352', '2399935075244442116', + '8724292567325338867', '16948784802625696584', '4136275908516066934', + '3575388346793700364', '5167142028379259461', '1557573948689737699', '17100725280812548567' ]; @@ -463,13 +514,18 @@ describe('binaryReaderTest', function() { it('testZigzagFields', function() { doTestSignedField_( jspb.BinaryReader.prototype.readSint32, - jspb.BinaryWriter.prototype.writeSint32, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeSint32, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readSint64, - jspb.BinaryWriter.prototype.writeSint64, - 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); + jspb.BinaryWriter.prototype.writeSint64, 1, -Math.pow(2, 63), + Math.pow(2, 63) - 513, Math.round); + + doTestSignedField_( + jspb.BinaryReader.prototype.readSintHash64, + jspb.BinaryWriter.prototype.writeSintHash64, 1, -Math.pow(2, 63), + Math.pow(2, 63) - 513, jspb.utils.numberToHash64); }); @@ -479,23 +535,23 @@ describe('binaryReaderTest', function() { it('testFixedFields', function() { doTestUnsignedField_( jspb.BinaryReader.prototype.readFixed32, - jspb.BinaryWriter.prototype.writeFixed32, - 1, Math.pow(2, 32) - 1, Math.round); + jspb.BinaryWriter.prototype.writeFixed32, 1, Math.pow(2, 32) - 1, + Math.round); doTestUnsignedField_( jspb.BinaryReader.prototype.readFixed64, - jspb.BinaryWriter.prototype.writeFixed64, - 1, Math.pow(2, 64) - 1025, Math.round); + jspb.BinaryWriter.prototype.writeFixed64, 1, Math.pow(2, 64) - 1025, + Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readSfixed32, - jspb.BinaryWriter.prototype.writeSfixed32, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeSfixed32, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readSfixed64, - jspb.BinaryWriter.prototype.writeSfixed64, - 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); + jspb.BinaryWriter.prototype.writeSfixed64, 1, -Math.pow(2, 63), + Math.pow(2, 63) - 513, Math.round); }); @@ -506,18 +562,17 @@ describe('binaryReaderTest', function() { doTestSignedField_( jspb.BinaryReader.prototype.readFloat, jspb.BinaryWriter.prototype.writeFloat, - jspb.BinaryConstants.FLOAT32_MIN, - -jspb.BinaryConstants.FLOAT32_MAX, - jspb.BinaryConstants.FLOAT32_MAX, - truncate); + jspb.BinaryConstants.FLOAT32_MIN, -jspb.BinaryConstants.FLOAT32_MAX, + jspb.BinaryConstants.FLOAT32_MAX, truncate); doTestSignedField_( jspb.BinaryReader.prototype.readDouble, jspb.BinaryWriter.prototype.writeDouble, jspb.BinaryConstants.FLOAT64_EPS * 10, - -jspb.BinaryConstants.FLOAT64_MIN, - jspb.BinaryConstants.FLOAT64_MIN, - function(x) { return x; }); + -jspb.BinaryConstants.FLOAT64_MIN, jspb.BinaryConstants.FLOAT64_MIN, + function(x) { + return x; + }); }); @@ -584,7 +639,7 @@ describe('binaryReaderTest', function() { */ it('testNesting', function() { var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeInt32(1, 100); @@ -677,11 +732,26 @@ describe('binaryReaderTest', function() { // Write a group with a nested group inside. writer.writeInt32(5, sentinel); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeGroup(5, dummyMessage, function() { + // Previously the skipGroup implementation was wrong, which only consume + // the decoder by nextField. This case is for making the previous + // implementation failed in skipGroup by an early end group tag. + // The reason is 44 = 5 * 8 + 4, this will be translated in to a field + // with number 5 and with type 4 (end group) + writer.writeInt64(44, 44); + // This will make previous implementation failed by invalid tag (7). + writer.writeInt64(42, 47); writer.writeInt64(42, 42); + // This is for making the previous implementation failed by an invalid + // varint. The bytes have at least 9 consecutive minus byte, which will + // fail in this.nextField for previous implementation. + writer.writeBytes(43, [255, 255, 255, 255, 255, 255, 255, 255, 255, 255]); writer.writeGroup(6, dummyMessage, function() { writer.writeInt64(84, 42); + writer.writeInt64(84, 44); + writer.writeBytes( + 43, [255, 255, 255, 255, 255, 255, 255, 255, 255, 255]); }); }); @@ -830,7 +900,7 @@ describe('binaryReaderTest', function() { var fieldTag = (1 << 3) | jspb.BinaryConstants.WireType.DELIMITED; var blob = [1, 2, 3, 4, 5]; var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeMessage(1, dummyMessage, function() { writer.writeMessage(1, dummyMessage, function() { @@ -863,7 +933,7 @@ describe('binaryReaderTest', function() { */ it('testReadCallbacks', function() { var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); // Add an int, a submessage, and another int. writer.writeInt32(1, 100); diff --git a/js/binary/utils.js b/js/binary/utils.js index 58f11b54a57e3..4d743310cf55a 100644 --- a/js/binary/utils.js +++ b/js/binary/utils.js @@ -32,12 +32,14 @@ * @fileoverview This file contains helper code used by jspb.BinaryReader * and BinaryWriter. * + * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * @author aappleby@google.com (Austin Appleby) */ goog.provide('jspb.utils'); goog.require('goog.asserts'); +goog.require('goog.crypt'); goog.require('goog.crypt.base64'); goog.require('goog.string'); goog.require('jspb.BinaryConstants'); @@ -116,7 +118,7 @@ jspb.utils.splitInt64 = function(value) { /** - * Convers a signed Javascript integer into zigzag format, splits it into two + * Converts a signed Javascript integer into zigzag format, splits it into two * 32-bit halves, and stores it in the temp values above. * @param {number} value The number to split. */ @@ -254,8 +256,25 @@ jspb.utils.splitFloat64 = function(value) { return; } - var exp = Math.floor(Math.log(value) / Math.LN2); - if (exp == 1024) exp = 1023; + // Compute the least significant exponent needed to represent the magnitude of + // the value by repeadly dividing/multiplying by 2 until the magnitude + // crosses 2. While tempting to use log math to find the exponent, at the + // boundaries of precision, the result can be off by one. + var maxDoubleExponent = 1023; + var minDoubleExponent = -1022; + var x = value; + var exp = 0; + if (x >= 2) { + while (x >= 2 && exp < maxDoubleExponent) { + exp++; + x = x / 2; + } + } else { + while (x < 1 && exp > minDoubleExponent) { + x = x * 2; + exp--; + } + } var mant = value * Math.pow(2, -exp); var mantHigh = (mant * jspb.BinaryConstants.TWO_TO_20) & 0xFFFFF; @@ -295,7 +314,7 @@ jspb.utils.splitHash64 = function(hash) { * @return {number} */ jspb.utils.joinUint64 = function(bitsLow, bitsHigh) { - return bitsHigh * jspb.BinaryConstants.TWO_TO_32 + bitsLow; + return bitsHigh * jspb.BinaryConstants.TWO_TO_32 + (bitsLow >>> 0); }; @@ -321,6 +340,33 @@ jspb.utils.joinInt64 = function(bitsLow, bitsHigh) { return sign ? -result : result; }; +/** + * Converts split 64-bit values from standard two's complement encoding to + * zig-zag encoding. Invokes the provided function to produce final result. + * + * @param {number} bitsLow + * @param {number} bitsHigh + * @param {function(number, number): T} convert Conversion function to produce + * the result value, takes parameters (lowBits, highBits). + * @return {T} + * @template T + */ +jspb.utils.toZigzag64 = function(bitsLow, bitsHigh, convert) { + // See + // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types + // 64-bit math is: (n << 1) ^ (n >> 63) + // + // To do this in 32 bits, we can get a 32-bit sign-flipping mask from the + // high word. + // Then we can operate on each word individually, with the addition of the + // "carry" to get the most significant bit from the low word into the high + // word. + var signFlipMask = bitsHigh >> 31; + bitsHigh = (bitsHigh << 1 | bitsLow >>> 31) ^ signFlipMask; + bitsLow = (bitsLow << 1) ^ signFlipMask; + return convert(bitsLow, bitsHigh); +}; + /** * Joins two 32-bit values into a 64-bit unsigned integer and applies zigzag @@ -330,21 +376,33 @@ jspb.utils.joinInt64 = function(bitsLow, bitsHigh) { * @return {number} */ jspb.utils.joinZigzag64 = function(bitsLow, bitsHigh) { - // Extract the sign bit and shift right by one. - var sign = bitsLow & 1; - bitsLow = ((bitsLow >>> 1) | (bitsHigh << 31)) >>> 0; - bitsHigh = bitsHigh >>> 1; + return jspb.utils.fromZigzag64(bitsLow, bitsHigh, jspb.utils.joinInt64); +}; - // Increment the split value if the sign bit was set. - if (sign) { - bitsLow = (bitsLow + 1) >>> 0; - if (bitsLow == 0) { - bitsHigh = (bitsHigh + 1) >>> 0; - } - } - var result = jspb.utils.joinUint64(bitsLow, bitsHigh); - return sign ? -result : result; +/** + * Converts split 64-bit values from zigzag encoding to standard two's + * complement encoding. Invokes the provided function to produce final result. + * + * @param {number} bitsLow + * @param {number} bitsHigh + * @param {function(number, number): T} convert Conversion function to produce + * the result value, takes parameters (lowBits, highBits). + * @return {T} + * @template T + */ +jspb.utils.fromZigzag64 = function(bitsLow, bitsHigh, convert) { + // 64 bit math is: + // signmask = (zigzag & 1) ? -1 : 0; + // twosComplement = (zigzag >> 1) ^ signmask; + // + // To work with 32 bit, we can operate on both but "carry" the lowest bit + // from the high word by shifting it up 31 bits to be the most significant bit + // of the low word. + var signFlipMask = -(bitsLow & 1); + bitsLow = ((bitsLow >>> 1) | (bitsHigh << 31)) ^ signFlipMask; + bitsHigh = (bitsHigh >>> 1) ^ signFlipMask; + return convert(bitsLow, bitsHigh); }; @@ -427,16 +485,20 @@ jspb.utils.joinHash64 = function(bitsLow, bitsHigh) { return String.fromCharCode(a, b, c, d, e, f, g, h); }; - /** * Individual digits for number->string conversion. - * @const {!Array.} + * @const {!Array} */ jspb.utils.DIGITS = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' ]; +/** @const @private {number} '0' */ +jspb.utils.ZERO_CHAR_CODE_ = 48; + +/** @const @private {number} 'a' */ +jspb.utils.A_CHAR_CODE_ = 97; /** * Losslessly converts a 64-bit unsigned integer in 32:32 split representation @@ -449,7 +511,7 @@ jspb.utils.joinUnsignedDecimalString = function(bitsLow, bitsHigh) { // Skip the expensive conversion if the number is small enough to use the // built-in conversions. if (bitsHigh <= 0x1FFFFF) { - return '' + (jspb.BinaryConstants.TWO_TO_32 * bitsHigh + bitsLow); + return '' + jspb.utils.joinUint64(bitsLow, bitsHigh); } // What this code is doing is essentially converting the input number from @@ -486,27 +548,20 @@ jspb.utils.joinUnsignedDecimalString = function(bitsLow, bitsHigh) { digitB %= base; } - // Convert base-1e7 digits to base-10, omitting leading zeroes. - var table = jspb.utils.DIGITS; - var start = false; - var result = ''; - - function emit(digit) { - var temp = base; - for (var i = 0; i < 7; i++) { - temp /= 10; - var decimalDigit = ((digit / temp) % 10) >>> 0; - if ((decimalDigit == 0) && !start) continue; - start = true; - result += table[decimalDigit]; + // Convert base-1e7 digits to base-10, with optional leading zeroes. + function decimalFrom1e7(digit1e7, needLeadingZeros) { + var partial = digit1e7 ? String(digit1e7) : ''; + if (needLeadingZeros) { + return '0000000'.slice(partial.length) + partial; } + return partial; } - if (digitC || start) emit(digitC); - if (digitB || start) emit(digitB); - if (digitA || start) emit(digitA); - - return result; + return decimalFrom1e7(digitC, /*needLeadingZeros=*/ 0) + + decimalFrom1e7(digitB, /*needLeadingZeros=*/ digitC) + + // If the final 1e7 digit didn't need leading zeros, we would have + // returned via the trivial code path at the top. + decimalFrom1e7(digitA, /*needLeadingZeros=*/ 1); }; @@ -553,10 +608,10 @@ jspb.utils.hash64ToDecimalString = function(hash, signed) { /** * Converts an array of 8-character hash strings into their decimal * representations. - * @param {!Array.} hashes The array of hash strings to convert. + * @param {!Array} hashes The array of hash strings to convert. * @param {boolean} signed True if we should treat the hash string as encoding * a signed integer. - * @return {!Array.} + * @return {!Array} */ jspb.utils.hash64ArrayToDecimalStrings = function(hashes, signed) { var result = new Array(hashes.length); @@ -604,7 +659,7 @@ jspb.utils.decimalStringToHash64 = function(dec) { // For each decimal digit, set result to 10*result + digit. for (var i = 0; i < dec.length; i++) { - muladd(10, jspb.utils.DIGITS.indexOf(dec[i])); + muladd(10, dec.charCodeAt(i) - jspb.utils.ZERO_CHAR_CODE_); } // If there's a minus sign, convert into two's complement. @@ -626,6 +681,28 @@ jspb.utils.splitDecimalString = function(value) { jspb.utils.splitHash64(jspb.utils.decimalStringToHash64(value)); }; +/** + * @param {number} nibble A 4-bit integer. + * @return {string} + * @private + */ +jspb.utils.toHexDigit_ = function(nibble) { + return String.fromCharCode( + nibble < 10 ? jspb.utils.ZERO_CHAR_CODE_ + nibble : + jspb.utils.A_CHAR_CODE_ - 10 + nibble); +}; + +/** + * @param {number} hexCharCode + * @return {number} + * @private + */ +jspb.utils.fromHexCharCode_ = function(hexCharCode) { + if (hexCharCode >= jspb.utils.A_CHAR_CODE_) { + return hexCharCode - jspb.utils.A_CHAR_CODE_ + 10; + } + return hexCharCode - jspb.utils.ZERO_CHAR_CODE_; +}; /** * Converts an 8-character hash string into its hexadecimal representation. @@ -639,8 +716,8 @@ jspb.utils.hash64ToHexString = function(hash) { for (var i = 0; i < 8; i++) { var c = hash.charCodeAt(7 - i); - temp[i * 2 + 2] = jspb.utils.DIGITS[c >> 4]; - temp[i * 2 + 3] = jspb.utils.DIGITS[c & 0xF]; + temp[i * 2 + 2] = jspb.utils.toHexDigit_(c >> 4); + temp[i * 2 + 3] = jspb.utils.toHexDigit_(c & 0xF); } var result = temp.join(''); @@ -661,8 +738,8 @@ jspb.utils.hexStringToHash64 = function(hex) { var result = ''; for (var i = 0; i < 8; i++) { - var hi = jspb.utils.DIGITS.indexOf(hex[i * 2 + 2]); - var lo = jspb.utils.DIGITS.indexOf(hex[i * 2 + 3]); + var hi = jspb.utils.fromHexCharCode_(hex.charCodeAt(i * 2 + 2)); + var lo = jspb.utils.fromHexCharCode_(hex.charCodeAt(i * 2 + 3)); result = String.fromCharCode(hi * 16 + lo) + result; } @@ -925,7 +1002,7 @@ jspb.utils.debugBytesToTextFormat = function(byteSource) { * @return {string} Stringified scalar for text format. */ jspb.utils.debugScalarToTextFormat = function(scalar) { - if (goog.isString(scalar)) { + if (typeof scalar === 'string') { return goog.string.quote(scalar); } else { return scalar.toString(); @@ -970,8 +1047,13 @@ jspb.utils.byteSourceToUint8Array = function(data) { return /** @type {!Uint8Array} */(new Uint8Array(data)); } + if (typeof Buffer != 'undefined' && data.constructor === Buffer) { + return /** @type {!Uint8Array} */ ( + new Uint8Array(/** @type {?} */ (data))); + } + if (data.constructor === Array) { - data = /** @type {!Array.} */(data); + data = /** @type {!Array} */(data); return /** @type {!Uint8Array} */(new Uint8Array(data)); } diff --git a/js/binary/utils_test.js b/js/binary/utils_test.js index 0a2f4f0a2d37c..9f735d325ea67 100644 --- a/js/binary/utils_test.js +++ b/js/binary/utils_test.js @@ -36,8 +36,8 @@ * @author aappleby@google.com (Austin Appleby) */ +goog.require('goog.crypt'); goog.require('goog.crypt.base64'); -goog.require('goog.testing.asserts'); goog.require('jspb.BinaryConstants'); goog.require('jspb.BinaryWriter'); goog.require('jspb.utils'); @@ -81,36 +81,36 @@ describe('binaryUtilsTest', function() { // Check some magic numbers. var result = jspb.utils.joinUnsignedDecimalString(0x89e80001, 0x8ac72304); - assertEquals('10000000000000000001', result); + expect(result).toEqual('10000000000000000001'); result = jspb.utils.joinUnsignedDecimalString(0xacd05f15, 0x1b69b4b); - assertEquals('123456789123456789', result); + expect(result).toEqual('123456789123456789'); result = jspb.utils.joinUnsignedDecimalString(0xeb1f0ad2, 0xab54a98c); - assertEquals('12345678901234567890', result); + expect(result).toEqual('12345678901234567890'); result = jspb.utils.joinUnsignedDecimalString(0xe3b70cb1, 0x891087b8); - assertEquals('9876543210987654321', result); + expect(result).toEqual('9876543210987654321'); // Check limits. result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00000000); - assertEquals('0', result); + expect(result).toEqual('0'); result = jspb.utils.joinUnsignedDecimalString(0xFFFFFFFF, 0xFFFFFFFF); - assertEquals('18446744073709551615', result); + expect(result).toEqual('18446744073709551615'); // Check each bit of the low dword. for (var i = 0; i < 32; i++) { var low = (1 << i) >>> 0; result = jspb.utils.joinUnsignedDecimalString(low, 0); - assertEquals('' + Math.pow(2, i), result); + expect(result).toEqual('' + Math.pow(2, i)); } // Check the first 20 bits of the high dword. for (var i = 0; i < 20; i++) { var high = (1 << i) >>> 0; result = jspb.utils.joinUnsignedDecimalString(0, high); - assertEquals('' + Math.pow(2, 32 + i), result); + expect(result).toEqual('' + Math.pow(2, 32 + i)); } // V8's internal double-to-string conversion is inaccurate for values above @@ -118,40 +118,40 @@ describe('binaryUtilsTest', function() { // manually against the correct string representations of 2^N. result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00100000); - assertEquals('4503599627370496', result); + expect(result).toEqual('4503599627370496'); result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00200000); - assertEquals('9007199254740992', result); + expect(result).toEqual('9007199254740992'); result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00400000); - assertEquals('18014398509481984', result); + expect(result).toEqual('18014398509481984'); result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00800000); - assertEquals('36028797018963968', result); + expect(result).toEqual('36028797018963968'); result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x01000000); - assertEquals('72057594037927936', result); + expect(result).toEqual('72057594037927936'); result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x02000000); - assertEquals('144115188075855872', result); + expect(result).toEqual('144115188075855872'); result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x04000000); - assertEquals('288230376151711744', result); + expect(result).toEqual('288230376151711744'); result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x08000000); - assertEquals('576460752303423488', result); + expect(result).toEqual('576460752303423488'); result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x10000000); - assertEquals('1152921504606846976', result); + expect(result).toEqual('1152921504606846976'); result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x20000000); - assertEquals('2305843009213693952', result); + expect(result).toEqual('2305843009213693952'); result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x40000000); - assertEquals('4611686018427387904', result); + expect(result).toEqual('4611686018427387904'); result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x80000000); - assertEquals('9223372036854775808', result); + expect(result).toEqual('9223372036854775808'); }); @@ -163,38 +163,38 @@ describe('binaryUtilsTest', function() { var convert = jspb.utils.hash64ToDecimalString; result = convert(toHashString(0x00000000, 0x00000000), false); - assertEquals('0', result); + expect(result).toEqual('0'); result = convert(toHashString(0x00000000, 0x00000000), true); - assertEquals('0', result); + expect(result).toEqual('0'); result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), false); - assertEquals('18446744073709551615', result); + expect(result).toEqual('18446744073709551615'); result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), true); - assertEquals('-1', result); + expect(result).toEqual('-1'); result = convert(toHashString(0x00000000, 0x80000000), false); - assertEquals('9223372036854775808', result); + expect(result).toEqual('9223372036854775808'); result = convert(toHashString(0x00000000, 0x80000000), true); - assertEquals('-9223372036854775808', result); + expect(result).toEqual('-9223372036854775808'); result = convert(toHashString(0xacd05f15, 0x01b69b4b), false); - assertEquals('123456789123456789', result); + expect(result).toEqual('123456789123456789'); result = convert(toHashString(~0xacd05f15 + 1, ~0x01b69b4b), true); - assertEquals('-123456789123456789', result); + expect(result).toEqual('-123456789123456789'); // And converting arrays of hashes should work the same way. result = jspb.utils.hash64ArrayToDecimalStrings([ toHashString(0xFFFFFFFF, 0xFFFFFFFF), toHashString(0x00000000, 0x80000000), toHashString(0xacd05f15, 0x01b69b4b)], false); - assertEquals(3, result.length); - assertEquals('18446744073709551615', result[0]); - assertEquals('9223372036854775808', result[1]); - assertEquals('123456789123456789', result[2]); + expect(result.length).toEqual(3); + expect(result[0]).toEqual('18446744073709551615'); + expect(result[1]).toEqual('9223372036854775808'); + expect(result[2]).toEqual('123456789123456789'); }); /* @@ -205,32 +205,32 @@ describe('binaryUtilsTest', function() { var convert = jspb.utils.decimalStringToHash64; result = convert('0'); - assertEquals(goog.crypt.byteArrayToString( - [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result); + expect(result).toEqual(goog.crypt.byteArrayToString( + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])); result = convert('-1'); - assertEquals(goog.crypt.byteArrayToString( - [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result); + expect(result).toEqual(goog.crypt.byteArrayToString( + [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])); result = convert('18446744073709551615'); - assertEquals(goog.crypt.byteArrayToString( - [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result); + expect(result).toEqual(goog.crypt.byteArrayToString( + [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])); result = convert('9223372036854775808'); - assertEquals(goog.crypt.byteArrayToString( - [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result); + expect(result).toEqual(goog.crypt.byteArrayToString( + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80])); result = convert('-9223372036854775808'); - assertEquals(goog.crypt.byteArrayToString( - [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result); + expect(result).toEqual(goog.crypt.byteArrayToString( + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80])); result = convert('123456789123456789'); - assertEquals(goog.crypt.byteArrayToString( - [0x15, 0x5F, 0xD0, 0xAC, 0x4B, 0x9B, 0xB6, 0x01]), result); + expect(result).toEqual(goog.crypt.byteArrayToString( + [0x15, 0x5F, 0xD0, 0xAC, 0x4B, 0x9B, 0xB6, 0x01])); result = convert('-123456789123456789'); - assertEquals(goog.crypt.byteArrayToString( - [0xEB, 0xA0, 0x2F, 0x53, 0xB4, 0x64, 0x49, 0xFE]), result); + expect(result).toEqual(goog.crypt.byteArrayToString( + [0xEB, 0xA0, 0x2F, 0x53, 0xB4, 0x64, 0x49, 0xFE])); }); /** @@ -241,13 +241,13 @@ describe('binaryUtilsTest', function() { var convert = jspb.utils.hash64ToHexString; result = convert(toHashString(0x00000000, 0x00000000)); - assertEquals('0x0000000000000000', result); + expect(result).toEqual('0x0000000000000000'); result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF)); - assertEquals('0xffffffffffffffff', result); + expect(result).toEqual('0xffffffffffffffff'); result = convert(toHashString(0x12345678, 0x9ABCDEF0)); - assertEquals('0x9abcdef012345678', result); + expect(result).toEqual('0x9abcdef012345678'); }); @@ -259,22 +259,22 @@ describe('binaryUtilsTest', function() { var convert = jspb.utils.hexStringToHash64; result = convert('0x0000000000000000'); - assertEquals(goog.crypt.byteArrayToString( - [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result); + expect(result).toEqual(goog.crypt.byteArrayToString( + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])); result = convert('0xffffffffffffffff'); - assertEquals(goog.crypt.byteArrayToString( - [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result); + expect(result).toEqual(goog.crypt.byteArrayToString( + [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])); // Hex string is big-endian, hash string is little-endian. result = convert('0x123456789ABCDEF0'); - assertEquals(goog.crypt.byteArrayToString( - [0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]), result); + expect(result).toEqual(goog.crypt.byteArrayToString( + [0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12])); // Capitalization should not matter. result = convert('0x0000abcdefABCDEF'); - assertEquals(goog.crypt.byteArrayToString( - [0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB, 0x00, 0x00]), result); + expect(result).toEqual(goog.crypt.byteArrayToString( + [0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB, 0x00, 0x00])); }); @@ -287,25 +287,25 @@ describe('binaryUtilsTest', function() { var convert = jspb.utils.numberToHash64; result = convert(0x0000000000000); - assertEquals('0x0000000000000000', jspb.utils.hash64ToHexString(result)); + expect(jspb.utils.hash64ToHexString(result)).toEqual('0x0000000000000000'); result = convert(0xFFFFFFFFFFFFF); - assertEquals('0x000fffffffffffff', jspb.utils.hash64ToHexString(result)); + expect(jspb.utils.hash64ToHexString(result)).toEqual('0x000fffffffffffff'); result = convert(0x123456789ABCD); - assertEquals('0x000123456789abcd', jspb.utils.hash64ToHexString(result)); + expect(jspb.utils.hash64ToHexString(result)).toEqual('0x000123456789abcd'); result = convert(0xDCBA987654321); - assertEquals('0x000dcba987654321', jspb.utils.hash64ToHexString(result)); + expect(jspb.utils.hash64ToHexString(result)).toEqual('0x000dcba987654321'); // 53 bits of precision should not be truncated. result = convert(0x10000000000001); - assertEquals('0x0010000000000001', jspb.utils.hash64ToHexString(result)); + expect(jspb.utils.hash64ToHexString(result)).toEqual('0x0010000000000001'); // 54 bits of precision should be truncated. result = convert(0x20000000000001); - assertNotEquals( - '0x0020000000000001', jspb.utils.hash64ToHexString(result)); + expect(jspb.utils.hash64ToHexString(result)) + .not.toEqual('0x0020000000000001'); }); @@ -321,15 +321,15 @@ describe('binaryUtilsTest', function() { // come back out of the string unchanged. for (var i = 0; i < 65536; i++) { strings[i] = 'a' + String.fromCharCode(i) + 'a'; - if (3 != strings[i].length) throw 'fail!'; - if (i != strings[i].charCodeAt(1)) throw 'fail!'; + expect(strings[i].length).toEqual(3); + expect(strings[i].charCodeAt(1)).toEqual(i); } // Each unicode character should compare equal to itself and not equal to a // different unicode character. for (var i = 0; i < 65536; i++) { - if (strings[i] != strings[i]) throw 'fail!'; - if (strings[i] == strings[(i + 1) % 65536]) throw 'fail!'; + expect(strings[i] == strings[i]).toEqual(true); + expect(strings[i] == strings[(i + 1) % 65536]).toEqual(false); } }); @@ -341,13 +341,14 @@ describe('binaryUtilsTest', function() { var f32_eps = jspb.BinaryConstants.FLOAT32_EPS; var f32_min = jspb.BinaryConstants.FLOAT32_MIN; var f32_max = jspb.BinaryConstants.FLOAT32_MAX; + var f32_max_safe_int = jspb.utils.joinFloat32(0x4b7fffff, 0); + var f32_pi = Math.fround(Math.PI); // NaN. jspb.utils.splitFloat32(NaN); - if (!isNaN(jspb.utils.joinFloat32(jspb.utils.split64Low, - jspb.utils.split64High))) { - throw 'fail!'; - } + expect(isNaN(jspb.utils.joinFloat32( + jspb.utils.split64Low, jspb.utils.split64High))) + .toEqual(true); /** * @param {number} x @@ -355,13 +356,12 @@ describe('binaryUtilsTest', function() { */ function test(x, opt_bits) { jspb.utils.splitFloat32(x); - if (goog.isDef(opt_bits)) { + if (opt_bits !== undefined) { if (opt_bits != jspb.utils.split64Low) throw 'fail!'; } - if (truncate(x) != jspb.utils.joinFloat32(jspb.utils.split64Low, - jspb.utils.split64High)) { - throw 'fail!'; - } + expect(truncate(x)) + .toEqual(jspb.utils.joinFloat32( + jspb.utils.split64Low, jspb.utils.split64High)); } // Positive and negative infinity. @@ -384,6 +384,13 @@ describe('binaryUtilsTest', function() { test(f32_max, 0x7F7FFFFF); test(-f32_max, 0xFF7FFFFF); + // Positive and negative max_safe_int. + test(f32_max_safe_int, 0x4B7FFFFF); + test(-f32_max_safe_int, 0xCB7FFFFF); + + // Pi. + test(f32_pi, 0x40490fdb); + // Various positive values. var cursor = f32_eps * 10; while (cursor != Infinity) { @@ -410,10 +417,9 @@ describe('binaryUtilsTest', function() { // NaN. jspb.utils.splitFloat64(NaN); - if (!isNaN(jspb.utils.joinFloat64(jspb.utils.split64Low, - jspb.utils.split64High))) { - throw 'fail!'; - } + expect(isNaN(jspb.utils.joinFloat64( + jspb.utils.split64Low, jspb.utils.split64High))) + .toEqual(true); /** * @param {number} x @@ -422,16 +428,17 @@ describe('binaryUtilsTest', function() { */ function test(x, opt_highBits, opt_lowBits) { jspb.utils.splitFloat64(x); - if (goog.isDef(opt_highBits)) { - if (opt_highBits != jspb.utils.split64High) throw 'fail!'; - } - if (goog.isDef(opt_lowBits)) { - if (opt_lowBits != jspb.utils.split64Low) throw 'fail!'; + if (opt_highBits !== undefined) { + var split64High = jspb.utils.split64High; + expect(opt_highBits.toString(16)).toEqual(split64High.toString(16)); } - if (x != jspb.utils.joinFloat64(jspb.utils.split64Low, - jspb.utils.split64High)) { - throw 'fail!'; + if (opt_lowBits !== undefined) { + var split64Low = jspb.utils.split64Low; + expect(opt_lowBits.toString(16)).toEqual(split64Low.toString(16)); } + expect( + jspb.utils.joinFloat64(jspb.utils.split64Low, jspb.utils.split64High)) + .toEqual(x); } // Positive and negative infinity. @@ -442,6 +449,9 @@ describe('binaryUtilsTest', function() { test(0, 0x00000000, 0x00000000); test(-0, 0x80000000, 0x00000000); + test(1, 0x3FF00000, 0x00000000); + test(2, 0x40000000, 0x00000000); + // Positive and negative epsilon. test(f64_eps, 0x00000000, 0x00000001); test(-f64_eps, 0x80000000, 0x00000001); @@ -454,6 +464,19 @@ describe('binaryUtilsTest', function() { test(f64_max, 0x7FEFFFFF, 0xFFFFFFFF); test(-f64_max, 0xFFEFFFFF, 0xFFFFFFFF); + test(Number.MAX_SAFE_INTEGER, 0x433FFFFF, 0xFFFFFFFF); + test(Number.MIN_SAFE_INTEGER, 0xC33FFFFF, 0xFFFFFFFF); + + // Test various edge cases with mantissa of all 1, all 0, or just the + // highest or lowest significant bit. + test(4503599627370497, 0x43300000, 0x00000001); + test(6755399441055744, 0x43380000, 0x00000000); + test(1.348269851146737e+308, 0x7FE80000, 0x00000000); + test(1.9999999999999998, 0x3FFFFFFF, 0xFFFFFFFF); + test(2.225073858507201e-308, 0x000FFFFF, 0xFFFFFFFF); + test(Math.PI, 0x400921fb, 0x54442d18); + test(jspb.BinaryConstants.FLOAT32_MIN, 0x38100000, 0x00000000); + // Various positive values. var cursor = f64_eps * 10; while (cursor != Infinity) { @@ -469,6 +492,53 @@ describe('binaryUtilsTest', function() { } }); + /** + * Tests zigzag conversions. + */ + it('can encode and decode zigzag 64', function() { + function stringToHiLoPair(str) { + jspb.utils.splitDecimalString(str); + return { + lo: jspb.utils.split64Low >>> 0, + hi: jspb.utils.split64High >>> 0 + }; + } + function makeHiLoPair(lo, hi) { + return {lo: lo >>> 0, hi: hi >>> 0}; + } + // Test cases directly from the protobuf dev guide. + // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types + var testCases = [ + {original: stringToHiLoPair('0'), zigzag: stringToHiLoPair('0')}, + {original: stringToHiLoPair('-1'), zigzag: stringToHiLoPair('1')}, + {original: stringToHiLoPair('1'), zigzag: stringToHiLoPair('2')}, + {original: stringToHiLoPair('-2'), zigzag: stringToHiLoPair('3')}, + { + original: stringToHiLoPair('2147483647'), + zigzag: stringToHiLoPair('4294967294') + }, + { + original: stringToHiLoPair('-2147483648'), + zigzag: stringToHiLoPair('4294967295') + }, + // 64-bit extremes + { + original: stringToHiLoPair('9223372036854775807'), + zigzag: stringToHiLoPair('18446744073709551614') + }, + { + original: stringToHiLoPair('-9223372036854775808'), + zigzag: stringToHiLoPair('18446744073709551615') + }, + ]; + for (const c of testCases) { + expect(jspb.utils.toZigzag64(c.original.lo, c.original.hi, makeHiLoPair)) + .toEqual(c.zigzag); + expect(jspb.utils.fromZigzag64(c.zigzag.lo, c.zigzag.hi, makeHiLoPair)) + .toEqual(c.original); + } + }); + /** * Tests counting packed varints. @@ -486,8 +556,8 @@ describe('binaryUtilsTest', function() { // We should have two more varints than we started with - one for the field // tag, one for the packed length. - assertEquals(values.length + 2, - jspb.utils.countVarints(buffer, 0, buffer.length)); + expect(jspb.utils.countVarints(buffer, 0, buffer.length)) + .toEqual(values.length + 2); }); @@ -505,8 +575,8 @@ describe('binaryUtilsTest', function() { writer.writeString(2, 'terminator'); var buffer = new Uint8Array(writer.getResultBuffer()); - assertEquals(count, - jspb.utils.countVarintFields(buffer, 0, buffer.length, 1)); + expect(jspb.utils.countVarintFields(buffer, 0, buffer.length, 1)) + .toEqual(count); writer = new jspb.BinaryWriter(); @@ -518,8 +588,8 @@ describe('binaryUtilsTest', function() { writer.writeString(2, 'terminator'); buffer = new Uint8Array(writer.getResultBuffer()); - assertEquals(count, - jspb.utils.countVarintFields(buffer, 0, buffer.length, 123456789)); + expect(jspb.utils.countVarintFields(buffer, 0, buffer.length, 123456789)) + .toEqual(count); }); @@ -537,8 +607,8 @@ describe('binaryUtilsTest', function() { writer.writeString(2, 'terminator'); var buffer = new Uint8Array(writer.getResultBuffer()); - assertEquals(count, - jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 1)); + expect(jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 1)) + .toEqual(count); writer = new jspb.BinaryWriter(); @@ -550,8 +620,8 @@ describe('binaryUtilsTest', function() { writer.writeString(2, 'terminator'); buffer = new Uint8Array(writer.getResultBuffer()); - assertEquals(count, - jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 123456789)); + expect(jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 123456789)) + .toEqual(count); }); @@ -569,8 +639,8 @@ describe('binaryUtilsTest', function() { writer.writeString(2, 'terminator'); var buffer = new Uint8Array(writer.getResultBuffer()); - assertEquals(count, - jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 1)); + expect(jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 1)) + .toEqual(count); writer = new jspb.BinaryWriter(); @@ -582,8 +652,8 @@ describe('binaryUtilsTest', function() { writer.writeString(2, 'terminator'); buffer = new Uint8Array(writer.getResultBuffer()); - assertEquals(count, - jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 123456789)); + expect(jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 123456789)) + .toEqual(count); }); @@ -601,8 +671,8 @@ describe('binaryUtilsTest', function() { writer.writeString(2, 'terminator'); var buffer = new Uint8Array(writer.getResultBuffer()); - assertEquals(count, - jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 1)); + expect(jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 1)) + .toEqual(count); writer = new jspb.BinaryWriter(); @@ -614,8 +684,8 @@ describe('binaryUtilsTest', function() { writer.writeString(2, 'terminator'); buffer = new Uint8Array(writer.getResultBuffer()); - assertEquals(count, - jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 123456789)); + expect(jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 123456789)) + .toEqual(count); }); @@ -623,9 +693,10 @@ describe('binaryUtilsTest', function() { * Tests byte format for debug strings. */ it('testDebugBytesToTextFormat', function() { - assertEquals('""', jspb.utils.debugBytesToTextFormat(null)); - assertEquals('"\\x00\\x10\\xff"', - jspb.utils.debugBytesToTextFormat([0, 16, 255])); + expect(jspb.utils.debugBytesToTextFormat(null)).toEqual('""'); + expect(jspb.utils.debugBytesToTextFormat([ + 0, 16, 255 + ])).toEqual('"\\x00\\x10\\xff"'); }); @@ -646,17 +717,17 @@ describe('binaryUtilsTest', function() { var sourceString = goog.crypt.byteArrayToString(sourceData); function check(result) { - assertEquals(Uint8Array, result.constructor); - assertEquals(sourceData.length, result.length); + expect(result.constructor).toEqual(Uint8Array); + expect(result.length).toEqual(sourceData.length); for (var i = 0; i < result.length; i++) { - assertEquals(sourceData[i], result[i]); + expect(result[i]).toEqual(sourceData[i]); } } // Converting Uint8Arrays into Uint8Arrays should be a no-op. - assertEquals(sourceBytes, convert(sourceBytes)); + expect(convert(sourceBytes)).toEqual(sourceBytes); - // Converting Array. into Uint8Arrays should work. + // Converting Array into Uint8Arrays should work. check(convert(sourceData)); // Converting ArrayBuffers into Uint8Arrays should work. diff --git a/js/binary/writer.js b/js/binary/writer.js index 037e92b240b73..1e2beee3e94e4 100644 --- a/js/binary/writer.js +++ b/js/binary/writer.js @@ -52,6 +52,7 @@ * Major caveat 3 - This class uses typed arrays and must not be used on older * browsers that do not support them. * + * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * @author aappleby@google.com (Austin Appleby) */ @@ -102,7 +103,7 @@ jspb.BinaryWriter = function() { * A stack of bookmarks containing the parent blocks for each message started * via beginSubMessage(), needed as bookkeeping for endSubMessage(). * TODO(aappleby): Deprecated, users should be calling writeMessage(). - * @private {!Array.>} + * @private {!Array>} */ this.bookmarks_ = []; }; @@ -126,7 +127,7 @@ jspb.BinaryWriter.prototype.appendUint8Array_ = function(arr) { * Begins a new message by writing the field header and returning a bookmark * which we will use to patch in the message length to in endDelimited_ below. * @param {number} field - * @return {!Array.} + * @return {!Array} * @private */ jspb.BinaryWriter.prototype.beginDelimited_ = function(field) { @@ -143,7 +144,7 @@ jspb.BinaryWriter.prototype.beginDelimited_ = function(field) { * Ends a message by encoding the _change_ in length of the buffer to the * parent block and adds the number of bytes needed to encode that length to * the total byte length. - * @param {!Array.} bookmark + * @param {!Array} bookmark * @private */ jspb.BinaryWriter.prototype.endDelimited_ = function(bookmark) { @@ -236,10 +237,11 @@ jspb.BinaryWriter.prototype.getResultBuffer = function() { /** * Converts the encoded data into a base64-encoded string. + * @param {!goog.crypt.base64.Alphabet=} alphabet Which flavor of base64 to use. * @return {string} */ -jspb.BinaryWriter.prototype.getResultBase64String = function() { - return goog.crypt.base64.encodeByteArray(this.getResultBuffer()); +jspb.BinaryWriter.prototype.getResultBase64String = function(alphabet) { + return goog.crypt.base64.encodeByteArray(this.getResultBuffer(), alphabet); }; @@ -448,6 +450,19 @@ jspb.BinaryWriter.prototype.writeZigzagVarint64String_ = function( }; +/** + * Writes a zigzag varint field to the buffer without range checking. + * @param {number} field The field number. + * @param {string?} value The value to write. + * @private + */ +jspb.BinaryWriter.prototype.writeZigzagVarintHash64_ = function(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeZigzagVarintHash64(value); +}; + + /** * Writes an int32 field to the buffer. Numbers outside the range [-2^31,2^31) * will be truncated. @@ -561,7 +576,7 @@ jspb.BinaryWriter.prototype.writeUint64String = function(field, value) { /** - * Writes a sint32 field to the buffer. Numbers outside the range [-2^31,2^31) + * Writes an sint32 field to the buffer. Numbers outside the range [-2^31,2^31) * will be truncated. * @param {number} field The field number. * @param {number?} value The value to write. @@ -575,7 +590,7 @@ jspb.BinaryWriter.prototype.writeSint32 = function(field, value) { /** - * Writes a sint64 field to the buffer. Numbers outside the range [-2^63,2^63) + * Writes an sint64 field to the buffer. Numbers outside the range [-2^63,2^63) * will be truncated. * @param {number} field The field number. * @param {number?} value The value to write. @@ -589,15 +604,25 @@ jspb.BinaryWriter.prototype.writeSint64 = function(field, value) { /** - * Writes a sint64 field to the buffer. Numbers outside the range [-2^63,2^63) + * Writes an sint64 field to the buffer from a hash64 encoded value. Numbers + * outside the range [-2^63,2^63) will be truncated. + * @param {number} field The field number. + * @param {string?} value The hash64 string to write. + */ +jspb.BinaryWriter.prototype.writeSintHash64 = function(field, value) { + if (value == null) return; + this.writeZigzagVarintHash64_(field, value); +}; + + +/** + * Writes an sint64 field to the buffer. Numbers outside the range [-2^63,2^63) * will be truncated. * @param {number} field The field number. * @param {string?} value The decimal string to write. */ jspb.BinaryWriter.prototype.writeSint64String = function(field, value) { if (value == null) return; - goog.asserts.assert((+value >= -jspb.BinaryConstants.TWO_TO_63) && - (+value < jspb.BinaryConstants.TWO_TO_63)); this.writeZigzagVarint64String_(field, value); }; @@ -724,7 +749,7 @@ jspb.BinaryWriter.prototype.writeDouble = function(field, value) { */ jspb.BinaryWriter.prototype.writeBool = function(field, value) { if (value == null) return; - goog.asserts.assert(goog.isBoolean(value) || goog.isNumber(value)); + goog.asserts.assert(typeof value === 'boolean' || typeof value === 'number'); this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); this.encoder_.writeBool(value); }; @@ -797,6 +822,38 @@ jspb.BinaryWriter.prototype.writeMessage = function( }; +/** + * Writes a message set extension to the buffer. + * @param {number} field The field number for the extension. + * @param {?MessageType} value The extension message object to write. Note that + * message set can only have extensions with type of optional message. + * @param {function(!MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback + * Will be invoked with the value to write and the writer to write it with. + * @template MessageType + * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace + * the null in blah|null with none. This is necessary because the compiler will + * infer MessageType to be nullable if the value parameter is nullable. + * @template MessageTypeNonNull := + * cond(isUnknown(MessageType), unknown(), + * mapunion(MessageType, (X) => + * cond(eq(X, 'null'), none(), X))) + * =: + */ +jspb.BinaryWriter.prototype.writeMessageSet = function( + field, value, writerCallback) { + if (value == null) return; + // The wire format for a message set is defined by + // google3/net/proto/message_set.proto + this.writeFieldHeader_(1, jspb.BinaryConstants.WireType.START_GROUP); + this.writeFieldHeader_(2, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeSignedVarint32(field); + var bookmark = this.beginDelimited_(3); + writerCallback(value, this); + this.endDelimited_(bookmark); + this.writeFieldHeader_(1, jspb.BinaryConstants.WireType.END_GROUP); +}; + + /** * Writes a group message to the buffer. * @@ -852,10 +909,52 @@ jspb.BinaryWriter.prototype.writeVarintHash64 = function(field, value) { }; +/** + * Writes a 64-bit field to the buffer as a fixed64. + * @param {number} field The field number. + * @param {number} lowBits The low 32 bits. + * @param {number} highBits The high 32 bits. + */ +jspb.BinaryWriter.prototype.writeSplitFixed64 = function( + field, lowBits, highBits) { + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); + this.encoder_.writeSplitFixed64(lowBits, highBits); +}; + + +/** + * Writes a 64-bit field to the buffer as a varint. + * @param {number} field The field number. + * @param {number} lowBits The low 32 bits. + * @param {number} highBits The high 32 bits. + */ +jspb.BinaryWriter.prototype.writeSplitVarint64 = function( + field, lowBits, highBits) { + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + this.encoder_.writeSplitVarint64(lowBits, highBits); +}; + + +/** + * Writes a 64-bit field to the buffer as a zigzag encoded varint. + * @param {number} field The field number. + * @param {number} lowBits The low 32 bits. + * @param {number} highBits The high 32 bits. + */ +jspb.BinaryWriter.prototype.writeSplitZigzagVarint64 = function( + field, lowBits, highBits) { + this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); + var encoder = this.encoder_; + jspb.utils.toZigzag64(lowBits, highBits, function(lowBits, highBits) { + encoder.writeSplitVarint64(lowBits >>> 0, highBits >>> 0); + }); +}; + + /** * Writes an array of numbers to the buffer as a repeated 32-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedInt32 = function(field, value) { if (value == null) return; @@ -869,7 +968,7 @@ jspb.BinaryWriter.prototype.writeRepeatedInt32 = function(field, value) { * Writes an array of numbers formatted as strings to the buffer as a repeated * 32-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedInt32String = function(field, value) { if (value == null) return; @@ -882,7 +981,7 @@ jspb.BinaryWriter.prototype.writeRepeatedInt32String = function(field, value) { /** * Writes an array of numbers to the buffer as a repeated 64-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedInt64 = function(field, value) { if (value == null) return; @@ -892,11 +991,62 @@ jspb.BinaryWriter.prototype.writeRepeatedInt64 = function(field, value) { }; +/** + * Writes an array of 64-bit values to the buffer as a fixed64. + * @param {number} field The field number. + * @param {?Array} value The value. + * @param {function(T): number} lo Function to get low bits. + * @param {function(T): number} hi Function to get high bits. + * @template T + */ +jspb.BinaryWriter.prototype.writeRepeatedSplitFixed64 = function( + field, value, lo, hi) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeSplitFixed64(field, lo(value[i]), hi(value[i])); + } +}; + + +/** + * Writes an array of 64-bit values to the buffer as a varint. + * @param {number} field The field number. + * @param {?Array} value The value. + * @param {function(T): number} lo Function to get low bits. + * @param {function(T): number} hi Function to get high bits. + * @template T + */ +jspb.BinaryWriter.prototype.writeRepeatedSplitVarint64 = function( + field, value, lo, hi) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeSplitVarint64(field, lo(value[i]), hi(value[i])); + } +}; + + +/** + * Writes an array of 64-bit values to the buffer as a zigzag varint. + * @param {number} field The field number. + * @param {?Array} value The value. + * @param {function(T): number} lo Function to get low bits. + * @param {function(T): number} hi Function to get high bits. + * @template T + */ +jspb.BinaryWriter.prototype.writeRepeatedSplitZigzagVarint64 = function( + field, value, lo, hi) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeSplitZigzagVarint64(field, lo(value[i]), hi(value[i])); + } +}; + + /** * Writes an array of numbers formatted as strings to the buffer as a repeated * 64-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedInt64String = function(field, value) { if (value == null) return; @@ -910,7 +1060,7 @@ jspb.BinaryWriter.prototype.writeRepeatedInt64String = function(field, value) { * Writes an array numbers to the buffer as a repeated unsigned 32-bit int * field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedUint32 = function(field, value) { if (value == null) return; @@ -924,7 +1074,7 @@ jspb.BinaryWriter.prototype.writeRepeatedUint32 = function(field, value) { * Writes an array of numbers formatted as strings to the buffer as a repeated * unsigned 32-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedUint32String = function(field, value) { if (value == null) return; @@ -938,7 +1088,7 @@ jspb.BinaryWriter.prototype.writeRepeatedUint32String = function(field, value) { * Writes an array numbers to the buffer as a repeated unsigned 64-bit int * field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedUint64 = function(field, value) { if (value == null) return; @@ -952,7 +1102,7 @@ jspb.BinaryWriter.prototype.writeRepeatedUint64 = function(field, value) { * Writes an array of numbers formatted as strings to the buffer as a repeated * unsigned 64-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedUint64String = function(field, value) { if (value == null) return; @@ -965,7 +1115,7 @@ jspb.BinaryWriter.prototype.writeRepeatedUint64String = function(field, value) { /** * Writes an array numbers to the buffer as a repeated signed 32-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedSint32 = function(field, value) { if (value == null) return; @@ -978,7 +1128,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSint32 = function(field, value) { /** * Writes an array numbers to the buffer as a repeated signed 64-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedSint64 = function(field, value) { if (value == null) return; @@ -991,7 +1141,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSint64 = function(field, value) { /** * Writes an array numbers to the buffer as a repeated signed 64-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedSint64String = function(field, value) { if (value == null) return; @@ -1001,11 +1151,25 @@ jspb.BinaryWriter.prototype.writeRepeatedSint64String = function(field, value) { }; +/** + * Writes an array of hash64 strings to the buffer as a repeated signed 64-bit + * int field. + * @param {number} field The field number. + * @param {?Array} value The array of ints to write. + */ +jspb.BinaryWriter.prototype.writeRepeatedSintHash64 = function(field, value) { + if (value == null) return; + for (var i = 0; i < value.length; i++) { + this.writeZigzagVarintHash64_(field, value[i]); + } +}; + + /** * Writes an array of numbers to the buffer as a repeated fixed32 field. This * works for both signed and unsigned fixed32s. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedFixed32 = function(field, value) { if (value == null) return; @@ -1019,7 +1183,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFixed32 = function(field, value) { * Writes an array of numbers to the buffer as a repeated fixed64 field. This * works for both signed and unsigned fixed64s. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedFixed64 = function(field, value) { if (value == null) return; @@ -1033,7 +1197,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFixed64 = function(field, value) { * Writes an array of numbers to the buffer as a repeated fixed64 field. This * works for both signed and unsigned fixed64s. * @param {number} field The field number. - * @param {?Array.} value The array of decimal strings to write. + * @param {?Array} value The array of decimal strings to write. */ jspb.BinaryWriter.prototype.writeRepeatedFixed64String = function( field, value) { @@ -1047,7 +1211,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFixed64String = function( /** * Writes an array of numbers to the buffer as a repeated sfixed32 field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedSfixed32 = function(field, value) { if (value == null) return; @@ -1060,7 +1224,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSfixed32 = function(field, value) { /** * Writes an array of numbers to the buffer as a repeated sfixed64 field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedSfixed64 = function(field, value) { if (value == null) return; @@ -1074,7 +1238,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSfixed64 = function(field, value) { * Writes an array of decimal strings to the buffer as a repeated sfixed64 * field. * @param {number} field The field number. - * @param {?Array.} value The array of decimal strings to write. + * @param {?Array} value The array of decimal strings to write. */ jspb.BinaryWriter.prototype.writeRepeatedSfixed64String = function(field, value) { if (value == null) return; @@ -1087,7 +1251,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSfixed64String = function(field, value) /** * Writes an array of numbers to the buffer as a repeated float field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedFloat = function(field, value) { if (value == null) return; @@ -1100,7 +1264,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFloat = function(field, value) { /** * Writes an array of numbers to the buffer as a repeated double field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedDouble = function(field, value) { if (value == null) return; @@ -1113,7 +1277,7 @@ jspb.BinaryWriter.prototype.writeRepeatedDouble = function(field, value) { /** * Writes an array of booleans to the buffer as a repeated bool field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedBool = function(field, value) { if (value == null) return; @@ -1126,7 +1290,7 @@ jspb.BinaryWriter.prototype.writeRepeatedBool = function(field, value) { /** * Writes an array of enums to the buffer as a repeated enum field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writeRepeatedEnum = function(field, value) { if (value == null) return; @@ -1139,7 +1303,7 @@ jspb.BinaryWriter.prototype.writeRepeatedEnum = function(field, value) { /** * Writes an array of strings to the buffer as a repeated string field. * @param {number} field The field number. - * @param {?Array.} value The array of strings to write. + * @param {?Array} value The array of strings to write. */ jspb.BinaryWriter.prototype.writeRepeatedString = function(field, value) { if (value == null) return; @@ -1152,7 +1316,7 @@ jspb.BinaryWriter.prototype.writeRepeatedString = function(field, value) { /** * Writes an array of arbitrary byte fields to the buffer. * @param {number} field The field number. - * @param {?Array.} value The arrays of arrays of bytes to + * @param {?Array} value The arrays of arrays of bytes to * write. */ jspb.BinaryWriter.prototype.writeRepeatedBytes = function(field, value) { @@ -1167,7 +1331,7 @@ jspb.BinaryWriter.prototype.writeRepeatedBytes = function(field, value) { * Writes an array of messages to the buffer. * @template MessageType * @param {number} field The field number. - * @param {?Array.} value The array of messages to + * @param {?Array} value The array of messages to * write. * @param {function(MessageType, !jspb.BinaryWriter)} writerCallback * Will be invoked with the value to write and the writer to write it with. @@ -1187,7 +1351,7 @@ jspb.BinaryWriter.prototype.writeRepeatedMessage = function( * Writes an array of group messages to the buffer. * @template MessageType * @param {number} field The field number. - * @param {?Array.} value The array of messages to + * @param {?Array} value The array of messages to * write. * @param {function(MessageType, !jspb.BinaryWriter)} writerCallback * Will be invoked with the value to write and the writer to write it with. @@ -1207,7 +1371,7 @@ jspb.BinaryWriter.prototype.writeRepeatedGroup = function( * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to * the buffer. * @param {number} field The field number. - * @param {?Array.} value The array of hashes to write. + * @param {?Array} value The array of hashes to write. */ jspb.BinaryWriter.prototype.writeRepeatedFixedHash64 = function(field, value) { @@ -1222,7 +1386,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFixedHash64 = * Writes a repeated 64-bit hash string field (8 characters @ 8 bits of data * each) to the buffer. * @param {number} field The field number. - * @param {?Array.} value The array of hashes to write. + * @param {?Array} value The array of hashes to write. */ jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 = function(field, value) { @@ -1236,7 +1400,7 @@ jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 = /** * Writes an array of numbers to the buffer as a packed 32-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedInt32 = function(field, value) { if (value == null || !value.length) return; @@ -1252,7 +1416,7 @@ jspb.BinaryWriter.prototype.writePackedInt32 = function(field, value) { * Writes an array of numbers represented as strings to the buffer as a packed * 32-bit int field. * @param {number} field - * @param {?Array.} value + * @param {?Array} value */ jspb.BinaryWriter.prototype.writePackedInt32String = function(field, value) { if (value == null || !value.length) return; @@ -1267,7 +1431,7 @@ jspb.BinaryWriter.prototype.writePackedInt32String = function(field, value) { /** * Writes an array of numbers to the buffer as a packed 64-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedInt64 = function(field, value) { if (value == null || !value.length) return; @@ -1279,11 +1443,72 @@ jspb.BinaryWriter.prototype.writePackedInt64 = function(field, value) { }; +/** + * Writes an array of 64-bit values to the buffer as a fixed64. + * @param {number} field The field number. + * @param {?Array} value The value. + * @param {function(T): number} lo Function to get low bits. + * @param {function(T): number} hi Function to get high bits. + * @template T + */ +jspb.BinaryWriter.prototype.writePackedSplitFixed64 = function( + field, value, lo, hi) { + if (value == null) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeSplitFixed64(lo(value[i]), hi(value[i])); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes an array of 64-bit values to the buffer as a varint. + * @param {number} field The field number. + * @param {?Array} value The value. + * @param {function(T): number} lo Function to get low bits. + * @param {function(T): number} hi Function to get high bits. + * @template T + */ +jspb.BinaryWriter.prototype.writePackedSplitVarint64 = function( + field, value, lo, hi) { + if (value == null) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeSplitVarint64(lo(value[i]), hi(value[i])); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes an array of 64-bit values to the buffer as a zigzag varint. + * @param {number} field The field number. + * @param {?Array} value The value. + * @param {function(T): number} lo Function to get low bits. + * @param {function(T): number} hi Function to get high bits. + * @template T + */ +jspb.BinaryWriter.prototype.writePackedSplitZigzagVarint64 = function( + field, value, lo, hi) { + if (value == null) return; + var bookmark = this.beginDelimited_(field); + var encoder = this.encoder_; + for (var i = 0; i < value.length; i++) { + jspb.utils.toZigzag64( + lo(value[i]), hi(value[i]), function(bitsLow, bitsHigh) { + encoder.writeSplitVarint64(bitsLow >>> 0, bitsHigh >>> 0); + }); + } + this.endDelimited_(bookmark); +}; + + /** * Writes an array of numbers represented as strings to the buffer as a packed * 64-bit int field. * @param {number} field - * @param {?Array.} value + * @param {?Array} value */ jspb.BinaryWriter.prototype.writePackedInt64String = function(field, value) { if (value == null || !value.length) return; @@ -1299,7 +1524,7 @@ jspb.BinaryWriter.prototype.writePackedInt64String = function(field, value) { /** * Writes an array numbers to the buffer as a packed unsigned 32-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedUint32 = function(field, value) { if (value == null || !value.length) return; @@ -1315,7 +1540,7 @@ jspb.BinaryWriter.prototype.writePackedUint32 = function(field, value) { * Writes an array of numbers represented as strings to the buffer as a packed * unsigned 32-bit int field. * @param {number} field - * @param {?Array.} value + * @param {?Array} value */ jspb.BinaryWriter.prototype.writePackedUint32String = function(field, value) { @@ -1331,7 +1556,7 @@ jspb.BinaryWriter.prototype.writePackedUint32String = /** * Writes an array numbers to the buffer as a packed unsigned 64-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedUint64 = function(field, value) { if (value == null || !value.length) return; @@ -1347,7 +1572,7 @@ jspb.BinaryWriter.prototype.writePackedUint64 = function(field, value) { * Writes an array of numbers represented as strings to the buffer as a packed * unsigned 64-bit int field. * @param {number} field - * @param {?Array.} value + * @param {?Array} value */ jspb.BinaryWriter.prototype.writePackedUint64String = function(field, value) { @@ -1364,7 +1589,7 @@ jspb.BinaryWriter.prototype.writePackedUint64String = /** * Writes an array numbers to the buffer as a packed signed 32-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedSint32 = function(field, value) { if (value == null || !value.length) return; @@ -1379,7 +1604,7 @@ jspb.BinaryWriter.prototype.writePackedSint32 = function(field, value) { /** * Writes an array of numbers to the buffer as a packed signed 64-bit int field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedSint64 = function(field, value) { if (value == null || !value.length) return; @@ -1395,14 +1620,30 @@ jspb.BinaryWriter.prototype.writePackedSint64 = function(field, value) { * Writes an array of decimal strings to the buffer as a packed signed 64-bit * int field. * @param {number} field The field number. - * @param {?Array.} value The array of decimal strings to write. + * @param {?Array} value The array of decimal strings to write. */ jspb.BinaryWriter.prototype.writePackedSint64String = function(field, value) { if (value == null || !value.length) return; var bookmark = this.beginDelimited_(field); for (var i = 0; i < value.length; i++) { - // TODO(haberman): make lossless - this.encoder_.writeZigzagVarint64(parseInt(value[i], 10)); + this.encoder_.writeZigzagVarintHash64( + jspb.utils.decimalStringToHash64(value[i])); + } + this.endDelimited_(bookmark); +}; + + +/** + * Writes an array of hash 64 strings to the buffer as a packed signed 64-bit + * int field. + * @param {number} field The field number. + * @param {?Array} value The array of decimal strings to write. + */ +jspb.BinaryWriter.prototype.writePackedSintHash64 = function(field, value) { + if (value == null || !value.length) return; + var bookmark = this.beginDelimited_(field); + for (var i = 0; i < value.length; i++) { + this.encoder_.writeZigzagVarintHash64(value[i]); } this.endDelimited_(bookmark); }; @@ -1411,7 +1652,7 @@ jspb.BinaryWriter.prototype.writePackedSint64String = function(field, value) { /** * Writes an array of numbers to the buffer as a packed fixed32 field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedFixed32 = function(field, value) { if (value == null || !value.length) return; @@ -1426,7 +1667,7 @@ jspb.BinaryWriter.prototype.writePackedFixed32 = function(field, value) { /** * Writes an array of numbers to the buffer as a packed fixed64 field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedFixed64 = function(field, value) { if (value == null || !value.length) return; @@ -1442,7 +1683,7 @@ jspb.BinaryWriter.prototype.writePackedFixed64 = function(field, value) { * Writes an array of numbers represented as strings to the buffer as a packed * fixed64 field. * @param {number} field The field number. - * @param {?Array.} value The array of strings to write. + * @param {?Array} value The array of strings to write. */ jspb.BinaryWriter.prototype.writePackedFixed64String = function(field, value) { if (value == null || !value.length) return; @@ -1458,7 +1699,7 @@ jspb.BinaryWriter.prototype.writePackedFixed64String = function(field, value) { /** * Writes an array of numbers to the buffer as a packed sfixed32 field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedSfixed32 = function(field, value) { if (value == null || !value.length) return; @@ -1473,7 +1714,7 @@ jspb.BinaryWriter.prototype.writePackedSfixed32 = function(field, value) { /** * Writes an array of numbers to the buffer as a packed sfixed64 field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedSfixed64 = function(field, value) { if (value == null || !value.length) return; @@ -1488,7 +1729,7 @@ jspb.BinaryWriter.prototype.writePackedSfixed64 = function(field, value) { /** * Writes an array of numbers to the buffer as a packed sfixed64 field. * @param {number} field The field number. - * @param {?Array.} value The array of decimal strings to write. + * @param {?Array} value The array of decimal strings to write. */ jspb.BinaryWriter.prototype.writePackedSfixed64String = function(field, value) { if (value == null || !value.length) return; @@ -1503,7 +1744,7 @@ jspb.BinaryWriter.prototype.writePackedSfixed64String = function(field, value) { /** * Writes an array of numbers to the buffer as a packed float field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedFloat = function(field, value) { if (value == null || !value.length) return; @@ -1518,7 +1759,7 @@ jspb.BinaryWriter.prototype.writePackedFloat = function(field, value) { /** * Writes an array of numbers to the buffer as a packed double field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedDouble = function(field, value) { if (value == null || !value.length) return; @@ -1533,7 +1774,7 @@ jspb.BinaryWriter.prototype.writePackedDouble = function(field, value) { /** * Writes an array of booleans to the buffer as a packed bool field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedBool = function(field, value) { if (value == null || !value.length) return; @@ -1548,7 +1789,7 @@ jspb.BinaryWriter.prototype.writePackedBool = function(field, value) { /** * Writes an array of enums to the buffer as a packed enum field. * @param {number} field The field number. - * @param {?Array.} value The array of ints to write. + * @param {?Array} value The array of ints to write. */ jspb.BinaryWriter.prototype.writePackedEnum = function(field, value) { if (value == null || !value.length) return; @@ -1564,7 +1805,7 @@ jspb.BinaryWriter.prototype.writePackedEnum = function(field, value) { * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to * the buffer. * @param {number} field The field number. - * @param {?Array.} value The array of hashes to write. + * @param {?Array} value The array of hashes to write. */ jspb.BinaryWriter.prototype.writePackedFixedHash64 = function(field, value) { if (value == null || !value.length) return; @@ -1580,7 +1821,7 @@ jspb.BinaryWriter.prototype.writePackedFixedHash64 = function(field, value) { * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to * the buffer. * @param {number} field The field number. - * @param {?Array.} value The array of hashes to write. + * @param {?Array} value The array of hashes to write. */ jspb.BinaryWriter.prototype.writePackedVarintHash64 = function(field, value) { if (value == null || !value.length) return; diff --git a/js/binary/writer_test.js b/js/binary/writer_test.js index 118eecfc6cd13..6c5f36e9218ed 100644 --- a/js/binary/writer_test.js +++ b/js/binary/writer_test.js @@ -40,8 +40,12 @@ goog.require('goog.crypt'); goog.require('goog.testing.asserts'); +goog.require('jspb.BinaryConstants'); +goog.require('jspb.BinaryReader'); goog.require('jspb.BinaryWriter'); - +goog.require('jspb.utils'); +goog.require('goog.crypt.base64'); +goog.requireType('jspb.BinaryMessage'); /** * @param {function()} func This function should throw an error when run. @@ -58,7 +62,7 @@ describe('binaryWriterTest', function() { it('testWriteErrors', function() { // Submessages with invalid field indices should assert. var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); assertFails(function() { writer.writeMessage(-1, dummyMessage, goog.nullFunction); @@ -66,40 +70,82 @@ describe('binaryWriterTest', function() { // Writing invalid field indices should assert. writer = new jspb.BinaryWriter(); - assertFails(function() {writer.writeUint64(-1, 1);}); + assertFails(function() { + writer.writeUint64(-1, 1); + }); // Writing out-of-range field values should assert. writer = new jspb.BinaryWriter(); - assertFails(function() {writer.writeInt32(1, -Infinity);}); - assertFails(function() {writer.writeInt32(1, Infinity);}); + assertFails(function() { + writer.writeInt32(1, -Infinity); + }); + assertFails(function() { + writer.writeInt32(1, Infinity); + }); - assertFails(function() {writer.writeInt64(1, -Infinity);}); - assertFails(function() {writer.writeInt64(1, Infinity);}); + assertFails(function() { + writer.writeInt64(1, -Infinity); + }); + assertFails(function() { + writer.writeInt64(1, Infinity); + }); - assertFails(function() {writer.writeUint32(1, -1);}); - assertFails(function() {writer.writeUint32(1, Infinity);}); + assertFails(function() { + writer.writeUint32(1, -1); + }); + assertFails(function() { + writer.writeUint32(1, Infinity); + }); - assertFails(function() {writer.writeUint64(1, -1);}); - assertFails(function() {writer.writeUint64(1, Infinity);}); + assertFails(function() { + writer.writeUint64(1, -1); + }); + assertFails(function() { + writer.writeUint64(1, Infinity); + }); - assertFails(function() {writer.writeSint32(1, -Infinity);}); - assertFails(function() {writer.writeSint32(1, Infinity);}); + assertFails(function() { + writer.writeSint32(1, -Infinity); + }); + assertFails(function() { + writer.writeSint32(1, Infinity); + }); - assertFails(function() {writer.writeSint64(1, -Infinity);}); - assertFails(function() {writer.writeSint64(1, Infinity);}); + assertFails(function() { + writer.writeSint64(1, -Infinity); + }); + assertFails(function() { + writer.writeSint64(1, Infinity); + }); - assertFails(function() {writer.writeFixed32(1, -1);}); - assertFails(function() {writer.writeFixed32(1, Infinity);}); + assertFails(function() { + writer.writeFixed32(1, -1); + }); + assertFails(function() { + writer.writeFixed32(1, Infinity); + }); - assertFails(function() {writer.writeFixed64(1, -1);}); - assertFails(function() {writer.writeFixed64(1, Infinity);}); + assertFails(function() { + writer.writeFixed64(1, -1); + }); + assertFails(function() { + writer.writeFixed64(1, Infinity); + }); - assertFails(function() {writer.writeSfixed32(1, -Infinity);}); - assertFails(function() {writer.writeSfixed32(1, Infinity);}); + assertFails(function() { + writer.writeSfixed32(1, -Infinity); + }); + assertFails(function() { + writer.writeSfixed32(1, Infinity); + }); - assertFails(function() {writer.writeSfixed64(1, -Infinity);}); - assertFails(function() {writer.writeSfixed64(1, Infinity);}); + assertFails(function() { + writer.writeSfixed64(1, -Infinity); + }); + assertFails(function() { + writer.writeSfixed64(1, Infinity); + }); }); @@ -118,4 +164,249 @@ describe('binaryWriterTest', function() { var buffer = writer.getResultBuffer(); assertEquals(expected, goog.crypt.byteArrayToHex(buffer)); }); + + + /** + * Tests websafe encodings for base64 strings. + */ + it('testWebSafeOption', function() { + var writer = new jspb.BinaryWriter(); + writer.writeBytes(1, new Uint8Array([127])); + assertEquals('CgF/', writer.getResultBase64String()); + assertEquals( + 'CgF/', + writer.getResultBase64String(goog.crypt.base64.Alphabet.DEFAULT)); + assertEquals( + 'CgF_', + writer.getResultBase64String( + goog.crypt.base64.Alphabet.WEBSAFE_NO_PADDING)); + }); + + it('writes split 64 fields', function() { + var writer = new jspb.BinaryWriter(); + writer.writeSplitVarint64(1, 0x1, 0x2); + writer.writeSplitVarint64(1, 0xFFFFFFFF, 0xFFFFFFFF); + writer.writeSplitFixed64(2, 0x1, 0x2); + writer.writeSplitFixed64(2, 0xFFFFFFF0, 0xFFFFFFFF); + function lo(i) { + return i + 1; + } + function hi(i) { + return i + 2; + } + writer.writeRepeatedSplitVarint64(3, [0, 1, 2], lo, hi); + writer.writeRepeatedSplitFixed64(4, [0, 1, 2], lo, hi); + writer.writePackedSplitVarint64(5, [0, 1, 2], lo, hi); + writer.writePackedSplitFixed64(6, [0, 1, 2], lo, hi); + + function bitsAsArray(lowBits, highBits) { + return [lowBits >>> 0, highBits >>> 0]; + } + var reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(1); + expect(reader.readSplitVarint64(bitsAsArray)).toEqual([0x1, 0x2]); + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(1); + expect(reader.readSplitVarint64(bitsAsArray)).toEqual([ + 0xFFFFFFFF, 0xFFFFFFFF + ]); + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(2); + expect(reader.readSplitFixed64(bitsAsArray)).toEqual([0x1, 0x2]); + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(2); + expect(reader.readSplitFixed64(bitsAsArray)).toEqual([ + 0xFFFFFFF0, 0xFFFFFFFF + ]); + + for (let i = 0; i < 3; i++) { + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(3); + expect(reader.readSplitVarint64(bitsAsArray)).toEqual([i + 1, i + 2]); + } + + for (let i = 0; i < 3; i++) { + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(4); + expect(reader.readSplitFixed64(bitsAsArray)).toEqual([i + 1, i + 2]); + } + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(5); + expect(reader.readPackedInt64String()).toEqual([ + String(2 * 2 ** 32 + 1), + String(3 * 2 ** 32 + 2), + String(4 * 2 ** 32 + 3), + ]); + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(6); + expect(reader.readPackedFixed64String()).toEqual([ + String(2 * 2 ** 32 + 1), + String(3 * 2 ** 32 + 2), + String(4 * 2 ** 32 + 3), + ]); + }); + + it('writes zigzag 64 fields', function() { + // Test cases directly from the protobuf dev guide. + // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types + var testCases = [ + {original: '0', zigzag: '0'}, + {original: '-1', zigzag: '1'}, + {original: '1', zigzag: '2'}, + {original: '-2', zigzag: '3'}, + {original: '2147483647', zigzag: '4294967294'}, + {original: '-2147483648', zigzag: '4294967295'}, + // 64-bit extremes, not in dev guide. + {original: '9223372036854775807', zigzag: '18446744073709551614'}, + {original: '-9223372036854775808', zigzag: '18446744073709551615'}, + ]; + function decimalToLowBits(v) { + jspb.utils.splitDecimalString(v); + return jspb.utils.split64Low >>> 0; + } + function decimalToHighBits(v) { + jspb.utils.splitDecimalString(v); + return jspb.utils.split64High >>> 0; + } + + var writer = new jspb.BinaryWriter(); + testCases.forEach(function(c) { + writer.writeSint64String(1, c.original); + writer.writeSintHash64(1, jspb.utils.decimalStringToHash64(c.original)); + jspb.utils.splitDecimalString(c.original); + writer.writeSplitZigzagVarint64( + 1, jspb.utils.split64Low, jspb.utils.split64High); + }); + + writer.writeRepeatedSint64String(2, testCases.map(function(c) { + return c.original; + })); + + writer.writeRepeatedSintHash64(3, testCases.map(function(c) { + return jspb.utils.decimalStringToHash64(c.original); + })); + + writer.writeRepeatedSplitZigzagVarint64( + 4, testCases.map(function(c) { + return c.original; + }), + decimalToLowBits, decimalToHighBits); + + writer.writePackedSint64String(5, testCases.map(function(c) { + return c.original; + })); + + writer.writePackedSintHash64(6, testCases.map(function(c) { + return jspb.utils.decimalStringToHash64(c.original); + })); + + writer.writePackedSplitZigzagVarint64( + 7, testCases.map(function(c) { + return c.original; + }), + decimalToLowBits, decimalToHighBits); + + // Verify by reading the stream as normal int64 fields and checking with + // the canonical zigzag encoding of each value. + var reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + testCases.forEach(function(c) { + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(1); + expect(reader.readUint64String()).toEqual(c.zigzag); + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(1); + expect(reader.readUint64String()).toEqual(c.zigzag); + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(1); + expect(reader.readUint64String()).toEqual(c.zigzag); + }); + + testCases.forEach(function(c) { + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(2); + expect(reader.readUint64String()).toEqual(c.zigzag); + }); + + testCases.forEach(function(c) { + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(3); + expect(reader.readUint64String()).toEqual(c.zigzag); + }); + + testCases.forEach(function(c) { + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(4); + expect(reader.readUint64String()).toEqual(c.zigzag); + }); + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(5); + expect(reader.readPackedUint64String()).toEqual(testCases.map(function(c) { + return c.zigzag; + })); + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(6); + expect(reader.readPackedUint64String()).toEqual(testCases.map(function(c) { + return c.zigzag; + })); + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(7); + expect(reader.readPackedUint64String()).toEqual(testCases.map(function(c) { + return c.zigzag; + })); + }); + + it('writes float32 fields', function() { + var testCases = [ + 0, 1, -1, jspb.BinaryConstants.FLOAT32_MIN, + -jspb.BinaryConstants.FLOAT32_MIN, jspb.BinaryConstants.FLOAT32_MAX, + -jspb.BinaryConstants.FLOAT32_MAX, 3.1415927410125732, Infinity, + -Infinity, NaN + ]; + var writer = new jspb.BinaryWriter(); + testCases.forEach(function(f) { + writer.writeFloat(1, f); + }); + var reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + testCases.forEach(function(f) { + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(1); + if (isNaN(f)) { + expect(isNaN(reader.readFloat())).toEqual(true); + } else { + expect(reader.readFloat()).toEqual(f); + } + }); + }); + + it('writes double fields', function() { + var testCases = [ + 0, 1, -1, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER, + Number.MAX_VALUE, Number.MIN_VALUE, jspb.BinaryConstants.FLOAT32_MIN, + -jspb.BinaryConstants.FLOAT32_MIN, jspb.BinaryConstants.FLOAT32_MAX, + -jspb.BinaryConstants.FLOAT32_MAX, Math.PI, Infinity, -Infinity, NaN + ]; + var writer = new jspb.BinaryWriter(); + testCases.forEach(function(f) { + writer.writeDouble(1, f); + }); + var reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + testCases.forEach(function(f) { + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(1); + if (isNaN(f)) { + expect(isNaN(reader.readDouble())).toEqual(true); + } else { + expect(reader.readDouble()).toEqual(f); + } + }); + }); }); diff --git a/js/commonjs/export_testdeps.js b/js/commonjs/export_testdeps.js index 6f5cd0839baa0..96d3f3470b38c 100644 --- a/js/commonjs/export_testdeps.js +++ b/js/commonjs/export_testdeps.js @@ -12,6 +12,7 @@ goog.provide('jspb.ExportTestDeps'); goog.require('goog.crypt.base64'); +goog.require('goog.testing.PropertyReplacer'); goog.require('jspb.arith.Int64'); goog.require('jspb.arith.UInt64'); goog.require('jspb.BinaryEncoder'); diff --git a/js/commonjs/rewrite_tests_for_commonjs.js b/js/commonjs/rewrite_tests_for_commonjs.js index b6d90d287da71..82eef18ed8ca7 100644 --- a/js/commonjs/rewrite_tests_for_commonjs.js +++ b/js/commonjs/rewrite_tests_for_commonjs.js @@ -80,6 +80,8 @@ lineReader.on('line', function(line) { if (isRequire) { if (module) { // Skip goog.require() lines before the first directive. var fullSym = isRequire[1]; + // Skip lines importing from jspb.*, these are handled by the header above. + if (fullSym.match(/^jspb\./)) return; var sym = tryStripPrefix(fullSym, pkg); console.log("googleProtobuf.exportSymbol('" + fullSym + "', " + module + sym + ', global);'); } diff --git a/js/commonjs/strict_test.js b/js/commonjs/strict_test.js new file mode 100644 index 0000000000000..46458c10b32a5 --- /dev/null +++ b/js/commonjs/strict_test.js @@ -0,0 +1,67 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Test suite is written using Jasmine -- see http://jasmine.github.io/ + + + +var googleProtobuf = require('google-protobuf'); +var asserts = require('closure_asserts_commonjs'); +var global = Function('return this')(); + +// Bring asserts into the global namespace. +googleProtobuf.object.extend(global, asserts); + +var test9_pb = require('./test9_pb'); +var test10_pb = require('./test10_pb'); + +describe('Strict test suite', function() { + it('testImportedMessage', function() { + var simple1 = new test9_pb.jspb.exttest.strict.nine.Simple9() + var simple2 = new test9_pb.jspb.exttest.strict.nine.Simple9() + assertObjectEquals(simple1.toObject(), simple2.toObject()); + }); + + it('testGlobalScopePollution', function() { + assertObjectEquals(global.jspb.exttest, undefined); + }); + + describe('with imports', function() { + it('testImportedMessage', function() { + var simple1 = new test10_pb.jspb.exttest.strict.ten.Simple10() + var simple2 = new test10_pb.jspb.exttest.strict.ten.Simple10() + assertObjectEquals(simple1.toObject(), simple2.toObject()); + }); + + it('testGlobalScopePollution', function() { + assertObjectEquals(global.jspb.exttest, undefined); + }); + }); +}); diff --git a/js/compatibility_tests/v3.0.0/binary/decoder_test.js b/js/compatibility_tests/v3.0.0/binary/decoder_test.js index ac3126484798a..fce2fe181cf11 100644 --- a/js/compatibility_tests/v3.0.0/binary/decoder_test.js +++ b/js/compatibility_tests/v3.0.0/binary/decoder_test.js @@ -228,24 +228,7 @@ describe('binaryDecoderTest', function() { assertThrows(function() {decoder.readSignedVarint64()}); decoder.reset(); assertThrows(function() {decoder.readZigzagVarint64()}); - - // Positive 32-bit varints encoded with 1 bits in positions 33 through 35 - // should trigger assertions. - decoder.setBlock([255, 255, 255, 255, 0x1F]); - assertThrows(function() {decoder.readUnsignedVarint32()}); - - decoder.setBlock([255, 255, 255, 255, 0x2F]); - assertThrows(function() {decoder.readUnsignedVarint32()}); - - decoder.setBlock([255, 255, 255, 255, 0x4F]); - assertThrows(function() {decoder.readUnsignedVarint32()}); - - // Negative 32-bit varints encoded with non-1 bits in the high dword should - // trigger assertions. - decoder.setBlock([255, 255, 255, 255, 255, 255, 0, 255, 255, 1]); - assertThrows(function() {decoder.readUnsignedVarint32()}); - - decoder.setBlock([255, 255, 255, 255, 255, 255, 255, 255, 255, 0]); + decoder.reset(); assertThrows(function() {decoder.readUnsignedVarint32()}); }); diff --git a/js/compatibility_tests/v3.0.0/binary/proto_test.js b/js/compatibility_tests/v3.0.0/binary/proto_test.js index 14d0f42e9549b..1364834570725 100644 --- a/js/compatibility_tests/v3.0.0/binary/proto_test.js +++ b/js/compatibility_tests/v3.0.0/binary/proto_test.js @@ -172,7 +172,7 @@ function fillAllFields(msg) { * @return {boolean} */ function bytesCompare(arr, expected) { - if (goog.isString(arr)) { + if (typeof arr === 'string') { arr = goog.crypt.base64.decodeStringToUint8Array(arr); } if (arr.length != expected.length) { @@ -477,8 +477,8 @@ describe('protoBinaryTest', function() { var msg = new proto.jspb.test.TestAllTypes(); function assertGetters() { - assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[0])); - assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[1])); + assertTrue(typeof msg.getRepeatedBytesList_asB64()[0] === 'string'); + assertTrue(typeof msg.getRepeatedBytesList_asB64()[1] === 'string'); assertTrue(msg.getRepeatedBytesList_asU8()[0] instanceof Uint8Array); assertTrue(msg.getRepeatedBytesList_asU8()[1] instanceof Uint8Array); diff --git a/js/compatibility_tests/v3.0.0/binary/utils_test.js b/js/compatibility_tests/v3.0.0/binary/utils_test.js index d27e5ea2c6305..abc36aac36b45 100644 --- a/js/compatibility_tests/v3.0.0/binary/utils_test.js +++ b/js/compatibility_tests/v3.0.0/binary/utils_test.js @@ -355,7 +355,7 @@ describe('binaryUtilsTest', function() { */ function test(x, opt_bits) { jspb.utils.splitFloat32(x); - if (goog.isDef(opt_bits)) { + if (opt_bits !== undefined) { if (opt_bits != jspb.utils.split64Low) throw 'fail!'; } if (truncate(x) != jspb.utils.joinFloat32(jspb.utils.split64Low, @@ -422,10 +422,10 @@ describe('binaryUtilsTest', function() { */ function test(x, opt_highBits, opt_lowBits) { jspb.utils.splitFloat64(x); - if (goog.isDef(opt_highBits)) { + if (opt_highBits !== undefined) { if (opt_highBits != jspb.utils.split64High) throw 'fail!'; } - if (goog.isDef(opt_lowBits)) { + if (opt_lowBits !== undefined) { if (opt_lowBits != jspb.utils.split64Low) throw 'fail!'; } if (x != jspb.utils.joinFloat64(jspb.utils.split64Low, diff --git a/js/compatibility_tests/v3.0.0/message_test.js b/js/compatibility_tests/v3.0.0/message_test.js index b7791431158a8..79a12e09ccd90 100644 --- a/js/compatibility_tests/v3.0.0/message_test.js +++ b/js/compatibility_tests/v3.0.0/message_test.js @@ -1057,8 +1057,9 @@ describe('Message test suite', function() { it('testFloatingPointFieldsSupportNan', function() { var assertNan = function(x) { - assertTrue('Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.', - goog.isNumber(x) && isNaN(x)); + assertTrue( + 'Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.', + typeof x === 'number' && isNaN(x)); }; var message = new proto.jspb.test.FloatingPointFields([ diff --git a/js/compatibility_tests/v3.0.0/proto3_test.js b/js/compatibility_tests/v3.0.0/proto3_test.js index fab0fd44ffe70..d020a11fc4d6c 100644 --- a/js/compatibility_tests/v3.0.0/proto3_test.js +++ b/js/compatibility_tests/v3.0.0/proto3_test.js @@ -50,7 +50,7 @@ var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES); * @return {boolean} */ function bytesCompare(arr, expected) { - if (goog.isString(arr)) { + if (typeof arr === 'string') { arr = goog.crypt.base64.decodeStringToUint8Array(arr); } if (arr.length != expected.length) { diff --git a/js/compatibility_tests/v3.1.0/binary/decoder_test.js b/js/compatibility_tests/v3.1.0/binary/decoder_test.js index ac3126484798a..71a3725de4076 100644 --- a/js/compatibility_tests/v3.1.0/binary/decoder_test.js +++ b/js/compatibility_tests/v3.1.0/binary/decoder_test.js @@ -139,9 +139,20 @@ function doTestSignedValue(readValue, assertEquals(inputValues[i], readValue.call(decoder)); } - // Encoding values outside the valid range should assert. - assertThrows(function() {writeValue.call(encoder, lowerLimit * 1.1);}); - assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);}); + // Encoding values outside the valid range should assert, except for doubles + // whose range runs all the way to infinity. + var pastLowerLimit = lowerLimit * 1.1; + var pastUpperLimit = upperLimit * 1.1; + if (pastLowerLimit !== -Infinity) { + expect(function() { + writeValue.call(encoder, lowerLimit * 1.1); + }).toThrow(); + } + if (pastUpperLimit !== Infinity) { + expect(function() { + writeValue.call(encoder, upperLimit * 1.1); + }).toThrow(); + } } describe('binaryDecoderTest', function() { @@ -228,24 +239,7 @@ describe('binaryDecoderTest', function() { assertThrows(function() {decoder.readSignedVarint64()}); decoder.reset(); assertThrows(function() {decoder.readZigzagVarint64()}); - - // Positive 32-bit varints encoded with 1 bits in positions 33 through 35 - // should trigger assertions. - decoder.setBlock([255, 255, 255, 255, 0x1F]); - assertThrows(function() {decoder.readUnsignedVarint32()}); - - decoder.setBlock([255, 255, 255, 255, 0x2F]); - assertThrows(function() {decoder.readUnsignedVarint32()}); - - decoder.setBlock([255, 255, 255, 255, 0x4F]); - assertThrows(function() {decoder.readUnsignedVarint32()}); - - // Negative 32-bit varints encoded with non-1 bits in the high dword should - // trigger assertions. - decoder.setBlock([255, 255, 255, 255, 255, 255, 0, 255, 255, 1]); - assertThrows(function() {decoder.readUnsignedVarint32()}); - - decoder.setBlock([255, 255, 255, 255, 255, 255, 255, 255, 255, 0]); + decoder.reset(); assertThrows(function() {decoder.readUnsignedVarint32()}); }); diff --git a/js/compatibility_tests/v3.1.0/binary/proto_test.js b/js/compatibility_tests/v3.1.0/binary/proto_test.js index 26e1d30f1c21d..ff9d97262b9f2 100644 --- a/js/compatibility_tests/v3.1.0/binary/proto_test.js +++ b/js/compatibility_tests/v3.1.0/binary/proto_test.js @@ -172,7 +172,7 @@ function fillAllFields(msg) { * @return {boolean} */ function bytesCompare(arr, expected) { - if (goog.isString(arr)) { + if (typeof arr === 'string') { arr = goog.crypt.base64.decodeStringToUint8Array(arr); } if (arr.length != expected.length) { @@ -477,8 +477,8 @@ describe('protoBinaryTest', function() { var msg = new proto.jspb.test.TestAllTypes(); function assertGetters() { - assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[0])); - assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[1])); + assertTrue(typeof msg.getRepeatedBytesList_asB64()[0] === 'string'); + assertTrue(typeof msg.getRepeatedBytesList_asB64()[1] === 'string'); assertTrue(msg.getRepeatedBytesList_asU8()[0] instanceof Uint8Array); assertTrue(msg.getRepeatedBytesList_asU8()[1] instanceof Uint8Array); diff --git a/js/compatibility_tests/v3.1.0/binary/reader_test.js b/js/compatibility_tests/v3.1.0/binary/reader_test.js index 957113859e5d2..d0062de56e443 100644 --- a/js/compatibility_tests/v3.1.0/binary/reader_test.js +++ b/js/compatibility_tests/v3.1.0/binary/reader_test.js @@ -46,7 +46,7 @@ goog.require('jspb.BinaryConstants'); goog.require('jspb.BinaryDecoder'); goog.require('jspb.BinaryReader'); goog.require('jspb.BinaryWriter'); - +goog.requireType('jspb.BinaryMessage'); describe('binaryReaderTest', function() { @@ -55,7 +55,7 @@ describe('binaryReaderTest', function() { */ it('testInstanceCaches', /** @suppress {visibility} */ function() { var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeMessage(1, dummyMessage, goog.nullFunction); writer.writeMessage(2, dummyMessage, goog.nullFunction); @@ -135,7 +135,7 @@ describe('binaryReaderTest', function() { // Calling readMessage on a non-delimited field should trigger an // assertion. var reader = jspb.BinaryReader.alloc([8, 1]); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); reader.nextField(); assertThrows(function() { reader.readMessage(dummyMessage, goog.nullFunction); @@ -144,47 +144,91 @@ describe('binaryReaderTest', function() { // Reading past the end of the stream should trigger an assertion. reader = jspb.BinaryReader.alloc([9, 1]); reader.nextField(); - assertThrows(function() {reader.readFixed64()}); + assertThrows(function() { + reader.readFixed64() + }); // Reading past the end of a submessage should trigger an assertion. reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]); reader.nextField(); reader.readMessage(dummyMessage, function() { reader.nextField(); - assertThrows(function() {reader.readFixed32()}); + assertThrows(function() { + reader.readFixed32() + }); }); // Skipping an invalid field should trigger an assertion. reader = jspb.BinaryReader.alloc([12, 1]); reader.nextWireType_ = 1000; - assertThrows(function() {reader.skipField()}); + assertThrows(function() { + reader.skipField() + }); // Reading fields with the wrong wire type should assert. reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]); reader.nextField(); - assertThrows(function() {reader.readInt32()}); - assertThrows(function() {reader.readInt32String()}); - assertThrows(function() {reader.readInt64()}); - assertThrows(function() {reader.readInt64String()}); - assertThrows(function() {reader.readUint32()}); - assertThrows(function() {reader.readUint32String()}); - assertThrows(function() {reader.readUint64()}); - assertThrows(function() {reader.readUint64String()}); - assertThrows(function() {reader.readSint32()}); - assertThrows(function() {reader.readBool()}); - assertThrows(function() {reader.readEnum()}); + assertThrows(function() { + reader.readInt32() + }); + assertThrows(function() { + reader.readInt32String() + }); + assertThrows(function() { + reader.readInt64() + }); + assertThrows(function() { + reader.readInt64String() + }); + assertThrows(function() { + reader.readUint32() + }); + assertThrows(function() { + reader.readUint32String() + }); + assertThrows(function() { + reader.readUint64() + }); + assertThrows(function() { + reader.readUint64String() + }); + assertThrows(function() { + reader.readSint32() + }); + assertThrows(function() { + reader.readBool() + }); + assertThrows(function() { + reader.readEnum() + }); reader = jspb.BinaryReader.alloc([8, 1]); reader.nextField(); - assertThrows(function() {reader.readFixed32()}); - assertThrows(function() {reader.readFixed64()}); - assertThrows(function() {reader.readSfixed32()}); - assertThrows(function() {reader.readSfixed64()}); - assertThrows(function() {reader.readFloat()}); - assertThrows(function() {reader.readDouble()}); + assertThrows(function() { + reader.readFixed32() + }); + assertThrows(function() { + reader.readFixed64() + }); + assertThrows(function() { + reader.readSfixed32() + }); + assertThrows(function() { + reader.readSfixed64() + }); + assertThrows(function() { + reader.readFloat() + }); + assertThrows(function() { + reader.readDouble() + }); - assertThrows(function() {reader.readString()}); - assertThrows(function() {reader.readBytes()}); + assertThrows(function() { + reader.readString() + }); + assertThrows(function() { + reader.readBytes() + }); }); @@ -198,8 +242,8 @@ describe('binaryReaderTest', function() { * @private * @suppress {missingProperties} */ - var doTestUnsignedField_ = function(readField, - writeField, epsilon, upperLimit, filter) { + var doTestUnsignedField_ = function( + readField, writeField, epsilon, upperLimit, filter) { assertNotNull(readField); assertNotNull(writeField); @@ -250,8 +294,8 @@ describe('binaryReaderTest', function() { * @private * @suppress {missingProperties} */ - var doTestSignedField_ = function(readField, - writeField, epsilon, lowerLimit, upperLimit, filter) { + var doTestSignedField_ = function( + readField, writeField, epsilon, lowerLimit, upperLimit, filter) { var writer = new jspb.BinaryWriter(); // Encode zero and limits. @@ -267,20 +311,14 @@ describe('binaryReaderTest', function() { for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) { var val = filter(cursor); writeField.call(writer, 6, val); - inputValues.push({ - fieldNumber: 6, - value: val - }); + inputValues.push({fieldNumber: 6, value: val}); } // Encode positive values. for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { var val = filter(cursor); writeField.call(writer, 7, val); - inputValues.push({ - fieldNumber: 7, - value: val - }); + inputValues.push({fieldNumber: 7, value: val}); } var reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); @@ -327,33 +365,34 @@ describe('binaryReaderTest', function() { assertNotUndefined(jspb.BinaryWriter.prototype.writeBool); doTestUnsignedField_( jspb.BinaryReader.prototype.readUint32, - jspb.BinaryWriter.prototype.writeUint32, - 1, Math.pow(2, 32) - 1, Math.round); + jspb.BinaryWriter.prototype.writeUint32, 1, Math.pow(2, 32) - 1, + Math.round); doTestUnsignedField_( jspb.BinaryReader.prototype.readUint64, - jspb.BinaryWriter.prototype.writeUint64, - 1, Math.pow(2, 64) - 1025, Math.round); + jspb.BinaryWriter.prototype.writeUint64, 1, Math.pow(2, 64) - 1025, + Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readInt32, - jspb.BinaryWriter.prototype.writeInt32, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeInt32, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readInt64, - jspb.BinaryWriter.prototype.writeInt64, - 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); + jspb.BinaryWriter.prototype.writeInt64, 1, -Math.pow(2, 63), + Math.pow(2, 63) - 513, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readEnum, - jspb.BinaryWriter.prototype.writeEnum, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeEnum, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestUnsignedField_( jspb.BinaryReader.prototype.readBool, - jspb.BinaryWriter.prototype.writeBool, - 1, 1, function(x) { return !!x; }); + jspb.BinaryWriter.prototype.writeBool, 1, 1, function(x) { + return !!x; + }); }); @@ -387,24 +426,22 @@ describe('binaryReaderTest', function() { // uint32 and sint32 take no more than 5 bytes // 08 - field prefix (type = 0 means varint) doTestHexStringVarint_( - jspb.BinaryReader.prototype.readUint32, - 12, '08 8C 80 80 80 00'); + jspb.BinaryReader.prototype.readUint32, 12, '08 8C 80 80 80 00'); // 11 stands for -6 in zigzag encoding doTestHexStringVarint_( - jspb.BinaryReader.prototype.readSint32, - -6, '08 8B 80 80 80 00'); + jspb.BinaryReader.prototype.readSint32, -6, '08 8B 80 80 80 00'); // uint64 and sint64 take no more than 10 bytes // 08 - field prefix (type = 0 means varint) doTestHexStringVarint_( - jspb.BinaryReader.prototype.readUint64, - 12, '08 8C 80 80 80 80 80 80 80 80 00'); + jspb.BinaryReader.prototype.readUint64, 12, + '08 8C 80 80 80 80 80 80 80 80 00'); // 11 stands for -6 in zigzag encoding doTestHexStringVarint_( - jspb.BinaryReader.prototype.readSint64, - -6, '08 8B 80 80 80 80 80 80 80 80 00'); + jspb.BinaryReader.prototype.readSint64, -6, + '08 8B 80 80 80 80 80 80 80 80 00'); }); @@ -415,27 +452,15 @@ describe('binaryReaderTest', function() { var writer = new jspb.BinaryWriter(); var testSignedData = [ - '2730538252207801776', - '-2688470994844604560', - '3398529779486536359', - '3568577411627971000', - '272477188847484900', - '-6649058714086158188', - '-7695254765712060806', - '-4525541438037104029', - '-4993706538836508568', + '2730538252207801776', '-2688470994844604560', '3398529779486536359', + '3568577411627971000', '272477188847484900', '-6649058714086158188', + '-7695254765712060806', '-4525541438037104029', '-4993706538836508568', '4990160321893729138' ]; var testUnsignedData = [ - '7822732630241694882', - '6753602971916687352', - '2399935075244442116', - '8724292567325338867', - '16948784802625696584', - '4136275908516066934', - '3575388346793700364', - '5167142028379259461', - '1557573948689737699', + '7822732630241694882', '6753602971916687352', '2399935075244442116', + '8724292567325338867', '16948784802625696584', '4136275908516066934', + '3575388346793700364', '5167142028379259461', '1557573948689737699', '17100725280812548567' ]; @@ -463,13 +488,13 @@ describe('binaryReaderTest', function() { it('testZigzagFields', function() { doTestSignedField_( jspb.BinaryReader.prototype.readSint32, - jspb.BinaryWriter.prototype.writeSint32, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeSint32, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readSint64, - jspb.BinaryWriter.prototype.writeSint64, - 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); + jspb.BinaryWriter.prototype.writeSint64, 1, -Math.pow(2, 63), + Math.pow(2, 63) - 513, Math.round); }); @@ -479,23 +504,23 @@ describe('binaryReaderTest', function() { it('testFixedFields', function() { doTestUnsignedField_( jspb.BinaryReader.prototype.readFixed32, - jspb.BinaryWriter.prototype.writeFixed32, - 1, Math.pow(2, 32) - 1, Math.round); + jspb.BinaryWriter.prototype.writeFixed32, 1, Math.pow(2, 32) - 1, + Math.round); doTestUnsignedField_( jspb.BinaryReader.prototype.readFixed64, - jspb.BinaryWriter.prototype.writeFixed64, - 1, Math.pow(2, 64) - 1025, Math.round); + jspb.BinaryWriter.prototype.writeFixed64, 1, Math.pow(2, 64) - 1025, + Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readSfixed32, - jspb.BinaryWriter.prototype.writeSfixed32, - 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + jspb.BinaryWriter.prototype.writeSfixed32, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); doTestSignedField_( jspb.BinaryReader.prototype.readSfixed64, - jspb.BinaryWriter.prototype.writeSfixed64, - 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); + jspb.BinaryWriter.prototype.writeSfixed64, 1, -Math.pow(2, 63), + Math.pow(2, 63) - 513, Math.round); }); @@ -506,18 +531,17 @@ describe('binaryReaderTest', function() { doTestSignedField_( jspb.BinaryReader.prototype.readFloat, jspb.BinaryWriter.prototype.writeFloat, - jspb.BinaryConstants.FLOAT32_MIN, - -jspb.BinaryConstants.FLOAT32_MAX, - jspb.BinaryConstants.FLOAT32_MAX, - truncate); + jspb.BinaryConstants.FLOAT32_MIN, -jspb.BinaryConstants.FLOAT32_MAX, + jspb.BinaryConstants.FLOAT32_MAX, truncate); doTestSignedField_( jspb.BinaryReader.prototype.readDouble, jspb.BinaryWriter.prototype.writeDouble, jspb.BinaryConstants.FLOAT64_EPS * 10, - -jspb.BinaryConstants.FLOAT64_MIN, - jspb.BinaryConstants.FLOAT64_MIN, - function(x) { return x; }); + -jspb.BinaryConstants.FLOAT64_MIN, jspb.BinaryConstants.FLOAT64_MIN, + function(x) { + return x; + }); }); @@ -584,7 +608,7 @@ describe('binaryReaderTest', function() { */ it('testNesting', function() { var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeInt32(1, 100); @@ -677,7 +701,7 @@ describe('binaryReaderTest', function() { // Write a group with a nested group inside. writer.writeInt32(5, sentinel); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeGroup(5, dummyMessage, function() { writer.writeInt64(42, 42); writer.writeGroup(6, dummyMessage, function() { @@ -830,7 +854,7 @@ describe('binaryReaderTest', function() { var fieldTag = (1 << 3) | jspb.BinaryConstants.WireType.DELIMITED; var blob = [1, 2, 3, 4, 5]; var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); writer.writeMessage(1, dummyMessage, function() { writer.writeMessage(1, dummyMessage, function() { @@ -863,7 +887,7 @@ describe('binaryReaderTest', function() { */ it('testReadCallbacks', function() { var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); // Add an int, a submessage, and another int. writer.writeInt32(1, 100); diff --git a/js/compatibility_tests/v3.1.0/binary/utils_test.js b/js/compatibility_tests/v3.1.0/binary/utils_test.js index d27e5ea2c6305..abc36aac36b45 100644 --- a/js/compatibility_tests/v3.1.0/binary/utils_test.js +++ b/js/compatibility_tests/v3.1.0/binary/utils_test.js @@ -355,7 +355,7 @@ describe('binaryUtilsTest', function() { */ function test(x, opt_bits) { jspb.utils.splitFloat32(x); - if (goog.isDef(opt_bits)) { + if (opt_bits !== undefined) { if (opt_bits != jspb.utils.split64Low) throw 'fail!'; } if (truncate(x) != jspb.utils.joinFloat32(jspb.utils.split64Low, @@ -422,10 +422,10 @@ describe('binaryUtilsTest', function() { */ function test(x, opt_highBits, opt_lowBits) { jspb.utils.splitFloat64(x); - if (goog.isDef(opt_highBits)) { + if (opt_highBits !== undefined) { if (opt_highBits != jspb.utils.split64High) throw 'fail!'; } - if (goog.isDef(opt_lowBits)) { + if (opt_lowBits !== undefined) { if (opt_lowBits != jspb.utils.split64Low) throw 'fail!'; } if (x != jspb.utils.joinFloat64(jspb.utils.split64Low, diff --git a/js/compatibility_tests/v3.1.0/binary/writer_test.js b/js/compatibility_tests/v3.1.0/binary/writer_test.js index d5dadb413549b..55bc6bedc1350 100644 --- a/js/compatibility_tests/v3.1.0/binary/writer_test.js +++ b/js/compatibility_tests/v3.1.0/binary/writer_test.js @@ -41,14 +41,14 @@ goog.require('goog.crypt'); goog.require('goog.testing.asserts'); goog.require('jspb.BinaryWriter'); - +goog.requireType('jspb.BinaryMessage'); /** * @param {function()} func This function should throw an error when run. */ function assertFails(func) { var e = assertThrows(func); - //assertNotNull(e.toString().match(/Error/)); + // assertNotNull(e.toString().match(/Error/)); } @@ -59,7 +59,7 @@ describe('binaryWriterTest', function() { it('testWriteErrors', function() { // Submessages with invalid field indices should assert. var writer = new jspb.BinaryWriter(); - var dummyMessage = /** @type {!jspb.BinaryMessage} */({}); + var dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); assertFails(function() { writer.writeMessage(-1, dummyMessage, goog.nullFunction); @@ -67,40 +67,82 @@ describe('binaryWriterTest', function() { // Writing invalid field indices should assert. writer = new jspb.BinaryWriter(); - assertFails(function() {writer.writeUint64(-1, 1);}); + assertFails(function() { + writer.writeUint64(-1, 1); + }); // Writing out-of-range field values should assert. writer = new jspb.BinaryWriter(); - assertFails(function() {writer.writeInt32(1, -Infinity);}); - assertFails(function() {writer.writeInt32(1, Infinity);}); + assertFails(function() { + writer.writeInt32(1, -Infinity); + }); + assertFails(function() { + writer.writeInt32(1, Infinity); + }); - assertFails(function() {writer.writeInt64(1, -Infinity);}); - assertFails(function() {writer.writeInt64(1, Infinity);}); + assertFails(function() { + writer.writeInt64(1, -Infinity); + }); + assertFails(function() { + writer.writeInt64(1, Infinity); + }); - assertFails(function() {writer.writeUint32(1, -1);}); - assertFails(function() {writer.writeUint32(1, Infinity);}); + assertFails(function() { + writer.writeUint32(1, -1); + }); + assertFails(function() { + writer.writeUint32(1, Infinity); + }); - assertFails(function() {writer.writeUint64(1, -1);}); - assertFails(function() {writer.writeUint64(1, Infinity);}); + assertFails(function() { + writer.writeUint64(1, -1); + }); + assertFails(function() { + writer.writeUint64(1, Infinity); + }); - assertFails(function() {writer.writeSint32(1, -Infinity);}); - assertFails(function() {writer.writeSint32(1, Infinity);}); + assertFails(function() { + writer.writeSint32(1, -Infinity); + }); + assertFails(function() { + writer.writeSint32(1, Infinity); + }); - assertFails(function() {writer.writeSint64(1, -Infinity);}); - assertFails(function() {writer.writeSint64(1, Infinity);}); + assertFails(function() { + writer.writeSint64(1, -Infinity); + }); + assertFails(function() { + writer.writeSint64(1, Infinity); + }); - assertFails(function() {writer.writeFixed32(1, -1);}); - assertFails(function() {writer.writeFixed32(1, Infinity);}); + assertFails(function() { + writer.writeFixed32(1, -1); + }); + assertFails(function() { + writer.writeFixed32(1, Infinity); + }); - assertFails(function() {writer.writeFixed64(1, -1);}); - assertFails(function() {writer.writeFixed64(1, Infinity);}); + assertFails(function() { + writer.writeFixed64(1, -1); + }); + assertFails(function() { + writer.writeFixed64(1, Infinity); + }); - assertFails(function() {writer.writeSfixed32(1, -Infinity);}); - assertFails(function() {writer.writeSfixed32(1, Infinity);}); + assertFails(function() { + writer.writeSfixed32(1, -Infinity); + }); + assertFails(function() { + writer.writeSfixed32(1, Infinity); + }); - assertFails(function() {writer.writeSfixed64(1, -Infinity);}); - assertFails(function() {writer.writeSfixed64(1, Infinity);}); + assertFails(function() { + writer.writeSfixed64(1, -Infinity); + }); + assertFails(function() { + writer.writeSfixed64(1, Infinity); + }); }); diff --git a/js/compatibility_tests/v3.1.0/maps_test.js b/js/compatibility_tests/v3.1.0/maps_test.js index 0d442f4fd1011..452dfe59d54ba 100644 --- a/js/compatibility_tests/v3.1.0/maps_test.js +++ b/js/compatibility_tests/v3.1.0/maps_test.js @@ -40,6 +40,8 @@ goog.require('proto.jspb.test.TestMapFields'); goog.require('proto.jspb.test.MapValueMessageNoBinary'); goog.require('proto.jspb.test.TestMapFieldsNoBinary'); +goog.requireType('jspb.Map'); + /** * Helper: check that the given map has exactly this set of (sorted) entries. * @param {!jspb.Map} map @@ -98,7 +100,9 @@ function makeTests(msgInfo, submessageCtor, suffix) { msg.getMapStringMsgMap().get('k').setFoo(42); msg.getMapStringMsgMap().get('l').setFoo(84); msg.getMapInt32StringMap().set(-1, 'a').set(42, 'b'); - msg.getMapInt64StringMap().set(0x123456789abc, 'c').set(0xcba987654321, 'd'); + msg.getMapInt64StringMap() + .set(0x123456789abc, 'c') + .set(0xcba987654321, 'd'); msg.getMapBoolStringMap().set(false, 'e').set(true, 'f'); }; @@ -107,42 +111,24 @@ function makeTests(msgInfo, submessageCtor, suffix) { * @param {?} msg */ var checkMapFields = function(msg) { - checkMapEquals(msg.getMapStringStringMap(), [ - ['asdf', 'jkl;'], - ['key 2', 'hello world'] - ]); - checkMapEquals(msg.getMapStringInt32Map(), [ - ['a', 1], - ['b', -2] - ]); - checkMapEquals(msg.getMapStringInt64Map(), [ - ['c', 0x100000000], - ['d', 0x200000000] - ]); - checkMapEquals(msg.getMapStringBoolMap(), [ - ['e', true], - ['f', false] - ]); - checkMapEquals(msg.getMapStringDoubleMap(), [ - ['g', 3.14159], - ['h', 2.71828] - ]); + checkMapEquals( + msg.getMapStringStringMap(), + [['asdf', 'jkl;'], ['key 2', 'hello world']]); + checkMapEquals(msg.getMapStringInt32Map(), [['a', 1], ['b', -2]]); + checkMapEquals( + msg.getMapStringInt64Map(), [['c', 0x100000000], ['d', 0x200000000]]); + checkMapEquals(msg.getMapStringBoolMap(), [['e', true], ['f', false]]); + checkMapEquals( + msg.getMapStringDoubleMap(), [['g', 3.14159], ['h', 2.71828]]); checkMapEquals(msg.getMapStringEnumMap(), [ - ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR], - ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ] - ]); - checkMapEquals(msg.getMapInt32StringMap(), [ - [-1, 'a'], - [42, 'b'] - ]); - checkMapEquals(msg.getMapInt64StringMap(), [ - [0x123456789abc, 'c'], - [0xcba987654321, 'd'] - ]); - checkMapEquals(msg.getMapBoolStringMap(), [ - [false, 'e'], - [true, 'f'] + ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR], + ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ] ]); + checkMapEquals(msg.getMapInt32StringMap(), [[-1, 'a'], [42, 'b']]); + checkMapEquals( + msg.getMapInt64StringMap(), + [[0x123456789abc, 'c'], [0xcba987654321, 'd']]); + checkMapEquals(msg.getMapBoolStringMap(), [[false, 'e'], [true, 'f']]); assertEquals(msg.getMapStringMsgMap().getLength(), 2); assertEquals(msg.getMapStringMsgMap().get('k').getFoo(), 42); @@ -187,10 +173,7 @@ function makeTests(msgInfo, submessageCtor, suffix) { assertElementsEquals(it.next().value, ['asdf', 'hello world']); assertElementsEquals(it.next().value, ['jkl;', 'key 2']); assertEquals(it.next().done, true); - checkMapEquals(m, [ - ['asdf', 'hello world'], - ['jkl;', 'key 2'] - ]); + checkMapEquals(m, [['asdf', 'hello world'], ['jkl;', 'key 2']]); m.del('jkl;'); assertEquals(m.has('jkl;'), false); assertEquals(m.get('jkl;'), undefined); @@ -242,11 +225,11 @@ function makeTests(msgInfo, submessageCtor, suffix) { msg.getMapStringStringMap().set('A', 'a'); var serialized = msg.serializeBinary(); var expectedSerialized = [ - 0x0a, 0x6, // field 1 (map_string_string), delimited, length 6 - 0x0a, 0x1, // field 1 in submessage (key), delimited, length 1 - 0x41, // ASCII 'A' - 0x12, 0x1, // field 2 in submessage (value), delimited, length 1 - 0x61 // ASCII 'a' + 0x0a, 0x6, // field 1 (map_string_string), delimited, length 6 + 0x0a, 0x1, // field 1 in submessage (key), delimited, length 1 + 0x41, // ASCII 'A' + 0x12, 0x1, // field 2 in submessage (value), delimited, length 1 + 0x61 // ASCII 'a' ]; assertEquals(serialized.length, expectedSerialized.length); for (var i = 0; i < serialized.length; i++) { @@ -267,11 +250,7 @@ function makeTests(msgInfo, submessageCtor, suffix) { */ it('testLazyMapSync' + suffix, function() { // Start with a JSPB array containing a few map entries. - var entries = [ - ['a', 'entry 1'], - ['c', 'entry 2'], - ['b', 'entry 3'] - ]; + var entries = [['a', 'entry 1'], ['c', 'entry 2'], ['b', 'entry 3']]; var msg = new msgInfo.constructor([entries]); assertEquals(entries.length, 3); assertEquals(entries[0][0], 'a'); @@ -279,9 +258,9 @@ function makeTests(msgInfo, submessageCtor, suffix) { assertEquals(entries[2][0], 'b'); msg.getMapStringStringMap().del('a'); assertEquals(entries.length, 3); // not yet sync'd - msg.toArray(); // force a sync + msg.toArray(); // force a sync assertEquals(entries.length, 2); - assertEquals(entries[0][0], 'b'); // now in sorted order + assertEquals(entries[0][0], 'b'); // now in sorted order assertEquals(entries[1][0], 'c'); var a = msg.toArray(); @@ -290,12 +269,16 @@ function makeTests(msgInfo, submessageCtor, suffix) { } describe('mapsTest', function() { - makeTests({ - constructor: proto.jspb.test.TestMapFields, - deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary - }, proto.jspb.test.MapValueMessage, "_Binary"); - makeTests({ - constructor: proto.jspb.test.TestMapFieldsNoBinary, - deserializeBinary: null - }, proto.jspb.test.MapValueMessageNoBinary, "_NoBinary"); + makeTests( + { + constructor: proto.jspb.test.TestMapFields, + deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary + }, + proto.jspb.test.MapValueMessage, '_Binary'); + makeTests( + { + constructor: proto.jspb.test.TestMapFieldsNoBinary, + deserializeBinary: null + }, + proto.jspb.test.MapValueMessageNoBinary, '_NoBinary'); }); diff --git a/js/compatibility_tests/v3.1.0/message_test.js b/js/compatibility_tests/v3.1.0/message_test.js index b46e50d3762f8..9830a02dfee68 100644 --- a/js/compatibility_tests/v3.1.0/message_test.js +++ b/js/compatibility_tests/v3.1.0/message_test.js @@ -67,7 +67,6 @@ goog.require('proto.jspb.test.Simple1'); goog.require('proto.jspb.test.Simple2'); goog.require('proto.jspb.test.SpecialCases'); goog.require('proto.jspb.test.TestClone'); -goog.require('proto.jspb.test.TestEndsWithBytes'); goog.require('proto.jspb.test.TestGroup'); goog.require('proto.jspb.test.TestGroup1'); goog.require('proto.jspb.test.TestMessageWithOneof'); @@ -77,7 +76,7 @@ goog.require('proto.jspb.test.TestReservedNamesExtension'); // CommonJS-LoadFromFile: test2_pb proto.jspb.test goog.require('proto.jspb.test.ExtensionMessage'); goog.require('proto.jspb.test.TestExtensionsMessage'); - +goog.require('proto.jspb.test.simple1'); @@ -102,59 +101,59 @@ describe('Message test suite', function() { }); it('testComplexConversion', function() { - var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1]; - var data2 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1]; + var data1 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , true]; + var data2 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , true]; var foo = new proto.jspb.test.Complex(data1); var bar = new proto.jspb.test.Complex(data2); var result = foo.toObject(); - assertObjectEquals({ - aString: 'a', - anOutOfOrderBool: 1, - aNestedMessage: { - anInt: 11 - }, - aRepeatedMessageList: [{anInt: 22}, {anInt: 33}], - aRepeatedStringList: ['s1', 's2'] - }, result); + assertObjectEquals( + { + aString: 'a', + anOutOfOrderBool: true, + aNestedMessage: {anInt: 11}, + aRepeatedMessageList: [{anInt: 22}, {anInt: 33}], + aRepeatedStringList: ['s1', 's2'] + }, + result); // Now test with the jspb instances included. result = foo.toObject(true /* opt_includeInstance */); - assertObjectEquals({ - aString: 'a', - anOutOfOrderBool: 1, - aNestedMessage: { - anInt: 11, - $jspbMessageInstance: foo.getANestedMessage() - }, - aRepeatedMessageList: [ - {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]}, - {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]} - ], - aRepeatedStringList: ['s1', 's2'], - $jspbMessageInstance: foo - }, result); - + assertObjectEquals( + { + aString: 'a', + anOutOfOrderBool: true, + aNestedMessage: + {anInt: 11, $jspbMessageInstance: foo.getANestedMessage()}, + aRepeatedMessageList: [ + {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]}, + {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]} + ], + aRepeatedStringList: ['s1', 's2'], + $jspbMessageInstance: foo + }, + result); }); it('testMissingFields', function() { var foo = new proto.jspb.test.Complex([ - undefined, undefined, undefined, [], - undefined, undefined, undefined, undefined]); + undefined, undefined, undefined, [], undefined, undefined, undefined, + undefined + ]); var bar = new proto.jspb.test.Complex([ - undefined, undefined, undefined, [], - undefined, undefined, undefined, undefined]); + undefined, undefined, undefined, [], undefined, undefined, undefined, + undefined + ]); var result = foo.toObject(); - assertObjectEquals({ - aString: undefined, - anOutOfOrderBool: undefined, - aNestedMessage: { - anInt: undefined - }, - // Note: JsPb converts undefined repeated fields to empty arrays. - aRepeatedMessageList: [], - aRepeatedStringList: [] - }, result); - + assertObjectEquals( + { + aString: undefined, + anOutOfOrderBool: undefined, + aNestedMessage: {anInt: undefined}, + // Note: JsPb converts undefined repeated fields to empty arrays. + aRepeatedMessageList: [], + aRepeatedStringList: [] + }, + result); }); it('testNestedComplexMessage', function() { @@ -167,20 +166,21 @@ describe('Message test suite', function() { it('testSpecialCases', function() { // Note: Some property names are reserved in JavaScript. // These names are converted to the Js property named pb_. - var special = - new proto.jspb.test.SpecialCases(['normal', 'default', 'function', - 'var']); + var special = new proto.jspb.test.SpecialCases( + ['normal', 'default', 'function', 'var']); var result = special.toObject(); - assertObjectEquals({ - normal: 'normal', - pb_default: 'default', - pb_function: 'function', - pb_var: 'var' - }, result); + assertObjectEquals( + { + normal: 'normal', + pb_default: 'default', + pb_function: 'function', + pb_var: 'var' + }, + result); }); it('testDefaultValues', function() { - var defaultString = "default<>\'\"abc"; + var defaultString = 'default<>\'"abc'; var response = new proto.jspb.test.DefaultValues(); // Test toObject @@ -244,8 +244,10 @@ describe('Message test suite', function() { // Test that clearing the values reverts them to the default state. response = makeDefault(['blah', false, 111, 77]); - response.clearStringField(); response.clearBoolField(); - response.clearIntField(); response.clearEnumField(); + response.clearStringField(); + response.clearBoolField(); + response.clearIntField(); + response.clearEnumField(); assertEquals(defaultString, response.getStringField()); assertEquals(true, response.getBoolField()); assertEquals(11, response.getIntField()); @@ -257,8 +259,10 @@ describe('Message test suite', function() { // Test that setFoo(null) clears the values. response = makeDefault(['blah', false, 111, 77]); - response.setStringField(null); response.setBoolField(null); - response.setIntField(undefined); response.setEnumField(undefined); + response.setStringField(null); + response.setBoolField(null); + response.setIntField(undefined); + response.setEnumField(undefined); assertEquals(defaultString, response.getStringField()); assertEquals(true, response.getBoolField()); assertEquals(11, response.getIntField()); @@ -288,15 +292,15 @@ describe('Message test suite', function() { // but we actually get a sparse array instead. We could use something // like [1,undefined,2] to avoid this, except that this is still // sparse on IE. No comment... - var expected = [,,, [], []]; + var expected = [, , , [], []]; expected[0] = expected[1] = expected[2] = undefined; assertObjectEquals(expected, foo.toArray()); }); it('testDifferenceRawObject', /** @suppress {visibility} */ function() { var p1 = new proto.jspb.test.HasExtensions(['hi', 'diff', {}]); - var p2 = new proto.jspb.test.HasExtensions(['hi', 'what', - {1000: 'unique'}]); + var p2 = + new proto.jspb.test.HasExtensions(['hi', 'what', {1000: 'unique'}]); var diff = /** @type {proto.jspb.test.HasExtensions} */ (jspb.Message.difference(p1, p2)); assertEquals('', diff.getStr1()); @@ -310,13 +314,13 @@ describe('Message test suite', function() { assertTrue(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi']))); assertFalse(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['bye']))); var s1b = new proto.jspb.test.Simple1(['hi', ['hello']]); - assertTrue(jspb.Message.equals(s1b, - new proto.jspb.test.Simple1(['hi', ['hello']]))); - assertTrue(jspb.Message.equals(s1b, - new proto.jspb.test.Simple1(['hi', ['hello', undefined, - undefined, undefined]]))); - assertFalse(jspb.Message.equals(s1b, - new proto.jspb.test.Simple1(['no', ['hello']]))); + assertTrue(jspb.Message.equals( + s1b, new proto.jspb.test.Simple1(['hi', ['hello']]))); + assertTrue(jspb.Message.equals(s1b, new proto.jspb.test.Simple1([ + 'hi', ['hello', undefined, undefined, undefined] + ]))); + assertFalse(jspb.Message.equals( + s1b, new proto.jspb.test.Simple1(['no', ['hello']]))); // Test with messages of different types var s2 = new proto.jspb.test.Simple2(['hi']); assertFalse(jspb.Message.equals(s1, s2)); @@ -324,18 +328,18 @@ describe('Message test suite', function() { it('testEquals_softComparison', function() { var s1 = new proto.jspb.test.Simple1(['hi', [], null]); - assertTrue(jspb.Message.equals(s1, - new proto.jspb.test.Simple1(['hi', []]))); + assertTrue( + jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi', []]))); var s1b = new proto.jspb.test.Simple1(['hi', [], true]); - assertTrue(jspb.Message.equals(s1b, - new proto.jspb.test.Simple1(['hi', [], 1]))); + assertTrue( + jspb.Message.equals(s1b, new proto.jspb.test.Simple1(['hi', [], 1]))); }); it('testEqualsComplex', function() { - var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1]; - var data2 = ['a',,, [, 11], [[, 22], [, 34]],, ['s1', 's2'],, 1]; - var data3 = ['a',,, [, 11], [[, 22]],, ['s1', 's2'],, 1]; + var data1 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , 1]; + var data2 = ['a', , , [, 11], [[, 22], [, 34]], , ['s1', 's2'], , 1]; + var data3 = ['a', , , [, 11], [[, 22]], , ['s1', 's2'], , 1]; var data4 = ['hi']; var c1a = new proto.jspb.test.Complex(data1); var c1b = new proto.jspb.test.Complex(data1); @@ -352,42 +356,34 @@ describe('Message test suite', function() { it('testEqualsExtensionsConstructed', function() { assertTrue(jspb.Message.equals( new proto.jspb.test.HasExtensions([]), - new proto.jspb.test.HasExtensions([{}]) - )); + new proto.jspb.test.HasExtensions([{}]))); assertTrue(jspb.Message.equals( new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]), - new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]) - )); + new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]))); assertFalse(jspb.Message.equals( new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]), - new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'b'}]}]) - )); + new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'b'}]}]))); assertTrue(jspb.Message.equals( new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]), - new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]) - )); + new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]))); assertTrue(jspb.Message.equals( new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]), - new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}]) - )); + new proto.jspb.test.HasExtensions([, , , {100: [{200: 'a'}]}]))); assertTrue(jspb.Message.equals( - new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}]), - new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]) - )); + new proto.jspb.test.HasExtensions([, , , {100: [{200: 'a'}]}]), + new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]))); assertTrue(jspb.Message.equals( new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]), - new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}]) - )); + new proto.jspb.test.HasExtensions(['hi', , , {100: [{200: 'a'}]}]))); assertTrue(jspb.Message.equals( - new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}]), - new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]) - )); + new proto.jspb.test.HasExtensions(['hi', , , {100: [{200: 'a'}]}]), + new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]))); }); it('testEqualsExtensionsUnconstructed', function() { assertTrue(jspb.Message.compareFields([], [{}])); - assertTrue(jspb.Message.compareFields([,,, {}], [])); - assertTrue(jspb.Message.compareFields([,,, {}], [,, {}])); + assertTrue(jspb.Message.compareFields([, , , {}], [])); + assertTrue(jspb.Message.compareFields([, , , {}], [, , {}])); assertTrue(jspb.Message.compareFields( ['hi', {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}])); assertFalse(jspb.Message.compareFields( @@ -395,25 +391,25 @@ describe('Message test suite', function() { assertTrue(jspb.Message.compareFields( [{100: [{200: 'a'}]}], [{100: [{200: 'a'}]}])); assertTrue(jspb.Message.compareFields( - [{100: [{200: 'a'}]}], [,,, {100: [{200: 'a'}]}])); + [{100: [{200: 'a'}]}], [, , , {100: [{200: 'a'}]}])); assertTrue(jspb.Message.compareFields( - [,,, {100: [{200: 'a'}]}], [{100: [{200: 'a'}]}])); + [, , , {100: [{200: 'a'}]}], [{100: [{200: 'a'}]}])); assertTrue(jspb.Message.compareFields( - ['hi', {100: [{200: 'a'}]}], ['hi',,, {100: [{200: 'a'}]}])); + ['hi', {100: [{200: 'a'}]}], ['hi', , , {100: [{200: 'a'}]}])); assertTrue(jspb.Message.compareFields( - ['hi',,, {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}])); + ['hi', , , {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}])); }); it('testToMap', function() { var p1 = new proto.jspb.test.Simple1(['k', ['v']]); var p2 = new proto.jspb.test.Simple1(['k1', ['v1', 'v2']]); - var soymap = jspb.Message.toMap([p1, p2], - proto.jspb.test.Simple1.prototype.getAString, + var soymap = jspb.Message.toMap( + [p1, p2], proto.jspb.test.Simple1.prototype.getAString, proto.jspb.test.Simple1.prototype.toObject); assertEquals('k', soymap['k'].aString); assertArrayEquals(['v'], soymap['k'].aRepeatedStringList); - var protomap = jspb.Message.toMap([p1, p2], - proto.jspb.test.Simple1.prototype.getAString); + var protomap = jspb.Message.toMap( + [p1, p2], proto.jspb.test.Simple1.prototype.getAString); assertEquals('k', protomap['k'].getAString()); assertArrayEquals(['v'], protomap['k'].getARepeatedStringList()); }); @@ -434,8 +430,12 @@ describe('Message test suite', function() { extension.setExt('e1'); original.setExtension(proto.jspb.test.IsExtension.extField, extension); var clone = original.clone(); - assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],, - [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }], + assertArrayEquals( + [ + 'v1', , ['x1', ['y1', 'z1']], , + [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1, , + {100: [, 'e1']} + ], clone.toArray()); clone.setStr('v2'); var simple4 = new proto.jspb.test.Simple1(['a1', ['b1', 'c1']]); @@ -452,11 +452,19 @@ describe('Message test suite', function() { var newExtension = new proto.jspb.test.CloneExtension(); newExtension.setExt('e2'); clone.setExtension(proto.jspb.test.CloneExtension.extField, newExtension); - assertArrayEquals(['v2',, ['a1', ['b1', 'c1']],, - [['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2,, { 100: [, 'e2'] }], + assertArrayEquals( + [ + 'v2', , ['a1', ['b1', 'c1']], , + [['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2, , + {100: [, 'e2']} + ], clone.toArray()); - assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],, - [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }], + assertArrayEquals( + [ + 'v1', , ['x1', ['y1', 'z1']], , + [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1, , + {100: [, 'e1']} + ], original.toArray()); }); @@ -488,11 +496,12 @@ describe('Message test suite', function() { jspb.Message.copyInto(original, dest); assertArrayEquals(original.toArray(), dest.toArray()); assertEquals('x1', dest.getSimple1().getAString()); - assertEquals('e1', + assertEquals( + 'e1', dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt()); dest.getSimple1().setAString('new value'); - assertNotEquals(dest.getSimple1().getAString(), - original.getSimple1().getAString()); + assertNotEquals( + dest.getSimple1().getAString(), original.getSimple1().getAString()); if (supportsUint8Array) { dest.getBytesField()[0] = 7; assertObjectEquals(bytes1, original.getBytesField()); @@ -502,12 +511,12 @@ describe('Message test suite', function() { assertObjectEquals(bytes1, original.getBytesField()); assertObjectEquals('789', dest.getBytesField()); } - dest.getExtension(proto.jspb.test.CloneExtension.extField). - setExt('new value'); + dest.getExtension(proto.jspb.test.CloneExtension.extField) + .setExt('new value'); assertNotEquals( dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt(), - original.getExtension( - proto.jspb.test.CloneExtension.extField).getExt()); + original.getExtension(proto.jspb.test.CloneExtension.extField) + .getExt()); }); it('testCopyInto_notSameType', function() { @@ -525,26 +534,32 @@ describe('Message test suite', function() { var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2']]); var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1); - extendable.setExtension(proto.jspb.test.IndirectExtension.simple, - extension2); + extendable.setExtension( + proto.jspb.test.IndirectExtension.simple, extension2); extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy'); - extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList, - ['a', 'b']); + extendable.setExtension( + proto.jspb.test.IndirectExtension.repeatedStrList, ['a', 'b']); var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]); var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2']]); extendable.setExtension( - proto.jspb.test.IndirectExtension.repeatedSimpleList, - [s1, s2]); - assertObjectEquals(extension1, + proto.jspb.test.IndirectExtension.repeatedSimpleList, [s1, s2]); + assertObjectEquals( + extension1, extendable.getExtension(proto.jspb.test.IsExtension.extField)); - assertObjectEquals(extension2, + assertObjectEquals( + extension2, extendable.getExtension(proto.jspb.test.IndirectExtension.simple)); - assertObjectEquals('xyzzy', + assertObjectEquals( + 'xyzzy', extendable.getExtension(proto.jspb.test.IndirectExtension.str)); - assertObjectEquals(['a', 'b'], extendable.getExtension( - proto.jspb.test.IndirectExtension.repeatedStrList)); - assertObjectEquals([s1, s2], extendable.getExtension( - proto.jspb.test.IndirectExtension.repeatedSimpleList)); + assertObjectEquals( + ['a', 'b'], + extendable.getExtension( + proto.jspb.test.IndirectExtension.repeatedStrList)); + assertObjectEquals( + [s1, s2], + extendable.getExtension( + proto.jspb.test.IndirectExtension.repeatedSimpleList)); // Not supported yet, but it should work... extendable.setExtension(proto.jspb.test.IndirectExtension.simple, null); assertNull( @@ -563,18 +578,18 @@ describe('Message test suite', function() { var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); var extension = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]); extendable.setExtension(proto.jspb.test.simple1, extension); - assertObjectEquals(extension, - extendable.getExtension(proto.jspb.test.simple1)); + assertObjectEquals( + extension, extendable.getExtension(proto.jspb.test.simple1)); // From _lib mode. extension = new proto.jspb.test.ExtensionMessage(['s1']); extendable = new proto.jspb.test.TestExtensionsMessage([16]); extendable.setExtension(proto.jspb.test.floatingMsgField, extension); extendable.setExtension(proto.jspb.test.floatingStrField, 's2'); - assertObjectEquals(extension, - extendable.getExtension(proto.jspb.test.floatingMsgField)); - assertObjectEquals('s2', - extendable.getExtension(proto.jspb.test.floatingStrField)); + assertObjectEquals( + extension, extendable.getExtension(proto.jspb.test.floatingMsgField)); + assertObjectEquals( + 's2', extendable.getExtension(proto.jspb.test.floatingStrField)); assertNotUndefined(proto.jspb.exttest.floatingMsgField); assertNotUndefined(proto.jspb.exttest.floatingMsgFieldTwo); assertNotUndefined(proto.jspb.exttest.beta.floatingStrField); @@ -585,70 +600,77 @@ describe('Message test suite', function() { var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2'], true]); var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1); - extendable.setExtension(proto.jspb.test.IndirectExtension.simple, - extension2); + extendable.setExtension( + proto.jspb.test.IndirectExtension.simple, extension2); extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy'); - extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList, - ['a', 'b']); + extendable.setExtension( + proto.jspb.test.IndirectExtension.repeatedStrList, ['a', 'b']); var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2'], true]); var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2'], false]); extendable.setExtension( - proto.jspb.test.IndirectExtension.repeatedSimpleList, - [s1, s2]); - assertObjectEquals({ - str1: 'v1', str2: 'v2', str3: 'v3', - extField: { ext1: 'ext1field' }, - simple: { - aString: 'str', aRepeatedStringList: ['s1', 's2'], aBoolean: true - }, - str: 'xyzzy', - repeatedStrList: ['a', 'b'], - repeatedSimpleList: [ - { aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true}, - { aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false} - ] - }, extendable.toObject()); + proto.jspb.test.IndirectExtension.repeatedSimpleList, [s1, s2]); + assertObjectEquals( + { + str1: 'v1', + str2: 'v2', + str3: 'v3', + extField: {ext1: 'ext1field'}, + simple: { + aString: 'str', + aRepeatedStringList: ['s1', 's2'], + aBoolean: true + }, + str: 'xyzzy', + repeatedStrList: ['a', 'b'], + repeatedSimpleList: [ + {aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true}, + {aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false} + ] + }, + extendable.toObject()); // Now, with instances included. - assertObjectEquals({ - str1: 'v1', str2: 'v2', str3: 'v3', - extField: { - ext1: 'ext1field', - $jspbMessageInstance: - extendable.getExtension(proto.jspb.test.IsExtension.extField) - }, - simple: { - aString: 'str', - aRepeatedStringList: ['s1', 's2'], - aBoolean: true, - $jspbMessageInstance: - extendable.getExtension(proto.jspb.test.IndirectExtension.simple) - }, - str: 'xyzzy', - repeatedStrList: ['a', 'b'], - repeatedSimpleList: [{ - aString: 'foo', - aRepeatedStringList: ['s1', 's2'], - aBoolean: true, - $jspbMessageInstance: s1 - }, { - aString: 'bar', - aRepeatedStringList: ['t1', 't2'], - aBoolean: false, - $jspbMessageInstance: s2 - }], - $jspbMessageInstance: extendable - }, extendable.toObject(true /* opt_includeInstance */)); + assertObjectEquals( + { + str1: 'v1', + str2: 'v2', + str3: 'v3', + extField: { + ext1: 'ext1field', + $jspbMessageInstance: + extendable.getExtension(proto.jspb.test.IsExtension.extField) + }, + simple: { + aString: 'str', + aRepeatedStringList: ['s1', 's2'], + aBoolean: true, + $jspbMessageInstance: extendable.getExtension( + proto.jspb.test.IndirectExtension.simple) + }, + str: 'xyzzy', + repeatedStrList: ['a', 'b'], + repeatedSimpleList: [ + { + aString: 'foo', + aRepeatedStringList: ['s1', 's2'], + aBoolean: true, + $jspbMessageInstance: s1 + }, + { + aString: 'bar', + aRepeatedStringList: ['t1', 't2'], + aBoolean: false, + $jspbMessageInstance: s2 + } + ], + $jspbMessageInstance: extendable + }, + extendable.toObject(true /* opt_includeInstance */)); }); it('testInitialization_emptyArray', function() { var msg = new proto.jspb.test.HasExtensions([]); - if (jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS) { - assertArrayEquals([], msg.toArray()); - } else { - // Extension object is created past all regular fields. - assertArrayEquals([,,, {}], msg.toArray()); - } + assertArrayEquals([], msg.toArray()); }); it('testInitialization_justExtensionObject', function() { @@ -695,8 +717,7 @@ describe('Message test suite', function() { var extensionMessage = new proto.jspb.test.IsExtension(['is_extension']); data.setExtension(proto.jspb.test.IsExtension.extField, extensionMessage); var obj = data.toObject(); - assertNotNull( - data.getExtension(proto.jspb.test.IsExtension.extField)); + assertNotNull(data.getExtension(proto.jspb.test.IsExtension.extField)); assertEquals('is_extension', obj.extField.ext1); }); @@ -713,16 +734,18 @@ describe('Message test suite', function() { var groups = group.getRepeatedGroupList(); assertEquals('g1', groups[0].getId()); assertObjectEquals([true, false], groups[0].getSomeBoolList()); - assertObjectEquals({id: 'g1', someBoolList: [true, false]}, - groups[0].toObject()); - assertObjectEquals({ - repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}], - requiredGroup: {id: undefined}, - optionalGroup: undefined, - requiredSimple: {aRepeatedStringList: [], aString: undefined}, - optionalSimple: undefined, - id: undefined - }, group.toObject()); + assertObjectEquals( + {id: 'g1', someBoolList: [true, false]}, groups[0].toObject()); + assertObjectEquals( + { + repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}], + requiredGroup: {id: undefined}, + optionalGroup: undefined, + requiredSimple: {aRepeatedStringList: [], aString: undefined}, + optionalSimple: undefined, + id: undefined + }, + group.toObject()); var group1 = new proto.jspb.test.TestGroup1(); group1.setGroup(someGroup); assertEquals(someGroup, group1.getGroup()); @@ -739,25 +762,26 @@ describe('Message test suite', function() { message.setExtension$(11); message.setExtension(proto.jspb.test.TestReservedNamesExtension.foo, 12); assertEquals(11, message.getExtension$()); - assertEquals(12, message.getExtension( - proto.jspb.test.TestReservedNamesExtension.foo)); + assertEquals( + 12, + message.getExtension(proto.jspb.test.TestReservedNamesExtension.foo)); assertObjectEquals({extension: 11, foo: 12}, message.toObject()); }); it('testInitializeMessageWithUnsetOneof', function() { var message = new proto.jspb.test.TestMessageWithOneof([]); assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase. - PARTIAL_ONEOF_NOT_SET, + proto.jspb.test.TestMessageWithOneof.PartialOneofCase + .PARTIAL_ONEOF_NOT_SET, message.getPartialOneofCase()); assertEquals( - proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase. - RECURSIVE_ONEOF_NOT_SET, + proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase + .RECURSIVE_ONEOF_NOT_SET, message.getRecursiveOneofCase()); }); it('testInitializeMessageWithSingleValueSetInOneof', function() { - var message = new proto.jspb.test.TestMessageWithOneof([,, 'x']); + var message = new proto.jspb.test.TestMessageWithOneof([, , 'x']); assertEquals('x', message.getPone()); assertEquals('', message.getPthree()); @@ -767,7 +791,7 @@ describe('Message test suite', function() { }); it('testKeepsLastWireValueSetInUnion_multipleValues', function() { - var message = new proto.jspb.test.TestMessageWithOneof([,, 'x',, 'y']); + var message = new proto.jspb.test.TestMessageWithOneof([, , 'x', , 'y']); assertEquals('', message.getPone()); assertEquals('y', message.getPthree()); @@ -824,8 +848,8 @@ describe('Message test suite', function() { it('testUnsetsOneofCaseWhenFieldIsCleared', function() { var message = new proto.jspb.test.TestMessageWithOneof; assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase. - PARTIAL_ONEOF_NOT_SET, + proto.jspb.test.TestMessageWithOneof.PartialOneofCase + .PARTIAL_ONEOF_NOT_SET, message.getPartialOneofCase()); message.setPone('hi'); @@ -835,8 +859,8 @@ describe('Message test suite', function() { message.clearPone(); assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase. - PARTIAL_ONEOF_NOT_SET, + proto.jspb.test.TestMessageWithOneof.PartialOneofCase + .PARTIAL_ONEOF_NOT_SET, message.getPartialOneofCase()); }); @@ -939,39 +963,39 @@ describe('Message test suite', function() { }); it('testInitializeMessageWithOneofDefaults_defaultNotSetOnFirstField', - function() { - var message; - - message = - new proto.jspb.test.TestMessageWithOneof(new Array(11).concat(567)); - assertEquals(567, message.getBone()); - assertEquals(1234, message.getBtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE, - message.getDefaultOneofBCase()); - - message = - new proto.jspb.test.TestMessageWithOneof(new Array(12).concat(890)); - assertEquals(0, message.getBone()); - assertEquals(890, message.getBtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO, - message.getDefaultOneofBCase()); - - message = new proto.jspb.test.TestMessageWithOneof( - new Array(11).concat(567, 890)); - assertEquals(0, message.getBone()); - assertEquals(890, message.getBtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO, - message.getDefaultOneofBCase()); - }); + function() { + var message; + + message = + new proto.jspb.test.TestMessageWithOneof(new Array(11).concat(567)); + assertEquals(567, message.getBone()); + assertEquals(1234, message.getBtwo()); + assertEquals( + proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE, + message.getDefaultOneofBCase()); + + message = + new proto.jspb.test.TestMessageWithOneof(new Array(12).concat(890)); + assertEquals(0, message.getBone()); + assertEquals(890, message.getBtwo()); + assertEquals( + proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO, + message.getDefaultOneofBCase()); + + message = new proto.jspb.test.TestMessageWithOneof( + new Array(11).concat(567, 890)); + assertEquals(0, message.getBone()); + assertEquals(890, message.getBtwo()); + assertEquals( + proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO, + message.getDefaultOneofBCase()); + }); it('testOneofContainingAnotherMessage', function() { var message = new proto.jspb.test.TestMessageWithOneof; assertEquals( - proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase. - RECURSIVE_ONEOF_NOT_SET, + proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase + .RECURSIVE_ONEOF_NOT_SET, message.getRecursiveOneofCase()); var other = new proto.jspb.test.TestMessageWithOneof; @@ -992,35 +1016,35 @@ describe('Message test suite', function() { it('testQueryingOneofCaseEnsuresOnlyOneFieldIsSetInUnderlyingArray', function() { - var message = new proto.jspb.test.TestMessageWithOneof; - message.setPone('x'); - assertEquals('x', message.getPone()); - assertEquals('', message.getPthree()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE, - message.getPartialOneofCase()); - - var array = message.toArray(); - assertEquals('x', array[2]); - assertUndefined(array[4]); - array[4] = 'y'; - - assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE, - message.getPartialOneofCase()); - assertUndefined(array[2]); - assertEquals('y', array[4]); - }); + var message = new proto.jspb.test.TestMessageWithOneof; + message.setPone('x'); + assertEquals('x', message.getPone()); + assertEquals('', message.getPthree()); + assertEquals( + proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE, + message.getPartialOneofCase()); + + var array = message.toArray(); + assertEquals('x', array[2]); + assertUndefined(array[4]); + array[4] = 'y'; + + assertEquals( + proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE, + message.getPartialOneofCase()); + assertUndefined(array[2]); + assertEquals('y', array[4]); + }); it('testFloatingPointFieldsSupportNan', function() { var assertNan = function(x) { - assertTrue('Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.', - goog.isNumber(x) && isNaN(x)); + assertTrue( + 'Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.', + typeof x === 'number' && isNaN(x)); }; var message = new proto.jspb.test.FloatingPointFields([ - 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN', - 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN' + 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN', 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN' ]); assertNan(message.getOptionalFloatField()); assertNan(message.getRequiredFloatField()); @@ -1033,5 +1057,4 @@ describe('Message test suite', function() { assertNan(message.getRepeatedDoubleFieldList()[1]); assertNan(message.getDefaultDoubleField()); }); - }); diff --git a/js/compatibility_tests/v3.1.0/proto3_test.js b/js/compatibility_tests/v3.1.0/proto3_test.js index 3c929effd58c8..696af3397f7fd 100644 --- a/js/compatibility_tests/v3.1.0/proto3_test.js +++ b/js/compatibility_tests/v3.1.0/proto3_test.js @@ -50,7 +50,7 @@ var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES); * @return {boolean} */ function bytesCompare(arr, expected) { - if (goog.isString(arr)) { + if (typeof arr === 'string') { arr = goog.crypt.base64.decodeStringToUint8Array(arr); } if (arr.length != expected.length) { diff --git a/js/data.proto b/js/data.proto index 74a8a994c75f0..ca815caf61ebd 100644 --- a/js/data.proto +++ b/js/data.proto @@ -32,11 +32,11 @@ syntax = "proto2"; +package jspb.test; + option java_package = "com.google.apps.jspb.proto"; option java_multiple_files = true; -package jspb.test; - // legacy data, must be nested message data { message NestedData { @@ -48,4 +48,3 @@ message data { message UnnestedData { required string str = 1; } - diff --git a/js/debug.js b/js/debug.js index 46b24853150af..9655b2e34c0bc 100644 --- a/js/debug.js +++ b/js/debug.js @@ -37,12 +37,13 @@ goog.provide('jspb.debug'); goog.require('goog.array'); goog.require('goog.asserts'); goog.require('goog.object'); +goog.require('jspb.Map'); goog.require('jspb.Message'); /** * Turns a proto into a human readable object that can i.e. be written to the - * console: {@code console.log(jspb.debug.dump(myProto))}. + * console: `console.log(jspb.debug.dump(myProto))`. * This function makes a best effort and may not work in all cases. It will not * work in obfuscated and or optimized code. * Use this in environments where {@see jspb.Message.prototype.toObject} is @@ -74,15 +75,32 @@ jspb.debug.dump = function(message) { */ jspb.debug.dump_ = function(thing) { var type = goog.typeOf(thing); + var message = thing; // Copy because we don't want type inference on thing. if (type == 'number' || type == 'string' || type == 'boolean' || type == 'null' || type == 'undefined') { return thing; } + if (typeof Uint8Array !== 'undefined') { + // Will fail on IE9, where Uint8Array doesn't exist. + if (message instanceof Uint8Array) { + return thing; + } + } + if (type == 'array') { goog.asserts.assertArray(thing); return goog.array.map(thing, jspb.debug.dump_); } - var message = thing; // Copy because we don't want type inference on thing. + + if (message instanceof jspb.Map) { + var mapObject = {}; + var entries = message.entries(); + for (var entry = entries.next(); !entry.done; entry = entries.next()) { + mapObject[entry.value[0]] = jspb.debug.dump_(entry.value[1]); + } + return mapObject; + } + goog.asserts.assert(message instanceof jspb.Message, 'Only messages expected: ' + thing); var ctor = message.constructor; diff --git a/js/debug_test.js b/js/debug_test.js index 702cc76e90a26..5096869962696 100644 --- a/js/debug_test.js +++ b/js/debug_test.js @@ -38,9 +38,13 @@ goog.require('jspb.debug'); // CommonJS-LoadFromFile: test_pb goog.require('proto.jspb.test.HasExtensions'); goog.require('proto.jspb.test.IsExtension'); +goog.require('proto.jspb.test.MapValueMessageNoBinary'); goog.require('proto.jspb.test.Simple1'); +goog.require('proto.jspb.test.TestMapFieldsNoBinary'); +// CommonJS-LoadFromFile: testbinary_pb +goog.require('proto.jspb.test.TestAllTypes'); describe('debugTest', function() { it('testSimple1', function() { @@ -74,6 +78,15 @@ describe('debugTest', function() { }, jspb.debug.dump(message)); }); + it('testBytes', function() { + if (COMPILED || typeof Uint8Array == 'undefined') { + return; + } + var message = new proto.jspb.test.TestAllTypes(); + var bytes = new Uint8Array(4); + message.setOptionalBytes(bytes); + assertEquals(jspb.debug.dump(message)['optionalBytes'], bytes); + }); it('testExtensions', function() { if (COMPILED) { @@ -102,4 +115,74 @@ describe('debugTest', function() { }, jspb.debug.dump(extendable)); }); + it('testMapsBasicTypes', function() { + if (COMPILED) { + return; + } + + var message = new proto.jspb.test.TestMapFieldsNoBinary(); + message.getMapBoolStringMap().set(true, 'bool_string_value1'); + message.getMapBoolStringMap().set(false, 'bool_string_value2'); + message.getMapStringInt32Map().set('key', 111); + + assertObjectEquals({ + '$name': 'proto.jspb.test.TestMapFieldsNoBinary', + 'mapBoolStringMap': { + true: 'bool_string_value1', + false: 'bool_string_value2' + }, + 'mapInt32StringMap': {}, + 'mapInt64StringMap': {}, + 'mapStringBoolMap': {}, + 'mapStringDoubleMap': {}, + 'mapStringEnumMap': {}, + 'mapStringInt32Map': { + 'key': 111 + }, + 'mapStringInt64Map': {}, + 'mapStringMsgMap': {}, + 'mapStringStringMap': {}, + 'mapStringTestmapfieldsMap': {} + }, jspb.debug.dump(message)); + }); + + it('testMapsMessageValues', function() { + if (COMPILED) { + return; + } + + var value1 = new proto.jspb.test.MapValueMessageNoBinary(); + value1.setFoo(1111); + var value2 = new proto.jspb.test.MapValueMessageNoBinary(); + value2.setFoo(2222); + + var message = new proto.jspb.test.TestMapFieldsNoBinary(); + message.getMapStringMsgMap().set('key1', value1); + message.getMapStringMsgMap().set('key2', value2); + + assertObjectEquals({ + '$name': 'proto.jspb.test.TestMapFieldsNoBinary', + 'mapBoolStringMap': {}, + 'mapInt32StringMap': {}, + 'mapInt64StringMap': {}, + 'mapStringBoolMap': {}, + 'mapStringDoubleMap': {}, + 'mapStringEnumMap': {}, + 'mapStringInt32Map': {}, + 'mapStringInt64Map': {}, + 'mapStringMsgMap': { + 'key1': { + '$name': 'proto.jspb.test.MapValueMessageNoBinary', + 'foo': 1111 + }, + 'key2': { + '$name': 'proto.jspb.test.MapValueMessageNoBinary', + 'foo': 2222 + } + }, + 'mapStringStringMap': {}, + 'mapStringTestmapfieldsMap': {} + }, jspb.debug.dump(message)); + }); + }); diff --git a/js/experimental/benchmarks/code_size/apps_jspb/all_types_proto2.js b/js/experimental/benchmarks/code_size/apps_jspb/all_types_proto2.js new file mode 100644 index 0000000000000..252520f71c47d --- /dev/null +++ b/js/experimental/benchmarks/code_size/apps_jspb/all_types_proto2.js @@ -0,0 +1,314 @@ +/** + * @fileoverview The code size benchmark of apps JSPB for proto2 all types + */ +goog.module('protobuf.benchmark.code_size.apps_jspb.AllTypesProto2'); + +// const ForeignEnum = goog.require('proto.proto2_unittest.ForeignEnum'); +const ForeignMessage = goog.require('proto.proto2_unittest.ForeignMessage'); +const TestAllTypes = goog.require('proto.proto2_unittest.TestAllTypes'); +const TestPackedTypes = goog.require('proto.proto2_unittest.TestPackedTypes'); +const {ensureCommonBaseLine} = goog.require('protobuf.benchmark.codeSize.codeSizeBase'); + +ensureCommonBaseLine(); + +/** + * The testing scenario is the same as kernel one. + * We have + * 1) add element to repeated fields + * 2) add element list to repeated fields + * 3) set fields + * 4) set repeated fields element + * 5) get fields + * 6) get repeated fields element + * 7) get repeated fields length + * @return {string} + */ +function accessAllTypes() { + const msgAllTypes = TestAllTypes.deserialize(''); + const msgPackedTypes = TestPackedTypes.deserialize(''); + + msgPackedTypes.addPackedBool(true); + [true].forEach((e) => msgPackedTypes.addPackedBool(e)); + msgAllTypes.addRepeatedBool(true, 1); + [true].forEach((e) => msgAllTypes.addRepeatedBool(e)); + msgAllTypes.addRepeatedBytes('1', 1); + ['1'].forEach((e) => msgAllTypes.addRepeatedBytes(e)); + msgPackedTypes.addPackedDouble(1.0); + [1.0].forEach((e) => msgPackedTypes.addPackedDouble(e)); + msgAllTypes.addRepeatedDouble(1.0, 1); + [1.0].forEach((e) => msgAllTypes.addRepeatedDouble(e)); + msgPackedTypes.addPackedFixed32(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedFixed32(e)); + msgAllTypes.addRepeatedFixed32(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedFixed32(e)); + msgPackedTypes.addPackedFixed64(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedFixed64(e)); + msgAllTypes.addRepeatedFixed64(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedFixed64(e)); + msgPackedTypes.addPackedFloat(1.0, 1); + [1.0].forEach((e) => msgPackedTypes.addPackedFloat(e)); + msgAllTypes.addRepeatedFloat(1.0, 1); + [1.0].forEach((e) => msgAllTypes.addRepeatedFloat(e)); + msgPackedTypes.addPackedInt32(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedInt32(e)); + msgAllTypes.addRepeatedInt32(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedInt32(e)); + msgPackedTypes.addPackedInt64(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedInt64(e)); + msgAllTypes.addRepeatedInt64(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedInt64(e)); + // msgPackedTypes.addPackedEnum(ForeignEnum.FOREIGN_BAR); + // [ForeignEnum.FOREIGN_BAR].forEach((e) => msgPackedTypes.addPackedEnum(e)); + // msgAllTypes.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAR); + // [ForeignEnum.FOREIGN_BAR].forEach( + // (e) => msgAllTypes.addRepeatedForeignEnum(e)); + msgAllTypes.addRepeatedForeignMessage(ForeignMessage.deserialize(''), 1); + [ForeignMessage.deserialize('')].forEach( + (e) => msgAllTypes.addRepeatedForeignMessage(e)); + msgPackedTypes.addPackedSfixed32(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedSfixed32(e)); + msgAllTypes.addRepeatedSfixed32(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedSfixed32(e)); + msgPackedTypes.addPackedSfixed64(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedSfixed64(e)); + msgAllTypes.addRepeatedSfixed64(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedSfixed64(e)); + msgPackedTypes.addPackedSint32(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedSint32(e)); + msgAllTypes.addRepeatedSint32(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedSint32(e)); + msgPackedTypes.addPackedSint64(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedSint64(e)); + msgAllTypes.addRepeatedSint64(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedSint64(e)); + msgAllTypes.addRepeatedString('', 1); + [''].forEach((e) => msgAllTypes.addRepeatedString(e)); + msgPackedTypes.addPackedUint32(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedUint32(e)); + msgAllTypes.addRepeatedUint32(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedUint32(e)); + msgPackedTypes.addPackedUint64(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedUint64(e)); + msgAllTypes.addRepeatedUint64(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedUint64(e)); + + msgAllTypes.setOptionalBool(true); + msgAllTypes.setOptionalBytes(''); + msgAllTypes.setOptionalDouble(1.0); + msgAllTypes.setOptionalFixed32(1); + msgAllTypes.setOptionalFixed64(1); + msgAllTypes.setOptionalFloat(1.0); + msgAllTypes.setOptionalInt32(1); + msgAllTypes.setOptionalInt64(1); + // msgAllTypes.setOptionalForeignEnum(ForeignEnum.FOREIGN_BAR); + msgAllTypes.setOptionalForeignMessage(ForeignMessage.deserialize('')); + msgAllTypes.setOptionalSfixed32(1); + msgAllTypes.setOptionalSfixed64(1); + msgAllTypes.setOptionalSint32(1); + msgAllTypes.setOptionalSint64(1); + msgAllTypes.setOptionalString(''); + msgAllTypes.setOptionalUint32(1); + msgAllTypes.setOptionalUint64(1); + msgPackedTypes.setPackedBoolList([true]); + let arrayVal; + arrayVal = msgPackedTypes.getPackedBoolList(); + arrayVal[0] = true; + msgPackedTypes.setPackedBoolList(arrayVal); + msgAllTypes.setRepeatedBoolList([true]); + arrayVal = msgAllTypes.getRepeatedBoolList(); + arrayVal[0] = true; + msgAllTypes.setRepeatedBoolList(arrayVal); + msgAllTypes.setRepeatedBytesList(['']); + arrayVal = msgAllTypes.getRepeatedBytesList(); + arrayVal[0] = ''; + msgAllTypes.setRepeatedBytesList(arrayVal); + msgPackedTypes.setPackedDoubleList([1.0]); + arrayVal = msgPackedTypes.getPackedDoubleList(); + arrayVal[0] = 1.0; + msgPackedTypes.setPackedDoubleList(arrayVal); + msgAllTypes.setRepeatedDoubleList([1.0]); + arrayVal = msgAllTypes.getRepeatedDoubleList(); + arrayVal[0] = 1.0; + msgAllTypes.setRepeatedDoubleList(arrayVal); + msgPackedTypes.setPackedFixed32List([1]); + arrayVal = msgPackedTypes.getPackedFixed32List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedFixed32List(arrayVal); + msgAllTypes.setRepeatedFixed32List([1]); + arrayVal = msgAllTypes.getRepeatedFixed32List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedFixed32List(arrayVal); + msgPackedTypes.setPackedFixed64List([1]); + arrayVal = msgPackedTypes.getPackedFixed64List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedFixed64List(arrayVal); + msgAllTypes.setRepeatedFixed64List([1]); + arrayVal = msgAllTypes.getRepeatedFixed64List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedFixed64List(arrayVal); + msgPackedTypes.setPackedFloatList([1.0]); + arrayVal = msgPackedTypes.getPackedFloatList(); + arrayVal[0] = 1.0; + msgPackedTypes.setPackedFloatList(arrayVal); + msgAllTypes.setRepeatedFloatList([1.0]); + arrayVal = msgAllTypes.getRepeatedFloatList(); + arrayVal[0] = 1.0; + msgAllTypes.setRepeatedFloatList(arrayVal); + msgPackedTypes.setPackedInt32List([1]); + arrayVal = msgPackedTypes.getPackedInt32List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedInt32List(arrayVal); + msgAllTypes.setRepeatedInt32List([1]); + arrayVal = msgAllTypes.getRepeatedInt32List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedInt32List(arrayVal); + msgPackedTypes.setPackedInt64List([1]); + arrayVal = msgPackedTypes.getPackedInt64List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedInt64List(arrayVal); + msgAllTypes.setRepeatedInt64List([1]); + arrayVal = msgAllTypes.getRepeatedInt64List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedInt64List(arrayVal); + // msgPackedTypes.setPackedEnumList([ForeignEnum.FOREIGN_BAR]); + // arrayVal = msgPackedTypes.getPackedEnumList(); + // arrayVal[0] = ForeignEnum.FOREIGN_BAR; + // msgPackedTypes.setPackedEnumList(arrayVal); + // msgAllTypes.setRepeatedForeignEnumList([ForeignEnum.FOREIGN_BAR]); + // arrayVal = msgAllTypes.getRepeatedForeignEnumList(); + // arrayVal[0] = ForeignEnum.FOREIGN_BAR; + // msgAllTypes.setRepeatedForeignEnumList(arrayVal); + msgAllTypes.setRepeatedForeignMessageList([ForeignMessage.deserialize('')]); + arrayVal = msgAllTypes.getRepeatedForeignMessageList(); + arrayVal[0] = ForeignMessage.deserialize(''); + msgAllTypes.setRepeatedForeignMessageList(arrayVal); + msgPackedTypes.setPackedSfixed32List([1]); + arrayVal = msgPackedTypes.getPackedSfixed32List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedSfixed32List(arrayVal); + msgAllTypes.setRepeatedSfixed32List([1]); + arrayVal = msgAllTypes.getRepeatedSfixed32List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedSfixed32List(arrayVal); + msgPackedTypes.setPackedSfixed64List([1]); + arrayVal = msgPackedTypes.getPackedSfixed64List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedSfixed64List(arrayVal); + msgAllTypes.setRepeatedSfixed64List([1]); + arrayVal = msgAllTypes.getRepeatedSfixed64List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedSfixed64List(arrayVal); + msgPackedTypes.setPackedSint32List([1]); + arrayVal = msgPackedTypes.getPackedSint32List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedSint32List(arrayVal); + msgAllTypes.setRepeatedSint32List([1]); + arrayVal = msgAllTypes.getRepeatedSint32List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedSint32List(arrayVal); + msgPackedTypes.setPackedSint64List([1]); + arrayVal = msgPackedTypes.getPackedSint64List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedSint64List(arrayVal); + msgAllTypes.setRepeatedSint64List([1]); + arrayVal = msgAllTypes.getRepeatedSint64List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedSint64List(arrayVal); + msgPackedTypes.setPackedUint32List([1]); + arrayVal = msgPackedTypes.getPackedUint32List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedUint32List(arrayVal); + msgAllTypes.setRepeatedUint32List([1]); + arrayVal = msgAllTypes.getRepeatedUint32List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedUint32List(arrayVal); + msgPackedTypes.setPackedUint64List([1]); + arrayVal = msgPackedTypes.getPackedUint64List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedUint64List(arrayVal); + msgAllTypes.setRepeatedUint64List([1]); + arrayVal = msgAllTypes.getRepeatedUint64List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedUint64List(arrayVal); + + let s = ''; + s += msgAllTypes.getOptionalBool() || false; + s += msgAllTypes.getOptionalBytes() || ''; + // s += msgAllTypes.getOptionalBytes_asB64() || ""; + // s += msgAllTypes.getOptionalBytes_asU8() || new Uint8Array([]); + s += msgAllTypes.getOptionalDouble() || 0.0; + s += msgAllTypes.getOptionalFixed32() || 0; + s += msgAllTypes.getOptionalFixed64() || 0; + s += msgAllTypes.getOptionalFloat() || 0.0; + s += msgAllTypes.getOptionalInt32() || 0; + s += msgAllTypes.getOptionalInt64() || 0; + // s += msgAllTypes.getOptionalForeignEnum() || ForeignEnum.FOREIGN_BAR; + s += msgAllTypes.getOptionalForeignMessage(); + s += msgAllTypes.getOptionalSfixed32() || 0; + s += msgAllTypes.getOptionalSfixed64() || 0; + s += msgAllTypes.getOptionalSint32() || 0; + s += msgAllTypes.getOptionalSint64() || 0; + s += msgAllTypes.getOptionalString() || ''; + s += msgAllTypes.getOptionalUint32() || 0; + s += msgAllTypes.getOptionalUint64() || 0; + s += msgAllTypes.getRepeatedBoolList(); + s += msgAllTypes.getRepeatedBoolList()[0]; + s += msgAllTypes.getRepeatedBoolList().length; + s += msgAllTypes.getRepeatedBytesList(); + s += msgAllTypes.getRepeatedBytesList()[0]; + s += msgAllTypes.getRepeatedBytesList().length; + s += msgAllTypes.getRepeatedBytesList_asB64(); + s += msgAllTypes.getRepeatedBytesList_asU8(); + s += msgAllTypes.getRepeatedDoubleList(); + s += msgAllTypes.getRepeatedDoubleList()[0]; + s += msgAllTypes.getRepeatedDoubleList().length; + s += msgAllTypes.getRepeatedFixed32List(); + s += msgAllTypes.getRepeatedFixed32List()[0]; + s += msgAllTypes.getRepeatedFixed32List().length; + s += msgAllTypes.getRepeatedFixed64List(); + s += msgAllTypes.getRepeatedFixed64List()[0]; + s += msgAllTypes.getRepeatedFixed64List().length; + s += msgAllTypes.getRepeatedFloatList(); + s += msgAllTypes.getRepeatedFloatList()[0]; + s += msgAllTypes.getRepeatedFloatList().length; + s += msgAllTypes.getRepeatedInt32List(); + s += msgAllTypes.getRepeatedInt32List()[0]; + s += msgAllTypes.getRepeatedInt32List().length; + s += msgAllTypes.getRepeatedInt64List(); + s += msgAllTypes.getRepeatedInt64List()[0]; + s += msgAllTypes.getRepeatedInt64List().length; + // s += msgAllTypes.getRepeatedForeignEnumList(); + // s += msgAllTypes.getRepeatedForeignEnumList()[0]; + // s += msgAllTypes.getRepeatedForeignEnumList().length; + s += msgAllTypes.getRepeatedForeignMessageList(); + s += msgAllTypes.getRepeatedForeignMessageList()[0]; + s += msgAllTypes.getRepeatedForeignMessageList().length; + s += msgAllTypes.getRepeatedSfixed32List(); + s += msgAllTypes.getRepeatedSfixed32List()[0]; + s += msgAllTypes.getRepeatedSfixed32List().length; + s += msgAllTypes.getRepeatedSfixed64List(); + s += msgAllTypes.getRepeatedSfixed64List()[0]; + s += msgAllTypes.getRepeatedSfixed64List().length; + s += msgAllTypes.getRepeatedSint32List(); + s += msgAllTypes.getRepeatedSint32List()[0]; + s += msgAllTypes.getRepeatedSint32List().length; + s += msgAllTypes.getRepeatedSint64List(); + s += msgAllTypes.getRepeatedSint64List()[0]; + s += msgAllTypes.getRepeatedSint64List().length; + s += msgAllTypes.getRepeatedStringList(); + s += msgAllTypes.getRepeatedStringList()[0]; + s += msgAllTypes.getRepeatedStringList().length; + s += msgAllTypes.getRepeatedUint32List(); + s += msgAllTypes.getRepeatedUint32List()[0]; + s += msgAllTypes.getRepeatedUint32List().length; + s += msgAllTypes.getRepeatedUint64List(); + s += msgAllTypes.getRepeatedUint64List()[0]; + s += msgAllTypes.getRepeatedUint64List().length; + + s += msgAllTypes.serialize(); + s += msgPackedTypes.serialize(); + + return s; +} + +goog.global['__hiddenTest'] += accessAllTypes(); diff --git a/js/experimental/benchmarks/code_size/apps_jspb/all_types_proto3.js b/js/experimental/benchmarks/code_size/apps_jspb/all_types_proto3.js new file mode 100644 index 0000000000000..3637df612f8d1 --- /dev/null +++ b/js/experimental/benchmarks/code_size/apps_jspb/all_types_proto3.js @@ -0,0 +1,314 @@ +/** + * @fileoverview The code size benchmark of apps JSPB for proto3 all types + */ +goog.module('protobuf.benchmark.code_size.apps_jspb.AllTypesProto3'); + +// const ForeignEnum = goog.require('proto.proto3_unittest.ForeignEnum'); +const ForeignMessage = goog.require('proto.proto3_unittest.ForeignMessage'); +const TestAllTypes = goog.require('proto.proto3_unittest.TestAllTypes'); +const TestPackedTypes = goog.require('proto.proto3_unittest.TestPackedTypes'); +const {ensureCommonBaseLine} = goog.require('protobuf.benchmark.codeSize.codeSizeBase'); + +ensureCommonBaseLine(); + +/** + * The testing scenario is the same as kernel one. + * We have + * 1) add element to repeated fields + * 2) add element list to repeated fields + * 3) set fields + * 4) set repeated fields element + * 5) get fields + * 6) get repeated fields element + * 7) get repeated fields length + * @return {string} + */ +function accessAllTypes() { + const msgAllTypes = TestAllTypes.deserialize(''); + const msgPackedTypes = TestPackedTypes.deserialize(''); + + msgPackedTypes.addPackedBool(true); + [true].forEach((e) => msgPackedTypes.addPackedBool(e)); + msgAllTypes.addRepeatedBool(true, 1); + [true].forEach((e) => msgAllTypes.addRepeatedBool(e)); + msgAllTypes.addRepeatedBytes('1', 1); + ['1'].forEach((e) => msgAllTypes.addRepeatedBytes(e)); + msgPackedTypes.addPackedDouble(1.0); + [1.0].forEach((e) => msgPackedTypes.addPackedDouble(e)); + msgAllTypes.addRepeatedDouble(1.0, 1); + [1.0].forEach((e) => msgAllTypes.addRepeatedDouble(e)); + msgPackedTypes.addPackedFixed32(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedFixed32(e)); + msgAllTypes.addRepeatedFixed32(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedFixed32(e)); + msgPackedTypes.addPackedFixed64(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedFixed64(e)); + msgAllTypes.addRepeatedFixed64(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedFixed64(e)); + msgPackedTypes.addPackedFloat(1.0, 1); + [1.0].forEach((e) => msgPackedTypes.addPackedFloat(e)); + msgAllTypes.addRepeatedFloat(1.0, 1); + [1.0].forEach((e) => msgAllTypes.addRepeatedFloat(e)); + msgPackedTypes.addPackedInt32(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedInt32(e)); + msgAllTypes.addRepeatedInt32(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedInt32(e)); + msgPackedTypes.addPackedInt64(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedInt64(e)); + msgAllTypes.addRepeatedInt64(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedInt64(e)); + // msgPackedTypes.addPackedEnum(ForeignEnum.FOREIGN_BAR); + // [ForeignEnum.FOREIGN_BAR].forEach((e) => msgPackedTypes.addPackedEnum(e)); + // msgAllTypes.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAR); + // [ForeignEnum.FOREIGN_BAR].forEach( + // (e) => msgAllTypes.addRepeatedForeignEnum(e)); + msgAllTypes.addRepeatedForeignMessage(ForeignMessage.deserialize(''), 1); + [ForeignMessage.deserialize('')].forEach( + (e) => msgAllTypes.addRepeatedForeignMessage(e)); + msgPackedTypes.addPackedSfixed32(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedSfixed32(e)); + msgAllTypes.addRepeatedSfixed32(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedSfixed32(e)); + msgPackedTypes.addPackedSfixed64(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedSfixed64(e)); + msgAllTypes.addRepeatedSfixed64(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedSfixed64(e)); + msgPackedTypes.addPackedSint32(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedSint32(e)); + msgAllTypes.addRepeatedSint32(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedSint32(e)); + msgPackedTypes.addPackedSint64(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedSint64(e)); + msgAllTypes.addRepeatedSint64(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedSint64(e)); + msgAllTypes.addRepeatedString('', 1); + [''].forEach((e) => msgAllTypes.addRepeatedString(e)); + msgPackedTypes.addPackedUint32(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedUint32(e)); + msgAllTypes.addRepeatedUint32(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedUint32(e)); + msgPackedTypes.addPackedUint64(1, 1); + [1].forEach((e) => msgPackedTypes.addPackedUint64(e)); + msgAllTypes.addRepeatedUint64(1, 1); + [1].forEach((e) => msgAllTypes.addRepeatedUint64(e)); + + msgAllTypes.setOptionalBool(true); + msgAllTypes.setOptionalBytes(''); + msgAllTypes.setOptionalDouble(1.0); + msgAllTypes.setOptionalFixed32(1); + msgAllTypes.setOptionalFixed64(1); + msgAllTypes.setOptionalFloat(1.0); + msgAllTypes.setOptionalInt32(1); + msgAllTypes.setOptionalInt64(1); + // msgAllTypes.setOptionalForeignEnum(ForeignEnum.FOREIGN_BAR); + msgAllTypes.setOptionalForeignMessage(ForeignMessage.deserialize('')); + msgAllTypes.setOptionalSfixed32(1); + msgAllTypes.setOptionalSfixed64(1); + msgAllTypes.setOptionalSint32(1); + msgAllTypes.setOptionalSint64(1); + msgAllTypes.setOptionalString(''); + msgAllTypes.setOptionalUint32(1); + msgAllTypes.setOptionalUint64(1); + msgPackedTypes.setPackedBoolList([true]); + let arrayVal; + arrayVal = msgPackedTypes.getPackedBoolList(); + arrayVal[0] = true; + msgPackedTypes.setPackedBoolList(arrayVal); + msgAllTypes.setRepeatedBoolList([true]); + arrayVal = msgAllTypes.getRepeatedBoolList(); + arrayVal[0] = true; + msgAllTypes.setRepeatedBoolList(arrayVal); + msgAllTypes.setRepeatedBytesList(['']); + arrayVal = msgAllTypes.getRepeatedBytesList(); + arrayVal[0] = ''; + msgAllTypes.setRepeatedBytesList(arrayVal); + msgPackedTypes.setPackedDoubleList([1.0]); + arrayVal = msgPackedTypes.getPackedDoubleList(); + arrayVal[0] = 1.0; + msgPackedTypes.setPackedDoubleList(arrayVal); + msgAllTypes.setRepeatedDoubleList([1.0]); + arrayVal = msgAllTypes.getRepeatedDoubleList(); + arrayVal[0] = 1.0; + msgAllTypes.setRepeatedDoubleList(arrayVal); + msgPackedTypes.setPackedFixed32List([1]); + arrayVal = msgPackedTypes.getPackedFixed32List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedFixed32List(arrayVal); + msgAllTypes.setRepeatedFixed32List([1]); + arrayVal = msgAllTypes.getRepeatedFixed32List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedFixed32List(arrayVal); + msgPackedTypes.setPackedFixed64List([1]); + arrayVal = msgPackedTypes.getPackedFixed64List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedFixed64List(arrayVal); + msgAllTypes.setRepeatedFixed64List([1]); + arrayVal = msgAllTypes.getRepeatedFixed64List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedFixed64List(arrayVal); + msgPackedTypes.setPackedFloatList([1.0]); + arrayVal = msgPackedTypes.getPackedFloatList(); + arrayVal[0] = 1.0; + msgPackedTypes.setPackedFloatList(arrayVal); + msgAllTypes.setRepeatedFloatList([1.0]); + arrayVal = msgAllTypes.getRepeatedFloatList(); + arrayVal[0] = 1.0; + msgAllTypes.setRepeatedFloatList(arrayVal); + msgPackedTypes.setPackedInt32List([1]); + arrayVal = msgPackedTypes.getPackedInt32List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedInt32List(arrayVal); + msgAllTypes.setRepeatedInt32List([1]); + arrayVal = msgAllTypes.getRepeatedInt32List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedInt32List(arrayVal); + msgPackedTypes.setPackedInt64List([1]); + arrayVal = msgPackedTypes.getPackedInt64List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedInt64List(arrayVal); + msgAllTypes.setRepeatedInt64List([1]); + arrayVal = msgAllTypes.getRepeatedInt64List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedInt64List(arrayVal); + // msgPackedTypes.setPackedEnumList([ForeignEnum.FOREIGN_BAR]); + // arrayVal = msgPackedTypes.getPackedEnumList(); + // arrayVal[0] = ForeignEnum.FOREIGN_BAR; + // msgPackedTypes.setPackedEnumList(arrayVal); + // msgAllTypes.setRepeatedForeignEnumList([ForeignEnum.FOREIGN_BAR]); + // arrayVal = msgAllTypes.getRepeatedForeignEnumList(); + // arrayVal[0] = ForeignEnum.FOREIGN_BAR; + // msgAllTypes.setRepeatedForeignEnumList(arrayVal); + msgAllTypes.setRepeatedForeignMessageList([ForeignMessage.deserialize('')]); + arrayVal = msgAllTypes.getRepeatedForeignMessageList(); + arrayVal[0] = ForeignMessage.deserialize(''); + msgAllTypes.setRepeatedForeignMessageList(arrayVal); + msgPackedTypes.setPackedSfixed32List([1]); + arrayVal = msgPackedTypes.getPackedSfixed32List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedSfixed32List(arrayVal); + msgAllTypes.setRepeatedSfixed32List([1]); + arrayVal = msgAllTypes.getRepeatedSfixed32List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedSfixed32List(arrayVal); + msgPackedTypes.setPackedSfixed64List([1]); + arrayVal = msgPackedTypes.getPackedSfixed64List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedSfixed64List(arrayVal); + msgAllTypes.setRepeatedSfixed64List([1]); + arrayVal = msgAllTypes.getRepeatedSfixed64List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedSfixed64List(arrayVal); + msgPackedTypes.setPackedSint32List([1]); + arrayVal = msgPackedTypes.getPackedSint32List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedSint32List(arrayVal); + msgAllTypes.setRepeatedSint32List([1]); + arrayVal = msgAllTypes.getRepeatedSint32List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedSint32List(arrayVal); + msgPackedTypes.setPackedSint64List([1]); + arrayVal = msgPackedTypes.getPackedSint64List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedSint64List(arrayVal); + msgAllTypes.setRepeatedSint64List([1]); + arrayVal = msgAllTypes.getRepeatedSint64List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedSint64List(arrayVal); + msgPackedTypes.setPackedUint32List([1]); + arrayVal = msgPackedTypes.getPackedUint32List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedUint32List(arrayVal); + msgAllTypes.setRepeatedUint32List([1]); + arrayVal = msgAllTypes.getRepeatedUint32List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedUint32List(arrayVal); + msgPackedTypes.setPackedUint64List([1]); + arrayVal = msgPackedTypes.getPackedUint64List(); + arrayVal[0] = 1; + msgPackedTypes.setPackedUint64List(arrayVal); + msgAllTypes.setRepeatedUint64List([1]); + arrayVal = msgAllTypes.getRepeatedUint64List(); + arrayVal[0] = 1; + msgAllTypes.setRepeatedUint64List(arrayVal); + + let s = ''; + s += msgAllTypes.getOptionalBool() || false; + s += msgAllTypes.getOptionalBytes() || ''; + // s += msgAllTypes.getOptionalBytes_asB64() || ""; + // s += msgAllTypes.getOptionalBytes_asU8() || new Uint8Array([]); + s += msgAllTypes.getOptionalDouble() || 0.0; + s += msgAllTypes.getOptionalFixed32() || 0; + s += msgAllTypes.getOptionalFixed64() || 0; + s += msgAllTypes.getOptionalFloat() || 0.0; + s += msgAllTypes.getOptionalInt32() || 0; + s += msgAllTypes.getOptionalInt64() || 0; + // s += msgAllTypes.getOptionalForeignEnum() || ForeignEnum.FOREIGN_BAR; + s += msgAllTypes.getOptionalForeignMessage(); + s += msgAllTypes.getOptionalSfixed32() || 0; + s += msgAllTypes.getOptionalSfixed64() || 0; + s += msgAllTypes.getOptionalSint32() || 0; + s += msgAllTypes.getOptionalSint64() || 0; + s += msgAllTypes.getOptionalString() || ''; + s += msgAllTypes.getOptionalUint32() || 0; + s += msgAllTypes.getOptionalUint64() || 0; + s += msgAllTypes.getRepeatedBoolList(); + s += msgAllTypes.getRepeatedBoolList()[0]; + s += msgAllTypes.getRepeatedBoolList().length; + s += msgAllTypes.getRepeatedBytesList(); + s += msgAllTypes.getRepeatedBytesList()[0]; + s += msgAllTypes.getRepeatedBytesList().length; + s += msgAllTypes.getRepeatedBytesList_asB64(); + s += msgAllTypes.getRepeatedBytesList_asU8(); + s += msgAllTypes.getRepeatedDoubleList(); + s += msgAllTypes.getRepeatedDoubleList()[0]; + s += msgAllTypes.getRepeatedDoubleList().length; + s += msgAllTypes.getRepeatedFixed32List(); + s += msgAllTypes.getRepeatedFixed32List()[0]; + s += msgAllTypes.getRepeatedFixed32List().length; + s += msgAllTypes.getRepeatedFixed64List(); + s += msgAllTypes.getRepeatedFixed64List()[0]; + s += msgAllTypes.getRepeatedFixed64List().length; + s += msgAllTypes.getRepeatedFloatList(); + s += msgAllTypes.getRepeatedFloatList()[0]; + s += msgAllTypes.getRepeatedFloatList().length; + s += msgAllTypes.getRepeatedInt32List(); + s += msgAllTypes.getRepeatedInt32List()[0]; + s += msgAllTypes.getRepeatedInt32List().length; + s += msgAllTypes.getRepeatedInt64List(); + s += msgAllTypes.getRepeatedInt64List()[0]; + s += msgAllTypes.getRepeatedInt64List().length; + // s += msgAllTypes.getRepeatedForeignEnumList(); + // s += msgAllTypes.getRepeatedForeignEnumList()[0]; + // s += msgAllTypes.getRepeatedForeignEnumList().length; + s += msgAllTypes.getRepeatedForeignMessageList(); + s += msgAllTypes.getRepeatedForeignMessageList()[0]; + s += msgAllTypes.getRepeatedForeignMessageList().length; + s += msgAllTypes.getRepeatedSfixed32List(); + s += msgAllTypes.getRepeatedSfixed32List()[0]; + s += msgAllTypes.getRepeatedSfixed32List().length; + s += msgAllTypes.getRepeatedSfixed64List(); + s += msgAllTypes.getRepeatedSfixed64List()[0]; + s += msgAllTypes.getRepeatedSfixed64List().length; + s += msgAllTypes.getRepeatedSint32List(); + s += msgAllTypes.getRepeatedSint32List()[0]; + s += msgAllTypes.getRepeatedSint32List().length; + s += msgAllTypes.getRepeatedSint64List(); + s += msgAllTypes.getRepeatedSint64List()[0]; + s += msgAllTypes.getRepeatedSint64List().length; + s += msgAllTypes.getRepeatedStringList(); + s += msgAllTypes.getRepeatedStringList()[0]; + s += msgAllTypes.getRepeatedStringList().length; + s += msgAllTypes.getRepeatedUint32List(); + s += msgAllTypes.getRepeatedUint32List()[0]; + s += msgAllTypes.getRepeatedUint32List().length; + s += msgAllTypes.getRepeatedUint64List(); + s += msgAllTypes.getRepeatedUint64List()[0]; + s += msgAllTypes.getRepeatedUint64List().length; + + s += msgAllTypes.serialize(); + s += msgPackedTypes.serialize(); + + return s; +} + +goog.global['__hiddenTest'] += accessAllTypes(); diff --git a/js/experimental/benchmarks/code_size/apps_jspb/popular_types_proto2.js b/js/experimental/benchmarks/code_size/apps_jspb/popular_types_proto2.js new file mode 100644 index 0000000000000..7bea88a274484 --- /dev/null +++ b/js/experimental/benchmarks/code_size/apps_jspb/popular_types_proto2.js @@ -0,0 +1,53 @@ +/** + * @fileoverview The code size benchmark of apps JSPB for proto2 popular types. + */ +goog.module('protobuf.benchmark.code_size.apps_jspb.PopularTypesProto2'); + +// const ForeignEnum = goog.require('proto.proto2_unittest.ForeignEnum'); +const ForeignMessage = goog.require('proto.proto2_unittest.ForeignMessage'); +const TestAllTypes = goog.require('proto.proto2_unittest.TestAllTypes'); +const {ensureCommonBaseLine} = goog.require('protobuf.benchmark.codeSize.codeSizeBase'); + +ensureCommonBaseLine(); + +/** + * @return {string} + */ +function accessPopularTypes() { + const msgAllTypes = TestAllTypes.deserialize(''); + msgAllTypes.addRepeatedForeignMessage(ForeignMessage.deserialize(''), 1); + [ForeignMessage.deserialize('')].forEach( + (e) => msgAllTypes.addRepeatedForeignMessage(e)); + + msgAllTypes.setOptionalString(''); + msgAllTypes.setOptionalInt32(1); + msgAllTypes.setOptionalForeignMessage(ForeignMessage.deserialize('')); + msgAllTypes.setOptionalBool(true); + // msgAllTypes.setOptionalForeignEnum(ForeignEnum.FOREIGN_BAR); + msgAllTypes.setOptionalInt64(1); + msgAllTypes.setOptionalDouble(1.0); + msgAllTypes.setRepeatedForeignMessageList([ForeignMessage.deserialize('')]); + let arrayVal = msgAllTypes.getRepeatedForeignMessageList(); + arrayVal[0] = ForeignMessage.deserialize(''); + msgAllTypes.setRepeatedForeignMessageList(arrayVal); + msgAllTypes.setOptionalUint64(1); + + let s = ''; + s += msgAllTypes.getOptionalString(); + s += msgAllTypes.getOptionalInt32(); + s += msgAllTypes.getOptionalForeignMessage(); + s += msgAllTypes.getOptionalBool(); + // s += msgAllTypes.getOptionalForeignEnum(); + s += msgAllTypes.getOptionalInt64(); + s += msgAllTypes.getOptionalDouble(); + s += msgAllTypes.getRepeatedForeignMessageList(); + s += msgAllTypes.getRepeatedForeignMessageList()[0]; + s += msgAllTypes.getRepeatedForeignMessageList().length; + s += msgAllTypes.getOptionalUint64(); + + s += msgAllTypes.serialize(); + + return s; +} + +goog.global['__hiddenTest'] += accessPopularTypes(); diff --git a/js/experimental/benchmarks/code_size/apps_jspb/popular_types_proto3.js b/js/experimental/benchmarks/code_size/apps_jspb/popular_types_proto3.js new file mode 100644 index 0000000000000..9b804283d1c3d --- /dev/null +++ b/js/experimental/benchmarks/code_size/apps_jspb/popular_types_proto3.js @@ -0,0 +1,53 @@ +/** + * @fileoverview The code size benchmark of apps JSPB for proto3 popular types. + */ +goog.module('protobuf.benchmark.code_size.apps_jspb.PopularTypesProto3'); + +// const ForeignEnum = goog.require('proto.proto3_unittest.ForeignEnum'); +const ForeignMessage = goog.require('proto.proto3_unittest.ForeignMessage'); +const TestAllTypes = goog.require('proto.proto3_unittest.TestAllTypes'); +const {ensureCommonBaseLine} = goog.require('protobuf.benchmark.codeSize.codeSizeBase'); + +ensureCommonBaseLine(); + +/** + * @return {string} + */ +function accessPopularTypes() { + const msgAllTypes = TestAllTypes.deserialize(''); + msgAllTypes.addRepeatedForeignMessage(ForeignMessage.deserialize(''), 1); + [ForeignMessage.deserialize('')].forEach( + (e) => msgAllTypes.addRepeatedForeignMessage(e)); + + msgAllTypes.setOptionalString(''); + msgAllTypes.setOptionalInt32(1); + msgAllTypes.setOptionalForeignMessage(ForeignMessage.deserialize('')); + msgAllTypes.setOptionalBool(true); + // msgAllTypes.setOptionalForeignEnum(ForeignEnum.FOREIGN_BAR); + msgAllTypes.setOptionalInt64(1); + msgAllTypes.setOptionalDouble(1.0); + msgAllTypes.setRepeatedForeignMessageList([ForeignMessage.deserialize('')]); + let arrayVal = msgAllTypes.getRepeatedForeignMessageList(); + arrayVal[0] = ForeignMessage.deserialize(''); + msgAllTypes.setRepeatedForeignMessageList(arrayVal); + msgAllTypes.setOptionalUint64(1); + + let s = ''; + s += msgAllTypes.getOptionalString(); + s += msgAllTypes.getOptionalInt32(); + s += msgAllTypes.getOptionalForeignMessage(); + s += msgAllTypes.getOptionalBool(); + // s += msgAllTypes.getOptionalForeignEnum(); + s += msgAllTypes.getOptionalInt64(); + s += msgAllTypes.getOptionalDouble(); + s += msgAllTypes.getRepeatedForeignMessageList(); + s += msgAllTypes.getRepeatedForeignMessageList()[0]; + s += msgAllTypes.getRepeatedForeignMessageList().length; + s += msgAllTypes.getOptionalUint64(); + + s += msgAllTypes.serialize(); + + return s; +} + +goog.global['__hiddenTest'] += accessPopularTypes(); diff --git a/js/experimental/benchmarks/code_size/code_size_base.js b/js/experimental/benchmarks/code_size/code_size_base.js new file mode 100644 index 0000000000000..04f6a4734f819 --- /dev/null +++ b/js/experimental/benchmarks/code_size/code_size_base.js @@ -0,0 +1,57 @@ +/** + * @fileoverview Ensures types are live that would be live in a typical g3 + * JS program. + * + * Making certain constructs live ensures that we compare against the same + * baseline for all code size benchmarks. This increases the size + * of our benchmarks, but note that this size in a regular app would be + * attributes to other places. + */ +goog.module('protobuf.benchmark.codeSize.codeSizeBase'); + + +/** + * Ensures that the array iterator polyfill is live. + * @return {string} + */ +function useArrayIterator() { + let a = []; + let s = ''; + for (let value of a) { + s += value; + } + return s; +} + +/** + * Ensures that the symbol iterator polyfill is live. + * @return {string} + */ +function useSymbolIterator() { + /** + * @implements {Iterable} + */ + class Foo { + /** @return {!Iterator} */ + [Symbol.iterator]() {} + } + + let foo = new Foo(); + let s = ''; + for (let value of foo) { + s += value; + } + return s; +} + +/** + * Ensures certain base libs are live so we can have an apples to apples + * comparison for code size of different implementations + */ +function ensureCommonBaseLine() { + goog.global['__hiddenTest'] += useArrayIterator(); + goog.global['__hiddenTest'] += useSymbolIterator(); +} + + +exports = {ensureCommonBaseLine}; diff --git a/js/experimental/benchmarks/code_size/kernel/all_types.js b/js/experimental/benchmarks/code_size/kernel/all_types.js new file mode 100644 index 0000000000000..17cc7a6eff7eb --- /dev/null +++ b/js/experimental/benchmarks/code_size/kernel/all_types.js @@ -0,0 +1,227 @@ +/** + * @fileoverview The code size benchmark of binary kernel for accessing all + * types setter and getter. + */ +goog.module('protobuf.benchmark.KernelCodeSizeBenchmarkAllTypes'); + +const ByteString = goog.require('protobuf.ByteString'); +const Int64 = goog.require('protobuf.Int64'); +const Kernel = goog.require('protobuf.runtime.Kernel'); +const TestMessage = goog.require('protobuf.testing.binary.TestMessage'); +const {ensureCommonBaseLine} = goog.require('protobuf.benchmark.codeSize.codeSizeBase'); + +ensureCommonBaseLine(); + + +/** + * @return {string} + */ +function accessAllTypes() { + const message = new TestMessage(Kernel.createEmpty()); + + message.addPackedBoolElement(1, true); + message.addPackedBoolIterable(1, [true]); + message.addUnpackedBoolElement(1, true); + message.addUnpackedBoolIterable(1, [true]); + message.addRepeatedBytesElement(1, ByteString.EMPTY); + message.addRepeatedBytesIterable(1, [ByteString.EMPTY]); + message.addPackedDoubleElement(1, 1.0); + message.addPackedDoubleIterable(1, [1.0]); + message.addUnpackedDoubleElement(1, 1.0); + message.addUnpackedDoubleIterable(1, [1.0]); + message.addPackedFixed32Element(1, 1); + message.addPackedFixed32Iterable(1, [1]); + message.addUnpackedFixed32Element(1, 1); + message.addUnpackedFixed32Iterable(1, [1]); + message.addPackedFixed64Element(1, Int64.fromBits(0, 1)); + message.addPackedFixed64Iterable(1, [Int64.fromBits(0, 1)]); + message.addUnpackedFixed64Element(1, Int64.fromBits(0, 1)); + message.addUnpackedFixed64Iterable(1, [Int64.fromBits(0, 1)]); + message.addPackedFloatElement(1, 1.0); + message.addPackedFloatIterable(1, [1.0]); + message.addUnpackedFloatElement(1, 1.0); + message.addUnpackedFloatIterable(1, [1.0]); + message.addPackedInt32Element(1, 1); + message.addPackedInt32Iterable(1, [1]); + message.addUnpackedInt32Element(1, 1); + message.addUnpackedInt32Iterable(1, [1]); + message.addPackedInt64Element(1, Int64.fromBits(0, 1)); + message.addPackedInt64Iterable(1, [Int64.fromBits(0, 1)]); + message.addUnpackedInt64Element(1, Int64.fromBits(0, 1)); + message.addUnpackedInt64Iterable(1, [Int64.fromBits(0, 1)]); + message.addRepeatedMessageElement(1, message, TestMessage.instanceCreator); + message.addRepeatedMessageIterable(1, [message], TestMessage.instanceCreator); + message.addPackedSfixed32Element(1, 1); + message.addPackedSfixed32Iterable(1, [1]); + message.addUnpackedSfixed32Element(1, 1); + message.addUnpackedSfixed32Iterable(1, [1]); + message.addPackedSfixed64Element(1, Int64.fromBits(0, 1)); + message.addPackedSfixed64Iterable(1, [Int64.fromBits(0, 1)]); + message.addUnpackedSfixed64Element(1, Int64.fromBits(0, 1)); + message.addUnpackedSfixed64Iterable(1, [Int64.fromBits(0, 1)]); + message.addPackedSint32Element(1, 1); + message.addPackedSint32Iterable(1, [1]); + message.addUnpackedSint32Element(1, 1); + message.addUnpackedSint32Iterable(1, [1]); + message.addPackedSint64Element(1, Int64.fromBits(0, 1)); + message.addPackedSint64Iterable(1, [Int64.fromBits(0, 1)]); + message.addUnpackedSint64Element(1, Int64.fromBits(0, 1)); + message.addUnpackedSint64Iterable(1, [Int64.fromBits(0, 1)]); + message.addRepeatedStringElement(1, ''); + message.addRepeatedStringIterable(1, ['']); + message.addPackedUint32Element(1, 1); + message.addPackedUint32Iterable(1, [1]); + message.addUnpackedUint32Element(1, 1); + message.addUnpackedUint32Iterable(1, [1]); + message.addPackedUint64Element(1, Int64.fromBits(0, 1)); + message.addPackedUint64Iterable(1, [Int64.fromBits(0, 1)]); + message.addUnpackedUint64Element(1, Int64.fromBits(0, 1)); + message.addUnpackedUint64Iterable(1, [Int64.fromBits(0, 1)]); + + message.setBool(1, true); + message.setBytes(1, ByteString.EMPTY); + message.setDouble(1, 1.0); + message.setFixed32(1, 1); + message.setFixed64(1, Int64.fromBits(0, 1)); + message.setFloat(1, 1.0); + message.setInt32(1, 1); + message.setInt64(1, Int64.fromBits(0, 1)); + message.setMessage(1, message); + message.setSfixed32(1, 1); + message.setSfixed64(1, Int64.fromBits(0, 1)); + message.setSint32(1, 1); + message.setSint64(1, Int64.fromBits(0, 1)); + message.setString(1, 'abc'); + message.setUint32(1, 1); + message.setUint64(1, Int64.fromBits(0, 1)); + message.setPackedBoolElement(1, 0, true); + message.setPackedBoolIterable(1, [true]); + message.setUnpackedBoolElement(1, 0, true); + message.setUnpackedBoolIterable(1, [true]); + message.setRepeatedBytesElement(1, 0, ByteString.EMPTY); + message.setRepeatedBytesIterable(1, [ByteString.EMPTY]); + message.setPackedDoubleElement(1, 0, 1.0); + message.setPackedDoubleIterable(1, [1.0]); + message.setUnpackedDoubleElement(1, 0, 1.0); + message.setUnpackedDoubleIterable(1, [1.0]); + message.setPackedFixed32Element(1, 0, 1); + message.setPackedFixed32Iterable(1, [1]); + message.setUnpackedFixed32Element(1, 0, 1); + message.setUnpackedFixed32Iterable(1, [1]); + message.setPackedFixed64Element(1, 0, Int64.fromBits(0, 1)); + message.setPackedFixed64Iterable(1, [Int64.fromBits(0, 1)]); + message.setUnpackedFixed64Element(1, 0, Int64.fromBits(0, 1)); + message.setUnpackedFixed64Iterable(1, [Int64.fromBits(0, 1)]); + message.setPackedFloatElement(1, 0, 1.0); + message.setPackedFloatIterable(1, [1.0]); + message.setUnpackedFloatElement(1, 0, 1.0); + message.setUnpackedFloatIterable(1, [1.0]); + message.setPackedInt32Element(1, 0, 1); + message.setPackedInt32Iterable(1, [1]); + message.setUnpackedInt32Element(1, 0, 1); + message.setUnpackedInt32Iterable(1, [1]); + message.setPackedInt64Element(1, 0, Int64.fromBits(0, 1)); + message.setPackedInt64Iterable(1, [Int64.fromBits(0, 1)]); + message.setUnpackedInt64Element(1, 0, Int64.fromBits(0, 1)); + message.setUnpackedInt64Iterable(1, [Int64.fromBits(0, 1)]); + message.setRepeatedMessageElement(1, message, TestMessage.instanceCreator, 0); + message.setRepeatedMessageIterable(1, [message]); + message.setPackedSfixed32Element(1, 0, 1); + message.setPackedSfixed32Iterable(1, [1]); + message.setUnpackedSfixed32Element(1, 0, 1); + message.setUnpackedSfixed32Iterable(1, [1]); + message.setPackedSfixed64Element(1, 0, Int64.fromBits(0, 1)); + message.setPackedSfixed64Iterable(1, [Int64.fromBits(0, 1)]); + message.setUnpackedSfixed64Element(1, 0, Int64.fromBits(0, 1)); + message.setUnpackedSfixed64Iterable(1, [Int64.fromBits(0, 1)]); + message.setRepeatedStringElement(1, 0, ''); + message.setRepeatedStringIterable(1, ['']); + message.setPackedSint32Element(1, 0, 1); + message.setPackedSint32Iterable(1, [1]); + message.setUnpackedSint32Element(1, 0, 1); + message.setUnpackedSint32Iterable(1, [1]); + message.setPackedSint64Element(1, 0, Int64.fromBits(0, 1)); + message.setPackedSint64Iterable(1, [Int64.fromBits(0, 1)]); + message.setUnpackedSint64Element(1, 0, Int64.fromBits(0, 1)); + message.setUnpackedSint64Iterable(1, [Int64.fromBits(0, 1)]); + message.setPackedUint32Element(1, 0, 1); + message.setPackedUint32Iterable(1, [1]); + message.setUnpackedUint32Element(1, 0, 1); + message.setUnpackedUint32Iterable(1, [1]); + message.setPackedUint64Element(1, 0, Int64.fromBits(0, 1)); + message.setPackedUint64Iterable(1, [Int64.fromBits(0, 1)]); + message.setUnpackedUint64Element(1, 0, Int64.fromBits(0, 1)); + message.setUnpackedUint64Iterable(1, [Int64.fromBits(0, 1)]); + + let s = ''; + s += message.getBoolWithDefault(1); + s += message.getBytesWithDefault(1); + s += message.getDoubleWithDefault(1); + s += message.getFixed32WithDefault(1); + s += message.getFixed64WithDefault(1); + s += message.getFloatWithDefault(1); + s += message.getInt32WithDefault(1); + s += message.getInt64WithDefault(1); + s += message.getMessage(1, TestMessage.instanceCreator); + s += message.getSfixed32WithDefault(1); + s += message.getSfixed64WithDefault(1); + s += message.getSint32WithDefault(1); + s += message.getSint64WithDefault(1); + s += message.getStringWithDefault(1); + s += message.getUint32WithDefault(1); + s += message.getUint64WithDefault(1); + s += message.getRepeatedBoolElement(1, 0); + s += message.getRepeatedBoolIterable(1); + s += message.getRepeatedBoolSize(1); + s += message.getRepeatedBytesElement(1, 0); + s += message.getRepeatedBytesIterable(1); + s += message.getRepeatedBytesSize(1); + s += message.getRepeatedDoubleElement(1, 0); + s += message.getRepeatedDoubleIterable(1); + s += message.getRepeatedDoubleSize(1); + s += message.getRepeatedFixed32Element(1, 0); + s += message.getRepeatedFixed32Iterable(1); + s += message.getRepeatedFixed32Size(1); + s += message.getRepeatedFixed64Element(1, 0); + s += message.getRepeatedFixed64Iterable(1); + s += message.getRepeatedFixed64Size(1); + s += message.getRepeatedFloatElement(1, 0); + s += message.getRepeatedFloatIterable(1); + s += message.getRepeatedFloatSize(1); + s += message.getRepeatedInt32Element(1, 0); + s += message.getRepeatedInt32Iterable(1); + s += message.getRepeatedInt32Size(1); + s += message.getRepeatedInt64Element(1, 0); + s += message.getRepeatedInt64Iterable(1); + s += message.getRepeatedInt64Size(1); + s += message.getRepeatedMessageElement(1, TestMessage.instanceCreator, 0); + s += message.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + s += message.getRepeatedMessageSize(1, TestMessage.instanceCreator); + s += message.getRepeatedSfixed32Element(1, 0); + s += message.getRepeatedSfixed32Iterable(1); + s += message.getRepeatedSfixed32Size(1); + s += message.getRepeatedSfixed64Element(1, 0); + s += message.getRepeatedSfixed64Iterable(1); + s += message.getRepeatedSfixed64Size(1); + s += message.getRepeatedSint32Element(1, 0); + s += message.getRepeatedSint32Iterable(1); + s += message.getRepeatedSint32Size(1); + s += message.getRepeatedSint64Element(1, 0); + s += message.getRepeatedSint64Iterable(1); + s += message.getRepeatedSint64Size(1); + s += message.getRepeatedStringElement(1, 0); + s += message.getRepeatedStringIterable(1); + s += message.getRepeatedStringSize(1); + s += message.getRepeatedUint32Element(1, 0); + s += message.getRepeatedUint32Iterable(1); + s += message.getRepeatedUint32Size(1); + s += message.getRepeatedUint64Element(1, 0); + s += message.getRepeatedUint64Iterable(1); + s += message.getRepeatedUint64Size(1); + + s += message.serialize(); + + return s; +} + +goog.global['__hiddenTest'] += accessAllTypes(); diff --git a/js/experimental/benchmarks/code_size/kernel/popular_types.js b/js/experimental/benchmarks/code_size/kernel/popular_types.js new file mode 100644 index 0000000000000..90e1792f67670 --- /dev/null +++ b/js/experimental/benchmarks/code_size/kernel/popular_types.js @@ -0,0 +1,68 @@ +/** + * @fileoverview The code size benchmark of binary kernel for accessing all + * popular types setter and getter. + * + * The types are those whose usage are more than 1%: + * + * ('STRING__LABEL_OPTIONAL', '29.7214%') + * ('INT32__LABEL_OPTIONAL', '17.7277%') + * ('MESSAGE__LABEL_OPTIONAL', '15.6462%') + * ('BOOL__LABEL_OPTIONAL', '13.0038%') + * ('ENUM__LABEL_OPTIONAL', '11.4466%') + * ('INT64__LABEL_OPTIONAL', '3.2198%') + * ('DOUBLE__LABEL_OPTIONAL', '1.357%') + * ('MESSAGE__LABEL_REPEATED', '1.2775%') + * ('FIXED32__LABEL_REQUIRED', '1.2%') + * ('UINT64__LABEL_OPTIONAL', '1.1771%') + * ('STRING__LABEL_REQUIRED', '1.0785%') + * + */ +goog.module('protobuf.benchmark.KernelCodeSizeBenchmarkPopularTypes'); + +const Int64 = goog.require('protobuf.Int64'); +const Kernel = goog.require('protobuf.runtime.Kernel'); +const TestMessage = goog.require('protobuf.testing.binary.TestMessage'); +const {ensureCommonBaseLine} = goog.require('protobuf.benchmark.codeSize.codeSizeBase'); + +ensureCommonBaseLine(); + + +/** + * @return {string} + */ +function accessAllTypes() { + const message = new TestMessage(Kernel.createEmpty()); + + message.addRepeatedMessageElement(1, message, TestMessage.instanceCreator); + message.addRepeatedMessageIterable(1, [message], TestMessage.instanceCreator); + + message.setString(1, 'abc'); + message.setInt32(1, 1); + message.setMessage(1, message); + message.setBool(1, true); + message.setInt64(1, Int64.fromBits(0, 1)); + message.setDouble(1, 1.0); + message.setRepeatedMessageElement(1, message, TestMessage.instanceCreator, 0); + message.setRepeatedMessageIterable(1, [message]); + message.setUint64(1, Int64.fromBits(0, 1)); + + + let s = ''; + s += message.getStringWithDefault(1); + s += message.getInt32WithDefault(1); + s += message.getMessage(1, TestMessage.instanceCreator); + s += message.getMessageOrNull(1, TestMessage.instanceCreator); + s += message.getBoolWithDefault(1); + s += message.getInt64WithDefault(1); + s += message.getDoubleWithDefault(1); + s += message.getRepeatedMessageElement(1, TestMessage.instanceCreator, 0); + s += message.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + s += message.getRepeatedMessageSize(1, TestMessage.instanceCreator); + s += message.getUint64WithDefault(1); + + s += message.serialize(); + + return s; +} + +goog.global['__hiddenTest'] += accessAllTypes(); diff --git a/js/experimental/runtime/bytestring.js b/js/experimental/runtime/bytestring.js new file mode 100644 index 0000000000000..d6af5f148ed0d --- /dev/null +++ b/js/experimental/runtime/bytestring.js @@ -0,0 +1,183 @@ +/** + * @fileoverview Provides ByteString as a basic data type for protos. + */ +goog.module('protobuf.ByteString'); + +const base64 = goog.require('goog.crypt.base64'); +const {arrayBufferSlice, cloneArrayBufferView, hashUint8Array, uint8ArrayEqual} = goog.require('protobuf.binary.typedArrays'); + +/** + * Immutable sequence of bytes. + * + * Bytes can be obtained as an ArrayBuffer or a base64 encoded string. + * @final + */ +class ByteString { + /** + * @param {?Uint8Array} bytes + * @param {?string} base64 + * @private + */ + constructor(bytes, base64) { + /** @private {?Uint8Array}*/ + this.bytes_ = bytes; + /** @private {?string} */ + this.base64_ = base64; + /** @private {number} */ + this.hashCode_ = 0; + } + + /** + * Constructs a ByteString instance from a base64 string. + * @param {string} value + * @return {!ByteString} + */ + static fromBase64String(value) { + if (value == null) { + throw new Error('value must not be null'); + } + return new ByteString(/* bytes */ null, value); + } + + /** + * Constructs a ByteString from an array buffer. + * @param {!ArrayBuffer} bytes + * @param {number=} start + * @param {number=} end + * @return {!ByteString} + */ + static fromArrayBuffer(bytes, start = 0, end = undefined) { + return new ByteString( + new Uint8Array(arrayBufferSlice(bytes, start, end)), /* base64 */ null); + } + + /** + * Constructs a ByteString from any ArrayBufferView (e.g. DataView, + * TypedArray, Uint8Array, etc.). + * @param {!ArrayBufferView} bytes + * @return {!ByteString} + */ + static fromArrayBufferView(bytes) { + return new ByteString(cloneArrayBufferView(bytes), /* base64 */ null); + } + + /** + * Constructs a ByteString from an Uint8Array. DON'T MODIFY the underlying + * ArrayBuffer, since the ByteString directly uses it without making a copy. + * + * This method exists so that internal APIs can construct a ByteString without + * paying the penalty of copying an ArrayBuffer when that ArrayBuffer is not + * supposed to change. It is exposed to a limited number of internal classes + * through bytestring_internal.js. + * + * @param {!Uint8Array} bytes + * @return {!ByteString} + * @package + */ + static fromUint8ArrayUnsafe(bytes) { + return new ByteString(bytes, /* base64 */ null); + } + + /** + * Returns this ByteString as an ArrayBuffer. + * @return {!ArrayBuffer} + */ + toArrayBuffer() { + const bytes = this.ensureBytes_(); + return arrayBufferSlice( + bytes.buffer, bytes.byteOffset, bytes.byteOffset + bytes.byteLength); + } + + /** + * Returns this ByteString as an Uint8Array. DON'T MODIFY the returned array, + * since the ByteString holds the reference to the same array. + * + * This method exists so that internal APIs can get contents of a ByteString + * without paying the penalty of copying an ArrayBuffer. It is exposed to a + * limited number of internal classes through bytestring_internal.js. + * @return {!Uint8Array} + * @package + */ + toUint8ArrayUnsafe() { + return this.ensureBytes_(); + } + + /** + * Returns this ByteString as a base64 encoded string. + * @return {string} + */ + toBase64String() { + return this.ensureBase64String_(); + } + + /** + * Returns true for Bytestrings that contain identical values. + * @param {*} other + * @return {boolean} + */ + equals(other) { + if (this === other) { + return true; + } + + if (!(other instanceof ByteString)) { + return false; + } + + const otherByteString = /** @type {!ByteString} */ (other); + return uint8ArrayEqual(this.ensureBytes_(), otherByteString.ensureBytes_()); + } + + /** + * Returns a number (int32) that is suitable for using in hashed structures. + * @return {number} + */ + hashCode() { + if (this.hashCode_ == 0) { + this.hashCode_ = hashUint8Array(this.ensureBytes_()); + } + return this.hashCode_; + } + + /** + * Returns true if the bytestring is empty. + * @return {boolean} + */ + isEmpty() { + if (this.bytes_ != null && this.bytes_.byteLength == 0) { + return true; + } + if (this.base64_ != null && this.base64_.length == 0) { + return true; + } + return false; + } + + /** + * @return {!Uint8Array} + * @private + */ + ensureBytes_() { + if (this.bytes_) { + return this.bytes_; + } + return this.bytes_ = base64.decodeStringToUint8Array( + /** @type {string} */ (this.base64_)); + } + + /** + * @return {string} + * @private + */ + ensureBase64String_() { + if (this.base64_ == null) { + this.base64_ = base64.encodeByteArray(this.bytes_); + } + return this.base64_; + } +} + +/** @const {!ByteString} */ +ByteString.EMPTY = new ByteString(new Uint8Array(0), null); + +exports = ByteString; diff --git a/js/experimental/runtime/bytestring_internal.js b/js/experimental/runtime/bytestring_internal.js new file mode 100644 index 0000000000000..2ea3f609b2dac --- /dev/null +++ b/js/experimental/runtime/bytestring_internal.js @@ -0,0 +1,33 @@ +/** + * @fileoverview Exposes internal only functions for ByteString. The + * corresponding BUILD rule restricts access to this file to only the binary + * kernel and APIs directly using the binary kernel. + */ +goog.module('protobuf.byteStringInternal'); + +const ByteString = goog.require('protobuf.ByteString'); + +/** + * Constructs a ByteString from an Uint8Array. DON'T MODIFY the underlying + * ArrayBuffer, since the ByteString directly uses it without making a copy. + * @param {!Uint8Array} bytes + * @return {!ByteString} + */ +function byteStringFromUint8ArrayUnsafe(bytes) { + return ByteString.fromUint8ArrayUnsafe(bytes); +} + +/** + * Returns this ByteString as an Uint8Array. DON'T MODIFY the returned array, + * since the ByteString holds the reference to the same array. + * @param {!ByteString} bytes + * @return {!Uint8Array} + */ +function byteStringToUint8ArrayUnsafe(bytes) { + return bytes.toUint8ArrayUnsafe(); +} + +exports = { + byteStringFromUint8ArrayUnsafe, + byteStringToUint8ArrayUnsafe, +}; diff --git a/js/experimental/runtime/bytestring_test.js b/js/experimental/runtime/bytestring_test.js new file mode 100644 index 0000000000000..b9928b6e7b8c9 --- /dev/null +++ b/js/experimental/runtime/bytestring_test.js @@ -0,0 +1,277 @@ +goog.module('proto.im.integration.ByteStringFieldsTest'); +goog.setTestOnly(); + +const ByteString = goog.require('protobuf.ByteString'); +const {arrayBufferSlice} = goog.require('protobuf.binary.typedArrays'); + +const /** !ArrayBuffer */ TEST_BYTES = new Uint8Array([1, 2, 3, 4]).buffer; +const /** !ByteString */ TEST_STRING = ByteString.fromArrayBuffer(TEST_BYTES); +const /** !ArrayBuffer */ PREFIXED_TEST_BYTES = + new Uint8Array([0, 1, 2, 3, 4]).buffer; +const /** string */ HALLO_IN_BASE64 = 'aGFsbG8='; +const /** string */ HALLO_IN_BASE64_WITH_SPACES = 'a G F s b G 8='; +const /** !ArrayBufferView */ BYTES_WITH_HALLO = new Uint8Array([ + 'h'.charCodeAt(0), + 'a'.charCodeAt(0), + 'l'.charCodeAt(0), + 'l'.charCodeAt(0), + 'o'.charCodeAt(0), +]); + +describe('ByteString does', () => { + it('create bytestring from buffer', () => { + const byteString = + ByteString.fromArrayBuffer(arrayBufferSlice(TEST_BYTES, 0)); + expect(byteString.toArrayBuffer()).toEqual(TEST_BYTES); + expect(byteString.toUint8ArrayUnsafe()).toEqual(new Uint8Array(TEST_BYTES)); + }); + + it('create bytestring from ArrayBufferView', () => { + const byteString = + ByteString.fromArrayBufferView(new Uint8Array(TEST_BYTES)); + expect(byteString.toArrayBuffer()).toEqual(TEST_BYTES); + expect(byteString.toUint8ArrayUnsafe()).toEqual(new Uint8Array(TEST_BYTES)); + }); + + it('create bytestring from subarray', () => { + const byteString = ByteString.fromArrayBufferView( + new Uint8Array(TEST_BYTES, /* offset */ 1, /* length */ 2)); + const expected = new Uint8Array([2, 3]); + expect(new Uint8Array(byteString.toArrayBuffer())).toEqual(expected); + expect(byteString.toUint8ArrayUnsafe()).toEqual(expected); + }); + + it('create bytestring from Uint8Array (unsafe)', () => { + const array = new Uint8Array(TEST_BYTES); + const byteString = ByteString.fromUint8ArrayUnsafe(array); + expect(byteString.toArrayBuffer()).toEqual(array.buffer); + expect(byteString.toUint8ArrayUnsafe()).toBe(array); + }); + + it('create bytestring from base64 string', () => { + const byteString = ByteString.fromBase64String(HALLO_IN_BASE64); + expect(byteString.toBase64String()).toEqual(HALLO_IN_BASE64); + expect(byteString.toArrayBuffer()).toEqual(BYTES_WITH_HALLO.buffer); + expect(byteString.toUint8ArrayUnsafe()).toEqual(BYTES_WITH_HALLO); + }); + + it('preserve immutability if underlying buffer changes: from buffer', () => { + const buffer = new ArrayBuffer(4); + const array = new Uint8Array(buffer); + array[0] = 1; + array[1] = 2; + array[2] = 3; + array[3] = 4; + + const byteString = ByteString.fromArrayBuffer(buffer); + const otherBuffer = byteString.toArrayBuffer(); + + expect(otherBuffer).not.toBe(buffer); + expect(new Uint8Array(otherBuffer)).toEqual(array); + + // modify the original buffer + array[0] = 5; + // Are we still returning the original bytes? + expect(new Uint8Array(byteString.toArrayBuffer())).toEqual(new Uint8Array([ + 1, 2, 3, 4 + ])); + }); + + it('preserve immutability if underlying buffer changes: from ArrayBufferView', + () => { + const buffer = new ArrayBuffer(4); + const array = new Uint8Array(buffer); + array[0] = 1; + array[1] = 2; + array[2] = 3; + array[3] = 4; + + const byteString = ByteString.fromArrayBufferView(array); + const otherBuffer = byteString.toArrayBuffer(); + + expect(otherBuffer).not.toBe(buffer); + expect(new Uint8Array(otherBuffer)).toEqual(array); + + // modify the original buffer + array[0] = 5; + // Are we still returning the original bytes? + expect(new Uint8Array(byteString.toArrayBuffer())) + .toEqual(new Uint8Array([1, 2, 3, 4])); + }); + + it('mutate if underlying buffer changes: from Uint8Array (unsafe)', () => { + const buffer = new ArrayBuffer(4); + const array = new Uint8Array(buffer); + array[0] = 1; + array[1] = 2; + array[2] = 3; + array[3] = 4; + + const byteString = ByteString.fromUint8ArrayUnsafe(array); + const otherBuffer = byteString.toArrayBuffer(); + + expect(otherBuffer).not.toBe(buffer); + expect(new Uint8Array(otherBuffer)).toEqual(array); + + // modify the original buffer + array[0] = 5; + // We are no longer returning the original bytes + expect(new Uint8Array(byteString.toArrayBuffer())).toEqual(new Uint8Array([ + 5, 2, 3, 4 + ])); + }); + + it('preserve immutability for returned buffers: toArrayBuffer', () => { + const byteString = ByteString.fromArrayBufferView(new Uint8Array(4)); + const buffer1 = byteString.toArrayBuffer(); + const buffer2 = byteString.toArrayBuffer(); + + expect(buffer1).toEqual(buffer2); + + const array1 = new Uint8Array(buffer1); + array1[0] = 1; + + expect(buffer1).not.toEqual(buffer2); + }); + + it('does not preserve immutability for returned buffers: toUint8ArrayUnsafe', + () => { + const byteString = ByteString.fromUint8ArrayUnsafe(new Uint8Array(4)); + const array1 = byteString.toUint8ArrayUnsafe(); + const array2 = byteString.toUint8ArrayUnsafe(); + + expect(array1).toEqual(array2); + array1[0] = 1; + + expect(array1).toEqual(array2); + }); + + it('throws when created with null ArrayBufferView', () => { + expect( + () => ByteString.fromArrayBufferView( + /** @type {!ArrayBufferView} */ (/** @type{*} */ (null)))) + .toThrow(); + }); + + it('throws when created with null buffer', () => { + expect( + () => ByteString.fromBase64String( + /** @type {string} */ (/** @type{*} */ (null)))) + .toThrow(); + }); + + it('convert base64 to ArrayBuffer', () => { + const other = ByteString.fromBase64String(HALLO_IN_BASE64); + expect(BYTES_WITH_HALLO).toEqual(new Uint8Array(other.toArrayBuffer())); + }); + + it('convert base64 with spaces to ArrayBuffer', () => { + const other = ByteString.fromBase64String(HALLO_IN_BASE64_WITH_SPACES); + expect(new Uint8Array(other.toArrayBuffer())).toEqual(BYTES_WITH_HALLO); + }); + + it('convert bytes to base64', () => { + const other = ByteString.fromArrayBufferView(BYTES_WITH_HALLO); + expect(HALLO_IN_BASE64).toEqual(other.toBase64String()); + }); + + it('equal empty bytetring', () => { + const empty = ByteString.fromArrayBuffer(new ArrayBuffer(0)); + expect(ByteString.EMPTY.equals(empty)).toEqual(true); + }); + + it('equal empty bytestring constructed from ArrayBufferView', () => { + const empty = ByteString.fromArrayBufferView(new Uint8Array(0)); + expect(ByteString.EMPTY.equals(empty)).toEqual(true); + }); + + it('equal empty bytestring constructed from Uint8Array (unsafe)', () => { + const empty = ByteString.fromUint8ArrayUnsafe(new Uint8Array(0)); + expect(ByteString.EMPTY.equals(empty)).toEqual(true); + }); + + it('equal empty bytestring constructed from base64', () => { + const empty = ByteString.fromBase64String(''); + expect(ByteString.EMPTY.equals(empty)).toEqual(true); + }); + + it('equal other instance', () => { + const other = ByteString.fromArrayBuffer(arrayBufferSlice(TEST_BYTES, 0)); + expect(TEST_STRING.equals(other)).toEqual(true); + }); + + it('not equal different instance', () => { + const other = + ByteString.fromArrayBuffer(new Uint8Array([1, 2, 3, 4, 5]).buffer); + expect(TEST_STRING.equals(other)).toEqual(false); + }); + + it('equal other instance constructed from ArrayBufferView', () => { + const other = + ByteString.fromArrayBufferView(new Uint8Array(PREFIXED_TEST_BYTES, 1)); + expect(TEST_STRING.equals(other)).toEqual(true); + }); + + it('not equal different instance constructed from ArrayBufferView', () => { + const other = + ByteString.fromArrayBufferView(new Uint8Array([1, 2, 3, 4, 5])); + expect(TEST_STRING.equals(other)).toEqual(false); + }); + + it('equal other instance constructed from Uint8Array (unsafe)', () => { + const other = + ByteString.fromUint8ArrayUnsafe(new Uint8Array(PREFIXED_TEST_BYTES, 1)); + expect(TEST_STRING.equals(other)).toEqual(true); + }); + + it('not equal different instance constructed from Uint8Array (unsafe)', + () => { + const other = + ByteString.fromUint8ArrayUnsafe(new Uint8Array([1, 2, 3, 4, 5])); + expect(TEST_STRING.equals(other)).toEqual(false); + }); + + it('have same hashcode for empty bytes', () => { + const empty = ByteString.fromArrayBuffer(new ArrayBuffer(0)); + expect(ByteString.EMPTY.hashCode()).toEqual(empty.hashCode()); + }); + + it('have same hashcode for test bytes', () => { + const other = ByteString.fromArrayBuffer(arrayBufferSlice(TEST_BYTES, 0)); + expect(TEST_STRING.hashCode()).toEqual(other.hashCode()); + }); + + it('have same hashcode for test bytes', () => { + const other = ByteString.fromArrayBufferView( + new Uint8Array(arrayBufferSlice(TEST_BYTES, 0))); + expect(TEST_STRING.hashCode()).toEqual(other.hashCode()); + }); + + it('have same hashcode for different instance constructed with base64', + () => { + const other = ByteString.fromBase64String(HALLO_IN_BASE64); + expect(ByteString.fromArrayBufferView(BYTES_WITH_HALLO).hashCode()) + .toEqual(other.hashCode()); + }); + + it('preserves the length of a Uint8Array', () => { + const original = new Uint8Array([105, 183, 51, 251, 253, 118, 247]); + const afterByteString = new Uint8Array( + ByteString.fromArrayBufferView(original).toArrayBuffer()); + expect(afterByteString).toEqual(original); + }); + + it('preserves the length of a base64 value', () => { + const expected = new Uint8Array([105, 183, 51, 251, 253, 118, 247]); + const afterByteString = new Uint8Array( + ByteString.fromBase64String('abcz+/129w').toArrayBuffer()); + expect(afterByteString).toEqual(expected); + }); + + it('preserves the length of a base64 value with padding', () => { + const expected = new Uint8Array([105, 183, 51, 251, 253, 118, 247]); + const afterByteString = new Uint8Array( + ByteString.fromBase64String('abcz+/129w==').toArrayBuffer()); + expect(afterByteString).toEqual(expected); + }); +}); diff --git a/js/experimental/runtime/int64.js b/js/experimental/runtime/int64.js new file mode 100644 index 0000000000000..45585b752519f --- /dev/null +++ b/js/experimental/runtime/int64.js @@ -0,0 +1,403 @@ +/** + * @fileoverview Protobufs Int64 representation. + */ +goog.module('protobuf.Int64'); + +const Long = goog.require('goog.math.Long'); +const {assert} = goog.require('goog.asserts'); + +/** + * A container for protobufs Int64/Uint64 data type. + * @final + */ +class Int64 { + /** @return {!Int64} */ + static getZero() { + return ZERO; + } + + /** @return {!Int64} */ + static getMinValue() { + return MIN_VALUE; + } + + /** @return {!Int64} */ + static getMaxValue() { + return MAX_VALUE; + } + + /** + * Constructs a Int64 given two 32 bit numbers + * @param {number} lowBits + * @param {number} highBits + * @return {!Int64} + */ + static fromBits(lowBits, highBits) { + return new Int64(lowBits, highBits); + } + + /** + * Constructs an Int64 from a signed 32 bit number. + * @param {number} value + * @return {!Int64} + */ + static fromInt(value) { + // TODO: Use our own checking system here. + assert(value === (value | 0), 'value should be a 32-bit integer'); + // Right shift 31 bits so all high bits are equal to the sign bit. + // Note: cannot use >> 32, because (1 >> 32) = 1 (!). + const signExtendedHighBits = value >> 31; + return new Int64(value, signExtendedHighBits); + } + + /** + * Constructs an Int64 from a number (over 32 bits). + * @param {number} value + * @return {!Int64} + */ + static fromNumber(value) { + if (value > 0) { + return new Int64(value, value / TWO_PWR_32_DBL); + } else if (value < 0) { + return negate(-value, -value / TWO_PWR_32_DBL); + } + return ZERO; + } + + /** + * Construct an Int64 from a signed decimal string. + * @param {string} value + * @return {!Int64} + */ + static fromDecimalString(value) { + // TODO: Use our own checking system here. + assert(value.length > 0); + // The basic Number conversion loses precision, but we can use it for + // a quick validation that the format is correct and it is an integer. + assert(Math.floor(Number(value)).toString().length == value.length); + return decimalStringToInt64(value); + } + + /** + * Construct an Int64 from a signed hexadecimal string. + * @param {string} value + * @return {!Int64} + */ + static fromHexString(value) { + // TODO: Use our own checking system here. + assert(value.length > 0); + assert(value.slice(0, 2) == '0x' || value.slice(0, 3) == '-0x'); + const minus = value[0] === '-'; + // Strip the 0x or -0x prefix. + value = value.slice(minus ? 3 : 2); + const lowBits = parseInt(value.slice(-8), 16); + const highBits = parseInt(value.slice(-16, -8) || '', 16); + return (minus ? negate : Int64.fromBits)(lowBits, highBits); + } + + // Note to the reader: + // goog.math.Long suffers from a code size issue. JsCompiler almost always + // considers toString methods to be alive in a program. So if you are + // constructing a Long instance the toString method is assumed to be live. + // Unfortunately Long's toString method makes a large chunk of code alive + // of the entire class adding 1.3kB (gzip) of extra code size. + // Callers that are sensitive to code size and are not using Long already + // should avoid calling this method. + /** + * Creates an Int64 instance from a Long value. + * @param {!Long} value + * @return {!Int64} + */ + static fromLong(value) { + return new Int64(value.getLowBits(), value.getHighBits()); + } + + /** + * @param {number} lowBits + * @param {number} highBits + * @private + */ + constructor(lowBits, highBits) { + /** @const @private {number} */ + this.lowBits_ = lowBits | 0; + /** @const @private {number} */ + this.highBits_ = highBits | 0; + } + + /** + * Returns the int64 value as a JavaScript number. This will lose precision + * if the number is outside of the safe range for JavaScript of 53 bits + * precision. + * @return {number} + */ + asNumber() { + const result = this.highBits_ * TWO_PWR_32_DBL + this.getLowBitsUnsigned(); + // TODO: Use our own checking system here. + assert( + Number.isSafeInteger(result), 'conversion to number loses precision.'); + return result; + } + + // Note to the reader: + // goog.math.Long suffers from a code size issue. JsCompiler almost always + // considers toString methods to be alive in a program. So if you are + // constructing a Long instance the toString method is assumed to be live. + // Unfortunately Long's toString method makes a large chunk of code alive + // of the entire class adding 1.3kB (gzip) of extra code size. + // Callers that are sensitive to code size and are not using Long already + // should avoid calling this method. + /** @return {!Long} */ + asLong() { + return Long.fromBits(this.lowBits_, this.highBits_); + } + + /** @return {number} Signed 32-bit integer value. */ + getLowBits() { + return this.lowBits_; + } + + /** @return {number} Signed 32-bit integer value. */ + getHighBits() { + return this.highBits_; + } + + /** @return {number} Unsigned 32-bit integer. */ + getLowBitsUnsigned() { + return this.lowBits_ >>> 0; + } + + /** @return {number} Unsigned 32-bit integer. */ + getHighBitsUnsigned() { + return this.highBits_ >>> 0; + } + + /** @return {string} */ + toSignedDecimalString() { + return joinSignedDecimalString(this); + } + + /** @return {string} */ + toUnsignedDecimalString() { + return joinUnsignedDecimalString(this); + } + + /** + * Returns an unsigned hexadecimal string representation of the Int64. + * @return {string} + */ + toHexString() { + let nibbles = new Array(16); + let lowBits = this.lowBits_; + let highBits = this.highBits_; + for (let highIndex = 7, lowIndex = 15; lowIndex > 7; + highIndex--, lowIndex--) { + nibbles[highIndex] = HEX_DIGITS[highBits & 0xF]; + nibbles[lowIndex] = HEX_DIGITS[lowBits & 0xF]; + highBits = highBits >>> 4; + lowBits = lowBits >>> 4; + } + // Always leave the least significant hex digit. + while (nibbles.length > 1 && nibbles[0] == '0') { + nibbles.shift(); + } + return `0x${nibbles.join('')}`; + } + + /** + * @param {*} other object to compare against. + * @return {boolean} Whether this Int64 equals the other. + */ + equals(other) { + if (this === other) { + return true; + } + if (!(other instanceof Int64)) { + return false; + } + // Compare low parts first as there is higher chance they are different. + const otherInt64 = /** @type{!Int64} */ (other); + return (this.lowBits_ === otherInt64.lowBits_) && + (this.highBits_ === otherInt64.highBits_); + } + + /** + * Returns a number (int32) that is suitable for using in hashed structures. + * @return {number} + */ + hashCode() { + return (31 * this.lowBits_ + 17 * this.highBits_) | 0; + } +} + +/** + * Losslessly converts a 64-bit unsigned integer in 32:32 split representation + * into a decimal string. + * @param {!Int64} int64 + * @return {string} The binary number represented as a string. + */ +const joinUnsignedDecimalString = (int64) => { + const lowBits = int64.getLowBitsUnsigned(); + const highBits = int64.getHighBitsUnsigned(); + // Skip the expensive conversion if the number is small enough to use the + // built-in conversions. + // Number.MAX_SAFE_INTEGER = 0x001FFFFF FFFFFFFF, thus any number with + // highBits <= 0x1FFFFF can be safely expressed with a double and retain + // integer precision. + // Proven by: Number.isSafeInteger(0x1FFFFF * 2**32 + 0xFFFFFFFF) == true. + if (highBits <= 0x1FFFFF) { + return String(TWO_PWR_32_DBL * highBits + lowBits); + } + + // What this code is doing is essentially converting the input number from + // base-2 to base-1e7, which allows us to represent the 64-bit range with + // only 3 (very large) digits. Those digits are then trivial to convert to + // a base-10 string. + + // The magic numbers used here are - + // 2^24 = 16777216 = (1,6777216) in base-1e7. + // 2^48 = 281474976710656 = (2,8147497,6710656) in base-1e7. + + // Split 32:32 representation into 16:24:24 representation so our + // intermediate digits don't overflow. + const low = lowBits & LOW_24_BITS; + const mid = ((lowBits >>> 24) | (highBits << 8)) & LOW_24_BITS; + const high = (highBits >> 16) & LOW_16_BITS; + + // Assemble our three base-1e7 digits, ignoring carries. The maximum + // value in a digit at this step is representable as a 48-bit integer, which + // can be stored in a 64-bit floating point number. + let digitA = low + (mid * 6777216) + (high * 6710656); + let digitB = mid + (high * 8147497); + let digitC = (high * 2); + + // Apply carries from A to B and from B to C. + const base = 10000000; + if (digitA >= base) { + digitB += Math.floor(digitA / base); + digitA %= base; + } + + if (digitB >= base) { + digitC += Math.floor(digitB / base); + digitB %= base; + } + + // If digitC is 0, then we should have returned in the trivial code path + // at the top for non-safe integers. Given this, we can assume both digitB + // and digitA need leading zeros. + // TODO: Use our own checking system here. + assert(digitC); + return digitC + decimalFrom1e7WithLeadingZeros(digitB) + + decimalFrom1e7WithLeadingZeros(digitA); +}; + +/** + * @param {number} digit1e7 Number < 1e7 + * @return {string} Decimal representation of digit1e7 with leading zeros. + */ +const decimalFrom1e7WithLeadingZeros = (digit1e7) => { + const partial = String(digit1e7); + return '0000000'.slice(partial.length) + partial; +}; + +/** + * Losslessly converts a 64-bit signed integer in 32:32 split representation + * into a decimal string. + * @param {!Int64} int64 + * @return {string} The binary number represented as a string. + */ +const joinSignedDecimalString = (int64) => { + // If we're treating the input as a signed value and the high bit is set, do + // a manual two's complement conversion before the decimal conversion. + const negative = (int64.getHighBits() & 0x80000000); + if (negative) { + int64 = negate(int64.getLowBits(), int64.getHighBits()); + } + + const result = joinUnsignedDecimalString(int64); + return negative ? '-' + result : result; +}; + +/** + * @param {string} dec + * @return {!Int64} + */ +const decimalStringToInt64 = (dec) => { + // Check for minus sign. + const minus = dec[0] === '-'; + if (minus) { + dec = dec.slice(1); + } + + // Work 6 decimal digits at a time, acting like we're converting base 1e6 + // digits to binary. This is safe to do with floating point math because + // Number.isSafeInteger(ALL_32_BITS * 1e6) == true. + const base = 1e6; + let lowBits = 0; + let highBits = 0; + function add1e6digit(begin, end = undefined) { + // Note: Number('') is 0. + const digit1e6 = Number(dec.slice(begin, end)); + highBits *= base; + lowBits = lowBits * base + digit1e6; + // Carry bits from lowBits to + if (lowBits >= TWO_PWR_32_DBL) { + highBits = highBits + ((lowBits / TWO_PWR_32_DBL) | 0); + lowBits = lowBits % TWO_PWR_32_DBL; + } + } + add1e6digit(-24, -18); + add1e6digit(-18, -12); + add1e6digit(-12, -6); + add1e6digit(-6); + + return (minus ? negate : Int64.fromBits)(lowBits, highBits); +}; + +/** + * @param {number} lowBits + * @param {number} highBits + * @return {!Int64} Two's compliment negation of input. + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Signed_32-bit_integers + */ +const negate = (lowBits, highBits) => { + highBits = ~highBits; + if (lowBits) { + lowBits = ~lowBits + 1; + } else { + // If lowBits is 0, then bitwise-not is 0xFFFFFFFF, + // adding 1 to that, results in 0x100000000, which leaves + // the low bits 0x0 and simply adds one to the high bits. + highBits += 1; + } + return Int64.fromBits(lowBits, highBits); +}; + +/** @const {!Int64} */ +const ZERO = new Int64(0, 0); + +/** @const @private {number} */ +const LOW_16_BITS = 0xFFFF; + +/** @const @private {number} */ +const LOW_24_BITS = 0xFFFFFF; + +/** @const @private {number} */ +const LOW_31_BITS = 0x7FFFFFFF; + +/** @const @private {number} */ +const ALL_32_BITS = 0xFFFFFFFF; + +/** @const {!Int64} */ +const MAX_VALUE = Int64.fromBits(ALL_32_BITS, LOW_31_BITS); + +/** @const {!Int64} */ +const MIN_VALUE = Int64.fromBits(0, 0x80000000); + +/** @const {number} */ +const TWO_PWR_32_DBL = 0x100000000; + +/** @const {string} */ +const HEX_DIGITS = '0123456789abcdef'; + +exports = Int64; diff --git a/js/experimental/runtime/int64_test.js b/js/experimental/runtime/int64_test.js new file mode 100644 index 0000000000000..76af14eabc050 --- /dev/null +++ b/js/experimental/runtime/int64_test.js @@ -0,0 +1,213 @@ +/** + * @fileoverview Tests for Int64. + */ +goog.module('protobuf.Int64Test'); +goog.setTestOnly(); + +const Int64 = goog.require('protobuf.Int64'); +const Long = goog.require('goog.math.Long'); + +describe('Int64', () => { + it('can be constructed from bits', () => { + const int64 = Int64.fromBits(0, 1); + expect(int64.getLowBits()).toEqual(0); + expect(int64.getHighBits()).toEqual(1); + }); + + it('zero is defined', () => { + const int64 = Int64.getZero(); + expect(int64.getLowBits()).toEqual(0); + expect(int64.getHighBits()).toEqual(0); + }); + + it('max value is defined', () => { + const int64 = Int64.getMaxValue(); + expect(int64).toEqual(Int64.fromBits(0xFFFFFFFF, 0x7FFFFFFF)); + expect(int64.asLong()).toEqual(Long.getMaxValue()); + }); + + it('min value is defined', () => { + const int64 = Int64.getMinValue(); + expect(int64).toEqual(Int64.fromBits(0, 0x80000000)); + expect(int64.asLong()).toEqual(Long.getMinValue()); + }); + + it('Can be converted to long', () => { + const int64 = Int64.fromInt(1); + expect(int64.asLong()).toEqual(Long.fromInt(1)); + }); + + it('Negative value can be converted to long', () => { + const int64 = Int64.fromInt(-1); + expect(int64.getLowBits()).toEqual(0xFFFFFFFF | 0); + expect(int64.getHighBits()).toEqual(0xFFFFFFFF | 0); + expect(int64.asLong()).toEqual(Long.fromInt(-1)); + }); + + it('Can be converted to number', () => { + const int64 = Int64.fromInt(1); + expect(int64.asNumber()).toEqual(1); + }); + + it('Can convert negative value to number', () => { + const int64 = Int64.fromInt(-1); + expect(int64.asNumber()).toEqual(-1); + }); + + it('MAX_SAFE_INTEGER can be used.', () => { + const int64 = Int64.fromNumber(Number.MAX_SAFE_INTEGER); + expect(int64.getLowBitsUnsigned()).toEqual(0xFFFFFFFF); + expect(int64.getHighBits()).toEqual(0x1FFFFF); + expect(int64.asNumber()).toEqual(Number.MAX_SAFE_INTEGER); + }); + + it('MIN_SAFE_INTEGER can be used.', () => { + const int64 = Int64.fromNumber(Number.MIN_SAFE_INTEGER); + expect(int64.asNumber()).toEqual(Number.MIN_SAFE_INTEGER); + }); + + it('constructs fromInt', () => { + const int64 = Int64.fromInt(1); + expect(int64.getLowBits()).toEqual(1); + expect(int64.getHighBits()).toEqual(0); + }); + + it('constructs fromLong', () => { + const int64 = Int64.fromLong(Long.fromInt(1)); + expect(int64.getLowBits()).toEqual(1); + expect(int64.getHighBits()).toEqual(0); + }); + + // TODO: Use our own checking system here. + if (goog.DEBUG) { + it('asNumber throws for MAX_SAFE_INTEGER + 1', () => { + expect(() => Int64.fromNumber(Number.MAX_SAFE_INTEGER + 1).asNumber()) + .toThrow(); + }); + + it('fromInt(MAX_SAFE_INTEGER) throws', () => { + expect(() => Int64.fromInt(Number.MAX_SAFE_INTEGER)).toThrow(); + }); + + it('fromInt(1.5) throws', () => { + expect(() => Int64.fromInt(1.5)).toThrow(); + }); + } + + const decimalHexPairs = { + '0x0000000000000000': {signed: '0'}, + '0x0000000000000001': {signed: '1'}, + '0x00000000ffffffff': {signed: '4294967295'}, + '0x0000000100000000': {signed: '4294967296'}, + '0xffffffffffffffff': {signed: '-1', unsigned: '18446744073709551615'}, + '0x8000000000000000': + {signed: '-9223372036854775808', unsigned: '9223372036854775808'}, + '0x8000000080000000': + {signed: '-9223372034707292160', unsigned: '9223372039002259456'}, + '0x01b69b4bacd05f15': {signed: '123456789123456789'}, + '0xfe4964b4532fa0eb': + {signed: '-123456789123456789', unsigned: '18323287284586094827'}, + '0xa5a5a5a5a5a5a5a5': + {signed: '-6510615555426900571', unsigned: '11936128518282651045'}, + '0x5a5a5a5a5a5a5a5a': {signed: '6510615555426900570'}, + '0xffffffff00000000': + {signed: '-4294967296', unsigned: '18446744069414584320'}, + }; + + it('serializes to signed decimal strings', () => { + for (const [hex, decimals] of Object.entries(decimalHexPairs)) { + const int64 = hexToInt64(hex); + expect(int64.toSignedDecimalString()).toEqual(decimals.signed); + } + }); + + it('serializes to unsigned decimal strings', () => { + for (const [hex, decimals] of Object.entries(decimalHexPairs)) { + const int64 = hexToInt64(hex); + expect(int64.toUnsignedDecimalString()) + .toEqual(decimals.unsigned || decimals.signed); + } + }); + + it('serializes to unsigned hex strings', () => { + for (const [hex, decimals] of Object.entries(decimalHexPairs)) { + const int64 = hexToInt64(hex); + let shortHex = hex.replace(/0x0*/, '0x'); + if (shortHex == '0x') { + shortHex = '0x0'; + } + expect(int64.toHexString()).toEqual(shortHex); + } + }); + + it('parses decimal strings', () => { + for (const [hex, decimals] of Object.entries(decimalHexPairs)) { + const signed = Int64.fromDecimalString(decimals.signed); + expect(int64ToHex(signed)).toEqual(hex); + if (decimals.unsigned) { + const unsigned = Int64.fromDecimalString(decimals.unsigned); + expect(int64ToHex(unsigned)).toEqual(hex); + } + } + }); + + it('parses hex strings', () => { + for (const [hex, decimals] of Object.entries(decimalHexPairs)) { + expect(int64ToHex(Int64.fromHexString(hex))).toEqual(hex); + } + expect(int64ToHex(Int64.fromHexString('-0x1'))) + .toEqual('0xffffffffffffffff'); + }); + + // TODO: Use our own checking system here. + if (goog.DEBUG) { + it('throws when parsing empty string', () => { + expect(() => Int64.fromDecimalString('')).toThrow(); + }); + + it('throws when parsing float string', () => { + expect(() => Int64.fromDecimalString('1.5')).toThrow(); + }); + + it('throws when parsing non-numeric string', () => { + expect(() => Int64.fromDecimalString('0xa')).toThrow(); + }); + } + + it('checks if equal', () => { + const low = Int64.fromInt(1); + const high = Int64.getMaxValue(); + expect(low.equals(Int64.fromInt(1))).toEqual(true); + expect(low.equals(high)).toEqual(false); + expect(high.equals(Int64.getMaxValue())).toEqual(true); + }); + + it('returns unique hashcode', () => { + expect(Int64.fromInt(1).hashCode()).toEqual(Int64.fromInt(1).hashCode()); + expect(Int64.fromInt(1).hashCode()) + .not.toEqual(Int64.fromInt(2).hashCode()); + }); +}); + +/** + * @param {string} hexString + * @return {!Int64} + */ +function hexToInt64(hexString) { + const high = hexString.slice(2, 10); + const low = hexString.slice(10); + return Int64.fromBits(parseInt(low, 16), parseInt(high, 16)); +} + +/** + * @param {!Int64} int64 + * @return {string} + */ +function int64ToHex(int64) { + const ZEROS_32_BIT = '00000000'; + const highPartialHex = int64.getHighBitsUnsigned().toString(16); + const lowPartialHex = int64.getLowBitsUnsigned().toString(16); + const highHex = ZEROS_32_BIT.slice(highPartialHex.length) + highPartialHex; + const lowHex = ZEROS_32_BIT.slice(lowPartialHex.length) + lowPartialHex; + return `0x${highHex}${lowHex}`; +} diff --git a/js/experimental/runtime/internal/checks.js b/js/experimental/runtime/internal/checks.js new file mode 100644 index 0000000000000..3d1af548f5985 --- /dev/null +++ b/js/experimental/runtime/internal/checks.js @@ -0,0 +1,708 @@ +/** + * @fileoverview Proto internal runtime checks. + * + * Checks are grouped into different severity, see: + * http://g3doc/third_party/protobuf/javascript/README.md#configurable-check-support-in-protocol-buffers + * + * Checks are also grouped into different sections: + * - CHECK_BOUNDS: + * Checks that ensure that indexed access is within bounds + * (e.g. an array being accessed past its size). + * - CHECK_STATE + * Checks related to the state of an object + * (e.g. a parser hitting an invalid case). + * - CHECK_TYPE: + * Checks that relate to type errors (e.g. code receives a number instead + * of a string). + */ +goog.module('protobuf.internal.checks'); + +const ByteString = goog.require('protobuf.ByteString'); +const Int64 = goog.require('protobuf.Int64'); +const WireType = goog.require('protobuf.binary.WireType'); + +// +// See +// http://g3doc/third_party/protobuf/javascript/README.md#configurable-check-support-in-protocol-buffers +// +/** @define{string} */ +const CHECK_LEVEL_DEFINE = goog.define('protobuf.defines.CHECK_LEVEL', ''); + +/** @define{boolean} */ +const POLYFILL_TEXT_ENCODING = + goog.define('protobuf.defines.POLYFILL_TEXT_ENCODING', true); + +/** + * @const {number} + */ +const MAX_FIELD_NUMBER = Math.pow(2, 29) - 1; + +/** + * The largest finite float32 value. + * @const {number} + */ +const FLOAT32_MAX = 3.4028234663852886e+38; + +/** @enum {number} */ +const CheckLevel = { + DEBUG: 0, + CRITICAL: 1, + OFF: 2 +}; + + +/** @return {!CheckLevel} */ +function calculateCheckLevel() { + const definedLevel = CHECK_LEVEL_DEFINE.toUpperCase(); + if (definedLevel === '') { + // user did not set a value, value now just depends on goog.DEBUG + return goog.DEBUG ? CheckLevel.DEBUG : CheckLevel.CRITICAL; + } + + if (definedLevel === 'CRITICAL') { + return CheckLevel.CRITICAL; + } + + if (definedLevel === 'OFF') { + return CheckLevel.OFF; + } + + if (definedLevel === 'DEBUG') { + return CheckLevel.DEBUG; + } + + throw new Error(`Unknown value for CHECK_LEVEL: ${CHECK_LEVEL_DEFINE}`); +} + +const /** !CheckLevel */ CHECK_LEVEL = calculateCheckLevel(); + +const /** boolean */ CHECK_STATE = CHECK_LEVEL === CheckLevel.DEBUG; + +const /** boolean */ CHECK_CRITICAL_STATE = + CHECK_LEVEL === CheckLevel.CRITICAL || CHECK_LEVEL === CheckLevel.DEBUG; + +const /** boolean */ CHECK_BOUNDS = CHECK_LEVEL === CheckLevel.DEBUG; + +const /** boolean */ CHECK_CRITICAL_BOUNDS = + CHECK_LEVEL === CheckLevel.CRITICAL || CHECK_LEVEL === CheckLevel.DEBUG; + +const /** boolean */ CHECK_TYPE = CHECK_LEVEL === CheckLevel.DEBUG; + +const /** boolean */ CHECK_CRITICAL_TYPE = + CHECK_LEVEL === CheckLevel.CRITICAL || CHECK_LEVEL === CheckLevel.DEBUG; + +/** + * Ensures the truth of an expression involving the state of the calling + * instance, but not involving any parameters to the calling method. + * + * For cases where failing fast is pretty important and not failing early could + * cause bugs that are much harder to debug. + * @param {boolean} state + * @param {string=} message + * @throws {!Error} If the state is false and the check state is critical. + */ +function checkCriticalState(state, message = '') { + if (!CHECK_CRITICAL_STATE) { + return; + } + if (!state) { + throw new Error(message); + } +} + +/** + * Ensures the truth of an expression involving the state of the calling + * instance, but not involving any parameters to the calling method. + * + * @param {boolean} state + * @param {string=} message + * @throws {!Error} If the state is false and the check state is debug. + */ +function checkState(state, message = '') { + if (!CHECK_STATE) { + return; + } + checkCriticalState(state, message); +} + +/** + * Ensures that `index` specifies a valid position in an indexable object of + * size `size`. A position index may range from zero to size, inclusive. + * @param {number} index + * @param {number} size + * @throws {!Error} If the index is out of range and the check state is debug. + */ +function checkPositionIndex(index, size) { + if (!CHECK_BOUNDS) { + return; + } + checkCriticalPositionIndex(index, size); +} + +/** + * Ensures that `index` specifies a valid position in an indexable object of + * size `size`. A position index may range from zero to size, inclusive. + * @param {number} index + * @param {number} size + * @throws {!Error} If the index is out of range and the check state is + * critical. + */ +function checkCriticalPositionIndex(index, size) { + if (!CHECK_CRITICAL_BOUNDS) { + return; + } + if (index < 0 || index > size) { + throw new Error(`Index out of bounds: index: ${index} size: ${size}`); + } +} + +/** + * Ensures that `index` specifies a valid element in an indexable object of + * size `size`. A element index may range from zero to size, exclusive. + * @param {number} index + * @param {number} size + * @throws {!Error} If the index is out of range and the check state is + * debug. + */ +function checkElementIndex(index, size) { + if (!CHECK_BOUNDS) { + return; + } + checkCriticalElementIndex(index, size); +} + +/** + * Ensures that `index` specifies a valid element in an indexable object of + * size `size`. A element index may range from zero to size, exclusive. + * @param {number} index + * @param {number} size + * @throws {!Error} If the index is out of range and the check state is + * critical. + */ +function checkCriticalElementIndex(index, size) { + if (!CHECK_CRITICAL_BOUNDS) { + return; + } + if (index < 0 || index >= size) { + throw new Error(`Index out of bounds: index: ${index} size: ${size}`); + } +} + +/** + * Ensures the range of [start, end) is with the range of [0, size). + * @param {number} start + * @param {number} end + * @param {number} size + * @throws {!Error} If start and end are out of range and the check state is + * debug. + */ +function checkRange(start, end, size) { + if (!CHECK_BOUNDS) { + return; + } + checkCriticalRange(start, end, size); +} + +/** + * Ensures the range of [start, end) is with the range of [0, size). + * @param {number} start + * @param {number} end + * @param {number} size + * @throws {!Error} If start and end are out of range and the check state is + * critical. + */ +function checkCriticalRange(start, end, size) { + if (!CHECK_CRITICAL_BOUNDS) { + return; + } + if (start < 0 || end < 0 || start > size || end > size) { + throw new Error(`Range error: start: ${start} end: ${end} size: ${size}`); + } + if (start > end) { + throw new Error(`Start > end: ${start} > ${end}`); + } +} + +/** + * Ensures that field number is an integer and within the range of + * [1, MAX_FIELD_NUMBER]. + * @param {number} fieldNumber + * @throws {!Error} If the field number is out of range and the check state is + * debug. + */ +function checkFieldNumber(fieldNumber) { + if (!CHECK_TYPE) { + return; + } + checkCriticalFieldNumber(fieldNumber); +} + +/** + * Ensures that the value is neither null nor undefined. + * + * @param {T} value + * @return {R} + * + * @template T + * @template R := + * mapunion(T, (V) => + * cond(eq(V, 'null'), + * none(), + * cond(eq(V, 'undefined'), + * none(), + * V))) + * =: + */ +function checkDefAndNotNull(value) { + if (CHECK_TYPE) { + // Note that undefined == null. + if (value == null) { + throw new Error(`Value can't be null`); + } + } + return value; +} + +/** + * Ensures that the value exists and is a function. + * + * @param {function(?): ?} func + */ +function checkFunctionExists(func) { + if (CHECK_TYPE) { + if (typeof func !== 'function') { + throw new Error(`${func} is not a function`); + } + } +} + +/** + * Ensures that field number is an integer and within the range of + * [1, MAX_FIELD_NUMBER]. + * @param {number} fieldNumber + * @throws {!Error} If the field number is out of range and the check state is + * critical. + */ +function checkCriticalFieldNumber(fieldNumber) { + if (!CHECK_CRITICAL_TYPE) { + return; + } + if (fieldNumber <= 0 || fieldNumber > MAX_FIELD_NUMBER) { + throw new Error(`Field number is out of range: ${fieldNumber}`); + } +} + +/** + * Ensures that wire type is valid. + * @param {!WireType} wireType + * @throws {!Error} If the wire type is invalid and the check state is debug. + */ +function checkWireType(wireType) { + if (!CHECK_TYPE) { + return; + } + checkCriticalWireType(wireType); +} + +/** + * Ensures that wire type is valid. + * @param {!WireType} wireType + * @throws {!Error} If the wire type is invalid and the check state is critical. + */ +function checkCriticalWireType(wireType) { + if (!CHECK_CRITICAL_TYPE) { + return; + } + if (wireType < WireType.VARINT || wireType > WireType.FIXED32) { + throw new Error(`Invalid wire type: ${wireType}`); + } +} + +/** + * Ensures the given value has the correct type. + * @param {boolean} expression + * @param {string} errorMsg + * @throws {!Error} If the value has the wrong type and the check state is + * critical. + */ +function checkCriticalType(expression, errorMsg) { + if (!CHECK_CRITICAL_TYPE) { + return; + } + if (!expression) { + throw new Error(errorMsg); + } +} + +/** + * Checks whether a given object is an array. + * @param {*} value + * @return {!Array<*>} + */ +function checkCriticalTypeArray(value) { + checkCriticalType( + Array.isArray(value), `Must be an array, but got: ${value}`); + return /** @type {!Array<*>} */ (value); +} + +/** + * Checks whether a given object is an iterable. + * @param {*} value + * @return {!Iterable<*>} + */ +function checkCriticalTypeIterable(value) { + checkCriticalType( + !!value[Symbol.iterator], `Must be an iterable, but got: ${value}`); + return /** @type {!Iterable<*>} */ (value); +} + +/** + * Checks whether a given object is a boolean. + * @param {*} value + */ +function checkCriticalTypeBool(value) { + checkCriticalType( + typeof value === 'boolean', `Must be a boolean, but got: ${value}`); +} + +/** + * Checks whether a given object is an array of boolean. + * @param {*} values + */ +function checkCriticalTypeBoolArray(values) { + // TODO(b/134765672) + if (!CHECK_CRITICAL_TYPE) { + return; + } + const array = checkCriticalTypeArray(values); + for (const value of array) { + checkCriticalTypeBool(value); + } +} + +/** + * Checks whether a given object is a ByteString. + * @param {*} value + */ +function checkCriticalTypeByteString(value) { + checkCriticalType( + value instanceof ByteString, `Must be a ByteString, but got: ${value}`); +} + +/** + * Checks whether a given object is an array of ByteString. + * @param {*} values + */ +function checkCriticalTypeByteStringArray(values) { + // TODO(b/134765672) + if (!CHECK_CRITICAL_TYPE) { + return; + } + const array = checkCriticalTypeArray(values); + for (const value of array) { + checkCriticalTypeByteString(value); + } +} + +/** + * Checks whether a given object is a number. + * @param {*} value + * @throws {!Error} If the value is not float and the check state is debug. + */ +function checkTypeDouble(value) { + if (!CHECK_TYPE) { + return; + } + checkCriticalTypeDouble(value); +} + +/** + * Checks whether a given object is a number. + * @param {*} value + * @throws {!Error} If the value is not float and the check state is critical. + */ +function checkCriticalTypeDouble(value) { + checkCriticalType( + typeof value === 'number', `Must be a number, but got: ${value}`); +} + +/** + * Checks whether a given object is an array of double. + * @param {*} values + */ +function checkCriticalTypeDoubleArray(values) { + // TODO(b/134765672) + if (!CHECK_CRITICAL_TYPE) { + return; + } + const array = checkCriticalTypeArray(values); + for (const value of array) { + checkCriticalTypeDouble(value); + } +} + +/** + * Checks whether a given object is a number. + * @param {*} value + * @throws {!Error} If the value is not signed int32 and the check state is + * debug. + */ +function checkTypeSignedInt32(value) { + if (!CHECK_TYPE) { + return; + } + checkCriticalTypeSignedInt32(value); +} + +/** + * Checks whether a given object is a number. + * @param {*} value + * @throws {!Error} If the value is not signed int32 and the check state is + * critical. + */ +function checkCriticalTypeSignedInt32(value) { + checkCriticalTypeDouble(value); + const valueAsNumber = /** @type {number} */ (value); + if (CHECK_CRITICAL_TYPE) { + if (valueAsNumber < -Math.pow(2, 31) || valueAsNumber > Math.pow(2, 31) || + !Number.isInteger(valueAsNumber)) { + throw new Error(`Must be int32, but got: ${valueAsNumber}`); + } + } +} + +/** + * Checks whether a given object is an array of numbers. + * @param {*} values + */ +function checkCriticalTypeSignedInt32Array(values) { + // TODO(b/134765672) + if (!CHECK_CRITICAL_TYPE) { + return; + } + const array = checkCriticalTypeArray(values); + for (const value of array) { + checkCriticalTypeSignedInt32(value); + } +} + +/** + * Ensures that value is a long instance. + * @param {*} value + * @throws {!Error} If the value is not a long instance and check state is + * debug. + */ +function checkTypeSignedInt64(value) { + if (!CHECK_TYPE) { + return; + } + checkCriticalTypeSignedInt64(value); +} + +/** + * Ensures that value is a long instance. + * @param {*} value + * @throws {!Error} If the value is not a long instance and check state is + * critical. + */ +function checkCriticalTypeSignedInt64(value) { + if (!CHECK_CRITICAL_TYPE) { + return; + } + if (!(value instanceof Int64)) { + throw new Error(`Must be Int64 instance, but got: ${value}`); + } +} + +/** + * Checks whether a given object is an array of long instances. + * @param {*} values + * @throws {!Error} If values is not an array of long instances. + */ +function checkCriticalTypeSignedInt64Array(values) { + // TODO(b/134765672) + if (!CHECK_CRITICAL_TYPE) { + return; + } + const array = checkCriticalTypeArray(values); + for (const value of array) { + checkCriticalTypeSignedInt64(value); + } +} + +/** + * Checks whether a given object is a number and within float32 precision. + * @param {*} value + * @throws {!Error} If the value is not float and the check state is debug. + */ +function checkTypeFloat(value) { + if (!CHECK_TYPE) { + return; + } + checkCriticalTypeFloat(value); +} + +/** + * Checks whether a given object is a number and within float32 precision. + * @param {*} value + * @throws {!Error} If the value is not float and the check state is critical. + */ +function checkCriticalTypeFloat(value) { + checkCriticalTypeDouble(value); + if (CHECK_CRITICAL_TYPE) { + const valueAsNumber = /** @type {number} */ (value); + if (Number.isFinite(valueAsNumber) && + (valueAsNumber > FLOAT32_MAX || valueAsNumber < -FLOAT32_MAX)) { + throw new Error( + `Given number does not fit into float precision: ${value}`); + } + } +} + +/** + * Checks whether a given object is an iterable of floats. + * @param {*} values + */ +function checkCriticalTypeFloatIterable(values) { + // TODO(b/134765672) + if (!CHECK_CRITICAL_TYPE) { + return; + } + const iterable = checkCriticalTypeIterable(values); + for (const value of iterable) { + checkCriticalTypeFloat(value); + } +} + +/** + * Checks whether a given object is a string. + * @param {*} value + */ +function checkCriticalTypeString(value) { + checkCriticalType( + typeof value === 'string', `Must be string, but got: ${value}`); +} + +/** + * Checks whether a given object is an array of string. + * @param {*} values + */ +function checkCriticalTypeStringArray(values) { + // TODO(b/134765672) + if (!CHECK_CRITICAL_TYPE) { + return; + } + const array = checkCriticalTypeArray(values); + for (const value of array) { + checkCriticalTypeString(value); + } +} + +/** + * Ensures that value is a valid unsigned int32. + * @param {*} value + * @throws {!Error} If the value is out of range and the check state is debug. + */ +function checkTypeUnsignedInt32(value) { + if (!CHECK_TYPE) { + return; + } + checkCriticalTypeUnsignedInt32(value); +} + +/** + * Ensures that value is a valid unsigned int32. + * @param {*} value + * @throws {!Error} If the value is out of range and the check state + * is critical. + */ +function checkCriticalTypeUnsignedInt32(value) { + if (!CHECK_CRITICAL_TYPE) { + return; + } + checkCriticalTypeDouble(value); + const valueAsNumber = /** @type {number} */ (value); + if (valueAsNumber < 0 || valueAsNumber > Math.pow(2, 32) - 1 || + !Number.isInteger(valueAsNumber)) { + throw new Error(`Must be uint32, but got: ${value}`); + } +} + +/** + * Checks whether a given object is an array of unsigned int32. + * @param {*} values + */ +function checkCriticalTypeUnsignedInt32Array(values) { + // TODO(b/134765672) + if (!CHECK_CRITICAL_TYPE) { + return; + } + const array = checkCriticalTypeArray(values); + for (const value of array) { + checkCriticalTypeUnsignedInt32(value); + } +} + +/** + * Checks whether a given object is an array of message. + * @param {*} values + */ +function checkCriticalTypeMessageArray(values) { + // TODO(b/134765672) + if (!CHECK_CRITICAL_TYPE) { + return; + } + const array = checkCriticalTypeArray(values); + for (const value of array) { + checkCriticalType( + value !== null, 'Given value is not a message instance: null'); + } +} + +exports = { + checkDefAndNotNull, + checkCriticalElementIndex, + checkCriticalFieldNumber, + checkCriticalPositionIndex, + checkCriticalRange, + checkCriticalState, + checkCriticalTypeBool, + checkCriticalTypeBoolArray, + checkCriticalTypeByteString, + checkCriticalTypeByteStringArray, + checkCriticalTypeDouble, + checkTypeDouble, + checkCriticalTypeDoubleArray, + checkTypeFloat, + checkCriticalTypeFloat, + checkCriticalTypeFloatIterable, + checkCriticalTypeMessageArray, + checkCriticalTypeSignedInt32, + checkCriticalTypeSignedInt32Array, + checkCriticalTypeSignedInt64, + checkTypeSignedInt64, + checkCriticalTypeSignedInt64Array, + checkCriticalTypeString, + checkCriticalTypeStringArray, + checkCriticalTypeUnsignedInt32, + checkCriticalTypeUnsignedInt32Array, + checkCriticalType, + checkCriticalWireType, + checkElementIndex, + checkFieldNumber, + checkFunctionExists, + checkPositionIndex, + checkRange, + checkState, + checkTypeUnsignedInt32, + checkTypeSignedInt32, + checkWireType, + CHECK_BOUNDS, + CHECK_CRITICAL_BOUNDS, + CHECK_STATE, + CHECK_CRITICAL_STATE, + CHECK_TYPE, + CHECK_CRITICAL_TYPE, + MAX_FIELD_NUMBER, + POLYFILL_TEXT_ENCODING, +}; diff --git a/js/experimental/runtime/internal/checks_test.js b/js/experimental/runtime/internal/checks_test.js new file mode 100644 index 0000000000000..50e857b3e0994 --- /dev/null +++ b/js/experimental/runtime/internal/checks_test.js @@ -0,0 +1,58 @@ +/** + * @fileoverview Tests for checks.js. + */ +goog.module('protobuf.internal.checksTest'); + +const {CHECK_TYPE, checkDefAndNotNull, checkFunctionExists} = goog.require('protobuf.internal.checks'); + +describe('checkDefAndNotNull', () => { + it('throws if undefined', () => { + let value; + if (CHECK_TYPE) { + expect(() => checkDefAndNotNull(value)).toThrow(); + } else { + expect(checkDefAndNotNull(value)).toBeUndefined(); + } + }); + + it('throws if null', () => { + const value = null; + if (CHECK_TYPE) { + expect(() => checkDefAndNotNull(value)).toThrow(); + } else { + expect(checkDefAndNotNull(value)).toBeNull(); + } + }); + + it('does not throw if empty string', () => { + const value = ''; + expect(checkDefAndNotNull(value)).toEqual(''); + }); +}); + +describe('checkFunctionExists', () => { + it('throws if the function is undefined', () => { + let foo = /** @type {function()} */ (/** @type {*} */ (undefined)); + if (CHECK_TYPE) { + expect(() => checkFunctionExists(foo)).toThrow(); + } else { + checkFunctionExists(foo); + } + }); + + it('throws if the property is defined but not a function', () => { + let foo = /** @type {function()} */ (/** @type {*} */ (1)); + if (CHECK_TYPE) { + expect(() => checkFunctionExists(foo)).toThrow(); + } else { + checkFunctionExists(foo); + } + }); + + it('does not throw if the function is defined', () => { + function foo(x) { + return x; + } + checkFunctionExists(foo); + }); +}); \ No newline at end of file diff --git a/js/experimental/runtime/kernel/binary_storage.js b/js/experimental/runtime/kernel/binary_storage.js new file mode 100644 index 0000000000000..4cbde30a69460 --- /dev/null +++ b/js/experimental/runtime/kernel/binary_storage.js @@ -0,0 +1,130 @@ +goog.module('protobuf.runtime.BinaryStorage'); + +const Storage = goog.require('protobuf.runtime.Storage'); +const {checkDefAndNotNull} = goog.require('protobuf.internal.checks'); + +/** + * Class storing all the fields of a binary protobuf message. + * + * @package + * @template FieldType + * @implements {Storage} + */ +class BinaryStorage { + /** + * @param {number=} pivot + */ + constructor(pivot = Storage.DEFAULT_PIVOT) { + /** + * Fields having a field number no greater than the pivot value are stored + * into an array for fast access. A field with field number X is stored into + * the array position X - 1. + * + * @private @const {!Array} + */ + this.array_ = new Array(pivot); + + /** + * Fields having a field number higher than the pivot value are stored into + * the map. We create the map only when it's needed, since even an empty map + * takes up a significant amount of memory. + * + * @private {?Map} + */ + this.map_ = null; + } + + /** + * Fields having a field number no greater than the pivot value are stored + * into an array for fast access. A field with field number X is stored into + * the array position X - 1. + * @return {number} + * @override + */ + getPivot() { + return this.array_.length; + } + + /** + * Sets a field in the specified field number. + * + * @param {number} fieldNumber + * @param {!FieldType} field + * @override + */ + set(fieldNumber, field) { + if (fieldNumber <= this.getPivot()) { + this.array_[fieldNumber - 1] = field; + } else { + if (this.map_) { + this.map_.set(fieldNumber, field); + } else { + this.map_ = new Map([[fieldNumber, field]]); + } + } + } + + /** + * Returns a field at the specified field number. + * + * @param {number} fieldNumber + * @return {!FieldType|undefined} + * @override + */ + get(fieldNumber) { + if (fieldNumber <= this.getPivot()) { + return this.array_[fieldNumber - 1]; + } else { + return this.map_ ? this.map_.get(fieldNumber) : undefined; + } + } + + /** + * Deletes a field from the specified field number. + * + * @param {number} fieldNumber + * @override + */ + delete(fieldNumber) { + if (fieldNumber <= this.getPivot()) { + delete this.array_[fieldNumber - 1]; + } else { + if (this.map_) { + this.map_.delete(fieldNumber); + } + } + } + + /** + * Executes the provided function once for each field. + * + * @param {function(!FieldType, number): void} callback + * @override + */ + forEach(callback) { + this.array_.forEach((field, fieldNumber) => { + if (field) { + callback(checkDefAndNotNull(field), fieldNumber + 1); + } + }); + if (this.map_) { + this.map_.forEach(callback); + } + } + + /** + * Creates a shallow copy of the storage. + * + * @return {!BinaryStorage} + * @override + */ + shallowCopy() { + const copy = new BinaryStorage(this.getPivot()); + this.forEach( + (field, fieldNumber) => + void copy.set(fieldNumber, field.shallowCopy())); + return copy; + } +} + +exports = BinaryStorage; diff --git a/js/experimental/runtime/kernel/binary_storage_test.js b/js/experimental/runtime/kernel/binary_storage_test.js new file mode 100644 index 0000000000000..2686f04e47c2f --- /dev/null +++ b/js/experimental/runtime/kernel/binary_storage_test.js @@ -0,0 +1,165 @@ +/** + * @fileoverview Tests for storage.js. + */ +goog.module('protobuf.runtime.BinaryStorageTest'); + +goog.setTestOnly(); + +const BinaryStorage = goog.require('protobuf.runtime.BinaryStorage'); +const {Field} = goog.require('protobuf.binary.field'); + +/** + * @type {number} + */ +const DEFAULT_PIVOT = 24; + +const /** !Field */ field1 = + Field.fromDecodedValue(/* decodedValue= */ 1, /* encoder= */ () => {}); +const /** !Field */ field2 = + Field.fromDecodedValue(/* decodedValue= */ 2, /* encoder= */ () => {}); +const /** !Field */ field3 = + Field.fromDecodedValue(/* decodedValue= */ 3, /* encoder= */ () => {}); +const /** !Field */ field4 = + Field.fromDecodedValue(/* decodedValue= */ 4, /* encoder= */ () => {}); + +/** + * Returns the number of fields stored. + * + * @param {!BinaryStorage} storage + * @return {number} + */ +function getStorageSize(storage) { + let size = 0; + storage.forEach(() => void size++); + return size; +} + +describe('BinaryStorage', () => { + it('sets and gets a field not greater than the pivot', () => { + const storage = new BinaryStorage(DEFAULT_PIVOT); + + storage.set(1, field1); + storage.set(DEFAULT_PIVOT, field2); + + expect(storage.getPivot()).toBe(DEFAULT_PIVOT); + expect(storage.get(1)).toBe(field1); + expect(storage.get(DEFAULT_PIVOT)).toBe(field2); + }); + + it('sets and gets a field greater than the pivot', () => { + const storage = new BinaryStorage(DEFAULT_PIVOT); + + storage.set(DEFAULT_PIVOT + 1, field1); + storage.set(100000, field2); + + expect(storage.get(DEFAULT_PIVOT + 1)).toBe(field1); + expect(storage.get(100000)).toBe(field2); + }); + + it('sets and gets a field when pivot is zero', () => { + const storage = new BinaryStorage(0); + + storage.set(0, field1); + storage.set(100000, field2); + + expect(storage.getPivot()).toBe(0); + expect(storage.get(0)).toBe(field1); + expect(storage.get(100000)).toBe(field2); + }); + + it('sets and gets a field when pivot is undefined', () => { + const storage = new BinaryStorage(); + + storage.set(0, field1); + storage.set(DEFAULT_PIVOT, field2); + storage.set(DEFAULT_PIVOT + 1, field3); + + expect(storage.getPivot()).toBe(DEFAULT_PIVOT); + expect(storage.get(0)).toBe(field1); + expect(storage.get(DEFAULT_PIVOT)).toBe(field2); + expect(storage.get(DEFAULT_PIVOT + 1)).toBe(field3); + }); + + it('returns undefined for nonexistent fields', () => { + const storage = new BinaryStorage(DEFAULT_PIVOT); + + expect(storage.get(1)).toBeUndefined(); + expect(storage.get(DEFAULT_PIVOT)).toBeUndefined(); + expect(storage.get(DEFAULT_PIVOT + 1)).toBeUndefined(); + expect(storage.get(100000)).toBeUndefined(); + }); + + it('returns undefined for nonexistent fields after map initialization', + () => { + const storage = new BinaryStorage(DEFAULT_PIVOT); + storage.set(100001, field1); + + expect(storage.get(1)).toBeUndefined(); + expect(storage.get(DEFAULT_PIVOT)).toBeUndefined(); + expect(storage.get(DEFAULT_PIVOT + 1)).toBeUndefined(); + expect(storage.get(100000)).toBeUndefined(); + }); + + it('deletes a field in delete() when values are only in array', () => { + const storage = new BinaryStorage(DEFAULT_PIVOT); + storage.set(1, field1); + + storage.delete(1); + + expect(storage.get(1)).toBeUndefined(); + }); + + it('deletes a field in delete() when values are both in array and map', + () => { + const storage = new BinaryStorage(DEFAULT_PIVOT); + storage.set(DEFAULT_PIVOT, field2); + storage.set(DEFAULT_PIVOT + 1, field3); + + storage.delete(DEFAULT_PIVOT); + storage.delete(DEFAULT_PIVOT + 1); + + expect(storage.get(DEFAULT_PIVOT)).toBeUndefined(); + expect(storage.get(DEFAULT_PIVOT + 1)).toBeUndefined(); + }); + + it('deletes a field in delete() when values are only in map', () => { + const storage = new BinaryStorage(DEFAULT_PIVOT); + storage.set(100000, field4); + + storage.delete(100000); + + expect(storage.get(100000)).toBeUndefined(); + }); + + it('loops over all the elements in forEach()', () => { + const storage = new BinaryStorage(DEFAULT_PIVOT); + storage.set(1, field1); + storage.set(DEFAULT_PIVOT, field2); + storage.set(DEFAULT_PIVOT + 1, field3); + storage.set(100000, field4); + + const fields = new Map(); + storage.forEach( + (field, fieldNumber) => void fields.set(fieldNumber, field)); + + expect(fields.size).toEqual(4); + expect(fields.get(1)).toBe(field1); + expect(storage.get(DEFAULT_PIVOT)).toBe(field2); + expect(storage.get(DEFAULT_PIVOT + 1)).toBe(field3); + expect(fields.get(100000)).toBe(field4); + }); + + it('creates a shallow copy of the storage in shallowCopy()', () => { + const storage = new BinaryStorage(DEFAULT_PIVOT); + storage.set(1, field1); + storage.set(100000, field2); + + const copy = storage.shallowCopy(); + + expect(getStorageSize(copy)).toEqual(2); + expect(copy.get(1)).not.toBe(field1); + expect(copy.get(1).getDecodedValue()).toEqual(1); + expect(copy.get(100000)).not.toBe(field1); + expect(copy.get(100000).getDecodedValue()).toEqual(2); + }); +}); diff --git a/js/experimental/runtime/kernel/bool_test_pairs.js b/js/experimental/runtime/kernel/bool_test_pairs.js new file mode 100644 index 0000000000000..4323f5baa8599 --- /dev/null +++ b/js/experimental/runtime/kernel/bool_test_pairs.js @@ -0,0 +1,79 @@ +/** + * @fileoverview Test data for bool encoding and decoding. + */ +goog.module('protobuf.binary.boolTestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of boolean values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, boolValue: boolean, bufferDecoder: + * !BufferDecoder, error: ?boolean, skip_writer: ?boolean}>} + */ +function getBoolPairs() { + const boolPairs = [ + { + name: 'true', + boolValue: true, + bufferDecoder: createBufferDecoder(0x01), + }, + { + name: 'false', + boolValue: false, + bufferDecoder: createBufferDecoder(0x00), + }, + { + name: 'two-byte true', + boolValue: true, + bufferDecoder: createBufferDecoder(0x80, 0x01), + skip_writer: true, + }, + { + name: 'two-byte false', + boolValue: false, + bufferDecoder: createBufferDecoder(0x80, 0x00), + skip_writer: true, + }, + { + name: 'minus one', + boolValue: true, + bufferDecoder: createBufferDecoder( + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01), + skip_writer: true, + }, + { + name: 'max signed int 2^63 - 1', + boolValue: true, + bufferDecoder: createBufferDecoder( + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F), + skip_writer: true, + }, + { + name: 'min signed int -2^63', + boolValue: true, + bufferDecoder: createBufferDecoder( + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01), + skip_writer: true, + }, + { + name: 'overflowed but valid varint', + boolValue: false, + bufferDecoder: createBufferDecoder( + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x02), + skip_writer: true, + }, + { + name: 'errors out for 11 bytes', + boolValue: true, + bufferDecoder: createBufferDecoder( + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + error: true, + skip_writer: true, + }, + ]; + return [...boolPairs]; +} + +exports = {getBoolPairs}; diff --git a/js/experimental/runtime/kernel/buffer_decoder.js b/js/experimental/runtime/kernel/buffer_decoder.js new file mode 100644 index 0000000000000..b0c45354266f6 --- /dev/null +++ b/js/experimental/runtime/kernel/buffer_decoder.js @@ -0,0 +1,343 @@ +/** + * @fileoverview A buffer implementation that can decode data for protobufs. + */ + +goog.module('protobuf.binary.BufferDecoder'); + +const ByteString = goog.require('protobuf.ByteString'); +const functions = goog.require('goog.functions'); +const {POLYFILL_TEXT_ENCODING, checkCriticalPositionIndex, checkCriticalState, checkState} = goog.require('protobuf.internal.checks'); +const {byteStringFromUint8ArrayUnsafe} = goog.require('protobuf.byteStringInternal'); +const {concatenateByteArrays} = goog.require('protobuf.binary.uint8arrays'); +const {decode} = goog.require('protobuf.binary.textencoding'); + +/** + * Returns a valid utf-8 decoder function based on TextDecoder if available or + * a polyfill. + * Some of the environments we run in do not have TextDecoder defined. + * TextDecoder is faster than our polyfill so we prefer it over the polyfill. + * @return {function(!DataView): string} + */ +function getStringDecoderFunction() { + if (goog.global['TextDecoder']) { + const textDecoder = new goog.global['TextDecoder']('utf-8', {fatal: true}); + return bytes => textDecoder.decode(bytes); + } + if (POLYFILL_TEXT_ENCODING) { + return decode; + } else { + throw new Error( + 'TextDecoder is missing. ' + + 'Enable protobuf.defines.POLYFILL_TEXT_ENCODING.'); + } +} + +/** @type {function(): function(!DataView): string} */ +const stringDecoderFunction = + functions.cacheReturnValue(() => getStringDecoderFunction()); + +/** @type {function(): !DataView} */ +const emptyDataView = + functions.cacheReturnValue(() => new DataView(new ArrayBuffer(0))); + +class BufferDecoder { + /** + * @param {!Array} bufferDecoders + * @return {!BufferDecoder} + */ + static merge(bufferDecoders) { + const uint8Arrays = bufferDecoders.map(b => b.asUint8Array()); + const bytesArray = concatenateByteArrays(uint8Arrays); + return BufferDecoder.fromArrayBuffer(bytesArray.buffer); + } + + /** + * @param {!ArrayBuffer} arrayBuffer + * @return {!BufferDecoder} + */ + static fromArrayBuffer(arrayBuffer) { + return new BufferDecoder( + new DataView(arrayBuffer), 0, arrayBuffer.byteLength); + } + + /** + * @param {!DataView} dataView + * @param {number} startIndex + * @param {number} length + * @private + */ + constructor(dataView, startIndex, length) { + /** @private @const {!DataView} */ + this.dataView_ = dataView; + /** @private @const {number} */ + this.startIndex_ = startIndex; + /** @private @const {number} */ + this.endIndex_ = startIndex + length; + /** @private {number} */ + this.cursor_ = startIndex; + } + + /** + * Returns the start index of the underlying buffer. + * @return {number} + */ + startIndex() { + return this.startIndex_; + } + + /** + * Returns the end index of the underlying buffer. + * @return {number} + */ + endIndex() { + return this.endIndex_; + } + + /** + * Returns the length of the underlying buffer. + * @return {number} + */ + length() { + return this.endIndex_ - this.startIndex_; + } + + /** + * Returns the start position of the next data, i.e. end position of the last + * read data + 1. + * @return {number} + */ + cursor() { + return this.cursor_; + } + + /** + * Sets the cursor to the specified position. + * @param {number} position + */ + setCursor(position) { + this.cursor_ = position; + } + + /** + * Returns if there is more data to read after the current cursor position. + * @return {boolean} + */ + hasNext() { + return this.cursor_ < this.endIndex_; + } + + /** + * Returns a float32 from a given index + * @param {number} index + * @return {number} + */ + getFloat32(index) { + this.cursor_ = index + 4; + return this.dataView_.getFloat32(index, true); + } + + /** + * Returns a float64 from a given index + * @param {number} index + * @return {number} + */ + getFloat64(index) { + this.cursor_ = index + 8; + return this.dataView_.getFloat64(index, true); + } + + /** + * Returns an int32 from a given index + * @param {number} index + * @return {number} + */ + getInt32(index) { + this.cursor_ = index + 4; + return this.dataView_.getInt32(index, true); + } + + /** + * Returns a uint32 from a given index + * @param {number} index + * @return {number} + */ + getUint32(index) { + this.cursor_ = index + 4; + return this.dataView_.getUint32(index, true); + } + + /** + * Returns two JS numbers each representing 32 bits of a 64 bit number. Also + * sets the cursor to the start of the next block of data. + * @param {number} index + * @return {{lowBits: number, highBits: number}} + */ + getVarint(index) { + this.cursor_ = index; + let lowBits = 0; + let highBits = 0; + + for (let shift = 0; shift < 28; shift += 7) { + const b = this.dataView_.getUint8(this.cursor_++); + lowBits |= (b & 0x7F) << shift; + if ((b & 0x80) === 0) { + return {lowBits, highBits}; + } + } + + const middleByte = this.dataView_.getUint8(this.cursor_++); + + // last four bits of the first 32 bit number + lowBits |= (middleByte & 0x0F) << 28; + + // 3 upper bits are part of the next 32 bit number + highBits = (middleByte & 0x70) >> 4; + + if ((middleByte & 0x80) === 0) { + return {lowBits, highBits}; + } + + + for (let shift = 3; shift <= 31; shift += 7) { + const b = this.dataView_.getUint8(this.cursor_++); + highBits |= (b & 0x7F) << shift; + if ((b & 0x80) === 0) { + return {lowBits, highBits}; + } + } + + checkCriticalState(false, 'Data is longer than 10 bytes'); + + return {lowBits, highBits}; + } + + /** + * Returns an unsigned int32 number at the current cursor position. The upper + * bits are discarded if the varint is longer than 32 bits. Also sets the + * cursor to the start of the next block of data. + * @return {number} + */ + getUnsignedVarint32() { + let b = this.dataView_.getUint8(this.cursor_++); + let result = b & 0x7F; + if ((b & 0x80) === 0) { + return result; + } + + b = this.dataView_.getUint8(this.cursor_++); + result |= (b & 0x7F) << 7; + if ((b & 0x80) === 0) { + return result; + } + + b = this.dataView_.getUint8(this.cursor_++); + result |= (b & 0x7F) << 14; + if ((b & 0x80) === 0) { + return result; + } + + b = this.dataView_.getUint8(this.cursor_++); + result |= (b & 0x7F) << 21; + if ((b & 0x80) === 0) { + return result; + } + + // Extract only last 4 bits + b = this.dataView_.getUint8(this.cursor_++); + result |= (b & 0x0F) << 28; + + for (let readBytes = 5; ((b & 0x80) !== 0) && readBytes < 10; readBytes++) { + b = this.dataView_.getUint8(this.cursor_++); + } + + checkCriticalState((b & 0x80) === 0, 'Data is longer than 10 bytes'); + + // Result can be have 32 bits, convert it to unsigned + return result >>> 0; + } + + /** + * Returns an unsigned int32 number at the specified index. The upper bits are + * discarded if the varint is longer than 32 bits. Also sets the cursor to the + * start of the next block of data. + * @param {number} index + * @return {number} + */ + getUnsignedVarint32At(index) { + this.cursor_ = index; + return this.getUnsignedVarint32(); + } + + /** + * Seeks forward by the given amount. + * @param {number} skipAmount + * @package + */ + skip(skipAmount) { + this.cursor_ += skipAmount; + checkCriticalPositionIndex(this.cursor_, this.endIndex_); + } + + /** + * Skips over a varint from the current cursor position. + * @package + */ + skipVarint() { + const startIndex = this.cursor_; + while (this.dataView_.getUint8(this.cursor_++) & 0x80) { + } + checkCriticalPositionIndex(this.cursor_, startIndex + 10); + } + + /** + * @param {number} startIndex + * @param {number} length + * @return {!BufferDecoder} + */ + subBufferDecoder(startIndex, length) { + checkState( + startIndex >= this.startIndex(), + `Current start: ${this.startIndex()}, subBufferDecoder start: ${ + startIndex}`); + checkState(length >= 0, `Length: ${length}`); + checkState( + startIndex + length <= this.endIndex(), + `Current end: ${this.endIndex()}, subBufferDecoder start: ${ + startIndex}, subBufferDecoder length: ${length}`); + return new BufferDecoder(this.dataView_, startIndex, length); + } + + /** + * Returns the buffer as a string. + * @return {string} + */ + asString() { + // TODO: Remove this check when we no longer need to support IE + const stringDataView = this.length() === 0 ? + emptyDataView() : + new DataView(this.dataView_.buffer, this.startIndex_, this.length()); + return stringDecoderFunction()(stringDataView); + } + + /** + * Returns the buffer as a ByteString. + * @return {!ByteString} + */ + asByteString() { + return byteStringFromUint8ArrayUnsafe(this.asUint8Array()); + } + + /** + * Returns the DataView as an Uint8Array. DO NOT MODIFY or expose the + * underlying buffer. + * + * @package + * @return {!Uint8Array} + */ + asUint8Array() { + return new Uint8Array( + this.dataView_.buffer, this.startIndex_, this.length()); + } +} + +exports = BufferDecoder; diff --git a/js/experimental/runtime/kernel/buffer_decoder_helper.js b/js/experimental/runtime/kernel/buffer_decoder_helper.js new file mode 100644 index 0000000000000..eed3c42d07d01 --- /dev/null +++ b/js/experimental/runtime/kernel/buffer_decoder_helper.js @@ -0,0 +1,18 @@ +/** + * @fileoverview Helper methods to create BufferDecoders. + */ +goog.module('protobuf.binary.bufferDecoderHelper'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); + +/** + * @param {...number} bytes + * @return {!BufferDecoder} + */ +function createBufferDecoder(...bytes) { + return BufferDecoder.fromArrayBuffer(new Uint8Array(bytes).buffer); +} + +exports = { + createBufferDecoder, +}; diff --git a/js/experimental/runtime/kernel/buffer_decoder_test.js b/js/experimental/runtime/kernel/buffer_decoder_test.js new file mode 100644 index 0000000000000..17f28966b8e41 --- /dev/null +++ b/js/experimental/runtime/kernel/buffer_decoder_test.js @@ -0,0 +1,242 @@ +/** + * @fileoverview Tests for BufferDecoder. + */ + +goog.module('protobuf.binary.varintsTest'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {CHECK_CRITICAL_STATE, CHECK_STATE} = goog.require('protobuf.internal.checks'); + +goog.setTestOnly(); + +/** + * @param {...number} bytes + * @return {!ArrayBuffer} + */ +function createArrayBuffer(...bytes) { + return new Uint8Array(bytes).buffer; +} + +describe('setCursor does', () => { + it('set the cursor at the position specified', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x0, 0x1)); + expect(bufferDecoder.cursor()).toBe(0); + bufferDecoder.setCursor(1); + expect(bufferDecoder.cursor()).toBe(1); + }); +}); + +describe('skip does', () => { + it('advance the cursor', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x0, 0x1, 0x2)); + bufferDecoder.setCursor(1); + bufferDecoder.skip(1); + expect(bufferDecoder.cursor()).toBe(2); + }); +}); + +describe('Skip varint does', () => { + it('skip a varint', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01)); + bufferDecoder.skipVarint(); + expect(bufferDecoder.cursor()).toBe(1); + }); + + it('fail when varint is larger than 10 bytes', () => { + const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer( + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00)); + + if (CHECK_CRITICAL_STATE) { + expect(() => bufferDecoder.skipVarint()).toThrow(); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + bufferDecoder.skipVarint(); + expect(bufferDecoder.cursor()).toBe(11); + } + }); + + it('fail when varint is beyond end of underlying array', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x80)); + expect(() => bufferDecoder.skipVarint()).toThrow(); + }); +}); + +describe('readVarint64 does', () => { + it('read zero', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00)); + const {lowBits, highBits} = bufferDecoder.getVarint(0); + expect(lowBits).toBe(0); + expect(highBits).toBe(0); + expect(bufferDecoder.cursor()).toBe(1); + }); + + it('read one', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01)); + const {lowBits, highBits} = bufferDecoder.getVarint(0); + expect(lowBits).toBe(1); + expect(highBits).toBe(0); + expect(bufferDecoder.cursor()).toBe(1); + }); + + it('read max value', () => { + const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer( + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01)); + const {lowBits, highBits} = bufferDecoder.getVarint(0); + expect(lowBits).toBe(-1); + expect(highBits).toBe(-1); + expect(bufferDecoder.cursor()).toBe(10); + }); +}); + +describe('readUnsignedVarint32 does', () => { + it('read zero', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00)); + const result = bufferDecoder.getUnsignedVarint32(); + expect(result).toBe(0); + expect(bufferDecoder.cursor()).toBe(1); + }); + + it('read one', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01)); + const result = bufferDecoder.getUnsignedVarint32(); + expect(result).toBe(1); + expect(bufferDecoder.cursor()).toBe(1); + }); + + it('read max int32', () => { + const bufferDecoder = BufferDecoder.fromArrayBuffer( + createArrayBuffer(0xFF, 0xFF, 0xFF, 0xFF, 0x0F)); + const result = bufferDecoder.getUnsignedVarint32(); + expect(result).toBe(4294967295); + expect(bufferDecoder.cursor()).toBe(5); + }); + + it('read max value', () => { + const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer( + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01)); + const result = bufferDecoder.getUnsignedVarint32(); + expect(result).toBe(4294967295); + expect(bufferDecoder.cursor()).toBe(10); + }); + + it('fail if data is longer than 10 bytes', () => { + const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer( + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01)); + if (CHECK_CRITICAL_STATE) { + expect(() => bufferDecoder.getUnsignedVarint32()).toThrow(); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + const result = bufferDecoder.getUnsignedVarint32(); + expect(result).toBe(4294967295); + expect(bufferDecoder.cursor()).toBe(10); + } + }); +}); + +describe('readUnsignedVarint32At does', () => { + it('reads from a specific index', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x1, 0x2)); + const result = bufferDecoder.getUnsignedVarint32At(1); + expect(result).toBe(2); + expect(bufferDecoder.cursor()).toBe(2); + }); +}); + +describe('getFloat32 does', () => { + it('read one', () => { + const bufferDecoder = BufferDecoder.fromArrayBuffer( + createArrayBuffer(0x00, 0x00, 0x80, 0x3F)); + const result = bufferDecoder.getFloat32(0); + expect(result).toBe(1); + expect(bufferDecoder.cursor()).toBe(4); + }); +}); + +describe('getFloat64 does', () => { + it('read one', () => { + const bufferDecoder = BufferDecoder.fromArrayBuffer( + createArrayBuffer(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F)); + const result = bufferDecoder.getFloat64(0); + expect(result).toBe(1); + expect(bufferDecoder.cursor()).toBe(8); + }); +}); + +describe('getInt32 does', () => { + it('read one', () => { + const bufferDecoder = BufferDecoder.fromArrayBuffer( + createArrayBuffer(0x01, 0x00, 0x00, 0x00)); + const result = bufferDecoder.getInt32(0); + expect(result).toBe(1); + expect(bufferDecoder.cursor()).toBe(4); + }); + + it('read minus one', () => { + const bufferDecoder = BufferDecoder.fromArrayBuffer( + createArrayBuffer(0xFF, 0xFF, 0xFF, 0xFF)); + const result = bufferDecoder.getInt32(0); + expect(result).toBe(-1); + expect(bufferDecoder.cursor()).toBe(4); + }); +}); + +describe('getUint32 does', () => { + it('read one', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01, 0x00, 0x00, 0x0)); + const result = bufferDecoder.getUint32(0); + expect(result).toBe(1); + expect(bufferDecoder.cursor()).toBe(4); + }); + + it('read max uint32', () => { + const bufferDecoder = BufferDecoder.fromArrayBuffer( + createArrayBuffer(0xFF, 0xFF, 0xFF, 0xFF)); + const result = bufferDecoder.getUint32(0); + expect(result).toBe(4294967295); + expect(bufferDecoder.cursor()).toBe(4); + }); +}); + +describe('subBufferDecoder does', () => { + it('can create valid sub buffers', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00, 0x01, 0x02)); + + expect(bufferDecoder.subBufferDecoder(0, 0)) + .toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer())); + expect(bufferDecoder.subBufferDecoder(0, 1)) + .toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00))); + expect(bufferDecoder.subBufferDecoder(1, 0)) + .toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer())); + expect(bufferDecoder.subBufferDecoder(1, 1)) + .toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01))); + expect(bufferDecoder.subBufferDecoder(1, 2)) + .toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01, 0x02))); + }); + + it('can not create invalid', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00, 0x01, 0x02)); + if (CHECK_STATE) { + expect(() => bufferDecoder.subBufferDecoder(-1, 1)).toThrow(); + expect(() => bufferDecoder.subBufferDecoder(0, -4)).toThrow(); + expect(() => bufferDecoder.subBufferDecoder(0, 4)).toThrow(); + } + }); +}); diff --git a/js/experimental/runtime/kernel/conformance/conformance_request.js b/js/experimental/runtime/kernel/conformance/conformance_request.js new file mode 100644 index 0000000000000..2d4f1067f893a --- /dev/null +++ b/js/experimental/runtime/kernel/conformance/conformance_request.js @@ -0,0 +1,91 @@ +/** + * @fileoverview Handwritten code of ConformanceRequest. + */ +goog.module('proto.conformance.ConformanceRequest'); + +const Kernel = goog.require('protobuf.runtime.Kernel'); +const WireFormat = goog.require('proto.conformance.WireFormat'); + +/** + * Handwritten code of conformance.ConformanceRequest. + * This is used to send request from the conformance test runner to the testee. + * Check //third_party/protobuf/testing/protobuf/conformance/conformance.proto + * for more details. + * @final + */ +class ConformanceRequest { + /** + * @param {!ArrayBuffer} bytes + * @private + */ + constructor(bytes) { + /** @private @const {!Kernel} */ + this.accessor_ = Kernel.fromArrayBuffer(bytes); + } + + /** + * Create a request instance with the given bytes data. + * @param {!ArrayBuffer} bytes + * @return {!ConformanceRequest} + */ + static deserialize(bytes) { + return new ConformanceRequest(bytes); + } + + /** + * Gets the protobuf_payload. + * @return {!ArrayBuffer} + */ + getProtobufPayload() { + return this.accessor_.getBytesWithDefault(1).toArrayBuffer(); + } + + /** + * Gets the requested_output_format. + * @return {!WireFormat} + */ + getRequestedOutputFormat() { + return /** @type {!WireFormat} */ (this.accessor_.getInt32WithDefault(3)); + } + + /** + * Gets the message_type. + * @return {string} + */ + getMessageType() { + return this.accessor_.getStringWithDefault(4); + } + + /** + * Gets the oneof case for payload field. + * This implementation assumes only one field in a oneof group is set. + * @return {!ConformanceRequest.PayloadCase} + */ + getPayloadCase() { + if (this.accessor_.hasFieldNumber(1)) { + return /** @type {!ConformanceRequest.PayloadCase} */ ( + ConformanceRequest.PayloadCase.PROTOBUF_PAYLOAD); + } else if (this.accessor_.hasFieldNumber(2)) { + return /** @type {!ConformanceRequest.PayloadCase} */ ( + ConformanceRequest.PayloadCase.JSON_PAYLOAD); + } else if (this.accessor_.hasFieldNumber(8)) { + return /** @type {!ConformanceRequest.PayloadCase} */ ( + ConformanceRequest.PayloadCase.TEXT_PAYLOAD); + } else { + return /** @type {!ConformanceRequest.PayloadCase} */ ( + ConformanceRequest.PayloadCase.PAYLOAD_NOT_SET); + } + } +} + +/** + * @enum {number} + */ +ConformanceRequest.PayloadCase = { + PAYLOAD_NOT_SET: 0, + PROTOBUF_PAYLOAD: 1, + JSON_PAYLOAD: 2, + TEXT_PAYLOAD: 8, +}; + +exports = ConformanceRequest; diff --git a/js/experimental/runtime/kernel/conformance/conformance_response.js b/js/experimental/runtime/kernel/conformance/conformance_response.js new file mode 100644 index 0000000000000..482f31bb8efef --- /dev/null +++ b/js/experimental/runtime/kernel/conformance/conformance_response.js @@ -0,0 +1,76 @@ +/** + * @fileoverview Handwritten code of ConformanceResponse. + */ +goog.module('proto.conformance.ConformanceResponse'); + +const ByteString = goog.require('protobuf.ByteString'); +const Kernel = goog.require('protobuf.runtime.Kernel'); + +/** + * Handwritten code of conformance.ConformanceResponse. + * This is used to send response from the conformance testee to the test runner. + * Check //third_party/protobuf/testing/protobuf/conformance/conformance.proto + * for more details. + * @final + */ +class ConformanceResponse { + /** + * @param {!ArrayBuffer} bytes + * @private + */ + constructor(bytes) { + /** @private @const {!Kernel} */ + this.accessor_ = Kernel.fromArrayBuffer(bytes); + } + + /** + * Create an empty response instance. + * @return {!ConformanceResponse} + */ + static createEmpty() { + return new ConformanceResponse(new ArrayBuffer(0)); + } + + /** + * Sets parse_error field. + * @param {string} value + */ + setParseError(value) { + this.accessor_.setString(1, value); + } + + /** + * Sets runtime_error field. + * @param {string} value + */ + setRuntimeError(value) { + this.accessor_.setString(2, value); + } + + /** + * Sets protobuf_payload field. + * @param {!ArrayBuffer} value + */ + setProtobufPayload(value) { + const bytesString = ByteString.fromArrayBuffer(value); + this.accessor_.setBytes(3, bytesString); + } + + /** + * Sets skipped field. + * @param {string} value + */ + setSkipped(value) { + this.accessor_.setString(5, value); + } + + /** + * Serializes into binary data. + * @return {!ArrayBuffer} + */ + serialize() { + return this.accessor_.serialize(); + } +} + +exports = ConformanceResponse; diff --git a/js/experimental/runtime/kernel/conformance/conformance_testee.js b/js/experimental/runtime/kernel/conformance/conformance_testee.js new file mode 100755 index 0000000000000..2945228dd9cd3 --- /dev/null +++ b/js/experimental/runtime/kernel/conformance/conformance_testee.js @@ -0,0 +1,103 @@ +goog.module('javascript.protobuf.conformance'); + +const ConformanceRequest = goog.require('proto.conformance.ConformanceRequest'); +const ConformanceResponse = goog.require('proto.conformance.ConformanceResponse'); +const TestAllTypesProto2 = goog.require('proto.conformance.TestAllTypesProto2'); +const TestAllTypesProto3 = goog.require('proto.conformance.TestAllTypesProto3'); +const WireFormat = goog.require('proto.conformance.WireFormat'); +const base64 = goog.require('goog.crypt.base64'); + +/** + * Creates a `proto.conformance.ConformanceResponse` response according to the + * `proto.conformance.ConformanceRequest` request. + * @param {!ConformanceRequest} request + * @return {!ConformanceResponse} response + */ +function doTest(request) { + const response = ConformanceResponse.createEmpty(); + + if(request.getPayloadCase() === ConformanceRequest.PayloadCase.JSON_PAYLOAD) { + response.setSkipped('Json is not supported as input format.'); + return response; + } + + if(request.getPayloadCase() === ConformanceRequest.PayloadCase.TEXT_PAYLOAD) { + response.setSkipped('Text format is not supported as input format.'); + return response; + } + + if(request.getPayloadCase() === ConformanceRequest.PayloadCase.PAYLOAD_NOT_SET) { + response.setRuntimeError('Request didn\'t have payload.'); + return response; + } + + if(request.getPayloadCase() !== ConformanceRequest.PayloadCase.PROTOBUF_PAYLOAD) { + throw new Error('Request didn\'t have accepted input format.'); + } + + if (request.getRequestedOutputFormat() === WireFormat.JSON) { + response.setSkipped('Json is not supported as output format.'); + return response; + } + + if (request.getRequestedOutputFormat() === WireFormat.TEXT_FORMAT) { + response.setSkipped('Text format is not supported as output format.'); + return response; + } + + if (request.getRequestedOutputFormat() === WireFormat.TEXT_FORMAT) { + response.setRuntimeError('Unspecified output format'); + return response; + } + + if (request.getRequestedOutputFormat() !== WireFormat.PROTOBUF) { + throw new Error('Request didn\'t have accepted output format.'); + } + + if (request.getMessageType() === 'conformance.FailureSet') { + response.setProtobufPayload(new ArrayBuffer(0)); + } else if ( + request.getMessageType() === + 'protobuf_test_messages.proto2.TestAllTypesProto2') { + try { + const testMessage = + TestAllTypesProto2.deserialize(request.getProtobufPayload()); + response.setProtobufPayload(testMessage.serialize()); + } catch (err) { + response.setParseError(err.toString()); + } + } else if ( + request.getMessageType() === + 'protobuf_test_messages.proto3.TestAllTypesProto3') { + try { + const testMessage = + TestAllTypesProto3.deserialize(request.getProtobufPayload()); + response.setProtobufPayload(testMessage.serialize()); + } catch (err) { + response.setParseError(err.toString()); + } + } else { + throw new Error( + `Payload message not supported: ${request.getMessageType()}.`); + } + + return response; +} + +/** + * Same as doTest, but both request and response are in base64. + * @param {string} base64Request + * @return {string} response + */ +function runConformanceTest(base64Request) { + const request = + ConformanceRequest.deserialize( + base64.decodeStringToUint8Array(base64Request).buffer); + const response = doTest(request); + return base64.encodeByteArray(new Uint8Array(response.serialize())); +} + +// Needed for node test +exports.doTest = doTest; +// Needed for browser test +goog.exportSymbol('runConformanceTest', runConformanceTest); diff --git a/js/experimental/runtime/kernel/conformance/conformance_testee_runner_node.js b/js/experimental/runtime/kernel/conformance/conformance_testee_runner_node.js new file mode 100755 index 0000000000000..c12f363ecb023 --- /dev/null +++ b/js/experimental/runtime/kernel/conformance/conformance_testee_runner_node.js @@ -0,0 +1,62 @@ +const ConformanceRequest = goog.require('proto.conformance.ConformanceRequest'); +const {doTest} = goog.require('javascript.protobuf.conformance'); +const fs = require('fs'); + + +/** + * Reads a buffer of N bytes. + * @param {number} bytes Number of bytes to read. + * @return {!Buffer} Buffer which contains data. + */ +function readBuffer(bytes) { + // Linux cannot use process.stdin.fd (which isn't set up as sync) + const buf = new Buffer.alloc(bytes); + const fd = fs.openSync('/dev/stdin', 'r'); + fs.readSync(fd, buf, 0, bytes); + fs.closeSync(fd); + return buf; +} + +/** + * Writes all data in buffer. + * @param {!Buffer} buffer Buffer which contains data. + */ +function writeBuffer(buffer) { + // Under linux, process.stdout.fd is async. Needs to open stdout in a synced + // way for sync write. + const fd = fs.openSync('/dev/stdout', 'w'); + fs.writeSync(fd, buffer, 0, buffer.length); + fs.closeSync(fd); +} + +/** + * Returns true if the test ran successfully, false on legitimate EOF. + * @return {boolean} Whether to continue test. + */ +function runConformanceTest() { + const requestLengthBuf = readBuffer(4); + const requestLength = requestLengthBuf.readInt32LE(0); + if (!requestLength) { + return false; + } + + const serializedRequest = readBuffer(requestLength); + const array = new Uint8Array(serializedRequest); + const request = ConformanceRequest.deserialize(array.buffer); + const response = doTest(request); + + const serializedResponse = response.serialize(); + + const responseLengthBuf = new Buffer.alloc(4); + responseLengthBuf.writeInt32LE(serializedResponse.byteLength, 0); + writeBuffer(responseLengthBuf); + writeBuffer(new Buffer.from(serializedResponse)); + + return true; +} + +while (true) { + if (!runConformanceTest()) { + break; + } +} diff --git a/js/experimental/runtime/kernel/conformance/test_all_types_proto2.js b/js/experimental/runtime/kernel/conformance/test_all_types_proto2.js new file mode 100644 index 0000000000000..3be1beea0fc61 --- /dev/null +++ b/js/experimental/runtime/kernel/conformance/test_all_types_proto2.js @@ -0,0 +1,309 @@ +/** + * @fileoverview Handwritten code of TestAllTypesProto2. + */ +goog.module('proto.conformance.TestAllTypesProto2'); + +const InternalMessage = goog.require('protobuf.binary.InternalMessage'); +const Kernel = goog.require('protobuf.runtime.Kernel'); + +/** + * Handwritten code of conformance.TestAllTypesProto2. + * Check google/protobuf/test_messages_proto3.proto for more details. + * @implements {InternalMessage} + * @final + */ +class TestAllTypesProto2 { + /** + * @param {!Kernel=} accessor + * @private + */ + constructor(accessor = Kernel.createEmpty()) { + /** @private @const {!Kernel} */ + this.accessor_ = accessor; + } + + /** + * @override + * @package + * @return {!Kernel} + */ + internalGetKernel() { + return this.accessor_; + } + + /** + * Create a request instance with the given bytes data. + * If we directly use the accessor created by the binary decoding, the + * Kernel instance will only copy the same data over for encoding. By + * explicitly fetching data from the previous accessor and setting all fields + * into a new accessor, we will actually test encoding/decoding for the binary + * format. + * @param {!ArrayBuffer} bytes + * @return {!TestAllTypesProto2} + */ + static deserialize(bytes) { + const msg = new TestAllTypesProto2(); + const requestAccessor = Kernel.fromArrayBuffer(bytes); + + if (requestAccessor.hasFieldNumber(1)) { + const value = requestAccessor.getInt32WithDefault(1); + msg.accessor_.setInt32(1, value); + } + + if (requestAccessor.hasFieldNumber(2)) { + const value = requestAccessor.getInt64WithDefault(2); + msg.accessor_.setInt64(2, value); + } + + if (requestAccessor.hasFieldNumber(3)) { + const value = requestAccessor.getUint32WithDefault(3); + msg.accessor_.setUint32(3, value); + } + + if (requestAccessor.hasFieldNumber(4)) { + const value = requestAccessor.getUint64WithDefault(4); + msg.accessor_.setUint64(4, value); + } + + if (requestAccessor.hasFieldNumber(5)) { + const value = requestAccessor.getSint32WithDefault(5); + msg.accessor_.setSint32(5, value); + } + + if (requestAccessor.hasFieldNumber(6)) { + const value = requestAccessor.getSint64WithDefault(6); + msg.accessor_.setSint64(6, value); + } + + if (requestAccessor.hasFieldNumber(7)) { + const value = requestAccessor.getFixed32WithDefault(7); + msg.accessor_.setFixed32(7, value); + } + + if (requestAccessor.hasFieldNumber(8)) { + const value = requestAccessor.getFixed64WithDefault(8); + msg.accessor_.setFixed64(8, value); + } + + if (requestAccessor.hasFieldNumber(9)) { + const value = requestAccessor.getSfixed32WithDefault(9); + msg.accessor_.setSfixed32(9, value); + } + + if (requestAccessor.hasFieldNumber(10)) { + const value = requestAccessor.getSfixed64WithDefault(10); + msg.accessor_.setSfixed64(10, value); + } + + if (requestAccessor.hasFieldNumber(11)) { + const value = requestAccessor.getFloatWithDefault(11); + msg.accessor_.setFloat(11, value); + } + + if (requestAccessor.hasFieldNumber(12)) { + const value = requestAccessor.getDoubleWithDefault(12); + msg.accessor_.setDouble(12, value); + } + + if (requestAccessor.hasFieldNumber(13)) { + const value = requestAccessor.getBoolWithDefault(13); + msg.accessor_.setBool(13, value); + } + + if (requestAccessor.hasFieldNumber(14)) { + const value = requestAccessor.getStringWithDefault(14); + msg.accessor_.setString(14, value); + } + + if (requestAccessor.hasFieldNumber(15)) { + const value = requestAccessor.getBytesWithDefault(15); + msg.accessor_.setBytes(15, value); + } + + if (requestAccessor.hasFieldNumber(18)) { + const value = requestAccessor.getMessage( + 18, (accessor) => new TestAllTypesProto2(accessor)); + msg.accessor_.setMessage(18, value); + } + + if (requestAccessor.hasFieldNumber(21)) { + // Unknown enum is not checked here, because even if an enum is unknown, + // it should be kept during encoding. For the purpose of wire format test, + // we can simplify the implementation by treating it as an int32 field, + // which has the same semantic except for the unknown value checking. + const value = requestAccessor.getInt32WithDefault(21); + msg.accessor_.setInt32(21, value); + } + + if (requestAccessor.hasFieldNumber(31)) { + const value = requestAccessor.getRepeatedInt32Iterable(31); + msg.accessor_.setUnpackedInt32Iterable(31, value); + } + + if (requestAccessor.hasFieldNumber(32)) { + const value = requestAccessor.getRepeatedInt64Iterable(32); + msg.accessor_.setUnpackedInt64Iterable(32, value); + } + + if (requestAccessor.hasFieldNumber(33)) { + const value = requestAccessor.getRepeatedUint32Iterable(33); + msg.accessor_.setUnpackedUint32Iterable(33, value); + } + + if (requestAccessor.hasFieldNumber(34)) { + const value = requestAccessor.getRepeatedUint64Iterable(34); + msg.accessor_.setUnpackedUint64Iterable(34, value); + } + + if (requestAccessor.hasFieldNumber(35)) { + const value = requestAccessor.getRepeatedSint32Iterable(35); + msg.accessor_.setUnpackedSint32Iterable(35, value); + } + + if (requestAccessor.hasFieldNumber(36)) { + const value = requestAccessor.getRepeatedSint64Iterable(36); + msg.accessor_.setUnpackedSint64Iterable(36, value); + } + + if (requestAccessor.hasFieldNumber(37)) { + const value = requestAccessor.getRepeatedFixed32Iterable(37); + msg.accessor_.setUnpackedFixed32Iterable(37, value); + } + + if (requestAccessor.hasFieldNumber(38)) { + const value = requestAccessor.getRepeatedFixed64Iterable(38); + msg.accessor_.setUnpackedFixed64Iterable(38, value); + } + + if (requestAccessor.hasFieldNumber(39)) { + const value = requestAccessor.getRepeatedSfixed32Iterable(39); + msg.accessor_.setUnpackedSfixed32Iterable(39, value); + } + + if (requestAccessor.hasFieldNumber(40)) { + const value = requestAccessor.getRepeatedSfixed64Iterable(40); + msg.accessor_.setUnpackedSfixed64Iterable(40, value); + } + + if (requestAccessor.hasFieldNumber(41)) { + const value = requestAccessor.getRepeatedFloatIterable(41); + msg.accessor_.setUnpackedFloatIterable(41, value); + } + + if (requestAccessor.hasFieldNumber(42)) { + const value = requestAccessor.getRepeatedDoubleIterable(42); + msg.accessor_.setUnpackedDoubleIterable(42, value); + } + + if (requestAccessor.hasFieldNumber(43)) { + const value = requestAccessor.getRepeatedBoolIterable(43); + msg.accessor_.setUnpackedBoolIterable(43, value); + } + + if (requestAccessor.hasFieldNumber(44)) { + const value = requestAccessor.getRepeatedStringIterable(44); + msg.accessor_.setRepeatedStringIterable(44, value); + } + + if (requestAccessor.hasFieldNumber(45)) { + const value = requestAccessor.getRepeatedBytesIterable(45); + msg.accessor_.setRepeatedBytesIterable(45, value); + } + + if (requestAccessor.hasFieldNumber(48)) { + const value = requestAccessor.getRepeatedMessageIterable( + 48, (accessor) => new TestAllTypesProto2(accessor)); + msg.accessor_.setRepeatedMessageIterable(48, value); + } + + if (requestAccessor.hasFieldNumber(51)) { + // Unknown enum is not checked here, because even if an enum is unknown, + // it should be kept during encoding. For the purpose of wire format test, + // we can simplify the implementation by treating it as an int32 field, + // which has the same semantic except for the unknown value checking. + const value = requestAccessor.getRepeatedInt32Iterable(51); + msg.accessor_.setUnpackedInt32Iterable(51, value); + } + + if (requestAccessor.hasFieldNumber(75)) { + const value = requestAccessor.getRepeatedInt32Iterable(75); + msg.accessor_.setPackedInt32Iterable(75, value); + } + + if (requestAccessor.hasFieldNumber(76)) { + const value = requestAccessor.getRepeatedInt64Iterable(76); + msg.accessor_.setPackedInt64Iterable(76, value); + } + + if (requestAccessor.hasFieldNumber(77)) { + const value = requestAccessor.getRepeatedUint32Iterable(77); + msg.accessor_.setPackedUint32Iterable(77, value); + } + + if (requestAccessor.hasFieldNumber(78)) { + const value = requestAccessor.getRepeatedUint64Iterable(78); + msg.accessor_.setPackedUint64Iterable(78, value); + } + + if (requestAccessor.hasFieldNumber(79)) { + const value = requestAccessor.getRepeatedSint32Iterable(79); + msg.accessor_.setPackedSint32Iterable(79, value); + } + + if (requestAccessor.hasFieldNumber(80)) { + const value = requestAccessor.getRepeatedSint64Iterable(80); + msg.accessor_.setPackedSint64Iterable(80, value); + } + + if (requestAccessor.hasFieldNumber(81)) { + const value = requestAccessor.getRepeatedFixed32Iterable(81); + msg.accessor_.setPackedFixed32Iterable(81, value); + } + + if (requestAccessor.hasFieldNumber(82)) { + const value = requestAccessor.getRepeatedFixed64Iterable(82); + msg.accessor_.setPackedFixed64Iterable(82, value); + } + + if (requestAccessor.hasFieldNumber(83)) { + const value = requestAccessor.getRepeatedSfixed32Iterable(83); + msg.accessor_.setPackedSfixed32Iterable(83, value); + } + + if (requestAccessor.hasFieldNumber(84)) { + const value = requestAccessor.getRepeatedSfixed64Iterable(84); + msg.accessor_.setPackedSfixed64Iterable(84, value); + } + + if (requestAccessor.hasFieldNumber(85)) { + const value = requestAccessor.getRepeatedFloatIterable(85); + msg.accessor_.setPackedFloatIterable(85, value); + } + + if (requestAccessor.hasFieldNumber(86)) { + const value = requestAccessor.getRepeatedDoubleIterable(86); + msg.accessor_.setPackedDoubleIterable(86, value); + } + + if (requestAccessor.hasFieldNumber(87)) { + const value = requestAccessor.getRepeatedBoolIterable(87); + msg.accessor_.setPackedBoolIterable(87, value); + } + + if (requestAccessor.hasFieldNumber(88)) { + const value = requestAccessor.getRepeatedInt32Iterable(88); + msg.accessor_.setPackedInt32Iterable(88, value); + } + return msg; + } + + /** + * Serializes into binary data. + * @return {!ArrayBuffer} + */ + serialize() { + return this.accessor_.serialize(); + } +} + +exports = TestAllTypesProto2; diff --git a/js/experimental/runtime/kernel/conformance/test_all_types_proto3.js b/js/experimental/runtime/kernel/conformance/test_all_types_proto3.js new file mode 100644 index 0000000000000..c68d370f19205 --- /dev/null +++ b/js/experimental/runtime/kernel/conformance/test_all_types_proto3.js @@ -0,0 +1,310 @@ +/** + * @fileoverview Handwritten code of TestAllTypesProto3. + */ +goog.module('proto.conformance.TestAllTypesProto3'); + +const InternalMessage = goog.require('protobuf.binary.InternalMessage'); +const Kernel = goog.require('protobuf.runtime.Kernel'); + +/** + * Handwritten code of conformance.TestAllTypesProto3. + * Check google/protobuf/test_messages_proto3.proto for more details. + * @implements {InternalMessage} + * @final + */ +class TestAllTypesProto3 { + /** + * @param {!Kernel=} accessor + * @private + */ + constructor(accessor = Kernel.createEmpty()) { + /** @private @const {!Kernel} */ + this.accessor_ = accessor; + } + + /** + * @override + * @package + * @return {!Kernel} + */ + internalGetKernel() { + return this.accessor_; + } + + /** + * Create a request instance with the given bytes data. + * If we directly use the accessor created by the binary decoding, the + * Kernel instance will only copy the same data over for encoding. By + * explicitly fetching data from the previous accessor and setting all fields + * into a new accessor, we will actually test encoding/decoding for the binary + * format. + * @param {!ArrayBuffer} bytes + * @return {!TestAllTypesProto3} + */ + static deserialize(bytes) { + const msg = new TestAllTypesProto3(); + const requestAccessor = Kernel.fromArrayBuffer(bytes); + + if (requestAccessor.hasFieldNumber(1)) { + const value = requestAccessor.getInt32WithDefault(1); + msg.accessor_.setInt32(1, value); + } + + if (requestAccessor.hasFieldNumber(2)) { + const value = requestAccessor.getInt64WithDefault(2); + msg.accessor_.setInt64(2, value); + } + + if (requestAccessor.hasFieldNumber(3)) { + const value = requestAccessor.getUint32WithDefault(3); + msg.accessor_.setUint32(3, value); + } + + if (requestAccessor.hasFieldNumber(4)) { + const value = requestAccessor.getUint64WithDefault(4); + msg.accessor_.setUint64(4, value); + } + + if (requestAccessor.hasFieldNumber(5)) { + const value = requestAccessor.getSint32WithDefault(5); + msg.accessor_.setSint32(5, value); + } + + if (requestAccessor.hasFieldNumber(6)) { + const value = requestAccessor.getSint64WithDefault(6); + msg.accessor_.setSint64(6, value); + } + + if (requestAccessor.hasFieldNumber(7)) { + const value = requestAccessor.getFixed32WithDefault(7); + msg.accessor_.setFixed32(7, value); + } + + if (requestAccessor.hasFieldNumber(8)) { + const value = requestAccessor.getFixed64WithDefault(8); + msg.accessor_.setFixed64(8, value); + } + + if (requestAccessor.hasFieldNumber(9)) { + const value = requestAccessor.getSfixed32WithDefault(9); + msg.accessor_.setSfixed32(9, value); + } + + if (requestAccessor.hasFieldNumber(10)) { + const value = requestAccessor.getSfixed64WithDefault(10); + msg.accessor_.setSfixed64(10, value); + } + + if (requestAccessor.hasFieldNumber(11)) { + const value = requestAccessor.getFloatWithDefault(11); + msg.accessor_.setFloat(11, value); + } + + if (requestAccessor.hasFieldNumber(12)) { + const value = requestAccessor.getDoubleWithDefault(12); + msg.accessor_.setDouble(12, value); + } + + if (requestAccessor.hasFieldNumber(13)) { + const value = requestAccessor.getBoolWithDefault(13); + msg.accessor_.setBool(13, value); + } + + if (requestAccessor.hasFieldNumber(14)) { + const value = requestAccessor.getStringWithDefault(14); + msg.accessor_.setString(14, value); + } + + if (requestAccessor.hasFieldNumber(15)) { + const value = requestAccessor.getBytesWithDefault(15); + msg.accessor_.setBytes(15, value); + } + + if (requestAccessor.hasFieldNumber(18)) { + const value = requestAccessor.getMessage( + 18, (accessor) => new TestAllTypesProto3(accessor)); + msg.accessor_.setMessage(18, value); + } + + if (requestAccessor.hasFieldNumber(21)) { + // Unknown enum is not checked here, because even if an enum is unknown, + // it should be kept during encoding. For the purpose of wire format test, + // we can simplify the implementation by treating it as an int32 field, + // which has the same semantic except for the unknown value checking. + const value = requestAccessor.getInt32WithDefault(21); + msg.accessor_.setInt32(21, value); + } + + if (requestAccessor.hasFieldNumber(31)) { + const value = requestAccessor.getRepeatedInt32Iterable(31); + msg.accessor_.setPackedInt32Iterable(31, value); + } + + if (requestAccessor.hasFieldNumber(32)) { + const value = requestAccessor.getRepeatedInt64Iterable(32); + msg.accessor_.setPackedInt64Iterable(32, value); + } + + if (requestAccessor.hasFieldNumber(33)) { + const value = requestAccessor.getRepeatedUint32Iterable(33); + msg.accessor_.setPackedUint32Iterable(33, value); + } + + if (requestAccessor.hasFieldNumber(34)) { + const value = requestAccessor.getRepeatedUint64Iterable(34); + msg.accessor_.setPackedUint64Iterable(34, value); + } + + if (requestAccessor.hasFieldNumber(35)) { + const value = requestAccessor.getRepeatedSint32Iterable(35); + msg.accessor_.setPackedSint32Iterable(35, value); + } + + if (requestAccessor.hasFieldNumber(36)) { + const value = requestAccessor.getRepeatedSint64Iterable(36); + msg.accessor_.setPackedSint64Iterable(36, value); + } + + if (requestAccessor.hasFieldNumber(37)) { + const value = requestAccessor.getRepeatedFixed32Iterable(37); + msg.accessor_.setPackedFixed32Iterable(37, value); + } + + if (requestAccessor.hasFieldNumber(38)) { + const value = requestAccessor.getRepeatedFixed64Iterable(38); + msg.accessor_.setPackedFixed64Iterable(38, value); + } + + if (requestAccessor.hasFieldNumber(39)) { + const value = requestAccessor.getRepeatedSfixed32Iterable(39); + msg.accessor_.setPackedSfixed32Iterable(39, value); + } + + if (requestAccessor.hasFieldNumber(40)) { + const value = requestAccessor.getRepeatedSfixed64Iterable(40); + msg.accessor_.setPackedSfixed64Iterable(40, value); + } + + if (requestAccessor.hasFieldNumber(41)) { + const value = requestAccessor.getRepeatedFloatIterable(41); + msg.accessor_.setPackedFloatIterable(41, value); + } + + if (requestAccessor.hasFieldNumber(42)) { + const value = requestAccessor.getRepeatedDoubleIterable(42); + msg.accessor_.setPackedDoubleIterable(42, value); + } + + if (requestAccessor.hasFieldNumber(43)) { + const value = requestAccessor.getRepeatedBoolIterable(43); + msg.accessor_.setPackedBoolIterable(43, value); + } + + if (requestAccessor.hasFieldNumber(44)) { + const value = requestAccessor.getRepeatedStringIterable(44); + msg.accessor_.setRepeatedStringIterable(44, value); + } + + if (requestAccessor.hasFieldNumber(45)) { + const value = requestAccessor.getRepeatedBytesIterable(45); + msg.accessor_.setRepeatedBytesIterable(45, value); + } + + if (requestAccessor.hasFieldNumber(48)) { + const value = requestAccessor.getRepeatedMessageIterable( + 48, (accessor) => new TestAllTypesProto3(accessor)); + msg.accessor_.setRepeatedMessageIterable(48, value); + } + + if (requestAccessor.hasFieldNumber(51)) { + // Unknown enum is not checked here, because even if an enum is unknown, + // it should be kept during encoding. For the purpose of wire format test, + // we can simplify the implementation by treating it as an int32 field, + // which has the same semantic except for the unknown value checking. + const value = requestAccessor.getRepeatedInt32Iterable(51); + msg.accessor_.setPackedInt32Iterable(51, value); + } + + if (requestAccessor.hasFieldNumber(89)) { + const value = requestAccessor.getRepeatedInt32Iterable(89); + msg.accessor_.setUnpackedInt32Iterable(89, value); + } + + if (requestAccessor.hasFieldNumber(90)) { + const value = requestAccessor.getRepeatedInt64Iterable(90); + msg.accessor_.setUnpackedInt64Iterable(90, value); + } + + if (requestAccessor.hasFieldNumber(91)) { + const value = requestAccessor.getRepeatedUint32Iterable(91); + msg.accessor_.setUnpackedUint32Iterable(91, value); + } + + if (requestAccessor.hasFieldNumber(92)) { + const value = requestAccessor.getRepeatedUint64Iterable(92); + msg.accessor_.setUnpackedUint64Iterable(92, value); + } + + if (requestAccessor.hasFieldNumber(93)) { + const value = requestAccessor.getRepeatedSint32Iterable(93); + msg.accessor_.setUnpackedSint32Iterable(93, value); + } + + if (requestAccessor.hasFieldNumber(94)) { + const value = requestAccessor.getRepeatedSint64Iterable(94); + msg.accessor_.setUnpackedSint64Iterable(94, value); + } + + if (requestAccessor.hasFieldNumber(95)) { + const value = requestAccessor.getRepeatedFixed32Iterable(95); + msg.accessor_.setUnpackedFixed32Iterable(95, value); + } + + if (requestAccessor.hasFieldNumber(96)) { + const value = requestAccessor.getRepeatedFixed64Iterable(96); + msg.accessor_.setUnpackedFixed64Iterable(96, value); + } + + if (requestAccessor.hasFieldNumber(97)) { + const value = requestAccessor.getRepeatedSfixed32Iterable(97); + msg.accessor_.setUnpackedSfixed32Iterable(97, value); + } + + if (requestAccessor.hasFieldNumber(98)) { + const value = requestAccessor.getRepeatedSfixed64Iterable(98); + msg.accessor_.setUnpackedSfixed64Iterable(98, value); + } + + if (requestAccessor.hasFieldNumber(99)) { + const value = requestAccessor.getRepeatedFloatIterable(99); + msg.accessor_.setUnpackedFloatIterable(99, value); + } + + if (requestAccessor.hasFieldNumber(100)) { + const value = requestAccessor.getRepeatedDoubleIterable(100); + msg.accessor_.setUnpackedDoubleIterable(100, value); + } + + if (requestAccessor.hasFieldNumber(101)) { + const value = requestAccessor.getRepeatedBoolIterable(101); + msg.accessor_.setUnpackedBoolIterable(101, value); + } + + if (requestAccessor.hasFieldNumber(102)) { + const value = requestAccessor.getRepeatedInt32Iterable(102); + msg.accessor_.setUnpackedInt32Iterable(102, value); + } + + return msg; + } + + /** + * Serializes into binary data. + * @return {!ArrayBuffer} + */ + serialize() { + return this.accessor_.serialize(); + } +} + +exports = TestAllTypesProto3; diff --git a/js/experimental/runtime/kernel/conformance/wire_format.js b/js/experimental/runtime/kernel/conformance/wire_format.js new file mode 100644 index 0000000000000..636e827bcdb29 --- /dev/null +++ b/js/experimental/runtime/kernel/conformance/wire_format.js @@ -0,0 +1,16 @@ +/** + * @fileoverview Handwritten code of WireFormat. + */ +goog.module('proto.conformance.WireFormat'); + +/** + * @enum {number} + */ +const WireFormat = { + UNSPECIFIED: 0, + PROTOBUF: 1, + JSON: 2, + TEXT_FORMAT: 4, +}; + +exports = WireFormat; diff --git a/js/experimental/runtime/kernel/double_test_pairs.js b/js/experimental/runtime/kernel/double_test_pairs.js new file mode 100644 index 0000000000000..86e1f26080462 --- /dev/null +++ b/js/experimental/runtime/kernel/double_test_pairs.js @@ -0,0 +1,89 @@ +/** + * @fileoverview Test data for double encoding and decoding. + */ +goog.module('protobuf.binary.doubleTestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of double values and their bit representation. + * This is used to test encoding and decoding from the protobuf wire format. + * @return {!Array<{name: string, doubleValue:number, bufferDecoder: + * !BufferDecoder}>} + */ +function getDoublePairs() { + const doublePairs = [ + { + name: 'zero', + doubleValue: 0, + bufferDecoder: + createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) + }, + { + name: 'minus zero', + doubleValue: -0, + bufferDecoder: + createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80) + }, + { + name: 'one', + doubleValue: 1, + bufferDecoder: + createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F) + }, + { + name: 'minus one', + doubleValue: -1, + bufferDecoder: + createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xBF) + }, + + { + name: 'PI', + doubleValue: Math.PI, + bufferDecoder: + createBufferDecoder(0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 0x09, 0x40) + + }, + { + name: 'max value', + doubleValue: Number.MAX_VALUE, + bufferDecoder: + createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x7F) + }, + { + name: 'min value', + doubleValue: Number.MIN_VALUE, + bufferDecoder: + createBufferDecoder(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) + }, + { + name: 'Infinity', + doubleValue: Infinity, + bufferDecoder: + createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7F) + }, + { + name: 'minus Infinity', + doubleValue: -Infinity, + bufferDecoder: + createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF) + }, + { + name: 'Number.MAX_SAFE_INTEGER', + doubleValue: Number.MAX_SAFE_INTEGER, + bufferDecoder: + createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x43) + }, + { + name: 'Number.MIN_SAFE_INTEGER', + doubleValue: Number.MIN_SAFE_INTEGER, + bufferDecoder: + createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xC3) + }, + ]; + return [...doublePairs]; +} + +exports = {getDoublePairs}; diff --git a/js/experimental/runtime/kernel/field.js b/js/experimental/runtime/kernel/field.js new file mode 100644 index 0000000000000..46d69997baa21 --- /dev/null +++ b/js/experimental/runtime/kernel/field.js @@ -0,0 +1,196 @@ +/** + * @fileoverview Contains classes that hold data for a protobuf field. + */ + +goog.module('protobuf.binary.field'); + +const WireType = goog.requireType('protobuf.binary.WireType'); +const Writer = goog.requireType('protobuf.binary.Writer'); +const {checkDefAndNotNull, checkState} = goog.require('protobuf.internal.checks'); + +/** + * Number of bits taken to represent a wire type. + * @const {number} + */ +const WIRE_TYPE_LENGTH_BITS = 3; + +/** @const {number} */ +const WIRE_TYPE_EXTRACTOR = (1 << WIRE_TYPE_LENGTH_BITS) - 1; + +/** + * An IndexEntry consists of the wire type and the position of a field in the + * binary data. The wire type and the position are encoded into a single number + * to save memory, which can be decoded using Field.getWireType() and + * Field.getStartIndex() methods. + * @typedef {number} + */ +let IndexEntry; + +/** + * An entry containing the index into the binary data and/or the corresponding + * cached JS object(s) for a field. + * @template T + * @final + * @package + */ +class Field { + /** + * Creates a field and inserts the wireType and position of the first + * occurrence of a field. + * @param {!WireType} wireType + * @param {number} startIndex + * @return {!Field} + */ + static fromFirstIndexEntry(wireType, startIndex) { + return new Field([Field.encodeIndexEntry(wireType, startIndex)]); + } + + /** + * @param {T} decodedValue The cached JS object decoded from the binary data. + * @param {function(!Writer, number, T):void|undefined} encoder Write function + * to encode the cache into binary bytes. + * @return {!Field} + * @template T + */ + static fromDecodedValue(decodedValue, encoder) { + return new Field(null, decodedValue, encoder); + } + + /** + * @param {!WireType} wireType + * @param {number} startIndex + * @return {!IndexEntry} + */ + static encodeIndexEntry(wireType, startIndex) { + return startIndex << WIRE_TYPE_LENGTH_BITS | wireType; + } + + /** + * @param {!IndexEntry} indexEntry + * @return {!WireType} + */ + static getWireType(indexEntry) { + return /** @type {!WireType} */ (indexEntry & WIRE_TYPE_EXTRACTOR); + } + + /** + * @param {!IndexEntry} indexEntry + * @return {number} + */ + static getStartIndex(indexEntry) { + return indexEntry >> WIRE_TYPE_LENGTH_BITS; + } + + /** + * @param {?Array} indexArray + * @param {T=} decodedValue + * @param {function(!Writer, number, T):void=} encoder + * @private + */ + constructor(indexArray, decodedValue = undefined, encoder = undefined) { + checkState( + !!indexArray || decodedValue !== undefined, + 'At least one of indexArray and decodedValue must be set'); + + /** @private {?Array} */ + this.indexArray_ = indexArray; + /** @private {T|undefined} */ + this.decodedValue_ = decodedValue; + // TODO: Consider storing an enum to represent encoder + /** @private {function(!Writer, number, T)|undefined} */ + this.encoder_ = encoder; + } + + /** + * Adds a new IndexEntry. + * @param {!WireType} wireType + * @param {number} startIndex + */ + addIndexEntry(wireType, startIndex) { + checkDefAndNotNull(this.indexArray_) + .push(Field.encodeIndexEntry(wireType, startIndex)); + } + + /** + * Returns the array of IndexEntry. + * @return {?Array} + */ + getIndexArray() { + return this.indexArray_; + } + + /** + * Caches the decoded value and sets the write function to encode cache into + * binary bytes. + * @param {T} decodedValue + * @param {function(!Writer, number, T):void|undefined} encoder + */ + setCache(decodedValue, encoder) { + this.decodedValue_ = decodedValue; + this.encoder_ = encoder; + this.maybeRemoveIndexArray_(); + } + + /** + * If the decoded value has been set. + * @return {boolean} + */ + hasDecodedValue() { + return this.decodedValue_ !== undefined; + } + + /** + * Returns the cached decoded value. The value needs to be set when this + * method is called. + * @return {T} + */ + getDecodedValue() { + // Makes sure that the decoded value in the cache has already been set. This + // prevents callers from doing `if (field.getDecodedValue()) {...}` to check + // if a value exist in the cache, because the check might return false even + // if the cache has a valid value set (e.g. 0 or empty string). + checkState(this.decodedValue_ !== undefined); + return this.decodedValue_; + } + + /** + * Returns the write function to encode cache into binary bytes. + * @return {function(!Writer, number, T)|undefined} + */ + getEncoder() { + return this.encoder_; + } + + /** + * Returns a copy of the field, containing the original index entries and a + * shallow copy of the cache. + * @return {!Field} + */ + shallowCopy() { + // Repeated fields are arrays in the cache. + // We have to copy the array to make sure that modifications to a repeated + // field (e.g. add) are not seen on a cloned accessor. + const copiedCache = this.hasDecodedValue() ? + (Array.isArray(this.getDecodedValue()) ? [...this.getDecodedValue()] : + this.getDecodedValue()) : + undefined; + return new Field(this.getIndexArray(), copiedCache, this.getEncoder()); + } + + /** + * @private + */ + maybeRemoveIndexArray_() { + checkState( + this.encoder_ === undefined || this.decodedValue_ !== undefined, + 'Encoder exists but decoded value doesn\'t'); + if (this.encoder_ !== undefined) { + this.indexArray_ = null; + } + } +} + +exports = { + IndexEntry, + Field, +}; diff --git a/js/experimental/runtime/kernel/fixed32_test_pairs.js b/js/experimental/runtime/kernel/fixed32_test_pairs.js new file mode 100644 index 0000000000000..1bbab3eb0440a --- /dev/null +++ b/js/experimental/runtime/kernel/fixed32_test_pairs.js @@ -0,0 +1,36 @@ +/** + * @fileoverview Test data for float encoding and decoding. + */ +goog.module('protobuf.binary.fixed32TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of float values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, intValue: number, bufferDecoder: + * !BufferDecoder}>} + */ +function getFixed32Pairs() { + const fixed32Pairs = [ + { + name: 'zero', + intValue: 0, + bufferDecoder: createBufferDecoder(0x00, 0x00, 0x00, 0x00), + }, + { + name: 'one ', + intValue: 1, + bufferDecoder: createBufferDecoder(0x01, 0x00, 0x00, 0x00) + }, + { + name: 'max int 2^32 -1', + intValue: Math.pow(2, 32) - 1, + bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF) + }, + ]; + return [...fixed32Pairs]; +} + +exports = {getFixed32Pairs}; diff --git a/js/experimental/runtime/kernel/float_test_pairs.js b/js/experimental/runtime/kernel/float_test_pairs.js new file mode 100644 index 0000000000000..816bdc2c9eca4 --- /dev/null +++ b/js/experimental/runtime/kernel/float_test_pairs.js @@ -0,0 +1,78 @@ +/** + * @fileoverview Test data for float encoding and decoding. + */ +goog.module('protobuf.binary.floatTestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of float values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, floatValue:number, bufferDecoder: + * !BufferDecoder}>} + */ +function getFloatPairs() { + const floatPairs = [ + { + name: 'zero', + floatValue: 0, + bufferDecoder: createBufferDecoder(0x00, 0x00, 0x00, 0x00), + }, + { + name: 'minus zero', + floatValue: -0, + bufferDecoder: createBufferDecoder(0x00, 0x00, 0x00, 0x80) + }, + { + name: 'one ', + floatValue: 1, + bufferDecoder: createBufferDecoder(0x00, 0x00, 0x80, 0x3F) + }, + { + name: 'minus one', + floatValue: -1, + bufferDecoder: createBufferDecoder(0x00, 0x00, 0x80, 0xBF) + }, + { + name: 'two', + floatValue: 2, + bufferDecoder: createBufferDecoder(0x00, 0x00, 0x00, 0x40) + }, + { + name: 'max float32', + floatValue: Math.pow(2, 127) * (2 - 1 / Math.pow(2, 23)), + bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0x7F, 0x7F) + }, + + { + name: 'min float32', + floatValue: 1 / Math.pow(2, 127 - 1), + bufferDecoder: createBufferDecoder(0x00, 0x00, 0x80, 0x00) + }, + + { + name: 'Infinity', + floatValue: Infinity, + bufferDecoder: createBufferDecoder(0x00, 0x00, 0x80, 0x7F) + }, + { + name: 'minus Infinity', + floatValue: -Infinity, + bufferDecoder: createBufferDecoder(0x00, 0x00, 0x80, 0xFF) + }, + { + name: '1.5', + floatValue: 1.5, + bufferDecoder: createBufferDecoder(0x00, 0x00, 0xC0, 0x3F) + }, + { + name: '1.6', + floatValue: 1.6, + bufferDecoder: createBufferDecoder(0xCD, 0xCC, 0xCC, 0x3F) + }, + ]; + return [...floatPairs]; +} + +exports = {getFloatPairs}; diff --git a/js/experimental/runtime/kernel/indexer.js b/js/experimental/runtime/kernel/indexer.js new file mode 100644 index 0000000000000..205a34e44de08 --- /dev/null +++ b/js/experimental/runtime/kernel/indexer.js @@ -0,0 +1,55 @@ +/** + * @fileoverview Utilities to index a binary proto by fieldnumbers without + * relying on strutural proto information. + */ +goog.module('protobuf.binary.indexer'); + +const BinaryStorage = goog.require('protobuf.runtime.BinaryStorage'); +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const WireType = goog.require('protobuf.binary.WireType'); +const {Field} = goog.require('protobuf.binary.field'); +const {checkCriticalState} = goog.require('protobuf.internal.checks'); +const {skipField, tagToFieldNumber, tagToWireType} = goog.require('protobuf.binary.tag'); + +/** + * Appends a new entry in the index array for the given field number. + * @param {!BinaryStorage} storage + * @param {number} fieldNumber + * @param {!WireType} wireType + * @param {number} startIndex + */ +function addIndexEntry(storage, fieldNumber, wireType, startIndex) { + const field = storage.get(fieldNumber); + if (field !== undefined) { + field.addIndexEntry(wireType, startIndex); + } else { + storage.set(fieldNumber, Field.fromFirstIndexEntry(wireType, startIndex)); + } +} + +/** + * Creates an index of field locations in a given binary protobuf. + * @param {!BufferDecoder} bufferDecoder + * @param {number|undefined} pivot + * @return {!BinaryStorage} + * @package + */ +function buildIndex(bufferDecoder, pivot) { + bufferDecoder.setCursor(bufferDecoder.startIndex()); + + const storage = new BinaryStorage(pivot); + while (bufferDecoder.hasNext()) { + const tag = bufferDecoder.getUnsignedVarint32(); + const wireType = tagToWireType(tag); + const fieldNumber = tagToFieldNumber(tag); + checkCriticalState(fieldNumber > 0, `Invalid field number ${fieldNumber}`); + addIndexEntry(storage, fieldNumber, wireType, bufferDecoder.cursor()); + skipField(bufferDecoder, wireType, fieldNumber); + } + return storage; +} + +exports = { + buildIndex, + tagToWireType, +}; diff --git a/js/experimental/runtime/kernel/indexer_test.js b/js/experimental/runtime/kernel/indexer_test.js new file mode 100644 index 0000000000000..ffb8807994b5e --- /dev/null +++ b/js/experimental/runtime/kernel/indexer_test.js @@ -0,0 +1,334 @@ +/** + * @fileoverview Tests for indexer.js. + */ +goog.module('protobuf.binary.IndexerTest'); + +goog.setTestOnly(); + +// Note to the reader: +// Since the index behavior changes with the checking level some of the tests +// in this file have to know which checking level is enabled to make correct +// assertions. +// Test are run in all checking levels. +const BinaryStorage = goog.require('protobuf.runtime.BinaryStorage'); +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const WireType = goog.require('protobuf.binary.WireType'); +const {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks'); +const {Field, IndexEntry} = goog.require('protobuf.binary.field'); +const {buildIndex} = goog.require('protobuf.binary.indexer'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * Returns the number of fields stored. + * + * @param {!BinaryStorage} storage + * @return {number} + */ +function getStorageSize(storage) { + let size = 0; + storage.forEach(() => void size++); + return size; +} + +/** + * @type {number} + */ +const PIVOT = 1; + +/** + * Asserts a single IndexEntry at a given field number. + * @param {!BinaryStorage} storage + * @param {number} fieldNumber + * @param {...!IndexEntry} expectedEntries + */ +function assertStorageEntries(storage, fieldNumber, ...expectedEntries) { + expect(getStorageSize(storage)).toBe(1); + + const entryArray = storage.get(fieldNumber).getIndexArray(); + expect(entryArray).not.toBeUndefined(); + expect(entryArray.length).toBe(expectedEntries.length); + + for (let i = 0; i < entryArray.length; i++) { + const storageEntry = entryArray[i]; + const expectedEntry = expectedEntries[i]; + + expect(storageEntry).toBe(expectedEntry); + } +} + +describe('Indexer does', () => { + it('return empty storage for empty array', () => { + const storage = buildIndex(createBufferDecoder(), PIVOT); + expect(storage).not.toBeNull(); + expect(getStorageSize(storage)).toBe(0); + }); + + it('throw for null array', () => { + expect( + () => buildIndex( + /** @type {!BufferDecoder} */ (/** @type {*} */ (null)), PIVOT)) + .toThrow(); + }); + + it('fail for invalid wire type (6)', () => { + expect(() => buildIndex(createBufferDecoder(0x0E, 0x01), PIVOT)) + .toThrowError('Unexpected wire type: 6'); + }); + + it('fail for invalid wire type (7)', () => { + expect(() => buildIndex(createBufferDecoder(0x0F, 0x01), PIVOT)) + .toThrowError('Unexpected wire type: 7'); + }); + + it('index varint', () => { + const data = createBufferDecoder(0x08, 0x01, 0x08, 0x01); + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.VARINT, /* startIndex= */ 1), + Field.encodeIndexEntry(WireType.VARINT, /* startIndex= */ 3)); + }); + + it('index varint with two bytes field number', () => { + const data = createBufferDecoder(0xF8, 0x01, 0x01); + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 31, + Field.encodeIndexEntry(WireType.VARINT, /* startIndex= */ 2)); + }); + + it('fail for varints that are longer than 10 bytes', () => { + const data = createBufferDecoder( + 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00); + if (CHECK_CRITICAL_STATE) { + expect(() => buildIndex(data, PIVOT)) + .toThrowError('Index out of bounds: index: 12 size: 11'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.VARINT, /* startIndex= */ 1)); + } + }); + + it('fail for varints with no data', () => { + const data = createBufferDecoder(0x08); + expect(() => buildIndex(data, PIVOT)).toThrow(); + }); + + it('index fixed64', () => { + const data = createBufferDecoder( + /* first= */ 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + /* second= */ 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08); + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.FIXED64, /* startIndex= */ 1), + Field.encodeIndexEntry(WireType.FIXED64, /* startIndex= */ 10)); + }); + + it('fail for fixed64 data missing in input', () => { + const data = + createBufferDecoder(0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07); + if (CHECK_CRITICAL_STATE) { + expect(() => buildIndex(data, PIVOT)) + .toThrowError('Index out of bounds: index: 9 size: 8'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.FIXED64, /* startIndex= */ 1)); + } + }); + + it('fail for fixed64 tag that has no data after it', () => { + if (CHECK_CRITICAL_STATE) { + const data = createBufferDecoder(0x09); + expect(() => buildIndex(data, PIVOT)) + .toThrowError('Index out of bounds: index: 9 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + const data = createBufferDecoder(0x09); + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.FIXED64, /* startIndex= */ 1)); + } + }); + + it('index delimited', () => { + const data = createBufferDecoder( + /* first= */ 0x0A, 0x02, 0x00, 0x01, /* second= */ 0x0A, 0x02, 0x00, + 0x01); + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.DELIMITED, /* startIndex= */ 1), + Field.encodeIndexEntry(WireType.DELIMITED, /* startIndex= */ 5)); + }); + + it('fail for length deliimted field data missing in input', () => { + const data = createBufferDecoder(0x0A, 0x04, 0x00, 0x01); + if (CHECK_CRITICAL_STATE) { + expect(() => buildIndex(data, PIVOT)) + .toThrowError('Index out of bounds: index: 6 size: 4'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.DELIMITED, /* startIndex= */ 1)); + } + }); + + it('fail for delimited tag that has no data after it', () => { + const data = createBufferDecoder(0x0A); + expect(() => buildIndex(data, PIVOT)).toThrow(); + }); + + it('index fixed32', () => { + const data = createBufferDecoder( + /* first= */ 0x0D, 0x01, 0x02, 0x03, 0x04, /* second= */ 0x0D, 0x01, + 0x02, 0x03, 0x04); + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.FIXED32, /* startIndex= */ 1), + Field.encodeIndexEntry(WireType.FIXED32, /* startIndex= */ 6)); + }); + + it('fail for fixed32 data missing in input', () => { + const data = createBufferDecoder(0x0D, 0x01, 0x02, 0x03); + + if (CHECK_CRITICAL_STATE) { + expect(() => buildIndex(data, PIVOT)) + .toThrowError('Index out of bounds: index: 5 size: 4'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.FIXED32, /* startIndex= */ 1)); + } + }); + + it('fail for fixed32 tag that has no data after it', () => { + if (CHECK_CRITICAL_STATE) { + const data = createBufferDecoder(0x0D); + expect(() => buildIndex(data, PIVOT)) + .toThrowError('Index out of bounds: index: 5 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + const data = createBufferDecoder(0x0D); + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.FIXED32, /* startIndex= */ 1)); + } + }); + + it('index group', () => { + const data = createBufferDecoder( + /* first= */ 0x0B, 0x08, 0x01, 0x0C, /* second= */ 0x0B, 0x08, 0x01, + 0x0C); + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1), + Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 5)); + }); + + it('index group and skips inner group', () => { + const data = + createBufferDecoder(0x0B, 0x0B, 0x08, 0x01, 0x0C, 0x08, 0x01, 0x0C); + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1)); + }); + + it('fail on unmatched stop group', () => { + const data = createBufferDecoder(0x0C, 0x01); + expect(() => buildIndex(data, PIVOT)) + .toThrowError('Unexpected wire type: 4'); + }); + + it('fail for groups without matching stop group', () => { + const data = createBufferDecoder(0x0B, 0x08, 0x01, 0x1C); + if (CHECK_CRITICAL_STATE) { + expect(() => buildIndex(data, PIVOT)) + .toThrowError('Expected stop group for fieldnumber 1 not found.'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1)); + } + }); + + it('fail for groups without stop group', () => { + const data = createBufferDecoder(0x0B, 0x08, 0x01); + if (CHECK_CRITICAL_STATE) { + expect(() => buildIndex(data, PIVOT)).toThrowError('No end group found.'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1)); + } + }); + + it('fail for group tag that has no data after it', () => { + const data = createBufferDecoder(0x0B); + if (CHECK_CRITICAL_STATE) { + expect(() => buildIndex(data, PIVOT)).toThrowError('No end group found.'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + const storage = buildIndex(data, PIVOT); + assertStorageEntries( + storage, /* fieldNumber= */ 1, + Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1)); + } + }); + + it('index too large tag', () => { + const data = createBufferDecoder(0xF8, 0xFF, 0xFF, 0xFF, 0xFF); + expect(() => buildIndex(data, PIVOT)).toThrow(); + }); + + it('fail for varint tag that has no data after it', () => { + const data = createBufferDecoder(0x08); + expect(() => buildIndex(data, PIVOT)).toThrow(); + }); +}); diff --git a/js/experimental/runtime/kernel/int32_test_pairs.js b/js/experimental/runtime/kernel/int32_test_pairs.js new file mode 100644 index 0000000000000..ef4f2e9c134f5 --- /dev/null +++ b/js/experimental/runtime/kernel/int32_test_pairs.js @@ -0,0 +1,71 @@ +/** + * @fileoverview Test data for int32 encoding and decoding. + */ +goog.module('protobuf.binary.int32TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of float values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, intValue:number, bufferDecoder: + * !BufferDecoder, error: ?boolean, skip_writer: ?boolean}>} + */ +function getInt32Pairs() { + const int32Pairs = [ + { + name: 'zero', + intValue: 0, + bufferDecoder: createBufferDecoder(0x00), + }, + { + name: 'one ', + intValue: 1, + bufferDecoder: createBufferDecoder(0x01), + }, + { + name: 'minus one', + intValue: -1, + bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0x0F), + // The writer will encode this with 64 bits, see below + skip_writer: true, + }, + { + name: 'minus one (64bits)', + intValue: -1, + bufferDecoder: createBufferDecoder( + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01), + }, + { + name: 'max signed int 2^31 - 1', + intValue: Math.pow(2, 31) - 1, + bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0x07), + + }, + { + name: 'min signed int -2^31', + intValue: -Math.pow(2, 31), + bufferDecoder: createBufferDecoder(0x80, 0x80, 0x80, 0x80, 0x08), + // The writer will encode this with 64 bits, see below + skip_writer: true, + }, + { + name: 'value min signed int -2^31 (64 bit)', + intValue: -Math.pow(2, 31), + bufferDecoder: createBufferDecoder( + 0x80, 0x80, 0x80, 0x80, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x01), + }, + { + name: 'errors out for 11 bytes', + intValue: -1, + bufferDecoder: createBufferDecoder( + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + error: true, + skip_writer: true, + }, + ]; + return [...int32Pairs]; +} + +exports = {getInt32Pairs}; diff --git a/js/experimental/runtime/kernel/int64_test_pairs.js b/js/experimental/runtime/kernel/int64_test_pairs.js new file mode 100644 index 0000000000000..19ef46ba43592 --- /dev/null +++ b/js/experimental/runtime/kernel/int64_test_pairs.js @@ -0,0 +1,59 @@ +/** + * @fileoverview Test data for int64 encoding and decoding. + */ +goog.module('protobuf.binary.int64TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const Int64 = goog.require('protobuf.Int64'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of float values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, longValue: !Int64, bufferDecoder: + * !BufferDecoder, error: ?boolean, skip_writer: ?boolean}>} + */ +function getInt64Pairs() { + const int64Pairs = [ + { + name: 'zero', + longValue: Int64.fromInt(0), + bufferDecoder: createBufferDecoder(0x00), + }, + { + name: 'one ', + longValue: Int64.fromInt(1), + bufferDecoder: createBufferDecoder(0x01), + }, + { + name: 'minus one', + longValue: Int64.fromInt(-1), + bufferDecoder: createBufferDecoder( + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01), + }, + { + name: 'max signed int 2^63 - 1', + longValue: Int64.fromBits(0xFFFFFFFF, 0x7FFFFFFF), + bufferDecoder: createBufferDecoder( + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F), + + }, + { + name: 'value min signed int -2^63 (64 bit)', + longValue: Int64.fromBits(0xFFFFFFFF, 0xFFFFFFFF), + bufferDecoder: createBufferDecoder( + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01), + }, + { + name: 'errors out for 11 bytes', + longValue: Int64.fromInt(-1), + bufferDecoder: createBufferDecoder( + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + error: true, + skip_writer: true, + }, + ]; + return [...int64Pairs]; +} + +exports = {getInt64Pairs}; diff --git a/js/experimental/runtime/kernel/internal_message.js b/js/experimental/runtime/kernel/internal_message.js new file mode 100644 index 0000000000000..1ba9ed983b7fd --- /dev/null +++ b/js/experimental/runtime/kernel/internal_message.js @@ -0,0 +1,24 @@ +/** + * @fileoverview Internal interface for messages implemented with the binary + * kernel. + */ +goog.module('protobuf.binary.InternalMessage'); + +const Kernel = goog.requireType('protobuf.runtime.Kernel'); + +/** + * Interface that needs to be implemented by messages implemented with the + * binary kernel. This is an internal only interface and should be used only by + * the classes in binary kernel. + * + * @interface + */ +class InternalMessage { + /** + * @package + * @return {!Kernel} + */ + internalGetKernel() {} +} + +exports = InternalMessage; \ No newline at end of file diff --git a/js/experimental/runtime/kernel/kernel.js b/js/experimental/runtime/kernel/kernel.js new file mode 100644 index 0000000000000..bb2608398ae01 --- /dev/null +++ b/js/experimental/runtime/kernel/kernel.js @@ -0,0 +1,4122 @@ +/** + * @fileoverview Kernel is a class to provide type-checked accessing + * (read/write bool/int32/string/...) on binary data. + * + * When creating the Kernel with the binary data, there is no deep + * decoding done (which requires full type information). The deep decoding is + * deferred until the first time accessing (when accessors can provide + * full type information). + * + * Because accessors can be statically analyzed and stripped, unlike eager + * binary decoding (which requires the full type information of all defined + * fields), Kernel will only need the full type information of used + * fields. + */ +goog.module('protobuf.runtime.Kernel'); + +const BinaryStorage = goog.require('protobuf.runtime.BinaryStorage'); +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const ByteString = goog.require('protobuf.ByteString'); +const Int64 = goog.require('protobuf.Int64'); +const InternalMessage = goog.require('protobuf.binary.InternalMessage'); +const Storage = goog.require('protobuf.runtime.Storage'); +const WireType = goog.require('protobuf.binary.WireType'); +const Writer = goog.require('protobuf.binary.Writer'); +const reader = goog.require('protobuf.binary.reader'); +const {CHECK_TYPE, checkCriticalElementIndex, checkCriticalState, checkCriticalType, checkCriticalTypeBool, checkCriticalTypeBoolArray, checkCriticalTypeByteString, checkCriticalTypeByteStringArray, checkCriticalTypeDouble, checkCriticalTypeDoubleArray, checkCriticalTypeFloat, checkCriticalTypeFloatIterable, checkCriticalTypeMessageArray, checkCriticalTypeSignedInt32, checkCriticalTypeSignedInt32Array, checkCriticalTypeSignedInt64, checkCriticalTypeSignedInt64Array, checkCriticalTypeString, checkCriticalTypeStringArray, checkCriticalTypeUnsignedInt32, checkCriticalTypeUnsignedInt32Array, checkDefAndNotNull, checkElementIndex, checkFieldNumber, checkFunctionExists, checkState, checkTypeDouble, checkTypeFloat, checkTypeSignedInt32, checkTypeSignedInt64, checkTypeUnsignedInt32} = goog.require('protobuf.internal.checks'); +const {Field, IndexEntry} = goog.require('protobuf.binary.field'); +const {buildIndex} = goog.require('protobuf.binary.indexer'); +const {createTag, get32BitVarintLength, getTagLength} = goog.require('protobuf.binary.tag'); + + +/** + * Validates the index entry has the correct wire type. + * @param {!IndexEntry} indexEntry + * @param {!WireType} expected + */ +function validateWireType(indexEntry, expected) { + const wireType = Field.getWireType(indexEntry); + checkCriticalState( + wireType === expected, + `Expected wire type: ${expected} but found: ${wireType}`); +} + +/** + * Checks if the object implements InternalMessage interface. + * @param {?} obj + * @return {!InternalMessage} + */ +function checkIsInternalMessage(obj) { + const message = /** @type {!InternalMessage} */ (obj); + checkFunctionExists(message.internalGetKernel); + return message; +} + +/** + * Checks if the instanceCreator returns an instance that implements the + * InternalMessage interface. + * @param {function(!Kernel):T} instanceCreator + * @template T + */ +function checkInstanceCreator(instanceCreator) { + if (CHECK_TYPE) { + const emptyMessage = instanceCreator(Kernel.createEmpty()); + checkFunctionExists(emptyMessage.internalGetKernel); + } +} + +/** + * Reads the last entry of the index array using the given read function. + * This is used to implement parsing singular primitive fields. + * @param {!Array} indexArray + * @param {!BufferDecoder} bufferDecoder + * @param {function(!BufferDecoder, number):T} readFunc + * @param {!WireType} wireType + * @return {T} + * @template T + */ +function readOptional(indexArray, bufferDecoder, readFunc, wireType) { + const index = indexArray.length - 1; + checkElementIndex(index, indexArray.length); + const indexEntry = indexArray[index]; + validateWireType(indexEntry, wireType); + return readFunc(bufferDecoder, Field.getStartIndex(indexEntry)); +} + +/** + * Converts all entries of the index array to the template type using given read + * methods and return an Iterable containing those converted values. + * Primitive repeated fields may be encoded either packed or unpacked. Thus, two + * read methods are needed for those two cases. + * This is used to implement parsing repeated primitive fields. + * @param {!Array} indexArray + * @param {!BufferDecoder} bufferDecoder + * @param {function(!BufferDecoder, number):T} singularReadFunc + * @param {function(!BufferDecoder, number):!Array} packedReadFunc + * @param {!WireType} expectedWireType + * @return {!Array} + * @template T + */ +function readRepeatedPrimitive( + indexArray, bufferDecoder, singularReadFunc, packedReadFunc, + expectedWireType) { + // Fast path when there is a single packed entry. + if (indexArray.length === 1 && + Field.getWireType(indexArray[0]) === WireType.DELIMITED) { + return packedReadFunc(bufferDecoder, Field.getStartIndex(indexArray[0])); + } + + let /** !Array */ result = []; + for (const indexEntry of indexArray) { + const wireType = Field.getWireType(indexEntry); + const startIndex = Field.getStartIndex(indexEntry); + if (wireType === WireType.DELIMITED) { + result = result.concat(packedReadFunc(bufferDecoder, startIndex)); + } else { + validateWireType(indexEntry, expectedWireType); + result.push(singularReadFunc(bufferDecoder, startIndex)); + } + } + return result; +} + +/** + * Converts all entries of the index array to the template type using the given + * read function and return an Array containing those converted values. This is + * used to implement parsing repeated non-primitive fields. + * @param {!Array} indexArray + * @param {!BufferDecoder} bufferDecoder + * @param {function(!BufferDecoder, number):T} singularReadFunc + * @return {!Array} + * @template T + */ +function readRepeatedNonPrimitive(indexArray, bufferDecoder, singularReadFunc) { + const result = new Array(indexArray.length); + for (let i = 0; i < indexArray.length; i++) { + validateWireType(indexArray[i], WireType.DELIMITED); + result[i] = + singularReadFunc(bufferDecoder, Field.getStartIndex(indexArray[i])); + } + return result; +} + +/** + * Converts all entries of the index array to the template type using the given + * read function and return an Array containing those converted values. This is + * used to implement parsing repeated non-primitive fields. + * @param {!Array} indexArray + * @param {!BufferDecoder} bufferDecoder + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {!Array} + * @template T + */ +function readRepeatedGroup( + indexArray, bufferDecoder, fieldNumber, instanceCreator, pivot) { + const result = new Array(indexArray.length); + for (let i = 0; i < indexArray.length; i++) { + result[i] = doReadGroup( + bufferDecoder, indexArray[i], fieldNumber, instanceCreator, pivot); + } + return result; +} + +/** + * Creates a new bytes array to contain all data of a submessage. + * When there are multiple entries, merge them together. + * @param {!Array} indexArray + * @param {!BufferDecoder} bufferDecoder + * @return {!BufferDecoder} + */ +function mergeMessageArrays(indexArray, bufferDecoder) { + const dataArrays = indexArray.map( + indexEntry => + reader.readDelimited(bufferDecoder, Field.getStartIndex(indexEntry))); + return BufferDecoder.merge(dataArrays); +} + +/** + * @param {!Array} indexArray + * @param {!BufferDecoder} bufferDecoder + * @param {number=} pivot + * @return {!Kernel} + */ +function readAccessor(indexArray, bufferDecoder, pivot = undefined) { + checkState(indexArray.length > 0); + let accessorBuffer; + // Faster access for one member. + if (indexArray.length === 1) { + const indexEntry = indexArray[0]; + validateWireType(indexEntry, WireType.DELIMITED); + accessorBuffer = + reader.readDelimited(bufferDecoder, Field.getStartIndex(indexEntry)); + } else { + indexArray.forEach(indexEntry => { + validateWireType(indexEntry, WireType.DELIMITED); + }); + accessorBuffer = mergeMessageArrays(indexArray, bufferDecoder); + } + return Kernel.fromBufferDecoder_(accessorBuffer, pivot); +} + +/** + * Merges all index entries of the index array using the given read function. + * This is used to implement parsing singular message fields. + * @param {!Array} indexArray + * @param {!BufferDecoder} bufferDecoder + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {T} + * @template T + */ +function readMessage(indexArray, bufferDecoder, instanceCreator, pivot) { + checkInstanceCreator(instanceCreator); + const accessor = readAccessor(indexArray, bufferDecoder, pivot); + return instanceCreator(accessor); +} + +/** + * Merges all index entries of the index array using the given read function. + * This is used to implement parsing singular group fields. + * @param {!Array} indexArray + * @param {!BufferDecoder} bufferDecoder + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {T} + * @template T + */ +function readGroup( + indexArray, bufferDecoder, fieldNumber, instanceCreator, pivot) { + checkInstanceCreator(instanceCreator); + checkState(indexArray.length > 0); + return doReadGroup( + bufferDecoder, indexArray[indexArray.length - 1], fieldNumber, + instanceCreator, pivot); +} + +/** + * Merges all index entries of the index array using the given read function. + * This is used to implement parsing singular message fields. + * @param {!BufferDecoder} bufferDecoder + * @param {!IndexEntry} indexEntry + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {T} + * @template T + */ +function doReadGroup( + bufferDecoder, indexEntry, fieldNumber, instanceCreator, pivot) { + validateWireType(indexEntry, WireType.START_GROUP); + const fieldStartIndex = Field.getStartIndex(indexEntry); + const tag = createTag(WireType.START_GROUP, fieldNumber); + const groupTagLength = get32BitVarintLength(tag); + const groupLength = getTagLength( + bufferDecoder, fieldStartIndex, WireType.START_GROUP, fieldNumber); + const accessorBuffer = bufferDecoder.subBufferDecoder( + fieldStartIndex, groupLength - groupTagLength); + const kernel = Kernel.fromBufferDecoder_(accessorBuffer, pivot); + return instanceCreator(kernel); +} + +/** + * @param {!Writer} writer + * @param {number} fieldNumber + * @param {?InternalMessage} value + */ +function writeMessage(writer, fieldNumber, value) { + writer.writeDelimited( + fieldNumber, checkDefAndNotNull(value).internalGetKernel().serialize()); +} + +/** + * @param {!Writer} writer + * @param {number} fieldNumber + * @param {?InternalMessage} value + */ +function writeGroup(writer, fieldNumber, value) { + const kernel = checkDefAndNotNull(value).internalGetKernel(); + writer.writeStartGroup(fieldNumber); + kernel.serializeToWriter(writer); + writer.writeEndGroup(fieldNumber); +} + +/** + * Writes the array of Messages into the writer for the given field number. + * @param {!Writer} writer + * @param {number} fieldNumber + * @param {!Iterable} values + */ +function writeRepeatedMessage(writer, fieldNumber, values) { + for (const value of values) { + writeMessage(writer, fieldNumber, value); + } +} + +/** + * Writes the array of Messages into the writer for the given field number. + * @param {!Writer} writer + * @param {number} fieldNumber + * @param {!Array} values + */ +function writeRepeatedGroup(writer, fieldNumber, values) { + for (const value of values) { + writeGroup(writer, fieldNumber, value); + } +} + +/** + * Array.from has a weird type definition in google3/javascript/externs/es6.js + * and wants the mapping function accept strings. + * @const {function((string|number)): number} + */ +const fround = /** @type {function((string|number)): number} */ (Math.fround); + +/** + * Wraps an array and exposes it as an Iterable. This class is used to provide + * immutable access of the array to the caller. + * @implements {Iterable} + * @template T + */ +class ArrayIterable { + /** + * @param {!Array} array + */ + constructor(array) { + /** @private @const {!Array} */ + this.array_ = array; + } + + /** @return {!Iterator} */ + [Symbol.iterator]() { + return this.array_[Symbol.iterator](); + } +} + +/** + * Accesses protobuf fields on binary format data. Binary data is decoded lazily + * at the first access. + * @final + */ +class Kernel { + /** + * Create a Kernel for the given binary bytes. + * The bytes array is kept by the Kernel. DON'T MODIFY IT. + * @param {!ArrayBuffer} arrayBuffer Binary bytes. + * @param {number=} pivot Fields with a field number no greater than the pivot + * value will be stored in an array for fast access. Other fields will be + * stored in a map. A higher pivot value can improve runtime performance + * at the expense of requiring more memory. It's recommended to set the + * value to the max field number of the message unless the field numbers + * are too sparse. If the value is not set, a default value specified in + * storage.js will be used. + * @return {!Kernel} + */ + static fromArrayBuffer(arrayBuffer, pivot = undefined) { + const bufferDecoder = BufferDecoder.fromArrayBuffer(arrayBuffer); + return Kernel.fromBufferDecoder_(bufferDecoder, pivot); + } + + /** + * Creates an empty Kernel. + * @param {number=} pivot Fields with a field number no greater than the pivot + * value will be stored in an array for fast access. Other fields will be + * stored in a map. A higher pivot value can improve runtime performance + * at the expense of requiring more memory. It's recommended to set the + * value to the max field number of the message unless the field numbers + * are too sparse. If the value is not set, a default value specified in + * storage.js will be used. + * @return {!Kernel} + */ + static createEmpty(pivot = undefined) { + return new Kernel(/* bufferDecoder= */ null, new BinaryStorage(pivot)); + } + + /** + * Create a Kernel for the given binary bytes. + * The bytes array is kept by the Kernel. DON'T MODIFY IT. + * @param {!BufferDecoder} bufferDecoder Binary bytes. + * @param {number|undefined} pivot + * @return {!Kernel} + * @private + */ + static fromBufferDecoder_(bufferDecoder, pivot) { + return new Kernel(bufferDecoder, buildIndex(bufferDecoder, pivot)); + } + + /** + * @param {?BufferDecoder} bufferDecoder Binary bytes. Accessor treats the + * bytes as immutable and will never attempt to write to it. + * @param {!Storage} fields A map of field number to Field. The + * IndexEntry in each Field needs to be populated with the location of the + * field in the binary data. + * @private + */ + constructor(bufferDecoder, fields) { + /** @private @const {?BufferDecoder} */ + this.bufferDecoder_ = bufferDecoder; + /** @private @const {!Storage} */ + this.fields_ = fields; + } + + /** + * Creates a shallow copy of the accessor. + * @return {!Kernel} + */ + shallowCopy() { + return new Kernel(this.bufferDecoder_, this.fields_.shallowCopy()); + } + + /** + * See definition of the pivot parameter on the fromArrayBuffer() method. + * @return {number} + */ + getPivot() { + return this.fields_.getPivot(); + } + + /** + * Clears the field for the given field number. + * @param {number} fieldNumber + */ + clearField(fieldNumber) { + this.fields_.delete(fieldNumber); + } + + /** + * Returns data for a field specified by the given field number. Also cache + * the data if it doesn't already exist in the cache. When no data is + * available, return the given default value. + * @param {number} fieldNumber + * @param {?T} defaultValue + * @param {function(!Array, !BufferDecoder):T} readFunc + * @param {function(!Writer, number, T)=} encoder + * @return {T} + * @template T + * @private + */ + getFieldWithDefault_( + fieldNumber, defaultValue, readFunc, encoder = undefined) { + checkFieldNumber(fieldNumber); + + const field = this.fields_.get(fieldNumber); + if (field === undefined) { + return defaultValue; + } + + if (field.hasDecodedValue()) { + checkState(!encoder || !!field.getEncoder()); + return field.getDecodedValue(); + } + + const parsed = readFunc( + checkDefAndNotNull(field.getIndexArray()), + checkDefAndNotNull(this.bufferDecoder_)); + field.setCache(parsed, encoder); + return parsed; + } + + /** + * Sets data for a singular field specified by the given field number. + * @param {number} fieldNumber + * @param {T} value + * @param {function(!Writer, number, T)} encoder + * @return {T} + * @template T + * @private + */ + setField_(fieldNumber, value, encoder) { + checkFieldNumber(fieldNumber); + this.fields_.set(fieldNumber, Field.fromDecodedValue(value, encoder)); + } + + /** + * Serializes internal contents to binary format bytes array to the + * given writer. + * @param {!Writer} writer + * @package + */ + serializeToWriter(writer) { + // If we use for...of here, jscompiler returns an array of both types for + // fieldNumber and field without specifying which type is for + // field, which prevents us to use fieldNumber. Thus, we use + // forEach here. + this.fields_.forEach((field, fieldNumber) => { + // If encoder doesn't exist, there is no need to encode the value + // because the data in the index is still valid. + if (field.getEncoder() !== undefined) { + const encoder = checkDefAndNotNull(field.getEncoder()); + encoder(writer, fieldNumber, field.getDecodedValue()); + return; + } + + const indexArr = field.getIndexArray(); + if (indexArr) { + for (const indexEntry of indexArr) { + writer.writeTag(fieldNumber, Field.getWireType(indexEntry)); + writer.writeBufferDecoder( + checkDefAndNotNull(this.bufferDecoder_), + Field.getStartIndex(indexEntry), Field.getWireType(indexEntry), + fieldNumber); + } + } + }); + } + + /** + * Serializes internal contents to binary format bytes array. + * @return {!ArrayBuffer} + */ + serialize() { + const writer = new Writer(); + this.serializeToWriter(writer); + return writer.getAndResetResultBuffer(); + } + + /** + * Returns whether data exists at the given field number. + * @param {number} fieldNumber + * @return {boolean} + */ + hasFieldNumber(fieldNumber) { + checkFieldNumber(fieldNumber); + const field = this.fields_.get(fieldNumber); + + if (field === undefined) { + return false; + } + + if (field.getIndexArray() !== null) { + return true; + } + + if (Array.isArray(field.getDecodedValue())) { + // For repeated fields, existence is decided by number of elements. + return (/** !Array */ (field.getDecodedValue())).length > 0; + } + return true; + } + + /*************************************************************************** + * OPTIONAL GETTER METHODS + ***************************************************************************/ + + /** + * Returns data as boolean for the given field number. + * If no default is given, use false as the default. + * @param {number} fieldNumber + * @param {boolean=} defaultValue + * @return {boolean} + */ + getBoolWithDefault(fieldNumber, defaultValue = false) { + return this.getFieldWithDefault_( + fieldNumber, defaultValue, + (indexArray, bytes) => + readOptional(indexArray, bytes, reader.readBool, WireType.VARINT)); + } + + /** + * Returns data as a ByteString for the given field number. + * If no default is given, use false as the default. + * @param {number} fieldNumber + * @param {!ByteString=} defaultValue + * @return {!ByteString} + */ + getBytesWithDefault(fieldNumber, defaultValue = ByteString.EMPTY) { + return this.getFieldWithDefault_( + fieldNumber, defaultValue, + (indexArray, bytes) => readOptional( + indexArray, bytes, reader.readBytes, WireType.DELIMITED)); + } + + /** + * Returns a double for the given field number. + * If no default is given uses zero as the default. + * @param {number} fieldNumber + * @param {number=} defaultValue + * @return {number} + */ + getDoubleWithDefault(fieldNumber, defaultValue = 0) { + checkTypeDouble(defaultValue); + return this.getFieldWithDefault_( + fieldNumber, defaultValue, + (indexArray, bytes) => readOptional( + indexArray, bytes, reader.readDouble, WireType.FIXED64)); + } + + /** + * Returns a fixed32 for the given field number. + * If no default is given zero as the default. + * @param {number} fieldNumber + * @param {number=} defaultValue + * @return {number} + */ + getFixed32WithDefault(fieldNumber, defaultValue = 0) { + checkTypeUnsignedInt32(defaultValue); + return this.getFieldWithDefault_( + fieldNumber, defaultValue, + (indexArray, bytes) => readOptional( + indexArray, bytes, reader.readFixed32, WireType.FIXED32)); + } + + /** + * Returns a fixed64 for the given field number. + * Note: Since g.m.Long does not support unsigned int64 values we are going + * the Java route here for now and simply output the number as a signed int64. + * Users can get to individual bits by themselves. + * @param {number} fieldNumber + * @param {!Int64=} defaultValue + * @return {!Int64} + */ + getFixed64WithDefault(fieldNumber, defaultValue = Int64.getZero()) { + return this.getSfixed64WithDefault(fieldNumber, defaultValue); + } + + /** + * Returns a float for the given field number. + * If no default is given zero as the default. + * @param {number} fieldNumber + * @param {number=} defaultValue + * @return {number} + */ + getFloatWithDefault(fieldNumber, defaultValue = 0) { + checkTypeFloat(defaultValue); + return this.getFieldWithDefault_( + fieldNumber, defaultValue, + (indexArray, bytes) => readOptional( + indexArray, bytes, reader.readFloat, WireType.FIXED32)); + } + + /** + * Returns a int32 for the given field number. + * If no default is given zero as the default. + * @param {number} fieldNumber + * @param {number=} defaultValue + * @return {number} + */ + getInt32WithDefault(fieldNumber, defaultValue = 0) { + checkTypeSignedInt32(defaultValue); + return this.getFieldWithDefault_( + fieldNumber, defaultValue, + (indexArray, bytes) => + readOptional(indexArray, bytes, reader.readInt32, WireType.VARINT)); + } + + /** + * Returns a int64 for the given field number. + * If no default is given zero as the default. + * @param {number} fieldNumber + * @param {!Int64=} defaultValue + * @return {!Int64} + */ + getInt64WithDefault(fieldNumber, defaultValue = Int64.getZero()) { + checkTypeSignedInt64(defaultValue); + return this.getFieldWithDefault_( + fieldNumber, defaultValue, + (indexArray, bytes) => + readOptional(indexArray, bytes, reader.readInt64, WireType.VARINT)); + } + + /** + * Returns a sfixed32 for the given field number. + * If no default is given zero as the default. + * @param {number} fieldNumber + * @param {number=} defaultValue + * @return {number} + */ + getSfixed32WithDefault(fieldNumber, defaultValue = 0) { + checkTypeSignedInt32(defaultValue); + return this.getFieldWithDefault_( + fieldNumber, defaultValue, + (indexArray, bytes) => readOptional( + indexArray, bytes, reader.readSfixed32, WireType.FIXED32)); + } + + /** + * Returns a sfixed64 for the given field number. + * If no default is given zero as the default. + * @param {number} fieldNumber + * @param {!Int64=} defaultValue + * @return {!Int64} + */ + getSfixed64WithDefault(fieldNumber, defaultValue = Int64.getZero()) { + checkTypeSignedInt64(defaultValue); + return this.getFieldWithDefault_( + fieldNumber, defaultValue, + (indexArray, bytes) => readOptional( + indexArray, bytes, reader.readSfixed64, WireType.FIXED64)); + } + + /** + * Returns a sint32 for the given field number. + * If no default is given zero as the default. + * @param {number} fieldNumber + * @param {number=} defaultValue + * @return {number} + */ + getSint32WithDefault(fieldNumber, defaultValue = 0) { + checkTypeSignedInt32(defaultValue); + return this.getFieldWithDefault_( + fieldNumber, defaultValue, + (indexArray, bytes) => readOptional( + indexArray, bytes, reader.readSint32, WireType.VARINT)); + } + + /** + * Returns a sint64 for the given field number. + * If no default is given zero as the default. + * @param {number} fieldNumber + * @param {!Int64=} defaultValue + * @return {!Int64} + */ + getSint64WithDefault(fieldNumber, defaultValue = Int64.getZero()) { + checkTypeSignedInt64(defaultValue); + return this.getFieldWithDefault_( + fieldNumber, defaultValue, + (indexArray, bytes) => readOptional( + indexArray, bytes, reader.readSint64, WireType.VARINT)); + } + + /** + * Returns a string for the given field number. + * If no default is given uses empty string as the default. + * @param {number} fieldNumber + * @param {string=} defaultValue + * @return {string} + */ + getStringWithDefault(fieldNumber, defaultValue = '') { + return this.getFieldWithDefault_( + fieldNumber, defaultValue, + (indexArray, bytes) => readOptional( + indexArray, bytes, reader.readString, WireType.DELIMITED)); + } + + /** + * Returns a uint32 for the given field number. + * If no default is given zero as the default. + * @param {number} fieldNumber + * @param {number=} defaultValue + * @return {number} + */ + getUint32WithDefault(fieldNumber, defaultValue = 0) { + checkTypeUnsignedInt32(defaultValue); + return this.getFieldWithDefault_( + fieldNumber, defaultValue, + (indexArray, bytes) => readOptional( + indexArray, bytes, reader.readUint32, WireType.VARINT)); + } + + /** + * Returns a uint64 for the given field number. + * Note: Since g.m.Long does not support unsigned int64 values we are going + * the Java route here for now and simply output the number as a signed int64. + * Users can get to individual bits by themselves. + * @param {number} fieldNumber + * @param {!Int64=} defaultValue + * @return {!Int64} + */ + getUint64WithDefault(fieldNumber, defaultValue = Int64.getZero()) { + return this.getInt64WithDefault(fieldNumber, defaultValue); + } + + /** + * Returns data as a mutable proto Message for the given field number. + * If no value has been set, return null. + * If hasFieldNumber(fieldNumber) == false before calling, it remains false. + * + * This method should not be used along with getMessage, since calling + * getMessageOrNull after getMessage will not register the encoder. + * + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {?T} + * @template T + */ + getMessageOrNull(fieldNumber, instanceCreator, pivot = undefined) { + return this.getFieldWithDefault_( + fieldNumber, null, + (indexArray, bytes) => + readMessage(indexArray, bytes, instanceCreator, pivot), + writeMessage); + } + + /** + * Returns data as a mutable proto Message for the given field number. + * If no value has been set, return null. + * If hasFieldNumber(fieldNumber) == false before calling, it remains false. + * + * This method should not be used along with getMessage, since calling + * getMessageOrNull after getMessage will not register the encoder. + * + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {?T} + * @template T + */ + getGroupOrNull(fieldNumber, instanceCreator, pivot = undefined) { + return this.getFieldWithDefault_( + fieldNumber, null, + (indexArray, bytes) => + readGroup(indexArray, bytes, fieldNumber, instanceCreator, pivot), + writeGroup); + } + + /** + * Returns data as a mutable proto Message for the given field number. + * If no value has been set previously, creates and attaches an instance. + * Postcondition: hasFieldNumber(fieldNumber) == true. + * + * This method should not be used along with getMessage, since calling + * getMessageAttach after getMessage will not register the encoder. + * + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {T} + * @template T + */ + getMessageAttach(fieldNumber, instanceCreator, pivot = undefined) { + checkInstanceCreator(instanceCreator); + let instance = this.getMessageOrNull(fieldNumber, instanceCreator, pivot); + if (!instance) { + instance = instanceCreator(Kernel.createEmpty()); + this.setField_(fieldNumber, instance, writeMessage); + } + return instance; + } + + /** + * Returns data as a mutable proto Message for the given field number. + * If no value has been set previously, creates and attaches an instance. + * Postcondition: hasFieldNumber(fieldNumber) == true. + * + * This method should not be used along with getMessage, since calling + * getMessageAttach after getMessage will not register the encoder. + * + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {T} + * @template T + */ + getGroupAttach(fieldNumber, instanceCreator, pivot = undefined) { + checkInstanceCreator(instanceCreator); + let instance = this.getGroupOrNull(fieldNumber, instanceCreator, pivot); + if (!instance) { + instance = instanceCreator(Kernel.createEmpty()); + this.setField_(fieldNumber, instance, writeGroup); + } + return instance; + } + + /** + * Returns data as a proto Message for the given field number. + * If no value has been set, return a default instance. + * This default instance is guaranteed to be the same instance, unless this + * field is cleared. + * Does not register the encoder, so changes made to the returned + * sub-message will not be included when serializing the parent message. + * Use getMessageAttach() if the resulting sub-message should be mutable. + * + * This method should not be used along with getMessageOrNull or + * getMessageAttach, since these methods register the encoder. + * + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {T} + * @template T + */ + getMessage(fieldNumber, instanceCreator, pivot = undefined) { + checkInstanceCreator(instanceCreator); + const message = this.getFieldWithDefault_( + fieldNumber, null, + (indexArray, bytes) => + readMessage(indexArray, bytes, instanceCreator, pivot)); + // Returns an empty message as the default value if the field doesn't exist. + // We don't pass the default value to getFieldWithDefault_ to reduce object + // allocation. + return message === null ? instanceCreator(Kernel.createEmpty()) : message; + } + + /** + * Returns data as a proto Message for the given field number. + * If no value has been set, return a default instance. + * This default instance is guaranteed to be the same instance, unless this + * field is cleared. + * Does not register the encoder, so changes made to the returned + * sub-message will not be included when serializing the parent message. + * Use getMessageAttach() if the resulting sub-message should be mutable. + * + * This method should not be used along with getMessageOrNull or + * getMessageAttach, since these methods register the encoder. + * + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {T} + * @template T + */ + getGroup(fieldNumber, instanceCreator, pivot = undefined) { + checkInstanceCreator(instanceCreator); + const message = this.getFieldWithDefault_( + fieldNumber, null, + (indexArray, bytes) => + readGroup(indexArray, bytes, fieldNumber, instanceCreator, pivot)); + // Returns an empty message as the default value if the field doesn't exist. + // We don't pass the default value to getFieldWithDefault_ to reduce object + // allocation. + return message === null ? instanceCreator(Kernel.createEmpty()) : message; + } + + /** + * Returns the accessor for the given singular message, or returns null if + * it hasn't been set. + * @param {number} fieldNumber + * @param {number=} pivot + * @return {?Kernel} + */ + getMessageAccessorOrNull(fieldNumber, pivot = undefined) { + checkFieldNumber(fieldNumber); + const field = this.fields_.get(fieldNumber); + if (field === undefined) { + return null; + } + + if (field.hasDecodedValue()) { + return checkIsInternalMessage(field.getDecodedValue()) + .internalGetKernel(); + } else { + return readAccessor( + checkDefAndNotNull(field.getIndexArray()), + checkDefAndNotNull(this.bufferDecoder_), pivot); + } + } + + /*************************************************************************** + * REPEATED GETTER METHODS + ***************************************************************************/ + + /* Bool */ + + /** + * Returns an Array instance containing boolean values for the given field + * number. + * @param {number} fieldNumber + * @return {!Array} + * @private + */ + getRepeatedBoolArray_(fieldNumber) { + return this.getFieldWithDefault_( + fieldNumber, /* defaultValue= */[], + (indexArray, bytes) => readRepeatedPrimitive( + indexArray, bytes, reader.readBool, reader.readPackedBool, + WireType.VARINT)); + } + + /** + * Returns the element at index for the given field number. + * @param {number} fieldNumber + * @param {number} index + * @return {boolean} + */ + getRepeatedBoolElement(fieldNumber, index) { + const array = this.getRepeatedBoolArray_(fieldNumber); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing boolean values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedBoolIterable(fieldNumber) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedBoolArray_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable(this.getRepeatedBoolArray_(fieldNumber)); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedBoolSize(fieldNumber) { + return this.getRepeatedBoolArray_(fieldNumber).length; + } + + /* Double */ + + /** + * Returns an Array instance containing double values for the given field + * number. + * @param {number} fieldNumber + * @return {!Array} + * @private + */ + getRepeatedDoubleArray_(fieldNumber) { + return this.getFieldWithDefault_( + fieldNumber, /* defaultValue= */[], + (indexArray, bytes) => readRepeatedPrimitive( + indexArray, bytes, reader.readDouble, reader.readPackedDouble, + WireType.FIXED64)); + } + + /** + * Returns the element at index for the given field number. + * @param {number} fieldNumber + * @param {number} index + * @return {number} + */ + getRepeatedDoubleElement(fieldNumber, index) { + const array = this.getRepeatedDoubleArray_(fieldNumber); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing double values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedDoubleIterable(fieldNumber) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedDoubleArray_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable(this.getRepeatedDoubleArray_(fieldNumber)); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedDoubleSize(fieldNumber) { + return this.getRepeatedDoubleArray_(fieldNumber).length; + } + + /* Fixed32 */ + + /** + * Returns an Array instance containing fixed32 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Array} + * @private + */ + getRepeatedFixed32Array_(fieldNumber) { + return this.getFieldWithDefault_( + fieldNumber, /* defaultValue= */[], + (indexArray, bytes) => readRepeatedPrimitive( + indexArray, bytes, reader.readFixed32, reader.readPackedFixed32, + WireType.FIXED32)); + } + + /** + * Returns the element at index for the given field number. + * @param {number} fieldNumber + * @param {number} index + * @return {number} + */ + getRepeatedFixed32Element(fieldNumber, index) { + const array = this.getRepeatedFixed32Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing fixed32 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedFixed32Iterable(fieldNumber) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedFixed32Array_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable(this.getRepeatedFixed32Array_(fieldNumber)); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedFixed32Size(fieldNumber) { + return this.getRepeatedFixed32Array_(fieldNumber).length; + } + + /* Fixed64 */ + + /** + * Returns the element at index for the given field number. + * @param {number} fieldNumber + * @param {number} index + * @return {!Int64} + */ + getRepeatedFixed64Element(fieldNumber, index) { + return this.getRepeatedSfixed64Element(fieldNumber, index); + } + + /** + * Returns an Iterable instance containing fixed64 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedFixed64Iterable(fieldNumber) { + return this.getRepeatedSfixed64Iterable(fieldNumber); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedFixed64Size(fieldNumber) { + return this.getRepeatedSfixed64Size(fieldNumber); + } + + /* Float */ + + /** + * Returns an Array instance containing float values for the given field + * number. + * @param {number} fieldNumber + * @return {!Array} + * @private + */ + getRepeatedFloatArray_(fieldNumber) { + return this.getFieldWithDefault_( + fieldNumber, /* defaultValue= */[], + (indexArray, bytes) => readRepeatedPrimitive( + indexArray, bytes, reader.readFloat, reader.readPackedFloat, + WireType.FIXED32)); + } + + /** + * Returns the element at index for the given field number. + * @param {number} fieldNumber + * @param {number} index + * @return {number} + */ + getRepeatedFloatElement(fieldNumber, index) { + const array = this.getRepeatedFloatArray_(fieldNumber); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing float values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedFloatIterable(fieldNumber) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedFloatArray_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable(this.getRepeatedFloatArray_(fieldNumber)); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedFloatSize(fieldNumber) { + return this.getRepeatedFloatArray_(fieldNumber).length; + } + + /* Int32 */ + + /** + * Returns an Array instance containing int32 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Array} + * @private + */ + getRepeatedInt32Array_(fieldNumber) { + return this.getFieldWithDefault_( + fieldNumber, /* defaultValue= */[], + (indexArray, bytes) => readRepeatedPrimitive( + indexArray, bytes, reader.readInt32, reader.readPackedInt32, + WireType.VARINT)); + } + + /** + * Returns the element at index for the given field number. + * @param {number} fieldNumber + * @param {number} index + * @return {number} + */ + getRepeatedInt32Element(fieldNumber, index) { + const array = this.getRepeatedInt32Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing int32 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedInt32Iterable(fieldNumber) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedInt32Array_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable(this.getRepeatedInt32Array_(fieldNumber)); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedInt32Size(fieldNumber) { + return this.getRepeatedInt32Array_(fieldNumber).length; + } + + /* Int64 */ + + /** + * Returns an Array instance containing int64 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Array} + * @private + */ + getRepeatedInt64Array_(fieldNumber) { + return this.getFieldWithDefault_( + fieldNumber, /* defaultValue= */[], + (indexArray, bytes) => readRepeatedPrimitive( + indexArray, bytes, reader.readInt64, reader.readPackedInt64, + WireType.VARINT)); + } + + /** + * Returns the element at index for the given field number. + * @param {number} fieldNumber + * @param {number} index + * @return {!Int64} + */ + getRepeatedInt64Element(fieldNumber, index) { + const array = this.getRepeatedInt64Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing int64 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedInt64Iterable(fieldNumber) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedInt64Array_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable(this.getRepeatedInt64Array_(fieldNumber)); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedInt64Size(fieldNumber) { + return this.getRepeatedInt64Array_(fieldNumber).length; + } + + /* Sfixed32 */ + + /** + * Returns an Array instance containing sfixed32 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Array} + * @private + */ + getRepeatedSfixed32Array_(fieldNumber) { + return this.getFieldWithDefault_( + fieldNumber, /* defaultValue= */[], + (indexArray, bytes) => readRepeatedPrimitive( + indexArray, bytes, reader.readSfixed32, reader.readPackedSfixed32, + WireType.FIXED32)); + } + + /** + * Returns the element at index for the given field number. + * @param {number} fieldNumber + * @param {number} index + * @return {number} + */ + getRepeatedSfixed32Element(fieldNumber, index) { + const array = this.getRepeatedSfixed32Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing sfixed32 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedSfixed32Iterable(fieldNumber) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedSfixed32Array_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable(this.getRepeatedSfixed32Array_(fieldNumber)); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedSfixed32Size(fieldNumber) { + return this.getRepeatedSfixed32Array_(fieldNumber).length; + } + + /* Sfixed64 */ + + /** + * Returns an Array instance containing sfixed64 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Array} + * @private + */ + getRepeatedSfixed64Array_(fieldNumber) { + return this.getFieldWithDefault_( + fieldNumber, /* defaultValue= */[], + (indexArray, bytes) => readRepeatedPrimitive( + indexArray, bytes, reader.readSfixed64, reader.readPackedSfixed64, + WireType.FIXED64)); + } + + /** + * Returns the element at index for the given field number. + * @param {number} fieldNumber + * @param {number} index + * @return {!Int64} + */ + getRepeatedSfixed64Element(fieldNumber, index) { + const array = this.getRepeatedSfixed64Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing sfixed64 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedSfixed64Iterable(fieldNumber) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedSfixed64Array_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable(this.getRepeatedSfixed64Array_(fieldNumber)); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedSfixed64Size(fieldNumber) { + return this.getRepeatedSfixed64Array_(fieldNumber).length; + } + + /* Sint32 */ + + /** + * Returns an Array instance containing sint32 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Array} + * @private + */ + getRepeatedSint32Array_(fieldNumber) { + return this.getFieldWithDefault_( + fieldNumber, /* defaultValue= */[], + (indexArray, bytes) => readRepeatedPrimitive( + indexArray, bytes, reader.readSint32, reader.readPackedSint32, + WireType.VARINT)); + } + + /** + * Returns the element at index for the given field number. + * @param {number} fieldNumber + * @param {number} index + * @return {number} + */ + getRepeatedSint32Element(fieldNumber, index) { + const array = this.getRepeatedSint32Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing sint32 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedSint32Iterable(fieldNumber) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedSint32Array_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable(this.getRepeatedSint32Array_(fieldNumber)); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedSint32Size(fieldNumber) { + return this.getRepeatedSint32Array_(fieldNumber).length; + } + + /* Sint64 */ + + /** + * Returns an Array instance containing sint64 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Array} + * @private + */ + getRepeatedSint64Array_(fieldNumber) { + return this.getFieldWithDefault_( + fieldNumber, /* defaultValue= */[], + (indexArray, bytes) => readRepeatedPrimitive( + indexArray, bytes, reader.readSint64, reader.readPackedSint64, + WireType.VARINT)); + } + + /** + * Returns the element at index for the given field number. + * @param {number} fieldNumber + * @param {number} index + * @return {!Int64} + */ + getRepeatedSint64Element(fieldNumber, index) { + const array = this.getRepeatedSint64Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing sint64 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedSint64Iterable(fieldNumber) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedSint64Array_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable(this.getRepeatedSint64Array_(fieldNumber)); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedSint64Size(fieldNumber) { + return this.getRepeatedSint64Array_(fieldNumber).length; + } + + /* Uint32 */ + + /** + * Returns an Array instance containing uint32 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Array} + * @private + */ + getRepeatedUint32Array_(fieldNumber) { + return this.getFieldWithDefault_( + fieldNumber, /* defaultValue= */[], + (indexArray, bytes) => readRepeatedPrimitive( + indexArray, bytes, reader.readUint32, reader.readPackedUint32, + WireType.VARINT)); + } + + /** + * Returns the element at index for the given field number. + * @param {number} fieldNumber + * @param {number} index + * @return {number} + */ + getRepeatedUint32Element(fieldNumber, index) { + const array = this.getRepeatedUint32Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing uint32 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedUint32Iterable(fieldNumber) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedUint32Array_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable(this.getRepeatedUint32Array_(fieldNumber)); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedUint32Size(fieldNumber) { + return this.getRepeatedUint32Array_(fieldNumber).length; + } + + /* Uint64 */ + + /** + * Returns the element at index for the given field number. + * @param {number} fieldNumber + * @param {number} index + * @return {!Int64} + */ + getRepeatedUint64Element(fieldNumber, index) { + return this.getRepeatedInt64Element(fieldNumber, index); + } + + /** + * Returns an Iterable instance containing uint64 values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedUint64Iterable(fieldNumber) { + return this.getRepeatedInt64Iterable(fieldNumber); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedUint64Size(fieldNumber) { + return this.getRepeatedInt64Size(fieldNumber); + } + + /* Bytes */ + + /** + * Returns an array instance containing bytes values for the given field + * number. + * @param {number} fieldNumber + * @return {!Array} + * @private + */ + getRepeatedBytesArray_(fieldNumber) { + return this.getFieldWithDefault_( + fieldNumber, /* defaultValue= */[], + (indexArray, bytes) => + readRepeatedNonPrimitive(indexArray, bytes, reader.readBytes)); + } + + /** + * Returns the element at index for the given field number as a bytes. + * @param {number} fieldNumber + * @param {number} index + * @return {!ByteString} + */ + getRepeatedBytesElement(fieldNumber, index) { + const array = this.getRepeatedBytesArray_(fieldNumber); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing bytes values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedBytesIterable(fieldNumber) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedBytesArray_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable(this.getRepeatedBytesArray_(fieldNumber)); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedBytesSize(fieldNumber) { + return this.getRepeatedBytesArray_(fieldNumber).length; + } + + /* String */ + + /** + * Returns an array instance containing string values for the given field + * number. + * @param {number} fieldNumber + * @return {!Array} + * @private + */ + getRepeatedStringArray_(fieldNumber) { + return this.getFieldWithDefault_( + fieldNumber, /* defaultValue= */[], + (indexArray, bufferDecoder) => readRepeatedNonPrimitive( + indexArray, bufferDecoder, reader.readString)); + } + + /** + * Returns the element at index for the given field number as a string. + * @param {number} fieldNumber + * @param {number} index + * @return {string} + */ + getRepeatedStringElement(fieldNumber, index) { + const array = this.getRepeatedStringArray_(fieldNumber); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing string values for the given field + * number. + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedStringIterable(fieldNumber) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedStringArray_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable(this.getRepeatedStringArray_(fieldNumber)); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedStringSize(fieldNumber) { + return this.getRepeatedStringArray_(fieldNumber).length; + } + + /* Message */ + + /** + * Returns an Array instance containing boolean values for the given field + * number. + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number|undefined} pivot + * @return {!Array} + * @template T + * @private + */ + getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot) { + // This method can be shortened using getFieldWithDefault and + // getRepeatedNonPrimitive methods. But that will require creating and + // passing a reader closure every time getRepeatedMessageArray_ is called, + // which is expensive. + checkInstanceCreator(instanceCreator); + checkFieldNumber(fieldNumber); + + const field = this.fields_.get(fieldNumber); + if (field === undefined) { + return []; + } + + if (field.hasDecodedValue()) { + return field.getDecodedValue(); + } + + const indexArray = checkDefAndNotNull(field.getIndexArray()); + const result = new Array(indexArray.length); + for (let i = 0; i < indexArray.length; i++) { + validateWireType(indexArray[i], WireType.DELIMITED); + const subMessageBuffer = reader.readDelimited( + checkDefAndNotNull(this.bufferDecoder_), + Field.getStartIndex(indexArray[i])); + result[i] = + instanceCreator(Kernel.fromBufferDecoder_(subMessageBuffer, pivot)); + } + field.setCache(result, writeRepeatedMessage); + + return result; + } + + /** + * Returns the element at index for the given field number as a message. + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number} index + * @param {number=} pivot + * @return {T} + * @template T + */ + getRepeatedMessageElement( + fieldNumber, instanceCreator, index, pivot = undefined) { + const array = + this.getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing message values for the given field + * number. + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {!Iterable} + * @template T + */ + getRepeatedMessageIterable(fieldNumber, instanceCreator, pivot = undefined) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedMessageArray_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable( + this.getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot)); + } + + /** + * Returns an Iterable instance containing message accessors for the given + * field number. + * @param {number} fieldNumber + * @param {number=} pivot + * @return {!Iterable} + */ + getRepeatedMessageAccessorIterable(fieldNumber, pivot = undefined) { + checkFieldNumber(fieldNumber); + + const field = this.fields_.get(fieldNumber); + if (!field) { + return []; + } + + if (field.hasDecodedValue()) { + return new ArrayIterable(field.getDecodedValue().map( + value => checkIsInternalMessage(value).internalGetKernel())); + } + + const readMessageFunc = (bufferDecoder, start) => Kernel.fromBufferDecoder_( + reader.readDelimited(bufferDecoder, start), pivot); + const array = readRepeatedNonPrimitive( + checkDefAndNotNull(field.getIndexArray()), + checkDefAndNotNull(this.bufferDecoder_), readMessageFunc); + return new ArrayIterable(array); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @return {number} + * @param {number=} pivot + * @template T + */ + getRepeatedMessageSize(fieldNumber, instanceCreator, pivot = undefined) { + return this.getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot) + .length; + } + + /** + * Returns an Array instance containing boolean values for the given field + * number. + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number|undefined} pivot + * @return {!Array} + * @template T + * @private + */ + getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot) { + return this.getFieldWithDefault_( + fieldNumber, [], + (indexArray, bufferDecoder) => readRepeatedGroup( + indexArray, bufferDecoder, fieldNumber, instanceCreator, pivot), + writeRepeatedGroup); + } + + /** + * Returns the element at index for the given field number as a group. + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number} index + * @param {number=} pivot + * @return {T} + * @template T + */ + getRepeatedGroupElement( + fieldNumber, instanceCreator, index, pivot = undefined) { + const array = + this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot); + checkCriticalElementIndex(index, array.length); + return array[index]; + } + + /** + * Returns an Iterable instance containing group values for the given field + * number. + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {!Iterable} + * @template T + */ + getRepeatedGroupIterable(fieldNumber, instanceCreator, pivot = undefined) { + // Don't split this statement unless needed. JS compiler thinks + // getRepeatedMessageArray_ might have side effects and doesn't inline the + // call in the compiled code. See cl/293894484 for details. + return new ArrayIterable( + this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot)); + } + + /** + * Returns the size of the repeated field. + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @return {number} + * @param {number=} pivot + * @template T + */ + getRepeatedGroupSize(fieldNumber, instanceCreator, pivot = undefined) { + return this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot) + .length; + } + + /*************************************************************************** + * OPTIONAL SETTER METHODS + ***************************************************************************/ + + /** + * Sets a boolean value to the field with the given field number. + * @param {number} fieldNumber + * @param {boolean} value + */ + setBool(fieldNumber, value) { + checkCriticalTypeBool(value); + this.setField_(fieldNumber, value, (writer, fieldNumber, value) => { + writer.writeBool(fieldNumber, value); + }); + } + + /** + * Sets a boolean value to the field with the given field number. + * @param {number} fieldNumber + * @param {!ByteString} value + */ + setBytes(fieldNumber, value) { + checkCriticalTypeByteString(value); + this.setField_(fieldNumber, value, (writer, fieldNumber, value) => { + writer.writeBytes(fieldNumber, value); + }); + } + + /** + * Sets a double value to the field with the given field number. + * @param {number} fieldNumber + * @param {number} value + */ + setDouble(fieldNumber, value) { + checkCriticalTypeDouble(value); + this.setField_(fieldNumber, value, (writer, fieldNumber, value) => { + writer.writeDouble(fieldNumber, value); + }); + } + + /** + * Sets a fixed32 value to the field with the given field number. + * @param {number} fieldNumber + * @param {number} value + */ + setFixed32(fieldNumber, value) { + checkCriticalTypeUnsignedInt32(value); + this.setField_(fieldNumber, value, (writer, fieldNumber, value) => { + writer.writeFixed32(fieldNumber, value); + }); + } + + /** + * Sets a uint64 value to the field with the given field number.\ + * Note: Since g.m.Long does not support unsigned int64 values we are going + * the Java route here for now and simply output the number as a signed int64. + * Users can get to individual bits by themselves. + * @param {number} fieldNumber + * @param {!Int64} value + */ + setFixed64(fieldNumber, value) { + this.setSfixed64(fieldNumber, value); + } + + /** + * Sets a float value to the field with the given field number. + * @param {number} fieldNumber + * @param {number} value + */ + setFloat(fieldNumber, value) { + checkCriticalTypeFloat(value); + // Eagerly round to 32-bit precision so that reading back after set will + // yield the same value a reader will receive after serialization. + const floatValue = Math.fround(value); + this.setField_(fieldNumber, floatValue, (writer, fieldNumber, value) => { + writer.writeFloat(fieldNumber, value); + }); + } + + /** + * Sets a int32 value to the field with the given field number. + * @param {number} fieldNumber + * @param {number} value + */ + setInt32(fieldNumber, value) { + checkCriticalTypeSignedInt32(value); + this.setField_(fieldNumber, value, (writer, fieldNumber, value) => { + writer.writeInt32(fieldNumber, value); + }); + } + + /** + * Sets a int64 value to the field with the given field number. + * @param {number} fieldNumber + * @param {!Int64} value + */ + setInt64(fieldNumber, value) { + checkCriticalTypeSignedInt64(value); + this.setField_(fieldNumber, value, (writer, fieldNumber, value) => { + writer.writeInt64(fieldNumber, value); + }); + } + + /** + * Sets a sfixed32 value to the field with the given field number. + * @param {number} fieldNumber + * @param {number} value + */ + setSfixed32(fieldNumber, value) { + checkCriticalTypeSignedInt32(value); + this.setField_(fieldNumber, value, (writer, fieldNumber, value) => { + writer.writeSfixed32(fieldNumber, value); + }); + } + + /** + * Sets a sfixed64 value to the field with the given field number. + * @param {number} fieldNumber + * @param {!Int64} value + */ + setSfixed64(fieldNumber, value) { + checkCriticalTypeSignedInt64(value); + this.setField_(fieldNumber, value, (writer, fieldNumber, value) => { + writer.writeSfixed64(fieldNumber, value); + }); + } + + /** + * Sets a sint32 value to the field with the given field number. + * @param {number} fieldNumber + * @param {number} value + */ + setSint32(fieldNumber, value) { + checkCriticalTypeSignedInt32(value); + this.setField_(fieldNumber, value, (writer, fieldNumber, value) => { + writer.writeSint32(fieldNumber, value); + }); + } + + /** + * Sets a sint64 value to the field with the given field number. + * @param {number} fieldNumber + * @param {!Int64} value + */ + setSint64(fieldNumber, value) { + checkCriticalTypeSignedInt64(value); + this.setField_(fieldNumber, value, (writer, fieldNumber, value) => { + writer.writeSint64(fieldNumber, value); + }); + } + + /** + * Sets a boolean value to the field with the given field number. + * @param {number} fieldNumber + * @param {string} value + */ + setString(fieldNumber, value) { + checkCriticalTypeString(value); + this.setField_(fieldNumber, value, (writer, fieldNumber, value) => { + writer.writeString(fieldNumber, value); + }); + } + + /** + * Sets a uint32 value to the field with the given field number. + * @param {number} fieldNumber + * @param {number} value + */ + setUint32(fieldNumber, value) { + checkCriticalTypeUnsignedInt32(value); + this.setField_(fieldNumber, value, (writer, fieldNumber, value) => { + writer.writeUint32(fieldNumber, value); + }); + } + + /** + * Sets a uint64 value to the field with the given field number.\ + * Note: Since g.m.Long does not support unsigned int64 values we are going + * the Java route here for now and simply output the number as a signed int64. + * Users can get to individual bits by themselves. + * @param {number} fieldNumber + * @param {!Int64} value + */ + setUint64(fieldNumber, value) { + this.setInt64(fieldNumber, value); + } + + /** + * Sets a proto Group to the field with the given field number. + * Instead of working with the Kernel inside of the message directly, we + * need the message instance to keep its reference equality for subsequent + * gettings. + * @param {number} fieldNumber + * @param {!InternalMessage} value + */ + setGroup(fieldNumber, value) { + checkCriticalType( + value !== null, 'Given value is not a message instance: null'); + this.setField_(fieldNumber, value, writeGroup); + } + + /** + * Sets a proto Message to the field with the given field number. + * Instead of working with the Kernel inside of the message directly, we + * need the message instance to keep its reference equality for subsequent + * gettings. + * @param {number} fieldNumber + * @param {!InternalMessage} value + */ + setMessage(fieldNumber, value) { + checkCriticalType( + value !== null, 'Given value is not a message instance: null'); + this.setField_(fieldNumber, value, writeMessage); + } + + /*************************************************************************** + * REPEATED SETTER METHODS + ***************************************************************************/ + + /* Bool */ + + /** + * Adds all boolean values into the field for the given field number. + * How these values are encoded depends on the given write function. + * @param {number} fieldNumber + * @param {!Iterable} values + * @param {function(!Writer, number, !Array): undefined} encoder + * @private + */ + addRepeatedBoolIterable_(fieldNumber, values, encoder) { + const array = [...this.getRepeatedBoolArray_(fieldNumber), ...values]; + checkCriticalTypeBoolArray(array); + // Needs to set it back because the default empty array was not cached. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Adds a single boolean value into the field for the given field number. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {boolean} value + */ + addPackedBoolElement(fieldNumber, value) { + this.addRepeatedBoolIterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writePackedBool(fieldNumber, values); + }); + } + + /** + * Adds all boolean values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedBoolIterable(fieldNumber, values) { + this.addRepeatedBoolIterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writePackedBool(fieldNumber, values); + }); + } + + /** + * Adds a single boolean value into the field for the given field number. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {boolean} value + */ + addUnpackedBoolElement(fieldNumber, value) { + this.addRepeatedBoolIterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writeRepeatedBool(fieldNumber, values); + }); + } + + /** + * Adds all boolean values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedBoolIterable(fieldNumber, values) { + this.addRepeatedBoolIterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writeRepeatedBool(fieldNumber, values); + }); + } + + /** + * Sets a single boolean value into the field for the given field number at + * the given index. How these values are encoded depends on the given write + * function. + * @param {number} fieldNumber + * @param {number} index + * @param {boolean} value + * @param {function(!Writer, number, !Array): undefined} encoder + * @throws {!Error} if index is out of range when check mode is critical + * @private + */ + setRepeatedBoolElement_(fieldNumber, index, value, encoder) { + checkCriticalTypeBool(value); + const array = this.getRepeatedBoolArray_(fieldNumber); + checkCriticalElementIndex(index, array.length); + array[index] = value; + // Needs to set it back to set encoder. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Sets a single boolean value into the field for the given field number at + * the given index. All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} index + * @param {boolean} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedBoolElement(fieldNumber, index, value) { + this.setRepeatedBoolElement_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writePackedBool(fieldNumber, values); + }); + } + + /** + * Sets all boolean values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedBoolIterable(fieldNumber, values) { + const /** !Array */ array = Array.from(values); + checkCriticalTypeBoolArray(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writePackedBool(fieldNumber, values); + }); + } + + /** + * Sets a single boolean value into the field for the given field number at + * the given index. All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} index + * @param {boolean} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedBoolElement(fieldNumber, index, value) { + this.setRepeatedBoolElement_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writeRepeatedBool(fieldNumber, values); + }); + } + + /** + * Sets all boolean values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedBoolIterable(fieldNumber, values) { + const /** !Array */ array = Array.from(values); + checkCriticalTypeBoolArray(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedBool(fieldNumber, values); + }); + } + + /* Double */ + + /** + * Adds all double values into the field for the given field number. + * How these values are encoded depends on the given write function. + * @param {number} fieldNumber + * @param {!Iterable} values + * @param {function(!Writer, number, !Array): undefined} encoder + * @private + */ + addRepeatedDoubleIterable_(fieldNumber, values, encoder) { + const array = [...this.getRepeatedDoubleArray_(fieldNumber), ...values]; + checkCriticalTypeDoubleArray(array); + // Needs to set it back because the default empty array was not cached. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Adds a single double value into the field for the given field number. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} value + */ + addPackedDoubleElement(fieldNumber, value) { + this.addRepeatedDoubleIterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writePackedDouble(fieldNumber, values); + }); + } + + /** + * Adds all double values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedDoubleIterable(fieldNumber, values) { + this.addRepeatedDoubleIterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writePackedDouble(fieldNumber, values); + }); + } + + /** + * Adds a single double value into the field for the given field number. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} value + */ + addUnpackedDoubleElement(fieldNumber, value) { + this.addRepeatedDoubleIterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writeRepeatedDouble(fieldNumber, values); + }); + } + + /** + * Adds all double values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedDoubleIterable(fieldNumber, values) { + this.addRepeatedDoubleIterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writeRepeatedDouble(fieldNumber, values); + }); + } + + /** + * Sets a single double value into the field for the given field number at the + * given index. + * How these values are encoded depends on the given write function. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @param {function(!Writer, number, !Array): undefined} encoder + * @throws {!Error} if index is out of range when check mode is critical + * @private + */ + setRepeatedDoubleElement_(fieldNumber, index, value, encoder) { + checkCriticalTypeDouble(value); + const array = this.getRepeatedDoubleArray_(fieldNumber); + checkCriticalElementIndex(index, array.length); + array[index] = value; + // Needs to set it back to set encoder. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Sets a single double value into the field for the given field number at the + * given index. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedDoubleElement(fieldNumber, index, value) { + this.setRepeatedDoubleElement_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writePackedDouble(fieldNumber, values); + }); + } + + /** + * Sets all double values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedDoubleIterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeDoubleArray(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writePackedDouble(fieldNumber, values); + }); + } + + /** + * Sets a single double value into the field for the given field number at the + * given index. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedDoubleElement(fieldNumber, index, value) { + this.setRepeatedDoubleElement_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writeRepeatedDouble(fieldNumber, values); + }); + } + + /** + * Sets all double values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedDoubleIterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeDoubleArray(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedDouble(fieldNumber, values); + }); + } + + /* Fixed32 */ + + /** + * Adds all fixed32 values into the field for the given field number. + * How these values are encoded depends on the given write function. + * @param {number} fieldNumber + * @param {!Iterable} values + * @param {function(!Writer, number, !Array): undefined} encoder + * @private + */ + addRepeatedFixed32Iterable_(fieldNumber, values, encoder) { + const array = [...this.getRepeatedFixed32Array_(fieldNumber), ...values]; + checkCriticalTypeUnsignedInt32Array(array); + // Needs to set it back because the default empty array was not cached. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Adds a single fixed32 value into the field for the given field number. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} value + */ + addPackedFixed32Element(fieldNumber, value) { + this.addRepeatedFixed32Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writePackedFixed32(fieldNumber, values); + }); + } + + /** + * Adds all fixed32 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedFixed32Iterable(fieldNumber, values) { + this.addRepeatedFixed32Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writePackedFixed32(fieldNumber, values); + }); + } + + /** + * Adds a single fixed32 value into the field for the given field number. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} value + */ + addUnpackedFixed32Element(fieldNumber, value) { + this.addRepeatedFixed32Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writeRepeatedFixed32(fieldNumber, values); + }); + } + + /** + * Adds all fixed32 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedFixed32Iterable(fieldNumber, values) { + this.addRepeatedFixed32Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writeRepeatedFixed32(fieldNumber, values); + }); + } + + /** + * Sets a single fixed32 value into the field for the given field number at + * the given index. How these values are encoded depends on the given write + * function. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @param {function(!Writer, number, !Array): undefined} encoder + * @throws {!Error} if index is out of range when check mode is critical + * @private + */ + setRepeatedFixed32Element_(fieldNumber, index, value, encoder) { + checkCriticalTypeUnsignedInt32(value); + const array = this.getRepeatedFixed32Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + array[index] = value; + // Needs to set it back to set encoder. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Sets a single fixed32 value into the field for the given field number at + * the given index. All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedFixed32Element(fieldNumber, index, value) { + this.setRepeatedFixed32Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writePackedFixed32(fieldNumber, values); + }); + } + + /** + * Sets all fixed32 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedFixed32Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeUnsignedInt32Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writePackedFixed32(fieldNumber, values); + }); + } + + /** + * Sets a single fixed32 value into the field for the given field number at + * the given index. All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedFixed32Element(fieldNumber, index, value) { + this.setRepeatedFixed32Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writeRepeatedFixed32(fieldNumber, values); + }); + } + + /** + * Sets all fixed32 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedFixed32Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeUnsignedInt32Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedFixed32(fieldNumber, values); + }); + } + + /* Fixed64 */ + + /** + * Adds a single fixed64 value into the field for the given field number. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Int64} value + */ + addPackedFixed64Element(fieldNumber, value) { + this.addPackedSfixed64Element(fieldNumber, value); + } + + /** + * Adds all fixed64 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedFixed64Iterable(fieldNumber, values) { + this.addPackedSfixed64Iterable(fieldNumber, values); + } + + /** + * Adds a single fixed64 value into the field for the given field number. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Int64} value + */ + addUnpackedFixed64Element(fieldNumber, value) { + this.addUnpackedSfixed64Element(fieldNumber, value); + } + + /** + * Adds all fixed64 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedFixed64Iterable(fieldNumber, values) { + this.addUnpackedSfixed64Iterable(fieldNumber, values); + } + + /** + * Sets a single fixed64 value into the field for the given field number at + * the given index. All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedFixed64Element(fieldNumber, index, value) { + this.setPackedSfixed64Element(fieldNumber, index, value); + } + + /** + * Sets all fixed64 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedFixed64Iterable(fieldNumber, values) { + this.setPackedSfixed64Iterable(fieldNumber, values); + } + + /** + * Sets a single fixed64 value into the field for the given field number at + * the given index. All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedFixed64Element(fieldNumber, index, value) { + this.setUnpackedSfixed64Element(fieldNumber, index, value); + } + + /** + * Sets all fixed64 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedFixed64Iterable(fieldNumber, values) { + this.setUnpackedSfixed64Iterable(fieldNumber, values); + } + + /* Float */ + + /** + * Adds all float values into the field for the given field number. + * How these values are encoded depends on the given write function. + * @param {number} fieldNumber + * @param {!Iterable} values + * @param {function(!Writer, number, !Array): undefined} encoder + * @private + */ + addRepeatedFloatIterable_(fieldNumber, values, encoder) { + checkCriticalTypeFloatIterable(values); + // Eagerly round to 32-bit precision so that reading back after set will + // yield the same value a reader will receive after serialization. + const floatValues = Array.from(values, fround); + const array = [...this.getRepeatedFloatArray_(fieldNumber), ...floatValues]; + checkCriticalTypeFloatIterable(array); + // Needs to set it back because the default empty array was not cached. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Adds a single float value into the field for the given field number. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} value + */ + addPackedFloatElement(fieldNumber, value) { + this.addRepeatedFloatIterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writePackedFloat(fieldNumber, values); + }); + } + + /** + * Adds all float values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedFloatIterable(fieldNumber, values) { + this.addRepeatedFloatIterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writePackedFloat(fieldNumber, values); + }); + } + + /** + * Adds a single float value into the field for the given field number. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} value + */ + addUnpackedFloatElement(fieldNumber, value) { + this.addRepeatedFloatIterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writeRepeatedFloat(fieldNumber, values); + }); + } + + /** + * Adds all float values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedFloatIterable(fieldNumber, values) { + this.addRepeatedFloatIterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writeRepeatedFloat(fieldNumber, values); + }); + } + + /** + * Sets a single float value into the field for the given field number at the + * given index. + * How these values are encoded depends on the given write function. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @param {function(!Writer, number, !Array): undefined} encoder + * @throws {!Error} if index is out of range when check mode is critical + * @private + */ + setRepeatedFloatElement_(fieldNumber, index, value, encoder) { + checkCriticalTypeFloat(value); + // Eagerly round to 32-bit precision so that reading back after set will + // yield the same value a reader will receive after serialization. + const floatValue = Math.fround(value); + const array = this.getRepeatedFloatArray_(fieldNumber); + checkCriticalElementIndex(index, array.length); + array[index] = floatValue; + // Needs to set it back to set encoder. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Sets a single float value into the field for the given field number at the + * given index. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedFloatElement(fieldNumber, index, value) { + this.setRepeatedFloatElement_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writePackedFloat(fieldNumber, values); + }); + } + + /** + * Sets all float values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedFloatIterable(fieldNumber, values) { + checkCriticalTypeFloatIterable(values); + // Eagerly round to 32-bit precision so that reading back after set will + // yield the same value a reader will receive after serialization. + const array = Array.from(values, fround); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writePackedFloat(fieldNumber, values); + }); + } + + /** + * Sets a single float value into the field for the given field number at the + * given index. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedFloatElement(fieldNumber, index, value) { + this.setRepeatedFloatElement_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writeRepeatedFloat(fieldNumber, values); + }); + } + + /** + * Sets all float values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedFloatIterable(fieldNumber, values) { + checkCriticalTypeFloatIterable(values); + // Eagerly round to 32-bit precision so that reading back after set will + // yield the same value a reader will receive after serialization. + const array = Array.from(values, fround); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedFloat(fieldNumber, values); + }); + } + + /* Int32 */ + + /** + * Adds all int32 values into the field for the given field number. + * How these values are encoded depends on the given write function. + * @param {number} fieldNumber + * @param {!Iterable} values + * @param {function(!Writer, number, !Array): undefined} encoder + * @private + */ + addRepeatedInt32Iterable_(fieldNumber, values, encoder) { + const array = [...this.getRepeatedInt32Array_(fieldNumber), ...values]; + checkCriticalTypeSignedInt32Array(array); + // Needs to set it back because the default empty array was not cached. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Adds a single int32 value into the field for the given field number. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} value + */ + addPackedInt32Element(fieldNumber, value) { + this.addRepeatedInt32Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writePackedInt32(fieldNumber, values); + }); + } + + /** + * Adds all int32 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedInt32Iterable(fieldNumber, values) { + this.addRepeatedInt32Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writePackedInt32(fieldNumber, values); + }); + } + + /** + * Adds a single int32 value into the field for the given field number. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} value + */ + addUnpackedInt32Element(fieldNumber, value) { + this.addRepeatedInt32Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writeRepeatedInt32(fieldNumber, values); + }); + } + + /** + * Adds all int32 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedInt32Iterable(fieldNumber, values) { + this.addRepeatedInt32Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writeRepeatedInt32(fieldNumber, values); + }); + } + + /** + * Sets a single int32 value into the field for the given field number at + * the given index. How these values are encoded depends on the given write + * function. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @param {function(!Writer, number, !Array): undefined} encoder + * @throws {!Error} if index is out of range when check mode is critical + * @private + */ + setRepeatedInt32Element_(fieldNumber, index, value, encoder) { + checkCriticalTypeSignedInt32(value); + const array = this.getRepeatedInt32Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + array[index] = value; + // Needs to set it back to set encoder. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Sets a single int32 value into the field for the given field number at + * the given index. All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedInt32Element(fieldNumber, index, value) { + this.setRepeatedInt32Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writePackedInt32(fieldNumber, values); + }); + } + + /** + * Sets all int32 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedInt32Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeSignedInt32Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writePackedInt32(fieldNumber, values); + }); + } + + /** + * Sets a single int32 value into the field for the given field number at + * the given index. All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedInt32Element(fieldNumber, index, value) { + this.setRepeatedInt32Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writeRepeatedInt32(fieldNumber, values); + }); + } + + /** + * Sets all int32 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedInt32Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeSignedInt32Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedInt32(fieldNumber, values); + }); + } + + /* Int64 */ + + /** + * Adds all int64 values into the field for the given field number. + * How these values are encoded depends on the given write function. + * @param {number} fieldNumber + * @param {!Iterable} values + * @param {function(!Writer, number, !Array): undefined} encoder + * @private + */ + addRepeatedInt64Iterable_(fieldNumber, values, encoder) { + const array = [...this.getRepeatedInt64Array_(fieldNumber), ...values]; + checkCriticalTypeSignedInt64Array(array); + // Needs to set it back because the default empty array was not cached. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Adds a single int64 value into the field for the given field number. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Int64} value + */ + addPackedInt64Element(fieldNumber, value) { + this.addRepeatedInt64Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writePackedInt64(fieldNumber, values); + }); + } + + /** + * Adds all int64 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedInt64Iterable(fieldNumber, values) { + this.addRepeatedInt64Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writePackedInt64(fieldNumber, values); + }); + } + + /** + * Adds a single int64 value into the field for the given field number. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Int64} value + */ + addUnpackedInt64Element(fieldNumber, value) { + this.addRepeatedInt64Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writeRepeatedInt64(fieldNumber, values); + }); + } + + /** + * Adds all int64 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedInt64Iterable(fieldNumber, values) { + this.addRepeatedInt64Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writeRepeatedInt64(fieldNumber, values); + }); + } + + /** + * Sets a single int64 value into the field for the given field number at + * the given index. How these values are encoded depends on the given write + * function. + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @param {function(!Writer, number, !Array): undefined} encoder + * @throws {!Error} if index is out of range when check mode is critical + * @private + */ + setRepeatedInt64Element_(fieldNumber, index, value, encoder) { + checkCriticalTypeSignedInt64(value); + const array = this.getRepeatedInt64Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + array[index] = value; + // Needs to set it back to set encoder. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Sets a single int64 value into the field for the given field number at + * the given index. All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedInt64Element(fieldNumber, index, value) { + this.setRepeatedInt64Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writePackedInt64(fieldNumber, values); + }); + } + + /** + * Sets all int64 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedInt64Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeSignedInt64Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writePackedInt64(fieldNumber, values); + }); + } + + /** + * Sets a single int64 value into the field for the given field number at + * the given index. All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedInt64Element(fieldNumber, index, value) { + this.setRepeatedInt64Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writeRepeatedInt64(fieldNumber, values); + }); + } + + /** + * Sets all int64 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedInt64Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeSignedInt64Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedInt64(fieldNumber, values); + }); + } + + /* Sfixed32 */ + + /** + * Adds all sfixed32 values into the field for the given field number. + * How these values are encoded depends on the given write function. + * @param {number} fieldNumber + * @param {!Iterable} values + * @param {function(!Writer, number, !Array): undefined} encoder + * @private + */ + addRepeatedSfixed32Iterable_(fieldNumber, values, encoder) { + const array = [...this.getRepeatedSfixed32Array_(fieldNumber), ...values]; + checkCriticalTypeSignedInt32Array(array); + // Needs to set it back because the default empty array was not cached. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Adds a single sfixed32 value into the field for the given field number. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} value + */ + addPackedSfixed32Element(fieldNumber, value) { + this.addRepeatedSfixed32Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writePackedSfixed32(fieldNumber, values); + }); + } + + /** + * Adds all sfixed32 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedSfixed32Iterable(fieldNumber, values) { + this.addRepeatedSfixed32Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writePackedSfixed32(fieldNumber, values); + }); + } + + /** + * Adds a single sfixed32 value into the field for the given field number. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} value + */ + addUnpackedSfixed32Element(fieldNumber, value) { + this.addRepeatedSfixed32Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writeRepeatedSfixed32(fieldNumber, values); + }); + } + + /** + * Adds all sfixed32 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedSfixed32Iterable(fieldNumber, values) { + this.addRepeatedSfixed32Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writeRepeatedSfixed32(fieldNumber, values); + }); + } + + /** + * Sets a single sfixed32 value into the field for the given field number at + * the given index. How these values are encoded depends on the given write + * function. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @param {function(!Writer, number, !Array): undefined} encoder + * @throws {!Error} if index is out of range when check mode is critical + * @private + */ + setRepeatedSfixed32Element_(fieldNumber, index, value, encoder) { + checkCriticalTypeSignedInt32(value); + const array = this.getRepeatedSfixed32Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + array[index] = value; + // Needs to set it back to set encoder. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Sets a single sfixed32 value into the field for the given field number at + * the given index. All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedSfixed32Element(fieldNumber, index, value) { + this.setRepeatedSfixed32Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writePackedSfixed32(fieldNumber, values); + }); + } + + /** + * Sets all sfixed32 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedSfixed32Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeSignedInt32Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writePackedSfixed32(fieldNumber, values); + }); + } + + /** + * Sets a single sfixed32 value into the field for the given field number at + * the given index. All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedSfixed32Element(fieldNumber, index, value) { + this.setRepeatedSfixed32Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writeRepeatedSfixed32(fieldNumber, values); + }); + } + + /** + * Sets all sfixed32 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedSfixed32Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeSignedInt32Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedSfixed32(fieldNumber, values); + }); + } + + /* Sfixed64 */ + + /** + * Adds all sfixed64 values into the field for the given field number. + * How these values are encoded depends on the given write function. + * @param {number} fieldNumber + * @param {!Iterable} values + * @param {function(!Writer, number, !Array): undefined} encoder + * @private + */ + addRepeatedSfixed64Iterable_(fieldNumber, values, encoder) { + const array = [...this.getRepeatedSfixed64Array_(fieldNumber), ...values]; + checkCriticalTypeSignedInt64Array(array); + // Needs to set it back because the default empty array was not cached. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Adds a single sfixed64 value into the field for the given field number. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Int64} value + */ + addPackedSfixed64Element(fieldNumber, value) { + this.addRepeatedSfixed64Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writePackedSfixed64(fieldNumber, values); + }); + } + + /** + * Adds all sfixed64 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedSfixed64Iterable(fieldNumber, values) { + this.addRepeatedSfixed64Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writePackedSfixed64(fieldNumber, values); + }); + } + + /** + * Adds a single sfixed64 value into the field for the given field number. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Int64} value + */ + addUnpackedSfixed64Element(fieldNumber, value) { + this.addRepeatedSfixed64Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writeRepeatedSfixed64(fieldNumber, values); + }); + } + + /** + * Adds all sfixed64 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedSfixed64Iterable(fieldNumber, values) { + this.addRepeatedSfixed64Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writeRepeatedSfixed64(fieldNumber, values); + }); + } + + /** + * Sets a single sfixed64 value into the field for the given field number at + * the given index. How these values are encoded depends on the given write + * function. + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @param {function(!Writer, number, !Array): undefined} encoder + * @throws {!Error} if index is out of range when check mode is critical + * @private + */ + setRepeatedSfixed64Element_(fieldNumber, index, value, encoder) { + checkCriticalTypeSignedInt64(value); + const array = this.getRepeatedSfixed64Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + array[index] = value; + // Needs to set it back to set encoder. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Sets a single sfixed64 value into the field for the given field number at + * the given index. All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedSfixed64Element(fieldNumber, index, value) { + this.setRepeatedSfixed64Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writePackedSfixed64(fieldNumber, values); + }); + } + + /** + * Sets all sfixed64 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedSfixed64Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeSignedInt64Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writePackedSfixed64(fieldNumber, values); + }); + } + + /** + * Sets a single sfixed64 value into the field for the given field number at + * the given index. All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedSfixed64Element(fieldNumber, index, value) { + this.setRepeatedSfixed64Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writeRepeatedSfixed64(fieldNumber, values); + }); + } + + /** + * Sets all sfixed64 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedSfixed64Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeSignedInt64Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedSfixed64(fieldNumber, values); + }); + } + + /* Sint32 */ + + /** + * Adds all sint32 values into the field for the given field number. + * How these values are encoded depends on the given write function. + * @param {number} fieldNumber + * @param {!Iterable} values + * @param {function(!Writer, number, !Array): undefined} encoder + * @private + */ + addRepeatedSint32Iterable_(fieldNumber, values, encoder) { + const array = [...this.getRepeatedSint32Array_(fieldNumber), ...values]; + checkCriticalTypeSignedInt32Array(array); + // Needs to set it back because the default empty array was not cached. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Adds a single sint32 value into the field for the given field number. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} value + */ + addPackedSint32Element(fieldNumber, value) { + this.addRepeatedSint32Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writePackedSint32(fieldNumber, values); + }); + } + + /** + * Adds all sint32 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedSint32Iterable(fieldNumber, values) { + this.addRepeatedSint32Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writePackedSint32(fieldNumber, values); + }); + } + + /** + * Adds a single sint32 value into the field for the given field number. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} value + */ + addUnpackedSint32Element(fieldNumber, value) { + this.addRepeatedSint32Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writeRepeatedSint32(fieldNumber, values); + }); + } + + /** + * Adds all sint32 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedSint32Iterable(fieldNumber, values) { + this.addRepeatedSint32Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writeRepeatedSint32(fieldNumber, values); + }); + } + + /** + * Sets a single sint32 value into the field for the given field number at + * the given index. How these values are encoded depends on the given write + * function. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @param {function(!Writer, number, !Array): undefined} encoder + * @throws {!Error} if index is out of range when check mode is critical + * @private + */ + setRepeatedSint32Element_(fieldNumber, index, value, encoder) { + checkCriticalTypeSignedInt32(value); + const array = this.getRepeatedSint32Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + array[index] = value; + // Needs to set it back to set encoder. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Sets a single sint32 value into the field for the given field number at + * the given index. All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedSint32Element(fieldNumber, index, value) { + this.setRepeatedSint32Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writePackedSint32(fieldNumber, values); + }); + } + + /** + * Sets all sint32 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedSint32Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeSignedInt32Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writePackedSint32(fieldNumber, values); + }); + } + + /** + * Sets a single sint32 value into the field for the given field number at + * the given index. All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedSint32Element(fieldNumber, index, value) { + this.setRepeatedSint32Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writeRepeatedSint32(fieldNumber, values); + }); + } + + /** + * Sets all sint32 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedSint32Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeSignedInt32Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedSint32(fieldNumber, values); + }); + } + + /* Sint64 */ + + /** + * Adds all sint64 values into the field for the given field number. + * How these values are encoded depends on the given write function. + * @param {number} fieldNumber + * @param {!Iterable} values + * @param {function(!Writer, number, !Array): undefined} encoder + * @private + */ + addRepeatedSint64Iterable_(fieldNumber, values, encoder) { + const array = [...this.getRepeatedSint64Array_(fieldNumber), ...values]; + checkCriticalTypeSignedInt64Array(array); + // Needs to set it back because the default empty array was not cached. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Adds a single sint64 value into the field for the given field number. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Int64} value + */ + addPackedSint64Element(fieldNumber, value) { + this.addRepeatedSint64Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writePackedSint64(fieldNumber, values); + }); + } + + /** + * Adds all sint64 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedSint64Iterable(fieldNumber, values) { + this.addRepeatedSint64Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writePackedSint64(fieldNumber, values); + }); + } + + /** + * Adds a single sint64 value into the field for the given field number. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Int64} value + */ + addUnpackedSint64Element(fieldNumber, value) { + this.addRepeatedSint64Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writeRepeatedSint64(fieldNumber, values); + }); + } + + /** + * Adds all sint64 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedSint64Iterable(fieldNumber, values) { + this.addRepeatedSint64Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writeRepeatedSint64(fieldNumber, values); + }); + } + + /** + * Sets a single sint64 value into the field for the given field number at + * the given index. How these values are encoded depends on the given write + * function. + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @param {function(!Writer, number, !Array): undefined} encoder + * @throws {!Error} if index is out of range when check mode is critical + * @private + */ + setRepeatedSint64Element_(fieldNumber, index, value, encoder) { + checkCriticalTypeSignedInt64(value); + const array = this.getRepeatedSint64Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + array[index] = value; + // Needs to set it back to set encoder. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Sets a single sint64 value into the field for the given field number at + * the given index. All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedSint64Element(fieldNumber, index, value) { + this.setRepeatedSint64Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writePackedSint64(fieldNumber, values); + }); + } + + /** + * Sets all sint64 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedSint64Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeSignedInt64Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writePackedSint64(fieldNumber, values); + }); + } + + /** + * Sets a single sint64 value into the field for the given field number at + * the given index. All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedSint64Element(fieldNumber, index, value) { + this.setRepeatedSint64Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writeRepeatedSint64(fieldNumber, values); + }); + } + + /** + * Sets all sint64 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedSint64Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeSignedInt64Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedSint64(fieldNumber, values); + }); + } + + /* Uint32 */ + + /** + * Adds all uint32 values into the field for the given field number. + * How these values are encoded depends on the given write function. + * @param {number} fieldNumber + * @param {!Iterable} values + * @param {function(!Writer, number, !Array): undefined} encoder + * @private + */ + addRepeatedUint32Iterable_(fieldNumber, values, encoder) { + const array = [...this.getRepeatedUint32Array_(fieldNumber), ...values]; + checkCriticalTypeUnsignedInt32Array(array); + // Needs to set it back because the default empty array was not cached. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Adds a single uint32 value into the field for the given field number. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} value + */ + addPackedUint32Element(fieldNumber, value) { + this.addRepeatedUint32Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writePackedUint32(fieldNumber, values); + }); + } + + /** + * Adds all uint32 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedUint32Iterable(fieldNumber, values) { + this.addRepeatedUint32Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writePackedUint32(fieldNumber, values); + }); + } + + /** + * Adds a single uint32 value into the field for the given field number. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} value + */ + addUnpackedUint32Element(fieldNumber, value) { + this.addRepeatedUint32Iterable_( + fieldNumber, [value], (writer, fieldNumber, values) => { + writer.writeRepeatedUint32(fieldNumber, values); + }); + } + + /** + * Adds all uint32 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedUint32Iterable(fieldNumber, values) { + this.addRepeatedUint32Iterable_( + fieldNumber, values, (writer, fieldNumber, values) => { + writer.writeRepeatedUint32(fieldNumber, values); + }); + } + + /** + * Sets a single uint32 value into the field for the given field number at + * the given index. How these values are encoded depends on the given write + * function. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @param {function(!Writer, number, !Array): undefined} encoder + * @throws {!Error} if index is out of range when check mode is critical + * @private + */ + setRepeatedUint32Element_(fieldNumber, index, value, encoder) { + checkCriticalTypeUnsignedInt32(value); + const array = this.getRepeatedUint32Array_(fieldNumber); + checkCriticalElementIndex(index, array.length); + array[index] = value; + // Needs to set it back to set encoder. + this.setField_(fieldNumber, array, encoder); + } + + /** + * Sets a single uint32 value into the field for the given field number at + * the given index. All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedUint32Element(fieldNumber, index, value) { + this.setRepeatedUint32Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writePackedUint32(fieldNumber, values); + }); + } + + /** + * Sets all uint32 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedUint32Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeUnsignedInt32Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writePackedUint32(fieldNumber, values); + }); + } + + /** + * Sets a single uint32 value into the field for the given field number at + * the given index. All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedUint32Element(fieldNumber, index, value) { + this.setRepeatedUint32Element_( + fieldNumber, index, value, (writer, fieldNumber, values) => { + writer.writeRepeatedUint32(fieldNumber, values); + }); + } + + /** + * Sets all uint32 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedUint32Iterable(fieldNumber, values) { + const array = Array.from(values); + checkCriticalTypeUnsignedInt32Array(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedUint32(fieldNumber, values); + }); + } + + /* Uint64 */ + + /** + * Adds a single uint64 value into the field for the given field number. + * All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Int64} value + */ + addPackedUint64Element(fieldNumber, value) { + this.addPackedInt64Element(fieldNumber, value); + } + + /** + * Adds all uint64 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedUint64Iterable(fieldNumber, values) { + this.addPackedInt64Iterable(fieldNumber, values); + } + + /** + * Adds a single uint64 value into the field for the given field number. + * All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Int64} value + */ + addUnpackedUint64Element(fieldNumber, value) { + this.addUnpackedInt64Element(fieldNumber, value); + } + + /** + * Adds all uint64 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedUint64Iterable(fieldNumber, values) { + this.addUnpackedInt64Iterable(fieldNumber, values); + } + + /** + * Sets a single uint64 value into the field for the given field number at + * the given index. All values will be encoded as packed values. + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedUint64Element(fieldNumber, index, value) { + this.setPackedInt64Element(fieldNumber, index, value); + } + + /** + * Sets all uint64 values into the field for the given field number. + * All these values will be encoded as packed values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedUint64Iterable(fieldNumber, values) { + this.setPackedInt64Iterable(fieldNumber, values); + } + + /** + * Sets a single uint64 value into the field for the given field number at + * the given index. All values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedUint64Element(fieldNumber, index, value) { + this.setUnpackedInt64Element(fieldNumber, index, value); + } + + /** + * Sets all uint64 values into the field for the given field number. + * All these values will be encoded as unpacked values. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedUint64Iterable(fieldNumber, values) { + this.setUnpackedInt64Iterable(fieldNumber, values); + } + + /* Bytes */ + + /** + * Sets all bytes values into the field for the given field number. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setRepeatedBytesIterable(fieldNumber, values) { + const /** !Array */ array = Array.from(values); + checkCriticalTypeByteStringArray(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedBytes(fieldNumber, values); + }); + } + + /** + * Adds all bytes values into the field for the given field number. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addRepeatedBytesIterable(fieldNumber, values) { + const array = [...this.getRepeatedBytesArray_(fieldNumber), ...values]; + checkCriticalTypeByteStringArray(array); + // Needs to set it back because the default empty array was not cached. + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedBytes(fieldNumber, values); + }); + } + + /** + * Sets a single bytes value into the field for the given field number at + * the given index. + * @param {number} fieldNumber + * @param {number} index + * @param {!ByteString} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setRepeatedBytesElement(fieldNumber, index, value) { + checkCriticalTypeByteString(value); + const array = this.getRepeatedBytesArray_(fieldNumber); + checkCriticalElementIndex(index, array.length); + array[index] = value; + // Needs to set it back to set encoder. + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedBytes(fieldNumber, values); + }); + } + + /** + * Adds a single bytes value into the field for the given field number. + * @param {number} fieldNumber + * @param {!ByteString} value + */ + addRepeatedBytesElement(fieldNumber, value) { + this.addRepeatedBytesIterable(fieldNumber, [value]); + } + + /* String */ + + /** + * Sets all string values into the field for the given field number. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setRepeatedStringIterable(fieldNumber, values) { + const /** !Array */ array = Array.from(values); + checkCriticalTypeStringArray(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedString(fieldNumber, values); + }); + } + + /** + * Adds all string values into the field for the given field number. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addRepeatedStringIterable(fieldNumber, values) { + const array = [...this.getRepeatedStringArray_(fieldNumber), ...values]; + checkCriticalTypeStringArray(array); + // Needs to set it back because the default empty array was not cached. + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedString(fieldNumber, values); + }); + } + + /** + * Sets a single string value into the field for the given field number at + * the given index. + * @param {number} fieldNumber + * @param {number} index + * @param {string} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setRepeatedStringElement(fieldNumber, index, value) { + checkCriticalTypeString(value); + const array = this.getRepeatedStringArray_(fieldNumber); + checkCriticalElementIndex(index, array.length); + array[index] = value; + // Needs to set it back to set encoder. + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writer.writeRepeatedString(fieldNumber, values); + }); + } + + /** + * Adds a single string value into the field for the given field number. + * @param {number} fieldNumber + * @param {string} value + */ + addRepeatedStringElement(fieldNumber, value) { + this.addRepeatedStringIterable(fieldNumber, [value]); + } + + /* Message */ + + /** + * Sets all message values into the field for the given field number. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setRepeatedMessageIterable(fieldNumber, values) { + const /** !Array */ array = Array.from(values); + checkCriticalTypeMessageArray(array); + this.setField_(fieldNumber, array, (writer, fieldNumber, values) => { + writeRepeatedMessage(writer, fieldNumber, values); + }); + } + + /** + * Adds all message values into the field for the given field number. + * @param {number} fieldNumber + * @param {!Iterable} values + * @param {function(!Kernel):!InternalMessage} instanceCreator + * @param {number=} pivot + */ + addRepeatedMessageIterable( + fieldNumber, values, instanceCreator, pivot = undefined) { + const array = [ + ...this.getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot), + ...values, + ]; + checkCriticalTypeMessageArray(array); + // Needs to set it back with the new array. + this.setField_( + fieldNumber, array, + (writer, fieldNumber, values) => + writeRepeatedMessage(writer, fieldNumber, values)); + } + + /** + * Sets a single message value into the field for the given field number at + * the given index. + * @param {number} fieldNumber + * @param {!InternalMessage} value + * @param {function(!Kernel):!InternalMessage} instanceCreator + * @param {number} index + * @param {number=} pivot + * @throws {!Error} if index is out of range when check mode is critical + */ + setRepeatedMessageElement( + fieldNumber, value, instanceCreator, index, pivot = undefined) { + checkInstanceCreator(instanceCreator); + checkCriticalType( + value !== null, 'Given value is not a message instance: null'); + const array = + this.getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot); + checkCriticalElementIndex(index, array.length); + array[index] = value; + } + + /** + * Adds a single message value into the field for the given field number. + * @param {number} fieldNumber + * @param {!InternalMessage} value + * @param {function(!Kernel):!InternalMessage} instanceCreator + * @param {number=} pivot + */ + addRepeatedMessageElement( + fieldNumber, value, instanceCreator, pivot = undefined) { + this.addRepeatedMessageIterable( + fieldNumber, [value], instanceCreator, pivot); + } + + // Groups + /** + * Sets all message values into the field for the given field number. + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setRepeatedGroupIterable(fieldNumber, values) { + const /** !Array */ array = Array.from(values); + checkCriticalTypeMessageArray(array); + this.setField_(fieldNumber, array, writeRepeatedGroup); + } + + /** + * Adds all message values into the field for the given field number. + * @param {number} fieldNumber + * @param {!Iterable} values + * @param {function(!Kernel):!InternalMessage} instanceCreator + * @param {number=} pivot + */ + addRepeatedGroupIterable( + fieldNumber, values, instanceCreator, pivot = undefined) { + const array = [ + ...this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot), + ...values, + ]; + checkCriticalTypeMessageArray(array); + // Needs to set it back with the new array. + this.setField_(fieldNumber, array, writeRepeatedGroup); + } + + /** + * Sets a single message value into the field for the given field number at + * the given index. + * @param {number} fieldNumber + * @param {!InternalMessage} value + * @param {function(!Kernel):!InternalMessage} instanceCreator + * @param {number} index + * @param {number=} pivot + * @throws {!Error} if index is out of range when check mode is critical + */ + setRepeatedGroupElement( + fieldNumber, value, instanceCreator, index, pivot = undefined) { + checkInstanceCreator(instanceCreator); + checkCriticalType( + value !== null, 'Given value is not a message instance: null'); + const array = + this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot); + checkCriticalElementIndex(index, array.length); + array[index] = value; + } + + /** + * Adds a single message value into the field for the given field number. + * @param {number} fieldNumber + * @param {!InternalMessage} value + * @param {function(!Kernel):!InternalMessage} instanceCreator + * @param {number=} pivot + */ + addRepeatedGroupElement( + fieldNumber, value, instanceCreator, pivot = undefined) { + this.addRepeatedGroupIterable(fieldNumber, [value], instanceCreator, pivot); + } +} + +exports = Kernel; diff --git a/js/experimental/runtime/kernel/kernel_compatibility_test.js b/js/experimental/runtime/kernel/kernel_compatibility_test.js new file mode 100644 index 0000000000000..155008f7b1e5f --- /dev/null +++ b/js/experimental/runtime/kernel/kernel_compatibility_test.js @@ -0,0 +1,266 @@ +/** + * @fileoverview Tests to make sure Kernel can read data in a backward + * compatible way even when protobuf schema changes according to the rules + * defined in + * https://developers.google.com/protocol-buffers/docs/proto#updating and + * https://developers.google.com/protocol-buffers/docs/proto3#updating. + * + * third_party/protobuf/conformance/binary_json_conformance_suite.cc already + * covers many compatibility tests, this file covers only the tests not covered + * by binary_json_conformance_suite. Ultimately all of the tests in this file + * should be moved to binary_json_conformance_suite. + */ +goog.module('protobuf.runtime.KernelCompatibilityTest'); + +goog.setTestOnly(); + +const ByteString = goog.require('protobuf.ByteString'); +const Int64 = goog.require('protobuf.Int64'); +const Kernel = goog.require('protobuf.runtime.Kernel'); +const TestMessage = goog.require('protobuf.testing.binary.TestMessage'); +const {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks'); + +/** + * @param {...number} bytes + * @return {!ArrayBuffer} + */ +function createArrayBuffer(...bytes) { + return new Uint8Array(bytes).buffer; +} + +/** + * Returns the Unicode character codes of a string. + * @param {string} str + * @return {!Array} + */ +function getCharacterCodes(str) { + return Array.from(str, (c) => c.charCodeAt(0)); +} + +describe('optional -> repeated compatibility', () => { + it('is maintained for scalars', () => { + const oldAccessor = Kernel.createEmpty(); + oldAccessor.setInt32(1, 1); + const serializedData = oldAccessor.serialize(); + expect(serializedData).toEqual(createArrayBuffer(0x8, 0x1)); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + expect(newAccessor.getRepeatedInt32Size(1)).toEqual(1); + expect(newAccessor.getRepeatedInt32Element(1, 0)).toEqual(1); + }); + + it('is maintained for messages', () => { + const message = new TestMessage(Kernel.createEmpty()); + message.setInt32(1, 1); + + const oldAccessor = Kernel.createEmpty(); + oldAccessor.setMessage(1, message); + const serializedData = oldAccessor.serialize(); + expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0x8, 0x1)); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + expect(newAccessor.getRepeatedMessageSize(1, TestMessage.instanceCreator)) + .toEqual(1); + expect( + newAccessor.getRepeatedMessageElement(1, TestMessage.instanceCreator, 0) + .serialize()) + .toEqual(message.serialize()); + }); + + it('is maintained for bytes', () => { + const message = new TestMessage(Kernel.createEmpty()); + message.setInt32(1, 1); + + const oldAccessor = Kernel.createEmpty(); + oldAccessor.setBytes( + 1, ByteString.fromArrayBuffer(createArrayBuffer(0xA, 0xB))); + const serializedData = oldAccessor.serialize(); + expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0xA, 0xB)); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + expect(newAccessor.getRepeatedBytesSize(1)).toEqual(1); + expect(newAccessor.getRepeatedBoolElement(1, 0)) + .toEqual(ByteString.fromArrayBuffer(createArrayBuffer(0xA, 0xB))); + }); + + it('is maintained for strings', () => { + const oldAccessor = Kernel.createEmpty(); + oldAccessor.setString(1, 'hello'); + const serializedData = oldAccessor.serialize(); + expect(serializedData) + .toEqual(createArrayBuffer(0xA, 0x5, 0x68, 0x65, 0x6C, 0x6C, 0x6F)); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + expect(newAccessor.getRepeatedStringSize(1)).toEqual(1); + expect(newAccessor.getRepeatedStringElement(1, 0)).toEqual('hello'); + }); +}); + +describe('Kernel repeated -> optional compatibility', () => { + it('is maintained for unpacked scalars', () => { + const oldAccessor = Kernel.createEmpty(); + oldAccessor.addUnpackedInt32Element(1, 0); + oldAccessor.addUnpackedInt32Element(1, 1); + const serializedData = oldAccessor.serialize(); + expect(serializedData).toEqual(createArrayBuffer(0x8, 0x0, 0x8, 0x1)); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + expect(newAccessor.getInt32WithDefault(1)).toEqual(1); + expect(newAccessor.serialize()).toEqual(serializedData); + }); + + // repeated -> optional transformation is not supported for packed fields yet: + // go/proto-schema-repeated + it('is not maintained for packed scalars', () => { + const oldAccessor = Kernel.createEmpty(); + oldAccessor.addPackedInt32Element(1, 0); + oldAccessor.addPackedInt32Element(1, 1); + const serializedData = oldAccessor.serialize(); + expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0x0, 0x1)); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + if (CHECK_CRITICAL_STATE) { + expect(() => newAccessor.getInt32WithDefault(1)).toThrow(); + } + }); + + it('is maintained for messages', () => { + const message1 = new TestMessage(Kernel.createEmpty()); + message1.setInt32(1, 1); + const message2 = new TestMessage(Kernel.createEmpty()); + message2.setInt32(1, 2); + message2.setInt32(2, 3); + + const oldAccessor = Kernel.createEmpty(); + oldAccessor.addRepeatedMessageElement( + 1, message1, TestMessage.instanceCreator); + oldAccessor.addRepeatedMessageElement( + 1, message2, TestMessage.instanceCreator); + const serializedData = oldAccessor.serialize(); + expect(serializedData) + .toEqual(createArrayBuffer( + 0xA, 0x2, 0x8, 0x1, 0xA, 0x4, 0x8, 0x2, 0x10, 0x3)); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + // Values from message1 and message2 have been merged + const newMessage = newAccessor.getMessage(1, TestMessage.instanceCreator); + expect(newMessage.getRepeatedInt32Size(1)).toEqual(2); + expect(newMessage.getRepeatedInt32Element(1, 0)).toEqual(1); + expect(newMessage.getRepeatedInt32Element(1, 1)).toEqual(2); + expect(newMessage.getInt32WithDefault(2)).toEqual(3); + expect(newMessage.serialize()) + .toEqual(createArrayBuffer(0x8, 0x1, 0x8, 0x2, 0x10, 0x3)); + }); + + it('is maintained for bytes', () => { + const oldAccessor = Kernel.createEmpty(); + oldAccessor.addRepeatedBytesElement( + 1, ByteString.fromArrayBuffer(createArrayBuffer(0xA, 0xB))); + oldAccessor.addRepeatedBytesElement( + 1, ByteString.fromArrayBuffer(createArrayBuffer(0xC, 0xD))); + const serializedData = oldAccessor.serialize(); + expect(serializedData) + .toEqual(createArrayBuffer(0xA, 0x2, 0xA, 0xB, 0xA, 0x2, 0xC, 0xD)); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + expect(newAccessor.getBytesWithDefault(1)) + .toEqual(ByteString.fromArrayBuffer(createArrayBuffer(0xC, 0xD))); + expect(newAccessor.serialize()).toEqual(serializedData); + }); + + it('is maintained for strings', () => { + const oldAccessor = Kernel.createEmpty(); + oldAccessor.addRepeatedStringElement(1, 'hello'); + oldAccessor.addRepeatedStringElement(1, 'world'); + const serializedData = oldAccessor.serialize(); + expect(serializedData) + .toEqual(createArrayBuffer( + 0xA, 0x5, ...getCharacterCodes('hello'), 0xA, 0x5, + ...getCharacterCodes('world'))); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + expect(newAccessor.getStringWithDefault(1)).toEqual('world'); + expect(newAccessor.serialize()).toEqual(serializedData); + }); +}); + +describe('Type change', () => { + it('is supported for fixed32 -> sfixed32', () => { + const oldAccessor = Kernel.createEmpty(); + oldAccessor.setFixed32(1, 4294967295); + const serializedData = oldAccessor.serialize(); + expect(serializedData) + .toEqual(createArrayBuffer(0xD, 0xFF, 0xFF, 0xFF, 0xFF)); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + expect(newAccessor.getSfixed32WithDefault(1)).toEqual(-1); + expect(newAccessor.serialize()).toEqual(serializedData); + }); + + it('is supported for sfixed32 -> fixed32', () => { + const oldAccessor = Kernel.createEmpty(); + oldAccessor.setSfixed32(1, -1); + const serializedData = oldAccessor.serialize(); + expect(serializedData) + .toEqual(createArrayBuffer(0xD, 0xFF, 0xFF, 0xFF, 0xFF)); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + expect(newAccessor.getFixed32WithDefault(1)).toEqual(4294967295); + expect(newAccessor.serialize()).toEqual(serializedData); + }); + + it('is supported for fixed64 -> sfixed64', () => { + const oldAccessor = Kernel.createEmpty(); + oldAccessor.setFixed64(1, Int64.fromHexString('0xFFFFFFFFFFFFFFFF')); + const serializedData = oldAccessor.serialize(); + expect(serializedData) + .toEqual(createArrayBuffer( + 0x9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + expect(newAccessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(-1)); + expect(newAccessor.serialize()).toEqual(serializedData); + }); + + it('is supported for sfixed64 -> fixed64', () => { + const oldAccessor = Kernel.createEmpty(); + oldAccessor.setSfixed64(1, Int64.fromInt(-1)); + const serializedData = oldAccessor.serialize(); + expect(serializedData) + .toEqual(createArrayBuffer( + 0x9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + expect(newAccessor.getFixed64WithDefault(1)) + .toEqual(Int64.fromHexString('0xFFFFFFFFFFFFFFFF')); + expect(newAccessor.serialize()).toEqual(serializedData); + }); + + it('is supported for bytes -> message', () => { + const oldAccessor = Kernel.createEmpty(); + oldAccessor.setBytes( + 1, ByteString.fromArrayBuffer(createArrayBuffer(0x8, 0x1))); + const serializedData = oldAccessor.serialize(); + expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0x8, 0x1)); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + const message = newAccessor.getMessage(1, TestMessage.instanceCreator); + expect(message.getInt32WithDefault(1)).toEqual(1); + expect(message.serialize()).toEqual(createArrayBuffer(0x8, 0x1)); + expect(newAccessor.serialize()).toEqual(serializedData); + }); + + it('is supported for message -> bytes', () => { + const oldAccessor = Kernel.createEmpty(); + const message = new TestMessage(Kernel.createEmpty()); + message.setInt32(1, 1); + oldAccessor.setMessage(1, message); + const serializedData = oldAccessor.serialize(); + expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0x8, 0x1)); + + const newAccessor = Kernel.fromArrayBuffer(serializedData); + expect(newAccessor.getBytesWithDefault(1)) + .toEqual(ByteString.fromArrayBuffer(createArrayBuffer(0x8, 0x1))); + expect(newAccessor.serialize()).toEqual(serializedData); + }); +}); diff --git a/js/experimental/runtime/kernel/kernel_repeated_test.js b/js/experimental/runtime/kernel/kernel_repeated_test.js new file mode 100644 index 0000000000000..6a798b6c09f0b --- /dev/null +++ b/js/experimental/runtime/kernel/kernel_repeated_test.js @@ -0,0 +1,7807 @@ +/** + * @fileoverview Tests for repeated methods in kernel.js. + */ +goog.module('protobuf.runtime.KernelTest'); + +goog.setTestOnly(); + +const ByteString = goog.require('protobuf.ByteString'); +const Int64 = goog.require('protobuf.Int64'); +const InternalMessage = goog.require('protobuf.binary.InternalMessage'); +const Kernel = goog.require('protobuf.runtime.Kernel'); +const TestMessage = goog.require('protobuf.testing.binary.TestMessage'); +// Note to the reader: +// Since the lazy accessor behavior changes with the checking level some of the +// tests in this file have to know which checking level is enable to make +// correct assertions. +const {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks'); + +/** + * @param {...number} bytes + * @return {!ArrayBuffer} + */ +function createArrayBuffer(...bytes) { + return new Uint8Array(bytes).buffer; +} + +/** + * Expects the Iterable instance yield the same values as the expected array. + * @param {!Iterable} iterable + * @param {!Array} expected + * @template T + * TODO: Implement this as a custom matcher. + */ +function expectEqualToArray(iterable, expected) { + const array = Array.from(iterable); + expect(array).toEqual(expected); +} + +/** + * Expects the Iterable instance yield qualified values. + * @param {!Iterable} iterable + * @param {(function(T): boolean)=} verify + * @template T + */ +function expectQualifiedIterable(iterable, verify) { + if (verify) { + for (const value of iterable) { + expect(verify(value)).toBe(true); + } + } +} + +/** + * Expects the Iterable instance yield the same values as the expected array of + * messages. + * @param {!Iterable} iterable + * @param {!Array} expected + * @template T + * TODO: Implement this as a custom matcher. + */ +function expectEqualToMessageArray(iterable, expected) { + const array = Array.from(iterable); + expect(array.length).toEqual(expected.length); + for (let i = 0; i < array.length; i++) { + const value = array[i].getBoolWithDefault(1, false); + const expectedValue = expected[i].getBoolWithDefault(1, false); + expect(value).toBe(expectedValue); + } +} + +describe('Kernel for repeated boolean does', () => { + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + const list1 = accessor.getRepeatedBoolIterable(1); + const list2 = accessor.getRepeatedBoolIterable(1); + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + expect(accessor.getRepeatedBoolSize(1)).toEqual(0); + }); + + it('return unpacked values from the input', () => { + const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true, false]); + }); + + it('ensure not the same instance returned for unpacked values', () => { + const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const list1 = accessor.getRepeatedBoolIterable(1); + const list2 = accessor.getRepeatedBoolIterable(1); + expect(list1).not.toBe(list2); + }); + + it('return unpacked multibytes values from the input', () => { + const bytes = createArrayBuffer(0x08, 0x80, 0x01, 0x08, 0x80, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true, false]); + }); + + it('return for adding single unpacked value', () => { + const accessor = Kernel.createEmpty(); + accessor.addUnpackedBoolElement(1, true); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true]); + accessor.addUnpackedBoolElement(1, false); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true, false]); + }); + + it('return for adding unpacked values', () => { + const accessor = Kernel.createEmpty(); + accessor.addUnpackedBoolIterable(1, [true]); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true]); + accessor.addUnpackedBoolIterable(1, [false]); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true, false]); + }); + + it('return for setting single unpacked value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00, 0x08, 0x01)); + accessor.setUnpackedBoolElement(1, 0, true); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true, true]); + }); + + it('return for setting unpacked values', () => { + const accessor = Kernel.createEmpty(); + accessor.setUnpackedBoolIterable(1, [true]); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true]); + accessor.setUnpackedBoolIterable(1, [false]); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [false]); + }); + + it('encode for adding single unpacked value', () => { + const accessor = Kernel.createEmpty(); + const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + accessor.addUnpackedBoolElement(1, true); + accessor.addUnpackedBoolElement(1, false); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('encode for adding unpacked values', () => { + const accessor = Kernel.createEmpty(); + const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + accessor.addUnpackedBoolIterable(1, [true, false]); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('encode for setting single unpacked value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x02, 0x00, 0x01)); + const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x01); + accessor.setUnpackedBoolElement(1, 0, true); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('encode for setting unpacked values', () => { + const accessor = Kernel.createEmpty(); + const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + accessor.setUnpackedBoolIterable(1, [true, false]); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('return packed values from the input', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x01, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true, false]); + }); + + it('ensure not the same instance returned for packed values', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x01, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const list1 = accessor.getRepeatedBoolIterable(1); + const list2 = accessor.getRepeatedBoolIterable(1); + expect(list1).not.toBe(list2); + }); + + it('return packed multibytes values from the input', () => { + const bytes = createArrayBuffer(0x0A, 0x04, 0x80, 0x01, 0x80, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true, false]); + }); + + it('return for adding single packed value', () => { + const accessor = Kernel.createEmpty(); + accessor.addPackedBoolElement(1, true); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true]); + accessor.addPackedBoolElement(1, false); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true, false]); + }); + + it('return for adding packed values', () => { + const accessor = Kernel.createEmpty(); + accessor.addPackedBoolIterable(1, [true]); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true]); + accessor.addPackedBoolIterable(1, [false]); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true, false]); + }); + + it('return for setting single packed value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00, 0x08, 0x01)); + accessor.setPackedBoolElement(1, 0, true); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true, true]); + }); + + it('return for setting packed values', () => { + const accessor = Kernel.createEmpty(); + accessor.setPackedBoolIterable(1, [true]); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true]); + accessor.setPackedBoolIterable(1, [false]); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [false]); + }); + + it('encode for adding single packed value', () => { + const accessor = Kernel.createEmpty(); + const bytes = createArrayBuffer(0x0A, 0x02, 0x01, 0x00); + accessor.addPackedBoolElement(1, true); + accessor.addPackedBoolElement(1, false); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('encode for adding packed values', () => { + const accessor = Kernel.createEmpty(); + const bytes = createArrayBuffer(0x0A, 0x02, 0x01, 0x00); + accessor.addPackedBoolIterable(1, [true, false]); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('encode for setting single packed value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00, 0x08, 0x01)); + const bytes = createArrayBuffer(0x0A, 0x02, 0x01, 0x01); + accessor.setPackedBoolElement(1, 0, true); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('encode for setting packed values', () => { + const accessor = Kernel.createEmpty(); + const bytes = createArrayBuffer(0x0A, 0x02, 0x01, 0x00); + accessor.setPackedBoolIterable(1, [true, false]); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('return combined values from the input', () => { + const bytes = + createArrayBuffer(0x08, 0x01, 0x0A, 0x02, 0x01, 0x00, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expectEqualToArray( + accessor.getRepeatedBoolIterable(1), [true, true, false, false]); + }); + + it('return the repeated field element from the input', () => { + const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getRepeatedBoolElement( + /* fieldNumber= */ 1, /* index= */ 0)) + .toEqual(true); + expect(accessor.getRepeatedBoolElement( + /* fieldNumber= */ 1, /* index= */ 1)) + .toEqual(false); + }); + + it('return the size from the input', () => { + const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getRepeatedBoolSize(1)).toEqual(2); + }); + + it('fail when getting unpacked bool value with other wire types', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedBoolIterable(1); + }).toThrowError('Expected wire type: 0 but found: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [true]); + } + }); + + it('fail when adding unpacked bool values with number value', () => { + const accessor = Kernel.createEmpty(); + const fakeBoolean = /** @type {boolean} */ (/** @type {*} */ (2)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedBoolIterable(1, [fakeBoolean])) + .toThrowError('Must be a boolean, but got: 2'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedBoolIterable(1, [fakeBoolean]); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [fakeBoolean]); + } + }); + + it('fail when adding single unpacked bool value with number value', () => { + const accessor = Kernel.createEmpty(); + const fakeBoolean = /** @type {boolean} */ (/** @type {*} */ (2)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedBoolElement(1, fakeBoolean)) + .toThrowError('Must be a boolean, but got: 2'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedBoolElement(1, fakeBoolean); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [fakeBoolean]); + } + }); + + it('fail when setting unpacked bool values with number value', () => { + const accessor = Kernel.createEmpty(); + const fakeBoolean = /** @type {boolean} */ (/** @type {*} */ (2)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedBoolIterable(1, [fakeBoolean])) + .toThrowError('Must be a boolean, but got: 2'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedBoolIterable(1, [fakeBoolean]); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [fakeBoolean]); + } + }); + + it('fail when setting single unpacked bool value with number value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + const fakeBoolean = /** @type {boolean} */ (/** @type {*} */ (2)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedBoolElement(1, 0, fakeBoolean)) + .toThrowError('Must be a boolean, but got: 2'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedBoolElement(1, 0, fakeBoolean); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [fakeBoolean]); + } + }); + + it('fail when adding packed bool values with number value', () => { + const accessor = Kernel.createEmpty(); + const fakeBoolean = /** @type {boolean} */ (/** @type {*} */ (2)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedBoolIterable(1, [fakeBoolean])) + .toThrowError('Must be a boolean, but got: 2'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedBoolIterable(1, [fakeBoolean]); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [fakeBoolean]); + } + }); + + it('fail when adding single packed bool value with number value', () => { + const accessor = Kernel.createEmpty(); + const fakeBoolean = /** @type {boolean} */ (/** @type {*} */ (2)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedBoolElement(1, fakeBoolean)) + .toThrowError('Must be a boolean, but got: 2'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedBoolElement(1, fakeBoolean); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [fakeBoolean]); + } + }); + + it('fail when setting packed bool values with number value', () => { + const accessor = Kernel.createEmpty(); + const fakeBoolean = /** @type {boolean} */ (/** @type {*} */ (2)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedBoolIterable(1, [fakeBoolean])) + .toThrowError('Must be a boolean, but got: 2'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedBoolIterable(1, [fakeBoolean]); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [fakeBoolean]); + } + }); + + it('fail when setting single packed bool value with number value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + const fakeBoolean = /** @type {boolean} */ (/** @type {*} */ (2)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedBoolElement(1, 0, fakeBoolean)) + .toThrowError('Must be a boolean, but got: 2'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedBoolElement(1, 0, fakeBoolean); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [fakeBoolean]); + } + }); + + it('fail when setting single unpacked with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedBoolElement(1, 1, true)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedBoolElement(1, 1, true); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [false, true]); + } + }); + + it('fail when setting single packed with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedBoolElement(1, 1, true)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedBoolElement(1, 1, true); + expectEqualToArray(accessor.getRepeatedBoolIterable(1), [false, true]); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedBoolElement( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedBoolElement( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated double does', () => { + const value1 = 1; + const value2 = 0; + + const unpackedValue1Value2 = createArrayBuffer( + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xF0, + 0x3F, // value1 + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + ); + const unpackedValue2Value1 = createArrayBuffer( + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value1 + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xF0, + 0x3F, // value2 + ); + + const packedValue1Value2 = createArrayBuffer( + 0x0A, + 0x10, // tag + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xF0, + 0x3F, // value1 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + ); + const packedValue2Value1 = createArrayBuffer( + 0x0A, + 0x10, // tag + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value1 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xF0, + 0x3F, // value2 + ); + + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list = accessor.getRepeatedDoubleIterable(1); + + expectEqualToArray(list, []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list1 = accessor.getRepeatedDoubleIterable(1); + const list2 = accessor.getRepeatedDoubleIterable(1); + + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const size = accessor.getRepeatedDoubleSize(1); + + expect(size).toEqual(0); + }); + + it('return unpacked values from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list = accessor.getRepeatedDoubleIterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for unpacked values', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list1 = accessor.getRepeatedDoubleIterable(1); + const list2 = accessor.getRepeatedDoubleIterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedDoubleElement(1, value1); + const list1 = accessor.getRepeatedDoubleIterable(1); + accessor.addUnpackedDoubleElement(1, value2); + const list2 = accessor.getRepeatedDoubleIterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedDoubleIterable(1, [value1]); + const list1 = accessor.getRepeatedDoubleIterable(1); + accessor.addUnpackedDoubleIterable(1, [value2]); + const list2 = accessor.getRepeatedDoubleIterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + accessor.setUnpackedDoubleElement(1, 1, value1); + const list = accessor.getRepeatedDoubleIterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedDoubleIterable(1, [value1]); + const list = accessor.getRepeatedDoubleIterable(1); + + expectEqualToArray(list, [value1]); + }); + + it('encode for adding single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedDoubleElement(1, value1); + accessor.addUnpackedDoubleElement(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for adding unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedDoubleIterable(1, [value1]); + accessor.addUnpackedDoubleIterable(1, [value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for setting single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setUnpackedDoubleElement(1, 0, value2); + accessor.setUnpackedDoubleElement(1, 1, value1); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue2Value1); + }); + + it('encode for setting unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedDoubleIterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('return packed values from the input', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list = accessor.getRepeatedDoubleIterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for packed values', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list1 = accessor.getRepeatedDoubleIterable(1); + const list2 = accessor.getRepeatedDoubleIterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedDoubleElement(1, value1); + const list1 = accessor.getRepeatedDoubleIterable(1); + accessor.addPackedDoubleElement(1, value2); + const list2 = accessor.getRepeatedDoubleIterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedDoubleIterable(1, [value1]); + const list1 = accessor.getRepeatedDoubleIterable(1); + accessor.addPackedDoubleIterable(1, [value2]); + const list2 = accessor.getRepeatedDoubleIterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedDoubleElement(1, 1, value1); + const list = accessor.getRepeatedDoubleIterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedDoubleIterable(1, [value1]); + const list1 = accessor.getRepeatedDoubleIterable(1); + accessor.setPackedDoubleIterable(1, [value2]); + const list2 = accessor.getRepeatedDoubleIterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value2]); + }); + + it('encode for adding single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedDoubleElement(1, value1); + accessor.addPackedDoubleElement(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for adding packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedDoubleIterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for setting single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedDoubleElement(1, 0, value2); + accessor.setPackedDoubleElement(1, 1, value1); + + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue2Value1); + }); + + it('encode for setting packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedDoubleIterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('return combined values from the input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xF0, + 0x3F, // value1 + 0x0A, + 0x10, // tag + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xF0, + 0x3F, // value1 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + )); + + const list = accessor.getRepeatedDoubleIterable(1); + + expectEqualToArray(list, [value1, value1, value2, value2]); + }); + + it('return the repeated field element from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const result1 = accessor.getRepeatedDoubleElement( + /* fieldNumber= */ 1, /* index= */ 0); + const result2 = accessor.getRepeatedDoubleElement( + /* fieldNumber= */ 1, /* index= */ 1); + + expect(result1).toEqual(value1); + expect(result2).toEqual(value2); + }); + + it('return the size from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const size = accessor.getRepeatedDoubleSize(1); + + expect(size).toEqual(2); + }); + + it('fail when getting unpacked double value with other wire types', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedDoubleIterable(1); + }).toThrowError('Expected wire type: 1 but found: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectEqualToArray( + accessor.getRepeatedDoubleIterable(1), [2.937446524422997e-306]); + } + }); + + it('fail when adding unpacked double values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeDouble = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedDoubleIterable(1, [fakeDouble])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedDoubleIterable(1, [fakeDouble]); + expectEqualToArray(accessor.getRepeatedDoubleIterable(1), [fakeDouble]); + } + }); + + it('fail when adding single unpacked double value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeDouble = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedDoubleElement(1, fakeDouble)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedDoubleElement(1, fakeDouble); + expectEqualToArray(accessor.getRepeatedDoubleIterable(1), [fakeDouble]); + } + }); + + it('fail when setting unpacked double values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeDouble = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedDoubleIterable(1, [fakeDouble])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedDoubleIterable(1, [fakeDouble]); + expectEqualToArray(accessor.getRepeatedDoubleIterable(1), [fakeDouble]); + } + }); + + it('fail when setting single unpacked double value with null value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00)); + const fakeDouble = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedDoubleElement(1, 0, fakeDouble)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedDoubleElement(1, 0, fakeDouble); + expectEqualToArray(accessor.getRepeatedDoubleIterable(1), [fakeDouble]); + } + }); + + it('fail when adding packed double values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeDouble = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedDoubleIterable(1, [fakeDouble])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedDoubleIterable(1, [fakeDouble]); + expectEqualToArray(accessor.getRepeatedDoubleIterable(1), [fakeDouble]); + } + }); + + it('fail when adding single packed double value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeDouble = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedDoubleElement(1, fakeDouble)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedDoubleElement(1, fakeDouble); + expectEqualToArray(accessor.getRepeatedDoubleIterable(1), [fakeDouble]); + } + }); + + it('fail when setting packed double values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeDouble = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedDoubleIterable(1, [fakeDouble])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedDoubleIterable(1, [fakeDouble]); + expectEqualToArray(accessor.getRepeatedDoubleIterable(1), [fakeDouble]); + } + }); + + it('fail when setting single packed double value with null value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + const fakeDouble = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedDoubleElement(1, 0, fakeDouble)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedDoubleElement(1, 0, fakeDouble); + expectEqualToArray(accessor.getRepeatedDoubleIterable(1), [fakeDouble]); + } + }); + + it('fail when setting single unpacked with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedDoubleElement(1, 1, 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedDoubleElement(1, 1, 1); + expectEqualToArray(accessor.getRepeatedDoubleIterable(1), [0, 1]); + } + }); + + it('fail when setting single packed with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedDoubleElement(1, 1, 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedDoubleElement(1, 1, 1); + expectEqualToArray(accessor.getRepeatedDoubleIterable(1), [0, 1]); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedDoubleElement( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedDoubleElement( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated fixed32 does', () => { + const value1 = 1; + const value2 = 0; + + const unpackedValue1Value2 = createArrayBuffer( + 0x0D, 0x01, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00); + const unpackedValue2Value1 = createArrayBuffer( + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, 0x00); + + const packedValue1Value2 = createArrayBuffer( + 0x0A, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + const packedValue2Value1 = createArrayBuffer( + 0x0A, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00); + + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list = accessor.getRepeatedFixed32Iterable(1); + + expectEqualToArray(list, []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list1 = accessor.getRepeatedFixed32Iterable(1); + const list2 = accessor.getRepeatedFixed32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const size = accessor.getRepeatedFixed32Size(1); + + expect(size).toEqual(0); + }); + + it('return unpacked values from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list = accessor.getRepeatedFixed32Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for unpacked values', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list1 = accessor.getRepeatedFixed32Iterable(1); + const list2 = accessor.getRepeatedFixed32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedFixed32Element(1, value1); + const list1 = accessor.getRepeatedFixed32Iterable(1); + accessor.addUnpackedFixed32Element(1, value2); + const list2 = accessor.getRepeatedFixed32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedFixed32Iterable(1, [value1]); + const list1 = accessor.getRepeatedFixed32Iterable(1); + accessor.addUnpackedFixed32Iterable(1, [value2]); + const list2 = accessor.getRepeatedFixed32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + accessor.setUnpackedFixed32Element(1, 1, value1); + const list = accessor.getRepeatedFixed32Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedFixed32Iterable(1, [value1]); + const list = accessor.getRepeatedFixed32Iterable(1); + + expectEqualToArray(list, [value1]); + }); + + it('encode for adding single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedFixed32Element(1, value1); + accessor.addUnpackedFixed32Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for adding unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedFixed32Iterable(1, [value1]); + accessor.addUnpackedFixed32Iterable(1, [value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for setting single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setUnpackedFixed32Element(1, 0, value2); + accessor.setUnpackedFixed32Element(1, 1, value1); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue2Value1); + }); + + it('encode for setting unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedFixed32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('return packed values from the input', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list = accessor.getRepeatedFixed32Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for packed values', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list1 = accessor.getRepeatedFixed32Iterable(1); + const list2 = accessor.getRepeatedFixed32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedFixed32Element(1, value1); + const list1 = accessor.getRepeatedFixed32Iterable(1); + accessor.addPackedFixed32Element(1, value2); + const list2 = accessor.getRepeatedFixed32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedFixed32Iterable(1, [value1]); + const list1 = accessor.getRepeatedFixed32Iterable(1); + accessor.addPackedFixed32Iterable(1, [value2]); + const list2 = accessor.getRepeatedFixed32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedFixed32Element(1, 1, value1); + const list = accessor.getRepeatedFixed32Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedFixed32Iterable(1, [value1]); + const list1 = accessor.getRepeatedFixed32Iterable(1); + accessor.setPackedFixed32Iterable(1, [value2]); + const list2 = accessor.getRepeatedFixed32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value2]); + }); + + it('encode for adding single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedFixed32Element(1, value1); + accessor.addPackedFixed32Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for adding packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedFixed32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for setting single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedFixed32Element(1, 0, value2); + accessor.setPackedFixed32Element(1, 1, value1); + + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue2Value1); + }); + + it('encode for setting packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedFixed32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('return combined values from the input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x0D, + 0x01, + 0x00, + 0x00, + 0x00, // value1 + 0x0A, + 0x08, // tag + 0x01, + 0x00, + 0x00, + 0x00, // value1 + 0x00, + 0x00, + 0x00, + 0x00, // value2 + 0x0D, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + )); + + const list = accessor.getRepeatedFixed32Iterable(1); + + expectEqualToArray(list, [value1, value1, value2, value2]); + }); + + it('return the repeated field element from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const result1 = accessor.getRepeatedFixed32Element( + /* fieldNumber= */ 1, /* index= */ 0); + const result2 = accessor.getRepeatedFixed32Element( + /* fieldNumber= */ 1, /* index= */ 1); + + expect(result1).toEqual(value1); + expect(result2).toEqual(value2); + }); + + it('return the size from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const size = accessor.getRepeatedFixed32Size(1); + + expect(size).toEqual(2); + }); + + it('fail when getting unpacked fixed32 value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedFixed32Iterable(1); + }).toThrowError('Expected wire type: 5 but found: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectQualifiedIterable( + accessor.getRepeatedFixed32Iterable(1), + (value) => Number.isInteger(value)); + } + }); + + it('fail when adding unpacked fixed32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedFixed32Iterable(1, [fakeFixed32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedFixed32Iterable(1, [fakeFixed32]); + expectQualifiedIterable(accessor.getRepeatedFixed32Iterable(1)); + } + }); + + it('fail when adding single unpacked fixed32 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedFixed32Element(1, fakeFixed32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedFixed32Element(1, fakeFixed32); + expectQualifiedIterable(accessor.getRepeatedFixed32Iterable(1)); + } + }); + + it('fail when setting unpacked fixed32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedFixed32Iterable(1, [fakeFixed32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedFixed32Iterable(1, [fakeFixed32]); + expectQualifiedIterable(accessor.getRepeatedFixed32Iterable(1)); + } + }); + + it('fail when setting single unpacked fixed32 value with null value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x80, 0x80, 0x80, 0x00)); + const fakeFixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedFixed32Element(1, 0, fakeFixed32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedFixed32Element(1, 0, fakeFixed32); + expectQualifiedIterable( + accessor.getRepeatedFixed32Iterable(1), + ); + } + }); + + it('fail when adding packed fixed32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedFixed32Iterable(1, [fakeFixed32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedFixed32Iterable(1, [fakeFixed32]); + expectQualifiedIterable(accessor.getRepeatedFixed32Iterable(1)); + } + }); + + it('fail when adding single packed fixed32 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedFixed32Element(1, fakeFixed32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedFixed32Element(1, fakeFixed32); + expectQualifiedIterable(accessor.getRepeatedFixed32Iterable(1)); + } + }); + + it('fail when setting packed fixed32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedFixed32Iterable(1, [fakeFixed32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedFixed32Iterable(1, [fakeFixed32]); + expectQualifiedIterable(accessor.getRepeatedFixed32Iterable(1)); + } + }); + + it('fail when setting single packed fixed32 value with null value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + const fakeFixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedFixed32Element(1, 0, fakeFixed32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedFixed32Element(1, 0, fakeFixed32); + expectQualifiedIterable(accessor.getRepeatedFixed32Iterable(1)); + } + }); + + it('fail when setting single unpacked with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer( + createArrayBuffer(0x0A, 0x04, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedFixed32Element(1, 1, 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedFixed32Element(1, 1, 1); + expectQualifiedIterable( + accessor.getRepeatedFixed32Iterable(1), + (value) => Number.isInteger(value)); + } + }); + + it('fail when setting single packed with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedFixed32Element(1, 1, 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedFixed32Element(1, 1, 1); + expectQualifiedIterable( + accessor.getRepeatedFixed32Iterable(1), + (value) => Number.isInteger(value)); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedFixed32Element( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedFixed32Element( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated fixed64 does', () => { + const value1 = Int64.fromInt(1); + const value2 = Int64.fromInt(0); + + const unpackedValue1Value2 = createArrayBuffer( + 0x09, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value1 + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + ); + const unpackedValue2Value1 = createArrayBuffer( + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value1 + 0x09, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + ); + + const packedValue1Value2 = createArrayBuffer( + 0x0A, + 0x10, // tag + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value1 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + ); + const packedValue2Value1 = createArrayBuffer( + 0x0A, + 0x10, // tag + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value1 + ); + + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list = accessor.getRepeatedFixed64Iterable(1); + + expectEqualToArray(list, []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list1 = accessor.getRepeatedFixed64Iterable(1); + const list2 = accessor.getRepeatedFixed64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const size = accessor.getRepeatedFixed64Size(1); + + expect(size).toEqual(0); + }); + + it('return unpacked values from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list = accessor.getRepeatedFixed64Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for unpacked values', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list1 = accessor.getRepeatedFixed64Iterable(1); + const list2 = accessor.getRepeatedFixed64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedFixed64Element(1, value1); + const list1 = accessor.getRepeatedFixed64Iterable(1); + accessor.addUnpackedFixed64Element(1, value2); + const list2 = accessor.getRepeatedFixed64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedFixed64Iterable(1, [value1]); + const list1 = accessor.getRepeatedFixed64Iterable(1); + accessor.addUnpackedFixed64Iterable(1, [value2]); + const list2 = accessor.getRepeatedFixed64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + accessor.setUnpackedFixed64Element(1, 1, value1); + const list = accessor.getRepeatedFixed64Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedFixed64Iterable(1, [value1]); + const list = accessor.getRepeatedFixed64Iterable(1); + + expectEqualToArray(list, [value1]); + }); + + it('encode for adding single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedFixed64Element(1, value1); + accessor.addUnpackedFixed64Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for adding unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedFixed64Iterable(1, [value1]); + accessor.addUnpackedFixed64Iterable(1, [value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for setting single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setUnpackedFixed64Element(1, 0, value2); + accessor.setUnpackedFixed64Element(1, 1, value1); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue2Value1); + }); + + it('encode for setting unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedFixed64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('return packed values from the input', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list = accessor.getRepeatedFixed64Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for packed values', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list1 = accessor.getRepeatedFixed64Iterable(1); + const list2 = accessor.getRepeatedFixed64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedFixed64Element(1, value1); + const list1 = accessor.getRepeatedFixed64Iterable(1); + accessor.addPackedFixed64Element(1, value2); + const list2 = accessor.getRepeatedFixed64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedFixed64Iterable(1, [value1]); + const list1 = accessor.getRepeatedFixed64Iterable(1); + accessor.addPackedFixed64Iterable(1, [value2]); + const list2 = accessor.getRepeatedFixed64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedFixed64Element(1, 1, value1); + const list = accessor.getRepeatedFixed64Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedFixed64Iterable(1, [value1]); + const list1 = accessor.getRepeatedFixed64Iterable(1); + accessor.setPackedFixed64Iterable(1, [value2]); + const list2 = accessor.getRepeatedFixed64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value2]); + }); + + it('encode for adding single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedFixed64Element(1, value1); + accessor.addPackedFixed64Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for adding packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedFixed64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for setting single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedFixed64Element(1, 0, value2); + accessor.setPackedFixed64Element(1, 1, value1); + + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue2Value1); + }); + + it('encode for setting packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedFixed64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('return combined values from the input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // value1 + 0x0A, 0x10, // tag + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // value1 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // value2 + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // value2 + )); + + const list = accessor.getRepeatedFixed64Iterable(1); + + expectEqualToArray(list, [value1, value1, value2, value2]); + }); + + it('return the repeated field element from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const result1 = accessor.getRepeatedFixed64Element( + /* fieldNumber= */ 1, /* index= */ 0); + const result2 = accessor.getRepeatedFixed64Element( + /* fieldNumber= */ 1, /* index= */ 1); + + expect(result1).toEqual(value1); + expect(result2).toEqual(value2); + }); + + it('return the size from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const size = accessor.getRepeatedFixed64Size(1); + + expect(size).toEqual(2); + }); + + it('fail when getting unpacked fixed64 value with other wire types', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedFixed64Iterable(1); + }).toThrowError('Expected wire type: 1 but found: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectQualifiedIterable( + accessor.getRepeatedFixed64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when adding unpacked fixed64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedFixed64Iterable(1, [fakeFixed64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedFixed64Iterable(1, [fakeFixed64]); + expectQualifiedIterable(accessor.getRepeatedFixed64Iterable(1)); + } + }); + + it('fail when adding single unpacked fixed64 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedFixed64Element(1, fakeFixed64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedFixed64Element(1, fakeFixed64); + expectQualifiedIterable(accessor.getRepeatedFixed64Iterable(1)); + } + }); + + it('fail when setting unpacked fixed64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedFixed64Iterable(1, [fakeFixed64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedFixed64Iterable(1, [fakeFixed64]); + expectQualifiedIterable(accessor.getRepeatedFixed64Iterable(1)); + } + }); + + it('fail when setting single unpacked fixed64 value with null value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00)); + const fakeFixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedFixed64Element(1, 0, fakeFixed64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedFixed64Element(1, 0, fakeFixed64); + expectQualifiedIterable(accessor.getRepeatedFixed64Iterable(1)); + } + }); + + it('fail when adding packed fixed64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedFixed64Iterable(1, [fakeFixed64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedFixed64Iterable(1, [fakeFixed64]); + expectQualifiedIterable(accessor.getRepeatedFixed64Iterable(1)); + } + }); + + it('fail when adding single packed fixed64 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedFixed64Element(1, fakeFixed64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedFixed64Element(1, fakeFixed64); + expectQualifiedIterable(accessor.getRepeatedFixed64Iterable(1)); + } + }); + + it('fail when setting packed fixed64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedFixed64Iterable(1, [fakeFixed64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedFixed64Iterable(1, [fakeFixed64]); + expectQualifiedIterable(accessor.getRepeatedFixed64Iterable(1)); + } + }); + + it('fail when setting single packed fixed64 value with null value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + const fakeFixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedFixed64Element(1, 0, fakeFixed64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedFixed64Element(1, 0, fakeFixed64); + expectQualifiedIterable(accessor.getRepeatedFixed64Iterable(1)); + } + }); + + it('fail when setting single unpacked with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedFixed64Element(1, 1, Int64.fromInt(1))) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedFixed64Element(1, 1, Int64.fromInt(1)); + expectQualifiedIterable( + accessor.getRepeatedFixed64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when setting single packed with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedFixed64Element(1, 1, Int64.fromInt(1))) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedFixed64Element(1, 1, Int64.fromInt(1)); + expectQualifiedIterable( + accessor.getRepeatedFixed64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedFixed64Element( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedFixed64Element( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated float does', () => { + const value1 = 1.6; + const value1Float = Math.fround(1.6); + const value2 = 0; + + const unpackedValue1Value2 = createArrayBuffer( + 0x0D, 0xCD, 0xCC, 0xCC, 0x3F, 0x0D, 0x00, 0x00, 0x00, 0x00); + const unpackedValue2Value1 = createArrayBuffer( + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xCD, 0xCC, 0xCC, 0x3F); + + const packedValue1Value2 = createArrayBuffer( + 0x0A, 0x08, 0xCD, 0xCC, 0xCC, 0x3F, 0x00, 0x00, 0x00, 0x00); + const packedValue2Value1 = createArrayBuffer( + 0x0A, 0x08, 0x00, 0x00, 0x00, 0x00, 0xCD, 0xCC, 0xCC, 0x3F); + + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list = accessor.getRepeatedFloatIterable(1); + + expectEqualToArray(list, []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list1 = accessor.getRepeatedFloatIterable(1); + const list2 = accessor.getRepeatedFloatIterable(1); + + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const size = accessor.getRepeatedFloatSize(1); + + expect(size).toEqual(0); + }); + + it('return unpacked values from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list = accessor.getRepeatedFloatIterable(1); + + expectEqualToArray(list, [value1Float, value2]); + }); + + it('ensure not the same instance returned for unpacked values', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list1 = accessor.getRepeatedFloatIterable(1); + const list2 = accessor.getRepeatedFloatIterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedFloatElement(1, value1); + const list1 = accessor.getRepeatedFloatIterable(1); + accessor.addUnpackedFloatElement(1, value2); + const list2 = accessor.getRepeatedFloatIterable(1); + + expectEqualToArray(list1, [value1Float]); + expectEqualToArray(list2, [value1Float, value2]); + }); + + it('add unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedFloatIterable(1, [value1]); + const list1 = accessor.getRepeatedFloatIterable(1); + accessor.addUnpackedFloatIterable(1, [value2]); + const list2 = accessor.getRepeatedFloatIterable(1); + + expectEqualToArray(list1, [value1Float]); + expectEqualToArray(list2, [value1Float, value2]); + }); + + it('set a single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + accessor.setUnpackedFloatElement(1, 1, value1); + const list = accessor.getRepeatedFloatIterable(1); + + expectEqualToArray(list, [value1Float, value1Float]); + }); + + it('set unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedFloatIterable(1, [value1]); + const list = accessor.getRepeatedFloatIterable(1); + + expectEqualToArray(list, [value1Float]); + }); + + it('encode for adding single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedFloatElement(1, value1); + accessor.addUnpackedFloatElement(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for adding unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedFloatIterable(1, [value1]); + accessor.addUnpackedFloatIterable(1, [value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for setting single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setUnpackedFloatElement(1, 0, value2); + accessor.setUnpackedFloatElement(1, 1, value1); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue2Value1); + }); + + it('encode for setting unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedFloatIterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('return packed values from the input', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list = accessor.getRepeatedFloatIterable(1); + + expectEqualToArray(list, [value1Float, value2]); + }); + + it('ensure not the same instance returned for packed values', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list1 = accessor.getRepeatedFloatIterable(1); + const list2 = accessor.getRepeatedFloatIterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedFloatElement(1, value1); + const list1 = accessor.getRepeatedFloatIterable(1); + accessor.addPackedFloatElement(1, value2); + const list2 = accessor.getRepeatedFloatIterable(1); + + expectEqualToArray(list1, [value1Float]); + expectEqualToArray(list2, [value1Float, value2]); + }); + + it('add packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedFloatIterable(1, [value1]); + const list1 = accessor.getRepeatedFloatIterable(1); + accessor.addPackedFloatIterable(1, [value2]); + const list2 = accessor.getRepeatedFloatIterable(1); + + expectEqualToArray(list1, [value1Float]); + expectEqualToArray(list2, [value1Float, value2]); + }); + + it('set a single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedFloatElement(1, 1, value1); + const list = accessor.getRepeatedFloatIterable(1); + + expectEqualToArray(list, [value1Float, value1Float]); + }); + + it('set packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedFloatIterable(1, [value1]); + const list1 = accessor.getRepeatedFloatIterable(1); + accessor.setPackedFloatIterable(1, [value2]); + const list2 = accessor.getRepeatedFloatIterable(1); + + expectEqualToArray(list1, [value1Float]); + expectEqualToArray(list2, [value2]); + }); + + it('encode for adding single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedFloatElement(1, value1); + accessor.addPackedFloatElement(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for adding packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedFloatIterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for setting single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedFloatElement(1, 0, value2); + accessor.setPackedFloatElement(1, 1, value1); + + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue2Value1); + }); + + it('encode for setting packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedFloatIterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('return combined values from the input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x0D, + 0xCD, + 0xCC, + 0xCC, + 0x3F, // value1 + 0x0A, + 0x08, // tag + 0xCD, + 0xCC, + 0xCC, + 0x3F, // value1 + 0x00, + 0x00, + 0x00, + 0x00, // value2 + 0x0D, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + )); + + const list = accessor.getRepeatedFloatIterable(1); + + expectEqualToArray(list, [value1Float, value1Float, value2, value2]); + }); + + it('return the repeated field element from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const result1 = accessor.getRepeatedFloatElement( + /* fieldNumber= */ 1, /* index= */ 0); + const result2 = accessor.getRepeatedFloatElement( + /* fieldNumber= */ 1, /* index= */ 1); + + expect(result1).toEqual(value1Float); + expect(result2).toEqual(value2); + }); + + it('return the size from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const size = accessor.getRepeatedFloatSize(1); + + expect(size).toEqual(2); + }); + + it('fail when getting unpacked float value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedFloatIterable(1); + }).toThrowError('Expected wire type: 5 but found: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectQualifiedIterable( + accessor.getRepeatedFloatIterable(1), + (value) => typeof value === 'number'); + } + }); + + it('fail when adding unpacked float values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFloat = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedFloatIterable(1, [fakeFloat])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedFloatIterable(1, [fakeFloat]); + expectQualifiedIterable(accessor.getRepeatedFloatIterable(1)); + } + }); + + it('fail when adding single unpacked float value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFloat = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedFloatElement(1, fakeFloat)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedFloatElement(1, fakeFloat); + expectQualifiedIterable(accessor.getRepeatedFloatIterable(1)); + } + }); + + it('fail when setting unpacked float values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFloat = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedFloatIterable(1, [fakeFloat])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedFloatIterable(1, [fakeFloat]); + expectQualifiedIterable(accessor.getRepeatedFloatIterable(1)); + } + }); + + it('fail when setting single unpacked float value with null value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x80, 0x80, 0x80, 0x00)); + const fakeFloat = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedFloatElement(1, 0, fakeFloat)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedFloatElement(1, 0, fakeFloat); + expectQualifiedIterable(accessor.getRepeatedFloatIterable(1)); + } + }); + + it('fail when adding packed float values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFloat = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedFloatIterable(1, [fakeFloat])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedFloatIterable(1, [fakeFloat]); + expectQualifiedIterable(accessor.getRepeatedFloatIterable(1)); + } + }); + + it('fail when adding single packed float value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFloat = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedFloatElement(1, fakeFloat)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedFloatElement(1, fakeFloat); + expectQualifiedIterable(accessor.getRepeatedFloatIterable(1)); + } + }); + + it('fail when setting packed float values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeFloat = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedFloatIterable(1, [fakeFloat])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedFloatIterable(1, [fakeFloat]); + expectQualifiedIterable(accessor.getRepeatedFloatIterable(1)); + } + }); + + it('fail when setting single packed float value with null value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + const fakeFloat = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedFloatElement(1, 0, fakeFloat)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedFloatElement(1, 0, fakeFloat); + expectQualifiedIterable(accessor.getRepeatedFloatIterable(1)); + } + }); + + it('fail when setting single unpacked with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedFloatElement(1, 1, 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedFloatElement(1, 1, 1); + expectQualifiedIterable( + accessor.getRepeatedFloatIterable(1), + (value) => typeof value === 'number'); + } + }); + + it('fail when setting single packed with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedFloatElement(1, 1, 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedFloatElement(1, 1, 1); + expectQualifiedIterable( + accessor.getRepeatedFloatIterable(1), + (value) => typeof value === 'number'); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedFloatElement( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedFloatElement( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated int32 does', () => { + const value1 = 1; + const value2 = 0; + + const unpackedValue1Value2 = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const unpackedValue2Value1 = createArrayBuffer(0x08, 0x00, 0x08, 0x01); + + const packedValue1Value2 = createArrayBuffer(0x0A, 0x02, 0x01, 0x00); + const packedValue2Value1 = createArrayBuffer(0x0A, 0x02, 0x00, 0x01); + + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list = accessor.getRepeatedInt32Iterable(1); + + expectEqualToArray(list, []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list1 = accessor.getRepeatedInt32Iterable(1); + const list2 = accessor.getRepeatedInt32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const size = accessor.getRepeatedInt32Size(1); + + expect(size).toEqual(0); + }); + + it('return unpacked values from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list = accessor.getRepeatedInt32Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for unpacked values', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list1 = accessor.getRepeatedInt32Iterable(1); + const list2 = accessor.getRepeatedInt32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedInt32Element(1, value1); + const list1 = accessor.getRepeatedInt32Iterable(1); + accessor.addUnpackedInt32Element(1, value2); + const list2 = accessor.getRepeatedInt32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedInt32Iterable(1, [value1]); + const list1 = accessor.getRepeatedInt32Iterable(1); + accessor.addUnpackedInt32Iterable(1, [value2]); + const list2 = accessor.getRepeatedInt32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + accessor.setUnpackedInt32Element(1, 1, value1); + const list = accessor.getRepeatedInt32Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedInt32Iterable(1, [value1]); + const list = accessor.getRepeatedInt32Iterable(1); + + expectEqualToArray(list, [value1]); + }); + + it('encode for adding single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedInt32Element(1, value1); + accessor.addUnpackedInt32Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for adding unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedInt32Iterable(1, [value1]); + accessor.addUnpackedInt32Iterable(1, [value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for setting single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setUnpackedInt32Element(1, 0, value2); + accessor.setUnpackedInt32Element(1, 1, value1); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue2Value1); + }); + + it('encode for setting unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedInt32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('return packed values from the input', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list = accessor.getRepeatedInt32Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for packed values', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list1 = accessor.getRepeatedInt32Iterable(1); + const list2 = accessor.getRepeatedInt32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedInt32Element(1, value1); + const list1 = accessor.getRepeatedInt32Iterable(1); + accessor.addPackedInt32Element(1, value2); + const list2 = accessor.getRepeatedInt32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedInt32Iterable(1, [value1]); + const list1 = accessor.getRepeatedInt32Iterable(1); + accessor.addPackedInt32Iterable(1, [value2]); + const list2 = accessor.getRepeatedInt32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedInt32Element(1, 1, value1); + const list = accessor.getRepeatedInt32Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedInt32Iterable(1, [value1]); + const list1 = accessor.getRepeatedInt32Iterable(1); + accessor.setPackedInt32Iterable(1, [value2]); + const list2 = accessor.getRepeatedInt32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value2]); + }); + + it('encode for adding single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedInt32Element(1, value1); + accessor.addPackedInt32Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for adding packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedInt32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for setting single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedInt32Element(1, 0, value2); + accessor.setPackedInt32Element(1, 1, value1); + + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue2Value1); + }); + + it('encode for setting packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedInt32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('return combined values from the input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, + 0x01, // unpacked value1 + 0x0A, + 0x02, + 0x01, + 0x00, // packed value1 and value2 + 0x08, + 0x00, // unpacked value2 + )); + + const list = accessor.getRepeatedInt32Iterable(1); + + expectEqualToArray(list, [value1, value1, value2, value2]); + }); + + it('return the repeated field element from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const result1 = accessor.getRepeatedInt32Element( + /* fieldNumber= */ 1, /* index= */ 0); + const result2 = accessor.getRepeatedInt32Element( + /* fieldNumber= */ 1, /* index= */ 1); + + expect(result1).toEqual(value1); + expect(result2).toEqual(value2); + }); + + it('return the size from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const size = accessor.getRepeatedInt32Size(1); + + expect(size).toEqual(2); + }); + + it('fail when getting unpacked int32 value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedInt32Iterable(1); + }).toThrowError('Expected wire type: 0 but found: 5'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectQualifiedIterable( + accessor.getRepeatedInt32Iterable(1), + (value) => Number.isInteger(value)); + } + }); + + it('fail when adding unpacked int32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeInt32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedInt32Iterable(1, [fakeInt32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedInt32Iterable(1, [fakeInt32]); + expectQualifiedIterable(accessor.getRepeatedInt32Iterable(1)); + } + }); + + it('fail when adding single unpacked int32 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeInt32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedInt32Element(1, fakeInt32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedInt32Element(1, fakeInt32); + expectQualifiedIterable(accessor.getRepeatedInt32Iterable(1)); + } + }); + + it('fail when setting unpacked int32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeInt32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedInt32Iterable(1, [fakeInt32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedInt32Iterable(1, [fakeInt32]); + expectQualifiedIterable(accessor.getRepeatedInt32Iterable(1)); + } + }); + + it('fail when setting single unpacked int32 value with null value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x80, 0x80, 0x80, 0x00)); + const fakeInt32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedInt32Element(1, 0, fakeInt32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedInt32Element(1, 0, fakeInt32); + expectQualifiedIterable( + accessor.getRepeatedInt32Iterable(1), + ); + } + }); + + it('fail when adding packed int32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeInt32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedInt32Iterable(1, [fakeInt32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedInt32Iterable(1, [fakeInt32]); + expectQualifiedIterable(accessor.getRepeatedInt32Iterable(1)); + } + }); + + it('fail when adding single packed int32 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeInt32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedInt32Element(1, fakeInt32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedInt32Element(1, fakeInt32); + expectQualifiedIterable(accessor.getRepeatedInt32Iterable(1)); + } + }); + + it('fail when setting packed int32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeInt32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedInt32Iterable(1, [fakeInt32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedInt32Iterable(1, [fakeInt32]); + expectQualifiedIterable(accessor.getRepeatedInt32Iterable(1)); + } + }); + + it('fail when setting single packed int32 value with null value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + const fakeInt32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedInt32Element(1, 0, fakeInt32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedInt32Element(1, 0, fakeInt32); + expectQualifiedIterable(accessor.getRepeatedInt32Iterable(1)); + } + }); + + it('fail when setting single unpacked with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedInt32Element(1, 1, 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedInt32Element(1, 1, 1); + expectQualifiedIterable( + accessor.getRepeatedInt32Iterable(1), + (value) => Number.isInteger(value)); + } + }); + + it('fail when setting single packed with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedInt32Element(1, 1, 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedInt32Element(1, 1, 1); + expectQualifiedIterable( + accessor.getRepeatedInt32Iterable(1), + (value) => Number.isInteger(value)); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedInt32Element( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedInt32Element( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated int64 does', () => { + const value1 = Int64.fromInt(1); + const value2 = Int64.fromInt(0); + + const unpackedValue1Value2 = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const unpackedValue2Value1 = createArrayBuffer(0x08, 0x00, 0x08, 0x01); + + const packedValue1Value2 = createArrayBuffer(0x0A, 0x02, 0x01, 0x00); + const packedValue2Value1 = createArrayBuffer(0x0A, 0x02, 0x00, 0x01); + + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list = accessor.getRepeatedInt64Iterable(1); + + expectEqualToArray(list, []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list1 = accessor.getRepeatedInt64Iterable(1); + const list2 = accessor.getRepeatedInt64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const size = accessor.getRepeatedInt64Size(1); + + expect(size).toEqual(0); + }); + + it('return unpacked values from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list = accessor.getRepeatedInt64Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for unpacked values', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list1 = accessor.getRepeatedInt64Iterable(1); + const list2 = accessor.getRepeatedInt64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedInt64Element(1, value1); + const list1 = accessor.getRepeatedInt64Iterable(1); + accessor.addUnpackedInt64Element(1, value2); + const list2 = accessor.getRepeatedInt64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedInt64Iterable(1, [value1]); + const list1 = accessor.getRepeatedInt64Iterable(1); + accessor.addUnpackedInt64Iterable(1, [value2]); + const list2 = accessor.getRepeatedInt64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + accessor.setUnpackedInt64Element(1, 1, value1); + const list = accessor.getRepeatedInt64Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedInt64Iterable(1, [value1]); + const list = accessor.getRepeatedInt64Iterable(1); + + expectEqualToArray(list, [value1]); + }); + + it('encode for adding single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedInt64Element(1, value1); + accessor.addUnpackedInt64Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for adding unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedInt64Iterable(1, [value1]); + accessor.addUnpackedInt64Iterable(1, [value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for setting single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setUnpackedInt64Element(1, 0, value2); + accessor.setUnpackedInt64Element(1, 1, value1); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue2Value1); + }); + + it('encode for setting unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedInt64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('return packed values from the input', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list = accessor.getRepeatedInt64Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for packed values', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list1 = accessor.getRepeatedInt64Iterable(1); + const list2 = accessor.getRepeatedInt64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedInt64Element(1, value1); + const list1 = accessor.getRepeatedInt64Iterable(1); + accessor.addPackedInt64Element(1, value2); + const list2 = accessor.getRepeatedInt64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedInt64Iterable(1, [value1]); + const list1 = accessor.getRepeatedInt64Iterable(1); + accessor.addPackedInt64Iterable(1, [value2]); + const list2 = accessor.getRepeatedInt64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedInt64Element(1, 1, value1); + const list = accessor.getRepeatedInt64Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedInt64Iterable(1, [value1]); + const list1 = accessor.getRepeatedInt64Iterable(1); + accessor.setPackedInt64Iterable(1, [value2]); + const list2 = accessor.getRepeatedInt64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value2]); + }); + + it('encode for adding single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedInt64Element(1, value1); + accessor.addPackedInt64Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for adding packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedInt64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for setting single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedInt64Element(1, 0, value2); + accessor.setPackedInt64Element(1, 1, value1); + + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue2Value1); + }); + + it('encode for setting packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedInt64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('return combined values from the input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, + 0x01, // unpacked value1 + 0x0A, + 0x02, + 0x01, + 0x00, // packed value1 and value2 + 0x08, + 0x00, // unpacked value2 + )); + + const list = accessor.getRepeatedInt64Iterable(1); + + expectEqualToArray(list, [value1, value1, value2, value2]); + }); + + it('return the repeated field element from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const result1 = accessor.getRepeatedInt64Element( + /* fieldNumber= */ 1, /* index= */ 0); + const result2 = accessor.getRepeatedInt64Element( + /* fieldNumber= */ 1, /* index= */ 1); + + expect(result1).toEqual(value1); + expect(result2).toEqual(value2); + }); + + it('return the size from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const size = accessor.getRepeatedInt64Size(1); + + expect(size).toEqual(2); + }); + + it('fail when getting unpacked int64 value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedInt64Iterable(1); + }).toThrowError('Expected wire type: 0 but found: 5'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectQualifiedIterable( + accessor.getRepeatedInt64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when adding unpacked int64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeInt64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedInt64Iterable(1, [fakeInt64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedInt64Iterable(1, [fakeInt64]); + expectQualifiedIterable(accessor.getRepeatedInt64Iterable(1)); + } + }); + + it('fail when adding single unpacked int64 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeInt64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedInt64Element(1, fakeInt64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedInt64Element(1, fakeInt64); + expectQualifiedIterable(accessor.getRepeatedInt64Iterable(1)); + } + }); + + it('fail when setting unpacked int64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeInt64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedInt64Iterable(1, [fakeInt64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedInt64Iterable(1, [fakeInt64]); + expectQualifiedIterable(accessor.getRepeatedInt64Iterable(1)); + } + }); + + it('fail when setting single unpacked int64 value with null value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x80, 0x80, 0x80, 0x00)); + const fakeInt64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedInt64Element(1, 0, fakeInt64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedInt64Element(1, 0, fakeInt64); + expectQualifiedIterable(accessor.getRepeatedInt64Iterable(1)); + } + }); + + it('fail when adding packed int64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeInt64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedInt64Iterable(1, [fakeInt64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedInt64Iterable(1, [fakeInt64]); + expectQualifiedIterable(accessor.getRepeatedInt64Iterable(1)); + } + }); + + it('fail when adding single packed int64 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeInt64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedInt64Element(1, fakeInt64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedInt64Element(1, fakeInt64); + expectQualifiedIterable(accessor.getRepeatedInt64Iterable(1)); + } + }); + + it('fail when setting packed int64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeInt64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedInt64Iterable(1, [fakeInt64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedInt64Iterable(1, [fakeInt64]); + expectQualifiedIterable(accessor.getRepeatedInt64Iterable(1)); + } + }); + + it('fail when setting single packed int64 value with null value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + const fakeInt64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedInt64Element(1, 0, fakeInt64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedInt64Element(1, 0, fakeInt64); + expectQualifiedIterable(accessor.getRepeatedInt64Iterable(1)); + } + }); + + it('fail when setting single unpacked with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedInt64Element(1, 1, Int64.fromInt(1))) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedInt64Element(1, 1, Int64.fromInt(1)); + expectQualifiedIterable( + accessor.getRepeatedInt64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when setting single packed with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedInt64Element(1, 1, Int64.fromInt(1))) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedInt64Element(1, 1, Int64.fromInt(1)); + expectQualifiedIterable( + accessor.getRepeatedInt64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedInt64Element( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedInt64Element( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated sfixed32 does', () => { + const value1 = 1; + const value2 = 0; + + const unpackedValue1Value2 = createArrayBuffer( + 0x0D, 0x01, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00); + const unpackedValue2Value1 = createArrayBuffer( + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, 0x00); + + const packedValue1Value2 = createArrayBuffer( + 0x0A, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + const packedValue2Value1 = createArrayBuffer( + 0x0A, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00); + + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list = accessor.getRepeatedSfixed32Iterable(1); + + expectEqualToArray(list, []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list1 = accessor.getRepeatedSfixed32Iterable(1); + const list2 = accessor.getRepeatedSfixed32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const size = accessor.getRepeatedSfixed32Size(1); + + expect(size).toEqual(0); + }); + + it('return unpacked values from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list = accessor.getRepeatedSfixed32Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for unpacked values', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list1 = accessor.getRepeatedSfixed32Iterable(1); + const list2 = accessor.getRepeatedSfixed32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSfixed32Element(1, value1); + const list1 = accessor.getRepeatedSfixed32Iterable(1); + accessor.addUnpackedSfixed32Element(1, value2); + const list2 = accessor.getRepeatedSfixed32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSfixed32Iterable(1, [value1]); + const list1 = accessor.getRepeatedSfixed32Iterable(1); + accessor.addUnpackedSfixed32Iterable(1, [value2]); + const list2 = accessor.getRepeatedSfixed32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + accessor.setUnpackedSfixed32Element(1, 1, value1); + const list = accessor.getRepeatedSfixed32Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedSfixed32Iterable(1, [value1]); + const list = accessor.getRepeatedSfixed32Iterable(1); + + expectEqualToArray(list, [value1]); + }); + + it('encode for adding single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSfixed32Element(1, value1); + accessor.addUnpackedSfixed32Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for adding unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSfixed32Iterable(1, [value1]); + accessor.addUnpackedSfixed32Iterable(1, [value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for setting single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setUnpackedSfixed32Element(1, 0, value2); + accessor.setUnpackedSfixed32Element(1, 1, value1); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue2Value1); + }); + + it('encode for setting unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedSfixed32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('return packed values from the input', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list = accessor.getRepeatedSfixed32Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for packed values', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list1 = accessor.getRepeatedSfixed32Iterable(1); + const list2 = accessor.getRepeatedSfixed32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSfixed32Element(1, value1); + const list1 = accessor.getRepeatedSfixed32Iterable(1); + accessor.addPackedSfixed32Element(1, value2); + const list2 = accessor.getRepeatedSfixed32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSfixed32Iterable(1, [value1]); + const list1 = accessor.getRepeatedSfixed32Iterable(1); + accessor.addPackedSfixed32Iterable(1, [value2]); + const list2 = accessor.getRepeatedSfixed32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedSfixed32Element(1, 1, value1); + const list = accessor.getRepeatedSfixed32Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedSfixed32Iterable(1, [value1]); + const list1 = accessor.getRepeatedSfixed32Iterable(1); + accessor.setPackedSfixed32Iterable(1, [value2]); + const list2 = accessor.getRepeatedSfixed32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value2]); + }); + + it('encode for adding single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSfixed32Element(1, value1); + accessor.addPackedSfixed32Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for adding packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSfixed32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for setting single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedSfixed32Element(1, 0, value2); + accessor.setPackedSfixed32Element(1, 1, value1); + + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue2Value1); + }); + + it('encode for setting packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedSfixed32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('return combined values from the input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x0D, + 0x01, + 0x00, + 0x00, + 0x00, // value1 + 0x0A, + 0x08, // tag + 0x01, + 0x00, + 0x00, + 0x00, // value1 + 0x00, + 0x00, + 0x00, + 0x00, // value2 + 0x0D, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + )); + + const list = accessor.getRepeatedSfixed32Iterable(1); + + expectEqualToArray(list, [value1, value1, value2, value2]); + }); + + it('return the repeated field element from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const result1 = accessor.getRepeatedSfixed32Element( + /* fieldNumber= */ 1, /* index= */ 0); + const result2 = accessor.getRepeatedSfixed32Element( + /* fieldNumber= */ 1, /* index= */ 1); + + expect(result1).toEqual(value1); + expect(result2).toEqual(value2); + }); + + it('return the size from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const size = accessor.getRepeatedSfixed32Size(1); + + expect(size).toEqual(2); + }); + + it('fail when getting unpacked sfixed32 value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedSfixed32Iterable(1); + }).toThrowError('Expected wire type: 5 but found: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectQualifiedIterable( + accessor.getRepeatedSfixed32Iterable(1), + (value) => typeof value === 'number'); + } + }); + + it('fail when adding unpacked sfixed32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSfixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedSfixed32Iterable(1, [fakeSfixed32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedSfixed32Iterable(1, [fakeSfixed32]); + expectQualifiedIterable(accessor.getRepeatedSfixed32Iterable(1)); + } + }); + + it('fail when adding single unpacked sfixed32 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSfixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedSfixed32Element(1, fakeSfixed32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedSfixed32Element(1, fakeSfixed32); + expectQualifiedIterable(accessor.getRepeatedSfixed32Iterable(1)); + } + }); + + it('fail when setting unpacked sfixed32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSfixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedSfixed32Iterable(1, [fakeSfixed32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedSfixed32Iterable(1, [fakeSfixed32]); + expectQualifiedIterable(accessor.getRepeatedSfixed32Iterable(1)); + } + }); + + it('fail when setting single unpacked sfixed32 value with null value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x80, 0x80, 0x80, 0x00)); + const fakeSfixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedSfixed32Element(1, 0, fakeSfixed32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedSfixed32Element(1, 0, fakeSfixed32); + expectQualifiedIterable(accessor.getRepeatedSfixed32Iterable(1)); + } + }); + + it('fail when adding packed sfixed32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSfixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedSfixed32Iterable(1, [fakeSfixed32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedSfixed32Iterable(1, [fakeSfixed32]); + expectQualifiedIterable(accessor.getRepeatedSfixed32Iterable(1)); + } + }); + + it('fail when adding single packed sfixed32 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSfixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedSfixed32Element(1, fakeSfixed32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedSfixed32Element(1, fakeSfixed32); + expectQualifiedIterable(accessor.getRepeatedSfixed32Iterable(1)); + } + }); + + it('fail when setting packed sfixed32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSfixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedSfixed32Iterable(1, [fakeSfixed32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedSfixed32Iterable(1, [fakeSfixed32]); + expectQualifiedIterable(accessor.getRepeatedSfixed32Iterable(1)); + } + }); + + it('fail when setting single packed sfixed32 value with null value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + const fakeSfixed32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedSfixed32Element(1, 0, fakeSfixed32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedSfixed32Element(1, 0, fakeSfixed32); + expectQualifiedIterable(accessor.getRepeatedSfixed32Iterable(1)); + } + }); + + it('fail when setting single unpacked with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedSfixed32Element(1, 1, 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedSfixed32Element(1, 1, 1); + expectQualifiedIterable( + accessor.getRepeatedSfixed32Iterable(1), + (value) => typeof value === 'number'); + } + }); + + it('fail when setting single packed with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedSfixed32Element(1, 1, 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedSfixed32Element(1, 1, 1); + expectQualifiedIterable( + accessor.getRepeatedSfixed32Iterable(1), + (value) => typeof value === 'number'); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedSfixed32Element( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedSfixed32Element( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated sfixed64 does', () => { + const value1 = Int64.fromInt(1); + const value2 = Int64.fromInt(0); + + const unpackedValue1Value2 = createArrayBuffer( + 0x09, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value1 + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + ); + const unpackedValue2Value1 = createArrayBuffer( + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value1 + 0x09, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + ); + + const packedValue1Value2 = createArrayBuffer( + 0x0A, + 0x10, // tag + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value1 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + ); + const packedValue2Value1 = createArrayBuffer( + 0x0A, + 0x10, // tag + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value2 + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // value1 + ); + + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list = accessor.getRepeatedSfixed64Iterable(1); + + expectEqualToArray(list, []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list1 = accessor.getRepeatedSfixed64Iterable(1); + const list2 = accessor.getRepeatedSfixed64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const size = accessor.getRepeatedSfixed64Size(1); + + expect(size).toEqual(0); + }); + + it('return unpacked values from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list = accessor.getRepeatedSfixed64Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for unpacked values', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list1 = accessor.getRepeatedSfixed64Iterable(1); + const list2 = accessor.getRepeatedSfixed64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSfixed64Element(1, value1); + const list1 = accessor.getRepeatedSfixed64Iterable(1); + accessor.addUnpackedSfixed64Element(1, value2); + const list2 = accessor.getRepeatedSfixed64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSfixed64Iterable(1, [value1]); + const list1 = accessor.getRepeatedSfixed64Iterable(1); + accessor.addUnpackedSfixed64Iterable(1, [value2]); + const list2 = accessor.getRepeatedSfixed64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + accessor.setUnpackedSfixed64Element(1, 1, value1); + const list = accessor.getRepeatedSfixed64Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedSfixed64Iterable(1, [value1]); + const list = accessor.getRepeatedSfixed64Iterable(1); + + expectEqualToArray(list, [value1]); + }); + + it('encode for adding single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSfixed64Element(1, value1); + accessor.addUnpackedSfixed64Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for adding unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSfixed64Iterable(1, [value1]); + accessor.addUnpackedSfixed64Iterable(1, [value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for setting single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setUnpackedSfixed64Element(1, 0, value2); + accessor.setUnpackedSfixed64Element(1, 1, value1); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue2Value1); + }); + + it('encode for setting unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedSfixed64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('return packed values from the input', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list = accessor.getRepeatedSfixed64Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for packed values', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list1 = accessor.getRepeatedSfixed64Iterable(1); + const list2 = accessor.getRepeatedSfixed64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSfixed64Element(1, value1); + const list1 = accessor.getRepeatedSfixed64Iterable(1); + accessor.addPackedSfixed64Element(1, value2); + const list2 = accessor.getRepeatedSfixed64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSfixed64Iterable(1, [value1]); + const list1 = accessor.getRepeatedSfixed64Iterable(1); + accessor.addPackedSfixed64Iterable(1, [value2]); + const list2 = accessor.getRepeatedSfixed64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedSfixed64Element(1, 1, value1); + const list = accessor.getRepeatedSfixed64Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedSfixed64Iterable(1, [value1]); + const list1 = accessor.getRepeatedSfixed64Iterable(1); + accessor.setPackedSfixed64Iterable(1, [value2]); + const list2 = accessor.getRepeatedSfixed64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value2]); + }); + + it('encode for adding single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSfixed64Element(1, value1); + accessor.addPackedSfixed64Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for adding packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSfixed64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for setting single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedSfixed64Element(1, 0, value2); + accessor.setPackedSfixed64Element(1, 1, value1); + + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue2Value1); + }); + + it('encode for setting packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedSfixed64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('return combined values from the input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // value1 + 0x0A, 0x10, // tag + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // value1 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // value2 + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // value2 + )); + + const list = accessor.getRepeatedSfixed64Iterable(1); + + expectEqualToArray(list, [value1, value1, value2, value2]); + }); + + it('return the repeated field element from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const result1 = accessor.getRepeatedSfixed64Element( + /* fieldNumber= */ 1, /* index= */ 0); + const result2 = accessor.getRepeatedSfixed64Element( + /* fieldNumber= */ 1, /* index= */ 1); + + expect(result1).toEqual(value1); + expect(result2).toEqual(value2); + }); + + it('return the size from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const size = accessor.getRepeatedSfixed64Size(1); + + expect(size).toEqual(2); + }); + + it('fail when getting unpacked sfixed64 value with other wire types', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedSfixed64Iterable(1); + }).toThrowError('Expected wire type: 1 but found: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectQualifiedIterable( + accessor.getRepeatedSfixed64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when adding unpacked sfixed64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSfixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedSfixed64Iterable(1, [fakeSfixed64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedSfixed64Iterable(1, [fakeSfixed64]); + expectQualifiedIterable(accessor.getRepeatedSfixed64Iterable(1)); + } + }); + + it('fail when adding single unpacked sfixed64 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSfixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedSfixed64Element(1, fakeSfixed64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedSfixed64Element(1, fakeSfixed64); + expectQualifiedIterable(accessor.getRepeatedSfixed64Iterable(1)); + } + }); + + it('fail when setting unpacked sfixed64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSfixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedSfixed64Iterable(1, [fakeSfixed64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedSfixed64Iterable(1, [fakeSfixed64]); + expectQualifiedIterable(accessor.getRepeatedSfixed64Iterable(1)); + } + }); + + it('fail when setting single unpacked sfixed64 value with null value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00)); + const fakeSfixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedSfixed64Element(1, 0, fakeSfixed64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedSfixed64Element(1, 0, fakeSfixed64); + expectQualifiedIterable(accessor.getRepeatedSfixed64Iterable(1)); + } + }); + + it('fail when adding packed sfixed64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSfixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedSfixed64Iterable(1, [fakeSfixed64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedSfixed64Iterable(1, [fakeSfixed64]); + expectQualifiedIterable(accessor.getRepeatedSfixed64Iterable(1)); + } + }); + + it('fail when adding single packed sfixed64 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSfixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedSfixed64Element(1, fakeSfixed64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedSfixed64Element(1, fakeSfixed64); + expectQualifiedIterable(accessor.getRepeatedSfixed64Iterable(1)); + } + }); + + it('fail when setting packed sfixed64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSfixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedSfixed64Iterable(1, [fakeSfixed64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedSfixed64Iterable(1, [fakeSfixed64]); + expectQualifiedIterable(accessor.getRepeatedSfixed64Iterable(1)); + } + }); + + it('fail when setting single packed sfixed64 value with null value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + const fakeSfixed64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedSfixed64Element(1, 0, fakeSfixed64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedSfixed64Element(1, 0, fakeSfixed64); + expectQualifiedIterable(accessor.getRepeatedSfixed64Iterable(1)); + } + }); + + it('fail when setting single unpacked with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedSfixed64Element(1, 1, Int64.fromInt(1))) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedSfixed64Element(1, 1, Int64.fromInt(1)); + expectQualifiedIterable( + accessor.getRepeatedSfixed64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when setting single packed with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedSfixed64Element(1, 1, Int64.fromInt(1))) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedSfixed64Element(1, 1, Int64.fromInt(1)); + expectQualifiedIterable( + accessor.getRepeatedSfixed64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedSfixed64Element( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedSfixed64Element( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated sint32 does', () => { + const value1 = -1; + const value2 = 0; + + const unpackedValue1Value2 = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const unpackedValue2Value1 = createArrayBuffer(0x08, 0x00, 0x08, 0x01); + + const packedValue1Value2 = createArrayBuffer(0x0A, 0x02, 0x01, 0x00); + const packedValue2Value1 = createArrayBuffer(0x0A, 0x02, 0x00, 0x01); + + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list = accessor.getRepeatedSint32Iterable(1); + + expectEqualToArray(list, []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list1 = accessor.getRepeatedSint32Iterable(1); + const list2 = accessor.getRepeatedSint32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const size = accessor.getRepeatedSint32Size(1); + + expect(size).toEqual(0); + }); + + it('return unpacked values from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list = accessor.getRepeatedSint32Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for unpacked values', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list1 = accessor.getRepeatedSint32Iterable(1); + const list2 = accessor.getRepeatedSint32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSint32Element(1, value1); + const list1 = accessor.getRepeatedSint32Iterable(1); + accessor.addUnpackedSint32Element(1, value2); + const list2 = accessor.getRepeatedSint32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSint32Iterable(1, [value1]); + const list1 = accessor.getRepeatedSint32Iterable(1); + accessor.addUnpackedSint32Iterable(1, [value2]); + const list2 = accessor.getRepeatedSint32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + accessor.setUnpackedSint32Element(1, 1, value1); + const list = accessor.getRepeatedSint32Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedSint32Iterable(1, [value1]); + const list = accessor.getRepeatedSint32Iterable(1); + + expectEqualToArray(list, [value1]); + }); + + it('encode for adding single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSint32Element(1, value1); + accessor.addUnpackedSint32Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for adding unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSint32Iterable(1, [value1]); + accessor.addUnpackedSint32Iterable(1, [value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for setting single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setUnpackedSint32Element(1, 0, value2); + accessor.setUnpackedSint32Element(1, 1, value1); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue2Value1); + }); + + it('encode for setting unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedSint32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('return packed values from the input', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list = accessor.getRepeatedSint32Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for packed values', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list1 = accessor.getRepeatedSint32Iterable(1); + const list2 = accessor.getRepeatedSint32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSint32Element(1, value1); + const list1 = accessor.getRepeatedSint32Iterable(1); + accessor.addPackedSint32Element(1, value2); + const list2 = accessor.getRepeatedSint32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSint32Iterable(1, [value1]); + const list1 = accessor.getRepeatedSint32Iterable(1); + accessor.addPackedSint32Iterable(1, [value2]); + const list2 = accessor.getRepeatedSint32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedSint32Element(1, 1, value1); + const list = accessor.getRepeatedSint32Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedSint32Iterable(1, [value1]); + const list1 = accessor.getRepeatedSint32Iterable(1); + accessor.setPackedSint32Iterable(1, [value2]); + const list2 = accessor.getRepeatedSint32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value2]); + }); + + it('encode for adding single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSint32Element(1, value1); + accessor.addPackedSint32Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for adding packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSint32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for setting single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedSint32Element(1, 0, value2); + accessor.setPackedSint32Element(1, 1, value1); + + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue2Value1); + }); + + it('encode for setting packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedSint32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('return combined values from the input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, + 0x01, // unpacked value1 + 0x0A, + 0x02, + 0x01, + 0x00, // packed value1 and value2 + 0x08, + 0x00, // unpacked value2 + )); + + const list = accessor.getRepeatedSint32Iterable(1); + + expectEqualToArray(list, [value1, value1, value2, value2]); + }); + + it('return the repeated field element from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const result1 = accessor.getRepeatedSint32Element( + /* fieldNumber= */ 1, /* index= */ 0); + const result2 = accessor.getRepeatedSint32Element( + /* fieldNumber= */ 1, /* index= */ 1); + + expect(result1).toEqual(value1); + expect(result2).toEqual(value2); + }); + + it('return the size from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const size = accessor.getRepeatedSint32Size(1); + + expect(size).toEqual(2); + }); + + it('fail when getting unpacked sint32 value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedSint32Iterable(1); + }).toThrowError('Expected wire type: 0 but found: 5'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectQualifiedIterable( + accessor.getRepeatedSint32Iterable(1), + (value) => Number.isInteger(value)); + } + }); + + it('fail when adding unpacked sint32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedSint32Iterable(1, [fakeSint32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedSint32Iterable(1, [fakeSint32]); + expectQualifiedIterable(accessor.getRepeatedSint32Iterable(1)); + } + }); + + it('fail when adding single unpacked sint32 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedSint32Element(1, fakeSint32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedSint32Element(1, fakeSint32); + expectQualifiedIterable(accessor.getRepeatedSint32Iterable(1)); + } + }); + + it('fail when setting unpacked sint32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedSint32Iterable(1, [fakeSint32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedSint32Iterable(1, [fakeSint32]); + expectQualifiedIterable(accessor.getRepeatedSint32Iterable(1)); + } + }); + + it('fail when setting single unpacked sint32 value with null value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x80, 0x80, 0x80, 0x00)); + const fakeSint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedSint32Element(1, 0, fakeSint32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedSint32Element(1, 0, fakeSint32); + expectQualifiedIterable( + accessor.getRepeatedSint32Iterable(1), + ); + } + }); + + it('fail when adding packed sint32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedSint32Iterable(1, [fakeSint32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedSint32Iterable(1, [fakeSint32]); + expectQualifiedIterable(accessor.getRepeatedSint32Iterable(1)); + } + }); + + it('fail when adding single packed sint32 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedSint32Element(1, fakeSint32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedSint32Element(1, fakeSint32); + expectQualifiedIterable(accessor.getRepeatedSint32Iterable(1)); + } + }); + + it('fail when setting packed sint32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedSint32Iterable(1, [fakeSint32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedSint32Iterable(1, [fakeSint32]); + expectQualifiedIterable(accessor.getRepeatedSint32Iterable(1)); + } + }); + + it('fail when setting single packed sint32 value with null value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + const fakeSint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedSint32Element(1, 0, fakeSint32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedSint32Element(1, 0, fakeSint32); + expectQualifiedIterable(accessor.getRepeatedSint32Iterable(1)); + } + }); + + it('fail when setting single unpacked with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedSint32Element(1, 1, 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedSint32Element(1, 1, 1); + expectQualifiedIterable( + accessor.getRepeatedSint32Iterable(1), + (value) => Number.isInteger(value)); + } + }); + + it('fail when setting single packed with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedSint32Element(1, 1, 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedSint32Element(1, 1, 1); + expectQualifiedIterable( + accessor.getRepeatedSint32Iterable(1), + (value) => Number.isInteger(value)); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedSint32Element( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedSint32Element( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated sint64 does', () => { + const value1 = Int64.fromInt(-1); + const value2 = Int64.fromInt(0); + + const unpackedValue1Value2 = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const unpackedValue2Value1 = createArrayBuffer(0x08, 0x00, 0x08, 0x01); + + const packedValue1Value2 = createArrayBuffer(0x0A, 0x02, 0x01, 0x00); + const packedValue2Value1 = createArrayBuffer(0x0A, 0x02, 0x00, 0x01); + + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list = accessor.getRepeatedSint64Iterable(1); + + expectEqualToArray(list, []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list1 = accessor.getRepeatedSint64Iterable(1); + const list2 = accessor.getRepeatedSint64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const size = accessor.getRepeatedSint64Size(1); + + expect(size).toEqual(0); + }); + + it('return unpacked values from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list = accessor.getRepeatedSint64Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for unpacked values', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list1 = accessor.getRepeatedSint64Iterable(1); + const list2 = accessor.getRepeatedSint64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSint64Element(1, value1); + const list1 = accessor.getRepeatedSint64Iterable(1); + accessor.addUnpackedSint64Element(1, value2); + const list2 = accessor.getRepeatedSint64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSint64Iterable(1, [value1]); + const list1 = accessor.getRepeatedSint64Iterable(1); + accessor.addUnpackedSint64Iterable(1, [value2]); + const list2 = accessor.getRepeatedSint64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + accessor.setUnpackedSint64Element(1, 1, value1); + const list = accessor.getRepeatedSint64Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedSint64Iterable(1, [value1]); + const list = accessor.getRepeatedSint64Iterable(1); + + expectEqualToArray(list, [value1]); + }); + + it('encode for adding single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSint64Element(1, value1); + accessor.addUnpackedSint64Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for adding unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedSint64Iterable(1, [value1]); + accessor.addUnpackedSint64Iterable(1, [value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for setting single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setUnpackedSint64Element(1, 0, value2); + accessor.setUnpackedSint64Element(1, 1, value1); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue2Value1); + }); + + it('encode for setting unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedSint64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('return packed values from the input', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list = accessor.getRepeatedSint64Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for packed values', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list1 = accessor.getRepeatedSint64Iterable(1); + const list2 = accessor.getRepeatedSint64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSint64Element(1, value1); + const list1 = accessor.getRepeatedSint64Iterable(1); + accessor.addPackedSint64Element(1, value2); + const list2 = accessor.getRepeatedSint64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSint64Iterable(1, [value1]); + const list1 = accessor.getRepeatedSint64Iterable(1); + accessor.addPackedSint64Iterable(1, [value2]); + const list2 = accessor.getRepeatedSint64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedSint64Element(1, 1, value1); + const list = accessor.getRepeatedSint64Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedSint64Iterable(1, [value1]); + const list1 = accessor.getRepeatedSint64Iterable(1); + accessor.setPackedSint64Iterable(1, [value2]); + const list2 = accessor.getRepeatedSint64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value2]); + }); + + it('encode for adding single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSint64Element(1, value1); + accessor.addPackedSint64Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for adding packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedSint64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for setting single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedSint64Element(1, 0, value2); + accessor.setPackedSint64Element(1, 1, value1); + + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue2Value1); + }); + + it('encode for setting packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedSint64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('return combined values from the input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, + 0x01, // unpacked value1 + 0x0A, + 0x02, + 0x01, + 0x00, // packed value1 and value2 + 0x08, + 0x00, // unpacked value2 + )); + + const list = accessor.getRepeatedSint64Iterable(1); + + expectEqualToArray(list, [value1, value1, value2, value2]); + }); + + it('return the repeated field element from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const result1 = accessor.getRepeatedSint64Element( + /* fieldNumber= */ 1, /* index= */ 0); + const result2 = accessor.getRepeatedSint64Element( + /* fieldNumber= */ 1, /* index= */ 1); + + expect(result1).toEqual(value1); + expect(result2).toEqual(value2); + }); + + it('return the size from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const size = accessor.getRepeatedSint64Size(1); + + expect(size).toEqual(2); + }); + + it('fail when getting unpacked sint64 value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedSint64Iterable(1); + }).toThrowError('Expected wire type: 0 but found: 5'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectQualifiedIterable( + accessor.getRepeatedSint64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when adding unpacked sint64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedSint64Iterable(1, [fakeSint64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedSint64Iterable(1, [fakeSint64]); + expectQualifiedIterable(accessor.getRepeatedSint64Iterable(1)); + } + }); + + it('fail when adding single unpacked sint64 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedSint64Element(1, fakeSint64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedSint64Element(1, fakeSint64); + expectQualifiedIterable(accessor.getRepeatedSint64Iterable(1)); + } + }); + + it('fail when setting unpacked sint64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedSint64Iterable(1, [fakeSint64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedSint64Iterable(1, [fakeSint64]); + expectQualifiedIterable(accessor.getRepeatedSint64Iterable(1)); + } + }); + + it('fail when setting single unpacked sint64 value with null value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x80, 0x80, 0x80, 0x00)); + const fakeSint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedSint64Element(1, 0, fakeSint64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedSint64Element(1, 0, fakeSint64); + expectQualifiedIterable(accessor.getRepeatedSint64Iterable(1)); + } + }); + + it('fail when adding packed sint64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedSint64Iterable(1, [fakeSint64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedSint64Iterable(1, [fakeSint64]); + expectQualifiedIterable(accessor.getRepeatedSint64Iterable(1)); + } + }); + + it('fail when adding single packed sint64 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedSint64Element(1, fakeSint64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedSint64Element(1, fakeSint64); + expectQualifiedIterable(accessor.getRepeatedSint64Iterable(1)); + } + }); + + it('fail when setting packed sint64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeSint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedSint64Iterable(1, [fakeSint64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedSint64Iterable(1, [fakeSint64]); + expectQualifiedIterable(accessor.getRepeatedSint64Iterable(1)); + } + }); + + it('fail when setting single packed sint64 value with null value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + const fakeSint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedSint64Element(1, 0, fakeSint64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedSint64Element(1, 0, fakeSint64); + expectQualifiedIterable(accessor.getRepeatedSint64Iterable(1)); + } + }); + + it('fail when setting single unpacked with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedSint64Element(1, 1, Int64.fromInt(1))) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedSint64Element(1, 1, Int64.fromInt(1)); + expectQualifiedIterable( + accessor.getRepeatedSint64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when setting single packed with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedSint64Element(1, 1, Int64.fromInt(1))) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedSint64Element(1, 1, Int64.fromInt(1)); + expectQualifiedIterable( + accessor.getRepeatedSint64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedSint64Element( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedSint64Element( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated uint32 does', () => { + const value1 = 1; + const value2 = 0; + + const unpackedValue1Value2 = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const unpackedValue2Value1 = createArrayBuffer(0x08, 0x00, 0x08, 0x01); + + const packedValue1Value2 = createArrayBuffer(0x0A, 0x02, 0x01, 0x00); + const packedValue2Value1 = createArrayBuffer(0x0A, 0x02, 0x00, 0x01); + + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list = accessor.getRepeatedUint32Iterable(1); + + expectEqualToArray(list, []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list1 = accessor.getRepeatedUint32Iterable(1); + const list2 = accessor.getRepeatedUint32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const size = accessor.getRepeatedUint32Size(1); + + expect(size).toEqual(0); + }); + + it('return unpacked values from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list = accessor.getRepeatedUint32Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for unpacked values', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list1 = accessor.getRepeatedUint32Iterable(1); + const list2 = accessor.getRepeatedUint32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedUint32Element(1, value1); + const list1 = accessor.getRepeatedUint32Iterable(1); + accessor.addUnpackedUint32Element(1, value2); + const list2 = accessor.getRepeatedUint32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedUint32Iterable(1, [value1]); + const list1 = accessor.getRepeatedUint32Iterable(1); + accessor.addUnpackedUint32Iterable(1, [value2]); + const list2 = accessor.getRepeatedUint32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + accessor.setUnpackedUint32Element(1, 1, value1); + const list = accessor.getRepeatedUint32Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedUint32Iterable(1, [value1]); + const list = accessor.getRepeatedUint32Iterable(1); + + expectEqualToArray(list, [value1]); + }); + + it('encode for adding single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedUint32Element(1, value1); + accessor.addUnpackedUint32Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for adding unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedUint32Iterable(1, [value1]); + accessor.addUnpackedUint32Iterable(1, [value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for setting single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setUnpackedUint32Element(1, 0, value2); + accessor.setUnpackedUint32Element(1, 1, value1); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue2Value1); + }); + + it('encode for setting unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedUint32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('return packed values from the input', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list = accessor.getRepeatedUint32Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for packed values', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list1 = accessor.getRepeatedUint32Iterable(1); + const list2 = accessor.getRepeatedUint32Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedUint32Element(1, value1); + const list1 = accessor.getRepeatedUint32Iterable(1); + accessor.addPackedUint32Element(1, value2); + const list2 = accessor.getRepeatedUint32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedUint32Iterable(1, [value1]); + const list1 = accessor.getRepeatedUint32Iterable(1); + accessor.addPackedUint32Iterable(1, [value2]); + const list2 = accessor.getRepeatedUint32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedUint32Element(1, 1, value1); + const list = accessor.getRepeatedUint32Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedUint32Iterable(1, [value1]); + const list1 = accessor.getRepeatedUint32Iterable(1); + accessor.setPackedUint32Iterable(1, [value2]); + const list2 = accessor.getRepeatedUint32Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value2]); + }); + + it('encode for adding single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedUint32Element(1, value1); + accessor.addPackedUint32Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for adding packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedUint32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for setting single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedUint32Element(1, 0, value2); + accessor.setPackedUint32Element(1, 1, value1); + + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue2Value1); + }); + + it('encode for setting packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedUint32Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('return combined values from the input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, + 0x01, // unpacked value1 + 0x0A, + 0x02, + 0x01, + 0x00, // packed value1 and value2 + 0x08, + 0x00, // unpacked value2 + )); + + const list = accessor.getRepeatedUint32Iterable(1); + + expectEqualToArray(list, [value1, value1, value2, value2]); + }); + + it('return the repeated field element from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const result1 = accessor.getRepeatedUint32Element( + /* fieldNumber= */ 1, /* index= */ 0); + const result2 = accessor.getRepeatedUint32Element( + /* fieldNumber= */ 1, /* index= */ 1); + + expect(result1).toEqual(value1); + expect(result2).toEqual(value2); + }); + + it('return the size from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const size = accessor.getRepeatedUint32Size(1); + + expect(size).toEqual(2); + }); + + it('fail when getting unpacked uint32 value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedUint32Iterable(1); + }).toThrowError('Expected wire type: 0 but found: 5'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectQualifiedIterable( + accessor.getRepeatedUint32Iterable(1), + (value) => Number.isInteger(value)); + } + }); + + it('fail when adding unpacked uint32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeUint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedUint32Iterable(1, [fakeUint32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedUint32Iterable(1, [fakeUint32]); + expectQualifiedIterable(accessor.getRepeatedUint32Iterable(1)); + } + }); + + it('fail when adding single unpacked uint32 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeUint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedUint32Element(1, fakeUint32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedUint32Element(1, fakeUint32); + expectQualifiedIterable(accessor.getRepeatedUint32Iterable(1)); + } + }); + + it('fail when setting unpacked uint32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeUint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedUint32Iterable(1, [fakeUint32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedUint32Iterable(1, [fakeUint32]); + expectQualifiedIterable(accessor.getRepeatedUint32Iterable(1)); + } + }); + + it('fail when setting single unpacked uint32 value with null value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x80, 0x80, 0x80, 0x00)); + const fakeUint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedUint32Element(1, 0, fakeUint32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedUint32Element(1, 0, fakeUint32); + expectQualifiedIterable( + accessor.getRepeatedUint32Iterable(1), + ); + } + }); + + it('fail when adding packed uint32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeUint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedUint32Iterable(1, [fakeUint32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedUint32Iterable(1, [fakeUint32]); + expectQualifiedIterable(accessor.getRepeatedUint32Iterable(1)); + } + }); + + it('fail when adding single packed uint32 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeUint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedUint32Element(1, fakeUint32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedUint32Element(1, fakeUint32); + expectQualifiedIterable(accessor.getRepeatedUint32Iterable(1)); + } + }); + + it('fail when setting packed uint32 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeUint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedUint32Iterable(1, [fakeUint32])) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedUint32Iterable(1, [fakeUint32]); + expectQualifiedIterable(accessor.getRepeatedUint32Iterable(1)); + } + }); + + it('fail when setting single packed uint32 value with null value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + const fakeUint32 = /** @type {number} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedUint32Element(1, 0, fakeUint32)) + .toThrowError('Must be a number, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedUint32Element(1, 0, fakeUint32); + expectQualifiedIterable(accessor.getRepeatedUint32Iterable(1)); + } + }); + + it('fail when setting single unpacked with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedUint32Element(1, 1, 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedUint32Element(1, 1, 1); + expectQualifiedIterable( + accessor.getRepeatedUint32Iterable(1), + (value) => Number.isInteger(value)); + } + }); + + it('fail when setting single packed with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedUint32Element(1, 1, 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedUint32Element(1, 1, 1); + expectQualifiedIterable( + accessor.getRepeatedUint32Iterable(1), + (value) => Number.isInteger(value)); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedUint32Element( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedUint32Element( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated uint64 does', () => { + const value1 = Int64.fromInt(1); + const value2 = Int64.fromInt(0); + + const unpackedValue1Value2 = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const unpackedValue2Value1 = createArrayBuffer(0x08, 0x00, 0x08, 0x01); + + const packedValue1Value2 = createArrayBuffer(0x0A, 0x02, 0x01, 0x00); + const packedValue2Value1 = createArrayBuffer(0x0A, 0x02, 0x00, 0x01); + + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list = accessor.getRepeatedUint64Iterable(1); + + expectEqualToArray(list, []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list1 = accessor.getRepeatedUint64Iterable(1); + const list2 = accessor.getRepeatedUint64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const size = accessor.getRepeatedUint64Size(1); + + expect(size).toEqual(0); + }); + + it('return unpacked values from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list = accessor.getRepeatedUint64Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for unpacked values', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const list1 = accessor.getRepeatedUint64Iterable(1); + const list2 = accessor.getRepeatedUint64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedUint64Element(1, value1); + const list1 = accessor.getRepeatedUint64Iterable(1); + accessor.addUnpackedUint64Element(1, value2); + const list2 = accessor.getRepeatedUint64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedUint64Iterable(1, [value1]); + const list1 = accessor.getRepeatedUint64Iterable(1); + accessor.addUnpackedUint64Iterable(1, [value2]); + const list2 = accessor.getRepeatedUint64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + accessor.setUnpackedUint64Element(1, 1, value1); + const list = accessor.getRepeatedUint64Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedUint64Iterable(1, [value1]); + const list = accessor.getRepeatedUint64Iterable(1); + + expectEqualToArray(list, [value1]); + }); + + it('encode for adding single unpacked value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedUint64Element(1, value1); + accessor.addUnpackedUint64Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for adding unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedUint64Iterable(1, [value1]); + accessor.addUnpackedUint64Iterable(1, [value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('encode for setting single unpacked value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setUnpackedUint64Element(1, 0, value2); + accessor.setUnpackedUint64Element(1, 1, value1); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue2Value1); + }); + + it('encode for setting unpacked values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setUnpackedUint64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(unpackedValue1Value2); + }); + + it('return packed values from the input', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list = accessor.getRepeatedUint64Iterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for packed values', () => { + const accessor = Kernel.fromArrayBuffer(packedValue1Value2); + + const list1 = accessor.getRepeatedUint64Iterable(1); + const list2 = accessor.getRepeatedUint64Iterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedUint64Element(1, value1); + const list1 = accessor.getRepeatedUint64Iterable(1); + accessor.addPackedUint64Element(1, value2); + const list2 = accessor.getRepeatedUint64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedUint64Iterable(1, [value1]); + const list1 = accessor.getRepeatedUint64Iterable(1); + accessor.addPackedUint64Iterable(1, [value2]); + const list2 = accessor.getRepeatedUint64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedUint64Element(1, 1, value1); + const list = accessor.getRepeatedUint64Iterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedUint64Iterable(1, [value1]); + const list1 = accessor.getRepeatedUint64Iterable(1); + accessor.setPackedUint64Iterable(1, [value2]); + const list2 = accessor.getRepeatedUint64Iterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value2]); + }); + + it('encode for adding single packed value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedUint64Element(1, value1); + accessor.addPackedUint64Element(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for adding packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addPackedUint64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('encode for setting single packed value', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + accessor.setPackedUint64Element(1, 0, value2); + accessor.setPackedUint64Element(1, 1, value1); + + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue2Value1); + }); + + it('encode for setting packed values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setPackedUint64Iterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(packedValue1Value2); + }); + + it('return combined values from the input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, + 0x01, // unpacked value1 + 0x0A, + 0x02, + 0x01, + 0x00, // packed value1 and value2 + 0x08, + 0x00, // unpacked value2 + )); + + const list = accessor.getRepeatedUint64Iterable(1); + + expectEqualToArray(list, [value1, value1, value2, value2]); + }); + + it('return the repeated field element from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const result1 = accessor.getRepeatedUint64Element( + /* fieldNumber= */ 1, /* index= */ 0); + const result2 = accessor.getRepeatedUint64Element( + /* fieldNumber= */ 1, /* index= */ 1); + + expect(result1).toEqual(value1); + expect(result2).toEqual(value2); + }); + + it('return the size from the input', () => { + const accessor = Kernel.fromArrayBuffer(unpackedValue1Value2); + + const size = accessor.getRepeatedUint64Size(1); + + expect(size).toEqual(2); + }); + + it('fail when getting unpacked uint64 value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedUint64Iterable(1); + }).toThrowError('Expected wire type: 0 but found: 5'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectQualifiedIterable( + accessor.getRepeatedUint64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when adding unpacked uint64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeUint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedUint64Iterable(1, [fakeUint64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedUint64Iterable(1, [fakeUint64]); + expectQualifiedIterable(accessor.getRepeatedUint64Iterable(1)); + } + }); + + it('fail when adding single unpacked uint64 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeUint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addUnpackedUint64Element(1, fakeUint64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addUnpackedUint64Element(1, fakeUint64); + expectQualifiedIterable(accessor.getRepeatedUint64Iterable(1)); + } + }); + + it('fail when setting unpacked uint64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeUint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedUint64Iterable(1, [fakeUint64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedUint64Iterable(1, [fakeUint64]); + expectQualifiedIterable(accessor.getRepeatedUint64Iterable(1)); + } + }); + + it('fail when setting single unpacked uint64 value with null value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x80, 0x80, 0x80, 0x00)); + const fakeUint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedUint64Element(1, 0, fakeUint64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedUint64Element(1, 0, fakeUint64); + expectQualifiedIterable(accessor.getRepeatedUint64Iterable(1)); + } + }); + + it('fail when adding packed uint64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeUint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedUint64Iterable(1, [fakeUint64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedUint64Iterable(1, [fakeUint64]); + expectQualifiedIterable(accessor.getRepeatedUint64Iterable(1)); + } + }); + + it('fail when adding single packed uint64 value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeUint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addPackedUint64Element(1, fakeUint64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addPackedUint64Element(1, fakeUint64); + expectQualifiedIterable(accessor.getRepeatedUint64Iterable(1)); + } + }); + + it('fail when setting packed uint64 values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeUint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedUint64Iterable(1, [fakeUint64])) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedUint64Iterable(1, [fakeUint64]); + expectQualifiedIterable(accessor.getRepeatedUint64Iterable(1)); + } + }); + + it('fail when setting single packed uint64 value with null value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + const fakeUint64 = /** @type {!Int64} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedUint64Element(1, 0, fakeUint64)) + .toThrowError('Must be Int64 instance, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedUint64Element(1, 0, fakeUint64); + expectQualifiedIterable(accessor.getRepeatedUint64Iterable(1)); + } + }); + + it('fail when setting single unpacked with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setUnpackedUint64Element(1, 1, Int64.fromInt(1))) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setUnpackedUint64Element(1, 1, Int64.fromInt(1)); + expectQualifiedIterable( + accessor.getRepeatedUint64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when setting single packed with out-of-bound index', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setPackedUint64Element(1, 1, Int64.fromInt(1))) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setPackedUint64Element(1, 1, Int64.fromInt(1)); + expectQualifiedIterable( + accessor.getRepeatedUint64Iterable(1), + (value) => value instanceof Int64); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedUint64Element( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedUint64Element( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated bytes does', () => { + const value1 = ByteString.fromArrayBuffer((createArrayBuffer(0x61))); + const value2 = ByteString.fromArrayBuffer((createArrayBuffer(0x62))); + + const repeatedValue1Value2 = createArrayBuffer( + 0x0A, + 0x01, + 0x61, // value1 + 0x0A, + 0x01, + 0x62, // value2 + ); + const repeatedValue2Value1 = createArrayBuffer( + 0x0A, + 0x01, + 0x62, // value2 + 0x0A, + 0x01, + 0x61, // value1 + ); + + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list = accessor.getRepeatedBytesIterable(1); + + expectEqualToArray(list, []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list1 = accessor.getRepeatedBytesIterable(1); + const list2 = accessor.getRepeatedBytesIterable(1); + + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const size = accessor.getRepeatedBytesSize(1); + + expect(size).toEqual(0); + }); + + it('return values from the input', () => { + const accessor = Kernel.fromArrayBuffer(repeatedValue1Value2); + + const list = accessor.getRepeatedBytesIterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for values', () => { + const accessor = Kernel.fromArrayBuffer(repeatedValue1Value2); + + const list1 = accessor.getRepeatedBytesIterable(1); + const list2 = accessor.getRepeatedBytesIterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addRepeatedBytesElement(1, value1); + const list1 = accessor.getRepeatedBytesIterable(1); + accessor.addRepeatedBytesElement(1, value2); + const list2 = accessor.getRepeatedBytesIterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addRepeatedBytesIterable(1, [value1]); + const list1 = accessor.getRepeatedBytesIterable(1); + accessor.addRepeatedBytesIterable(1, [value2]); + const list2 = accessor.getRepeatedBytesIterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single value', () => { + const accessor = Kernel.fromArrayBuffer(repeatedValue1Value2); + + accessor.setRepeatedBytesElement(1, 1, value1); + const list = accessor.getRepeatedBytesIterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setRepeatedBytesIterable(1, [value1]); + const list = accessor.getRepeatedBytesIterable(1); + + expectEqualToArray(list, [value1]); + }); + + it('encode for adding single value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addRepeatedBytesElement(1, value1); + accessor.addRepeatedBytesElement(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(repeatedValue1Value2); + }); + + it('encode for adding values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addRepeatedBytesIterable(1, [value1]); + accessor.addRepeatedBytesIterable(1, [value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(repeatedValue1Value2); + }); + + it('encode for setting single value', () => { + const accessor = Kernel.fromArrayBuffer(repeatedValue1Value2); + + accessor.setRepeatedBytesElement(1, 0, value2); + accessor.setRepeatedBytesElement(1, 1, value1); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(repeatedValue2Value1); + }); + + it('encode for setting values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setRepeatedBytesIterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(repeatedValue1Value2); + }); + + it('return the repeated field element from the input', () => { + const accessor = Kernel.fromArrayBuffer(repeatedValue1Value2); + + const result1 = accessor.getRepeatedBytesElement( + /* fieldNumber= */ 1, /* index= */ 0); + const result2 = accessor.getRepeatedBytesElement( + /* fieldNumber= */ 1, /* index= */ 1); + + expect(result1).toEqual(value1); + expect(result2).toEqual(value2); + }); + + it('return the size from the input', () => { + const accessor = Kernel.fromArrayBuffer(repeatedValue1Value2); + + const size = accessor.getRepeatedBytesSize(1); + + expect(size).toEqual(2); + }); + + it('fail when getting bytes value with other wire types', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedBytesIterable(1); + }).toThrowError('Expected wire type: 2 but found: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectQualifiedIterable( + accessor.getRepeatedBytesIterable(1), + (value) => value instanceof ByteString); + } + }); + + it('fail when adding bytes values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeBytes = /** @type {!ByteString} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addRepeatedBytesIterable(1, [fakeBytes])) + .toThrowError('Must be a ByteString, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addRepeatedBytesIterable(1, [fakeBytes]); + expectQualifiedIterable(accessor.getRepeatedBytesIterable(1)); + } + }); + + it('fail when adding single bytes value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeBytes = /** @type {!ByteString} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addRepeatedBytesElement(1, fakeBytes)) + .toThrowError('Must be a ByteString, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addRepeatedBytesElement(1, fakeBytes); + expectQualifiedIterable(accessor.getRepeatedBytesIterable(1)); + } + }); + + it('fail when setting bytes values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeBytes = /** @type {!ByteString} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setRepeatedBytesIterable(1, [fakeBytes])) + .toThrowError('Must be a ByteString, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setRepeatedBytesIterable(1, [fakeBytes]); + expectQualifiedIterable(accessor.getRepeatedBytesIterable(1)); + } + }); + + it('fail when setting single bytes value with null value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00)); + const fakeBytes = /** @type {!ByteString} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setRepeatedBytesElement(1, 0, fakeBytes)) + .toThrowError('Must be a ByteString, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setRepeatedBytesElement(1, 0, fakeBytes); + expectQualifiedIterable(accessor.getRepeatedBytesIterable(1)); + } + }); + + it('fail when setting single with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x61)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setRepeatedBytesElement(1, 1, value1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setRepeatedBytesElement(1, 1, value1); + expectQualifiedIterable( + accessor.getRepeatedBytesIterable(1), + (value) => value instanceof ByteString); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedBytesElement( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedBytesElement( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated string does', () => { + const value1 = 'a'; + const value2 = 'b'; + + const repeatedValue1Value2 = createArrayBuffer( + 0x0A, + 0x01, + 0x61, // value1 + 0x0A, + 0x01, + 0x62, // value2 + ); + const repeatedValue2Value1 = createArrayBuffer( + 0x0A, + 0x01, + 0x62, // value2 + 0x0A, + 0x01, + 0x61, // value1 + ); + + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list = accessor.getRepeatedStringIterable(1); + + expectEqualToArray(list, []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const list1 = accessor.getRepeatedStringIterable(1); + const list2 = accessor.getRepeatedStringIterable(1); + + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + + const size = accessor.getRepeatedStringSize(1); + + expect(size).toEqual(0); + }); + + it('return values from the input', () => { + const accessor = Kernel.fromArrayBuffer(repeatedValue1Value2); + + const list = accessor.getRepeatedStringIterable(1); + + expectEqualToArray(list, [value1, value2]); + }); + + it('ensure not the same instance returned for values', () => { + const accessor = Kernel.fromArrayBuffer(repeatedValue1Value2); + + const list1 = accessor.getRepeatedStringIterable(1); + const list2 = accessor.getRepeatedStringIterable(1); + + expect(list1).not.toBe(list2); + }); + + it('add single value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addRepeatedStringElement(1, value1); + const list1 = accessor.getRepeatedStringIterable(1); + accessor.addRepeatedStringElement(1, value2); + const list2 = accessor.getRepeatedStringIterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('add values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addRepeatedStringIterable(1, [value1]); + const list1 = accessor.getRepeatedStringIterable(1); + accessor.addRepeatedStringIterable(1, [value2]); + const list2 = accessor.getRepeatedStringIterable(1); + + expectEqualToArray(list1, [value1]); + expectEqualToArray(list2, [value1, value2]); + }); + + it('set a single value', () => { + const accessor = Kernel.fromArrayBuffer(repeatedValue1Value2); + + accessor.setRepeatedStringElement(1, 1, value1); + const list = accessor.getRepeatedStringIterable(1); + + expectEqualToArray(list, [value1, value1]); + }); + + it('set values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setRepeatedStringIterable(1, [value1]); + const list = accessor.getRepeatedStringIterable(1); + + expectEqualToArray(list, [value1]); + }); + + it('encode for adding single value', () => { + const accessor = Kernel.createEmpty(); + + accessor.addRepeatedStringElement(1, value1); + accessor.addRepeatedStringElement(1, value2); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(repeatedValue1Value2); + }); + + it('encode for adding values', () => { + const accessor = Kernel.createEmpty(); + + accessor.addRepeatedStringIterable(1, [value1]); + accessor.addRepeatedStringIterable(1, [value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(repeatedValue1Value2); + }); + + it('encode for setting single value', () => { + const accessor = Kernel.fromArrayBuffer(repeatedValue1Value2); + + accessor.setRepeatedStringElement(1, 0, value2); + accessor.setRepeatedStringElement(1, 1, value1); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(repeatedValue2Value1); + }); + + it('encode for setting values', () => { + const accessor = Kernel.createEmpty(); + + accessor.setRepeatedStringIterable(1, [value1, value2]); + const serialized = accessor.serialize(); + + expect(serialized).toEqual(repeatedValue1Value2); + }); + + it('return the repeated field element from the input', () => { + const accessor = Kernel.fromArrayBuffer(repeatedValue1Value2); + + const result1 = accessor.getRepeatedStringElement( + /* fieldNumber= */ 1, /* index= */ 0); + const result2 = accessor.getRepeatedStringElement( + /* fieldNumber= */ 1, /* index= */ 1); + + expect(result1).toEqual(value1); + expect(result2).toEqual(value2); + }); + + it('return the size from the input', () => { + const accessor = Kernel.fromArrayBuffer(repeatedValue1Value2); + + const size = accessor.getRepeatedStringSize(1); + + expect(size).toEqual(2); + }); + + it('fail when getting string value with other wire types', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedStringIterable(1); + }).toThrowError('Expected wire type: 2 but found: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expectQualifiedIterable( + accessor.getRepeatedStringIterable(1), + (value) => typeof value === 'string'); + } + }); + + it('fail when adding string values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeString = /** @type {string} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addRepeatedStringIterable(1, [fakeString])) + .toThrowError('Must be string, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addRepeatedStringIterable(1, [fakeString]); + expectQualifiedIterable(accessor.getRepeatedStringIterable(1)); + } + }); + + it('fail when adding single string value with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeString = /** @type {string} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.addRepeatedStringElement(1, fakeString)) + .toThrowError('Must be string, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addRepeatedStringElement(1, fakeString); + expectQualifiedIterable(accessor.getRepeatedStringIterable(1)); + } + }); + + it('fail when setting string values with null value', () => { + const accessor = Kernel.createEmpty(); + const fakeString = /** @type {string} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setRepeatedStringIterable(1, [fakeString])) + .toThrowError('Must be string, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setRepeatedStringIterable(1, [fakeString]); + expectQualifiedIterable(accessor.getRepeatedStringIterable(1)); + } + }); + + it('fail when setting single string value with null value', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00)); + const fakeString = /** @type {string} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setRepeatedStringElement(1, 0, fakeString)) + .toThrowError('Must be string, but got: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setRepeatedStringElement(1, 0, fakeString); + expectQualifiedIterable(accessor.getRepeatedStringIterable(1)); + } + }); + + it('fail when setting single with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x61)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setRepeatedStringElement(1, 1, value1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setRepeatedStringElement(1, 1, value1); + expectQualifiedIterable( + accessor.getRepeatedStringIterable(1), + (value) => typeof value === 'string'); + } + }); + + it('fail when getting element with out-of-range index', () => { + const accessor = Kernel.createEmpty(); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedStringElement( + /* fieldNumber= */ 1, /* index= */ 0); + }).toThrowError('Index out of bounds: index: 0 size: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getRepeatedStringElement( + /* fieldNumber= */ 1, /* index= */ 0)) + .toBe(undefined); + } + }); +}); + +describe('Kernel for repeated message does', () => { + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + expectEqualToArray( + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator), + []); + }); + + it('return empty accessor array for the empty input', () => { + const accessor = Kernel.createEmpty(); + expectEqualToArray(accessor.getRepeatedMessageAccessorIterable(1), []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + const list1 = + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + const list2 = + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + expect(accessor.getRepeatedMessageSize(1, TestMessage.instanceCreator)) + .toEqual(0); + }); + + it('return values from the input', () => { + const bytes1 = createArrayBuffer(0x08, 0x01); + const bytes2 = createArrayBuffer(0x08, 0x00); + const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1)); + const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2)); + + const bytes = + createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expectEqualToMessageArray( + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator), + [msg1, msg2]); + }); + + it('ensure not the same array instance returned', () => { + const bytes = + createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const list1 = + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + const list2 = + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + expect(list1).not.toBe(list2); + }); + + it('ensure the same array element returned for get iterable', () => { + const bytes = + createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const list1 = + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + const list2 = accessor.getRepeatedMessageIterable( + 1, TestMessage.instanceCreator, /* pivot= */ 0); + const array1 = Array.from(list1); + const array2 = Array.from(list2); + for (let i = 0; i < array1.length; i++) { + expect(array1[i]).toBe(array2[i]); + } + }); + + it('return accessors from the input', () => { + const bytes = + createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const [accessor1, accessor2] = + [...accessor.getRepeatedMessageAccessorIterable(1)]; + expect(accessor1.getInt32WithDefault(1)).toEqual(1); + expect(accessor2.getInt32WithDefault(1)).toEqual(0); + }); + + it('return accessors from the input when pivot is set', () => { + const bytes = + createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const [accessor1, accessor2] = + [...accessor.getRepeatedMessageAccessorIterable(1, /* pivot= */ 0)]; + expect(accessor1.getInt32WithDefault(1)).toEqual(1); + expect(accessor2.getInt32WithDefault(1)).toEqual(0); + }); + + it('return the repeated field element from the input', () => { + const bytes = + createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const msg1 = accessor.getRepeatedMessageElement( + /* fieldNumber= */ 1, TestMessage.instanceCreator, + /* index= */ 0); + const msg2 = accessor.getRepeatedMessageElement( + /* fieldNumber= */ 1, TestMessage.instanceCreator, + /* index= */ 1, /* pivot= */ 0); + expect(msg1.getBoolWithDefault( + /* fieldNumber= */ 1, /* default= */ false)) + .toEqual(true); + expect(msg2.getBoolWithDefault( + /* fieldNumber= */ 1, /* default= */ false)) + .toEqual(false); + }); + + it('ensure the same array element returned', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + const msg1 = accessor.getRepeatedMessageElement( + /* fieldNumber= */ 1, TestMessage.instanceCreator, + /* index= */ 0); + const msg2 = accessor.getRepeatedMessageElement( + /* fieldNumber= */ 1, TestMessage.instanceCreator, + /* index= */ 0); + expect(msg1).toBe(msg2); + }); + + it('return the size from the input', () => { + const bytes = + createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getRepeatedMessageSize(1, TestMessage.instanceCreator)) + .toEqual(2); + }); + + it('encode repeated message from the input', () => { + const bytes = + createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('add a single value', () => { + const accessor = Kernel.createEmpty(); + const bytes1 = createArrayBuffer(0x08, 0x01); + const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1)); + const bytes2 = createArrayBuffer(0x08, 0x00); + const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2)); + + accessor.addRepeatedMessageElement(1, msg1, TestMessage.instanceCreator); + accessor.addRepeatedMessageElement(1, msg2, TestMessage.instanceCreator); + const result = + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + + expect(Array.from(result)).toEqual([msg1, msg2]); + }); + + it('add values', () => { + const accessor = Kernel.createEmpty(); + const bytes1 = createArrayBuffer(0x08, 0x01); + const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1)); + const bytes2 = createArrayBuffer(0x08, 0x00); + const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2)); + + accessor.addRepeatedMessageIterable(1, [msg1], TestMessage.instanceCreator); + accessor.addRepeatedMessageIterable(1, [msg2], TestMessage.instanceCreator); + const result = + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + + expect(Array.from(result)).toEqual([msg1, msg2]); + }); + + it('set a single value', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const subbytes = createArrayBuffer(0x08, 0x01); + const submsg = new TestMessage(Kernel.fromArrayBuffer(subbytes)); + + accessor.setRepeatedMessageElement( + /* fieldNumber= */ 1, submsg, TestMessage.instanceCreator, + /* index= */ 0); + const result = + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + + expect(Array.from(result)).toEqual([submsg]); + }); + + it('write submessage changes made via getRepeatedMessagElement', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x05); + const expected = createArrayBuffer(0x0A, 0x02, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const submsg = accessor.getRepeatedMessageElement( + /* fieldNumber= */ 1, TestMessage.instanceCreator, + /* index= */ 0); + expect(submsg.getInt32WithDefault(1, 0)).toEqual(5); + submsg.setInt32(1, 0); + + expect(accessor.serialize()).toEqual(expected); + }); + + it('set values', () => { + const accessor = Kernel.createEmpty(); + const subbytes = createArrayBuffer(0x08, 0x01); + const submsg = new TestMessage(Kernel.fromArrayBuffer(subbytes)); + + accessor.setRepeatedMessageIterable(1, [submsg]); + const result = + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + + expect(Array.from(result)).toEqual([submsg]); + }); + + it('encode for adding single value', () => { + const accessor = Kernel.createEmpty(); + const bytes1 = createArrayBuffer(0x08, 0x01); + const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1)); + const bytes2 = createArrayBuffer(0x08, 0x00); + const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2)); + const expected = + createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x08, 0x00); + + accessor.addRepeatedMessageElement(1, msg1, TestMessage.instanceCreator); + accessor.addRepeatedMessageElement(1, msg2, TestMessage.instanceCreator); + const result = accessor.serialize(); + + expect(result).toEqual(expected); + }); + + it('encode for adding values', () => { + const accessor = Kernel.createEmpty(); + const bytes1 = createArrayBuffer(0x08, 0x01); + const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1)); + const bytes2 = createArrayBuffer(0x08, 0x00); + const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2)); + const expected = + createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x08, 0x00); + + accessor.addRepeatedMessageIterable( + 1, [msg1, msg2], TestMessage.instanceCreator); + const result = accessor.serialize(); + + expect(result).toEqual(expected); + }); + + it('encode for setting single value', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const subbytes = createArrayBuffer(0x08, 0x01); + const submsg = new TestMessage(Kernel.fromArrayBuffer(subbytes)); + const expected = createArrayBuffer(0x0A, 0x02, 0x08, 0x01); + + accessor.setRepeatedMessageElement( + /* fieldNumber= */ 1, submsg, TestMessage.instanceCreator, + /* index= */ 0); + const result = accessor.serialize(); + + expect(result).toEqual(expected); + }); + + it('encode for setting values', () => { + const accessor = Kernel.createEmpty(); + const subbytes = createArrayBuffer(0x08, 0x01); + const submsg = new TestMessage(Kernel.fromArrayBuffer(subbytes)); + const expected = createArrayBuffer(0x0A, 0x02, 0x08, 0x01); + + accessor.setRepeatedMessageIterable(1, [submsg]); + const result = accessor.serialize(); + + expect(result).toEqual(expected); + }); + + it('get accessors from set values.', () => { + const accessor = Kernel.createEmpty(); + const bytes1 = createArrayBuffer(0x08, 0x01); + const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1)); + const bytes2 = createArrayBuffer(0x08, 0x00); + const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2)); + + accessor.addRepeatedMessageIterable( + 1, [msg1, msg2], TestMessage.instanceCreator); + + const [accessor1, accessor2] = + [...accessor.getRepeatedMessageAccessorIterable(1)]; + expect(accessor1.getInt32WithDefault(1)).toEqual(1); + expect(accessor2.getInt32WithDefault(1)).toEqual(0); + + // Retrieved accessors are the exact same accessors as the added messages. + expect(accessor1).toBe( + (/** @type {!InternalMessage} */ (msg1)).internalGetKernel()); + expect(accessor2).toBe( + (/** @type {!InternalMessage} */ (msg2)).internalGetKernel()); + }); + + it('fail when getting message value with other wire types', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + }).toThrow(); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + const [msg1] = + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + expect(msg1.serialize()).toEqual(createArrayBuffer()); + } + }); + + it('fail when adding message values with wrong type value', () => { + const accessor = Kernel.createEmpty(); + const fakeValue = /** @type {!TestMessage} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect( + () => accessor.addRepeatedMessageIterable( + 1, [fakeValue], TestMessage.instanceCreator)) + .toThrowError('Given value is not a message instance: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addRepeatedMessageIterable( + 1, [fakeValue], TestMessage.instanceCreator); + const list = + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + expect(Array.from(list)).toEqual([null]); + } + }); + + it('fail when adding single message value with wrong type value', () => { + const accessor = Kernel.createEmpty(); + const fakeValue = /** @type {!TestMessage} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect( + () => accessor.addRepeatedMessageElement( + 1, fakeValue, TestMessage.instanceCreator)) + .toThrowError('Given value is not a message instance: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addRepeatedMessageElement( + 1, fakeValue, TestMessage.instanceCreator); + const list = + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + expect(Array.from(list)).toEqual([null]); + } + }); + + it('fail when setting message values with wrong type value', () => { + const accessor = Kernel.createEmpty(); + const fakeValue = /** @type {!TestMessage} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setRepeatedMessageIterable(1, [fakeValue])) + .toThrowError('Given value is not a message instance: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setRepeatedMessageIterable(1, [fakeValue]); + const list = + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + expect(Array.from(list)).toEqual([null]); + } + }); + + it('fail when setting single value with wrong type value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x02, 0x08, 0x00)); + const fakeValue = /** @type {!TestMessage} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect( + () => accessor.setRepeatedMessageElement( + /* fieldNumber= */ 1, fakeValue, TestMessage.instanceCreator, + /* index= */ 0)) + .toThrowError('Given value is not a message instance: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setRepeatedMessageElement( + /* fieldNumber= */ 1, fakeValue, TestMessage.instanceCreator, + /* index= */ 0); + const list = + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator); + expect(Array.from(list).length).toEqual(1); + } + }); + + it('fail when setting single value with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x02, 0x08, 0x00)); + const msg1 = + accessor.getRepeatedMessageElement(1, TestMessage.instanceCreator, 0); + const bytes2 = createArrayBuffer(0x08, 0x01); + const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2)); + if (CHECK_CRITICAL_STATE) { + expect( + () => accessor.setRepeatedMessageElement( + /* fieldNumber= */ 1, msg2, TestMessage.instanceCreator, + /* index= */ 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setRepeatedMessageElement( + /* fieldNumber= */ 1, msg2, TestMessage.instanceCreator, + /* index= */ 1); + expectEqualToArray( + accessor.getRepeatedMessageIterable(1, TestMessage.instanceCreator), + [msg1, msg2]); + } + }); +}); + +describe('Kernel for repeated groups does', () => { + it('return empty array for the empty input', () => { + const accessor = Kernel.createEmpty(); + expectEqualToArray( + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator), []); + }); + + it('ensure not the same instance returned for the empty input', () => { + const accessor = Kernel.createEmpty(); + const list1 = + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator); + const list2 = + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator); + expect(list1).not.toBe(list2); + }); + + it('return size for the empty input', () => { + const accessor = Kernel.createEmpty(); + expect(accessor.getRepeatedGroupSize(1, TestMessage.instanceCreator)) + .toEqual(0); + }); + + it('return values from the input', () => { + const bytes1 = createArrayBuffer(0x08, 0x01); + const bytes2 = createArrayBuffer(0x08, 0x02); + const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1)); + const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2)); + + const bytes = + createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + expectEqualToMessageArray( + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator), + [msg1, msg2]); + }); + + it('ensure not the same array instance returned', () => { + const bytes = + createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + const list1 = + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator); + const list2 = + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator); + expect(list1).not.toBe(list2); + }); + + it('ensure the same array element returned for get iterable', () => { + const bytes = + createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + const list1 = + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator); + const list2 = accessor.getRepeatedGroupIterable( + 1, TestMessage.instanceCreator, /* pivot= */ 0); + const array1 = Array.from(list1); + const array2 = Array.from(list2); + for (let i = 0; i < array1.length; i++) { + expect(array1[i]).toBe(array2[i]); + } + }); + + it('return accessors from the input', () => { + const bytes = + createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + const [accessor1, accessor2] = + [...accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator)]; + expect(accessor1.getInt32WithDefault(1)).toEqual(1); + expect(accessor2.getInt32WithDefault(1)).toEqual(2); + }); + + it('return accessors from the input when pivot is set', () => { + const bytes = + createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + const [accessor1, accessor2] = [...accessor.getRepeatedGroupIterable( + 1, TestMessage.instanceCreator, /* pivot= */ 0)]; + expect(accessor1.getInt32WithDefault(1)).toEqual(1); + expect(accessor2.getInt32WithDefault(1)).toEqual(2); + }); + + it('return the repeated field element from the input', () => { + const bytes = + createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + const msg1 = accessor.getRepeatedGroupElement( + /* fieldNumber= */ 1, TestMessage.instanceCreator, + /* index= */ 0); + const msg2 = accessor.getRepeatedGroupElement( + /* fieldNumber= */ 1, TestMessage.instanceCreator, + /* index= */ 1, /* pivot= */ 0); + expect(msg1.getInt32WithDefault( + /* fieldNumber= */ 1, /* default= */ 0)) + .toEqual(1); + expect(msg2.getInt32WithDefault( + /* fieldNumber= */ 1, /* default= */ 0)) + .toEqual(2); + }); + + it('ensure the same array element returned', () => { + const bytes = + createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + const msg1 = accessor.getRepeatedGroupElement( + /* fieldNumber= */ 1, TestMessage.instanceCreator, + /* index= */ 0); + const msg2 = accessor.getRepeatedGroupElement( + /* fieldNumber= */ 1, TestMessage.instanceCreator, + /* index= */ 0); + expect(msg1).toBe(msg2); + }); + + it('return the size from the input', () => { + const bytes = + createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getRepeatedGroupSize(1, TestMessage.instanceCreator)) + .toEqual(2); + }); + + it('encode repeated message from the input', () => { + const bytes = + createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('add a single value', () => { + const accessor = Kernel.createEmpty(); + const bytes1 = createArrayBuffer(0x08, 0x01); + const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1)); + const bytes2 = createArrayBuffer(0x08, 0x02); + const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2)); + + accessor.addRepeatedGroupElement(1, msg1, TestMessage.instanceCreator); + accessor.addRepeatedGroupElement(1, msg2, TestMessage.instanceCreator); + const result = + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator); + + expect(Array.from(result)).toEqual([msg1, msg2]); + }); + + it('add values', () => { + const accessor = Kernel.createEmpty(); + const bytes1 = createArrayBuffer(0x08, 0x01); + const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1)); + const bytes2 = createArrayBuffer(0x08, 0x02); + const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2)); + + accessor.addRepeatedGroupIterable(1, [msg1], TestMessage.instanceCreator); + accessor.addRepeatedGroupIterable(1, [msg2], TestMessage.instanceCreator); + const result = + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator); + + expect(Array.from(result)).toEqual([msg1, msg2]); + }); + + it('set a single value', () => { + const bytes = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + const subbytes = createArrayBuffer(0x08, 0x01); + const submsg = new TestMessage(Kernel.fromArrayBuffer(subbytes)); + + accessor.setRepeatedGroupElement( + /* fieldNumber= */ 1, submsg, TestMessage.instanceCreator, + /* index= */ 0); + const result = + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator); + + expect(Array.from(result)).toEqual([submsg]); + }); + + it('write submessage changes made via getRepeatedGroupElement', () => { + const bytes = createArrayBuffer(0x0B, 0x08, 0x05, 0x0C); + const expected = createArrayBuffer(0x0B, 0x08, 0x00, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + const submsg = accessor.getRepeatedGroupElement( + /* fieldNumber= */ 1, TestMessage.instanceCreator, + /* index= */ 0); + expect(submsg.getInt32WithDefault(1, 0)).toEqual(5); + submsg.setInt32(1, 0); + + expect(accessor.serialize()).toEqual(expected); + }); + + it('set values', () => { + const accessor = Kernel.createEmpty(); + const subbytes = createArrayBuffer(0x08, 0x01); + const submsg = new TestMessage(Kernel.fromArrayBuffer(subbytes)); + + accessor.setRepeatedGroupIterable(1, [submsg]); + const result = + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator); + + expect(Array.from(result)).toEqual([submsg]); + }); + + it('encode for adding single value', () => { + const accessor = Kernel.createEmpty(); + const bytes1 = createArrayBuffer(0x08, 0x01); + const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1)); + const bytes2 = createArrayBuffer(0x08, 0x00); + const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2)); + const expected = + createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x00, 0x0C); + + accessor.addRepeatedGroupElement(1, msg1, TestMessage.instanceCreator); + accessor.addRepeatedGroupElement(1, msg2, TestMessage.instanceCreator); + const result = accessor.serialize(); + + expect(result).toEqual(expected); + }); + + it('encode for adding values', () => { + const accessor = Kernel.createEmpty(); + const bytes1 = createArrayBuffer(0x08, 0x01); + const msg1 = new TestMessage(Kernel.fromArrayBuffer(bytes1)); + const bytes2 = createArrayBuffer(0x08, 0x00); + const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2)); + const expected = + createArrayBuffer(0x0B, 0x08, 0x01, 0x0C, 0x0B, 0x08, 0x00, 0x0C); + + accessor.addRepeatedGroupIterable( + 1, [msg1, msg2], TestMessage.instanceCreator); + const result = accessor.serialize(); + + expect(result).toEqual(expected); + }); + + it('encode for setting single value', () => { + const bytes = createArrayBuffer(0x0B, 0x08, 0x00, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + const subbytes = createArrayBuffer(0x08, 0x01); + const submsg = new TestMessage(Kernel.fromArrayBuffer(subbytes)); + const expected = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C); + + accessor.setRepeatedGroupElement( + /* fieldNumber= */ 1, submsg, TestMessage.instanceCreator, + /* index= */ 0); + const result = accessor.serialize(); + + expect(result).toEqual(expected); + }); + + it('encode for setting values', () => { + const accessor = Kernel.createEmpty(); + const subbytes = createArrayBuffer(0x08, 0x01); + const submsg = new TestMessage(Kernel.fromArrayBuffer(subbytes)); + const expected = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C); + + accessor.setRepeatedGroupIterable(1, [submsg]); + const result = accessor.serialize(); + + expect(result).toEqual(expected); + }); + + it('fail when getting groups value with other wire types', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + + if (CHECK_CRITICAL_STATE) { + expect(() => { + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator); + }).toThrow(); + } + }); + + it('fail when adding group values with wrong type value', () => { + const accessor = Kernel.createEmpty(); + const fakeValue = /** @type {!TestMessage} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect( + () => accessor.addRepeatedGroupIterable( + 1, [fakeValue], TestMessage.instanceCreator)) + .toThrowError('Given value is not a message instance: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addRepeatedGroupIterable( + 1, [fakeValue], TestMessage.instanceCreator); + const list = + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator); + expect(Array.from(list)).toEqual([null]); + } + }); + + it('fail when adding single group value with wrong type value', () => { + const accessor = Kernel.createEmpty(); + const fakeValue = /** @type {!TestMessage} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect( + () => accessor.addRepeatedGroupElement( + 1, fakeValue, TestMessage.instanceCreator)) + .toThrowError('Given value is not a message instance: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.addRepeatedGroupElement( + 1, fakeValue, TestMessage.instanceCreator); + const list = + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator); + expect(Array.from(list)).toEqual([null]); + } + }); + + it('fail when setting message values with wrong type value', () => { + const accessor = Kernel.createEmpty(); + const fakeValue = /** @type {!TestMessage} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect(() => accessor.setRepeatedGroupIterable(1, [fakeValue])) + .toThrowError('Given value is not a message instance: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setRepeatedGroupIterable(1, [fakeValue]); + const list = + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator); + expect(Array.from(list)).toEqual([null]); + } + }); + + it('fail when setting single value with wrong type value', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0B, 0x08, 0x00, 0x0C)); + const fakeValue = /** @type {!TestMessage} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_STATE) { + expect( + () => accessor.setRepeatedGroupElement( + /* fieldNumber= */ 1, fakeValue, TestMessage.instanceCreator, + /* index= */ 0)) + .toThrowError('Given value is not a message instance: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setRepeatedGroupElement( + /* fieldNumber= */ 1, fakeValue, TestMessage.instanceCreator, + /* index= */ 0); + const list = + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator); + expect(Array.from(list).length).toEqual(1); + } + }); + + it('fail when setting single value with out-of-bound index', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0B, 0x08, 0x00, 0x0C)); + const msg1 = + accessor.getRepeatedGroupElement(1, TestMessage.instanceCreator, 0); + const bytes2 = createArrayBuffer(0x08, 0x01); + const msg2 = new TestMessage(Kernel.fromArrayBuffer(bytes2)); + if (CHECK_CRITICAL_STATE) { + expect( + () => accessor.setRepeatedGroupElement( + /* fieldNumber= */ 1, msg2, TestMessage.instanceCreator, + /* index= */ 1)) + .toThrowError('Index out of bounds: index: 1 size: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setRepeatedGroupElement( + /* fieldNumber= */ 1, msg2, TestMessage.instanceCreator, + /* index= */ 1); + expectEqualToArray( + accessor.getRepeatedGroupIterable(1, TestMessage.instanceCreator), + [msg1, msg2]); + } + }); +}); diff --git a/js/experimental/runtime/kernel/kernel_test.js b/js/experimental/runtime/kernel/kernel_test.js new file mode 100644 index 0000000000000..eba7c4a55a2de --- /dev/null +++ b/js/experimental/runtime/kernel/kernel_test.js @@ -0,0 +1,2329 @@ +/** + * @fileoverview Tests for kernel.js. + */ +goog.module('protobuf.runtime.KernelTest'); + +goog.setTestOnly(); + +const ByteString = goog.require('protobuf.ByteString'); +const Int64 = goog.require('protobuf.Int64'); +const InternalMessage = goog.require('protobuf.binary.InternalMessage'); +const Kernel = goog.require('protobuf.runtime.Kernel'); +const TestMessage = goog.require('protobuf.testing.binary.TestMessage'); +// Note to the reader: +// Since the lazy accessor behavior changes with the checking level some of the +// tests in this file have to know which checking level is enable to make +// correct assertions. +const {CHECK_BOUNDS, CHECK_CRITICAL_STATE, CHECK_CRITICAL_TYPE, CHECK_TYPE, MAX_FIELD_NUMBER} = goog.require('protobuf.internal.checks'); + +/** + * @param {...number} bytes + * @return {!ArrayBuffer} + */ +function createArrayBuffer(...bytes) { + return new Uint8Array(bytes).buffer; +} + +describe('Kernel', () => { + it('encodes none for the empty input', () => { + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + expect(accessor.serialize()).toEqual(new ArrayBuffer(0)); + }); + + it('encodes and decodes max field number', () => { + const accessor = Kernel.fromArrayBuffer( + createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x0F, 0x01)); + expect(accessor.getBoolWithDefault(MAX_FIELD_NUMBER)).toBe(true); + accessor.setBool(MAX_FIELD_NUMBER, false); + expect(accessor.serialize()) + .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x0F, 0x00)); + }); + + it('uses the default pivot point', () => { + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + expect(accessor.getPivot()).toBe(24); + }); + + it('makes the pivot point configurable', () => { + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0), 50); + expect(accessor.getPivot()).toBe(50); + }); +}); + +describe('Kernel hasFieldNumber', () => { + it('returns false for empty input', () => { + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + expect(accessor.hasFieldNumber(1)).toBe(false); + }); + + it('returns true for non-empty input', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.hasFieldNumber(1)).toBe(true); + }); + + it('returns false for empty array', () => { + const accessor = Kernel.createEmpty(); + accessor.setPackedBoolIterable(1, []); + expect(accessor.hasFieldNumber(1)).toBe(false); + }); + + it('returns true for non-empty array', () => { + const accessor = Kernel.createEmpty(); + accessor.setPackedBoolIterable(1, [true]); + expect(accessor.hasFieldNumber(1)).toBe(true); + }); + + it('updates value after write', () => { + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + expect(accessor.hasFieldNumber(1)).toBe(false); + accessor.setBool(1, false); + expect(accessor.hasFieldNumber(1)).toBe(true); + }); +}); + +describe('Kernel clear field does', () => { + it('clear the field set', () => { + const accessor = Kernel.createEmpty(); + accessor.setBool(1, true); + accessor.clearField(1); + + expect(accessor.hasFieldNumber(1)).toEqual(false); + expect(accessor.serialize()).toEqual(new ArrayBuffer(0)); + expect(accessor.getBoolWithDefault(1)).toEqual(false); + }); + + it('clear the field decoded', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.clearField(1); + + expect(accessor.hasFieldNumber(1)).toEqual(false); + expect(accessor.serialize()).toEqual(new ArrayBuffer(0)); + expect(accessor.getBoolWithDefault(1)).toEqual(false); + }); + + it('clear the field read', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getBoolWithDefault(1)).toEqual(true); + accessor.clearField(1); + + expect(accessor.hasFieldNumber(1)).toEqual(false); + expect(accessor.serialize()).toEqual(new ArrayBuffer(0)); + expect(accessor.getBoolWithDefault(1)).toEqual(false); + }); + + it('clear set and copied fields without affecting the old', () => { + const accessor = Kernel.createEmpty(); + accessor.setBool(1, true); + + const clonedAccessor = accessor.shallowCopy(); + clonedAccessor.clearField(1); + + expect(accessor.hasFieldNumber(1)).toEqual(true); + expect(accessor.getBoolWithDefault(1)).toEqual(true); + expect(clonedAccessor.hasFieldNumber(1)).toEqual(false); + expect(clonedAccessor.serialize()).toEqual(new ArrayBuffer(0)); + expect(clonedAccessor.getBoolWithDefault(1)).toEqual(false); + }); + + it('clear decoded and copied fields without affecting the old', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + + const clonedAccessor = accessor.shallowCopy(); + clonedAccessor.clearField(1); + + expect(accessor.hasFieldNumber(1)).toEqual(true); + expect(accessor.getBoolWithDefault(1)).toEqual(true); + expect(clonedAccessor.hasFieldNumber(1)).toEqual(false); + expect(clonedAccessor.serialize()).toEqual(new ArrayBuffer(0)); + expect(clonedAccessor.getBoolWithDefault(1)).toEqual(false); + }); + + it('clear read and copied fields without affecting the old', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getBoolWithDefault(1)).toEqual(true); + + const clonedAccessor = accessor.shallowCopy(); + clonedAccessor.clearField(1); + + expect(accessor.hasFieldNumber(1)).toEqual(true); + expect(accessor.getBoolWithDefault(1)).toEqual(true); + expect(clonedAccessor.hasFieldNumber(1)).toEqual(false); + expect(clonedAccessor.serialize()).toEqual(new ArrayBuffer(0)); + expect(clonedAccessor.getBoolWithDefault(1)).toEqual(false); + }); + + it('clear the max field number', () => { + const accessor = Kernel.createEmpty(); + accessor.setBool(MAX_FIELD_NUMBER, true); + + accessor.clearField(MAX_FIELD_NUMBER); + + expect(accessor.hasFieldNumber(MAX_FIELD_NUMBER)).toEqual(false); + expect(accessor.getBoolWithDefault(MAX_FIELD_NUMBER)).toEqual(false); + }); +}); + +describe('Kernel shallow copy does', () => { + it('work for singular fields', () => { + const accessor = Kernel.createEmpty(); + accessor.setBool(1, true); + accessor.setBool(MAX_FIELD_NUMBER, true); + const clonedAccessor = accessor.shallowCopy(); + expect(clonedAccessor.getBoolWithDefault(1)).toEqual(true); + expect(clonedAccessor.getBoolWithDefault(MAX_FIELD_NUMBER)).toEqual(true); + + accessor.setBool(1, false); + accessor.setBool(MAX_FIELD_NUMBER, false); + expect(clonedAccessor.getBoolWithDefault(1)).toEqual(true); + expect(clonedAccessor.getBoolWithDefault(MAX_FIELD_NUMBER)).toEqual(true); + }); + + it('work for repeated fields', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedBoolIterable(2, [true, true]); + + const clonedAccessor = accessor.shallowCopy(); + + // Modify a repeated field after clone + accessor.addUnpackedBoolElement(2, true); + + const array = Array.from(clonedAccessor.getRepeatedBoolIterable(2)); + expect(array).toEqual([true, true]); + }); + + it('work for repeated fields', () => { + const accessor = Kernel.createEmpty(); + + accessor.addUnpackedBoolIterable(2, [true, true]); + + const clonedAccessor = accessor.shallowCopy(); + + // Modify a repeated field after clone + accessor.addUnpackedBoolElement(2, true); + + const array = Array.from(clonedAccessor.getRepeatedBoolIterable(2)); + expect(array).toEqual([true, true]); + }); + + it('return the correct bytes after serialization', () => { + const bytes = createArrayBuffer(0x08, 0x01, 0x10, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes, /* pivot= */ 1); + const clonedAccessor = accessor.shallowCopy(); + + accessor.setBool(1, false); + + expect(clonedAccessor.getBoolWithDefault(1)).toEqual(true); + expect(clonedAccessor.serialize()).toEqual(bytes); + }); +}); + +describe('Kernel for singular boolean does', () => { + it('return false for the empty input', () => { + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + expect(accessor.getBoolWithDefault( + /* fieldNumber= */ 1)) + .toBe(false); + }); + + it('return the value from the input', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getBoolWithDefault( + /* fieldNumber= */ 1)) + .toBe(true); + }); + + it('encode the value from the input', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('encode the value from the input after read', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.getBoolWithDefault( + /* fieldNumber= */ 1); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('return the value from multiple inputs', () => { + const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getBoolWithDefault( + /* fieldNumber= */ 1)) + .toBe(false); + }); + + it('encode the value from multiple inputs', () => { + const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('encode the value from multiple inputs after read', () => { + const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.getBoolWithDefault(/* fieldNumber= */ 1); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('return the value from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setBool(1, true); + expect(accessor.getBoolWithDefault( + /* fieldNumber= */ 1)) + .toBe(true); + }); + + it('encode the value from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = createArrayBuffer(0x08, 0x01); + accessor.setBool(1, true); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('return the bool value from cache', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getBoolWithDefault( + /* fieldNumber= */ 1)) + .toBe(true); + // Make sure the value is cached. + bytes[1] = 0x00; + expect(accessor.getBoolWithDefault( + /* fieldNumber= */ 1)) + .toBe(true); + }); + + it('fail when getting bool value with other wire types', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_TYPE) { + expect(() => { + accessor.getBoolWithDefault(/* fieldNumber= */ 1); + }).toThrowError('Expected wire type: 0 but found: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getBoolWithDefault( + /* fieldNumber= */ 1)) + .toBe(true); + } + }); + + it('fail when setting bool value with out-of-range field number', () => { + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + if (CHECK_TYPE) { + expect(() => accessor.setBool(MAX_FIELD_NUMBER + 1, false)) + .toThrowError('Field number is out of range: 536870912'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setBool(MAX_FIELD_NUMBER + 1, false); + expect(accessor.getBoolWithDefault(MAX_FIELD_NUMBER + 1)).toBe(false); + } + }); + + it('fail when setting bool value with number value', () => { + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + const fakeBoolean = /** @type {boolean} */ (/** @type {*} */ (2)); + if (CHECK_CRITICAL_TYPE) { + expect(() => accessor.setBool(1, fakeBoolean)) + .toThrowError('Must be a boolean, but got: 2'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setBool(1, fakeBoolean); + expect(accessor.getBoolWithDefault( + /* fieldNumber= */ 1)) + .toBe(2); + } + }); +}); + +describe('Kernel for singular message does', () => { + it('return message from the input', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + const msg = accessor.getMessageOrNull(1, TestMessage.instanceCreator); + expect(msg.getBoolWithDefault(1, false)).toBe(true); + }); + + it('return message from the input when pivot is set', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes, /* pivot= */ 0); + const msg = accessor.getMessageOrNull(1, TestMessage.instanceCreator); + expect(msg.getBoolWithDefault(1, false)).toBe(true); + }); + + it('encode message from the input', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('encode message from the input after read', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.getMessageOrNull(1, TestMessage.instanceCreator); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('return message from multiple inputs', () => { + const bytes = + createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x10, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + const msg = accessor.getMessageOrNull(1, TestMessage.instanceCreator); + expect(msg.getBoolWithDefault(1, false)).toBe(true); + expect(msg.getBoolWithDefault(2, false)).toBe(true); + }); + + it('encode message from multiple inputs', () => { + const bytes = + createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x10, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('encode message merged from multiple inputs after read', () => { + const bytes = + createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x10, 0x01); + const expected = createArrayBuffer(0x0A, 0x04, 0x08, 0x01, 0x10, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.getMessageOrNull(1, TestMessage.instanceCreator); + expect(accessor.serialize()).toEqual(expected); + }); + + it('return null for generic accessor', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + const accessor1 = accessor.getMessageAccessorOrNull(7); + expect(accessor1).toBe(null); + }); + + it('return null for generic accessor when pivot is set', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + const accessor1 = accessor.getMessageAccessorOrNull(7, /* pivot= */ 0); + expect(accessor1).toBe(null); + }); + + it('return generic accessor from the input', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + const accessor1 = accessor.getMessageAccessorOrNull(1); + expect(accessor1.getBoolWithDefault(1, false)).toBe(true); + // Second call returns a new instance, isn't cached. + const accessor2 = accessor.getMessageAccessorOrNull(1); + expect(accessor2.getBoolWithDefault(1, false)).toBe(true); + expect(accessor2).not.toBe(accessor1); + }); + + it('return generic accessor from the cached input', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + const wrappedMessage = + accessor.getMessageOrNull(1, TestMessage.instanceCreator); + + // Returns accessor from the cached wrapper instance. + const accessor1 = accessor.getMessageAccessorOrNull(1); + expect(accessor1.getBoolWithDefault(1, false)).toBe(true); + expect(accessor1).toBe( + (/** @type {!InternalMessage} */ (wrappedMessage)).internalGetKernel()); + + // Second call returns exact same instance. + const accessor2 = accessor.getMessageAccessorOrNull(1); + expect(accessor2.getBoolWithDefault(1, false)).toBe(true); + expect(accessor2).toBe( + (/** @type {!InternalMessage} */ (wrappedMessage)).internalGetKernel()); + expect(accessor2).toBe(accessor1); + }); + + it('return message from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + const subaccessor = Kernel.fromArrayBuffer(bytes); + const submsg1 = new TestMessage(subaccessor); + accessor.setMessage(1, submsg1); + const submsg2 = accessor.getMessage(1, TestMessage.instanceCreator); + expect(submsg1).toBe(submsg2); + }); + + it('encode message from setter', () => { + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + const subaccessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + const subsubaccessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01)); + const subsubmsg = new TestMessage(subsubaccessor); + subaccessor.setMessage(1, subsubmsg); + const submsg = new TestMessage(subaccessor); + accessor.setMessage(1, submsg); + const expected = createArrayBuffer(0x0A, 0x04, 0x0A, 0x02, 0x08, 0x01); + expect(accessor.serialize()).toEqual(expected); + }); + + it('encode message with multiple submessage from setter', () => { + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + const subaccessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + const subsubaccessor1 = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01)); + const subsubaccessor2 = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x02)); + + const subsubmsg1 = new TestMessage(subsubaccessor1); + const subsubmsg2 = new TestMessage(subsubaccessor2); + + subaccessor.setMessage(1, subsubmsg1); + subaccessor.setMessage(2, subsubmsg2); + + const submsg = new TestMessage(subaccessor); + accessor.setMessage(1, submsg); + + const expected = createArrayBuffer( + 0x0A, 0x08, 0x0A, 0x02, 0x08, 0x01, 0x12, 0x02, 0x08, 0x02); + expect(accessor.serialize()).toEqual(expected); + }); + + it('leave hasFieldNumber unchanged after getMessageOrNull', () => { + const accessor = Kernel.createEmpty(); + expect(accessor.hasFieldNumber(1)).toBe(false); + expect(accessor.getMessageOrNull(1, TestMessage.instanceCreator)) + .toBe(null); + expect(accessor.hasFieldNumber(1)).toBe(false); + }); + + it('serialize changes to submessages made with getMessageOrNull', () => { + const intTwoBytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x02); + const accessor = Kernel.fromArrayBuffer(intTwoBytes); + const mutableSubMessage = + accessor.getMessageOrNull(1, TestMessage.instanceCreator); + mutableSubMessage.setInt32(1, 10); + const intTenBytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x0A); + expect(accessor.serialize()).toEqual(intTenBytes); + }); + + it('serialize additions to submessages made with getMessageOrNull', () => { + const intTwoBytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x02); + const accessor = Kernel.fromArrayBuffer(intTwoBytes); + const mutableSubMessage = + accessor.getMessageOrNull(1, TestMessage.instanceCreator); + mutableSubMessage.setInt32(2, 3); + // Sub message contains the original field, plus the new one. + expect(accessor.serialize()) + .toEqual(createArrayBuffer(0x0A, 0x04, 0x08, 0x02, 0x10, 0x03)); + }); + + it('fail with getMessageOrNull if immutable message exist in cache', () => { + const intTwoBytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x02); + const accessor = Kernel.fromArrayBuffer(intTwoBytes); + + const readOnly = accessor.getMessage(1, TestMessage.instanceCreator); + if (CHECK_TYPE) { + expect(() => accessor.getMessageOrNull(1, TestMessage.instanceCreator)) + .toThrow(); + } else { + const mutableSubMessage = + accessor.getMessageOrNull(1, TestMessage.instanceCreator); + // The instance returned by getMessageOrNull is the exact same instance. + expect(mutableSubMessage).toBe(readOnly); + + // Serializing the submessage does not write the changes + mutableSubMessage.setInt32(1, 0); + expect(accessor.serialize()).toEqual(intTwoBytes); + } + }); + + it('change hasFieldNumber after getMessageAttach', () => { + const accessor = Kernel.createEmpty(); + expect(accessor.hasFieldNumber(1)).toBe(false); + expect(accessor.getMessageAttach(1, TestMessage.instanceCreator)) + .not.toBe(null); + expect(accessor.hasFieldNumber(1)).toBe(true); + }); + + it('change hasFieldNumber after getMessageAttach when pivot is set', () => { + const accessor = Kernel.createEmpty(); + expect(accessor.hasFieldNumber(1)).toBe(false); + expect(accessor.getMessageAttach( + 1, TestMessage.instanceCreator, /* pivot= */ 1)) + .not.toBe(null); + expect(accessor.hasFieldNumber(1)).toBe(true); + }); + + it('serialize submessages made with getMessageAttach', () => { + const accessor = Kernel.createEmpty(); + const mutableSubMessage = + accessor.getMessageAttach(1, TestMessage.instanceCreator); + mutableSubMessage.setInt32(1, 10); + const intTenBytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x0A); + expect(accessor.serialize()).toEqual(intTenBytes); + }); + + it('serialize additions to submessages using getMessageAttach', () => { + const intTwoBytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x02); + const accessor = Kernel.fromArrayBuffer(intTwoBytes); + const mutableSubMessage = + accessor.getMessageAttach(1, TestMessage.instanceCreator); + mutableSubMessage.setInt32(2, 3); + // Sub message contains the original field, plus the new one. + expect(accessor.serialize()) + .toEqual(createArrayBuffer(0x0A, 0x04, 0x08, 0x02, 0x10, 0x03)); + }); + + it('fail with getMessageAttach if immutable message exist in cache', () => { + const intTwoBytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x02); + const accessor = Kernel.fromArrayBuffer(intTwoBytes); + + const readOnly = accessor.getMessage(1, TestMessage.instanceCreator); + if (CHECK_TYPE) { + expect(() => accessor.getMessageAttach(1, TestMessage.instanceCreator)) + .toThrow(); + } else { + const mutableSubMessage = + accessor.getMessageAttach(1, TestMessage.instanceCreator); + // The instance returned by getMessageOrNull is the exact same instance. + expect(mutableSubMessage).toBe(readOnly); + + // Serializing the submessage does not write the changes + mutableSubMessage.setInt32(1, 0); + expect(accessor.serialize()).toEqual(intTwoBytes); + } + }); + + it('read default message return empty message with getMessage', () => { + const bytes = new ArrayBuffer(0); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getMessage(1, TestMessage.instanceCreator)).toBeTruthy(); + expect(accessor.getMessage(1, TestMessage.instanceCreator).serialize()) + .toEqual(bytes); + }); + + it('read default message return null with getMessageOrNull', () => { + const bytes = new ArrayBuffer(0); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getMessageOrNull(1, TestMessage.instanceCreator)) + .toBe(null); + }); + + it('read message preserve reference equality', () => { + const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + const msg1 = accessor.getMessageOrNull(1, TestMessage.instanceCreator); + const msg2 = accessor.getMessageOrNull(1, TestMessage.instanceCreator); + const msg3 = accessor.getMessageAttach(1, TestMessage.instanceCreator); + expect(msg1).toBe(msg2); + expect(msg1).toBe(msg3); + }); + + it('fail when getting message with other wire types', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01)); + expect(() => accessor.getMessageOrNull(1, TestMessage.instanceCreator)) + .toThrow(); + }); + + it('fail when submessage has incomplete data', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x08)); + expect(() => accessor.getMessageOrNull(1, TestMessage.instanceCreator)) + .toThrow(); + }); + + it('fail when mutable submessage has incomplete data', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x08)); + expect(() => accessor.getMessageAttach(1, TestMessage.instanceCreator)) + .toThrow(); + }); + + it('fail when getting message with null instance constructor', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x02, 0x08, 0x01)); + const nullMessage = /** @type {function(!Kernel):!TestMessage} */ + (/** @type {*} */ (null)); + expect(() => accessor.getMessageOrNull(1, nullMessage)).toThrow(); + }); + + it('fail when setting message value with null value', () => { + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + const fakeMessage = /** @type {!TestMessage} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_TYPE) { + expect(() => accessor.setMessage(1, fakeMessage)) + .toThrowError('Given value is not a message instance: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setMessage(1, fakeMessage); + expect(accessor.getMessageOrNull( + /* fieldNumber= */ 1, TestMessage.instanceCreator)) + .toBeNull(); + } + }); +}); + +describe('Bytes access', () => { + const simpleByteString = ByteString.fromArrayBuffer(createArrayBuffer(1)); + + it('returns default value for empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getBytesWithDefault(1)).toEqual(ByteString.EMPTY); + }); + + it('returns the default from parameter', () => { + const defaultByteString = ByteString.fromArrayBuffer(createArrayBuffer(1)); + const returnValue = ByteString.fromArrayBuffer(createArrayBuffer(1)); + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getBytesWithDefault(1, defaultByteString)) + .toEqual(returnValue); + }); + + it('decodes value from wire', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x01)); + expect(accessor.getBytesWithDefault(1)).toEqual(simpleByteString); + }); + + it('decodes value from wire with multiple values being present', () => { + const accessor = Kernel.fromArrayBuffer( + createArrayBuffer(0x0A, 0x01, 0x00, 0x0A, 0x01, 0x01)); + expect(accessor.getBytesWithDefault(1)).toEqual(simpleByteString); + }); + + it('fails when getting value with other wire types', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01)); + if (CHECK_CRITICAL_TYPE) { + expect(() => { + accessor.getBytesWithDefault(1); + }).toThrowError('Expected wire type: 2 but found: 1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + const arrayBuffer = createArrayBuffer(1); + expect(accessor.getBytesWithDefault(1)) + .toEqual(ByteString.fromArrayBuffer(arrayBuffer)); + } + }); + + it('throws in getter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect( + () => Kernel.createEmpty().getBytesWithDefault(-1, simpleByteString)) + .toThrowError('Field number is out of range: -1'); + } else { + expect(Kernel.createEmpty().getBytesWithDefault(-1, simpleByteString)) + .toEqual(simpleByteString); + } + }); + + it('returns the value from setter', () => { + const bytes = createArrayBuffer(0x0A, 0x01, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setBytes(1, simpleByteString); + expect(accessor.getBytesWithDefault(1)).toEqual(simpleByteString); + }); + + it('encode the value from setter', () => { + const bytes = createArrayBuffer(0x0A, 0x01, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = createArrayBuffer(0x0A, 0x01, 0x01); + accessor.setBytes(1, simpleByteString); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('returns value from cache', () => { + const bytes = createArrayBuffer(0x0A, 0x01, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getBytesWithDefault(1)).toEqual(simpleByteString); + // Make sure the value is cached. + bytes[2] = 0x00; + expect(accessor.getBytesWithDefault(1)).toEqual(simpleByteString); + }); + + it('throws in setter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().setBytes(-1, simpleByteString)) + .toThrowError('Field number is out of range: -1'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setBytes(-1, simpleByteString); + expect(accessor.getBytesWithDefault(-1)).toEqual(simpleByteString); + } + }); + + it('throws in setter for invalid value', () => { + if (CHECK_CRITICAL_TYPE) { + expect( + () => Kernel.createEmpty().setBytes( + 1, /** @type {!ByteString} */ (/** @type {*} */ (null)))) + .toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setBytes( + 1, /** @type {!ByteString} */ (/** @type {*} */ (null))); + expect(accessor.getBytesWithDefault(1)).toEqual(null); + } + }); +}); + +describe('Fixed32 access', () => { + it('returns default value for empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getFixed32WithDefault(1)).toEqual(0); + }); + + it('returns the default from parameter', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getFixed32WithDefault(1, 2)).toEqual(2); + }); + + it('decodes value from wire', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00)); + expect(accessor.getFixed32WithDefault(1)).toEqual(1); + }); + + it('decodes value from wire with multiple values being present', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x0D, 0x01, 0x00, 0x80, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00)); + expect(accessor.getFixed32WithDefault(1)).toEqual(2); + }); + + it('fails when getting value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_TYPE) { + expect(() => { + accessor.getFixed32WithDefault(1); + }).toThrowError('Expected wire type: 5 but found: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getFixed32WithDefault(1)).toEqual(8421504); + } + }); + + it('throws in getter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().getFixed32WithDefault(-1, 1)) + .toThrowError('Field number is out of range: -1'); + } else { + expect(Kernel.createEmpty().getFixed32WithDefault(-1, 1)).toEqual(1); + } + }); + + it('returns the value from setter', () => { + const bytes = createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setFixed32(1, 2); + expect(accessor.getFixed32WithDefault(1)).toEqual(2); + }); + + it('encode the value from setter', () => { + const bytes = createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00); + accessor.setFixed32(1, 0); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('returns value from cache', () => { + const bytes = createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getFixed32WithDefault(1)).toBe(1); + // Make sure the value is cached. + bytes[2] = 0x00; + expect(accessor.getFixed32WithDefault(1)).toBe(1); + }); + + it('throws in setter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().setFixed32(-1, 1)) + .toThrowError('Field number is out of range: -1'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setFixed32(-1, 1); + expect(accessor.getFixed32WithDefault(-1)).toEqual(1); + } + }); + + it('throws in setter for invalid value', () => { + if (CHECK_CRITICAL_TYPE) { + expect( + () => Kernel.createEmpty().setFixed32( + 1, /** @type {number} */ (/** @type {*} */ (null)))) + .toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setFixed32(1, /** @type {number} */ (/** @type {*} */ (null))); + expect(accessor.getFixed32WithDefault(1)).toEqual(null); + } + }); + + it('throws in setter for negative value', () => { + if (CHECK_CRITICAL_TYPE) { + expect(() => Kernel.createEmpty().setFixed32(1, -1)).toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setFixed32(1, -1); + expect(accessor.getFixed32WithDefault(1)).toEqual(-1); + } + }); +}); + +describe('Fixed64 access', () => { + it('returns default value for empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getFixed64WithDefault(1)).toEqual(Int64.fromInt(0)); + }); + + it('returns the default from parameter', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getFixed64WithDefault(1, Int64.fromInt(2))) + .toEqual(Int64.fromInt(2)); + }); + + it('decodes value from wire', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + expect(accessor.getFixed64WithDefault(1)).toEqual(Int64.fromInt(1)); + }); + + it('decodes value from wire with multiple values being present', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + expect(accessor.getFixed64WithDefault(1)).toEqual(Int64.fromInt(2)); + }); + + if (CHECK_CRITICAL_STATE) { + it('fails when getting value with other wire types', () => { + const accessor = Kernel.fromArrayBuffer( + createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + expect(() => { + accessor.getFixed64WithDefault(1); + }).toThrow(); + }); + } + + it('throws in getter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect( + () => + Kernel.createEmpty().getFixed64WithDefault(-1, Int64.fromInt(1))) + .toThrowError('Field number is out of range: -1'); + } else { + expect(Kernel.createEmpty().getFixed64WithDefault(-1, Int64.fromInt(1))) + .toEqual(Int64.fromInt(1)); + } + }); + + it('returns the value from setter', () => { + const bytes = + createArrayBuffer(0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setFixed64(1, Int64.fromInt(2)); + expect(accessor.getFixed64WithDefault(1)).toEqual(Int64.fromInt(2)); + }); + + it('encode the value from setter', () => { + const bytes = + createArrayBuffer(0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = + createArrayBuffer(0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + accessor.setFixed64(1, Int64.fromInt(0)); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('returns value from cache', () => { + const bytes = + createArrayBuffer(0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getFixed64WithDefault(1)).toEqual(Int64.fromInt(1)); + // Make sure the value is cached. + bytes[2] = 0x00; + expect(accessor.getFixed64WithDefault(1)).toEqual(Int64.fromInt(1)); + }); + + it('throws in setter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().setFixed64(-1, Int64.fromInt(1))) + .toThrowError('Field number is out of range: -1'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setFixed64(-1, Int64.fromInt(1)); + expect(accessor.getFixed64WithDefault(-1)).toEqual(Int64.fromInt(1)); + } + }); + + it('throws in setter for invalid value', () => { + if (CHECK_CRITICAL_TYPE) { + expect( + () => Kernel.createEmpty().setSfixed64( + 1, /** @type {!Int64} */ (/** @type {*} */ (null)))) + .toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setFixed64(1, /** @type {!Int64} */ (/** @type {*} */ (null))); + expect(accessor.getFixed64WithDefault(1)).toEqual(null); + } + }); +}); + +describe('Float access', () => { + it('returns default value for empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getFloatWithDefault(1)).toEqual(0); + }); + + it('returns the default from parameter', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getFloatWithDefault(1, 2)).toEqual(2); + }); + + it('decodes value from wire', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x80, 0x3F)); + expect(accessor.getFloatWithDefault(1)).toEqual(1); + }); + + it('decodes value from wire with multiple values being present', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x0D, 0x00, 0x00, 0x80, 0x3F, 0x0D, 0x00, 0x00, 0x80, 0xBF)); + expect(accessor.getFloatWithDefault(1)).toEqual(-1); + }); + + if (CHECK_CRITICAL_STATE) { + it('fails when getting float value with other wire types', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F)); + expect(() => { + accessor.getFloatWithDefault(1); + }).toThrow(); + }); + } + + + it('throws in getter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().getFloatWithDefault(-1, 1)) + .toThrowError('Field number is out of range: -1'); + } else { + expect(Kernel.createEmpty().getFloatWithDefault(-1, 1)).toEqual(1); + } + }); + + it('returns the value from setter', () => { + const bytes = createArrayBuffer(0x0D, 0x00, 0x00, 0x80, 0x3F); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setFloat(1, 1.6); + expect(accessor.getFloatWithDefault(1)).toEqual(Math.fround(1.6)); + }); + + it('encode the value from setter', () => { + const bytes = createArrayBuffer(0x0D, 0x00, 0x00, 0x80, 0x3F); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00); + accessor.setFloat(1, 0); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('returns float value from cache', () => { + const bytes = createArrayBuffer(0x0D, 0x00, 0x00, 0x80, 0x3F); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getFloatWithDefault(1)).toBe(1); + // Make sure the value is cached. + bytes[2] = 0x00; + expect(accessor.getFloatWithDefault(1)).toBe(1); + }); + + it('throws in setter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().setFloat(-1, 1)) + .toThrowError('Field number is out of range: -1'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setFloat(-1, 1); + expect(accessor.getFloatWithDefault(-1)).toEqual(1); + } + }); + + it('throws in setter for invalid value', () => { + if (CHECK_CRITICAL_TYPE) { + expect( + () => Kernel.createEmpty().setFloat( + 1, /** @type {number} */ (/** @type {*} */ (null)))) + .toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setFloat(1, /** @type {number} */ (/** @type {*} */ (null))); + expect(accessor.getFloatWithDefault(1)).toEqual(0); + } + }); + + it('throws in setter for value outside of float32 precision', () => { + if (CHECK_CRITICAL_TYPE) { + expect(() => Kernel.createEmpty().setFloat(1, Number.MAX_VALUE)) + .toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setFloat(1, Number.MAX_VALUE); + expect(accessor.getFloatWithDefault(1)).toEqual(Infinity); + } + }); +}); + +describe('Int32 access', () => { + it('returns default value for empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getInt32WithDefault(1)).toEqual(0); + }); + + it('returns the default from parameter', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getInt32WithDefault(1, 2)).toEqual(2); + }); + + it('decodes value from wire', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01)); + expect(accessor.getInt32WithDefault(1)).toEqual(1); + }); + + it('decodes value from wire with multiple values being present', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02)); + expect(accessor.getInt32WithDefault(1)).toEqual(2); + }); + + it('fails when getting value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_TYPE) { + expect(() => { + accessor.getInt32WithDefault(1); + }).toThrowError('Expected wire type: 0 but found: 5'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getInt32WithDefault(1)).toEqual(0); + } + }); + + it('throws in getter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().getInt32WithDefault(-1, 1)) + .toThrowError('Field number is out of range: -1'); + } else { + expect(Kernel.createEmpty().getInt32WithDefault(-1, 1)).toEqual(1); + } + }); + + it('returns the value from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setInt32(1, 2); + expect(accessor.getInt32WithDefault(1)).toEqual(2); + }); + + it('encode the value from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = createArrayBuffer(0x08, 0x00); + accessor.setInt32(1, 0); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('returns value from cache', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getInt32WithDefault(1)).toBe(1); + // Make sure the value is cached. + bytes[2] = 0x00; + expect(accessor.getInt32WithDefault(1)).toBe(1); + }); + + it('throws in setter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().setInt32(-1, 1)) + .toThrowError('Field number is out of range: -1'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setInt32(-1, 1); + expect(accessor.getInt32WithDefault(-1)).toEqual(1); + } + }); + + it('throws in setter for invalid value', () => { + if (CHECK_CRITICAL_TYPE) { + expect( + () => Kernel.createEmpty().setInt32( + 1, /** @type {number} */ (/** @type {*} */ (null)))) + .toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setInt32(1, /** @type {number} */ (/** @type {*} */ (null))); + expect(accessor.getInt32WithDefault(1)).toEqual(null); + } + }); +}); + +describe('Int64 access', () => { + it('returns default value for empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(0)); + }); + + it('returns the default from parameter', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getInt64WithDefault(1, Int64.fromInt(2))) + .toEqual(Int64.fromInt(2)); + }); + + it('decodes value from wire', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01)); + expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(1)); + }); + + it('decodes value from wire with multiple values being present', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02)); + expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(2)); + }); + + it('fails when getting value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_TYPE) { + expect(() => { + accessor.getInt64WithDefault(1); + }).toThrowError('Expected wire type: 0 but found: 5'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(0)); + } + }); + + it('throws in getter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect( + () => Kernel.createEmpty().getInt64WithDefault(-1, Int64.fromInt(1))) + .toThrowError('Field number is out of range: -1'); + } else { + expect(Kernel.createEmpty().getInt64WithDefault(-1, Int64.fromInt(1))) + .toEqual(Int64.fromInt(1)); + } + }); + + it('returns the value from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setInt64(1, Int64.fromInt(2)); + expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(2)); + }); + + it('encode the value from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = createArrayBuffer(0x08, 0x00); + accessor.setInt64(1, Int64.fromInt(0)); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('returns value from cache', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(1)); + // Make sure the value is cached. + bytes[2] = 0x00; + expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(1)); + }); + + it('throws in setter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().setInt64(-1, Int64.fromInt(1))) + .toThrowError('Field number is out of range: -1'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setInt64(-1, Int64.fromInt(1)); + expect(accessor.getInt64WithDefault(-1)).toEqual(Int64.fromInt(1)); + } + }); + + it('throws in setter for invalid value', () => { + if (CHECK_CRITICAL_TYPE) { + expect( + () => Kernel.createEmpty().setInt64( + 1, /** @type {!Int64} */ (/** @type {*} */ (null)))) + .toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setInt64(1, /** @type {!Int64} */ (/** @type {*} */ (null))); + expect(accessor.getInt64WithDefault(1)).toEqual(null); + } + }); +}); + +describe('Sfixed32 access', () => { + it('returns default value for empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getSfixed32WithDefault(1)).toEqual(0); + }); + + it('returns the default from parameter', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getSfixed32WithDefault(1, 2)).toEqual(2); + }); + + it('decodes value from wire', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00)); + expect(accessor.getSfixed32WithDefault(1)).toEqual(1); + }); + + it('decodes value from wire with multiple values being present', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x0D, 0x01, 0x00, 0x80, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00)); + expect(accessor.getSfixed32WithDefault(1)).toEqual(2); + }); + + it('fails when getting value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x80, 0x80, 0x80, 0x00)); + if (CHECK_CRITICAL_TYPE) { + expect(() => { + accessor.getSfixed32WithDefault(1); + }).toThrowError('Expected wire type: 5 but found: 0'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getSfixed32WithDefault(1)).toEqual(8421504); + } + }); + + it('throws in getter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().getSfixed32WithDefault(-1, 1)) + .toThrowError('Field number is out of range: -1'); + } else { + expect(Kernel.createEmpty().getSfixed32WithDefault(-1, 1)).toEqual(1); + } + }); + + it('returns the value from setter', () => { + const bytes = createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setSfixed32(1, 2); + expect(accessor.getSfixed32WithDefault(1)).toEqual(2); + }); + + it('encode the value from setter', () => { + const bytes = createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00); + accessor.setSfixed32(1, 0); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('returns value from cache', () => { + const bytes = createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getSfixed32WithDefault(1)).toBe(1); + // Make sure the value is cached. + bytes[2] = 0x00; + expect(accessor.getSfixed32WithDefault(1)).toBe(1); + }); + + it('throws in setter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().setSfixed32(-1, 1)) + .toThrowError('Field number is out of range: -1'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setSfixed32(-1, 1); + expect(accessor.getSfixed32WithDefault(-1)).toEqual(1); + } + }); + + it('throws in setter for invalid value', () => { + if (CHECK_CRITICAL_TYPE) { + expect( + () => Kernel.createEmpty().setSfixed32( + 1, /** @type {number} */ (/** @type {*} */ (null)))) + .toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setSfixed32(1, /** @type {number} */ (/** @type {*} */ (null))); + expect(accessor.getSfixed32WithDefault(1)).toEqual(null); + } + }); +}); + +describe('Sfixed64 access', () => { + it('returns default value for empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(0)); + }); + + it('returns the default from parameter', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getSfixed64WithDefault(1, Int64.fromInt(2))) + .toEqual(Int64.fromInt(2)); + }); + + it('decodes value from wire', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + expect(accessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(1)); + }); + + it('decodes value from wire with multiple values being present', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + expect(accessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(2)); + }); + + if (CHECK_CRITICAL_STATE) { + it('fails when getting value with other wire types', () => { + const accessor = Kernel.fromArrayBuffer( + createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + expect(() => { + accessor.getSfixed64WithDefault(1); + }).toThrow(); + }); + } + + it('throws in getter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect( + () => + Kernel.createEmpty().getSfixed64WithDefault(-1, Int64.fromInt(1))) + .toThrowError('Field number is out of range: -1'); + } else { + expect(Kernel.createEmpty().getSfixed64WithDefault(-1, Int64.fromInt(1))) + .toEqual(Int64.fromInt(1)); + } + }); + + it('returns the value from setter', () => { + const bytes = + createArrayBuffer(0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setSfixed64(1, Int64.fromInt(2)); + expect(accessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(2)); + }); + + it('encode the value from setter', () => { + const bytes = + createArrayBuffer(0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = + createArrayBuffer(0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + accessor.setSfixed64(1, Int64.fromInt(0)); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('returns value from cache', () => { + const bytes = + createArrayBuffer(0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(1)); + // Make sure the value is cached. + bytes[2] = 0x00; + expect(accessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(1)); + }); + + it('throws in setter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().setSfixed64(-1, Int64.fromInt(1))) + .toThrowError('Field number is out of range: -1'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setSfixed64(-1, Int64.fromInt(1)); + expect(accessor.getSfixed64WithDefault(-1)).toEqual(Int64.fromInt(1)); + } + }); + + it('throws in setter for invalid value', () => { + if (CHECK_CRITICAL_TYPE) { + expect( + () => Kernel.createEmpty().setSfixed64( + 1, /** @type {!Int64} */ (/** @type {*} */ (null)))) + .toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setSfixed64(1, /** @type {!Int64} */ (/** @type {*} */ (null))); + expect(accessor.getSfixed64WithDefault(1)).toEqual(null); + } + }); +}); + +describe('Sint32 access', () => { + it('returns default value for empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getSint32WithDefault(1)).toEqual(0); + }); + + it('returns the default from parameter', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getSint32WithDefault(1, 2)).toEqual(2); + }); + + it('decodes value from wire', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x02)); + expect(accessor.getSint32WithDefault(1)).toEqual(1); + }); + + it('decodes value from wire with multiple values being present', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x03, 0x08, 0x02)); + expect(accessor.getSint32WithDefault(1)).toEqual(1); + }); + + it('fails when getting value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_TYPE) { + expect(() => { + accessor.getSint32WithDefault(1); + }).toThrowError('Expected wire type: 0 but found: 5'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getSint32WithDefault(1)).toEqual(0); + } + }); + + it('throws in getter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().getSint32WithDefault(-1, 1)) + .toThrowError('Field number is out of range: -1'); + } else { + expect(Kernel.createEmpty().getSint32WithDefault(-1, 1)).toEqual(1); + } + }); + + it('returns the value from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setSint32(1, 2); + expect(accessor.getSint32WithDefault(1)).toEqual(2); + }); + + it('encode the value from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = createArrayBuffer(0x08, 0x00); + accessor.setSint32(1, 0); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('returns value from cache', () => { + const bytes = createArrayBuffer(0x08, 0x02); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getSint32WithDefault(1)).toBe(1); + // Make sure the value is cached. + bytes[2] = 0x00; + expect(accessor.getSint32WithDefault(1)).toBe(1); + }); + + it('throws in setter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().setSint32(-1, 1)) + .toThrowError('Field number is out of range: -1'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setSint32(-1, 1); + expect(accessor.getSint32WithDefault(-1)).toEqual(1); + } + }); + + it('throws in setter for invalid value', () => { + if (CHECK_CRITICAL_TYPE) { + expect( + () => Kernel.createEmpty().setSint32( + 1, /** @type {number} */ (/** @type {*} */ (null)))) + .toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setSint32(1, /** @type {number} */ (/** @type {*} */ (null))); + expect(accessor.getSint32WithDefault(1)).toEqual(null); + } + }); +}); + +describe('SInt64 access', () => { + it('returns default value for empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(0)); + }); + + it('returns the default from parameter', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getSint64WithDefault(1, Int64.fromInt(2))) + .toEqual(Int64.fromInt(2)); + }); + + it('decodes value from wire', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x02)); + expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(1)); + }); + + it('decodes value from wire with multiple values being present', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02)); + expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(1)); + }); + + it('fails when getting value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_TYPE) { + expect(() => { + accessor.getSint64WithDefault(1); + }).toThrowError('Expected wire type: 0 but found: 5'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(0)); + } + }); + + it('throws in getter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect( + () => Kernel.createEmpty().getSint64WithDefault(-1, Int64.fromInt(1))) + .toThrowError('Field number is out of range: -1'); + } else { + expect(Kernel.createEmpty().getSint64WithDefault(-1, Int64.fromInt(1))) + .toEqual(Int64.fromInt(1)); + } + }); + + it('returns the value from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setSint64(1, Int64.fromInt(2)); + expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(2)); + }); + + it('encode the value from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = createArrayBuffer(0x08, 0x00); + accessor.setSint64(1, Int64.fromInt(0)); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('returns value from cache', () => { + const bytes = createArrayBuffer(0x08, 0x02); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(1)); + // Make sure the value is cached. + bytes[1] = 0x00; + expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(1)); + }); + + it('throws in setter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().setSint64(-1, Int64.fromInt(1))) + .toThrowError('Field number is out of range: -1'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setInt64(-1, Int64.fromInt(1)); + expect(accessor.getSint64WithDefault(-1)).toEqual(Int64.fromInt(1)); + } + }); + + it('throws in setter for invalid value', () => { + if (CHECK_CRITICAL_TYPE) { + expect( + () => Kernel.createEmpty().setSint64( + 1, /** @type {!Int64} */ (/** @type {*} */ (null)))) + .toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setSint64(1, /** @type {!Int64} */ (/** @type {*} */ (null))); + expect(accessor.getSint64WithDefault(1)).toEqual(null); + } + }); +}); + +describe('String access', () => { + it('returns empty string for the empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getStringWithDefault(1)).toEqual(''); + }); + + it('returns the default for the empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getStringWithDefault(1, 'bar')).toEqual('bar'); + }); + + it('decodes value from wire', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x61)); + expect(accessor.getStringWithDefault(1)).toEqual('a'); + }); + + it('decodes value from wire with multiple values being present', () => { + const accessor = Kernel.fromArrayBuffer( + createArrayBuffer(0x0A, 0x01, 0x60, 0x0A, 0x01, 0x61)); + expect(accessor.getStringWithDefault(1)).toEqual('a'); + }); + + if (CHECK_CRITICAL_STATE) { + it('fails when getting string value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x02, 0x08, 0x08)); + expect(() => { + accessor.getStringWithDefault(1); + }).toThrow(); + }); + } + + + it('throws in getter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().getStringWithDefault(-1, 'a')) + .toThrowError('Field number is out of range: -1'); + } else { + expect(Kernel.createEmpty().getStringWithDefault(-1, 'a')).toEqual('a'); + } + }); + + it('returns the value from setter', () => { + const bytes = createArrayBuffer(0x0A, 0x01, 0x61); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setString(1, 'b'); + expect(accessor.getStringWithDefault(1)).toEqual('b'); + }); + + it('encode the value from setter', () => { + const bytes = createArrayBuffer(0x0A, 0x01, 0x61); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = createArrayBuffer(0x0A, 0x01, 0x62); + accessor.setString(1, 'b'); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('returns string value from cache', () => { + const bytes = createArrayBuffer(0x0A, 0x01, 0x61); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getStringWithDefault(1)).toBe('a'); + // Make sure the value is cached. + bytes[2] = 0x00; + expect(accessor.getStringWithDefault(1)).toBe('a'); + }); + + it('throws in setter for invalid fieldNumber', () => { + if (CHECK_TYPE) { + expect(() => Kernel.createEmpty().setString(-1, 'a')) + .toThrowError('Field number is out of range: -1'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setString(-1, 'a'); + expect(accessor.getStringWithDefault(-1)).toEqual('a'); + } + }); + + it('throws in setter for invalid value', () => { + if (CHECK_CRITICAL_TYPE) { + expect( + () => Kernel.createEmpty().setString( + 1, /** @type {string} */ (/** @type {*} */ (null)))) + .toThrowError('Must be string, but got: null'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setString(1, /** @type {string} */ (/** @type {*} */ (null))); + expect(accessor.getStringWithDefault(1)).toEqual(null); + } + }); +}); + +describe('Uint32 access', () => { + it('returns default value for empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getUint32WithDefault(1)).toEqual(0); + }); + + it('returns the default from parameter', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getUint32WithDefault(1, 2)).toEqual(2); + }); + + it('decodes value from wire', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01)); + expect(accessor.getUint32WithDefault(1)).toEqual(1); + }); + + it('decodes value from wire with multiple values being present', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02)); + expect(accessor.getUint32WithDefault(1)).toEqual(2); + }); + + it('fails when getting value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_TYPE) { + expect(() => { + accessor.getUint32WithDefault(1); + }).toThrowError('Expected wire type: 0 but found: 5'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getUint32WithDefault(1)).toEqual(0); + } + }); + + it('throws in getter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().getUint32WithDefault(-1, 1)) + .toThrowError('Field number is out of range: -1'); + } else { + expect(Kernel.createEmpty().getUint32WithDefault(-1, 1)).toEqual(1); + } + }); + + it('returns the value from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setUint32(1, 2); + expect(accessor.getUint32WithDefault(1)).toEqual(2); + }); + + it('encode the value from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = createArrayBuffer(0x08, 0x00); + accessor.setUint32(1, 0); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('returns value from cache', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getUint32WithDefault(1)).toBe(1); + // Make sure the value is cached. + bytes[2] = 0x00; + expect(accessor.getUint32WithDefault(1)).toBe(1); + }); + + it('throws in setter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().setInt32(-1, 1)) + .toThrowError('Field number is out of range: -1'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setUint32(-1, 1); + expect(accessor.getUint32WithDefault(-1)).toEqual(1); + } + }); + + it('throws in setter for invalid value', () => { + if (CHECK_CRITICAL_TYPE) { + expect( + () => Kernel.createEmpty().setUint32( + 1, /** @type {number} */ (/** @type {*} */ (null)))) + .toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setUint32(1, /** @type {number} */ (/** @type {*} */ (null))); + expect(accessor.getUint32WithDefault(1)).toEqual(null); + } + }); + + it('throws in setter for negative value', () => { + if (CHECK_CRITICAL_TYPE) { + expect(() => Kernel.createEmpty().setUint32(1, -1)).toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setUint32(1, -1); + expect(accessor.getUint32WithDefault(1)).toEqual(-1); + } + }); +}); + +describe('Uint64 access', () => { + it('returns default value for empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(0)); + }); + + it('returns the default from parameter', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getUint64WithDefault(1, Int64.fromInt(2))) + .toEqual(Int64.fromInt(2)); + }); + + it('decodes value from wire', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01)); + expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(1)); + }); + + it('decodes value from wire with multiple values being present', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02)); + expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(2)); + }); + + it('fails when getting value with other wire types', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00)); + if (CHECK_CRITICAL_TYPE) { + expect(() => { + accessor.getUint64WithDefault(1); + }).toThrowError('Expected wire type: 0 but found: 5'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(0)); + } + }); + + it('throws in getter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect( + () => Kernel.createEmpty().getUint64WithDefault(-1, Int64.fromInt(1))) + .toThrowError('Field number is out of range: -1'); + } else { + expect(Kernel.createEmpty().getUint64WithDefault(-1, Int64.fromInt(1))) + .toEqual(Int64.fromInt(1)); + } + }); + + it('returns the value from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setUint64(1, Int64.fromInt(2)); + expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(2)); + }); + + it('encode the value from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = createArrayBuffer(0x08, 0x00); + accessor.setUint64(1, Int64.fromInt(0)); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('returns value from cache', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(1)); + // Make sure the value is cached. + bytes[2] = 0x00; + expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(1)); + }); + + it('throws in setter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().setUint64(-1, Int64.fromInt(1))) + .toThrowError('Field number is out of range: -1'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setUint64(-1, Int64.fromInt(1)); + expect(accessor.getUint64WithDefault(-1)).toEqual(Int64.fromInt(1)); + } + }); + + it('throws in setter for invalid value', () => { + if (CHECK_CRITICAL_TYPE) { + expect( + () => Kernel.createEmpty().setUint64( + 1, /** @type {!Int64} */ (/** @type {*} */ (null)))) + .toThrow(); + } else { + const accessor = Kernel.createEmpty(); + accessor.setUint64(1, /** @type {!Int64} */ (/** @type {*} */ (null))); + expect(accessor.getUint64WithDefault(1)).toEqual(null); + } + }); +}); + +describe('Double access', () => { + it('returns default value for empty input', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getDoubleWithDefault(1)).toEqual(0); + }); + + it('returns the default from parameter', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer()); + expect(accessor.getDoubleWithDefault(1, 2)).toEqual(2); + }); + + it('decodes value from wire', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F)); + expect(accessor.getDoubleWithDefault(1)).toEqual(1); + }); + + + it('decodes value from wire with multiple values being present', () => { + const accessor = Kernel.fromArrayBuffer(createArrayBuffer( + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF0, 0xBF)); + expect(accessor.getDoubleWithDefault(1)).toEqual(-1); + }); + + if (CHECK_CRITICAL_STATE) { + it('fails when getting double value with other wire types', () => { + const accessor = Kernel.fromArrayBuffer( + createArrayBuffer(0x0D, 0x00, 0x00, 0xF0, 0x3F)); + expect(() => { + accessor.getDoubleWithDefault(1); + }).toThrow(); + }); + } + + + it('throws in getter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().getDoubleWithDefault(-1, 1)) + .toThrowError('Field number is out of range: -1'); + } else { + expect(Kernel.createEmpty().getDoubleWithDefault(-1, 1)).toEqual(1); + } + }); + + it('returns the value from setter', () => { + const bytes = + createArrayBuffer(0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.setDouble(1, 2); + expect(accessor.getDoubleWithDefault(1)).toEqual(2); + }); + + it('encode the value from setter', () => { + const bytes = + createArrayBuffer(0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F); + const accessor = Kernel.fromArrayBuffer(bytes); + const newBytes = + createArrayBuffer(0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + accessor.setDouble(1, 0); + expect(accessor.serialize()).toEqual(newBytes); + }); + + it('returns string value from cache', () => { + const bytes = + createArrayBuffer(0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getDoubleWithDefault(1)).toBe(1); + // Make sure the value is cached. + bytes[2] = 0x00; + expect(accessor.getDoubleWithDefault(1)).toBe(1); + }); + + it('throws in setter for invalid fieldNumber', () => { + if (CHECK_BOUNDS) { + expect(() => Kernel.createEmpty().setDouble(-1, 1)) + .toThrowError('Field number is out of range: -1'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setDouble(-1, 1); + expect(accessor.getDoubleWithDefault(-1)).toEqual(1); + } + }); + + it('throws in setter for invalid value', () => { + if (CHECK_CRITICAL_TYPE) { + expect( + () => Kernel.createEmpty().setDouble( + 1, /** @type {number} */ (/** @type {*} */ (null)))) + .toThrowError('Must be a number, but got: null'); + } else { + const accessor = Kernel.createEmpty(); + accessor.setDouble(1, /** @type {number} */ (/** @type {*} */ (null))); + expect(accessor.getDoubleWithDefault(1)).toEqual(null); + } + }); +}); + +describe('Kernel for singular group does', () => { + it('return group from the input', () => { + const bytes = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + const msg = accessor.getGroupOrNull(1, TestMessage.instanceCreator); + expect(msg.getBoolWithDefault(1, false)).toBe(true); + }); + + it('return group from the input when pivot is set', () => { + const bytes = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + const msg = accessor.getGroupOrNull(1, TestMessage.instanceCreator, 0); + expect(msg.getBoolWithDefault(1, false)).toBe(true); + }); + + it('encode group from the input', () => { + const bytes = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('encode group from the input after read', () => { + const bytes = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.getGroupOrNull(1, TestMessage.instanceCreator); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('return last group from multiple inputs', () => { + const bytes = + createArrayBuffer(0x0B, 0x08, 0x00, 0x0C, 0x0B, 0x08, 0x01, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + const msg = accessor.getGroupOrNull(1, TestMessage.instanceCreator); + expect(msg.getBoolWithDefault(1, false)).toBe(true); + }); + + it('removes duplicated group when serializing', () => { + const bytes = + createArrayBuffer(0x0B, 0x08, 0x00, 0x0C, 0x0B, 0x08, 0x01, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.getGroupOrNull(1, TestMessage.instanceCreator); + expect(accessor.serialize()) + .toEqual(createArrayBuffer(0x0B, 0x08, 0x01, 0x0C)); + }); + + it('encode group from multiple inputs', () => { + const bytes = + createArrayBuffer(0x0B, 0x08, 0x00, 0x0C, 0x0B, 0x08, 0x01, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.serialize()).toEqual(bytes); + }); + + it('encode group after read', () => { + const bytes = + createArrayBuffer(0x0B, 0x08, 0x00, 0x0C, 0x0B, 0x08, 0x01, 0x0C); + const expected = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + accessor.getGroupOrNull(1, TestMessage.instanceCreator); + expect(accessor.serialize()).toEqual(expected); + }); + + it('return group from setter', () => { + const bytes = createArrayBuffer(0x08, 0x01); + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + const subaccessor = Kernel.fromArrayBuffer(bytes); + const submsg1 = new TestMessage(subaccessor); + accessor.setGroup(1, submsg1); + const submsg2 = accessor.getGroup(1, TestMessage.instanceCreator); + expect(submsg1).toBe(submsg2); + }); + + it('encode group from setter', () => { + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + const subaccessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01)); + const submsg = new TestMessage(subaccessor); + accessor.setGroup(1, submsg); + const expected = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C); + expect(accessor.serialize()).toEqual(expected); + }); + + it('leave hasFieldNumber unchanged after getGroupOrNull', () => { + const accessor = Kernel.createEmpty(); + expect(accessor.hasFieldNumber(1)).toBe(false); + expect(accessor.getGroupOrNull(1, TestMessage.instanceCreator)).toBe(null); + expect(accessor.hasFieldNumber(1)).toBe(false); + }); + + it('serialize changes to subgroups made with getGroupsOrNull', () => { + const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(intTwoBytes); + const mutableSubMessage = + accessor.getGroupOrNull(1, TestMessage.instanceCreator); + mutableSubMessage.setInt32(1, 10); + const intTenBytes = createArrayBuffer(0x0B, 0x08, 0x0A, 0x0C); + expect(accessor.serialize()).toEqual(intTenBytes); + }); + + it('serialize additions to subgroups made with getGroupOrNull', () => { + const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(intTwoBytes); + const mutableSubMessage = + accessor.getGroupOrNull(1, TestMessage.instanceCreator); + mutableSubMessage.setInt32(2, 3); + // Sub group contains the original field, plus the new one. + expect(accessor.serialize()) + .toEqual(createArrayBuffer(0x0B, 0x08, 0x02, 0x10, 0x03, 0x0C)); + }); + + it('fail with getGroupOrNull if immutable group exist in cache', () => { + const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(intTwoBytes); + + const readOnly = accessor.getGroup(1, TestMessage.instanceCreator); + if (CHECK_TYPE) { + expect(() => accessor.getGroupOrNull(1, TestMessage.instanceCreator)) + .toThrow(); + } else { + const mutableSubGropu = + accessor.getGroupOrNull(1, TestMessage.instanceCreator); + // The instance returned by getGroupOrNull is the exact same instance. + expect(mutableSubGropu).toBe(readOnly); + + // Serializing the subgroup does not write the changes + mutableSubGropu.setInt32(1, 0); + expect(accessor.serialize()).toEqual(intTwoBytes); + } + }); + + it('change hasFieldNumber after getGroupAttach', () => { + const accessor = Kernel.createEmpty(); + expect(accessor.hasFieldNumber(1)).toBe(false); + expect(accessor.getGroupAttach(1, TestMessage.instanceCreator)) + .not.toBe(null); + expect(accessor.hasFieldNumber(1)).toBe(true); + }); + + it('change hasFieldNumber after getGroupAttach when pivot is set', () => { + const accessor = Kernel.createEmpty(); + expect(accessor.hasFieldNumber(1)).toBe(false); + expect( + accessor.getGroupAttach(1, TestMessage.instanceCreator, /* pivot= */ 1)) + .not.toBe(null); + expect(accessor.hasFieldNumber(1)).toBe(true); + }); + + it('serialize subgroups made with getGroupAttach', () => { + const accessor = Kernel.createEmpty(); + const mutableSubGroup = + accessor.getGroupAttach(1, TestMessage.instanceCreator); + mutableSubGroup.setInt32(1, 10); + const intTenBytes = createArrayBuffer(0x0B, 0x08, 0x0A, 0x0C); + expect(accessor.serialize()).toEqual(intTenBytes); + }); + + it('serialize additions to subgroups using getMessageAttach', () => { + const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(intTwoBytes); + const mutableSubGroup = + accessor.getGroupAttach(1, TestMessage.instanceCreator); + mutableSubGroup.setInt32(2, 3); + // Sub message contains the original field, plus the new one. + expect(accessor.serialize()) + .toEqual(createArrayBuffer(0x0B, 0x08, 0x02, 0x10, 0x03, 0x0C)); + }); + + it('fail with getGroupAttach if immutable message exist in cache', () => { + const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(intTwoBytes); + + const readOnly = accessor.getGroup(1, TestMessage.instanceCreator); + if (CHECK_TYPE) { + expect(() => accessor.getGroupAttach(1, TestMessage.instanceCreator)) + .toThrow(); + } else { + const mutableSubGroup = + accessor.getGroupAttach(1, TestMessage.instanceCreator); + // The instance returned by getMessageOrNull is the exact same instance. + expect(mutableSubGroup).toBe(readOnly); + + // Serializing the submessage does not write the changes + mutableSubGroup.setInt32(1, 0); + expect(accessor.serialize()).toEqual(intTwoBytes); + } + }); + + it('read default group return empty group with getGroup', () => { + const bytes = new ArrayBuffer(0); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getGroup(1, TestMessage.instanceCreator)).toBeTruthy(); + expect(accessor.getGroup(1, TestMessage.instanceCreator).serialize()) + .toEqual(bytes); + }); + + it('read default group return null with getGroupOrNull', () => { + const bytes = new ArrayBuffer(0); + const accessor = Kernel.fromArrayBuffer(bytes); + expect(accessor.getGroupOrNull(1, TestMessage.instanceCreator)).toBe(null); + }); + + it('read group preserve reference equality', () => { + const bytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + const msg1 = accessor.getGroupOrNull(1, TestMessage.instanceCreator); + const msg2 = accessor.getGroupOrNull(1, TestMessage.instanceCreator); + const msg3 = accessor.getGroupAttach(1, TestMessage.instanceCreator); + expect(msg1).toBe(msg2); + expect(msg1).toBe(msg3); + }); + + it('fail when getting group with null instance constructor', () => { + const accessor = + Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x02, 0x08, 0x01)); + const nullMessage = /** @type {function(!Kernel):!TestMessage} */ + (/** @type {*} */ (null)); + expect(() => accessor.getGroupOrNull(1, nullMessage)).toThrow(); + }); + + it('fail when setting group value with null value', () => { + const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0)); + const fakeMessage = /** @type {!TestMessage} */ (/** @type {*} */ (null)); + if (CHECK_CRITICAL_TYPE) { + expect(() => accessor.setGroup(1, fakeMessage)) + .toThrowError('Given value is not a message instance: null'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + accessor.setMessage(1, fakeMessage); + expect(accessor.getGroupOrNull( + /* fieldNumber= */ 1, TestMessage.instanceCreator)) + .toBeNull(); + } + }); + + it('reads group in a longer buffer', () => { + const bytes = createArrayBuffer( + 0x12, 0x20, // 32 length delimited + 0x00, // random values for padding start + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, // random values for padding end + 0x0B, // Group tag + 0x08, 0x02, 0x0C); + const accessor = Kernel.fromArrayBuffer(bytes); + const msg1 = accessor.getGroupOrNull(1, TestMessage.instanceCreator); + const msg2 = accessor.getGroupOrNull(1, TestMessage.instanceCreator); + expect(msg1).toBe(msg2); + }); +}); diff --git a/js/experimental/runtime/kernel/message_set.js b/js/experimental/runtime/kernel/message_set.js new file mode 100644 index 0000000000000..d66bace7b5fd0 --- /dev/null +++ b/js/experimental/runtime/kernel/message_set.js @@ -0,0 +1,285 @@ +/* +########################################################## +# # +# __ __ _____ _ _ _____ _ _ _____ # +# \ \ / /\ | __ \| \ | |_ _| \ | |/ ____| # +# \ \ /\ / / \ | |__) | \| | | | | \| | | __ # +# \ \/ \/ / /\ \ | _ /| . ` | | | | . ` | | |_ | # +# \ /\ / ____ \| | \ \| |\ |_| |_| |\ | |__| | # +# \/ \/_/ \_\_| \_\_| \_|_____|_| \_|\_____| # +# # +# # +########################################################## +# Do not use this class in your code. This class purely # +# exists to make proto code generation easier. # +########################################################## +*/ +goog.module('protobuf.runtime.MessageSet'); + +const InternalMessage = goog.require('protobuf.binary.InternalMessage'); +const Kernel = goog.require('protobuf.runtime.Kernel'); + +// These are the tags for the old MessageSet format, which was defined as: +// message MessageSet { +// repeated group Item = 1 { +// required uint32 type_id = 2; +// optional bytes message = 3; +// } +// } +/** @const {number} */ +const MSET_GROUP_FIELD_NUMBER = 1; +/** @const {number} */ +const MSET_TYPE_ID_FIELD_NUMBER = 2; +/** @const {number} */ +const MSET_MESSAGE_FIELD_NUMBER = 3; + +/** + * @param {!Kernel} kernel + * @return {!Map} + */ +function createItemMap(kernel) { + const itemMap = new Map(); + let totalCount = 0; + for (const item of kernel.getRepeatedGroupIterable( + MSET_GROUP_FIELD_NUMBER, Item.fromKernel)) { + itemMap.set(item.getTypeId(), item); + totalCount++; + } + + // Normalize the entries. + if (totalCount > itemMap.size) { + writeItemMap(kernel, itemMap); + } + return itemMap; +} + +/** + * @param {!Kernel} kernel + * @param {!Map} itemMap + */ +function writeItemMap(kernel, itemMap) { + kernel.setRepeatedGroupIterable(MSET_GROUP_FIELD_NUMBER, itemMap.values()); +} + +/** + * @implements {InternalMessage} + * @final + */ +class MessageSet { + /** + * @param {!Kernel} kernel + * @return {!MessageSet} + */ + static fromKernel(kernel) { + const itemMap = createItemMap(kernel); + return new MessageSet(kernel, itemMap); + } + + /** + * @return {!MessageSet} + */ + static createEmpty() { + return MessageSet.fromKernel(Kernel.createEmpty()); + } + + /** + * @param {!Kernel} kernel + * @param {!Map} itemMap + * @private + */ + constructor(kernel, itemMap) { + /** @const {!Kernel} @private */ + this.kernel_ = kernel; + /** @const {!Map} @private */ + this.itemMap_ = itemMap; + } + + + + // code helpers for code gen + + /** + * @param {number} typeId + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {?T} + * @template T + */ + getMessageOrNull(typeId, instanceCreator, pivot) { + const item = this.itemMap_.get(typeId); + return item ? item.getMessageOrNull(instanceCreator, pivot) : null; + } + + /** + * @param {number} typeId + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {T} + * @template T + */ + getMessageAttach(typeId, instanceCreator, pivot) { + let item = this.itemMap_.get(typeId); + if (item) { + return item.getMessageAttach(instanceCreator, pivot); + } + const message = instanceCreator(Kernel.createEmpty()); + this.setMessage(typeId, message); + return message; + } + + /** + * @param {number} typeId + * @param {number=} pivot + * @return {?Kernel} + */ + getMessageAccessorOrNull(typeId, pivot) { + const item = this.itemMap_.get(typeId); + return item ? item.getMessageAccessorOrNull(pivot) : null; + } + + + /** + * @param {number} typeId + */ + clearMessage(typeId) { + if (this.itemMap_.delete(typeId)) { + writeItemMap(this.kernel_, this.itemMap_); + } + } + + /** + * @param {number} typeId + * @return {boolean} + */ + hasMessage(typeId) { + return this.itemMap_.has(typeId); + } + + /** + * @param {number} typeId + * @param {!InternalMessage} value + */ + setMessage(typeId, value) { + const item = this.itemMap_.get(typeId); + if (item) { + item.setMessage(value); + } else { + this.itemMap_.set(typeId, Item.create(typeId, value)); + writeItemMap(this.kernel_, this.itemMap_); + } + } + + /** + * @return {!Kernel} + * @override + */ + internalGetKernel() { + return this.kernel_; + } +} + +/** + * @implements {InternalMessage} + * @final + */ +class Item { + /** + * @param {number} typeId + * @param {!InternalMessage} message + * @return {!Item} + */ + static create(typeId, message) { + const messageSet = Item.fromKernel(Kernel.createEmpty()); + messageSet.setTypeId_(typeId); + messageSet.setMessage(message); + return messageSet; + } + + + /** + * @param {!Kernel} kernel + * @return {!Item} + */ + static fromKernel(kernel) { + return new Item(kernel); + } + + /** + * @param {!Kernel} kernel + * @private + */ + constructor(kernel) { + /** @const {!Kernel} @private */ + this.kernel_ = kernel; + } + + /** + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {T} + * @template T + */ + getMessage(instanceCreator, pivot) { + return this.kernel_.getMessage( + MSET_MESSAGE_FIELD_NUMBER, instanceCreator, pivot); + } + + /** + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {?T} + * @template T + */ + getMessageOrNull(instanceCreator, pivot) { + return this.kernel_.getMessageOrNull( + MSET_MESSAGE_FIELD_NUMBER, instanceCreator, pivot); + } + + /** + * @param {function(!Kernel):T} instanceCreator + * @param {number=} pivot + * @return {T} + * @template T + */ + getMessageAttach(instanceCreator, pivot) { + return this.kernel_.getMessageAttach( + MSET_MESSAGE_FIELD_NUMBER, instanceCreator, pivot); + } + + /** + * @param {number=} pivot + * @return {?Kernel} + */ + getMessageAccessorOrNull(pivot) { + return this.kernel_.getMessageAccessorOrNull( + MSET_MESSAGE_FIELD_NUMBER, pivot); + } + + /** @param {!InternalMessage} value */ + setMessage(value) { + this.kernel_.setMessage(MSET_MESSAGE_FIELD_NUMBER, value); + } + + /** @return {number} */ + getTypeId() { + return this.kernel_.getUint32WithDefault(MSET_TYPE_ID_FIELD_NUMBER); + } + + /** + * @param {number} value + * @private + */ + setTypeId_(value) { + this.kernel_.setUint32(MSET_TYPE_ID_FIELD_NUMBER, value); + } + + /** + * @return {!Kernel} + * @override + */ + internalGetKernel() { + return this.kernel_; + } +} + +exports = MessageSet; diff --git a/js/experimental/runtime/kernel/message_set_test.js b/js/experimental/runtime/kernel/message_set_test.js new file mode 100644 index 0000000000000..35e593501536f --- /dev/null +++ b/js/experimental/runtime/kernel/message_set_test.js @@ -0,0 +1,262 @@ +/** + * @fileoverview Tests for message_set.js. + */ +goog.module('protobuf.runtime.MessageSetTest'); + +goog.setTestOnly(); + +const Kernel = goog.require('protobuf.runtime.Kernel'); +const MessageSet = goog.require('protobuf.runtime.MessageSet'); +const TestMessage = goog.require('protobuf.testing.binary.TestMessage'); + +/** + * @param {...number} bytes + * @return {!ArrayBuffer} + */ +function createArrayBuffer(...bytes) { + return new Uint8Array(bytes).buffer; +} + +describe('MessageSet does', () => { + it('returns no messages for empty set', () => { + const messageSet = MessageSet.createEmpty(); + expect(messageSet.getMessageOrNull(12345, TestMessage.instanceCreator)) + .toBeNull(); + }); + + it('returns no kernel for empty set', () => { + const messageSet = MessageSet.createEmpty(); + expect(messageSet.getMessageAccessorOrNull(12345)).toBeNull(); + }); + + it('returns message that has been set', () => { + const messageSet = MessageSet.createEmpty(); + const message = TestMessage.createEmpty(); + messageSet.setMessage(12345, message); + expect(messageSet.getMessageOrNull(12345, TestMessage.instanceCreator)) + .toBe(message); + }); + + it('returns null for cleared message', () => { + const messageSet = MessageSet.createEmpty(); + const message = TestMessage.createEmpty(); + messageSet.setMessage(12345, message); + messageSet.clearMessage(12345); + expect(messageSet.getMessageAccessorOrNull(12345)).toBeNull(); + }); + + it('returns false for not present message', () => { + const messageSet = MessageSet.createEmpty(); + expect(messageSet.hasMessage(12345)).toBe(false); + }); + + it('returns true for present message', () => { + const messageSet = MessageSet.createEmpty(); + const message = TestMessage.createEmpty(); + messageSet.setMessage(12345, message); + expect(messageSet.hasMessage(12345)).toBe(true); + }); + + it('returns false for cleared message', () => { + const messageSet = MessageSet.createEmpty(); + const message = TestMessage.createEmpty(); + messageSet.setMessage(12345, message); + messageSet.clearMessage(12345); + expect(messageSet.hasMessage(12345)).toBe(false); + }); + + it('returns false for cleared message without it being present', () => { + const messageSet = MessageSet.createEmpty(); + messageSet.clearMessage(12345); + expect(messageSet.hasMessage(12345)).toBe(false); + }); + + const createMessageSet = () => { + const messageSet = MessageSet.createEmpty(); + const message = TestMessage.createEmpty(); + message.setInt32(1, 2); + messageSet.setMessage(12345, message); + + + const parsedKernel = + Kernel.fromArrayBuffer(messageSet.internalGetKernel().serialize()); + return MessageSet.fromKernel(parsedKernel); + }; + + it('pass through pivot for getMessageOrNull', () => { + const messageSet = createMessageSet(); + const message = + messageSet.getMessageOrNull(12345, TestMessage.instanceCreator, 2); + expect(message.internalGetKernel().getPivot()).toBe(2); + }); + + it('pass through pivot for getMessageAttach', () => { + const messageSet = createMessageSet(); + const message = + messageSet.getMessageAttach(12345, TestMessage.instanceCreator, 2); + expect(message.internalGetKernel().getPivot()).toBe(2); + }); + + it('pass through pivot for getMessageAccessorOrNull', () => { + const messageSet = createMessageSet(); + const kernel = messageSet.getMessageAccessorOrNull(12345, 2); + expect(kernel.getPivot()).toBe(2); + }); + + it('pick the last value in the stream', () => { + const arrayBuffer = createArrayBuffer( + 0x52, // Tag (field:10, length delimited) + 0x14, // Length of 20 bytes + 0x0B, // Start group fieldnumber 1 + 0x10, // Tag (field 2, varint) + 0xB9, // 12345 + 0x60, // 12345 + 0x1A, // Tag (field 3, length delimited) + 0x03, // length 3 + 0xA0, // Tag (fieldnumber 20, varint) + 0x01, // Tag (fieldnumber 20, varint) + 0x1E, // 30 + 0x0C, // Stop Group field number 1 + // second group + 0x0B, // Start group fieldnumber 1 + 0x10, // Tag (field 2, varint) + 0xB9, // 12345 + 0x60, // 12345 + 0x1A, // Tag (field 3, length delimited) + 0x03, // length 3 + 0xA0, // Tag (fieldnumber 20, varint) + 0x01, // Tag (fieldnumber 20, varint) + 0x01, // 1 + 0x0C // Stop Group field number 1 + ); + + const outerMessage = Kernel.fromArrayBuffer(arrayBuffer); + + const messageSet = outerMessage.getMessage(10, MessageSet.fromKernel); + + const message = + messageSet.getMessageOrNull(12345, TestMessage.instanceCreator); + expect(message.getInt32WithDefault(20)).toBe(1); + }); + + it('removes duplicates when read', () => { + const arrayBuffer = createArrayBuffer( + 0x52, // Tag (field:10, length delimited) + 0x14, // Length of 20 bytes + 0x0B, // Start group fieldnumber 1 + 0x10, // Tag (field 2, varint) + 0xB9, // 12345 + 0x60, // 12345 + 0x1A, // Tag (field 3, length delimited) + 0x03, // length 3 + 0xA0, // Tag (fieldnumber 20, varint) + 0x01, // Tag (fieldnumber 20, varint) + 0x1E, // 30 + 0x0C, // Stop Group field number 1 + // second group + 0x0B, // Start group fieldnumber 1 + 0x10, // Tag (field 2, varint) + 0xB9, // 12345 + 0x60, // 12345 + 0x1A, // Tag (field 3, length delimited) + 0x03, // length 3 + 0xA0, // Tag (fieldnumber 20, varint) + 0x01, // Tag (fieldnumber 20, varint) + 0x01, // 1 + 0x0C // Stop Group field number 1 + ); + + + const outerMessage = Kernel.fromArrayBuffer(arrayBuffer); + outerMessage.getMessageAttach(10, MessageSet.fromKernel); + + expect(outerMessage.serialize()) + .toEqual(createArrayBuffer( + 0x52, // Tag (field:10, length delimited) + 0x0A, // Length of 10 bytes + 0x0B, // Start group fieldnumber 1 + 0x10, // Tag (field 2, varint) + 0xB9, // 12345 + 0x60, // 12345 + 0x1A, // Tag (field 3, length delimited) + 0x03, // length 3 + 0xA0, // Tag (fieldnumber 20, varint) + 0x01, // Tag (fieldnumber 20, varint) + 0x01, // 1 + 0x0C // Stop Group field number 1 + )); + }); + + it('allow for large typeIds', () => { + const messageSet = MessageSet.createEmpty(); + const message = TestMessage.createEmpty(); + messageSet.setMessage(0xFFFFFFFE >>> 0, message); + expect(messageSet.hasMessage(0xFFFFFFFE >>> 0)).toBe(true); + }); +}); + +describe('Optional MessageSet does', () => { + // message Bar { + // optional MessageSet mset = 10; + //} + // + // message Foo { + // extend proto2.bridge.MessageSet { + // optional Foo message_set_extension = 12345; + // } + // optional int32 f20 = 20; + //} + + it('encode as a field', () => { + const fooMessage = Kernel.createEmpty(); + fooMessage.setInt32(20, 30); + + const messageSet = MessageSet.createEmpty(); + messageSet.setMessage(12345, TestMessage.instanceCreator(fooMessage)); + + const barMessage = Kernel.createEmpty(); + barMessage.setMessage(10, messageSet); + + expect(barMessage.serialize()) + .toEqual(createArrayBuffer( + 0x52, // Tag (field:10, length delimited) + 0x0A, // Length of 10 bytes + 0x0B, // Start group fieldnumber 1 + 0x10, // Tag (field 2, varint) + 0xB9, // 12345 + 0x60, // 12345 + 0x1A, // Tag (field 3, length delimited) + 0x03, // length 3 + 0xA0, // Tag (fieldnumber 20, varint) + 0x01, // Tag (fieldnumber 20, varint) + 0x1E, // 30 + 0x0C // Stop Group field number 1 + )); + }); + + it('deserializes', () => { + const fooMessage = Kernel.createEmpty(); + fooMessage.setInt32(20, 30); + + const messageSet = MessageSet.createEmpty(); + messageSet.setMessage(12345, TestMessage.instanceCreator(fooMessage)); + + + const barMessage = Kernel.createEmpty(); + barMessage.setMessage(10, messageSet); + + const arrayBuffer = barMessage.serialize(); + + const barMessageParsed = Kernel.fromArrayBuffer(arrayBuffer); + expect(barMessageParsed.hasFieldNumber(10)).toBe(true); + + const messageSetParsed = + barMessageParsed.getMessage(10, MessageSet.fromKernel); + + const fooMessageParsed = + messageSetParsed.getMessageOrNull(12345, TestMessage.instanceCreator) + .internalGetKernel(); + + expect(fooMessageParsed.getInt32WithDefault(20)).toBe(30); + }); +}); diff --git a/js/experimental/runtime/kernel/packed_bool_test_pairs.js b/js/experimental/runtime/kernel/packed_bool_test_pairs.js new file mode 100644 index 0000000000000..e8dd2f4b65e4d --- /dev/null +++ b/js/experimental/runtime/kernel/packed_bool_test_pairs.js @@ -0,0 +1,59 @@ +goog.module('protobuf.binary.packedBoolTestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of packed bool values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, boolValues: !Array, + * bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>} + */ +function getPackedBoolPairs() { + return [ + { + name: 'empty value', + boolValues: [], + bufferDecoder: createBufferDecoder(0x00), + skip_writer: true, + }, + { + name: 'single value', + boolValues: [true], + bufferDecoder: createBufferDecoder(0x01, 0x01), + }, + { + name: 'single multi-bytes value', + boolValues: [true], + bufferDecoder: createBufferDecoder(0x02, 0x80, 0x01), + skip_writer: true, + }, + { + name: 'multiple values', + boolValues: [true, false], + bufferDecoder: createBufferDecoder(0x02, 0x01, 0x00), + }, + { + name: 'multiple multi-bytes values', + boolValues: [true, false], + bufferDecoder: createBufferDecoder( + 0x0C, // length + 0x80, + 0x80, + 0x80, + 0x80, + 0x80, + 0x01, // true + 0x80, + 0x80, + 0x80, + 0x80, + 0x80, + 0x00, // false + ), + skip_writer: true, + }, + ]; +} + +exports = {getPackedBoolPairs}; diff --git a/js/experimental/runtime/kernel/packed_double_test_pairs.js b/js/experimental/runtime/kernel/packed_double_test_pairs.js new file mode 100644 index 0000000000000..de2cb5510ef35 --- /dev/null +++ b/js/experimental/runtime/kernel/packed_double_test_pairs.js @@ -0,0 +1,52 @@ +goog.module('protobuf.binary.packedDoubleTestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of packed double values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, doubleValues: !Array, + * bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>} + */ +function getPackedDoublePairs() { + return [ + { + name: 'empty value', + doubleValues: [], + bufferDecoder: createBufferDecoder(0x00), + skip_writer: true, + }, + { + name: 'single value', + doubleValues: [1], + bufferDecoder: createBufferDecoder( + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F), + }, + { + name: 'multiple values', + doubleValues: [1, 0], + bufferDecoder: createBufferDecoder( + 0x10, // length + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xF0, + 0x3F, // 1 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // 0 + ), + }, + ]; +} + +exports = {getPackedDoublePairs}; diff --git a/js/experimental/runtime/kernel/packed_fixed32_test_pairs.js b/js/experimental/runtime/kernel/packed_fixed32_test_pairs.js new file mode 100644 index 0000000000000..5c8a54d1eb2ed --- /dev/null +++ b/js/experimental/runtime/kernel/packed_fixed32_test_pairs.js @@ -0,0 +1,34 @@ +goog.module('protobuf.binary.packedFixed32TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of packed fixed32 values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, fixed32Values: !Array, + * bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>} + */ +function getPackedFixed32Pairs() { + return [ + { + name: 'empty value', + fixed32Values: [], + bufferDecoder: createBufferDecoder(0x00), + skip_writer: true, + }, + { + name: 'single value', + fixed32Values: [1], + bufferDecoder: createBufferDecoder(0x04, 0x01, 0x00, 0x00, 0x00), + }, + { + name: 'multiple values', + fixed32Values: [1, 0], + bufferDecoder: createBufferDecoder( + 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + }, + ]; +} + +exports = {getPackedFixed32Pairs}; diff --git a/js/experimental/runtime/kernel/packed_float_test_pairs.js b/js/experimental/runtime/kernel/packed_float_test_pairs.js new file mode 100644 index 0000000000000..6d1204664d66d --- /dev/null +++ b/js/experimental/runtime/kernel/packed_float_test_pairs.js @@ -0,0 +1,34 @@ +goog.module('protobuf.binary.packedFloatTestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of packed float values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, floatValues: !Array, + * bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>} + */ +function getPackedFloatPairs() { + return [ + { + name: 'empty value', + floatValues: [], + bufferDecoder: createBufferDecoder(0x00), + skip_writer: true, + }, + { + name: 'single value', + floatValues: [1], + bufferDecoder: createBufferDecoder(0x04, 0x00, 0x00, 0x80, 0x3F), + }, + { + name: 'multiple values', + floatValues: [1, 0], + bufferDecoder: createBufferDecoder( + 0x08, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00), + }, + ]; +} + +exports = {getPackedFloatPairs}; diff --git a/js/experimental/runtime/kernel/packed_int32_test_pairs.js b/js/experimental/runtime/kernel/packed_int32_test_pairs.js new file mode 100644 index 0000000000000..fbe5f40fbe42b --- /dev/null +++ b/js/experimental/runtime/kernel/packed_int32_test_pairs.js @@ -0,0 +1,33 @@ +goog.module('protobuf.binary.packedInt32TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of packed int32 values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, int32Values: !Array, + * bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>} + */ +function getPackedInt32Pairs() { + return [ + { + name: 'empty value', + int32Values: [], + bufferDecoder: createBufferDecoder(0x00), + skip_writer: true, + }, + { + name: 'single value', + int32Values: [1], + bufferDecoder: createBufferDecoder(0x01, 0x01), + }, + { + name: 'multiple values', + int32Values: [1, 0], + bufferDecoder: createBufferDecoder(0x02, 0x01, 0x00), + }, + ]; +} + +exports = {getPackedInt32Pairs}; diff --git a/js/experimental/runtime/kernel/packed_int64_test_pairs.js b/js/experimental/runtime/kernel/packed_int64_test_pairs.js new file mode 100644 index 0000000000000..a6cf54e3c523b --- /dev/null +++ b/js/experimental/runtime/kernel/packed_int64_test_pairs.js @@ -0,0 +1,34 @@ +goog.module('protobuf.binary.packedInt64TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const Int64 = goog.require('protobuf.Int64'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of packed int64 values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, int64Values: !Array, + * bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>} + */ +function getPackedInt64Pairs() { + return [ + { + name: 'empty value', + int64Values: [], + bufferDecoder: createBufferDecoder(0x00), + skip_writer: true, + }, + { + name: 'single value', + int64Values: [Int64.fromInt(1)], + bufferDecoder: createBufferDecoder(0x01, 0x01), + }, + { + name: 'multiple values', + int64Values: [Int64.fromInt(1), Int64.fromInt(0)], + bufferDecoder: createBufferDecoder(0x02, 0x01, 0x00), + }, + ]; +} + +exports = {getPackedInt64Pairs}; diff --git a/js/experimental/runtime/kernel/packed_sfixed32_test_pairs.js b/js/experimental/runtime/kernel/packed_sfixed32_test_pairs.js new file mode 100644 index 0000000000000..d6daa79643bbf --- /dev/null +++ b/js/experimental/runtime/kernel/packed_sfixed32_test_pairs.js @@ -0,0 +1,34 @@ +goog.module('protobuf.binary.packedSfixed32TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of packed sfixed32 values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, sfixed32Values: !Array, + * bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>} + */ +function getPackedSfixed32Pairs() { + return [ + { + name: 'empty value', + sfixed32Values: [], + bufferDecoder: createBufferDecoder(0x00), + skip_writer: true, + }, + { + name: 'single value', + sfixed32Values: [1], + bufferDecoder: createBufferDecoder(0x04, 0x01, 0x00, 0x00, 0x00), + }, + { + name: 'multiple values', + sfixed32Values: [1, 0], + bufferDecoder: createBufferDecoder( + 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + }, + ]; +} + +exports = {getPackedSfixed32Pairs}; diff --git a/js/experimental/runtime/kernel/packed_sfixed64_test_pairs.js b/js/experimental/runtime/kernel/packed_sfixed64_test_pairs.js new file mode 100644 index 0000000000000..5b86703665c8c --- /dev/null +++ b/js/experimental/runtime/kernel/packed_sfixed64_test_pairs.js @@ -0,0 +1,53 @@ +goog.module('protobuf.binary.packedSfixed64TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const Int64 = goog.require('protobuf.Int64'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of packed sfixed64 values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, sfixed64Values: !Array, + * bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>} + */ +function getPackedSfixed64Pairs() { + return [ + { + name: 'empty value', + sfixed64Values: [], + bufferDecoder: createBufferDecoder(0x00), + skip_writer: true, + }, + { + name: 'single value', + sfixed64Values: [Int64.fromInt(1)], + bufferDecoder: createBufferDecoder( + 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + }, + { + name: 'multiple values', + sfixed64Values: [Int64.fromInt(1), Int64.fromInt(0)], + bufferDecoder: createBufferDecoder( + 0x10, // length + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // 1 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // 2 + ), + }, + ]; +} + +exports = {getPackedSfixed64Pairs}; diff --git a/js/experimental/runtime/kernel/packed_sint32_test_pairs.js b/js/experimental/runtime/kernel/packed_sint32_test_pairs.js new file mode 100644 index 0000000000000..314ac11fe94f5 --- /dev/null +++ b/js/experimental/runtime/kernel/packed_sint32_test_pairs.js @@ -0,0 +1,33 @@ +goog.module('protobuf.binary.packedSint32TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of packed sint32 values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, sint32Values: !Array, + * bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>} + */ +function getPackedSint32Pairs() { + return [ + { + name: 'empty value', + sint32Values: [], + bufferDecoder: createBufferDecoder(0x00), + skip_writer: true, + }, + { + name: 'single value', + sint32Values: [-1], + bufferDecoder: createBufferDecoder(0x01, 0x01), + }, + { + name: 'multiple values', + sint32Values: [-1, 0], + bufferDecoder: createBufferDecoder(0x02, 0x01, 0x00), + }, + ]; +} + +exports = {getPackedSint32Pairs}; diff --git a/js/experimental/runtime/kernel/packed_sint64_test_pairs.js b/js/experimental/runtime/kernel/packed_sint64_test_pairs.js new file mode 100644 index 0000000000000..c8730227853c1 --- /dev/null +++ b/js/experimental/runtime/kernel/packed_sint64_test_pairs.js @@ -0,0 +1,34 @@ +goog.module('protobuf.binary.packedSint64TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const Int64 = goog.require('protobuf.Int64'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of packed sint64 values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, sint64Values: !Array, + * bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>} + */ +function getPackedSint64Pairs() { + return [ + { + name: 'empty value', + sint64Values: [], + bufferDecoder: createBufferDecoder(0x00), + skip_writer: true, + }, + { + name: 'single value', + sint64Values: [Int64.fromInt(-1)], + bufferDecoder: createBufferDecoder(0x01, 0x01), + }, + { + name: 'multiple values', + sint64Values: [Int64.fromInt(-1), Int64.fromInt(0)], + bufferDecoder: createBufferDecoder(0x02, 0x01, 0x00), + }, + ]; +} + +exports = {getPackedSint64Pairs}; diff --git a/js/experimental/runtime/kernel/packed_uint32_test_pairs.js b/js/experimental/runtime/kernel/packed_uint32_test_pairs.js new file mode 100644 index 0000000000000..34fbbdfed3797 --- /dev/null +++ b/js/experimental/runtime/kernel/packed_uint32_test_pairs.js @@ -0,0 +1,33 @@ +goog.module('protobuf.binary.packedUint32TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of packed uint32 values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, uint32Values: !Array, + * bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>} + */ +function getPackedUint32Pairs() { + return [ + { + name: 'empty value', + uint32Values: [], + bufferDecoder: createBufferDecoder(0x00), + skip_writer: true, + }, + { + name: 'single value', + uint32Values: [1], + bufferDecoder: createBufferDecoder(0x01, 0x01), + }, + { + name: 'multiple values', + uint32Values: [1, 0], + bufferDecoder: createBufferDecoder(0x02, 0x01, 0x00), + }, + ]; +} + +exports = {getPackedUint32Pairs}; diff --git a/js/experimental/runtime/kernel/reader.js b/js/experimental/runtime/kernel/reader.js new file mode 100644 index 0000000000000..2b80e15bffa63 --- /dev/null +++ b/js/experimental/runtime/kernel/reader.js @@ -0,0 +1,366 @@ +/** + * @fileoverview Helper methods for reading data from the binary wire format. + */ +goog.module('protobuf.binary.reader'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const ByteString = goog.require('protobuf.ByteString'); +const Int64 = goog.require('protobuf.Int64'); +const {checkState} = goog.require('protobuf.internal.checks'); + + +/****************************************************************************** + * OPTIONAL FUNCTIONS + ******************************************************************************/ + +/** + * Reads a boolean value from the binary bytes. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {boolean} + * @package + */ +function readBool(bufferDecoder, start) { + const {lowBits, highBits} = bufferDecoder.getVarint(start); + return lowBits !== 0 || highBits !== 0; +} + +/** + * Reads a ByteString value from the binary bytes. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!ByteString} + * @package + */ +function readBytes(bufferDecoder, start) { + return readDelimited(bufferDecoder, start).asByteString(); +} + +/** + * Reads a int32 value from the binary bytes encoded as varint. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {number} + * @package + */ +function readInt32(bufferDecoder, start) { + // Negative 32 bit integers are encoded with 64 bit values. + // Clients are expected to truncate back to 32 bits. + // This is why we are dropping the upper bytes here. + return bufferDecoder.getUnsignedVarint32At(start) | 0; +} + +/** + * Reads a int32 value from the binary bytes encoded as varint. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!Int64} + * @package + */ +function readInt64(bufferDecoder, start) { + const {lowBits, highBits} = bufferDecoder.getVarint(start); + return Int64.fromBits(lowBits, highBits); +} + +/** + * Reads a fixed int32 value from the binary bytes. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {number} + * @package + */ +function readFixed32(bufferDecoder, start) { + return bufferDecoder.getUint32(start); +} + +/** + * Reads a float value from the binary bytes. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {number} + * @package + */ +function readFloat(bufferDecoder, start) { + return bufferDecoder.getFloat32(start); +} + +/** + * Reads a fixed int64 value from the binary bytes. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!Int64} + * @package + */ +function readSfixed64(bufferDecoder, start) { + const lowBits = bufferDecoder.getInt32(start); + const highBits = bufferDecoder.getInt32(start + 4); + return Int64.fromBits(lowBits, highBits); +} + +/** + * Reads a sint32 value from the binary bytes encoded as varint. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {number} + * @package + */ +function readSint32(bufferDecoder, start) { + const bits = bufferDecoder.getUnsignedVarint32At(start); + // Truncate upper bits and convert from zig zag to signd int + return (bits >>> 1) ^ -(bits & 0x01); +} + +/** + * Reads a sint64 value from the binary bytes encoded as varint. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!Int64} + * @package + */ +function readSint64(bufferDecoder, start) { + const {lowBits, highBits} = bufferDecoder.getVarint(start); + const sign = -(lowBits & 0x01); + const decodedLowerBits = ((lowBits >>> 1) | (highBits & 0x01) << 31) ^ sign; + const decodedUpperBits = (highBits >>> 1) ^ sign; + return Int64.fromBits(decodedLowerBits, decodedUpperBits); +} + +/** + * Read a subarray of bytes representing a length delimited field. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!BufferDecoder} + * @package + */ +function readDelimited(bufferDecoder, start) { + const unsignedLength = bufferDecoder.getUnsignedVarint32At(start); + return bufferDecoder.subBufferDecoder(bufferDecoder.cursor(), unsignedLength); +} + +/** + * Reads a string value from the binary bytes. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {string} + * @package + */ +function readString(bufferDecoder, start) { + return readDelimited(bufferDecoder, start).asString(); +} + +/** + * Reads a uint32 value from the binary bytes encoded as varint. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {number} + * @package + */ +function readUint32(bufferDecoder, start) { + return bufferDecoder.getUnsignedVarint32At(start); +} + +/** + * Reads a double value from the binary bytes. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {number} + * @package + */ +function readDouble(bufferDecoder, start) { + return bufferDecoder.getFloat64(start); +} + +/** + * Reads a fixed int32 value from the binary bytes. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {number} + * @package + */ +function readSfixed32(bufferDecoder, start) { + return bufferDecoder.getInt32(start); +} + +/****************************************************************************** + * REPEATED FUNCTIONS + ******************************************************************************/ + +/** + * Reads a packed bool field, which consists of a length header and a list of + * unsigned varints. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!Array} + * @package + */ +function readPackedBool(bufferDecoder, start) { + return readPacked(bufferDecoder, start, readBool); +} + +/** + * Reads a packed double field, which consists of a length header and a list of + * fixed64. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!Array} + * @package + */ +function readPackedDouble(bufferDecoder, start) { + return readPacked(bufferDecoder, start, readDouble); +} + +/** + * Reads a packed fixed32 field, which consists of a length header and a list of + * fixed32. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!Array} + * @package + */ +function readPackedFixed32(bufferDecoder, start) { + return readPacked(bufferDecoder, start, readFixed32); +} + +/** + * Reads a packed float field, which consists of a length header and a list of + * fixed64. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!Array} + * @package + */ +function readPackedFloat(bufferDecoder, start) { + return readPacked(bufferDecoder, start, readFloat); +} + +/** + * Reads a packed int32 field, which consists of a length header and a list of + * varint. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!Array} + * @package + */ +function readPackedInt32(bufferDecoder, start) { + return readPacked(bufferDecoder, start, readInt32); +} + +/** + * Reads a packed int64 field, which consists of a length header and a list + * of int64. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!Array} + * @package + */ +function readPackedInt64(bufferDecoder, start) { + return readPacked(bufferDecoder, start, readInt64); +} + +/** + * Reads a packed sfixed32 field, which consists of a length header and a list + * of sfixed32. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!Array} + * @package + */ +function readPackedSfixed32(bufferDecoder, start) { + return readPacked(bufferDecoder, start, readSfixed32); +} + +/** + * Reads a packed sfixed64 field, which consists of a length header and a list + * of sfixed64. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!Array} + * @package + */ +function readPackedSfixed64(bufferDecoder, start) { + return readPacked(bufferDecoder, start, readSfixed64); +} + +/** + * Reads a packed sint32 field, which consists of a length header and a list of + * varint. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!Array} + * @package + */ +function readPackedSint32(bufferDecoder, start) { + return readPacked(bufferDecoder, start, readSint32); +} + +/** + * Reads a packed sint64 field, which consists of a length header and a list + * of sint64. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!Array} + * @package + */ +function readPackedSint64(bufferDecoder, start) { + return readPacked(bufferDecoder, start, readSint64); +} + +/** + * Reads a packed uint32 field, which consists of a length header and a list of + * varint. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @return {!Array} + * @package + */ +function readPackedUint32(bufferDecoder, start) { + return readPacked(bufferDecoder, start, readUint32); +} + +/** + * Read packed values. + * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes. + * @param {number} start Start of the data. + * @param {function(!BufferDecoder, number):T} valueFunction + * @return {!Array} + * @package + * @template T + */ +function readPacked(bufferDecoder, start, valueFunction) { + const /** !Array */ result = []; + const unsignedLength = bufferDecoder.getUnsignedVarint32At(start); + const dataStart = bufferDecoder.cursor(); + while (bufferDecoder.cursor() < dataStart + unsignedLength) { + checkState(bufferDecoder.cursor() > 0); + result.push(valueFunction(bufferDecoder, bufferDecoder.cursor())); + } + return result; +} + +exports = { + readBool, + readBytes, + readDelimited, + readDouble, + readFixed32, + readFloat, + readInt32, + readInt64, + readSint32, + readSint64, + readSfixed32, + readSfixed64, + readString, + readUint32, + readPackedBool, + readPackedDouble, + readPackedFixed32, + readPackedFloat, + readPackedInt32, + readPackedInt64, + readPackedSfixed32, + readPackedSfixed64, + readPackedSint32, + readPackedSint64, + readPackedUint32, +}; diff --git a/js/experimental/runtime/kernel/reader_test.js b/js/experimental/runtime/kernel/reader_test.js new file mode 100644 index 0000000000000..100c7937a2243 --- /dev/null +++ b/js/experimental/runtime/kernel/reader_test.js @@ -0,0 +1,425 @@ +/** + * @fileoverview Tests for reader.js. + */ +goog.module('protobuf.binary.ReaderTest'); + +goog.setTestOnly(); + +// Note to the reader: +// Since the reader behavior changes with the checking level some of the +// tests in this file have to know which checking level is enable to make +// correct assertions. +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const ByteString = goog.require('protobuf.ByteString'); +const reader = goog.require('protobuf.binary.reader'); +const {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); +const {encode} = goog.require('protobuf.binary.textencoding'); +const {getBoolPairs} = goog.require('protobuf.binary.boolTestPairs'); +const {getDoublePairs} = goog.require('protobuf.binary.doubleTestPairs'); +const {getFixed32Pairs} = goog.require('protobuf.binary.fixed32TestPairs'); +const {getFloatPairs} = goog.require('protobuf.binary.floatTestPairs'); +const {getInt32Pairs} = goog.require('protobuf.binary.int32TestPairs'); +const {getInt64Pairs} = goog.require('protobuf.binary.int64TestPairs'); +const {getPackedBoolPairs} = goog.require('protobuf.binary.packedBoolTestPairs'); +const {getPackedDoublePairs} = goog.require('protobuf.binary.packedDoubleTestPairs'); +const {getPackedFixed32Pairs} = goog.require('protobuf.binary.packedFixed32TestPairs'); +const {getPackedFloatPairs} = goog.require('protobuf.binary.packedFloatTestPairs'); +const {getPackedInt32Pairs} = goog.require('protobuf.binary.packedInt32TestPairs'); +const {getPackedInt64Pairs} = goog.require('protobuf.binary.packedInt64TestPairs'); +const {getPackedSfixed32Pairs} = goog.require('protobuf.binary.packedSfixed32TestPairs'); +const {getPackedSfixed64Pairs} = goog.require('protobuf.binary.packedSfixed64TestPairs'); +const {getPackedSint32Pairs} = goog.require('protobuf.binary.packedSint32TestPairs'); +const {getPackedSint64Pairs} = goog.require('protobuf.binary.packedSint64TestPairs'); +const {getPackedUint32Pairs} = goog.require('protobuf.binary.packedUint32TestPairs'); +const {getSfixed32Pairs} = goog.require('protobuf.binary.sfixed32TestPairs'); +const {getSfixed64Pairs} = goog.require('protobuf.binary.sfixed64TestPairs'); +const {getSint32Pairs} = goog.require('protobuf.binary.sint32TestPairs'); +const {getSint64Pairs} = goog.require('protobuf.binary.sint64TestPairs'); +const {getUint32Pairs} = goog.require('protobuf.binary.uint32TestPairs'); + +/****************************************************************************** + * Optional FUNCTIONS + ******************************************************************************/ + +describe('Read bool does', () => { + for (const pair of getBoolPairs()) { + it(`decode ${pair.name}`, () => { + if (pair.error && CHECK_CRITICAL_STATE) { + expect(() => reader.readBool(pair.bufferDecoder, 0)).toThrow(); + } else { + const d = reader.readBool( + pair.bufferDecoder, pair.bufferDecoder.startIndex()); + expect(d).toEqual(pair.boolValue); + } + }); + } +}); + +describe('readBytes does', () => { + it('throw exception if data is too short', () => { + const bufferDecoder = createBufferDecoder(); + expect(() => reader.readBytes(bufferDecoder, 0)).toThrow(); + }); + + it('read bytes by index', () => { + const bufferDecoder = createBufferDecoder(3, 1, 2, 3); + const byteString = reader.readBytes(bufferDecoder, 0); + expect(ByteString.fromArrayBuffer(new Uint8Array([1, 2, 3]).buffer)) + .toEqual(byteString); + }); +}); + +describe('readDouble does', () => { + it('throw exception if data is too short', () => { + const bufferDecoder = createBufferDecoder(); + expect(() => reader.readDouble(bufferDecoder, 0)).toThrow(); + }); + + for (const pair of getDoublePairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readDouble(pair.bufferDecoder, 0); + expect(d).toEqual(pair.doubleValue); + }); + } +}); + +describe('readFixed32 does', () => { + it('throw exception if data is too short', () => { + const bufferDecoder = createBufferDecoder(); + expect(() => reader.readFixed32(bufferDecoder, 0)).toThrow(); + }); + + for (const pair of getFixed32Pairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readFixed32(pair.bufferDecoder, 0); + expect(d).toEqual(pair.intValue); + }); + } +}); + +describe('readFloat does', () => { + it('throw exception if data is too short', () => { + const bufferDecoder = createBufferDecoder(); + expect(() => reader.readFloat(bufferDecoder, 0)).toThrow(); + }); + + for (const pair of getFloatPairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readFloat(pair.bufferDecoder, 0); + expect(d).toEqual(Math.fround(pair.floatValue)); + }); + } +}); + +describe('readInt32 does', () => { + it('throw exception if data is too short', () => { + const bufferDecoder = createBufferDecoder(0x80); + expect(() => reader.readInt32(bufferDecoder, 0)).toThrow(); + }); + + for (const pair of getInt32Pairs()) { + it(`decode ${pair.name}`, () => { + if (pair.error && CHECK_CRITICAL_STATE) { + expect(() => reader.readInt32(pair.bufferDecoder, 0)).toThrow(); + } else { + const d = reader.readInt32(pair.bufferDecoder, 0); + expect(d).toEqual(pair.intValue); + } + }); + } +}); + +describe('readSfixed32 does', () => { + it('throw exception if data is too short', () => { + const bufferDecoder = createBufferDecoder(0x80); + expect(() => reader.readSfixed32(bufferDecoder, 0)).toThrow(); + }); + + for (const pair of getSfixed32Pairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readSfixed32(pair.bufferDecoder, 0); + expect(d).toEqual(pair.intValue); + }); + } +}); + +describe('readSfixed64 does', () => { + it('throw exception if data is too short', () => { + const bufferDecoder = createBufferDecoder(0x80); + expect(() => reader.readSfixed64(bufferDecoder, 0)).toThrow(); + }); + + for (const pair of getSfixed64Pairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readSfixed64(pair.bufferDecoder, 0); + expect(d).toEqual(pair.longValue); + }); + } +}); + +describe('readSint32 does', () => { + it('throw exception if data is too short', () => { + const bufferDecoder = createBufferDecoder(0x80); + expect(() => reader.readSint32(bufferDecoder, 0)).toThrow(); + }); + + for (const pair of getSint32Pairs()) { + it(`decode ${pair.name}`, () => { + if (pair.error && CHECK_CRITICAL_STATE) { + expect(() => reader.readSint32(pair.bufferDecoder, 0)).toThrow(); + } else { + const d = reader.readSint32(pair.bufferDecoder, 0); + expect(d).toEqual(pair.intValue); + } + }); + } +}); + +describe('readInt64 does', () => { + it('throw exception if data is too short', () => { + const bufferDecoder = createBufferDecoder(0x80); + expect(() => reader.readInt64(bufferDecoder, 0)).toThrow(); + }); + + for (const pair of getInt64Pairs()) { + it(`decode ${pair.name}`, () => { + if (pair.error && CHECK_CRITICAL_STATE) { + expect(() => reader.readInt64(pair.bufferDecoder, 0)).toThrow(); + } else { + const d = reader.readInt64(pair.bufferDecoder, 0); + expect(d).toEqual(pair.longValue); + } + }); + } +}); + +describe('readSint64 does', () => { + it('throw exception if data is too short', () => { + const bufferDecoder = createBufferDecoder(0x80); + expect(() => reader.readSint64(bufferDecoder, 0)).toThrow(); + }); + + for (const pair of getSint64Pairs()) { + it(`decode ${pair.name}`, () => { + if (pair.error && CHECK_CRITICAL_STATE) { + expect(() => reader.readSint64(pair.bufferDecoder, 0)).toThrow(); + } else { + const d = reader.readSint64(pair.bufferDecoder, 0); + expect(d).toEqual(pair.longValue); + } + }); + } +}); + +describe('readUint32 does', () => { + it('throw exception if data is too short', () => { + const bufferDecoder = createBufferDecoder(0x80); + expect(() => reader.readUint32(bufferDecoder, 0)).toThrow(); + }); + + for (const pair of getUint32Pairs()) { + if (!pair.skip_reader) { + it(`decode ${pair.name}`, () => { + if (pair.error && CHECK_CRITICAL_STATE) { + expect(() => reader.readUint32(pair.bufferDecoder, 0)).toThrow(); + } else { + const d = reader.readUint32(pair.bufferDecoder, 0); + expect(d).toEqual(pair.intValue); + } + }); + } + } +}); + +/** + * + * @param {string} s + * @return {!Uint8Array} + */ +function encodeString(s) { + if (typeof TextEncoder !== 'undefined') { + const textEncoder = new TextEncoder('utf-8'); + return textEncoder.encode(s); + } else { + return encode(s); + } +} + +/** @param {string} s */ +function expectEncodedStringToMatch(s) { + const array = encodeString(s); + const length = array.length; + if (length > 127) { + throw new Error('Test only works for strings shorter than 128'); + } + const encodedArray = new Uint8Array(length + 1); + encodedArray[0] = length; + encodedArray.set(array, 1); + const bufferDecoder = BufferDecoder.fromArrayBuffer(encodedArray.buffer); + expect(reader.readString(bufferDecoder, 0)).toEqual(s); +} + +describe('readString does', () => { + it('return empty string for zero length string', () => { + const s = reader.readString(createBufferDecoder(0x00), 0); + expect(s).toEqual(''); + }); + + it('decode random strings', () => { + // 1 byte strings + expectEncodedStringToMatch('hello'); + expectEncodedStringToMatch('HELLO1!'); + + // 2 byte String + expectEncodedStringToMatch('©'); + + // 3 byte string + expectEncodedStringToMatch('❄'); + + // 4 byte string + expectEncodedStringToMatch('😁'); + }); + + it('decode 1 byte strings', () => { + for (let i = 0; i < 0x80; i++) { + const s = String.fromCharCode(i); + expectEncodedStringToMatch(s); + } + }); + + it('decode 2 byte strings', () => { + for (let i = 0xC0; i < 0x7FF; i++) { + const s = String.fromCharCode(i); + expectEncodedStringToMatch(s); + } + }); + + it('decode 3 byte strings', () => { + for (let i = 0x7FF; i < 0x8FFF; i++) { + const s = String.fromCharCode(i); + expectEncodedStringToMatch(s); + } + }); + + it('throw exception on invalid bytes', () => { + // This test will only succeed with the native TextDecoder since + // our polyfill does not do any validation. IE10 and IE11 don't support + // TextDecoder. + // TODO: Remove this check once we no longer need to support IE + if (typeof TextDecoder !== 'undefined') { + expect( + () => reader.readString( + createBufferDecoder(0x01, /* invalid utf data point*/ 0xFF), 0)) + .toThrow(); + } + }); + + it('throw exception if data is too short', () => { + const array = createBufferDecoder(0x02, '?'.charCodeAt(0)); + expect(() => reader.readString(array, 0)).toThrow(); + }); +}); + +/****************************************************************************** + * REPEATED FUNCTIONS + ******************************************************************************/ + +describe('readPackedBool does', () => { + for (const pair of getPackedBoolPairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readPackedBool(pair.bufferDecoder, 0); + expect(d).toEqual(pair.boolValues); + }); + } +}); + +describe('readPackedDouble does', () => { + for (const pair of getPackedDoublePairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readPackedDouble(pair.bufferDecoder, 0); + expect(d).toEqual(pair.doubleValues); + }); + } +}); + +describe('readPackedFixed32 does', () => { + for (const pair of getPackedFixed32Pairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readPackedFixed32(pair.bufferDecoder, 0); + expect(d).toEqual(pair.fixed32Values); + }); + } +}); + +describe('readPackedFloat does', () => { + for (const pair of getPackedFloatPairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readPackedFloat(pair.bufferDecoder, 0); + expect(d).toEqual(pair.floatValues); + }); + } +}); + +describe('readPackedInt32 does', () => { + for (const pair of getPackedInt32Pairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readPackedInt32(pair.bufferDecoder, 0); + expect(d).toEqual(pair.int32Values); + }); + } +}); + +describe('readPackedInt64 does', () => { + for (const pair of getPackedInt64Pairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readPackedInt64(pair.bufferDecoder, 0); + expect(d).toEqual(pair.int64Values); + }); + } +}); + +describe('readPackedSfixed32 does', () => { + for (const pair of getPackedSfixed32Pairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readPackedSfixed32(pair.bufferDecoder, 0); + expect(d).toEqual(pair.sfixed32Values); + }); + } +}); + +describe('readPackedSfixed64 does', () => { + for (const pair of getPackedSfixed64Pairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readPackedSfixed64(pair.bufferDecoder, 0); + expect(d).toEqual(pair.sfixed64Values); + }); + } +}); + +describe('readPackedSint32 does', () => { + for (const pair of getPackedSint32Pairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readPackedSint32(pair.bufferDecoder, 0); + expect(d).toEqual(pair.sint32Values); + }); + } +}); + +describe('readPackedSint64 does', () => { + for (const pair of getPackedSint64Pairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readPackedSint64(pair.bufferDecoder, 0); + expect(d).toEqual(pair.sint64Values); + }); + } +}); + +describe('readPackedUint32 does', () => { + for (const pair of getPackedUint32Pairs()) { + it(`decode ${pair.name}`, () => { + const d = reader.readPackedUint32(pair.bufferDecoder, 0); + expect(d).toEqual(pair.uint32Values); + }); + } +}); diff --git a/js/experimental/runtime/kernel/sfixed32_test_pairs.js b/js/experimental/runtime/kernel/sfixed32_test_pairs.js new file mode 100644 index 0000000000000..5a082ce97273b --- /dev/null +++ b/js/experimental/runtime/kernel/sfixed32_test_pairs.js @@ -0,0 +1,46 @@ +/** + * @fileoverview Test data for sfixed32 encoding and decoding. + */ +goog.module('protobuf.binary.sfixed32TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of int values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, intValue: number, bufferDecoder: + * !BufferDecoder}>} + */ +function getSfixed32Pairs() { + const sfixed32Pairs = [ + { + name: 'zero', + intValue: 0, + bufferDecoder: createBufferDecoder(0x00, 0x00, 0x00, 0x00), + }, + { + name: 'one', + intValue: 1, + bufferDecoder: createBufferDecoder(0x01, 0x00, 0x00, 0x00) + }, + { + name: 'minus one', + intValue: -1, + bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF), + }, + { + name: 'max int 2^31 -1', + intValue: Math.pow(2, 31) - 1, + bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0x7F) + }, + { + name: 'min int -2^31', + intValue: -Math.pow(2, 31), + bufferDecoder: createBufferDecoder(0x00, 0x00, 0x00, 0x80) + }, + ]; + return [...sfixed32Pairs]; +} + +exports = {getSfixed32Pairs}; diff --git a/js/experimental/runtime/kernel/sfixed64_test_pairs.js b/js/experimental/runtime/kernel/sfixed64_test_pairs.js new file mode 100644 index 0000000000000..c7c8d0020b6ca --- /dev/null +++ b/js/experimental/runtime/kernel/sfixed64_test_pairs.js @@ -0,0 +1,52 @@ +/** + * @fileoverview Test data for sfixed32 encoding and decoding. + */ +goog.module('protobuf.binary.sfixed64TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const Int64 = goog.require('protobuf.Int64'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of int values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, longValue: !Int64, bufferDecoder: + * !BufferDecoder}>} + */ +function getSfixed64Pairs() { + const sfixed64Pairs = [ + { + name: 'zero', + longValue: Int64.fromInt(0), + bufferDecoder: + createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + }, + { + name: 'one', + longValue: Int64.fromInt(1), + bufferDecoder: + createBufferDecoder(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) + }, + { + name: 'minus one', + longValue: Int64.fromInt(-1), + bufferDecoder: + createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + }, + { + name: 'max int 2^63 -1', + longValue: Int64.getMaxValue(), + bufferDecoder: + createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F) + }, + { + name: 'min int -2^63', + longValue: Int64.getMinValue(), + bufferDecoder: + createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80) + }, + ]; + return [...sfixed64Pairs]; +} + +exports = {getSfixed64Pairs}; diff --git a/js/experimental/runtime/kernel/sint32_test_pairs.js b/js/experimental/runtime/kernel/sint32_test_pairs.js new file mode 100644 index 0000000000000..954df90c918c1 --- /dev/null +++ b/js/experimental/runtime/kernel/sint32_test_pairs.js @@ -0,0 +1,57 @@ +/** + * @fileoverview Test data for int32 encoding and decoding. + */ +goog.module('protobuf.binary.sint32TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of float values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, intValue:number, bufferDecoder: + * !BufferDecoder, error: ?boolean, skip_writer: ?boolean}>} + */ +function getSint32Pairs() { + const sint32Pairs = [ + { + name: 'zero', + intValue: 0, + bufferDecoder: createBufferDecoder(0x00), + }, + { + name: 'one ', + intValue: 1, + bufferDecoder: createBufferDecoder(0x02), + }, + { + name: 'minus one', + intValue: -1, + bufferDecoder: createBufferDecoder(0x01), + }, + { + name: 'two', + intValue: 2, + bufferDecoder: createBufferDecoder(0x04), + }, + { + name: 'minus two', + intValue: -2, + bufferDecoder: createBufferDecoder(0x03), + }, + { + name: 'int 2^31 - 1', + intValue: Math.pow(2, 31) - 1, + bufferDecoder: createBufferDecoder(0xFE, 0xFF, 0xFF, 0xFF, 0x0F), + + }, + { + name: '-2^31', + intValue: -Math.pow(2, 31), + bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0x0F), + }, + ]; + return [...sint32Pairs]; +} + +exports = {getSint32Pairs}; diff --git a/js/experimental/runtime/kernel/sint64_test_pairs.js b/js/experimental/runtime/kernel/sint64_test_pairs.js new file mode 100644 index 0000000000000..f1b4610e7ee73 --- /dev/null +++ b/js/experimental/runtime/kernel/sint64_test_pairs.js @@ -0,0 +1,60 @@ +/** + * @fileoverview Test data for sint64 encoding and decoding. + */ +goog.module('protobuf.binary.sint64TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const Int64 = goog.require('protobuf.Int64'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of float values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, longValue: !Int64, bufferDecoder: + * !BufferDecoder, error: ?boolean, skip_writer: ?boolean}>} + */ +function getSint64Pairs() { + const sint64Pairs = [ + { + name: 'zero', + longValue: Int64.fromInt(0), + bufferDecoder: createBufferDecoder(0x00), + }, + { + name: 'one ', + longValue: Int64.fromInt(1), + bufferDecoder: createBufferDecoder(0x02), + }, + { + name: 'minus one', + longValue: Int64.fromInt(-1), + bufferDecoder: createBufferDecoder(0x01), + }, + { + name: 'two', + longValue: Int64.fromInt(2), + bufferDecoder: createBufferDecoder(0x04), + }, + { + name: 'minus two', + longValue: Int64.fromInt(-2), + bufferDecoder: createBufferDecoder(0x03), + }, + { + name: 'min value', + longValue: Int64.getMinValue(), + bufferDecoder: createBufferDecoder( + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01), + }, + + { + name: 'max value', + longValue: Int64.getMaxValue(), + bufferDecoder: createBufferDecoder( + 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01), + }, + ]; + return [...sint64Pairs]; +} + +exports = {getSint64Pairs}; diff --git a/js/experimental/runtime/kernel/storage.js b/js/experimental/runtime/kernel/storage.js new file mode 100644 index 0000000000000..a3e1e4f004d45 --- /dev/null +++ b/js/experimental/runtime/kernel/storage.js @@ -0,0 +1,67 @@ +goog.module('protobuf.runtime.Storage'); + +/** + * Interface for getting and storing fields of a protobuf message. + * + * @interface + * @package + * @template FieldType + */ +class Storage { + /** + * Returns the pivot value. + * + * @return {number} + */ + getPivot() {} + + /** + * Sets a field in the specified field number. + * + * @param {number} fieldNumber + * @param {!FieldType} field + */ + set(fieldNumber, field) {} + + /** + * Returns a field at the specified field number. + * + * @param {number} fieldNumber + * @return {!FieldType|undefined} + */ + get(fieldNumber) {} + + /** + * Deletes a field from the specified field number. + * + * @param {number} fieldNumber + */ + delete(fieldNumber) {} + + /** + * Executes the provided function once for each field. + * + * @param {function(!FieldType, number): void} callback + */ + forEach(callback) {} + + /** + * Creates a shallow copy of the storage. + * + * @return {!Storage} + */ + shallowCopy() {} +} + +/** + * 85% of the proto fields have a field number <= 24: + * https://plx.corp.google.com/scripts2/script_5d._f02af6_0000_23b1_a15f_001a1139dd02 + * + * @type {number} + */ +// LINT.IfChange +Storage.DEFAULT_PIVOT = 24; +// LINT.ThenChange(//depot/google3/third_party/protobuf/javascript/runtime/kernel/binary_storage_test.js, +// //depot/google3/net/proto2/contrib/js_proto/internal/kernel_message_generator.cc) + +exports = Storage; diff --git a/js/experimental/runtime/kernel/tag.js b/js/experimental/runtime/kernel/tag.js new file mode 100644 index 0000000000000..b288df3b8e89f --- /dev/null +++ b/js/experimental/runtime/kernel/tag.js @@ -0,0 +1,144 @@ +goog.module('protobuf.binary.tag'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const WireType = goog.require('protobuf.binary.WireType'); +const {checkCriticalElementIndex, checkCriticalState} = goog.require('protobuf.internal.checks'); + +/** + * Returns wire type stored in a tag. + * Protos store the wire type as the first 3 bit of a tag. + * @param {number} tag + * @return {!WireType} + */ +function tagToWireType(tag) { + return /** @type {!WireType} */ (tag & 0x07); +} + +/** + * Returns the field number stored in a tag. + * Protos store the field number in the upper 29 bits of a 32 bit number. + * @param {number} tag + * @return {number} + */ +function tagToFieldNumber(tag) { + return tag >>> 3; +} + +/** + * Combines wireType and fieldNumber into a tag. + * @param {!WireType} wireType + * @param {number} fieldNumber + * @return {number} + */ +function createTag(wireType, fieldNumber) { + return (fieldNumber << 3 | wireType) >>> 0; +} + +/** + * Returns the length, in bytes, of the field in the tag stream, less the tag + * itself. + * Note: This moves the cursor in the bufferDecoder. + * @param {!BufferDecoder} bufferDecoder + * @param {number} start + * @param {!WireType} wireType + * @param {number} fieldNumber + * @return {number} + * @private + */ +function getTagLength(bufferDecoder, start, wireType, fieldNumber) { + bufferDecoder.setCursor(start); + skipField(bufferDecoder, wireType, fieldNumber); + return bufferDecoder.cursor() - start; +} + +/** + * @param {number} value + * @return {number} + */ +function get32BitVarintLength(value) { + if (value < 0) { + return 5; + } + let size = 1; + while (value >= 128) { + size++; + value >>>= 7; + } + return size; +} + +/** + * Skips over a field. + * Note: If the field is a start group the entire group will be skipped, placing + * the cursor onto the next field. + * @param {!BufferDecoder} bufferDecoder + * @param {!WireType} wireType + * @param {number} fieldNumber + */ +function skipField(bufferDecoder, wireType, fieldNumber) { + switch (wireType) { + case WireType.VARINT: + checkCriticalElementIndex( + bufferDecoder.cursor(), bufferDecoder.endIndex()); + bufferDecoder.skipVarint(); + return; + case WireType.FIXED64: + bufferDecoder.skip(8); + return; + case WireType.DELIMITED: + checkCriticalElementIndex( + bufferDecoder.cursor(), bufferDecoder.endIndex()); + const length = bufferDecoder.getUnsignedVarint32(); + bufferDecoder.skip(length); + return; + case WireType.START_GROUP: + const foundGroup = skipGroup_(bufferDecoder, fieldNumber); + checkCriticalState(foundGroup, 'No end group found.'); + return; + case WireType.FIXED32: + bufferDecoder.skip(4); + return; + default: + throw new Error(`Unexpected wire type: ${wireType}`); + } +} + +/** + * Skips over fields until it finds the end of a given group consuming the stop + * group tag. + * @param {!BufferDecoder} bufferDecoder + * @param {number} groupFieldNumber + * @return {boolean} Whether the end group tag was found. + * @private + */ +function skipGroup_(bufferDecoder, groupFieldNumber) { + // On a start group we need to keep skipping fields until we find a + // corresponding stop group + // Note: Since we are calling skipField from here nested groups will be + // handled by recursion of this method and thus we will not see a nested + // STOP GROUP here unless there is something wrong with the input data. + while (bufferDecoder.hasNext()) { + const tag = bufferDecoder.getUnsignedVarint32(); + const wireType = tagToWireType(tag); + const fieldNumber = tagToFieldNumber(tag); + + if (wireType === WireType.END_GROUP) { + checkCriticalState( + groupFieldNumber === fieldNumber, + `Expected stop group for fieldnumber ${groupFieldNumber} not found.`); + return true; + } else { + skipField(bufferDecoder, wireType, fieldNumber); + } + } + return false; +} + +exports = { + createTag, + get32BitVarintLength, + getTagLength, + skipField, + tagToWireType, + tagToFieldNumber, +}; diff --git a/js/experimental/runtime/kernel/tag_test.js b/js/experimental/runtime/kernel/tag_test.js new file mode 100644 index 0000000000000..35137bb247053 --- /dev/null +++ b/js/experimental/runtime/kernel/tag_test.js @@ -0,0 +1,221 @@ +/** + * @fileoverview Tests for tag.js. + */ +goog.module('protobuf.binary.TagTests'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const WireType = goog.require('protobuf.binary.WireType'); +const {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks'); +const {createTag, get32BitVarintLength, skipField, tagToFieldNumber, tagToWireType} = goog.require('protobuf.binary.tag'); + + +goog.setTestOnly(); + +/** + * @param {...number} bytes + * @return {!ArrayBuffer} + */ +function createArrayBuffer(...bytes) { + return new Uint8Array(bytes).buffer; +} + +describe('skipField', () => { + it('skips varints', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00)); + skipField(bufferDecoder, WireType.VARINT, 1); + expect(bufferDecoder.cursor()).toBe(2); + }); + + it('throws for out of bounds varints', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00)); + bufferDecoder.setCursor(2); + if (CHECK_CRITICAL_STATE) { + expect(() => skipField(bufferDecoder, WireType.VARINT, 1)).toThrowError(); + } + }); + + it('skips fixed64', () => { + const bufferDecoder = BufferDecoder.fromArrayBuffer( + createArrayBuffer(0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + skipField(bufferDecoder, WireType.FIXED64, 1); + expect(bufferDecoder.cursor()).toBe(8); + }); + + it('throws for fixed64 if length is too short', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => skipField(bufferDecoder, WireType.FIXED64, 1)) + .toThrowError(); + } + }); + + it('skips fixed32', () => { + const bufferDecoder = BufferDecoder.fromArrayBuffer( + createArrayBuffer(0x80, 0x00, 0x00, 0x00)); + skipField(bufferDecoder, WireType.FIXED32, 1); + expect(bufferDecoder.cursor()).toBe(4); + }); + + it('throws for fixed32 if length is too short', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => skipField(bufferDecoder, WireType.FIXED32, 1)) + .toThrowError(); + } + }); + + + it('skips length delimited', () => { + const bufferDecoder = BufferDecoder.fromArrayBuffer( + createArrayBuffer(0x03, 0x00, 0x00, 0x00)); + skipField(bufferDecoder, WireType.DELIMITED, 1); + expect(bufferDecoder.cursor()).toBe(4); + }); + + it('throws for length delimited if length is too short', () => { + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x03, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => skipField(bufferDecoder, WireType.DELIMITED, 1)) + .toThrowError(); + } + }); + + it('skips groups', () => { + const bufferDecoder = BufferDecoder.fromArrayBuffer( + createArrayBuffer(0x0B, 0x08, 0x01, 0x0C)); + bufferDecoder.setCursor(1); + skipField(bufferDecoder, WireType.START_GROUP, 1); + expect(bufferDecoder.cursor()).toBe(4); + }); + + it('skips group in group', () => { + const buffer = createArrayBuffer( + 0x0B, // start outer + 0x10, 0x01, // field: 2, value: 1 + 0x0B, // start inner group + 0x10, 0x01, // payload inner group + 0x0C, // stop inner group + 0x0C // end outer + ); + const bufferDecoder = BufferDecoder.fromArrayBuffer(buffer); + bufferDecoder.setCursor(1); + skipField(bufferDecoder, WireType.START_GROUP, 1); + expect(bufferDecoder.cursor()).toBe(8); + }); + + it('throws for group if length is too short', () => { + // no closing group + const bufferDecoder = + BufferDecoder.fromArrayBuffer(createArrayBuffer(0x0B, 0x00, 0x00)); + if (CHECK_CRITICAL_STATE) { + expect(() => skipField(bufferDecoder, WireType.START_GROUP, 1)) + .toThrowError(); + } + }); +}); + + +describe('tagToWireType', () => { + it('decodes numbers ', () => { + // simple numbers + expect(tagToWireType(0x00)).toBe(WireType.VARINT); + expect(tagToWireType(0x01)).toBe(WireType.FIXED64); + expect(tagToWireType(0x02)).toBe(WireType.DELIMITED); + expect(tagToWireType(0x03)).toBe(WireType.START_GROUP); + expect(tagToWireType(0x04)).toBe(WireType.END_GROUP); + expect(tagToWireType(0x05)).toBe(WireType.FIXED32); + + // upper bits should not matter + expect(tagToWireType(0x08)).toBe(WireType.VARINT); + expect(tagToWireType(0x09)).toBe(WireType.FIXED64); + expect(tagToWireType(0x0A)).toBe(WireType.DELIMITED); + expect(tagToWireType(0x0B)).toBe(WireType.START_GROUP); + expect(tagToWireType(0x0C)).toBe(WireType.END_GROUP); + expect(tagToWireType(0x0D)).toBe(WireType.FIXED32); + + // upper bits should not matter + expect(tagToWireType(0xF8)).toBe(WireType.VARINT); + expect(tagToWireType(0xF9)).toBe(WireType.FIXED64); + expect(tagToWireType(0xFA)).toBe(WireType.DELIMITED); + expect(tagToWireType(0xFB)).toBe(WireType.START_GROUP); + expect(tagToWireType(0xFC)).toBe(WireType.END_GROUP); + expect(tagToWireType(0xFD)).toBe(WireType.FIXED32); + + // negative numbers work + expect(tagToWireType(-8)).toBe(WireType.VARINT); + expect(tagToWireType(-7)).toBe(WireType.FIXED64); + expect(tagToWireType(-6)).toBe(WireType.DELIMITED); + expect(tagToWireType(-5)).toBe(WireType.START_GROUP); + expect(tagToWireType(-4)).toBe(WireType.END_GROUP); + expect(tagToWireType(-3)).toBe(WireType.FIXED32); + }); +}); + +describe('tagToFieldNumber', () => { + it('returns fieldNumber', () => { + expect(tagToFieldNumber(0x08)).toBe(1); + expect(tagToFieldNumber(0x09)).toBe(1); + expect(tagToFieldNumber(0x10)).toBe(2); + expect(tagToFieldNumber(0x12)).toBe(2); + }); +}); + +describe('createTag', () => { + it('combines fieldNumber and wireType', () => { + expect(createTag(WireType.VARINT, 1)).toBe(0x08); + expect(createTag(WireType.FIXED64, 1)).toBe(0x09); + expect(createTag(WireType.DELIMITED, 1)).toBe(0x0A); + expect(createTag(WireType.START_GROUP, 1)).toBe(0x0B); + expect(createTag(WireType.END_GROUP, 1)).toBe(0x0C); + expect(createTag(WireType.FIXED32, 1)).toBe(0x0D); + + expect(createTag(WireType.VARINT, 2)).toBe(0x10); + expect(createTag(WireType.FIXED64, 2)).toBe(0x11); + expect(createTag(WireType.DELIMITED, 2)).toBe(0x12); + expect(createTag(WireType.START_GROUP, 2)).toBe(0x13); + expect(createTag(WireType.END_GROUP, 2)).toBe(0x14); + expect(createTag(WireType.FIXED32, 2)).toBe(0x15); + + expect(createTag(WireType.VARINT, 0x1FFFFFFF)).toBe(0xFFFFFFF8 >>> 0); + expect(createTag(WireType.FIXED64, 0x1FFFFFFF)).toBe(0xFFFFFFF9 >>> 0); + expect(createTag(WireType.DELIMITED, 0x1FFFFFFF)).toBe(0xFFFFFFFA >>> 0); + expect(createTag(WireType.START_GROUP, 0x1FFFFFFF)).toBe(0xFFFFFFFB >>> 0); + expect(createTag(WireType.END_GROUP, 0x1FFFFFFF)).toBe(0xFFFFFFFC >>> 0); + expect(createTag(WireType.FIXED32, 0x1FFFFFFF)).toBe(0xFFFFFFFD >>> 0); + }); +}); + +describe('get32BitVarintLength', () => { + it('length of tag', () => { + expect(get32BitVarintLength(0)).toBe(1); + expect(get32BitVarintLength(1)).toBe(1); + expect(get32BitVarintLength(1)).toBe(1); + + expect(get32BitVarintLength(Math.pow(2, 7) - 1)).toBe(1); + expect(get32BitVarintLength(Math.pow(2, 7))).toBe(2); + + expect(get32BitVarintLength(Math.pow(2, 14) - 1)).toBe(2); + expect(get32BitVarintLength(Math.pow(2, 14))).toBe(3); + + expect(get32BitVarintLength(Math.pow(2, 21) - 1)).toBe(3); + expect(get32BitVarintLength(Math.pow(2, 21))).toBe(4); + + expect(get32BitVarintLength(Math.pow(2, 28) - 1)).toBe(4); + expect(get32BitVarintLength(Math.pow(2, 28))).toBe(5); + + expect(get32BitVarintLength(Math.pow(2, 31) - 1)).toBe(5); + + expect(get32BitVarintLength(-1)).toBe(5); + expect(get32BitVarintLength(-Math.pow(2, 31))).toBe(5); + + expect(get32BitVarintLength(createTag(WireType.VARINT, 0x1fffffff))) + .toBe(5); + expect(get32BitVarintLength(createTag(WireType.FIXED32, 0x1fffffff))) + .toBe(5); + }); +}); diff --git a/js/experimental/runtime/kernel/textencoding.js b/js/experimental/runtime/kernel/textencoding.js new file mode 100644 index 0000000000000..fe8fd25e65829 --- /dev/null +++ b/js/experimental/runtime/kernel/textencoding.js @@ -0,0 +1,116 @@ +/** + * @fileoverview A UTF8 decoder. + */ +goog.module('protobuf.binary.textencoding'); + +const {checkElementIndex} = goog.require('protobuf.internal.checks'); + +/** + * Combines an array of codePoints into a string. + * @param {!Array} codePoints + * @return {string} + */ +function codePointsToString(codePoints) { + // Performance: http://jsperf.com/string-fromcharcode-test/13 + let s = '', i = 0; + const length = codePoints.length; + const BATCH_SIZE = 10000; + while (i < length) { + const end = Math.min(i + BATCH_SIZE, length); + s += String.fromCharCode.apply(null, codePoints.slice(i, end)); + i = end; + } + return s; +} + +/** + * Decodes raw bytes into a string. + * Supports codepoints from U+0000 up to U+10FFFF. + * (http://en.wikipedia.org/wiki/UTF-8). + * @param {!DataView} bytes + * @return {string} + */ +function decode(bytes) { + let cursor = 0; + const codePoints = []; + + while (cursor < bytes.byteLength) { + const c = bytes.getUint8(cursor++); + if (c < 0x80) { // Regular 7-bit ASCII. + codePoints.push(c); + } else if (c < 0xC0) { + // UTF-8 continuation mark. We are out of sync. This + // might happen if we attempted to read a character + // with more than four bytes. + continue; + } else if (c < 0xE0) { // UTF-8 with two bytes. + checkElementIndex(cursor, bytes.byteLength); + const c2 = bytes.getUint8(cursor++); + codePoints.push(((c & 0x1F) << 6) | (c2 & 0x3F)); + } else if (c < 0xF0) { // UTF-8 with three bytes. + checkElementIndex(cursor + 1, bytes.byteLength); + const c2 = bytes.getUint8(cursor++); + const c3 = bytes.getUint8(cursor++); + codePoints.push(((c & 0xF) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)); + } else if (c < 0xF8) { // UTF-8 with 4 bytes. + checkElementIndex(cursor + 2, bytes.byteLength); + const c2 = bytes.getUint8(cursor++); + const c3 = bytes.getUint8(cursor++); + const c4 = bytes.getUint8(cursor++); + // Characters written on 4 bytes have 21 bits for a codepoint. + // We can't fit that on 16bit characters, so we use surrogates. + let codepoint = ((c & 0x07) << 18) | ((c2 & 0x3F) << 12) | + ((c3 & 0x3F) << 6) | (c4 & 0x3F); + // Surrogates formula from wikipedia. + // 1. Subtract 0x10000 from codepoint + codepoint -= 0x10000; + // 2. Split this into the high 10-bit value and the low 10-bit value + // 3. Add 0xD800 to the high value to form the high surrogate + // 4. Add 0xDC00 to the low value to form the low surrogate: + const low = (codepoint & 0x3FF) + 0xDC00; + const high = ((codepoint >> 10) & 0x3FF) + 0xD800; + codePoints.push(high, low); + } + } + return codePointsToString(codePoints); +} + +/** + * Writes a UTF16 JavaScript string to the buffer encoded as UTF8. + * @param {string} value The string to write. + * @return {!Uint8Array} An array containing the encoded bytes. + */ +function encode(value) { + const buffer = []; + + for (let i = 0; i < value.length; i++) { + const c1 = value.charCodeAt(i); + + if (c1 < 0x80) { + buffer.push(c1); + } else if (c1 < 0x800) { + buffer.push((c1 >> 6) | 0xC0); + buffer.push((c1 & 0x3F) | 0x80); + } else if (c1 < 0xD800 || c1 >= 0xE000) { + buffer.push((c1 >> 12) | 0xE0); + buffer.push(((c1 >> 6) & 0x3F) | 0x80); + buffer.push((c1 & 0x3F) | 0x80); + } else { + // surrogate pair + i++; + checkElementIndex(i, value.length); + const c2 = value.charCodeAt(i); + const paired = 0x10000 + (((c1 & 0x3FF) << 10) | (c2 & 0x3FF)); + buffer.push((paired >> 18) | 0xF0); + buffer.push(((paired >> 12) & 0x3F) | 0x80); + buffer.push(((paired >> 6) & 0x3F) | 0x80); + buffer.push((paired & 0x3F) | 0x80); + } + } + return new Uint8Array(buffer); +} + +exports = { + decode, + encode, +}; diff --git a/js/experimental/runtime/kernel/textencoding_test.js b/js/experimental/runtime/kernel/textencoding_test.js new file mode 100644 index 0000000000000..c7ecd18a6f115 --- /dev/null +++ b/js/experimental/runtime/kernel/textencoding_test.js @@ -0,0 +1,113 @@ +/** + * @fileoverview Tests for textdecoder.js. + */ +goog.module('protobuf.binary.TextDecoderTest'); + +goog.setTestOnly(); + +const {decode, encode} = goog.require('protobuf.binary.textencoding'); + +describe('Decode does', () => { + it('return empty string for empty array', () => { + expect(decode(new DataView(new ArrayBuffer(0)))).toEqual(''); + }); + + it('throw on null being passed', () => { + expect(() => decode(/** @type {!DataView} */ (/** @type {*} */ (null)))) + .toThrow(); + }); +}); + +describe('Encode does', () => { + it('return empty array for empty string', () => { + expect(encode('')).toEqual(new Uint8Array(0)); + }); + + it('throw on null being passed', () => { + expect(() => encode(/** @type {string} */ (/** @type {*} */ (null)))) + .toThrow(); + }); +}); + +/** @const {!TextEncoder} */ +const textEncoder = new TextEncoder('utf-8'); + +/** + * A Pair of string and Uint8Array representing the same data. + * Each pair has the string value and its utf-8 bytes. + */ +class Pair { + /** + * Constructs a pair from a given string. + * @param {string} s + * @return {!Pair} + */ + static fromString(s) { + return new Pair(s, textEncoder.encode(s).buffer); + } + /** + * Constructs a pair from a given charCode. + * @param {number} charCode + * @return {!Pair} + */ + static fromCharCode(charCode) { + return Pair.fromString(String.fromCharCode(charCode)); + } + + /** + * @param {string} stringValue + * @param {!ArrayBuffer} bytes + * @private + */ + constructor(stringValue, bytes) { + /** @const @private {string} */ + this.stringValue_ = stringValue; + /** @const @private {!ArrayBuffer} */ + this.bytes_ = bytes; + } + + /** Ensures that a given pair encodes and decodes round trip*/ + expectPairToMatch() { + expect(decode(new DataView(this.bytes_))).toEqual(this.stringValue_); + expect(encode(this.stringValue_)).toEqual(new Uint8Array(this.bytes_)); + } +} + +describe('textencoding does', () => { + it('works for empty string', () => { + Pair.fromString('').expectPairToMatch(); + }); + + it('decode and encode random strings', () => { + // 1 byte strings + Pair.fromString('hello').expectPairToMatch(); + Pair.fromString('HELLO1!'); + + // 2 byte String + Pair.fromString('©').expectPairToMatch(); + + // 3 byte string + Pair.fromString('❄').expectPairToMatch(); + + // 4 byte string + Pair.fromString('😁').expectPairToMatch(); + }); + + it('decode and encode 1 byte strings', () => { + for (let i = 0; i < 0x80; i++) { + Pair.fromCharCode(i).expectPairToMatch(); + } + }); + + it('decode and encode 2 byte strings', () => { + for (let i = 0xC0; i < 0x7FF; i++) { + Pair.fromCharCode(i).expectPairToMatch(); + } + }); + + it('decode and encode 3 byte strings', () => { + for (let i = 0x7FF; i < 0x8FFF; i++) { + Pair.fromCharCode(i).expectPairToMatch(); + } + }); +}); diff --git a/js/experimental/runtime/kernel/typed_arrays.js b/js/experimental/runtime/kernel/typed_arrays.js new file mode 100644 index 0000000000000..028096510a44a --- /dev/null +++ b/js/experimental/runtime/kernel/typed_arrays.js @@ -0,0 +1,116 @@ +/** + * @fileoverview Helper methods for typed arrays. + */ +goog.module('protobuf.binary.typedArrays'); + +const {assert} = goog.require('goog.asserts'); + +/** + * @param {!ArrayBuffer} buffer1 + * @param {!ArrayBuffer} buffer2 + * @return {boolean} + */ +function arrayBufferEqual(buffer1, buffer2) { + if (!buffer1 || !buffer2) { + throw new Error('Buffer shouldn\'t be empty'); + } + + const array1 = new Uint8Array(buffer1); + const array2 = new Uint8Array(buffer2); + + return uint8ArrayEqual(array1, array2); +} + +/** + * @param {!Uint8Array} array1 + * @param {!Uint8Array} array2 + * @return {boolean} + */ +function uint8ArrayEqual(array1, array2) { + if (array1 === array2) { + return true; + } + + if (array1.byteLength !== array2.byteLength) { + return false; + } + + for (let i = 0; i < array1.byteLength; i++) { + if (array1[i] !== array2[i]) { + return false; + } + } + return true; +} + +/** + * ArrayBuffer.prototype.slice, but fallback to manual copy if missing. + * @param {!ArrayBuffer} buffer + * @param {number} start + * @param {number=} end + * @return {!ArrayBuffer} New array buffer with given the contents of `buffer`. + */ +function arrayBufferSlice(buffer, start, end = undefined) { + // The fallback isn't fully compatible with ArrayBuffer.slice, enforce + // strict requirements on start/end. + // Spec: + // https://www.ecma-international.org/ecma-262/6.0/#sec-arraybuffer.prototype.slice + assert(start >= 0); + assert(end === undefined || (end >= 0 && end <= buffer.byteLength)); + assert((end === undefined ? buffer.byteLength : end) >= start); + if (buffer.slice) { + const slicedBuffer = buffer.slice(start, end); + // The ArrayBuffer.prototype.slice function was flawed before iOS 12.2. This + // causes 0-length results when passing undefined or a number greater + // than 32 bits for the optional end value. In these cases, we fall back to + // using our own slice implementation. + // More details: https://bugs.webkit.org/show_bug.cgi?id=185127 + if (slicedBuffer.byteLength !== 0 || (start === end)) { + return slicedBuffer; + } + } + const realEnd = end == null ? buffer.byteLength : end; + const length = realEnd - start; + assert(length >= 0); + const view = new Uint8Array(buffer, start, length); + // A TypedArray constructed from another Typed array copies the data. + const clone = new Uint8Array(view); + + return clone.buffer; +} + +/** + * Returns a new Uint8Array with the size and contents of the given + * ArrayBufferView. ArrayBufferView is an interface implemented by DataView, + * Uint8Array and all typed arrays. + * @param {!ArrayBufferView} view + * @return {!Uint8Array} + */ +function cloneArrayBufferView(view) { + return new Uint8Array(arrayBufferSlice( + view.buffer, view.byteOffset, view.byteOffset + view.byteLength)); +} + +/** + * Returns a 32 bit number for the corresponding Uint8Array. + * @param {!Uint8Array} array + * @return {number} + */ +function hashUint8Array(array) { + const prime = 31; + let result = 17; + + for (let i = 0; i < array.length; i++) { + // '| 0' ensures signed 32 bits + result = (result * prime + array[i]) | 0; + } + return result; +} + +exports = { + arrayBufferEqual, + uint8ArrayEqual, + arrayBufferSlice, + cloneArrayBufferView, + hashUint8Array, +}; diff --git a/js/experimental/runtime/kernel/typed_arrays_test.js b/js/experimental/runtime/kernel/typed_arrays_test.js new file mode 100644 index 0000000000000..be9ba65da9539 --- /dev/null +++ b/js/experimental/runtime/kernel/typed_arrays_test.js @@ -0,0 +1,191 @@ +/** + * @fileoverview Tests for typed_arrays.js. + */ +goog.module('protobuf.binary.typedArraysTest'); + +const {arrayBufferEqual, arrayBufferSlice, cloneArrayBufferView, hashUint8Array, uint8ArrayEqual} = goog.require('protobuf.binary.typedArrays'); + +describe('arrayBufferEqual', () => { + it('returns true for empty buffers', () => { + const buffer1 = new ArrayBuffer(0); + const buffer2 = new ArrayBuffer(0); + expect(arrayBufferEqual(buffer1, buffer2)).toBe(true); + }); + + it('throws for first null buffers', () => { + const buffer = new ArrayBuffer(0); + expect( + () => arrayBufferEqual( + /** @type {!ArrayBuffer} */ (/** @type {*} */ (null)), buffer)) + .toThrow(); + }); + + it('throws for second null buffers', () => { + const buffer = new ArrayBuffer(0); + expect( + () => arrayBufferEqual( + buffer, /** @type {!ArrayBuffer} */ (/** @type {*} */ (null)))) + .toThrow(); + }); + + it('returns true for arrays with same values', () => { + const array1 = new Uint8Array(4); + array1[0] = 1; + const array2 = new Uint8Array(4); + array2[0] = 1; + expect(arrayBufferEqual(array1.buffer, array2.buffer)).toBe(true); + }); + + it('returns false for arrays with different values', () => { + const array1 = new Uint8Array(4); + array1[0] = 1; + const array2 = new Uint8Array(4); + array2[0] = 2; + expect(arrayBufferEqual(array1.buffer, array2.buffer)).toBe(false); + }); + + it('returns true same instance', () => { + const array1 = new Uint8Array(4); + array1[0] = 1; + expect(arrayBufferEqual(array1.buffer, array1.buffer)).toBe(true); + }); +}); + +describe('uint8ArrayEqual', () => { + it('returns true for empty arrays', () => { + const array1 = new Uint8Array(0); + const array2 = new Uint8Array(0); + expect(uint8ArrayEqual(array1, array2)).toBe(true); + }); + + it('throws for first Uint8Array array', () => { + const array = new Uint8Array(0); + expect( + () => uint8ArrayEqual( + /** @type {!Uint8Array} */ (/** @type {*} */ (null)), array)) + .toThrow(); + }); + + it('throws for second null array', () => { + const array = new Uint8Array(0); + expect( + () => uint8ArrayEqual( + array, /** @type {!Uint8Array} */ (/** @type {*} */ (null)))) + .toThrow(); + }); + + it('returns true for arrays with same values', () => { + const buffer1 = new Uint8Array([0, 1, 2, 3]).buffer; + const buffer2 = new Uint8Array([1, 2, 3, 4]).buffer; + const array1 = new Uint8Array(buffer1, 1, 3); + const array2 = new Uint8Array(buffer2, 0, 3); + expect(uint8ArrayEqual(array1, array2)).toBe(true); + }); + + it('returns false for arrays with different values', () => { + const array1 = new Uint8Array(4); + array1[0] = 1; + const array2 = new Uint8Array(4); + array2[0] = 2; + expect(uint8ArrayEqual(array1, array2)).toBe(false); + }); + + it('returns true same instance', () => { + const array1 = new Uint8Array(4); + array1[0] = 1; + expect(uint8ArrayEqual(array1, array1)).toBe(true); + }); +}); + +describe('arrayBufferSlice', () => { + it('Returns a new instance.', () => { + const buffer1 = new ArrayBuffer(0); + const buffer2 = arrayBufferSlice(buffer1, 0); + expect(buffer2).not.toBe(buffer1); + expect(arrayBufferEqual(buffer1, buffer2)).toBe(true); + }); + + it('Copies data with positive start/end.', () => { + const buffer1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).buffer; + expect(buffer1.byteLength).toEqual(10); + + const buffer2 = arrayBufferSlice(buffer1, 2, 6); + expect(buffer2.byteLength).toEqual(4); + expect(buffer2).not.toBe(buffer1); + const expected = new Uint8Array([2, 3, 4, 5]).buffer; + expect(arrayBufferEqual(expected, buffer2)).toBe(true); + }); + + it('Copies all data without end.', () => { + const buffer1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).buffer; + expect(buffer1.byteLength).toEqual(10); + + const buffer2 = arrayBufferSlice(buffer1, 0); + expect(buffer2.byteLength).toEqual(10); + expect(arrayBufferEqual(buffer1, buffer2)).toBe(true); + }); + + if (goog.DEBUG) { + it('Fails with negative end.', () => { + const buffer1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).buffer; + expect(() => void arrayBufferSlice(buffer1, 2, -1)).toThrow(); + }); + + it('Fails with negative start.', () => { + const buffer1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).buffer; + expect(() => void arrayBufferSlice(buffer1, 2, -1)).toThrow(); + }); + + it('Fails when start > end.', () => { + const buffer1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).buffer; + expect(() => void arrayBufferSlice(buffer1, 2, 1)).toThrow(); + }); + } +}); + +describe('cloneArrayBufferView', () => { + it('Returns a new instance.', () => { + const array1 = new Uint8Array(0); + const array2 = cloneArrayBufferView(new Uint8Array(array1)); + expect(array2).not.toBe(array1); + expect(uint8ArrayEqual(array1, array2)).toBe(true); + }); + + it('Returns an array of the exact size.', () => { + const array1 = + new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).subarray(2, 5); + expect(array1.length).toEqual(3); + expect(array1.buffer.byteLength).toEqual(10); + const array2 = cloneArrayBufferView(array1); + expect(array2.byteLength).toEqual(3); + expect(array2).toEqual(new Uint8Array([2, 3, 4])); + }); +}); + +describe('hashUint8Array', () => { + it('returns same hashcode for empty Uint8Arrays', () => { + const array1 = new Uint8Array(0); + const array2 = new Uint8Array(0); + expect(hashUint8Array(array1)).toBe(hashUint8Array(array2)); + }); + + it('returns same hashcode for Uint8Arrays with same values', () => { + const array1 = new Uint8Array(4); + array1[0] = 1; + const array2 = new Uint8Array(4); + array2[0] = 1; + expect(hashUint8Array(array1)).toBe(hashUint8Array(array2)); + }); + + it('returns different hashcode for Uint8Arrays with different values', () => { + // This test might fail in the future if the hashing algorithm is updated + // and we end up with a collision here. + // We still need this test to make sure that we are not just returning + // the same number for all buffers. + const array1 = new Uint8Array(4); + array1[0] = 1; + const array2 = new Uint8Array(4); + array2[0] = 2; + expect(hashUint8Array(array1)).not.toBe(hashUint8Array(array2)); + }); +}); diff --git a/js/experimental/runtime/kernel/uint32_test_pairs.js b/js/experimental/runtime/kernel/uint32_test_pairs.js new file mode 100644 index 0000000000000..851996d0fcd18 --- /dev/null +++ b/js/experimental/runtime/kernel/uint32_test_pairs.js @@ -0,0 +1,68 @@ +/** + * @fileoverview Test data for int32 encoding and decoding. + */ +goog.module('protobuf.binary.uint32TestPairs'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'); + +/** + * An array of Pairs of float values and their bit representation. + * This is used to test encoding and decoding from/to the protobuf wire format. + * @return {!Array<{name: string, intValue:number, bufferDecoder: + * !BufferDecoder, error: (boolean|undefined), + * skip_reader: (boolean|undefined), skip_writer: (boolean|undefined)}>} + */ +function getUint32Pairs() { + const uint32Pairs = [ + { + name: 'zero', + intValue: 0, + bufferDecoder: createBufferDecoder(0x00), + }, + { + name: 'one ', + intValue: 1, + bufferDecoder: createBufferDecoder(0x01), + }, + { + name: 'max signed int 2^31 - 1', + intValue: Math.pow(2, 31) - 1, + bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0x07), + }, + { + name: 'max unsigned int 2^32 - 1', + intValue: Math.pow(2, 32) - 1, + bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0x0F), + }, + { + name: 'negative one', + intValue: -1, + bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0x0F), + skip_reader: true, + }, + { + name: 'truncates more than 32 bits', + intValue: Math.pow(2, 32) - 1, + bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01), + skip_writer: true, + }, + { + name: 'truncates more than 32 bits (bit 33 set)', + intValue: Math.pow(2, 28) - 1, + bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0x10), + skip_writer: true, + }, + { + name: 'errors out for 11 bytes', + intValue: Math.pow(2, 32) - 1, + bufferDecoder: createBufferDecoder( + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + error: true, + skip_writer: true, + }, + ]; + return [...uint32Pairs]; +} + +exports = {getUint32Pairs}; diff --git a/js/experimental/runtime/kernel/uint8arrays.js b/js/experimental/runtime/kernel/uint8arrays.js new file mode 100644 index 0000000000000..c6bed16667328 --- /dev/null +++ b/js/experimental/runtime/kernel/uint8arrays.js @@ -0,0 +1,28 @@ +/** + * @fileoverview Helper methods for Uint8Arrays. + */ +goog.module('protobuf.binary.uint8arrays'); + +/** + * Combines multiple bytes arrays (either Uint8Array or number array whose + * values are bytes) into a single Uint8Array. + * @param {!Array|!Array>} arrays + * @return {!Uint8Array} + */ +function concatenateByteArrays(arrays) { + let totalLength = 0; + for (const array of arrays) { + totalLength += array.length; + } + const result = new Uint8Array(totalLength); + let offset = 0; + for (const array of arrays) { + result.set(array, offset); + offset += array.length; + } + return result; +} + +exports = { + concatenateByteArrays, +}; diff --git a/js/experimental/runtime/kernel/uint8arrays_test.js b/js/experimental/runtime/kernel/uint8arrays_test.js new file mode 100644 index 0000000000000..6bb5a75654a18 --- /dev/null +++ b/js/experimental/runtime/kernel/uint8arrays_test.js @@ -0,0 +1,47 @@ +/** + * @fileoverview Tests for uint8arrays.js. + */ +goog.module('protobuf.binary.Uint8ArraysTest'); + +goog.setTestOnly(); + +const {concatenateByteArrays} = goog.require('protobuf.binary.uint8arrays'); + +describe('concatenateByteArrays does', () => { + it('concatenate empty array', () => { + const byteArrays = []; + expect(concatenateByteArrays(byteArrays)).toEqual(new Uint8Array(0)); + }); + + it('concatenate Uint8Arrays', () => { + const byteArrays = [new Uint8Array([0x01]), new Uint8Array([0x02])]; + expect(concatenateByteArrays(byteArrays)).toEqual(new Uint8Array([ + 0x01, 0x02 + ])); + }); + + it('concatenate array of bytes', () => { + const byteArrays = [[0x01], [0x02]]; + expect(concatenateByteArrays(byteArrays)).toEqual(new Uint8Array([ + 0x01, 0x02 + ])); + }); + + it('concatenate array of non-bytes', () => { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + const byteArrays = [[40.0], [256]]; + expect(concatenateByteArrays(byteArrays)).toEqual(new Uint8Array([ + 0x28, 0x00 + ])); + }); + + it('throw for null array', () => { + expect( + () => concatenateByteArrays( + /** @type {!Array} */ (/** @type {*} */ (null)))) + .toThrow(); + }); +}); diff --git a/js/experimental/runtime/kernel/wire_type.js b/js/experimental/runtime/kernel/wire_type.js new file mode 100644 index 0000000000000..dee6fe4bd020a --- /dev/null +++ b/js/experimental/runtime/kernel/wire_type.js @@ -0,0 +1,17 @@ +goog.module('protobuf.binary.WireType'); + +/** + * Wire-format type codes, taken from proto2/public/wire_format_lite.h. + * @enum {number} + */ +const WireType = { + VARINT: 0, + FIXED64: 1, + DELIMITED: 2, + START_GROUP: 3, + END_GROUP: 4, + FIXED32: 5, + INVALID: 6 +}; + +exports = WireType; diff --git a/js/experimental/runtime/kernel/writer.js b/js/experimental/runtime/kernel/writer.js new file mode 100644 index 0000000000000..5b8b79b6c351e --- /dev/null +++ b/js/experimental/runtime/kernel/writer.js @@ -0,0 +1,743 @@ +/** + * @fileoverview Implements Writer for writing data as the binary wire format + * bytes array. + */ +goog.module('protobuf.binary.Writer'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const ByteString = goog.require('protobuf.ByteString'); +const Int64 = goog.require('protobuf.Int64'); +const WireType = goog.require('protobuf.binary.WireType'); +const {POLYFILL_TEXT_ENCODING, checkFieldNumber, checkTypeUnsignedInt32, checkWireType} = goog.require('protobuf.internal.checks'); +const {concatenateByteArrays} = goog.require('protobuf.binary.uint8arrays'); +const {createTag, getTagLength} = goog.require('protobuf.binary.tag'); +const {encode} = goog.require('protobuf.binary.textencoding'); + +/** + * Returns a valid utf-8 encoder function based on TextEncoder if available or + * a polyfill. + * Some of the environments we run in do not have TextEncoder defined. + * TextEncoder is faster than our polyfill so we prefer it over the polyfill. + * @return {function(string):!Uint8Array} + */ +function getEncoderFunction() { + if (goog.global['TextEncoder']) { + const textEncoder = new goog.global['TextEncoder']('utf-8'); + return s => s.length === 0 ? new Uint8Array(0) : textEncoder.encode(s); + } + if (POLYFILL_TEXT_ENCODING) { + return encode; + } else { + throw new Error( + 'TextEncoder is missing. ' + + 'Enable protobuf.defines.POLYFILL_TEXT_ENCODING'); + } +} + +/** @const {function(string): !Uint8Array} */ +const encoderFunction = getEncoderFunction(); + +/** + * Writer provides methods for encoding all protobuf supported type into a + * binary format bytes array. + * Check https://developers.google.com/protocol-buffers/docs/encoding for binary + * format definition. + * @final + * @package + */ +class Writer { + constructor() { + /** + * Blocks of data that needs to be serialized. After writing all the data, + * the blocks are concatenated into a single Uint8Array. + * @private {!Array} + */ + this.blocks_ = []; + + /** + * A buffer for writing varint data (tag number + field number for each + * field, int32, uint32 etc.). Before writing a non-varint data block + * (string, fixed32 etc.), the buffer is appended to the block array as a + * new block, and a new buffer is started. + * + * We could've written each varint as a new block instead of writing + * multiple varints in this buffer. But this will increase the number of + * blocks, and concatenating many small blocks is slower than concatenating + * few large blocks. + * + * TODO: Experiment with writing data in a fixed-length + * Uint8Array instead of using a growing buffer. + * + * @private {!Array} + */ + this.currentBuffer_ = []; + } + + /** + * Converts the encoded data into a Uint8Array. + * The writer is also reset. + * @return {!ArrayBuffer} + */ + getAndResetResultBuffer() { + this.closeAndStartNewBuffer_(); + const result = concatenateByteArrays(this.blocks_); + this.blocks_ = []; + return result.buffer; + } + + /** + * Encodes a (field number, wire type) tuple into a wire-format field header. + * @param {number} fieldNumber + * @param {!WireType} wireType + */ + writeTag(fieldNumber, wireType) { + checkFieldNumber(fieldNumber); + checkWireType(wireType); + const tag = createTag(wireType, fieldNumber); + this.writeUnsignedVarint32_(tag); + } + + /** + * Appends the current buffer into the blocks array and starts a new buffer. + * @private + */ + closeAndStartNewBuffer_() { + this.blocks_.push(new Uint8Array(this.currentBuffer_)); + this.currentBuffer_ = []; + } + + /** + * Encodes a 32-bit integer into its wire-format varint representation and + * stores it in the buffer. + * @param {number} value + * @private + */ + writeUnsignedVarint32_(value) { + checkTypeUnsignedInt32(value); + while (value > 0x7f) { + this.currentBuffer_.push((value & 0x7f) | 0x80); + value = value >>> 7; + } + this.currentBuffer_.push(value); + } + + /**************************************************************************** + * OPTIONAL METHODS + ****************************************************************************/ + + /** + * Writes a boolean value field to the buffer as a varint. + * @param {boolean} value + * @private + */ + writeBoolValue_(value) { + this.currentBuffer_.push(value ? 1 : 0); + } + + /** + * Writes a boolean value field to the buffer as a varint. + * @param {number} fieldNumber + * @param {boolean} value + */ + writeBool(fieldNumber, value) { + this.writeTag(fieldNumber, WireType.VARINT); + this.writeBoolValue_(value); + } + + /** + * Writes a bytes value field to the buffer as a length delimited field. + * @param {number} fieldNumber + * @param {!ByteString} value + */ + writeBytes(fieldNumber, value) { + this.writeTag(fieldNumber, WireType.DELIMITED); + const buffer = value.toArrayBuffer(); + this.writeUnsignedVarint32_(buffer.byteLength); + this.writeRaw_(buffer); + } + + /** + * Writes a double value field to the buffer without tag. + * @param {number} value + * @private + */ + writeDoubleValue_(value) { + const buffer = new ArrayBuffer(8); + const view = new DataView(buffer); + view.setFloat64(0, value, true); + this.writeRaw_(buffer); + } + + /** + * Writes a double value field to the buffer. + * @param {number} fieldNumber + * @param {number} value + */ + writeDouble(fieldNumber, value) { + this.writeTag(fieldNumber, WireType.FIXED64); + this.writeDoubleValue_(value); + } + + /** + * Writes a fixed32 value field to the buffer without tag. + * @param {number} value + * @private + */ + writeFixed32Value_(value) { + const buffer = new ArrayBuffer(4); + const view = new DataView(buffer); + view.setUint32(0, value, true); + this.writeRaw_(buffer); + } + + /** + * Writes a fixed32 value field to the buffer. + * @param {number} fieldNumber + * @param {number} value + */ + writeFixed32(fieldNumber, value) { + this.writeTag(fieldNumber, WireType.FIXED32); + this.writeFixed32Value_(value); + } + + /** + * Writes a float value field to the buffer without tag. + * @param {number} value + * @private + */ + writeFloatValue_(value) { + const buffer = new ArrayBuffer(4); + const view = new DataView(buffer); + view.setFloat32(0, value, true); + this.writeRaw_(buffer); + } + + /** + * Writes a float value field to the buffer. + * @param {number} fieldNumber + * @param {number} value + */ + writeFloat(fieldNumber, value) { + this.writeTag(fieldNumber, WireType.FIXED32); + this.writeFloatValue_(value); + } + + /** + * Writes a int32 value field to the buffer as a varint without tag. + * @param {number} value + * @private + */ + writeInt32Value_(value) { + if (value >= 0) { + this.writeVarint64_(0, value); + } else { + this.writeVarint64_(0xFFFFFFFF, value); + } + } + + /** + * Writes a int32 value field to the buffer as a varint. + * @param {number} fieldNumber + * @param {number} value + */ + writeInt32(fieldNumber, value) { + this.writeTag(fieldNumber, WireType.VARINT); + this.writeInt32Value_(value); + } + + /** + * Writes a int64 value field to the buffer as a varint. + * @param {number} fieldNumber + * @param {!Int64} value + */ + writeInt64(fieldNumber, value) { + this.writeTag(fieldNumber, WireType.VARINT); + this.writeVarint64_(value.getHighBits(), value.getLowBits()); + } + + /** + * Writes a sfixed32 value field to the buffer. + * @param {number} value + * @private + */ + writeSfixed32Value_(value) { + const buffer = new ArrayBuffer(4); + const view = new DataView(buffer); + view.setInt32(0, value, true); + this.writeRaw_(buffer); + } + + /** + * Writes a sfixed32 value field to the buffer. + * @param {number} fieldNumber + * @param {number} value + */ + writeSfixed32(fieldNumber, value) { + this.writeTag(fieldNumber, WireType.FIXED32); + this.writeSfixed32Value_(value); + } + + /** + * Writes a sfixed64 value field to the buffer without tag. + * @param {!Int64} value + * @private + */ + writeSfixed64Value_(value) { + const buffer = new ArrayBuffer(8); + const view = new DataView(buffer); + view.setInt32(0, value.getLowBits(), true); + view.setInt32(4, value.getHighBits(), true); + this.writeRaw_(buffer); + } + + /** + * Writes a sfixed64 value field to the buffer. + * @param {number} fieldNumber + * @param {!Int64} value + */ + writeSfixed64(fieldNumber, value) { + this.writeTag(fieldNumber, WireType.FIXED64); + this.writeSfixed64Value_(value); + } + + /** + * Writes a sfixed64 value field to the buffer. + * @param {number} fieldNumber + */ + writeStartGroup(fieldNumber) { + this.writeTag(fieldNumber, WireType.START_GROUP); + } + + /** + * Writes a sfixed64 value field to the buffer. + * @param {number} fieldNumber + */ + writeEndGroup(fieldNumber) { + this.writeTag(fieldNumber, WireType.END_GROUP); + } + + /** + * Writes a uint32 value field to the buffer as a varint without tag. + * @param {number} value + * @private + */ + writeUint32Value_(value) { + this.writeVarint64_(0, value); + } + + /** + * Writes a uint32 value field to the buffer as a varint. + * @param {number} fieldNumber + * @param {number} value + */ + writeUint32(fieldNumber, value) { + this.writeTag(fieldNumber, WireType.VARINT); + this.writeUint32Value_(value); + } + + /** + * Writes the bits of a 64 bit number to the buffer as a varint. + * @param {number} highBits + * @param {number} lowBits + * @private + */ + writeVarint64_(highBits, lowBits) { + for (let i = 0; i < 28; i = i + 7) { + const shift = lowBits >>> i; + const hasNext = !((shift >>> 7) === 0 && highBits === 0); + const byte = (hasNext ? shift | 0x80 : shift) & 0xFF; + this.currentBuffer_.push(byte); + if (!hasNext) { + return; + } + } + + const splitBits = ((lowBits >>> 28) & 0x0F) | ((highBits & 0x07) << 4); + const hasMoreBits = !((highBits >> 3) === 0); + this.currentBuffer_.push( + (hasMoreBits ? splitBits | 0x80 : splitBits) & 0xFF); + + if (!hasMoreBits) { + return; + } + + for (let i = 3; i < 31; i = i + 7) { + const shift = highBits >>> i; + const hasNext = !((shift >>> 7) === 0); + const byte = (hasNext ? shift | 0x80 : shift) & 0xFF; + this.currentBuffer_.push(byte); + if (!hasNext) { + return; + } + } + + this.currentBuffer_.push((highBits >>> 31) & 0x01); + } + + /** + * Writes a sint32 value field to the buffer as a varint without tag. + * @param {number} value + * @private + */ + writeSint32Value_(value) { + value = (value << 1) ^ (value >> 31); + this.writeVarint64_(0, value); + } + + /** + * Writes a sint32 value field to the buffer as a varint. + * @param {number} fieldNumber + * @param {number} value + */ + writeSint32(fieldNumber, value) { + this.writeTag(fieldNumber, WireType.VARINT); + this.writeSint32Value_(value); + } + + /** + * Writes a sint64 value field to the buffer as a varint without tag. + * @param {!Int64} value + * @private + */ + writeSint64Value_(value) { + const highBits = value.getHighBits(); + const lowBits = value.getLowBits(); + + const sign = highBits >> 31; + const encodedLowBits = (lowBits << 1) ^ sign; + const encodedHighBits = ((highBits << 1) | (lowBits >>> 31)) ^ sign; + this.writeVarint64_(encodedHighBits, encodedLowBits); + } + + /** + * Writes a sint64 value field to the buffer as a varint. + * @param {number} fieldNumber + * @param {!Int64} value + */ + writeSint64(fieldNumber, value) { + this.writeTag(fieldNumber, WireType.VARINT); + this.writeSint64Value_(value); + } + + /** + * Writes a string value field to the buffer as a varint. + * @param {number} fieldNumber + * @param {string} value + */ + writeString(fieldNumber, value) { + this.writeTag(fieldNumber, WireType.DELIMITED); + const array = encoderFunction(value); + this.writeUnsignedVarint32_(array.length); + this.closeAndStartNewBuffer_(); + this.blocks_.push(array); + } + + /** + * Writes raw bytes to the buffer. + * @param {!ArrayBuffer} arrayBuffer + * @private + */ + writeRaw_(arrayBuffer) { + this.closeAndStartNewBuffer_(); + this.blocks_.push(new Uint8Array(arrayBuffer)); + } + + /** + * Writes raw bytes to the buffer. + * @param {!BufferDecoder} bufferDecoder + * @param {number} start + * @param {!WireType} wireType + * @param {number} fieldNumber + * @package + */ + writeBufferDecoder(bufferDecoder, start, wireType, fieldNumber) { + this.closeAndStartNewBuffer_(); + const dataLength = + getTagLength(bufferDecoder, start, wireType, fieldNumber); + this.blocks_.push( + bufferDecoder.subBufferDecoder(start, dataLength).asUint8Array()); + } + + /** + * Write the whole bytes as a length delimited field. + * @param {number} fieldNumber + * @param {!ArrayBuffer} arrayBuffer + */ + writeDelimited(fieldNumber, arrayBuffer) { + this.writeTag(fieldNumber, WireType.DELIMITED); + this.writeUnsignedVarint32_(arrayBuffer.byteLength); + this.writeRaw_(arrayBuffer); + } + + /**************************************************************************** + * REPEATED METHODS + ****************************************************************************/ + + /** + * Writes repeated boolean values to the buffer as unpacked varints. + * @param {number} fieldNumber + * @param {!Array} values + */ + writeRepeatedBool(fieldNumber, values) { + values.forEach(val => this.writeBool(fieldNumber, val)); + } + + /** + * Writes repeated boolean values to the buffer as packed varints. + * @param {number} fieldNumber + * @param {!Array} values + */ + writePackedBool(fieldNumber, values) { + this.writeFixedPacked_( + fieldNumber, values, val => this.writeBoolValue_(val), 1); + } + + /** + * Writes repeated double values to the buffer as unpacked fixed64. + * @param {number} fieldNumber + * @param {!Array} values + */ + writeRepeatedDouble(fieldNumber, values) { + values.forEach(val => this.writeDouble(fieldNumber, val)); + } + + /** + * Writes repeated double values to the buffer as packed fixed64. + * @param {number} fieldNumber + * @param {!Array} values + */ + writePackedDouble(fieldNumber, values) { + this.writeFixedPacked_( + fieldNumber, values, val => this.writeDoubleValue_(val), 8); + } + + /** + * Writes repeated fixed32 values to the buffer as unpacked fixed32. + * @param {number} fieldNumber + * @param {!Array} values + */ + writeRepeatedFixed32(fieldNumber, values) { + values.forEach(val => this.writeFixed32(fieldNumber, val)); + } + + /** + * Writes repeated fixed32 values to the buffer as packed fixed32. + * @param {number} fieldNumber + * @param {!Array} values + */ + writePackedFixed32(fieldNumber, values) { + this.writeFixedPacked_( + fieldNumber, values, val => this.writeFixed32Value_(val), 4); + } + + /** + * Writes repeated float values to the buffer as unpacked fixed64. + * @param {number} fieldNumber + * @param {!Array} values + */ + writeRepeatedFloat(fieldNumber, values) { + values.forEach(val => this.writeFloat(fieldNumber, val)); + } + + /** + * Writes repeated float values to the buffer as packed fixed64. + * @param {number} fieldNumber + * @param {!Array} values + */ + writePackedFloat(fieldNumber, values) { + this.writeFixedPacked_( + fieldNumber, values, val => this.writeFloatValue_(val), 4); + } + + /** + * Writes repeated int32 values to the buffer as unpacked int32. + * @param {number} fieldNumber + * @param {!Array} values + */ + writeRepeatedInt32(fieldNumber, values) { + values.forEach(val => this.writeInt32(fieldNumber, val)); + } + + /** + * Writes repeated int32 values to the buffer as packed int32. + * @param {number} fieldNumber + * @param {!Array} values + */ + writePackedInt32(fieldNumber, values) { + this.writeVariablePacked_( + fieldNumber, values, (writer, val) => writer.writeInt32Value_(val)); + } + + /** + * Writes repeated int64 values to the buffer as unpacked varint. + * @param {number} fieldNumber + * @param {!Array} values + */ + writeRepeatedInt64(fieldNumber, values) { + values.forEach(val => this.writeInt64(fieldNumber, val)); + } + + /** + * Writes repeated int64 values to the buffer as packed varint. + * @param {number} fieldNumber + * @param {!Array} values + */ + writePackedInt64(fieldNumber, values) { + this.writeVariablePacked_( + fieldNumber, values, + (writer, val) => + writer.writeVarint64_(val.getHighBits(), val.getLowBits())); + } + + /** + * Writes repeated sfixed32 values to the buffer as unpacked fixed32. + * @param {number} fieldNumber + * @param {!Array} values + */ + writeRepeatedSfixed32(fieldNumber, values) { + values.forEach(val => this.writeSfixed32(fieldNumber, val)); + } + + /** + * Writes repeated sfixed32 values to the buffer as packed fixed32. + * @param {number} fieldNumber + * @param {!Array} values + */ + writePackedSfixed32(fieldNumber, values) { + this.writeFixedPacked_( + fieldNumber, values, val => this.writeSfixed32Value_(val), 4); + } + + /** + * Writes repeated sfixed64 values to the buffer as unpacked fixed64. + * @param {number} fieldNumber + * @param {!Array} values + */ + writeRepeatedSfixed64(fieldNumber, values) { + values.forEach(val => this.writeSfixed64(fieldNumber, val)); + } + + /** + * Writes repeated sfixed64 values to the buffer as packed fixed64. + * @param {number} fieldNumber + * @param {!Array} values + */ + writePackedSfixed64(fieldNumber, values) { + this.writeFixedPacked_( + fieldNumber, values, val => this.writeSfixed64Value_(val), 8); + } + + /** + * Writes repeated sint32 values to the buffer as unpacked sint32. + * @param {number} fieldNumber + * @param {!Array} values + */ + writeRepeatedSint32(fieldNumber, values) { + values.forEach(val => this.writeSint32(fieldNumber, val)); + } + + /** + * Writes repeated sint32 values to the buffer as packed sint32. + * @param {number} fieldNumber + * @param {!Array} values + */ + writePackedSint32(fieldNumber, values) { + this.writeVariablePacked_( + fieldNumber, values, (writer, val) => writer.writeSint32Value_(val)); + } + + /** + * Writes repeated sint64 values to the buffer as unpacked varint. + * @param {number} fieldNumber + * @param {!Array} values + */ + writeRepeatedSint64(fieldNumber, values) { + values.forEach(val => this.writeSint64(fieldNumber, val)); + } + + /** + * Writes repeated sint64 values to the buffer as packed varint. + * @param {number} fieldNumber + * @param {!Array} values + */ + writePackedSint64(fieldNumber, values) { + this.writeVariablePacked_( + fieldNumber, values, (writer, val) => writer.writeSint64Value_(val)); + } + + /** + * Writes repeated uint32 values to the buffer as unpacked uint32. + * @param {number} fieldNumber + * @param {!Array} values + */ + writeRepeatedUint32(fieldNumber, values) { + values.forEach(val => this.writeUint32(fieldNumber, val)); + } + + /** + * Writes repeated uint32 values to the buffer as packed uint32. + * @param {number} fieldNumber + * @param {!Array} values + */ + writePackedUint32(fieldNumber, values) { + this.writeVariablePacked_( + fieldNumber, values, (writer, val) => writer.writeUint32Value_(val)); + } + + /** + * Writes repeated bytes values to the buffer. + * @param {number} fieldNumber + * @param {!Array} values + */ + writeRepeatedBytes(fieldNumber, values) { + values.forEach(val => this.writeBytes(fieldNumber, val)); + } + + /** + * Writes packed fields with fixed length. + * @param {number} fieldNumber + * @param {!Array} values + * @param {function(T)} valueWriter + * @param {number} entitySize + * @template T + * @private + */ + writeFixedPacked_(fieldNumber, values, valueWriter, entitySize) { + if (values.length === 0) { + return; + } + this.writeTag(fieldNumber, WireType.DELIMITED); + this.writeUnsignedVarint32_(values.length * entitySize); + this.closeAndStartNewBuffer_(); + values.forEach(value => valueWriter(value)); + } + + /** + * Writes packed fields with variable length. + * @param {number} fieldNumber + * @param {!Array} values + * @param {function(!Writer, T)} valueWriter + * @template T + * @private + */ + writeVariablePacked_(fieldNumber, values, valueWriter) { + if (values.length === 0) { + return; + } + const writer = new Writer(); + values.forEach(val => valueWriter(writer, val)); + const bytes = writer.getAndResetResultBuffer(); + this.writeDelimited(fieldNumber, bytes); + } + + /** + * Writes repeated string values to the buffer. + * @param {number} fieldNumber + * @param {!Array} values + */ + writeRepeatedString(fieldNumber, values) { + values.forEach(val => this.writeString(fieldNumber, val)); + } +} + +exports = Writer; diff --git a/js/experimental/runtime/kernel/writer_test.js b/js/experimental/runtime/kernel/writer_test.js new file mode 100644 index 0000000000000..019ae1e18aa61 --- /dev/null +++ b/js/experimental/runtime/kernel/writer_test.js @@ -0,0 +1,927 @@ +/** + * @fileoverview Tests for writer.js. + */ +goog.module('protobuf.binary.WriterTest'); + +goog.setTestOnly(); + +// Note to the reader: +// Since the writer behavior changes with the checking level some of the tests +// in this file have to know which checking level is enable to make correct +// assertions. +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const ByteString = goog.require('protobuf.ByteString'); +const WireType = goog.require('protobuf.binary.WireType'); +const Writer = goog.require('protobuf.binary.Writer'); +const {CHECK_BOUNDS, CHECK_TYPE, MAX_FIELD_NUMBER} = goog.require('protobuf.internal.checks'); +const {arrayBufferSlice} = goog.require('protobuf.binary.typedArrays'); +const {getDoublePairs} = goog.require('protobuf.binary.doubleTestPairs'); +const {getFixed32Pairs} = goog.require('protobuf.binary.fixed32TestPairs'); +const {getFloatPairs} = goog.require('protobuf.binary.floatTestPairs'); +const {getInt32Pairs} = goog.require('protobuf.binary.int32TestPairs'); +const {getInt64Pairs} = goog.require('protobuf.binary.int64TestPairs'); +const {getPackedBoolPairs} = goog.require('protobuf.binary.packedBoolTestPairs'); +const {getPackedDoublePairs} = goog.require('protobuf.binary.packedDoubleTestPairs'); +const {getPackedFixed32Pairs} = goog.require('protobuf.binary.packedFixed32TestPairs'); +const {getPackedFloatPairs} = goog.require('protobuf.binary.packedFloatTestPairs'); +const {getPackedInt32Pairs} = goog.require('protobuf.binary.packedInt32TestPairs'); +const {getPackedInt64Pairs} = goog.require('protobuf.binary.packedInt64TestPairs'); +const {getPackedSfixed32Pairs} = goog.require('protobuf.binary.packedSfixed32TestPairs'); +const {getPackedSfixed64Pairs} = goog.require('protobuf.binary.packedSfixed64TestPairs'); +const {getPackedSint32Pairs} = goog.require('protobuf.binary.packedSint32TestPairs'); +const {getPackedSint64Pairs} = goog.require('protobuf.binary.packedSint64TestPairs'); +const {getPackedUint32Pairs} = goog.require('protobuf.binary.packedUint32TestPairs'); +const {getSfixed32Pairs} = goog.require('protobuf.binary.sfixed32TestPairs'); +const {getSfixed64Pairs} = goog.require('protobuf.binary.sfixed64TestPairs'); +const {getSint32Pairs} = goog.require('protobuf.binary.sint32TestPairs'); +const {getSint64Pairs} = goog.require('protobuf.binary.sint64TestPairs'); +const {getUint32Pairs} = goog.require('protobuf.binary.uint32TestPairs'); + + +/** + * @param {...number} bytes + * @return {!ArrayBuffer} + */ +function createArrayBuffer(...bytes) { + return new Uint8Array(bytes).buffer; +} + +/****************************************************************************** + * OPTIONAL FUNCTIONS + ******************************************************************************/ + +describe('Writer does', () => { + it('return an empty ArrayBuffer when nothing is encoded', () => { + const writer = new Writer(); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + it('encode tag', () => { + const writer = new Writer(); + writer.writeTag(1, WireType.VARINT); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0x08)); + + writer.writeTag(0x0FFFFFFF, WireType.VARINT); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x7)); + + writer.writeTag(0x10000000, WireType.VARINT); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer(0x80, 0x80, 0x80, 0x80, 0x08)); + + writer.writeTag(0x1FFFFFFF, WireType.VARINT); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x0F)); + }); + + it('reset after calling getAndResetResultBuffer', () => { + const writer = new Writer(); + writer.writeTag(1, WireType.VARINT); + writer.getAndResetResultBuffer(); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + it('fail when field number is too large for writeTag', () => { + const writer = new Writer(); + if (CHECK_TYPE) { + expect(() => writer.writeTag(MAX_FIELD_NUMBER + 1, WireType.VARINT)) + .toThrowError('Field number is out of range: 536870912'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + writer.writeTag(MAX_FIELD_NUMBER + 1, WireType.VARINT); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0)); + } + }); + + it('fail when field number is negative for writeTag', () => { + const writer = new Writer(); + if (CHECK_TYPE) { + expect(() => writer.writeTag(-1, WireType.VARINT)) + .toThrowError('Field number is out of range: -1'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + writer.writeTag(-1, WireType.VARINT); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0xF)); + } + }); + + it('fail when wire type is invalid for writeTag', () => { + const writer = new Writer(); + if (CHECK_TYPE) { + expect(() => writer.writeTag(1, /** @type {!WireType} */ (0x08))) + .toThrowError('Invalid wire type: 8'); + } else { + // Note in unchecked mode we produce invalid output for invalid inputs. + // This test just documents our behavior in those cases. + // These values might change at any point and are not considered + // what the implementation should be doing here. + writer.writeTag(1, /** @type {!WireType} */ (0x08)); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0x08)); + } + }); + + it('encode singular boolean value', () => { + const writer = new Writer(); + writer.writeBool(1, true); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer(0x08, 0x01)); + }); + + it('encode length delimited', () => { + const writer = new Writer(); + writer.writeDelimited(1, createArrayBuffer(0x01, 0x02)); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer(0x0A, 0x02, 0x01, 0x02)); + }); +}); + +describe('Writer.writeBufferDecoder does', () => { + it('encode BufferDecoder containing a varint value', () => { + const writer = new Writer(); + const expected = createArrayBuffer( + 0x08, /* varint start= */ 0xFF, /* varint end= */ 0x01, 0x08, 0x01); + writer.writeBufferDecoder( + BufferDecoder.fromArrayBuffer(expected), 1, WireType.VARINT, 1); + const result = writer.getAndResetResultBuffer(); + expect(result).toEqual(arrayBufferSlice(expected, 1, 3)); + }); + + it('encode BufferDecoder containing a fixed64 value', () => { + const writer = new Writer(); + const expected = createArrayBuffer( + 0x09, /* fixed64 start= */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + /* fixed64 end= */ 0x08, 0x08, 0x01); + writer.writeBufferDecoder( + BufferDecoder.fromArrayBuffer(expected), 1, WireType.FIXED64, 1); + const result = writer.getAndResetResultBuffer(); + expect(result).toEqual(arrayBufferSlice(expected, 1, 9)); + }); + + it('encode BufferDecoder containing a length delimited value', () => { + const writer = new Writer(); + const expected = createArrayBuffer( + 0xA, /* length= */ 0x03, /* data start= */ 0x01, 0x02, + /* data end= */ 0x03, 0x08, 0x01); + writer.writeBufferDecoder( + BufferDecoder.fromArrayBuffer(expected), 1, WireType.DELIMITED, 1); + const result = writer.getAndResetResultBuffer(); + expect(result).toEqual(arrayBufferSlice(expected, 1, 5)); + }); + + it('encode BufferDecoder containing a group', () => { + const writer = new Writer(); + const expected = createArrayBuffer( + 0xB, /* group start= */ 0x08, 0x01, /* nested group start= */ 0x0B, + /* nested group end= */ 0x0C, /* group end= */ 0x0C, 0x08, 0x01); + writer.writeBufferDecoder( + BufferDecoder.fromArrayBuffer(expected), 1, WireType.START_GROUP, 1); + const result = writer.getAndResetResultBuffer(); + expect(result).toEqual(arrayBufferSlice(expected, 1, 6)); + }); + + it('encode BufferDecoder containing a fixed32 value', () => { + const writer = new Writer(); + const expected = createArrayBuffer( + 0x09, /* fixed64 start= */ 0x01, 0x02, 0x03, /* fixed64 end= */ 0x04, + 0x08, 0x01); + writer.writeBufferDecoder( + BufferDecoder.fromArrayBuffer(expected), 1, WireType.FIXED32, 1); + const result = writer.getAndResetResultBuffer(); + expect(result).toEqual(arrayBufferSlice(expected, 1, 5)); + }); + + it('fail when encoding out of bound data', () => { + const writer = new Writer(); + const buffer = createArrayBuffer(0x4, 0x0, 0x1, 0x2, 0x3); + const subBuffer = arrayBufferSlice(buffer, 0, 2); + expect( + () => writer.writeBufferDecoder( + BufferDecoder.fromArrayBuffer(subBuffer), 0, WireType.DELIMITED, 1)) + .toThrow(); + }); +}); + +describe('Writer.writeBytes does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encodes empty ByteString', () => { + writer.writeBytes(1, ByteString.EMPTY); + const buffer = writer.getAndResetResultBuffer(); + expect(buffer.byteLength).toBe(2); + }); + + it('encodes empty array', () => { + writer.writeBytes(1, ByteString.fromArrayBuffer(new ArrayBuffer(0))); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer( + 1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited)) + 0, // length of the bytes + )); + }); + + it('encodes ByteString', () => { + const array = createArrayBuffer(1, 2, 3); + writer.writeBytes(1, ByteString.fromArrayBuffer(array)); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer( + 1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited)) + 3, // length of the bytes + 1, + 2, + 3, + )); + }); +}); + +describe('Writer.writeDouble does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + for (const pair of getDoublePairs()) { + it(`encode ${pair.name}`, () => { + writer.writeDouble(1, pair.doubleValue); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + expect(buffer.length).toBe(9); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x09); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, 9)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + + /** + * NaN may have different value in different browsers. Thus, we need to make + * the test lenient. + */ + it('encode NaN', () => { + writer.writeDouble(1, NaN); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + expect(buffer.length).toBe(9); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x09); + // Encoded values are stored right after the tag + const float64 = new DataView(buffer.buffer); + expect(float64.getFloat64(1, true)).toBeNaN(); + }); +}); + +describe('Writer.writeFixed32 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + for (const pair of getFixed32Pairs()) { + it(`encode ${pair.name}`, () => { + writer.writeFixed32(1, pair.intValue); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + expect(buffer.length).toBe(5); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0D); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array()); + }); + } +}); + +describe('Writer.writeFloat does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + for (const pair of getFloatPairs()) { + it(`encode ${pair.name}`, () => { + writer.writeFloat(1, pair.floatValue); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + expect(buffer.length).toBe(5); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0D); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + + /** + * NaN may have different value in different browsers. Thus, we need to make + * the test lenient. + */ + it('encode NaN', () => { + writer.writeFloat(1, NaN); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + expect(buffer.length).toBe(5); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0D); + // Encoded values are stored right after the tag + const float32 = new DataView(buffer.buffer); + expect(float32.getFloat32(1, true)).toBeNaN(); + }); +}); + +describe('Writer.writeInt32 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + for (const pair of getInt32Pairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writeInt32(1, pair.intValue); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x08); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writeSfixed32 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writePackedSfixed32(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + for (const pair of getSfixed32Pairs()) { + it(`encode ${pair.name}`, () => { + writer.writeSfixed32(1, pair.intValue); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + expect(buffer.length).toBe(5); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0D); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array()); + }); + } +}); + +describe('Writer.writeSfixed64 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + for (const pair of getSfixed64Pairs()) { + it(`encode ${pair.name}`, () => { + writer.writeSfixed64(1, pair.longValue); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + expect(buffer.length).toBe(9); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x09); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, 9)).toEqual(pair.bufferDecoder.asUint8Array()); + }); + } +}); + +describe('Writer.writeSint32 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + for (const pair of getSint32Pairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writeSint32(1, pair.intValue); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x08); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writeSint64 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + for (const pair of getSint64Pairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writeSint64(1, pair.longValue); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x08); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writeInt64 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + for (const pair of getInt64Pairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writeInt64(1, pair.longValue); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x08); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writeUint32 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + for (const pair of getUint32Pairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writeUint32(1, pair.intValue); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x08); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writeString does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty string', () => { + writer.writeString(1, ''); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer( + 1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited)) + 0, // length of the string + )); + }); + + it('encode simple string', () => { + writer.writeString(1, 'hello'); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer( + 1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited)) + 5, // length of the string + 'h'.charCodeAt(0), + 'e'.charCodeAt(0), + 'l'.charCodeAt(0), + 'l'.charCodeAt(0), + 'o'.charCodeAt(0), + )); + }); + + it('throw for invalid fieldnumber', () => { + if (CHECK_BOUNDS) { + expect(() => writer.writeString(-1, 'a')) + .toThrowError('Field number is out of range: -1'); + } else { + writer.writeString(-1, 'a'); + expect(new Uint8Array(writer.getAndResetResultBuffer())) + .toEqual(new Uint8Array(createArrayBuffer( + -6, // invalid tag + 0xff, + 0xff, + 0xff, + 0x0f, + 1, // string length + 'a'.charCodeAt(0), + ))); + } + }); + + it('throw for null string value', () => { + expect( + () => writer.writeString( + 1, /** @type {string} */ (/** @type {*} */ (null)))) + .toThrow(); + }); +}); + + +/****************************************************************************** + * REPEATED FUNCTIONS + ******************************************************************************/ + +describe('Writer.writePackedBool does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writePackedBool(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + for (const pair of getPackedBoolPairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writePackedBool(1, pair.boolValues); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0A); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writeRepeatedBool does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writeRepeatedBool(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + it('encode repeated unpacked boolean values', () => { + const writer = new Writer(); + writer.writeRepeatedBool(1, [true, false]); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer( + 1 << 3 | 0x00, // tag (fieldnumber << 3 | (varint)) + 0x01, // value[0] + 1 << 3 | 0x00, // tag (fieldnumber << 3 | (varint)) + 0x00, // value[1] + )); + }); +}); + +describe('Writer.writePackedDouble does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writePackedDouble(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + for (const pair of getPackedDoublePairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writePackedDouble(1, pair.doubleValues); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0A); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writePackedFixed32 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writePackedFixed32(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + for (const pair of getPackedFixed32Pairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writePackedFixed32(1, pair.fixed32Values); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0A); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writePackedFloat does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writePackedFloat(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + for (const pair of getPackedFloatPairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writePackedFloat(1, pair.floatValues); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0A); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writePackedInt32 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writePackedInt32(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + for (const pair of getPackedInt32Pairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writePackedInt32(1, pair.int32Values); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0A); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writePackedInt64 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writePackedInt64(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + for (const pair of getPackedInt64Pairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writePackedInt64(1, pair.int64Values); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0A); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writePackedSfixed32 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writePackedSfixed32(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + for (const pair of getPackedSfixed32Pairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writePackedSfixed32(1, pair.sfixed32Values); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0A); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writePackedSfixed64 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writePackedSfixed64(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + for (const pair of getPackedSfixed64Pairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writePackedSfixed64(1, pair.sfixed64Values); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0A); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writePackedSint32 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writePackedSint32(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + for (const pair of getPackedSint32Pairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writePackedSint32(1, pair.sint32Values); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0A); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writePackedSint64 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writePackedSint64(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + for (const pair of getPackedSint64Pairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writePackedSint64(1, pair.sint64Values); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0A); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writePackedUint32 does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writePackedUint32(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + for (const pair of getPackedUint32Pairs()) { + if (!pair.skip_writer) { + it(`encode ${pair.name}`, () => { + writer.writePackedUint32(1, pair.uint32Values); + const buffer = new Uint8Array(writer.getAndResetResultBuffer()); + // ensure we have a correct tag + expect(buffer[0]).toEqual(0x0A); + // Encoded values are stored right after the tag + expect(buffer.subarray(1, buffer.length)) + .toEqual(pair.bufferDecoder.asUint8Array()); + }); + } + } +}); + +describe('Writer.writeRepeatedBytes does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writeRepeatedBytes(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + it('encode single value', () => { + const value = createArrayBuffer(0x61); + writer.writeRepeatedBytes(1, [ByteString.fromArrayBuffer(value)]); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer( + 0x0A, + 0x01, + 0x61, // a + )); + }); + + it('encode multiple values', () => { + const value1 = createArrayBuffer(0x61); + const value2 = createArrayBuffer(0x62); + writer.writeRepeatedBytes(1, [ + ByteString.fromArrayBuffer(value1), + ByteString.fromArrayBuffer(value2), + ]); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer( + 0x0A, + 0x01, + 0x61, // a + 0x0A, + 0x01, + 0x62, // b + )); + }); +}); + +describe('Writer.writeRepeatedString does', () => { + let writer; + beforeEach(() => { + writer = new Writer(); + }); + + it('encode empty array', () => { + writer.writeRepeatedString(1, []); + expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer()); + }); + + it('encode single value', () => { + writer.writeRepeatedString(1, ['a']); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer( + 0x0A, + 0x01, + 0x61, // a + )); + }); + + it('encode multiple values', () => { + writer.writeRepeatedString(1, ['a', 'b']); + expect(writer.getAndResetResultBuffer()) + .toEqual(createArrayBuffer( + 0x0A, + 0x01, + 0x61, // a + 0x0A, + 0x01, + 0x62, // b + )); + }); +}); diff --git a/js/experimental/runtime/testing/binary/test_message.js b/js/experimental/runtime/testing/binary/test_message.js new file mode 100644 index 0000000000000..cfd264b324979 --- /dev/null +++ b/js/experimental/runtime/testing/binary/test_message.js @@ -0,0 +1,1769 @@ +/** + * @fileoverview Kernel wrapper message. + */ +goog.module('protobuf.testing.binary.TestMessage'); + +const ByteString = goog.require('protobuf.ByteString'); +const Int64 = goog.require('protobuf.Int64'); +const InternalMessage = goog.require('protobuf.binary.InternalMessage'); +const Kernel = goog.require('protobuf.runtime.Kernel'); + +/** + * A protobuf message implemented as a Kernel wrapper. + * @implements {InternalMessage} + */ +class TestMessage { + /** + * @return {!TestMessage} + */ + static createEmpty() { + return TestMessage.instanceCreator(Kernel.createEmpty()); + } + + /** + * @param {!Kernel} kernel + * @return {!TestMessage} + */ + static instanceCreator(kernel) { + return new TestMessage(kernel); + } + + /** + * @param {!Kernel} kernel + */ + constructor(kernel) { + /** @private @const {!Kernel} */ + this.kernel_ = kernel; + } + + /** + * @override + * @return {!Kernel} + */ + internalGetKernel() { + return this.kernel_; + } + + /** + * @return {!ArrayBuffer} + */ + serialize() { + return this.kernel_.serialize(); + } + + /** + * @param {number} fieldNumber + * @param {boolean=} defaultValue + * @return {boolean} + */ + getBoolWithDefault(fieldNumber, defaultValue = false) { + return this.kernel_.getBoolWithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {!ByteString=} defaultValue + * @return {!ByteString} + */ + getBytesWithDefault(fieldNumber, defaultValue = ByteString.EMPTY) { + return this.kernel_.getBytesWithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {number=} defaultValue + * @return {number} + */ + getDoubleWithDefault(fieldNumber, defaultValue = 0) { + return this.kernel_.getDoubleWithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {number=} defaultValue + * @return {number} + */ + getFixed32WithDefault(fieldNumber, defaultValue = 0) { + return this.kernel_.getFixed32WithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {!Int64=} defaultValue + * @return {!Int64} + */ + getFixed64WithDefault(fieldNumber, defaultValue = Int64.getZero()) { + return this.kernel_.getFixed64WithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {number=} defaultValue + * @return {number} + */ + getFloatWithDefault(fieldNumber, defaultValue = 0) { + return this.kernel_.getFloatWithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {number=} defaultValue + * @return {number} + */ + getInt32WithDefault(fieldNumber, defaultValue = 0) { + return this.kernel_.getInt32WithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {!Int64=} defaultValue + * @return {!Int64} + */ + getInt64WithDefault(fieldNumber, defaultValue = Int64.getZero()) { + return this.kernel_.getInt64WithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {number=} defaultValue + * @return {number} + */ + getSfixed32WithDefault(fieldNumber, defaultValue = 0) { + return this.kernel_.getSfixed32WithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {!Int64=} defaultValue + * @return {!Int64} + */ + getSfixed64WithDefault(fieldNumber, defaultValue = Int64.getZero()) { + return this.kernel_.getSfixed64WithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {number=} defaultValue + * @return {number} + */ + getSint32WithDefault(fieldNumber, defaultValue = 0) { + return this.kernel_.getSint32WithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {!Int64=} defaultValue + * @return {!Int64} + */ + getSint64WithDefault(fieldNumber, defaultValue = Int64.getZero()) { + return this.kernel_.getSint64WithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {string=} defaultValue + * @return {string} + */ + getStringWithDefault(fieldNumber, defaultValue = '') { + return this.kernel_.getStringWithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {number=} defaultValue + * @return {number} + */ + getUint32WithDefault(fieldNumber, defaultValue = 0) { + return this.kernel_.getUint32WithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {!Int64=} defaultValue + * @return {!Int64} + */ + getUint64WithDefault(fieldNumber, defaultValue = Int64.getZero()) { + return this.kernel_.getUint64WithDefault(fieldNumber, defaultValue); + } + + /** + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @return {?T} + * @template T + */ + getMessageOrNull(fieldNumber, instanceCreator) { + return this.kernel_.getMessageOrNull(fieldNumber, instanceCreator); + } + + /** + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @return {T} + * @template T + */ + getMessageAttach(fieldNumber, instanceCreator) { + return this.kernel_.getMessageAttach(fieldNumber, instanceCreator); + } + + /** + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @return {T} + * @template T + */ + getMessage(fieldNumber, instanceCreator) { + return this.kernel_.getMessage(fieldNumber, instanceCreator); + } + + /** + * @param {number} fieldNumber + * @return {?Kernel} + * @template T + */ + getMessageAccessorOrNull(fieldNumber) { + return this.kernel_.getMessageAccessorOrNull(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @return {boolean} + */ + getRepeatedBoolElement(fieldNumber, index) { + return this.kernel_.getRepeatedBoolElement(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedBoolIterable(fieldNumber) { + return this.kernel_.getRepeatedBoolIterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedBoolSize(fieldNumber) { + return this.kernel_.getRepeatedBoolSize(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @return {number} + */ + getRepeatedDoubleElement(fieldNumber, index) { + return this.kernel_.getRepeatedDoubleElement(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedDoubleIterable(fieldNumber) { + return this.kernel_.getRepeatedDoubleIterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedDoubleSize(fieldNumber) { + return this.kernel_.getRepeatedDoubleSize(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @return {number} + */ + getRepeatedFixed32Element(fieldNumber, index) { + return this.kernel_.getRepeatedFixed32Element(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedFixed32Iterable(fieldNumber) { + return this.kernel_.getRepeatedFixed32Iterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedFixed32Size(fieldNumber) { + return this.kernel_.getRepeatedFixed32Size(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @return {!Int64} + */ + getRepeatedFixed64Element(fieldNumber, index) { + return this.kernel_.getRepeatedFixed64Element(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedFixed64Iterable(fieldNumber) { + return this.kernel_.getRepeatedFixed64Iterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedFixed64Size(fieldNumber) { + return this.kernel_.getRepeatedFixed64Size(fieldNumber); + } + /** + * @param {number} fieldNumber + * @param {number} index + * @return {number} + */ + getRepeatedFloatElement(fieldNumber, index) { + return this.kernel_.getRepeatedFloatElement(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedFloatIterable(fieldNumber) { + return this.kernel_.getRepeatedFloatIterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedFloatSize(fieldNumber) { + return this.kernel_.getRepeatedFloatSize(fieldNumber); + } + /** + * @param {number} fieldNumber + * @param {number} index + * @return {number} + */ + getRepeatedInt32Element(fieldNumber, index) { + return this.kernel_.getRepeatedInt32Element(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedInt32Iterable(fieldNumber) { + return this.kernel_.getRepeatedInt32Iterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedInt32Size(fieldNumber) { + return this.kernel_.getRepeatedInt32Size(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @return {!Int64} + */ + getRepeatedInt64Element(fieldNumber, index) { + return this.kernel_.getRepeatedInt64Element(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedInt64Iterable(fieldNumber) { + return this.kernel_.getRepeatedInt64Iterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedInt64Size(fieldNumber) { + return this.kernel_.getRepeatedInt64Size(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @return {number} + */ + getRepeatedSfixed32Element(fieldNumber, index) { + return this.kernel_.getRepeatedSfixed32Element(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedSfixed32Iterable(fieldNumber) { + return this.kernel_.getRepeatedSfixed32Iterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedSfixed32Size(fieldNumber) { + return this.kernel_.getRepeatedSfixed32Size(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @return {!Int64} + */ + getRepeatedSfixed64Element(fieldNumber, index) { + return this.kernel_.getRepeatedSfixed64Element(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedSfixed64Iterable(fieldNumber) { + return this.kernel_.getRepeatedSfixed64Iterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedSfixed64Size(fieldNumber) { + return this.kernel_.getRepeatedSfixed64Size(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @return {number} + */ + getRepeatedSint32Element(fieldNumber, index) { + return this.kernel_.getRepeatedSint32Element(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedSint32Iterable(fieldNumber) { + return this.kernel_.getRepeatedSint32Iterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedSint32Size(fieldNumber) { + return this.kernel_.getRepeatedSint32Size(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @return {!Int64} + */ + getRepeatedSint64Element(fieldNumber, index) { + return this.kernel_.getRepeatedSint64Element(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedSint64Iterable(fieldNumber) { + return this.kernel_.getRepeatedSint64Iterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedSint64Size(fieldNumber) { + return this.kernel_.getRepeatedSint64Size(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @return {number} + */ + getRepeatedUint32Element(fieldNumber, index) { + return this.kernel_.getRepeatedUint32Element(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedUint32Iterable(fieldNumber) { + return this.kernel_.getRepeatedUint32Iterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedUint32Size(fieldNumber) { + return this.kernel_.getRepeatedUint32Size(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @return {!Int64} + */ + getRepeatedUint64Element(fieldNumber, index) { + return this.kernel_.getRepeatedUint64Element(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedUint64Iterable(fieldNumber) { + return this.kernel_.getRepeatedUint64Iterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedUint64Size(fieldNumber) { + return this.kernel_.getRepeatedUint64Size(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @return {!ByteString} + */ + getRepeatedBytesElement(fieldNumber, index) { + return this.kernel_.getRepeatedBytesElement(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedBytesIterable(fieldNumber) { + return this.kernel_.getRepeatedBytesIterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedBytesSize(fieldNumber) { + return this.kernel_.getRepeatedBytesSize(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @return {string} + */ + getRepeatedStringElement(fieldNumber, index) { + return this.kernel_.getRepeatedStringElement(fieldNumber, index); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + */ + getRepeatedStringIterable(fieldNumber) { + return this.kernel_.getRepeatedStringIterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @return {number} + */ + getRepeatedStringSize(fieldNumber) { + return this.kernel_.getRepeatedStringSize(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @param {number} index + * @return {T} + * @template T + */ + getRepeatedMessageElement(fieldNumber, instanceCreator, index) { + return this.kernel_.getRepeatedMessageElement( + fieldNumber, instanceCreator, index); + } + + /** + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @return {!Iterable} + * @template T + */ + getRepeatedMessageIterable(fieldNumber, instanceCreator) { + return this.kernel_.getRepeatedMessageIterable( + fieldNumber, instanceCreator); + } + + /** + * @param {number} fieldNumber + * @return {!Iterable} + * @template T + */ + getRepeatedMessageAccessorIterable(fieldNumber) { + return this.kernel_.getRepeatedMessageAccessorIterable(fieldNumber); + } + + /** + * @param {number} fieldNumber + * @param {function(!Kernel):T} instanceCreator + * @return {number} + * @template T + */ + getRepeatedMessageSize(fieldNumber, instanceCreator) { + return this.kernel_.getRepeatedMessageSize(fieldNumber, instanceCreator); + } + + /** + * @param {number} fieldNumber + * @param {boolean} value + */ + setBool(fieldNumber, value) { + this.kernel_.setBool(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!ByteString} value + */ + setBytes(fieldNumber, value) { + this.kernel_.setBytes(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + setDouble(fieldNumber, value) { + this.kernel_.setDouble(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + setFixed32(fieldNumber, value) { + this.kernel_.setFixed32(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + setFixed64(fieldNumber, value) { + this.kernel_.setFixed64(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + setFloat(fieldNumber, value) { + this.kernel_.setFloat(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + setInt32(fieldNumber, value) { + this.kernel_.setInt32(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + setInt64(fieldNumber, value) { + this.kernel_.setInt64(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + setSfixed32(fieldNumber, value) { + this.kernel_.setSfixed32(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + setSfixed64(fieldNumber, value) { + this.kernel_.setSfixed64(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + setSint32(fieldNumber, value) { + this.kernel_.setSint32(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + setSint64(fieldNumber, value) { + this.kernel_.setSint64(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {string} value + */ + setString(fieldNumber, value) { + this.kernel_.setString(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + setUint32(fieldNumber, value) { + this.kernel_.setUint32(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + setUint64(fieldNumber, value) { + this.kernel_.setUint64(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {T} value + * @template T + */ + setMessage(fieldNumber, value) { + this.kernel_.setMessage(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {boolean} value + */ + addPackedBoolElement(fieldNumber, value) { + this.kernel_.addPackedBoolElement(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedBoolIterable(fieldNumber, values) { + this.kernel_.addPackedBoolIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {boolean} value + */ + addUnpackedBoolElement(fieldNumber, value) { + this.kernel_.addUnpackedBoolElement(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedBoolIterable(fieldNumber, values) { + this.kernel_.addUnpackedBoolIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {boolean} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedBoolElement(fieldNumber, index, value) { + this.kernel_.setPackedBoolElement(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedBoolIterable(fieldNumber, values) { + this.kernel_.setPackedBoolIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {boolean} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedBoolElement(fieldNumber, index, value) { + this.kernel_.setUnpackedBoolElement(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedBoolIterable(fieldNumber, values) { + this.kernel_.setUnpackedBoolIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + addPackedDoubleElement(fieldNumber, value) { + this.kernel_.addPackedDoubleElement(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedDoubleIterable(fieldNumber, values) { + this.kernel_.addPackedDoubleIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + addUnpackedDoubleElement(fieldNumber, value) { + this.kernel_.addUnpackedDoubleElement(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedDoubleIterable(fieldNumber, values) { + this.kernel_.addUnpackedDoubleIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedDoubleElement(fieldNumber, index, value) { + this.kernel_.setPackedDoubleElement(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedDoubleIterable(fieldNumber, values) { + this.kernel_.setPackedDoubleIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedDoubleElement(fieldNumber, index, value) { + this.kernel_.setUnpackedDoubleElement(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedDoubleIterable(fieldNumber, values) { + this.kernel_.setUnpackedDoubleIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + addPackedFixed32Element(fieldNumber, value) { + this.kernel_.addPackedFixed32Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedFixed32Iterable(fieldNumber, values) { + this.kernel_.addPackedFixed32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + addUnpackedFixed32Element(fieldNumber, value) { + this.kernel_.addUnpackedFixed32Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedFixed32Iterable(fieldNumber, values) { + this.kernel_.addUnpackedFixed32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedFixed32Element(fieldNumber, index, value) { + this.kernel_.setPackedFixed32Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedFixed32Iterable(fieldNumber, values) { + this.kernel_.setPackedFixed32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedFixed32Element(fieldNumber, index, value) { + this.kernel_.setUnpackedFixed32Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedFixed32Iterable(fieldNumber, values) { + this.kernel_.setUnpackedFixed32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + addPackedFixed64Element(fieldNumber, value) { + this.kernel_.addPackedFixed64Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedFixed64Iterable(fieldNumber, values) { + this.kernel_.addPackedFixed64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + addUnpackedFixed64Element(fieldNumber, value) { + this.kernel_.addUnpackedFixed64Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedFixed64Iterable(fieldNumber, values) { + this.kernel_.addUnpackedFixed64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedFixed64Element(fieldNumber, index, value) { + this.kernel_.setPackedFixed64Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedFixed64Iterable(fieldNumber, values) { + this.kernel_.setPackedFixed64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedFixed64Element(fieldNumber, index, value) { + this.kernel_.setUnpackedFixed64Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedFixed64Iterable(fieldNumber, values) { + this.kernel_.setUnpackedFixed64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + addPackedFloatElement(fieldNumber, value) { + this.kernel_.addPackedFloatElement(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedFloatIterable(fieldNumber, values) { + this.kernel_.addPackedFloatIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + addUnpackedFloatElement(fieldNumber, value) { + this.kernel_.addUnpackedFloatElement(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedFloatIterable(fieldNumber, values) { + this.kernel_.addUnpackedFloatIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedFloatElement(fieldNumber, index, value) { + this.kernel_.setPackedFloatElement(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedFloatIterable(fieldNumber, values) { + this.kernel_.setPackedFloatIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedFloatElement(fieldNumber, index, value) { + this.kernel_.setUnpackedFloatElement(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedFloatIterable(fieldNumber, values) { + this.kernel_.setUnpackedFloatIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + addPackedInt32Element(fieldNumber, value) { + this.kernel_.addPackedInt32Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedInt32Iterable(fieldNumber, values) { + this.kernel_.addPackedInt32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + addUnpackedInt32Element(fieldNumber, value) { + this.kernel_.addUnpackedInt32Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedInt32Iterable(fieldNumber, values) { + this.kernel_.addUnpackedInt32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedInt32Element(fieldNumber, index, value) { + this.kernel_.setPackedInt32Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedInt32Iterable(fieldNumber, values) { + this.kernel_.setPackedInt32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedInt32Element(fieldNumber, index, value) { + this.kernel_.setUnpackedInt32Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedInt32Iterable(fieldNumber, values) { + this.kernel_.setUnpackedInt32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + addPackedInt64Element(fieldNumber, value) { + this.kernel_.addPackedInt64Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedInt64Iterable(fieldNumber, values) { + this.kernel_.addPackedInt64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + addUnpackedInt64Element(fieldNumber, value) { + this.kernel_.addUnpackedInt64Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedInt64Iterable(fieldNumber, values) { + this.kernel_.addUnpackedInt64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedInt64Element(fieldNumber, index, value) { + this.kernel_.setPackedInt64Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedInt64Iterable(fieldNumber, values) { + this.kernel_.setPackedInt64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedInt64Element(fieldNumber, index, value) { + this.kernel_.setUnpackedInt64Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedInt64Iterable(fieldNumber, values) { + this.kernel_.setUnpackedInt64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + addPackedSfixed32Element(fieldNumber, value) { + this.kernel_.addPackedSfixed32Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedSfixed32Iterable(fieldNumber, values) { + this.kernel_.addPackedSfixed32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + addUnpackedSfixed32Element(fieldNumber, value) { + this.kernel_.addUnpackedSfixed32Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedSfixed32Iterable(fieldNumber, values) { + this.kernel_.addUnpackedSfixed32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedSfixed32Element(fieldNumber, index, value) { + this.kernel_.setPackedSfixed32Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedSfixed32Iterable(fieldNumber, values) { + this.kernel_.setPackedSfixed32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedSfixed32Element(fieldNumber, index, value) { + this.kernel_.setUnpackedSfixed32Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedSfixed32Iterable(fieldNumber, values) { + this.kernel_.setUnpackedSfixed32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + addPackedSfixed64Element(fieldNumber, value) { + this.kernel_.addPackedSfixed64Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedSfixed64Iterable(fieldNumber, values) { + this.kernel_.addPackedSfixed64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + addUnpackedSfixed64Element(fieldNumber, value) { + this.kernel_.addUnpackedSfixed64Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedSfixed64Iterable(fieldNumber, values) { + this.kernel_.addUnpackedSfixed64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedSfixed64Element(fieldNumber, index, value) { + this.kernel_.setPackedSfixed64Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedSfixed64Iterable(fieldNumber, values) { + this.kernel_.setPackedSfixed64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedSfixed64Element(fieldNumber, index, value) { + this.kernel_.setUnpackedSfixed64Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedSfixed64Iterable(fieldNumber, values) { + this.kernel_.setUnpackedSfixed64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + addPackedSint32Element(fieldNumber, value) { + this.kernel_.addPackedSint32Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedSint32Iterable(fieldNumber, values) { + this.kernel_.addPackedSint32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + addUnpackedSint32Element(fieldNumber, value) { + this.kernel_.addUnpackedSint32Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedSint32Iterable(fieldNumber, values) { + this.kernel_.addUnpackedSint32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedSint32Element(fieldNumber, index, value) { + this.kernel_.setPackedSint32Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedSint32Iterable(fieldNumber, values) { + this.kernel_.setPackedSint32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedSint32Element(fieldNumber, index, value) { + this.kernel_.setUnpackedSint32Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedSint32Iterable(fieldNumber, values) { + this.kernel_.setUnpackedSint32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + addPackedSint64Element(fieldNumber, value) { + this.kernel_.addPackedSint64Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedSint64Iterable(fieldNumber, values) { + this.kernel_.addPackedSint64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + addUnpackedSint64Element(fieldNumber, value) { + this.kernel_.addUnpackedSint64Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedSint64Iterable(fieldNumber, values) { + this.kernel_.addUnpackedSint64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedSint64Element(fieldNumber, index, value) { + this.kernel_.setPackedSint64Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedSint64Iterable(fieldNumber, values) { + this.kernel_.setPackedSint64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedSint64Element(fieldNumber, index, value) { + this.kernel_.setUnpackedSint64Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedSint64Iterable(fieldNumber, values) { + this.kernel_.setUnpackedSint64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + addPackedUint32Element(fieldNumber, value) { + this.kernel_.addPackedUint32Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedUint32Iterable(fieldNumber, values) { + this.kernel_.addPackedUint32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} value + */ + addUnpackedUint32Element(fieldNumber, value) { + this.kernel_.addUnpackedUint32Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedUint32Iterable(fieldNumber, values) { + this.kernel_.addUnpackedUint32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedUint32Element(fieldNumber, index, value) { + this.kernel_.setPackedUint32Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedUint32Iterable(fieldNumber, values) { + this.kernel_.setPackedUint32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {number} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedUint32Element(fieldNumber, index, value) { + this.kernel_.setUnpackedUint32Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedUint32Iterable(fieldNumber, values) { + this.kernel_.setUnpackedUint32Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + addPackedUint64Element(fieldNumber, value) { + this.kernel_.addPackedUint64Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addPackedUint64Iterable(fieldNumber, values) { + this.kernel_.addPackedUint64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {!Int64} value + */ + addUnpackedUint64Element(fieldNumber, value) { + this.kernel_.addUnpackedUint64Element(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addUnpackedUint64Iterable(fieldNumber, values) { + this.kernel_.addUnpackedUint64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setPackedUint64Element(fieldNumber, index, value) { + this.kernel_.setPackedUint64Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setPackedUint64Iterable(fieldNumber, values) { + this.kernel_.setPackedUint64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {!Int64} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setUnpackedUint64Element(fieldNumber, index, value) { + this.kernel_.setUnpackedUint64Element(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setUnpackedUint64Iterable(fieldNumber, values) { + this.kernel_.setUnpackedUint64Iterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setRepeatedBytesIterable(fieldNumber, values) { + this.kernel_.setRepeatedBytesIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addRepeatedBytesIterable(fieldNumber, values) { + this.kernel_.addRepeatedBytesIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {!ByteString} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setRepeatedBytesElement(fieldNumber, index, value) { + this.kernel_.setRepeatedBytesElement(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {!ByteString} value + */ + addRepeatedBytesElement(fieldNumber, value) { + this.kernel_.addRepeatedBytesElement(fieldNumber, value); + } + + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + setRepeatedStringIterable(fieldNumber, values) { + this.kernel_.setRepeatedStringIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + */ + addRepeatedStringIterable(fieldNumber, values) { + this.kernel_.addRepeatedStringIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {number} index + * @param {string} value + * @throws {!Error} if index is out of range when check mode is critical + */ + setRepeatedStringElement(fieldNumber, index, value) { + this.kernel_.setRepeatedStringElement(fieldNumber, index, value); + } + + /** + * @param {number} fieldNumber + * @param {string} value + */ + addRepeatedStringElement(fieldNumber, value) { + this.kernel_.addRepeatedStringElement(fieldNumber, value); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + * @template T + */ + setRepeatedMessageIterable(fieldNumber, values) { + this.kernel_.setRepeatedMessageIterable(fieldNumber, values); + } + + /** + * @param {number} fieldNumber + * @param {!Iterable} values + * @param {function(!Kernel):T} instanceCreator + * @template T + */ + addRepeatedMessageIterable(fieldNumber, values, instanceCreator) { + this.kernel_.addRepeatedMessageIterable( + fieldNumber, values, instanceCreator); + } + + /** + * @param {number} fieldNumber + * @param {T} value + * @param {function(!Kernel):T} instanceCreator + * @param {number} index + * @throws {!Error} if index is out of range when check mode is critical + * @template T + */ + setRepeatedMessageElement(fieldNumber, value, instanceCreator, index) { + this.kernel_.setRepeatedMessageElement( + fieldNumber, value, instanceCreator, index); + } + + /** + * @param {number} fieldNumber + * @param {T} value + * @param {function(!Kernel):T} instanceCreator + * @template T + */ + addRepeatedMessageElement(fieldNumber, value, instanceCreator) { + this.kernel_.addRepeatedMessageElement(fieldNumber, value, instanceCreator); + } +} + +exports = TestMessage; diff --git a/js/experimental/runtime/testing/ensure_custom_equality_test.js b/js/experimental/runtime/testing/ensure_custom_equality_test.js new file mode 100644 index 0000000000000..9323ffd524a93 --- /dev/null +++ b/js/experimental/runtime/testing/ensure_custom_equality_test.js @@ -0,0 +1,44 @@ +/** + * @fileoverview Tests in this file will fail if our custom equality have not + * been installed. + * see b/131864652 + */ + +goog.module('protobuf.testing.ensureCustomEqualityTest'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const ByteString = goog.require('protobuf.ByteString'); + +describe('Custom equality', () => { + it('ensure that custom equality for ArrayBuffer is installed', () => { + const buffer1 = new ArrayBuffer(4); + const buffer2 = new ArrayBuffer(4); + const array = new Uint8Array(buffer1); + array[0] = 1; + expect(buffer1).not.toEqual(buffer2); + }); + + it('ensure that custom equality for ByteString is installed', () => { + const HALLO_IN_BASE64 = 'aGFsbG8='; + const BYTES_WITH_HALLO = new Uint8Array([ + 'h'.charCodeAt(0), + 'a'.charCodeAt(0), + 'l'.charCodeAt(0), + 'l'.charCodeAt(0), + 'o'.charCodeAt(0), + ]); + + const byteString1 = ByteString.fromBase64String(HALLO_IN_BASE64); + const byteString2 = ByteString.fromArrayBufferView(BYTES_WITH_HALLO); + expect(byteString1).toEqual(byteString2); + }); + + it('ensure that custom equality for BufferDecoder is installed', () => { + const arrayBuffer1 = new Uint8Array([0, 1, 2]).buffer; + const arrayBuffer2 = new Uint8Array([0, 1, 2]).buffer; + + const bufferDecoder1 = BufferDecoder.fromArrayBuffer(arrayBuffer1); + const bufferDecoder2 = BufferDecoder.fromArrayBuffer(arrayBuffer2); + expect(bufferDecoder1).toEqual(bufferDecoder2); + }); +}); diff --git a/js/experimental/runtime/testing/jasmine_protobuf.js b/js/experimental/runtime/testing/jasmine_protobuf.js new file mode 100644 index 0000000000000..d6bc0ffd36766 --- /dev/null +++ b/js/experimental/runtime/testing/jasmine_protobuf.js @@ -0,0 +1,88 @@ +/** + * @fileoverview Installs our custom equality matchers in Jasmine. + */ +goog.module('protobuf.testing.jasmineProtoBuf'); + +const BufferDecoder = goog.require('protobuf.binary.BufferDecoder'); +const ByteString = goog.require('protobuf.ByteString'); +const {arrayBufferEqual} = goog.require('protobuf.binary.typedArrays'); + +/** + * A function that ensures custom equality for ByteStrings. + * Since Jasmine compare structure by default Bytestrings might be equal that + * are not equal since ArrayBuffers still compare content in g3. + * (Jasmine fix upstream: https://github.com/jasmine/jasmine/issues/1687) + * Also ByteStrings that are equal might compare non equal in jasmine of the + * base64 string has been initialized. + * @param {*} first + * @param {*} second + * @return {boolean|undefined} + */ +const byteStringEquality = (first, second) => { + if (second instanceof ByteString) { + return second.equals(first); + } + + // Intentionally not returning anything, this signals to jasmine that we + // did not perform any equality on the given objects. +}; + +/** + * A function that ensures custom equality for ArrayBuffers. + * By default Jasmine does not compare the content of an ArrayBuffer and thus + * will return true for buffers with the same length but different content. + * @param {*} first + * @param {*} second + * @return {boolean|undefined} + */ +const arrayBufferCustomEquality = (first, second) => { + if (first instanceof ArrayBuffer && second instanceof ArrayBuffer) { + return arrayBufferEqual(first, second); + } + // Intentionally not returning anything, this signals to jasmine that we + // did not perform any equality on the given objects. +}; + +/** + * A function that ensures custom equality for ArrayBuffers. + * By default Jasmine does not compare the content of an ArrayBuffer and thus + * will return true for buffers with the same length but different content. + * @param {*} first + * @param {*} second + * @return {boolean|undefined} + */ +const bufferDecoderCustomEquality = (first, second) => { + if (first instanceof BufferDecoder && second instanceof BufferDecoder) { + return first.asByteString().equals(second.asByteString()); + } + // Intentionally not returning anything, this signals to jasmine that we + // did not perform any equality on the given objects. +}; + +/** + * Overrides the default ArrayBuffer toString method ([object ArrayBuffer]) with + * a more readable representation. + */ +function overrideArrayBufferToString() { + /** + * Returns the hex values of the underlying bytes of the ArrayBuffer. + * + * @override + * @return {string} + */ + ArrayBuffer.prototype.toString = function() { + const arr = Array.from(new Uint8Array(this)); + return 'ArrayBuffer[' + + arr.map((b) => '0x' + (b & 0xFF).toString(16).toUpperCase()) + .join(', ') + + ']'; + }; +} + +beforeEach(() => { + jasmine.addCustomEqualityTester(arrayBufferCustomEquality); + jasmine.addCustomEqualityTester(bufferDecoderCustomEquality); + jasmine.addCustomEqualityTester(byteStringEquality); + + overrideArrayBufferToString(); +}); diff --git a/js/gulpfile.js b/js/gulpfile.js index fc9559f934eb5..8137b90702052 100644 --- a/js/gulpfile.js +++ b/js/gulpfile.js @@ -29,9 +29,15 @@ var group1Protos = [ 'test5.proto', 'commonjs/test6/test6.proto', 'test8.proto', + 'test11.proto', + 'test12.proto', + 'test13.proto', + 'test14.proto', + 'test15.proto', 'testbinary.proto', 'testempty.proto', 'test.proto', + 'testlargenumbers.proto', ]; var group2Protos = [ @@ -41,6 +47,12 @@ var group2Protos = [ 'commonjs/test7/test7.proto', ]; +var group3Protos = [ + 'test9.proto', + 'test10.proto' +]; + + gulp.task('genproto_well_known_types_closure', function (cb) { exec(protoc + ' --js_out=one_output_file_per_input_file,binary:. -I ../src -I . ' + wellKnownTypes.join(' '), function (err, stdout, stderr) { @@ -59,13 +71,16 @@ gulp.task('genproto_group1_closure', function (cb) { }); }); -gulp.task('genproto_group2_closure', function (cb) { - exec(protoc + ' --js_out=library=testproto_libs2,binary:. -I ../src -I . -I commonjs ' + group2Protos.join(' '), - function (err, stdout, stderr) { - console.log(stdout); - console.log(stderr); - cb(err); - }); +gulp.task('genproto_group2_closure', function(cb) { + exec( + protoc + + ' --experimental_allow_proto3_optional --js_out=library=testproto_libs2,binary:. -I ../src -I . -I commonjs ' + + group2Protos.join(' '), + function(err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); }); gulp.task('genproto_well_known_types_commonjs', function (cb) { @@ -86,13 +101,16 @@ gulp.task('genproto_group1_commonjs', function (cb) { }); }); -gulp.task('genproto_group2_commonjs', function (cb) { - exec('mkdir -p commonjs_out && ' + protoc + ' --js_out=import_style=commonjs,binary:commonjs_out -I ../src -I commonjs -I . ' + group2Protos.join(' '), - function (err, stdout, stderr) { - console.log(stdout); - console.log(stderr); - cb(err); - }); +gulp.task('genproto_group2_commonjs', function(cb) { + exec( + 'mkdir -p commonjs_out && ' + protoc + + ' --experimental_allow_proto3_optional --js_out=import_style=commonjs,binary:commonjs_out -I ../src -I commonjs -I . ' + + group2Protos.join(' '), + function(err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); }); gulp.task('genproto_commonjs_wellknowntypes', function (cb) { @@ -112,19 +130,28 @@ gulp.task('genproto_wellknowntypes', function (cb) { cb(err); }); }); +gulp.task('genproto_group3_commonjs_strict', function (cb) { + exec('mkdir -p commonjs_out && ' + protoc + ' --js_out=import_style=commonjs_strict,binary:commonjs_out -I ../src -I commonjs -I . ' + group3Protos.join(' '), + function (err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); +}); + function getClosureBuilderCommand(exportsFile, outputFile) { return './node_modules/google-closure-library/closure/bin/build/closurebuilder.py ' + '--root node_modules ' + '-o compiled ' + - '--compiler_jar node_modules/google-closure-compiler/compiler.jar ' + + '--compiler_jar node_modules/google-closure-compiler-java/compiler.jar ' + '-i ' + exportsFile + ' ' + 'map.js message.js binary/arith.js binary/constants.js binary/decoder.js ' + 'binary/encoder.js binary/reader.js binary/utils.js binary/writer.js ' + exportsFile + ' > ' + outputFile; } -gulp.task('dist', ['genproto_wellknowntypes'], function (cb) { +gulp.task('dist', gulp.series(['genproto_wellknowntypes'], function(cb) { // TODO(haberman): minify this more aggressively. // Will require proper externs/exports. exec(getClosureBuilderCommand('commonjs/export.js', 'google-protobuf.js'), @@ -133,7 +160,7 @@ gulp.task('dist', ['genproto_wellknowntypes'], function (cb) { console.log(stderr); cb(err); }); -}); +})); gulp.task('commonjs_asserts', function (cb) { exec('mkdir -p commonjs_out/test_node_modules && ' + @@ -159,56 +186,83 @@ gulp.task('commonjs_testdeps', function (cb) { }); }); -gulp.task('make_commonjs_out', ['dist', 'genproto_well_known_types_commonjs', 'genproto_group1_commonjs', 'genproto_group2_commonjs', 'genproto_commonjs_wellknowntypes', 'commonjs_asserts', 'commonjs_testdeps'], function (cb) { - // TODO(haberman): minify this more aggressively. - // Will require proper externs/exports. - var cmd = "mkdir -p commonjs_out/binary && mkdir -p commonjs_out/test_node_modules && "; - function addTestFile(file) { - cmd += 'node commonjs/rewrite_tests_for_commonjs.js < ' + file + - ' > commonjs_out/' + file + '&& '; - } - - glob.sync('*_test.js').forEach(addTestFile); - glob.sync('binary/*_test.js').forEach(addTestFile); - - exec(cmd + - 'cp commonjs/jasmine.json commonjs_out/jasmine.json && ' + - 'cp google-protobuf.js commonjs_out/test_node_modules && ' + - 'cp commonjs/import_test.js commonjs_out/import_test.js', - function (err, stdout, stderr) { - console.log(stdout); - console.log(stderr); - cb(err); - }); -}); +gulp.task( + 'make_commonjs_out', + gulp.series( + [ + 'dist', 'genproto_well_known_types_commonjs', + 'genproto_group1_commonjs', 'genproto_group2_commonjs', + 'genproto_commonjs_wellknowntypes', 'commonjs_asserts', + 'commonjs_testdeps', 'genproto_group3_commonjs_strict' + ], + function(cb) { + // TODO(haberman): minify this more aggressively. + // Will require proper externs/exports. + var cmd = + 'mkdir -p commonjs_out/binary && mkdir -p commonjs_out/test_node_modules && '; + function addTestFile(file) { + cmd += 'node commonjs/rewrite_tests_for_commonjs.js < ' + file + + ' > commonjs_out/' + file + '&& '; + } -gulp.task('deps', ['genproto_well_known_types_closure', 'genproto_group1_closure', 'genproto_group2_closure'], function (cb) { - exec('./node_modules/google-closure-library/closure/bin/build/depswriter.py binary/arith.js binary/constants.js binary/decoder.js binary/encoder.js binary/reader.js binary/utils.js binary/writer.js debug.js map.js message.js node_loader.js test_bootstrap.js > deps.js', - function (err, stdout, stderr) { - console.log(stdout); - console.log(stderr); - cb(err); - }); -}); + glob.sync('*_test.js').forEach(addTestFile); + glob.sync('binary/*_test.js').forEach(addTestFile); -gulp.task('test_closure', ['genproto_well_known_types_closure', 'genproto_group1_closure', 'genproto_group2_closure', 'deps'], function (cb) { - exec('JASMINE_CONFIG_PATH=jasmine.json ./node_modules/.bin/jasmine', - function (err, stdout, stderr) { - console.log(stdout); - console.log(stderr); - cb(err); - }); -}); + exec( + cmd + 'cp commonjs/jasmine.json commonjs_out/jasmine.json && ' + + 'cp google-protobuf.js commonjs_out/test_node_modules && ' + + 'cp commonjs/strict_test.js commonjs_out/strict_test.js &&' + + 'cp commonjs/import_test.js commonjs_out/import_test.js', + function(err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); + })); + +gulp.task( + 'deps', + gulp.series( + [ + 'genproto_well_known_types_closure', 'genproto_group1_closure', + 'genproto_group2_closure' + ], + function(cb) { + exec( + './node_modules/google-closure-library/closure/bin/build/depswriter.py binary/arith.js binary/constants.js binary/decoder.js binary/encoder.js binary/reader.js binary/utils.js binary/writer.js debug.js map.js message.js node_loader.js test_bootstrap.js > deps.js', + function(err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); + })); + +gulp.task( + 'test_closure', + gulp.series( + [ + 'genproto_well_known_types_closure', 'genproto_group1_closure', + 'genproto_group2_closure', 'deps' + ], + function(cb) { + exec( + 'JASMINE_CONFIG_PATH=jasmine.json ./node_modules/.bin/jasmine', + function(err, stdout, stderr) { + console.log(stdout); + console.log(stderr); + cb(err); + }); + })); -gulp.task('test_commonjs', ['make_commonjs_out'], function (cb) { +gulp.task('test_commonjs', gulp.series(['make_commonjs_out'], function(cb) { exec('cd commonjs_out && JASMINE_CONFIG_PATH=jasmine.json NODE_PATH=test_node_modules ../node_modules/.bin/jasmine', function (err, stdout, stderr) { console.log(stdout); console.log(stderr); cb(err); }); -}); +})); -gulp.task('test', ['test_closure', 'test_commonjs'], function(cb) { +gulp.task('test', gulp.series(['test_closure', 'test_commonjs'], function(cb) { cb(); -}); +})); diff --git a/js/map.js b/js/map.js index d423499f05e3d..61f0f3b63f19d 100644 --- a/js/map.js +++ b/js/map.js @@ -1,3 +1,4 @@ + // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ @@ -28,12 +29,16 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/** + * @fileoverview + * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed + */ goog.provide('jspb.Map'); goog.require('goog.asserts'); -goog.forwardDeclare('jspb.BinaryReader'); -goog.forwardDeclare('jspb.BinaryWriter'); +goog.requireType('jspb.BinaryReader'); +goog.requireType('jspb.BinaryWriter'); @@ -48,9 +53,9 @@ goog.forwardDeclare('jspb.BinaryWriter'); * * @template K, V * - * @param {!Array>} arr + * @param {!Array>} arr * - * @param {?function(new:V)|function(new:V,?)=} opt_valueCtor + * @param {?function(new:V, ?=)=} opt_valueCtor * The constructor for type V, if type V is a message type. * * @constructor @@ -118,7 +123,7 @@ jspb.Map.prototype.toArray = function() { strKeys.sort(); for (var i = 0; i < strKeys.length; i++) { var entry = this.map_[strKeys[i]]; - var valueWrapper = /** @type {!Object} */ (entry.valueWrapper); + var valueWrapper = /** @type {?jspb.Message} */ (entry.valueWrapper); if (valueWrapper) { valueWrapper.toArray(); } @@ -136,7 +141,7 @@ jspb.Map.prototype.toArray = function() { * * @param {boolean=} includeInstance Whether to include the JSPB instance for * transitional soy proto support: http://goto/soy-param-migration - * @param {!function((boolean|undefined),V):!Object=} valueToObject + * @param {function((boolean|undefined),V):!Object=} valueToObject * The static toObject() method, if V is a message type. * @return {!Array>} */ @@ -165,9 +170,9 @@ jspb.Map.prototype.toObject = function(includeInstance, valueToObject) { * * @template K, V * @param {!Array>} entries - * @param {!function(new:V)|function(new:V,?)} valueCtor + * @param {function(new:V,?=)} valueCtor * The constructor for type V. - * @param {!function(!Object):V} valueFromObject + * @param {function(!Object):V} valueFromObject * The fromObject function for type V. * @return {!jspb.Map} */ @@ -410,9 +415,9 @@ jspb.Map.prototype.has = function(key) { * number. * @param {number} fieldNumber * @param {!jspb.BinaryWriter} writer - * @param {!function(this:jspb.BinaryWriter,number,K)} keyWriterFn + * @param {function(this:jspb.BinaryWriter,number,K)} keyWriterFn * The method on BinaryWriter that writes type K to the stream. - * @param {!function(this:jspb.BinaryWriter,number,V,?=)| + * @param {function(this:jspb.BinaryWriter,number,V,?=)| * function(this:jspb.BinaryWriter,number,V,?)} valueWriterFn * The method on BinaryWriter that writes type V to the stream. May be * writeMessage, in which case the second callback arg form is used. @@ -432,7 +437,8 @@ jspb.Map.prototype.serializeBinary = function( valueWriterFn.call(writer, 2, this.wrapEntry_(entry), opt_valueWriterCallback); } else { - valueWriterFn.call(writer, 2, entry.value); + /** @type {function(this:jspb.BinaryWriter,number,?)} */ (valueWriterFn) + .call(writer, 2, entry.value); } writer.endSubMessage(); } @@ -442,43 +448,63 @@ jspb.Map.prototype.serializeBinary = function( /** * Read one key/value message from the given BinaryReader. Compatible as the * `reader` callback parameter to jspb.BinaryReader.readMessage, to be called - * when a key/value pair submessage is encountered. + * when a key/value pair submessage is encountered. If the Key is undefined, + * we should default it to 0. * @template K, V * @param {!jspb.Map} map * @param {!jspb.BinaryReader} reader - * @param {!function(this:jspb.BinaryReader):K} keyReaderFn + * @param {function(this:jspb.BinaryReader):K} keyReaderFn * The method on BinaryReader that reads type K from the stream. * - * @param {!function(this:jspb.BinaryReader):V| + * @param {function(this:jspb.BinaryReader):V| * function(this:jspb.BinaryReader,V, * function(V,!jspb.BinaryReader))} valueReaderFn * The method on BinaryReader that reads type V from the stream. May be * readMessage, in which case the second callback arg form is used. * * @param {?function(V,!jspb.BinaryReader)=} opt_valueReaderCallback - * The BinaryReader parsing callback for type V, if V is a message type. + * The BinaryReader parsing callback for type V, if V is a message type + * + * @param {K=} opt_defaultKey + * The default value for the type of map keys. Accepting map entries with + * unset keys is required for maps to be backwards compatible with the + * repeated message representation described here: goo.gl/zuoLAC + * + * @param {V=} opt_defaultValue + * The default value for the type of map values. Accepting map entries with + * unset values is required for maps to be backwards compatible with the + * repeated message representation described here: goo.gl/zuoLAC * */ jspb.Map.deserializeBinary = function(map, reader, keyReaderFn, valueReaderFn, - opt_valueReaderCallback) { - var key = undefined; - var value = undefined; + opt_valueReaderCallback, opt_defaultKey, + opt_defaultValue) { + var key = opt_defaultKey; + var value = opt_defaultValue; while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); + if (field == 1) { // Key. key = keyReaderFn.call(reader); } else if (field == 2) { // Value. if (map.valueCtor_) { - value = new map.valueCtor_(); + goog.asserts.assert(opt_valueReaderCallback); + if (!value) { + // Old generator still doesn't provide default value message. + // Need this for backward compatibility. + value = new map.valueCtor_(); + } valueReaderFn.call(reader, value, opt_valueReaderCallback); } else { - value = valueReaderFn.call(reader); + value = + (/** @type {function(this:jspb.BinaryReader):?} */ (valueReaderFn)) + .call(reader); } } } diff --git a/js/maps_test.js b/js/maps_test.js old mode 100755 new mode 100644 index e8dd2f219b9b7..68ed6834c0e4b --- a/js/maps_test.js +++ b/js/maps_test.js @@ -35,11 +35,26 @@ goog.require('goog.userAgent'); goog.require('proto.jspb.test.MapValueEnum'); goog.require('proto.jspb.test.MapValueMessage'); goog.require('proto.jspb.test.TestMapFields'); +goog.require('proto.jspb.test.TestMapFieldsOptionalKeys'); +goog.require('proto.jspb.test.TestMapFieldsOptionalValues'); +goog.require('proto.jspb.test.MapEntryOptionalKeysStringKey'); +goog.require('proto.jspb.test.MapEntryOptionalKeysInt32Key'); +goog.require('proto.jspb.test.MapEntryOptionalKeysInt64Key'); +goog.require('proto.jspb.test.MapEntryOptionalKeysBoolKey'); +goog.require('proto.jspb.test.MapEntryOptionalValuesStringValue'); +goog.require('proto.jspb.test.MapEntryOptionalValuesInt32Value'); +goog.require('proto.jspb.test.MapEntryOptionalValuesInt64Value'); +goog.require('proto.jspb.test.MapEntryOptionalValuesBoolValue'); +goog.require('proto.jspb.test.MapEntryOptionalValuesDoubleValue'); +goog.require('proto.jspb.test.MapEntryOptionalValuesEnumValue'); +goog.require('proto.jspb.test.MapEntryOptionalValuesMessageValue'); // CommonJS-LoadFromFile: test_pb proto.jspb.test goog.require('proto.jspb.test.MapValueMessageNoBinary'); goog.require('proto.jspb.test.TestMapFieldsNoBinary'); +goog.requireType('jspb.Map'); + /** * Helper: check that the given map has exactly this set of (sorted) entries. * @param {!jspb.Map} map @@ -49,7 +64,12 @@ function checkMapEquals(map, entries) { var arr = map.toArray(); assertEquals(arr.length, entries.length); for (var i = 0; i < arr.length; i++) { - assertElementsEquals(arr[i], entries[i]); + if (Array.isArray(arr[i])) { + assertTrue(Array.isArray(entries[i])); + assertArrayEquals(arr[i], entries[i]); + } else { + assertElementsEquals(arr[i], entries[i]); + } } } @@ -76,7 +96,7 @@ function toArray(iter) { * Helper: generate test methods for this TestMapFields class. * @param {?} msgInfo * @param {?} submessageCtor - * @param {!string} suffix + * @param {string} suffix */ function makeTests(msgInfo, submessageCtor, suffix) { /** @@ -98,7 +118,9 @@ function makeTests(msgInfo, submessageCtor, suffix) { msg.getMapStringMsgMap().get('k').setFoo(42); msg.getMapStringMsgMap().get('l').setFoo(84); msg.getMapInt32StringMap().set(-1, 'a').set(42, 'b'); - msg.getMapInt64StringMap().set(0x123456789abc, 'c').set(0xcba987654321, 'd'); + msg.getMapInt64StringMap() + .set(0x123456789abc, 'c') + .set(0xcba987654321, 'd'); msg.getMapBoolStringMap().set(false, 'e').set(true, 'f'); }; @@ -107,42 +129,24 @@ function makeTests(msgInfo, submessageCtor, suffix) { * @param {?} msg */ var checkMapFields = function(msg) { - checkMapEquals(msg.getMapStringStringMap(), [ - ['asdf', 'jkl;'], - ['key 2', 'hello world'] - ]); - checkMapEquals(msg.getMapStringInt32Map(), [ - ['a', 1], - ['b', -2] - ]); - checkMapEquals(msg.getMapStringInt64Map(), [ - ['c', 0x100000000], - ['d', 0x200000000] - ]); - checkMapEquals(msg.getMapStringBoolMap(), [ - ['e', true], - ['f', false] - ]); - checkMapEquals(msg.getMapStringDoubleMap(), [ - ['g', 3.14159], - ['h', 2.71828] - ]); + checkMapEquals( + msg.getMapStringStringMap(), + [['asdf', 'jkl;'], ['key 2', 'hello world']]); + checkMapEquals(msg.getMapStringInt32Map(), [['a', 1], ['b', -2]]); + checkMapEquals( + msg.getMapStringInt64Map(), [['c', 0x100000000], ['d', 0x200000000]]); + checkMapEquals(msg.getMapStringBoolMap(), [['e', true], ['f', false]]); + checkMapEquals( + msg.getMapStringDoubleMap(), [['g', 3.14159], ['h', 2.71828]]); checkMapEquals(msg.getMapStringEnumMap(), [ - ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR], - ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ] - ]); - checkMapEquals(msg.getMapInt32StringMap(), [ - [-1, 'a'], - [42, 'b'] - ]); - checkMapEquals(msg.getMapInt64StringMap(), [ - [0x123456789abc, 'c'], - [0xcba987654321, 'd'] - ]); - checkMapEquals(msg.getMapBoolStringMap(), [ - [false, 'e'], - [true, 'f'] + ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR], + ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ] ]); + checkMapEquals(msg.getMapInt32StringMap(), [[-1, 'a'], [42, 'b']]); + checkMapEquals( + msg.getMapInt64StringMap(), + [[0x123456789abc, 'c'], [0xcba987654321, 'd']]); + checkMapEquals(msg.getMapBoolStringMap(), [[false, 'e'], [true, 'f']]); assertEquals(msg.getMapStringMsgMap().getLength(), 2); assertEquals(msg.getMapStringMsgMap().get('k').getFoo(), 42); @@ -187,10 +191,7 @@ function makeTests(msgInfo, submessageCtor, suffix) { assertElementsEquals(it.next().value, ['asdf', 'hello world']); assertElementsEquals(it.next().value, ['jkl;', 'key 2']); assertEquals(it.next().done, true); - checkMapEquals(m, [ - ['asdf', 'hello world'], - ['jkl;', 'key 2'] - ]); + checkMapEquals(m, [['asdf', 'hello world'], ['jkl;', 'key 2']]); m.del('jkl;'); assertEquals(m.has('jkl;'), false); assertEquals(m.get('jkl;'), undefined); @@ -242,11 +243,11 @@ function makeTests(msgInfo, submessageCtor, suffix) { msg.getMapStringStringMap().set('A', 'a'); var serialized = msg.serializeBinary(); var expectedSerialized = [ - 0x0a, 0x6, // field 1 (map_string_string), delimited, length 6 - 0x0a, 0x1, // field 1 in submessage (key), delimited, length 1 - 0x41, // ASCII 'A' - 0x12, 0x1, // field 2 in submessage (value), delimited, length 1 - 0x61 // ASCII 'a' + 0x0a, 0x6, // field 1 (map_string_string), delimited, length 6 + 0x0a, 0x1, // field 1 in submessage (key), delimited, length 1 + 0x41, // ASCII 'A' + 0x12, 0x1, // field 2 in submessage (value), delimited, length 1 + 0x61 // ASCII 'a' ]; assertEquals(serialized.length, expectedSerialized.length); for (var i = 0; i < serialized.length; i++) { @@ -260,6 +261,80 @@ function makeTests(msgInfo, submessageCtor, suffix) { var decoded = msgInfo.deserializeBinary(serialized); checkMapFields(decoded); }); + + /** + * Tests deserialization of undefined map keys go to default values in + * binary format. + */ + it('testMapDeserializationForUndefinedKeys', function() { + var testMessageOptionalKeys = + new proto.jspb.test.TestMapFieldsOptionalKeys(); + var mapEntryStringKey = + new proto.jspb.test.MapEntryOptionalKeysStringKey(); + mapEntryStringKey.setValue('a'); + testMessageOptionalKeys.setMapStringString(mapEntryStringKey); + var mapEntryInt32Key = new proto.jspb.test.MapEntryOptionalKeysInt32Key(); + mapEntryInt32Key.setValue('b'); + testMessageOptionalKeys.setMapInt32String(mapEntryInt32Key); + var mapEntryInt64Key = new proto.jspb.test.MapEntryOptionalKeysInt64Key(); + mapEntryInt64Key.setValue('c'); + testMessageOptionalKeys.setMapInt64String(mapEntryInt64Key); + var mapEntryBoolKey = new proto.jspb.test.MapEntryOptionalKeysBoolKey(); + mapEntryBoolKey.setValue('d'); + testMessageOptionalKeys.setMapBoolString(mapEntryBoolKey); + var deserializedMessage = + msgInfo.deserializeBinary(testMessageOptionalKeys.serializeBinary()); + checkMapEquals(deserializedMessage.getMapStringStringMap(), [['', 'a']]); + checkMapEquals(deserializedMessage.getMapInt32StringMap(), [[0, 'b']]); + checkMapEquals(deserializedMessage.getMapInt64StringMap(), [[0, 'c']]); + checkMapEquals(deserializedMessage.getMapBoolStringMap(), [[false, 'd']]); + }); + + /** + * Tests deserialization of undefined map values go to default values in + * binary format. + */ + it('testMapDeserializationForUndefinedValues', function() { + var testMessageOptionalValues = + new proto.jspb.test.TestMapFieldsOptionalValues(); + var mapEntryStringValue = + new proto.jspb.test.MapEntryOptionalValuesStringValue(); + mapEntryStringValue.setKey('a'); + testMessageOptionalValues.setMapStringString(mapEntryStringValue); + var mapEntryInt32Value = + new proto.jspb.test.MapEntryOptionalValuesInt32Value(); + mapEntryInt32Value.setKey('b'); + testMessageOptionalValues.setMapStringInt32(mapEntryInt32Value); + var mapEntryInt64Value = + new proto.jspb.test.MapEntryOptionalValuesInt64Value(); + mapEntryInt64Value.setKey('c'); + testMessageOptionalValues.setMapStringInt64(mapEntryInt64Value); + var mapEntryBoolValue = + new proto.jspb.test.MapEntryOptionalValuesBoolValue(); + mapEntryBoolValue.setKey('d'); + testMessageOptionalValues.setMapStringBool(mapEntryBoolValue); + var mapEntryDoubleValue = + new proto.jspb.test.MapEntryOptionalValuesDoubleValue(); + mapEntryDoubleValue.setKey('e'); + testMessageOptionalValues.setMapStringDouble(mapEntryDoubleValue); + var mapEntryEnumValue = + new proto.jspb.test.MapEntryOptionalValuesEnumValue(); + mapEntryEnumValue.setKey('f'); + testMessageOptionalValues.setMapStringEnum(mapEntryEnumValue); + var mapEntryMessageValue = + new proto.jspb.test.MapEntryOptionalValuesMessageValue(); + mapEntryMessageValue.setKey('g'); + testMessageOptionalValues.setMapStringMsg(mapEntryMessageValue); + var deserializedMessage = msgInfo.deserializeBinary( + testMessageOptionalValues.serializeBinary()); + checkMapEquals(deserializedMessage.getMapStringStringMap(), [['a', '']]); + checkMapEquals(deserializedMessage.getMapStringInt32Map(), [['b', 0]]); + checkMapEquals(deserializedMessage.getMapStringInt64Map(), [['c', 0]]); + checkMapEquals(deserializedMessage.getMapStringBoolMap(), [['d', false]]); + checkMapEquals(deserializedMessage.getMapStringDoubleMap(), [['e', 0.0]]); + checkMapEquals(deserializedMessage.getMapStringEnumMap(), [['f', 0]]); + checkMapEquals(deserializedMessage.getMapStringMsgMap(), [['g', []]]); + }); } @@ -268,11 +343,7 @@ function makeTests(msgInfo, submessageCtor, suffix) { */ it('testLazyMapSync' + suffix, function() { // Start with a JSPB array containing a few map entries. - var entries = [ - ['a', 'entry 1'], - ['c', 'entry 2'], - ['b', 'entry 3'] - ]; + var entries = [['a', 'entry 1'], ['c', 'entry 2'], ['b', 'entry 3']]; var msg = new msgInfo.constructor([entries]); assertEquals(entries.length, 3); assertEquals(entries[0][0], 'a'); @@ -280,9 +351,9 @@ function makeTests(msgInfo, submessageCtor, suffix) { assertEquals(entries[2][0], 'b'); msg.getMapStringStringMap().del('a'); assertEquals(entries.length, 3); // not yet sync'd - msg.toArray(); // force a sync + msg.toArray(); // force a sync assertEquals(entries.length, 2); - assertEquals(entries[0][0], 'b'); // now in sorted order + assertEquals(entries[0][0], 'b'); // now in sorted order assertEquals(entries[1][0], 'c'); var a = msg.toArray(); @@ -302,11 +373,17 @@ function makeTests(msgInfo, submessageCtor, suffix) { assertElementsEquals(entryIterator.next().value, ['key2', 'value2']); assertEquals(entryIterator.next().done, true); - if (typeof(Symbol) != 'undefined') { + try { var entryIterable = m.entries()[Symbol.iterator](); assertElementsEquals(entryIterable.next().value, ['key1', 'value1']); assertElementsEquals(entryIterable.next().value, ['key2', 'value2']); assertEquals(entryIterable.next().done, true); + } catch (err) { + // jspb.Map.ArrayIteratorIterable_.prototype[Symbol.iterator] may be + // undefined in some environment. + if (err.name != 'TypeError' && err.name != 'ReferenceError') { + throw err; + } } var keyIterator = m.keys(); @@ -314,22 +391,34 @@ function makeTests(msgInfo, submessageCtor, suffix) { assertEquals(keyIterator.next().value, 'key2'); assertEquals(keyIterator.next().done, true); - if (typeof(Symbol) != 'undefined') { + try { var keyIterable = m.keys()[Symbol.iterator](); assertEquals(keyIterable.next().value, 'key1'); assertEquals(keyIterable.next().value, 'key2'); assertEquals(keyIterable.next().done, true); + } catch (err) { + // jspb.Map.ArrayIteratorIterable_.prototype[Symbol.iterator] may be + // undefined in some environment. + if (err.name != 'TypeError' && err.name != 'ReferenceError') { + throw err; + } } var valueIterator = m.values(); assertEquals(valueIterator.next().value, 'value1'); assertEquals(valueIterator.next().value, 'value2'); assertEquals(valueIterator.next().done, true); - if (typeof(Symbol) != 'undefined') { + try { var valueIterable = m.values()[Symbol.iterator](); assertEquals(valueIterable.next().value, 'value1'); assertEquals(valueIterable.next().value, 'value2'); assertEquals(valueIterable.next().done, true); + } catch (err) { + // jspb.Map.ArrayIteratorIterable_.prototype[Symbol.iterator] may be + // undefined in some environment. + if (err.name != 'TypeError' && err.name != 'ReferenceError') { + throw err; + } } }); } diff --git a/js/message.js b/js/message.js index f7dcfa964e849..905329fe44095 100644 --- a/js/message.js +++ b/js/message.js @@ -31,6 +31,7 @@ /** * @fileoverview Definition of jspb.Message. * + * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * @author mwr@google.com (Mark Rawling) */ @@ -41,10 +42,9 @@ goog.provide('jspb.Message'); goog.require('goog.array'); goog.require('goog.asserts'); goog.require('goog.crypt.base64'); +goog.require('jspb.BinaryReader'); goog.require('jspb.Map'); -// Not needed in compilation units that have no protos with xids. -goog.forwardDeclare('xid.String'); @@ -105,7 +105,7 @@ jspb.ExtensionFieldInfo = function(fieldNumber, fieldName, ctor, toObjectFn, /** * Stores binary-related information for a single extension field. * @param {!jspb.ExtensionFieldInfo} fieldInfo - * @param {function(this:jspb.BinaryReader,number,?)} binaryReaderFn + * @param {function(this:jspb.BinaryReader,number,?,?)} binaryReaderFn * @param {function(this:jspb.BinaryWriter,number,?) * |function(this:jspb.BinaryWriter,number,?,?,?,?,?)} binaryWriterFn * @param {function(?,?)=} opt_binaryMessageSerializeFn @@ -171,7 +171,8 @@ jspb.Message = function() { * dead code eliminate fields used in protocol buffers that are never used * in an application. */ -goog.define('jspb.Message.GENERATE_TO_OBJECT', true); +jspb.Message.GENERATE_TO_OBJECT = + goog.define('jspb.Message.GENERATE_TO_OBJECT', true); /** @@ -181,12 +182,10 @@ goog.define('jspb.Message.GENERATE_TO_OBJECT', true); * calling fromObject. Enabling this might disable the JSCompiler's ability * to dead code eliminate fields used in protocol buffers that are never * used in an application. - * NOTE: By default no protos actually have a fromObject method. You need to - * add the jspb.generate_from_object options to the proto definition to - * activate the feature. * By default this is enabled for test code only. */ -goog.define('jspb.Message.GENERATE_FROM_OBJECT', !goog.DISALLOW_TEST_ONLY_CODE); +jspb.Message.GENERATE_FROM_OBJECT = goog.define( + 'jspb.Message.GENERATE_FROM_OBJECT', !goog.DISALLOW_TEST_ONLY_CODE); /** @@ -194,7 +193,8 @@ goog.define('jspb.Message.GENERATE_FROM_OBJECT', !goog.DISALLOW_TEST_ONLY_CODE); * this off if you do not use toString in your project and want to trim it * from the compiled JS. */ -goog.define('jspb.Message.GENERATE_TO_STRING', true); +jspb.Message.GENERATE_TO_STRING = + goog.define('jspb.Message.GENERATE_TO_STRING', true); /** @@ -202,18 +202,19 @@ goog.define('jspb.Message.GENERATE_TO_STRING', true); * local (e.g. not from another iframe) and thus safely classified with * instanceof Array. */ -goog.define('jspb.Message.ASSUME_LOCAL_ARRAYS', false); +jspb.Message.ASSUME_LOCAL_ARRAYS = + goog.define('jspb.Message.ASSUME_LOCAL_ARRAYS', false); +// TODO(jakubvrana): Turn this off by default. /** - * @define {boolean} Turning on this flag does NOT change the behavior of JSPB - * and only affects private internal state. It may, however, break some - * tests that use naive deeply-equals algorithms, because using a proto - * mutates its internal state. - * Projects are advised to turn this flag always on. + * @define {boolean} Disabling the serialization of empty trailing fields + * reduces the size of serialized protos. The price is an extra iteration of + * the proto before serialization. This is enabled by default to be + * backwards compatible. Projects are advised to turn this flag always off. */ -goog.define('jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS', COMPILED); -// TODO(b/19419436) Turn this on by default. +jspb.Message.SERIALIZE_EMPTY_TRAILING_FIELDS = + goog.define('jspb.Message.SERIALIZE_EMPTY_TRAILING_FIELDS', true); /** @@ -270,23 +271,18 @@ jspb.Message.prototype.messageId_; /** - * Repeated float or double fields which have been converted to include only - * numbers and not strings holding "NaN", "Infinity" and "-Infinity". + * Repeated fields that have been converted to their proper type. This is used + * for numbers stored as strings (typically "NaN", "Infinity" and "-Infinity") + * and for booleans stored as numbers (0 or 1). * @private {!Object|undefined} */ -jspb.Message.prototype.convertedFloatingPointFields_; - +jspb.Message.prototype.convertedPrimitiveFields_; /** - * The xid of this proto type (The same for all instances of a proto). Provides - * a way to identify a proto by stable obfuscated name. - * @see {xid}. - * Available if {@link jspb.generate_xid} is added as a Message option to - * a protocol buffer. - * @const {!xid.String|undefined} The xid or undefined if message is - * annotated to generate the xid. + * Repeated fields numbers. + * @protected {?Array|undefined} */ -jspb.Message.prototype.messageXid; +jspb.Message.prototype.repeatedFields; @@ -322,6 +318,22 @@ jspb.Message.getIndex_ = function(msg, fieldNumber) { return fieldNumber + msg.arrayIndexOffset_; }; +// This is only here to ensure we are not back sliding on ES6 requirements for +// protos in g3. +jspb.Message.hiddenES6Property_ = class {}; + + +/** + * Returns the tag number based on the index in msg.array. + * @param {!jspb.Message} msg Message for which we're calculating an index. + * @param {number} index The tag number. + * @return {number} The field number. + * @private + */ +jspb.Message.getFieldNumber_ = function(msg, index) { + return index - msg.arrayIndexOffset_; +}; + /** * Initializes a JsPb Message. @@ -340,7 +352,7 @@ jspb.Message.getIndex_ = function(msg, fieldNumber) { */ jspb.Message.initialize = function( msg, data, messageId, suggestedPivot, repeatedFields, opt_oneofFields) { - msg.wrappers_ = jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ? null : {}; + msg.wrappers_ = null; if (!data) { data = messageId ? [messageId] : []; } @@ -351,24 +363,26 @@ jspb.Message.initialize = function( msg.arrayIndexOffset_ = messageId === 0 ? -1 : 0; msg.array = data; jspb.Message.initPivotAndExtensionObject_(msg, suggestedPivot); - msg.convertedFloatingPointFields_ = {}; + msg.convertedPrimitiveFields_ = {}; + + if (!jspb.Message.SERIALIZE_EMPTY_TRAILING_FIELDS) { + // TODO(jakubvrana): This is same for all instances, move to prototype. + // TODO(jakubvrana): There are indexOf calls on this in serialization, + // consider switching to a set. + msg.repeatedFields = repeatedFields; + } if (repeatedFields) { for (var i = 0; i < repeatedFields.length; i++) { var fieldNumber = repeatedFields[i]; if (fieldNumber < msg.pivot_) { var index = jspb.Message.getIndex_(msg, fieldNumber); - msg.array[index] = msg.array[index] || - (jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ? - jspb.Message.EMPTY_LIST_SENTINEL_ : - []); + msg.array[index] = + msg.array[index] || jspb.Message.EMPTY_LIST_SENTINEL_; } else { jspb.Message.maybeInitEmptyExtensionObject_(msg); - msg.extensionObject_[fieldNumber] = - msg.extensionObject_[fieldNumber] || - (jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ? - jspb.Message.EMPTY_LIST_SENTINEL_ : - []); + msg.extensionObject_[fieldNumber] = msg.extensionObject_[fieldNumber] || + jspb.Message.EMPTY_LIST_SENTINEL_; } } } @@ -376,8 +390,9 @@ jspb.Message.initialize = function( if (opt_oneofFields && opt_oneofFields.length) { // Compute the oneof case for each union. This ensures only one value is // set in the union. - goog.array.forEach( - opt_oneofFields, goog.partial(jspb.Message.computeOneofCase, msg)); + for (var i = 0; i < opt_oneofFields.length; i++) { + jspb.Message.computeOneofCase(msg, opt_oneofFields[i]); + } } }; @@ -403,7 +418,25 @@ jspb.Message.EMPTY_LIST_SENTINEL_ = goog.DEBUG && Object.freeze ? */ jspb.Message.isArray_ = function(o) { return jspb.Message.ASSUME_LOCAL_ARRAYS ? o instanceof Array : - goog.isArray(o); + Array.isArray(o); +}; + +/** + * Returns true if the provided argument is an extension object. + * @param {*} o The object to classify as array or not. + * @return {boolean} True if the provided object is an extension object. + * @private + */ +jspb.Message.isExtensionObject_ = function(o) { + // Normal fields are never objects, so we can be sure that if we find an + // object here, then it's the extension object. However, we must ensure that + // the object is not an array, since arrays are valid field values (bytes + // fields can also be array). + // NOTE(lukestebbing): We avoid looking at .length to avoid a JIT bug + // in Safari on iOS 8. See the description of CL/86511464 for details. + return (o !== null && typeof o == 'object' && + !jspb.Message.isArray_(o) && + !(jspb.Message.SUPPORTS_UINT8ARRAY_ && o instanceof Uint8Array)); }; @@ -418,24 +451,31 @@ jspb.Message.isArray_ = function(o) { * @private */ jspb.Message.initPivotAndExtensionObject_ = function(msg, suggestedPivot) { - if (msg.array.length) { - var foundIndex = msg.array.length - 1; - var obj = msg.array[foundIndex]; - // Normal fields are never objects, so we can be sure that if we find an - // object here, then it's the extension object. However, we must ensure that - // the object is not an array, since arrays are valid field values. - // NOTE(lukestebbing): We avoid looking at .length to avoid a JIT bug - // in Safari on iOS 8. See the description of CL/86511464 for details. - if (obj && typeof obj == 'object' && !jspb.Message.isArray_(obj) && - !(jspb.Message.SUPPORTS_UINT8ARRAY_ && obj instanceof Uint8Array)) { - msg.pivot_ = foundIndex - msg.arrayIndexOffset_; + // There are 3 variants that need to be dealt with which are the + // combination of whether there exists an extension object (EO) and + // whether there is a suggested pivot (SP). + // + // EO, ? : pivot is the index of the EO + // no-EO, no-SP: pivot is MAX_INT + // no-EO, SP : pivot is the max(lastindex + 1, SP) + + var msgLength = msg.array.length; + var lastIndex = -1; + if (msgLength) { + lastIndex = msgLength - 1; + var obj = msg.array[lastIndex]; + if (jspb.Message.isExtensionObject_(obj)) { + msg.pivot_ = jspb.Message.getFieldNumber_(msg, lastIndex); msg.extensionObject_ = obj; return; } } if (suggestedPivot > -1) { - msg.pivot_ = suggestedPivot; + // If a extension object is not present, set the pivot value as being + // after the last value in the array to avoid overwriting values, etc. + msg.pivot_ = Math.max( + suggestedPivot, jspb.Message.getFieldNumber_(msg, lastIndex + 1)); // Avoid changing the shape of the proto with an empty extension object by // deferring the materialization of the extension object until the first // time a field set into it (may be due to getting a repeated proto field @@ -480,8 +520,7 @@ jspb.Message.toObjectList = function(field, toObjectFn, opt_includeInstance) { // And not using it here to avoid a function call. var result = []; for (var i = 0; i < field.length; i++) { - result[i] = toObjectFn.call(field[i], opt_includeInstance, - /** @type {!jspb.Message} */ (field[i])); + result[i] = toObjectFn.call(field[i], opt_includeInstance, field[i]); } return result; }; @@ -514,10 +553,11 @@ jspb.Message.toObjectExtension = function(proto, obj, extensions, } else { if (fieldInfo.isRepeated) { obj[name] = jspb.Message.toObjectList( - /** @type {!Array} */ (value), + /** @type {!Array} */ (value), fieldInfo.toObjectFn, opt_includeInstance); } else { - obj[name] = fieldInfo.toObjectFn(opt_includeInstance, value); + obj[name] = fieldInfo.toObjectFn( + opt_includeInstance, /** @type {!jspb.Message} */ (value)); } } } @@ -576,10 +616,7 @@ jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions, * Reads an extension field from the given reader and, if a valid extension, * sets the extension value. * @param {!jspb.Message} msg A jspb proto. - * @param {{ - * skipField:function(this:jspb.BinaryReader), - * getFieldNumber:function(this:jspb.BinaryReader):number - * }} reader + * @param {!jspb.BinaryReader} reader * @param {!Object} extensions The extensions object. * @param {function(this:jspb.Message,!jspb.ExtensionFieldInfo)} getExtensionFn * @param {function(this:jspb.Message,!jspb.ExtensionFieldInfo, ?)} setExtensionFn @@ -658,20 +695,7 @@ jspb.Message.getField = function(msg, fieldNumber) { * @protected */ jspb.Message.getRepeatedField = function(msg, fieldNumber) { - if (fieldNumber < msg.pivot_) { - var index = jspb.Message.getIndex_(msg, fieldNumber); - var val = msg.array[index]; - if (val === jspb.Message.EMPTY_LIST_SENTINEL_) { - return msg.array[index] = []; - } - return val; - } - - var val = msg.extensionObject_[fieldNumber]; - if (val === jspb.Message.EMPTY_LIST_SENTINEL_) { - return msg.extensionObject_[fieldNumber] = []; - } - return val; + return /** @type {!Array} */ (jspb.Message.getField(msg, fieldNumber)); }; @@ -689,6 +713,20 @@ jspb.Message.getOptionalFloatingPointField = function(msg, fieldNumber) { }; +/** + * Gets the value of an optional boolean field. + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @return {?boolean|undefined} The field's value. + * @protected + */ +jspb.Message.getBooleanField = function(msg, fieldNumber) { + var value = jspb.Message.getField(msg, fieldNumber); + // TODO(b/122673075): always return null when the value is null-ish. + return value == null ? (value) : !!value; +}; + + /** * Gets the value of a repeated float or double field. * @param {!jspb.Message} msg A jspb proto. @@ -698,20 +736,42 @@ jspb.Message.getOptionalFloatingPointField = function(msg, fieldNumber) { */ jspb.Message.getRepeatedFloatingPointField = function(msg, fieldNumber) { var values = jspb.Message.getRepeatedField(msg, fieldNumber); - if (!msg.convertedFloatingPointFields_) { - msg.convertedFloatingPointFields_ = {}; + if (!msg.convertedPrimitiveFields_) { + msg.convertedPrimitiveFields_ = {}; } - if (!msg.convertedFloatingPointFields_[fieldNumber]) { + if (!msg.convertedPrimitiveFields_[fieldNumber]) { for (var i = 0; i < values.length; i++) { // Converts "NaN", "Infinity" and "-Infinity" to their corresponding // numbers. values[i] = +values[i]; } - msg.convertedFloatingPointFields_[fieldNumber] = true; + msg.convertedPrimitiveFields_[fieldNumber] = true; } return /** @type {!Array} */ (values); }; +/** + * Gets the value of a repeated boolean field. + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @return {!Array} The field's value. + * @protected + */ +jspb.Message.getRepeatedBooleanField = function(msg, fieldNumber) { + var values = jspb.Message.getRepeatedField(msg, fieldNumber); + if (!msg.convertedPrimitiveFields_) { + msg.convertedPrimitiveFields_ = {}; + } + if (!msg.convertedPrimitiveFields_[fieldNumber]) { + for (var i = 0; i < values.length; i++) { + // Converts 0 and 1 to their corresponding booleans. + values[i] = !!values[i]; + } + msg.convertedPrimitiveFields_[fieldNumber] = true; + } + return /** @type {!Array} */ (values); +}; + /** * Coerce a 'bytes' field to a base 64 string. @@ -719,7 +779,7 @@ jspb.Message.getRepeatedFloatingPointField = function(msg, fieldNumber) { * @return {?string} The field's coerced value. */ jspb.Message.bytesAsB64 = function(value) { - if (value == null || goog.isString(value)) { + if (value == null || typeof value === 'string') { return value; } if (jspb.Message.SUPPORTS_UINT8ARRAY_ && value instanceof Uint8Array) { @@ -741,7 +801,7 @@ jspb.Message.bytesAsU8 = function(value) { if (value == null || value instanceof Uint8Array) { return value; } - if (goog.isString(value)) { + if (typeof value === 'string') { return goog.crypt.base64.decodeStringToUint8Array(value); } goog.asserts.fail('Cannot coerce to Uint8Array: ' + goog.typeOf(value)); @@ -757,7 +817,7 @@ jspb.Message.bytesAsU8 = function(value) { */ jspb.Message.bytesListAsB64 = function(value) { jspb.Message.assertConsistentTypes_(value); - if (!value.length || goog.isString(value[0])) { + if (!value.length || typeof value[0] === 'string') { return /** @type {!Array} */ (value); } return goog.array.map(value, jspb.Message.bytesAsB64); @@ -820,6 +880,49 @@ jspb.Message.getFieldWithDefault = function(msg, fieldNumber, defaultValue) { }; +/** + * Gets the value of a boolean field, with proto3 (non-nullable primitives) + * semantics. Returns `defaultValue` if the field is not otherwise set. + * @template T + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {boolean} defaultValue The default value. + * @return {boolean} The field's value. + * @protected + */ +jspb.Message.getBooleanFieldWithDefault = function( + msg, fieldNumber, defaultValue) { + var value = jspb.Message.getBooleanField(msg, fieldNumber); + if (value == null) { + return defaultValue; + } else { + return value; + } +}; + + +/** + * Gets the value of a floating point field, with proto3 (non-nullable + * primitives) semantics. Returns `defaultValue` if the field is not otherwise + * set. + * @template T + * @param {!jspb.Message} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {number} defaultValue The default value. + * @return {number} The field's value. + * @protected + */ +jspb.Message.getFloatingPointFieldWithDefault = function( + msg, fieldNumber, defaultValue) { + var value = jspb.Message.getOptionalFloatingPointField(msg, fieldNumber); + if (value == null) { + return defaultValue; + } else { + return value; + } +}; + + /** * Alias for getFieldWithDefault used by older generated code. * @template T @@ -856,67 +959,207 @@ jspb.Message.getMapField = function(msg, fieldNumber, noLazyCreate, // If we already have a map in the map wrappers, return that. if (fieldNumber in msg.wrappers_) { return msg.wrappers_[fieldNumber]; - } else if (noLazyCreate) { - return undefined; - } else { - // Wrap the underlying elements array with a Map. - var arr = jspb.Message.getField(msg, fieldNumber); - if (!arr) { - arr = []; - jspb.Message.setField(msg, fieldNumber, arr); + } + var arr = jspb.Message.getField(msg, fieldNumber); + // Wrap the underlying elements array with a Map. + if (!arr) { + if (noLazyCreate) { + return undefined; } - return msg.wrappers_[fieldNumber] = - new jspb.Map( - /** @type {!Array>} */ (arr), opt_valueCtor); + arr = []; + jspb.Message.setField(msg, fieldNumber, arr); } + return msg.wrappers_[fieldNumber] = + new jspb.Map( + /** @type {!Array>} */ (arr), opt_valueCtor); }; /** * Sets the value of a non-extension field. - * @param {!jspb.Message} msg A jspb proto. + * @param {T} msg A jspb proto. * @param {number} fieldNumber The field number. * @param {string|number|boolean|Uint8Array|Array|undefined} value New value + * @return {T} return msg + * @template T * @protected */ jspb.Message.setField = function(msg, fieldNumber, value) { + // TODO(b/35241823): replace this with a bounded generic when available + goog.asserts.assertInstanceof(msg, jspb.Message); if (fieldNumber < msg.pivot_) { msg.array[jspb.Message.getIndex_(msg, fieldNumber)] = value; } else { jspb.Message.maybeInitEmptyExtensionObject_(msg); msg.extensionObject_[fieldNumber] = value; } + return msg; +}; + + +/** + * Sets the value of a non-extension integer field of a proto3 + * @param {T} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {number} value New value + * @return {T} return msg + * @template T + * @protected + */ +jspb.Message.setProto3IntField = function(msg, fieldNumber, value) { + return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0); +}; + + +/** + * Sets the value of a non-extension floating point field of a proto3 + * @param {T} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {number} value New value + * @return {T} return msg + * @template T + * @protected + */ +jspb.Message.setProto3FloatField = function(msg, fieldNumber, value) { + return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0.0); +}; + + +/** + * Sets the value of a non-extension boolean field of a proto3 + * @param {T} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {boolean} value New value + * @return {T} return msg + * @template T + * @protected + */ +jspb.Message.setProto3BooleanField = function(msg, fieldNumber, value) { + return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, false); +}; + + +/** + * Sets the value of a non-extension String field of a proto3 + * @param {T} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {string} value New value + * @return {T} return msg + * @template T + * @protected + */ +jspb.Message.setProto3StringField = function(msg, fieldNumber, value) { + return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, ''); +}; + + +/** + * Sets the value of a non-extension Bytes field of a proto3 + * @param {T} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {!Uint8Array|string} value New value + * @return {T} return msg + * @template T + * @protected + */ +jspb.Message.setProto3BytesField = function(msg, fieldNumber, value) { + return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, ''); +}; + + +/** + * Sets the value of a non-extension enum field of a proto3 + * @param {T} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {number} value New value + * @return {T} return msg + * @template T + * @protected + */ +jspb.Message.setProto3EnumField = function(msg, fieldNumber, value) { + return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, 0); +}; + + +/** + * Sets the value of a non-extension int field of a proto3 that has jstype set + * to String. + * @param {T} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {string} value New value + * @return {T} return msg + * @template T + * @protected + */ +jspb.Message.setProto3StringIntField = function(msg, fieldNumber, value) { + return jspb.Message.setFieldIgnoringDefault_(msg, fieldNumber, value, '0'); +}; + +/** + * Sets the value of a non-extension primitive field, with proto3 (non-nullable + * primitives) semantics of ignoring values that are equal to the type's + * default. + * @param {T} msg A jspb proto. + * @param {number} fieldNumber The field number. + * @param {!Uint8Array|string|number|boolean|undefined} value New value + * @param {!Uint8Array|string|number|boolean} defaultValue The default value. + * @return {T} return msg + * @template T + * @private + */ +jspb.Message.setFieldIgnoringDefault_ = function( + msg, fieldNumber, value, defaultValue) { + // TODO(b/35241823): replace this with a bounded generic when available + goog.asserts.assertInstanceof(msg, jspb.Message); + if (value !== defaultValue) { + jspb.Message.setField(msg, fieldNumber, value); + } else if (fieldNumber < msg.pivot_) { + msg.array[jspb.Message.getIndex_(msg, fieldNumber)] = null; + } else { + jspb.Message.maybeInitEmptyExtensionObject_(msg); + delete msg.extensionObject_[fieldNumber]; + } + return msg; }; /** * Adds a value to a repeated, primitive field. - * @param {!jspb.Message} msg A jspb proto. + * @param {T} msg A jspb proto. * @param {number} fieldNumber The field number. * @param {string|number|boolean|!Uint8Array} value New value * @param {number=} opt_index Index where to put new value. + * @return {T} return msg + * @template T * @protected */ jspb.Message.addToRepeatedField = function(msg, fieldNumber, value, opt_index) { + // TODO(b/35241823): replace this with a bounded generic when available + goog.asserts.assertInstanceof(msg, jspb.Message); var arr = jspb.Message.getRepeatedField(msg, fieldNumber); if (opt_index != undefined) { arr.splice(opt_index, 0, value); } else { arr.push(value); } + return msg; }; /** * Sets the value of a field in a oneof union and clears all other fields in * the union. - * @param {!jspb.Message} msg A jspb proto. + * @param {T} msg A jspb proto. * @param {number} fieldNumber The field number. * @param {!Array} oneof The fields belonging to the union. * @param {string|number|boolean|Uint8Array|Array|undefined} value New value + * @return {T} return msg + * @template T * @protected */ jspb.Message.setOneofField = function(msg, fieldNumber, oneof, value) { + // TODO(b/35241823): replace this with a bounded generic when available + goog.asserts.assertInstanceof(msg, jspb.Message); var currentCase = jspb.Message.computeOneofCase(msg, oneof); if (currentCase && currentCase !== fieldNumber && value !== undefined) { if (msg.wrappers_ && currentCase in msg.wrappers_) { @@ -924,7 +1167,7 @@ jspb.Message.setOneofField = function(msg, fieldNumber, oneof, value) { } jspb.Message.setField(msg, currentCase, undefined); } - jspb.Message.setField(msg, fieldNumber, value); + return jspb.Message.setField(msg, fieldNumber, value); }; @@ -949,14 +1192,15 @@ jspb.Message.computeOneofCase = function(msg, oneof) { var oneofField; var oneofValue; - goog.array.forEach(oneof, function(fieldNumber) { + for (var i = 0; i < oneof.length; i++) { + var fieldNumber = oneof[i]; var value = jspb.Message.getField(msg, fieldNumber); - if (goog.isDefAndNotNull(value)) { + if (value != null) { oneofField = fieldNumber; oneofValue = value; jspb.Message.setField(msg, fieldNumber, undefined); } - }); + } if (oneofField) { // NB: We know the value is unique, so we can call jspb.Message.setField @@ -1000,7 +1244,7 @@ jspb.Message.getWrapperField = function(msg, ctor, fieldNumber, opt_required) { * @param {!jspb.Message} msg A jspb proto. * @param {function(new:jspb.Message, Array)} ctor Constructor for the field. * @param {number} fieldNumber The field number. - * @return {Array} The repeated field as an array of protos. + * @return {!Array} The repeated field as an array of protos. * @protected */ jspb.Message.getRepeatedWrapperField = function(msg, ctor, fieldNumber) { @@ -1037,48 +1281,61 @@ jspb.Message.wrapRepeatedField_ = function(msg, ctor, fieldNumber) { /** * Sets a proto field and syncs it to the backing array. - * @param {!jspb.Message} msg A jspb proto. + * @param {T} msg A jspb proto. * @param {number} fieldNumber The field number. * @param {?jspb.Message|?jspb.Map|undefined} value A new value for this proto * field. + * @return {T} the msg + * @template T * @protected */ jspb.Message.setWrapperField = function(msg, fieldNumber, value) { + // TODO(b/35241823): replace this with a bounded generic when available + goog.asserts.assertInstanceof(msg, jspb.Message); if (!msg.wrappers_) { msg.wrappers_ = {}; } var data = value ? value.toArray() : value; msg.wrappers_[fieldNumber] = value; - jspb.Message.setField(msg, fieldNumber, data); + return jspb.Message.setField(msg, fieldNumber, data); }; + /** * Sets a proto field in a oneof union and syncs it to the backing array. - * @param {!jspb.Message} msg A jspb proto. + * @param {T} msg A jspb proto. * @param {number} fieldNumber The field number. * @param {!Array} oneof The fields belonging to the union. * @param {jspb.Message|undefined} value A new value for this proto field. + * @return {T} the msg + * @template T * @protected */ jspb.Message.setOneofWrapperField = function(msg, fieldNumber, oneof, value) { + // TODO(b/35241823): replace this with a bounded generic when available + goog.asserts.assertInstanceof(msg, jspb.Message); if (!msg.wrappers_) { msg.wrappers_ = {}; } var data = value ? value.toArray() : value; msg.wrappers_[fieldNumber] = value; - jspb.Message.setOneofField(msg, fieldNumber, oneof, data); + return jspb.Message.setOneofField(msg, fieldNumber, oneof, data); }; /** * Sets a repeated proto field and syncs it to the backing array. - * @param {!jspb.Message} msg A jspb proto. + * @param {T} msg A jspb proto. * @param {number} fieldNumber The field number. * @param {Array|undefined} value An array of protos. + * @return {T} the msg + * @template T * @protected */ jspb.Message.setRepeatedWrapperField = function(msg, fieldNumber, value) { + // TODO(b/35241823): replace this with a bounded generic when available + goog.asserts.assertInstanceof(msg, jspb.Message); if (!msg.wrappers_) { msg.wrappers_ = {}; } @@ -1087,7 +1344,7 @@ jspb.Message.setRepeatedWrapperField = function(msg, fieldNumber, value) { data[i] = value[i].toArray(); } msg.wrappers_[fieldNumber] = value; - jspb.Message.setField(msg, fieldNumber, data); + return jspb.Message.setField(msg, fieldNumber, data); }; @@ -1147,7 +1404,7 @@ jspb.Message.addToRepeatedWrapperField = function( * dead code removal. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration - * @return {!Object.} A map of proto or Soy objects. + * @return {!Object} A map of proto or Soy objects. * @template T */ jspb.Message.toMap = function( @@ -1177,7 +1434,7 @@ jspb.Message.prototype.syncMapFields_ = function() { if (this.wrappers_) { for (var fieldNumber in this.wrappers_) { var val = this.wrappers_[fieldNumber]; - if (goog.isArray(val)) { + if (Array.isArray(val)) { for (var i = 0; i < val.length; i++) { if (val[i]) { val[i].toArray(); @@ -1224,7 +1481,7 @@ jspb.Message.prototype.toString = function() { /** * Gets the value of the extension field from the extended object. - * @param {jspb.ExtensionFieldInfo.} fieldInfo Specifies the field to get. + * @param {jspb.ExtensionFieldInfo} fieldInfo Specifies the field to get. * @return {T} The value of the field. * @template T */ @@ -1287,7 +1544,7 @@ jspb.Message.prototype.setExtension = function(fieldInfo, value) { if (fieldInfo.isMessageType()) { self.wrappers_[fieldNumber] = value; self.extensionObject_[fieldNumber] = goog.array.map( - /** @type {Array} */ (value), function(msg) { + /** @type {!Array} */ (value), function(msg) { return msg.toArray(); }); } else { @@ -1296,7 +1553,8 @@ jspb.Message.prototype.setExtension = function(fieldInfo, value) { } else { if (fieldInfo.isMessageType()) { self.wrappers_[fieldNumber] = value; - self.extensionObject_[fieldNumber] = value ? value.toArray() : value; + self.extensionObject_[fieldNumber] = + value ? /** @type {!jspb.Message} */ (value).toArray() : value; } else { self.extensionObject_[fieldNumber] = value; } @@ -1398,9 +1656,15 @@ jspb.Message.compareFields = function(field1, field2) { // If the fields are trivially equal, they're equal. if (field1 == field2) return true; - // If the fields aren't trivially equal and one of them isn't an object, - // they can't possibly be equal. if (!goog.isObject(field1) || !goog.isObject(field2)) { + // NaN != NaN so we cover this case. + if ((typeof field1 === 'number' && isNaN(field1)) || + (typeof field2 === 'number' && isNaN(field2))) { + // One of the fields might be a string 'NaN'. + return String(field1) == String(field2); + } + // If the fields aren't trivially equal and one of them isn't an object, + // they can't possibly be equal. return false; } @@ -1423,24 +1687,26 @@ jspb.Message.compareFields = function(field1, field2) { // If they're both Arrays, compare them element by element except for the // optional extension objects at the end, which we compare separately. if (field1.constructor === Array) { + var typedField1 = /** @type {!Array} */ (field1); + var typedField2 = /** @type {!Array} */ (field2); var extension1 = undefined; var extension2 = undefined; - var length = Math.max(field1.length, field2.length); + var length = Math.max(typedField1.length, typedField2.length); for (var i = 0; i < length; i++) { - var val1 = field1[i]; - var val2 = field2[i]; + var val1 = typedField1[i]; + var val2 = typedField2[i]; if (val1 && (val1.constructor == Object)) { goog.asserts.assert(extension1 === undefined); - goog.asserts.assert(i === field1.length - 1); + goog.asserts.assert(i === typedField1.length - 1); extension1 = val1; val1 = undefined; } if (val2 && (val2.constructor == Object)) { goog.asserts.assert(extension2 === undefined); - goog.asserts.assert(i === field2.length - 1); + goog.asserts.assert(i === typedField2.length - 1); extension2 = val2; val2 = undefined; } @@ -1558,13 +1824,18 @@ jspb.Message.copyInto = function(fromMessage, toMessage) { */ jspb.Message.clone_ = function(obj) { var o; - if (goog.isArray(obj)) { + if (Array.isArray(obj)) { // Allocate array of correct size. var clonedArray = new Array(obj.length); // Use array iteration where possible because it is faster than for-in. for (var i = 0; i < obj.length; i++) { - if ((o = obj[i]) != null) { - clonedArray[i] = typeof o == 'object' ? jspb.Message.clone_(o) : o; + o = obj[i]; + if (o != null) { + // NOTE:redundant null check existing for NTI compatibility. + // see b/70515949 + clonedArray[i] = (typeof o == 'object') ? + jspb.Message.clone_(goog.asserts.assert(o)) : + o; } } return clonedArray; @@ -1574,8 +1845,13 @@ jspb.Message.clone_ = function(obj) { } var clone = {}; for (var key in obj) { - if ((o = obj[key]) != null) { - clone[key] = typeof o == 'object' ? jspb.Message.clone_(o) : o; + o = obj[key]; + if (o != null) { + // NOTE:redundant null check existing for NTI compatibility. + // see b/70515949 + clone[key] = (typeof o == 'object') ? + jspb.Message.clone_(goog.asserts.assert(o)) : + o; } } return clone; @@ -1588,20 +1864,13 @@ jspb.Message.clone_ = function(obj) { * @param {Function} constructor The message constructor. */ jspb.Message.registerMessageType = function(id, constructor) { - jspb.Message.registry_[id] = constructor; - // This is needed so we can later access messageId directly on the contructor, + // This is needed so we can later access messageId directly on the constructor, // otherwise it is not available due to 'property collapsing' by the compiler. + /** + * @suppress {strictMissingProperties} messageId is not defined on Function + */ constructor.messageId = id; }; - - -/** - * The registry of message ids to message constructors. - * @private - */ -jspb.Message.registry_ = {}; - - /** * The extensions registered on MessageSet. This is a map of extension * field number to field info object. This should be considered as a @@ -1611,7 +1880,11 @@ jspb.Message.registry_ = {}; * non-MessageSet. We special case MessageSet so that we do not need * to goog.require MessageSet from classes that extends MessageSet. * - * @type {!Object.} + * @type {!Object} */ jspb.Message.messageSetExtensions = {}; + +/** + * @type {!Object} + */ jspb.Message.messageSetExtensionsBinary = {}; diff --git a/js/message_test.js b/js/message_test.js index 7d61dacbb35d6..2a524deebab83 100644 --- a/js/message_test.js +++ b/js/message_test.js @@ -32,14 +32,45 @@ goog.setTestOnly(); -goog.require('goog.json'); -goog.require('goog.string'); +goog.require('goog.testing.PropertyReplacer'); goog.require('goog.testing.asserts'); goog.require('goog.userAgent'); // CommonJS-LoadFromFile: google-protobuf jspb goog.require('jspb.Message'); +// CommonJS-LoadFromFile: test15_pb proto.jspb.filenametest.package1 +goog.require('proto.jspb.filenametest.package1.b'); + +// CommonJS-LoadFromFile: test14_pb proto.jspb.filenametest.package2 +goog.require('proto.jspb.filenametest.package2.TestMessage'); + +// CommonJS-LoadFromFile: test13_pb proto.jspb.filenametest.package1 +goog.require('proto.jspb.filenametest.package1.a'); +goog.require('proto.jspb.filenametest.package1.TestMessage'); + +// CommonJS-LoadFromFile: test12_pb proto.jspb.circulartest +goog.require('proto.jspb.circulartest.ExtensionContainingType1'); +goog.require('proto.jspb.circulartest.ExtensionContainingType2'); +goog.require('proto.jspb.circulartest.ExtensionField1'); +goog.require('proto.jspb.circulartest.ExtensionField2'); +goog.require('proto.jspb.circulartest.ExtensionField3'); +goog.require('proto.jspb.circulartest.MapField1'); +goog.require('proto.jspb.circulartest.MapField2'); +goog.require('proto.jspb.circulartest.MessageField1'); +goog.require('proto.jspb.circulartest.MessageField2'); +goog.require('proto.jspb.circulartest.NestedEnum1'); +goog.require('proto.jspb.circulartest.NestedEnum2'); +goog.require('proto.jspb.circulartest.NestedMessage1'); +goog.require('proto.jspb.circulartest.NestedMessage2'); +goog.require('proto.jspb.circulartest.RepeatedMessageField1'); +goog.require('proto.jspb.circulartest.RepeatedMessageField2'); + +// CommonJS-LoadFromFile: test11_pb proto.jspb.exttest.reverse +goog.require('proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage1'); +goog.require('proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage2'); +goog.require('proto.jspb.exttest.reverse.c'); + // CommonJS-LoadFromFile: test8_pb proto.jspb.exttest.nested goog.require('proto.jspb.exttest.nested.TestNestedExtensionsMessage'); goog.require('proto.jspb.exttest.nested.TestOuterMessage'); @@ -54,6 +85,7 @@ goog.require('proto.jspb.exttest.floatingMsgField'); goog.require('proto.jspb.exttest.floatingMsgFieldTwo'); // CommonJS-LoadFromFile: test_pb proto.jspb.test +goog.require('proto.jspb.test.BooleanFields'); goog.require('proto.jspb.test.CloneExtension'); goog.require('proto.jspb.test.Complex'); goog.require('proto.jspb.test.DefaultValues'); @@ -72,9 +104,11 @@ goog.require('proto.jspb.test.Simple1'); goog.require('proto.jspb.test.Simple2'); goog.require('proto.jspb.test.SpecialCases'); goog.require('proto.jspb.test.TestClone'); +goog.require('proto.jspb.test.TestCloneExtension'); goog.require('proto.jspb.test.TestEndsWithBytes'); goog.require('proto.jspb.test.TestGroup'); goog.require('proto.jspb.test.TestGroup1'); +goog.require('proto.jspb.test.TestLastFieldBeforePivot'); goog.require('proto.jspb.test.TestMessageWithOneof'); goog.require('proto.jspb.test.TestReservedNames'); goog.require('proto.jspb.test.TestReservedNamesExtension'); @@ -83,8 +117,23 @@ goog.require('proto.jspb.test.TestReservedNamesExtension'); goog.require('proto.jspb.test.ExtensionMessage'); goog.require('proto.jspb.test.TestExtensionsMessage'); +goog.require('proto.jspb.test.TestAllowAliasEnum'); +// CommonJS-LoadFromFile: testlargenumbers_pb proto.jspb.test +goog.require('proto.jspb.test.MessageWithLargeFieldNumbers'); + +goog.require('proto.jspb.test.simple1'); describe('Message test suite', function() { + var stubs = new goog.testing.PropertyReplacer(); + + beforeEach(function() { + stubs.set(jspb.Message, 'SERIALIZE_EMPTY_TRAILING_FIELDS', false); + }); + + afterEach(function() { + stubs.reset(); + }); + it('testEmptyProto', function() { var empty1 = new proto.jspb.test.Empty([]); var empty2 = new proto.jspb.test.Empty([]); @@ -105,59 +154,62 @@ describe('Message test suite', function() { }); it('testComplexConversion', function() { - var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1]; - var data2 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1]; + var data1 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , 1]; + var data2 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , 1]; var foo = new proto.jspb.test.Complex(data1); var bar = new proto.jspb.test.Complex(data2); var result = foo.toObject(); - assertObjectEquals({ - aString: 'a', - anOutOfOrderBool: 1, - aNestedMessage: { - anInt: 11 - }, - aRepeatedMessageList: [{anInt: 22}, {anInt: 33}], - aRepeatedStringList: ['s1', 's2'] - }, result); + assertObjectEquals( + { + aString: 'a', + anOutOfOrderBool: true, + aNestedMessage: {anInt: 11}, + aRepeatedMessageList: [{anInt: 22}, {anInt: 33}], + aRepeatedStringList: ['s1', 's2'], + aFloatingPointField: undefined, + }, + result); // Now test with the jspb instances included. result = foo.toObject(true /* opt_includeInstance */); - assertObjectEquals({ - aString: 'a', - anOutOfOrderBool: 1, - aNestedMessage: { - anInt: 11, - $jspbMessageInstance: foo.getANestedMessage() - }, - aRepeatedMessageList: [ - {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]}, - {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]} - ], - aRepeatedStringList: ['s1', 's2'], - $jspbMessageInstance: foo - }, result); - + assertObjectEquals( + { + aString: 'a', + anOutOfOrderBool: true, + aNestedMessage: + {anInt: 11, $jspbMessageInstance: foo.getANestedMessage()}, + aRepeatedMessageList: [ + {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]}, + {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]} + ], + aRepeatedStringList: ['s1', 's2'], + aFloatingPointField: undefined, + $jspbMessageInstance: foo + }, + result); }); it('testMissingFields', function() { var foo = new proto.jspb.test.Complex([ - undefined, undefined, undefined, [], - undefined, undefined, undefined, undefined]); + undefined, undefined, undefined, [], undefined, undefined, undefined, + undefined + ]); var bar = new proto.jspb.test.Complex([ - undefined, undefined, undefined, [], - undefined, undefined, undefined, undefined]); + undefined, undefined, undefined, [], undefined, undefined, undefined, + undefined + ]); var result = foo.toObject(); - assertObjectEquals({ - aString: undefined, - anOutOfOrderBool: undefined, - aNestedMessage: { - anInt: undefined - }, - // Note: JsPb converts undefined repeated fields to empty arrays. - aRepeatedMessageList: [], - aRepeatedStringList: [] - }, result); - + assertObjectEquals( + { + aString: undefined, + anOutOfOrderBool: undefined, + aNestedMessage: {anInt: undefined}, + // Note: JsPb converts undefined repeated fields to empty arrays. + aRepeatedMessageList: [], + aRepeatedStringList: [], + aFloatingPointField: undefined, + }, + result); }); it('testNestedComplexMessage', function() { @@ -170,20 +222,21 @@ describe('Message test suite', function() { it('testSpecialCases', function() { // Note: Some property names are reserved in JavaScript. // These names are converted to the Js property named pb_. - var special = - new proto.jspb.test.SpecialCases(['normal', 'default', 'function', - 'var']); + var special = new proto.jspb.test.SpecialCases( + ['normal', 'default', 'function', 'var']); var result = special.toObject(); - assertObjectEquals({ - normal: 'normal', - pb_default: 'default', - pb_function: 'function', - pb_var: 'var' - }, result); + assertObjectEquals( + { + normal: 'normal', + pb_default: 'default', + pb_function: 'function', + pb_var: 'var' + }, + result); }); it('testDefaultValues', function() { - var defaultString = "default<>\'\"abc"; + var defaultString = 'default<>\'"abc'; var response = new proto.jspb.test.DefaultValues(); // Test toObject @@ -247,8 +300,10 @@ describe('Message test suite', function() { // Test that clearing the values reverts them to the default state. response = makeDefault(['blah', false, 111, 77]); - response.clearStringField(); response.clearBoolField(); - response.clearIntField(); response.clearEnumField(); + response.clearStringField(); + response.clearBoolField(); + response.clearIntField(); + response.clearEnumField(); assertEquals(defaultString, response.getStringField()); assertEquals(true, response.getBoolField()); assertEquals(11, response.getIntField()); @@ -260,8 +315,10 @@ describe('Message test suite', function() { // Test that setFoo(null) clears the values. response = makeDefault(['blah', false, 111, 77]); - response.setStringField(null); response.setBoolField(null); - response.setIntField(undefined); response.setEnumField(undefined); + response.setStringField(null); + response.setBoolField(null); + response.setIntField(undefined); + response.setEnumField(undefined); assertEquals(defaultString, response.getStringField()); assertEquals(true, response.getBoolField()); assertEquals(11, response.getIntField()); @@ -272,54 +329,18 @@ describe('Message test suite', function() { assertFalse(response.hasEnumField()); }); - it('testClearFields', function() { - var data = ['str', true, [11], [[22], [33]], ['s1', 's2']]; - var foo = new proto.jspb.test.OptionalFields(data); - foo.clearAString(); - foo.clearABool(); - foo.clearANestedMessage(); - foo.clearARepeatedMessageList(); - foo.clearARepeatedStringList(); - assertEquals('', foo.getAString()); - assertEquals(false, foo.getABool()); - assertUndefined(foo.getANestedMessage()); - assertFalse(foo.hasAString()); - assertFalse(foo.hasABool()); - assertObjectEquals([], foo.getARepeatedMessageList()); - assertObjectEquals([], foo.getARepeatedStringList()); - // NOTE: We want the missing fields in 'expected' to be undefined, - // but we actually get a sparse array instead. We could use something - // like [1,undefined,2] to avoid this, except that this is still - // sparse on IE. No comment... - var expected = [,,, [], []]; - expected[0] = expected[1] = expected[2] = undefined; - assertObjectEquals(expected, foo.toArray()); - }); - - it('testDifferenceRawObject', /** @suppress {visibility} */ function() { - var p1 = new proto.jspb.test.HasExtensions(['hi', 'diff', {}]); - var p2 = new proto.jspb.test.HasExtensions(['hi', 'what', - {1000: 'unique'}]); - var diff = /** @type {proto.jspb.test.HasExtensions} */ - (jspb.Message.difference(p1, p2)); - assertEquals('', diff.getStr1()); - assertEquals('what', diff.getStr2()); - assertEquals('', diff.getStr3()); - assertEquals('unique', diff.extensionObject_[1000]); - }); - it('testEqualsSimple', function() { var s1 = new proto.jspb.test.Simple1(['hi']); assertTrue(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi']))); assertFalse(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['bye']))); var s1b = new proto.jspb.test.Simple1(['hi', ['hello']]); - assertTrue(jspb.Message.equals(s1b, - new proto.jspb.test.Simple1(['hi', ['hello']]))); - assertTrue(jspb.Message.equals(s1b, - new proto.jspb.test.Simple1(['hi', ['hello', undefined, - undefined, undefined]]))); - assertFalse(jspb.Message.equals(s1b, - new proto.jspb.test.Simple1(['no', ['hello']]))); + assertTrue(jspb.Message.equals( + s1b, new proto.jspb.test.Simple1(['hi', ['hello']]))); + assertTrue(jspb.Message.equals(s1b, new proto.jspb.test.Simple1([ + 'hi', ['hello', undefined, undefined, undefined] + ]))); + assertFalse(jspb.Message.equals( + s1b, new proto.jspb.test.Simple1(['no', ['hello']]))); // Test with messages of different types var s2 = new proto.jspb.test.Simple2(['hi']); assertFalse(jspb.Message.equals(s1, s2)); @@ -327,18 +348,18 @@ describe('Message test suite', function() { it('testEquals_softComparison', function() { var s1 = new proto.jspb.test.Simple1(['hi', [], null]); - assertTrue(jspb.Message.equals(s1, - new proto.jspb.test.Simple1(['hi', []]))); + assertTrue( + jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi', []]))); var s1b = new proto.jspb.test.Simple1(['hi', [], true]); - assertTrue(jspb.Message.equals(s1b, - new proto.jspb.test.Simple1(['hi', [], 1]))); + assertTrue( + jspb.Message.equals(s1b, new proto.jspb.test.Simple1(['hi', [], 1]))); }); it('testEqualsComplex', function() { - var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1]; - var data2 = ['a',,, [, 11], [[, 22], [, 34]],, ['s1', 's2'],, 1]; - var data3 = ['a',,, [, 11], [[, 22]],, ['s1', 's2'],, 1]; + var data1 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , 1]; + var data2 = ['a', , , [, 11], [[, 22], [, 34]], , ['s1', 's2'], , 1]; + var data3 = ['a', , , [, 11], [[, 22]], , ['s1', 's2'], , 1]; var data4 = ['hi']; var c1a = new proto.jspb.test.Complex(data1); var c1b = new proto.jspb.test.Complex(data1); @@ -355,42 +376,34 @@ describe('Message test suite', function() { it('testEqualsExtensionsConstructed', function() { assertTrue(jspb.Message.equals( new proto.jspb.test.HasExtensions([]), - new proto.jspb.test.HasExtensions([{}]) - )); + new proto.jspb.test.HasExtensions([{}]))); assertTrue(jspb.Message.equals( new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]), - new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]) - )); + new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]))); assertFalse(jspb.Message.equals( new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]), - new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'b'}]}]) - )); + new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'b'}]}]))); assertTrue(jspb.Message.equals( new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]), - new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]) - )); + new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]))); assertTrue(jspb.Message.equals( new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]), - new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}]) - )); + new proto.jspb.test.HasExtensions([, , , {100: [{200: 'a'}]}]))); assertTrue(jspb.Message.equals( - new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}]), - new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]) - )); + new proto.jspb.test.HasExtensions([, , , {100: [{200: 'a'}]}]), + new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]))); assertTrue(jspb.Message.equals( new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]), - new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}]) - )); + new proto.jspb.test.HasExtensions(['hi', , , {100: [{200: 'a'}]}]))); assertTrue(jspb.Message.equals( - new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}]), - new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]) - )); + new proto.jspb.test.HasExtensions(['hi', , , {100: [{200: 'a'}]}]), + new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]))); }); it('testEqualsExtensionsUnconstructed', function() { assertTrue(jspb.Message.compareFields([], [{}])); - assertTrue(jspb.Message.compareFields([,,, {}], [])); - assertTrue(jspb.Message.compareFields([,,, {}], [,, {}])); + assertTrue(jspb.Message.compareFields([, , , {}], [])); + assertTrue(jspb.Message.compareFields([, , , {}], [, , {}])); assertTrue(jspb.Message.compareFields( ['hi', {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}])); assertFalse(jspb.Message.compareFields( @@ -398,25 +411,43 @@ describe('Message test suite', function() { assertTrue(jspb.Message.compareFields( [{100: [{200: 'a'}]}], [{100: [{200: 'a'}]}])); assertTrue(jspb.Message.compareFields( - [{100: [{200: 'a'}]}], [,,, {100: [{200: 'a'}]}])); + [{100: [{200: 'a'}]}], [, , , {100: [{200: 'a'}]}])); assertTrue(jspb.Message.compareFields( - [,,, {100: [{200: 'a'}]}], [{100: [{200: 'a'}]}])); + [, , , {100: [{200: 'a'}]}], [{100: [{200: 'a'}]}])); assertTrue(jspb.Message.compareFields( - ['hi', {100: [{200: 'a'}]}], ['hi',,, {100: [{200: 'a'}]}])); + ['hi', {100: [{200: 'a'}]}], ['hi', , , {100: [{200: 'a'}]}])); assertTrue(jspb.Message.compareFields( - ['hi',,, {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}])); + ['hi', , , {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}])); + }); + + it('testInitializeMessageWithLastFieldNull', function() { + // This tests for regression to bug http://b/117298778 + var msg = new proto.jspb.test.TestLastFieldBeforePivot([null]); + assertNotUndefined(msg.getLastFieldBeforePivot()); + }); + + it('testEqualsNonFinite', function() { + assertTrue(jspb.Message.compareFields(NaN, NaN)); + assertTrue(jspb.Message.compareFields(NaN, 'NaN')); + assertTrue(jspb.Message.compareFields('NaN', NaN)); + assertTrue(jspb.Message.compareFields(Infinity, Infinity)); + assertTrue(jspb.Message.compareFields(Infinity, 'Infinity')); + assertTrue(jspb.Message.compareFields('-Infinity', -Infinity)); + assertTrue(jspb.Message.compareFields([NaN], ['NaN'])); + assertFalse(jspb.Message.compareFields(undefined, NaN)); + assertFalse(jspb.Message.compareFields(NaN, undefined)); }); it('testToMap', function() { var p1 = new proto.jspb.test.Simple1(['k', ['v']]); var p2 = new proto.jspb.test.Simple1(['k1', ['v1', 'v2']]); - var soymap = jspb.Message.toMap([p1, p2], - proto.jspb.test.Simple1.prototype.getAString, + var soymap = jspb.Message.toMap( + [p1, p2], proto.jspb.test.Simple1.prototype.getAString, proto.jspb.test.Simple1.prototype.toObject); assertEquals('k', soymap['k'].aString); assertArrayEquals(['v'], soymap['k'].aRepeatedStringList); - var protomap = jspb.Message.toMap([p1, p2], - proto.jspb.test.Simple1.prototype.getAString); + var protomap = jspb.Message.toMap( + [p1, p2], proto.jspb.test.Simple1.prototype.getAString); assertEquals('k', protomap['k'].getAString()); assertArrayEquals(['v'], protomap['k'].getARepeatedStringList()); }); @@ -437,8 +468,12 @@ describe('Message test suite', function() { extension.setExt('e1'); original.setExtension(proto.jspb.test.IsExtension.extField, extension); var clone = original.clone(); - assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],, - [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }], + assertArrayEquals( + [ + 'v1', , ['x1', ['y1', 'z1']], , + [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1, , + {100: [, 'e1']} + ], clone.toArray()); clone.setStr('v2'); var simple4 = new proto.jspb.test.Simple1(['a1', ['b1', 'c1']]); @@ -455,11 +490,19 @@ describe('Message test suite', function() { var newExtension = new proto.jspb.test.CloneExtension(); newExtension.setExt('e2'); clone.setExtension(proto.jspb.test.CloneExtension.extField, newExtension); - assertArrayEquals(['v2',, ['a1', ['b1', 'c1']],, - [['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2,, { 100: [, 'e2'] }], + assertArrayEquals( + [ + 'v2', , ['a1', ['b1', 'c1']], , + [['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2, , + {100: [, 'e2']} + ], clone.toArray()); - assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],, - [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }], + assertArrayEquals( + [ + 'v1', , ['x1', ['y1', 'z1']], , + [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1, , + {100: [, 'e1']} + ], original.toArray()); }); @@ -491,11 +534,12 @@ describe('Message test suite', function() { jspb.Message.copyInto(original, dest); assertArrayEquals(original.toArray(), dest.toArray()); assertEquals('x1', dest.getSimple1().getAString()); - assertEquals('e1', + assertEquals( + 'e1', dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt()); dest.getSimple1().setAString('new value'); - assertNotEquals(dest.getSimple1().getAString(), - original.getSimple1().getAString()); + assertNotEquals( + dest.getSimple1().getAString(), original.getSimple1().getAString()); if (supportsUint8Array) { dest.getBytesField()[0] = 7; assertObjectEquals(bytes1, original.getBytesField()); @@ -505,12 +549,12 @@ describe('Message test suite', function() { assertObjectEquals(bytes1, original.getBytesField()); assertObjectEquals('789', dest.getBytesField()); } - dest.getExtension(proto.jspb.test.CloneExtension.extField). - setExt('new value'); + dest.getExtension(proto.jspb.test.CloneExtension.extField) + .setExt('new value'); assertNotEquals( dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt(), - original.getExtension( - proto.jspb.test.CloneExtension.extField).getExt()); + original.getExtension(proto.jspb.test.CloneExtension.extField) + .getExt()); }); it('testCopyInto_notSameType', function() { @@ -528,26 +572,32 @@ describe('Message test suite', function() { var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2']]); var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1); - extendable.setExtension(proto.jspb.test.IndirectExtension.simple, - extension2); + extendable.setExtension( + proto.jspb.test.IndirectExtension.simple, extension2); extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy'); - extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList, - ['a', 'b']); + extendable.setExtension( + proto.jspb.test.IndirectExtension.repeatedStrList, ['a', 'b']); var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]); var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2']]); extendable.setExtension( - proto.jspb.test.IndirectExtension.repeatedSimpleList, - [s1, s2]); - assertObjectEquals(extension1, + proto.jspb.test.IndirectExtension.repeatedSimpleList, [s1, s2]); + assertObjectEquals( + extension1, extendable.getExtension(proto.jspb.test.IsExtension.extField)); - assertObjectEquals(extension2, + assertObjectEquals( + extension2, extendable.getExtension(proto.jspb.test.IndirectExtension.simple)); - assertObjectEquals('xyzzy', + assertObjectEquals( + 'xyzzy', extendable.getExtension(proto.jspb.test.IndirectExtension.str)); - assertObjectEquals(['a', 'b'], extendable.getExtension( - proto.jspb.test.IndirectExtension.repeatedStrList)); - assertObjectEquals([s1, s2], extendable.getExtension( - proto.jspb.test.IndirectExtension.repeatedSimpleList)); + assertObjectEquals( + ['a', 'b'], + extendable.getExtension( + proto.jspb.test.IndirectExtension.repeatedStrList)); + assertObjectEquals( + [s1, s2], + extendable.getExtension( + proto.jspb.test.IndirectExtension.repeatedSimpleList)); // Not supported yet, but it should work... extendable.setExtension(proto.jspb.test.IndirectExtension.simple, null); assertNull( @@ -566,29 +616,35 @@ describe('Message test suite', function() { var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); var extension = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]); extendable.setExtension(proto.jspb.test.simple1, extension); - assertObjectEquals(extension, - extendable.getExtension(proto.jspb.test.simple1)); + assertObjectEquals( + extension, extendable.getExtension(proto.jspb.test.simple1)); // From _lib mode. extension = new proto.jspb.test.ExtensionMessage(['s1']); extendable = new proto.jspb.test.TestExtensionsMessage([16]); extendable.setExtension(proto.jspb.test.floatingMsgField, extension); extendable.setExtension(proto.jspb.test.floatingStrField, 's2'); - assertObjectEquals(extension, - extendable.getExtension(proto.jspb.test.floatingMsgField)); - assertObjectEquals('s2', - extendable.getExtension(proto.jspb.test.floatingStrField)); + assertObjectEquals( + extension, extendable.getExtension(proto.jspb.test.floatingMsgField)); + assertObjectEquals( + 's2', extendable.getExtension(proto.jspb.test.floatingStrField)); assertNotUndefined(proto.jspb.exttest.floatingMsgField); assertNotUndefined(proto.jspb.exttest.floatingMsgFieldTwo); assertNotUndefined(proto.jspb.exttest.beta.floatingStrField); }); it('testNestedExtensions', function() { - var extendable = new proto.jspb.exttest.nested.TestNestedExtensionsMessage(); - var extension = new proto.jspb.exttest.nested.TestOuterMessage.NestedExtensionMessage(['s1']); - extendable.setExtension(proto.jspb.exttest.nested.TestOuterMessage.innerExtension, extension); - assertObjectEquals(extension, - extendable.getExtension(proto.jspb.exttest.nested.TestOuterMessage.innerExtension)); + var extendable = + new proto.jspb.exttest.nested.TestNestedExtensionsMessage(); + var extension = + new proto.jspb.exttest.nested.TestOuterMessage.NestedExtensionMessage( + ['s1']); + extendable.setExtension( + proto.jspb.exttest.nested.TestOuterMessage.innerExtension, extension); + assertObjectEquals( + extension, + extendable.getExtension( + proto.jspb.exttest.nested.TestOuterMessage.innerExtension)); }); it('testToObject_extendedObject', function() { @@ -596,60 +652,72 @@ describe('Message test suite', function() { var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2'], true]); var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1); - extendable.setExtension(proto.jspb.test.IndirectExtension.simple, - extension2); + extendable.setExtension( + proto.jspb.test.IndirectExtension.simple, extension2); extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy'); - extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList, - ['a', 'b']); + extendable.setExtension( + proto.jspb.test.IndirectExtension.repeatedStrList, ['a', 'b']); var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2'], true]); var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2'], false]); extendable.setExtension( - proto.jspb.test.IndirectExtension.repeatedSimpleList, - [s1, s2]); - assertObjectEquals({ - str1: 'v1', str2: 'v2', str3: 'v3', - extField: { ext1: 'ext1field' }, - simple: { - aString: 'str', aRepeatedStringList: ['s1', 's2'], aBoolean: true - }, - str: 'xyzzy', - repeatedStrList: ['a', 'b'], - repeatedSimpleList: [ - { aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true}, - { aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false} - ] - }, extendable.toObject()); + proto.jspb.test.IndirectExtension.repeatedSimpleList, [s1, s2]); + assertObjectEquals( + { + str1: 'v1', + str2: 'v2', + str3: 'v3', + extField: {ext1: 'ext1field'}, + simple: { + aString: 'str', + aRepeatedStringList: ['s1', 's2'], + aBoolean: true + }, + str: 'xyzzy', + repeatedStrList: ['a', 'b'], + repeatedSimpleList: [ + {aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true}, + {aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false} + ] + }, + extendable.toObject()); // Now, with instances included. - assertObjectEquals({ - str1: 'v1', str2: 'v2', str3: 'v3', - extField: { - ext1: 'ext1field', - $jspbMessageInstance: - extendable.getExtension(proto.jspb.test.IsExtension.extField) - }, - simple: { - aString: 'str', - aRepeatedStringList: ['s1', 's2'], - aBoolean: true, - $jspbMessageInstance: - extendable.getExtension(proto.jspb.test.IndirectExtension.simple) - }, - str: 'xyzzy', - repeatedStrList: ['a', 'b'], - repeatedSimpleList: [{ - aString: 'foo', - aRepeatedStringList: ['s1', 's2'], - aBoolean: true, - $jspbMessageInstance: s1 - }, { - aString: 'bar', - aRepeatedStringList: ['t1', 't2'], - aBoolean: false, - $jspbMessageInstance: s2 - }], - $jspbMessageInstance: extendable - }, extendable.toObject(true /* opt_includeInstance */)); + assertObjectEquals( + { + str1: 'v1', + str2: 'v2', + str3: 'v3', + extField: { + ext1: 'ext1field', + $jspbMessageInstance: + extendable.getExtension(proto.jspb.test.IsExtension.extField) + }, + simple: { + aString: 'str', + aRepeatedStringList: ['s1', 's2'], + aBoolean: true, + $jspbMessageInstance: extendable.getExtension( + proto.jspb.test.IndirectExtension.simple) + }, + str: 'xyzzy', + repeatedStrList: ['a', 'b'], + repeatedSimpleList: [ + { + aString: 'foo', + aRepeatedStringList: ['s1', 's2'], + aBoolean: true, + $jspbMessageInstance: s1 + }, + { + aString: 'bar', + aRepeatedStringList: ['t1', 't2'], + aBoolean: false, + $jspbMessageInstance: s2 + } + ], + $jspbMessageInstance: extendable + }, + extendable.toObject(true /* opt_includeInstance */)); }); it('testInitialization_emptyArray', function() { @@ -682,7 +750,8 @@ describe('Message test suite', function() { }); it('testToObject_hasExtensionField', function() { - var data = new proto.jspb.test.HasExtensions(['str1', {100: ['ext1'], 102: ''}]); + var data = + new proto.jspb.test.HasExtensions(['str1', {100: ['ext1'], 102: ''}]); var obj = data.toObject(); assertEquals('str1', obj.str1); assertEquals('ext1', obj.extField.ext1); @@ -702,8 +771,7 @@ describe('Message test suite', function() { var extensionMessage = new proto.jspb.test.IsExtension(['is_extension']); data.setExtension(proto.jspb.test.IsExtension.extField, extensionMessage); var obj = data.toObject(); - assertNotNull( - data.getExtension(proto.jspb.test.IsExtension.extField)); + assertNotNull(data.getExtension(proto.jspb.test.IsExtension.extField)); assertEquals('is_extension', obj.extField.ext1); }); @@ -720,16 +788,18 @@ describe('Message test suite', function() { var groups = group.getRepeatedGroupList(); assertEquals('g1', groups[0].getId()); assertObjectEquals([true, false], groups[0].getSomeBoolList()); - assertObjectEquals({id: 'g1', someBoolList: [true, false]}, - groups[0].toObject()); - assertObjectEquals({ - repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}], - requiredGroup: {id: undefined}, - optionalGroup: undefined, - requiredSimple: {aRepeatedStringList: [], aString: undefined}, - optionalSimple: undefined, - id: undefined - }, group.toObject()); + assertObjectEquals( + {id: 'g1', someBoolList: [true, false]}, groups[0].toObject()); + assertObjectEquals( + { + repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}], + requiredGroup: {id: undefined}, + optionalGroup: undefined, + requiredSimple: {aRepeatedStringList: [], aString: undefined}, + optionalSimple: undefined, + id: undefined + }, + group.toObject()); var group1 = new proto.jspb.test.TestGroup1(); group1.setGroup(someGroup); assertEquals(someGroup, group1.getGroup()); @@ -746,299 +816,296 @@ describe('Message test suite', function() { message.setExtension$(11); message.setExtension(proto.jspb.test.TestReservedNamesExtension.foo, 12); assertEquals(11, message.getExtension$()); - assertEquals(12, message.getExtension( - proto.jspb.test.TestReservedNamesExtension.foo)); + assertEquals( + 12, + message.getExtension(proto.jspb.test.TestReservedNamesExtension.foo)); assertObjectEquals({extension: 11, foo: 12}, message.toObject()); }); it('testInitializeMessageWithUnsetOneof', function() { var message = new proto.jspb.test.TestMessageWithOneof([]); assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase. - PARTIAL_ONEOF_NOT_SET, + proto.jspb.test.TestMessageWithOneof.PartialOneofCase + .PARTIAL_ONEOF_NOT_SET, message.getPartialOneofCase()); assertEquals( - proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase. - RECURSIVE_ONEOF_NOT_SET, + proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase + .RECURSIVE_ONEOF_NOT_SET, message.getRecursiveOneofCase()); }); - it('testInitializeMessageWithSingleValueSetInOneof', function() { - var message = new proto.jspb.test.TestMessageWithOneof([,, 'x']); + it('testUnsetsOneofCaseWhenFieldIsCleared', function() { + var message = new proto.jspb.test.TestMessageWithOneof; + assertEquals( + proto.jspb.test.TestMessageWithOneof.PartialOneofCase + .PARTIAL_ONEOF_NOT_SET, + message.getPartialOneofCase()); - assertEquals('x', message.getPone()); - assertEquals('', message.getPthree()); + message.setPone('hi'); assertEquals( proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE, message.getPartialOneofCase()); - }); - - it('testKeepsLastWireValueSetInUnion_multipleValues', function() { - var message = new proto.jspb.test.TestMessageWithOneof([,, 'x',, 'y']); - assertEquals('', message.getPone()); - assertEquals('y', message.getPthree()); + message.clearPone(); assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE, + proto.jspb.test.TestMessageWithOneof.PartialOneofCase + .PARTIAL_ONEOF_NOT_SET, message.getPartialOneofCase()); }); - it('testSettingOneofFieldClearsOthers', function() { - var message = new proto.jspb.test.TestMessageWithOneof; - assertEquals('', message.getPone()); - assertEquals('', message.getPthree()); - assertFalse(message.hasPone()); - assertFalse(message.hasPthree()); + it('testFloatingPointFieldsSupportNan', function() { + var assertNan = function(x) { + assertTrue( + 'Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.', + typeof x === 'number' && isNaN(x)); + }; - message.setPone('hi'); - assertEquals('hi', message.getPone()); - assertEquals('', message.getPthree()); - assertTrue(message.hasPone()); - assertFalse(message.hasPthree()); - - message.setPthree('bye'); - assertEquals('', message.getPone()); - assertEquals('bye', message.getPthree()); - assertFalse(message.hasPone()); - assertTrue(message.hasPthree()); + var message = new proto.jspb.test.FloatingPointFields([ + 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN', 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN' + ]); + assertNan(message.getOptionalFloatField()); + assertNan(message.getRequiredFloatField()); + assertNan(message.getRepeatedFloatFieldList()[0]); + assertNan(message.getRepeatedFloatFieldList()[1]); + assertNan(message.getDefaultFloatField()); + assertNan(message.getOptionalDoubleField()); + assertNan(message.getRequiredDoubleField()); + assertNan(message.getRepeatedDoubleFieldList()[0]); + assertNan(message.getRepeatedDoubleFieldList()[1]); + assertNan(message.getDefaultDoubleField()); }); - it('testSettingOneofFieldDoesNotClearFieldsFromOtherUnions', function() { - var other = new proto.jspb.test.TestMessageWithOneof; - var message = new proto.jspb.test.TestMessageWithOneof; - assertEquals('', message.getPone()); - assertEquals('', message.getPthree()); - assertUndefined(message.getRone()); - assertFalse(message.hasPone()); - assertFalse(message.hasPthree()); + it('testFloatingPointsAreConvertedFromStringInput', function() { + var assertInf = function(x) { + assertTrue( + 'Expected ' + x + ' (' + goog.typeOf(x) + ') to be Infinity.', + x === Infinity); + }; + var message = new proto.jspb.test.FloatingPointFields([ + Infinity, 'Infinity', ['Infinity', Infinity], 'Infinity', 'Infinity', + 'Infinity', ['Infinity', Infinity], 'Infinity' + ]); + assertInf(message.getOptionalFloatField()); + assertInf(message.getRequiredFloatField()); + assertInf(message.getRepeatedFloatFieldList()[0]); + assertInf(message.getRepeatedFloatFieldList()[1]); + assertInf(message.getDefaultFloatField()); + assertInf(message.getOptionalDoubleField()); + assertInf(message.getRequiredDoubleField()); + assertInf(message.getRepeatedDoubleFieldList()[0]); + assertInf(message.getRepeatedDoubleFieldList()[1]); + assertInf(message.getDefaultDoubleField()); + }); - message.setPone('hi'); - message.setRone(other); - assertEquals('hi', message.getPone()); - assertEquals('', message.getPthree()); - assertEquals(other, message.getRone()); - assertTrue(message.hasPone()); - assertFalse(message.hasPthree()); - - message.setPthree('bye'); - assertEquals('', message.getPone()); - assertEquals('bye', message.getPthree()); - assertEquals(other, message.getRone()); - assertFalse(message.hasPone()); - assertTrue(message.hasPthree()); + it('testBooleansAreConvertedFromNumberInput', function() { + var assertBooleanFieldTrue = function(x) { + assertTrue( + 'Expected ' + x + ' (' + goog.typeOf(x) + ') to be True.', + x === true); + }; + var message = new proto.jspb.test.BooleanFields([1, 1, [true, 1]]); + assertBooleanFieldTrue(message.getOptionalBooleanField()); + assertBooleanFieldTrue(message.getRequiredBooleanField()); + assertBooleanFieldTrue(message.getRepeatedBooleanFieldList()[0]); + assertBooleanFieldTrue(message.getRepeatedBooleanFieldList()[1]); + assertBooleanFieldTrue(message.getDefaultBooleanField()); + + var assertBooleanFieldFalse = function(x) { + assertTrue( + 'Expected ' + x + ' (' + goog.typeOf(x) + ') to be False.', + x === false); + }; + message = new proto.jspb.test.BooleanFields([0, 0, [0, 0]]); + assertBooleanFieldFalse(message.getOptionalBooleanField()); + assertBooleanFieldFalse(message.getRequiredBooleanField()); + assertBooleanFieldFalse(message.getRepeatedBooleanFieldList()[0]); + assertBooleanFieldFalse(message.getRepeatedBooleanFieldList()[1]); }); - it('testUnsetsOneofCaseWhenFieldIsCleared', function() { - var message = new proto.jspb.test.TestMessageWithOneof; - assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase. - PARTIAL_ONEOF_NOT_SET, - message.getPartialOneofCase()); + it('testExtensionReverseOrder', function() { + var message2 = + new proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage2; - message.setPone('hi'); - assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE, - message.getPartialOneofCase()); + message2.setExtension( + proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage1.a, 233); + message2.setExtension( + proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage1 + .TestExtensionReverseOrderNestedMessage1.b, + 2333); + message2.setExtension(proto.jspb.exttest.reverse.c, 23333); - message.clearPone(); assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase. - PARTIAL_ONEOF_NOT_SET, - message.getPartialOneofCase()); + 233, + message2.getExtension( + proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage1.a)); + assertEquals( + 2333, + message2.getExtension( + proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage1 + .TestExtensionReverseOrderNestedMessage1.b)); + assertEquals(23333, message2.getExtension(proto.jspb.exttest.reverse.c)); }); - it('testMessageWithDefaultOneofValues', function() { - var message = new proto.jspb.test.TestMessageWithOneof; - assertEquals(1234, message.getAone()); - assertEquals(0, message.getAtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofACase - .DEFAULT_ONEOF_A_NOT_SET, - message.getDefaultOneofACase()); + it('testCircularDepsBaseOnMessageField', function() { + var nestMessage1 = new proto.jspb.circulartest.MessageField1; + var nestMessage2 = new proto.jspb.circulartest.MessageField2; + var message1 = new proto.jspb.circulartest.MessageField1; + var message2 = new proto.jspb.circulartest.MessageField2; - message.setAone(567); - assertEquals(567, message.getAone()); - assertEquals(0, message.getAtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE, - message.getDefaultOneofACase()); + nestMessage1.setA(1); + nestMessage2.setA(2); + message1.setB(nestMessage2); + message2.setB(nestMessage1); - message.setAtwo(890); - assertEquals(1234, message.getAone()); - assertEquals(890, message.getAtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO, - message.getDefaultOneofACase()); - message.clearAtwo(); - assertEquals(1234, message.getAone()); - assertEquals(0, message.getAtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofACase - .DEFAULT_ONEOF_A_NOT_SET, - message.getDefaultOneofACase()); + assertEquals(2, message1.getB().getA()); + assertEquals(1, message2.getB().getA()); }); - it('testMessageWithDefaultOneofValues_defaultNotOnFirstField', function() { - var message = new proto.jspb.test.TestMessageWithOneof; - assertEquals(0, message.getBone()); - assertEquals(1234, message.getBtwo()); - assertFalse(message.hasBone()); - assertFalse(message.hasBtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase - .DEFAULT_ONEOF_B_NOT_SET, - message.getDefaultOneofBCase()); - - message.setBone(2); - assertEquals(2, message.getBone()); - assertEquals(1234, message.getBtwo()); - assertTrue(message.hasBone()); - assertFalse(message.hasBtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE, - message.getDefaultOneofBCase()); - - message.setBtwo(3); - assertEquals(0, message.getBone()); - assertFalse(message.hasBone()); - assertTrue(message.hasBtwo()); - assertEquals(3, message.getBtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO, - message.getDefaultOneofBCase()); - - message.clearBtwo(); - assertEquals(0, message.getBone()); - assertFalse(message.hasBone()); - assertFalse(message.hasBtwo()); - assertEquals(1234, message.getBtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase - .DEFAULT_ONEOF_B_NOT_SET, - message.getDefaultOneofBCase()); + + it('testCircularDepsBaseOnRepeatedMessageField', function() { + var nestMessage1 = new proto.jspb.circulartest.RepeatedMessageField1; + var nestMessage2 = new proto.jspb.circulartest.RepeatedMessageField2; + var message1 = new proto.jspb.circulartest.RepeatedMessageField1; + var message2 = new proto.jspb.circulartest.RepeatedMessageField2; + + nestMessage1.setA(1); + nestMessage2.setA(2); + message1.setB(nestMessage2); + message2.addB(nestMessage1); + + + assertEquals(2, message1.getB().getA()); + assertEquals(1, message2.getBList()[0].getA()); }); - it('testInitializeMessageWithOneofDefaults', function() { - var message = - new proto.jspb.test.TestMessageWithOneof(new Array(9).concat(567)); - assertEquals(567, message.getAone()); - assertEquals(0, message.getAtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE, - message.getDefaultOneofACase()); + it('testCircularDepsBaseOnMapField', function() { + var nestMessage1 = new proto.jspb.circulartest.MapField1; + var nestMessage2 = new proto.jspb.circulartest.MapField2; + var message1 = new proto.jspb.circulartest.MapField1; + var message2 = new proto.jspb.circulartest.MapField2; - message = - new proto.jspb.test.TestMessageWithOneof(new Array(10).concat(890)); - assertEquals(1234, message.getAone()); - assertEquals(890, message.getAtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO, - message.getDefaultOneofACase()); + nestMessage1.setA(1); + nestMessage2.setA(2); + message1.setB(nestMessage2); + message2.getBMap().set(1, nestMessage1); - message = - new proto.jspb.test.TestMessageWithOneof(new Array(9).concat(567, 890)); - assertEquals(1234, message.getAone()); - assertEquals(890, message.getAtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO, - message.getDefaultOneofACase()); + + assertEquals(2, message1.getB().getA()); + assertEquals(1, message2.getBMap().get(1).getA()); }); - it('testInitializeMessageWithOneofDefaults_defaultNotSetOnFirstField', - function() { - var message; - - message = - new proto.jspb.test.TestMessageWithOneof(new Array(11).concat(567)); - assertEquals(567, message.getBone()); - assertEquals(1234, message.getBtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE, - message.getDefaultOneofBCase()); - - message = - new proto.jspb.test.TestMessageWithOneof(new Array(12).concat(890)); - assertEquals(0, message.getBone()); - assertEquals(890, message.getBtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO, - message.getDefaultOneofBCase()); - - message = new proto.jspb.test.TestMessageWithOneof( - new Array(11).concat(567, 890)); - assertEquals(0, message.getBone()); - assertEquals(890, message.getBtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO, - message.getDefaultOneofBCase()); - }); - - it('testOneofContainingAnotherMessage', function() { - var message = new proto.jspb.test.TestMessageWithOneof; - assertEquals( - proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase. - RECURSIVE_ONEOF_NOT_SET, - message.getRecursiveOneofCase()); + it('testCircularDepsBaseOnNestedMessage', function() { + var nestMessage1 = + new proto.jspb.circulartest.NestedMessage1.NestedNestedMessage; + var nestMessage2 = new proto.jspb.circulartest.NestedMessage2; + var message1 = new proto.jspb.circulartest.NestedMessage1; + var message2 = new proto.jspb.circulartest.NestedMessage2; - var other = new proto.jspb.test.TestMessageWithOneof; - message.setRone(other); - assertEquals(other, message.getRone()); - assertEquals('', message.getRtwo()); - assertEquals( - proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.RONE, - message.getRecursiveOneofCase()); + nestMessage1.setA(1); + nestMessage2.setA(2); + message1.setB(nestMessage2); + message2.setB(nestMessage1); + + + assertEquals(2, message1.getB().getA()); + assertEquals(1, message2.getB().getA()); + }); + + it('testCircularDepsBaseOnNestedEnum', function() { + var nestMessage2 = new proto.jspb.circulartest.NestedEnum2; + var message1 = new proto.jspb.circulartest.NestedEnum1; + var message2 = new proto.jspb.circulartest.NestedEnum2; + + nestMessage2.setA(2); + message1.setB(nestMessage2); + message2.setB(proto.jspb.circulartest.NestedEnum1.NestedNestedEnum.VALUE_1); - message.setRtwo('hi'); - assertUndefined(message.getRone()); - assertEquals('hi', message.getRtwo()); + + assertEquals(2, message1.getB().getA()); assertEquals( - proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.RTWO, - message.getRecursiveOneofCase()); + proto.jspb.circulartest.NestedEnum1.NestedNestedEnum.VALUE_1, + message2.getB()); }); - it('testQueryingOneofCaseEnsuresOnlyOneFieldIsSetInUnderlyingArray', - function() { - var message = new proto.jspb.test.TestMessageWithOneof; - message.setPone('x'); - assertEquals('x', message.getPone()); - assertEquals('', message.getPthree()); + it('testCircularDepsBaseOnExtensionContainingType', function() { + var nestMessage2 = new proto.jspb.circulartest.ExtensionContainingType2; + var message1 = new proto.jspb.circulartest.ExtensionContainingType1; + + nestMessage2.setA(2); + message1.setB(nestMessage2); + message1.setExtension( + proto.jspb.circulartest.ExtensionContainingType2.c, 1); + + + assertEquals(2, message1.getB().getA()); assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE, - message.getPartialOneofCase()); + 1, + message1.getExtension( + proto.jspb.circulartest.ExtensionContainingType2.c)); + }); + + it('testCircularDepsBaseOnExtensionField', function() { + var nestMessage2 = new proto.jspb.circulartest.ExtensionField2; + var message1 = new proto.jspb.circulartest.ExtensionField1; + var message3 = new proto.jspb.circulartest.ExtensionField3; + + nestMessage2.setA(2); + message1.setB(nestMessage2); + message3.setExtension(proto.jspb.circulartest.ExtensionField2.c, message1); - var array = message.toArray(); - assertEquals('x', array[2]); - assertUndefined(array[4]); - array[4] = 'y'; assertEquals( - proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE, - message.getPartialOneofCase()); - assertUndefined(array[2]); - assertEquals('y', array[4]); + 2, + message3.getExtension(proto.jspb.circulartest.ExtensionField2.c) + .getB() + .getA()); }); - it('testFloatingPointFieldsSupportNan', function() { - var assertNan = function(x) { - assertTrue('Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.', - goog.isNumber(x) && isNaN(x)); - }; + it('testSameMessageNameOuputs', function() { + var package1Message = new proto.jspb.filenametest.package1.TestMessage; + var package2Message = new proto.jspb.filenametest.package2.TestMessage; - var message = new proto.jspb.test.FloatingPointFields([ - 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN', - 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN' - ]); - assertNan(message.getOptionalFloatField()); - assertNan(message.getRequiredFloatField()); - assertNan(message.getRepeatedFloatFieldList()[0]); - assertNan(message.getRepeatedFloatFieldList()[1]); - assertNan(message.getDefaultFloatField()); - assertNan(message.getOptionalDoubleField()); - assertNan(message.getRequiredDoubleField()); - assertNan(message.getRepeatedDoubleFieldList()[0]); - assertNan(message.getRepeatedDoubleFieldList()[1]); - assertNan(message.getDefaultDoubleField()); + package1Message.setExtension(proto.jspb.filenametest.package1.a, 10); + package1Message.setExtension(proto.jspb.filenametest.package1.b, 11); + package2Message.setA(12); + + assertEquals( + 10, package1Message.getExtension(proto.jspb.filenametest.package1.a)); + assertEquals( + 11, package1Message.getExtension(proto.jspb.filenametest.package1.b)); + assertEquals(12, package2Message.getA()); }); + + it('testMessageWithLargeFieldNumbers', function() { + var message = new proto.jspb.test.MessageWithLargeFieldNumbers; + + message.setAString('string'); + assertEquals('string', message.getAString()); + + message.setAString(''); + assertEquals('', message.getAString()); + + message.setAString('new string'); + assertEquals('new string', message.getAString()); + + message.setABoolean(true); + assertEquals(true, message.getABoolean()); + + message.setABoolean(false); + assertEquals(false, message.getABoolean()); + + message.setABoolean(true); + assertEquals(true, message.getABoolean()); + + message.setAInt(42); + assertEquals(42, message.getAInt()); + + message.setAInt(0); + assertEquals(0, message.getAInt()); + + message.setAInt(42); + assertEquals(42, message.getAInt()); + }); }); diff --git a/js/package.json b/js/package.json index c8b7538501c2e..768b37a4d0142 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "google-protobuf", - "version": "3.4.0", + "version": "3.15.0", "description": "Protocol Buffers for JavaScript", "main": "google-protobuf.js", "files": [ @@ -8,19 +8,19 @@ ], "dependencies": {}, "devDependencies": { - "glob": "~6.0.4", - "google-closure-compiler": "~20160619.0.0", - "google-closure-library": "~20160125.0.0", - "gulp": "~3.9.0", - "jasmine": "~2.4.1" + "glob": "~7.1.4", + "google-closure-compiler": "~20190819.0.0", + "google-closure-library": "~20190819.0.0", + "gulp": "~4.0.2", + "jasmine": "~3.4.0" }, "scripts": { "test": "node ./node_modules/gulp/bin/gulp.js test" }, "repository": { "type": "git", - "url": "https://github.com/google/protobuf/tree/master/js" + "url": "https://github.com/protocolbuffers/protobuf/tree/master/js" }, "author": "Google Protocol Buffers Team", - "license" : "BSD-3-Clause" + "license": "BSD-3-Clause" } diff --git a/js/proto3_test.js b/js/proto3_test.js index 81d6de2f5eeec..8de157524bc6d 100644 --- a/js/proto3_test.js +++ b/js/proto3_test.js @@ -30,20 +30,18 @@ goog.require('goog.crypt.base64'); goog.require('goog.testing.asserts'); - // CommonJS-LoadFromFile: testbinary_pb proto.jspb.test goog.require('proto.jspb.test.ForeignMessage'); - // CommonJS-LoadFromFile: proto3_test_pb proto.jspb.test goog.require('proto.jspb.test.Proto3Enum'); goog.require('proto.jspb.test.TestProto3'); - +// CommonJS-LoadFromFile: google/protobuf/any_pb proto.google.protobuf +goog.require('proto.google.protobuf.Any'); // CommonJS-LoadFromFile: google/protobuf/timestamp_pb proto.google.protobuf goog.require('proto.google.protobuf.Timestamp'); - // CommonJS-LoadFromFile: google/protobuf/struct_pb proto.google.protobuf goog.require('proto.google.protobuf.Struct'); - +goog.require('jspb.Message'); var BYTES = new Uint8Array([1, 2, 8, 9]); var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES); @@ -56,7 +54,7 @@ var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES); * @return {boolean} */ function bytesCompare(arr, expected) { - if (goog.isString(arr)) { + if (typeof arr === 'string') { arr = goog.crypt.base64.decodeStringToUint8Array(arr); } if (arr.length != expected.length) { @@ -72,12 +70,94 @@ function bytesCompare(arr, expected) { describe('proto3Test', function() { + /** + * Test default values don't affect equality test. + */ + it('testEqualsProto3', function() { + var msg1 = new proto.jspb.test.TestProto3(); + var msg2 = new proto.jspb.test.TestProto3(); + msg2.setSingularString(''); + + assertTrue(jspb.Message.equals(msg1, msg2)); + }); + + + /** + * Test setting when a field has default semantics. + */ + it('testSetProto3ToValueAndBackToDefault', function() { + var msg = new proto.jspb.test.TestProto3(); + + // Setting should work normally. + msg.setSingularString('optionalString'); + assertEquals(msg.getSingularString(), 'optionalString'); + + // Clearing should work too ... + msg.setSingularString(''); + assertEquals(msg.getSingularString(), ''); + + // ... and shouldn't affect the equality with a brand new message. + assertTrue(jspb.Message.equals(msg, new proto.jspb.test.TestProto3())); + }); + /** * Test defaults for proto3 message fields. */ it('testProto3FieldDefaults', function() { var msg = new proto.jspb.test.TestProto3(); + assertEquals(msg.getSingularInt32(), 0); + assertEquals(msg.getSingularInt64(), 0); + assertEquals(msg.getSingularUint32(), 0); + assertEquals(msg.getSingularUint64(), 0); + assertEquals(msg.getSingularSint32(), 0); + assertEquals(msg.getSingularSint64(), 0); + assertEquals(msg.getSingularFixed32(), 0); + assertEquals(msg.getSingularFixed64(), 0); + assertEquals(msg.getSingularSfixed32(), 0); + assertEquals(msg.getSingularSfixed64(), 0); + assertEquals(msg.getSingularFloat(), 0); + assertEquals(msg.getSingularDouble(), 0); + assertEquals(msg.getSingularString(), ''); + + // TODO(b/26173701): when we change bytes fields default getter to return + // Uint8Array, we'll want to switch this assertion to match the u8 case. + assertEquals(typeof msg.getSingularBytes(), 'string'); + assertEquals(msg.getSingularBytes_asU8() instanceof Uint8Array, true); + assertEquals(typeof msg.getSingularBytes_asB64(), 'string'); + assertEquals(msg.getSingularBytes().length, 0); + assertEquals(msg.getSingularBytes_asU8().length, 0); + assertEquals(msg.getSingularBytes_asB64(), ''); + + assertEquals( + msg.getSingularForeignEnum(), proto.jspb.test.Proto3Enum.PROTO3_FOO); + assertEquals(msg.getSingularForeignMessage(), undefined); + assertEquals(msg.getSingularForeignMessage(), undefined); + + assertEquals(msg.getRepeatedInt32List().length, 0); + assertEquals(msg.getRepeatedInt64List().length, 0); + assertEquals(msg.getRepeatedUint32List().length, 0); + assertEquals(msg.getRepeatedUint64List().length, 0); + assertEquals(msg.getRepeatedSint32List().length, 0); + assertEquals(msg.getRepeatedSint64List().length, 0); + assertEquals(msg.getRepeatedFixed32List().length, 0); + assertEquals(msg.getRepeatedFixed64List().length, 0); + assertEquals(msg.getRepeatedSfixed32List().length, 0); + assertEquals(msg.getRepeatedSfixed64List().length, 0); + assertEquals(msg.getRepeatedFloatList().length, 0); + assertEquals(msg.getRepeatedDoubleList().length, 0); + assertEquals(msg.getRepeatedStringList().length, 0); + assertEquals(msg.getRepeatedBytesList().length, 0); + assertEquals(msg.getRepeatedForeignEnumList().length, 0); + assertEquals(msg.getRepeatedForeignMessageList().length, 0); + }); + + /** + * Test presence for proto3 optional fields. + */ + it('testProto3Optional', function() { + var msg = new proto.jspb.test.TestProto3(); + assertEquals(msg.getOptionalInt32(), 0); assertEquals(msg.getOptionalInt64(), 0); assertEquals(msg.getOptionalUint32(), 0); @@ -101,56 +181,70 @@ describe('proto3Test', function() { assertEquals(msg.getOptionalBytes_asU8().length, 0); assertEquals(msg.getOptionalBytes_asB64(), ''); - assertEquals(msg.getOptionalForeignEnum(), - proto.jspb.test.Proto3Enum.PROTO3_FOO); + assertEquals( + msg.getOptionalForeignEnum(), proto.jspb.test.Proto3Enum.PROTO3_FOO); assertEquals(msg.getOptionalForeignMessage(), undefined); assertEquals(msg.getOptionalForeignMessage(), undefined); - assertEquals(msg.getRepeatedInt32List().length, 0); - assertEquals(msg.getRepeatedInt64List().length, 0); - assertEquals(msg.getRepeatedUint32List().length, 0); - assertEquals(msg.getRepeatedUint64List().length, 0); - assertEquals(msg.getRepeatedSint32List().length, 0); - assertEquals(msg.getRepeatedSint64List().length, 0); - assertEquals(msg.getRepeatedFixed32List().length, 0); - assertEquals(msg.getRepeatedFixed64List().length, 0); - assertEquals(msg.getRepeatedSfixed32List().length, 0); - assertEquals(msg.getRepeatedSfixed64List().length, 0); - assertEquals(msg.getRepeatedFloatList().length, 0); - assertEquals(msg.getRepeatedDoubleList().length, 0); - assertEquals(msg.getRepeatedStringList().length, 0); - assertEquals(msg.getRepeatedBytesList().length, 0); - assertEquals(msg.getRepeatedForeignEnumList().length, 0); - assertEquals(msg.getRepeatedForeignMessageList().length, 0); + // Serializing an empty proto yields the empty string. + assertEquals(msg.serializeBinary().length, 0); - }); + // Values start as unset, but can be explicitly set even to default values + // like 0. + assertFalse(msg.hasOptionalInt32()); + msg.setOptionalInt32(0); + assertTrue(msg.hasOptionalInt32()); + + assertFalse(msg.hasOptionalInt64()); + msg.setOptionalInt64(0); + assertTrue(msg.hasOptionalInt64()); + + assertFalse(msg.hasOptionalString()); + msg.setOptionalString(''); + assertTrue(msg.hasOptionalString()); + // Now the proto will have a non-zero size, even though its values are 0. + var serialized = msg.serializeBinary(); + assertNotEquals(serialized.length, 0); + + var msg2 = proto.jspb.test.TestProto3.deserializeBinary(serialized); + assertTrue(msg2.hasOptionalInt32()); + assertTrue(msg2.hasOptionalInt64()); + assertTrue(msg2.hasOptionalString()); + + // We can clear fields to go back to empty. + msg2.clearOptionalInt32(); + assertFalse(msg2.hasOptionalInt32()); + + msg2.clearOptionalString(); + assertFalse(msg2.hasOptionalString()); + }); /** - * Test that all fields can be set and read via a serialization roundtrip. + * Test that all fields can be set ,and read via a serialization roundtrip. */ it('testProto3FieldSetGet', function() { var msg = new proto.jspb.test.TestProto3(); - msg.setOptionalInt32(-42); - msg.setOptionalInt64(-0x7fffffff00000000); - msg.setOptionalUint32(0x80000000); - msg.setOptionalUint64(0xf000000000000000); - msg.setOptionalSint32(-100); - msg.setOptionalSint64(-0x8000000000000000); - msg.setOptionalFixed32(1234); - msg.setOptionalFixed64(0x1234567800000000); - msg.setOptionalSfixed32(-1234); - msg.setOptionalSfixed64(-0x1234567800000000); - msg.setOptionalFloat(1.5); - msg.setOptionalDouble(-1.5); - msg.setOptionalBool(true); - msg.setOptionalString('hello world'); - msg.setOptionalBytes(BYTES); + msg.setSingularInt32(-42); + msg.setSingularInt64(-0x7fffffff00000000); + msg.setSingularUint32(0x80000000); + msg.setSingularUint64(0xf000000000000000); + msg.setSingularSint32(-100); + msg.setSingularSint64(-0x8000000000000000); + msg.setSingularFixed32(1234); + msg.setSingularFixed64(0x1234567800000000); + msg.setSingularSfixed32(-1234); + msg.setSingularSfixed64(-0x1234567800000000); + msg.setSingularFloat(1.5); + msg.setSingularDouble(-1.5); + msg.setSingularBool(true); + msg.setSingularString('hello world'); + msg.setSingularBytes(BYTES); var submsg = new proto.jspb.test.ForeignMessage(); submsg.setC(16); - msg.setOptionalForeignMessage(submsg); - msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR); + msg.setSingularForeignMessage(submsg); + msg.setSingularForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR); msg.setRepeatedInt32List([-42]); msg.setRepeatedInt64List([-0x7fffffff00000000]); @@ -177,24 +271,24 @@ describe('proto3Test', function() { var serialized = msg.serializeBinary(); msg = proto.jspb.test.TestProto3.deserializeBinary(serialized); - assertEquals(msg.getOptionalInt32(), -42); - assertEquals(msg.getOptionalInt64(), -0x7fffffff00000000); - assertEquals(msg.getOptionalUint32(), 0x80000000); - assertEquals(msg.getOptionalUint64(), 0xf000000000000000); - assertEquals(msg.getOptionalSint32(), -100); - assertEquals(msg.getOptionalSint64(), -0x8000000000000000); - assertEquals(msg.getOptionalFixed32(), 1234); - assertEquals(msg.getOptionalFixed64(), 0x1234567800000000); - assertEquals(msg.getOptionalSfixed32(), -1234); - assertEquals(msg.getOptionalSfixed64(), -0x1234567800000000); - assertEquals(msg.getOptionalFloat(), 1.5); - assertEquals(msg.getOptionalDouble(), -1.5); - assertEquals(msg.getOptionalBool(), true); - assertEquals(msg.getOptionalString(), 'hello world'); - assertEquals(true, bytesCompare(msg.getOptionalBytes(), BYTES)); - assertEquals(msg.getOptionalForeignMessage().getC(), 16); - assertEquals(msg.getOptionalForeignEnum(), - proto.jspb.test.Proto3Enum.PROTO3_BAR); + assertEquals(msg.getSingularInt32(), -42); + assertEquals(msg.getSingularInt64(), -0x7fffffff00000000); + assertEquals(msg.getSingularUint32(), 0x80000000); + assertEquals(msg.getSingularUint64(), 0xf000000000000000); + assertEquals(msg.getSingularSint32(), -100); + assertEquals(msg.getSingularSint64(), -0x8000000000000000); + assertEquals(msg.getSingularFixed32(), 1234); + assertEquals(msg.getSingularFixed64(), 0x1234567800000000); + assertEquals(msg.getSingularSfixed32(), -1234); + assertEquals(msg.getSingularSfixed64(), -0x1234567800000000); + assertEquals(msg.getSingularFloat(), 1.5); + assertEquals(msg.getSingularDouble(), -1.5); + assertEquals(msg.getSingularBool(), true); + assertEquals(msg.getSingularString(), 'hello world'); + assertEquals(true, bytesCompare(msg.getSingularBytes(), BYTES)); + assertEquals(msg.getSingularForeignMessage().getC(), 16); + assertEquals( + msg.getSingularForeignEnum(), proto.jspb.test.Proto3Enum.PROTO3_BAR); assertElementsEquals(msg.getRepeatedInt32List(), [-42]); assertElementsEquals(msg.getRepeatedInt64List(), [-0x7fffffff00000000]); @@ -214,7 +308,8 @@ describe('proto3Test', function() { assertEquals(true, bytesCompare(msg.getRepeatedBytesList()[0], BYTES)); assertEquals(msg.getRepeatedForeignMessageList().length, 1); assertEquals(msg.getRepeatedForeignMessageList()[0].getC(), 1000); - assertElementsEquals(msg.getRepeatedForeignEnumList(), + assertElementsEquals( + msg.getRepeatedForeignEnumList(), [proto.jspb.test.Proto3Enum.PROTO3_BAR]); assertEquals(msg.getOneofString(), 'asdf'); @@ -225,52 +320,66 @@ describe('proto3Test', function() { * Test that oneofs continue to have a notion of field presence. */ it('testOneofs', function() { + // Default instance. var msg = new proto.jspb.test.TestProto3(); - assertEquals(msg.getOneofUint32(), 0); assertEquals(msg.getOneofForeignMessage(), undefined); assertEquals(msg.getOneofString(), ''); assertEquals(msg.getOneofBytes(), ''); + assertFalse(msg.hasOneofUint32()); + assertFalse(msg.hasOneofForeignMessage()); assertFalse(msg.hasOneofString()); assertFalse(msg.hasOneofBytes()); + // Integer field. msg.setOneofUint32(42); assertEquals(msg.getOneofUint32(), 42); assertEquals(msg.getOneofForeignMessage(), undefined); assertEquals(msg.getOneofString(), ''); assertEquals(msg.getOneofBytes(), ''); + assertTrue(msg.hasOneofUint32()); + assertFalse(msg.hasOneofForeignMessage()); assertFalse(msg.hasOneofString()); assertFalse(msg.hasOneofBytes()); - + // Sub-message field. var submsg = new proto.jspb.test.ForeignMessage(); msg.setOneofForeignMessage(submsg); assertEquals(msg.getOneofUint32(), 0); assertEquals(msg.getOneofForeignMessage(), submsg); assertEquals(msg.getOneofString(), ''); assertEquals(msg.getOneofBytes(), ''); + assertFalse(msg.hasOneofUint32()); + assertTrue(msg.hasOneofForeignMessage()); assertFalse(msg.hasOneofString()); assertFalse(msg.hasOneofBytes()); + // String field. msg.setOneofString('hello'); assertEquals(msg.getOneofUint32(), 0); assertEquals(msg.getOneofForeignMessage(), undefined); assertEquals(msg.getOneofString(), 'hello'); assertEquals(msg.getOneofBytes(), ''); + assertFalse(msg.hasOneofUint32()); + assertFalse(msg.hasOneofForeignMessage()); assertTrue(msg.hasOneofString()); assertFalse(msg.hasOneofBytes()); + // Bytes field. msg.setOneofBytes(goog.crypt.base64.encodeString('\u00FF\u00FF')); assertEquals(msg.getOneofUint32(), 0); assertEquals(msg.getOneofForeignMessage(), undefined); assertEquals(msg.getOneofString(), ''); - assertEquals(msg.getOneofBytes_asB64(), + assertEquals( + msg.getOneofBytes_asB64(), goog.crypt.base64.encodeString('\u00FF\u00FF')); + assertFalse(msg.hasOneofUint32()); + assertFalse(msg.hasOneofForeignMessage()); assertFalse(msg.hasOneofString()); assertTrue(msg.hasOneofBytes()); }); @@ -285,20 +394,20 @@ describe('proto3Test', function() { // Set each primitive to a non-default value, then back to its default, to // ensure that the serialization is actually checking the value and not just // whether it has ever been set. - msg.setOptionalInt32(42); - msg.setOptionalInt32(0); - msg.setOptionalDouble(3.14); - msg.setOptionalDouble(0.0); - msg.setOptionalBool(true); - msg.setOptionalBool(false); - msg.setOptionalString('hello world'); - msg.setOptionalString(''); - msg.setOptionalBytes(goog.crypt.base64.encodeString('\u00FF\u00FF')); - msg.setOptionalBytes(''); - msg.setOptionalForeignMessage(new proto.jspb.test.ForeignMessage()); - msg.setOptionalForeignMessage(null); - msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR); - msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_FOO); + msg.setSingularInt32(42); + msg.setSingularInt32(0); + msg.setSingularDouble(3.14); + msg.setSingularDouble(0.0); + msg.setSingularBool(true); + msg.setSingularBool(false); + msg.setSingularString('hello world'); + msg.setSingularString(''); + msg.setSingularBytes(goog.crypt.base64.encodeString('\u00FF\u00FF')); + msg.setSingularBytes(''); + msg.setSingularForeignMessage(new proto.jspb.test.ForeignMessage()); + msg.setSingularForeignMessage(null); + msg.setSingularForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR); + msg.setSingularForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_FOO); msg.setOneofUint32(32); msg.clearOneofUint32(); @@ -313,24 +422,23 @@ describe('proto3Test', function() { it('testBytesFieldsInterop', function() { var msg = new proto.jspb.test.TestProto3(); // Set as a base64 string and check all the getters work. - msg.setOptionalBytes(BYTES_B64); - assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES)); - assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES)); - assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES)); + msg.setSingularBytes(BYTES_B64); + assertTrue(bytesCompare(msg.getSingularBytes_asU8(), BYTES)); + assertTrue(bytesCompare(msg.getSingularBytes_asB64(), BYTES)); + assertTrue(bytesCompare(msg.getSingularBytes(), BYTES)); // Test binary serialize round trip doesn't break it. msg = proto.jspb.test.TestProto3.deserializeBinary(msg.serializeBinary()); - assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES)); - assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES)); - assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES)); + assertTrue(bytesCompare(msg.getSingularBytes_asU8(), BYTES)); + assertTrue(bytesCompare(msg.getSingularBytes_asB64(), BYTES)); + assertTrue(bytesCompare(msg.getSingularBytes(), BYTES)); msg = new proto.jspb.test.TestProto3(); // Set as a Uint8Array and check all the getters work. - msg.setOptionalBytes(BYTES); - assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES)); - assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES)); - assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES)); - + msg.setSingularBytes(BYTES); + assertTrue(bytesCompare(msg.getSingularBytes_asU8(), BYTES)); + assertTrue(bytesCompare(msg.getSingularBytes_asB64(), BYTES)); + assertTrue(bytesCompare(msg.getSingularBytes(), BYTES)); }); it('testTimestampWellKnownType', function() { @@ -340,28 +448,31 @@ describe('proto3Test', function() { assertEquals(789000000, msg.getNanos()); var date = msg.toDate(); assertEquals(123456789, date.getTime()); + var anotherMsg = proto.google.protobuf.Timestamp.fromDate(date); + assertEquals(msg.getSeconds(), anotherMsg.getSeconds()); + assertEquals(msg.getNanos(), anotherMsg.getNanos()); }); it('testStructWellKnownType', function() { var jsObj = { - abc: "def", + abc: 'def', number: 12345.678, nullKey: null, boolKey: true, - listKey: [1, null, true, false, "abc"], - structKey: {foo: "bar", somenum: 123}, - complicatedKey: [{xyz: {abc: [3, 4, null, false]}}, "zzz"] + listKey: [1, null, true, false, 'abc'], + structKey: {foo: 'bar', somenum: 123}, + complicatedKey: [{xyz: {abc: [3, 4, null, false]}}, 'zzz'] }; var struct = proto.google.protobuf.Struct.fromJavaScript(jsObj); var jsObj2 = struct.toJavaScript(); - assertEquals("def", jsObj2.abc); + assertEquals('def', jsObj2.abc); assertEquals(12345.678, jsObj2.number); assertEquals(null, jsObj2.nullKey); assertEquals(true, jsObj2.boolKey); - assertEquals("abc", jsObj2.listKey[4]); - assertEquals("bar", jsObj2.structKey.foo); + assertEquals('abc', jsObj2.listKey[4]); + assertEquals('bar', jsObj2.structKey.foo); assertEquals(4, jsObj2.complicatedKey[0].xyz.abc[1]); }); }); diff --git a/js/proto3_test.proto b/js/proto3_test.proto index 0d073ea03ed19..14f104ef56d36 100644 --- a/js/proto3_test.proto +++ b/js/proto3_test.proto @@ -30,49 +30,67 @@ syntax = "proto3"; -import "testbinary.proto"; - package jspb.test; +import "testbinary.proto"; + message TestProto3 { - 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; + int32 singular_int32 = 1; + int64 singular_int64 = 2; + uint32 singular_uint32 = 3; + uint64 singular_uint64 = 4; + sint32 singular_sint32 = 5; + sint64 singular_sint64 = 6; + fixed32 singular_fixed32 = 7; + fixed64 singular_fixed64 = 8; + sfixed32 singular_sfixed32 = 9; + sfixed64 singular_sfixed64 = 10; + float singular_float = 11; + double singular_double = 12; + bool singular_bool = 13; + string singular_string = 14; + bytes singular_bytes = 15; - ForeignMessage optional_foreign_message = 19; - Proto3Enum optional_foreign_enum = 22; + ForeignMessage singular_foreign_message = 19; + Proto3Enum singular_foreign_enum = 22; - repeated int32 repeated_int32 = 31; - repeated int64 repeated_int64 = 32; - repeated uint32 repeated_uint32 = 33; - repeated uint64 repeated_uint64 = 34; - repeated sint32 repeated_sint32 = 35; - repeated sint64 repeated_sint64 = 36; - repeated fixed32 repeated_fixed32 = 37; - repeated fixed64 repeated_fixed64 = 38; + optional int32 optional_int32 = 121; + optional int64 optional_int64 = 122; + optional uint32 optional_uint32 = 123; + optional uint64 optional_uint64 = 124; + optional sint32 optional_sint32 = 125; + optional sint64 optional_sint64 = 126; + optional fixed32 optional_fixed32 = 127; + optional fixed64 optional_fixed64 = 128; + optional sfixed32 optional_sfixed32 = 129; + optional sfixed64 optional_sfixed64 = 130; + optional float optional_float = 131; + optional double optional_double = 132; + optional bool optional_bool = 133; + optional string optional_string = 134; + optional bytes optional_bytes = 135; + + optional ForeignMessage optional_foreign_message = 136; + optional Proto3Enum optional_foreign_enum = 137; + + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; repeated sfixed32 repeated_sfixed32 = 39; repeated sfixed64 repeated_sfixed64 = 40; - repeated float repeated_float = 41; - repeated double repeated_double = 42; - repeated bool repeated_bool = 43; - repeated string repeated_string = 44; - repeated bytes repeated_bytes = 45; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; repeated ForeignMessage repeated_foreign_message = 49; - repeated Proto3Enum repeated_foreign_enum = 52; - + repeated Proto3Enum repeated_foreign_enum = 52; oneof oneof_field { uint32 oneof_uint32 = 111; diff --git a/js/test.proto b/js/test.proto index 7c881c0dfdfe0..7c0578a4f3129 100644 --- a/js/test.proto +++ b/js/test.proto @@ -28,6 +28,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// LINT: LEGACY_NAMES // Author: mwr@google.com (Mark Rawling) syntax = "proto2"; @@ -39,8 +40,7 @@ import "google/protobuf/descriptor.proto"; package jspb.test; -message Empty { -} +message Empty {} enum OuterEnum { FOO = 1; @@ -94,10 +94,11 @@ message Complex { required int32 an_int = 2; } required string a_string = 1; - required bool an_out_of_order_bool = 9; + optional bool an_out_of_order_bool = 9; optional Nested a_nested_message = 4; repeated Nested a_repeated_message = 5; repeated string a_repeated_string = 7; + optional double a_floating_point_field = 10; } message OuterMessage { @@ -107,6 +108,13 @@ message OuterMessage { } } +message MineField { + // document.cookie is a banned property in a couple of conformance check + // configs at Google. Verify that having a field called cookie doesn't confuse + // the compiler and break the build. + optional string cookie = 1; +} + message IsExtension { extend HasExtensions { optional IsExtension ext_field = 100; @@ -137,12 +145,13 @@ message DefaultValues { E1 = 13; E2 = 77; } - optional string string_field = 1 [default="default<>\'\"abc"]; - optional bool bool_field = 2 [default=true]; - optional int64 int_field = 3 [default=11]; - optional Enum enum_field = 4 [default=E1]; - optional string empty_field = 6 [default=""]; - optional bytes bytes_field = 8 [default="moo"]; // Base64 encoding is "bW9v" + optional string string_field = 1 [default = "default<>\'\"abc"]; + optional bool bool_field = 2 [default = true]; + optional int64 int_field = 3 [default = 11]; + optional Enum enum_field = 4 [default = E1]; + optional string empty_field = 6 [default = ""]; + optional bytes bytes_field = 8 + [default = "moo"]; // Base64 encoding is "bW9v" } message FloatingPointFields { @@ -156,6 +165,13 @@ message FloatingPointFields { optional double default_double_field = 8 [default = 2.0]; } +message BooleanFields { + optional bool optional_boolean_field = 1; + required bool required_boolean_field = 2; + repeated bool repeated_boolean_field = 3; + optional bool default_boolean_field = 4 [default = true]; +} + message TestClone { optional string str = 1; optional Simple1 simple1 = 3; @@ -165,6 +181,13 @@ message TestClone { extensions 10 to max; } +message TestCloneExtension { + extend TestClone { + optional TestCloneExtension low_ext = 11; + } + optional int32 f = 1; +} + message CloneExtension { extend TestClone { optional CloneExtension ext_field = 100; @@ -234,16 +257,26 @@ message TestEndsWithBytes { optional bytes data = 2; } +// This message is for testing extension handling doesn't affect fields before +// pivot. Don't add new field to this message. See b/117298778 for more detail. +message TestLastFieldBeforePivot { + optional int32 last_field_before_pivot = 1; + extensions 100 to max; +} + +extend TestLastFieldBeforePivot { + optional int32 extend_test_last_field_before_pivot_field = 101; +} + message Int64Types { - optional int64 int64_normal = 1 [jstype=JS_NORMAL]; - optional sint64 int64_string = 2 [jstype=JS_STRING]; - optional uint64 int64_number = 3 [jstype=JS_NUMBER]; + optional int64 int64_normal = 1 [jstype = JS_NORMAL]; + optional sint64 int64_string = 2 [jstype = JS_STRING]; + optional uint64 int64_number = 3 [jstype = JS_NUMBER]; } message TestMapFieldsNoBinary { - map map_string_string = 1; map map_string_int32 = 2; map map_string_int64 = 3; @@ -267,7 +300,6 @@ enum MapValueEnumNoBinary { } message MapValueMessageNoBinary { - optional int32 foo = 1; } @@ -279,3 +311,12 @@ message Deeply { } } + + +enum TestAllowAliasEnum { + option allow_alias = true; + + TEST_ALLOW_ALIAS_DEFAULT = 0; + VALUE1 = 1; + value1 = 1; +} diff --git a/js/test10.proto b/js/test10.proto new file mode 100644 index 0000000000000..9fa5256c54669 --- /dev/null +++ b/js/test10.proto @@ -0,0 +1,39 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package jspb.exttest.strict.ten; + +import "test9.proto"; + +message Simple10 { + jspb.exttest.strict.nine.Simple9 a = 1; +} diff --git a/js/test11.proto b/js/test11.proto new file mode 100644 index 0000000000000..ae65a46a7f57e --- /dev/null +++ b/js/test11.proto @@ -0,0 +1,52 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package jspb.exttest.reverse; + +message TestExtensionReverseOrderMessage1 { + extend TestExtensionReverseOrderMessage2 { + optional int32 a = 1; + } + message TestExtensionReverseOrderNestedMessage1 { + extend TestExtensionReverseOrderMessage2 { + optional int32 b = 2; + } + } +} + +extend TestExtensionReverseOrderMessage2 { + optional int32 c = 3; +} + +message TestExtensionReverseOrderMessage2 { + extensions 1 to 100; +} diff --git a/js/test12.proto b/js/test12.proto new file mode 100644 index 0000000000000..4ece1d0632f1f --- /dev/null +++ b/js/test12.proto @@ -0,0 +1,119 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + + +package jspb.circulartest; + +message MessageField1 { + optional int32 a = 1; + optional MessageField2 b = 2; +} + +message MessageField2 { + optional int32 a = 1; + optional MessageField1 b = 2; +} + + +message RepeatedMessageField1 { + optional int32 a = 1; + optional RepeatedMessageField2 b = 2; +} + +message RepeatedMessageField2 { + optional int32 a = 1; + repeated RepeatedMessageField1 b = 2; +} + +message MapField1 { + optional int32 a = 1; + optional MapField2 b = 2; +} + +message MapField2 { + optional int32 a = 1; + map b = 2; +} + +message NestedMessage1 { + optional NestedMessage2 b = 2; + message NestedNestedMessage { + optional int32 a = 1; + } +} + +message NestedMessage2 { + optional int32 a = 1; + optional NestedMessage1.NestedNestedMessage b = 2; +} + +message NestedEnum1 { + optional NestedEnum2 b = 2; + enum NestedNestedEnum { + UNDEFINED = 0; + VALUE_1 = 1; + } +} + +message NestedEnum2 { + optional int32 a = 1; + optional NestedEnum1.NestedNestedEnum b = 2; +} + +message ExtensionContainingType1 { + optional int32 a = 1; + optional ExtensionContainingType2 b = 2; + extensions 99 to 100; +} + +message ExtensionContainingType2 { + optional int32 a = 1; + extend ExtensionContainingType1 { + optional int32 c = 99; + } +} + +message ExtensionField1 { + optional int32 a = 1; + optional ExtensionField2 b = 2; +} + +message ExtensionField2 { + optional int32 a = 1; + extend ExtensionField3 { + optional ExtensionField1 c = 99; + } +} + +message ExtensionField3 { + extensions 99 to 100; +} diff --git a/js/test13.proto b/js/test13.proto new file mode 100644 index 0000000000000..b9895d87ae4d0 --- /dev/null +++ b/js/test13.proto @@ -0,0 +1,70 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package jspb.filenametest.package1; + +message TestMessage { + extensions 1 to 100; +} + +extend TestMessage { + optional int32 a = 1; +} + +enum TestEnum { + VALUE_0 = 0; + VALUE_1 = 1; +} + +message TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName1 { + optional TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName2 + a = 1; + optional int32 b = 2; +} + +message TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName2 { + optional TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName3 + a = 1; + optional int32 b = 2; +} + +message TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName3 { + optional TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName4 + a = 1; + optional int32 b = 2; +} + +message TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName4 { + optional TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName1 + a = 1; + optional int32 b = 2; +} diff --git a/js/test14.proto b/js/test14.proto new file mode 100644 index 0000000000000..2447eb14036f9 --- /dev/null +++ b/js/test14.proto @@ -0,0 +1,43 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package jspb.filenametest.package2; + +message TestMessage { + optional int32 a = 1; +} + +enum TestEnum { + VALUE_0 = 0; + VALUE_1 = 1; + VALUE_2 = 2; +} diff --git a/js/test15.proto b/js/test15.proto new file mode 100644 index 0000000000000..b481116519c92 --- /dev/null +++ b/js/test15.proto @@ -0,0 +1,39 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package jspb.filenametest.package1; + +import "test13.proto"; + +extend TestMessage { + optional int32 b = 2; +} diff --git a/js/test2.proto b/js/test2.proto index b67f93fa9ece8..e9457e7c71d3f 100644 --- a/js/test2.proto +++ b/js/test2.proto @@ -30,13 +30,13 @@ syntax = "proto2"; -option java_package = "com.google.apps.jspb.proto"; -option java_multiple_files = true; - package jspb.test; import "test.proto"; +option java_package = "com.google.apps.jspb.proto"; +option java_multiple_files = true; + message TestExtensionsMessage { optional int32 intfield = 1; extensions 100 to max; diff --git a/js/test3.proto b/js/test3.proto index 940a552ed56f0..3fa037dfbacb3 100644 --- a/js/test3.proto +++ b/js/test3.proto @@ -30,11 +30,11 @@ syntax = "proto2"; +package jspb.exttest; + option java_package = "com.google.apps.jspb.proto"; option java_multiple_files = true; -package jspb.exttest; - message TestExtensionsMessage { optional int32 intfield = 1; extensions 100 to max; diff --git a/js/test4.proto b/js/test4.proto index cf2451e9cbe48..c3c8342411447 100644 --- a/js/test4.proto +++ b/js/test4.proto @@ -30,13 +30,13 @@ syntax = "proto2"; -option java_package = "com.google.apps.jspb.proto"; -option java_multiple_files = true; - package jspb.exttest; import "test3.proto"; +option java_package = "com.google.apps.jspb.proto"; +option java_multiple_files = true; + extend TestExtensionsMessage { optional ExtensionMessage floating_msg_field_two = 103; } diff --git a/js/test5.proto b/js/test5.proto index 34979517e551c..db297213a40c7 100644 --- a/js/test5.proto +++ b/js/test5.proto @@ -30,11 +30,11 @@ syntax = "proto2"; +package jspb.exttest.beta; + option java_package = "com.google.apps.jspb.proto"; option java_multiple_files = true; -package jspb.exttest.beta; - message TestBetaExtensionsMessage { extensions 100 to max; } diff --git a/js/test8.proto b/js/test8.proto index 2ae80dab67336..7dbb6eff1483b 100644 --- a/js/test8.proto +++ b/js/test8.proto @@ -30,11 +30,11 @@ syntax = "proto2"; +package jspb.exttest.nested; + option java_package = "com.google.apps.jspb.proto"; option java_multiple_files = true; -package jspb.exttest.nested; - message TestNestedExtensionsMessage { optional int32 intfield = 1; extensions 100 to max; diff --git a/js/test9.proto b/js/test9.proto new file mode 100644 index 0000000000000..9f68085282805 --- /dev/null +++ b/js/test9.proto @@ -0,0 +1,39 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package jspb.exttest.strict.nine; + +message Simple9 { + required string a_string = 1; + repeated string a_repeated_string = 2; + optional bool a_boolean = 3; +} diff --git a/js/testbinary.proto b/js/testbinary.proto index 116f17fb50862..a14128564488e 100644 --- a/js/testbinary.proto +++ b/js/testbinary.proto @@ -39,66 +39,66 @@ package jspb.test; // to ensure that the binary-format support will handle all field types // properly. message TestAllTypes { - 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 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 float optional_float = 11; + optional double optional_double = 12; + optional bool optional_bool = 13; + optional string optional_string = 14; + optional bytes optional_bytes = 15; optional group OptionalGroup = 16 { optional int32 a = 17; } - optional ForeignMessage optional_foreign_message = 19; - optional ForeignEnum optional_foreign_enum = 22; + optional ForeignMessage optional_foreign_message = 19; + optional ForeignEnum optional_foreign_enum = 22; // Repeated - repeated int32 repeated_int32 = 31; - repeated int64 repeated_int64 = 32; - repeated uint32 repeated_uint32 = 33; - repeated uint64 repeated_uint64 = 34; - repeated sint32 repeated_sint32 = 35; - repeated sint64 repeated_sint64 = 36; - repeated fixed32 repeated_fixed32 = 37; - repeated fixed64 repeated_fixed64 = 38; + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; repeated sfixed32 repeated_sfixed32 = 39; repeated sfixed64 repeated_sfixed64 = 40; - repeated float repeated_float = 41; - repeated double repeated_double = 42; - repeated bool repeated_bool = 43; - repeated string repeated_string = 44; - repeated bytes repeated_bytes = 45; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; repeated group RepeatedGroup = 46 { optional int32 a = 47; } - repeated ForeignMessage repeated_foreign_message = 49; - repeated ForeignEnum repeated_foreign_enum = 52; + repeated ForeignMessage repeated_foreign_message = 49; + repeated ForeignEnum repeated_foreign_enum = 52; // Packed repeated - repeated int32 packed_repeated_int32 = 61 [packed=true]; - repeated int64 packed_repeated_int64 = 62 [packed=true]; - repeated uint32 packed_repeated_uint32 = 63 [packed=true]; - repeated uint64 packed_repeated_uint64 = 64 [packed=true]; - repeated sint32 packed_repeated_sint32 = 65 [packed=true]; - repeated sint64 packed_repeated_sint64 = 66 [packed=true]; - repeated fixed32 packed_repeated_fixed32 = 67 [packed=true]; - repeated fixed64 packed_repeated_fixed64 = 68 [packed=true]; - repeated sfixed32 packed_repeated_sfixed32 = 69 [packed=true]; - repeated sfixed64 packed_repeated_sfixed64 = 70 [packed=true]; - repeated float packed_repeated_float = 71 [packed=true]; - repeated double packed_repeated_double = 72 [packed=true]; - repeated bool packed_repeated_bool = 73 [packed=true]; + repeated int32 packed_repeated_int32 = 61 [packed = true]; + repeated int64 packed_repeated_int64 = 62 [packed = true]; + repeated uint32 packed_repeated_uint32 = 63 [packed = true]; + repeated uint64 packed_repeated_uint64 = 64 [packed = true]; + repeated sint32 packed_repeated_sint32 = 65 [packed = true]; + repeated sint64 packed_repeated_sint64 = 66 [packed = true]; + repeated fixed32 packed_repeated_fixed32 = 67 [packed = true]; + repeated fixed64 packed_repeated_fixed64 = 68 [packed = true]; + repeated sfixed32 packed_repeated_sfixed32 = 69 [packed = true]; + repeated sfixed64 packed_repeated_sfixed64 = 70 [packed = true]; + repeated float packed_repeated_float = 71 [packed = true]; + repeated double packed_repeated_double = 72 [packed = true]; + repeated bool packed_repeated_bool = 73 [packed = true]; oneof oneof_field { uint32 oneof_uint32 = 111; @@ -132,55 +132,54 @@ message ExtendsWithMessage { } extend TestExtendable { - optional int32 extend_optional_int32 = 1; - optional int64 extend_optional_int64 = 2; - optional uint32 extend_optional_uint32 = 3; - optional uint64 extend_optional_uint64 = 4; - optional sint32 extend_optional_sint32 = 5; - optional sint64 extend_optional_sint64 = 6; - optional fixed32 extend_optional_fixed32 = 7; - optional fixed64 extend_optional_fixed64 = 8; - optional sfixed32 extend_optional_sfixed32 = 9; + optional int32 extend_optional_int32 = 1; + optional int64 extend_optional_int64 = 2; + optional uint32 extend_optional_uint32 = 3; + optional uint64 extend_optional_uint64 = 4; + optional sint32 extend_optional_sint32 = 5; + optional sint64 extend_optional_sint64 = 6; + optional fixed32 extend_optional_fixed32 = 7; + optional fixed64 extend_optional_fixed64 = 8; + optional sfixed32 extend_optional_sfixed32 = 9; optional sfixed64 extend_optional_sfixed64 = 10; - optional float extend_optional_float = 11; - optional double extend_optional_double = 12; - optional bool extend_optional_bool = 13; - optional string extend_optional_string = 14; - optional bytes extend_optional_bytes = 15; - optional ForeignEnum extend_optional_foreign_enum = 22; - - repeated int32 extend_repeated_int32 = 31; - repeated int64 extend_repeated_int64 = 32; - repeated uint32 extend_repeated_uint32 = 33; - repeated uint64 extend_repeated_uint64 = 34; - repeated sint32 extend_repeated_sint32 = 35; - repeated sint64 extend_repeated_sint64 = 36; - repeated fixed32 extend_repeated_fixed32 = 37; - repeated fixed64 extend_repeated_fixed64 = 38; + optional float extend_optional_float = 11; + optional double extend_optional_double = 12; + optional bool extend_optional_bool = 13; + optional string extend_optional_string = 14; + optional bytes extend_optional_bytes = 15; + optional ForeignEnum extend_optional_foreign_enum = 22; + + repeated int32 extend_repeated_int32 = 31; + repeated int64 extend_repeated_int64 = 32; + repeated uint32 extend_repeated_uint32 = 33; + repeated uint64 extend_repeated_uint64 = 34; + repeated sint32 extend_repeated_sint32 = 35; + repeated sint64 extend_repeated_sint64 = 36; + repeated fixed32 extend_repeated_fixed32 = 37; + repeated fixed64 extend_repeated_fixed64 = 38; repeated sfixed32 extend_repeated_sfixed32 = 39; repeated sfixed64 extend_repeated_sfixed64 = 40; - repeated float extend_repeated_float = 41; - repeated double extend_repeated_double = 42; - repeated bool extend_repeated_bool = 43; - repeated string extend_repeated_string = 44; - repeated bytes extend_repeated_bytes = 45; - repeated ForeignEnum extend_repeated_foreign_enum = 52; - - repeated int32 extend_packed_repeated_int32 = 61 [packed=true]; - repeated int64 extend_packed_repeated_int64 = 62 [packed=true]; - repeated uint32 extend_packed_repeated_uint32 = 63 [packed=true]; - repeated uint64 extend_packed_repeated_uint64 = 64 [packed=true]; - repeated sint32 extend_packed_repeated_sint32 = 65 [packed=true]; - repeated sint64 extend_packed_repeated_sint64 = 66 [packed=true]; - repeated fixed32 extend_packed_repeated_fixed32 = 67 [packed=true]; - repeated fixed64 extend_packed_repeated_fixed64 = 68 [packed=true]; - repeated sfixed32 extend_packed_repeated_sfixed32 = 69 [packed=true]; - repeated sfixed64 extend_packed_repeated_sfixed64 = 70 [packed=true]; - repeated float extend_packed_repeated_float = 71 [packed=true]; - repeated double extend_packed_repeated_double = 72 [packed=true]; - repeated bool extend_packed_repeated_bool = 73 [packed=true]; - repeated ForeignEnum extend_packed_repeated_foreign_enum = 82 - [packed=true]; + repeated float extend_repeated_float = 41; + repeated double extend_repeated_double = 42; + repeated bool extend_repeated_bool = 43; + repeated string extend_repeated_string = 44; + repeated bytes extend_repeated_bytes = 45; + repeated ForeignEnum extend_repeated_foreign_enum = 52; + + repeated int32 extend_packed_repeated_int32 = 61 [packed = true]; + repeated int64 extend_packed_repeated_int64 = 62 [packed = true]; + repeated uint32 extend_packed_repeated_uint32 = 63 [packed = true]; + repeated uint64 extend_packed_repeated_uint64 = 64 [packed = true]; + repeated sint32 extend_packed_repeated_sint32 = 65 [packed = true]; + repeated sint64 extend_packed_repeated_sint64 = 66 [packed = true]; + repeated fixed32 extend_packed_repeated_fixed32 = 67 [packed = true]; + repeated fixed64 extend_packed_repeated_fixed64 = 68 [packed = true]; + repeated sfixed32 extend_packed_repeated_sfixed32 = 69 [packed = true]; + repeated sfixed64 extend_packed_repeated_sfixed64 = 70 [packed = true]; + repeated float extend_packed_repeated_float = 71 [packed = true]; + repeated double extend_packed_repeated_double = 72 [packed = true]; + repeated bool extend_packed_repeated_bool = 73 [packed = true]; + repeated ForeignEnum extend_packed_repeated_foreign_enum = 82 [packed = true]; } @@ -201,6 +200,88 @@ message TestMapFields { map map_string_testmapfields = 12; } +// These proto are 'mock map' entries to test the above map deserializing with +// undefined keys. Make sure TestMapFieldsOptionalKeys is written to be +// deserialized by TestMapFields +message MapEntryOptionalKeysStringKey { + optional string key = 1; + optional string value = 2; +} + +message MapEntryOptionalKeysInt32Key { + optional int32 key = 1; + optional string value = 2; +} + +message MapEntryOptionalKeysInt64Key { + optional int64 key = 1; + optional string value = 2; +} + +message MapEntryOptionalKeysBoolKey { + optional bool key = 1; + optional string value = 2; +} + +message TestMapFieldsOptionalKeys { + optional MapEntryOptionalKeysStringKey map_string_string = 1; + optional MapEntryOptionalKeysInt32Key map_int32_string = 8; + optional MapEntryOptionalKeysInt64Key map_int64_string = 9; + optional MapEntryOptionalKeysBoolKey map_bool_string = 10; +} + +// End mock-map entries + +// These proto are 'mock map' entries to test the above map deserializing with +// undefined values. Make sure TestMapFieldsOptionalValues is written to be +// deserialized by TestMapFields +message MapEntryOptionalValuesStringValue { + optional string key = 1; + optional string value = 2; +} + +message MapEntryOptionalValuesInt32Value { + optional string key = 1; + optional int32 value = 2; +} + +message MapEntryOptionalValuesInt64Value { + optional string key = 1; + optional int64 value = 2; +} + +message MapEntryOptionalValuesBoolValue { + optional string key = 1; + optional bool value = 2; +} + +message MapEntryOptionalValuesDoubleValue { + optional string key = 1; + optional double value = 2; +} + +message MapEntryOptionalValuesEnumValue { + optional string key = 1; + optional MapValueEnum value = 2; +} + +message MapEntryOptionalValuesMessageValue { + optional string key = 1; + optional MapValueMessage value = 2; +} + +message TestMapFieldsOptionalValues { + optional MapEntryOptionalValuesStringValue map_string_string = 1; + optional MapEntryOptionalValuesInt32Value map_string_int32 = 2; + optional MapEntryOptionalValuesInt64Value map_string_int64 = 3; + optional MapEntryOptionalValuesBoolValue map_string_bool = 4; + optional MapEntryOptionalValuesDoubleValue map_string_double = 5; + optional MapEntryOptionalValuesEnumValue map_string_enum = 6; + optional MapEntryOptionalValuesMessageValue map_string_msg = 7; +} + +// End mock-map entries + enum MapValueEnum { MAP_VALUE_FOO = 0; MAP_VALUE_BAR = 1; @@ -210,3 +291,4 @@ enum MapValueEnum { message MapValueMessage { optional int32 foo = 1; } + diff --git a/js/testempty.proto b/js/testempty.proto index 960bce4e5c69c..6161753fd5e8f 100644 --- a/js/testempty.proto +++ b/js/testempty.proto @@ -31,4 +31,3 @@ syntax = "proto2"; package javatests.com.google.apps.jspb; - diff --git a/js/testlargenumbers.proto b/js/testlargenumbers.proto new file mode 100644 index 0000000000000..47aef35798a50 --- /dev/null +++ b/js/testlargenumbers.proto @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package jspb.test; + + +message MessageWithLargeFieldNumbers { + string a_string = 1; + bool a_boolean = 900; + int32 a_int = 5000; +} diff --git a/kokoro/README.md b/kokoro/README.md index 0791c9253bd40..590d7bd36bf9f 100644 --- a/kokoro/README.md +++ b/kokoro/README.md @@ -3,4 +3,10 @@ Kokoro Infrastructure ---------------------- The files in this directory serve as plumbing for running Protobuf -tests under Kokoro, our internal CI. \ No newline at end of file +tests under Kokoro, our internal CI. + +We have shared this part of our CI configuration in hopes that it is +helpful to contributors who want to better understand the details of +our test and release processes. If there are changes, please file an +issue; unfortunately, we may not be able to accept PRs (but feel free +to send one if it helps to explain the issue). diff --git a/kokoro/docs/common.cfg b/kokoro/docs/common.cfg new file mode 100644 index 0000000000000..771ca7f637c62 --- /dev/null +++ b/kokoro/docs/common.cfg @@ -0,0 +1,44 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Build logs will be here +action { + define_artifacts { + regex: "**/*sponge_log.xml" + } +} + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "protobuf/kokoro/docs/trampoline.sh" + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/python-multi" +} + +env_vars: { + key: "STAGING_BUCKET" + value: "docs-staging" +} + +# Fetch the token needed for reporting release status to GitHub +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "yoshi-automation-github-key" + } + } +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "docuploader_service_account" + } + } +} diff --git a/kokoro/docs/publish-python.sh b/kokoro/docs/publish-python.sh new file mode 100755 index 0000000000000..eea17552b4806 --- /dev/null +++ b/kokoro/docs/publish-python.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# Adapted from https://github.com/googleapis/google-cloud-python/blob/master/.kokoro/publish-docs.sh + +set -eo pipefail + +# Disable buffering, so that the logs stream through. +export PYTHONUNBUFFERED=1 + +cd github/protobuf/python + +# install package +sudo apt-get update +sudo apt-get -y install software-properties-common +sudo add-apt-repository universe +sudo apt-get update +sudo apt-get -y install unzip +wget https://github.com/protocolbuffers/protobuf/releases/download/v3.11.2/protoc-3.11.2-linux-x86_64.zip +unzip protoc-3.11.2-linux-x86_64.zip bin/protoc +mv bin/protoc ../src/protoc +python3.6 -m venv venv +source venv/bin/activate +python setup.py install + +# install docs dependencies +python -m pip install -r docs/requirements.txt + +# build docs +cd docs +make html +cd .. +deactivate + +python3.6 -m pip install protobuf==3.11.1 gcp-docuploader + +# install a json parser +sudo apt-get -y install jq + +# create metadata +python3.6 -m docuploader create-metadata \ + --name=$(jq --raw-output '.name // empty' .repo-metadata.json) \ + --version=$(python3 setup.py --version) \ + --language=$(jq --raw-output '.language // empty' .repo-metadata.json) \ + --distribution-name=$(python3 setup.py --name) \ + --product-page=$(jq --raw-output '.product_documentation // empty' .repo-metadata.json) \ + --github-repository=$(jq --raw-output '.repo // empty' .repo-metadata.json) \ + --issue-tracker=$(jq --raw-output '.issue_tracker // empty' .repo-metadata.json) + +cat docs.metadata + +# upload docs +python3.6 -m docuploader upload docs/_build/html --metadata-file docs.metadata --staging-bucket docs-staging diff --git a/kokoro/docs/python.cfg b/kokoro/docs/python.cfg new file mode 100644 index 0000000000000..382f431ad2f26 --- /dev/null +++ b/kokoro/docs/python.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Tell the trampoline which build file to use. +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/protobuf/kokoro/docs/publish-python.sh" +} diff --git a/kokoro/docs/trampoline.sh b/kokoro/docs/trampoline.sh new file mode 100755 index 0000000000000..db7e90b2e8ca1 --- /dev/null +++ b/kokoro/docs/trampoline.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# Copied from https://github.com/googleapis/google-cloud-python/blob/master/.kokoro/trampoline.sh + +set -eo pipefail + +python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py" || ret_code=$? + +chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh +${KOKORO_GFILE_DIR}/trampoline_cleanup.sh || true + +exit ${ret_code} diff --git a/jenkins/docker32/Dockerfile b/kokoro/linux/32-bit/Dockerfile similarity index 100% rename from jenkins/docker32/Dockerfile rename to kokoro/linux/32-bit/Dockerfile diff --git a/kokoro/linux/32-bit/build.sh b/kokoro/linux/32-bit/build.sh new file mode 100755 index 0000000000000..8c0a41ea2e91e --- /dev/null +++ b/kokoro/linux/32-bit/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request 32" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/php_32bit +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="php_all_32" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/32-bit/continuous.cfg b/kokoro/linux/32-bit/continuous.cfg new file mode 100644 index 0000000000000..28b66c07c2e1b --- /dev/null +++ b/kokoro/linux/32-bit/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/32-bit/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/32-bit/presubmit.cfg b/kokoro/linux/32-bit/presubmit.cfg new file mode 100644 index 0000000000000..28b66c07c2e1b --- /dev/null +++ b/kokoro/linux/32-bit/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/32-bit/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/64-bit/Dockerfile b/kokoro/linux/64-bit/Dockerfile new file mode 100644 index 0000000000000..3a279e6602492 --- /dev/null +++ b/kokoro/linux/64-bit/Dockerfile @@ -0,0 +1,244 @@ +# This Dockerfile specifies the recipe for creating an image for the tests +# to run in. +# +# We install as many test dependencies here as we can, because these setup +# steps can be cached. They do *not* run every time we run the build. +# The Docker image is only rebuilt when the Dockerfile (ie. this file) +# changes. + +# Base Dockerfile for gRPC dev images +FROM debian:latest + +# Apt source for old Python versions. +RUN echo 'deb http://ppa.launchpad.net/fkrull/deadsnakes/ubuntu trusty main' > /etc/apt/sources.list.d/deadsnakes.list && \ + apt-key adv --keyserver keyserver.ubuntu.com --recv-keys DB82666C + +# Apt source for Oracle Java. +RUN echo 'deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main' > /etc/apt/sources.list.d/webupd8team-java-trusty.list && \ + apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EEA14886 && \ + echo "oracle-java7-installer shared/accepted-oracle-license-v1-1 select true" | debconf-set-selections + +# Apt source for Mono +RUN echo "deb http://download.mono-project.com/repo/debian wheezy main" | tee /etc/apt/sources.list.d/mono-xamarin.list && \ + echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list && \ + apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF + +# Apt source for php +RUN echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu trusty main" | tee /etc/apt/sources.list.d/various-php.list && \ + apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F4FCBB07 + +# Install dotnet SDK based on https://www.microsoft.com/net/core#debian +# (Ubuntu instructions need apt to support https) +RUN apt-get update && apt-get install -y --force-yes curl libunwind8 gettext && \ + curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?LinkID=847105 && \ + mkdir -p /opt/dotnet && tar zxf dotnet.tar.gz -C /opt/dotnet && \ + ln -s /opt/dotnet/dotnet /usr/local/bin + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get clean && apt-get update && apt-get install -y --force-yes \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + # -- For csharp -- + mono-devel \ + referenceassemblies-pcl \ + nunit \ + # -- For all Java builds -- \ + maven \ + # -- For java_jdk6 -- \ + # oops! not in jessie. too old? openjdk-6-jdk \ + # -- For java_jdk7 -- \ + openjdk-7-jdk \ + # -- For java_oracle7 -- \ + oracle-java7-installer \ + # -- For python / python_cpp -- \ + python-setuptools \ + python-pip \ + python-dev \ + python2.6-dev \ + python3.3-dev \ + python3.4-dev \ + # -- For Ruby -- + ruby \ + # -- For C++ benchmarks -- + cmake \ + # -- For PHP -- + php5.6 \ + php5.6-dev \ + php5.6-xml \ + php7.0 \ + php7.0-dev \ + php7.0-xml \ + phpunit \ + valgrind \ + libxml2-dev \ + && apt-get clean + +################## +# C# dependencies + +RUN wget www.nuget.org/NuGet.exe -O /usr/local/bin/nuget.exe + +################## +# Python dependencies + +# These packages exist in apt-get, but their versions are too old, so we have +# to get updates from pip. + +RUN pip install pip --upgrade +RUN pip install virtualenv tox yattag + +################## +# Ruby dependencies + +# Install rvm +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 +RUN \curl -sSL https://get.rvm.io | bash -s stable + +# Install Ruby 2.1, Ruby 2.2 and JRuby 1.7 +RUN /bin/bash -l -c "rvm install ruby-2.1" +RUN /bin/bash -l -c "rvm install ruby-2.2" +RUN /bin/bash -l -c "rvm install jruby-1.7" +RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" +RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" +RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc" + +################## +# Java dependencies + +# This step requires compiling protoc. :( + +ENV MAVEN_REPO /var/maven_local_repository +ENV MVN mvn --batch-mode + +RUN cd /tmp && \ + git clone https://github.com/google/protobuf.git && \ + cd protobuf && \ + git reset --hard 129a6e2aca95dcfb6c3e717d7b9cca1f104fde39 && \ + ./autogen.sh && \ + ./configure && \ + make -j4 && \ + cd java && \ + $MVN install dependency:go-offline -Dmaven.repo.local=$MAVEN_REPO && \ + cd ../javanano && \ + $MVN install dependency:go-offline -Dmaven.repo.local=$MAVEN_REPO + +################## +# PHP dependencies. +RUN wget http://am1.php.net/get/php-5.5.38.tar.bz2/from/this/mirror +RUN mv mirror php-5.5.38.tar.bz2 +RUN tar -xvf php-5.5.38.tar.bz2 +RUN cd php-5.5.38 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-5.5-zts && \ + make && make install && cd .. +RUN cd php-5.5.38 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-5.5 && \ + make && make install && cd .. + +RUN wget http://am1.php.net/get/php-5.6.30.tar.bz2/from/this/mirror +RUN mv mirror php-5.6.30.tar.bz2 +RUN tar -xvf php-5.6.30.tar.bz2 +RUN cd php-5.6.30 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-5.6-zts && \ + make && make install && cd .. +RUN cd php-5.6.30 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-5.6 && \ + make && make install && cd .. + +RUN wget http://am1.php.net/get/php-7.0.18.tar.bz2/from/this/mirror +RUN mv mirror php-7.0.18.tar.bz2 +RUN tar -xvf php-7.0.18.tar.bz2 +RUN cd php-7.0.18 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-7.0-zts && \ + make && make install && cd .. +RUN cd php-7.0.18 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-7.0 && \ + make && make install && cd .. + +RUN wget http://am1.php.net/get/php-7.1.4.tar.bz2/from/this/mirror +RUN mv mirror php-7.1.4.tar.bz2 +RUN tar -xvf php-7.1.4.tar.bz2 +RUN cd php-7.1.4 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-7.1-zts && \ + make && make install && cd .. +RUN cd php-7.1.4 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-7.1 && \ + make && make install && cd .. + +RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" +RUN php composer-setup.php +RUN mv composer.phar /usr/bin/composer +RUN php -r "unlink('composer-setup.php');" +RUN composer config -g -- disable-tls true +RUN composer config -g -- secure-http false +RUN cd /tmp && \ + rm -rf protobuf && \ + git clone https://github.com/google/protobuf.git && \ + cd protobuf && \ + git reset --hard 49b44bff2b6257a119f9c6a342d6151c736586b8 && \ + cd php && \ + ln -sfn /usr/local/php-5.5/bin/php /usr/bin/php && \ + ln -sfn /usr/local/php-5.5/bin/php-config /usr/bin/php-config && \ + ln -sfn /usr/local/php-5.5/bin/phpize /usr/bin/phpize && \ + composer install && \ + mv vendor /usr/local/vendor-5.5 && \ + ln -sfn /usr/local/php-5.6/bin/php /usr/bin/php && \ + ln -sfn /usr/local/php-5.6/bin/php-config /usr/bin/php-config && \ + ln -sfn /usr/local/php-5.6/bin/phpize /usr/bin/phpize && \ + composer install && \ + mv vendor /usr/local/vendor-5.6 && \ + ln -sfn /usr/local/php-7.0/bin/php /usr/bin/php && \ + ln -sfn /usr/local/php-7.0/bin/php-config /usr/bin/php-config && \ + ln -sfn /usr/local/php-7.0/bin/phpize /usr/bin/phpize && \ + composer install && \ + mv vendor /usr/local/vendor-7.0 && \ + ln -sfn /usr/local/php-7.1/bin/php /usr/bin/php && \ + ln -sfn /usr/local/php-7.1/bin/php-config /usr/bin/php-config && \ + ln -sfn /usr/local/php-7.1/bin/phpize /usr/bin/phpize && \ + composer install && \ + mv vendor /usr/local/vendor-7.1 + +################## +# Go dependencies. +RUN apt-get install -y \ + # -- For go -- \ + golang + +################## +# Javascript dependencies. +RUN apt-get install -y \ + # -- For javascript -- \ + npm + +################## +# Python 3.5 3.6 dependencies. +RUN apt-get clean && apt-get update && apt-get install -y --force-yes \ + python3.5-dev \ + python3.6-dev \ + && apt-get clean + +# On Debian/Ubuntu, nodejs binary is named 'nodejs' because the name 'node' +# is taken by another legacy binary. We don't have that legacy binary and +# npm expects the binary to be named 'node', so we just create a symbol +# link here. +RUN ln -s `which nodejs` /usr/bin/node + +################## +# Prepare ccache + +RUN ln -s /usr/bin/ccache /usr/local/bin/gcc +RUN ln -s /usr/bin/ccache /usr/local/bin/g++ +RUN ln -s /usr/bin/ccache /usr/local/bin/cc +RUN ln -s /usr/bin/ccache /usr/local/bin/c++ +RUN ln -s /usr/bin/ccache /usr/local/bin/clang +RUN ln -s /usr/bin/ccache /usr/local/bin/clang++ + +# Define the default command. +CMD ["bash"] diff --git a/kokoro/linux/bazel/build.sh b/kokoro/linux/bazel/build.sh new file mode 100755 index 0000000000000..5f34bea30ef12 --- /dev/null +++ b/kokoro/linux/bazel/build.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# +# Build file to set up and run tests +set -ex + +# Install the latest Bazel version available +use_bazel.sh latest +bazel version + +# Print bazel testlogs to stdout when tests failed. +function print_test_logs { + # TODO(yannic): Only print logs of failing tests. + testlogs_dir=$(bazel info bazel-testlogs) + testlogs=$(find "${testlogs_dir}" -name "*.log") + for log in $testlogs; do + cat "${log}" + done +} + +# Change to repo root +cd $(dirname $0)/../../.. + +git submodule update --init --recursive + +trap print_test_logs EXIT +bazel test --copt=-Werror --host_copt=-Werror \ + //:build_files_updated_unittest \ + //java/... \ + //:protoc \ + //:protobuf \ + //:protobuf_python \ + //:protobuf_test \ + @com_google_protobuf//:cc_proto_blacklist_test +trap - EXIT + +cd examples +bazel build //... diff --git a/kokoro/linux/bazel/continuous.cfg b/kokoro/linux/bazel/continuous.cfg new file mode 100644 index 0000000000000..13cfef1583c06 --- /dev/null +++ b/kokoro/linux/bazel/continuous.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/bazel/build.sh" +timeout_mins: 15 diff --git a/kokoro/linux/bazel/presubmit.cfg b/kokoro/linux/bazel/presubmit.cfg new file mode 100644 index 0000000000000..13cfef1583c06 --- /dev/null +++ b/kokoro/linux/bazel/presubmit.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/bazel/build.sh" +timeout_mins: 15 diff --git a/kokoro/linux/benchmark/build.sh b/kokoro/linux/benchmark/build.sh new file mode 100755 index 0000000000000..e563e791663c8 --- /dev/null +++ b/kokoro/linux/benchmark/build.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +cd $(dirname $0)/../../.. + +# prepare php environments +sudo apt-get update && sudo apt-get install -y --force-yes php5 +sudo ln -sf /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h +mkdir php_temp +cd php_temp +curl -sS https://getcomposer.org/installer | php +sudo mv composer.phar /usr/local/bin/composer +git clone https://github.com/php/php-src +cd php-src && git checkout PHP-7.2.13 && ./buildconf --force +./configure \ + --enable-bcmatch \ + --with-gmp --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.2 && \ +make -j8 && sudo make install && make clean +wget -O phpunit https://phar.phpunit.de/phpunit-7.phar && \ + chmod +x phpunit && \ + sudo cp phpunit /usr/local/php-7.2/bin +sudo apt-get install -y --force-yes valgrind +cd ../.. + +./tests.sh benchmark diff --git a/kokoro/linux/benchmark/continuous.cfg b/kokoro/linux/benchmark/continuous.cfg new file mode 100644 index 0000000000000..8cc8f96bfa62b --- /dev/null +++ b/kokoro/linux/benchmark/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/benchmark/build.sh" +timeout_mins: 240 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/benchmark/run.sh b/kokoro/linux/benchmark/run.sh new file mode 100755 index 0000000000000..1b1032bd3775c --- /dev/null +++ b/kokoro/linux/benchmark/run.sh @@ -0,0 +1,105 @@ +#!/bin/bash +# +# Change to repo root +cd $(dirname $0)/../../.. + +export OUTPUT_DIR=testoutput +oldpwd=`pwd` + +# tcmalloc +if [ ! -f gperftools/.libs/libtcmalloc.so ]; then + git clone https://github.com/gperftools/gperftools.git + cd gperftools + ./autogen.sh + ./configure + make -j8 + cd .. +fi + +# download datasets for benchmark +cd benchmarks +./download_data.sh +datasets=$(for file in $(find . -type f -name "dataset.*.pb" -not -path "./tmp/*"); do echo "$(pwd)/$file"; done | xargs) +echo $datasets +cd $oldpwd + +# build Python protobuf +./autogen.sh +./configure CXXFLAGS="-fPIC -O2" +make -j8 +cd python +python setup.py build --cpp_implementation +pip install . --user + + +# build and run Python benchmark +cd ../benchmarks +make python-pure-python-benchmark +make python-cpp-reflection-benchmark +make -j8 python-cpp-generated-code-benchmark +echo "[" > tmp/python_result.json +echo "benchmarking pure python..." +./python-pure-python-benchmark --json --behavior_prefix="pure-python-benchmark" $datasets >> tmp/python_result.json +echo "," >> "tmp/python_result.json" +echo "benchmarking python cpp reflection..." +env LD_PRELOAD="$oldpwd/gperftools/.libs/libtcmalloc.so" LD_LIBRARY_PATH="$oldpwd/src/.libs" ./python-cpp-reflection-benchmark --json --behavior_prefix="cpp-reflection-benchmark" $datasets >> tmp/python_result.json +echo "," >> "tmp/python_result.json" +echo "benchmarking python cpp generated code..." +env LD_PRELOAD="$oldpwd/gperftools/.libs/libtcmalloc.so" LD_LIBRARY_PATH="$oldpwd/src/.libs" ./python-cpp-generated-code-benchmark --json --behavior_prefix="cpp-generated-code-benchmark" $datasets >> tmp/python_result.json +echo "]" >> "tmp/python_result.json" +cd $oldpwd + +# build CPP protobuf +./configure +make clean && make -j8 + +# build Java protobuf +cd java +mvn package +cd .. + +# build CPP benchmark +cd benchmarks +mv tmp/python_result.json . && make clean && make -j8 cpp-benchmark && mv python_result.json tmp +echo "benchmarking cpp..." +env LD_PRELOAD="$oldpwd/gperftools/.libs/libtcmalloc.so" ./cpp-benchmark --benchmark_min_time=5.0 --benchmark_out_format=json --benchmark_out="tmp/cpp_result.json" $datasets +cd $oldpwd + +# build go protobuf +export PATH="`pwd`/src:$PATH" +export GOPATH="$HOME/gocode" +mkdir -p "$GOPATH/src/github.com/google" +rm -f "$GOPATH/src/github.com/protocolbuffers/protobuf" +ln -s "`pwd`" "$GOPATH/src/github.com/protocolbuffers/protobuf" +export PATH="$GOPATH/bin:$PATH" +go get github.com/golang/protobuf/protoc-gen-go + +# build go benchmark +cd benchmarks +make go-benchmark +echo "benchmarking go..." +./go-benchmark $datasets > tmp/go_result.txt + +# build java benchmark +make java-benchmark +echo "benchmarking java..." +./java-benchmark -Cresults.file.options.file="tmp/java_result.json" $datasets + +make js-benchmark +echo "benchmarking js..." +./js-benchmark $datasets --json_output=$(pwd)/tmp/node_result.json + +make -j8 generate_proto3_data +proto3_datasets=$(for file in $datasets; do echo $(pwd)/tmp/proto3_data/${file#$(pwd)}; done | xargs) +echo $proto3_datasets + +# build php benchmark +make -j8 php-c-benchmark +echo "benchmarking php_c..." +./php-c-benchmark $proto3_datasets --json --behavior_prefix="php_c" > tmp/php_c_result.json + +# upload result to bq +make python_add_init +env LD_LIBRARY_PATH="$oldpwd/src/.libs" python -m util.result_uploader -php_c="../tmp/php_c_result.json" \ + -cpp="../tmp/cpp_result.json" -java="../tmp/java_result.json" -go="../tmp/go_result.txt" -python="../tmp/python_result.json" -node="../tmp/node_result.json" +cd $oldpwd diff --git a/kokoro/linux/build_and_run_docker.sh b/kokoro/linux/build_and_run_docker.sh new file mode 100755 index 0000000000000..cdbd6e29b0fb3 --- /dev/null +++ b/kokoro/linux/build_and_run_docker.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# +# Builds docker image and runs a command under it. +# This is a generic script that is configured with the following variables: +# +# DOCKERHUB_ORGANIZATION - The organization on docker hub storing the +# Dockerfile. +# DOCKERFILE_DIR - Directory in which Dockerfile file is located. +# DOCKER_RUN_SCRIPT - Script to run under docker (relative to protobuf repo root) +# OUTPUT_DIR - Directory that will be copied from inside docker after finishing. +# $@ - Extra args to pass to docker run + +set -ex + +cd $(dirname $0)/../.. +git_root=$(pwd) +cd - + +# Use image name based on Dockerfile sha1 +if [ -z "$DOCKERHUB_ORGANIZATION" ] +then + DOCKERHUB_ORGANIZATION=grpctesting/protobuf + DOCKER_IMAGE_NAME=${DOCKERHUB_ORGANIZATION}_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ ) +else + # TODO(teboring): Remove this when all tests have been migrated to separate + # docker images. + DOCKERFILE_PREFIX=$(basename $DOCKERFILE_DIR) + DOCKER_IMAGE_NAME=${DOCKERHUB_ORGANIZATION}/${DOCKERFILE_PREFIX}_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ ) +fi + +# Pull dockerimage from Dockerhub. This sometimes fails intermittently, so we +# keep trying until we succeed. +until docker pull $DOCKER_IMAGE_NAME; do sleep 10; done + +# Ensure existence of ccache directory +CCACHE_DIR=/tmp/protobuf-ccache +mkdir -p $CCACHE_DIR + +# Choose random name for docker container +CONTAINER_NAME="build_and_run_docker_$(uuidgen)" + +echo $git_root + +# Run command inside docker +docker run \ + "$@" \ + -e CCACHE_DIR=$CCACHE_DIR \ + -e KOKORO_BUILD_NUMBER=$KOKORO_BUILD_NUMBER \ + -e KOKORO_BUILD_ID=$KOKORO_BUILD_ID \ + -e EXTERNAL_GIT_ROOT="/var/local/kokoro/protobuf" \ + -e TEST_SET="$TEST_SET" \ + -v "$git_root:/var/local/kokoro/protobuf:ro" \ + -v $CCACHE_DIR:$CCACHE_DIR \ + -w /var/local/git/protobuf \ + --name=$CONTAINER_NAME \ + $DOCKER_IMAGE_NAME \ + bash -l "/var/local/kokoro/protobuf/$DOCKER_RUN_SCRIPT" || FAILED="true" + +# remove the container, possibly killing it first +docker rm -f $CONTAINER_NAME || true + +[ -z "$FAILED" ] || { + exit 1 +} diff --git a/kokoro/linux/cpp_distcheck/build.sh b/kokoro/linux/cpp_distcheck/build.sh index b8b57e358efa5..a28843e9cba1b 100755 --- a/kokoro/linux/cpp_distcheck/build.sh +++ b/kokoro/linux/cpp_distcheck/build.sh @@ -2,10 +2,24 @@ # # Build file to set up and run tests +set -ex # exit immediately on error + # Change to repo root cd $(dirname $0)/../../.. -# Prepare worker environment to run tests -source kokoro/linux/prepare_build_linux_rc - ./tests.sh cpp_distcheck + +# Run tests under release docker image. +DOCKER_IMAGE_NAME=protobuf/protoc_$(sha1sum protoc-artifacts/Dockerfile | cut -f1 -d " ") +until docker pull $DOCKER_IMAGE_NAME; do sleep 10; done + +docker run -v $(pwd):/var/local/protobuf --rm $DOCKER_IMAGE_NAME \ + bash -l /var/local/protobuf/tests.sh cpp || FAILED="true" + +# This directory is owned by root. We need to delete it, because otherwise +# Kokoro will attempt to rsync it and fail with a permission error. +rm -rf src/core + +if [ "$FAILED" = "true" ]; then + exit 1 +fi diff --git a/kokoro/linux/cpp_tcmalloc/build.sh b/kokoro/linux/cpp_tcmalloc/build.sh new file mode 100755 index 0000000000000..3c77b11e70f47 --- /dev/null +++ b/kokoro/linux/cpp_tcmalloc/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# +# Build file to set up and run tests + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/cpp_tcmalloc +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="cpp_tcmalloc" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/cpp_tcmalloc/continuous.cfg b/kokoro/linux/cpp_tcmalloc/continuous.cfg new file mode 100644 index 0000000000000..46312a9be29cc --- /dev/null +++ b/kokoro/linux/cpp_tcmalloc/continuous.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/cpp_tcmalloc/build.sh" +timeout_mins: 1440 diff --git a/kokoro/linux/cpp_tcmalloc/presubmit.cfg b/kokoro/linux/cpp_tcmalloc/presubmit.cfg new file mode 100644 index 0000000000000..46312a9be29cc --- /dev/null +++ b/kokoro/linux/cpp_tcmalloc/presubmit.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/cpp_tcmalloc/build.sh" +timeout_mins: 1440 diff --git a/kokoro/linux/csharp/build.sh b/kokoro/linux/csharp/build.sh index de178b844dc8c..9a2eb48621a87 100755 --- a/kokoro/linux/csharp/build.sh +++ b/kokoro/linux/csharp/build.sh @@ -1,11 +1,18 @@ #!/bin/bash # -# Build file to set up and run tests +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. # Change to repo root cd $(dirname $0)/../../.. -# Prepare worker environment to run tests -source kokoro/linux/prepare_build_linux_rc - -./tests.sh csharp +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/csharp +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="csharp" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/dist_install/build.sh b/kokoro/linux/dist_install/build.sh new file mode 100755 index 0000000000000..81a0516aa8453 --- /dev/null +++ b/kokoro/linux/dist_install/build.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# +# Build file to set up and run tests + +set -ex # exit immediately on error + +# Change to repo root +cd $(dirname $0)/../../.. + +# Run tests under release docker image. +export DOCKERFILE_DIR=kokoro/linux/64-bit +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="dist_install" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/dist_install/continuous.cfg b/kokoro/linux/dist_install/continuous.cfg new file mode 100644 index 0000000000000..b1e0b2013d06b --- /dev/null +++ b/kokoro/linux/dist_install/continuous.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/dist_install/build.sh" +timeout_mins: 1440 diff --git a/kokoro/linux/dist_install/presubmit.cfg b/kokoro/linux/dist_install/presubmit.cfg new file mode 100644 index 0000000000000..b1e0b2013d06b --- /dev/null +++ b/kokoro/linux/dist_install/presubmit.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/dist_install/build.sh" +timeout_mins: 1440 diff --git a/kokoro/linux/dockerfile/push_testing_images.sh b/kokoro/linux/dockerfile/push_testing_images.sh new file mode 100755 index 0000000000000..2d82babba4190 --- /dev/null +++ b/kokoro/linux/dockerfile/push_testing_images.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +set -ex + +cd $(dirname $0)/../../.. +git_root=$(pwd) +cd kokoro/linux/dockerfile + +DOCKERHUB_ORGANIZATION=protobuftesting + +for DOCKERFILE_DIR in test/* +do + # Generate image name based on Dockerfile checksum. That works well as long + # as can count on dockerfiles being written in a way that changing the logical + # contents of the docker image always changes the SHA (e.g. using "ADD file" + # cmd in the dockerfile in not ok as contents of the added file will not be + # reflected in the SHA). + DOCKER_IMAGE_NAME=$(basename $DOCKERFILE_DIR)_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ ) + + echo $DOCKER_IMAGE_NAME + # skip the image if it already exists in the repo + curl --silent -f -lSL https://registry.hub.docker.com/v2/repositories/${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME}/tags/latest > /dev/null \ + && continue + + docker build -t ${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME} ${DOCKERFILE_DIR} + + # "docker login" needs to be run in advance + docker push ${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME} +done diff --git a/kokoro/linux/dockerfile/test/cpp_tcmalloc/Dockerfile b/kokoro/linux/dockerfile/test/cpp_tcmalloc/Dockerfile new file mode 100644 index 0000000000000..0ce9982ad410c --- /dev/null +++ b/kokoro/linux/dockerfile/test/cpp_tcmalloc/Dockerfile @@ -0,0 +1,29 @@ +FROM debian:jessie + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean + +# Install dependencies for TC malloc +RUN apt-get install -y \ + google-perftools \ + libgoogle-perftools4 \ + libgoogle-perftools-dev diff --git a/kokoro/linux/dockerfile/test/csharp/Dockerfile b/kokoro/linux/dockerfile/test/csharp/Dockerfile new file mode 100644 index 0000000000000..95bd653152f09 --- /dev/null +++ b/kokoro/linux/dockerfile/test/csharp/Dockerfile @@ -0,0 +1,37 @@ +FROM debian:stretch + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean + +# dotnet SDK prerequisites +RUN apt-get update && apt-get install -y libunwind8 libicu57 && apt-get clean + +# Install dotnet SDK via install script +RUN wget -q https://dot.net/v1/dotnet-install.sh && \ + chmod u+x dotnet-install.sh && \ + ./dotnet-install.sh --version 2.1.802 && \ + ./dotnet-install.sh --version 3.1.301 && \ + ln -s /root/.dotnet/dotnet /usr/local/bin + +RUN wget -q www.nuget.org/NuGet.exe -O /usr/local/bin/nuget.exe + +ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE true diff --git a/kokoro/linux/dockerfile/test/java_stretch/Dockerfile b/kokoro/linux/dockerfile/test/java_stretch/Dockerfile new file mode 100644 index 0000000000000..fc5e82abdbb38 --- /dev/null +++ b/kokoro/linux/dockerfile/test/java_stretch/Dockerfile @@ -0,0 +1,31 @@ +FROM debian:stretch + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean + +# Java dependencies +RUN apt-get install -y \ + # -- For all Java builds -- \ + maven \ + # -- For java_linkage_monitor \ + openjdk-8-jdk \ + && apt-get clean diff --git a/kokoro/linux/dockerfile/test/javascript/Dockerfile b/kokoro/linux/dockerfile/test/javascript/Dockerfile new file mode 100644 index 0000000000000..dff7e7bec115e --- /dev/null +++ b/kokoro/linux/dockerfile/test/javascript/Dockerfile @@ -0,0 +1,33 @@ +FROM ubuntu:latest + +RUN apt-get update && apt-get install -y gnupg + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get clean && apt-get update && apt-get install -y --force-yes \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean + + +################## +# Javascript dependencies. +RUN apt-get install -y \ + # -- For javascript and closure compiler -- \ + npm \ + default-jre diff --git a/kokoro/linux/dockerfile/test/php/Dockerfile b/kokoro/linux/dockerfile/test/php/Dockerfile new file mode 100644 index 0000000000000..4c9d69d181f18 --- /dev/null +++ b/kokoro/linux/dockerfile/test/php/Dockerfile @@ -0,0 +1,255 @@ +FROM debian:jessie + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + re2c \ + sqlite3 \ + libsqlite3-dev \ + && apt-get clean + +# Install php dependencies +RUN apt-get clean && apt-get update && apt-get install -y --force-yes \ + php5 \ + libcurl4-openssl-dev \ + libgmp-dev \ + libgmp3-dev \ + libssl-dev \ + libxml2-dev \ + unzip \ + zlib1g-dev \ + pkg-config \ + && apt-get clean + +# Install other dependencies +RUN ln -sf /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h +RUN wget http://ftp.gnu.org/gnu/bison/bison-2.6.4.tar.gz -O /var/local/bison-2.6.4.tar.gz +RUN cd /var/local \ + && tar -zxvf bison-2.6.4.tar.gz \ + && cd /var/local/bison-2.6.4 \ + && ./configure \ + && make \ + && make install + +# Install composer +RUN curl -sS https://getcomposer.org/installer | php +RUN mv composer.phar /usr/local/bin/composer + +# Download php source code +RUN git clone https://github.com/php/php-src + +# php 5.6 +RUN cd php-src \ + && git checkout PHP-5.6.39 \ + && ./buildconf --force +RUN cd php-src \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-5.6 \ + && make \ + && make install \ + && make clean + +RUN wget -O phpunit https://phar.phpunit.de/phpunit-5.phar \ + && chmod +x phpunit \ + && mv phpunit /usr/local/php-5.6/bin + +# php 7.0 +RUN cd php-src \ + && git checkout PHP-7.0.33 \ + && ./buildconf --force +RUN cd php-src \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.0 \ + && make \ + && make install \ + && make clean +RUN cd php-src \ + && ./configure \ + --enable-maintainer-zts \ + --enable-mbstring \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.0-zts \ + && make \ + && make install \ + && make clean + +RUN wget -O phpunit https://phar.phpunit.de/phpunit-6.phar \ + && chmod +x phpunit \ + && cp phpunit /usr/local/php-7.0/bin \ + && mv phpunit /usr/local/php-7.0-zts/bin + +# php 7.1 +RUN cd php-src \ + && git checkout PHP-7.1.25 \ + && ./buildconf --force +RUN cd php-src \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.1 \ + && make \ + && make install \ + && make clean +RUN cd php-src \ + && ./configure \ + --enable-maintainer-zts \ + --enable-mbstring \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.1-zts \ + && make \ + && make install \ + && make clean + +RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.5.0.phar \ + && chmod +x phpunit \ + && cp phpunit /usr/local/php-7.1/bin \ + && mv phpunit /usr/local/php-7.1-zts/bin + +# php 7.2 +RUN cd php-src \ + && git checkout PHP-7.2.13 \ + && ./buildconf --force +RUN cd php-src \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.2 \ + && make \ + && make install \ + && make clean +RUN cd php-src \ + && ./configure \ + --enable-maintainer-zts \ + --enable-mbstring \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.2-zts \ + && make \ + && make install \ + && make clean + +RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.5.0.phar \ + && chmod +x phpunit \ + && cp phpunit /usr/local/php-7.2/bin \ + && mv phpunit /usr/local/php-7.2-zts/bin + +# php 7.3 +RUN cd php-src \ + && git checkout PHP-7.3.0 \ + && ./buildconf --force +RUN cd php-src \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.3 \ + && make \ + && make install \ + && make clean +RUN cd php-src \ + && ./configure \ + --enable-maintainer-zts \ + --enable-mbstring \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.3-zts \ + && make \ + && make install \ + && make clean + +RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.5.0.phar \ + && chmod +x phpunit \ + && cp phpunit /usr/local/php-7.3/bin \ + && mv phpunit /usr/local/php-7.3-zts/bin + +# php 7.4 +RUN wget https://ftp.gnu.org/gnu/bison/bison-3.0.1.tar.gz -O /var/local/bison-3.0.1.tar.gz +RUN cd /var/local \ + && tar -zxvf bison-3.0.1.tar.gz \ + && cd /var/local/bison-3.0.1 \ + && ./configure \ + && make \ + && make install + +RUN wget https://github.com/php/php-src/archive/php-7.4.0.tar.gz -O /var/local/php-7.4.0.tar.gz + +RUN cd /var/local \ + && tar -zxvf php-7.4.0.tar.gz + +RUN cd /var/local/php-src-php-7.4.0 \ + && ./buildconf --force \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --disable-mbregex \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.4 \ + && make \ + && make install \ + && make clean +RUN cd /var/local/php-src-php-7.4.0 \ + && ./buildconf --force \ + && ./configure \ + --enable-maintainer-zts \ + --enable-mbstring \ + --disable-mbregex \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.4-zts \ + && make \ + && make install \ + && make clean + +RUN wget -O phpunit https://phar.phpunit.de/phpunit-8.phar \ + && chmod +x phpunit \ + && cp phpunit /usr/local/php-7.4/bin \ + && mv phpunit /usr/local/php-7.4-zts/bin + +# Install php dependencies +RUN apt-get clean && apt-get update && apt-get install -y --force-yes \ + valgrind \ + && apt-get clean diff --git a/kokoro/linux/dockerfile/test/php80/Dockerfile b/kokoro/linux/dockerfile/test/php80/Dockerfile new file mode 100644 index 0000000000000..8093eae16c1ce --- /dev/null +++ b/kokoro/linux/dockerfile/test/php80/Dockerfile @@ -0,0 +1,96 @@ +FROM debian:jessie + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + re2c \ + sqlite3 \ + vim \ + libonig-dev \ + libsqlite3-dev \ + && apt-get clean + +# Install php dependencies +RUN apt-get clean && apt-get update && apt-get install -y --force-yes \ + php5 \ + libcurl4-openssl-dev \ + libgmp-dev \ + libgmp3-dev \ + libssl-dev \ + libxml2-dev \ + unzip \ + zlib1g-dev \ + pkg-config \ + && apt-get clean + +# Install other dependencies +RUN ln -sf /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h +RUN wget https://ftp.gnu.org/gnu/bison/bison-3.0.1.tar.gz -O /var/local/bison-3.0.1.tar.gz +RUN cd /var/local \ + && tar -zxvf bison-3.0.1.tar.gz \ + && cd /var/local/bison-3.0.1 \ + && ./configure \ + && make \ + && make install + +# Install composer +RUN curl -sS https://getcomposer.org/installer | php +RUN mv composer.phar /usr/local/bin/composer + +# Download php source code +RUN git clone https://github.com/php/php-src + +# php 8.0 +RUN cd php-src \ + && git checkout php-8.0.0 \ + && ./buildconf --force +RUN cd php-src \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-8.0 \ + && make \ + && make install \ + && make clean +RUN cd php-src \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --enable-maintainer-zts \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-8.0-zts \ + && make \ + && make install \ + && make clean + +RUN wget -O phpunit https://phar.phpunit.de/phpunit-9.phar \ + && chmod +x phpunit \ + && cp phpunit /usr/local/php-8.0/bin \ + && mv phpunit /usr/local/php-8.0-zts/bin + +# Install php dependencies +RUN apt-get clean && apt-get update && apt-get install -y --force-yes \ + valgrind \ + && apt-get clean diff --git a/kokoro/linux/dockerfile/test/php_32bit/Dockerfile b/kokoro/linux/dockerfile/test/php_32bit/Dockerfile new file mode 100644 index 0000000000000..d657af1649dd1 --- /dev/null +++ b/kokoro/linux/dockerfile/test/php_32bit/Dockerfile @@ -0,0 +1,258 @@ +FROM i386/debian:jessie + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + re2c \ + sqlite3 \ + libsqlite3-dev \ + && apt-get clean + +# Install php dependencies +RUN apt-get clean && apt-get update && apt-get install -y --force-yes \ + bison \ + php5 \ + libcurl4-openssl-dev \ + libssl-dev \ + libxml2-dev \ + unzip \ + zlib1g-dev \ + pkg-config \ + && apt-get clean + +# Install other dependencies +RUN wget http://ftp.gnu.org/gnu/bison/bison-2.6.4.tar.gz -O /var/local/bison-2.6.4.tar.gz +RUN cd /var/local \ + && tar -zxvf bison-2.6.4.tar.gz \ + && cd /var/local/bison-2.6.4 \ + && ./configure \ + && make \ + && make install + +# Install composer +RUN curl -sS https://getcomposer.org/installer | php +RUN mv composer.phar /usr/local/bin/composer + +# Download php source code +RUN git clone https://github.com/php/php-src + +# php 5.6 +RUN cd php-src \ + && git checkout PHP-5.6.39 \ + && ./buildconf --force +RUN cd php-src \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-5.6 \ + && make \ + && make install \ + && make clean + +RUN wget -O phpunit https://phar.phpunit.de/phpunit-5.phar \ + && chmod +x phpunit \ + && mv phpunit /usr/local/php-5.6/bin + +# php 7.0 +RUN wget https://github.com/php/php-src/archive/php-7.0.33.tar.gz -O /var/local/php-7.0.33.tar.gz + +RUN cd /var/local \ + && tar -zxvf php-7.0.33.tar.gz + +RUN cd /var/local/php-src-php-7.0.33 \ + && ./buildconf --force \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.0 \ + && make \ + && make install \ + && make clean +RUN cd /var/local/php-src-php-7.0.33 \ + && ./buildconf --force \ + && ./configure \ + --enable-maintainer-zts \ + --enable-mbstring \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.0-zts \ + && make \ + && make install \ + && make clean + +RUN wget -O phpunit https://phar.phpunit.de/phpunit-6.phar \ + && chmod +x phpunit \ + && cp phpunit /usr/local/php-7.0/bin \ + && mv phpunit /usr/local/php-7.0-zts/bin + +# php 7.1 +RUN wget https://github.com/php/php-src/archive/php-7.1.25.tar.gz -O /var/local/php-7.1.25.tar.gz + +RUN cd /var/local \ + && tar -zxvf php-7.1.25.tar.gz + +RUN cd /var/local/php-src-php-7.1.25 \ + && ./buildconf --force \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.1 \ + && make \ + && make install \ + && make clean +RUN cd /var/local/php-src-php-7.1.25 \ + && ./buildconf --force \ + && ./configure \ + --enable-maintainer-zts \ + --enable-mbstring \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.1-zts \ + && make \ + && make install \ + && make clean + +RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.5.0.phar \ + && chmod +x phpunit \ + && cp phpunit /usr/local/php-7.1/bin \ + && mv phpunit /usr/local/php-7.1-zts/bin + +# php 7.2 +RUN wget https://github.com/php/php-src/archive/php-7.2.13.tar.gz -O /var/local/php-7.2.13.tar.gz + +RUN cd /var/local \ + && tar -zxvf php-7.2.13.tar.gz + +RUN cd /var/local/php-src-php-7.2.13 \ + && ./buildconf --force \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.2 \ + && make \ + && make install \ + && make clean +RUN cd /var/local/php-src-php-7.2.13 \ + && ./buildconf --force \ + && ./configure \ + --enable-maintainer-zts \ + --enable-mbstring \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.2-zts \ + && make \ + && make install \ + && make clean + +RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.5.0.phar \ + && chmod +x phpunit \ + && cp phpunit /usr/local/php-7.2/bin \ + && mv phpunit /usr/local/php-7.2-zts/bin + +# php 7.3 +RUN wget https://github.com/php/php-src/archive/php-7.3.0.tar.gz -O /var/local/php-7.3.0.tar.gz + +RUN cd /var/local \ + && tar -zxvf php-7.3.0.tar.gz + +RUN cd /var/local/php-src-php-7.3.0 \ + && ./buildconf --force \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.3 \ + && make \ + && make install \ + && make clean +RUN cd /var/local/php-src-php-7.3.0 \ + && ./buildconf --force \ + && ./configure \ + --enable-maintainer-zts \ + --enable-mbstring \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.3-zts \ + && make \ + && make install \ + && make clean + +RUN wget -O phpunit https://phar.phpunit.de/phpunit-7.5.0.phar \ + && chmod +x phpunit \ + && cp phpunit /usr/local/php-7.3/bin \ + && mv phpunit /usr/local/php-7.3-zts/bin + +# php 7.4 +RUN wget https://ftp.gnu.org/gnu/bison/bison-3.0.1.tar.gz -O /var/local/bison-3.0.1.tar.gz +RUN cd /var/local \ + && tar -zxvf bison-3.0.1.tar.gz \ + && cd /var/local/bison-3.0.1 \ + && ./configure \ + && make \ + && make install + +RUN wget https://github.com/php/php-src/archive/php-7.4.0.tar.gz -O /var/local/php-7.4.0.tar.gz + +RUN cd /var/local \ + && tar -zxvf php-7.4.0.tar.gz + +RUN cd /var/local/php-src-php-7.4.0 \ + && ./buildconf --force \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --disable-mbregex \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.4 \ + && make \ + && make install \ + && make clean +RUN cd /var/local/php-src-php-7.4.0 \ + && ./buildconf --force \ + && ./configure \ + --enable-maintainer-zts \ + --enable-mbstring \ + --disable-mbregex \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-7.4-zts \ + && make \ + && make install \ + && make clean + +RUN wget -O phpunit https://phar.phpunit.de/phpunit-8.phar \ + && chmod +x phpunit \ + && cp phpunit /usr/local/php-7.4/bin \ + && mv phpunit /usr/local/php-7.4-zts/bin + +# Install php dependencies +RUN apt-get clean && apt-get update && apt-get install -y --force-yes \ + valgrind \ + && apt-get clean diff --git a/kokoro/linux/dockerfile/test/python27/Dockerfile b/kokoro/linux/dockerfile/test/python27/Dockerfile new file mode 100644 index 0000000000000..6b0eaf72c8626 --- /dev/null +++ b/kokoro/linux/dockerfile/test/python27/Dockerfile @@ -0,0 +1,31 @@ +FROM python:2.7-buster + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install Python libraries. +RUN python -m pip install --no-cache-dir --upgrade \ + pip \ + setuptools \ + tox \ + wheel diff --git a/kokoro/linux/dockerfile/test/python35/Dockerfile b/kokoro/linux/dockerfile/test/python35/Dockerfile new file mode 100644 index 0000000000000..50ee184536190 --- /dev/null +++ b/kokoro/linux/dockerfile/test/python35/Dockerfile @@ -0,0 +1,31 @@ +FROM python:3.5-buster + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install Python libraries. +RUN python -m pip install --no-cache-dir --upgrade \ + pip \ + setuptools \ + tox \ + wheel diff --git a/kokoro/linux/dockerfile/test/python36/Dockerfile b/kokoro/linux/dockerfile/test/python36/Dockerfile new file mode 100644 index 0000000000000..742503e5a4174 --- /dev/null +++ b/kokoro/linux/dockerfile/test/python36/Dockerfile @@ -0,0 +1,31 @@ +FROM python:3.6-buster + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install Python libraries. +RUN python -m pip install --no-cache-dir --upgrade \ + pip \ + setuptools \ + tox \ + wheel diff --git a/kokoro/linux/dockerfile/test/python37/Dockerfile b/kokoro/linux/dockerfile/test/python37/Dockerfile new file mode 100644 index 0000000000000..ee108dd030125 --- /dev/null +++ b/kokoro/linux/dockerfile/test/python37/Dockerfile @@ -0,0 +1,31 @@ +FROM python:3.7-buster + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install Python libraries. +RUN python -m pip install --no-cache-dir --upgrade \ + pip \ + setuptools \ + tox \ + wheel diff --git a/kokoro/linux/dockerfile/test/python38/Dockerfile b/kokoro/linux/dockerfile/test/python38/Dockerfile new file mode 100644 index 0000000000000..56efc9d6bf39d --- /dev/null +++ b/kokoro/linux/dockerfile/test/python38/Dockerfile @@ -0,0 +1,31 @@ +FROM python:3.8-buster + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install Python libraries. +RUN python -m pip install --no-cache-dir --upgrade \ + pip \ + setuptools \ + tox \ + wheel diff --git a/kokoro/linux/dockerfile/test/python39/Dockerfile b/kokoro/linux/dockerfile/test/python39/Dockerfile new file mode 100644 index 0000000000000..ee7554dd644d7 --- /dev/null +++ b/kokoro/linux/dockerfile/test/python39/Dockerfile @@ -0,0 +1,31 @@ +FROM python:3.9-buster + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install Python libraries. +RUN python -m pip install --no-cache-dir --upgrade \ + pip \ + setuptools \ + tox \ + wheel diff --git a/kokoro/linux/dockerfile/test/ruby/Dockerfile b/kokoro/linux/dockerfile/test/ruby/Dockerfile new file mode 100644 index 0000000000000..b73bf84095a75 --- /dev/null +++ b/kokoro/linux/dockerfile/test/ruby/Dockerfile @@ -0,0 +1,39 @@ +FROM debian:jessie + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean + +# Install rvm +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys \ + 409B6B1796C275462A1703113804BB82D39DC0E3 \ + 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +RUN \curl -sSL https://get.rvm.io | bash -s master + +RUN /bin/bash -l -c "rvm install 2.3.8" +RUN /bin/bash -l -c "rvm install 2.4.5" +RUN /bin/bash -l -c "rvm install 2.5.1" +RUN /bin/bash -l -c "rvm install 2.6.0" +RUN /bin/bash -l -c "rvm install 2.7.0" +RUN /bin/bash -l -c "rvm install 3.0.0" + +RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" +RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" diff --git a/kokoro/linux/golang/build.sh b/kokoro/linux/golang/build.sh new file mode 100755 index 0000000000000..79cddff15ca2d --- /dev/null +++ b/kokoro/linux/golang/build.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERFILE_DIR=kokoro/linux/64-bit +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="golang" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/golang/continuous.cfg b/kokoro/linux/golang/continuous.cfg new file mode 100644 index 0000000000000..2282f78f047bc --- /dev/null +++ b/kokoro/linux/golang/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/golang/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/golang/presubmit.cfg b/kokoro/linux/golang/presubmit.cfg new file mode 100644 index 0000000000000..2282f78f047bc --- /dev/null +++ b/kokoro/linux/golang/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/golang/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/java_compatibility/build.sh b/kokoro/linux/java_compatibility/build.sh index b1ef27963f597..de88454fc7fa2 100755 --- a/kokoro/linux/java_compatibility/build.sh +++ b/kokoro/linux/java_compatibility/build.sh @@ -1,11 +1,17 @@ #!/bin/bash # -# Build file to set up and run tests +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. # Change to repo root cd $(dirname $0)/../../.. -# Prepare worker environment to run tests -source kokoro/linux/prepare_build_linux_rc - -./tests.sh java_compatibility +export DOCKERFILE_DIR=kokoro/linux/64-bit +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="java_compatibility" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/java_jdk7/build.sh b/kokoro/linux/java_jdk7/build.sh new file mode 100755 index 0000000000000..0a5604b426a63 --- /dev/null +++ b/kokoro/linux/java_jdk7/build.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERFILE_DIR=kokoro/linux/64-bit +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="java_jdk7" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/java_jdk7/continuous.cfg b/kokoro/linux/java_jdk7/continuous.cfg new file mode 100644 index 0000000000000..07a9df5f443f3 --- /dev/null +++ b/kokoro/linux/java_jdk7/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/java_jdk7/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/java_jdk7/presubmit.cfg b/kokoro/linux/java_jdk7/presubmit.cfg new file mode 100644 index 0000000000000..07a9df5f443f3 --- /dev/null +++ b/kokoro/linux/java_jdk7/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/java_jdk7/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/java_linkage_monitor/build.sh b/kokoro/linux/java_linkage_monitor/build.sh new file mode 100755 index 0000000000000..c447453f607db --- /dev/null +++ b/kokoro/linux/java_linkage_monitor/build.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +# The image of the Dockerfile sha1 is fetched from the organization +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/java_stretch +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="java_linkage_monitor" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/java_linkage_monitor/continuous.cfg b/kokoro/linux/java_linkage_monitor/continuous.cfg new file mode 100644 index 0000000000000..d0486cce416f5 --- /dev/null +++ b/kokoro/linux/java_linkage_monitor/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/java_linkage_monitor/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/java_linkage_monitor/presubmit.cfg b/kokoro/linux/java_linkage_monitor/presubmit.cfg new file mode 100644 index 0000000000000..c02a52f0fa619 --- /dev/null +++ b/kokoro/linux/java_linkage_monitor/presubmit.cfg @@ -0,0 +1,12 @@ +# Config file for running Linkage Monitor in Kokoro +# https://github.com/GoogleCloudPlatform/cloud-opensource-java/tree/master/linkage-monitor + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/java_linkage_monitor/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/java_oracle7/build.sh b/kokoro/linux/java_oracle7/build.sh new file mode 100755 index 0000000000000..9ab90dadf253d --- /dev/null +++ b/kokoro/linux/java_oracle7/build.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERFILE_DIR=kokoro/linux/64-bit +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="java_oracle7" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/java_oracle7/continuous.cfg b/kokoro/linux/java_oracle7/continuous.cfg new file mode 100644 index 0000000000000..610469b42c993 --- /dev/null +++ b/kokoro/linux/java_oracle7/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/java_oracle7/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/java_oracle7/presubmit.cfg b/kokoro/linux/java_oracle7/presubmit.cfg new file mode 100644 index 0000000000000..610469b42c993 --- /dev/null +++ b/kokoro/linux/java_oracle7/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/java_oracle7/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/javascript/build.sh b/kokoro/linux/javascript/build.sh new file mode 100755 index 0000000000000..e1e172310cf58 --- /dev/null +++ b/kokoro/linux/javascript/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/javascript +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="javascript" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/javascript/continuous.cfg b/kokoro/linux/javascript/continuous.cfg new file mode 100644 index 0000000000000..b42f522fe9c31 --- /dev/null +++ b/kokoro/linux/javascript/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/javascript/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/javascript/presubmit.cfg b/kokoro/linux/javascript/presubmit.cfg new file mode 100644 index 0000000000000..b42f522fe9c31 --- /dev/null +++ b/kokoro/linux/javascript/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/javascript/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/jenkins/make_test_output.py b/kokoro/linux/make_test_output.py similarity index 96% rename from jenkins/make_test_output.py rename to kokoro/linux/make_test_output.py index b1f2e2c0bb67f..985368534cb83 100644 --- a/jenkins/make_test_output.py +++ b/kokoro/linux/make_test_output.py @@ -17,11 +17,12 @@ finishes. """ -import os; -import sys; +import os +import sys from yattag import Doc from collections import defaultdict + def readtests(basedir): tests = defaultdict(dict) @@ -68,6 +69,7 @@ def readtests(basedir): return ret + def genxml(tests): doc, tag, text = Doc().tagtext() @@ -86,6 +88,7 @@ def genxml(tests): return doc.getvalue() + sys.stderr.write("make_test_output.py: writing XML from directory: " + - sys.argv[1] + "\n"); -print genxml(readtests(sys.argv[1])) + sys.argv[1] + "\n") +print(genxml(readtests(sys.argv[1]))) diff --git a/kokoro/linux/php80/build.sh b/kokoro/linux/php80/build.sh new file mode 100755 index 0000000000000..f17aec104f9b7 --- /dev/null +++ b/kokoro/linux/php80/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/php80 +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="php8.0_all" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/php80/continuous.cfg b/kokoro/linux/php80/continuous.cfg new file mode 100644 index 0000000000000..8426318bbee4d --- /dev/null +++ b/kokoro/linux/php80/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/php80/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/php80/presubmit.cfg b/kokoro/linux/php80/presubmit.cfg new file mode 100644 index 0000000000000..8426318bbee4d --- /dev/null +++ b/kokoro/linux/php80/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/php80/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/php_all/build.sh b/kokoro/linux/php_all/build.sh new file mode 100755 index 0000000000000..23468a70107eb --- /dev/null +++ b/kokoro/linux/php_all/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/php +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="php_all" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/php_all/continuous.cfg b/kokoro/linux/php_all/continuous.cfg new file mode 100644 index 0000000000000..dfa8037ef8246 --- /dev/null +++ b/kokoro/linux/php_all/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/php_all/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/php_all/presubmit.cfg b/kokoro/linux/php_all/presubmit.cfg new file mode 100644 index 0000000000000..dfa8037ef8246 --- /dev/null +++ b/kokoro/linux/php_all/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/php_all/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/prepare_build_linux_rc b/kokoro/linux/prepare_build_linux_rc deleted file mode 100644 index 4c3f255dd505e..0000000000000 --- a/kokoro/linux/prepare_build_linux_rc +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -# Source this rc script to prepare the environment for Linux builds - -# Set up dotnet -sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ trusty main" > /etc/apt/sources.list.d/dotnetdev.list' -sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 417A0893 -sudo apt-get update -sudo apt-get install -y dotnet-dev-1.0.4 diff --git a/kokoro/linux/pull_request_in_docker.sh b/kokoro/linux/pull_request_in_docker.sh new file mode 100755 index 0000000000000..a048c470315ac --- /dev/null +++ b/kokoro/linux/pull_request_in_docker.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# +# This is the script that runs inside Docker, once the image has been built, +# to execute all tests for the "pull request" project. + +WORKSPACE_BASE=`pwd` +MY_DIR="$(dirname "$0")" +TEST_SCRIPT=./tests.sh +BUILD_DIR=/tmp/protobuf + +set -e # exit immediately on error +set -x # display all commands + +# The protobuf repository is mounted into our Docker image, but read-only. +# We clone into a directory inside Docker (this is faster than cp). +rm -rf $BUILD_DIR +mkdir -p $BUILD_DIR +cd $BUILD_DIR +git clone /var/local/kokoro/protobuf +cd protobuf + +# Initialize any submodules: +git submodule update --init --recursive + +$TEST_SCRIPT $TEST_SET diff --git a/kokoro/linux/python/build.sh b/kokoro/linux/python/build.sh new file mode 100755 index 0000000000000..86964f55ef1d6 --- /dev/null +++ b/kokoro/linux/python/build.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERFILE_DIR=kokoro/linux/64-bit +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/python/continuous.cfg new file mode 100644 index 0000000000000..e2fc4136f07e3 --- /dev/null +++ b/kokoro/linux/python/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python/presubmit.cfg b/kokoro/linux/python/presubmit.cfg new file mode 100644 index 0000000000000..e2fc4136f07e3 --- /dev/null +++ b/kokoro/linux/python/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python27/build.sh b/kokoro/linux/python27/build.sh new file mode 100755 index 0000000000000..41531a15efe88 --- /dev/null +++ b/kokoro/linux/python27/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python27 +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python27" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python27/continuous.cfg b/kokoro/linux/python27/continuous.cfg new file mode 100644 index 0000000000000..dd98469a6fb60 --- /dev/null +++ b/kokoro/linux/python27/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python27/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python27/presubmit.cfg b/kokoro/linux/python27/presubmit.cfg new file mode 100644 index 0000000000000..dd98469a6fb60 --- /dev/null +++ b/kokoro/linux/python27/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python27/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python27_cpp/build.sh b/kokoro/linux/python27_cpp/build.sh new file mode 100755 index 0000000000000..1a972ee9f2611 --- /dev/null +++ b/kokoro/linux/python27_cpp/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python27 +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python27_cpp" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python27_cpp/continuous.cfg b/kokoro/linux/python27_cpp/continuous.cfg new file mode 100644 index 0000000000000..ace22d0077174 --- /dev/null +++ b/kokoro/linux/python27_cpp/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python27_cpp/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python27_cpp/presubmit.cfg b/kokoro/linux/python27_cpp/presubmit.cfg new file mode 100644 index 0000000000000..ace22d0077174 --- /dev/null +++ b/kokoro/linux/python27_cpp/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python27_cpp/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python35/build.sh b/kokoro/linux/python35/build.sh new file mode 100755 index 0000000000000..66ea03f0367ab --- /dev/null +++ b/kokoro/linux/python35/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python35 +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python35" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python35/continuous.cfg b/kokoro/linux/python35/continuous.cfg new file mode 100644 index 0000000000000..2b3e12cbb0cde --- /dev/null +++ b/kokoro/linux/python35/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python35/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python35/presubmit.cfg b/kokoro/linux/python35/presubmit.cfg new file mode 100644 index 0000000000000..2b3e12cbb0cde --- /dev/null +++ b/kokoro/linux/python35/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python35/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python35_cpp/build.sh b/kokoro/linux/python35_cpp/build.sh new file mode 100755 index 0000000000000..4d0dbd4986b29 --- /dev/null +++ b/kokoro/linux/python35_cpp/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python35 +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python35_cpp" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python35_cpp/continuous.cfg b/kokoro/linux/python35_cpp/continuous.cfg new file mode 100644 index 0000000000000..ad5cc8657adc7 --- /dev/null +++ b/kokoro/linux/python35_cpp/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python35_cpp/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python35_cpp/presubmit.cfg b/kokoro/linux/python35_cpp/presubmit.cfg new file mode 100644 index 0000000000000..ad5cc8657adc7 --- /dev/null +++ b/kokoro/linux/python35_cpp/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python35_cpp/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python36/build.sh b/kokoro/linux/python36/build.sh new file mode 100755 index 0000000000000..a483efc3027f1 --- /dev/null +++ b/kokoro/linux/python36/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python36 +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python36" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python36/continuous.cfg b/kokoro/linux/python36/continuous.cfg new file mode 100644 index 0000000000000..ee7f4888f8c76 --- /dev/null +++ b/kokoro/linux/python36/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python36/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python36/presubmit.cfg b/kokoro/linux/python36/presubmit.cfg new file mode 100644 index 0000000000000..ee7f4888f8c76 --- /dev/null +++ b/kokoro/linux/python36/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python36/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python36_cpp/build.sh b/kokoro/linux/python36_cpp/build.sh new file mode 100755 index 0000000000000..eb71bda92c48c --- /dev/null +++ b/kokoro/linux/python36_cpp/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python36 +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python36_cpp" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python36_cpp/continuous.cfg b/kokoro/linux/python36_cpp/continuous.cfg new file mode 100644 index 0000000000000..df9e7144943a8 --- /dev/null +++ b/kokoro/linux/python36_cpp/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python36_cpp/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python36_cpp/presubmit.cfg b/kokoro/linux/python36_cpp/presubmit.cfg new file mode 100644 index 0000000000000..df9e7144943a8 --- /dev/null +++ b/kokoro/linux/python36_cpp/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python36_cpp/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python37/build.sh b/kokoro/linux/python37/build.sh new file mode 100755 index 0000000000000..2117a271ce647 --- /dev/null +++ b/kokoro/linux/python37/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python37 +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python37" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python37/continuous.cfg b/kokoro/linux/python37/continuous.cfg new file mode 100644 index 0000000000000..9fa20c19757ef --- /dev/null +++ b/kokoro/linux/python37/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python37/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python37/presubmit.cfg b/kokoro/linux/python37/presubmit.cfg new file mode 100644 index 0000000000000..9fa20c19757ef --- /dev/null +++ b/kokoro/linux/python37/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python37/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python37_cpp/build.sh b/kokoro/linux/python37_cpp/build.sh new file mode 100755 index 0000000000000..3126b481e3722 --- /dev/null +++ b/kokoro/linux/python37_cpp/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python37 +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python37_cpp" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python37_cpp/continuous.cfg b/kokoro/linux/python37_cpp/continuous.cfg new file mode 100644 index 0000000000000..49c441ffe8925 --- /dev/null +++ b/kokoro/linux/python37_cpp/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python37_cpp/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python37_cpp/presubmit.cfg b/kokoro/linux/python37_cpp/presubmit.cfg new file mode 100644 index 0000000000000..49c441ffe8925 --- /dev/null +++ b/kokoro/linux/python37_cpp/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python37_cpp/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python38/build.sh b/kokoro/linux/python38/build.sh new file mode 100755 index 0000000000000..299c7ba6f3bdb --- /dev/null +++ b/kokoro/linux/python38/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python38 +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python38" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python38/continuous.cfg b/kokoro/linux/python38/continuous.cfg new file mode 100644 index 0000000000000..76425d2f193ae --- /dev/null +++ b/kokoro/linux/python38/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python38/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python38/presubmit.cfg b/kokoro/linux/python38/presubmit.cfg new file mode 100644 index 0000000000000..76425d2f193ae --- /dev/null +++ b/kokoro/linux/python38/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python38/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python38_cpp/build.sh b/kokoro/linux/python38_cpp/build.sh new file mode 100755 index 0000000000000..b43859b988a9f --- /dev/null +++ b/kokoro/linux/python38_cpp/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python38 +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python38_cpp" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python38_cpp/continuous.cfg b/kokoro/linux/python38_cpp/continuous.cfg new file mode 100644 index 0000000000000..1e8888cc5d1bc --- /dev/null +++ b/kokoro/linux/python38_cpp/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python38_cpp/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python38_cpp/presubmit.cfg b/kokoro/linux/python38_cpp/presubmit.cfg new file mode 100644 index 0000000000000..1e8888cc5d1bc --- /dev/null +++ b/kokoro/linux/python38_cpp/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python38_cpp/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python39/build.sh b/kokoro/linux/python39/build.sh new file mode 100755 index 0000000000000..497dc66e7c09a --- /dev/null +++ b/kokoro/linux/python39/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python39 +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python39" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python39/continuous.cfg b/kokoro/linux/python39/continuous.cfg new file mode 100644 index 0000000000000..b03bc908df5e0 --- /dev/null +++ b/kokoro/linux/python39/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python39/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python39/presubmit.cfg b/kokoro/linux/python39/presubmit.cfg new file mode 100644 index 0000000000000..b03bc908df5e0 --- /dev/null +++ b/kokoro/linux/python39/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python39/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python39_cpp/build.sh b/kokoro/linux/python39_cpp/build.sh new file mode 100755 index 0000000000000..f45d2ec7c3dc2 --- /dev/null +++ b/kokoro/linux/python39_cpp/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python39 +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python39_cpp" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python39_cpp/continuous.cfg b/kokoro/linux/python39_cpp/continuous.cfg new file mode 100644 index 0000000000000..dd84fbe86bd0c --- /dev/null +++ b/kokoro/linux/python39_cpp/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python39_cpp/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python39_cpp/presubmit.cfg b/kokoro/linux/python39_cpp/presubmit.cfg new file mode 100644 index 0000000000000..dd84fbe86bd0c --- /dev/null +++ b/kokoro/linux/python39_cpp/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python39_cpp/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python_compatibility/build.sh b/kokoro/linux/python_compatibility/build.sh index 041e65ffb65ef..1ba35394d1c9f 100755 --- a/kokoro/linux/python_compatibility/build.sh +++ b/kokoro/linux/python_compatibility/build.sh @@ -1,11 +1,17 @@ #!/bin/bash # -# Build file to set up and run tests +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. # Change to repo root cd $(dirname $0)/../../.. -# Prepare worker environment to run tests -source kokoro/linux/prepare_build_linux_rc - -./tests.sh python_compatibility +export DOCKERFILE_DIR=kokoro/linux/64-bit +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python_compatibility" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python_cpp/build.sh b/kokoro/linux/python_cpp/build.sh new file mode 100755 index 0000000000000..add6465190950 --- /dev/null +++ b/kokoro/linux/python_cpp/build.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERFILE_DIR=kokoro/linux/64-bit +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="python_cpp" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python_cpp/continuous.cfg b/kokoro/linux/python_cpp/continuous.cfg new file mode 100644 index 0000000000000..b1b0e550ffd44 --- /dev/null +++ b/kokoro/linux/python_cpp/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python_cpp/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/python_cpp/presubmit.cfg b/kokoro/linux/python_cpp/presubmit.cfg new file mode 100644 index 0000000000000..b1b0e550ffd44 --- /dev/null +++ b/kokoro/linux/python_cpp/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/python_cpp/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/ruby23/build.sh b/kokoro/linux/ruby23/build.sh new file mode 100755 index 0000000000000..503a320de22e7 --- /dev/null +++ b/kokoro/linux/ruby23/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/ruby +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="ruby23" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/ruby23/continuous.cfg b/kokoro/linux/ruby23/continuous.cfg new file mode 100644 index 0000000000000..f5c64988bfc7c --- /dev/null +++ b/kokoro/linux/ruby23/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/ruby23/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/ruby23/presubmit.cfg b/kokoro/linux/ruby23/presubmit.cfg new file mode 100644 index 0000000000000..f5c64988bfc7c --- /dev/null +++ b/kokoro/linux/ruby23/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/ruby23/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/ruby24/build.sh b/kokoro/linux/ruby24/build.sh new file mode 100755 index 0000000000000..68585aabc0a59 --- /dev/null +++ b/kokoro/linux/ruby24/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/ruby +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="ruby24" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/ruby24/continuous.cfg b/kokoro/linux/ruby24/continuous.cfg new file mode 100644 index 0000000000000..a1ccfc0b8ba85 --- /dev/null +++ b/kokoro/linux/ruby24/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/ruby24/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/ruby24/presubmit.cfg b/kokoro/linux/ruby24/presubmit.cfg new file mode 100644 index 0000000000000..a1ccfc0b8ba85 --- /dev/null +++ b/kokoro/linux/ruby24/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/ruby24/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/ruby25/build.sh b/kokoro/linux/ruby25/build.sh new file mode 100755 index 0000000000000..1e82ec5f4c68f --- /dev/null +++ b/kokoro/linux/ruby25/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/ruby +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="ruby25" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/ruby25/continuous.cfg b/kokoro/linux/ruby25/continuous.cfg new file mode 100644 index 0000000000000..dee2db033fc5e --- /dev/null +++ b/kokoro/linux/ruby25/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/ruby25/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/ruby25/presubmit.cfg b/kokoro/linux/ruby25/presubmit.cfg new file mode 100644 index 0000000000000..dee2db033fc5e --- /dev/null +++ b/kokoro/linux/ruby25/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/ruby25/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/ruby26/build.sh b/kokoro/linux/ruby26/build.sh new file mode 100755 index 0000000000000..72d2d45669cbd --- /dev/null +++ b/kokoro/linux/ruby26/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/ruby +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="ruby26" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/ruby26/continuous.cfg b/kokoro/linux/ruby26/continuous.cfg new file mode 100644 index 0000000000000..47790656704b3 --- /dev/null +++ b/kokoro/linux/ruby26/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/ruby26/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/ruby26/presubmit.cfg b/kokoro/linux/ruby26/presubmit.cfg new file mode 100644 index 0000000000000..47790656704b3 --- /dev/null +++ b/kokoro/linux/ruby26/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/ruby26/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/ruby27/build.sh b/kokoro/linux/ruby27/build.sh new file mode 100755 index 0000000000000..c38ee36e584a3 --- /dev/null +++ b/kokoro/linux/ruby27/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/ruby +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="ruby27" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/ruby27/continuous.cfg b/kokoro/linux/ruby27/continuous.cfg new file mode 100644 index 0000000000000..9cce8c90e1ffc --- /dev/null +++ b/kokoro/linux/ruby27/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/ruby27/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/ruby27/presubmit.cfg b/kokoro/linux/ruby27/presubmit.cfg new file mode 100644 index 0000000000000..9cce8c90e1ffc --- /dev/null +++ b/kokoro/linux/ruby27/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/ruby27/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/ruby30/build.sh b/kokoro/linux/ruby30/build.sh new file mode 100755 index 0000000000000..9e44575652bb9 --- /dev/null +++ b/kokoro/linux/ruby30/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/ruby +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="ruby30" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/ruby30/continuous.cfg b/kokoro/linux/ruby30/continuous.cfg new file mode 100644 index 0000000000000..b03a3352f4872 --- /dev/null +++ b/kokoro/linux/ruby30/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/ruby30/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/ruby30/presubmit.cfg b/kokoro/linux/ruby30/presubmit.cfg new file mode 100644 index 0000000000000..b03a3352f4872 --- /dev/null +++ b/kokoro/linux/ruby30/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/ruby30/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/macos/jruby/build.sh b/kokoro/macos/jruby/build.sh deleted file mode 100755 index c82eaebfbd59b..0000000000000 --- a/kokoro/macos/jruby/build.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -# -# Build file to set up and run tests - -# Change to repo root -cd $(dirname $0)/../../.. - -# Prepare worker environment to run tests -source kokoro/macos/prepare_build_macos_rc - -./tests.sh jruby diff --git a/kokoro/macos/jruby/continuous.cfg b/kokoro/macos/jruby/continuous.cfg deleted file mode 100644 index f1310fd34980b..0000000000000 --- a/kokoro/macos/jruby/continuous.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/macos/jruby/build.sh" -timeout_mins: 1440 diff --git a/kokoro/macos/jruby/presubmit.cfg b/kokoro/macos/jruby/presubmit.cfg deleted file mode 100644 index f1310fd34980b..0000000000000 --- a/kokoro/macos/jruby/presubmit.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/macos/jruby/build.sh" -timeout_mins: 1440 diff --git a/kokoro/macos/objectivec_cocoapods_integration/build.sh b/kokoro/macos/objectivec_cocoapods_integration/build.sh index f96d2899d9093..8f3c9b4c15d64 100755 --- a/kokoro/macos/objectivec_cocoapods_integration/build.sh +++ b/kokoro/macos/objectivec_cocoapods_integration/build.sh @@ -6,6 +6,7 @@ cd $(dirname $0)/../../.. # Prepare worker environment to run tests +KOKORO_INSTALL_COCOAPODS=yes source kokoro/macos/prepare_build_macos_rc ./tests.sh objectivec_cocoapods_integration diff --git a/kokoro/macos/php5.6_mac/build.sh b/kokoro/macos/php5.6_mac/build.sh deleted file mode 100755 index 74878898faa71..0000000000000 --- a/kokoro/macos/php5.6_mac/build.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -# -# Build file to set up and run tests - -# Change to repo root -cd $(dirname $0)/../../.. - -# Prepare worker environment to run tests -source kokoro/macos/prepare_build_macos_rc - -./tests.sh php5.6_mac diff --git a/kokoro/macos/php5.6_mac/continuous.cfg b/kokoro/macos/php5.6_mac/continuous.cfg deleted file mode 100644 index ff345e9fc41d0..0000000000000 --- a/kokoro/macos/php5.6_mac/continuous.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/macos/php5.6_mac/build.sh" -timeout_mins: 1440 diff --git a/kokoro/macos/php5.6_mac/presubmit.cfg b/kokoro/macos/php5.6_mac/presubmit.cfg deleted file mode 100644 index ff345e9fc41d0..0000000000000 --- a/kokoro/macos/php5.6_mac/presubmit.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/macos/php5.6_mac/build.sh" -timeout_mins: 1440 diff --git a/kokoro/macos/php7.3_mac/build.sh b/kokoro/macos/php7.3_mac/build.sh new file mode 100755 index 0000000000000..2d2f679da2ca0 --- /dev/null +++ b/kokoro/macos/php7.3_mac/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# +# Build file to set up and run tests + +# Change to repo root +cd $(dirname $0)/../../.. + +# Prepare worker environment to run tests +source kokoro/macos/prepare_build_macos_rc + +./tests.sh php7.3_mac diff --git a/kokoro/macos/php7.3_mac/continuous.cfg b/kokoro/macos/php7.3_mac/continuous.cfg new file mode 100644 index 0000000000000..9a717451d373b --- /dev/null +++ b/kokoro/macos/php7.3_mac/continuous.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/php7.3_mac/build.sh" +timeout_mins: 1440 diff --git a/kokoro/macos/php7.3_mac/presubmit.cfg b/kokoro/macos/php7.3_mac/presubmit.cfg new file mode 100644 index 0000000000000..9a717451d373b --- /dev/null +++ b/kokoro/macos/php7.3_mac/presubmit.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/php7.3_mac/build.sh" +timeout_mins: 1440 diff --git a/kokoro/macos/prepare_build_macos_rc b/kokoro/macos/prepare_build_macos_rc index 2b9f4df25f3ab..d94dd543fd5b4 100755 --- a/kokoro/macos/prepare_build_macos_rc +++ b/kokoro/macos/prepare_build_macos_rc @@ -2,10 +2,16 @@ # # This script sets up a Kokoro MacOS worker for running Protobuf tests +set -eux + ## # Select Xcode version -export DEVELOPER_DIR=/Applications/Xcode_8.1.app/Contents/Developer +# Remember to update the Xcode version when Xcode_11.3.app is not available. +# If xcode is not available, it will probably encounter the failure for +# "autom4te: need GNU m4 1.4 or later: /usr/bin/m4" +# go/kokoro/userdocs/macos/selecting_xcode.md for more information. +export DEVELOPER_DIR=/Applications/Xcode_11.3.app/Contents/Developer ## # Select C/C++ compilers @@ -14,20 +20,65 @@ export CC=gcc export CXX=g++ ## -# Install Brew and core softwares +# Brew: update, then upgrade the installed tools to current version and install +# some needed ones not in the Kokoro base image. This ensure current versions +# of CMake, autotools, etc. + +# But first... +# +# The transitive deps of the installed tools need protobuf, but Kokoro manually +# installed it outside of brew so it needs to be removed so brew can install the +# tools (and a newer version of protobuf). g/kokoro-users/7FRvQMUdN40 about why +# it is a manual install vs. a brew install in the first place. +sudo rm -rf \ + /usr/local/include/google/protobuf \ + /usr/local/bin/protoc +# Likewise, updating python can have issues because of some existing binaries. +sudo rm -rf \ + /usr/local/bin/2to3* \ + /usr/local/bin/idle3* \ + /usr/local/bin/pip3 \ + /usr/local/bin/pydoc3* \ + /usr/local/bin/python3* \ + /usr/local/bin/pyvenv* -ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" -brew tap homebrew/homebrew-php -brew install autoconf automake ccache cmake gflags gpg gpg2 libtool maven node pcre php56 ruby wget +git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow +git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow + +brew update +brew upgrade + +## +# Install Ruby + +if [[ "${KOKORO_INSTALL_RUBY:-}" == "yes" ]] ; then + brew install ruby +fi + +## +# Install Cocoapods + +if [[ "${KOKORO_INSTALL_COCOAPODS:-}" == "yes" ]] ; then + # The existing cocoapods was installed via gem, but that doesn't work well + # with the overlap in deps with things managed by brew (errors around ruby + # versions, etc.); so remove it and install in via brew instead. + gem uninstall -a "$(gem list | grep cocoapods | cut -d ' ' -f 1)" + brew install cocoapods +fi ## # Install Tox -sudo pip install tox==2.4.1 +if [[ "${KOKORO_INSTALL_TOX:-}" == "yes" ]] ; then + sudo python3 -m pip install --upgrade pip tox +fi ## # Install RVM -gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 -command curl -sSL https://rvm.io/mpapis.asc | gpg2 --import - -curl -sSL https://get.rvm.io | bash -s stable --ruby +if [[ "${KOKORO_INSTALL_RVM:-}" == "yes" ]] ; then + curl -sSL https://rvm.io/mpapis.asc | gpg --import - + curl -sSL https://rvm.io/pkuczynski.asc | gpg --import - + + curl -sSL https://get.rvm.io | bash -s master --ruby +fi diff --git a/kokoro/macos/python/build.sh b/kokoro/macos/python/build.sh index 6b17b95446474..388e24b4ac128 100755 --- a/kokoro/macos/python/build.sh +++ b/kokoro/macos/python/build.sh @@ -6,6 +6,7 @@ cd $(dirname $0)/../../.. # Prepare worker environment to run tests +KOKORO_INSTALL_TOX=yes source kokoro/macos/prepare_build_macos_rc ./tests.sh python diff --git a/kokoro/macos/python_cpp/build.sh b/kokoro/macos/python_cpp/build.sh index cb53def9d31a7..f86dd6f76e49e 100755 --- a/kokoro/macos/python_cpp/build.sh +++ b/kokoro/macos/python_cpp/build.sh @@ -6,6 +6,7 @@ cd $(dirname $0)/../../.. # Prepare worker environment to run tests +KOKORO_INSTALL_TOX=yes source kokoro/macos/prepare_build_macos_rc g++ --version diff --git a/kokoro/macos/ruby21/build.sh b/kokoro/macos/ruby21/build.sh deleted file mode 100755 index 748ea65595d55..0000000000000 --- a/kokoro/macos/ruby21/build.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -# -# Build file to set up and run tests - -# Change to repo root -cd $(dirname $0)/../../.. - -# Prepare worker environment to run tests -source kokoro/macos/prepare_build_macos_rc - -./tests.sh ruby21 diff --git a/kokoro/macos/ruby21/continuous.cfg b/kokoro/macos/ruby21/continuous.cfg deleted file mode 100644 index 489796daf28b6..0000000000000 --- a/kokoro/macos/ruby21/continuous.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/macos/ruby21/build.sh" -timeout_mins: 1440 diff --git a/kokoro/macos/ruby21/presubmit.cfg b/kokoro/macos/ruby21/presubmit.cfg deleted file mode 100644 index 489796daf28b6..0000000000000 --- a/kokoro/macos/ruby21/presubmit.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/macos/ruby21/build.sh" -timeout_mins: 1440 diff --git a/kokoro/macos/ruby22/build.sh b/kokoro/macos/ruby22/build.sh deleted file mode 100755 index 5c4de42952bf8..0000000000000 --- a/kokoro/macos/ruby22/build.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -# -# Build file to set up and run tests - -# Change to repo root -cd $(dirname $0)/../../.. - -# Prepare worker environment to run tests -source kokoro/macos/prepare_build_macos_rc - -./tests.sh ruby22 diff --git a/kokoro/macos/ruby22/continuous.cfg b/kokoro/macos/ruby22/continuous.cfg deleted file mode 100644 index d27054417ae4d..0000000000000 --- a/kokoro/macos/ruby22/continuous.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/macos/ruby22/build.sh" -timeout_mins: 1440 diff --git a/kokoro/macos/ruby22/presubmit.cfg b/kokoro/macos/ruby22/presubmit.cfg deleted file mode 100644 index d27054417ae4d..0000000000000 --- a/kokoro/macos/ruby22/presubmit.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/macos/ruby22/build.sh" -timeout_mins: 1440 diff --git a/kokoro/macos/ruby23/build.sh b/kokoro/macos/ruby23/build.sh new file mode 100755 index 0000000000000..9317838781cea --- /dev/null +++ b/kokoro/macos/ruby23/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# +# Build file to set up and run tests + +# Change to repo root +cd $(dirname $0)/../../.. + +# Prepare worker environment to run tests +KOKORO_INSTALL_RUBY=yes +KOKORO_INSTALL_RVM=yes +source kokoro/macos/prepare_build_macos_rc + +./tests.sh ruby23 diff --git a/kokoro/macos/ruby23/continuous.cfg b/kokoro/macos/ruby23/continuous.cfg new file mode 100644 index 0000000000000..c9b1f61284af3 --- /dev/null +++ b/kokoro/macos/ruby23/continuous.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/ruby23/build.sh" +timeout_mins: 1440 diff --git a/kokoro/macos/ruby23/presubmit.cfg b/kokoro/macos/ruby23/presubmit.cfg new file mode 100644 index 0000000000000..c9b1f61284af3 --- /dev/null +++ b/kokoro/macos/ruby23/presubmit.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/ruby23/build.sh" +timeout_mins: 1440 diff --git a/kokoro/macos/ruby24/build.sh b/kokoro/macos/ruby24/build.sh new file mode 100755 index 0000000000000..51bb2e603b8cf --- /dev/null +++ b/kokoro/macos/ruby24/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# +# Build file to set up and run tests + +# Change to repo root +cd $(dirname $0)/../../.. + +# Prepare worker environment to run tests +KOKORO_INSTALL_RUBY=yes +KOKORO_INSTALL_RVM=yes +source kokoro/macos/prepare_build_macos_rc + +./tests.sh ruby24 diff --git a/kokoro/macos/ruby24/continuous.cfg b/kokoro/macos/ruby24/continuous.cfg new file mode 100644 index 0000000000000..fada028fc502e --- /dev/null +++ b/kokoro/macos/ruby24/continuous.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/ruby24/build.sh" +timeout_mins: 1440 diff --git a/kokoro/macos/ruby24/presubmit.cfg b/kokoro/macos/ruby24/presubmit.cfg new file mode 100644 index 0000000000000..fada028fc502e --- /dev/null +++ b/kokoro/macos/ruby24/presubmit.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/ruby24/build.sh" +timeout_mins: 1440 diff --git a/kokoro/macos/ruby25/build.sh b/kokoro/macos/ruby25/build.sh new file mode 100755 index 0000000000000..ba2d0a4d1926f --- /dev/null +++ b/kokoro/macos/ruby25/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# +# Build file to set up and run tests + +# Change to repo root +cd $(dirname $0)/../../.. + +# Prepare worker environment to run tests +KOKORO_INSTALL_RUBY=yes +KOKORO_INSTALL_RVM=yes +source kokoro/macos/prepare_build_macos_rc + +./tests.sh ruby25 diff --git a/kokoro/macos/ruby25/continuous.cfg b/kokoro/macos/ruby25/continuous.cfg new file mode 100644 index 0000000000000..b3755e4104489 --- /dev/null +++ b/kokoro/macos/ruby25/continuous.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/ruby25/build.sh" +timeout_mins: 1440 diff --git a/kokoro/macos/ruby25/presubmit.cfg b/kokoro/macos/ruby25/presubmit.cfg new file mode 100644 index 0000000000000..b3755e4104489 --- /dev/null +++ b/kokoro/macos/ruby25/presubmit.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/ruby25/build.sh" +timeout_mins: 1440 diff --git a/kokoro/macos/ruby26/build.sh b/kokoro/macos/ruby26/build.sh new file mode 100755 index 0000000000000..5a4c2432227e8 --- /dev/null +++ b/kokoro/macos/ruby26/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# +# Build file to set up and run tests + +# Change to repo root +cd $(dirname $0)/../../.. + +# Prepare worker environment to run tests +KOKORO_INSTALL_RUBY=yes +KOKORO_INSTALL_RVM=yes +source kokoro/macos/prepare_build_macos_rc + +./tests.sh ruby26 diff --git a/kokoro/macos/ruby26/continuous.cfg b/kokoro/macos/ruby26/continuous.cfg new file mode 100644 index 0000000000000..688f63c2bc3ef --- /dev/null +++ b/kokoro/macos/ruby26/continuous.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/ruby26/build.sh" +timeout_mins: 1440 diff --git a/kokoro/macos/ruby26/presubmit.cfg b/kokoro/macos/ruby26/presubmit.cfg new file mode 100644 index 0000000000000..688f63c2bc3ef --- /dev/null +++ b/kokoro/macos/ruby26/presubmit.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/ruby26/build.sh" +timeout_mins: 1440 diff --git a/kokoro/macos/ruby27/build.sh b/kokoro/macos/ruby27/build.sh new file mode 100755 index 0000000000000..b1529b9da02b3 --- /dev/null +++ b/kokoro/macos/ruby27/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# +# Build file to set up and run tests + +# Change to repo root +cd $(dirname $0)/../../.. + +# Prepare worker environment to run tests +KOKORO_INSTALL_RUBY=yes +KOKORO_INSTALL_RVM=yes +source kokoro/macos/prepare_build_macos_rc + +./tests.sh ruby27 diff --git a/kokoro/macos/ruby27/continuous.cfg b/kokoro/macos/ruby27/continuous.cfg new file mode 100644 index 0000000000000..b10b455da3fbf --- /dev/null +++ b/kokoro/macos/ruby27/continuous.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/ruby27/build.sh" +timeout_mins: 1440 diff --git a/kokoro/macos/ruby27/presubmit.cfg b/kokoro/macos/ruby27/presubmit.cfg new file mode 100644 index 0000000000000..b10b455da3fbf --- /dev/null +++ b/kokoro/macos/ruby27/presubmit.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/ruby27/build.sh" +timeout_mins: 1440 diff --git a/kokoro/macos/ruby30/build.sh b/kokoro/macos/ruby30/build.sh new file mode 100755 index 0000000000000..6b9bfb3215738 --- /dev/null +++ b/kokoro/macos/ruby30/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# +# Build file to set up and run tests + +# Change to repo root +cd $(dirname $0)/../../.. + +# Prepare worker environment to run tests +KOKORO_INSTALL_RUBY=yes +KOKORO_INSTALL_RVM=yes +source kokoro/macos/prepare_build_macos_rc + +./tests.sh ruby30 diff --git a/kokoro/macos/ruby30/continuous.cfg b/kokoro/macos/ruby30/continuous.cfg new file mode 100644 index 0000000000000..d5051170bef0f --- /dev/null +++ b/kokoro/macos/ruby30/continuous.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/ruby30/build.sh" +timeout_mins: 1440 diff --git a/kokoro/macos/ruby30/presubmit.cfg b/kokoro/macos/ruby30/presubmit.cfg new file mode 100644 index 0000000000000..d5051170bef0f --- /dev/null +++ b/kokoro/macos/ruby30/presubmit.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/ruby30/build.sh" +timeout_mins: 1440 diff --git a/kokoro/release/collect_all_artifacts.cfg b/kokoro/release/collect_all_artifacts.cfg new file mode 100644 index 0000000000000..3da1a7c49a02c --- /dev/null +++ b/kokoro/release/collect_all_artifacts.cfg @@ -0,0 +1,7 @@ +build_file: "protobuf/kokoro/release/collect_all_artifacts.sh" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/collect_all_artifacts.sh b/kokoro/release/collect_all_artifacts.sh new file mode 100755 index 0000000000000..3372a01975e0c --- /dev/null +++ b/kokoro/release/collect_all_artifacts.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +set -ex + +# Change to repo root. +cd $(dirname $0)/../.. + +# Initialize any submodules. +git submodule update --init --recursive + +# The directory with all resulting artifacts +mkdir -p artifacts + +# Artifacts from all predecessor jobs get copied to this directory by kokoro +INPUT_ARTIFACTS_DIR="${KOKORO_GFILE_DIR}/github/protobuf" + +# TODO(jtattermusch): remove listing the files, but for now it make it easier +# to iterate on the script. +ls -R ${INPUT_ARTIFACTS_DIR} + +# ==================================== +# Copy to expose all the artifacts from the predecessor jobs to the output +# TODO(jtattermusch): the directory layout of the artifact builds is pretty messy, +# so will be the output artifacts of this job. +cp -r ${INPUT_ARTIFACTS_DIR}/* artifacts + +# ==================================== +# Build Google.Protobuf.Tools C# nuget +# The reason it's being done in this script is that we need access to protoc binaries +# built on multiple platform (the build is performed by the "build artifact" step) +# and adding and extra chained build just for building the Google.Protobuf.Tools +# nuget seems like an overkill. +cd csharp +mkdir -p protoc/windows_x86 +mkdir -p protoc/windows_x64 +cp ${INPUT_ARTIFACTS_DIR}/build32/Release/protoc.exe protoc/windows_x86/protoc.exe +cp ${INPUT_ARTIFACTS_DIR}/build64/Release/protoc.exe protoc/windows_x64/protoc.exe + +mkdir -p protoc/linux_x86 +mkdir -p protoc/linux_x64 +# Because of maven unrelated reasonse the linux protoc binaries have a dummy .exe extension. +# For the Google.Protobuf.Tools nuget, we don't want that exception, so we just remove it. +cp ${INPUT_ARTIFACTS_DIR}/protoc-artifacts/target/linux/x86_32/protoc.exe protoc/linux_x86/protoc +cp ${INPUT_ARTIFACTS_DIR}/protoc-artifacts/target/linux/x86_64/protoc.exe protoc/linux_x64/protoc + +mkdir -p protoc/macosx_x64 +cp ${INPUT_ARTIFACTS_DIR}/build64/src/protoc protoc/macosx_x64/protoc + +# Install nuget (will also install mono) +# TODO(jtattermusch): use "mono:5.14" docker image instead so we don't have to apt-get install +sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF +echo "deb https://download.mono-project.com/repo/ubuntu stable-xenial main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list +sudo apt update +sudo apt-get install -y nuget + +nuget pack Google.Protobuf.Tools.nuspec + +# Copy the nupkg to the output artifacts +cp Google.Protobuf.Tools.*.nupkg ../artifacts diff --git a/kokoro/release/csharp/windows/build_nuget.bat b/kokoro/release/csharp/windows/build_nuget.bat new file mode 100644 index 0000000000000..590c391dd4699 --- /dev/null +++ b/kokoro/release/csharp/windows/build_nuget.bat @@ -0,0 +1,17 @@ +@rem enter repo root +cd /d %~dp0\..\..\..\.. + +cd csharp + +@rem Install dotnet SDK +powershell -File install_dotnet_sdk.ps1 +set PATH=%LOCALAPPDATA%\Microsoft\dotnet;%PATH% + +@rem Disable some unwanted dotnet options +set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true +set DOTNET_CLI_TELEMETRY_OPTOUT=true + +@rem Work around https://github.com/dotnet/core/issues/5881 +dotnet nuget locals all --clear + +call build_packages.bat diff --git a/kokoro/release/csharp/windows/continuous.cfg b/kokoro/release/csharp/windows/continuous.cfg new file mode 100644 index 0000000000000..f508c65bda0fe --- /dev/null +++ b/kokoro/release/csharp/windows/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/release/csharp/windows/build_nuget.bat" +timeout_mins: 60 + +action { + define_artifacts { + regex: "**/*.nupkg" + } +} diff --git a/kokoro/release/csharp/windows/presubmit.cfg b/kokoro/release/csharp/windows/presubmit.cfg new file mode 100644 index 0000000000000..f508c65bda0fe --- /dev/null +++ b/kokoro/release/csharp/windows/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/release/csharp/windows/build_nuget.bat" +timeout_mins: 60 + +action { + define_artifacts { + regex: "**/*.nupkg" + } +} diff --git a/kokoro/release/csharp/windows/release.cfg b/kokoro/release/csharp/windows/release.cfg new file mode 100644 index 0000000000000..f508c65bda0fe --- /dev/null +++ b/kokoro/release/csharp/windows/release.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/release/csharp/windows/build_nuget.bat" +timeout_mins: 60 + +action { + define_artifacts { + regex: "**/*.nupkg" + } +} diff --git a/kokoro/release/protoc/linux/build.sh b/kokoro/release/protoc/linux/build.sh new file mode 100755 index 0000000000000..efc3ee62caaba --- /dev/null +++ b/kokoro/release/protoc/linux/build.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +set -x + +# Change to repo root. +cd $(dirname $0)/../../../.. + +# Initialize any submodules. +git submodule update --init --recursive + +# Generate the configure script. +./autogen.sh + +# Cross-build for aarch64, ppc64le and s390x. Note: we do these builds first to avoid +# file permission issues. The Docker builds will create directories owned by +# root, which causes problems if we try to add new artifacts to those +# directories afterward. + +sudo apt install -y g++-aarch64-linux-gnu +protoc-artifacts/build-protoc.sh linux aarch_64 protoc + +sudo apt install -y g++-powerpc64le-linux-gnu +protoc-artifacts/build-protoc.sh linux ppcle_64 protoc + +sudo apt install -y g++-s390x-linux-gnu +protoc-artifacts/build-protoc.sh linux s390x protoc + +# Use docker image to build linux artifacts. +DOCKER_IMAGE_NAME=protobuf/protoc_$(sha1sum protoc-artifacts/Dockerfile | cut -f1 -d " ") +docker pull $DOCKER_IMAGE_NAME + +docker run -v $(pwd):/var/local/protobuf --rm $DOCKER_IMAGE_NAME \ + bash -l /var/local/protobuf/protoc-artifacts/build-protoc.sh \ + linux x86_64 protoc || { + echo "Failed to build protoc for linux + x86_64." + exit 1 +} + +docker run -v $(pwd):/var/local/protobuf --rm $DOCKER_IMAGE_NAME \ + bash -l /var/local/protobuf/protoc-artifacts/build-protoc.sh \ + linux x86_32 protoc || { + echo "Failed to build protoc for linux + x86_32." + exit 1 +} diff --git a/kokoro/release/protoc/linux/release.cfg b/kokoro/release/protoc/linux/release.cfg new file mode 100644 index 0000000000000..4d8b7b612f1d8 --- /dev/null +++ b/kokoro/release/protoc/linux/release.cfg @@ -0,0 +1,7 @@ +build_file: "protobuf/kokoro/release/protoc/linux/build.sh" + +action { + define_artifacts { + regex: "**/protoc.exe" + } +} diff --git a/kokoro/release/protoc/macos/build.sh b/kokoro/release/protoc/macos/build.sh new file mode 100755 index 0000000000000..47c9bfa9685ed --- /dev/null +++ b/kokoro/release/protoc/macos/build.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -ex +CXXFLAGS_COMMON="-std=c++14 -DNDEBUG -mmacosx-version-min=10.9" + +cd github/protobuf +./autogen.sh + +mkdir build64 && cd build64 +export CXXFLAGS="$CXXFLAGS_COMMON -m64" +../configure --disable-shared +make -j4 +file src/protoc +otool -L src/protoc | grep dylib +cd .. diff --git a/kokoro/release/protoc/macos/release.cfg b/kokoro/release/protoc/macos/release.cfg new file mode 100644 index 0000000000000..da903d0316073 --- /dev/null +++ b/kokoro/release/protoc/macos/release.cfg @@ -0,0 +1,8 @@ +# Configuration for Mac OSX protoc release builds +build_file: "protobuf/kokoro/release/protoc/macos/build.sh" + +action { + define_artifacts { + regex: "**/protoc" + } +} diff --git a/kokoro/release/protoc/windows/build.bat b/kokoro/release/protoc/windows/build.bat new file mode 100644 index 0000000000000..ae0fa94a106e7 --- /dev/null +++ b/kokoro/release/protoc/windows/build.bat @@ -0,0 +1,27 @@ +set PATH=C:\Program Files (x86)\MSBuild\14.0\bin\;%PATH% +set generator32=Visual Studio 14 +set generator64=Visual Studio 14 Win64 +set vcplatform32=win32 +set vcplatform64=x64 +set configuration=Release + +echo Building protoc +cd github\protobuf + +mkdir build32 +cd build32 +cmake -G "%generator32%" -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF -Dprotobuf_UNICODE=ON ../cmake +msbuild protobuf.sln /p:Platform=%vcplatform32% || goto error +cd .. + +mkdir build64 +cd build64 +cmake -G "%generator64%" -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF -Dprotobuf_UNICODE=ON ../cmake +msbuild protobuf.sln /p:Platform=%vcplatform64% || goto error +cd .. + +goto :EOF + +:error +echo Failed! +exit /b %ERRORLEVEL% diff --git a/kokoro/release/protoc/windows/release.cfg b/kokoro/release/protoc/windows/release.cfg new file mode 100644 index 0000000000000..0d0da8f133b78 --- /dev/null +++ b/kokoro/release/protoc/windows/release.cfg @@ -0,0 +1,8 @@ +# Configuration for Windows protoc release builds +build_file: "protobuf/kokoro/release/protoc/windows/build.bat" + +action { + define_artifacts { + regex: "**/protoc.exe" + } +} diff --git a/kokoro/release/python/linux/build_artifacts.sh b/kokoro/release/python/linux/build_artifacts.sh new file mode 100755 index 0000000000000..a35fc6f4279c7 --- /dev/null +++ b/kokoro/release/python/linux/build_artifacts.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +set -ex + +# change to repo root +pushd $(dirname $0)/../../../.. + +# Create stage dir +ORIGINAL_DIR=`pwd` +pushd .. +cp -R $ORIGINAL_DIR stage +export STAGE_DIR="`pwd`/stage" +popd + +export REPO_DIR=protobuf +export BUILD_VERSION=`grep -i "version" python/google/protobuf/__init__.py | grep -o "'.*'" | tr -d "'"` + +export BUILD_COMMIT=`git rev-parse HEAD` +export PLAT=x86_64 +export UNICODE_WIDTH=32 +export MACOSX_DEPLOYMENT_TARGET=10.9 + +rm -rf artifacts/ +rm -rf multibuild/ +mkdir artifacts +export ARTIFACT_DIR=$(pwd)/artifacts + +git clone https://github.com/matthew-brett/multibuild.git +cp kokoro/release/python/linux/config.sh config.sh + +build_artifact_version() { + MB_PYTHON_VERSION=$1 + cp -R $STAGE_DIR $REPO_DIR + + source multibuild/common_utils.sh + source multibuild/travis_steps.sh + before_install + + clean_code $REPO_DIR $BUILD_COMMIT + sed -i '/Wno-sign-compare/a \ \ \ \ \ \ \ \ extra_compile_args.append("-std=c++11")' $REPO_DIR/python/setup.py + cat $REPO_DIR/python/setup.py + + build_wheel $REPO_DIR/python $PLAT + + mv wheelhouse/* $ARTIFACT_DIR + + # Clean up env + rm -rf venv + sudo rm -rf $REPO_DIR +} + +build_artifact_version 2.7 +build_artifact_version 3.5 +build_artifact_version 3.6 +build_artifact_version 3.7 +build_artifact_version 3.8 +build_artifact_version 3.9 diff --git a/kokoro/release/python/linux/config.sh b/kokoro/release/python/linux/config.sh new file mode 100644 index 0000000000000..7a8f663d81a93 --- /dev/null +++ b/kokoro/release/python/linux/config.sh @@ -0,0 +1,50 @@ +# Define custom utilities +# Test for OSX with [ -n "$IS_OSX" ] + +function pre_build { + # Any stuff that you need to do before you start building the wheels + # Runs in the root directory of this repository. + pushd protobuf + + yum install -y devtoolset-2-libatomic-devel + + # Build protoc + ./autogen.sh + ./configure + + CXXFLAGS="-fPIC -g -O2" ./configure + make -j8 + + # Generate python dependencies. + pushd python + python setup.py build_py + popd + + popd +} + +function bdist_wheel_cmd { + # Builds wheel with bdist_wheel, puts into wheelhouse + # + # It may sometimes be useful to use bdist_wheel for the wheel building + # process. For example, versioneer has problems with versions which are + # fixed with bdist_wheel: + # https://github.com/warner/python-versioneer/issues/121 + local abs_wheelhouse=$1 + + # Modify build version + pwd + ls + python setup.py bdist_wheel --cpp_implementation --compile_static_extension + cp dist/*.whl $abs_wheelhouse +} + +function build_wheel { + build_wheel_cmd "bdist_wheel_cmd" $@ +} + +function run_tests { + # Runs tests on installed distribution from an empty directory + python --version + python -c "from google.protobuf.pyext import _message;" +} diff --git a/kokoro/release/python/linux/continuous.cfg b/kokoro/release/python/linux/continuous.cfg new file mode 100644 index 0000000000000..c0b9a018f131d --- /dev/null +++ b/kokoro/release/python/linux/continuous.cfg @@ -0,0 +1,8 @@ +# Config file for running tests in Kokoro +build_file: "protobuf/kokoro/release/python/linux/build_artifacts.sh" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/python/linux/presubmit.cfg b/kokoro/release/python/linux/presubmit.cfg new file mode 100644 index 0000000000000..c0b9a018f131d --- /dev/null +++ b/kokoro/release/python/linux/presubmit.cfg @@ -0,0 +1,8 @@ +# Config file for running tests in Kokoro +build_file: "protobuf/kokoro/release/python/linux/build_artifacts.sh" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/python/linux/release.cfg b/kokoro/release/python/linux/release.cfg new file mode 100644 index 0000000000000..b31b3f11929b4 --- /dev/null +++ b/kokoro/release/python/linux/release.cfg @@ -0,0 +1,8 @@ +# Configuration for Linux release builds +build_file: "protobuf/kokoro/release/python/linux/build_artifacts.sh" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/python/macos/build_artifacts.sh b/kokoro/release/python/macos/build_artifacts.sh new file mode 100755 index 0000000000000..7801b0125f7e2 --- /dev/null +++ b/kokoro/release/python/macos/build_artifacts.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +set -ex + +# change to repo root +pushd $(dirname $0)/../../../.. + +# Create stage dir +ORIGINAL_DIR=`pwd` +pushd .. +cp -R $ORIGINAL_DIR stage +export STAGE_DIR="`pwd`/stage" +popd + +export REPO_DIR=protobuf +export BUILD_VERSION=`grep -i "version" python/google/protobuf/__init__.py | grep -o "'.*'" | tr -d "'"` +export BUILD_COMMIT=`git rev-parse HEAD` +export PLAT=x86_64 +export UNICODE_WIDTH=32 +export MACOSX_DEPLOYMENT_TARGET=10.9 +export TRAVIS_OS_NAME="osx" + +rm -rf artifacts/ +rm -rf multibuild/ +mkdir artifacts +export ARTIFACT_DIR=$(pwd)/artifacts + +git clone https://github.com/matthew-brett/multibuild.git +cp kokoro/release/python/macos/config.sh config.sh + +OLD_PATH=$PATH + +build_artifact_version() { + MB_PYTHON_VERSION=$1 + + # Clean up env + rm -rf venv + sudo rm -rf $REPO_DIR + cp -R $STAGE_DIR $REPO_DIR + export PATH=$OLD_PATH + + source multibuild/common_utils.sh + source multibuild/travis_steps.sh + before_install + + clean_code $REPO_DIR $BUILD_COMMIT + + build_wheel $REPO_DIR/python $PLAT + + mv wheelhouse/* $ARTIFACT_DIR +} + +export MB_PYTHON_OSX_VER=10.9 +build_artifact_version 2.7 +build_artifact_version 3.6 +build_artifact_version 3.7 +build_artifact_version 3.8 +build_artifact_version 3.9 + +# python OSX10.9 does not have python 3.5 +export MB_PYTHON_OSX_VER=10.6 +build_artifact_version 3.5 + diff --git a/kokoro/release/python/macos/config.sh b/kokoro/release/python/macos/config.sh new file mode 100644 index 0000000000000..1b0a302e4cb35 --- /dev/null +++ b/kokoro/release/python/macos/config.sh @@ -0,0 +1,67 @@ +# Define custom utilities +# Test for OSX with [ -n "$IS_OSX" ] + +function remove_travis_ve_pip { + # Removing the system virtualenv or pip can be very problematic for + # macOS on Kokoro, so just leave them be. + :; +} + +function install_pip { + check_python + PIP_CMD="sudo $PYTHON_EXE -m pip${pip_args:+ $pip_args}" + $PIP_CMD install --upgrade pip +} + +function install_virtualenv { + check_python + check_pip + $PIP_CMD install --upgrade virtualenv + VIRTUALENV_CMD="$PYTHON_EXE -m virtualenv" +} + +function pre_build { + # Any stuff that you need to do before you start building the wheels + # Runs in the root directory of this repository. + pushd protobuf + + # Build protoc + ./autogen.sh + ./configure + + CXXFLAGS="-std=c++14 -fPIC -g -O2" ./configure + make -j8 + + # Generate python dependencies. + pushd python + python setup.py build_py + popd + + popd +} + +function bdist_wheel_cmd { + # Builds wheel with bdist_wheel, puts into wheelhouse + # + # It may sometimes be useful to use bdist_wheel for the wheel building + # process. For example, versioneer has problems with versions which are + # fixed with bdist_wheel: + # https://github.com/warner/python-versioneer/issues/121 + local abs_wheelhouse=$1 + + # Modify build version + pwd + ls + python setup.py bdist_wheel --cpp_implementation --compile_static_extension + cp dist/*.whl $abs_wheelhouse +} + +function build_wheel { + build_wheel_cmd "bdist_wheel_cmd" $@ +} + +function run_tests { + # Runs tests on installed distribution from an empty directory + python --version + python -c "from google.protobuf.pyext import _message;" +} diff --git a/kokoro/release/python/macos/continuous.cfg b/kokoro/release/python/macos/continuous.cfg new file mode 100644 index 0000000000000..85cf81b507f45 --- /dev/null +++ b/kokoro/release/python/macos/continuous.cfg @@ -0,0 +1,8 @@ +# Configuration for Mac OSX release builds +build_file: "protobuf/kokoro/release/python/macos/build_artifacts.sh" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/python/macos/presubmit.cfg b/kokoro/release/python/macos/presubmit.cfg new file mode 100644 index 0000000000000..85cf81b507f45 --- /dev/null +++ b/kokoro/release/python/macos/presubmit.cfg @@ -0,0 +1,8 @@ +# Configuration for Mac OSX release builds +build_file: "protobuf/kokoro/release/python/macos/build_artifacts.sh" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/python/macos/release.cfg b/kokoro/release/python/macos/release.cfg new file mode 100644 index 0000000000000..85cf81b507f45 --- /dev/null +++ b/kokoro/release/python/macos/release.cfg @@ -0,0 +1,8 @@ +# Configuration for Mac OSX release builds +build_file: "protobuf/kokoro/release/python/macos/build_artifacts.sh" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/python/windows/build_artifacts.bat b/kokoro/release/python/windows/build_artifacts.bat new file mode 100644 index 0000000000000..b2adbe03f3ffe --- /dev/null +++ b/kokoro/release/python/windows/build_artifacts.bat @@ -0,0 +1,88 @@ +REM Move scripts to root +set REPO_DIR_STAGE=%cd%\github\protobuf-stage +xcopy /S github\protobuf "%REPO_DIR_STAGE%\" +cd github\protobuf +copy kokoro\release\python\windows\build_single_artifact.bat build_single_artifact.bat + +REM Set environment variables +set PACKAGE_NAME=protobuf +set REPO_DIR=protobuf +set BUILD_DLL=OFF +set UNICODE=ON +set PB_TEST_DEP="six==1.9" +set OTHER_TEST_DEP="setuptools==38.5.1" +set OLD_PATH=C:\Program Files (x86)\MSBuild\14.0\bin\;%PATH% + +REM Fetch multibuild +git clone https://github.com/matthew-brett/multibuild.git + +REM Install zlib +mkdir zlib +curl -L -o zlib.zip http://www.winimage.com/zLibDll/zlib123dll.zip +curl -L -o zlib-src.zip http://www.winimage.com/zLibDll/zlib123.zip +7z x zlib.zip -ozlib +7z x zlib-src.zip -ozlib\include +SET ZLIB_ROOT=%cd%\zlib +del /Q zlib.zip +del /Q zlib-src.zip + +REM Create directory for artifacts +SET ARTIFACT_DIR=%cd%\artifacts +mkdir %ARTIFACT_DIR% + +REM Build wheel + +SET PYTHON=C:\python35_32bit +SET PYTHON_VERSION=3.5 +SET PYTHON_ARCH=32 +CALL build_single_artifact.bat || goto :error + +SET PYTHON=C:\python35 +SET PYTHON_VERSION=3.5 +SET PYTHON_ARCH=64 +CALL build_single_artifact.bat || goto :error + +SET PYTHON=C:\python36_32bit +SET PYTHON_VERSION=3.6 +SET PYTHON_ARCH=32 +CALL build_single_artifact.bat || goto :error + +SET PYTHON=C:\python36 +SET PYTHON_VERSION=3.6 +SET PYTHON_ARCH=64 +CALL build_single_artifact.bat || goto :error + +SET PYTHON=C:\python37_32bit +SET PYTHON_VERSION=3.7 +SET PYTHON_ARCH=32 +CALL build_single_artifact.bat || goto :error + +SET PYTHON=C:\python37 +SET PYTHON_VERSION=3.7 +SET PYTHON_ARCH=64 +CALL build_single_artifact.bat || goto :error + +SET PYTHON=C:\python38_32bit +SET PYTHON_VERSION=3.8 +SET PYTHON_ARCH=32 +CALL build_single_artifact.bat || goto :error + +SET PYTHON=C:\python38 +SET PYTHON_VERSION=3.8 +SET PYTHON_ARCH=64 +CALL build_single_artifact.bat || goto :error + +SET PYTHON=C:\python39_32bit +SET PYTHON_VERSION=3.9 +SET PYTHON_ARCH=32 +CALL build_single_artifact.bat || goto :error + +SET PYTHON=C:\python39 +SET PYTHON_VERSION=3.9 +SET PYTHON_ARCH=64 +CALL build_single_artifact.bat || goto :error + +goto :EOF + +:error +exit /b %errorlevel% diff --git a/kokoro/release/python/windows/build_single_artifact.bat b/kokoro/release/python/windows/build_single_artifact.bat new file mode 100644 index 0000000000000..a3cfef95d6e08 --- /dev/null +++ b/kokoro/release/python/windows/build_single_artifact.bat @@ -0,0 +1,84 @@ +setlocal + +if %PYTHON%==C:\python35_32bit set generator=Visual Studio 14 +if %PYTHON%==C:\python35_32bit set vcplatform=Win32 + +if %PYTHON%==C:\python35 set generator=Visual Studio 14 Win64 +if %PYTHON%==C:\python35 set vcplatform=x64 + +if %PYTHON%==C:\python36_32bit set generator=Visual Studio 14 +if %PYTHON%==C:\python36_32bit set vcplatform=Win32 + +if %PYTHON%==C:\python36 set generator=Visual Studio 14 Win64 +if %PYTHON%==C:\python36 set vcplatform=x64 + +if %PYTHON%==C:\python37_32bit set generator=Visual Studio 14 +if %PYTHON%==C:\python37_32bit set vcplatform=Win32 + +if %PYTHON%==C:\python37 set generator=Visual Studio 14 Win64 +if %PYTHON%==C:\python37 set vcplatform=x64 + +if %PYTHON%==C:\python38_32bit set generator=Visual Studio 14 +if %PYTHON%==C:\python38_32bit set vcplatform=Win32 + +if %PYTHON%==C:\python38 set generator=Visual Studio 14 Win64 +if %PYTHON%==C:\python38 set vcplatform=x64 + +if %PYTHON%==C:\python39_32bit set generator=Visual Studio 14 +if %PYTHON%==C:\python39_32bit set vcplatform=Win32 + +if %PYTHON%==C:\python39 set generator=Visual Studio 14 Win64 +if %PYTHON%==C:\python39 set vcplatform=x64 + +REM Prepend newly installed Python to the PATH of this build (this cannot be +REM done from inside the powershell script as it would require to restart +REM the parent CMD process). +SET PATH=C:\Program Files\CMake\bin;%PYTHON%;%PYTHON%\Scripts;%OLD_PATH% +python -m pip install -U pip +pip install wheel + +REM Check that we have the expected version and architecture for Python +python --version +python -c "import struct; print(struct.calcsize('P') * 8)" + +rmdir /s/q %REPO_DIR% +xcopy /s %REPO_DIR_STAGE% "%REPO_DIR%\" + +REM Checkout release commit +cd %REPO_DIR% + +REM ====================== +REM Build Protobuf Library +REM ====================== + +mkdir src\.libs + +mkdir vcprojects +pushd vcprojects +cmake -G "%generator%" -Dprotobuf_BUILD_SHARED_LIBS=%BUILD_DLL% -Dprotobuf_UNICODE=%UNICODE% -Dprotobuf_BUILD_TESTS=OFF ../cmake || goto :error +msbuild protobuf.sln /p:Platform=%vcplatform% /p:Configuration=Release || goto :error +dir /s /b +popd +copy vcprojects\Release\libprotobuf.lib src\.libs\libprotobuf.a +copy vcprojects\Release\libprotobuf-lite.lib src\.libs\libprotobuf-lite.a +SET PATH=%cd%\vcprojects\Release;%PATH% +dir vcprojects\Release + +REM ====================== +REM Build python library +REM ====================== + +cd python + +REM sed -i 's/\ extra_compile_args\ =\ \[\]/\ extra_compile_args\ =\ \[\'\/MT\'\]/g' setup.py + +python setup.py bdist_wheel --cpp_implementation --compile_static_extension +dir dist +copy dist\* %ARTIFACT_DIR% +dir %ARTIFACT_DIR% +cd ..\.. + +goto :EOF + +:error +exit /b %errorlevel% diff --git a/kokoro/release/python/windows/continuous.cfg b/kokoro/release/python/windows/continuous.cfg new file mode 100644 index 0000000000000..5261606477ab1 --- /dev/null +++ b/kokoro/release/python/windows/continuous.cfg @@ -0,0 +1,8 @@ +# Configuration for Windows protoc release builds +build_file: "protobuf/kokoro/release/python/windows/build_artifacts.bat" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/python/windows/presubmit.cfg b/kokoro/release/python/windows/presubmit.cfg new file mode 100644 index 0000000000000..5261606477ab1 --- /dev/null +++ b/kokoro/release/python/windows/presubmit.cfg @@ -0,0 +1,8 @@ +# Configuration for Windows protoc release builds +build_file: "protobuf/kokoro/release/python/windows/build_artifacts.bat" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/python/windows/release.cfg b/kokoro/release/python/windows/release.cfg new file mode 100644 index 0000000000000..5261606477ab1 --- /dev/null +++ b/kokoro/release/python/windows/release.cfg @@ -0,0 +1,8 @@ +# Configuration for Windows protoc release builds +build_file: "protobuf/kokoro/release/python/windows/build_artifacts.bat" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/ruby/linux/build_artifacts.sh b/kokoro/release/ruby/linux/build_artifacts.sh new file mode 100755 index 0000000000000..88555226b01f0 --- /dev/null +++ b/kokoro/release/ruby/linux/build_artifacts.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -ex + +# change to repo root +cd $(dirname $0)/../../../.. + +source kokoro/release/ruby/linux/prepare_build.sh + +# ruby environment +source kokoro/release/ruby/linux/ruby/ruby_build_environment.sh + +# build artifacts +bash kokoro/release/ruby/linux/ruby/ruby_build.sh diff --git a/kokoro/release/ruby/linux/continuous.cfg b/kokoro/release/ruby/linux/continuous.cfg new file mode 100644 index 0000000000000..dbc71b2ceb305 --- /dev/null +++ b/kokoro/release/ruby/linux/continuous.cfg @@ -0,0 +1,8 @@ +# Configuration for Linux release builds +build_file: "protobuf/kokoro/release/ruby/linux/build_artifacts.sh" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/ruby/linux/prepare_build.sh b/kokoro/release/ruby/linux/prepare_build.sh new file mode 100755 index 0000000000000..91d186898cbde --- /dev/null +++ b/kokoro/release/ruby/linux/prepare_build.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# Move docker's storage location to scratch disk so we don't run out of space. +echo 'DOCKER_OPTS="${DOCKER_OPTS} --graph=/tmpfs/docker"' | sudo tee --append /etc/default/docker +# Use container registry mirror for pulling docker images (should make downloads faster) +# See https://cloud.google.com/container-registry/docs/using-dockerhub-mirroring +echo 'DOCKER_OPTS="${DOCKER_OPTS} --registry-mirror=https://mirror.gcr.io"' | sudo tee --append /etc/default/docker +sudo service docker restart + +# All artifacts come here +mkdir artifacts +export ARTIFACT_DIR=$(pwd)/artifacts diff --git a/kokoro/release/ruby/linux/presubmit.cfg b/kokoro/release/ruby/linux/presubmit.cfg new file mode 100644 index 0000000000000..dbc71b2ceb305 --- /dev/null +++ b/kokoro/release/ruby/linux/presubmit.cfg @@ -0,0 +1,8 @@ +# Configuration for Linux release builds +build_file: "protobuf/kokoro/release/ruby/linux/build_artifacts.sh" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/ruby/linux/release.cfg b/kokoro/release/ruby/linux/release.cfg new file mode 100644 index 0000000000000..dbc71b2ceb305 --- /dev/null +++ b/kokoro/release/ruby/linux/release.cfg @@ -0,0 +1,8 @@ +# Configuration for Linux release builds +build_file: "protobuf/kokoro/release/ruby/linux/build_artifacts.sh" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/ruby/linux/ruby/ruby_build.sh b/kokoro/release/ruby/linux/ruby/ruby_build.sh new file mode 100755 index 0000000000000..f8ae9623f255f --- /dev/null +++ b/kokoro/release/ruby/linux/ruby/ruby_build.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -ex + +# Build protoc +if test ! -e src/protoc; then + ./autogen.sh + ./configure + make -j4 +fi + +umask 0022 +pushd ruby +gem install bundler -v 2.1.4 +bundle update && bundle exec rake gem:native +ls pkg +mv pkg/* $ARTIFACT_DIR +popd diff --git a/kokoro/release/ruby/linux/ruby/ruby_build_environment.sh b/kokoro/release/ruby/linux/ruby/ruby_build_environment.sh new file mode 100755 index 0000000000000..87c0f75448d82 --- /dev/null +++ b/kokoro/release/ruby/linux/ruby/ruby_build_environment.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set +ex +[[ -s /etc/profile.d/rvm.sh ]] && . /etc/profile.d/rvm.sh +set -e # rvm commands are very verbose +rvm --default use ruby-2.4.1 +# The version needs to be updated if the version specified in Gemfile.lock is changed +gem install bundler -v '1.17.3' +set -ex diff --git a/kokoro/release/ruby/macos/build_artifacts.sh b/kokoro/release/ruby/macos/build_artifacts.sh new file mode 100755 index 0000000000000..c68b63cc43d7d --- /dev/null +++ b/kokoro/release/ruby/macos/build_artifacts.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -ex + +# change to repo root +cd $(dirname $0)/../../../.. + +# all artifacts come here +mkdir artifacts +export ARTIFACT_DIR=$(pwd)/artifacts + +# ruby environment +bash kokoro/release/ruby/macos/ruby/ruby_build_environment.sh + +gem install rubygems-update +update_rubygems + +# build artifacts +bash kokoro/release/ruby/macos/ruby/ruby_build.sh diff --git a/kokoro/release/ruby/macos/continuous.cfg b/kokoro/release/ruby/macos/continuous.cfg new file mode 100644 index 0000000000000..cb1c08bb88279 --- /dev/null +++ b/kokoro/release/ruby/macos/continuous.cfg @@ -0,0 +1,8 @@ +# Configuration for Mac OSX release builds +build_file: "protobuf/kokoro/release/ruby/macos/build_artifacts.sh" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/ruby/macos/presubmit.cfg b/kokoro/release/ruby/macos/presubmit.cfg new file mode 100644 index 0000000000000..cb1c08bb88279 --- /dev/null +++ b/kokoro/release/ruby/macos/presubmit.cfg @@ -0,0 +1,8 @@ +# Configuration for Mac OSX release builds +build_file: "protobuf/kokoro/release/ruby/macos/build_artifacts.sh" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/ruby/macos/release.cfg b/kokoro/release/ruby/macos/release.cfg new file mode 100644 index 0000000000000..cb1c08bb88279 --- /dev/null +++ b/kokoro/release/ruby/macos/release.cfg @@ -0,0 +1,8 @@ +# Configuration for Mac OSX release builds +build_file: "protobuf/kokoro/release/ruby/macos/build_artifacts.sh" + +action { + define_artifacts { + regex: "github/protobuf/artifacts/**" + } +} diff --git a/kokoro/release/ruby/macos/ruby/ruby_build.sh b/kokoro/release/ruby/macos/ruby/ruby_build.sh new file mode 100755 index 0000000000000..7f6c18fe8e8d7 --- /dev/null +++ b/kokoro/release/ruby/macos/ruby/ruby_build.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -ex + +# Build protoc +if test ! -e src/protoc; then + ./autogen.sh + ./configure + make -j4 +fi + +umask 0022 +pushd ruby +bundle update && bundle exec rake gem:native +ls pkg +mv pkg/* $ARTIFACT_DIR +popd diff --git a/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh b/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh new file mode 100755 index 0000000000000..046b604b40e10 --- /dev/null +++ b/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +set -ex + +set +ex # rvm script is very verbose and exits with errorcode +source $HOME/.rvm/scripts/rvm +set -e # rvm commands are very verbose +time rvm install 2.5.0 +rvm use 2.5.0 +gem install rake-compiler --no-document +gem install bundler --no-document +time rvm install 2.7.0 +rvm use 2.7.0 --default +gem install rake-compiler --no-document +gem install bundler --no-document +rvm osx-ssl-certs status all +rvm osx-ssl-certs update all +set -ex + +rm -rf ~/.rake-compiler + +CROSS_RUBY=$(mktemp tmpfile.XXXXXXXX) + +curl https://raw.githubusercontent.com/rake-compiler/rake-compiler/72184e51779b6a3b9b8580b036a052fdc3181ced/tasks/bin/cross-ruby.rake > "$CROSS_RUBY" + +# See https://github.com/grpc/grpc/issues/12161 for verconf.h patch details +patch "$CROSS_RUBY" << EOF +--- cross-ruby.rake 2020-12-11 11:17:53.000000000 +0900 ++++ patched 2020-12-11 11:18:52.000000000 +0900 +@@ -111,10 +111,12 @@ + "--host=#{MINGW_HOST}", + "--target=#{MINGW_TARGET}", + "--build=#{RUBY_BUILD}", +- '--enable-shared', ++ '--enable-static', ++ '--disable-shared', + '--disable-install-doc', ++ '--without-gmp', + '--with-ext=', +- 'LDFLAGS=-pipe -s', ++ 'LDFLAGS=-pipe', + ] + + # Force Winsock2 for Ruby 1.8, 1.9 defaults to it +@@ -130,6 +132,7 @@ + # make + file "#{build_dir}/ruby.exe" => ["#{build_dir}/Makefile"] do |t| + chdir File.dirname(t.prerequisites.first) do ++ sh "test -s verconf.h || rm -f verconf.h" # if verconf.h has size 0, make sure it gets re-built by make + sh MAKE + end + end +EOF + +MAKE="make -j8" + +set +x # rvm commands are very verbose +rvm use 2.7.0 +set -x +ruby --version | grep 'ruby 2.7.0' +for v in 3.0.0 2.7.0 ; do + ccache -c + rake -f "$CROSS_RUBY" cross-ruby VERSION="$v" HOST=x86_64-darwin11 MAKE="$MAKE" +done +set +x +rvm use 2.5.0 +set -x +ruby --version | grep 'ruby 2.5.0' +for v in 2.6.0 2.5.1 2.4.0 2.3.0; do + ccache -c + rake -f "$CROSS_RUBY" cross-ruby VERSION="$v" HOST=x86_64-darwin11 MAKE="$MAKE" +done +set +x +rvm use 2.7.0 +set -x + +sed 's/x86_64-darwin-11/universal-darwin/' ~/.rake-compiler/config.yml > "$CROSS_RUBY" +mv "$CROSS_RUBY" ~/.rake-compiler/config.yml diff --git a/kokoro/windows/csharp/build.bat b/kokoro/windows/csharp/build.bat new file mode 100644 index 0000000000000..4f1df377c0c82 --- /dev/null +++ b/kokoro/windows/csharp/build.bat @@ -0,0 +1,17 @@ +@rem enter repo root +cd /d %~dp0\..\..\.. + +cd csharp + +@rem Install dotnet SDK +powershell -File install_dotnet_sdk.ps1 +set PATH=%LOCALAPPDATA%\Microsoft\dotnet;%PATH% + +@rem Disable some unwanted dotnet options +set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true +set DOTNET_CLI_TELEMETRY_OPTOUT=true + +@rem Work around https://github.com/dotnet/core/issues/5881 +dotnet nuget locals all --clear + +call buildall.bat diff --git a/kokoro/windows/csharp/continuous.cfg b/kokoro/windows/csharp/continuous.cfg new file mode 100644 index 0000000000000..f586585176b10 --- /dev/null +++ b/kokoro/windows/csharp/continuous.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/windows/csharp/build.bat" +timeout_mins: 1440 diff --git a/kokoro/windows/csharp/presubmit.cfg b/kokoro/windows/csharp/presubmit.cfg new file mode 100644 index 0000000000000..f586585176b10 --- /dev/null +++ b/kokoro/windows/csharp/presubmit.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/windows/csharp/build.bat" +timeout_mins: 1440 diff --git a/m4/acx_check_suncc.m4 b/m4/acx_check_suncc.m4 index 8bc0a890dc257..0a9a5770b37b5 100644 --- a/m4/acx_check_suncc.m4 +++ b/m4/acx_check_suncc.m4 @@ -26,7 +26,7 @@ AC_DEFUN([ACX_CHECK_SUNCC],[ AS_IF([test "$SUNCC" = "yes" -a "x${ac_cv_env_CXXFLAGS_set}" = "x"],[ dnl Sun Studio has a crashing bug with -xO4 in some cases. Keep this dnl at -xO3 until a proper test to detect those crashes can be done. - CXXFLAGS="-g0 -xO3 -xlibmil -xdepend -xbuiltin -mt -compat=5 -library=stlport4 -library=Crun -template=no%extdef ${CXXFLAGS}" + CXXFLAGS="-g0 -xO3 -xlibmil -xdepend -xbuiltin -mt -template=no%extdef ${CXXFLAGS}" ]) case $host_os in @@ -67,4 +67,7 @@ AC_DEFUN([ACX_CHECK_SUNCC],[ ;; esac + AS_IF([test "$target_cpu" = "sparc" -a "x$SUNCC" = "xyes" ],[ + CXXFLAGS="-xregs=no%appl ${CXXFLAGS}" + ]) ]) diff --git a/m4/acx_pthread.m4 b/m4/acx_pthread.m4 deleted file mode 100644 index 89d42c7449ef3..0000000000000 --- a/m4/acx_pthread.m4 +++ /dev/null @@ -1,397 +0,0 @@ -# This was retrieved from -# http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?revision=1277&root=avahi -# See also (perhaps for new versions?) -# http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?root=avahi -# -# We've rewritten the inconsistency check code (from avahi), to work -# more broadly. In particular, it no longer assumes ld accepts -zdefs. -# This caused a restructing of the code, but the functionality has only -# changed a little. - -dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) -dnl -dnl @summary figure out how to build C programs using POSIX threads -dnl -dnl This macro figures out how to build C programs using POSIX threads. -dnl It sets the PTHREAD_LIBS output variable to the threads library and -dnl linker flags, and the PTHREAD_CFLAGS output variable to any special -dnl C compiler flags that are needed. (The user can also force certain -dnl compiler flags/libs to be tested by setting these environment -dnl variables.) -dnl -dnl Also sets PTHREAD_CC to any special C compiler that is needed for -dnl multi-threaded programs (defaults to the value of CC otherwise). -dnl (This is necessary on AIX to use the special cc_r compiler alias.) -dnl -dnl NOTE: You are assumed to not only compile your program with these -dnl flags, but also link it with them as well. e.g. you should link -dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS -dnl $LIBS -dnl -dnl If you are only building threads programs, you may wish to use -dnl these variables in your default LIBS, CFLAGS, and CC: -dnl -dnl LIBS="$PTHREAD_LIBS $LIBS" -dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS" -dnl CC="$PTHREAD_CC" -dnl -dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute -dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to -dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). -dnl -dnl ACTION-IF-FOUND is a list of shell commands to run if a threads -dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to -dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the -dnl default action will define HAVE_PTHREAD. -dnl -dnl Please let the authors know if this macro fails on any platform, or -dnl if you have any other suggestions or comments. This macro was based -dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with -dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros -dnl posted by Alejandro Forero Cuervo to the autoconf macro repository. -dnl We are also grateful for the helpful feedback of numerous users. -dnl -dnl @category InstalledPackages -dnl @author Steven G. Johnson -dnl @version 2006-05-29 -dnl @license GPLWithACException -dnl -dnl Checks for GCC shared/pthread inconsistency based on work by -dnl Marcin Owsiany - - -AC_DEFUN([ACX_PTHREAD], [ -AC_REQUIRE([AC_CANONICAL_HOST]) -AC_LANG_SAVE -AC_LANG_C -acx_pthread_ok=no - -# We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on True64 or Sequent). -# It gets checked for in the link test anyway. - -# First of all, check if the user has set any of the PTHREAD_LIBS, -# etcetera environment variables, and if threads linking works using -# them: -if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) - AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) - AC_MSG_RESULT($acx_pthread_ok) - if test x"$acx_pthread_ok" = xno; then - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" - fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" -fi - -# We must check for the threads library under a number of different -# names; the ordering is very important because some systems -# (e.g. DEC) have both -lpthread and -lpthreads, where one of the -# libraries is broken (non-POSIX). - -# Create a list of thread flags to try. Items starting with a "-" are -# C compiler flags, and other items are library names, except for "none" -# which indicates that we try without any flags at all, and "pthread-config" -# which is a program returning the flags for the Pth emulation library. - -acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" - -# The ordering *is* (sometimes) important. Some notes on the -# individual items follow: - -# pthreads: AIX (must check this before -lpthread) -# none: in case threads are in libc; should be tried before -Kthread and -# other compiler flags to prevent continual compiler warnings -# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) -# -pthreads: Solaris/gcc -# -mthreads: Mingw32/gcc, Lynx/gcc -# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads too; -# also defines -D_REENTRANT) -# ... -mt is also the pthreads flag for HP/aCC -# pthread: Linux, etcetera -# --thread-safe: KAI C++ -# pthread-config: use pthread-config program (for GNU Pth library) - -case "${host_cpu}-${host_os}" in - *solaris*) - - # On Solaris (at least, for some versions), libc contains stubbed - # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthreads/-mt/ - # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather - # a function called by this macro, so we could check for that, but - # who knows whether they'll stub that too in a future libc.) So, - # we'll just look for -pthreads and -lpthread first: - - acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" - ;; -esac - -if test x"$acx_pthread_ok" = xno; then -for flag in $acx_pthread_flags; do - - case $flag in - none) - AC_MSG_CHECKING([whether pthreads work without any flags]) - ;; - - -*) - AC_MSG_CHECKING([whether pthreads work with $flag]) - PTHREAD_CFLAGS="$flag" - ;; - - pthread-config) - AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) - if test x"$acx_pthread_config" = xno; then continue; fi - PTHREAD_CFLAGS="`pthread-config --cflags`" - PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" - ;; - - *) - AC_MSG_CHECKING([for the pthreads library -l$flag]) - PTHREAD_LIBS="-l$flag" - ;; - esac - - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - - # Check for various functions. We must include pthread.h, - # since some functions may be macros. (On the Sequent, we - # need a special flag -Kthread to make this header compile.) - # We check for pthread_join because it is in -lpthread on IRIX - # while pthread_create is in libc. We check for pthread_attr_init - # due to DEC craziness with -lpthreads. We check for - # pthread_cleanup_push because it is one of the few pthread - # functions on Solaris that doesn't have a non-functional libc stub. - # We try pthread_create on general principles. - AC_TRY_LINK([#include ], - [pthread_t th; pthread_join(th, 0); - pthread_attr_init(0); pthread_cleanup_push(0, 0); - pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], - [acx_pthread_ok=yes]) - - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" - - AC_MSG_RESULT($acx_pthread_ok) - if test "x$acx_pthread_ok" = xyes; then - break; - fi - - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" -done -fi - -# Various other checks: -if test "x$acx_pthread_ok" = xyes; then - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - - # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. - AC_MSG_CHECKING([for joinable pthread attribute]) - attr_name=unknown - for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do - AC_TRY_LINK([#include ], [int attr=$attr; return attr;], - [attr_name=$attr; break]) - done - AC_MSG_RESULT($attr_name) - if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then - AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, - [Define to necessary symbol if this constant - uses a non-standard name on your system.]) - fi - - AC_MSG_CHECKING([if more special flags are required for pthreads]) - flag=no - case "${host_cpu}-${host_os}" in - *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; - *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; - esac - AC_MSG_RESULT(${flag}) - if test "x$flag" != xno; then - PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" - fi - - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" - # More AIX lossage: must compile with xlc_r or cc_r - if test x"$GCC" != xyes; then - AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) - else - PTHREAD_CC=$CC - fi - - # The next part tries to detect GCC inconsistency with -shared on some - # architectures and systems. The problem is that in certain - # configurations, when -shared is specified, GCC "forgets" to - # internally use various flags which are still necessary. - - # - # Prepare the flags - # - save_CFLAGS="$CFLAGS" - save_LIBS="$LIBS" - save_CC="$CC" - - # Try with the flags determined by the earlier checks. - # - # -Wl,-z,defs forces link-time symbol resolution, so that the - # linking checks with -shared actually have any value - # - # FIXME: -fPIC is required for -shared on many architectures, - # so we specify it here, but the right way would probably be to - # properly detect whether it is actually required. - CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - CC="$PTHREAD_CC" - - # In order not to create several levels of indentation, we test - # the value of "$done" until we find the cure or run out of ideas. - done="no" - - # First, make sure the CFLAGS we added are actually accepted by our - # compiler. If not (and OS X's ld, for instance, does not accept -z), - # then we can't do this test. - if test x"$done" = xno; then - AC_MSG_CHECKING([whether to check for GCC pthread/shared inconsistencies]) - AC_TRY_LINK(,, , [done=yes]) - - if test "x$done" = xyes ; then - AC_MSG_RESULT([no]) - else - AC_MSG_RESULT([yes]) - fi - fi - - if test x"$done" = xno; then - AC_MSG_CHECKING([whether -pthread is sufficient with -shared]) - AC_TRY_LINK([#include ], - [pthread_t th; pthread_join(th, 0); - pthread_attr_init(0); pthread_cleanup_push(0, 0); - pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], - [done=yes]) - - if test "x$done" = xyes; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - fi - - # - # Linux gcc on some architectures such as mips/mipsel forgets - # about -lpthread - # - if test x"$done" = xno; then - AC_MSG_CHECKING([whether -lpthread fixes that]) - LIBS="-lpthread $PTHREAD_LIBS $save_LIBS" - AC_TRY_LINK([#include ], - [pthread_t th; pthread_join(th, 0); - pthread_attr_init(0); pthread_cleanup_push(0, 0); - pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], - [done=yes]) - - if test "x$done" = xyes; then - AC_MSG_RESULT([yes]) - PTHREAD_LIBS="-lpthread $PTHREAD_LIBS" - else - AC_MSG_RESULT([no]) - fi - fi - # - # FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc - # - if test x"$done" = xno; then - AC_MSG_CHECKING([whether -lc_r fixes that]) - LIBS="-lc_r $PTHREAD_LIBS $save_LIBS" - AC_TRY_LINK([#include ], - [pthread_t th; pthread_join(th, 0); - pthread_attr_init(0); pthread_cleanup_push(0, 0); - pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], - [done=yes]) - - if test "x$done" = xyes; then - AC_MSG_RESULT([yes]) - PTHREAD_LIBS="-lc_r $PTHREAD_LIBS" - else - AC_MSG_RESULT([no]) - fi - fi - if test x"$done" = xno; then - # OK, we have run out of ideas - AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries]) - - # so it's not safe to assume that we may use pthreads - acx_pthread_ok=no - fi - - AC_MSG_CHECKING([whether what we have so far is sufficient with -nostdlib]) - CFLAGS="-nostdlib $CFLAGS" - # we need c with nostdlib - LIBS="$LIBS -lc" - AC_TRY_LINK([#include ], - [pthread_t th; pthread_join(th, 0); - pthread_attr_init(0); pthread_cleanup_push(0, 0); - pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], - [done=yes],[done=no]) - - if test "x$done" = xyes; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - - if test x"$done" = xno; then - AC_MSG_CHECKING([whether -lpthread saves the day]) - LIBS="-lpthread $LIBS" - AC_TRY_LINK([#include ], - [pthread_t th; pthread_join(th, 0); - pthread_attr_init(0); pthread_cleanup_push(0, 0); - pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], - [done=yes],[done=no]) - - if test "x$done" = xyes; then - AC_MSG_RESULT([yes]) - PTHREAD_LIBS="$PTHREAD_LIBS -lpthread" - else - AC_MSG_RESULT([no]) - AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries and -nostdlib]) - fi - fi - - CFLAGS="$save_CFLAGS" - LIBS="$save_LIBS" - CC="$save_CC" -else - PTHREAD_CC="$CC" -fi - -AC_SUBST(PTHREAD_LIBS) -AC_SUBST(PTHREAD_CFLAGS) -AC_SUBST(PTHREAD_CC) - -# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test x"$acx_pthread_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) - : -else - acx_pthread_ok=no - $2 -fi -AC_LANG_RESTORE -])dnl ACX_PTHREAD diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4 new file mode 100644 index 0000000000000..1598d077ff020 --- /dev/null +++ b/m4/ax_pthread.m4 @@ -0,0 +1,507 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_pthread.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. It +# sets the PTHREAD_LIBS output variable to the threads library and linker +# flags, and the PTHREAD_CFLAGS output variable to any special C compiler +# flags that are needed. (The user can also force certain compiler +# flags/libs to be tested by setting these environment variables.) +# +# Also sets PTHREAD_CC to any special C compiler that is needed for +# multi-threaded programs (defaults to the value of CC otherwise). (This +# is necessary on AIX to use the special cc_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these flags, +# but also to link with them as well. For example, you might link with +# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# +# If you are only building threaded programs, you may wish to use these +# variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant +# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the +# PTHREAD_PRIO_INHERIT symbol is defined when compiling with +# PTHREAD_CFLAGS. +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads library +# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it +# is not found. If ACTION-IF-FOUND is not specified, the default action +# will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or if +# you have any other suggestions or comments. This macro was based on work +# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help +# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by +# Alejandro Forero Cuervo to the autoconf macro repository. We are also +# grateful for the helpful feedback of numerous users. +# +# Updated for Autoconf 2.68 by Daniel Richard G. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2011 Daniel Richard G. +# Copyright (c) 2019 Marc Stevens +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 27 + +AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) +AC_DEFUN([AX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_PROG_SED]) +AC_LANG_PUSH([C]) +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on Tru64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items with a "," contain both +# C compiler flags (before ",") and linker flags (after ","). Other items +# starting with a "-" are C compiler flags, and remaining items are +# library names, except for "none" which indicates that we try without +# any flags at all, and "pthread-config" which is a program returning +# the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], + [ +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + ], + [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) + ;; + + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags" + ;; +esac + +# Are we compiling with Clang? + +AC_CACHE_CHECK([whether $CC is Clang], + [ax_cv_PTHREAD_CLANG], + [ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], + [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + ], + [ax_cv_PTHREAD_CLANG=yes]) + fi + ]) +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +# Note that for GCC and Clang -pthread generally implies -lpthread, +# except when -nostdlib is passed. +# This is problematic using libtool to build C++ shared libraries with pthread: +# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460 +# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333 +# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555 +# To solve this, first try -pthread together with -lpthread for GCC + +AS_IF([test "x$GCC" = "xyes"], + [ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"]) + +# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first + +AS_IF([test "x$ax_pthread_clang" = "xyes"], + [ax_pthread_flags="-pthread,-lpthread -pthread"]) + + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +AS_IF([test "x$ax_pthread_check_macro" = "x--"], + [ax_pthread_check_cond=0], + [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) + + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + *,*) + PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"` + PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"` + AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void *some_global = NULL; + static void routine(void *a) + { + /* To avoid any unused-parameter or + unused-but-set-parameter warning. */ + some_global = a; + } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + AC_MSG_RESULT([$ax_pthread_ok]) + AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + + + +# Various other checks: +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_CACHE_CHECK([for joinable pthread attribute], + [ax_cv_PTHREAD_JOINABLE_ATTR], + [ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $ax_pthread_attr; return attr /* ; */])], + [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], + []) + done + ]) + AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"], + [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], + [$ax_cv_PTHREAD_JOINABLE_ATTR], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + ax_pthread_joinable_attr_defined=yes + ]) + + AC_CACHE_CHECK([whether more special flags are required for pthreads], + [ax_cv_PTHREAD_SPECIAL_FLAGS], + [ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + ]) + AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"], + [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes]) + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + [ax_cv_PTHREAD_PRIO_INHERIT], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT; + return i;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) + ax_pthread_prio_inherit_defined=yes + ]) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + +AC_SUBST([PTHREAD_LIBS]) +AC_SUBST([PTHREAD_CFLAGS]) +AC_SUBST([PTHREAD_CC]) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "x$ax_pthread_ok" = "xyes"; then + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) + : +else + ax_pthread_ok=no + $2 +fi +AC_LANG_POP +])dnl AX_PTHREAD diff --git a/more_tests/Makefile b/more_tests/Makefile deleted file mode 100755 index 286cf0f12c812..0000000000000 --- a/more_tests/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -# Additional tests to run before releasing a package. -# -# Run like: -# make PACKAGE=/path/to/protobuf-VERSION.tar.gz -# -# Some of these tests require tools or make assumptions that may not be -# available on end-user machines, so these cannot be part of "make check". For -# example, we test that the headers compile with strict warning settings, but -# since different compilers produce wildly different warnings we cannot assume -# that this test will pass everywhere. If we ran it as part of "make check", -# it could unnecessarily block users from running the real tests just because -# their compiler produces some extra warnings that probably aren't a big deal. -# So we run it separately. - -all: header_warning_test - -clean: - rm -rf src target header_warning_test.cc header_warning_test.o header_warning_test - -# Unpack the package into src, then install it into target. -PACKAGE=protobuf.tar.gz - -src: $(PACKAGE) - tar zxvf $(PACKAGE) - mv `basename $(PACKAGE) .tar.gz` src - -target: src - (cd src && ./configure --prefix=$$PWD/../target --disable-shared) - (cd src && make -j4 check) - (cd src && make install) - -# Verify that headers produce no warnings even under strict settings. -header_warning_test.cc: target - ( (cd target/include && find google/protobuf -name '*.h') | \ - awk '{print "#include \""$$1"\""} ' > header_warning_test.cc ) - -header_warning_test: header_warning_test.cc - # TODO(kenton): Consider adding -pedantic and -Weffc++. Currently these - # produce tons of extra warnings so we'll need to do some work first. - g++ -Itarget/include -Wall -Werror -Wsign-compare -O2 -c header_warning_test.cc - touch header_warning_test diff --git a/objectivec/.clang-format b/objectivec/.clang-format new file mode 100644 index 0000000000000..d3ff76bb20af3 --- /dev/null +++ b/objectivec/.clang-format @@ -0,0 +1,7 @@ +BasedOnStyle: Google + +# Ignore pddm directives. +CommentPragmas: '^%' + +# Following the rest of the protobuf code. +ColumnLimit: 80 diff --git a/objectivec/BUILD b/objectivec/BUILD new file mode 100644 index 0000000000000..9f702ec95fde8 --- /dev/null +++ b/objectivec/BUILD @@ -0,0 +1,90 @@ +load("@rules_cc//cc:defs.bzl", "objc_library") + +objc_library( + name = "objectivec", + hdrs = [ + "GPBAny.pbobjc.h", + "GPBApi.pbobjc.h", + "GPBDuration.pbobjc.h", + "GPBEmpty.pbobjc.h", + "GPBFieldMask.pbobjc.h", + "GPBSourceContext.pbobjc.h", + "GPBStruct.pbobjc.h", + "GPBTimestamp.pbobjc.h", + "GPBType.pbobjc.h", + "GPBWrappers.pbobjc.h", + "GPBArray.h", + "GPBBootstrap.h", + "GPBCodedInputStream.h", + "GPBCodedOutputStream.h", + "GPBDescriptor.h", + "GPBDictionary.h", + "GPBExtensionInternals.h", + "GPBExtensionRegistry.h", + "GPBMessage.h", + "GPBProtocolBuffers.h", + "GPBProtocolBuffers_RuntimeSupport.h", + "GPBRootObject.h", + "GPBRuntimeTypes.h", + "GPBUnknownField.h", + "GPBUnknownFieldSet.h", + "GPBUtilities.h", + "GPBWellKnownTypes.h", + "GPBWireFormat.h", + "google/protobuf/Any.pbobjc.h", + "google/protobuf/Api.pbobjc.h", + "google/protobuf/Duration.pbobjc.h", + "google/protobuf/Empty.pbobjc.h", + "google/protobuf/FieldMask.pbobjc.h", + "google/protobuf/SourceContext.pbobjc.h", + "google/protobuf/Struct.pbobjc.h", + "google/protobuf/Timestamp.pbobjc.h", + "google/protobuf/Type.pbobjc.h", + "google/protobuf/Wrappers.pbobjc.h", + # Package private headers, but exposed because the generated sources + # need to use them. + "GPBArray_PackagePrivate.h", + "GPBCodedInputStream_PackagePrivate.h", + "GPBCodedOutputStream_PackagePrivate.h", + "GPBDescriptor_PackagePrivate.h", + "GPBDictionary_PackagePrivate.h", + "GPBMessage_PackagePrivate.h", + "GPBRootObject_PackagePrivate.h", + "GPBUnknownFieldSet_PackagePrivate.h", + "GPBUnknownField_PackagePrivate.h", + "GPBUtilities_PackagePrivate.h", + ], + copts = [ + "-Wno-vla", + ], + includes = [ + ".", + ], + non_arc_srcs = [ + "GPBAny.pbobjc.m", + "GPBApi.pbobjc.m", + "GPBDuration.pbobjc.m", + "GPBEmpty.pbobjc.m", + "GPBFieldMask.pbobjc.m", + "GPBSourceContext.pbobjc.m", + "GPBStruct.pbobjc.m", + "GPBTimestamp.pbobjc.m", + "GPBType.pbobjc.m", + "GPBWrappers.pbobjc.m", + "GPBArray.m", + "GPBCodedInputStream.m", + "GPBCodedOutputStream.m", + "GPBDescriptor.m", + "GPBDictionary.m", + "GPBExtensionInternals.m", + "GPBExtensionRegistry.m", + "GPBMessage.m", + "GPBRootObject.m", + "GPBUnknownField.m", + "GPBUnknownFieldSet.m", + "GPBUtilities.m", + "GPBWellKnownTypes.m", + "GPBWireFormat.m", + ], + visibility = ["//visibility:public"], +) diff --git a/objectivec/DevTools/compile_testing_protos.sh b/objectivec/DevTools/compile_testing_protos.sh index d7f3f60589f3e..69c32f920bdc4 100755 --- a/objectivec/DevTools/compile_testing_protos.sh +++ b/objectivec/DevTools/compile_testing_protos.sh @@ -25,6 +25,62 @@ case "${ACTION}" in ;; esac +# ----------------------------------------------------------------------------- +# Reusing a bunch of the protos from the protocolbuffers/protobuf tree, this +# can include some extras as there is no harm in ensuring work for C++ +# generation. + +CORE_PROTO_FILES=( + src/google/protobuf/any_test.proto + src/google/protobuf/unittest_arena.proto + src/google/protobuf/unittest_custom_options.proto + src/google/protobuf/unittest_enormous_descriptor.proto + src/google/protobuf/unittest_embed_optimize_for.proto + src/google/protobuf/unittest_empty.proto + src/google/protobuf/unittest_import.proto + src/google/protobuf/unittest_import_lite.proto + src/google/protobuf/unittest_lite.proto + src/google/protobuf/unittest_mset.proto + src/google/protobuf/unittest_mset_wire_format.proto + src/google/protobuf/unittest_no_generic_services.proto + src/google/protobuf/unittest_optimize_for.proto + src/google/protobuf/unittest.proto + src/google/protobuf/unittest_import_public.proto + src/google/protobuf/unittest_import_public_lite.proto + src/google/protobuf/unittest_drop_unknown_fields.proto + src/google/protobuf/unittest_preserve_unknown_enum.proto + src/google/protobuf/map_lite_unittest.proto + src/google/protobuf/map_proto2_unittest.proto + src/google/protobuf/map_unittest.proto + # The unittest_custom_options.proto extends the messages in descriptor.proto + # so we build it in to test extending in general. The library doesn't provide + # a descriptor as it doesn't use the classes/enums. + src/google/protobuf/descriptor.proto +) + +# ----------------------------------------------------------------------------- +# The objc unittest specific proto files. + +OBJC_TEST_PROTO_FILES=( + objectivec/Tests/unittest_cycle.proto + objectivec/Tests/unittest_deprecated.proto + objectivec/Tests/unittest_deprecated_file.proto + objectivec/Tests/unittest_extension_chain_a.proto + objectivec/Tests/unittest_extension_chain_b.proto + objectivec/Tests/unittest_extension_chain_c.proto + objectivec/Tests/unittest_extension_chain_d.proto + objectivec/Tests/unittest_extension_chain_e.proto + objectivec/Tests/unittest_extension_chain_f.proto + objectivec/Tests/unittest_extension_chain_g.proto + objectivec/Tests/unittest_objc.proto + objectivec/Tests/unittest_objc_startup.proto + objectivec/Tests/unittest_objc_options.proto + objectivec/Tests/unittest_runtime_proto2.proto + objectivec/Tests/unittest_runtime_proto3.proto +) + +OBJC_EXTENSIONS=( .pbobjc.h .pbobjc.m ) + # ----------------------------------------------------------------------------- # Ensure the output dir exists mkdir -p "${OUTPUT_DIR}/google/protobuf" @@ -37,11 +93,27 @@ cd "${SRCROOT}/.." die "Could not find the protoc binary; make sure you have built it (objectivec/DevTools/full_mac_build.sh -h)." # ----------------------------------------------------------------------------- -# See the compiler or proto files have changed. RUN_PROTOC=no -if [[ ! -d "${OUTPUT_DIR}" ]] ; then - RUN_PROTOC=yes -else + +# Check to if all the output files exist (in case a new one got added). + +for PROTO_FILE in "${CORE_PROTO_FILES[@]}" "${OBJC_TEST_PROTO_FILES[@]}"; do + DIR=${PROTO_FILE%/*} + BASE_NAME=${PROTO_FILE##*/} + # Drop the extension + BASE_NAME=${BASE_NAME%.*} + OBJC_NAME=$(echo "${BASE_NAME}" | awk -F _ '{for(i=1; i<=NF; i++) printf "%s", toupper(substr($i,1,1)) substr($i,2);}') + + for EXT in "${OBJC_EXTENSIONS[@]}"; do + if [[ ! -f "${OUTPUT_DIR}/google/protobuf/${OBJC_NAME}${EXT}" ]]; then + RUN_PROTOC=yes + fi + done +done + +# If we haven't decided to run protoc because of a missing file, check to see if +# an input has changed. +if [[ "${RUN_PROTOC}" != "yes" ]] ; then # Find the newest input file (protos, compiler, and this script). # (these patterns catch some extra stuff, but better to over sample than # under) @@ -56,7 +128,7 @@ else # Find the oldest output file. readonly OldestOutput=$(find \ "${OUTPUT_DIR}" \ - -type f -name "*pbobjc.[hm]" -print0 \ + -type f -name "*.pbobjc.[hm]" -print0 \ | xargs -0 stat -f "%m %N" \ | sort -n -r | tail -n1 | cut -f2- -d" ") # If the newest input is newer than the oldest output, regenerate. @@ -74,7 +146,7 @@ fi # Prune out all the files from previous generations to ensure we only have # current ones. find "${OUTPUT_DIR}" \ - -type f -name "*pbobjc.[hm]" -print0 \ + -type f -name "*.pbobjc.[hm]" -print0 \ | xargs -0 rm -rf # ----------------------------------------------------------------------------- @@ -84,43 +156,12 @@ compile_protos() { --objc_out="${OUTPUT_DIR}/google/protobuf" \ --proto_path=src/google/protobuf/ \ --proto_path=src \ + --experimental_allow_proto3_optional \ "$@" } # ----------------------------------------------------------------------------- -# Generate most of the proto files that exist in the C++ src tree. Several -# are used in the tests, but the extra don't hurt in that they ensure ObjC -# sources can be generated from them. - -CORE_PROTO_FILES=( - src/google/protobuf/any_test.proto - src/google/protobuf/unittest_arena.proto - src/google/protobuf/unittest_custom_options.proto - src/google/protobuf/unittest_enormous_descriptor.proto - src/google/protobuf/unittest_embed_optimize_for.proto - src/google/protobuf/unittest_empty.proto - src/google/protobuf/unittest_import.proto - src/google/protobuf/unittest_import_lite.proto - src/google/protobuf/unittest_lite.proto - src/google/protobuf/unittest_mset.proto - src/google/protobuf/unittest_mset_wire_format.proto - src/google/protobuf/unittest_no_arena.proto - src/google/protobuf/unittest_no_arena_import.proto - src/google/protobuf/unittest_no_generic_services.proto - src/google/protobuf/unittest_optimize_for.proto - src/google/protobuf/unittest.proto - src/google/protobuf/unittest_import_public.proto - src/google/protobuf/unittest_import_public_lite.proto - src/google/protobuf/unittest_drop_unknown_fields.proto - src/google/protobuf/unittest_preserve_unknown_enum.proto - src/google/protobuf/map_lite_unittest.proto - src/google/protobuf/map_proto2_unittest.proto - src/google/protobuf/map_unittest.proto - # The unittest_custom_options.proto extends the messages in descriptor.proto - # so we build it in to test extending in general. The library doesn't provide - # a descriptor as it doesn't use the classes/enums. - src/google/protobuf/descriptor.proto -) +# Generate most of the proto files that exist in the C++ src tree. # Note: there is overlap in package.Message names between some of the test # files, so they can't be generated all at once. This works because the overlap @@ -133,17 +174,4 @@ done # Generate the Objective C specific testing protos. compile_protos \ --proto_path="objectivec/Tests" \ - objectivec/Tests/unittest_cycle.proto \ - objectivec/Tests/unittest_deprecated.proto \ - objectivec/Tests/unittest_deprecated_file.proto \ - objectivec/Tests/unittest_extension_chain_a.proto \ - objectivec/Tests/unittest_extension_chain_b.proto \ - objectivec/Tests/unittest_extension_chain_c.proto \ - objectivec/Tests/unittest_extension_chain_d.proto \ - objectivec/Tests/unittest_extension_chain_e.proto \ - objectivec/Tests/unittest_extension_chain_f.proto \ - objectivec/Tests/unittest_extension_chain_g.proto \ - objectivec/Tests/unittest_runtime_proto2.proto \ - objectivec/Tests/unittest_runtime_proto3.proto \ - objectivec/Tests/unittest_objc.proto \ - objectivec/Tests/unittest_objc_startup.proto + "${OBJC_TEST_PROTO_FILES[@]}" diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh index c3cc8e682671d..9319b5587176c 100755 --- a/objectivec/DevTools/full_mac_build.sh +++ b/objectivec/DevTools/full_mac_build.sh @@ -41,8 +41,10 @@ OPTIONS: Skip the Xcode Debug configuration. --skip-xcode-release Skip the Xcode Release configuration. - --skip-xcode-osx + --skip-xcode-osx | --skip-xcode-macos Skip the invoke of Xcode to test the runtime on OS X. + --skip-xcode-tvos + Skip the invoke of Xcode to test the runtime on tvOS. --skip-objc-conformance Skip the Objective C conformance tests (run on OS X). --xcode-quiet @@ -82,6 +84,7 @@ REGEN_DESCRIPTORS=no CORE_ONLY=no DO_XCODE_IOS_TESTS=yes DO_XCODE_OSX_TESTS=yes +DO_XCODE_TVOS_TESTS=yes DO_XCODE_DEBUG=yes DO_XCODE_RELEASE=yes DO_OBJC_CONFORMANCE_TESTS=yes @@ -111,13 +114,17 @@ while [[ $# != 0 ]]; do --skip-xcode ) DO_XCODE_IOS_TESTS=no DO_XCODE_OSX_TESTS=no + DO_XCODE_TVOS_TESTS=no ;; --skip-xcode-ios ) DO_XCODE_IOS_TESTS=no ;; - --skip-xcode-osx ) + --skip-xcode-osx | --skip-xcode-macos) DO_XCODE_OSX_TESTS=no ;; + --skip-xcode-tvos ) + DO_XCODE_TVOS_TESTS=no + ;; --skip-xcode-debug ) DO_XCODE_DEBUG=no ;; @@ -156,8 +163,7 @@ if [[ "${DO_AUTOGEN}" == "yes" ]] ; then header "Running autogen & configure" ./autogen.sh ./configure \ - CPPFLAGS="-mmacosx-version-min=10.9 -Wunused-const-variable -Wunused-function" \ - CXXFLAGS="-Wnon-virtual-dtor -Woverloaded-virtual" + CPPFLAGS="-mmacosx-version-min=10.9 -Wunused-const-variable -Wunused-function" fi if [[ "${DO_CLEAN}" == "yes" ]] ; then @@ -189,6 +195,19 @@ if [[ "${DO_CLEAN}" == "yes" ]] ; then "${XCODEBUILD_CLEAN_BASE_OSX[@]}" -configuration Release clean fi fi + if [[ "${DO_XCODE_TVOS_TESTS}" == "yes" ]] ; then + XCODEBUILD_CLEAN_BASE_OSX=( + xcodebuild + -project objectivec/ProtocolBuffers_tvOS.xcodeproj + -scheme ProtocolBuffers + ) + if [[ "${DO_XCODE_DEBUG}" == "yes" ]] ; then + "${XCODEBUILD_CLEAN_BASE_OSX[@]}" -configuration Debug clean + fi + if [[ "${DO_XCODE_RELEASE}" == "yes" ]] ; then + "${XCODEBUILD_CLEAN_BASE_OSX[@]}" -configuration Release clean + fi + fi fi if [[ "${REGEN_DESCRIPTORS}" == "yes" ]] ; then @@ -239,50 +258,48 @@ if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then # just pick a mix of OS Versions and 32/64 bit. # NOTE: Different Xcode have different simulated hardware/os support. case "${XCODE_VERSION}" in - 6.* ) - echo "ERROR: Xcode 6.3/6.4 no longer supported for building, please use 8.0 or higher." 1>&2 - exit 10 - ;; - 7.* ) - echo "ERROR: The unittests include Swift code that is now Swift 3.0." 1>&2 - echo "ERROR: Xcode 8.0 or higher is required to build the test suite, but the library works with Xcode 7.x." 1>&2 + [6-8].* ) + echo "ERROR: The unittests include Swift code that is now Swift 4.0." 1>&2 + echo "ERROR: Xcode 9.0 or higher is required to build the test suite, but the library works with Xcode 7.x." 1>&2 exit 11 ;; - 8.0* ) - # The 8.* device seem to hang and never start under Xcode 8. + 9.[0-2]* ) XCODEBUILD_TEST_BASE_IOS+=( - -destination "platform=iOS Simulator,name=iPhone 4s,OS=9.0" # 32bit - -destination "platform=iOS Simulator,name=iPhone 7,OS=10.0" # 64bit - -destination "platform=iOS Simulator,name=iPad 2,OS=9.0" # 32bit - -destination "platform=iOS Simulator,name=iPad Pro (9.7 inch),OS=10.0" # 64bit + -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit + -destination "platform=iOS Simulator,name=iPhone 7,OS=latest" # 64bit + # 9.0-9.2 all seem to often fail running destinations in parallel + -disable-concurrent-testing ) ;; - 8.1* ) + 9.[3-4]* ) XCODEBUILD_TEST_BASE_IOS+=( - -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit - -destination "platform=iOS Simulator,name=iPhone 7,OS=10.1" # 64bit - -destination "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit - -destination "platform=iOS Simulator,name=iPad Pro (9.7 inch),OS=10.1" # 64bit + # Xcode 9.3 chokes targeting iOS 8.x - http://www.openradar.me/39335367 + -destination "platform=iOS Simulator,name=iPhone 4s,OS=9.0" # 32bit + -destination "platform=iOS Simulator,name=iPhone 7,OS=latest" # 64bit + # 9.3 also seems to often fail running destinations in parallel + -disable-concurrent-testing ) ;; - 8.2* ) + 10.*) XCODEBUILD_TEST_BASE_IOS+=( -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit - -destination "platform=iOS Simulator,name=iPhone 7,OS=10.2" # 64bit - -destination "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit - -destination "platform=iOS Simulator,name=iPad Pro (9.7 inch),OS=10.2" # 64bit + -destination "platform=iOS Simulator,name=iPhone 7,OS=latest" # 64bit + # 10.x also seems to often fail running destinations in parallel (with + # 32bit one include at least) + -disable-concurrent-destination-testing ) ;; - 8.3* ) + 11.* | 12.*) + # Dropped 32bit as Apple doesn't seem support the simulators either. XCODEBUILD_TEST_BASE_IOS+=( - -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit - -destination "platform=iOS Simulator,name=iPhone 7,OS=10.3" # 64bit - -destination "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit - -destination "platform=iOS Simulator,name=iPad Pro (9.7 inch),OS=10.3" # 64bit + -destination "platform=iOS Simulator,name=iPhone 8,OS=latest" # 64bit ) ;; * ) - echo "Time to update the simulator targets for Xcode ${XCODE_VERSION}" + echo "" + echo "ATTENTION: Time to update the simulator targets for Xcode ${XCODE_VERSION}" + echo "" + echo "ERROR: Build aborted!" exit 2 ;; esac @@ -295,7 +312,7 @@ if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then "${XCODEBUILD_TEST_BASE_IOS[@]}" -configuration Release test fi # Don't leave the simulator in the developer's face. - killall Simulator + killall Simulator 2> /dev/null || true fi if [[ "${DO_XCODE_OSX_TESTS}" == "yes" ]] ; then XCODEBUILD_TEST_BASE_OSX=( @@ -309,13 +326,9 @@ if [[ "${DO_XCODE_OSX_TESTS}" == "yes" ]] ; then XCODEBUILD_TEST_BASE_OSX+=( -quiet ) fi case "${XCODE_VERSION}" in - 6.* ) - echo "ERROR: Xcode 6.3/6.4 no longer supported for building, please use 8.0 or higher." 1>&2 - exit 10 - ;; - 7.* ) - echo "ERROR: The unittests include Swift code that is now Swift 3.0." 1>&2 - echo "ERROR: Xcode 8.0 or higher is required to build the test suite, but the library works with Xcode 7.x." 1>&2 + [6-8].* ) + echo "ERROR: The unittests include Swift code that is now Swift 4.0." 1>&2 + echo "ERROR: Xcode 9.0 or higher is required to build the test suite, but the library works with Xcode 7.x." 1>&2 exit 11 ;; esac @@ -328,6 +341,42 @@ if [[ "${DO_XCODE_OSX_TESTS}" == "yes" ]] ; then "${XCODEBUILD_TEST_BASE_OSX[@]}" -configuration Release test fi fi +if [[ "${DO_XCODE_TVOS_TESTS}" == "yes" ]] ; then + XCODEBUILD_TEST_BASE_TVOS=( + xcodebuild + -project objectivec/ProtocolBuffers_tvOS.xcodeproj + -scheme ProtocolBuffers + ) + case "${XCODE_VERSION}" in + [6-9].* ) + echo "ERROR: Xcode 10.0 or higher is required to build the test suite." 1>&2 + exit 11 + ;; + 10.* | 11.* | 12.*) + XCODEBUILD_TEST_BASE_TVOS+=( + -destination "platform=tvOS Simulator,name=Apple TV 4K,OS=latest" + ) + ;; + * ) + echo "" + echo "ATTENTION: Time to update the simulator targets for Xcode ${XCODE_VERSION}" + echo "" + echo "ERROR: Build aborted!" + exit 2 + ;; + esac + if [[ "${XCODE_QUIET}" == "yes" ]] ; then + XCODEBUILD_TEST_BASE_TVOS+=( -quiet ) + fi + if [[ "${DO_XCODE_DEBUG}" == "yes" ]] ; then + header "Doing Xcode tvOS build/tests - Debug" + "${XCODEBUILD_TEST_BASE_TVOS[@]}" -configuration Debug test + fi + if [[ "${DO_XCODE_RELEASE}" == "yes" ]] ; then + header "Doing Xcode tvOS build/tests - Release" + "${XCODEBUILD_TEST_BASE_TVOS[@]}" -configuration Release test + fi +fi if [[ "${DO_OBJC_CONFORMANCE_TESTS}" == "yes" ]] ; then header "Running ObjC Conformance Tests" @@ -335,3 +384,6 @@ if [[ "${DO_OBJC_CONFORMANCE_TESTS}" == "yes" ]] ; then wrapped_make -j "${NUM_MAKE_JOBS}" test_objc cd .. fi + +echo "" +echo "$(basename "${0}"): Success!" diff --git a/objectivec/DevTools/pddm.py b/objectivec/DevTools/pddm.py index 9a11fec449ed7..b572cc75b6183 100755 --- a/objectivec/DevTools/pddm.py +++ b/objectivec/DevTools/pddm.py @@ -124,6 +124,7 @@ def _MacroRefRe(macro_names): return re.compile(r'\b(?P(?P(%s))\((?P.*?)\))' % '|'.join(macro_names)) + def _MacroArgRefRe(macro_arg_names): # Takes in a list of macro arg names and makes a regex that will match # uses of those args. @@ -287,7 +288,7 @@ def _Expand(self, macro_ref_match, macro_stack, macro_ref_str=None): name = macro_ref_match.group('name') for prev_name, prev_macro_ref in macro_stack: if name == prev_name: - raise PDDMError('Found macro recusion, invoking "%s":%s' % + raise PDDMError('Found macro recursion, invoking "%s":%s' % (macro_ref_str, self._FormatStack(macro_stack))) macro = self._macros[name] args_str = macro_ref_match.group('args').strip() @@ -318,25 +319,26 @@ def _ReplaceArgValues(self, return macro.body assert len(arg_values) == len(macro.args) args = dict(zip(macro.args, arg_values)) + def _lookupArg(match): val = args[match.group('name')] opt = match.group('option') if opt: - if opt == 'S': # Spaces for the length + if opt == 'S': # Spaces for the length return ' ' * len(val) - elif opt == 'l': # Lowercase first character + elif opt == 'l': # Lowercase first character if val: return val[0].lower() + val[1:] else: return val - elif opt == 'L': # All Lowercase + elif opt == 'L': # All Lowercase return val.lower() - elif opt == 'u': # Uppercase first character + elif opt == 'u': # Uppercase first character if val: return val[0].upper() + val[1:] else: return val - elif opt == 'U': # All Uppercase + elif opt == 'U': # All Uppercase return val.upper() else: raise PDDMError('Unknown arg option "%s$%s" while expanding "%s".%s' @@ -350,6 +352,7 @@ def _lookupArg(match): def _EvalMacrosRefs(self, text, macro_stack): macro_ref_re = _MacroRefRe(self._macros.keys()) + def _resolveMacro(match): return self._Expand(match, macro_stack) return macro_ref_re.sub(_resolveMacro, text) @@ -392,7 +395,7 @@ def TryAppend(self, line, line_num): wasn't append. If SUCCESS is True, then CAN_ADD_MORE is True/False to indicate if more lines can be added after this one. """ - assert False, "sublcass should have overridden" + assert False, "subclass should have overridden" return (False, False) def HitEOF(self): @@ -479,13 +482,14 @@ def lines(self): if self._macro_collection: # Always add a blank line, seems to read better. (If need be, add an # option to the EXPAND to indicate if this should be done.) - result.extend([_GENERATED_CODE_LINE, '']) + result.extend([_GENERATED_CODE_LINE, '// clang-format off', '']) macro = line[directive_len:].strip() try: expand_result = self._macro_collection.Expand(macro) # Since expansions are line oriented, strip trailing whitespace # from the lines. lines = [x.rstrip() for x in expand_result.split('\n')] + lines.append('// clang-format on') result.append('\n'.join(lines)) except PDDMError as e: raise PDDMError('%s\n...while expanding "%s" from the section' @@ -496,10 +500,10 @@ def lines(self): # Add the ending marker. if len(captured_lines) == 1: result.append('//%%PDDM-EXPAND-END %s' % - captured_lines[0][directive_len:].strip()) + captured_lines[0][directive_len:].strip()) else: - result.append('//%%PDDM-EXPAND-END (%s expansions)' % len(captured_lines)) - + result.append('//%%PDDM-EXPAND-END (%s expansions)' % + len(captured_lines)) return result class DefinitionSection(SectionBase): @@ -641,7 +645,7 @@ def main(args): opts, extra_args = parser.parse_args(args) if not extra_args: - parser.error('Need atleast one file to process') + parser.error('Need at least one file to process') result = 0 for a_path in extra_args: @@ -669,15 +673,15 @@ def _ImportResolver(name): if src_file.processed_content != src_file.original_content: if not opts.dry_run: - print 'Updating for "%s".' % a_path + print('Updating for "%s".' % a_path) with open(a_path, 'w') as f: f.write(src_file.processed_content) else: # Special result to indicate things need updating. - print 'Update needed for "%s".' % a_path + print('Update needed for "%s".' % a_path) result = 1 elif opts.verbose: - print 'No update for "%s".' % a_path + print('No update for "%s".' % a_path) return result diff --git a/objectivec/DevTools/pddm_tests.py b/objectivec/DevTools/pddm_tests.py index 8a73b8427bcf5..81842090ccaa7 100755 --- a/objectivec/DevTools/pddm_tests.py +++ b/objectivec/DevTools/pddm_tests.py @@ -311,10 +311,10 @@ def testCatchRecursion(self): mc = pddm.MacroCollection(f) try: result = mc.Expand('foo(A,B)') - self.fail('Should throw exception, entry %d' % idx) + self.fail('Should throw exception! Test failed to catch recursion.') except pddm.PDDMError as e: self.assertEqual(e.message, - 'Found macro recusion, invoking "foo(1, A)":\n...while expanding "bar(1, A)".\n...while expanding "foo(A,B)".') + 'Found macro recursion, invoking "foo(1, A)":\n...while expanding "bar(1, A)".\n...while expanding "foo(A,B)".') class TestParsingSource(unittest.TestCase): @@ -394,6 +394,7 @@ def testErrors(self): class TestProcessingSource(unittest.TestCase): def testBasics(self): + self.maxDiff = None input_str = u""" //%PDDM-IMPORT-DEFINES ImportFile foo @@ -417,18 +418,24 @@ def testBasics(self): foo //%PDDM-EXPAND mumble(abc) // This block of code is generated, do not edit it directly. +// clang-format off abc: doAbc(int abc); +// clang-format on //%PDDM-EXPAND-END mumble(abc) bar //%PDDM-EXPAND mumble(def) // This block of code is generated, do not edit it directly. +// clang-format off def: doDef(int def); +// clang-format on //%PDDM-EXPAND mumble(ghi) // This block of code is generated, do not edit it directly. +// clang-format off ghi: doGhi(int ghi); +// clang-format on //%PDDM-EXPAND-END (2 expansions) baz //%PDDM-DEFINE mumble(a_) @@ -483,7 +490,7 @@ def testProcessFileWithMacroParseError(self): sf = pddm.SourceFile(f) try: sf.ProcessContent() - self.fail('Should throw exception, entry %d' % idx) + self.fail('Should throw exception! Test failed to catch macro parsing error.') except pddm.PDDMError as e: self.assertEqual(e.message, 'Attempt to redefine macro: "PDDM-DEFINE mumble(x_)"\n' @@ -503,7 +510,7 @@ def testProcessFileWithExpandError(self): sf = pddm.SourceFile(f) try: sf.ProcessContent() - self.fail('Should throw exception, entry %d' % idx) + self.fail('Should throw exception! Test failed to catch expand error.') except pddm.PDDMError as e: self.assertEqual(e.message, 'No macro named "foobar".\n' diff --git a/objectivec/GPBAny.pbobjc.h b/objectivec/GPBAny.pbobjc.h new file mode 100644 index 0000000000000..21b7dcf4afb4c --- /dev/null +++ b/objectivec/GPBAny.pbobjc.h @@ -0,0 +1,186 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/any.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBAnyRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +GPB_FINAL @interface GPBAnyRoot : GPBRootObject +@end + +#pragma mark - GPBAny + +typedef GPB_ENUM(GPBAny_FieldNumber) { + GPBAny_FieldNumber_TypeURL = 1, + GPBAny_FieldNumber_Value = 2, +}; + +/** + * `Any` contains an arbitrary serialized protocol buffer message along with a + * URL that describes the type of the serialized message. + * + * Protobuf library provides support to pack/unpack Any values in the form + * of utility functions or additional generated methods of the Any type. + * + * Example 1: Pack and unpack a message in C++. + * + * Foo foo = ...; + * Any any; + * any.PackFrom(foo); + * ... + * if (any.UnpackTo(&foo)) { + * ... + * } + * + * Example 2: Pack and unpack a message in Java. + * + * Foo foo = ...; + * Any any = Any.pack(foo); + * ... + * if (any.is(Foo.class)) { + * foo = any.unpack(Foo.class); + * } + * + * Example 3: Pack and unpack a message in Python. + * + * foo = Foo(...) + * any = Any() + * any.Pack(foo) + * ... + * if any.Is(Foo.DESCRIPTOR): + * any.Unpack(foo) + * ... + * + * Example 4: Pack and unpack a message in Go + * + * foo := &pb.Foo{...} + * any, err := anypb.New(foo) + * if err != nil { + * ... + * } + * ... + * foo := &pb.Foo{} + * if err := any.UnmarshalTo(foo); err != nil { + * ... + * } + * + * The pack methods provided by protobuf library will by default use + * 'type.googleapis.com/full.type.name' as the type URL and the unpack + * methods only use the fully qualified type name after the last '/' + * in the type URL, for example "foo.bar.com/x/y.z" will yield type + * name "y.z". + * + * + * JSON + * ==== + * The JSON representation of an `Any` value uses the regular + * representation of the deserialized, embedded message, with an + * additional field `\@type` which contains the type URL. Example: + * + * package google.profile; + * message Person { + * string first_name = 1; + * string last_name = 2; + * } + * + * { + * "\@type": "type.googleapis.com/google.profile.Person", + * "firstName": , + * "lastName": + * } + * + * If the embedded message type is well-known and has a custom JSON + * representation, that representation will be embedded adding a field + * `value` which holds the custom JSON in addition to the `\@type` + * field. Example (for message [google.protobuf.Duration][]): + * + * { + * "\@type": "type.googleapis.com/google.protobuf.Duration", + * "value": "1.212s" + * } + **/ +GPB_FINAL @interface GPBAny : GPBMessage + +/** + * A URL/resource name that uniquely identifies the type of the serialized + * protocol buffer message. This string must contain at least + * one "/" character. The last segment of the URL's path must represent + * the fully qualified name of the type (as in + * `path/google.protobuf.Duration`). The name should be in a canonical form + * (e.g., leading "." is not accepted). + * + * In practice, teams usually precompile into the binary all types that they + * expect it to use in the context of Any. However, for URLs which use the + * scheme `http`, `https`, or no scheme, one can optionally set up a type + * server that maps type URLs to message definitions as follows: + * + * * If no scheme is provided, `https` is assumed. + * * An HTTP GET on the URL must yield a [google.protobuf.Type][] + * value in binary format, or produce an error. + * * Applications are allowed to cache lookup results based on the + * URL, or have them precompiled into a binary to avoid any + * lookup. Therefore, binary compatibility needs to be preserved + * on changes to types. (Use versioned type names to manage + * breaking changes.) + * + * Note: this functionality is not currently available in the official + * protobuf release, and it is not used for type URLs beginning with + * type.googleapis.com. + * + * Schemes other than `http`, `https` (or the empty scheme) might be + * used with implementation specific semantics. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL; + +/** Must be a valid serialized protocol buffer of the above specified type. */ +@property(nonatomic, readwrite, copy, null_resettable) NSData *value; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBAny.pbobjc.m b/objectivec/GPBAny.pbobjc.m new file mode 100644 index 0000000000000..a5143f15dc3ca --- /dev/null +++ b/objectivec/GPBAny.pbobjc.m @@ -0,0 +1,114 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/any.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBAny.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBAnyRoot + +@implementation GPBAnyRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBAnyRoot_FileDescriptor + +static GPBFileDescriptor *GPBAnyRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBAny + +@implementation GPBAny + +@dynamic typeURL; +@dynamic value; + +typedef struct GPBAny__storage_ { + uint32_t _has_storage_[1]; + NSString *typeURL; + NSData *value; +} GPBAny__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "typeURL", + .dataTypeSpecific.clazz = Nil, + .number = GPBAny_FieldNumber_TypeURL, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBAny__storage_, typeURL), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "value", + .dataTypeSpecific.clazz = Nil, + .number = GPBAny_FieldNumber_Value, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBAny__storage_, value), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBytes, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBAny class] + rootClass:[GPBAnyRoot class] + file:GPBAnyRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBAny__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\001\001\004\241!!\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBApi.pbobjc.h b/objectivec/GPBApi.pbobjc.h new file mode 100644 index 0000000000000..5d55ebf39921a --- /dev/null +++ b/objectivec/GPBApi.pbobjc.h @@ -0,0 +1,311 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/api.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +@class GPBMethod; +@class GPBMixin; +@class GPBOption; +@class GPBSourceContext; +GPB_ENUM_FWD_DECLARE(GPBSyntax); + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBApiRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +GPB_FINAL @interface GPBApiRoot : GPBRootObject +@end + +#pragma mark - GPBApi + +typedef GPB_ENUM(GPBApi_FieldNumber) { + GPBApi_FieldNumber_Name = 1, + GPBApi_FieldNumber_MethodsArray = 2, + GPBApi_FieldNumber_OptionsArray = 3, + GPBApi_FieldNumber_Version = 4, + GPBApi_FieldNumber_SourceContext = 5, + GPBApi_FieldNumber_MixinsArray = 6, + GPBApi_FieldNumber_Syntax = 7, +}; + +/** + * Api is a light-weight descriptor for an API Interface. + * + * Interfaces are also described as "protocol buffer services" in some contexts, + * such as by the "service" keyword in a .proto file, but they are different + * from API Services, which represent a concrete implementation of an interface + * as opposed to simply a description of methods and bindings. They are also + * sometimes simply referred to as "APIs" in other contexts, such as the name of + * this message itself. See https://cloud.google.com/apis/design/glossary for + * detailed terminology. + **/ +GPB_FINAL @interface GPBApi : GPBMessage + +/** + * The fully qualified name of this interface, including package name + * followed by the interface's simple name. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** The methods of this interface, in unspecified order. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *methodsArray; +/** The number of items in @c methodsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger methodsArray_Count; + +/** Any metadata attached to the interface. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** + * A version string for this interface. If specified, must have the form + * `major-version.minor-version`, as in `1.10`. If the minor version is + * omitted, it defaults to zero. If the entire version field is empty, the + * major version is derived from the package name, as outlined below. If the + * field is not empty, the version in the package name will be verified to be + * consistent with what is provided here. + * + * The versioning schema uses [semantic + * versioning](http://semver.org) where the major version number + * indicates a breaking change and the minor version an additive, + * non-breaking change. Both version numbers are signals to users + * what to expect from different versions, and should be carefully + * chosen based on the product plan. + * + * The major version is also reflected in the package name of the + * interface, which must end in `v`, as in + * `google.feature.v1`. For major versions 0 and 1, the suffix can + * be omitted. Zero major versions must only be used for + * experimental, non-GA interfaces. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *version; + +/** + * Source context for the protocol buffer service represented by this + * message. + **/ +@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; +/** Test to see if @c sourceContext has been set. */ +@property(nonatomic, readwrite) BOOL hasSourceContext; + +/** Included interfaces. See [Mixin][]. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *mixinsArray; +/** The number of items in @c mixinsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger mixinsArray_Count; + +/** The source syntax of the service. */ +@property(nonatomic, readwrite) enum GPBSyntax syntax; + +@end + +/** + * Fetches the raw value of a @c GPBApi's @c syntax property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBApi_Syntax_RawValue(GPBApi *message); +/** + * Sets the raw value of an @c GPBApi's @c syntax property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value); + +#pragma mark - GPBMethod + +typedef GPB_ENUM(GPBMethod_FieldNumber) { + GPBMethod_FieldNumber_Name = 1, + GPBMethod_FieldNumber_RequestTypeURL = 2, + GPBMethod_FieldNumber_RequestStreaming = 3, + GPBMethod_FieldNumber_ResponseTypeURL = 4, + GPBMethod_FieldNumber_ResponseStreaming = 5, + GPBMethod_FieldNumber_OptionsArray = 6, + GPBMethod_FieldNumber_Syntax = 7, +}; + +/** + * Method represents a method of an API interface. + **/ +GPB_FINAL @interface GPBMethod : GPBMessage + +/** The simple name of this method. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** A URL of the input message type. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *requestTypeURL; + +/** If true, the request is streamed. */ +@property(nonatomic, readwrite) BOOL requestStreaming; + +/** The URL of the output message type. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *responseTypeURL; + +/** If true, the response is streamed. */ +@property(nonatomic, readwrite) BOOL responseStreaming; + +/** Any metadata attached to the method. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** The source syntax of this method. */ +@property(nonatomic, readwrite) enum GPBSyntax syntax; + +@end + +/** + * Fetches the raw value of a @c GPBMethod's @c syntax property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBMethod_Syntax_RawValue(GPBMethod *message); +/** + * Sets the raw value of an @c GPBMethod's @c syntax property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value); + +#pragma mark - GPBMixin + +typedef GPB_ENUM(GPBMixin_FieldNumber) { + GPBMixin_FieldNumber_Name = 1, + GPBMixin_FieldNumber_Root = 2, +}; + +/** + * Declares an API Interface to be included in this interface. The including + * interface must redeclare all the methods from the included interface, but + * documentation and options are inherited as follows: + * + * - If after comment and whitespace stripping, the documentation + * string of the redeclared method is empty, it will be inherited + * from the original method. + * + * - Each annotation belonging to the service config (http, + * visibility) which is not set in the redeclared method will be + * inherited. + * + * - If an http annotation is inherited, the path pattern will be + * modified as follows. Any version prefix will be replaced by the + * version of the including interface plus the [root][] path if + * specified. + * + * Example of a simple mixin: + * + * package google.acl.v1; + * service AccessControl { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v1/{resource=**}:getAcl"; + * } + * } + * + * package google.storage.v2; + * service Storage { + * rpc GetAcl(GetAclRequest) returns (Acl); + * + * // Get a data record. + * rpc GetData(GetDataRequest) returns (Data) { + * option (google.api.http).get = "/v2/{resource=**}"; + * } + * } + * + * Example of a mixin configuration: + * + * apis: + * - name: google.storage.v2.Storage + * mixins: + * - name: google.acl.v1.AccessControl + * + * The mixin construct implies that all methods in `AccessControl` are + * also declared with same name and request/response types in + * `Storage`. A documentation generator or annotation processor will + * see the effective `Storage.GetAcl` method after inheriting + * documentation and annotations as follows: + * + * service Storage { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v2/{resource=**}:getAcl"; + * } + * ... + * } + * + * Note how the version in the path pattern changed from `v1` to `v2`. + * + * If the `root` field in the mixin is specified, it should be a + * relative path under which inherited HTTP paths are placed. Example: + * + * apis: + * - name: google.storage.v2.Storage + * mixins: + * - name: google.acl.v1.AccessControl + * root: acls + * + * This implies the following inherited HTTP annotation: + * + * service Storage { + * // Get the underlying ACL object. + * rpc GetAcl(GetAclRequest) returns (Acl) { + * option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; + * } + * ... + * } + **/ +GPB_FINAL @interface GPBMixin : GPBMessage + +/** The fully qualified name of the interface which is included. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** + * If non-empty specifies a path under which inherited HTTP paths + * are rooted. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *root; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBApi.pbobjc.m b/objectivec/GPBApi.pbobjc.m new file mode 100644 index 0000000000000..5915ce1122628 --- /dev/null +++ b/objectivec/GPBApi.pbobjc.m @@ -0,0 +1,372 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/api.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBApi.pbobjc.h" + #import "GPBSourceContext.pbobjc.h" + #import "GPBType.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" + +#pragma mark - Objective C Class declarations +// Forward declarations of Objective C classes that we can use as +// static values in struct initializers. +// We don't use [Foo class] because it is not a static value. +GPBObjCClassDeclaration(GPBMethod); +GPBObjCClassDeclaration(GPBMixin); +GPBObjCClassDeclaration(GPBOption); +GPBObjCClassDeclaration(GPBSourceContext); + +#pragma mark - GPBApiRoot + +@implementation GPBApiRoot + +// No extensions in the file and none of the imports (direct or indirect) +// defined extensions, so no need to generate +extensionRegistry. + +@end + +#pragma mark - GPBApiRoot_FileDescriptor + +static GPBFileDescriptor *GPBApiRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBApi + +@implementation GPBApi + +@dynamic name; +@dynamic methodsArray, methodsArray_Count; +@dynamic optionsArray, optionsArray_Count; +@dynamic version; +@dynamic hasSourceContext, sourceContext; +@dynamic mixinsArray, mixinsArray_Count; +@dynamic syntax; + +typedef struct GPBApi__storage_ { + uint32_t _has_storage_[1]; + GPBSyntax syntax; + NSString *name; + NSMutableArray *methodsArray; + NSMutableArray *optionsArray; + NSString *version; + GPBSourceContext *sourceContext; + NSMutableArray *mixinsArray; +} GPBApi__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.clazz = Nil, + .number = GPBApi_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBApi__storage_, name), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "methodsArray", + .dataTypeSpecific.clazz = GPBObjCClass(GPBMethod), + .number = GPBApi_FieldNumber_MethodsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBApi__storage_, methodsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "optionsArray", + .dataTypeSpecific.clazz = GPBObjCClass(GPBOption), + .number = GPBApi_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBApi__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "version", + .dataTypeSpecific.clazz = Nil, + .number = GPBApi_FieldNumber_Version, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBApi__storage_, version), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "sourceContext", + .dataTypeSpecific.clazz = GPBObjCClass(GPBSourceContext), + .number = GPBApi_FieldNumber_SourceContext, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GPBApi__storage_, sourceContext), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "mixinsArray", + .dataTypeSpecific.clazz = GPBObjCClass(GPBMixin), + .number = GPBApi_FieldNumber_MixinsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBApi__storage_, mixinsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "syntax", + .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, + .number = GPBApi_FieldNumber_Syntax, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GPBApi__storage_, syntax), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeEnum, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBApi class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBApi__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBApi_Syntax_RawValue(GPBApi *message) { + GPBDescriptor *descriptor = [GPBApi descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax]; + return GPBGetMessageRawEnumField(message, field); +} + +void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value) { + GPBDescriptor *descriptor = [GPBApi descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax]; + GPBSetMessageRawEnumField(message, field, value); +} + +#pragma mark - GPBMethod + +@implementation GPBMethod + +@dynamic name; +@dynamic requestTypeURL; +@dynamic requestStreaming; +@dynamic responseTypeURL; +@dynamic responseStreaming; +@dynamic optionsArray, optionsArray_Count; +@dynamic syntax; + +typedef struct GPBMethod__storage_ { + uint32_t _has_storage_[1]; + GPBSyntax syntax; + NSString *name; + NSString *requestTypeURL; + NSString *responseTypeURL; + NSMutableArray *optionsArray; +} GPBMethod__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.clazz = Nil, + .number = GPBMethod_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBMethod__storage_, name), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "requestTypeURL", + .dataTypeSpecific.clazz = Nil, + .number = GPBMethod_FieldNumber_RequestTypeURL, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBMethod__storage_, requestTypeURL), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "requestStreaming", + .dataTypeSpecific.clazz = Nil, + .number = GPBMethod_FieldNumber_RequestStreaming, + .hasIndex = 2, + .offset = 3, // Stored in _has_storage_ to save space. + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBool, + }, + { + .name = "responseTypeURL", + .dataTypeSpecific.clazz = Nil, + .number = GPBMethod_FieldNumber_ResponseTypeURL, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GPBMethod__storage_, responseTypeURL), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "responseStreaming", + .dataTypeSpecific.clazz = Nil, + .number = GPBMethod_FieldNumber_ResponseStreaming, + .hasIndex = 5, + .offset = 6, // Stored in _has_storage_ to save space. + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBool, + }, + { + .name = "optionsArray", + .dataTypeSpecific.clazz = GPBObjCClass(GPBOption), + .number = GPBMethod_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBMethod__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "syntax", + .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, + .number = GPBMethod_FieldNumber_Syntax, + .hasIndex = 7, + .offset = (uint32_t)offsetof(GPBMethod__storage_, syntax), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeEnum, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBMethod class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBMethod__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\002\002\007\244\241!!\000\004\010\244\241!!\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBMethod_Syntax_RawValue(GPBMethod *message) { + GPBDescriptor *descriptor = [GPBMethod descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax]; + return GPBGetMessageRawEnumField(message, field); +} + +void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value) { + GPBDescriptor *descriptor = [GPBMethod descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax]; + GPBSetMessageRawEnumField(message, field, value); +} + +#pragma mark - GPBMixin + +@implementation GPBMixin + +@dynamic name; +@dynamic root; + +typedef struct GPBMixin__storage_ { + uint32_t _has_storage_[1]; + NSString *name; + NSString *root; +} GPBMixin__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.clazz = Nil, + .number = GPBMixin_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBMixin__storage_, name), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "root", + .dataTypeSpecific.clazz = Nil, + .number = GPBMixin_FieldNumber_Root, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBMixin__storage_, root), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBMixin class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBMixin__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBArray.h b/objectivec/GPBArray.h index 638b2882d3f82..5aea75cd6e967 100644 --- a/objectivec/GPBArray.h +++ b/objectivec/GPBArray.h @@ -36,6 +36,7 @@ NS_ASSUME_NONNULL_BEGIN //%PDDM-EXPAND DECLARE_ARRAYS() // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Int32 @@ -134,7 +135,7 @@ NS_ASSUME_NONNULL_BEGIN * **idx**: The index of the current value. * **stop**: A pointer to a boolean that when set stops the enumeration. **/ -- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block; +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; /** * Enumerates the values on this array with the given block. @@ -146,7 +147,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block; + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; /** * Adds a value to this array. @@ -306,7 +307,7 @@ NS_ASSUME_NONNULL_BEGIN * **idx**: The index of the current value. * **stop**: A pointer to a boolean that when set stops the enumeration. **/ -- (void)enumerateValuesWithBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block; +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block; /** * Enumerates the values on this array with the given block. @@ -318,7 +319,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block; + usingBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block; /** * Adds a value to this array. @@ -478,7 +479,7 @@ NS_ASSUME_NONNULL_BEGIN * **idx**: The index of the current value. * **stop**: A pointer to a boolean that when set stops the enumeration. **/ -- (void)enumerateValuesWithBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block; +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block; /** * Enumerates the values on this array with the given block. @@ -490,7 +491,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block; + usingBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block; /** * Adds a value to this array. @@ -650,7 +651,7 @@ NS_ASSUME_NONNULL_BEGIN * **idx**: The index of the current value. * **stop**: A pointer to a boolean that when set stops the enumeration. **/ -- (void)enumerateValuesWithBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block; +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block; /** * Enumerates the values on this array with the given block. @@ -662,7 +663,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block; + usingBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block; /** * Adds a value to this array. @@ -822,7 +823,7 @@ NS_ASSUME_NONNULL_BEGIN * **idx**: The index of the current value. * **stop**: A pointer to a boolean that when set stops the enumeration. **/ -- (void)enumerateValuesWithBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block; +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block; /** * Enumerates the values on this array with the given block. @@ -834,7 +835,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block; + usingBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block; /** * Adds a value to this array. @@ -994,7 +995,7 @@ NS_ASSUME_NONNULL_BEGIN * **idx**: The index of the current value. * **stop**: A pointer to a boolean that when set stops the enumeration. **/ -- (void)enumerateValuesWithBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block; +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block; /** * Enumerates the values on this array with the given block. @@ -1006,7 +1007,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block; + usingBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block; /** * Adds a value to this array. @@ -1166,7 +1167,7 @@ NS_ASSUME_NONNULL_BEGIN * **idx**: The index of the current value. * **stop**: A pointer to a boolean that when set stops the enumeration. **/ -- (void)enumerateValuesWithBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block; +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block; /** * Enumerates the values on this array with the given block. @@ -1178,7 +1179,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block; + usingBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block; /** * Adds a value to this array. @@ -1369,7 +1370,7 @@ NS_ASSUME_NONNULL_BEGIN * **idx**: The index of the current value. * **stop**: A pointer to a boolean that when set stops the enumeration. **/ -- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block; +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; /** * Enumerates the values on this array with the given block. @@ -1381,7 +1382,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block; + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; // These methods bypass the validationFunc to provide access to values that were not // known at the time the binary was compiled. @@ -1403,7 +1404,7 @@ NS_ASSUME_NONNULL_BEGIN * **idx**: The index of the current value. * **stop**: A pointer to a boolean that when set stops the enumeration. **/ -- (void)enumerateRawValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block; +- (void)enumerateRawValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; /** * Enumerates the values on this array with the given block. @@ -1415,7 +1416,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block; + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block; // If value is not a valid enumerator as defined by validationFunc, these // methods will assert in debug, and will log in release and assign the value @@ -1535,6 +1536,7 @@ NS_ASSUME_NONNULL_BEGIN @end +// clang-format on //%PDDM-EXPAND-END DECLARE_ARRAYS() NS_ASSUME_NONNULL_END @@ -1779,7 +1781,7 @@ NS_ASSUME_NONNULL_END //% * **idx**: The index of the current value. //% * **stop**: A pointer to a boolean that when set stops the enumeration. //% **/ -//%- (void)enumerateRawValuesWithBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block; +//%- (void)enumerateRawValuesWithBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block; //% //%/** //% * Enumerates the values on this array with the given block. @@ -1791,7 +1793,7 @@ NS_ASSUME_NONNULL_END //% * **stop**: A pointer to a boolean that when set stops the enumeration. //% **/ //%- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts -//% usingBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block; +//% usingBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block; //% //%// If value is not a valid enumerator as defined by validationFunc, these //%// methods will assert in debug, and will log in release and assign the value @@ -1821,7 +1823,7 @@ NS_ASSUME_NONNULL_END //% * **idx**: The index of the current value. //% * **stop**: A pointer to a boolean that when set stops the enumeration. //% **/ -//%- (void)enumerateValuesWithBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block; +//%- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block; //% //%/** //% * Enumerates the values on this array with the given block. @@ -1833,7 +1835,7 @@ NS_ASSUME_NONNULL_END //% * **stop**: A pointer to a boolean that when set stops the enumeration. //% **/ //%- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts -//% usingBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block; +//% usingBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block; //%PDDM-DEFINE ARRAY_MUTABLE_INTERFACE(NAME, TYPE, HELPER_NAME) //%/** diff --git a/objectivec/GPBArray.m b/objectivec/GPBArray.m index f401631d12ff1..bb9a0777af793 100644 --- a/objectivec/GPBArray.m +++ b/objectivec/GPBArray.m @@ -194,12 +194,12 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { //% return result; //%} //% -//%- (void)enumerate##ACCESSOR_NAME##ValuesWithBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block { +//%- (void)enumerate##ACCESSOR_NAME##ValuesWithBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block { //% [self enumerate##ACCESSOR_NAME##ValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; //%} //% //%- (void)enumerate##ACCESSOR_NAME##ValuesWithOptions:(NSEnumerationOptions)opts -//% ACCESSOR_NAME$S usingBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block { +//% ACCESSOR_NAME$S usingBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block { //% // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). //% BOOL stop = NO; //% if ((opts & NSEnumerationReverse) == 0) { @@ -295,6 +295,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { //%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Int32, int32_t, %d) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Int32 @@ -405,12 +406,12 @@ - (NSString *)description { return result; } -- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block { +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block { + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). BOOL stop = NO; if ((opts & NSEnumerationReverse) == 0) { @@ -541,8 +542,10 @@ - (void)exchangeValueAtIndex:(NSUInteger)idx1 @end +// clang-format on //%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(UInt32, uint32_t, %u) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - UInt32 @@ -653,12 +656,12 @@ - (NSString *)description { return result; } -- (void)enumerateValuesWithBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block { +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block { [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block { + usingBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block { // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). BOOL stop = NO; if ((opts & NSEnumerationReverse) == 0) { @@ -789,8 +792,10 @@ - (void)exchangeValueAtIndex:(NSUInteger)idx1 @end +// clang-format on //%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Int64, int64_t, %lld) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Int64 @@ -901,12 +906,12 @@ - (NSString *)description { return result; } -- (void)enumerateValuesWithBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block { +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block { [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block { + usingBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block { // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). BOOL stop = NO; if ((opts & NSEnumerationReverse) == 0) { @@ -1037,8 +1042,10 @@ - (void)exchangeValueAtIndex:(NSUInteger)idx1 @end +// clang-format on //%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(UInt64, uint64_t, %llu) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - UInt64 @@ -1149,12 +1156,12 @@ - (NSString *)description { return result; } -- (void)enumerateValuesWithBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block { +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block { [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block { + usingBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block { // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). BOOL stop = NO; if ((opts & NSEnumerationReverse) == 0) { @@ -1285,8 +1292,10 @@ - (void)exchangeValueAtIndex:(NSUInteger)idx1 @end +// clang-format on //%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Float, float, %f) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Float @@ -1397,12 +1406,12 @@ - (NSString *)description { return result; } -- (void)enumerateValuesWithBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block { +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block { [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block { + usingBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block { // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). BOOL stop = NO; if ((opts & NSEnumerationReverse) == 0) { @@ -1533,8 +1542,10 @@ - (void)exchangeValueAtIndex:(NSUInteger)idx1 @end +// clang-format on //%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Double, double, %lf) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Double @@ -1645,12 +1656,12 @@ - (NSString *)description { return result; } -- (void)enumerateValuesWithBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block { +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block { [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block { + usingBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block { // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). BOOL stop = NO; if ((opts & NSEnumerationReverse) == 0) { @@ -1781,8 +1792,10 @@ - (void)exchangeValueAtIndex:(NSUInteger)idx1 @end +// clang-format on //%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Bool, BOOL, %d) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool @@ -1893,12 +1906,12 @@ - (NSString *)description { return result; } -- (void)enumerateValuesWithBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block { +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block { [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block { + usingBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block { // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). BOOL stop = NO; if ((opts & NSEnumerationReverse) == 0) { @@ -2029,6 +2042,7 @@ - (void)exchangeValueAtIndex:(NSUInteger)idx1 @end +// clang-format on //%PDDM-EXPAND-END (7 expansions) #pragma mark - Enum @@ -2126,6 +2140,7 @@ - (instancetype)copyWithZone:(NSZone *)zone { //%PDDM-EXPAND ARRAY_IMMUTABLE_CORE(Enum, int32_t, Raw, %d) // This block of code is generated, do not edit it directly. +// clang-format off - (void)dealloc { NSAssert(!_autocreator, @@ -2165,12 +2180,12 @@ - (NSString *)description { return result; } -- (void)enumerateRawValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block { +- (void)enumerateRawValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { [self enumerateRawValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block { + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). BOOL stop = NO; if ((opts & NSEnumerationReverse) == 0) { @@ -2185,17 +2200,20 @@ - (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts } } } +// clang-format on //%PDDM-EXPAND-END ARRAY_IMMUTABLE_CORE(Enum, int32_t, Raw, %d) - (int32_t)valueAtIndex:(NSUInteger)index { //%PDDM-EXPAND VALIDATE_RANGE(index, _count) // This block of code is generated, do not edit it directly. +// clang-format off if (index >= _count) { [NSException raise:NSRangeException format:@"Index (%lu) beyond bounds (%lu)", (unsigned long)index, (unsigned long)_count]; } +// clang-format on //%PDDM-EXPAND-END VALIDATE_RANGE(index, _count) int32_t result = _values[index]; if (!_validationFunc(result)) { @@ -2207,22 +2225,24 @@ - (int32_t)valueAtIndex:(NSUInteger)index { - (int32_t)rawValueAtIndex:(NSUInteger)index { //%PDDM-EXPAND VALIDATE_RANGE(index, _count) // This block of code is generated, do not edit it directly. +// clang-format off if (index >= _count) { [NSException raise:NSRangeException format:@"Index (%lu) beyond bounds (%lu)", (unsigned long)index, (unsigned long)_count]; } +// clang-format on //%PDDM-EXPAND-END VALIDATE_RANGE(index, _count) return _values[index]; } -- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block { +- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block { + usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block { // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok). BOOL stop = NO; GPBEnumValidationFunc func = _validationFunc; @@ -2253,6 +2273,7 @@ - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts //%PDDM-EXPAND ARRAY_MUTABLE_CORE(Enum, int32_t, Raw, %d) // This block of code is generated, do not edit it directly. +// clang-format off - (void)internalResizeToCapacity:(NSUInteger)newCapacity { _values = reallocf(_values, newCapacity * sizeof(int32_t)); @@ -2358,8 +2379,10 @@ - (void)exchangeValueAtIndex:(NSUInteger)idx1 _values[idx2] = temp; } +// clang-format on //%PDDM-EXPAND MUTATION_METHODS(Enum, int32_t, , EnumValidationList, EnumValidationOne) // This block of code is generated, do not edit it directly. +// clang-format off - (void)addValue:(int32_t)value { [self addValues:&value count:1]; @@ -2426,6 +2449,7 @@ - (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value { } _values[index] = value; } +// clang-format on //%PDDM-EXPAND-END (2 expansions) //%PDDM-DEFINE MUTATION_HOOK_EnumValidationList() @@ -2537,12 +2561,12 @@ - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state return [_array countByEnumeratingWithState:state objects:buffer count:len]; } -- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block { +- (void)enumerateObjectsUsingBlock:(void (NS_NOESCAPE ^)(id obj, NSUInteger idx, BOOL *stop))block { [_array enumerateObjectsUsingBlock:block]; } - (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block { + usingBlock:(void (NS_NOESCAPE ^)(id obj, NSUInteger idx, BOOL *stop))block { [_array enumerateObjectsWithOptions:opts usingBlock:block]; } diff --git a/objectivec/GPBArray_PackagePrivate.h b/objectivec/GPBArray_PackagePrivate.h index 35a4538131296..07eab89d6eb40 100644 --- a/objectivec/GPBArray_PackagePrivate.h +++ b/objectivec/GPBArray_PackagePrivate.h @@ -54,6 +54,7 @@ //%PDDM-EXPAND DECLARE_ARRAY_EXTRAS() // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Int32 @@ -119,6 +120,7 @@ } @end +// clang-format on //%PDDM-EXPAND-END DECLARE_ARRAY_EXTRAS() #pragma mark - NSArray Subclass diff --git a/objectivec/GPBBootstrap.h b/objectivec/GPBBootstrap.h index ed53ae7cbc036..ea5986b8bf1c0 100644 --- a/objectivec/GPBBootstrap.h +++ b/objectivec/GPBBootstrap.h @@ -46,7 +46,7 @@ #endif // If the headers are imported into Objective-C++, we can run into an issue -// where the defintion of NS_ENUM (really CF_ENUM) changes based on the C++ +// where the definition of NS_ENUM (really CF_ENUM) changes based on the C++ // standard that is in effect. If it isn't C++11 or higher, the definition // doesn't allow us to forward declare. We work around this one case by // providing a local definition. The default case has to use NS_ENUM for the @@ -91,12 +91,35 @@ #endif #endif +/** + * Attribute used for Objective-C proto interface deprecations without messages. + **/ +#ifndef GPB_DEPRECATED +#define GPB_DEPRECATED __attribute__((deprecated)) +#endif + +/** + * Attribute used for Objective-C proto interface deprecations with messages. + **/ +#ifndef GPB_DEPRECATED_MSG +#if __has_extension(attribute_deprecated_with_message) +#define GPB_DEPRECATED_MSG(msg) __attribute__((deprecated(msg))) +#else +#define GPB_DEPRECATED_MSG(msg) __attribute__((deprecated)) +#endif +#endif + // If property name starts with init we need to annotate it to get past ARC. // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227 // // Meant to be used internally by generated code. #define GPB_METHOD_FAMILY_NONE __attribute__((objc_method_family(none))) +// Prevent subclassing of generated proto classes. +#ifndef GPB_FINAL +#define GPB_FINAL __attribute__((objc_subclassing_restricted)) +#endif // GPB_FINAL + // ---------------------------------------------------------------------------- // These version numbers are all internal to the ObjC Protobuf runtime; they // are used to ensure compatibility between the generated sources and the @@ -109,7 +132,7 @@ // Current library runtime version. // - Gets bumped when the runtime makes changes to the interfaces between the // generated code and runtime (things added/removed, etc). -#define GOOGLE_PROTOBUF_OBJC_VERSION 30002 +#define GOOGLE_PROTOBUF_OBJC_VERSION 30004 // Minimum runtime version supported for compiling/running against. // - Gets changed when support for the older generated code is dropped. diff --git a/objectivec/GPBCodedInputStream.m b/objectivec/GPBCodedInputStream.m index 22859e771193a..1864d91274cd2 100644 --- a/objectivec/GPBCodedInputStream.m +++ b/objectivec/GPBCodedInputStream.m @@ -46,9 +46,9 @@ GPBNSStringifySymbol(GPBCodedInputStreamErrorDomain); // Matching: -// https://github.com/google/protobuf/blob/master/java/core/src/main/java/com/google/protobuf/CodedInputStream.java#L62 +// https://github.com/protocolbuffers/protobuf/blob/master/java/core/src/main/java/com/google/protobuf/CodedInputStream.java#L62 // private static final int DEFAULT_RECURSION_LIMIT = 100; -// https://github.com/google/protobuf/blob/master/src/google/protobuf/io/coded_stream.cc#L86 +// https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/io/coded_stream.cc#L86 // int CodedInputStream::default_recursion_limit_ = 100; static const NSUInteger kDefaultRecursionLimit = 100; @@ -63,9 +63,15 @@ static void RaiseException(NSInteger code, NSString *reason) { NSDictionary *exceptionInfo = @{ GPBCodedInputStreamUnderlyingErrorKey: error }; - [[[NSException alloc] initWithName:GPBCodedInputStreamException - reason:reason - userInfo:exceptionInfo] raise]; + [[NSException exceptionWithName:GPBCodedInputStreamException + reason:reason + userInfo:exceptionInfo] raise]; +} + +static void CheckRecursionLimit(GPBCodedInputStreamState *state) { + if (state->recursionDepth >= kDefaultRecursionLimit) { + RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil); + } } static void CheckSize(GPBCodedInputStreamState *state, size_t size) { @@ -87,59 +93,32 @@ static int8_t ReadRawByte(GPBCodedInputStreamState *state) { static int32_t ReadRawLittleEndian32(GPBCodedInputStreamState *state) { CheckSize(state, sizeof(int32_t)); - int32_t value = OSReadLittleInt32(state->bytes, state->bufferPos); + // Not using OSReadLittleInt32 because it has undocumented dependency + // on reads being aligned. + int32_t value; + memcpy(&value, state->bytes + state->bufferPos, sizeof(int32_t)); + value = OSSwapLittleToHostInt32(value); state->bufferPos += sizeof(int32_t); return value; } static int64_t ReadRawLittleEndian64(GPBCodedInputStreamState *state) { CheckSize(state, sizeof(int64_t)); - int64_t value = OSReadLittleInt64(state->bytes, state->bufferPos); + // Not using OSReadLittleInt64 because it has undocumented dependency + // on reads being aligned. + int64_t value; + memcpy(&value, state->bytes + state->bufferPos, sizeof(int64_t)); + value = OSSwapLittleToHostInt64(value); state->bufferPos += sizeof(int64_t); return value; } -static int32_t ReadRawVarint32(GPBCodedInputStreamState *state) { - int8_t tmp = ReadRawByte(state); - if (tmp >= 0) { - return tmp; - } - int32_t result = tmp & 0x7f; - if ((tmp = ReadRawByte(state)) >= 0) { - result |= tmp << 7; - } else { - result |= (tmp & 0x7f) << 7; - if ((tmp = ReadRawByte(state)) >= 0) { - result |= tmp << 14; - } else { - result |= (tmp & 0x7f) << 14; - if ((tmp = ReadRawByte(state)) >= 0) { - result |= tmp << 21; - } else { - result |= (tmp & 0x7f) << 21; - result |= (tmp = ReadRawByte(state)) << 28; - if (tmp < 0) { - // Discard upper 32 bits. - for (int i = 0; i < 5; i++) { - if (ReadRawByte(state) >= 0) { - return result; - } - } - RaiseException(GPBCodedInputStreamErrorInvalidVarInt, - @"Invalid VarInt32"); - } - } - } - } - return result; -} - static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) { int32_t shift = 0; int64_t result = 0; while (shift < 64) { int8_t b = ReadRawByte(state); - result |= (int64_t)(b & 0x7F) << shift; + result |= (int64_t)((uint64_t)(b & 0x7F) << shift); if ((b & 0x80) == 0) { return result; } @@ -149,6 +128,10 @@ static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) { return 0; } +static int32_t ReadRawVarint32(GPBCodedInputStreamState *state) { + return (int32_t)ReadRawVarint64(state); +} + static void SkipRawData(GPBCodedInputStreamState *state, size_t size) { CheckSize(state, size); state->bufferPos += size; @@ -220,7 +203,7 @@ int64_t GPBCodedInputStreamReadSInt64(GPBCodedInputStreamState *state) { } BOOL GPBCodedInputStreamReadBool(GPBCodedInputStreamState *state) { - return ReadRawVarint32(state) != 0; + return ReadRawVarint64(state) != 0; } int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) { @@ -452,9 +435,7 @@ - (NSString *)readString { - (void)readGroup:(int32_t)fieldNumber message:(GPBMessage *)message extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { - if (state_.recursionDepth >= kDefaultRecursionLimit) { - RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil); - } + CheckRecursionLimit(&state_); ++state_.recursionDepth; [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry]; GPBCodedInputStreamCheckLastTagWas( @@ -464,9 +445,7 @@ - (void)readGroup:(int32_t)fieldNumber - (void)readUnknownGroup:(int32_t)fieldNumber message:(GPBUnknownFieldSet *)message { - if (state_.recursionDepth >= kDefaultRecursionLimit) { - RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil); - } + CheckRecursionLimit(&state_); ++state_.recursionDepth; [message mergeFromCodedInputStream:self]; GPBCodedInputStreamCheckLastTagWas( @@ -476,10 +455,8 @@ - (void)readUnknownGroup:(int32_t)fieldNumber - (void)readMessage:(GPBMessage *)message extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + CheckRecursionLimit(&state_); int32_t length = ReadRawVarint32(&state_); - if (state_.recursionDepth >= kDefaultRecursionLimit) { - RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil); - } size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length); ++state_.recursionDepth; [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry]; @@ -492,10 +469,8 @@ - (void)readMapEntry:(id)mapDictionary extensionRegistry:(GPBExtensionRegistry *)extensionRegistry field:(GPBFieldDescriptor *)field parentMessage:(GPBMessage *)parentMessage { + CheckRecursionLimit(&state_); int32_t length = ReadRawVarint32(&state_); - if (state_.recursionDepth >= kDefaultRecursionLimit) { - RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil); - } size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length); ++state_.recursionDepth; GPBDictionaryReadEntry(mapDictionary, self, extensionRegistry, field, diff --git a/objectivec/GPBCodedInputStream_PackagePrivate.h b/objectivec/GPBCodedInputStream_PackagePrivate.h index 90bd0c92cece8..43ec6e79b2f35 100644 --- a/objectivec/GPBCodedInputStream_PackagePrivate.h +++ b/objectivec/GPBCodedInputStream_PackagePrivate.h @@ -34,8 +34,6 @@ #import "GPBCodedInputStream.h" -#import - @class GPBUnknownFieldSet; @class GPBFieldDescriptor; diff --git a/objectivec/GPBCodedOutputStream.h b/objectivec/GPBCodedOutputStream.h index 23c404b8533a6..5dde974e3ae57 100644 --- a/objectivec/GPBCodedOutputStream.h +++ b/objectivec/GPBCodedOutputStream.h @@ -177,6 +177,7 @@ extern NSString *const GPBCodedOutputStreamException_WriteFailed; //%PDDM-EXPAND _WRITE_DECLS() // This block of code is generated, do not edit it directly. +// clang-format off /** * Write a double for the given field number. @@ -527,7 +528,8 @@ extern NSString *const GPBCodedOutputStreamException_WriteFailed; * @param fieldNumber The field number assigned to the values. * @param values The values to write out. **/ -- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values; +- (void)writeStringArray:(int32_t)fieldNumber + values:(NSArray *)values; /** * Write a NSString without any tag. * @@ -548,7 +550,8 @@ extern NSString *const GPBCodedOutputStreamException_WriteFailed; * @param fieldNumber The field number assigned to the values. * @param values The values to write out. **/ -- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values; +- (void)writeMessageArray:(int32_t)fieldNumber + values:(NSArray *)values; /** * Write a GPBMessage without any tag. * @@ -569,7 +572,8 @@ extern NSString *const GPBCodedOutputStreamException_WriteFailed; * @param fieldNumber The field number assigned to the values. * @param values The values to write out. **/ -- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values; +- (void)writeBytesArray:(int32_t)fieldNumber + values:(NSArray *)values; /** * Write a NSData without any tag. * @@ -591,7 +595,8 @@ extern NSString *const GPBCodedOutputStreamException_WriteFailed; * @param fieldNumber The field number assigned to the values. * @param values The values to write out. **/ -- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values; +- (void)writeGroupArray:(int32_t)fieldNumber + values:(NSArray *)values; /** * Write a GPBMessage without any tag (but does write the endGroup tag). * @@ -615,7 +620,8 @@ extern NSString *const GPBCodedOutputStreamException_WriteFailed; * @param fieldNumber The field number assigned to the values. * @param values The values to write out. **/ -- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values; +- (void)writeUnknownGroupArray:(int32_t)fieldNumber + values:(NSArray *)values; /** * Write a GPBUnknownFieldSet without any tag (but does write the endGroup tag). * @@ -625,6 +631,7 @@ extern NSString *const GPBCodedOutputStreamException_WriteFailed; - (void)writeUnknownGroupNoTag:(int32_t)fieldNumber value:(GPBUnknownFieldSet *)value; +// clang-format on //%PDDM-EXPAND-END _WRITE_DECLS() /** @@ -690,7 +697,8 @@ NS_ASSUME_NONNULL_END //% * @param fieldNumber The field number assigned to the values. //% * @param values The values to write out. //% **/ -//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray<##TYPE##*> *)values; +//%- (void)write##NAME##Array:(int32_t)fieldNumber +//% NAME$S values:(NSArray<##TYPE##*> *)values; //%/** //% * Write a TYPE without any tag. //% * @@ -714,7 +722,8 @@ NS_ASSUME_NONNULL_END //% * @param fieldNumber The field number assigned to the values. //% * @param values The values to write out. //% **/ -//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray<##TYPE##*> *)values; +//%- (void)write##NAME##Array:(int32_t)fieldNumber +//% NAME$S values:(NSArray<##TYPE##*> *)values; //%/** //% * Write a TYPE without any tag (but does write the endGroup tag). //% * diff --git a/objectivec/GPBCodedOutputStream.m b/objectivec/GPBCodedOutputStream.m index c299040f0bb25..4e2a51413a615 100644 --- a/objectivec/GPBCodedOutputStream.m +++ b/objectivec/GPBCodedOutputStream.m @@ -174,10 +174,10 @@ - (instancetype)initWithOutputStream:(NSOutputStream *)output data:(NSMutableData *)data { if ((self = [super init])) { buffer_ = [data retain]; - [output open]; state_.bytes = [data mutableBytes]; state_.size = [data length]; state_.output = [output retain]; + [state_.output open]; } return self; } @@ -374,12 +374,12 @@ - (void)writeUInt32:(int32_t)fieldNumber value:(uint32_t)value { } - (void)writeEnumNoTag:(int32_t)value { - GPBWriteRawVarint32(&state_, value); + GPBWriteInt32NoTag(&state_, value); } - (void)writeEnum:(int32_t)fieldNumber value:(int32_t)value { GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint); - GPBWriteRawVarint32(&state_, value); + GPBWriteInt32NoTag(&state_, value); } - (void)writeSFixed32NoTag:(int32_t)value { @@ -452,6 +452,7 @@ - (void)writeSInt64:(int32_t)fieldNumber value:(int64_t)value { //% //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Double, Double, double, ) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeDoubleArray:(int32_t)fieldNumber values:(GPBDoubleArray *)values @@ -477,8 +478,10 @@ - (void)writeDoubleArray:(int32_t)fieldNumber } } +// clang-format on //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Float, Float, float, ) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeFloatArray:(int32_t)fieldNumber values:(GPBFloatArray *)values @@ -504,8 +507,10 @@ - (void)writeFloatArray:(int32_t)fieldNumber } } +// clang-format on //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt64, UInt64, uint64_t, ) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeUInt64Array:(int32_t)fieldNumber values:(GPBUInt64Array *)values @@ -531,8 +536,10 @@ - (void)writeUInt64Array:(int32_t)fieldNumber } } +// clang-format on //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int64, Int64, int64_t, ) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeInt64Array:(int32_t)fieldNumber values:(GPBInt64Array *)values @@ -558,8 +565,10 @@ - (void)writeInt64Array:(int32_t)fieldNumber } } +// clang-format on //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int32, Int32, int32_t, ) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeInt32Array:(int32_t)fieldNumber values:(GPBInt32Array *)values @@ -585,8 +594,10 @@ - (void)writeInt32Array:(int32_t)fieldNumber } } +// clang-format on //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt32, UInt32, uint32_t, ) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeUInt32Array:(int32_t)fieldNumber values:(GPBUInt32Array *)values @@ -612,8 +623,10 @@ - (void)writeUInt32Array:(int32_t)fieldNumber } } +// clang-format on //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed64, UInt64, uint64_t, ) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeFixed64Array:(int32_t)fieldNumber values:(GPBUInt64Array *)values @@ -639,8 +652,10 @@ - (void)writeFixed64Array:(int32_t)fieldNumber } } +// clang-format on //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed32, UInt32, uint32_t, ) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeFixed32Array:(int32_t)fieldNumber values:(GPBUInt32Array *)values @@ -666,8 +681,10 @@ - (void)writeFixed32Array:(int32_t)fieldNumber } } +// clang-format on //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt32, Int32, int32_t, ) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeSInt32Array:(int32_t)fieldNumber values:(GPBInt32Array *)values @@ -693,8 +710,10 @@ - (void)writeSInt32Array:(int32_t)fieldNumber } } +// clang-format on //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt64, Int64, int64_t, ) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeSInt64Array:(int32_t)fieldNumber values:(GPBInt64Array *)values @@ -720,8 +739,10 @@ - (void)writeSInt64Array:(int32_t)fieldNumber } } +// clang-format on //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed64, Int64, int64_t, ) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeSFixed64Array:(int32_t)fieldNumber values:(GPBInt64Array *)values @@ -747,8 +768,10 @@ - (void)writeSFixed64Array:(int32_t)fieldNumber } } +// clang-format on //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed32, Int32, int32_t, ) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeSFixed32Array:(int32_t)fieldNumber values:(GPBInt32Array *)values @@ -774,8 +797,10 @@ - (void)writeSFixed32Array:(int32_t)fieldNumber } } +// clang-format on //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Bool, Bool, BOOL, ) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeBoolArray:(int32_t)fieldNumber values:(GPBBoolArray *)values @@ -801,8 +826,10 @@ - (void)writeBoolArray:(int32_t)fieldNumber } } +// clang-format on //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Enum, Enum, int32_t, Raw) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeEnumArray:(int32_t)fieldNumber values:(GPBEnumArray *)values @@ -828,8 +855,10 @@ - (void)writeEnumArray:(int32_t)fieldNumber } } +// clang-format on //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(String, NSString) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values { for (NSString *value in values) { @@ -837,8 +866,10 @@ - (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values { } } +// clang-format on //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Message, GPBMessage) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values { for (GPBMessage *value in values) { @@ -846,8 +877,10 @@ - (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values { } } +// clang-format on //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Bytes, NSData) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values { for (NSData *value in values) { @@ -855,8 +888,10 @@ - (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values { } } +// clang-format on //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Group, GPBMessage) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values { for (GPBMessage *value in values) { @@ -864,8 +899,10 @@ - (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values { } } +// clang-format on //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(UnknownGroup, GPBUnknownFieldSet) // This block of code is generated, do not edit it directly. +// clang-format off - (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values { for (GPBUnknownFieldSet *value in values) { @@ -873,6 +910,7 @@ - (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values { } } +// clang-format on //%PDDM-EXPAND-END (19 expansions) - (void)writeMessageSetExtension:(int32_t)fieldNumber @@ -942,7 +980,10 @@ - (void)writeRawPtr:(const void *)value state_.position = length; } else { // Write is very big. Let's do it all at once. - [state_.output write:((uint8_t *)value) + offset maxLength:length]; + NSInteger written = [state_.output write:((uint8_t *)value) + offset maxLength:length]; + if (written != (NSInteger)length) { + [NSException raise:GPBCodedOutputStreamException_WriteFailed format:@""]; + } } } } @@ -1050,7 +1091,7 @@ size_t GPBComputeUInt32SizeNoTag(int32_t value) { } size_t GPBComputeEnumSizeNoTag(int32_t value) { - return GPBComputeRawVarint32Size(value); + return GPBComputeInt32SizeNoTag(value); } size_t GPBComputeSFixed32SizeNoTag(int32_t value) { diff --git a/objectivec/GPBDescriptor.h b/objectivec/GPBDescriptor.h index 651f4de08f980..331d4444ab651 100644 --- a/objectivec/GPBDescriptor.h +++ b/objectivec/GPBDescriptor.h @@ -75,7 +75,7 @@ typedef NS_ENUM(uint8_t, GPBFieldType) { /** Number of extension ranges declared for the message. */ @property(nonatomic, readonly) uint32_t extensionRangesCount; /** Descriptor for the file where the message was defined. */ -@property(nonatomic, readonly, assign) GPBFileDescriptor *file; +@property(nonatomic, readonly) GPBFileDescriptor *file; /** Whether the message is in wire format or not. */ @property(nonatomic, readonly, getter=isWireFormat) BOOL wireFormat; @@ -188,10 +188,10 @@ typedef NS_ENUM(uint8_t, GPBFieldType) { @property(nonatomic, readonly, getter=isPackable) BOOL packable; /** The containing oneof if this field is part of one, nil otherwise. */ -@property(nonatomic, readonly, assign, nullable) GPBOneofDescriptor *containingOneof; +@property(nonatomic, readonly, nullable) GPBOneofDescriptor *containingOneof; /** Class of the message if the field is of message type. */ -@property(nonatomic, readonly, assign, nullable) Class msgClass; +@property(nonatomic, readonly, nullable) Class msgClass; /** Descriptor for the enum if this field is an enum. */ @property(nonatomic, readonly, strong, nullable) GPBEnumDescriptor *enumDescriptor; @@ -223,9 +223,12 @@ typedef NS_ENUM(uint8_t, GPBFieldType) { /** * Returns the enum value name for the given raw enum. * + * Note that there can be more than one name corresponding to a given value + * if the allow_alias option is used. + * * @param number The raw enum value. * - * @return The name of the enum value passed, or nil if not valid. + * @return The first name that matches the enum value passed, or nil if not valid. **/ - (nullable NSString *)enumNameForValue:(int32_t)number; @@ -244,7 +247,7 @@ typedef NS_ENUM(uint8_t, GPBFieldType) { * * @param number The raw enum value. * - * @return The text format name for the raw enum value, or nil if not valid. + * @return The first text format name which matches the enum value, or nil if not valid. **/ - (nullable NSString *)textFormatNameForValue:(int32_t)number; @@ -258,6 +261,33 @@ typedef NS_ENUM(uint8_t, GPBFieldType) { **/ - (BOOL)getValue:(nullable int32_t *)outValue forEnumTextFormatName:(NSString *)textFormatName; +/** + * Gets the number of defined enum names. + * + * @return Count of the number of enum names, including any aliases. + */ +@property(nonatomic, readonly) uint32_t enumNameCount; + +/** + * Gets the enum name corresponding to the given index. + * + * @param index Index into the available names. The defined range is from 0 + * to self.enumNameCount - 1. + * + * @returns The enum name at the given index, or nil if the index is out of range. + */ +- (nullable NSString *)getEnumNameForIndex:(uint32_t)index; + +/** + * Gets the enum text format name corresponding to the given index. + * + * @param index Index into the available names. The defined range is from 0 + * to self.enumNameCount - 1. + * + * @returns The text format name at the given index, or nil if the index is out of range. + */ +- (nullable NSString *)getEnumTextFormatNameForIndex:(uint32_t)index; + @end /** @@ -275,7 +305,7 @@ typedef NS_ENUM(uint8_t, GPBFieldType) { /** Whether the extension is packable. */ @property(nonatomic, readonly, getter=isPackable) BOOL packable; /** The class of the message if the extension is of message type. */ -@property(nonatomic, readonly, assign) Class msgClass; +@property(nonatomic, readonly) Class msgClass; /** The singleton name for the extension. */ @property(nonatomic, readonly) NSString *singletonName; /** The enum descriptor if the extension is of enum type. */ diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m index 0753a9485bb83..c29b95539f510 100644 --- a/objectivec/GPBDescriptor.m +++ b/objectivec/GPBDescriptor.m @@ -44,7 +44,7 @@ // The addresses of these variables are used as keys for objc_getAssociatedObject. static const char kTextFormatExtraValueKey = 0; -static const char kParentClassNameValueKey = 0; +static const char kParentClassValueKey = 0; static const char kClassNameSuffixKey = 0; // Utility function to generate selectors on the fly. @@ -126,6 +126,10 @@ @implementation GPBDescriptor { GPBFileSyntax syntax = file.syntax; BOOL fieldsIncludeDefault = (flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0; + BOOL usesClassRefs = + (flags & GPBDescriptorInitializationFlag_UsesClassRefs) != 0; + BOOL proto3OptionalKnown = + (flags & GPBDescriptorInitializationFlag_Proto3OptionalKnown) != 0; void *desc; for (uint32_t i = 0; i < fieldCount; ++i) { @@ -143,6 +147,8 @@ @implementation GPBDescriptor { GPBFieldDescriptor *fieldDescriptor = [[GPBFieldDescriptor alloc] initWithFieldDescription:desc includesDefault:fieldsIncludeDefault + usesClassRefs:usesClassRefs + proto3OptionalKnown:proto3OptionalKnown syntax:syntax]; [fields addObject:fieldDescriptor]; [fieldDescriptor release]; @@ -217,15 +223,19 @@ - (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)co extensionRangesCount_ = count; } +- (void)setupContainingMessageClass:(Class)messageClass { + objc_setAssociatedObject(self, &kParentClassValueKey, + messageClass, + OBJC_ASSOCIATION_ASSIGN); +} + - (void)setupContainingMessageClassName:(const char *)msgClassName { // Note: Only fetch the class here, can't send messages to it because // that could cause cycles back to this class within +initialize if // two messages have each other in fields (i.e. - they build a graph). - NSAssert(objc_getClass(msgClassName), @"Class %s not defined", msgClassName); - NSValue *parentNameValue = [NSValue valueWithPointer:msgClassName]; - objc_setAssociatedObject(self, &kParentClassNameValueKey, - parentNameValue, - OBJC_ASSOCIATION_RETAIN_NONATOMIC); + Class clazz = objc_getClass(msgClassName); + NSAssert(clazz, @"Class %s not defined", msgClassName); + [self setupContainingMessageClass:clazz]; } - (void)setupMessageClassNameSuffix:(NSString *)suffix { @@ -241,14 +251,7 @@ - (NSString *)name { } - (GPBDescriptor *)containingType { - NSValue *parentNameValue = - objc_getAssociatedObject(self, &kParentClassNameValueKey); - if (!parentNameValue) { - return nil; - } - const char *parentName = [parentNameValue pointerValue]; - Class parentClass = objc_getClass(parentName); - NSAssert(parentClass, @"Class %s not defined", parentName); + Class parentClass = objc_getAssociatedObject(self, &kParentClassValueKey); return [parentClass descriptor]; } @@ -411,7 +414,7 @@ - (void)dealloc { } - (NSString *)name { - return @(name_); + return (NSString * _Nonnull)@(name_); } - (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { @@ -487,6 +490,8 @@ - (instancetype)init { - (instancetype)initWithFieldDescription:(void *)description includesDefault:(BOOL)includesDefault + usesClassRefs:(BOOL)usesClassRefs + proto3OptionalKnown:(BOOL)proto3OptionalKnown syntax:(GPBFileSyntax)syntax { if ((self = [super init])) { GPBMessageFieldDescription *coreDesc; @@ -503,20 +508,34 @@ - (instancetype)initWithFieldDescription:(void *)description BOOL isMessage = GPBDataTypeIsMessage(dataType); BOOL isMapOrArray = GPBFieldIsMapOrArray(self); + // If proto3 optionals weren't known (i.e. generated code from an + // older version), compute the flag for the rest of the runtime. + if (!proto3OptionalKnown) { + // If it was... + // - proto3 syntax + // - not repeated/map + // - not in a oneof (negative has index) + // - not a message (the flag doesn't make sense for messages) + BOOL clearOnZero = ((syntax == GPBFileSyntaxProto3) && + !isMapOrArray && + (coreDesc->hasIndex >= 0) && + !isMessage); + if (clearOnZero) { + coreDesc->flags |= GPBFieldClearHasIvarOnZero; + } + } + if (isMapOrArray) { // map<>/repeated fields get a *Count property (inplace of a has*) to // support checking if there are any entries without triggering // autocreation. hasOrCountSel_ = SelFromStrings(NULL, coreDesc->name, "_Count", NO); } else { - // If there is a positive hasIndex, then: - // - All fields types for proto2 messages get has* selectors. - // - Only message fields for proto3 messages get has* selectors. - // Note: the positive check is to handle oneOfs, we can't check - // containingOneof_ because it isn't set until after initialization. + // It is a single field; it gets has/setHas selectors if... + // - not in a oneof (negative has index) + // - not clearing on zero if ((coreDesc->hasIndex >= 0) && - (coreDesc->hasIndex != GPBNoHasBit) && - ((syntax != GPBFileSyntaxProto3) || isMessage)) { + ((coreDesc->flags & GPBFieldClearHasIvarOnZero) == 0)) { hasOrCountSel_ = SelFromStrings("has", coreDesc->name, NULL, NO); setHasSel_ = SelFromStrings("setHas", coreDesc->name, NULL, YES); } @@ -524,12 +543,17 @@ - (instancetype)initWithFieldDescription:(void *)description // Extra type specific data. if (isMessage) { - const char *className = coreDesc->dataTypeSpecific.className; // Note: Only fetch the class here, can't send messages to it because // that could cause cycles back to this class within +initialize if // two messages have each other in fields (i.e. - they build a graph). - msgClass_ = objc_getClass(className); - NSAssert(msgClass_, @"Class %s not defined", className); + if (usesClassRefs) { + msgClass_ = coreDesc->dataTypeSpecific.clazz; + } else { + // Backwards compatibility for sources generated with older protoc. + const char *className = coreDesc->dataTypeSpecific.className; + msgClass_ = objc_getClass(className); + NSAssert(msgClass_, @"Class %s not defined", className); + } } else if (dataType == GPBDataTypeEnum) { if ((coreDesc->flags & GPBFieldHasEnumDescriptor) != 0) { enumHandling_.enumDescriptor_ = @@ -548,7 +572,8 @@ - (instancetype)initWithFieldDescription:(void *)description // descriptor structure. const uint8_t *bytes = (const uint8_t *)defaultValue_.valueData; if (bytes) { - uint32_t length = *((uint32_t *)bytes); + uint32_t length; + memcpy(&length, bytes, sizeof(length)); length = ntohl(length); bytes += sizeof(length); defaultValue_.valueData = @@ -581,7 +606,7 @@ - (uint32_t)number { } - (NSString *)name { - return @(description_->name); + return (NSString * _Nonnull)@(description_->name); } - (BOOL)isRequired { @@ -818,6 +843,7 @@ - (void)calcValueNameOffsets { return; } uint32_t *offsets = malloc(valueCount_ * sizeof(uint32_t)); + if (!offsets) return; const char *scan = valueNames_; for (uint32_t i = 0; i < valueCount_; ++i) { offsets[i] = (uint32_t)(scan - valueNames_); @@ -829,13 +855,9 @@ - (void)calcValueNameOffsets { } - (NSString *)enumNameForValue:(int32_t)number { - if (nameOffsets_ == NULL) [self calcValueNameOffsets]; - for (uint32_t i = 0; i < valueCount_; ++i) { if (values_[i] == number) { - const char *valueName = valueNames_ + nameOffsets_[i]; - NSString *fullName = [NSString stringWithFormat:@"%@_%s", name_, valueName]; - return fullName; + return [self getEnumNameForIndex:i]; } } return nil; @@ -854,6 +876,7 @@ - (BOOL)getValue:(int32_t *)outValue forEnumName:(NSString *)name { nameAsCStr += prefixLen; if (nameOffsets_ == NULL) [self calcValueNameOffsets]; + if (nameOffsets_ == NULL) return NO; // Find it. for (uint32_t i = 0; i < valueCount_; ++i) { @@ -870,13 +893,13 @@ - (BOOL)getValue:(int32_t *)outValue forEnumName:(NSString *)name { - (BOOL)getValue:(int32_t *)outValue forEnumTextFormatName:(NSString *)textFormatName { if (nameOffsets_ == NULL) [self calcValueNameOffsets]; + if (nameOffsets_ == NULL) return NO; for (uint32_t i = 0; i < valueCount_; ++i) { - int32_t value = values_[i]; - NSString *valueTextFormatName = [self textFormatNameForValue:value]; + NSString *valueTextFormatName = [self getEnumTextFormatNameForIndex:i]; if ([valueTextFormatName isEqual:textFormatName]) { if (outValue) { - *outValue = value; + *outValue = values_[i]; } return YES; } @@ -885,8 +908,6 @@ - (BOOL)getValue:(int32_t *)outValue forEnumTextFormatName:(NSString *)textForma } - (NSString *)textFormatNameForValue:(int32_t)number { - if (nameOffsets_ == NULL) [self calcValueNameOffsets]; - // Find the EnumValue descriptor and its index. BOOL foundIt = NO; uint32_t valueDescriptorIndex; @@ -901,16 +922,41 @@ - (NSString *)textFormatNameForValue:(int32_t)number { if (!foundIt) { return nil; } + return [self getEnumTextFormatNameForIndex:valueDescriptorIndex]; +} +- (uint32_t)enumNameCount { + return valueCount_; +} + +- (NSString *)getEnumNameForIndex:(uint32_t)index { + if (nameOffsets_ == NULL) [self calcValueNameOffsets]; + if (nameOffsets_ == NULL) return nil; + + if (index >= valueCount_) { + return nil; + } + const char *valueName = valueNames_ + nameOffsets_[index]; + NSString *fullName = [NSString stringWithFormat:@"%@_%s", name_, valueName]; + return fullName; +} + +- (NSString *)getEnumTextFormatNameForIndex:(uint32_t)index { + if (nameOffsets_ == NULL) [self calcValueNameOffsets]; + if (nameOffsets_ == NULL) return nil; + + if (index >= valueCount_) { + return nil; + } NSString *result = nil; // Naming adds an underscore between enum name and value name, skip that also. - const char *valueName = valueNames_ + nameOffsets_[valueDescriptorIndex]; + const char *valueName = valueNames_ + nameOffsets_[index]; NSString *shortName = @(valueName); // See if it is in the map of special format handling. if (extraTextFormatInfo_) { result = GPBDecodeTextFormatName(extraTextFormatInfo_, - (int32_t)valueDescriptorIndex, shortName); + (int32_t)index, shortName); } // Logic here needs to match what objectivec_enum.cc does in the proto // compiler. @@ -935,35 +981,35 @@ @implementation GPBExtensionDescriptor { GPBGenericValue defaultValue_; } -@synthesize containingMessageClass = containingMessageClass_; - -- (instancetype)initWithExtensionDescription: - (GPBExtensionDescription *)description { +- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc + usesClassRefs:(BOOL)usesClassRefs { if ((self = [super init])) { - description_ = description; - -#if defined(DEBUG) && DEBUG - const char *className = description->messageOrGroupClassName; - if (className) { - NSAssert(objc_lookUpClass(className) != Nil, - @"Class %s not defined", className); - } -#endif + description_ = desc; + if (!usesClassRefs) { + // Legacy without class ref support. + const char *className = description_->messageOrGroupClass.name; + if (className) { + Class clazz = objc_lookUpClass(className); + NSAssert(clazz != Nil, @"Class %s not defined", className); + description_->messageOrGroupClass.clazz = clazz; + } - if (description->extendedClass) { - Class containingClass = objc_lookUpClass(description->extendedClass); - NSAssert(containingClass, @"Class %s not defined", - description->extendedClass); - containingMessageClass_ = containingClass; + const char *extendedClassName = description_->extendedClass.name; + if (extendedClassName) { + Class clazz = objc_lookUpClass(extendedClassName); + NSAssert(clazz, @"Class %s not defined", extendedClassName); + description_->extendedClass.clazz = clazz; + } } GPBDataType type = description_->dataType; if (type == GPBDataTypeBytes) { // Data stored as a length prefixed c-string in descriptor records. const uint8_t *bytes = - (const uint8_t *)description->defaultValue.valueData; + (const uint8_t *)description_->defaultValue.valueData; if (bytes) { - uint32_t length = *((uint32_t *)bytes); + uint32_t length; + memcpy(&length, bytes, sizeof(length)); // The length is stored in network byte order. length = ntohl(length); bytes += sizeof(length); @@ -975,12 +1021,16 @@ - (instancetype)initWithExtensionDescription: // aren't common, we avoid the hit startup hit and it avoid initialization // order issues. } else { - defaultValue_ = description->defaultValue; + defaultValue_ = description_->defaultValue; } } return self; } +- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc { + return [self initWithExtensionDescription:desc usesClassRefs:NO]; +} + - (void)dealloc { if ((description_->dataType == GPBDataTypeBytes) && !GPBExtensionIsRepeated(description_)) { @@ -996,7 +1046,7 @@ - (instancetype)copyWithZone:(NSZone *)zone { } - (NSString *)singletonName { - return @(description_->singletonName); + return (NSString * _Nonnull)@(description_->singletonName); } - (const char *)singletonNameC { @@ -1027,16 +1077,16 @@ - (BOOL)isRepeated { return GPBExtensionIsRepeated(description_); } -- (BOOL)isMap { - return (description_->options & GPBFieldMapKeyMask) != 0; -} - - (BOOL)isPackable { return GPBExtensionIsPacked(description_); } - (Class)msgClass { - return objc_getClass(description_->messageOrGroupClassName); + return description_->messageOrGroupClass.clazz; +} + +- (Class)containingMessageClass { + return description_->extendedClass.clazz; } - (GPBEnumDescriptor *)enumDescriptor { diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h index 452b3f8e7ecc7..408f8d4e1014b 100644 --- a/objectivec/GPBDescriptor_PackagePrivate.h +++ b/objectivec/GPBDescriptor_PackagePrivate.h @@ -45,6 +45,10 @@ typedef NS_OPTIONS(uint16_t, GPBFieldFlags) { GPBFieldOptional = 1 << 3, GPBFieldHasDefaultValue = 1 << 4, + // Indicate that the field should "clear" when set to zero value. This is the + // proto3 non optional behavior for singular data (ints, data, string, enum) + // fields. + GPBFieldClearHasIvarOnZero = 1 << 5, // Indicates the field needs custom handling for the TextFormat name, if not // set, the name can be derived from the ObjC name. GPBFieldTextFormatNameCustom = 1 << 6, @@ -80,7 +84,11 @@ typedef struct GPBMessageFieldDescription { // Name of ivar. const char *name; union { - const char *className; // Name for message class. + // className is deprecated and will be removed in favor of clazz. + // kept around right now for backwards compatibility. + // clazz is used iff GPBDescriptorInitializationFlag_UsesClassRefs is set. + char *className; // Name of the class of the message. + Class clazz; // Class of the message. // For enums only: If EnumDescriptors are compiled in, it will be that, // otherwise it will be the verifier. GPBEnumDescriptorFunc enumDescFunc; @@ -123,8 +131,29 @@ typedef NS_OPTIONS(uint8_t, GPBExtensionOptions) { typedef struct GPBExtensionDescription { GPBGenericValue defaultValue; const char *singletonName; - const char *extendedClass; - const char *messageOrGroupClassName; + // Before 3.12, `extendedClass` was just a `const char *`. Thanks to nested + // initialization (https://en.cppreference.com/w/c/language/struct_initialization#Nested_initialization) + // old generated code with `.extendedClass = GPBStringifySymbol(Something)` + // still works; and the current generator can use `extendedClass.clazz`, to + // pass a Class reference. + union { + const char *name; + Class clazz; + } extendedClass; + // Before 3.12, this was `const char *messageOrGroupClassName`. In the + // initial 3.12 release, we moved the `union messageOrGroupClass`, and failed + // to realize that would break existing source code for extensions. So to + // keep existing source code working, we added an unnamed union (C11) to + // provide both the old field name and the new union. This keeps both older + // and newer code working. + // Background: https://github.com/protocolbuffers/protobuf/issues/7555 + union { + const char *messageOrGroupClassName; + union { + const char *name; + Class clazz; + } messageOrGroupClass; + }; GPBEnumDescriptorFunc enumDescriptorFunc; int32_t fieldNumber; GPBDataType dataType; @@ -135,6 +164,17 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { GPBDescriptorInitializationFlag_None = 0, GPBDescriptorInitializationFlag_FieldsWithDefault = 1 << 0, GPBDescriptorInitializationFlag_WireFormat = 1 << 1, + + // This is used as a stopgap as we move from using class names to class + // references. The runtime needs to support both until we allow a + // breaking change in the runtime. + GPBDescriptorInitializationFlag_UsesClassRefs = 1 << 2, + + // This flag is used to indicate that the generated sources already contain + // the `GPBFieldClearHasIvarOnZero` flag and it doesn't have to be computed + // at startup. This allows older generated code to still work with the + // current runtime library. + GPBDescriptorInitializationFlag_Proto3OptionalKnown = 1 << 3, }; @interface GPBDescriptor () { @@ -168,9 +208,12 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { firstHasIndex:(int32_t)firstHasIndex; - (void)setupExtraTextInfo:(const char *)extraTextFormatInfo; - (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count; -- (void)setupContainingMessageClassName:(const char *)msgClassName; +- (void)setupContainingMessageClass:(Class)msgClass; - (void)setupMessageClassNameSuffix:(NSString *)suffix; +// Deprecated. Use setupContainingMessageClass instead. +- (void)setupContainingMessageClassName:(const char *)msgClassName; + @end @interface GPBFileDescriptor () @@ -206,7 +249,10 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { // description has to be long lived, it is held as a raw pointer. - (instancetype)initWithFieldDescription:(void *)description includesDefault:(BOOL)includesDefault + usesClassRefs:(BOOL)usesClassRefs + proto3OptionalKnown:(BOOL)proto3OptionalKnown syntax:(GPBFileSyntax)syntax; + @end @interface GPBEnumDescriptor () @@ -246,8 +292,11 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { @property(nonatomic, readonly) GPBWireFormat alternateWireType; // description has to be long lived, it is held as a raw pointer. -- (instancetype)initWithExtensionDescription: - (GPBExtensionDescription *)description; +- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc + usesClassRefs:(BOOL)usesClassRefs; +// Deprecated. Calls above with `usesClassRefs = NO` +- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc; + - (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other; @end diff --git a/objectivec/GPBDictionary.h b/objectivec/GPBDictionary.h index 9d674150e3f41..28d880d6f717a 100644 --- a/objectivec/GPBDictionary.h +++ b/objectivec/GPBDictionary.h @@ -45,6 +45,7 @@ NS_ASSUME_NONNULL_BEGIN //%PDDM-EXPAND DECLARE_DICTIONARIES() // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - UInt32 -> UInt32 @@ -59,55 +60,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithUInt32:(uint32_t)value - forKey:(uint32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithUInt32s:(const uint32_t [__nullable])values - forKeys:(const uint32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -158,7 +110,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndUInt32sUsingBlock: - (void (^)(uint32_t key, uint32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint32_t key, uint32_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -203,55 +155,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithInt32:(int32_t)value - forKey:(uint32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithInt32s:(const int32_t [__nullable])values - forKeys:(const uint32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt32Int32Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -302,7 +205,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndInt32sUsingBlock: - (void (^)(uint32_t key, int32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -347,55 +250,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithUInt64:(uint64_t)value - forKey:(uint32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithUInt64s:(const uint64_t [__nullable])values - forKeys:(const uint32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -446,7 +300,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndUInt64sUsingBlock: - (void (^)(uint32_t key, uint64_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint32_t key, uint64_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -491,55 +345,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithInt64:(int64_t)value - forKey:(uint32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithInt64s:(const int64_t [__nullable])values - forKeys:(const uint32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt32Int64Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -590,7 +395,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndInt64sUsingBlock: - (void (^)(uint32_t key, int64_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint32_t key, int64_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -635,55 +440,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithBool:(BOOL)value - forKey:(uint32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithBools:(const BOOL [__nullable])values - forKeys:(const uint32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt32BoolDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -734,7 +490,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndBoolsUsingBlock: - (void (^)(uint32_t key, BOOL value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint32_t key, BOOL value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -779,55 +535,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithFloat:(float)value - forKey:(uint32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithFloats:(const float [__nullable])values - forKeys:(const uint32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt32FloatDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -878,7 +585,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndFloatsUsingBlock: - (void (^)(uint32_t key, float value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint32_t key, float value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -923,55 +630,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithDouble:(double)value - forKey:(uint32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithDoubles:(const double [__nullable])values - forKeys:(const uint32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt32DoubleDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -1022,7 +680,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndDoublesUsingBlock: - (void (^)(uint32_t key, double value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint32_t key, double value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -1069,70 +727,6 @@ NS_ASSUME_NONNULL_BEGIN /** The validation function to check if the enums are valid. */ @property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the given validation function. - * - * @param func The enum validation function for the dictionary. - * - * @return A newly instanced dictionary. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param func The enum validation function for the dictionary. - * @param rawValue The raw enum value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - rawValue:(int32_t)rawValue - forKey:(uint32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param func The enum validation function for the dictionary. - * @param values The raw enum values values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - rawValues:(const int32_t [__nullable])values - forKeys:(const uint32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt32EnumDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param func The enum validation function for the dictionary. - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - capacity:(NSUInteger)numItems; - /** * Initializes a dictionary with the given validation function. * @@ -1202,7 +796,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndEnumsUsingBlock: - (void (^)(uint32_t key, int32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block; /** * Gets the raw enum value for the given key. @@ -1229,7 +823,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndRawValuesUsingBlock: - (void (^)(uint32_t key, int32_t rawValue, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint32_t key, int32_t rawValue, BOOL *stop))block; /** * Adds the keys and raw enum values from another dictionary. @@ -1294,69 +888,20 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, readonly) NSUInteger count; /** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. + * Initializes this dictionary, copying the given values and keys. * - * @param object The value to be placed in the dictionary. - * @param key The key under which to store the value. + * @param objects The values to be placed in this dictionary. + * @param keys The keys under which to store the values. + * @param count The number of elements to copy into the dictionary. * - * @return A newly instanced dictionary with the key and value in it. + * @return A newly initialized dictionary with a copy of the values and keys. **/ -+ (instancetype)dictionaryWithObject:(ObjectType)object - forKey:(uint32_t)key; +- (instancetype)initWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects + forKeys:(const uint32_t [__nullable])keys + count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; /** - * Creates and initializes a dictionary with the entries given. - * - * @param objects The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects - forKeys:(const uint32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt32ObjectDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - -/** - * Initializes this dictionary, copying the given values and keys. - * - * @param objects The values to be placed in this dictionary. - * @param keys The keys under which to store the values. - * @param count The number of elements to copy into the dictionary. - * - * @return A newly initialized dictionary with a copy of the values and keys. - **/ -- (instancetype)initWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects - forKeys:(const uint32_t [__nullable])keys - count:(NSUInteger)count NS_DESIGNATED_INITIALIZER; - -/** - * Initializes this dictionary, copying the entries from the given dictionary. + * Initializes this dictionary, copying the entries from the given dictionary. * * @param dictionary Dictionary containing the entries to add to this dictionary. * @@ -1391,7 +936,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndObjectsUsingBlock: - (void (^)(uint32_t key, ObjectType object, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint32_t key, ObjectType object, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -1436,55 +981,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithUInt32:(uint32_t)value - forKey:(int32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithUInt32s:(const uint32_t [__nullable])values - forKeys:(const int32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt32UInt32Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -1535,7 +1031,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndUInt32sUsingBlock: - (void (^)(int32_t key, uint32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int32_t key, uint32_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -1580,55 +1076,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithInt32:(int32_t)value - forKey:(int32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithInt32s:(const int32_t [__nullable])values - forKeys:(const int32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt32Int32Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -1679,7 +1126,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndInt32sUsingBlock: - (void (^)(int32_t key, int32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -1724,55 +1171,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithUInt64:(uint64_t)value - forKey:(int32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithUInt64s:(const uint64_t [__nullable])values - forKeys:(const int32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt32UInt64Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -1823,7 +1221,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndUInt64sUsingBlock: - (void (^)(int32_t key, uint64_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int32_t key, uint64_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -1868,55 +1266,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithInt64:(int64_t)value - forKey:(int32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithInt64s:(const int64_t [__nullable])values - forKeys:(const int32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt32Int64Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -1967,7 +1316,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndInt64sUsingBlock: - (void (^)(int32_t key, int64_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int32_t key, int64_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -2012,55 +1361,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithBool:(BOOL)value - forKey:(int32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithBools:(const BOOL [__nullable])values - forKeys:(const int32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt32BoolDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -2111,7 +1411,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndBoolsUsingBlock: - (void (^)(int32_t key, BOOL value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int32_t key, BOOL value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -2156,55 +1456,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithFloat:(float)value - forKey:(int32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithFloats:(const float [__nullable])values - forKeys:(const int32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt32FloatDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -2255,7 +1506,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndFloatsUsingBlock: - (void (^)(int32_t key, float value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int32_t key, float value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -2300,55 +1551,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithDouble:(double)value - forKey:(int32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithDoubles:(const double [__nullable])values - forKeys:(const int32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt32DoubleDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -2399,7 +1601,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndDoublesUsingBlock: - (void (^)(int32_t key, double value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int32_t key, double value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -2446,70 +1648,6 @@ NS_ASSUME_NONNULL_BEGIN /** The validation function to check if the enums are valid. */ @property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the given validation function. - * - * @param func The enum validation function for the dictionary. - * - * @return A newly instanced dictionary. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param func The enum validation function for the dictionary. - * @param rawValue The raw enum value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - rawValue:(int32_t)rawValue - forKey:(int32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param func The enum validation function for the dictionary. - * @param values The raw enum values values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - rawValues:(const int32_t [__nullable])values - forKeys:(const int32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt32EnumDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param func The enum validation function for the dictionary. - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - capacity:(NSUInteger)numItems; - /** * Initializes a dictionary with the given validation function. * @@ -2579,7 +1717,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndEnumsUsingBlock: - (void (^)(int32_t key, int32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block; /** * Gets the raw enum value for the given key. @@ -2606,7 +1744,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndRawValuesUsingBlock: - (void (^)(int32_t key, int32_t rawValue, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int32_t key, int32_t rawValue, BOOL *stop))block; /** * Adds the keys and raw enum values from another dictionary. @@ -2670,55 +1808,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param object The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithObject:(ObjectType)object - forKey:(int32_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param objects The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects - forKeys:(const int32_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt32ObjectDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -2768,7 +1857,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndObjectsUsingBlock: - (void (^)(int32_t key, ObjectType object, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int32_t key, ObjectType object, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -2813,55 +1902,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithUInt32:(uint32_t)value - forKey:(uint64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithUInt32s:(const uint32_t [__nullable])values - forKeys:(const uint64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -2912,7 +1952,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndUInt32sUsingBlock: - (void (^)(uint64_t key, uint32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint64_t key, uint32_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -2957,55 +1997,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithInt32:(int32_t)value - forKey:(uint64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithInt32s:(const int32_t [__nullable])values - forKeys:(const uint64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt64Int32Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -3056,7 +2047,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndInt32sUsingBlock: - (void (^)(uint64_t key, int32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -3101,55 +2092,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithUInt64:(uint64_t)value - forKey:(uint64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithUInt64s:(const uint64_t [__nullable])values - forKeys:(const uint64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -3200,7 +2142,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndUInt64sUsingBlock: - (void (^)(uint64_t key, uint64_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint64_t key, uint64_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -3245,55 +2187,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithInt64:(int64_t)value - forKey:(uint64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithInt64s:(const int64_t [__nullable])values - forKeys:(const uint64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt64Int64Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -3344,7 +2237,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndInt64sUsingBlock: - (void (^)(uint64_t key, int64_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint64_t key, int64_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -3380,63 +2273,14 @@ NS_ASSUME_NONNULL_BEGIN /** * Class used for map fields of - * values. This performs better than boxing into NSNumbers in NSDictionaries. - * - * @note This class is not meant to be subclassed. - **/ -@interface GPBUInt64BoolDictionary : NSObject - -/** Number of entries stored in this dictionary. */ -@property(nonatomic, readonly) NSUInteger count; - -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithBool:(BOOL)value - forKey:(uint64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithBools:(const BOOL [__nullable])values - forKeys:(const uint64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt64BoolDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. + * values. This performs better than boxing into NSNumbers in NSDictionaries. * - * @return A newly instanced dictionary with the given capacity. + * @note This class is not meant to be subclassed. **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; +@interface GPBUInt64BoolDictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; /** * Initializes this dictionary, copying the given values and keys. @@ -3488,7 +2332,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndBoolsUsingBlock: - (void (^)(uint64_t key, BOOL value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint64_t key, BOOL value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -3533,55 +2377,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithFloat:(float)value - forKey:(uint64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithFloats:(const float [__nullable])values - forKeys:(const uint64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt64FloatDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -3632,7 +2427,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndFloatsUsingBlock: - (void (^)(uint64_t key, float value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint64_t key, float value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -3677,55 +2472,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithDouble:(double)value - forKey:(uint64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithDoubles:(const double [__nullable])values - forKeys:(const uint64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt64DoubleDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -3776,7 +2522,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndDoublesUsingBlock: - (void (^)(uint64_t key, double value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint64_t key, double value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -3823,70 +2569,6 @@ NS_ASSUME_NONNULL_BEGIN /** The validation function to check if the enums are valid. */ @property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the given validation function. - * - * @param func The enum validation function for the dictionary. - * - * @return A newly instanced dictionary. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param func The enum validation function for the dictionary. - * @param rawValue The raw enum value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - rawValue:(int32_t)rawValue - forKey:(uint64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param func The enum validation function for the dictionary. - * @param values The raw enum values values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - rawValues:(const int32_t [__nullable])values - forKeys:(const uint64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt64EnumDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param func The enum validation function for the dictionary. - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - capacity:(NSUInteger)numItems; - /** * Initializes a dictionary with the given validation function. * @@ -3956,7 +2638,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndEnumsUsingBlock: - (void (^)(uint64_t key, int32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block; /** * Gets the raw enum value for the given key. @@ -3983,7 +2665,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndRawValuesUsingBlock: - (void (^)(uint64_t key, int32_t rawValue, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint64_t key, int32_t rawValue, BOOL *stop))block; /** * Adds the keys and raw enum values from another dictionary. @@ -4047,55 +2729,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param object The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithObject:(ObjectType)object - forKey:(uint64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param objects The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects - forKeys:(const uint64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBUInt64ObjectDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -4145,7 +2778,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndObjectsUsingBlock: - (void (^)(uint64_t key, ObjectType object, BOOL *stop))block; + (void (NS_NOESCAPE ^)(uint64_t key, ObjectType object, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -4190,55 +2823,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithUInt32:(uint32_t)value - forKey:(int64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithUInt32s:(const uint32_t [__nullable])values - forKeys:(const int64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt64UInt32Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -4289,7 +2873,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndUInt32sUsingBlock: - (void (^)(int64_t key, uint32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int64_t key, uint32_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -4334,55 +2918,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithInt32:(int32_t)value - forKey:(int64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithInt32s:(const int32_t [__nullable])values - forKeys:(const int64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt64Int32Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -4433,7 +2968,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndInt32sUsingBlock: - (void (^)(int64_t key, int32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -4478,55 +3013,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithUInt64:(uint64_t)value - forKey:(int64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithUInt64s:(const uint64_t [__nullable])values - forKeys:(const int64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt64UInt64Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -4577,7 +3063,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndUInt64sUsingBlock: - (void (^)(int64_t key, uint64_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int64_t key, uint64_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -4611,65 +3097,16 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Int64 -> Int64 -/** - * Class used for map fields of - * values. This performs better than boxing into NSNumbers in NSDictionaries. - * - * @note This class is not meant to be subclassed. - **/ -@interface GPBInt64Int64Dictionary : NSObject - -/** Number of entries stored in this dictionary. */ -@property(nonatomic, readonly) NSUInteger count; - -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithInt64:(int64_t)value - forKey:(int64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithInt64s:(const int64_t [__nullable])values - forKeys:(const int64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt64Int64Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. +/** + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. * - * @return A newly instanced dictionary with the given capacity. + * @note This class is not meant to be subclassed. **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; +@interface GPBInt64Int64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; /** * Initializes this dictionary, copying the given values and keys. @@ -4721,7 +3158,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndInt64sUsingBlock: - (void (^)(int64_t key, int64_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int64_t key, int64_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -4766,55 +3203,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithBool:(BOOL)value - forKey:(int64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithBools:(const BOOL [__nullable])values - forKeys:(const int64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt64BoolDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -4865,7 +3253,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndBoolsUsingBlock: - (void (^)(int64_t key, BOOL value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int64_t key, BOOL value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -4910,55 +3298,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithFloat:(float)value - forKey:(int64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithFloats:(const float [__nullable])values - forKeys:(const int64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt64FloatDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -5009,7 +3348,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndFloatsUsingBlock: - (void (^)(int64_t key, float value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int64_t key, float value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -5054,55 +3393,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithDouble:(double)value - forKey:(int64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithDoubles:(const double [__nullable])values - forKeys:(const int64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt64DoubleDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -5153,7 +3443,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndDoublesUsingBlock: - (void (^)(int64_t key, double value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int64_t key, double value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -5200,70 +3490,6 @@ NS_ASSUME_NONNULL_BEGIN /** The validation function to check if the enums are valid. */ @property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the given validation function. - * - * @param func The enum validation function for the dictionary. - * - * @return A newly instanced dictionary. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param func The enum validation function for the dictionary. - * @param rawValue The raw enum value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - rawValue:(int32_t)rawValue - forKey:(int64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param func The enum validation function for the dictionary. - * @param values The raw enum values values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - rawValues:(const int32_t [__nullable])values - forKeys:(const int64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt64EnumDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param func The enum validation function for the dictionary. - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - capacity:(NSUInteger)numItems; - /** * Initializes a dictionary with the given validation function. * @@ -5333,7 +3559,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndEnumsUsingBlock: - (void (^)(int64_t key, int32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block; /** * Gets the raw enum value for the given key. @@ -5360,7 +3586,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndRawValuesUsingBlock: - (void (^)(int64_t key, int32_t rawValue, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int64_t key, int32_t rawValue, BOOL *stop))block; /** * Adds the keys and raw enum values from another dictionary. @@ -5424,55 +3650,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param object The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithObject:(ObjectType)object - forKey:(int64_t)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param objects The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects - forKeys:(const int64_t [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBInt64ObjectDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -5522,7 +3699,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndObjectsUsingBlock: - (void (^)(int64_t key, ObjectType object, BOOL *stop))block; + (void (NS_NOESCAPE ^)(int64_t key, ObjectType object, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -5567,55 +3744,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithUInt32:(uint32_t)value - forKey:(BOOL)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithUInt32s:(const uint32_t [__nullable])values - forKeys:(const BOOL [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBBoolUInt32Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -5666,7 +3794,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndUInt32sUsingBlock: - (void (^)(BOOL key, uint32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(BOOL key, uint32_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -5711,55 +3839,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithInt32:(int32_t)value - forKey:(BOOL)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithInt32s:(const int32_t [__nullable])values - forKeys:(const BOOL [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBBoolInt32Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -5810,7 +3889,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndInt32sUsingBlock: - (void (^)(BOOL key, int32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(BOOL key, int32_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -5842,67 +3921,18 @@ NS_ASSUME_NONNULL_BEGIN @end -#pragma mark - Bool -> UInt64 - -/** - * Class used for map fields of - * values. This performs better than boxing into NSNumbers in NSDictionaries. - * - * @note This class is not meant to be subclassed. - **/ -@interface GPBBoolUInt64Dictionary : NSObject - -/** Number of entries stored in this dictionary. */ -@property(nonatomic, readonly) NSUInteger count; - -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithUInt64:(uint64_t)value - forKey:(BOOL)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithUInt64s:(const uint64_t [__nullable])values - forKeys:(const BOOL [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBBoolUInt64Dictionary *)dictionary; +#pragma mark - Bool -> UInt64 /** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. + * Class used for map fields of + * values. This performs better than boxing into NSNumbers in NSDictionaries. * - * @return A newly instanced dictionary with the given capacity. + * @note This class is not meant to be subclassed. **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; +@interface GPBBoolUInt64Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; /** * Initializes this dictionary, copying the given values and keys. @@ -5954,7 +3984,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndUInt64sUsingBlock: - (void (^)(BOOL key, uint64_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(BOOL key, uint64_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -5999,55 +4029,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithInt64:(int64_t)value - forKey:(BOOL)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithInt64s:(const int64_t [__nullable])values - forKeys:(const BOOL [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBBoolInt64Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -6098,7 +4079,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndInt64sUsingBlock: - (void (^)(BOOL key, int64_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(BOOL key, int64_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -6143,55 +4124,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithBool:(BOOL)value - forKey:(BOOL)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithBools:(const BOOL [__nullable])values - forKeys:(const BOOL [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBBoolBoolDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -6242,7 +4174,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndBoolsUsingBlock: - (void (^)(BOOL key, BOOL value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(BOOL key, BOOL value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -6287,55 +4219,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithFloat:(float)value - forKey:(BOOL)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithFloats:(const float [__nullable])values - forKeys:(const BOOL [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBBoolFloatDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -6386,7 +4269,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndFloatsUsingBlock: - (void (^)(BOOL key, float value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(BOOL key, float value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -6431,55 +4314,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithDouble:(double)value - forKey:(BOOL)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithDoubles:(const double [__nullable])values - forKeys:(const BOOL [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBBoolDoubleDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -6530,7 +4364,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndDoublesUsingBlock: - (void (^)(BOOL key, double value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(BOOL key, double value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -6577,70 +4411,6 @@ NS_ASSUME_NONNULL_BEGIN /** The validation function to check if the enums are valid. */ @property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the given validation function. - * - * @param func The enum validation function for the dictionary. - * - * @return A newly instanced dictionary. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param func The enum validation function for the dictionary. - * @param rawValue The raw enum value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - rawValue:(int32_t)rawValue - forKey:(BOOL)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param func The enum validation function for the dictionary. - * @param values The raw enum values values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - rawValues:(const int32_t [__nullable])values - forKeys:(const BOOL [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBBoolEnumDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param func The enum validation function for the dictionary. - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - capacity:(NSUInteger)numItems; - /** * Initializes a dictionary with the given validation function. * @@ -6710,7 +4480,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndEnumsUsingBlock: - (void (^)(BOOL key, int32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(BOOL key, int32_t value, BOOL *stop))block; /** * Gets the raw enum value for the given key. @@ -6737,7 +4507,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndRawValuesUsingBlock: - (void (^)(BOOL key, int32_t rawValue, BOOL *stop))block; + (void (NS_NOESCAPE ^)(BOOL key, int32_t rawValue, BOOL *stop))block; /** * Adds the keys and raw enum values from another dictionary. @@ -6801,55 +4571,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param object The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithObject:(ObjectType)object - forKey:(BOOL)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param objects The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithObjects:(const ObjectType __nonnull GPB_UNSAFE_UNRETAINED [__nullable])objects - forKeys:(const BOOL [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBBoolObjectDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -6899,7 +4620,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndObjectsUsingBlock: - (void (^)(BOOL key, ObjectType object, BOOL *stop))block; + (void (NS_NOESCAPE ^)(BOOL key, ObjectType object, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -6944,55 +4665,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithUInt32:(uint32_t)value - forKey:(NSString *)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithUInt32s:(const uint32_t [__nullable])values - forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBStringUInt32Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -7043,7 +4715,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndUInt32sUsingBlock: - (void (^)(NSString *key, uint32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(NSString *key, uint32_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -7083,59 +4755,10 @@ NS_ASSUME_NONNULL_BEGIN * * @note This class is not meant to be subclassed. **/ -@interface GPBStringInt32Dictionary : NSObject - -/** Number of entries stored in this dictionary. */ -@property(nonatomic, readonly) NSUInteger count; - -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithInt32:(int32_t)value - forKey:(NSString *)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithInt32s:(const int32_t [__nullable])values - forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBStringInt32Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; +@interface GPBStringInt32Dictionary : NSObject + +/** Number of entries stored in this dictionary. */ +@property(nonatomic, readonly) NSUInteger count; /** * Initializes this dictionary, copying the given values and keys. @@ -7187,7 +4810,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndInt32sUsingBlock: - (void (^)(NSString *key, int32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -7232,55 +4855,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithUInt64:(uint64_t)value - forKey:(NSString *)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithUInt64s:(const uint64_t [__nullable])values - forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBStringUInt64Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -7331,7 +4905,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndUInt64sUsingBlock: - (void (^)(NSString *key, uint64_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(NSString *key, uint64_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -7376,55 +4950,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithInt64:(int64_t)value - forKey:(NSString *)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithInt64s:(const int64_t [__nullable])values - forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBStringInt64Dictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -7475,7 +5000,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndInt64sUsingBlock: - (void (^)(NSString *key, int64_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(NSString *key, int64_t value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -7520,55 +5045,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithBool:(BOOL)value - forKey:(NSString *)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithBools:(const BOOL [__nullable])values - forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBStringBoolDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -7619,7 +5095,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndBoolsUsingBlock: - (void (^)(NSString *key, BOOL value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(NSString *key, BOOL value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -7664,55 +5140,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithFloat:(float)value - forKey:(NSString *)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithFloats:(const float [__nullable])values - forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBStringFloatDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -7763,7 +5190,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndFloatsUsingBlock: - (void (^)(NSString *key, float value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(NSString *key, float value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -7808,55 +5235,6 @@ NS_ASSUME_NONNULL_BEGIN /** Number of entries stored in this dictionary. */ @property(nonatomic, readonly) NSUInteger count; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param value The value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithDouble:(double)value - forKey:(NSString *)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param values The values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithDoubles:(const double [__nullable])values - forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBStringDoubleDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; - /** * Initializes this dictionary, copying the given values and keys. * @@ -7907,7 +5285,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndDoublesUsingBlock: - (void (^)(NSString *key, double value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(NSString *key, double value, BOOL *stop))block; /** * Adds the keys and values from another dictionary. @@ -7954,70 +5332,6 @@ NS_ASSUME_NONNULL_BEGIN /** The validation function to check if the enums are valid. */ @property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; -/** - * @return A newly instanced and empty dictionary. - **/ -+ (instancetype)dictionary; - -/** - * Creates and initializes a dictionary with the given validation function. - * - * @param func The enum validation function for the dictionary. - * - * @return A newly instanced dictionary. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func; - -/** - * Creates and initializes a dictionary with the single entry given. - * - * @param func The enum validation function for the dictionary. - * @param rawValue The raw enum value to be placed in the dictionary. - * @param key The key under which to store the value. - * - * @return A newly instanced dictionary with the key and value in it. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - rawValue:(int32_t)rawValue - forKey:(NSString *)key; - -/** - * Creates and initializes a dictionary with the entries given. - * - * @param func The enum validation function for the dictionary. - * @param values The raw enum values values to be placed in the dictionary. - * @param keys The keys under which to store the values. - * @param count The number of entries to store in the dictionary. - * - * @return A newly instanced dictionary with the keys and values in it. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - rawValues:(const int32_t [__nullable])values - forKeys:(const NSString * __nonnull GPB_UNSAFE_UNRETAINED [__nullable])keys - count:(NSUInteger)count; - -/** - * Creates and initializes a dictionary with the entries from the given. - * dictionary. - * - * @param dictionary Dictionary containing the entries to add to the dictionary. - * - * @return A newly instanced dictionary with the entries from the given - * dictionary in it. - **/ -+ (instancetype)dictionaryWithDictionary:(GPBStringEnumDictionary *)dictionary; - -/** - * Creates and initializes a dictionary with the given capacity. - * - * @param func The enum validation function for the dictionary. - * @param numItems Capacity needed for the dictionary. - * - * @return A newly instanced dictionary with the given capacity. - **/ -+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func - capacity:(NSUInteger)numItems; - /** * Initializes a dictionary with the given validation function. * @@ -8087,7 +5401,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndEnumsUsingBlock: - (void (^)(NSString *key, int32_t value, BOOL *stop))block; + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block; /** * Gets the raw enum value for the given key. @@ -8114,7 +5428,7 @@ NS_ASSUME_NONNULL_BEGIN * **stop**: A pointer to a boolean that when set stops the enumeration. **/ - (void)enumerateKeysAndRawValuesUsingBlock: - (void (^)(NSString *key, int32_t rawValue, BOOL *stop))block; + (void (NS_NOESCAPE ^)(NSString *key, int32_t rawValue, BOOL *stop))block; /** * Adds the keys and raw enum values from another dictionary. @@ -8165,6 +5479,7 @@ NS_ASSUME_NONNULL_BEGIN @end +// clang-format on //%PDDM-EXPAND-END DECLARE_DICTIONARIES() NS_ASSUME_NONNULL_END @@ -8240,55 +5555,6 @@ NS_ASSUME_NONNULL_END //%@property(nonatomic, readonly) NSUInteger count; //% //%/** -//% * @return A newly instanced and empty dictionary. -//% **/ -//%+ (instancetype)dictionary; -//% -//%/** -//% * Creates and initializes a dictionary with the single entry given. -//% * -//% * @param ##VNAME_VAR The value to be placed in the dictionary. -//% * @param key ##VNAME_VAR$S## The key under which to store the value. -//% * -//% * @return A newly instanced dictionary with the key and value in it. -//% **/ -//%+ (instancetype)dictionaryWith##VNAME##:(VALUE_TYPE)##VNAME_VAR -//% ##VNAME$S## forKey:(KEY_TYPE##KisP$S##KisP)key; -//% -//%/** -//% * Creates and initializes a dictionary with the entries given. -//% * -//% * @param ##VNAME_VAR##s The values to be placed in the dictionary. -//% * @param keys ##VNAME_VAR$S## The keys under which to store the values. -//% * @param count ##VNAME_VAR$S## The number of entries to store in the dictionary. -//% * -//% * @return A newly instanced dictionary with the keys and values in it. -//% **/ -//%+ (instancetype)dictionaryWith##VNAME##s:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[__nullable])##VNAME_VAR##s -//% ##VNAME$S## forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[__nullable])keys -//% ##VNAME$S## count:(NSUInteger)count; -//% -//%/** -//% * Creates and initializes a dictionary with the entries from the given. -//% * dictionary. -//% * -//% * @param dictionary Dictionary containing the entries to add to the dictionary. -//% * -//% * @return A newly instanced dictionary with the entries from the given -//% * dictionary in it. -//% **/ -//%+ (instancetype)dictionaryWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary; -//% -//%/** -//% * Creates and initializes a dictionary with the given capacity. -//% * -//% * @param numItems Capacity needed for the dictionary. -//% * -//% * @return A newly instanced dictionary with the given capacity. -//% **/ -//%+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems; -//% -//%/** //% * Initializes this dictionary, copying the given values and keys. //% * //% * @param ##VNAME_VAR##s The values to be placed in this dictionary. @@ -8353,70 +5619,6 @@ NS_ASSUME_NONNULL_END //%@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc; //% //%/** -//% * @return A newly instanced and empty dictionary. -//% **/ -//%+ (instancetype)dictionary; -//% -//%/** -//% * Creates and initializes a dictionary with the given validation function. -//% * -//% * @param func The enum validation function for the dictionary. -//% * -//% * @return A newly instanced dictionary. -//% **/ -//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func; -//% -//%/** -//% * Creates and initializes a dictionary with the single entry given. -//% * -//% * @param func The enum validation function for the dictionary. -//% * @param rawValue The raw enum value to be placed in the dictionary. -//% * @param key The key under which to store the value. -//% * -//% * @return A newly instanced dictionary with the key and value in it. -//% **/ -//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func -//% rawValue:(VALUE_TYPE)rawValue -//% forKey:(KEY_TYPE##KisP$S##KisP)key; -//% -//%/** -//% * Creates and initializes a dictionary with the entries given. -//% * -//% * @param func The enum validation function for the dictionary. -//% * @param values The raw enum values values to be placed in the dictionary. -//% * @param keys The keys under which to store the values. -//% * @param count The number of entries to store in the dictionary. -//% * -//% * @return A newly instanced dictionary with the keys and values in it. -//% **/ -//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func -//% rawValues:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[__nullable])values -//% forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[__nullable])keys -//% count:(NSUInteger)count; -//% -//%/** -//% * Creates and initializes a dictionary with the entries from the given. -//% * dictionary. -//% * -//% * @param dictionary Dictionary containing the entries to add to the dictionary. -//% * -//% * @return A newly instanced dictionary with the entries from the given -//% * dictionary in it. -//% **/ -//%+ (instancetype)dictionaryWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary; -//% -//%/** -//% * Creates and initializes a dictionary with the given capacity. -//% * -//% * @param func The enum validation function for the dictionary. -//% * @param numItems Capacity needed for the dictionary. -//% * -//% * @return A newly instanced dictionary with the given capacity. -//% **/ -//%+ (instancetype)dictionaryWithValidationFunction:(nullable GPBEnumValidationFunc)func -//% capacity:(NSUInteger)numItems; -//% -//%/** //% * Initializes a dictionary with the given validation function. //% * //% * @param func The enum validation function for the dictionary. @@ -8493,7 +5695,7 @@ NS_ASSUME_NONNULL_END //% * **stop**: A pointer to a boolean that when set stops the enumeration. //% **/ //%- (void)enumerateKeysAndRawValuesUsingBlock: -//% (void (^)(KEY_TYPE KisP##key, VALUE_TYPE rawValue, BOOL *stop))block; +//% (void (NS_NOESCAPE ^)(KEY_TYPE KisP##key, VALUE_TYPE rawValue, BOOL *stop))block; //% //%/** //% * Adds the keys and raw enum values from another dictionary. @@ -8528,7 +5730,7 @@ NS_ASSUME_NONNULL_END //% * **stop**: ##VNAME_VAR$S## A pointer to a boolean that when set stops the enumeration. //% **/ //%- (void)enumerateKeysAnd##VNAME##sUsingBlock: -//% (void (^)(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, BOOL *stop))block; +//% (void (NS_NOESCAPE ^)(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, BOOL *stop))block; //%PDDM-DEFINE DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER, VNAME, VNAME_VAR) //%/** diff --git a/objectivec/GPBDictionary.m b/objectivec/GPBDictionary.m index 7713376e3f676..187a97092fbbf 100644 --- a/objectivec/GPBDictionary.m +++ b/objectivec/GPBDictionary.m @@ -147,6 +147,7 @@ static BOOL DictDefault_IsValidValue(int32_t value) { //%SERIALIZE_SUPPORT_3_TYPE(Object, id, Message, String, Bytes) //%PDDM-EXPAND SERIALIZE_SUPPORT_HELPERS() // This block of code is generated, do not edit it directly. +// clang-format off static size_t ComputeDictInt32FieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) { if (dataType == GPBDataTypeInt32) { @@ -325,6 +326,7 @@ static void WriteDictObjectField(GPBCodedOutputStream *stream, id value, uint32_ } } +// clang-format on //%PDDM-EXPAND-END SERIALIZE_SUPPORT_HELPERS() size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) { @@ -508,7 +510,7 @@ void GPBDictionaryReadEntry(id mapDictionary, #if defined(__clang_analyzer__) case GPBDataTypeGroup: // Maps can't really have Groups as the value type, but this case is needed - // so the analyzer won't report the posibility of send nil in for the value + // so the analyzer won't report the possibility of send nil in for the value // in the NSMutableDictionary case below. #endif case GPBDataTypeMessage: { @@ -596,39 +598,6 @@ void GPBDictionaryReadEntry(id mapDictionary, //% NSMutableDictionary *_dictionary; //%} //% -//%+ (instancetype)dictionary { -//% return [[[self alloc] initWith##VNAME##s:NULL forKeys:NULL count:0] autorelease]; -//%} -//% -//%+ (instancetype)dictionaryWith##VNAME##:(VALUE_TYPE)##VNAME_VAR -//% ##VNAME$S## forKey:(KEY_TYPE##KisP$S##KisP)key { -//% // Cast is needed so the compiler knows what class we are invoking initWith##VNAME##s:forKeys:count: -//% // on to get the type correct. -//% return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWith##VNAME##s:&##VNAME_VAR -//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## forKeys:&key -//% KEY_NAME$S VALUE_NAME$S ##VNAME$S## count:1] autorelease]; -//%} -//% -//%+ (instancetype)dictionaryWith##VNAME##s:(const VALUE_TYPE [])##VNAME_VAR##s -//% ##VNAME$S## forKeys:(const KEY_TYPE##KisP$S##KisP [])keys -//% ##VNAME$S## count:(NSUInteger)count { -//% // Cast is needed so the compiler knows what class we are invoking initWith##VNAME##s:forKeys:count: -//% // on to get the type correct. -//% return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWith##VNAME##s:##VNAME_VAR##s -//% KEY_NAME$S VALUE_NAME$S forKeys:keys -//% KEY_NAME$S VALUE_NAME$S count:count] autorelease]; -//%} -//% -//%+ (instancetype)dictionaryWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary { -//% // Cast is needed so the compiler knows what class we are invoking initWithDictionary: -//% // on to get the type correct. -//% return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -//%} -//% -//%+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { -//% return [[[self alloc] initWithCapacity:numItems] autorelease]; -//%} -//% //%- (instancetype)init { //% return [self initWith##VNAME##s:NULL forKeys:NULL count:0]; //%} @@ -685,54 +654,6 @@ void GPBDictionaryReadEntry(id mapDictionary, //% //%@synthesize validationFunc = _validationFunc; //% -//%+ (instancetype)dictionary { -//% return [[[self alloc] initWithValidationFunction:NULL -//% rawValues:NULL -//% forKeys:NULL -//% count:0] autorelease]; -//%} -//% -//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func { -//% return [[[self alloc] initWithValidationFunction:func -//% rawValues:NULL -//% forKeys:NULL -//% count:0] autorelease]; -//%} -//% -//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func -//% rawValue:(VALUE_TYPE)rawValue -//% forKey:(KEY_TYPE##KisP$S##KisP)key { -//% // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: -//% // on to get the type correct. -//% return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWithValidationFunction:func -//% KEY_NAME$S VALUE_NAME$S rawValues:&rawValue -//% KEY_NAME$S VALUE_NAME$S forKeys:&key -//% KEY_NAME$S VALUE_NAME$S count:1] autorelease]; -//%} -//% -//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func -//% rawValues:(const VALUE_TYPE [])rawValues -//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys -//% count:(NSUInteger)count { -//% // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: -//% // on to get the type correct. -//% return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWithValidationFunction:func -//% KEY_NAME$S VALUE_NAME$S rawValues:rawValues -//% KEY_NAME$S VALUE_NAME$S forKeys:keys -//% KEY_NAME$S VALUE_NAME$S count:count] autorelease]; -//%} -//% -//%+ (instancetype)dictionaryWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary { -//% // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: -//% // on to get the type correct. -//% return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -//%} -//% -//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func -//% capacity:(NSUInteger)numItems { -//% return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease]; -//%} -//% //%- (instancetype)init { //% return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; //%} @@ -800,7 +721,7 @@ void GPBDictionaryReadEntry(id mapDictionary, //%} //% //%- (void)enumerateKeysAndEnumsUsingBlock: -//% (void (^)(KEY_TYPE KisP##key, VALUE_TYPE value, BOOL *stop))block { +//% (void (NS_NOESCAPE ^)(KEY_TYPE KisP##key, VALUE_TYPE value, BOOL *stop))block { //% GPBEnumValidationFunc func = _validationFunc; //% BOOL stop = NO; //% NSEnumerator *keys = [_dictionary keyEnumerator]; @@ -873,7 +794,7 @@ void GPBDictionaryReadEntry(id mapDictionary, //%} //% //%- (void)enumerateKeysAnd##ACCESSOR_NAME##VNAME##sUsingBlock: -//% (void (^)(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, BOOL *stop))block { +//% (void (NS_NOESCAPE ^)(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, BOOL *stop))block { //% BOOL stop = NO; //% NSDictionary *internal = _dictionary; //% NSEnumerator *keys = [internal keyEnumerator]; @@ -938,7 +859,7 @@ void GPBDictionaryReadEntry(id mapDictionary, //% [_dictionary setObject:WRAPPED##VHELPER(value->##GPBVALUE_##VHELPER(VALUE_NAME)##) forKey:WRAPPED##KHELPER(key->value##KEY_NAME)]; //%} //% -//%- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +//%- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { //% [self enumerateKeysAnd##ACCESSOR_NAME##VNAME##sUsingBlock:^(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, BOOL *stop) { //% #pragma unused(stop) //% block(TEXT_FORMAT_OBJ##KEY_NAME(key), TEXT_FORMAT_OBJ##VALUE_NAME(VNAME_VAR)); @@ -988,39 +909,6 @@ void GPBDictionaryReadEntry(id mapDictionary, //% VALUE_TYPE _values[2]; //%BOOL_DICT_HAS_STORAGE_##HELPER()} //% -//%+ (instancetype)dictionary { -//% return [[[self alloc] initWith##VNAME##s:NULL forKeys:NULL count:0] autorelease]; -//%} -//% -//%+ (instancetype)dictionaryWith##VNAME##:(VALUE_TYPE)VNAME_VAR -//% ##VNAME$S## forKey:(BOOL)key { -//% // Cast is needed so the compiler knows what class we are invoking initWith##VNAME##s:forKeys:count: -//% // on to get the type correct. -//% return [[(GPBBool##VALUE_NAME##Dictionary*)[self alloc] initWith##VNAME##s:&##VNAME_VAR -//% VALUE_NAME$S ##VNAME$S## forKeys:&key -//% VALUE_NAME$S ##VNAME$S## count:1] autorelease]; -//%} -//% -//%+ (instancetype)dictionaryWith##VNAME##s:(const VALUE_TYPE [])##VNAME_VAR##s -//% ##VNAME$S## forKeys:(const BOOL [])keys -//% ##VNAME$S## count:(NSUInteger)count { -//% // Cast is needed so the compiler knows what class we are invoking initWith##VNAME##s:forKeys:count: -//% // on to get the type correct. -//% return [[(GPBBool##VALUE_NAME##Dictionary*)[self alloc] initWith##VNAME##s:##VNAME_VAR##s -//% VALUE_NAME$S ##VNAME$S## forKeys:keys -//% VALUE_NAME$S ##VNAME$S## count:count] autorelease]; -//%} -//% -//%+ (instancetype)dictionaryWithDictionary:(GPBBool##VALUE_NAME##Dictionary *)dictionary { -//% // Cast is needed so the compiler knows what class we are invoking initWithDictionary: -//% // on to get the type correct. -//% return [[(GPBBool##VALUE_NAME##Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -//%} -//% -//%+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { -//% return [[[self alloc] initWithCapacity:numItems] autorelease]; -//%} -//% //%- (instancetype)init { //% return [self initWith##VNAME##s:NULL forKeys:NULL count:0]; //%} @@ -1081,7 +969,7 @@ void GPBDictionaryReadEntry(id mapDictionary, //% //%BOOL_SET_GPBVALUE_FOR_KEY_##HELPER(VALUE_NAME, VALUE_TYPE, VisP) //% -//%- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +//%- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { //% if (BOOL_DICT_HAS##HELPER(0, )) { //% block(@"false", TEXT_FORMAT_OBJ##VALUE_NAME(_values[0])); //% } @@ -1091,7 +979,7 @@ void GPBDictionaryReadEntry(id mapDictionary, //%} //% //%- (void)enumerateKeysAnd##VNAME##sUsingBlock: -//% (void (^)(BOOL key, VALUE_TYPE VNAME_VAR, BOOL *stop))block { +//% (void (NS_NOESCAPE ^)(BOOL key, VALUE_TYPE VNAME_VAR, BOOL *stop))block { //% BOOL stop = NO; //% if (BOOL_DICT_HAS##HELPER(0, )) { //% block(NO, _values[0], &stop); @@ -1541,6 +1429,7 @@ void GPBDictionaryReadEntry(id mapDictionary, //%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(UInt32, uint32_t) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - UInt32 -> UInt32 @@ -1549,39 +1438,6 @@ @implementation GPBUInt32UInt32Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithUInt32s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithUInt32:(uint32_t)value - forKey:(uint32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithUInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32UInt32Dictionary*)[self alloc] initWithUInt32s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithUInt32s:(const uint32_t [])values - forKeys:(const uint32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithUInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32UInt32Dictionary*)[self alloc] initWithUInt32s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt32UInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithUInt32s:NULL forKeys:NULL count:0]; } @@ -1652,7 +1508,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndUInt32sUsingBlock: - (void (^)(uint32_t key, uint32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint32_t key, uint32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -1717,7 +1573,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndUInt32sUsingBlock:^(uint32_t key, uint32_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%u", value]); @@ -1765,39 +1621,6 @@ @implementation GPBUInt32Int32Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithInt32s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithInt32:(int32_t)value - forKey:(uint32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32Int32Dictionary*)[self alloc] initWithInt32s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithInt32s:(const int32_t [])values - forKeys:(const uint32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32Int32Dictionary*)[self alloc] initWithInt32s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt32Int32Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt32Int32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithInt32s:NULL forKeys:NULL count:0]; } @@ -1868,7 +1691,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndInt32sUsingBlock: - (void (^)(uint32_t key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -1933,7 +1756,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndInt32sUsingBlock:^(uint32_t key, int32_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%d", value]); @@ -1981,39 +1804,6 @@ @implementation GPBUInt32UInt64Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithUInt64s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithUInt64:(uint64_t)value - forKey:(uint32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithUInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32UInt64Dictionary*)[self alloc] initWithUInt64s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithUInt64s:(const uint64_t [])values - forKeys:(const uint32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithUInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32UInt64Dictionary*)[self alloc] initWithUInt64s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt32UInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithUInt64s:NULL forKeys:NULL count:0]; } @@ -2084,7 +1874,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndUInt64sUsingBlock: - (void (^)(uint32_t key, uint64_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint32_t key, uint64_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -2149,7 +1939,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndUInt64sUsingBlock:^(uint32_t key, uint64_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%llu", value]); @@ -2197,39 +1987,6 @@ @implementation GPBUInt32Int64Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithInt64s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithInt64:(int64_t)value - forKey:(uint32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32Int64Dictionary*)[self alloc] initWithInt64s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithInt64s:(const int64_t [])values - forKeys:(const uint32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32Int64Dictionary*)[self alloc] initWithInt64s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt32Int64Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt32Int64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithInt64s:NULL forKeys:NULL count:0]; } @@ -2300,7 +2057,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndInt64sUsingBlock: - (void (^)(uint32_t key, int64_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint32_t key, int64_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -2365,7 +2122,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndInt64sUsingBlock:^(uint32_t key, int64_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%lld", value]); @@ -2413,39 +2170,6 @@ @implementation GPBUInt32BoolDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithBools:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithBool:(BOOL)value - forKey:(uint32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithBools:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32BoolDictionary*)[self alloc] initWithBools:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithBools:(const BOOL [])values - forKeys:(const uint32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithBools:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32BoolDictionary*)[self alloc] initWithBools:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt32BoolDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt32BoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithBools:NULL forKeys:NULL count:0]; } @@ -2516,7 +2240,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndBoolsUsingBlock: - (void (^)(uint32_t key, BOOL value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint32_t key, BOOL value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -2581,7 +2305,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndBoolsUsingBlock:^(uint32_t key, BOOL value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%u", key], (value ? @"true" : @"false")); @@ -2629,39 +2353,6 @@ @implementation GPBUInt32FloatDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithFloats:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithFloat:(float)value - forKey:(uint32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithFloats:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32FloatDictionary*)[self alloc] initWithFloats:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithFloats:(const float [])values - forKeys:(const uint32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithFloats:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32FloatDictionary*)[self alloc] initWithFloats:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt32FloatDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt32FloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithFloats:NULL forKeys:NULL count:0]; } @@ -2732,7 +2423,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndFloatsUsingBlock: - (void (^)(uint32_t key, float value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint32_t key, float value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -2797,7 +2488,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndFloatsUsingBlock:^(uint32_t key, float value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); @@ -2845,39 +2536,6 @@ @implementation GPBUInt32DoubleDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithDoubles:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithDouble:(double)value - forKey:(uint32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithDoubles:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32DoubleDictionary*)[self alloc] initWithDoubles:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithDoubles:(const double [])values - forKeys:(const uint32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithDoubles:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32DoubleDictionary*)[self alloc] initWithDoubles:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt32DoubleDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt32DoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithDoubles:NULL forKeys:NULL count:0]; } @@ -2948,7 +2606,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndDoublesUsingBlock: - (void (^)(uint32_t key, double value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint32_t key, double value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -3013,7 +2671,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndDoublesUsingBlock:^(uint32_t key, double value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); @@ -3064,54 +2722,6 @@ @implementation GPBUInt32EnumDictionary { @synthesize validationFunc = _validationFunc; -+ (instancetype)dictionary { - return [[[self alloc] initWithValidationFunction:NULL - rawValues:NULL - forKeys:NULL - count:0] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func { - return [[[self alloc] initWithValidationFunction:func - rawValues:NULL - forKeys:NULL - count:0] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - rawValue:(int32_t)rawValue - forKey:(uint32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32EnumDictionary*)[self alloc] initWithValidationFunction:func - rawValues:&rawValue - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - rawValues:(const int32_t [])rawValues - forKeys:(const uint32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32EnumDictionary*)[self alloc] initWithValidationFunction:func - rawValues:rawValues - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt32EnumDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32EnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - capacity:(NSUInteger)numItems { - return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; } @@ -3192,7 +2802,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndRawValuesUsingBlock: - (void (^)(uint32_t key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -3269,7 +2879,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndRawValuesUsingBlock:^(uint32_t key, int32_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%u", key], @(value)); @@ -3297,7 +2907,7 @@ - (BOOL)getRawValue:(int32_t *)rawValue forKey:(uint32_t)key { } - (void)enumerateKeysAndEnumsUsingBlock: - (void (^)(uint32_t key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint32_t key, int32_t value, BOOL *stop))block { GPBEnumValidationFunc func = _validationFunc; BOOL stop = NO; NSEnumerator *keys = [_dictionary keyEnumerator]; @@ -3361,39 +2971,6 @@ @implementation GPBUInt32ObjectDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithObjects:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithObject:(id)object - forKey:(uint32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32ObjectDictionary*)[self alloc] initWithObjects:&object - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithObjects:(const id [])objects - forKeys:(const uint32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count: - // on to get the type correct. - return [[(GPBUInt32ObjectDictionary*)[self alloc] initWithObjects:objects - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt32ObjectDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt32ObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithObjects:NULL forKeys:NULL count:0]; } @@ -3468,7 +3045,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndObjectsUsingBlock: - (void (^)(uint32_t key, id object, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint32_t key, id object, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -3557,7 +3134,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:value->valueString forKey:@(key->valueUInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndObjectsUsingBlock:^(uint32_t key, id object, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%u", key], object); @@ -3599,8 +3176,10 @@ - (void)removeAll { @end +// clang-format on //%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(Int32, int32_t) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Int32 -> UInt32 @@ -3609,39 +3188,6 @@ @implementation GPBInt32UInt32Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithUInt32s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithUInt32:(uint32_t)value - forKey:(int32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithUInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBInt32UInt32Dictionary*)[self alloc] initWithUInt32s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithUInt32s:(const uint32_t [])values - forKeys:(const int32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithUInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBInt32UInt32Dictionary*)[self alloc] initWithUInt32s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt32UInt32Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt32UInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithUInt32s:NULL forKeys:NULL count:0]; } @@ -3712,7 +3258,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndUInt32sUsingBlock: - (void (^)(int32_t key, uint32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int32_t key, uint32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -3777,7 +3323,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndUInt32sUsingBlock:^(int32_t key, uint32_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%u", value]); @@ -3825,39 +3371,6 @@ @implementation GPBInt32Int32Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithInt32s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithInt32:(int32_t)value - forKey:(int32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBInt32Int32Dictionary*)[self alloc] initWithInt32s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithInt32s:(const int32_t [])values - forKeys:(const int32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBInt32Int32Dictionary*)[self alloc] initWithInt32s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt32Int32Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt32Int32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithInt32s:NULL forKeys:NULL count:0]; } @@ -3928,7 +3441,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndInt32sUsingBlock: - (void (^)(int32_t key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -3993,7 +3506,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndInt32sUsingBlock:^(int32_t key, int32_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%d", value]); @@ -4041,39 +3554,6 @@ @implementation GPBInt32UInt64Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithUInt64s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithUInt64:(uint64_t)value - forKey:(int32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithUInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBInt32UInt64Dictionary*)[self alloc] initWithUInt64s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithUInt64s:(const uint64_t [])values - forKeys:(const int32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithUInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBInt32UInt64Dictionary*)[self alloc] initWithUInt64s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt32UInt64Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt32UInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithUInt64s:NULL forKeys:NULL count:0]; } @@ -4144,7 +3624,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndUInt64sUsingBlock: - (void (^)(int32_t key, uint64_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int32_t key, uint64_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -4209,7 +3689,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndUInt64sUsingBlock:^(int32_t key, uint64_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%llu", value]); @@ -4257,39 +3737,6 @@ @implementation GPBInt32Int64Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithInt64s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithInt64:(int64_t)value - forKey:(int32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBInt32Int64Dictionary*)[self alloc] initWithInt64s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithInt64s:(const int64_t [])values - forKeys:(const int32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBInt32Int64Dictionary*)[self alloc] initWithInt64s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt32Int64Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt32Int64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithInt64s:NULL forKeys:NULL count:0]; } @@ -4360,7 +3807,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndInt64sUsingBlock: - (void (^)(int32_t key, int64_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int32_t key, int64_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -4425,7 +3872,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndInt64sUsingBlock:^(int32_t key, int64_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%lld", value]); @@ -4473,39 +3920,6 @@ @implementation GPBInt32BoolDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithBools:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithBool:(BOOL)value - forKey:(int32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithBools:forKeys:count: - // on to get the type correct. - return [[(GPBInt32BoolDictionary*)[self alloc] initWithBools:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithBools:(const BOOL [])values - forKeys:(const int32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithBools:forKeys:count: - // on to get the type correct. - return [[(GPBInt32BoolDictionary*)[self alloc] initWithBools:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt32BoolDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt32BoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithBools:NULL forKeys:NULL count:0]; } @@ -4576,7 +3990,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndBoolsUsingBlock: - (void (^)(int32_t key, BOOL value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int32_t key, BOOL value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -4641,7 +4055,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndBoolsUsingBlock:^(int32_t key, BOOL value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%d", key], (value ? @"true" : @"false")); @@ -4689,39 +4103,6 @@ @implementation GPBInt32FloatDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithFloats:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithFloat:(float)value - forKey:(int32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithFloats:forKeys:count: - // on to get the type correct. - return [[(GPBInt32FloatDictionary*)[self alloc] initWithFloats:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithFloats:(const float [])values - forKeys:(const int32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithFloats:forKeys:count: - // on to get the type correct. - return [[(GPBInt32FloatDictionary*)[self alloc] initWithFloats:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt32FloatDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt32FloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithFloats:NULL forKeys:NULL count:0]; } @@ -4792,7 +4173,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndFloatsUsingBlock: - (void (^)(int32_t key, float value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int32_t key, float value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -4857,7 +4238,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndFloatsUsingBlock:^(int32_t key, float value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); @@ -4905,39 +4286,6 @@ @implementation GPBInt32DoubleDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithDoubles:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithDouble:(double)value - forKey:(int32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithDoubles:forKeys:count: - // on to get the type correct. - return [[(GPBInt32DoubleDictionary*)[self alloc] initWithDoubles:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithDoubles:(const double [])values - forKeys:(const int32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithDoubles:forKeys:count: - // on to get the type correct. - return [[(GPBInt32DoubleDictionary*)[self alloc] initWithDoubles:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt32DoubleDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt32DoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithDoubles:NULL forKeys:NULL count:0]; } @@ -5008,7 +4356,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndDoublesUsingBlock: - (void (^)(int32_t key, double value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int32_t key, double value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -5073,7 +4421,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndDoublesUsingBlock:^(int32_t key, double value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); @@ -5124,54 +4472,6 @@ @implementation GPBInt32EnumDictionary { @synthesize validationFunc = _validationFunc; -+ (instancetype)dictionary { - return [[[self alloc] initWithValidationFunction:NULL - rawValues:NULL - forKeys:NULL - count:0] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func { - return [[[self alloc] initWithValidationFunction:func - rawValues:NULL - forKeys:NULL - count:0] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - rawValue:(int32_t)rawValue - forKey:(int32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBInt32EnumDictionary*)[self alloc] initWithValidationFunction:func - rawValues:&rawValue - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - rawValues:(const int32_t [])rawValues - forKeys:(const int32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBInt32EnumDictionary*)[self alloc] initWithValidationFunction:func - rawValues:rawValues - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt32EnumDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBInt32EnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - capacity:(NSUInteger)numItems { - return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; } @@ -5252,7 +4552,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndRawValuesUsingBlock: - (void (^)(int32_t key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -5329,7 +4629,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndRawValuesUsingBlock:^(int32_t key, int32_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%d", key], @(value)); @@ -5357,7 +4657,7 @@ - (BOOL)getRawValue:(int32_t *)rawValue forKey:(int32_t)key { } - (void)enumerateKeysAndEnumsUsingBlock: - (void (^)(int32_t key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int32_t key, int32_t value, BOOL *stop))block { GPBEnumValidationFunc func = _validationFunc; BOOL stop = NO; NSEnumerator *keys = [_dictionary keyEnumerator]; @@ -5421,39 +4721,6 @@ @implementation GPBInt32ObjectDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithObjects:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithObject:(id)object - forKey:(int32_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count: - // on to get the type correct. - return [[(GPBInt32ObjectDictionary*)[self alloc] initWithObjects:&object - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithObjects:(const id [])objects - forKeys:(const int32_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count: - // on to get the type correct. - return [[(GPBInt32ObjectDictionary*)[self alloc] initWithObjects:objects - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt32ObjectDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt32ObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithObjects:NULL forKeys:NULL count:0]; } @@ -5528,7 +4795,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndObjectsUsingBlock: - (void (^)(int32_t key, id object, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int32_t key, id object, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -5617,7 +4884,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:value->valueString forKey:@(key->valueInt32)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndObjectsUsingBlock:^(int32_t key, id object, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%d", key], object); @@ -5659,8 +4926,10 @@ - (void)removeAll { @end +// clang-format on //%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(UInt64, uint64_t) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - UInt64 -> UInt32 @@ -5669,39 +4938,6 @@ @implementation GPBUInt64UInt32Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithUInt32s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithUInt32:(uint32_t)value - forKey:(uint64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithUInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64UInt32Dictionary*)[self alloc] initWithUInt32s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithUInt32s:(const uint32_t [])values - forKeys:(const uint64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithUInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64UInt32Dictionary*)[self alloc] initWithUInt32s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt64UInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithUInt32s:NULL forKeys:NULL count:0]; } @@ -5772,7 +5008,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndUInt32sUsingBlock: - (void (^)(uint64_t key, uint32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint64_t key, uint32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -5837,7 +5073,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndUInt32sUsingBlock:^(uint64_t key, uint32_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%u", value]); @@ -5885,39 +5121,6 @@ @implementation GPBUInt64Int32Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithInt32s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithInt32:(int32_t)value - forKey:(uint64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64Int32Dictionary*)[self alloc] initWithInt32s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithInt32s:(const int32_t [])values - forKeys:(const uint64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64Int32Dictionary*)[self alloc] initWithInt32s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt64Int32Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt64Int32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithInt32s:NULL forKeys:NULL count:0]; } @@ -5988,7 +5191,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndInt32sUsingBlock: - (void (^)(uint64_t key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -6053,7 +5256,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndInt32sUsingBlock:^(uint64_t key, int32_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%d", value]); @@ -6101,39 +5304,6 @@ @implementation GPBUInt64UInt64Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithUInt64s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithUInt64:(uint64_t)value - forKey:(uint64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithUInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64UInt64Dictionary*)[self alloc] initWithUInt64s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithUInt64s:(const uint64_t [])values - forKeys:(const uint64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithUInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64UInt64Dictionary*)[self alloc] initWithUInt64s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt64UInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithUInt64s:NULL forKeys:NULL count:0]; } @@ -6204,7 +5374,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndUInt64sUsingBlock: - (void (^)(uint64_t key, uint64_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint64_t key, uint64_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -6269,7 +5439,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndUInt64sUsingBlock:^(uint64_t key, uint64_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%llu", value]); @@ -6317,39 +5487,6 @@ @implementation GPBUInt64Int64Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithInt64s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithInt64:(int64_t)value - forKey:(uint64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64Int64Dictionary*)[self alloc] initWithInt64s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithInt64s:(const int64_t [])values - forKeys:(const uint64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64Int64Dictionary*)[self alloc] initWithInt64s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt64Int64Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt64Int64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithInt64s:NULL forKeys:NULL count:0]; } @@ -6420,7 +5557,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndInt64sUsingBlock: - (void (^)(uint64_t key, int64_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint64_t key, int64_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -6485,7 +5622,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndInt64sUsingBlock:^(uint64_t key, int64_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%lld", value]); @@ -6533,39 +5670,6 @@ @implementation GPBUInt64BoolDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithBools:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithBool:(BOOL)value - forKey:(uint64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithBools:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64BoolDictionary*)[self alloc] initWithBools:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithBools:(const BOOL [])values - forKeys:(const uint64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithBools:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64BoolDictionary*)[self alloc] initWithBools:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt64BoolDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt64BoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithBools:NULL forKeys:NULL count:0]; } @@ -6636,7 +5740,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndBoolsUsingBlock: - (void (^)(uint64_t key, BOOL value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint64_t key, BOOL value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -6701,7 +5805,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndBoolsUsingBlock:^(uint64_t key, BOOL value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%llu", key], (value ? @"true" : @"false")); @@ -6749,39 +5853,6 @@ @implementation GPBUInt64FloatDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithFloats:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithFloat:(float)value - forKey:(uint64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithFloats:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64FloatDictionary*)[self alloc] initWithFloats:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithFloats:(const float [])values - forKeys:(const uint64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithFloats:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64FloatDictionary*)[self alloc] initWithFloats:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt64FloatDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt64FloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithFloats:NULL forKeys:NULL count:0]; } @@ -6852,7 +5923,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndFloatsUsingBlock: - (void (^)(uint64_t key, float value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint64_t key, float value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -6917,7 +5988,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndFloatsUsingBlock:^(uint64_t key, float value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); @@ -6965,39 +6036,6 @@ @implementation GPBUInt64DoubleDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithDoubles:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithDouble:(double)value - forKey:(uint64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithDoubles:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64DoubleDictionary*)[self alloc] initWithDoubles:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithDoubles:(const double [])values - forKeys:(const uint64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithDoubles:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64DoubleDictionary*)[self alloc] initWithDoubles:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt64DoubleDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt64DoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithDoubles:NULL forKeys:NULL count:0]; } @@ -7068,7 +6106,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndDoublesUsingBlock: - (void (^)(uint64_t key, double value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint64_t key, double value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -7133,7 +6171,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndDoublesUsingBlock:^(uint64_t key, double value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); @@ -7184,54 +6222,6 @@ @implementation GPBUInt64EnumDictionary { @synthesize validationFunc = _validationFunc; -+ (instancetype)dictionary { - return [[[self alloc] initWithValidationFunction:NULL - rawValues:NULL - forKeys:NULL - count:0] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func { - return [[[self alloc] initWithValidationFunction:func - rawValues:NULL - forKeys:NULL - count:0] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - rawValue:(int32_t)rawValue - forKey:(uint64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64EnumDictionary*)[self alloc] initWithValidationFunction:func - rawValues:&rawValue - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - rawValues:(const int32_t [])rawValues - forKeys:(const uint64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64EnumDictionary*)[self alloc] initWithValidationFunction:func - rawValues:rawValues - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt64EnumDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64EnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - capacity:(NSUInteger)numItems { - return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; } @@ -7312,7 +6302,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndRawValuesUsingBlock: - (void (^)(uint64_t key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -7389,7 +6379,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndRawValuesUsingBlock:^(uint64_t key, int32_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%llu", key], @(value)); @@ -7417,7 +6407,7 @@ - (BOOL)getRawValue:(int32_t *)rawValue forKey:(uint64_t)key { } - (void)enumerateKeysAndEnumsUsingBlock: - (void (^)(uint64_t key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint64_t key, int32_t value, BOOL *stop))block { GPBEnumValidationFunc func = _validationFunc; BOOL stop = NO; NSEnumerator *keys = [_dictionary keyEnumerator]; @@ -7481,39 +6471,6 @@ @implementation GPBUInt64ObjectDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithObjects:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithObject:(id)object - forKey:(uint64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64ObjectDictionary*)[self alloc] initWithObjects:&object - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithObjects:(const id [])objects - forKeys:(const uint64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count: - // on to get the type correct. - return [[(GPBUInt64ObjectDictionary*)[self alloc] initWithObjects:objects - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBUInt64ObjectDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBUInt64ObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithObjects:NULL forKeys:NULL count:0]; } @@ -7588,7 +6545,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndObjectsUsingBlock: - (void (^)(uint64_t key, id object, BOOL *stop))block { + (void (NS_NOESCAPE ^)(uint64_t key, id object, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -7677,7 +6634,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:value->valueString forKey:@(key->valueUInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndObjectsUsingBlock:^(uint64_t key, id object, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%llu", key], object); @@ -7719,8 +6676,10 @@ - (void)removeAll { @end +// clang-format on //%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(Int64, int64_t) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Int64 -> UInt32 @@ -7729,39 +6688,6 @@ @implementation GPBInt64UInt32Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithUInt32s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithUInt32:(uint32_t)value - forKey:(int64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithUInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBInt64UInt32Dictionary*)[self alloc] initWithUInt32s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithUInt32s:(const uint32_t [])values - forKeys:(const int64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithUInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBInt64UInt32Dictionary*)[self alloc] initWithUInt32s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt64UInt32Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt64UInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithUInt32s:NULL forKeys:NULL count:0]; } @@ -7832,7 +6758,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndUInt32sUsingBlock: - (void (^)(int64_t key, uint32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int64_t key, uint32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -7897,7 +6823,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndUInt32sUsingBlock:^(int64_t key, uint32_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%u", value]); @@ -7945,39 +6871,6 @@ @implementation GPBInt64Int32Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithInt32s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithInt32:(int32_t)value - forKey:(int64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBInt64Int32Dictionary*)[self alloc] initWithInt32s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithInt32s:(const int32_t [])values - forKeys:(const int64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBInt64Int32Dictionary*)[self alloc] initWithInt32s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt64Int32Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt64Int32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithInt32s:NULL forKeys:NULL count:0]; } @@ -8048,7 +6941,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndInt32sUsingBlock: - (void (^)(int64_t key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -8113,7 +7006,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndInt32sUsingBlock:^(int64_t key, int32_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%d", value]); @@ -8161,39 +7054,6 @@ @implementation GPBInt64UInt64Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithUInt64s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithUInt64:(uint64_t)value - forKey:(int64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithUInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBInt64UInt64Dictionary*)[self alloc] initWithUInt64s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithUInt64s:(const uint64_t [])values - forKeys:(const int64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithUInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBInt64UInt64Dictionary*)[self alloc] initWithUInt64s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt64UInt64Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt64UInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithUInt64s:NULL forKeys:NULL count:0]; } @@ -8264,7 +7124,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndUInt64sUsingBlock: - (void (^)(int64_t key, uint64_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int64_t key, uint64_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -8329,7 +7189,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndUInt64sUsingBlock:^(int64_t key, uint64_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%llu", value]); @@ -8377,39 +7237,6 @@ @implementation GPBInt64Int64Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithInt64s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithInt64:(int64_t)value - forKey:(int64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBInt64Int64Dictionary*)[self alloc] initWithInt64s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithInt64s:(const int64_t [])values - forKeys:(const int64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBInt64Int64Dictionary*)[self alloc] initWithInt64s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt64Int64Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt64Int64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithInt64s:NULL forKeys:NULL count:0]; } @@ -8480,7 +7307,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndInt64sUsingBlock: - (void (^)(int64_t key, int64_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int64_t key, int64_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -8545,7 +7372,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndInt64sUsingBlock:^(int64_t key, int64_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%lld", value]); @@ -8593,39 +7420,6 @@ @implementation GPBInt64BoolDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithBools:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithBool:(BOOL)value - forKey:(int64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithBools:forKeys:count: - // on to get the type correct. - return [[(GPBInt64BoolDictionary*)[self alloc] initWithBools:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithBools:(const BOOL [])values - forKeys:(const int64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithBools:forKeys:count: - // on to get the type correct. - return [[(GPBInt64BoolDictionary*)[self alloc] initWithBools:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt64BoolDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt64BoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithBools:NULL forKeys:NULL count:0]; } @@ -8696,7 +7490,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndBoolsUsingBlock: - (void (^)(int64_t key, BOOL value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int64_t key, BOOL value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -8761,7 +7555,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndBoolsUsingBlock:^(int64_t key, BOOL value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%lld", key], (value ? @"true" : @"false")); @@ -8809,39 +7603,6 @@ @implementation GPBInt64FloatDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithFloats:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithFloat:(float)value - forKey:(int64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithFloats:forKeys:count: - // on to get the type correct. - return [[(GPBInt64FloatDictionary*)[self alloc] initWithFloats:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithFloats:(const float [])values - forKeys:(const int64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithFloats:forKeys:count: - // on to get the type correct. - return [[(GPBInt64FloatDictionary*)[self alloc] initWithFloats:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt64FloatDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt64FloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithFloats:NULL forKeys:NULL count:0]; } @@ -8912,7 +7673,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndFloatsUsingBlock: - (void (^)(int64_t key, float value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int64_t key, float value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -8977,7 +7738,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndFloatsUsingBlock:^(int64_t key, float value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); @@ -9025,39 +7786,6 @@ @implementation GPBInt64DoubleDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithDoubles:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithDouble:(double)value - forKey:(int64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithDoubles:forKeys:count: - // on to get the type correct. - return [[(GPBInt64DoubleDictionary*)[self alloc] initWithDoubles:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithDoubles:(const double [])values - forKeys:(const int64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithDoubles:forKeys:count: - // on to get the type correct. - return [[(GPBInt64DoubleDictionary*)[self alloc] initWithDoubles:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt64DoubleDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt64DoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithDoubles:NULL forKeys:NULL count:0]; } @@ -9128,7 +7856,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndDoublesUsingBlock: - (void (^)(int64_t key, double value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int64_t key, double value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -9193,7 +7921,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndDoublesUsingBlock:^(int64_t key, double value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); @@ -9244,54 +7972,6 @@ @implementation GPBInt64EnumDictionary { @synthesize validationFunc = _validationFunc; -+ (instancetype)dictionary { - return [[[self alloc] initWithValidationFunction:NULL - rawValues:NULL - forKeys:NULL - count:0] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func { - return [[[self alloc] initWithValidationFunction:func - rawValues:NULL - forKeys:NULL - count:0] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - rawValue:(int32_t)rawValue - forKey:(int64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBInt64EnumDictionary*)[self alloc] initWithValidationFunction:func - rawValues:&rawValue - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - rawValues:(const int32_t [])rawValues - forKeys:(const int64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBInt64EnumDictionary*)[self alloc] initWithValidationFunction:func - rawValues:rawValues - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt64EnumDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBInt64EnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - capacity:(NSUInteger)numItems { - return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; } @@ -9372,7 +8052,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndRawValuesUsingBlock: - (void (^)(int64_t key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -9449,7 +8129,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndRawValuesUsingBlock:^(int64_t key, int32_t value, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%lld", key], @(value)); @@ -9477,7 +8157,7 @@ - (BOOL)getRawValue:(int32_t *)rawValue forKey:(int64_t)key { } - (void)enumerateKeysAndEnumsUsingBlock: - (void (^)(int64_t key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int64_t key, int32_t value, BOOL *stop))block { GPBEnumValidationFunc func = _validationFunc; BOOL stop = NO; NSEnumerator *keys = [_dictionary keyEnumerator]; @@ -9541,39 +8221,6 @@ @implementation GPBInt64ObjectDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithObjects:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithObject:(id)object - forKey:(int64_t)key { - // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count: - // on to get the type correct. - return [[(GPBInt64ObjectDictionary*)[self alloc] initWithObjects:&object - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithObjects:(const id [])objects - forKeys:(const int64_t [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count: - // on to get the type correct. - return [[(GPBInt64ObjectDictionary*)[self alloc] initWithObjects:objects - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBInt64ObjectDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBInt64ObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithObjects:NULL forKeys:NULL count:0]; } @@ -9648,7 +8295,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndObjectsUsingBlock: - (void (^)(int64_t key, id object, BOOL *stop))block { + (void (NS_NOESCAPE ^)(int64_t key, id object, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -9737,7 +8384,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:value->valueString forKey:@(key->valueInt64)]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndObjectsUsingBlock:^(int64_t key, id object, BOOL *stop) { #pragma unused(stop) block([NSString stringWithFormat:@"%lld", key], object); @@ -9779,8 +8426,10 @@ - (void)removeAll { @end +// clang-format on //%PDDM-EXPAND DICTIONARY_POD_IMPL_FOR_KEY(String, NSString, *, OBJECT) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - String -> UInt32 @@ -9789,39 +8438,6 @@ @implementation GPBStringUInt32Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithUInt32s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithUInt32:(uint32_t)value - forKey:(NSString *)key { - // Cast is needed so the compiler knows what class we are invoking initWithUInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBStringUInt32Dictionary*)[self alloc] initWithUInt32s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithUInt32s:(const uint32_t [])values - forKeys:(const NSString * [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithUInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBStringUInt32Dictionary*)[self alloc] initWithUInt32s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBStringUInt32Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBStringUInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithUInt32s:NULL forKeys:NULL count:0]; } @@ -9896,7 +8512,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndUInt32sUsingBlock: - (void (^)(NSString *key, uint32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(NSString *key, uint32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -9961,7 +8577,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueUInt32) forKey:key->valueString]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndUInt32sUsingBlock:^(NSString *key, uint32_t value, BOOL *stop) { #pragma unused(stop) block(key, [NSString stringWithFormat:@"%u", value]); @@ -10013,39 +8629,6 @@ @implementation GPBStringInt32Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithInt32s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithInt32:(int32_t)value - forKey:(NSString *)key { - // Cast is needed so the compiler knows what class we are invoking initWithInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBStringInt32Dictionary*)[self alloc] initWithInt32s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithInt32s:(const int32_t [])values - forKeys:(const NSString * [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBStringInt32Dictionary*)[self alloc] initWithInt32s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBStringInt32Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBStringInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithInt32s:NULL forKeys:NULL count:0]; } @@ -10120,7 +8703,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndInt32sUsingBlock: - (void (^)(NSString *key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -10185,7 +8768,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueInt32) forKey:key->valueString]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndInt32sUsingBlock:^(NSString *key, int32_t value, BOOL *stop) { #pragma unused(stop) block(key, [NSString stringWithFormat:@"%d", value]); @@ -10237,39 +8820,6 @@ @implementation GPBStringUInt64Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithUInt64s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithUInt64:(uint64_t)value - forKey:(NSString *)key { - // Cast is needed so the compiler knows what class we are invoking initWithUInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBStringUInt64Dictionary*)[self alloc] initWithUInt64s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithUInt64s:(const uint64_t [])values - forKeys:(const NSString * [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithUInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBStringUInt64Dictionary*)[self alloc] initWithUInt64s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBStringUInt64Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBStringUInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithUInt64s:NULL forKeys:NULL count:0]; } @@ -10344,7 +8894,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndUInt64sUsingBlock: - (void (^)(NSString *key, uint64_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(NSString *key, uint64_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -10409,7 +8959,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueUInt64) forKey:key->valueString]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndUInt64sUsingBlock:^(NSString *key, uint64_t value, BOOL *stop) { #pragma unused(stop) block(key, [NSString stringWithFormat:@"%llu", value]); @@ -10461,39 +9011,6 @@ @implementation GPBStringInt64Dictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithInt64s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithInt64:(int64_t)value - forKey:(NSString *)key { - // Cast is needed so the compiler knows what class we are invoking initWithInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBStringInt64Dictionary*)[self alloc] initWithInt64s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithInt64s:(const int64_t [])values - forKeys:(const NSString * [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBStringInt64Dictionary*)[self alloc] initWithInt64s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBStringInt64Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBStringInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithInt64s:NULL forKeys:NULL count:0]; } @@ -10568,7 +9085,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndInt64sUsingBlock: - (void (^)(NSString *key, int64_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(NSString *key, int64_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -10633,7 +9150,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueInt64) forKey:key->valueString]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndInt64sUsingBlock:^(NSString *key, int64_t value, BOOL *stop) { #pragma unused(stop) block(key, [NSString stringWithFormat:@"%lld", value]); @@ -10685,39 +9202,6 @@ @implementation GPBStringBoolDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithBools:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithBool:(BOOL)value - forKey:(NSString *)key { - // Cast is needed so the compiler knows what class we are invoking initWithBools:forKeys:count: - // on to get the type correct. - return [[(GPBStringBoolDictionary*)[self alloc] initWithBools:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithBools:(const BOOL [])values - forKeys:(const NSString * [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithBools:forKeys:count: - // on to get the type correct. - return [[(GPBStringBoolDictionary*)[self alloc] initWithBools:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBStringBoolDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBStringBoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithBools:NULL forKeys:NULL count:0]; } @@ -10792,7 +9276,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndBoolsUsingBlock: - (void (^)(NSString *key, BOOL value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(NSString *key, BOOL value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -10857,7 +9341,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueBool) forKey:key->valueString]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndBoolsUsingBlock:^(NSString *key, BOOL value, BOOL *stop) { #pragma unused(stop) block(key, (value ? @"true" : @"false")); @@ -10909,39 +9393,6 @@ @implementation GPBStringFloatDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithFloats:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithFloat:(float)value - forKey:(NSString *)key { - // Cast is needed so the compiler knows what class we are invoking initWithFloats:forKeys:count: - // on to get the type correct. - return [[(GPBStringFloatDictionary*)[self alloc] initWithFloats:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithFloats:(const float [])values - forKeys:(const NSString * [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithFloats:forKeys:count: - // on to get the type correct. - return [[(GPBStringFloatDictionary*)[self alloc] initWithFloats:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBStringFloatDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBStringFloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithFloats:NULL forKeys:NULL count:0]; } @@ -11016,7 +9467,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndFloatsUsingBlock: - (void (^)(NSString *key, float value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(NSString *key, float value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -11081,7 +9532,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueFloat) forKey:key->valueString]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndFloatsUsingBlock:^(NSString *key, float value, BOOL *stop) { #pragma unused(stop) block(key, [NSString stringWithFormat:@"%.*g", FLT_DIG, value]); @@ -11133,39 +9584,6 @@ @implementation GPBStringDoubleDictionary { NSMutableDictionary *_dictionary; } -+ (instancetype)dictionary { - return [[[self alloc] initWithDoubles:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithDouble:(double)value - forKey:(NSString *)key { - // Cast is needed so the compiler knows what class we are invoking initWithDoubles:forKeys:count: - // on to get the type correct. - return [[(GPBStringDoubleDictionary*)[self alloc] initWithDoubles:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithDoubles:(const double [])values - forKeys:(const NSString * [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithDoubles:forKeys:count: - // on to get the type correct. - return [[(GPBStringDoubleDictionary*)[self alloc] initWithDoubles:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBStringDoubleDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBStringDoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithDoubles:NULL forKeys:NULL count:0]; } @@ -11240,7 +9658,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndDoublesUsingBlock: - (void (^)(NSString *key, double value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(NSString *key, double value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -11305,7 +9723,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueDouble) forKey:key->valueString]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndDoublesUsingBlock:^(NSString *key, double value, BOOL *stop) { #pragma unused(stop) block(key, [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]); @@ -11360,54 +9778,6 @@ @implementation GPBStringEnumDictionary { @synthesize validationFunc = _validationFunc; -+ (instancetype)dictionary { - return [[[self alloc] initWithValidationFunction:NULL - rawValues:NULL - forKeys:NULL - count:0] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func { - return [[[self alloc] initWithValidationFunction:func - rawValues:NULL - forKeys:NULL - count:0] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - rawValue:(int32_t)rawValue - forKey:(NSString *)key { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBStringEnumDictionary*)[self alloc] initWithValidationFunction:func - rawValues:&rawValue - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - rawValues:(const int32_t [])rawValues - forKeys:(const NSString * [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBStringEnumDictionary*)[self alloc] initWithValidationFunction:func - rawValues:rawValues - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBStringEnumDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBStringEnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - capacity:(NSUInteger)numItems { - return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; } @@ -11492,7 +9862,7 @@ - (NSUInteger)count { } - (void)enumerateKeysAndRawValuesUsingBlock: - (void (^)(NSString *key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block { BOOL stop = NO; NSDictionary *internal = _dictionary; NSEnumerator *keys = [internal keyEnumerator]; @@ -11569,7 +9939,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value [_dictionary setObject:@(value->valueEnum) forKey:key->valueString]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { [self enumerateKeysAndRawValuesUsingBlock:^(NSString *key, int32_t value, BOOL *stop) { #pragma unused(stop) block(key, @(value)); @@ -11597,7 +9967,7 @@ - (BOOL)getRawValue:(int32_t *)rawValue forKey:(NSString *)key { } - (void)enumerateKeysAndEnumsUsingBlock: - (void (^)(NSString *key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(NSString *key, int32_t value, BOOL *stop))block { GPBEnumValidationFunc func = _validationFunc; BOOL stop = NO; NSEnumerator *keys = [_dictionary keyEnumerator]; @@ -11662,11 +10032,13 @@ - (void)setEnum:(int32_t)value forKey:(NSString *)key { @end +// clang-format on //%PDDM-EXPAND-END (5 expansions) //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(UInt32, uint32_t) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> UInt32 @@ -11676,39 +10048,6 @@ @implementation GPBBoolUInt32Dictionary { BOOL _valueSet[2]; } -+ (instancetype)dictionary { - return [[[self alloc] initWithUInt32s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithUInt32:(uint32_t)value - forKey:(BOOL)key { - // Cast is needed so the compiler knows what class we are invoking initWithUInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBBoolUInt32Dictionary*)[self alloc] initWithUInt32s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithUInt32s:(const uint32_t [])values - forKeys:(const BOOL [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithUInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBBoolUInt32Dictionary*)[self alloc] initWithUInt32s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBBoolUInt32Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBBoolUInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithUInt32s:NULL forKeys:NULL count:0]; } @@ -11817,7 +10156,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value _valueSet[idx] = YES; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { if (_valueSet[0]) { block(@"false", [NSString stringWithFormat:@"%u", _values[0]]); } @@ -11827,7 +10166,7 @@ - (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { } - (void)enumerateKeysAndUInt32sUsingBlock: - (void (^)(BOOL key, uint32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(BOOL key, uint32_t value, BOOL *stop))block { BOOL stop = NO; if (_valueSet[0]) { block(NO, _values[0], &stop); @@ -11907,8 +10246,10 @@ - (void)removeAll { @end +// clang-format on //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Int32, int32_t) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> Int32 @@ -11918,39 +10259,6 @@ @implementation GPBBoolInt32Dictionary { BOOL _valueSet[2]; } -+ (instancetype)dictionary { - return [[[self alloc] initWithInt32s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithInt32:(int32_t)value - forKey:(BOOL)key { - // Cast is needed so the compiler knows what class we are invoking initWithInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBBoolInt32Dictionary*)[self alloc] initWithInt32s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithInt32s:(const int32_t [])values - forKeys:(const BOOL [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithInt32s:forKeys:count: - // on to get the type correct. - return [[(GPBBoolInt32Dictionary*)[self alloc] initWithInt32s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBBoolInt32Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBBoolInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithInt32s:NULL forKeys:NULL count:0]; } @@ -12059,7 +10367,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value _valueSet[idx] = YES; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { if (_valueSet[0]) { block(@"false", [NSString stringWithFormat:@"%d", _values[0]]); } @@ -12069,7 +10377,7 @@ - (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { } - (void)enumerateKeysAndInt32sUsingBlock: - (void (^)(BOOL key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(BOOL key, int32_t value, BOOL *stop))block { BOOL stop = NO; if (_valueSet[0]) { block(NO, _values[0], &stop); @@ -12149,8 +10457,10 @@ - (void)removeAll { @end +// clang-format on //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(UInt64, uint64_t) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> UInt64 @@ -12160,39 +10470,6 @@ @implementation GPBBoolUInt64Dictionary { BOOL _valueSet[2]; } -+ (instancetype)dictionary { - return [[[self alloc] initWithUInt64s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithUInt64:(uint64_t)value - forKey:(BOOL)key { - // Cast is needed so the compiler knows what class we are invoking initWithUInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBBoolUInt64Dictionary*)[self alloc] initWithUInt64s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithUInt64s:(const uint64_t [])values - forKeys:(const BOOL [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithUInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBBoolUInt64Dictionary*)[self alloc] initWithUInt64s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBBoolUInt64Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBBoolUInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithUInt64s:NULL forKeys:NULL count:0]; } @@ -12301,7 +10578,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value _valueSet[idx] = YES; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { if (_valueSet[0]) { block(@"false", [NSString stringWithFormat:@"%llu", _values[0]]); } @@ -12311,7 +10588,7 @@ - (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { } - (void)enumerateKeysAndUInt64sUsingBlock: - (void (^)(BOOL key, uint64_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(BOOL key, uint64_t value, BOOL *stop))block { BOOL stop = NO; if (_valueSet[0]) { block(NO, _values[0], &stop); @@ -12391,8 +10668,10 @@ - (void)removeAll { @end +// clang-format on //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Int64, int64_t) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> Int64 @@ -12402,39 +10681,6 @@ @implementation GPBBoolInt64Dictionary { BOOL _valueSet[2]; } -+ (instancetype)dictionary { - return [[[self alloc] initWithInt64s:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithInt64:(int64_t)value - forKey:(BOOL)key { - // Cast is needed so the compiler knows what class we are invoking initWithInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBBoolInt64Dictionary*)[self alloc] initWithInt64s:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithInt64s:(const int64_t [])values - forKeys:(const BOOL [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithInt64s:forKeys:count: - // on to get the type correct. - return [[(GPBBoolInt64Dictionary*)[self alloc] initWithInt64s:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBBoolInt64Dictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBBoolInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithInt64s:NULL forKeys:NULL count:0]; } @@ -12543,7 +10789,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value _valueSet[idx] = YES; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { if (_valueSet[0]) { block(@"false", [NSString stringWithFormat:@"%lld", _values[0]]); } @@ -12553,7 +10799,7 @@ - (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { } - (void)enumerateKeysAndInt64sUsingBlock: - (void (^)(BOOL key, int64_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(BOOL key, int64_t value, BOOL *stop))block { BOOL stop = NO; if (_valueSet[0]) { block(NO, _values[0], &stop); @@ -12633,8 +10879,10 @@ - (void)removeAll { @end +// clang-format on //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Bool, BOOL) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> Bool @@ -12644,39 +10892,6 @@ @implementation GPBBoolBoolDictionary { BOOL _valueSet[2]; } -+ (instancetype)dictionary { - return [[[self alloc] initWithBools:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithBool:(BOOL)value - forKey:(BOOL)key { - // Cast is needed so the compiler knows what class we are invoking initWithBools:forKeys:count: - // on to get the type correct. - return [[(GPBBoolBoolDictionary*)[self alloc] initWithBools:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithBools:(const BOOL [])values - forKeys:(const BOOL [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithBools:forKeys:count: - // on to get the type correct. - return [[(GPBBoolBoolDictionary*)[self alloc] initWithBools:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBBoolBoolDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBBoolBoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithBools:NULL forKeys:NULL count:0]; } @@ -12785,7 +11000,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value _valueSet[idx] = YES; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { if (_valueSet[0]) { block(@"false", (_values[0] ? @"true" : @"false")); } @@ -12795,7 +11010,7 @@ - (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { } - (void)enumerateKeysAndBoolsUsingBlock: - (void (^)(BOOL key, BOOL value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(BOOL key, BOOL value, BOOL *stop))block { BOOL stop = NO; if (_valueSet[0]) { block(NO, _values[0], &stop); @@ -12875,8 +11090,10 @@ - (void)removeAll { @end +// clang-format on //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Float, float) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> Float @@ -12886,39 +11103,6 @@ @implementation GPBBoolFloatDictionary { BOOL _valueSet[2]; } -+ (instancetype)dictionary { - return [[[self alloc] initWithFloats:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithFloat:(float)value - forKey:(BOOL)key { - // Cast is needed so the compiler knows what class we are invoking initWithFloats:forKeys:count: - // on to get the type correct. - return [[(GPBBoolFloatDictionary*)[self alloc] initWithFloats:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithFloats:(const float [])values - forKeys:(const BOOL [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithFloats:forKeys:count: - // on to get the type correct. - return [[(GPBBoolFloatDictionary*)[self alloc] initWithFloats:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBBoolFloatDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBBoolFloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithFloats:NULL forKeys:NULL count:0]; } @@ -13027,7 +11211,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value _valueSet[idx] = YES; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { if (_valueSet[0]) { block(@"false", [NSString stringWithFormat:@"%.*g", FLT_DIG, _values[0]]); } @@ -13037,7 +11221,7 @@ - (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { } - (void)enumerateKeysAndFloatsUsingBlock: - (void (^)(BOOL key, float value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(BOOL key, float value, BOOL *stop))block { BOOL stop = NO; if (_valueSet[0]) { block(NO, _values[0], &stop); @@ -13117,8 +11301,10 @@ - (void)removeAll { @end +// clang-format on //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Double, double) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> Double @@ -13128,39 +11314,6 @@ @implementation GPBBoolDoubleDictionary { BOOL _valueSet[2]; } -+ (instancetype)dictionary { - return [[[self alloc] initWithDoubles:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithDouble:(double)value - forKey:(BOOL)key { - // Cast is needed so the compiler knows what class we are invoking initWithDoubles:forKeys:count: - // on to get the type correct. - return [[(GPBBoolDoubleDictionary*)[self alloc] initWithDoubles:&value - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithDoubles:(const double [])values - forKeys:(const BOOL [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithDoubles:forKeys:count: - // on to get the type correct. - return [[(GPBBoolDoubleDictionary*)[self alloc] initWithDoubles:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBBoolDoubleDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBBoolDoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithDoubles:NULL forKeys:NULL count:0]; } @@ -13269,7 +11422,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value _valueSet[idx] = YES; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { if (_valueSet[0]) { block(@"false", [NSString stringWithFormat:@"%.*lg", DBL_DIG, _values[0]]); } @@ -13279,7 +11432,7 @@ - (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { } - (void)enumerateKeysAndDoublesUsingBlock: - (void (^)(BOOL key, double value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(BOOL key, double value, BOOL *stop))block { BOOL stop = NO; if (_valueSet[0]) { block(NO, _values[0], &stop); @@ -13359,8 +11512,10 @@ - (void)removeAll { @end +// clang-format on //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_OBJECT_IMPL(Object, id) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> Object @@ -13369,39 +11524,6 @@ @implementation GPBBoolObjectDictionary { id _values[2]; } -+ (instancetype)dictionary { - return [[[self alloc] initWithObjects:NULL forKeys:NULL count:0] autorelease]; -} - -+ (instancetype)dictionaryWithObject:(id)object - forKey:(BOOL)key { - // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count: - // on to get the type correct. - return [[(GPBBoolObjectDictionary*)[self alloc] initWithObjects:&object - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithObjects:(const id [])objects - forKeys:(const BOOL [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithObjects:forKeys:count: - // on to get the type correct. - return [[(GPBBoolObjectDictionary*)[self alloc] initWithObjects:objects - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBBoolObjectDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithDictionary: - // on to get the type correct. - return [[(GPBBoolObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems { - return [[[self alloc] initWithCapacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithObjects:NULL forKeys:NULL count:0]; } @@ -13503,7 +11625,7 @@ - (void)setGPBGenericValue:(GPBGenericValue *)value _values[idx] = [value->valueString retain]; } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { if (_values[0] != nil) { block(@"false", _values[0]); } @@ -13513,7 +11635,7 @@ - (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { } - (void)enumerateKeysAndObjectsUsingBlock: - (void (^)(BOOL key, id object, BOOL *stop))block { + (void (NS_NOESCAPE ^)(BOOL key, id object, BOOL *stop))block { BOOL stop = NO; if (_values[0] != nil) { block(NO, _values[0], &stop); @@ -13622,6 +11744,7 @@ - (void)removeAll { @end +// clang-format on //%PDDM-EXPAND-END (8 expansions) #pragma mark - Bool -> Enum @@ -13635,54 +11758,6 @@ @implementation GPBBoolEnumDictionary { @synthesize validationFunc = _validationFunc; -+ (instancetype)dictionary { - return [[[self alloc] initWithValidationFunction:NULL - rawValues:NULL - forKeys:NULL - count:0] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func { - return [[[self alloc] initWithValidationFunction:func - rawValues:NULL - forKeys:NULL - count:0] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - rawValue:(int32_t)rawValue - forKey:(BOOL)key { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBBoolEnumDictionary*)[self alloc] initWithValidationFunction:func - rawValues:&rawValue - forKeys:&key - count:1] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - rawValues:(const int32_t [])values - forKeys:(const BOOL [])keys - count:(NSUInteger)count { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBBoolEnumDictionary*)[self alloc] initWithValidationFunction:func - rawValues:values - forKeys:keys - count:count] autorelease]; -} - -+ (instancetype)dictionaryWithDictionary:(GPBBoolEnumDictionary *)dictionary { - // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count: - // on to get the type correct. - return [[(GPBBoolEnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease]; -} - -+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func - capacity:(NSUInteger)numItems { - return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease]; -} - - (instancetype)init { return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0]; } @@ -13810,7 +11885,7 @@ - (BOOL)getRawValue:(int32_t*)rawValue forKey:(BOOL)key { } - (void)enumerateKeysAndRawValuesUsingBlock: - (void (^)(BOOL key, int32_t value, BOOL *stop))block { + (void (NS_NOESCAPE ^)(BOOL key, int32_t value, BOOL *stop))block { BOOL stop = NO; if (_valueSet[0]) { block(NO, _values[0], &stop); @@ -13821,7 +11896,7 @@ - (void)enumerateKeysAndRawValuesUsingBlock: } - (void)enumerateKeysAndEnumsUsingBlock: - (void (^)(BOOL key, int32_t rawValue, BOOL *stop))block { + (void (NS_NOESCAPE ^)(BOOL key, int32_t rawValue, BOOL *stop))block { BOOL stop = NO; GPBEnumValidationFunc func = _validationFunc; int32_t validatedValue; @@ -13843,6 +11918,7 @@ - (void)enumerateKeysAndEnumsUsingBlock: //%PDDM-EXPAND SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool) // This block of code is generated, do not edit it directly. +// clang-format off - (NSData *)serializedDataForUnknownValue:(int32_t)value forKey:(GPBGenericValue *)key @@ -13857,6 +11933,7 @@ - (NSData *)serializedDataForUnknownValue:(int32_t)value return data; } +// clang-format on //%PDDM-EXPAND-END SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool) - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { @@ -13895,7 +11972,7 @@ - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream } } -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block { +- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block { if (_valueSet[0]) { block(@"false", @(_values[0])); } @@ -14055,14 +12132,14 @@ - (void)setObject:(id)obj forKeyedSubscript:(id)key { } } -- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, +- (void)enumerateKeysAndObjectsUsingBlock:(void (NS_NOESCAPE ^)(id key, id obj, BOOL *stop))block { [_dictionary enumerateKeysAndObjectsUsingBlock:block]; } - (void)enumerateKeysAndObjectsWithOptions:(NSEnumerationOptions)opts - usingBlock:(void (^)(id key, + usingBlock:(void (NS_NOESCAPE ^)(id key, id obj, BOOL *stop))block { [_dictionary enumerateKeysAndObjectsWithOptions:opts usingBlock:block]; diff --git a/objectivec/GPBDictionary_PackagePrivate.h b/objectivec/GPBDictionary_PackagePrivate.h index 7b921e8ec7088..15e4283264152 100644 --- a/objectivec/GPBDictionary_PackagePrivate.h +++ b/objectivec/GPBDictionary_PackagePrivate.h @@ -82,6 +82,7 @@ //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt32) // This block of code is generated, do not edit it directly. +// clang-format off @interface GPBUInt32UInt32Dictionary () { @package @@ -143,8 +144,10 @@ __attribute__((ns_returns_retained)); @end +// clang-format on //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Int32) // This block of code is generated, do not edit it directly. +// clang-format off @interface GPBInt32UInt32Dictionary () { @package @@ -206,8 +209,10 @@ __attribute__((ns_returns_retained)); @end +// clang-format on //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt64) // This block of code is generated, do not edit it directly. +// clang-format off @interface GPBUInt64UInt32Dictionary () { @package @@ -269,8 +274,10 @@ __attribute__((ns_returns_retained)); @end +// clang-format on //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Int64) // This block of code is generated, do not edit it directly. +// clang-format off @interface GPBInt64UInt32Dictionary () { @package @@ -332,8 +339,10 @@ __attribute__((ns_returns_retained)); @end +// clang-format on //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Bool) // This block of code is generated, do not edit it directly. +// clang-format off @interface GPBBoolUInt32Dictionary () { @package @@ -395,8 +404,10 @@ __attribute__((ns_returns_retained)); @end +// clang-format on //%PDDM-EXPAND DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(String) // This block of code is generated, do not edit it directly. +// clang-format off @interface GPBStringUInt32Dictionary () { @package @@ -449,6 +460,7 @@ keyDataType:(GPBDataType)keyDataType; @end +// clang-format on //%PDDM-EXPAND-END (6 expansions) #pragma mark - NSDictionary Subclass diff --git a/objectivec/GPBDuration.pbobjc.h b/objectivec/GPBDuration.pbobjc.h new file mode 100644 index 0000000000000..88527f520d3c3 --- /dev/null +++ b/objectivec/GPBDuration.pbobjc.h @@ -0,0 +1,145 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/duration.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBDurationRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +GPB_FINAL @interface GPBDurationRoot : GPBRootObject +@end + +#pragma mark - GPBDuration + +typedef GPB_ENUM(GPBDuration_FieldNumber) { + GPBDuration_FieldNumber_Seconds = 1, + GPBDuration_FieldNumber_Nanos = 2, +}; + +/** + * A Duration represents a signed, fixed-length span of time represented + * as a count of seconds and fractions of seconds at nanosecond + * resolution. It is independent of any calendar and concepts like "day" + * or "month". It is related to Timestamp in that the difference between + * two Timestamp values is a Duration and it can be added or subtracted + * from a Timestamp. Range is approximately +-10,000 years. + * + * # Examples + * + * Example 1: Compute Duration from two Timestamps in pseudo code. + * + * Timestamp start = ...; + * Timestamp end = ...; + * Duration duration = ...; + * + * duration.seconds = end.seconds - start.seconds; + * duration.nanos = end.nanos - start.nanos; + * + * if (duration.seconds < 0 && duration.nanos > 0) { + * duration.seconds += 1; + * duration.nanos -= 1000000000; + * } else if (duration.seconds > 0 && duration.nanos < 0) { + * duration.seconds -= 1; + * duration.nanos += 1000000000; + * } + * + * Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. + * + * Timestamp start = ...; + * Duration duration = ...; + * Timestamp end = ...; + * + * end.seconds = start.seconds + duration.seconds; + * end.nanos = start.nanos + duration.nanos; + * + * if (end.nanos < 0) { + * end.seconds -= 1; + * end.nanos += 1000000000; + * } else if (end.nanos >= 1000000000) { + * end.seconds += 1; + * end.nanos -= 1000000000; + * } + * + * Example 3: Compute Duration from datetime.timedelta in Python. + * + * td = datetime.timedelta(days=3, minutes=10) + * duration = Duration() + * duration.FromTimedelta(td) + * + * # JSON Mapping + * + * In JSON format, the Duration type is encoded as a string rather than an + * object, where the string ends in the suffix "s" (indicating seconds) and + * is preceded by the number of seconds, with nanoseconds expressed as + * fractional seconds. For example, 3 seconds with 0 nanoseconds should be + * encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should + * be expressed in JSON format as "3.000000001s", and 3 seconds and 1 + * microsecond should be expressed in JSON format as "3.000001s". + **/ +GPB_FINAL @interface GPBDuration : GPBMessage + +/** + * Signed seconds of the span of time. Must be from -315,576,000,000 + * to +315,576,000,000 inclusive. Note: these bounds are computed from: + * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + **/ +@property(nonatomic, readwrite) int64_t seconds; + +/** + * Signed fractions of a second at nanosecond resolution of the span + * of time. Durations less than one second are represented with a 0 + * `seconds` field and a positive or negative `nanos` field. For durations + * of one second or more, a non-zero value for the `nanos` field must be + * of the same sign as the `seconds` field. Must be from -999,999,999 + * to +999,999,999 inclusive. + **/ +@property(nonatomic, readwrite) int32_t nanos; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBDuration.pbobjc.m b/objectivec/GPBDuration.pbobjc.m new file mode 100644 index 0000000000000..d3cc7e31ca3f4 --- /dev/null +++ b/objectivec/GPBDuration.pbobjc.m @@ -0,0 +1,109 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/duration.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBDuration.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBDurationRoot + +@implementation GPBDurationRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBDurationRoot_FileDescriptor + +static GPBFileDescriptor *GPBDurationRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBDuration + +@implementation GPBDuration + +@dynamic seconds; +@dynamic nanos; + +typedef struct GPBDuration__storage_ { + uint32_t _has_storage_[1]; + int32_t nanos; + int64_t seconds; +} GPBDuration__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "seconds", + .dataTypeSpecific.clazz = Nil, + .number = GPBDuration_FieldNumber_Seconds, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBDuration__storage_, seconds), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeInt64, + }, + { + .name = "nanos", + .dataTypeSpecific.clazz = Nil, + .number = GPBDuration_FieldNumber_Nanos, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBDuration__storage_, nanos), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBDuration class] + rootClass:[GPBDurationRoot class] + file:GPBDurationRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBDuration__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBEmpty.pbobjc.h b/objectivec/GPBEmpty.pbobjc.h new file mode 100644 index 0000000000000..45600ead863a1 --- /dev/null +++ b/objectivec/GPBEmpty.pbobjc.h @@ -0,0 +1,74 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/empty.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBEmptyRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +GPB_FINAL @interface GPBEmptyRoot : GPBRootObject +@end + +#pragma mark - GPBEmpty + +/** + * A generic empty message that you can re-use to avoid defining duplicated + * empty messages in your APIs. A typical example is to use it as the request + * or the response type of an API method. For instance: + * + * service Foo { + * rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); + * } + * + * The JSON representation for `Empty` is empty JSON object `{}`. + **/ +GPB_FINAL @interface GPBEmpty : GPBMessage + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBEmpty.pbobjc.m b/objectivec/GPBEmpty.pbobjc.m new file mode 100644 index 0000000000000..df3e398170afb --- /dev/null +++ b/objectivec/GPBEmpty.pbobjc.m @@ -0,0 +1,85 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/empty.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBEmpty.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBEmptyRoot + +@implementation GPBEmptyRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBEmptyRoot_FileDescriptor + +static GPBFileDescriptor *GPBEmptyRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBEmpty + +@implementation GPBEmpty + + +typedef struct GPBEmpty__storage_ { + uint32_t _has_storage_[1]; +} GPBEmpty__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEmpty class] + rootClass:[GPBEmptyRoot class] + file:GPBEmptyRoot_FileDescriptor() + fields:NULL + fieldCount:0 + storageSize:sizeof(GPBEmpty__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBExtensionInternals.m b/objectivec/GPBExtensionInternals.m index 290c82a1bb820..bacec5740a506 100644 --- a/objectivec/GPBExtensionInternals.m +++ b/objectivec/GPBExtensionInternals.m @@ -361,8 +361,8 @@ static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension, if (existingValue) { message = [existingValue retain]; } else { - GPBDescriptor *decriptor = [extension.msgClass descriptor]; - message = [[decriptor.messageClass alloc] init]; + GPBDescriptor *descriptor = [extension.msgClass descriptor]; + message = [[descriptor.messageClass alloc] init]; } if (description->dataType == GPBDataTypeGroup) { diff --git a/objectivec/GPBFieldMask.pbobjc.h b/objectivec/GPBFieldMask.pbobjc.h new file mode 100644 index 0000000000000..3028b775dcd6d --- /dev/null +++ b/objectivec/GPBFieldMask.pbobjc.h @@ -0,0 +1,273 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/field_mask.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBFieldMaskRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +GPB_FINAL @interface GPBFieldMaskRoot : GPBRootObject +@end + +#pragma mark - GPBFieldMask + +typedef GPB_ENUM(GPBFieldMask_FieldNumber) { + GPBFieldMask_FieldNumber_PathsArray = 1, +}; + +/** + * `FieldMask` represents a set of symbolic field paths, for example: + * + * paths: "f.a" + * paths: "f.b.d" + * + * Here `f` represents a field in some root message, `a` and `b` + * fields in the message found in `f`, and `d` a field found in the + * message in `f.b`. + * + * Field masks are used to specify a subset of fields that should be + * returned by a get operation or modified by an update operation. + * Field masks also have a custom JSON encoding (see below). + * + * # Field Masks in Projections + * + * When used in the context of a projection, a response message or + * sub-message is filtered by the API to only contain those fields as + * specified in the mask. For example, if the mask in the previous + * example is applied to a response message as follows: + * + * f { + * a : 22 + * b { + * d : 1 + * x : 2 + * } + * y : 13 + * } + * z: 8 + * + * The result will not contain specific values for fields x,y and z + * (their value will be set to the default, and omitted in proto text + * output): + * + * + * f { + * a : 22 + * b { + * d : 1 + * } + * } + * + * A repeated field is not allowed except at the last position of a + * paths string. + * + * If a FieldMask object is not present in a get operation, the + * operation applies to all fields (as if a FieldMask of all fields + * had been specified). + * + * Note that a field mask does not necessarily apply to the + * top-level response message. In case of a REST get operation, the + * field mask applies directly to the response, but in case of a REST + * list operation, the mask instead applies to each individual message + * in the returned resource list. In case of a REST custom method, + * other definitions may be used. Where the mask applies will be + * clearly documented together with its declaration in the API. In + * any case, the effect on the returned resource/resources is required + * behavior for APIs. + * + * # Field Masks in Update Operations + * + * A field mask in update operations specifies which fields of the + * targeted resource are going to be updated. The API is required + * to only change the values of the fields as specified in the mask + * and leave the others untouched. If a resource is passed in to + * describe the updated values, the API ignores the values of all + * fields not covered by the mask. + * + * If a repeated field is specified for an update operation, new values will + * be appended to the existing repeated field in the target resource. Note that + * a repeated field is only allowed in the last position of a `paths` string. + * + * If a sub-message is specified in the last position of the field mask for an + * update operation, then new value will be merged into the existing sub-message + * in the target resource. + * + * For example, given the target message: + * + * f { + * b { + * d: 1 + * x: 2 + * } + * c: [1] + * } + * + * And an update message: + * + * f { + * b { + * d: 10 + * } + * c: [2] + * } + * + * then if the field mask is: + * + * paths: ["f.b", "f.c"] + * + * then the result will be: + * + * f { + * b { + * d: 10 + * x: 2 + * } + * c: [1, 2] + * } + * + * An implementation may provide options to override this default behavior for + * repeated and message fields. + * + * In order to reset a field's value to the default, the field must + * be in the mask and set to the default value in the provided resource. + * Hence, in order to reset all fields of a resource, provide a default + * instance of the resource and set all fields in the mask, or do + * not provide a mask as described below. + * + * If a field mask is not present on update, the operation applies to + * all fields (as if a field mask of all fields has been specified). + * Note that in the presence of schema evolution, this may mean that + * fields the client does not know and has therefore not filled into + * the request will be reset to their default. If this is unwanted + * behavior, a specific service may require a client to always specify + * a field mask, producing an error if not. + * + * As with get operations, the location of the resource which + * describes the updated values in the request message depends on the + * operation kind. In any case, the effect of the field mask is + * required to be honored by the API. + * + * ## Considerations for HTTP REST + * + * The HTTP kind of an update operation which uses a field mask must + * be set to PATCH instead of PUT in order to satisfy HTTP semantics + * (PUT must only be used for full updates). + * + * # JSON Encoding of Field Masks + * + * In JSON, a field mask is encoded as a single string where paths are + * separated by a comma. Fields name in each path are converted + * to/from lower-camel naming conventions. + * + * As an example, consider the following message declarations: + * + * message Profile { + * User user = 1; + * Photo photo = 2; + * } + * message User { + * string display_name = 1; + * string address = 2; + * } + * + * In proto a field mask for `Profile` may look as such: + * + * mask { + * paths: "user.display_name" + * paths: "photo" + * } + * + * In JSON, the same mask is represented as below: + * + * { + * mask: "user.displayName,photo" + * } + * + * # Field Masks and Oneof Fields + * + * Field masks treat fields in oneofs just as regular fields. Consider the + * following message: + * + * message SampleMessage { + * oneof test_oneof { + * string name = 4; + * SubMessage sub_message = 9; + * } + * } + * + * The field mask can be: + * + * mask { + * paths: "name" + * } + * + * Or: + * + * mask { + * paths: "sub_message" + * } + * + * Note that oneof type names ("test_oneof" in this case) cannot be used in + * paths. + * + * ## Field Mask Verification + * + * The implementation of any API method which has a FieldMask type field in the + * request should verify the included field paths, and return an + * `INVALID_ARGUMENT` error if any path is unmappable. + **/ +GPB_FINAL @interface GPBFieldMask : GPBMessage + +/** The set of field mask paths. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *pathsArray; +/** The number of items in @c pathsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger pathsArray_Count; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBFieldMask.pbobjc.m b/objectivec/GPBFieldMask.pbobjc.m new file mode 100644 index 0000000000000..3605f89d80578 --- /dev/null +++ b/objectivec/GPBFieldMask.pbobjc.m @@ -0,0 +1,98 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/field_mask.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBFieldMask.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBFieldMaskRoot + +@implementation GPBFieldMaskRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBFieldMaskRoot_FileDescriptor + +static GPBFileDescriptor *GPBFieldMaskRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBFieldMask + +@implementation GPBFieldMask + +@dynamic pathsArray, pathsArray_Count; + +typedef struct GPBFieldMask__storage_ { + uint32_t _has_storage_[1]; + NSMutableArray *pathsArray; +} GPBFieldMask__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "pathsArray", + .dataTypeSpecific.clazz = Nil, + .number = GPBFieldMask_FieldNumber_PathsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBFieldMask__storage_, pathsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFieldMask class] + rootClass:[GPBFieldMaskRoot class] + file:GPBFieldMaskRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBFieldMask__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBMessage.h b/objectivec/GPBMessage.h index 276740d2f9962..01253a4afc99b 100644 --- a/objectivec/GPBMessage.h +++ b/objectivec/GPBMessage.h @@ -308,7 +308,7 @@ CF_EXTERN_C_END - (void)writeToOutputStream:(NSOutputStream *)output; /** - * Writes out a varint for the message size followed by the the message to + * Writes out a varint for the message size followed by the message to * the given output stream. * * @param output The coded output stream into which to write the message. @@ -318,7 +318,7 @@ CF_EXTERN_C_END - (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output; /** - * Writes out a varint for the message size followed by the the message to + * Writes out a varint for the message size followed by the message to * the given output stream. * * @param output The output stream into which to write the message. diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m index 37cff6ceffb0a..ee94dee8ed4d8 100644 --- a/objectivec/GPBMessage.m +++ b/objectivec/GPBMessage.m @@ -32,6 +32,7 @@ #import #import +#import #import "GPBArray_PackagePrivate.h" #import "GPBCodedInputStream_PackagePrivate.h" @@ -70,6 +71,8 @@ @interface GPBMessage () { @package GPBUnknownFieldSet *unknownFields_; NSMutableDictionary *extensionMap_; + // Readonly access to autocreatedExtensionMap_ is protected via + // readOnlySemaphore_. NSMutableDictionary *autocreatedExtensionMap_; // If the object was autocreated, we remember the creator so that if we get @@ -77,6 +80,20 @@ @interface GPBMessage () { GPBMessage *autocreator_; GPBFieldDescriptor *autocreatorField_; GPBExtensionDescriptor *autocreatorExtension_; + + // Message can only be mutated from one thread. But some *readonly* operations + // modify internal state because they autocreate things. The + // autocreatedExtensionMap_ is one such structure. Access during readonly + // operations is protected via this semaphore. + // NOTE: OSSpinLock may seem like a good fit here but Apple engineers have + // pointed out that they are vulnerable to live locking on iOS in cases of + // priority inversion: + // http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/ + // https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html + // Use of readOnlySemaphore_ must be prefaced by a call to + // GPBPrepareReadOnlySemaphore to ensure it has been created. This allows + // readOnlySemaphore_ to be only created when actually needed. + _Atomic(dispatch_semaphore_t) readOnlySemaphore_; } @end @@ -84,15 +101,13 @@ static id CreateArrayForField(GPBFieldDescriptor *field, GPBMessage *autocreator) __attribute__((ns_returns_retained)); static id GetOrCreateArrayIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - GPBFileSyntax syntax); + GPBFieldDescriptor *field); static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); static id CreateMapForField(GPBFieldDescriptor *field, GPBMessage *autocreator) __attribute__((ns_returns_retained)); static id GetOrCreateMapIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - GPBFileSyntax syntax); + GPBFieldDescriptor *field); static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, NSZone *zone) @@ -545,25 +560,24 @@ static id CreateMapForField(GPBFieldDescriptor *field, #if !defined(__clang_analyzer__) // These functions are blocked from the analyzer because the analyzer sees the -// GPBSetRetainedObjectIvarWithFieldInternal() call as consuming the array/map, +// GPBSetRetainedObjectIvarWithFieldPrivate() call as consuming the array/map, // so use of the array/map after the call returns is flagged as a use after // free. -// But GPBSetRetainedObjectIvarWithFieldInternal() is "consuming" the retain -// count be holding onto the object (it is transfering it), the object is +// But GPBSetRetainedObjectIvarWithFieldPrivate() is "consuming" the retain +// count be holding onto the object (it is transferring it), the object is // still valid after returning from the call. The other way to avoid this // would be to add a -retain/-autorelease, but that would force every // repeated/map field parsed into the autorelease pool which is both a memory // and performance hit. static id GetOrCreateArrayIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - GPBFileSyntax syntax) { + GPBFieldDescriptor *field) { id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (!array) { // No lock needed, this is called from places expecting to mutate // so no threading protection is needed. array = CreateArrayForField(field, nil); - GPBSetRetainedObjectIvarWithFieldInternal(self, field, array, syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, array); } return array; } @@ -571,30 +585,40 @@ static id GetOrCreateArrayIvarWithField(GPBMessage *self, // This is like GPBGetObjectIvarWithField(), but for arrays, it should // only be used to wire the method into the class. static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { - id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - if (!array) { - // Check again after getting the lock. - GPBPrepareReadOnlySemaphore(self); - dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); - array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - if (!array) { - array = CreateArrayForField(field, self); - GPBSetAutocreatedRetainedObjectIvarWithField(self, field, array); - } - dispatch_semaphore_signal(self->readOnlySemaphore_); + uint8_t *storage = (uint8_t *)self->messageStorage_; + _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset]; + id array = atomic_load(typePtr); + if (array) { + return array; } - return array; + + id expected = nil; + id autocreated = CreateArrayForField(field, self); + if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) { + // Value was set, return it. + return autocreated; + } + + // Some other thread set it, release the one created and return what got set. + if (GPBFieldDataTypeIsObject(field)) { + GPBAutocreatedArray *autoArray = autocreated; + autoArray->_autocreator = nil; + } else { + GPBInt32Array *gpbArray = autocreated; + gpbArray->_autocreator = nil; + } + [autocreated release]; + return expected; } static id GetOrCreateMapIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - GPBFileSyntax syntax) { + GPBFieldDescriptor *field) { id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (!dict) { // No lock needed, this is called from places expecting to mutate // so no threading protection is needed. dict = CreateMapForField(field, nil); - GPBSetRetainedObjectIvarWithFieldInternal(self, field, dict, syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, dict); } return dict; } @@ -602,19 +626,31 @@ static id GetOrCreateMapIvarWithField(GPBMessage *self, // This is like GPBGetObjectIvarWithField(), but for maps, it should // only be used to wire the method into the class. static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { - id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - if (!dict) { - // Check again after getting the lock. - GPBPrepareReadOnlySemaphore(self); - dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); - dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - if (!dict) { - dict = CreateMapForField(field, self); - GPBSetAutocreatedRetainedObjectIvarWithField(self, field, dict); - } - dispatch_semaphore_signal(self->readOnlySemaphore_); + uint8_t *storage = (uint8_t *)self->messageStorage_; + _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset]; + id dict = atomic_load(typePtr); + if (dict) { + return dict; } - return dict; + + id expected = nil; + id autocreated = CreateMapForField(field, self); + if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) { + // Value was set, return it. + return autocreated; + } + + // Some other thread set it, release the one created and return what got set. + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBFieldDataTypeIsObject(field)) { + GPBAutocreatedDictionary *autoDict = autocreated; + autoDict->_autocreator = nil; + } else { + GPBInt32Int32Dictionary *gpbDict = autocreated; + gpbDict->_autocreator = nil; + } + [autocreated release]; + return expected; } #endif // !defined(__clang_analyzer__) @@ -653,9 +689,8 @@ void GPBBecomeVisibleToAutocreator(GPBMessage *self) { // This will recursively make all parent messages visible until it reaches a // super-creator that's visible. if (self->autocreatorField_) { - GPBFileSyntax syntax = [self->autocreator_ descriptor].file.syntax; - GPBSetObjectIvarWithFieldInternal(self->autocreator_, - self->autocreatorField_, self, syntax); + GPBSetObjectIvarWithFieldPrivate(self->autocreator_, + self->autocreatorField_, self); } else { [self->autocreator_ setExtension:self->autocreatorExtension_ value:self]; } @@ -742,16 +777,22 @@ void GPBClearMessageAutocreator(GPBMessage *self) { void GPBPrepareReadOnlySemaphore(GPBMessage *self) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdirect-ivar-access" -#pragma clang diagnostic ignored "-Wdeprecated-declarations" // Create the semaphore on demand (rather than init) as developers might not cause them // to be needed, and the heap usage can add up. The atomic swap is used to avoid needing // another lock around creating it. if (self->readOnlySemaphore_ == nil) { dispatch_semaphore_t worker = dispatch_semaphore_create(1); - if (!OSAtomicCompareAndSwapPtrBarrier(NULL, worker, (void * volatile *)&(self->readOnlySemaphore_))) { + dispatch_semaphore_t expected = nil; + if (!atomic_compare_exchange_strong(&self->readOnlySemaphore_, &expected, worker)) { dispatch_release(worker); } +#if defined(__clang_analyzer__) + // The Xcode 9.2 (and 9.3 beta) static analyzer thinks worker is leaked + // (doesn't seem to know about atomic_compare_exchange_strong); so just + // for the analyzer, let it think worker is also released in this case. + else { dispatch_release(worker); } +#endif } #pragma clang diagnostic pop @@ -915,8 +956,6 @@ - (void)copyFieldsInto:(GPBMessage *)message // Copy all the storage... memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_); - GPBFileSyntax syntax = descriptor.file.syntax; - // Loop over the fields doing fixup... for (GPBFieldDescriptor *field in descriptor->fields_) { if (GPBFieldIsMapOrArray(field)) { @@ -969,7 +1008,8 @@ - (void)copyFieldsInto:(GPBMessage *)message newValue = [value copyWithZone:zone]; } } else { - if (field.mapKeyDataType == GPBDataTypeString) { + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBFieldDataTypeIsObject(field)) { // NSDictionary newValue = [value mutableCopyWithZone:zone]; } else { @@ -983,8 +1023,7 @@ - (void)copyFieldsInto:(GPBMessage *)message // We retain here because the memcpy picked up the pointer value and // the next call to SetRetainedObject... will release the current value. [value retain]; - GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, - syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue); } } else if (GPBFieldDataTypeIsMessage(field)) { // For object types, if we have a value, copy it. If we don't, @@ -996,8 +1035,7 @@ - (void)copyFieldsInto:(GPBMessage *)message // We retain here because the memcpy picked up the pointer value and // the next call to SetRetainedObject... will release the current value. [value retain]; - GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, - syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue); } else { uint8_t *storage = (uint8_t *)message->messageStorage_; id *typePtr = (id *)&storage[field->description_->offset]; @@ -1011,8 +1049,7 @@ - (void)copyFieldsInto:(GPBMessage *)message // We retain here because the memcpy picked up the pointer value and // the next call to SetRetainedObject... will release the current value. [value retain]; - GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, - syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue); } else { // memcpy took care of the rest of the primitive fields if they were set. } @@ -1261,16 +1298,20 @@ - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output { NSUInteger fieldCount = fieldsArray.count; const GPBExtensionRange *extensionRanges = descriptor.extensionRanges; NSUInteger extensionRangesCount = descriptor.extensionRangesCount; + NSArray *sortedExtensions = + [[extensionMap_ allKeys] sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) { if (i == fieldCount) { [self writeExtensionsToCodedOutputStream:output - range:extensionRanges[j++]]; + range:extensionRanges[j++] + sortedExtensions:sortedExtensions]; } else if (j == extensionRangesCount || GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) { [self writeField:fieldsArray[i++] toCodedOutputStream:output]; } else { [self writeExtensionsToCodedOutputStream:output - range:extensionRanges[j++]]; + range:extensionRanges[j++] + sortedExtensions:sortedExtensions]; } } if (descriptor.isWireFormat) { @@ -1350,6 +1391,7 @@ - (void)writeField:(GPBFieldDescriptor *)field //%PDDM-EXPAND FIELD_CASE(Bool, Bool) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeBool: if (fieldType == GPBFieldTypeRepeated) { @@ -1368,8 +1410,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeFixed32: if (fieldType == GPBFieldTypeRepeated) { @@ -1388,8 +1432,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE(SFixed32, Int32) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeSFixed32: if (fieldType == GPBFieldTypeRepeated) { @@ -1408,8 +1454,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE(Float, Float) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeFloat: if (fieldType == GPBFieldTypeRepeated) { @@ -1428,8 +1476,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeFixed64: if (fieldType == GPBFieldTypeRepeated) { @@ -1448,8 +1498,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE(SFixed64, Int64) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeSFixed64: if (fieldType == GPBFieldTypeRepeated) { @@ -1468,8 +1520,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE(Double, Double) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeDouble: if (fieldType == GPBFieldTypeRepeated) { @@ -1488,8 +1542,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE(Int32, Int32) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeInt32: if (fieldType == GPBFieldTypeRepeated) { @@ -1508,8 +1564,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE(Int64, Int64) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeInt64: if (fieldType == GPBFieldTypeRepeated) { @@ -1528,8 +1586,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE(SInt32, Int32) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeSInt32: if (fieldType == GPBFieldTypeRepeated) { @@ -1548,8 +1608,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE(SInt64, Int64) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeSInt64: if (fieldType == GPBFieldTypeRepeated) { @@ -1568,8 +1630,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE(UInt32, UInt32) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeUInt32: if (fieldType == GPBFieldTypeRepeated) { @@ -1588,8 +1652,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE(UInt64, UInt64) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeUInt64: if (fieldType == GPBFieldTypeRepeated) { @@ -1608,8 +1674,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeEnum: if (fieldType == GPBFieldTypeRepeated) { @@ -1628,8 +1696,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE2(Bytes) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeBytes: if (fieldType == GPBFieldTypeRepeated) { @@ -1652,8 +1722,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE2(String) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeString: if (fieldType == GPBFieldTypeRepeated) { @@ -1676,8 +1748,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE2(Message) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeMessage: if (fieldType == GPBFieldTypeRepeated) { @@ -1700,8 +1774,10 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND FIELD_CASE2(Group) // This block of code is generated, do not edit it directly. +// clang-format off case GPBDataTypeGroup: if (fieldType == GPBFieldTypeRepeated) { @@ -1724,6 +1800,7 @@ - (void)writeField:(GPBFieldDescriptor *)field } break; +// clang-format on //%PDDM-EXPAND-END (18 expansions) } } @@ -1786,17 +1863,20 @@ - (NSArray *)extensionsCurrentlySet { } - (void)writeExtensionsToCodedOutputStream:(GPBCodedOutputStream *)output - range:(GPBExtensionRange)range { - NSArray *sortedExtensions = [[extensionMap_ allKeys] - sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; + range:(GPBExtensionRange)range + sortedExtensions:(NSArray *)sortedExtensions { uint32_t start = range.start; uint32_t end = range.end; for (GPBExtensionDescriptor *extension in sortedExtensions) { uint32_t fieldNumber = extension.fieldNumber; - if (fieldNumber >= start && fieldNumber < end) { - id value = [extensionMap_ objectForKey:extension]; - GPBWriteExtensionValueToOutputStream(extension, value, output); + if (fieldNumber < start) { + continue; } + if (fieldNumber >= end) { + break; + } + id value = [extensionMap_ objectForKey:extension]; + GPBWriteExtensionValueToOutputStream(extension, value, output); } } @@ -2026,7 +2106,12 @@ - (void)parseMessageSet:(GPBCodedInputStream *)input [newInput release]; } else { GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); - [unknownFields mergeMessageSetMessage:typeId data:rawBytes]; + // rawBytes was created via a NoCopy, so it can be reusing a + // subrange of another NSData that might go out of scope as things + // unwind, so a copy is needed to ensure what is saved in the + // unknown fields stays valid. + NSData *cloned = [NSData dataWithData:rawBytes]; + [unknownFields mergeMessageSetMessage:typeId data:cloned]; } } } @@ -2091,13 +2176,13 @@ static void MergeSingleFieldFromCodedInputStream( #define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ case GPBDataType##NAME: { \ TYPE val = GPBCodedInputStreamRead##NAME(&input->state_); \ - GPBSet##FUNC_TYPE##IvarWithFieldInternal(self, field, val, syntax); \ + GPBSet##FUNC_TYPE##IvarWithFieldPrivate(self, field, val); \ break; \ } #define CASE_SINGLE_OBJECT(NAME) \ case GPBDataType##NAME: { \ id val = GPBCodedInputStreamReadRetained##NAME(&input->state_); \ - GPBSetRetainedObjectIvarWithFieldInternal(self, field, val, syntax); \ + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, val); \ break; \ } CASE_SINGLE_POD(Bool, BOOL, Bool) @@ -2128,7 +2213,7 @@ static void MergeSingleFieldFromCodedInputStream( } else { GPBMessage *message = [[field.msgClass alloc] init]; [input readMessage:message extensionRegistry:extensionRegistry]; - GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message); } break; } @@ -2147,7 +2232,7 @@ static void MergeSingleFieldFromCodedInputStream( [input readGroup:GPBFieldNumber(field) message:message extensionRegistry:extensionRegistry]; - GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message); } break; } @@ -2156,7 +2241,7 @@ static void MergeSingleFieldFromCodedInputStream( int32_t val = GPBCodedInputStreamReadEnum(&input->state_); if (GPBHasPreservingUnknownEnumSemantics(syntax) || [field isValidEnumValue:val]) { - GPBSetInt32IvarWithFieldInternal(self, field, val, syntax); + GPBSetInt32IvarWithFieldPrivate(self, field, val); } else { GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; @@ -2170,7 +2255,7 @@ static void MergeRepeatedPackedFieldFromCodedInputStream( GPBCodedInputStream *input) { GPBDataType fieldDataType = GPBGetFieldDataType(field); GPBCodedInputStreamState *state = &input->state_; - id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax); + id genericArray = GetOrCreateArrayIvarWithField(self, field); int32_t length = GPBCodedInputStreamReadInt32(state); size_t limit = GPBCodedInputStreamPushLimit(state, length); while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { @@ -2223,7 +2308,7 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream( GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) { GPBCodedInputStreamState *state = &input->state_; - id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax); + id genericArray = GetOrCreateArrayIvarWithField(self, field); switch (GPBGetFieldDataType(field)) { #define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ case GPBDataType##NAME: { \ @@ -2325,7 +2410,7 @@ - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input } else { // fieldType == GPBFieldTypeMap // GPB*Dictionary or NSDictionary, exact type doesn't matter at this // point. - id map = GetOrCreateMapIvarWithField(self, fieldDescriptor, syntax); + id map = GetOrCreateMapIvarWithField(self, fieldDescriptor); [input readMapEntry:map extensionRegistry:extensionRegistry field:fieldDescriptor @@ -2399,7 +2484,6 @@ - (void)mergeFrom:(GPBMessage *)other { GPBBecomeVisibleToAutocreator(self); GPBDescriptor *descriptor = [[self class] descriptor]; - GPBFileSyntax syntax = descriptor.file.syntax; for (GPBFieldDescriptor *field in descriptor->fields_) { GPBFieldType fieldType = field.fieldType; @@ -2413,44 +2497,44 @@ - (void)mergeFrom:(GPBMessage *)other { GPBDataType fieldDataType = GPBGetFieldDataType(field); switch (fieldDataType) { case GPBDataTypeBool: - GPBSetBoolIvarWithFieldInternal( - self, field, GPBGetMessageBoolField(other, field), syntax); + GPBSetBoolIvarWithFieldPrivate( + self, field, GPBGetMessageBoolField(other, field)); break; case GPBDataTypeSFixed32: case GPBDataTypeEnum: case GPBDataTypeInt32: case GPBDataTypeSInt32: - GPBSetInt32IvarWithFieldInternal( - self, field, GPBGetMessageInt32Field(other, field), syntax); + GPBSetInt32IvarWithFieldPrivate( + self, field, GPBGetMessageInt32Field(other, field)); break; case GPBDataTypeFixed32: case GPBDataTypeUInt32: - GPBSetUInt32IvarWithFieldInternal( - self, field, GPBGetMessageUInt32Field(other, field), syntax); + GPBSetUInt32IvarWithFieldPrivate( + self, field, GPBGetMessageUInt32Field(other, field)); break; case GPBDataTypeSFixed64: case GPBDataTypeInt64: case GPBDataTypeSInt64: - GPBSetInt64IvarWithFieldInternal( - self, field, GPBGetMessageInt64Field(other, field), syntax); + GPBSetInt64IvarWithFieldPrivate( + self, field, GPBGetMessageInt64Field(other, field)); break; case GPBDataTypeFixed64: case GPBDataTypeUInt64: - GPBSetUInt64IvarWithFieldInternal( - self, field, GPBGetMessageUInt64Field(other, field), syntax); + GPBSetUInt64IvarWithFieldPrivate( + self, field, GPBGetMessageUInt64Field(other, field)); break; case GPBDataTypeFloat: - GPBSetFloatIvarWithFieldInternal( - self, field, GPBGetMessageFloatField(other, field), syntax); + GPBSetFloatIvarWithFieldPrivate( + self, field, GPBGetMessageFloatField(other, field)); break; case GPBDataTypeDouble: - GPBSetDoubleIvarWithFieldInternal( - self, field, GPBGetMessageDoubleField(other, field), syntax); + GPBSetDoubleIvarWithFieldPrivate( + self, field, GPBGetMessageDoubleField(other, field)); break; case GPBDataTypeBytes: case GPBDataTypeString: { id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); - GPBSetObjectIvarWithFieldInternal(self, field, otherVal, syntax); + GPBSetObjectIvarWithFieldPrivate(self, field, otherVal); break; } case GPBDataTypeMessage: @@ -2462,8 +2546,7 @@ - (void)mergeFrom:(GPBMessage *)other { [message mergeFrom:otherVal]; } else { GPBMessage *message = [otherVal copy]; - GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, - syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message); } break; } @@ -2477,17 +2560,17 @@ - (void)mergeFrom:(GPBMessage *)other { GPBDataType fieldDataType = field->description_->dataType; if (GPBDataTypeIsObject(fieldDataType)) { NSMutableArray *resultArray = - GetOrCreateArrayIvarWithField(self, field, syntax); + GetOrCreateArrayIvarWithField(self, field); [resultArray addObjectsFromArray:otherArray]; } else if (fieldDataType == GPBDataTypeEnum) { GPBEnumArray *resultArray = - GetOrCreateArrayIvarWithField(self, field, syntax); + GetOrCreateArrayIvarWithField(self, field); [resultArray addRawValuesFromArray:otherArray]; } else { - // The array type doesn't matter, that all implment + // The array type doesn't matter, that all implement // -addValuesFromArray:. GPBInt32Array *resultArray = - GetOrCreateArrayIvarWithField(self, field, syntax); + GetOrCreateArrayIvarWithField(self, field); [resultArray addValuesFromArray:otherArray]; } } @@ -2501,19 +2584,19 @@ - (void)mergeFrom:(GPBMessage *)other { if (GPBDataTypeIsObject(keyDataType) && GPBDataTypeIsObject(valueDataType)) { NSMutableDictionary *resultDict = - GetOrCreateMapIvarWithField(self, field, syntax); + GetOrCreateMapIvarWithField(self, field); [resultDict addEntriesFromDictionary:otherDict]; } else if (valueDataType == GPBDataTypeEnum) { // The exact type doesn't matter, just need to know it is a // GPB*EnumDictionary. GPBInt32EnumDictionary *resultDict = - GetOrCreateMapIvarWithField(self, field, syntax); + GetOrCreateMapIvarWithField(self, field); [resultDict addRawEntriesFromDictionary:otherDict]; } else { // The exact type doesn't matter, they all implement // -addEntriesFromDictionary:. GPBInt32Int32Dictionary *resultDict = - GetOrCreateMapIvarWithField(self, field, syntax); + GetOrCreateMapIvarWithField(self, field); [resultDict addEntriesFromDictionary:otherDict]; } } @@ -2591,13 +2674,14 @@ - (BOOL)isEqual:(id)other { if (other == self) { return YES; } - if (![other isKindOfClass:[self class]] && - ![self isKindOfClass:[other class]]) { + if (![other isKindOfClass:[GPBMessage class]]) { return NO; } - GPBMessage *otherMsg = other; GPBDescriptor *descriptor = [[self class] descriptor]; + if ([[otherMsg class] descriptor] != descriptor) { + return NO; + } uint8_t *selfStorage = (uint8_t *)messageStorage_; uint8_t *otherStorage = (uint8_t *)otherMsg->messageStorage_; @@ -2997,7 +3081,10 @@ - (size_t)serializedSize { SEL encodingSelector; } ResolveIvarAccessorMethodResult; -static void ResolveIvarGet(GPBFieldDescriptor *field, +// |field| can be __unsafe_unretained because they are created at startup +// and are essentially global. No need to pay for retain/release when +// they are captured in blocks. +static void ResolveIvarGet(__unsafe_unretained GPBFieldDescriptor *field, ResolveIvarAccessorMethodResult *result) { GPBDataType fieldDataType = GPBGetFieldDataType(field); switch (fieldDataType) { @@ -3039,15 +3126,23 @@ static void ResolveIvarGet(GPBFieldDescriptor *field, } } -static void ResolveIvarSet(GPBFieldDescriptor *field, - GPBFileSyntax syntax, +// See comment about __unsafe_unretained on ResolveIvarGet. +static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field, ResolveIvarAccessorMethodResult *result) { GPBDataType fieldDataType = GPBGetFieldDataType(field); switch (fieldDataType) { #define CASE_SET(NAME, TYPE, TRUE_NAME) \ case GPBDataType##NAME: { \ result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) { \ - return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax); \ + return GPBSet##TRUE_NAME##IvarWithFieldPrivate(obj, field, value); \ + }); \ + result->encodingSelector = @selector(set##NAME:); \ + break; \ + } +#define CASE_SET_COPY(NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj, id value) { \ + return GPBSetRetainedObjectIvarWithFieldPrivate(obj, field, [value copy]); \ }); \ result->encodingSelector = @selector(set##NAME:); \ break; \ @@ -3065,8 +3160,8 @@ static void ResolveIvarSet(GPBFieldDescriptor *field, CASE_SET(SInt64, int64_t, Int64) CASE_SET(UInt32, uint32_t, UInt32) CASE_SET(UInt64, uint64_t, UInt64) - CASE_SET(Bytes, id, Object) - CASE_SET(String, id, Object) + CASE_SET_COPY(Bytes) + CASE_SET_COPY(String) CASE_SET(Message, id, Object) CASE_SET(Group, id, Object) CASE_SET(Enum, int32_t, Enum) @@ -3083,9 +3178,10 @@ + (BOOL)resolveInstanceMethod:(SEL)sel { // NOTE: hasOrCountSel_/setHasSel_ will be NULL if the field for the given // message should not have has support (done in GPBDescriptor.m), so there is // no need for checks here to see if has*/setHas* are allowed. - ResolveIvarAccessorMethodResult result = {NULL, NULL}; - for (GPBFieldDescriptor *field in descriptor->fields_) { + + // See comment about __unsafe_unretained on ResolveIvarGet. + for (__unsafe_unretained GPBFieldDescriptor *field in descriptor->fields_) { BOOL isMapOrArray = GPBFieldIsMapOrArray(field); if (!isMapOrArray) { // Single fields. @@ -3093,7 +3189,7 @@ + (BOOL)resolveInstanceMethod:(SEL)sel { ResolveIvarGet(field, &result); break; } else if (sel == field->setSel_) { - ResolveIvarSet(field, descriptor.file.syntax, &result); + ResolveIvarSet(field, &result); break; } else if (sel == field->hasOrCountSel_) { int32_t index = GPBFieldHasIndex(field); @@ -3143,9 +3239,8 @@ + (BOOL)resolveInstanceMethod:(SEL)sel { } else if (sel == field->setSel_) { // Local for syntax so the block can directly capture it and not the // full lookup. - const GPBFileSyntax syntax = descriptor.file.syntax; result.impToAdd = imp_implementationWithBlock(^(id obj, id value) { - return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax); + GPBSetObjectIvarWithFieldPrivate(obj, field, value); }); result.encodingSelector = @selector(setArray:); break; @@ -3183,7 +3278,7 @@ + (BOOL)resolveInstanceMethod:(SEL)sel { + (BOOL)resolveClassMethod:(SEL)sel { // Extensions scoped to a Message and looked up via class methods. - if (GPBResolveExtensionClassMethod([self descriptor].messageClass, sel)) { + if (GPBResolveExtensionClassMethod(self, sel)) { return YES; } return [super resolveClassMethod:sel]; @@ -3208,6 +3303,22 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder { } - (void)encodeWithCoder:(NSCoder *)aCoder { +#if defined(DEBUG) && DEBUG + if (extensionMap_.count) { + // Hint to go along with the docs on GPBMessage about this. + // + // Note: This is incomplete, in that it only checked the "root" message, + // if a sub message in a field has extensions, the issue still exists. A + // recursive check could be done here (like the work in + // GPBMessageDropUnknownFieldsRecursively()), but that has the potential to + // be expensive and could slow down serialization in DEBUG enough to cause + // developers other problems. + NSLog(@"Warning: writing out a GPBMessage (%@) via NSCoding and it" + @" has %ld extensions; when read back in, those fields will be" + @" in the unknownFields property instead.", + [self class], (long)extensionMap_.count); + } +#endif NSData *data = [self data]; if (data.length) { [aCoder encodeObject:data forKey:kGPBDataCoderKey]; @@ -3234,9 +3345,7 @@ id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field) { [self class], field.name]; } #endif - GPBDescriptor *descriptor = [[self class] descriptor]; - GPBFileSyntax syntax = descriptor.file.syntax; - return GetOrCreateArrayIvarWithField(self, field, syntax); + return GetOrCreateArrayIvarWithField(self, field); } // Only exists for public api, no core code should use this. @@ -3248,9 +3357,39 @@ id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) { [self class], field.name]; } #endif - GPBDescriptor *descriptor = [[self class] descriptor]; - GPBFileSyntax syntax = descriptor.file.syntax; - return GetOrCreateMapIvarWithField(self, field, syntax); + return GetOrCreateMapIvarWithField(self, field); +} + +id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { + NSCAssert(!GPBFieldIsMapOrArray(field), @"Shouldn't get here"); + if (!GPBFieldDataTypeIsMessage(field)) { + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + return *typePtr; + } + // Not set...non messages (string/data), get their default. + return field.defaultValue.valueMessage; + } + + uint8_t *storage = (uint8_t *)self->messageStorage_; + _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset]; + id msg = atomic_load(typePtr); + if (msg) { + return msg; + } + + id expected = nil; + id autocreated = GPBCreateMessageWithAutocreator(field.msgClass, self, field); + if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) { + // Value was set, return it. + return autocreated; + } + + // Some other thread set it, release the one created and return what got set. + GPBClearMessageAutocreator(autocreated); + [autocreated release]; + return expected; } #pragma clang diagnostic pop diff --git a/objectivec/GPBMessage_PackagePrivate.h b/objectivec/GPBMessage_PackagePrivate.h index 90834d4073d0b..ca10983b3c2c5 100644 --- a/objectivec/GPBMessage_PackagePrivate.h +++ b/objectivec/GPBMessage_PackagePrivate.h @@ -34,6 +34,10 @@ #import "GPBMessage.h" +// TODO: Remove this import. Older generated code use the OSAtomic* apis, +// so anyone that hasn't regenerated says building by having this. After +// enough time has passed, this likely can be removed as folks should have +// regenerated. #import #import "GPBBootstrap.h" @@ -57,20 +61,6 @@ typedef struct GPBMessage_Storage *GPBMessage_StoragePtr; // GPBMessage_Storage with _has_storage__ as the first field. // Kept public because static functions need to access it. GPBMessage_StoragePtr messageStorage_; - - // A lock to provide mutual exclusion from internal data that can be modified - // by *read* operations such as getters (autocreation of message fields and - // message extensions, not setting of values). Used to guarantee thread safety - // for concurrent reads on the message. - // NOTE: OSSpinLock may seem like a good fit here but Apple engineers have - // pointed out that they are vulnerable to live locking on iOS in cases of - // priority inversion: - // http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/ - // https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html - // Use of readOnlySemaphore_ must be prefaced by a call to - // GPBPrepareReadOnlySemaphore to ensure it has been created. This allows - // readOnlySemaphore_ to be only created when actually needed. - dispatch_semaphore_t readOnlySemaphore_; } // Gets an extension value without autocreating the result if not found. (i.e. diff --git a/objectivec/GPBProtocolBuffers.h b/objectivec/GPBProtocolBuffers.h index 68d8854eb8e7f..c5df916396987 100644 --- a/objectivec/GPBProtocolBuffers.h +++ b/objectivec/GPBProtocolBuffers.h @@ -52,25 +52,25 @@ // Well-known proto types #if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import - #import - #import - #import - #import - #import - #import - #import - #import - #import + #import + #import + #import + #import + #import + #import + #import + #import + #import + #import #else - #import "google/protobuf/Any.pbobjc.h" - #import "google/protobuf/Api.pbobjc.h" - #import "google/protobuf/Duration.pbobjc.h" - #import "google/protobuf/Empty.pbobjc.h" - #import "google/protobuf/FieldMask.pbobjc.h" - #import "google/protobuf/SourceContext.pbobjc.h" - #import "google/protobuf/Struct.pbobjc.h" - #import "google/protobuf/Timestamp.pbobjc.h" - #import "google/protobuf/Type.pbobjc.h" - #import "google/protobuf/Wrappers.pbobjc.h" + #import "GPBAny.pbobjc.h" + #import "GPBApi.pbobjc.h" + #import "GPBDuration.pbobjc.h" + #import "GPBEmpty.pbobjc.h" + #import "GPBFieldMask.pbobjc.h" + #import "GPBSourceContext.pbobjc.h" + #import "GPBStruct.pbobjc.h" + #import "GPBTimestamp.pbobjc.h" + #import "GPBType.pbobjc.h" + #import "GPBWrappers.pbobjc.h" #endif diff --git a/objectivec/GPBProtocolBuffers.m b/objectivec/GPBProtocolBuffers.m index d04c8be155ff1..0545ae9b2b638 100644 --- a/objectivec/GPBProtocolBuffers.m +++ b/objectivec/GPBProtocolBuffers.m @@ -54,13 +54,13 @@ #import "GPBWellKnownTypes.m" #import "GPBWireFormat.m" -#import "google/protobuf/Any.pbobjc.m" -#import "google/protobuf/Api.pbobjc.m" -#import "google/protobuf/Duration.pbobjc.m" -#import "google/protobuf/Empty.pbobjc.m" -#import "google/protobuf/FieldMask.pbobjc.m" -#import "google/protobuf/SourceContext.pbobjc.m" -#import "google/protobuf/Struct.pbobjc.m" -#import "google/protobuf/Timestamp.pbobjc.m" -#import "google/protobuf/Type.pbobjc.m" -#import "google/protobuf/Wrappers.pbobjc.m" +#import "GPBAny.pbobjc.m" +#import "GPBApi.pbobjc.m" +#import "GPBDuration.pbobjc.m" +#import "GPBEmpty.pbobjc.m" +#import "GPBFieldMask.pbobjc.m" +#import "GPBSourceContext.pbobjc.m" +#import "GPBStruct.pbobjc.m" +#import "GPBTimestamp.pbobjc.m" +#import "GPBType.pbobjc.m" +#import "GPBWrappers.pbobjc.m" diff --git a/objectivec/GPBProtocolBuffers_RuntimeSupport.h b/objectivec/GPBProtocolBuffers_RuntimeSupport.h index fea75b93bc256..04dde620a2b8c 100644 --- a/objectivec/GPBProtocolBuffers_RuntimeSupport.h +++ b/objectivec/GPBProtocolBuffers_RuntimeSupport.h @@ -31,7 +31,7 @@ // This header is meant to only be used by the generated source, it should not // be included in code using protocol buffers. -#import "GPBProtocolBuffers.h" +#import "GPBBootstrap.h" #import "GPBDescriptor_PackagePrivate.h" #import "GPBExtensionInternals.h" diff --git a/objectivec/GPBRootObject.m b/objectivec/GPBRootObject.m index 585d205a21896..bad2f9a7a1c4f 100644 --- a/objectivec/GPBRootObject.m +++ b/objectivec/GPBRootObject.m @@ -43,6 +43,14 @@ @interface GPBExtensionDescriptor (GPBRootObject) - (const char *)singletonNameC; @end +// We need some object to conform to the MessageSignatureProtocol to make sure +// the selectors in it are recorded in our Objective C runtime information. +// GPBMessage is arguably the more "obvious" choice, but given that all messages +// inherit from GPBMessage, conflicts seem likely, so we are using GPBRootObject +// instead. +@interface GPBRootObject () +@end + @implementation GPBRootObject // Taken from http://www.burtleburtle.net/bob/hash/doobs.html diff --git a/objectivec/GPBRuntimeTypes.h b/objectivec/GPBRuntimeTypes.h index 4d552060b0043..9c1083a8153a6 100644 --- a/objectivec/GPBRuntimeTypes.h +++ b/objectivec/GPBRuntimeTypes.h @@ -74,7 +74,7 @@ typedef union { /** * Enum listing the possible data types that a field can contain. - * + * * @note Do not change the order of this enum (or add things to it) without * thinking about it very carefully. There are several things that depend * on the order. @@ -142,3 +142,10 @@ typedef struct GPBExtensionRange { /** Exclusive. */ uint32_t end; } GPBExtensionRange; + +/** + A type to represent an Objective C class. + This is actually an `objc_class` but the runtime headers will not allow us to + reference `objc_class`, so we have defined our own. +*/ +typedef struct GPBObjcClass_t GPBObjcClass_t; diff --git a/objectivec/GPBSourceContext.pbobjc.h b/objectivec/GPBSourceContext.pbobjc.h new file mode 100644 index 0000000000000..7a103362b5658 --- /dev/null +++ b/objectivec/GPBSourceContext.pbobjc.h @@ -0,0 +1,77 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/source_context.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBSourceContextRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +GPB_FINAL @interface GPBSourceContextRoot : GPBRootObject +@end + +#pragma mark - GPBSourceContext + +typedef GPB_ENUM(GPBSourceContext_FieldNumber) { + GPBSourceContext_FieldNumber_FileName = 1, +}; + +/** + * `SourceContext` represents information about the source of a + * protobuf element, like the file in which it is defined. + **/ +GPB_FINAL @interface GPBSourceContext : GPBMessage + +/** + * The path-qualified name of the .proto file that contained the associated + * protobuf element. For example: `"google/protobuf/source_context.proto"`. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *fileName; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBSourceContext.pbobjc.m b/objectivec/GPBSourceContext.pbobjc.m new file mode 100644 index 0000000000000..b3e6fa759ce48 --- /dev/null +++ b/objectivec/GPBSourceContext.pbobjc.m @@ -0,0 +1,98 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/source_context.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBSourceContext.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBSourceContextRoot + +@implementation GPBSourceContextRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBSourceContextRoot_FileDescriptor + +static GPBFileDescriptor *GPBSourceContextRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBSourceContext + +@implementation GPBSourceContext + +@dynamic fileName; + +typedef struct GPBSourceContext__storage_ { + uint32_t _has_storage_[1]; + NSString *fileName; +} GPBSourceContext__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "fileName", + .dataTypeSpecific.clazz = Nil, + .number = GPBSourceContext_FieldNumber_FileName, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBSourceContext__storage_, fileName), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBSourceContext class] + rootClass:[GPBSourceContextRoot class] + file:GPBSourceContextRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBSourceContext__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBStruct.pbobjc.h b/objectivec/GPBStruct.pbobjc.h new file mode 100644 index 0000000000000..e36df3f1a3a1e --- /dev/null +++ b/objectivec/GPBStruct.pbobjc.h @@ -0,0 +1,204 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/struct.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +@class GPBListValue; +@class GPBStruct; +@class GPBValue; + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Enum GPBNullValue + +/** + * `NullValue` is a singleton enumeration to represent the null value for the + * `Value` type union. + * + * The JSON representation for `NullValue` is JSON `null`. + **/ +typedef GPB_ENUM(GPBNullValue) { + /** + * Value used if any message's field encounters a value that is not defined + * by this enum. The message will also have C functions to get/set the rawValue + * of the field. + **/ + GPBNullValue_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + /** Null value. */ + GPBNullValue_NullValue = 0, +}; + +GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GPBNullValue_IsValidValue(int32_t value); + +#pragma mark - GPBStructRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +GPB_FINAL @interface GPBStructRoot : GPBRootObject +@end + +#pragma mark - GPBStruct + +typedef GPB_ENUM(GPBStruct_FieldNumber) { + GPBStruct_FieldNumber_Fields = 1, +}; + +/** + * `Struct` represents a structured data value, consisting of fields + * which map to dynamically typed values. In some languages, `Struct` + * might be supported by a native representation. For example, in + * scripting languages like JS a struct is represented as an + * object. The details of that representation are described together + * with the proto support for the language. + * + * The JSON representation for `Struct` is JSON object. + **/ +GPB_FINAL @interface GPBStruct : GPBMessage + +/** Unordered map of dynamically typed values. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableDictionary *fields; +/** The number of items in @c fields without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger fields_Count; + +@end + +#pragma mark - GPBValue + +typedef GPB_ENUM(GPBValue_FieldNumber) { + GPBValue_FieldNumber_NullValue = 1, + GPBValue_FieldNumber_NumberValue = 2, + GPBValue_FieldNumber_StringValue = 3, + GPBValue_FieldNumber_BoolValue = 4, + GPBValue_FieldNumber_StructValue = 5, + GPBValue_FieldNumber_ListValue = 6, +}; + +typedef GPB_ENUM(GPBValue_Kind_OneOfCase) { + GPBValue_Kind_OneOfCase_GPBUnsetOneOfCase = 0, + GPBValue_Kind_OneOfCase_NullValue = 1, + GPBValue_Kind_OneOfCase_NumberValue = 2, + GPBValue_Kind_OneOfCase_StringValue = 3, + GPBValue_Kind_OneOfCase_BoolValue = 4, + GPBValue_Kind_OneOfCase_StructValue = 5, + GPBValue_Kind_OneOfCase_ListValue = 6, +}; + +/** + * `Value` represents a dynamically typed value which can be either + * null, a number, a string, a boolean, a recursive struct value, or a + * list of values. A producer of value is expected to set one of that + * variants, absence of any variant indicates an error. + * + * The JSON representation for `Value` is JSON value. + **/ +GPB_FINAL @interface GPBValue : GPBMessage + +/** The kind of value. */ +@property(nonatomic, readonly) GPBValue_Kind_OneOfCase kindOneOfCase; + +/** Represents a null value. */ +@property(nonatomic, readwrite) GPBNullValue nullValue; + +/** Represents a double value. */ +@property(nonatomic, readwrite) double numberValue; + +/** Represents a string value. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *stringValue; + +/** Represents a boolean value. */ +@property(nonatomic, readwrite) BOOL boolValue; + +/** Represents a structured value. */ +@property(nonatomic, readwrite, strong, null_resettable) GPBStruct *structValue; + +/** Represents a repeated `Value`. */ +@property(nonatomic, readwrite, strong, null_resettable) GPBListValue *listValue; + +@end + +/** + * Fetches the raw value of a @c GPBValue's @c nullValue property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBValue_NullValue_RawValue(GPBValue *message); +/** + * Sets the raw value of an @c GPBValue's @c nullValue property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value); + +/** + * Clears whatever value was set for the oneof 'kind'. + **/ +void GPBValue_ClearKindOneOfCase(GPBValue *message); + +#pragma mark - GPBListValue + +typedef GPB_ENUM(GPBListValue_FieldNumber) { + GPBListValue_FieldNumber_ValuesArray = 1, +}; + +/** + * `ListValue` is a wrapper around a repeated field of values. + * + * The JSON representation for `ListValue` is JSON array. + **/ +GPB_FINAL @interface GPBListValue : GPBMessage + +/** Repeated field of dynamically typed values. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *valuesArray; +/** The number of items in @c valuesArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger valuesArray_Count; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBStruct.pbobjc.m b/objectivec/GPBStruct.pbobjc.m new file mode 100644 index 0000000000000..554046a9fe50f --- /dev/null +++ b/objectivec/GPBStruct.pbobjc.m @@ -0,0 +1,311 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/struct.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#import + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBStruct.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#pragma clang diagnostic ignored "-Wdirect-ivar-access" +#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" + +#pragma mark - Objective C Class declarations +// Forward declarations of Objective C classes that we can use as +// static values in struct initializers. +// We don't use [Foo class] because it is not a static value. +GPBObjCClassDeclaration(GPBListValue); +GPBObjCClassDeclaration(GPBStruct); +GPBObjCClassDeclaration(GPBValue); + +#pragma mark - GPBStructRoot + +@implementation GPBStructRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBStructRoot_FileDescriptor + +static GPBFileDescriptor *GPBStructRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - Enum GPBNullValue + +GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "NullValue\000"; + static const int32_t values[] = { + GPBNullValue_NullValue, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBNullValue) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GPBNullValue_IsValidValue]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GPBNullValue_IsValidValue(int32_t value__) { + switch (value__) { + case GPBNullValue_NullValue: + return YES; + default: + return NO; + } +} + +#pragma mark - GPBStruct + +@implementation GPBStruct + +@dynamic fields, fields_Count; + +typedef struct GPBStruct__storage_ { + uint32_t _has_storage_[1]; + NSMutableDictionary *fields; +} GPBStruct__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "fields", + .dataTypeSpecific.clazz = GPBObjCClass(GPBValue), + .number = GPBStruct_FieldNumber_Fields, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBStruct__storage_, fields), + .flags = GPBFieldMapKeyString, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBStruct class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBStruct__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBValue + +@implementation GPBValue + +@dynamic kindOneOfCase; +@dynamic nullValue; +@dynamic numberValue; +@dynamic stringValue; +@dynamic boolValue; +@dynamic structValue; +@dynamic listValue; + +typedef struct GPBValue__storage_ { + uint32_t _has_storage_[2]; + GPBNullValue nullValue; + NSString *stringValue; + GPBStruct *structValue; + GPBListValue *listValue; + double numberValue; +} GPBValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "nullValue", + .dataTypeSpecific.enumDescFunc = GPBNullValue_EnumDescriptor, + .number = GPBValue_FieldNumber_NullValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, nullValue), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .dataType = GPBDataTypeEnum, + }, + { + .name = "numberValue", + .dataTypeSpecific.clazz = Nil, + .number = GPBValue_FieldNumber_NumberValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, numberValue), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeDouble, + }, + { + .name = "stringValue", + .dataTypeSpecific.clazz = Nil, + .number = GPBValue_FieldNumber_StringValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, stringValue), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeString, + }, + { + .name = "boolValue", + .dataTypeSpecific.clazz = Nil, + .number = GPBValue_FieldNumber_BoolValue, + .hasIndex = -1, + .offset = 0, // Stored in _has_storage_ to save space. + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBool, + }, + { + .name = "structValue", + .dataTypeSpecific.clazz = GPBObjCClass(GPBStruct), + .number = GPBValue_FieldNumber_StructValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, structValue), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "listValue", + .dataTypeSpecific.clazz = GPBObjCClass(GPBListValue), + .number = GPBValue_FieldNumber_ListValue, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GPBValue__storage_, listValue), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBValue class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBValue__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + static const char *oneofs[] = { + "kind", + }; + [localDescriptor setupOneofs:oneofs + count:(uint32_t)(sizeof(oneofs) / sizeof(char*)) + firstHasIndex:-1]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBValue_NullValue_RawValue(GPBValue *message) { + GPBDescriptor *descriptor = [GPBValue descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue]; + return GPBGetMessageRawEnumField(message, field); +} + +void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value) { + GPBDescriptor *descriptor = [GPBValue descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue]; + GPBSetMessageRawEnumField(message, field, value); +} + +void GPBValue_ClearKindOneOfCase(GPBValue *message) { + GPBDescriptor *descriptor = [GPBValue descriptor]; + GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; + GPBClearOneof(message, oneof); +} +#pragma mark - GPBListValue + +@implementation GPBListValue + +@dynamic valuesArray, valuesArray_Count; + +typedef struct GPBListValue__storage_ { + uint32_t _has_storage_[1]; + NSMutableArray *valuesArray; +} GPBListValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "valuesArray", + .dataTypeSpecific.clazz = GPBObjCClass(GPBValue), + .number = GPBListValue_FieldNumber_ValuesArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBListValue__storage_, valuesArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBListValue class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBListValue__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBTimestamp.pbobjc.h b/objectivec/GPBTimestamp.pbobjc.h new file mode 100644 index 0000000000000..a328afc7c93d4 --- /dev/null +++ b/objectivec/GPBTimestamp.pbobjc.h @@ -0,0 +1,176 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/timestamp.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBTimestampRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +GPB_FINAL @interface GPBTimestampRoot : GPBRootObject +@end + +#pragma mark - GPBTimestamp + +typedef GPB_ENUM(GPBTimestamp_FieldNumber) { + GPBTimestamp_FieldNumber_Seconds = 1, + GPBTimestamp_FieldNumber_Nanos = 2, +}; + +/** + * A Timestamp represents a point in time independent of any time zone or local + * calendar, encoded as a count of seconds and fractions of seconds at + * nanosecond resolution. The count is relative to an epoch at UTC midnight on + * January 1, 1970, in the proleptic Gregorian calendar which extends the + * Gregorian calendar backwards to year one. + * + * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + * second table is needed for interpretation, using a [24-hour linear + * smear](https://developers.google.com/time/smear). + * + * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + * restricting to that range, we ensure that we can convert to and from [RFC + * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. + * + * # Examples + * + * Example 1: Compute Timestamp from POSIX `time()`. + * + * Timestamp timestamp; + * timestamp.set_seconds(time(NULL)); + * timestamp.set_nanos(0); + * + * Example 2: Compute Timestamp from POSIX `gettimeofday()`. + * + * struct timeval tv; + * gettimeofday(&tv, NULL); + * + * Timestamp timestamp; + * timestamp.set_seconds(tv.tv_sec); + * timestamp.set_nanos(tv.tv_usec * 1000); + * + * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + * + * FILETIME ft; + * GetSystemTimeAsFileTime(&ft); + * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + * + * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z + * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. + * Timestamp timestamp; + * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); + * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + * + * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + * + * long millis = System.currentTimeMillis(); + * + * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) + * .setNanos((int) ((millis % 1000) * 1000000)).build(); + * + * + * Example 5: Compute Timestamp from Java `Instant.now()`. + * + * Instant now = Instant.now(); + * + * Timestamp timestamp = + * Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + * .setNanos(now.getNano()).build(); + * + * + * Example 6: Compute Timestamp from current time in Python. + * + * timestamp = Timestamp() + * timestamp.GetCurrentTime() + * + * # JSON Mapping + * + * In JSON format, the Timestamp type is encoded as a string in the + * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the + * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" + * where {year} is always expressed using four digits while {month}, {day}, + * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional + * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), + * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone + * is required. A proto3 JSON serializer should always use UTC (as indicated by + * "Z") when printing the Timestamp type and a proto3 JSON parser should be + * able to accept both UTC and other timezones (as indicated by an offset). + * + * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past + * 01:30 UTC on January 15, 2017. + * + * In JavaScript, one can convert a Date object to this format using the + * standard + * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) + * method. In Python, a standard `datetime.datetime` object can be converted + * to this format using + * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with + * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use + * the Joda Time's [`ISODateTimeFormat.dateTime()`]( + * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D + * ) to obtain a formatter capable of generating timestamps in this format. + **/ +GPB_FINAL @interface GPBTimestamp : GPBMessage + +/** + * Represents seconds of UTC time since Unix epoch + * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59Z inclusive. + **/ +@property(nonatomic, readwrite) int64_t seconds; + +/** + * Non-negative fractions of a second at nanosecond resolution. Negative + * second values with fractions must still have non-negative nanos values + * that count forward in time. Must be from 0 to 999,999,999 + * inclusive. + **/ +@property(nonatomic, readwrite) int32_t nanos; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBTimestamp.pbobjc.m b/objectivec/GPBTimestamp.pbobjc.m new file mode 100644 index 0000000000000..736a75d19f9d0 --- /dev/null +++ b/objectivec/GPBTimestamp.pbobjc.m @@ -0,0 +1,109 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/timestamp.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBTimestamp.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBTimestampRoot + +@implementation GPBTimestampRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBTimestampRoot_FileDescriptor + +static GPBFileDescriptor *GPBTimestampRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBTimestamp + +@implementation GPBTimestamp + +@dynamic seconds; +@dynamic nanos; + +typedef struct GPBTimestamp__storage_ { + uint32_t _has_storage_[1]; + int32_t nanos; + int64_t seconds; +} GPBTimestamp__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "seconds", + .dataTypeSpecific.clazz = Nil, + .number = GPBTimestamp_FieldNumber_Seconds, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBTimestamp__storage_, seconds), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeInt64, + }, + { + .name = "nanos", + .dataTypeSpecific.clazz = Nil, + .number = GPBTimestamp_FieldNumber_Nanos, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBTimestamp__storage_, nanos), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBTimestamp class] + rootClass:[GPBTimestampRoot class] + file:GPBTimestampRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBTimestamp__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBType.pbobjc.h b/objectivec/GPBType.pbobjc.h new file mode 100644 index 0000000000000..747e15d455dc7 --- /dev/null +++ b/objectivec/GPBType.pbobjc.h @@ -0,0 +1,444 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/type.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +@class GPBAny; +@class GPBEnumValue; +@class GPBField; +@class GPBOption; +@class GPBSourceContext; + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Enum GPBSyntax + +/** The syntax in which a protocol buffer element is defined. */ +typedef GPB_ENUM(GPBSyntax) { + /** + * Value used if any message's field encounters a value that is not defined + * by this enum. The message will also have C functions to get/set the rawValue + * of the field. + **/ + GPBSyntax_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + /** Syntax `proto2`. */ + GPBSyntax_SyntaxProto2 = 0, + + /** Syntax `proto3`. */ + GPBSyntax_SyntaxProto3 = 1, +}; + +GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GPBSyntax_IsValidValue(int32_t value); + +#pragma mark - Enum GPBField_Kind + +/** Basic field types. */ +typedef GPB_ENUM(GPBField_Kind) { + /** + * Value used if any message's field encounters a value that is not defined + * by this enum. The message will also have C functions to get/set the rawValue + * of the field. + **/ + GPBField_Kind_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + /** Field type unknown. */ + GPBField_Kind_TypeUnknown = 0, + + /** Field type double. */ + GPBField_Kind_TypeDouble = 1, + + /** Field type float. */ + GPBField_Kind_TypeFloat = 2, + + /** Field type int64. */ + GPBField_Kind_TypeInt64 = 3, + + /** Field type uint64. */ + GPBField_Kind_TypeUint64 = 4, + + /** Field type int32. */ + GPBField_Kind_TypeInt32 = 5, + + /** Field type fixed64. */ + GPBField_Kind_TypeFixed64 = 6, + + /** Field type fixed32. */ + GPBField_Kind_TypeFixed32 = 7, + + /** Field type bool. */ + GPBField_Kind_TypeBool = 8, + + /** Field type string. */ + GPBField_Kind_TypeString = 9, + + /** Field type group. Proto2 syntax only, and deprecated. */ + GPBField_Kind_TypeGroup = 10, + + /** Field type message. */ + GPBField_Kind_TypeMessage = 11, + + /** Field type bytes. */ + GPBField_Kind_TypeBytes = 12, + + /** Field type uint32. */ + GPBField_Kind_TypeUint32 = 13, + + /** Field type enum. */ + GPBField_Kind_TypeEnum = 14, + + /** Field type sfixed32. */ + GPBField_Kind_TypeSfixed32 = 15, + + /** Field type sfixed64. */ + GPBField_Kind_TypeSfixed64 = 16, + + /** Field type sint32. */ + GPBField_Kind_TypeSint32 = 17, + + /** Field type sint64. */ + GPBField_Kind_TypeSint64 = 18, +}; + +GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GPBField_Kind_IsValidValue(int32_t value); + +#pragma mark - Enum GPBField_Cardinality + +/** Whether a field is optional, required, or repeated. */ +typedef GPB_ENUM(GPBField_Cardinality) { + /** + * Value used if any message's field encounters a value that is not defined + * by this enum. The message will also have C functions to get/set the rawValue + * of the field. + **/ + GPBField_Cardinality_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + /** For fields with unknown cardinality. */ + GPBField_Cardinality_CardinalityUnknown = 0, + + /** For optional fields. */ + GPBField_Cardinality_CardinalityOptional = 1, + + /** For required fields. Proto2 syntax only. */ + GPBField_Cardinality_CardinalityRequired = 2, + + /** For repeated fields. */ + GPBField_Cardinality_CardinalityRepeated = 3, +}; + +GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GPBField_Cardinality_IsValidValue(int32_t value); + +#pragma mark - GPBTypeRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +GPB_FINAL @interface GPBTypeRoot : GPBRootObject +@end + +#pragma mark - GPBType + +typedef GPB_ENUM(GPBType_FieldNumber) { + GPBType_FieldNumber_Name = 1, + GPBType_FieldNumber_FieldsArray = 2, + GPBType_FieldNumber_OneofsArray = 3, + GPBType_FieldNumber_OptionsArray = 4, + GPBType_FieldNumber_SourceContext = 5, + GPBType_FieldNumber_Syntax = 6, +}; + +/** + * A protocol buffer message type. + **/ +GPB_FINAL @interface GPBType : GPBMessage + +/** The fully qualified message name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** The list of fields. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *fieldsArray; +/** The number of items in @c fieldsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger fieldsArray_Count; + +/** The list of types appearing in `oneof` definitions in this type. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *oneofsArray; +/** The number of items in @c oneofsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger oneofsArray_Count; + +/** The protocol buffer options. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** The source context. */ +@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; +/** Test to see if @c sourceContext has been set. */ +@property(nonatomic, readwrite) BOOL hasSourceContext; + +/** The source syntax. */ +@property(nonatomic, readwrite) GPBSyntax syntax; + +@end + +/** + * Fetches the raw value of a @c GPBType's @c syntax property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBType_Syntax_RawValue(GPBType *message); +/** + * Sets the raw value of an @c GPBType's @c syntax property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value); + +#pragma mark - GPBField + +typedef GPB_ENUM(GPBField_FieldNumber) { + GPBField_FieldNumber_Kind = 1, + GPBField_FieldNumber_Cardinality = 2, + GPBField_FieldNumber_Number = 3, + GPBField_FieldNumber_Name = 4, + GPBField_FieldNumber_TypeURL = 6, + GPBField_FieldNumber_OneofIndex = 7, + GPBField_FieldNumber_Packed = 8, + GPBField_FieldNumber_OptionsArray = 9, + GPBField_FieldNumber_JsonName = 10, + GPBField_FieldNumber_DefaultValue = 11, +}; + +/** + * A single field of a message type. + **/ +GPB_FINAL @interface GPBField : GPBMessage + +/** The field type. */ +@property(nonatomic, readwrite) GPBField_Kind kind; + +/** The field cardinality. */ +@property(nonatomic, readwrite) GPBField_Cardinality cardinality; + +/** The field number. */ +@property(nonatomic, readwrite) int32_t number; + +/** The field name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** + * The field type URL, without the scheme, for message or enumeration + * types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL; + +/** + * The index of the field type in `Type.oneofs`, for message or enumeration + * types. The first type has index 1; zero means the type is not in the list. + **/ +@property(nonatomic, readwrite) int32_t oneofIndex; + +/** Whether to use alternative packed wire representation. */ +@property(nonatomic, readwrite) BOOL packed; + +/** The protocol buffer options. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** The field JSON name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *jsonName; + +/** The string value of the default value of this field. Proto2 syntax only. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *defaultValue; + +@end + +/** + * Fetches the raw value of a @c GPBField's @c kind property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBField_Kind_RawValue(GPBField *message); +/** + * Sets the raw value of an @c GPBField's @c kind property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBField_Kind_RawValue(GPBField *message, int32_t value); + +/** + * Fetches the raw value of a @c GPBField's @c cardinality property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBField_Cardinality_RawValue(GPBField *message); +/** + * Sets the raw value of an @c GPBField's @c cardinality property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value); + +#pragma mark - GPBEnum + +typedef GPB_ENUM(GPBEnum_FieldNumber) { + GPBEnum_FieldNumber_Name = 1, + GPBEnum_FieldNumber_EnumvalueArray = 2, + GPBEnum_FieldNumber_OptionsArray = 3, + GPBEnum_FieldNumber_SourceContext = 4, + GPBEnum_FieldNumber_Syntax = 5, +}; + +/** + * Enum type definition. + **/ +GPB_FINAL @interface GPBEnum : GPBMessage + +/** Enum type name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** Enum value definitions. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *enumvalueArray; +/** The number of items in @c enumvalueArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger enumvalueArray_Count; + +/** Protocol buffer options. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +/** The source context. */ +@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; +/** Test to see if @c sourceContext has been set. */ +@property(nonatomic, readwrite) BOOL hasSourceContext; + +/** The source syntax. */ +@property(nonatomic, readwrite) GPBSyntax syntax; + +@end + +/** + * Fetches the raw value of a @c GPBEnum's @c syntax property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GPBEnum_Syntax_RawValue(GPBEnum *message); +/** + * Sets the raw value of an @c GPBEnum's @c syntax property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value); + +#pragma mark - GPBEnumValue + +typedef GPB_ENUM(GPBEnumValue_FieldNumber) { + GPBEnumValue_FieldNumber_Name = 1, + GPBEnumValue_FieldNumber_Number = 2, + GPBEnumValue_FieldNumber_OptionsArray = 3, +}; + +/** + * Enum value definition. + **/ +GPB_FINAL @interface GPBEnumValue : GPBMessage + +/** Enum value name. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** Enum value number. */ +@property(nonatomic, readwrite) int32_t number; + +/** Protocol buffer options. */ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; +/** The number of items in @c optionsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger optionsArray_Count; + +@end + +#pragma mark - GPBOption + +typedef GPB_ENUM(GPBOption_FieldNumber) { + GPBOption_FieldNumber_Name = 1, + GPBOption_FieldNumber_Value = 2, +}; + +/** + * A protocol buffer option, which can be attached to a message, field, + * enumeration, etc. + **/ +GPB_FINAL @interface GPBOption : GPBMessage + +/** + * The option's name. For protobuf built-in options (options defined in + * descriptor.proto), this is the short name. For example, `"map_entry"`. + * For custom options, it should be the fully-qualified name. For example, + * `"google.api.http"`. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSString *name; + +/** + * The option's value packed in an Any message. If the value is a primitive, + * the corresponding wrapper type defined in google/protobuf/wrappers.proto + * should be used. If the value is an enum, it should be stored as an int32 + * value using the google.protobuf.Int32Value type. + **/ +@property(nonatomic, readwrite, strong, null_resettable) GPBAny *value; +/** Test to see if @c value has been set. */ +@property(nonatomic, readwrite) BOOL hasValue; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBType.pbobjc.m b/objectivec/GPBType.pbobjc.m new file mode 100644 index 0000000000000..70dae31c68a06 --- /dev/null +++ b/objectivec/GPBType.pbobjc.m @@ -0,0 +1,727 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/type.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#import + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBType.pbobjc.h" + #import "GPBAny.pbobjc.h" + #import "GPBSourceContext.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" + +#pragma mark - Objective C Class declarations +// Forward declarations of Objective C classes that we can use as +// static values in struct initializers. +// We don't use [Foo class] because it is not a static value. +GPBObjCClassDeclaration(GPBAny); +GPBObjCClassDeclaration(GPBEnumValue); +GPBObjCClassDeclaration(GPBField); +GPBObjCClassDeclaration(GPBOption); +GPBObjCClassDeclaration(GPBSourceContext); + +#pragma mark - GPBTypeRoot + +@implementation GPBTypeRoot + +// No extensions in the file and none of the imports (direct or indirect) +// defined extensions, so no need to generate +extensionRegistry. + +@end + +#pragma mark - GPBTypeRoot_FileDescriptor + +static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - Enum GPBSyntax + +GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "SyntaxProto2\000SyntaxProto3\000"; + static const int32_t values[] = { + GPBSyntax_SyntaxProto2, + GPBSyntax_SyntaxProto3, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBSyntax) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GPBSyntax_IsValidValue]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GPBSyntax_IsValidValue(int32_t value__) { + switch (value__) { + case GPBSyntax_SyntaxProto2: + case GPBSyntax_SyntaxProto3: + return YES; + default: + return NO; + } +} + +#pragma mark - GPBType + +@implementation GPBType + +@dynamic name; +@dynamic fieldsArray, fieldsArray_Count; +@dynamic oneofsArray, oneofsArray_Count; +@dynamic optionsArray, optionsArray_Count; +@dynamic hasSourceContext, sourceContext; +@dynamic syntax; + +typedef struct GPBType__storage_ { + uint32_t _has_storage_[1]; + GPBSyntax syntax; + NSString *name; + NSMutableArray *fieldsArray; + NSMutableArray *oneofsArray; + NSMutableArray *optionsArray; + GPBSourceContext *sourceContext; +} GPBType__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.clazz = Nil, + .number = GPBType_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBType__storage_, name), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "fieldsArray", + .dataTypeSpecific.clazz = GPBObjCClass(GPBField), + .number = GPBType_FieldNumber_FieldsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBType__storage_, fieldsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "oneofsArray", + .dataTypeSpecific.clazz = Nil, + .number = GPBType_FieldNumber_OneofsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBType__storage_, oneofsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeString, + }, + { + .name = "optionsArray", + .dataTypeSpecific.clazz = GPBObjCClass(GPBOption), + .number = GPBType_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBType__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "sourceContext", + .dataTypeSpecific.clazz = GPBObjCClass(GPBSourceContext), + .number = GPBType_FieldNumber_SourceContext, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBType__storage_, sourceContext), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "syntax", + .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, + .number = GPBType_FieldNumber_Syntax, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GPBType__storage_, syntax), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeEnum, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBType class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBType__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBType_Syntax_RawValue(GPBType *message) { + GPBDescriptor *descriptor = [GPBType descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax]; + return GPBGetMessageRawEnumField(message, field); +} + +void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value) { + GPBDescriptor *descriptor = [GPBType descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax]; + GPBSetMessageRawEnumField(message, field, value); +} + +#pragma mark - GPBField + +@implementation GPBField + +@dynamic kind; +@dynamic cardinality; +@dynamic number; +@dynamic name; +@dynamic typeURL; +@dynamic oneofIndex; +@dynamic packed; +@dynamic optionsArray, optionsArray_Count; +@dynamic jsonName; +@dynamic defaultValue; + +typedef struct GPBField__storage_ { + uint32_t _has_storage_[1]; + GPBField_Kind kind; + GPBField_Cardinality cardinality; + int32_t number; + int32_t oneofIndex; + NSString *name; + NSString *typeURL; + NSMutableArray *optionsArray; + NSString *jsonName; + NSString *defaultValue; +} GPBField__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "kind", + .dataTypeSpecific.enumDescFunc = GPBField_Kind_EnumDescriptor, + .number = GPBField_FieldNumber_Kind, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBField__storage_, kind), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeEnum, + }, + { + .name = "cardinality", + .dataTypeSpecific.enumDescFunc = GPBField_Cardinality_EnumDescriptor, + .number = GPBField_FieldNumber_Cardinality, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBField__storage_, cardinality), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeEnum, + }, + { + .name = "number", + .dataTypeSpecific.clazz = Nil, + .number = GPBField_FieldNumber_Number, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GPBField__storage_, number), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeInt32, + }, + { + .name = "name", + .dataTypeSpecific.clazz = Nil, + .number = GPBField_FieldNumber_Name, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GPBField__storage_, name), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "typeURL", + .dataTypeSpecific.clazz = Nil, + .number = GPBField_FieldNumber_TypeURL, + .hasIndex = 4, + .offset = (uint32_t)offsetof(GPBField__storage_, typeURL), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "oneofIndex", + .dataTypeSpecific.clazz = Nil, + .number = GPBField_FieldNumber_OneofIndex, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GPBField__storage_, oneofIndex), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeInt32, + }, + { + .name = "packed", + .dataTypeSpecific.clazz = Nil, + .number = GPBField_FieldNumber_Packed, + .hasIndex = 6, + .offset = 7, // Stored in _has_storage_ to save space. + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBool, + }, + { + .name = "optionsArray", + .dataTypeSpecific.clazz = GPBObjCClass(GPBOption), + .number = GPBField_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBField__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "jsonName", + .dataTypeSpecific.clazz = Nil, + .number = GPBField_FieldNumber_JsonName, + .hasIndex = 8, + .offset = (uint32_t)offsetof(GPBField__storage_, jsonName), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "defaultValue", + .dataTypeSpecific.clazz = Nil, + .number = GPBField_FieldNumber_DefaultValue, + .hasIndex = 9, + .offset = (uint32_t)offsetof(GPBField__storage_, defaultValue), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBField class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBField__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; +#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + static const char *extraTextFormatInfo = + "\001\006\004\241!!\000"; + [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; +#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBField_Kind_RawValue(GPBField *message) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind]; + return GPBGetMessageRawEnumField(message, field); +} + +void SetGPBField_Kind_RawValue(GPBField *message, int32_t value) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind]; + GPBSetMessageRawEnumField(message, field, value); +} + +int32_t GPBField_Cardinality_RawValue(GPBField *message) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality]; + return GPBGetMessageRawEnumField(message, field); +} + +void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality]; + GPBSetMessageRawEnumField(message, field, value); +} + +#pragma mark - Enum GPBField_Kind + +GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "TypeUnknown\000TypeDouble\000TypeFloat\000TypeInt" + "64\000TypeUint64\000TypeInt32\000TypeFixed64\000Type" + "Fixed32\000TypeBool\000TypeString\000TypeGroup\000Ty" + "peMessage\000TypeBytes\000TypeUint32\000TypeEnum\000" + "TypeSfixed32\000TypeSfixed64\000TypeSint32\000Typ" + "eSint64\000"; + static const int32_t values[] = { + GPBField_Kind_TypeUnknown, + GPBField_Kind_TypeDouble, + GPBField_Kind_TypeFloat, + GPBField_Kind_TypeInt64, + GPBField_Kind_TypeUint64, + GPBField_Kind_TypeInt32, + GPBField_Kind_TypeFixed64, + GPBField_Kind_TypeFixed32, + GPBField_Kind_TypeBool, + GPBField_Kind_TypeString, + GPBField_Kind_TypeGroup, + GPBField_Kind_TypeMessage, + GPBField_Kind_TypeBytes, + GPBField_Kind_TypeUint32, + GPBField_Kind_TypeEnum, + GPBField_Kind_TypeSfixed32, + GPBField_Kind_TypeSfixed64, + GPBField_Kind_TypeSint32, + GPBField_Kind_TypeSint64, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Kind) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GPBField_Kind_IsValidValue]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GPBField_Kind_IsValidValue(int32_t value__) { + switch (value__) { + case GPBField_Kind_TypeUnknown: + case GPBField_Kind_TypeDouble: + case GPBField_Kind_TypeFloat: + case GPBField_Kind_TypeInt64: + case GPBField_Kind_TypeUint64: + case GPBField_Kind_TypeInt32: + case GPBField_Kind_TypeFixed64: + case GPBField_Kind_TypeFixed32: + case GPBField_Kind_TypeBool: + case GPBField_Kind_TypeString: + case GPBField_Kind_TypeGroup: + case GPBField_Kind_TypeMessage: + case GPBField_Kind_TypeBytes: + case GPBField_Kind_TypeUint32: + case GPBField_Kind_TypeEnum: + case GPBField_Kind_TypeSfixed32: + case GPBField_Kind_TypeSfixed64: + case GPBField_Kind_TypeSint32: + case GPBField_Kind_TypeSint64: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GPBField_Cardinality + +GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "CardinalityUnknown\000CardinalityOptional\000C" + "ardinalityRequired\000CardinalityRepeated\000"; + static const int32_t values[] = { + GPBField_Cardinality_CardinalityUnknown, + GPBField_Cardinality_CardinalityOptional, + GPBField_Cardinality_CardinalityRequired, + GPBField_Cardinality_CardinalityRepeated, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Cardinality) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GPBField_Cardinality_IsValidValue]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GPBField_Cardinality_IsValidValue(int32_t value__) { + switch (value__) { + case GPBField_Cardinality_CardinalityUnknown: + case GPBField_Cardinality_CardinalityOptional: + case GPBField_Cardinality_CardinalityRequired: + case GPBField_Cardinality_CardinalityRepeated: + return YES; + default: + return NO; + } +} + +#pragma mark - GPBEnum + +@implementation GPBEnum + +@dynamic name; +@dynamic enumvalueArray, enumvalueArray_Count; +@dynamic optionsArray, optionsArray_Count; +@dynamic hasSourceContext, sourceContext; +@dynamic syntax; + +typedef struct GPBEnum__storage_ { + uint32_t _has_storage_[1]; + GPBSyntax syntax; + NSString *name; + NSMutableArray *enumvalueArray; + NSMutableArray *optionsArray; + GPBSourceContext *sourceContext; +} GPBEnum__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.clazz = Nil, + .number = GPBEnum_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBEnum__storage_, name), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "enumvalueArray", + .dataTypeSpecific.clazz = GPBObjCClass(GPBEnumValue), + .number = GPBEnum_FieldNumber_EnumvalueArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBEnum__storage_, enumvalueArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "optionsArray", + .dataTypeSpecific.clazz = GPBObjCClass(GPBOption), + .number = GPBEnum_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBEnum__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "sourceContext", + .dataTypeSpecific.clazz = GPBObjCClass(GPBSourceContext), + .number = GPBEnum_FieldNumber_SourceContext, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBEnum__storage_, sourceContext), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "syntax", + .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, + .number = GPBEnum_FieldNumber_Syntax, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GPBEnum__storage_, syntax), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeEnum, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEnum class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBEnum__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GPBEnum_Syntax_RawValue(GPBEnum *message) { + GPBDescriptor *descriptor = [GPBEnum descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax]; + return GPBGetMessageRawEnumField(message, field); +} + +void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value) { + GPBDescriptor *descriptor = [GPBEnum descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax]; + GPBSetMessageRawEnumField(message, field, value); +} + +#pragma mark - GPBEnumValue + +@implementation GPBEnumValue + +@dynamic name; +@dynamic number; +@dynamic optionsArray, optionsArray_Count; + +typedef struct GPBEnumValue__storage_ { + uint32_t _has_storage_[1]; + int32_t number; + NSString *name; + NSMutableArray *optionsArray; +} GPBEnumValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.clazz = Nil, + .number = GPBEnumValue_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBEnumValue__storage_, name), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "number", + .dataTypeSpecific.clazz = Nil, + .number = GPBEnumValue_FieldNumber_Number, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBEnumValue__storage_, number), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeInt32, + }, + { + .name = "optionsArray", + .dataTypeSpecific.clazz = GPBObjCClass(GPBOption), + .number = GPBEnumValue_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GPBEnumValue__storage_, optionsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEnumValue class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBEnumValue__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBOption + +@implementation GPBOption + +@dynamic name; +@dynamic hasValue, value; + +typedef struct GPBOption__storage_ { + uint32_t _has_storage_[1]; + NSString *name; + GPBAny *value; +} GPBOption__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .dataTypeSpecific.clazz = Nil, + .number = GPBOption_FieldNumber_Name, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBOption__storage_, name), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "value", + .dataTypeSpecific.clazz = GPBObjCClass(GPBAny), + .number = GPBOption_FieldNumber_Value, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GPBOption__storage_, value), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBOption class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBOption__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBUnknownField.m b/objectivec/GPBUnknownField.m index 30efe7563b712..7fa8cade2d8d1 100644 --- a/objectivec/GPBUnknownField.m +++ b/objectivec/GPBUnknownField.m @@ -32,6 +32,7 @@ #import "GPBArray.h" #import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBUnknownFieldSet.h" @implementation GPBUnknownField { @protected @@ -79,7 +80,7 @@ - (id)copyWithZone:(NSZone *)zone { result->mutableFixed32List_ = [mutableFixed32List_ copyWithZone:zone]; result->mutableFixed64List_ = [mutableFixed64List_ copyWithZone:zone]; result->mutableLengthDelimitedList_ = - [mutableLengthDelimitedList_ copyWithZone:zone]; + [mutableLengthDelimitedList_ mutableCopyWithZone:zone]; result->mutableVarintList_ = [mutableVarintList_ copyWithZone:zone]; if (mutableGroupList_.count) { result->mutableGroupList_ = [[NSMutableArray allocWithZone:zone] @@ -97,6 +98,7 @@ - (BOOL)isEqual:(id)object { if (self == object) return YES; if (![object isKindOfClass:[GPBUnknownField class]]) return NO; GPBUnknownField *field = (GPBUnknownField *)object; + if (number_ != field->number_) return NO; BOOL equalVarint = (mutableVarintList_.count == 0 && field->mutableVarintList_.count == 0) || [mutableVarintList_ isEqual:field->mutableVarintList_]; @@ -202,8 +204,9 @@ - (size_t)serializedSizeAsMessageSetExtension { } - (NSString *)description { - NSMutableString *description = [NSMutableString - stringWithFormat:@"<%@ %p>: Field: %d {\n", [self class], self, number_]; + NSMutableString *description = + [NSMutableString stringWithFormat:@"<%@ %p>: Field: %d {\n", + [self class], self, number_]; [mutableVarintList_ enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { #pragma unused(idx, stop) diff --git a/objectivec/GPBUtilities.h b/objectivec/GPBUtilities.h index 5464dfb356139..75759b2334077 100644 --- a/objectivec/GPBUtilities.h +++ b/objectivec/GPBUtilities.h @@ -34,6 +34,8 @@ #import "GPBMessage.h" #import "GPBRuntimeTypes.h" +@class GPBOneofDescriptor; + CF_EXTERN_C_BEGIN NS_ASSUME_NONNULL_BEGIN @@ -92,8 +94,17 @@ BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field); **/ void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field); +/** + * Clears the given oneof field for the given message. + * + * @param self The message for which to clear the field. + * @param oneof The oneof to clear. + **/ +void GPBClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof); + //%PDDM-EXPAND GPB_ACCESSORS() // This block of code is generated, do not edit it directly. +// clang-format off // @@ -384,6 +395,7 @@ void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, id dictionary); +// clang-format on //%PDDM-EXPAND-END GPB_ACCESSORS() /** diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m index 5029ec73b3469..08dd358225fb2 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -49,6 +49,25 @@ static void AppendTextFormatForMessage(GPBMessage *message, NSMutableString *toStr, NSString *lineIndent); +// Are two datatypes the same basic type representation (ex Int32 and SInt32). +// Marked unused because currently only called from asserts/debug. +static BOOL DataTypesEquivalent(GPBDataType type1, + GPBDataType type2) __attribute__ ((unused)); + +// Basic type representation for a type (ex: for SInt32 it is Int32). +// Marked unused because currently only called from asserts/debug. +static GPBDataType BaseDataType(GPBDataType type) __attribute__ ((unused)); + +// String name for a data type. +// Marked unused because currently only called from asserts/debug. +static NSString *TypeToString(GPBDataType dataType) __attribute__ ((unused)); + +// Helper for clearing oneofs. +static void GPBMaybeClearOneofPrivate(GPBMessage *self, + GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, + uint32_t fieldNumberNotToClear); + NSData *GPBEmptyNSData(void) { static dispatch_once_t onceToken; static NSData *defaultNSData = nil; @@ -200,7 +219,7 @@ void GPBCheckRuntimeVersionSupport(int32_t objcRuntimeVersion) { // Library is too old for headers. [NSException raise:NSInternalInconsistencyException format:@"Linked to ProtocolBuffer runtime version %d," - @" but code compiled needing atleast %d!", + @" but code compiled needing at least %d!", GOOGLE_PROTOBUF_OBJC_VERSION, objcRuntimeVersion]; } if (objcRuntimeVersion < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) { @@ -254,17 +273,28 @@ void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) { return; } + GPBMessageFieldDescription *fieldDesc = field->description_; if (GPBFieldStoresObject(field)) { // Object types are handled slightly differently, they need to be released. uint8_t *storage = (uint8_t *)self->messageStorage_; - id *typePtr = (id *)&storage[field->description_->offset]; + id *typePtr = (id *)&storage[fieldDesc->offset]; [*typePtr release]; *typePtr = nil; } else { // POD types just need to clear the has bit as the Get* method will // fetch the default when needed. } - GPBSetHasIvarField(self, field, NO); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, NO); +} + +void GPBClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof) { + #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof, + @"OneofDescriptor %@ doesn't appear to be for %@ messages.", + oneof.name, [self class]); + #endif + GPBFieldDescriptor *firstField = oneof->fields_[0]; + GPBMaybeClearOneofPrivate(self, oneof, firstField->description_->hasIndex, 0); } BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) { @@ -278,7 +308,7 @@ BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) { } else { NSCAssert(idx != GPBNoHasBit, @"Invalid has bit."); uint32_t byteIndex = idx / 32; - uint32_t bitMask = (1 << (idx % 32)); + uint32_t bitMask = (1U << (idx % 32)); BOOL hasIvar = (self->messageStorage_->_has_storage_[byteIndex] & bitMask) ? YES : NO; return hasIvar; @@ -302,7 +332,7 @@ void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber, NSCAssert(idx != GPBNoHasBit, @"Invalid has bit."); uint32_t *has_storage = self->messageStorage_->_has_storage_; uint32_t byte = idx / 32; - uint32_t bitMask = (1 << (idx % 32)); + uint32_t bitMask = (1U << (idx % 32)); if (value) { has_storage[byte] |= bitMask; } else { @@ -311,8 +341,10 @@ void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber, } } -void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, - int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) { +static void GPBMaybeClearOneofPrivate(GPBMessage *self, + GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, + uint32_t fieldNumberNotToClear) { uint32_t fieldNumberSet = GPBGetHasOneof(self, oneofHasIndex); if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) { // Do nothing/nothing set in the oneof. @@ -342,6 +374,17 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE) //%TYPE GPBGetMessage##NAME##Field(GPBMessage *self, //% TYPE$S NAME$S GPBFieldDescriptor *field) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, +//% @"FieldDescriptor %@ doesn't appear to be for %@ messages.", +//% field.name, [self class]); +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to get value of TYPE from field %@ " +//% @"of %@ which is of type %@.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif //% if (GPBGetHasIvarField(self, field)) { //% uint8_t *storage = (uint8_t *)self->messageStorage_; //% TYPE *typePtr = (TYPE *)&storage[field->description_->offset]; @@ -356,34 +399,44 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //% NAME$S GPBFieldDescriptor *field, //% NAME$S TYPE value) { //% if (self == nil || field == nil) return; -//% GPBFileSyntax syntax = [self descriptor].file.syntax; -//% GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax); +//%#if defined(DEBUG) && DEBUG +//% NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, +//% @"FieldDescriptor %@ doesn't appear to be for %@ messages.", +//% field.name, [self class]); +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to set field %@ of %@ which is of type %@ with " +//% @"value of type TYPE.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% GPBSet##NAME##IvarWithFieldPrivate(self, field, value); //%} //% -//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self, -//% NAME$S GPBFieldDescriptor *field, -//% NAME$S TYPE value, -//% NAME$S GPBFileSyntax syntax) { +//%void GPBSet##NAME##IvarWithFieldPrivate(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE value) { //% GPBOneofDescriptor *oneof = field->containingOneof_; +//% GPBMessageFieldDescription *fieldDesc = field->description_; //% if (oneof) { -//% GPBMessageFieldDescription *fieldDesc = field->description_; -//% GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); +//% GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); //% } +//%#if defined(DEBUG) && DEBUG //% NSCAssert(self->messageStorage_ != NULL, //% @"%@: All messages should have storage (from init)", //% [self class]); +//%#endif //%#if defined(__clang_analyzer__) //% if (self->messageStorage_ == NULL) return; //%#endif //% uint8_t *storage = (uint8_t *)self->messageStorage_; -//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset]; +//% TYPE *typePtr = (TYPE *)&storage[fieldDesc->offset]; //% *typePtr = value; -//% // proto2: any value counts as having been set; proto3, it -//% // has to be a non zero value or be in a oneof. -//% BOOL hasValue = ((syntax == GPBFileSyntaxProto2) -//% || (value != (TYPE)0) -//% || (field->containingOneof_ != NULL)); -//% GPBSetHasIvarField(self, field, hasValue); +//% // If the value is zero, then we only count the field as "set" if the field +//% // shouldn't auto clear on zero. +//% BOOL hasValue = ((value != (TYPE)0) +//% || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); +//% GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); //% GPBBecomeVisibleToAutocreator(self); //%} //% @@ -391,6 +444,14 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //%// Only exists for public api, no core code should use this. //%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self, //% TYPE$S NAME$S GPBFieldDescriptor *field) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to get value of TYPE from field %@ " +//% @"of %@ which is of type %@.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif //% return (TYPE *)GPBGetObjectIvarWithField(self, field); //%} //% @@ -398,22 +459,51 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //%void GPBSetMessage##NAME##Field(GPBMessage *self, //% NAME$S GPBFieldDescriptor *field, //% NAME$S TYPE *value) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to set field %@ of %@ which is of type %@ with " +//% @"value of type TYPE.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif //% GPBSetObjectIvarWithField(self, field, (id)value); //%} //% +//%PDDM-DEFINE IVAR_ALIAS_DEFN_COPY_OBJECT(NAME, TYPE) +//%// Only exists for public api, no core code should use this. +//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self, +//% TYPE$S NAME$S GPBFieldDescriptor *field) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to get value of TYPE from field %@ " +//% @"of %@ which is of type %@.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% return (TYPE *)GPBGetObjectIvarWithField(self, field); +//%} +//% +//%// Only exists for public api, no core code should use this. +//%void GPBSetMessage##NAME##Field(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE *value) { +//%#if defined(DEBUG) && DEBUG +//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), +//% GPBDataType##NAME), +//% @"Attempting to set field %@ of %@ which is of type %@ with " +//% @"value of type TYPE.", +//% [self class], field.name, +//% TypeToString(GPBGetFieldDataType(field))); +//%#endif +//% GPBSetCopyObjectIvarWithField(self, field, (id)value); +//%} +//% // Object types are handled slightly differently, they need to be released // and retained. -void GPBSetAutocreatedRetainedObjectIvarWithField( - GPBMessage *self, GPBFieldDescriptor *field, - id __attribute__((ns_consumed)) value) { - uint8_t *storage = (uint8_t *)self->messageStorage_; - id *typePtr = (id *)&storage[field->description_->offset]; - NSCAssert(*typePtr == NULL, @"Can't set autocreated object more than once."); - *typePtr = value; -} - void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { @@ -427,25 +517,37 @@ void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, [oldValue release]; } -// This exists only for briging some aliased types, nothing else should use it. +// This exists only for bridging some aliased types, nothing else should use it. static void GPBSetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field, id value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain], - syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value retain]); } -void GPBSetObjectIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, id value, - GPBFileSyntax syntax) { - GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain], - syntax); +static void GPBSetCopyObjectIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, id value); + +// GPBSetCopyObjectIvarWithField is blocked from the analyzer because it flags +// a leak for the -copy even though GPBSetRetainedObjectIvarWithFieldPrivate +// is marked as consuming the value. Note: For some reason this doesn't happen +// with the -retain in GPBSetObjectIvarWithField. +#if !defined(__clang_analyzer__) +// This exists only for bridging some aliased types, nothing else should use it. +static void GPBSetCopyObjectIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, id value) { + if (self == nil || field == nil) return; + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value copy]); } +#endif // !defined(__clang_analyzer__) -void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - id value, GPBFileSyntax syntax) { +void GPBSetObjectIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, id value) { + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value retain]); +} + +void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + id value) { NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)", [self class]); @@ -455,7 +557,7 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, GPBDataType fieldType = GPBGetFieldDataType(field); BOOL isMapOrArray = GPBFieldIsMapOrArray(field); BOOL fieldIsMessage = GPBDataTypeIsMessage(fieldType); -#ifdef DEBUG +#if defined(DEBUG) && DEBUG if (value == nil && !isMapOrArray && !fieldIsMessage && field.hasDefaultValue) { // Setting a message to nil is an obvious way to "clear" the value @@ -484,39 +586,30 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, // valueData/valueMessage. } #endif // DEBUG + GPBMessageFieldDescription *fieldDesc = field->description_; if (!isMapOrArray) { // Non repeated/map can be in an oneof, clear any existing value from the // oneof. GPBOneofDescriptor *oneof = field->containingOneof_; if (oneof) { - GPBMessageFieldDescription *fieldDesc = field->description_; - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } // Clear "has" if they are being set to nil. BOOL setHasValue = (value != nil); - // Under proto3, Bytes & String fields get cleared by resetting them to - // their default (empty) values, so if they are set to something of length - // zero, they are being cleared. - if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage && + // If the field should clear on a "zero" value, then check if the string/data + // was zero length, and clear instead. + if (((fieldDesc->flags & GPBFieldClearHasIvarOnZero) != 0) && ([value length] == 0)) { - // Except, if the field was in a oneof, then it still gets recorded as - // having been set so the state of the oneof can be serialized back out. - if (!oneof) { - setHasValue = NO; - } - if (setHasValue) { - NSCAssert(value != nil, @"Should never be setting has for nil"); - } else { - // The value passed in was retained, it must be released since we - // aren't saving anything in the field. - [value release]; - value = nil; - } + setHasValue = NO; + // The value passed in was retained, it must be released since we + // aren't saving anything in the field. + [value release]; + value = nil; } - GPBSetHasIvarField(self, field, setHasValue); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, setHasValue); } uint8_t *storage = (uint8_t *)self->messageStorage_; - id *typePtr = (id *)&storage[field->description_->offset]; + id *typePtr = (id *)&storage[fieldDesc->offset]; id oldValue = *typePtr; @@ -581,46 +674,24 @@ id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self, return *typePtr; } -id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { - NSCAssert(!GPBFieldIsMapOrArray(field), @"Shouldn't get here"); - if (GPBGetHasIvarField(self, field)) { - uint8_t *storage = (uint8_t *)self->messageStorage_; - id *typePtr = (id *)&storage[field->description_->offset]; - return *typePtr; - } - // Not set... - - // Non messages (string/data), get their default. - if (!GPBFieldDataTypeIsMessage(field)) { - return field.defaultValue.valueMessage; - } - - GPBPrepareReadOnlySemaphore(self); - dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); - GPBMessage *result = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - if (!result) { - // For non repeated messages, create the object, set it and return it. - // This object will not initially be visible via GPBGetHasIvar, so - // we save its creator so it can become visible if it's mutated later. - result = GPBCreateMessageWithAutocreator(field.msgClass, self, field); - GPBSetAutocreatedRetainedObjectIvarWithField(self, field, result); - } - dispatch_semaphore_signal(self->readOnlySemaphore_); - return result; -} - // Only exists for public api, no core code should use this. int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) { - GPBFileSyntax syntax = [self descriptor].file.syntax; - return GPBGetEnumIvarWithFieldInternal(self, field, syntax); -} + #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum, + @"Attempting to get value of type Enum from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); + #endif -int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - GPBFileSyntax syntax) { int32_t result = GPBGetMessageInt32Field(self, field); // If this is presevering unknown enums, make sure the value is valid before // returning it. + + GPBFileSyntax syntax = [self descriptor].file.syntax; if (GPBHasPreservingUnknownEnumSemantics(syntax) && ![field isValidEnumValue:result]) { result = kGPBUnrecognizedEnumeratorValue; @@ -631,20 +702,28 @@ int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, // Only exists for public api, no core code should use this. void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value) { - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); -} - -void GPBSetEnumIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, int32_t value, - GPBFileSyntax syntax) { + #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum, + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type Enum.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); + #endif + GPBSetEnumIvarWithFieldPrivate(self, field, value); +} + +void GPBSetEnumIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, int32_t value) { // Don't allow in unknown values. Proto3 can use the Raw method. if (![field isValidEnumValue:value]) { [NSException raise:NSInvalidArgumentException format:@"%@.%@: Attempt to set an unknown enum value (%d)", [self class], field.name, value]; } - GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); + GPBSetInt32IvarWithFieldPrivate(self, field, value); } // Only exists for public api, no core code should use this. @@ -657,12 +736,21 @@ int32_t GPBGetMessageRawEnumField(GPBMessage *self, // Only exists for public api, no core code should use this. void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value) { - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); + GPBSetInt32IvarWithFieldPrivate(self, field, value); } BOOL GPBGetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool), + @"Attempting to get value of type bool from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif if (GPBGetHasIvarField(self, field)) { // Bools are stored in the has bits to avoid needing explicit space in the // storage structure. @@ -680,18 +768,26 @@ void GPBSetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field, BOOL value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetBoolIvarWithFieldInternal(self, field, value, syntax); -} - -void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - BOOL value, - GPBFileSyntax syntax) { + #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type bool.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); + #endif + GPBSetBoolIvarWithFieldPrivate(self, field, value); +} + +void GPBSetBoolIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + BOOL value) { GPBMessageFieldDescription *fieldDesc = field->description_; GPBOneofDescriptor *oneof = field->containingOneof_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } // Bools are stored in the has bits to avoid needing explicit space in the @@ -700,20 +796,31 @@ void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, // the offset is never negative) GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value); - // proto2: any value counts as having been set; proto3, it - // has to be a non zero value or be in a oneof. - BOOL hasValue = ((syntax == GPBFileSyntaxProto2) - || (value != (BOOL)0) - || (field->containingOneof_ != NULL)); - GPBSetHasIvarField(self, field, hasValue); + // If the value is zero, then we only count the field as "set" if the field + // shouldn't auto clear on zero. + BOOL hasValue = ((value != (BOOL)0) + || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int32, int32_t) // This block of code is generated, do not edit it directly. +// clang-format off int32_t GPBGetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeInt32), + @"Attempting to get value of int32_t from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; int32_t *typePtr = (int32_t *)&storage[field->description_->offset]; @@ -728,42 +835,65 @@ void GPBSetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field, int32_t value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); +#if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeInt32), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type int32_t.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetInt32IvarWithFieldPrivate(self, field, value); } -void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value, - GPBFileSyntax syntax) { +void GPBSetInt32IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value) { GPBOneofDescriptor *oneof = field->containingOneof_; + GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMessageFieldDescription *fieldDesc = field->description_; - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } +#if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)", [self class]); +#endif #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif uint8_t *storage = (uint8_t *)self->messageStorage_; - int32_t *typePtr = (int32_t *)&storage[field->description_->offset]; + int32_t *typePtr = (int32_t *)&storage[fieldDesc->offset]; *typePtr = value; - // proto2: any value counts as having been set; proto3, it - // has to be a non zero value or be in a oneof. - BOOL hasValue = ((syntax == GPBFileSyntaxProto2) - || (value != (int32_t)0) - || (field->containingOneof_ != NULL)); - GPBSetHasIvarField(self, field, hasValue); + // If the value is zero, then we only count the field as "set" if the field + // shouldn't auto clear on zero. + BOOL hasValue = ((value != (int32_t)0) + || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } +// clang-format on //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt32, uint32_t) // This block of code is generated, do not edit it directly. +// clang-format off uint32_t GPBGetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeUInt32), + @"Attempting to get value of uint32_t from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset]; @@ -778,42 +908,65 @@ void GPBSetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field, uint32_t value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax); +#if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeUInt32), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type uint32_t.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetUInt32IvarWithFieldPrivate(self, field, value); } -void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - uint32_t value, - GPBFileSyntax syntax) { +void GPBSetUInt32IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + uint32_t value) { GPBOneofDescriptor *oneof = field->containingOneof_; + GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMessageFieldDescription *fieldDesc = field->description_; - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } +#if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)", [self class]); +#endif #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif uint8_t *storage = (uint8_t *)self->messageStorage_; - uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset]; + uint32_t *typePtr = (uint32_t *)&storage[fieldDesc->offset]; *typePtr = value; - // proto2: any value counts as having been set; proto3, it - // has to be a non zero value or be in a oneof. - BOOL hasValue = ((syntax == GPBFileSyntaxProto2) - || (value != (uint32_t)0) - || (field->containingOneof_ != NULL)); - GPBSetHasIvarField(self, field, hasValue); + // If the value is zero, then we only count the field as "set" if the field + // shouldn't auto clear on zero. + BOOL hasValue = ((value != (uint32_t)0) + || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } +// clang-format on //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int64, int64_t) // This block of code is generated, do not edit it directly. +// clang-format off int64_t GPBGetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeInt64), + @"Attempting to get value of int64_t from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; int64_t *typePtr = (int64_t *)&storage[field->description_->offset]; @@ -828,42 +981,65 @@ void GPBSetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field, int64_t value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetInt64IvarWithFieldInternal(self, field, value, syntax); +#if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeInt64), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type int64_t.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetInt64IvarWithFieldPrivate(self, field, value); } -void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - int64_t value, - GPBFileSyntax syntax) { +void GPBSetInt64IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + int64_t value) { GPBOneofDescriptor *oneof = field->containingOneof_; + GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMessageFieldDescription *fieldDesc = field->description_; - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } +#if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)", [self class]); +#endif #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif uint8_t *storage = (uint8_t *)self->messageStorage_; - int64_t *typePtr = (int64_t *)&storage[field->description_->offset]; + int64_t *typePtr = (int64_t *)&storage[fieldDesc->offset]; *typePtr = value; - // proto2: any value counts as having been set; proto3, it - // has to be a non zero value or be in a oneof. - BOOL hasValue = ((syntax == GPBFileSyntaxProto2) - || (value != (int64_t)0) - || (field->containingOneof_ != NULL)); - GPBSetHasIvarField(self, field, hasValue); + // If the value is zero, then we only count the field as "set" if the field + // shouldn't auto clear on zero. + BOOL hasValue = ((value != (int64_t)0) + || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } +// clang-format on //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt64, uint64_t) // This block of code is generated, do not edit it directly. +// clang-format off uint64_t GPBGetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeUInt64), + @"Attempting to get value of uint64_t from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset]; @@ -878,42 +1054,65 @@ void GPBSetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field, uint64_t value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax); +#if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeUInt64), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type uint64_t.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetUInt64IvarWithFieldPrivate(self, field, value); } -void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - uint64_t value, - GPBFileSyntax syntax) { +void GPBSetUInt64IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + uint64_t value) { GPBOneofDescriptor *oneof = field->containingOneof_; + GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMessageFieldDescription *fieldDesc = field->description_; - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } +#if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)", [self class]); +#endif #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif uint8_t *storage = (uint8_t *)self->messageStorage_; - uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset]; + uint64_t *typePtr = (uint64_t *)&storage[fieldDesc->offset]; *typePtr = value; - // proto2: any value counts as having been set; proto3, it - // has to be a non zero value or be in a oneof. - BOOL hasValue = ((syntax == GPBFileSyntaxProto2) - || (value != (uint64_t)0) - || (field->containingOneof_ != NULL)); - GPBSetHasIvarField(self, field, hasValue); + // If the value is zero, then we only count the field as "set" if the field + // shouldn't auto clear on zero. + BOOL hasValue = ((value != (uint64_t)0) + || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } +// clang-format on //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Float, float) // This block of code is generated, do not edit it directly. +// clang-format off float GPBGetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeFloat), + @"Attempting to get value of float from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; float *typePtr = (float *)&storage[field->description_->offset]; @@ -928,42 +1127,65 @@ void GPBSetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field, float value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetFloatIvarWithFieldInternal(self, field, value, syntax); +#if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeFloat), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type float.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetFloatIvarWithFieldPrivate(self, field, value); } -void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - float value, - GPBFileSyntax syntax) { +void GPBSetFloatIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + float value) { GPBOneofDescriptor *oneof = field->containingOneof_; + GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMessageFieldDescription *fieldDesc = field->description_; - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } +#if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)", [self class]); +#endif #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif uint8_t *storage = (uint8_t *)self->messageStorage_; - float *typePtr = (float *)&storage[field->description_->offset]; + float *typePtr = (float *)&storage[fieldDesc->offset]; *typePtr = value; - // proto2: any value counts as having been set; proto3, it - // has to be a non zero value or be in a oneof. - BOOL hasValue = ((syntax == GPBFileSyntaxProto2) - || (value != (float)0) - || (field->containingOneof_ != NULL)); - GPBSetHasIvarField(self, field, hasValue); + // If the value is zero, then we only count the field as "set" if the field + // shouldn't auto clear on zero. + BOOL hasValue = ((value != (float)0) + || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } +// clang-format on //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Double, double) // This block of code is generated, do not edit it directly. +// clang-format off double GPBGetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeDouble), + @"Attempting to get value of double from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; double *typePtr = (double *)&storage[field->description_->offset]; @@ -978,47 +1200,67 @@ void GPBSetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field, double value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax); +#if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeDouble), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type double.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetDoubleIvarWithFieldPrivate(self, field, value); } -void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - double value, - GPBFileSyntax syntax) { +void GPBSetDoubleIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + double value) { GPBOneofDescriptor *oneof = field->containingOneof_; + GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMessageFieldDescription *fieldDesc = field->description_; - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } +#if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)", [self class]); +#endif #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif uint8_t *storage = (uint8_t *)self->messageStorage_; - double *typePtr = (double *)&storage[field->description_->offset]; + double *typePtr = (double *)&storage[fieldDesc->offset]; *typePtr = value; - // proto2: any value counts as having been set; proto3, it - // has to be a non zero value or be in a oneof. - BOOL hasValue = ((syntax == GPBFileSyntaxProto2) - || (value != (double)0) - || (field->containingOneof_ != NULL)); - GPBSetHasIvarField(self, field, hasValue); + // If the value is zero, then we only count the field as "set" if the field + // shouldn't auto clear on zero. + BOOL hasValue = ((value != (double)0) + || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } +// clang-format on //%PDDM-EXPAND-END (6 expansions) // Aliases are function calls that are virtually the same. -//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(String, NSString) +//%PDDM-EXPAND IVAR_ALIAS_DEFN_COPY_OBJECT(String, NSString) // This block of code is generated, do not edit it directly. +// clang-format off // Only exists for public api, no core code should use this. NSString *GPBGetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeString), + @"Attempting to get value of NSString from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif return (NSString *)GPBGetObjectIvarWithField(self, field); } @@ -1026,15 +1268,33 @@ void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, void GPBSetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field, NSString *value) { - GPBSetObjectIvarWithField(self, field, (id)value); +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeString), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type NSString.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetCopyObjectIvarWithField(self, field, (id)value); } -//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Bytes, NSData) +// clang-format on +//%PDDM-EXPAND IVAR_ALIAS_DEFN_COPY_OBJECT(Bytes, NSData) // This block of code is generated, do not edit it directly. +// clang-format off // Only exists for public api, no core code should use this. NSData *GPBGetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeBytes), + @"Attempting to get value of NSData from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif return (NSData *)GPBGetObjectIvarWithField(self, field); } @@ -1042,15 +1302,33 @@ void GPBSetMessageStringField(GPBMessage *self, void GPBSetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field, NSData *value) { - GPBSetObjectIvarWithField(self, field, (id)value); +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeBytes), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type NSData.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif + GPBSetCopyObjectIvarWithField(self, field, (id)value); } +// clang-format on //%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Message, GPBMessage) // This block of code is generated, do not edit it directly. +// clang-format off // Only exists for public api, no core code should use this. GPBMessage *GPBGetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeMessage), + @"Attempting to get value of GPBMessage from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif return (GPBMessage *)GPBGetObjectIvarWithField(self, field); } @@ -1058,15 +1336,33 @@ void GPBSetMessageBytesField(GPBMessage *self, void GPBSetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeMessage), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type GPBMessage.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif GPBSetObjectIvarWithField(self, field, (id)value); } +// clang-format on //%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Group, GPBMessage) // This block of code is generated, do not edit it directly. +// clang-format off // Only exists for public api, no core code should use this. GPBMessage *GPBGetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeGroup), + @"Attempting to get value of GPBMessage from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif return (GPBMessage *)GPBGetObjectIvarWithField(self, field); } @@ -1074,9 +1370,18 @@ void GPBSetMessageMessageField(GPBMessage *self, void GPBSetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value) { +#if defined(DEBUG) && DEBUG + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), + GPBDataTypeGroup), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type GPBMessage.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); +#endif GPBSetObjectIvarWithField(self, field, (id)value); } +// clang-format on //%PDDM-EXPAND-END (4 expansions) // GPBGetMessageRepeatedField is defined in GPBMessage.m @@ -1137,8 +1442,40 @@ void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id GPBSetObjectIvarWithField(self, field, array); } -#if defined(DEBUG) && DEBUG -static NSString *TypeToStr(GPBDataType dataType) { +static GPBDataType BaseDataType(GPBDataType type) { + switch (type) { + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + return GPBDataTypeInt32; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + return GPBDataTypeUInt32; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + return GPBDataTypeInt64; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + return GPBDataTypeUInt64; + case GPBDataTypeMessage: + case GPBDataTypeGroup: + return GPBDataTypeMessage; + case GPBDataTypeBool: + case GPBDataTypeFloat: + case GPBDataTypeDouble: + case GPBDataTypeBytes: + case GPBDataTypeString: + return type; + } +} + +static BOOL DataTypesEquivalent(GPBDataType type1, GPBDataType type2) { + return BaseDataType(type1) == BaseDataType(type2); +} + +static NSString *TypeToString(GPBDataType dataType) { switch (dataType) { case GPBDataTypeBool: return @"Bool"; @@ -1166,10 +1503,9 @@ void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id case GPBDataTypeGroup: return @"Object"; case GPBDataTypeEnum: - return @"Bool"; + return @"Enum"; } } -#endif // GPBGetMessageMapField is defined in GPBMessage.m @@ -1185,8 +1521,8 @@ void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, if (dictionary) { GPBDataType keyDataType = field.mapKeyDataType; GPBDataType valueDataType = GPBGetFieldDataType(field); - NSString *keyStr = TypeToStr(keyDataType); - NSString *valueStr = TypeToStr(valueDataType); + NSString *keyStr = TypeToString(keyDataType); + NSString *valueStr = TypeToString(valueDataType); if (keyDataType == GPBDataTypeString) { keyStr = @"String"; } @@ -1216,8 +1552,11 @@ void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) { Protocol *protocol = objc_getProtocol(GPBStringifySymbol(GPBMessageSignatureProtocol)); + NSCAssert(protocol, @"Missing GPBMessageSignatureProtocol"); struct objc_method_description description = protocol_getMethodDescription(protocol, selector, NO, instanceSel); + NSCAssert(description.name != Nil && description.types != nil, + @"Missing method for selector %@", NSStringFromSelector(selector)); return description.types; } @@ -1564,7 +1903,7 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, // Not there yet. continue; } - if (fieldNumber > end) { + if (fieldNumber >= end) { // Done. break; } @@ -1648,10 +1987,10 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, } // switch(extDataType) - } // for(numValues) + // End the line. + [toStr appendFormat:@"%@\n", lineEnding]; - // End the line. - [toStr appendFormat:@"%@\n", lineEnding]; + } // for(numValues) } // for..in(activeExtensions) } @@ -1891,8 +2230,36 @@ static int32_t ReadRawVarint32FromData(const uint8_t **data) { return result; } +#pragma mark Legacy methods old generated code calls + +// Shim from the older generated code into the runtime. +void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value, + GPBFileSyntax syntax) { +#pragma unused(syntax) + GPBSetMessageInt32Field(self, field, value); +} + +void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) { +#pragma unused(fieldNumberNotToClear) + #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof, + @"OneofDescriptor %@ doesn't appear to be for %@ messages.", + oneof.name, [self class]); + GPBFieldDescriptor *firstField = oneof->fields_[0]; + NSCAssert(firstField->description_->hasIndex == oneofHasIndex, + @"Internal error, oneofHasIndex (%d) doesn't match (%d).", + firstField->description_->hasIndex, oneofHasIndex); + #endif + GPBMaybeClearOneofPrivate(self, oneof, oneofHasIndex, 0); +} + #pragma clang diagnostic pop +#pragma mark Misc Helpers + BOOL GPBClassHasSel(Class aClass, SEL sel) { // NOTE: We have to use class_copyMethodList, all other runtime method // lookups actually also resolve the method implementation and this @@ -1911,13 +2278,3 @@ BOOL GPBClassHasSel(Class aClass, SEL sel) { free(methodList); return result; } - -#pragma mark - GPBMessageSignatureProtocol - -// A series of selectors that are used solely to get @encoding values -// for them by the dynamic protobuf runtime code. An object using the protocol -// needs to be declared for the protocol to be valid at runtime. -@interface GPBMessageSignatureProtocol : NSObject -@end -@implementation GPBMessageSignatureProtocol -@end diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h index 16859d4875345..3d3d7349ec786 100644 --- a/objectivec/GPBUtilities_PackagePrivate.h +++ b/objectivec/GPBUtilities_PackagePrivate.h @@ -35,14 +35,23 @@ #import "GPBDescriptor_PackagePrivate.h" // Macros for stringifying library symbols. These are used in the generated -// PB descriptor classes wherever a library symbol name is represented as a -// string. See README.google for more information. +// GPB descriptor classes wherever a library symbol name is represented as a +// string. #define GPBStringify(S) #S #define GPBStringifySymbol(S) GPBStringify(S) #define GPBNSStringify(S) @#S #define GPBNSStringifySymbol(S) GPBNSStringify(S) +// Macros for generating a Class from a class name. These are used in +// the generated GPB descriptor classes wherever an Objective C class +// reference is needed for a generated class. +#define GPBObjCClassSymbol(name) OBJC_CLASS_$_##name +#define GPBObjCClass(name) \ + ((__bridge Class)&(GPBObjCClassSymbol(name))) +#define GPBObjCClassDeclaration(name) \ + extern const GPBObjcClass_t GPBObjCClassSymbol(name) + // Constant to internally mark when there is no has bit. #define GPBNoHasBit INT32_MAX @@ -71,27 +80,31 @@ GPB_INLINE void GPBDebugCheckRuntimeVersion() { // Conversion functions for de/serializing floating point types. GPB_INLINE int64_t GPBConvertDoubleToInt64(double v) { - union { double f; int64_t i; } u; - u.f = v; - return u.i; + GPBInternalCompileAssert(sizeof(double) == sizeof(int64_t), double_not_64_bits); + int64_t result; + memcpy(&result, &v, sizeof(result)); + return result; } GPB_INLINE int32_t GPBConvertFloatToInt32(float v) { - union { float f; int32_t i; } u; - u.f = v; - return u.i; + GPBInternalCompileAssert(sizeof(float) == sizeof(int32_t), float_not_32_bits); + int32_t result; + memcpy(&result, &v, sizeof(result)); + return result; } GPB_INLINE double GPBConvertInt64ToDouble(int64_t v) { - union { double f; int64_t i; } u; - u.i = v; - return u.f; + GPBInternalCompileAssert(sizeof(double) == sizeof(int64_t), double_not_64_bits); + double result; + memcpy(&result, &v, sizeof(result)); + return result; } GPB_INLINE float GPBConvertInt32ToFloat(int32_t v) { - union { float f; int32_t i; } u; - u.i = v; - return u.f; + GPBInternalCompileAssert(sizeof(float) == sizeof(int32_t), float_not_32_bits); + float result; + memcpy(&result, &v, sizeof(result)); + return result; } GPB_INLINE int32_t GPBLogicalRightShift32(int32_t value, int32_t spaces) { @@ -124,7 +137,7 @@ GPB_INLINE int64_t GPBDecodeZigZag64(uint64_t n) { // thus always taking 10 bytes on the wire.) GPB_INLINE uint32_t GPBEncodeZigZag32(int32_t n) { // Note: the right-shift must be arithmetic - return (uint32_t)((n << 1) ^ (n >> 31)); + return ((uint32_t)n << 1) ^ (uint32_t)(n >> 31); } // Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers @@ -133,7 +146,7 @@ GPB_INLINE uint32_t GPBEncodeZigZag32(int32_t n) { // thus always taking 10 bytes on the wire.) GPB_INLINE uint64_t GPBEncodeZigZag64(int64_t n) { // Note: the right-shift must be arithmetic - return (uint64_t)((n << 1) ^ (n >> 63)); + return ((uint64_t)n << 1) ^ (uint64_t)(n >> 63); } #pragma clang diagnostic push @@ -193,104 +206,89 @@ GPBGetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field) { GPBMessageFieldDescription *fieldDesc = field->description_; return GPBGetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number); } -GPB_INLINE void GPBSetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field, - BOOL value) { - GPBMessageFieldDescription *fieldDesc = field->description_; - GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, value); -} - -void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, - int32_t oneofHasIndex, uint32_t fieldNumberNotToClear); #pragma clang diagnostic pop //%PDDM-DEFINE GPB_IVAR_SET_DECL(NAME, TYPE) -//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self, -//% NAME$S GPBFieldDescriptor *field, -//% NAME$S TYPE value, -//% NAME$S GPBFileSyntax syntax); +//%void GPBSet##NAME##IvarWithFieldPrivate(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE value); //%PDDM-EXPAND GPB_IVAR_SET_DECL(Bool, BOOL) // This block of code is generated, do not edit it directly. +// clang-format off -void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - BOOL value, - GPBFileSyntax syntax); +void GPBSetBoolIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + BOOL value); +// clang-format on //%PDDM-EXPAND GPB_IVAR_SET_DECL(Int32, int32_t) // This block of code is generated, do not edit it directly. +// clang-format off -void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value, - GPBFileSyntax syntax); +void GPBSetInt32IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value); +// clang-format on //%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt32, uint32_t) // This block of code is generated, do not edit it directly. +// clang-format off -void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - uint32_t value, - GPBFileSyntax syntax); +void GPBSetUInt32IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + uint32_t value); +// clang-format on //%PDDM-EXPAND GPB_IVAR_SET_DECL(Int64, int64_t) // This block of code is generated, do not edit it directly. +// clang-format off -void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - int64_t value, - GPBFileSyntax syntax); +void GPBSetInt64IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + int64_t value); +// clang-format on //%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt64, uint64_t) // This block of code is generated, do not edit it directly. +// clang-format off -void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - uint64_t value, - GPBFileSyntax syntax); +void GPBSetUInt64IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + uint64_t value); +// clang-format on //%PDDM-EXPAND GPB_IVAR_SET_DECL(Float, float) // This block of code is generated, do not edit it directly. +// clang-format off -void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - float value, - GPBFileSyntax syntax); +void GPBSetFloatIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + float value); +// clang-format on //%PDDM-EXPAND GPB_IVAR_SET_DECL(Double, double) // This block of code is generated, do not edit it directly. +// clang-format off -void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - double value, - GPBFileSyntax syntax); -//%PDDM-EXPAND GPB_IVAR_SET_DECL(Enum, int32_t) -// This block of code is generated, do not edit it directly. - -void GPBSetEnumIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value, - GPBFileSyntax syntax); -//%PDDM-EXPAND-END (8 expansions) +void GPBSetDoubleIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + double value); +// clang-format on +//%PDDM-EXPAND-END (7 expansions) -int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - GPBFileSyntax syntax); +void GPBSetEnumIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value); id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); -void GPBSetObjectIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, id value, - GPBFileSyntax syntax); -void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - id __attribute__((ns_consumed)) - value, - GPBFileSyntax syntax); +void GPBSetObjectIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, id value); +void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + id __attribute__((ns_consumed)) + value); // GPBGetObjectIvarWithField will automatically create the field (message) if // it doesn't exist. GPBGetObjectIvarWithFieldNoAutocreate will return nil. id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self, GPBFieldDescriptor *field); -void GPBSetAutocreatedRetainedObjectIvarWithField( - GPBMessage *self, GPBFieldDescriptor *field, - id __attribute__((ns_consumed)) value); - // Clears and releases the autocreated message ivar, if it's autocreated. If // it's not set as autocreated, this method does nothing. void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, @@ -302,14 +300,24 @@ void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel); // Helper for text format name encoding. -// decodeData is the data describing the sepecial decodes. +// decodeData is the data describing the special decodes. // key and inputString are the input that needs decoding. NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, NSString *inputString); + +// Shims from the older generated code into the runtime. +void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value, + GPBFileSyntax syntax); +void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, uint32_t fieldNumberNotToClear); + // A series of selectors that are used solely to get @encoding values // for them by the dynamic protobuf runtime code. See -// GPBMessageEncodingForSelector for details. +// GPBMessageEncodingForSelector for details. GPBRootObject conforms to +// the protocol so that it is encoded in the Objective C runtime. @protocol GPBMessageSignatureProtocol @optional diff --git a/objectivec/GPBWellKnownTypes.h b/objectivec/GPBWellKnownTypes.h index 04df417889227..784ba9ff99e85 100644 --- a/objectivec/GPBWellKnownTypes.h +++ b/objectivec/GPBWellKnownTypes.h @@ -37,13 +37,13 @@ #endif #if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import - #import - #import + #import + #import + #import #else - #import "google/protobuf/Any.pbobjc.h" - #import "google/protobuf/Duration.pbobjc.h" - #import "google/protobuf/Timestamp.pbobjc.h" + #import "GPBAny.pbobjc.h" + #import "GPBDuration.pbobjc.h" + #import "GPBTimestamp.pbobjc.h" #endif NS_ASSUME_NONNULL_BEGIN diff --git a/objectivec/GPBWrappers.pbobjc.h b/objectivec/GPBWrappers.pbobjc.h new file mode 100644 index 0000000000000..713bafc89b025 --- /dev/null +++ b/objectivec/GPBWrappers.pbobjc.h @@ -0,0 +1,219 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/wrappers.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import + #import + #import +#else + #import "GPBDescriptor.h" + #import "GPBMessage.h" + #import "GPBRootObject.h" +#endif + +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 +#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. +#endif +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. +#endif + +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +CF_EXTERN_C_BEGIN + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - GPBWrappersRoot + +/** + * Exposes the extension registry for this file. + * + * The base class provides: + * @code + * + (GPBExtensionRegistry *)extensionRegistry; + * @endcode + * which is a @c GPBExtensionRegistry that includes all the extensions defined by + * this file and all files that it depends on. + **/ +GPB_FINAL @interface GPBWrappersRoot : GPBRootObject +@end + +#pragma mark - GPBDoubleValue + +typedef GPB_ENUM(GPBDoubleValue_FieldNumber) { + GPBDoubleValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `double`. + * + * The JSON representation for `DoubleValue` is JSON number. + **/ +GPB_FINAL @interface GPBDoubleValue : GPBMessage + +/** The double value. */ +@property(nonatomic, readwrite) double value; + +@end + +#pragma mark - GPBFloatValue + +typedef GPB_ENUM(GPBFloatValue_FieldNumber) { + GPBFloatValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `float`. + * + * The JSON representation for `FloatValue` is JSON number. + **/ +GPB_FINAL @interface GPBFloatValue : GPBMessage + +/** The float value. */ +@property(nonatomic, readwrite) float value; + +@end + +#pragma mark - GPBInt64Value + +typedef GPB_ENUM(GPBInt64Value_FieldNumber) { + GPBInt64Value_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `int64`. + * + * The JSON representation for `Int64Value` is JSON string. + **/ +GPB_FINAL @interface GPBInt64Value : GPBMessage + +/** The int64 value. */ +@property(nonatomic, readwrite) int64_t value; + +@end + +#pragma mark - GPBUInt64Value + +typedef GPB_ENUM(GPBUInt64Value_FieldNumber) { + GPBUInt64Value_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `uint64`. + * + * The JSON representation for `UInt64Value` is JSON string. + **/ +GPB_FINAL @interface GPBUInt64Value : GPBMessage + +/** The uint64 value. */ +@property(nonatomic, readwrite) uint64_t value; + +@end + +#pragma mark - GPBInt32Value + +typedef GPB_ENUM(GPBInt32Value_FieldNumber) { + GPBInt32Value_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `int32`. + * + * The JSON representation for `Int32Value` is JSON number. + **/ +GPB_FINAL @interface GPBInt32Value : GPBMessage + +/** The int32 value. */ +@property(nonatomic, readwrite) int32_t value; + +@end + +#pragma mark - GPBUInt32Value + +typedef GPB_ENUM(GPBUInt32Value_FieldNumber) { + GPBUInt32Value_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `uint32`. + * + * The JSON representation for `UInt32Value` is JSON number. + **/ +GPB_FINAL @interface GPBUInt32Value : GPBMessage + +/** The uint32 value. */ +@property(nonatomic, readwrite) uint32_t value; + +@end + +#pragma mark - GPBBoolValue + +typedef GPB_ENUM(GPBBoolValue_FieldNumber) { + GPBBoolValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `bool`. + * + * The JSON representation for `BoolValue` is JSON `true` and `false`. + **/ +GPB_FINAL @interface GPBBoolValue : GPBMessage + +/** The bool value. */ +@property(nonatomic, readwrite) BOOL value; + +@end + +#pragma mark - GPBStringValue + +typedef GPB_ENUM(GPBStringValue_FieldNumber) { + GPBStringValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `string`. + * + * The JSON representation for `StringValue` is JSON string. + **/ +GPB_FINAL @interface GPBStringValue : GPBMessage + +/** The string value. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *value; + +@end + +#pragma mark - GPBBytesValue + +typedef GPB_ENUM(GPBBytesValue_FieldNumber) { + GPBBytesValue_FieldNumber_Value = 1, +}; + +/** + * Wrapper message for `bytes`. + * + * The JSON representation for `BytesValue` is JSON string. + **/ +GPB_FINAL @interface GPBBytesValue : GPBMessage + +/** The bytes value. */ +@property(nonatomic, readwrite, copy, null_resettable) NSData *value; + +@end + +NS_ASSUME_NONNULL_END + +CF_EXTERN_C_END + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/GPBWrappers.pbobjc.m b/objectivec/GPBWrappers.pbobjc.m new file mode 100644 index 0000000000000..32201d4d8305a --- /dev/null +++ b/objectivec/GPBWrappers.pbobjc.m @@ -0,0 +1,457 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/wrappers.proto + +// This CPP symbol can be defined to use imports that match up to the framework +// imports needed when using CocoaPods. +#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) + #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBProtocolBuffers_RuntimeSupport.h" +#endif + +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import +#else + #import "GPBWrappers.pbobjc.h" +#endif +// @@protoc_insertion_point(imports) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#pragma mark - GPBWrappersRoot + +@implementation GPBWrappersRoot + +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + +@end + +#pragma mark - GPBWrappersRoot_FileDescriptor + +static GPBFileDescriptor *GPBWrappersRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBDoubleValue + +@implementation GPBDoubleValue + +@dynamic value; + +typedef struct GPBDoubleValue__storage_ { + uint32_t _has_storage_[1]; + double value; +} GPBDoubleValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.clazz = Nil, + .number = GPBDoubleValue_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBDoubleValue__storage_, value), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeDouble, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBDoubleValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBDoubleValue__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBFloatValue + +@implementation GPBFloatValue + +@dynamic value; + +typedef struct GPBFloatValue__storage_ { + uint32_t _has_storage_[1]; + float value; +} GPBFloatValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.clazz = Nil, + .number = GPBFloatValue_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBFloatValue__storage_, value), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeFloat, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFloatValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBFloatValue__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBInt64Value + +@implementation GPBInt64Value + +@dynamic value; + +typedef struct GPBInt64Value__storage_ { + uint32_t _has_storage_[1]; + int64_t value; +} GPBInt64Value__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.clazz = Nil, + .number = GPBInt64Value_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBInt64Value__storage_, value), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBInt64Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBInt64Value__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBUInt64Value + +@implementation GPBUInt64Value + +@dynamic value; + +typedef struct GPBUInt64Value__storage_ { + uint32_t _has_storage_[1]; + uint64_t value; +} GPBUInt64Value__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.clazz = Nil, + .number = GPBUInt64Value_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBUInt64Value__storage_, value), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeUInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBUInt64Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBUInt64Value__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBInt32Value + +@implementation GPBInt32Value + +@dynamic value; + +typedef struct GPBInt32Value__storage_ { + uint32_t _has_storage_[1]; + int32_t value; +} GPBInt32Value__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.clazz = Nil, + .number = GPBInt32Value_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBInt32Value__storage_, value), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBInt32Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBInt32Value__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBUInt32Value + +@implementation GPBUInt32Value + +@dynamic value; + +typedef struct GPBUInt32Value__storage_ { + uint32_t _has_storage_[1]; + uint32_t value; +} GPBUInt32Value__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.clazz = Nil, + .number = GPBUInt32Value_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBUInt32Value__storage_, value), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeUInt32, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBUInt32Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBUInt32Value__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBBoolValue + +@implementation GPBBoolValue + +@dynamic value; + +typedef struct GPBBoolValue__storage_ { + uint32_t _has_storage_[1]; +} GPBBoolValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.clazz = Nil, + .number = GPBBoolValue_FieldNumber_Value, + .hasIndex = 0, + .offset = 1, // Stored in _has_storage_ to save space. + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBBoolValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBBoolValue__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBStringValue + +@implementation GPBStringValue + +@dynamic value; + +typedef struct GPBStringValue__storage_ { + uint32_t _has_storage_[1]; + NSString *value; +} GPBStringValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.clazz = Nil, + .number = GPBStringValue_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBStringValue__storage_, value), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBStringValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBStringValue__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GPBBytesValue + +@implementation GPBBytesValue + +@dynamic value; + +typedef struct GPBBytesValue__storage_ { + uint32_t _has_storage_[1]; + NSData *value; +} GPBBytesValue__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .dataTypeSpecific.clazz = Nil, + .number = GPBBytesValue_FieldNumber_Value, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GPBBytesValue__storage_, value), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBytes, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBBytesValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GPBBytesValue__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + + +#pragma clang diagnostic pop + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj index cd7fcc9e30ce5..365fdc30ca07c 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj @@ -35,8 +35,34 @@ 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; }; 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; }; 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 8BFF9D1A23AD582300E63E32 /* GPBMessageTests+ClassNames.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */; }; F401DC2D1A8D444600FCC765 /* GPBArray.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC2B1A8D444600FCC765 /* GPBArray.m */; }; F401DC331A8E5C0200FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */; }; + F40EE4AB206BF8B90071091A /* GPBCompileTest01.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE488206BF8B00071091A /* GPBCompileTest01.m */; }; + F40EE4AC206BF8B90071091A /* GPBCompileTest02.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE481206BF8AE0071091A /* GPBCompileTest02.m */; }; + F40EE4AD206BF8B90071091A /* GPBCompileTest03.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE491206BF8B10071091A /* GPBCompileTest03.m */; }; + F40EE4AE206BF8B90071091A /* GPBCompileTest04.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE47E206BF8AE0071091A /* GPBCompileTest04.m */; }; + F40EE4AF206BF8B90071091A /* GPBCompileTest05.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE47F206BF8AE0071091A /* GPBCompileTest05.m */; }; + F40EE4B0206BF8B90071091A /* GPBCompileTest06.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE492206BF8B10071091A /* GPBCompileTest06.m */; }; + F40EE4B1206BF8B90071091A /* GPBCompileTest07.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE480206BF8AE0071091A /* GPBCompileTest07.m */; }; + F40EE4B2206BF8B90071091A /* GPBCompileTest08.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE47D206BF8AD0071091A /* GPBCompileTest08.m */; }; + F40EE4B3206BF8B90071091A /* GPBCompileTest09.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE484206BF8AF0071091A /* GPBCompileTest09.m */; }; + F40EE4B4206BF8B90071091A /* GPBCompileTest10.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE48C206BF8B00071091A /* GPBCompileTest10.m */; }; + F40EE4B5206BF8B90071091A /* GPBCompileTest11.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE493206BF8B20071091A /* GPBCompileTest11.m */; }; + F40EE4B6206BF8B90071091A /* GPBCompileTest12.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE490206BF8B10071091A /* GPBCompileTest12.m */; }; + F40EE4B7206BF8B90071091A /* GPBCompileTest13.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE483206BF8AF0071091A /* GPBCompileTest13.m */; }; + F40EE4B8206BF8B90071091A /* GPBCompileTest14.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE48F206BF8B10071091A /* GPBCompileTest14.m */; }; + F40EE4B9206BF8B90071091A /* GPBCompileTest15.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE489206BF8B00071091A /* GPBCompileTest15.m */; }; + F40EE4BA206BF8B90071091A /* GPBCompileTest16.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE48B206BF8B00071091A /* GPBCompileTest16.m */; }; + F40EE4BB206BF8B90071091A /* GPBCompileTest17.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE48D206BF8B00071091A /* GPBCompileTest17.m */; }; + F40EE4BC206BF8B90071091A /* GPBCompileTest18.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE48E206BF8B10071091A /* GPBCompileTest18.m */; }; + F40EE4BD206BF8B90071091A /* GPBCompileTest19.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE482206BF8AF0071091A /* GPBCompileTest19.m */; }; + F40EE4BE206BF8B90071091A /* GPBCompileTest20.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE485206BF8AF0071091A /* GPBCompileTest20.m */; }; + F40EE4BF206BF8B90071091A /* GPBCompileTest21.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE486206BF8AF0071091A /* GPBCompileTest21.m */; }; + F40EE4C0206BF8B90071091A /* GPBCompileTest22.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE48A206BF8B00071091A /* GPBCompileTest22.m */; }; + F40EE4C1206BF8B90071091A /* GPBCompileTest23.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE487206BF8B00071091A /* GPBCompileTest23.m */; }; + F40EE50B206C06640071091A /* GPBCompileTest24.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE508206C06440071091A /* GPBCompileTest24.m */; }; + F40EE50C206C06640071091A /* GPBCompileTest25.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE507206C06440071091A /* GPBCompileTest25.m */; }; F41C175D1833D3310064ED4D /* GPBPerfTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F41C175C1833D3310064ED4D /* GPBPerfTests.m */; }; F4353D1D1AB8822D005A6198 /* GPBDescriptorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D1C1AB8822D005A6198 /* GPBDescriptorTests.m */; }; F4353D231ABB1537005A6198 /* GPBDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D211ABB1537005A6198 /* GPBDictionary.m */; }; @@ -55,18 +81,19 @@ F4584D821ECCB52A00803AB6 /* GPBExtensionRegistryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F4584D7E1ECCB38900803AB6 /* GPBExtensionRegistryTest.m */; }; F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */ = {isa = PBXBuildFile; fileRef = F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */; }; F45E57C71AE6DC6A000B7D99 /* text_format_map_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F45E57C61AE6DC6A000B7D99 /* text_format_map_unittest_data.txt */; }; - F47476E51D21A524007C7B1A /* Duration.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248D41A92826400BC1EC6 /* Duration.pbobjc.m */; }; - F47476E61D21A524007C7B1A /* Timestamp.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248D61A92826400BC1EC6 /* Timestamp.pbobjc.m */; }; + F47CF92B23D9006000C7B24C /* GPBStruct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF91F23D9005F00C7B24C /* GPBStruct.pbobjc.m */; }; + F47CF92F23D9006000C7B24C /* GPBSourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF92323D9006000C7B24C /* GPBSourceContext.pbobjc.m */; }; + F47CF93123D9006000C7B24C /* GPBType.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF92523D9006000C7B24C /* GPBType.pbobjc.m */; }; + F47CF93223D9006000C7B24C /* GPBWrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF92623D9006000C7B24C /* GPBWrappers.pbobjc.m */; }; + F47CF93423D9006000C7B24C /* GPBFieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF92823D9006000C7B24C /* GPBFieldMask.pbobjc.m */; }; + F47CF93523D9006000C7B24C /* GPBTimestamp.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF92923D9006000C7B24C /* GPBTimestamp.pbobjc.m */; }; + F47CF94123D902D500C7B24C /* GPBEmpty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF93923D902D500C7B24C /* GPBEmpty.pbobjc.m */; }; + F47CF94223D902D500C7B24C /* GPBApi.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF93A23D902D500C7B24C /* GPBApi.pbobjc.m */; }; + F47CF94323D902D500C7B24C /* GPBAny.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF93B23D902D500C7B24C /* GPBAny.pbobjc.m */; }; + F47CF94623D902D500C7B24C /* GPBDuration.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF93E23D902D500C7B24C /* GPBDuration.pbobjc.m */; }; F4B51B1E1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4B51B1D1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm */; }; F4C4B9E41E1D976300D3B61D /* GPBDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C4B9E21E1D974F00D3B61D /* GPBDictionaryTests.m */; }; - F4E675971B21D0000054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675871B21D0000054530B /* Any.pbobjc.m */; }; - F4E675991B21D0000054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675891B21D0000054530B /* Api.pbobjc.m */; }; - F4E6759B1B21D0000054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758B1B21D0000054530B /* Empty.pbobjc.m */; }; - F4E6759D1B21D0000054530B /* FieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */; }; - F4E6759F1B21D0000054530B /* SourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */; }; - F4E675A11B21D0000054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675911B21D0000054530B /* Struct.pbobjc.m */; }; - F4E675A31B21D0000054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675931B21D0000054530B /* Type.pbobjc.m */; }; - F4E675A51B21D0000054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675951B21D0000054530B /* Wrappers.pbobjc.m */; }; + F4F53F8A219CC4F2001EABF4 /* text_format_extensions_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F4F53F89219CC4F2001EABF4 /* text_format_extensions_unittest_data.txt */; }; F4F8D8831D789FD9002CE128 /* GPBUnittestProtos2.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F8D8811D789FCE002CE128 /* GPBUnittestProtos2.m */; }; /* End PBXBuildFile section */ @@ -124,15 +151,11 @@ 8B09AAF614B663A7007B4184 /* unittest_objc.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc.proto; sourceTree = ""; }; 8B210CCD159383D60032D72D /* golden_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_message; sourceTree = ""; }; 8B210CCF159386920032D72D /* golden_packed_fields_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_packed_fields_message; sourceTree = ""; }; - 8B4248B81A8C254000BC1EC6 /* protobuf */ = {isa = PBXFileReference; lastKnownFileType = text; name = protobuf; path = ../../Intermediates/ProtocolBuffers_OSX.build/DerivedSources/protos/google/protobuf; sourceTree = BUILT_PRODUCTS_DIR; }; + 8B35468421A616F6000BD30D /* unittest_objc_options.proto */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.protobuf; path = unittest_objc_options.proto; sourceTree = ""; }; 8B4248B91A8C256900BC1EC6 /* UnitTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UnitTests-Bridging-Header.h"; sourceTree = ""; }; 8B4248BA1A8C256A00BC1EC6 /* GPBSwiftTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GPBSwiftTests.swift; sourceTree = ""; }; 8B4248CF1A927E1500BC1EC6 /* GPBWellKnownTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWellKnownTypes.h; sourceTree = ""; }; 8B4248D01A927E1500BC1EC6 /* GPBWellKnownTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWellKnownTypes.m; sourceTree = ""; }; - 8B4248D31A92826400BC1EC6 /* Duration.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Duration.pbobjc.h; path = google/protobuf/Duration.pbobjc.h; sourceTree = ""; }; - 8B4248D41A92826400BC1EC6 /* Duration.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Duration.pbobjc.m; path = google/protobuf/Duration.pbobjc.m; sourceTree = ""; }; - 8B4248D51A92826400BC1EC6 /* Timestamp.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Timestamp.pbobjc.h; path = google/protobuf/Timestamp.pbobjc.h; sourceTree = ""; }; - 8B4248D61A92826400BC1EC6 /* Timestamp.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Timestamp.pbobjc.m; path = google/protobuf/Timestamp.pbobjc.m; sourceTree = ""; }; 8B4248DB1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWellKnownTypesTest.m; sourceTree = ""; }; 8B42494C1A92A16600BC1EC6 /* duration.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = duration.proto; path = ../src/google/protobuf/duration.proto; sourceTree = ""; }; 8B42494D1A92A16600BC1EC6 /* timestamp.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = timestamp.proto; path = ../src/google/protobuf/timestamp.proto; sourceTree = ""; }; @@ -155,9 +178,35 @@ 8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = ""; }; 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = ""; }; 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = ""; }; + 8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = ""; }; F401DC2A1A8D444600FCC765 /* GPBArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBArray.h; sourceTree = ""; }; F401DC2B1A8D444600FCC765 /* GPBArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArray.m; sourceTree = ""; }; F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = ""; }; + F40EE47D206BF8AD0071091A /* GPBCompileTest08.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest08.m; sourceTree = ""; }; + F40EE47E206BF8AE0071091A /* GPBCompileTest04.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest04.m; sourceTree = ""; }; + F40EE47F206BF8AE0071091A /* GPBCompileTest05.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest05.m; sourceTree = ""; }; + F40EE480206BF8AE0071091A /* GPBCompileTest07.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest07.m; sourceTree = ""; }; + F40EE481206BF8AE0071091A /* GPBCompileTest02.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest02.m; sourceTree = ""; }; + F40EE482206BF8AF0071091A /* GPBCompileTest19.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest19.m; sourceTree = ""; }; + F40EE483206BF8AF0071091A /* GPBCompileTest13.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest13.m; sourceTree = ""; }; + F40EE484206BF8AF0071091A /* GPBCompileTest09.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest09.m; sourceTree = ""; }; + F40EE485206BF8AF0071091A /* GPBCompileTest20.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest20.m; sourceTree = ""; }; + F40EE486206BF8AF0071091A /* GPBCompileTest21.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest21.m; sourceTree = ""; }; + F40EE487206BF8B00071091A /* GPBCompileTest23.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest23.m; sourceTree = ""; }; + F40EE488206BF8B00071091A /* GPBCompileTest01.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest01.m; sourceTree = ""; }; + F40EE489206BF8B00071091A /* GPBCompileTest15.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest15.m; sourceTree = ""; }; + F40EE48A206BF8B00071091A /* GPBCompileTest22.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest22.m; sourceTree = ""; }; + F40EE48B206BF8B00071091A /* GPBCompileTest16.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest16.m; sourceTree = ""; }; + F40EE48C206BF8B00071091A /* GPBCompileTest10.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest10.m; sourceTree = ""; }; + F40EE48D206BF8B00071091A /* GPBCompileTest17.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest17.m; sourceTree = ""; }; + F40EE48E206BF8B10071091A /* GPBCompileTest18.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest18.m; sourceTree = ""; }; + F40EE48F206BF8B10071091A /* GPBCompileTest14.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest14.m; sourceTree = ""; }; + F40EE490206BF8B10071091A /* GPBCompileTest12.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest12.m; sourceTree = ""; }; + F40EE491206BF8B10071091A /* GPBCompileTest03.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest03.m; sourceTree = ""; }; + F40EE492206BF8B10071091A /* GPBCompileTest06.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest06.m; sourceTree = ""; }; + F40EE493206BF8B20071091A /* GPBCompileTest11.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest11.m; sourceTree = ""; }; + F40EE507206C06440071091A /* GPBCompileTest25.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest25.m; sourceTree = ""; }; + F40EE508206C06440071091A /* GPBCompileTest24.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest24.m; sourceTree = ""; }; F41C175C1833D3310064ED4D /* GPBPerfTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBPerfTests.m; sourceTree = ""; }; F4353D1C1AB8822D005A6198 /* GPBDescriptorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptorTests.m; sourceTree = ""; }; F4353D201ABB1537005A6198 /* GPBDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBDictionary.h; sourceTree = ""; }; @@ -184,6 +233,26 @@ F4584D7E1ECCB38900803AB6 /* GPBExtensionRegistryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionRegistryTest.m; sourceTree = ""; }; F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionInternals.m; sourceTree = ""; }; F45E57C61AE6DC6A000B7D99 /* text_format_map_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_map_unittest_data.txt; sourceTree = ""; }; + F47CF91F23D9005F00C7B24C /* GPBStruct.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBStruct.pbobjc.m; sourceTree = ""; }; + F47CF92023D9006000C7B24C /* GPBSourceContext.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBSourceContext.pbobjc.h; sourceTree = ""; }; + F47CF92123D9006000C7B24C /* GPBStruct.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBStruct.pbobjc.h; sourceTree = ""; }; + F47CF92223D9006000C7B24C /* GPBFieldMask.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBFieldMask.pbobjc.h; sourceTree = ""; }; + F47CF92323D9006000C7B24C /* GPBSourceContext.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBSourceContext.pbobjc.m; sourceTree = ""; }; + F47CF92423D9006000C7B24C /* GPBTimestamp.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBTimestamp.pbobjc.h; sourceTree = ""; }; + F47CF92523D9006000C7B24C /* GPBType.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBType.pbobjc.m; sourceTree = ""; }; + F47CF92623D9006000C7B24C /* GPBWrappers.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWrappers.pbobjc.m; sourceTree = ""; }; + F47CF92723D9006000C7B24C /* GPBWrappers.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWrappers.pbobjc.h; sourceTree = ""; }; + F47CF92823D9006000C7B24C /* GPBFieldMask.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBFieldMask.pbobjc.m; sourceTree = ""; }; + F47CF92923D9006000C7B24C /* GPBTimestamp.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBTimestamp.pbobjc.m; sourceTree = ""; }; + F47CF92A23D9006000C7B24C /* GPBType.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBType.pbobjc.h; sourceTree = ""; }; + F47CF93723D902D500C7B24C /* GPBAny.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBAny.pbobjc.h; sourceTree = ""; }; + F47CF93823D902D500C7B24C /* GPBEmpty.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBEmpty.pbobjc.h; sourceTree = ""; }; + F47CF93923D902D500C7B24C /* GPBEmpty.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBEmpty.pbobjc.m; sourceTree = ""; }; + F47CF93A23D902D500C7B24C /* GPBApi.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBApi.pbobjc.m; sourceTree = ""; }; + F47CF93B23D902D500C7B24C /* GPBAny.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBAny.pbobjc.m; sourceTree = ""; }; + F47CF93C23D902D500C7B24C /* GPBDuration.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBDuration.pbobjc.h; sourceTree = ""; }; + F47CF93D23D902D500C7B24C /* GPBApi.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBApi.pbobjc.h; sourceTree = ""; }; + F47CF93E23D902D500C7B24C /* GPBDuration.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDuration.pbobjc.m; sourceTree = ""; }; F4AC9E1D1A8BEB3500BD6E83 /* unittest_cycle.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_cycle.proto; sourceTree = ""; }; F4B51B1D1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GPBObjectiveCPlusPlusTest.mm; sourceTree = ""; }; F4B6B8AF1A9CC98000892426 /* GPBUnknownField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField_PackagePrivate.h; sourceTree = ""; }; @@ -192,22 +261,6 @@ F4B6B8B81A9CD1DE00892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = ""; }; F4C4B9E21E1D974F00D3B61D /* GPBDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDictionaryTests.m; sourceTree = ""; }; F4CF31701B162ED800BD9B06 /* unittest_objc_startup.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc_startup.proto; sourceTree = ""; }; - F4E675861B21D0000054530B /* Any.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Any.pbobjc.h; path = google/protobuf/Any.pbobjc.h; sourceTree = ""; }; - F4E675871B21D0000054530B /* Any.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Any.pbobjc.m; path = google/protobuf/Any.pbobjc.m; sourceTree = ""; }; - F4E675881B21D0000054530B /* Api.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Api.pbobjc.h; path = google/protobuf/Api.pbobjc.h; sourceTree = ""; }; - F4E675891B21D0000054530B /* Api.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Api.pbobjc.m; path = google/protobuf/Api.pbobjc.m; sourceTree = ""; }; - F4E6758A1B21D0000054530B /* Empty.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Empty.pbobjc.h; path = google/protobuf/Empty.pbobjc.h; sourceTree = ""; }; - F4E6758B1B21D0000054530B /* Empty.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Empty.pbobjc.m; path = google/protobuf/Empty.pbobjc.m; sourceTree = ""; }; - F4E6758C1B21D0000054530B /* FieldMask.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FieldMask.pbobjc.h; path = google/protobuf/FieldMask.pbobjc.h; sourceTree = ""; }; - F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FieldMask.pbobjc.m; path = google/protobuf/FieldMask.pbobjc.m; sourceTree = ""; }; - F4E6758E1B21D0000054530B /* SourceContext.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SourceContext.pbobjc.h; path = google/protobuf/SourceContext.pbobjc.h; sourceTree = ""; }; - F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SourceContext.pbobjc.m; path = google/protobuf/SourceContext.pbobjc.m; sourceTree = ""; }; - F4E675901B21D0000054530B /* Struct.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Struct.pbobjc.h; path = google/protobuf/Struct.pbobjc.h; sourceTree = ""; }; - F4E675911B21D0000054530B /* Struct.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Struct.pbobjc.m; path = google/protobuf/Struct.pbobjc.m; sourceTree = ""; }; - F4E675921B21D0000054530B /* Type.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Type.pbobjc.h; path = google/protobuf/Type.pbobjc.h; sourceTree = ""; }; - F4E675931B21D0000054530B /* Type.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Type.pbobjc.m; path = google/protobuf/Type.pbobjc.m; sourceTree = ""; }; - F4E675941B21D0000054530B /* Wrappers.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Wrappers.pbobjc.h; path = google/protobuf/Wrappers.pbobjc.h; sourceTree = ""; }; - F4E675951B21D0000054530B /* Wrappers.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Wrappers.pbobjc.m; path = google/protobuf/Wrappers.pbobjc.m; sourceTree = ""; }; F4E675A61B21D05C0054530B /* any.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = any.proto; path = ../src/google/protobuf/any.proto; sourceTree = ""; }; F4E675A71B21D05C0054530B /* api.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = api.proto; path = ../src/google/protobuf/api.proto; sourceTree = ""; }; F4E675A81B21D05C0054530B /* empty.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = empty.proto; path = ../src/google/protobuf/empty.proto; sourceTree = ""; }; @@ -216,6 +269,7 @@ F4E675AB1B21D05C0054530B /* struct.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = struct.proto; path = ../src/google/protobuf/struct.proto; sourceTree = ""; }; F4E675AC1B21D05C0054530B /* type.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = type.proto; path = ../src/google/protobuf/type.proto; sourceTree = ""; }; F4E675AD1B21D05C0054530B /* wrappers.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = wrappers.proto; path = ../src/google/protobuf/wrappers.proto; sourceTree = ""; }; + F4F53F89219CC4F2001EABF4 /* text_format_extensions_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_extensions_unittest_data.txt; sourceTree = ""; }; F4F8D8811D789FCE002CE128 /* GPBUnittestProtos2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos2.m; sourceTree = ""; }; /* End PBXFileReference section */ @@ -288,35 +342,35 @@ 29B97315FDCFA39411CA2CEA /* Generated */ = { isa = PBXGroup; children = ( - F4E675861B21D0000054530B /* Any.pbobjc.h */, - F4E675871B21D0000054530B /* Any.pbobjc.m */, + F47CF93723D902D500C7B24C /* GPBAny.pbobjc.h */, + F47CF93B23D902D500C7B24C /* GPBAny.pbobjc.m */, + F47CF93D23D902D500C7B24C /* GPBApi.pbobjc.h */, + F47CF93A23D902D500C7B24C /* GPBApi.pbobjc.m */, + F47CF93C23D902D500C7B24C /* GPBDuration.pbobjc.h */, + F47CF93E23D902D500C7B24C /* GPBDuration.pbobjc.m */, + F47CF93823D902D500C7B24C /* GPBEmpty.pbobjc.h */, + F47CF93923D902D500C7B24C /* GPBEmpty.pbobjc.m */, + F47CF92223D9006000C7B24C /* GPBFieldMask.pbobjc.h */, + F47CF92823D9006000C7B24C /* GPBFieldMask.pbobjc.m */, + F47CF92023D9006000C7B24C /* GPBSourceContext.pbobjc.h */, + F47CF92323D9006000C7B24C /* GPBSourceContext.pbobjc.m */, + F47CF92123D9006000C7B24C /* GPBStruct.pbobjc.h */, + F47CF91F23D9005F00C7B24C /* GPBStruct.pbobjc.m */, + F47CF92423D9006000C7B24C /* GPBTimestamp.pbobjc.h */, + F47CF92923D9006000C7B24C /* GPBTimestamp.pbobjc.m */, + F47CF92A23D9006000C7B24C /* GPBType.pbobjc.h */, + F47CF92523D9006000C7B24C /* GPBType.pbobjc.m */, + F47CF92723D9006000C7B24C /* GPBWrappers.pbobjc.h */, + F47CF92623D9006000C7B24C /* GPBWrappers.pbobjc.m */, F4E675A61B21D05C0054530B /* any.proto */, - F4E675881B21D0000054530B /* Api.pbobjc.h */, - F4E675891B21D0000054530B /* Api.pbobjc.m */, F4E675A71B21D05C0054530B /* api.proto */, - 8B4248D31A92826400BC1EC6 /* Duration.pbobjc.h */, - 8B4248D41A92826400BC1EC6 /* Duration.pbobjc.m */, 8B42494C1A92A16600BC1EC6 /* duration.proto */, - F4E6758A1B21D0000054530B /* Empty.pbobjc.h */, - F4E6758B1B21D0000054530B /* Empty.pbobjc.m */, F4E675A81B21D05C0054530B /* empty.proto */, F4E675A91B21D05C0054530B /* field_mask.proto */, - F4E6758C1B21D0000054530B /* FieldMask.pbobjc.h */, - F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */, F4E675AA1B21D05C0054530B /* source_context.proto */, - F4E6758E1B21D0000054530B /* SourceContext.pbobjc.h */, - F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */, - F4E675901B21D0000054530B /* Struct.pbobjc.h */, - F4E675911B21D0000054530B /* Struct.pbobjc.m */, F4E675AB1B21D05C0054530B /* struct.proto */, - 8B4248D51A92826400BC1EC6 /* Timestamp.pbobjc.h */, - 8B4248D61A92826400BC1EC6 /* Timestamp.pbobjc.m */, 8B42494D1A92A16600BC1EC6 /* timestamp.proto */, - F4E675921B21D0000054530B /* Type.pbobjc.h */, - F4E675931B21D0000054530B /* Type.pbobjc.m */, F4E675AC1B21D05C0054530B /* type.proto */, - F4E675941B21D0000054530B /* Wrappers.pbobjc.h */, - F4E675951B21D0000054530B /* Wrappers.pbobjc.m */, F4E675AD1B21D05C0054530B /* wrappers.proto */, ); name = Generated; @@ -388,13 +442,37 @@ 7461B6940F94FDDD00A0C422 /* Tests */ = { isa = PBXGroup; children = ( - 8B4248B81A8C254000BC1EC6 /* protobuf */, 8B210CCD159383D60032D72D /* golden_message */, 8B210CCF159386920032D72D /* golden_packed_fields_message */, 8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */, F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */, 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */, 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */, + F40EE488206BF8B00071091A /* GPBCompileTest01.m */, + F40EE481206BF8AE0071091A /* GPBCompileTest02.m */, + F40EE491206BF8B10071091A /* GPBCompileTest03.m */, + F40EE47E206BF8AE0071091A /* GPBCompileTest04.m */, + F40EE47F206BF8AE0071091A /* GPBCompileTest05.m */, + F40EE492206BF8B10071091A /* GPBCompileTest06.m */, + F40EE480206BF8AE0071091A /* GPBCompileTest07.m */, + F40EE47D206BF8AD0071091A /* GPBCompileTest08.m */, + F40EE484206BF8AF0071091A /* GPBCompileTest09.m */, + F40EE48C206BF8B00071091A /* GPBCompileTest10.m */, + F40EE493206BF8B20071091A /* GPBCompileTest11.m */, + F40EE490206BF8B10071091A /* GPBCompileTest12.m */, + F40EE483206BF8AF0071091A /* GPBCompileTest13.m */, + F40EE48F206BF8B10071091A /* GPBCompileTest14.m */, + F40EE489206BF8B00071091A /* GPBCompileTest15.m */, + F40EE48B206BF8B00071091A /* GPBCompileTest16.m */, + F40EE48D206BF8B00071091A /* GPBCompileTest17.m */, + F40EE48E206BF8B10071091A /* GPBCompileTest18.m */, + F40EE482206BF8AF0071091A /* GPBCompileTest19.m */, + F40EE485206BF8AF0071091A /* GPBCompileTest20.m */, + F40EE486206BF8AF0071091A /* GPBCompileTest21.m */, + F40EE48A206BF8B00071091A /* GPBCompileTest22.m */, + F40EE487206BF8B00071091A /* GPBCompileTest23.m */, + F40EE508206C06440071091A /* GPBCompileTest24.m */, + F40EE507206C06440071091A /* GPBCompileTest25.m */, 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */, F4353D1C1AB8822D005A6198 /* GPBDescriptorTests.m */, F4C4B9E21E1D974F00D3B61D /* GPBDictionaryTests.m */, @@ -409,6 +487,7 @@ 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */, F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */, F4487C741AADF7F500531423 /* GPBMessageTests+Runtime.m */, + 8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */, F4487C7E1AAF62CD00531423 /* GPBMessageTests+Serialization.m */, F4B51B1D1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm */, F41C175C1833D3310064ED4D /* GPBPerfTests.m */, @@ -421,6 +500,7 @@ 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */, 8B4248DB1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m */, 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */, + F4F53F89219CC4F2001EABF4 /* text_format_extensions_unittest_data.txt */, F45E57C61AE6DC6A000B7D99 /* text_format_map_unittest_data.txt */, F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */, 8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */, @@ -432,6 +512,7 @@ 8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */, 8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */, 8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */, + 8B35468421A616F6000BD30D /* unittest_objc_options.proto */, F4CF31701B162ED800BD9B06 /* unittest_objc_startup.proto */, 8B09AAF614B663A7007B4184 /* unittest_objc.proto */, 8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */, @@ -562,10 +643,10 @@ attributes = { LastSwiftUpdateCheck = 0710; LastTestingUpgradeCheck = 0600; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0930; TargetAttributes = { 8BBEA4A5147C727100C4ADB7 = { - LastSwiftMigration = 0800; + LastSwiftMigration = 0940; TestTargetID = 8B9A5EA41831993600A9D33B; }; F45BBC141B0CE3C6002D064D = { @@ -578,6 +659,7 @@ developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( + English, en, ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; @@ -598,6 +680,7 @@ buildActionMask = 2147483647; files = ( 8B210CCE159383D60032D72D /* golden_message in Resources */, + F4F53F8A219CC4F2001EABF4 /* text_format_extensions_unittest_data.txt in Resources */, F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */, 8B210CD0159386920032D72D /* golden_packed_fields_message in Resources */, F45E57C71AE6DC6A000B7D99 /* text_format_map_unittest_data.txt in Resources */, @@ -629,30 +712,30 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F47CF93123D9006000C7B24C /* GPBType.pbobjc.m in Sources */, 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */, - F4E6759B1B21D0000054530B /* Empty.pbobjc.m in Sources */, + F47CF93223D9006000C7B24C /* GPBWrappers.pbobjc.m in Sources */, + F47CF94123D902D500C7B24C /* GPBEmpty.pbobjc.m in Sources */, + F47CF94623D902D500C7B24C /* GPBDuration.pbobjc.m in Sources */, + F47CF92F23D9006000C7B24C /* GPBSourceContext.pbobjc.m in Sources */, 7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */, F401DC2D1A8D444600FCC765 /* GPBArray.m in Sources */, 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */, - F4E6759D1B21D0000054530B /* FieldMask.pbobjc.m in Sources */, 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */, 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */, - F47476E51D21A524007C7B1A /* Duration.pbobjc.m in Sources */, 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */, + F47CF93423D9006000C7B24C /* GPBFieldMask.pbobjc.m in Sources */, 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */, 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */, - F4E675991B21D0000054530B /* Api.pbobjc.m in Sources */, - F4E6759F1B21D0000054530B /* SourceContext.pbobjc.m in Sources */, F4353D231ABB1537005A6198 /* GPBDictionary.m in Sources */, 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */, + F47CF93523D9006000C7B24C /* GPBTimestamp.pbobjc.m in Sources */, 8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */, - F4E675971B21D0000054530B /* Any.pbobjc.m in Sources */, F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */, + F47CF92B23D9006000C7B24C /* GPBStruct.pbobjc.m in Sources */, + F47CF94323D902D500C7B24C /* GPBAny.pbobjc.m in Sources */, 8B4248D21A927E1500BC1EC6 /* GPBWellKnownTypes.m in Sources */, - F4E675A31B21D0000054530B /* Type.pbobjc.m in Sources */, - F4E675A11B21D0000054530B /* Struct.pbobjc.m in Sources */, - F4E675A51B21D0000054530B /* Wrappers.pbobjc.m in Sources */, - F47476E61D21A524007C7B1A /* Timestamp.pbobjc.m in Sources */, + F47CF94223D902D500C7B24C /* GPBApi.pbobjc.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -661,28 +744,54 @@ buildActionMask = 2147483647; files = ( 8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */, + F40EE50B206C06640071091A /* GPBCompileTest24.m in Sources */, + F40EE4BE206BF8B90071091A /* GPBCompileTest20.m in Sources */, F401DC331A8E5C0200FCC765 /* GPBArrayTests.m in Sources */, + F40EE4B4206BF8B90071091A /* GPBCompileTest10.m in Sources */, F4353D361AC06F10005A6198 /* GPBDictionaryTests+Int64.m in Sources */, + F40EE4C0206BF8B90071091A /* GPBCompileTest22.m in Sources */, + F40EE4B2206BF8B90071091A /* GPBCompileTest08.m in Sources */, + F40EE4BB206BF8B90071091A /* GPBCompileTest17.m in Sources */, F4353D391AC06F10005A6198 /* GPBDictionaryTests+UInt64.m in Sources */, 8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */, + F40EE4C1206BF8B90071091A /* GPBCompileTest23.m in Sources */, 8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */, F4B51B1E1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */, + F40EE4BD206BF8B90071091A /* GPBCompileTest19.m in Sources */, + F40EE4B0206BF8B90071091A /* GPBCompileTest06.m in Sources */, + F40EE4B6206BF8B90071091A /* GPBCompileTest12.m in Sources */, F4487C7F1AAF62CD00531423 /* GPBMessageTests+Serialization.m in Sources */, + F40EE4AD206BF8B90071091A /* GPBCompileTest03.m in Sources */, + F40EE4BC206BF8B90071091A /* GPBCompileTest18.m in Sources */, + F40EE4B7206BF8B90071091A /* GPBCompileTest13.m in Sources */, + F40EE4B9206BF8B90071091A /* GPBCompileTest15.m in Sources */, + F40EE4B1206BF8B90071091A /* GPBCompileTest07.m in Sources */, 8B4248DC1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m in Sources */, + F40EE4BF206BF8B90071091A /* GPBCompileTest21.m in Sources */, + F40EE4B5206BF8B90071091A /* GPBCompileTest11.m in Sources */, F4F8D8831D789FD9002CE128 /* GPBUnittestProtos2.m in Sources */, F4353D1D1AB8822D005A6198 /* GPBDescriptorTests.m in Sources */, 8B4248BB1A8C256A00BC1EC6 /* GPBSwiftTests.swift in Sources */, + F40EE50C206C06640071091A /* GPBCompileTest25.m in Sources */, F4584D821ECCB52A00803AB6 /* GPBExtensionRegistryTest.m in Sources */, + 8BFF9D1A23AD582300E63E32 /* GPBMessageTests+ClassNames.m in Sources */, 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */, F4487C751AADF7F500531423 /* GPBMessageTests+Runtime.m in Sources */, + F40EE4AC206BF8B90071091A /* GPBCompileTest02.m in Sources */, F4353D351AC06F10005A6198 /* GPBDictionaryTests+Int32.m in Sources */, + F40EE4AF206BF8B90071091A /* GPBCompileTest05.m in Sources */, + F40EE4B8206BF8B90071091A /* GPBCompileTest14.m in Sources */, 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */, + F40EE4AE206BF8B90071091A /* GPBCompileTest04.m in Sources */, + F40EE4BA206BF8B90071091A /* GPBCompileTest16.m in Sources */, F41C175D1833D3310064ED4D /* GPBPerfTests.m in Sources */, F4353D341AC06F10005A6198 /* GPBDictionaryTests+Bool.m in Sources */, F4487C831AAF6AB300531423 /* GPBMessageTests+Merge.m in Sources */, + F40EE4AB206BF8B90071091A /* GPBCompileTest01.m in Sources */, 8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */, F4353D371AC06F10005A6198 /* GPBDictionaryTests+String.m in Sources */, F4353D381AC06F10005A6198 /* GPBDictionaryTests+UInt32.m in Sources */, + F40EE4B3206BF8B90071091A /* GPBCompileTest09.m in Sources */, 8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */, F4C4B9E41E1D976300D3B61D /* GPBDictionaryTests.m in Sources */, 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */, @@ -718,18 +827,20 @@ 7461B52F0F94FAFA00A0C422 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; COMBINE_HIDPI_IMAGES = YES; - HEADER_SEARCH_PATHS = "$(SRCROOT)"; PRODUCT_NAME = ProtocolBuffers; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; }; name = Debug; }; 7461B5300F94FAFA00A0C422 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; COMBINE_HIDPI_IMAGES = YES; - HEADER_SEARCH_PATHS = "$(SRCROOT)"; PRODUCT_NAME = ProtocolBuffers; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; }; name = Release; }; @@ -737,11 +848,8 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; COMBINE_HIDPI_IMAGES = YES; - HEADER_SEARCH_PATHS = ( - "${PROJECT_DERIVED_FILE_DIR}/protos", - "$(SRCROOT)", - ); INFOPLIST_FILE = "Tests/UnitTests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; OTHER_LDFLAGS = "-ObjC"; @@ -749,7 +857,8 @@ PRODUCT_NAME = UnitTests; SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; + USER_HEADER_SEARCH_PATHS = "${PROJECT_DERIVED_FILE_DIR}/protos $(SRCROOT)"; WARNING_CFLAGS = ( "$(inherited)", "-Wno-documentation-unknown-command", @@ -763,18 +872,16 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; COMBINE_HIDPI_IMAGES = YES; - HEADER_SEARCH_PATHS = ( - "${PROJECT_DERIVED_FILE_DIR}/protos", - "$(SRCROOT)", - ); INFOPLIST_FILE = "Tests/UnitTests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = "com.yourcompany.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = UnitTests; SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; + USER_HEADER_SEARCH_PATHS = "${PROJECT_DERIVED_FILE_DIR}/protos $(SRCROOT)"; WARNING_CFLAGS = ( "$(inherited)", "-Wno-documentation-unknown-command", @@ -787,13 +894,15 @@ C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; + ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_STATIC_ANALYZER_MODE = deep; CLANG_WARN_ASSIGN_ENUM = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -803,6 +912,8 @@ CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE; @@ -839,6 +950,7 @@ ONLY_ACTIVE_ARCH = YES; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = macosx; + USE_HEADERMAP = NO; WARNING_CFLAGS = ( "-Wdocumentation-unknown-command", "-Wundef", @@ -853,13 +965,15 @@ C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; + ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_STATIC_ANALYZER_MODE = deep; CLANG_WARN_ASSIGN_ENUM = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -869,6 +983,8 @@ CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE; @@ -903,6 +1019,7 @@ RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + USE_HEADERMAP = NO; WARNING_CFLAGS = ( "-Wdocumentation-unknown-command", "-Wundef", @@ -917,30 +1034,34 @@ F4487C4F1A9F8E0200531423 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; COMBINE_HIDPI_IMAGES = YES; - HEADER_SEARCH_PATHS = "$(SRCROOT)"; PRODUCT_NAME = TestSingleSourceBuild; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; }; name = Debug; }; F4487C501A9F8E0200531423 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; COMBINE_HIDPI_IMAGES = YES; - HEADER_SEARCH_PATHS = "$(SRCROOT)"; PRODUCT_NAME = TestSingleSourceBuild; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; }; name = Release; }; F45BBC151B0CE3C6002D064D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; }; name = Debug; }; F45BBC161B0CE3C6002D064D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; }; name = Release; }; diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000000..18d981003d68d --- /dev/null +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme index 2883109c71a2d..6653a1b02bdd6 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme @@ -1,6 +1,6 @@ + codeCoverageEnabled = "YES" + shouldUseLaunchSchemeArgsEnv = "YES"> diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj index 2211cb3757b8b..f0f82c8289373 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj @@ -25,13 +25,6 @@ 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B79657914992E3E002FFBFC /* GPBRootObject.m */; }; 8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; 8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */; }; - 8B9742331A89D19F00DCE92C /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8B9742321A89D19F00DCE92C /* LaunchScreen.xib */; }; - 8B9742431A8AAA7800DCE92C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B9742421A8AAA7800DCE92C /* CoreGraphics.framework */; }; - 8B9A5EA61831993600A9D33B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 8B9A5EA81831993600A9D33B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B9A5E9F1831913D00A9D33B /* UIKit.framework */; }; - 8B9A5EAE1831993600A9D33B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8B9A5EAC1831993600A9D33B /* InfoPlist.strings */; }; - 8B9A5EB41831993600A9D33B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B9A5EB31831993600A9D33B /* AppDelegate.m */; }; - 8B9A5EB61831993600A9D33B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8B9A5EB51831993600A9D33B /* Images.xcassets */; }; 8B9A5EEC18330A0F00A9D33B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B9A5E9F1831913D00A9D33B /* UIKit.framework */; }; 8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */; }; 8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */; }; @@ -43,7 +36,33 @@ 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; }; 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; }; 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 8BFF9D1C23AD593C00E63E32 /* GPBMessageTests+ClassNames.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */; }; F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */; }; + F40EE4F0206BF91E0071091A /* GPBCompileTest01.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CD206BF9170071091A /* GPBCompileTest01.m */; }; + F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C6206BF9170071091A /* GPBCompileTest02.m */; }; + F40EE4F2206BF91E0071091A /* GPBCompileTest03.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D6206BF9190071091A /* GPBCompileTest03.m */; }; + F40EE4F3206BF91E0071091A /* GPBCompileTest04.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C3206BF9160071091A /* GPBCompileTest04.m */; }; + F40EE4F4206BF91E0071091A /* GPBCompileTest05.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C4206BF9160071091A /* GPBCompileTest05.m */; }; + F40EE4F5206BF91E0071091A /* GPBCompileTest06.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D7206BF9190071091A /* GPBCompileTest06.m */; }; + F40EE4F6206BF91E0071091A /* GPBCompileTest07.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C5206BF9170071091A /* GPBCompileTest07.m */; }; + F40EE4F7206BF91E0071091A /* GPBCompileTest08.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C2206BF9160071091A /* GPBCompileTest08.m */; }; + F40EE4F8206BF91E0071091A /* GPBCompileTest09.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C9206BF9170071091A /* GPBCompileTest09.m */; }; + F40EE4F9206BF91E0071091A /* GPBCompileTest10.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D1206BF9180071091A /* GPBCompileTest10.m */; }; + F40EE4FA206BF91E0071091A /* GPBCompileTest11.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D8206BF9190071091A /* GPBCompileTest11.m */; }; + F40EE4FB206BF91E0071091A /* GPBCompileTest12.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D5206BF9180071091A /* GPBCompileTest12.m */; }; + F40EE4FC206BF91E0071091A /* GPBCompileTest13.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C8206BF9170071091A /* GPBCompileTest13.m */; }; + F40EE4FD206BF91E0071091A /* GPBCompileTest14.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D4206BF9180071091A /* GPBCompileTest14.m */; }; + F40EE4FE206BF91E0071091A /* GPBCompileTest15.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CE206BF9170071091A /* GPBCompileTest15.m */; }; + F40EE4FF206BF91E0071091A /* GPBCompileTest16.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D0206BF9180071091A /* GPBCompileTest16.m */; }; + F40EE500206BF91E0071091A /* GPBCompileTest17.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D2206BF9180071091A /* GPBCompileTest17.m */; }; + F40EE501206BF91E0071091A /* GPBCompileTest18.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D3206BF9180071091A /* GPBCompileTest18.m */; }; + F40EE502206BF91E0071091A /* GPBCompileTest19.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C7206BF9170071091A /* GPBCompileTest19.m */; }; + F40EE503206BF91E0071091A /* GPBCompileTest20.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CA206BF9170071091A /* GPBCompileTest20.m */; }; + F40EE504206BF91E0071091A /* GPBCompileTest21.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CB206BF9170071091A /* GPBCompileTest21.m */; }; + F40EE505206BF91E0071091A /* GPBCompileTest22.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CF206BF9170071091A /* GPBCompileTest22.m */; }; + F40EE506206BF91E0071091A /* GPBCompileTest23.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CC206BF9170071091A /* GPBCompileTest23.m */; }; + F40EE511206C068D0071091A /* GPBCompileTest24.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE50E206C06880071091A /* GPBCompileTest24.m */; }; + F40EE512206C068D0071091A /* GPBCompileTest25.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE50D206C06880071091A /* GPBCompileTest25.m */; }; F41C175D1833D3310064ED4D /* GPBPerfTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F41C175C1833D3310064ED4D /* GPBPerfTests.m */; }; F4353D1F1AB88243005A6198 /* GPBDescriptorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */; }; F4353D271ABB156F005A6198 /* GPBDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D251ABB156F005A6198 /* GPBDictionary.m */; }; @@ -63,29 +82,23 @@ F4584D831ECCB53600803AB6 /* GPBExtensionRegistryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F4584D801ECCB39E00803AB6 /* GPBExtensionRegistryTest.m */; }; F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */ = {isa = PBXBuildFile; fileRef = F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */; }; F45E57C91AE6DC98000B7D99 /* text_format_map_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F45E57C81AE6DC98000B7D99 /* text_format_map_unittest_data.txt */; }; - F47476E91D21A537007C7B1A /* Duration.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248DE1A929C7D00BC1EC6 /* Duration.pbobjc.m */; }; - F47476EA1D21A537007C7B1A /* Timestamp.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248E01A929C7D00BC1EC6 /* Timestamp.pbobjc.m */; }; + F47CF95F23D903C600C7B24C /* GPBDuration.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF94B23D903C600C7B24C /* GPBDuration.pbobjc.m */; }; + F47CF96023D903C600C7B24C /* GPBWrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF94C23D903C600C7B24C /* GPBWrappers.pbobjc.m */; }; + F47CF96223D903C600C7B24C /* GPBFieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF94E23D903C600C7B24C /* GPBFieldMask.pbobjc.m */; }; + F47CF96423D903C600C7B24C /* GPBStruct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF95023D903C600C7B24C /* GPBStruct.pbobjc.m */; }; + F47CF96523D903C600C7B24C /* GPBApi.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF95123D903C600C7B24C /* GPBApi.pbobjc.m */; }; + F47CF96623D903C600C7B24C /* GPBSourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF95223D903C600C7B24C /* GPBSourceContext.pbobjc.m */; }; + F47CF96723D903C600C7B24C /* GPBEmpty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF95323D903C600C7B24C /* GPBEmpty.pbobjc.m */; }; + F47CF96923D903C600C7B24C /* GPBTimestamp.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF95523D903C600C7B24C /* GPBTimestamp.pbobjc.m */; }; + F47CF96C23D903C600C7B24C /* GPBType.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF95823D903C600C7B24C /* GPBType.pbobjc.m */; }; + F47CF96D23D903C600C7B24C /* GPBAny.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF95923D903C600C7B24C /* GPBAny.pbobjc.m */; }; F4B51B1C1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */; }; F4C4B9E71E1D97BF00D3B61D /* GPBDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */; }; - F4E675D01B21D1620054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675B71B21D1440054530B /* Any.pbobjc.m */; }; - F4E675D11B21D1620054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675B91B21D1440054530B /* Api.pbobjc.m */; }; - F4E675D21B21D1620054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675BC1B21D1440054530B /* Empty.pbobjc.m */; }; - F4E675D31B21D1620054530B /* FieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675BE1B21D1440054530B /* FieldMask.pbobjc.m */; }; - F4E675D41B21D1620054530B /* SourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C01B21D1440054530B /* SourceContext.pbobjc.m */; }; - F4E675D51B21D1620054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C21B21D1440054530B /* Struct.pbobjc.m */; }; - F4E675D61B21D1620054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C51B21D1440054530B /* Type.pbobjc.m */; }; - F4E675D71B21D1620054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C71B21D1440054530B /* Wrappers.pbobjc.m */; }; + F4F53F8C219CC5DF001EABF4 /* text_format_extensions_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F4F53F8B219CC5DF001EABF4 /* text_format_extensions_unittest_data.txt */; }; F4F8D8861D78A193002CE128 /* GPBUnittestProtos2.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 8B9A5ED01831994600A9D33B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; - proxyType = 1; - remoteGlobalIDString = 8B9A5EA41831993600A9D33B; - remoteInfo = iOSTestHarness; - }; 8BBEA4BC147C729A00C4ADB7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; @@ -139,12 +152,9 @@ 8B09AAF614B663A7007B4184 /* unittest_objc.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc.proto; sourceTree = ""; }; 8B210CCD159383D60032D72D /* golden_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_message; sourceTree = ""; }; 8B210CCF159386920032D72D /* golden_packed_fields_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_packed_fields_message; sourceTree = ""; }; + 8B35468621A61EB2000BD30D /* unittest_objc_options.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_objc_options.proto; sourceTree = ""; }; 8B4248B21A8BD96D00BC1EC6 /* UnitTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UnitTests-Bridging-Header.h"; sourceTree = ""; }; 8B4248B31A8BD96E00BC1EC6 /* GPBSwiftTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GPBSwiftTests.swift; sourceTree = ""; }; - 8B4248B71A8BDD9600BC1EC6 /* protobuf */ = {isa = PBXFileReference; lastKnownFileType = text; name = protobuf; path = ../../Intermediates/ProtocolBuffers_iOS.build/DerivedSources/protos/google/protobuf; sourceTree = BUILT_PRODUCTS_DIR; }; - 8B4248DD1A929C7D00BC1EC6 /* Duration.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Duration.pbobjc.h; path = google/protobuf/Duration.pbobjc.h; sourceTree = ""; }; - 8B4248DE1A929C7D00BC1EC6 /* Duration.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Duration.pbobjc.m; path = google/protobuf/Duration.pbobjc.m; sourceTree = ""; }; - 8B4248E01A929C7D00BC1EC6 /* Timestamp.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Timestamp.pbobjc.m; path = google/protobuf/Timestamp.pbobjc.m; sourceTree = ""; }; 8B4248E11A929C8900BC1EC6 /* GPBWellKnownTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWellKnownTypes.h; sourceTree = ""; }; 8B4248E21A929C8900BC1EC6 /* GPBWellKnownTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWellKnownTypes.m; sourceTree = ""; }; 8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWellKnownTypesTest.m; sourceTree = ""; }; @@ -163,21 +173,41 @@ 8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBARCUnittestProtos.m; sourceTree = ""; }; 8B96157214C8B06000A2AC0B /* GPBDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDescriptor.h; sourceTree = ""; }; 8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptor.m; sourceTree = ""; }; - 8B9742321A89D19F00DCE92C /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = ""; }; 8B9742421A8AAA7800DCE92C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 8B9A5E9F1831913D00A9D33B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 8B9A5EA51831993600A9D33B /* iOSTestHarness.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iOSTestHarness.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 8B9A5EAB1831993600A9D33B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 8B9A5EAD1831993600A9D33B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 8B9A5EB31831993600A9D33B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 8B9A5EB51831993600A9D33B /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_lite.proto; path = ../../src/google/protobuf/unittest_lite.proto; sourceTree = ""; }; 8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = ""; }; 8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = ""; }; 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = ""; }; 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = ""; }; + 8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = ""; }; F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = ""; }; + F40EE4C2206BF9160071091A /* GPBCompileTest08.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest08.m; sourceTree = ""; }; + F40EE4C3206BF9160071091A /* GPBCompileTest04.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest04.m; sourceTree = ""; }; + F40EE4C4206BF9160071091A /* GPBCompileTest05.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest05.m; sourceTree = ""; }; + F40EE4C5206BF9170071091A /* GPBCompileTest07.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest07.m; sourceTree = ""; }; + F40EE4C6206BF9170071091A /* GPBCompileTest02.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest02.m; sourceTree = ""; }; + F40EE4C7206BF9170071091A /* GPBCompileTest19.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest19.m; sourceTree = ""; }; + F40EE4C8206BF9170071091A /* GPBCompileTest13.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest13.m; sourceTree = ""; }; + F40EE4C9206BF9170071091A /* GPBCompileTest09.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest09.m; sourceTree = ""; }; + F40EE4CA206BF9170071091A /* GPBCompileTest20.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest20.m; sourceTree = ""; }; + F40EE4CB206BF9170071091A /* GPBCompileTest21.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest21.m; sourceTree = ""; }; + F40EE4CC206BF9170071091A /* GPBCompileTest23.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest23.m; sourceTree = ""; }; + F40EE4CD206BF9170071091A /* GPBCompileTest01.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest01.m; sourceTree = ""; }; + F40EE4CE206BF9170071091A /* GPBCompileTest15.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest15.m; sourceTree = ""; }; + F40EE4CF206BF9170071091A /* GPBCompileTest22.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest22.m; sourceTree = ""; }; + F40EE4D0206BF9180071091A /* GPBCompileTest16.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest16.m; sourceTree = ""; }; + F40EE4D1206BF9180071091A /* GPBCompileTest10.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest10.m; sourceTree = ""; }; + F40EE4D2206BF9180071091A /* GPBCompileTest17.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest17.m; sourceTree = ""; }; + F40EE4D3206BF9180071091A /* GPBCompileTest18.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest18.m; sourceTree = ""; }; + F40EE4D4206BF9180071091A /* GPBCompileTest14.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest14.m; sourceTree = ""; }; + F40EE4D5206BF9180071091A /* GPBCompileTest12.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest12.m; sourceTree = ""; }; + F40EE4D6206BF9190071091A /* GPBCompileTest03.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest03.m; sourceTree = ""; }; + F40EE4D7206BF9190071091A /* GPBCompileTest06.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest06.m; sourceTree = ""; }; + F40EE4D8206BF9190071091A /* GPBCompileTest11.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest11.m; sourceTree = ""; }; + F40EE50D206C06880071091A /* GPBCompileTest25.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest25.m; sourceTree = ""; }; + F40EE50E206C06880071091A /* GPBCompileTest24.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest24.m; sourceTree = ""; }; F41C175C1833D3310064ED4D /* GPBPerfTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBPerfTests.m; sourceTree = ""; }; F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptorTests.m; sourceTree = ""; }; F4353D241ABB156F005A6198 /* GPBDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBDictionary.h; sourceTree = ""; }; @@ -206,6 +236,26 @@ F4584D801ECCB39E00803AB6 /* GPBExtensionRegistryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPBExtensionRegistryTest.m; path = Tests/GPBExtensionRegistryTest.m; sourceTree = SOURCE_ROOT; }; F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionInternals.m; sourceTree = ""; }; F45E57C81AE6DC98000B7D99 /* text_format_map_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_map_unittest_data.txt; sourceTree = ""; }; + F47CF94723D903C500C7B24C /* GPBFieldMask.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBFieldMask.pbobjc.h; sourceTree = ""; }; + F47CF94823D903C500C7B24C /* GPBDuration.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBDuration.pbobjc.h; sourceTree = ""; }; + F47CF94923D903C500C7B24C /* GPBApi.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBApi.pbobjc.h; sourceTree = ""; }; + F47CF94A23D903C500C7B24C /* GPBEmpty.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBEmpty.pbobjc.h; sourceTree = ""; }; + F47CF94B23D903C600C7B24C /* GPBDuration.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDuration.pbobjc.m; sourceTree = ""; }; + F47CF94C23D903C600C7B24C /* GPBWrappers.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWrappers.pbobjc.m; sourceTree = ""; }; + F47CF94D23D903C600C7B24C /* GPBWrappers.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWrappers.pbobjc.h; sourceTree = ""; }; + F47CF94E23D903C600C7B24C /* GPBFieldMask.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBFieldMask.pbobjc.m; sourceTree = ""; }; + F47CF94F23D903C600C7B24C /* GPBStruct.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBStruct.pbobjc.h; sourceTree = ""; }; + F47CF95023D903C600C7B24C /* GPBStruct.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBStruct.pbobjc.m; sourceTree = ""; }; + F47CF95123D903C600C7B24C /* GPBApi.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBApi.pbobjc.m; sourceTree = ""; }; + F47CF95223D903C600C7B24C /* GPBSourceContext.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBSourceContext.pbobjc.m; sourceTree = ""; }; + F47CF95323D903C600C7B24C /* GPBEmpty.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBEmpty.pbobjc.m; sourceTree = ""; }; + F47CF95423D903C600C7B24C /* GPBAny.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBAny.pbobjc.h; sourceTree = ""; }; + F47CF95523D903C600C7B24C /* GPBTimestamp.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBTimestamp.pbobjc.m; sourceTree = ""; }; + F47CF95623D903C600C7B24C /* GPBType.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBType.pbobjc.h; sourceTree = ""; }; + F47CF95723D903C600C7B24C /* GPBTimestamp.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBTimestamp.pbobjc.h; sourceTree = ""; }; + F47CF95823D903C600C7B24C /* GPBType.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBType.pbobjc.m; sourceTree = ""; }; + F47CF95923D903C600C7B24C /* GPBAny.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBAny.pbobjc.m; sourceTree = ""; }; + F47CF95A23D903C600C7B24C /* GPBSourceContext.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBSourceContext.pbobjc.h; sourceTree = ""; }; F4AC9E1C1A8BEB1000BD6E83 /* unittest_cycle.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_cycle.proto; sourceTree = ""; }; F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GPBObjectiveCPlusPlusTest.mm; sourceTree = ""; }; F4B6B8B01A9CC99500892426 /* GPBUnknownField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField_PackagePrivate.h; sourceTree = ""; }; @@ -214,23 +264,6 @@ F4B6B8B51A9CD1C600892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = ""; }; F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDictionaryTests.m; sourceTree = ""; }; F4CF31711B162EF500BD9B06 /* unittest_objc_startup.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc_startup.proto; sourceTree = ""; }; - F4E675B61B21D1440054530B /* Any.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Any.pbobjc.h; path = google/protobuf/Any.pbobjc.h; sourceTree = ""; }; - F4E675B71B21D1440054530B /* Any.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Any.pbobjc.m; path = google/protobuf/Any.pbobjc.m; sourceTree = ""; }; - F4E675B81B21D1440054530B /* Api.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Api.pbobjc.h; path = google/protobuf/Api.pbobjc.h; sourceTree = ""; }; - F4E675B91B21D1440054530B /* Api.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Api.pbobjc.m; path = google/protobuf/Api.pbobjc.m; sourceTree = ""; }; - F4E675BB1B21D1440054530B /* Empty.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Empty.pbobjc.h; path = google/protobuf/Empty.pbobjc.h; sourceTree = ""; }; - F4E675BC1B21D1440054530B /* Empty.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Empty.pbobjc.m; path = google/protobuf/Empty.pbobjc.m; sourceTree = ""; }; - F4E675BD1B21D1440054530B /* FieldMask.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FieldMask.pbobjc.h; path = google/protobuf/FieldMask.pbobjc.h; sourceTree = ""; }; - F4E675BE1B21D1440054530B /* FieldMask.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FieldMask.pbobjc.m; path = google/protobuf/FieldMask.pbobjc.m; sourceTree = ""; }; - F4E675BF1B21D1440054530B /* SourceContext.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SourceContext.pbobjc.h; path = google/protobuf/SourceContext.pbobjc.h; sourceTree = ""; }; - F4E675C01B21D1440054530B /* SourceContext.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SourceContext.pbobjc.m; path = google/protobuf/SourceContext.pbobjc.m; sourceTree = ""; }; - F4E675C11B21D1440054530B /* Struct.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Struct.pbobjc.h; path = google/protobuf/Struct.pbobjc.h; sourceTree = ""; }; - F4E675C21B21D1440054530B /* Struct.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Struct.pbobjc.m; path = google/protobuf/Struct.pbobjc.m; sourceTree = ""; }; - F4E675C31B21D1440054530B /* Timestamp.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Timestamp.pbobjc.h; path = google/protobuf/Timestamp.pbobjc.h; sourceTree = ""; }; - F4E675C41B21D1440054530B /* Type.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Type.pbobjc.h; path = google/protobuf/Type.pbobjc.h; sourceTree = ""; }; - F4E675C51B21D1440054530B /* Type.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Type.pbobjc.m; path = google/protobuf/Type.pbobjc.m; sourceTree = ""; }; - F4E675C61B21D1440054530B /* Wrappers.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Wrappers.pbobjc.h; path = google/protobuf/Wrappers.pbobjc.h; sourceTree = ""; }; - F4E675C71B21D1440054530B /* Wrappers.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Wrappers.pbobjc.m; path = google/protobuf/Wrappers.pbobjc.m; sourceTree = ""; }; F4E675D81B21D1DE0054530B /* any.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = any.proto; path = ../src/google/protobuf/any.proto; sourceTree = ""; }; F4E675D91B21D1DE0054530B /* api.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = api.proto; path = ../src/google/protobuf/api.proto; sourceTree = ""; }; F4E675DA1B21D1DE0054530B /* empty.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = empty.proto; path = ../src/google/protobuf/empty.proto; sourceTree = ""; }; @@ -239,6 +272,7 @@ F4E675DD1B21D1DE0054530B /* struct.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = struct.proto; path = ../src/google/protobuf/struct.proto; sourceTree = ""; }; F4E675DE1B21D1DE0054530B /* type.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = type.proto; path = ../src/google/protobuf/type.proto; sourceTree = ""; }; F4E675DF1B21D1DE0054530B /* wrappers.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = wrappers.proto; path = ../src/google/protobuf/wrappers.proto; sourceTree = ""; }; + F4F53F8B219CC5DF001EABF4 /* text_format_extensions_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_extensions_unittest_data.txt; sourceTree = ""; }; F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos2.m; sourceTree = ""; }; /* End PBXFileReference section */ @@ -251,16 +285,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 8B9A5EA21831993600A9D33B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 8B9742431A8AAA7800DCE92C /* CoreGraphics.framework in Frameworks */, - 8B9A5EA81831993600A9D33B /* UIKit.framework in Frameworks */, - 8B9A5EA61831993600A9D33B /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 8BBEA4A3147C727100C4ADB7 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -303,7 +327,6 @@ children = ( 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */, 8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */, - 8B9A5EA51831993600A9D33B /* iOSTestHarness.app */, F4487C6E1A9F8F8100531423 /* libTestSingleSourceBuild.a */, ); name = Products; @@ -323,35 +346,35 @@ 29B97315FDCFA39411CA2CEA /* Generated */ = { isa = PBXGroup; children = ( - F4E675B61B21D1440054530B /* Any.pbobjc.h */, - F4E675B71B21D1440054530B /* Any.pbobjc.m */, + F47CF95423D903C600C7B24C /* GPBAny.pbobjc.h */, + F47CF95923D903C600C7B24C /* GPBAny.pbobjc.m */, + F47CF94923D903C500C7B24C /* GPBApi.pbobjc.h */, + F47CF95123D903C600C7B24C /* GPBApi.pbobjc.m */, + F47CF94823D903C500C7B24C /* GPBDuration.pbobjc.h */, + F47CF94B23D903C600C7B24C /* GPBDuration.pbobjc.m */, + F47CF94A23D903C500C7B24C /* GPBEmpty.pbobjc.h */, + F47CF95323D903C600C7B24C /* GPBEmpty.pbobjc.m */, + F47CF94723D903C500C7B24C /* GPBFieldMask.pbobjc.h */, + F47CF94E23D903C600C7B24C /* GPBFieldMask.pbobjc.m */, + F47CF95A23D903C600C7B24C /* GPBSourceContext.pbobjc.h */, + F47CF95223D903C600C7B24C /* GPBSourceContext.pbobjc.m */, + F47CF94F23D903C600C7B24C /* GPBStruct.pbobjc.h */, + F47CF95023D903C600C7B24C /* GPBStruct.pbobjc.m */, + F47CF95723D903C600C7B24C /* GPBTimestamp.pbobjc.h */, + F47CF95523D903C600C7B24C /* GPBTimestamp.pbobjc.m */, + F47CF95623D903C600C7B24C /* GPBType.pbobjc.h */, + F47CF95823D903C600C7B24C /* GPBType.pbobjc.m */, + F47CF94D23D903C600C7B24C /* GPBWrappers.pbobjc.h */, + F47CF94C23D903C600C7B24C /* GPBWrappers.pbobjc.m */, F4E675D81B21D1DE0054530B /* any.proto */, - F4E675B81B21D1440054530B /* Api.pbobjc.h */, - F4E675B91B21D1440054530B /* Api.pbobjc.m */, F4E675D91B21D1DE0054530B /* api.proto */, - 8B4248DD1A929C7D00BC1EC6 /* Duration.pbobjc.h */, - 8B4248DE1A929C7D00BC1EC6 /* Duration.pbobjc.m */, 8B42494A1A92A0BA00BC1EC6 /* duration.proto */, - F4E675BB1B21D1440054530B /* Empty.pbobjc.h */, - F4E675BC1B21D1440054530B /* Empty.pbobjc.m */, F4E675DA1B21D1DE0054530B /* empty.proto */, F4E675DB1B21D1DE0054530B /* field_mask.proto */, - F4E675BD1B21D1440054530B /* FieldMask.pbobjc.h */, - F4E675BE1B21D1440054530B /* FieldMask.pbobjc.m */, F4E675DC1B21D1DE0054530B /* source_context.proto */, - F4E675BF1B21D1440054530B /* SourceContext.pbobjc.h */, - F4E675C01B21D1440054530B /* SourceContext.pbobjc.m */, - F4E675C11B21D1440054530B /* Struct.pbobjc.h */, - F4E675C21B21D1440054530B /* Struct.pbobjc.m */, F4E675DD1B21D1DE0054530B /* struct.proto */, - F4E675C31B21D1440054530B /* Timestamp.pbobjc.h */, - 8B4248E01A929C7D00BC1EC6 /* Timestamp.pbobjc.m */, 8B4249481A92A02300BC1EC6 /* timestamp.proto */, - F4E675C41B21D1440054530B /* Type.pbobjc.h */, - F4E675C51B21D1440054530B /* Type.pbobjc.m */, F4E675DE1B21D1DE0054530B /* type.proto */, - F4E675C61B21D1440054530B /* Wrappers.pbobjc.h */, - F4E675C71B21D1440054530B /* Wrappers.pbobjc.m */, F4E675DF1B21D1DE0054530B /* wrappers.proto */, ); name = Generated; @@ -425,14 +448,37 @@ 7461B6940F94FDDD00A0C422 /* Tests */ = { isa = PBXGroup; children = ( - 8B9A5EA91831993600A9D33B /* iOSTestHarness */, - 8B4248B71A8BDD9600BC1EC6 /* protobuf */, 8B210CCD159383D60032D72D /* golden_message */, 8B210CCF159386920032D72D /* golden_packed_fields_message */, 8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */, F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */, 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */, 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */, + F40EE4CD206BF9170071091A /* GPBCompileTest01.m */, + F40EE4C6206BF9170071091A /* GPBCompileTest02.m */, + F40EE4D6206BF9190071091A /* GPBCompileTest03.m */, + F40EE4C3206BF9160071091A /* GPBCompileTest04.m */, + F40EE4C4206BF9160071091A /* GPBCompileTest05.m */, + F40EE4D7206BF9190071091A /* GPBCompileTest06.m */, + F40EE4C5206BF9170071091A /* GPBCompileTest07.m */, + F40EE4C2206BF9160071091A /* GPBCompileTest08.m */, + F40EE4C9206BF9170071091A /* GPBCompileTest09.m */, + F40EE4D1206BF9180071091A /* GPBCompileTest10.m */, + F40EE4D8206BF9190071091A /* GPBCompileTest11.m */, + F40EE4D5206BF9180071091A /* GPBCompileTest12.m */, + F40EE4C8206BF9170071091A /* GPBCompileTest13.m */, + F40EE4D4206BF9180071091A /* GPBCompileTest14.m */, + F40EE4CE206BF9170071091A /* GPBCompileTest15.m */, + F40EE4D0206BF9180071091A /* GPBCompileTest16.m */, + F40EE4D2206BF9180071091A /* GPBCompileTest17.m */, + F40EE4D3206BF9180071091A /* GPBCompileTest18.m */, + F40EE4C7206BF9170071091A /* GPBCompileTest19.m */, + F40EE4CA206BF9170071091A /* GPBCompileTest20.m */, + F40EE4CB206BF9170071091A /* GPBCompileTest21.m */, + F40EE4CF206BF9170071091A /* GPBCompileTest22.m */, + F40EE4CC206BF9170071091A /* GPBCompileTest23.m */, + F40EE50E206C06880071091A /* GPBCompileTest24.m */, + F40EE50D206C06880071091A /* GPBCompileTest25.m */, 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */, F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */, F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */, @@ -447,6 +493,7 @@ 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */, F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */, F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */, + 8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */, F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */, F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */, F41C175C1833D3310064ED4D /* GPBPerfTests.m */, @@ -459,6 +506,7 @@ 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */, 8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */, 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */, + F4F53F8B219CC5DF001EABF4 /* text_format_extensions_unittest_data.txt */, F45E57C81AE6DC98000B7D99 /* text_format_map_unittest_data.txt */, F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */, 8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */, @@ -470,6 +518,7 @@ 8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */, 8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */, 8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */, + 8B35468621A61EB2000BD30D /* unittest_objc_options.proto */, F4CF31711B162EF500BD9B06 /* unittest_objc_startup.proto */, 8B09AAF614B663A7007B4184 /* unittest_objc.proto */, 8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */, @@ -482,26 +531,6 @@ path = Tests; sourceTree = ""; }; - 8B9A5EA91831993600A9D33B /* iOSTestHarness */ = { - isa = PBXGroup; - children = ( - 8B9A5EB31831993600A9D33B /* AppDelegate.m */, - 8B9A5EB51831993600A9D33B /* Images.xcassets */, - 8B9A5EAA1831993600A9D33B /* Supporting Files */, - 8B9742321A89D19F00DCE92C /* LaunchScreen.xib */, - ); - path = iOSTestHarness; - sourceTree = ""; - }; - 8B9A5EAA1831993600A9D33B /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 8B9A5EAB1831993600A9D33B /* Info.plist */, - 8B9A5EAC1831993600A9D33B /* InfoPlist.strings */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; 8BCF334414ED727300BC5317 /* Support */ = { isa = PBXGroup; children = ( @@ -576,23 +605,6 @@ productReference = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; productType = "com.apple.product-type.library.static"; }; - 8B9A5EA41831993600A9D33B /* iOSTestHarness */ = { - isa = PBXNativeTarget; - buildConfigurationList = 8B9A5ECA1831993600A9D33B /* Build configuration list for PBXNativeTarget "iOSTestHarness" */; - buildPhases = ( - 8B9A5EA11831993600A9D33B /* Sources */, - 8B9A5EA21831993600A9D33B /* Frameworks */, - 8B9A5EA31831993600A9D33B /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = iOSTestHarness; - productName = iOSTestHarness; - productReference = 8B9A5EA51831993600A9D33B /* iOSTestHarness.app */; - productType = "com.apple.product-type.application"; - }; 8BBEA4A5147C727100C4ADB7 /* UnitTests */ = { isa = PBXNativeTarget; buildConfigurationList = 8BBEA4BA147C728600C4ADB7 /* Build configuration list for PBXNativeTarget "UnitTests" */; @@ -607,7 +619,6 @@ dependencies = ( 8BBEA4BD147C729A00C4ADB7 /* PBXTargetDependency */, F45BBC131B0CDBBA002D064D /* PBXTargetDependency */, - 8B9A5ED11831994600A9D33B /* PBXTargetDependency */, ); name = UnitTests; productName = UnitTests; @@ -639,10 +650,10 @@ attributes = { LastSwiftUpdateCheck = 0710; LastTestingUpgradeCheck = 0600; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0930; TargetAttributes = { 8BBEA4A5147C727100C4ADB7 = { - LastSwiftMigration = 0800; + LastSwiftMigration = 0940; TestTargetID = 8B9A5EA41831993600A9D33B; }; F45BBC0E1B0CDB50002D064D = { @@ -655,6 +666,7 @@ developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( + English, en, ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; @@ -663,7 +675,6 @@ targets = ( 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */, 8BBEA4A5147C727100C4ADB7 /* UnitTests */, - 8B9A5EA41831993600A9D33B /* iOSTestHarness */, F4487C551A9F8F8100531423 /* TestSingleSourceBuild */, F45BBC0E1B0CDB50002D064D /* Compile Unittest Protos */, ); @@ -671,21 +682,12 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 8B9A5EA31831993600A9D33B /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 8B9A5EAE1831993600A9D33B /* InfoPlist.strings in Resources */, - 8B9A5EB61831993600A9D33B /* Images.xcassets in Resources */, - 8B9742331A89D19F00DCE92C /* LaunchScreen.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 8BBEA4A1147C727100C4ADB7 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 8B210CCE159383D60032D72D /* golden_message in Resources */, + F4F53F8C219CC5DF001EABF4 /* text_format_extensions_unittest_data.txt in Resources */, F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */, 8B210CD0159386920032D72D /* golden_packed_fields_message in Resources */, F45E57C91AE6DC98000B7D99 /* text_format_map_unittest_data.txt in Resources */, @@ -718,37 +720,29 @@ buildActionMask = 2147483647; files = ( 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */, - F4E675D21B21D1620054530B /* Empty.pbobjc.m in Sources */, + F47CF96D23D903C600C7B24C /* GPBAny.pbobjc.m in Sources */, + F47CF96623D903C600C7B24C /* GPBSourceContext.pbobjc.m in Sources */, + F47CF96C23D903C600C7B24C /* GPBType.pbobjc.m in Sources */, + F47CF96423D903C600C7B24C /* GPBStruct.pbobjc.m in Sources */, + F47CF96723D903C600C7B24C /* GPBEmpty.pbobjc.m in Sources */, F4487C731A9F906200531423 /* GPBArray.m in Sources */, 7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */, 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */, - F4E675D31B21D1620054530B /* FieldMask.pbobjc.m in Sources */, + F47CF95F23D903C600C7B24C /* GPBDuration.pbobjc.m in Sources */, 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */, 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */, - F47476E91D21A537007C7B1A /* Duration.pbobjc.m in Sources */, 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */, 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */, 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */, - F4E675D11B21D1620054530B /* Api.pbobjc.m in Sources */, - F4E675D41B21D1620054530B /* SourceContext.pbobjc.m in Sources */, + F47CF96023D903C600C7B24C /* GPBWrappers.pbobjc.m in Sources */, + F47CF96523D903C600C7B24C /* GPBApi.pbobjc.m in Sources */, F4353D271ABB156F005A6198 /* GPBDictionary.m in Sources */, 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */, + F47CF96223D903C600C7B24C /* GPBFieldMask.pbobjc.m in Sources */, 8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */, - F4E675D01B21D1620054530B /* Any.pbobjc.m in Sources */, F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */, 8B4248E41A929C8900BC1EC6 /* GPBWellKnownTypes.m in Sources */, - F4E675D61B21D1620054530B /* Type.pbobjc.m in Sources */, - F4E675D51B21D1620054530B /* Struct.pbobjc.m in Sources */, - F4E675D71B21D1620054530B /* Wrappers.pbobjc.m in Sources */, - F47476EA1D21A537007C7B1A /* Timestamp.pbobjc.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 8B9A5EA11831993600A9D33B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 8B9A5EB41831993600A9D33B /* AppDelegate.m in Sources */, + F47CF96923D903C600C7B24C /* GPBTimestamp.pbobjc.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -757,28 +751,54 @@ buildActionMask = 2147483647; files = ( 8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */, + F40EE511206C068D0071091A /* GPBCompileTest24.m in Sources */, + F40EE503206BF91E0071091A /* GPBCompileTest20.m in Sources */, F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */, + F40EE4F9206BF91E0071091A /* GPBCompileTest10.m in Sources */, F4353D441AC06F31005A6198 /* GPBDictionaryTests+Int64.m in Sources */, + F40EE505206BF91E0071091A /* GPBCompileTest22.m in Sources */, + F40EE4F7206BF91E0071091A /* GPBCompileTest08.m in Sources */, + F40EE500206BF91E0071091A /* GPBCompileTest17.m in Sources */, F4353D471AC06F31005A6198 /* GPBDictionaryTests+UInt64.m in Sources */, 8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */, + F40EE506206BF91E0071091A /* GPBCompileTest23.m in Sources */, 8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */, F4487C811AAF62FC00531423 /* GPBMessageTests+Serialization.m in Sources */, + F40EE502206BF91E0071091A /* GPBCompileTest19.m in Sources */, + F40EE4F5206BF91E0071091A /* GPBCompileTest06.m in Sources */, + F40EE4FB206BF91E0071091A /* GPBCompileTest12.m in Sources */, 8B4248E61A929C9900BC1EC6 /* GPBWellKnownTypesTest.m in Sources */, + F40EE4F2206BF91E0071091A /* GPBCompileTest03.m in Sources */, + F40EE501206BF91E0071091A /* GPBCompileTest18.m in Sources */, + F40EE4FC206BF91E0071091A /* GPBCompileTest13.m in Sources */, + F40EE4FE206BF91E0071091A /* GPBCompileTest15.m in Sources */, + F40EE4F6206BF91E0071091A /* GPBCompileTest07.m in Sources */, F4353D1F1AB88243005A6198 /* GPBDescriptorTests.m in Sources */, + F40EE504206BF91E0071091A /* GPBCompileTest21.m in Sources */, + F40EE4FA206BF91E0071091A /* GPBCompileTest11.m in Sources */, F4F8D8861D78A193002CE128 /* GPBUnittestProtos2.m in Sources */, F4B51B1C1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */, 8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */, + F40EE512206C068D0071091A /* GPBCompileTest25.m in Sources */, F4584D831ECCB53600803AB6 /* GPBExtensionRegistryTest.m in Sources */, + 8BFF9D1C23AD593C00E63E32 /* GPBMessageTests+ClassNames.m in Sources */, 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */, F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */, + F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */, F4353D431AC06F31005A6198 /* GPBDictionaryTests+Int32.m in Sources */, + F40EE4F4206BF91E0071091A /* GPBCompileTest05.m in Sources */, + F40EE4FD206BF91E0071091A /* GPBCompileTest14.m in Sources */, 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */, + F40EE4F3206BF91E0071091A /* GPBCompileTest04.m in Sources */, + F40EE4FF206BF91E0071091A /* GPBCompileTest16.m in Sources */, F41C175D1833D3310064ED4D /* GPBPerfTests.m in Sources */, F4353D421AC06F31005A6198 /* GPBDictionaryTests+Bool.m in Sources */, F4487C851AAF6AC500531423 /* GPBMessageTests+Merge.m in Sources */, + F40EE4F0206BF91E0071091A /* GPBCompileTest01.m in Sources */, 8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */, F4353D451AC06F31005A6198 /* GPBDictionaryTests+String.m in Sources */, F4353D461AC06F31005A6198 /* GPBDictionaryTests+UInt32.m in Sources */, + F40EE4F8206BF91E0071091A /* GPBCompileTest09.m in Sources */, 8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */, F4C4B9E71E1D97BF00D3B61D /* GPBDictionaryTests.m in Sources */, 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */, @@ -798,11 +818,6 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 8B9A5ED11831994600A9D33B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 8B9A5EA41831993600A9D33B /* iOSTestHarness */; - targetProxy = 8B9A5ED01831994600A9D33B /* PBXContainerItemProxy */; - }; 8BBEA4BD147C729A00C4ADB7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */; @@ -815,63 +830,24 @@ }; /* End PBXTargetDependency section */ -/* Begin PBXVariantGroup section */ - 8B9A5EAC1831993600A9D33B /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 8B9A5EAD1831993600A9D33B /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - /* Begin XCBuildConfiguration section */ 7461B52F0F94FAFA00A0C422 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - HEADER_SEARCH_PATHS = "$(SRCROOT)"; + CLANG_ENABLE_OBJC_WEAK = YES; PRODUCT_NAME = ProtocolBuffers; TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; }; name = Debug; }; 7461B5300F94FAFA00A0C422 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - HEADER_SEARCH_PATHS = "$(SRCROOT)"; + CLANG_ENABLE_OBJC_WEAK = YES; PRODUCT_NAME = ProtocolBuffers; TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 8B9A5ECB1831993600A9D33B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - CLANG_ENABLE_OBJC_ARC = YES; - INFOPLIST_FILE = "$(SRCROOT)/Tests/iOSTestHarness/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.google.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = app; - }; - name = Debug; - }; - 8B9A5ECC1831993600A9D33B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - CLANG_ENABLE_OBJC_ARC = YES; - INFOPLIST_FILE = "$(SRCROOT)/Tests/iOSTestHarness/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.google.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = app; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; }; name = Release; }; @@ -879,17 +855,12 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; FRAMEWORK_SEARCH_PATHS = ( - "\"$(SDKROOT)/Developer/Library/Frameworks\"", "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", "$(inherited)", ); - HEADER_SEARCH_PATHS = ( - "${PROJECT_DERIVED_FILE_DIR}/protos", - "$(SRCROOT)", - ); INFOPLIST_FILE = "Tests/UnitTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -899,9 +870,9 @@ PRODUCT_NAME = UnitTests; SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOSTestHarness.app/iOSTestHarness"; + USER_HEADER_SEARCH_PATHS = "${PROJECT_DERIVED_FILE_DIR}/protos $(SRCROOT)"; WARNING_CFLAGS = ( "$(inherited)", "-Wno-documentation-unknown-command", @@ -915,17 +886,12 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; FRAMEWORK_SEARCH_PATHS = ( - "\"$(SDKROOT)/Developer/Library/Frameworks\"", "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", "$(inherited)", ); - HEADER_SEARCH_PATHS = ( - "${PROJECT_DERIVED_FILE_DIR}/protos", - "$(SRCROOT)", - ); INFOPLIST_FILE = "Tests/UnitTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -934,9 +900,9 @@ OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = UnitTests; SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOSTestHarness.app/iOSTestHarness"; + USER_HEADER_SEARCH_PATHS = "${PROJECT_DERIVED_FILE_DIR}/protos $(SRCROOT)"; WARNING_CFLAGS = ( "$(inherited)", "-Wno-documentation-unknown-command", @@ -949,13 +915,15 @@ C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; + ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_STATIC_ANALYZER_MODE = deep; CLANG_WARN_ASSIGN_ENUM = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -965,6 +933,8 @@ CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE; @@ -998,7 +968,7 @@ GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; GENERATE_PROFILING_CODE = NO; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; ONLY_ACTIVE_ARCH = YES; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = iphoneos; @@ -1016,13 +986,15 @@ C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; + ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_STATIC_ANALYZER_MODE = deep; CLANG_WARN_ASSIGN_ENUM = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -1032,6 +1004,8 @@ CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE; @@ -1063,7 +1037,7 @@ GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; GENERATE_PROFILING_CODE = NO; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; @@ -1081,30 +1055,34 @@ F4487C6C1A9F8F8100531423 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - HEADER_SEARCH_PATHS = "$(SRCROOT)"; + CLANG_ENABLE_OBJC_WEAK = YES; PRODUCT_NAME = TestSingleSourceBuild; TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; }; name = Debug; }; F4487C6D1A9F8F8100531423 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - HEADER_SEARCH_PATHS = "$(SRCROOT)"; + CLANG_ENABLE_OBJC_WEAK = YES; PRODUCT_NAME = TestSingleSourceBuild; TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; }; name = Release; }; F45BBC0F1B0CDB50002D064D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; }; name = Debug; }; F45BBC101B0CDB50002D064D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; }; name = Release; }; @@ -1120,15 +1098,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 8B9A5ECA1831993600A9D33B /* Build configuration list for PBXNativeTarget "iOSTestHarness" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 8B9A5ECB1831993600A9D33B /* Debug */, - 8B9A5ECC1831993600A9D33B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 8BBEA4BA147C728600C4ADB7 /* Build configuration list for PBXNativeTarget "UnitTests" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000000..18d981003d68d --- /dev/null +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme index 1ba3a3292178e..1a02f7e4cb089 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme @@ -1,6 +1,6 @@ - - - - diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme index edbe689822865..bacbcba3a9bcf 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme @@ -1,6 +1,6 @@ + codeCoverageEnabled = "YES" + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -95,16 +95,15 @@ debugDocumentVersioning = "YES" debugServiceExtension = "internal" allowLocationSimulation = "YES"> - + - + diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj new file mode 100644 index 0000000000000..c7a8d854c7489 --- /dev/null +++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj @@ -0,0 +1,1134 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 47; + objects = { + +/* Begin PBXBuildFile section */ + 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */; }; + 7461B5360F94FB4600A0C422 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B48F0F94F99000A0C422 /* GPBCodedInputStream.m */; }; + 7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */; }; + 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */; }; + 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */; }; + 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4BF0F94F99000A0C422 /* GPBMessage.m */; }; + 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */; }; + 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E60F94F99000A0C422 /* GPBUtilities.m */; }; + 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E80F94F99000A0C422 /* GPBWireFormat.m */; }; + 8B210CCE159383D60032D72D /* golden_message in Resources */ = {isa = PBXBuildFile; fileRef = 8B210CCD159383D60032D72D /* golden_message */; }; + 8B210CD0159386920032D72D /* golden_packed_fields_message in Resources */ = {isa = PBXBuildFile; fileRef = 8B210CCF159386920032D72D /* golden_packed_fields_message */; }; + 8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248B31A8BD96E00BC1EC6 /* GPBSwiftTests.swift */; }; + 8B4248E41A929C8900BC1EC6 /* GPBWellKnownTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248E21A929C8900BC1EC6 /* GPBWellKnownTypes.m */; }; + 8B4248E61A929C9900BC1EC6 /* GPBWellKnownTypesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */; }; + 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B79657914992E3E002FFBFC /* GPBRootObject.m */; }; + 8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; + 8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */; }; + 8B9A5EEC18330A0F00A9D33B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B9A5E9F1831913D00A9D33B /* UIKit.framework */; }; + 8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */; }; + 8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */; }; + 8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */; }; + 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */; }; + 8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */; }; + 8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */; }; + 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */; }; + 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; }; + 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; }; + 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 8BFF9D1E23AD599400E63E32 /* GPBMessageTests+ClassNames.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */; }; + F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */; }; + F40EE4F0206BF91E0071091A /* GPBCompileTest01.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CD206BF9170071091A /* GPBCompileTest01.m */; }; + F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C6206BF9170071091A /* GPBCompileTest02.m */; }; + F40EE4F2206BF91E0071091A /* GPBCompileTest03.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D6206BF9190071091A /* GPBCompileTest03.m */; }; + F40EE4F3206BF91E0071091A /* GPBCompileTest04.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C3206BF9160071091A /* GPBCompileTest04.m */; }; + F40EE4F4206BF91E0071091A /* GPBCompileTest05.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C4206BF9160071091A /* GPBCompileTest05.m */; }; + F40EE4F5206BF91E0071091A /* GPBCompileTest06.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D7206BF9190071091A /* GPBCompileTest06.m */; }; + F40EE4F6206BF91E0071091A /* GPBCompileTest07.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C5206BF9170071091A /* GPBCompileTest07.m */; }; + F40EE4F7206BF91E0071091A /* GPBCompileTest08.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C2206BF9160071091A /* GPBCompileTest08.m */; }; + F40EE4F8206BF91E0071091A /* GPBCompileTest09.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C9206BF9170071091A /* GPBCompileTest09.m */; }; + F40EE4F9206BF91E0071091A /* GPBCompileTest10.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D1206BF9180071091A /* GPBCompileTest10.m */; }; + F40EE4FA206BF91E0071091A /* GPBCompileTest11.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D8206BF9190071091A /* GPBCompileTest11.m */; }; + F40EE4FB206BF91E0071091A /* GPBCompileTest12.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D5206BF9180071091A /* GPBCompileTest12.m */; }; + F40EE4FC206BF91E0071091A /* GPBCompileTest13.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C8206BF9170071091A /* GPBCompileTest13.m */; }; + F40EE4FD206BF91E0071091A /* GPBCompileTest14.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D4206BF9180071091A /* GPBCompileTest14.m */; }; + F40EE4FE206BF91E0071091A /* GPBCompileTest15.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CE206BF9170071091A /* GPBCompileTest15.m */; }; + F40EE4FF206BF91E0071091A /* GPBCompileTest16.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D0206BF9180071091A /* GPBCompileTest16.m */; }; + F40EE500206BF91E0071091A /* GPBCompileTest17.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D2206BF9180071091A /* GPBCompileTest17.m */; }; + F40EE501206BF91E0071091A /* GPBCompileTest18.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4D3206BF9180071091A /* GPBCompileTest18.m */; }; + F40EE502206BF91E0071091A /* GPBCompileTest19.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C7206BF9170071091A /* GPBCompileTest19.m */; }; + F40EE503206BF91E0071091A /* GPBCompileTest20.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CA206BF9170071091A /* GPBCompileTest20.m */; }; + F40EE504206BF91E0071091A /* GPBCompileTest21.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CB206BF9170071091A /* GPBCompileTest21.m */; }; + F40EE505206BF91E0071091A /* GPBCompileTest22.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CF206BF9170071091A /* GPBCompileTest22.m */; }; + F40EE506206BF91E0071091A /* GPBCompileTest23.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CC206BF9170071091A /* GPBCompileTest23.m */; }; + F40EE511206C068D0071091A /* GPBCompileTest24.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE50E206C06880071091A /* GPBCompileTest24.m */; }; + F40EE512206C068D0071091A /* GPBCompileTest25.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE50D206C06880071091A /* GPBCompileTest25.m */; }; + F41C175D1833D3310064ED4D /* GPBPerfTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F41C175C1833D3310064ED4D /* GPBPerfTests.m */; }; + F4353D1F1AB88243005A6198 /* GPBDescriptorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */; }; + F4353D271ABB156F005A6198 /* GPBDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D251ABB156F005A6198 /* GPBDictionary.m */; }; + F4353D421AC06F31005A6198 /* GPBDictionaryTests+Bool.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3B1AC06F31005A6198 /* GPBDictionaryTests+Bool.m */; }; + F4353D431AC06F31005A6198 /* GPBDictionaryTests+Int32.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3C1AC06F31005A6198 /* GPBDictionaryTests+Int32.m */; }; + F4353D441AC06F31005A6198 /* GPBDictionaryTests+Int64.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3D1AC06F31005A6198 /* GPBDictionaryTests+Int64.m */; }; + F4353D451AC06F31005A6198 /* GPBDictionaryTests+String.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3E1AC06F31005A6198 /* GPBDictionaryTests+String.m */; }; + F4353D461AC06F31005A6198 /* GPBDictionaryTests+UInt32.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */; }; + F4353D471AC06F31005A6198 /* GPBDictionaryTests+UInt64.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */; }; + F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */; }; + F4487C6A1A9F8F8100531423 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + F4487C6F1A9F8FFF00531423 /* GPBProtocolBuffers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */; }; + F4487C731A9F906200531423 /* GPBArray.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C711A9F906200531423 /* GPBArray.m */; }; + F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */; }; + F4487C811AAF62FC00531423 /* GPBMessageTests+Serialization.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */; }; + F4487C851AAF6AC500531423 /* GPBMessageTests+Merge.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */; }; + F4584D831ECCB53600803AB6 /* GPBExtensionRegistryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F4584D801ECCB39E00803AB6 /* GPBExtensionRegistryTest.m */; }; + F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */ = {isa = PBXBuildFile; fileRef = F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */; }; + F45E57C91AE6DC98000B7D99 /* text_format_map_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F45E57C81AE6DC98000B7D99 /* text_format_map_unittest_data.txt */; }; + F47CF98523D904E600C7B24C /* GPBApi.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF97123D904E500C7B24C /* GPBApi.pbobjc.m */; }; + F47CF98623D904E600C7B24C /* GPBEmpty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF97223D904E500C7B24C /* GPBEmpty.pbobjc.m */; }; + F47CF98923D904E600C7B24C /* GPBStruct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF97523D904E500C7B24C /* GPBStruct.pbobjc.m */; }; + F47CF98A23D904E600C7B24C /* GPBFieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF97623D904E500C7B24C /* GPBFieldMask.pbobjc.m */; }; + F47CF98B23D904E600C7B24C /* GPBDuration.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF97723D904E500C7B24C /* GPBDuration.pbobjc.m */; }; + F47CF98E23D904E600C7B24C /* GPBType.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF97A23D904E600C7B24C /* GPBType.pbobjc.m */; }; + F47CF98F23D904E600C7B24C /* GPBTimestamp.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF97B23D904E600C7B24C /* GPBTimestamp.pbobjc.m */; }; + F47CF99323D904E600C7B24C /* GPBWrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF97F23D904E600C7B24C /* GPBWrappers.pbobjc.m */; }; + F47CF99423D904E600C7B24C /* GPBAny.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF98023D904E600C7B24C /* GPBAny.pbobjc.m */; }; + F47CF99623D904E600C7B24C /* GPBSourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F47CF98223D904E600C7B24C /* GPBSourceContext.pbobjc.m */; }; + F4B51B1C1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */; }; + F4C4B9E71E1D97BF00D3B61D /* GPBDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */; }; + F4F53F8C219CC5DF001EABF4 /* text_format_extensions_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F4F53F8B219CC5DF001EABF4 /* text_format_extensions_unittest_data.txt */; }; + F4F8D8861D78A193002CE128 /* GPBUnittestProtos2.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 8BBEA4BC147C729A00C4ADB7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 7461B52D0F94FAF800A0C422; + remoteInfo = ProtocolBuffers; + }; + F45BBC121B0CDBBA002D064D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = F45BBC0E1B0CDB50002D064D; + remoteInfo = "Compile Unittest Protos"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBConcurrencyTests.m; sourceTree = ""; }; + 51457B5F18D0B7AF00CCC606 /* GPBCodedInputStream_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBCodedInputStream_PackagePrivate.h; sourceTree = ""; }; + 515B840C18B7DEE30031753B /* GPBDescriptor_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDescriptor_PackagePrivate.h; sourceTree = ""; }; + 5196A06918CE16B000B759E2 /* GPBMessage_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBMessage_PackagePrivate.h; sourceTree = ""; }; + 7401C1A90F950347006D8281 /* UnitTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "UnitTests-Info.plist"; sourceTree = ""; }; + 7461B48D0F94F99000A0C422 /* GPBBootstrap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBBootstrap.h; sourceTree = ""; }; + 7461B48E0F94F99000A0C422 /* GPBCodedInputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBCodedInputStream.h; sourceTree = ""; }; + 7461B48F0F94F99000A0C422 /* GPBCodedInputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GPBCodedInputStream.m; sourceTree = ""; }; + 7461B4900F94F99000A0C422 /* GPBCodedOutputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBCodedOutputStream.h; sourceTree = ""; }; + 7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOutputStream.m; sourceTree = ""; }; + 7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBExtensionRegistry.h; sourceTree = ""; }; + 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionRegistry.m; sourceTree = ""; }; + 7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField.h; sourceTree = ""; }; + 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownField.m; sourceTree = ""; }; + 7461B4BE0F94F99000A0C422 /* GPBMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBMessage.h; sourceTree = ""; }; + 7461B4BF0F94F99000A0C422 /* GPBMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessage.m; sourceTree = ""; }; + 7461B4CD0F94F99000A0C422 /* GPBProtocolBuffers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers.h; sourceTree = ""; }; + 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet.h; sourceTree = ""; }; + 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSet.m; sourceTree = ""; }; + 7461B4E50F94F99000A0C422 /* GPBUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUtilities.h; sourceTree = ""; }; + 7461B4E60F94F99000A0C422 /* GPBUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilities.m; sourceTree = ""; }; + 7461B4E70F94F99000A0C422 /* GPBWireFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWireFormat.h; sourceTree = ""; }; + 7461B4E80F94F99000A0C422 /* GPBWireFormat.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormat.m; sourceTree = ""; }; + 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libProtocolBuffers.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedInputStreamTests.m; sourceTree = ""; }; + 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOuputStreamTests.m; sourceTree = ""; }; + 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessageTests.m; sourceTree = ""; }; + 7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBTestUtilities.h; sourceTree = ""; }; + 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBTestUtilities.m; sourceTree = ""; }; + 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSetTest.m; sourceTree = ""; }; + 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilitiesTests.m; sourceTree = ""; }; + 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormatTests.m; sourceTree = ""; }; + 8B09AAF614B663A7007B4184 /* unittest_objc.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc.proto; sourceTree = ""; }; + 8B210CCD159383D60032D72D /* golden_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_message; sourceTree = ""; }; + 8B210CCF159386920032D72D /* golden_packed_fields_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_packed_fields_message; sourceTree = ""; }; + 8B35468621A61EB2000BD30D /* unittest_objc_options.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_objc_options.proto; sourceTree = ""; }; + 8B4248B21A8BD96D00BC1EC6 /* UnitTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UnitTests-Bridging-Header.h"; sourceTree = ""; }; + 8B4248B31A8BD96E00BC1EC6 /* GPBSwiftTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GPBSwiftTests.swift; sourceTree = ""; }; + 8B4248E11A929C8900BC1EC6 /* GPBWellKnownTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWellKnownTypes.h; sourceTree = ""; }; + 8B4248E21A929C8900BC1EC6 /* GPBWellKnownTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWellKnownTypes.m; sourceTree = ""; }; + 8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWellKnownTypesTest.m; sourceTree = ""; }; + 8B4249481A92A02300BC1EC6 /* timestamp.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = timestamp.proto; path = ../src/google/protobuf/timestamp.proto; sourceTree = ""; }; + 8B42494A1A92A0BA00BC1EC6 /* duration.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = duration.proto; path = ../src/google/protobuf/duration.proto; sourceTree = ""; }; + 8B79657814992E3E002FFBFC /* GPBRootObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBRootObject.h; sourceTree = ""; }; + 8B79657914992E3E002FFBFC /* GPBRootObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBRootObject.m; sourceTree = ""; }; + 8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_custom_options.proto; path = ../../src/google/protobuf/unittest_custom_options.proto; sourceTree = ""; }; + 8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_embed_optimize_for.proto; path = ../../src/google/protobuf/unittest_embed_optimize_for.proto; sourceTree = ""; }; + 8B7E6A7614893DBA00F8884A /* unittest_empty.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_empty.proto; path = ../../src/google/protobuf/unittest_empty.proto; sourceTree = ""; }; + 8B7E6A7814893DBB00F8884A /* unittest_import.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_import.proto; path = ../../src/google/protobuf/unittest_import.proto; sourceTree = ""; }; + 8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_mset.proto; path = ../../src/google/protobuf/unittest_mset.proto; sourceTree = ""; }; + 8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_no_generic_services.proto; path = ../../src/google/protobuf/unittest_no_generic_services.proto; sourceTree = ""; }; + 8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_optimize_for.proto; path = ../../src/google/protobuf/unittest_optimize_for.proto; sourceTree = ""; }; + 8B7E6A7E14893DBC00F8884A /* unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest.proto; path = ../../src/google/protobuf/unittest.proto; sourceTree = ""; }; + 8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBARCUnittestProtos.m; sourceTree = ""; }; + 8B96157214C8B06000A2AC0B /* GPBDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDescriptor.h; sourceTree = ""; }; + 8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptor.m; sourceTree = ""; }; + 8B9742421A8AAA7800DCE92C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 8B9A5E9F1831913D00A9D33B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_lite.proto; path = ../../src/google/protobuf/unittest_lite.proto; sourceTree = ""; }; + 8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = ""; }; + 8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = ""; }; + 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = ""; }; + 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = ""; }; + 8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = ""; }; + F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = ""; }; + F40EE4C2206BF9160071091A /* GPBCompileTest08.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest08.m; sourceTree = ""; }; + F40EE4C3206BF9160071091A /* GPBCompileTest04.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest04.m; sourceTree = ""; }; + F40EE4C4206BF9160071091A /* GPBCompileTest05.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest05.m; sourceTree = ""; }; + F40EE4C5206BF9170071091A /* GPBCompileTest07.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest07.m; sourceTree = ""; }; + F40EE4C6206BF9170071091A /* GPBCompileTest02.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest02.m; sourceTree = ""; }; + F40EE4C7206BF9170071091A /* GPBCompileTest19.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest19.m; sourceTree = ""; }; + F40EE4C8206BF9170071091A /* GPBCompileTest13.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest13.m; sourceTree = ""; }; + F40EE4C9206BF9170071091A /* GPBCompileTest09.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest09.m; sourceTree = ""; }; + F40EE4CA206BF9170071091A /* GPBCompileTest20.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest20.m; sourceTree = ""; }; + F40EE4CB206BF9170071091A /* GPBCompileTest21.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest21.m; sourceTree = ""; }; + F40EE4CC206BF9170071091A /* GPBCompileTest23.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest23.m; sourceTree = ""; }; + F40EE4CD206BF9170071091A /* GPBCompileTest01.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest01.m; sourceTree = ""; }; + F40EE4CE206BF9170071091A /* GPBCompileTest15.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest15.m; sourceTree = ""; }; + F40EE4CF206BF9170071091A /* GPBCompileTest22.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest22.m; sourceTree = ""; }; + F40EE4D0206BF9180071091A /* GPBCompileTest16.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest16.m; sourceTree = ""; }; + F40EE4D1206BF9180071091A /* GPBCompileTest10.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest10.m; sourceTree = ""; }; + F40EE4D2206BF9180071091A /* GPBCompileTest17.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest17.m; sourceTree = ""; }; + F40EE4D3206BF9180071091A /* GPBCompileTest18.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest18.m; sourceTree = ""; }; + F40EE4D4206BF9180071091A /* GPBCompileTest14.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest14.m; sourceTree = ""; }; + F40EE4D5206BF9180071091A /* GPBCompileTest12.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest12.m; sourceTree = ""; }; + F40EE4D6206BF9190071091A /* GPBCompileTest03.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest03.m; sourceTree = ""; }; + F40EE4D7206BF9190071091A /* GPBCompileTest06.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest06.m; sourceTree = ""; }; + F40EE4D8206BF9190071091A /* GPBCompileTest11.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest11.m; sourceTree = ""; }; + F40EE50D206C06880071091A /* GPBCompileTest25.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest25.m; sourceTree = ""; }; + F40EE50E206C06880071091A /* GPBCompileTest24.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest24.m; sourceTree = ""; }; + F41C175C1833D3310064ED4D /* GPBPerfTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBPerfTests.m; sourceTree = ""; }; + F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptorTests.m; sourceTree = ""; }; + F4353D241ABB156F005A6198 /* GPBDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBDictionary.h; sourceTree = ""; }; + F4353D251ABB156F005A6198 /* GPBDictionary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDictionary.m; sourceTree = ""; }; + F4353D3A1AC06F31005A6198 /* GPBDictionaryTests.pddm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = GPBDictionaryTests.pddm; sourceTree = ""; }; + F4353D3B1AC06F31005A6198 /* GPBDictionaryTests+Bool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+Bool.m"; sourceTree = ""; }; + F4353D3C1AC06F31005A6198 /* GPBDictionaryTests+Int32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+Int32.m"; sourceTree = ""; }; + F4353D3D1AC06F31005A6198 /* GPBDictionaryTests+Int64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+Int64.m"; sourceTree = ""; }; + F4353D3E1AC06F31005A6198 /* GPBDictionaryTests+String.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+String.m"; sourceTree = ""; }; + F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt32.m"; sourceTree = ""; }; + F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt64.m"; sourceTree = ""; }; + F43725921AC9835D004DCAFB /* GPBDictionary_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDictionary_PackagePrivate.h; sourceTree = ""; }; + F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_unittest_data.txt; sourceTree = ""; }; + F4411BE81AF1301700324B4A /* GPBArray_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBArray_PackagePrivate.h; sourceTree = ""; }; + F4487C6E1A9F8F8100531423 /* libTestSingleSourceBuild.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTestSingleSourceBuild.a; sourceTree = BUILT_PRODUCTS_DIR; }; + F4487C701A9F906200531423 /* GPBArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBArray.h; sourceTree = ""; }; + F4487C711A9F906200531423 /* GPBArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArray.m; sourceTree = ""; }; + F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Runtime.m"; sourceTree = ""; }; + F4487C7A1AADFB5500531423 /* unittest_runtime_proto2.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_runtime_proto2.proto; sourceTree = ""; }; + F4487C7B1AADFB5500531423 /* unittest_runtime_proto3.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_runtime_proto3.proto; sourceTree = ""; }; + F4487C7D1AAE06C500531423 /* GPBUtilities_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUtilities_PackagePrivate.h; sourceTree = ""; }; + F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Serialization.m"; sourceTree = ""; }; + F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Merge.m"; sourceTree = ""; }; + F44929021C866B3B00C2548A /* GPBCodedOutputStream_PackagePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBCodedOutputStream_PackagePrivate.h; sourceTree = ""; }; + F451D3F61A8AAEA600B8A22C /* GPBProtocolBuffers_RuntimeSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers_RuntimeSupport.h; sourceTree = ""; }; + F4584D801ECCB39E00803AB6 /* GPBExtensionRegistryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPBExtensionRegistryTest.m; path = Tests/GPBExtensionRegistryTest.m; sourceTree = SOURCE_ROOT; }; + F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionInternals.m; sourceTree = ""; }; + F45E57C81AE6DC98000B7D99 /* text_format_map_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_map_unittest_data.txt; sourceTree = ""; }; + F47CF96F23D904E500C7B24C /* GPBWrappers.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWrappers.pbobjc.h; sourceTree = ""; }; + F47CF97023D904E500C7B24C /* GPBFieldMask.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBFieldMask.pbobjc.h; sourceTree = ""; }; + F47CF97123D904E500C7B24C /* GPBApi.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBApi.pbobjc.m; sourceTree = ""; }; + F47CF97223D904E500C7B24C /* GPBEmpty.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBEmpty.pbobjc.m; sourceTree = ""; }; + F47CF97323D904E500C7B24C /* GPBSourceContext.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBSourceContext.pbobjc.h; sourceTree = ""; }; + F47CF97423D904E500C7B24C /* GPBDuration.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBDuration.pbobjc.h; sourceTree = ""; }; + F47CF97523D904E500C7B24C /* GPBStruct.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBStruct.pbobjc.m; sourceTree = ""; }; + F47CF97623D904E500C7B24C /* GPBFieldMask.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBFieldMask.pbobjc.m; sourceTree = ""; }; + F47CF97723D904E500C7B24C /* GPBDuration.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDuration.pbobjc.m; sourceTree = ""; }; + F47CF97823D904E600C7B24C /* GPBTimestamp.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBTimestamp.pbobjc.h; sourceTree = ""; }; + F47CF97923D904E600C7B24C /* GPBType.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBType.pbobjc.h; sourceTree = ""; }; + F47CF97A23D904E600C7B24C /* GPBType.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBType.pbobjc.m; sourceTree = ""; }; + F47CF97B23D904E600C7B24C /* GPBTimestamp.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBTimestamp.pbobjc.m; sourceTree = ""; }; + F47CF97C23D904E600C7B24C /* GPBApi.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBApi.pbobjc.h; sourceTree = ""; }; + F47CF97D23D904E600C7B24C /* GPBAny.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBAny.pbobjc.h; sourceTree = ""; }; + F47CF97E23D904E600C7B24C /* GPBEmpty.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBEmpty.pbobjc.h; sourceTree = ""; }; + F47CF97F23D904E600C7B24C /* GPBWrappers.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWrappers.pbobjc.m; sourceTree = ""; }; + F47CF98023D904E600C7B24C /* GPBAny.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBAny.pbobjc.m; sourceTree = ""; }; + F47CF98123D904E600C7B24C /* GPBStruct.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBStruct.pbobjc.h; sourceTree = ""; }; + F47CF98223D904E600C7B24C /* GPBSourceContext.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBSourceContext.pbobjc.m; sourceTree = ""; }; + F4AC9E1C1A8BEB1000BD6E83 /* unittest_cycle.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_cycle.proto; sourceTree = ""; }; + F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GPBObjectiveCPlusPlusTest.mm; sourceTree = ""; }; + F4B6B8B01A9CC99500892426 /* GPBUnknownField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField_PackagePrivate.h; sourceTree = ""; }; + F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet_PackagePrivate.h; sourceTree = ""; }; + F4B6B8B31A9CD1C600892426 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionInternals.h; sourceTree = ""; }; + F4B6B8B51A9CD1C600892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = ""; }; + F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDictionaryTests.m; sourceTree = ""; }; + F4CF31711B162EF500BD9B06 /* unittest_objc_startup.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc_startup.proto; sourceTree = ""; }; + F4E675D81B21D1DE0054530B /* any.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = any.proto; path = ../src/google/protobuf/any.proto; sourceTree = ""; }; + F4E675D91B21D1DE0054530B /* api.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = api.proto; path = ../src/google/protobuf/api.proto; sourceTree = ""; }; + F4E675DA1B21D1DE0054530B /* empty.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = empty.proto; path = ../src/google/protobuf/empty.proto; sourceTree = ""; }; + F4E675DB1B21D1DE0054530B /* field_mask.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = field_mask.proto; path = ../src/google/protobuf/field_mask.proto; sourceTree = ""; }; + F4E675DC1B21D1DE0054530B /* source_context.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = source_context.proto; path = ../src/google/protobuf/source_context.proto; sourceTree = ""; }; + F4E675DD1B21D1DE0054530B /* struct.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = struct.proto; path = ../src/google/protobuf/struct.proto; sourceTree = ""; }; + F4E675DE1B21D1DE0054530B /* type.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = type.proto; path = ../src/google/protobuf/type.proto; sourceTree = ""; }; + F4E675DF1B21D1DE0054530B /* wrappers.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = wrappers.proto; path = ../src/google/protobuf/wrappers.proto; sourceTree = ""; }; + F4F53F8B219CC5DF001EABF4 /* text_format_extensions_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_extensions_unittest_data.txt; sourceTree = ""; }; + F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos2.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7461B52C0F94FAF800A0C422 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7461B5360F94FB4600A0C422 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8BBEA4A3147C727100C4ADB7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */, + 8B9A5EEC18330A0F00A9D33B /* UIKit.framework in Frameworks */, + 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F4487C691A9F8F8100531423 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F4487C6A1A9F8F8100531423 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 080E96DDFE201D6D7F000001 /* Core Source */ = { + isa = PBXGroup; + children = ( + 7461B4CD0F94F99000A0C422 /* GPBProtocolBuffers.h */, + F451D3F61A8AAEA600B8A22C /* GPBProtocolBuffers_RuntimeSupport.h */, + 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */, + 7461B3C50F94F84100A0C422 /* Extensions */, + 7461B4850F94F96600A0C422 /* Fields */, + 7461B4860F94F96B00A0C422 /* IO */, + 7461B5150F94FA7300A0C422 /* Messages */, + 8BCF334414ED727300BC5317 /* Support */, + 29B97315FDCFA39411CA2CEA /* Generated */, + ); + name = "Core Source"; + sourceTree = ""; + }; + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */, + 8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */, + F4487C6E1A9F8F8100531423 /* libTestSingleSourceBuild.a */, + ); + name = Products; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { + isa = PBXGroup; + children = ( + 080E96DDFE201D6D7F000001 /* Core Source */, + 7461B6940F94FDDD00A0C422 /* Tests */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = CustomTemplate; + sourceTree = ""; + }; + 29B97315FDCFA39411CA2CEA /* Generated */ = { + isa = PBXGroup; + children = ( + F47CF97D23D904E600C7B24C /* GPBAny.pbobjc.h */, + F47CF98023D904E600C7B24C /* GPBAny.pbobjc.m */, + F47CF97C23D904E600C7B24C /* GPBApi.pbobjc.h */, + F47CF97123D904E500C7B24C /* GPBApi.pbobjc.m */, + F47CF97423D904E500C7B24C /* GPBDuration.pbobjc.h */, + F47CF97723D904E500C7B24C /* GPBDuration.pbobjc.m */, + F47CF97E23D904E600C7B24C /* GPBEmpty.pbobjc.h */, + F47CF97223D904E500C7B24C /* GPBEmpty.pbobjc.m */, + F47CF97023D904E500C7B24C /* GPBFieldMask.pbobjc.h */, + F47CF97623D904E500C7B24C /* GPBFieldMask.pbobjc.m */, + F47CF97323D904E500C7B24C /* GPBSourceContext.pbobjc.h */, + F47CF98223D904E600C7B24C /* GPBSourceContext.pbobjc.m */, + F47CF98123D904E600C7B24C /* GPBStruct.pbobjc.h */, + F47CF97523D904E500C7B24C /* GPBStruct.pbobjc.m */, + F47CF97823D904E600C7B24C /* GPBTimestamp.pbobjc.h */, + F47CF97B23D904E600C7B24C /* GPBTimestamp.pbobjc.m */, + F47CF97923D904E600C7B24C /* GPBType.pbobjc.h */, + F47CF97A23D904E600C7B24C /* GPBType.pbobjc.m */, + F47CF96F23D904E500C7B24C /* GPBWrappers.pbobjc.h */, + F47CF97F23D904E600C7B24C /* GPBWrappers.pbobjc.m */, + F4E675D81B21D1DE0054530B /* any.proto */, + F4E675D91B21D1DE0054530B /* api.proto */, + 8B42494A1A92A0BA00BC1EC6 /* duration.proto */, + F4E675DA1B21D1DE0054530B /* empty.proto */, + F4E675DB1B21D1DE0054530B /* field_mask.proto */, + F4E675DC1B21D1DE0054530B /* source_context.proto */, + F4E675DD1B21D1DE0054530B /* struct.proto */, + 8B4249481A92A02300BC1EC6 /* timestamp.proto */, + F4E675DE1B21D1DE0054530B /* type.proto */, + F4E675DF1B21D1DE0054530B /* wrappers.proto */, + ); + name = Generated; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8B9742421A8AAA7800DCE92C /* CoreGraphics.framework */, + 8B9A5E9F1831913D00A9D33B /* UIKit.framework */, + 1D30AB110D05D00D00671497 /* Foundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 7461B3C50F94F84100A0C422 /* Extensions */ = { + isa = PBXGroup; + children = ( + F4B6B8B31A9CD1C600892426 /* GPBExtensionInternals.h */, + F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */, + 7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */, + 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */, + F4B6B8B51A9CD1C600892426 /* GPBRootObject_PackagePrivate.h */, + 8B79657814992E3E002FFBFC /* GPBRootObject.h */, + 8B79657914992E3E002FFBFC /* GPBRootObject.m */, + ); + name = Extensions; + sourceTree = ""; + }; + 7461B4850F94F96600A0C422 /* Fields */ = { + isa = PBXGroup; + children = ( + F4B6B8B01A9CC99500892426 /* GPBUnknownField_PackagePrivate.h */, + 7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */, + 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */, + F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */, + 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */, + 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */, + ); + name = Fields; + sourceTree = ""; + }; + 7461B4860F94F96B00A0C422 /* IO */ = { + isa = PBXGroup; + children = ( + 51457B5F18D0B7AF00CCC606 /* GPBCodedInputStream_PackagePrivate.h */, + 7461B48E0F94F99000A0C422 /* GPBCodedInputStream.h */, + 7461B48F0F94F99000A0C422 /* GPBCodedInputStream.m */, + F44929021C866B3B00C2548A /* GPBCodedOutputStream_PackagePrivate.h */, + 7461B4900F94F99000A0C422 /* GPBCodedOutputStream.h */, + 7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */, + 7461B4E70F94F99000A0C422 /* GPBWireFormat.h */, + 7461B4E80F94F99000A0C422 /* GPBWireFormat.m */, + ); + name = IO; + sourceTree = ""; + }; + 7461B5150F94FA7300A0C422 /* Messages */ = { + isa = PBXGroup; + children = ( + 515B840C18B7DEE30031753B /* GPBDescriptor_PackagePrivate.h */, + 8B96157214C8B06000A2AC0B /* GPBDescriptor.h */, + 8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */, + 7461B4BE0F94F99000A0C422 /* GPBMessage.h */, + 5196A06918CE16B000B759E2 /* GPBMessage_PackagePrivate.h */, + 7461B4BF0F94F99000A0C422 /* GPBMessage.m */, + ); + name = Messages; + sourceTree = ""; + }; + 7461B6940F94FDDD00A0C422 /* Tests */ = { + isa = PBXGroup; + children = ( + 8B210CCD159383D60032D72D /* golden_message */, + 8B210CCF159386920032D72D /* golden_packed_fields_message */, + 8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */, + F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */, + 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */, + 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */, + F40EE4CD206BF9170071091A /* GPBCompileTest01.m */, + F40EE4C6206BF9170071091A /* GPBCompileTest02.m */, + F40EE4D6206BF9190071091A /* GPBCompileTest03.m */, + F40EE4C3206BF9160071091A /* GPBCompileTest04.m */, + F40EE4C4206BF9160071091A /* GPBCompileTest05.m */, + F40EE4D7206BF9190071091A /* GPBCompileTest06.m */, + F40EE4C5206BF9170071091A /* GPBCompileTest07.m */, + F40EE4C2206BF9160071091A /* GPBCompileTest08.m */, + F40EE4C9206BF9170071091A /* GPBCompileTest09.m */, + F40EE4D1206BF9180071091A /* GPBCompileTest10.m */, + F40EE4D8206BF9190071091A /* GPBCompileTest11.m */, + F40EE4D5206BF9180071091A /* GPBCompileTest12.m */, + F40EE4C8206BF9170071091A /* GPBCompileTest13.m */, + F40EE4D4206BF9180071091A /* GPBCompileTest14.m */, + F40EE4CE206BF9170071091A /* GPBCompileTest15.m */, + F40EE4D0206BF9180071091A /* GPBCompileTest16.m */, + F40EE4D2206BF9180071091A /* GPBCompileTest17.m */, + F40EE4D3206BF9180071091A /* GPBCompileTest18.m */, + F40EE4C7206BF9170071091A /* GPBCompileTest19.m */, + F40EE4CA206BF9170071091A /* GPBCompileTest20.m */, + F40EE4CB206BF9170071091A /* GPBCompileTest21.m */, + F40EE4CF206BF9170071091A /* GPBCompileTest22.m */, + F40EE4CC206BF9170071091A /* GPBCompileTest23.m */, + F40EE50E206C06880071091A /* GPBCompileTest24.m */, + F40EE50D206C06880071091A /* GPBCompileTest25.m */, + 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */, + F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */, + F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */, + F4353D3A1AC06F31005A6198 /* GPBDictionaryTests.pddm */, + F4353D3B1AC06F31005A6198 /* GPBDictionaryTests+Bool.m */, + F4353D3C1AC06F31005A6198 /* GPBDictionaryTests+Int32.m */, + F4353D3D1AC06F31005A6198 /* GPBDictionaryTests+Int64.m */, + F4353D3E1AC06F31005A6198 /* GPBDictionaryTests+String.m */, + F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */, + F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */, + F4584D801ECCB39E00803AB6 /* GPBExtensionRegistryTest.m */, + 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */, + F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */, + F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */, + 8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */, + F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */, + F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */, + F41C175C1833D3310064ED4D /* GPBPerfTests.m */, + 8B4248B31A8BD96E00BC1EC6 /* GPBSwiftTests.swift */, + 7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */, + 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */, + 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */, + F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */, + 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */, + 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */, + 8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */, + 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */, + F4F53F8B219CC5DF001EABF4 /* text_format_extensions_unittest_data.txt */, + F45E57C81AE6DC98000B7D99 /* text_format_map_unittest_data.txt */, + F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */, + 8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */, + F4AC9E1C1A8BEB1000BD6E83 /* unittest_cycle.proto */, + 8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */, + 8B7E6A7614893DBA00F8884A /* unittest_empty.proto */, + 8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */, + 8B7E6A7814893DBB00F8884A /* unittest_import.proto */, + 8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */, + 8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */, + 8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */, + 8B35468621A61EB2000BD30D /* unittest_objc_options.proto */, + F4CF31711B162EF500BD9B06 /* unittest_objc_startup.proto */, + 8B09AAF614B663A7007B4184 /* unittest_objc.proto */, + 8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */, + F4487C7A1AADFB5500531423 /* unittest_runtime_proto2.proto */, + F4487C7B1AADFB5500531423 /* unittest_runtime_proto3.proto */, + 8B7E6A7E14893DBC00F8884A /* unittest.proto */, + 8B4248B21A8BD96D00BC1EC6 /* UnitTests-Bridging-Header.h */, + 7401C1A90F950347006D8281 /* UnitTests-Info.plist */, + ); + path = Tests; + sourceTree = ""; + }; + 8BCF334414ED727300BC5317 /* Support */ = { + isa = PBXGroup; + children = ( + F4411BE81AF1301700324B4A /* GPBArray_PackagePrivate.h */, + F4487C701A9F906200531423 /* GPBArray.h */, + F4487C711A9F906200531423 /* GPBArray.m */, + 7461B48D0F94F99000A0C422 /* GPBBootstrap.h */, + F43725921AC9835D004DCAFB /* GPBDictionary_PackagePrivate.h */, + F4353D241ABB156F005A6198 /* GPBDictionary.h */, + F4353D251ABB156F005A6198 /* GPBDictionary.m */, + 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */, + F4487C7D1AAE06C500531423 /* GPBUtilities_PackagePrivate.h */, + 7461B4E50F94F99000A0C422 /* GPBUtilities.h */, + 7461B4E60F94F99000A0C422 /* GPBUtilities.m */, + 8B4248E11A929C8900BC1EC6 /* GPBWellKnownTypes.h */, + 8B4248E21A929C8900BC1EC6 /* GPBWellKnownTypes.m */, + ); + name = Support; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 7461B52A0F94FAF800A0C422 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F4487C561A9F8F8100531423 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXLegacyTarget section */ + F45BBC0E1B0CDB50002D064D /* Compile Unittest Protos */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(ACTION)"; + buildConfigurationList = F45BBC111B0CDB50002D064D /* Build configuration list for PBXLegacyTarget "Compile Unittest Protos" */; + buildPhases = ( + ); + buildToolPath = DevTools/compile_testing_protos.sh; + buildWorkingDirectory = ""; + dependencies = ( + ); + name = "Compile Unittest Protos"; + passBuildSettingsInEnvironment = 1; + productName = "Compile Unittest Protos"; + }; +/* End PBXLegacyTarget section */ + +/* Begin PBXNativeTarget section */ + 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7461B5330F94FAFD00A0C422 /* Build configuration list for PBXNativeTarget "ProtocolBuffers" */; + buildPhases = ( + 7461B52A0F94FAF800A0C422 /* Headers */, + 7461B52B0F94FAF800A0C422 /* Sources */, + 7461B52C0F94FAF800A0C422 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ProtocolBuffers; + productName = "ProtocolBuffers-iPhoneDevice"; + productReference = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; + productType = "com.apple.product-type.library.static"; + }; + 8BBEA4A5147C727100C4ADB7 /* UnitTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8BBEA4BA147C728600C4ADB7 /* Build configuration list for PBXNativeTarget "UnitTests" */; + buildPhases = ( + F4B62A791AF91F7500AFCEDC /* Script: Check Runtime Stamps */, + 8BBEA4A1147C727100C4ADB7 /* Resources */, + 8BBEA4A2147C727100C4ADB7 /* Sources */, + 8BBEA4A3147C727100C4ADB7 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 8BBEA4BD147C729A00C4ADB7 /* PBXTargetDependency */, + F45BBC131B0CDBBA002D064D /* PBXTargetDependency */, + ); + name = UnitTests; + productName = UnitTests; + productReference = 8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + F4487C551A9F8F8100531423 /* TestSingleSourceBuild */ = { + isa = PBXNativeTarget; + buildConfigurationList = F4487C6B1A9F8F8100531423 /* Build configuration list for PBXNativeTarget "TestSingleSourceBuild" */; + buildPhases = ( + F4487C561A9F8F8100531423 /* Headers */, + F4487C5A1A9F8F8100531423 /* Sources */, + F4487C691A9F8F8100531423 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = TestSingleSourceBuild; + productName = "ProtocolBuffers-iPhoneDevice"; + productReference = F4487C6E1A9F8F8100531423 /* libTestSingleSourceBuild.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0710; + LastTestingUpgradeCheck = 0600; + LastUpgradeCheck = 0930; + TargetAttributes = { + 8BBEA4A5147C727100C4ADB7 = { + LastSwiftMigration = 0940; + TestTargetID = 8B9A5EA41831993600A9D33B; + }; + F45BBC0E1B0CDB50002D064D = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_tvOS" */; + compatibilityVersion = "Xcode 6.3"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + en, + ); + mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */, + 8BBEA4A5147C727100C4ADB7 /* UnitTests */, + F4487C551A9F8F8100531423 /* TestSingleSourceBuild */, + F45BBC0E1B0CDB50002D064D /* Compile Unittest Protos */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8BBEA4A1147C727100C4ADB7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8B210CCE159383D60032D72D /* golden_message in Resources */, + F4F53F8C219CC5DF001EABF4 /* text_format_extensions_unittest_data.txt in Resources */, + F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */, + 8B210CD0159386920032D72D /* golden_packed_fields_message in Resources */, + F45E57C91AE6DC98000B7D99 /* text_format_map_unittest_data.txt in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + F4B62A791AF91F7500AFCEDC /* Script: Check Runtime Stamps */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Script: Check Runtime Stamps"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "set -eu\nexec \"${SOURCE_ROOT}/DevTools/check_version_stamps.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7461B52B0F94FAF800A0C422 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */, + F4487C731A9F906200531423 /* GPBArray.m in Sources */, + F47CF98923D904E600C7B24C /* GPBStruct.pbobjc.m in Sources */, + F47CF98623D904E600C7B24C /* GPBEmpty.pbobjc.m in Sources */, + 7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */, + F47CF98523D904E600C7B24C /* GPBApi.pbobjc.m in Sources */, + 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */, + 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */, + F47CF98E23D904E600C7B24C /* GPBType.pbobjc.m in Sources */, + F47CF99623D904E600C7B24C /* GPBSourceContext.pbobjc.m in Sources */, + 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */, + F47CF99323D904E600C7B24C /* GPBWrappers.pbobjc.m in Sources */, + F47CF98F23D904E600C7B24C /* GPBTimestamp.pbobjc.m in Sources */, + 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */, + 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */, + 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */, + F4353D271ABB156F005A6198 /* GPBDictionary.m in Sources */, + F47CF98B23D904E600C7B24C /* GPBDuration.pbobjc.m in Sources */, + 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */, + 8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */, + F47CF98A23D904E600C7B24C /* GPBFieldMask.pbobjc.m in Sources */, + F47CF99423D904E600C7B24C /* GPBAny.pbobjc.m in Sources */, + F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */, + 8B4248E41A929C8900BC1EC6 /* GPBWellKnownTypes.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8BBEA4A2147C727100C4ADB7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */, + F40EE511206C068D0071091A /* GPBCompileTest24.m in Sources */, + F40EE503206BF91E0071091A /* GPBCompileTest20.m in Sources */, + F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */, + F40EE4F9206BF91E0071091A /* GPBCompileTest10.m in Sources */, + F4353D441AC06F31005A6198 /* GPBDictionaryTests+Int64.m in Sources */, + F40EE505206BF91E0071091A /* GPBCompileTest22.m in Sources */, + F40EE4F7206BF91E0071091A /* GPBCompileTest08.m in Sources */, + F40EE500206BF91E0071091A /* GPBCompileTest17.m in Sources */, + F4353D471AC06F31005A6198 /* GPBDictionaryTests+UInt64.m in Sources */, + 8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */, + F40EE506206BF91E0071091A /* GPBCompileTest23.m in Sources */, + 8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */, + F4487C811AAF62FC00531423 /* GPBMessageTests+Serialization.m in Sources */, + F40EE502206BF91E0071091A /* GPBCompileTest19.m in Sources */, + F40EE4F5206BF91E0071091A /* GPBCompileTest06.m in Sources */, + F40EE4FB206BF91E0071091A /* GPBCompileTest12.m in Sources */, + 8B4248E61A929C9900BC1EC6 /* GPBWellKnownTypesTest.m in Sources */, + F40EE4F2206BF91E0071091A /* GPBCompileTest03.m in Sources */, + F40EE501206BF91E0071091A /* GPBCompileTest18.m in Sources */, + F40EE4FC206BF91E0071091A /* GPBCompileTest13.m in Sources */, + F40EE4FE206BF91E0071091A /* GPBCompileTest15.m in Sources */, + F40EE4F6206BF91E0071091A /* GPBCompileTest07.m in Sources */, + F4353D1F1AB88243005A6198 /* GPBDescriptorTests.m in Sources */, + F40EE504206BF91E0071091A /* GPBCompileTest21.m in Sources */, + F40EE4FA206BF91E0071091A /* GPBCompileTest11.m in Sources */, + F4F8D8861D78A193002CE128 /* GPBUnittestProtos2.m in Sources */, + F4B51B1C1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */, + 8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */, + F40EE512206C068D0071091A /* GPBCompileTest25.m in Sources */, + F4584D831ECCB53600803AB6 /* GPBExtensionRegistryTest.m in Sources */, + 8BFF9D1E23AD599400E63E32 /* GPBMessageTests+ClassNames.m in Sources */, + 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */, + F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */, + F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */, + F4353D431AC06F31005A6198 /* GPBDictionaryTests+Int32.m in Sources */, + F40EE4F4206BF91E0071091A /* GPBCompileTest05.m in Sources */, + F40EE4FD206BF91E0071091A /* GPBCompileTest14.m in Sources */, + 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */, + F40EE4F3206BF91E0071091A /* GPBCompileTest04.m in Sources */, + F40EE4FF206BF91E0071091A /* GPBCompileTest16.m in Sources */, + F41C175D1833D3310064ED4D /* GPBPerfTests.m in Sources */, + F4353D421AC06F31005A6198 /* GPBDictionaryTests+Bool.m in Sources */, + F4487C851AAF6AC500531423 /* GPBMessageTests+Merge.m in Sources */, + F40EE4F0206BF91E0071091A /* GPBCompileTest01.m in Sources */, + 8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */, + F4353D451AC06F31005A6198 /* GPBDictionaryTests+String.m in Sources */, + F4353D461AC06F31005A6198 /* GPBDictionaryTests+UInt32.m in Sources */, + F40EE4F8206BF91E0071091A /* GPBCompileTest09.m in Sources */, + 8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */, + F4C4B9E71E1D97BF00D3B61D /* GPBDictionaryTests.m in Sources */, + 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */, + 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */, + 8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F4487C5A1A9F8F8100531423 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F4487C6F1A9F8FFF00531423 /* GPBProtocolBuffers.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 8BBEA4BD147C729A00C4ADB7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */; + targetProxy = 8BBEA4BC147C729A00C4ADB7 /* PBXContainerItemProxy */; + }; + F45BBC131B0CDBBA002D064D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = F45BBC0E1B0CDB50002D064D /* Compile Unittest Protos */; + targetProxy = F45BBC121B0CDBBA002D064D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 7461B52F0F94FAFA00A0C422 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; + PRODUCT_NAME = ProtocolBuffers; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; + }; + name = Debug; + }; + 7461B5300F94FAFA00A0C422 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; + PRODUCT_NAME = ProtocolBuffers; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; + }; + name = Release; + }; + 8BBEA4A7147C727100C4ADB7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + FRAMEWORK_SEARCH_PATHS = ( + "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", + "$(inherited)", + ); + INFOPLIST_FILE = "Tests/UnitTests-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(DEVELOPER_DIR)/usr/lib\"", + ); + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = UnitTests; + SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + USER_HEADER_SEARCH_PATHS = "${PROJECT_DERIVED_FILE_DIR}/protos $(SRCROOT)"; + WARNING_CFLAGS = ( + "$(inherited)", + "-Wno-documentation-unknown-command", + "-Wno-reserved-id-macro", + "-Wno-direct-ivar-access", + ); + }; + name = Debug; + }; + 8BBEA4A8147C727100C4ADB7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + FRAMEWORK_SEARCH_PATHS = ( + "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", + "$(inherited)", + ); + INFOPLIST_FILE = "Tests/UnitTests-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(DEVELOPER_DIR)/usr/lib\"", + ); + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = UnitTests; + SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h"; + SWIFT_VERSION = 4.0; + USER_HEADER_SEARCH_PATHS = "${PROJECT_DERIVED_FILE_DIR}/protos $(SRCROOT)"; + WARNING_CFLAGS = ( + "$(inherited)", + "-Wno-documentation-unknown-command", + "-Wno-reserved-id-macro", + "-Wno-direct-ivar-access", + ); + }; + name = Release; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; + CLANG_STATIC_ANALYZER_MODE = deep; + CLANG_WARN_ASSIGN_ENUM = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; + CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES; + CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_PROFILING_CODE = NO; + ONLY_ACTIVE_ARCH = YES; + RUN_CLANG_STATIC_ANALYZER = YES; + SDKROOT = appletvos; + TVOS_DEPLOYMENT_TARGET = 9.0; + WARNING_CFLAGS = ( + "-Wdocumentation-unknown-command", + "-Wundef", + "-Wreserved-id-macro", + "-Wswitch-enum", + "-Wdirect-ivar-access", + "-Woverriding-method-mismatch", + ); + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; + CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; + CLANG_STATIC_ANALYZER_MODE = deep; + CLANG_WARN_ASSIGN_ENUM = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; + CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES; + CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_PROFILING_CODE = NO; + RUN_CLANG_STATIC_ANALYZER = YES; + SDKROOT = appletvos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TVOS_DEPLOYMENT_TARGET = 9.0; + WARNING_CFLAGS = ( + "-Wdocumentation-unknown-command", + "-Wundef", + "-Wreserved-id-macro", + "-Wswitch-enum", + "-Wdirect-ivar-access", + "-Woverriding-method-mismatch", + ); + }; + name = Release; + }; + F4487C6C1A9F8F8100531423 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; + PRODUCT_NAME = TestSingleSourceBuild; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; + }; + name = Debug; + }; + F4487C6D1A9F8F8100531423 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; + PRODUCT_NAME = TestSingleSourceBuild; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; + }; + name = Release; + }; + F45BBC0F1B0CDB50002D064D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; + }; + name = Debug; + }; + F45BBC101B0CDB50002D064D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7461B5330F94FAFD00A0C422 /* Build configuration list for PBXNativeTarget "ProtocolBuffers" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7461B52F0F94FAFA00A0C422 /* Debug */, + 7461B5300F94FAFA00A0C422 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8BBEA4BA147C728600C4ADB7 /* Build configuration list for PBXNativeTarget "UnitTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8BBEA4A7147C727100C4ADB7 /* Debug */, + 8BBEA4A8147C727100C4ADB7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + C01FCF5008A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F4487C6B1A9F8F8100531423 /* Build configuration list for PBXNativeTarget "TestSingleSourceBuild" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F4487C6C1A9F8F8100531423 /* Debug */, + F4487C6D1A9F8F8100531423 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F45BBC111B0CDB50002D064D /* Build configuration list for PBXLegacyTarget "Compile Unittest Protos" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F45BBC0F1B0CDB50002D064D /* Debug */, + F45BBC101B0CDB50002D064D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000000..4c32c7f836c0a --- /dev/null +++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000000..18d981003d68d --- /dev/null +++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000000000..08de0be8d3c8c --- /dev/null +++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme new file mode 100644 index 0000000000000..b11dc6ea937f8 --- /dev/null +++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme @@ -0,0 +1,370 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme new file mode 100644 index 0000000000000..25d047a1886fd --- /dev/null +++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/objectivec/README.md b/objectivec/README.md index 7226f0b9a189c..2583779d38f0d 100644 --- a/objectivec/README.md +++ b/objectivec/README.md @@ -1,7 +1,7 @@ Protocol Buffers - Google's data interchange format =================================================== -[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) +[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_cocoapods_integration.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_cocoapods_integration%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_ios_debug.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_ios_debug%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_ios_release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_ios_release%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_osx.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_osx%2Fcontinuous) Copyright 2008 Google Inc. @@ -13,16 +13,17 @@ Requirements The Objective C implementation requires: - Objective C 2.0 Runtime (32bit & 64bit iOS, 64bit OS X). -- Xcode 7.0 (or later). +- Xcode 10.3 (or later). - The library code does *not* use ARC (for performance reasons), but it all can be called from ARC code. Installation ------------ -The full distribution pulled from github includes the sources for both the -compiler (protoc) and the runtime (this directory). To build the compiler -and run the runtime tests, you can use: +The distribution pulled from github includes the sources for both the +compiler (protoc) and the runtime (this directory). After cloning the distribution +and needed submodules ([see the src directory's README](../src/README.md)), +to build the compiler and run the runtime tests, you can use: $ objectivec/DevTools/full_mac_build.sh @@ -33,19 +34,21 @@ Building There are two ways to include the Runtime sources in your project: -Add `objectivec/\*.h` & `objectivec/GPBProtocolBuffers.m` to your project. +Add `objectivec/*.h`, `objectivec/google/protobuf/*.pbobjc.h`, and +`objectivec/GPBProtocolBuffers.m` to your project. *or* -Add `objectivec/\*.h` & `objectivec/\*.m` except for +Add `objectivec/*.h`, `objectivec/google/protobuf/*.pbobjc.h`, +`objectivec/google/protobuf/*.pbobjc.m`, and `objectivec/*.m` except for `objectivec/GPBProtocolBuffers.m` to your project. If the target is using ARC, remember to turn off ARC (`-fno-objc-arc`) for the `.m` files. -The files generated by `protoc` for the `*.proto` files (`\*.pbobjc.h` and -`\*.pbobjc.m`) are then also added to the target. +The files generated by `protoc` for the `*.proto` files (`*.pbobjc.h` and +`*.pbobjc.m`) are then also added to the target. Usage ----- @@ -165,10 +168,16 @@ supported keys are: Any number of files can be listed for a framework, just separate them with commas. - There can be multiple lines listing the same frameworkName incase it has a + There can be multiple lines listing the same frameworkName in case it has a lot of proto files included in it; and having multiple lines makes things easier to read. + * `runtime_import_prefix`: The `value` used for this key to be used as a + prefix on `#import`s of runtime provided headers in the generated files. + When integrating ObjC protos into a build system, this can be used to avoid + having to add the runtime directory to the header search path since the + generate `#import` will be more complete. + Contributing ------------ diff --git a/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-framework b/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-framework index 913a289b8ec15..e0ee905514527 100644 --- a/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-framework +++ b/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-framework @@ -1,5 +1,5 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, '9.0' install! 'cocoapods', :deterministic_uuids => false diff --git a/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-static b/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-static index e9b3c235dd169..1bb8cb2e1aa49 100644 --- a/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-static +++ b/objectivec/Tests/CocoaPods/iOSCocoaPodsTester/Podfile-static @@ -1,5 +1,5 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, '9.0' install! 'cocoapods', :deterministic_uuids => false diff --git a/objectivec/Tests/CocoaPods/run_tests.sh b/objectivec/Tests/CocoaPods/run_tests.sh index 6d3e12be30f28..35bcc18df7a9d 100755 --- a/objectivec/Tests/CocoaPods/run_tests.sh +++ b/objectivec/Tests/CocoaPods/run_tests.sh @@ -90,7 +90,7 @@ cleanup() { echo "Cleaning up..." # Generally don't let things fail, and eat common stdout, but let stderr show - # incase something does hiccup. + # in case something does hiccup. xcodebuild -workspace "${TEST_NAME}.xcworkspace" -scheme "${TEST_NAME}" clean > /dev/null || true pod deintegrate > /dev/null || true # Flush the cache so nothing is left behind. diff --git a/objectivec/Tests/GPBArrayTests.m b/objectivec/Tests/GPBArrayTests.m index 31f75501dc085..9b004bc33857d 100644 --- a/objectivec/Tests/GPBArrayTests.m +++ b/objectivec/Tests/GPBArrayTests.m @@ -39,6 +39,7 @@ // To let the testing macros work, add some extra methods to simplify things. @interface GPBEnumArray (TestingTweak) + (instancetype)arrayWithValue:(int32_t)value; ++ (instancetype)arrayWithCapacity:(NSUInteger)count; - (instancetype)initWithValues:(const int32_t [])values count:(NSUInteger)count; @end @@ -72,6 +73,10 @@ + (instancetype)arrayWithValue:(int32_t)value { rawValues:&value count:1] autorelease]; } ++ (instancetype)arrayWithCapacity:(NSUInteger)count { + return [[[self alloc] initWithValidationFunction:TestingEnum_IsValidValue + capacity:count] autorelease]; +} - (instancetype)initWithValues:(const int32_t [])values count:(NSUInteger)count { return [self initWithValidationFunction:TestingEnum_IsValidValue @@ -177,6 +182,8 @@ - (instancetype)initWithValues:(const int32_t [])values //% XCTAssertNotEqual(idx, 0U); //% ++idx2; //% }]; +//% // Ensure description doesn't choke. +//% XCTAssertTrue(array.description.length > 10); //% [array release]; //%} //% @@ -201,6 +208,10 @@ - (instancetype)initWithValues:(const int32_t [])values //% NAME$S count:GPBARRAYSIZE(kValues3)]; //% XCTAssertNotNil(array3); //% +//% // Identity +//% XCTAssertTrue([array1 isEqual:array1]); +//% // Wrong type doesn't blow up. +//% XCTAssertFalse([array1 isEqual:@"bogus"]); //% // 1/1Prime should be different objects, but equal. //% XCTAssertNotEqual(array1, array1prime); //% XCTAssertEqualObjects(array1, array1prime); @@ -271,6 +282,12 @@ - (instancetype)initWithValues:(const int32_t [])values //% [array add##HELPER##ValuesFromArray:array2]; //% XCTAssertEqual(array.count, 5U); //% +//% // Zero/nil inputs do nothing. +//% [array addValues:kValues1 count:0]; +//% XCTAssertEqual(array.count, 5U); +//% [array addValues:NULL count:5]; +//% XCTAssertEqual(array.count, 5U); +//% //% XCTAssertEqual([array valueAtIndex:0], VAL1); //% XCTAssertEqual([array valueAtIndex:1], VAL2); //% XCTAssertEqual([array valueAtIndex:2], VAL3); @@ -391,9 +408,9 @@ - (instancetype)initWithValues:(const int32_t [])values //%- (void)testInternalResizing { //% const TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; //% GPB##NAME##Array *array = -//% [[GPB##NAME##Array alloc] initWithValues:kValues -//% NAME$S count:GPBARRAYSIZE(kValues)]; +//% [GPB##NAME##Array arrayWithCapacity:GPBARRAYSIZE(kValues)]; //% XCTAssertNotNil(array); +//% [array addValues:kValues count:GPBARRAYSIZE(kValues)]; //% //% // Add/remove to trigger the intneral buffer to grow/shrink. //% for (int i = 0; i < 100; ++i) { @@ -410,13 +427,13 @@ - (instancetype)initWithValues:(const int32_t [])values //% XCTAssertEqual(array.count, 404U); //% [array removeAll]; //% XCTAssertEqual(array.count, 0U); -//% [array release]; //%} //% //%@end //% //%PDDM-EXPAND ARRAY_TESTS(Int32, int32_t, 1, 2, 3, 4) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Int32 @@ -510,6 +527,8 @@ - (void)testBasics { XCTAssertNotEqual(idx, 0U); ++idx2; }]; + // Ensure description doesn't choke. + XCTAssertTrue(array.description.length > 10); [array release]; } @@ -534,6 +553,10 @@ - (void)testEquality { count:GPBARRAYSIZE(kValues3)]; XCTAssertNotNil(array3); + // Identity + XCTAssertTrue([array1 isEqual:array1]); + // Wrong type doesn't blow up. + XCTAssertFalse([array1 isEqual:@"bogus"]); // 1/1Prime should be different objects, but equal. XCTAssertNotEqual(array1, array1prime); XCTAssertEqualObjects(array1, array1prime); @@ -604,6 +627,12 @@ - (void)testAdds { [array addValuesFromArray:array2]; XCTAssertEqual(array.count, 5U); + // Zero/nil inputs do nothing. + [array addValues:kValues1 count:0]; + XCTAssertEqual(array.count, 5U); + [array addValues:NULL count:5]; + XCTAssertEqual(array.count, 5U); + XCTAssertEqual([array valueAtIndex:0], 1); XCTAssertEqual([array valueAtIndex:1], 2); XCTAssertEqual([array valueAtIndex:2], 3); @@ -724,9 +753,9 @@ - (void)testInplaceMutation { - (void)testInternalResizing { const int32_t kValues[] = { 1, 2, 3, 4 }; GPBInt32Array *array = - [[GPBInt32Array alloc] initWithValues:kValues - count:GPBARRAYSIZE(kValues)]; + [GPBInt32Array arrayWithCapacity:GPBARRAYSIZE(kValues)]; XCTAssertNotNil(array); + [array addValues:kValues count:GPBARRAYSIZE(kValues)]; // Add/remove to trigger the intneral buffer to grow/shrink. for (int i = 0; i < 100; ++i) { @@ -743,13 +772,14 @@ - (void)testInternalResizing { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); - [array release]; } @end +// clang-format on //%PDDM-EXPAND ARRAY_TESTS(UInt32, uint32_t, 11U, 12U, 13U, 14U) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - UInt32 @@ -843,6 +873,8 @@ - (void)testBasics { XCTAssertNotEqual(idx, 0U); ++idx2; }]; + // Ensure description doesn't choke. + XCTAssertTrue(array.description.length > 10); [array release]; } @@ -867,6 +899,10 @@ - (void)testEquality { count:GPBARRAYSIZE(kValues3)]; XCTAssertNotNil(array3); + // Identity + XCTAssertTrue([array1 isEqual:array1]); + // Wrong type doesn't blow up. + XCTAssertFalse([array1 isEqual:@"bogus"]); // 1/1Prime should be different objects, but equal. XCTAssertNotEqual(array1, array1prime); XCTAssertEqualObjects(array1, array1prime); @@ -937,6 +973,12 @@ - (void)testAdds { [array addValuesFromArray:array2]; XCTAssertEqual(array.count, 5U); + // Zero/nil inputs do nothing. + [array addValues:kValues1 count:0]; + XCTAssertEqual(array.count, 5U); + [array addValues:NULL count:5]; + XCTAssertEqual(array.count, 5U); + XCTAssertEqual([array valueAtIndex:0], 11U); XCTAssertEqual([array valueAtIndex:1], 12U); XCTAssertEqual([array valueAtIndex:2], 13U); @@ -1057,9 +1099,9 @@ - (void)testInplaceMutation { - (void)testInternalResizing { const uint32_t kValues[] = { 11U, 12U, 13U, 14U }; GPBUInt32Array *array = - [[GPBUInt32Array alloc] initWithValues:kValues - count:GPBARRAYSIZE(kValues)]; + [GPBUInt32Array arrayWithCapacity:GPBARRAYSIZE(kValues)]; XCTAssertNotNil(array); + [array addValues:kValues count:GPBARRAYSIZE(kValues)]; // Add/remove to trigger the intneral buffer to grow/shrink. for (int i = 0; i < 100; ++i) { @@ -1076,13 +1118,14 @@ - (void)testInternalResizing { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); - [array release]; } @end +// clang-format on //%PDDM-EXPAND ARRAY_TESTS(Int64, int64_t, 31LL, 32LL, 33LL, 34LL) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Int64 @@ -1176,6 +1219,8 @@ - (void)testBasics { XCTAssertNotEqual(idx, 0U); ++idx2; }]; + // Ensure description doesn't choke. + XCTAssertTrue(array.description.length > 10); [array release]; } @@ -1200,6 +1245,10 @@ - (void)testEquality { count:GPBARRAYSIZE(kValues3)]; XCTAssertNotNil(array3); + // Identity + XCTAssertTrue([array1 isEqual:array1]); + // Wrong type doesn't blow up. + XCTAssertFalse([array1 isEqual:@"bogus"]); // 1/1Prime should be different objects, but equal. XCTAssertNotEqual(array1, array1prime); XCTAssertEqualObjects(array1, array1prime); @@ -1270,6 +1319,12 @@ - (void)testAdds { [array addValuesFromArray:array2]; XCTAssertEqual(array.count, 5U); + // Zero/nil inputs do nothing. + [array addValues:kValues1 count:0]; + XCTAssertEqual(array.count, 5U); + [array addValues:NULL count:5]; + XCTAssertEqual(array.count, 5U); + XCTAssertEqual([array valueAtIndex:0], 31LL); XCTAssertEqual([array valueAtIndex:1], 32LL); XCTAssertEqual([array valueAtIndex:2], 33LL); @@ -1390,9 +1445,9 @@ - (void)testInplaceMutation { - (void)testInternalResizing { const int64_t kValues[] = { 31LL, 32LL, 33LL, 34LL }; GPBInt64Array *array = - [[GPBInt64Array alloc] initWithValues:kValues - count:GPBARRAYSIZE(kValues)]; + [GPBInt64Array arrayWithCapacity:GPBARRAYSIZE(kValues)]; XCTAssertNotNil(array); + [array addValues:kValues count:GPBARRAYSIZE(kValues)]; // Add/remove to trigger the intneral buffer to grow/shrink. for (int i = 0; i < 100; ++i) { @@ -1409,13 +1464,14 @@ - (void)testInternalResizing { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); - [array release]; } @end +// clang-format on //%PDDM-EXPAND ARRAY_TESTS(UInt64, uint64_t, 41ULL, 42ULL, 43ULL, 44ULL) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - UInt64 @@ -1509,6 +1565,8 @@ - (void)testBasics { XCTAssertNotEqual(idx, 0U); ++idx2; }]; + // Ensure description doesn't choke. + XCTAssertTrue(array.description.length > 10); [array release]; } @@ -1533,6 +1591,10 @@ - (void)testEquality { count:GPBARRAYSIZE(kValues3)]; XCTAssertNotNil(array3); + // Identity + XCTAssertTrue([array1 isEqual:array1]); + // Wrong type doesn't blow up. + XCTAssertFalse([array1 isEqual:@"bogus"]); // 1/1Prime should be different objects, but equal. XCTAssertNotEqual(array1, array1prime); XCTAssertEqualObjects(array1, array1prime); @@ -1603,6 +1665,12 @@ - (void)testAdds { [array addValuesFromArray:array2]; XCTAssertEqual(array.count, 5U); + // Zero/nil inputs do nothing. + [array addValues:kValues1 count:0]; + XCTAssertEqual(array.count, 5U); + [array addValues:NULL count:5]; + XCTAssertEqual(array.count, 5U); + XCTAssertEqual([array valueAtIndex:0], 41ULL); XCTAssertEqual([array valueAtIndex:1], 42ULL); XCTAssertEqual([array valueAtIndex:2], 43ULL); @@ -1723,9 +1791,9 @@ - (void)testInplaceMutation { - (void)testInternalResizing { const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL, 44ULL }; GPBUInt64Array *array = - [[GPBUInt64Array alloc] initWithValues:kValues - count:GPBARRAYSIZE(kValues)]; + [GPBUInt64Array arrayWithCapacity:GPBARRAYSIZE(kValues)]; XCTAssertNotNil(array); + [array addValues:kValues count:GPBARRAYSIZE(kValues)]; // Add/remove to trigger the intneral buffer to grow/shrink. for (int i = 0; i < 100; ++i) { @@ -1742,13 +1810,14 @@ - (void)testInternalResizing { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); - [array release]; } @end +// clang-format on //%PDDM-EXPAND ARRAY_TESTS(Float, float, 51.f, 52.f, 53.f, 54.f) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Float @@ -1842,6 +1911,8 @@ - (void)testBasics { XCTAssertNotEqual(idx, 0U); ++idx2; }]; + // Ensure description doesn't choke. + XCTAssertTrue(array.description.length > 10); [array release]; } @@ -1866,6 +1937,10 @@ - (void)testEquality { count:GPBARRAYSIZE(kValues3)]; XCTAssertNotNil(array3); + // Identity + XCTAssertTrue([array1 isEqual:array1]); + // Wrong type doesn't blow up. + XCTAssertFalse([array1 isEqual:@"bogus"]); // 1/1Prime should be different objects, but equal. XCTAssertNotEqual(array1, array1prime); XCTAssertEqualObjects(array1, array1prime); @@ -1936,6 +2011,12 @@ - (void)testAdds { [array addValuesFromArray:array2]; XCTAssertEqual(array.count, 5U); + // Zero/nil inputs do nothing. + [array addValues:kValues1 count:0]; + XCTAssertEqual(array.count, 5U); + [array addValues:NULL count:5]; + XCTAssertEqual(array.count, 5U); + XCTAssertEqual([array valueAtIndex:0], 51.f); XCTAssertEqual([array valueAtIndex:1], 52.f); XCTAssertEqual([array valueAtIndex:2], 53.f); @@ -2056,9 +2137,9 @@ - (void)testInplaceMutation { - (void)testInternalResizing { const float kValues[] = { 51.f, 52.f, 53.f, 54.f }; GPBFloatArray *array = - [[GPBFloatArray alloc] initWithValues:kValues - count:GPBARRAYSIZE(kValues)]; + [GPBFloatArray arrayWithCapacity:GPBARRAYSIZE(kValues)]; XCTAssertNotNil(array); + [array addValues:kValues count:GPBARRAYSIZE(kValues)]; // Add/remove to trigger the intneral buffer to grow/shrink. for (int i = 0; i < 100; ++i) { @@ -2075,13 +2156,14 @@ - (void)testInternalResizing { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); - [array release]; } @end +// clang-format on //%PDDM-EXPAND ARRAY_TESTS(Double, double, 61., 62., 63., 64.) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Double @@ -2175,6 +2257,8 @@ - (void)testBasics { XCTAssertNotEqual(idx, 0U); ++idx2; }]; + // Ensure description doesn't choke. + XCTAssertTrue(array.description.length > 10); [array release]; } @@ -2199,6 +2283,10 @@ - (void)testEquality { count:GPBARRAYSIZE(kValues3)]; XCTAssertNotNil(array3); + // Identity + XCTAssertTrue([array1 isEqual:array1]); + // Wrong type doesn't blow up. + XCTAssertFalse([array1 isEqual:@"bogus"]); // 1/1Prime should be different objects, but equal. XCTAssertNotEqual(array1, array1prime); XCTAssertEqualObjects(array1, array1prime); @@ -2269,6 +2357,12 @@ - (void)testAdds { [array addValuesFromArray:array2]; XCTAssertEqual(array.count, 5U); + // Zero/nil inputs do nothing. + [array addValues:kValues1 count:0]; + XCTAssertEqual(array.count, 5U); + [array addValues:NULL count:5]; + XCTAssertEqual(array.count, 5U); + XCTAssertEqual([array valueAtIndex:0], 61.); XCTAssertEqual([array valueAtIndex:1], 62.); XCTAssertEqual([array valueAtIndex:2], 63.); @@ -2389,9 +2483,9 @@ - (void)testInplaceMutation { - (void)testInternalResizing { const double kValues[] = { 61., 62., 63., 64. }; GPBDoubleArray *array = - [[GPBDoubleArray alloc] initWithValues:kValues - count:GPBARRAYSIZE(kValues)]; + [GPBDoubleArray arrayWithCapacity:GPBARRAYSIZE(kValues)]; XCTAssertNotNil(array); + [array addValues:kValues count:GPBARRAYSIZE(kValues)]; // Add/remove to trigger the intneral buffer to grow/shrink. for (int i = 0; i < 100; ++i) { @@ -2408,13 +2502,14 @@ - (void)testInternalResizing { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); - [array release]; } @end +// clang-format on //%PDDM-EXPAND ARRAY_TESTS(Bool, BOOL, TRUE, TRUE, FALSE, FALSE) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool @@ -2508,6 +2603,8 @@ - (void)testBasics { XCTAssertNotEqual(idx, 0U); ++idx2; }]; + // Ensure description doesn't choke. + XCTAssertTrue(array.description.length > 10); [array release]; } @@ -2532,6 +2629,10 @@ - (void)testEquality { count:GPBARRAYSIZE(kValues3)]; XCTAssertNotNil(array3); + // Identity + XCTAssertTrue([array1 isEqual:array1]); + // Wrong type doesn't blow up. + XCTAssertFalse([array1 isEqual:@"bogus"]); // 1/1Prime should be different objects, but equal. XCTAssertNotEqual(array1, array1prime); XCTAssertEqualObjects(array1, array1prime); @@ -2602,6 +2703,12 @@ - (void)testAdds { [array addValuesFromArray:array2]; XCTAssertEqual(array.count, 5U); + // Zero/nil inputs do nothing. + [array addValues:kValues1 count:0]; + XCTAssertEqual(array.count, 5U); + [array addValues:NULL count:5]; + XCTAssertEqual(array.count, 5U); + XCTAssertEqual([array valueAtIndex:0], TRUE); XCTAssertEqual([array valueAtIndex:1], TRUE); XCTAssertEqual([array valueAtIndex:2], FALSE); @@ -2722,9 +2829,9 @@ - (void)testInplaceMutation { - (void)testInternalResizing { const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE }; GPBBoolArray *array = - [[GPBBoolArray alloc] initWithValues:kValues - count:GPBARRAYSIZE(kValues)]; + [GPBBoolArray arrayWithCapacity:GPBARRAYSIZE(kValues)]; XCTAssertNotNil(array); + [array addValues:kValues count:GPBARRAYSIZE(kValues)]; // Add/remove to trigger the intneral buffer to grow/shrink. for (int i = 0; i < 100; ++i) { @@ -2741,13 +2848,14 @@ - (void)testInternalResizing { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); - [array release]; } @end +// clang-format on //%PDDM-EXPAND ARRAY_TESTS2(Enum, int32_t, 71, 72, 73, 74, Raw) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Enum @@ -2841,6 +2949,8 @@ - (void)testBasics { XCTAssertNotEqual(idx, 0U); ++idx2; }]; + // Ensure description doesn't choke. + XCTAssertTrue(array.description.length > 10); [array release]; } @@ -2865,6 +2975,10 @@ - (void)testEquality { count:GPBARRAYSIZE(kValues3)]; XCTAssertNotNil(array3); + // Identity + XCTAssertTrue([array1 isEqual:array1]); + // Wrong type doesn't blow up. + XCTAssertFalse([array1 isEqual:@"bogus"]); // 1/1Prime should be different objects, but equal. XCTAssertNotEqual(array1, array1prime); XCTAssertEqualObjects(array1, array1prime); @@ -2935,6 +3049,12 @@ - (void)testAdds { [array addRawValuesFromArray:array2]; XCTAssertEqual(array.count, 5U); + // Zero/nil inputs do nothing. + [array addValues:kValues1 count:0]; + XCTAssertEqual(array.count, 5U); + [array addValues:NULL count:5]; + XCTAssertEqual(array.count, 5U); + XCTAssertEqual([array valueAtIndex:0], 71); XCTAssertEqual([array valueAtIndex:1], 72); XCTAssertEqual([array valueAtIndex:2], 73); @@ -3055,9 +3175,9 @@ - (void)testInplaceMutation { - (void)testInternalResizing { const int32_t kValues[] = { 71, 72, 73, 74 }; GPBEnumArray *array = - [[GPBEnumArray alloc] initWithValues:kValues - count:GPBARRAYSIZE(kValues)]; + [GPBEnumArray arrayWithCapacity:GPBARRAYSIZE(kValues)]; XCTAssertNotNil(array); + [array addValues:kValues count:GPBARRAYSIZE(kValues)]; // Add/remove to trigger the intneral buffer to grow/shrink. for (int i = 0; i < 100; ++i) { @@ -3074,11 +3194,11 @@ - (void)testInternalResizing { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); - [array release]; } @end +// clang-format on //%PDDM-EXPAND-END (8 expansions) #pragma mark - Non macro-based Enum tests diff --git a/objectivec/Tests/GPBCodedInputStreamTests.m b/objectivec/Tests/GPBCodedInputStreamTests.m index cc40215698c73..6cd5a1ffd7694 100644 --- a/objectivec/Tests/GPBCodedInputStreamTests.m +++ b/objectivec/Tests/GPBCodedInputStreamTests.m @@ -62,52 +62,101 @@ - (NSData*)bytes_with_sentinel:(int32_t)unused, ... { #define bytes(...) [self bytes_with_sentinel:0, __VA_ARGS__, 256] - (void)testDecodeZigZag { - XCTAssertEqual(0, GPBDecodeZigZag32(0)); - XCTAssertEqual(-1, GPBDecodeZigZag32(1)); - XCTAssertEqual(1, GPBDecodeZigZag32(2)); - XCTAssertEqual(-2, GPBDecodeZigZag32(3)); - XCTAssertEqual((int32_t)0x3FFFFFFF, GPBDecodeZigZag32(0x7FFFFFFE)); - XCTAssertEqual((int32_t)0xC0000000, GPBDecodeZigZag32(0x7FFFFFFF)); - XCTAssertEqual((int32_t)0x7FFFFFFF, GPBDecodeZigZag32(0xFFFFFFFE)); - XCTAssertEqual((int32_t)0x80000000, GPBDecodeZigZag32(0xFFFFFFFF)); - - XCTAssertEqual((int64_t)0, GPBDecodeZigZag64(0)); - XCTAssertEqual((int64_t)-1, GPBDecodeZigZag64(1)); - XCTAssertEqual((int64_t)1, GPBDecodeZigZag64(2)); - XCTAssertEqual((int64_t)-2, GPBDecodeZigZag64(3)); - XCTAssertEqual((int64_t)0x000000003FFFFFFFL, - GPBDecodeZigZag64(0x000000007FFFFFFEL)); - XCTAssertEqual((int64_t)0xFFFFFFFFC0000000L, - GPBDecodeZigZag64(0x000000007FFFFFFFL)); - XCTAssertEqual((int64_t)0x000000007FFFFFFFL, - GPBDecodeZigZag64(0x00000000FFFFFFFEL)); - XCTAssertEqual((int64_t)0xFFFFFFFF80000000L, - GPBDecodeZigZag64(0x00000000FFFFFFFFL)); - XCTAssertEqual((int64_t)0x7FFFFFFFFFFFFFFFL, - GPBDecodeZigZag64(0xFFFFFFFFFFFFFFFEL)); - XCTAssertEqual((int64_t)0x8000000000000000L, - GPBDecodeZigZag64(0xFFFFFFFFFFFFFFFFL)); + [self assertReadZigZag32:bytes(0x0) value:0]; + [self assertReadZigZag32:bytes(0x1) value:-1]; + [self assertReadZigZag32:bytes(0x2) value:1]; + [self assertReadZigZag32:bytes(0x3) value:-2]; + + [self assertReadZigZag32:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0x07) value:(int32_t)0x3FFFFFFF]; + [self assertReadZigZag32:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x07) value:(int32_t)0xC0000000]; + [self assertReadZigZag32:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0x0F) value:(int32_t)0x7FFFFFFF]; + [self assertReadZigZag32:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x0F) value:(int32_t)0x80000000]; + + [self assertReadZigZag64:bytes(0x0) value:0]; + [self assertReadZigZag64:bytes(0x1) value:-1]; + [self assertReadZigZag64:bytes(0x2) value:1]; + [self assertReadZigZag64:bytes(0x3) value:-2]; + + [self assertReadZigZag64:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0x07) value:(int32_t)0x3FFFFFFF]; + [self assertReadZigZag64:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x07) value:(int32_t)0xC0000000]; + [self assertReadZigZag64:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0x0F) value:(int32_t)0x7FFFFFFF]; + [self assertReadZigZag64:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x0F) value:(int32_t)0x80000000]; + + [self assertReadZigZag64:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01) value:0x7FFFFFFFFFFFFFFFL]; + [self assertReadZigZag64:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01) value:0x8000000000000000L]; } - (void)assertReadVarint:(NSData*)data value:(int64_t)value { - { + if (value <= INT32_MAX && value >= INT32_MIN) { + { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual((int32_t)value, [input readInt32]); + } + { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual((int32_t)value, [input readEnum]); + } + } + if (value <= UINT32_MAX && value >= 0) { GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; - XCTAssertEqual((int32_t)value, [input readInt32]); + XCTAssertEqual((uint32_t)value, [input readUInt32]); } { GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; XCTAssertEqual(value, [input readInt64]); } + if (value >= 0) { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual((uint64_t)value, [input readUInt64]); + } } - (void)assertReadLittleEndian32:(NSData*)data value:(int32_t)value { - GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; - XCTAssertEqual(value, [input readSFixed32]); + { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual(value, [input readSFixed32]); + } + { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual(GPBConvertInt32ToFloat(value), [input readFloat]); + } + { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual((uint32_t)value, [input readFixed32]); + } + { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual(value, [input readSFixed32]); + } } - (void)assertReadLittleEndian64:(NSData*)data value:(int64_t)value { + { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual(value, [input readSFixed64]); + } + { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual(GPBConvertInt64ToDouble(value), [input readDouble]); + } + { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual((uint64_t)value, [input readFixed64]); + } + { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual(value, [input readSFixed64]); + } +} + +- (void)assertReadZigZag32:(NSData*)data value:(int64_t)value { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual((int32_t)value, [input readSInt32]); +} + +- (void)assertReadZigZag64:(NSData*)data value:(int64_t)value { GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; - XCTAssertEqual(value, [input readSFixed64]); + XCTAssertEqual(value, [input readSInt64]); } - (void)assertReadVarintFailure:(NSData*)data { @@ -128,12 +177,28 @@ - (void)testBytes { XCTAssertEqual(((uint8_t*)data.bytes)[1], (uint8_t)0x74); } +- (void)testReadBool { + { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:bytes(0x00)]; + XCTAssertEqual(NO, [input readBool]); + } + { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:bytes(0x01)]; + XCTAssertEqual(YES, [input readBool]); + } +} + - (void)testReadVarint { [self assertReadVarint:bytes(0x00) value:0]; [self assertReadVarint:bytes(0x01) value:1]; [self assertReadVarint:bytes(0x7f) value:127]; // 14882 [self assertReadVarint:bytes(0xa2, 0x74) value:(0x22 << 0) | (0x74 << 7)]; + // 1904930 + [self assertReadVarint:bytes(0xa2, 0xa2, 0x74) value:(0x22 << 0) | (0x22 << 7) | (0x74 << 14)]; + // 243831074 + [self assertReadVarint:bytes(0xa2, 0xa2, 0xa2, 0x74) + value:(0x22 << 0) | (0x22 << 7) | (0x22 << 14) | (0x74 << 21)]; // 2961488830 [self assertReadVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b) value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | @@ -155,7 +220,7 @@ - (void)testReadVarint { 0xa6, 0x01) value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) | (0x3bLL << 28) | (0x56LL << 35) | (0x00LL << 42) | - (0x05LL << 49) | (0x26LL << 56) | (0x01LL << 63)]; + (0x05LL << 49) | (0x26LL << 56) | (0x01ULL << 63)]; // Failures [self assertReadVarintFailure:bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, @@ -163,6 +228,45 @@ - (void)testReadVarint { [self assertReadVarintFailure:bytes(0x80)]; } +- (void)testReadVarint32FromVarint64 { + { + // Turn on lower 31 bits of the upper half on a 64 bit varint. + NSData* data = bytes(0x80, 0x80, 0x80, 0x80, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E); + + int32_t value32 = 0x0; + GPBCodedInputStream* input32 = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual(value32, [input32 readInt32]); + + int64_t value64 = INT64_MAX & 0xFFFFFFFF00000000; + GPBCodedInputStream* input64 = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual(value64, [input64 readInt64]); + } + { + // Turn on lower 31 bits and lower 31 bits on upper half on a 64 bit varint. + NSData* data = bytes(0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E); + + int32_t value32 = INT32_MAX; + GPBCodedInputStream* input32 = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual(value32, [input32 readInt32]); + + int64_t value64 = INT64_MAX & 0xFFFFFFFF7FFFFFFF; + GPBCodedInputStream* input64 = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual(value64, [input64 readInt64]); + } + { + // Turn on bits 32 and 64 bit on a 64 bit varint. + NSData* data = bytes(0x80, 0x80, 0x80, 0x80, 0x88, 0x80, 0x80, 0x80, 0x80, 0x01); + + int32_t value32 = INT32_MIN; + GPBCodedInputStream* input32 = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual(value32, [input32 readInt32]); + + int64_t value64 = INT64_MIN | (0x01LL << 31); + GPBCodedInputStream* input64 = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqual(value64, [input64 readInt64]); + } +} + - (void)testReadLittleEndian { [self assertReadLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12) value:0x12345678]; @@ -265,6 +369,27 @@ - (void)testReadMaliciouslyLargeBlob { XCTAssertThrows([input readBytes]); } +- (void)testReadEmptyString { + NSData *data = bytes(0x00); + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + XCTAssertEqualObjects(@"", [input readString]); +} + +- (void)testInvalidGroupEndTagThrows { + NSData *data = bytes(0x0B, 0x1A, 0x02, 0x4B, 0x50, 0x14); + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + XCTAssertThrowsSpecificNamed([input skipMessage], + NSException, + GPBCodedInputStreamException, + @"should throw a GPBCodedInputStreamException exception "); +} + +- (void)testBytesWithNegativeSize { + NSData *data = bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x0F); + GPBCodedInputStream *input = [GPBCodedInputStream streamWithData:data]; + XCTAssertNil([input readBytes]); +} + // Verifies fix for b/10315336. // Note: Now that there isn't a custom string class under the hood, this test // isn't as critical, but it does cover bad input and if a custom class is added @@ -297,7 +422,7 @@ - (void)testReadMalformedString { - (void)testBOMWithinStrings { // We've seen servers that end up with BOMs within strings (not always at the // start, and sometimes in multiple places), make sure they always parse - // correctly. (Again, this is inpart incase a custom string class is ever + // correctly. (Again, this is inpart in case a custom string class is ever // used again.) const char* strs[] = { "\xEF\xBB\xBF String with BOM", diff --git a/objectivec/Tests/GPBCodedOuputStreamTests.m b/objectivec/Tests/GPBCodedOuputStreamTests.m index 2ad326beb96a7..a9934acdac1ab 100644 --- a/objectivec/Tests/GPBCodedOuputStreamTests.m +++ b/objectivec/Tests/GPBCodedOuputStreamTests.m @@ -237,7 +237,15 @@ - (void)testWriteVarint4 { } - (void)testWriteVarint5 { - // 2961488830 + // The sign/nosign distinction is done here because normally varints are + // around 64bit values, but for some cases a 32bit value is forced with + // with the sign bit (tags, uint32, etc.) + + // 1887747006 (no sign bit) + [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x07) + value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | + (0x04 << 21) | (0x07LL << 28)]; + // 2961488830 (sign bit) [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b) value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x0bLL << 28)]; @@ -266,7 +274,7 @@ - (void)testWriteVarint8 { value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) | (0x3bLL << 28) | (0x56LL << 35) | (0x00LL << 42) | (0x05LL << 49) | (0x26LL << 56) | - (0x01LL << 63)]; + (0x01ULL << 63)]; } - (void)testWriteLittleEndian { @@ -392,7 +400,7 @@ - (void)testCFStringGetCStringPtrAndStringsWithNullChars { - (void)testWriteStringsWithZeroChar { // Unicode allows `\0` as a character, and NSString is a class cluster, so - // there are a few different classes that could end up beind a given string. + // there are a few different classes that could end up behind a given string. // Historically, we've seen differences based on constant strings in code and // strings built via the NSString apis. So this round trips them to ensure // they are acting as expected. @@ -423,4 +431,14 @@ - (void)testWriteStringsWithZeroChar { } } +- (void)testThatItThrowsWhenWriteRawPtrFails { + NSOutputStream *output = [NSOutputStream outputStreamToMemory]; + GPBCodedOutputStream *codedOutput = + [GPBCodedOutputStream streamWithOutputStream:output bufferSize:0]; // Skip buffering. + [output close]; // Close the output stream to force failure on write. + const char *cString = "raw"; + XCTAssertThrowsSpecificNamed([codedOutput writeRawPtr:cString offset:0 length:strlen(cString)], + NSException, GPBCodedOutputStreamException_WriteFailed); +} + @end diff --git a/objectivec/Tests/GPBCompileTest01.m b/objectivec/Tests/GPBCompileTest01.m new file mode 100644 index 0000000000000..c8bc433a048e1 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest01.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBArray.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_1 = 0; diff --git a/objectivec/Tests/GPBCompileTest02.m b/objectivec/Tests/GPBCompileTest02.m new file mode 100644 index 0000000000000..c44e201a4df45 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest02.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBCodedInputStream.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_2 = 0; diff --git a/objectivec/Tests/GPBCompileTest03.m b/objectivec/Tests/GPBCompileTest03.m new file mode 100644 index 0000000000000..41994f94dd868 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest03.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBCodedOutputStream.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_3 = 0; diff --git a/objectivec/Tests/GPBCompileTest04.m b/objectivec/Tests/GPBCompileTest04.m new file mode 100644 index 0000000000000..c31498f12cef5 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest04.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBDescriptor.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_4 = 0; diff --git a/objectivec/Tests/GPBCompileTest05.m b/objectivec/Tests/GPBCompileTest05.m new file mode 100644 index 0000000000000..adb72252f5339 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest05.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBDictionary.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_5 = 0; diff --git a/objectivec/Tests/GPBCompileTest06.m b/objectivec/Tests/GPBCompileTest06.m new file mode 100644 index 0000000000000..b7505b02a666c --- /dev/null +++ b/objectivec/Tests/GPBCompileTest06.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBExtensionRegistry.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_6 = 0; diff --git a/objectivec/Tests/GPBCompileTest07.m b/objectivec/Tests/GPBCompileTest07.m new file mode 100644 index 0000000000000..939bb7097d5c7 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest07.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBMessage.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_7 = 0; diff --git a/objectivec/Tests/GPBCompileTest08.m b/objectivec/Tests/GPBCompileTest08.m new file mode 100644 index 0000000000000..a84f38cf71327 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest08.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBRootObject.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_8 = 0; diff --git a/objectivec/Tests/GPBCompileTest09.m b/objectivec/Tests/GPBCompileTest09.m new file mode 100644 index 0000000000000..f8ccb4a00f782 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest09.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBUnknownField.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_9 = 0; diff --git a/objectivec/Tests/GPBCompileTest10.m b/objectivec/Tests/GPBCompileTest10.m new file mode 100644 index 0000000000000..d8318678dbcfd --- /dev/null +++ b/objectivec/Tests/GPBCompileTest10.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBUnknownFieldSet.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_10 = 0; diff --git a/objectivec/Tests/GPBCompileTest11.m b/objectivec/Tests/GPBCompileTest11.m new file mode 100644 index 0000000000000..9f2c6b11a0803 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest11.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBUtilities.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_11 = 0; diff --git a/objectivec/Tests/GPBCompileTest12.m b/objectivec/Tests/GPBCompileTest12.m new file mode 100644 index 0000000000000..3aa29b3171af7 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest12.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBWellKnownTypes.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_12 = 0; diff --git a/objectivec/Tests/GPBCompileTest13.m b/objectivec/Tests/GPBCompileTest13.m new file mode 100644 index 0000000000000..fef2af5f4a484 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest13.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBWireFormat.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_13 = 0; diff --git a/objectivec/Tests/GPBCompileTest14.m b/objectivec/Tests/GPBCompileTest14.m new file mode 100644 index 0000000000000..1e64b7116dcf3 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest14.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBAny.pbobjc.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_14 = 0; diff --git a/objectivec/Tests/GPBCompileTest15.m b/objectivec/Tests/GPBCompileTest15.m new file mode 100644 index 0000000000000..2eaedb26fbd64 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest15.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBApi.pbobjc.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_15 = 0; diff --git a/objectivec/Tests/GPBCompileTest16.m b/objectivec/Tests/GPBCompileTest16.m new file mode 100644 index 0000000000000..25af89e0029ab --- /dev/null +++ b/objectivec/Tests/GPBCompileTest16.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBDuration.pbobjc.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_16 = 0; diff --git a/objectivec/Tests/GPBCompileTest17.m b/objectivec/Tests/GPBCompileTest17.m new file mode 100644 index 0000000000000..c719ad31cc9df --- /dev/null +++ b/objectivec/Tests/GPBCompileTest17.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBEmpty.pbobjc.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_17 = 0; diff --git a/objectivec/Tests/GPBCompileTest18.m b/objectivec/Tests/GPBCompileTest18.m new file mode 100644 index 0000000000000..a02b2590e3fa8 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest18.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBFieldMask.pbobjc.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_18 = 0; diff --git a/objectivec/Tests/GPBCompileTest19.m b/objectivec/Tests/GPBCompileTest19.m new file mode 100644 index 0000000000000..b4472846e0788 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest19.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBSourceContext.pbobjc.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_19 = 0; diff --git a/objectivec/Tests/GPBCompileTest20.m b/objectivec/Tests/GPBCompileTest20.m new file mode 100644 index 0000000000000..120ef5546d7b9 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest20.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBStruct.pbobjc.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_20 = 0; diff --git a/objectivec/Tests/GPBCompileTest21.m b/objectivec/Tests/GPBCompileTest21.m new file mode 100644 index 0000000000000..766d890b70c07 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest21.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBTimestamp.pbobjc.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_21 = 0; diff --git a/objectivec/Tests/GPBCompileTest22.m b/objectivec/Tests/GPBCompileTest22.m new file mode 100644 index 0000000000000..6d0955b73a9c1 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest22.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBType.pbobjc.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_22 = 0; diff --git a/objectivec/Tests/GPBCompileTest23.m b/objectivec/Tests/GPBCompileTest23.m new file mode 100644 index 0000000000000..22f2db63bf3a1 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest23.m @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single public header to ensure things build. +// It helps test that imports are complete/ordered correctly. + +#import "GPBWrappers.pbobjc.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_23 = 0; diff --git a/objectivec/Tests/GPBCompileTest24.m b/objectivec/Tests/GPBCompileTest24.m new file mode 100644 index 0000000000000..c81ea732556a6 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest24.m @@ -0,0 +1,42 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single header to ensure things build. This +// is NOT a public header of the library, but uses a file that defines +// proto2 syntax messages that are extendable, so it can need more things +// that the proto3 syntax WKTs bundled with the library. + +#import "google/protobuf/Descriptor.pbobjc.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_24 = 0; diff --git a/objectivec/Tests/GPBCompileTest25.m b/objectivec/Tests/GPBCompileTest25.m new file mode 100644 index 0000000000000..7a482b51b1779 --- /dev/null +++ b/objectivec/Tests/GPBCompileTest25.m @@ -0,0 +1,42 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// This is a test including a single header to ensure things build. This +// is NOT a public header of the library, but uses a file that defines +// extensions to proto2 syntax messages, so it can need more things +// that the proto3 syntax WKTs bundled with the library. + +#import "google/protobuf/UnittestCustomOptions.pbobjc.h" + + +// Something in the body of this file so the compiler/linker won't complain +// about an empty .o file. +__attribute__((visibility("default"))) char dummy_symbol_25 = 0; diff --git a/objectivec/Tests/GPBDescriptorTests.m b/objectivec/Tests/GPBDescriptorTests.m index 1e1c3de8d0198..6fa7202bc46fc 100644 --- a/objectivec/Tests/GPBDescriptorTests.m +++ b/objectivec/Tests/GPBDescriptorTests.m @@ -32,7 +32,7 @@ #import -#import "GPBDescriptor.h" +#import "GPBDescriptor_PackagePrivate.h" #import "google/protobuf/Unittest.pbobjc.h" #import "google/protobuf/UnittestObjc.pbobjc.h" #import "google/protobuf/Descriptor.pbobjc.h" @@ -83,6 +83,8 @@ - (void)testFieldDescriptor { XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor); XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name, @"TestAllTypes_NestedEnum"); + XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number); + XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeEnum); // Foreign Enum fieldDescriptorWithName = [descriptor fieldWithName:@"optionalForeignEnum"]; @@ -93,6 +95,8 @@ - (void)testFieldDescriptor { XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor); XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name, @"ForeignEnum"); + XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number); + XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeEnum); // Import Enum fieldDescriptorWithName = [descriptor fieldWithName:@"optionalImportEnum"]; @@ -103,6 +107,8 @@ - (void)testFieldDescriptor { XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor); XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name, @"ImportEnum"); + XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number); + XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeEnum); // Nested Message fieldDescriptorWithName = [descriptor fieldWithName:@"optionalNestedMessage"]; @@ -111,6 +117,8 @@ - (void)testFieldDescriptor { XCTAssertNotNil(fieldDescriptorWithNumber); XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber); XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor); + XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number); + XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeMessage); // Foreign Message fieldDescriptorWithName = @@ -120,6 +128,8 @@ - (void)testFieldDescriptor { XCTAssertNotNil(fieldDescriptorWithNumber); XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber); XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor); + XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number); + XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeMessage); // Import Message fieldDescriptorWithName = [descriptor fieldWithName:@"optionalImportMessage"]; @@ -128,6 +138,12 @@ - (void)testFieldDescriptor { XCTAssertNotNil(fieldDescriptorWithNumber); XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber); XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor); + XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number); + XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeMessage); + + // Some failed lookups. + XCTAssertNil([descriptor fieldWithName:@"NOT THERE"]); + XCTAssertNil([descriptor fieldWithNumber:9876543]); } - (void)testEnumDescriptor { @@ -159,6 +175,7 @@ - (void)testEnumDescriptor { XCTAssertNotNil(enumName); XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:@"FOO"]); XCTAssertEqual(value, TestAllTypes_NestedEnum_Foo); + XCTAssertNil([descriptor textFormatNameForValue:99999]); // Bad values enumName = [descriptor enumNameForValue:0]; @@ -173,6 +190,100 @@ - (void)testEnumDescriptor { XCTAssertFalse([descriptor getValue:&value forEnumTextFormatName:@"Unknown"]); } +- (void)testEnumDescriptorIntrospection { + GPBEnumDescriptor *descriptor = TestAllTypes_NestedEnum_EnumDescriptor(); + + XCTAssertEqual(descriptor.enumNameCount, 4U); + XCTAssertEqualObjects([descriptor getEnumNameForIndex:0], + @"TestAllTypes_NestedEnum_Foo"); + XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:0], @"FOO"); + XCTAssertEqualObjects([descriptor getEnumNameForIndex:1], + @"TestAllTypes_NestedEnum_Bar"); + XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:1], @"BAR"); + XCTAssertEqualObjects([descriptor getEnumNameForIndex:2], + @"TestAllTypes_NestedEnum_Baz"); + XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:2], @"BAZ"); + XCTAssertEqualObjects([descriptor getEnumNameForIndex:3], + @"TestAllTypes_NestedEnum_Neg"); + XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:3], @"NEG"); +} + +- (void)testEnumDescriptorIntrospectionWithAlias { + GPBEnumDescriptor *descriptor = TestEnumWithDupValue_EnumDescriptor(); + NSString *enumName; + int32_t value; + + XCTAssertEqual(descriptor.enumNameCount, 5U); + + enumName = [descriptor getEnumNameForIndex:0]; + XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Foo1"); + XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]); + XCTAssertEqual(value, 1); + XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:0], @"FOO1"); + + enumName = [descriptor getEnumNameForIndex:1]; + XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Bar1"); + XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]); + XCTAssertEqual(value, 2); + XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:1], @"BAR1"); + + enumName = [descriptor getEnumNameForIndex:2]; + XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Baz"); + XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]); + XCTAssertEqual(value, 3); + XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:2], @"BAZ"); + + enumName = [descriptor getEnumNameForIndex:3]; + XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Foo2"); + XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]); + XCTAssertEqual(value, 1); + XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:3], @"FOO2"); + + enumName = [descriptor getEnumNameForIndex:4]; + XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Bar2"); + XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]); + XCTAssertEqual(value, 2); + XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:4], @"BAR2"); +} + +- (void)testEnumAliasNameCollisions { + GPBEnumDescriptor *descriptor = TestEnumObjCNameCollision_EnumDescriptor(); + NSString *textFormatName; + int32_t value; + + XCTAssertEqual(descriptor.enumNameCount, 5U); + + XCTAssertEqualObjects([descriptor getEnumNameForIndex:0], @"TestEnumObjCNameCollision_Foo"); + textFormatName = [descriptor getEnumTextFormatNameForIndex:0]; + XCTAssertEqualObjects(textFormatName, @"FOO"); + XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]); + XCTAssertEqual(value, 1); + + XCTAssertEqualObjects([descriptor getEnumNameForIndex:1], @"TestEnumObjCNameCollision_Foo"); + textFormatName = [descriptor getEnumTextFormatNameForIndex:1]; + XCTAssertEqualObjects(textFormatName, @"foo"); + XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]); + XCTAssertEqual(value, 1); + + XCTAssertEqualObjects([descriptor getEnumNameForIndex:2], @"TestEnumObjCNameCollision_Bar"); + textFormatName = [descriptor getEnumTextFormatNameForIndex:2]; + XCTAssertEqualObjects(textFormatName, @"BAR"); + XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]); + XCTAssertEqual(value, 2); + + XCTAssertEqualObjects([descriptor getEnumNameForIndex:3], @"TestEnumObjCNameCollision_Mumble"); + textFormatName = [descriptor getEnumTextFormatNameForIndex:3]; + XCTAssertEqualObjects(textFormatName, @"mumble"); + XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]); + XCTAssertEqual(value, 2); + + XCTAssertEqualObjects([descriptor getEnumNameForIndex:4], @"TestEnumObjCNameCollision_Mumble"); + textFormatName = [descriptor getEnumTextFormatNameForIndex:4]; + XCTAssertEqualObjects(textFormatName, @"MUMBLE"); + XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]); + XCTAssertEqual(value, 2); +} + - (void)testEnumValueValidator { GPBDescriptor *descriptor = [TestAllTypes descriptor]; GPBFieldDescriptor *fieldDescriptor = @@ -244,7 +355,7 @@ - (void)testOneofDescriptor { XCTAssertNil([oneofBar fieldWithNumber:TestOneof2_FieldNumber_FooString]); // Check pointers back to the enclosing oneofs. - // (pointer comparisions) + // (pointer comparisons) XCTAssertEqual(fooStringField.containingOneof, oneofFoo); XCTAssertEqual(barStringField.containingOneof, oneofBar); GPBFieldDescriptor *bazString = @@ -253,4 +364,102 @@ - (void)testOneofDescriptor { XCTAssertNil(bazString.containingOneof); } +- (void)testExtensiondDescriptor { + Class msgClass = [TestAllExtensions class]; + Class packedMsgClass = [TestPackedExtensions class]; + + // Int + + GPBExtensionDescriptor *descriptor = [UnittestRoot optionalInt32Extension]; + XCTAssertNotNil(descriptor); + XCTAssertEqual(descriptor.containingMessageClass, msgClass); // ptr equality + XCTAssertFalse(descriptor.isPackable); + XCTAssertEqualObjects(descriptor.defaultValue, @0); + XCTAssertNil(descriptor.enumDescriptor); + + descriptor = [UnittestRoot defaultInt32Extension]; + XCTAssertNotNil(descriptor); + XCTAssertEqual(descriptor.containingMessageClass, msgClass); // ptr equality + XCTAssertFalse(descriptor.isPackable); + XCTAssertEqualObjects(descriptor.defaultValue, @41); + XCTAssertNil(descriptor.enumDescriptor); + + // Enum + + descriptor = [UnittestRoot optionalNestedEnumExtension]; + XCTAssertNotNil(descriptor); + XCTAssertEqual(descriptor.containingMessageClass, msgClass); // ptr equality + XCTAssertFalse(descriptor.isPackable); + XCTAssertEqual(descriptor.defaultValue, @1); + XCTAssertEqualObjects(descriptor.enumDescriptor.name, @"TestAllTypes_NestedEnum"); + + descriptor = [UnittestRoot defaultNestedEnumExtension]; + XCTAssertNotNil(descriptor); + XCTAssertEqual(descriptor.containingMessageClass, msgClass); // ptr equality + XCTAssertFalse(descriptor.isPackable); + XCTAssertEqual(descriptor.defaultValue, @2); + XCTAssertEqualObjects(descriptor.enumDescriptor.name, @"TestAllTypes_NestedEnum"); + + // Message + + descriptor = [UnittestRoot optionalNestedMessageExtension]; + XCTAssertNotNil(descriptor); + XCTAssertEqual(descriptor.containingMessageClass, msgClass); // ptr equality + XCTAssertFalse(descriptor.isPackable); + XCTAssertNil(descriptor.defaultValue); + XCTAssertNil(descriptor.enumDescriptor); + + // Repeated Int + + descriptor = [UnittestRoot repeatedInt32Extension]; + XCTAssertNotNil(descriptor); + XCTAssertEqual(descriptor.containingMessageClass, msgClass); // ptr equality + XCTAssertFalse(descriptor.isPackable); + XCTAssertNil(descriptor.defaultValue); + XCTAssertNil(descriptor.enumDescriptor); + + descriptor = [UnittestRoot packedInt32Extension]; + XCTAssertNotNil(descriptor); + XCTAssertEqual(descriptor.containingMessageClass, packedMsgClass); // ptr equality + XCTAssertTrue(descriptor.isPackable); + XCTAssertNil(descriptor.defaultValue); + XCTAssertNil(descriptor.enumDescriptor); + + // Repeated Enum + + descriptor = [UnittestRoot repeatedNestedEnumExtension]; + XCTAssertNotNil(descriptor); + XCTAssertEqual(descriptor.containingMessageClass, msgClass); // ptr equality + XCTAssertFalse(descriptor.isPackable); + XCTAssertNil(descriptor.defaultValue); + XCTAssertEqualObjects(descriptor.enumDescriptor.name, @"TestAllTypes_NestedEnum"); + + descriptor = [UnittestRoot packedEnumExtension]; + XCTAssertNotNil(descriptor); + XCTAssertEqual(descriptor.containingMessageClass, packedMsgClass); // ptr equality + XCTAssertTrue(descriptor.isPackable); + XCTAssertNil(descriptor.defaultValue); + XCTAssertEqualObjects(descriptor.enumDescriptor.name, @"ForeignEnum"); + + // Repeated Message + + descriptor = [UnittestRoot repeatedNestedMessageExtension]; + XCTAssertNotNil(descriptor); + XCTAssertEqual(descriptor.containingMessageClass, msgClass); // ptr equality + XCTAssertFalse(descriptor.isPackable); + XCTAssertNil(descriptor.defaultValue); + XCTAssertNil(descriptor.enumDescriptor); + + // Compare (used internally for serialization). + + GPBExtensionDescriptor *ext1 = [UnittestRoot optionalInt32Extension]; + XCTAssertEqual(ext1.fieldNumber, 1u); + GPBExtensionDescriptor *ext2 = [UnittestRoot optionalInt64Extension]; + XCTAssertEqual(ext2.fieldNumber, 2u); + + XCTAssertEqual([ext1 compareByFieldNumber:ext2], NSOrderedAscending); + XCTAssertEqual([ext2 compareByFieldNumber:ext1], NSOrderedDescending); + XCTAssertEqual([ext1 compareByFieldNumber:ext1], NSOrderedSame); +} + @end diff --git a/objectivec/Tests/GPBDictionaryTests+Bool.m b/objectivec/Tests/GPBDictionaryTests+Bool.m index 0dbe07b6e9322..4c021441a69e1 100644 --- a/objectivec/Tests/GPBDictionaryTests+Bool.m +++ b/objectivec/Tests/GPBDictionaryTests+Bool.m @@ -42,6 +42,7 @@ //%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(UInt32, uint32_t, 100U, 101U) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> UInt32 @@ -63,7 +64,8 @@ - (void)testEmpty { } - (void)testOne { - GPBBoolUInt32Dictionary *dict = [GPBBoolUInt32Dictionary dictionaryWithUInt32:100U forKey:YES]; + GPBBoolUInt32Dictionary *dict = [[GPBBoolUInt32Dictionary alloc] init]; + [dict setUInt32:100U forKey:YES]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); uint32_t value; @@ -76,6 +78,7 @@ - (void)testOne { XCTAssertEqual(aValue, 100U); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -214,17 +217,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBBoolUInt32Dictionary *dict2 = - [GPBBoolUInt32Dictionary dictionaryWithDictionary:dict]; + [[GPBBoolUInt32Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBBoolUInt32Dictionary *dict = [GPBBoolUInt32Dictionary dictionary]; + GPBBoolUInt32Dictionary *dict = [[GPBBoolUInt32Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -249,6 +253,7 @@ - (void)testAdds { XCTAssertTrue([dict getUInt32:&value forKey:NO]); XCTAssertEqual(value, 101U); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -341,8 +346,10 @@ - (void)testInplaceMutation { @end +// clang-format on //%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Int32, int32_t, 200, 201) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> Int32 @@ -364,7 +371,8 @@ - (void)testEmpty { } - (void)testOne { - GPBBoolInt32Dictionary *dict = [GPBBoolInt32Dictionary dictionaryWithInt32:200 forKey:YES]; + GPBBoolInt32Dictionary *dict = [[GPBBoolInt32Dictionary alloc] init]; + [dict setInt32:200 forKey:YES]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int32_t value; @@ -377,6 +385,7 @@ - (void)testOne { XCTAssertEqual(aValue, 200); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -515,17 +524,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBBoolInt32Dictionary *dict2 = - [GPBBoolInt32Dictionary dictionaryWithDictionary:dict]; + [[GPBBoolInt32Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBBoolInt32Dictionary *dict = [GPBBoolInt32Dictionary dictionary]; + GPBBoolInt32Dictionary *dict = [[GPBBoolInt32Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -550,6 +560,7 @@ - (void)testAdds { XCTAssertTrue([dict getInt32:&value forKey:NO]); XCTAssertEqual(value, 201); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -642,8 +653,10 @@ - (void)testInplaceMutation { @end +// clang-format on //%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(UInt64, uint64_t, 300U, 301U) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> UInt64 @@ -665,7 +678,8 @@ - (void)testEmpty { } - (void)testOne { - GPBBoolUInt64Dictionary *dict = [GPBBoolUInt64Dictionary dictionaryWithUInt64:300U forKey:YES]; + GPBBoolUInt64Dictionary *dict = [[GPBBoolUInt64Dictionary alloc] init]; + [dict setUInt64:300U forKey:YES]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); uint64_t value; @@ -678,6 +692,7 @@ - (void)testOne { XCTAssertEqual(aValue, 300U); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -816,17 +831,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBBoolUInt64Dictionary *dict2 = - [GPBBoolUInt64Dictionary dictionaryWithDictionary:dict]; + [[GPBBoolUInt64Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBBoolUInt64Dictionary *dict = [GPBBoolUInt64Dictionary dictionary]; + GPBBoolUInt64Dictionary *dict = [[GPBBoolUInt64Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -851,6 +867,7 @@ - (void)testAdds { XCTAssertTrue([dict getUInt64:&value forKey:NO]); XCTAssertEqual(value, 301U); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -943,8 +960,10 @@ - (void)testInplaceMutation { @end +// clang-format on //%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Int64, int64_t, 400, 401) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> Int64 @@ -966,7 +985,8 @@ - (void)testEmpty { } - (void)testOne { - GPBBoolInt64Dictionary *dict = [GPBBoolInt64Dictionary dictionaryWithInt64:400 forKey:YES]; + GPBBoolInt64Dictionary *dict = [[GPBBoolInt64Dictionary alloc] init]; + [dict setInt64:400 forKey:YES]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int64_t value; @@ -979,6 +999,7 @@ - (void)testOne { XCTAssertEqual(aValue, 400); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -1117,17 +1138,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBBoolInt64Dictionary *dict2 = - [GPBBoolInt64Dictionary dictionaryWithDictionary:dict]; + [[GPBBoolInt64Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBBoolInt64Dictionary *dict = [GPBBoolInt64Dictionary dictionary]; + GPBBoolInt64Dictionary *dict = [[GPBBoolInt64Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1152,6 +1174,7 @@ - (void)testAdds { XCTAssertTrue([dict getInt64:&value forKey:NO]); XCTAssertEqual(value, 401); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1244,8 +1267,10 @@ - (void)testInplaceMutation { @end +// clang-format on //%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Bool, BOOL, NO, YES) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> Bool @@ -1267,7 +1292,8 @@ - (void)testEmpty { } - (void)testOne { - GPBBoolBoolDictionary *dict = [GPBBoolBoolDictionary dictionaryWithBool:NO forKey:YES]; + GPBBoolBoolDictionary *dict = [[GPBBoolBoolDictionary alloc] init]; + [dict setBool:NO forKey:YES]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); BOOL value; @@ -1280,6 +1306,7 @@ - (void)testOne { XCTAssertEqual(aValue, NO); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -1418,17 +1445,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBBoolBoolDictionary *dict2 = - [GPBBoolBoolDictionary dictionaryWithDictionary:dict]; + [[GPBBoolBoolDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBBoolBoolDictionary *dict = [GPBBoolBoolDictionary dictionary]; + GPBBoolBoolDictionary *dict = [[GPBBoolBoolDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1453,6 +1481,7 @@ - (void)testAdds { XCTAssertTrue([dict getBool:&value forKey:NO]); XCTAssertEqual(value, YES); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1545,8 +1574,10 @@ - (void)testInplaceMutation { @end +// clang-format on //%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Float, float, 500.f, 501.f) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> Float @@ -1568,7 +1599,8 @@ - (void)testEmpty { } - (void)testOne { - GPBBoolFloatDictionary *dict = [GPBBoolFloatDictionary dictionaryWithFloat:500.f forKey:YES]; + GPBBoolFloatDictionary *dict = [[GPBBoolFloatDictionary alloc] init]; + [dict setFloat:500.f forKey:YES]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); float value; @@ -1581,6 +1613,7 @@ - (void)testOne { XCTAssertEqual(aValue, 500.f); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -1719,17 +1752,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBBoolFloatDictionary *dict2 = - [GPBBoolFloatDictionary dictionaryWithDictionary:dict]; + [[GPBBoolFloatDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBBoolFloatDictionary *dict = [GPBBoolFloatDictionary dictionary]; + GPBBoolFloatDictionary *dict = [[GPBBoolFloatDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1754,6 +1788,7 @@ - (void)testAdds { XCTAssertTrue([dict getFloat:&value forKey:NO]); XCTAssertEqual(value, 501.f); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1846,8 +1881,10 @@ - (void)testInplaceMutation { @end +// clang-format on //%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Double, double, 600., 601.) // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> Double @@ -1869,7 +1906,8 @@ - (void)testEmpty { } - (void)testOne { - GPBBoolDoubleDictionary *dict = [GPBBoolDoubleDictionary dictionaryWithDouble:600. forKey:YES]; + GPBBoolDoubleDictionary *dict = [[GPBBoolDoubleDictionary alloc] init]; + [dict setDouble:600. forKey:YES]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); double value; @@ -1882,6 +1920,7 @@ - (void)testOne { XCTAssertEqual(aValue, 600.); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2020,17 +2059,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBBoolDoubleDictionary *dict2 = - [GPBBoolDoubleDictionary dictionaryWithDictionary:dict]; + [[GPBBoolDoubleDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBBoolDoubleDictionary *dict = [GPBBoolDoubleDictionary dictionary]; + GPBBoolDoubleDictionary *dict = [[GPBBoolDoubleDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2055,6 +2095,7 @@ - (void)testAdds { XCTAssertTrue([dict getDouble:&value forKey:NO]); XCTAssertEqual(value, 601.); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -2147,8 +2188,10 @@ - (void)testInplaceMutation { @end +// clang-format on //%PDDM-EXPAND TESTS_FOR_BOOL_KEY_OBJECT_VALUE(Object, NSString*, @"abc", @"def") // This block of code is generated, do not edit it directly. +// clang-format off #pragma mark - Bool -> Object @@ -2170,7 +2213,8 @@ - (void)testEmpty { } - (void)testOne { - GPBBoolObjectDictionary *dict = [GPBBoolObjectDictionary dictionaryWithObject:@"abc" forKey:YES]; + GPBBoolObjectDictionary *dict = [[GPBBoolObjectDictionary alloc] init]; + [dict setObject:@"abc" forKey:YES]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); XCTAssertEqualObjects([dict objectForKey:YES], @"abc"); @@ -2180,6 +2224,7 @@ - (void)testOne { XCTAssertEqualObjects(aObject, @"abc"); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2313,17 +2358,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBBoolObjectDictionary *dict2 = - [GPBBoolObjectDictionary dictionaryWithDictionary:dict]; + [[GPBBoolObjectDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBBoolObjectDictionary *dict = [GPBBoolObjectDictionary dictionary]; + GPBBoolObjectDictionary *dict = [[GPBBoolObjectDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2343,6 +2389,7 @@ - (void)testAdds { XCTAssertEqualObjects([dict objectForKey:YES], @"abc"); XCTAssertEqualObjects([dict objectForKey:NO], @"def"); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -2413,6 +2460,7 @@ - (void)testInplaceMutation { @end +// clang-format on //%PDDM-EXPAND-END (8 expansions) diff --git a/objectivec/Tests/GPBDictionaryTests+Int32.m b/objectivec/Tests/GPBDictionaryTests+Int32.m index c539bdc2edf87..8dafaac822068 100644 --- a/objectivec/Tests/GPBDictionaryTests+Int32.m +++ b/objectivec/Tests/GPBDictionaryTests+Int32.m @@ -42,10 +42,10 @@ //%PDDM-EXPAND TEST_FOR_POD_KEY(Int32, int32_t, 11, 12, 13, 14) // This block of code is generated, do not edit it directly. +// clang-format off // To let the testing macros work, add some extra methods to simplify things. @interface GPBInt32EnumDictionary (TestingTweak) -+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(int32_t)key; - (instancetype)initWithEnums:(const int32_t [])values forKeys:(const int32_t [])keys count:(NSUInteger)count; @@ -64,14 +64,6 @@ static BOOL TestingEnum_IsValidValue(int32_t value) { } @implementation GPBInt32EnumDictionary (TestingTweak) -+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(int32_t)key { - // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the - // type correct. - return [[(GPBInt32EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue - rawValues:&value - forKeys:&key - count:1] autorelease]; -} - (instancetype)initWithEnums:(const int32_t [])values forKeys:(const int32_t [])keys count:(NSUInteger)count { @@ -103,7 +95,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt32UInt32Dictionary *dict = [GPBInt32UInt32Dictionary dictionaryWithUInt32:100U forKey:11]; + GPBInt32UInt32Dictionary *dict = [[GPBInt32UInt32Dictionary alloc] init]; + [dict setUInt32:100U forKey:11]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); uint32_t value; @@ -116,6 +109,7 @@ - (void)testOne { XCTAssertEqual(aValue, 100U); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -258,17 +252,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt32UInt32Dictionary *dict2 = - [GPBInt32UInt32Dictionary dictionaryWithDictionary:dict]; + [[GPBInt32UInt32Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt32UInt32Dictionary *dict = [GPBInt32UInt32Dictionary dictionary]; + GPBInt32UInt32Dictionary *dict = [[GPBInt32UInt32Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -299,6 +294,7 @@ - (void)testAdds { XCTAssertTrue([dict getUInt32:&value forKey:14]); XCTAssertEqual(value, 103U); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -460,7 +456,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt32Int32Dictionary *dict = [GPBInt32Int32Dictionary dictionaryWithInt32:200 forKey:11]; + GPBInt32Int32Dictionary *dict = [[GPBInt32Int32Dictionary alloc] init]; + [dict setInt32:200 forKey:11]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int32_t value; @@ -473,6 +470,7 @@ - (void)testOne { XCTAssertEqual(aValue, 200); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -615,17 +613,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt32Int32Dictionary *dict2 = - [GPBInt32Int32Dictionary dictionaryWithDictionary:dict]; + [[GPBInt32Int32Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt32Int32Dictionary *dict = [GPBInt32Int32Dictionary dictionary]; + GPBInt32Int32Dictionary *dict = [[GPBInt32Int32Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -656,6 +655,7 @@ - (void)testAdds { XCTAssertTrue([dict getInt32:&value forKey:14]); XCTAssertEqual(value, 203); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -817,7 +817,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt32UInt64Dictionary *dict = [GPBInt32UInt64Dictionary dictionaryWithUInt64:300U forKey:11]; + GPBInt32UInt64Dictionary *dict = [[GPBInt32UInt64Dictionary alloc] init]; + [dict setUInt64:300U forKey:11]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); uint64_t value; @@ -830,6 +831,7 @@ - (void)testOne { XCTAssertEqual(aValue, 300U); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -972,17 +974,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt32UInt64Dictionary *dict2 = - [GPBInt32UInt64Dictionary dictionaryWithDictionary:dict]; + [[GPBInt32UInt64Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt32UInt64Dictionary *dict = [GPBInt32UInt64Dictionary dictionary]; + GPBInt32UInt64Dictionary *dict = [[GPBInt32UInt64Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1013,6 +1016,7 @@ - (void)testAdds { XCTAssertTrue([dict getUInt64:&value forKey:14]); XCTAssertEqual(value, 303U); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1174,7 +1178,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt32Int64Dictionary *dict = [GPBInt32Int64Dictionary dictionaryWithInt64:400 forKey:11]; + GPBInt32Int64Dictionary *dict = [[GPBInt32Int64Dictionary alloc] init]; + [dict setInt64:400 forKey:11]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int64_t value; @@ -1187,6 +1192,7 @@ - (void)testOne { XCTAssertEqual(aValue, 400); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -1329,17 +1335,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt32Int64Dictionary *dict2 = - [GPBInt32Int64Dictionary dictionaryWithDictionary:dict]; + [[GPBInt32Int64Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt32Int64Dictionary *dict = [GPBInt32Int64Dictionary dictionary]; + GPBInt32Int64Dictionary *dict = [[GPBInt32Int64Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1370,6 +1377,7 @@ - (void)testAdds { XCTAssertTrue([dict getInt64:&value forKey:14]); XCTAssertEqual(value, 403); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1531,7 +1539,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt32BoolDictionary *dict = [GPBInt32BoolDictionary dictionaryWithBool:YES forKey:11]; + GPBInt32BoolDictionary *dict = [[GPBInt32BoolDictionary alloc] init]; + [dict setBool:YES forKey:11]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); BOOL value; @@ -1544,6 +1553,7 @@ - (void)testOne { XCTAssertEqual(aValue, YES); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -1686,17 +1696,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt32BoolDictionary *dict2 = - [GPBInt32BoolDictionary dictionaryWithDictionary:dict]; + [[GPBInt32BoolDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt32BoolDictionary *dict = [GPBInt32BoolDictionary dictionary]; + GPBInt32BoolDictionary *dict = [[GPBInt32BoolDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1727,6 +1738,7 @@ - (void)testAdds { XCTAssertTrue([dict getBool:&value forKey:14]); XCTAssertEqual(value, NO); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1888,7 +1900,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt32FloatDictionary *dict = [GPBInt32FloatDictionary dictionaryWithFloat:500.f forKey:11]; + GPBInt32FloatDictionary *dict = [[GPBInt32FloatDictionary alloc] init]; + [dict setFloat:500.f forKey:11]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); float value; @@ -1901,6 +1914,7 @@ - (void)testOne { XCTAssertEqual(aValue, 500.f); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2043,17 +2057,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt32FloatDictionary *dict2 = - [GPBInt32FloatDictionary dictionaryWithDictionary:dict]; + [[GPBInt32FloatDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt32FloatDictionary *dict = [GPBInt32FloatDictionary dictionary]; + GPBInt32FloatDictionary *dict = [[GPBInt32FloatDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2084,6 +2099,7 @@ - (void)testAdds { XCTAssertTrue([dict getFloat:&value forKey:14]); XCTAssertEqual(value, 503.f); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -2245,7 +2261,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt32DoubleDictionary *dict = [GPBInt32DoubleDictionary dictionaryWithDouble:600. forKey:11]; + GPBInt32DoubleDictionary *dict = [[GPBInt32DoubleDictionary alloc] init]; + [dict setDouble:600. forKey:11]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); double value; @@ -2258,6 +2275,7 @@ - (void)testOne { XCTAssertEqual(aValue, 600.); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2400,17 +2418,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt32DoubleDictionary *dict2 = - [GPBInt32DoubleDictionary dictionaryWithDictionary:dict]; + [[GPBInt32DoubleDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt32DoubleDictionary *dict = [GPBInt32DoubleDictionary dictionary]; + GPBInt32DoubleDictionary *dict = [[GPBInt32DoubleDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2441,6 +2460,7 @@ - (void)testAdds { XCTAssertTrue([dict getDouble:&value forKey:14]); XCTAssertEqual(value, 603.); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -2602,7 +2622,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt32EnumDictionary *dict = [GPBInt32EnumDictionary dictionaryWithEnum:700 forKey:11]; + GPBInt32EnumDictionary *dict = [[GPBInt32EnumDictionary alloc] init]; + [dict setEnum:700 forKey:11]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int32_t value; @@ -2615,6 +2636,7 @@ - (void)testOne { XCTAssertEqual(aValue, 700); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2757,17 +2779,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt32EnumDictionary *dict2 = - [GPBInt32EnumDictionary dictionaryWithDictionary:dict]; + [[GPBInt32EnumDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt32EnumDictionary *dict = [GPBInt32EnumDictionary dictionary]; + GPBInt32EnumDictionary *dict = [[GPBInt32EnumDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2798,6 +2821,7 @@ - (void)testAdds { XCTAssertTrue([dict getEnum:&value forKey:14]); XCTAssertEqual(value, 703); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -3120,19 +3144,20 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt32EnumDictionary *dict2 = - [GPBInt32EnumDictionary dictionaryWithDictionary:dict]; + [[GPBInt32EnumDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison + [dict2 release]; [dict release]; } - (void)testUnknownAdds { GPBInt32EnumDictionary *dict = - [GPBInt32EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue]; + [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -3172,6 +3197,7 @@ - (void)testUnknownAdds { XCTAssertTrue([dict getRawValue:&value forKey:14]); XCTAssertEqual(value, 803); [dict2 release]; + [dict release]; } - (void)testUnknownRemove { @@ -3375,7 +3401,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt32ObjectDictionary *dict = [GPBInt32ObjectDictionary dictionaryWithObject:@"abc" forKey:11]; + GPBInt32ObjectDictionary *dict = [[GPBInt32ObjectDictionary alloc] init]; + [dict setObject:@"abc" forKey:11]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); XCTAssertEqualObjects([dict objectForKey:11], @"abc"); @@ -3385,6 +3412,7 @@ - (void)testOne { XCTAssertEqualObjects(aObject, @"abc"); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -3520,17 +3548,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt32ObjectDictionary *dict2 = - [GPBInt32ObjectDictionary dictionaryWithDictionary:dict]; + [[GPBInt32ObjectDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt32ObjectDictionary *dict = [GPBInt32ObjectDictionary dictionary]; + GPBInt32ObjectDictionary *dict = [[GPBInt32ObjectDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -3552,6 +3581,7 @@ - (void)testAdds { XCTAssertEqualObjects([dict objectForKey:13], @"ghi"); XCTAssertEqualObjects([dict objectForKey:14], @"jkl"); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -3643,5 +3673,6 @@ - (void)testInplaceMutation { @end +// clang-format on //%PDDM-EXPAND-END TEST_FOR_POD_KEY(Int32, int32_t, 11, 12, 13, 14) diff --git a/objectivec/Tests/GPBDictionaryTests+Int64.m b/objectivec/Tests/GPBDictionaryTests+Int64.m index b90cdf8c02959..a603356c93803 100644 --- a/objectivec/Tests/GPBDictionaryTests+Int64.m +++ b/objectivec/Tests/GPBDictionaryTests+Int64.m @@ -42,10 +42,10 @@ //%PDDM-EXPAND TEST_FOR_POD_KEY(Int64, int64_t, 21LL, 22LL, 23LL, 24LL) // This block of code is generated, do not edit it directly. +// clang-format off // To let the testing macros work, add some extra methods to simplify things. @interface GPBInt64EnumDictionary (TestingTweak) -+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(int64_t)key; - (instancetype)initWithEnums:(const int32_t [])values forKeys:(const int64_t [])keys count:(NSUInteger)count; @@ -64,14 +64,6 @@ static BOOL TestingEnum_IsValidValue(int32_t value) { } @implementation GPBInt64EnumDictionary (TestingTweak) -+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(int64_t)key { - // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the - // type correct. - return [[(GPBInt64EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue - rawValues:&value - forKeys:&key - count:1] autorelease]; -} - (instancetype)initWithEnums:(const int32_t [])values forKeys:(const int64_t [])keys count:(NSUInteger)count { @@ -103,7 +95,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt64UInt32Dictionary *dict = [GPBInt64UInt32Dictionary dictionaryWithUInt32:100U forKey:21LL]; + GPBInt64UInt32Dictionary *dict = [[GPBInt64UInt32Dictionary alloc] init]; + [dict setUInt32:100U forKey:21LL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); uint32_t value; @@ -116,6 +109,7 @@ - (void)testOne { XCTAssertEqual(aValue, 100U); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -258,17 +252,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt64UInt32Dictionary *dict2 = - [GPBInt64UInt32Dictionary dictionaryWithDictionary:dict]; + [[GPBInt64UInt32Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt64UInt32Dictionary *dict = [GPBInt64UInt32Dictionary dictionary]; + GPBInt64UInt32Dictionary *dict = [[GPBInt64UInt32Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -299,6 +294,7 @@ - (void)testAdds { XCTAssertTrue([dict getUInt32:&value forKey:24LL]); XCTAssertEqual(value, 103U); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -460,7 +456,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt64Int32Dictionary *dict = [GPBInt64Int32Dictionary dictionaryWithInt32:200 forKey:21LL]; + GPBInt64Int32Dictionary *dict = [[GPBInt64Int32Dictionary alloc] init]; + [dict setInt32:200 forKey:21LL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int32_t value; @@ -473,6 +470,7 @@ - (void)testOne { XCTAssertEqual(aValue, 200); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -615,17 +613,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt64Int32Dictionary *dict2 = - [GPBInt64Int32Dictionary dictionaryWithDictionary:dict]; + [[GPBInt64Int32Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt64Int32Dictionary *dict = [GPBInt64Int32Dictionary dictionary]; + GPBInt64Int32Dictionary *dict = [[GPBInt64Int32Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -656,6 +655,7 @@ - (void)testAdds { XCTAssertTrue([dict getInt32:&value forKey:24LL]); XCTAssertEqual(value, 203); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -817,7 +817,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt64UInt64Dictionary *dict = [GPBInt64UInt64Dictionary dictionaryWithUInt64:300U forKey:21LL]; + GPBInt64UInt64Dictionary *dict = [[GPBInt64UInt64Dictionary alloc] init]; + [dict setUInt64:300U forKey:21LL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); uint64_t value; @@ -830,6 +831,7 @@ - (void)testOne { XCTAssertEqual(aValue, 300U); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -972,17 +974,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt64UInt64Dictionary *dict2 = - [GPBInt64UInt64Dictionary dictionaryWithDictionary:dict]; + [[GPBInt64UInt64Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt64UInt64Dictionary *dict = [GPBInt64UInt64Dictionary dictionary]; + GPBInt64UInt64Dictionary *dict = [[GPBInt64UInt64Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1013,6 +1016,7 @@ - (void)testAdds { XCTAssertTrue([dict getUInt64:&value forKey:24LL]); XCTAssertEqual(value, 303U); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1174,7 +1178,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt64Int64Dictionary *dict = [GPBInt64Int64Dictionary dictionaryWithInt64:400 forKey:21LL]; + GPBInt64Int64Dictionary *dict = [[GPBInt64Int64Dictionary alloc] init]; + [dict setInt64:400 forKey:21LL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int64_t value; @@ -1187,6 +1192,7 @@ - (void)testOne { XCTAssertEqual(aValue, 400); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -1329,17 +1335,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt64Int64Dictionary *dict2 = - [GPBInt64Int64Dictionary dictionaryWithDictionary:dict]; + [[GPBInt64Int64Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt64Int64Dictionary *dict = [GPBInt64Int64Dictionary dictionary]; + GPBInt64Int64Dictionary *dict = [[GPBInt64Int64Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1370,6 +1377,7 @@ - (void)testAdds { XCTAssertTrue([dict getInt64:&value forKey:24LL]); XCTAssertEqual(value, 403); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1531,7 +1539,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt64BoolDictionary *dict = [GPBInt64BoolDictionary dictionaryWithBool:YES forKey:21LL]; + GPBInt64BoolDictionary *dict = [[GPBInt64BoolDictionary alloc] init]; + [dict setBool:YES forKey:21LL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); BOOL value; @@ -1544,6 +1553,7 @@ - (void)testOne { XCTAssertEqual(aValue, YES); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -1686,17 +1696,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt64BoolDictionary *dict2 = - [GPBInt64BoolDictionary dictionaryWithDictionary:dict]; + [[GPBInt64BoolDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt64BoolDictionary *dict = [GPBInt64BoolDictionary dictionary]; + GPBInt64BoolDictionary *dict = [[GPBInt64BoolDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1727,6 +1738,7 @@ - (void)testAdds { XCTAssertTrue([dict getBool:&value forKey:24LL]); XCTAssertEqual(value, NO); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1888,7 +1900,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt64FloatDictionary *dict = [GPBInt64FloatDictionary dictionaryWithFloat:500.f forKey:21LL]; + GPBInt64FloatDictionary *dict = [[GPBInt64FloatDictionary alloc] init]; + [dict setFloat:500.f forKey:21LL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); float value; @@ -1901,6 +1914,7 @@ - (void)testOne { XCTAssertEqual(aValue, 500.f); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2043,17 +2057,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt64FloatDictionary *dict2 = - [GPBInt64FloatDictionary dictionaryWithDictionary:dict]; + [[GPBInt64FloatDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt64FloatDictionary *dict = [GPBInt64FloatDictionary dictionary]; + GPBInt64FloatDictionary *dict = [[GPBInt64FloatDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2084,6 +2099,7 @@ - (void)testAdds { XCTAssertTrue([dict getFloat:&value forKey:24LL]); XCTAssertEqual(value, 503.f); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -2245,7 +2261,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt64DoubleDictionary *dict = [GPBInt64DoubleDictionary dictionaryWithDouble:600. forKey:21LL]; + GPBInt64DoubleDictionary *dict = [[GPBInt64DoubleDictionary alloc] init]; + [dict setDouble:600. forKey:21LL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); double value; @@ -2258,6 +2275,7 @@ - (void)testOne { XCTAssertEqual(aValue, 600.); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2400,17 +2418,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt64DoubleDictionary *dict2 = - [GPBInt64DoubleDictionary dictionaryWithDictionary:dict]; + [[GPBInt64DoubleDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt64DoubleDictionary *dict = [GPBInt64DoubleDictionary dictionary]; + GPBInt64DoubleDictionary *dict = [[GPBInt64DoubleDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2441,6 +2460,7 @@ - (void)testAdds { XCTAssertTrue([dict getDouble:&value forKey:24LL]); XCTAssertEqual(value, 603.); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -2602,7 +2622,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt64EnumDictionary *dict = [GPBInt64EnumDictionary dictionaryWithEnum:700 forKey:21LL]; + GPBInt64EnumDictionary *dict = [[GPBInt64EnumDictionary alloc] init]; + [dict setEnum:700 forKey:21LL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int32_t value; @@ -2615,6 +2636,7 @@ - (void)testOne { XCTAssertEqual(aValue, 700); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2757,17 +2779,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt64EnumDictionary *dict2 = - [GPBInt64EnumDictionary dictionaryWithDictionary:dict]; + [[GPBInt64EnumDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt64EnumDictionary *dict = [GPBInt64EnumDictionary dictionary]; + GPBInt64EnumDictionary *dict = [[GPBInt64EnumDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2798,6 +2821,7 @@ - (void)testAdds { XCTAssertTrue([dict getEnum:&value forKey:24LL]); XCTAssertEqual(value, 703); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -3120,19 +3144,20 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt64EnumDictionary *dict2 = - [GPBInt64EnumDictionary dictionaryWithDictionary:dict]; + [[GPBInt64EnumDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison + [dict2 release]; [dict release]; } - (void)testUnknownAdds { GPBInt64EnumDictionary *dict = - [GPBInt64EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue]; + [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -3172,6 +3197,7 @@ - (void)testUnknownAdds { XCTAssertTrue([dict getRawValue:&value forKey:24LL]); XCTAssertEqual(value, 803); [dict2 release]; + [dict release]; } - (void)testUnknownRemove { @@ -3375,7 +3401,8 @@ - (void)testEmpty { } - (void)testOne { - GPBInt64ObjectDictionary *dict = [GPBInt64ObjectDictionary dictionaryWithObject:@"abc" forKey:21LL]; + GPBInt64ObjectDictionary *dict = [[GPBInt64ObjectDictionary alloc] init]; + [dict setObject:@"abc" forKey:21LL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); XCTAssertEqualObjects([dict objectForKey:21LL], @"abc"); @@ -3385,6 +3412,7 @@ - (void)testOne { XCTAssertEqualObjects(aObject, @"abc"); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -3520,17 +3548,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBInt64ObjectDictionary *dict2 = - [GPBInt64ObjectDictionary dictionaryWithDictionary:dict]; + [[GPBInt64ObjectDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBInt64ObjectDictionary *dict = [GPBInt64ObjectDictionary dictionary]; + GPBInt64ObjectDictionary *dict = [[GPBInt64ObjectDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -3552,6 +3581,7 @@ - (void)testAdds { XCTAssertEqualObjects([dict objectForKey:23LL], @"ghi"); XCTAssertEqualObjects([dict objectForKey:24LL], @"jkl"); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -3643,5 +3673,6 @@ - (void)testInplaceMutation { @end +// clang-format on //%PDDM-EXPAND-END TEST_FOR_POD_KEY(Int64, int64_t, 21LL, 22LL, 23LL, 24LL) diff --git a/objectivec/Tests/GPBDictionaryTests+String.m b/objectivec/Tests/GPBDictionaryTests+String.m index 5df1d51d59016..8ad1cea04fd12 100644 --- a/objectivec/Tests/GPBDictionaryTests+String.m +++ b/objectivec/Tests/GPBDictionaryTests+String.m @@ -42,10 +42,10 @@ //%PDDM-EXPAND TESTS_FOR_POD_VALUES(String, NSString, *, Objects, @"foo", @"bar", @"baz", @"mumble") // This block of code is generated, do not edit it directly. +// clang-format off // To let the testing macros work, add some extra methods to simplify things. @interface GPBStringEnumDictionary (TestingTweak) -+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(NSString *)key; - (instancetype)initWithEnums:(const int32_t [])values forKeys:(const NSString * [])keys count:(NSUInteger)count; @@ -64,14 +64,6 @@ static BOOL TestingEnum_IsValidValue(int32_t value) { } @implementation GPBStringEnumDictionary (TestingTweak) -+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(NSString *)key { - // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the - // type correct. - return [[(GPBStringEnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue - rawValues:&value - forKeys:&key - count:1] autorelease]; -} - (instancetype)initWithEnums:(const int32_t [])values forKeys:(const NSString * [])keys count:(NSUInteger)count { @@ -103,7 +95,8 @@ - (void)testEmpty { } - (void)testOne { - GPBStringUInt32Dictionary *dict = [GPBStringUInt32Dictionary dictionaryWithUInt32:100U forKey:@"foo"]; + GPBStringUInt32Dictionary *dict = [[GPBStringUInt32Dictionary alloc] init]; + [dict setUInt32:100U forKey:@"foo"]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); uint32_t value; @@ -116,6 +109,7 @@ - (void)testOne { XCTAssertEqual(aValue, 100U); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -258,17 +252,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBStringUInt32Dictionary *dict2 = - [GPBStringUInt32Dictionary dictionaryWithDictionary:dict]; + [[GPBStringUInt32Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBStringUInt32Dictionary *dict = [GPBStringUInt32Dictionary dictionary]; + GPBStringUInt32Dictionary *dict = [[GPBStringUInt32Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -299,6 +294,7 @@ - (void)testAdds { XCTAssertTrue([dict getUInt32:&value forKey:@"mumble"]); XCTAssertEqual(value, 103U); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -460,7 +456,8 @@ - (void)testEmpty { } - (void)testOne { - GPBStringInt32Dictionary *dict = [GPBStringInt32Dictionary dictionaryWithInt32:200 forKey:@"foo"]; + GPBStringInt32Dictionary *dict = [[GPBStringInt32Dictionary alloc] init]; + [dict setInt32:200 forKey:@"foo"]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int32_t value; @@ -473,6 +470,7 @@ - (void)testOne { XCTAssertEqual(aValue, 200); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -615,17 +613,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBStringInt32Dictionary *dict2 = - [GPBStringInt32Dictionary dictionaryWithDictionary:dict]; + [[GPBStringInt32Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBStringInt32Dictionary *dict = [GPBStringInt32Dictionary dictionary]; + GPBStringInt32Dictionary *dict = [[GPBStringInt32Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -656,6 +655,7 @@ - (void)testAdds { XCTAssertTrue([dict getInt32:&value forKey:@"mumble"]); XCTAssertEqual(value, 203); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -817,7 +817,8 @@ - (void)testEmpty { } - (void)testOne { - GPBStringUInt64Dictionary *dict = [GPBStringUInt64Dictionary dictionaryWithUInt64:300U forKey:@"foo"]; + GPBStringUInt64Dictionary *dict = [[GPBStringUInt64Dictionary alloc] init]; + [dict setUInt64:300U forKey:@"foo"]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); uint64_t value; @@ -830,6 +831,7 @@ - (void)testOne { XCTAssertEqual(aValue, 300U); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -972,17 +974,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBStringUInt64Dictionary *dict2 = - [GPBStringUInt64Dictionary dictionaryWithDictionary:dict]; + [[GPBStringUInt64Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBStringUInt64Dictionary *dict = [GPBStringUInt64Dictionary dictionary]; + GPBStringUInt64Dictionary *dict = [[GPBStringUInt64Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1013,6 +1016,7 @@ - (void)testAdds { XCTAssertTrue([dict getUInt64:&value forKey:@"mumble"]); XCTAssertEqual(value, 303U); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1174,7 +1178,8 @@ - (void)testEmpty { } - (void)testOne { - GPBStringInt64Dictionary *dict = [GPBStringInt64Dictionary dictionaryWithInt64:400 forKey:@"foo"]; + GPBStringInt64Dictionary *dict = [[GPBStringInt64Dictionary alloc] init]; + [dict setInt64:400 forKey:@"foo"]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int64_t value; @@ -1187,6 +1192,7 @@ - (void)testOne { XCTAssertEqual(aValue, 400); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -1329,17 +1335,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBStringInt64Dictionary *dict2 = - [GPBStringInt64Dictionary dictionaryWithDictionary:dict]; + [[GPBStringInt64Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBStringInt64Dictionary *dict = [GPBStringInt64Dictionary dictionary]; + GPBStringInt64Dictionary *dict = [[GPBStringInt64Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1370,6 +1377,7 @@ - (void)testAdds { XCTAssertTrue([dict getInt64:&value forKey:@"mumble"]); XCTAssertEqual(value, 403); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1531,7 +1539,8 @@ - (void)testEmpty { } - (void)testOne { - GPBStringBoolDictionary *dict = [GPBStringBoolDictionary dictionaryWithBool:YES forKey:@"foo"]; + GPBStringBoolDictionary *dict = [[GPBStringBoolDictionary alloc] init]; + [dict setBool:YES forKey:@"foo"]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); BOOL value; @@ -1544,6 +1553,7 @@ - (void)testOne { XCTAssertEqual(aValue, YES); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -1686,17 +1696,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBStringBoolDictionary *dict2 = - [GPBStringBoolDictionary dictionaryWithDictionary:dict]; + [[GPBStringBoolDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBStringBoolDictionary *dict = [GPBStringBoolDictionary dictionary]; + GPBStringBoolDictionary *dict = [[GPBStringBoolDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1727,6 +1738,7 @@ - (void)testAdds { XCTAssertTrue([dict getBool:&value forKey:@"mumble"]); XCTAssertEqual(value, NO); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1888,7 +1900,8 @@ - (void)testEmpty { } - (void)testOne { - GPBStringFloatDictionary *dict = [GPBStringFloatDictionary dictionaryWithFloat:500.f forKey:@"foo"]; + GPBStringFloatDictionary *dict = [[GPBStringFloatDictionary alloc] init]; + [dict setFloat:500.f forKey:@"foo"]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); float value; @@ -1901,6 +1914,7 @@ - (void)testOne { XCTAssertEqual(aValue, 500.f); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2043,17 +2057,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBStringFloatDictionary *dict2 = - [GPBStringFloatDictionary dictionaryWithDictionary:dict]; + [[GPBStringFloatDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBStringFloatDictionary *dict = [GPBStringFloatDictionary dictionary]; + GPBStringFloatDictionary *dict = [[GPBStringFloatDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2084,6 +2099,7 @@ - (void)testAdds { XCTAssertTrue([dict getFloat:&value forKey:@"mumble"]); XCTAssertEqual(value, 503.f); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -2245,7 +2261,8 @@ - (void)testEmpty { } - (void)testOne { - GPBStringDoubleDictionary *dict = [GPBStringDoubleDictionary dictionaryWithDouble:600. forKey:@"foo"]; + GPBStringDoubleDictionary *dict = [[GPBStringDoubleDictionary alloc] init]; + [dict setDouble:600. forKey:@"foo"]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); double value; @@ -2258,6 +2275,7 @@ - (void)testOne { XCTAssertEqual(aValue, 600.); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2400,17 +2418,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBStringDoubleDictionary *dict2 = - [GPBStringDoubleDictionary dictionaryWithDictionary:dict]; + [[GPBStringDoubleDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBStringDoubleDictionary *dict = [GPBStringDoubleDictionary dictionary]; + GPBStringDoubleDictionary *dict = [[GPBStringDoubleDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2441,6 +2460,7 @@ - (void)testAdds { XCTAssertTrue([dict getDouble:&value forKey:@"mumble"]); XCTAssertEqual(value, 603.); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -2602,7 +2622,8 @@ - (void)testEmpty { } - (void)testOne { - GPBStringEnumDictionary *dict = [GPBStringEnumDictionary dictionaryWithEnum:700 forKey:@"foo"]; + GPBStringEnumDictionary *dict = [[GPBStringEnumDictionary alloc] init]; + [dict setEnum:700 forKey:@"foo"]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int32_t value; @@ -2615,6 +2636,7 @@ - (void)testOne { XCTAssertEqual(aValue, 700); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2757,17 +2779,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBStringEnumDictionary *dict2 = - [GPBStringEnumDictionary dictionaryWithDictionary:dict]; + [[GPBStringEnumDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBStringEnumDictionary *dict = [GPBStringEnumDictionary dictionary]; + GPBStringEnumDictionary *dict = [[GPBStringEnumDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2798,6 +2821,7 @@ - (void)testAdds { XCTAssertTrue([dict getEnum:&value forKey:@"mumble"]); XCTAssertEqual(value, 703); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -3120,19 +3144,20 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBStringEnumDictionary *dict2 = - [GPBStringEnumDictionary dictionaryWithDictionary:dict]; + [[GPBStringEnumDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison + [dict2 release]; [dict release]; } - (void)testUnknownAdds { GPBStringEnumDictionary *dict = - [GPBStringEnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue]; + [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -3172,6 +3197,7 @@ - (void)testUnknownAdds { XCTAssertTrue([dict getRawValue:&value forKey:@"mumble"]); XCTAssertEqual(value, 803); [dict2 release]; + [dict release]; } - (void)testUnknownRemove { @@ -3355,5 +3381,6 @@ - (void)testCopyUnknowns { @end +// clang-format on //%PDDM-EXPAND-END TESTS_FOR_POD_VALUES(String, NSString, *, Objects, @"foo", @"bar", @"baz", @"mumble") diff --git a/objectivec/Tests/GPBDictionaryTests+UInt32.m b/objectivec/Tests/GPBDictionaryTests+UInt32.m index 1d3f6f78b0c82..f607538aa0433 100644 --- a/objectivec/Tests/GPBDictionaryTests+UInt32.m +++ b/objectivec/Tests/GPBDictionaryTests+UInt32.m @@ -42,10 +42,10 @@ //%PDDM-EXPAND TEST_FOR_POD_KEY(UInt32, uint32_t, 1U, 2U, 3U, 4U) // This block of code is generated, do not edit it directly. +// clang-format off // To let the testing macros work, add some extra methods to simplify things. @interface GPBUInt32EnumDictionary (TestingTweak) -+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(uint32_t)key; - (instancetype)initWithEnums:(const int32_t [])values forKeys:(const uint32_t [])keys count:(NSUInteger)count; @@ -64,14 +64,6 @@ static BOOL TestingEnum_IsValidValue(int32_t value) { } @implementation GPBUInt32EnumDictionary (TestingTweak) -+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(uint32_t)key { - // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the - // type correct. - return [[(GPBUInt32EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue - rawValues:&value - forKeys:&key - count:1] autorelease]; -} - (instancetype)initWithEnums:(const int32_t [])values forKeys:(const uint32_t [])keys count:(NSUInteger)count { @@ -103,7 +95,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt32UInt32Dictionary *dict = [GPBUInt32UInt32Dictionary dictionaryWithUInt32:100U forKey:1U]; + GPBUInt32UInt32Dictionary *dict = [[GPBUInt32UInt32Dictionary alloc] init]; + [dict setUInt32:100U forKey:1U]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); uint32_t value; @@ -116,6 +109,7 @@ - (void)testOne { XCTAssertEqual(aValue, 100U); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -258,17 +252,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt32UInt32Dictionary *dict2 = - [GPBUInt32UInt32Dictionary dictionaryWithDictionary:dict]; + [[GPBUInt32UInt32Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt32UInt32Dictionary *dict = [GPBUInt32UInt32Dictionary dictionary]; + GPBUInt32UInt32Dictionary *dict = [[GPBUInt32UInt32Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -299,6 +294,7 @@ - (void)testAdds { XCTAssertTrue([dict getUInt32:&value forKey:4U]); XCTAssertEqual(value, 103U); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -460,7 +456,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt32Int32Dictionary *dict = [GPBUInt32Int32Dictionary dictionaryWithInt32:200 forKey:1U]; + GPBUInt32Int32Dictionary *dict = [[GPBUInt32Int32Dictionary alloc] init]; + [dict setInt32:200 forKey:1U]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int32_t value; @@ -473,6 +470,7 @@ - (void)testOne { XCTAssertEqual(aValue, 200); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -615,17 +613,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt32Int32Dictionary *dict2 = - [GPBUInt32Int32Dictionary dictionaryWithDictionary:dict]; + [[GPBUInt32Int32Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt32Int32Dictionary *dict = [GPBUInt32Int32Dictionary dictionary]; + GPBUInt32Int32Dictionary *dict = [[GPBUInt32Int32Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -656,6 +655,7 @@ - (void)testAdds { XCTAssertTrue([dict getInt32:&value forKey:4U]); XCTAssertEqual(value, 203); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -817,7 +817,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt32UInt64Dictionary *dict = [GPBUInt32UInt64Dictionary dictionaryWithUInt64:300U forKey:1U]; + GPBUInt32UInt64Dictionary *dict = [[GPBUInt32UInt64Dictionary alloc] init]; + [dict setUInt64:300U forKey:1U]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); uint64_t value; @@ -830,6 +831,7 @@ - (void)testOne { XCTAssertEqual(aValue, 300U); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -972,17 +974,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt32UInt64Dictionary *dict2 = - [GPBUInt32UInt64Dictionary dictionaryWithDictionary:dict]; + [[GPBUInt32UInt64Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt32UInt64Dictionary *dict = [GPBUInt32UInt64Dictionary dictionary]; + GPBUInt32UInt64Dictionary *dict = [[GPBUInt32UInt64Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1013,6 +1016,7 @@ - (void)testAdds { XCTAssertTrue([dict getUInt64:&value forKey:4U]); XCTAssertEqual(value, 303U); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1174,7 +1178,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt32Int64Dictionary *dict = [GPBUInt32Int64Dictionary dictionaryWithInt64:400 forKey:1U]; + GPBUInt32Int64Dictionary *dict = [[GPBUInt32Int64Dictionary alloc] init]; + [dict setInt64:400 forKey:1U]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int64_t value; @@ -1187,6 +1192,7 @@ - (void)testOne { XCTAssertEqual(aValue, 400); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -1329,17 +1335,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt32Int64Dictionary *dict2 = - [GPBUInt32Int64Dictionary dictionaryWithDictionary:dict]; + [[GPBUInt32Int64Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt32Int64Dictionary *dict = [GPBUInt32Int64Dictionary dictionary]; + GPBUInt32Int64Dictionary *dict = [[GPBUInt32Int64Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1370,6 +1377,7 @@ - (void)testAdds { XCTAssertTrue([dict getInt64:&value forKey:4U]); XCTAssertEqual(value, 403); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1531,7 +1539,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt32BoolDictionary *dict = [GPBUInt32BoolDictionary dictionaryWithBool:YES forKey:1U]; + GPBUInt32BoolDictionary *dict = [[GPBUInt32BoolDictionary alloc] init]; + [dict setBool:YES forKey:1U]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); BOOL value; @@ -1544,6 +1553,7 @@ - (void)testOne { XCTAssertEqual(aValue, YES); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -1686,17 +1696,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt32BoolDictionary *dict2 = - [GPBUInt32BoolDictionary dictionaryWithDictionary:dict]; + [[GPBUInt32BoolDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt32BoolDictionary *dict = [GPBUInt32BoolDictionary dictionary]; + GPBUInt32BoolDictionary *dict = [[GPBUInt32BoolDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1727,6 +1738,7 @@ - (void)testAdds { XCTAssertTrue([dict getBool:&value forKey:4U]); XCTAssertEqual(value, NO); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1888,7 +1900,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt32FloatDictionary *dict = [GPBUInt32FloatDictionary dictionaryWithFloat:500.f forKey:1U]; + GPBUInt32FloatDictionary *dict = [[GPBUInt32FloatDictionary alloc] init]; + [dict setFloat:500.f forKey:1U]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); float value; @@ -1901,6 +1914,7 @@ - (void)testOne { XCTAssertEqual(aValue, 500.f); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2043,17 +2057,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt32FloatDictionary *dict2 = - [GPBUInt32FloatDictionary dictionaryWithDictionary:dict]; + [[GPBUInt32FloatDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt32FloatDictionary *dict = [GPBUInt32FloatDictionary dictionary]; + GPBUInt32FloatDictionary *dict = [[GPBUInt32FloatDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2084,6 +2099,7 @@ - (void)testAdds { XCTAssertTrue([dict getFloat:&value forKey:4U]); XCTAssertEqual(value, 503.f); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -2245,7 +2261,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt32DoubleDictionary *dict = [GPBUInt32DoubleDictionary dictionaryWithDouble:600. forKey:1U]; + GPBUInt32DoubleDictionary *dict = [[GPBUInt32DoubleDictionary alloc] init]; + [dict setDouble:600. forKey:1U]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); double value; @@ -2258,6 +2275,7 @@ - (void)testOne { XCTAssertEqual(aValue, 600.); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2400,17 +2418,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt32DoubleDictionary *dict2 = - [GPBUInt32DoubleDictionary dictionaryWithDictionary:dict]; + [[GPBUInt32DoubleDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt32DoubleDictionary *dict = [GPBUInt32DoubleDictionary dictionary]; + GPBUInt32DoubleDictionary *dict = [[GPBUInt32DoubleDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2441,6 +2460,7 @@ - (void)testAdds { XCTAssertTrue([dict getDouble:&value forKey:4U]); XCTAssertEqual(value, 603.); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -2602,7 +2622,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt32EnumDictionary *dict = [GPBUInt32EnumDictionary dictionaryWithEnum:700 forKey:1U]; + GPBUInt32EnumDictionary *dict = [[GPBUInt32EnumDictionary alloc] init]; + [dict setEnum:700 forKey:1U]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int32_t value; @@ -2615,6 +2636,7 @@ - (void)testOne { XCTAssertEqual(aValue, 700); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2757,17 +2779,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt32EnumDictionary *dict2 = - [GPBUInt32EnumDictionary dictionaryWithDictionary:dict]; + [[GPBUInt32EnumDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt32EnumDictionary *dict = [GPBUInt32EnumDictionary dictionary]; + GPBUInt32EnumDictionary *dict = [[GPBUInt32EnumDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2798,6 +2821,7 @@ - (void)testAdds { XCTAssertTrue([dict getEnum:&value forKey:4U]); XCTAssertEqual(value, 703); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -3120,19 +3144,20 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt32EnumDictionary *dict2 = - [GPBUInt32EnumDictionary dictionaryWithDictionary:dict]; + [[GPBUInt32EnumDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison + [dict2 release]; [dict release]; } - (void)testUnknownAdds { GPBUInt32EnumDictionary *dict = - [GPBUInt32EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue]; + [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -3172,6 +3197,7 @@ - (void)testUnknownAdds { XCTAssertTrue([dict getRawValue:&value forKey:4U]); XCTAssertEqual(value, 803); [dict2 release]; + [dict release]; } - (void)testUnknownRemove { @@ -3375,7 +3401,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt32ObjectDictionary *dict = [GPBUInt32ObjectDictionary dictionaryWithObject:@"abc" forKey:1U]; + GPBUInt32ObjectDictionary *dict = [[GPBUInt32ObjectDictionary alloc] init]; + [dict setObject:@"abc" forKey:1U]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); XCTAssertEqualObjects([dict objectForKey:1U], @"abc"); @@ -3385,6 +3412,7 @@ - (void)testOne { XCTAssertEqualObjects(aObject, @"abc"); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -3520,17 +3548,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt32ObjectDictionary *dict2 = - [GPBUInt32ObjectDictionary dictionaryWithDictionary:dict]; + [[GPBUInt32ObjectDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt32ObjectDictionary *dict = [GPBUInt32ObjectDictionary dictionary]; + GPBUInt32ObjectDictionary *dict = [[GPBUInt32ObjectDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -3552,6 +3581,7 @@ - (void)testAdds { XCTAssertEqualObjects([dict objectForKey:3U], @"ghi"); XCTAssertEqualObjects([dict objectForKey:4U], @"jkl"); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -3643,5 +3673,6 @@ - (void)testInplaceMutation { @end +// clang-format on //%PDDM-EXPAND-END TEST_FOR_POD_KEY(UInt32, uint32_t, 1U, 2U, 3U, 4U) diff --git a/objectivec/Tests/GPBDictionaryTests+UInt64.m b/objectivec/Tests/GPBDictionaryTests+UInt64.m index 94c116f67f61c..b5dd91e0943dc 100644 --- a/objectivec/Tests/GPBDictionaryTests+UInt64.m +++ b/objectivec/Tests/GPBDictionaryTests+UInt64.m @@ -42,10 +42,10 @@ //%PDDM-EXPAND TEST_FOR_POD_KEY(UInt64, uint64_t, 31ULL, 32ULL, 33ULL, 34ULL) // This block of code is generated, do not edit it directly. +// clang-format off // To let the testing macros work, add some extra methods to simplify things. @interface GPBUInt64EnumDictionary (TestingTweak) -+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(uint64_t)key; - (instancetype)initWithEnums:(const int32_t [])values forKeys:(const uint64_t [])keys count:(NSUInteger)count; @@ -64,14 +64,6 @@ static BOOL TestingEnum_IsValidValue(int32_t value) { } @implementation GPBUInt64EnumDictionary (TestingTweak) -+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(uint64_t)key { - // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the - // type correct. - return [[(GPBUInt64EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue - rawValues:&value - forKeys:&key - count:1] autorelease]; -} - (instancetype)initWithEnums:(const int32_t [])values forKeys:(const uint64_t [])keys count:(NSUInteger)count { @@ -103,7 +95,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt64UInt32Dictionary *dict = [GPBUInt64UInt32Dictionary dictionaryWithUInt32:100U forKey:31ULL]; + GPBUInt64UInt32Dictionary *dict = [[GPBUInt64UInt32Dictionary alloc] init]; + [dict setUInt32:100U forKey:31ULL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); uint32_t value; @@ -116,6 +109,7 @@ - (void)testOne { XCTAssertEqual(aValue, 100U); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -258,17 +252,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt64UInt32Dictionary *dict2 = - [GPBUInt64UInt32Dictionary dictionaryWithDictionary:dict]; + [[GPBUInt64UInt32Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt64UInt32Dictionary *dict = [GPBUInt64UInt32Dictionary dictionary]; + GPBUInt64UInt32Dictionary *dict = [[GPBUInt64UInt32Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -299,6 +294,7 @@ - (void)testAdds { XCTAssertTrue([dict getUInt32:&value forKey:34ULL]); XCTAssertEqual(value, 103U); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -460,7 +456,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt64Int32Dictionary *dict = [GPBUInt64Int32Dictionary dictionaryWithInt32:200 forKey:31ULL]; + GPBUInt64Int32Dictionary *dict = [[GPBUInt64Int32Dictionary alloc] init]; + [dict setInt32:200 forKey:31ULL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int32_t value; @@ -473,6 +470,7 @@ - (void)testOne { XCTAssertEqual(aValue, 200); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -615,17 +613,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt64Int32Dictionary *dict2 = - [GPBUInt64Int32Dictionary dictionaryWithDictionary:dict]; + [[GPBUInt64Int32Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt64Int32Dictionary *dict = [GPBUInt64Int32Dictionary dictionary]; + GPBUInt64Int32Dictionary *dict = [[GPBUInt64Int32Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -656,6 +655,7 @@ - (void)testAdds { XCTAssertTrue([dict getInt32:&value forKey:34ULL]); XCTAssertEqual(value, 203); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -817,7 +817,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt64UInt64Dictionary *dict = [GPBUInt64UInt64Dictionary dictionaryWithUInt64:300U forKey:31ULL]; + GPBUInt64UInt64Dictionary *dict = [[GPBUInt64UInt64Dictionary alloc] init]; + [dict setUInt64:300U forKey:31ULL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); uint64_t value; @@ -830,6 +831,7 @@ - (void)testOne { XCTAssertEqual(aValue, 300U); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -972,17 +974,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt64UInt64Dictionary *dict2 = - [GPBUInt64UInt64Dictionary dictionaryWithDictionary:dict]; + [[GPBUInt64UInt64Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt64UInt64Dictionary *dict = [GPBUInt64UInt64Dictionary dictionary]; + GPBUInt64UInt64Dictionary *dict = [[GPBUInt64UInt64Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1013,6 +1016,7 @@ - (void)testAdds { XCTAssertTrue([dict getUInt64:&value forKey:34ULL]); XCTAssertEqual(value, 303U); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1174,7 +1178,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt64Int64Dictionary *dict = [GPBUInt64Int64Dictionary dictionaryWithInt64:400 forKey:31ULL]; + GPBUInt64Int64Dictionary *dict = [[GPBUInt64Int64Dictionary alloc] init]; + [dict setInt64:400 forKey:31ULL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int64_t value; @@ -1187,6 +1192,7 @@ - (void)testOne { XCTAssertEqual(aValue, 400); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -1329,17 +1335,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt64Int64Dictionary *dict2 = - [GPBUInt64Int64Dictionary dictionaryWithDictionary:dict]; + [[GPBUInt64Int64Dictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt64Int64Dictionary *dict = [GPBUInt64Int64Dictionary dictionary]; + GPBUInt64Int64Dictionary *dict = [[GPBUInt64Int64Dictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1370,6 +1377,7 @@ - (void)testAdds { XCTAssertTrue([dict getInt64:&value forKey:34ULL]); XCTAssertEqual(value, 403); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1531,7 +1539,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt64BoolDictionary *dict = [GPBUInt64BoolDictionary dictionaryWithBool:YES forKey:31ULL]; + GPBUInt64BoolDictionary *dict = [[GPBUInt64BoolDictionary alloc] init]; + [dict setBool:YES forKey:31ULL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); BOOL value; @@ -1544,6 +1553,7 @@ - (void)testOne { XCTAssertEqual(aValue, YES); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -1686,17 +1696,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt64BoolDictionary *dict2 = - [GPBUInt64BoolDictionary dictionaryWithDictionary:dict]; + [[GPBUInt64BoolDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt64BoolDictionary *dict = [GPBUInt64BoolDictionary dictionary]; + GPBUInt64BoolDictionary *dict = [[GPBUInt64BoolDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -1727,6 +1738,7 @@ - (void)testAdds { XCTAssertTrue([dict getBool:&value forKey:34ULL]); XCTAssertEqual(value, NO); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -1888,7 +1900,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt64FloatDictionary *dict = [GPBUInt64FloatDictionary dictionaryWithFloat:500.f forKey:31ULL]; + GPBUInt64FloatDictionary *dict = [[GPBUInt64FloatDictionary alloc] init]; + [dict setFloat:500.f forKey:31ULL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); float value; @@ -1901,6 +1914,7 @@ - (void)testOne { XCTAssertEqual(aValue, 500.f); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2043,17 +2057,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt64FloatDictionary *dict2 = - [GPBUInt64FloatDictionary dictionaryWithDictionary:dict]; + [[GPBUInt64FloatDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt64FloatDictionary *dict = [GPBUInt64FloatDictionary dictionary]; + GPBUInt64FloatDictionary *dict = [[GPBUInt64FloatDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2084,6 +2099,7 @@ - (void)testAdds { XCTAssertTrue([dict getFloat:&value forKey:34ULL]); XCTAssertEqual(value, 503.f); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -2245,7 +2261,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt64DoubleDictionary *dict = [GPBUInt64DoubleDictionary dictionaryWithDouble:600. forKey:31ULL]; + GPBUInt64DoubleDictionary *dict = [[GPBUInt64DoubleDictionary alloc] init]; + [dict setDouble:600. forKey:31ULL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); double value; @@ -2258,6 +2275,7 @@ - (void)testOne { XCTAssertEqual(aValue, 600.); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2400,17 +2418,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt64DoubleDictionary *dict2 = - [GPBUInt64DoubleDictionary dictionaryWithDictionary:dict]; + [[GPBUInt64DoubleDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt64DoubleDictionary *dict = [GPBUInt64DoubleDictionary dictionary]; + GPBUInt64DoubleDictionary *dict = [[GPBUInt64DoubleDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2441,6 +2460,7 @@ - (void)testAdds { XCTAssertTrue([dict getDouble:&value forKey:34ULL]); XCTAssertEqual(value, 603.); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -2602,7 +2622,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt64EnumDictionary *dict = [GPBUInt64EnumDictionary dictionaryWithEnum:700 forKey:31ULL]; + GPBUInt64EnumDictionary *dict = [[GPBUInt64EnumDictionary alloc] init]; + [dict setEnum:700 forKey:31ULL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); int32_t value; @@ -2615,6 +2636,7 @@ - (void)testOne { XCTAssertEqual(aValue, 700); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -2757,17 +2779,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt64EnumDictionary *dict2 = - [GPBUInt64EnumDictionary dictionaryWithDictionary:dict]; + [[GPBUInt64EnumDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt64EnumDictionary *dict = [GPBUInt64EnumDictionary dictionary]; + GPBUInt64EnumDictionary *dict = [[GPBUInt64EnumDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -2798,6 +2821,7 @@ - (void)testAdds { XCTAssertTrue([dict getEnum:&value forKey:34ULL]); XCTAssertEqual(value, 703); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -3120,19 +3144,20 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt64EnumDictionary *dict2 = - [GPBUInt64EnumDictionary dictionaryWithDictionary:dict]; + [[GPBUInt64EnumDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison + [dict2 release]; [dict release]; } - (void)testUnknownAdds { GPBUInt64EnumDictionary *dict = - [GPBUInt64EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue]; + [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -3172,6 +3197,7 @@ - (void)testUnknownAdds { XCTAssertTrue([dict getRawValue:&value forKey:34ULL]); XCTAssertEqual(value, 803); [dict2 release]; + [dict release]; } - (void)testUnknownRemove { @@ -3375,7 +3401,8 @@ - (void)testEmpty { } - (void)testOne { - GPBUInt64ObjectDictionary *dict = [GPBUInt64ObjectDictionary dictionaryWithObject:@"abc" forKey:31ULL]; + GPBUInt64ObjectDictionary *dict = [[GPBUInt64ObjectDictionary alloc] init]; + [dict setObject:@"abc" forKey:31ULL]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 1U); XCTAssertEqualObjects([dict objectForKey:31ULL], @"abc"); @@ -3385,6 +3412,7 @@ - (void)testOne { XCTAssertEqualObjects(aObject, @"abc"); XCTAssertNotEqual(stop, NULL); }]; + [dict release]; } - (void)testBasics { @@ -3520,17 +3548,18 @@ - (void)testDictionaryFromDictionary { XCTAssertNotNil(dict); GPBUInt64ObjectDictionary *dict2 = - [GPBUInt64ObjectDictionary dictionaryWithDictionary:dict]; + [[GPBUInt64ObjectDictionary alloc] initWithDictionary:dict]; XCTAssertNotNil(dict2); // Should be new pointer, but equal objects. XCTAssertNotEqual(dict, dict2); XCTAssertEqualObjects(dict, dict2); + [dict2 release]; [dict release]; } - (void)testAdds { - GPBUInt64ObjectDictionary *dict = [GPBUInt64ObjectDictionary dictionary]; + GPBUInt64ObjectDictionary *dict = [[GPBUInt64ObjectDictionary alloc] init]; XCTAssertNotNil(dict); XCTAssertEqual(dict.count, 0U); @@ -3552,6 +3581,7 @@ - (void)testAdds { XCTAssertEqualObjects([dict objectForKey:33ULL], @"ghi"); XCTAssertEqualObjects([dict objectForKey:34ULL], @"jkl"); [dict2 release]; + [dict release]; } - (void)testRemove { @@ -3643,4 +3673,5 @@ - (void)testInplaceMutation { @end +// clang-format on //%PDDM-EXPAND-END TEST_FOR_POD_KEY(UInt64, uint64_t, 31ULL, 32ULL, 33ULL, 34ULL) diff --git a/objectivec/Tests/GPBDictionaryTests.pddm b/objectivec/Tests/GPBDictionaryTests.pddm index d6aa72119058d..17f12c28f0031 100644 --- a/objectivec/Tests/GPBDictionaryTests.pddm +++ b/objectivec/Tests/GPBDictionaryTests.pddm @@ -78,7 +78,8 @@ //%} //% //%- (void)testOne { -//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWith##VALUE_NAME$u##:VAL1 forKey:KEY1]; +//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init]; +//% [dict set##VALUE_NAME$u##:VAL1 forKey:KEY1]; //% XCTAssertNotNil(dict); //% XCTAssertEqual(dict.count, 1U); //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1) @@ -88,6 +89,7 @@ //% XCTAssertEqual##VSUFFIX(a##VNAME$u, VAL1); //% XCTAssertNotEqual(stop, NULL); //% }]; +//% [dict release]; //%} //% //%- (void)testBasics { @@ -223,17 +225,18 @@ //% XCTAssertNotNil(dict); //% //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = -//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict]; +//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithDictionary:dict]; //% XCTAssertNotNil(dict2); //% //% // Should be new pointer, but equal objects. //% XCTAssertNotEqual(dict, dict2); //% XCTAssertEqualObjects(dict, dict2); +//% [dict2 release]; //% [dict release]; //%} //% //%- (void)testAdds { -//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary]; +//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init]; //% XCTAssertNotNil(dict); //% //% XCTAssertEqual(dict.count, 0U); @@ -255,6 +258,7 @@ //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY3, VAL3) //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY4, VAL4) //% [dict2 release]; +//% [dict release]; //%} //% //%- (void)testRemove { @@ -522,19 +526,20 @@ //% XCTAssertNotNil(dict); //% //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = -//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict]; +//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithDictionary:dict]; //% XCTAssertNotNil(dict2); //% //% // Should be new pointer, but equal objects. //% XCTAssertNotEqual(dict, dict2); //% XCTAssertEqualObjects(dict, dict2); //% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison +//% [dict2 release]; //% [dict release]; //%} //% //%- (void)testUnknownAdds { //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = -//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue]; +//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue]; //% XCTAssertNotNil(dict); //% //% XCTAssertEqual(dict.count, 0U); @@ -561,6 +566,7 @@ //%TEST_VALUE##VHELPER(VALUE_NAME, dict, value, KEY4, kGPBUnrecognizedEnumeratorValue) //%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4) //% [dict2 release]; +//% [dict release]; //%} //% //%- (void)testUnknownRemove { @@ -729,7 +735,6 @@ //%PDDM-DEFINE TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP) //%// To let the testing macros work, add some extra methods to simplify things. //%@interface GPB##KEY_NAME##EnumDictionary (TestingTweak) -//%+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(KEY_TYPE##KisP$S##KisP)key; //%- (instancetype)initWithEnums:(const int32_t [])values //% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys //% count:(NSUInteger)count; @@ -748,14 +753,6 @@ //%} //% //%@implementation GPB##KEY_NAME##EnumDictionary (TestingTweak) -//%+ (instancetype)dictionaryWithEnum:(int32_t)value forKey:(KEY_TYPE##KisP$S##KisP)key { -//% // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the -//% // type correct. -//% return [[(GPB##KEY_NAME##EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue -//% KEY_NAME$S rawValues:&value -//% KEY_NAME$S forKeys:&key -//% KEY_NAME$S count:1] autorelease]; -//%} //%- (instancetype)initWithEnums:(const int32_t [])values //% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys //% count:(NSUInteger)count { @@ -801,7 +798,8 @@ //%} //% //%- (void)testOne { -//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWith##VALUE_NAME$u##:VAL1 forKey:KEY1]; +//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init]; +//% [dict set##VALUE_NAME$u##:VAL1 forKey:KEY1]; //% XCTAssertNotNil(dict); //% XCTAssertEqual(dict.count, 1U); //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1) @@ -811,6 +809,7 @@ //% XCTAssertEqual##VSUFFIX(a##VNAME$u, VAL1); //% XCTAssertNotEqual(stop, NULL); //% }]; +//% [dict release]; //%} //% //%- (void)testBasics { @@ -944,17 +943,18 @@ //% XCTAssertNotNil(dict); //% //% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict2 = -//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict]; +//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithDictionary:dict]; //% XCTAssertNotNil(dict2); //% //% // Should be new pointer, but equal objects. //% XCTAssertNotEqual(dict, dict2); //% XCTAssertEqualObjects(dict, dict2); +//% [dict2 release]; //% [dict release]; //%} //% //%- (void)testAdds { -//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary]; +//% DICTIONARY_CLASS_DECL##VHELPER(KEY_NAME, VALUE_NAME, VALUE_TYPE) *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init]; //% XCTAssertNotNil(dict); //% //% XCTAssertEqual(dict.count, 0U); @@ -974,6 +974,7 @@ //%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, VNAME)TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY1, VAL1) //%TEST_VALUE##VHELPER(VALUE_NAME, dict, VNAME, KEY2, VAL2) //% [dict2 release]; +//% [dict release]; //%} //% //%- (void)testRemove { diff --git a/objectivec/Tests/GPBMessageTests+ClassNames.m b/objectivec/Tests/GPBMessageTests+ClassNames.m new file mode 100644 index 0000000000000..b5a5c51d043c7 --- /dev/null +++ b/objectivec/Tests/GPBMessageTests+ClassNames.m @@ -0,0 +1,164 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "GPBTestUtilities.h" + +#import + +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBExtensionRegistry.h" +#import "GPBMessage.h" +#import "GPBRootObject_PackagePrivate.h" + +// Support classes for tests using old class name (vs classrefs) interfaces. +GPB_FINAL @interface MessageLackingClazzRoot : GPBRootObject +@end + +@interface MessageLackingClazzRoot (DynamicMethods) ++ (GPBExtensionDescriptor *)ext1; +@end + +GPB_FINAL @interface MessageLackingClazz : GPBMessage +@property(copy, nonatomic) NSString *foo; +@end + +@implementation MessageLackingClazz + +@dynamic foo; + +typedef struct MessageLackingClazz_storage_ { + uint32_t _has_storage_[1]; + NSString *foo; +} MessageLackingClazz_storage_; + ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "foo", + .dataTypeSpecific.className = "NSString", + .number = 1, + .hasIndex = 0, + .offset = (uint32_t)offsetof(MessageLackingClazz_storage_, foo), + .flags = (GPBFieldFlags)(GPBFieldOptional), + .dataType = GPBDataTypeMessage, + }, + }; + GPBFileDescriptor *desc = + [[[GPBFileDescriptor alloc] initWithPackage:@"test" + objcPrefix:@"TEST" + syntax:GPBFileSyntaxProto3] autorelease]; + + // GPBDescriptorInitializationFlag_UsesClassRefs intentionally not set here + descriptor = + [GPBDescriptor allocDescriptorForClass:[MessageLackingClazz class] + rootClass:[MessageLackingClazzRoot class] + file:desc + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(MessageLackingClazz_storage_) + flags:GPBDescriptorInitializationFlag_None]; + [descriptor setupContainingMessageClassName:"MessageLackingClazz"]; + } + return descriptor; +} +@end + +@implementation MessageLackingClazzRoot + ++ (GPBExtensionRegistry*)extensionRegistry { + // This is called by +initialize so there is no need to worry + // about thread safety and initialization of registry. + static GPBExtensionRegistry* registry = nil; + if (!registry) { + registry = [[GPBExtensionRegistry alloc] init]; + static GPBExtensionDescription descriptions[] = { + { + .defaultValue.valueMessage = NULL, + .singletonName = "MessageLackingClazzRoot_ext1", + .extendedClass.name = "MessageLackingClazz", + .messageOrGroupClass.name = "MessageLackingClazz", + .enumDescriptorFunc = NULL, + .fieldNumber = 1, + .dataType = GPBDataTypeMessage, + // GPBExtensionUsesClazz Intentionally not set + .options = 0, + }, + }; + for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) { + // Intentionall using `-initWithExtensionDescription:` and not ` + // -initWithExtensionDescription:usesClassRefs:` to test backwards + // compatibility + GPBExtensionDescriptor *extension = + [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]]; + [registry addExtension:extension]; + [self globallyRegisterExtension:extension]; + [extension release]; + } + // None of the imports (direct or indirect) defined extensions, so no need to add + // them to this registry. + } + return registry; +} +@end + +@interface MessageClassNameTests : GPBTestCase +@end + +@implementation MessageClassNameTests + +- (void)testClassNameSupported { + // This tests backwards compatibility to make sure we support older sources + // that use class names instead of references. + GPBDescriptor *desc = [MessageLackingClazz descriptor]; + GPBFieldDescriptor *fieldDesc = [desc fieldWithName:@"foo"]; + XCTAssertEqualObjects(fieldDesc.msgClass, [NSString class]); +} + +- (void)testSetupContainingMessageClassNameSupported { + // This tests backwards compatibility to make sure we support older sources + // that use class names instead of references. + GPBDescriptor *desc = [MessageLackingClazz descriptor]; + GPBDescriptor *container = [desc containingType]; + XCTAssertEqualObjects(container.messageClass, [MessageLackingClazz class]); +} + +- (void)testExtensionsNameSupported { + // This tests backwards compatibility to make sure we support older sources + // that use class names instead of references. + GPBExtensionDescriptor *desc = [MessageLackingClazzRoot ext1]; + Class containerClass = [desc containingMessageClass]; + XCTAssertEqualObjects(containerClass, [MessageLackingClazz class]); + Class msgClass = [desc msgClass]; + XCTAssertEqualObjects(msgClass, [MessageLackingClazz class]); +} + +@end diff --git a/objectivec/Tests/GPBMessageTests+Merge.m b/objectivec/Tests/GPBMessageTests+Merge.m index c0bd5897a4a69..f895542bf2f12 100644 --- a/objectivec/Tests/GPBMessageTests+Merge.m +++ b/objectivec/Tests/GPBMessageTests+Merge.m @@ -267,6 +267,7 @@ - (void)testProto2MergeOneof { //% //%PDDM-EXPAND MERGE2_TEST(Int32, 10, Enum, Message2_Enum_Baz) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofInt32 = 10; [dst mergeFrom:src]; @@ -274,8 +275,10 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oneofInt32, 10); XCTAssertEqual(dst.oneofEnum, Message2_Enum_Baz); +// clang-format on //%PDDM-EXPAND MERGE2_TEST(Int64, 11, Int32, 100) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofInt64 = 11; [dst mergeFrom:src]; @@ -283,8 +286,10 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oneofInt64, 11); XCTAssertEqual(dst.oneofInt32, 100); +// clang-format on //%PDDM-EXPAND MERGE2_TEST(Uint32, 12U, Int64, 101) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofUint32 = 12U; [dst mergeFrom:src]; @@ -292,8 +297,10 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oneofUint32, 12U); XCTAssertEqual(dst.oneofInt64, 101); +// clang-format on //%PDDM-EXPAND MERGE2_TEST(Uint64, 13U, Uint32, 102U) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofUint64 = 13U; [dst mergeFrom:src]; @@ -301,8 +308,10 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oneofUint64, 13U); XCTAssertEqual(dst.oneofUint32, 102U); +// clang-format on //%PDDM-EXPAND MERGE2_TEST(Sint32, 14, Uint64, 103U) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofSint32 = 14; [dst mergeFrom:src]; @@ -310,8 +319,10 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oneofSint32, 14); XCTAssertEqual(dst.oneofUint64, 103U); +// clang-format on //%PDDM-EXPAND MERGE2_TEST(Sint64, 15, Sint32, 104) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofSint64 = 15; [dst mergeFrom:src]; @@ -319,8 +330,10 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oneofSint64, 15); XCTAssertEqual(dst.oneofSint32, 104); +// clang-format on //%PDDM-EXPAND MERGE2_TEST(Fixed32, 16U, Sint64, 105) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofFixed32 = 16U; [dst mergeFrom:src]; @@ -328,8 +341,10 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oneofFixed32, 16U); XCTAssertEqual(dst.oneofSint64, 105); +// clang-format on //%PDDM-EXPAND MERGE2_TEST(Fixed64, 17U, Fixed32, 106U) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofFixed64 = 17U; [dst mergeFrom:src]; @@ -337,8 +352,10 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oneofFixed64, 17U); XCTAssertEqual(dst.oneofFixed32, 106U); +// clang-format on //%PDDM-EXPAND MERGE2_TEST(Sfixed32, 18, Fixed64, 107U) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofSfixed32 = 18; [dst mergeFrom:src]; @@ -346,8 +363,10 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oneofSfixed32, 18); XCTAssertEqual(dst.oneofFixed64, 107U); +// clang-format on //%PDDM-EXPAND MERGE2_TEST(Sfixed64, 19, Sfixed32, 108) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofSfixed64 = 19; [dst mergeFrom:src]; @@ -355,8 +374,10 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oneofSfixed64, 19); XCTAssertEqual(dst.oneofSfixed32, 108); +// clang-format on //%PDDM-EXPAND MERGE2_TEST(Float, 20.0f, Sfixed64, 109) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofFloat = 20.0f; [dst mergeFrom:src]; @@ -364,8 +385,10 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oneofFloat, 20.0f); XCTAssertEqual(dst.oneofSfixed64, 109); +// clang-format on //%PDDM-EXPAND MERGE2_TEST(Double, 21.0, Float, 110.0f) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofDouble = 21.0; [dst mergeFrom:src]; @@ -373,8 +396,10 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oneofDouble, 21.0); XCTAssertEqual(dst.oneofFloat, 110.0f); +// clang-format on //%PDDM-EXPAND MERGE2_TEST(Bool, NO, Double, 111.0) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofBool = NO; [dst mergeFrom:src]; @@ -382,8 +407,10 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oneofBool, NO); XCTAssertEqual(dst.oneofDouble, 111.0); +// clang-format on //%PDDM-EXPAND MERGE2_TEST(Enum, Message2_Enum_Bar, Bool, YES) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofEnum = Message2_Enum_Bar; [dst mergeFrom:src]; @@ -391,6 +418,7 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oneofEnum, Message2_Enum_Bar); XCTAssertEqual(dst.oneofBool, YES); +// clang-format on //%PDDM-EXPAND-END (14 expansions) NSString *oneofStringDefault = @"string"; @@ -416,7 +444,7 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofGroup); Message2_OneofGroup *mergedGroup = [[dst.oneofGroup retain] autorelease]; XCTAssertNotNil(mergedGroup); - XCTAssertNotEqual(mergedGroup, group); // Pointer comparision. + XCTAssertNotEqual(mergedGroup, group); // Pointer comparison. XCTAssertEqualObjects(mergedGroup, group); XCTAssertEqualObjects(dst.oneofBytes, oneofBytesDefault); @@ -427,10 +455,10 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofMessage); Message2 *mergedSubMessage = [[dst.oneofMessage retain] autorelease]; XCTAssertNotNil(mergedSubMessage); - XCTAssertNotEqual(mergedSubMessage, subMessage); // Pointer comparision. + XCTAssertNotEqual(mergedSubMessage, subMessage); // Pointer comparison. XCTAssertEqualObjects(mergedSubMessage, subMessage); XCTAssertNotNil(dst.oneofGroup); - XCTAssertNotEqual(dst.oneofGroup, mergedGroup); // Pointer comparision. + XCTAssertNotEqual(dst.oneofGroup, mergedGroup); // Pointer comparison. // Back to something else to make sure message clears out ok. @@ -439,7 +467,7 @@ - (void)testProto2MergeOneof { XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofInt32); XCTAssertNotNil(dst.oneofMessage); XCTAssertNotEqual(dst.oneofMessage, - mergedSubMessage); // Pointer comparision. + mergedSubMessage); // Pointer comparison. // // Test merging in to message/group when they already had something. @@ -452,9 +480,9 @@ - (void)testProto2MergeOneof { [dst mergeFrom:src]; XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofGroup); // Shouldn't have been a new object. - XCTAssertEqual(dst.oneofGroup, mergedGroup); // Pointer comparision. - XCTAssertEqual(dst.oneofGroup.a, 666); // Pointer comparision. - XCTAssertEqual(dst.oneofGroup.b, 888); // Pointer comparision. + XCTAssertEqual(dst.oneofGroup, mergedGroup); // Pointer comparison. + XCTAssertEqual(dst.oneofGroup.a, 666); // Pointer comparison. + XCTAssertEqual(dst.oneofGroup.b, 888); // Pointer comparison. src.oneofMessage = subMessage; mergedSubMessage = [Message2 message]; @@ -463,9 +491,9 @@ - (void)testProto2MergeOneof { [dst mergeFrom:src]; XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofMessage); // Shouldn't have been a new object. - XCTAssertEqual(dst.oneofMessage, mergedSubMessage); // Pointer comparision. - XCTAssertEqual(dst.oneofMessage.optionalInt32, 777); // Pointer comparision. - XCTAssertEqual(dst.oneofMessage.optionalInt64, 999); // Pointer comparision. + XCTAssertEqual(dst.oneofMessage, mergedSubMessage); // Pointer comparison. + XCTAssertEqual(dst.oneofMessage.optionalInt32, 777); // Pointer comparison. + XCTAssertEqual(dst.oneofMessage.optionalInt64, 999); // Pointer comparison. } - (void)testProto3MergeOneof { @@ -487,6 +515,7 @@ - (void)testProto3MergeOneof { //% //%PDDM-EXPAND MERGE3_TEST(Int32, 10, Enum, Message3_Enum_Foo) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofInt32 = 10; [dst mergeFrom:src]; @@ -494,8 +523,10 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oneofInt32, 10); XCTAssertEqual(dst.oneofEnum, Message3_Enum_Foo); +// clang-format on //%PDDM-EXPAND MERGE3_TEST(Int64, 11, Int32, 0) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofInt64 = 11; [dst mergeFrom:src]; @@ -503,8 +534,10 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oneofInt64, 11); XCTAssertEqual(dst.oneofInt32, 0); +// clang-format on //%PDDM-EXPAND MERGE3_TEST(Uint32, 12U, Int64, 0) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofUint32 = 12U; [dst mergeFrom:src]; @@ -512,8 +545,10 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oneofUint32, 12U); XCTAssertEqual(dst.oneofInt64, 0); +// clang-format on //%PDDM-EXPAND MERGE3_TEST(Uint64, 13U, Uint32, 0U) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofUint64 = 13U; [dst mergeFrom:src]; @@ -521,8 +556,10 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oneofUint64, 13U); XCTAssertEqual(dst.oneofUint32, 0U); +// clang-format on //%PDDM-EXPAND MERGE3_TEST(Sint32, 14, Uint64, 0U) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofSint32 = 14; [dst mergeFrom:src]; @@ -530,8 +567,10 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oneofSint32, 14); XCTAssertEqual(dst.oneofUint64, 0U); +// clang-format on //%PDDM-EXPAND MERGE3_TEST(Sint64, 15, Sint32, 0) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofSint64 = 15; [dst mergeFrom:src]; @@ -539,8 +578,10 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oneofSint64, 15); XCTAssertEqual(dst.oneofSint32, 0); +// clang-format on //%PDDM-EXPAND MERGE3_TEST(Fixed32, 16U, Sint64, 0) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofFixed32 = 16U; [dst mergeFrom:src]; @@ -548,8 +589,10 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oneofFixed32, 16U); XCTAssertEqual(dst.oneofSint64, 0); +// clang-format on //%PDDM-EXPAND MERGE3_TEST(Fixed64, 17U, Fixed32, 0U) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofFixed64 = 17U; [dst mergeFrom:src]; @@ -557,8 +600,10 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oneofFixed64, 17U); XCTAssertEqual(dst.oneofFixed32, 0U); +// clang-format on //%PDDM-EXPAND MERGE3_TEST(Sfixed32, 18, Fixed64, 0U) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofSfixed32 = 18; [dst mergeFrom:src]; @@ -566,8 +611,10 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oneofSfixed32, 18); XCTAssertEqual(dst.oneofFixed64, 0U); +// clang-format on //%PDDM-EXPAND MERGE3_TEST(Sfixed64, 19, Sfixed32, 0) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofSfixed64 = 19; [dst mergeFrom:src]; @@ -575,8 +622,10 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oneofSfixed64, 19); XCTAssertEqual(dst.oneofSfixed32, 0); +// clang-format on //%PDDM-EXPAND MERGE3_TEST(Float, 20.0f, Sfixed64, 0) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofFloat = 20.0f; [dst mergeFrom:src]; @@ -584,8 +633,10 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oneofFloat, 20.0f); XCTAssertEqual(dst.oneofSfixed64, 0); +// clang-format on //%PDDM-EXPAND MERGE3_TEST(Double, 21.0, Float, 0.0f) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofDouble = 21.0; [dst mergeFrom:src]; @@ -593,8 +644,10 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oneofDouble, 21.0); XCTAssertEqual(dst.oneofFloat, 0.0f); +// clang-format on //%PDDM-EXPAND MERGE3_TEST(Bool, YES, Double, 0.0) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofBool = YES; [dst mergeFrom:src]; @@ -602,8 +655,10 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oneofBool, YES); XCTAssertEqual(dst.oneofDouble, 0.0); +// clang-format on //%PDDM-EXPAND MERGE3_TEST(Enum, Message3_Enum_Bar, Bool, NO) // This block of code is generated, do not edit it directly. +// clang-format off src.oneofEnum = Message3_Enum_Bar; [dst mergeFrom:src]; @@ -611,6 +666,7 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oneofEnum, Message3_Enum_Bar); XCTAssertEqual(dst.oneofBool, NO); +// clang-format on //%PDDM-EXPAND-END (14 expansions) NSString *oneofStringDefault = @""; @@ -637,7 +693,7 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofMessage); Message3 *mergedSubMessage = [[dst.oneofMessage retain] autorelease]; XCTAssertNotNil(mergedSubMessage); - XCTAssertNotEqual(mergedSubMessage, subMessage); // Pointer comparision. + XCTAssertNotEqual(mergedSubMessage, subMessage); // Pointer comparison. XCTAssertEqualObjects(mergedSubMessage, subMessage); XCTAssertEqualObjects(dst.oneofBytes, oneofBytesDefault); @@ -648,7 +704,7 @@ - (void)testProto3MergeOneof { XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofInt32); XCTAssertNotNil(dst.oneofMessage); XCTAssertNotEqual(dst.oneofMessage, - mergedSubMessage); // Pointer comparision. + mergedSubMessage); // Pointer comparison. // // Test merging in to message when they already had something. @@ -661,9 +717,9 @@ - (void)testProto3MergeOneof { [dst mergeFrom:src]; XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofMessage); // Shouldn't have been a new object. - XCTAssertEqual(dst.oneofMessage, mergedSubMessage); // Pointer comparision. - XCTAssertEqual(dst.oneofMessage.optionalInt32, 777); // Pointer comparision. - XCTAssertEqual(dst.oneofMessage.optionalInt64, 999); // Pointer comparision. + XCTAssertEqual(dst.oneofMessage, mergedSubMessage); // Pointer comparison. + XCTAssertEqual(dst.oneofMessage.optionalInt32, 777); // Pointer comparison. + XCTAssertEqual(dst.oneofMessage.optionalInt64, 999); // Pointer comparison. } #pragma mark - Subset from from map_tests.cc diff --git a/objectivec/Tests/GPBMessageTests+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m index 0058311b3bf09..1dac79754e93e 100644 --- a/objectivec/Tests/GPBMessageTests+Runtime.m +++ b/objectivec/Tests/GPBMessageTests+Runtime.m @@ -212,7 +212,7 @@ - (void)testProto3HasMethodSupport { // Proto3 gets: // Single fields - // - has*/setHas* invalid for primative types. + // - has*/setHas* invalid for primitive types. // - has*/setHas* valid for Message. for (NSString *name in names) { @@ -252,7 +252,7 @@ - (void)testProto3HasMethodSupport { // build the selector, i.e. - repeatedInt32Array_Count SEL countSel = NSSelectorFromString( [NSString stringWithFormat:@"repeated%@Array_Count", name]); - XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@", + XCTAssertTrue([Message3 instancesRespondToSelector:countSel], @"field: %@", name); } @@ -264,12 +264,29 @@ - (void)testProto3HasMethodSupport { NSSelectorFromString([NSString stringWithFormat:@"hasOneof%@", name]); SEL setHasSel = NSSelectorFromString( [NSString stringWithFormat:@"setHasOneof%@:", name]); - XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@", + XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@", name); - XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], + XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel], @"field: %@", name); } + // Single Optional fields + // - has*/setHas* thanks to the optional keyword in proto3, they exist + // for primitive types. + // - has*/setHas* valid for Message. + + for (NSString *name in names) { + // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32: + SEL hasSel = NSSelectorFromString( + [NSString stringWithFormat:@"hasOptional%@", name]); + SEL setHasSel = NSSelectorFromString( + [NSString stringWithFormat:@"setHasOptional%@:", name]); + XCTAssertTrue([Message3Optional instancesRespondToSelector:hasSel], @"field: %@", + name); + XCTAssertTrue([Message3Optional instancesRespondToSelector:setHasSel], + @"field: %@", name); + } + // map<> fields // - no has*/setHas* // - *Count @@ -302,14 +319,14 @@ - (void)testProto3HasMethodSupport { [NSString stringWithFormat:@"hasMap%@", name]); SEL setHasSel = NSSelectorFromString( [NSString stringWithFormat:@"setHasMap%@:", name]); - XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@", + XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@", name); - XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], + XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel], @"field: %@", name); // build the selector, i.e. - mapInt32Int32Count SEL countSel = NSSelectorFromString( [NSString stringWithFormat:@"map%@_Count", name]); - XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@", + XCTAssertTrue([Message3 instancesRespondToSelector:countSel], @"field: %@", name); } } @@ -382,6 +399,7 @@ - (void)testProto2SingleFieldHasBehavior { //%PROTO2_TEST_CLEAR_FIELD_WITH_NIL(Message, [Message2 message]) //%PDDM-EXPAND PROTO2_TEST_HAS_FIELDS() // This block of code is generated, do not edit it directly. +// clang-format off { // optionalInt32 :: 1 Message2 *msg = [[Message2 alloc] init]; @@ -735,6 +753,7 @@ - (void)testProto2SingleFieldHasBehavior { [msg release]; } +// clang-format on //%PDDM-EXPAND-END PROTO2_TEST_HAS_FIELDS() } @@ -796,6 +815,7 @@ - (void)testProto3SingleFieldHasBehavior { //%PROTO3_TEST_CLEAR_FIELD_WITH_NIL(Message, [Message3 message]) //%PDDM-EXPAND PROTO3_TEST_HAS_FIELDS() // This block of code is generated, do not edit it directly. +// clang-format off { // optionalInt32 Message3 *msg = [[Message3 alloc] init]; @@ -995,9 +1015,253 @@ - (void)testProto3SingleFieldHasBehavior { [msg release]; } +// clang-format on //%PDDM-EXPAND-END PROTO3_TEST_HAS_FIELDS() } +- (void)testProto3SingleOptionalFieldHasBehavior { + // + // Setting to any value including the default (0) should result in true. + // + +//%PDDM-DEFINE PROTO3_TEST_OPTIONAL_HAS_FIELD(FIELD, NON_ZERO_VALUE, ZERO_VALUE) +//% { // optional##FIELD +//% Message3Optional *msg = [[Message3Optional alloc] init]; +//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD)); +//% msg.optional##FIELD = NON_ZERO_VALUE; +//% XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD)); +//% msg.hasOptional##FIELD = NO; +//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD)); +//% msg.optional##FIELD = ZERO_VALUE; +//% XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD)); +//% [msg release]; +//% } +//% +//%PDDM-DEFINE PROTO3_TEST_OPTIONAL_HAS_FIELDS() +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Int32, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Int64, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Uint32, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Uint64, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sint32, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sint64, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Fixed32, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Fixed64, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sfixed32, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sfixed64, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Float, 1.0f, 0.0f) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Double, 1.0, 0.0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Bool, YES, NO) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(String, @"foo", @"") +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Bytes, [@"foo" dataUsingEncoding:NSUTF8StringEncoding], [NSData data]) +//% // +//% // Test doesn't apply to optionalMessage (no groups in proto3). +//% // +//% +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Enum, Message3Optional_Enum_Bar, Message3Optional_Enum_Foo) +//%PDDM-EXPAND PROTO3_TEST_OPTIONAL_HAS_FIELDS() +// This block of code is generated, do not edit it directly. +// clang-format off + + { // optionalInt32 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32)); + msg.optionalInt32 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32)); + msg.hasOptionalInt32 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32)); + msg.optionalInt32 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32)); + [msg release]; + } + + { // optionalInt64 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64)); + msg.optionalInt64 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64)); + msg.hasOptionalInt64 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64)); + msg.optionalInt64 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64)); + [msg release]; + } + + { // optionalUint32 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32)); + msg.optionalUint32 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32)); + msg.hasOptionalUint32 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32)); + msg.optionalUint32 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32)); + [msg release]; + } + + { // optionalUint64 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64)); + msg.optionalUint64 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64)); + msg.hasOptionalUint64 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64)); + msg.optionalUint64 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64)); + [msg release]; + } + + { // optionalSint32 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32)); + msg.optionalSint32 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32)); + msg.hasOptionalSint32 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32)); + msg.optionalSint32 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32)); + [msg release]; + } + + { // optionalSint64 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64)); + msg.optionalSint64 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64)); + msg.hasOptionalSint64 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64)); + msg.optionalSint64 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64)); + [msg release]; + } + + { // optionalFixed32 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32)); + msg.optionalFixed32 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32)); + msg.hasOptionalFixed32 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32)); + msg.optionalFixed32 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32)); + [msg release]; + } + + { // optionalFixed64 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64)); + msg.optionalFixed64 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64)); + msg.hasOptionalFixed64 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64)); + msg.optionalFixed64 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64)); + [msg release]; + } + + { // optionalSfixed32 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32)); + msg.optionalSfixed32 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32)); + msg.hasOptionalSfixed32 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32)); + msg.optionalSfixed32 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32)); + [msg release]; + } + + { // optionalSfixed64 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64)); + msg.optionalSfixed64 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64)); + msg.hasOptionalSfixed64 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64)); + msg.optionalSfixed64 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64)); + [msg release]; + } + + { // optionalFloat + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat)); + msg.optionalFloat = 1.0f; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat)); + msg.hasOptionalFloat = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat)); + msg.optionalFloat = 0.0f; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat)); + [msg release]; + } + + { // optionalDouble + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble)); + msg.optionalDouble = 1.0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble)); + msg.hasOptionalDouble = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble)); + msg.optionalDouble = 0.0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble)); + [msg release]; + } + + { // optionalBool + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool)); + msg.optionalBool = YES; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool)); + msg.hasOptionalBool = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool)); + msg.optionalBool = NO; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool)); + [msg release]; + } + + { // optionalString + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString)); + msg.optionalString = @"foo"; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString)); + msg.hasOptionalString = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString)); + msg.optionalString = @""; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString)); + [msg release]; + } + + { // optionalBytes + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes)); + msg.optionalBytes = [@"foo" dataUsingEncoding:NSUTF8StringEncoding]; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes)); + msg.hasOptionalBytes = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes)); + msg.optionalBytes = [NSData data]; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes)); + [msg release]; + } + + // + // Test doesn't apply to optionalMessage (no groups in proto3). + // + + { // optionalEnum + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum)); + msg.optionalEnum = Message3Optional_Enum_Bar; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum)); + msg.hasOptionalEnum = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum)); + msg.optionalEnum = Message3Optional_Enum_Foo; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum)); + [msg release]; + } + +// clang-format on +//%PDDM-EXPAND-END PROTO3_TEST_OPTIONAL_HAS_FIELDS() +} + - (void)testAccessingProto2UnknownEnumValues { Message2 *msg = [[Message2 alloc] init]; @@ -1482,7 +1746,7 @@ - (void)testProto2OneofBasicBehaviors { [msg release]; msg = [[Message2 alloc] init]; - uint32_t values[] = { + int32_t values[] = { Message2_O_OneOfCase_OneofInt32, Message2_O_OneOfCase_OneofInt64, Message2_O_OneOfCase_OneofUint32, @@ -1992,7 +2256,7 @@ - (void)testProto3OneofBasicBehaviors { [msg release]; msg = [[Message3 alloc] init]; - uint32_t values[] = { + int32_t values[] = { Message3_O_OneOfCase_OneofInt32, Message3_O_OneOfCase_OneofInt64, Message3_O_OneOfCase_OneofUint32, @@ -2113,7 +2377,7 @@ - (void)testProto2OneofSetToDefault { Message2 *msg = [[Message2 alloc] init]; - uint32_t values[] = { + int32_t values[] = { Message2_O_OneOfCase_OneofInt32, Message2_O_OneOfCase_OneofInt64, Message2_O_OneOfCase_OneofUint32, @@ -2234,7 +2498,7 @@ - (void)testProto2OneofSetToDefault { - (void)testProto3OneofSetToZero { // Normally setting a proto3 field to the zero value should result in it being - // reset/cleared. But in a oneof, it still gets recored so it can go out + // reset/cleared. But in a oneof, it still gets recorded so it can go out // over the wire and the other side can see what was set in the oneof. NSString *oneofStringDefault = @""; @@ -2242,7 +2506,7 @@ - (void)testProto3OneofSetToZero { Message3 *msg = [[Message3 alloc] init]; - uint32_t values[] = { + int32_t values[] = { Message3_O_OneOfCase_OneofInt32, Message3_O_OneOfCase_OneofInt64, Message3_O_OneOfCase_OneofUint32, @@ -2367,7 +2631,7 @@ - (void)testCopyingMakesUniqueObjects { XCTAssertNotEqual(msg1, msg2); // Ptr compare, new object. XCTAssertEqualObjects(msg1, msg2); // Equal values. - // Pointer comparisions, different objects. + // Pointer comparisons, different objects. XCTAssertNotEqual(msg1.optionalGroup, msg2.optionalGroup); XCTAssertNotEqual(msg1.optionalNestedMessage, msg2.optionalNestedMessage); @@ -2423,7 +2687,7 @@ - (void)testCopyingMapsMakesUniqueObjects { XCTAssertNotEqual(msg1, msg2); // Ptr compare, new object. XCTAssertEqualObjects(msg1, msg2); // Equal values. - // Pointer comparisions, different objects. + // Pointer comparisons, different objects. XCTAssertNotEqual(msg1.mapInt32Int32, msg2.mapInt32Int32); XCTAssertNotEqual(msg1.mapInt64Int64, msg2.mapInt64Int64); XCTAssertNotEqual(msg1.mapUint32Uint32, msg2.mapUint32Uint32); @@ -2491,6 +2755,72 @@ - (void)test_GPBSetMessageMapField { XCTAssertEqualObjects(@"bar", message.mapStringString[@"foo"]); } +- (void)test_StringFieldsCopy { + // ObjC conventions call for NSString properties to be copy, ensure + // that is done correctly and the string isn't simply retained. + + Message2 *msg1 = [Message2 message]; + Message2 *msg2 = [Message2 message]; + + GPBFieldDescriptor *fieldDesc = + [[Message2 descriptor] fieldWithNumber:Message2_FieldNumber_OptionalString]; + NSMutableString *mutableStr = [NSMutableString stringWithString:@"foo"]; + + msg1.optionalString = mutableStr; + GPBSetMessageStringField(msg2, fieldDesc, mutableStr); + + XCTAssertEqualObjects(msg1.optionalString, mutableStr); + XCTAssertEqualObjects(msg1.optionalString, @"foo"); + XCTAssertTrue(msg1.optionalString != mutableStr); // Ptr comparison. + + XCTAssertEqualObjects(msg2.optionalString, mutableStr); + XCTAssertEqualObjects(msg2.optionalString, @"foo"); + XCTAssertTrue(msg2.optionalString != mutableStr); // Ptr comparison. + + [mutableStr appendString:@"bar"]; + + XCTAssertNotEqualObjects(msg1.optionalString, mutableStr); + XCTAssertEqualObjects(msg1.optionalString, @"foo"); + XCTAssertTrue(msg1.optionalString != mutableStr); // Ptr comparison. + + XCTAssertNotEqualObjects(msg2.optionalString, mutableStr); + XCTAssertEqualObjects(msg2.optionalString, @"foo"); + XCTAssertTrue(msg2.optionalString != mutableStr); // Ptr comparison. +} + +- (void)test_BytesFieldsCopy { + // ObjC conventions call for NSData properties to be copy, ensure + // that is done correctly and the data isn't simply retained. + + Message2 *msg1 = [Message2 message]; + Message2 *msg2 = [Message2 message]; + + GPBFieldDescriptor *fieldDesc = + [[Message2 descriptor] fieldWithNumber:Message2_FieldNumber_OptionalBytes]; + NSMutableData *mutableData = [NSMutableData dataWithData:DataFromCStr("abc")]; + + msg1.optionalBytes = mutableData; + GPBSetMessageBytesField(msg2, fieldDesc, mutableData); + + XCTAssertEqualObjects(msg1.optionalBytes, mutableData); + XCTAssertEqualObjects(msg1.optionalBytes, DataFromCStr("abc")); + XCTAssertTrue(msg1.optionalBytes != mutableData); // Ptr comparison. + + XCTAssertEqualObjects(msg2.optionalBytes, mutableData); + XCTAssertEqualObjects(msg2.optionalBytes, DataFromCStr("abc")); + XCTAssertTrue(msg2.optionalBytes != mutableData); // Ptr comparison. + + [mutableData appendData:DataFromCStr("123")]; + + XCTAssertNotEqualObjects(msg1.optionalBytes, mutableData); + XCTAssertEqualObjects(msg1.optionalBytes, DataFromCStr("abc")); + XCTAssertTrue(msg1.optionalBytes != mutableData); // Ptr comparison. + + XCTAssertNotEqualObjects(msg2.optionalBytes, mutableData); + XCTAssertEqualObjects(msg2.optionalBytes, DataFromCStr("abc")); + XCTAssertTrue(msg2.optionalBytes != mutableData); // Ptr comparison. +} + #pragma mark - Subset from from map_tests.cc // TEST(GeneratedMapFieldTest, IsInitialized) diff --git a/objectivec/Tests/GPBMessageTests+Serialization.m b/objectivec/Tests/GPBMessageTests+Serialization.m index 4a4c54476a750..6f20797aeee72 100644 --- a/objectivec/Tests/GPBMessageTests+Serialization.m +++ b/objectivec/Tests/GPBMessageTests+Serialization.m @@ -42,10 +42,6 @@ #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto3.pbobjc.h" -static NSData *DataFromCStr(const char *str) { - return [NSData dataWithBytes:str length:strlen(str)]; -} - @interface MessageSerializationTests : GPBTestCase @end @@ -113,6 +109,317 @@ - (void)testProto3SerializationHandlingDefaults { [msg release]; } +- (void)testProto3SerializationHandlingOptionals { + // + // Proto3 optionals should be just like proto2, zero values also get serialized. + // + +//%PDDM-DEFINE PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(FIELD, ZERO_VALUE, EXPECTED_LEN) +//% { // optional##FIELD +//% Message3Optional *msg = [[Message3Optional alloc] init]; +//% NSData *data = [msg data]; +//% XCTAssertEqual([data length], 0U); +//% msg.optional##FIELD = ZERO_VALUE; +//% data = [msg data]; +//% XCTAssertEqual(data.length, EXPECTED_LEN); +//% NSError *err = nil; +//% Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; +//% XCTAssertNotNil(msg2); +//% XCTAssertNil(err); +//% XCTAssertTrue(msg2.hasOptional##FIELD); +//% XCTAssertEqualObjects(msg, msg2); +//% [msg release]; +//% } +//% +//%PDDM-DEFINE PROTO3_TEST_SERIALIZE_OPTIONAL_FIELDS() +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Int32, 0, 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Int64, 0, 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Uint32, 0, 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Uint64, 0, 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sint32, 0, 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sint64, 0, 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Fixed32, 0, 5) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Fixed64, 0, 9) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sfixed32, 0, 5) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sfixed64, 0, 9) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Float, 0.0f, 5) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Double, 0.0, 9) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Bool, NO, 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(String, @"", 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Bytes, [NSData data], 2) +//% // +//% // Test doesn't apply to optionalMessage (no groups in proto3). +//% // +//% +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Enum, Message3Optional_Enum_Foo, 3) +//%PDDM-EXPAND PROTO3_TEST_SERIALIZE_OPTIONAL_FIELDS() +// This block of code is generated, do not edit it directly. +// clang-format off + + { // optionalInt32 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalInt32 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalInt32); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalInt64 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalInt64 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalInt64); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalUint32 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalUint32 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalUint32); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalUint64 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalUint64 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalUint64); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalSint32 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalSint32 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalSint32); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalSint64 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalSint64 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalSint64); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalFixed32 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalFixed32 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 5); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalFixed32); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalFixed64 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalFixed64 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 9); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalFixed64); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalSfixed32 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalSfixed32 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 5); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalSfixed32); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalSfixed64 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalSfixed64 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 9); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalSfixed64); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalFloat + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalFloat = 0.0f; + data = [msg data]; + XCTAssertEqual(data.length, 5); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalFloat); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalDouble + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalDouble = 0.0; + data = [msg data]; + XCTAssertEqual(data.length, 9); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalDouble); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalBool + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalBool = NO; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalBool); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalString + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalString = @""; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalString); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalBytes + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalBytes = [NSData data]; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalBytes); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + // + // Test doesn't apply to optionalMessage (no groups in proto3). + // + + { // optionalEnum + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalEnum = Message3Optional_Enum_Foo; + data = [msg data]; + XCTAssertEqual(data.length, 3); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalEnum); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + +// clang-format on +//%PDDM-EXPAND-END PROTO3_TEST_SERIALIZE_OPTIONAL_FIELDS() +} + - (void)testProto2UnknownEnumToUnknownField { Message3 *orig = [[Message3 alloc] init]; @@ -277,6 +584,7 @@ - (void)testProto3UnknownEnumPreserving { //% //%PDDM-EXPAND TEST_ROUNDTRIP_ONEOFS(2, NO) // This block of code is generated, do not edit it directly. +// clang-format off - (void)testProto2RoundTripOneof { @@ -507,8 +815,10 @@ - (void)testProto2RoundTripOneof { [subMessage release]; } +// clang-format on //%PDDM-EXPAND TEST_ROUNDTRIP_ONEOFS(3, YES) // This block of code is generated, do not edit it directly. +// clang-format off - (void)testProto3RoundTripOneof { @@ -725,6 +1035,7 @@ - (void)testProto3RoundTripOneof { [subMessage release]; } +// clang-format on //%PDDM-EXPAND-END (2 expansions) - (void)testPackedUnpackedMessageParsing { @@ -980,6 +1291,16 @@ - (void)testErrorRecursionDepthReached { XCTAssertEqual(error.code, GPBCodedInputStreamErrorRecursionDepthExceeded); } +- (void)testParseDelimitedDataWithNegativeSize { + NSData *data = DataFromCStr("\xFF\xFF\xFF\xFF\x0F"); + GPBCodedInputStream *input = [GPBCodedInputStream streamWithData:data]; + NSError *error; + [GPBMessage parseDelimitedFromCodedInputStream:input + extensionRegistry:nil + error:&error]; + XCTAssertNil(error); +} + #ifdef DEBUG - (void)testErrorMissingRequiredField { NSData *data = DataFromCStr(""); @@ -1108,10 +1429,10 @@ - (void)testMap_CorruptedWireFormat { - (void)testMap_Proto2UnknownEnum { TestEnumMapPlusExtra *orig = [[TestEnumMapPlusExtra alloc] init]; - orig.knownMapField = [GPBInt32EnumDictionary - dictionaryWithValidationFunction:Proto2MapEnumPlusExtra_IsValidValue]; - orig.unknownMapField = [GPBInt32EnumDictionary - dictionaryWithValidationFunction:Proto2MapEnumPlusExtra_IsValidValue]; + orig.knownMapField = [[[GPBInt32EnumDictionary alloc] + initWithValidationFunction:Proto2MapEnumPlusExtra_IsValidValue] autorelease]; + orig.unknownMapField = [[[GPBInt32EnumDictionary alloc] + initWithValidationFunction:Proto2MapEnumPlusExtra_IsValidValue] autorelease]; [orig.knownMapField setEnum:Proto2MapEnumPlusExtra_EProto2MapEnumFoo forKey:0]; [orig.unknownMapField setEnum:Proto2MapEnumPlusExtra_EProto2MapEnumExtra diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m index c15535c50804e..ea224fa6138bf 100644 --- a/objectivec/Tests/GPBMessageTests.m +++ b/objectivec/Tests/GPBMessageTests.m @@ -40,6 +40,7 @@ #import "GPBUnknownFieldSet_PackagePrivate.h" #import "google/protobuf/Unittest.pbobjc.h" #import "google/protobuf/UnittestObjc.pbobjc.h" +#import "google/protobuf/UnittestObjcOptions.pbobjc.h" @interface MessageTests : GPBTestCase @end @@ -337,14 +338,38 @@ - (void)testParseUninitialized { } - (void)testCoding { + GPBMessage *original = [self mergeResult]; NSData *data = - [NSKeyedArchiver archivedDataWithRootObject:[self mergeResult]]; + [NSKeyedArchiver archivedDataWithRootObject:original]; id unarchivedObject = [NSKeyedUnarchiver unarchiveObjectWithData:data]; - XCTAssertEqualObjects(unarchivedObject, [self mergeResult]); + XCTAssertEqualObjects(unarchivedObject, original); // Intentionally doing a pointer comparison. - XCTAssertNotEqual(unarchivedObject, [self mergeResult]); + XCTAssertNotEqual(unarchivedObject, original); +} + +- (void)testSecureCoding { + GPBMessage *original = [self mergeResult]; + + NSString *key = @"testing123"; + + NSMutableData *data = [NSMutableData data]; + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; + [archiver setRequiresSecureCoding:YES]; + [archiver encodeObject:original forKey:key]; + [archiver finishEncoding]; + + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; + [unarchiver setRequiresSecureCoding:YES]; + id unarchivedObject = [unarchiver decodeObjectOfClass:[GPBMessage class] + forKey:key]; + [unarchiver finishDecoding]; + + XCTAssertEqualObjects(unarchivedObject, original); + + // Intentionally doing a pointer comparison. + XCTAssertNotEqual(unarchivedObject, original); } - (void)testObjectReset { @@ -1106,10 +1131,10 @@ - (void)testReplaceAutocreatedArray { XCTAssertNotNil(message.a.iArray); XCTAssertFalse([message hasA]); GPBInt32Array *iArray = [message.a.iArray retain]; - XCTAssertEqual(iArray->_autocreator, message.a); // Pointer comparision + XCTAssertEqual(iArray->_autocreator, message.a); // Pointer comparison message.a.iArray = [GPBInt32Array arrayWithValue:1]; XCTAssertTrue([message hasA]); - XCTAssertNotEqual(message.a.iArray, iArray); // Pointer comparision + XCTAssertNotEqual(message.a.iArray, iArray); // Pointer comparison XCTAssertNil(iArray->_autocreator); [iArray release]; } @@ -1123,10 +1148,10 @@ - (void)testReplaceAutocreatedArray { GPBAutocreatedArray *strArray = (GPBAutocreatedArray *)[message.a.strArray retain]; XCTAssertTrue([strArray isKindOfClass:[GPBAutocreatedArray class]]); - XCTAssertEqual(strArray->_autocreator, message.a); // Pointer comparision + XCTAssertEqual(strArray->_autocreator, message.a); // Pointer comparison message.a.strArray = [NSMutableArray arrayWithObject:@"foo"]; XCTAssertTrue([message hasA]); - XCTAssertNotEqual(message.a.strArray, strArray); // Pointer comparision + XCTAssertNotEqual(message.a.strArray, strArray); // Pointer comparison XCTAssertNil(strArray->_autocreator); [strArray release]; } @@ -1238,7 +1263,8 @@ - (void)testAutocreatedMapCopy { // with different objects that are equal). TestRecursiveMessageWithRepeatedField *message3 = [TestRecursiveMessageWithRepeatedField message]; - message3.iToI = [GPBInt32Int32Dictionary dictionaryWithInt32:10 forKey:20]; + message3.iToI = [[[GPBInt32Int32Dictionary alloc] init] autorelease]; + [message3.iToI setInt32:10 forKey:20]; message3.strToStr = [NSMutableDictionary dictionaryWithObject:@"abc" forKey:@"123"]; XCTAssertNotNil(message.iToI); @@ -1322,10 +1348,11 @@ - (void)testReplaceAutocreatedMap { XCTAssertNotNil(message.a.iToI); XCTAssertFalse([message hasA]); GPBInt32Int32Dictionary *iToI = [message.a.iToI retain]; - XCTAssertEqual(iToI->_autocreator, message.a); // Pointer comparision - message.a.iToI = [GPBInt32Int32Dictionary dictionaryWithInt32:6 forKey:7]; + XCTAssertEqual(iToI->_autocreator, message.a); // Pointer comparison + message.a.iToI = [[[GPBInt32Int32Dictionary alloc] init] autorelease]; + [message.a.iToI setInt32:6 forKey:7]; XCTAssertTrue([message hasA]); - XCTAssertNotEqual(message.a.iToI, iToI); // Pointer comparision + XCTAssertNotEqual(message.a.iToI, iToI); // Pointer comparison XCTAssertNil(iToI->_autocreator); [iToI release]; } @@ -1339,11 +1366,11 @@ - (void)testReplaceAutocreatedMap { GPBAutocreatedDictionary *strToStr = (GPBAutocreatedDictionary *)[message.a.strToStr retain]; XCTAssertTrue([strToStr isKindOfClass:[GPBAutocreatedDictionary class]]); - XCTAssertEqual(strToStr->_autocreator, message.a); // Pointer comparision + XCTAssertEqual(strToStr->_autocreator, message.a); // Pointer comparison message.a.strToStr = [NSMutableDictionary dictionaryWithObject:@"abc" forKey:@"def"]; XCTAssertTrue([message hasA]); - XCTAssertNotEqual(message.a.strToStr, strToStr); // Pointer comparision + XCTAssertNotEqual(message.a.strToStr, strToStr); // Pointer comparison XCTAssertNil(strToStr->_autocreator); [strToStr release]; } @@ -1891,7 +1918,7 @@ - (void)testEnumNaming { aTime = Time_SomethingElse; Time_IsValidValue(aTime); - // This block confirms the names in the decriptors is what we wanted. + // This block confirms the names in the descriptors is what we wanted. GPBEnumDescriptor *descriptor; NSString *valueName; @@ -1978,8 +2005,53 @@ - (void)testNegativeEnums { EnumTestMsg_MyEnum_NegTwo); } +- (void)testReservedWordNaming { + // objectivec_helpers.cc has some special handing to make sure that + // some "reserved" objc names get renamed in a way so they + // don't conflict. + // + // This "test" confirms that the expected names are generated, + // otherwise the test itself will fail to compile. + self_Class *msg = [self_Class message]; + + // Some ObjC/C/C++ keywords. + msg.className_p = msg.hasClassName_p; + msg.cmd = msg.hasCmd; + msg.nullable_p = msg.hasNullable_p; + msg.typeof_p = msg.hasTypeof_p; + msg.instancetype_p = msg.hasInstancetype_p; + msg.nil_p = msg.hasNil_p; + msg.instancetype_p = msg.hasInstancetype_p; + msg.public_p = msg.hasPublic_p; + + // Some that would override NSObject methods + msg.camltype = msg.hasCamltype; + msg.isNsdictionary = msg.hasIsNsdictionary; + msg.dealloc_p = msg.hasDealloc_p; + msg.zone_p = msg.hasZone_p; + msg.accessibilityLabel_p = msg.hasAccessibilityLabel_p; + + // Some that we shouldn't need to handle. + msg.atomic = msg.hasAtomic; + msg.nonatomic = msg.hasNonatomic; + msg.strong = msg.hasStrong; + msg.nullResettable = msg.hasNullResettable; + + // Some that would override GPBMessage methods + msg.clear_p = msg.hasClear_p; + msg.data_p = msg.hasData_p; + + // Some MacTypes + msg.fixed = msg.hasFixed; + msg.style = msg.hasStyle; + + // Some C Identifiers + msg.generic = msg.hasGeneric; + msg.block = msg.hasBlock; +} + - (void)testOneBasedEnumHolder { - // Test case for https://github.com/google/protobuf/issues/1453 + // Test case for https://github.com/protocolbuffers/protobuf/issues/1453 // Message with no explicit defaults, but a non zero default for an enum. MessageWithOneBasedEnum *enumMsg = [MessageWithOneBasedEnum message]; XCTAssertEqual(enumMsg.enumField, MessageWithOneBasedEnum_OneBasedEnum_One); @@ -2050,4 +2122,89 @@ - (void)testBoolOffsetUsage { XCTAssertEqual([msg1 hash], [msg1Prime hash]); } +- (void)testCopyingMapFields { + TestMessageOfMaps *msg = [TestMessageOfMaps message]; + + msg.strToStr[@"foo"] = @"bar"; + + [msg.strToInt setInt32:1 forKey:@"mumble"]; + [msg.intToStr setObject:@"wee" forKey:42]; + [msg.intToInt setInt32:123 forKey:321]; + + [msg.strToBool setBool:YES forKey:@"one"]; + [msg.boolToStr setObject:@"something" forKey:YES]; + [msg.boolToBool setBool:YES forKey:NO]; + + [msg.intToBool setBool:YES forKey:13]; + [msg.boolToInt setInt32:111 forKey:NO]; + + TestAllTypes *subMsg1 = [TestAllTypes message]; + subMsg1.optionalInt32 = 1; + TestAllTypes *subMsg2 = [TestAllTypes message]; + subMsg1.optionalInt32 = 2; + TestAllTypes *subMsg3 = [TestAllTypes message]; + subMsg1.optionalInt32 = 3; + + msg.strToMsg[@"baz"] = subMsg1; + [msg.intToMsg setObject:subMsg2 forKey:222]; + [msg.boolToMsg setObject:subMsg3 forKey:YES]; + + TestMessageOfMaps *msg2 = [[msg copy] autorelease]; + XCTAssertNotNil(msg2); + XCTAssertEqualObjects(msg2, msg); + XCTAssertTrue(msg2 != msg); // ptr compare + XCTAssertTrue(msg.strToStr != msg2.strToStr); // ptr compare + XCTAssertTrue(msg.intToStr != msg2.intToStr); // ptr compare + XCTAssertTrue(msg.intToInt != msg2.intToInt); // ptr compare + XCTAssertTrue(msg.strToBool != msg2.strToBool); // ptr compare + XCTAssertTrue(msg.boolToStr != msg2.boolToStr); // ptr compare + XCTAssertTrue(msg.boolToBool != msg2.boolToBool); // ptr compare + XCTAssertTrue(msg.intToBool != msg2.intToBool); // ptr compare + XCTAssertTrue(msg.boolToInt != msg2.boolToInt); // ptr compare + XCTAssertTrue(msg.strToMsg != msg2.strToMsg); // ptr compare + XCTAssertTrue(msg.intToMsg != msg2.intToMsg); // ptr compare + XCTAssertTrue(msg.boolToMsg != msg2.boolToMsg); // ptr compare + + XCTAssertTrue(msg.strToMsg[@"baz"] != msg2.strToMsg[@"baz"]); // ptr compare + XCTAssertEqualObjects(msg.strToMsg[@"baz"], msg2.strToMsg[@"baz"]); + XCTAssertTrue([msg.intToMsg objectForKey:222] != [msg2.intToMsg objectForKey:222]); // ptr compare + XCTAssertEqualObjects([msg.intToMsg objectForKey:222], [msg2.intToMsg objectForKey:222]); + XCTAssertTrue([msg.boolToMsg objectForKey:YES] != [msg2.boolToMsg objectForKey:YES]); // ptr compare + XCTAssertEqualObjects([msg.boolToMsg objectForKey:YES], [msg2.boolToMsg objectForKey:YES]); +} + +- (void)testPrefixedNames { + // The fact that this compiles is sufficient as a test. + // The assertions are just there to avoid "not-used" warnings. + + // Verify that enum types and values get the prefix. + GPBTESTTestObjcProtoPrefixEnum value = GPBTESTTestObjcProtoPrefixEnum_Value; + XCTAssertNotEqual(value, 0); + + // Verify that roots get the prefix. + GPBTESTUnittestObjcOptionsRoot *root = nil; + XCTAssertNil(root); + + // Verify that messages that don't already have the prefix get a prefix. + GPBTESTTestObjcProtoPrefixMessage *prefixedMessage = nil; + XCTAssertNil(prefixedMessage); + + // Verify that messages that already have a prefix aren't prefixed twice. + GPBTESTTestHasAPrefixMessage *alreadyPrefixedMessage = nil; + XCTAssertNil(alreadyPrefixedMessage); + + // Verify that enums that already have a prefix aren't prefixed twice. + GPBTESTTestHasAPrefixEnum prefixedValue = GPBTESTTestHasAPrefixEnum_ValueB; + XCTAssertNotEqual(prefixedValue, 0); + + // Verify that classes named the same as prefixes are prefixed. + GPBTESTGPBTEST *prefixMessage = nil; + XCTAssertNil(prefixMessage); + + // Verify that classes that have the prefix followed by a lowercase + // letter DO get the prefix. + GPBTESTGPBTESTshouldGetAPrefixMessage *shouldGetAPrefixMessage = nil; + XCTAssertNil(shouldGetAPrefixMessage); +} + @end diff --git a/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm b/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm index 9ba8fd0b90642..fb67495903dbe 100644 --- a/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm +++ b/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm @@ -35,7 +35,7 @@ // // This is just a compile test (here to make sure things never regress). // -// Objective C++ can run into issues with how the NS_ENUM/CF_ENUM declartion +// Objective C++ can run into issues with how the NS_ENUM/CF_ENUM declaration // works because of the C++ spec being used for that compilation unit. So // the fact that these imports all work without errors/warning means things // are still good. diff --git a/objectivec/Tests/GPBSwiftTests.swift b/objectivec/Tests/GPBSwiftTests.swift index 9d8a0faeb0a40..03d7510680bcc 100644 --- a/objectivec/Tests/GPBSwiftTests.swift +++ b/objectivec/Tests/GPBSwiftTests.swift @@ -276,7 +276,7 @@ class GPBBridgeTests: XCTestCase { msg5.optionalInt32 = 123 msg.optional = msg5 XCTAssertTrue(msg.hasOptionalMessage) - // Modifing the autocreated doesn't replaced the explicit set one. + // Modifying the autocreated doesn't replaced the explicit set one. autoCreated?.optionalInt32 = 456 XCTAssertTrue(msg.hasOptionalMessage) XCTAssertTrue(msg.optional === msg5) @@ -355,7 +355,7 @@ class GPBBridgeTests: XCTestCase { msg.oneof = nil XCTAssertEqual(msg.oneof.optionalInt32, Int32(0)) // Default XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.gpbUnsetOneOfCase) -} + } func testProto3OneOfSupport() { let msg = Message3() diff --git a/objectivec/Tests/GPBTestUtilities.h b/objectivec/Tests/GPBTestUtilities.h index 44c808449dff3..780184b07c8d7 100644 --- a/objectivec/Tests/GPBTestUtilities.h +++ b/objectivec/Tests/GPBTestUtilities.h @@ -39,6 +39,9 @@ @class TestUnpackedExtensions; @class GPBExtensionRegistry; +static inline NSData *DataFromCStr(const char *str) { + return [NSData dataWithBytes:str length:strlen(str)]; +} // Helper for uses of C arrays in tests cases. #ifndef GPBARRAYSIZE diff --git a/objectivec/Tests/GPBTestUtilities.m b/objectivec/Tests/GPBTestUtilities.m index ebccaac9c7cfc..48d75e794ab83 100644 --- a/objectivec/Tests/GPBTestUtilities.m +++ b/objectivec/Tests/GPBTestUtilities.m @@ -85,7 +85,7 @@ - (NSData *)getDataFileNamed:(NSString *)name NSLog(@"Wrote data file to %@", path); #else // Kill off the unused variable warning. - dataToWrite = dataToWrite; + (void)dataToWrite; #endif return data; } @@ -779,7 +779,7 @@ - (void)setAllFields:(TestAllTypes *)message repeatedCount:(uint32_t)count { [message.repeatedSfixed64Array addValue:210 + i * 100]; [message.repeatedFloatArray addValue:211 + i * 100]; [message.repeatedDoubleArray addValue:212 + i * 100]; - [message.repeatedBoolArray addValue:(i % 2)]; + [message.repeatedBoolArray addValue:(BOOL)(i % 2)]; NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100]; [message.repeatedStringArray addObject:string]; [string release]; diff --git a/objectivec/Tests/GPBUnittestProtos.m b/objectivec/Tests/GPBUnittestProtos.m index 756bd99ef77d2..1c6eddfbacfb5 100644 --- a/objectivec/Tests/GPBUnittestProtos.m +++ b/objectivec/Tests/GPBUnittestProtos.m @@ -56,8 +56,6 @@ #import "google/protobuf/UnittestLite.pbobjc.m" #import "google/protobuf/UnittestMset.pbobjc.m" #import "google/protobuf/UnittestMsetWireFormat.pbobjc.m" -#import "google/protobuf/UnittestNoArena.pbobjc.m" -#import "google/protobuf/UnittestNoArenaImport.pbobjc.m" #import "google/protobuf/UnittestNoGenericServices.pbobjc.m" #import "google/protobuf/UnittestObjc.pbobjc.m" #import "google/protobuf/UnittestObjcStartup.pbobjc.m" diff --git a/objectivec/Tests/GPBUnknownFieldSetTest.m b/objectivec/Tests/GPBUnknownFieldSetTest.m index b2b5b21e6175a..5fa60b2cd8fd9 100644 --- a/objectivec/Tests/GPBUnknownFieldSetTest.m +++ b/objectivec/Tests/GPBUnknownFieldSetTest.m @@ -60,6 +60,95 @@ - (void)setUp { unknownFields_ = emptyMessage_.unknownFields; } +- (void)testInvalidFieldNumber { + GPBUnknownFieldSet *set = [[[GPBUnknownFieldSet alloc] init] autorelease]; + GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:0] autorelease]; + XCTAssertThrowsSpecificNamed([set addField:field], NSException, NSInvalidArgumentException); +} + +- (void)testEqualityAndHash { + // Empty + + GPBUnknownFieldSet *set1 = [[[GPBUnknownFieldSet alloc] init] autorelease]; + XCTAssertTrue([set1 isEqual:set1]); + XCTAssertFalse([set1 isEqual:@"foo"]); + GPBUnknownFieldSet *set2 = [[[GPBUnknownFieldSet alloc] init] autorelease]; + XCTAssertEqualObjects(set1, set2); + XCTAssertEqual([set1 hash], [set2 hash]); + + // Varint + + GPBUnknownField* field1 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; + [field1 addVarint:1]; + [set1 addField:field1]; + XCTAssertNotEqualObjects(set1, set2); + GPBUnknownField* field2 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; + [field2 addVarint:1]; + [set2 addField:field2]; + XCTAssertEqualObjects(set1, set2); + XCTAssertEqual([set1 hash], [set2 hash]); + + // Fixed32 + + field1 = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; + [field1 addFixed32:2]; + [set1 addField:field1]; + XCTAssertNotEqualObjects(set1, set2); + field2 = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; + [field2 addFixed32:2]; + [set2 addField:field2]; + XCTAssertEqualObjects(set1, set2); + XCTAssertEqual([set1 hash], [set2 hash]); + + // Fixed64 + + field1 = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; + [field1 addFixed64:3]; + [set1 addField:field1]; + XCTAssertNotEqualObjects(set1, set2); + field2 = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; + [field2 addFixed64:3]; + [set2 addField:field2]; + XCTAssertEqualObjects(set1, set2); + XCTAssertEqual([set1 hash], [set2 hash]); + + // LengthDelimited + + field1 = [[[GPBUnknownField alloc] initWithNumber:4] autorelease]; + [field1 addLengthDelimited:DataFromCStr("foo")]; + [set1 addField:field1]; + XCTAssertNotEqualObjects(set1, set2); + field2 = [[[GPBUnknownField alloc] initWithNumber:4] autorelease]; + [field2 addLengthDelimited:DataFromCStr("foo")]; + [set2 addField:field2]; + XCTAssertEqualObjects(set1, set2); + XCTAssertEqual([set1 hash], [set2 hash]); + + // Group + + GPBUnknownFieldSet *group1 = [[[GPBUnknownFieldSet alloc] init] autorelease]; + GPBUnknownField* fieldGroup1 = [[[GPBUnknownField alloc] initWithNumber:10] autorelease]; + [fieldGroup1 addVarint:1]; + [group1 addField:fieldGroup1]; + GPBUnknownFieldSet *group2 = [[[GPBUnknownFieldSet alloc] init] autorelease]; + GPBUnknownField* fieldGroup2 = [[[GPBUnknownField alloc] initWithNumber:10] autorelease]; + [fieldGroup2 addVarint:1]; + [group2 addField:fieldGroup2]; + + field1 = [[[GPBUnknownField alloc] initWithNumber:5] autorelease]; + [field1 addGroup:group1]; + [set1 addField:field1]; + XCTAssertNotEqualObjects(set1, set2); + field2 = [[[GPBUnknownField alloc] initWithNumber:5] autorelease]; + [field2 addGroup:group2]; + [set2 addField:field2]; + XCTAssertEqualObjects(set1, set2); + XCTAssertEqual([set1 hash], [set2 hash]); + + // Exercise description for completeness. + XCTAssertTrue(set1.description.length > 10); +} + // Constructs a protocol buffer which contains fields with all the same // numbers as allFieldsData except that each field is some other wire // type. @@ -67,25 +156,34 @@ - (NSData*)getBizarroData { GPBUnknownFieldSet* bizarroFields = [[[GPBUnknownFieldSet alloc] init] autorelease]; NSUInteger count = [unknownFields_ countOfFields]; - int32_t tags[count]; - [unknownFields_ getTags:tags]; - for (NSUInteger i = 0; i < count; ++i) { - int32_t tag = tags[i]; - GPBUnknownField* field = [unknownFields_ getField:tag]; - if (field.varintList.count == 0) { - // Original field is not a varint, so use a varint. - GPBUnknownField* varintField = - [[[GPBUnknownField alloc] initWithNumber:tag] autorelease]; - [varintField addVarint:1]; - [bizarroFields addField:varintField]; - } else { - // Original field *is* a varint, so use something else. - GPBUnknownField* fixed32Field = - [[[GPBUnknownField alloc] initWithNumber:tag] autorelease]; - [fixed32Field addFixed32:1]; - [bizarroFields addField:fixed32Field]; + int32_t *tags = malloc(count * sizeof(int32_t)); + if (!tags) { + XCTFail(@"Failed to make scratch buffer for testing"); + return [NSData data]; + } + @try { + [unknownFields_ getTags:tags]; + for (NSUInteger i = 0; i < count; ++i) { + int32_t tag = tags[i]; + GPBUnknownField* field = [unknownFields_ getField:tag]; + if (field.varintList.count == 0) { + // Original field is not a varint, so use a varint. + GPBUnknownField* varintField = + [[[GPBUnknownField alloc] initWithNumber:tag] autorelease]; + [varintField addVarint:1]; + [bizarroFields addField:varintField]; + } else { + // Original field *is* a varint, so use something else. + GPBUnknownField* fixed32Field = + [[[GPBUnknownField alloc] initWithNumber:tag] autorelease]; + [fixed32Field addFixed32:1]; + [bizarroFields addField:fixed32Field]; + } } } + @finally { + free(tags); + } return [bizarroFields data]; } @@ -112,6 +210,24 @@ - (void)testMergeFrom { field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; [field addVarint:4]; [set1 addField:field]; + field = [[[GPBUnknownField alloc] initWithNumber:4] autorelease]; + [field addFixed32:6]; + [set1 addField:field]; + field = [[[GPBUnknownField alloc] initWithNumber:5] autorelease]; + [field addFixed64:20]; + [set1 addField:field]; + field = [[[GPBUnknownField alloc] initWithNumber:10] autorelease]; + [field addLengthDelimited:DataFromCStr("data1")]; + [set1 addField:field]; + + GPBUnknownFieldSet *group1 = [[[GPBUnknownFieldSet alloc] init] autorelease]; + GPBUnknownField* fieldGroup1 = [[[GPBUnknownField alloc] initWithNumber:200] autorelease]; + [fieldGroup1 addVarint:100]; + [group1 addField:fieldGroup1]; + + field = [[[GPBUnknownField alloc] initWithNumber:11] autorelease]; + [field addGroup:group1]; + [set1 addField:field]; GPBUnknownFieldSet* set2 = [[[GPBUnknownFieldSet alloc] init] autorelease]; field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; @@ -120,22 +236,63 @@ - (void)testMergeFrom { field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; [field addVarint:3]; [set2 addField:field]; + field = [[[GPBUnknownField alloc] initWithNumber:4] autorelease]; + [field addFixed32:7]; + [set2 addField:field]; + field = [[[GPBUnknownField alloc] initWithNumber:5] autorelease]; + [field addFixed64:30]; + [set2 addField:field]; + field = [[[GPBUnknownField alloc] initWithNumber:10] autorelease]; + [field addLengthDelimited:DataFromCStr("data2")]; + [set2 addField:field]; + + GPBUnknownFieldSet *group2 = [[[GPBUnknownFieldSet alloc] init] autorelease]; + GPBUnknownField* fieldGroup2 = [[[GPBUnknownField alloc] initWithNumber:201] autorelease]; + [fieldGroup2 addVarint:99]; + [group2 addField:fieldGroup2]; + + field = [[[GPBUnknownField alloc] initWithNumber:11] autorelease]; + [field addGroup:group2]; + [set2 addField:field]; GPBUnknownFieldSet* set3 = [[[GPBUnknownFieldSet alloc] init] autorelease]; field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; [field addVarint:1]; [set3 addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; - [field addVarint:4]; - [set3 addField:field]; - - GPBUnknownFieldSet* set4 = [[[GPBUnknownFieldSet alloc] init] autorelease]; field = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; [field addVarint:2]; - [set4 addField:field]; + [set3 addField:field]; field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; + [field addVarint:4]; + [set3 addField:field]; [field addVarint:3]; - [set4 addField:field]; + [set3 addField:field]; + field = [[[GPBUnknownField alloc] initWithNumber:4] autorelease]; + [field addFixed32:6]; + [field addFixed32:7]; + [set3 addField:field]; + field = [[[GPBUnknownField alloc] initWithNumber:5] autorelease]; + [field addFixed64:20]; + [field addFixed64:30]; + [set3 addField:field]; + field = [[[GPBUnknownField alloc] initWithNumber:10] autorelease]; + [field addLengthDelimited:DataFromCStr("data1")]; + [field addLengthDelimited:DataFromCStr("data2")]; + [set3 addField:field]; + + GPBUnknownFieldSet *group3a = [[[GPBUnknownFieldSet alloc] init] autorelease]; + GPBUnknownField* fieldGroup3a1 = [[[GPBUnknownField alloc] initWithNumber:200] autorelease]; + [fieldGroup3a1 addVarint:100]; + [group3a addField:fieldGroup3a1]; + GPBUnknownFieldSet *group3b = [[[GPBUnknownFieldSet alloc] init] autorelease]; + GPBUnknownField* fieldGroup3b2 = [[[GPBUnknownField alloc] initWithNumber:201] autorelease]; + [fieldGroup3b2 addVarint:99]; + [group3b addField:fieldGroup3b2]; + + field = [[[GPBUnknownField alloc] initWithNumber:11] autorelease]; + [field addGroup:group1]; + [field addGroup:group3b]; + [set3 addField:field]; TestEmptyMessage* source1 = [TestEmptyMessage message]; [source1 setUnknownFields:set1]; @@ -143,8 +300,6 @@ - (void)testMergeFrom { [source2 setUnknownFields:set2]; TestEmptyMessage* source3 = [TestEmptyMessage message]; [source3 setUnknownFields:set3]; - TestEmptyMessage* source4 = [TestEmptyMessage message]; - [source4 setUnknownFields:set4]; TestEmptyMessage* destination1 = [TestEmptyMessage message]; [destination1 mergeFrom:source1]; @@ -152,9 +307,10 @@ - (void)testMergeFrom { TestEmptyMessage* destination2 = [TestEmptyMessage message]; [destination2 mergeFrom:source3]; - [destination2 mergeFrom:source4]; XCTAssertEqualObjects(destination1.data, destination2.data); + XCTAssertEqualObjects(destination1.data, source3.data); + XCTAssertEqualObjects(destination2.data, source3.data); } - (void)testClearMessage { @@ -240,6 +396,107 @@ - (void)testLargeVarint { XCTAssertEqual(0x7FFFFFFFFFFFFFFFULL, [field2.varintList valueAtIndex:0]); } +#pragma mark - Field tests +// Some tests directly on fields since the dictionary in FieldSet can gate +// testing some of these. + +- (void)testFieldEqualityAndHash { + GPBUnknownField* field1 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; + XCTAssertTrue([field1 isEqual:field1]); + XCTAssertFalse([field1 isEqual:@"foo"]); + GPBUnknownField* field2 = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; + XCTAssertNotEqualObjects(field1, field2); + + field2 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; + XCTAssertEqualObjects(field1, field2); + XCTAssertEqual([field1 hash], [field2 hash]); + + // Varint + + [field1 addVarint:10]; + XCTAssertNotEqualObjects(field1, field2); + [field2 addVarint:10]; + XCTAssertEqualObjects(field1, field2); + XCTAssertEqual([field1 hash], [field2 hash]); + [field1 addVarint:11]; + XCTAssertNotEqualObjects(field1, field2); + [field2 addVarint:11]; + XCTAssertEqualObjects(field1, field2); + XCTAssertEqual([field1 hash], [field2 hash]); + + // Fixed32 + + [field1 addFixed32:20]; + XCTAssertNotEqualObjects(field1, field2); + [field2 addFixed32:20]; + XCTAssertEqualObjects(field1, field2); + XCTAssertEqual([field1 hash], [field2 hash]); + [field1 addFixed32:21]; + XCTAssertNotEqualObjects(field1, field2); + [field2 addFixed32:21]; + XCTAssertEqualObjects(field1, field2); + XCTAssertEqual([field1 hash], [field2 hash]); + + // Fixed64 + + [field1 addFixed64:30]; + XCTAssertNotEqualObjects(field1, field2); + [field2 addFixed64:30]; + XCTAssertEqualObjects(field1, field2); + XCTAssertEqual([field1 hash], [field2 hash]); + [field1 addFixed64:31]; + XCTAssertNotEqualObjects(field1, field2); + [field2 addFixed64:31]; + XCTAssertEqualObjects(field1, field2); + XCTAssertEqual([field1 hash], [field2 hash]); + + // LengthDelimited + + [field1 addLengthDelimited:DataFromCStr("foo")]; + XCTAssertNotEqualObjects(field1, field2); + [field2 addLengthDelimited:DataFromCStr("foo")]; + XCTAssertEqualObjects(field1, field2); + XCTAssertEqual([field1 hash], [field2 hash]); + [field1 addLengthDelimited:DataFromCStr("bar")]; + XCTAssertNotEqualObjects(field1, field2); + [field2 addLengthDelimited:DataFromCStr("bar")]; + XCTAssertEqualObjects(field1, field2); + XCTAssertEqual([field1 hash], [field2 hash]); + + // Group + + GPBUnknownFieldSet *group = [[[GPBUnknownFieldSet alloc] init] autorelease]; + GPBUnknownField* fieldGroup = [[[GPBUnknownField alloc] initWithNumber:100] autorelease]; + [fieldGroup addVarint:100]; + [group addField:fieldGroup]; + [field1 addGroup:group]; + XCTAssertNotEqualObjects(field1, field2); + group = [[[GPBUnknownFieldSet alloc] init] autorelease]; + fieldGroup = [[[GPBUnknownField alloc] initWithNumber:100] autorelease]; + [fieldGroup addVarint:100]; + [group addField:fieldGroup]; + [field2 addGroup:group]; + XCTAssertEqualObjects(field1, field2); + XCTAssertEqual([field1 hash], [field2 hash]); + + group = [[[GPBUnknownFieldSet alloc] init] autorelease]; + fieldGroup = [[[GPBUnknownField alloc] initWithNumber:101] autorelease]; + [fieldGroup addVarint:101]; + [group addField:fieldGroup]; + [field1 addGroup:group]; + XCTAssertNotEqualObjects(field1, field2); + group = [[[GPBUnknownFieldSet alloc] init] autorelease]; + fieldGroup = [[[GPBUnknownField alloc] initWithNumber:101] autorelease]; + [fieldGroup addVarint:101]; + [group addField:fieldGroup]; + [field2 addGroup:group]; + XCTAssertEqualObjects(field1, field2); + XCTAssertEqual([field1 hash], [field2 hash]); + + // Exercise description for completeness. + XCTAssertTrue(field1.description.length > 10); +} + - (void)testMergingFields { GPBUnknownField* field1 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; [field1 addVarint:1]; @@ -247,9 +504,8 @@ - (void)testMergingFields { [field1 addFixed64:3]; [field1 addLengthDelimited:[NSData dataWithBytes:"hello" length:5]]; [field1 addGroup:[[unknownFields_ copy] autorelease]]; - GPBUnknownField* field2 = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; + GPBUnknownField* field2 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; [field2 mergeFromField:field1]; - XCTAssertEqualObjects(field1, field2); } @end diff --git a/objectivec/Tests/GPBUtilitiesTests.m b/objectivec/Tests/GPBUtilitiesTests.m index 2e206a54ea78f..f4a09de586876 100644 --- a/objectivec/Tests/GPBUtilitiesTests.m +++ b/objectivec/Tests/GPBUtilitiesTests.m @@ -52,12 +52,12 @@ @implementation UtilitiesTests - (void)testRightShiftFunctions { XCTAssertEqual((1UL << 31) >> 31, 1UL); - XCTAssertEqual((1 << 31) >> 31, -1); + XCTAssertEqual((int32_t)(1U << 31) >> 31, -1); XCTAssertEqual((1ULL << 63) >> 63, 1ULL); - XCTAssertEqual((1LL << 63) >> 63, -1LL); + XCTAssertEqual((int64_t)(1ULL << 63) >> 63, -1LL); - XCTAssertEqual(GPBLogicalRightShift32((1 << 31), 31), 1); - XCTAssertEqual(GPBLogicalRightShift64((1LL << 63), 63), 1LL); + XCTAssertEqual(GPBLogicalRightShift32((1U << 31), 31), 1); + XCTAssertEqual(GPBLogicalRightShift64((1ULL << 63), 63), 1LL); } - (void)testGPBDecodeTextFormatName { @@ -169,7 +169,27 @@ - (void)testTextFormatMaps { [expected release]; } -// TODO(thomasvl): add test with extensions once those format with correct names. +- (void)testTextFormatExtensions { + TestAllExtensions *message = [TestAllExtensions message]; + + // Not kGPBDefaultRepeatCount because we are comparing to golden master file + // which was generated with 2. + [self setAllExtensions:message repeatedCount:2]; + + NSString *result = GPBTextFormatForMessage(message, nil); + + // NOTE: ObjC TextFormat doesn't have the proper extension names so it + // uses comments for the ObjC name and raw numbers for the fields instead + // of the bracketed extension name. + NSString *fileName = @"text_format_extensions_unittest_data.txt"; + NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding]; + NSData *expectedData = + [self getDataFileNamed:fileName dataToWrite:resultData]; + NSString *expected = [[NSString alloc] initWithData:expectedData + encoding:NSUTF8StringEncoding]; + XCTAssertEqualObjects(expected, result); + [expected release]; +} - (void)testSetRepeatedFields { TestAllTypes *message = [TestAllTypes message]; diff --git a/objectivec/Tests/iOSTestHarness/AppDelegate.m b/objectivec/Tests/iOSTestHarness/AppDelegate.m deleted file mode 100644 index 8c4a586bbddb5..0000000000000 --- a/objectivec/Tests/iOSTestHarness/AppDelegate.m +++ /dev/null @@ -1,35 +0,0 @@ -#import - -@interface AppDelegate : UIResponder -@property (strong, nonatomic) UIWindow *window; -@end - -@implementation AppDelegate - -@synthesize window; - -- (BOOL)application:(UIApplication *)application - didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - #pragma unused (application, launchOptions) - - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - self.window.backgroundColor = [UIColor whiteColor]; - [self.window makeKeyAndVisible]; - self.window.rootViewController = [[UIViewController alloc] init]; - - UILabel *label = - [[UILabel alloc] initWithFrame:CGRectMake(0, 200, CGRectGetWidth(self.window.frame), 40)]; - label.text = @"Protocol Buffer Test Harness"; - label.textAlignment = NSTextAlignmentCenter; - [self.window addSubview:label]; - - return YES; -} - -@end - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 0cbf9acc1c271..0000000000000 --- a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "57x57", - "idiom" : "iphone", - "filename" : "iPhone6.png", - "scale" : "1x" - }, - { - "size" : "57x57", - "idiom" : "iphone", - "filename" : "iPhone6_2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "iPhone7_2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "iPhone7_3x.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "50x50", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "50x50", - "scale" : "2x" - }, - { - "size" : "72x72", - "idiom" : "ipad", - "filename" : "iPad6.png", - "scale" : "1x" - }, - { - "size" : "72x72", - "idiom" : "ipad", - "filename" : "iPad6_2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "iPad7.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "iPad7_2x.png", - "scale" : "2x" - }, - { - "idiom" : "car", - "size" : "120x120", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png deleted file mode 100644 index 43da2ee43490b..0000000000000 Binary files a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png and /dev/null differ diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6_2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6_2x.png deleted file mode 100644 index 2ec93704ca230..0000000000000 Binary files a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6_2x.png and /dev/null differ diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png deleted file mode 100644 index aec8bc1b1bb16..0000000000000 Binary files a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png and /dev/null differ diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7_2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7_2x.png deleted file mode 100644 index e39cc3e754e35..0000000000000 Binary files a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7_2x.png and /dev/null differ diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png deleted file mode 100644 index 5572d79f6f66c..0000000000000 Binary files a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png and /dev/null differ diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6_2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6_2x.png deleted file mode 100644 index 2424997f93f58..0000000000000 Binary files a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6_2x.png and /dev/null differ diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_2x.png deleted file mode 100644 index 10bfc3cfae014..0000000000000 Binary files a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_2x.png and /dev/null differ diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_3x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_3x.png deleted file mode 100644 index 8d16f14dcc500..0000000000000 Binary files a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_3x.png and /dev/null differ diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json b/objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json deleted file mode 100644 index 5a2966687aa05..0000000000000 --- a/objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "images" : [ - { - "orientation" : "portrait", - "idiom" : "ipad", - "minimum-system-version" : "7.0", - "extent" : "full-screen", - "scale" : "2x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "minimum-system-version" : "7.0", - "extent" : "full-screen", - "scale" : "1x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "minimum-system-version" : "7.0", - "extent" : "full-screen", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "minimum-system-version" : "7.0", - "subtype" : "retina4", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "minimum-system-version" : "7.0", - "extent" : "full-screen", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/objectivec/Tests/iOSTestHarness/Info.plist b/objectivec/Tests/iOSTestHarness/Info.plist deleted file mode 100644 index 24bd333d0b8b0..0000000000000 --- a/objectivec/Tests/iOSTestHarness/Info.plist +++ /dev/null @@ -1,43 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - UIInterfaceOrientationPortraitUpsideDown - - - diff --git a/objectivec/Tests/iOSTestHarness/LaunchScreen.xib b/objectivec/Tests/iOSTestHarness/LaunchScreen.xib deleted file mode 100644 index 22204bfe441f3..0000000000000 --- a/objectivec/Tests/iOSTestHarness/LaunchScreen.xib +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings b/objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings deleted file mode 100644 index 477b28ff8f86a..0000000000000 --- a/objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,2 +0,0 @@ -/* Localized versions of Info.plist keys */ - diff --git a/objectivec/Tests/text_format_extensions_unittest_data.txt b/objectivec/Tests/text_format_extensions_unittest_data.txt new file mode 100644 index 0000000000000..d5205456c5fea --- /dev/null +++ b/objectivec/Tests/text_format_extensions_unittest_data.txt @@ -0,0 +1,140 @@ +1: 101 # [UnittestRoot_optionalInt32Extension] +2: 102 # [UnittestRoot_optionalInt64Extension] +3: 103 # [UnittestRoot_optionalUint32Extension] +4: 104 # [UnittestRoot_optionalUint64Extension] +5: 105 # [UnittestRoot_optionalSint32Extension] +6: 106 # [UnittestRoot_optionalSint64Extension] +7: 107 # [UnittestRoot_optionalFixed32Extension] +8: 108 # [UnittestRoot_optionalFixed64Extension] +9: 109 # [UnittestRoot_optionalSfixed32Extension] +10: 110 # [UnittestRoot_optionalSfixed64Extension] +11: 111 # [UnittestRoot_optionalFloatExtension] +12: 112 # [UnittestRoot_optionalDoubleExtension] +13: true # [UnittestRoot_optionalBoolExtension] +14: "115" # [UnittestRoot_optionalStringExtension] +15: "\001\000\002\003\000\005" # [UnittestRoot_optionalBytesExtension] +16 { # [UnittestRoot_optionalGroupExtension] + a: 117 +} +18 { # [UnittestRoot_optionalNestedMessageExtension] + bb: 118 +} +19 { # [UnittestRoot_optionalForeignMessageExtension] + c: 119 +} +20 { # [UnittestRoot_optionalImportMessageExtension] + d: 120 +} +21: 3 # [UnittestRoot_optionalNestedEnumExtension] +22: 6 # [UnittestRoot_optionalForeignEnumExtension] +23: 9 # [UnittestRoot_optionalImportEnumExtension] +24: "124" # [UnittestRoot_optionalStringPieceExtension] +25: "125" # [UnittestRoot_optionalCordExtension] +# [UnittestRoot_repeatedInt32Extension] +31: 201 +31: 301 +# [UnittestRoot_repeatedInt64Extension] +32: 202 +32: 302 +# [UnittestRoot_repeatedUint32Extension] +33: 203 +33: 303 +# [UnittestRoot_repeatedUint64Extension] +34: 204 +34: 304 +# [UnittestRoot_repeatedSint32Extension] +35: 205 +35: 305 +# [UnittestRoot_repeatedSint64Extension] +36: 206 +36: 306 +# [UnittestRoot_repeatedFixed32Extension] +37: 207 +37: 307 +# [UnittestRoot_repeatedFixed64Extension] +38: 208 +38: 308 +# [UnittestRoot_repeatedSfixed32Extension] +39: 209 +39: 309 +# [UnittestRoot_repeatedSfixed64Extension] +40: 210 +40: 310 +# [UnittestRoot_repeatedFloatExtension] +41: 211 +41: 311 +# [UnittestRoot_repeatedDoubleExtension] +42: 212 +42: 312 +# [UnittestRoot_repeatedBoolExtension] +43: false +43: true +# [UnittestRoot_repeatedStringExtension] +44: "215" +44: "315" +# [UnittestRoot_repeatedBytesExtension] +45: "\330\000\000\000" +45: "<\001\000\000" +# [UnittestRoot_repeatedGroupExtension] +46 { + a: 217 +} +46 { + a: 317 +} +# [UnittestRoot_repeatedNestedMessageExtension] +48 { + bb: 218 +} +48 { + bb: 318 +} +# [UnittestRoot_repeatedForeignMessageExtension] +49 { + c: 219 +} +49 { + c: 319 +} +# [UnittestRoot_repeatedImportMessageExtension] +50 { + d: 220 +} +50 { + d: 320 +} +# [UnittestRoot_repeatedNestedEnumExtension] +51: 3 +51: 2 +# [UnittestRoot_repeatedForeignEnumExtension] +52: 6 +52: 5 +# [UnittestRoot_repeatedImportEnumExtension] +53: 9 +53: 8 +# [UnittestRoot_repeatedStringPieceExtension] +54: "224" +54: "324" +# [UnittestRoot_repeatedCordExtension] +55: "225" +55: "325" +61: 401 # [UnittestRoot_defaultInt32Extension] +62: 402 # [UnittestRoot_defaultInt64Extension] +63: 403 # [UnittestRoot_defaultUint32Extension] +64: 404 # [UnittestRoot_defaultUint64Extension] +65: 405 # [UnittestRoot_defaultSint32Extension] +66: 406 # [UnittestRoot_defaultSint64Extension] +67: 407 # [UnittestRoot_defaultFixed32Extension] +68: 408 # [UnittestRoot_defaultFixed64Extension] +69: 409 # [UnittestRoot_defaultSfixed32Extension] +70: 410 # [UnittestRoot_defaultSfixed64Extension] +71: 411 # [UnittestRoot_defaultFloatExtension] +72: 412 # [UnittestRoot_defaultDoubleExtension] +73: false # [UnittestRoot_defaultBoolExtension] +74: "415" # [UnittestRoot_defaultStringExtension] +75: "\240\001\000\000" # [UnittestRoot_defaultBytesExtension] +81: 1 # [UnittestRoot_defaultNestedEnumExtension] +82: 4 # [UnittestRoot_defaultForeignEnumExtension] +83: 7 # [UnittestRoot_defaultImportEnumExtension] +84: "424" # [UnittestRoot_defaultStringPieceExtension] +85: "425" # [UnittestRoot_defaultCordExtension] diff --git a/objectivec/Tests/unittest_extension_chain_f.proto b/objectivec/Tests/unittest_extension_chain_f.proto index b9bed7239b538..096598d63190c 100644 --- a/objectivec/Tests/unittest_extension_chain_f.proto +++ b/objectivec/Tests/unittest_extension_chain_f.proto @@ -34,7 +34,7 @@ package protobuf_unittest; import "unittest_extension_chain_g.proto"; // The Root for this file should just be merging in the extensions from C's -// Root (because G doens't define anything itself). +// Root (because G doesn't define anything itself). // The generated source will also have to directly import C's .h file so it can // compile the reference to C's Root class. diff --git a/objectivec/Tests/unittest_objc.proto b/objectivec/Tests/unittest_objc.proto index e5577faf0defe..91c213921e7f5 100644 --- a/objectivec/Tests/unittest_objc.proto +++ b/objectivec/Tests/unittest_objc.proto @@ -58,6 +58,27 @@ message TestRecursiveMessageWithRepeatedField { map str_to_str = 5; } +// Message with a few types of maps to cover the different custom flows +// in the runtime. +message TestMessageOfMaps { + map str_to_str = 1; + + map str_to_int = 2; + map int_to_str = 3; + map int_to_int = 4; + + map str_to_bool = 5; + map bool_to_str = 6; + map bool_to_bool = 7; + + map int_to_bool = 8; + map bool_to_int = 9; + + map str_to_msg = 10; + map int_to_msg = 11; + map bool_to_msg = 12; +} + // Recursive message and extension to for testing autocreators at different // depths. message TestRecursiveExtension { @@ -82,37 +103,89 @@ message self { } // Singular - optional bool id = 1; - optional bool _cmd = 2; - optional bool in = 3; - optional bool out = 4; - optional bool inout = 5; - optional bool bycopy = 6; - optional bool byref = 7; - optional bool oneway = 8; - optional bool dealloc = 9; - optional bool zone = 10; - optional bool isProxy = 11; - optional bool copy = 12; - optional bool readonly = 13; - optional bool default = 14; - optional bool assign = 15; - optional bool getter = 16; - optional bool setter = 17; - optional bool weak = 18; - optional bool public = 19; - optional bool case = 20; - - optional autorelease SubEnum = 25; - - optional group New = 50 { - optional string copy = 51; - } - optional group MutableCopy = 60 { - optional int32 extensionRegistry = 61; + // Objective C Keywords + optional bool id = 1; + optional bool _cmd = 2; + // super is used as submessage above + optional bool in = 4; + optional bool out = 5; + optional bool inout = 6; + optional bool bycopy = 7; + optional bool byref = 8; + optional bool oneway = 9; + optional bool self = 10; + optional bool instancetype = 11; + optional bool nullable = 12; + optional bool nonnull = 13; + optional bool nil = 14; + // Nil and nil can't be in the same message + optional bool YES = 16; + optional bool NO = 17; + optional bool weak = 18; + + // Some C/C++ Keywords + optional bool case = 30; + optional bool if = 31; + optional bool and_eq = 32; + optional bool public = 33; + optional bool private = 34; + optional bool typename = 35; + optional bool static_cast = 36; + optional bool typeof = 37; + optional bool restrict = 38; + optional bool NULL = 39; + + // Some NSObject Methods + optional bool dealloc = 110; + optional bool isProxy = 111; + optional bool copy = 112; + optional bool description = 113; + optional bool zone = 114; + optional bool className = 115; + optional bool __retain_OA = 116; + optional bool CAMLType = 117; + optional bool isNSDictionary__ = 118; + optional bool accessibilityLabel = 119; + + // Some Objc "keywords" that we shouldn't + // have to worry about because they + // can only appear in specialized areas. + optional bool assign = 200; + optional bool getter = 201; + optional bool setter = 202; + optional bool atomic = 203; + optional bool nonatomic = 204; + optional bool strong = 205; + optional bool null_resettable = 206; + optional bool readonly = 207; + + // Some GPBMessage methods + optional bool clear = 300; + optional bool data = 301; + optional bool descriptor = 302; + optional bool delimitedData = 303; + + // Some MacTypes + optional bool Fixed = 400; + optional bool Point = 401; + optional bool FixedPoint = 402; + optional bool Style = 403; + + // C/C++ reserved identifiers + optional bool _Generic = 500; + optional bool __block = 501; + + // Try a keyword as a type + optional autorelease SubEnum = 1000; + + optional group New = 2000 { + optional string copy = 1; + } + optional group MutableCopy = 2001 { + optional int32 extensionRegistry = 1; } - extensions 90 to 94; + extensions 3000 to 3999; } @@ -156,11 +229,11 @@ enum Time { } extend self { - repeated int32 debugDescription = 90 [packed = true]; - repeated int64 finalize = 91 [packed = true]; - repeated uint32 hash = 92 [packed = true]; - repeated uint64 classForCoder = 93 [packed = true]; - repeated sint32 byref = 94 [packed = true]; + repeated int32 debugDescription = 3000 [packed = true]; + repeated int64 finalize = 3001 [packed = true]; + repeated uint32 hash = 3002 [packed = true]; + repeated uint64 classForCoder = 3003 [packed = true]; + repeated sint32 byref = 3004 [packed = true]; } // Test handing of fields that start with init* since Xcode 5's ARC support @@ -336,6 +409,335 @@ message ObjCRetainedFoo { repeated Foo mutableCopy_Val_upper_enum_repeated = 724; repeated Foo mutableCopyvalue_lower_no_underscore_enum_repeated = 725; repeated Foo mutableCopyValue_upper_no_underscore_enum_repeated = 726; + + extensions 1000 to 3999; +} + +// Extension fields with retained names. +extend ObjCRetainedFoo { + optional string new_val_lower_complex = 1011; + optional string new_Val_upper_complex = 1012; + optional string newvalue_lower_no_underscore_complex = 1013; + optional string newValue_upper_no_underscore_complex = 1014; + + optional int32 new_val_lower_primitive = 1015; + optional int32 new_Val_upper_primitive = 1016; + optional int32 newvalue_lower_no_underscore_primitive = 1017; + optional int32 newValue_upper_no_underscore_primitive = 1018; + + optional self new_val_lower_message = 1019; + optional self new_Val_upper_message = 1020; + optional self newvalue_lower_no_underscore_message = 1021; + optional self newValue_upper_no_underscore_message = 1022; + + optional Foo new_val_lower_enum = 1023; + optional Foo new_Val_upper_enum = 1024; + optional Foo newvalue_lower_no_underscore_enum = 1025; + optional Foo newValue_upper_no_underscore_enum = 1026; + + repeated string new_val_lower_complex_repeated = 1111; + repeated string new_Val_upper_complex_repeated = 1112; + repeated string newvalue_lower_no_underscore_complex_repeated = 1113; + repeated string newValue_upper_no_underscore_complex_repeated = 1114; + + repeated int32 new_val_lower_primitive_repeated = 1115; + repeated int32 new_Val_upper_primitive_repeated = 1116; + repeated int32 newvalue_lower_no_underscore_primitive_repeated = 1117; + repeated int32 newValue_upper_no_underscore_primitive_repeated = 1118; + + repeated self new_val_lower_message_repeated = 1119; + repeated self new_Val_upper_message_repeated = 1120; + repeated self newvalue_lower_no_underscore_message_repeated = 1121; + repeated self newValue_upper_no_underscore_message_repeated = 1122; + + repeated Foo new_val_lower_enum_repeated = 1123; + repeated Foo new_Val_upper_enum_repeated = 1124; + repeated Foo newvalue_lower_no_underscore_enum_repeated = 1125; + repeated Foo newValue_upper_no_underscore_enum_repeated = 1126; + + optional string alloc_val_lower_complex = 1211; + optional string alloc_Val_upper_complex = 1212; + optional string allocvalue_lower_no_underscore_complex = 1213; + optional string allocValue_upper_no_underscore_complex = 1214; + + optional int32 alloc_val_lower_primitive = 1215; + optional int32 alloc_Val_upper_primitive = 1216; + optional int32 allocvalue_lower_no_underscore_primitive = 1217; + optional int32 allocValue_upper_no_underscore_primitive = 1218; + + optional self alloc_val_lower_message = 1219; + optional self alloc_Val_upper_message = 1220; + optional self allocvalue_lower_no_underscore_message = 1221; + optional self allocValue_upper_no_underscore_message = 1222; + + optional Foo alloc_val_lower_enum = 1223; + optional Foo alloc_Val_upper_enum = 1224; + optional Foo allocvalue_lower_no_underscore_enum = 1225; + optional Foo allocValue_upper_no_underscore_enum = 1226; + + repeated string alloc_val_lower_complex_repeated = 1311; + repeated string alloc_Val_upper_complex_repeated = 1312; + repeated string allocvalue_lower_no_underscore_complex_repeated = 1313; + repeated string allocValue_upper_no_underscore_complex_repeated = 1314; + + repeated int32 alloc_val_lower_primitive_repeated = 1315; + repeated int32 alloc_Val_upper_primitive_repeated = 1316; + repeated int32 allocvalue_lower_no_underscore_primitive_repeated = 1317; + repeated int32 allocValue_upper_no_underscore_primitive_repeated = 1318; + + repeated self alloc_val_lower_message_repeated = 1319; + repeated self alloc_Val_upper_message_repeated = 1320; + repeated self allocvalue_lower_no_underscore_message_repeated = 1321; + repeated self allocValue_upper_no_underscore_message_repeated = 1322; + + repeated Foo alloc_val_lower_enum_repeated = 1323; + repeated Foo alloc_Val_upper_enum_repeated = 1324; + repeated Foo allocvalue_lower_no_underscore_enum_repeated = 1325; + repeated Foo allocValue_upper_no_underscore_enum_repeated = 1326; + + optional string copy_val_lower_complex = 1411; + optional string copy_Val_upper_complex = 1412; + optional string copyvalue_lower_no_underscore_complex = 1413; + optional string copyValue_upper_no_underscore_complex = 1414; + + optional int32 copy_val_lower_primitive = 1415; + optional int32 copy_Val_upper_primitive = 1416; + optional int32 copyvalue_lower_no_underscore_primitive = 1417; + optional int32 copyValue_upper_no_underscore_primitive = 1418; + + optional self copy_val_lower_message = 1419; + optional self copy_Val_upper_message = 1420; + optional self copyvalue_lower_no_underscore_message = 1421; + optional self copyValue_upper_no_underscore_message = 1422; + + optional Foo copy_val_lower_enum = 1423; + optional Foo copy_Val_upper_enum = 1424; + optional Foo copyvalue_lower_no_underscore_enum = 1425; + optional Foo copyValue_upper_no_underscore_enum = 1426; + + repeated string copy_val_lower_complex_repeated = 1511; + repeated string copy_Val_upper_complex_repeated = 1512; + repeated string copyvalue_lower_no_underscore_complex_repeated = 1513; + repeated string copyValue_upper_no_underscore_complex_repeated = 1514; + + repeated int32 copy_val_lower_primitive_repeated = 1515; + repeated int32 copy_Val_upper_primitive_repeated = 1516; + repeated int32 copyvalue_lower_no_underscore_primitive_repeated = 1517; + repeated int32 copyValue_upper_no_underscore_primitive_repeated = 1518; + + repeated self copy_val_lower_message_repeated = 1519; + repeated self copy_Val_upper_message_repeated = 1520; + repeated self copyvalue_lower_no_underscore_message_repeated = 1521; + repeated self copyValue_upper_no_underscore_message_repeated = 1522; + + repeated Foo copy_val_lower_enum_repeated = 1523; + repeated Foo copy_Val_upper_enum_repeated = 1524; + repeated Foo copyvalue_lower_no_underscore_enum_repeated = 1525; + repeated Foo copyValue_upper_no_underscore_enum_repeated = 1526; + + optional string mutableCopy_val_lower_complex = 1611; + optional string mutableCopy_Val_upper_complex = 1612; + optional string mutableCopyvalue_lower_no_underscore_complex = 1613; + optional string mutableCopyValue_upper_no_underscore_complex = 1614; + + optional int32 mutableCopy_val_lower_primitive = 1615; + optional int32 mutableCopy_Val_upper_primitive = 1616; + optional int32 mutableCopyvalue_lower_no_underscore_primitive = 1617; + optional int32 mutableCopyValue_upper_no_underscore_primitive = 1618; + + optional self mutableCopy_val_lower_message = 1619; + optional self mutableCopy_Val_upper_message = 1620; + optional self mutableCopyvalue_lower_no_underscore_message = 1621; + optional self mutableCopyValue_upper_no_underscore_message = 1622; + + optional Foo mutableCopy_val_lower_enum = 1623; + optional Foo mutableCopy_Val_upper_enum = 1624; + optional Foo mutableCopyvalue_lower_no_underscore_enum = 1625; + optional Foo mutableCopyValue_upper_no_underscore_enum = 1626; + + repeated string mutableCopy_val_lower_complex_repeated = 1711; + repeated string mutableCopy_Val_upper_complex_repeated = 1712; + repeated string mutableCopyvalue_lower_no_underscore_complex_repeated = 1713; + repeated string mutableCopyValue_upper_no_underscore_complex_repeated = 1714; + + repeated int32 mutableCopy_val_lower_primitive_repeated = 1715; + repeated int32 mutableCopy_Val_upper_primitive_repeated = 1716; + repeated int32 mutableCopyvalue_lower_no_underscore_primitive_repeated = 1717; + repeated int32 mutableCopyValue_upper_no_underscore_primitive_repeated = 1718; + + repeated self mutableCopy_val_lower_message_repeated = 1719; + repeated self mutableCopy_Val_upper_message_repeated = 1720; + repeated self mutableCopyvalue_lower_no_underscore_message_repeated = 1721; + repeated self mutableCopyValue_upper_no_underscore_message_repeated = 1722; + + repeated Foo mutableCopy_val_lower_enum_repeated = 1723; + repeated Foo mutableCopy_Val_upper_enum_repeated = 1724; + repeated Foo mutableCopyvalue_lower_no_underscore_enum_repeated = 1725; + repeated Foo mutableCopyValue_upper_no_underscore_enum_repeated = 1726; +} + +message JustToScopeExtensions { + extend ObjCRetainedFoo { + optional string new_val_lower_complex = 2011; + optional string new_Val_upper_complex = 2012; + optional string newvalue_lower_no_underscore_complex = 2013; + optional string newValue_upper_no_underscore_complex = 2014; + + optional int32 new_val_lower_primitive = 2015; + optional int32 new_Val_upper_primitive = 2016; + optional int32 newvalue_lower_no_underscore_primitive = 2017; + optional int32 newValue_upper_no_underscore_primitive = 2018; + + optional self new_val_lower_message = 2019; + optional self new_Val_upper_message = 2020; + optional self newvalue_lower_no_underscore_message = 2021; + optional self newValue_upper_no_underscore_message = 2022; + + optional Foo new_val_lower_enum = 2023; + optional Foo new_Val_upper_enum = 2024; + optional Foo newvalue_lower_no_underscore_enum = 2025; + optional Foo newValue_upper_no_underscore_enum = 2026; + + repeated string new_val_lower_complex_repeated = 2111; + repeated string new_Val_upper_complex_repeated = 2112; + repeated string newvalue_lower_no_underscore_complex_repeated = 2113; + repeated string newValue_upper_no_underscore_complex_repeated = 2114; + + repeated int32 new_val_lower_primitive_repeated = 2115; + repeated int32 new_Val_upper_primitive_repeated = 2116; + repeated int32 newvalue_lower_no_underscore_primitive_repeated = 2117; + repeated int32 newValue_upper_no_underscore_primitive_repeated = 2118; + + repeated self new_val_lower_message_repeated = 2119; + repeated self new_Val_upper_message_repeated = 2120; + repeated self newvalue_lower_no_underscore_message_repeated = 2121; + repeated self newValue_upper_no_underscore_message_repeated = 2122; + + repeated Foo new_val_lower_enum_repeated = 2123; + repeated Foo new_Val_upper_enum_repeated = 2124; + repeated Foo newvalue_lower_no_underscore_enum_repeated = 2125; + repeated Foo newValue_upper_no_underscore_enum_repeated = 2126; + + optional string alloc_val_lower_complex = 2211; + optional string alloc_Val_upper_complex = 2212; + optional string allocvalue_lower_no_underscore_complex = 2213; + optional string allocValue_upper_no_underscore_complex = 2214; + + optional int32 alloc_val_lower_primitive = 2215; + optional int32 alloc_Val_upper_primitive = 2216; + optional int32 allocvalue_lower_no_underscore_primitive = 2217; + optional int32 allocValue_upper_no_underscore_primitive = 2218; + + optional self alloc_val_lower_message = 2219; + optional self alloc_Val_upper_message = 2220; + optional self allocvalue_lower_no_underscore_message = 2221; + optional self allocValue_upper_no_underscore_message = 2222; + + optional Foo alloc_val_lower_enum = 2223; + optional Foo alloc_Val_upper_enum = 2224; + optional Foo allocvalue_lower_no_underscore_enum = 2225; + optional Foo allocValue_upper_no_underscore_enum = 2226; + + repeated string alloc_val_lower_complex_repeated = 2311; + repeated string alloc_Val_upper_complex_repeated = 2312; + repeated string allocvalue_lower_no_underscore_complex_repeated = 2313; + repeated string allocValue_upper_no_underscore_complex_repeated = 2314; + + repeated int32 alloc_val_lower_primitive_repeated = 2315; + repeated int32 alloc_Val_upper_primitive_repeated = 2316; + repeated int32 allocvalue_lower_no_underscore_primitive_repeated = 2317; + repeated int32 allocValue_upper_no_underscore_primitive_repeated = 2318; + + repeated self alloc_val_lower_message_repeated = 2319; + repeated self alloc_Val_upper_message_repeated = 2320; + repeated self allocvalue_lower_no_underscore_message_repeated = 2321; + repeated self allocValue_upper_no_underscore_message_repeated = 2322; + + repeated Foo alloc_val_lower_enum_repeated = 2323; + repeated Foo alloc_Val_upper_enum_repeated = 2324; + repeated Foo allocvalue_lower_no_underscore_enum_repeated = 2325; + repeated Foo allocValue_upper_no_underscore_enum_repeated = 2326; + + optional string copy_val_lower_complex = 2411; + optional string copy_Val_upper_complex = 2412; + optional string copyvalue_lower_no_underscore_complex = 2413; + optional string copyValue_upper_no_underscore_complex = 2414; + + optional int32 copy_val_lower_primitive = 2415; + optional int32 copy_Val_upper_primitive = 2416; + optional int32 copyvalue_lower_no_underscore_primitive = 2417; + optional int32 copyValue_upper_no_underscore_primitive = 2418; + + optional self copy_val_lower_message = 2419; + optional self copy_Val_upper_message = 2420; + optional self copyvalue_lower_no_underscore_message = 2421; + optional self copyValue_upper_no_underscore_message = 2422; + + optional Foo copy_val_lower_enum = 2423; + optional Foo copy_Val_upper_enum = 2424; + optional Foo copyvalue_lower_no_underscore_enum = 2425; + optional Foo copyValue_upper_no_underscore_enum = 2426; + + repeated string copy_val_lower_complex_repeated = 2511; + repeated string copy_Val_upper_complex_repeated = 2512; + repeated string copyvalue_lower_no_underscore_complex_repeated = 2513; + repeated string copyValue_upper_no_underscore_complex_repeated = 2514; + + repeated int32 copy_val_lower_primitive_repeated = 2515; + repeated int32 copy_Val_upper_primitive_repeated = 2516; + repeated int32 copyvalue_lower_no_underscore_primitive_repeated = 2517; + repeated int32 copyValue_upper_no_underscore_primitive_repeated = 2518; + + repeated self copy_val_lower_message_repeated = 2519; + repeated self copy_Val_upper_message_repeated = 2520; + repeated self copyvalue_lower_no_underscore_message_repeated = 2521; + repeated self copyValue_upper_no_underscore_message_repeated = 2522; + + repeated Foo copy_val_lower_enum_repeated = 2523; + repeated Foo copy_Val_upper_enum_repeated = 2524; + repeated Foo copyvalue_lower_no_underscore_enum_repeated = 2525; + repeated Foo copyValue_upper_no_underscore_enum_repeated = 2526; + + optional string mutableCopy_val_lower_complex = 2611; + optional string mutableCopy_Val_upper_complex = 2612; + optional string mutableCopyvalue_lower_no_underscore_complex = 2613; + optional string mutableCopyValue_upper_no_underscore_complex = 2614; + + optional int32 mutableCopy_val_lower_primitive = 2615; + optional int32 mutableCopy_Val_upper_primitive = 2616; + optional int32 mutableCopyvalue_lower_no_underscore_primitive = 2617; + optional int32 mutableCopyValue_upper_no_underscore_primitive = 2618; + + optional self mutableCopy_val_lower_message = 2619; + optional self mutableCopy_Val_upper_message = 2620; + optional self mutableCopyvalue_lower_no_underscore_message = 2621; + optional self mutableCopyValue_upper_no_underscore_message = 2622; + + optional Foo mutableCopy_val_lower_enum = 2623; + optional Foo mutableCopy_Val_upper_enum = 2624; + optional Foo mutableCopyvalue_lower_no_underscore_enum = 2625; + optional Foo mutableCopyValue_upper_no_underscore_enum = 2626; + + repeated string mutableCopy_val_lower_complex_repeated = 2711; + repeated string mutableCopy_Val_upper_complex_repeated = 2712; + repeated string mutableCopyvalue_lower_no_underscore_complex_repeated = 2713; + repeated string mutableCopyValue_upper_no_underscore_complex_repeated = 2714; + + repeated int32 mutableCopy_val_lower_primitive_repeated = 2715; + repeated int32 mutableCopy_Val_upper_primitive_repeated = 2716; + repeated int32 mutableCopyvalue_lower_no_underscore_primitive_repeated = 2717; + repeated int32 mutableCopyValue_upper_no_underscore_primitive_repeated = 2718; + + repeated self mutableCopy_val_lower_message_repeated = 2719; + repeated self mutableCopy_Val_upper_message_repeated = 2720; + repeated self mutableCopyvalue_lower_no_underscore_message_repeated = 2721; + repeated self mutableCopyValue_upper_no_underscore_message_repeated = 2722; + + repeated Foo mutableCopy_val_lower_enum_repeated = 2723; + repeated Foo mutableCopy_Val_upper_enum_repeated = 2724; + repeated Foo mutableCopyvalue_lower_no_underscore_enum_repeated = 2725; + repeated Foo mutableCopyValue_upper_no_underscore_enum_repeated = 2726; + } } // Test handling of fields that are the retained names. @@ -412,7 +814,7 @@ message EnumTestMsg { repeated MyEnum mumble = 4; } -// Test case for https://github.com/google/protobuf/issues/1453 +// Test case for https://github.com/protocolbuffers/protobuf/issues/1453 // Message with no explicit defaults, but a non zero default for an enum. message MessageWithOneBasedEnum { enum OneBasedEnum { @@ -465,3 +867,18 @@ message BoolOnlyMessage { message WKTRefereceMessage { optional google.protobuf.Any an_any = 1; } + +// This is in part a compile test, it ensures that when aliases end up with +// the same ObjC name, we drop them to avoid the duplication names. There +// is a test to ensure the descriptors are still generated to support +// reflection and TextFormat. +enum TestEnumObjCNameCollision { + option allow_alias = true; + + FOO = 1; + foo = 1; + + BAR = 2; + mumble = 2; + MUMBLE = 2; +} diff --git a/objectivec/Tests/unittest_objc_options.proto b/objectivec/Tests/unittest_objc_options.proto new file mode 100644 index 0000000000000..6129b854e0450 --- /dev/null +++ b/objectivec/Tests/unittest_objc_options.proto @@ -0,0 +1,61 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package protobuf_objc_unittest; +option objc_class_prefix = "GPBTEST"; + +// Verify that enum types and values get the prefix. +message TestObjcProtoPrefixMessage { +} + +// Verify that messages that don't already have the prefix get a prefix. +enum TestObjcProtoPrefixEnum { + value = 1; +} + +// Verify that messages that already have a prefix aren't prefixed twice. +message GPBTESTTestHasAPrefixMessage { +} + +// Verify that enums that already have a prefix aren't prefixed twice. +enum GPBTESTTestHasAPrefixEnum { + valueB = 1; +} + +// Verify that classes that have the prefix followed by a lowercase +// letter DO get the prefix. +message GPBTESTshouldGetAPrefixMessage { +} + +// Verify that classes named the same as prefixes are prefixed. +message GPBTEST { +} diff --git a/objectivec/Tests/unittest_runtime_proto3.proto b/objectivec/Tests/unittest_runtime_proto3.proto index ad2e3620d3e38..c2ee5fb52faa5 100644 --- a/objectivec/Tests/unittest_runtime_proto3.proto +++ b/objectivec/Tests/unittest_runtime_proto3.proto @@ -119,3 +119,31 @@ message Message3 { map map_int32_enum = 87; map map_int32_message = 88; } + +message Message3Optional { + enum Enum { + FOO = 0; + BAR = 1; + BAZ = 2; + EXTRA_3 = 30; + } + + 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; + // No 'group' in proto3. + optional Message3 optional_message = 18; + optional Enum optional_enum = 19; +} diff --git a/objectivec/generate_well_known_types.sh b/objectivec/generate_well_known_types.sh index 36c346031c85d..1b9de6ec55eee 100755 --- a/objectivec/generate_well_known_types.sh +++ b/objectivec/generate_well_known_types.sh @@ -10,7 +10,8 @@ set -eu readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")") -readonly ProtoRootDir="${ScriptDir}/.." +readonly ObjCDir="${ScriptDir}" +readonly ProtoRootDir="${ObjCDir}/.." # Flag for continuous integration to check that everything is current. CHECK_ONLY=0 @@ -19,9 +20,9 @@ if [[ $# -ge 1 && ( "$1" == "--check-only" ) ]] ; then shift fi -pushd "${ProtoRootDir}" > /dev/null +cd "${ProtoRootDir}" -if test ! -e src/google/protobuf/stubs/common.h; then +if [[ ! -e src/google/protobuf/stubs/common.h ]]; then cat >&2 << __EOF__ Could not find source code. Make sure you are running this script from the root of the distribution tree. @@ -29,7 +30,7 @@ __EOF__ exit 1 fi -if test ! -e src/Makefile; then +if [[ ! -e src/Makefile ]]; then cat >&2 << __EOF__ Could not find src/Makefile. You must run ./configure (and perhaps ./autogen.sh) first. @@ -53,24 +54,36 @@ declare -a RUNTIME_PROTO_FILES=( \ google/protobuf/type.proto \ google/protobuf/wrappers.proto) +declare -a OBJC_EXTENSIONS=( .pbobjc.h .pbobjc.m ) + # Generate to a temp directory to see if they match. TMP_DIR=$(mktemp -d) trap "rm -rf ${TMP_DIR}" EXIT ./protoc --objc_out="${TMP_DIR}" ${RUNTIME_PROTO_FILES[@]} -set +e -diff -r "${TMP_DIR}/google" "${ProtoRootDir}/objectivec/google" > /dev/null -if [[ $? -eq 0 ]] ; then - echo "Generated source for WellKnownTypes is current." - exit 0 -fi -set -e -# If check only mode, error out. -if [[ "${CHECK_ONLY}" == 1 ]] ; then - echo "ERROR: The WKTs need to be regenerated! Run $0" - exit 1 -fi +DID_COPY=0 +for PROTO_FILE in "${RUNTIME_PROTO_FILES[@]}"; do + DIR=${PROTO_FILE%/*} + BASE_NAME=${PROTO_FILE##*/} + # Drop the extension + BASE_NAME=${BASE_NAME%.*} + OBJC_NAME=$(echo "${BASE_NAME}" | awk -F _ '{for(i=1; i<=NF; i++) printf "%s", toupper(substr($i,1,1)) substr($i,2);}') -# Copy them over. -echo "Copying over updated WellKnownType sources." -cp -r "${TMP_DIR}/google/." "${ProtoRootDir}/objectivec/google/" + for EXT in "${OBJC_EXTENSIONS[@]}"; do + if ! diff "${ObjCDir}/GPB${OBJC_NAME}${EXT}" "${TMP_DIR}/${DIR}/${OBJC_NAME}${EXT}" > /dev/null 2>&1 ; then + if [[ "${CHECK_ONLY}" == 1 ]] ; then + echo "ERROR: The WKTs need to be regenerated! Run $0" + exit 1 + fi + + echo "INFO: Updating GPB${OBJC_NAME}${EXT}" + cp "${TMP_DIR}/${DIR}/${OBJC_NAME}${EXT}" "${ObjCDir}/GPB${OBJC_NAME}${EXT}" + DID_COPY=1 + fi + done +done + +if [[ "${DID_COPY}" == 0 ]]; then + echo "INFO: Generated source for WellKnownTypes is current." + exit 0 +fi diff --git a/objectivec/google/protobuf/Any.pbobjc.h b/objectivec/google/protobuf/Any.pbobjc.h index b17e76f0aaaaa..e6d1b7450abe5 100644 --- a/objectivec/google/protobuf/Any.pbobjc.h +++ b/objectivec/google/protobuf/Any.pbobjc.h @@ -1,173 +1,2 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/any.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers.h" -#endif - -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 -#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. -#endif -#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION -#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. -#endif - -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -CF_EXTERN_C_BEGIN - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - GPBAnyRoot - -/** - * Exposes the extension registry for this file. - * - * The base class provides: - * @code - * + (GPBExtensionRegistry *)extensionRegistry; - * @endcode - * which is a @c GPBExtensionRegistry that includes all the extensions defined by - * this file and all files that it depends on. - **/ -@interface GPBAnyRoot : GPBRootObject -@end - -#pragma mark - GPBAny - -typedef GPB_ENUM(GPBAny_FieldNumber) { - GPBAny_FieldNumber_TypeURL = 1, - GPBAny_FieldNumber_Value = 2, -}; - -/** - * `Any` contains an arbitrary serialized protocol buffer message along with a - * URL that describes the type of the serialized message. - * - * Protobuf library provides support to pack/unpack Any values in the form - * of utility functions or additional generated methods of the Any type. - * - * Example 1: Pack and unpack a message in C++. - * - * Foo foo = ...; - * Any any; - * any.PackFrom(foo); - * ... - * if (any.UnpackTo(&foo)) { - * ... - * } - * - * Example 2: Pack and unpack a message in Java. - * - * Foo foo = ...; - * Any any = Any.pack(foo); - * ... - * if (any.is(Foo.class)) { - * foo = any.unpack(Foo.class); - * } - * - * Example 3: Pack and unpack a message in Python. - * - * foo = Foo(...) - * any = Any() - * any.Pack(foo) - * ... - * if any.Is(Foo.DESCRIPTOR): - * any.Unpack(foo) - * ... - * - * Example 4: Pack and unpack a message in Go - * - * foo := &pb.Foo{...} - * any, err := ptypes.MarshalAny(foo) - * ... - * foo := &pb.Foo{} - * if err := ptypes.UnmarshalAny(any, foo); err != nil { - * ... - * } - * - * The pack methods provided by protobuf library will by default use - * 'type.googleapis.com/full.type.name' as the type URL and the unpack - * methods only use the fully qualified type name after the last '/' - * in the type URL, for example "foo.bar.com/x/y.z" will yield type - * name "y.z". - * - * - * JSON - * ==== - * The JSON representation of an `Any` value uses the regular - * representation of the deserialized, embedded message, with an - * additional field `\@type` which contains the type URL. Example: - * - * package google.profile; - * message Person { - * string first_name = 1; - * string last_name = 2; - * } - * - * { - * "\@type": "type.googleapis.com/google.profile.Person", - * "firstName": , - * "lastName": - * } - * - * If the embedded message type is well-known and has a custom JSON - * representation, that representation will be embedded adding a field - * `value` which holds the custom JSON in addition to the `\@type` - * field. Example (for message [google.protobuf.Duration][]): - * - * { - * "\@type": "type.googleapis.com/google.protobuf.Duration", - * "value": "1.212s" - * } - **/ -@interface GPBAny : GPBMessage - -/** - * A URL/resource name whose content describes the type of the - * serialized protocol buffer message. - * - * For URLs which use the scheme `http`, `https`, or no scheme, the - * following restrictions and interpretations apply: - * - * * If no scheme is provided, `https` is assumed. - * * The last segment of the URL's path must represent the fully - * qualified name of the type (as in `path/google.protobuf.Duration`). - * The name should be in a canonical form (e.g., leading "." is - * not accepted). - * * An HTTP GET on the URL must yield a [google.protobuf.Type][] - * value in binary format, or produce an error. - * * Applications are allowed to cache lookup results based on the - * URL, or have them precompiled into a binary to avoid any - * lookup. Therefore, binary compatibility needs to be preserved - * on changes to types. (Use versioned type names to manage - * breaking changes.) - * - * Schemes other than `http`, `https` (or the empty scheme) might be - * used with implementation specific semantics. - **/ -@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL; - -/** Must be a valid serialized protocol buffer of the above specified type. */ -@property(nonatomic, readwrite, copy, null_resettable) NSData *value; - -@end - -NS_ASSUME_NONNULL_END - -CF_EXTERN_C_END - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) +// Moved to root of objectivec directory, shim to keep anyone's imports working. +#import "GPBAny.pbobjc.h" diff --git a/objectivec/google/protobuf/Any.pbobjc.m b/objectivec/google/protobuf/Any.pbobjc.m deleted file mode 100644 index d210643f05bfd..0000000000000 --- a/objectivec/google/protobuf/Any.pbobjc.m +++ /dev/null @@ -1,112 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/any.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers_RuntimeSupport.h" -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "google/protobuf/Any.pbobjc.h" -#endif -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -#pragma mark - GPBAnyRoot - -@implementation GPBAnyRoot - -// No extensions in the file and no imports, so no need to generate -// +extensionRegistry. - -@end - -#pragma mark - GPBAnyRoot_FileDescriptor - -static GPBFileDescriptor *GPBAnyRoot_FileDescriptor(void) { - // This is called by +initialize so there is no need to worry - // about thread safety of the singleton. - static GPBFileDescriptor *descriptor = NULL; - if (!descriptor) { - GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); - descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" - objcPrefix:@"GPB" - syntax:GPBFileSyntaxProto3]; - } - return descriptor; -} - -#pragma mark - GPBAny - -@implementation GPBAny - -@dynamic typeURL; -@dynamic value; - -typedef struct GPBAny__storage_ { - uint32_t _has_storage_[1]; - NSString *typeURL; - NSData *value; -} GPBAny__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "typeURL", - .dataTypeSpecific.className = NULL, - .number = GPBAny_FieldNumber_TypeURL, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBAny__storage_, typeURL), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), - .dataType = GPBDataTypeString, - }, - { - .name = "value", - .dataTypeSpecific.className = NULL, - .number = GPBAny_FieldNumber_Value, - .hasIndex = 1, - .offset = (uint32_t)offsetof(GPBAny__storage_, value), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeBytes, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBAny class] - rootClass:[GPBAnyRoot class] - file:GPBAnyRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBAny__storage_) - flags:GPBDescriptorInitializationFlag_None]; -#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS - static const char *extraTextFormatInfo = - "\001\001\004\241!!\000"; - [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; -#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Api.pbobjc.h b/objectivec/google/protobuf/Api.pbobjc.h index 095fc2cd6d246..e7957db4e1220 100644 --- a/objectivec/google/protobuf/Api.pbobjc.h +++ b/objectivec/google/protobuf/Api.pbobjc.h @@ -1,307 +1,2 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/api.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers.h" -#endif - -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 -#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. -#endif -#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION -#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. -#endif - -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -CF_EXTERN_C_BEGIN - -@class GPBMethod; -@class GPBMixin; -@class GPBOption; -@class GPBSourceContext; -GPB_ENUM_FWD_DECLARE(GPBSyntax); - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - GPBApiRoot - -/** - * Exposes the extension registry for this file. - * - * The base class provides: - * @code - * + (GPBExtensionRegistry *)extensionRegistry; - * @endcode - * which is a @c GPBExtensionRegistry that includes all the extensions defined by - * this file and all files that it depends on. - **/ -@interface GPBApiRoot : GPBRootObject -@end - -#pragma mark - GPBApi - -typedef GPB_ENUM(GPBApi_FieldNumber) { - GPBApi_FieldNumber_Name = 1, - GPBApi_FieldNumber_MethodsArray = 2, - GPBApi_FieldNumber_OptionsArray = 3, - GPBApi_FieldNumber_Version = 4, - GPBApi_FieldNumber_SourceContext = 5, - GPBApi_FieldNumber_MixinsArray = 6, - GPBApi_FieldNumber_Syntax = 7, -}; - -/** - * Api is a light-weight descriptor for an API Interface. - * - * Interfaces are also described as "protocol buffer services" in some contexts, - * such as by the "service" keyword in a .proto file, but they are different - * from API Services, which represent a concrete implementation of an interface - * as opposed to simply a description of methods and bindings. They are also - * sometimes simply referred to as "APIs" in other contexts, such as the name of - * this message itself. See https://cloud.google.com/apis/design/glossary for - * detailed terminology. - **/ -@interface GPBApi : GPBMessage - -/** - * The fully qualified name of this interface, including package name - * followed by the interface's simple name. - **/ -@property(nonatomic, readwrite, copy, null_resettable) NSString *name; - -/** The methods of this interface, in unspecified order. */ -@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *methodsArray; -/** The number of items in @c methodsArray without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger methodsArray_Count; - -/** Any metadata attached to the interface. */ -@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; -/** The number of items in @c optionsArray without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger optionsArray_Count; - -/** - * A version string for this interface. If specified, must have the form - * `major-version.minor-version`, as in `1.10`. If the minor version is - * omitted, it defaults to zero. If the entire version field is empty, the - * major version is derived from the package name, as outlined below. If the - * field is not empty, the version in the package name will be verified to be - * consistent with what is provided here. - * - * The versioning schema uses [semantic - * versioning](http://semver.org) where the major version number - * indicates a breaking change and the minor version an additive, - * non-breaking change. Both version numbers are signals to users - * what to expect from different versions, and should be carefully - * chosen based on the product plan. - * - * The major version is also reflected in the package name of the - * interface, which must end in `v`, as in - * `google.feature.v1`. For major versions 0 and 1, the suffix can - * be omitted. Zero major versions must only be used for - * experimental, non-GA interfaces. - **/ -@property(nonatomic, readwrite, copy, null_resettable) NSString *version; - -/** - * Source context for the protocol buffer service represented by this - * message. - **/ -@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; -/** Test to see if @c sourceContext has been set. */ -@property(nonatomic, readwrite) BOOL hasSourceContext; - -/** Included interfaces. See [Mixin][]. */ -@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *mixinsArray; -/** The number of items in @c mixinsArray without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger mixinsArray_Count; - -/** The source syntax of the service. */ -@property(nonatomic, readwrite) enum GPBSyntax syntax; - -@end - -/** - * Fetches the raw value of a @c GPBApi's @c syntax property, even - * if the value was not defined by the enum at the time the code was generated. - **/ -int32_t GPBApi_Syntax_RawValue(GPBApi *message); -/** - * Sets the raw value of an @c GPBApi's @c syntax property, allowing - * it to be set to a value that was not defined by the enum at the time the code - * was generated. - **/ -void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value); - -#pragma mark - GPBMethod - -typedef GPB_ENUM(GPBMethod_FieldNumber) { - GPBMethod_FieldNumber_Name = 1, - GPBMethod_FieldNumber_RequestTypeURL = 2, - GPBMethod_FieldNumber_RequestStreaming = 3, - GPBMethod_FieldNumber_ResponseTypeURL = 4, - GPBMethod_FieldNumber_ResponseStreaming = 5, - GPBMethod_FieldNumber_OptionsArray = 6, - GPBMethod_FieldNumber_Syntax = 7, -}; - -/** - * Method represents a method of an API interface. - **/ -@interface GPBMethod : GPBMessage - -/** The simple name of this method. */ -@property(nonatomic, readwrite, copy, null_resettable) NSString *name; - -/** A URL of the input message type. */ -@property(nonatomic, readwrite, copy, null_resettable) NSString *requestTypeURL; - -/** If true, the request is streamed. */ -@property(nonatomic, readwrite) BOOL requestStreaming; - -/** The URL of the output message type. */ -@property(nonatomic, readwrite, copy, null_resettable) NSString *responseTypeURL; - -/** If true, the response is streamed. */ -@property(nonatomic, readwrite) BOOL responseStreaming; - -/** Any metadata attached to the method. */ -@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; -/** The number of items in @c optionsArray without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger optionsArray_Count; - -/** The source syntax of this method. */ -@property(nonatomic, readwrite) enum GPBSyntax syntax; - -@end - -/** - * Fetches the raw value of a @c GPBMethod's @c syntax property, even - * if the value was not defined by the enum at the time the code was generated. - **/ -int32_t GPBMethod_Syntax_RawValue(GPBMethod *message); -/** - * Sets the raw value of an @c GPBMethod's @c syntax property, allowing - * it to be set to a value that was not defined by the enum at the time the code - * was generated. - **/ -void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value); - -#pragma mark - GPBMixin - -typedef GPB_ENUM(GPBMixin_FieldNumber) { - GPBMixin_FieldNumber_Name = 1, - GPBMixin_FieldNumber_Root = 2, -}; - -/** - * Declares an API Interface to be included in this interface. The including - * interface must redeclare all the methods from the included interface, but - * documentation and options are inherited as follows: - * - * - If after comment and whitespace stripping, the documentation - * string of the redeclared method is empty, it will be inherited - * from the original method. - * - * - Each annotation belonging to the service config (http, - * visibility) which is not set in the redeclared method will be - * inherited. - * - * - If an http annotation is inherited, the path pattern will be - * modified as follows. Any version prefix will be replaced by the - * version of the including interface plus the [root][] path if - * specified. - * - * Example of a simple mixin: - * - * package google.acl.v1; - * service AccessControl { - * // Get the underlying ACL object. - * rpc GetAcl(GetAclRequest) returns (Acl) { - * option (google.api.http).get = "/v1/{resource=**}:getAcl"; - * } - * } - * - * package google.storage.v2; - * service Storage { - * rpc GetAcl(GetAclRequest) returns (Acl); - * - * // Get a data record. - * rpc GetData(GetDataRequest) returns (Data) { - * option (google.api.http).get = "/v2/{resource=**}"; - * } - * } - * - * Example of a mixin configuration: - * - * apis: - * - name: google.storage.v2.Storage - * mixins: - * - name: google.acl.v1.AccessControl - * - * The mixin construct implies that all methods in `AccessControl` are - * also declared with same name and request/response types in - * `Storage`. A documentation generator or annotation processor will - * see the effective `Storage.GetAcl` method after inherting - * documentation and annotations as follows: - * - * service Storage { - * // Get the underlying ACL object. - * rpc GetAcl(GetAclRequest) returns (Acl) { - * option (google.api.http).get = "/v2/{resource=**}:getAcl"; - * } - * ... - * } - * - * Note how the version in the path pattern changed from `v1` to `v2`. - * - * If the `root` field in the mixin is specified, it should be a - * relative path under which inherited HTTP paths are placed. Example: - * - * apis: - * - name: google.storage.v2.Storage - * mixins: - * - name: google.acl.v1.AccessControl - * root: acls - * - * This implies the following inherited HTTP annotation: - * - * service Storage { - * // Get the underlying ACL object. - * rpc GetAcl(GetAclRequest) returns (Acl) { - * option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; - * } - * ... - * } - **/ -@interface GPBMixin : GPBMessage - -/** The fully qualified name of the interface which is included. */ -@property(nonatomic, readwrite, copy, null_resettable) NSString *name; - -/** - * If non-empty specifies a path under which inherited HTTP paths - * are rooted. - **/ -@property(nonatomic, readwrite, copy, null_resettable) NSString *root; - -@end - -NS_ASSUME_NONNULL_END - -CF_EXTERN_C_END - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) +// Moved to root of objectivec directory, shim to keep anyone's imports working. +#import "GPBApi.pbobjc.h" diff --git a/objectivec/google/protobuf/Api.pbobjc.m b/objectivec/google/protobuf/Api.pbobjc.m deleted file mode 100644 index 58b47157def59..0000000000000 --- a/objectivec/google/protobuf/Api.pbobjc.m +++ /dev/null @@ -1,356 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/api.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers_RuntimeSupport.h" -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import - #import - #import -#else - #import "google/protobuf/Api.pbobjc.h" - #import "google/protobuf/SourceContext.pbobjc.h" - #import "google/protobuf/Type.pbobjc.h" -#endif -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -#pragma mark - GPBApiRoot - -@implementation GPBApiRoot - -// No extensions in the file and none of the imports (direct or indirect) -// defined extensions, so no need to generate +extensionRegistry. - -@end - -#pragma mark - GPBApiRoot_FileDescriptor - -static GPBFileDescriptor *GPBApiRoot_FileDescriptor(void) { - // This is called by +initialize so there is no need to worry - // about thread safety of the singleton. - static GPBFileDescriptor *descriptor = NULL; - if (!descriptor) { - GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); - descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" - objcPrefix:@"GPB" - syntax:GPBFileSyntaxProto3]; - } - return descriptor; -} - -#pragma mark - GPBApi - -@implementation GPBApi - -@dynamic name; -@dynamic methodsArray, methodsArray_Count; -@dynamic optionsArray, optionsArray_Count; -@dynamic version; -@dynamic hasSourceContext, sourceContext; -@dynamic mixinsArray, mixinsArray_Count; -@dynamic syntax; - -typedef struct GPBApi__storage_ { - uint32_t _has_storage_[1]; - GPBSyntax syntax; - NSString *name; - NSMutableArray *methodsArray; - NSMutableArray *optionsArray; - NSString *version; - GPBSourceContext *sourceContext; - NSMutableArray *mixinsArray; -} GPBApi__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "name", - .dataTypeSpecific.className = NULL, - .number = GPBApi_FieldNumber_Name, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBApi__storage_, name), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - { - .name = "methodsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBMethod), - .number = GPBApi_FieldNumber_MethodsArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GPBApi__storage_, methodsArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeMessage, - }, - { - .name = "optionsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), - .number = GPBApi_FieldNumber_OptionsArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GPBApi__storage_, optionsArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeMessage, - }, - { - .name = "version", - .dataTypeSpecific.className = NULL, - .number = GPBApi_FieldNumber_Version, - .hasIndex = 1, - .offset = (uint32_t)offsetof(GPBApi__storage_, version), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - { - .name = "sourceContext", - .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), - .number = GPBApi_FieldNumber_SourceContext, - .hasIndex = 2, - .offset = (uint32_t)offsetof(GPBApi__storage_, sourceContext), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeMessage, - }, - { - .name = "mixinsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBMixin), - .number = GPBApi_FieldNumber_MixinsArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GPBApi__storage_, mixinsArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeMessage, - }, - { - .name = "syntax", - .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, - .number = GPBApi_FieldNumber_Syntax, - .hasIndex = 3, - .offset = (uint32_t)offsetof(GPBApi__storage_, syntax), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), - .dataType = GPBDataTypeEnum, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBApi class] - rootClass:[GPBApiRoot class] - file:GPBApiRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBApi__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -int32_t GPBApi_Syntax_RawValue(GPBApi *message) { - GPBDescriptor *descriptor = [GPBApi descriptor]; - GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax]; - return GPBGetMessageInt32Field(message, field); -} - -void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value) { - GPBDescriptor *descriptor = [GPBApi descriptor]; - GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax]; - GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); -} - -#pragma mark - GPBMethod - -@implementation GPBMethod - -@dynamic name; -@dynamic requestTypeURL; -@dynamic requestStreaming; -@dynamic responseTypeURL; -@dynamic responseStreaming; -@dynamic optionsArray, optionsArray_Count; -@dynamic syntax; - -typedef struct GPBMethod__storage_ { - uint32_t _has_storage_[1]; - GPBSyntax syntax; - NSString *name; - NSString *requestTypeURL; - NSString *responseTypeURL; - NSMutableArray *optionsArray; -} GPBMethod__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "name", - .dataTypeSpecific.className = NULL, - .number = GPBMethod_FieldNumber_Name, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBMethod__storage_, name), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - { - .name = "requestTypeURL", - .dataTypeSpecific.className = NULL, - .number = GPBMethod_FieldNumber_RequestTypeURL, - .hasIndex = 1, - .offset = (uint32_t)offsetof(GPBMethod__storage_, requestTypeURL), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), - .dataType = GPBDataTypeString, - }, - { - .name = "requestStreaming", - .dataTypeSpecific.className = NULL, - .number = GPBMethod_FieldNumber_RequestStreaming, - .hasIndex = 2, - .offset = 3, // Stored in _has_storage_ to save space. - .flags = GPBFieldOptional, - .dataType = GPBDataTypeBool, - }, - { - .name = "responseTypeURL", - .dataTypeSpecific.className = NULL, - .number = GPBMethod_FieldNumber_ResponseTypeURL, - .hasIndex = 4, - .offset = (uint32_t)offsetof(GPBMethod__storage_, responseTypeURL), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), - .dataType = GPBDataTypeString, - }, - { - .name = "responseStreaming", - .dataTypeSpecific.className = NULL, - .number = GPBMethod_FieldNumber_ResponseStreaming, - .hasIndex = 5, - .offset = 6, // Stored in _has_storage_ to save space. - .flags = GPBFieldOptional, - .dataType = GPBDataTypeBool, - }, - { - .name = "optionsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), - .number = GPBMethod_FieldNumber_OptionsArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GPBMethod__storage_, optionsArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeMessage, - }, - { - .name = "syntax", - .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, - .number = GPBMethod_FieldNumber_Syntax, - .hasIndex = 7, - .offset = (uint32_t)offsetof(GPBMethod__storage_, syntax), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), - .dataType = GPBDataTypeEnum, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBMethod class] - rootClass:[GPBApiRoot class] - file:GPBApiRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBMethod__storage_) - flags:GPBDescriptorInitializationFlag_None]; -#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS - static const char *extraTextFormatInfo = - "\002\002\007\244\241!!\000\004\010\244\241!!\000"; - [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; -#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -int32_t GPBMethod_Syntax_RawValue(GPBMethod *message) { - GPBDescriptor *descriptor = [GPBMethod descriptor]; - GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax]; - return GPBGetMessageInt32Field(message, field); -} - -void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value) { - GPBDescriptor *descriptor = [GPBMethod descriptor]; - GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax]; - GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); -} - -#pragma mark - GPBMixin - -@implementation GPBMixin - -@dynamic name; -@dynamic root; - -typedef struct GPBMixin__storage_ { - uint32_t _has_storage_[1]; - NSString *name; - NSString *root; -} GPBMixin__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "name", - .dataTypeSpecific.className = NULL, - .number = GPBMixin_FieldNumber_Name, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBMixin__storage_, name), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - { - .name = "root", - .dataTypeSpecific.className = NULL, - .number = GPBMixin_FieldNumber_Root, - .hasIndex = 1, - .offset = (uint32_t)offsetof(GPBMixin__storage_, root), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBMixin class] - rootClass:[GPBApiRoot class] - file:GPBApiRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBMixin__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Duration.pbobjc.h b/objectivec/google/protobuf/Duration.pbobjc.h index d9a388ac1b287..fabf00f413d1e 100644 --- a/objectivec/google/protobuf/Duration.pbobjc.h +++ b/objectivec/google/protobuf/Duration.pbobjc.h @@ -1,141 +1,2 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/duration.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers.h" -#endif - -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 -#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. -#endif -#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION -#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. -#endif - -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -CF_EXTERN_C_BEGIN - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - GPBDurationRoot - -/** - * Exposes the extension registry for this file. - * - * The base class provides: - * @code - * + (GPBExtensionRegistry *)extensionRegistry; - * @endcode - * which is a @c GPBExtensionRegistry that includes all the extensions defined by - * this file and all files that it depends on. - **/ -@interface GPBDurationRoot : GPBRootObject -@end - -#pragma mark - GPBDuration - -typedef GPB_ENUM(GPBDuration_FieldNumber) { - GPBDuration_FieldNumber_Seconds = 1, - GPBDuration_FieldNumber_Nanos = 2, -}; - -/** - * A Duration represents a signed, fixed-length span of time represented - * as a count of seconds and fractions of seconds at nanosecond - * resolution. It is independent of any calendar and concepts like "day" - * or "month". It is related to Timestamp in that the difference between - * two Timestamp values is a Duration and it can be added or subtracted - * from a Timestamp. Range is approximately +-10,000 years. - * - * # Examples - * - * Example 1: Compute Duration from two Timestamps in pseudo code. - * - * Timestamp start = ...; - * Timestamp end = ...; - * Duration duration = ...; - * - * duration.seconds = end.seconds - start.seconds; - * duration.nanos = end.nanos - start.nanos; - * - * if (duration.seconds < 0 && duration.nanos > 0) { - * duration.seconds += 1; - * duration.nanos -= 1000000000; - * } else if (durations.seconds > 0 && duration.nanos < 0) { - * duration.seconds -= 1; - * duration.nanos += 1000000000; - * } - * - * Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. - * - * Timestamp start = ...; - * Duration duration = ...; - * Timestamp end = ...; - * - * end.seconds = start.seconds + duration.seconds; - * end.nanos = start.nanos + duration.nanos; - * - * if (end.nanos < 0) { - * end.seconds -= 1; - * end.nanos += 1000000000; - * } else if (end.nanos >= 1000000000) { - * end.seconds += 1; - * end.nanos -= 1000000000; - * } - * - * Example 3: Compute Duration from datetime.timedelta in Python. - * - * td = datetime.timedelta(days=3, minutes=10) - * duration = Duration() - * duration.FromTimedelta(td) - * - * # JSON Mapping - * - * In JSON format, the Duration type is encoded as a string rather than an - * object, where the string ends in the suffix "s" (indicating seconds) and - * is preceded by the number of seconds, with nanoseconds expressed as - * fractional seconds. For example, 3 seconds with 0 nanoseconds should be - * encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should - * be expressed in JSON format as "3.000000001s", and 3 seconds and 1 - * microsecond should be expressed in JSON format as "3.000001s". - **/ -@interface GPBDuration : GPBMessage - -/** - * Signed seconds of the span of time. Must be from -315,576,000,000 - * to +315,576,000,000 inclusive. Note: these bounds are computed from: - * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years - **/ -@property(nonatomic, readwrite) int64_t seconds; - -/** - * Signed fractions of a second at nanosecond resolution of the span - * of time. Durations less than one second are represented with a 0 - * `seconds` field and a positive or negative `nanos` field. For durations - * of one second or more, a non-zero value for the `nanos` field must be - * of the same sign as the `seconds` field. Must be from -999,999,999 - * to +999,999,999 inclusive. - **/ -@property(nonatomic, readwrite) int32_t nanos; - -@end - -NS_ASSUME_NONNULL_END - -CF_EXTERN_C_END - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) +// Moved to root of objectivec directory, shim to keep anyone's imports working. +#import "GPBDuration.pbobjc.h" diff --git a/objectivec/google/protobuf/Duration.pbobjc.m b/objectivec/google/protobuf/Duration.pbobjc.m deleted file mode 100644 index bafb64a04f643..0000000000000 --- a/objectivec/google/protobuf/Duration.pbobjc.m +++ /dev/null @@ -1,107 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/duration.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers_RuntimeSupport.h" -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "google/protobuf/Duration.pbobjc.h" -#endif -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -#pragma mark - GPBDurationRoot - -@implementation GPBDurationRoot - -// No extensions in the file and no imports, so no need to generate -// +extensionRegistry. - -@end - -#pragma mark - GPBDurationRoot_FileDescriptor - -static GPBFileDescriptor *GPBDurationRoot_FileDescriptor(void) { - // This is called by +initialize so there is no need to worry - // about thread safety of the singleton. - static GPBFileDescriptor *descriptor = NULL; - if (!descriptor) { - GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); - descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" - objcPrefix:@"GPB" - syntax:GPBFileSyntaxProto3]; - } - return descriptor; -} - -#pragma mark - GPBDuration - -@implementation GPBDuration - -@dynamic seconds; -@dynamic nanos; - -typedef struct GPBDuration__storage_ { - uint32_t _has_storage_[1]; - int32_t nanos; - int64_t seconds; -} GPBDuration__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "seconds", - .dataTypeSpecific.className = NULL, - .number = GPBDuration_FieldNumber_Seconds, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBDuration__storage_, seconds), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeInt64, - }, - { - .name = "nanos", - .dataTypeSpecific.className = NULL, - .number = GPBDuration_FieldNumber_Nanos, - .hasIndex = 1, - .offset = (uint32_t)offsetof(GPBDuration__storage_, nanos), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeInt32, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBDuration class] - rootClass:[GPBDurationRoot class] - file:GPBDurationRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBDuration__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Empty.pbobjc.h b/objectivec/google/protobuf/Empty.pbobjc.h index bd49cfdbc3d09..4de910870aa15 100644 --- a/objectivec/google/protobuf/Empty.pbobjc.h +++ b/objectivec/google/protobuf/Empty.pbobjc.h @@ -1,70 +1,2 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/empty.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers.h" -#endif - -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 -#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. -#endif -#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION -#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. -#endif - -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -CF_EXTERN_C_BEGIN - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - GPBEmptyRoot - -/** - * Exposes the extension registry for this file. - * - * The base class provides: - * @code - * + (GPBExtensionRegistry *)extensionRegistry; - * @endcode - * which is a @c GPBExtensionRegistry that includes all the extensions defined by - * this file and all files that it depends on. - **/ -@interface GPBEmptyRoot : GPBRootObject -@end - -#pragma mark - GPBEmpty - -/** - * A generic empty message that you can re-use to avoid defining duplicated - * empty messages in your APIs. A typical example is to use it as the request - * or the response type of an API method. For instance: - * - * service Foo { - * rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); - * } - * - * The JSON representation for `Empty` is empty JSON object `{}`. - **/ -@interface GPBEmpty : GPBMessage - -@end - -NS_ASSUME_NONNULL_END - -CF_EXTERN_C_END - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) +// Moved to root of objectivec directory, shim to keep anyone's imports working. +#import "GPBEmpty.pbobjc.h" diff --git a/objectivec/google/protobuf/Empty.pbobjc.m b/objectivec/google/protobuf/Empty.pbobjc.m deleted file mode 100644 index 506b500e0490c..0000000000000 --- a/objectivec/google/protobuf/Empty.pbobjc.m +++ /dev/null @@ -1,83 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/empty.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers_RuntimeSupport.h" -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "google/protobuf/Empty.pbobjc.h" -#endif -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -#pragma mark - GPBEmptyRoot - -@implementation GPBEmptyRoot - -// No extensions in the file and no imports, so no need to generate -// +extensionRegistry. - -@end - -#pragma mark - GPBEmptyRoot_FileDescriptor - -static GPBFileDescriptor *GPBEmptyRoot_FileDescriptor(void) { - // This is called by +initialize so there is no need to worry - // about thread safety of the singleton. - static GPBFileDescriptor *descriptor = NULL; - if (!descriptor) { - GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); - descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" - objcPrefix:@"GPB" - syntax:GPBFileSyntaxProto3]; - } - return descriptor; -} - -#pragma mark - GPBEmpty - -@implementation GPBEmpty - - -typedef struct GPBEmpty__storage_ { - uint32_t _has_storage_[1]; -} GPBEmpty__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBEmpty class] - rootClass:[GPBEmptyRoot class] - file:GPBEmptyRoot_FileDescriptor() - fields:NULL - fieldCount:0 - storageSize:sizeof(GPBEmpty__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.h b/objectivec/google/protobuf/FieldMask.pbobjc.h index 07e60818522d0..26913200467ae 100644 --- a/objectivec/google/protobuf/FieldMask.pbobjc.h +++ b/objectivec/google/protobuf/FieldMask.pbobjc.h @@ -1,271 +1,2 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/field_mask.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers.h" -#endif - -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 -#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. -#endif -#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION -#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. -#endif - -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -CF_EXTERN_C_BEGIN - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - GPBFieldMaskRoot - -/** - * Exposes the extension registry for this file. - * - * The base class provides: - * @code - * + (GPBExtensionRegistry *)extensionRegistry; - * @endcode - * which is a @c GPBExtensionRegistry that includes all the extensions defined by - * this file and all files that it depends on. - **/ -@interface GPBFieldMaskRoot : GPBRootObject -@end - -#pragma mark - GPBFieldMask - -typedef GPB_ENUM(GPBFieldMask_FieldNumber) { - GPBFieldMask_FieldNumber_PathsArray = 1, -}; - -/** - * `FieldMask` represents a set of symbolic field paths, for example: - * - * paths: "f.a" - * paths: "f.b.d" - * - * Here `f` represents a field in some root message, `a` and `b` - * fields in the message found in `f`, and `d` a field found in the - * message in `f.b`. - * - * Field masks are used to specify a subset of fields that should be - * returned by a get operation or modified by an update operation. - * Field masks also have a custom JSON encoding (see below). - * - * # Field Masks in Projections - * - * When used in the context of a projection, a response message or - * sub-message is filtered by the API to only contain those fields as - * specified in the mask. For example, if the mask in the previous - * example is applied to a response message as follows: - * - * f { - * a : 22 - * b { - * d : 1 - * x : 2 - * } - * y : 13 - * } - * z: 8 - * - * The result will not contain specific values for fields x,y and z - * (their value will be set to the default, and omitted in proto text - * output): - * - * - * f { - * a : 22 - * b { - * d : 1 - * } - * } - * - * A repeated field is not allowed except at the last position of a - * paths string. - * - * If a FieldMask object is not present in a get operation, the - * operation applies to all fields (as if a FieldMask of all fields - * had been specified). - * - * Note that a field mask does not necessarily apply to the - * top-level response message. In case of a REST get operation, the - * field mask applies directly to the response, but in case of a REST - * list operation, the mask instead applies to each individual message - * in the returned resource list. In case of a REST custom method, - * other definitions may be used. Where the mask applies will be - * clearly documented together with its declaration in the API. In - * any case, the effect on the returned resource/resources is required - * behavior for APIs. - * - * # Field Masks in Update Operations - * - * A field mask in update operations specifies which fields of the - * targeted resource are going to be updated. The API is required - * to only change the values of the fields as specified in the mask - * and leave the others untouched. If a resource is passed in to - * describe the updated values, the API ignores the values of all - * fields not covered by the mask. - * - * If a repeated field is specified for an update operation, the existing - * repeated values in the target resource will be overwritten by the new values. - * Note that a repeated field is only allowed in the last position of a `paths` - * string. - * - * If a sub-message is specified in the last position of the field mask for an - * update operation, then the existing sub-message in the target resource is - * overwritten. Given the target message: - * - * f { - * b { - * d : 1 - * x : 2 - * } - * c : 1 - * } - * - * And an update message: - * - * f { - * b { - * d : 10 - * } - * } - * - * then if the field mask is: - * - * paths: "f.b" - * - * then the result will be: - * - * f { - * b { - * d : 10 - * } - * c : 1 - * } - * - * However, if the update mask was: - * - * paths: "f.b.d" - * - * then the result would be: - * - * f { - * b { - * d : 10 - * x : 2 - * } - * c : 1 - * } - * - * In order to reset a field's value to the default, the field must - * be in the mask and set to the default value in the provided resource. - * Hence, in order to reset all fields of a resource, provide a default - * instance of the resource and set all fields in the mask, or do - * not provide a mask as described below. - * - * If a field mask is not present on update, the operation applies to - * all fields (as if a field mask of all fields has been specified). - * Note that in the presence of schema evolution, this may mean that - * fields the client does not know and has therefore not filled into - * the request will be reset to their default. If this is unwanted - * behavior, a specific service may require a client to always specify - * a field mask, producing an error if not. - * - * As with get operations, the location of the resource which - * describes the updated values in the request message depends on the - * operation kind. In any case, the effect of the field mask is - * required to be honored by the API. - * - * ## Considerations for HTTP REST - * - * The HTTP kind of an update operation which uses a field mask must - * be set to PATCH instead of PUT in order to satisfy HTTP semantics - * (PUT must only be used for full updates). - * - * # JSON Encoding of Field Masks - * - * In JSON, a field mask is encoded as a single string where paths are - * separated by a comma. Fields name in each path are converted - * to/from lower-camel naming conventions. - * - * As an example, consider the following message declarations: - * - * message Profile { - * User user = 1; - * Photo photo = 2; - * } - * message User { - * string display_name = 1; - * string address = 2; - * } - * - * In proto a field mask for `Profile` may look as such: - * - * mask { - * paths: "user.display_name" - * paths: "photo" - * } - * - * In JSON, the same mask is represented as below: - * - * { - * mask: "user.displayName,photo" - * } - * - * # Field Masks and Oneof Fields - * - * Field masks treat fields in oneofs just as regular fields. Consider the - * following message: - * - * message SampleMessage { - * oneof test_oneof { - * string name = 4; - * SubMessage sub_message = 9; - * } - * } - * - * The field mask can be: - * - * mask { - * paths: "name" - * } - * - * Or: - * - * mask { - * paths: "sub_message" - * } - * - * Note that oneof type names ("test_oneof" in this case) cannot be used in - * paths. - **/ -@interface GPBFieldMask : GPBMessage - -/** The set of field mask paths. */ -@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *pathsArray; -/** The number of items in @c pathsArray without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger pathsArray_Count; - -@end - -NS_ASSUME_NONNULL_END - -CF_EXTERN_C_END - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) +// Moved to root of objectivec directory, shim to keep anyone's imports working. +#import "GPBFieldMask.pbobjc.h" diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.m b/objectivec/google/protobuf/FieldMask.pbobjc.m deleted file mode 100644 index b0915af4502d6..0000000000000 --- a/objectivec/google/protobuf/FieldMask.pbobjc.m +++ /dev/null @@ -1,96 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/field_mask.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers_RuntimeSupport.h" -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "google/protobuf/FieldMask.pbobjc.h" -#endif -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -#pragma mark - GPBFieldMaskRoot - -@implementation GPBFieldMaskRoot - -// No extensions in the file and no imports, so no need to generate -// +extensionRegistry. - -@end - -#pragma mark - GPBFieldMaskRoot_FileDescriptor - -static GPBFileDescriptor *GPBFieldMaskRoot_FileDescriptor(void) { - // This is called by +initialize so there is no need to worry - // about thread safety of the singleton. - static GPBFileDescriptor *descriptor = NULL; - if (!descriptor) { - GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); - descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" - objcPrefix:@"GPB" - syntax:GPBFileSyntaxProto3]; - } - return descriptor; -} - -#pragma mark - GPBFieldMask - -@implementation GPBFieldMask - -@dynamic pathsArray, pathsArray_Count; - -typedef struct GPBFieldMask__storage_ { - uint32_t _has_storage_[1]; - NSMutableArray *pathsArray; -} GPBFieldMask__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "pathsArray", - .dataTypeSpecific.className = NULL, - .number = GPBFieldMask_FieldNumber_PathsArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GPBFieldMask__storage_, pathsArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeString, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBFieldMask class] - rootClass:[GPBFieldMaskRoot class] - file:GPBFieldMaskRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBFieldMask__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.h b/objectivec/google/protobuf/SourceContext.pbobjc.h index 799d190ac60f6..321dfec993b21 100644 --- a/objectivec/google/protobuf/SourceContext.pbobjc.h +++ b/objectivec/google/protobuf/SourceContext.pbobjc.h @@ -1,73 +1,2 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/source_context.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers.h" -#endif - -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 -#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. -#endif -#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION -#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. -#endif - -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -CF_EXTERN_C_BEGIN - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - GPBSourceContextRoot - -/** - * Exposes the extension registry for this file. - * - * The base class provides: - * @code - * + (GPBExtensionRegistry *)extensionRegistry; - * @endcode - * which is a @c GPBExtensionRegistry that includes all the extensions defined by - * this file and all files that it depends on. - **/ -@interface GPBSourceContextRoot : GPBRootObject -@end - -#pragma mark - GPBSourceContext - -typedef GPB_ENUM(GPBSourceContext_FieldNumber) { - GPBSourceContext_FieldNumber_FileName = 1, -}; - -/** - * `SourceContext` represents information about the source of a - * protobuf element, like the file in which it is defined. - **/ -@interface GPBSourceContext : GPBMessage - -/** - * The path-qualified name of the .proto file that contained the associated - * protobuf element. For example: `"google/protobuf/source_context.proto"`. - **/ -@property(nonatomic, readwrite, copy, null_resettable) NSString *fileName; - -@end - -NS_ASSUME_NONNULL_END - -CF_EXTERN_C_END - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) +// Moved to root of objectivec directory, shim to keep anyone's imports working. +#import "GPBSourceContext.pbobjc.h" diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.m b/objectivec/google/protobuf/SourceContext.pbobjc.m deleted file mode 100644 index 83bfa3460bba6..0000000000000 --- a/objectivec/google/protobuf/SourceContext.pbobjc.m +++ /dev/null @@ -1,96 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/source_context.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers_RuntimeSupport.h" -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "google/protobuf/SourceContext.pbobjc.h" -#endif -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -#pragma mark - GPBSourceContextRoot - -@implementation GPBSourceContextRoot - -// No extensions in the file and no imports, so no need to generate -// +extensionRegistry. - -@end - -#pragma mark - GPBSourceContextRoot_FileDescriptor - -static GPBFileDescriptor *GPBSourceContextRoot_FileDescriptor(void) { - // This is called by +initialize so there is no need to worry - // about thread safety of the singleton. - static GPBFileDescriptor *descriptor = NULL; - if (!descriptor) { - GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); - descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" - objcPrefix:@"GPB" - syntax:GPBFileSyntaxProto3]; - } - return descriptor; -} - -#pragma mark - GPBSourceContext - -@implementation GPBSourceContext - -@dynamic fileName; - -typedef struct GPBSourceContext__storage_ { - uint32_t _has_storage_[1]; - NSString *fileName; -} GPBSourceContext__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "fileName", - .dataTypeSpecific.className = NULL, - .number = GPBSourceContext_FieldNumber_FileName, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBSourceContext__storage_, fileName), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBSourceContext class] - rootClass:[GPBSourceContextRoot class] - file:GPBSourceContextRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBSourceContext__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Struct.pbobjc.h b/objectivec/google/protobuf/Struct.pbobjc.h index 3fc80caa5ab19..1173d16fac609 100644 --- a/objectivec/google/protobuf/Struct.pbobjc.h +++ b/objectivec/google/protobuf/Struct.pbobjc.h @@ -1,200 +1,2 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/struct.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers.h" -#endif - -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 -#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. -#endif -#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION -#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. -#endif - -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -CF_EXTERN_C_BEGIN - -@class GPBListValue; -@class GPBStruct; -@class GPBValue; - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - Enum GPBNullValue - -/** - * `NullValue` is a singleton enumeration to represent the null value for the - * `Value` type union. - * - * The JSON representation for `NullValue` is JSON `null`. - **/ -typedef GPB_ENUM(GPBNullValue) { - /** - * Value used if any message's field encounters a value that is not defined - * by this enum. The message will also have C functions to get/set the rawValue - * of the field. - **/ - GPBNullValue_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, - /** Null value. */ - GPBNullValue_NullValue = 0, -}; - -GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void); - -/** - * Checks to see if the given value is defined by the enum or was not known at - * the time this source was generated. - **/ -BOOL GPBNullValue_IsValidValue(int32_t value); - -#pragma mark - GPBStructRoot - -/** - * Exposes the extension registry for this file. - * - * The base class provides: - * @code - * + (GPBExtensionRegistry *)extensionRegistry; - * @endcode - * which is a @c GPBExtensionRegistry that includes all the extensions defined by - * this file and all files that it depends on. - **/ -@interface GPBStructRoot : GPBRootObject -@end - -#pragma mark - GPBStruct - -typedef GPB_ENUM(GPBStruct_FieldNumber) { - GPBStruct_FieldNumber_Fields = 1, -}; - -/** - * `Struct` represents a structured data value, consisting of fields - * which map to dynamically typed values. In some languages, `Struct` - * might be supported by a native representation. For example, in - * scripting languages like JS a struct is represented as an - * object. The details of that representation are described together - * with the proto support for the language. - * - * The JSON representation for `Struct` is JSON object. - **/ -@interface GPBStruct : GPBMessage - -/** Unordered map of dynamically typed values. */ -@property(nonatomic, readwrite, strong, null_resettable) NSMutableDictionary *fields; -/** The number of items in @c fields without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger fields_Count; - -@end - -#pragma mark - GPBValue - -typedef GPB_ENUM(GPBValue_FieldNumber) { - GPBValue_FieldNumber_NullValue = 1, - GPBValue_FieldNumber_NumberValue = 2, - GPBValue_FieldNumber_StringValue = 3, - GPBValue_FieldNumber_BoolValue = 4, - GPBValue_FieldNumber_StructValue = 5, - GPBValue_FieldNumber_ListValue = 6, -}; - -typedef GPB_ENUM(GPBValue_Kind_OneOfCase) { - GPBValue_Kind_OneOfCase_GPBUnsetOneOfCase = 0, - GPBValue_Kind_OneOfCase_NullValue = 1, - GPBValue_Kind_OneOfCase_NumberValue = 2, - GPBValue_Kind_OneOfCase_StringValue = 3, - GPBValue_Kind_OneOfCase_BoolValue = 4, - GPBValue_Kind_OneOfCase_StructValue = 5, - GPBValue_Kind_OneOfCase_ListValue = 6, -}; - -/** - * `Value` represents a dynamically typed value which can be either - * null, a number, a string, a boolean, a recursive struct value, or a - * list of values. A producer of value is expected to set one of that - * variants, absence of any variant indicates an error. - * - * The JSON representation for `Value` is JSON value. - **/ -@interface GPBValue : GPBMessage - -/** The kind of value. */ -@property(nonatomic, readonly) GPBValue_Kind_OneOfCase kindOneOfCase; - -/** Represents a null value. */ -@property(nonatomic, readwrite) GPBNullValue nullValue; - -/** Represents a double value. */ -@property(nonatomic, readwrite) double numberValue; - -/** Represents a string value. */ -@property(nonatomic, readwrite, copy, null_resettable) NSString *stringValue; - -/** Represents a boolean value. */ -@property(nonatomic, readwrite) BOOL boolValue; - -/** Represents a structured value. */ -@property(nonatomic, readwrite, strong, null_resettable) GPBStruct *structValue; - -/** Represents a repeated `Value`. */ -@property(nonatomic, readwrite, strong, null_resettable) GPBListValue *listValue; - -@end - -/** - * Fetches the raw value of a @c GPBValue's @c nullValue property, even - * if the value was not defined by the enum at the time the code was generated. - **/ -int32_t GPBValue_NullValue_RawValue(GPBValue *message); -/** - * Sets the raw value of an @c GPBValue's @c nullValue property, allowing - * it to be set to a value that was not defined by the enum at the time the code - * was generated. - **/ -void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value); - -/** - * Clears whatever value was set for the oneof 'kind'. - **/ -void GPBValue_ClearKindOneOfCase(GPBValue *message); - -#pragma mark - GPBListValue - -typedef GPB_ENUM(GPBListValue_FieldNumber) { - GPBListValue_FieldNumber_ValuesArray = 1, -}; - -/** - * `ListValue` is a wrapper around a repeated field of values. - * - * The JSON representation for `ListValue` is JSON array. - **/ -@interface GPBListValue : GPBMessage - -/** Repeated field of dynamically typed values. */ -@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *valuesArray; -/** The number of items in @c valuesArray without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger valuesArray_Count; - -@end - -NS_ASSUME_NONNULL_END - -CF_EXTERN_C_END - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) +// Moved to root of objectivec directory, shim to keep anyone's imports working. +#import "GPBStruct.pbobjc.h" diff --git a/objectivec/google/protobuf/Struct.pbobjc.m b/objectivec/google/protobuf/Struct.pbobjc.m deleted file mode 100644 index f36ec582f9805..0000000000000 --- a/objectivec/google/protobuf/Struct.pbobjc.m +++ /dev/null @@ -1,293 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/struct.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers_RuntimeSupport.h" -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "google/protobuf/Struct.pbobjc.h" -#endif -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -#pragma clang diagnostic ignored "-Wdirect-ivar-access" - -#pragma mark - GPBStructRoot - -@implementation GPBStructRoot - -// No extensions in the file and no imports, so no need to generate -// +extensionRegistry. - -@end - -#pragma mark - GPBStructRoot_FileDescriptor - -static GPBFileDescriptor *GPBStructRoot_FileDescriptor(void) { - // This is called by +initialize so there is no need to worry - // about thread safety of the singleton. - static GPBFileDescriptor *descriptor = NULL; - if (!descriptor) { - GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); - descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" - objcPrefix:@"GPB" - syntax:GPBFileSyntaxProto3]; - } - return descriptor; -} - -#pragma mark - Enum GPBNullValue - -GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void) { - static GPBEnumDescriptor *descriptor = NULL; - if (!descriptor) { - static const char *valueNames = - "NullValue\000"; - static const int32_t values[] = { - GPBNullValue_NullValue, - }; - GPBEnumDescriptor *worker = - [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBNullValue) - valueNames:valueNames - values:values - count:(uint32_t)(sizeof(values) / sizeof(int32_t)) - enumVerifier:GPBNullValue_IsValidValue]; - if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { - [worker release]; - } - } - return descriptor; -} - -BOOL GPBNullValue_IsValidValue(int32_t value__) { - switch (value__) { - case GPBNullValue_NullValue: - return YES; - default: - return NO; - } -} - -#pragma mark - GPBStruct - -@implementation GPBStruct - -@dynamic fields, fields_Count; - -typedef struct GPBStruct__storage_ { - uint32_t _has_storage_[1]; - NSMutableDictionary *fields; -} GPBStruct__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "fields", - .dataTypeSpecific.className = GPBStringifySymbol(GPBValue), - .number = GPBStruct_FieldNumber_Fields, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GPBStruct__storage_, fields), - .flags = GPBFieldMapKeyString, - .dataType = GPBDataTypeMessage, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBStruct class] - rootClass:[GPBStructRoot class] - file:GPBStructRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBStruct__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -#pragma mark - GPBValue - -@implementation GPBValue - -@dynamic kindOneOfCase; -@dynamic nullValue; -@dynamic numberValue; -@dynamic stringValue; -@dynamic boolValue; -@dynamic structValue; -@dynamic listValue; - -typedef struct GPBValue__storage_ { - uint32_t _has_storage_[2]; - GPBNullValue nullValue; - NSString *stringValue; - GPBStruct *structValue; - GPBListValue *listValue; - double numberValue; -} GPBValue__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "nullValue", - .dataTypeSpecific.enumDescFunc = GPBNullValue_EnumDescriptor, - .number = GPBValue_FieldNumber_NullValue, - .hasIndex = -1, - .offset = (uint32_t)offsetof(GPBValue__storage_, nullValue), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), - .dataType = GPBDataTypeEnum, - }, - { - .name = "numberValue", - .dataTypeSpecific.className = NULL, - .number = GPBValue_FieldNumber_NumberValue, - .hasIndex = -1, - .offset = (uint32_t)offsetof(GPBValue__storage_, numberValue), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeDouble, - }, - { - .name = "stringValue", - .dataTypeSpecific.className = NULL, - .number = GPBValue_FieldNumber_StringValue, - .hasIndex = -1, - .offset = (uint32_t)offsetof(GPBValue__storage_, stringValue), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - { - .name = "boolValue", - .dataTypeSpecific.className = NULL, - .number = GPBValue_FieldNumber_BoolValue, - .hasIndex = -1, - .offset = 0, // Stored in _has_storage_ to save space. - .flags = GPBFieldOptional, - .dataType = GPBDataTypeBool, - }, - { - .name = "structValue", - .dataTypeSpecific.className = GPBStringifySymbol(GPBStruct), - .number = GPBValue_FieldNumber_StructValue, - .hasIndex = -1, - .offset = (uint32_t)offsetof(GPBValue__storage_, structValue), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeMessage, - }, - { - .name = "listValue", - .dataTypeSpecific.className = GPBStringifySymbol(GPBListValue), - .number = GPBValue_FieldNumber_ListValue, - .hasIndex = -1, - .offset = (uint32_t)offsetof(GPBValue__storage_, listValue), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeMessage, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBValue class] - rootClass:[GPBStructRoot class] - file:GPBStructRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; - static const char *oneofs[] = { - "kind", - }; - [localDescriptor setupOneofs:oneofs - count:(uint32_t)(sizeof(oneofs) / sizeof(char*)) - firstHasIndex:-1]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -int32_t GPBValue_NullValue_RawValue(GPBValue *message) { - GPBDescriptor *descriptor = [GPBValue descriptor]; - GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue]; - return GPBGetMessageInt32Field(message, field); -} - -void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value) { - GPBDescriptor *descriptor = [GPBValue descriptor]; - GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue]; - GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); -} - -void GPBValue_ClearKindOneOfCase(GPBValue *message) { - GPBDescriptor *descriptor = [message descriptor]; - GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; - GPBMaybeClearOneof(message, oneof, -1, 0); -} -#pragma mark - GPBListValue - -@implementation GPBListValue - -@dynamic valuesArray, valuesArray_Count; - -typedef struct GPBListValue__storage_ { - uint32_t _has_storage_[1]; - NSMutableArray *valuesArray; -} GPBListValue__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "valuesArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBValue), - .number = GPBListValue_FieldNumber_ValuesArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GPBListValue__storage_, valuesArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeMessage, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBListValue class] - rootClass:[GPBStructRoot class] - file:GPBStructRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBListValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.h b/objectivec/google/protobuf/Timestamp.pbobjc.h index 5d74bd3274a2a..6a7cef84492ae 100644 --- a/objectivec/google/protobuf/Timestamp.pbobjc.h +++ b/objectivec/google/protobuf/Timestamp.pbobjc.h @@ -1,157 +1,2 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/timestamp.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers.h" -#endif - -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 -#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. -#endif -#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION -#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. -#endif - -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -CF_EXTERN_C_BEGIN - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - GPBTimestampRoot - -/** - * Exposes the extension registry for this file. - * - * The base class provides: - * @code - * + (GPBExtensionRegistry *)extensionRegistry; - * @endcode - * which is a @c GPBExtensionRegistry that includes all the extensions defined by - * this file and all files that it depends on. - **/ -@interface GPBTimestampRoot : GPBRootObject -@end - -#pragma mark - GPBTimestamp - -typedef GPB_ENUM(GPBTimestamp_FieldNumber) { - GPBTimestamp_FieldNumber_Seconds = 1, - GPBTimestamp_FieldNumber_Nanos = 2, -}; - -/** - * A Timestamp represents a point in time independent of any time zone - * or calendar, represented as seconds and fractions of seconds at - * nanosecond resolution in UTC Epoch time. It is encoded using the - * Proleptic Gregorian Calendar which extends the Gregorian calendar - * backwards to year one. It is encoded assuming all minutes are 60 - * seconds long, i.e. leap seconds are "smeared" so that no leap second - * table is needed for interpretation. Range is from - * 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. - * By restricting to that range, we ensure that we can convert to - * and from RFC 3339 date strings. - * See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). - * - * # Examples - * - * Example 1: Compute Timestamp from POSIX `time()`. - * - * Timestamp timestamp; - * timestamp.set_seconds(time(NULL)); - * timestamp.set_nanos(0); - * - * Example 2: Compute Timestamp from POSIX `gettimeofday()`. - * - * struct timeval tv; - * gettimeofday(&tv, NULL); - * - * Timestamp timestamp; - * timestamp.set_seconds(tv.tv_sec); - * timestamp.set_nanos(tv.tv_usec * 1000); - * - * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. - * - * FILETIME ft; - * GetSystemTimeAsFileTime(&ft); - * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; - * - * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z - * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. - * Timestamp timestamp; - * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); - * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); - * - * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. - * - * long millis = System.currentTimeMillis(); - * - * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) - * .setNanos((int) ((millis % 1000) * 1000000)).build(); - * - * - * Example 5: Compute Timestamp from current time in Python. - * - * timestamp = Timestamp() - * timestamp.GetCurrentTime() - * - * # JSON Mapping - * - * In JSON format, the Timestamp type is encoded as a string in the - * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the - * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" - * where {year} is always expressed using four digits while {month}, {day}, - * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional - * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), - * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone - * is required, though only UTC (as indicated by "Z") is presently supported. - * - * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past - * 01:30 UTC on January 15, 2017. - * - * In JavaScript, one can convert a Date object to this format using the - * standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString] - * method. In Python, a standard `datetime.datetime` object can be converted - * to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) - * with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one - * can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( - * http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()) - * to obtain a formatter capable of generating timestamps in this format. - **/ -@interface GPBTimestamp : GPBMessage - -/** - * Represents seconds of UTC time since Unix epoch - * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - * 9999-12-31T23:59:59Z inclusive. - **/ -@property(nonatomic, readwrite) int64_t seconds; - -/** - * Non-negative fractions of a second at nanosecond resolution. Negative - * second values with fractions must still have non-negative nanos values - * that count forward in time. Must be from 0 to 999,999,999 - * inclusive. - **/ -@property(nonatomic, readwrite) int32_t nanos; - -@end - -NS_ASSUME_NONNULL_END - -CF_EXTERN_C_END - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) +// Moved to root of objectivec directory, shim to keep anyone's imports working. +#import "GPBTimestamp.pbobjc.h" diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.m b/objectivec/google/protobuf/Timestamp.pbobjc.m deleted file mode 100644 index 4ab159fb9ce29..0000000000000 --- a/objectivec/google/protobuf/Timestamp.pbobjc.m +++ /dev/null @@ -1,107 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/timestamp.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers_RuntimeSupport.h" -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "google/protobuf/Timestamp.pbobjc.h" -#endif -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -#pragma mark - GPBTimestampRoot - -@implementation GPBTimestampRoot - -// No extensions in the file and no imports, so no need to generate -// +extensionRegistry. - -@end - -#pragma mark - GPBTimestampRoot_FileDescriptor - -static GPBFileDescriptor *GPBTimestampRoot_FileDescriptor(void) { - // This is called by +initialize so there is no need to worry - // about thread safety of the singleton. - static GPBFileDescriptor *descriptor = NULL; - if (!descriptor) { - GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); - descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" - objcPrefix:@"GPB" - syntax:GPBFileSyntaxProto3]; - } - return descriptor; -} - -#pragma mark - GPBTimestamp - -@implementation GPBTimestamp - -@dynamic seconds; -@dynamic nanos; - -typedef struct GPBTimestamp__storage_ { - uint32_t _has_storage_[1]; - int32_t nanos; - int64_t seconds; -} GPBTimestamp__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "seconds", - .dataTypeSpecific.className = NULL, - .number = GPBTimestamp_FieldNumber_Seconds, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBTimestamp__storage_, seconds), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeInt64, - }, - { - .name = "nanos", - .dataTypeSpecific.className = NULL, - .number = GPBTimestamp_FieldNumber_Nanos, - .hasIndex = 1, - .offset = (uint32_t)offsetof(GPBTimestamp__storage_, nanos), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeInt32, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBTimestamp class] - rootClass:[GPBTimestampRoot class] - file:GPBTimestampRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBTimestamp__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Type.pbobjc.h b/objectivec/google/protobuf/Type.pbobjc.h index 1798697080daf..e14e7cdcae8fb 100644 --- a/objectivec/google/protobuf/Type.pbobjc.h +++ b/objectivec/google/protobuf/Type.pbobjc.h @@ -1,440 +1,2 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/type.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers.h" -#endif - -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 -#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. -#endif -#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION -#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. -#endif - -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -CF_EXTERN_C_BEGIN - -@class GPBAny; -@class GPBEnumValue; -@class GPBField; -@class GPBOption; -@class GPBSourceContext; - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - Enum GPBSyntax - -/** The syntax in which a protocol buffer element is defined. */ -typedef GPB_ENUM(GPBSyntax) { - /** - * Value used if any message's field encounters a value that is not defined - * by this enum. The message will also have C functions to get/set the rawValue - * of the field. - **/ - GPBSyntax_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, - /** Syntax `proto2`. */ - GPBSyntax_SyntaxProto2 = 0, - - /** Syntax `proto3`. */ - GPBSyntax_SyntaxProto3 = 1, -}; - -GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void); - -/** - * Checks to see if the given value is defined by the enum or was not known at - * the time this source was generated. - **/ -BOOL GPBSyntax_IsValidValue(int32_t value); - -#pragma mark - Enum GPBField_Kind - -/** Basic field types. */ -typedef GPB_ENUM(GPBField_Kind) { - /** - * Value used if any message's field encounters a value that is not defined - * by this enum. The message will also have C functions to get/set the rawValue - * of the field. - **/ - GPBField_Kind_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, - /** Field type unknown. */ - GPBField_Kind_TypeUnknown = 0, - - /** Field type double. */ - GPBField_Kind_TypeDouble = 1, - - /** Field type float. */ - GPBField_Kind_TypeFloat = 2, - - /** Field type int64. */ - GPBField_Kind_TypeInt64 = 3, - - /** Field type uint64. */ - GPBField_Kind_TypeUint64 = 4, - - /** Field type int32. */ - GPBField_Kind_TypeInt32 = 5, - - /** Field type fixed64. */ - GPBField_Kind_TypeFixed64 = 6, - - /** Field type fixed32. */ - GPBField_Kind_TypeFixed32 = 7, - - /** Field type bool. */ - GPBField_Kind_TypeBool = 8, - - /** Field type string. */ - GPBField_Kind_TypeString = 9, - - /** Field type group. Proto2 syntax only, and deprecated. */ - GPBField_Kind_TypeGroup = 10, - - /** Field type message. */ - GPBField_Kind_TypeMessage = 11, - - /** Field type bytes. */ - GPBField_Kind_TypeBytes = 12, - - /** Field type uint32. */ - GPBField_Kind_TypeUint32 = 13, - - /** Field type enum. */ - GPBField_Kind_TypeEnum = 14, - - /** Field type sfixed32. */ - GPBField_Kind_TypeSfixed32 = 15, - - /** Field type sfixed64. */ - GPBField_Kind_TypeSfixed64 = 16, - - /** Field type sint32. */ - GPBField_Kind_TypeSint32 = 17, - - /** Field type sint64. */ - GPBField_Kind_TypeSint64 = 18, -}; - -GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void); - -/** - * Checks to see if the given value is defined by the enum or was not known at - * the time this source was generated. - **/ -BOOL GPBField_Kind_IsValidValue(int32_t value); - -#pragma mark - Enum GPBField_Cardinality - -/** Whether a field is optional, required, or repeated. */ -typedef GPB_ENUM(GPBField_Cardinality) { - /** - * Value used if any message's field encounters a value that is not defined - * by this enum. The message will also have C functions to get/set the rawValue - * of the field. - **/ - GPBField_Cardinality_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, - /** For fields with unknown cardinality. */ - GPBField_Cardinality_CardinalityUnknown = 0, - - /** For optional fields. */ - GPBField_Cardinality_CardinalityOptional = 1, - - /** For required fields. Proto2 syntax only. */ - GPBField_Cardinality_CardinalityRequired = 2, - - /** For repeated fields. */ - GPBField_Cardinality_CardinalityRepeated = 3, -}; - -GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void); - -/** - * Checks to see if the given value is defined by the enum or was not known at - * the time this source was generated. - **/ -BOOL GPBField_Cardinality_IsValidValue(int32_t value); - -#pragma mark - GPBTypeRoot - -/** - * Exposes the extension registry for this file. - * - * The base class provides: - * @code - * + (GPBExtensionRegistry *)extensionRegistry; - * @endcode - * which is a @c GPBExtensionRegistry that includes all the extensions defined by - * this file and all files that it depends on. - **/ -@interface GPBTypeRoot : GPBRootObject -@end - -#pragma mark - GPBType - -typedef GPB_ENUM(GPBType_FieldNumber) { - GPBType_FieldNumber_Name = 1, - GPBType_FieldNumber_FieldsArray = 2, - GPBType_FieldNumber_OneofsArray = 3, - GPBType_FieldNumber_OptionsArray = 4, - GPBType_FieldNumber_SourceContext = 5, - GPBType_FieldNumber_Syntax = 6, -}; - -/** - * A protocol buffer message type. - **/ -@interface GPBType : GPBMessage - -/** The fully qualified message name. */ -@property(nonatomic, readwrite, copy, null_resettable) NSString *name; - -/** The list of fields. */ -@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *fieldsArray; -/** The number of items in @c fieldsArray without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger fieldsArray_Count; - -/** The list of types appearing in `oneof` definitions in this type. */ -@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *oneofsArray; -/** The number of items in @c oneofsArray without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger oneofsArray_Count; - -/** The protocol buffer options. */ -@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; -/** The number of items in @c optionsArray without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger optionsArray_Count; - -/** The source context. */ -@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; -/** Test to see if @c sourceContext has been set. */ -@property(nonatomic, readwrite) BOOL hasSourceContext; - -/** The source syntax. */ -@property(nonatomic, readwrite) GPBSyntax syntax; - -@end - -/** - * Fetches the raw value of a @c GPBType's @c syntax property, even - * if the value was not defined by the enum at the time the code was generated. - **/ -int32_t GPBType_Syntax_RawValue(GPBType *message); -/** - * Sets the raw value of an @c GPBType's @c syntax property, allowing - * it to be set to a value that was not defined by the enum at the time the code - * was generated. - **/ -void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value); - -#pragma mark - GPBField - -typedef GPB_ENUM(GPBField_FieldNumber) { - GPBField_FieldNumber_Kind = 1, - GPBField_FieldNumber_Cardinality = 2, - GPBField_FieldNumber_Number = 3, - GPBField_FieldNumber_Name = 4, - GPBField_FieldNumber_TypeURL = 6, - GPBField_FieldNumber_OneofIndex = 7, - GPBField_FieldNumber_Packed = 8, - GPBField_FieldNumber_OptionsArray = 9, - GPBField_FieldNumber_JsonName = 10, - GPBField_FieldNumber_DefaultValue = 11, -}; - -/** - * A single field of a message type. - **/ -@interface GPBField : GPBMessage - -/** The field type. */ -@property(nonatomic, readwrite) GPBField_Kind kind; - -/** The field cardinality. */ -@property(nonatomic, readwrite) GPBField_Cardinality cardinality; - -/** The field number. */ -@property(nonatomic, readwrite) int32_t number; - -/** The field name. */ -@property(nonatomic, readwrite, copy, null_resettable) NSString *name; - -/** - * The field type URL, without the scheme, for message or enumeration - * types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. - **/ -@property(nonatomic, readwrite, copy, null_resettable) NSString *typeURL; - -/** - * The index of the field type in `Type.oneofs`, for message or enumeration - * types. The first type has index 1; zero means the type is not in the list. - **/ -@property(nonatomic, readwrite) int32_t oneofIndex; - -/** Whether to use alternative packed wire representation. */ -@property(nonatomic, readwrite) BOOL packed; - -/** The protocol buffer options. */ -@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; -/** The number of items in @c optionsArray without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger optionsArray_Count; - -/** The field JSON name. */ -@property(nonatomic, readwrite, copy, null_resettable) NSString *jsonName; - -/** The string value of the default value of this field. Proto2 syntax only. */ -@property(nonatomic, readwrite, copy, null_resettable) NSString *defaultValue; - -@end - -/** - * Fetches the raw value of a @c GPBField's @c kind property, even - * if the value was not defined by the enum at the time the code was generated. - **/ -int32_t GPBField_Kind_RawValue(GPBField *message); -/** - * Sets the raw value of an @c GPBField's @c kind property, allowing - * it to be set to a value that was not defined by the enum at the time the code - * was generated. - **/ -void SetGPBField_Kind_RawValue(GPBField *message, int32_t value); - -/** - * Fetches the raw value of a @c GPBField's @c cardinality property, even - * if the value was not defined by the enum at the time the code was generated. - **/ -int32_t GPBField_Cardinality_RawValue(GPBField *message); -/** - * Sets the raw value of an @c GPBField's @c cardinality property, allowing - * it to be set to a value that was not defined by the enum at the time the code - * was generated. - **/ -void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value); - -#pragma mark - GPBEnum - -typedef GPB_ENUM(GPBEnum_FieldNumber) { - GPBEnum_FieldNumber_Name = 1, - GPBEnum_FieldNumber_EnumvalueArray = 2, - GPBEnum_FieldNumber_OptionsArray = 3, - GPBEnum_FieldNumber_SourceContext = 4, - GPBEnum_FieldNumber_Syntax = 5, -}; - -/** - * Enum type definition. - **/ -@interface GPBEnum : GPBMessage - -/** Enum type name. */ -@property(nonatomic, readwrite, copy, null_resettable) NSString *name; - -/** Enum value definitions. */ -@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *enumvalueArray; -/** The number of items in @c enumvalueArray without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger enumvalueArray_Count; - -/** Protocol buffer options. */ -@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; -/** The number of items in @c optionsArray without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger optionsArray_Count; - -/** The source context. */ -@property(nonatomic, readwrite, strong, null_resettable) GPBSourceContext *sourceContext; -/** Test to see if @c sourceContext has been set. */ -@property(nonatomic, readwrite) BOOL hasSourceContext; - -/** The source syntax. */ -@property(nonatomic, readwrite) GPBSyntax syntax; - -@end - -/** - * Fetches the raw value of a @c GPBEnum's @c syntax property, even - * if the value was not defined by the enum at the time the code was generated. - **/ -int32_t GPBEnum_Syntax_RawValue(GPBEnum *message); -/** - * Sets the raw value of an @c GPBEnum's @c syntax property, allowing - * it to be set to a value that was not defined by the enum at the time the code - * was generated. - **/ -void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value); - -#pragma mark - GPBEnumValue - -typedef GPB_ENUM(GPBEnumValue_FieldNumber) { - GPBEnumValue_FieldNumber_Name = 1, - GPBEnumValue_FieldNumber_Number = 2, - GPBEnumValue_FieldNumber_OptionsArray = 3, -}; - -/** - * Enum value definition. - **/ -@interface GPBEnumValue : GPBMessage - -/** Enum value name. */ -@property(nonatomic, readwrite, copy, null_resettable) NSString *name; - -/** Enum value number. */ -@property(nonatomic, readwrite) int32_t number; - -/** Protocol buffer options. */ -@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *optionsArray; -/** The number of items in @c optionsArray without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger optionsArray_Count; - -@end - -#pragma mark - GPBOption - -typedef GPB_ENUM(GPBOption_FieldNumber) { - GPBOption_FieldNumber_Name = 1, - GPBOption_FieldNumber_Value = 2, -}; - -/** - * A protocol buffer option, which can be attached to a message, field, - * enumeration, etc. - **/ -@interface GPBOption : GPBMessage - -/** - * The option's name. For protobuf built-in options (options defined in - * descriptor.proto), this is the short name. For example, `"map_entry"`. - * For custom options, it should be the fully-qualified name. For example, - * `"google.api.http"`. - **/ -@property(nonatomic, readwrite, copy, null_resettable) NSString *name; - -/** - * The option's value packed in an Any message. If the value is a primitive, - * the corresponding wrapper type defined in google/protobuf/wrappers.proto - * should be used. If the value is an enum, it should be stored as an int32 - * value using the google.protobuf.Int32Value type. - **/ -@property(nonatomic, readwrite, strong, null_resettable) GPBAny *value; -/** Test to see if @c value has been set. */ -@property(nonatomic, readwrite) BOOL hasValue; - -@end - -NS_ASSUME_NONNULL_END - -CF_EXTERN_C_END - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) +// Moved to root of objectivec directory, shim to keep anyone's imports working. +#import "GPBType.pbobjc.h" diff --git a/objectivec/google/protobuf/Type.pbobjc.m b/objectivec/google/protobuf/Type.pbobjc.m deleted file mode 100644 index 7a949388f8f41..0000000000000 --- a/objectivec/google/protobuf/Type.pbobjc.m +++ /dev/null @@ -1,701 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/type.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers_RuntimeSupport.h" -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import - #import - #import -#else - #import "google/protobuf/Type.pbobjc.h" - #import "google/protobuf/Any.pbobjc.h" - #import "google/protobuf/SourceContext.pbobjc.h" -#endif -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -#pragma mark - GPBTypeRoot - -@implementation GPBTypeRoot - -// No extensions in the file and none of the imports (direct or indirect) -// defined extensions, so no need to generate +extensionRegistry. - -@end - -#pragma mark - GPBTypeRoot_FileDescriptor - -static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) { - // This is called by +initialize so there is no need to worry - // about thread safety of the singleton. - static GPBFileDescriptor *descriptor = NULL; - if (!descriptor) { - GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); - descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" - objcPrefix:@"GPB" - syntax:GPBFileSyntaxProto3]; - } - return descriptor; -} - -#pragma mark - Enum GPBSyntax - -GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void) { - static GPBEnumDescriptor *descriptor = NULL; - if (!descriptor) { - static const char *valueNames = - "SyntaxProto2\000SyntaxProto3\000"; - static const int32_t values[] = { - GPBSyntax_SyntaxProto2, - GPBSyntax_SyntaxProto3, - }; - GPBEnumDescriptor *worker = - [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBSyntax) - valueNames:valueNames - values:values - count:(uint32_t)(sizeof(values) / sizeof(int32_t)) - enumVerifier:GPBSyntax_IsValidValue]; - if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { - [worker release]; - } - } - return descriptor; -} - -BOOL GPBSyntax_IsValidValue(int32_t value__) { - switch (value__) { - case GPBSyntax_SyntaxProto2: - case GPBSyntax_SyntaxProto3: - return YES; - default: - return NO; - } -} - -#pragma mark - GPBType - -@implementation GPBType - -@dynamic name; -@dynamic fieldsArray, fieldsArray_Count; -@dynamic oneofsArray, oneofsArray_Count; -@dynamic optionsArray, optionsArray_Count; -@dynamic hasSourceContext, sourceContext; -@dynamic syntax; - -typedef struct GPBType__storage_ { - uint32_t _has_storage_[1]; - GPBSyntax syntax; - NSString *name; - NSMutableArray *fieldsArray; - NSMutableArray *oneofsArray; - NSMutableArray *optionsArray; - GPBSourceContext *sourceContext; -} GPBType__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "name", - .dataTypeSpecific.className = NULL, - .number = GPBType_FieldNumber_Name, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBType__storage_, name), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - { - .name = "fieldsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBField), - .number = GPBType_FieldNumber_FieldsArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GPBType__storage_, fieldsArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeMessage, - }, - { - .name = "oneofsArray", - .dataTypeSpecific.className = NULL, - .number = GPBType_FieldNumber_OneofsArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GPBType__storage_, oneofsArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeString, - }, - { - .name = "optionsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), - .number = GPBType_FieldNumber_OptionsArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GPBType__storage_, optionsArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeMessage, - }, - { - .name = "sourceContext", - .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), - .number = GPBType_FieldNumber_SourceContext, - .hasIndex = 1, - .offset = (uint32_t)offsetof(GPBType__storage_, sourceContext), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeMessage, - }, - { - .name = "syntax", - .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, - .number = GPBType_FieldNumber_Syntax, - .hasIndex = 2, - .offset = (uint32_t)offsetof(GPBType__storage_, syntax), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), - .dataType = GPBDataTypeEnum, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBType class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBType__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -int32_t GPBType_Syntax_RawValue(GPBType *message) { - GPBDescriptor *descriptor = [GPBType descriptor]; - GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax]; - return GPBGetMessageInt32Field(message, field); -} - -void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value) { - GPBDescriptor *descriptor = [GPBType descriptor]; - GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax]; - GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); -} - -#pragma mark - GPBField - -@implementation GPBField - -@dynamic kind; -@dynamic cardinality; -@dynamic number; -@dynamic name; -@dynamic typeURL; -@dynamic oneofIndex; -@dynamic packed; -@dynamic optionsArray, optionsArray_Count; -@dynamic jsonName; -@dynamic defaultValue; - -typedef struct GPBField__storage_ { - uint32_t _has_storage_[1]; - GPBField_Kind kind; - GPBField_Cardinality cardinality; - int32_t number; - int32_t oneofIndex; - NSString *name; - NSString *typeURL; - NSMutableArray *optionsArray; - NSString *jsonName; - NSString *defaultValue; -} GPBField__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "kind", - .dataTypeSpecific.enumDescFunc = GPBField_Kind_EnumDescriptor, - .number = GPBField_FieldNumber_Kind, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBField__storage_, kind), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), - .dataType = GPBDataTypeEnum, - }, - { - .name = "cardinality", - .dataTypeSpecific.enumDescFunc = GPBField_Cardinality_EnumDescriptor, - .number = GPBField_FieldNumber_Cardinality, - .hasIndex = 1, - .offset = (uint32_t)offsetof(GPBField__storage_, cardinality), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), - .dataType = GPBDataTypeEnum, - }, - { - .name = "number", - .dataTypeSpecific.className = NULL, - .number = GPBField_FieldNumber_Number, - .hasIndex = 2, - .offset = (uint32_t)offsetof(GPBField__storage_, number), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeInt32, - }, - { - .name = "name", - .dataTypeSpecific.className = NULL, - .number = GPBField_FieldNumber_Name, - .hasIndex = 3, - .offset = (uint32_t)offsetof(GPBField__storage_, name), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - { - .name = "typeURL", - .dataTypeSpecific.className = NULL, - .number = GPBField_FieldNumber_TypeURL, - .hasIndex = 4, - .offset = (uint32_t)offsetof(GPBField__storage_, typeURL), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), - .dataType = GPBDataTypeString, - }, - { - .name = "oneofIndex", - .dataTypeSpecific.className = NULL, - .number = GPBField_FieldNumber_OneofIndex, - .hasIndex = 5, - .offset = (uint32_t)offsetof(GPBField__storage_, oneofIndex), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeInt32, - }, - { - .name = "packed", - .dataTypeSpecific.className = NULL, - .number = GPBField_FieldNumber_Packed, - .hasIndex = 6, - .offset = 7, // Stored in _has_storage_ to save space. - .flags = GPBFieldOptional, - .dataType = GPBDataTypeBool, - }, - { - .name = "optionsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), - .number = GPBField_FieldNumber_OptionsArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GPBField__storage_, optionsArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeMessage, - }, - { - .name = "jsonName", - .dataTypeSpecific.className = NULL, - .number = GPBField_FieldNumber_JsonName, - .hasIndex = 8, - .offset = (uint32_t)offsetof(GPBField__storage_, jsonName), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - { - .name = "defaultValue", - .dataTypeSpecific.className = NULL, - .number = GPBField_FieldNumber_DefaultValue, - .hasIndex = 9, - .offset = (uint32_t)offsetof(GPBField__storage_, defaultValue), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBField class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBField__storage_) - flags:GPBDescriptorInitializationFlag_None]; -#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS - static const char *extraTextFormatInfo = - "\001\006\004\241!!\000"; - [localDescriptor setupExtraTextInfo:extraTextFormatInfo]; -#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -int32_t GPBField_Kind_RawValue(GPBField *message) { - GPBDescriptor *descriptor = [GPBField descriptor]; - GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind]; - return GPBGetMessageInt32Field(message, field); -} - -void SetGPBField_Kind_RawValue(GPBField *message, int32_t value) { - GPBDescriptor *descriptor = [GPBField descriptor]; - GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind]; - GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); -} - -int32_t GPBField_Cardinality_RawValue(GPBField *message) { - GPBDescriptor *descriptor = [GPBField descriptor]; - GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality]; - return GPBGetMessageInt32Field(message, field); -} - -void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value) { - GPBDescriptor *descriptor = [GPBField descriptor]; - GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality]; - GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); -} - -#pragma mark - Enum GPBField_Kind - -GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void) { - static GPBEnumDescriptor *descriptor = NULL; - if (!descriptor) { - static const char *valueNames = - "TypeUnknown\000TypeDouble\000TypeFloat\000TypeInt" - "64\000TypeUint64\000TypeInt32\000TypeFixed64\000Type" - "Fixed32\000TypeBool\000TypeString\000TypeGroup\000Ty" - "peMessage\000TypeBytes\000TypeUint32\000TypeEnum\000" - "TypeSfixed32\000TypeSfixed64\000TypeSint32\000Typ" - "eSint64\000"; - static const int32_t values[] = { - GPBField_Kind_TypeUnknown, - GPBField_Kind_TypeDouble, - GPBField_Kind_TypeFloat, - GPBField_Kind_TypeInt64, - GPBField_Kind_TypeUint64, - GPBField_Kind_TypeInt32, - GPBField_Kind_TypeFixed64, - GPBField_Kind_TypeFixed32, - GPBField_Kind_TypeBool, - GPBField_Kind_TypeString, - GPBField_Kind_TypeGroup, - GPBField_Kind_TypeMessage, - GPBField_Kind_TypeBytes, - GPBField_Kind_TypeUint32, - GPBField_Kind_TypeEnum, - GPBField_Kind_TypeSfixed32, - GPBField_Kind_TypeSfixed64, - GPBField_Kind_TypeSint32, - GPBField_Kind_TypeSint64, - }; - GPBEnumDescriptor *worker = - [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Kind) - valueNames:valueNames - values:values - count:(uint32_t)(sizeof(values) / sizeof(int32_t)) - enumVerifier:GPBField_Kind_IsValidValue]; - if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { - [worker release]; - } - } - return descriptor; -} - -BOOL GPBField_Kind_IsValidValue(int32_t value__) { - switch (value__) { - case GPBField_Kind_TypeUnknown: - case GPBField_Kind_TypeDouble: - case GPBField_Kind_TypeFloat: - case GPBField_Kind_TypeInt64: - case GPBField_Kind_TypeUint64: - case GPBField_Kind_TypeInt32: - case GPBField_Kind_TypeFixed64: - case GPBField_Kind_TypeFixed32: - case GPBField_Kind_TypeBool: - case GPBField_Kind_TypeString: - case GPBField_Kind_TypeGroup: - case GPBField_Kind_TypeMessage: - case GPBField_Kind_TypeBytes: - case GPBField_Kind_TypeUint32: - case GPBField_Kind_TypeEnum: - case GPBField_Kind_TypeSfixed32: - case GPBField_Kind_TypeSfixed64: - case GPBField_Kind_TypeSint32: - case GPBField_Kind_TypeSint64: - return YES; - default: - return NO; - } -} - -#pragma mark - Enum GPBField_Cardinality - -GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void) { - static GPBEnumDescriptor *descriptor = NULL; - if (!descriptor) { - static const char *valueNames = - "CardinalityUnknown\000CardinalityOptional\000C" - "ardinalityRequired\000CardinalityRepeated\000"; - static const int32_t values[] = { - GPBField_Cardinality_CardinalityUnknown, - GPBField_Cardinality_CardinalityOptional, - GPBField_Cardinality_CardinalityRequired, - GPBField_Cardinality_CardinalityRepeated, - }; - GPBEnumDescriptor *worker = - [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Cardinality) - valueNames:valueNames - values:values - count:(uint32_t)(sizeof(values) / sizeof(int32_t)) - enumVerifier:GPBField_Cardinality_IsValidValue]; - if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) { - [worker release]; - } - } - return descriptor; -} - -BOOL GPBField_Cardinality_IsValidValue(int32_t value__) { - switch (value__) { - case GPBField_Cardinality_CardinalityUnknown: - case GPBField_Cardinality_CardinalityOptional: - case GPBField_Cardinality_CardinalityRequired: - case GPBField_Cardinality_CardinalityRepeated: - return YES; - default: - return NO; - } -} - -#pragma mark - GPBEnum - -@implementation GPBEnum - -@dynamic name; -@dynamic enumvalueArray, enumvalueArray_Count; -@dynamic optionsArray, optionsArray_Count; -@dynamic hasSourceContext, sourceContext; -@dynamic syntax; - -typedef struct GPBEnum__storage_ { - uint32_t _has_storage_[1]; - GPBSyntax syntax; - NSString *name; - NSMutableArray *enumvalueArray; - NSMutableArray *optionsArray; - GPBSourceContext *sourceContext; -} GPBEnum__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "name", - .dataTypeSpecific.className = NULL, - .number = GPBEnum_FieldNumber_Name, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBEnum__storage_, name), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - { - .name = "enumvalueArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumValue), - .number = GPBEnum_FieldNumber_EnumvalueArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GPBEnum__storage_, enumvalueArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeMessage, - }, - { - .name = "optionsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), - .number = GPBEnum_FieldNumber_OptionsArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GPBEnum__storage_, optionsArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeMessage, - }, - { - .name = "sourceContext", - .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), - .number = GPBEnum_FieldNumber_SourceContext, - .hasIndex = 1, - .offset = (uint32_t)offsetof(GPBEnum__storage_, sourceContext), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeMessage, - }, - { - .name = "syntax", - .dataTypeSpecific.enumDescFunc = GPBSyntax_EnumDescriptor, - .number = GPBEnum_FieldNumber_Syntax, - .hasIndex = 2, - .offset = (uint32_t)offsetof(GPBEnum__storage_, syntax), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), - .dataType = GPBDataTypeEnum, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBEnum class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBEnum__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -int32_t GPBEnum_Syntax_RawValue(GPBEnum *message) { - GPBDescriptor *descriptor = [GPBEnum descriptor]; - GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax]; - return GPBGetMessageInt32Field(message, field); -} - -void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value) { - GPBDescriptor *descriptor = [GPBEnum descriptor]; - GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax]; - GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); -} - -#pragma mark - GPBEnumValue - -@implementation GPBEnumValue - -@dynamic name; -@dynamic number; -@dynamic optionsArray, optionsArray_Count; - -typedef struct GPBEnumValue__storage_ { - uint32_t _has_storage_[1]; - int32_t number; - NSString *name; - NSMutableArray *optionsArray; -} GPBEnumValue__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "name", - .dataTypeSpecific.className = NULL, - .number = GPBEnumValue_FieldNumber_Name, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBEnumValue__storage_, name), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - { - .name = "number", - .dataTypeSpecific.className = NULL, - .number = GPBEnumValue_FieldNumber_Number, - .hasIndex = 1, - .offset = (uint32_t)offsetof(GPBEnumValue__storage_, number), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeInt32, - }, - { - .name = "optionsArray", - .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), - .number = GPBEnumValue_FieldNumber_OptionsArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GPBEnumValue__storage_, optionsArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeMessage, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBEnumValue class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBEnumValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -#pragma mark - GPBOption - -@implementation GPBOption - -@dynamic name; -@dynamic hasValue, value; - -typedef struct GPBOption__storage_ { - uint32_t _has_storage_[1]; - NSString *name; - GPBAny *value; -} GPBOption__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "name", - .dataTypeSpecific.className = NULL, - .number = GPBOption_FieldNumber_Name, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBOption__storage_, name), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - { - .name = "value", - .dataTypeSpecific.className = GPBStringifySymbol(GPBAny), - .number = GPBOption_FieldNumber_Value, - .hasIndex = 1, - .offset = (uint32_t)offsetof(GPBOption__storage_, value), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeMessage, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBOption class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBOption__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.h b/objectivec/google/protobuf/Wrappers.pbobjc.h index 3cb9fe77dc95a..8365afc6df211 100644 --- a/objectivec/google/protobuf/Wrappers.pbobjc.h +++ b/objectivec/google/protobuf/Wrappers.pbobjc.h @@ -1,215 +1,2 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/wrappers.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers.h" -#endif - -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30002 -#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. -#endif -#if 30002 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION -#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. -#endif - -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -CF_EXTERN_C_BEGIN - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - GPBWrappersRoot - -/** - * Exposes the extension registry for this file. - * - * The base class provides: - * @code - * + (GPBExtensionRegistry *)extensionRegistry; - * @endcode - * which is a @c GPBExtensionRegistry that includes all the extensions defined by - * this file and all files that it depends on. - **/ -@interface GPBWrappersRoot : GPBRootObject -@end - -#pragma mark - GPBDoubleValue - -typedef GPB_ENUM(GPBDoubleValue_FieldNumber) { - GPBDoubleValue_FieldNumber_Value = 1, -}; - -/** - * Wrapper message for `double`. - * - * The JSON representation for `DoubleValue` is JSON number. - **/ -@interface GPBDoubleValue : GPBMessage - -/** The double value. */ -@property(nonatomic, readwrite) double value; - -@end - -#pragma mark - GPBFloatValue - -typedef GPB_ENUM(GPBFloatValue_FieldNumber) { - GPBFloatValue_FieldNumber_Value = 1, -}; - -/** - * Wrapper message for `float`. - * - * The JSON representation for `FloatValue` is JSON number. - **/ -@interface GPBFloatValue : GPBMessage - -/** The float value. */ -@property(nonatomic, readwrite) float value; - -@end - -#pragma mark - GPBInt64Value - -typedef GPB_ENUM(GPBInt64Value_FieldNumber) { - GPBInt64Value_FieldNumber_Value = 1, -}; - -/** - * Wrapper message for `int64`. - * - * The JSON representation for `Int64Value` is JSON string. - **/ -@interface GPBInt64Value : GPBMessage - -/** The int64 value. */ -@property(nonatomic, readwrite) int64_t value; - -@end - -#pragma mark - GPBUInt64Value - -typedef GPB_ENUM(GPBUInt64Value_FieldNumber) { - GPBUInt64Value_FieldNumber_Value = 1, -}; - -/** - * Wrapper message for `uint64`. - * - * The JSON representation for `UInt64Value` is JSON string. - **/ -@interface GPBUInt64Value : GPBMessage - -/** The uint64 value. */ -@property(nonatomic, readwrite) uint64_t value; - -@end - -#pragma mark - GPBInt32Value - -typedef GPB_ENUM(GPBInt32Value_FieldNumber) { - GPBInt32Value_FieldNumber_Value = 1, -}; - -/** - * Wrapper message for `int32`. - * - * The JSON representation for `Int32Value` is JSON number. - **/ -@interface GPBInt32Value : GPBMessage - -/** The int32 value. */ -@property(nonatomic, readwrite) int32_t value; - -@end - -#pragma mark - GPBUInt32Value - -typedef GPB_ENUM(GPBUInt32Value_FieldNumber) { - GPBUInt32Value_FieldNumber_Value = 1, -}; - -/** - * Wrapper message for `uint32`. - * - * The JSON representation for `UInt32Value` is JSON number. - **/ -@interface GPBUInt32Value : GPBMessage - -/** The uint32 value. */ -@property(nonatomic, readwrite) uint32_t value; - -@end - -#pragma mark - GPBBoolValue - -typedef GPB_ENUM(GPBBoolValue_FieldNumber) { - GPBBoolValue_FieldNumber_Value = 1, -}; - -/** - * Wrapper message for `bool`. - * - * The JSON representation for `BoolValue` is JSON `true` and `false`. - **/ -@interface GPBBoolValue : GPBMessage - -/** The bool value. */ -@property(nonatomic, readwrite) BOOL value; - -@end - -#pragma mark - GPBStringValue - -typedef GPB_ENUM(GPBStringValue_FieldNumber) { - GPBStringValue_FieldNumber_Value = 1, -}; - -/** - * Wrapper message for `string`. - * - * The JSON representation for `StringValue` is JSON string. - **/ -@interface GPBStringValue : GPBMessage - -/** The string value. */ -@property(nonatomic, readwrite, copy, null_resettable) NSString *value; - -@end - -#pragma mark - GPBBytesValue - -typedef GPB_ENUM(GPBBytesValue_FieldNumber) { - GPBBytesValue_FieldNumber_Value = 1, -}; - -/** - * Wrapper message for `bytes`. - * - * The JSON representation for `BytesValue` is JSON string. - **/ -@interface GPBBytesValue : GPBMessage - -/** The bytes value. */ -@property(nonatomic, readwrite, copy, null_resettable) NSData *value; - -@end - -NS_ASSUME_NONNULL_END - -CF_EXTERN_C_END - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) +// Moved to root of objectivec directory, shim to keep anyone's imports working. +#import "GPBWrappers.pbobjc.h" diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.m b/objectivec/google/protobuf/Wrappers.pbobjc.m deleted file mode 100644 index 5479eb127b54f..0000000000000 --- a/objectivec/google/protobuf/Wrappers.pbobjc.m +++ /dev/null @@ -1,439 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: google/protobuf/wrappers.proto - -// This CPP symbol can be defined to use imports that match up to the framework -// imports needed when using CocoaPods. -#if !defined(GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS) - #define GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS 0 -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "GPBProtocolBuffers_RuntimeSupport.h" -#endif - -#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS - #import -#else - #import "google/protobuf/Wrappers.pbobjc.h" -#endif -// @@protoc_insertion_point(imports) - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -#pragma mark - GPBWrappersRoot - -@implementation GPBWrappersRoot - -// No extensions in the file and no imports, so no need to generate -// +extensionRegistry. - -@end - -#pragma mark - GPBWrappersRoot_FileDescriptor - -static GPBFileDescriptor *GPBWrappersRoot_FileDescriptor(void) { - // This is called by +initialize so there is no need to worry - // about thread safety of the singleton. - static GPBFileDescriptor *descriptor = NULL; - if (!descriptor) { - GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); - descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" - objcPrefix:@"GPB" - syntax:GPBFileSyntaxProto3]; - } - return descriptor; -} - -#pragma mark - GPBDoubleValue - -@implementation GPBDoubleValue - -@dynamic value; - -typedef struct GPBDoubleValue__storage_ { - uint32_t _has_storage_[1]; - double value; -} GPBDoubleValue__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "value", - .dataTypeSpecific.className = NULL, - .number = GPBDoubleValue_FieldNumber_Value, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBDoubleValue__storage_, value), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeDouble, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBDoubleValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBDoubleValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -#pragma mark - GPBFloatValue - -@implementation GPBFloatValue - -@dynamic value; - -typedef struct GPBFloatValue__storage_ { - uint32_t _has_storage_[1]; - float value; -} GPBFloatValue__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "value", - .dataTypeSpecific.className = NULL, - .number = GPBFloatValue_FieldNumber_Value, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBFloatValue__storage_, value), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeFloat, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBFloatValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBFloatValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -#pragma mark - GPBInt64Value - -@implementation GPBInt64Value - -@dynamic value; - -typedef struct GPBInt64Value__storage_ { - uint32_t _has_storage_[1]; - int64_t value; -} GPBInt64Value__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "value", - .dataTypeSpecific.className = NULL, - .number = GPBInt64Value_FieldNumber_Value, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBInt64Value__storage_, value), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeInt64, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBInt64Value class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBInt64Value__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -#pragma mark - GPBUInt64Value - -@implementation GPBUInt64Value - -@dynamic value; - -typedef struct GPBUInt64Value__storage_ { - uint32_t _has_storage_[1]; - uint64_t value; -} GPBUInt64Value__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "value", - .dataTypeSpecific.className = NULL, - .number = GPBUInt64Value_FieldNumber_Value, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBUInt64Value__storage_, value), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeUInt64, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBUInt64Value class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBUInt64Value__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -#pragma mark - GPBInt32Value - -@implementation GPBInt32Value - -@dynamic value; - -typedef struct GPBInt32Value__storage_ { - uint32_t _has_storage_[1]; - int32_t value; -} GPBInt32Value__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "value", - .dataTypeSpecific.className = NULL, - .number = GPBInt32Value_FieldNumber_Value, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBInt32Value__storage_, value), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeInt32, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBInt32Value class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBInt32Value__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -#pragma mark - GPBUInt32Value - -@implementation GPBUInt32Value - -@dynamic value; - -typedef struct GPBUInt32Value__storage_ { - uint32_t _has_storage_[1]; - uint32_t value; -} GPBUInt32Value__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "value", - .dataTypeSpecific.className = NULL, - .number = GPBUInt32Value_FieldNumber_Value, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBUInt32Value__storage_, value), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeUInt32, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBUInt32Value class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBUInt32Value__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -#pragma mark - GPBBoolValue - -@implementation GPBBoolValue - -@dynamic value; - -typedef struct GPBBoolValue__storage_ { - uint32_t _has_storage_[1]; -} GPBBoolValue__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "value", - .dataTypeSpecific.className = NULL, - .number = GPBBoolValue_FieldNumber_Value, - .hasIndex = 0, - .offset = 1, // Stored in _has_storage_ to save space. - .flags = GPBFieldOptional, - .dataType = GPBDataTypeBool, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBBoolValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBBoolValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -#pragma mark - GPBStringValue - -@implementation GPBStringValue - -@dynamic value; - -typedef struct GPBStringValue__storage_ { - uint32_t _has_storage_[1]; - NSString *value; -} GPBStringValue__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "value", - .dataTypeSpecific.className = NULL, - .number = GPBStringValue_FieldNumber_Value, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBStringValue__storage_, value), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeString, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBStringValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBStringValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -#pragma mark - GPBBytesValue - -@implementation GPBBytesValue - -@dynamic value; - -typedef struct GPBBytesValue__storage_ { - uint32_t _has_storage_[1]; - NSData *value; -} GPBBytesValue__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "value", - .dataTypeSpecific.className = NULL, - .number = GPBBytesValue_FieldNumber_Value, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GPBBytesValue__storage_, value), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeBytes, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GPBBytesValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GPBBytesValue__storage_) - flags:GPBDescriptorInitializationFlag_None]; - NSAssert(descriptor == nil, @"Startup recursed!"); - descriptor = localDescriptor; - } - return descriptor; -} - -@end - - -#pragma clang diagnostic pop - -// @@protoc_insertion_point(global_scope) diff --git a/php/README.md b/php/README.md index cebeb3e5a27d0..16757be58bf74 100644 --- a/php/README.md +++ b/php/README.md @@ -16,8 +16,8 @@ generation functionality. To use PHP runtime library requires: -- C extension: PHP 5.5.x or 5.6.x. -- PHP package: PHP 5.5, 5.6 or 7. +- C extension: PHP 5.5, 5.6, or 7. +- [PHP package](http://php.net/downloads.php): PHP 5.5, 5.6 or 7. ## Installation @@ -36,7 +36,7 @@ To install the c extension, the following tools are needed: On Ubuntu, you can install them with: ``` -sudo apt-get install php-pear php5-dev autoconf automake libtool make gcc +sudo apt-get install -y php-pear php5-dev autoconf automake libtool make gcc ``` On other platforms, please use the corresponding package managing tool to install them before proceeding. @@ -95,3 +95,45 @@ Known Issues * HHVM not tested. * C extension not tested on windows, mac, php 7.0. * Message name cannot be Empty. + +## Development + +### Docker Image + +We provide a docker image for php development, which is also used in our automatic tests: +``` +docker run --security-opt seccomp=unconfined -it protobuftesting/php_8dbe419c6df1a8b3af0ae3a267c112efb436b45c +``` + +### Test Native PHP + +``` +# Download protobuf +git clone https://github.com/protocolbuffers/protobuf.git +cd protobuf + +# Build protoc +./autogen.sh +./configure +make -j4 + +# Test native php +cd php +composer install +composer test +``` + +### Test C Extension + +After you have finished testing the native php, you can test the c extension: +``` +cd tests +./test.sh 5.6 # The php runtime version. + # We provide 5.5, 5.5-zts, 5.6, 5.6-zts, 7.0, 7.0-zts, 7.1, 7.1-zts, 7.2, 7.2-zts, 7.3 and 7.3-zts + # ls /usr/local for more details +``` + +If you want to use gdb to debug the c extension, you can do: +``` +./gdb_test.sh +``` diff --git a/php/composer.json b/php/composer.json index 34e0447c80480..4c1b5ac675823 100644 --- a/php/composer.json +++ b/php/composer.json @@ -9,13 +9,21 @@ "php": ">=5.5.0" }, "require-dev": { - "phpunit/phpunit": ">=4.8.0" + "phpunit/phpunit": ">=5.0.0" }, "autoload": { "psr-4": { "Google\\Protobuf\\": "src/Google/Protobuf", - "GPBMetadata\\Google\\Protobuf\\": "src/GPBMetadata/Google/Protobuf", + "GPBMetadata\\Google\\Protobuf\\": "src/GPBMetadata/Google/Protobuf" + } + }, + "autoload-dev": { + "psr-4": { "": "tests/generated" } + }, + "scripts": { + "test": "tests/generate_protos.sh && vendor/bin/phpunit", + "aggregate_metadata_test": "tests/generate_protos.sh --aggregate_metadata && vendor/bin/phpunit" } } diff --git a/php/ext/google/protobuf/arena.c b/php/ext/google/protobuf/arena.c new file mode 100644 index 0000000000000..035dfcad760f2 --- /dev/null +++ b/php/ext/google/protobuf/arena.c @@ -0,0 +1,95 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "php-upb.h" + +// ----------------------------------------------------------------------------- +// Arena +// ----------------------------------------------------------------------------- + +typedef struct Arena { + zend_object std; + upb_arena* arena; +} Arena; + +zend_class_entry *Arena_class_entry; +static zend_object_handlers Arena_object_handlers; + +// PHP Object Handlers ///////////////////////////////////////////////////////// + +static zend_object* Arena_Create(zend_class_entry *class_type) { + Arena *intern = emalloc(sizeof(Arena)); + zend_object_std_init(&intern->std, class_type); + intern->std.handlers = &Arena_object_handlers; + intern->arena = upb_arena_new(); + // Skip object_properties_init(), we don't allow derived classes. + return &intern->std; +} + +static void Arena_Free(zend_object* obj) { + Arena* intern = (Arena*)obj; + upb_arena_free(intern->arena); + zend_object_std_dtor(&intern->std); +} + +// C Functions from arena.h //////////////////////////////////////////////////// + +void Arena_Init(zval* val) { + ZVAL_OBJ(val, Arena_Create(Arena_class_entry)); +} + +upb_arena *Arena_Get(zval *val) { + Arena *a = (Arena*)Z_OBJ_P(val); + return a->arena; +} + +// ----------------------------------------------------------------------------- +// Module init. +// ----------------------------------------------------------------------------- + +// No public methods. +static const zend_function_entry Arena_methods[] = { + ZEND_FE_END +}; + +void Arena_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\Arena", Arena_methods); + Arena_class_entry = zend_register_internal_class(&tmp_ce); + Arena_class_entry->create_object = Arena_Create; + Arena_class_entry->ce_flags |= ZEND_ACC_FINAL; + + memcpy(&Arena_object_handlers, &std_object_handlers, + sizeof(zend_object_handlers)); + Arena_object_handlers.free_obj = Arena_Free; +} diff --git a/php/ext/google/protobuf/arena.h b/php/ext/google/protobuf/arena.h new file mode 100644 index 0000000000000..67e165d37d35c --- /dev/null +++ b/php/ext/google/protobuf/arena.h @@ -0,0 +1,47 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef PHP_PROTOBUF_ARENA_H_ +#define PHP_PROTOBUF_ARENA_H_ + +#include + +#include "php-upb.h" + +// Registers the PHP Arena class. +void Arena_ModuleInit(); + +// Creates and returns a new arena object that wraps a new upb_arena*. +void Arena_Init(zval *val); + +// Gets the underlying upb_arena from this arena object. +upb_arena *Arena_Get(zval *arena); + +#endif // PHP_PROTOBUF_ARENA_H_ diff --git a/php/ext/google/protobuf/array.c b/php/ext/google/protobuf/array.c index e69bef429985a..3a2f734a71d8b 100644 --- a/php/ext/google/protobuf/array.c +++ b/php/ext/google/protobuf/array.c @@ -28,377 +28,326 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include +#include "array.h" + #include #include -#include "protobuf.h" - -ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1) - ZEND_ARG_INFO(0, index) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2) - ZEND_ARG_INFO(0, index) - ZEND_ARG_INFO(0, newval) -ZEND_END_ARG_INFO() +#include -ZEND_BEGIN_ARG_INFO(arginfo_void, 0) -ZEND_END_ARG_INFO() +// This is not self-contained: it must be after other Zend includes. +#include -static zend_function_entry repeated_field_methods[] = { - PHP_ME(RepeatedField, __construct, NULL, ZEND_ACC_PUBLIC) - PHP_ME(RepeatedField, append, NULL, ZEND_ACC_PUBLIC) - PHP_ME(RepeatedField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC) - PHP_ME(RepeatedField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC) - PHP_ME(RepeatedField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC) - PHP_ME(RepeatedField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC) - PHP_ME(RepeatedField, count, arginfo_void, ZEND_ACC_PUBLIC) - PHP_ME(RepeatedField, getIterator, arginfo_void, ZEND_ACC_PUBLIC) - ZEND_FE_END -}; - -static zend_function_entry repeated_field_iter_methods[] = { - PHP_ME(RepeatedFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC) - PHP_ME(RepeatedFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC) - PHP_ME(RepeatedFieldIter, key, arginfo_void, ZEND_ACC_PUBLIC) - PHP_ME(RepeatedFieldIter, next, arginfo_void, ZEND_ACC_PUBLIC) - PHP_ME(RepeatedFieldIter, valid, arginfo_void, ZEND_ACC_PUBLIC) - ZEND_FE_END -}; +#include "arena.h" +#include "convert.h" +#include "def.h" +#include "message.h" +#include "php-upb.h" +#include "protobuf.h" -// Forward declare static functions. - -static int repeated_field_array_init(zval *array, upb_fieldtype_t type, - uint size ZEND_FILE_LINE_DC); -static void repeated_field_write_dimension(zval *object, zval *offset, - zval *value TSRMLS_DC); -static int repeated_field_has_dimension(zval *object, zval *offset TSRMLS_DC); -static HashTable *repeated_field_get_gc(zval *object, CACHED_VALUE **table, - int *n TSRMLS_DC); -#if PHP_MAJOR_VERSION < 7 -static zend_object_value repeated_field_create(zend_class_entry *ce TSRMLS_DC); -static zend_object_value repeated_field_iter_create(zend_class_entry *ce TSRMLS_DC); -#else -static zend_object *repeated_field_create(zend_class_entry *ce TSRMLS_DC); -static zend_object *repeated_field_iter_create(zend_class_entry *ce TSRMLS_DC); -#endif +static void RepeatedFieldIter_make(zval *val, zval *repeated_field); // ----------------------------------------------------------------------------- -// RepeatedField creation/desctruction +// RepeatedField // ----------------------------------------------------------------------------- -zend_class_entry* repeated_field_type; -zend_class_entry* repeated_field_iter_type; -zend_object_handlers* repeated_field_handlers; -zend_object_handlers* repeated_field_iter_handlers; +typedef struct { + zend_object std; + zval arena; + upb_array *array; + TypeInfo type; +} RepeatedField; -// Define object free method. -PHP_PROTO_OBJECT_FREE_START(RepeatedField, repeated_field) -#if PHP_MAJOR_VERSION < 7 -php_proto_zval_ptr_dtor(intern->array); -#else -php_proto_zval_ptr_dtor(&intern->array); -#endif -PHP_PROTO_OBJECT_FREE_END +zend_class_entry *RepeatedField_class_entry; +static zend_object_handlers RepeatedField_object_handlers; -PHP_PROTO_OBJECT_DTOR_START(RepeatedField, repeated_field) -PHP_PROTO_OBJECT_DTOR_END +// PHP Object Handlers ///////////////////////////////////////////////////////// -// Define object create method. -PHP_PROTO_OBJECT_CREATE_START(RepeatedField, repeated_field) -#if PHP_MAJOR_VERSION < 7 -intern->array = NULL; -#endif -intern->type = 0; -intern->msg_ce = NULL; -PHP_PROTO_OBJECT_CREATE_END(RepeatedField, repeated_field) - -// Init class entry. -PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\RepeatedField", - RepeatedField, repeated_field) -zend_class_implements(repeated_field_type TSRMLS_CC, 3, spl_ce_ArrayAccess, - zend_ce_aggregate, spl_ce_Countable); -repeated_field_handlers->write_dimension = repeated_field_write_dimension; -repeated_field_handlers->get_gc = repeated_field_get_gc; -PHP_PROTO_INIT_CLASS_END - -// Define array element free function. -#if PHP_MAJOR_VERSION < 7 -static inline void php_proto_array_string_release(void *value) { - zval_ptr_dtor(value); +/** + * RepeatedField_create() + * + * PHP class entry function to allocate and initialize a new RepeatedField + * object. + */ +static zend_object* RepeatedField_create(zend_class_entry *class_type) { + RepeatedField *intern = emalloc(sizeof(RepeatedField)); + zend_object_std_init(&intern->std, class_type); + intern->std.handlers = &RepeatedField_object_handlers; + Arena_Init(&intern->arena); + intern->array = NULL; + // Skip object_properties_init(), we don't allow derived classes. + return &intern->std; } -static inline void php_proto_array_object_release(void *value) { - zval_ptr_dtor(value); -} -static inline void php_proto_array_default_release(void *value) { -} -#else -static inline void php_proto_array_string_release(zval *value) { - void* ptr = Z_PTR_P(value); - zend_string* object = *(zend_string**)ptr; - zend_string_release(object); - efree(ptr); -} -static inline void php_proto_array_object_release(zval *value) { - zval_ptr_dtor(value); +/** + * RepeatedField_dtor() + * + * Object handler to destroy a RepeatedField. This releases all resources + * associated with the message. Note that it is possible to access a destroyed + * object from PHP in rare cases. + */ +static void RepeatedField_destructor(zend_object* obj) { + RepeatedField* intern = (RepeatedField*)obj; + ObjCache_Delete(intern->array); + zval_ptr_dtor(&intern->arena); + zend_object_std_dtor(&intern->std); } -static void php_proto_array_default_release(zval* value) { - void* ptr = Z_PTR_P(value); - efree(ptr); + +/** + * RepeatedField_compare_objects() + * + * Object handler for comparing two repeated field objects. Called whenever PHP + * code does: + * + * $rf1 == $rf2 + */ +static int RepeatedField_compare_objects(zval *rf1, zval *rf2) { + RepeatedField* intern1 = (RepeatedField*)Z_OBJ_P(rf1); + RepeatedField* intern2 = (RepeatedField*)Z_OBJ_P(rf2); + + return TypeInfo_Eq(intern1->type, intern2->type) && + ArrayEq(intern1->array, intern2->array, intern1->type) + ? 0 + : 1; } -#endif -static int repeated_field_array_init(zval *array, upb_fieldtype_t type, - uint size ZEND_FILE_LINE_DC) { - PHP_PROTO_ALLOC_ARRAY(array); - - switch (type) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - zend_hash_init(Z_ARRVAL_P(array), size, NULL, - php_proto_array_string_release, 0); - break; - case UPB_TYPE_MESSAGE: - zend_hash_init(Z_ARRVAL_P(array), size, NULL, - php_proto_array_object_release, 0); - break; - default: - zend_hash_init(Z_ARRVAL_P(array), size, NULL, - php_proto_array_default_release, 0); +/** + * RepeatedField_clone_obj() + * + * Object handler for cloning an object in PHP. Called when PHP code does: + * + * $rf2 = clone $rf1; + */ +static zend_object *RepeatedField_clone_obj(PROTO_VAL *object) { + RepeatedField* intern = PROTO_VAL_P(object); + upb_arena *arena = Arena_Get(&intern->arena); + upb_array *clone = upb_array_new(arena, intern->type.type); + size_t n = upb_array_size(intern->array); + size_t i; + + for (i = 0; i < n; i++) { + upb_msgval msgval = upb_array_get(intern->array, i); + upb_array_append(clone, msgval, arena); } - return SUCCESS; + + zval ret; + RepeatedField_GetPhpWrapper(&ret, clone, intern->type, &intern->arena); + return Z_OBJ_P(&ret); } -// ----------------------------------------------------------------------------- -// RepeatedField Handlers -// ----------------------------------------------------------------------------- +static HashTable *RepeatedField_GetProperties(PROTO_VAL *object) { + return NULL; // We do not have a properties table. +} -static void repeated_field_write_dimension(zval *object, zval *offset, - zval *value TSRMLS_DC) { - uint64_t index; +static zval *RepeatedField_GetPropertyPtrPtr(PROTO_VAL *object, + PROTO_STR *member, + int type, void **cache_slot) { + return NULL; // We don't offer direct references to our properties. +} - RepeatedField *intern = UNBOX(RepeatedField, object); - HashTable *ht = PHP_PROTO_HASH_OF(intern->array); - int size = native_slot_size(intern->type); +// C Functions from array.h //////////////////////////////////////////////////// - unsigned char memory[NATIVE_SLOT_MAX_SIZE]; - memset(memory, 0, NATIVE_SLOT_MAX_SIZE); +// These are documented in the header file. - if (!native_slot_set_by_array(intern->type, intern->msg_ce, memory, - value TSRMLS_CC)) { +void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, TypeInfo type, + zval *arena) { + if (!arr) { + ZVAL_NULL(val); return; } - if (!offset || Z_TYPE_P(offset) == IS_NULL) { - index = zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array)); - } else { - if (protobuf_convert_to_uint64(offset, &index)) { - if (!zend_hash_index_exists(ht, index)) { - zend_error(E_USER_ERROR, "Element at %llu doesn't exist.\n", - (long long unsigned int)index); - return; - } - } else { - return; - } + if (!ObjCache_Get(arr, val)) { + RepeatedField *intern = emalloc(sizeof(RepeatedField)); + zend_object_std_init(&intern->std, RepeatedField_class_entry); + intern->std.handlers = &RepeatedField_object_handlers; + ZVAL_COPY(&intern->arena, arena); + intern->array = arr; + intern->type = type; + // Skip object_properties_init(), we don't allow derived classes. + ObjCache_Add(intern->array, &intern->std); + ZVAL_OBJ(val, &intern->std); } +} - if (intern->type == UPB_TYPE_MESSAGE) { - php_proto_zend_hash_index_update_zval(ht, index, *(zval**)memory); - } else { - php_proto_zend_hash_index_update_mem(ht, index, memory, size, NULL); +upb_array *RepeatedField_GetUpbArray(zval *val, TypeInfo type, + upb_arena *arena) { + if (Z_ISREF_P(val)) { + ZVAL_DEREF(val); } -} -#if PHP_MAJOR_VERSION < 7 -static HashTable *repeated_field_get_gc(zval *object, zval ***table, - int *n TSRMLS_DC) { -#else -static HashTable *repeated_field_get_gc(zval *object, zval **table, int *n) { -#endif - *table = NULL; - *n = 0; - RepeatedField *intern = UNBOX(RepeatedField, object); - return PHP_PROTO_HASH_OF(intern->array); -} + if (Z_TYPE_P(val) == IS_ARRAY) { + // Auto-construct, eg. [1, 2, 3] -> upb_array([1, 2, 3]). + upb_array *arr = upb_array_new(arena, type.type); + HashTable *table = HASH_OF(val); + HashPosition pos; -// ----------------------------------------------------------------------------- -// C RepeatedField Utilities -// ----------------------------------------------------------------------------- + zend_hash_internal_pointer_reset_ex(table, &pos); -void *repeated_field_index_native(RepeatedField *intern, int index TSRMLS_DC) { - HashTable *ht = PHP_PROTO_HASH_OF(intern->array); - void *value; + while (true) { + zval *zv = zend_hash_get_current_data_ex(table, &pos); + upb_msgval val; - if (intern->type == UPB_TYPE_MESSAGE) { - if (php_proto_zend_hash_index_find_zval(ht, index, (void **)&value) == - FAILURE) { - zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index); - return NULL; + if (!zv) return arr; + + if (!Convert_PhpToUpbAutoWrap(zv, &val, type, arena)) { + return NULL; + } + + upb_array_append(arr, val, arena); + zend_hash_move_forward_ex(table, &pos); } - } else { - if (php_proto_zend_hash_index_find_mem(ht, index, (void **)&value) == - FAILURE) { - zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index); - return NULL; + } else if (Z_TYPE_P(val) == IS_OBJECT && + Z_OBJCE_P(val) == RepeatedField_class_entry) { + // Unwrap existing RepeatedField object to get the upb_array* inside. + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(val); + + if (!TypeInfo_Eq(intern->type, type)) { + php_error_docref(NULL, E_USER_ERROR, + "Wrong type for this repeated field."); } - } - return value; -} - -void repeated_field_push_native(RepeatedField *intern, void *value) { - HashTable *ht = PHP_PROTO_HASH_OF(intern->array); - int size = native_slot_size(intern->type); - if (intern->type == UPB_TYPE_MESSAGE) { - php_proto_zend_hash_next_index_insert_zval(ht, value); + upb_arena_fuse(arena, Arena_Get(&intern->arena)); + return intern->array; } else { - php_proto_zend_hash_next_index_insert_mem(ht, (void **)value, size, NULL); + php_error_docref(NULL, E_USER_ERROR, "Must be a repeated field"); + return NULL; } } -void repeated_field_create_with_field( - zend_class_entry *ce, const upb_fielddef *field, - CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC) { - upb_fieldtype_t type = upb_fielddef_type(field); - const zend_class_entry *msg_ce = field_type_class(field PHP_PROTO_TSRMLS_CC); - repeated_field_create_with_type(ce, type, msg_ce, - repeated_field PHP_PROTO_TSRMLS_CC); -} +bool ArrayEq(const upb_array *a1, const upb_array *a2, TypeInfo type) { + size_t i; + size_t n; -void repeated_field_create_with_type( - zend_class_entry *ce, upb_fieldtype_t type, const zend_class_entry *msg_ce, - CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC) { - CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(CACHED_PTR_TO_ZVAL_PTR(repeated_field), - repeated_field_type); - - RepeatedField *intern = - UNBOX(RepeatedField, CACHED_TO_ZVAL_PTR(*repeated_field)); - intern->type = type; - intern->msg_ce = msg_ce; -#if PHP_MAJOR_VERSION < 7 - MAKE_STD_ZVAL(intern->array); - repeated_field_array_init(intern->array, intern->type, 0 ZEND_FILE_LINE_CC); -#else - repeated_field_array_init(&intern->array, intern->type, 0 ZEND_FILE_LINE_CC); -#endif + if ((a1 == NULL) != (a2 == NULL)) return false; + if (a1 == NULL) return true; + + n = upb_array_size(a1); + if (n != upb_array_size(a2)) return false; - // TODO(teboring): Link class entry for message and enum + for (i = 0; i < n; i++) { + upb_msgval val1 = upb_array_get(a1, i); + upb_msgval val2 = upb_array_get(a2, i); + if (!ValueEq(val1, val2, type)) return false; + } + + return true; } -// ----------------------------------------------------------------------------- -// PHP RepeatedField Methods -// ----------------------------------------------------------------------------- +// RepeatedField PHP methods /////////////////////////////////////////////////// /** + * RepeatedField::__construct() + * * Constructs an instance of RepeatedField. * @param long Type of the stored element. - * @param string Message/Enum class name (message/enum fields only). + * @param string Message/Enum class. */ PHP_METHOD(RepeatedField, __construct) { - long type; + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + zend_long type; zend_class_entry* klass = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|C", &type, &klass) == - FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|C", &type, &klass) != SUCCESS) { return; } - RepeatedField *intern = UNBOX(RepeatedField, getThis()); - intern->type = to_fieldtype(type); - intern->msg_ce = klass; + intern->type.type = pbphp_dtype_to_type(type); + intern->type.desc = Descriptor_GetFromClassEntry(klass); -#if PHP_MAJOR_VERSION < 7 - MAKE_STD_ZVAL(intern->array); - repeated_field_array_init(intern->array, intern->type, 0 ZEND_FILE_LINE_CC); -#else - repeated_field_array_init(&intern->array, intern->type, 0 ZEND_FILE_LINE_CC); -#endif - - if (intern->type == UPB_TYPE_MESSAGE && klass == NULL) { - zend_error(E_USER_ERROR, "Message type must have concrete class."); + if (intern->type.type == UPB_TYPE_MESSAGE && klass == NULL) { + php_error_docref(NULL, E_USER_ERROR, + "Message/enum type must have concrete class."); return; } - // TODO(teboring): Consider enum. + intern->array = upb_array_new(arena, intern->type.type); + ObjCache_Add(intern->array, &intern->std); } /** + * RepeatedField::append() + * * Append element to the end of the repeated field. * @param object The element to be added. */ PHP_METHOD(RepeatedField, append) { - zval *value; + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + zval *php_val; + upb_msgval msgval; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == - FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &php_val) != SUCCESS || + !Convert_PhpToUpb(php_val, &msgval, intern->type, arena)) { return; } - repeated_field_write_dimension(getThis(), NULL, value TSRMLS_CC); + + upb_array_append(intern->array, msgval, arena); } /** - * Check whether the element at given index exists. + * RepeatedField::offsetExists() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * isset($arr[$idx]); + * empty($arr[$idx]); + * * @param long The index to be checked. * @return bool True if the element at the given index exists. */ PHP_METHOD(RepeatedField, offsetExists) { - long index; + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis()); + zend_long index; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == - FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { return; } - RepeatedField *intern = UNBOX(RepeatedField, getThis()); - - RETURN_BOOL(index >= 0 && - index < zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array))); + RETURN_BOOL(index >= 0 && index < upb_array_size(intern->array)); } /** - * Return the element at the given index. - * This will also be called for: $ele = $arr[0] + * RepeatedField::offsetGet() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * $x = $arr[$idx]; + * * @param long The index of the element to be fetched. * @return object The stored element at given index. * @exception Invalid type for index. * @exception Non-existing index. */ PHP_METHOD(RepeatedField, offsetGet) { - long index; - void *memory; + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis()); + zend_long index; + upb_msgval msgval; + zval ret; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == - FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { return; } - RepeatedField *intern = UNBOX(RepeatedField, getThis()); - HashTable *table = PHP_PROTO_HASH_OF(intern->array); - - if (intern->type == UPB_TYPE_MESSAGE) { - if (php_proto_zend_hash_index_find_zval(table, index, (void **)&memory) == - FAILURE) { - zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index); - return; - } - } else { - if (php_proto_zend_hash_index_find_mem(table, index, (void **)&memory) == - FAILURE) { - zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index); - return; - } + if (index < 0 || index >= upb_array_size(intern->array)) { + zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index); + return; } - native_slot_get_by_array(intern->type, memory, - ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC); + + msgval = upb_array_get(intern->array, index); + Convert_UpbToPhp(msgval, &ret, intern->type, &intern->arena); + RETURN_ZVAL(&ret, 0, 1); } /** - * Assign the element at the given index. - * This will also be called for: $arr []= $ele and $arr[0] = ele + * RepeatedField::offsetSet() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * $arr[$idx] = $x; + * $arr []= $x; // Append + * * @param long The index of the element to be assigned. * @param object The element to be assigned. * @exception Invalid type for index. @@ -406,140 +355,318 @@ PHP_METHOD(RepeatedField, offsetGet) { * @exception Incorrect type of the element. */ PHP_METHOD(RepeatedField, offsetSet) { - zval *index, *value; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &index, &value) == - FAILURE) { + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + size_t size = upb_array_size(intern->array); + zval *offset, *val; + int64_t index; + upb_msgval msgval; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &offset, &val) != SUCCESS) { + return; + } + + if (Z_TYPE_P(offset) == IS_NULL) { + index = size; + } else if (!Convert_PhpToInt64(offset, &index)) { + return; + } + + if (!Convert_PhpToUpb(val, &msgval, intern->type, arena)) { return; } - repeated_field_write_dimension(getThis(), index, value TSRMLS_CC); + + if (index > size) { + zend_error(E_USER_ERROR, "Element at index %ld doesn't exist.\n", index); + } else if (index == size) { + upb_array_append(intern->array, msgval, Arena_Get(&intern->arena)); + } else { + upb_array_set(intern->array, index, msgval); + } } /** - * Remove the element at the given index. - * This will also be called for: unset($arr) + * RepeatedField::offsetUnset() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * unset($arr[$idx]); + * * @param long The index of the element to be removed. * @exception Invalid type for index. * @exception The element to be removed is not at the end of the RepeatedField. */ PHP_METHOD(RepeatedField, offsetUnset) { - long index; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == - FAILURE) { + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis()); + zend_long index; + zend_long size = upb_array_size(intern->array); + + // Only the element at the end of the array can be removed. + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) != SUCCESS) { return; } - RepeatedField *intern = UNBOX(RepeatedField, getThis()); - - // Only the element at the end of the array can be removed. - if (index == -1 || - index != (zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array)) - 1)) { - zend_error(E_USER_ERROR, "Cannot remove element at %ld.\n", index); + if (size == 0 || index != size - 1) { + php_error_docref(NULL, E_USER_ERROR, "Cannot remove element at %ld.\n", + index); return; } - zend_hash_index_del(PHP_PROTO_HASH_OF(intern->array), index); + upb_array_resize(intern->array, size - 1, Arena_Get(&intern->arena)); } /** + * RepeatedField::count() + * + * Implements the Countable interface. Invoked when PHP code calls: + * + * $len = count($arr); * Return the number of stored elements. * This will also be called for: count($arr) * @return long The number of stored elements. */ PHP_METHOD(RepeatedField, count) { - RepeatedField *intern = UNBOX(RepeatedField, getThis()); + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } - RETURN_LONG(zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array))); + RETURN_LONG(upb_array_size(intern->array)); } /** - * Return the beginning iterator. - * This will also be called for: foreach($arr) + * RepeatedField::getIterator() + * + * Implements the IteratorAggregate interface. Invoked when PHP code calls: + * + * foreach ($arr) {} + * * @return object Beginning iterator. */ PHP_METHOD(RepeatedField, getIterator) { - CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(return_value, - repeated_field_iter_type); - - RepeatedField *intern = UNBOX(RepeatedField, getThis()); - RepeatedFieldIter *iter = UNBOX(RepeatedFieldIter, return_value); - iter->repeated_field = intern; - iter->position = 0; + zval ret; + RepeatedFieldIter_make(&ret, getThis()); + RETURN_ZVAL(&ret, 0, 1); } -// ----------------------------------------------------------------------------- -// RepeatedFieldIter creation/desctruction -// ----------------------------------------------------------------------------- +ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 1) + ZEND_ARG_INFO(0, type) + ZEND_ARG_INFO(0, class) +ZEND_END_ARG_INFO() -// Define object free method. -PHP_PROTO_OBJECT_FREE_START(RepeatedFieldIter, repeated_field_iter) -PHP_PROTO_OBJECT_FREE_END +ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 1) + ZEND_ARG_INFO(0, newval) +ZEND_END_ARG_INFO() -PHP_PROTO_OBJECT_DTOR_START(RepeatedFieldIter, repeated_field_iter) -PHP_PROTO_OBJECT_DTOR_END +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1) + ZEND_ARG_INFO(0, index) +ZEND_END_ARG_INFO() -// Define object create method. -PHP_PROTO_OBJECT_CREATE_START(RepeatedFieldIter, repeated_field_iter) -intern->repeated_field = NULL; -intern->position = 0; -PHP_PROTO_OBJECT_CREATE_END(RepeatedFieldIter, repeated_field_iter) +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2) + ZEND_ARG_INFO(0, index) + ZEND_ARG_INFO(0, newval) +ZEND_END_ARG_INFO() -// Init class entry. -PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\RepeatedFieldIter", - RepeatedFieldIter, repeated_field_iter) -zend_class_implements(repeated_field_iter_type TSRMLS_CC, 1, zend_ce_iterator); -PHP_PROTO_INIT_CLASS_END +static zend_function_entry repeated_field_methods[] = { + PHP_ME(RepeatedField, __construct, arginfo_construct, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, append, arginfo_append, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, count, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, getIterator, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; // ----------------------------------------------------------------------------- -// PHP RepeatedFieldIter Methods +// PHP RepeatedFieldIter // ----------------------------------------------------------------------------- -PHP_METHOD(RepeatedFieldIter, rewind) { - RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis()); +typedef struct { + zend_object std; + zval repeated_field; + zend_long position; +} RepeatedFieldIter; + +zend_class_entry *RepeatedFieldIter_class_entry; +static zend_object_handlers repeated_field_iter_object_handlers; + +/** + * RepeatedFieldIter_create() + * + * PHP class entry function to allocate and initialize a new RepeatedFieldIter + * object. + */ +zend_object* RepeatedFieldIter_create(zend_class_entry *class_type) { + RepeatedFieldIter *intern = emalloc(sizeof(RepeatedFieldIter)); + zend_object_std_init(&intern->std, class_type); + intern->std.handlers = &repeated_field_iter_object_handlers; + ZVAL_NULL(&intern->repeated_field); intern->position = 0; + // Skip object_properties_init(), we don't allow derived classes. + return &intern->std; } -PHP_METHOD(RepeatedFieldIter, current) { - RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis()); - RepeatedField *repeated_field = intern->repeated_field; +/** + * RepeatedFieldIter_dtor() + * + * Object handler to destroy a RepeatedFieldIter. This releases all resources + * associated with the message. Note that it is possible to access a destroyed + * object from PHP in rare cases. + */ +static void RepeatedFieldIter_dtor(zend_object* obj) { + RepeatedFieldIter* intern = (RepeatedFieldIter*)obj; + zval_ptr_dtor(&intern->repeated_field); + zend_object_std_dtor(&intern->std); +} - long index; - void *memory; +/** + * RepeatedFieldIter_make() + * + * C function to create a RepeatedFieldIter. + */ +static void RepeatedFieldIter_make(zval *val, zval *repeated_field) { + RepeatedFieldIter *iter; + ZVAL_OBJ(val, RepeatedFieldIter_class_entry->create_object( + RepeatedFieldIter_class_entry)); + iter = (RepeatedFieldIter*)Z_OBJ_P(val); + ZVAL_COPY(&iter->repeated_field, repeated_field); +} - HashTable *table = PHP_PROTO_HASH_OF(repeated_field->array); +/* + * When a user writes: + * + * foreach($arr as $key => $val) {} + * + * PHP's iterator protocol is: + * + * $iter = $arr->getIterator(); + * for ($iter->rewind(); $iter->valid(); $iter->next()) { + * $key = $iter->key(); + * $val = $iter->current(); + * } + */ - if (repeated_field->type == UPB_TYPE_MESSAGE) { - if (php_proto_zend_hash_index_find_zval(table, intern->position, - (void **)&memory) == FAILURE) { - zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index); - return; - } - } else { - if (php_proto_zend_hash_index_find_mem(table, intern->position, - (void **)&memory) == FAILURE) { - zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index); - return; - } +/** + * RepeatedFieldIter::rewind() + * + * Implements the Iterator interface. Sets the iterator to the first element. + */ +PHP_METHOD(RepeatedFieldIter, rewind) { + RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis()); + intern->position = 0; +} + +/** + * RepeatedFieldIter::current() + * + * Implements the Iterator interface. Returns the current value. + */ +PHP_METHOD(RepeatedFieldIter, current) { + RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis()); + RepeatedField *field = (RepeatedField*)Z_OBJ_P(&intern->repeated_field); + upb_array *array = field->array; + zend_long index = intern->position; + upb_msgval msgval; + zval ret; + + if (index < 0 || index >= upb_array_size(array)) { + zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index); } - native_slot_get_by_array(repeated_field->type, memory, - ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC); + + msgval = upb_array_get(array, index); + + Convert_UpbToPhp(msgval, &ret, field->type, &field->arena); + RETURN_ZVAL(&ret, 0, 1); } +/** + * RepeatedFieldIter::key() + * + * Implements the Iterator interface. Returns the current key. + */ PHP_METHOD(RepeatedFieldIter, key) { - RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis()); + RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis()); RETURN_LONG(intern->position); } +/** + * RepeatedFieldIter::next() + * + * Implements the Iterator interface. Advances to the next element. + */ PHP_METHOD(RepeatedFieldIter, next) { - RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis()); + RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis()); ++intern->position; } +/** + * RepeatedFieldIter::valid() + * + * Implements the Iterator interface. Returns true if this is a valid element. + */ PHP_METHOD(RepeatedFieldIter, valid) { - RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis()); - RETURN_BOOL(zend_hash_num_elements(PHP_PROTO_HASH_OF( - intern->repeated_field->array)) > intern->position); + RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis()); + RepeatedField *field = (RepeatedField*)Z_OBJ_P(&intern->repeated_field); + RETURN_BOOL(intern->position < upb_array_size(field->array)); +} + +static zend_function_entry repeated_field_iter_methods[] = { + PHP_ME(RepeatedFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedFieldIter, key, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedFieldIter, next, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedFieldIter, valid, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// Module init. +// ----------------------------------------------------------------------------- + +/** + * Array_ModuleInit() + * + * Called when the C extension is loaded to register all types. + */ +void Array_ModuleInit() { + zend_class_entry tmp_ce; + zend_object_handlers *h; + + // RepeatedField. + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\RepeatedField", + repeated_field_methods); + + RepeatedField_class_entry = zend_register_internal_class(&tmp_ce); + zend_class_implements(RepeatedField_class_entry, 3, spl_ce_ArrayAccess, + zend_ce_aggregate, spl_ce_Countable); + RepeatedField_class_entry->ce_flags |= ZEND_ACC_FINAL; + RepeatedField_class_entry->create_object = RepeatedField_create; + + h = &RepeatedField_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + h->dtor_obj = RepeatedField_destructor; +#if PHP_VERSION_ID < 80000 + h->compare_objects = RepeatedField_compare_objects; +#else + h->compare = RepeatedField_compare_objects; +#endif + h->clone_obj = RepeatedField_clone_obj; + h->get_properties = RepeatedField_GetProperties; + h->get_property_ptr_ptr = RepeatedField_GetPropertyPtrPtr; + + // RepeatedFieldIter + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\RepeatedFieldIter", + repeated_field_iter_methods); + + RepeatedFieldIter_class_entry = zend_register_internal_class(&tmp_ce); + zend_class_implements(RepeatedFieldIter_class_entry, 1, zend_ce_iterator); + RepeatedFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL; + RepeatedFieldIter_class_entry->create_object = RepeatedFieldIter_create; + + h = &repeated_field_iter_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + h->dtor_obj = RepeatedFieldIter_dtor; } diff --git a/php/ext/google/protobuf/array.h b/php/ext/google/protobuf/array.h new file mode 100644 index 0000000000000..031effa711233 --- /dev/null +++ b/php/ext/google/protobuf/array.h @@ -0,0 +1,67 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef PHP_PROTOBUF_ARRAY_H_ +#define PHP_PROTOBUF_ARRAY_H_ + +#include + +#include "def.h" +#include "php-upb.h" + +// Registers PHP classes for RepeatedField. +void Array_ModuleInit(); + +// Gets a upb_array* for the PHP object |val|: +// * If |val| is a RepeatedField object, we first check its type and verify +// that that the elements have the correct type for |type|. If so, we return +// the wrapped upb_array*. We also make sure that this array's arena is fused +// to |arena|, so the returned upb_array is guaranteed to live as long as +// |arena|. +// * If |val| is a PHP Array, we attempt to create a new upb_array using +// |arena| and add all of the PHP elements to it. +// +// If an error occurs, we raise a PHP error and return NULL. +upb_array *RepeatedField_GetUpbArray(zval *val, TypeInfo type, + upb_arena *arena); + +// Creates a PHP RepeatedField object for the given upb_array* and |type| and +// returns it in |val|. The PHP object will keep a reference to this |arena| to +// ensure the underlying array data stays alive. +// +// If |arr| is NULL, this will return a PHP null object. +void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, TypeInfo type, + zval *arena); + +// Returns true if the given arrays are equal. Both arrays must be of this +// |type| and, if the type is |UPB_TYPE_MESSAGE|, must have the same |m|. +bool ArrayEq(const upb_array *a1, const upb_array *a2, TypeInfo type); + +#endif // PHP_PROTOBUF_ARRAY_H_ diff --git a/php/ext/google/protobuf/config.m4 b/php/ext/google/protobuf/config.m4 index ab032e466b574..c09c03af0a5b7 100644 --- a/php/ext/google/protobuf/config.m4 +++ b/php/ext/google/protobuf/config.m4 @@ -4,7 +4,7 @@ if test "$PHP_PROTOBUF" != "no"; then PHP_NEW_EXTENSION( protobuf, - array.c def.c encode_decode.c map.c message.c protobuf.c storage.c type_check.c upb.c utf8.c, - $ext_shared) + arena.c array.c convert.c def.c map.c message.c names.c php-upb.c protobuf.c, + $ext_shared, , -std=gnu99) fi diff --git a/php/ext/google/protobuf/convert.c b/php/ext/google/protobuf/convert.c new file mode 100644 index 0000000000000..c518ccaa4da61 --- /dev/null +++ b/php/ext/google/protobuf/convert.c @@ -0,0 +1,512 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "convert.h" + +#include + +// This is not self-contained: it must be after other Zend includes. +#include + +#include "array.h" +#include "map.h" +#include "message.h" +#include "php-upb.h" +#include "protobuf.h" + +// ----------------------------------------------------------------------------- +// GPBUtil +// ----------------------------------------------------------------------------- + +static zend_class_entry* GPBUtil_class_entry; + +// The implementation of type checking for primitive fields is empty. This is +// because type checking is done when direct assigning message fields (e.g., +// foo->a = 1). Functions defined here are place holders in generated code for +// pure PHP implementation (c extension and pure PHP share the same generated +// code). + +PHP_METHOD(Util, checkInt32) {} +PHP_METHOD(Util, checkUint32) {} +PHP_METHOD(Util, checkInt64) {} +PHP_METHOD(Util, checkUint64) {} +PHP_METHOD(Util, checkEnum) {} +PHP_METHOD(Util, checkFloat) {} +PHP_METHOD(Util, checkDouble) {} +PHP_METHOD(Util, checkBool) {} +PHP_METHOD(Util, checkString) {} +PHP_METHOD(Util, checkBytes) {} +PHP_METHOD(Util, checkMessage) {} + +// The result of checkMapField() is assigned, so we need to return the first +// param: +// $arr = GPBUtil::checkMapField($var, +// \Google\Protobuf\Internal\GPBType::INT64, +// \Google\Protobuf\Internal\GPBType::INT32); +PHP_METHOD(Util, checkMapField) { + zval *val, *key_type, *val_type, *klass; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|z", &val, &key_type, + &val_type, &klass) == FAILURE) { + return; + } + RETURN_ZVAL(val, 1, 0); +} + +// The result of checkRepeatedField() is assigned, so we need to return the +// first param: +// $arr = GPBUtil::checkRepeatedField( +// $var, \Google\Protobuf\Internal\GPBType::STRING); +PHP_METHOD(Util, checkRepeatedField) { + zval *val, *type, *klass; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|z", &val, &type, &klass) == + FAILURE) { + return; + } + RETURN_ZVAL(val, 1, 0); +} + +ZEND_BEGIN_ARG_INFO_EX(arginfo_checkPrimitive, 0, 0, 1) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_checkMessage, 0, 0, 2) + ZEND_ARG_INFO(0, value) + ZEND_ARG_INFO(0, class) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_checkMapField, 0, 0, 3) + ZEND_ARG_INFO(0, value) + ZEND_ARG_INFO(0, key_type) + ZEND_ARG_INFO(0, value_type) + ZEND_ARG_INFO(0, value_class) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_checkRepeatedField, 0, 0, 2) + ZEND_ARG_INFO(0, value) + ZEND_ARG_INFO(0, type) + ZEND_ARG_INFO(0, class) +ZEND_END_ARG_INFO() + +static zend_function_entry util_methods[] = { + PHP_ME(Util, checkInt32, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkUint32, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkInt64, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkUint64, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkEnum, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkFloat, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkDouble, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkBool, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkString, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkBytes, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkMessage, arginfo_checkMessage, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkMapField, arginfo_checkMapField, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkRepeatedField, arginfo_checkRepeatedField, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// Conversion functions used from C +// ----------------------------------------------------------------------------- + +upb_fieldtype_t pbphp_dtype_to_type(upb_descriptortype_t type) { + switch (type) { +#define CASE(descriptor_type, type) \ + case UPB_DESCRIPTOR_TYPE_##descriptor_type: \ + return UPB_TYPE_##type; + + CASE(FLOAT, FLOAT); + CASE(DOUBLE, DOUBLE); + CASE(BOOL, BOOL); + CASE(STRING, STRING); + CASE(BYTES, BYTES); + CASE(MESSAGE, MESSAGE); + CASE(GROUP, MESSAGE); + CASE(ENUM, ENUM); + CASE(INT32, INT32); + CASE(INT64, INT64); + CASE(UINT32, UINT32); + CASE(UINT64, UINT64); + CASE(SINT32, INT32); + CASE(SINT64, INT64); + CASE(FIXED32, UINT32); + CASE(FIXED64, UINT64); + CASE(SFIXED32, INT32); + CASE(SFIXED64, INT64); + +#undef CASE + + } + + zend_error(E_ERROR, "Unknown field type."); + return 0; +} + +static bool buftouint64(const char *ptr, const char *end, uint64_t *val) { + uint64_t u64 = 0; + while (ptr < end) { + unsigned ch = (unsigned)(*ptr - '0'); + if (ch >= 10) break; + if (u64 > UINT64_MAX / 10 || u64 * 10 > UINT64_MAX - ch) { + return false; + } + u64 *= 10; + u64 += ch; + ptr++; + } + + if (ptr != end) { + // In PHP tradition, we allow truncation: "1.1" -> 1. + // But we don't allow 'e', eg. '1.1e2' or any other non-numeric chars. + if (*ptr++ != '.') return false; + + for (;ptr < end; ptr++) { + if (*ptr < '0' || *ptr > '9') { + return false; + } + } + } + + *val = u64; + return true; +} + +static bool buftoint64(const char *ptr, const char *end, int64_t *val) { + bool neg = false; + uint64_t u64; + + if (ptr != end && *ptr == '-') { + ptr++; + neg = true; + } + + if (!buftouint64(ptr, end, &u64) || + u64 > (uint64_t)INT64_MAX + neg) { + return false; + } + + *val = neg ? -u64 : u64; + return true; +} + +static void throw_conversion_exception(const char *to, const zval *zv) { + zval tmp; + ZVAL_COPY(&tmp, zv); + convert_to_string(&tmp); + + zend_throw_exception_ex(NULL, 0, "Cannot convert '%s' to %s", + Z_STRVAL_P(&tmp), to); + + zval_ptr_dtor(&tmp); +} + +bool Convert_PhpToInt64(const zval *php_val, int64_t *i64) { + switch (Z_TYPE_P(php_val)) { + case IS_LONG: + *i64 = Z_LVAL_P(php_val); + return true; + case IS_DOUBLE: { + double dbl = Z_DVAL_P(php_val); + if (dbl > 9223372036854774784.0 || dbl < -9223372036854775808.0) { + zend_throw_exception_ex(NULL, 0, "Out of range"); + return false; + } + *i64 = dbl; /* must be guarded, overflow here is UB */ + return true; + } + case IS_STRING: { + const char *buf = Z_STRVAL_P(php_val); + // PHP would accept scientific notation here, but we're going to be a + // little more discerning and only accept pure integers. + bool ok = buftoint64(buf, buf + Z_STRLEN_P(php_val), i64); + if (!ok) { + throw_conversion_exception("integer", php_val); + } + return ok; + } + default: + throw_conversion_exception("integer", php_val); + return false; + } +} + +static bool to_double(zval *php_val, double *dbl) { + switch (Z_TYPE_P(php_val)) { + case IS_LONG: + *dbl = Z_LVAL_P(php_val); + return true; + case IS_DOUBLE: + *dbl = Z_DVAL_P(php_val); + return true; + case IS_STRING: { + zend_long lval; + switch (is_numeric_string(Z_STRVAL_P(php_val), Z_STRLEN_P(php_val), &lval, + dbl, false)) { + case IS_LONG: + *dbl = lval; + return true; + case IS_DOUBLE: + return true; + default: + goto fail; + } + } + default: + fail: + throw_conversion_exception("double", php_val); + return false; + } +} + +static bool to_bool(zval* from, bool* to) { + switch (Z_TYPE_P(from)) { + case IS_TRUE: + *to = true; + return true; + case IS_FALSE: + *to = false; + return true; + case IS_LONG: + *to = (Z_LVAL_P(from) != 0); + return true; + case IS_DOUBLE: + *to = (Z_LVAL_P(from) != 0); + return true; + case IS_STRING: + if (Z_STRLEN_P(from) == 0 || + (Z_STRLEN_P(from) == 1 && Z_STRVAL_P(from)[0] == '0')) { + *to = false; + } else { + *to = true; + } + return true; + default: + throw_conversion_exception("bool", from); + return false; + } +} + +static bool to_string(zval* from) { + if (Z_ISREF_P(from)) { + ZVAL_DEREF(from); + } + + switch (Z_TYPE_P(from)) { + case IS_STRING: + return true; + case IS_TRUE: + case IS_FALSE: + case IS_LONG: + case IS_DOUBLE: { + zval tmp; + zend_make_printable_zval(from, &tmp); + ZVAL_COPY_VALUE(from, &tmp); + return true; + } + default: + throw_conversion_exception("string", from); + return false; + } +} + +bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, TypeInfo type, + upb_arena *arena) { + int64_t i64; + + if (Z_ISREF_P(php_val)) { + ZVAL_DEREF(php_val); + } + + switch (type.type) { + case UPB_TYPE_INT64: + return Convert_PhpToInt64(php_val, &upb_val->int64_val); + case UPB_TYPE_INT32: + case UPB_TYPE_ENUM: + if (!Convert_PhpToInt64(php_val, &i64)) { + return false; + } + upb_val->int32_val = i64; + return true; + case UPB_TYPE_UINT64: + if (!Convert_PhpToInt64(php_val, &i64)) { + return false; + } + upb_val->uint64_val = i64; + return true; + case UPB_TYPE_UINT32: + if (!Convert_PhpToInt64(php_val, &i64)) { + return false; + } + upb_val->uint32_val = i64; + return true; + case UPB_TYPE_DOUBLE: + return to_double(php_val, &upb_val->double_val); + case UPB_TYPE_FLOAT: + if (!to_double(php_val, &upb_val->double_val)) return false; + upb_val->float_val = upb_val->double_val; + return true; + case UPB_TYPE_BOOL: + return to_bool(php_val, &upb_val->bool_val); + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: { + char *ptr; + size_t size; + + if (!to_string(php_val)) return false; + + size = Z_STRLEN_P(php_val); + + // If arena is NULL we reference the input zval. + // The resulting upb_strview will only be value while the zval is alive. + if (arena) { + ptr = upb_arena_malloc(arena, size); + memcpy(ptr, Z_STRVAL_P(php_val), size); + } else { + ptr = Z_STRVAL_P(php_val); + } + + upb_val->str_val = upb_strview_make(ptr, size); + return true; + } + case UPB_TYPE_MESSAGE: + PBPHP_ASSERT(type.desc); + return Message_GetUpbMessage(php_val, type.desc, arena, + (upb_msg **)&upb_val->msg_val); + } + + return false; +} + +void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, TypeInfo type, + zval *arena) { + switch (type.type) { + case UPB_TYPE_INT64: +#if SIZEOF_ZEND_LONG == 8 + ZVAL_LONG(php_val, upb_val.int64_val); +#else + { + char buf[20]; + int size = sprintf(buf, "%lld", upb_val.int64_val); + ZVAL_NEW_STR(php_val, zend_string_init(buf, size, 0)); + } +#endif + break; + case UPB_TYPE_UINT64: +#if SIZEOF_ZEND_LONG == 8 + ZVAL_LONG(php_val, upb_val.uint64_val); +#else + { + char buf[20]; + int size = sprintf(buf, "%lld", (int64_t)upb_val.uint64_val); + ZVAL_NEW_STR(php_val, zend_string_init(buf, size, 0)); + } +#endif + break; + case UPB_TYPE_INT32: + case UPB_TYPE_ENUM: + ZVAL_LONG(php_val, upb_val.int32_val); + break; + case UPB_TYPE_UINT32: { + // Sign-extend for consistency between 32/64-bit builds. + zend_long val = (int32_t)upb_val.uint32_val; + ZVAL_LONG(php_val, val); + break; + } + case UPB_TYPE_DOUBLE: + ZVAL_DOUBLE(php_val, upb_val.double_val); + break; + case UPB_TYPE_FLOAT: + ZVAL_DOUBLE(php_val, upb_val.float_val); + break; + case UPB_TYPE_BOOL: + ZVAL_BOOL(php_val, upb_val.bool_val); + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: { + upb_strview str = upb_val.str_val; + ZVAL_NEW_STR(php_val, zend_string_init(str.data, str.size, 0)); + break; + } + case UPB_TYPE_MESSAGE: + PBPHP_ASSERT(type.desc); + Message_GetPhpWrapper(php_val, type.desc, (upb_msg *)upb_val.msg_val, + arena); + break; + } +} + +bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, TypeInfo type, + upb_arena *arena) { + const upb_msgdef *subm = type.desc ? type.desc->msgdef : NULL; + if (subm && upb_msgdef_iswrapper(subm) && Z_TYPE_P(val) != IS_OBJECT) { + // Assigning a scalar to a wrapper-typed value. We will automatically wrap + // the value, so the user doesn't need to create a FooWrapper(['value': X]) + // message manually. + upb_msg *wrapper = upb_msg_new(subm, arena); + const upb_fielddef *val_f = upb_msgdef_itof(subm, 1); + upb_msgval msgval; + if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(val_f), arena)) return false; + upb_msg_set(wrapper, val_f, msgval, arena); + upb_val->msg_val = wrapper; + return true; + } else { + // Convert_PhpToUpb doesn't auto-construct messages. This means that we only + // allow: + // ['foo_submsg': new Foo(['a' => 1])] + // not: + // ['foo_submsg': ['a' => 1]] + return Convert_PhpToUpb(val, upb_val, type, arena); + } +} + +void Convert_ModuleInit(void) { + const char *prefix_name = "TYPE_URL_PREFIX"; + zend_class_entry class_type; + + INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBUtil", + util_methods); + GPBUtil_class_entry = zend_register_internal_class(&class_type); + + zend_declare_class_constant_string(GPBUtil_class_entry, prefix_name, + strlen(prefix_name), + "type.googleapis.com/"); +} diff --git a/php/ext/google/protobuf/convert.h b/php/ext/google/protobuf/convert.h new file mode 100644 index 0000000000000..1bae233425ff9 --- /dev/null +++ b/php/ext/google/protobuf/convert.h @@ -0,0 +1,72 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef PHP_PROTOBUF_CONVERT_H_ +#define PHP_PROTOBUF_CONVERT_H_ + +#include + +#include "php-upb.h" +#include "def.h" + +upb_fieldtype_t pbphp_dtype_to_type(upb_descriptortype_t type); + +// Converts |php_val| to an int64_t. Returns false if the value cannot be +// converted. +bool Convert_PhpToInt64(const zval *php_val, int64_t *i64); + +// Converts |php_val| to a upb_msgval according to |type|. If type is +// UPB_TYPE_MESSAGE, then |desc| must be the Descriptor for this message type. +// If type is string, message, or bytes, then |arena| will be used to copy +// string data or fuse this arena to the given message's arena. +bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, TypeInfo type, + upb_arena *arena); + +// Similar to Convert_PhpToUpb, but supports automatically wrapping the wrapper +// types if a primitive is specified: +// +// 5 -> Int64Wrapper(value=5) +// +// We currently allow this implicit conversion in initializers, but not for +// assignment. +bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, TypeInfo type, + upb_arena *arena); + +// Converts |upb_val| to a PHP zval according to |type|. This may involve +// creating a PHP wrapper object. If type == UPB_TYPE_MESSAGE, then |desc| must +// be the Descriptor for this message type. Any newly created wrapper object +// will reference |arena|. +void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, TypeInfo type, + zval *arena); + +// Registers the GPBUtil class. +void Convert_ModuleInit(void); + +#endif // PHP_PROTOBUF_CONVERT_H_ diff --git a/php/ext/google/protobuf/def.c b/php/ext/google/protobuf/def.c index f885c1452fd07..6e1a7e4e43355 100644 --- a/php/ext/google/protobuf/def.c +++ b/php/ext/google/protobuf/def.c @@ -28,422 +28,330 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "protobuf.h" - -const char* const kReservedNames[] = {"Empty", "ECHO", "ARRAY"}; -const int kReservedNamesSize = 3; - -// Forward declare. -static void descriptor_init_c_instance(Descriptor* intern TSRMLS_DC); -static void descriptor_free_c(Descriptor* object TSRMLS_DC); - -static void field_descriptor_init_c_instance(FieldDescriptor* intern TSRMLS_DC); -static void field_descriptor_free_c(FieldDescriptor* object TSRMLS_DC); - -static void enum_descriptor_init_c_instance(EnumDescriptor* intern TSRMLS_DC); -static void enum_descriptor_free_c(EnumDescriptor* object TSRMLS_DC); - -static void enum_value_descriptor_init_c_instance( - EnumValueDescriptor *intern TSRMLS_DC); -static void enum_value_descriptor_free_c(EnumValueDescriptor *object TSRMLS_DC); +#include "def.h" -static void descriptor_pool_free_c(DescriptorPool* object TSRMLS_DC); -static void descriptor_pool_init_c_instance(DescriptorPool* pool TSRMLS_DC); +#include -static void internal_descriptor_pool_free_c( - InternalDescriptorPool *object TSRMLS_DC); -static void internal_descriptor_pool_init_c_instance( - InternalDescriptorPool *pool TSRMLS_DC); +// This is not self-contained: it must be after other Zend includes. +#include -static void oneof_descriptor_free_c(Oneof* object TSRMLS_DC); -static void oneof_descriptor_init_c_instance(Oneof* pool TSRMLS_DC); - -// ----------------------------------------------------------------------------- -// Common Utilities -// ----------------------------------------------------------------------------- +#include "names.h" +#include "php-upb.h" +#include "protobuf.h" -static void check_upb_status(const upb_status* status, const char* msg) { +static void CheckUpbStatus(const upb_status* status, const char* msg) { if (!upb_ok(status)) { zend_error(E_ERROR, "%s: %s\n", msg, upb_status_errmsg(status)); } } -static void upb_filedef_free(void *r) { - upb_filedef *f = *(upb_filedef **)r; - size_t i; - - for (i = 0; i < upb_filedef_depcount(f); i++) { - upb_filedef_unref(upb_filedef_dep(f, i), f); - } - - upb_inttable_uninit(&f->defs); - upb_inttable_uninit(&f->deps); - upb_gfree((void *)f->name); - upb_gfree((void *)f->package); - upb_gfree(f); -} - -// Camel-case the field name and append "Entry" for generated map entry name. -// e.g. map foo_map => FooMapEntry -static void append_map_entry_name(char *result, const char *field_name, - int pos) { - bool cap_next = true; - int i; +static void FieldDescriptor_FromFieldDef(zval *val, const upb_fielddef *f); - for (i = 0; i < strlen(field_name); ++i) { - if (field_name[i] == '_') { - cap_next = true; - } else if (cap_next) { - // Note: Do not use ctype.h due to locales. - if ('a' <= field_name[i] && field_name[i] <= 'z') { - result[pos++] = field_name[i] - 'a' + 'A'; - } else { - result[pos++] = field_name[i]; - } - cap_next = false; - } else { - result[pos++] = field_name[i]; - } - } - strcat(result, "Entry"); +// We use this for objects that should not be created directly from PHP. +static zend_object *CreateHandler_ReturnNull(zend_class_entry *class_type) { + return NULL; // Nobody should call this. } -#define CHECK_UPB(code, msg) \ - do { \ - upb_status status = UPB_STATUS_INIT; \ - code; \ - check_upb_status(&status, msg); \ - } while (0) - -// Define PHP class -#define DEFINE_PROTOBUF_INIT_CLASS(CLASSNAME, CAMELNAME, LOWERNAME) \ - PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWERNAME) \ - PHP_PROTO_INIT_CLASS_END - -#define DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME) \ - PHP_PROTO_OBJECT_CREATE_START(NAME, LOWERNAME) \ - LOWERNAME##_init_c_instance(intern TSRMLS_CC); \ - PHP_PROTO_OBJECT_CREATE_END(NAME, LOWERNAME) - -#define DEFINE_PROTOBUF_FREE(CAMELNAME, LOWERNAME) \ - PHP_PROTO_OBJECT_FREE_START(CAMELNAME, LOWERNAME) \ - LOWERNAME##_free_c(intern TSRMLS_CC); \ - PHP_PROTO_OBJECT_FREE_END - -#define DEFINE_PROTOBUF_DTOR(CAMELNAME, LOWERNAME) \ - PHP_PROTO_OBJECT_DTOR_START(CAMELNAME, LOWERNAME) \ - PHP_PROTO_OBJECT_DTOR_END - -#define DEFINE_CLASS(NAME, LOWERNAME, string_name) \ - zend_class_entry *LOWERNAME##_type; \ - zend_object_handlers *LOWERNAME##_handlers; \ - DEFINE_PROTOBUF_FREE(NAME, LOWERNAME) \ - DEFINE_PROTOBUF_DTOR(NAME, LOWERNAME) \ - DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME) \ - DEFINE_PROTOBUF_INIT_CLASS(string_name, NAME, LOWERNAME) // ----------------------------------------------------------------------------- -// GPBType +// EnumValueDescriptor // ----------------------------------------------------------------------------- -zend_class_entry* gpb_type_type; +typedef struct { + zend_object std; + const char *name; + int32_t number; +} EnumValueDescriptor; + +zend_class_entry *EnumValueDescriptor_class_entry; +static zend_object_handlers EnumValueDescriptor_object_handlers; + +/* + * EnumValueDescriptor_Make() + * + * Function to create an EnumValueDescriptor object from C. + */ +static void EnumValueDescriptor_Make(zval *val, const char *name, + int32_t number) { + EnumValueDescriptor *intern = emalloc(sizeof(EnumValueDescriptor)); + zend_object_std_init(&intern->std, EnumValueDescriptor_class_entry); + intern->std.handlers = &EnumValueDescriptor_object_handlers; + intern->name = name; + intern->number = number; + // Skip object_properties_init(), we don't allow derived classes. + ZVAL_OBJ(val, &intern->std); +} -static zend_function_entry gpb_type_methods[] = { - ZEND_FE_END -}; +/* + * EnumValueDescriptor::getName() + * + * Returns the name for this enum value. + */ +PHP_METHOD(EnumValueDescriptor, getName) { + EnumValueDescriptor *intern = (EnumValueDescriptor*)Z_OBJ_P(getThis()); + RETURN_STRING(intern->name); +} -void gpb_type_init(TSRMLS_D) { - zend_class_entry class_type; - INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBType", - gpb_type_methods); - gpb_type_type = zend_register_internal_class(&class_type TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("DOUBLE"), 1 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("FLOAT"), 2 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("INT64"), 3 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("UINT64"), 4 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("INT32"), 5 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("FIXED64"), 6 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("FIXED32"), 7 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("BOOL"), 8 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("STRING"), 9 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("GROUP"), 10 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("MESSAGE"), 11 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("BYTES"), 12 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("UINT32"), 13 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("ENUM"), 14 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("SFIXED32"), - 15 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("SFIXED64"), - 16 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("SINT32"), 17 TSRMLS_CC); - zend_declare_class_constant_long(gpb_type_type, STR("SINT64"), 18 TSRMLS_CC); +/* + * EnumValueDescriptor::getNumber() + * + * Returns the number for this enum value. + */ +PHP_METHOD(EnumValueDescriptor, getNumber) { + EnumValueDescriptor *intern = (EnumValueDescriptor*)Z_OBJ_P(getThis()); + RETURN_LONG(intern->number); } +static zend_function_entry EnumValueDescriptor_methods[] = { + PHP_ME(EnumValueDescriptor, getName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(EnumValueDescriptor, getNumber, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + // ----------------------------------------------------------------------------- -// Descriptor +// EnumDescriptor // ----------------------------------------------------------------------------- -static zend_function_entry descriptor_methods[] = { - PHP_ME(Descriptor, getClass, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Descriptor, getFullName, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Descriptor, getField, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Descriptor, getFieldCount, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Descriptor, getOneofDecl, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Descriptor, getOneofDeclCount, NULL, ZEND_ACC_PUBLIC) - ZEND_FE_END -}; +typedef struct { + zend_object std; + const upb_enumdef *enumdef; +} EnumDescriptor; -DEFINE_CLASS(Descriptor, descriptor, "Google\\Protobuf\\Descriptor"); +zend_class_entry *EnumDescriptor_class_entry; +static zend_object_handlers EnumDescriptor_object_handlers; -static void descriptor_free_c(Descriptor *self TSRMLS_DC) { - if (self->layout) { - free_layout(self->layout); - } - if (self->fill_handlers) { - upb_handlers_unref(self->fill_handlers, &self->fill_handlers); - } - if (self->fill_method) { - upb_pbdecodermethod_unref(self->fill_method, &self->fill_method); - } - if (self->json_fill_method) { - upb_json_parsermethod_unref(self->json_fill_method, - &self->json_fill_method); - } - if (self->pb_serialize_handlers) { - upb_handlers_unref(self->pb_serialize_handlers, - &self->pb_serialize_handlers); - } - if (self->json_serialize_handlers) { - upb_handlers_unref(self->json_serialize_handlers, - &self->json_serialize_handlers); - } - if (self->json_serialize_handlers_preserve) { - upb_handlers_unref(self->json_serialize_handlers_preserve, - &self->json_serialize_handlers_preserve); +void EnumDescriptor_FromClassEntry(zval *val, zend_class_entry *ce) { + // To differentiate enums from classes, we pointer-tag the class entry. + void* key = (void*)((uintptr_t)ce | 1); + PBPHP_ASSERT(key != ce); + + if (ce == NULL) { + ZVAL_NULL(val); + return; } -} -static void descriptor_init_c_instance(Descriptor *desc TSRMLS_DC) { - desc->msgdef = NULL; - desc->layout = NULL; - desc->klass = NULL; - desc->fill_handlers = NULL; - desc->fill_method = NULL; - desc->json_fill_method = NULL; - desc->pb_serialize_handlers = NULL; - desc->json_serialize_handlers = NULL; - desc->json_serialize_handlers_preserve = NULL; -} + if (!ObjCache_Get(key, val)) { + const upb_enumdef *e = NameMap_GetEnum(ce); + if (!e) { + ZVAL_NULL(val); + return; + } + EnumDescriptor* ret = emalloc(sizeof(EnumDescriptor)); + zend_object_std_init(&ret->std, EnumDescriptor_class_entry); + ret->std.handlers = &EnumDescriptor_object_handlers; + ret->enumdef = e; + ObjCache_Add(key, &ret->std); -PHP_METHOD(Descriptor, getClass) { - Descriptor *intern = UNBOX(Descriptor, getThis()); -#if PHP_MAJOR_VERSION < 7 - const char* classname = intern->klass->name; -#else - const char* classname = ZSTR_VAL(intern->klass->name); -#endif - PHP_PROTO_RETVAL_STRINGL(classname, strlen(classname), 1); -} + // Prevent this from ever being collected (within a request). + GC_ADDREF(&ret->std); -PHP_METHOD(Descriptor, getFullName) { - Descriptor *intern = UNBOX(Descriptor, getThis()); - const char* fullname = upb_msgdef_fullname(intern->msgdef); - PHP_PROTO_RETVAL_STRINGL(fullname, strlen(fullname), 1); + ZVAL_OBJ(val, &ret->std); + } } -PHP_METHOD(Descriptor, getField) { - long index; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == - FAILURE) { - zend_error(E_USER_ERROR, "Expect integer for index.\n"); - return; - } +void EnumDescriptor_FromEnumDef(zval *val, const upb_enumdef *m) { + if (!m) { + ZVAL_NULL(val); + } else { + char *classname = + GetPhpClassname(upb_enumdef_file(m), upb_enumdef_fullname(m)); + zend_string *str = zend_string_init(classname, strlen(classname), 0); + zend_class_entry *ce = zend_lookup_class(str); // May autoload the class. - Descriptor *intern = UNBOX(Descriptor, getThis()); - int field_num = upb_msgdef_numfields(intern->msgdef); - if (index < 0 || index >= field_num) { - zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); - return; - } + zend_string_release (str); - upb_msg_field_iter iter; - int i; - for(upb_msg_field_begin(&iter, intern->msgdef), i = 0; - !upb_msg_field_done(&iter) && i < index; - upb_msg_field_next(&iter), i++); - const upb_fielddef *field = upb_msg_iter_field(&iter); + if (!ce) { + zend_error(E_ERROR, "Couldn't load generated class %s", classname); + } - PHP_PROTO_HASHTABLE_VALUE field_hashtable_value = get_def_obj(field); - if (field_hashtable_value == NULL) { -#if PHP_MAJOR_VERSION < 7 - MAKE_STD_ZVAL(field_hashtable_value); - ZVAL_OBJ(field_hashtable_value, field_descriptor_type->create_object( - field_descriptor_type TSRMLS_CC)); -#else - field_hashtable_value = - field_descriptor_type->create_object(field_descriptor_type TSRMLS_CC); -#endif - FieldDescriptor *field_php = - UNBOX_HASHTABLE_VALUE(FieldDescriptor, field_hashtable_value); - field_php->fielddef = field; - add_def_obj(field, field_hashtable_value); - } - -#if PHP_MAJOR_VERSION < 7 - RETURN_ZVAL(field_hashtable_value, 1, 0); -#else - ++GC_REFCOUNT(field_hashtable_value); - RETURN_OBJ(field_hashtable_value); -#endif + free(classname); + EnumDescriptor_FromClassEntry(val, ce); + } } -PHP_METHOD(Descriptor, getFieldCount) { - Descriptor *intern = UNBOX(Descriptor, getThis()); - RETURN_LONG(upb_msgdef_numfields(intern->msgdef)); -} +/* + * EnumDescriptor::getValue() + * + * Returns an EnumValueDescriptor for this index. Note: we are not looking + * up by numeric enum value, but by the index in the list of enum values. + */ +PHP_METHOD(EnumDescriptor, getValue) { + EnumDescriptor *intern = (EnumDescriptor*)Z_OBJ_P(getThis()); + zend_long index; + zval ret; -PHP_METHOD(Descriptor, getOneofDecl) { - long index; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == - FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { zend_error(E_USER_ERROR, "Expect integer for index.\n"); return; } - Descriptor *intern = UNBOX(Descriptor, getThis()); - int field_num = upb_msgdef_numoneofs(intern->msgdef); + int field_num = upb_enumdef_numvals(intern->enumdef); if (index < 0 || index >= field_num) { zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); return; } - upb_msg_oneof_iter iter; + upb_enum_iter iter; int i; - for(upb_msg_oneof_begin(&iter, intern->msgdef), i = 0; - !upb_msg_oneof_done(&iter) && i < index; - upb_msg_oneof_next(&iter), i++); - upb_oneofdef *oneof = upb_msg_iter_oneof(&iter); + for(upb_enum_begin(&iter, intern->enumdef), i = 0; + !upb_enum_done(&iter) && i < index; + upb_enum_next(&iter), i++); - ZVAL_OBJ(return_value, oneof_descriptor_type->create_object( - oneof_descriptor_type TSRMLS_CC)); - Oneof *oneof_php = UNBOX(Oneof, return_value); - oneof_php->oneofdef = oneof; + EnumValueDescriptor_Make(&ret, upb_enum_iter_name(&iter), + upb_enum_iter_number(&iter)); + RETURN_ZVAL(&ret, 0, 1); } -PHP_METHOD(Descriptor, getOneofDeclCount) { - Descriptor *intern = UNBOX(Descriptor, getThis()); - RETURN_LONG(upb_msgdef_numoneofs(intern->msgdef)); +/* + * EnumDescriptor::getValueCount() + * + * Returns the number of values in this enum. + */ +PHP_METHOD(EnumDescriptor, getValueCount) { + EnumDescriptor *intern = (EnumDescriptor*)Z_OBJ_P(getThis()); + RETURN_LONG(upb_enumdef_numvals(intern->enumdef)); } -// ----------------------------------------------------------------------------- -// EnumDescriptor -// ----------------------------------------------------------------------------- +/* + * EnumDescriptor::getPublicDescriptor() + * + * Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not + * have two separate EnumDescriptor classes. We use a single class for both + * the public and private descriptor. + */ +PHP_METHOD(EnumDescriptor, getPublicDescriptor) { + RETURN_ZVAL(getThis(), 1, 0); +} -static zend_function_entry enum_descriptor_methods[] = { - PHP_ME(EnumDescriptor, getValue, NULL, ZEND_ACC_PUBLIC) - PHP_ME(EnumDescriptor, getValueCount, NULL, ZEND_ACC_PUBLIC) +static zend_function_entry EnumDescriptor_methods[] = { + PHP_ME(EnumDescriptor, getPublicDescriptor, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(EnumDescriptor, getValueCount, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(EnumDescriptor, getValue, arginfo_void, ZEND_ACC_PUBLIC) ZEND_FE_END }; -DEFINE_CLASS(EnumDescriptor, enum_descriptor, - "Google\\Protobuf\\EnumDescriptor"); +// ----------------------------------------------------------------------------- +// Oneof +// ----------------------------------------------------------------------------- + +typedef struct { + zend_object std; + const upb_oneofdef *oneofdef; +} OneofDescriptor; + +zend_class_entry *OneofDescriptor_class_entry; +static zend_object_handlers OneofDescriptor_object_handlers; -static void enum_descriptor_free_c(EnumDescriptor *self TSRMLS_DC) { +static void OneofDescriptor_FromOneofDef(zval *val, const upb_oneofdef *o) { + if (o == NULL) { + ZVAL_NULL(val); + return; + } + + if (!ObjCache_Get(o, val)) { + OneofDescriptor* ret = emalloc(sizeof(OneofDescriptor)); + zend_object_std_init(&ret->std, OneofDescriptor_class_entry); + ret->std.handlers = &OneofDescriptor_object_handlers; + ret->oneofdef = o; + ObjCache_Add(o, &ret->std); + + // Prevent this from ever being collected (within a request). + GC_ADDREF(&ret->std); + + ZVAL_OBJ(val, &ret->std); + } } -static void enum_descriptor_init_c_instance(EnumDescriptor *self TSRMLS_DC) { - self->enumdef = NULL; - self->klass = NULL; +/* + * OneofDescriptor::getName() + * + * Returns the name of this oneof. + */ +PHP_METHOD(OneofDescriptor, getName) { + OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis()); + RETURN_STRING(upb_oneofdef_name(intern->oneofdef)); } -PHP_METHOD(EnumDescriptor, getValue) { - long index; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == - FAILURE) { +/* + * OneofDescriptor::getField() + * + * Returns a field from this oneof. The given index must be in the range + * [0, getFieldCount() - 1]. + */ +PHP_METHOD(OneofDescriptor, getField) { + OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis()); + zend_long index; + zval ret; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { zend_error(E_USER_ERROR, "Expect integer for index.\n"); return; } - EnumDescriptor *intern = UNBOX(EnumDescriptor, getThis()); - int field_num = upb_enumdef_numvals(intern->enumdef); + int field_num = upb_oneofdef_numfields(intern->oneofdef); if (index < 0 || index >= field_num) { zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); return; } - upb_enum_iter iter; + upb_oneof_iter iter; int i; - for(upb_enum_begin(&iter, intern->enumdef), i = 0; - !upb_enum_done(&iter) && i < index; - upb_enum_next(&iter), i++); + for(upb_oneof_begin(&iter, intern->oneofdef), i = 0; + !upb_oneof_done(&iter) && i < index; + upb_oneof_next(&iter), i++); + const upb_fielddef *field = upb_oneof_iter_field(&iter); - ZVAL_OBJ(return_value, enum_value_descriptor_type->create_object( - enum_value_descriptor_type TSRMLS_CC)); - EnumValueDescriptor *enum_value_php = - UNBOX(EnumValueDescriptor, return_value); - enum_value_php->name = upb_enum_iter_name(&iter); - enum_value_php->number = upb_enum_iter_number(&iter); + FieldDescriptor_FromFieldDef(&ret, field); + RETURN_ZVAL(&ret, 1, 0); } -PHP_METHOD(EnumDescriptor, getValueCount) { - EnumDescriptor *intern = UNBOX(EnumDescriptor, getThis()); - RETURN_LONG(upb_enumdef_numvals(intern->enumdef)); +/* + * OneofDescriptor::getFieldCount() + * + * Returns the number of fields in this oneof. + */ +PHP_METHOD(OneofDescriptor, getFieldCount) { + OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis()); + RETURN_LONG(upb_oneofdef_numfields(intern->oneofdef)); } -// ----------------------------------------------------------------------------- -// EnumValueDescriptor -// ----------------------------------------------------------------------------- - -static zend_function_entry enum_value_descriptor_methods[] = { - PHP_ME(EnumValueDescriptor, getName, NULL, ZEND_ACC_PUBLIC) - PHP_ME(EnumValueDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC) +static zend_function_entry OneofDescriptor_methods[] = { + PHP_ME(OneofDescriptor, getName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(OneofDescriptor, getField, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(OneofDescriptor, getFieldCount, arginfo_void, ZEND_ACC_PUBLIC) ZEND_FE_END }; -DEFINE_CLASS(EnumValueDescriptor, enum_value_descriptor, - "Google\\Protobuf\\EnumValueDescriptor"); - -static void enum_value_descriptor_free_c(EnumValueDescriptor *self TSRMLS_DC) { -} - -static void enum_value_descriptor_init_c_instance(EnumValueDescriptor *self TSRMLS_DC) { - self->name = NULL; - self->number = 0; -} - -PHP_METHOD(EnumValueDescriptor, getName) { - EnumValueDescriptor *intern = UNBOX(EnumValueDescriptor, getThis()); - PHP_PROTO_RETVAL_STRINGL(intern->name, strlen(intern->name), 1); -} - -PHP_METHOD(EnumValueDescriptor, getNumber) { - EnumValueDescriptor *intern = UNBOX(EnumValueDescriptor, getThis()); - RETURN_LONG(intern->number); -} - // ----------------------------------------------------------------------------- // FieldDescriptor // ----------------------------------------------------------------------------- -static zend_function_entry field_descriptor_methods[] = { - PHP_ME(FieldDescriptor, getName, NULL, ZEND_ACC_PUBLIC) - PHP_ME(FieldDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC) - PHP_ME(FieldDescriptor, getLabel, NULL, ZEND_ACC_PUBLIC) - PHP_ME(FieldDescriptor, getType, NULL, ZEND_ACC_PUBLIC) - PHP_ME(FieldDescriptor, isMap, NULL, ZEND_ACC_PUBLIC) - PHP_ME(FieldDescriptor, getEnumType, NULL, ZEND_ACC_PUBLIC) - PHP_ME(FieldDescriptor, getMessageType, NULL, ZEND_ACC_PUBLIC) - ZEND_FE_END -}; +typedef struct { + zend_object std; + const upb_fielddef *fielddef; +} FieldDescriptor; -DEFINE_CLASS(FieldDescriptor, field_descriptor, - "Google\\Protobuf\\FieldDescriptor"); +zend_class_entry *FieldDescriptor_class_entry; +static zend_object_handlers FieldDescriptor_object_handlers; -static void field_descriptor_free_c(FieldDescriptor *self TSRMLS_DC) { -} +static void FieldDescriptor_FromFieldDef(zval *val, const upb_fielddef *f) { + if (f == NULL) { + ZVAL_NULL(val); + return; + } + + if (!ObjCache_Get(f, val)) { + FieldDescriptor* ret = emalloc(sizeof(FieldDescriptor)); + zend_object_std_init(&ret->std, FieldDescriptor_class_entry); + ret->std.handlers = &FieldDescriptor_object_handlers; + ret->fielddef = f; + ObjCache_Add(f, &ret->std); + + // Prevent this from ever being collected (within a request). + GC_ADDREF(&ret->std); -static void field_descriptor_init_c_instance(FieldDescriptor *self TSRMLS_DC) { - self->fielddef = NULL; + ZVAL_OBJ(val, &ret->std); + } } upb_fieldtype_t to_fieldtype(upb_descriptortype_t type) { @@ -479,536 +387,763 @@ upb_fieldtype_t to_fieldtype(upb_descriptortype_t type) { return 0; } +/* + * FieldDescriptor::getName() + * + * Returns the name of this field. + */ PHP_METHOD(FieldDescriptor, getName) { - FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis()); - const char* name = upb_fielddef_name(intern->fielddef); - PHP_PROTO_RETVAL_STRINGL(name, strlen(name), 1); + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); + RETURN_STRING(upb_fielddef_name(intern->fielddef)); } +/* + * FieldDescriptor::getNumber() + * + * Returns the number of this field. + */ PHP_METHOD(FieldDescriptor, getNumber) { - FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis()); + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); RETURN_LONG(upb_fielddef_number(intern->fielddef)); } +/* + * FieldDescriptor::getLabel() + * + * Returns the label of this field as an integer. + */ PHP_METHOD(FieldDescriptor, getLabel) { - FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis()); + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); RETURN_LONG(upb_fielddef_label(intern->fielddef)); } +/* + * FieldDescriptor::getType() + * + * Returns the type of this field as an integer. + */ PHP_METHOD(FieldDescriptor, getType) { - FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis()); + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); RETURN_LONG(upb_fielddef_descriptortype(intern->fielddef)); } +/* + * FieldDescriptor::isMap() + * + * Returns true if this field is a map. + */ PHP_METHOD(FieldDescriptor, isMap) { - FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis()); + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); RETURN_BOOL(upb_fielddef_ismap(intern->fielddef)); } +/* + * FieldDescriptor::getEnumType() + * + * Returns the EnumDescriptor for this field, which must be an enum. + */ PHP_METHOD(FieldDescriptor, getEnumType) { - FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis()); - const upb_enumdef *enumdef = upb_fielddef_enumsubdef(intern->fielddef); - if (enumdef == NULL) { - char error_msg[100]; - sprintf(error_msg, "Cannot get enum type for non-enum field '%s'", - upb_fielddef_name(intern->fielddef)); - zend_throw_exception(NULL, error_msg, 0 TSRMLS_CC); + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); + const upb_enumdef *e = upb_fielddef_enumsubdef(intern->fielddef); + zval ret; + + if (!e) { + zend_throw_exception_ex(NULL, 0, + "Cannot get enum type for non-enum field '%s'", + upb_fielddef_name(intern->fielddef)); return; } - PHP_PROTO_HASHTABLE_VALUE desc = get_def_obj(enumdef); -#if PHP_MAJOR_VERSION < 7 - RETURN_ZVAL(desc, 1, 0); -#else - ++GC_REFCOUNT(desc); - RETURN_OBJ(desc); -#endif + EnumDescriptor_FromEnumDef(&ret, e); + RETURN_ZVAL(&ret, 1, 0); } +/* + * FieldDescriptor::getMessageType() + * + * Returns the Descriptor for this field, which must be a message. + */ PHP_METHOD(FieldDescriptor, getMessageType) { - FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis()); - const upb_msgdef *msgdef = upb_fielddef_msgsubdef(intern->fielddef); - if (msgdef == NULL) { - char error_msg[100]; - sprintf(error_msg, "Cannot get message type for non-message field '%s'", - upb_fielddef_name(intern->fielddef)); - zend_throw_exception(NULL, error_msg, 0 TSRMLS_CC); + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); + Descriptor* desc = Descriptor_GetFromFieldDef(intern->fielddef); + zval ret; + + if (!desc) { + zend_throw_exception_ex( + NULL, 0, "Cannot get message type for non-message field '%s'", + upb_fielddef_name(intern->fielddef)); return; } - PHP_PROTO_HASHTABLE_VALUE desc = get_def_obj(msgdef); -#if PHP_MAJOR_VERSION < 7 - RETURN_ZVAL(desc, 1, 0); -#else - ++GC_REFCOUNT(desc); - RETURN_OBJ(desc); -#endif + ZVAL_OBJ(&ret, &desc->std); + RETURN_ZVAL(&ret, 1, 0); } +static zend_function_entry FieldDescriptor_methods[] = { + PHP_ME(FieldDescriptor, getName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(FieldDescriptor, getNumber, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(FieldDescriptor, getLabel, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(FieldDescriptor, getType, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(FieldDescriptor, isMap, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(FieldDescriptor, getEnumType, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(FieldDescriptor, getMessageType, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + // ----------------------------------------------------------------------------- -// Oneof +// Descriptor // ----------------------------------------------------------------------------- -static zend_function_entry oneof_descriptor_methods[] = { - PHP_ME(Oneof, getName, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Oneof, getField, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Oneof, getFieldCount, NULL, ZEND_ACC_PUBLIC) - ZEND_FE_END -}; +zend_class_entry *Descriptor_class_entry; +static zend_object_handlers Descriptor_object_handlers; + +static void Descriptor_destructor(zend_object* obj) { + // We don't really need to do anything here, we don't allow this to be + // collected before the end of the request. +} + +// C Functions from def.h ////////////////////////////////////////////////////// -DEFINE_CLASS(Oneof, oneof_descriptor, - "Google\\Protobuf\\OneofDescriptor"); +// These are documented in the header file. -static void oneof_descriptor_free_c(Oneof *self TSRMLS_DC) { +void Descriptor_FromClassEntry(zval *val, zend_class_entry *ce) { + if (ce == NULL) { + ZVAL_NULL(val); + return; + } + + if (!ObjCache_Get(ce, val)) { + const upb_msgdef *msgdef = NameMap_GetMessage(ce); + if (!msgdef) { + ZVAL_NULL(val); + return; + } + Descriptor* ret = emalloc(sizeof(Descriptor)); + zend_object_std_init(&ret->std, Descriptor_class_entry); + ret->std.handlers = &Descriptor_object_handlers; + ret->class_entry = ce; + ret->msgdef = msgdef; + ObjCache_Add(ce, &ret->std); + + // Prevent this from ever being collected (within a request). + GC_ADDREF(&ret->std); + + ZVAL_OBJ(val, &ret->std); + } } -static void oneof_descriptor_init_c_instance(Oneof *self TSRMLS_DC) { - self->oneofdef = NULL; +Descriptor* Descriptor_GetFromClassEntry(zend_class_entry *ce) { + zval desc; + Descriptor_FromClassEntry(&desc, ce); + if (Z_TYPE_P(&desc) == IS_NULL) { + return NULL; + } else { + return (Descriptor*)Z_OBJ_P(&desc); + } } -PHP_METHOD(Oneof, getName) { - Oneof *intern = UNBOX(Oneof, getThis()); - const char *name = upb_oneofdef_name(intern->oneofdef); - PHP_PROTO_RETVAL_STRINGL(name, strlen(name), 1); +Descriptor* Descriptor_GetFromMessageDef(const upb_msgdef *m) { + if (m) { + if (upb_msgdef_mapentry(m)) { + // A bit of a hack, since map entries don't have classes. + Descriptor* ret = emalloc(sizeof(Descriptor)); + zend_object_std_init(&ret->std, Descriptor_class_entry); + ret->std.handlers = &Descriptor_object_handlers; + ret->class_entry = NULL; + ret->msgdef = m; + + // Prevent this from ever being collected (within a request). + GC_ADDREF(&ret->std); + + return ret; + } + + char *classname = + GetPhpClassname(upb_msgdef_file(m), upb_msgdef_fullname(m)); + zend_string *str = zend_string_init(classname, strlen(classname), 0); + zend_class_entry *ce = zend_lookup_class(str); // May autoload the class. + + zend_string_release (str); + + if (!ce) { + zend_error(E_ERROR, "Couldn't load generated class %s", classname); + } + + free(classname); + return Descriptor_GetFromClassEntry(ce); + } else { + return NULL; + } } -PHP_METHOD(Oneof, getField) { - long index; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == - FAILURE) { +Descriptor* Descriptor_GetFromFieldDef(const upb_fielddef *f) { + return Descriptor_GetFromMessageDef(upb_fielddef_msgsubdef(f)); +} + +/* + * Descriptor::getPublicDescriptor() + * + * Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not + * have two separate EnumDescriptor classes. We use a single class for both + * the public and private descriptor. + */ +PHP_METHOD(Descriptor, getPublicDescriptor) { + RETURN_ZVAL(getThis(), 1, 0); +} + +/* + * Descriptor::getFullName() + * + * Returns the full name for this message type. + */ +PHP_METHOD(Descriptor, getFullName) { + Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis()); + RETURN_STRING(upb_msgdef_fullname(intern->msgdef)); +} + +/* + * Descriptor::getField() + * + * Returns a FieldDescriptor for the given index, which must be in the range + * [0, getFieldCount()-1]. + */ +PHP_METHOD(Descriptor, getField) { + Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis()); + int count = upb_msgdef_numfields(intern->msgdef); + zval ret; + zend_long index; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { zend_error(E_USER_ERROR, "Expect integer for index.\n"); return; } - Oneof *intern = UNBOX(Oneof, getThis()); - int field_num = upb_oneofdef_numfields(intern->oneofdef); + if (index < 0 || index >= count) { + zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); + return; + } + + upb_msg_field_iter iter; + int i; + for(upb_msg_field_begin(&iter, intern->msgdef), i = 0; + !upb_msg_field_done(&iter) && i < index; + upb_msg_field_next(&iter), i++); + const upb_fielddef *field = upb_msg_iter_field(&iter); + + FieldDescriptor_FromFieldDef(&ret, field); + RETURN_ZVAL(&ret, 1, 0); +} + +/* + * Descriptor::getFieldCount() + * + * Returns the number of fields in this message. + */ +PHP_METHOD(Descriptor, getFieldCount) { + Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis()); + RETURN_LONG(upb_msgdef_numfields(intern->msgdef)); +} + +/* + * Descriptor::getOneofDecl() + * + * Returns a OneofDescriptor for the given index, which must be in the range + * [0, getOneofDeclCount()]. + */ +PHP_METHOD(Descriptor, getOneofDecl) { + Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis()); + zend_long index; + zval ret; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { + zend_error(E_USER_ERROR, "Expect integer for index.\n"); + return; + } + + int field_num = upb_msgdef_numoneofs(intern->msgdef); if (index < 0 || index >= field_num) { zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); return; } - upb_oneof_iter iter; + upb_msg_oneof_iter iter; int i; - for(upb_oneof_begin(&iter, intern->oneofdef), i = 0; - !upb_oneof_done(&iter) && i < index; - upb_oneof_next(&iter), i++); - const upb_fielddef *field = upb_oneof_iter_field(&iter); + for(upb_msg_oneof_begin(&iter, intern->msgdef), i = 0; + !upb_msg_oneof_done(&iter) && i < index; + upb_msg_oneof_next(&iter), i++); + const upb_oneofdef *oneof = upb_msg_iter_oneof(&iter); - PHP_PROTO_HASHTABLE_VALUE field_hashtable_value = get_def_obj(field); - if (field_hashtable_value == NULL) { -#if PHP_MAJOR_VERSION < 7 - MAKE_STD_ZVAL(field_hashtable_value); - ZVAL_OBJ(field_hashtable_value, field_descriptor_type->create_object( - field_descriptor_type TSRMLS_CC)); -#else - field_hashtable_value = - field_descriptor_type->create_object(field_descriptor_type TSRMLS_CC); -#endif - FieldDescriptor *field_php = - UNBOX_HASHTABLE_VALUE(FieldDescriptor, field_hashtable_value); - field_php->fielddef = field; - add_def_obj(field, field_hashtable_value); - } - -#if PHP_MAJOR_VERSION < 7 - RETURN_ZVAL(field_hashtable_value, 1, 0); -#else - ++GC_REFCOUNT(field_hashtable_value); - RETURN_OBJ(field_hashtable_value); -#endif -} - -PHP_METHOD(Oneof, getFieldCount) { - Oneof *intern = UNBOX(Oneof, getThis()); - RETURN_LONG(upb_oneofdef_numfields(intern->oneofdef)); + OneofDescriptor_FromOneofDef(&ret, oneof); + RETURN_ZVAL(&ret, 1, 0); +} + +/* + * Descriptor::getOneofDeclCount() + * + * Returns the number of oneofs in this message. + */ +PHP_METHOD(Descriptor, getOneofDeclCount) { + Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis()); + RETURN_LONG(upb_msgdef_numoneofs(intern->msgdef)); +} + +/* + * Descriptor::getClass() + * + * Returns the name of the PHP class for this message. + */ +PHP_METHOD(Descriptor, getClass) { + Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis()); + const char* classname = ZSTR_VAL(intern->class_entry->name); + RETURN_STRING(classname); } + +static zend_function_entry Descriptor_methods[] = { + PHP_ME(Descriptor, getClass, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Descriptor, getFullName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Descriptor, getField, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Descriptor, getFieldCount, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Descriptor, getOneofDecl, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Descriptor, getOneofDeclCount, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Descriptor, getPublicDescriptor, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + // ----------------------------------------------------------------------------- // DescriptorPool // ----------------------------------------------------------------------------- -static zend_function_entry descriptor_pool_methods[] = { - PHP_ME(DescriptorPool, getGeneratedPool, NULL, - ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(DescriptorPool, getDescriptorByClassName, NULL, ZEND_ACC_PUBLIC) - PHP_ME(DescriptorPool, getEnumDescriptorByClassName, NULL, ZEND_ACC_PUBLIC) - ZEND_FE_END -}; +typedef struct DescriptorPool { + zend_object std; + upb_symtab *symtab; +} DescriptorPool; -static zend_function_entry internal_descriptor_pool_methods[] = { - PHP_ME(InternalDescriptorPool, getGeneratedPool, NULL, - ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(InternalDescriptorPool, internalAddGeneratedFile, NULL, ZEND_ACC_PUBLIC) - ZEND_FE_END -}; +zend_class_entry *DescriptorPool_class_entry; +static zend_object_handlers DescriptorPool_object_handlers; -DEFINE_CLASS(DescriptorPool, descriptor_pool, - "Google\\Protobuf\\DescriptorPool"); -DEFINE_CLASS(InternalDescriptorPool, internal_descriptor_pool, - "Google\\Protobuf\\Internal\\DescriptorPool"); - -// wrapper of generated pool -#if PHP_MAJOR_VERSION < 7 -zval* generated_pool_php; -zval* internal_generated_pool_php; -#else -zend_object *generated_pool_php; -zend_object *internal_generated_pool_php; -#endif -InternalDescriptorPool *generated_pool; // The actual generated pool - -static void init_generated_pool_once(TSRMLS_D) { - if (generated_pool == NULL) { -#if PHP_MAJOR_VERSION < 7 - MAKE_STD_ZVAL(generated_pool_php); - MAKE_STD_ZVAL(internal_generated_pool_php); - ZVAL_OBJ(internal_generated_pool_php, - internal_descriptor_pool_type->create_object( - internal_descriptor_pool_type TSRMLS_CC)); - generated_pool = UNBOX(InternalDescriptorPool, internal_generated_pool_php); - ZVAL_OBJ(generated_pool_php, descriptor_pool_type->create_object( - descriptor_pool_type TSRMLS_CC)); -#else - internal_generated_pool_php = internal_descriptor_pool_type->create_object( - internal_descriptor_pool_type TSRMLS_CC); - generated_pool = (InternalDescriptorPool *)((char *)internal_generated_pool_php - - XtOffsetOf(InternalDescriptorPool, std)); - generated_pool_php = - descriptor_pool_type->create_object(descriptor_pool_type TSRMLS_CC); -#endif - } -} - -static void internal_descriptor_pool_init_c_instance( - InternalDescriptorPool *pool TSRMLS_DC) { - pool->symtab = upb_symtab_new(); - - ALLOC_HASHTABLE(pool->pending_list); - zend_hash_init(pool->pending_list, 1, NULL, ZVAL_PTR_DTOR, 0); -} - -static void internal_descriptor_pool_free_c( - InternalDescriptorPool *pool TSRMLS_DC) { - upb_symtab_free(pool->symtab); - - zend_hash_destroy(pool->pending_list); - FREE_HASHTABLE(pool->pending_list); -} - -static void descriptor_pool_init_c_instance(DescriptorPool *pool TSRMLS_DC) { - assert(generated_pool != NULL); - pool->intern = generated_pool; -} - -static void descriptor_pool_free_c(DescriptorPool *pool TSRMLS_DC) { -} - -static void validate_enumdef(const upb_enumdef *enumdef) { - // Verify that an entry exists with integer value 0. (This is the default - // value.) - const char *lookup = upb_enumdef_iton(enumdef, 0); - if (lookup == NULL) { - zend_error(E_USER_ERROR, - "Enum definition does not contain a value for '0'."); - } -} - -static void validate_msgdef(const upb_msgdef* msgdef) { - // Verify that no required fields exist. proto3 does not support these. - upb_msg_field_iter it; - for (upb_msg_field_begin(&it, msgdef); - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* field = upb_msg_iter_field(&it); - if (upb_fielddef_label(field) == UPB_LABEL_REQUIRED) { - zend_error(E_ERROR, "Required fields are unsupported in proto3."); - } - } +static DescriptorPool *GetPool(const zval* this_ptr) { + return (DescriptorPool*)Z_OBJ_P(this_ptr); } -PHP_METHOD(DescriptorPool, getGeneratedPool) { - init_generated_pool_once(TSRMLS_C); -#if PHP_MAJOR_VERSION < 7 - RETURN_ZVAL(generated_pool_php, 1, 0); -#else - ++GC_REFCOUNT(generated_pool_php); - RETURN_OBJ(generated_pool_php); -#endif +/** + * Object handler to create an DescriptorPool. + */ +static zend_object* DescriptorPool_create(zend_class_entry *class_type) { + DescriptorPool *intern = emalloc(sizeof(DescriptorPool)); + zend_object_std_init(&intern->std, class_type); + intern->std.handlers = &DescriptorPool_object_handlers; + intern->symtab = upb_symtab_new(); + // Skip object_properties_init(), we don't allow derived classes. + return &intern->std; } -PHP_METHOD(InternalDescriptorPool, getGeneratedPool) { - init_generated_pool_once(TSRMLS_C); -#if PHP_MAJOR_VERSION < 7 - RETURN_ZVAL(internal_generated_pool_php, 1, 0); -#else - ++GC_REFCOUNT(internal_generated_pool_php); - RETURN_OBJ(internal_generated_pool_php); -#endif -} - -static void classname_no_prefix(const char *fullname, const char *package_name, - char *class_name) { - size_t i = 0, j; - bool first_char = true, is_reserved = false; - size_t pkg_name_len = package_name == NULL ? 0 : strlen(package_name); - size_t message_name_start = package_name == NULL ? 0 : pkg_name_len + 1; - size_t message_len = (strlen(fullname) - message_name_start); - - // Submessage is concatenated with its containing messages by '_'. - for (j = message_name_start; j < message_name_start + message_len; j++) { - if (fullname[j] == '.') { - class_name[i++] = '_'; - } else { - class_name[i++] = fullname[j]; - } +/** + * Object handler to free an DescriptorPool. + */ +static void DescriptorPool_destructor(zend_object* obj) { + DescriptorPool* intern = (DescriptorPool*)obj; + if (intern->symtab) { + upb_symtab_free(intern->symtab); } + intern->symtab = NULL; + zend_object_std_dtor(&intern->std); } -static const char *classname_prefix(const char *classname, - const char *prefix_given, - const char *package_name) { - size_t i; - bool is_reserved = false; +void DescriptorPool_CreateWithSymbolTable(zval *zv, upb_symtab *symtab) { + ZVAL_OBJ(zv, DescriptorPool_create(DescriptorPool_class_entry)); - if (prefix_given != NULL && strcmp(prefix_given, "") != 0) { - return prefix_given; + if (symtab) { + DescriptorPool *intern = GetPool(zv); + upb_symtab_free(intern->symtab); + intern->symtab = symtab; } +} - for (i = 0; i < kReservedNamesSize; i++) { - if (strcmp(kReservedNames[i], classname) == 0) { - is_reserved = true; - break; - } - } +upb_symtab *DescriptorPool_Steal(zval *zv) { + DescriptorPool *intern = GetPool(zv); + upb_symtab *ret = intern->symtab; + intern->symtab = NULL; + return ret; +} - if (is_reserved) { - if (package_name != NULL && strcmp("google.protobuf", package_name) == 0) { - return "GPB"; - } else { - return "PB"; - } - } +upb_symtab *DescriptorPool_GetSymbolTable() { + DescriptorPool *intern = GetPool(get_generated_pool()); + return intern->symtab; +} - return ""; -} - -static void convert_to_class_name_inplace(const char *package, - const char *namespace_given, - const char *prefix, char *classname) { - size_t prefix_len = prefix == NULL ? 0 : strlen(prefix); - size_t classname_len = strlen(classname); - int i = 0, j; - bool first_char = true; - - size_t package_len = package == NULL ? 0 : strlen(package); - size_t namespace_given_len = - namespace_given == NULL ? 0 : strlen(namespace_given); - bool use_namespace_given = namespace_given != NULL; - size_t namespace_len = - use_namespace_given ? namespace_given_len : package_len; - - int offset = namespace_len != 0 ? 2 : 0; - - for (j = 0; j < classname_len; j++) { - classname[namespace_len + prefix_len + classname_len + offset - 1 - j] = - classname[classname_len - j - 1]; - } - - if (namespace_len != 0) { - classname[i++] = '\\'; - for (j = 0; j < namespace_len; j++) { - if (use_namespace_given) { - classname[i++] = namespace_given[j]; - continue; - } - // php packages are divided by '\'. - if (package[j] == '.') { - classname[i++] = '\\'; - first_char = true; - } else if (first_char) { - // PHP package uses camel case. - if (package[j] < 'A' || package[j] > 'Z') { - classname[i++] = package[j] + 'A' - 'a'; - } else { - classname[i++] = package[j]; - } - first_char = false; - } else { - classname[i++] = package[j]; - } - } - classname[i++] = '\\'; - } - memcpy(classname + i, prefix, prefix_len); +/* + * DescriptorPool::getGeneratedPool() + * + * Returns the generated DescriptorPool. + */ +PHP_METHOD(DescriptorPool, getGeneratedPool) { + zval ret; + ZVAL_COPY(&ret, get_generated_pool()); + RETURN_ZVAL(&ret, 0, 1); } -PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) { - char *data = NULL; - PHP_PROTO_SIZE data_len; - upb_filedef **files; - size_t i; +/* + * DescriptorPool::getDescriptorByClassName() + * + * Returns a Descriptor object for the given PHP class name. + */ +PHP_METHOD(DescriptorPool, getDescriptorByClassName) { + char *classname = NULL; + zend_long classname_len; + zend_class_entry *ce; + zend_string *str; + zval ret; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) == + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &classname, &classname_len) == FAILURE) { return; } - InternalDescriptorPool *pool = UNBOX(InternalDescriptorPool, getThis()); - CHECK_UPB(files = upb_loaddescriptor(data, data_len, &pool, &status), - "Parse binary descriptors to internal descriptors failed"); - - // This method is called only once in each file. - assert(files[0] != NULL); - assert(files[1] == NULL); - - CHECK_UPB(upb_symtab_addfile(pool->symtab, files[0], &status), - "Unable to add file to DescriptorPool"); - - // For each enum/message, we need its PHP class, upb descriptor and its PHP - // wrapper. These information are needed later for encoding, decoding and type - // checking. However, sometimes we just have one of them. In order to find - // them quickly, here, we store the mapping for them. - for (i = 0; i < upb_filedef_defcount(files[0]); i++) { - const upb_def *def = upb_filedef_def(files[0], i); - switch (upb_def_type(def)) { -#define CASE_TYPE(def_type, def_type_lower, desc_type, desc_type_lower) \ - case UPB_DEF_##def_type: { \ - CREATE_HASHTABLE_VALUE(desc, desc_php, desc_type, desc_type_lower##_type); \ - const upb_##def_type_lower *def_type_lower = \ - upb_downcast_##def_type_lower(def); \ - desc->def_type_lower = def_type_lower; \ - add_def_obj(desc->def_type_lower, desc_php); \ - /* Unlike other messages, MapEntry is shared by all map fields and doesn't \ - * have generated PHP class.*/ \ - if (upb_def_type(def) == UPB_DEF_MSG && \ - upb_msgdef_mapentry(upb_downcast_msgdef(def))) { \ - break; \ - } \ - /* Prepend '.' to package name to make it absolute. In the 5 additional \ - * bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if \ - * given message is google.protobuf.Empty.*/ \ - const char *fullname = upb_##def_type_lower##_fullname(def_type_lower); \ - const char *php_namespace = upb_filedef_phpnamespace(files[0]); \ - const char *prefix_given = upb_filedef_phpprefix(files[0]); \ - size_t classname_len = strlen(fullname) + 5; \ - if (prefix_given != NULL) { \ - classname_len += strlen(prefix_given); \ - } \ - if (php_namespace != NULL) { \ - classname_len += strlen(php_namespace); \ - } \ - char *classname = ecalloc(sizeof(char), classname_len); \ - const char *package = upb_filedef_package(files[0]); \ - classname_no_prefix(fullname, package, classname); \ - const char *prefix = classname_prefix(classname, prefix_given, package); \ - convert_to_class_name_inplace(package, php_namespace, prefix, classname); \ - PHP_PROTO_CE_DECLARE pce; \ - if (php_proto_zend_lookup_class(classname, strlen(classname), &pce) == \ - FAILURE) { \ - zend_error(E_ERROR, "Generated message class %s hasn't been defined", \ - classname); \ - return; \ - } else { \ - desc->klass = PHP_PROTO_CE_UNREF(pce); \ - } \ - add_ce_obj(desc->klass, desc_php); \ - efree(classname); \ - break; \ - } - - CASE_TYPE(MSG, msgdef, Descriptor, descriptor) - CASE_TYPE(ENUM, enumdef, EnumDescriptor, enum_descriptor) -#undef CASE_TYPE - - default: - break; - } - } + str = zend_string_init(classname, strlen(classname), 0); + ce = zend_lookup_class(str); // May autoload the class. + zend_string_release (str); - for (i = 0; i < upb_filedef_defcount(files[0]); i++) { - const upb_def *def = upb_filedef_def(files[0], i); - if (upb_def_type(def) == UPB_DEF_MSG) { - const upb_msgdef *msgdef = upb_downcast_msgdef(def); - PHP_PROTO_HASHTABLE_VALUE desc_php = get_def_obj(msgdef); - build_class_from_descriptor(desc_php TSRMLS_CC); - } + if (!ce) { + RETURN_NULL(); } - upb_filedef_unref(files[0], &pool); - upb_gfree(files); + Descriptor_FromClassEntry(&ret, ce); + RETURN_ZVAL(&ret, 1, 0); } -PHP_METHOD(DescriptorPool, getDescriptorByClassName) { - DescriptorPool *public_pool = UNBOX(DescriptorPool, getThis()); - InternalDescriptorPool *pool = public_pool->intern; - +/* + * DescriptorPool::getEnumDescriptorByClassName() + * + * Returns a EnumDescriptor object for the given PHP class name. + */ +PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) { char *classname = NULL; - PHP_PROTO_SIZE classname_len; + zend_long classname_len; + zend_class_entry *ce; + zend_string *str; + zval ret; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname, - &classname_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &classname, &classname_len) == + FAILURE) { return; } - PHP_PROTO_CE_DECLARE pce; - if (php_proto_zend_lookup_class(classname, classname_len, &pce) == - FAILURE) { + str = zend_string_init(classname, strlen(classname), 0); + ce = zend_lookup_class(str); // May autoload the class. + zend_string_release (str); + + if (!ce) { RETURN_NULL(); } - PHP_PROTO_HASHTABLE_VALUE desc = get_ce_obj(PHP_PROTO_CE_UNREF(pce)); - if (desc == NULL) { - RETURN_NULL(); + EnumDescriptor_FromClassEntry(&ret, ce); + RETURN_ZVAL(&ret, 1, 0); +} + +/* + * DescriptorPool::getEnumDescriptorByProtoName() + * + * Returns a Descriptor object for the given protobuf message name. + */ +PHP_METHOD(DescriptorPool, getDescriptorByProtoName) { + DescriptorPool *intern = GetPool(getThis()); + char *protoname = NULL; + zend_long protoname_len; + const upb_msgdef *m; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &protoname, &protoname_len) == + FAILURE) { + return; } - zend_class_entry* instance_ce = HASHTABLE_VALUE_CE(desc); + if (*protoname == '.') protoname++; + + m = upb_symtab_lookupmsg(intern->symtab, protoname); - if (!instanceof_function(instance_ce, descriptor_type TSRMLS_CC)) { + if (m) { + zval ret; + ZVAL_OBJ(&ret, &Descriptor_GetFromMessageDef(m)->std); + RETURN_ZVAL(&ret, 1, 0); + } else { RETURN_NULL(); } +} -#if PHP_MAJOR_VERSION < 7 - RETURN_ZVAL(desc, 1, 0); -#else - ++GC_REFCOUNT(desc); - RETURN_OBJ(desc); -#endif +/* + * depends_on_descriptor() + * + * Returns true if this FileDescriptorProto depends on descriptor.proto. + */ +bool depends_on_descriptor(const google_protobuf_FileDescriptorProto* file) { + const upb_strview *deps; + upb_strview name = upb_strview_makez("google/protobuf/descriptor.proto"); + size_t i, n; + + deps = google_protobuf_FileDescriptorProto_dependency(file, &n); + for (i = 0; i < n; i++) { + if (upb_strview_eql(deps[i], name)) { + return true; + } + } + + return false; } -PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) { - DescriptorPool *public_pool = UNBOX(DescriptorPool, getThis()); - InternalDescriptorPool *pool = public_pool->intern; +/* + * add_name_mappings() + * + * Adds the messages and enums in this file to the NameMap. + */ +static void add_name_mappings(const upb_filedef *file) { + size_t i; + for (i = 0; i < upb_filedef_msgcount(file); i++) { + NameMap_AddMessage(upb_filedef_msg(file, i)); + } - char *classname = NULL; - PHP_PROTO_SIZE classname_len; + for (i = 0; i < upb_filedef_enumcount(file); i++) { + NameMap_AddEnum(upb_filedef_enum(file, i)); + } +} - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname, - &classname_len) == FAILURE) { +static void add_descriptor(DescriptorPool *pool, + const google_protobuf_FileDescriptorProto *file) { + upb_strview name = google_protobuf_FileDescriptorProto_name(file); + upb_status status; + const upb_filedef *file_def; + upb_status_clear(&status); + + if (upb_symtab_lookupfile2(pool->symtab, name.data, name.size)) { + // Already added. + zend_error(E_USER_WARNING, + "proto descriptor was previously loaded (included in multiple " + "metadata bundles?): " UPB_STRVIEW_FORMAT, + UPB_STRVIEW_ARGS(name)); return; } - PHP_PROTO_CE_DECLARE pce; - if (php_proto_zend_lookup_class(classname, classname_len, &pce) == - FAILURE) { - RETURN_NULL(); + // The PHP code generator currently special-cases descriptor.proto. It + // doesn't add it as a dependency even if the proto file actually does + // depend on it. + if (depends_on_descriptor(file)) { + google_protobuf_FileDescriptorProto_getmsgdef(pool->symtab); } - PHP_PROTO_HASHTABLE_VALUE desc = get_ce_obj(PHP_PROTO_CE_UNREF(pce)); - if (desc == NULL) { - RETURN_NULL(); + file_def = upb_symtab_addfile(pool->symtab, file, &status); + CheckUpbStatus(&status, "Unable to load descriptor"); + add_name_mappings(file_def); +} + +/* + * add_descriptor() + * + * Adds the given descriptor data to this DescriptorPool. + */ +static void add_descriptor_set(DescriptorPool *pool, const char *data, + int data_len, upb_arena *arena) { + size_t i, n; + google_protobuf_FileDescriptorSet *set; + const google_protobuf_FileDescriptorProto* const* files; + + set = google_protobuf_FileDescriptorSet_parse(data, data_len, arena); + + if (!set) { + zend_error(E_ERROR, "Failed to parse binary descriptor\n"); + return; } - zend_class_entry* instance_ce = HASHTABLE_VALUE_CE(desc); + files = google_protobuf_FileDescriptorSet_file(set, &n); - if (!instanceof_function(instance_ce, enum_descriptor_type TSRMLS_CC)) { - RETURN_NULL(); + for (i = 0; i < n; i++) { + const google_protobuf_FileDescriptorProto* file = files[i]; + add_descriptor(pool, file); + } +} + +bool DescriptorPool_HasFile(const char *filename) { + DescriptorPool *intern = GetPool(get_generated_pool()); + return upb_symtab_lookupfile(intern->symtab, filename) != NULL; +} + +void DescriptorPool_AddDescriptor(const char *filename, const char *data, + int size) { + upb_arena *arena = upb_arena_new(); + const google_protobuf_FileDescriptorProto *file = + google_protobuf_FileDescriptorProto_parse(data, size, arena); + + if (!file) { + zend_error(E_ERROR, "Failed to parse binary descriptor for %s\n", filename); + return; } -#if PHP_MAJOR_VERSION < 7 - RETURN_ZVAL(desc, 1, 0); -#else - ++GC_REFCOUNT(desc); - RETURN_OBJ(desc); -#endif + add_descriptor(GetPool(get_generated_pool()), file); + upb_arena_free(arena); +} + +/* + * DescriptorPool::internalAddGeneratedFile() + * + * Adds the given descriptor data to this DescriptorPool. + */ +PHP_METHOD(DescriptorPool, internalAddGeneratedFile) { + DescriptorPool *intern = GetPool(getThis()); + char *data = NULL; + zend_long data_len; + zend_bool use_nested_submsg = false; + upb_arena *arena; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &data, &data_len, + &use_nested_submsg) != SUCCESS) { + return; + } + + arena = upb_arena_new(); + add_descriptor_set(intern, data, data_len, arena); + upb_arena_free(arena); +} + +ZEND_BEGIN_ARG_INFO_EX(arginfo_addgeneratedfile, 0, 0, 2) + ZEND_ARG_INFO(0, data) + ZEND_ARG_INFO(0, data_len) +ZEND_END_ARG_INFO() + +static zend_function_entry DescriptorPool_methods[] = { + PHP_ME(DescriptorPool, getGeneratedPool, arginfo_void, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(DescriptorPool, getDescriptorByClassName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(DescriptorPool, getDescriptorByProtoName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(DescriptorPool, getEnumDescriptorByClassName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(DescriptorPool, internalAddGeneratedFile, arginfo_addgeneratedfile, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// InternalDescriptorPool +// ----------------------------------------------------------------------------- + +// For the C extension, Google\Protobuf\Internal\DescriptorPool is not a +// separate instantiable object, it just returns a +// Google\Protobuf\DescriptorPool. + +zend_class_entry *InternalDescriptorPool_class_entry; + +/* + * InternalDescriptorPool::getGeneratedPool() + * + * Returns the generated DescriptorPool. Note that this is identical to + * DescriptorPool::getGeneratedPool(), and in fact returns a DescriptorPool + * instance. + */ +PHP_METHOD(InternalDescriptorPool, getGeneratedPool) { + zval ret; + ZVAL_COPY(&ret, get_generated_pool()); + RETURN_ZVAL(&ret, 0, 1); +} + +static zend_function_entry InternalDescriptorPool_methods[] = { + PHP_ME(InternalDescriptorPool, getGeneratedPool, arginfo_void, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// GPBType +// ----------------------------------------------------------------------------- + +zend_class_entry* gpb_type_type; + +static zend_function_entry gpb_type_methods[] = { + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// Module Init +// ----------------------------------------------------------------------------- + +void Def_ModuleInit() { + zend_class_entry tmp_ce; + zend_object_handlers *h; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\OneofDescriptor", + OneofDescriptor_methods); + OneofDescriptor_class_entry = zend_register_internal_class(&tmp_ce); + OneofDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; + OneofDescriptor_class_entry->create_object = CreateHandler_ReturnNull; + h = &OneofDescriptor_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumValueDescriptor", + EnumValueDescriptor_methods); + EnumValueDescriptor_class_entry = zend_register_internal_class(&tmp_ce); + EnumValueDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; + EnumValueDescriptor_class_entry->create_object = CreateHandler_ReturnNull; + h = &EnumValueDescriptor_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumDescriptor", + EnumDescriptor_methods); + EnumDescriptor_class_entry = zend_register_internal_class(&tmp_ce); + EnumDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; + EnumDescriptor_class_entry->create_object = CreateHandler_ReturnNull; + h = &EnumDescriptor_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Descriptor", + Descriptor_methods); + + Descriptor_class_entry = zend_register_internal_class(&tmp_ce); + Descriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; + Descriptor_class_entry->create_object = CreateHandler_ReturnNull; + h = &Descriptor_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + h->dtor_obj = Descriptor_destructor; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\FieldDescriptor", + FieldDescriptor_methods); + FieldDescriptor_class_entry = zend_register_internal_class(&tmp_ce); + FieldDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; + FieldDescriptor_class_entry->create_object = CreateHandler_ReturnNull; + h = &FieldDescriptor_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\DescriptorPool", + DescriptorPool_methods); + DescriptorPool_class_entry = zend_register_internal_class(&tmp_ce); + DescriptorPool_class_entry->ce_flags |= ZEND_ACC_FINAL; + DescriptorPool_class_entry->create_object = DescriptorPool_create; + h = &DescriptorPool_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + h->dtor_obj = DescriptorPool_destructor; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\DescriptorPool", + InternalDescriptorPool_methods); + InternalDescriptorPool_class_entry = zend_register_internal_class(&tmp_ce); + + // GPBType. +#define STR(str) (str), strlen(str) + zend_class_entry class_type; + INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBType", + gpb_type_methods); + gpb_type_type = zend_register_internal_class(&class_type); + zend_declare_class_constant_long(gpb_type_type, STR("DOUBLE"), 1); + zend_declare_class_constant_long(gpb_type_type, STR("FLOAT"), 2); + zend_declare_class_constant_long(gpb_type_type, STR("INT64"), 3); + zend_declare_class_constant_long(gpb_type_type, STR("UINT64"), 4); + zend_declare_class_constant_long(gpb_type_type, STR("INT32"), 5); + zend_declare_class_constant_long(gpb_type_type, STR("FIXED64"), 6); + zend_declare_class_constant_long(gpb_type_type, STR("FIXED32"), 7); + zend_declare_class_constant_long(gpb_type_type, STR("BOOL"), 8); + zend_declare_class_constant_long(gpb_type_type, STR("STRING"), 9); + zend_declare_class_constant_long(gpb_type_type, STR("GROUP"), 10); + zend_declare_class_constant_long(gpb_type_type, STR("MESSAGE"), 11); + zend_declare_class_constant_long(gpb_type_type, STR("BYTES"), 12); + zend_declare_class_constant_long(gpb_type_type, STR("UINT32"), 13); + zend_declare_class_constant_long(gpb_type_type, STR("ENUM"), 14); + zend_declare_class_constant_long(gpb_type_type, STR("SFIXED32"), 15); + zend_declare_class_constant_long(gpb_type_type, STR("SFIXED64"), 16); + zend_declare_class_constant_long(gpb_type_type, STR("SINT32"), 17); + zend_declare_class_constant_long(gpb_type_type, STR("SINT64"), 18); +#undef STR } diff --git a/php/ext/google/protobuf/def.h b/php/ext/google/protobuf/def.h new file mode 100644 index 0000000000000..372c889b31ccf --- /dev/null +++ b/php/ext/google/protobuf/def.h @@ -0,0 +1,98 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef PHP_PROTOBUF_DEF_H_ +#define PHP_PROTOBUF_DEF_H_ + +#include + +#include "php-upb.h" + +// Initializes the Def module, which defines all of the descriptor classes. +void Def_ModuleInit(); + +// Creates a new DescriptorPool to wrap the given symtab. The DescriptorPool +// takes ownership of the given symtab. If symtab is NULL, the DescriptorPool +// will create an empty symtab instead. +void DescriptorPool_CreateWithSymbolTable(zval *zv, upb_symtab *symtab); + +// Given a zval representing a DescriptorPool, steals and returns its symtab, +// which is now owned by the caller. +upb_symtab *DescriptorPool_Steal(zval *zv); + +upb_symtab *DescriptorPool_GetSymbolTable(); + +// Returns true if the global descriptor pool already has the given filename. +bool DescriptorPool_HasFile(const char *filename); + +// Adds the given descriptor with the given filename to the global pool. +void DescriptorPool_AddDescriptor(const char *filename, const char *data, int size); + +typedef struct Descriptor { + zend_object std; + const upb_msgdef *msgdef; + zend_class_entry *class_entry; +} Descriptor; + +// Gets or creates a PHP Descriptor object for a |ce| and stores it in |val|. +// If this is not a protobuf generated class, |val| will be set to null. +void Descriptor_FromClassEntry(zval *val, zend_class_entry *ce); + +// Gets or creates a Descriptor* for the given class entry, upb_msgdef, or +// upb_fielddef. The returned Descriptor* will live for the entire request, +// so no ref is necessary to keep it alive. +Descriptor* Descriptor_GetFromClassEntry(zend_class_entry *ce); +Descriptor* Descriptor_GetFromMessageDef(const upb_msgdef *m); +Descriptor* Descriptor_GetFromFieldDef(const upb_fielddef *f); + +// Packages up a upb_fieldtype_t with a Descriptor, since many functions need +// both. +typedef struct { + upb_fieldtype_t type; + const Descriptor *desc; // When type == UPB_TYPE_MESSAGE. +} TypeInfo; + +static inline TypeInfo TypeInfo_Get(const upb_fielddef *f) { + TypeInfo ret = {upb_fielddef_type(f), Descriptor_GetFromFieldDef(f)}; + return ret; +} + +static inline TypeInfo TypeInfo_FromType(upb_fieldtype_t type) { + TypeInfo ret = {type}; + return ret; +} + +static inline bool TypeInfo_Eq(TypeInfo a, TypeInfo b) { + if (a.type != b.type) return false; + if (a.type == UPB_TYPE_MESSAGE && a.desc != b.desc) return false; + return true; +} + +#endif // PHP_PROTOBUF_DEF_H_ diff --git a/php/ext/google/protobuf/encode_decode.c b/php/ext/google/protobuf/encode_decode.c deleted file mode 100644 index 89e75d6a0d41e..0000000000000 --- a/php/ext/google/protobuf/encode_decode.c +++ /dev/null @@ -1,1565 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "protobuf.h" -#include "utf8.h" - -/* stringsink *****************************************************************/ - -typedef struct { - upb_byteshandler handler; - upb_bytessink sink; - char *ptr; - size_t len, size; -} stringsink; - - -static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) { - stringsink *sink = _sink; - sink->len = 0; - return sink; -} - -static size_t stringsink_string(void *_sink, const void *hd, const char *ptr, - size_t len, const upb_bufhandle *handle) { - stringsink *sink = _sink; - size_t new_size = sink->size; - - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - while (sink->len + len > new_size) { - new_size *= 2; - } - - if (new_size != sink->size) { - sink->ptr = realloc(sink->ptr, new_size); - sink->size = new_size; - } - - memcpy(sink->ptr + sink->len, ptr, len); - sink->len += len; - - return len; -} - -void stringsink_init(stringsink *sink) { - upb_byteshandler_init(&sink->handler); - upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL); - upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL); - - upb_bytessink_reset(&sink->sink, &sink->handler, sink); - - sink->size = 32; - sink->ptr = malloc(sink->size); - sink->len = 0; -} - -void stringsink_uninit(stringsink *sink) { free(sink->ptr); } - -/* stackenv *****************************************************************/ - -// Stack-allocated context during an encode/decode operation. Contains the upb -// environment and its stack-based allocator, an initial buffer for allocations -// to avoid malloc() when possible, and a template for PHP exception messages -// if any error occurs. -#define STACK_ENV_STACKBYTES 4096 -typedef struct { - upb_env env; - const char *php_error_template; - char allocbuf[STACK_ENV_STACKBYTES]; -} stackenv; - - -static void stackenv_init(stackenv* se, const char* errmsg); -static void stackenv_uninit(stackenv* se); - -// Callback invoked by upb if any error occurs during parsing or serialization. -static bool env_error_func(void* ud, const upb_status* status) { - char err_msg[100] = ""; - stackenv* se = ud; - // Free the env -- zend_error will longjmp up the stack past the - // encode/decode function so it would not otherwise have been freed. - stackenv_uninit(se); - - // TODO(teboring): have a way to verify that this is actually a parse error, - // instead of just throwing "parse error" unconditionally. - sprintf(err_msg, se->php_error_template, upb_status_errmsg(status)); - TSRMLS_FETCH(); - zend_throw_exception(NULL, err_msg, 0 TSRMLS_CC); - // Never reached. - return false; -} - -static void stackenv_init(stackenv* se, const char* errmsg) { - se->php_error_template = errmsg; - upb_env_init2(&se->env, se->allocbuf, sizeof(se->allocbuf), NULL); - upb_env_seterrorfunc(&se->env, env_error_func, se); -} - -static void stackenv_uninit(stackenv* se) { - upb_env_uninit(&se->env); -} - -// ----------------------------------------------------------------------------- -// Parsing. -// ----------------------------------------------------------------------------- - -#define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs) - -// Creates a handlerdata that simply contains the offset for this field. -static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) { - size_t* hd_ofs = (size_t*)malloc(sizeof(size_t)); - *hd_ofs = ofs; - upb_handlers_addcleanup(h, hd_ofs, free); - return hd_ofs; -} - -typedef struct { - size_t ofs; - const upb_msgdef *md; -} submsg_handlerdata_t; - -// Creates a handlerdata that contains offset and submessage type information. -static const void *newsubmsghandlerdata(upb_handlers* h, uint32_t ofs, - const upb_fielddef* f) { - submsg_handlerdata_t* hd = - (submsg_handlerdata_t*)malloc(sizeof(submsg_handlerdata_t)); - hd->ofs = ofs; - hd->md = upb_fielddef_msgsubdef(f); - upb_handlers_addcleanup(h, hd, free); - return hd; -} - -typedef struct { - size_t ofs; // union data slot - size_t case_ofs; // oneof_case field - int property_ofs; // properties table cache - uint32_t oneof_case_num; // oneof-case number to place in oneof_case field - const upb_msgdef *md; // msgdef, for oneof submessage handler - const upb_msgdef *parent_md; // msgdef, for parent submessage -} oneof_handlerdata_t; - -static const void *newoneofhandlerdata(upb_handlers *h, - uint32_t ofs, - uint32_t case_ofs, - int property_ofs, - const upb_msgdef *m, - const upb_fielddef *f) { - oneof_handlerdata_t* hd = - (oneof_handlerdata_t*)malloc(sizeof(oneof_handlerdata_t)); - hd->ofs = ofs; - hd->case_ofs = case_ofs; - hd->property_ofs = property_ofs; - hd->parent_md = m; - // We reuse the field tag number as a oneof union discriminant tag. Note that - // we don't expose these numbers to the user, so the only requirement is that - // we have some unique ID for each union case/possibility. The field tag - // numbers are already present and are easy to use so there's no reason to - // create a separate ID space. In addition, using the field tag number here - // lets us easily look up the field in the oneof accessor. - hd->oneof_case_num = upb_fielddef_number(f); - if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) { - hd->md = upb_fielddef_msgsubdef(f); - } else { - hd->md = NULL; - } - upb_handlers_addcleanup(h, hd, free); - return hd; -} - -// A handler that starts a repeated field. Gets the Repeated*Field instance for -// this field (such an instance always exists even in an empty message). -static void *startseq_handler(void* closure, const void* hd) { - MessageHeader* msg = closure; - const size_t *ofs = hd; - return CACHED_PTR_TO_ZVAL_PTR(DEREF(message_data(msg), *ofs, CACHED_VALUE*)); -} - -// Handlers that append primitive values to a repeated field. -#define DEFINE_APPEND_HANDLER(type, ctype) \ - static bool append##type##_handler(void* closure, const void* hd, \ - ctype val) { \ - zval* array = (zval*)closure; \ - TSRMLS_FETCH(); \ - RepeatedField* intern = UNBOX(RepeatedField, array); \ - repeated_field_push_native(intern, &val); \ - return true; \ - } - -DEFINE_APPEND_HANDLER(bool, bool) -DEFINE_APPEND_HANDLER(int32, int32_t) -DEFINE_APPEND_HANDLER(uint32, uint32_t) -DEFINE_APPEND_HANDLER(float, float) -DEFINE_APPEND_HANDLER(int64, int64_t) -DEFINE_APPEND_HANDLER(uint64, uint64_t) -DEFINE_APPEND_HANDLER(double, double) - -// Appends a string to a repeated field. -static void* appendstr_handler(void *closure, - const void *hd, - size_t size_hint) { - zval* array = (zval*)closure; - TSRMLS_FETCH(); - RepeatedField* intern = UNBOX(RepeatedField, array); - -#if PHP_MAJOR_VERSION < 7 - zval* str; - MAKE_STD_ZVAL(str); - PHP_PROTO_ZVAL_STRING(str, "", 1); - repeated_field_push_native(intern, &str); - return (void*)str; -#else - zend_string* str = zend_string_init("", 0, 1); - repeated_field_push_native(intern, &str); - return intern; -#endif -} - -// Appends a 'bytes' string to a repeated field. -static void* appendbytes_handler(void *closure, - const void *hd, - size_t size_hint) { - zval* array = (zval*)closure; - TSRMLS_FETCH(); - RepeatedField* intern = UNBOX(RepeatedField, array); - -#if PHP_MAJOR_VERSION < 7 - zval* str; - MAKE_STD_ZVAL(str); - PHP_PROTO_ZVAL_STRING(str, "", 1); - repeated_field_push_native(intern, &str); - return (void*)str; -#else - zend_string* str = zend_string_init("", 0, 1); - repeated_field_push_native(intern, &str); - return intern; -#endif -} - -// Handlers that append primitive values to a repeated field. -#define DEFINE_SINGULAR_HANDLER(type, ctype) \ - static bool type##_handler(void* closure, const void* hd, \ - ctype val) { \ - MessageHeader* msg = (MessageHeader*)closure; \ - const size_t *ofs = hd; \ - DEREF(message_data(msg), *ofs, ctype) = val; \ - return true; \ - } - -DEFINE_SINGULAR_HANDLER(bool, bool) -DEFINE_SINGULAR_HANDLER(int32, int32_t) -DEFINE_SINGULAR_HANDLER(uint32, uint32_t) -DEFINE_SINGULAR_HANDLER(float, float) -DEFINE_SINGULAR_HANDLER(int64, int64_t) -DEFINE_SINGULAR_HANDLER(uint64, uint64_t) -DEFINE_SINGULAR_HANDLER(double, double) - -#undef DEFINE_SINGULAR_HANDLER - -#if PHP_MAJOR_VERSION < 7 -static void *empty_php_string(zval** value_ptr) { - SEPARATE_ZVAL_IF_NOT_REF(value_ptr); - if (Z_TYPE_PP(value_ptr) == IS_STRING && - !IS_INTERNED(Z_STRVAL_PP(value_ptr))) { - FREE(Z_STRVAL_PP(value_ptr)); - } - ZVAL_EMPTY_STRING(*value_ptr); - return (void*)(*value_ptr); -} -#else -static void *empty_php_string(zval* value_ptr) { - if (Z_TYPE_P(value_ptr) == IS_STRING) { - zend_string_release(Z_STR_P(value_ptr)); - } - ZVAL_EMPTY_STRING(value_ptr); - return value_ptr; -} -#endif - -// Sets a non-repeated string field in a message. -static void* str_handler(void *closure, - const void *hd, - size_t size_hint) { - MessageHeader* msg = closure; - const size_t *ofs = hd; - return empty_php_string(DEREF(message_data(msg), *ofs, CACHED_VALUE*)); -} - -// Sets a non-repeated 'bytes' field in a message. -static void* bytes_handler(void *closure, - const void *hd, - size_t size_hint) { - MessageHeader* msg = closure; - const size_t *ofs = hd; - return empty_php_string(DEREF(message_data(msg), *ofs, CACHED_VALUE*)); -} - -static size_t stringdata_handler(void* closure, const void* hd, - const char* str, size_t len, - const upb_bufhandle* handle) { - zval* php_str = (zval*)closure; -#if PHP_MAJOR_VERSION < 7 - // Oneof string/bytes fields may have NULL initial value, which doesn't need - // to be freed. - if (Z_TYPE_P(php_str) == IS_STRING && !IS_INTERNED(Z_STRVAL_P(php_str))) { - FREE(Z_STRVAL_P(php_str)); - } - ZVAL_STRINGL(php_str, str, len, 1); -#else - if (Z_TYPE_P(php_str) == IS_STRING) { - zend_string_release(Z_STR_P(php_str)); - } - ZVAL_NEW_STR(php_str, zend_string_init(str, len, 0)); -#endif - return len; -} - -#if PHP_MAJOR_VERSION >= 7 -static size_t zendstringdata_handler(void* closure, const void* hd, - const char* str, size_t len, - const upb_bufhandle* handle) { - RepeatedField* intern = (RepeatedField*)closure; - - unsigned char memory[NATIVE_SLOT_MAX_SIZE]; - memset(memory, 0, NATIVE_SLOT_MAX_SIZE); - *(zend_string**)memory = zend_string_init(str, len, 0); - - HashTable *ht = PHP_PROTO_HASH_OF(intern->array); - int index = zend_hash_num_elements(ht) - 1; - php_proto_zend_hash_index_update_mem( - ht, index, memory, sizeof(zend_string*), NULL); - - return len; -} -#endif - -// Appends a submessage to a repeated field. -static void *appendsubmsg_handler(void *closure, const void *hd) { - zval* array = (zval*)closure; - TSRMLS_FETCH(); - RepeatedField* intern = UNBOX(RepeatedField, array); - - const submsg_handlerdata_t *submsgdata = hd; - Descriptor* subdesc = - UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)submsgdata->md)); - zend_class_entry* subklass = subdesc->klass; - MessageHeader* submsg; - -#if PHP_MAJOR_VERSION < 7 - zval* val = NULL; - MAKE_STD_ZVAL(val); - ZVAL_OBJ(val, subklass->create_object(subklass TSRMLS_CC)); - repeated_field_push_native(intern, &val); - submsg = UNBOX(MessageHeader, val); -#else - zend_object* obj = subklass->create_object(subklass TSRMLS_CC); - repeated_field_push_native(intern, &obj); - submsg = (MessageHeader*)((char*)obj - XtOffsetOf(MessageHeader, std)); -#endif - custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC); - - return submsg; -} - -// Sets a non-repeated submessage field in a message. -static void *submsg_handler(void *closure, const void *hd) { - MessageHeader* msg = closure; - const submsg_handlerdata_t* submsgdata = hd; - TSRMLS_FETCH(); - Descriptor* subdesc = - UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)submsgdata->md)); - zend_class_entry* subklass = subdesc->klass; - zval* submsg_php; - MessageHeader* submsg; - - if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(DEREF(message_data(msg), submsgdata->ofs, - CACHED_VALUE*))) == IS_NULL) { -#if PHP_MAJOR_VERSION < 7 - zval* val = NULL; - MAKE_STD_ZVAL(val); - ZVAL_OBJ(val, subklass->create_object(subklass TSRMLS_CC)); - MessageHeader* intern = UNBOX(MessageHeader, val); - custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC); - php_proto_zval_ptr_dtor(*DEREF(message_data(msg), submsgdata->ofs, zval**)); - *DEREF(message_data(msg), submsgdata->ofs, zval**) = val; -#else - zend_object* obj = subklass->create_object(subklass TSRMLS_CC); - ZVAL_OBJ(DEREF(message_data(msg), submsgdata->ofs, zval*), obj); - MessageHeader* intern = UNBOX_HASHTABLE_VALUE(MessageHeader, obj); - custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC); -#endif - } - - submsg_php = CACHED_PTR_TO_ZVAL_PTR( - DEREF(message_data(msg), submsgdata->ofs, CACHED_VALUE*)); - - submsg = UNBOX(MessageHeader, submsg_php); - return submsg; -} - -// Handler data for startmap/endmap handlers. -typedef struct { - size_t ofs; - upb_fieldtype_t key_field_type; - upb_fieldtype_t value_field_type; - - // We know that we can hold this reference because the handlerdata has the - // same lifetime as the upb_handlers struct, and the upb_handlers struct holds - // a reference to the upb_msgdef, which in turn has references to its subdefs. - const upb_def* value_field_subdef; -} map_handlerdata_t; - -// Temporary frame for map parsing: at the beginning of a map entry message, a -// submsg handler allocates a frame to hold (i) a reference to the Map object -// into which this message will be inserted and (ii) storage slots to -// temporarily hold the key and value for this map entry until the end of the -// submessage. When the submessage ends, another handler is called to insert the -// value into the map. -typedef struct { - char key_storage[NATIVE_SLOT_MAX_SIZE]; - char value_storage[NATIVE_SLOT_MAX_SIZE]; -} map_parse_frame_data_t; - -PHP_PROTO_WRAP_OBJECT_START(map_parse_frame_t) - map_parse_frame_data_t* data; // Place needs to be consistent with - // MessageHeader. - zval* map; - // In php7, we cannot allocate zval dynamically. So we need to add zval here - // to help decoding. - zval key_zval; - zval value_zval; -PHP_PROTO_WRAP_OBJECT_END -typedef struct map_parse_frame_t map_parse_frame_t; - -static void map_slot_init(void* memory, upb_fieldtype_t type, zval* cache) { - switch (type) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { -#if PHP_MAJOR_VERSION < 7 - // Store zval** in memory in order to be consistent with the layout of - // singular fields. - zval** holder = ALLOC(zval*); - zval* tmp; - MAKE_STD_ZVAL(tmp); - PHP_PROTO_ZVAL_STRINGL(tmp, "", 0, 1); - *holder = tmp; - *(zval***)memory = holder; -#else - *(zval**)memory = cache; - PHP_PROTO_ZVAL_STRINGL(*(zval**)memory, "", 0, 1); -#endif - break; - } - case UPB_TYPE_MESSAGE: { -#if PHP_MAJOR_VERSION < 7 - zval** holder = ALLOC(zval*); - zval* tmp; - MAKE_STD_ZVAL(tmp); - ZVAL_NULL(tmp); - *holder = tmp; - *(zval***)memory = holder; -#else - *(zval**)memory = cache; - ZVAL_NULL(*(zval**)memory); -#endif - break; - } - default: - native_slot_init(type, memory, NULL); - } -} - -static void map_slot_uninit(void* memory, upb_fieldtype_t type) { - switch (type) { - case UPB_TYPE_MESSAGE: - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { -#if PHP_MAJOR_VERSION < 7 - zval** holder = *(zval***)memory; - php_proto_zval_ptr_dtor(*holder); - FREE(holder); -#else - php_proto_zval_ptr_dtor(*(zval**)memory); -#endif - break; - } - default: - break; - } -} - -static void map_slot_key(upb_fieldtype_t type, const void* from, - const char** keyval, - size_t* length) { - if (type == UPB_TYPE_STRING) { -#if PHP_MAJOR_VERSION < 7 - zval* key_php = **(zval***)from; -#else - zval* key_php = *(zval**)from; -#endif - *keyval = Z_STRVAL_P(key_php); - *length = Z_STRLEN_P(key_php); - } else { - *keyval = from; - *length = native_slot_size(type); - } -} - -static void map_slot_value(upb_fieldtype_t type, const void* from, - upb_value* v) { - size_t len; - void* to = upb_value_memory(v); -#ifndef NDEBUG - v->ctype = UPB_CTYPE_UINT64; -#endif - - memset(to, 0, native_slot_size(type)); - - switch (type) { -#if PHP_MAJOR_VERSION < 7 - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: { - *(zval**)to = **(zval***)from; - Z_ADDREF_PP((zval**)to); - break; - } -#else - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - *(zend_string**)to = Z_STR_P(*(zval**)from); - zend_string_addref(*(zend_string**)to); - break; - case UPB_TYPE_MESSAGE: - *(zend_object**)to = Z_OBJ_P(*(zval**)from); - ++GC_REFCOUNT(*(zend_object**)to); - break; -#endif - default: - len = native_slot_size(type); - memcpy(to, from, len); - } -} - -// Handler to begin a map entry: allocates a temporary frame. This is the -// 'startsubmsg' handler on the msgdef that contains the map field. -static void *startmapentry_handler(void *closure, const void *hd) { - MessageHeader* msg = closure; - const map_handlerdata_t* mapdata = hd; - zval* map = CACHED_PTR_TO_ZVAL_PTR( - DEREF(message_data(msg), mapdata->ofs, CACHED_VALUE*)); - - map_parse_frame_t* frame = ALLOC(map_parse_frame_t); - frame->data = ALLOC(map_parse_frame_data_t); - frame->map = map; - - map_slot_init(&frame->data->key_storage, mapdata->key_field_type, - &frame->key_zval); - map_slot_init(&frame->data->value_storage, mapdata->value_field_type, - &frame->value_zval); - - return frame; -} - -// Handler to end a map entry: inserts the value defined during the message into -// the map. This is the 'endmsg' handler on the map entry msgdef. -static bool endmap_handler(void* closure, const void* hd, upb_status* s) { - map_parse_frame_t* frame = closure; - const map_handlerdata_t* mapdata = hd; - - TSRMLS_FETCH(); - Map *map = UNBOX(Map, frame->map); - - const char* keyval = NULL; - upb_value v; - size_t length; - - map_slot_key(map->key_type, &frame->data->key_storage, &keyval, &length); - map_slot_value(map->value_type, &frame->data->value_storage, &v); - - map_index_set(map, keyval, length, v); - - map_slot_uninit(&frame->data->key_storage, mapdata->key_field_type); - map_slot_uninit(&frame->data->value_storage, mapdata->value_field_type); - FREE(frame->data); - FREE(frame); - - return true; -} - -// Allocates a new map_handlerdata_t given the map entry message definition. If -// the offset of the field within the parent message is also given, that is -// added to the handler data as well. Note that this is called *twice* per map -// field: once in the parent message handler setup when setting the startsubmsg -// handler and once in the map entry message handler setup when setting the -// key/value and endmsg handlers. The reason is that there is no easy way to -// pass the handlerdata down to the sub-message handler setup. -static map_handlerdata_t* new_map_handlerdata( - size_t ofs, - const upb_msgdef* mapentry_def, - Descriptor* desc) { - const upb_fielddef* key_field; - const upb_fielddef* value_field; - // TODO(teboring): Use emalloc and efree. - map_handlerdata_t* hd = - (map_handlerdata_t*)malloc(sizeof(map_handlerdata_t)); - - hd->ofs = ofs; - key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD); - assert(key_field != NULL); - hd->key_field_type = upb_fielddef_type(key_field); - value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD); - assert(value_field != NULL); - hd->value_field_type = upb_fielddef_type(value_field); - hd->value_field_subdef = upb_fielddef_subdef(value_field); - - return hd; -} - -// Handlers that set primitive values in oneofs. -#define DEFINE_ONEOF_HANDLER(type, ctype) \ - static bool oneof##type##_handler(void* closure, const void* hd, \ - ctype val) { \ - const oneof_handlerdata_t* oneofdata = hd; \ - MessageHeader* msg = (MessageHeader*)closure; \ - DEREF(message_data(closure), oneofdata->case_ofs, uint32_t) = \ - oneofdata->oneof_case_num; \ - DEREF(message_data(closure), oneofdata->ofs, ctype) = val; \ - return true; \ - } - -DEFINE_ONEOF_HANDLER(bool, bool) -DEFINE_ONEOF_HANDLER(int32, int32_t) -DEFINE_ONEOF_HANDLER(uint32, uint32_t) -DEFINE_ONEOF_HANDLER(float, float) -DEFINE_ONEOF_HANDLER(int64, int64_t) -DEFINE_ONEOF_HANDLER(uint64, uint64_t) -DEFINE_ONEOF_HANDLER(double, double) - -#undef DEFINE_ONEOF_HANDLER - -static void oneof_cleanup(MessageHeader* msg, - const oneof_handlerdata_t* oneofdata) { - uint32_t old_case_num = - DEREF(message_data(msg), oneofdata->case_ofs, uint32_t); - if (old_case_num == 0) { - return; - } - - const upb_fielddef* old_field = - upb_msgdef_itof(oneofdata->parent_md, old_case_num); - bool need_clean = false; - - switch (upb_fielddef_type(old_field)) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - need_clean = true; - break; - case UPB_TYPE_MESSAGE: - if (oneofdata->oneof_case_num != old_case_num) { - need_clean = true; - } - break; - default: - break; - } - - if (need_clean) { -#if PHP_MAJOR_VERSION < 7 - SEPARATE_ZVAL_IF_NOT_REF( - DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*)); - php_proto_zval_ptr_dtor( - *DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*)); - MAKE_STD_ZVAL(*DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*)); - ZVAL_NULL(*DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*)); -#endif - } -} - -// Handlers for string/bytes in a oneof. -static void *oneofbytes_handler(void *closure, - const void *hd, - size_t size_hint) { - MessageHeader* msg = closure; - const oneof_handlerdata_t *oneofdata = hd; - - oneof_cleanup(msg, oneofdata); - - DEREF(message_data(msg), oneofdata->case_ofs, uint32_t) = - oneofdata->oneof_case_num; - DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) = - OBJ_PROP(&msg->std, oneofdata->property_ofs); - - return empty_php_string(DEREF( - message_data(msg), oneofdata->ofs, CACHED_VALUE*)); -} - -static void *oneofstr_handler(void *closure, - const void *hd, - size_t size_hint) { - // TODO(teboring): Add it back. - // rb_enc_associate(str, kRubyString8bitEncoding); - return oneofbytes_handler(closure, hd, size_hint); -} - -// Handler for a submessage field in a oneof. -static void* oneofsubmsg_handler(void* closure, const void* hd) { - MessageHeader* msg = closure; - const oneof_handlerdata_t *oneofdata = hd; - uint32_t oldcase = DEREF(message_data(msg), oneofdata->case_ofs, uint32_t); - TSRMLS_FETCH(); - Descriptor* subdesc = - UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)oneofdata->md)); - zend_class_entry* subklass = subdesc->klass; - zval* submsg_php; - MessageHeader* submsg; - - if (oldcase != oneofdata->oneof_case_num) { - oneof_cleanup(msg, oneofdata); - - // Create new message. - DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) = - OBJ_PROP(&msg->std, oneofdata->property_ofs); - ZVAL_OBJ(CACHED_PTR_TO_ZVAL_PTR( - DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*)), - subklass->create_object(subklass TSRMLS_CC)); - } - - DEREF(message_data(msg), oneofdata->case_ofs, uint32_t) = - oneofdata->oneof_case_num; - - submsg_php = CACHED_PTR_TO_ZVAL_PTR( - DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*)); - submsg = UNBOX(MessageHeader, submsg_php); - custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC); - return submsg; -} - -// Set up handlers for a repeated field. -static void add_handlers_for_repeated_field(upb_handlers *h, - const upb_fielddef *f, - size_t offset) { - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset)); - upb_handlers_setstartseq(h, f, startseq_handler, &attr); - upb_handlerattr_uninit(&attr); - - switch (upb_fielddef_type(f)) { - -#define SET_HANDLER(utype, ltype) \ - case utype: \ - upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \ - break; - - SET_HANDLER(UPB_TYPE_BOOL, bool); - SET_HANDLER(UPB_TYPE_INT32, int32); - SET_HANDLER(UPB_TYPE_UINT32, uint32); - SET_HANDLER(UPB_TYPE_ENUM, int32); - SET_HANDLER(UPB_TYPE_FLOAT, float); - SET_HANDLER(UPB_TYPE_INT64, int64); - SET_HANDLER(UPB_TYPE_UINT64, uint64); - SET_HANDLER(UPB_TYPE_DOUBLE, double); - -#undef SET_HANDLER - - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; - upb_handlers_setstartstr(h, f, is_bytes ? - appendbytes_handler : appendstr_handler, - NULL); -#if PHP_MAJOR_VERSION < 7 - upb_handlers_setstring(h, f, stringdata_handler, NULL); -#else - upb_handlers_setstring(h, f, zendstringdata_handler, NULL); -#endif - break; - } - case UPB_TYPE_MESSAGE: { - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, 0, f)); - upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr); - upb_handlerattr_uninit(&attr); - break; - } - } -} - -// Set up handlers for a singular field. -static void add_handlers_for_singular_field(upb_handlers *h, - const upb_fielddef *f, - size_t offset) { - switch (upb_fielddef_type(f)) { - -#define SET_HANDLER(utype, ltype) \ - case utype: { \ - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; \ - upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset)); \ - upb_handlers_set##ltype(h, f, ltype##_handler, &attr); \ - break; \ - } - - SET_HANDLER(UPB_TYPE_BOOL, bool); - SET_HANDLER(UPB_TYPE_INT32, int32); - SET_HANDLER(UPB_TYPE_UINT32, uint32); - SET_HANDLER(UPB_TYPE_ENUM, int32); - SET_HANDLER(UPB_TYPE_FLOAT, float); - SET_HANDLER(UPB_TYPE_INT64, int64); - SET_HANDLER(UPB_TYPE_UINT64, uint64); - SET_HANDLER(UPB_TYPE_DOUBLE, double); - -#undef SET_HANDLER - - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset)); - upb_handlers_setstartstr(h, f, - is_bytes ? bytes_handler : str_handler, - &attr); - upb_handlers_setstring(h, f, stringdata_handler, &attr); - upb_handlerattr_uninit(&attr); - break; - } - case UPB_TYPE_MESSAGE: { - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, offset, f)); - upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr); - upb_handlerattr_uninit(&attr); - break; - } - } -} - -// Adds handlers to a map field. -static void add_handlers_for_mapfield(upb_handlers* h, - const upb_fielddef* fielddef, - size_t offset, - Descriptor* desc) { - const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef); - map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc); - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - - upb_handlers_addcleanup(h, hd, free); - upb_handlerattr_sethandlerdata(&attr, hd); - upb_handlers_setstartsubmsg(h, fielddef, startmapentry_handler, &attr); - upb_handlerattr_uninit(&attr); -} - -// Adds handlers to a map-entry msgdef. -static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h, - Descriptor* desc) { - const upb_fielddef* key_field = map_entry_key(msgdef); - const upb_fielddef* value_field = map_entry_value(msgdef); - map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc); - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - - upb_handlers_addcleanup(h, hd, free); - upb_handlerattr_sethandlerdata(&attr, hd); - upb_handlers_setendmsg(h, endmap_handler, &attr); - - add_handlers_for_singular_field(h, key_field, - offsetof(map_parse_frame_data_t, - key_storage)); - add_handlers_for_singular_field(h, value_field, - offsetof(map_parse_frame_data_t, - value_storage)); -} - -// Set up handlers for a oneof field. -static void add_handlers_for_oneof_field(upb_handlers *h, - const upb_msgdef *m, - const upb_fielddef *f, - size_t offset, - size_t oneof_case_offset, - int property_cache_offset) { - - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata( - &attr, newoneofhandlerdata(h, offset, oneof_case_offset, - property_cache_offset, m, f)); - - switch (upb_fielddef_type(f)) { - -#define SET_HANDLER(utype, ltype) \ - case utype: \ - upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \ - break; - - SET_HANDLER(UPB_TYPE_BOOL, bool); - SET_HANDLER(UPB_TYPE_INT32, int32); - SET_HANDLER(UPB_TYPE_UINT32, uint32); - SET_HANDLER(UPB_TYPE_ENUM, int32); - SET_HANDLER(UPB_TYPE_FLOAT, float); - SET_HANDLER(UPB_TYPE_INT64, int64); - SET_HANDLER(UPB_TYPE_UINT64, uint64); - SET_HANDLER(UPB_TYPE_DOUBLE, double); - -#undef SET_HANDLER - - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; - upb_handlers_setstartstr(h, f, is_bytes ? - oneofbytes_handler : oneofstr_handler, - &attr); - upb_handlers_setstring(h, f, stringdata_handler, NULL); - break; - } - case UPB_TYPE_MESSAGE: { - upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr); - break; - } - } - - upb_handlerattr_uninit(&attr); -} - -static void add_handlers_for_message(const void* closure, - upb_handlers* h) { - const upb_msgdef* msgdef = upb_handlers_msgdef(h); - TSRMLS_FETCH(); - Descriptor* desc = - UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)msgdef)); - upb_msg_field_iter i; - - // If this is a mapentry message type, set up a special set of handlers and - // bail out of the normal (user-defined) message type handling. - if (upb_msgdef_mapentry(msgdef)) { - add_handlers_for_mapentry(msgdef, h, desc); - return; - } - - // Ensure layout exists. We may be invoked to create handlers for a given - // message if we are included as a submsg of another message type before our - // class is actually built, so to work around this, we just create the layout - // (and handlers, in the class-building function) on-demand. - if (desc->layout == NULL) { - desc->layout = create_layout(desc->msgdef); - } - - for (upb_msg_field_begin(&i, desc->msgdef); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset; - - if (upb_fielddef_containingoneof(f)) { - size_t oneof_case_offset = - desc->layout->fields[upb_fielddef_index(f)].case_offset; - int property_cache_index = - desc->layout->fields[upb_fielddef_index(f)].cache_index; - add_handlers_for_oneof_field(h, desc->msgdef, f, offset, - oneof_case_offset, property_cache_index); - } else if (is_map_field(f)) { - add_handlers_for_mapfield(h, f, offset, desc); - } else if (upb_fielddef_isseq(f)) { - add_handlers_for_repeated_field(h, f, offset); - } else { - add_handlers_for_singular_field(h, f, offset); - } - } -} - -// Creates upb handlers for populating a message. -static const upb_handlers *new_fill_handlers(Descriptor* desc, - const void* owner) { - // TODO(cfallin, haberman): once upb gets a caching/memoization layer for - // handlers, reuse subdef handlers so that e.g. if we already parse - // B-with-field-of-type-C, we don't have to rebuild the whole hierarchy to - // parse A-with-field-of-type-B-with-field-of-type-C. - return upb_handlers_newfrozen(desc->msgdef, owner, - add_handlers_for_message, NULL); -} - -// Constructs the handlers for filling a message's data into an in-memory -// object. -const upb_handlers* get_fill_handlers(Descriptor* desc) { - if (!desc->fill_handlers) { - desc->fill_handlers = - new_fill_handlers(desc, &desc->fill_handlers); - } - return desc->fill_handlers; -} - -const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor* desc, - const void* owner) { - const upb_handlers* handlers = get_fill_handlers(desc); - upb_pbdecodermethodopts opts; - upb_pbdecodermethodopts_init(&opts, handlers); - - return upb_pbdecodermethod_new(&opts, owner); -} - -static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) { - if (desc->fill_method == NULL) { - desc->fill_method = new_fillmsg_decodermethod( - desc, &desc->fill_method); - } - return desc->fill_method; -} - -static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) { - if (desc->json_fill_method == NULL) { - desc->json_fill_method = - upb_json_parsermethod_new(desc->msgdef, &desc->json_fill_method); - } - return desc->json_fill_method; -} - -// ----------------------------------------------------------------------------- -// Serializing. -// ----------------------------------------------------------------------------- - -static void putmsg(zval* msg, const Descriptor* desc, upb_sink* sink, - int depth TSRMLS_DC); -static void putrawmsg(MessageHeader* msg, const Descriptor* desc, - upb_sink* sink, int depth TSRMLS_DC); - -static void putstr(zval* str, const upb_fielddef* f, upb_sink* sink); - -static void putrawstr(const char* str, int len, const upb_fielddef* f, - upb_sink* sink); - -static void putsubmsg(zval* submsg, const upb_fielddef* f, upb_sink* sink, - int depth TSRMLS_DC); -static void putrawsubmsg(MessageHeader* submsg, const upb_fielddef* f, - upb_sink* sink, int depth TSRMLS_DC); - -static void putarray(zval* array, const upb_fielddef* f, upb_sink* sink, - int depth TSRMLS_DC); -static void putmap(zval* map, const upb_fielddef* f, upb_sink* sink, - int depth TSRMLS_DC); - -static upb_selector_t getsel(const upb_fielddef* f, upb_handlertype_t type) { - upb_selector_t ret; - bool ok = upb_handlers_getselector(f, type, &ret); - UPB_ASSERT(ok); - return ret; -} - -static void put_optional_value(const void* memory, int len, const upb_fielddef* f, - int depth, upb_sink* sink TSRMLS_DC) { - assert(upb_fielddef_label(f) == UPB_LABEL_OPTIONAL); - - switch (upb_fielddef_type(f)) { -#define T(upbtypeconst, upbtype, ctype, default_value) \ - case upbtypeconst: { \ - ctype value = DEREF(memory, 0, ctype); \ - if (value != default_value) { \ - upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); \ - upb_sink_put##upbtype(sink, sel, value); \ - } \ - } break; - - T(UPB_TYPE_FLOAT, float, float, 0.0) - T(UPB_TYPE_DOUBLE, double, double, 0.0) - T(UPB_TYPE_BOOL, bool, uint8_t, 0) - T(UPB_TYPE_ENUM, int32, int32_t, 0) - T(UPB_TYPE_INT32, int32, int32_t, 0) - T(UPB_TYPE_UINT32, uint32, uint32_t, 0) - T(UPB_TYPE_INT64, int64, int64_t, 0) - T(UPB_TYPE_UINT64, uint64, uint64_t, 0) - -#undef T - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - putrawstr(memory, len, f, sink); - break; - case UPB_TYPE_MESSAGE: { -#if PHP_MAJOR_VERSION < 7 - MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory); -#else - MessageHeader *submsg = - (MessageHeader*)((char*)(*(zend_object**)memory) - - XtOffsetOf(MessageHeader, std)); -#endif - putrawsubmsg(submsg, f, sink, depth TSRMLS_CC); - break; - } - default: - assert(false); - } -} - -// Only string/bytes fields are stored as zval. -static const char* raw_value(void* memory, const upb_fielddef* f) { - switch (upb_fielddef_type(f)) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: -#if PHP_MAJOR_VERSION < 7 - return Z_STRVAL_PP((zval**)memory); -#else - return ZSTR_VAL(*(zend_string**)memory); -#endif - break; - default: - return memory; - } -} - -static int raw_value_len(void* memory, int len, const upb_fielddef* f) { - switch (upb_fielddef_type(f)) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: -#if PHP_MAJOR_VERSION < 7 - return Z_STRLEN_PP((zval**)memory); -#else - return ZSTR_LEN(*(zend_string**)memory); -#endif - default: - return len; - } -} - -static void putmap(zval* map, const upb_fielddef* f, upb_sink* sink, - int depth TSRMLS_DC) { - upb_sink subsink; - const upb_fielddef* key_field; - const upb_fielddef* value_field; - MapIter it; - int len, size; - - assert(map != NULL); - Map* intern = UNBOX(Map, map); - size = upb_strtable_count(&intern->table); - if (size == 0) return; - - upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink); - - assert(upb_fielddef_type(f) == UPB_TYPE_MESSAGE); - key_field = map_field_key(f); - value_field = map_field_value(f); - - for (map_begin(map, &it TSRMLS_CC); !map_done(&it); map_next(&it)) { - upb_status status; - - upb_sink entry_sink; - upb_sink_startsubmsg(&subsink, getsel(f, UPB_HANDLER_STARTSUBMSG), - &entry_sink); - upb_sink_startmsg(&entry_sink); - - // Serialize key. - const char *key = map_iter_key(&it, &len); - put_optional_value(key, len, key_field, depth + 1, &entry_sink TSRMLS_CC); - - // Serialize value. - upb_value value = map_iter_value(&it, &len); - put_optional_value(raw_value(upb_value_memory(&value), value_field), - raw_value_len(upb_value_memory(&value), len, value_field), - value_field, depth + 1, &entry_sink TSRMLS_CC); - - upb_sink_endmsg(&entry_sink, &status); - upb_sink_endsubmsg(&subsink, getsel(f, UPB_HANDLER_ENDSUBMSG)); - } - - upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); -} - -static void putmsg(zval* msg_php, const Descriptor* desc, upb_sink* sink, - int depth TSRMLS_DC) { - MessageHeader* msg = UNBOX(MessageHeader, msg_php); - putrawmsg(msg, desc, sink, depth TSRMLS_CC); -} - -static void putrawmsg(MessageHeader* msg, const Descriptor* desc, - upb_sink* sink, int depth TSRMLS_DC) { - upb_msg_field_iter i; - upb_status status; - - upb_sink_startmsg(sink); - - // Protect against cycles (possible because users may freely reassign message - // and repeated fields) by imposing a maximum recursion depth. - if (depth > ENCODE_MAX_NESTING) { - zend_error(E_ERROR, - "Maximum recursion depth exceeded during encoding."); - } - - for (upb_msg_field_begin(&i, desc->msgdef); !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef* f = upb_msg_iter_field(&i); - uint32_t offset = desc->layout->fields[upb_fielddef_index(f)].offset; - bool containing_oneof = false; - - if (upb_fielddef_containingoneof(f)) { - uint32_t oneof_case_offset = - desc->layout->fields[upb_fielddef_index(f)].case_offset; - // For a oneof, check that this field is actually present -- skip all the - // below if not. - if (DEREF(message_data(msg), oneof_case_offset, uint32_t) != - upb_fielddef_number(f)) { - continue; - } - // Otherwise, fall through to the appropriate singular-field handler - // below. - containing_oneof = true; - } - - if (is_map_field(f)) { - zval* map = CACHED_PTR_TO_ZVAL_PTR( - DEREF(message_data(msg), offset, CACHED_VALUE*)); - if (map != NULL) { - putmap(map, f, sink, depth TSRMLS_CC); - } - } else if (upb_fielddef_isseq(f)) { - zval* array = CACHED_PTR_TO_ZVAL_PTR( - DEREF(message_data(msg), offset, CACHED_VALUE*)); - if (array != NULL) { - putarray(array, f, sink, depth TSRMLS_CC); - } - } else if (upb_fielddef_isstring(f)) { - zval* str = CACHED_PTR_TO_ZVAL_PTR( - DEREF(message_data(msg), offset, CACHED_VALUE*)); - if (containing_oneof || Z_STRLEN_P(str) > 0) { - putstr(str, f, sink); - } - } else if (upb_fielddef_issubmsg(f)) { - putsubmsg(CACHED_PTR_TO_ZVAL_PTR( - DEREF(message_data(msg), offset, CACHED_VALUE*)), - f, sink, depth TSRMLS_CC); - } else { - upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); - -#define T(upbtypeconst, upbtype, ctype, default_value) \ - case upbtypeconst: { \ - ctype value = DEREF(message_data(msg), offset, ctype); \ - if (containing_oneof || value != default_value) { \ - upb_sink_put##upbtype(sink, sel, value); \ - } \ - } break; - - switch (upb_fielddef_type(f)) { - T(UPB_TYPE_FLOAT, float, float, 0.0) - T(UPB_TYPE_DOUBLE, double, double, 0.0) - T(UPB_TYPE_BOOL, bool, uint8_t, 0) - case UPB_TYPE_ENUM: - T(UPB_TYPE_INT32, int32, int32_t, 0) - T(UPB_TYPE_UINT32, uint32, uint32_t, 0) - T(UPB_TYPE_INT64, int64, int64_t, 0) - T(UPB_TYPE_UINT64, uint64, uint64_t, 0) - - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - zend_error(E_ERROR, "Internal error."); - } - -#undef T - } - } - - upb_sink_endmsg(sink, &status); -} - -static void putstr(zval* str, const upb_fielddef *f, upb_sink *sink) { - upb_sink subsink; - - if (ZVAL_IS_NULL(str)) return; - - assert(Z_TYPE_P(str) == IS_STRING); - - upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), Z_STRLEN_P(str), - &subsink); - - // For oneof string field, we may get here with string length is zero. - if (Z_STRLEN_P(str) > 0) { - // Ensure that the string has the correct encoding. We also check at - // field-set time, but the user may have mutated the string object since - // then. - if (upb_fielddef_type(f) == UPB_TYPE_STRING && - !is_structurally_valid_utf8(Z_STRVAL_P(str), Z_STRLEN_P(str))) { - zend_error(E_USER_ERROR, "Given string is not UTF8 encoded."); - return; - } - upb_sink_putstring(&subsink, getsel(f, UPB_HANDLER_STRING), Z_STRVAL_P(str), - Z_STRLEN_P(str), NULL); - } - - upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR)); -} - -static void putrawstr(const char* str, int len, const upb_fielddef* f, - upb_sink* sink) { - upb_sink subsink; - - if (len == 0) return; - - // Ensure that the string has the correct encoding. We also check at field-set - // time, but the user may have mutated the string object since then. - if (upb_fielddef_type(f) == UPB_TYPE_STRING && - !is_structurally_valid_utf8(str, len)) { - zend_error(E_USER_ERROR, "Given string is not UTF8 encoded."); - return; - } - - upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), len, &subsink); - upb_sink_putstring(&subsink, getsel(f, UPB_HANDLER_STRING), str, len, NULL); - upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR)); -} - -static void putsubmsg(zval* submsg_php, const upb_fielddef* f, upb_sink* sink, - int depth TSRMLS_DC) { - if (Z_TYPE_P(submsg_php) == IS_NULL) return; - - MessageHeader *submsg = UNBOX(MessageHeader, submsg_php); - putrawsubmsg(submsg, f, sink, depth TSRMLS_CC); -} - -static void putrawsubmsg(MessageHeader* submsg, const upb_fielddef* f, - upb_sink* sink, int depth TSRMLS_DC) { - upb_sink subsink; - - Descriptor* subdesc = - UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(upb_fielddef_msgsubdef(f))); - - upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink); - putrawmsg(submsg, subdesc, &subsink, depth + 1 TSRMLS_CC); - upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG)); -} - -static void putarray(zval* array, const upb_fielddef* f, upb_sink* sink, - int depth TSRMLS_DC) { - upb_sink subsink; - upb_fieldtype_t type = upb_fielddef_type(f); - upb_selector_t sel = 0; - int size, i; - - assert(array != NULL); - RepeatedField* intern = UNBOX(RepeatedField, array); - HashTable *ht = PHP_PROTO_HASH_OF(intern->array); - size = zend_hash_num_elements(ht); - // size = zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array)); - if (size == 0) return; - - upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink); - - if (upb_fielddef_isprimitive(f)) { - sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); - } - - for (i = 0; i < size; i++) { - void* memory = repeated_field_index_native(intern, i TSRMLS_CC); - switch (type) { -#define T(upbtypeconst, upbtype, ctype) \ - case upbtypeconst: \ - upb_sink_put##upbtype(&subsink, sel, *((ctype*)memory)); \ - break; - - T(UPB_TYPE_FLOAT, float, float) - T(UPB_TYPE_DOUBLE, double, double) - T(UPB_TYPE_BOOL, bool, int8_t) - case UPB_TYPE_ENUM: - T(UPB_TYPE_INT32, int32, int32_t) - T(UPB_TYPE_UINT32, uint32, uint32_t) - T(UPB_TYPE_INT64, int64, int64_t) - T(UPB_TYPE_UINT64, uint64, uint64_t) - - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { -#if PHP_MAJOR_VERSION < 7 - const char* rawstr = Z_STRVAL_P(*(zval**)memory); - int len = Z_STRLEN_P(*(zval**)memory); -#else - const char* rawstr = ZSTR_VAL(*(zend_string**)memory); - int len = ZSTR_LEN(*(zend_string**)memory); -#endif - putrawstr(rawstr, len, f, &subsink); - break; - } - case UPB_TYPE_MESSAGE: { -#if PHP_MAJOR_VERSION < 7 - MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory); -#else - MessageHeader *submsg = - (MessageHeader*)((char*)(Z_OBJ_P((zval*)memory)) - - XtOffsetOf(MessageHeader, std)); -#endif - putrawsubmsg(submsg, f, &subsink, depth TSRMLS_CC); - break; - } - -#undef T - } - } - upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); -} - -static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) { - if (desc->pb_serialize_handlers == NULL) { - desc->pb_serialize_handlers = - upb_pb_encoder_newhandlers(desc->msgdef, &desc->pb_serialize_handlers); - } - return desc->pb_serialize_handlers; -} - -static const upb_handlers* msgdef_json_serialize_handlers( - Descriptor* desc, bool preserve_proto_fieldnames) { - if (preserve_proto_fieldnames) { - if (desc->json_serialize_handlers == NULL) { - desc->json_serialize_handlers = - upb_json_printer_newhandlers( - desc->msgdef, true, &desc->json_serialize_handlers); - } - return desc->json_serialize_handlers; - } else { - if (desc->json_serialize_handlers_preserve == NULL) { - desc->json_serialize_handlers_preserve = - upb_json_printer_newhandlers( - desc->msgdef, false, &desc->json_serialize_handlers_preserve); - } - return desc->json_serialize_handlers_preserve; - } -} - -// ----------------------------------------------------------------------------- -// PHP encode/decode methods -// ----------------------------------------------------------------------------- - -PHP_METHOD(Message, serializeToString) { - Descriptor* desc = - UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis()))); - - stringsink sink; - stringsink_init(&sink); - - { - const upb_handlers* serialize_handlers = msgdef_pb_serialize_handlers(desc); - - stackenv se; - upb_pb_encoder* encoder; - - stackenv_init(&se, "Error occurred during encoding: %s"); - encoder = upb_pb_encoder_create(&se.env, serialize_handlers, &sink.sink); - - putmsg(getThis(), desc, upb_pb_encoder_input(encoder), 0 TSRMLS_CC); - - PHP_PROTO_RETVAL_STRINGL(sink.ptr, sink.len, 1); - - stackenv_uninit(&se); - stringsink_uninit(&sink); - } -} - -PHP_METHOD(Message, mergeFromString) { - Descriptor* desc = - UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis()))); - MessageHeader* msg = UNBOX(MessageHeader, getThis()); - - char *data = NULL; - PHP_PROTO_SIZE data_len; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) == - FAILURE) { - return; - } - - { - const upb_pbdecodermethod* method = msgdef_decodermethod(desc); - const upb_handlers* h = upb_pbdecodermethod_desthandlers(method); - stackenv se; - upb_sink sink; - upb_pbdecoder* decoder; - stackenv_init(&se, "Error occurred during parsing: %s"); - - upb_sink_reset(&sink, h, msg); - decoder = upb_pbdecoder_create(&se.env, method, &sink); - upb_bufsrc_putbuf(data, data_len, upb_pbdecoder_input(decoder)); - - stackenv_uninit(&se); - } -} - -PHP_METHOD(Message, serializeToJsonString) { - Descriptor* desc = - UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis()))); - - zend_bool preserve_proto_fieldnames = false; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", - &preserve_proto_fieldnames) == FAILURE) { - return; - } - - stringsink sink; - stringsink_init(&sink); - - { - const upb_handlers* serialize_handlers = - msgdef_json_serialize_handlers(desc, preserve_proto_fieldnames); - upb_json_printer* printer; - stackenv se; - - stackenv_init(&se, "Error occurred during encoding: %s"); - printer = upb_json_printer_create(&se.env, serialize_handlers, &sink.sink); - - putmsg(getThis(), desc, upb_json_printer_input(printer), 0 TSRMLS_CC); - - PHP_PROTO_RETVAL_STRINGL(sink.ptr, sink.len, 1); - - stackenv_uninit(&se); - stringsink_uninit(&sink); - } -} - -PHP_METHOD(Message, mergeFromJsonString) { - Descriptor* desc = - UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis()))); - MessageHeader* msg = UNBOX(MessageHeader, getThis()); - - char *data = NULL; - PHP_PROTO_SIZE data_len; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) == - FAILURE) { - return; - } - - // TODO(teboring): Check and respect string encoding. If not UTF-8, we need to - // convert, because string handlers pass data directly to message string - // fields. - - // TODO(teboring): Clear message. - - { - const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc); - stackenv se; - upb_sink sink; - upb_json_parser* parser; - stackenv_init(&se, "Error occurred during parsing: %s"); - - upb_sink_reset(&sink, get_fill_handlers(desc), msg); - parser = upb_json_parser_create(&se.env, method, &sink); - upb_bufsrc_putbuf(data, data_len, upb_json_parser_input(parser)); - - stackenv_uninit(&se); - } -} diff --git a/php/ext/google/protobuf/map.c b/php/ext/google/protobuf/map.c index 2680b5478cfce..babd638dab8c8 100644 --- a/php/ext/google/protobuf/map.c +++ b/php/ext/google/protobuf/map.c @@ -28,351 +28,258 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include +#include "map.h" + #include #include -#include "protobuf.h" -#include "utf8.h" - -ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1) - ZEND_ARG_INFO(0, index) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2) - ZEND_ARG_INFO(0, index) - ZEND_ARG_INFO(0, newval) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_void, 0) -ZEND_END_ARG_INFO() +#include -// Utilities +#include "arena.h" +#include "convert.h" +#include "message.h" +#include "php-upb.h" +#include "protobuf.h" -void* upb_value_memory(upb_value* v) { - return (void*)(&v->val); -} +static void MapFieldIter_make(zval *val, zval *map_field); // ----------------------------------------------------------------------------- -// Basic map operations on top of upb's strtable. -// -// Note that we roll our own `Map` container here because, as for -// `RepeatedField`, we want a strongly-typed container. This is so that any user -// errors due to incorrect map key or value types are raised as close as -// possible to the error site, rather than at some deferred point (e.g., -// serialization). -// -// We build our `Map` on top of upb_strtable so that we're able to take -// advantage of the native_slot storage abstraction, as RepeatedField does. -// (This is not quite a perfect mapping -- see the key conversions below -- but -// gives us full support and error-checking for all value types for free.) +// MapField // ----------------------------------------------------------------------------- -// Map values are stored using the native_slot abstraction (as with repeated -// field values), but keys are a bit special. Since we use a strtable, we need -// to store keys as sequences of bytes such that equality of those bytes maps -// one-to-one to equality of keys. We store strings directly (i.e., they map to -// their own bytes) and integers as native integers (using the native_slot -// abstraction). - -// Note that there is another tradeoff here in keeping string keys as native -// strings rather than PHP strings: traversing the Map requires conversion to -// PHP string values on every traversal, potentially creating more garbage. We -// should consider ways to cache a PHP version of the key if this becomes an -// issue later. - -// Forms a key to use with the underlying strtable from a PHP key value. |buf| -// must point to TABLE_KEY_BUF_LENGTH bytes of temporary space, used to -// construct a key byte sequence if needed. |out_key| and |out_length| provide -// the resulting key data/length. -#define TABLE_KEY_BUF_LENGTH 8 // sizeof(uint64_t) -static bool table_key(Map* self, zval* key, - char* buf, - const char** out_key, - size_t* out_length TSRMLS_DC) { - switch (self->key_type) { - case UPB_TYPE_STRING: - if (!protobuf_convert_to_string(key)) { - return false; - } - if (!is_structurally_valid_utf8(Z_STRVAL_P(key), Z_STRLEN_P(key))) { - zend_error(E_USER_ERROR, "Given key is not UTF8 encoded."); - return false; - } - *out_key = Z_STRVAL_P(key); - *out_length = Z_STRLEN_P(key); - break; - -#define CASE_TYPE(upb_type, type, c_type, php_type) \ - case UPB_TYPE_##upb_type: { \ - c_type type##_value; \ - if (!protobuf_convert_to_##type(key, &type##_value)) { \ - return false; \ - } \ - native_slot_set_by_array(self->key_type, NULL, buf, key TSRMLS_CC); \ - *out_key = buf; \ - *out_length = native_slot_size(self->key_type); \ - break; \ +typedef struct { + zend_object std; + zval arena; + upb_map *map; + MapField_Type type; +} MapField; + +zend_class_entry *MapField_class_entry; +static zend_object_handlers MapField_object_handlers; + +static bool MapType_Eq(MapField_Type a, MapField_Type b) { + return a.key_type == b.key_type && TypeInfo_Eq(a.val_type, b.val_type); +} + +static TypeInfo KeyType(MapField_Type type) { + TypeInfo ret = {type.key_type}; + return ret; +} + +MapField_Type MapType_Get(const upb_fielddef *f) { + const upb_msgdef *ent = upb_fielddef_msgsubdef(f); + const upb_fielddef *key_f = upb_msgdef_itof(ent, 1); + const upb_fielddef *val_f = upb_msgdef_itof(ent, 2); + MapField_Type type = { + upb_fielddef_type(key_f), + {upb_fielddef_type(val_f), Descriptor_GetFromFieldDef(val_f)}}; + return type; +} + +// PHP Object Handlers ///////////////////////////////////////////////////////// + +/** + * MapField_create() + * + * PHP class entry function to allocate and initialize a new MapField + * object. + */ +static zend_object* MapField_create(zend_class_entry *class_type) { + MapField *intern = emalloc(sizeof(MapField)); + zend_object_std_init(&intern->std, class_type); + intern->std.handlers = &MapField_object_handlers; + Arena_Init(&intern->arena); + intern->map = NULL; + // Skip object_properties_init(), we don't allow derived classes. + return &intern->std; +} + +/** + * MapField_dtor() + * + * Object handler to destroy a MapField. This releases all resources + * associated with the message. Note that it is possible to access a destroyed + * object from PHP in rare cases. + */ +static void MapField_destructor(zend_object* obj) { + MapField* intern = (MapField*)obj; + ObjCache_Delete(intern->map); + zval_ptr_dtor(&intern->arena); + zend_object_std_dtor(&intern->std); +} + +/** + * MapField_compare_objects() + * + * Object handler for comparing two repeated field objects. Called whenever PHP + * code does: + * + * $map1 == $map2 + */ +static int MapField_compare_objects(zval *map1, zval *map2) { + MapField* intern1 = (MapField*)Z_OBJ_P(map1); + MapField* intern2 = (MapField*)Z_OBJ_P(map2); + + return MapType_Eq(intern1->type, intern2->type) && + MapEq(intern1->map, intern2->map, intern1->type) + ? 0 + : 1; +} + +/** + * MapField_clone_obj() + * + * Object handler for cloning an object in PHP. Called when PHP code does: + * + * $map2 = clone $map1; + */ +static zend_object *MapField_clone_obj(PROTO_VAL *object) { + MapField* intern = PROTO_VAL_P(object); + upb_arena *arena = Arena_Get(&intern->arena); + upb_map *clone = + upb_map_new(arena, intern->type.key_type, intern->type.val_type.type); + size_t iter = UPB_MAP_BEGIN; + + while (upb_mapiter_next(intern->map, &iter)) { + upb_msgval key = upb_mapiter_key(intern->map, iter); + upb_msgval val = upb_mapiter_value(intern->map, iter); + upb_map_set(clone, key, val, arena); } - CASE_TYPE(BOOL, bool, int8_t, BOOL) - CASE_TYPE(INT32, int32, int32_t, LONG) - CASE_TYPE(INT64, int64, int64_t, LONG) - CASE_TYPE(UINT32, uint32, uint32_t, LONG) - CASE_TYPE(UINT64, uint64, uint64_t, LONG) - -#undef CASE_TYPE - default: - // Map constructor should not allow a Map with another key type to be - // constructed. - assert(false); - break; - } - - return true; + zval ret; + MapField_GetPhpWrapper(&ret, clone, intern->type, &intern->arena); + return Z_OBJ_P(&ret); } -// ----------------------------------------------------------------------------- -// MapField methods -// ----------------------------------------------------------------------------- - -static zend_function_entry map_field_methods[] = { - PHP_ME(MapField, __construct, NULL, ZEND_ACC_PUBLIC) - PHP_ME(MapField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC) - PHP_ME(MapField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC) - PHP_ME(MapField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC) - PHP_ME(MapField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC) - PHP_ME(MapField, count, arginfo_void, ZEND_ACC_PUBLIC) - PHP_ME(MapField, getIterator, arginfo_void, ZEND_ACC_PUBLIC) - ZEND_FE_END -}; - -// Forward declare static functions. - -static void map_field_write_dimension(zval *object, zval *key, - zval *value TSRMLS_DC); - -// ----------------------------------------------------------------------------- -// MapField creation/desctruction -// ----------------------------------------------------------------------------- - -zend_class_entry* map_field_type; -zend_class_entry* map_field_iter_type; - -zend_object_handlers* map_field_handlers; -zend_object_handlers* map_field_iter_handlers; - -static void map_begin_internal(Map *map, MapIter *iter) { - iter->self = map; - upb_strtable_begin(&iter->it, &map->table); +static zval *Map_GetPropertyPtrPtr(PROTO_VAL *object, PROTO_STR *member, + int type, void **cache_slot) { + return NULL; // We don't offer direct references to our properties. } -static HashTable *map_field_get_gc(zval *object, CACHED_VALUE **table, int *n) { - // TODO(teboring): Unfortunately, zend engine does not support garbage - // collection for custom array. We have to use zend engine's native array - // instead. - *table = NULL; - *n = 0; - return NULL; +static HashTable *Map_GetProperties(PROTO_VAL *object) { + return NULL; // We do not have a properties table. } -// Define map value element free function. -#if PHP_MAJOR_VERSION < 7 -static inline void php_proto_map_string_release(void *value) { - zval_ptr_dtor(value); -} +// C Functions from map.h ////////////////////////////////////////////////////// -static inline void php_proto_map_object_release(void *value) { - zval_ptr_dtor(value); -} -#else -static inline void php_proto_map_string_release(void *value) { - zend_string* object = *(zend_string**)value; - zend_string_release(object); -} -static inline void php_proto_map_object_release(void *value) { - zend_object* object = *(zend_object**)value; - if(--GC_REFCOUNT(object) == 0) { - zend_objects_store_del(object); +// These are documented in the header file. + +void MapField_GetPhpWrapper(zval *val, upb_map *map, MapField_Type type, + zval *arena) { + if (!map) { + ZVAL_NULL(val); + return; } -} -#endif -// Define object free method. -PHP_PROTO_OBJECT_FREE_START(Map, map_field) -MapIter it; -int len; -for (map_begin_internal(intern, &it); !map_done(&it); map_next(&it)) { - upb_value value = map_iter_value(&it, &len); - void *mem = upb_value_memory(&value); - switch (intern->value_type) { - case UPB_TYPE_MESSAGE: - php_proto_map_object_release(mem); - break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - php_proto_map_string_release(mem); - break; - default: - break; + if (!ObjCache_Get(map, val)) { + MapField *intern = emalloc(sizeof(MapField)); + zend_object_std_init(&intern->std, MapField_class_entry); + intern->std.handlers = &MapField_object_handlers; + ZVAL_COPY(&intern->arena, arena); + intern->map = map; + intern->type = type; + // Skip object_properties_init(), we don't allow derived classes. + ObjCache_Add(intern->map, &intern->std); + ZVAL_OBJ(val, &intern->std); } } -upb_strtable_uninit(&intern->table); -PHP_PROTO_OBJECT_FREE_END - -PHP_PROTO_OBJECT_DTOR_START(Map, map_field) -PHP_PROTO_OBJECT_DTOR_END - -// Define object create method. -PHP_PROTO_OBJECT_CREATE_START(Map, map_field) -// Table value type is always UINT64: this ensures enough space to store the -// native_slot value. -if (!upb_strtable_init(&intern->table, UPB_CTYPE_UINT64)) { - zend_error(E_USER_ERROR, "Could not allocate table."); -} -PHP_PROTO_OBJECT_CREATE_END(Map, map_field) - -// Init class entry. -PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\MapField", Map, - map_field) -zend_class_implements(map_field_type TSRMLS_CC, 3, spl_ce_ArrayAccess, - zend_ce_aggregate, spl_ce_Countable); -map_field_handlers->write_dimension = map_field_write_dimension; -map_field_handlers->get_gc = map_field_get_gc; -PHP_PROTO_INIT_CLASS_END - -void map_field_create_with_field(const zend_class_entry *ce, - const upb_fielddef *field, - CACHED_VALUE *map_field PHP_PROTO_TSRMLS_DC) { - const upb_fielddef *key_field = map_field_key(field); - const upb_fielddef *value_field = map_field_value(field); - map_field_create_with_type( - ce, upb_fielddef_type(key_field), upb_fielddef_type(value_field), - field_type_class(value_field TSRMLS_CC), map_field PHP_PROTO_TSRMLS_CC); -} -void map_field_create_with_type(const zend_class_entry *ce, - upb_fieldtype_t key_type, - upb_fieldtype_t value_type, - const zend_class_entry *msg_ce, - CACHED_VALUE *map_field PHP_PROTO_TSRMLS_DC) { - CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(CACHED_PTR_TO_ZVAL_PTR(map_field), - map_field_type); - Map *intern = UNBOX(Map, CACHED_TO_ZVAL_PTR(*map_field)); - intern->key_type = key_type; - intern->value_type = value_type; - intern->msg_ce = msg_ce; -} +upb_map *MapField_GetUpbMap(zval *val, MapField_Type type, upb_arena *arena) { + if (Z_ISREF_P(val)) { + ZVAL_DEREF(val); + } -// ----------------------------------------------------------------------------- -// MapField Handlers -// ----------------------------------------------------------------------------- + if (Z_TYPE_P(val) == IS_ARRAY) { + upb_map *map = upb_map_new(arena, type.key_type, type.val_type.type); + HashTable *table = HASH_OF(val); + HashPosition pos; -static bool map_field_read_dimension(zval *object, zval *key, int type, - CACHED_VALUE *retval TSRMLS_DC) { - Map *intern = UNBOX(Map, object); + zend_hash_internal_pointer_reset_ex(table, &pos); - char keybuf[TABLE_KEY_BUF_LENGTH]; - const char* keyval = NULL; - size_t length = 0; - upb_value v; -#ifndef NDEBUG - v.ctype = UPB_CTYPE_UINT64; -#endif - if (!table_key(intern, key, keybuf, &keyval, &length TSRMLS_CC)) { - return false; - } + while (true) { + zval php_key; + zval *php_val; + upb_msgval upb_key; + upb_msgval upb_val; - if (upb_strtable_lookup2(&intern->table, keyval, length, &v)) { - void* mem = upb_value_memory(&v); - native_slot_get_by_map_value(intern->value_type, mem, retval TSRMLS_CC); - return true; - } else { - zend_error(E_USER_ERROR, "Given key doesn't exist."); - return false; - } -} + zend_hash_get_current_key_zval_ex(table, &php_key, &pos); + php_val = zend_hash_get_current_data_ex(table, &pos); -bool map_index_set(Map *intern, const char* keyval, int length, upb_value v) { - // Replace any existing value by issuing a 'remove' operation first. - upb_strtable_remove2(&intern->table, keyval, length, NULL); - if (!upb_strtable_insert2(&intern->table, keyval, length, v)) { - zend_error(E_USER_ERROR, "Could not insert into table"); - return false; - } - return true; -} + if (!php_val) return map; -static void map_field_write_dimension(zval *object, zval *key, - zval *value TSRMLS_DC) { - Map *intern = UNBOX(Map, object); + if (!Convert_PhpToUpb(&php_key, &upb_key, KeyType(type), arena) || + !Convert_PhpToUpbAutoWrap(php_val, &upb_val, type.val_type, arena)) { + return NULL; + } - char keybuf[TABLE_KEY_BUF_LENGTH]; - const char* keyval = NULL; - size_t length = 0; - upb_value v; - void* mem; - if (!table_key(intern, key, keybuf, &keyval, &length TSRMLS_CC)) { - return; + upb_map_set(map, upb_key, upb_val, arena); + zend_hash_move_forward_ex(table, &pos); + zval_dtor(&php_key); + } + } else if (Z_TYPE_P(val) == IS_OBJECT && + Z_OBJCE_P(val) == MapField_class_entry) { + MapField *intern = (MapField*)Z_OBJ_P(val); + + if (!MapType_Eq(intern->type, type)) { + php_error_docref(NULL, E_USER_ERROR, "Wrong type for this map field."); + return NULL; + } + + upb_arena_fuse(arena, Arena_Get(&intern->arena)); + return intern->map; + } else { + php_error_docref(NULL, E_USER_ERROR, "Must be a map"); + return NULL; } +} - mem = upb_value_memory(&v); - memset(mem, 0, native_slot_size(intern->value_type)); - if (!native_slot_set_by_map(intern->value_type, intern->msg_ce, mem, - value TSRMLS_CC)) { - return; - } -#ifndef NDEBUG - v.ctype = UPB_CTYPE_UINT64; -#endif +bool MapEq(const upb_map *m1, const upb_map *m2, MapField_Type type) { + size_t iter = UPB_MAP_BEGIN; - // Replace any existing value by issuing a 'remove' operation first. - upb_strtable_remove2(&intern->table, keyval, length, NULL); - if (!upb_strtable_insert2(&intern->table, keyval, length, v)) { - zend_error(E_USER_ERROR, "Could not insert into table"); - return; - } -} + if ((m1 == NULL) != (m2 == NULL)) return false; + if (m1 == NULL) return true; + if (upb_map_size(m1) != upb_map_size(m2)) return false; -static bool map_field_unset_dimension(zval *object, zval *key TSRMLS_DC) { - Map *intern = UNBOX(Map, object); + while (upb_mapiter_next(m1, &iter)) { + upb_msgval key = upb_mapiter_key(m1, iter); + upb_msgval val1 = upb_mapiter_value(m1, iter); + upb_msgval val2; - char keybuf[TABLE_KEY_BUF_LENGTH]; - const char* keyval = NULL; - size_t length = 0; - upb_value v; - if (!table_key(intern, key, keybuf, &keyval, &length TSRMLS_CC)) { - return false; + if (!upb_map_get(m2, key, &val2)) return false; + if (!ValueEq(val1, val2, type.val_type)) return false; } -#ifndef NDEBUG - v.ctype = UPB_CTYPE_UINT64; -#endif - - upb_strtable_remove2(&intern->table, keyval, length, &v); return true; } -// ----------------------------------------------------------------------------- -// PHP MapField Methods -// ----------------------------------------------------------------------------- +// MapField PHP methods //////////////////////////////////////////////////////// + +/** + * MapField::__construct() + * + * Constructs an instance of MapField. + * @param long Key type. + * @param long Value type. + * @param string Message/Enum class (message/enum value types only). + */ PHP_METHOD(MapField, __construct) { - long key_type, value_type; + MapField *intern = (MapField*)Z_OBJ_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + zend_long key_type, val_type; zend_class_entry* klass = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|C", &key_type, - &value_type, &klass) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|C", &key_type, &val_type, + &klass) != SUCCESS) { return; } - Map *intern = UNBOX(Map, getThis()); - intern->key_type = to_fieldtype(key_type); - intern->value_type = to_fieldtype(value_type); - intern->msg_ce = klass; + intern->type.key_type = pbphp_dtype_to_type(key_type); + intern->type.val_type.type = pbphp_dtype_to_type(val_type); + intern->type.val_type.desc = Descriptor_GetFromClassEntry(klass); // Check that the key type is an allowed type. - switch (intern->key_type) { + switch (intern->type.key_type) { case UPB_TYPE_INT32: case UPB_TYPE_INT64: case UPB_TYPE_UINT32: @@ -385,108 +292,323 @@ PHP_METHOD(MapField, __construct) { default: zend_error(E_USER_ERROR, "Invalid key type for map."); } -} + if (intern->type.val_type.type == UPB_TYPE_MESSAGE && klass == NULL) { + php_error_docref(NULL, E_USER_ERROR, + "Message/enum type must have concrete class."); + return; + } + + intern->map = + upb_map_new(arena, intern->type.key_type, intern->type.val_type.type); + ObjCache_Add(intern->map, &intern->std); +} + +/** + * MapField::offsetExists() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * isset($map[$idx]); + * empty($map[$idx]); + * + * @param long The index to be checked. + * @return bool True if the element at the given index exists. + */ PHP_METHOD(MapField, offsetExists) { + MapField *intern = (MapField*)Z_OBJ_P(getThis()); zval *key; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == - FAILURE) { + upb_msgval upb_key; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS || + !Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL)) { return; } - Map *intern = UNBOX(Map, getThis()); + RETURN_BOOL(upb_map_get(intern->map, upb_key, NULL)); +} + +/** + * MapField::offsetGet() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * $x = $map[$idx]; + * + * @param long The index of the element to be fetched. + * @return object The stored element at given index. + * @exception Invalid type for index. + * @exception Non-existing index. + */ +PHP_METHOD(MapField, offsetGet) { + MapField *intern = (MapField*)Z_OBJ_P(getThis()); + zval *key; + zval ret; + upb_msgval upb_key, upb_val; - char keybuf[TABLE_KEY_BUF_LENGTH]; - const char* keyval = NULL; - size_t length = 0; - upb_value v; -#ifndef NDEBUG - v.ctype = UPB_CTYPE_UINT64; -#endif - if (!table_key(intern, key, keybuf, &keyval, &length TSRMLS_CC)) { - RETURN_BOOL(false); + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS || + !Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL)) { + return; } - RETURN_BOOL(upb_strtable_lookup2(&intern->table, keyval, length, &v)); -} - -PHP_METHOD(MapField, offsetGet) { - zval *index, *value; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) == - FAILURE) { + if (!upb_map_get(intern->map, upb_key, &upb_val)) { + zend_error(E_USER_ERROR, "Given key doesn't exist."); return; } - map_field_read_dimension(getThis(), index, BP_VAR_R, - ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC); -} + Convert_UpbToPhp(upb_val, &ret, intern->type.val_type, &intern->arena); + RETURN_ZVAL(&ret, 0, 1); +} + +/** + * MapField::offsetSet() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * $map[$idx] = $x; + * + * @param long The index of the element to be assigned. + * @param object The element to be assigned. + * @exception Invalid type for index. + * @exception Non-existing index. + * @exception Incorrect type of the element. + */ PHP_METHOD(MapField, offsetSet) { - zval *index, *value; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &index, &value) == - FAILURE) { + MapField *intern = (MapField*)Z_OBJ_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + zval *key, *val; + upb_msgval upb_key, upb_val; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &key, &val) != SUCCESS || + !Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL) || + !Convert_PhpToUpb(val, &upb_val, intern->type.val_type, arena)) { return; } - map_field_write_dimension(getThis(), index, value TSRMLS_CC); + + upb_map_set(intern->map, upb_key, upb_val, arena); } +/** + * MapField::offsetUnset() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * unset($map[$idx]); + * + * @param long The index of the element to be removed. + * @exception Invalid type for index. + * @exception The element to be removed is not at the end of the MapField. + */ PHP_METHOD(MapField, offsetUnset) { - zval *index; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) == - FAILURE) { + MapField *intern = (MapField*)Z_OBJ_P(getThis()); + zval *key; + upb_msgval upb_key; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS || + !Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL)) { return; } - map_field_unset_dimension(getThis(), index TSRMLS_CC); + + upb_map_delete(intern->map, upb_key); } +/** + * MapField::count() + * + * Implements the Countable interface. Invoked when PHP code calls: + * + * $len = count($map); + * Return the number of stored elements. + * This will also be called for: count($map) + * @return long The number of stored elements. + */ PHP_METHOD(MapField, count) { - Map *intern = UNBOX(Map, getThis()); + MapField *intern = (MapField*)Z_OBJ_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } - RETURN_LONG(upb_strtable_count(&intern->table)); + RETURN_LONG(upb_map_size(intern->map)); } +/** + * MapField::getIterator() + * + * Implements the IteratorAggregate interface. Invoked when PHP code calls: + * + * foreach ($arr) {} + * + * @return object Beginning iterator. + */ PHP_METHOD(MapField, getIterator) { - CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(return_value, - map_field_iter_type); - - Map *intern = UNBOX(Map, getThis()); - MapIter *iter = UNBOX(MapIter, return_value); - map_begin(getThis(), iter TSRMLS_CC); + zval ret; + MapFieldIter_make(&ret, getThis()); + RETURN_ZVAL(&ret, 0, 1); } +ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2) + ZEND_ARG_INFO(0, key_type) + ZEND_ARG_INFO(0, value_type) + ZEND_ARG_INFO(0, value_class) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1) + ZEND_ARG_INFO(0, index) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2) + ZEND_ARG_INFO(0, index) + ZEND_ARG_INFO(0, newval) +ZEND_END_ARG_INFO() + +static zend_function_entry MapField_methods[] = { + PHP_ME(MapField, __construct, arginfo_construct, ZEND_ACC_PUBLIC) + PHP_ME(MapField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC) + PHP_ME(MapField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC) + PHP_ME(MapField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC) + PHP_ME(MapField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC) + PHP_ME(MapField, count, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(MapField, getIterator, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + // ----------------------------------------------------------------------------- -// Map Iterator +// MapFieldIter // ----------------------------------------------------------------------------- -void map_begin(zval *map_php, MapIter *iter TSRMLS_DC) { - Map *self = UNBOX(Map, map_php); - map_begin_internal(self, iter); +typedef struct { + zend_object std; + zval map_field; + size_t position; +} MapFieldIter; + +zend_class_entry *MapFieldIter_class_entry; +static zend_object_handlers MapFieldIter_object_handlers; + +/** + * MapFieldIter_create() + * + * PHP class entry function to allocate and initialize a new MapFieldIter + * object. + */ +zend_object* MapFieldIter_create(zend_class_entry *class_type) { + MapFieldIter *intern = emalloc(sizeof(MapFieldIter)); + zend_object_std_init(&intern->std, class_type); + intern->std.handlers = &MapFieldIter_object_handlers; + ZVAL_NULL(&intern->map_field); + intern->position = 0; + // Skip object_properties_init(), we don't allow derived classes. + return &intern->std; +} + +/** + * MapFieldIter_dtor() + * + * Object handler to destroy a MapFieldIter. This releases all resources + * associated with the message. Note that it is possible to access a destroyed + * object from PHP in rare cases. + */ +static void map_field_iter_dtor(zend_object* obj) { + MapFieldIter* intern = (MapFieldIter*)obj; + zval_ptr_dtor(&intern->map_field); + zend_object_std_dtor(&intern->std); +} + +/** + * MapFieldIter_make() + * + * Function to create a MapFieldIter directly from C. + */ +static void MapFieldIter_make(zval *val, zval *map_field) { + MapFieldIter *iter; + ZVAL_OBJ(val, + MapFieldIter_class_entry->create_object(MapFieldIter_class_entry)); + iter = (MapFieldIter*)Z_OBJ_P(val); + ZVAL_COPY(&iter->map_field, map_field); } -void map_next(MapIter *iter) { - upb_strtable_next(&iter->it); -} +// ----------------------------------------------------------------------------- +// PHP MapFieldIter Methods +// ----------------------------------------------------------------------------- -bool map_done(MapIter *iter) { - return upb_strtable_done(&iter->it); +/* + * When a user writes: + * + * foreach($arr as $key => $val) {} + * + * PHP translates this into: + * + * $iter = $arr->getIterator(); + * for ($iter->rewind(); $iter->valid(); $iter->next()) { + * $key = $iter->key(); + * $val = $iter->current(); + * } + */ + +/** + * MapFieldIter::rewind() + * + * Implements the Iterator interface. Sets the iterator to the first element. + */ +PHP_METHOD(MapFieldIter, rewind) { + MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis()); + MapField *map_field = (MapField*)Z_OBJ_P(&intern->map_field); + intern->position = UPB_MAP_BEGIN; + upb_mapiter_next(map_field->map, &intern->position); } -const char *map_iter_key(MapIter *iter, int *len) { - *len = upb_strtable_iter_keylength(&iter->it); - return upb_strtable_iter_key(&iter->it); +/** + * MapFieldIter::current() + * + * Implements the Iterator interface. Returns the current value. + */ +PHP_METHOD(MapFieldIter, current) { + MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis()); + MapField *field = (MapField*)Z_OBJ_P(&intern->map_field); + upb_msgval upb_val = upb_mapiter_value(field->map, intern->position); + zval ret; + Convert_UpbToPhp(upb_val, &ret, field->type.val_type, &field->arena); + RETURN_ZVAL(&ret, 0, 1); +} + +/** + * MapFieldIter::key() + * + * Implements the Iterator interface. Returns the current key. + */ +PHP_METHOD(MapFieldIter, key) { + MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis()); + MapField *field = (MapField*)Z_OBJ_P(&intern->map_field); + upb_msgval upb_key = upb_mapiter_key(field->map, intern->position); + zval ret; + Convert_UpbToPhp(upb_key, &ret, KeyType(field->type), NULL); + RETURN_ZVAL(&ret, 0, 1); +} + +/** + * MapFieldIter::next() + * + * Implements the Iterator interface. Advances to the next element. + */ +PHP_METHOD(MapFieldIter, next) { + MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis()); + MapField *field = (MapField*)Z_OBJ_P(&intern->map_field); + upb_mapiter_next(field->map, &intern->position); } -upb_value map_iter_value(MapIter *iter, int *len) { - *len = native_slot_size(iter->self->value_type); - return upb_strtable_iter_value(&iter->it); +/** + * MapFieldIter::valid() + * + * Implements the Iterator interface. Returns true if this is a valid element. + */ +PHP_METHOD(MapFieldIter, valid) { + MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis()); + MapField *field = (MapField*)Z_OBJ_P(&intern->map_field); + bool done = upb_mapiter_done(field->map, intern->position); + RETURN_BOOL(!done); } -// ----------------------------------------------------------------------------- -// MapFieldIter methods -// ----------------------------------------------------------------------------- static zend_function_entry map_field_iter_methods[] = { PHP_ME(MapFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC) PHP_ME(MapFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC) @@ -497,65 +619,50 @@ static zend_function_entry map_field_iter_methods[] = { }; // ----------------------------------------------------------------------------- -// MapFieldIter creation/desctruction -// ----------------------------------------------------------------------------- - -// Define object free method. -PHP_PROTO_OBJECT_FREE_START(MapIter, map_field_iter) -PHP_PROTO_OBJECT_FREE_END - -PHP_PROTO_OBJECT_DTOR_START(MapIter, map_field_iter) -PHP_PROTO_OBJECT_DTOR_END - -// Define object create method. -PHP_PROTO_OBJECT_CREATE_START(MapIter, map_field_iter) -intern->self = NULL; -PHP_PROTO_OBJECT_CREATE_END(MapIter, map_field_iter) - -// Init class entry. -PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\MapFieldIter", - MapIter, map_field_iter) -zend_class_implements(map_field_iter_type TSRMLS_CC, 1, zend_ce_iterator); -PHP_PROTO_INIT_CLASS_END - -// ----------------------------------------------------------------------------- -// PHP MapFieldIter Methods +// Module init. // ----------------------------------------------------------------------------- -PHP_METHOD(MapFieldIter, rewind) { - MapIter *intern = UNBOX(MapIter, getThis()); - map_begin_internal(intern->self, intern); -} - -PHP_METHOD(MapFieldIter, current) { - MapIter *intern = UNBOX(MapIter, getThis()); - Map *map_field = intern->self; - - int value_length = 0; - upb_value value = map_iter_value(intern, &value_length); - - void* mem = upb_value_memory(&value); - native_slot_get_by_map_value(map_field->value_type, mem, - ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC); -} - -PHP_METHOD(MapFieldIter, key) { - MapIter *intern = UNBOX(MapIter, getThis()); - Map *map_field = intern->self; - - int key_length = 0; - const char* key = map_iter_key(intern, &key_length); - - native_slot_get_by_map_key(map_field->key_type, key, key_length, - ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC); -} - -PHP_METHOD(MapFieldIter, next) { - MapIter *intern = UNBOX(MapIter, getThis()); - map_next(intern); -} - -PHP_METHOD(MapFieldIter, valid) { - MapIter *intern = UNBOX(MapIter, getThis()); - RETURN_BOOL(!map_done(intern)); +/** + * Map_ModuleInit() + * + * Called when the C extension is loaded to register all types. + */ + +void Map_ModuleInit() { + zend_class_entry tmp_ce; + zend_object_handlers *h; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapField", + MapField_methods); + + MapField_class_entry = zend_register_internal_class(&tmp_ce); + zend_class_implements(MapField_class_entry, 3, spl_ce_ArrayAccess, + zend_ce_aggregate, spl_ce_Countable); + MapField_class_entry->ce_flags |= ZEND_ACC_FINAL; + MapField_class_entry->create_object = MapField_create; + + h = &MapField_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + h->dtor_obj = MapField_destructor; +#if PHP_VERSION_ID < 80000 + h->compare_objects = MapField_compare_objects; +#else + h->compare = MapField_compare_objects; +#endif + h->clone_obj = MapField_clone_obj; + h->get_properties = Map_GetProperties; + h->get_property_ptr_ptr = Map_GetPropertyPtrPtr; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapFieldIter", + map_field_iter_methods); + + MapFieldIter_class_entry = zend_register_internal_class(&tmp_ce); + zend_class_implements(MapFieldIter_class_entry, 1, zend_ce_iterator); + MapFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL; + MapFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL; + MapFieldIter_class_entry->create_object = MapFieldIter_create; + + h = &MapFieldIter_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + h->dtor_obj = map_field_iter_dtor; } diff --git a/php/ext/google/protobuf/map.h b/php/ext/google/protobuf/map.h new file mode 100644 index 0000000000000..c523cd0da937b --- /dev/null +++ b/php/ext/google/protobuf/map.h @@ -0,0 +1,70 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef PHP_PROTOBUF_MAP_H_ +#define PHP_PROTOBUF_MAP_H_ + +#include + +#include "def.h" +#include "php-upb.h" + +void Map_ModuleInit(); + +typedef struct { + upb_fieldtype_t key_type; + TypeInfo val_type; +} MapField_Type; + +MapField_Type MapType_Get(const upb_fielddef *f); + +// Gets a upb_map* for the PHP object |val|: +// * If |val| is a RepeatedField object, we first check its type and verify +// that that the elements have the correct type for |f|. If so, we return the +// wrapped upb_map*. We also make sure that this map's arena is fused to +// |arena|, so the returned upb_map is guaranteed to live as long as +// |arena|. +// * If |val| is a PHP Map, we attempt to create a new upb_map using +// |arena| and add all of the PHP elements to it. +// +// If an error occurs, we raise a PHP error and return NULL. +upb_map *MapField_GetUpbMap(zval *val, MapField_Type type, upb_arena *arena); + +// Creates a PHP MapField object for the given upb_map* and |f| and returns it +// in |val|. The PHP object will keep a reference to this |arena| to ensure the +// underlying array data stays alive. +// +// If |map| is NULL, this will return a PHP null object. +void MapField_GetPhpWrapper(zval *val, upb_map *arr, MapField_Type type, + zval *arena); + +bool MapEq(const upb_map *m1, const upb_map *m2, MapField_Type type); + +#endif // PHP_PROTOBUF_MAP_H_ diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c index 519786ddf92b2..7f27670320dc0 100644 --- a/php/ext/google/protobuf/message.c +++ b/php/ext/google/protobuf/message.c @@ -28,317 +28,1351 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include "message.h" + +#include #include #include +// This is not self-contained: it must be after other Zend includes. +#include +#include + +#include "arena.h" +#include "array.h" +#include "convert.h" +#include "def.h" +#include "map.h" +#include "php-upb.h" #include "protobuf.h" -static zend_class_entry* message_type; -zend_object_handlers* message_handlers; - -static zend_function_entry message_methods[] = { - PHP_ME(Message, clear, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, serializeToString, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, mergeFromString, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, serializeToJsonString, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, mergeFromJsonString, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, mergeFrom, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, readOneof, NULL, ZEND_ACC_PROTECTED) - PHP_ME(Message, writeOneof, NULL, ZEND_ACC_PROTECTED) - PHP_ME(Message, whichOneof, NULL, ZEND_ACC_PROTECTED) - PHP_ME(Message, __construct, NULL, ZEND_ACC_PROTECTED) - {NULL, NULL, NULL} -}; +// ----------------------------------------------------------------------------- +// Message +// ----------------------------------------------------------------------------- -// Forward declare static functions. +typedef struct { + zend_object std; + zval arena; + const Descriptor* desc; + upb_msg *msg; +} Message; -#if PHP_MAJOR_VERSION < 7 -static void message_set_property(zval* object, zval* member, zval* value, - php_proto_zend_literal key TSRMLS_DC); -static zval* message_get_property(zval* object, zval* member, int type, - const zend_literal* key TSRMLS_DC); -static zval** message_get_property_ptr_ptr(zval* object, zval* member, int type, - php_proto_zend_literal key TSRMLS_DC); -static HashTable* message_get_gc(zval* object, zval*** table, int* n TSRMLS_DC); -#else -static void message_set_property(zval* object, zval* member, zval* value, - void** cache_slot); -static zval* message_get_property(zval* object, zval* member, int type, - void** cache_slot, zval* rv); -static zval* message_get_property_ptr_ptr(zval* object, zval* member, int type, - void** cache_slot); -static HashTable* message_get_gc(zval* object, zval** table, int* n); -#endif -static HashTable* message_get_properties(zval* object TSRMLS_DC); +zend_class_entry *message_ce; +static zend_object_handlers message_object_handlers; -// ----------------------------------------------------------------------------- -// PHP Message Handlers -// ----------------------------------------------------------------------------- +static void Message_SuppressDefaultProperties(zend_class_entry *class_type) { + // We suppress all default properties, because all our properties are handled + // by our read_property handler. + // + // This also allows us to put our zend_object member at the beginning of our + // struct -- instead of putting it at the end with pointer fixups to access + // our own data, as recommended in the docs -- because Zend won't add any of + // its own storage directly after the zend_object if default_properties_count + // == 0. + // + // This is not officially supported, but since it simplifies the code, we'll + // do it for as long as it works in practice. + class_type->default_properties_count = 0; +} -// Define object free method. -PHP_PROTO_OBJECT_FREE_START(MessageHeader, message) - FREE(intern->data); -PHP_PROTO_OBJECT_FREE_END - -PHP_PROTO_OBJECT_DTOR_START(MessageHeader, message) -PHP_PROTO_OBJECT_DTOR_END - -// Define object create method. -PHP_PROTO_OBJECT_CREATE_START(MessageHeader, message) -// Because php call this create func before calling the sub-message's -// constructor defined in PHP, it's possible that the decriptor of this class -// hasn't been added to descritpor pool (when the class is first -// instantiated). In that case, we will defer the initialization of the custom -// data to the parent Message's constructor, which will be called by -// sub-message's constructors after the descriptor has been added. -PHP_PROTO_OBJECT_CREATE_END(MessageHeader, message) - -// Init class entry. -PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\Message", - MessageHeader, message) - message_handlers->write_property = message_set_property; - message_handlers->read_property = message_get_property; - message_handlers->get_property_ptr_ptr = message_get_property_ptr_ptr; - message_handlers->get_properties = message_get_properties; - message_handlers->get_gc = message_get_gc; -PHP_PROTO_INIT_CLASS_END - -#if PHP_MAJOR_VERSION < 7 -static void message_set_property(zval* object, zval* member, zval* value, - php_proto_zend_literal key TSRMLS_DC) { -#else -static void message_set_property(zval* object, zval* member, zval* value, - void** cache_slot) { -#endif - if (Z_TYPE_P(member) != IS_STRING) { - zend_error(E_USER_ERROR, "Unexpected type for field name"); +// PHP Object Handlers ///////////////////////////////////////////////////////// + +/** + * Message_create() + * + * PHP class entry function to allocate and initialize a new Message object. + */ +static zend_object* Message_create(zend_class_entry *class_type) { + Message *intern = emalloc(sizeof(Message)); + Message_SuppressDefaultProperties(class_type); + zend_object_std_init(&intern->std, class_type); + intern->std.handlers = &message_object_handlers; + Arena_Init(&intern->arena); + return &intern->std; +} + +/** + * Message_dtor() + * + * Object handler to destroy a Message. This releases all resources associated + * with the message. Note that it is possible to access a destroyed object from + * PHP in rare cases. + */ +static void Message_dtor(zend_object* obj) { + Message* intern = (Message*)obj; + ObjCache_Delete(intern->msg); + zval_dtor(&intern->arena); + zend_object_std_dtor(&intern->std); +} + +/** + * get_field() + * + * Helper function to look up a field given a member name (as a string). + */ +static const upb_fielddef *get_field(Message *msg, PROTO_STR *member) { + const upb_msgdef *m = msg->desc->msgdef; + const upb_fielddef *f = + upb_msgdef_ntof(m, PROTO_STRVAL_P(member), PROTO_STRLEN_P(member)); + + if (!f) { + zend_throw_exception_ex(NULL, 0, "No such property %s.", + ZSTR_VAL(msg->desc->class_entry->name)); + } + + return f; +} + +static void Message_get(Message *intern, const upb_fielddef *f, zval *rv) { + upb_arena *arena = Arena_Get(&intern->arena); + + if (upb_fielddef_ismap(f)) { + upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena); + MapField_GetPhpWrapper(rv, msgval.map, MapType_Get(f), &intern->arena); + } else if (upb_fielddef_isseq(f)) { + upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena); + RepeatedField_GetPhpWrapper(rv, msgval.array, TypeInfo_Get(f), + &intern->arena); + } else { + upb_msgval msgval = upb_msg_get(intern->msg, f); + Convert_UpbToPhp(msgval, rv, TypeInfo_Get(f), &intern->arena); + } +} + +static bool Message_set(Message *intern, const upb_fielddef *f, zval *val) { + upb_arena *arena = Arena_Get(&intern->arena); + upb_msgval msgval; + + if (upb_fielddef_ismap(f)) { + msgval.map_val = MapField_GetUpbMap(val, MapType_Get(f), arena); + if (!msgval.map_val) return false; + } else if (upb_fielddef_isseq(f)) { + msgval.array_val = RepeatedField_GetUpbArray(val, TypeInfo_Get(f), arena); + if (!msgval.array_val) return false; + } else { + if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(f), arena)) return false; + } + + upb_msg_set(intern->msg, f, msgval, arena); + return true; +} + +static bool MessageEq(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m); + +/** + * ValueEq() + */ +bool ValueEq(upb_msgval val1, upb_msgval val2, TypeInfo type) { + switch (type.type) { + case UPB_TYPE_BOOL: + return val1.bool_val == val2.bool_val; + case UPB_TYPE_INT32: + case UPB_TYPE_UINT32: + case UPB_TYPE_ENUM: + return val1.int32_val == val2.int32_val; + case UPB_TYPE_INT64: + case UPB_TYPE_UINT64: + return val1.int64_val == val2.int64_val; + case UPB_TYPE_FLOAT: + return val1.float_val == val2.float_val; + case UPB_TYPE_DOUBLE: + return val1.double_val == val2.double_val; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + return val1.str_val.size == val2.str_val.size && + memcmp(val1.str_val.data, val2.str_val.data, val1.str_val.size) == 0; + case UPB_TYPE_MESSAGE: + return MessageEq(val1.msg_val, val2.msg_val, type.desc->msgdef); + default: + return false; + } +} + +/** + * MessageEq() + */ +static bool MessageEq(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m) { + upb_msg_field_iter i; + + for(upb_msg_field_begin(&i, m); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { + const upb_fielddef *f = upb_msg_iter_field(&i); + upb_msgval val1 = upb_msg_get(m1, f); + upb_msgval val2 = upb_msg_get(m2, f); + + if (upb_fielddef_haspresence(f)) { + if (upb_msg_has(m1, f) != upb_msg_has(m2, f)) { + return false; + } + if (!upb_msg_has(m1, f)) continue; + } + + if (upb_fielddef_ismap(f)) { + if (!MapEq(val1.map_val, val2.map_val, MapType_Get(f))) return false; + } else if (upb_fielddef_isseq(f)) { + if (!ArrayEq(val1.array_val, val2.array_val, TypeInfo_Get(f))) return false; + } else { + if (!ValueEq(val1, val2, TypeInfo_Get(f))) return false; + } + } + + return true; +} + +/** + * Message_compare_objects() + * + * Object handler for comparing two message objects. Called whenever PHP code + * does: + * + * $m1 == $m2 + */ +static int Message_compare_objects(zval *m1, zval *m2) { + Message* intern1 = (Message*)Z_OBJ_P(m1); + Message* intern2 = (Message*)Z_OBJ_P(m2); + const upb_msgdef *m = intern1->desc->msgdef; + + if (intern2->desc->msgdef != m) return 1; + + return MessageEq(intern1->msg, intern2->msg, m) ? 0 : 1; +} + +/** + * Message_has_property() + * + * Object handler for testing whether a property exists. Called when PHP code + * does any of: + * + * isset($message->foobar); + * property_exists($message->foobar); + * + * Note that all properties of generated messages are private, so this should + * only be possible to invoke from generated code, which has accessors like this + * (if the field has presence): + * + * public function hasOptionalInt32() + * { + * return isset($this->optional_int32); + * } + */ +static int Message_has_property(PROTO_VAL *obj, PROTO_STR *member, + int has_set_exists, + void **cache_slot) { + Message* intern = PROTO_VAL_P(obj); + const upb_fielddef *f = get_field(intern, member); + + if (!f) return 0; + + if (!upb_fielddef_haspresence(f)) { + zend_throw_exception_ex( + NULL, 0, + "Cannot call isset() on field %s which does not have presence.", + ZSTR_VAL(intern->desc->class_entry->name)); + return 0; + } + + return upb_msg_has(intern->msg, f); +} + +/** + * Message_unset_property() + * + * Object handler for unsetting a property. Called when PHP code calls: + * does any of: + * + * unset($message->foobar); + * + * Note that all properties of generated messages are private, so this should + * only be possible to invoke from generated code, which has accessors like this + * (if the field has presence): + * + * public function clearOptionalInt32() + * { + * unset($this->optional_int32); + * } + */ +static void Message_unset_property(PROTO_VAL *obj, PROTO_STR *member, + void **cache_slot) { + Message* intern = PROTO_VAL_P(obj); + const upb_fielddef *f = get_field(intern, member); + + if (!f) return; + + if (!upb_fielddef_haspresence(f)) { + zend_throw_exception_ex( + NULL, 0, + "Cannot call unset() on field %s which does not have presence.", + ZSTR_VAL(intern->desc->class_entry->name)); return; } -#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0) - if (Z_OBJCE_P(object) != EG(scope)) { + upb_msg_clearfield(intern->msg, f); +} + + +/** + * Message_read_property() + * + * Object handler for reading a property in PHP. Called when PHP code does: + * + * $x = $message->foobar; + * + * Note that all properties of generated messages are private, so this should + * only be possible to invoke from generated code, which has accessors like: + * + * public function getOptionalInt32() + * { + * return $this->optional_int32; + * } + * + * We lookup the field and return the scalar, RepeatedField, or MapField for + * this field. + */ +static zval *Message_read_property(PROTO_VAL *obj, PROTO_STR *member, + int type, void **cache_slot, zval *rv) { + Message* intern = PROTO_VAL_P(obj); + const upb_fielddef *f = get_field(intern, member); + + if (!f) return NULL; + Message_get(intern, f, rv); + return rv; +} + +/** + * Message_write_property() + * + * Object handler for writing a property in PHP. Called when PHP code does: + * + * $message->foobar = $x; + * + * Note that all properties of generated messages are private, so this should + * only be possible to invoke from generated code, which has accessors like: + * + * public function setOptionalInt32($var) + * { + * GPBUtil::checkInt32($var); + * $this->optional_int32 = $var; + * + * return $this; + * } + * + * The C extension version of checkInt32() doesn't actually check anything, so + * we perform all checking and conversion in this function. + */ +static PROTO_RETURN_VAL Message_write_property( + PROTO_VAL *obj, PROTO_STR *member, zval *val, void **cache_slot) { + Message* intern = PROTO_VAL_P(obj); + const upb_fielddef *f = get_field(intern, member); + + if (f && Message_set(intern, f, val)) { +#if PHP_VERSION_ID < 70400 + return; #else - if (Z_OBJCE_P(object) != zend_get_executed_scope()) { + return val; #endif - // User cannot set property directly (e.g., $m->a = 1) - zend_error(E_USER_ERROR, "Cannot access private property."); + } else { +#if PHP_VERSION_ID < 70400 return; +#else + return &EG(error_zval); +#endif } +} - const upb_fielddef* field; +/** + * Message_get_property_ptr_ptr() + * + * Object handler for the get_property_ptr_ptr event in PHP. This returns a + * reference to our internal properties. We don't support this, so we return + * NULL. + */ +static zval *Message_get_property_ptr_ptr(PROTO_VAL *object, PROTO_STR *member, + int type, + void **cache_slot) { + return NULL; // We do not have a properties table. +} + +/** + * Message_clone_obj() + * + * Object handler for cloning an object in PHP. Called when PHP code does: + * + * $msg2 = clone $msg; + */ +static zend_object *Message_clone_obj(PROTO_VAL *object) { + Message* intern = PROTO_VAL_P(object); + upb_msg *clone = upb_msg_new(intern->desc->msgdef, Arena_Get(&intern->arena)); - MessageHeader* self = UNBOX(MessageHeader, object); + // TODO: copy unknown fields? + // TODO: use official upb msg copy function + memcpy(clone, intern->msg, upb_msgdef_layout(intern->desc->msgdef)->size); + zval ret; + Message_GetPhpWrapper(&ret, intern->desc, clone, &intern->arena); + return Z_OBJ_P(&ret); +} + +/** + * Message_get_properties() + * + * Object handler for the get_properties event in PHP. This returns a HashTable + * of our internal properties. We don't support this, so we return NULL. + */ +static HashTable *Message_get_properties(PROTO_VAL *object) { + return NULL; // We don't offer direct references to our properties. +} - field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member)); - if (field == NULL) { - zend_error(E_USER_ERROR, "Unknown field: %s", Z_STRVAL_P(member)); +// C Functions from message.h. ///////////////////////////////////////////////// + +// These are documented in the header file. + +void Message_GetPhpWrapper(zval *val, const Descriptor *desc, upb_msg *msg, + zval *arena) { + if (!msg) { + ZVAL_NULL(val); + return; } - layout_set(self->descriptor->layout, self, field, value TSRMLS_CC); + if (!ObjCache_Get(msg, val)) { + Message *intern = emalloc(sizeof(Message)); + Message_SuppressDefaultProperties(desc->class_entry); + zend_object_std_init(&intern->std, desc->class_entry); + intern->std.handlers = &message_object_handlers; + ZVAL_COPY(&intern->arena, arena); + intern->desc = desc; + intern->msg = msg; + ZVAL_OBJ(val, &intern->std); + ObjCache_Add(intern->msg, &intern->std); + } } -#if PHP_MAJOR_VERSION < 7 -static zval* message_get_property(zval* object, zval* member, int type, - const zend_literal* key TSRMLS_DC) { -#else -static zval* message_get_property(zval* object, zval* member, int type, - void** cache_slot, zval* rv) { -#endif - if (Z_TYPE_P(member) != IS_STRING) { - zend_error(E_USER_ERROR, "Property name has to be a string."); - return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL; +bool Message_GetUpbMessage(zval *val, const Descriptor *desc, upb_arena *arena, + upb_msg **msg) { + PBPHP_ASSERT(desc); + + if (Z_ISREF_P(val)) { + ZVAL_DEREF(val); } -#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0) - if (Z_OBJCE_P(object) != EG(scope)) { -#else - if (Z_OBJCE_P(object) != zend_get_executed_scope()) { -#endif - // User cannot get property directly (e.g., $a = $m->a) - zend_error(E_USER_ERROR, "Cannot access private property."); - return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL; + if (Z_TYPE_P(val) == IS_NULL) { + *msg = NULL; + return true; } - MessageHeader* self = UNBOX(MessageHeader, object); - const upb_fielddef* field; - field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member)); - if (field == NULL) { - return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL; - } - - zend_property_info* property_info; -#if PHP_MAJOR_VERSION < 7 - property_info = - zend_get_property_info(Z_OBJCE_P(object), member, true TSRMLS_CC); - return layout_get( - self->descriptor->layout, message_data(self), field, - OBJ_PROP(Z_OBJ_P(object), property_info->offset) TSRMLS_CC); -#else - property_info = - zend_get_property_info(Z_OBJCE_P(object), Z_STR_P(member), true); - return layout_get( - self->descriptor->layout, message_data(self), field, - OBJ_PROP(Z_OBJ_P(object), property_info->offset) TSRMLS_CC); -#endif + if (Z_TYPE_P(val) == IS_OBJECT && + instanceof_function(Z_OBJCE_P(val), desc->class_entry)) { + Message *intern = (Message*)Z_OBJ_P(val); + upb_arena_fuse(arena, Arena_Get(&intern->arena)); + *msg = intern->msg; + return true; + } else { + zend_throw_exception_ex(NULL, 0, "Given value is not an instance of %s.", + ZSTR_VAL(desc->class_entry->name)); + return false; + } } -#if PHP_MAJOR_VERSION < 7 -static zval** message_get_property_ptr_ptr(zval* object, zval* member, int type, - php_proto_zend_literal key - TSRMLS_DC) { -#else -static zval* message_get_property_ptr_ptr(zval* object, zval* member, int type, - void** cache_slot) { -#endif - return NULL; +// Message PHP methods ///////////////////////////////////////////////////////// + +/** + * Message_InitFromPhp() + * + * Helper method to handle the initialization of a message from a PHP value, eg. + * + * $m = new TestMessage([ + * 'optional_int32' => -42, + * 'optional_bool' => true, + * 'optional_string' => 'a', + * 'optional_enum' => TestEnum::ONE, + * 'optional_message' => new Sub([ + * 'a' => 33 + * ]), + * 'repeated_int32' => [-42, -52], + * 'repeated_enum' => [TestEnum::ZERO, TestEnum::ONE], + * 'repeated_message' => [new Sub(['a' => 34]), + * new Sub(['a' => 35])], + * 'map_int32_int32' => [-62 => -62], + * 'map_int32_enum' => [1 => TestEnum::ONE], + * 'map_int32_message' => [1 => new Sub(['a' => 36])], + * ]); + * + * The initializer must be an array. + */ +bool Message_InitFromPhp(upb_msg *msg, const upb_msgdef *m, zval *init, + upb_arena *arena) { + HashTable* table = HASH_OF(init); + HashPosition pos; + + if (Z_ISREF_P(init)) { + ZVAL_DEREF(init); + } + + if (Z_TYPE_P(init) != IS_ARRAY) { + zend_throw_exception_ex(NULL, 0, + "Initializer for a message %s must be an array.", + upb_msgdef_fullname(m)); + return false; + } + + zend_hash_internal_pointer_reset_ex(table, &pos); + + while (true) { // Iterate over key/value pairs. + zval key; + zval *val; + const upb_fielddef *f; + upb_msgval msgval; + + zend_hash_get_current_key_zval_ex(table, &key, &pos); + val = zend_hash_get_current_data_ex(table, &pos); + + if (!val) return true; // Finished iteration. + + if (Z_ISREF_P(val)) { + ZVAL_DEREF(val); + } + + f = upb_msgdef_ntof(m, Z_STRVAL_P(&key), Z_STRLEN_P(&key)); + + if (!f) { + zend_throw_exception_ex(NULL, 0, + "No such field %s", Z_STRVAL_P(&key)); + return false; + } + + if (upb_fielddef_ismap(f)) { + msgval.map_val = MapField_GetUpbMap(val, MapType_Get(f), arena); + if (!msgval.map_val) return false; + } else if (upb_fielddef_isseq(f)) { + msgval.array_val = RepeatedField_GetUpbArray(val, TypeInfo_Get(f), arena); + if (!msgval.array_val) return false; + } else { + if (!Convert_PhpToUpbAutoWrap(val, &msgval, TypeInfo_Get(f), arena)) { + return false; + } + } + + upb_msg_set(msg, f, msgval, arena); + zend_hash_move_forward_ex(table, &pos); + zval_dtor(&key); + } } -static HashTable* message_get_properties(zval* object TSRMLS_DC) { - return NULL; +static void Message_Initialize(Message *intern, const Descriptor *desc) { + intern->desc = desc; + intern->msg = upb_msg_new(desc->msgdef, Arena_Get(&intern->arena)); + ObjCache_Add(intern->msg, &intern->std); } -static HashTable* message_get_gc(zval* object, CACHED_VALUE** table, - int* n TSRMLS_DC) { - zend_object* zobj = Z_OBJ_P(object); - *table = zobj->properties_table; - *n = zobj->ce->default_properties_count; - return NULL; +/** + * Message::__construct() + * + * Constructor for Message. + * @param array Map of initial values ['k' = val] + */ +PHP_METHOD(Message, __construct) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const Descriptor* desc; + zend_class_entry *ce = Z_OBJCE_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + zval *init_arr = NULL; + + // This descriptor should always be available, as the generated __construct + // method calls initOnce() to load the descriptor prior to calling us. + // + // However, if the user created their own class derived from Message, this + // will trigger an infinite construction loop and blow the stack. We + // temporarily clear create_object to break this loop (see check in + // NameMap_GetMessage()). + PBPHP_ASSERT(ce->create_object == Message_create); + ce->create_object = NULL; + desc = Descriptor_GetFromClassEntry(ce); + ce->create_object = Message_create; + + if (!desc) { + zend_throw_exception_ex( + NULL, 0, + "Couldn't find descriptor. Note only generated code may derive from " + "\\Google\\Protobuf\\Internal\\Message"); + return; + } + + + Message_Initialize(intern, desc); + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &init_arr) == FAILURE) { + return; + } + + if (init_arr) { + Message_InitFromPhp(intern->msg, desc->msgdef, init_arr, arena); + } } -// ----------------------------------------------------------------------------- -// C Message Utilities -// ----------------------------------------------------------------------------- +/** + * Message::discardUnknownFields() + * + * Discards any unknown fields for this message or any submessages. + */ +PHP_METHOD(Message, discardUnknownFields) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + upb_msg_discardunknown(intern->msg, intern->desc->msgdef, 64); +} -void* message_data(MessageHeader* msg) { - return msg->data; +/** + * Message::clear() + * + * Clears all fields of this message. + */ +PHP_METHOD(Message, clear) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + upb_msg_clear(intern->msg, intern->desc->msgdef); } -void custom_data_init(const zend_class_entry* ce, - MessageHeader* intern PHP_PROTO_TSRMLS_DC) { - Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(ce)); - intern->data = ALLOC_N(uint8_t, desc->layout->size); - memset(message_data(intern), 0, desc->layout->size); - // We wrap first so that everything in the message object is GC-rooted in - // case a collection happens during object creation in layout_init(). - intern->descriptor = desc; - layout_init(desc->layout, message_data(intern), - &intern->std PHP_PROTO_TSRMLS_CC); +/** + * Message::mergeFrom() + * + * Merges from the given message, which must be of the same class as us. + * @param object Message to merge from. + */ +PHP_METHOD(Message, mergeFrom) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + Message* from; + upb_arena *arena = Arena_Get(&intern->arena); + const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef); + zval* value; + char *pb; + size_t size; + bool ok; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &value, + intern->desc->class_entry) == FAILURE) { + return; + } + + from = (Message*)Z_OBJ_P(value); + + // Should be guaranteed since we passed the class type to + // zend_parse_parameters(). + PBPHP_ASSERT(from->desc == intern->desc); + + // TODO(haberman): use a temp arena for this once we can make upb_decode() + // copy strings. + pb = upb_encode(from->msg, l, arena, &size); + + if (!pb) { + zend_throw_exception_ex(NULL, 0, "Max nesting exceeded"); + return; + } + + ok = upb_decode(pb, size, intern->msg, l, arena); + PBPHP_ASSERT(ok); } -void build_class_from_descriptor( - PHP_PROTO_HASHTABLE_VALUE php_descriptor TSRMLS_DC) { - Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, php_descriptor); +/** + * Message::mergeFromString() + * + * Merges from the given string. + * @param string Binary protobuf data to merge. + */ +PHP_METHOD(Message, mergeFromString) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + char *data = NULL; + char *data_copy = NULL; + zend_long data_len; + const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef); + upb_arena *arena = Arena_Get(&intern->arena); - // Map entries don't have existing php class. - if (upb_msgdef_mapentry(desc->msgdef)) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &data, &data_len) == + FAILURE) { return; } - zend_class_entry* registered_ce = desc->klass; + // TODO(haberman): avoid this copy when we can make the decoder copy. + data_copy = upb_arena_malloc(arena, data_len); + memcpy(data_copy, data, data_len); - if (desc->layout == NULL) { - MessageLayout* layout = create_layout(desc->msgdef); - desc->layout = layout; + if (!upb_decode(data_copy, data_len, intern->msg, l, arena)) { + zend_throw_exception_ex(NULL, 0, "Error occurred during parsing"); + return; } +} - registered_ce->create_object = message_create; +/** + * Message::serializeToString() + * + * Serializes this message instance to protobuf data. + * @return string Serialized protobuf data. + */ +PHP_METHOD(Message, serializeToString) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef); + upb_arena *tmp_arena = upb_arena_new(); + char *data; + size_t size; + + data = upb_encode(intern->msg, l, tmp_arena, &size); + + if (!data) { + zend_throw_exception_ex(NULL, 0, "Error occurred during serialization"); + upb_arena_free(tmp_arena); + return; + } + + RETVAL_STRINGL(data, size); + upb_arena_free(tmp_arena); } -// ----------------------------------------------------------------------------- -// PHP Methods -// ----------------------------------------------------------------------------- +/** + * Message::mergeFromJsonString() + * + * Merges the JSON data parsed from the given string. + * @param string Serialized JSON data. + */ +PHP_METHOD(Message, mergeFromJsonString) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + char *data = NULL; + char *data_copy = NULL; + zend_long data_len; + upb_arena *arena = Arena_Get(&intern->arena); + upb_status status; + zend_bool ignore_json_unknown = false; + int options = 0; -// At the first time the message is created, the class entry hasn't been -// modified. As a result, the first created instance will be a normal zend -// object. Here, we manually modify it to our message in such a case. -PHP_METHOD(Message, __construct) { - zend_class_entry* ce = Z_OBJCE_P(getThis()); - if (EXPECTED(class_added(ce))) { - MessageHeader* intern = UNBOX(MessageHeader, getThis()); - custom_data_init(ce, intern PHP_PROTO_TSRMLS_CC); + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &data, &data_len, + &ignore_json_unknown) == FAILURE) { + return; + } + + // TODO(haberman): avoid this copy when we can make the decoder copy. + data_copy = upb_arena_malloc(arena, data_len + 1); + memcpy(data_copy, data, data_len); + data_copy[data_len] = '\0'; + + if (ignore_json_unknown) { + options |= UPB_JSONDEC_IGNOREUNKNOWN; + } + + upb_status_clear(&status); + if (!upb_json_decode(data_copy, data_len, intern->msg, intern->desc->msgdef, + DescriptorPool_GetSymbolTable(), options, arena, + &status)) { + zend_throw_exception_ex(NULL, 0, "Error occurred during parsing: %s", + upb_status_errmsg(&status)); + return; } } -PHP_METHOD(Message, clear) { - MessageHeader* msg = UNBOX(MessageHeader, getThis()); - Descriptor* desc = msg->descriptor; - zend_class_entry* ce = desc->klass; +/** + * Message::serializeToJsonString() + * + * Serializes this object to JSON. + * @return string Serialized JSON data. + */ +PHP_METHOD(Message, serializeToJsonString) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + size_t size; + int options = 0; + char buf[1024]; + zend_bool preserve_proto_fieldnames = false; + upb_status status; - object_properties_init(&msg->std, ce); - layout_init(desc->layout, message_data(msg), &msg->std TSRMLS_CC); + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", + &preserve_proto_fieldnames) == FAILURE) { + return; + } + + if (preserve_proto_fieldnames) { + options |= UPB_JSONENC_PROTONAMES; + } + + upb_status_clear(&status); + size = upb_json_encode(intern->msg, intern->desc->msgdef, + DescriptorPool_GetSymbolTable(), options, buf, + sizeof(buf), &status); + + if (!upb_ok(&status)) { + zend_throw_exception_ex(NULL, 0, + "Error occurred during JSON serialization: %s", + upb_status_errmsg(&status)); + return; + } + + if (size >= sizeof(buf)) { + char *buf2 = malloc(size + 1); + upb_json_encode(intern->msg, intern->desc->msgdef, + DescriptorPool_GetSymbolTable(), options, buf2, size + 1, + &status); + RETVAL_STRINGL(buf2, size); + free(buf2); + } else { + RETVAL_STRINGL(buf, size); + } } -PHP_METHOD(Message, mergeFrom) { - zval* value; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &value, - message_type) == FAILURE) { +/** + * Message::readWrapperValue() + * + * Returns an unboxed value for the given field. This is called from generated + * methods for wrapper fields, eg. + * + * public function getDoubleValueUnwrapped() + * { + * return $this->readWrapperValue("double_value"); + * } + * + * @return Unwrapped field value or null. + */ +PHP_METHOD(Message, readWrapperValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + char* member; + const upb_fielddef *f; + zend_long size; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &member, &size) == FAILURE) { return; } - MessageHeader* from = UNBOX(MessageHeader, value); - MessageHeader* to = UNBOX(MessageHeader, getThis()); + f = upb_msgdef_ntof(intern->desc->msgdef, member, size); - if(from->descriptor != to->descriptor) { - zend_error(E_USER_ERROR, "Cannot merge messages with different class."); + if (!f || !upb_msgdef_iswrapper(upb_fielddef_msgsubdef(f))) { + zend_throw_exception_ex(NULL, 0, "Message %s has no field %s", + upb_msgdef_fullname(intern->desc->msgdef), member); return; } - layout_merge(from->descriptor->layout, from, to TSRMLS_CC); + if (upb_msg_has(intern->msg, f)) { + const upb_msg *wrapper = upb_msg_get(intern->msg, f).msg_val; + const upb_msgdef *m = upb_fielddef_msgsubdef(f); + const upb_fielddef *val_f = upb_msgdef_itof(m, 1); + upb_msgval msgval = upb_msg_get(wrapper, val_f); + zval ret; + Convert_UpbToPhp(msgval, &ret, TypeInfo_Get(val_f), &intern->arena); + RETURN_ZVAL(&ret, 1, 0); + } else { + RETURN_NULL(); + } } -PHP_METHOD(Message, readOneof) { - PHP_PROTO_LONG index; +/** + * Message::writeWrapperValue() + * + * Sets the given wrapper field to the given unboxed value. This is called from + * generated methods for wrapper fields, eg. + * + * + * public function setDoubleValueUnwrapped($var) + * { + * $this->writeWrapperValue("double_value", $var); + * return $this; + * } + * + * @param Unwrapped field value or null. + */ +PHP_METHOD(Message, writeWrapperValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + char* member; + const upb_fielddef *f; + upb_msgval msgval; + zend_long size; + zval* val; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz", &member, &size, &val) == FAILURE) { return; } - MessageHeader* msg = UNBOX(MessageHeader, getThis()); + f = upb_msgdef_ntof(intern->desc->msgdef, member, size); + + if (!f || !upb_msgdef_iswrapper(upb_fielddef_msgsubdef(f))) { + zend_throw_exception_ex(NULL, 0, "Message %s has no field %s", + upb_msgdef_fullname(intern->desc->msgdef), member); + return; + } + + if (Z_ISREF_P(val)) { + ZVAL_DEREF(val); + } + + if (Z_TYPE_P(val) == IS_NULL) { + upb_msg_clearfield(intern->msg, f); + } else { + const upb_msgdef *m = upb_fielddef_msgsubdef(f); + const upb_fielddef *val_f = upb_msgdef_itof(m, 1); + upb_msg *wrapper; - const upb_fielddef* field = upb_msgdef_itof(msg->descriptor->msgdef, index); + if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(val_f), arena)) { + return; // Error is already set. + } - int property_cache_index = - msg->descriptor->layout->fields[upb_fielddef_index(field)].cache_index; - zval* property_ptr = CACHED_PTR_TO_ZVAL_PTR( - OBJ_PROP(Z_OBJ_P(getThis()), property_cache_index)); + wrapper = upb_msg_mutable(intern->msg, f, arena).msg; + upb_msg_set(wrapper, val_f, msgval, arena); + } +} + +/** + * Message::whichOneof() + * + * Given a oneof name, returns the name of the field that is set for this oneof, + * or otherwise the empty string. + * + * @return string The field name in this oneof that is currently set. + */ +PHP_METHOD(Message, whichOneof) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_oneofdef* oneof; + const upb_fielddef* field; + char* name; + zend_long len; - // Unlike singular fields, oneof fields share cached property. So we cannot - // let lay_get modify the cached property. Instead, we pass in the return - // value directly. - layout_get(msg->descriptor->layout, message_data(msg), field, - ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC); + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &len) == FAILURE) { + return; + } + + oneof = upb_msgdef_ntoo(intern->desc->msgdef, name, len); + + if (!oneof) { + zend_throw_exception_ex(NULL, 0, "Message %s has no oneof %s", + upb_msgdef_fullname(intern->desc->msgdef), name); + return; + } + + field = upb_msg_whichoneof(intern->msg, oneof); + RETURN_STRING(field ? upb_fielddef_name(field) : ""); } +/** + * Message::hasOneof() + * + * Returns the presence of the given oneof field, given a field number. Called + * from generated code methods such as: + * + * public function hasDoubleValueOneof() + * { + * return $this->hasOneof(10); + * } + * + * @return boolean + */ +PHP_METHOD(Message, hasOneof) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + zend_long field_num; + const upb_fielddef* f; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &field_num) == FAILURE) { + return; + } + + f = upb_msgdef_itof(intern->desc->msgdef, field_num); + + if (!f || !upb_fielddef_realcontainingoneof(f)) { + php_error_docref(NULL, E_USER_ERROR, + "Internal error, no such oneof field %d\n", + (int)field_num); + } + + RETVAL_BOOL(upb_msg_has(intern->msg, f)); +} + +/** + * Message::readOneof() + * + * Returns the contents of the given oneof field, given a field number. Called + * from generated code methods such as: + * + * public function getDoubleValueOneof() + * { + * return $this->readOneof(10); + * } + * + * @return object The oneof's field value. + */ +PHP_METHOD(Message, readOneof) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + zend_long field_num; + const upb_fielddef* f; + zval ret; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &field_num) == FAILURE) { + return; + } + + f = upb_msgdef_itof(intern->desc->msgdef, field_num); + + if (!f || !upb_fielddef_realcontainingoneof(f)) { + php_error_docref(NULL, E_USER_ERROR, + "Internal error, no such oneof field %d\n", + (int)field_num); + } + + if (upb_fielddef_issubmsg(f) && !upb_msg_has(intern->msg, f)) { + RETURN_NULL(); + } + + { + upb_msgval msgval = upb_msg_get(intern->msg, f); + Convert_UpbToPhp(msgval, &ret, TypeInfo_Get(f), &intern->arena); + } + + RETURN_ZVAL(&ret, 1, 0); +} + +/** + * Message::writeOneof() + * + * Sets the contents of the given oneof field, given a field number. Called + * from generated code methods such as: + * + * public function setDoubleValueOneof($var) + * { + * GPBUtil::checkMessage($var, \Google\Protobuf\DoubleValue::class); + * $this->writeOneof(10, $var); + * + * return $this; + * } + * + * The C extension version of GPBUtil::check*() does nothing, so we perform + * all type checking and conversion here. + * + * @param integer The field number we are setting. + * @param object The field value we want to set. + */ PHP_METHOD(Message, writeOneof) { - PHP_PROTO_LONG index; - zval* value; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &index, &value) == + Message* intern = (Message*)Z_OBJ_P(getThis()); + zend_long field_num; + const upb_fielddef* f; + upb_arena *arena = Arena_Get(&intern->arena); + upb_msgval msgval; + zval* val; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz", &field_num, &val) == FAILURE) { return; } - MessageHeader* msg = UNBOX(MessageHeader, getThis()); + f = upb_msgdef_itof(intern->desc->msgdef, field_num); - const upb_fielddef* field = upb_msgdef_itof(msg->descriptor->msgdef, index); + if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(f), arena)) { + return; + } - layout_set(msg->descriptor->layout, msg, field, value TSRMLS_CC); + upb_msg_set(intern->msg, f, msgval, arena); } -PHP_METHOD(Message, whichOneof) { - char* oneof_name; - PHP_PROTO_SIZE length; +ZEND_BEGIN_ARG_INFO_EX(arginfo_mergeFrom, 0, 0, 1) + ZEND_ARG_INFO(0, data) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_read, 0, 0, 1) + ZEND_ARG_INFO(0, field) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_write, 0, 0, 2) + ZEND_ARG_INFO(0, field) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +static zend_function_entry Message_methods[] = { + PHP_ME(Message, clear, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Message, discardUnknownFields, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Message, serializeToString, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Message, mergeFromString, arginfo_mergeFrom, ZEND_ACC_PUBLIC) + PHP_ME(Message, serializeToJsonString, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Message, mergeFromJsonString, arginfo_mergeFrom, ZEND_ACC_PUBLIC) + PHP_ME(Message, mergeFrom, arginfo_mergeFrom, ZEND_ACC_PUBLIC) + PHP_ME(Message, readWrapperValue, arginfo_read, ZEND_ACC_PROTECTED) + PHP_ME(Message, writeWrapperValue, arginfo_write, ZEND_ACC_PROTECTED) + PHP_ME(Message, hasOneof, arginfo_read, ZEND_ACC_PROTECTED) + PHP_ME(Message, readOneof, arginfo_read, ZEND_ACC_PROTECTED) + PHP_ME(Message, writeOneof, arginfo_write, ZEND_ACC_PROTECTED) + PHP_ME(Message, whichOneof, arginfo_read, ZEND_ACC_PROTECTED) + PHP_ME(Message, __construct, arginfo_void, ZEND_ACC_PROTECTED) + ZEND_FE_END +}; + +// Well-known types //////////////////////////////////////////////////////////// + +static const char TYPE_URL_PREFIX[] = "type.googleapis.com/"; + +static upb_msgval Message_getval(Message *intern, const char *field_name) { + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, field_name); + PBPHP_ASSERT(f); + return upb_msg_get(intern->msg, f); +} + +static void Message_setval(Message *intern, const char *field_name, + upb_msgval val) { + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, field_name); + PBPHP_ASSERT(f); + return upb_msg_set(intern->msg, f, val, Arena_Get(&intern->arena)); +} + +static upb_msgval StringVal(upb_strview view) { + upb_msgval ret; + ret.str_val = view; + return ret; +} - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &oneof_name, - &length) == FAILURE) { +static bool TryStripUrlPrefix(upb_strview *str) { + size_t size = strlen(TYPE_URL_PREFIX); + if (str->size < size || memcmp(TYPE_URL_PREFIX, str->data, size) != 0) { + return false; + } + str->data += size; + str->size -= size; + return true; +} + +static bool StrViewEq(upb_strview view, const char *str) { + size_t size = strlen(str); + return view.size == size && memcmp(view.data, str, size) == 0; +} + +PHP_METHOD(google_protobuf_Any, unpack) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + upb_strview type_url = Message_getval(intern, "type_url").str_val; + upb_strview value = Message_getval(intern, "value").str_val; + upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_msgdef *m; + Descriptor *desc; + zval ret; + + // Ensure that type_url has TYPE_URL_PREFIX as a prefix. + if (!TryStripUrlPrefix(&type_url)) { + zend_throw_exception( + NULL, "Type url needs to be type.googleapis.com/fully-qualified", + 0); + return; + } + + m = upb_symtab_lookupmsg2(symtab, type_url.data, type_url.size); + + if (m == NULL) { + zend_throw_exception( + NULL, "Specified message in any hasn't been added to descriptor pool", + 0); + return; + } + + desc = Descriptor_GetFromMessageDef(m); + PBPHP_ASSERT(desc->class_entry->create_object == Message_create); + zend_object *obj = Message_create(desc->class_entry); + Message *msg = (Message*)obj; + Message_Initialize(msg, desc); + ZVAL_OBJ(&ret, obj); + + // Get value. + if (!upb_decode(value.data, value.size, msg->msg, + upb_msgdef_layout(desc->msgdef), Arena_Get(&msg->arena))) { + zend_throw_exception_ex(NULL, 0, "Error occurred during parsing"); + return; + } + + // Fuse since the parsed message could alias "value". + upb_arena_fuse(Arena_Get(&intern->arena), Arena_Get(&msg->arena)); + + RETURN_ZVAL(&ret, 1, 0); +} + +PHP_METHOD(google_protobuf_Any, pack) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + zval *val; + Message *msg; + upb_strview value; + upb_strview type_url; + const char *full_name; + char *buf; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &val) == + FAILURE) { + return; + } + + if (!instanceof_function(Z_OBJCE_P(val), message_ce)) { + zend_error(E_USER_ERROR, "Given value is not an instance of Message."); + return; + } + + msg = (Message*)Z_OBJ_P(val); + + // Serialize and set value. + value.data = upb_encode(msg->msg, upb_msgdef_layout(msg->desc->msgdef), arena, + &value.size); + Message_setval(intern, "value", StringVal(value)); + + // Set type url: type_url_prefix + fully_qualified_name + full_name = upb_msgdef_fullname(msg->desc->msgdef); + type_url.size = strlen(TYPE_URL_PREFIX) + strlen(full_name); + buf = upb_arena_malloc(arena, type_url.size + 1); + memcpy(buf, TYPE_URL_PREFIX, strlen(TYPE_URL_PREFIX)); + memcpy(buf + strlen(TYPE_URL_PREFIX), full_name, strlen(full_name)); + type_url.data = buf; + Message_setval(intern, "type_url", StringVal(type_url)); +} + +PHP_METHOD(google_protobuf_Any, is) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + upb_strview type_url = Message_getval(intern, "type_url").str_val; + zend_class_entry *klass = NULL; + const upb_msgdef *m; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "C", &klass) == + FAILURE) { + return; + } + + m = NameMap_GetMessage(klass); + + if (m == NULL) { + RETURN_BOOL(false); + } + + RETURN_BOOL(TryStripUrlPrefix(&type_url) && + StrViewEq(type_url, upb_msgdef_fullname(m))); +} + +PHP_METHOD(google_protobuf_Timestamp, fromDateTime) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + zval* datetime; + const char *classname = "\\DatetimeInterface"; + zend_string *classname_str = zend_string_init(classname, strlen(classname), 0); + zend_class_entry *date_interface_ce = zend_lookup_class(classname_str); + + if (date_interface_ce == NULL) { + zend_error(E_ERROR, "Make sure date extension is enabled."); + return; + } + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &datetime, + date_interface_ce) == FAILURE) { + zend_error(E_USER_ERROR, "Expect DatetimeInterface."); return; } - MessageHeader* msg = UNBOX(MessageHeader, getThis()); + upb_msgval timestamp_seconds; + { + zval retval; + zval function_name; + + ZVAL_STRING(&function_name, "date_timestamp_get"); + + if (call_user_function(EG(function_table), NULL, &function_name, &retval, 1, + datetime) == FAILURE || + !Convert_PhpToUpb(&retval, ×tamp_seconds, + TypeInfo_FromType(UPB_TYPE_INT64), NULL)) { + zend_error(E_ERROR, "Cannot get timestamp from DateTime."); + return; + } + + zval_dtor(&retval); + zval_dtor(&function_name); + } + + upb_msgval timestamp_nanos; + { + zval retval; + zval function_name; + zval format_string; + + ZVAL_STRING(&function_name, "date_format"); + ZVAL_STRING(&format_string, "u"); + + zval params[2] = { + *datetime, + format_string, + }; + + if (call_user_function(EG(function_table), NULL, &function_name, &retval, 2, + params) == FAILURE || + !Convert_PhpToUpb(&retval, ×tamp_nanos, + TypeInfo_FromType(UPB_TYPE_INT32), NULL)) { + zend_error(E_ERROR, "Cannot format DateTime."); + return; + } + + timestamp_nanos.int32_val *= 1000; + + zval_dtor(&retval); + zval_dtor(&function_name); + zval_dtor(&format_string); + } + + Message_setval(intern, "seconds", timestamp_seconds); + Message_setval(intern, "nanos", timestamp_nanos); + + RETURN_NULL(); +} + +PHP_METHOD(google_protobuf_Timestamp, toDateTime) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + upb_msgval seconds = Message_getval(intern, "seconds"); + upb_msgval nanos = Message_getval(intern, "nanos"); + + // Get formatted time string. + char formatted_time[32]; + snprintf(formatted_time, sizeof(formatted_time), "%" PRId64 ".%06" PRId32, + seconds.int64_val, nanos.int32_val / 1000); + + // Create Datetime object. + zval datetime; + zval function_name; + zval format_string; + zval formatted_time_php; + + ZVAL_STRING(&function_name, "date_create_from_format"); + ZVAL_STRING(&format_string, "U.u"); + ZVAL_STRING(&formatted_time_php, formatted_time); + + zval params[2] = { + format_string, + formatted_time_php, + }; + + if (call_user_function(EG(function_table), NULL, &function_name, &datetime, 2, + params) == FAILURE) { + zend_error(E_ERROR, "Cannot create DateTime."); + return; + } + + zval_dtor(&function_name); + zval_dtor(&format_string); + zval_dtor(&formatted_time_php); + + ZVAL_OBJ(return_value, Z_OBJ(datetime)); +} + +#include "wkt.inc" + +/** + * Message_ModuleInit() + * + * Called when the C extension is loaded to register all types. + */ +void Message_ModuleInit() { + zend_class_entry tmp_ce; + zend_object_handlers *h = &message_object_handlers; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\Message", + Message_methods); + + message_ce = zend_register_internal_class(&tmp_ce); + message_ce->create_object = Message_create; + + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + h->dtor_obj = Message_dtor; +#if PHP_VERSION_ID < 80000 + h->compare_objects = Message_compare_objects; +#else + h->compare = Message_compare_objects; +#endif + h->read_property = Message_read_property; + h->write_property = Message_write_property; + h->has_property = Message_has_property; + h->unset_property = Message_unset_property; + h->get_properties = Message_get_properties; + h->get_property_ptr_ptr = Message_get_property_ptr_ptr; + h->clone_obj = Message_clone_obj; - const upb_oneofdef* oneof = - upb_msgdef_ntoo(msg->descriptor->msgdef, oneof_name, length); - const char* oneof_case_name = layout_get_oneof_case( - msg->descriptor->layout, message_data(msg), oneof TSRMLS_CC); - PHP_PROTO_RETURN_STRING(oneof_case_name, 1); + WellKnownTypes_ModuleInit(); /* From wkt.inc. */ } diff --git a/php/ext/google/protobuf/message.h b/php/ext/google/protobuf/message.h new file mode 100644 index 0000000000000..5b49e0db84dba --- /dev/null +++ b/php/ext/google/protobuf/message.h @@ -0,0 +1,61 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef PHP_PROTOBUF_MESSAGE_H_ +#define PHP_PROTOBUF_MESSAGE_H_ + +#include + +#include "def.h" + +// Registers the PHP Message class. +void Message_ModuleInit(); + +// Gets a upb_msg* for the PHP object |val|, which must either be a Message +// object or 'null'. Returns true and stores the message in |msg| if the +// conversion succeeded (we can't return upb_msg* because null->NULL is a valid +// conversion). Returns false and raises a PHP error if this isn't a Message +// object or null, or if the Message object doesn't match this Descriptor. +// +// The given |arena| will be fused to this message's arena. +bool Message_GetUpbMessage(zval *val, const Descriptor *desc, upb_arena *arena, + upb_msg **msg); + +// Gets or creates a PHP Message object to wrap the given upb_msg* and |desc| +// and returns it in |val|. The PHP object will keep a reference to this |arena| +// to ensure the underlying message data stays alive. +// +// If |msg| is NULL, this will return a PHP null. +void Message_GetPhpWrapper(zval *val, const Descriptor *desc, upb_msg *msg, + zval *arena); + +bool ValueEq(upb_msgval val1, upb_msgval val2, TypeInfo type); + +#endif // PHP_PROTOBUF_MESSAGE_H_ diff --git a/php/ext/google/protobuf/names.c b/php/ext/google/protobuf/names.c new file mode 100644 index 0000000000000..ff04b3cbc35b0 --- /dev/null +++ b/php/ext/google/protobuf/names.c @@ -0,0 +1,226 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "names.h" + +#include + +#include "protobuf.h" + +/* stringsink *****************************************************************/ + +typedef struct { + char *ptr; + size_t len, size; +} stringsink; + +static size_t stringsink_string(stringsink *sink, const char *ptr, size_t len) { + size_t new_size = sink->size; + + while (sink->len + len > new_size) { + new_size *= 2; + } + + if (new_size != sink->size) { + sink->ptr = realloc(sink->ptr, new_size); + sink->size = new_size; + } + + memcpy(sink->ptr + sink->len, ptr, len); + sink->len += len; + + return len; +} + +static void stringsink_init(stringsink *sink) { + sink->size = 32; + sink->ptr = malloc(sink->size); + PBPHP_ASSERT(sink->ptr != NULL); + sink->len = 0; +} + +static void stringsink_uninit(stringsink *sink) { free(sink->ptr); } + +/* def name -> classname ******************************************************/ + +const char *const kReservedNames[] = { + "abstract", "and", "array", "as", "break", + "callable", "case", "catch", "class", "clone", + "const", "continue", "declare", "default", "die", + "do", "echo", "else", "elseif", "empty", + "enddeclare", "endfor", "endforeach", "endif", "endswitch", + "endwhile", "eval", "exit", "extends", "final", + "for", "foreach", "function", "global", "goto", + "if", "implements", "include", "include_once", "instanceof", + "insteadof", "interface", "isset", "list", "namespace", + "new", "or", "print", "private", "protected", + "public", "require", "require_once", "return", "static", + "switch", "throw", "trait", "try", "unset", + "use", "var", "while", "xor", "int", + "float", "bool", "string", "true", "false", + "null", "void", "iterable", NULL}; + +bool is_reserved_name(const char* name) { + int i; + for (i = 0; kReservedNames[i]; i++) { + if (strcmp(kReservedNames[i], name) == 0) { + return true; + } + } + return false; +} + +static char nolocale_tolower(char ch) { + if (ch >= 'A' && ch <= 'Z') { + return ch - ('A' - 'a'); + } else { + return ch; + } +} + +static char nolocale_toupper(char ch) { + if (ch >= 'a' && ch <= 'z') { + return ch - ('a' - 'A'); + } else { + return ch; + } +} + +static bool is_reserved(const char *segment, int length) { + bool result; + char* lower = calloc(1, length + 1); + memcpy(lower, segment, length); + int i = 0; + while(lower[i]) { + lower[i] = nolocale_tolower(lower[i]); + i++; + } + lower[length] = 0; + result = is_reserved_name(lower); + free(lower); + return result; +} + +static void fill_prefix(const char *segment, int length, + const char *prefix_given, + const char *package_name, + stringsink *classname) { + if (prefix_given != NULL && strcmp(prefix_given, "") != 0) { + stringsink_string(classname, prefix_given, strlen(prefix_given)); + } else { + if (is_reserved(segment, length)) { + if (package_name != NULL && + strcmp("google.protobuf", package_name) == 0) { + stringsink_string(classname, "GPB", 3); + } else { + stringsink_string(classname, "PB", 2); + } + } + } +} + +static void fill_segment(const char *segment, int length, + stringsink *classname, bool use_camel) { + if (use_camel && (segment[0] < 'A' || segment[0] > 'Z')) { + char first = nolocale_toupper(segment[0]); + stringsink_string(classname, &first, 1); + stringsink_string(classname, segment + 1, length - 1); + } else { + stringsink_string(classname, segment, length); + } +} + +static void fill_namespace(const char *package, const char *php_namespace, + stringsink *classname) { + if (php_namespace != NULL) { + if (strlen(php_namespace) != 0) { + stringsink_string(classname, php_namespace, strlen(php_namespace)); + stringsink_string(classname, "\\", 1); + } + } else if (package != NULL) { + int i = 0, j = 0; + size_t package_len = strlen(package); + while (i < package_len) { + j = i; + while (j < package_len && package[j] != '.') { + j++; + } + fill_prefix(package + i, j - i, "", package, classname); + fill_segment(package + i, j - i, classname, true); + stringsink_string(classname, "\\", 1); + i = j + 1; + } + } +} + +static void fill_classname(const char *fullname, + const char *package, + const char *prefix, + stringsink *classname) { + int classname_start = 0; + if (package != NULL) { + size_t package_len = strlen(package); + classname_start = package_len == 0 ? 0 : package_len + 1; + } + size_t fullname_len = strlen(fullname); + + int i = classname_start, j; + while (i < fullname_len) { + j = i; + while (j < fullname_len && fullname[j] != '.') { + j++; + } + fill_prefix(fullname + i, j - i, prefix, package, classname); + fill_segment(fullname + i, j - i, classname, false); + if (j != fullname_len) { + stringsink_string(classname, "\\", 1); + } + i = j + 1; + } +} + +char *GetPhpClassname(const upb_filedef *file, const char *fullname) { + // Prepend '.' to package name to make it absolute. In the 5 additional + // bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if + // given message is google.protobuf.Empty. + const char *package = upb_filedef_package(file); + const char *php_namespace = upb_filedef_phpnamespace(file); + const char *prefix = upb_filedef_phpprefix(file); + char *ret; + stringsink namesink; + stringsink_init(&namesink); + + fill_namespace(package, php_namespace, &namesink); + fill_classname(fullname, package, prefix, &namesink); + stringsink_string(&namesink, "\0", 1); + ret = strdup(namesink.ptr); + stringsink_uninit(&namesink); + return ret; +} diff --git a/php/ext/google/protobuf/names.h b/php/ext/google/protobuf/names.h new file mode 100644 index 0000000000000..75101c5a78c39 --- /dev/null +++ b/php/ext/google/protobuf/names.h @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef PHP_PROTOBUF_NAMES_H_ +#define PHP_PROTOBUF_NAMES_H_ + +#include "php-upb.h" + +// Translates a protobuf symbol name (eg. foo.bar.Baz) into a PHP class name +// (eg. \Foo\Bar\Baz). +char *GetPhpClassname(const upb_filedef *file, const char *fullname); + +#endif // PHP_PROTOBUF_NAMES_H_ diff --git a/php/ext/google/protobuf/package.xml b/php/ext/google/protobuf/package.xml index 20a45bc63ca39..805c071f752c3 100644 --- a/php/ext/google/protobuf/package.xml +++ b/php/ext/google/protobuf/package.xml @@ -10,11 +10,11 @@ protobuf-opensource@google.com yes - 2017-01-13 - + 2021-02-18 + - 3.3.2 - 3.3.0 + 3.15.0 + 3.15.0 stable @@ -22,31 +22,47 @@ 3-Clause BSD License -GA release. + New changes in 3.15.0: + * unregister INI entries and fix invalid read on shutdown (#8042) + * Fix PhpDoc comments for message accessors to include "|null". (#8136) + * fix: convert native PHP floats to single precision (#8187) + * Fixed PHP to support field numbers >=2**28. (#8235) + * feat: add support for deprecated fields to PHP compiler (#8223) + * Protect against stack overflow if the user derives from Message. (#8248) + * Fixed clone for Message, RepeatedField, and MapField. (#8245) + * Updated upb to allow nonzero offset minutes in JSON timestamps. (#8258)

- - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - 5.5.9 + 7.0.0 1.4.0 @@ -54,7 +70,7 @@ GA release. protobuf - + @@ -136,5 +152,658 @@ GA release. GA release. + + + 3.4.0 + 3.4.0 + + + stable + stable + + 2017-08-16 + + 3-Clause BSD License + +GA release. + + + + + 3.4.1 + 3.4.1 + + + stable + stable + + 2017-09-14 + + 3-Clause BSD License + +GA release. + + + + + 3.5.0 + 3.5.0 + + + stable + stable + + 2017-11-15 + + 3-Clause BSD License + +GA release. + + + + + 3.5.0.1 + 3.5.0.1 + + + stable + stable + + 2017-12-06 + + 3-Clause BSD License + +GA release. + + + + + 3.5.1 + 3.5.1 + + + stable + stable + + 2017-12-11 + + 3-Clause BSD License + +GA release. + + + + + 3.5.2 + 3.5.2 + + + stable + stable + + 2018-03-06 + + 3-Clause BSD License + +G A release. + + + + + 3.6.0 + 3.6.0 + + + stable + stable + + 2018-06-06 + + 3-Clause BSD License + +G A release. + + + + + 3.6.1 + 3.6.1 + + + stable + stable + + 2018-08-03 + + 3-Clause BSD License + +G A release. + + + + + 3.7.0RC2 + 3.7.0 + + + stable + stable + + 2019-02-1 + + 3-Clause BSD License + GA release. + + + + 3.7.0RC3 + 3.7.0 + + + beta + beta + + 2019-02-22 + + 3-Clause BSD License + GA release. + + + + 3.7.0 + 3.7.0 + + + stable + stable + + 2019-02-28 + + 3-Clause BSD License + GA release. + + + + 3.7.1 + 3.7.1 + + + stable + stable + + 2019-03-25 + + 3-Clause BSD License + GA release. + + + + 3.8.0RC1 + 3.8.0 + + + beta + beta + + 2019-04-23 + + 3-Clause BSD License + GA release. + + + + 3.8.0 + 3.8.0 + + + stable + stable + + 2019-05-21 + + 3-Clause BSD License + GA release. + + + + 3.9.0RC1 + 3.9.0 + + + beta + beta + + 2019-06-17 + + 3-Clause BSD License + GA release. + + + + 3.9.0 + 3.9.0 + + + stable + stable + + 2019-07-10 + + 3-Clause BSD License + GA release. + + + + 3.9.1 + 3.9.1 + + + stable + stable + + 2019-08-02 + + 3-Clause BSD License + GA release. + + + + 3.10.0RC1 + 3.10.0 + + + beta + beta + + 2019-09-04 + + 3-Clause BSD License + GA release. + + + + 3.10.0RC1 + 3.10.0 + + + beta + beta + + 2019-09-05 + + 3-Clause BSD License + GA release. + + + + 3.10.0 + 3.10.0 + + + stable + stable + + 2019-09-12 + + 3-Clause BSD License + GA release. + + + + 3.11.0RC1 + 3.11.0 + + + beta + beta + + 2019-11-15 + + 3-Clause BSD License + GA release. + + + + 3.11.0RC2 + 3.11.0 + + + beta + beta + + 2019-11-21 + + 3-Clause BSD License + GA release. + + + + 3.11.0 + 3.11.0 + + + stable + stable + + 2019-11-25 + + 3-Clause BSD License + GA release. + + + + 3.11.1 + 3.11.1 + + + stable + stable + + 2019-12-02 + + 3-Clause BSD License + GA release. + + + + 3.11.2 + 3.11.2 + + + stable + stable + + 2019-12-10 + + 3-Clause BSD License + GA release. + + + + 3.11.3 + 3.11.3 + + + stable + stable + + 2020-01-28 + + 3-Clause BSD License + GA release. + + + + 3.11.4 + 3.11.4 + + + stable + stable + + 2020-02-12 + + 3-Clause BSD License + GA release. + + + + 3.12.0RC1 + 3.12.0 + + + beta + beta + + 2020-04-30 + + 3-Clause BSD License + GA release. + + + + 3.12.0RC2 + 3.12.0 + + + beta + beta + + 2020-05-12 + + 3-Clause BSD License + GA release. + + + + 3.12.0 + 3.12.0 + + + stable + stable + + 2020-05-15 + + 3-Clause BSD License + GA release. + + + + 3.12.1 + 3.12.1 + + + stable + stable + + 2020-05-20 + + 3-Clause BSD License + GA release. + + + + 3.12.2 + 3.12.2 + + + stable + stable + + 2020-05-26 + + 3-Clause BSD License + GA release. + + + + 3.12.3 + 3.12.3 + + + stable + stable + + 2020-06-01 + + 3-Clause BSD License + GA release. + + + + 3.13.0RC1 + 3.13.0 + + + beta + beta + + 2020-08-05 + + 3-Clause BSD License + GA release. + + + + 3.13.0RC2 + 3.13.0 + + + beta + beta + + 2020-08-05 + + 3-Clause BSD License + GA release. + + + + 3.13.0RC3 + 3.13.0 + + + beta + beta + + 2020-08-12 + + 3-Clause BSD License + GA release. + + + + 3.13.0 + 3.13.0 + + + stable + stable + + 2020-08-14 + + 3-Clause BSD License + GA release. + + + + 3.13.0.1 + 3.13.0.1 + + + stable + stable + + 2020-10-08 + + 3-Clause BSD License + GA release. + + + + 3.14.0RC1 + 3.14.0 + + + beta + beta + + 2020-11-05 + + 3-Clause BSD License + + + + + + 3.14.0RC2 + 3.14.0 + + + beta + beta + + 2020-11-10 + + 3-Clause BSD License + + + + + + 3.14.0RC3 + 3.14.0 + + + beta + beta + + 2020-11-11 + + 3-Clause BSD License + + + + + + 3.14.0 + 3.14.0 + + + stable + stable + + 2020-11-12 + + 3-Clause BSD License + + + + + + 3.15.0RC1 + 3.15.0 + + + beta + beta + + 2021-02-05 + + 3-Clause BSD License + + + + + + 3.15.0RC2 + 3.15.0 + + + beta + beta + + 2021-02-17 + + 3-Clause BSD License + + + + + + 3.15.0 + 3.15.0 + + + stable + stable + + 2021-02-18 + + 3-Clause BSD License + + + diff --git a/php/ext/google/protobuf/php-upb.c b/php/ext/google/protobuf/php-upb.c new file mode 100644 index 0000000000000..c56a567ca38a3 --- /dev/null +++ b/php/ext/google/protobuf/php-upb.c @@ -0,0 +1,9299 @@ +/* Amalgamated source file */ +#include "php-upb.h" +/* +* This is where we define macros used across upb. +* +* All of these macros are undef'd in port_undef.inc to avoid leaking them to +* users. +* +* The correct usage is: +* +* #include "upb/foobar.h" +* #include "upb/baz.h" +* +* // MUST be last included header. +* #include "upb/port_def.inc" +* +* // Code for this file. +* // <...> +* +* // Can be omitted for .c files, required for .h. +* #include "upb/port_undef.inc" +* +* This file is private and must not be included by users! +*/ + +#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) || \ + (defined(_MSC_VER) && _MSC_VER >= 1900)) +#error upb requires C99 or C++11 or MSVC >= 2015. +#endif + +#include +#include + +#if UINTPTR_MAX == 0xffffffff +#define UPB_SIZE(size32, size64) size32 +#else +#define UPB_SIZE(size32, size64) size64 +#endif + +/* If we always read/write as a consistent type to each address, this shouldn't + * violate aliasing. + */ +#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs))) + +#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \ + *UPB_PTR_AT(msg, case_offset, int) == case_val \ + ? *UPB_PTR_AT(msg, offset, fieldtype) \ + : default + +#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \ + *UPB_PTR_AT(msg, case_offset, int) = case_val; \ + *UPB_PTR_AT(msg, offset, fieldtype) = value; + +#define UPB_MAPTYPE_STRING 0 + +/* UPB_INLINE: inline if possible, emit standalone code if required. */ +#ifdef __cplusplus +#define UPB_INLINE inline +#elif defined (__GNUC__) || defined(__clang__) +#define UPB_INLINE static __inline__ +#else +#define UPB_INLINE static +#endif + +#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align)) +#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align)) +#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16) +#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member) + +/* Hints to the compiler about likely/unlikely branches. */ +#if defined (__GNUC__) || defined(__clang__) +#define UPB_LIKELY(x) __builtin_expect((x),1) +#define UPB_UNLIKELY(x) __builtin_expect((x),0) +#else +#define UPB_LIKELY(x) (x) +#define UPB_UNLIKELY(x) (x) +#endif + +/* Macros for function attributes on compilers that support them. */ +#ifdef __GNUC__ +#define UPB_FORCEINLINE __inline__ __attribute__((always_inline)) +#define UPB_NOINLINE __attribute__((noinline)) +#define UPB_NORETURN __attribute__((__noreturn__)) +#define UPB_PRINTF(str, first_vararg) __attribute__((format (printf, str, first_vararg))) +#elif defined(_MSC_VER) +#define UPB_NOINLINE +#define UPB_FORCEINLINE +#define UPB_NORETURN __declspec(noreturn) +#define UPB_PRINTF(str, first_vararg) +#else /* !defined(__GNUC__) */ +#define UPB_FORCEINLINE +#define UPB_NOINLINE +#define UPB_NORETURN +#define UPB_PRINTF(str, first_vararg) +#endif + +#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) +#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y)) + +#define UPB_UNUSED(var) (void)var + +/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true. + */ +#ifdef NDEBUG +#ifdef __GNUC__ +#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable() +#elif defined _MSC_VER +#define UPB_ASSUME(expr) if (!(expr)) __assume(0) +#else +#define UPB_ASSUME(expr) do {} while (false && (expr)) +#endif +#else +#define UPB_ASSUME(expr) assert(expr) +#endif + +/* UPB_ASSERT(): in release mode, we use the expression without letting it be + * evaluated. This prevents "unused variable" warnings. */ +#ifdef NDEBUG +#define UPB_ASSERT(expr) do {} while (false && (expr)) +#else +#define UPB_ASSERT(expr) assert(expr) +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0) +#else +#define UPB_UNREACHABLE() do { assert(0); } while(0) +#endif + +/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */ +#ifdef __APPLE__ +#define UPB_SETJMP(buf) _setjmp(buf) +#define UPB_LONGJMP(buf, val) _longjmp(buf, val) +#else +#define UPB_SETJMP(buf) setjmp(buf) +#define UPB_LONGJMP(buf, val) longjmp(buf, val) +#endif + +/* Configure whether fasttable is switched on or not. *************************/ + +#if defined(__x86_64__) && defined(__GNUC__) +#define UPB_FASTTABLE_SUPPORTED 1 +#else +#define UPB_FASTTABLE_SUPPORTED 0 +#endif + +/* define UPB_ENABLE_FASTTABLE to force fast table support. + * This is useful when we want to ensure we are really getting fasttable, + * for example for testing or benchmarking. */ +#if defined(UPB_ENABLE_FASTTABLE) +#if !UPB_FASTTABLE_SUPPORTED +#error fasttable is x86-64 + Clang/GCC only +#endif +#define UPB_FASTTABLE 1 +/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible. + * This is useful for releasing code that might be used on multiple platforms, + * for example the PHP or Ruby C extensions. */ +#elif defined(UPB_TRY_ENABLE_FASTTABLE) +#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED +#else +#define UPB_FASTTABLE 0 +#endif + +/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully + * degrade to non-fasttable if we are using UPB_TRY_ENABLE_FASTTABLE. */ +#if !UPB_FASTTABLE && defined(UPB_TRY_ENABLE_FASTTABLE) +#define UPB_FASTTABLE_INIT(...) +#else +#define UPB_FASTTABLE_INIT(...) __VA_ARGS__ +#endif + +#undef UPB_FASTTABLE_SUPPORTED + +/* ASAN poisoning (for arena) *************************************************/ + +#if defined(__SANITIZE_ADDRESS__) +#define UPB_ASAN 1 +#ifdef __cplusplus +extern "C" { +#endif +void __asan_poison_memory_region(void const volatile *addr, size_t size); +void __asan_unpoison_memory_region(void const volatile *addr, size_t size); +#ifdef __cplusplus +} /* extern "C" */ +#endif +#define UPB_POISON_MEMORY_REGION(addr, size) \ + __asan_poison_memory_region((addr), (size)) +#define UPB_UNPOISON_MEMORY_REGION(addr, size) \ + __asan_unpoison_memory_region((addr), (size)) +#else +#define UPB_ASAN 0 +#define UPB_POISON_MEMORY_REGION(addr, size) \ + ((void)(addr), (void)(size)) +#define UPB_UNPOISON_MEMORY_REGION(addr, size) \ + ((void)(addr), (void)(size)) +#endif + + +#include +#include + + +/* Must be last. */ + +/* Maps descriptor type -> elem_size_lg2. */ +static const uint8_t desctype_to_elem_size_lg2[] = { + -1, /* invalid descriptor type */ + 3, /* DOUBLE */ + 2, /* FLOAT */ + 3, /* INT64 */ + 3, /* UINT64 */ + 2, /* INT32 */ + 3, /* FIXED64 */ + 2, /* FIXED32 */ + 0, /* BOOL */ + UPB_SIZE(3, 4), /* STRING */ + UPB_SIZE(2, 3), /* GROUP */ + UPB_SIZE(2, 3), /* MESSAGE */ + UPB_SIZE(3, 4), /* BYTES */ + 2, /* UINT32 */ + 2, /* ENUM */ + 2, /* SFIXED32 */ + 3, /* SFIXED64 */ + 2, /* SINT32 */ + 3, /* SINT64 */ +}; + +/* Maps descriptor type -> upb map size. */ +static const uint8_t desctype_to_mapsize[] = { + -1, /* invalid descriptor type */ + 8, /* DOUBLE */ + 4, /* FLOAT */ + 8, /* INT64 */ + 8, /* UINT64 */ + 4, /* INT32 */ + 8, /* FIXED64 */ + 4, /* FIXED32 */ + 1, /* BOOL */ + UPB_MAPTYPE_STRING, /* STRING */ + sizeof(void *), /* GROUP */ + sizeof(void *), /* MESSAGE */ + UPB_MAPTYPE_STRING, /* BYTES */ + 4, /* UINT32 */ + 4, /* ENUM */ + 4, /* SFIXED32 */ + 8, /* SFIXED64 */ + 4, /* SINT32 */ + 8, /* SINT64 */ +}; + +static const unsigned fixed32_ok = (1 << UPB_DTYPE_FLOAT) | + (1 << UPB_DTYPE_FIXED32) | + (1 << UPB_DTYPE_SFIXED32); + +static const unsigned fixed64_ok = (1 << UPB_DTYPE_DOUBLE) | + (1 << UPB_DTYPE_FIXED64) | + (1 << UPB_DTYPE_SFIXED64); + +/* Op: an action to be performed for a wire-type/field-type combination. */ +#define OP_SCALAR_LG2(n) (n) /* n in [0, 2, 3] => op in [0, 2, 3] */ +#define OP_STRING 4 +#define OP_BYTES 5 +#define OP_SUBMSG 6 +/* Ops above are scalar-only. Repeated fields can use any op. */ +#define OP_FIXPCK_LG2(n) (n + 5) /* n in [2, 3] => op in [7, 8] */ +#define OP_VARPCK_LG2(n) (n + 9) /* n in [0, 2, 3] => op in [9, 11, 12] */ + +static const int8_t varint_ops[19] = { + -1, /* field not found */ + -1, /* DOUBLE */ + -1, /* FLOAT */ + OP_SCALAR_LG2(3), /* INT64 */ + OP_SCALAR_LG2(3), /* UINT64 */ + OP_SCALAR_LG2(2), /* INT32 */ + -1, /* FIXED64 */ + -1, /* FIXED32 */ + OP_SCALAR_LG2(0), /* BOOL */ + -1, /* STRING */ + -1, /* GROUP */ + -1, /* MESSAGE */ + -1, /* BYTES */ + OP_SCALAR_LG2(2), /* UINT32 */ + OP_SCALAR_LG2(2), /* ENUM */ + -1, /* SFIXED32 */ + -1, /* SFIXED64 */ + OP_SCALAR_LG2(2), /* SINT32 */ + OP_SCALAR_LG2(3), /* SINT64 */ +}; + +static const int8_t delim_ops[37] = { + /* For non-repeated field type. */ + -1, /* field not found */ + -1, /* DOUBLE */ + -1, /* FLOAT */ + -1, /* INT64 */ + -1, /* UINT64 */ + -1, /* INT32 */ + -1, /* FIXED64 */ + -1, /* FIXED32 */ + -1, /* BOOL */ + OP_STRING, /* STRING */ + -1, /* GROUP */ + OP_SUBMSG, /* MESSAGE */ + OP_BYTES, /* BYTES */ + -1, /* UINT32 */ + -1, /* ENUM */ + -1, /* SFIXED32 */ + -1, /* SFIXED64 */ + -1, /* SINT32 */ + -1, /* SINT64 */ + /* For repeated field type. */ + OP_FIXPCK_LG2(3), /* REPEATED DOUBLE */ + OP_FIXPCK_LG2(2), /* REPEATED FLOAT */ + OP_VARPCK_LG2(3), /* REPEATED INT64 */ + OP_VARPCK_LG2(3), /* REPEATED UINT64 */ + OP_VARPCK_LG2(2), /* REPEATED INT32 */ + OP_FIXPCK_LG2(3), /* REPEATED FIXED64 */ + OP_FIXPCK_LG2(2), /* REPEATED FIXED32 */ + OP_VARPCK_LG2(0), /* REPEATED BOOL */ + OP_STRING, /* REPEATED STRING */ + OP_SUBMSG, /* REPEATED GROUP */ + OP_SUBMSG, /* REPEATED MESSAGE */ + OP_BYTES, /* REPEATED BYTES */ + OP_VARPCK_LG2(2), /* REPEATED UINT32 */ + OP_VARPCK_LG2(2), /* REPEATED ENUM */ + OP_FIXPCK_LG2(2), /* REPEATED SFIXED32 */ + OP_FIXPCK_LG2(3), /* REPEATED SFIXED64 */ + OP_VARPCK_LG2(2), /* REPEATED SINT32 */ + OP_VARPCK_LG2(3), /* REPEATED SINT64 */ +}; + +typedef union { + bool bool_val; + uint32_t uint32_val; + uint64_t uint64_val; + uint32_t size; +} wireval; + +static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *layout); + +UPB_NORETURN static void decode_err(upb_decstate *d) { UPB_LONGJMP(d->err, 1); } + +// We don't want to mark this NORETURN, see comment in .h. +// Unfortunately this code to suppress the warning doesn't appear to be working. +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma clang diagnostic ignored "-Wsuggest-attribute" +#endif + +const char *fastdecode_err(upb_decstate *d) { + longjmp(d->err, 1); + return NULL; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +const uint8_t upb_utf8_offsets[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static void decode_verifyutf8(upb_decstate *d, const char *buf, int len) { + if (!decode_verifyutf8_inl(buf, len)) decode_err(d); +} + +static bool decode_reserve(upb_decstate *d, upb_array *arr, size_t elem) { + bool need_realloc = arr->size - arr->len < elem; + if (need_realloc && !_upb_array_realloc(arr, arr->len + elem, &d->arena)) { + decode_err(d); + } + return need_realloc; +} + +typedef struct { + const char *ptr; + uint64_t val; +} decode_vret; + +UPB_NOINLINE +static decode_vret decode_longvarint64(const char *ptr, uint64_t val) { + decode_vret ret = {NULL, 0}; + uint64_t byte; + int i; + for (i = 1; i < 10; i++) { + byte = (uint8_t)ptr[i]; + val += (byte - 1) << (i * 7); + if (!(byte & 0x80)) { + ret.ptr = ptr + i + 1; + ret.val = val; + return ret; + } + } + return ret; +} + +UPB_FORCEINLINE +static const char *decode_varint64(upb_decstate *d, const char *ptr, + uint64_t *val) { + uint64_t byte = (uint8_t)*ptr; + if (UPB_LIKELY((byte & 0x80) == 0)) { + *val = byte; + return ptr + 1; + } else { + decode_vret res = decode_longvarint64(ptr, byte); + if (!res.ptr) decode_err(d); + *val = res.val; + return res.ptr; + } +} + +UPB_FORCEINLINE +static const char *decode_tag(upb_decstate *d, const char *ptr, + uint32_t *val) { + uint64_t byte = (uint8_t)*ptr; + if (UPB_LIKELY((byte & 0x80) == 0)) { + *val = byte; + return ptr + 1; + } else { + const char *start = ptr; + decode_vret res = decode_longvarint64(ptr, byte); + ptr = res.ptr; + *val = res.val; + if (!ptr || *val > UINT32_MAX || ptr - start > 5) decode_err(d); + return ptr; + } +} + +static void decode_munge(int type, wireval *val) { + switch (type) { + case UPB_DESCRIPTOR_TYPE_BOOL: + val->bool_val = val->uint64_val != 0; + break; + case UPB_DESCRIPTOR_TYPE_SINT32: { + uint32_t n = val->uint32_val; + val->uint32_val = (n >> 1) ^ -(int32_t)(n & 1); + break; + } + case UPB_DESCRIPTOR_TYPE_SINT64: { + uint64_t n = val->uint64_val; + val->uint64_val = (n >> 1) ^ -(int64_t)(n & 1); + break; + } + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_UINT32: + if (!_upb_isle()) { + /* The next stage will memcpy(dst, &val, 4) */ + val->uint32_val = val->uint64_val; + } + break; + } +} + +static const upb_msglayout_field *upb_find_field(const upb_msglayout *l, + uint32_t field_number) { + static upb_msglayout_field none = {0, 0, 0, 0, 0, 0}; + + /* Lots of optimization opportunities here. */ + int i; + if (l == NULL) return &none; + for (i = 0; i < l->field_count; i++) { + if (l->fields[i].number == field_number) { + return &l->fields[i]; + } + } + + return &none; /* Unknown field. */ +} + +static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout, + const upb_msglayout_field *field) { + const upb_msglayout *subl = layout->submsgs[field->submsg_index]; + return _upb_msg_new_inl(subl, &d->arena); +} + +UPB_NOINLINE +const char *decode_isdonefallback(upb_decstate *d, const char *ptr, + int overrun) { + ptr = decode_isdonefallback_inl(d, ptr, overrun); + if (ptr == NULL) { + decode_err(d); + } + return ptr; +} + +static const char *decode_readstr(upb_decstate *d, const char *ptr, int size, + upb_strview *str) { + if (d->alias) { + str->data = ptr; + } else { + char *data = upb_arena_malloc(&d->arena, size); + if (!data) decode_err(d); + memcpy(data, ptr, size); + str->data = data; + } + str->size = size; + return ptr + size; +} + +UPB_FORCEINLINE +static const char *decode_tosubmsg(upb_decstate *d, const char *ptr, + upb_msg *submsg, const upb_msglayout *layout, + const upb_msglayout_field *field, int size) { + const upb_msglayout *subl = layout->submsgs[field->submsg_index]; + int saved_delta = decode_pushlimit(d, ptr, size); + if (--d->depth < 0) decode_err(d); + if (!decode_isdone(d, &ptr)) { + ptr = decode_msg(d, ptr, submsg, subl); + } + if (d->end_group != DECODE_NOGROUP) decode_err(d); + decode_poplimit(d, ptr, saved_delta); + d->depth++; + return ptr; +} + +UPB_FORCEINLINE +static const char *decode_group(upb_decstate *d, const char *ptr, + upb_msg *submsg, const upb_msglayout *subl, + uint32_t number) { + if (--d->depth < 0) decode_err(d); + if (decode_isdone(d, &ptr)) { + decode_err(d); + } + ptr = decode_msg(d, ptr, submsg, subl); + if (d->end_group != number) decode_err(d); + d->end_group = DECODE_NOGROUP; + d->depth++; + return ptr; +} + +UPB_FORCEINLINE +static const char *decode_togroup(upb_decstate *d, const char *ptr, + upb_msg *submsg, const upb_msglayout *layout, + const upb_msglayout_field *field) { + const upb_msglayout *subl = layout->submsgs[field->submsg_index]; + return decode_group(d, ptr, submsg, subl, field->number); +} + +static const char *decode_toarray(upb_decstate *d, const char *ptr, + upb_msg *msg, const upb_msglayout *layout, + const upb_msglayout_field *field, wireval val, + int op) { + upb_array **arrp = UPB_PTR_AT(msg, field->offset, void); + upb_array *arr = *arrp; + void *mem; + + if (arr) { + decode_reserve(d, arr, 1); + } else { + size_t lg2 = desctype_to_elem_size_lg2[field->descriptortype]; + arr = _upb_array_new(&d->arena, 4, lg2); + if (!arr) decode_err(d); + *arrp = arr; + } + + switch (op) { + case OP_SCALAR_LG2(0): + case OP_SCALAR_LG2(2): + case OP_SCALAR_LG2(3): + /* Append scalar value. */ + mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << op, void); + arr->len++; + memcpy(mem, &val, 1 << op); + return ptr; + case OP_STRING: + decode_verifyutf8(d, ptr, val.size); + /* Fallthrough. */ + case OP_BYTES: { + /* Append bytes. */ + upb_strview *str = (upb_strview*)_upb_array_ptr(arr) + arr->len; + arr->len++; + return decode_readstr(d, ptr, val.size, str); + } + case OP_SUBMSG: { + /* Append submessage / group. */ + upb_msg *submsg = decode_newsubmsg(d, layout, field); + *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void *), upb_msg *) = + submsg; + arr->len++; + if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) { + return decode_togroup(d, ptr, submsg, layout, field); + } else { + return decode_tosubmsg(d, ptr, submsg, layout, field, val.size); + } + } + case OP_FIXPCK_LG2(2): + case OP_FIXPCK_LG2(3): { + /* Fixed packed. */ + int lg2 = op - OP_FIXPCK_LG2(0); + int mask = (1 << lg2) - 1; + size_t count = val.size >> lg2; + if ((val.size & mask) != 0) { + decode_err(d); /* Length isn't a round multiple of elem size. */ + } + decode_reserve(d, arr, count); + mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void); + arr->len += count; + memcpy(mem, ptr, val.size); /* XXX: ptr boundary. */ + return ptr + val.size; + } + case OP_VARPCK_LG2(0): + case OP_VARPCK_LG2(2): + case OP_VARPCK_LG2(3): { + /* Varint packed. */ + int lg2 = op - OP_VARPCK_LG2(0); + int scale = 1 << lg2; + int saved_limit = decode_pushlimit(d, ptr, val.size); + char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void); + while (!decode_isdone(d, &ptr)) { + wireval elem; + ptr = decode_varint64(d, ptr, &elem.uint64_val); + decode_munge(field->descriptortype, &elem); + if (decode_reserve(d, arr, 1)) { + out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void); + } + arr->len++; + memcpy(out, &elem, scale); + out += scale; + } + decode_poplimit(d, ptr, saved_limit); + return ptr; + } + default: + UPB_UNREACHABLE(); + } +} + +static const char *decode_tomap(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *layout, + const upb_msglayout_field *field, wireval val) { + upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *); + upb_map *map = *map_p; + upb_map_entry ent; + const upb_msglayout *entry = layout->submsgs[field->submsg_index]; + + if (!map) { + /* Lazily create map. */ + const upb_msglayout *entry = layout->submsgs[field->submsg_index]; + const upb_msglayout_field *key_field = &entry->fields[0]; + const upb_msglayout_field *val_field = &entry->fields[1]; + char key_size = desctype_to_mapsize[key_field->descriptortype]; + char val_size = desctype_to_mapsize[val_field->descriptortype]; + UPB_ASSERT(key_field->offset == 0); + UPB_ASSERT(val_field->offset == sizeof(upb_strview)); + map = _upb_map_new(&d->arena, key_size, val_size); + *map_p = map; + } + + /* Parse map entry. */ + memset(&ent, 0, sizeof(ent)); + + if (entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE || + entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_GROUP) { + /* Create proactively to handle the case where it doesn't appear. */ + ent.v.val = upb_value_ptr(_upb_msg_new(entry->submsgs[0], &d->arena)); + } + + ptr = decode_tosubmsg(d, ptr, &ent.k, layout, field, val.size); + _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, &d->arena); + return ptr; +} + +static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *layout, + const upb_msglayout_field *field, wireval val, + int op) { + void *mem = UPB_PTR_AT(msg, field->offset, void); + int type = field->descriptortype; + + /* Set presence if necessary. */ + if (field->presence < 0) { + /* Oneof case */ + uint32_t *oneof_case = _upb_oneofcase_field(msg, field); + if (op == OP_SUBMSG && *oneof_case != field->number) { + memset(mem, 0, sizeof(void*)); + } + *oneof_case = field->number; + } else if (field->presence > 0) { + _upb_sethas_field(msg, field); + } + + /* Store into message. */ + switch (op) { + case OP_SUBMSG: { + upb_msg **submsgp = mem; + upb_msg *submsg = *submsgp; + if (!submsg) { + submsg = decode_newsubmsg(d, layout, field); + *submsgp = submsg; + } + if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) { + ptr = decode_togroup(d, ptr, submsg, layout, field); + } else { + ptr = decode_tosubmsg(d, ptr, submsg, layout, field, val.size); + } + break; + } + case OP_STRING: + decode_verifyutf8(d, ptr, val.size); + /* Fallthrough. */ + case OP_BYTES: + return decode_readstr(d, ptr, val.size, mem); + case OP_SCALAR_LG2(3): + memcpy(mem, &val, 8); + break; + case OP_SCALAR_LG2(2): + memcpy(mem, &val, 4); + break; + case OP_SCALAR_LG2(0): + memcpy(mem, &val, 1); + break; + default: + UPB_UNREACHABLE(); + } + + return ptr; +} + +UPB_FORCEINLINE +static bool decode_tryfastdispatch(upb_decstate *d, const char **ptr, + upb_msg *msg, const upb_msglayout *layout) { +#if UPB_FASTTABLE + if (layout && layout->table_mask != (unsigned char)-1) { + uint16_t tag = fastdecode_loadtag(*ptr); + intptr_t table = decode_totable(layout); + *ptr = fastdecode_tagdispatch(d, *ptr, msg, table, 0, tag); + return true; + } +#endif + return false; +} + +UPB_NOINLINE +static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *layout) { + while (true) { + uint32_t tag; + const upb_msglayout_field *field; + int field_number; + int wire_type; + const char *field_start = ptr; + wireval val; + int op; + + UPB_ASSERT(ptr < d->limit_ptr); + ptr = decode_tag(d, ptr, &tag); + field_number = tag >> 3; + wire_type = tag & 7; + + field = upb_find_field(layout, field_number); + + switch (wire_type) { + case UPB_WIRE_TYPE_VARINT: + ptr = decode_varint64(d, ptr, &val.uint64_val); + op = varint_ops[field->descriptortype]; + decode_munge(field->descriptortype, &val); + break; + case UPB_WIRE_TYPE_32BIT: + memcpy(&val.uint32_val, ptr, 4); + val.uint32_val = _upb_be_swap32(val.uint32_val); + ptr += 4; + op = OP_SCALAR_LG2(2); + if (((1 << field->descriptortype) & fixed32_ok) == 0) goto unknown; + break; + case UPB_WIRE_TYPE_64BIT: + memcpy(&val.uint64_val, ptr, 8); + val.uint64_val = _upb_be_swap64(val.uint64_val); + ptr += 8; + op = OP_SCALAR_LG2(3); + if (((1 << field->descriptortype) & fixed64_ok) == 0) goto unknown; + break; + case UPB_WIRE_TYPE_DELIMITED: { + int ndx = field->descriptortype; + uint64_t size; + if (_upb_isrepeated(field)) ndx += 18; + ptr = decode_varint64(d, ptr, &size); + if (size >= INT32_MAX || + ptr - d->end + (int32_t)size > d->limit) { + decode_err(d); /* Length overflow. */ + } + op = delim_ops[ndx]; + val.size = size; + break; + } + case UPB_WIRE_TYPE_START_GROUP: + val.uint32_val = field_number; + op = OP_SUBMSG; + if (field->descriptortype != UPB_DTYPE_GROUP) goto unknown; + break; + case UPB_WIRE_TYPE_END_GROUP: + d->end_group = field_number; + return ptr; + default: + decode_err(d); + } + + if (op >= 0) { + /* Parse, using op for dispatch. */ + switch (field->label) { + case UPB_LABEL_REPEATED: + case _UPB_LABEL_PACKED: + ptr = decode_toarray(d, ptr, msg, layout, field, val, op); + break; + case _UPB_LABEL_MAP: + ptr = decode_tomap(d, ptr, msg, layout, field, val); + break; + default: + ptr = decode_tomsg(d, ptr, msg, layout, field, val, op); + break; + } + } else { + unknown: + /* Skip unknown field. */ + if (field_number == 0) decode_err(d); + if (wire_type == UPB_WIRE_TYPE_DELIMITED) ptr += val.size; + if (msg) { + if (wire_type == UPB_WIRE_TYPE_START_GROUP) { + d->unknown = field_start; + d->unknown_msg = msg; + ptr = decode_group(d, ptr, NULL, NULL, field_number); + d->unknown_msg = NULL; + field_start = d->unknown; + } + if (!_upb_msg_addunknown(msg, field_start, ptr - field_start, + &d->arena)) { + decode_err(d); + } + } else if (wire_type == UPB_WIRE_TYPE_START_GROUP) { + ptr = decode_group(d, ptr, NULL, NULL, field_number); + } + } + + if (decode_isdone(d, &ptr)) return ptr; + if (decode_tryfastdispatch(d, &ptr, msg, layout)) return ptr; + } +} + +const char *fastdecode_generic(struct upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, uint64_t hasbits, + uint64_t data) { + (void)data; + *(uint32_t*)msg |= hasbits; + return decode_msg(d, ptr, msg, decode_totablep(table)); +} + +static bool decode_top(struct upb_decstate *d, const char *buf, void *msg, + const upb_msglayout *l) { + if (!decode_tryfastdispatch(d, &buf, msg, l)) { + decode_msg(d, buf, msg, l); + } + return d->end_group == DECODE_NOGROUP; +} + +bool _upb_decode(const char *buf, size_t size, void *msg, + const upb_msglayout *l, upb_arena *arena, int options) { + bool ok; + upb_decstate state; + unsigned depth = (unsigned)options >> 16; + + if (size == 0) { + return true; + } else if (size <= 16) { + memset(&state.patch, 0, 32); + memcpy(&state.patch, buf, size); + buf = state.patch; + state.end = buf + size; + state.limit = 0; + state.alias = false; + } else { + state.end = buf + size - 16; + state.limit = 16; + state.alias = options & UPB_DECODE_ALIAS; + } + + state.limit_ptr = state.end; + state.unknown_msg = NULL; + state.depth = depth ? depth : 64; + state.end_group = DECODE_NOGROUP; + state.arena.head = arena->head; + state.arena.last_size = arena->last_size; + state.arena.cleanups = arena->cleanups; + state.arena.parent = arena; + + if (UPB_UNLIKELY(UPB_SETJMP(state.err))) { + ok = false; + } else { + ok = decode_top(&state, buf, msg, l); + } + + arena->head.ptr = state.arena.head.ptr; + arena->head.end = state.arena.head.end; + arena->cleanups = state.arena.cleanups; + return ok; +} + +#undef OP_SCALAR_LG2 +#undef OP_FIXPCK_LG2 +#undef OP_VARPCK_LG2 +#undef OP_STRING +#undef OP_SUBMSG +/* We encode backwards, to avoid pre-computing lengths (one-pass encode). */ + + +#include +#include + + +/* Must be last. */ + +#define UPB_PB_VARINT_MAX_LEN 10 + +UPB_NOINLINE +static size_t encode_varint64(uint64_t val, char *buf) { + size_t i = 0; + do { + uint8_t byte = val & 0x7fU; + val >>= 7; + if (val) byte |= 0x80U; + buf[i++] = byte; + } while (val); + return i; +} + +static uint32_t encode_zz32(int32_t n) { return ((uint32_t)n << 1) ^ (n >> 31); } +static uint64_t encode_zz64(int64_t n) { return ((uint64_t)n << 1) ^ (n >> 63); } + +typedef struct { + jmp_buf err; + upb_alloc *alloc; + char *buf, *ptr, *limit; + int options; + int depth; + _upb_mapsorter sorter; +} upb_encstate; + +static size_t upb_roundup_pow2(size_t bytes) { + size_t ret = 128; + while (ret < bytes) { + ret *= 2; + } + return ret; +} + +UPB_NORETURN static void encode_err(upb_encstate *e) { + UPB_LONGJMP(e->err, 1); +} + +UPB_NOINLINE +static void encode_growbuffer(upb_encstate *e, size_t bytes) { + size_t old_size = e->limit - e->buf; + size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr)); + char *new_buf = upb_realloc(e->alloc, e->buf, old_size, new_size); + + if (!new_buf) encode_err(e); + + /* We want previous data at the end, realloc() put it at the beginning. */ + if (old_size > 0) { + memmove(new_buf + new_size - old_size, e->buf, old_size); + } + + e->ptr = new_buf + new_size - (e->limit - e->ptr); + e->limit = new_buf + new_size; + e->buf = new_buf; + + e->ptr -= bytes; +} + +/* Call to ensure that at least "bytes" bytes are available for writing at + * e->ptr. Returns false if the bytes could not be allocated. */ +UPB_FORCEINLINE +static void encode_reserve(upb_encstate *e, size_t bytes) { + if ((size_t)(e->ptr - e->buf) < bytes) { + encode_growbuffer(e, bytes); + return; + } + + e->ptr -= bytes; +} + +/* Writes the given bytes to the buffer, handling reserve/advance. */ +static void encode_bytes(upb_encstate *e, const void *data, size_t len) { + if (len == 0) return; /* memcpy() with zero size is UB */ + encode_reserve(e, len); + memcpy(e->ptr, data, len); +} + +static void encode_fixed64(upb_encstate *e, uint64_t val) { + val = _upb_be_swap64(val); + encode_bytes(e, &val, sizeof(uint64_t)); +} + +static void encode_fixed32(upb_encstate *e, uint32_t val) { + val = _upb_be_swap32(val); + encode_bytes(e, &val, sizeof(uint32_t)); +} + +UPB_NOINLINE +static void encode_longvarint(upb_encstate *e, uint64_t val) { + size_t len; + char *start; + + encode_reserve(e, UPB_PB_VARINT_MAX_LEN); + len = encode_varint64(val, e->ptr); + start = e->ptr + UPB_PB_VARINT_MAX_LEN - len; + memmove(start, e->ptr, len); + e->ptr = start; +} + +UPB_FORCEINLINE +static void encode_varint(upb_encstate *e, uint64_t val) { + if (val < 128 && e->ptr != e->buf) { + --e->ptr; + *e->ptr = val; + } else { + encode_longvarint(e, val); + } +} + +static void encode_double(upb_encstate *e, double d) { + uint64_t u64; + UPB_ASSERT(sizeof(double) == sizeof(uint64_t)); + memcpy(&u64, &d, sizeof(uint64_t)); + encode_fixed64(e, u64); +} + +static void encode_float(upb_encstate *e, float d) { + uint32_t u32; + UPB_ASSERT(sizeof(float) == sizeof(uint32_t)); + memcpy(&u32, &d, sizeof(uint32_t)); + encode_fixed32(e, u32); +} + +static void encode_tag(upb_encstate *e, uint32_t field_number, + uint8_t wire_type) { + encode_varint(e, (field_number << 3) | wire_type); +} + +static void encode_fixedarray(upb_encstate *e, const upb_array *arr, + size_t elem_size, uint32_t tag) { + size_t bytes = arr->len * elem_size; + const char* data = _upb_array_constptr(arr); + const char* ptr = data + bytes - elem_size; + if (tag) { + while (true) { + encode_bytes(e, ptr, elem_size); + encode_varint(e, tag); + if (ptr == data) break; + ptr -= elem_size; + } + } else { + encode_bytes(e, data, bytes); + } +} + +static void encode_message(upb_encstate *e, const char *msg, + const upb_msglayout *m, size_t *size); + +static void encode_scalar(upb_encstate *e, const void *_field_mem, + const upb_msglayout *m, const upb_msglayout_field *f, + bool skip_zero_value) { + const char *field_mem = _field_mem; + int wire_type; + +#define CASE(ctype, type, wtype, encodeval) \ + { \ + ctype val = *(ctype *)field_mem; \ + if (skip_zero_value && val == 0) { \ + return; \ + } \ + encode_##type(e, encodeval); \ + wire_type = wtype; \ + break; \ + } + + switch (f->descriptortype) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + CASE(double, double, UPB_WIRE_TYPE_64BIT, val); + case UPB_DESCRIPTOR_TYPE_FLOAT: + CASE(float, float, UPB_WIRE_TYPE_32BIT, val); + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val); + case UPB_DESCRIPTOR_TYPE_UINT32: + CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val); + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_ENUM: + CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, (int64_t)val); + case UPB_DESCRIPTOR_TYPE_SFIXED64: + case UPB_DESCRIPTOR_TYPE_FIXED64: + CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val); + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val); + case UPB_DESCRIPTOR_TYPE_BOOL: + CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val); + case UPB_DESCRIPTOR_TYPE_SINT32: + CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, encode_zz32(val)); + case UPB_DESCRIPTOR_TYPE_SINT64: + CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, encode_zz64(val)); + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: { + upb_strview view = *(upb_strview*)field_mem; + if (skip_zero_value && view.size == 0) { + return; + } + encode_bytes(e, view.data, view.size); + encode_varint(e, view.size); + wire_type = UPB_WIRE_TYPE_DELIMITED; + break; + } + case UPB_DESCRIPTOR_TYPE_GROUP: { + size_t size; + void *submsg = *(void **)field_mem; + const upb_msglayout *subm = m->submsgs[f->submsg_index]; + if (submsg == NULL) { + return; + } + if (--e->depth == 0) encode_err(e); + encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP); + encode_message(e, submsg, subm, &size); + wire_type = UPB_WIRE_TYPE_START_GROUP; + e->depth++; + break; + } + case UPB_DESCRIPTOR_TYPE_MESSAGE: { + size_t size; + void *submsg = *(void **)field_mem; + const upb_msglayout *subm = m->submsgs[f->submsg_index]; + if (submsg == NULL) { + return; + } + if (--e->depth == 0) encode_err(e); + encode_message(e, submsg, subm, &size); + encode_varint(e, size); + wire_type = UPB_WIRE_TYPE_DELIMITED; + e->depth++; + break; + } + default: + UPB_UNREACHABLE(); + } +#undef CASE + + encode_tag(e, f->number, wire_type); +} + +static void encode_array(upb_encstate *e, const char *field_mem, + const upb_msglayout *m, const upb_msglayout_field *f) { + const upb_array *arr = *(const upb_array**)field_mem; + bool packed = f->label == _UPB_LABEL_PACKED; + size_t pre_len = e->limit - e->ptr; + + if (arr == NULL || arr->len == 0) { + return; + } + +#define VARINT_CASE(ctype, encode) \ + { \ + const ctype *start = _upb_array_constptr(arr); \ + const ctype *ptr = start + arr->len; \ + uint32_t tag = packed ? 0 : (f->number << 3) | UPB_WIRE_TYPE_VARINT; \ + do { \ + ptr--; \ + encode_varint(e, encode); \ + if (tag) encode_varint(e, tag); \ + } while (ptr != start); \ + } \ + break; + +#define TAG(wire_type) (packed ? 0 : (f->number << 3 | wire_type)) + + switch (f->descriptortype) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + encode_fixedarray(e, arr, sizeof(double), TAG(UPB_WIRE_TYPE_64BIT)); + break; + case UPB_DESCRIPTOR_TYPE_FLOAT: + encode_fixedarray(e, arr, sizeof(float), TAG(UPB_WIRE_TYPE_32BIT)); + break; + case UPB_DESCRIPTOR_TYPE_SFIXED64: + case UPB_DESCRIPTOR_TYPE_FIXED64: + encode_fixedarray(e, arr, sizeof(uint64_t), TAG(UPB_WIRE_TYPE_64BIT)); + break; + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + encode_fixedarray(e, arr, sizeof(uint32_t), TAG(UPB_WIRE_TYPE_32BIT)); + break; + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + VARINT_CASE(uint64_t, *ptr); + case UPB_DESCRIPTOR_TYPE_UINT32: + VARINT_CASE(uint32_t, *ptr); + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_ENUM: + VARINT_CASE(int32_t, (int64_t)*ptr); + case UPB_DESCRIPTOR_TYPE_BOOL: + VARINT_CASE(bool, *ptr); + case UPB_DESCRIPTOR_TYPE_SINT32: + VARINT_CASE(int32_t, encode_zz32(*ptr)); + case UPB_DESCRIPTOR_TYPE_SINT64: + VARINT_CASE(int64_t, encode_zz64(*ptr)); + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: { + const upb_strview *start = _upb_array_constptr(arr); + const upb_strview *ptr = start + arr->len; + do { + ptr--; + encode_bytes(e, ptr->data, ptr->size); + encode_varint(e, ptr->size); + encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); + } while (ptr != start); + return; + } + case UPB_DESCRIPTOR_TYPE_GROUP: { + const void *const*start = _upb_array_constptr(arr); + const void *const*ptr = start + arr->len; + const upb_msglayout *subm = m->submsgs[f->submsg_index]; + if (--e->depth == 0) encode_err(e); + do { + size_t size; + ptr--; + encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP); + encode_message(e, *ptr, subm, &size); + encode_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP); + } while (ptr != start); + e->depth++; + return; + } + case UPB_DESCRIPTOR_TYPE_MESSAGE: { + const void *const*start = _upb_array_constptr(arr); + const void *const*ptr = start + arr->len; + const upb_msglayout *subm = m->submsgs[f->submsg_index]; + if (--e->depth == 0) encode_err(e); + do { + size_t size; + ptr--; + encode_message(e, *ptr, subm, &size); + encode_varint(e, size); + encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); + } while (ptr != start); + e->depth++; + return; + } + } +#undef VARINT_CASE + + if (packed) { + encode_varint(e, e->limit - e->ptr - pre_len); + encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); + } +} + +static void encode_mapentry(upb_encstate *e, uint32_t number, + const upb_msglayout *layout, + const upb_map_entry *ent) { + const upb_msglayout_field *key_field = &layout->fields[0]; + const upb_msglayout_field *val_field = &layout->fields[1]; + size_t pre_len = e->limit - e->ptr; + size_t size; + encode_scalar(e, &ent->v, layout, val_field, false); + encode_scalar(e, &ent->k, layout, key_field, false); + size = (e->limit - e->ptr) - pre_len; + encode_varint(e, size); + encode_tag(e, number, UPB_WIRE_TYPE_DELIMITED); +} + +static void encode_map(upb_encstate *e, const char *field_mem, + const upb_msglayout *m, const upb_msglayout_field *f) { + const upb_map *map = *(const upb_map**)field_mem; + const upb_msglayout *layout = m->submsgs[f->submsg_index]; + UPB_ASSERT(layout->field_count == 2); + + if (map == NULL) return; + + if (e->options & UPB_ENCODE_DETERMINISTIC) { + _upb_sortedmap sorted; + _upb_mapsorter_pushmap(&e->sorter, layout->fields[0].descriptortype, map, + &sorted); + upb_map_entry ent; + while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) { + encode_mapentry(e, f->number, layout, &ent); + } + _upb_mapsorter_popmap(&e->sorter, &sorted); + } else { + upb_strtable_iter i; + upb_strtable_begin(&i, &map->table); + for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { + upb_strview key = upb_strtable_iter_key(&i); + const upb_value val = upb_strtable_iter_value(&i); + upb_map_entry ent; + _upb_map_fromkey(key, &ent.k, map->key_size); + _upb_map_fromvalue(val, &ent.v, map->val_size); + encode_mapentry(e, f->number, layout, &ent); + } + } +} + +static void encode_scalarfield(upb_encstate *e, const char *msg, + const upb_msglayout *m, + const upb_msglayout_field *f) { + bool skip_empty = false; + if (f->presence == 0) { + /* Proto3 presence. */ + skip_empty = true; + } else if (f->presence > 0) { + /* Proto2 presence: hasbit. */ + if (!_upb_hasbit_field(msg, f)) return; + } else { + /* Field is in a oneof. */ + if (_upb_getoneofcase_field(msg, f) != f->number) return; + } + encode_scalar(e, msg + f->offset, m, f, skip_empty); +} + +static void encode_message(upb_encstate *e, const char *msg, + const upb_msglayout *m, size_t *size) { + size_t pre_len = e->limit - e->ptr; + const upb_msglayout_field *f = &m->fields[m->field_count]; + const upb_msglayout_field *first = &m->fields[0]; + + if ((e->options & UPB_ENCODE_SKIPUNKNOWN) == 0) { + size_t unknown_size; + const char *unknown = upb_msg_getunknown(msg, &unknown_size); + + if (unknown) { + encode_bytes(e, unknown, unknown_size); + } + } + + while (f != first) { + f--; + if (_upb_isrepeated(f)) { + encode_array(e, msg + f->offset, m, f); + } else if (f->label == _UPB_LABEL_MAP) { + encode_map(e, msg + f->offset, m, f); + } else { + encode_scalarfield(e, msg, m, f); + } + } + + *size = (e->limit - e->ptr) - pre_len; +} + +char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options, + upb_arena *arena, size_t *size) { + upb_encstate e; + unsigned depth = (unsigned)options >> 16; + + e.alloc = upb_arena_alloc(arena); + e.buf = NULL; + e.limit = NULL; + e.ptr = NULL; + e.depth = depth ? depth : 64; + e.options = options; + _upb_mapsorter_init(&e.sorter); + char *ret = NULL; + + if (UPB_SETJMP(e.err)) { + *size = 0; + ret = NULL; + } else { + encode_message(&e, msg, l, size); + *size = e.limit - e.ptr; + if (*size == 0) { + static char ch; + ret = &ch; + } else { + UPB_ASSERT(e.ptr); + ret = e.ptr; + } + } + + _upb_mapsorter_destroy(&e.sorter); + return ret; +} + + + + +/** upb_msg *******************************************************************/ + +static const size_t overhead = sizeof(upb_msg_internal); + +static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) { + ptrdiff_t size = sizeof(upb_msg_internal); + return (upb_msg_internal*)((char*)msg - size); +} + +upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a) { + return _upb_msg_new_inl(l, a); +} + +void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l) { + void *mem = UPB_PTR_AT(msg, -sizeof(upb_msg_internal), char); + memset(mem, 0, upb_msg_sizeof(l)); +} + +bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, + upb_arena *arena) { + + upb_msg_internal *in = upb_msg_getinternal(msg); + if (!in->unknown) { + size_t size = 128; + while (size < len) size *= 2; + in->unknown = upb_arena_malloc(arena, size + overhead); + if (!in->unknown) return false; + in->unknown->size = size; + in->unknown->len = 0; + } else if (in->unknown->size - in->unknown->len < len) { + size_t need = in->unknown->len + len; + size_t size = in->unknown->size; + while (size < need) size *= 2; + in->unknown = upb_arena_realloc( + arena, in->unknown, in->unknown->size + overhead, size + overhead); + if (!in->unknown) return false; + in->unknown->size = size; + } + memcpy(UPB_PTR_AT(in->unknown + 1, in->unknown->len, char), data, len); + in->unknown->len += len; + return true; +} + +void _upb_msg_discardunknown_shallow(upb_msg *msg) { + upb_msg_internal *in = upb_msg_getinternal(msg); + if (in->unknown) { + in->unknown->len = 0; + } +} + +const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) { + const upb_msg_internal *in = upb_msg_getinternal_const(msg); + if (in->unknown) { + *len = in->unknown->len; + return (char*)(in->unknown + 1); + } else { + *len = 0; + return NULL; + } +} + +/** upb_array *****************************************************************/ + +bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena) { + size_t new_size = UPB_MAX(arr->size, 4); + int elem_size_lg2 = arr->data & 7; + size_t old_bytes = arr->size << elem_size_lg2; + size_t new_bytes; + void* ptr = _upb_array_ptr(arr); + + /* Log2 ceiling of size. */ + while (new_size < min_size) new_size *= 2; + + new_bytes = new_size << elem_size_lg2; + ptr = upb_arena_realloc(arena, ptr, old_bytes, new_bytes); + + if (!ptr) { + return false; + } + + arr->data = _upb_tag_arrptr(ptr, elem_size_lg2); + arr->size = new_size; + return true; +} + +static upb_array *getorcreate_array(upb_array **arr_ptr, int elem_size_lg2, + upb_arena *arena) { + upb_array *arr = *arr_ptr; + if (!arr) { + arr = _upb_array_new(arena, 4, elem_size_lg2); + if (!arr) return NULL; + *arr_ptr = arr; + } + return arr; +} + +void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size, + int elem_size_lg2, upb_arena *arena) { + upb_array *arr = getorcreate_array(arr_ptr, elem_size_lg2, arena); + return arr && _upb_array_resize(arr, size, arena) ? _upb_array_ptr(arr) + : NULL; +} + +bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value, + int elem_size_lg2, upb_arena *arena) { + upb_array *arr = getorcreate_array(arr_ptr, elem_size_lg2, arena); + if (!arr) return false; + + size_t elems = arr->len; + + if (!_upb_array_resize(arr, elems + 1, arena)) { + return false; + } + + char *data = _upb_array_ptr(arr); + memcpy(data + (elems << elem_size_lg2), value, 1 << elem_size_lg2); + return true; +} + +/** upb_map *******************************************************************/ + +upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) { + upb_map *map = upb_arena_malloc(a, sizeof(upb_map)); + + if (!map) { + return NULL; + } + + upb_strtable_init2(&map->table, UPB_CTYPE_INT32, 4, upb_arena_alloc(a)); + map->key_size = key_size; + map->val_size = value_size; + + return map; +} + +static void _upb_mapsorter_getkeys(const void *_a, const void *_b, void *a_key, + void *b_key, size_t size) { + const upb_tabent *const*a = _a; + const upb_tabent *const*b = _b; + upb_strview a_tabkey = upb_tabstrview((*a)->key); + upb_strview b_tabkey = upb_tabstrview((*b)->key); + _upb_map_fromkey(a_tabkey, a_key, size); + _upb_map_fromkey(b_tabkey, b_key, size); +} + +static int _upb_mapsorter_cmpi64(const void *_a, const void *_b) { + int64_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 8); + return a - b; +} + +static int _upb_mapsorter_cmpu64(const void *_a, const void *_b) { + uint64_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 8); + return a - b; +} + +static int _upb_mapsorter_cmpi32(const void *_a, const void *_b) { + int32_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 4); + return a - b; +} + +static int _upb_mapsorter_cmpu32(const void *_a, const void *_b) { + uint32_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 4); + return a - b; +} + +static int _upb_mapsorter_cmpbool(const void *_a, const void *_b) { + bool a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 1); + return a - b; +} + +static int _upb_mapsorter_cmpstr(const void *_a, const void *_b) { + upb_strview a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, UPB_MAPTYPE_STRING); + size_t common_size = UPB_MIN(a.size, b.size); + int cmp = memcmp(a.data, b.data, common_size); + if (cmp) return cmp; + return a.size - b.size; +} + +bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type, + const upb_map *map, _upb_sortedmap *sorted) { + int map_size = _upb_map_size(map); + sorted->start = s->size; + sorted->pos = sorted->start; + sorted->end = sorted->start + map_size; + + /* Grow s->entries if necessary. */ + if (sorted->end > s->cap) { + s->cap = _upb_lg2ceilsize(sorted->end); + s->entries = realloc(s->entries, s->cap * sizeof(*s->entries)); + if (!s->entries) return false; + } + + s->size = sorted->end; + + /* Copy non-empty entries from the table to s->entries. */ + upb_tabent const**dst = &s->entries[sorted->start]; + const upb_tabent *src = map->table.t.entries; + const upb_tabent *end = src + upb_table_size(&map->table.t); + for (; src < end; src++) { + if (!upb_tabent_isempty(src)) { + *dst = src; + dst++; + } + } + UPB_ASSERT(dst == &s->entries[sorted->end]); + + /* Sort entries according to the key type. */ + + int (*compar)(const void *, const void *); + + switch (key_type) { + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_SFIXED64: + case UPB_DESCRIPTOR_TYPE_SINT64: + compar = _upb_mapsorter_cmpi64; + break; + case UPB_DESCRIPTOR_TYPE_UINT64: + case UPB_DESCRIPTOR_TYPE_FIXED64: + compar = _upb_mapsorter_cmpu64; + break; + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_SINT32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + case UPB_DESCRIPTOR_TYPE_ENUM: + compar = _upb_mapsorter_cmpi32; + break; + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_FIXED32: + compar = _upb_mapsorter_cmpu32; + break; + case UPB_DESCRIPTOR_TYPE_BOOL: + compar = _upb_mapsorter_cmpbool; + break; + case UPB_DESCRIPTOR_TYPE_STRING: + compar = _upb_mapsorter_cmpstr; + break; + default: + UPB_UNREACHABLE(); + } + + qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), compar); + return true; +} +/* +** upb_table Implementation +** +** Implementation is heavily inspired by Lua's ltable.c. +*/ + +#include + +#include "third_party/wyhash/wyhash.h" + +/* Must be last. */ + +#define UPB_MAXARRSIZE 16 /* 64k. */ + +/* From Chromium. */ +#define ARRAY_SIZE(x) \ + ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) + +static const double MAX_LOAD = 0.85; + +/* The minimum utilization of the array part of a mixed hash/array table. This + * is a speed/memory-usage tradeoff (though it's not straightforward because of + * cache effects). The lower this is, the more memory we'll use. */ +static const double MIN_DENSITY = 0.1; + +bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; } + +int log2ceil(uint64_t v) { + int ret = 0; + bool pow2 = is_pow2(v); + while (v >>= 1) ret++; + ret = pow2 ? ret : ret + 1; /* Ceiling. */ + return UPB_MIN(UPB_MAXARRSIZE, ret); +} + +char *upb_strdup(const char *s, upb_alloc *a) { + return upb_strdup2(s, strlen(s), a); +} + +char *upb_strdup2(const char *s, size_t len, upb_alloc *a) { + size_t n; + char *p; + + /* Prevent overflow errors. */ + if (len == SIZE_MAX) return NULL; + /* Always null-terminate, even if binary data; but don't rely on the input to + * have a null-terminating byte since it may be a raw binary buffer. */ + n = len + 1; + p = upb_malloc(a, n); + if (p) { + memcpy(p, s, len); + p[len] = 0; + } + return p; +} + +/* A type to represent the lookup key of either a strtable or an inttable. */ +typedef union { + uintptr_t num; + struct { + const char *str; + size_t len; + } str; +} lookupkey_t; + +static lookupkey_t strkey2(const char *str, size_t len) { + lookupkey_t k; + k.str.str = str; + k.str.len = len; + return k; +} + +static lookupkey_t intkey(uintptr_t key) { + lookupkey_t k; + k.num = key; + return k; +} + +typedef uint32_t hashfunc_t(upb_tabkey key); +typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2); + +/* Base table (shared code) ***************************************************/ + +/* For when we need to cast away const. */ +static upb_tabent *mutable_entries(upb_table *t) { + return (upb_tabent*)t->entries; +} + +static bool isfull(upb_table *t) { + return t->count == t->max_count; +} + +static bool init(upb_table *t, uint8_t size_lg2, upb_alloc *a) { + size_t bytes; + + t->count = 0; + t->size_lg2 = size_lg2; + t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0; + t->max_count = upb_table_size(t) * MAX_LOAD; + bytes = upb_table_size(t) * sizeof(upb_tabent); + if (bytes > 0) { + t->entries = upb_malloc(a, bytes); + if (!t->entries) return false; + memset(mutable_entries(t), 0, bytes); + } else { + t->entries = NULL; + } + return true; +} + +static void uninit(upb_table *t, upb_alloc *a) { + upb_free(a, mutable_entries(t)); +} + +static upb_tabent *emptyent(upb_table *t, upb_tabent *e) { + upb_tabent *begin = mutable_entries(t); + upb_tabent *end = begin + upb_table_size(t); + for (e = e + 1; e < end; e++) { + if (upb_tabent_isempty(e)) return e; + } + for (e = begin; e < end; e++) { + if (upb_tabent_isempty(e)) return e; + } + UPB_ASSERT(false); + return NULL; +} + +static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) { + return (upb_tabent*)upb_getentry(t, hash); +} + +static const upb_tabent *findentry(const upb_table *t, lookupkey_t key, + uint32_t hash, eqlfunc_t *eql) { + const upb_tabent *e; + + if (t->size_lg2 == 0) return NULL; + e = upb_getentry(t, hash); + if (upb_tabent_isempty(e)) return NULL; + while (1) { + if (eql(e->key, key)) return e; + if ((e = e->next) == NULL) return NULL; + } +} + +static upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key, + uint32_t hash, eqlfunc_t *eql) { + return (upb_tabent*)findentry(t, key, hash, eql); +} + +static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v, + uint32_t hash, eqlfunc_t *eql) { + const upb_tabent *e = findentry(t, key, hash, eql); + if (e) { + if (v) { + _upb_value_setval(v, e->val.val); + } + return true; + } else { + return false; + } +} + +/* The given key must not already exist in the table. */ +static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey, + upb_value val, uint32_t hash, + hashfunc_t *hashfunc, eqlfunc_t *eql) { + upb_tabent *mainpos_e; + upb_tabent *our_e; + + UPB_ASSERT(findentry(t, key, hash, eql) == NULL); + + t->count++; + mainpos_e = getentry_mutable(t, hash); + our_e = mainpos_e; + + if (upb_tabent_isempty(mainpos_e)) { + /* Our main position is empty; use it. */ + our_e->next = NULL; + } else { + /* Collision. */ + upb_tabent *new_e = emptyent(t, mainpos_e); + /* Head of collider's chain. */ + upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key)); + if (chain == mainpos_e) { + /* Existing ent is in its main position (it has the same hash as us, and + * is the head of our chain). Insert to new ent and append to this chain. */ + new_e->next = mainpos_e->next; + mainpos_e->next = new_e; + our_e = new_e; + } else { + /* Existing ent is not in its main position (it is a node in some other + * chain). This implies that no existing ent in the table has our hash. + * Evict it (updating its chain) and use its ent for head of our chain. */ + *new_e = *mainpos_e; /* copies next. */ + while (chain->next != mainpos_e) { + chain = (upb_tabent*)chain->next; + UPB_ASSERT(chain); + } + chain->next = new_e; + our_e = mainpos_e; + our_e->next = NULL; + } + } + our_e->key = tabkey; + our_e->val.val = val.val; + UPB_ASSERT(findentry(t, key, hash, eql) == our_e); +} + +static bool rm(upb_table *t, lookupkey_t key, upb_value *val, + upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) { + upb_tabent *chain = getentry_mutable(t, hash); + if (upb_tabent_isempty(chain)) return false; + if (eql(chain->key, key)) { + /* Element to remove is at the head of its chain. */ + t->count--; + if (val) _upb_value_setval(val, chain->val.val); + if (removed) *removed = chain->key; + if (chain->next) { + upb_tabent *move = (upb_tabent*)chain->next; + *chain = *move; + move->key = 0; /* Make the slot empty. */ + } else { + chain->key = 0; /* Make the slot empty. */ + } + return true; + } else { + /* Element to remove is either in a non-head position or not in the + * table. */ + while (chain->next && !eql(chain->next->key, key)) { + chain = (upb_tabent*)chain->next; + } + if (chain->next) { + /* Found element to remove. */ + upb_tabent *rm = (upb_tabent*)chain->next; + t->count--; + if (val) _upb_value_setval(val, chain->next->val.val); + if (removed) *removed = rm->key; + rm->key = 0; /* Make the slot empty. */ + chain->next = rm->next; + return true; + } else { + /* Element to remove is not in the table. */ + return false; + } + } +} + +static size_t next(const upb_table *t, size_t i) { + do { + if (++i >= upb_table_size(t)) + return SIZE_MAX - 1; /* Distinct from -1. */ + } while(upb_tabent_isempty(&t->entries[i])); + + return i; +} + +static size_t begin(const upb_table *t) { + return next(t, -1); +} + + +/* upb_strtable ***************************************************************/ + +/* A simple "subclass" of upb_table that only adds a hash function for strings. */ + +static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) { + uint32_t len = (uint32_t) k2.str.len; + char *str = upb_malloc(a, k2.str.len + sizeof(uint32_t) + 1); + if (str == NULL) return 0; + memcpy(str, &len, sizeof(uint32_t)); + if (k2.str.len) memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len); + str[sizeof(uint32_t) + k2.str.len] = '\0'; + return (uintptr_t)str; +} + +static uint32_t table_hash(const char *p, size_t n) { + return wyhash(p, n, 0, _wyp); +} + +static uint32_t strhash(upb_tabkey key) { + uint32_t len; + char *str = upb_tabstr(key, &len); + return table_hash(str, len); +} + +static bool streql(upb_tabkey k1, lookupkey_t k2) { + uint32_t len; + char *str = upb_tabstr(k1, &len); + return len == k2.str.len && (len == 0 || memcmp(str, k2.str.str, len) == 0); +} + +bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, + size_t expected_size, upb_alloc *a) { + UPB_UNUSED(ctype); /* TODO(haberman): rm */ + // Multiply by approximate reciprocal of MAX_LOAD (0.85), with pow2 denominator. + size_t need_entries = (expected_size + 1) * 1204 / 1024; + UPB_ASSERT(need_entries >= expected_size * 0.85); + int size_lg2 = _upb_lg2ceil(need_entries); + return init(&t->t, size_lg2, a); +} + +void upb_strtable_clear(upb_strtable *t) { + size_t bytes = upb_table_size(&t->t) * sizeof(upb_tabent); + t->t.count = 0; + memset((char*)t->t.entries, 0, bytes); +} + +void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) { + size_t i; + for (i = 0; i < upb_table_size(&t->t); i++) + upb_free(a, (void*)t->t.entries[i].key); + uninit(&t->t, a); +} + +bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) { + upb_strtable new_table; + upb_strtable_iter i; + + if (!init(&new_table.t, size_lg2, a)) + return false; + upb_strtable_begin(&i, t); + for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) { + upb_strview key = upb_strtable_iter_key(&i); + upb_strtable_insert3( + &new_table, key.data, key.size, + upb_strtable_iter_value(&i), a); + } + upb_strtable_uninit2(t, a); + *t = new_table; + return true; +} + +bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len, + upb_value v, upb_alloc *a) { + lookupkey_t key; + upb_tabkey tabkey; + uint32_t hash; + + if (isfull(&t->t)) { + /* Need to resize. New table of double the size, add old elements to it. */ + if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) { + return false; + } + } + + key = strkey2(k, len); + tabkey = strcopy(key, a); + if (tabkey == 0) return false; + + hash = table_hash(key.str.str, key.str.len); + insert(&t->t, key, tabkey, v, hash, &strhash, &streql); + return true; +} + +bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len, + upb_value *v) { + uint32_t hash = table_hash(key, len); + return lookup(&t->t, strkey2(key, len), v, hash, &streql); +} + +bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len, + upb_value *val, upb_alloc *alloc) { + uint32_t hash = table_hash(key, len); + upb_tabkey tabkey; + if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) { + if (alloc) { + /* Arena-based allocs don't need to free and won't pass this. */ + upb_free(alloc, (void*)tabkey); + } + return true; + } else { + return false; + } +} + +/* Iteration */ + +void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) { + i->t = t; + i->index = begin(&t->t); +} + +void upb_strtable_next(upb_strtable_iter *i) { + i->index = next(&i->t->t, i->index); +} + +bool upb_strtable_done(const upb_strtable_iter *i) { + if (!i->t) return true; + return i->index >= upb_table_size(&i->t->t) || + upb_tabent_isempty(str_tabent(i)); +} + +upb_strview upb_strtable_iter_key(const upb_strtable_iter *i) { + upb_strview key; + uint32_t len; + UPB_ASSERT(!upb_strtable_done(i)); + key.data = upb_tabstr(str_tabent(i)->key, &len); + key.size = len; + return key; +} + +upb_value upb_strtable_iter_value(const upb_strtable_iter *i) { + UPB_ASSERT(!upb_strtable_done(i)); + return _upb_value_val(str_tabent(i)->val.val); +} + +void upb_strtable_iter_setdone(upb_strtable_iter *i) { + i->t = NULL; + i->index = SIZE_MAX; +} + +bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, + const upb_strtable_iter *i2) { + if (upb_strtable_done(i1) && upb_strtable_done(i2)) + return true; + return i1->t == i2->t && i1->index == i2->index; +} + + +/* upb_inttable ***************************************************************/ + +/* For inttables we use a hybrid structure where small keys are kept in an + * array and large keys are put in the hash table. */ + +static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); } + +static bool inteql(upb_tabkey k1, lookupkey_t k2) { + return k1 == k2.num; +} + +static upb_tabval *mutable_array(upb_inttable *t) { + return (upb_tabval*)t->array; +} + +static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) { + if (key < t->array_size) { + return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL; + } else { + upb_tabent *e = + findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql); + return e ? &e->val : NULL; + } +} + +static const upb_tabval *inttable_val_const(const upb_inttable *t, + uintptr_t key) { + return inttable_val((upb_inttable*)t, key); +} + +size_t upb_inttable_count(const upb_inttable *t) { + return t->t.count + t->array_count; +} + +static void check(upb_inttable *t) { + UPB_UNUSED(t); +#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG) + { + /* This check is very expensive (makes inserts/deletes O(N)). */ + size_t count = 0; + upb_inttable_iter i; + upb_inttable_begin(&i, t); + for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) { + UPB_ASSERT(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL)); + } + UPB_ASSERT(count == upb_inttable_count(t)); + } +#endif +} + +bool upb_inttable_sizedinit(upb_inttable *t, size_t asize, int hsize_lg2, + upb_alloc *a) { + size_t array_bytes; + + if (!init(&t->t, hsize_lg2, a)) return false; + /* Always make the array part at least 1 long, so that we know key 0 + * won't be in the hash part, which simplifies things. */ + t->array_size = UPB_MAX(1, asize); + t->array_count = 0; + array_bytes = t->array_size * sizeof(upb_value); + t->array = upb_malloc(a, array_bytes); + if (!t->array) { + uninit(&t->t, a); + return false; + } + memset(mutable_array(t), 0xff, array_bytes); + check(t); + return true; +} + +bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) { + UPB_UNUSED(ctype); /* TODO(haberman): rm */ + return upb_inttable_sizedinit(t, 0, 4, a); +} + +void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) { + uninit(&t->t, a); + upb_free(a, mutable_array(t)); +} + +bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, + upb_alloc *a) { + upb_tabval tabval; + tabval.val = val.val; + UPB_ASSERT(upb_arrhas(tabval)); /* This will reject (uint64_t)-1. Fix this. */ + + if (key < t->array_size) { + UPB_ASSERT(!upb_arrhas(t->array[key])); + t->array_count++; + mutable_array(t)[key].val = val.val; + } else { + if (isfull(&t->t)) { + /* Need to resize the hash part, but we re-use the array part. */ + size_t i; + upb_table new_table; + + if (!init(&new_table, t->t.size_lg2 + 1, a)) { + return false; + } + + for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) { + const upb_tabent *e = &t->t.entries[i]; + uint32_t hash; + upb_value v; + + _upb_value_setval(&v, e->val.val); + hash = upb_inthash(e->key); + insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql); + } + + UPB_ASSERT(t->t.count == new_table.count); + + uninit(&t->t, a); + t->t = new_table; + } + insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql); + } + check(t); + return true; +} + +bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) { + const upb_tabval *table_v = inttable_val_const(t, key); + if (!table_v) return false; + if (v) _upb_value_setval(v, table_v->val); + return true; +} + +bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) { + upb_tabval *table_v = inttable_val(t, key); + if (!table_v) return false; + table_v->val = val.val; + return true; +} + +bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) { + bool success; + if (key < t->array_size) { + if (upb_arrhas(t->array[key])) { + upb_tabval empty = UPB_TABVALUE_EMPTY_INIT; + t->array_count--; + if (val) { + _upb_value_setval(val, t->array[key].val); + } + mutable_array(t)[key] = empty; + success = true; + } else { + success = false; + } + } else { + success = rm(&t->t, intkey(key), val, NULL, upb_inthash(key), &inteql); + } + check(t); + return success; +} + +bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val, + upb_alloc *a) { + return upb_inttable_insert2(t, (uintptr_t)key, val, a); +} + +bool upb_inttable_lookupptr(const upb_inttable *t, const void *key, + upb_value *v) { + return upb_inttable_lookup(t, (uintptr_t)key, v); +} + +bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) { + return upb_inttable_remove(t, (uintptr_t)key, val); +} + +void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) { + /* A power-of-two histogram of the table keys. */ + size_t counts[UPB_MAXARRSIZE + 1] = {0}; + + /* The max key in each bucket. */ + uintptr_t max[UPB_MAXARRSIZE + 1] = {0}; + + upb_inttable_iter i; + size_t arr_count; + int size_lg2; + upb_inttable new_t; + + upb_inttable_begin(&i, t); + for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { + uintptr_t key = upb_inttable_iter_key(&i); + int bucket = log2ceil(key); + max[bucket] = UPB_MAX(max[bucket], key); + counts[bucket]++; + } + + /* Find the largest power of two that satisfies the MIN_DENSITY + * definition (while actually having some keys). */ + arr_count = upb_inttable_count(t); + + for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) { + if (counts[size_lg2] == 0) { + /* We can halve again without losing any entries. */ + continue; + } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) { + break; + } + + arr_count -= counts[size_lg2]; + } + + UPB_ASSERT(arr_count <= upb_inttable_count(t)); + + { + /* Insert all elements into new, perfectly-sized table. */ + size_t arr_size = max[size_lg2] + 1; /* +1 so arr[max] will fit. */ + size_t hash_count = upb_inttable_count(t) - arr_count; + size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0; + int hashsize_lg2 = log2ceil(hash_size); + + upb_inttable_sizedinit(&new_t, arr_size, hashsize_lg2, a); + upb_inttable_begin(&i, t); + for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { + uintptr_t k = upb_inttable_iter_key(&i); + upb_inttable_insert2(&new_t, k, upb_inttable_iter_value(&i), a); + } + UPB_ASSERT(new_t.array_size == arr_size); + UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2); + } + upb_inttable_uninit2(t, a); + *t = new_t; +} + +/* Iteration. */ + +static const upb_tabent *int_tabent(const upb_inttable_iter *i) { + UPB_ASSERT(!i->array_part); + return &i->t->t.entries[i->index]; +} + +static upb_tabval int_arrent(const upb_inttable_iter *i) { + UPB_ASSERT(i->array_part); + return i->t->array[i->index]; +} + +void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) { + i->t = t; + i->index = -1; + i->array_part = true; + upb_inttable_next(i); +} + +void upb_inttable_next(upb_inttable_iter *iter) { + const upb_inttable *t = iter->t; + if (iter->array_part) { + while (++iter->index < t->array_size) { + if (upb_arrhas(int_arrent(iter))) { + return; + } + } + iter->array_part = false; + iter->index = begin(&t->t); + } else { + iter->index = next(&t->t, iter->index); + } +} + +bool upb_inttable_done(const upb_inttable_iter *i) { + if (!i->t) return true; + if (i->array_part) { + return i->index >= i->t->array_size || + !upb_arrhas(int_arrent(i)); + } else { + return i->index >= upb_table_size(&i->t->t) || + upb_tabent_isempty(int_tabent(i)); + } +} + +uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) { + UPB_ASSERT(!upb_inttable_done(i)); + return i->array_part ? i->index : int_tabent(i)->key; +} + +upb_value upb_inttable_iter_value(const upb_inttable_iter *i) { + UPB_ASSERT(!upb_inttable_done(i)); + return _upb_value_val( + i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val); +} + +void upb_inttable_iter_setdone(upb_inttable_iter *i) { + i->t = NULL; + i->index = SIZE_MAX; + i->array_part = false; +} + +bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, + const upb_inttable_iter *i2) { + if (upb_inttable_done(i1) && upb_inttable_done(i2)) + return true; + return i1->t == i2->t && i1->index == i2->index && + i1->array_part == i2->array_part; +} + + +#include +#include +#include +#include +#include +#include +#include + + +/* upb_status *****************************************************************/ + +void upb_status_clear(upb_status *status) { + if (!status) return; + status->ok = true; + status->msg[0] = '\0'; +} + +bool upb_ok(const upb_status *status) { return status->ok; } + +const char *upb_status_errmsg(const upb_status *status) { return status->msg; } + +void upb_status_seterrmsg(upb_status *status, const char *msg) { + if (!status) return; + status->ok = false; + strncpy(status->msg, msg, UPB_STATUS_MAX_MESSAGE - 1); + status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0'; +} + +void upb_status_seterrf(upb_status *status, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + upb_status_vseterrf(status, fmt, args); + va_end(args); +} + +void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) { + if (!status) return; + status->ok = false; + vsnprintf(status->msg, sizeof(status->msg), fmt, args); + status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0'; +} + +void upb_status_vappenderrf(upb_status *status, const char *fmt, va_list args) { + size_t len; + if (!status) return; + status->ok = false; + len = strlen(status->msg); + vsnprintf(status->msg + len, sizeof(status->msg) - len, fmt, args); + status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0'; +} + +/* upb_alloc ******************************************************************/ + +static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize, + size_t size) { + UPB_UNUSED(alloc); + UPB_UNUSED(oldsize); + if (size == 0) { + free(ptr); + return NULL; + } else { + return realloc(ptr, size); + } +} + +upb_alloc upb_alloc_global = {&upb_global_allocfunc}; + +/* upb_arena ******************************************************************/ + +/* Be conservative and choose 16 in case anyone is using SSE. */ + +struct mem_block { + struct mem_block *next; + uint32_t size; + uint32_t cleanups; + /* Data follows. */ +}; + +typedef struct cleanup_ent { + upb_cleanup_func *cleanup; + void *ud; +} cleanup_ent; + +static const size_t memblock_reserve = UPB_ALIGN_UP(sizeof(mem_block), 16); + +static upb_arena *arena_findroot(upb_arena *a) { + /* Path splitting keeps time complexity down, see: + * https://en.wikipedia.org/wiki/Disjoint-set_data_structure */ + while (a->parent != a) { + upb_arena *next = a->parent; + a->parent = next->parent; + a = next; + } + return a; +} + +static void upb_arena_addblock(upb_arena *a, upb_arena *root, void *ptr, + size_t size) { + mem_block *block = ptr; + + /* The block is for arena |a|, but should appear in the freelist of |root|. */ + block->next = root->freelist; + block->size = (uint32_t)size; + block->cleanups = 0; + root->freelist = block; + a->last_size = block->size; + if (!root->freelist_tail) root->freelist_tail = block; + + a->head.ptr = UPB_PTR_AT(block, memblock_reserve, char); + a->head.end = UPB_PTR_AT(block, size, char); + a->cleanups = &block->cleanups; + + UPB_POISON_MEMORY_REGION(a->head.ptr, a->head.end - a->head.ptr); +} + +static bool upb_arena_allocblock(upb_arena *a, size_t size) { + upb_arena *root = arena_findroot(a); + size_t block_size = UPB_MAX(size, a->last_size * 2) + memblock_reserve; + mem_block *block = upb_malloc(root->block_alloc, block_size); + + if (!block) return false; + upb_arena_addblock(a, root, block, block_size); + return true; +} + +void *_upb_arena_slowmalloc(upb_arena *a, size_t size) { + if (!upb_arena_allocblock(a, size)) return NULL; /* Out of memory. */ + UPB_ASSERT(_upb_arenahas(a) >= size); + return upb_arena_malloc(a, size); +} + +static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize, + size_t size) { + upb_arena *a = (upb_arena*)alloc; /* upb_alloc is initial member. */ + return upb_arena_realloc(a, ptr, oldsize, size); +} + +/* Public Arena API ***********************************************************/ + +upb_arena *arena_initslow(void *mem, size_t n, upb_alloc *alloc) { + const size_t first_block_overhead = sizeof(upb_arena) + memblock_reserve; + upb_arena *a; + + /* We need to malloc the initial block. */ + n = first_block_overhead + 256; + if (!alloc || !(mem = upb_malloc(alloc, n))) { + return NULL; + } + + a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena); + n -= sizeof(*a); + + a->head.alloc.func = &upb_arena_doalloc; + a->block_alloc = alloc; + a->parent = a; + a->refcount = 1; + a->freelist = NULL; + a->freelist_tail = NULL; + + upb_arena_addblock(a, a, mem, n); + + return a; +} + +upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) { + upb_arena *a; + + /* Round block size down to alignof(*a) since we will allocate the arena + * itself at the end. */ + n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_arena)); + + if (UPB_UNLIKELY(n < sizeof(upb_arena))) { + return arena_initslow(mem, n, alloc); + } + + a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena); + + a->head.alloc.func = &upb_arena_doalloc; + a->block_alloc = alloc; + a->parent = a; + a->refcount = 1; + a->last_size = UPB_MAX(128, n); + a->head.ptr = mem; + a->head.end = UPB_PTR_AT(mem, n - sizeof(*a), char); + a->freelist = NULL; + a->cleanups = NULL; + + return a; +} + +static void arena_dofree(upb_arena *a) { + mem_block *block = a->freelist; + UPB_ASSERT(a->parent == a); + UPB_ASSERT(a->refcount == 0); + + while (block) { + /* Load first since we are deleting block. */ + mem_block *next = block->next; + + if (block->cleanups > 0) { + cleanup_ent *end = UPB_PTR_AT(block, block->size, void); + cleanup_ent *ptr = end - block->cleanups; + + for (; ptr < end; ptr++) { + ptr->cleanup(ptr->ud); + } + } + + upb_free(a->block_alloc, block); + block = next; + } +} + +void upb_arena_free(upb_arena *a) { + a = arena_findroot(a); + if (--a->refcount == 0) arena_dofree(a); +} + +bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) { + cleanup_ent *ent; + + if (!a->cleanups || _upb_arenahas(a) < sizeof(cleanup_ent)) { + if (!upb_arena_allocblock(a, 128)) return false; /* Out of memory. */ + UPB_ASSERT(_upb_arenahas(a) >= sizeof(cleanup_ent)); + } + + a->head.end -= sizeof(cleanup_ent); + ent = (cleanup_ent*)a->head.end; + (*a->cleanups)++; + UPB_UNPOISON_MEMORY_REGION(ent, sizeof(cleanup_ent)); + + ent->cleanup = func; + ent->ud = ud; + + return true; +} + +void upb_arena_fuse(upb_arena *a1, upb_arena *a2) { + upb_arena *r1 = arena_findroot(a1); + upb_arena *r2 = arena_findroot(a2); + + if (r1 == r2) return; /* Already fused. */ + + /* We want to join the smaller tree to the larger tree. + * So swap first if they are backwards. */ + if (r1->refcount < r2->refcount) { + upb_arena *tmp = r1; + r1 = r2; + r2 = tmp; + } + + /* r1 takes over r2's freelist and refcount. */ + r1->refcount += r2->refcount; + if (r2->freelist_tail) { + UPB_ASSERT(r2->freelist_tail->next == NULL); + r2->freelist_tail->next = r1->freelist; + r1->freelist = r2->freelist; + } + r2->parent = r1; +} +// Fast decoder: ~3x the speed of decode.c, but x86-64 specific. +// Also the table size grows by 2x. +// +// Could potentially be ported to ARM64 or other 64-bit archs that pass at +// least six arguments in registers. +// +// The overall design is to create specialized functions for every possible +// field type (eg. oneof boolean field with a 1 byte tag) and then dispatch +// to the specialized function as quickly as possible. + + + +/* Must be last. */ + +#if UPB_FASTTABLE + +// The standard set of arguments passed to each parsing function. +// Thanks to x86-64 calling conventions, these will stay in registers. +#define UPB_PARSE_PARAMS \ + upb_decstate *d, const char *ptr, upb_msg *msg, intptr_t table, \ + uint64_t hasbits, uint64_t data + +#define UPB_PARSE_ARGS d, ptr, msg, table, hasbits, data + +#define RETURN_GENERIC(m) \ + /* fprintf(stderr, m); */ \ + return fastdecode_generic(d, ptr, msg, table, hasbits, 0); + +typedef enum { + CARD_s = 0, /* Singular (optional, non-repeated) */ + CARD_o = 1, /* Oneof */ + CARD_r = 2, /* Repeated */ + CARD_p = 3 /* Packed Repeated */ +} upb_card; + +UPB_NOINLINE +static const char *fastdecode_isdonefallback(upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits, int overrun) { + ptr = decode_isdonefallback_inl(d, ptr, overrun); + if (ptr == NULL) { + return fastdecode_err(d); + } + uint16_t tag = fastdecode_loadtag(ptr); + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, tag); +} + +UPB_FORCEINLINE +static const char *fastdecode_dispatch(upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits) { + if (UPB_UNLIKELY(ptr >= d->limit_ptr)) { + int overrun = ptr - d->end; + if (UPB_LIKELY(overrun == d->limit)) { + // Parse is finished. + *(uint32_t*)msg |= hasbits; // Sync hasbits. + return ptr; + } else { + return fastdecode_isdonefallback(d, ptr, msg, table, hasbits, overrun); + } + } + + // Read two bytes of tag data (for a one-byte tag, the high byte is junk). + uint16_t tag = fastdecode_loadtag(ptr); + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, tag); +} + +UPB_FORCEINLINE +static bool fastdecode_checktag(uint64_t data, int tagbytes) { + if (tagbytes == 1) { + return (data & 0xff) == 0; + } else { + return (data & 0xffff) == 0; + } +} + +UPB_FORCEINLINE +static const char *fastdecode_longsize(const char *ptr, int *size) { + int i; + UPB_ASSERT(*size & 0x80); + *size &= 0xff; + for (i = 0; i < 3; i++) { + ptr++; + size_t byte = (uint8_t)ptr[-1]; + *size += (byte - 1) << (7 + 7 * i); + if (UPB_LIKELY((byte & 0x80) == 0)) return ptr; + } + ptr++; + size_t byte = (uint8_t)ptr[-1]; + // len is limited by 2gb not 4gb, hence 8 and not 16 as normally expected + // for a 32 bit varint. + if (UPB_UNLIKELY(byte >= 8)) return NULL; + *size += (byte - 1) << 28; + return ptr; +} + +UPB_FORCEINLINE +static bool fastdecode_boundscheck(const char *ptr, size_t len, + const char *end) { + uintptr_t uptr = (uintptr_t)ptr; + uintptr_t uend = (uintptr_t)end + 16; + uintptr_t res = uptr + len; + return res < uptr || res > uend; +} + +UPB_FORCEINLINE +static bool fastdecode_boundscheck2(const char *ptr, size_t len, + const char *end) { + // This is one extra branch compared to the more normal: + // return (size_t)(end - ptr) < size; + // However it is one less computation if we are just about to use "ptr + len": + // https://godbolt.org/z/35YGPz + // In microbenchmarks this shows an overall 4% improvement. + uintptr_t uptr = (uintptr_t)ptr; + uintptr_t uend = (uintptr_t)end; + uintptr_t res = uptr + len; + return res < uptr || res > uend; +} + +typedef const char *fastdecode_delimfunc(upb_decstate *d, const char *ptr, + void *ctx); + +UPB_FORCEINLINE +static const char *fastdecode_delimited(upb_decstate *d, const char *ptr, + fastdecode_delimfunc *func, void *ctx) { + ptr++; + int len = (int8_t)ptr[-1]; + if (fastdecode_boundscheck2(ptr, len, d->limit_ptr)) { + // Slow case: Sub-message is >=128 bytes and/or exceeds the current buffer. + // If it exceeds the buffer limit, limit/limit_ptr will change during + // sub-message parsing, so we need to preserve delta, not limit. + if (UPB_UNLIKELY(len & 0x80)) { + // Size varint >1 byte (length >= 128). + ptr = fastdecode_longsize(ptr, &len); + if (!ptr) { + // Corrupt wire format: size exceeded INT_MAX. + return NULL; + } + } + if (ptr - d->end + (int)len > d->limit) { + // Corrupt wire format: invalid limit. + return NULL; + } + int delta = decode_pushlimit(d, ptr, len); + ptr = func(d, ptr, ctx); + decode_poplimit(d, ptr, delta); + } else { + // Fast case: Sub-message is <128 bytes and fits in the current buffer. + // This means we can preserve limit/limit_ptr verbatim. + const char *saved_limit_ptr = d->limit_ptr; + int saved_limit = d->limit; + d->limit_ptr = ptr + len; + d->limit = d->limit_ptr - d->end; + UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit)); + ptr = func(d, ptr, ctx); + d->limit_ptr = saved_limit_ptr; + d->limit = saved_limit; + UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit)); + } + return ptr; +} + +/* singular, oneof, repeated field handling ***********************************/ + +typedef struct { + upb_array *arr; + void *end; +} fastdecode_arr; + +typedef enum { + FD_NEXT_ATLIMIT, + FD_NEXT_SAMEFIELD, + FD_NEXT_OTHERFIELD +} fastdecode_next; + +typedef struct { + void *dst; + fastdecode_next next; + uint32_t tag; +} fastdecode_nextret; + +UPB_FORCEINLINE +static void *fastdecode_resizearr(upb_decstate *d, void *dst, + fastdecode_arr *farr, int valbytes) { + if (UPB_UNLIKELY(dst == farr->end)) { + size_t old_size = farr->arr->size; + size_t old_bytes = old_size * valbytes; + size_t new_size = old_size * 2; + size_t new_bytes = new_size * valbytes; + char *old_ptr = _upb_array_ptr(farr->arr); + char *new_ptr = upb_arena_realloc(&d->arena, old_ptr, old_bytes, new_bytes); + uint8_t elem_size_lg2 = __builtin_ctz(valbytes); + farr->arr->size = new_size; + farr->arr->data = _upb_array_tagptr(new_ptr, elem_size_lg2); + dst = (void*)(new_ptr + (old_size * valbytes)); + farr->end = (void*)(new_ptr + (new_size * valbytes)); + } + return dst; +} + +UPB_FORCEINLINE +static bool fastdecode_tagmatch(uint32_t tag, uint64_t data, int tagbytes) { + if (tagbytes == 1) { + return (uint8_t)tag == (uint8_t)data; + } else { + return (uint16_t)tag == (uint16_t)data; + } +} + +UPB_FORCEINLINE +static void fastdecode_commitarr(void *dst, fastdecode_arr *farr, + int valbytes) { + farr->arr->len = + (size_t)((char *)dst - (char *)_upb_array_ptr(farr->arr)) / valbytes; +} + +UPB_FORCEINLINE +static fastdecode_nextret fastdecode_nextrepeated(upb_decstate *d, void *dst, + const char **ptr, + fastdecode_arr *farr, + uint64_t data, int tagbytes, + int valbytes) { + fastdecode_nextret ret; + dst = (char *)dst + valbytes; + + if (UPB_LIKELY(!decode_isdone(d, ptr))) { + ret.tag = fastdecode_loadtag(*ptr); + if (fastdecode_tagmatch(ret.tag, data, tagbytes)) { + ret.next = FD_NEXT_SAMEFIELD; + } else { + fastdecode_commitarr(dst, farr, valbytes); + ret.next = FD_NEXT_OTHERFIELD; + } + } else { + fastdecode_commitarr(dst, farr, valbytes); + ret.next = FD_NEXT_ATLIMIT; + } + + ret.dst = dst; + return ret; +} + +UPB_FORCEINLINE +static void *fastdecode_fieldmem(upb_msg *msg, uint64_t data) { + size_t ofs = data >> 48; + return (char *)msg + ofs; +} + +UPB_FORCEINLINE +static void *fastdecode_getfield(upb_decstate *d, const char *ptr, upb_msg *msg, + uint64_t *data, uint64_t *hasbits, + fastdecode_arr *farr, int valbytes, + upb_card card) { + switch (card) { + case CARD_s: { + uint8_t hasbit_index = *data >> 24; + // Set hasbit and return pointer to scalar field. + *hasbits |= 1ull << hasbit_index; + return fastdecode_fieldmem(msg, *data); + } + case CARD_o: { + uint16_t case_ofs = *data >> 32; + uint32_t *oneof_case = UPB_PTR_AT(msg, case_ofs, uint32_t); + uint8_t field_number = *data >> 24; + *oneof_case = field_number; + return fastdecode_fieldmem(msg, *data); + } + case CARD_r: { + // Get pointer to upb_array and allocate/expand if necessary. + uint8_t elem_size_lg2 = __builtin_ctz(valbytes); + upb_array **arr_p = fastdecode_fieldmem(msg, *data); + char *begin; + *(uint32_t*)msg |= *hasbits; + *hasbits = 0; + if (UPB_LIKELY(!*arr_p)) { + farr->arr = _upb_array_new(&d->arena, 8, elem_size_lg2); + *arr_p = farr->arr; + } else { + farr->arr = *arr_p; + } + begin = _upb_array_ptr(farr->arr); + farr->end = begin + (farr->arr->size * valbytes); + *data = fastdecode_loadtag(ptr); + return begin + (farr->arr->len * valbytes); + } + default: + UPB_UNREACHABLE(); + } +} + +UPB_FORCEINLINE +static bool fastdecode_flippacked(uint64_t *data, int tagbytes) { + *data ^= (0x2 ^ 0x0); // Patch data to match packed wiretype. + return fastdecode_checktag(*data, tagbytes); +} + +/* varint fields **************************************************************/ + +UPB_FORCEINLINE +static uint64_t fastdecode_munge(uint64_t val, int valbytes, bool zigzag) { + if (valbytes == 1) { + return val != 0; + } else if (zigzag) { + if (valbytes == 4) { + uint32_t n = val; + return (n >> 1) ^ -(int32_t)(n & 1); + } else if (valbytes == 8) { + return (val >> 1) ^ -(int64_t)(val & 1); + } + UPB_UNREACHABLE(); + } + return val; +} + +UPB_FORCEINLINE +static const char *fastdecode_varint64(const char *ptr, uint64_t *val) { + ptr++; + *val = (uint8_t)ptr[-1]; + if (UPB_UNLIKELY(*val & 0x80)) { + int i; + for (i = 0; i < 8; i++) { + ptr++; + uint64_t byte = (uint8_t)ptr[-1]; + *val += (byte - 1) << (7 + 7 * i); + if (UPB_LIKELY((byte & 0x80) == 0)) goto done; + } + ptr++; + uint64_t byte = (uint8_t)ptr[-1]; + if (byte > 1) { + return NULL; + } + *val += (byte - 1) << 63; + } +done: + UPB_ASSUME(ptr != NULL); + return ptr; +} + +UPB_FORCEINLINE +static const char *fastdecode_unpackedvarint(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, upb_card card, + bool zigzag, + _upb_field_parser *packed) { + uint64_t val; + void *dst; + fastdecode_arr farr; + + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) { + return packed(UPB_PARSE_ARGS); + } + RETURN_GENERIC("varint field tag mismatch\n"); + } + + dst = + fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, card); + if (card == CARD_r) { + if (UPB_UNLIKELY(!dst)) { + RETURN_GENERIC("need array resize\n"); + } + } + +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, valbytes); + } + + ptr += tagbytes; + ptr = fastdecode_varint64(ptr, &val); + if (ptr == NULL) return fastdecode_err(d); + val = fastdecode_munge(val, valbytes, zigzag); + memcpy(dst, &val, valbytes); + + if (card == CARD_r) { + fastdecode_nextret ret = + fastdecode_nextrepeated(d, dst, &ptr, &farr, data, tagbytes, valbytes); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + goto again; + case FD_NEXT_OTHERFIELD: + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + return ptr; + } + } + + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +typedef struct { + uint8_t valbytes; + bool zigzag; + void *dst; + fastdecode_arr farr; +} fastdecode_varintdata; + +UPB_FORCEINLINE +static const char *fastdecode_topackedvarint(upb_decstate *d, const char *ptr, + void *ctx) { + fastdecode_varintdata *data = ctx; + void *dst = data->dst; + uint64_t val; + + while (!decode_isdone(d, &ptr)) { + dst = fastdecode_resizearr(d, dst, &data->farr, data->valbytes); + ptr = fastdecode_varint64(ptr, &val); + if (ptr == NULL) return NULL; + val = fastdecode_munge(val, data->valbytes, data->zigzag); + memcpy(dst, &val, data->valbytes); + dst = (char *)dst + data->valbytes; + } + + fastdecode_commitarr(dst, &data->farr, data->valbytes); + return ptr; +} + +UPB_FORCEINLINE +static const char *fastdecode_packedvarint(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, bool zigzag, + _upb_field_parser *unpacked) { + fastdecode_varintdata ctx = {valbytes, zigzag}; + + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + if (fastdecode_flippacked(&data, tagbytes)) { + return unpacked(UPB_PARSE_ARGS); + } else { + RETURN_GENERIC("varint field tag mismatch\n"); + } + } + + ctx.dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &ctx.farr, + valbytes, CARD_r); + if (UPB_UNLIKELY(!ctx.dst)) { + RETURN_GENERIC("need array resize\n"); + } + + ptr += tagbytes; + ptr = fastdecode_delimited(d, ptr, &fastdecode_topackedvarint, &ctx); + + if (UPB_UNLIKELY(ptr == NULL)) { + return fastdecode_err(d); + } + + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +UPB_FORCEINLINE +static const char *fastdecode_varint(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, upb_card card, bool zigzag, + _upb_field_parser *unpacked, + _upb_field_parser *packed) { + if (card == CARD_p) { + return fastdecode_packedvarint(UPB_PARSE_ARGS, tagbytes, valbytes, zigzag, + unpacked); + } else { + return fastdecode_unpackedvarint(UPB_PARSE_ARGS, tagbytes, valbytes, card, + zigzag, packed); + } +} + +#define z_ZZ true +#define b_ZZ false +#define v_ZZ false + +/* Generate all combinations: + * {s,o,r,p} x {b1,v4,z4,v8,z8} x {1bt,2bt} */ + +#define F(card, type, valbytes, tagbytes) \ + UPB_NOINLINE \ + const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \ + return fastdecode_varint(UPB_PARSE_ARGS, tagbytes, valbytes, CARD_##card, \ + type##_ZZ, \ + &upb_pr##type##valbytes##_##tagbytes##bt, \ + &upb_pp##type##valbytes##_##tagbytes##bt); \ + } + +#define TYPES(card, tagbytes) \ + F(card, b, 1, tagbytes) \ + F(card, v, 4, tagbytes) \ + F(card, v, 8, tagbytes) \ + F(card, z, 4, tagbytes) \ + F(card, z, 8, tagbytes) + +#define TAGBYTES(card) \ + TYPES(card, 1) \ + TYPES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) +TAGBYTES(p) + +#undef z_ZZ +#undef b_ZZ +#undef v_ZZ +#undef o_ONEOF +#undef s_ONEOF +#undef r_ONEOF +#undef F +#undef TYPES +#undef TAGBYTES + + +/* fixed fields ***************************************************************/ + +UPB_FORCEINLINE +static const char *fastdecode_unpackedfixed(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, upb_card card, + _upb_field_parser *packed) { + void *dst; + fastdecode_arr farr; + + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) { + return packed(UPB_PARSE_ARGS); + } + RETURN_GENERIC("fixed field tag mismatch\n"); + } + + dst = + fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, card); + if (card == CARD_r) { + if (UPB_UNLIKELY(!dst)) { + RETURN_GENERIC("couldn't allocate array in arena\n"); + } + } + + +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, valbytes); + } + + ptr += tagbytes; + memcpy(dst, ptr, valbytes); + ptr += valbytes; + + if (card == CARD_r) { + fastdecode_nextret ret = + fastdecode_nextrepeated(d, dst, &ptr, &farr, data, tagbytes, valbytes); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + goto again; + case FD_NEXT_OTHERFIELD: + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + return ptr; + } + } + + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +UPB_FORCEINLINE +static const char *fastdecode_packedfixed(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, + _upb_field_parser *unpacked) { + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + if (fastdecode_flippacked(&data, tagbytes)) { + return unpacked(UPB_PARSE_ARGS); + } else { + RETURN_GENERIC("varint field tag mismatch\n"); + } + } + + ptr += tagbytes; + int size = (uint8_t)ptr[0]; + ptr++; + if (size & 0x80) { + ptr = fastdecode_longsize(ptr, &size); + } + + if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr)) || + (size % valbytes) != 0) { + return fastdecode_err(d); + } + + upb_array **arr_p = fastdecode_fieldmem(msg, data); + upb_array *arr = *arr_p; + uint8_t elem_size_lg2 = __builtin_ctz(valbytes); + int elems = size / valbytes; + + if (UPB_LIKELY(!arr)) { + *arr_p = arr = _upb_array_new(&d->arena, elems, elem_size_lg2); + if (!arr) { + return fastdecode_err(d); + } + } else { + _upb_array_resize(arr, elems, &d->arena); + } + + char *dst = _upb_array_ptr(arr); + memcpy(dst, ptr, size); + arr->len = elems; + + return fastdecode_dispatch(d, ptr + size, msg, table, hasbits); +} + +UPB_FORCEINLINE +static const char *fastdecode_fixed(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, upb_card card, + _upb_field_parser *unpacked, + _upb_field_parser *packed) { + if (card == CARD_p) { + return fastdecode_packedfixed(UPB_PARSE_ARGS, tagbytes, valbytes, unpacked); + } else { + return fastdecode_unpackedfixed(UPB_PARSE_ARGS, tagbytes, valbytes, card, + packed); + } +} + +/* Generate all combinations: + * {s,o,r,p} x {f4,f8} x {1bt,2bt} */ + +#define F(card, valbytes, tagbytes) \ + UPB_NOINLINE \ + const char *upb_p##card##f##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \ + return fastdecode_fixed(UPB_PARSE_ARGS, tagbytes, valbytes, CARD_##card, \ + &upb_ppf##valbytes##_##tagbytes##bt, \ + &upb_prf##valbytes##_##tagbytes##bt); \ + } + +#define TYPES(card, tagbytes) \ + F(card, 4, tagbytes) \ + F(card, 8, tagbytes) + +#define TAGBYTES(card) \ + TYPES(card, 1) \ + TYPES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) +TAGBYTES(p) + +#undef F +#undef TYPES +#undef TAGBYTES + +/* string fields **************************************************************/ + +typedef const char *fastdecode_copystr_func(struct upb_decstate *d, + const char *ptr, upb_msg *msg, + const upb_msglayout *table, + uint64_t hasbits, upb_strview *dst); + +UPB_NOINLINE +static const char *fastdecode_verifyutf8(upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits, upb_strview *dst) { + if (!decode_verifyutf8_inl(dst->data, dst->size)) { + return fastdecode_err(d); + } + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +UPB_FORCEINLINE +static const char *fastdecode_longstring(struct upb_decstate *d, + const char *ptr, upb_msg *msg, + intptr_t table, uint64_t hasbits, + upb_strview *dst, + bool validate_utf8) { + int size = (uint8_t)ptr[0]; // Could plumb through hasbits. + ptr++; + if (size & 0x80) { + ptr = fastdecode_longsize(ptr, &size); + } + + if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr))) { + dst->size = 0; + return fastdecode_err(d); + } + + if (d->alias) { + dst->data = ptr; + dst->size = size; + } else { + char *data = upb_arena_malloc(&d->arena, size); + if (!data) { + return fastdecode_err(d); + } + memcpy(data, ptr, size); + dst->data = data; + dst->size = size; + } + + if (validate_utf8) { + return fastdecode_verifyutf8(d, ptr + size, msg, table, hasbits, dst); + } else { + return fastdecode_dispatch(d, ptr + size, msg, table, hasbits); + } +} + +UPB_NOINLINE +static const char *fastdecode_longstring_utf8(struct upb_decstate *d, + const char *ptr, upb_msg *msg, + intptr_t table, uint64_t hasbits, + upb_strview *dst) { + return fastdecode_longstring(d, ptr, msg, table, hasbits, dst, true); +} + +UPB_NOINLINE +static const char *fastdecode_longstring_noutf8(struct upb_decstate *d, + const char *ptr, upb_msg *msg, + intptr_t table, + uint64_t hasbits, + upb_strview *dst) { + return fastdecode_longstring(d, ptr, msg, table, hasbits, dst, false); +} + +UPB_FORCEINLINE +static void fastdecode_docopy(upb_decstate *d, const char *ptr, uint32_t size, + int copy, char *data, upb_strview *dst) { + d->arena.head.ptr += copy; + dst->data = data; + UPB_UNPOISON_MEMORY_REGION(data, copy); + memcpy(data, ptr, copy); + UPB_POISON_MEMORY_REGION(data + size, copy - size); +} + +UPB_FORCEINLINE +static const char *fastdecode_copystring(UPB_PARSE_PARAMS, int tagbytes, + upb_card card, bool validate_utf8) { + upb_strview *dst; + fastdecode_arr farr; + int64_t size; + size_t arena_has; + size_t common_has; + char *buf; + + UPB_ASSERT(!d->alias); + UPB_ASSERT(fastdecode_checktag(data, tagbytes)); + + dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, + sizeof(upb_strview), card); + +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview)); + } + + size = (uint8_t)ptr[tagbytes]; + ptr += tagbytes + 1; + dst->size = size; + + buf = d->arena.head.ptr; + arena_has = _upb_arenahas(&d->arena); + common_has = UPB_MIN(arena_has, (d->end - ptr) + 16); + + if (UPB_LIKELY(size <= 15 - tagbytes)) { + if (arena_has < 16) goto longstr; + d->arena.head.ptr += 16; + memcpy(buf, ptr - tagbytes - 1, 16); + dst->data = buf + tagbytes + 1; + } else if (UPB_LIKELY(size <= 32)) { + if (UPB_UNLIKELY(common_has < 32)) goto longstr; + fastdecode_docopy(d, ptr, size, 32, buf, dst); + } else if (UPB_LIKELY(size <= 64)) { + if (UPB_UNLIKELY(common_has < 64)) goto longstr; + fastdecode_docopy(d, ptr, size, 64, buf, dst); + } else if (UPB_LIKELY(size < 128)) { + if (UPB_UNLIKELY(common_has < 128)) goto longstr; + fastdecode_docopy(d, ptr, size, 128, buf, dst); + } else { + goto longstr; + } + + ptr += size; + + if (card == CARD_r) { + if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) { + return fastdecode_err(d); + } + fastdecode_nextret ret = fastdecode_nextrepeated( + d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview)); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + goto again; + case FD_NEXT_OTHERFIELD: + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + return ptr; + } + } + + if (card != CARD_r && validate_utf8) { + return fastdecode_verifyutf8(d, ptr, msg, table, hasbits, dst); + } + + return fastdecode_dispatch(d, ptr, msg, table, hasbits); + +longstr: + ptr--; + if (validate_utf8) { + return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, dst); + } else { + return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, dst); + } +} + +UPB_FORCEINLINE +static const char *fastdecode_string(UPB_PARSE_PARAMS, int tagbytes, + upb_card card, _upb_field_parser *copyfunc, + bool validate_utf8) { + upb_strview *dst; + fastdecode_arr farr; + int64_t size; + + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + RETURN_GENERIC("string field tag mismatch\n"); + } + + if (UPB_UNLIKELY(!d->alias)) { + return copyfunc(UPB_PARSE_ARGS); + } + + dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, + sizeof(upb_strview), card); + +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview)); + } + + size = (int8_t)ptr[tagbytes]; + ptr += tagbytes + 1; + dst->data = ptr; + dst->size = size; + + if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->end))) { + ptr--; + if (validate_utf8) { + return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, dst); + } else { + return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, dst); + } + } + + ptr += size; + + if (card == CARD_r) { + if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) { + return fastdecode_err(d); + } + fastdecode_nextret ret = fastdecode_nextrepeated( + d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview)); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + if (UPB_UNLIKELY(!d->alias)) { + // Buffer flipped and we can't alias any more. Bounce to copyfunc(), + // but via dispatch since we need to reload table data also. + fastdecode_commitarr(dst, &farr, sizeof(upb_strview)); + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + } + goto again; + case FD_NEXT_OTHERFIELD: + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + return ptr; + } + } + + if (card != CARD_r && validate_utf8) { + return fastdecode_verifyutf8(d, ptr, msg, table, hasbits, dst); + } + + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +/* Generate all combinations: + * {p,c} x {s,o,r} x {s, b} x {1bt,2bt} */ + +#define s_VALIDATE true +#define b_VALIDATE false + +#define F(card, tagbytes, type) \ + UPB_NOINLINE \ + const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \ + return fastdecode_copystring(UPB_PARSE_ARGS, tagbytes, CARD_##card, \ + type##_VALIDATE); \ + } \ + const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \ + return fastdecode_string(UPB_PARSE_ARGS, tagbytes, CARD_##card, \ + &upb_c##card##type##_##tagbytes##bt, \ + type##_VALIDATE); \ + } + +#define UTF8(card, tagbytes) \ + F(card, tagbytes, s) \ + F(card, tagbytes, b) + +#define TAGBYTES(card) \ + UTF8(card, 1) \ + UTF8(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef s_VALIDATE +#undef b_VALIDATE +#undef F +#undef TAGBYTES + +/* message fields *************************************************************/ + +UPB_INLINE +upb_msg *decode_newmsg_ceil(upb_decstate *d, const upb_msglayout *l, + int msg_ceil_bytes) { + size_t size = l->size + sizeof(upb_msg_internal); + char *msg_data; + if (UPB_LIKELY(msg_ceil_bytes > 0 && + _upb_arenahas(&d->arena) >= msg_ceil_bytes)) { + UPB_ASSERT(size <= (size_t)msg_ceil_bytes); + msg_data = d->arena.head.ptr; + d->arena.head.ptr += size; + UPB_UNPOISON_MEMORY_REGION(msg_data, msg_ceil_bytes); + memset(msg_data, 0, msg_ceil_bytes); + UPB_POISON_MEMORY_REGION(msg_data + size, msg_ceil_bytes - size); + } else { + msg_data = (char*)upb_arena_malloc(&d->arena, size); + memset(msg_data, 0, size); + } + return msg_data + sizeof(upb_msg_internal); +} + +typedef struct { + intptr_t table; + upb_msg *msg; +} fastdecode_submsgdata; + +UPB_FORCEINLINE +static const char *fastdecode_tosubmsg(upb_decstate *d, const char *ptr, + void *ctx) { + fastdecode_submsgdata *submsg = ctx; + ptr = fastdecode_dispatch(d, ptr, submsg->msg, submsg->table, 0); + UPB_ASSUME(ptr != NULL); + return ptr; +} + +UPB_FORCEINLINE +static const char *fastdecode_submsg(UPB_PARSE_PARAMS, int tagbytes, + int msg_ceil_bytes, upb_card card) { + + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + RETURN_GENERIC("submessage field tag mismatch\n"); + } + + if (--d->depth == 0) return fastdecode_err(d); + + upb_msg **dst; + uint32_t submsg_idx = (data >> 16) & 0xff; + const upb_msglayout *tablep = decode_totablep(table); + const upb_msglayout *subtablep = tablep->submsgs[submsg_idx]; + fastdecode_submsgdata submsg = {decode_totable(subtablep)}; + fastdecode_arr farr; + + if (subtablep->table_mask == (uint8_t)-1) { + RETURN_GENERIC("submessage doesn't have fast tables."); + } + + dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, + sizeof(upb_msg *), card); + + if (card == CARD_s) { + *(uint32_t*)msg |= hasbits; + hasbits = 0; + } + +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_msg*)); + } + + submsg.msg = *dst; + + if (card == CARD_r || UPB_LIKELY(!submsg.msg)) { + *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes); + } + + ptr += tagbytes; + ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg); + + if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) { + return fastdecode_err(d); + } + + if (card == CARD_r) { + fastdecode_nextret ret = fastdecode_nextrepeated( + d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_msg *)); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + goto again; + case FD_NEXT_OTHERFIELD: + d->depth++; + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + d->depth++; + return ptr; + } + } + + d->depth++; + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +#define F(card, tagbytes, size_ceil, ceil_arg) \ + const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b( \ + UPB_PARSE_PARAMS) { \ + return fastdecode_submsg(UPB_PARSE_ARGS, tagbytes, ceil_arg, CARD_##card); \ + } + +#define SIZES(card, tagbytes) \ + F(card, tagbytes, 64, 64) \ + F(card, tagbytes, 128, 128) \ + F(card, tagbytes, 192, 192) \ + F(card, tagbytes, 256, 256) \ + F(card, tagbytes, max, -1) + +#define TAGBYTES(card) \ + SIZES(card, 1) \ + SIZES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef TAGBYTES +#undef SIZES +#undef F + +#endif /* UPB_FASTTABLE */ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include + + +static const upb_msglayout *const google_protobuf_FileDescriptorSet_submsgs[1] = { + &google_protobuf_FileDescriptorProto_msginit, +}; + +static const upb_msglayout_field google_protobuf_FileDescriptorSet__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_FileDescriptorSet_msginit = { + &google_protobuf_FileDescriptorSet_submsgs[0], + &google_protobuf_FileDescriptorSet__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] = { + &google_protobuf_DescriptorProto_msginit, + &google_protobuf_EnumDescriptorProto_msginit, + &google_protobuf_FieldDescriptorProto_msginit, + &google_protobuf_FileOptions_msginit, + &google_protobuf_ServiceDescriptorProto_msginit, + &google_protobuf_SourceCodeInfo_msginit, +}; + +static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12] = { + {1, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(12, 24), 2, 0, 12, 1}, + {3, UPB_SIZE(36, 72), 0, 0, 12, 3}, + {4, UPB_SIZE(40, 80), 0, 0, 11, 3}, + {5, UPB_SIZE(44, 88), 0, 1, 11, 3}, + {6, UPB_SIZE(48, 96), 0, 4, 11, 3}, + {7, UPB_SIZE(52, 104), 0, 2, 11, 3}, + {8, UPB_SIZE(28, 56), 3, 3, 11, 1}, + {9, UPB_SIZE(32, 64), 4, 5, 11, 1}, + {10, UPB_SIZE(56, 112), 0, 0, 5, 3}, + {11, UPB_SIZE(60, 120), 0, 0, 5, 3}, + {12, UPB_SIZE(20, 40), 5, 0, 12, 1}, +}; + +const upb_msglayout google_protobuf_FileDescriptorProto_msginit = { + &google_protobuf_FileDescriptorProto_submsgs[0], + &google_protobuf_FileDescriptorProto__fields[0], + UPB_SIZE(64, 128), 12, false, 255, +}; + +static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[7] = { + &google_protobuf_DescriptorProto_msginit, + &google_protobuf_DescriptorProto_ExtensionRange_msginit, + &google_protobuf_DescriptorProto_ReservedRange_msginit, + &google_protobuf_EnumDescriptorProto_msginit, + &google_protobuf_FieldDescriptorProto_msginit, + &google_protobuf_MessageOptions_msginit, + &google_protobuf_OneofDescriptorProto_msginit, +}; + +static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = { + {1, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(16, 32), 0, 4, 11, 3}, + {3, UPB_SIZE(20, 40), 0, 0, 11, 3}, + {4, UPB_SIZE(24, 48), 0, 3, 11, 3}, + {5, UPB_SIZE(28, 56), 0, 1, 11, 3}, + {6, UPB_SIZE(32, 64), 0, 4, 11, 3}, + {7, UPB_SIZE(12, 24), 2, 5, 11, 1}, + {8, UPB_SIZE(36, 72), 0, 6, 11, 3}, + {9, UPB_SIZE(40, 80), 0, 2, 11, 3}, + {10, UPB_SIZE(44, 88), 0, 0, 12, 3}, +}; + +const upb_msglayout google_protobuf_DescriptorProto_msginit = { + &google_protobuf_DescriptorProto_submsgs[0], + &google_protobuf_DescriptorProto__fields[0], + UPB_SIZE(48, 96), 10, false, 255, +}; + +static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = { + &google_protobuf_ExtensionRangeOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_DescriptorProto_ExtensionRange__fields[3] = { + {1, UPB_SIZE(4, 4), 1, 0, 5, 1}, + {2, UPB_SIZE(8, 8), 2, 0, 5, 1}, + {3, UPB_SIZE(12, 16), 3, 0, 11, 1}, +}; + +const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit = { + &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0], + &google_protobuf_DescriptorProto_ExtensionRange__fields[0], + UPB_SIZE(16, 24), 3, false, 255, +}; + +static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__fields[2] = { + {1, UPB_SIZE(4, 4), 1, 0, 5, 1}, + {2, UPB_SIZE(8, 8), 2, 0, 5, 1}, +}; + +const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit = { + NULL, + &google_protobuf_DescriptorProto_ReservedRange__fields[0], + UPB_SIZE(16, 16), 2, false, 255, +}; + +static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_ExtensionRangeOptions__fields[1] = { + {999, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit = { + &google_protobuf_ExtensionRangeOptions_submsgs[0], + &google_protobuf_ExtensionRangeOptions__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1] = { + &google_protobuf_FieldOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = { + {1, UPB_SIZE(24, 24), 1, 0, 12, 1}, + {2, UPB_SIZE(32, 40), 2, 0, 12, 1}, + {3, UPB_SIZE(12, 12), 3, 0, 5, 1}, + {4, UPB_SIZE(4, 4), 4, 0, 14, 1}, + {5, UPB_SIZE(8, 8), 5, 0, 14, 1}, + {6, UPB_SIZE(40, 56), 6, 0, 12, 1}, + {7, UPB_SIZE(48, 72), 7, 0, 12, 1}, + {8, UPB_SIZE(64, 104), 8, 0, 11, 1}, + {9, UPB_SIZE(16, 16), 9, 0, 5, 1}, + {10, UPB_SIZE(56, 88), 10, 0, 12, 1}, + {17, UPB_SIZE(20, 20), 11, 0, 8, 1}, +}; + +const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = { + &google_protobuf_FieldDescriptorProto_submsgs[0], + &google_protobuf_FieldDescriptorProto__fields[0], + UPB_SIZE(72, 112), 11, false, 255, +}; + +static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = { + &google_protobuf_OneofOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2] = { + {1, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(12, 24), 2, 0, 11, 1}, +}; + +const upb_msglayout google_protobuf_OneofDescriptorProto_msginit = { + &google_protobuf_OneofDescriptorProto_submsgs[0], + &google_protobuf_OneofDescriptorProto__fields[0], + UPB_SIZE(16, 32), 2, false, 255, +}; + +static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] = { + &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, + &google_protobuf_EnumOptions_msginit, + &google_protobuf_EnumValueDescriptorProto_msginit, +}; + +static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5] = { + {1, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(16, 32), 0, 2, 11, 3}, + {3, UPB_SIZE(12, 24), 2, 1, 11, 1}, + {4, UPB_SIZE(20, 40), 0, 0, 11, 3}, + {5, UPB_SIZE(24, 48), 0, 0, 12, 3}, +}; + +const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = { + &google_protobuf_EnumDescriptorProto_submsgs[0], + &google_protobuf_EnumDescriptorProto__fields[0], + UPB_SIZE(32, 64), 5, false, 255, +}; + +static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = { + {1, UPB_SIZE(4, 4), 1, 0, 5, 1}, + {2, UPB_SIZE(8, 8), 2, 0, 5, 1}, +}; + +const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = { + NULL, + &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0], + UPB_SIZE(16, 16), 2, false, 255, +}; + +static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_submsgs[1] = { + &google_protobuf_EnumValueOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__fields[3] = { + {1, UPB_SIZE(8, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(4, 4), 2, 0, 5, 1}, + {3, UPB_SIZE(16, 24), 3, 0, 11, 1}, +}; + +const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit = { + &google_protobuf_EnumValueDescriptorProto_submsgs[0], + &google_protobuf_EnumValueDescriptorProto__fields[0], + UPB_SIZE(24, 32), 3, false, 255, +}; + +static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs[2] = { + &google_protobuf_MethodDescriptorProto_msginit, + &google_protobuf_ServiceOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[3] = { + {1, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(16, 32), 0, 0, 11, 3}, + {3, UPB_SIZE(12, 24), 2, 1, 11, 1}, +}; + +const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit = { + &google_protobuf_ServiceDescriptorProto_submsgs[0], + &google_protobuf_ServiceDescriptorProto__fields[0], + UPB_SIZE(24, 48), 3, false, 255, +}; + +static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[1] = { + &google_protobuf_MethodOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_MethodDescriptorProto__fields[6] = { + {1, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(12, 24), 2, 0, 12, 1}, + {3, UPB_SIZE(20, 40), 3, 0, 12, 1}, + {4, UPB_SIZE(28, 56), 4, 0, 11, 1}, + {5, UPB_SIZE(1, 1), 5, 0, 8, 1}, + {6, UPB_SIZE(2, 2), 6, 0, 8, 1}, +}; + +const upb_msglayout google_protobuf_MethodDescriptorProto_msginit = { + &google_protobuf_MethodDescriptorProto_submsgs[0], + &google_protobuf_MethodDescriptorProto__fields[0], + UPB_SIZE(32, 64), 6, false, 255, +}; + +static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = { + {1, UPB_SIZE(20, 24), 1, 0, 12, 1}, + {8, UPB_SIZE(28, 40), 2, 0, 12, 1}, + {9, UPB_SIZE(4, 4), 3, 0, 14, 1}, + {10, UPB_SIZE(8, 8), 4, 0, 8, 1}, + {11, UPB_SIZE(36, 56), 5, 0, 12, 1}, + {16, UPB_SIZE(9, 9), 6, 0, 8, 1}, + {17, UPB_SIZE(10, 10), 7, 0, 8, 1}, + {18, UPB_SIZE(11, 11), 8, 0, 8, 1}, + {20, UPB_SIZE(12, 12), 9, 0, 8, 1}, + {23, UPB_SIZE(13, 13), 10, 0, 8, 1}, + {27, UPB_SIZE(14, 14), 11, 0, 8, 1}, + {31, UPB_SIZE(15, 15), 12, 0, 8, 1}, + {36, UPB_SIZE(44, 72), 13, 0, 12, 1}, + {37, UPB_SIZE(52, 88), 14, 0, 12, 1}, + {39, UPB_SIZE(60, 104), 15, 0, 12, 1}, + {40, UPB_SIZE(68, 120), 16, 0, 12, 1}, + {41, UPB_SIZE(76, 136), 17, 0, 12, 1}, + {42, UPB_SIZE(16, 16), 18, 0, 8, 1}, + {44, UPB_SIZE(84, 152), 19, 0, 12, 1}, + {45, UPB_SIZE(92, 168), 20, 0, 12, 1}, + {999, UPB_SIZE(100, 184), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_FileOptions_msginit = { + &google_protobuf_FileOptions_submsgs[0], + &google_protobuf_FileOptions__fields[0], + UPB_SIZE(104, 192), 21, false, 255, +}; + +static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_MessageOptions__fields[5] = { + {1, UPB_SIZE(1, 1), 1, 0, 8, 1}, + {2, UPB_SIZE(2, 2), 2, 0, 8, 1}, + {3, UPB_SIZE(3, 3), 3, 0, 8, 1}, + {7, UPB_SIZE(4, 4), 4, 0, 8, 1}, + {999, UPB_SIZE(8, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_MessageOptions_msginit = { + &google_protobuf_MessageOptions_submsgs[0], + &google_protobuf_MessageOptions__fields[0], + UPB_SIZE(16, 16), 5, false, 255, +}; + +static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_FieldOptions__fields[7] = { + {1, UPB_SIZE(4, 4), 1, 0, 14, 1}, + {2, UPB_SIZE(12, 12), 2, 0, 8, 1}, + {3, UPB_SIZE(13, 13), 3, 0, 8, 1}, + {5, UPB_SIZE(14, 14), 4, 0, 8, 1}, + {6, UPB_SIZE(8, 8), 5, 0, 14, 1}, + {10, UPB_SIZE(15, 15), 6, 0, 8, 1}, + {999, UPB_SIZE(16, 16), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_FieldOptions_msginit = { + &google_protobuf_FieldOptions_submsgs[0], + &google_protobuf_FieldOptions__fields[0], + UPB_SIZE(24, 24), 7, false, 255, +}; + +static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_OneofOptions__fields[1] = { + {999, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_OneofOptions_msginit = { + &google_protobuf_OneofOptions_submsgs[0], + &google_protobuf_OneofOptions__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_EnumOptions__fields[3] = { + {2, UPB_SIZE(1, 1), 1, 0, 8, 1}, + {3, UPB_SIZE(2, 2), 2, 0, 8, 1}, + {999, UPB_SIZE(4, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_EnumOptions_msginit = { + &google_protobuf_EnumOptions_submsgs[0], + &google_protobuf_EnumOptions__fields[0], + UPB_SIZE(8, 16), 3, false, 255, +}; + +static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_EnumValueOptions__fields[2] = { + {1, UPB_SIZE(1, 1), 1, 0, 8, 1}, + {999, UPB_SIZE(4, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_EnumValueOptions_msginit = { + &google_protobuf_EnumValueOptions_submsgs[0], + &google_protobuf_EnumValueOptions__fields[0], + UPB_SIZE(8, 16), 2, false, 255, +}; + +static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_ServiceOptions__fields[2] = { + {33, UPB_SIZE(1, 1), 1, 0, 8, 1}, + {999, UPB_SIZE(4, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_ServiceOptions_msginit = { + &google_protobuf_ServiceOptions_submsgs[0], + &google_protobuf_ServiceOptions__fields[0], + UPB_SIZE(8, 16), 2, false, 255, +}; + +static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_MethodOptions__fields[3] = { + {33, UPB_SIZE(8, 8), 1, 0, 8, 1}, + {34, UPB_SIZE(4, 4), 2, 0, 14, 1}, + {999, UPB_SIZE(12, 16), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_MethodOptions_msginit = { + &google_protobuf_MethodOptions_submsgs[0], + &google_protobuf_MethodOptions__fields[0], + UPB_SIZE(16, 24), 3, false, 255, +}; + +static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] = { + &google_protobuf_UninterpretedOption_NamePart_msginit, +}; + +static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7] = { + {2, UPB_SIZE(56, 80), 0, 0, 11, 3}, + {3, UPB_SIZE(32, 32), 1, 0, 12, 1}, + {4, UPB_SIZE(8, 8), 2, 0, 4, 1}, + {5, UPB_SIZE(16, 16), 3, 0, 3, 1}, + {6, UPB_SIZE(24, 24), 4, 0, 1, 1}, + {7, UPB_SIZE(40, 48), 5, 0, 12, 1}, + {8, UPB_SIZE(48, 64), 6, 0, 12, 1}, +}; + +const upb_msglayout google_protobuf_UninterpretedOption_msginit = { + &google_protobuf_UninterpretedOption_submsgs[0], + &google_protobuf_UninterpretedOption__fields[0], + UPB_SIZE(64, 96), 7, false, 255, +}; + +static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = { + {1, UPB_SIZE(4, 8), 1, 0, 12, 2}, + {2, UPB_SIZE(1, 1), 2, 0, 8, 2}, +}; + +const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit = { + NULL, + &google_protobuf_UninterpretedOption_NamePart__fields[0], + UPB_SIZE(16, 32), 2, false, 255, +}; + +static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = { + &google_protobuf_SourceCodeInfo_Location_msginit, +}; + +static const upb_msglayout_field google_protobuf_SourceCodeInfo__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_SourceCodeInfo_msginit = { + &google_protobuf_SourceCodeInfo_submsgs[0], + &google_protobuf_SourceCodeInfo__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = { + {1, UPB_SIZE(20, 40), 0, 0, 5, _UPB_LABEL_PACKED}, + {2, UPB_SIZE(24, 48), 0, 0, 5, _UPB_LABEL_PACKED}, + {3, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {4, UPB_SIZE(12, 24), 2, 0, 12, 1}, + {6, UPB_SIZE(28, 56), 0, 0, 12, 3}, +}; + +const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = { + NULL, + &google_protobuf_SourceCodeInfo_Location__fields[0], + UPB_SIZE(32, 64), 5, false, 255, +}; + +static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] = { + &google_protobuf_GeneratedCodeInfo_Annotation_msginit, +}; + +static const upb_msglayout_field google_protobuf_GeneratedCodeInfo__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = { + &google_protobuf_GeneratedCodeInfo_submsgs[0], + &google_protobuf_GeneratedCodeInfo__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = { + {1, UPB_SIZE(20, 32), 0, 0, 5, _UPB_LABEL_PACKED}, + {2, UPB_SIZE(12, 16), 1, 0, 12, 1}, + {3, UPB_SIZE(4, 4), 2, 0, 5, 1}, + {4, UPB_SIZE(8, 8), 3, 0, 5, 1}, +}; + +const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit = { + NULL, + &google_protobuf_GeneratedCodeInfo_Annotation__fields[0], + UPB_SIZE(24, 48), 4, false, 255, +}; + + +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + + +extern const upb_msglayout google_protobuf_FileDescriptorSet_msginit; +extern const upb_msglayout google_protobuf_FileDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_DescriptorProto_msginit; +extern const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit; +extern const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit; +extern const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit; +extern const upb_msglayout google_protobuf_FieldDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_OneofDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_EnumDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit; +extern const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_MethodDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_FileOptions_msginit; +extern const upb_msglayout google_protobuf_MessageOptions_msginit; +extern const upb_msglayout google_protobuf_FieldOptions_msginit; +extern const upb_msglayout google_protobuf_OneofOptions_msginit; +extern const upb_msglayout google_protobuf_EnumOptions_msginit; +extern const upb_msglayout google_protobuf_EnumValueOptions_msginit; +extern const upb_msglayout google_protobuf_ServiceOptions_msginit; +extern const upb_msglayout google_protobuf_MethodOptions_msginit; +extern const upb_msglayout google_protobuf_UninterpretedOption_msginit; +extern const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit; +extern const upb_msglayout google_protobuf_SourceCodeInfo_msginit; +extern const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit; +extern const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit; +extern const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit; + +static const upb_msglayout *layouts[27] = { + &google_protobuf_FileDescriptorSet_msginit, + &google_protobuf_FileDescriptorProto_msginit, + &google_protobuf_DescriptorProto_msginit, + &google_protobuf_DescriptorProto_ExtensionRange_msginit, + &google_protobuf_DescriptorProto_ReservedRange_msginit, + &google_protobuf_ExtensionRangeOptions_msginit, + &google_protobuf_FieldDescriptorProto_msginit, + &google_protobuf_OneofDescriptorProto_msginit, + &google_protobuf_EnumDescriptorProto_msginit, + &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, + &google_protobuf_EnumValueDescriptorProto_msginit, + &google_protobuf_ServiceDescriptorProto_msginit, + &google_protobuf_MethodDescriptorProto_msginit, + &google_protobuf_FileOptions_msginit, + &google_protobuf_MessageOptions_msginit, + &google_protobuf_FieldOptions_msginit, + &google_protobuf_OneofOptions_msginit, + &google_protobuf_EnumOptions_msginit, + &google_protobuf_EnumValueOptions_msginit, + &google_protobuf_ServiceOptions_msginit, + &google_protobuf_MethodOptions_msginit, + &google_protobuf_UninterpretedOption_msginit, + &google_protobuf_UninterpretedOption_NamePart_msginit, + &google_protobuf_SourceCodeInfo_msginit, + &google_protobuf_SourceCodeInfo_Location_msginit, + &google_protobuf_GeneratedCodeInfo_msginit, + &google_protobuf_GeneratedCodeInfo_Annotation_msginit, +}; + +static const char descriptor[7601] = {'\n', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', +'t', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '\"', 'M', '\n', '\021', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'S', 'e', 't', '\022', '8', '\n', +'\004', 'f', 'i', 'l', 'e', '\030', '\001', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', +'o', 'b', 'u', 'f', '.', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', +'\004', 'f', 'i', 'l', 'e', '\"', '\344', '\004', '\n', '\023', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', +'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', +'\030', '\n', '\007', 'p', 'a', 'c', 'k', 'a', 'g', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\007', 'p', 'a', 'c', 'k', 'a', 'g', 'e', +'\022', '\036', '\n', '\n', 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\030', '\003', ' ', '\003', '(', '\t', 'R', '\n', 'd', 'e', 'p', +'e', 'n', 'd', 'e', 'n', 'c', 'y', '\022', '+', '\n', '\021', 'p', 'u', 'b', 'l', 'i', 'c', '_', 'd', 'e', 'p', 'e', 'n', 'd', 'e', +'n', 'c', 'y', '\030', '\n', ' ', '\003', '(', '\005', 'R', '\020', 'p', 'u', 'b', 'l', 'i', 'c', 'D', 'e', 'p', 'e', 'n', 'd', 'e', 'n', +'c', 'y', '\022', '\'', '\n', '\017', 'w', 'e', 'a', 'k', '_', 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\030', '\013', ' ', '\003', +'(', '\005', 'R', '\016', 'w', 'e', 'a', 'k', 'D', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\022', 'C', '\n', '\014', 'm', 'e', 's', +'s', 'a', 'g', 'e', '_', 't', 'y', 'p', 'e', '\030', '\004', ' ', '\003', '(', '\013', '2', ' ', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', +'\013', 'm', 'e', 's', 's', 'a', 'g', 'e', 'T', 'y', 'p', 'e', '\022', 'A', '\n', '\t', 'e', 'n', 'u', 'm', '_', 't', 'y', 'p', 'e', +'\030', '\005', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'E', 'n', 'u', 'm', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\010', 'e', 'n', 'u', 'm', +'T', 'y', 'p', 'e', '\022', 'A', '\n', '\007', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\030', '\006', ' ', '\003', '(', '\013', '2', '\'', '.', 'g', +'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'D', 'e', 's', +'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\007', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\022', 'C', '\n', '\t', +'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\007', ' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', +'r', 'o', 't', 'o', 'R', '\t', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\022', '6', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', +'s', '\030', '\010', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', +'.', 'F', 'i', 'l', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', 'I', '\n', '\020', +'s', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'd', 'e', '_', 'i', 'n', 'f', 'o', '\030', '\t', ' ', '\001', '(', '\013', '2', '\037', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'd', +'e', 'I', 'n', 'f', 'o', 'R', '\016', 's', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', '\026', '\n', '\006', +'s', 'y', 'n', 't', 'a', 'x', '\030', '\014', ' ', '\001', '(', '\t', 'R', '\006', 's', 'y', 'n', 't', 'a', 'x', '\"', '\271', '\006', '\n', '\017', +'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', +' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', ';', '\n', '\005', 'f', 'i', 'e', 'l', 'd', '\030', '\002', ' ', '\003', '(', '\013', +'2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', +'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\005', 'f', 'i', 'e', 'l', 'd', '\022', 'C', '\n', '\t', +'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\006', ' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', +'r', 'o', 't', 'o', 'R', '\t', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\022', 'A', '\n', '\013', 'n', 'e', 's', 't', 'e', 'd', +'_', 't', 'y', 'p', 'e', '\030', '\003', ' ', '\003', '(', '\013', '2', ' ', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', +'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\n', 'n', 'e', 's', +'t', 'e', 'd', 'T', 'y', 'p', 'e', '\022', 'A', '\n', '\t', 'e', 'n', 'u', 'm', '_', 't', 'y', 'p', 'e', '\030', '\004', ' ', '\003', '(', +'\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'D', +'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\010', 'e', 'n', 'u', 'm', 'T', 'y', 'p', 'e', '\022', +'X', '\n', '\017', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\005', ' ', '\003', '(', '\013', '2', +'/', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', +'t', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 'R', '\016', +'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', '\022', 'D', '\n', '\n', 'o', 'n', 'e', 'o', 'f', '_', 'd', +'e', 'c', 'l', '\030', '\010', ' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', +'u', 'f', '.', 'O', 'n', 'e', 'o', 'f', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\t', +'o', 'n', 'e', 'o', 'f', 'D', 'e', 'c', 'l', '\022', '9', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\007', ' ', '\001', '(', +'\013', '2', '\037', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 's', 's', 'a', +'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', 'U', '\n', '\016', 'r', 'e', 's', +'e', 'r', 'v', 'e', 'd', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\t', ' ', '\003', '(', '\013', '2', '.', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', +'o', '.', 'R', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', 'R', '\r', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', +'R', 'a', 'n', 'g', 'e', '\022', '#', '\n', '\r', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'n', 'a', 'm', 'e', '\030', '\n', ' ', +'\003', '(', '\t', 'R', '\014', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'N', 'a', 'm', 'e', '\032', 'z', '\n', '\016', 'E', 'x', 't', 'e', +'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', '\022', '\024', '\n', '\005', 's', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', '(', '\005', +'R', '\005', 's', 't', 'a', 'r', 't', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', +'\022', '@', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '&', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', +'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\032', '7', '\n', '\r', 'R', 'e', 's', 'e', 'r', +'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', '\022', '\024', '\n', '\005', 's', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', '(', '\005', 'R', '\005', +'s', 't', 'a', 'r', 't', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', '\"', '|', +'\n', '\025', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'X', +'\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', +' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', +'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', +'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', +'\301', '\006', '\n', '\024', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', +'\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\026', '\n', '\006', 'n', 'u', +'m', 'b', 'e', 'r', '\030', '\003', ' ', '\001', '(', '\005', 'R', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\022', 'A', '\n', '\005', 'l', 'a', 'b', +'e', 'l', '\030', '\004', ' ', '\001', '(', '\016', '2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'L', 'a', +'b', 'e', 'l', 'R', '\005', 'l', 'a', 'b', 'e', 'l', '\022', '>', '\n', '\004', 't', 'y', 'p', 'e', '\030', '\005', ' ', '\001', '(', '\016', '2', +'*', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', +'s', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'T', 'y', 'p', 'e', 'R', '\004', 't', 'y', 'p', 'e', '\022', +'\033', '\n', '\t', 't', 'y', 'p', 'e', '_', 'n', 'a', 'm', 'e', '\030', '\006', ' ', '\001', '(', '\t', 'R', '\010', 't', 'y', 'p', 'e', 'N', +'a', 'm', 'e', '\022', '\032', '\n', '\010', 'e', 'x', 't', 'e', 'n', 'd', 'e', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\010', 'e', 'x', +'t', 'e', 'n', 'd', 'e', 'e', '\022', '#', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\007', +' ', '\001', '(', '\t', 'R', '\014', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'V', 'a', 'l', 'u', 'e', '\022', '\037', '\n', '\013', 'o', 'n', 'e', +'o', 'f', '_', 'i', 'n', 'd', 'e', 'x', '\030', '\t', ' ', '\001', '(', '\005', 'R', '\n', 'o', 'n', 'e', 'o', 'f', 'I', 'n', 'd', 'e', +'x', '\022', '\033', '\n', '\t', 'j', 's', 'o', 'n', '_', 'n', 'a', 'm', 'e', '\030', '\n', ' ', '\001', '(', '\t', 'R', '\010', 'j', 's', 'o', +'n', 'N', 'a', 'm', 'e', '\022', '7', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\010', ' ', '\001', '(', '\013', '2', '\035', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', +'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', '\'', '\n', '\017', 'p', 'r', 'o', 't', 'o', '3', '_', 'o', 'p', +'t', 'i', 'o', 'n', 'a', 'l', '\030', '\021', ' ', '\001', '(', '\010', 'R', '\016', 'p', 'r', 'o', 't', 'o', '3', 'O', 'p', 't', 'i', 'o', +'n', 'a', 'l', '\"', '\266', '\002', '\n', '\004', 'T', 'y', 'p', 'e', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'D', 'O', 'U', 'B', +'L', 'E', '\020', '\001', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'F', 'L', 'O', 'A', 'T', '\020', '\002', '\022', '\016', '\n', '\n', 'T', +'Y', 'P', 'E', '_', 'I', 'N', 'T', '6', '4', '\020', '\003', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', '6', +'4', '\020', '\004', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'I', 'N', 'T', '3', '2', '\020', '\005', '\022', '\020', '\n', '\014', 'T', 'Y', +'P', 'E', '_', 'F', 'I', 'X', 'E', 'D', '6', '4', '\020', '\006', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'F', 'I', 'X', 'E', +'D', '3', '2', '\020', '\007', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', 'E', '_', 'B', 'O', 'O', 'L', '\020', '\010', '\022', '\017', '\n', '\013', 'T', +'Y', 'P', 'E', '_', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\t', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'G', 'R', 'O', 'U', +'P', '\020', '\n', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'M', 'E', 'S', 'S', 'A', 'G', 'E', '\020', '\013', '\022', '\016', '\n', '\n', +'T', 'Y', 'P', 'E', '_', 'B', 'Y', 'T', 'E', 'S', '\020', '\014', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', +'3', '2', '\020', '\r', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', 'E', '_', 'E', 'N', 'U', 'M', '\020', '\016', '\022', '\021', '\n', '\r', 'T', 'Y', +'P', 'E', '_', 'S', 'F', 'I', 'X', 'E', 'D', '3', '2', '\020', '\017', '\022', '\021', '\n', '\r', 'T', 'Y', 'P', 'E', '_', 'S', 'F', 'I', +'X', 'E', 'D', '6', '4', '\020', '\020', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '3', '2', '\020', '\021', '\022', +'\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '6', '4', '\020', '\022', '\"', 'C', '\n', '\005', 'L', 'a', 'b', 'e', 'l', +'\022', '\022', '\n', '\016', 'L', 'A', 'B', 'E', 'L', '_', 'O', 'P', 'T', 'I', 'O', 'N', 'A', 'L', '\020', '\001', '\022', '\022', '\n', '\016', 'L', +'A', 'B', 'E', 'L', '_', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D', '\020', '\002', '\022', '\022', '\n', '\016', 'L', 'A', 'B', 'E', 'L', '_', +'R', 'E', 'P', 'E', 'A', 'T', 'E', 'D', '\020', '\003', '\"', 'c', '\n', '\024', 'O', 'n', 'e', 'o', 'f', 'D', 'e', 's', 'c', 'r', 'i', +'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', +'n', 'a', 'm', 'e', '\022', '7', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '\035', '.', 'g', +'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'n', 'e', 'o', 'f', 'O', 'p', 't', 'i', 'o', +'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\"', '\343', '\002', '\n', '\023', 'E', 'n', 'u', 'm', 'D', 'e', 's', 'c', 'r', +'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', +'\004', 'n', 'a', 'm', 'e', '\022', '?', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\003', '(', '\013', '2', ')', '.', 'g', 'o', +'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'D', 'e', +'s', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\005', 'v', 'a', 'l', 'u', 'e', '\022', '6', '\n', '\007', 'o', +'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', +'t', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', +'s', '\022', ']', '\n', '\016', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\004', ' ', '\003', '(', '\013', +'2', '6', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'D', 'e', +'s', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'E', 'n', 'u', 'm', 'R', 'e', 's', 'e', 'r', 'v', 'e', +'d', 'R', 'a', 'n', 'g', 'e', 'R', '\r', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', '\022', '#', '\n', '\r', +'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'n', 'a', 'm', 'e', '\030', '\005', ' ', '\003', '(', '\t', 'R', '\014', 'r', 'e', 's', 'e', +'r', 'v', 'e', 'd', 'N', 'a', 'm', 'e', '\032', ';', '\n', '\021', 'E', 'n', 'u', 'm', 'R', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', +'a', 'n', 'g', 'e', '\022', '\024', '\n', '\005', 's', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', '(', '\005', 'R', '\005', 's', 't', 'a', 'r', +'t', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', '\"', '\203', '\001', '\n', '\030', 'E', +'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', +'\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\026', '\n', '\006', 'n', 'u', 'm', +'b', 'e', 'r', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\022', ';', '\n', '\007', 'o', 'p', 't', 'i', +'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '!', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', +'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', +'o', 'n', 's', '\"', '\247', '\001', '\n', '\026', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', +'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', +'\022', '>', '\n', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\030', '\002', ' ', '\003', '(', '\013', '2', '&', '.', 'g', 'o', 'o', 'g', 'l', 'e', +'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 't', 'h', 'o', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', +'r', 'P', 'r', 'o', 't', 'o', 'R', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\022', '9', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', +'\030', '\003', ' ', '\001', '(', '\013', '2', '\037', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'S', 'e', 'r', 'v', 'i', 'c', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\"', '\211', +'\002', '\n', '\025', 'M', 'e', 't', 'h', 'o', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', +'\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\035', '\n', '\n', 'i', 'n', +'p', 'u', 't', '_', 't', 'y', 'p', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\t', 'i', 'n', 'p', 'u', 't', 'T', 'y', 'p', 'e', +'\022', '\037', '\n', '\013', 'o', 'u', 't', 'p', 'u', 't', '_', 't', 'y', 'p', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\n', 'o', 'u', +'t', 'p', 'u', 't', 'T', 'y', 'p', 'e', '\022', '8', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\004', ' ', '\001', '(', '\013', +'2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 't', 'h', 'o', 'd', +'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', '0', '\n', '\020', 'c', 'l', 'i', 'e', 'n', +'t', '_', 's', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\030', '\005', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', +'\017', 'c', 'l', 'i', 'e', 'n', 't', 'S', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\022', '0', '\n', '\020', 's', 'e', 'r', 'v', 'e', +'r', '_', 's', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\030', '\006', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', +'\017', 's', 'e', 'r', 'v', 'e', 'r', 'S', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\"', '\221', '\t', '\n', '\013', 'F', 'i', 'l', 'e', +'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '!', '\n', '\014', 'j', 'a', 'v', 'a', '_', 'p', 'a', 'c', 'k', 'a', 'g', 'e', '\030', '\001', +' ', '\001', '(', '\t', 'R', '\013', 'j', 'a', 'v', 'a', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\022', '0', '\n', '\024', 'j', 'a', 'v', 'a', +'_', 'o', 'u', 't', 'e', 'r', '_', 'c', 'l', 'a', 's', 's', 'n', 'a', 'm', 'e', '\030', '\010', ' ', '\001', '(', '\t', 'R', '\022', 'j', +'a', 'v', 'a', 'O', 'u', 't', 'e', 'r', 'C', 'l', 'a', 's', 's', 'n', 'a', 'm', 'e', '\022', '5', '\n', '\023', 'j', 'a', 'v', 'a', +'_', 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', '_', 'f', 'i', 'l', 'e', 's', '\030', '\n', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', +'l', 's', 'e', 'R', '\021', 'j', 'a', 'v', 'a', 'M', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'F', 'i', 'l', 'e', 's', '\022', 'D', '\n', +'\035', 'j', 'a', 'v', 'a', '_', 'g', 'e', 'n', 'e', 'r', 'a', 't', 'e', '_', 'e', 'q', 'u', 'a', 'l', 's', '_', 'a', 'n', 'd', +'_', 'h', 'a', 's', 'h', '\030', '\024', ' ', '\001', '(', '\010', 'B', '\002', '\030', '\001', 'R', '\031', 'j', 'a', 'v', 'a', 'G', 'e', 'n', 'e', +'r', 'a', 't', 'e', 'E', 'q', 'u', 'a', 'l', 's', 'A', 'n', 'd', 'H', 'a', 's', 'h', '\022', ':', '\n', '\026', 'j', 'a', 'v', 'a', +'_', 's', 't', 'r', 'i', 'n', 'g', '_', 'c', 'h', 'e', 'c', 'k', '_', 'u', 't', 'f', '8', '\030', '\033', ' ', '\001', '(', '\010', ':', +'\005', 'f', 'a', 'l', 's', 'e', 'R', '\023', 'j', 'a', 'v', 'a', 'S', 't', 'r', 'i', 'n', 'g', 'C', 'h', 'e', 'c', 'k', 'U', 't', +'f', '8', '\022', 'S', '\n', '\014', 'o', 'p', 't', 'i', 'm', 'i', 'z', 'e', '_', 'f', 'o', 'r', '\030', '\t', ' ', '\001', '(', '\016', '2', +')', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'l', 'e', 'O', 'p', 't', +'i', 'o', 'n', 's', '.', 'O', 'p', 't', 'i', 'm', 'i', 'z', 'e', 'M', 'o', 'd', 'e', ':', '\005', 'S', 'P', 'E', 'E', 'D', 'R', +'\013', 'o', 'p', 't', 'i', 'm', 'i', 'z', 'e', 'F', 'o', 'r', '\022', '\035', '\n', '\n', 'g', 'o', '_', 'p', 'a', 'c', 'k', 'a', 'g', +'e', '\030', '\013', ' ', '\001', '(', '\t', 'R', '\t', 'g', 'o', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\022', '5', '\n', '\023', 'c', 'c', '_', +'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\030', '\020', ' ', '\001', '(', '\010', ':', '\005', 'f', +'a', 'l', 's', 'e', 'R', '\021', 'c', 'c', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '9', +'\n', '\025', 'j', 'a', 'v', 'a', '_', 'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\030', '\021', +' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\023', 'j', 'a', 'v', 'a', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'S', +'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '5', '\n', '\023', 'p', 'y', '_', 'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 's', 'e', 'r', +'v', 'i', 'c', 'e', 's', '\030', '\022', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\021', 'p', 'y', 'G', 'e', 'n', +'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '7', '\n', '\024', 'p', 'h', 'p', '_', 'g', 'e', 'n', 'e', 'r', +'i', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\030', '*', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', +'\022', 'p', 'h', 'p', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '%', '\n', '\n', 'd', 'e', +'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\027', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', +'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '.', '\n', '\020', 'c', 'c', '_', 'e', 'n', 'a', 'b', 'l', 'e', '_', 'a', 'r', 'e', +'n', 'a', 's', '\030', '\037', ' ', '\001', '(', '\010', ':', '\004', 't', 'r', 'u', 'e', 'R', '\016', 'c', 'c', 'E', 'n', 'a', 'b', 'l', 'e', +'A', 'r', 'e', 'n', 'a', 's', '\022', '*', '\n', '\021', 'o', 'b', 'j', 'c', '_', 'c', 'l', 'a', 's', 's', '_', 'p', 'r', 'e', 'f', +'i', 'x', '\030', '$', ' ', '\001', '(', '\t', 'R', '\017', 'o', 'b', 'j', 'c', 'C', 'l', 'a', 's', 's', 'P', 'r', 'e', 'f', 'i', 'x', +'\022', ')', '\n', '\020', 'c', 's', 'h', 'a', 'r', 'p', '_', 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\030', '%', ' ', '\001', '(', +'\t', 'R', '\017', 'c', 's', 'h', 'a', 'r', 'p', 'N', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\022', '!', '\n', '\014', 's', 'w', 'i', +'f', 't', '_', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '\'', ' ', '\001', '(', '\t', 'R', '\013', 's', 'w', 'i', 'f', 't', 'P', 'r', 'e', +'f', 'i', 'x', '\022', '(', '\n', '\020', 'p', 'h', 'p', '_', 'c', 'l', 'a', 's', 's', '_', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '(', +' ', '\001', '(', '\t', 'R', '\016', 'p', 'h', 'p', 'C', 'l', 'a', 's', 's', 'P', 'r', 'e', 'f', 'i', 'x', '\022', '#', '\n', '\r', 'p', +'h', 'p', '_', 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\030', ')', ' ', '\001', '(', '\t', 'R', '\014', 'p', 'h', 'p', 'N', 'a', +'m', 'e', 's', 'p', 'a', 'c', 'e', '\022', '4', '\n', '\026', 'p', 'h', 'p', '_', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '_', 'n', +'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\030', ',', ' ', '\001', '(', '\t', 'R', '\024', 'p', 'h', 'p', 'M', 'e', 't', 'a', 'd', 'a', +'t', 'a', 'N', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\022', '!', '\n', '\014', 'r', 'u', 'b', 'y', '_', 'p', 'a', 'c', 'k', 'a', +'g', 'e', '\030', '-', ' ', '\001', '(', '\t', 'R', '\013', 'r', 'u', 'b', 'y', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\022', 'X', '\n', '\024', +'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', +'(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', +'t', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', +'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\"', ':', '\n', '\014', 'O', 'p', 't', 'i', 'm', 'i', 'z', 'e', 'M', 'o', +'d', 'e', '\022', '\t', '\n', '\005', 'S', 'P', 'E', 'E', 'D', '\020', '\001', '\022', '\r', '\n', '\t', 'C', 'O', 'D', 'E', '_', 'S', 'I', 'Z', +'E', '\020', '\002', '\022', '\020', '\n', '\014', 'L', 'I', 'T', 'E', '_', 'R', 'U', 'N', 'T', 'I', 'M', 'E', '\020', '\003', '*', '\t', '\010', '\350', +'\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '&', '\020', '\'', '\"', '\321', '\002', '\n', '\016', 'M', 'e', 's', 's', 'a', 'g', 'e', +'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '<', '\n', '\027', 'm', 'e', 's', 's', 'a', 'g', 'e', '_', 's', 'e', 't', '_', 'w', 'i', +'r', 'e', '_', 'f', 'o', 'r', 'm', 'a', 't', '\030', '\001', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\024', 'm', +'e', 's', 's', 'a', 'g', 'e', 'S', 'e', 't', 'W', 'i', 'r', 'e', 'F', 'o', 'r', 'm', 'a', 't', '\022', 'L', '\n', '\037', 'n', 'o', +'_', 's', 't', 'a', 'n', 'd', 'a', 'r', 'd', '_', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'a', 'c', 'c', 'e', +'s', 's', 'o', 'r', '\030', '\002', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\034', 'n', 'o', 'S', 't', 'a', 'n', +'d', 'a', 'r', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'A', 'c', 'c', 'e', 's', 's', 'o', 'r', '\022', '%', '\n', +'\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', +'\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '\033', '\n', '\t', 'm', 'a', 'p', '_', 'e', 'n', 't', 'r', 'y', '\030', +'\007', ' ', '\001', '(', '\010', 'R', '\010', 'm', 'a', 'p', 'E', 'n', 't', 'r', 'y', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', +'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', +'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', +'t', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', +'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '\010', '\020', '\t', 'J', '\004', '\010', +'\t', '\020', '\n', '\"', '\342', '\003', '\n', '\014', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'A', '\n', '\005', 'c', +'t', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', '\016', '2', '#', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', +'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'C', 'T', 'y', 'p', 'e', ':', '\006', 'S', +'T', 'R', 'I', 'N', 'G', 'R', '\005', 'c', 't', 'y', 'p', 'e', '\022', '\026', '\n', '\006', 'p', 'a', 'c', 'k', 'e', 'd', '\030', '\002', ' ', +'\001', '(', '\010', 'R', '\006', 'p', 'a', 'c', 'k', 'e', 'd', '\022', 'G', '\n', '\006', 'j', 's', 't', 'y', 'p', 'e', '\030', '\006', ' ', '\001', +'(', '\016', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', +'d', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'J', 'S', 'T', 'y', 'p', 'e', ':', '\t', 'J', 'S', '_', 'N', 'O', 'R', 'M', 'A', +'L', 'R', '\006', 'j', 's', 't', 'y', 'p', 'e', '\022', '\031', '\n', '\004', 'l', 'a', 'z', 'y', '\030', '\005', ' ', '\001', '(', '\010', ':', '\005', +'f', 'a', 'l', 's', 'e', 'R', '\004', 'l', 'a', 'z', 'y', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', +'\030', '\003', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', +'\022', '\031', '\n', '\004', 'w', 'e', 'a', 'k', '\030', '\n', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\004', 'w', 'e', +'a', 'k', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', +'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', +'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\"', '/', '\n', '\005', 'C', 'T', 'y', 'p', +'e', '\022', '\n', '\n', '\006', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\000', '\022', '\010', '\n', '\004', 'C', 'O', 'R', 'D', '\020', '\001', '\022', '\020', +'\n', '\014', 'S', 'T', 'R', 'I', 'N', 'G', '_', 'P', 'I', 'E', 'C', 'E', '\020', '\002', '\"', '5', '\n', '\006', 'J', 'S', 'T', 'y', 'p', +'e', '\022', '\r', '\n', '\t', 'J', 'S', '_', 'N', 'O', 'R', 'M', 'A', 'L', '\020', '\000', '\022', '\r', '\n', '\t', 'J', 'S', '_', 'S', 'T', +'R', 'I', 'N', 'G', '\020', '\001', '\022', '\r', '\n', '\t', 'J', 'S', '_', 'N', 'U', 'M', 'B', 'E', 'R', '\020', '\002', '*', '\t', '\010', '\350', +'\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '\004', '\020', '\005', '\"', 's', '\n', '\014', 'O', 'n', 'e', 'o', 'f', 'O', 'p', 't', +'i', 'o', 'n', 's', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', +'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', +'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', +'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', +'\200', '\200', '\200', '\200', '\002', '\"', '\300', '\001', '\n', '\013', 'E', 'n', 'u', 'm', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '\037', '\n', '\013', +'a', 'l', 'l', 'o', 'w', '_', 'a', 'l', 'i', 'a', 's', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\n', 'a', 'l', 'l', 'o', 'w', 'A', +'l', 'i', 'a', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', '(', '\010', ':', +'\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', 'X', '\n', '\024', 'u', 'n', 'i', +'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', +'$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', +'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', +'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '\005', '\020', '\006', +'\"', '\236', '\001', '\n', '\020', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '%', '\n', '\n', +'d', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\001', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', +'d', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', +'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', +'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', +'t', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', +'*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', '\234', '\001', '\n', '\016', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'O', 'p', +'t', 'i', 'o', 'n', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '!', ' ', '\001', '(', '\010', +':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', 'X', '\n', '\024', 'u', 'n', +'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', +'2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', +'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', +'t', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', '\340', '\002', '\n', '\r', +'M', 'e', 't', 'h', 'o', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', +'e', 'd', '\030', '!', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', +'e', 'd', '\022', 'q', '\n', '\021', 'i', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', '_', 'l', 'e', 'v', 'e', 'l', '\030', '\"', +' ', '\001', '(', '\016', '2', '/', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', +'t', 'h', 'o', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'I', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', 'L', 'e', +'v', 'e', 'l', ':', '\023', 'I', 'D', 'E', 'M', 'P', 'O', 'T', 'E', 'N', 'C', 'Y', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', 'R', +'\020', 'i', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', 'L', 'e', 'v', 'e', 'l', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', +'t', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', +'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', +'d', 'O', 'p', 't', 'i', 'o', 'n', '\"', 'P', '\n', '\020', 'I', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', 'L', 'e', 'v', +'e', 'l', '\022', '\027', '\n', '\023', 'I', 'D', 'E', 'M', 'P', 'O', 'T', 'E', 'N', 'C', 'Y', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', +'\020', '\000', '\022', '\023', '\n', '\017', 'N', 'O', '_', 'S', 'I', 'D', 'E', '_', 'E', 'F', 'F', 'E', 'C', 'T', 'S', '\020', '\001', '\022', '\016', +'\n', '\n', 'I', 'D', 'E', 'M', 'P', 'O', 'T', 'E', 'N', 'T', '\020', '\002', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', +'\"', '\232', '\003', '\n', '\023', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\022', +'A', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\003', '(', '\013', '2', '-', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', +'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', +'n', '.', 'N', 'a', 'm', 'e', 'P', 'a', 'r', 't', 'R', '\004', 'n', 'a', 'm', 'e', '\022', ')', '\n', '\020', 'i', 'd', 'e', 'n', 't', +'i', 'f', 'i', 'e', 'r', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\017', 'i', 'd', 'e', 'n', 't', 'i', +'f', 'i', 'e', 'r', 'V', 'a', 'l', 'u', 'e', '\022', ',', '\n', '\022', 'p', 'o', 's', 'i', 't', 'i', 'v', 'e', '_', 'i', 'n', 't', +'_', 'v', 'a', 'l', 'u', 'e', '\030', '\004', ' ', '\001', '(', '\004', 'R', '\020', 'p', 'o', 's', 'i', 't', 'i', 'v', 'e', 'I', 'n', 't', +'V', 'a', 'l', 'u', 'e', '\022', ',', '\n', '\022', 'n', 'e', 'g', 'a', 't', 'i', 'v', 'e', '_', 'i', 'n', 't', '_', 'v', 'a', 'l', +'u', 'e', '\030', '\005', ' ', '\001', '(', '\003', 'R', '\020', 'n', 'e', 'g', 'a', 't', 'i', 'v', 'e', 'I', 'n', 't', 'V', 'a', 'l', 'u', +'e', '\022', '!', '\n', '\014', 'd', 'o', 'u', 'b', 'l', 'e', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\006', ' ', '\001', '(', '\001', 'R', '\013', +'d', 'o', 'u', 'b', 'l', 'e', 'V', 'a', 'l', 'u', 'e', '\022', '!', '\n', '\014', 's', 't', 'r', 'i', 'n', 'g', '_', 'v', 'a', 'l', +'u', 'e', '\030', '\007', ' ', '\001', '(', '\014', 'R', '\013', 's', 't', 'r', 'i', 'n', 'g', 'V', 'a', 'l', 'u', 'e', '\022', '\'', '\n', '\017', +'a', 'g', 'g', 'r', 'e', 'g', 'a', 't', 'e', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\010', ' ', '\001', '(', '\t', 'R', '\016', 'a', 'g', +'g', 'r', 'e', 'g', 'a', 't', 'e', 'V', 'a', 'l', 'u', 'e', '\032', 'J', '\n', '\010', 'N', 'a', 'm', 'e', 'P', 'a', 'r', 't', '\022', +'\033', '\n', '\t', 'n', 'a', 'm', 'e', '_', 'p', 'a', 'r', 't', '\030', '\001', ' ', '\002', '(', '\t', 'R', '\010', 'n', 'a', 'm', 'e', 'P', +'a', 'r', 't', '\022', '!', '\n', '\014', 'i', 's', '_', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\002', ' ', '\002', '(', '\010', +'R', '\013', 'i', 's', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\"', '\247', '\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', '\"', '\321', '\001', '\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', 'm', '\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', '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_def_init *deps[1] = { + NULL +}; + +upb_def_init google_protobuf_descriptor_proto_upbdefinit = { + deps, + layouts, + "google/protobuf/descriptor.proto", + UPB_STRVIEW_INIT(descriptor, 7601) +}; + + +#include +#include +#include +#include +#include + + +/* Must be last. */ + +typedef struct { + size_t len; + char str[1]; /* Null-terminated string data follows. */ +} str_t; + +struct upb_fielddef { + const upb_filedef *file; + const upb_msgdef *msgdef; + const char *full_name; + const char *json_name; + union { + int64_t sint; + uint64_t uint; + double dbl; + float flt; + bool boolean; + str_t *str; + } defaultval; + const upb_oneofdef *oneof; + union { + const upb_msgdef *msgdef; + const upb_enumdef *enumdef; + const google_protobuf_FieldDescriptorProto *unresolved; + } sub; + uint32_t number_; + uint16_t index_; + uint16_t layout_index; + uint32_t selector_base; /* Used to index into a upb::Handlers table. */ + bool is_extension_; + bool lazy_; + bool packed_; + bool proto3_optional_; + upb_descriptortype_t type_; + upb_label_t label_; +}; + +struct upb_msgdef { + const upb_msglayout *layout; + const upb_filedef *file; + const char *full_name; + uint32_t selector_count; + uint32_t submsg_field_count; + + /* Tables for looking up fields by number and name. */ + upb_inttable itof; + upb_strtable ntof; + + const upb_fielddef *fields; + const upb_oneofdef *oneofs; + int field_count; + int oneof_count; + int real_oneof_count; + + /* Is this a map-entry message? */ + bool map_entry; + upb_wellknowntype_t well_known_type; + + /* TODO(haberman): proper extension ranges (there can be multiple). */ +}; + +struct upb_enumdef { + const upb_filedef *file; + const char *full_name; + upb_strtable ntoi; + upb_inttable iton; + int32_t defaultval; +}; + +struct upb_oneofdef { + const upb_msgdef *parent; + const char *full_name; + int field_count; + bool synthetic; + const upb_fielddef **fields; + upb_strtable ntof; + upb_inttable itof; +}; + +struct upb_filedef { + const char *name; + const char *package; + const char *phpprefix; + const char *phpnamespace; + + const upb_filedef **deps; + const upb_msgdef *msgs; + const upb_enumdef *enums; + const upb_fielddef *exts; + const upb_symtab *symtab; + + int dep_count; + int msg_count; + int enum_count; + int ext_count; + upb_syntax_t syntax; +}; + +struct upb_symtab { + upb_arena *arena; + upb_strtable syms; /* full_name -> packed def ptr */ + upb_strtable files; /* file_name -> upb_filedef* */ + size_t bytes_loaded; +}; + +/* Inside a symtab we store tagged pointers to specific def types. */ +typedef enum { + UPB_DEFTYPE_FIELD = 0, + + /* Only inside symtab table. */ + UPB_DEFTYPE_MSG = 1, + UPB_DEFTYPE_ENUM = 2, + + /* Only inside message table. */ + UPB_DEFTYPE_ONEOF = 1, + UPB_DEFTYPE_FIELD_JSONNAME = 2 +} upb_deftype_t; + +static const void *unpack_def(upb_value v, upb_deftype_t type) { + uintptr_t num = (uintptr_t)upb_value_getconstptr(v); + return (num & 3) == type ? (const void*)(num & ~3) : NULL; +} + +static upb_value pack_def(const void *ptr, upb_deftype_t type) { + uintptr_t num = (uintptr_t)ptr | type; + return upb_value_constptr((const void*)num); +} + +/* isalpha() etc. from are locale-dependent, which we don't want. */ +static bool upb_isbetween(char c, char low, char high) { + return c >= low && c <= high; +} + +static bool upb_isletter(char c) { + return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_'; +} + +static bool upb_isalphanum(char c) { + return upb_isletter(c) || upb_isbetween(c, '0', '9'); +} + +static const char *shortdefname(const char *fullname) { + const char *p; + + if (fullname == NULL) { + return NULL; + } else if ((p = strrchr(fullname, '.')) == NULL) { + /* No '.' in the name, return the full string. */ + return fullname; + } else { + /* Return one past the last '.'. */ + return p + 1; + } +} + +/* All submessage fields are lower than all other fields. + * Secondly, fields are increasing in order. */ +uint32_t field_rank(const upb_fielddef *f) { + uint32_t ret = upb_fielddef_number(f); + const uint32_t high_bit = 1 << 30; + UPB_ASSERT(ret < high_bit); + if (!upb_fielddef_issubmsg(f)) + ret |= high_bit; + return ret; +} + +int cmp_fields(const void *p1, const void *p2) { + const upb_fielddef *f1 = *(upb_fielddef*const*)p1; + const upb_fielddef *f2 = *(upb_fielddef*const*)p2; + return field_rank(f1) - field_rank(f2); +} + +/* A few implementation details of handlers. We put these here to avoid + * a def -> handlers dependency. */ + +#define UPB_STATIC_SELECTOR_COUNT 3 /* Warning: also in upb/handlers.h. */ + +static uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) { + return upb_fielddef_isseq(f) ? 2 : 0; +} + +static uint32_t upb_handlers_selectorcount(const upb_fielddef *f) { + uint32_t ret = 1; + if (upb_fielddef_isseq(f)) ret += 2; /* STARTSEQ/ENDSEQ */ + if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */ + if (upb_fielddef_issubmsg(f)) { + /* ENDSUBMSG (STARTSUBMSG is at table beginning) */ + ret += 0; + if (upb_fielddef_lazy(f)) { + /* STARTSTR/ENDSTR/STRING (for lazy) */ + ret += 3; + } + } + return ret; +} + +static void upb_status_setoom(upb_status *status) { + upb_status_seterrmsg(status, "out of memory"); +} + +static void assign_msg_wellknowntype(upb_msgdef *m) { + const char *name = upb_msgdef_fullname(m); + if (name == NULL) { + m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED; + return; + } + if (!strcmp(name, "google.protobuf.Any")) { + m->well_known_type = UPB_WELLKNOWN_ANY; + } else if (!strcmp(name, "google.protobuf.FieldMask")) { + m->well_known_type = UPB_WELLKNOWN_FIELDMASK; + } else if (!strcmp(name, "google.protobuf.Duration")) { + m->well_known_type = UPB_WELLKNOWN_DURATION; + } else if (!strcmp(name, "google.protobuf.Timestamp")) { + m->well_known_type = UPB_WELLKNOWN_TIMESTAMP; + } else if (!strcmp(name, "google.protobuf.DoubleValue")) { + m->well_known_type = UPB_WELLKNOWN_DOUBLEVALUE; + } else if (!strcmp(name, "google.protobuf.FloatValue")) { + m->well_known_type = UPB_WELLKNOWN_FLOATVALUE; + } else if (!strcmp(name, "google.protobuf.Int64Value")) { + m->well_known_type = UPB_WELLKNOWN_INT64VALUE; + } else if (!strcmp(name, "google.protobuf.UInt64Value")) { + m->well_known_type = UPB_WELLKNOWN_UINT64VALUE; + } else if (!strcmp(name, "google.protobuf.Int32Value")) { + m->well_known_type = UPB_WELLKNOWN_INT32VALUE; + } else if (!strcmp(name, "google.protobuf.UInt32Value")) { + m->well_known_type = UPB_WELLKNOWN_UINT32VALUE; + } else if (!strcmp(name, "google.protobuf.BoolValue")) { + m->well_known_type = UPB_WELLKNOWN_BOOLVALUE; + } else if (!strcmp(name, "google.protobuf.StringValue")) { + m->well_known_type = UPB_WELLKNOWN_STRINGVALUE; + } else if (!strcmp(name, "google.protobuf.BytesValue")) { + m->well_known_type = UPB_WELLKNOWN_BYTESVALUE; + } else if (!strcmp(name, "google.protobuf.Value")) { + m->well_known_type = UPB_WELLKNOWN_VALUE; + } else if (!strcmp(name, "google.protobuf.ListValue")) { + m->well_known_type = UPB_WELLKNOWN_LISTVALUE; + } else if (!strcmp(name, "google.protobuf.Struct")) { + m->well_known_type = UPB_WELLKNOWN_STRUCT; + } else { + m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED; + } +} + + +/* upb_enumdef ****************************************************************/ + +const char *upb_enumdef_fullname(const upb_enumdef *e) { + return e->full_name; +} + +const char *upb_enumdef_name(const upb_enumdef *e) { + return shortdefname(e->full_name); +} + +const upb_filedef *upb_enumdef_file(const upb_enumdef *e) { + return e->file; +} + +int32_t upb_enumdef_default(const upb_enumdef *e) { + UPB_ASSERT(upb_enumdef_iton(e, e->defaultval)); + return e->defaultval; +} + +int upb_enumdef_numvals(const upb_enumdef *e) { + return (int)upb_strtable_count(&e->ntoi); +} + +void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) { + /* We iterate over the ntoi table, to account for duplicate numbers. */ + upb_strtable_begin(i, &e->ntoi); +} + +void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); } +bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); } + +bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name, + size_t len, int32_t *num) { + upb_value v; + if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) { + return false; + } + if (num) *num = upb_value_getint32(v); + return true; +} + +const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) { + upb_value v; + return upb_inttable_lookup32(&def->iton, num, &v) ? + upb_value_getcstr(v) : NULL; +} + +const char *upb_enum_iter_name(upb_enum_iter *iter) { + return upb_strtable_iter_key(iter).data; +} + +int32_t upb_enum_iter_number(upb_enum_iter *iter) { + return upb_value_getint32(upb_strtable_iter_value(iter)); +} + + +/* upb_fielddef ***************************************************************/ + +const char *upb_fielddef_fullname(const upb_fielddef *f) { + return f->full_name; +} + +upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) { + switch (f->type_) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + return UPB_TYPE_DOUBLE; + case UPB_DESCRIPTOR_TYPE_FLOAT: + return UPB_TYPE_FLOAT; + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_SINT64: + case UPB_DESCRIPTOR_TYPE_SFIXED64: + return UPB_TYPE_INT64; + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + case UPB_DESCRIPTOR_TYPE_SINT32: + return UPB_TYPE_INT32; + case UPB_DESCRIPTOR_TYPE_UINT64: + case UPB_DESCRIPTOR_TYPE_FIXED64: + return UPB_TYPE_UINT64; + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_FIXED32: + return UPB_TYPE_UINT32; + case UPB_DESCRIPTOR_TYPE_ENUM: + return UPB_TYPE_ENUM; + case UPB_DESCRIPTOR_TYPE_BOOL: + return UPB_TYPE_BOOL; + case UPB_DESCRIPTOR_TYPE_STRING: + return UPB_TYPE_STRING; + case UPB_DESCRIPTOR_TYPE_BYTES: + return UPB_TYPE_BYTES; + case UPB_DESCRIPTOR_TYPE_GROUP: + case UPB_DESCRIPTOR_TYPE_MESSAGE: + return UPB_TYPE_MESSAGE; + } + UPB_UNREACHABLE(); +} + +upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) { + return f->type_; +} + +uint32_t upb_fielddef_index(const upb_fielddef *f) { + return f->index_; +} + +upb_label_t upb_fielddef_label(const upb_fielddef *f) { + return f->label_; +} + +uint32_t upb_fielddef_number(const upb_fielddef *f) { + return f->number_; +} + +bool upb_fielddef_isextension(const upb_fielddef *f) { + return f->is_extension_; +} + +bool upb_fielddef_lazy(const upb_fielddef *f) { + return f->lazy_; +} + +bool upb_fielddef_packed(const upb_fielddef *f) { + return f->packed_; +} + +const char *upb_fielddef_name(const upb_fielddef *f) { + return shortdefname(f->full_name); +} + +const char *upb_fielddef_jsonname(const upb_fielddef *f) { + return f->json_name; +} + +uint32_t upb_fielddef_selectorbase(const upb_fielddef *f) { + return f->selector_base; +} + +const upb_filedef *upb_fielddef_file(const upb_fielddef *f) { + return f->file; +} + +const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) { + return f->msgdef; +} + +const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) { + return f->oneof; +} + +const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f) { + if (!f->oneof || upb_oneofdef_issynthetic(f->oneof)) return NULL; + return f->oneof; +} + +upb_msgval upb_fielddef_default(const upb_fielddef *f) { + UPB_ASSERT(!upb_fielddef_issubmsg(f)); + upb_msgval ret; + if (upb_fielddef_isstring(f)) { + str_t *str = f->defaultval.str; + if (str) { + ret.str_val.data = str->str; + ret.str_val.size = str->len; + } else { + ret.str_val.size = 0; + } + } else { + memcpy(&ret, &f->defaultval, 8); + } + return ret; +} + +static void chkdefaulttype(const upb_fielddef *f, int ctype) { + UPB_UNUSED(f); + UPB_UNUSED(ctype); +} + +int64_t upb_fielddef_defaultint64(const upb_fielddef *f) { + chkdefaulttype(f, UPB_TYPE_INT64); + return f->defaultval.sint; +} + +int32_t upb_fielddef_defaultint32(const upb_fielddef *f) { + chkdefaulttype(f, UPB_TYPE_INT32); + return (int32_t)f->defaultval.sint; +} + +uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) { + chkdefaulttype(f, UPB_TYPE_UINT64); + return f->defaultval.uint; +} + +uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) { + chkdefaulttype(f, UPB_TYPE_UINT32); + return (uint32_t)f->defaultval.uint; +} + +bool upb_fielddef_defaultbool(const upb_fielddef *f) { + chkdefaulttype(f, UPB_TYPE_BOOL); + return f->defaultval.boolean; +} + +float upb_fielddef_defaultfloat(const upb_fielddef *f) { + chkdefaulttype(f, UPB_TYPE_FLOAT); + return f->defaultval.flt; +} + +double upb_fielddef_defaultdouble(const upb_fielddef *f) { + chkdefaulttype(f, UPB_TYPE_DOUBLE); + return f->defaultval.dbl; +} + +const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) { + str_t *str = f->defaultval.str; + UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_STRING || + upb_fielddef_type(f) == UPB_TYPE_BYTES || + upb_fielddef_type(f) == UPB_TYPE_ENUM); + if (str) { + if (len) *len = str->len; + return str->str; + } else { + if (len) *len = 0; + return NULL; + } +} + +const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) { + return upb_fielddef_type(f) == UPB_TYPE_MESSAGE ? f->sub.msgdef : NULL; +} + +const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) { + return upb_fielddef_type(f) == UPB_TYPE_ENUM ? f->sub.enumdef : NULL; +} + +const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f) { + return &f->msgdef->layout->fields[f->layout_index]; +} + +bool upb_fielddef_issubmsg(const upb_fielddef *f) { + return upb_fielddef_type(f) == UPB_TYPE_MESSAGE; +} + +bool upb_fielddef_isstring(const upb_fielddef *f) { + return upb_fielddef_type(f) == UPB_TYPE_STRING || + upb_fielddef_type(f) == UPB_TYPE_BYTES; +} + +bool upb_fielddef_isseq(const upb_fielddef *f) { + return upb_fielddef_label(f) == UPB_LABEL_REPEATED; +} + +bool upb_fielddef_isprimitive(const upb_fielddef *f) { + return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f); +} + +bool upb_fielddef_ismap(const upb_fielddef *f) { + return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) && + upb_msgdef_mapentry(upb_fielddef_msgsubdef(f)); +} + +bool upb_fielddef_hassubdef(const upb_fielddef *f) { + return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM; +} + +bool upb_fielddef_haspresence(const upb_fielddef *f) { + if (upb_fielddef_isseq(f)) return false; + return upb_fielddef_issubmsg(f) || upb_fielddef_containingoneof(f) || + f->file->syntax == UPB_SYNTAX_PROTO2; +} + +static bool between(int32_t x, int32_t low, int32_t high) { + return x >= low && x <= high; +} + +bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); } +bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); } +bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); } + +bool upb_fielddef_checkdescriptortype(int32_t type) { + return between(type, 1, 18); +} + +/* upb_msgdef *****************************************************************/ + +const char *upb_msgdef_fullname(const upb_msgdef *m) { + return m->full_name; +} + +const upb_filedef *upb_msgdef_file(const upb_msgdef *m) { + return m->file; +} + +const char *upb_msgdef_name(const upb_msgdef *m) { + return shortdefname(m->full_name); +} + +upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) { + return m->file->syntax; +} + +size_t upb_msgdef_selectorcount(const upb_msgdef *m) { + return m->selector_count; +} + +uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m) { + return m->submsg_field_count; +} + +const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) { + upb_value val; + return upb_inttable_lookup32(&m->itof, i, &val) ? + upb_value_getconstptr(val) : NULL; +} + +const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name, + size_t len) { + upb_value val; + + if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { + return NULL; + } + + return unpack_def(val, UPB_DEFTYPE_FIELD); +} + +const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, + size_t len) { + upb_value val; + + if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { + return NULL; + } + + return unpack_def(val, UPB_DEFTYPE_ONEOF); +} + +bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len, + const upb_fielddef **f, const upb_oneofdef **o) { + upb_value val; + + if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { + return false; + } + + *o = unpack_def(val, UPB_DEFTYPE_ONEOF); + *f = unpack_def(val, UPB_DEFTYPE_FIELD); + return *o || *f; /* False if this was a JSON name. */ +} + +const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m, + const char *name, size_t len) { + upb_value val; + const upb_fielddef* f; + + if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { + return NULL; + } + + f = unpack_def(val, UPB_DEFTYPE_FIELD); + if (!f) f = unpack_def(val, UPB_DEFTYPE_FIELD_JSONNAME); + + return f; +} + +int upb_msgdef_numfields(const upb_msgdef *m) { + return m->field_count; +} + +int upb_msgdef_numoneofs(const upb_msgdef *m) { + return m->oneof_count; +} + +int upb_msgdef_numrealoneofs(const upb_msgdef *m) { + return m->real_oneof_count; +} + +int upb_msgdef_fieldcount(const upb_msgdef *m) { + return m->field_count; +} + +int upb_msgdef_oneofcount(const upb_msgdef *m) { + return m->oneof_count; +} + +int upb_msgdef_realoneofcount(const upb_msgdef *m) { + return m->real_oneof_count; +} + +const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m) { + return m->layout; +} + +const upb_fielddef *upb_msgdef_field(const upb_msgdef *m, int i) { + UPB_ASSERT(i >= 0 && i < m->field_count); + return &m->fields[i]; +} + +const upb_oneofdef *upb_msgdef_oneof(const upb_msgdef *m, int i) { + UPB_ASSERT(i >= 0 && i < m->oneof_count); + return &m->oneofs[i]; +} + +bool upb_msgdef_mapentry(const upb_msgdef *m) { + return m->map_entry; +} + +upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m) { + return m->well_known_type; +} + +bool upb_msgdef_isnumberwrapper(const upb_msgdef *m) { + upb_wellknowntype_t type = upb_msgdef_wellknowntype(m); + return type >= UPB_WELLKNOWN_DOUBLEVALUE && + type <= UPB_WELLKNOWN_UINT32VALUE; +} + +bool upb_msgdef_iswrapper(const upb_msgdef *m) { + upb_wellknowntype_t type = upb_msgdef_wellknowntype(m); + return type >= UPB_WELLKNOWN_DOUBLEVALUE && + type <= UPB_WELLKNOWN_BOOLVALUE; +} + +void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) { + upb_inttable_begin(iter, &m->itof); +} + +void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); } + +bool upb_msg_field_done(const upb_msg_field_iter *iter) { + return upb_inttable_done(iter); +} + +upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) { + return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter)); +} + +void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) { + upb_inttable_iter_setdone(iter); +} + +bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1, + const upb_msg_field_iter * iter2) { + return upb_inttable_iter_isequal(iter1, iter2); +} + +void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) { + upb_strtable_begin(iter, &m->ntof); + /* We need to skip past any initial fields. */ + while (!upb_strtable_done(iter) && + !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF)) { + upb_strtable_next(iter); + } +} + +void upb_msg_oneof_next(upb_msg_oneof_iter *iter) { + /* We need to skip past fields to return only oneofs. */ + do { + upb_strtable_next(iter); + } while (!upb_strtable_done(iter) && + !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF)); +} + +bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) { + return upb_strtable_done(iter); +} + +const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) { + return unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF); +} + +void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) { + upb_strtable_iter_setdone(iter); +} + +bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1, + const upb_msg_oneof_iter *iter2) { + return upb_strtable_iter_isequal(iter1, iter2); +} + +/* upb_oneofdef ***************************************************************/ + +const char *upb_oneofdef_name(const upb_oneofdef *o) { + return shortdefname(o->full_name); +} + +const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) { + return o->parent; +} + +int upb_oneofdef_fieldcount(const upb_oneofdef *o) { + return o->field_count; +} + +const upb_fielddef *upb_oneofdef_field(const upb_oneofdef *o, int i) { + UPB_ASSERT(i < o->field_count); + return o->fields[i]; +} + +int upb_oneofdef_numfields(const upb_oneofdef *o) { + return o->field_count; +} + +uint32_t upb_oneofdef_index(const upb_oneofdef *o) { + return o - o->parent->oneofs; +} + +bool upb_oneofdef_issynthetic(const upb_oneofdef *o) { + return o->synthetic; +} + +const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, + const char *name, size_t length) { + upb_value val; + return upb_strtable_lookup2(&o->ntof, name, length, &val) ? + upb_value_getptr(val) : NULL; +} + +const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) { + upb_value val; + return upb_inttable_lookup32(&o->itof, num, &val) ? + upb_value_getptr(val) : NULL; +} + +void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) { + upb_inttable_begin(iter, &o->itof); +} + +void upb_oneof_next(upb_oneof_iter *iter) { + upb_inttable_next(iter); +} + +bool upb_oneof_done(upb_oneof_iter *iter) { + return upb_inttable_done(iter); +} + +upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) { + return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter)); +} + +void upb_oneof_iter_setdone(upb_oneof_iter *iter) { + upb_inttable_iter_setdone(iter); +} + +/* upb_filedef ****************************************************************/ + +const char *upb_filedef_name(const upb_filedef *f) { + return f->name; +} + +const char *upb_filedef_package(const upb_filedef *f) { + return f->package; +} + +const char *upb_filedef_phpprefix(const upb_filedef *f) { + return f->phpprefix; +} + +const char *upb_filedef_phpnamespace(const upb_filedef *f) { + return f->phpnamespace; +} + +upb_syntax_t upb_filedef_syntax(const upb_filedef *f) { + return f->syntax; +} + +int upb_filedef_msgcount(const upb_filedef *f) { + return f->msg_count; +} + +int upb_filedef_depcount(const upb_filedef *f) { + return f->dep_count; +} + +int upb_filedef_enumcount(const upb_filedef *f) { + return f->enum_count; +} + +const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i) { + return i < 0 || i >= f->dep_count ? NULL : f->deps[i]; +} + +const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i) { + return i < 0 || i >= f->msg_count ? NULL : &f->msgs[i]; +} + +const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i) { + return i < 0 || i >= f->enum_count ? NULL : &f->enums[i]; +} + +const upb_symtab *upb_filedef_symtab(const upb_filedef *f) { + return f->symtab; +} + +void upb_symtab_free(upb_symtab *s) { + upb_arena_free(s->arena); + upb_gfree(s); +} + +upb_symtab *upb_symtab_new(void) { + upb_symtab *s = upb_gmalloc(sizeof(*s)); + upb_alloc *alloc; + + if (!s) { + return NULL; + } + + s->arena = upb_arena_new(); + s->bytes_loaded = 0; + alloc = upb_arena_alloc(s->arena); + + if (!upb_strtable_init2(&s->syms, UPB_CTYPE_CONSTPTR, 32, alloc) || + !upb_strtable_init2(&s->files, UPB_CTYPE_CONSTPTR, 4, alloc)) { + upb_arena_free(s->arena); + upb_gfree(s); + s = NULL; + } + return s; +} + +const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) { + upb_value v; + return upb_strtable_lookup(&s->syms, sym, &v) ? + unpack_def(v, UPB_DEFTYPE_MSG) : NULL; +} + +const upb_msgdef *upb_symtab_lookupmsg2(const upb_symtab *s, const char *sym, + size_t len) { + upb_value v; + return upb_strtable_lookup2(&s->syms, sym, len, &v) ? + unpack_def(v, UPB_DEFTYPE_MSG) : NULL; +} + +const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) { + upb_value v; + return upb_strtable_lookup(&s->syms, sym, &v) ? + unpack_def(v, UPB_DEFTYPE_ENUM) : NULL; +} + +const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name) { + upb_value v; + return upb_strtable_lookup(&s->files, name, &v) ? upb_value_getconstptr(v) + : NULL; +} + +const upb_filedef *upb_symtab_lookupfile2( + const upb_symtab *s, const char *name, size_t len) { + upb_value v; + return upb_strtable_lookup2(&s->files, name, len, &v) ? + upb_value_getconstptr(v) : NULL; +} + +int upb_symtab_filecount(const upb_symtab *s) { + return (int)upb_strtable_count(&s->files); +} + +/* Code to build defs from descriptor protos. *********************************/ + +/* There is a question of how much validation to do here. It will be difficult + * to perfectly match the amount of validation performed by proto2. But since + * this code is used to directly build defs from Ruby (for example) we do need + * to validate important constraints like uniqueness of names and numbers. */ + +#define CHK_OOM(x) if (!(x)) { symtab_oomerr(ctx); } + +typedef struct { + upb_symtab *symtab; + upb_filedef *file; /* File we are building. */ + upb_arena *file_arena; /* Allocate defs here. */ + upb_alloc *alloc; /* Alloc of file_arena, for tables. */ + const upb_msglayout **layouts; /* NULL if we should build layouts. */ + upb_status *status; /* Record errors here. */ + jmp_buf err; /* longjmp() on error. */ +} symtab_addctx; + +UPB_NORETURN UPB_NOINLINE UPB_PRINTF(2, 3) +static void symtab_errf(symtab_addctx *ctx, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + upb_status_vseterrf(ctx->status, fmt, argp); + va_end(argp); + UPB_LONGJMP(ctx->err, 1); +} + +UPB_NORETURN UPB_NOINLINE +static void symtab_oomerr(symtab_addctx *ctx) { + upb_status_setoom(ctx->status); + UPB_LONGJMP(ctx->err, 1); +} + +void *symtab_alloc(symtab_addctx *ctx, size_t bytes) { + void *ret = upb_arena_malloc(ctx->file_arena, bytes); + if (!ret) symtab_oomerr(ctx); + return ret; +} + +static void check_ident(symtab_addctx *ctx, upb_strview name, bool full) { + const char *str = name.data; + size_t len = name.size; + bool start = true; + size_t i; + for (i = 0; i < len; i++) { + char c = str[i]; + if (c == '.') { + if (start || !full) { + symtab_errf(ctx, "invalid name: unexpected '.' (%.*s)", (int)len, str); + } + start = true; + } else if (start) { + if (!upb_isletter(c)) { + symtab_errf( + ctx, + "invalid name: path components must start with a letter (%.*s)", + (int)len, str); + } + start = false; + } else { + if (!upb_isalphanum(c)) { + symtab_errf(ctx, "invalid name: non-alphanumeric character (%.*s)", + (int)len, str); + } + } + } + if (start) { + symtab_errf(ctx, "invalid name: empty part (%.*s)", (int)len, str); + } +} + +static size_t div_round_up(size_t n, size_t d) { + return (n + d - 1) / d; +} + +static size_t upb_msgval_sizeof(upb_fieldtype_t type) { + switch (type) { + case UPB_TYPE_DOUBLE: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT64: + return 8; + case UPB_TYPE_ENUM: + case UPB_TYPE_INT32: + case UPB_TYPE_UINT32: + case UPB_TYPE_FLOAT: + return 4; + case UPB_TYPE_BOOL: + return 1; + case UPB_TYPE_MESSAGE: + return sizeof(void*); + case UPB_TYPE_BYTES: + case UPB_TYPE_STRING: + return sizeof(upb_strview); + } + UPB_UNREACHABLE(); +} + +static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) { + if (upb_msgdef_mapentry(upb_fielddef_containingtype(f))) { + upb_map_entry ent; + UPB_ASSERT(sizeof(ent.k) == sizeof(ent.v)); + return sizeof(ent.k); + } else if (upb_fielddef_isseq(f)) { + return sizeof(void*); + } else { + return upb_msgval_sizeof(upb_fielddef_type(f)); + } +} + +static uint32_t upb_msglayout_place(upb_msglayout *l, size_t size) { + uint32_t ret; + + l->size = UPB_ALIGN_UP(l->size, size); + ret = l->size; + l->size += size; + return ret; +} + +static int field_number_cmp(const void *p1, const void *p2) { + const upb_msglayout_field *f1 = p1; + const upb_msglayout_field *f2 = p2; + return f1->number - f2->number; +} + +static void assign_layout_indices(const upb_msgdef *m, upb_msglayout_field *fields) { + int i; + int n = upb_msgdef_numfields(m); + for (i = 0; i < n; i++) { + upb_fielddef *f = (upb_fielddef*)upb_msgdef_itof(m, fields[i].number); + UPB_ASSERT(f); + f->layout_index = i; + } +} + +/* This function is the dynamic equivalent of message_layout.{cc,h} in upbc. + * It computes a dynamic layout for all of the fields in |m|. */ +static void make_layout(symtab_addctx *ctx, const upb_msgdef *m) { + upb_msglayout *l = (upb_msglayout*)m->layout; + upb_msg_field_iter it; + upb_msg_oneof_iter oit; + size_t hasbit; + size_t submsg_count = m->submsg_field_count; + const upb_msglayout **submsgs; + upb_msglayout_field *fields; + + memset(l, 0, sizeof(*l) + sizeof(_upb_fasttable_entry)); + + fields = symtab_alloc(ctx, upb_msgdef_numfields(m) * sizeof(*fields)); + submsgs = symtab_alloc(ctx, submsg_count * sizeof(*submsgs)); + + l->field_count = upb_msgdef_numfields(m); + l->fields = fields; + l->submsgs = submsgs; + l->table_mask = 0; + + /* TODO(haberman): initialize fast tables so that reflection-based parsing + * can get the same speeds as linked-in types. */ + l->fasttable[0].field_parser = &fastdecode_generic; + l->fasttable[0].field_data = 0; + + if (upb_msgdef_mapentry(m)) { + /* TODO(haberman): refactor this method so this special case is more + * elegant. */ + const upb_fielddef *key = upb_msgdef_itof(m, 1); + const upb_fielddef *val = upb_msgdef_itof(m, 2); + fields[0].number = 1; + fields[1].number = 2; + fields[0].label = UPB_LABEL_OPTIONAL; + fields[1].label = UPB_LABEL_OPTIONAL; + fields[0].presence = 0; + fields[1].presence = 0; + fields[0].descriptortype = upb_fielddef_descriptortype(key); + fields[1].descriptortype = upb_fielddef_descriptortype(val); + fields[0].offset = 0; + fields[1].offset = sizeof(upb_strview); + fields[1].submsg_index = 0; + + if (upb_fielddef_type(val) == UPB_TYPE_MESSAGE) { + submsgs[0] = upb_fielddef_msgsubdef(val)->layout; + } + + l->field_count = 2; + l->size = 2 * sizeof(upb_strview); + l->size = UPB_ALIGN_UP(l->size, 8); + return; + } + + /* Allocate data offsets in three stages: + * + * 1. hasbits. + * 2. regular fields. + * 3. oneof fields. + * + * OPT: There is a lot of room for optimization here to minimize the size. + */ + + /* Allocate hasbits and set basic field attributes. */ + submsg_count = 0; + for (upb_msg_field_begin(&it, m), hasbit = 0; + !upb_msg_field_done(&it); + upb_msg_field_next(&it)) { + upb_fielddef* f = upb_msg_iter_field(&it); + upb_msglayout_field *field = &fields[upb_fielddef_index(f)]; + + field->number = upb_fielddef_number(f); + field->descriptortype = upb_fielddef_descriptortype(f); + field->label = upb_fielddef_label(f); + + if (field->descriptortype == UPB_DTYPE_STRING && + f->file->syntax == UPB_SYNTAX_PROTO2) { + /* See TableDescriptorType() in upbc/generator.cc for details and + * rationale. */ + field->descriptortype = UPB_DTYPE_BYTES; + } + + if (upb_fielddef_ismap(f)) { + field->label = _UPB_LABEL_MAP; + } else if (upb_fielddef_packed(f)) { + field->label = _UPB_LABEL_PACKED; + } + + if (upb_fielddef_issubmsg(f)) { + const upb_msgdef *subm = upb_fielddef_msgsubdef(f); + field->submsg_index = submsg_count++; + submsgs[field->submsg_index] = subm->layout; + } + + if (upb_fielddef_haspresence(f) && !upb_fielddef_realcontainingoneof(f)) { + /* We don't use hasbit 0, so that 0 can indicate "no presence" in the + * table. This wastes one hasbit, but we don't worry about it for now. */ + field->presence = ++hasbit; + } else { + field->presence = 0; + } + } + + /* Account for space used by hasbits. */ + l->size = div_round_up(hasbit, 8); + + /* Allocate non-oneof fields. */ + for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); + upb_msg_field_next(&it)) { + const upb_fielddef* f = upb_msg_iter_field(&it); + size_t field_size = upb_msg_fielddefsize(f); + size_t index = upb_fielddef_index(f); + + if (upb_fielddef_realcontainingoneof(f)) { + /* Oneofs are handled separately below. */ + continue; + } + + fields[index].offset = upb_msglayout_place(l, field_size); + } + + /* Allocate oneof fields. Each oneof field consists of a uint32 for the case + * and space for the actual data. */ + for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit); + upb_msg_oneof_next(&oit)) { + const upb_oneofdef* o = upb_msg_iter_oneof(&oit); + upb_oneof_iter fit; + + size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */ + size_t field_size = 0; + uint32_t case_offset; + uint32_t data_offset; + + if (upb_oneofdef_issynthetic(o)) continue; + + /* Calculate field size: the max of all field sizes. */ + for (upb_oneof_begin(&fit, o); + !upb_oneof_done(&fit); + upb_oneof_next(&fit)) { + const upb_fielddef* f = upb_oneof_iter_field(&fit); + field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f)); + } + + /* Align and allocate case offset. */ + case_offset = upb_msglayout_place(l, case_size); + data_offset = upb_msglayout_place(l, field_size); + + for (upb_oneof_begin(&fit, o); + !upb_oneof_done(&fit); + upb_oneof_next(&fit)) { + const upb_fielddef* f = upb_oneof_iter_field(&fit); + fields[upb_fielddef_index(f)].offset = data_offset; + fields[upb_fielddef_index(f)].presence = ~case_offset; + } + } + + /* Size of the entire structure should be a multiple of its greatest + * alignment. TODO: track overall alignment for real? */ + l->size = UPB_ALIGN_UP(l->size, 8); + + /* Sort fields by number. */ + qsort(fields, upb_msgdef_numfields(m), sizeof(*fields), field_number_cmp); + assign_layout_indices(m, fields); +} + +static void assign_msg_indices(symtab_addctx *ctx, upb_msgdef *m) { + /* Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the + * lowest indexes, but we do not publicly guarantee this. */ + upb_msg_field_iter j; + int i; + uint32_t selector; + int n = upb_msgdef_numfields(m); + upb_fielddef **fields; + + if (n == 0) { + m->selector_count = UPB_STATIC_SELECTOR_COUNT; + m->submsg_field_count = 0; + return; + } + + fields = upb_gmalloc(n * sizeof(*fields)); + + m->submsg_field_count = 0; + for(i = 0, upb_msg_field_begin(&j, m); + !upb_msg_field_done(&j); + upb_msg_field_next(&j), i++) { + upb_fielddef *f = upb_msg_iter_field(&j); + UPB_ASSERT(f->msgdef == m); + if (upb_fielddef_issubmsg(f)) { + m->submsg_field_count++; + } + fields[i] = f; + } + + qsort(fields, n, sizeof(*fields), cmp_fields); + + selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count; + for (i = 0; i < n; i++) { + upb_fielddef *f = fields[i]; + f->index_ = i; + f->selector_base = selector + upb_handlers_selectorbaseoffset(f); + selector += upb_handlers_selectorcount(f); + } + m->selector_count = selector; + + upb_gfree(fields); +} + +static char *strviewdup(symtab_addctx *ctx, upb_strview view) { + return upb_strdup2(view.data, view.size, ctx->alloc); +} + +static bool streql2(const char *a, size_t n, const char *b) { + return n == strlen(b) && memcmp(a, b, n) == 0; +} + +static bool streql_view(upb_strview view, const char *b) { + return streql2(view.data, view.size, b); +} + +static const char *makefullname(symtab_addctx *ctx, const char *prefix, + upb_strview name) { + if (prefix) { + /* ret = prefix + '.' + name; */ + size_t n = strlen(prefix); + char *ret = symtab_alloc(ctx, n + name.size + 2); + strcpy(ret, prefix); + ret[n] = '.'; + memcpy(&ret[n + 1], name.data, name.size); + ret[n + 1 + name.size] = '\0'; + return ret; + } else { + return strviewdup(ctx, name); + } +} + +static void finalize_oneofs(symtab_addctx *ctx, upb_msgdef *m) { + int i; + int synthetic_count = 0; + upb_oneofdef *mutable_oneofs = (upb_oneofdef*)m->oneofs; + + for (i = 0; i < m->oneof_count; i++) { + upb_oneofdef *o = &mutable_oneofs[i]; + + if (o->synthetic && o->field_count != 1) { + symtab_errf(ctx, "Synthetic oneofs must have one field, not %d: %s", + o->field_count, upb_oneofdef_name(o)); + } + + if (o->synthetic) { + synthetic_count++; + } else if (synthetic_count != 0) { + symtab_errf(ctx, "Synthetic oneofs must be after all other oneofs: %s", + upb_oneofdef_name(o)); + } + + o->fields = symtab_alloc(ctx, sizeof(upb_fielddef *) * o->field_count); + o->field_count = 0; + } + + for (i = 0; i < m->field_count; i++) { + const upb_fielddef *f = &m->fields[i]; + upb_oneofdef *o = (upb_oneofdef*)f->oneof; + if (o) { + o->fields[o->field_count++] = f; + } + } + + m->real_oneof_count = m->oneof_count - synthetic_count; +} + +size_t getjsonname(const char *name, char *buf, size_t len) { + size_t src, dst = 0; + bool ucase_next = false; + +#define WRITE(byte) \ + ++dst; \ + if (dst < len) buf[dst - 1] = byte; \ + else if (dst == len) buf[dst - 1] = '\0' + + if (!name) { + WRITE('\0'); + return 0; + } + + /* Implement the transformation as described in the spec: + * 1. upper case all letters after an underscore. + * 2. remove all underscores. + */ + for (src = 0; name[src]; src++) { + if (name[src] == '_') { + ucase_next = true; + continue; + } + + if (ucase_next) { + WRITE(toupper(name[src])); + ucase_next = false; + } else { + WRITE(name[src]); + } + } + + WRITE('\0'); + return dst; + +#undef WRITE +} + +static char* makejsonname(symtab_addctx *ctx, const char* name) { + size_t size = getjsonname(name, NULL, 0); + char* json_name = symtab_alloc(ctx, size); + getjsonname(name, json_name, size); + return json_name; +} + +static void symtab_add(symtab_addctx *ctx, const char *name, upb_value v) { + if (upb_strtable_lookup(&ctx->symtab->syms, name, NULL)) { + symtab_errf(ctx, "duplicate symbol '%s'", name); + } + upb_alloc *alloc = upb_arena_alloc(ctx->symtab->arena); + size_t len = strlen(name); + CHK_OOM(upb_strtable_insert3(&ctx->symtab->syms, name, len, v, alloc)); +} + +/* Given a symbol and the base symbol inside which it is defined, find the + * symbol's definition in t. */ +static const void *symtab_resolve(symtab_addctx *ctx, const upb_fielddef *f, + const char *base, upb_strview sym, + upb_deftype_t type) { + const upb_strtable *t = &ctx->symtab->syms; + if(sym.size == 0) goto notfound; + if(sym.data[0] == '.') { + /* Symbols starting with '.' are absolute, so we do a single lookup. + * Slice to omit the leading '.' */ + upb_value v; + if (!upb_strtable_lookup2(t, sym.data + 1, sym.size - 1, &v)) { + goto notfound; + } + + const void *ret = unpack_def(v, type); + if (!ret) { + symtab_errf(ctx, "type mismatch when resolving field %s, name %s", + f->full_name, sym.data); + } + return ret; + } else { + /* Remove components from base until we find an entry or run out. + * TODO: This branch is totally broken, but currently not used. */ + (void)base; + UPB_ASSERT(false); + goto notfound; + } + +notfound: + symtab_errf(ctx, "couldn't resolve name '%s'", sym.data); +} + +static void create_oneofdef( + symtab_addctx *ctx, upb_msgdef *m, + const google_protobuf_OneofDescriptorProto *oneof_proto) { + upb_oneofdef *o; + upb_strview name = google_protobuf_OneofDescriptorProto_name(oneof_proto); + upb_value v; + + o = (upb_oneofdef*)&m->oneofs[m->oneof_count++]; + o->parent = m; + o->full_name = makefullname(ctx, m->full_name, name); + o->field_count = 0; + o->synthetic = false; + + v = pack_def(o, UPB_DEFTYPE_ONEOF); + symtab_add(ctx, o->full_name, v); + CHK_OOM(upb_strtable_insert3(&m->ntof, name.data, name.size, v, ctx->alloc)); + + CHK_OOM(upb_inttable_init2(&o->itof, UPB_CTYPE_CONSTPTR, ctx->alloc)); + CHK_OOM(upb_strtable_init2(&o->ntof, UPB_CTYPE_CONSTPTR, 4, ctx->alloc)); +} + +static str_t *newstr(symtab_addctx *ctx, const char *data, size_t len) { + str_t *ret = symtab_alloc(ctx, sizeof(*ret) + len); + if (!ret) return NULL; + ret->len = len; + if (len) memcpy(ret->str, data, len); + ret->str[len] = '\0'; + return ret; +} + +static void parse_default(symtab_addctx *ctx, const char *str, size_t len, + upb_fielddef *f) { + char *end; + char nullz[64]; + errno = 0; + + switch (upb_fielddef_type(f)) { + case UPB_TYPE_INT32: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT32: + case UPB_TYPE_UINT64: + case UPB_TYPE_DOUBLE: + case UPB_TYPE_FLOAT: + /* Standard C number parsing functions expect null-terminated strings. */ + if (len >= sizeof(nullz) - 1) { + symtab_errf(ctx, "Default too long: %.*s", (int)len, str); + } + memcpy(nullz, str, len); + nullz[len] = '\0'; + str = nullz; + break; + default: + break; + } + + switch (upb_fielddef_type(f)) { + case UPB_TYPE_INT32: { + long val = strtol(str, &end, 0); + if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end) { + goto invalid; + } + f->defaultval.sint = val; + break; + } + case UPB_TYPE_ENUM: { + const upb_enumdef *e = f->sub.enumdef; + int32_t val; + if (!upb_enumdef_ntoi(e, str, len, &val)) { + goto invalid; + } + f->defaultval.sint = val; + break; + } + case UPB_TYPE_INT64: { + /* XXX: Need to write our own strtoll, since it's not available in c89. */ + int64_t val = strtol(str, &end, 0); + if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end) { + goto invalid; + } + f->defaultval.sint = val; + break; + } + case UPB_TYPE_UINT32: { + unsigned long val = strtoul(str, &end, 0); + if (val > UINT32_MAX || errno == ERANGE || *end) { + goto invalid; + } + f->defaultval.uint = val; + break; + } + case UPB_TYPE_UINT64: { + /* XXX: Need to write our own strtoull, since it's not available in c89. */ + uint64_t val = strtoul(str, &end, 0); + if (val > UINT64_MAX || errno == ERANGE || *end) { + goto invalid; + } + f->defaultval.uint = val; + break; + } + case UPB_TYPE_DOUBLE: { + double val = strtod(str, &end); + if (errno == ERANGE || *end) { + goto invalid; + } + f->defaultval.dbl = val; + break; + } + case UPB_TYPE_FLOAT: { + /* XXX: Need to write our own strtof, since it's not available in c89. */ + float val = strtod(str, &end); + if (errno == ERANGE || *end) { + goto invalid; + } + f->defaultval.flt = val; + break; + } + case UPB_TYPE_BOOL: { + if (streql2(str, len, "false")) { + f->defaultval.boolean = false; + } else if (streql2(str, len, "true")) { + f->defaultval.boolean = true; + } else { + } + break; + } + case UPB_TYPE_STRING: + f->defaultval.str = newstr(ctx, str, len); + break; + case UPB_TYPE_BYTES: + /* XXX: need to interpret the C-escaped value. */ + f->defaultval.str = newstr(ctx, str, len); + break; + case UPB_TYPE_MESSAGE: + /* Should not have a default value. */ + symtab_errf(ctx, "Message should not have a default (%s)", + upb_fielddef_fullname(f)); + } + + return; + +invalid: + symtab_errf(ctx, "Invalid default '%.*s' for field %s", (int)len, str, + upb_fielddef_fullname(f)); +} + +static void set_default_default(symtab_addctx *ctx, upb_fielddef *f) { + switch (upb_fielddef_type(f)) { + case UPB_TYPE_INT32: + case UPB_TYPE_INT64: + case UPB_TYPE_ENUM: + f->defaultval.sint = 0; + break; + case UPB_TYPE_UINT64: + case UPB_TYPE_UINT32: + f->defaultval.uint = 0; + break; + case UPB_TYPE_DOUBLE: + case UPB_TYPE_FLOAT: + f->defaultval.dbl = 0; + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + f->defaultval.str = newstr(ctx, NULL, 0); + break; + case UPB_TYPE_BOOL: + f->defaultval.boolean = false; + break; + case UPB_TYPE_MESSAGE: + break; + } +} + +static void create_fielddef( + symtab_addctx *ctx, const char *prefix, upb_msgdef *m, + const google_protobuf_FieldDescriptorProto *field_proto) { + upb_alloc *alloc = ctx->alloc; + upb_fielddef *f; + const google_protobuf_FieldOptions *options; + upb_strview name; + const char *full_name; + const char *json_name; + const char *shortname; + uint32_t field_number; + + if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) { + symtab_errf(ctx, "field has no name (%s)", upb_msgdef_fullname(m)); + } + + name = google_protobuf_FieldDescriptorProto_name(field_proto); + check_ident(ctx, name, false); + full_name = makefullname(ctx, prefix, name); + shortname = shortdefname(full_name); + + if (google_protobuf_FieldDescriptorProto_has_json_name(field_proto)) { + json_name = strviewdup( + ctx, google_protobuf_FieldDescriptorProto_json_name(field_proto)); + } else { + json_name = makejsonname(ctx, shortname); + } + + field_number = google_protobuf_FieldDescriptorProto_number(field_proto); + + if (field_number == 0 || field_number > UPB_MAX_FIELDNUMBER) { + symtab_errf(ctx, "invalid field number (%u)", field_number); + } + + if (m) { + /* direct message field. */ + upb_value v, field_v, json_v; + size_t json_size; + + f = (upb_fielddef*)&m->fields[m->field_count++]; + f->msgdef = m; + f->is_extension_ = false; + + if (upb_strtable_lookup(&m->ntof, shortname, NULL)) { + symtab_errf(ctx, "duplicate field name (%s)", shortname); + } + + if (upb_strtable_lookup(&m->ntof, json_name, NULL)) { + symtab_errf(ctx, "duplicate json_name (%s)", json_name); + } + + if (upb_inttable_lookup(&m->itof, field_number, NULL)) { + symtab_errf(ctx, "duplicate field number (%u)", field_number); + } + + field_v = pack_def(f, UPB_DEFTYPE_FIELD); + json_v = pack_def(f, UPB_DEFTYPE_FIELD_JSONNAME); + v = upb_value_constptr(f); + json_size = strlen(json_name); + + CHK_OOM( + upb_strtable_insert3(&m->ntof, name.data, name.size, field_v, alloc)); + CHK_OOM(upb_inttable_insert2(&m->itof, field_number, v, alloc)); + + if (strcmp(shortname, json_name) != 0) { + upb_strtable_insert3(&m->ntof, json_name, json_size, json_v, alloc); + } + + if (ctx->layouts) { + const upb_msglayout_field *fields = m->layout->fields; + int count = m->layout->field_count; + bool found = false; + int i; + for (i = 0; i < count; i++) { + if (fields[i].number == field_number) { + f->layout_index = i; + found = true; + break; + } + } + UPB_ASSERT(found); + } + } else { + /* extension field. */ + f = (upb_fielddef*)&ctx->file->exts[ctx->file->ext_count++]; + f->is_extension_ = true; + symtab_add(ctx, full_name, pack_def(f, UPB_DEFTYPE_FIELD)); + } + + f->full_name = full_name; + f->json_name = json_name; + f->file = ctx->file; + f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto); + f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto); + f->number_ = field_number; + f->oneof = NULL; + f->proto3_optional_ = + google_protobuf_FieldDescriptorProto_proto3_optional(field_proto); + + /* We can't resolve the subdef or (in the case of extensions) the containing + * message yet, because it may not have been defined yet. We stash a pointer + * to the field_proto until later when we can properly resolve it. */ + f->sub.unresolved = field_proto; + + if (f->label_ == UPB_LABEL_REQUIRED && f->file->syntax == UPB_SYNTAX_PROTO3) { + symtab_errf(ctx, "proto3 fields cannot be required (%s)", f->full_name); + } + + if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) { + int oneof_index = + google_protobuf_FieldDescriptorProto_oneof_index(field_proto); + upb_oneofdef *oneof; + upb_value v = upb_value_constptr(f); + + if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) { + symtab_errf(ctx, "fields in oneof must have OPTIONAL label (%s)", + f->full_name); + } + + if (!m) { + symtab_errf(ctx, "oneof_index provided for extension field (%s)", + f->full_name); + } + + if (oneof_index >= m->oneof_count) { + symtab_errf(ctx, "oneof_index out of range (%s)", f->full_name); + } + + oneof = (upb_oneofdef*)&m->oneofs[oneof_index]; + f->oneof = oneof; + + oneof->field_count++; + if (f->proto3_optional_) { + oneof->synthetic = true; + } + CHK_OOM(upb_inttable_insert2(&oneof->itof, f->number_, v, alloc)); + CHK_OOM(upb_strtable_insert3(&oneof->ntof, name.data, name.size, v, alloc)); + } else { + f->oneof = NULL; + if (f->proto3_optional_) { + symtab_errf(ctx, "field with proto3_optional was not in a oneof (%s)", + f->full_name); + } + } + + options = google_protobuf_FieldDescriptorProto_has_options(field_proto) ? + google_protobuf_FieldDescriptorProto_options(field_proto) : NULL; + + if (options && google_protobuf_FieldOptions_has_packed(options)) { + f->packed_ = google_protobuf_FieldOptions_packed(options); + } else { + /* Repeated fields default to packed for proto3 only. */ + f->packed_ = upb_fielddef_isprimitive(f) && + f->label_ == UPB_LABEL_REPEATED && f->file->syntax == UPB_SYNTAX_PROTO3; + } + + if (options) { + f->lazy_ = google_protobuf_FieldOptions_lazy(options); + } else { + f->lazy_ = false; + } +} + +static void create_enumdef( + symtab_addctx *ctx, const char *prefix, + const google_protobuf_EnumDescriptorProto *enum_proto) { + upb_enumdef *e; + const google_protobuf_EnumValueDescriptorProto *const *values; + upb_strview name; + size_t i, n; + + name = google_protobuf_EnumDescriptorProto_name(enum_proto); + check_ident(ctx, name, false); + + e = (upb_enumdef*)&ctx->file->enums[ctx->file->enum_count++]; + e->full_name = makefullname(ctx, prefix, name); + symtab_add(ctx, e->full_name, pack_def(e, UPB_DEFTYPE_ENUM)); + + values = google_protobuf_EnumDescriptorProto_value(enum_proto, &n); + CHK_OOM(upb_strtable_init2(&e->ntoi, UPB_CTYPE_INT32, n, ctx->alloc)); + CHK_OOM(upb_inttable_init2(&e->iton, UPB_CTYPE_CSTR, ctx->alloc)); + + e->file = ctx->file; + e->defaultval = 0; + + if (n == 0) { + symtab_errf(ctx, "enums must contain at least one value (%s)", + e->full_name); + } + + for (i = 0; i < n; i++) { + const google_protobuf_EnumValueDescriptorProto *value = values[i]; + upb_strview name = google_protobuf_EnumValueDescriptorProto_name(value); + char *name2 = strviewdup(ctx, name); + int32_t num = google_protobuf_EnumValueDescriptorProto_number(value); + upb_value v = upb_value_int32(num); + + if (i == 0 && e->file->syntax == UPB_SYNTAX_PROTO3 && num != 0) { + symtab_errf(ctx, "for proto3, the first enum value must be zero (%s)", + e->full_name); + } + + if (upb_strtable_lookup(&e->ntoi, name2, NULL)) { + symtab_errf(ctx, "duplicate enum label '%s'", name2); + } + + CHK_OOM(name2) + CHK_OOM( + upb_strtable_insert3(&e->ntoi, name2, strlen(name2), v, ctx->alloc)); + + if (!upb_inttable_lookup(&e->iton, num, NULL)) { + upb_value v = upb_value_cstr(name2); + CHK_OOM(upb_inttable_insert2(&e->iton, num, v, ctx->alloc)); + } + } + + upb_inttable_compact2(&e->iton, ctx->alloc); +} + +static void create_msgdef(symtab_addctx *ctx, const char *prefix, + const google_protobuf_DescriptorProto *msg_proto) { + upb_msgdef *m; + const google_protobuf_MessageOptions *options; + const google_protobuf_OneofDescriptorProto *const *oneofs; + const google_protobuf_FieldDescriptorProto *const *fields; + const google_protobuf_EnumDescriptorProto *const *enums; + const google_protobuf_DescriptorProto *const *msgs; + size_t i, n_oneof, n_field, n; + upb_strview name; + + name = google_protobuf_DescriptorProto_name(msg_proto); + check_ident(ctx, name, false); + + m = (upb_msgdef*)&ctx->file->msgs[ctx->file->msg_count++]; + m->full_name = makefullname(ctx, prefix, name); + symtab_add(ctx, m->full_name, pack_def(m, UPB_DEFTYPE_MSG)); + + oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n_oneof); + fields = google_protobuf_DescriptorProto_field(msg_proto, &n_field); + + CHK_OOM(upb_inttable_init2(&m->itof, UPB_CTYPE_CONSTPTR, ctx->alloc)); + CHK_OOM(upb_strtable_init2(&m->ntof, UPB_CTYPE_CONSTPTR, n_oneof + n_field, + ctx->alloc)); + + m->file = ctx->file; + m->map_entry = false; + + options = google_protobuf_DescriptorProto_options(msg_proto); + + if (options) { + m->map_entry = google_protobuf_MessageOptions_map_entry(options); + } + + if (ctx->layouts) { + m->layout = *ctx->layouts; + ctx->layouts++; + } else { + /* Allocate now (to allow cross-linking), populate later. */ + m->layout = symtab_alloc( + ctx, sizeof(*m->layout) + sizeof(_upb_fasttable_entry)); + } + + m->oneof_count = 0; + m->oneofs = symtab_alloc(ctx, sizeof(*m->oneofs) * n_oneof); + for (i = 0; i < n_oneof; i++) { + create_oneofdef(ctx, m, oneofs[i]); + } + + m->field_count = 0; + m->fields = symtab_alloc(ctx, sizeof(*m->fields) * n_field); + for (i = 0; i < n_field; i++) { + create_fielddef(ctx, m->full_name, m, fields[i]); + } + + assign_msg_indices(ctx, m); + finalize_oneofs(ctx, m); + assign_msg_wellknowntype(m); + upb_inttable_compact2(&m->itof, ctx->alloc); + + /* This message is built. Now build nested messages and enums. */ + + enums = google_protobuf_DescriptorProto_enum_type(msg_proto, &n); + for (i = 0; i < n; i++) { + create_enumdef(ctx, m->full_name, enums[i]); + } + + msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n); + for (i = 0; i < n; i++) { + create_msgdef(ctx, m->full_name, msgs[i]); + } +} + +static void count_types_in_msg(const google_protobuf_DescriptorProto *msg_proto, + upb_filedef *file) { + const google_protobuf_DescriptorProto *const *msgs; + size_t i, n; + + file->msg_count++; + + msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n); + for (i = 0; i < n; i++) { + count_types_in_msg(msgs[i], file); + } + + google_protobuf_DescriptorProto_enum_type(msg_proto, &n); + file->enum_count += n; + + google_protobuf_DescriptorProto_extension(msg_proto, &n); + file->ext_count += n; +} + +static void count_types_in_file( + const google_protobuf_FileDescriptorProto *file_proto, + upb_filedef *file) { + const google_protobuf_DescriptorProto *const *msgs; + size_t i, n; + + msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n); + for (i = 0; i < n; i++) { + count_types_in_msg(msgs[i], file); + } + + google_protobuf_FileDescriptorProto_enum_type(file_proto, &n); + file->enum_count += n; + + google_protobuf_FileDescriptorProto_extension(file_proto, &n); + file->ext_count += n; +} + +static void resolve_fielddef(symtab_addctx *ctx, const char *prefix, + upb_fielddef *f) { + upb_strview name; + const google_protobuf_FieldDescriptorProto *field_proto = f->sub.unresolved; + + if (f->is_extension_) { + if (!google_protobuf_FieldDescriptorProto_has_extendee(field_proto)) { + symtab_errf(ctx, "extension for field '%s' had no extendee", + f->full_name); + } + + name = google_protobuf_FieldDescriptorProto_extendee(field_proto); + f->msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG); + } + + if ((upb_fielddef_issubmsg(f) || f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) && + !google_protobuf_FieldDescriptorProto_has_type_name(field_proto)) { + symtab_errf(ctx, "field '%s' is missing type name", f->full_name); + } + + name = google_protobuf_FieldDescriptorProto_type_name(field_proto); + + if (upb_fielddef_issubmsg(f)) { + f->sub.msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG); + } else if (f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) { + f->sub.enumdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_ENUM); + } + + /* Have to delay resolving of the default value until now because of the enum + * case, since enum defaults are specified with a label. */ + if (google_protobuf_FieldDescriptorProto_has_default_value(field_proto)) { + upb_strview defaultval = + google_protobuf_FieldDescriptorProto_default_value(field_proto); + + if (f->file->syntax == UPB_SYNTAX_PROTO3) { + symtab_errf(ctx, "proto3 fields cannot have explicit defaults (%s)", + f->full_name); + } + + if (upb_fielddef_issubmsg(f)) { + symtab_errf(ctx, "message fields cannot have explicit defaults (%s)", + f->full_name); + } + + parse_default(ctx, defaultval.data, defaultval.size, f); + } else { + set_default_default(ctx, f); + } +} + +static void build_filedef( + symtab_addctx *ctx, upb_filedef *file, + const google_protobuf_FileDescriptorProto *file_proto) { + const google_protobuf_FileOptions *file_options_proto; + const google_protobuf_DescriptorProto *const *msgs; + const google_protobuf_EnumDescriptorProto *const *enums; + const google_protobuf_FieldDescriptorProto *const *exts; + const upb_strview* strs; + size_t i, n; + + count_types_in_file(file_proto, file); + + file->msgs = symtab_alloc(ctx, sizeof(*file->msgs) * file->msg_count); + file->enums = symtab_alloc(ctx, sizeof(*file->enums) * file->enum_count); + file->exts = symtab_alloc(ctx, sizeof(*file->exts) * file->ext_count); + + /* We increment these as defs are added. */ + file->msg_count = 0; + file->enum_count = 0; + file->ext_count = 0; + + if (!google_protobuf_FileDescriptorProto_has_name(file_proto)) { + symtab_errf(ctx, "File has no name"); + } + + file->name = + strviewdup(ctx, google_protobuf_FileDescriptorProto_name(file_proto)); + file->phpprefix = NULL; + file->phpnamespace = NULL; + + if (google_protobuf_FileDescriptorProto_has_package(file_proto)) { + upb_strview package = + google_protobuf_FileDescriptorProto_package(file_proto); + check_ident(ctx, package, true); + file->package = strviewdup(ctx, package); + } else { + file->package = NULL; + } + + if (google_protobuf_FileDescriptorProto_has_syntax(file_proto)) { + upb_strview syntax = + google_protobuf_FileDescriptorProto_syntax(file_proto); + + if (streql_view(syntax, "proto2")) { + file->syntax = UPB_SYNTAX_PROTO2; + } else if (streql_view(syntax, "proto3")) { + file->syntax = UPB_SYNTAX_PROTO3; + } else { + symtab_errf(ctx, "Invalid syntax '" UPB_STRVIEW_FORMAT "'", + UPB_STRVIEW_ARGS(syntax)); + } + } else { + file->syntax = UPB_SYNTAX_PROTO2; + } + + /* Read options. */ + file_options_proto = google_protobuf_FileDescriptorProto_options(file_proto); + if (file_options_proto) { + if (google_protobuf_FileOptions_has_php_class_prefix(file_options_proto)) { + file->phpprefix = strviewdup( + ctx, + google_protobuf_FileOptions_php_class_prefix(file_options_proto)); + } + if (google_protobuf_FileOptions_has_php_namespace(file_options_proto)) { + file->phpnamespace = strviewdup( + ctx, google_protobuf_FileOptions_php_namespace(file_options_proto)); + } + } + + /* Verify dependencies. */ + strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n); + file->deps = symtab_alloc(ctx, sizeof(*file->deps) * n); + + for (i = 0; i < n; i++) { + upb_strview dep_name = strs[i]; + upb_value v; + if (!upb_strtable_lookup2(&ctx->symtab->files, dep_name.data, + dep_name.size, &v)) { + symtab_errf(ctx, + "Depends on file '" UPB_STRVIEW_FORMAT + "', but it has not been loaded", + UPB_STRVIEW_ARGS(dep_name)); + } + file->deps[i] = upb_value_getconstptr(v); + } + + /* Create messages. */ + msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n); + for (i = 0; i < n; i++) { + create_msgdef(ctx, file->package, msgs[i]); + } + + /* Create enums. */ + enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n); + for (i = 0; i < n; i++) { + create_enumdef(ctx, file->package, enums[i]); + } + + /* Create extensions. */ + exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n); + file->exts = symtab_alloc(ctx, sizeof(*file->exts) * n); + for (i = 0; i < n; i++) { + create_fielddef(ctx, file->package, NULL, exts[i]); + } + + /* Now that all names are in the table, build layouts and resolve refs. */ + for (i = 0; i < (size_t)file->ext_count; i++) { + resolve_fielddef(ctx, file->package, (upb_fielddef*)&file->exts[i]); + } + + for (i = 0; i < (size_t)file->msg_count; i++) { + const upb_msgdef *m = &file->msgs[i]; + int j; + for (j = 0; j < m->field_count; j++) { + resolve_fielddef(ctx, m->full_name, (upb_fielddef*)&m->fields[j]); + } + } + + if (!ctx->layouts) { + for (i = 0; i < (size_t)file->msg_count; i++) { + const upb_msgdef *m = &file->msgs[i]; + make_layout(ctx, m); + } + } +} + +static void remove_filedef(upb_symtab *s, upb_filedef *file) { + upb_alloc *alloc = upb_arena_alloc(s->arena); + int i; + for (i = 0; i < file->msg_count; i++) { + const char *name = file->msgs[i].full_name; + upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc); + } + for (i = 0; i < file->enum_count; i++) { + const char *name = file->enums[i].full_name; + upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc); + } + for (i = 0; i < file->ext_count; i++) { + const char *name = file->exts[i].full_name; + upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc); + } +} + +static const upb_filedef *_upb_symtab_addfile( + upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto, + const upb_msglayout **layouts, upb_status *status) { + upb_arena *file_arena = upb_arena_new(); + upb_filedef *file; + symtab_addctx ctx; + + if (!file_arena) return NULL; + + file = upb_arena_malloc(file_arena, sizeof(*file)); + if (!file) goto done; + + ctx.file = file; + ctx.symtab = s; + ctx.file_arena = file_arena; + ctx.alloc = upb_arena_alloc(file_arena); + ctx.layouts = layouts; + ctx.status = status; + + file->msg_count = 0; + file->enum_count = 0; + file->ext_count = 0; + file->symtab = s; + + if (UPB_UNLIKELY(UPB_SETJMP(ctx.err))) { + UPB_ASSERT(!upb_ok(status)); + remove_filedef(s, file); + file = NULL; + } else { + build_filedef(&ctx, file, file_proto); + upb_strtable_insert3(&s->files, file->name, strlen(file->name), + upb_value_constptr(file), ctx.alloc); + UPB_ASSERT(upb_ok(status)); + upb_arena_fuse(s->arena, file_arena); + } + +done: + upb_arena_free(file_arena); + return file; +} + +const upb_filedef *upb_symtab_addfile( + upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto, + upb_status *status) { + return _upb_symtab_addfile(s, file_proto, NULL, status); +} + +/* Include here since we want most of this file to be stdio-free. */ +#include + +bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) { + /* Since this function should never fail (it would indicate a bug in upb) we + * print errors to stderr instead of returning error status to the user. */ + upb_def_init **deps = init->deps; + google_protobuf_FileDescriptorProto *file; + upb_arena *arena; + upb_status status; + + upb_status_clear(&status); + + if (upb_strtable_lookup(&s->files, init->filename, NULL)) { + return true; + } + + arena = upb_arena_new(); + + for (; *deps; deps++) { + if (!_upb_symtab_loaddefinit(s, *deps)) goto err; + } + + file = google_protobuf_FileDescriptorProto_parse_ex( + init->descriptor.data, init->descriptor.size, arena, UPB_DECODE_ALIAS); + s->bytes_loaded += init->descriptor.size; + + if (!file) { + upb_status_seterrf( + &status, + "Failed to parse compiled-in descriptor for file '%s'. This should " + "never happen.", + init->filename); + goto err; + } + + if (!_upb_symtab_addfile(s, file, init->layouts, &status)) goto err; + + upb_arena_free(arena); + return true; + +err: + fprintf(stderr, "Error loading compiled-in descriptor: %s\n", + upb_status_errmsg(&status)); + upb_arena_free(arena); + return false; +} + +size_t _upb_symtab_bytesloaded(const upb_symtab *s) { + return s->bytes_loaded; +} + +upb_arena *_upb_symtab_arena(const upb_symtab *s) { + return s->arena; +} + +#undef CHK_OOM + + +#include + + +static size_t get_field_size(const upb_msglayout_field *f) { + static unsigned char sizes[] = { + 0,/* 0 */ + 8, /* UPB_DESCRIPTOR_TYPE_DOUBLE */ + 4, /* UPB_DESCRIPTOR_TYPE_FLOAT */ + 8, /* UPB_DESCRIPTOR_TYPE_INT64 */ + 8, /* UPB_DESCRIPTOR_TYPE_UINT64 */ + 4, /* UPB_DESCRIPTOR_TYPE_INT32 */ + 8, /* UPB_DESCRIPTOR_TYPE_FIXED64 */ + 4, /* UPB_DESCRIPTOR_TYPE_FIXED32 */ + 1, /* UPB_DESCRIPTOR_TYPE_BOOL */ + sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_STRING */ + sizeof(void*), /* UPB_DESCRIPTOR_TYPE_GROUP */ + sizeof(void*), /* UPB_DESCRIPTOR_TYPE_MESSAGE */ + sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_BYTES */ + 4, /* UPB_DESCRIPTOR_TYPE_UINT32 */ + 4, /* UPB_DESCRIPTOR_TYPE_ENUM */ + 4, /* UPB_DESCRIPTOR_TYPE_SFIXED32 */ + 8, /* UPB_DESCRIPTOR_TYPE_SFIXED64 */ + 4, /* UPB_DESCRIPTOR_TYPE_SINT32 */ + 8, /* UPB_DESCRIPTOR_TYPE_SINT64 */ + }; + return _upb_repeated_or_map(f) ? sizeof(void *) : sizes[f->descriptortype]; +} + +/* Strings/bytes are special-cased in maps. */ +static char _upb_fieldtype_to_mapsize[12] = { + 0, + 1, /* UPB_TYPE_BOOL */ + 4, /* UPB_TYPE_FLOAT */ + 4, /* UPB_TYPE_INT32 */ + 4, /* UPB_TYPE_UINT32 */ + 4, /* UPB_TYPE_ENUM */ + sizeof(void*), /* UPB_TYPE_MESSAGE */ + 8, /* UPB_TYPE_DOUBLE */ + 8, /* UPB_TYPE_INT64 */ + 8, /* UPB_TYPE_UINT64 */ + 0, /* UPB_TYPE_STRING */ + 0, /* UPB_TYPE_BYTES */ +}; + +static const char _upb_fieldtype_to_sizelg2[12] = { + 0, + 0, /* UPB_TYPE_BOOL */ + 2, /* UPB_TYPE_FLOAT */ + 2, /* UPB_TYPE_INT32 */ + 2, /* UPB_TYPE_UINT32 */ + 2, /* UPB_TYPE_ENUM */ + UPB_SIZE(2, 3), /* UPB_TYPE_MESSAGE */ + 3, /* UPB_TYPE_DOUBLE */ + 3, /* UPB_TYPE_INT64 */ + 3, /* UPB_TYPE_UINT64 */ + UPB_SIZE(3, 4), /* UPB_TYPE_STRING */ + UPB_SIZE(3, 4), /* UPB_TYPE_BYTES */ +}; + +/** upb_msg *******************************************************************/ + +upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a) { + return _upb_msg_new(upb_msgdef_layout(m), a); +} + +static bool in_oneof(const upb_msglayout_field *field) { + return field->presence < 0; +} + +static upb_msgval _upb_msg_getraw(const upb_msg *msg, const upb_fielddef *f) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + const char *mem = UPB_PTR_AT(msg, field->offset, char); + upb_msgval val = {0}; + memcpy(&val, mem, get_field_size(field)); + return val; +} + +bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + if (in_oneof(field)) { + return _upb_getoneofcase_field(msg, field) == field->number; + } else if (field->presence > 0) { + return _upb_hasbit_field(msg, field); + } else { + UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE || + field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP); + return _upb_msg_getraw(msg, f).msg_val != NULL; + } +} + +const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg, + const upb_oneofdef *o) { + const upb_fielddef *f = upb_oneofdef_field(o, 0); + if (upb_oneofdef_issynthetic(o)) { + UPB_ASSERT(upb_oneofdef_fieldcount(o) == 1); + return upb_msg_has(msg, f) ? f : NULL; + } else { + const upb_msglayout_field *field = upb_fielddef_layout(f); + uint32_t oneof_case = _upb_getoneofcase_field(msg, field); + f = oneof_case ? upb_oneofdef_itof(o, oneof_case) : NULL; + UPB_ASSERT((f != NULL) == (oneof_case != 0)); + return f; + } +} + +upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f) { + if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) { + return _upb_msg_getraw(msg, f); + } else { + /* TODO(haberman): change upb_fielddef to not require this switch(). */ + upb_msgval val = {0}; + switch (upb_fielddef_type(f)) { + case UPB_TYPE_INT32: + case UPB_TYPE_ENUM: + val.int32_val = upb_fielddef_defaultint32(f); + break; + case UPB_TYPE_INT64: + val.int64_val = upb_fielddef_defaultint64(f); + break; + case UPB_TYPE_UINT32: + val.uint32_val = upb_fielddef_defaultuint32(f); + break; + case UPB_TYPE_UINT64: + val.uint64_val = upb_fielddef_defaultuint64(f); + break; + case UPB_TYPE_FLOAT: + val.float_val = upb_fielddef_defaultfloat(f); + break; + case UPB_TYPE_DOUBLE: + val.double_val = upb_fielddef_defaultdouble(f); + break; + case UPB_TYPE_BOOL: + val.bool_val = upb_fielddef_defaultbool(f); + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + val.str_val.data = upb_fielddef_defaultstr(f, &val.str_val.size); + break; + case UPB_TYPE_MESSAGE: + val.msg_val = NULL; + break; + } + return val; + } +} + +upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, + upb_arena *a) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + upb_mutmsgval ret; + char *mem = UPB_PTR_AT(msg, field->offset, char); + bool wrong_oneof = + in_oneof(field) && _upb_getoneofcase_field(msg, field) != field->number; + + memcpy(&ret, mem, sizeof(void*)); + + if (a && (!ret.msg || wrong_oneof)) { + if (upb_fielddef_ismap(f)) { + const upb_msgdef *entry = upb_fielddef_msgsubdef(f); + const upb_fielddef *key = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY); + const upb_fielddef *value = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE); + ret.map = upb_map_new(a, upb_fielddef_type(key), upb_fielddef_type(value)); + } else if (upb_fielddef_isseq(f)) { + ret.array = upb_array_new(a, upb_fielddef_type(f)); + } else { + UPB_ASSERT(upb_fielddef_issubmsg(f)); + ret.msg = upb_msg_new(upb_fielddef_msgsubdef(f), a); + } + + memcpy(mem, &ret, sizeof(void*)); + + if (wrong_oneof) { + *_upb_oneofcase_field(msg, field) = field->number; + } else if (field->presence > 0) { + _upb_sethas_field(msg, field); + } + } + return ret; +} + +void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val, + upb_arena *a) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + char *mem = UPB_PTR_AT(msg, field->offset, char); + UPB_UNUSED(a); /* We reserve the right to make set insert into a map. */ + memcpy(mem, &val, get_field_size(field)); + if (field->presence > 0) { + _upb_sethas_field(msg, field); + } else if (in_oneof(field)) { + *_upb_oneofcase_field(msg, field) = field->number; + } +} + +void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + char *mem = UPB_PTR_AT(msg, field->offset, char); + + if (field->presence > 0) { + _upb_clearhas_field(msg, field); + } else if (in_oneof(field)) { + uint32_t *oneof_case = _upb_oneofcase_field(msg, field); + if (*oneof_case != field->number) return; + *oneof_case = 0; + } + + memset(mem, 0, get_field_size(field)); +} + +void upb_msg_clear(upb_msg *msg, const upb_msgdef *m) { + _upb_msg_clear(msg, upb_msgdef_layout(m)); +} + +bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m, + const upb_symtab *ext_pool, const upb_fielddef **out_f, + upb_msgval *out_val, size_t *iter) { + int i = *iter; + int n = upb_msgdef_fieldcount(m); + const upb_msgval zero = {0}; + UPB_UNUSED(ext_pool); + while (++i < n) { + const upb_fielddef *f = upb_msgdef_field(m, i); + upb_msgval val = _upb_msg_getraw(msg, f); + + /* Skip field if unset or empty. */ + if (upb_fielddef_haspresence(f)) { + if (!upb_msg_has(msg, f)) continue; + } else { + upb_msgval test = val; + if (upb_fielddef_isstring(f) && !upb_fielddef_isseq(f)) { + /* Clear string pointer, only size matters (ptr could be non-NULL). */ + test.str_val.data = NULL; + } + /* Continue if NULL or 0. */ + if (memcmp(&test, &zero, sizeof(test)) == 0) continue; + + /* Continue on empty array or map. */ + if (upb_fielddef_ismap(f)) { + if (upb_map_size(test.map_val) == 0) continue; + } else if (upb_fielddef_isseq(f)) { + if (upb_array_size(test.array_val) == 0) continue; + } + } + + *out_val = val; + *out_f = f; + *iter = i; + return true; + } + *iter = i; + return false; +} + +bool _upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int depth) { + size_t iter = UPB_MSG_BEGIN; + const upb_fielddef *f; + upb_msgval val; + bool ret = true; + + if (--depth == 0) return false; + + _upb_msg_discardunknown_shallow(msg); + + while (upb_msg_next(msg, m, NULL /*ext_pool*/, &f, &val, &iter)) { + const upb_msgdef *subm = upb_fielddef_msgsubdef(f); + if (!subm) continue; + if (upb_fielddef_ismap(f)) { + const upb_fielddef *val_f = upb_msgdef_itof(subm, 2); + const upb_msgdef *val_m = upb_fielddef_msgsubdef(val_f); + upb_map *map = (upb_map*)val.map_val; + size_t iter = UPB_MAP_BEGIN; + + if (!val_m) continue; + + while (upb_mapiter_next(map, &iter)) { + upb_msgval map_val = upb_mapiter_value(map, iter); + if (!_upb_msg_discardunknown((upb_msg*)map_val.msg_val, val_m, depth)) { + ret = false; + } + } + } else if (upb_fielddef_isseq(f)) { + const upb_array *arr = val.array_val; + size_t i, n = upb_array_size(arr); + for (i = 0; i < n; i++) { + upb_msgval elem = upb_array_get(arr, i); + if (!_upb_msg_discardunknown((upb_msg*)elem.msg_val, subm, depth)) { + ret = false; + } + } + } else { + if (!_upb_msg_discardunknown((upb_msg*)val.msg_val, subm, depth)) { + ret = false; + } + } + } + + return ret; +} + +bool upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int maxdepth) { + return _upb_msg_discardunknown(msg, m, maxdepth); +} + +/** upb_array *****************************************************************/ + +upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type) { + return _upb_array_new(a, 4, _upb_fieldtype_to_sizelg2[type]); +} + +size_t upb_array_size(const upb_array *arr) { + return arr->len; +} + +upb_msgval upb_array_get(const upb_array *arr, size_t i) { + upb_msgval ret; + const char* data = _upb_array_constptr(arr); + int lg2 = arr->data & 7; + UPB_ASSERT(i < arr->len); + memcpy(&ret, data + (i << lg2), 1 << lg2); + return ret; +} + +void upb_array_set(upb_array *arr, size_t i, upb_msgval val) { + char* data = _upb_array_ptr(arr); + int lg2 = arr->data & 7; + UPB_ASSERT(i < arr->len); + memcpy(data + (i << lg2), &val, 1 << lg2); +} + +bool upb_array_append(upb_array *arr, upb_msgval val, upb_arena *arena) { + if (!_upb_array_realloc(arr, arr->len + 1, arena)) { + return false; + } + arr->len++; + upb_array_set(arr, arr->len - 1, val); + return true; +} + +bool upb_array_resize(upb_array *arr, size_t size, upb_arena *arena) { + return _upb_array_resize(arr, size, arena); +} + +/** upb_map *******************************************************************/ + +upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type, + upb_fieldtype_t value_type) { + return _upb_map_new(a, _upb_fieldtype_to_mapsize[key_type], + _upb_fieldtype_to_mapsize[value_type]); +} + +size_t upb_map_size(const upb_map *map) { + return _upb_map_size(map); +} + +bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) { + return _upb_map_get(map, &key, map->key_size, val, map->val_size); +} + +void upb_map_clear(upb_map *map) { + _upb_map_clear(map); +} + +bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, + upb_arena *arena) { + return _upb_map_set(map, &key, map->key_size, &val, map->val_size, arena); +} + +bool upb_map_delete(upb_map *map, upb_msgval key) { + return _upb_map_delete(map, &key, map->key_size); +} + +bool upb_mapiter_next(const upb_map *map, size_t *iter) { + return _upb_map_next(map, iter); +} + +bool upb_mapiter_done(const upb_map *map, size_t iter) { + upb_strtable_iter i; + UPB_ASSERT(iter != UPB_MAP_BEGIN); + i.t = &map->table; + i.index = iter; + return upb_strtable_done(&i); +} + +/* Returns the key and value for this entry of the map. */ +upb_msgval upb_mapiter_key(const upb_map *map, size_t iter) { + upb_strtable_iter i; + upb_msgval ret; + i.t = &map->table; + i.index = iter; + _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size); + return ret; +} + +upb_msgval upb_mapiter_value(const upb_map *map, size_t iter) { + upb_strtable_iter i; + upb_msgval ret; + i.t = &map->table; + i.index = iter; + _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size); + return ret; +} + +/* void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Special header, must be included last. */ + +typedef struct { + const char *ptr, *end; + upb_arena *arena; /* TODO: should we have a tmp arena for tmp data? */ + const upb_symtab *any_pool; + int depth; + upb_status *status; + jmp_buf err; + int line; + const char *line_begin; + bool is_first; + int options; + const upb_fielddef *debug_field; +} jsondec; + +enum { JD_OBJECT, JD_ARRAY, JD_STRING, JD_NUMBER, JD_TRUE, JD_FALSE, JD_NULL }; + +/* Forward declarations of mutually-recursive functions. */ +static void jsondec_wellknown(jsondec *d, upb_msg *msg, const upb_msgdef *m); +static upb_msgval jsondec_value(jsondec *d, const upb_fielddef *f); +static void jsondec_wellknownvalue(jsondec *d, upb_msg *msg, + const upb_msgdef *m); +static void jsondec_object(jsondec *d, upb_msg *msg, const upb_msgdef *m); + +static bool jsondec_streql(upb_strview str, const char *lit) { + return str.size == strlen(lit) && memcmp(str.data, lit, str.size) == 0; +} + +static bool jsondec_isnullvalue(const upb_fielddef *f) { + return upb_fielddef_type(f) == UPB_TYPE_ENUM && + strcmp(upb_enumdef_fullname(upb_fielddef_enumsubdef(f)), + "google.protobuf.NullValue") == 0; +} + +static bool jsondec_isvalue(const upb_fielddef *f) { + return (upb_fielddef_type(f) == UPB_TYPE_MESSAGE && + upb_msgdef_wellknowntype(upb_fielddef_msgsubdef(f)) == + UPB_WELLKNOWN_VALUE) || + jsondec_isnullvalue(f); +} + +UPB_NORETURN static void jsondec_err(jsondec *d, const char *msg) { + upb_status_seterrf(d->status, "Error parsing JSON @%d:%d: %s", d->line, + (int)(d->ptr - d->line_begin), msg); + UPB_LONGJMP(d->err, 1); +} + +UPB_PRINTF(2, 3) +UPB_NORETURN static void jsondec_errf(jsondec *d, const char *fmt, ...) { + va_list argp; + upb_status_seterrf(d->status, "Error parsing JSON @%d:%d: ", d->line, + (int)(d->ptr - d->line_begin)); + va_start(argp, fmt); + upb_status_vappenderrf(d->status, fmt, argp); + va_end(argp); + UPB_LONGJMP(d->err, 1); +} + +static void jsondec_skipws(jsondec *d) { + while (d->ptr != d->end) { + switch (*d->ptr) { + case '\n': + d->line++; + d->line_begin = d->ptr; + /* Fallthrough. */ + case '\r': + case '\t': + case ' ': + d->ptr++; + break; + default: + return; + } + } + jsondec_err(d, "Unexpected EOF"); +} + +static bool jsondec_tryparsech(jsondec *d, char ch) { + if (d->ptr == d->end || *d->ptr != ch) return false; + d->ptr++; + return true; +} + +static void jsondec_parselit(jsondec *d, const char *lit) { + size_t avail = d->end - d->ptr; + size_t len = strlen(lit); + if (avail < len || memcmp(d->ptr, lit, len) != 0) { + jsondec_errf(d, "Expected: '%s'", lit); + } + d->ptr += len; +} + +static void jsondec_wsch(jsondec *d, char ch) { + jsondec_skipws(d); + if (!jsondec_tryparsech(d, ch)) { + jsondec_errf(d, "Expected: '%c'", ch); + } +} + +static void jsondec_true(jsondec *d) { jsondec_parselit(d, "true"); } +static void jsondec_false(jsondec *d) { jsondec_parselit(d, "false"); } +static void jsondec_null(jsondec *d) { jsondec_parselit(d, "null"); } + +static void jsondec_entrysep(jsondec *d) { + jsondec_skipws(d); + jsondec_parselit(d, ":"); +} + +static int jsondec_rawpeek(jsondec *d) { + switch (*d->ptr) { + case '{': + return JD_OBJECT; + case '[': + return JD_ARRAY; + case '"': + return JD_STRING; + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return JD_NUMBER; + case 't': + return JD_TRUE; + case 'f': + return JD_FALSE; + case 'n': + return JD_NULL; + default: + jsondec_errf(d, "Unexpected character: '%c'", *d->ptr); + } +} + +/* JSON object/array **********************************************************/ + +/* These are used like so: + * + * jsondec_objstart(d); + * while (jsondec_objnext(d)) { + * ... + * } + * jsondec_objend(d) */ + +static int jsondec_peek(jsondec *d) { + jsondec_skipws(d); + return jsondec_rawpeek(d); +} + +static void jsondec_push(jsondec *d) { + if (--d->depth < 0) { + jsondec_err(d, "Recursion limit exceeded"); + } + d->is_first = true; +} + +static bool jsondec_seqnext(jsondec *d, char end_ch) { + bool is_first = d->is_first; + d->is_first = false; + jsondec_skipws(d); + if (*d->ptr == end_ch) return false; + if (!is_first) jsondec_parselit(d, ","); + return true; +} + +static void jsondec_arrstart(jsondec *d) { + jsondec_push(d); + jsondec_wsch(d, '['); +} + +static void jsondec_arrend(jsondec *d) { + d->depth++; + jsondec_wsch(d, ']'); +} + +static bool jsondec_arrnext(jsondec *d) { + return jsondec_seqnext(d, ']'); +} + +static void jsondec_objstart(jsondec *d) { + jsondec_push(d); + jsondec_wsch(d, '{'); +} + +static void jsondec_objend(jsondec *d) { + d->depth++; + jsondec_wsch(d, '}'); +} + +static bool jsondec_objnext(jsondec *d) { + if (!jsondec_seqnext(d, '}')) return false; + if (jsondec_peek(d) != JD_STRING) { + jsondec_err(d, "Object must start with string"); + } + return true; +} + +/* JSON number ****************************************************************/ + +static bool jsondec_tryskipdigits(jsondec *d) { + const char *start = d->ptr; + + while (d->ptr < d->end) { + if (*d->ptr < '0' || *d->ptr > '9') { + break; + } + d->ptr++; + } + + return d->ptr != start; +} + +static void jsondec_skipdigits(jsondec *d) { + if (!jsondec_tryskipdigits(d)) { + jsondec_err(d, "Expected one or more digits"); + } +} + +static double jsondec_number(jsondec *d) { + const char *start = d->ptr; + + assert(jsondec_rawpeek(d) == JD_NUMBER); + + /* Skip over the syntax of a number, as specified by JSON. */ + if (*d->ptr == '-') d->ptr++; + + if (jsondec_tryparsech(d, '0')) { + if (jsondec_tryskipdigits(d)) { + jsondec_err(d, "number cannot have leading zero"); + } + } else { + jsondec_skipdigits(d); + } + + if (d->ptr == d->end) goto parse; + if (jsondec_tryparsech(d, '.')) { + jsondec_skipdigits(d); + } + if (d->ptr == d->end) goto parse; + + if (*d->ptr == 'e' || *d->ptr == 'E') { + d->ptr++; + if (d->ptr == d->end) { + jsondec_err(d, "Unexpected EOF in number"); + } + if (*d->ptr == '+' || *d->ptr == '-') { + d->ptr++; + } + jsondec_skipdigits(d); + } + +parse: + /* Having verified the syntax of a JSON number, use strtod() to parse + * (strtod() accepts a superset of JSON syntax). */ + errno = 0; + { + char* end; + double val = strtod(start, &end); + assert(end == d->ptr); + + /* Currently the min/max-val conformance tests fail if we check this. Does + * this mean the conformance tests are wrong or strtod() is wrong, or + * something else? Investigate further. */ + /* + if (errno == ERANGE) { + jsondec_err(d, "Number out of range"); + } + */ + + if (val > DBL_MAX || val < -DBL_MAX) { + jsondec_err(d, "Number out of range"); + } + + return val; + } +} + +/* JSON string ****************************************************************/ + +static char jsondec_escape(jsondec *d) { + switch (*d->ptr++) { + case '"': + return '\"'; + case '\\': + return '\\'; + case '/': + return '/'; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + default: + jsondec_err(d, "Invalid escape char"); + } +} + +static uint32_t jsondec_codepoint(jsondec *d) { + uint32_t cp = 0; + const char *end; + + if (d->end - d->ptr < 4) { + jsondec_err(d, "EOF inside string"); + } + + end = d->ptr + 4; + while (d->ptr < end) { + char ch = *d->ptr++; + if (ch >= '0' && ch <= '9') { + ch -= '0'; + } else if (ch >= 'a' && ch <= 'f') { + ch = ch - 'a' + 10; + } else if (ch >= 'A' && ch <= 'F') { + ch = ch - 'A' + 10; + } else { + jsondec_err(d, "Invalid hex digit"); + } + cp = (cp << 4) | ch; + } + + return cp; +} + +/* Parses a \uXXXX unicode escape (possibly a surrogate pair). */ +static size_t jsondec_unicode(jsondec *d, char* out) { + uint32_t cp = jsondec_codepoint(d); + if (cp >= 0xd800 && cp <= 0xdbff) { + /* Surrogate pair: two 16-bit codepoints become a 32-bit codepoint. */ + uint32_t high = cp; + uint32_t low; + jsondec_parselit(d, "\\u"); + low = jsondec_codepoint(d); + if (low < 0xdc00 || low > 0xdfff) { + jsondec_err(d, "Invalid low surrogate"); + } + cp = (high & 0x3ff) << 10; + cp |= (low & 0x3ff); + cp += 0x10000; + } else if (cp >= 0xdc00 && cp <= 0xdfff) { + jsondec_err(d, "Unpaired low surrogate"); + } + + /* Write to UTF-8 */ + if (cp <= 0x7f) { + out[0] = cp; + return 1; + } else if (cp <= 0x07FF) { + out[0] = ((cp >> 6) & 0x1F) | 0xC0; + out[1] = ((cp >> 0) & 0x3F) | 0x80; + return 2; + } else if (cp <= 0xFFFF) { + out[0] = ((cp >> 12) & 0x0F) | 0xE0; + out[1] = ((cp >> 6) & 0x3F) | 0x80; + out[2] = ((cp >> 0) & 0x3F) | 0x80; + return 3; + } else if (cp < 0x10FFFF) { + out[0] = ((cp >> 18) & 0x07) | 0xF0; + out[1] = ((cp >> 12) & 0x3f) | 0x80; + out[2] = ((cp >> 6) & 0x3f) | 0x80; + out[3] = ((cp >> 0) & 0x3f) | 0x80; + return 4; + } else { + jsondec_err(d, "Invalid codepoint"); + } +} + +static void jsondec_resize(jsondec *d, char **buf, char **end, char **buf_end) { + size_t oldsize = *buf_end - *buf; + size_t len = *end - *buf; + size_t size = UPB_MAX(8, 2 * oldsize); + + *buf = upb_arena_realloc(d->arena, *buf, len, size); + if (!*buf) jsondec_err(d, "Out of memory"); + + *end = *buf + len; + *buf_end = *buf + size; +} + +static upb_strview jsondec_string(jsondec *d) { + char *buf = NULL; + char *end = NULL; + char *buf_end = NULL; + + jsondec_skipws(d); + + if (*d->ptr++ != '"') { + jsondec_err(d, "Expected string"); + } + + while (d->ptr < d->end) { + char ch = *d->ptr++; + + if (end == buf_end) { + jsondec_resize(d, &buf, &end, &buf_end); + } + + switch (ch) { + case '"': { + upb_strview ret; + ret.data = buf; + ret.size = end - buf; + *end = '\0'; /* Needed for possible strtod(). */ + return ret; + } + case '\\': + if (d->ptr == d->end) goto eof; + if (*d->ptr == 'u') { + d->ptr++; + if (buf_end - end < 4) { + /* Allow space for maximum-sized code point (4 bytes). */ + jsondec_resize(d, &buf, &end, &buf_end); + } + end += jsondec_unicode(d, end); + } else { + *end++ = jsondec_escape(d); + } + break; + default: + if ((unsigned char)*d->ptr < 0x20) { + jsondec_err(d, "Invalid char in JSON string"); + } + *end++ = ch; + break; + } + } + +eof: + jsondec_err(d, "EOF inside string"); +} + +static void jsondec_skipval(jsondec *d) { + switch (jsondec_peek(d)) { + case JD_OBJECT: + jsondec_objstart(d); + while (jsondec_objnext(d)) { + jsondec_string(d); + jsondec_entrysep(d); + jsondec_skipval(d); + } + jsondec_objend(d); + break; + case JD_ARRAY: + jsondec_arrstart(d); + while (jsondec_arrnext(d)) { + jsondec_skipval(d); + } + jsondec_arrend(d); + break; + case JD_TRUE: + jsondec_true(d); + break; + case JD_FALSE: + jsondec_false(d); + break; + case JD_NULL: + jsondec_null(d); + break; + case JD_STRING: + jsondec_string(d); + break; + case JD_NUMBER: + jsondec_number(d); + break; + } +} + +/* Base64 decoding for bytes fields. ******************************************/ + +static unsigned int jsondec_base64_tablelookup(const char ch) { + /* Table includes the normal base64 chars plus the URL-safe variant. */ + const signed char table[256] = { + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, 62 /*+*/, -1, 62 /*-*/, -1, 63 /*/ */, 52 /*0*/, + 53 /*1*/, 54 /*2*/, 55 /*3*/, 56 /*4*/, 57 /*5*/, 58 /*6*/, 59 /*7*/, + 60 /*8*/, 61 /*9*/, -1, -1, -1, -1, -1, + -1, -1, 0 /*A*/, 1 /*B*/, 2 /*C*/, 3 /*D*/, 4 /*E*/, + 5 /*F*/, 6 /*G*/, 07 /*H*/, 8 /*I*/, 9 /*J*/, 10 /*K*/, 11 /*L*/, + 12 /*M*/, 13 /*N*/, 14 /*O*/, 15 /*P*/, 16 /*Q*/, 17 /*R*/, 18 /*S*/, + 19 /*T*/, 20 /*U*/, 21 /*V*/, 22 /*W*/, 23 /*X*/, 24 /*Y*/, 25 /*Z*/, + -1, -1, -1, -1, 63 /*_*/, -1, 26 /*a*/, + 27 /*b*/, 28 /*c*/, 29 /*d*/, 30 /*e*/, 31 /*f*/, 32 /*g*/, 33 /*h*/, + 34 /*i*/, 35 /*j*/, 36 /*k*/, 37 /*l*/, 38 /*m*/, 39 /*n*/, 40 /*o*/, + 41 /*p*/, 42 /*q*/, 43 /*r*/, 44 /*s*/, 45 /*t*/, 46 /*u*/, 47 /*v*/, + 48 /*w*/, 49 /*x*/, 50 /*y*/, 51 /*z*/, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1}; + + /* Sign-extend return value so high bit will be set on any unexpected char. */ + return table[(unsigned)ch]; +} + +static char *jsondec_partialbase64(jsondec *d, const char *ptr, const char *end, + char *out) { + int32_t val = -1; + + switch (end - ptr) { + case 2: + val = jsondec_base64_tablelookup(ptr[0]) << 18 | + jsondec_base64_tablelookup(ptr[1]) << 12; + out[0] = val >> 16; + out += 1; + break; + case 3: + val = jsondec_base64_tablelookup(ptr[0]) << 18 | + jsondec_base64_tablelookup(ptr[1]) << 12 | + jsondec_base64_tablelookup(ptr[2]) << 6; + out[0] = val >> 16; + out[1] = (val >> 8) & 0xff; + out += 2; + break; + } + + if (val < 0) { + jsondec_err(d, "Corrupt base64"); + } + + return out; +} + +static size_t jsondec_base64(jsondec *d, upb_strview str) { + /* We decode in place. This is safe because this is a new buffer (not + * aliasing the input) and because base64 decoding shrinks 4 bytes into 3. */ + char *out = (char*)str.data; + const char *ptr = str.data; + const char *end = ptr + str.size; + const char *end4 = ptr + (str.size & -4); /* Round down to multiple of 4. */ + + for (; ptr < end4; ptr += 4, out += 3) { + int val = jsondec_base64_tablelookup(ptr[0]) << 18 | + jsondec_base64_tablelookup(ptr[1]) << 12 | + jsondec_base64_tablelookup(ptr[2]) << 6 | + jsondec_base64_tablelookup(ptr[3]) << 0; + + if (val < 0) { + /* Junk chars or padding. Remove trailing padding, if any. */ + if (end - ptr == 4 && ptr[3] == '=') { + if (ptr[2] == '=') { + end -= 2; + } else { + end -= 1; + } + } + break; + } + + out[0] = val >> 16; + out[1] = (val >> 8) & 0xff; + out[2] = val & 0xff; + } + + if (ptr < end) { + /* Process remaining chars. We do not require padding. */ + out = jsondec_partialbase64(d, ptr, end, out); + } + + return out - str.data; +} + +/* Low-level integer parsing **************************************************/ + +/* We use these hand-written routines instead of strto[u]l() because the "long + * long" variants aren't in c89. Also our version allows setting a ptr limit. */ + +static const char *jsondec_buftouint64(jsondec *d, const char *ptr, + const char *end, uint64_t *val) { + uint64_t u64 = 0; + while (ptr < end) { + unsigned ch = *ptr - '0'; + if (ch >= 10) break; + if (u64 > UINT64_MAX / 10 || u64 * 10 > UINT64_MAX - ch) { + jsondec_err(d, "Integer overflow"); + } + u64 *= 10; + u64 += ch; + ptr++; + } + + *val = u64; + return ptr; +} + +static const char *jsondec_buftoint64(jsondec *d, const char *ptr, + const char *end, int64_t *val) { + bool neg = false; + uint64_t u64; + + if (ptr != end && *ptr == '-') { + ptr++; + neg = true; + } + + ptr = jsondec_buftouint64(d, ptr, end, &u64); + if (u64 > (uint64_t)INT64_MAX + neg) { + jsondec_err(d, "Integer overflow"); + } + + *val = neg ? -u64 : u64; + return ptr; +} + +static uint64_t jsondec_strtouint64(jsondec *d, upb_strview str) { + const char *end = str.data + str.size; + uint64_t ret; + if (jsondec_buftouint64(d, str.data, end, &ret) != end) { + jsondec_err(d, "Non-number characters in quoted integer"); + } + return ret; +} + +static int64_t jsondec_strtoint64(jsondec *d, upb_strview str) { + const char *end = str.data + str.size; + int64_t ret; + if (jsondec_buftoint64(d, str.data, end, &ret) != end) { + jsondec_err(d, "Non-number characters in quoted integer"); + } + return ret; +} + +/* Primitive value types ******************************************************/ + +/* Parse INT32 or INT64 value. */ +static upb_msgval jsondec_int(jsondec *d, const upb_fielddef *f) { + upb_msgval val; + + switch (jsondec_peek(d)) { + case JD_NUMBER: { + double dbl = jsondec_number(d); + if (dbl > 9223372036854774784.0 || dbl < -9223372036854775808.0) { + jsondec_err(d, "JSON number is out of range."); + } + val.int64_val = dbl; /* must be guarded, overflow here is UB */ + if (val.int64_val != dbl) { + jsondec_errf(d, "JSON number was not integral (%f != %" PRId64 ")", dbl, + val.int64_val); + } + break; + } + case JD_STRING: { + upb_strview str = jsondec_string(d); + val.int64_val = jsondec_strtoint64(d, str); + break; + } + default: + jsondec_err(d, "Expected number or string"); + } + + if (upb_fielddef_type(f) == UPB_TYPE_INT32) { + if (val.int64_val > INT32_MAX || val.int64_val < INT32_MIN) { + jsondec_err(d, "Integer out of range."); + } + val.int32_val = (int32_t)val.int64_val; + } + + return val; +} + +/* Parse UINT32 or UINT64 value. */ +static upb_msgval jsondec_uint(jsondec *d, const upb_fielddef *f) { + upb_msgval val = {0}; + + switch (jsondec_peek(d)) { + case JD_NUMBER: { + double dbl = jsondec_number(d); + if (dbl > 18446744073709549568.0 || dbl < 0) { + jsondec_err(d, "JSON number is out of range."); + } + val.uint64_val = dbl; /* must be guarded, overflow here is UB */ + if (val.uint64_val != dbl) { + jsondec_errf(d, "JSON number was not integral (%f != %" PRIu64 ")", dbl, + val.uint64_val); + } + break; + } + case JD_STRING: { + upb_strview str = jsondec_string(d); + val.uint64_val = jsondec_strtouint64(d, str); + break; + } + default: + jsondec_err(d, "Expected number or string"); + } + + if (upb_fielddef_type(f) == UPB_TYPE_UINT32) { + if (val.uint64_val > UINT32_MAX) { + jsondec_err(d, "Integer out of range."); + } + val.uint32_val = (uint32_t)val.uint64_val; + } + + return val; +} + +/* Parse DOUBLE or FLOAT value. */ +static upb_msgval jsondec_double(jsondec *d, const upb_fielddef *f) { + upb_strview str; + upb_msgval val = {0}; + + switch (jsondec_peek(d)) { + case JD_NUMBER: + val.double_val = jsondec_number(d); + break; + case JD_STRING: + str = jsondec_string(d); + if (jsondec_streql(str, "NaN")) { + val.double_val = NAN; + } else if (jsondec_streql(str, "Infinity")) { + val.double_val = INFINITY; + } else if (jsondec_streql(str, "-Infinity")) { + val.double_val = -INFINITY; + } else { + val.double_val = strtod(str.data, NULL); + } + break; + default: + jsondec_err(d, "Expected number or string"); + } + + if (upb_fielddef_type(f) == UPB_TYPE_FLOAT) { + if (val.double_val != INFINITY && val.double_val != -INFINITY && + (val.double_val > FLT_MAX || val.double_val < -FLT_MAX)) { + jsondec_err(d, "Float out of range"); + } + val.float_val = val.double_val; + } + + return val; +} + +/* Parse STRING or BYTES value. */ +static upb_msgval jsondec_strfield(jsondec *d, const upb_fielddef *f) { + upb_msgval val; + val.str_val = jsondec_string(d); + if (upb_fielddef_type(f) == UPB_TYPE_BYTES) { + val.str_val.size = jsondec_base64(d, val.str_val); + } + return val; +} + +static upb_msgval jsondec_enum(jsondec *d, const upb_fielddef *f) { + switch (jsondec_peek(d)) { + case JD_STRING: { + const upb_enumdef *e = upb_fielddef_enumsubdef(f); + upb_strview str = jsondec_string(d); + upb_msgval val; + if (!upb_enumdef_ntoi(e, str.data, str.size, &val.int32_val)) { + if (d->options & UPB_JSONDEC_IGNOREUNKNOWN) { + val.int32_val = 0; + } else { + jsondec_errf(d, "Unknown enumerator: '" UPB_STRVIEW_FORMAT "'", + UPB_STRVIEW_ARGS(str)); + } + } + return val; + } + case JD_NULL: { + if (jsondec_isnullvalue(f)) { + upb_msgval val; + jsondec_null(d); + val.int32_val = 0; + return val; + } + } + /* Fallthrough. */ + default: + return jsondec_int(d, f); + } +} + +static upb_msgval jsondec_bool(jsondec *d, const upb_fielddef *f) { + bool is_map_key = upb_fielddef_number(f) == 1 && + upb_msgdef_mapentry(upb_fielddef_containingtype(f)); + upb_msgval val; + + if (is_map_key) { + upb_strview str = jsondec_string(d); + if (jsondec_streql(str, "true")) { + val.bool_val = true; + } else if (jsondec_streql(str, "false")) { + val.bool_val = false; + } else { + jsondec_err(d, "Invalid boolean map key"); + } + } else { + switch (jsondec_peek(d)) { + case JD_TRUE: + val.bool_val = true; + jsondec_true(d); + break; + case JD_FALSE: + val.bool_val = false; + jsondec_false(d); + break; + default: + jsondec_err(d, "Expected true or false"); + } + } + + return val; +} + +/* Composite types (array/message/map) ****************************************/ + +static void jsondec_array(jsondec *d, upb_msg *msg, const upb_fielddef *f) { + upb_array *arr = upb_msg_mutable(msg, f, d->arena).array; + + jsondec_arrstart(d); + while (jsondec_arrnext(d)) { + upb_msgval elem = jsondec_value(d, f); + upb_array_append(arr, elem, d->arena); + } + jsondec_arrend(d); +} + +static void jsondec_map(jsondec *d, upb_msg *msg, const upb_fielddef *f) { + upb_map *map = upb_msg_mutable(msg, f, d->arena).map; + const upb_msgdef *entry = upb_fielddef_msgsubdef(f); + const upb_fielddef *key_f = upb_msgdef_itof(entry, 1); + const upb_fielddef *val_f = upb_msgdef_itof(entry, 2); + + jsondec_objstart(d); + while (jsondec_objnext(d)) { + upb_msgval key, val; + key = jsondec_value(d, key_f); + jsondec_entrysep(d); + val = jsondec_value(d, val_f); + upb_map_set(map, key, val, d->arena); + } + jsondec_objend(d); +} + +static void jsondec_tomsg(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + if (upb_msgdef_wellknowntype(m) == UPB_WELLKNOWN_UNSPECIFIED) { + jsondec_object(d, msg, m); + } else { + jsondec_wellknown(d, msg, m); + } +} + +static upb_msgval jsondec_msg(jsondec *d, const upb_fielddef *f) { + const upb_msgdef *m = upb_fielddef_msgsubdef(f); + upb_msg *msg = upb_msg_new(m, d->arena); + upb_msgval val; + + jsondec_tomsg(d, msg, m); + val.msg_val = msg; + return val; +} + +static void jsondec_field(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + upb_strview name; + const upb_fielddef *f; + const upb_fielddef *preserved; + + name = jsondec_string(d); + jsondec_entrysep(d); + f = upb_msgdef_lookupjsonname(m, name.data, name.size); + + if (!f) { + if ((d->options & UPB_JSONDEC_IGNOREUNKNOWN) == 0) { + jsondec_errf(d, "No such field: " UPB_STRVIEW_FORMAT, + UPB_STRVIEW_ARGS(name)); + } + jsondec_skipval(d); + return; + } + + if (upb_fielddef_realcontainingoneof(f) && + upb_msg_whichoneof(msg, upb_fielddef_containingoneof(f))) { + jsondec_err(d, "More than one field for this oneof."); + } + + if (jsondec_peek(d) == JD_NULL && !jsondec_isvalue(f)) { + /* JSON "null" indicates a default value, so no need to set anything. */ + jsondec_null(d); + return; + } + + preserved = d->debug_field; + d->debug_field = f; + + if (upb_fielddef_ismap(f)) { + jsondec_map(d, msg, f); + } else if (upb_fielddef_isseq(f)) { + jsondec_array(d, msg, f); + } else if (upb_fielddef_issubmsg(f)) { + upb_msg *submsg = upb_msg_mutable(msg, f, d->arena).msg; + const upb_msgdef *subm = upb_fielddef_msgsubdef(f); + jsondec_tomsg(d, submsg, subm); + } else { + upb_msgval val = jsondec_value(d, f); + upb_msg_set(msg, f, val, d->arena); + } + + d->debug_field = preserved; +} + +static void jsondec_object(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + jsondec_objstart(d); + while (jsondec_objnext(d)) { + jsondec_field(d, msg, m); + } + jsondec_objend(d); +} + +static upb_msgval jsondec_value(jsondec *d, const upb_fielddef *f) { + switch (upb_fielddef_type(f)) { + case UPB_TYPE_BOOL: + return jsondec_bool(d, f); + case UPB_TYPE_FLOAT: + case UPB_TYPE_DOUBLE: + return jsondec_double(d, f); + case UPB_TYPE_UINT32: + case UPB_TYPE_UINT64: + return jsondec_uint(d, f); + case UPB_TYPE_INT32: + case UPB_TYPE_INT64: + return jsondec_int(d, f); + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + return jsondec_strfield(d, f); + case UPB_TYPE_ENUM: + return jsondec_enum(d, f); + case UPB_TYPE_MESSAGE: + return jsondec_msg(d, f); + default: + UPB_UNREACHABLE(); + } +} + +/* Well-known types ***********************************************************/ + +static int jsondec_tsdigits(jsondec *d, const char **ptr, size_t digits, + const char *after) { + uint64_t val; + const char *p = *ptr; + const char *end = p + digits; + size_t after_len = after ? strlen(after) : 0; + + UPB_ASSERT(digits <= 9); /* int can't overflow. */ + + if (jsondec_buftouint64(d, p, end, &val) != end || + (after_len && memcmp(end, after, after_len) != 0)) { + jsondec_err(d, "Malformed timestamp"); + } + + UPB_ASSERT(val < INT_MAX); + + *ptr = end + after_len; + return (int)val; +} + +static int jsondec_nanos(jsondec *d, const char **ptr, const char *end) { + uint64_t nanos = 0; + const char *p = *ptr; + + if (p != end && *p == '.') { + const char *nano_end = jsondec_buftouint64(d, p + 1, end, &nanos); + int digits = (int)(nano_end - p - 1); + int exp_lg10 = 9 - digits; + if (digits > 9) { + jsondec_err(d, "Too many digits for partial seconds"); + } + while (exp_lg10--) nanos *= 10; + *ptr = nano_end; + } + + UPB_ASSERT(nanos < INT_MAX); + + return (int)nanos; +} + +/* jsondec_epochdays(1970, 1, 1) == 1970-01-01 == 0. */ +int jsondec_epochdays(int y, int m, int d) { + const uint32_t year_base = 4800; /* Before min year, multiple of 400. */ + const uint32_t m_adj = m - 3; /* March-based month. */ + const uint32_t carry = m_adj > (uint32_t)m ? 1 : 0; + const uint32_t adjust = carry ? 12 : 0; + const uint32_t y_adj = y + year_base - carry; + const uint32_t month_days = ((m_adj + adjust) * 62719 + 769) / 2048; + const uint32_t leap_days = y_adj / 4 - y_adj / 100 + y_adj / 400; + return y_adj * 365 + leap_days + month_days + (d - 1) - 2472632; +} + +static int64_t jsondec_unixtime(int y, int m, int d, int h, int min, int s) { + return (int64_t)jsondec_epochdays(y, m, d) * 86400 + h * 3600 + min * 60 + s; +} + +static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + upb_msgval seconds; + upb_msgval nanos; + upb_strview str = jsondec_string(d); + const char *ptr = str.data; + const char *end = ptr + str.size; + + if (str.size < 20) goto malformed; + + { + /* 1972-01-01T01:00:00 */ + int year = jsondec_tsdigits(d, &ptr, 4, "-"); + int mon = jsondec_tsdigits(d, &ptr, 2, "-"); + int day = jsondec_tsdigits(d, &ptr, 2, "T"); + int hour = jsondec_tsdigits(d, &ptr, 2, ":"); + int min = jsondec_tsdigits(d, &ptr, 2, ":"); + int sec = jsondec_tsdigits(d, &ptr, 2, NULL); + + seconds.int64_val = jsondec_unixtime(year, mon, day, hour, min, sec); + } + + nanos.int32_val = jsondec_nanos(d, &ptr, end); + + { + /* [+-]08:00 or Z */ + int ofs_hour = 0; + int ofs_min = 0; + bool neg = false; + + if (ptr == end) goto malformed; + + switch (*ptr++) { + case '-': + neg = true; + /* fallthrough */ + case '+': + if ((end - ptr) != 5) goto malformed; + ofs_hour = jsondec_tsdigits(d, &ptr, 2, ":"); + ofs_min = jsondec_tsdigits(d, &ptr, 2, NULL); + ofs_min = ((ofs_hour * 60) + ofs_min) * 60; + seconds.int64_val += (neg ? ofs_min : -ofs_min); + break; + case 'Z': + if (ptr != end) goto malformed; + break; + default: + goto malformed; + } + } + + if (seconds.int64_val < -62135596800) { + jsondec_err(d, "Timestamp out of range"); + } + + upb_msg_set(msg, upb_msgdef_itof(m, 1), seconds, d->arena); + upb_msg_set(msg, upb_msgdef_itof(m, 2), nanos, d->arena); + return; + +malformed: + jsondec_err(d, "Malformed timestamp"); +} + +static void jsondec_duration(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + upb_msgval seconds; + upb_msgval nanos; + upb_strview str = jsondec_string(d); + const char *ptr = str.data; + const char *end = ptr + str.size; + const int64_t max = (uint64_t)3652500 * 86400; + + /* "3.000000001s", "3s", etc. */ + ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val); + nanos.int32_val = jsondec_nanos(d, &ptr, end); + + if (end - ptr != 1 || *ptr != 's') { + jsondec_err(d, "Malformed duration"); + } + + if (seconds.int64_val < -max || seconds.int64_val > max) { + jsondec_err(d, "Duration out of range"); + } + + if (seconds.int64_val < 0) { + nanos.int32_val = - nanos.int32_val; + } + + upb_msg_set(msg, upb_msgdef_itof(m, 1), seconds, d->arena); + upb_msg_set(msg, upb_msgdef_itof(m, 2), nanos, d->arena); +} + +static void jsondec_listvalue(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + const upb_fielddef *values_f = upb_msgdef_itof(m, 1); + const upb_msgdef *value_m = upb_fielddef_msgsubdef(values_f); + upb_array *values = upb_msg_mutable(msg, values_f, d->arena).array; + + jsondec_arrstart(d); + while (jsondec_arrnext(d)) { + upb_msg *value_msg = upb_msg_new(value_m, d->arena); + upb_msgval value; + value.msg_val = value_msg; + upb_array_append(values, value, d->arena); + jsondec_wellknownvalue(d, value_msg, value_m); + } + jsondec_arrend(d); +} + +static void jsondec_struct(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + const upb_fielddef *fields_f = upb_msgdef_itof(m, 1); + const upb_msgdef *entry_m = upb_fielddef_msgsubdef(fields_f); + const upb_fielddef *value_f = upb_msgdef_itof(entry_m, 2); + const upb_msgdef *value_m = upb_fielddef_msgsubdef(value_f); + upb_map *fields = upb_msg_mutable(msg, fields_f, d->arena).map; + + jsondec_objstart(d); + while (jsondec_objnext(d)) { + upb_msgval key, value; + upb_msg *value_msg = upb_msg_new(value_m, d->arena); + key.str_val = jsondec_string(d); + value.msg_val = value_msg; + upb_map_set(fields, key, value, d->arena); + jsondec_entrysep(d); + jsondec_wellknownvalue(d, value_msg, value_m); + } + jsondec_objend(d); +} + +static void jsondec_wellknownvalue(jsondec *d, upb_msg *msg, + const upb_msgdef *m) { + upb_msgval val; + const upb_fielddef *f; + upb_msg *submsg; + + switch (jsondec_peek(d)) { + case JD_NUMBER: + /* double number_value = 2; */ + f = upb_msgdef_itof(m, 2); + val.double_val = jsondec_number(d); + break; + case JD_STRING: + /* string string_value = 3; */ + f = upb_msgdef_itof(m, 3); + val.str_val = jsondec_string(d); + break; + case JD_FALSE: + /* bool bool_value = 4; */ + f = upb_msgdef_itof(m, 4); + val.bool_val = false; + jsondec_false(d); + break; + case JD_TRUE: + /* bool bool_value = 4; */ + f = upb_msgdef_itof(m, 4); + val.bool_val = true; + jsondec_true(d); + break; + case JD_NULL: + /* NullValue null_value = 1; */ + f = upb_msgdef_itof(m, 1); + val.int32_val = 0; + jsondec_null(d); + break; + /* Note: these cases return, because upb_msg_mutable() is enough. */ + case JD_OBJECT: + /* Struct struct_value = 5; */ + f = upb_msgdef_itof(m, 5); + submsg = upb_msg_mutable(msg, f, d->arena).msg; + jsondec_struct(d, submsg, upb_fielddef_msgsubdef(f)); + return; + case JD_ARRAY: + /* ListValue list_value = 6; */ + f = upb_msgdef_itof(m, 6); + submsg = upb_msg_mutable(msg, f, d->arena).msg; + jsondec_listvalue(d, submsg, upb_fielddef_msgsubdef(f)); + return; + default: + UPB_UNREACHABLE(); + } + + upb_msg_set(msg, f, val, d->arena); +} + +static upb_strview jsondec_mask(jsondec *d, const char *buf, const char *end) { + /* FieldMask fields grow due to inserted '_' characters, so we can't do the + * transform in place. */ + const char *ptr = buf; + upb_strview ret; + char *out; + + ret.size = end - ptr; + while (ptr < end) { + ret.size += (*ptr >= 'A' && *ptr <= 'Z'); + ptr++; + } + + out = upb_arena_malloc(d->arena, ret.size); + ptr = buf; + ret.data = out; + + while (ptr < end) { + char ch = *ptr++; + if (ch >= 'A' && ch <= 'Z') { + *out++ = '_'; + *out++ = ch + 32; + } else if (ch == '_') { + jsondec_err(d, "field mask may not contain '_'"); + } else { + *out++ = ch; + } + } + + return ret; +} + +static void jsondec_fieldmask(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + /* repeated string paths = 1; */ + const upb_fielddef *paths_f = upb_msgdef_itof(m, 1); + upb_array *arr = upb_msg_mutable(msg, paths_f, d->arena).array; + upb_strview str = jsondec_string(d); + const char *ptr = str.data; + const char *end = ptr + str.size; + upb_msgval val; + + while (ptr < end) { + const char *elem_end = memchr(ptr, ',', end - ptr); + if (elem_end) { + val.str_val = jsondec_mask(d, ptr, elem_end); + ptr = elem_end + 1; + } else { + val.str_val = jsondec_mask(d, ptr, end); + ptr = end; + } + upb_array_append(arr, val, d->arena); + } +} + +static void jsondec_anyfield(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + if (upb_msgdef_wellknowntype(m) == UPB_WELLKNOWN_UNSPECIFIED) { + /* For regular types: {"@type": "[user type]", "f1": , "f2": } + * where f1, f2, etc. are the normal fields of this type. */ + jsondec_field(d, msg, m); + } else { + /* For well-known types: {"@type": "[well-known type]", "value": } + * where is whatever encoding the WKT normally uses. */ + upb_strview str = jsondec_string(d); + jsondec_entrysep(d); + if (!jsondec_streql(str, "value")) { + jsondec_err(d, "Key for well-known type must be 'value'"); + } + jsondec_wellknown(d, msg, m); + } +} + +static const upb_msgdef *jsondec_typeurl(jsondec *d, upb_msg *msg, + const upb_msgdef *m) { + const upb_fielddef *type_url_f = upb_msgdef_itof(m, 1); + const upb_msgdef *type_m; + upb_strview type_url = jsondec_string(d); + const char *end = type_url.data + type_url.size; + const char *ptr = end; + upb_msgval val; + + val.str_val = type_url; + upb_msg_set(msg, type_url_f, val, d->arena); + + /* Find message name after the last '/' */ + while (ptr > type_url.data && *--ptr != '/') {} + + if (ptr == type_url.data || ptr == end) { + jsondec_err(d, "Type url must have at least one '/' and non-empty host"); + } + + ptr++; + type_m = upb_symtab_lookupmsg2(d->any_pool, ptr, end - ptr); + + if (!type_m) { + jsondec_err(d, "Type was not found"); + } + + return type_m; +} + +static void jsondec_any(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + /* string type_url = 1; + * bytes value = 2; */ + const upb_fielddef *value_f = upb_msgdef_itof(m, 2); + upb_msg *any_msg; + const upb_msgdef *any_m = NULL; + const char *pre_type_data = NULL; + const char *pre_type_end = NULL; + upb_msgval encoded; + + jsondec_objstart(d); + + /* Scan looking for "@type", which is not necessarily first. */ + while (!any_m && jsondec_objnext(d)) { + const char *start = d->ptr; + upb_strview name = jsondec_string(d); + jsondec_entrysep(d); + if (jsondec_streql(name, "@type")) { + any_m = jsondec_typeurl(d, msg, m); + if (pre_type_data) { + pre_type_end = start; + while (*pre_type_end != ',') pre_type_end--; + } + } else { + if (!pre_type_data) pre_type_data = start; + jsondec_skipval(d); + } + } + + if (!any_m) { + jsondec_err(d, "Any object didn't contain a '@type' field"); + } + + any_msg = upb_msg_new(any_m, d->arena); + + if (pre_type_data) { + size_t len = pre_type_end - pre_type_data + 1; + char *tmp = upb_arena_malloc(d->arena, len); + const char *saved_ptr = d->ptr; + const char *saved_end = d->end; + memcpy(tmp, pre_type_data, len - 1); + tmp[len - 1] = '}'; + d->ptr = tmp; + d->end = tmp + len; + d->is_first = true; + while (jsondec_objnext(d)) { + jsondec_anyfield(d, any_msg, any_m); + } + d->ptr = saved_ptr; + d->end = saved_end; + } + + while (jsondec_objnext(d)) { + jsondec_anyfield(d, any_msg, any_m); + } + + jsondec_objend(d); + + encoded.str_val.data = upb_encode(any_msg, upb_msgdef_layout(any_m), d->arena, + &encoded.str_val.size); + upb_msg_set(msg, value_f, encoded, d->arena); +} + +static void jsondec_wrapper(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + const upb_fielddef *value_f = upb_msgdef_itof(m, 1); + upb_msgval val = jsondec_value(d, value_f); + upb_msg_set(msg, value_f, val, d->arena); +} + +static void jsondec_wellknown(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + switch (upb_msgdef_wellknowntype(m)) { + case UPB_WELLKNOWN_ANY: + jsondec_any(d, msg, m); + break; + case UPB_WELLKNOWN_FIELDMASK: + jsondec_fieldmask(d, msg, m); + break; + case UPB_WELLKNOWN_DURATION: + jsondec_duration(d, msg, m); + break; + case UPB_WELLKNOWN_TIMESTAMP: + jsondec_timestamp(d, msg, m); + break; + case UPB_WELLKNOWN_VALUE: + jsondec_wellknownvalue(d, msg, m); + break; + case UPB_WELLKNOWN_LISTVALUE: + jsondec_listvalue(d, msg, m); + break; + case UPB_WELLKNOWN_STRUCT: + jsondec_struct(d, msg, m); + break; + case UPB_WELLKNOWN_DOUBLEVALUE: + case UPB_WELLKNOWN_FLOATVALUE: + case UPB_WELLKNOWN_INT64VALUE: + case UPB_WELLKNOWN_UINT64VALUE: + case UPB_WELLKNOWN_INT32VALUE: + case UPB_WELLKNOWN_UINT32VALUE: + case UPB_WELLKNOWN_STRINGVALUE: + case UPB_WELLKNOWN_BYTESVALUE: + case UPB_WELLKNOWN_BOOLVALUE: + jsondec_wrapper(d, msg, m); + break; + default: + UPB_UNREACHABLE(); + } +} + +bool upb_json_decode(const char *buf, size_t size, upb_msg *msg, + const upb_msgdef *m, const upb_symtab *any_pool, + int options, upb_arena *arena, upb_status *status) { + jsondec d; + d.ptr = buf; + d.end = buf + size; + d.arena = arena; + d.any_pool = any_pool; + d.status = status; + d.options = options; + d.depth = 64; + d.line = 1; + d.line_begin = d.ptr; + d.debug_field = NULL; + d.is_first = false; + + if (UPB_SETJMP(d.err)) return false; + + jsondec_tomsg(&d, msg, m); + return true; +} + + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Must be last. */ + +typedef struct { + char *buf, *ptr, *end; + size_t overflow; + int indent_depth; + int options; + const upb_symtab *ext_pool; + jmp_buf err; + upb_status *status; + upb_arena *arena; +} jsonenc; + +static void jsonenc_msg(jsonenc *e, const upb_msg *msg, const upb_msgdef *m); +static void jsonenc_scalar(jsonenc *e, upb_msgval val, const upb_fielddef *f); +static void jsonenc_msgfield(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m); +static void jsonenc_msgfields(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m); +static void jsonenc_value(jsonenc *e, const upb_msg *msg, const upb_msgdef *m); + +UPB_NORETURN static void jsonenc_err(jsonenc *e, const char *msg) { + upb_status_seterrmsg(e->status, msg); + longjmp(e->err, 1); +} + +UPB_PRINTF(2, 3) +UPB_NORETURN static void jsonenc_errf(jsonenc *e, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + upb_status_vseterrf(e->status, fmt, argp); + va_end(argp); + longjmp(e->err, 1); +} + +static upb_arena *jsonenc_arena(jsonenc *e) { + /* Create lazily, since it's only needed for Any */ + if (!e->arena) { + e->arena = upb_arena_new(); + } + return e->arena; +} + +static void jsonenc_putbytes(jsonenc *e, const void *data, size_t len) { + size_t have = e->end - e->ptr; + if (UPB_LIKELY(have >= len)) { + memcpy(e->ptr, data, len); + e->ptr += len; + } else { + if (have) memcpy(e->ptr, data, have); + e->ptr += have; + e->overflow += (len - have); + } +} + +static void jsonenc_putstr(jsonenc *e, const char *str) { + jsonenc_putbytes(e, str, strlen(str)); +} + +UPB_PRINTF(2, 3) +static void jsonenc_printf(jsonenc *e, const char *fmt, ...) { + size_t n; + size_t have = e->end - e->ptr; + va_list args; + + va_start(args, fmt); + n = vsnprintf(e->ptr, have, fmt, args); + va_end(args); + + if (UPB_LIKELY(have > n)) { + e->ptr += n; + } else { + e->ptr += have; + e->overflow += (n - have); + } +} + +static void jsonenc_nanos(jsonenc *e, int32_t nanos) { + int digits = 9; + + if (nanos == 0) return; + if (nanos < 0 || nanos >= 1000000000) { + jsonenc_err(e, "error formatting timestamp as JSON: invalid nanos"); + } + + while (nanos % 1000 == 0) { + nanos /= 1000; + digits -= 3; + } + + jsonenc_printf(e, ".%.*" PRId32, digits, nanos); +} + +static void jsonenc_timestamp(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m) { + const upb_fielddef *seconds_f = upb_msgdef_itof(m, 1); + const upb_fielddef *nanos_f = upb_msgdef_itof(m, 2); + int64_t seconds = upb_msg_get(msg, seconds_f).int64_val; + int32_t nanos = upb_msg_get(msg, nanos_f).int32_val; + int L, N, I, J, K, hour, min, sec; + + if (seconds < -62135596800) { + jsonenc_err(e, + "error formatting timestamp as JSON: minimum acceptable value " + "is 0001-01-01T00:00:00Z"); + } else if (seconds > 253402300799) { + jsonenc_err(e, + "error formatting timestamp as JSON: maximum acceptable value " + "is 9999-12-31T23:59:59Z"); + } + + /* Julian Day -> Y/M/D, Algorithm from: + * Fliegel, H. F., and Van Flandern, T. C., "A Machine Algorithm for + * Processing Calendar Dates," Communications of the Association of + * Computing Machines, vol. 11 (1968), p. 657. */ + L = (int)(seconds / 86400) + 68569 + 2440588; + N = 4 * L / 146097; + L = L - (146097 * N + 3) / 4; + I = 4000 * (L + 1) / 1461001; + L = L - 1461 * I / 4 + 31; + J = 80 * L / 2447; + K = L - 2447 * J / 80; + L = J / 11; + J = J + 2 - 12 * L; + I = 100 * (N - 49) + I + L; + + sec = seconds % 60; + min = (seconds / 60) % 60; + hour = (seconds / 3600) % 24; + + jsonenc_printf(e, "\"%04d-%02d-%02dT%02d:%02d:%02d", I, J, K, hour, min, sec); + jsonenc_nanos(e, nanos); + jsonenc_putstr(e, "Z\""); +} + +static void jsonenc_duration(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) { + const upb_fielddef *seconds_f = upb_msgdef_itof(m, 1); + const upb_fielddef *nanos_f = upb_msgdef_itof(m, 2); + int64_t seconds = upb_msg_get(msg, seconds_f).int64_val; + int32_t nanos = upb_msg_get(msg, nanos_f).int32_val; + + if (seconds > 315576000000 || seconds < -315576000000 || + (seconds < 0) != (nanos < 0)) { + jsonenc_err(e, "bad duration"); + } + + if (nanos < 0) { + nanos = -nanos; + } + + jsonenc_printf(e, "\"%" PRId64, seconds); + jsonenc_nanos(e, nanos); + jsonenc_putstr(e, "s\""); +} + +static void jsonenc_enum(int32_t val, const upb_fielddef *f, jsonenc *e) { + const upb_enumdef *e_def = upb_fielddef_enumsubdef(f); + + if (strcmp(upb_enumdef_fullname(e_def), "google.protobuf.NullValue") == 0) { + jsonenc_putstr(e, "null"); + } else { + const char *name = upb_enumdef_iton(e_def, val); + + if (name) { + jsonenc_printf(e, "\"%s\"", name); + } else { + jsonenc_printf(e, "%" PRId32, val); + } + } +} + +static void jsonenc_bytes(jsonenc *e, upb_strview str) { + /* This is the regular base64, not the "web-safe" version. */ + static const char base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + const unsigned char *ptr = (unsigned char*)str.data; + const unsigned char *end = ptr + str.size; + char buf[4]; + + jsonenc_putstr(e, "\""); + + while (end - ptr >= 3) { + buf[0] = base64[ptr[0] >> 2]; + buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)]; + buf[2] = base64[((ptr[1] & 0xf) << 2) | (ptr[2] >> 6)]; + buf[3] = base64[ptr[2] & 0x3f]; + jsonenc_putbytes(e, buf, 4); + ptr += 3; + } + + switch (end - ptr) { + case 2: + buf[0] = base64[ptr[0] >> 2]; + buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)]; + buf[2] = base64[(ptr[1] & 0xf) << 2]; + buf[3] = '='; + jsonenc_putbytes(e, buf, 4); + break; + case 1: + buf[0] = base64[ptr[0] >> 2]; + buf[1] = base64[((ptr[0] & 0x3) << 4)]; + buf[2] = '='; + buf[3] = '='; + jsonenc_putbytes(e, buf, 4); + break; + } + + jsonenc_putstr(e, "\""); +} + +static void jsonenc_stringbody(jsonenc *e, upb_strview str) { + const char *ptr = str.data; + const char *end = ptr + str.size; + + while (ptr < end) { + switch (*ptr) { + case '\n': + jsonenc_putstr(e, "\\n"); + break; + case '\r': + jsonenc_putstr(e, "\\r"); + break; + case '\t': + jsonenc_putstr(e, "\\t"); + break; + case '\"': + jsonenc_putstr(e, "\\\""); + break; + case '\f': + jsonenc_putstr(e, "\\f"); + break; + case '\b': + jsonenc_putstr(e, "\\b"); + break; + case '\\': + jsonenc_putstr(e, "\\\\"); + break; + default: + if ((uint8_t)*ptr < 0x20) { + jsonenc_printf(e, "\\u%04x", (int)(uint8_t)*ptr); + } else { + /* This could be a non-ASCII byte. We rely on the string being valid + * UTF-8. */ + jsonenc_putbytes(e, ptr, 1); + } + break; + } + ptr++; + } +} + +static void jsonenc_string(jsonenc *e, upb_strview str) { + jsonenc_putstr(e, "\""); + jsonenc_stringbody(e, str); + jsonenc_putstr(e, "\""); +} + +static void jsonenc_double(jsonenc *e, const char *fmt, double val) { + if (val == INFINITY) { + jsonenc_putstr(e, "\"Infinity\""); + } else if (val == -INFINITY) { + jsonenc_putstr(e, "\"-Infinity\""); + } else if (val != val) { + jsonenc_putstr(e, "\"NaN\""); + } else { + jsonenc_printf(e, fmt, val); + } +} + +static void jsonenc_wrapper(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m) { + const upb_fielddef *val_f = upb_msgdef_itof(m, 1); + upb_msgval val = upb_msg_get(msg, val_f); + jsonenc_scalar(e, val, val_f); +} + +static const upb_msgdef *jsonenc_getanymsg(jsonenc *e, upb_strview type_url) { + /* Find last '/', if any. */ + const char *end = type_url.data + type_url.size; + const char *ptr = end; + const upb_msgdef *ret; + + if (!e->ext_pool) { + jsonenc_err(e, "Tried to encode Any, but no symtab was provided"); + } + + if (type_url.size == 0) goto badurl; + + while (true) { + if (--ptr == type_url.data) { + /* Type URL must contain at least one '/', with host before. */ + goto badurl; + } + if (*ptr == '/') { + ptr++; + break; + } + } + + ret = upb_symtab_lookupmsg2(e->ext_pool, ptr, end - ptr); + + if (!ret) { + jsonenc_errf(e, "Couldn't find Any type: %.*s", (int)(end - ptr), ptr); + } + + return ret; + +badurl: + jsonenc_errf( + e, "Bad type URL: " UPB_STRVIEW_FORMAT, UPB_STRVIEW_ARGS(type_url)); +} + +static void jsonenc_any(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) { + const upb_fielddef *type_url_f = upb_msgdef_itof(m, 1); + const upb_fielddef *value_f = upb_msgdef_itof(m, 2); + upb_strview type_url = upb_msg_get(msg, type_url_f).str_val; + upb_strview value = upb_msg_get(msg, value_f).str_val; + const upb_msgdef *any_m = jsonenc_getanymsg(e, type_url); + const upb_msglayout *any_layout = upb_msgdef_layout(any_m); + upb_arena *arena = jsonenc_arena(e); + upb_msg *any = upb_msg_new(any_m, arena); + + if (!upb_decode(value.data, value.size, any, any_layout, arena)) { + jsonenc_err(e, "Error decoding message in Any"); + } + + jsonenc_putstr(e, "{\"@type\":"); + jsonenc_string(e, type_url); + jsonenc_putstr(e, ","); + + if (upb_msgdef_wellknowntype(any_m) == UPB_WELLKNOWN_UNSPECIFIED) { + /* Regular messages: {"@type": "...","foo": 1, "bar": 2} */ + jsonenc_msgfields(e, any, any_m); + } else { + /* Well-known type: {"@type": "...","value": } */ + jsonenc_putstr(e, "\"value\":"); + jsonenc_msgfield(e, any, any_m); + } + + jsonenc_putstr(e, "}"); +} + +static void jsonenc_putsep(jsonenc *e, const char *str, bool *first) { + if (*first) { + *first = false; + } else { + jsonenc_putstr(e, str); + } +} + +static void jsonenc_fieldpath(jsonenc *e, upb_strview path) { + const char *ptr = path.data; + const char *end = ptr + path.size; + + while (ptr < end) { + char ch = *ptr; + + if (ch >= 'A' && ch <= 'Z') { + jsonenc_err(e, "Field mask element may not have upper-case letter."); + } else if (ch == '_') { + if (ptr == end - 1 || *(ptr + 1) < 'a' || *(ptr + 1) > 'z') { + jsonenc_err(e, "Underscore must be followed by a lowercase letter."); + } + ch = *++ptr - 32; + } + + jsonenc_putbytes(e, &ch, 1); + ptr++; + } +} + +static void jsonenc_fieldmask(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m) { + const upb_fielddef *paths_f = upb_msgdef_itof(m, 1); + const upb_array *paths = upb_msg_get(msg, paths_f).array_val; + bool first = true; + size_t i, n = 0; + + if (paths) n = upb_array_size(paths); + + jsonenc_putstr(e, "\""); + + for (i = 0; i < n; i++) { + jsonenc_putsep(e, ",", &first); + jsonenc_fieldpath(e, upb_array_get(paths, i).str_val); + } + + jsonenc_putstr(e, "\""); +} + +static void jsonenc_struct(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m) { + const upb_fielddef *fields_f = upb_msgdef_itof(m, 1); + const upb_map *fields = upb_msg_get(msg, fields_f).map_val; + const upb_msgdef *entry_m = upb_fielddef_msgsubdef(fields_f); + const upb_fielddef *value_f = upb_msgdef_itof(entry_m, 2); + size_t iter = UPB_MAP_BEGIN; + bool first = true; + + jsonenc_putstr(e, "{"); + + if (fields) { + while (upb_mapiter_next(fields, &iter)) { + upb_msgval key = upb_mapiter_key(fields, iter); + upb_msgval val = upb_mapiter_value(fields, iter); + + jsonenc_putsep(e, ",", &first); + jsonenc_string(e, key.str_val); + jsonenc_putstr(e, ":"); + jsonenc_value(e, val.msg_val, upb_fielddef_msgsubdef(value_f)); + } + } + + jsonenc_putstr(e, "}"); +} + +static void jsonenc_listvalue(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m) { + const upb_fielddef *values_f = upb_msgdef_itof(m, 1); + const upb_msgdef *values_m = upb_fielddef_msgsubdef(values_f); + const upb_array *values = upb_msg_get(msg, values_f).array_val; + size_t i; + bool first = true; + + jsonenc_putstr(e, "["); + + if (values) { + const size_t size = upb_array_size(values); + for (i = 0; i < size; i++) { + upb_msgval elem = upb_array_get(values, i); + + jsonenc_putsep(e, ",", &first); + jsonenc_value(e, elem.msg_val, values_m); + } + } + + jsonenc_putstr(e, "]"); +} + +static void jsonenc_value(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) { + /* TODO(haberman): do we want a reflection method to get oneof case? */ + size_t iter = UPB_MSG_BEGIN; + const upb_fielddef *f; + upb_msgval val; + + if (!upb_msg_next(msg, m, NULL, &f, &val, &iter)) { + jsonenc_err(e, "No value set in Value proto"); + } + + switch (upb_fielddef_number(f)) { + case 1: + jsonenc_putstr(e, "null"); + break; + case 2: + jsonenc_double(e, "%.17g", val.double_val); + break; + case 3: + jsonenc_string(e, val.str_val); + break; + case 4: + jsonenc_putstr(e, val.bool_val ? "true" : "false"); + break; + case 5: + jsonenc_struct(e, val.msg_val, upb_fielddef_msgsubdef(f)); + break; + case 6: + jsonenc_listvalue(e, val.msg_val, upb_fielddef_msgsubdef(f)); + break; + } +} + +static void jsonenc_msgfield(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m) { + switch (upb_msgdef_wellknowntype(m)) { + case UPB_WELLKNOWN_UNSPECIFIED: + jsonenc_msg(e, msg, m); + break; + case UPB_WELLKNOWN_ANY: + jsonenc_any(e, msg, m); + break; + case UPB_WELLKNOWN_FIELDMASK: + jsonenc_fieldmask(e, msg, m); + break; + case UPB_WELLKNOWN_DURATION: + jsonenc_duration(e, msg, m); + break; + case UPB_WELLKNOWN_TIMESTAMP: + jsonenc_timestamp(e, msg, m); + break; + case UPB_WELLKNOWN_DOUBLEVALUE: + case UPB_WELLKNOWN_FLOATVALUE: + case UPB_WELLKNOWN_INT64VALUE: + case UPB_WELLKNOWN_UINT64VALUE: + case UPB_WELLKNOWN_INT32VALUE: + case UPB_WELLKNOWN_UINT32VALUE: + case UPB_WELLKNOWN_STRINGVALUE: + case UPB_WELLKNOWN_BYTESVALUE: + case UPB_WELLKNOWN_BOOLVALUE: + jsonenc_wrapper(e, msg, m); + break; + case UPB_WELLKNOWN_VALUE: + jsonenc_value(e, msg, m); + break; + case UPB_WELLKNOWN_LISTVALUE: + jsonenc_listvalue(e, msg, m); + break; + case UPB_WELLKNOWN_STRUCT: + jsonenc_struct(e, msg, m); + break; + } +} + +static void jsonenc_scalar(jsonenc *e, upb_msgval val, const upb_fielddef *f) { + switch (upb_fielddef_type(f)) { + case UPB_TYPE_BOOL: + jsonenc_putstr(e, val.bool_val ? "true" : "false"); + break; + case UPB_TYPE_FLOAT: + jsonenc_double(e, "%.9g", val.float_val); + break; + case UPB_TYPE_DOUBLE: + jsonenc_double(e, "%.17g", val.double_val); + break; + case UPB_TYPE_INT32: + jsonenc_printf(e, "%" PRId32, val.int32_val); + break; + case UPB_TYPE_UINT32: + jsonenc_printf(e, "%" PRIu32, val.uint32_val); + break; + case UPB_TYPE_INT64: + jsonenc_printf(e, "\"%" PRId64 "\"", val.int64_val); + break; + case UPB_TYPE_UINT64: + jsonenc_printf(e, "\"%" PRIu64 "\"", val.uint64_val); + break; + case UPB_TYPE_STRING: + jsonenc_string(e, val.str_val); + break; + case UPB_TYPE_BYTES: + jsonenc_bytes(e, val.str_val); + break; + case UPB_TYPE_ENUM: + jsonenc_enum(val.int32_val, f, e); + break; + case UPB_TYPE_MESSAGE: + jsonenc_msgfield(e, val.msg_val, upb_fielddef_msgsubdef(f)); + break; + } +} + +static void jsonenc_mapkey(jsonenc *e, upb_msgval val, const upb_fielddef *f) { + jsonenc_putstr(e, "\""); + + switch (upb_fielddef_type(f)) { + case UPB_TYPE_BOOL: + jsonenc_putstr(e, val.bool_val ? "true" : "false"); + break; + case UPB_TYPE_INT32: + jsonenc_printf(e, "%" PRId32, val.int32_val); + break; + case UPB_TYPE_UINT32: + jsonenc_printf(e, "%" PRIu32, val.uint32_val); + break; + case UPB_TYPE_INT64: + jsonenc_printf(e, "%" PRId64, val.int64_val); + break; + case UPB_TYPE_UINT64: + jsonenc_printf(e, "%" PRIu64, val.uint64_val); + break; + case UPB_TYPE_STRING: + jsonenc_stringbody(e, val.str_val); + break; + default: + UPB_UNREACHABLE(); + } + + jsonenc_putstr(e, "\":"); +} + +static void jsonenc_array(jsonenc *e, const upb_array *arr, + const upb_fielddef *f) { + size_t i; + size_t size = arr ? upb_array_size(arr) : 0; + bool first = true; + + jsonenc_putstr(e, "["); + + for (i = 0; i < size; i++) { + jsonenc_putsep(e, ",", &first); + jsonenc_scalar(e, upb_array_get(arr, i), f); + } + + jsonenc_putstr(e, "]"); +} + +static void jsonenc_map(jsonenc *e, const upb_map *map, const upb_fielddef *f) { + const upb_msgdef *entry = upb_fielddef_msgsubdef(f); + const upb_fielddef *key_f = upb_msgdef_itof(entry, 1); + const upb_fielddef *val_f = upb_msgdef_itof(entry, 2); + size_t iter = UPB_MAP_BEGIN; + bool first = true; + + jsonenc_putstr(e, "{"); + + if (map) { + while (upb_mapiter_next(map, &iter)) { + jsonenc_putsep(e, ",", &first); + jsonenc_mapkey(e, upb_mapiter_key(map, iter), key_f); + jsonenc_scalar(e, upb_mapiter_value(map, iter), val_f); + } + } + + jsonenc_putstr(e, "}"); +} + +static void jsonenc_fieldval(jsonenc *e, const upb_fielddef *f, + upb_msgval val, bool *first) { + const char *name; + + if (e->options & UPB_JSONENC_PROTONAMES) { + name = upb_fielddef_name(f); + } else { + name = upb_fielddef_jsonname(f); + } + + jsonenc_putsep(e, ",", first); + jsonenc_printf(e, "\"%s\":", name); + + if (upb_fielddef_ismap(f)) { + jsonenc_map(e, val.map_val, f); + } else if (upb_fielddef_isseq(f)) { + jsonenc_array(e, val.array_val, f); + } else { + jsonenc_scalar(e, val, f); + } +} + +static void jsonenc_msgfields(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m) { + upb_msgval val; + const upb_fielddef *f; + bool first = true; + + if (e->options & UPB_JSONENC_EMITDEFAULTS) { + /* Iterate over all fields. */ + int i = 0; + int n = upb_msgdef_fieldcount(m); + for (i = 0; i < n; i++) { + f = upb_msgdef_field(m, i); + if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) { + jsonenc_fieldval(e, f, upb_msg_get(msg, f), &first); + } + } + } else { + /* Iterate over non-empty fields. */ + size_t iter = UPB_MSG_BEGIN; + while (upb_msg_next(msg, m, e->ext_pool, &f, &val, &iter)) { + jsonenc_fieldval(e, f, val, &first); + } + } +} + +static void jsonenc_msg(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) { + jsonenc_putstr(e, "{"); + jsonenc_msgfields(e, msg, m); + jsonenc_putstr(e, "}"); +} + +static size_t jsonenc_nullz(jsonenc *e, size_t size) { + size_t ret = e->ptr - e->buf + e->overflow; + + if (size > 0) { + if (e->ptr == e->end) e->ptr--; + *e->ptr = '\0'; + } + + return ret; +} + +size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m, + const upb_symtab *ext_pool, int options, char *buf, + size_t size, upb_status *status) { + jsonenc e; + + e.buf = buf; + e.ptr = buf; + e.end = buf + size; + e.overflow = 0; + e.options = options; + e.ext_pool = ext_pool; + e.status = status; + e.arena = NULL; + + if (setjmp(e.err)) return -1; + + jsonenc_msgfield(&e, msg, m); + if (e.arena) upb_arena_free(e.arena); + return jsonenc_nullz(&e, size); +} +/* See port_def.inc. This should #undef all macros #defined there. */ + +#undef UPB_MAPTYPE_STRING +#undef UPB_SIZE +#undef UPB_PTR_AT +#undef UPB_READ_ONEOF +#undef UPB_WRITE_ONEOF +#undef UPB_INLINE +#undef UPB_ALIGN_UP +#undef UPB_ALIGN_DOWN +#undef UPB_ALIGN_MALLOC +#undef UPB_ALIGN_OF +#undef UPB_FORCEINLINE +#undef UPB_NOINLINE +#undef UPB_NORETURN +#undef UPB_MAX +#undef UPB_MIN +#undef UPB_UNUSED +#undef UPB_ASSUME +#undef UPB_ASSERT +#undef UPB_UNREACHABLE +#undef UPB_POISON_MEMORY_REGION +#undef UPB_UNPOISON_MEMORY_REGION +#undef UPB_ASAN diff --git a/php/ext/google/protobuf/php-upb.h b/php/ext/google/protobuf/php-upb.h new file mode 100644 index 0000000000000..bd72cd9c081fa --- /dev/null +++ b/php/ext/google/protobuf/php-upb.h @@ -0,0 +1,4612 @@ +/* Amalgamated source file */ +#include /* +* This is where we define macros used across upb. +* +* All of these macros are undef'd in port_undef.inc to avoid leaking them to +* users. +* +* The correct usage is: +* +* #include "upb/foobar.h" +* #include "upb/baz.h" +* +* // MUST be last included header. +* #include "upb/port_def.inc" +* +* // Code for this file. +* // <...> +* +* // Can be omitted for .c files, required for .h. +* #include "upb/port_undef.inc" +* +* This file is private and must not be included by users! +*/ + +#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) || \ + (defined(_MSC_VER) && _MSC_VER >= 1900)) +#error upb requires C99 or C++11 or MSVC >= 2015. +#endif + +#include +#include + +#if UINTPTR_MAX == 0xffffffff +#define UPB_SIZE(size32, size64) size32 +#else +#define UPB_SIZE(size32, size64) size64 +#endif + +/* If we always read/write as a consistent type to each address, this shouldn't + * violate aliasing. + */ +#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs))) + +#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \ + *UPB_PTR_AT(msg, case_offset, int) == case_val \ + ? *UPB_PTR_AT(msg, offset, fieldtype) \ + : default + +#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \ + *UPB_PTR_AT(msg, case_offset, int) = case_val; \ + *UPB_PTR_AT(msg, offset, fieldtype) = value; + +#define UPB_MAPTYPE_STRING 0 + +/* UPB_INLINE: inline if possible, emit standalone code if required. */ +#ifdef __cplusplus +#define UPB_INLINE inline +#elif defined (__GNUC__) || defined(__clang__) +#define UPB_INLINE static __inline__ +#else +#define UPB_INLINE static +#endif + +#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align)) +#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align)) +#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16) +#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member) + +/* Hints to the compiler about likely/unlikely branches. */ +#if defined (__GNUC__) || defined(__clang__) +#define UPB_LIKELY(x) __builtin_expect((x),1) +#define UPB_UNLIKELY(x) __builtin_expect((x),0) +#else +#define UPB_LIKELY(x) (x) +#define UPB_UNLIKELY(x) (x) +#endif + +/* Macros for function attributes on compilers that support them. */ +#ifdef __GNUC__ +#define UPB_FORCEINLINE __inline__ __attribute__((always_inline)) +#define UPB_NOINLINE __attribute__((noinline)) +#define UPB_NORETURN __attribute__((__noreturn__)) +#define UPB_PRINTF(str, first_vararg) __attribute__((format (printf, str, first_vararg))) +#elif defined(_MSC_VER) +#define UPB_NOINLINE +#define UPB_FORCEINLINE +#define UPB_NORETURN __declspec(noreturn) +#define UPB_PRINTF(str, first_vararg) +#else /* !defined(__GNUC__) */ +#define UPB_FORCEINLINE +#define UPB_NOINLINE +#define UPB_NORETURN +#define UPB_PRINTF(str, first_vararg) +#endif + +#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) +#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y)) + +#define UPB_UNUSED(var) (void)var + +/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true. + */ +#ifdef NDEBUG +#ifdef __GNUC__ +#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable() +#elif defined _MSC_VER +#define UPB_ASSUME(expr) if (!(expr)) __assume(0) +#else +#define UPB_ASSUME(expr) do {} while (false && (expr)) +#endif +#else +#define UPB_ASSUME(expr) assert(expr) +#endif + +/* UPB_ASSERT(): in release mode, we use the expression without letting it be + * evaluated. This prevents "unused variable" warnings. */ +#ifdef NDEBUG +#define UPB_ASSERT(expr) do {} while (false && (expr)) +#else +#define UPB_ASSERT(expr) assert(expr) +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0) +#else +#define UPB_UNREACHABLE() do { assert(0); } while(0) +#endif + +/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */ +#ifdef __APPLE__ +#define UPB_SETJMP(buf) _setjmp(buf) +#define UPB_LONGJMP(buf, val) _longjmp(buf, val) +#else +#define UPB_SETJMP(buf) setjmp(buf) +#define UPB_LONGJMP(buf, val) longjmp(buf, val) +#endif + +/* Configure whether fasttable is switched on or not. *************************/ + +#if defined(__x86_64__) && defined(__GNUC__) +#define UPB_FASTTABLE_SUPPORTED 1 +#else +#define UPB_FASTTABLE_SUPPORTED 0 +#endif + +/* define UPB_ENABLE_FASTTABLE to force fast table support. + * This is useful when we want to ensure we are really getting fasttable, + * for example for testing or benchmarking. */ +#if defined(UPB_ENABLE_FASTTABLE) +#if !UPB_FASTTABLE_SUPPORTED +#error fasttable is x86-64 + Clang/GCC only +#endif +#define UPB_FASTTABLE 1 +/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible. + * This is useful for releasing code that might be used on multiple platforms, + * for example the PHP or Ruby C extensions. */ +#elif defined(UPB_TRY_ENABLE_FASTTABLE) +#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED +#else +#define UPB_FASTTABLE 0 +#endif + +/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully + * degrade to non-fasttable if we are using UPB_TRY_ENABLE_FASTTABLE. */ +#if !UPB_FASTTABLE && defined(UPB_TRY_ENABLE_FASTTABLE) +#define UPB_FASTTABLE_INIT(...) +#else +#define UPB_FASTTABLE_INIT(...) __VA_ARGS__ +#endif + +#undef UPB_FASTTABLE_SUPPORTED + +/* ASAN poisoning (for arena) *************************************************/ + +#if defined(__SANITIZE_ADDRESS__) +#define UPB_ASAN 1 +#ifdef __cplusplus +extern "C" { +#endif +void __asan_poison_memory_region(void const volatile *addr, size_t size); +void __asan_unpoison_memory_region(void const volatile *addr, size_t size); +#ifdef __cplusplus +} /* extern "C" */ +#endif +#define UPB_POISON_MEMORY_REGION(addr, size) \ + __asan_poison_memory_region((addr), (size)) +#define UPB_UNPOISON_MEMORY_REGION(addr, size) \ + __asan_unpoison_memory_region((addr), (size)) +#else +#define UPB_ASAN 0 +#define UPB_POISON_MEMORY_REGION(addr, size) \ + ((void)(addr), (void)(size)) +#define UPB_UNPOISON_MEMORY_REGION(addr, size) \ + ((void)(addr), (void)(size)) +#endif +/* +** upb_decode: parsing into a upb_msg using a upb_msglayout. +*/ + +#ifndef UPB_DECODE_H_ +#define UPB_DECODE_H_ + +/* +** Our memory representation for parsing tables and messages themselves. +** Functions in this file are used by generated code and possibly reflection. +** +** The definitions in this file are internal to upb. +**/ + +#ifndef UPB_MSG_H_ +#define UPB_MSG_H_ + +#include +#include +#include + +/* +** upb_table +** +** This header is INTERNAL-ONLY! Its interfaces are not public or stable! +** This file defines very fast int->upb_value (inttable) and string->upb_value +** (strtable) hash tables. +** +** The table uses chained scatter with Brent's variation (inspired by the Lua +** implementation of hash tables). The hash function for strings is Austin +** Appleby's "MurmurHash." +** +** The inttable uses uintptr_t as its key, which guarantees it can be used to +** store pointers or integers of at least 32 bits (upb isn't really useful on +** systems where sizeof(void*) < 4). +** +** The table must be homogeneous (all values of the same type). In debug +** mode, we check this on insert and lookup. +*/ + +#ifndef UPB_TABLE_H_ +#define UPB_TABLE_H_ + +#include +#include +/* +** This file contains shared definitions that are widely used across upb. +*/ + +#ifndef UPB_H_ +#define UPB_H_ + +#include +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/* upb_status *****************************************************************/ + +#define UPB_STATUS_MAX_MESSAGE 127 + +typedef struct { + bool ok; + char msg[UPB_STATUS_MAX_MESSAGE]; /* Error message; NULL-terminated. */ +} upb_status; + +const char *upb_status_errmsg(const upb_status *status); +bool upb_ok(const upb_status *status); + +/* These are no-op if |status| is NULL. */ +void upb_status_clear(upb_status *status); +void upb_status_seterrmsg(upb_status *status, const char *msg); +void upb_status_seterrf(upb_status *status, const char *fmt, ...) + UPB_PRINTF(2, 3); +void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) + UPB_PRINTF(2, 0); +void upb_status_vappenderrf(upb_status *status, const char *fmt, va_list args) + UPB_PRINTF(2, 0); + +/** upb_strview ************************************************************/ + +typedef struct { + const char *data; + size_t size; +} upb_strview; + +UPB_INLINE upb_strview upb_strview_make(const char *data, size_t size) { + upb_strview ret; + ret.data = data; + ret.size = size; + return ret; +} + +UPB_INLINE upb_strview upb_strview_makez(const char *data) { + return upb_strview_make(data, strlen(data)); +} + +UPB_INLINE bool upb_strview_eql(upb_strview a, upb_strview b) { + return a.size == b.size && memcmp(a.data, b.data, a.size) == 0; +} + +#define UPB_STRVIEW_INIT(ptr, len) {ptr, len} + +#define UPB_STRVIEW_FORMAT "%.*s" +#define UPB_STRVIEW_ARGS(view) (int)(view).size, (view).data + +/** upb_alloc *****************************************************************/ + +/* A upb_alloc is a possibly-stateful allocator object. + * + * It could either be an arena allocator (which doesn't require individual + * free() calls) or a regular malloc() (which does). The client must therefore + * free memory unless it knows that the allocator is an arena allocator. */ + +struct upb_alloc; +typedef struct upb_alloc upb_alloc; + +/* A malloc()/free() function. + * If "size" is 0 then the function acts like free(), otherwise it acts like + * realloc(). Only "oldsize" bytes from a previous allocation are preserved. */ +typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize, + size_t size); + +struct upb_alloc { + upb_alloc_func *func; +}; + +UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) { + UPB_ASSERT(alloc); + return alloc->func(alloc, NULL, 0, size); +} + +UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize, + size_t size) { + UPB_ASSERT(alloc); + return alloc->func(alloc, ptr, oldsize, size); +} + +UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) { + assert(alloc); + alloc->func(alloc, ptr, 0, 0); +} + +/* The global allocator used by upb. Uses the standard malloc()/free(). */ + +extern upb_alloc upb_alloc_global; + +/* Functions that hard-code the global malloc. + * + * We still get benefit because we can put custom logic into our global + * allocator, like injecting out-of-memory faults in debug/testing builds. */ + +UPB_INLINE void *upb_gmalloc(size_t size) { + return upb_malloc(&upb_alloc_global, size); +} + +UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) { + return upb_realloc(&upb_alloc_global, ptr, oldsize, size); +} + +UPB_INLINE void upb_gfree(void *ptr) { + upb_free(&upb_alloc_global, ptr); +} + +/* upb_arena ******************************************************************/ + +/* upb_arena is a specific allocator implementation that uses arena allocation. + * The user provides an allocator that will be used to allocate the underlying + * arena blocks. Arenas by nature do not require the individual allocations + * to be freed. However the Arena does allow users to register cleanup + * functions that will run when the arena is destroyed. + * + * A upb_arena is *not* thread-safe. + * + * You could write a thread-safe arena allocator that satisfies the + * upb_alloc interface, but it would not be as efficient for the + * single-threaded case. */ + +typedef void upb_cleanup_func(void *ud); + +struct upb_arena; +typedef struct upb_arena upb_arena; + +typedef struct { + /* We implement the allocator interface. + * This must be the first member of upb_arena! + * TODO(haberman): remove once handlers are gone. */ + upb_alloc alloc; + + char *ptr, *end; +} _upb_arena_head; + +/* Creates an arena from the given initial block (if any -- n may be 0). + * Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this + * is a fixed-size arena and cannot grow. */ +upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc); +void upb_arena_free(upb_arena *a); +bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func); +void upb_arena_fuse(upb_arena *a, upb_arena *b); +void *_upb_arena_slowmalloc(upb_arena *a, size_t size); + +UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; } + +UPB_INLINE size_t _upb_arenahas(upb_arena *a) { + _upb_arena_head *h = (_upb_arena_head*)a; + return (size_t)(h->end - h->ptr); +} + +UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) { + _upb_arena_head *h = (_upb_arena_head*)a; + void* ret; + size = UPB_ALIGN_MALLOC(size); + + if (UPB_UNLIKELY(_upb_arenahas(a) < size)) { + return _upb_arena_slowmalloc(a, size); + } + + ret = h->ptr; + h->ptr += size; + UPB_UNPOISON_MEMORY_REGION(ret, size); + +#if UPB_ASAN + { + size_t guard_size = 32; + if (_upb_arenahas(a) >= guard_size) { + h->ptr += guard_size; + } else { + h->ptr = h->end; + } + } +#endif + + return ret; +} + +UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize, + size_t size) { + void *ret = upb_arena_malloc(a, size); + + if (ret && oldsize > 0) { + memcpy(ret, ptr, oldsize); + } + + return ret; +} + +UPB_INLINE upb_arena *upb_arena_new(void) { + return upb_arena_init(NULL, 0, &upb_alloc_global); +} + +/* Constants ******************************************************************/ + +/* Generic function type. */ +typedef void upb_func(void); + +/* A list of types as they are encoded on-the-wire. */ +typedef enum { + UPB_WIRE_TYPE_VARINT = 0, + UPB_WIRE_TYPE_64BIT = 1, + UPB_WIRE_TYPE_DELIMITED = 2, + UPB_WIRE_TYPE_START_GROUP = 3, + UPB_WIRE_TYPE_END_GROUP = 4, + UPB_WIRE_TYPE_32BIT = 5 +} upb_wiretype_t; + +/* The types a field can have. Note that this list is not identical to the + * types defined in descriptor.proto, which gives INT32 and SINT32 separate + * types (we distinguish the two with the "integer encoding" enum below). */ +typedef enum { + UPB_TYPE_BOOL = 1, + UPB_TYPE_FLOAT = 2, + UPB_TYPE_INT32 = 3, + UPB_TYPE_UINT32 = 4, + UPB_TYPE_ENUM = 5, /* Enum values are int32. */ + UPB_TYPE_MESSAGE = 6, + UPB_TYPE_DOUBLE = 7, + UPB_TYPE_INT64 = 8, + UPB_TYPE_UINT64 = 9, + UPB_TYPE_STRING = 10, + UPB_TYPE_BYTES = 11 +} upb_fieldtype_t; + +/* The repeated-ness of each field; this matches descriptor.proto. */ +typedef enum { + UPB_LABEL_OPTIONAL = 1, + UPB_LABEL_REQUIRED = 2, + UPB_LABEL_REPEATED = 3 +} upb_label_t; + +/* Descriptor types, as defined in descriptor.proto. */ +typedef enum { + /* Old (long) names. TODO(haberman): remove */ + UPB_DESCRIPTOR_TYPE_DOUBLE = 1, + UPB_DESCRIPTOR_TYPE_FLOAT = 2, + UPB_DESCRIPTOR_TYPE_INT64 = 3, + UPB_DESCRIPTOR_TYPE_UINT64 = 4, + UPB_DESCRIPTOR_TYPE_INT32 = 5, + UPB_DESCRIPTOR_TYPE_FIXED64 = 6, + UPB_DESCRIPTOR_TYPE_FIXED32 = 7, + UPB_DESCRIPTOR_TYPE_BOOL = 8, + UPB_DESCRIPTOR_TYPE_STRING = 9, + UPB_DESCRIPTOR_TYPE_GROUP = 10, + UPB_DESCRIPTOR_TYPE_MESSAGE = 11, + UPB_DESCRIPTOR_TYPE_BYTES = 12, + UPB_DESCRIPTOR_TYPE_UINT32 = 13, + UPB_DESCRIPTOR_TYPE_ENUM = 14, + UPB_DESCRIPTOR_TYPE_SFIXED32 = 15, + UPB_DESCRIPTOR_TYPE_SFIXED64 = 16, + UPB_DESCRIPTOR_TYPE_SINT32 = 17, + UPB_DESCRIPTOR_TYPE_SINT64 = 18, + + UPB_DTYPE_DOUBLE = 1, + UPB_DTYPE_FLOAT = 2, + UPB_DTYPE_INT64 = 3, + UPB_DTYPE_UINT64 = 4, + UPB_DTYPE_INT32 = 5, + UPB_DTYPE_FIXED64 = 6, + UPB_DTYPE_FIXED32 = 7, + UPB_DTYPE_BOOL = 8, + UPB_DTYPE_STRING = 9, + UPB_DTYPE_GROUP = 10, + UPB_DTYPE_MESSAGE = 11, + UPB_DTYPE_BYTES = 12, + UPB_DTYPE_UINT32 = 13, + UPB_DTYPE_ENUM = 14, + UPB_DTYPE_SFIXED32 = 15, + UPB_DTYPE_SFIXED64 = 16, + UPB_DTYPE_SINT32 = 17, + UPB_DTYPE_SINT64 = 18 +} upb_descriptortype_t; + +#define UPB_MAP_BEGIN ((size_t)-1) + +UPB_INLINE bool _upb_isle(void) { + int x = 1; + return *(char*)&x == 1; +} + +UPB_INLINE uint32_t _upb_be_swap32(uint32_t val) { + if (_upb_isle()) { + return val; + } else { + return ((val & 0xff) << 24) | ((val & 0xff00) << 8) | + ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24); + } +} + +UPB_INLINE uint64_t _upb_be_swap64(uint64_t val) { + if (_upb_isle()) { + return val; + } else { + return ((uint64_t)_upb_be_swap32(val) << 32) | _upb_be_swap32(val >> 32); + } +} + +UPB_INLINE int _upb_lg2ceil(int x) { + if (x <= 1) return 0; +#ifdef __GNUC__ + return 32 - __builtin_clz(x - 1); +#else + int lg2 = 0; + while (1 << lg2 < x) lg2++; + return lg2; +#endif +} + +UPB_INLINE int _upb_lg2ceilsize(int x) { + return 1 << _upb_lg2ceil(x); +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* UPB_H_ */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* upb_value ******************************************************************/ + +/* A tagged union (stored untagged inside the table) so that we can check that + * clients calling table accessors are correctly typed without having to have + * an explosion of accessors. */ +typedef enum { + UPB_CTYPE_INT32 = 1, + UPB_CTYPE_INT64 = 2, + UPB_CTYPE_UINT32 = 3, + UPB_CTYPE_UINT64 = 4, + UPB_CTYPE_BOOL = 5, + UPB_CTYPE_CSTR = 6, + UPB_CTYPE_PTR = 7, + UPB_CTYPE_CONSTPTR = 8, + UPB_CTYPE_FPTR = 9, + UPB_CTYPE_FLOAT = 10, + UPB_CTYPE_DOUBLE = 11 +} upb_ctype_t; + +typedef struct { + uint64_t val; +} upb_value; + +/* Like strdup(), which isn't always available since it's not ANSI C. */ +char *upb_strdup(const char *s, upb_alloc *a); +/* Variant that works with a length-delimited rather than NULL-delimited string, + * as supported by strtable. */ +char *upb_strdup2(const char *s, size_t len, upb_alloc *a); + +UPB_INLINE char *upb_gstrdup(const char *s) { + return upb_strdup(s, &upb_alloc_global); +} + +UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val) { + v->val = val; +} + +UPB_INLINE upb_value _upb_value_val(uint64_t val) { + upb_value ret; + _upb_value_setval(&ret, val); + return ret; +} + +/* For each value ctype, define the following set of functions: + * + * // Get/set an int32 from a upb_value. + * int32_t upb_value_getint32(upb_value val); + * void upb_value_setint32(upb_value *val, int32_t cval); + * + * // Construct a new upb_value from an int32. + * upb_value upb_value_int32(int32_t val); */ +#define FUNCS(name, membername, type_t, converter, proto_type) \ + UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \ + val->val = (converter)cval; \ + } \ + UPB_INLINE upb_value upb_value_ ## name(type_t val) { \ + upb_value ret; \ + upb_value_set ## name(&ret, val); \ + return ret; \ + } \ + UPB_INLINE type_t upb_value_get ## name(upb_value val) { \ + return (type_t)(converter)val.val; \ + } + +FUNCS(int32, int32, int32_t, int32_t, UPB_CTYPE_INT32) +FUNCS(int64, int64, int64_t, int64_t, UPB_CTYPE_INT64) +FUNCS(uint32, uint32, uint32_t, uint32_t, UPB_CTYPE_UINT32) +FUNCS(uint64, uint64, uint64_t, uint64_t, UPB_CTYPE_UINT64) +FUNCS(bool, _bool, bool, bool, UPB_CTYPE_BOOL) +FUNCS(cstr, cstr, char*, uintptr_t, UPB_CTYPE_CSTR) +FUNCS(ptr, ptr, void*, uintptr_t, UPB_CTYPE_PTR) +FUNCS(constptr, constptr, const void*, uintptr_t, UPB_CTYPE_CONSTPTR) +FUNCS(fptr, fptr, upb_func*, uintptr_t, UPB_CTYPE_FPTR) + +#undef FUNCS + +UPB_INLINE void upb_value_setfloat(upb_value *val, float cval) { + memcpy(&val->val, &cval, sizeof(cval)); +} + +UPB_INLINE void upb_value_setdouble(upb_value *val, double cval) { + memcpy(&val->val, &cval, sizeof(cval)); +} + +UPB_INLINE upb_value upb_value_float(float cval) { + upb_value ret; + upb_value_setfloat(&ret, cval); + return ret; +} + +UPB_INLINE upb_value upb_value_double(double cval) { + upb_value ret; + upb_value_setdouble(&ret, cval); + return ret; +} + +#undef SET_TYPE + + +/* upb_tabkey *****************************************************************/ + +/* Either: + * 1. an actual integer key, or + * 2. a pointer to a string prefixed by its uint32_t length, owned by us. + * + * ...depending on whether this is a string table or an int table. We would + * make this a union of those two types, but C89 doesn't support statically + * initializing a non-first union member. */ +typedef uintptr_t upb_tabkey; + +UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) { + char* mem = (char*)key; + if (len) memcpy(len, mem, sizeof(*len)); + return mem + sizeof(*len); +} + +UPB_INLINE upb_strview upb_tabstrview(upb_tabkey key) { + upb_strview ret; + uint32_t len; + ret.data = upb_tabstr(key, &len); + ret.size = len; + return ret; +} + +/* upb_tabval *****************************************************************/ + +typedef struct upb_tabval { + uint64_t val; +} upb_tabval; + +#define UPB_TABVALUE_EMPTY_INIT {-1} + +/* upb_table ******************************************************************/ + +typedef struct _upb_tabent { + upb_tabkey key; + upb_tabval val; + + /* Internal chaining. This is const so we can create static initializers for + * tables. We cast away const sometimes, but *only* when the containing + * upb_table is known to be non-const. This requires a bit of care, but + * the subtlety is confined to table.c. */ + const struct _upb_tabent *next; +} upb_tabent; + +typedef struct { + size_t count; /* Number of entries in the hash part. */ + uint32_t mask; /* Mask to turn hash value -> bucket. */ + uint32_t max_count; /* Max count before we hit our load limit. */ + uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ + + /* Hash table entries. + * Making this const isn't entirely accurate; what we really want is for it to + * have the same const-ness as the table it's inside. But there's no way to + * declare that in C. So we have to make it const so that we can statically + * initialize const hash tables. Then we cast away const when we have to. + */ + const upb_tabent *entries; +} upb_table; + +typedef struct { + upb_table t; +} upb_strtable; + +typedef struct { + upb_table t; /* For entries that don't fit in the array part. */ + const upb_tabval *array; /* Array part of the table. See const note above. */ + size_t array_size; /* Array part size. */ + size_t array_count; /* Array part number of elements. */ +} upb_inttable; + +#define UPB_ARRAY_EMPTYENT -1 + +UPB_INLINE size_t upb_table_size(const upb_table *t) { + if (t->size_lg2 == 0) + return 0; + else + return 1 << t->size_lg2; +} + +/* Internal-only functions, in .h file only out of necessity. */ +UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) { + return e->key == 0; +} + +/* Used by some of the unit tests for generic hashing functionality. */ +uint32_t upb_murmur_hash2(const void * key, size_t len, uint32_t seed); + +UPB_INLINE uintptr_t upb_intkey(uintptr_t key) { + return key; +} + +UPB_INLINE uint32_t upb_inthash(uintptr_t key) { + return (uint32_t)key; +} + +static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) { + return t->entries + (hash & t->mask); +} + +UPB_INLINE bool upb_arrhas(upb_tabval key) { + return key.val != (uint64_t)-1; +} + +/* Initialize and uninitialize a table, respectively. If memory allocation + * failed, false is returned that the table is uninitialized. */ +bool upb_inttable_init2(upb_inttable *table, upb_ctype_t ctype, upb_alloc *a); +bool upb_strtable_init2(upb_strtable *table, upb_ctype_t ctype, + size_t expected_size, upb_alloc *a); +void upb_inttable_uninit2(upb_inttable *table, upb_alloc *a); +void upb_strtable_uninit2(upb_strtable *table, upb_alloc *a); + +UPB_INLINE bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype) { + return upb_inttable_init2(table, ctype, &upb_alloc_global); +} + +UPB_INLINE bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype) { + return upb_strtable_init2(table, ctype, 4, &upb_alloc_global); +} + +UPB_INLINE void upb_inttable_uninit(upb_inttable *table) { + upb_inttable_uninit2(table, &upb_alloc_global); +} + +UPB_INLINE void upb_strtable_uninit(upb_strtable *table) { + upb_strtable_uninit2(table, &upb_alloc_global); +} + +/* Returns the number of values in the table. */ +size_t upb_inttable_count(const upb_inttable *t); +UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) { + return t->t.count; +} + +void upb_inttable_packedsize(const upb_inttable *t, size_t *size); +void upb_strtable_packedsize(const upb_strtable *t, size_t *size); +upb_inttable *upb_inttable_pack(const upb_inttable *t, void *p, size_t *ofs, + size_t size); +upb_strtable *upb_strtable_pack(const upb_strtable *t, void *p, size_t *ofs, + size_t size); +void upb_strtable_clear(upb_strtable *t); + +/* Inserts the given key into the hashtable with the given value. The key must + * not already exist in the hash table. For string tables, the key must be + * NULL-terminated, and the table will make an internal copy of the key. + * Inttables must not insert a value of UINTPTR_MAX. + * + * If a table resize was required but memory allocation failed, false is + * returned and the table is unchanged. */ +bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, + upb_alloc *a); +bool upb_strtable_insert3(upb_strtable *t, const char *key, size_t len, + upb_value val, upb_alloc *a); + +UPB_INLINE bool upb_inttable_insert(upb_inttable *t, uintptr_t key, + upb_value val) { + return upb_inttable_insert2(t, key, val, &upb_alloc_global); +} + +UPB_INLINE bool upb_strtable_insert2(upb_strtable *t, const char *key, + size_t len, upb_value val) { + return upb_strtable_insert3(t, key, len, val, &upb_alloc_global); +} + +/* For NULL-terminated strings. */ +UPB_INLINE bool upb_strtable_insert(upb_strtable *t, const char *key, + upb_value val) { + return upb_strtable_insert2(t, key, strlen(key), val); +} + +/* Looks up key in this table, returning "true" if the key was found. + * If v is non-NULL, copies the value for this key into *v. */ +bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v); +bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len, + upb_value *v); + +/* For NULL-terminated strings. */ +UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key, + upb_value *v) { + return upb_strtable_lookup2(t, key, strlen(key), v); +} + +/* Removes an item from the table. Returns true if the remove was successful, + * and stores the removed item in *val if non-NULL. */ +bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val); +bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len, + upb_value *val, upb_alloc *alloc); + +UPB_INLINE bool upb_strtable_remove2(upb_strtable *t, const char *key, + size_t len, upb_value *val) { + return upb_strtable_remove3(t, key, len, val, &upb_alloc_global); +} + +/* For NULL-terminated strings. */ +UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key, + upb_value *v) { + return upb_strtable_remove2(t, key, strlen(key), v); +} + +/* Updates an existing entry in an inttable. If the entry does not exist, + * returns false and does nothing. Unlike insert/remove, this does not + * invalidate iterators. */ +bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val); + +/* Convenience routines for inttables with pointer keys. */ +bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val, + upb_alloc *a); +bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val); +bool upb_inttable_lookupptr( + const upb_inttable *t, const void *key, upb_value *val); + +UPB_INLINE bool upb_inttable_insertptr(upb_inttable *t, const void *key, + upb_value val) { + return upb_inttable_insertptr2(t, key, val, &upb_alloc_global); +} + +/* Optimizes the table for the current set of entries, for both memory use and + * lookup time. Client should call this after all entries have been inserted; + * inserting more entries is legal, but will likely require a table resize. */ +void upb_inttable_compact2(upb_inttable *t, upb_alloc *a); + +UPB_INLINE void upb_inttable_compact(upb_inttable *t) { + upb_inttable_compact2(t, &upb_alloc_global); +} + +/* A special-case inlinable version of the lookup routine for 32-bit + * integers. */ +UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, + upb_value *v) { + *v = upb_value_int32(0); /* Silence compiler warnings. */ + if (key < t->array_size) { + upb_tabval arrval = t->array[key]; + if (upb_arrhas(arrval)) { + _upb_value_setval(v, arrval.val); + return true; + } else { + return false; + } + } else { + const upb_tabent *e; + if (t->t.entries == NULL) return false; + for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) { + if ((uint32_t)e->key == key) { + _upb_value_setval(v, e->val.val); + return true; + } + if (e->next == NULL) return false; + } + } +} + +/* Exposed for testing only. */ +bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a); + +/* Iterators ******************************************************************/ + +/* Iterators for int and string tables. We are subject to some kind of unusual + * design constraints: + * + * For high-level languages: + * - we must be able to guarantee that we don't crash or corrupt memory even if + * the program accesses an invalidated iterator. + * + * For C++11 range-based for: + * - iterators must be copyable + * - iterators must be comparable + * - it must be possible to construct an "end" value. + * + * Iteration order is undefined. + * + * Modifying the table invalidates iterators. upb_{str,int}table_done() is + * guaranteed to work even on an invalidated iterator, as long as the table it + * is iterating over has not been freed. Calling next() or accessing data from + * an invalidated iterator yields unspecified elements from the table, but it is + * guaranteed not to crash and to return real table elements (except when done() + * is true). */ + + +/* upb_strtable_iter **********************************************************/ + +/* upb_strtable_iter i; + * upb_strtable_begin(&i, t); + * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { + * const char *key = upb_strtable_iter_key(&i); + * const upb_value val = upb_strtable_iter_value(&i); + * // ... + * } + */ + +typedef struct { + const upb_strtable *t; + size_t index; +} upb_strtable_iter; + +void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t); +void upb_strtable_next(upb_strtable_iter *i); +bool upb_strtable_done(const upb_strtable_iter *i); +upb_strview upb_strtable_iter_key(const upb_strtable_iter *i); +upb_value upb_strtable_iter_value(const upb_strtable_iter *i); +void upb_strtable_iter_setdone(upb_strtable_iter *i); +bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, + const upb_strtable_iter *i2); + + +/* upb_inttable_iter **********************************************************/ + +/* upb_inttable_iter i; + * upb_inttable_begin(&i, t); + * for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { + * uintptr_t key = upb_inttable_iter_key(&i); + * upb_value val = upb_inttable_iter_value(&i); + * // ... + * } + */ + +typedef struct { + const upb_inttable *t; + size_t index; + bool array_part; +} upb_inttable_iter; + +UPB_INLINE const upb_tabent *str_tabent(const upb_strtable_iter *i) { + return &i->t->t.entries[i->index]; +} + +void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t); +void upb_inttable_next(upb_inttable_iter *i); +bool upb_inttable_done(const upb_inttable_iter *i); +uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i); +upb_value upb_inttable_iter_value(const upb_inttable_iter *i); +void upb_inttable_iter_setdone(upb_inttable_iter *i); +bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, + const upb_inttable_iter *i2); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_TABLE_H_ */ + +/* Must be last. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs) + +typedef void upb_msg; + +/** upb_msglayout *************************************************************/ + +/* upb_msglayout represents the memory layout of a given upb_msgdef. The + * members are public so generated code can initialize them, but users MUST NOT + * read or write any of its members. */ + +/* These aren't real labels according to descriptor.proto, but in the table we + * use these for map/packed fields instead of UPB_LABEL_REPEATED. */ +enum { + _UPB_LABEL_MAP = 4, + _UPB_LABEL_PACKED = 7 /* Low 3 bits are common with UPB_LABEL_REPEATED. */ +}; + +typedef struct { + uint32_t number; + uint16_t offset; + int16_t presence; /* If >0, hasbit_index. If <0, ~oneof_index. */ + uint16_t submsg_index; /* undefined if descriptortype != MESSAGE or GROUP. */ + uint8_t descriptortype; + uint8_t label; /* google.protobuf.Label or _UPB_LABEL_* above. */ +} upb_msglayout_field; + +struct upb_decstate; +struct upb_msglayout; + +typedef const char *_upb_field_parser(struct upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits, uint64_t data); + +typedef struct { + uint64_t field_data; + _upb_field_parser *field_parser; +} _upb_fasttable_entry; + +typedef struct upb_msglayout { + const struct upb_msglayout *const* submsgs; + const upb_msglayout_field *fields; + /* Must be aligned to sizeof(void*). Doesn't include internal members like + * unknown fields, extension dict, pointer to msglayout, etc. */ + uint16_t size; + uint16_t field_count; + bool extendable; + uint8_t table_mask; + /* To constant-initialize the tables of variable length, we need a flexible + * array member, and we need to compile in C99 mode. */ + _upb_fasttable_entry fasttable[]; +} upb_msglayout; + +/** upb_msg *******************************************************************/ + +/* Internal members of a upb_msg. We can change this without breaking binary + * compatibility. We put these before the user's data. The user's upb_msg* + * points after the upb_msg_internal. */ + +typedef struct { + uint32_t len; + uint32_t size; + /* Data follows. */ +} upb_msg_unknowndata; + +/* Used when a message is not extendable. */ +typedef struct { + upb_msg_unknowndata *unknown; +} upb_msg_internal; + +/* Maps upb_fieldtype_t -> memory size. */ +extern char _upb_fieldtype_to_size[12]; + +UPB_INLINE size_t upb_msg_sizeof(const upb_msglayout *l) { + return l->size + sizeof(upb_msg_internal); +} + +UPB_INLINE upb_msg *_upb_msg_new_inl(const upb_msglayout *l, upb_arena *a) { + size_t size = upb_msg_sizeof(l); + void *mem = upb_arena_malloc(a, size); + upb_msg *msg; + if (UPB_UNLIKELY(!mem)) return NULL; + msg = UPB_PTR_AT(mem, sizeof(upb_msg_internal), upb_msg); + memset(mem, 0, size); + return msg; +} + +/* Creates a new messages with the given layout on the given arena. */ +upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a); + +UPB_INLINE upb_msg_internal *upb_msg_getinternal(upb_msg *msg) { + ptrdiff_t size = sizeof(upb_msg_internal); + return (upb_msg_internal*)((char*)msg - size); +} + +/* Clears the given message. */ +void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l); + +/* Discards the unknown fields for this message only. */ +void _upb_msg_discardunknown_shallow(upb_msg *msg); + +/* Adds unknown data (serialized protobuf data) to the given message. The data + * is copied into the message instance. */ +bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, + upb_arena *arena); + +/* Returns a reference to the message's unknown data. */ +const char *upb_msg_getunknown(const upb_msg *msg, size_t *len); + +/** Hasbit access *************************************************************/ + +UPB_INLINE bool _upb_hasbit(const upb_msg *msg, size_t idx) { + return (*PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0; +} + +UPB_INLINE void _upb_sethas(const upb_msg *msg, size_t idx) { + (*PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8)); +} + +UPB_INLINE void _upb_clearhas(const upb_msg *msg, size_t idx) { + (*PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8))); +} + +UPB_INLINE size_t _upb_msg_hasidx(const upb_msglayout_field *f) { + UPB_ASSERT(f->presence > 0); + return f->presence; +} + +UPB_INLINE bool _upb_hasbit_field(const upb_msg *msg, + const upb_msglayout_field *f) { + return _upb_hasbit(msg, _upb_msg_hasidx(f)); +} + +UPB_INLINE void _upb_sethas_field(const upb_msg *msg, + const upb_msglayout_field *f) { + _upb_sethas(msg, _upb_msg_hasidx(f)); +} + +UPB_INLINE void _upb_clearhas_field(const upb_msg *msg, + const upb_msglayout_field *f) { + _upb_clearhas(msg, _upb_msg_hasidx(f)); +} + +/** Oneof case access *********************************************************/ + +UPB_INLINE uint32_t *_upb_oneofcase(upb_msg *msg, size_t case_ofs) { + return PTR_AT(msg, case_ofs, uint32_t); +} + +UPB_INLINE uint32_t _upb_getoneofcase(const void *msg, size_t case_ofs) { + return *PTR_AT(msg, case_ofs, uint32_t); +} + +UPB_INLINE size_t _upb_oneofcase_ofs(const upb_msglayout_field *f) { + UPB_ASSERT(f->presence < 0); + return ~(ptrdiff_t)f->presence; +} + +UPB_INLINE uint32_t *_upb_oneofcase_field(upb_msg *msg, + const upb_msglayout_field *f) { + return _upb_oneofcase(msg, _upb_oneofcase_ofs(f)); +} + +UPB_INLINE uint32_t _upb_getoneofcase_field(const upb_msg *msg, + const upb_msglayout_field *f) { + return _upb_getoneofcase(msg, _upb_oneofcase_ofs(f)); +} + +UPB_INLINE bool _upb_has_submsg_nohasbit(const upb_msg *msg, size_t ofs) { + return *PTR_AT(msg, ofs, const upb_msg*) != NULL; +} + +UPB_INLINE bool _upb_isrepeated(const upb_msglayout_field *field) { + return (field->label & 3) == UPB_LABEL_REPEATED; +} + +UPB_INLINE bool _upb_repeated_or_map(const upb_msglayout_field *field) { + return field->label >= UPB_LABEL_REPEATED; +} + +/** upb_array *****************************************************************/ + +/* Our internal representation for repeated fields. */ +typedef struct { + uintptr_t data; /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */ + size_t len; /* Measured in elements. */ + size_t size; /* Measured in elements. */ + uint64_t junk; +} upb_array; + +UPB_INLINE const void *_upb_array_constptr(const upb_array *arr) { + UPB_ASSERT((arr->data & 7) <= 4); + return (void*)(arr->data & ~(uintptr_t)7); +} + +UPB_INLINE uintptr_t _upb_array_tagptr(void* ptr, int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 <= 4); + return (uintptr_t)ptr | elem_size_lg2; +} + +UPB_INLINE void *_upb_array_ptr(upb_array *arr) { + return (void*)_upb_array_constptr(arr); +} + +UPB_INLINE uintptr_t _upb_tag_arrptr(void* ptr, int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 <= 4); + UPB_ASSERT(((uintptr_t)ptr & 7) == 0); + return (uintptr_t)ptr | (unsigned)elem_size_lg2; +} + +UPB_INLINE upb_array *_upb_array_new(upb_arena *a, size_t init_size, + int elem_size_lg2) { + const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_array), 8); + const size_t bytes = sizeof(upb_array) + (init_size << elem_size_lg2); + upb_array *arr = (upb_array*)upb_arena_malloc(a, bytes); + if (!arr) return NULL; + arr->data = _upb_tag_arrptr(UPB_PTR_AT(arr, arr_size, void), elem_size_lg2); + arr->len = 0; + arr->size = init_size; + return arr; +} + +/* Resizes the capacity of the array to be at least min_size. */ +bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena); + +/* Fallback functions for when the accessors require a resize. */ +void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size, + int elem_size_lg2, upb_arena *arena); +bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value, + int elem_size_lg2, upb_arena *arena); + +UPB_INLINE bool _upb_array_reserve(upb_array *arr, size_t size, + upb_arena *arena) { + if (arr->size < size) return _upb_array_realloc(arr, size, arena); + return true; +} + +UPB_INLINE bool _upb_array_resize(upb_array *arr, size_t size, + upb_arena *arena) { + if (!_upb_array_reserve(arr, size, arena)) return false; + arr->len = size; + return true; +} + +UPB_INLINE const void *_upb_array_accessor(const void *msg, size_t ofs, + size_t *size) { + const upb_array *arr = *PTR_AT(msg, ofs, const upb_array*); + if (arr) { + if (size) *size = arr->len; + return _upb_array_constptr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} + +UPB_INLINE void *_upb_array_mutable_accessor(void *msg, size_t ofs, + size_t *size) { + upb_array *arr = *PTR_AT(msg, ofs, upb_array*); + if (arr) { + if (size) *size = arr->len; + return _upb_array_ptr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} + +UPB_INLINE void *_upb_array_resize_accessor2(void *msg, size_t ofs, size_t size, + int elem_size_lg2, + upb_arena *arena) { + upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array *); + upb_array *arr = *arr_ptr; + if (!arr || arr->size < size) { + return _upb_array_resize_fallback(arr_ptr, size, elem_size_lg2, arena); + } + arr->len = size; + return _upb_array_ptr(arr); +} + +UPB_INLINE bool _upb_array_append_accessor2(void *msg, size_t ofs, + int elem_size_lg2, + const void *value, + upb_arena *arena) { + upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array *); + size_t elem_size = 1 << elem_size_lg2; + upb_array *arr = *arr_ptr; + void *ptr; + if (!arr || arr->len == arr->size) { + return _upb_array_append_fallback(arr_ptr, value, elem_size_lg2, arena); + } + ptr = _upb_array_ptr(arr); + memcpy(PTR_AT(ptr, arr->len * elem_size, char), value, elem_size); + arr->len++; + return true; +} + +/* Used by old generated code, remove once all code has been regenerated. */ +UPB_INLINE int _upb_sizelg2(upb_fieldtype_t type) { + switch (type) { + case UPB_TYPE_BOOL: + return 0; + case UPB_TYPE_FLOAT: + case UPB_TYPE_INT32: + case UPB_TYPE_UINT32: + case UPB_TYPE_ENUM: + return 2; + case UPB_TYPE_MESSAGE: + return UPB_SIZE(2, 3); + case UPB_TYPE_DOUBLE: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT64: + return 3; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + return UPB_SIZE(3, 4); + } + UPB_UNREACHABLE(); +} +UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size, + upb_fieldtype_t type, + upb_arena *arena) { + return _upb_array_resize_accessor2(msg, ofs, size, _upb_sizelg2(type), arena); +} +UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs, + size_t elem_size, upb_fieldtype_t type, + const void *value, + upb_arena *arena) { + (void)elem_size; + return _upb_array_append_accessor2(msg, ofs, _upb_sizelg2(type), value, + arena); +} + +/** upb_map *******************************************************************/ + +/* Right now we use strmaps for everything. We'll likely want to use + * integer-specific maps for integer-keyed maps.*/ +typedef struct { + /* Size of key and val, based on the map type. Strings are represented as '0' + * because they must be handled specially. */ + char key_size; + char val_size; + + upb_strtable table; +} upb_map; + +/* Map entries aren't actually stored, they are only used during parsing. For + * parsing, it helps a lot if all map entry messages have the same layout. + * The compiler and def.c must ensure that all map entries have this layout. */ +typedef struct { + upb_msg_internal internal; + union { + upb_strview str; /* For str/bytes. */ + upb_value val; /* For all other types. */ + } k; + union { + upb_strview str; /* For str/bytes. */ + upb_value val; /* For all other types. */ + } v; +} upb_map_entry; + +/* Creates a new map on the given arena with this key/value type. */ +upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size); + +/* Converting between internal table representation and user values. + * + * _upb_map_tokey() and _upb_map_fromkey() are inverses. + * _upb_map_tovalue() and _upb_map_fromvalue() are inverses. + * + * These functions account for the fact that strings are treated differently + * from other types when stored in a map. + */ + +UPB_INLINE upb_strview _upb_map_tokey(const void *key, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + return *(upb_strview*)key; + } else { + return upb_strview_make((const char*)key, size); + } +} + +UPB_INLINE void _upb_map_fromkey(upb_strview key, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + memcpy(out, &key, sizeof(key)); + } else { + memcpy(out, key.data, size); + } +} + +UPB_INLINE bool _upb_map_tovalue(const void *val, size_t size, upb_value *msgval, + upb_arena *a) { + if (size == UPB_MAPTYPE_STRING) { + upb_strview *strp = (upb_strview*)upb_arena_malloc(a, sizeof(*strp)); + if (!strp) return false; + *strp = *(upb_strview*)val; + *msgval = upb_value_ptr(strp); + } else { + memcpy(msgval, val, size); + } + return true; +} + +UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + const upb_strview *strp = (const upb_strview*)upb_value_getptr(val); + memcpy(out, strp, sizeof(upb_strview)); + } else { + memcpy(out, &val, size); + } +} + +/* Map operations, shared by reflection and generated code. */ + +UPB_INLINE size_t _upb_map_size(const upb_map *map) { + return map->table.t.count; +} + +UPB_INLINE bool _upb_map_get(const upb_map *map, const void *key, + size_t key_size, void *val, size_t val_size) { + upb_value tabval; + upb_strview k = _upb_map_tokey(key, key_size); + bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval); + if (ret && val) { + _upb_map_fromvalue(tabval, val, val_size); + } + return ret; +} + +UPB_INLINE void* _upb_map_next(const upb_map *map, size_t *iter) { + upb_strtable_iter it; + it.t = &map->table; + it.index = *iter; + upb_strtable_next(&it); + *iter = it.index; + if (upb_strtable_done(&it)) return NULL; + return (void*)str_tabent(&it); +} + +UPB_INLINE bool _upb_map_set(upb_map *map, const void *key, size_t key_size, + void *val, size_t val_size, upb_arena *arena) { + upb_strview strkey = _upb_map_tokey(key, key_size); + upb_value tabval = {0}; + if (!_upb_map_tovalue(val, val_size, &tabval, arena)) return false; + upb_alloc *a = upb_arena_alloc(arena); + + /* TODO(haberman): add overwrite operation to minimize number of lookups. */ + upb_strtable_remove3(&map->table, strkey.data, strkey.size, NULL, a); + return upb_strtable_insert3(&map->table, strkey.data, strkey.size, tabval, a); +} + +UPB_INLINE bool _upb_map_delete(upb_map *map, const void *key, size_t key_size) { + upb_strview k = _upb_map_tokey(key, key_size); + return upb_strtable_remove3(&map->table, k.data, k.size, NULL, NULL); +} + +UPB_INLINE void _upb_map_clear(upb_map *map) { + upb_strtable_clear(&map->table); +} + +/* Message map operations, these get the map from the message first. */ + +UPB_INLINE size_t _upb_msg_map_size(const upb_msg *msg, size_t ofs) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + return map ? _upb_map_size(map) : 0; +} + +UPB_INLINE bool _upb_msg_map_get(const upb_msg *msg, size_t ofs, + const void *key, size_t key_size, void *val, + size_t val_size) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + if (!map) return false; + return _upb_map_get(map, key, key_size, val, val_size); +} + +UPB_INLINE void *_upb_msg_map_next(const upb_msg *msg, size_t ofs, + size_t *iter) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + if (!map) return NULL; + return _upb_map_next(map, iter); +} + +UPB_INLINE bool _upb_msg_map_set(upb_msg *msg, size_t ofs, const void *key, + size_t key_size, void *val, size_t val_size, + upb_arena *arena) { + upb_map **map = PTR_AT(msg, ofs, upb_map *); + if (!*map) { + *map = _upb_map_new(arena, key_size, val_size); + } + return _upb_map_set(*map, key, key_size, val, val_size, arena); +} + +UPB_INLINE bool _upb_msg_map_delete(upb_msg *msg, size_t ofs, const void *key, + size_t key_size) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + if (!map) return false; + return _upb_map_delete(map, key, key_size); +} + +UPB_INLINE void _upb_msg_map_clear(upb_msg *msg, size_t ofs) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + if (!map) return; + _upb_map_clear(map); +} + +/* Accessing map key/value from a pointer, used by generated code only. */ + +UPB_INLINE void _upb_msg_map_key(const void* msg, void* key, size_t size) { + const upb_tabent *ent = (const upb_tabent*)msg; + uint32_t u32len; + upb_strview k; + k.data = upb_tabstr(ent->key, &u32len); + k.size = u32len; + _upb_map_fromkey(k, key, size); +} + +UPB_INLINE void _upb_msg_map_value(const void* msg, void* val, size_t size) { + const upb_tabent *ent = (const upb_tabent*)msg; + upb_value v; + _upb_value_setval(&v, ent->val.val); + _upb_map_fromvalue(v, val, size); +} + +UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, size_t size) { + upb_tabent *ent = (upb_tabent*)msg; + /* This is like _upb_map_tovalue() except the entry already exists so we can + * reuse the allocated upb_strview for string fields. */ + if (size == UPB_MAPTYPE_STRING) { + upb_strview *strp = (upb_strview*)(uintptr_t)ent->val.val; + memcpy(strp, val, sizeof(*strp)); + } else { + memcpy(&ent->val.val, val, size); + } +} + +/** _upb_mapsorter *************************************************************/ + +/* _upb_mapsorter sorts maps and provides ordered iteration over the entries. + * Since maps can be recursive (map values can be messages which contain other maps). + * _upb_mapsorter can contain a stack of maps. */ + +typedef struct { + upb_tabent const**entries; + int size; + int cap; +} _upb_mapsorter; + +typedef struct { + int start; + int pos; + int end; +} _upb_sortedmap; + +UPB_INLINE void _upb_mapsorter_init(_upb_mapsorter *s) { + s->entries = NULL; + s->size = 0; + s->cap = 0; +} + +UPB_INLINE void _upb_mapsorter_destroy(_upb_mapsorter *s) { + if (s->entries) free(s->entries); +} + +bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type, + const upb_map *map, _upb_sortedmap *sorted); + +UPB_INLINE void _upb_mapsorter_popmap(_upb_mapsorter *s, _upb_sortedmap *sorted) { + s->size = sorted->start; +} + +UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter *s, const upb_map *map, + _upb_sortedmap *sorted, + upb_map_entry *ent) { + if (sorted->pos == sorted->end) return false; + const upb_tabent *tabent = s->entries[sorted->pos++]; + upb_strview key = upb_tabstrview(tabent->key); + _upb_map_fromkey(key, &ent->k, map->key_size); + upb_value val = {tabent->val.val}; + _upb_map_fromvalue(val, &ent->v, map->val_size); + return true; +} + +#undef PTR_AT + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MSG_H_ */ + +/* Must be last. */ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /* If set, strings will alias the input buffer instead of copying into the + * arena. */ + UPB_DECODE_ALIAS = 1, +}; + +#define UPB_DECODE_MAXDEPTH(depth) ((depth) << 16) + +bool _upb_decode(const char *buf, size_t size, upb_msg *msg, + const upb_msglayout *l, upb_arena *arena, int options); + +UPB_INLINE +bool upb_decode(const char *buf, size_t size, upb_msg *msg, + const upb_msglayout *l, upb_arena *arena) { + return _upb_decode(buf, size, msg, l, arena, 0); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_DECODE_H_ */ +/* +** Internal implementation details of the decoder that are shared between +** decode.c and decode_fast.c. +*/ + +#ifndef UPB_DECODE_INT_H_ +#define UPB_DECODE_INT_H_ + +#include + + +#ifndef UPB_INT_H_ +#define UPB_INT_H_ + + +struct mem_block; +typedef struct mem_block mem_block; + +struct upb_arena { + _upb_arena_head head; + uint32_t *cleanups; + + /* Allocator to allocate arena blocks. We are responsible for freeing these + * when we are destroyed. */ + upb_alloc *block_alloc; + uint32_t last_size; + + /* When multiple arenas are fused together, each arena points to a parent + * arena (root points to itself). The root tracks how many live arenas + * reference it. */ + uint32_t refcount; /* Only used when a->parent == a */ + struct upb_arena *parent; + + /* Linked list of blocks to free/cleanup. */ + mem_block *freelist, *freelist_tail; +}; + +#endif /* UPB_INT_H_ */ + +/* Must be last. */ + +#define DECODE_NOGROUP (uint32_t)-1 + +typedef struct upb_decstate { + const char *end; /* Can read up to 16 bytes slop beyond this. */ + const char *limit_ptr; /* = end + UPB_MIN(limit, 0) */ + upb_msg *unknown_msg; /* If non-NULL, add unknown data at buffer flip. */ + const char *unknown; /* Start of unknown data. */ + int limit; /* Submessage limit relative to end. */ + int depth; + uint32_t end_group; /* field number of END_GROUP tag, else DECODE_NOGROUP */ + bool alias; + char patch[32]; + upb_arena arena; + jmp_buf err; +} upb_decstate; + +/* Error function that will abort decoding with longjmp(). We can't declare this + * UPB_NORETURN, even though it is appropriate, because if we do then compilers + * will "helpfully" refuse to tailcall to it + * (see: https://stackoverflow.com/a/55657013), which will defeat a major goal + * of our optimizations. That is also why we must declare it in a separate file, + * otherwise the compiler will see that it calls longjmp() and deduce that it is + * noreturn. */ +const char *fastdecode_err(upb_decstate *d); + +extern const uint8_t upb_utf8_offsets[]; + +UPB_INLINE +bool decode_verifyutf8_inl(const char *buf, int len) { + int i, j; + uint8_t offset; + + i = 0; + while (i < len) { + offset = upb_utf8_offsets[(uint8_t)buf[i]]; + if (offset == 0 || i + offset > len) { + return false; + } + for (j = i + 1; j < i + offset; j++) { + if ((buf[j] & 0xc0) != 0x80) { + return false; + } + } + i += offset; + } + return i == len; +} + +/* x86-64 pointers always have the high 16 bits matching. So we can shift + * left 8 and right 8 without loss of information. */ +UPB_INLINE intptr_t decode_totable(const upb_msglayout *tablep) { + return ((intptr_t)tablep << 8) | tablep->table_mask; +} + +UPB_INLINE const upb_msglayout *decode_totablep(intptr_t table) { + return (const upb_msglayout*)(table >> 8); +} + +UPB_INLINE +const char *decode_isdonefallback_inl(upb_decstate *d, const char *ptr, + int overrun) { + if (overrun < d->limit) { + /* Need to copy remaining data into patch buffer. */ + UPB_ASSERT(overrun < 16); + if (d->unknown_msg) { + if (!_upb_msg_addunknown(d->unknown_msg, d->unknown, ptr - d->unknown, + &d->arena)) { + return NULL; + } + d->unknown = &d->patch[0] + overrun; + } + memset(d->patch + 16, 0, 16); + memcpy(d->patch, d->end, 16); + ptr = &d->patch[0] + overrun; + d->end = &d->patch[16]; + d->limit -= 16; + d->limit_ptr = d->end + d->limit; + d->alias = false; + UPB_ASSERT(ptr < d->limit_ptr); + return ptr; + } else { + return NULL; + } +} + +const char *decode_isdonefallback(upb_decstate *d, const char *ptr, + int overrun); + +UPB_INLINE +bool decode_isdone(upb_decstate *d, const char **ptr) { + int overrun = *ptr - d->end; + if (UPB_LIKELY(*ptr < d->limit_ptr)) { + return false; + } else if (UPB_LIKELY(overrun == d->limit)) { + return true; + } else { + *ptr = decode_isdonefallback(d, *ptr, overrun); + return false; + } +} + +UPB_INLINE +const char *fastdecode_tagdispatch(upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits, uint32_t tag) { + const upb_msglayout *table_p = decode_totablep(table); + uint8_t mask = table; + uint64_t data; + size_t idx = tag & mask; + UPB_ASSUME((idx & 7) == 0); + idx >>= 3; + data = table_p->fasttable[idx].field_data ^ tag; + return table_p->fasttable[idx].field_parser(d, ptr, msg, table, hasbits, data); +} + +UPB_INLINE uint32_t fastdecode_loadtag(const char* ptr) { + uint16_t tag; + memcpy(&tag, ptr, 2); + return tag; +} + +UPB_INLINE void decode_checklimit(upb_decstate *d) { + UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit)); +} + +UPB_INLINE int decode_pushlimit(upb_decstate *d, const char *ptr, int size) { + int limit = size + (int)(ptr - d->end); + int delta = d->limit - limit; + decode_checklimit(d); + d->limit = limit; + d->limit_ptr = d->end + UPB_MIN(0, limit); + decode_checklimit(d); + return delta; +} + +UPB_INLINE void decode_poplimit(upb_decstate *d, const char *ptr, + int saved_delta) { + UPB_ASSERT(ptr - d->end == d->limit); + decode_checklimit(d); + d->limit += saved_delta; + d->limit_ptr = d->end + UPB_MIN(0, d->limit); + decode_checklimit(d); +} + + +#endif /* UPB_DECODE_INT_H_ */ +/* +** upb_encode: parsing into a upb_msg using a upb_msglayout. +*/ + +#ifndef UPB_ENCODE_H_ +#define UPB_ENCODE_H_ + + +/* Must be last. */ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /* If set, the results of serializing will be deterministic across all + * instances of this binary. There are no guarantees across different + * binary builds. + * + * If your proto contains maps, the encoder will need to malloc()/free() + * memory during encode. */ + UPB_ENCODE_DETERMINISTIC = 1, + + /* When set, unknown fields are not printed. */ + UPB_ENCODE_SKIPUNKNOWN = 2, +}; + +#define UPB_ENCODE_MAXDEPTH(depth) ((depth) << 16) + +char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options, + upb_arena *arena, size_t *size); + +UPB_INLINE char *upb_encode(const void *msg, const upb_msglayout *l, + upb_arena *arena, size_t *size) { + return upb_encode_ex(msg, l, 0, arena, size); +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* UPB_ENCODE_H_ */ +// These are the specialized field parser functions for the fast parser. +// Generated tables will refer to these by name. +// +// The function names are encoded with names like: +// +// // 123 4 +// upb_pss_1bt(); // Parse singular string, 1 byte tag. +// +// In position 1: +// - 'p' for parse, most function use this +// - 'c' for copy, for when we are copying strings instead of aliasing +// +// In position 2 (cardinality): +// - 's' for singular, with or without hasbit +// - 'o' for oneof +// - 'r' for non-packed repeated +// - 'p' for packed repeated +// +// In position 3 (type): +// - 'b1' for bool +// - 'v4' for 4-byte varint +// - 'v8' for 8-byte varint +// - 'z4' for zig-zag-encoded 4-byte varint +// - 'z8' for zig-zag-encoded 8-byte varint +// - 'f4' for 4-byte fixed +// - 'f8' for 8-byte fixed +// - 'm' for sub-message +// - 's' for string (validate UTF-8) +// - 'b' for bytes +// +// In position 4 (tag length): +// - '1' for one-byte tags (field numbers 1-15) +// - '2' for two-byte tags (field numbers 16-2048) + +#ifndef UPB_DECODE_FAST_H_ +#define UPB_DECODE_FAST_H_ + + +struct upb_decstate; + +// The fallback, generic parsing function that can handle any field type. +// This just uses the regular (non-fast) parser to parse a single field. +const char *fastdecode_generic(struct upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, uint64_t hasbits, + uint64_t data); + +#define UPB_PARSE_PARAMS \ + struct upb_decstate *d, const char *ptr, upb_msg *msg, intptr_t table, \ + uint64_t hasbits, uint64_t data + +/* primitive fields ***********************************************************/ + +#define F(card, type, valbytes, tagbytes) \ + const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS); + +#define TYPES(card, tagbytes) \ + F(card, b, 1, tagbytes) \ + F(card, v, 4, tagbytes) \ + F(card, v, 8, tagbytes) \ + F(card, z, 4, tagbytes) \ + F(card, z, 8, tagbytes) \ + F(card, f, 4, tagbytes) \ + F(card, f, 8, tagbytes) + +#define TAGBYTES(card) \ + TYPES(card, 1) \ + TYPES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) +TAGBYTES(p) + +#undef F +#undef TYPES +#undef TAGBYTES + +/* string fields **************************************************************/ + +#define F(card, tagbytes, type) \ + const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); \ + const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); + +#define UTF8(card, tagbytes) \ + F(card, tagbytes, s) \ + F(card, tagbytes, b) + +#define TAGBYTES(card) \ + UTF8(card, 1) \ + UTF8(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef F +#undef TAGBYTES + +/* sub-message fields *********************************************************/ + +#define F(card, tagbytes, size_ceil, ceil_arg) \ + const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b(UPB_PARSE_PARAMS); + +#define SIZES(card, tagbytes) \ + F(card, tagbytes, 64, 64) \ + F(card, tagbytes, 128, 128) \ + F(card, tagbytes, 192, 192) \ + F(card, tagbytes, 256, 256) \ + F(card, tagbytes, max, -1) + +#define TAGBYTES(card) \ + SIZES(card, 1) \ + SIZES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef TAGBYTES +#undef SIZES +#undef F + +#undef UPB_PARSE_PARAMS + +#endif /* UPB_DECODE_FAST_H_ */ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ + + + +#ifdef __cplusplus +extern "C" { +#endif + +struct google_protobuf_FileDescriptorSet; +struct google_protobuf_FileDescriptorProto; +struct google_protobuf_DescriptorProto; +struct google_protobuf_DescriptorProto_ExtensionRange; +struct google_protobuf_DescriptorProto_ReservedRange; +struct google_protobuf_ExtensionRangeOptions; +struct google_protobuf_FieldDescriptorProto; +struct google_protobuf_OneofDescriptorProto; +struct google_protobuf_EnumDescriptorProto; +struct google_protobuf_EnumDescriptorProto_EnumReservedRange; +struct google_protobuf_EnumValueDescriptorProto; +struct google_protobuf_ServiceDescriptorProto; +struct google_protobuf_MethodDescriptorProto; +struct google_protobuf_FileOptions; +struct google_protobuf_MessageOptions; +struct google_protobuf_FieldOptions; +struct google_protobuf_OneofOptions; +struct google_protobuf_EnumOptions; +struct google_protobuf_EnumValueOptions; +struct google_protobuf_ServiceOptions; +struct google_protobuf_MethodOptions; +struct google_protobuf_UninterpretedOption; +struct google_protobuf_UninterpretedOption_NamePart; +struct google_protobuf_SourceCodeInfo; +struct google_protobuf_SourceCodeInfo_Location; +struct google_protobuf_GeneratedCodeInfo; +struct google_protobuf_GeneratedCodeInfo_Annotation; +typedef struct google_protobuf_FileDescriptorSet google_protobuf_FileDescriptorSet; +typedef struct google_protobuf_FileDescriptorProto google_protobuf_FileDescriptorProto; +typedef struct google_protobuf_DescriptorProto google_protobuf_DescriptorProto; +typedef struct google_protobuf_DescriptorProto_ExtensionRange google_protobuf_DescriptorProto_ExtensionRange; +typedef struct google_protobuf_DescriptorProto_ReservedRange google_protobuf_DescriptorProto_ReservedRange; +typedef struct google_protobuf_ExtensionRangeOptions google_protobuf_ExtensionRangeOptions; +typedef struct google_protobuf_FieldDescriptorProto google_protobuf_FieldDescriptorProto; +typedef struct google_protobuf_OneofDescriptorProto google_protobuf_OneofDescriptorProto; +typedef struct google_protobuf_EnumDescriptorProto google_protobuf_EnumDescriptorProto; +typedef struct google_protobuf_EnumDescriptorProto_EnumReservedRange google_protobuf_EnumDescriptorProto_EnumReservedRange; +typedef struct google_protobuf_EnumValueDescriptorProto google_protobuf_EnumValueDescriptorProto; +typedef struct google_protobuf_ServiceDescriptorProto google_protobuf_ServiceDescriptorProto; +typedef struct google_protobuf_MethodDescriptorProto google_protobuf_MethodDescriptorProto; +typedef struct google_protobuf_FileOptions google_protobuf_FileOptions; +typedef struct google_protobuf_MessageOptions google_protobuf_MessageOptions; +typedef struct google_protobuf_FieldOptions google_protobuf_FieldOptions; +typedef struct google_protobuf_OneofOptions google_protobuf_OneofOptions; +typedef struct google_protobuf_EnumOptions google_protobuf_EnumOptions; +typedef struct google_protobuf_EnumValueOptions google_protobuf_EnumValueOptions; +typedef struct google_protobuf_ServiceOptions google_protobuf_ServiceOptions; +typedef struct google_protobuf_MethodOptions google_protobuf_MethodOptions; +typedef struct google_protobuf_UninterpretedOption google_protobuf_UninterpretedOption; +typedef struct google_protobuf_UninterpretedOption_NamePart google_protobuf_UninterpretedOption_NamePart; +typedef struct google_protobuf_SourceCodeInfo google_protobuf_SourceCodeInfo; +typedef struct google_protobuf_SourceCodeInfo_Location google_protobuf_SourceCodeInfo_Location; +typedef struct google_protobuf_GeneratedCodeInfo google_protobuf_GeneratedCodeInfo; +typedef struct google_protobuf_GeneratedCodeInfo_Annotation google_protobuf_GeneratedCodeInfo_Annotation; +extern const upb_msglayout google_protobuf_FileDescriptorSet_msginit; +extern const upb_msglayout google_protobuf_FileDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_DescriptorProto_msginit; +extern const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit; +extern const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit; +extern const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit; +extern const upb_msglayout google_protobuf_FieldDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_OneofDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_EnumDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit; +extern const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_MethodDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_FileOptions_msginit; +extern const upb_msglayout google_protobuf_MessageOptions_msginit; +extern const upb_msglayout google_protobuf_FieldOptions_msginit; +extern const upb_msglayout google_protobuf_OneofOptions_msginit; +extern const upb_msglayout google_protobuf_EnumOptions_msginit; +extern const upb_msglayout google_protobuf_EnumValueOptions_msginit; +extern const upb_msglayout google_protobuf_ServiceOptions_msginit; +extern const upb_msglayout google_protobuf_MethodOptions_msginit; +extern const upb_msglayout google_protobuf_UninterpretedOption_msginit; +extern const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit; +extern const upb_msglayout google_protobuf_SourceCodeInfo_msginit; +extern const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit; +extern const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit; +extern const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit; + +typedef enum { + google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1, + google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2, + google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3 +} google_protobuf_FieldDescriptorProto_Label; + +typedef enum { + google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1, + google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2, + google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3, + google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4, + google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5, + google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6, + google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7, + google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8, + google_protobuf_FieldDescriptorProto_TYPE_STRING = 9, + google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10, + google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11, + google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12, + google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13, + google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14, + google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15, + google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16, + google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17, + google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18 +} google_protobuf_FieldDescriptorProto_Type; + +typedef enum { + google_protobuf_FieldOptions_STRING = 0, + google_protobuf_FieldOptions_CORD = 1, + google_protobuf_FieldOptions_STRING_PIECE = 2 +} google_protobuf_FieldOptions_CType; + +typedef enum { + google_protobuf_FieldOptions_JS_NORMAL = 0, + google_protobuf_FieldOptions_JS_STRING = 1, + google_protobuf_FieldOptions_JS_NUMBER = 2 +} google_protobuf_FieldOptions_JSType; + +typedef enum { + google_protobuf_FileOptions_SPEED = 1, + google_protobuf_FileOptions_CODE_SIZE = 2, + google_protobuf_FileOptions_LITE_RUNTIME = 3 +} google_protobuf_FileOptions_OptimizeMode; + +typedef enum { + google_protobuf_MethodOptions_IDEMPOTENCY_UNKNOWN = 0, + google_protobuf_MethodOptions_NO_SIDE_EFFECTS = 1, + google_protobuf_MethodOptions_IDEMPOTENT = 2 +} google_protobuf_MethodOptions_IdempotencyLevel; + + +/* google.protobuf.FileDescriptorSet */ + +UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_new(upb_arena *arena) { + return (google_protobuf_FileDescriptorSet *)_upb_msg_new(&google_protobuf_FileDescriptorSet_msginit, arena); +} +UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize(const google_protobuf_FileDescriptorSet *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_FileDescriptorSet_has_file(const google_protobuf_FileDescriptorSet *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet *msg, size_t *len) { return (const google_protobuf_FileDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } + +UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_mutable_file(google_protobuf_FileDescriptorSet *msg, size_t *len) { + return (google_protobuf_FileDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_resize_file(google_protobuf_FileDescriptorSet *msg, size_t len, upb_arena *arena) { + return (google_protobuf_FileDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorSet_add_file(google_protobuf_FileDescriptorSet *msg, upb_arena *arena) { + struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.FileDescriptorProto */ + +UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_new(upb_arena *arena) { + return (google_protobuf_FileDescriptorProto *)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize(const google_protobuf_FileDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FileDescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } +UPB_INLINE upb_strview const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_message_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); } +UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_enum_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(44, 88)); } +UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_service(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(48, 96)); } +UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_ServiceDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(48, 96), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_extension(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(52, 104)); } +UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(52, 104), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_FileOptions*); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 64), const google_protobuf_SourceCodeInfo*); } +UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(56, 112), len); } +UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(60, 120), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); } + +UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; +} +UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) { + return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len); +} +UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { + return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(36, 72), len, UPB_SIZE(3, 4), arena); +} +UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto *msg, upb_strview val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(36, 72), UPB_SIZE(3, 4), &val, + arena); +} +UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_mutable_message_type(google_protobuf_FileDescriptorProto *msg, size_t *len) { + return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len); +} +UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_resize_message_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(40, 80), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescriptorProto_add_message_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(40, 80), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_mutable_enum_type(google_protobuf_FileDescriptorProto *msg, size_t *len) { + return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len); +} +UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_resize_enum_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(44, 88), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescriptorProto_add_enum_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(44, 88), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_mutable_service(google_protobuf_FileDescriptorProto *msg, size_t *len) { + return (google_protobuf_ServiceDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 96), len); +} +UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_resize_service(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_ServiceDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(48, 96), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDescriptorProto_add_service(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(48, 96), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_mutable_extension(google_protobuf_FileDescriptorProto *msg, size_t *len) { + return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 104), len); +} +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_resize_extension(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(52, 104), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDescriptorProto_add_extension(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(52, 104), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_FileOptions*) = value; +} +UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_FileOptions* sub = (struct google_protobuf_FileOptions*)google_protobuf_FileDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FileOptions*)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_FileDescriptorProto_set_options(msg, sub); + } + return sub; +} +UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(32, 64), google_protobuf_SourceCodeInfo*) = value; +} +UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_SourceCodeInfo* sub = (struct google_protobuf_SourceCodeInfo*)google_protobuf_FileDescriptorProto_source_code_info(msg); + if (sub == NULL) { + sub = (struct google_protobuf_SourceCodeInfo*)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena); + if (!sub) return NULL; + google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub); + } + return sub; +} +UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) { + return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 112), len); +} +UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { + return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(56, 112), len, 2, arena); +} +UPB_INLINE bool google_protobuf_FileDescriptorProto_add_public_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(56, 112), 2, &val, + arena); +} +UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) { + return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(60, 120), len); +} +UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { + return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(60, 120), len, 2, arena); +} +UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(60, 120), 2, &val, + arena); +} +UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value; +} + +/* google.protobuf.DescriptorProto */ + +UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_new(upb_arena *arena) { + return (google_protobuf_DescriptorProto *)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_DescriptorProto_serialize(const google_protobuf_DescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_DescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_field(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } +UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_nested_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); } +UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_enum_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(24, 48)); } +UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_extension_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 56)); } +UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ExtensionRange* const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_extension(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(32, 64)); } +UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(32, 64), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_MessageOptions*); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_oneof_decl(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(36, 72)); } +UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_OneofDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_reserved_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); } +UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); } +UPB_INLINE upb_strview const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); } + +UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_field(google_protobuf_DescriptorProto *msg, size_t *len) { + return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); +} +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_field(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_field(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_mutable_nested_type(google_protobuf_DescriptorProto *msg, size_t *len) { + return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len); +} +UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_resize_nested_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_add_nested_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(20, 40), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_mutable_enum_type(google_protobuf_DescriptorProto *msg, size_t *len) { + return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len); +} +UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_resize_enum_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_DescriptorProto_add_enum_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(24, 48), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_mutable_extension_range(google_protobuf_DescriptorProto *msg, size_t *len) { + return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len); +} +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_resize_extension_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(28, 56), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_add_extension_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(28, 56), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_extension(google_protobuf_DescriptorProto *msg, size_t *len) { + return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 64), len); +} +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_extension(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(32, 64), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_extension(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(32, 64), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_MessageOptions*) = value; +} +UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProto_mutable_options(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_MessageOptions* sub = (struct google_protobuf_MessageOptions*)google_protobuf_DescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_MessageOptions*)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_DescriptorProto_set_options(msg, sub); + } + return sub; +} +UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_mutable_oneof_decl(google_protobuf_DescriptorProto *msg, size_t *len) { + return (google_protobuf_OneofDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len); +} +UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_resize_oneof_decl(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_OneofDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(36, 72), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_DescriptorProto_add_oneof_decl(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(36, 72), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_mutable_reserved_range(google_protobuf_DescriptorProto *msg, size_t *len) { + return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len); +} +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_resize_reserved_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(40, 80), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_add_reserved_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(40, 80), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE upb_strview* google_protobuf_DescriptorProto_mutable_reserved_name(google_protobuf_DescriptorProto *msg, size_t *len) { + return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len); +} +UPB_INLINE upb_strview* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(44, 88), len, UPB_SIZE(3, 4), arena); +} +UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto *msg, upb_strview val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(44, 88), UPB_SIZE(3, 4), &val, + arena); +} + +/* google.protobuf.DescriptorProto.ExtensionRange */ + +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_new(upb_arena *arena) { + return (google_protobuf_DescriptorProto_ExtensionRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena); +} +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize(const google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } +UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const google_protobuf_ExtensionRangeOptions*); } + +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_start(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; +} +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(12, 16), google_protobuf_ExtensionRangeOptions*) = value; +} +UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_mutable_options(google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena) { + struct google_protobuf_ExtensionRangeOptions* sub = (struct google_protobuf_ExtensionRangeOptions*)google_protobuf_DescriptorProto_ExtensionRange_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_ExtensionRangeOptions*)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub); + } + return sub; +} + +/* google.protobuf.DescriptorProto.ReservedRange */ + +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_new(upb_arena *arena) { + return (google_protobuf_DescriptorProto_ReservedRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena); +} +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize(const google_protobuf_DescriptorProto_ReservedRange *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } + +UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_start(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; +} + +/* google.protobuf.ExtensionRangeOptions */ + +UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_new(upb_arena *arena) { + return (google_protobuf_ExtensionRangeOptions *)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena); +} +UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize(const google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } + +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_resize_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ExtensionRangeOptions_add_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.FieldDescriptorProto */ + +UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_new(upb_arena *arena) { + return (google_protobuf_FieldDescriptorProto *)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_protobuf_FieldDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), int32_t); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 7); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 8); } +UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(64, 104), const google_protobuf_FieldOptions*); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 9); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 10); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 11); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool); } + +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(12, 12), int32_t) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 6); + *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 7); + *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) { + _upb_sethas(msg, 8); + *UPB_PTR_AT(msg, UPB_SIZE(64, 104), google_protobuf_FieldOptions*) = value; +} +UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FieldOptions*)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_FieldDescriptorProto_set_options(msg, sub); + } + return sub; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) { + _upb_sethas(msg, 9); + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 10); + *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) { + _upb_sethas(msg, 11); + *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool) = value; +} + +/* google.protobuf.OneofDescriptorProto */ + +UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_new(upb_arena *arena) { + return (google_protobuf_OneofDescriptorProto *)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize(const google_protobuf_OneofDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_OneofDescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_OneofOptions*); } + +UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_OneofOptions*) = value; +} +UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_mutable_options(google_protobuf_OneofDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_OneofOptions* sub = (struct google_protobuf_OneofOptions*)google_protobuf_OneofDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_OneofOptions*)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_OneofDescriptorProto_set_options(msg, sub); + } + return sub; +} + +/* google.protobuf.EnumDescriptorProto */ + +UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_new(upb_arena *arena) { + return (google_protobuf_EnumDescriptorProto *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize(const google_protobuf_EnumDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumDescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_value(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } +UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumValueDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } +UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_EnumOptions*); } +UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_reserved_range(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); } +UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto_EnumReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); } +UPB_INLINE upb_strview const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); } + +UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_mutable_value(google_protobuf_EnumDescriptorProto *msg, size_t *len) { + return (google_protobuf_EnumValueDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); +} +UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_resize_value(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_EnumValueDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumDescriptorProto_add_value(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_EnumOptions*) = value; +} +UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_mutable_options(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_EnumOptions* sub = (struct google_protobuf_EnumOptions*)google_protobuf_EnumDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_EnumOptions*)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_EnumDescriptorProto_set_options(msg, sub); + } + return sub; +} +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_mutable_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t *len) { + return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len); +} +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_resize_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_add_reserved_range(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(20, 40), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_mutable_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t *len) { + return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len); +} +UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) { + return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, UPB_SIZE(3, 4), arena); +} +UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto *msg, upb_strview val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(24, 48), UPB_SIZE(3, 4), &val, + arena); +} + +/* google.protobuf.EnumDescriptorProto.EnumReservedRange */ + +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_new(upb_arena *arena) { + return (google_protobuf_EnumDescriptorProto_EnumReservedRange *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena); +} +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } + +UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; +} + +/* google.protobuf.EnumValueDescriptorProto */ + +UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_new(upb_arena *arena) { + return (google_protobuf_EnumValueDescriptorProto *)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize(const google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); } +UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const google_protobuf_EnumValueOptions*); } + +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value; +} +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(16, 24), google_protobuf_EnumValueOptions*) = value; +} +UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_mutable_options(google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_EnumValueOptions* sub = (struct google_protobuf_EnumValueOptions*)google_protobuf_EnumValueDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_EnumValueOptions*)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_EnumValueDescriptorProto_set_options(msg, sub); + } + return sub; +} + +/* google.protobuf.ServiceDescriptorProto */ + +UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_new(upb_arena *arena) { + return (google_protobuf_ServiceDescriptorProto *)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize(const google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_method(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } +UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto *msg, size_t *len) { return (const google_protobuf_MethodDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } +UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_ServiceOptions*); } + +UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_mutable_method(google_protobuf_ServiceDescriptorProto *msg, size_t *len) { + return (google_protobuf_MethodDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); +} +UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_resize_method(google_protobuf_ServiceDescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_MethodDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_ServiceDescriptorProto_add_method(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_ServiceOptions*) = value; +} +UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_mutable_options(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_ServiceOptions* sub = (struct google_protobuf_ServiceOptions*)google_protobuf_ServiceDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_ServiceOptions*)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_ServiceDescriptorProto_set_options(msg, sub); + } + return sub; +} + +/* google.protobuf.MethodDescriptorProto */ + +UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_new(upb_arena *arena) { + return (google_protobuf_MethodDescriptorProto *)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize(const google_protobuf_MethodDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_MethodDescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_MethodOptions*); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); } + +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; +} +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value; +} +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_MethodOptions*) = value; +} +UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_MethodOptions* sub = (struct google_protobuf_MethodOptions*)google_protobuf_MethodDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_MethodOptions*)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_MethodDescriptorProto_set_options(msg, sub); + } + return sub; +} +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; +} +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { + _upb_sethas(msg, 6); + *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value; +} + +/* google.protobuf.FileOptions */ + +UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_new(upb_arena *arena) { + return (google_protobuf_FileOptions *)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena); +} +UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FileOptions_serialize(const google_protobuf_FileOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FileOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE upb_strview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE upb_strview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(9, 9), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 7); } +UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(10, 10), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 8); } +UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(11, 11), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 9); } +UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 10); } +UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 11); } +UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 12); } +UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 13); } +UPB_INLINE upb_strview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 14); } +UPB_INLINE upb_strview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 15); } +UPB_INLINE upb_strview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 16); } +UPB_INLINE upb_strview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 17); } +UPB_INLINE upb_strview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 18); } +UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 19); } +UPB_INLINE upb_strview google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 20); } +UPB_INLINE upb_strview google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(92, 168), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_uninterpreted_option(const google_protobuf_FileOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(100, 184)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(100, 184), len); } + +UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 6); + *UPB_PTR_AT(msg, UPB_SIZE(9, 9), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 7); + *UPB_PTR_AT(msg, UPB_SIZE(10, 10), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 8); + *UPB_PTR_AT(msg, UPB_SIZE(11, 11), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 9); + *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 10); + *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 11); + *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 12); + *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 13); + *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 14); + *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 15); + *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 16); + *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 17); + *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 18); + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 19); + *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 20); + *UPB_PTR_AT(msg, UPB_SIZE(92, 168), upb_strview) = value; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mutable_uninterpreted_option(google_protobuf_FileOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(100, 184), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_resize_uninterpreted_option(google_protobuf_FileOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(100, 184), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptions_add_uninterpreted_option(google_protobuf_FileOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(100, 184), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.MessageOptions */ + +UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_new(upb_arena *arena) { + return (google_protobuf_MessageOptions *)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena); +} +UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_MessageOptions_serialize(const google_protobuf_MessageOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_MessageOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } +UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_MessageOptions_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); } +UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool); } +UPB_INLINE bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool); } +UPB_INLINE bool google_protobuf_MessageOptions_has_uninterpreted_option(const google_protobuf_MessageOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 8)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(8, 8), len); } + +UPB_INLINE void google_protobuf_MessageOptions_set_message_set_wire_format(google_protobuf_MessageOptions *msg, bool value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; +} +UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value; +} +UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool) = value; +} +UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool) = value; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_mutable_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 8), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_resize_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 8), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOptions_add_uninterpreted_option(google_protobuf_MessageOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(8, 8), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.FieldOptions */ + +UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_new(upb_arena *arena) { + return (google_protobuf_FieldOptions *)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena); +} +UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FieldOptions_serialize(const google_protobuf_FieldOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FieldOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool); } +UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool); } +UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool); } +UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } +UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool); } +UPB_INLINE bool google_protobuf_FieldOptions_has_uninterpreted_option(const google_protobuf_FieldOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 16)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(16, 16), len); } + +UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOptions *msg, int32_t value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool) = value; +} +UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool) = value; +} +UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool) = value; +} +UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; +} +UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) { + _upb_sethas(msg, 6); + *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool) = value; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 16), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_resize_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOptions_add_uninterpreted_option(google_protobuf_FieldOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(16, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.OneofOptions */ + +UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_new(upb_arena *arena) { + return (google_protobuf_OneofOptions *)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena); +} +UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_OneofOptions_serialize(const google_protobuf_OneofOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_OneofOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_OneofOptions_has_uninterpreted_option(const google_protobuf_OneofOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } + +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mutable_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_resize_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOptions_add_uninterpreted_option(google_protobuf_OneofOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.EnumOptions */ + +UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_new(upb_arena *arena) { + return (google_protobuf_EnumOptions *)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena); +} +UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumOptions_serialize(const google_protobuf_EnumOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } +UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); } +UPB_INLINE bool google_protobuf_EnumOptions_has_uninterpreted_option(const google_protobuf_EnumOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } + +UPB_INLINE void google_protobuf_EnumOptions_set_allow_alias(google_protobuf_EnumOptions *msg, bool value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; +} +UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mutable_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_resize_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptions_add_uninterpreted_option(google_protobuf_EnumOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.EnumValueOptions */ + +UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_new(upb_arena *arena) { + return (google_protobuf_EnumValueOptions *)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena); +} +UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumValueOptions_serialize(const google_protobuf_EnumValueOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumValueOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } +UPB_INLINE bool google_protobuf_EnumValueOptions_has_uninterpreted_option(const google_protobuf_EnumValueOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } + +UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_EnumValueOptions *msg, bool value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_resize_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValueOptions_add_uninterpreted_option(google_protobuf_EnumValueOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.ServiceOptions */ + +UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_new(upb_arena *arena) { + return (google_protobuf_ServiceOptions *)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena); +} +UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_ServiceOptions_serialize(const google_protobuf_ServiceOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_ServiceOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } +UPB_INLINE bool google_protobuf_ServiceOptions_has_uninterpreted_option(const google_protobuf_ServiceOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } + +UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_ServiceOptions *msg, bool value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_mutable_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_resize_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOptions_add_uninterpreted_option(google_protobuf_ServiceOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.MethodOptions */ + +UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_new(upb_arena *arena) { + return (google_protobuf_MethodOptions *)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena); +} +UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_MethodOptions_serialize(const google_protobuf_MethodOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_MethodOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool); } +UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_MethodOptions_has_uninterpreted_option(const google_protobuf_MethodOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(12, 16)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(12, 16), len); } + +UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value; +} +UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 16), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_resize_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(12, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOptions_add_uninterpreted_option(google_protobuf_MethodOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(12, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.UninterpretedOption */ + +UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_new(upb_arena *arena) { + return (google_protobuf_UninterpretedOption *)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); +} +UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_UninterpretedOption_serialize(const google_protobuf_UninterpretedOption *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_UninterpretedOption_has_name(const google_protobuf_UninterpretedOption *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(56, 80)); } +UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg, size_t *len) { return (const google_protobuf_UninterpretedOption_NamePart* const*)_upb_array_accessor(msg, UPB_SIZE(56, 80), len); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview); } + +UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_mutable_name(google_protobuf_UninterpretedOption *msg, size_t *len) { + return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 80), len); +} +UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_resize_name(google_protobuf_UninterpretedOption *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_resize_accessor2(msg, UPB_SIZE(56, 80), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_add_name(google_protobuf_UninterpretedOption *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(56, 80), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview) = value; +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t) = value; +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t) = value; +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double) = value; +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_strview value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview) = value; +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_strview value) { + _upb_sethas(msg, 6); + *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview) = value; +} + +/* google.protobuf.UninterpretedOption.NamePart */ + +UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_new(upb_arena *arena) { + return (google_protobuf_UninterpretedOption_NamePart *)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena); +} +UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize(const google_protobuf_UninterpretedOption_NamePart *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } + +UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; +} + +/* google.protobuf.SourceCodeInfo */ + +UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_new(upb_arena *arena) { + return (google_protobuf_SourceCodeInfo *)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena); +} +UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize(const google_protobuf_SourceCodeInfo *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_SourceCodeInfo_has_location(const google_protobuf_SourceCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo *msg, size_t *len) { return (const google_protobuf_SourceCodeInfo_Location* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } + +UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_mutable_location(google_protobuf_SourceCodeInfo *msg, size_t *len) { + return (google_protobuf_SourceCodeInfo_Location**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_resize_location(google_protobuf_SourceCodeInfo *msg, size_t len, upb_arena *arena) { + return (google_protobuf_SourceCodeInfo_Location**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_add_location(google_protobuf_SourceCodeInfo *msg, upb_arena *arena) { + struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.SourceCodeInfo.Location */ + +UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_new(upb_arena *arena) { + return (google_protobuf_SourceCodeInfo_Location *)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena); +} +UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize(const google_protobuf_SourceCodeInfo_Location *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, arena, len); +} + +UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); } +UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); } +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } +UPB_INLINE upb_strview const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); } + +UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_path(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { + return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len); +} +UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_path(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) { + return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, 2, arena); +} +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_path(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(20, 40), 2, &val, + arena); +} +UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_span(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { + return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len); +} +UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_span(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) { + return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, 2, arena); +} +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_span(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(24, 48), 2, &val, + arena); +} +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; +} +UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { + return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len); +} +UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) { + return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(28, 56), len, UPB_SIZE(3, 4), arena); +} +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(28, 56), UPB_SIZE(3, 4), &val, + arena); +} + +/* google.protobuf.GeneratedCodeInfo */ + +UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_new(upb_arena *arena) { + return (google_protobuf_GeneratedCodeInfo *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_msginit, arena); +} +UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize(const google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_has_annotation(const google_protobuf_GeneratedCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo *msg, size_t *len) { return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } + +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_mutable_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t *len) { + return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_resize_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t len, upb_arena *arena) { + return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_add_annotation(google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena) { + struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.GeneratedCodeInfo.Annotation */ + +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_new(upb_arena *arena) { + return (google_protobuf_GeneratedCodeInfo_Annotation *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena); +} +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize(const google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, len); +} + +UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); } +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview); } +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } + +UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { + return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 32), len); +} +UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_resize_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t len, upb_arena *arena) { + return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 32), len, 2, arena); +} +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(20, 32), 2, &val, + arena); +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview) = value; +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ */ +/* +** Defs are upb's internal representation of the constructs that can appear +** in a .proto file: +** +** - upb_msgdef: describes a "message" construct. +** - upb_fielddef: describes a message field. +** - upb_filedef: describes a .proto file and its defs. +** - upb_enumdef: describes an enum. +** - upb_oneofdef: describes a oneof. +** +** TODO: definitions of services. +*/ + +#ifndef UPB_DEF_H_ +#define UPB_DEF_H_ + + +/* Must be last. */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct upb_enumdef; +typedef struct upb_enumdef upb_enumdef; +struct upb_fielddef; +typedef struct upb_fielddef upb_fielddef; +struct upb_filedef; +typedef struct upb_filedef upb_filedef; +struct upb_msgdef; +typedef struct upb_msgdef upb_msgdef; +struct upb_oneofdef; +typedef struct upb_oneofdef upb_oneofdef; +struct upb_symtab; +typedef struct upb_symtab upb_symtab; + +typedef enum { + UPB_SYNTAX_PROTO2 = 2, + UPB_SYNTAX_PROTO3 = 3 +} upb_syntax_t; + +/* 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. + */ +typedef enum { + UPB_WELLKNOWN_UNSPECIFIED, + UPB_WELLKNOWN_ANY, + UPB_WELLKNOWN_FIELDMASK, + UPB_WELLKNOWN_DURATION, + UPB_WELLKNOWN_TIMESTAMP, + /* number wrappers */ + UPB_WELLKNOWN_DOUBLEVALUE, + UPB_WELLKNOWN_FLOATVALUE, + UPB_WELLKNOWN_INT64VALUE, + UPB_WELLKNOWN_UINT64VALUE, + UPB_WELLKNOWN_INT32VALUE, + UPB_WELLKNOWN_UINT32VALUE, + /* string wrappers */ + UPB_WELLKNOWN_STRINGVALUE, + UPB_WELLKNOWN_BYTESVALUE, + UPB_WELLKNOWN_BOOLVALUE, + UPB_WELLKNOWN_VALUE, + UPB_WELLKNOWN_LISTVALUE, + UPB_WELLKNOWN_STRUCT +} upb_wellknowntype_t; + +/* upb_fielddef ***************************************************************/ + +/* Maximum field number allowed for FieldDefs. This is an inherent limit of the + * protobuf wire format. */ +#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1) + +const char *upb_fielddef_fullname(const upb_fielddef *f); +upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f); +upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f); +upb_label_t upb_fielddef_label(const upb_fielddef *f); +uint32_t upb_fielddef_number(const upb_fielddef *f); +const char *upb_fielddef_name(const upb_fielddef *f); +const char *upb_fielddef_jsonname(const upb_fielddef *f); +bool upb_fielddef_isextension(const upb_fielddef *f); +bool upb_fielddef_lazy(const upb_fielddef *f); +bool upb_fielddef_packed(const upb_fielddef *f); +const upb_filedef *upb_fielddef_file(const upb_fielddef *f); +const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f); +const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f); +const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f); +uint32_t upb_fielddef_index(const upb_fielddef *f); +bool upb_fielddef_issubmsg(const upb_fielddef *f); +bool upb_fielddef_isstring(const upb_fielddef *f); +bool upb_fielddef_isseq(const upb_fielddef *f); +bool upb_fielddef_isprimitive(const upb_fielddef *f); +bool upb_fielddef_ismap(const upb_fielddef *f); +int64_t upb_fielddef_defaultint64(const upb_fielddef *f); +int32_t upb_fielddef_defaultint32(const upb_fielddef *f); +uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f); +uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f); +bool upb_fielddef_defaultbool(const upb_fielddef *f); +float upb_fielddef_defaultfloat(const upb_fielddef *f); +double upb_fielddef_defaultdouble(const upb_fielddef *f); +const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len); +bool upb_fielddef_hassubdef(const upb_fielddef *f); +bool upb_fielddef_haspresence(const upb_fielddef *f); +const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f); +const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f); +const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f); + +/* Internal only. */ +uint32_t upb_fielddef_selectorbase(const upb_fielddef *f); + +/* upb_oneofdef ***************************************************************/ + +typedef upb_inttable_iter upb_oneof_iter; + +const char *upb_oneofdef_name(const upb_oneofdef *o); +const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o); +uint32_t upb_oneofdef_index(const upb_oneofdef *o); +bool upb_oneofdef_issynthetic(const upb_oneofdef *o); +int upb_oneofdef_fieldcount(const upb_oneofdef *o); +const upb_fielddef *upb_oneofdef_field(const upb_oneofdef *o, int i); + +/* Oneof lookups: + * - ntof: look up a field by name. + * - ntofz: look up a field by name (as a null-terminated string). + * - itof: look up a field by number. */ +const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, + const char *name, size_t length); +UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o, + const char *name) { + return upb_oneofdef_ntof(o, name, strlen(name)); +} +const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num); + +/* DEPRECATED, slated for removal. */ +int upb_oneofdef_numfields(const upb_oneofdef *o); +void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o); +void upb_oneof_next(upb_oneof_iter *iter); +bool upb_oneof_done(upb_oneof_iter *iter); +upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter); +void upb_oneof_iter_setdone(upb_oneof_iter *iter); +bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1, + const upb_oneof_iter *iter2); +/* END DEPRECATED */ + +/* upb_msgdef *****************************************************************/ + +typedef upb_inttable_iter upb_msg_field_iter; +typedef upb_strtable_iter upb_msg_oneof_iter; + +/* Well-known field tag numbers for map-entry messages. */ +#define UPB_MAPENTRY_KEY 1 +#define UPB_MAPENTRY_VALUE 2 + +/* Well-known field tag numbers for Any messages. */ +#define UPB_ANY_TYPE 1 +#define UPB_ANY_VALUE 2 + +/* Well-known field tag numbers for timestamp messages. */ +#define UPB_DURATION_SECONDS 1 +#define UPB_DURATION_NANOS 2 + +/* Well-known field tag numbers for duration messages. */ +#define UPB_TIMESTAMP_SECONDS 1 +#define UPB_TIMESTAMP_NANOS 2 + +const char *upb_msgdef_fullname(const upb_msgdef *m); +const upb_filedef *upb_msgdef_file(const upb_msgdef *m); +const char *upb_msgdef_name(const upb_msgdef *m); +upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m); +bool upb_msgdef_mapentry(const upb_msgdef *m); +upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m); +bool upb_msgdef_iswrapper(const upb_msgdef *m); +bool upb_msgdef_isnumberwrapper(const upb_msgdef *m); +int upb_msgdef_fieldcount(const upb_msgdef *m); +int upb_msgdef_oneofcount(const upb_msgdef *m); +const upb_fielddef *upb_msgdef_field(const upb_msgdef *m, int i); +const upb_oneofdef *upb_msgdef_oneof(const upb_msgdef *m, int i); +const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i); +const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name, + size_t len); +const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, + size_t len); +const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m); + +UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m, + const char *name) { + return upb_msgdef_ntoo(m, name, strlen(name)); +} + +UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m, + const char *name) { + return upb_msgdef_ntof(m, name, strlen(name)); +} + +/* Internal-only. */ +size_t upb_msgdef_selectorcount(const upb_msgdef *m); +uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m); + +/* Lookup of either field or oneof by name. Returns whether either was found. + * If the return is true, then the found def will be set, and the non-found + * one set to NULL. */ +bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len, + const upb_fielddef **f, const upb_oneofdef **o); + +UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name, + const upb_fielddef **f, + const upb_oneofdef **o) { + return upb_msgdef_lookupname(m, name, strlen(name), f, o); +} + +/* Returns a field by either JSON name or regular proto name. */ +const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m, + const char *name, size_t len); + +/* DEPRECATED, slated for removal */ +int upb_msgdef_numfields(const upb_msgdef *m); +int upb_msgdef_numoneofs(const upb_msgdef *m); +int upb_msgdef_numrealoneofs(const upb_msgdef *m); +void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m); +void upb_msg_field_next(upb_msg_field_iter *iter); +bool upb_msg_field_done(const upb_msg_field_iter *iter); +upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter); +void upb_msg_field_iter_setdone(upb_msg_field_iter *iter); +bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1, + const upb_msg_field_iter * iter2); +void upb_msg_oneof_begin(upb_msg_oneof_iter * iter, const upb_msgdef *m); +void upb_msg_oneof_next(upb_msg_oneof_iter * iter); +bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter); +const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter); +void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter); +bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1, + const upb_msg_oneof_iter *iter2); +/* END DEPRECATED */ + +/* upb_enumdef ****************************************************************/ + +typedef upb_strtable_iter upb_enum_iter; + +const char *upb_enumdef_fullname(const upb_enumdef *e); +const char *upb_enumdef_name(const upb_enumdef *e); +const upb_filedef *upb_enumdef_file(const upb_enumdef *e); +int32_t upb_enumdef_default(const upb_enumdef *e); +int upb_enumdef_numvals(const upb_enumdef *e); + +/* Enum lookups: + * - ntoi: look up a name with specified length. + * - ntoiz: look up a name provided as a null-terminated string. + * - iton: look up an integer, returning the name as a null-terminated + * string. */ +bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len, + int32_t *num); +UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e, + const char *name, int32_t *num) { + return upb_enumdef_ntoi(e, name, strlen(name), num); +} +const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num); + +void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e); +void upb_enum_next(upb_enum_iter *iter); +bool upb_enum_done(upb_enum_iter *iter); +const char *upb_enum_iter_name(upb_enum_iter *iter); +int32_t upb_enum_iter_number(upb_enum_iter *iter); + +/* upb_filedef ****************************************************************/ + +const char *upb_filedef_name(const upb_filedef *f); +const char *upb_filedef_package(const upb_filedef *f); +const char *upb_filedef_phpprefix(const upb_filedef *f); +const char *upb_filedef_phpnamespace(const upb_filedef *f); +upb_syntax_t upb_filedef_syntax(const upb_filedef *f); +int upb_filedef_depcount(const upb_filedef *f); +int upb_filedef_msgcount(const upb_filedef *f); +int upb_filedef_enumcount(const upb_filedef *f); +const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i); +const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i); +const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i); +const upb_symtab *upb_filedef_symtab(const upb_filedef *f); + +/* upb_symtab *****************************************************************/ + +upb_symtab *upb_symtab_new(void); +void upb_symtab_free(upb_symtab* s); +const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym); +const upb_msgdef *upb_symtab_lookupmsg2( + const upb_symtab *s, const char *sym, size_t len); +const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym); +const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name); +const upb_filedef *upb_symtab_lookupfile2( + const upb_symtab *s, const char *name, size_t len); +int upb_symtab_filecount(const upb_symtab *s); +const upb_filedef *upb_symtab_addfile( + upb_symtab *s, const google_protobuf_FileDescriptorProto *file, + upb_status *status); +size_t _upb_symtab_bytesloaded(const upb_symtab *s); +upb_arena *_upb_symtab_arena(const upb_symtab *s); + +/* For generated code only: loads a generated descriptor. */ +typedef struct upb_def_init { + struct upb_def_init **deps; /* Dependencies of this file. */ + const upb_msglayout **layouts; /* Pre-order layouts of all messages. */ + const char *filename; + upb_strview descriptor; /* Serialized descriptor. */ +} upb_def_init; + +bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* UPB_DEF_H_ */ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPBDEFS_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPBDEFS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +extern upb_def_init google_protobuf_descriptor_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *google_protobuf_FileDescriptorSet_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorSet"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_FileDescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_DescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_DescriptorProto_ExtensionRange_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto.ExtensionRange"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_DescriptorProto_ReservedRange_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto.ReservedRange"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_ExtensionRangeOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.ExtensionRangeOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_FieldDescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.FieldDescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_OneofDescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.OneofDescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_EnumDescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.EnumDescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_EnumDescriptorProto_EnumReservedRange_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.EnumDescriptorProto.EnumReservedRange"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_EnumValueDescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.EnumValueDescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_ServiceDescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.ServiceDescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_MethodDescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.MethodDescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_FileOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.FileOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_MessageOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.MessageOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_FieldOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.FieldOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_OneofOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.OneofOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_EnumOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.EnumOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_EnumValueOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.EnumValueOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_ServiceOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.ServiceOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_MethodOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.MethodOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_UninterpretedOption_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_UninterpretedOption_NamePart_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption.NamePart"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_SourceCodeInfo_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_SourceCodeInfo_Location_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo.Location"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_GeneratedCodeInfo_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.GeneratedCodeInfo"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_GeneratedCodeInfo_Annotation_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.GeneratedCodeInfo.Annotation"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPBDEFS_H_ */ + +#ifndef UPB_REFLECTION_H_ +#define UPB_REFLECTION_H_ + + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef union { + bool bool_val; + float float_val; + double double_val; + int32_t int32_val; + int64_t int64_val; + uint32_t uint32_val; + uint64_t uint64_val; + const upb_map* map_val; + const upb_msg* msg_val; + const upb_array* array_val; + upb_strview str_val; +} upb_msgval; + +typedef union { + upb_map* map; + upb_msg* msg; + upb_array* array; +} upb_mutmsgval; + +upb_msgval upb_fielddef_default(const upb_fielddef *f); + +/** upb_msg *******************************************************************/ + +/* Creates a new message of the given type in the given arena. */ +upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a); + +/* Returns the value associated with this field. */ +upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f); + +/* Returns a mutable pointer to a map, array, or submessage value. If the given + * arena is non-NULL this will construct a new object if it was not previously + * present. May not be called for primitive fields. */ +upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, upb_arena *a); + +/* May only be called for fields where upb_fielddef_haspresence(f) == true. */ +bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f); + +/* Returns the field that is set in the oneof, or NULL if none are set. */ +const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg, + const upb_oneofdef *o); + +/* Sets the given field to the given value. For a msg/array/map/string, the + * value must be in the same arena. */ +void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val, + upb_arena *a); + +/* Clears any field presence and sets the value back to its default. */ +void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f); + +/* Clear all data and unknown fields. */ +void upb_msg_clear(upb_msg *msg, const upb_msgdef *m); + +/* Iterate over present fields. + * + * size_t iter = UPB_MSG_BEGIN; + * const upb_fielddef *f; + * upb_msgval val; + * while (upb_msg_next(msg, m, ext_pool, &f, &val, &iter)) { + * process_field(f, val); + * } + * + * If ext_pool is NULL, no extensions will be returned. If the given symtab + * returns extensions that don't match what is in this message, those extensions + * will be skipped. + */ + +#define UPB_MSG_BEGIN -1 +bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m, + const upb_symtab *ext_pool, const upb_fielddef **f, + upb_msgval *val, size_t *iter); + +/* Adds unknown data (serialized protobuf data) to the given message. The data + * is copied into the message instance. */ +void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, + upb_arena *arena); + +/* Clears all unknown field data from this message and all submessages. */ +bool upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int maxdepth); + +/* Returns a reference to the message's unknown data. */ +const char *upb_msg_getunknown(const upb_msg *msg, size_t *len); + +/** upb_array *****************************************************************/ + +/* Creates a new array on the given arena that holds elements of this type. */ +upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type); + +/* Returns the size of the array. */ +size_t upb_array_size(const upb_array *arr); + +/* Returns the given element, which must be within the array's current size. */ +upb_msgval upb_array_get(const upb_array *arr, size_t i); + +/* Sets the given element, which must be within the array's current size. */ +void upb_array_set(upb_array *arr, size_t i, upb_msgval val); + +/* Appends an element to the array. Returns false on allocation failure. */ +bool upb_array_append(upb_array *array, upb_msgval val, upb_arena *arena); + +/* Changes the size of a vector. New elements are initialized to empty/0. + * Returns false on allocation failure. */ +bool upb_array_resize(upb_array *array, size_t size, upb_arena *arena); + +/** upb_map *******************************************************************/ + +/* Creates a new map on the given arena with the given key/value size. */ +upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type, + upb_fieldtype_t value_type); + +/* Returns the number of entries in the map. */ +size_t upb_map_size(const upb_map *map); + +/* Stores a value for the given key into |*val| (or the zero value if the key is + * not present). Returns whether the key was present. The |val| pointer may be + * NULL, in which case the function tests whether the given key is present. */ +bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val); + +/* Removes all entries in the map. */ +void upb_map_clear(upb_map *map); + +/* Sets the given key to the given value. Returns true if this was a new key in + * the map, or false if an existing key was replaced. */ +bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, + upb_arena *arena); + +/* Deletes this key from the table. Returns true if the key was present. */ +bool upb_map_delete(upb_map *map, upb_msgval key); + +/* Map iteration: + * + * size_t iter = UPB_MAP_BEGIN; + * while (upb_mapiter_next(map, &iter)) { + * upb_msgval key = upb_mapiter_key(map, iter); + * upb_msgval val = upb_mapiter_value(map, iter); + * + * // If mutating is desired. + * upb_mapiter_setvalue(map, iter, value2); + * } + */ + +/* Advances to the next entry. Returns false if no more entries are present. */ +bool upb_mapiter_next(const upb_map *map, size_t *iter); + +/* Returns true if the iterator still points to a valid entry, or false if the + * iterator is past the last element. It is an error to call this function with + * UPB_MAP_BEGIN (you must call next() at least once first). */ +bool upb_mapiter_done(const upb_map *map, size_t iter); + +/* Returns the key and value for this entry of the map. */ +upb_msgval upb_mapiter_key(const upb_map *map, size_t iter); +upb_msgval upb_mapiter_value(const upb_map *map, size_t iter); + +/* Sets the value for this entry. The iterator must not be done, and the + * iterator must not have been initialized const. */ +void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_REFLECTION_H_ */ + +#ifndef UPB_JSONDECODE_H_ +#define UPB_JSONDECODE_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + UPB_JSONDEC_IGNOREUNKNOWN = 1 +}; + +bool upb_json_decode(const char *buf, size_t size, upb_msg *msg, + const upb_msgdef *m, const upb_symtab *any_pool, + int options, upb_arena *arena, upb_status *status); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* UPB_JSONDECODE_H_ */ + +#ifndef UPB_JSONENCODE_H_ +#define UPB_JSONENCODE_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /* When set, emits 0/default values. TODO(haberman): proto3 only? */ + UPB_JSONENC_EMITDEFAULTS = 1, + + /* When set, use normal (snake_caes) field names instead of JSON (camelCase) + names. */ + UPB_JSONENC_PROTONAMES = 2 +}; + +/* Encodes the given |msg| to JSON format. The message's reflection is given in + * |m|. The symtab in |symtab| is used to find extensions (if NULL, extensions + * will not be printed). + * + * Output is placed in the given buffer, and always NULL-terminated. The output + * size (excluding NULL) is returned. This means that a return value >= |size| + * implies that the output was truncated. (These are the same semantics as + * snprintf()). */ +size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m, + const upb_symtab *ext_pool, int options, char *buf, + size_t size, upb_status *status); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* UPB_JSONENCODE_H_ */ +/* See port_def.inc. This should #undef all macros #defined there. */ + +#undef UPB_MAPTYPE_STRING +#undef UPB_SIZE +#undef UPB_PTR_AT +#undef UPB_READ_ONEOF +#undef UPB_WRITE_ONEOF +#undef UPB_INLINE +#undef UPB_ALIGN_UP +#undef UPB_ALIGN_DOWN +#undef UPB_ALIGN_MALLOC +#undef UPB_ALIGN_OF +#undef UPB_FORCEINLINE +#undef UPB_NOINLINE +#undef UPB_NORETURN +#undef UPB_MAX +#undef UPB_MIN +#undef UPB_UNUSED +#undef UPB_ASSUME +#undef UPB_ASSERT +#undef UPB_UNREACHABLE +#undef UPB_POISON_MEMORY_REGION +#undef UPB_UNPOISON_MEMORY_REGION +#undef UPB_ASAN diff --git a/php/ext/google/protobuf/protobuf.c b/php/ext/google/protobuf/protobuf.c index dc73003069897..dbdd22a8f624e 100644 --- a/php/ext/google/protobuf/protobuf.c +++ b/php/ext/google/protobuf/protobuf.c @@ -30,203 +30,294 @@ #include "protobuf.h" -#include +#include +#include -ZEND_DECLARE_MODULE_GLOBALS(protobuf) -static PHP_GINIT_FUNCTION(protobuf); -static PHP_GSHUTDOWN_FUNCTION(protobuf); -static PHP_RINIT_FUNCTION(protobuf); -static PHP_RSHUTDOWN_FUNCTION(protobuf); -static PHP_MINIT_FUNCTION(protobuf); -static PHP_MSHUTDOWN_FUNCTION(protobuf); - -// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor -// instances. -static HashTable* upb_def_to_php_obj_map; -// Global map from message/enum's php class entry to corresponding wrapper -// Descriptor/EnumDescriptor instances. -static HashTable* ce_to_php_obj_map; +#include "arena.h" +#include "array.h" +#include "convert.h" +#include "def.h" +#include "map.h" +#include "message.h" +#include "names.h" // ----------------------------------------------------------------------------- -// Global maps. +// Module "globals" // ----------------------------------------------------------------------------- -static void add_to_table(HashTable* t, const void* def, void* value) { - uint nIndex = (ulong)def & t->nTableMask; +// Despite the name, module "globals" are really thread-locals: +// * PROTOBUF_G(var) accesses the thread-local variable for 'var'. Either: +// * PROTOBUF_G(var) -> protobuf_globals.var (Non-ZTS / non-thread-safe) +// * PROTOBUF_G(var) -> (ZTS / thread-safe builds) + +#define PROTOBUF_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(protobuf, v) + +ZEND_BEGIN_MODULE_GLOBALS(protobuf) + // Set by the user to make the descriptor pool persist between requests. + zend_bool keep_descriptor_pool_after_request; + + // Currently we make the generated pool a "global", which means that if a user + // does explicitly create threads within their request, the other threads will + // get different results from DescriptorPool::getGeneratedPool(). We require + // that all descriptors are loaded from the main thread. + zval generated_pool; + + // A upb_symtab that we are saving for the next request so that we don't have + // to rebuild it from scratch. When keep_descriptor_pool_after_request==true, + // we steal the upb_symtab from the global DescriptorPool object just before + // destroying it. + upb_symtab *saved_symtab; + + // Object cache (see interface in protobuf.h). + HashTable object_cache; - zval* pDest = NULL; - php_proto_zend_hash_index_update_mem(t, (zend_ulong)def, &value, - sizeof(zval*), (void**)&pDest); + // Name cache (see interface in protobuf.h). + HashTable name_msg_cache; + HashTable name_enum_cache; +ZEND_END_MODULE_GLOBALS(protobuf) + +ZEND_DECLARE_MODULE_GLOBALS(protobuf) + +const zval *get_generated_pool() { + return &PROTOBUF_G(generated_pool); } -static void* get_from_table(const HashTable* t, const void* def) { - void** value; - if (php_proto_zend_hash_index_find_mem(t, (zend_ulong)def, (void**)&value) == - FAILURE) { - return NULL; +// This is a PHP extension (not a Zend extension). What follows is a summary of +// a PHP extension's lifetime and when various handlers are called. +// +// * PHP_GINIT_FUNCTION(protobuf) / PHP_GSHUTDOWN_FUNCTION(protobuf) +// are the constructor/destructor for the globals. The sequence over the +// course of a process lifetime is: +// +// # Process startup +// GINIT(
) +// MINIT +// +// foreach request: +// RINIT +// # Request is processed here. +// RSHUTDOWN +// +// foreach thread: +// GINIT() +// # Code for the thread runs here. +// GSHUTDOWN() +// +// # Process Shutdown +// # +// # These should be running per the docs, but I have not been able to +// # actually get the process-wide shutdown functions to run. +// # +// # MSHUTDOWN +// # GSHUTDOWN(
) +// +// * Threads can be created either explicitly by the user, inside a request, +// or implicitly by the runtime, to process multiple requests concurrently. +// If the latter is being used, then the "foreach thread" block above +// actually looks like this: +// +// foreach thread: +// GINIT() +// # A non-main thread will only receive requests when using a threaded +// # MPM with Apache +// foreach request: +// RINIT +// # Request is processed here. +// RSHUTDOWN +// GSHUTDOWN() +// +// That said, it appears that few people use threads with PHP: +// * The pthread package documented at +// https://www.php.net/manual/en/class.thread.php nas not been released +// since 2016, and the current release fails to compile against any PHP +// newer than 7.0.33. +// * The GitHub master branch supports 7.2+, but this has not been released +// to PECL. +// * Its owner has disavowed it as "broken by design" and "in an untenable +// position for the future": https://github.com/krakjoe/pthreads/issues/929 +// * The only way to use PHP with requests in different threads is to use the +// Apache 2 mod_php with the "worker" MPM. But this is explicitly +// discouraged by the documentation: https://serverfault.com/a/231660 + +static PHP_GSHUTDOWN_FUNCTION(protobuf) { + if (protobuf_globals->saved_symtab) { + upb_symtab_free(protobuf_globals->saved_symtab); } - return *value; } -static bool exist_in_table(const HashTable* t, const void* def) { - void** value; - return (php_proto_zend_hash_index_find_mem(t, (zend_ulong)def, - (void**)&value) == SUCCESS); +static PHP_GINIT_FUNCTION(protobuf) { + ZVAL_NULL(&protobuf_globals->generated_pool); + protobuf_globals->saved_symtab = NULL; } -static void add_to_list(HashTable* t, void* value) { - zval* pDest = NULL; - php_proto_zend_hash_next_index_insert_mem(t, &value, sizeof(void*), - (void**)&pDest); -} +/** + * PHP_RINIT_FUNCTION(protobuf) + * + * This function is run at the beginning of processing each request. + */ +static PHP_RINIT_FUNCTION(protobuf) { + // Create the global generated pool. + // Reuse the symtab (if any) left to us by the last request. + upb_symtab *symtab = PROTOBUF_G(saved_symtab); + DescriptorPool_CreateWithSymbolTable(&PROTOBUF_G(generated_pool), symtab); -void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value) { -#if PHP_MAJOR_VERSION < 7 - Z_ADDREF_P(value); -#else - ++GC_REFCOUNT(value); -#endif - add_to_table(upb_def_to_php_obj_map, def, value); -} + zend_hash_init(&PROTOBUF_G(object_cache), 64, NULL, NULL, 0); + zend_hash_init(&PROTOBUF_G(name_msg_cache), 64, NULL, NULL, 0); + zend_hash_init(&PROTOBUF_G(name_enum_cache), 64, NULL, NULL, 0); -PHP_PROTO_HASHTABLE_VALUE get_def_obj(const void* def) { - return (PHP_PROTO_HASHTABLE_VALUE)get_from_table(upb_def_to_php_obj_map, def); + return SUCCESS; } -void add_ce_obj(const void* ce, PHP_PROTO_HASHTABLE_VALUE value) { -#if PHP_MAJOR_VERSION < 7 - Z_ADDREF_P(value); -#else - ++GC_REFCOUNT(value); -#endif - add_to_table(ce_to_php_obj_map, ce, value); -} +/** + * PHP_RSHUTDOWN_FUNCTION(protobuf) + * + * This function is run at the end of processing each request. + */ +static PHP_RSHUTDOWN_FUNCTION(protobuf) { + // Preserve the symtab if requested. + if (PROTOBUF_G(keep_descriptor_pool_after_request)) { + zval *zv = &PROTOBUF_G(generated_pool); + PROTOBUF_G(saved_symtab) = DescriptorPool_Steal(zv); + } -PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce) { - return (PHP_PROTO_HASHTABLE_VALUE)get_from_table(ce_to_php_obj_map, ce); -} + zval_dtor(&PROTOBUF_G(generated_pool)); + zend_hash_destroy(&PROTOBUF_G(object_cache)); + zend_hash_destroy(&PROTOBUF_G(name_msg_cache)); + zend_hash_destroy(&PROTOBUF_G(name_enum_cache)); -bool class_added(const void* ce) { - return exist_in_table(ce_to_php_obj_map, ce); + return SUCCESS; } // ----------------------------------------------------------------------------- -// Utilities. +// Object Cache. // ----------------------------------------------------------------------------- -zend_function_entry protobuf_functions[] = { - ZEND_FE_END -}; - -zend_module_entry protobuf_module_entry = { - STANDARD_MODULE_HEADER, - PHP_PROTOBUF_EXTNAME, // extension name - protobuf_functions, // function list - PHP_MINIT(protobuf), // process startup - PHP_MSHUTDOWN(protobuf), // process shutdown - PHP_RINIT(protobuf), // request shutdown - PHP_RSHUTDOWN(protobuf), // request shutdown - NULL, // extension info - PHP_PROTOBUF_VERSION, // extension version - PHP_MODULE_GLOBALS(protobuf), // globals descriptor - PHP_GINIT(protobuf), // globals ctor - PHP_GSHUTDOWN(protobuf), // globals dtor - NULL, // post deactivate - STANDARD_MODULE_PROPERTIES_EX -}; - -// install module -ZEND_GET_MODULE(protobuf) - -// global variables -static PHP_GINIT_FUNCTION(protobuf) { +void ObjCache_Add(const void *upb_obj, zend_object *php_obj) { + zend_ulong k = (zend_ulong)upb_obj; + zend_hash_index_add_ptr(&PROTOBUF_G(object_cache), k, php_obj); } -static PHP_GSHUTDOWN_FUNCTION(protobuf) { +void ObjCache_Delete(const void *upb_obj) { + if (upb_obj) { + zend_ulong k = (zend_ulong)upb_obj; + int ret = zend_hash_index_del(&PROTOBUF_G(object_cache), k); + PBPHP_ASSERT(ret == SUCCESS); + } } -#if PHP_MAJOR_VERSION >= 7 -static void php_proto_hashtable_descriptor_release(zval* value) { - void* ptr = Z_PTR_P(value); - zend_object* object = *(zend_object**)ptr; - if(--GC_REFCOUNT(object) == 0) { - zend_objects_store_del(object); +bool ObjCache_Get(const void *upb_obj, zval *val) { + zend_ulong k = (zend_ulong)upb_obj; + zend_object *obj = zend_hash_index_find_ptr(&PROTOBUF_G(object_cache), k); + + if (obj) { + GC_ADDREF(obj); + ZVAL_OBJ(val, obj); + return true; + } else { + ZVAL_NULL(val); + return false; } - efree(ptr); } -#endif - -static PHP_RINIT_FUNCTION(protobuf) { - ALLOC_HASHTABLE(upb_def_to_php_obj_map); - zend_hash_init(upb_def_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0); - - ALLOC_HASHTABLE(ce_to_php_obj_map); - zend_hash_init(ce_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0); - generated_pool = NULL; - generated_pool_php = NULL; - internal_generated_pool_php = NULL; +// ----------------------------------------------------------------------------- +// Name Cache. +// ----------------------------------------------------------------------------- - return 0; +void NameMap_AddMessage(const upb_msgdef *m) { + char *k = GetPhpClassname(upb_msgdef_file(m), upb_msgdef_fullname(m)); + zend_hash_str_add_ptr(&PROTOBUF_G(name_msg_cache), k, strlen(k), (void*)m); + free(k); } -static PHP_RSHUTDOWN_FUNCTION(protobuf) { - zend_hash_destroy(upb_def_to_php_obj_map); - FREE_HASHTABLE(upb_def_to_php_obj_map); +void NameMap_AddEnum(const upb_enumdef *e) { + char *k = GetPhpClassname(upb_enumdef_file(e), upb_enumdef_fullname(e)); + zend_hash_str_add_ptr(&PROTOBUF_G(name_enum_cache), k, strlen(k), (void*)e); + free(k); +} - zend_hash_destroy(ce_to_php_obj_map); - FREE_HASHTABLE(ce_to_php_obj_map); +const upb_msgdef *NameMap_GetMessage(zend_class_entry *ce) { + const upb_msgdef *ret = + zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name); -#if PHP_MAJOR_VERSION < 7 - if (generated_pool_php != NULL) { - zval_dtor(generated_pool_php); - FREE_ZVAL(generated_pool_php); - } - if (internal_generated_pool_php != NULL) { - zval_dtor(internal_generated_pool_php); - FREE_ZVAL(internal_generated_pool_php); - } -#else - if (generated_pool_php != NULL) { + if (!ret && ce->create_object) { +#if PHP_VERSION_ID < 80000 zval tmp; - ZVAL_OBJ(&tmp, generated_pool_php); - zval_dtor(&tmp); - } - if (internal_generated_pool_php != NULL) { - zval tmp; - ZVAL_OBJ(&tmp, internal_generated_pool_php); - zval_dtor(&tmp); - } + zval zv; + ZVAL_OBJ(&tmp, ce->create_object(ce)); + zend_call_method_with_0_params(&tmp, ce, NULL, "__construct", &zv); + zval_ptr_dtor(&tmp); +#else + zval zv; + zend_object *tmp = ce->create_object(ce); + zend_call_method_with_0_params(tmp, ce, NULL, "__construct", &zv); + OBJ_RELEASE(tmp); #endif + zval_ptr_dtor(&zv); + ret = zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name); + } - return 0; + return ret; } +const upb_enumdef *NameMap_GetEnum(zend_class_entry *ce) { + const upb_enumdef *ret = + zend_hash_find_ptr(&PROTOBUF_G(name_enum_cache), ce->name); + return ret; +} + +// ----------------------------------------------------------------------------- +// Module init. +// ----------------------------------------------------------------------------- + +zend_function_entry protobuf_functions[] = { + ZEND_FE_END +}; + +static const zend_module_dep protobuf_deps[] = { + ZEND_MOD_OPTIONAL("date") + ZEND_MOD_END +}; + +PHP_INI_BEGIN() +STD_PHP_INI_ENTRY("protobuf.keep_descriptor_pool_after_request", "0", + PHP_INI_SYSTEM, OnUpdateBool, + keep_descriptor_pool_after_request, zend_protobuf_globals, + protobuf_globals) +PHP_INI_END() + static PHP_MINIT_FUNCTION(protobuf) { - descriptor_pool_init(TSRMLS_C); - descriptor_init(TSRMLS_C); - enum_descriptor_init(TSRMLS_C); - enum_value_descriptor_init(TSRMLS_C); - field_descriptor_init(TSRMLS_C); - gpb_type_init(TSRMLS_C); - internal_descriptor_pool_init(TSRMLS_C); - map_field_init(TSRMLS_C); - map_field_iter_init(TSRMLS_C); - message_init(TSRMLS_C); - oneof_descriptor_init(TSRMLS_C); - repeated_field_init(TSRMLS_C); - repeated_field_iter_init(TSRMLS_C); - util_init(TSRMLS_C); - - return 0; + REGISTER_INI_ENTRIES(); + Arena_ModuleInit(); + Array_ModuleInit(); + Convert_ModuleInit(); + Def_ModuleInit(); + Map_ModuleInit(); + Message_ModuleInit(); + return SUCCESS; } static PHP_MSHUTDOWN_FUNCTION(protobuf) { - PEFREE(message_handlers); - PEFREE(repeated_field_handlers); - PEFREE(repeated_field_iter_handlers); - PEFREE(map_field_handlers); - PEFREE(map_field_iter_handlers); - - return 0; + UNREGISTER_INI_ENTRIES(); + return SUCCESS; } + +zend_module_entry protobuf_module_entry = { + STANDARD_MODULE_HEADER_EX, + NULL, + protobuf_deps, + "protobuf", // extension name + protobuf_functions, // function list + PHP_MINIT(protobuf), // process startup + PHP_MSHUTDOWN(protobuf), // process shutdown + PHP_RINIT(protobuf), // request shutdown + PHP_RSHUTDOWN(protobuf), // request shutdown + NULL, // extension info + PHP_PROTOBUF_VERSION, // extension version + PHP_MODULE_GLOBALS(protobuf), // globals descriptor + PHP_GINIT(protobuf), // globals ctor + PHP_GSHUTDOWN(protobuf), // globals dtor + NULL, // post deactivate + STANDARD_MODULE_PROPERTIES_EX +}; + +ZEND_GET_MODULE(protobuf) diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h index f9e9d229863ca..7e63ca095bcfb 100644 --- a/php/ext/google/protobuf/protobuf.h +++ b/php/ext/google/protobuf/protobuf.h @@ -28,886 +28,97 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#ifndef __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__ -#define __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__ +#ifndef PHP_PROTOBUF_H_ +#define PHP_PROTOBUF_H_ #include +#include -// ubp.h has to be placed after php.h. Othwise, php.h will introduce NDEBUG. -#include "upb.h" +#include "php-upb.h" -#define PHP_PROTOBUF_EXTNAME "protobuf" -#define PHP_PROTOBUF_VERSION "3.3.2" +const zval *get_generated_pool(); -#define MAX_LENGTH_OF_INT64 20 -#define SIZEOF_INT64 8 - -// ----------------------------------------------------------------------------- -// PHP7 Wrappers -// ---------------------------------------------------------------------------- - -#if PHP_MAJOR_VERSION < 7 - -#define php_proto_zend_literal const zend_literal* -#define PHP_PROTO_CASE_IS_BOOL IS_BOOL -#define PHP_PROTO_SIZE int -#define PHP_PROTO_LONG long -#define PHP_PROTO_TSRMLS_DC TSRMLS_DC -#define PHP_PROTO_TSRMLS_CC TSRMLS_CC - -// PHP String - -#define PHP_PROTO_ZVAL_STRING(zval_ptr, s, copy) \ - ZVAL_STRING(zval_ptr, s, copy) -#define PHP_PROTO_ZVAL_STRINGL(zval_ptr, s, len, copy) \ - ZVAL_STRINGL(zval_ptr, s, len, copy) -#define PHP_PROTO_RETURN_STRING(s, copy) RETURN_STRING(s, copy) -#define PHP_PROTO_RETURN_STRINGL(s, len, copy) RETURN_STRINGL(s, len, copy) -#define PHP_PROTO_RETVAL_STRINGL(s, len, copy) RETVAL_STRINGL(s, len, copy) -#define php_proto_zend_make_printable_zval(from, to) \ - { \ - int use_copy; \ - zend_make_printable_zval(from, to, &use_copy); \ - } - -// PHP Array - -#define PHP_PROTO_HASH_OF(array) Z_ARRVAL_P(array) - -#define php_proto_zend_hash_index_update_zval(ht, h, pData) \ - zend_hash_index_update(ht, h, &(pData), sizeof(void*), NULL) - -#define php_proto_zend_hash_index_update_mem(ht, h, pData, nDataSize, pDest) \ - zend_hash_index_update(ht, h, pData, nDataSize, pDest) - -#define php_proto_zend_hash_index_find_zval(ht, h, pDest) \ - zend_hash_index_find(ht, h, pDest) - -#define php_proto_zend_hash_index_find_mem(ht, h, pDest) \ - zend_hash_index_find(ht, h, pDest) - -#define php_proto_zend_hash_next_index_insert_zval(ht, pData) \ - zend_hash_next_index_insert(ht, pData, sizeof(void*), NULL) - -#define php_proto_zend_hash_next_index_insert_mem(ht, pData, nDataSize, pDest) \ - zend_hash_next_index_insert(ht, pData, nDataSize, pDest) - -#define php_proto_zend_hash_get_current_data_ex(ht, pDest, pos) \ - zend_hash_get_current_data_ex(ht, pDest, pos) - -// PHP Object - -#define PHP_PROTO_WRAP_OBJECT_START(name) \ - struct name { \ - zend_object std; -#define PHP_PROTO_WRAP_OBJECT_END \ - }; - -#define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \ - void LOWWERNAME##_init(TSRMLS_D) { \ - zend_class_entry class_type; \ - const char* class_name = CLASSNAME; \ - INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \ - LOWWERNAME##_methods); \ - LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \ - LOWWERNAME##_type->create_object = LOWWERNAME##_create; \ - LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers); \ - memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(), \ - sizeof(zend_object_handlers)); -#define PHP_PROTO_INIT_CLASS_END \ - } - -#define PHP_PROTO_OBJECT_CREATE_START(NAME, LOWWERNAME) \ - static zend_object_value LOWWERNAME##_create( \ - zend_class_entry* ce TSRMLS_DC) { \ - PHP_PROTO_ALLOC_CLASS_OBJECT(NAME, ce); \ - zend_object_std_init(&intern->std, ce TSRMLS_CC); \ - object_properties_init(&intern->std, ce); -#define PHP_PROTO_OBJECT_CREATE_END(NAME, LOWWERNAME) \ - PHP_PROTO_FREE_CLASS_OBJECT(NAME, LOWWERNAME##_free, LOWWERNAME##_handlers); \ - } - -#define PHP_PROTO_OBJECT_FREE_START(classname, lowername) \ - void lowername##_free(void* object TSRMLS_DC) { \ - classname* intern = object; -#define PHP_PROTO_OBJECT_FREE_END \ - zend_object_std_dtor(&intern->std TSRMLS_CC); \ - efree(intern); \ - } - -#define PHP_PROTO_OBJECT_DTOR_START(classname, lowername) -#define PHP_PROTO_OBJECT_DTOR_END - -#define CACHED_VALUE zval* -#define CACHED_TO_ZVAL_PTR(VALUE) (VALUE) -#define CACHED_PTR_TO_ZVAL_PTR(VALUE) (*VALUE) -#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (&VALUE) - -#define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \ - ZVAL_OBJ(zval_ptr, class_type->create_object(class_type TSRMLS_CC)); - -#define PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(value) \ - SEPARATE_ZVAL_IF_NOT_REF(value) - -#define PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL EG(uninitialized_zval_ptr) - -#define OBJ_PROP(OBJECT, OFFSET) &((OBJECT)->properties_table[OFFSET]) - -#define php_proto_zval_ptr_dtor(zval_ptr) \ - zval_ptr_dtor(&(zval_ptr)) - -#define PHP_PROTO_ALLOC_CLASS_OBJECT(class_object, class_type) \ - class_object* intern; \ - intern = (class_object*)emalloc(sizeof(class_object)); \ - memset(intern, 0, sizeof(class_object)); - -#define PHP_PROTO_FREE_CLASS_OBJECT(class_object, class_object_free, handler) \ - zend_object_value retval = {0}; \ - retval.handle = zend_objects_store_put( \ - intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, \ - class_object_free, NULL TSRMLS_CC); \ - retval.handlers = handler; \ - return retval; - -#define PHP_PROTO_ALLOC_ARRAY(zval_ptr) \ - ALLOC_HASHTABLE(Z_ARRVAL_P(zval_ptr)); \ - Z_TYPE_P(zval_ptr) = IS_ARRAY; - -#define ZVAL_OBJ(zval_ptr, call_create) \ - Z_TYPE_P(zval_ptr) = IS_OBJECT; \ - Z_OBJVAL_P(zval_ptr) = call_create; - -#define UNBOX(class_name, val) \ - (class_name*)zend_object_store_get_object(val TSRMLS_CC); - -#define UNBOX_HASHTABLE_VALUE(class_name, val) UNBOX(class_name, val) - -#define HASHTABLE_VALUE_DTOR ZVAL_PTR_DTOR - -#define PHP_PROTO_HASHTABLE_VALUE zval* -#define HASHTABLE_VALUE_CE(val) Z_OBJCE_P(val) - -#define CREATE_HASHTABLE_VALUE(OBJ, WRAPPED_OBJ, OBJ_TYPE, OBJ_CLASS_ENTRY) \ - OBJ_TYPE* OBJ; \ - PHP_PROTO_HASHTABLE_VALUE WRAPPED_OBJ; \ - MAKE_STD_ZVAL(WRAPPED_OBJ); \ - ZVAL_OBJ(WRAPPED_OBJ, \ - OBJ_CLASS_ENTRY->create_object(OBJ_CLASS_ENTRY TSRMLS_CC)); \ - OBJ = UNBOX_HASHTABLE_VALUE(OBJ_TYPE, WRAPPED_OBJ); \ - Z_DELREF_P(desc_php); - -#define PHP_PROTO_CE_DECLARE zend_class_entry** -#define PHP_PROTO_CE_UNREF(ce) (*ce) - -#define php_proto_zend_lookup_class(name, name_length, ce) \ - zend_lookup_class(name, name_length, ce TSRMLS_CC) - -#else // PHP_MAJOR_VERSION >= 7 - -#define php_proto_zend_literal void** -#define PHP_PROTO_CASE_IS_BOOL IS_TRUE: case IS_FALSE -#define PHP_PROTO_SIZE size_t -#define PHP_PROTO_LONG zend_long -#define PHP_PROTO_TSRMLS_DC -#define PHP_PROTO_TSRMLS_CC - -// PHP String - -#define PHP_PROTO_ZVAL_STRING(zval_ptr, s, copy) \ - ZVAL_STRING(zval_ptr, s) -#define PHP_PROTO_ZVAL_STRINGL(zval_ptr, s, len, copy) \ - ZVAL_STRINGL(zval_ptr, s, len) -#define PHP_PROTO_RETURN_STRING(s, copy) RETURN_STRING(s) -#define PHP_PROTO_RETURN_STRINGL(s, len, copy) RETURN_STRINGL(s, len) -#define PHP_PROTO_RETVAL_STRINGL(s, len, copy) RETVAL_STRINGL(s, len) -#define php_proto_zend_make_printable_zval(from, to) \ - zend_make_printable_zval(from, to) - -// PHP Array - -#define PHP_PROTO_HASH_OF(array) Z_ARRVAL_P(&array) - -static inline int php_proto_zend_hash_index_update_zval(HashTable* ht, ulong h, - zval* pData) { - void* result = NULL; - result = zend_hash_index_update(ht, h, pData); - return result != NULL ? SUCCESS : FAILURE; -} - -static inline int php_proto_zend_hash_index_update_mem(HashTable* ht, ulong h, - void* pData, uint nDataSize, - void** pDest) { - void* result = NULL; - result = zend_hash_index_update_mem(ht, h, pData, nDataSize); - if (pDest != NULL) *pDest = result; - return result != NULL ? SUCCESS : FAILURE; -} - -static inline int php_proto_zend_hash_index_find_zval(const HashTable* ht, - ulong h, void** pDest) { - zval* result = zend_hash_index_find(ht, h); - if (pDest != NULL) *pDest = result; - return result != NULL ? SUCCESS : FAILURE; -} - -static inline int php_proto_zend_hash_index_find_mem(const HashTable* ht, - ulong h, void** pDest) { - void* result = NULL; - result = zend_hash_index_find_ptr(ht, h); - if (pDest != NULL) *pDest = result; - return result != NULL ? SUCCESS : FAILURE; -} - -static inline int php_proto_zend_hash_next_index_insert_zval(HashTable* ht, - void* pData) { - zval tmp; - ZVAL_OBJ(&tmp, *(zend_object**)pData); - zval* result = zend_hash_next_index_insert(ht, &tmp); - return result != NULL ? SUCCESS : FAILURE; -} - -static inline int php_proto_zend_hash_next_index_insert_mem(HashTable* ht, - void* pData, - uint nDataSize, - void** pDest) { - void* result = NULL; - result = zend_hash_next_index_insert_mem(ht, pData, nDataSize); - if (pDest != NULL) *pDest = result; - return result != NULL ? SUCCESS : FAILURE; -} - -static inline int php_proto_zend_hash_get_current_data_ex(HashTable* ht, - void** pDest, - HashPosition* pos) { - void* result = NULL; - result = zend_hash_get_current_data_ex(ht, pos); - if (pDest != NULL) *pDest = result; - return result != NULL ? SUCCESS : FAILURE; -} - -// PHP Object - -#define PHP_PROTO_WRAP_OBJECT_START(name) struct name { -#define PHP_PROTO_WRAP_OBJECT_END \ - zend_object std; \ - }; - -#define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \ - void LOWWERNAME##_init(TSRMLS_D) { \ - zend_class_entry class_type; \ - const char* class_name = CLASSNAME; \ - INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \ - LOWWERNAME##_methods); \ - LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \ - LOWWERNAME##_type->create_object = LOWWERNAME##_create; \ - LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers); \ - memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(), \ - sizeof(zend_object_handlers)); \ - LOWWERNAME##_handlers->free_obj = LOWWERNAME##_free; \ - LOWWERNAME##_handlers->dtor_obj = LOWWERNAME##_dtor; \ - LOWWERNAME##_handlers->offset = XtOffsetOf(CAMELNAME, std); -#define PHP_PROTO_INIT_CLASS_END \ - } - -#define PHP_PROTO_OBJECT_FREE_START(classname, lowername) \ - void lowername##_free(zend_object* object) { \ - classname* intern = \ - (classname*)((char*)object - XtOffsetOf(classname, std)); -#define PHP_PROTO_OBJECT_FREE_END \ - } - -#define PHP_PROTO_OBJECT_DTOR_START(classname, lowername) \ - void lowername##_dtor(zend_object* object) { \ - classname* intern = \ - (classname*)((char*)object - XtOffsetOf(classname, std)); -#define PHP_PROTO_OBJECT_DTOR_END \ - zend_object_std_dtor(object TSRMLS_CC); \ - } - -#define PHP_PROTO_OBJECT_CREATE_START(NAME, LOWWERNAME) \ - static zend_object* LOWWERNAME##_create(zend_class_entry* ce TSRMLS_DC) { \ - PHP_PROTO_ALLOC_CLASS_OBJECT(NAME, ce); \ - zend_object_std_init(&intern->std, ce TSRMLS_CC); \ - object_properties_init(&intern->std, ce); -#define PHP_PROTO_OBJECT_CREATE_END(NAME, LOWWERNAME) \ - PHP_PROTO_FREE_CLASS_OBJECT(NAME, LOWWERNAME##_free, LOWWERNAME##_handlers); \ - } - -#define CACHED_VALUE zval -#define CACHED_TO_ZVAL_PTR(VALUE) (&VALUE) -#define CACHED_PTR_TO_ZVAL_PTR(VALUE) (VALUE) -#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (VALUE) - -#define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \ - ZVAL_OBJ(zval_ptr, class_type->create_object(class_type)); - -#define PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(value) ; - -#define PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL &EG(uninitialized_zval) - -#define php_proto_zval_ptr_dtor(zval_ptr) \ - zval_ptr_dtor(zval_ptr) - -#define PHP_PROTO_ALLOC_CLASS_OBJECT(class_object, class_type) \ - class_object* intern; \ - int size = sizeof(class_object) + zend_object_properties_size(class_type); \ - intern = ecalloc(1, size); \ - memset(intern, 0, size); - -#define PHP_PROTO_FREE_CLASS_OBJECT(class_object, class_object_free, handler) \ - intern->std.handlers = handler; \ - return &intern->std; - -#define PHP_PROTO_ALLOC_ARRAY(zval_ptr) \ - ZVAL_NEW_ARR(zval_ptr) - -#define UNBOX(class_name, val) \ - (class_name*)((char*)Z_OBJ_P(val) - XtOffsetOf(class_name, std)); - -#define UNBOX_HASHTABLE_VALUE(class_name, val) \ - (class_name*)((char*)val - XtOffsetOf(class_name, std)) - -#define HASHTABLE_VALUE_DTOR php_proto_hashtable_descriptor_release - -#define PHP_PROTO_HASHTABLE_VALUE zend_object* -#define HASHTABLE_VALUE_CE(val) val->ce - -#define CREATE_HASHTABLE_VALUE(OBJ, WRAPPED_OBJ, OBJ_TYPE, OBJ_CLASS_ENTRY) \ - OBJ_TYPE* OBJ; \ - PHP_PROTO_HASHTABLE_VALUE WRAPPED_OBJ; \ - WRAPPED_OBJ = OBJ_CLASS_ENTRY->create_object(OBJ_CLASS_ENTRY); \ - OBJ = UNBOX_HASHTABLE_VALUE(OBJ_TYPE, WRAPPED_OBJ); \ - --GC_REFCOUNT(WRAPPED_OBJ); - -#define PHP_PROTO_CE_DECLARE zend_class_entry* -#define PHP_PROTO_CE_UNREF(ce) (ce) - -static inline int php_proto_zend_lookup_class( - const char* name, int name_length, zend_class_entry** ce TSRMLS_DC) { - zend_string *zstr_name = zend_string_init(name, name_length, 0); - *ce = zend_lookup_class(zstr_name); - zend_string_release(zstr_name); - return *ce != NULL ? SUCCESS : FAILURE; -} - -#endif // PHP_MAJOR_VERSION >= 7 - -// ----------------------------------------------------------------------------- -// Forward Declaration -// ---------------------------------------------------------------------------- - -struct DescriptorPool; -struct Descriptor; -struct EnumDescriptor; -struct EnumValueDescriptor; -struct FieldDescriptor; -struct InternalDescriptorPool; -struct MessageField; -struct MessageHeader; -struct MessageLayout; -struct RepeatedField; -struct RepeatedFieldIter; -struct Map; -struct MapIter; -struct Oneof; - -typedef struct DescriptorPool DescriptorPool; -typedef struct Descriptor Descriptor; -typedef struct EnumDescriptor EnumDescriptor; -typedef struct EnumValueDescriptor EnumValueDescriptor; -typedef struct FieldDescriptor FieldDescriptor; -typedef struct InternalDescriptorPool InternalDescriptorPool; -typedef struct MessageField MessageField; -typedef struct MessageHeader MessageHeader; -typedef struct MessageLayout MessageLayout; -typedef struct RepeatedField RepeatedField; -typedef struct RepeatedFieldIter RepeatedFieldIter; -typedef struct Map Map; -typedef struct MapIter MapIter; -typedef struct Oneof Oneof; - -// ----------------------------------------------------------------------------- -// Globals. -// ----------------------------------------------------------------------------- - -ZEND_BEGIN_MODULE_GLOBALS(protobuf) -ZEND_END_MODULE_GLOBALS(protobuf) - -// Init module and PHP classes. -void descriptor_init(TSRMLS_D); -void enum_descriptor_init(TSRMLS_D); -void descriptor_pool_init(TSRMLS_D); -void internal_descriptor_pool_init(TSRMLS_D); -void field_descriptor_init(TSRMLS_D); -void gpb_type_init(TSRMLS_D); -void map_field_init(TSRMLS_D); -void map_field_iter_init(TSRMLS_D); -void oneof_descriptor_init(TSRMLS_D); -void repeated_field_init(TSRMLS_D); -void repeated_field_iter_init(TSRMLS_D); -void util_init(TSRMLS_D); -void message_init(TSRMLS_D); - -// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor -// instances. -void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value); -PHP_PROTO_HASHTABLE_VALUE get_def_obj(const void* def); - -// Global map from PHP class entries to wrapper Descriptor/EnumDescriptor -// instances. -void add_ce_obj(const void* ce, PHP_PROTO_HASHTABLE_VALUE value); -PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce); -bool class_added(const void* ce); - -extern zend_class_entry* map_field_type; -extern zend_class_entry* repeated_field_type; - -// ----------------------------------------------------------------------------- -// Descriptor. -// ----------------------------------------------------------------------------- - -PHP_PROTO_WRAP_OBJECT_START(DescriptorPool) - InternalDescriptorPool* intern; -PHP_PROTO_WRAP_OBJECT_END - -PHP_METHOD(DescriptorPool, getGeneratedPool); -PHP_METHOD(DescriptorPool, getDescriptorByClassName); -PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName); - -PHP_PROTO_WRAP_OBJECT_START(InternalDescriptorPool) - upb_symtab* symtab; - HashTable* pending_list; -PHP_PROTO_WRAP_OBJECT_END - -PHP_METHOD(InternalDescriptorPool, getGeneratedPool); -PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile); +#if PHP_VERSION_ID < 70300 +#define GC_ADDREF(h) ++GC_REFCOUNT(h) +#define GC_DELREF(h) --GC_REFCOUNT(h) +#endif -// wrapper of generated pool -#if PHP_MAJOR_VERSION < 7 -extern zval* generated_pool_php; -extern zval* internal_generated_pool_php; -void descriptor_pool_free(void* object TSRMLS_DC); -void internal_descriptor_pool_free(void* object TSRMLS_DC); +// Since php 7.4, the write_property() object handler now returns the assigned +// value (after possible type coercions) rather than void. +// https://github.com/php/php-src/blob/PHP-7.4.0/UPGRADING.INTERNALS#L171-L173 +#if PHP_VERSION_ID < 70400 +#define PROTO_RETURN_VAL void #else -extern zend_object *generated_pool_php; -extern zend_object *internal_generated_pool_php; -void descriptor_pool_free(zend_object* object); -void internal_descriptor_pool_free(zend_object* object); +#define PROTO_RETURN_VAL zval* #endif -extern InternalDescriptorPool* generated_pool; // The actual generated pool - -PHP_PROTO_WRAP_OBJECT_START(Descriptor) - const upb_msgdef* msgdef; - MessageLayout* layout; - zend_class_entry* klass; // begins as NULL - const upb_handlers* fill_handlers; - const upb_pbdecodermethod* fill_method; - const upb_json_parsermethod* json_fill_method; - const upb_handlers* pb_serialize_handlers; - const upb_handlers* json_serialize_handlers; - const upb_handlers* json_serialize_handlers_preserve; -PHP_PROTO_WRAP_OBJECT_END - -PHP_METHOD(Descriptor, getClass); -PHP_METHOD(Descriptor, getFullName); -PHP_METHOD(Descriptor, getField); -PHP_METHOD(Descriptor, getFieldCount); -PHP_METHOD(Descriptor, getOneofDecl); -PHP_METHOD(Descriptor, getOneofDeclCount); - -extern zend_class_entry* descriptor_type; - -void descriptor_name_set(Descriptor *desc, const char *name); - -PHP_PROTO_WRAP_OBJECT_START(FieldDescriptor) - const upb_fielddef* fielddef; -PHP_PROTO_WRAP_OBJECT_END - -PHP_METHOD(FieldDescriptor, getName); -PHP_METHOD(FieldDescriptor, getNumber); -PHP_METHOD(FieldDescriptor, getLabel); -PHP_METHOD(FieldDescriptor, getType); -PHP_METHOD(FieldDescriptor, isMap); -PHP_METHOD(FieldDescriptor, getEnumType); -PHP_METHOD(FieldDescriptor, getMessageType); - -extern zend_class_entry* field_descriptor_type; - -PHP_PROTO_WRAP_OBJECT_START(EnumDescriptor) - const upb_enumdef* enumdef; - zend_class_entry* klass; // begins as NULL -PHP_PROTO_WRAP_OBJECT_END - -PHP_METHOD(EnumDescriptor, getValue); -PHP_METHOD(EnumDescriptor, getValueCount); - -extern zend_class_entry* enum_descriptor_type; - -PHP_PROTO_WRAP_OBJECT_START(EnumValueDescriptor) - const char* name; - int32_t number; -PHP_PROTO_WRAP_OBJECT_END - -PHP_METHOD(EnumValueDescriptor, getName); -PHP_METHOD(EnumValueDescriptor, getNumber); - -extern zend_class_entry* enum_value_descriptor_type; - -// ----------------------------------------------------------------------------- -// Message class creation. -// ----------------------------------------------------------------------------- - -void* message_data(MessageHeader* msg); -void custom_data_init(const zend_class_entry* ce, - MessageHeader* msg PHP_PROTO_TSRMLS_DC); - -// Build PHP class for given descriptor. Instead of building from scratch, this -// function modifies existing class which has been partially defined in PHP -// code. -void build_class_from_descriptor( - PHP_PROTO_HASHTABLE_VALUE php_descriptor TSRMLS_DC); - -extern zend_object_handlers* message_handlers; - -// ----------------------------------------------------------------------------- -// Message layout / storage. -// ----------------------------------------------------------------------------- - -/* - * In c extension, each protobuf message is a zval instance. The zval instance - * is like union, which can be used to store int, string, zend_object_value and - * etc. For protobuf message, the zval instance is used to store the - * zend_object_value. - * - * The zend_object_value is composed of handlers and a handle to look up the - * actual stored data. The handlers are pointers to functions, e.g., read, - * write, and etc, to access properties. - * - * The actual data of protobuf messages is stored as MessageHeader in zend - * engine's central repository. Each MessageHeader instance is composed of a - * zend_object, a Descriptor instance and the real message data. - * - * For the reason that PHP's native types may not be large enough to store - * protobuf message's field (e.g., int64), all message's data is stored in - * custom memory layout and is indexed by the Descriptor instance. - * - * The zend_object contains the zend class entry and the properties table. The - * zend class entry contains all information about protobuf message's - * corresponding PHP class. The most useful information is the offset table of - * properties. Because read access to properties requires returning zval - * instance, we need to convert data from the custom layout to zval instance. - * Instead of creating zval instance for every read access, we use the zval - * instances in the properties table in the zend_object as cache. When - * accessing properties, the offset is needed to find the zval property in - * zend_object's properties table. These properties will be updated using the - * data from custom memory layout only when reading these properties. - * - * zval - * |-zend_object_value obj - * |-zend_object_handlers* handlers -> |-read_property_handler - * | |-write_property_handler - * | ++++++++++++++++++++++ - * |-zend_object_handle handle -> + central repository + - * ++++++++++++++++++++++ - * MessageHeader <-----------------| - * |-zend_object std - * | |-class_entry* ce -> class_entry - * | | |-HashTable properties_table (name->offset) - * | |-zval** properties_table <------------------------------| - * | |------> zval* property(cache) - * |-Descriptor* desc (name->offset) - * |-void** data <-----------| - * |-----------------------> void* property(data) - * - */ - -#define MESSAGE_FIELD_NO_CASE ((size_t)-1) - -struct MessageField { - size_t offset; - int cache_index; // Each field except oneof field has a zval cache to avoid - // multiple creation when being accessed. - size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE. -}; - -struct MessageLayout { - const upb_msgdef* msgdef; - MessageField* fields; - size_t size; -}; - -PHP_PROTO_WRAP_OBJECT_START(MessageHeader) - void* data; // Point to the real message data. - // Place needs to be consistent with map_parse_frame_data_t. - Descriptor* descriptor; // Kept alive by self.class.descriptor reference. -PHP_PROTO_WRAP_OBJECT_END - -MessageLayout* create_layout(const upb_msgdef* msgdef); -void layout_init(MessageLayout* layout, void* storage, - zend_object* object PHP_PROTO_TSRMLS_DC); -zval* layout_get(MessageLayout* layout, const void* storage, - const upb_fielddef* field, CACHED_VALUE* cache TSRMLS_DC); -void layout_set(MessageLayout* layout, MessageHeader* header, - const upb_fielddef* field, zval* val TSRMLS_DC); -void layout_merge(MessageLayout* layout, MessageHeader* from, - MessageHeader* to TSRMLS_DC); -const char* layout_get_oneof_case(MessageLayout* layout, const void* storage, - const upb_oneofdef* oneof TSRMLS_DC); -void free_layout(MessageLayout* layout); - -PHP_METHOD(Message, clear); -PHP_METHOD(Message, mergeFrom); -PHP_METHOD(Message, readOneof); -PHP_METHOD(Message, writeOneof); -PHP_METHOD(Message, whichOneof); -PHP_METHOD(Message, __construct); -// ----------------------------------------------------------------------------- -// Encode / Decode. -// ----------------------------------------------------------------------------- - -// Maximum depth allowed during encoding, to avoid stack overflows due to -// cycles. -#define ENCODE_MAX_NESTING 63 - -// Constructs the upb decoder method for parsing messages of this type. -// This is called from the message class creation code. -const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor *desc, - const void *owner); - -PHP_METHOD(Message, serializeToString); -PHP_METHOD(Message, mergeFromString); -PHP_METHOD(Message, serializeToJsonString); -PHP_METHOD(Message, mergeFromJsonString); - -// ----------------------------------------------------------------------------- -// Type check / conversion. -// ----------------------------------------------------------------------------- - -bool protobuf_convert_to_int32(zval* from, int32_t* to); -bool protobuf_convert_to_uint32(zval* from, uint32_t* to); -bool protobuf_convert_to_int64(zval* from, int64_t* to); -bool protobuf_convert_to_uint64(zval* from, uint64_t* to); -bool protobuf_convert_to_float(zval* from, float* to); -bool protobuf_convert_to_double(zval* from, double* to); -bool protobuf_convert_to_bool(zval* from, int8_t* to); -bool protobuf_convert_to_string(zval* from); - -PHP_METHOD(Util, checkInt32); -PHP_METHOD(Util, checkUint32); -PHP_METHOD(Util, checkInt64); -PHP_METHOD(Util, checkUint64); -PHP_METHOD(Util, checkEnum); -PHP_METHOD(Util, checkFloat); -PHP_METHOD(Util, checkDouble); -PHP_METHOD(Util, checkBool); -PHP_METHOD(Util, checkString); -PHP_METHOD(Util, checkBytes); -PHP_METHOD(Util, checkMessage); -PHP_METHOD(Util, checkMapField); -PHP_METHOD(Util, checkRepeatedField); - -// ----------------------------------------------------------------------------- -// Native slot storage abstraction. -// ----------------------------------------------------------------------------- - -#define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t) - -size_t native_slot_size(upb_fieldtype_t type); -bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass, - void* memory, zval* value TSRMLS_DC); -// String/Message is stored differently in array/map from normal message fields. -// So we need to make a special method to handle that. -bool native_slot_set_by_array(upb_fieldtype_t type, - const zend_class_entry* klass, void* memory, - zval* value TSRMLS_DC); -bool native_slot_set_by_map(upb_fieldtype_t type, const zend_class_entry* klass, - void* memory, zval* value TSRMLS_DC); -void native_slot_init(upb_fieldtype_t type, void* memory, CACHED_VALUE* cache); -// For each property, in order to avoid conversion between the zval object and -// the actual data type during parsing/serialization, the containing message -// object use the custom memory layout to store the actual data type for each -// property inside of it. To access a property from php code, the property -// needs to be converted to a zval object. The message object is not responsible -// for providing such a zval object. Instead the caller needs to provide one -// (cache) and update it with the actual data (memory). -void native_slot_get(upb_fieldtype_t type, const void* memory, - CACHED_VALUE* cache TSRMLS_DC); -// String/Message is stored differently in array/map from normal message fields. -// So we need to make a special method to handle that. -void native_slot_get_by_array(upb_fieldtype_t type, const void* memory, - CACHED_VALUE* cache TSRMLS_DC); -void native_slot_get_by_map_key(upb_fieldtype_t type, const void* memory, - int length, CACHED_VALUE* cache TSRMLS_DC); -void native_slot_get_by_map_value(upb_fieldtype_t type, const void* memory, - CACHED_VALUE* cache TSRMLS_DC); -void native_slot_get_default(upb_fieldtype_t type, - CACHED_VALUE* cache TSRMLS_DC); - -// ----------------------------------------------------------------------------- -// Map Field. -// ----------------------------------------------------------------------------- - -extern zend_object_handlers* map_field_handlers; -extern zend_object_handlers* map_field_iter_handlers; - -PHP_PROTO_WRAP_OBJECT_START(Map) - upb_fieldtype_t key_type; - upb_fieldtype_t value_type; - const zend_class_entry* msg_ce; // class entry for value message - upb_strtable table; -PHP_PROTO_WRAP_OBJECT_END - -PHP_PROTO_WRAP_OBJECT_START(MapIter) - Map* self; - upb_strtable_iter it; -PHP_PROTO_WRAP_OBJECT_END - -void map_begin(zval* self, MapIter* iter TSRMLS_DC); -void map_next(MapIter* iter); -bool map_done(MapIter* iter); -const char* map_iter_key(MapIter* iter, int* len); -upb_value map_iter_value(MapIter* iter, int* len); - -// These operate on a map-entry msgdef. -const upb_fielddef* map_entry_key(const upb_msgdef* msgdef); -const upb_fielddef* map_entry_value(const upb_msgdef* msgdef); - -void map_field_create_with_field(const zend_class_entry* ce, - const upb_fielddef* field, - CACHED_VALUE* map_field PHP_PROTO_TSRMLS_DC); -void map_field_create_with_type(const zend_class_entry* ce, - upb_fieldtype_t key_type, - upb_fieldtype_t value_type, - const zend_class_entry* msg_ce, - CACHED_VALUE* map_field PHP_PROTO_TSRMLS_DC); -void* upb_value_memory(upb_value* v); - -#define MAP_KEY_FIELD 1 -#define MAP_VALUE_FIELD 2 - -// These operate on a map field (i.e., a repeated field of submessages whose -// submessage type is a map-entry msgdef). -bool is_map_field(const upb_fielddef* field); -const upb_fielddef* map_field_key(const upb_fielddef* field); -const upb_fielddef* map_field_value(const upb_fielddef* field); - -bool map_index_set(Map *intern, const char* keyval, int length, upb_value v); - -PHP_METHOD(MapField, __construct); -PHP_METHOD(MapField, offsetExists); -PHP_METHOD(MapField, offsetGet); -PHP_METHOD(MapField, offsetSet); -PHP_METHOD(MapField, offsetUnset); -PHP_METHOD(MapField, count); -PHP_METHOD(MapField, getIterator); - -PHP_METHOD(MapFieldIter, rewind); -PHP_METHOD(MapFieldIter, current); -PHP_METHOD(MapFieldIter, key); -PHP_METHOD(MapFieldIter, next); -PHP_METHOD(MapFieldIter, valid); - -// ----------------------------------------------------------------------------- -// Repeated Field. -// ----------------------------------------------------------------------------- - -extern zend_object_handlers* repeated_field_handlers; -extern zend_object_handlers* repeated_field_iter_handlers; - -PHP_PROTO_WRAP_OBJECT_START(RepeatedField) -#if PHP_MAJOR_VERSION < 7 - zval* array; +// Sine php 8.0, the Object Handlers API was changed to receive zend_object* +// instead of zval* and zend_string* instead of zval* for property names. +// https://github.com/php/php-src/blob/php-8.0.0beta1/UPGRADING.INTERNALS#L37-L39 +#if PHP_VERSION_ID < 80000 +#define PROTO_VAL zval +#define PROTO_STR zval +#define PROTO_VAL_P(obj) Z_OBJ_P(obj) +#define PROTO_STRVAL_P(obj) Z_STRVAL_P(obj) +#define PROTO_STRLEN_P(obj) Z_STRLEN_P(obj) #else - zval array; +#define PROTO_VAL zend_object +#define PROTO_STR zend_string +#define PROTO_VAL_P(obj) (void*)(obj) +#define PROTO_STRVAL_P(obj) ZSTR_VAL(obj) +#define PROTO_STRLEN_P(obj) ZSTR_LEN(obj) #endif - upb_fieldtype_t type; - const zend_class_entry* msg_ce; // class entry for containing message - // (for message field only). -PHP_PROTO_WRAP_OBJECT_END - -PHP_PROTO_WRAP_OBJECT_START(RepeatedFieldIter) - RepeatedField* repeated_field; - long position; -PHP_PROTO_WRAP_OBJECT_END - -void repeated_field_create_with_field( - zend_class_entry* ce, const upb_fielddef* field, - CACHED_VALUE* repeated_field PHP_PROTO_TSRMLS_DC); -void repeated_field_create_with_type( - zend_class_entry* ce, upb_fieldtype_t type, const zend_class_entry* msg_ce, - CACHED_VALUE* repeated_field PHP_PROTO_TSRMLS_DC); -// Return the element at the index position from the repeated field. There is -// not restriction on the type of stored elements. -void *repeated_field_index_native(RepeatedField *intern, int index TSRMLS_DC); -// Add the element to the end of the repeated field. There is not restriction on -// the type of stored elements. -void repeated_field_push_native(RepeatedField *intern, void *value); - -PHP_METHOD(RepeatedField, __construct); -PHP_METHOD(RepeatedField, append); -PHP_METHOD(RepeatedField, offsetExists); -PHP_METHOD(RepeatedField, offsetGet); -PHP_METHOD(RepeatedField, offsetSet); -PHP_METHOD(RepeatedField, offsetUnset); -PHP_METHOD(RepeatedField, count); -PHP_METHOD(RepeatedField, getIterator); - -PHP_METHOD(RepeatedFieldIter, rewind); -PHP_METHOD(RepeatedFieldIter, current); -PHP_METHOD(RepeatedFieldIter, key); -PHP_METHOD(RepeatedFieldIter, next); -PHP_METHOD(RepeatedFieldIter, valid); -// ----------------------------------------------------------------------------- -// Oneof Field. -// ----------------------------------------------------------------------------- +ZEND_BEGIN_ARG_INFO(arginfo_void, 0) +ZEND_END_ARG_INFO() -PHP_PROTO_WRAP_OBJECT_START(Oneof) - upb_oneofdef* oneofdef; - int index; // Index of field in oneof. -1 if not set. - char value[NATIVE_SLOT_MAX_SIZE]; -PHP_PROTO_WRAP_OBJECT_END +ZEND_BEGIN_ARG_INFO_EX(arginfo_setter, 0, 0, 1) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() -PHP_METHOD(Oneof, getName); -PHP_METHOD(Oneof, getField); -PHP_METHOD(Oneof, getFieldCount); +#define PHP_PROTOBUF_VERSION "3.15.0" -extern zend_class_entry* oneof_descriptor_type; - -// Oneof case slot value to indicate that no oneof case is set. The value `0` is -// safe because field numbers are used as case identifiers, and no field can -// have a number of 0. -#define ONEOF_CASE_NONE 0 - -// ----------------------------------------------------------------------------- -// Upb. -// ----------------------------------------------------------------------------- - -upb_fieldtype_t to_fieldtype(upb_descriptortype_t type); -const zend_class_entry* field_type_class( - const upb_fielddef* field PHP_PROTO_TSRMLS_DC); - -// ----------------------------------------------------------------------------- -// Utilities. -// ----------------------------------------------------------------------------- - -// Memory management -#define ALLOC(class_name) (class_name*) emalloc(sizeof(class_name)) -#define PEMALLOC(class_name) (class_name*) pemalloc(sizeof(class_name), 1) -#define ALLOC_N(class_name, n) (class_name*) emalloc(sizeof(class_name) * n) -#define FREE(object) efree(object) -#define PEFREE(object) pefree(object, 1) - -// String argument. -#define STR(str) (str), strlen(str) - -// Zend Value -#if PHP_MAJOR_VERSION < 7 -#define Z_OBJ_P(zval_p) \ - ((zend_object*)(EG(objects_store) \ - .object_buckets[Z_OBJ_HANDLE_P(zval_p)] \ - .bucket.obj.object)) +// ptr -> PHP object cache. This is a weak map that caches lazily-created +// wrapper objects around upb types: +// * upb_msg* -> Message +// * upb_array* -> RepeatedField +// * upb_map*, -> MapField +// * upb_msgdef* -> Descriptor +// * upb_enumdef* -> EnumDescriptor +// * zend_class_entry* -> Descriptor +// +// Each wrapped object should add itself to the map when it is constructed, and +// remove itself from the map when it is destroyed. This is how we ensure that +// the map only contains live objects. The map is weak so it does not actually +// take references to the cached objects. +void ObjCache_Add(const void *key, zend_object *php_obj); +void ObjCache_Delete(const void *key); +bool ObjCache_Get(const void *key, zval *val); + +// PHP class name map. This is necessary because the pb_name->php_class_name +// transformation is non-reversible, so when we need to look up a msgdef or +// enumdef by PHP class, we can't turn the class name into a pb_name. +// * php_class_name -> upb_msgdef* +// * php_class_name -> upb_enumdef* +void NameMap_AddMessage(const upb_msgdef *m); +void NameMap_AddEnum(const upb_enumdef *m); +const upb_msgdef *NameMap_GetMessage(zend_class_entry *ce); +const upb_enumdef *NameMap_GetEnum(zend_class_entry *ce); + +// We need our own assert() because PHP takes control of NDEBUG in its headers. +#ifdef PBPHP_ENABLE_ASSERTS +#define PBPHP_ASSERT(x) \ + do { \ + if (!(x)) { \ + fprintf(stderr, "Assertion failure at %s:%d %s", __FILE__, __LINE__, \ + #x); \ + abort(); \ + } \ + } while (false) +#else +#define PBPHP_ASSERT(x) \ + do { \ + } while (false && (x)) #endif -#endif // __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__ +#endif // PHP_PROTOBUF_H_ diff --git a/php/ext/google/protobuf/storage.c b/php/ext/google/protobuf/storage.c deleted file mode 100644 index 4830e15f233e2..0000000000000 --- a/php/ext/google/protobuf/storage.c +++ /dev/null @@ -1,1109 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include -#include -#include - -#include "utf8.h" - -// ----------------------------------------------------------------------------- -// Native slot storage. -// ----------------------------------------------------------------------------- - -#define DEREF(memory, type) *(type*)(memory) - -size_t native_slot_size(upb_fieldtype_t type) { - switch (type) { - case UPB_TYPE_FLOAT: return 4; - case UPB_TYPE_DOUBLE: return 8; - case UPB_TYPE_BOOL: return 1; - case UPB_TYPE_STRING: return sizeof(void*); - case UPB_TYPE_BYTES: return sizeof(void*); - case UPB_TYPE_MESSAGE: return sizeof(void*); - case UPB_TYPE_ENUM: return 4; - case UPB_TYPE_INT32: return 4; - case UPB_TYPE_INT64: return 8; - case UPB_TYPE_UINT32: return 4; - case UPB_TYPE_UINT64: return 8; - default: return 0; - } -} - -static bool native_slot_is_default(upb_fieldtype_t type, const void* memory) { - switch (type) { -#define CASE_TYPE(upb_type, c_type) \ - case UPB_TYPE_##upb_type: { \ - return DEREF(memory, c_type) == 0; \ - } - CASE_TYPE(INT32, int32_t ) - CASE_TYPE(UINT32, uint32_t) - CASE_TYPE(ENUM, int32_t ) - CASE_TYPE(INT64, int64_t ) - CASE_TYPE(UINT64, uint64_t) - CASE_TYPE(FLOAT, float ) - CASE_TYPE(DOUBLE, double ) - CASE_TYPE(BOOL, int8_t ) - -#undef CASE_TYPE - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - return Z_STRLEN_P(CACHED_PTR_TO_ZVAL_PTR(DEREF(memory, CACHED_VALUE*))) == - 0; - case UPB_TYPE_MESSAGE: - return Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(DEREF(memory, CACHED_VALUE*))) == - IS_NULL; - default: return false; - } -} - -bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass, - void* memory, zval* value PHP_PROTO_TSRMLS_DC) { - switch (type) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - if (!protobuf_convert_to_string(value)) { - return false; - } - if (type == UPB_TYPE_STRING && - !is_structurally_valid_utf8(Z_STRVAL_P(value), Z_STRLEN_P(value))) { - zend_error(E_USER_ERROR, "Given string is not UTF8 encoded."); - return false; - } - - zval* cached_zval = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory); - if (EXPECTED(cached_zval != NULL)) { -#if PHP_MAJOR_VERSION < 7 - REPLACE_ZVAL_VALUE((zval**)memory, value, 1); -#else - zend_assign_to_variable(cached_zval, value, IS_CV); -#endif - } - break; - } - case UPB_TYPE_MESSAGE: { - if (Z_TYPE_P(value) != IS_OBJECT && Z_TYPE_P(value) != IS_NULL) { - zend_error(E_USER_ERROR, "Given value is not message."); - return false; - } - if (Z_TYPE_P(value) == IS_OBJECT && klass != Z_OBJCE_P(value)) { - zend_error(E_USER_ERROR, "Given message does not have correct class."); - return false; - } - - zval* property_ptr = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory); - if (EXPECTED(property_ptr != value)) { - php_proto_zval_ptr_dtor(property_ptr); - } - -#if PHP_MAJOR_VERSION < 7 - DEREF(memory, zval*) = value; - Z_ADDREF_P(value); -#else - ZVAL_ZVAL(property_ptr, value, 1, 0); -#endif - break; - } - -#define CASE_TYPE(upb_type, type, c_type, php_type) \ - case UPB_TYPE_##upb_type: { \ - c_type type##_value; \ - if (protobuf_convert_to_##type(value, &type##_value)) { \ - DEREF(memory, c_type) = type##_value; \ - } \ - break; \ - } - CASE_TYPE(INT32, int32, int32_t, LONG) - CASE_TYPE(UINT32, uint32, uint32_t, LONG) - CASE_TYPE(ENUM, int32, int32_t, LONG) - CASE_TYPE(INT64, int64, int64_t, LONG) - CASE_TYPE(UINT64, uint64, uint64_t, LONG) - CASE_TYPE(FLOAT, float, float, DOUBLE) - CASE_TYPE(DOUBLE, double, double, DOUBLE) - CASE_TYPE(BOOL, bool, int8_t, BOOL) - -#undef CASE_TYPE - - default: - break; - } - - return true; -} - -bool native_slot_set_by_array(upb_fieldtype_t type, - const zend_class_entry* klass, void* memory, - zval* value TSRMLS_DC) { - switch (type) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - if (!protobuf_convert_to_string(value)) { - return false; - } - if (type == UPB_TYPE_STRING && - !is_structurally_valid_utf8(Z_STRVAL_P(value), Z_STRLEN_P(value))) { - zend_error(E_USER_ERROR, "Given string is not UTF8 encoded."); - return false; - } - - // Handles repeated/map string field. Memory provided by - // RepeatedField/Map is not initialized. -#if PHP_MAJOR_VERSION < 7 - MAKE_STD_ZVAL(DEREF(memory, zval*)); - PHP_PROTO_ZVAL_STRINGL(DEREF(memory, zval*), Z_STRVAL_P(value), - Z_STRLEN_P(value), 1); -#else - *(zend_string**)memory = zend_string_dup(Z_STR_P(value), 0); -#endif - break; - } - case UPB_TYPE_MESSAGE: { - if (Z_TYPE_P(value) != IS_OBJECT) { - zend_error(E_USER_ERROR, "Given value is not message."); - return false; - } - if (Z_TYPE_P(value) == IS_OBJECT && klass != Z_OBJCE_P(value)) { - zend_error(E_USER_ERROR, "Given message does not have correct class."); - return false; - } -#if PHP_MAJOR_VERSION < 7 - if (EXPECTED(DEREF(memory, zval*) != value)) { - DEREF(memory, zval*) = value; - Z_ADDREF_P(value); - } -#else - DEREF(memory, zval*) = value; - ++GC_REFCOUNT(Z_OBJ_P(value)); -#endif - break; - } - default: - return native_slot_set(type, klass, memory, value TSRMLS_CC); - } - return true; -} - -bool native_slot_set_by_map(upb_fieldtype_t type, const zend_class_entry* klass, - void* memory, zval* value TSRMLS_DC) { - switch (type) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - if (!protobuf_convert_to_string(value)) { - return false; - } - if (type == UPB_TYPE_STRING && - !is_structurally_valid_utf8(Z_STRVAL_P(value), Z_STRLEN_P(value))) { - zend_error(E_USER_ERROR, "Given string is not UTF8 encoded."); - return false; - } - - // Handles repeated/map string field. Memory provided by - // RepeatedField/Map is not initialized. -#if PHP_MAJOR_VERSION < 7 - MAKE_STD_ZVAL(DEREF(memory, zval*)); - PHP_PROTO_ZVAL_STRINGL(DEREF(memory, zval*), Z_STRVAL_P(value), - Z_STRLEN_P(value), 1); -#else - *(zend_string**)memory = zend_string_dup(Z_STR_P(value), 0); -#endif - break; - } - case UPB_TYPE_MESSAGE: { - if (Z_TYPE_P(value) != IS_OBJECT) { - zend_error(E_USER_ERROR, "Given value is not message."); - return false; - } - if (Z_TYPE_P(value) == IS_OBJECT && klass != Z_OBJCE_P(value)) { - zend_error(E_USER_ERROR, "Given message does not have correct class."); - return false; - } -#if PHP_MAJOR_VERSION < 7 - if (EXPECTED(DEREF(memory, zval*) != value)) { - DEREF(memory, zval*) = value; - Z_ADDREF_P(value); - } -#else - DEREF(memory, zend_object*) = Z_OBJ_P(value); - ++GC_REFCOUNT(Z_OBJ_P(value)); -#endif - break; - } - default: - return native_slot_set(type, klass, memory, value TSRMLS_CC); - } - return true; -} - -void native_slot_init(upb_fieldtype_t type, void* memory, CACHED_VALUE* cache) { - zval* tmp = NULL; - switch (type) { - case UPB_TYPE_FLOAT: - DEREF(memory, float) = 0.0; - break; - case UPB_TYPE_DOUBLE: - DEREF(memory, double) = 0.0; - break; - case UPB_TYPE_BOOL: - DEREF(memory, int8_t) = 0; - break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - DEREF(memory, CACHED_VALUE*) = cache; - break; - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - DEREF(memory, int32_t) = 0; - break; - case UPB_TYPE_INT64: - DEREF(memory, int64_t) = 0; - break; - case UPB_TYPE_UINT32: - DEREF(memory, uint32_t) = 0; - break; - case UPB_TYPE_UINT64: - DEREF(memory, uint64_t) = 0; - break; - default: - break; - } -} - -void native_slot_get(upb_fieldtype_t type, const void* memory, - CACHED_VALUE* cache TSRMLS_DC) { - switch (type) { -#define CASE(upb_type, php_type, c_type) \ - case UPB_TYPE_##upb_type: \ - PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); \ - ZVAL_##php_type(CACHED_PTR_TO_ZVAL_PTR(cache), DEREF(memory, c_type)); \ - return; - - CASE(FLOAT, DOUBLE, float) - CASE(DOUBLE, DOUBLE, double) - CASE(BOOL, BOOL, int8_t) - CASE(INT32, LONG, int32_t) - CASE(ENUM, LONG, uint32_t) - -#undef CASE - -#if SIZEOF_LONG == 4 -#define CASE(upb_type, c_type) \ - case UPB_TYPE_##upb_type: { \ - PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); \ - char buffer[MAX_LENGTH_OF_INT64]; \ - sprintf(buffer, "%lld", DEREF(memory, c_type)); \ - PHP_PROTO_ZVAL_STRING(CACHED_PTR_TO_ZVAL_PTR(cache), buffer, 1); \ - return; \ - } -#else -#define CASE(upb_type, c_type) \ - case UPB_TYPE_##upb_type: { \ - PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); \ - ZVAL_LONG(CACHED_PTR_TO_ZVAL_PTR(cache), DEREF(memory, c_type)); \ - return; \ - } -#endif -CASE(UINT64, uint64_t) -CASE(INT64, int64_t) -#undef CASE - - case UPB_TYPE_UINT32: { - // Prepend bit-1 for negative numbers, so that uint32 value will be - // consistent on both 32-bit and 64-bit architectures. - PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); - int value = DEREF(memory, int32_t); - if (sizeof(int) == 8) { - value |= (-((value >> 31) & 0x1) & 0xFFFFFFFF00000000); - } - ZVAL_LONG(CACHED_PTR_TO_ZVAL_PTR(cache), value); - return; - } - - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - // For optional string/bytes/message fields, the cache is owned by the - // containing message and should have been updated during - // setting/decoding. However, oneof accessor call this function by - // providing the return value directly, which is not the same as the cache - // value. - zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory); - if (CACHED_PTR_TO_ZVAL_PTR(cache) != value) { - PHP_PROTO_ZVAL_STRINGL(CACHED_PTR_TO_ZVAL_PTR(cache), Z_STRVAL_P(value), - Z_STRLEN_P(value), 1); - } - break; - } - case UPB_TYPE_MESSAGE: { - // Same as above for string/bytes fields. - zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory); - if (CACHED_PTR_TO_ZVAL_PTR(cache) != value) { - ZVAL_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cache), value, 1, 0); - } - return; - } - default: - return; - } -} - -void native_slot_get_by_array(upb_fieldtype_t type, const void* memory, - CACHED_VALUE* cache TSRMLS_DC) { - switch (type) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { -#if PHP_MAJOR_VERSION < 7 - zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory); - if (EXPECTED(CACHED_PTR_TO_ZVAL_PTR(cache) != value)) { - PHP_PROTO_ZVAL_STRINGL(CACHED_PTR_TO_ZVAL_PTR(cache), - Z_STRVAL_P(value), Z_STRLEN_P(value), 1); - } -#else - ZVAL_NEW_STR(cache, zend_string_dup(*(zend_string**)memory, 0)); -#endif - return; - } - case UPB_TYPE_MESSAGE: { -#if PHP_MAJOR_VERSION < 7 - zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory); - if (EXPECTED(CACHED_PTR_TO_ZVAL_PTR(cache) != value)) { - ZVAL_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cache), value, 1, 0); - } -#else - ZVAL_COPY(CACHED_PTR_TO_ZVAL_PTR(cache), memory); -#endif - return; - } - default: - native_slot_get(type, memory, cache TSRMLS_CC); - } -} - -void native_slot_get_by_map_key(upb_fieldtype_t type, const void* memory, - int length, CACHED_VALUE* cache TSRMLS_DC) { - switch (type) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - PHP_PROTO_ZVAL_STRINGL(CACHED_PTR_TO_ZVAL_PTR(cache), memory, length, 1); - return; - } - default: - native_slot_get(type, memory, cache TSRMLS_CC); - } -} - -void native_slot_get_by_map_value(upb_fieldtype_t type, const void* memory, - CACHED_VALUE* cache TSRMLS_DC) { - switch (type) { - case UPB_TYPE_MESSAGE: { -#if PHP_MAJOR_VERSION < 7 - zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory); - if (EXPECTED(CACHED_PTR_TO_ZVAL_PTR(cache) != value)) { - ZVAL_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cache), value, 1, 0); - } -#else - ++GC_REFCOUNT(*(zend_object**)memory); - ZVAL_OBJ(cache, *(zend_object**)memory); -#endif - return; - } - default: - native_slot_get_by_array(type, memory, cache TSRMLS_CC); - } -} - -void native_slot_get_default(upb_fieldtype_t type, - CACHED_VALUE* cache TSRMLS_DC) { - switch (type) { -#define CASE(upb_type, php_type) \ - case UPB_TYPE_##upb_type: \ - PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); \ - ZVAL_##php_type(CACHED_PTR_TO_ZVAL_PTR(cache), 0); \ - return; - - CASE(FLOAT, DOUBLE) - CASE(DOUBLE, DOUBLE) - CASE(BOOL, BOOL) - CASE(INT32, LONG) - CASE(UINT32, LONG) - CASE(ENUM, LONG) - -#undef CASE - -#if SIZEOF_LONG == 4 -#define CASE(upb_type) \ - case UPB_TYPE_##upb_type: { \ - PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); \ - PHP_PROTO_ZVAL_STRING(CACHED_PTR_TO_ZVAL_PTR(cache), "0", 1); \ - return; \ - } -#else -#define CASE(upb_type) \ - case UPB_TYPE_##upb_type: { \ - PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); \ - ZVAL_LONG(CACHED_PTR_TO_ZVAL_PTR(cache), 0); \ - return; \ - } -#endif -CASE(UINT64) -CASE(INT64) -#undef CASE - - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); - PHP_PROTO_ZVAL_STRINGL(CACHED_PTR_TO_ZVAL_PTR(cache), "", 0, 1); - break; - } - case UPB_TYPE_MESSAGE: { - PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); - ZVAL_NULL(CACHED_PTR_TO_ZVAL_PTR(cache)); - return; - } - default: - return; - } -} - -// ----------------------------------------------------------------------------- -// Map field utilities. -// ---------------------------------------------------------------------------- - -const upb_msgdef* tryget_map_entry_msgdef(const upb_fielddef* field) { - const upb_msgdef* subdef; - if (upb_fielddef_label(field) != UPB_LABEL_REPEATED || - upb_fielddef_type(field) != UPB_TYPE_MESSAGE) { - return NULL; - } - subdef = upb_fielddef_msgsubdef(field); - return upb_msgdef_mapentry(subdef) ? subdef : NULL; -} - -const upb_msgdef* map_entry_msgdef(const upb_fielddef* field) { - const upb_msgdef* subdef = tryget_map_entry_msgdef(field); - assert(subdef); - return subdef; -} - -bool is_map_field(const upb_fielddef* field) { - return tryget_map_entry_msgdef(field) != NULL; -} - -const upb_fielddef* map_field_key(const upb_fielddef* field) { - const upb_msgdef* subdef = map_entry_msgdef(field); - return map_entry_key(subdef); -} - -const upb_fielddef* map_field_value(const upb_fielddef* field) { - const upb_msgdef* subdef = map_entry_msgdef(field); - return map_entry_value(subdef); -} - -const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) { - const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD); - assert(key_field != NULL); - return key_field; -} - -const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) { - const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD); - assert(value_field != NULL); - return value_field; -} - -const zend_class_entry* field_type_class( - const upb_fielddef* field PHP_PROTO_TSRMLS_DC) { - if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) { - Descriptor* desc = UNBOX_HASHTABLE_VALUE( - Descriptor, get_def_obj(upb_fielddef_subdef(field))); - return desc->klass; - } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) { - EnumDescriptor* desc = UNBOX_HASHTABLE_VALUE( - EnumDescriptor, get_def_obj(upb_fielddef_subdef(field))); - return desc->klass; - } - return NULL; -} - -// ----------------------------------------------------------------------------- -// Memory layout management. -// ----------------------------------------------------------------------------- - -static size_t align_up_to(size_t offset, size_t granularity) { - // Granularity must be a power of two. - return (offset + granularity - 1) & ~(granularity - 1); -} - -static void* slot_memory(MessageLayout* layout, const void* storage, - const upb_fielddef* field) { - return ((uint8_t*)storage) + layout->fields[upb_fielddef_index(field)].offset; -} - -static uint32_t* slot_oneof_case(MessageLayout* layout, const void* storage, - const upb_fielddef* field) { - return (uint32_t*)(((uint8_t*)storage) + - layout->fields[upb_fielddef_index(field)].case_offset); -} - -static int slot_property_cache(MessageLayout* layout, const void* storage, - const upb_fielddef* field) { - return layout->fields[upb_fielddef_index(field)].cache_index; -} - -MessageLayout* create_layout(const upb_msgdef* msgdef) { - MessageLayout* layout = ALLOC(MessageLayout); - int nfields = upb_msgdef_numfields(msgdef); - upb_msg_field_iter it; - upb_msg_oneof_iter oit; - size_t off = 0; - int i = 0; - TSRMLS_FETCH(); - Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msgdef)); - - layout->fields = ALLOC_N(MessageField, nfields); - - for (upb_msg_field_begin(&it, msgdef); !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* field = upb_msg_iter_field(&it); - size_t field_size; - - if (upb_fielddef_containingoneof(field)) { - // Oneofs are handled separately below. - continue; - } - - // Allocate |field_size| bytes for this field in the layout. - field_size = 0; - if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - field_size = sizeof(zval*); - } else { - field_size = native_slot_size(upb_fielddef_type(field)); - } - - // Align current offset up to | size | granularity. - off = align_up_to(off, field_size); - layout->fields[upb_fielddef_index(field)].offset = off; - layout->fields[upb_fielddef_index(field)].case_offset = - MESSAGE_FIELD_NO_CASE; - - const char* fieldname = upb_fielddef_name(field); - -#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0) - zend_class_entry* old_scope = EG(scope); - EG(scope) = desc->klass; -#else - zend_class_entry* old_scope = EG(fake_scope); - EG(fake_scope) = desc->klass; -#endif - -#if PHP_MAJOR_VERSION < 7 - zval member; - ZVAL_STRINGL(&member, fieldname, strlen(fieldname), 0); - zend_property_info* property_info = - zend_get_property_info(desc->klass, &member, true TSRMLS_CC); -#else - zend_string* member = zend_string_init(fieldname, strlen(fieldname), 1); - zend_property_info* property_info = - zend_get_property_info(desc->klass, member, true); - zend_string_release(member); -#endif - -#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0) - EG(scope) = old_scope; -#else - EG(fake_scope) = old_scope; -#endif - - layout->fields[upb_fielddef_index(field)].cache_index = - property_info->offset; - off += field_size; - } - - // Handle oneofs now -- we iterate over oneofs specifically and allocate only - // one slot per oneof. - // - // We assign all value slots first, then pack the 'case' fields at the end, - // since in the common case (modern 64-bit platform) these are 8 bytes and 4 - // bytes respectively and we want to avoid alignment overhead. - // - // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value - // space for oneof cases is conceptually as wide as field tag numbers. In - // practice, it's unlikely that a oneof would have more than e.g. 256 or 64K - // members (8 or 16 bits respectively), so conceivably we could assign - // consecutive case numbers and then pick a smaller oneof case slot size, but - // the complexity to implement this indirection is probably not worthwhile. - for (upb_msg_oneof_begin(&oit, msgdef); !upb_msg_oneof_done(&oit); - upb_msg_oneof_next(&oit)) { - const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit); - upb_oneof_iter fit; - - // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between - // all fields. - size_t field_size = NATIVE_SLOT_MAX_SIZE; - // Align the offset . - off = align_up_to( off, field_size); - // Assign all fields in the oneof this same offset. - const char* oneofname = upb_oneofdef_name(oneof); - for (upb_oneof_begin(&fit, oneof); !upb_oneof_done(&fit); - upb_oneof_next(&fit)) { - const upb_fielddef* field = upb_oneof_iter_field(&fit); - layout->fields[upb_fielddef_index(field)].offset = off; - -#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0) - zend_class_entry* old_scope = EG(scope); - EG(scope) = desc->klass; -#else - zend_class_entry* old_scope = EG(fake_scope); - EG(fake_scope) = desc->klass; -#endif - -#if PHP_MAJOR_VERSION < 7 - zval member; - ZVAL_STRINGL(&member, oneofname, strlen(oneofname), 0); - zend_property_info* property_info = - zend_get_property_info(desc->klass, &member, true TSRMLS_CC); -#else - zend_string* member = zend_string_init(oneofname, strlen(oneofname), 1); - zend_property_info* property_info = - zend_get_property_info(desc->klass, member, true); - zend_string_release(member); -#endif - -#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0) - EG(scope) = old_scope; -#else - EG(fake_scope) = old_scope; -#endif - - layout->fields[upb_fielddef_index(field)].cache_index = - property_info->offset; - } - i++; - off += field_size; - } - - // Now the case offset. - for (upb_msg_oneof_begin(&oit, msgdef); !upb_msg_oneof_done(&oit); - upb_msg_oneof_next(&oit)) { - const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit); - upb_oneof_iter fit; - - size_t field_size = sizeof(uint32_t); - // Align the offset . - off = (off + field_size - 1) & ~(field_size - 1); - // Assign all fields in the oneof this same offset. - for (upb_oneof_begin(&fit, oneof); !upb_oneof_done(&fit); - upb_oneof_next(&fit)) { - const upb_fielddef* field = upb_oneof_iter_field(&fit); - layout->fields[upb_fielddef_index(field)].case_offset = off; - } - off += field_size; - } - - layout->size = off; - - layout->msgdef = msgdef; - upb_msgdef_ref(layout->msgdef, &layout->msgdef); - - return layout; -} - -void free_layout(MessageLayout* layout) { - FREE(layout->fields); - upb_msgdef_unref(layout->msgdef, &layout->msgdef); - FREE(layout); -} - -void layout_init(MessageLayout* layout, void* storage, - zend_object* object PHP_PROTO_TSRMLS_DC) { - int i; - upb_msg_field_iter it; - for (upb_msg_field_begin(&it, layout->msgdef), i = 0; !upb_msg_field_done(&it); - upb_msg_field_next(&it), i++) { - const upb_fielddef* field = upb_msg_iter_field(&it); - void* memory = slot_memory(layout, storage, field); - uint32_t* oneof_case = slot_oneof_case(layout, storage, field); - int cache_index = slot_property_cache(layout, storage, field); - CACHED_VALUE* property_ptr = OBJ_PROP(object, cache_index); - - if (upb_fielddef_containingoneof(field)) { - memset(memory, 0, NATIVE_SLOT_MAX_SIZE); - *oneof_case = ONEOF_CASE_NONE; - } else if (is_map_field(field)) { - zval_ptr_dtor(property_ptr); -#if PHP_MAJOR_VERSION < 7 - MAKE_STD_ZVAL(*property_ptr); -#endif - map_field_create_with_field(map_field_type, field, - property_ptr PHP_PROTO_TSRMLS_CC); - DEREF(memory, CACHED_VALUE*) = property_ptr; - } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - zval_ptr_dtor(property_ptr); -#if PHP_MAJOR_VERSION < 7 - MAKE_STD_ZVAL(*property_ptr); -#endif - repeated_field_create_with_field(repeated_field_type, field, - property_ptr PHP_PROTO_TSRMLS_CC); - DEREF(memory, CACHED_VALUE*) = property_ptr; - } else { - native_slot_init(upb_fielddef_type(field), memory, property_ptr); - } - } -} - -// For non-singular fields, the related memory needs to point to the actual -// zval in properties table first. -static void* value_memory(const upb_fielddef* field, void* memory) { - switch (upb_fielddef_type(field)) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - memory = DEREF(memory, CACHED_VALUE*); - break; - default: - // No operation - break; - } - return memory; -} - -zval* layout_get(MessageLayout* layout, const void* storage, - const upb_fielddef* field, CACHED_VALUE* cache TSRMLS_DC) { - void* memory = slot_memory(layout, storage, field); - uint32_t* oneof_case = slot_oneof_case(layout, storage, field); - - if (upb_fielddef_containingoneof(field)) { - if (*oneof_case != upb_fielddef_number(field)) { - native_slot_get_default(upb_fielddef_type(field), cache TSRMLS_CC); - } else { - native_slot_get(upb_fielddef_type(field), value_memory(field, memory), - cache TSRMLS_CC); - } - return CACHED_PTR_TO_ZVAL_PTR(cache); - } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - return CACHED_PTR_TO_ZVAL_PTR(cache); - } else { - native_slot_get(upb_fielddef_type(field), value_memory(field, memory), - cache TSRMLS_CC); - return CACHED_PTR_TO_ZVAL_PTR(cache); - } -} - -void layout_set(MessageLayout* layout, MessageHeader* header, - const upb_fielddef* field, zval* val TSRMLS_DC) { - void* storage = message_data(header); - void* memory = slot_memory(layout, storage, field); - uint32_t* oneof_case = slot_oneof_case(layout, storage, field); - - if (upb_fielddef_containingoneof(field)) { - upb_fieldtype_t type = upb_fielddef_type(field); - zend_class_entry *ce = NULL; - - // For non-singular fields, the related memory needs to point to the actual - // zval in properties table first. - switch (type) { - case UPB_TYPE_MESSAGE: { - const upb_msgdef* msg = upb_fielddef_msgsubdef(field); - Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg)); - ce = desc->klass; - // Intentionally fall through. - } - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - int property_cache_index = - header->descriptor->layout->fields[upb_fielddef_index(field)] - .cache_index; - DEREF(memory, CACHED_VALUE*) = - OBJ_PROP(&header->std, property_cache_index); - memory = DEREF(memory, CACHED_VALUE*); - break; - } - default: - break; - } - - native_slot_set(type, ce, memory, val TSRMLS_CC); - *oneof_case = upb_fielddef_number(field); - } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - // Works for both repeated and map fields - memory = DEREF(memory, void**); - zval* property_ptr = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory); - - if (EXPECTED(property_ptr != val)) { -#if PHP_MAJOR_VERSION < 7 - REPLACE_ZVAL_VALUE((zval**)memory, val, 1); -#else - php_proto_zval_ptr_dtor(property_ptr); - ZVAL_ZVAL(property_ptr, val, 1, 0); -#endif - } - } else { - upb_fieldtype_t type = upb_fielddef_type(field); - zend_class_entry *ce = NULL; - if (type == UPB_TYPE_MESSAGE) { - const upb_msgdef* msg = upb_fielddef_msgsubdef(field); - Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg)); - ce = desc->klass; - } - native_slot_set(type, ce, value_memory(field, memory), val TSRMLS_CC); - } -} - -static void native_slot_merge(const upb_fielddef* field, const void* from_memory, - void* to_memory PHP_PROTO_TSRMLS_DC) { - upb_fieldtype_t type = upb_fielddef_type(field); - zend_class_entry* ce = NULL; - if (!native_slot_is_default(type, from_memory)) { - switch (type) { -#define CASE_TYPE(upb_type, c_type) \ - case UPB_TYPE_##upb_type: { \ - DEREF(to_memory, c_type) = DEREF(from_memory, c_type); \ - break; \ - } - CASE_TYPE(INT32, int32_t) - CASE_TYPE(UINT32, uint32_t) - CASE_TYPE(ENUM, int32_t) - CASE_TYPE(INT64, int64_t) - CASE_TYPE(UINT64, uint64_t) - CASE_TYPE(FLOAT, float) - CASE_TYPE(DOUBLE, double) - CASE_TYPE(BOOL, int8_t) - -#undef CASE_TYPE - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - native_slot_set(type, NULL, value_memory(field, to_memory), - CACHED_PTR_TO_ZVAL_PTR(DEREF( - from_memory, CACHED_VALUE*)) PHP_PROTO_TSRMLS_CC); - break; - case UPB_TYPE_MESSAGE: { - const upb_msgdef* msg = upb_fielddef_msgsubdef(field); - Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg)); - ce = desc->klass; - if (native_slot_is_default(type, to_memory)) { -#if PHP_MAJOR_VERSION < 7 - SEPARATE_ZVAL_IF_NOT_REF((zval**)value_memory(field, to_memory)); -#endif - CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR( - CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*)), ce); - MessageHeader* submsg = - UNBOX(MessageHeader, - CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*))); - custom_data_init(ce, submsg PHP_PROTO_TSRMLS_CC); - } - - MessageHeader* sub_from = - UNBOX(MessageHeader, - CACHED_PTR_TO_ZVAL_PTR(DEREF(from_memory, CACHED_VALUE*))); - MessageHeader* sub_to = - UNBOX(MessageHeader, - CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*))); - - layout_merge(desc->layout, sub_from, sub_to PHP_PROTO_TSRMLS_CC); - break; - } - } - } -} - -static void native_slot_merge_by_array(const upb_fielddef* field, const void* from_memory, - void* to_memory PHP_PROTO_TSRMLS_DC) { - upb_fieldtype_t type = upb_fielddef_type(field); - switch (type) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { -#if PHP_MAJOR_VERSION < 7 - MAKE_STD_ZVAL(DEREF(to_memory, zval*)); - PHP_PROTO_ZVAL_STRINGL(DEREF(to_memory, zval*), - Z_STRVAL_P(*(zval**)from_memory), - Z_STRLEN_P(*(zval**)from_memory), 1); -#else - DEREF(to_memory, zend_string*) = - zend_string_dup(*(zend_string**)from_memory, 0); -#endif - break; - } - case UPB_TYPE_MESSAGE: { - const upb_msgdef* msg = upb_fielddef_msgsubdef(field); - Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg)); - zend_class_entry* ce = desc->klass; -#if PHP_MAJOR_VERSION < 7 - MAKE_STD_ZVAL(DEREF(to_memory, zval*)); - CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(DEREF(to_memory, zval*), ce); -#else - DEREF(to_memory, zend_object*) = ce->create_object(ce TSRMLS_CC); -#endif - MessageHeader* sub_from = UNBOX_HASHTABLE_VALUE( - MessageHeader, DEREF(from_memory, PHP_PROTO_HASHTABLE_VALUE)); - MessageHeader* sub_to = UNBOX_HASHTABLE_VALUE( - MessageHeader, DEREF(to_memory, PHP_PROTO_HASHTABLE_VALUE)); - custom_data_init(ce, sub_to PHP_PROTO_TSRMLS_CC); - - layout_merge(desc->layout, sub_from, sub_to PHP_PROTO_TSRMLS_CC); - break; - } - default: - native_slot_merge(field, from_memory, to_memory PHP_PROTO_TSRMLS_CC); - break; - } -} - -void layout_merge(MessageLayout* layout, MessageHeader* from, - MessageHeader* to PHP_PROTO_TSRMLS_DC) { - int i, j; - upb_msg_field_iter it; - - for (upb_msg_field_begin(&it, layout->msgdef), i = 0; !upb_msg_field_done(&it); - upb_msg_field_next(&it), i++) { - const upb_fielddef* field = upb_msg_iter_field(&it); - - void* to_memory = slot_memory(layout, message_data(to), field); - void* from_memory = slot_memory(layout, message_data(from), field); - - if (upb_fielddef_containingoneof(field)) { - uint32_t oneof_case_offset = - layout->fields[upb_fielddef_index(field)].case_offset; - // For a oneof, check that this field is actually present -- skip all the - // below if not. - if (DEREF((message_data(from) + oneof_case_offset), uint32_t) != - upb_fielddef_number(field)) { - continue; - } - uint32_t* from_oneof_case = slot_oneof_case(layout, message_data(from), field); - uint32_t* to_oneof_case = slot_oneof_case(layout, message_data(to), field); - - // For non-singular fields, the related memory needs to point to the - // actual zval in properties table first. - switch (upb_fielddef_type(field)) { - case UPB_TYPE_MESSAGE: - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - int property_cache_index = - layout->fields[upb_fielddef_index(field)].cache_index; - DEREF(to_memory, CACHED_VALUE*) = - OBJ_PROP(&to->std, property_cache_index); - break; - } - default: - break; - } - - *to_oneof_case = *from_oneof_case; - - // Otherwise, fall through to the appropriate singular-field handler - // below. - } - - if (is_map_field(field)) { - int size, key_length, value_length; - MapIter map_it; - - zval* to_map_php = - CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*)); - zval* from_map_php = - CACHED_PTR_TO_ZVAL_PTR(DEREF(from_memory, CACHED_VALUE*)); - Map* to_map = UNBOX(Map, to_map_php); - Map* from_map = UNBOX(Map, from_map_php); - - size = upb_strtable_count(&from_map->table); - if (size == 0) continue; - - const upb_msgdef *mapentry_def = upb_fielddef_msgsubdef(field); - const upb_fielddef *value_field = upb_msgdef_itof(mapentry_def, 2); - - for (map_begin(from_map_php, &map_it TSRMLS_CC); !map_done(&map_it); - map_next(&map_it)) { - const char* key = map_iter_key(&map_it, &key_length); - upb_value from_value = map_iter_value(&map_it, &value_length); - upb_value to_value; - void* from_mem = upb_value_memory(&from_value); - void* to_mem = upb_value_memory(&to_value); - memset(to_mem, 0, native_slot_size(to_map->value_type)); - - native_slot_merge_by_array(value_field, from_mem, - to_mem PHP_PROTO_TSRMLS_CC); - - map_index_set(to_map, key, key_length, to_value); - } - - } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - zval* to_array_php = CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*)); - zval* from_array_php = CACHED_PTR_TO_ZVAL_PTR(DEREF(from_memory, CACHED_VALUE*)); - RepeatedField* to_array = UNBOX(RepeatedField, to_array_php); - RepeatedField* from_array = UNBOX(RepeatedField, from_array_php); - - int size = zend_hash_num_elements(PHP_PROTO_HASH_OF(from_array->array)); - if (size > 0) { - for (j = 0; j < size; j++) { - void* from_memory = NULL; - void* to_memory = - ALLOC_N(char, native_slot_size(upb_fielddef_type(field))); - memset(to_memory, 0, native_slot_size(upb_fielddef_type(field))); - - if (to_array->type == UPB_TYPE_MESSAGE) { - php_proto_zend_hash_index_find_zval( - PHP_PROTO_HASH_OF(from_array->array), j, (void**)&from_memory); -#if PHP_MAJOR_VERSION >= 7 - from_memory = &Z_OBJ_P((zval*)from_memory); -#endif - } else { - php_proto_zend_hash_index_find_mem( - PHP_PROTO_HASH_OF(from_array->array), j, (void**)&from_memory); - } - - native_slot_merge_by_array(field, from_memory, - to_memory PHP_PROTO_TSRMLS_CC); - repeated_field_push_native(to_array, to_memory); - FREE(to_memory); - } - } - } else { - native_slot_merge(field, from_memory, to_memory PHP_PROTO_TSRMLS_CC); - } - } -} - -const char* layout_get_oneof_case(MessageLayout* layout, const void* storage, - const upb_oneofdef* oneof TSRMLS_DC) { - upb_oneof_iter i; - const upb_fielddef* first_field; - - // Oneof is guaranteed to have at least one field. Get the first field. - for(upb_oneof_begin(&i, oneof); !upb_oneof_done(&i); upb_oneof_next(&i)) { - first_field = upb_oneof_iter_field(&i); - break; - } - - uint32_t* oneof_case = slot_oneof_case(layout, storage, first_field); - if (*oneof_case == 0) { - return ""; - } - const upb_fielddef* field = upb_oneofdef_itof(oneof, *oneof_case); - return upb_fielddef_name(field); -} diff --git a/php/ext/google/protobuf/type_check.c b/php/ext/google/protobuf/type_check.c deleted file mode 100644 index fada8d6a79f6a..0000000000000 --- a/php/ext/google/protobuf/type_check.c +++ /dev/null @@ -1,567 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include - -#include "protobuf.h" -#include "utf8.h" - -static zend_class_entry* util_type; -static const char int64_min_digits[] = "9223372036854775808"; - -ZEND_BEGIN_ARG_INFO_EX(arg_check_optional, 0, 0, 1) - ZEND_ARG_INFO(1, val) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arg_check_message, 0, 0, 2) - ZEND_ARG_INFO(1, val) - ZEND_ARG_INFO(0, klass) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arg_check_repeated, 0, 0, 2) - ZEND_ARG_INFO(1, val) - ZEND_ARG_INFO(0, type) - ZEND_ARG_INFO(0, klass) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arg_check_map, 0, 0, 3) - ZEND_ARG_INFO(1, val) - ZEND_ARG_INFO(0, key_type) - ZEND_ARG_INFO(0, value_type) - ZEND_ARG_INFO(0, klass) -ZEND_END_ARG_INFO() - -static zend_function_entry util_methods[] = { - PHP_ME(Util, checkInt32, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkUint32, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkInt64, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkUint64, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkEnum, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkFloat, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkDouble, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkBool, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkString, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkBytes, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkMessage, arg_check_message, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkMapField, arg_check_map, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkRepeatedField, arg_check_repeated, - ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - ZEND_FE_END -}; - -void util_init(TSRMLS_D) { - zend_class_entry class_type; - INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBUtil", - util_methods); - util_type = zend_register_internal_class(&class_type TSRMLS_CC); -} - -// ----------------------------------------------------------------------------- -// Type checking/conversion. -// ----------------------------------------------------------------------------- - -// This is modified from is_numeric_string in zend_operators.h. The behavior of -// this function is the same as is_numeric_string, except that this takes -// int64_t as input instead of long. -static zend_uchar convert_numeric_string( - const char *str, int length, int64_t *lval, double *dval) { - const char *ptr; - int base = 10, digits = 0, dp_or_e = 0; - double local_dval = 0.0; - zend_uchar type; - - if (length == 0) { - return IS_NULL; - } - - while (*str == ' ' || *str == '\t' || *str == '\n' || - *str == '\r' || *str == '\v' || *str == '\f') { - str++; - length--; - } - ptr = str; - - if (*ptr == '-' || *ptr == '+') { - ptr++; - } - - if (ZEND_IS_DIGIT(*ptr)) { - // Handle hex numbers - // str is used instead of ptr to disallow signs and keep old behavior. - if (length > 2 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) { - base = 16; - ptr += 2; - } - - // Skip any leading 0s. - while (*ptr == '0') { - ptr++; - } - - // Count the number of digits. If a decimal point/exponent is found, - // it's a double. Otherwise, if there's a dval or no need to check for - // a full match, stop when there are too many digits for a int64 */ - for (type = IS_LONG; - !(digits >= MAX_LENGTH_OF_INT64 && dval); - digits++, ptr++) { -check_digits: - if (ZEND_IS_DIGIT(*ptr) || (base == 16 && ZEND_IS_XDIGIT(*ptr))) { - continue; - } else if (base == 10) { - if (*ptr == '.' && dp_or_e < 1) { - goto process_double; - } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) { - const char *e = ptr + 1; - - if (*e == '-' || *e == '+') { - ptr = e++; - } - if (ZEND_IS_DIGIT(*e)) { - goto process_double; - } - } - } - break; - } - - if (base == 10) { - if (digits >= MAX_LENGTH_OF_INT64) { - dp_or_e = -1; - goto process_double; - } - } else if (!(digits < SIZEOF_INT64 * 2 || - (digits == SIZEOF_INT64 * 2 && ptr[-digits] <= '7'))) { - if (dval) { - local_dval = zend_hex_strtod(str, &ptr); - } - type = IS_DOUBLE; - } - } else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) { -process_double: - type = IS_DOUBLE; - - // If there's a dval, do the conversion; else continue checking - // the digits if we need to check for a full match. - if (dval) { - local_dval = zend_strtod(str, &ptr); - } else if (dp_or_e != -1) { - dp_or_e = (*ptr++ == '.') ? 1 : 2; - goto check_digits; - } - } else { - return IS_NULL; - } - if (ptr != str + length) { - zend_error(E_NOTICE, "A non well formed numeric value encountered"); - return 0; - } - - if (type == IS_LONG) { - if (digits == MAX_LENGTH_OF_INT64 - 1) { - int cmp = strcmp(&ptr[-digits], int64_min_digits); - - if (!(cmp < 0 || (cmp == 0 && *str == '-'))) { - if (dval) { - *dval = zend_strtod(str, NULL); - } - - return IS_DOUBLE; - } - } - if (lval) { - *lval = strtoll(str, NULL, base); - } - return IS_LONG; - } else { - if (dval) { - *dval = local_dval; - } - return IS_DOUBLE; - } -} - -#define CONVERT_TO_INTEGER(type) \ - static bool convert_int64_to_##type(int64_t val, type##_t* type##_value) { \ - *type##_value = (type##_t)val; \ - return true; \ - } \ - \ - static bool convert_double_to_##type(double val, type##_t* type##_value) { \ - *type##_value = (type##_t)zend_dval_to_lval(val); \ - return true; \ - } \ - \ - static bool convert_string_to_##type(const char* val, int len, \ - type##_t* type##_value) { \ - int64_t lval; \ - double dval; \ - \ - switch (convert_numeric_string(val, len, &lval, &dval)) { \ - case IS_DOUBLE: { \ - return convert_double_to_##type(dval, type##_value); \ - } \ - case IS_LONG: { \ - return convert_int64_to_##type(lval, type##_value); \ - } \ - default: \ - zend_error(E_USER_ERROR, \ - "Given string value cannot be converted to integer."); \ - return false; \ - } \ - } \ - \ - bool protobuf_convert_to_##type(zval* from, type##_t* to) { \ - switch (Z_TYPE_P(from)) { \ - case IS_LONG: { \ - return convert_int64_to_##type(Z_LVAL_P(from), to); \ - } \ - case IS_DOUBLE: { \ - return convert_double_to_##type(Z_DVAL_P(from), to); \ - } \ - case IS_STRING: { \ - return convert_string_to_##type(Z_STRVAL_P(from), Z_STRLEN_P(from), \ - to); \ - } \ - default: { \ - zend_error(E_USER_ERROR, \ - "Given value cannot be converted to integer."); \ - return false; \ - } \ - } \ - return false; \ - } - -CONVERT_TO_INTEGER(int32); -CONVERT_TO_INTEGER(uint32); -CONVERT_TO_INTEGER(int64); -CONVERT_TO_INTEGER(uint64); - -#undef CONVERT_TO_INTEGER - -#define CONVERT_TO_FLOAT(type) \ - static bool convert_int64_to_##type(int64_t val, type* type##_value) { \ - *type##_value = (type)val; \ - return true; \ - } \ - \ - static bool convert_double_to_##type(double val, type* type##_value) { \ - *type##_value = (type)val; \ - return true; \ - } \ - \ - static bool convert_string_to_##type(const char* val, int len, \ - type* type##_value) { \ - int64_t lval; \ - double dval; \ - \ - switch (convert_numeric_string(val, len, &lval, &dval)) { \ - case IS_DOUBLE: { \ - *type##_value = (type)dval; \ - return true; \ - } \ - case IS_LONG: { \ - *type##_value = (type)lval; \ - return true; \ - } \ - default: \ - zend_error(E_USER_ERROR, \ - "Given string value cannot be converted to integer."); \ - return false; \ - } \ - } \ - \ - bool protobuf_convert_to_##type(zval* from, type* to) { \ - switch (Z_TYPE_P(from)) { \ - case IS_LONG: { \ - return convert_int64_to_##type(Z_LVAL_P(from), to); \ - } \ - case IS_DOUBLE: { \ - return convert_double_to_##type(Z_DVAL_P(from), to); \ - } \ - case IS_STRING: { \ - return convert_string_to_##type(Z_STRVAL_P(from), Z_STRLEN_P(from), \ - to); \ - } \ - default: { \ - zend_error(E_USER_ERROR, \ - "Given value cannot be converted to integer."); \ - return false; \ - } \ - } \ - return false; \ - } - -CONVERT_TO_FLOAT(float); -CONVERT_TO_FLOAT(double); - -#undef CONVERT_TO_FLOAT - -bool protobuf_convert_to_bool(zval* from, int8_t* to) { - switch (Z_TYPE_P(from)) { -#if PHP_MAJOR_VERSION < 7 - case IS_BOOL: - *to = (int8_t)Z_BVAL_P(from); - break; -#else - case IS_TRUE: - *to = 1; - break; - case IS_FALSE: - *to = 0; - break; -#endif - case IS_LONG: - *to = (int8_t)(Z_LVAL_P(from) != 0); - break; - case IS_DOUBLE: - *to = (int8_t)(Z_LVAL_P(from) != 0); - break; - case IS_STRING: { - char* strval = Z_STRVAL_P(from); - - if (Z_STRLEN_P(from) == 0 || - (Z_STRLEN_P(from) == 1 && Z_STRVAL_P(from)[0] == '0')) { - *to = 0; - } else { - *to = 1; - } - } break; - default: { - zend_error(E_USER_ERROR, "Given value cannot be converted to bool."); - return false; - } - } - return true; -} - -bool protobuf_convert_to_string(zval* from) { - switch (Z_TYPE_P(from)) { - case IS_STRING: { - return true; - } -#if PHP_MAJOR_VERSION < 7 - case IS_BOOL: -#else - case IS_TRUE: - case IS_FALSE: -#endif - case IS_LONG: - case IS_DOUBLE: { - zval tmp; - php_proto_zend_make_printable_zval(from, &tmp); - ZVAL_COPY_VALUE(from, &tmp); - return true; - } - default: - zend_error(E_USER_ERROR, "Given value cannot be converted to string."); - return false; - } -} - -// ----------------------------------------------------------------------------- -// PHP Functions. -// ----------------------------------------------------------------------------- - -// The implementation of type checking for primitive fields is empty. This is -// because type checking is done when direct assigning message fields (e.g., -// foo->a = 1). Functions defined here are place holders in generated code for -// pure PHP implementation (c extension and pure PHP share the same generated -// code). -#define PHP_TYPE_CHECK(type) \ - PHP_METHOD(Util, check##type) {} - -PHP_TYPE_CHECK(Int32) -PHP_TYPE_CHECK(Uint32) -PHP_TYPE_CHECK(Int64) -PHP_TYPE_CHECK(Uint64) -PHP_TYPE_CHECK(Enum) -PHP_TYPE_CHECK(Float) -PHP_TYPE_CHECK(Double) -PHP_TYPE_CHECK(Bool) -PHP_TYPE_CHECK(String) -PHP_TYPE_CHECK(Bytes) - -#undef PHP_TYPE_CHECK - -PHP_METHOD(Util, checkMessage) { - zval* val; - zend_class_entry* klass = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!C", &val, &klass) == - FAILURE) { - return; - } - if (val == NULL) { - RETURN_NULL(); - } - if (!instanceof_function(Z_OBJCE_P(val), klass TSRMLS_CC)) { - zend_error(E_USER_ERROR, "Given value is not an instance of %s.", - klass->name); - return; - } - RETURN_ZVAL(val, 1, 0); -} - -PHP_METHOD(Util, checkRepeatedField) { - zval* val; - PHP_PROTO_LONG type; - const zend_class_entry* klass = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl|C", &val, &type, - &klass) == FAILURE) { - return; - } - -#if PHP_MAJOR_VERSION >= 7 - if (Z_ISREF_P(val)) { - ZVAL_DEREF(val); - } -#endif - - if (Z_TYPE_P(val) == IS_ARRAY) { - HashTable* table = HASH_OF(val); - HashPosition pointer; - void* memory; - -#if PHP_MAJOR_VERSION < 7 - zval* repeated_field; - MAKE_STD_ZVAL(repeated_field); -#else - zval repeated_field; -#endif - - repeated_field_create_with_type(repeated_field_type, to_fieldtype(type), - klass, &repeated_field TSRMLS_CC); - - for (zend_hash_internal_pointer_reset_ex(table, &pointer); - php_proto_zend_hash_get_current_data_ex(table, (void**)&memory, - &pointer) == SUCCESS; - zend_hash_move_forward_ex(table, &pointer)) { - repeated_field_handlers->write_dimension( - CACHED_TO_ZVAL_PTR(repeated_field), NULL, - CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory) TSRMLS_CC); - } - - Z_DELREF_P(CACHED_TO_ZVAL_PTR(repeated_field)); - RETURN_ZVAL(CACHED_TO_ZVAL_PTR(repeated_field), 1, 0); - - } else if (Z_TYPE_P(val) == IS_OBJECT) { - if (!instanceof_function(Z_OBJCE_P(val), repeated_field_type TSRMLS_CC)) { - zend_error(E_USER_ERROR, "Given value is not an instance of %s.", - repeated_field_type->name); - return; - } - RepeatedField* intern = UNBOX(RepeatedField, val); - if (to_fieldtype(type) != intern->type) { - zend_error(E_USER_ERROR, "Incorrect repeated field type."); - return; - } - if (klass != NULL && intern->msg_ce != klass) { - zend_error(E_USER_ERROR, - "Expect a repeated field of %s, but %s is given.", klass->name, - intern->msg_ce->name); - return; - } - RETURN_ZVAL(val, 1, 0); - } else { - zend_error(E_USER_ERROR, "Incorrect repeated field type."); - return; - } - -} - -PHP_METHOD(Util, checkMapField) { - zval* val; - PHP_PROTO_LONG key_type, value_type; - const zend_class_entry* klass = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zll|C", &val, &key_type, - &value_type, &klass) == FAILURE) { - return; - } - -#if PHP_MAJOR_VERSION >= 7 - if (Z_ISREF_P(val)) { - ZVAL_DEREF(val); - } -#endif - - if (Z_TYPE_P(val) == IS_ARRAY) { - HashTable* table = Z_ARRVAL_P(val); - HashPosition pointer; - zval key; - void* value; - -#if PHP_MAJOR_VERSION < 7 - zval* map_field; - MAKE_STD_ZVAL(map_field); -#else - zval map_field; -#endif - - map_field_create_with_type(map_field_type, to_fieldtype(key_type), - to_fieldtype(value_type), klass, - &map_field TSRMLS_CC); - - for (zend_hash_internal_pointer_reset_ex(table, &pointer); - php_proto_zend_hash_get_current_data_ex(table, (void**)&value, - &pointer) == SUCCESS; - zend_hash_move_forward_ex(table, &pointer)) { - zend_hash_get_current_key_zval_ex(table, &key, &pointer); - map_field_handlers->write_dimension( - CACHED_TO_ZVAL_PTR(map_field), &key, - CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value) TSRMLS_CC); - } - - Z_DELREF_P(CACHED_TO_ZVAL_PTR(map_field)); - RETURN_ZVAL(CACHED_TO_ZVAL_PTR(map_field), 1, 0); - } else if (Z_TYPE_P(val) == IS_OBJECT) { - if (!instanceof_function(Z_OBJCE_P(val), map_field_type TSRMLS_CC)) { - zend_error(E_USER_ERROR, "Given value is not an instance of %s.", - map_field_type->name); - return; - } - Map* intern = UNBOX(Map, val); - if (to_fieldtype(key_type) != intern->key_type) { - zend_error(E_USER_ERROR, "Incorrect map field key type."); - return; - } - if (to_fieldtype(value_type) != intern->value_type) { - zend_error(E_USER_ERROR, "Incorrect map field value type."); - return; - } - if (klass != NULL && intern->msg_ce != klass) { - zend_error(E_USER_ERROR, "Expect a map field of %s, but %s is given.", - klass->name, intern->msg_ce->name); - return; - } - RETURN_ZVAL(val, 1, 0); - } else { - zend_error(E_USER_ERROR, "Incorrect map field type."); - return; - } -} diff --git a/php/ext/google/protobuf/upb.c b/php/ext/google/protobuf/upb.c deleted file mode 100644 index d701dcbaaf6dd..0000000000000 --- a/php/ext/google/protobuf/upb.c +++ /dev/null @@ -1,13853 +0,0 @@ -// Amalgamated source file -#include "upb.h" - - -#include -#include -#include - -typedef struct { - size_t len; - char str[1]; /* Null-terminated string data follows. */ -} str_t; - -static str_t *newstr(const char *data, size_t len) { - str_t *ret = upb_gmalloc(sizeof(*ret) + len); - if (!ret) return NULL; - ret->len = len; - memcpy(ret->str, data, len); - ret->str[len] = '\0'; - return ret; -} - -static void freestr(str_t *s) { upb_gfree(s); } - -/* isalpha() etc. from are locale-dependent, which we don't want. */ -static bool upb_isbetween(char c, char low, char high) { - return c >= low && c <= high; -} - -static bool upb_isletter(char c) { - return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_'; -} - -static bool upb_isalphanum(char c) { - return upb_isletter(c) || upb_isbetween(c, '0', '9'); -} - -static bool upb_isident(const char *str, size_t len, bool full, upb_status *s) { - bool start = true; - size_t i; - for (i = 0; i < len; i++) { - char c = str[i]; - if (c == '.') { - if (start || !full) { - upb_status_seterrf(s, "invalid name: unexpected '.' (%s)", str); - return false; - } - start = true; - } else if (start) { - if (!upb_isletter(c)) { - upb_status_seterrf( - s, "invalid name: path components must start with a letter (%s)", - str); - return false; - } - start = false; - } else { - if (!upb_isalphanum(c)) { - upb_status_seterrf(s, "invalid name: non-alphanumeric character (%s)", - str); - return false; - } - } - } - return !start; -} - -static bool upb_isoneof(const upb_refcounted *def) { - return def->vtbl == &upb_oneofdef_vtbl; -} - -static bool upb_isfield(const upb_refcounted *def) { - return def->vtbl == &upb_fielddef_vtbl; -} - -static const upb_oneofdef *upb_trygetoneof(const upb_refcounted *def) { - return upb_isoneof(def) ? (const upb_oneofdef*)def : NULL; -} - -static const upb_fielddef *upb_trygetfield(const upb_refcounted *def) { - return upb_isfield(def) ? (const upb_fielddef*)def : NULL; -} - - -/* upb_def ********************************************************************/ - -upb_deftype_t upb_def_type(const upb_def *d) { return d->type; } - -const char *upb_def_fullname(const upb_def *d) { return d->fullname; } - -const char *upb_def_name(const upb_def *d) { - const char *p; - - if (d->fullname == NULL) { - return NULL; - } else if ((p = strrchr(d->fullname, '.')) == NULL) { - /* No '.' in the name, return the full string. */ - return d->fullname; - } else { - /* Return one past the last '.'. */ - return p + 1; - } -} - -bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s) { - UPB_ASSERT(!upb_def_isfrozen(def)); - if (!upb_isident(fullname, strlen(fullname), true, s)) { - return false; - } - - fullname = upb_gstrdup(fullname); - if (!fullname) { - upb_upberr_setoom(s); - return false; - } - - upb_gfree((void*)def->fullname); - def->fullname = fullname; - return true; -} - -const upb_filedef *upb_def_file(const upb_def *d) { return d->file; } - -static bool upb_def_init(upb_def *def, upb_deftype_t type, - const struct upb_refcounted_vtbl *vtbl, - const void *owner) { - if (!upb_refcounted_init(upb_def_upcast_mutable(def), vtbl, owner)) return false; - def->type = type; - def->fullname = NULL; - def->came_from_user = false; - def->file = NULL; - return true; -} - -static void upb_def_uninit(upb_def *def) { - upb_gfree((void*)def->fullname); -} - -static const char *msgdef_name(const upb_msgdef *m) { - const char *name = upb_def_fullname(upb_msgdef_upcast(m)); - return name ? name : "(anonymous)"; -} - -static bool upb_validate_field(upb_fielddef *f, upb_status *s) { - if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { - upb_status_seterrmsg(s, "fielddef must have name and number set"); - return false; - } - - if (!f->type_is_set_) { - upb_status_seterrmsg(s, "fielddef type was not initialized"); - return false; - } - - if (upb_fielddef_lazy(f) && - upb_fielddef_descriptortype(f) != UPB_DESCRIPTOR_TYPE_MESSAGE) { - upb_status_seterrmsg(s, - "only length-delimited submessage fields may be lazy"); - return false; - } - - if (upb_fielddef_hassubdef(f)) { - const upb_def *subdef; - - if (f->subdef_is_symbolic) { - upb_status_seterrf(s, "field '%s.%s' has not been resolved", - msgdef_name(f->msg.def), upb_fielddef_name(f)); - return false; - } - - subdef = upb_fielddef_subdef(f); - if (subdef == NULL) { - upb_status_seterrf(s, "field %s.%s is missing required subdef", - msgdef_name(f->msg.def), upb_fielddef_name(f)); - return false; - } - - if (!upb_def_isfrozen(subdef) && !subdef->came_from_user) { - upb_status_seterrf(s, - "subdef of field %s.%s is not frozen or being frozen", - msgdef_name(f->msg.def), upb_fielddef_name(f)); - return false; - } - } - - if (upb_fielddef_type(f) == UPB_TYPE_ENUM) { - bool has_default_name = upb_fielddef_enumhasdefaultstr(f); - bool has_default_number = upb_fielddef_enumhasdefaultint32(f); - - /* Previously verified by upb_validate_enumdef(). */ - UPB_ASSERT(upb_enumdef_numvals(upb_fielddef_enumsubdef(f)) > 0); - - /* We've already validated that we have an associated enumdef and that it - * has at least one member, so at least one of these should be true. - * Because if the user didn't set anything, we'll pick up the enum's - * default, but if the user *did* set something we should at least pick up - * the one they set (int32 or string). */ - UPB_ASSERT(has_default_name || has_default_number); - - if (!has_default_name) { - upb_status_seterrf(s, - "enum default for field %s.%s (%d) is not in the enum", - msgdef_name(f->msg.def), upb_fielddef_name(f), - upb_fielddef_defaultint32(f)); - return false; - } - - if (!has_default_number) { - upb_status_seterrf(s, - "enum default for field %s.%s (%s) is not in the enum", - msgdef_name(f->msg.def), upb_fielddef_name(f), - upb_fielddef_defaultstr(f, NULL)); - return false; - } - - /* Lift the effective numeric default into the field's default slot, in case - * we were only getting it "by reference" from the enumdef. */ - upb_fielddef_setdefaultint32(f, upb_fielddef_defaultint32(f)); - } - - /* Ensure that MapEntry submessages only appear as repeated fields, not - * optional/required (singular) fields. */ - if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE && - upb_fielddef_msgsubdef(f) != NULL) { - const upb_msgdef *subdef = upb_fielddef_msgsubdef(f); - if (upb_msgdef_mapentry(subdef) && !upb_fielddef_isseq(f)) { - upb_status_seterrf(s, - "Field %s refers to mapentry message but is not " - "a repeated field", - upb_fielddef_name(f) ? upb_fielddef_name(f) : - "(unnamed)"); - return false; - } - } - - return true; -} - -static bool upb_validate_enumdef(const upb_enumdef *e, upb_status *s) { - if (upb_enumdef_numvals(e) == 0) { - upb_status_seterrf(s, "enum %s has no members (must have at least one)", - upb_enumdef_fullname(e)); - return false; - } - - return true; -} - -/* All submessage fields are lower than all other fields. - * Secondly, fields are increasing in order. */ -uint32_t field_rank(const upb_fielddef *f) { - uint32_t ret = upb_fielddef_number(f); - const uint32_t high_bit = 1 << 30; - UPB_ASSERT(ret < high_bit); - if (!upb_fielddef_issubmsg(f)) - ret |= high_bit; - return ret; -} - -int cmp_fields(const void *p1, const void *p2) { - const upb_fielddef *f1 = *(upb_fielddef*const*)p1; - const upb_fielddef *f2 = *(upb_fielddef*const*)p2; - return field_rank(f1) - field_rank(f2); -} - -static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { - /* Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the - * lowest indexes, but we do not publicly guarantee this. */ - upb_msg_field_iter j; - upb_msg_oneof_iter k; - int i; - uint32_t selector; - int n = upb_msgdef_numfields(m); - upb_fielddef **fields; - - if (n == 0) { - m->selector_count = UPB_STATIC_SELECTOR_COUNT; - m->submsg_field_count = 0; - return true; - } - - fields = upb_gmalloc(n * sizeof(*fields)); - if (!fields) { - upb_upberr_setoom(s); - return false; - } - - m->submsg_field_count = 0; - for(i = 0, upb_msg_field_begin(&j, m); - !upb_msg_field_done(&j); - upb_msg_field_next(&j), i++) { - upb_fielddef *f = upb_msg_iter_field(&j); - UPB_ASSERT(f->msg.def == m); - if (!upb_validate_field(f, s)) { - upb_gfree(fields); - return false; - } - if (upb_fielddef_issubmsg(f)) { - m->submsg_field_count++; - } - fields[i] = f; - } - - qsort(fields, n, sizeof(*fields), cmp_fields); - - selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count; - for (i = 0; i < n; i++) { - upb_fielddef *f = fields[i]; - f->index_ = i; - f->selector_base = selector + upb_handlers_selectorbaseoffset(f); - selector += upb_handlers_selectorcount(f); - } - m->selector_count = selector; - -#ifndef NDEBUG - { - /* Verify that all selectors for the message are distinct. */ -#define TRY(type) \ - if (upb_handlers_getselector(f, type, &sel)) upb_inttable_insert(&t, sel, v); - - upb_inttable t; - upb_value v; - upb_selector_t sel; - - upb_inttable_init(&t, UPB_CTYPE_BOOL); - v = upb_value_bool(true); - upb_inttable_insert(&t, UPB_STARTMSG_SELECTOR, v); - upb_inttable_insert(&t, UPB_ENDMSG_SELECTOR, v); - for(upb_msg_field_begin(&j, m); - !upb_msg_field_done(&j); - upb_msg_field_next(&j)) { - upb_fielddef *f = upb_msg_iter_field(&j); - /* These calls will assert-fail in upb_table if the value already - * exists. */ - TRY(UPB_HANDLER_INT32); - TRY(UPB_HANDLER_INT64) - TRY(UPB_HANDLER_UINT32) - TRY(UPB_HANDLER_UINT64) - TRY(UPB_HANDLER_FLOAT) - TRY(UPB_HANDLER_DOUBLE) - TRY(UPB_HANDLER_BOOL) - TRY(UPB_HANDLER_STARTSTR) - TRY(UPB_HANDLER_STRING) - TRY(UPB_HANDLER_ENDSTR) - TRY(UPB_HANDLER_STARTSUBMSG) - TRY(UPB_HANDLER_ENDSUBMSG) - TRY(UPB_HANDLER_STARTSEQ) - TRY(UPB_HANDLER_ENDSEQ) - } - upb_inttable_uninit(&t); - } -#undef TRY -#endif - - for(upb_msg_oneof_begin(&k, m), i = 0; - !upb_msg_oneof_done(&k); - upb_msg_oneof_next(&k), i++) { - upb_oneofdef *o = upb_msg_iter_oneof(&k); - o->index = i; - } - - upb_gfree(fields); - return true; -} - -bool _upb_def_validate(upb_def *const*defs, size_t n, upb_status *s) { - size_t i; - - /* First perform validation, in two passes so we can check that we have a - * transitive closure without needing to search. */ - for (i = 0; i < n; i++) { - upb_def *def = defs[i]; - if (upb_def_isfrozen(def)) { - /* Could relax this requirement if it's annoying. */ - upb_status_seterrmsg(s, "def is already frozen"); - goto err; - } else if (def->type == UPB_DEF_FIELD) { - upb_status_seterrmsg(s, "standalone fielddefs can not be frozen"); - goto err; - } else { - /* Set now to detect transitive closure in the second pass. */ - def->came_from_user = true; - - if (def->type == UPB_DEF_ENUM && - !upb_validate_enumdef(upb_dyncast_enumdef(def), s)) { - goto err; - } - } - } - - /* Second pass of validation. Also assign selector bases and indexes, and - * compact tables. */ - for (i = 0; i < n; i++) { - upb_def *def = defs[i]; - upb_msgdef *m = upb_dyncast_msgdef_mutable(def); - upb_enumdef *e = upb_dyncast_enumdef_mutable(def); - if (m) { - upb_inttable_compact(&m->itof); - if (!assign_msg_indices(m, s)) { - goto err; - } - } else if (e) { - upb_inttable_compact(&e->iton); - } - } - - return true; - -err: - for (i = 0; i < n; i++) { - upb_def *def = defs[i]; - def->came_from_user = false; - } - UPB_ASSERT(!(s && upb_ok(s))); - return false; -} - -bool upb_def_freeze(upb_def *const* defs, size_t n, upb_status *s) { - /* Def graph contains FieldDefs between each MessageDef, so double the - * limit. */ - const size_t maxdepth = UPB_MAX_MESSAGE_DEPTH * 2; - - if (!_upb_def_validate(defs, n, s)) { - return false; - } - - - /* Validation all passed; freeze the objects. */ - return upb_refcounted_freeze((upb_refcounted *const*)defs, n, s, maxdepth); -} - - -/* upb_enumdef ****************************************************************/ - -static void visitenum(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_enumdef *e = (const upb_enumdef*)r; - const upb_def *def = upb_enumdef_upcast(e); - if (upb_def_file(def)) { - visit(r, upb_filedef_upcast(upb_def_file(def)), closure); - } -} - -static void freeenum(upb_refcounted *r) { - upb_enumdef *e = (upb_enumdef*)r; - upb_inttable_iter i; - upb_inttable_begin(&i, &e->iton); - for( ; !upb_inttable_done(&i); upb_inttable_next(&i)) { - /* To clean up the upb_gstrdup() from upb_enumdef_addval(). */ - upb_gfree(upb_value_getcstr(upb_inttable_iter_value(&i))); - } - upb_strtable_uninit(&e->ntoi); - upb_inttable_uninit(&e->iton); - upb_def_uninit(upb_enumdef_upcast_mutable(e)); - upb_gfree(e); -} - -const struct upb_refcounted_vtbl upb_enumdef_vtbl = {&visitenum, &freeenum}; - -upb_enumdef *upb_enumdef_new(const void *owner) { - upb_enumdef *e = upb_gmalloc(sizeof(*e)); - if (!e) return NULL; - - if (!upb_def_init(upb_enumdef_upcast_mutable(e), UPB_DEF_ENUM, - &upb_enumdef_vtbl, owner)) { - goto err2; - } - - if (!upb_strtable_init(&e->ntoi, UPB_CTYPE_INT32)) goto err2; - if (!upb_inttable_init(&e->iton, UPB_CTYPE_CSTR)) goto err1; - return e; - -err1: - upb_strtable_uninit(&e->ntoi); -err2: - upb_gfree(e); - return NULL; -} - -bool upb_enumdef_freeze(upb_enumdef *e, upb_status *status) { - upb_def *d = upb_enumdef_upcast_mutable(e); - return upb_def_freeze(&d, 1, status); -} - -const char *upb_enumdef_fullname(const upb_enumdef *e) { - return upb_def_fullname(upb_enumdef_upcast(e)); -} - -const char *upb_enumdef_name(const upb_enumdef *e) { - return upb_def_name(upb_enumdef_upcast(e)); -} - -bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname, - upb_status *s) { - return upb_def_setfullname(upb_enumdef_upcast_mutable(e), fullname, s); -} - -bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num, - upb_status *status) { - char *name2; - - if (!upb_isident(name, strlen(name), false, status)) { - return false; - } - - if (upb_enumdef_ntoiz(e, name, NULL)) { - upb_status_seterrf(status, "name '%s' is already defined", name); - return false; - } - - if (!upb_strtable_insert(&e->ntoi, name, upb_value_int32(num))) { - upb_status_seterrmsg(status, "out of memory"); - return false; - } - - if (!upb_inttable_lookup(&e->iton, num, NULL)) { - name2 = upb_gstrdup(name); - if (!name2 || !upb_inttable_insert(&e->iton, num, upb_value_cstr(name2))) { - upb_status_seterrmsg(status, "out of memory"); - upb_strtable_remove(&e->ntoi, name, NULL); - return false; - } - } - - if (upb_enumdef_numvals(e) == 1) { - bool ok = upb_enumdef_setdefault(e, num, NULL); - UPB_ASSERT(ok); - } - - return true; -} - -int32_t upb_enumdef_default(const upb_enumdef *e) { - UPB_ASSERT(upb_enumdef_iton(e, e->defaultval)); - return e->defaultval; -} - -bool upb_enumdef_setdefault(upb_enumdef *e, int32_t val, upb_status *s) { - UPB_ASSERT(!upb_enumdef_isfrozen(e)); - if (!upb_enumdef_iton(e, val)) { - upb_status_seterrf(s, "number '%d' is not in the enum.", val); - return false; - } - e->defaultval = val; - return true; -} - -int upb_enumdef_numvals(const upb_enumdef *e) { - return upb_strtable_count(&e->ntoi); -} - -void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) { - /* We iterate over the ntoi table, to account for duplicate numbers. */ - upb_strtable_begin(i, &e->ntoi); -} - -void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); } -bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); } - -bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name, - size_t len, int32_t *num) { - upb_value v; - if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) { - return false; - } - if (num) *num = upb_value_getint32(v); - return true; -} - -const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) { - upb_value v; - return upb_inttable_lookup32(&def->iton, num, &v) ? - upb_value_getcstr(v) : NULL; -} - -const char *upb_enum_iter_name(upb_enum_iter *iter) { - return upb_strtable_iter_key(iter); -} - -int32_t upb_enum_iter_number(upb_enum_iter *iter) { - return upb_value_getint32(upb_strtable_iter_value(iter)); -} - - -/* upb_fielddef ***************************************************************/ - -static void upb_fielddef_init_default(upb_fielddef *f); - -static void upb_fielddef_uninit_default(upb_fielddef *f) { - if (f->type_is_set_ && f->default_is_string && f->defaultval.bytes) - freestr(f->defaultval.bytes); -} - -const char *upb_fielddef_fullname(const upb_fielddef *e) { - return upb_def_fullname(upb_fielddef_upcast(e)); -} - -static void visitfield(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_fielddef *f = (const upb_fielddef*)r; - const upb_def *def = upb_fielddef_upcast(f); - if (upb_fielddef_containingtype(f)) { - visit(r, upb_msgdef_upcast2(upb_fielddef_containingtype(f)), closure); - } - if (upb_fielddef_containingoneof(f)) { - visit(r, upb_oneofdef_upcast(upb_fielddef_containingoneof(f)), closure); - } - if (upb_fielddef_subdef(f)) { - visit(r, upb_def_upcast(upb_fielddef_subdef(f)), closure); - } - if (upb_def_file(def)) { - visit(r, upb_filedef_upcast(upb_def_file(def)), closure); - } -} - -static void freefield(upb_refcounted *r) { - upb_fielddef *f = (upb_fielddef*)r; - upb_fielddef_uninit_default(f); - if (f->subdef_is_symbolic) - upb_gfree(f->sub.name); - upb_def_uninit(upb_fielddef_upcast_mutable(f)); - upb_gfree(f); -} - -static const char *enumdefaultstr(const upb_fielddef *f) { - const upb_enumdef *e; - UPB_ASSERT(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); - e = upb_fielddef_enumsubdef(f); - if (f->default_is_string && f->defaultval.bytes) { - /* Default was explicitly set as a string. */ - str_t *s = f->defaultval.bytes; - return s->str; - } else if (e) { - if (!f->default_is_string) { - /* Default was explicitly set as an integer; look it up in enumdef. */ - const char *name = upb_enumdef_iton(e, f->defaultval.sint); - if (name) { - return name; - } - } else { - /* Default is completely unset; pull enumdef default. */ - if (upb_enumdef_numvals(e) > 0) { - const char *name = upb_enumdef_iton(e, upb_enumdef_default(e)); - UPB_ASSERT(name); - return name; - } - } - } - return NULL; -} - -static bool enumdefaultint32(const upb_fielddef *f, int32_t *val) { - const upb_enumdef *e; - UPB_ASSERT(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); - e = upb_fielddef_enumsubdef(f); - if (!f->default_is_string) { - /* Default was explicitly set as an integer. */ - *val = f->defaultval.sint; - return true; - } else if (e) { - if (f->defaultval.bytes) { - /* Default was explicitly set as a str; try to lookup corresponding int. */ - str_t *s = f->defaultval.bytes; - if (upb_enumdef_ntoiz(e, s->str, val)) { - return true; - } - } else { - /* Default is unset; try to pull in enumdef default. */ - if (upb_enumdef_numvals(e) > 0) { - *val = upb_enumdef_default(e); - return true; - } - } - } - return false; -} - -const struct upb_refcounted_vtbl upb_fielddef_vtbl = {visitfield, freefield}; - -upb_fielddef *upb_fielddef_new(const void *o) { - upb_fielddef *f = upb_gmalloc(sizeof(*f)); - if (!f) return NULL; - if (!upb_def_init(upb_fielddef_upcast_mutable(f), UPB_DEF_FIELD, - &upb_fielddef_vtbl, o)) { - upb_gfree(f); - return NULL; - } - f->msg.def = NULL; - f->sub.def = NULL; - f->oneof = NULL; - f->subdef_is_symbolic = false; - f->msg_is_symbolic = false; - f->label_ = UPB_LABEL_OPTIONAL; - f->type_ = UPB_TYPE_INT32; - f->number_ = 0; - f->type_is_set_ = false; - f->tagdelim = false; - f->is_extension_ = false; - f->lazy_ = false; - f->packed_ = true; - - /* For the moment we default this to UPB_INTFMT_VARIABLE, since it will work - * with all integer types and is in some since more "default" since the most - * normal-looking proto2 types int32/int64/uint32/uint64 use variable. - * - * Other options to consider: - * - there is no default; users must set this manually (like type). - * - default signed integers to UPB_INTFMT_ZIGZAG, since it's more likely to - * be an optimal default for signed integers. */ - f->intfmt = UPB_INTFMT_VARIABLE; - return f; -} - -bool upb_fielddef_typeisset(const upb_fielddef *f) { - return f->type_is_set_; -} - -upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) { - UPB_ASSERT(f->type_is_set_); - return f->type_; -} - -uint32_t upb_fielddef_index(const upb_fielddef *f) { - return f->index_; -} - -upb_label_t upb_fielddef_label(const upb_fielddef *f) { - return f->label_; -} - -upb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f) { - return f->intfmt; -} - -bool upb_fielddef_istagdelim(const upb_fielddef *f) { - return f->tagdelim; -} - -uint32_t upb_fielddef_number(const upb_fielddef *f) { - return f->number_; -} - -bool upb_fielddef_isextension(const upb_fielddef *f) { - return f->is_extension_; -} - -bool upb_fielddef_lazy(const upb_fielddef *f) { - return f->lazy_; -} - -bool upb_fielddef_packed(const upb_fielddef *f) { - return f->packed_; -} - -const char *upb_fielddef_name(const upb_fielddef *f) { - return upb_def_fullname(upb_fielddef_upcast(f)); -} - -size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len) { - const char *name = upb_fielddef_name(f); - size_t src, dst = 0; - bool ucase_next = false; - -#define WRITE(byte) \ - ++dst; \ - if (dst < len) buf[dst - 1] = byte; \ - else if (dst == len) buf[dst - 1] = '\0' - - if (!name) { - WRITE('\0'); - return 0; - } - - /* Implement the transformation as described in the spec: - * 1. upper case all letters after an underscore. - * 2. remove all underscores. - */ - for (src = 0; name[src]; src++) { - if (name[src] == '_') { - ucase_next = true; - continue; - } - - if (ucase_next) { - WRITE(toupper(name[src])); - ucase_next = false; - } else { - WRITE(name[src]); - } - } - - WRITE('\0'); - return dst; - -#undef WRITE -} - -const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) { - return f->msg_is_symbolic ? NULL : f->msg.def; -} - -const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) { - return f->oneof; -} - -upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f) { - return (upb_msgdef*)upb_fielddef_containingtype(f); -} - -const char *upb_fielddef_containingtypename(upb_fielddef *f) { - return f->msg_is_symbolic ? f->msg.name : NULL; -} - -static void release_containingtype(upb_fielddef *f) { - if (f->msg_is_symbolic) upb_gfree(f->msg.name); -} - -bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name, - upb_status *s) { - char *name_copy; - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - if (upb_fielddef_containingtype(f)) { - upb_status_seterrmsg(s, "field has already been added to a message."); - return false; - } - /* TODO: validate name (upb_isident() doesn't quite work atm because this name - * may have a leading "."). */ - - name_copy = upb_gstrdup(name); - if (!name_copy) { - upb_upberr_setoom(s); - return false; - } - - release_containingtype(f); - f->msg.name = name_copy; - f->msg_is_symbolic = true; - return true; -} - -bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s) { - if (upb_fielddef_containingtype(f) || upb_fielddef_containingoneof(f)) { - upb_status_seterrmsg(s, "Already added to message or oneof"); - return false; - } - return upb_def_setfullname(upb_fielddef_upcast_mutable(f), name, s); -} - -static void chkdefaulttype(const upb_fielddef *f, upb_fieldtype_t type) { - UPB_UNUSED(f); - UPB_UNUSED(type); - UPB_ASSERT(f->type_is_set_ && upb_fielddef_type(f) == type); -} - -int64_t upb_fielddef_defaultint64(const upb_fielddef *f) { - chkdefaulttype(f, UPB_TYPE_INT64); - return f->defaultval.sint; -} - -int32_t upb_fielddef_defaultint32(const upb_fielddef *f) { - if (f->type_is_set_ && upb_fielddef_type(f) == UPB_TYPE_ENUM) { - int32_t val; - bool ok = enumdefaultint32(f, &val); - UPB_ASSERT(ok); - return val; - } else { - chkdefaulttype(f, UPB_TYPE_INT32); - return f->defaultval.sint; - } -} - -uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) { - chkdefaulttype(f, UPB_TYPE_UINT64); - return f->defaultval.uint; -} - -uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) { - chkdefaulttype(f, UPB_TYPE_UINT32); - return f->defaultval.uint; -} - -bool upb_fielddef_defaultbool(const upb_fielddef *f) { - chkdefaulttype(f, UPB_TYPE_BOOL); - return f->defaultval.uint; -} - -float upb_fielddef_defaultfloat(const upb_fielddef *f) { - chkdefaulttype(f, UPB_TYPE_FLOAT); - return f->defaultval.flt; -} - -double upb_fielddef_defaultdouble(const upb_fielddef *f) { - chkdefaulttype(f, UPB_TYPE_DOUBLE); - return f->defaultval.dbl; -} - -const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) { - UPB_ASSERT(f->type_is_set_); - UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_STRING || - upb_fielddef_type(f) == UPB_TYPE_BYTES || - upb_fielddef_type(f) == UPB_TYPE_ENUM); - - if (upb_fielddef_type(f) == UPB_TYPE_ENUM) { - const char *ret = enumdefaultstr(f); - UPB_ASSERT(ret); - /* Enum defaults can't have embedded NULLs. */ - if (len) *len = strlen(ret); - return ret; - } - - if (f->default_is_string) { - str_t *str = f->defaultval.bytes; - if (len) *len = str->len; - return str->str; - } - - return NULL; -} - -static void upb_fielddef_init_default(upb_fielddef *f) { - f->default_is_string = false; - switch (upb_fielddef_type(f)) { - case UPB_TYPE_DOUBLE: f->defaultval.dbl = 0; break; - case UPB_TYPE_FLOAT: f->defaultval.flt = 0; break; - case UPB_TYPE_INT32: - case UPB_TYPE_INT64: f->defaultval.sint = 0; break; - case UPB_TYPE_UINT64: - case UPB_TYPE_UINT32: - case UPB_TYPE_BOOL: f->defaultval.uint = 0; break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - f->defaultval.bytes = newstr("", 0); - f->default_is_string = true; - break; - case UPB_TYPE_MESSAGE: break; - case UPB_TYPE_ENUM: - /* This is our special sentinel that indicates "not set" for an enum. */ - f->default_is_string = true; - f->defaultval.bytes = NULL; - break; - } -} - -const upb_def *upb_fielddef_subdef(const upb_fielddef *f) { - return f->subdef_is_symbolic ? NULL : f->sub.def; -} - -const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) { - const upb_def *def = upb_fielddef_subdef(f); - return def ? upb_dyncast_msgdef(def) : NULL; -} - -const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) { - const upb_def *def = upb_fielddef_subdef(f); - return def ? upb_dyncast_enumdef(def) : NULL; -} - -upb_def *upb_fielddef_subdef_mutable(upb_fielddef *f) { - return (upb_def*)upb_fielddef_subdef(f); -} - -const char *upb_fielddef_subdefname(const upb_fielddef *f) { - if (f->subdef_is_symbolic) { - return f->sub.name; - } else if (f->sub.def) { - return upb_def_fullname(f->sub.def); - } else { - return NULL; - } -} - -bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s) { - if (upb_fielddef_containingtype(f)) { - upb_status_seterrmsg( - s, "cannot change field number after adding to a message"); - return false; - } - if (number == 0 || number > UPB_MAX_FIELDNUMBER) { - upb_status_seterrf(s, "invalid field number (%u)", number); - return false; - } - f->number_ = number; - return true; -} - -void upb_fielddef_settype(upb_fielddef *f, upb_fieldtype_t type) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - UPB_ASSERT(upb_fielddef_checktype(type)); - upb_fielddef_uninit_default(f); - f->type_ = type; - f->type_is_set_ = true; - upb_fielddef_init_default(f); -} - -void upb_fielddef_setdescriptortype(upb_fielddef *f, int type) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - switch (type) { - case UPB_DESCRIPTOR_TYPE_DOUBLE: - upb_fielddef_settype(f, UPB_TYPE_DOUBLE); - break; - case UPB_DESCRIPTOR_TYPE_FLOAT: - upb_fielddef_settype(f, UPB_TYPE_FLOAT); - break; - case UPB_DESCRIPTOR_TYPE_INT64: - case UPB_DESCRIPTOR_TYPE_SFIXED64: - case UPB_DESCRIPTOR_TYPE_SINT64: - upb_fielddef_settype(f, UPB_TYPE_INT64); - break; - case UPB_DESCRIPTOR_TYPE_UINT64: - case UPB_DESCRIPTOR_TYPE_FIXED64: - upb_fielddef_settype(f, UPB_TYPE_UINT64); - break; - case UPB_DESCRIPTOR_TYPE_INT32: - case UPB_DESCRIPTOR_TYPE_SFIXED32: - case UPB_DESCRIPTOR_TYPE_SINT32: - upb_fielddef_settype(f, UPB_TYPE_INT32); - break; - case UPB_DESCRIPTOR_TYPE_UINT32: - case UPB_DESCRIPTOR_TYPE_FIXED32: - upb_fielddef_settype(f, UPB_TYPE_UINT32); - break; - case UPB_DESCRIPTOR_TYPE_BOOL: - upb_fielddef_settype(f, UPB_TYPE_BOOL); - break; - case UPB_DESCRIPTOR_TYPE_STRING: - upb_fielddef_settype(f, UPB_TYPE_STRING); - break; - case UPB_DESCRIPTOR_TYPE_BYTES: - upb_fielddef_settype(f, UPB_TYPE_BYTES); - break; - case UPB_DESCRIPTOR_TYPE_GROUP: - case UPB_DESCRIPTOR_TYPE_MESSAGE: - upb_fielddef_settype(f, UPB_TYPE_MESSAGE); - break; - case UPB_DESCRIPTOR_TYPE_ENUM: - upb_fielddef_settype(f, UPB_TYPE_ENUM); - break; - default: UPB_ASSERT(false); - } - - if (type == UPB_DESCRIPTOR_TYPE_FIXED64 || - type == UPB_DESCRIPTOR_TYPE_FIXED32 || - type == UPB_DESCRIPTOR_TYPE_SFIXED64 || - type == UPB_DESCRIPTOR_TYPE_SFIXED32) { - upb_fielddef_setintfmt(f, UPB_INTFMT_FIXED); - } else if (type == UPB_DESCRIPTOR_TYPE_SINT64 || - type == UPB_DESCRIPTOR_TYPE_SINT32) { - upb_fielddef_setintfmt(f, UPB_INTFMT_ZIGZAG); - } else { - upb_fielddef_setintfmt(f, UPB_INTFMT_VARIABLE); - } - - upb_fielddef_settagdelim(f, type == UPB_DESCRIPTOR_TYPE_GROUP); -} - -upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) { - switch (upb_fielddef_type(f)) { - case UPB_TYPE_FLOAT: return UPB_DESCRIPTOR_TYPE_FLOAT; - case UPB_TYPE_DOUBLE: return UPB_DESCRIPTOR_TYPE_DOUBLE; - case UPB_TYPE_BOOL: return UPB_DESCRIPTOR_TYPE_BOOL; - case UPB_TYPE_STRING: return UPB_DESCRIPTOR_TYPE_STRING; - case UPB_TYPE_BYTES: return UPB_DESCRIPTOR_TYPE_BYTES; - case UPB_TYPE_ENUM: return UPB_DESCRIPTOR_TYPE_ENUM; - case UPB_TYPE_INT32: - switch (upb_fielddef_intfmt(f)) { - case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_INT32; - case UPB_INTFMT_FIXED: return UPB_DESCRIPTOR_TYPE_SFIXED32; - case UPB_INTFMT_ZIGZAG: return UPB_DESCRIPTOR_TYPE_SINT32; - } - case UPB_TYPE_INT64: - switch (upb_fielddef_intfmt(f)) { - case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_INT64; - case UPB_INTFMT_FIXED: return UPB_DESCRIPTOR_TYPE_SFIXED64; - case UPB_INTFMT_ZIGZAG: return UPB_DESCRIPTOR_TYPE_SINT64; - } - case UPB_TYPE_UINT32: - switch (upb_fielddef_intfmt(f)) { - case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_UINT32; - case UPB_INTFMT_FIXED: return UPB_DESCRIPTOR_TYPE_FIXED32; - case UPB_INTFMT_ZIGZAG: return -1; - } - case UPB_TYPE_UINT64: - switch (upb_fielddef_intfmt(f)) { - case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_UINT64; - case UPB_INTFMT_FIXED: return UPB_DESCRIPTOR_TYPE_FIXED64; - case UPB_INTFMT_ZIGZAG: return -1; - } - case UPB_TYPE_MESSAGE: - return upb_fielddef_istagdelim(f) ? - UPB_DESCRIPTOR_TYPE_GROUP : UPB_DESCRIPTOR_TYPE_MESSAGE; - } - return 0; -} - -void upb_fielddef_setisextension(upb_fielddef *f, bool is_extension) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - f->is_extension_ = is_extension; -} - -void upb_fielddef_setlazy(upb_fielddef *f, bool lazy) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - f->lazy_ = lazy; -} - -void upb_fielddef_setpacked(upb_fielddef *f, bool packed) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - f->packed_ = packed; -} - -void upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - UPB_ASSERT(upb_fielddef_checklabel(label)); - f->label_ = label; -} - -void upb_fielddef_setintfmt(upb_fielddef *f, upb_intfmt_t fmt) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - UPB_ASSERT(upb_fielddef_checkintfmt(fmt)); - f->intfmt = fmt; -} - -void upb_fielddef_settagdelim(upb_fielddef *f, bool tag_delim) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - f->tagdelim = tag_delim; - f->tagdelim = tag_delim; -} - -static bool checksetdefault(upb_fielddef *f, upb_fieldtype_t type) { - if (!f->type_is_set_ || upb_fielddef_isfrozen(f) || - upb_fielddef_type(f) != type) { - UPB_ASSERT(false); - return false; - } - if (f->default_is_string) { - str_t *s = f->defaultval.bytes; - UPB_ASSERT(s || type == UPB_TYPE_ENUM); - if (s) freestr(s); - } - f->default_is_string = false; - return true; -} - -void upb_fielddef_setdefaultint64(upb_fielddef *f, int64_t value) { - if (checksetdefault(f, UPB_TYPE_INT64)) - f->defaultval.sint = value; -} - -void upb_fielddef_setdefaultint32(upb_fielddef *f, int32_t value) { - if ((upb_fielddef_type(f) == UPB_TYPE_ENUM && - checksetdefault(f, UPB_TYPE_ENUM)) || - checksetdefault(f, UPB_TYPE_INT32)) { - f->defaultval.sint = value; - } -} - -void upb_fielddef_setdefaultuint64(upb_fielddef *f, uint64_t value) { - if (checksetdefault(f, UPB_TYPE_UINT64)) - f->defaultval.uint = value; -} - -void upb_fielddef_setdefaultuint32(upb_fielddef *f, uint32_t value) { - if (checksetdefault(f, UPB_TYPE_UINT32)) - f->defaultval.uint = value; -} - -void upb_fielddef_setdefaultbool(upb_fielddef *f, bool value) { - if (checksetdefault(f, UPB_TYPE_BOOL)) - f->defaultval.uint = value; -} - -void upb_fielddef_setdefaultfloat(upb_fielddef *f, float value) { - if (checksetdefault(f, UPB_TYPE_FLOAT)) - f->defaultval.flt = value; -} - -void upb_fielddef_setdefaultdouble(upb_fielddef *f, double value) { - if (checksetdefault(f, UPB_TYPE_DOUBLE)) - f->defaultval.dbl = value; -} - -bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len, - upb_status *s) { - str_t *str2; - UPB_ASSERT(upb_fielddef_isstring(f) || f->type_ == UPB_TYPE_ENUM); - if (f->type_ == UPB_TYPE_ENUM && !upb_isident(str, len, false, s)) - return false; - - if (f->default_is_string) { - str_t *s = f->defaultval.bytes; - UPB_ASSERT(s || f->type_ == UPB_TYPE_ENUM); - if (s) freestr(s); - } else { - UPB_ASSERT(f->type_ == UPB_TYPE_ENUM); - } - - str2 = newstr(str, len); - f->defaultval.bytes = str2; - f->default_is_string = true; - return true; -} - -void upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str, - upb_status *s) { - UPB_ASSERT(f->type_is_set_); - upb_fielddef_setdefaultstr(f, str, str ? strlen(str) : 0, s); -} - -bool upb_fielddef_enumhasdefaultint32(const upb_fielddef *f) { - int32_t val; - UPB_ASSERT(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); - return enumdefaultint32(f, &val); -} - -bool upb_fielddef_enumhasdefaultstr(const upb_fielddef *f) { - UPB_ASSERT(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); - return enumdefaultstr(f) != NULL; -} - -static bool upb_subdef_typecheck(upb_fielddef *f, const upb_def *subdef, - upb_status *s) { - if (f->type_ == UPB_TYPE_MESSAGE) { - if (upb_dyncast_msgdef(subdef)) return true; - upb_status_seterrmsg(s, "invalid subdef type for this submessage field"); - return false; - } else if (f->type_ == UPB_TYPE_ENUM) { - if (upb_dyncast_enumdef(subdef)) return true; - upb_status_seterrmsg(s, "invalid subdef type for this enum field"); - return false; - } else { - upb_status_seterrmsg(s, "only message and enum fields can have a subdef"); - return false; - } -} - -static void release_subdef(upb_fielddef *f) { - if (f->subdef_is_symbolic) { - upb_gfree(f->sub.name); - } else if (f->sub.def) { - upb_unref2(f->sub.def, f); - } -} - -bool upb_fielddef_setsubdef(upb_fielddef *f, const upb_def *subdef, - upb_status *s) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - UPB_ASSERT(upb_fielddef_hassubdef(f)); - if (subdef && !upb_subdef_typecheck(f, subdef, s)) return false; - release_subdef(f); - f->sub.def = subdef; - f->subdef_is_symbolic = false; - if (f->sub.def) upb_ref2(f->sub.def, f); - return true; -} - -bool upb_fielddef_setmsgsubdef(upb_fielddef *f, const upb_msgdef *subdef, - upb_status *s) { - return upb_fielddef_setsubdef(f, upb_msgdef_upcast(subdef), s); -} - -bool upb_fielddef_setenumsubdef(upb_fielddef *f, const upb_enumdef *subdef, - upb_status *s) { - return upb_fielddef_setsubdef(f, upb_enumdef_upcast(subdef), s); -} - -bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name, - upb_status *s) { - char *name_copy; - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - if (!upb_fielddef_hassubdef(f)) { - upb_status_seterrmsg(s, "field type does not accept a subdef"); - return false; - } - - name_copy = upb_gstrdup(name); - if (!name_copy) { - upb_upberr_setoom(s); - return false; - } - - /* TODO: validate name (upb_isident() doesn't quite work atm because this name - * may have a leading "."). */ - release_subdef(f); - f->sub.name = name_copy; - f->subdef_is_symbolic = true; - return true; -} - -bool upb_fielddef_issubmsg(const upb_fielddef *f) { - return upb_fielddef_type(f) == UPB_TYPE_MESSAGE; -} - -bool upb_fielddef_isstring(const upb_fielddef *f) { - return upb_fielddef_type(f) == UPB_TYPE_STRING || - upb_fielddef_type(f) == UPB_TYPE_BYTES; -} - -bool upb_fielddef_isseq(const upb_fielddef *f) { - return upb_fielddef_label(f) == UPB_LABEL_REPEATED; -} - -bool upb_fielddef_isprimitive(const upb_fielddef *f) { - return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f); -} - -bool upb_fielddef_ismap(const upb_fielddef *f) { - return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) && - upb_msgdef_mapentry(upb_fielddef_msgsubdef(f)); -} - -bool upb_fielddef_haspresence(const upb_fielddef *f) { - if (upb_fielddef_isseq(f)) return false; - if (upb_fielddef_issubmsg(f)) return true; - - /* Primitive field: return true unless there is a message that specifies - * presence should not exist. */ - if (f->msg_is_symbolic || !f->msg.def) return true; - return f->msg.def->syntax == UPB_SYNTAX_PROTO2; -} - -bool upb_fielddef_hassubdef(const upb_fielddef *f) { - return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM; -} - -static bool between(int32_t x, int32_t low, int32_t high) { - return x >= low && x <= high; -} - -bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); } -bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); } -bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); } - -bool upb_fielddef_checkdescriptortype(int32_t type) { - return between(type, 1, 18); -} - -/* upb_msgdef *****************************************************************/ - -static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - upb_msg_oneof_iter o; - const upb_msgdef *m = (const upb_msgdef*)r; - const upb_def *def = upb_msgdef_upcast(m); - upb_msg_field_iter i; - for(upb_msg_field_begin(&i, m); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - visit(r, upb_fielddef_upcast2(f), closure); - } - for(upb_msg_oneof_begin(&o, m); - !upb_msg_oneof_done(&o); - upb_msg_oneof_next(&o)) { - upb_oneofdef *f = upb_msg_iter_oneof(&o); - visit(r, upb_oneofdef_upcast(f), closure); - } - if (upb_def_file(def)) { - visit(r, upb_filedef_upcast(upb_def_file(def)), closure); - } -} - -static void freemsg(upb_refcounted *r) { - upb_msgdef *m = (upb_msgdef*)r; - upb_strtable_uninit(&m->ntof); - upb_inttable_uninit(&m->itof); - upb_def_uninit(upb_msgdef_upcast_mutable(m)); - upb_gfree(m); -} - -const struct upb_refcounted_vtbl upb_msgdef_vtbl = {visitmsg, freemsg}; - -upb_msgdef *upb_msgdef_new(const void *owner) { - upb_msgdef *m = upb_gmalloc(sizeof(*m)); - if (!m) return NULL; - - if (!upb_def_init(upb_msgdef_upcast_mutable(m), UPB_DEF_MSG, &upb_msgdef_vtbl, - owner)) { - goto err2; - } - - if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err2; - if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err1; - m->map_entry = false; - m->syntax = UPB_SYNTAX_PROTO2; - return m; - -err1: - upb_inttable_uninit(&m->itof); -err2: - upb_gfree(m); - return NULL; -} - -bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status) { - upb_def *d = upb_msgdef_upcast_mutable(m); - return upb_def_freeze(&d, 1, status); -} - -const char *upb_msgdef_fullname(const upb_msgdef *m) { - return upb_def_fullname(upb_msgdef_upcast(m)); -} - -const char *upb_msgdef_name(const upb_msgdef *m) { - return upb_def_name(upb_msgdef_upcast(m)); -} - -bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, - upb_status *s) { - return upb_def_setfullname(upb_msgdef_upcast_mutable(m), fullname, s); -} - -bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax) { - if (syntax != UPB_SYNTAX_PROTO2 && syntax != UPB_SYNTAX_PROTO3) { - return false; - } - - m->syntax = syntax; - return true; -} - -upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) { - return m->syntax; -} - -/* Helper: check that the field |f| is safe to add to msgdef |m|. Set an error - * on status |s| and return false if not. */ -static bool check_field_add(const upb_msgdef *m, const upb_fielddef *f, - upb_status *s) { - if (upb_fielddef_containingtype(f) != NULL) { - upb_status_seterrmsg(s, "fielddef already belongs to a message"); - return false; - } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { - upb_status_seterrmsg(s, "field name or number were not set"); - return false; - } else if (upb_msgdef_itof(m, upb_fielddef_number(f))) { - upb_status_seterrmsg(s, "duplicate field number"); - return false; - } else if (upb_strtable_lookup(&m->ntof, upb_fielddef_name(f), NULL)) { - upb_status_seterrmsg(s, "name conflicts with existing field or oneof"); - return false; - } - return true; -} - -static void add_field(upb_msgdef *m, upb_fielddef *f, const void *ref_donor) { - release_containingtype(f); - f->msg.def = m; - f->msg_is_symbolic = false; - upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f)); - upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f)); - upb_ref2(f, m); - upb_ref2(m, f); - if (ref_donor) upb_fielddef_unref(f, ref_donor); -} - -bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor, - upb_status *s) { - /* TODO: extensions need to have a separate namespace, because proto2 allows a - * top-level extension (ie. one not in any package) to have the same name as a - * field from the message. - * - * This also implies that there needs to be a separate lookup-by-name method - * for extensions. It seems desirable for iteration to return both extensions - * and non-extensions though. - * - * We also need to validate that the field number is in an extension range iff - * it is an extension. - * - * This method is idempotent. Check if |f| is already part of this msgdef and - * return immediately if so. */ - if (upb_fielddef_containingtype(f) == m) { - if (ref_donor) upb_fielddef_unref(f, ref_donor); - return true; - } - - /* Check constraints for all fields before performing any action. */ - if (!check_field_add(m, f, s)) { - return false; - } else if (upb_fielddef_containingoneof(f) != NULL) { - /* Fields in a oneof can only be added by adding the oneof to the msgdef. */ - upb_status_seterrmsg(s, "fielddef is part of a oneof"); - return false; - } - - /* Constraint checks ok, perform the action. */ - add_field(m, f, ref_donor); - return true; -} - -bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, - upb_status *s) { - upb_oneof_iter it; - - /* Check various conditions that would prevent this oneof from being added. */ - if (upb_oneofdef_containingtype(o)) { - upb_status_seterrmsg(s, "oneofdef already belongs to a message"); - return false; - } else if (upb_oneofdef_name(o) == NULL) { - upb_status_seterrmsg(s, "oneofdef name was not set"); - return false; - } else if (upb_strtable_lookup(&m->ntof, upb_oneofdef_name(o), NULL)) { - upb_status_seterrmsg(s, "name conflicts with existing field or oneof"); - return false; - } - - /* Check that all of the oneof's fields do not conflict with names or numbers - * of fields already in the message. */ - for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) { - const upb_fielddef *f = upb_oneof_iter_field(&it); - if (!check_field_add(m, f, s)) { - return false; - } - } - - /* Everything checks out -- commit now. */ - - /* Add oneof itself first. */ - o->parent = m; - upb_strtable_insert(&m->ntof, upb_oneofdef_name(o), upb_value_ptr(o)); - upb_ref2(o, m); - upb_ref2(m, o); - - /* Add each field of the oneof directly to the msgdef. */ - for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) { - upb_fielddef *f = upb_oneof_iter_field(&it); - add_field(m, f, NULL); - } - - if (ref_donor) upb_oneofdef_unref(o, ref_donor); - - return true; -} - -const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) { - upb_value val; - return upb_inttable_lookup32(&m->itof, i, &val) ? - upb_value_getptr(val) : NULL; -} - -const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name, - size_t len) { - upb_value val; - - if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { - return NULL; - } - - return upb_trygetfield(upb_value_getptr(val)); -} - -const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, - size_t len) { - upb_value val; - - if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { - return NULL; - } - - return upb_trygetoneof(upb_value_getptr(val)); -} - -bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len, - const upb_fielddef **f, const upb_oneofdef **o) { - upb_value val; - - if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { - return false; - } - - *o = upb_trygetoneof(upb_value_getptr(val)); - *f = upb_trygetfield(upb_value_getptr(val)); - UPB_ASSERT((*o != NULL) ^ (*f != NULL)); /* Exactly one of the two should be set. */ - return true; -} - -int upb_msgdef_numfields(const upb_msgdef *m) { - /* The number table contains only fields. */ - return upb_inttable_count(&m->itof); -} - -int upb_msgdef_numoneofs(const upb_msgdef *m) { - /* The name table includes oneofs, and the number table does not. */ - return upb_strtable_count(&m->ntof) - upb_inttable_count(&m->itof); -} - -void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry) { - UPB_ASSERT(!upb_msgdef_isfrozen(m)); - m->map_entry = map_entry; -} - -bool upb_msgdef_mapentry(const upb_msgdef *m) { - return m->map_entry; -} - -void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) { - upb_inttable_begin(iter, &m->itof); -} - -void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); } - -bool upb_msg_field_done(const upb_msg_field_iter *iter) { - return upb_inttable_done(iter); -} - -upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) { - return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter)); -} - -void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) { - upb_inttable_iter_setdone(iter); -} - -void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) { - upb_strtable_begin(iter, &m->ntof); - /* We need to skip past any initial fields. */ - while (!upb_strtable_done(iter) && - !upb_isoneof(upb_value_getptr(upb_strtable_iter_value(iter)))) { - upb_strtable_next(iter); - } -} - -void upb_msg_oneof_next(upb_msg_oneof_iter *iter) { - /* We need to skip past fields to return only oneofs. */ - do { - upb_strtable_next(iter); - } while (!upb_strtable_done(iter) && - !upb_isoneof(upb_value_getptr(upb_strtable_iter_value(iter)))); -} - -bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) { - return upb_strtable_done(iter); -} - -upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) { - return (upb_oneofdef*)upb_value_getptr(upb_strtable_iter_value(iter)); -} - -void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) { - upb_strtable_iter_setdone(iter); -} - -/* upb_oneofdef ***************************************************************/ - -static void visitoneof(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_oneofdef *o = (const upb_oneofdef*)r; - upb_oneof_iter i; - for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) { - const upb_fielddef *f = upb_oneof_iter_field(&i); - visit(r, upb_fielddef_upcast2(f), closure); - } - if (o->parent) { - visit(r, upb_msgdef_upcast2(o->parent), closure); - } -} - -static void freeoneof(upb_refcounted *r) { - upb_oneofdef *o = (upb_oneofdef*)r; - upb_strtable_uninit(&o->ntof); - upb_inttable_uninit(&o->itof); - upb_gfree((void*)o->name); - upb_gfree(o); -} - -const struct upb_refcounted_vtbl upb_oneofdef_vtbl = {visitoneof, freeoneof}; - -upb_oneofdef *upb_oneofdef_new(const void *owner) { - upb_oneofdef *o = upb_gmalloc(sizeof(*o)); - - if (!o) { - return NULL; - } - - o->parent = NULL; - o->name = NULL; - - if (!upb_refcounted_init(upb_oneofdef_upcast_mutable(o), &upb_oneofdef_vtbl, - owner)) { - goto err2; - } - - if (!upb_inttable_init(&o->itof, UPB_CTYPE_PTR)) goto err2; - if (!upb_strtable_init(&o->ntof, UPB_CTYPE_PTR)) goto err1; - - return o; - -err1: - upb_inttable_uninit(&o->itof); -err2: - upb_gfree(o); - return NULL; -} - -const char *upb_oneofdef_name(const upb_oneofdef *o) { return o->name; } - -bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s) { - UPB_ASSERT(!upb_oneofdef_isfrozen(o)); - if (upb_oneofdef_containingtype(o)) { - upb_status_seterrmsg(s, "oneof already added to a message"); - return false; - } - - if (!upb_isident(name, strlen(name), true, s)) { - return false; - } - - name = upb_gstrdup(name); - if (!name) { - upb_status_seterrmsg(s, "One of memory"); - return false; - } - - upb_gfree((void*)o->name); - o->name = name; - return true; -} - -const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) { - return o->parent; -} - -int upb_oneofdef_numfields(const upb_oneofdef *o) { - return upb_strtable_count(&o->ntof); -} - -uint32_t upb_oneofdef_index(const upb_oneofdef *o) { - return o->index; -} - -bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f, - const void *ref_donor, - upb_status *s) { - UPB_ASSERT(!upb_oneofdef_isfrozen(o)); - UPB_ASSERT(!o->parent || !upb_msgdef_isfrozen(o->parent)); - - /* This method is idempotent. Check if |f| is already part of this oneofdef - * and return immediately if so. */ - if (upb_fielddef_containingoneof(f) == o) { - return true; - } - - /* The field must have an OPTIONAL label. */ - if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) { - upb_status_seterrmsg(s, "fields in oneof must have OPTIONAL label"); - return false; - } - - /* Check that no field with this name or number exists already in the oneof. - * Also check that the field is not already part of a oneof. */ - if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { - upb_status_seterrmsg(s, "field name or number were not set"); - return false; - } else if (upb_oneofdef_itof(o, upb_fielddef_number(f)) || - upb_oneofdef_ntofz(o, upb_fielddef_name(f))) { - upb_status_seterrmsg(s, "duplicate field name or number"); - return false; - } else if (upb_fielddef_containingoneof(f) != NULL) { - upb_status_seterrmsg(s, "fielddef already belongs to a oneof"); - return false; - } - - /* We allow adding a field to the oneof either if the field is not part of a - * msgdef, or if it is and we are also part of the same msgdef. */ - if (o->parent == NULL) { - /* If we're not in a msgdef, the field cannot be either. Otherwise we would - * need to magically add this oneof to a msgdef to remain consistent, which - * is surprising behavior. */ - if (upb_fielddef_containingtype(f) != NULL) { - upb_status_seterrmsg(s, "fielddef already belongs to a message, but " - "oneof does not"); - return false; - } - } else { - /* If we're in a msgdef, the user can add fields that either aren't in any - * msgdef (in which case they're added to our msgdef) or already a part of - * our msgdef. */ - if (upb_fielddef_containingtype(f) != NULL && - upb_fielddef_containingtype(f) != o->parent) { - upb_status_seterrmsg(s, "fielddef belongs to a different message " - "than oneof"); - return false; - } - } - - /* Commit phase. First add the field to our parent msgdef, if any, because - * that may fail; then add the field to our own tables. */ - - if (o->parent != NULL && upb_fielddef_containingtype(f) == NULL) { - if (!upb_msgdef_addfield((upb_msgdef*)o->parent, f, NULL, s)) { - return false; - } - } - - release_containingtype(f); - f->oneof = o; - upb_inttable_insert(&o->itof, upb_fielddef_number(f), upb_value_ptr(f)); - upb_strtable_insert(&o->ntof, upb_fielddef_name(f), upb_value_ptr(f)); - upb_ref2(f, o); - upb_ref2(o, f); - if (ref_donor) upb_fielddef_unref(f, ref_donor); - - return true; -} - -const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, - const char *name, size_t length) { - upb_value val; - return upb_strtable_lookup2(&o->ntof, name, length, &val) ? - upb_value_getptr(val) : NULL; -} - -const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) { - upb_value val; - return upb_inttable_lookup32(&o->itof, num, &val) ? - upb_value_getptr(val) : NULL; -} - -void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) { - upb_inttable_begin(iter, &o->itof); -} - -void upb_oneof_next(upb_oneof_iter *iter) { - upb_inttable_next(iter); -} - -bool upb_oneof_done(upb_oneof_iter *iter) { - return upb_inttable_done(iter); -} - -upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) { - return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter)); -} - -void upb_oneof_iter_setdone(upb_oneof_iter *iter) { - upb_inttable_iter_setdone(iter); -} - -/* upb_filedef ****************************************************************/ - -static void visitfiledef(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_filedef *f = (const upb_filedef*)r; - size_t i; - - for(i = 0; i < upb_filedef_defcount(f); i++) { - visit(r, upb_def_upcast(upb_filedef_def(f, i)), closure); - } -} - -static void freefiledef(upb_refcounted *r) { - upb_filedef *f = (upb_filedef*)r; - size_t i; - - for(i = 0; i < upb_filedef_depcount(f); i++) { - upb_filedef_unref(upb_filedef_dep(f, i), f); - } - - upb_inttable_uninit(&f->defs); - upb_inttable_uninit(&f->deps); - upb_gfree((void*)f->name); - upb_gfree((void*)f->package); - upb_gfree((void*)f->phpprefix); - upb_gfree((void*)f->phpnamespace); - upb_gfree(f); -} - -const struct upb_refcounted_vtbl upb_filedef_vtbl = {visitfiledef, freefiledef}; - -upb_filedef *upb_filedef_new(const void *owner) { - upb_filedef *f = upb_gmalloc(sizeof(*f)); - - if (!f) { - return NULL; - } - - f->package = NULL; - f->name = NULL; - f->phpprefix = NULL; - f->phpnamespace = NULL; - f->syntax = UPB_SYNTAX_PROTO2; - - if (!upb_refcounted_init(upb_filedef_upcast_mutable(f), &upb_filedef_vtbl, - owner)) { - goto err; - } - - if (!upb_inttable_init(&f->defs, UPB_CTYPE_CONSTPTR)) { - goto err; - } - - if (!upb_inttable_init(&f->deps, UPB_CTYPE_CONSTPTR)) { - goto err2; - } - - return f; - - -err2: - upb_inttable_uninit(&f->defs); - -err: - upb_gfree(f); - return NULL; -} - -const char *upb_filedef_name(const upb_filedef *f) { - return f->name; -} - -const char *upb_filedef_package(const upb_filedef *f) { - return f->package; -} - -const char *upb_filedef_phpprefix(const upb_filedef *f) { - return f->phpprefix; -} - -const char *upb_filedef_phpnamespace(const upb_filedef *f) { - return f->phpnamespace; -} - -upb_syntax_t upb_filedef_syntax(const upb_filedef *f) { - return f->syntax; -} - -size_t upb_filedef_defcount(const upb_filedef *f) { - return upb_inttable_count(&f->defs); -} - -size_t upb_filedef_depcount(const upb_filedef *f) { - return upb_inttable_count(&f->deps); -} - -const upb_def *upb_filedef_def(const upb_filedef *f, size_t i) { - upb_value v; - - if (upb_inttable_lookup32(&f->defs, i, &v)) { - return upb_value_getconstptr(v); - } else { - return NULL; - } -} - -const upb_filedef *upb_filedef_dep(const upb_filedef *f, size_t i) { - upb_value v; - - if (upb_inttable_lookup32(&f->deps, i, &v)) { - return upb_value_getconstptr(v); - } else { - return NULL; - } -} - -bool upb_filedef_setname(upb_filedef *f, const char *name, upb_status *s) { - name = upb_gstrdup(name); - if (!name) { - upb_upberr_setoom(s); - return false; - } - upb_gfree((void*)f->name); - f->name = name; - return true; -} - -bool upb_filedef_setpackage(upb_filedef *f, const char *package, - upb_status *s) { - if (!upb_isident(package, strlen(package), true, s)) return false; - package = upb_gstrdup(package); - if (!package) { - upb_upberr_setoom(s); - return false; - } - upb_gfree((void*)f->package); - f->package = package; - return true; -} - -bool upb_filedef_setphpprefix(upb_filedef *f, const char *phpprefix, - upb_status *s) { - phpprefix = upb_gstrdup(phpprefix); - if (!phpprefix) { - upb_upberr_setoom(s); - return false; - } - upb_gfree((void*)f->phpprefix); - f->phpprefix = phpprefix; - return true; -} - -bool upb_filedef_setphpnamespace(upb_filedef *f, const char *phpnamespace, - upb_status *s) { - phpnamespace = upb_gstrdup(phpnamespace); - if (!phpnamespace) { - upb_upberr_setoom(s); - return false; - } - upb_gfree((void*)f->phpnamespace); - f->phpnamespace = phpnamespace; - return true; -} - -bool upb_filedef_setsyntax(upb_filedef *f, upb_syntax_t syntax, - upb_status *s) { - UPB_UNUSED(s); - if (syntax != UPB_SYNTAX_PROTO2 && - syntax != UPB_SYNTAX_PROTO3) { - upb_status_seterrmsg(s, "Unknown syntax value."); - return false; - } - f->syntax = syntax; - - { - /* Set all messages in this file to match. */ - size_t i; - for (i = 0; i < upb_filedef_defcount(f); i++) { - /* Casting const away is safe since all defs in mutable filedef must - * also be mutable. */ - upb_def *def = (upb_def*)upb_filedef_def(f, i); - - upb_msgdef *m = upb_dyncast_msgdef_mutable(def); - if (m) { - m->syntax = syntax; - } - } - } - - return true; -} - -bool upb_filedef_adddef(upb_filedef *f, upb_def *def, const void *ref_donor, - upb_status *s) { - if (def->file) { - upb_status_seterrmsg(s, "Def is already part of another filedef."); - return false; - } - - if (upb_inttable_push(&f->defs, upb_value_constptr(def))) { - def->file = f; - upb_ref2(def, f); - upb_ref2(f, def); - if (ref_donor) upb_def_unref(def, ref_donor); - if (def->type == UPB_DEF_MSG) { - upb_downcast_msgdef_mutable(def)->syntax = f->syntax; - } - return true; - } else { - upb_upberr_setoom(s); - return false; - } -} - -bool upb_filedef_adddep(upb_filedef *f, const upb_filedef *dep) { - if (upb_inttable_push(&f->deps, upb_value_constptr(dep))) { - /* Regular ref instead of ref2 because files can't form cycles. */ - upb_filedef_ref(dep, f); - return true; - } else { - return false; - } -} - -void upb_symtab_free(upb_symtab *s) { - upb_strtable_iter i; - upb_strtable_begin(&i, &s->symtab); - for (; !upb_strtable_done(&i); upb_strtable_next(&i)) { - const upb_def *def = upb_value_getptr(upb_strtable_iter_value(&i)); - upb_def_unref(def, s); - } - upb_strtable_uninit(&s->symtab); - upb_gfree(s); -} - -upb_symtab *upb_symtab_new() { - upb_symtab *s = upb_gmalloc(sizeof(*s)); - if (!s) { - return NULL; - } - - upb_strtable_init(&s->symtab, UPB_CTYPE_PTR); - return s; -} - -const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym) { - upb_value v; - upb_def *ret = upb_strtable_lookup(&s->symtab, sym, &v) ? - upb_value_getptr(v) : NULL; - return ret; -} - -const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) { - upb_value v; - upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ? - upb_value_getptr(v) : NULL; - return def ? upb_dyncast_msgdef(def) : NULL; -} - -const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) { - upb_value v; - upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ? - upb_value_getptr(v) : NULL; - return def ? upb_dyncast_enumdef(def) : NULL; -} - -/* Given a symbol and the base symbol inside which it is defined, find the - * symbol's definition in t. */ -static upb_def *upb_resolvename(const upb_strtable *t, - const char *base, const char *sym) { - if(strlen(sym) == 0) return NULL; - if(sym[0] == '.') { - /* Symbols starting with '.' are absolute, so we do a single lookup. - * Slice to omit the leading '.' */ - upb_value v; - return upb_strtable_lookup(t, sym + 1, &v) ? upb_value_getptr(v) : NULL; - } else { - /* Remove components from base until we find an entry or run out. - * TODO: This branch is totally broken, but currently not used. */ - (void)base; - UPB_ASSERT(false); - return NULL; - } -} - -const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, - const char *sym) { - upb_def *ret = upb_resolvename(&s->symtab, base, sym); - return ret; -} - -/* TODO(haberman): we need a lot more testing of error conditions. */ -static bool symtab_add(upb_symtab *s, upb_def *const*defs, size_t n, - void *ref_donor, upb_refcounted *freeze_also, - upb_status *status) { - size_t i; - size_t add_n; - size_t freeze_n; - upb_strtable_iter iter; - upb_refcounted **add_objs = NULL; - upb_def **add_defs = NULL; - size_t add_objs_size; - upb_strtable addtab; - - if (n == 0 && !freeze_also) { - return true; - } - - if (!upb_strtable_init(&addtab, UPB_CTYPE_PTR)) { - upb_status_seterrmsg(status, "out of memory"); - return false; - } - - /* Add new defs to our "add" set. */ - for (i = 0; i < n; i++) { - upb_def *def = defs[i]; - const char *fullname; - upb_fielddef *f; - - if (upb_def_isfrozen(def)) { - upb_status_seterrmsg(status, "added defs must be mutable"); - goto err; - } - UPB_ASSERT(!upb_def_isfrozen(def)); - fullname = upb_def_fullname(def); - if (!fullname) { - upb_status_seterrmsg( - status, "Anonymous defs cannot be added to a symtab"); - goto err; - } - - f = upb_dyncast_fielddef_mutable(def); - - if (f) { - if (!upb_fielddef_containingtypename(f)) { - upb_status_seterrmsg(status, - "Standalone fielddefs must have a containing type " - "(extendee) name set"); - goto err; - } - } else { - if (upb_strtable_lookup(&addtab, fullname, NULL)) { - upb_status_seterrf(status, "Conflicting defs named '%s'", fullname); - goto err; - } - if (upb_strtable_lookup(&s->symtab, fullname, NULL)) { - upb_status_seterrf(status, "Symtab already has a def named '%s'", - fullname); - goto err; - } - if (!upb_strtable_insert(&addtab, fullname, upb_value_ptr(def))) - goto oom_err; - upb_def_donateref(def, ref_donor, s); - } - - if (upb_dyncast_fielddef_mutable(def)) { - /* TODO(haberman): allow adding extensions attached to files. */ - upb_status_seterrf(status, "Can't add extensions to symtab.\n"); - goto err; - } - } - - /* Now using the table, resolve symbolic references for subdefs. */ - upb_strtable_begin(&iter, &addtab); - for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { - const char *base; - upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter)); - upb_msgdef *m = upb_dyncast_msgdef_mutable(def); - upb_msg_field_iter j; - - if (!m) continue; - /* Type names are resolved relative to the message in which they appear. */ - base = upb_msgdef_fullname(m); - - for(upb_msg_field_begin(&j, m); - !upb_msg_field_done(&j); - upb_msg_field_next(&j)) { - upb_fielddef *f = upb_msg_iter_field(&j); - const char *name = upb_fielddef_subdefname(f); - if (name && !upb_fielddef_subdef(f)) { - /* Try the lookup in the current set of to-be-added defs first. If not - * there, try existing defs. */ - upb_def *subdef = upb_resolvename(&addtab, base, name); - if (subdef == NULL) { - subdef = upb_resolvename(&s->symtab, base, name); - } - if (subdef == NULL) { - upb_status_seterrf( - status, "couldn't resolve name '%s' in message '%s'", name, base); - goto err; - } else if (!upb_fielddef_setsubdef(f, subdef, status)) { - goto err; - } - } - } - } - - /* We need an array of the defs in addtab, for passing to - * upb_refcounted_freeze(). */ - add_objs_size = upb_strtable_count(&addtab); - if (freeze_also) { - add_objs_size++; - } - - add_defs = upb_gmalloc(sizeof(void*) * add_objs_size); - if (add_defs == NULL) goto oom_err; - upb_strtable_begin(&iter, &addtab); - for (add_n = 0; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { - add_defs[add_n++] = upb_value_getptr(upb_strtable_iter_value(&iter)); - } - - /* Validate defs. */ - if (!_upb_def_validate(add_defs, add_n, status)) { - goto err; - } - - /* Cheat a little and give the array a new type. - * This is probably undefined behavior, but this code will be deleted soon. */ - add_objs = (upb_refcounted**)add_defs; - - freeze_n = add_n; - if (freeze_also) { - add_objs[freeze_n++] = freeze_also; - } - - if (!upb_refcounted_freeze(add_objs, freeze_n, status, - UPB_MAX_MESSAGE_DEPTH * 2)) { - goto err; - } - - /* This must be delayed until all errors have been detected, since error - * recovery code uses this table to cleanup defs. */ - upb_strtable_uninit(&addtab); - - /* TODO(haberman) we don't properly handle errors after this point (like - * OOM in upb_strtable_insert() below). */ - for (i = 0; i < add_n; i++) { - upb_def *def = (upb_def*)add_objs[i]; - const char *name = upb_def_fullname(def); - bool success; - success = upb_strtable_insert(&s->symtab, name, upb_value_ptr(def)); - UPB_ASSERT(success); - } - upb_gfree(add_defs); - return true; - -oom_err: - upb_status_seterrmsg(status, "out of memory"); -err: { - /* We need to donate the refs back. */ - upb_strtable_begin(&iter, &addtab); - for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { - upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter)); - upb_def_donateref(def, s, ref_donor); - } - } - upb_strtable_uninit(&addtab); - upb_gfree(add_defs); - UPB_ASSERT(!upb_ok(status)); - return false; -} - -bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, size_t n, - void *ref_donor, upb_status *status) { - return symtab_add(s, defs, n, ref_donor, NULL, status); -} - -bool upb_symtab_addfile(upb_symtab *s, upb_filedef *file, upb_status *status) { - size_t n; - size_t i; - upb_def **defs; - bool ret; - - n = upb_filedef_defcount(file); - if (n == 0) { - return true; - } - defs = upb_gmalloc(sizeof(*defs) * n); - - if (defs == NULL) { - upb_status_seterrmsg(status, "Out of memory"); - return false; - } - - for (i = 0; i < n; i++) { - defs[i] = upb_filedef_mutabledef(file, i); - } - - ret = symtab_add(s, defs, n, NULL, upb_filedef_upcast_mutable(file), status); - - upb_gfree(defs); - return ret; -} - -/* Iteration. */ - -static void advance_to_matching(upb_symtab_iter *iter) { - if (iter->type == UPB_DEF_ANY) - return; - - while (!upb_strtable_done(&iter->iter) && - iter->type != upb_symtab_iter_def(iter)->type) { - upb_strtable_next(&iter->iter); - } -} - -void upb_symtab_begin(upb_symtab_iter *iter, const upb_symtab *s, - upb_deftype_t type) { - upb_strtable_begin(&iter->iter, &s->symtab); - iter->type = type; - advance_to_matching(iter); -} - -void upb_symtab_next(upb_symtab_iter *iter) { - upb_strtable_next(&iter->iter); - advance_to_matching(iter); -} - -bool upb_symtab_done(const upb_symtab_iter *iter) { - return upb_strtable_done(&iter->iter); -} - -const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) { - return upb_value_getptr(upb_strtable_iter_value(&iter->iter)); -} -/* -** TODO(haberman): it's unclear whether a lot of the consistency checks should -** UPB_ASSERT() or return false. -*/ - - -#include - - -static void *upb_calloc(size_t size) { - void *mem = upb_gmalloc(size); - if (mem) { - memset(mem, 0, size); - } - return mem; -} - -/* Defined for the sole purpose of having a unique pointer value for - * UPB_NO_CLOSURE. */ -char _upb_noclosure; - -static void freehandlers(upb_refcounted *r) { - upb_handlers *h = (upb_handlers*)r; - - upb_inttable_iter i; - upb_inttable_begin(&i, &h->cleanup_); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - void *val = (void*)upb_inttable_iter_key(&i); - upb_value func_val = upb_inttable_iter_value(&i); - upb_handlerfree *func = upb_value_getfptr(func_val); - func(val); - } - - upb_inttable_uninit(&h->cleanup_); - upb_msgdef_unref(h->msg, h); - upb_gfree(h->sub); - upb_gfree(h); -} - -static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_handlers *h = (const upb_handlers*)r; - upb_msg_field_iter i; - for(upb_msg_field_begin(&i, h->msg); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - const upb_handlers *sub; - if (!upb_fielddef_issubmsg(f)) continue; - sub = upb_handlers_getsubhandlers(h, f); - if (sub) visit(r, upb_handlers_upcast(sub), closure); - } -} - -static const struct upb_refcounted_vtbl vtbl = {visithandlers, freehandlers}; - -typedef struct { - upb_inttable tab; /* maps upb_msgdef* -> upb_handlers*. */ - upb_handlers_callback *callback; - const void *closure; -} dfs_state; - -/* TODO(haberman): discard upb_handlers* objects that do not actually have any - * handlers set and cannot reach any upb_handlers* object that does. This is - * slightly tricky to do correctly. */ -static upb_handlers *newformsg(const upb_msgdef *m, const void *owner, - dfs_state *s) { - upb_msg_field_iter i; - upb_handlers *h = upb_handlers_new(m, owner); - if (!h) return NULL; - if (!upb_inttable_insertptr(&s->tab, m, upb_value_ptr(h))) goto oom; - - s->callback(s->closure, h); - - /* For each submessage field, get or create a handlers object and set it as - * the subhandlers. */ - for(upb_msg_field_begin(&i, m); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - const upb_msgdef *subdef; - upb_value subm_ent; - - if (!upb_fielddef_issubmsg(f)) continue; - - subdef = upb_downcast_msgdef(upb_fielddef_subdef(f)); - if (upb_inttable_lookupptr(&s->tab, subdef, &subm_ent)) { - upb_handlers_setsubhandlers(h, f, upb_value_getptr(subm_ent)); - } else { - upb_handlers *sub_mh = newformsg(subdef, &sub_mh, s); - if (!sub_mh) goto oom; - upb_handlers_setsubhandlers(h, f, sub_mh); - upb_handlers_unref(sub_mh, &sub_mh); - } - } - return h; - -oom: - upb_handlers_unref(h, owner); - return NULL; -} - -/* Given a selector for a STARTSUBMSG handler, resolves to a pointer to the - * subhandlers for this submessage field. */ -#define SUBH(h, selector) (h->sub[selector]) - -/* The selector for a submessage field is the field index. */ -#define SUBH_F(h, f) SUBH(h, f->index_) - -static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f, - upb_handlertype_t type) { - upb_selector_t sel; - UPB_ASSERT(!upb_handlers_isfrozen(h)); - if (upb_handlers_msgdef(h) != upb_fielddef_containingtype(f)) { - upb_status_seterrf( - &h->status_, "type mismatch: field %s does not belong to message %s", - upb_fielddef_name(f), upb_msgdef_fullname(upb_handlers_msgdef(h))); - return -1; - } - if (!upb_handlers_getselector(f, type, &sel)) { - upb_status_seterrf( - &h->status_, - "type mismatch: cannot register handler type %d for field %s", - type, upb_fielddef_name(f)); - return -1; - } - return sel; -} - -static upb_selector_t handlers_getsel(upb_handlers *h, const upb_fielddef *f, - upb_handlertype_t type) { - int32_t sel = trygetsel(h, f, type); - UPB_ASSERT(sel >= 0); - return sel; -} - -static const void **returntype(upb_handlers *h, const upb_fielddef *f, - upb_handlertype_t type) { - return &h->table[handlers_getsel(h, f, type)].attr.return_closure_type_; -} - -static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f, - upb_handlertype_t type, upb_func *func, - upb_handlerattr *attr) { - upb_handlerattr set_attr = UPB_HANDLERATTR_INITIALIZER; - const void *closure_type; - const void **context_closure_type; - - UPB_ASSERT(!upb_handlers_isfrozen(h)); - - if (sel < 0) { - upb_status_seterrmsg(&h->status_, - "incorrect handler type for this field."); - return false; - } - - if (h->table[sel].func) { - upb_status_seterrmsg(&h->status_, - "cannot change handler once it has been set."); - return false; - } - - if (attr) { - set_attr = *attr; - } - - /* Check that the given closure type matches the closure type that has been - * established for this context (if any). */ - closure_type = upb_handlerattr_closuretype(&set_attr); - - if (type == UPB_HANDLER_STRING) { - context_closure_type = returntype(h, f, UPB_HANDLER_STARTSTR); - } else if (f && upb_fielddef_isseq(f) && - type != UPB_HANDLER_STARTSEQ && - type != UPB_HANDLER_ENDSEQ) { - context_closure_type = returntype(h, f, UPB_HANDLER_STARTSEQ); - } else { - context_closure_type = &h->top_closure_type; - } - - if (closure_type && *context_closure_type && - closure_type != *context_closure_type) { - /* TODO(haberman): better message for debugging. */ - if (f) { - upb_status_seterrf(&h->status_, - "closure type does not match for field %s", - upb_fielddef_name(f)); - } else { - upb_status_seterrmsg( - &h->status_, "closure type does not match for message-level handler"); - } - return false; - } - - if (closure_type) - *context_closure_type = closure_type; - - /* If this is a STARTSEQ or STARTSTR handler, check that the returned pointer - * matches any pre-existing expectations about what type is expected. */ - if (type == UPB_HANDLER_STARTSEQ || type == UPB_HANDLER_STARTSTR) { - const void *return_type = upb_handlerattr_returnclosuretype(&set_attr); - const void *table_return_type = - upb_handlerattr_returnclosuretype(&h->table[sel].attr); - if (return_type && table_return_type && return_type != table_return_type) { - upb_status_seterrmsg(&h->status_, "closure return type does not match"); - return false; - } - - if (table_return_type && !return_type) - upb_handlerattr_setreturnclosuretype(&set_attr, table_return_type); - } - - h->table[sel].func = (upb_func*)func; - h->table[sel].attr = set_attr; - return true; -} - -/* Returns the effective closure type for this handler (which will propagate - * from outer frames if this frame has no START* handler). Not implemented for - * UPB_HANDLER_STRING at the moment since this is not needed. Returns NULL is - * the effective closure type is unspecified (either no handler was registered - * to specify it or the handler that was registered did not specify the closure - * type). */ -const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f, - upb_handlertype_t type) { - const void *ret; - upb_selector_t sel; - - UPB_ASSERT(type != UPB_HANDLER_STRING); - ret = h->top_closure_type; - - if (upb_fielddef_isseq(f) && - type != UPB_HANDLER_STARTSEQ && - type != UPB_HANDLER_ENDSEQ && - h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)].func) { - ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr); - } - - if (type == UPB_HANDLER_STRING && - h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSTR)].func) { - ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr); - } - - /* The effective type of the submessage; not used yet. - * if (type == SUBMESSAGE && - * h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) { - * ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr); - * } */ - - return ret; -} - -/* Checks whether the START* handler specified by f & type is missing even - * though it is required to convert the established type of an outer frame - * ("closure_type") into the established type of an inner frame (represented in - * the return closure type of this handler's attr. */ -bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type, - upb_status *status) { - const void *closure_type; - const upb_handlerattr *attr; - const void *return_closure_type; - - upb_selector_t sel = handlers_getsel(h, f, type); - if (h->table[sel].func) return true; - closure_type = effective_closure_type(h, f, type); - attr = &h->table[sel].attr; - return_closure_type = upb_handlerattr_returnclosuretype(attr); - if (closure_type && return_closure_type && - closure_type != return_closure_type) { - upb_status_seterrf(status, - "expected start handler to return sub type for field %f", - upb_fielddef_name(f)); - return false; - } - return true; -} - -/* Public interface ***********************************************************/ - -upb_handlers *upb_handlers_new(const upb_msgdef *md, const void *owner) { - int extra; - upb_handlers *h; - - UPB_ASSERT(upb_msgdef_isfrozen(md)); - - extra = sizeof(upb_handlers_tabent) * (md->selector_count - 1); - h = upb_calloc(sizeof(*h) + extra); - if (!h) return NULL; - - h->msg = md; - upb_msgdef_ref(h->msg, h); - upb_status_clear(&h->status_); - - if (md->submsg_field_count > 0) { - h->sub = upb_calloc(md->submsg_field_count * sizeof(*h->sub)); - if (!h->sub) goto oom; - } else { - h->sub = 0; - } - - if (!upb_refcounted_init(upb_handlers_upcast_mutable(h), &vtbl, owner)) - goto oom; - if (!upb_inttable_init(&h->cleanup_, UPB_CTYPE_FPTR)) goto oom; - - /* calloc() above initialized all handlers to NULL. */ - return h; - -oom: - freehandlers(upb_handlers_upcast_mutable(h)); - return NULL; -} - -const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m, - const void *owner, - upb_handlers_callback *callback, - const void *closure) { - dfs_state state; - upb_handlers *ret; - bool ok; - upb_refcounted *r; - - state.callback = callback; - state.closure = closure; - if (!upb_inttable_init(&state.tab, UPB_CTYPE_PTR)) return NULL; - - ret = newformsg(m, owner, &state); - - upb_inttable_uninit(&state.tab); - if (!ret) return NULL; - - r = upb_handlers_upcast_mutable(ret); - ok = upb_refcounted_freeze(&r, 1, NULL, UPB_MAX_HANDLER_DEPTH); - UPB_ASSERT(ok); - - return ret; -} - -const upb_status *upb_handlers_status(upb_handlers *h) { - UPB_ASSERT(!upb_handlers_isfrozen(h)); - return &h->status_; -} - -void upb_handlers_clearerr(upb_handlers *h) { - UPB_ASSERT(!upb_handlers_isfrozen(h)); - upb_status_clear(&h->status_); -} - -#define SETTER(name, handlerctype, handlertype) \ - bool upb_handlers_set ## name(upb_handlers *h, const upb_fielddef *f, \ - handlerctype func, upb_handlerattr *attr) { \ - int32_t sel = trygetsel(h, f, handlertype); \ - return doset(h, sel, f, handlertype, (upb_func*)func, attr); \ - } - -SETTER(int32, upb_int32_handlerfunc*, UPB_HANDLER_INT32) -SETTER(int64, upb_int64_handlerfunc*, UPB_HANDLER_INT64) -SETTER(uint32, upb_uint32_handlerfunc*, UPB_HANDLER_UINT32) -SETTER(uint64, upb_uint64_handlerfunc*, UPB_HANDLER_UINT64) -SETTER(float, upb_float_handlerfunc*, UPB_HANDLER_FLOAT) -SETTER(double, upb_double_handlerfunc*, UPB_HANDLER_DOUBLE) -SETTER(bool, upb_bool_handlerfunc*, UPB_HANDLER_BOOL) -SETTER(startstr, upb_startstr_handlerfunc*, UPB_HANDLER_STARTSTR) -SETTER(string, upb_string_handlerfunc*, UPB_HANDLER_STRING) -SETTER(endstr, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSTR) -SETTER(startseq, upb_startfield_handlerfunc*, UPB_HANDLER_STARTSEQ) -SETTER(startsubmsg, upb_startfield_handlerfunc*, UPB_HANDLER_STARTSUBMSG) -SETTER(endsubmsg, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSUBMSG) -SETTER(endseq, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSEQ) - -#undef SETTER - -bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func, - upb_handlerattr *attr) { - return doset(h, UPB_STARTMSG_SELECTOR, NULL, UPB_HANDLER_INT32, - (upb_func *)func, attr); -} - -bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func, - upb_handlerattr *attr) { - UPB_ASSERT(!upb_handlers_isfrozen(h)); - return doset(h, UPB_ENDMSG_SELECTOR, NULL, UPB_HANDLER_INT32, - (upb_func *)func, attr); -} - -bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f, - const upb_handlers *sub) { - UPB_ASSERT(sub); - UPB_ASSERT(!upb_handlers_isfrozen(h)); - UPB_ASSERT(upb_fielddef_issubmsg(f)); - if (SUBH_F(h, f)) return false; /* Can't reset. */ - if (upb_msgdef_upcast(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) { - return false; - } - SUBH_F(h, f) = sub; - upb_ref2(sub, h); - return true; -} - -const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h, - const upb_fielddef *f) { - UPB_ASSERT(upb_fielddef_issubmsg(f)); - return SUBH_F(h, f); -} - -bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t sel, - upb_handlerattr *attr) { - if (!upb_handlers_gethandler(h, sel)) - return false; - *attr = h->table[sel].attr; - return true; -} - -const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h, - upb_selector_t sel) { - /* STARTSUBMSG selector in sel is the field's selector base. */ - return SUBH(h, sel - UPB_STATIC_SELECTOR_COUNT); -} - -const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; } - -bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) { - bool ok; - if (upb_inttable_lookupptr(&h->cleanup_, p, NULL)) { - return false; - } - ok = upb_inttable_insertptr(&h->cleanup_, p, upb_value_fptr(func)); - UPB_ASSERT(ok); - return true; -} - - -/* "Static" methods ***********************************************************/ - -bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) { - /* TODO: verify we have a transitive closure. */ - int i; - for (i = 0; i < n; i++) { - upb_msg_field_iter j; - upb_handlers *h = handlers[i]; - - if (!upb_ok(&h->status_)) { - upb_status_seterrf(s, "handlers for message %s had error status: %s", - upb_msgdef_fullname(upb_handlers_msgdef(h)), - upb_status_errmsg(&h->status_)); - return false; - } - - /* Check that there are no closure mismatches due to missing Start* handlers - * or subhandlers with different type-level types. */ - for(upb_msg_field_begin(&j, h->msg); - !upb_msg_field_done(&j); - upb_msg_field_next(&j)) { - - const upb_fielddef *f = upb_msg_iter_field(&j); - if (upb_fielddef_isseq(f)) { - if (!checkstart(h, f, UPB_HANDLER_STARTSEQ, s)) - return false; - } - - if (upb_fielddef_isstring(f)) { - if (!checkstart(h, f, UPB_HANDLER_STARTSTR, s)) - return false; - } - - if (upb_fielddef_issubmsg(f)) { - bool hashandler = false; - if (upb_handlers_gethandler( - h, handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)) || - upb_handlers_gethandler( - h, handlers_getsel(h, f, UPB_HANDLER_ENDSUBMSG))) { - hashandler = true; - } - - if (upb_fielddef_isseq(f) && - (upb_handlers_gethandler( - h, handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)) || - upb_handlers_gethandler( - h, handlers_getsel(h, f, UPB_HANDLER_ENDSEQ)))) { - hashandler = true; - } - - if (hashandler && !upb_handlers_getsubhandlers(h, f)) { - /* For now we add an empty subhandlers in this case. It makes the - * decoder code generator simpler, because it only has to handle two - * cases (submessage has handlers or not) as opposed to three - * (submessage has handlers in enclosing message but no subhandlers). - * - * This makes parsing less efficient in the case that we want to - * notice a submessage but skip its contents (like if we're testing - * for submessage presence or counting the number of repeated - * submessages). In this case we will end up parsing the submessage - * field by field and throwing away the results for each, instead of - * skipping the whole delimited thing at once. If this is an issue we - * can revisit it, but do remember that this only arises when you have - * handlers (startseq/startsubmsg/endsubmsg/endseq) set for the - * submessage but no subhandlers. The uses cases for this are - * limited. */ - upb_handlers *sub = upb_handlers_new(upb_fielddef_msgsubdef(f), &sub); - upb_handlers_setsubhandlers(h, f, sub); - upb_handlers_unref(sub, &sub); - } - - /* TODO(haberman): check type of submessage. - * This is slightly tricky; also consider whether we should check that - * they match at setsubhandlers time. */ - } - } - } - - if (!upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s, - UPB_MAX_HANDLER_DEPTH)) { - return false; - } - - return true; -} - -upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) { - switch (upb_fielddef_type(f)) { - case UPB_TYPE_INT32: - case UPB_TYPE_ENUM: return UPB_HANDLER_INT32; - case UPB_TYPE_INT64: return UPB_HANDLER_INT64; - case UPB_TYPE_UINT32: return UPB_HANDLER_UINT32; - case UPB_TYPE_UINT64: return UPB_HANDLER_UINT64; - case UPB_TYPE_FLOAT: return UPB_HANDLER_FLOAT; - case UPB_TYPE_DOUBLE: return UPB_HANDLER_DOUBLE; - case UPB_TYPE_BOOL: return UPB_HANDLER_BOOL; - default: UPB_ASSERT(false); return -1; /* Invalid input. */ - } -} - -bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type, - upb_selector_t *s) { - switch (type) { - case UPB_HANDLER_INT32: - case UPB_HANDLER_INT64: - case UPB_HANDLER_UINT32: - case UPB_HANDLER_UINT64: - case UPB_HANDLER_FLOAT: - case UPB_HANDLER_DOUBLE: - case UPB_HANDLER_BOOL: - if (!upb_fielddef_isprimitive(f) || - upb_handlers_getprimitivehandlertype(f) != type) - return false; - *s = f->selector_base; - break; - case UPB_HANDLER_STRING: - if (upb_fielddef_isstring(f)) { - *s = f->selector_base; - } else if (upb_fielddef_lazy(f)) { - *s = f->selector_base + 3; - } else { - return false; - } - break; - case UPB_HANDLER_STARTSTR: - if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) { - *s = f->selector_base + 1; - } else { - return false; - } - break; - case UPB_HANDLER_ENDSTR: - if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) { - *s = f->selector_base + 2; - } else { - return false; - } - break; - case UPB_HANDLER_STARTSEQ: - if (!upb_fielddef_isseq(f)) return false; - *s = f->selector_base - 2; - break; - case UPB_HANDLER_ENDSEQ: - if (!upb_fielddef_isseq(f)) return false; - *s = f->selector_base - 1; - break; - case UPB_HANDLER_STARTSUBMSG: - if (!upb_fielddef_issubmsg(f)) return false; - /* Selectors for STARTSUBMSG are at the beginning of the table so that the - * selector can also be used as an index into the "sub" array of - * subhandlers. The indexes for the two into these two tables are the - * same, except that in the handler table the static selectors come first. */ - *s = f->index_ + UPB_STATIC_SELECTOR_COUNT; - break; - case UPB_HANDLER_ENDSUBMSG: - if (!upb_fielddef_issubmsg(f)) return false; - *s = f->selector_base; - break; - } - UPB_ASSERT((size_t)*s < upb_fielddef_containingtype(f)->selector_count); - return true; -} - -uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) { - return upb_fielddef_isseq(f) ? 2 : 0; -} - -uint32_t upb_handlers_selectorcount(const upb_fielddef *f) { - uint32_t ret = 1; - if (upb_fielddef_isseq(f)) ret += 2; /* STARTSEQ/ENDSEQ */ - if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */ - if (upb_fielddef_issubmsg(f)) { - /* ENDSUBMSG (STARTSUBMSG is at table beginning) */ - ret += 0; - if (upb_fielddef_lazy(f)) { - /* STARTSTR/ENDSTR/STRING (for lazy) */ - ret += 3; - } - } - return ret; -} - - -/* upb_handlerattr ************************************************************/ - -void upb_handlerattr_init(upb_handlerattr *attr) { - upb_handlerattr from = UPB_HANDLERATTR_INITIALIZER; - memcpy(attr, &from, sizeof(*attr)); -} - -void upb_handlerattr_uninit(upb_handlerattr *attr) { - UPB_UNUSED(attr); -} - -bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, const void *hd) { - attr->handler_data_ = hd; - return true; -} - -bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type) { - attr->closure_type_ = type; - return true; -} - -const void *upb_handlerattr_closuretype(const upb_handlerattr *attr) { - return attr->closure_type_; -} - -bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr, - const void *type) { - attr->return_closure_type_ = type; - return true; -} - -const void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr) { - return attr->return_closure_type_; -} - -bool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok) { - attr->alwaysok_ = alwaysok; - return true; -} - -bool upb_handlerattr_alwaysok(const upb_handlerattr *attr) { - return attr->alwaysok_; -} - -/* upb_bufhandle **************************************************************/ - -size_t upb_bufhandle_objofs(const upb_bufhandle *h) { - return h->objofs_; -} - -/* upb_byteshandler ***********************************************************/ - -void upb_byteshandler_init(upb_byteshandler* h) { - memset(h, 0, sizeof(*h)); -} - -/* For when we support handlerfree callbacks. */ -void upb_byteshandler_uninit(upb_byteshandler* h) { - UPB_UNUSED(h); -} - -bool upb_byteshandler_setstartstr(upb_byteshandler *h, - upb_startstr_handlerfunc *func, void *d) { - h->table[UPB_STARTSTR_SELECTOR].func = (upb_func*)func; - h->table[UPB_STARTSTR_SELECTOR].attr.handler_data_ = d; - return true; -} - -bool upb_byteshandler_setstring(upb_byteshandler *h, - upb_string_handlerfunc *func, void *d) { - h->table[UPB_STRING_SELECTOR].func = (upb_func*)func; - h->table[UPB_STRING_SELECTOR].attr.handler_data_ = d; - return true; -} - -bool upb_byteshandler_setendstr(upb_byteshandler *h, - upb_endfield_handlerfunc *func, void *d) { - h->table[UPB_ENDSTR_SELECTOR].func = (upb_func*)func; - h->table[UPB_ENDSTR_SELECTOR].attr.handler_data_ = d; - return true; -} - - -static bool is_power_of_two(size_t val) { - return (val & (val - 1)) == 0; -} - -/* Align up to the given power of 2. */ -static size_t align_up(size_t val, size_t align) { - UPB_ASSERT(is_power_of_two(align)); - return (val + align - 1) & ~(align - 1); -} - -static size_t div_round_up(size_t n, size_t d) { - return (n + d - 1) / d; -} - -bool upb_fieldtype_mapkeyok(upb_fieldtype_t type) { - return type == UPB_TYPE_BOOL || type == UPB_TYPE_INT32 || - type == UPB_TYPE_UINT32 || type == UPB_TYPE_INT64 || - type == UPB_TYPE_UINT64 || type == UPB_TYPE_STRING; -} - -void *upb_array_pack(const upb_array *arr, void *p, size_t *ofs, size_t size); -void *upb_map_pack(const upb_map *map, void *p, size_t *ofs, size_t size); - -#define CHARPTR_AT(msg, ofs) ((char*)msg + ofs) -#define ENCODE_MAX_NESTING 64 -#define CHECK_TRUE(x) if (!(x)) { return false; } - -/** upb_msgval ****************************************************************/ - -#define upb_alignof(t) offsetof(struct { char c; t x; }, x) - -/* These functions will generate real memcpy() calls on ARM sadly, because - * the compiler assumes they might not be aligned. */ - -static upb_msgval upb_msgval_read(const void *p, size_t ofs, - uint8_t size) { - upb_msgval val; - p = (char*)p + ofs; - memcpy(&val, p, size); - return val; -} - -static void upb_msgval_write(void *p, size_t ofs, upb_msgval val, - uint8_t size) { - p = (char*)p + ofs; - memcpy(p, &val, size); -} - -static size_t upb_msgval_sizeof(upb_fieldtype_t type) { - switch (type) { - case UPB_TYPE_DOUBLE: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT64: - return 8; - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - case UPB_TYPE_UINT32: - case UPB_TYPE_FLOAT: - return 4; - case UPB_TYPE_BOOL: - return 1; - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - return sizeof(void*); - case UPB_TYPE_STRING: - return sizeof(char*) + sizeof(size_t); - } - UPB_UNREACHABLE(); -} - -static uint8_t upb_msg_fieldsize(const upb_fielddef *f) { - if (upb_fielddef_isseq(f)) { - return sizeof(void*); - } else { - return upb_msgval_sizeof(upb_fielddef_type(f)); - } -} - -/* TODO(haberman): this is broken right now because upb_msgval can contain - * a char* / size_t pair, which is too big for a upb_value. To fix this - * we'll probably need to dynamically allocate a upb_msgval and store a - * pointer to that in the tables for extensions/maps. */ -static upb_value upb_toval(upb_msgval val) { - upb_value ret; - UPB_UNUSED(val); - memset(&ret, 0, sizeof(upb_value)); /* XXX */ - return ret; -} - -static upb_msgval upb_msgval_fromval(upb_value val) { - upb_msgval ret; - UPB_UNUSED(val); - memset(&ret, 0, sizeof(upb_msgval)); /* XXX */ - return ret; -} - -static upb_ctype_t upb_fieldtotabtype(upb_fieldtype_t type) { - switch (type) { - case UPB_TYPE_FLOAT: return UPB_CTYPE_FLOAT; - case UPB_TYPE_DOUBLE: return UPB_CTYPE_DOUBLE; - case UPB_TYPE_BOOL: return UPB_CTYPE_BOOL; - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - case UPB_TYPE_STRING: return UPB_CTYPE_CONSTPTR; - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: return UPB_CTYPE_INT32; - case UPB_TYPE_UINT32: return UPB_CTYPE_UINT32; - case UPB_TYPE_INT64: return UPB_CTYPE_INT64; - case UPB_TYPE_UINT64: return UPB_CTYPE_UINT64; - default: UPB_ASSERT(false); return 0; - } -} - -static upb_msgval upb_msgval_fromdefault(const upb_fielddef *f) { - /* TODO(haberman): improve/optimize this (maybe use upb_msgval in fielddef) */ - switch (upb_fielddef_type(f)) { - case UPB_TYPE_FLOAT: - return upb_msgval_float(upb_fielddef_defaultfloat(f)); - case UPB_TYPE_DOUBLE: - return upb_msgval_double(upb_fielddef_defaultdouble(f)); - case UPB_TYPE_BOOL: - return upb_msgval_bool(upb_fielddef_defaultbool(f)); - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - size_t len; - const char *ptr = upb_fielddef_defaultstr(f, &len); - return upb_msgval_str(ptr, len); - } - case UPB_TYPE_MESSAGE: - return upb_msgval_msg(NULL); - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - return upb_msgval_int32(upb_fielddef_defaultint32(f)); - case UPB_TYPE_UINT32: - return upb_msgval_uint32(upb_fielddef_defaultuint32(f)); - case UPB_TYPE_INT64: - return upb_msgval_int64(upb_fielddef_defaultint64(f)); - case UPB_TYPE_UINT64: - return upb_msgval_uint64(upb_fielddef_defaultuint64(f)); - default: - UPB_ASSERT(false); - return upb_msgval_msg(NULL); - } -} - - -/** upb_msglayout *************************************************************/ - -struct upb_msglayout { - upb_msgfactory *factory; - const upb_msgdef *msgdef; - size_t size; - size_t extdict_offset; - void *default_msg; - uint32_t *field_offsets; - uint32_t *case_offsets; - uint32_t *hasbits; - bool has_extdict; - uint8_t align; -}; - -static void upb_msg_checkfield(const upb_msglayout *l, const upb_fielddef *f) { - UPB_ASSERT(l->msgdef == upb_fielddef_containingtype(f)); -} - -static void upb_msglayout_free(upb_msglayout *l) { - upb_gfree(l->default_msg); - upb_gfree(l); -} - -const upb_msgdef *upb_msglayout_msgdef(const upb_msglayout *l) { - return l->msgdef; -} - -static size_t upb_msglayout_place(upb_msglayout *l, size_t size) { - size_t ret; - - l->size = align_up(l->size, size); - l->align = align_up(l->align, size); - ret = l->size; - l->size += size; - return ret; -} - -static uint32_t upb_msglayout_offset(const upb_msglayout *l, - const upb_fielddef *f) { - return l->field_offsets[upb_fielddef_index(f)]; -} - -static uint32_t upb_msglayout_hasbit(const upb_msglayout *l, - const upb_fielddef *f) { - return l->hasbits[upb_fielddef_index(f)]; -} - -static bool upb_msglayout_initdefault(upb_msglayout *l) { - const upb_msgdef *m = l->msgdef; - upb_msg_field_iter it; - - if (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2 && l->size) { - /* Allocate default message and set default values in it. */ - l->default_msg = upb_gmalloc(l->size); - if (!l->default_msg) { - return false; - } - - memset(l->default_msg, 0, l->size); - - for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* f = upb_msg_iter_field(&it); - - if (upb_fielddef_containingoneof(f)) { - continue; - } - - if (!upb_fielddef_isstring(f) && - !upb_fielddef_issubmsg(f) && - !upb_fielddef_isseq(f)) { - upb_msg_set(l->default_msg, f, upb_msgval_fromdefault(f), l); - } - } - } - - return true; -} - -static upb_msglayout *upb_msglayout_new(const upb_msgdef *m) { - upb_msg_field_iter it; - upb_msg_oneof_iter oit; - upb_msglayout *l; - size_t hasbit; - size_t array_size = upb_msgdef_numfields(m) + upb_msgdef_numoneofs(m); - - if (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2) { - array_size += upb_msgdef_numfields(m); /* hasbits. */ - } - - l = upb_gmalloc(sizeof(*l) + (sizeof(uint32_t) * array_size)); - if (!l) return NULL; - - memset(l, 0, sizeof(*l)); - - l->msgdef = m; - l->align = 1; - l->field_offsets = (uint32_t*)CHARPTR_AT(l, sizeof(*l)); - l->case_offsets = l->field_offsets + upb_msgdef_numfields(m); - l->hasbits = l->case_offsets + upb_msgdef_numoneofs(m); - - /* Allocate data offsets in three stages: - * - * 1. hasbits. - * 2. regular fields. - * 3. oneof fields. - * - * OPT: There is a lot of room for optimization here to minimize the size. - */ - - /* Allocate hasbits. Start at sizeof(void*) for upb_alloc*. */ - for (upb_msg_field_begin(&it, m), hasbit = sizeof(void*) * 8; - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* f = upb_msg_iter_field(&it); - - if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) { - l->hasbits[upb_fielddef_index(f)] = hasbit++; - } - } - - /* Account for space used by hasbits. */ - l->size = div_round_up(hasbit, 8); - - /* Allocate non-oneof fields. */ - for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* f = upb_msg_iter_field(&it); - size_t field_size = upb_msg_fieldsize(f); - size_t index = upb_fielddef_index(f); - - - if (upb_fielddef_containingoneof(f)) { - /* Oneofs are handled separately below. */ - continue; - } - - l->field_offsets[index] = upb_msglayout_place(l, field_size); - } - - /* Allocate oneof fields. Each oneof field consists of a uint32 for the case - * and space for the actual data. */ - for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit); - upb_msg_oneof_next(&oit)) { - const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit); - upb_oneof_iter fit; - size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */ - size_t field_size = 0; - size_t case_offset; - size_t val_offset; - - /* Calculate field size: the max of all field sizes. */ - for (upb_oneof_begin(&fit, oneof); - !upb_oneof_done(&fit); - upb_oneof_next(&fit)) { - const upb_fielddef* f = upb_oneof_iter_field(&fit); - field_size = UPB_MAX(field_size, upb_msg_fieldsize(f)); - } - - /* Align and allocate case offset. */ - case_offset = upb_msglayout_place(l, case_size); - val_offset = upb_msglayout_place(l, field_size); - - l->case_offsets[upb_oneofdef_index(oneof)] = case_offset; - - /* Assign all fields in the oneof this same offset. */ - for (upb_oneof_begin(&fit, oneof); !upb_oneof_done(&fit); - upb_oneof_next(&fit)) { - const upb_fielddef* f = upb_oneof_iter_field(&fit); - l->field_offsets[upb_fielddef_index(f)] = val_offset; - } - } - - /* Size of the entire structure should be a multiple of its greatest - * alignment. */ - l->size = align_up(l->size, l->align); - - if (upb_msglayout_initdefault(l)) { - return l; - } else { - upb_msglayout_free(l); - return NULL; - } -} - -upb_msgfactory *upb_msglayout_factory(const upb_msglayout *layout) { - return layout->factory; -} - - -/** upb_msgfactory ************************************************************/ - -struct upb_msgfactory { - const upb_symtab *symtab; /* We own a ref. */ - upb_inttable layouts; - upb_inttable mergehandlers; -}; - -upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab) { - upb_msgfactory *ret = upb_gmalloc(sizeof(*ret)); - - ret->symtab = symtab; - upb_inttable_init(&ret->layouts, UPB_CTYPE_PTR); - upb_inttable_init(&ret->mergehandlers, UPB_CTYPE_CONSTPTR); - - return ret; -} - -void upb_msgfactory_free(upb_msgfactory *f) { - upb_inttable_iter i; - upb_inttable_begin(&i, &f->layouts); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_msglayout *l = upb_value_getptr(upb_inttable_iter_value(&i)); - upb_msglayout_free(l); - } - - upb_inttable_begin(&i, &f->mergehandlers); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - const upb_handlers *h = upb_value_getconstptr(upb_inttable_iter_value(&i)); - upb_handlers_unref(h, f); - } - - upb_inttable_uninit(&f->layouts); - upb_inttable_uninit(&f->mergehandlers); - upb_gfree(f); -} - -const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f) { - return f->symtab; -} - -const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f, - const upb_msgdef *m) { - upb_value v; - UPB_ASSERT(upb_symtab_lookupmsg(f->symtab, upb_msgdef_fullname(m)) == m); - UPB_ASSERT(!upb_msgdef_mapentry(m)); - - if (upb_inttable_lookupptr(&f->layouts, m, &v)) { - UPB_ASSERT(upb_value_getptr(v)); - return upb_value_getptr(v); - } else { - upb_msgfactory *mutable_f = (void*)f; - upb_msglayout *l = upb_msglayout_new(m); - upb_inttable_insertptr(&mutable_f->layouts, m, upb_value_ptr(l)); - UPB_ASSERT(l); - l->factory = f; - return l; - } -} - -/* Our handlers that we don't expose externally. */ - -void *upb_msg_startstr(void *msg, const void *hd, size_t size_hint) { - uint32_t ofs = (uintptr_t)hd; - /* We pass NULL here because we know we can get away with it. */ - upb_alloc *alloc = upb_msg_alloc(msg, NULL); - upb_msgval val; - UPB_UNUSED(size_hint); - - val = upb_msgval_read(msg, ofs, upb_msgval_sizeof(UPB_TYPE_STRING)); - - upb_free(alloc, (void*)val.str.ptr); - val.str.ptr = NULL; - val.str.len = 0; - - upb_msgval_write(msg, ofs, val, upb_msgval_sizeof(UPB_TYPE_STRING)); - return msg; -} - -size_t upb_msg_str(void *msg, const void *hd, const char *ptr, size_t size, - const upb_bufhandle *handle) { - uint32_t ofs = (uintptr_t)hd; - /* We pass NULL here because we know we can get away with it. */ - upb_alloc *alloc = upb_msg_alloc(msg, NULL); - upb_msgval val; - size_t newsize; - UPB_UNUSED(handle); - - val = upb_msgval_read(msg, ofs, upb_msgval_sizeof(UPB_TYPE_STRING)); - - newsize = val.str.len + size; - val.str.ptr = upb_realloc(alloc, (void*)val.str.ptr, val.str.len, newsize); - - if (!val.str.ptr) { - return false; - } - - memcpy((char*)val.str.ptr + val.str.len, ptr, size); - val.str.len = newsize; - upb_msgval_write(msg, ofs, val, upb_msgval_sizeof(UPB_TYPE_STRING)); - return size; -} - -static void callback(const void *closure, upb_handlers *h) { - upb_msgfactory *factory = (upb_msgfactory*)closure; - const upb_msgdef *md = upb_handlers_msgdef(h); - const upb_msglayout* layout = upb_msgfactory_getlayout(factory, md); - upb_msg_field_iter i; - UPB_UNUSED(factory); - - for(upb_msg_field_begin(&i, md); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - size_t offset = upb_msglayout_offset(layout, f); - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, (void*)offset); - - if (upb_fielddef_isseq(f)) { - } else if (upb_fielddef_isstring(f)) { - upb_handlers_setstartstr(h, f, upb_msg_startstr, &attr); - upb_handlers_setstring(h, f, upb_msg_str, &attr); - } else { - upb_msg_setscalarhandler( - h, f, offset, upb_msglayout_hasbit(layout, f)); - } - } -} - -const upb_handlers *upb_msgfactory_getmergehandlers(upb_msgfactory *f, - const upb_msgdef *m) { - upb_msgfactory *mutable_f = (void*)f; - - /* TODO(haberman): properly cache these. */ - const upb_handlers *ret = upb_handlers_newfrozen(m, f, callback, f); - upb_inttable_push(&mutable_f->mergehandlers, upb_value_constptr(ret)); - - return ret; -} - -const upb_visitorplan *upb_msgfactory_getvisitorplan(upb_msgfactory *f, - const upb_handlers *h) { - const upb_msgdef *md = upb_handlers_msgdef(h); - return (const upb_visitorplan*)upb_msgfactory_getlayout(f, md); -} - - -/** upb_visitor ***************************************************************/ - -struct upb_visitor { - const upb_msglayout *layout; - upb_sink *sink; -}; - -static upb_selector_t getsel2(const upb_fielddef *f, upb_handlertype_t type) { - upb_selector_t ret; - bool ok = upb_handlers_getselector(f, type, &ret); - UPB_ASSERT(ok); - return ret; -} - -static bool upb_visitor_hasfield(const upb_msg *msg, const upb_fielddef *f, - const upb_msglayout *layout) { - if (upb_fielddef_isseq(f)) { - return upb_msgval_getarr(upb_msg_get(msg, f, layout)) != NULL; - } else if (upb_msgdef_syntax(upb_fielddef_containingtype(f)) == - UPB_SYNTAX_PROTO2) { - return upb_msg_has(msg, f, layout); - } else { - upb_msgval val = upb_msg_get(msg, f, layout); - switch (upb_fielddef_type(f)) { - case UPB_TYPE_FLOAT: - return upb_msgval_getfloat(val) != 0; - case UPB_TYPE_DOUBLE: - return upb_msgval_getdouble(val) != 0; - case UPB_TYPE_BOOL: - return upb_msgval_getbool(val); - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - return upb_msgval_getint32(val) != 0; - case UPB_TYPE_UINT32: - return upb_msgval_getuint32(val) != 0; - case UPB_TYPE_INT64: - return upb_msgval_getint64(val) != 0; - case UPB_TYPE_UINT64: - return upb_msgval_getuint64(val) != 0; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - return upb_msgval_getstr(val) && upb_msgval_getstrlen(val) > 0; - case UPB_TYPE_MESSAGE: - return upb_msgval_getmsg(val) != NULL; - } - UPB_UNREACHABLE(); - } -} - -static bool upb_visitor_visitmsg2(const upb_msg *msg, - const upb_msglayout *layout, upb_sink *sink, - int depth) { - const upb_msgdef *md = upb_msglayout_msgdef(layout); - upb_msg_field_iter i; - upb_status status; - - upb_sink_startmsg(sink); - - /* Protect against cycles (possible because users may freely reassign message - * and repeated fields) by imposing a maximum recursion depth. */ - if (depth > ENCODE_MAX_NESTING) { - return false; - } - - for (upb_msg_field_begin(&i, md); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - upb_msgval val; - - if (!upb_visitor_hasfield(msg, f, layout)) { - continue; - } - - val = upb_msg_get(msg, f, layout); - - if (upb_fielddef_isseq(f)) { - const upb_array *arr = upb_msgval_getarr(val); - UPB_ASSERT(arr); - /* TODO: putary(ary, f, sink, depth);*/ - } else if (upb_fielddef_issubmsg(f)) { - const upb_map *map = upb_msgval_getmap(val); - UPB_ASSERT(map); - /* TODO: putmap(map, f, sink, depth);*/ - } else if (upb_fielddef_isstring(f)) { - /* TODO putstr(); */ - } else { - upb_selector_t sel = getsel2(f, upb_handlers_getprimitivehandlertype(f)); - UPB_ASSERT(upb_fielddef_isprimitive(f)); - - switch (upb_fielddef_type(f)) { - case UPB_TYPE_FLOAT: - CHECK_TRUE(upb_sink_putfloat(sink, sel, upb_msgval_getfloat(val))); - break; - case UPB_TYPE_DOUBLE: - CHECK_TRUE(upb_sink_putdouble(sink, sel, upb_msgval_getdouble(val))); - break; - case UPB_TYPE_BOOL: - CHECK_TRUE(upb_sink_putbool(sink, sel, upb_msgval_getbool(val))); - break; - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - CHECK_TRUE(upb_sink_putint32(sink, sel, upb_msgval_getint32(val))); - break; - case UPB_TYPE_UINT32: - CHECK_TRUE(upb_sink_putuint32(sink, sel, upb_msgval_getuint32(val))); - break; - case UPB_TYPE_INT64: - CHECK_TRUE(upb_sink_putint64(sink, sel, upb_msgval_getint64(val))); - break; - case UPB_TYPE_UINT64: - CHECK_TRUE(upb_sink_putuint64(sink, sel, upb_msgval_getuint64(val))); - break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - UPB_UNREACHABLE(); - } - } - } - - upb_sink_endmsg(sink, &status); - return true; -} - -upb_visitor *upb_visitor_create(upb_env *e, const upb_visitorplan *vp, - upb_sink *output) { - upb_visitor *visitor = upb_env_malloc(e, sizeof(*visitor)); - visitor->layout = (const upb_msglayout*)vp; - visitor->sink = output; - return visitor; -} - -bool upb_visitor_visitmsg(upb_visitor *visitor, const upb_msg *msg) { - return upb_visitor_visitmsg2(msg, visitor->layout, visitor->sink, 0); -} - - -/** upb_msg *******************************************************************/ - -/* If we always read/write as a consistent type to each address, this shouldn't - * violate aliasing. - */ -#define DEREF(msg, ofs, type) *(type*)CHARPTR_AT(msg, ofs) - -static upb_inttable *upb_msg_trygetextdict(const upb_msg *msg, - const upb_msglayout *l) { - return l->has_extdict ? DEREF(msg, l->extdict_offset, upb_inttable*) : NULL; -} - -static upb_inttable *upb_msg_getextdict(upb_msg *msg, - const upb_msglayout *l, - upb_alloc *a) { - upb_inttable *ext_dict; - UPB_ASSERT(l->has_extdict); - - ext_dict = upb_msg_trygetextdict(msg, l); - - if (!ext_dict) { - ext_dict = upb_malloc(a, sizeof(upb_inttable)); - - if (!ext_dict) { - return NULL; - } - - /* Use an 8-byte type to ensure all bytes are copied. */ - if (!upb_inttable_init2(ext_dict, UPB_CTYPE_INT64, a)) { - upb_free(a, ext_dict); - return NULL; - } - - DEREF(msg, l->extdict_offset, upb_inttable*) = ext_dict; - } - - return ext_dict; -} - -static uint32_t upb_msg_getoneofint(const upb_msg *msg, - const upb_oneofdef *o, - const upb_msglayout *l) { - size_t oneof_ofs = l->case_offsets[upb_oneofdef_index(o)]; - return DEREF(msg, oneof_ofs, uint8_t); -} - -static void upb_msg_setoneofcase(const upb_msg *msg, - const upb_oneofdef *o, - const upb_msglayout *l, - uint32_t val) { - size_t oneof_ofs = l->case_offsets[upb_oneofdef_index(o)]; - DEREF(msg, oneof_ofs, uint8_t) = val; -} - - -static bool upb_msg_oneofis(const upb_msg *msg, const upb_msglayout *l, - const upb_oneofdef *o, const upb_fielddef *f) { - return upb_msg_getoneofint(msg, o, l) == upb_fielddef_number(f); -} - -size_t upb_msg_sizeof(const upb_msglayout *l) { return l->size; } - -void upb_msg_init(upb_msg *msg, const upb_msglayout *l, upb_alloc *a) { - if (l->default_msg) { - memcpy(msg, l->default_msg, l->size); - } else { - memset(msg, 0, l->size); - } - - /* Set arena pointer. */ - memcpy(msg, &a, sizeof(a)); -} - -void upb_msg_uninit(upb_msg *msg, const upb_msglayout *l) { - upb_inttable *ext_dict = upb_msg_trygetextdict(msg, l); - if (ext_dict) { - upb_inttable_uninit2(ext_dict, upb_msg_alloc(msg, l)); - } -} - -upb_msg *upb_msg_new(const upb_msglayout *l, upb_alloc *a) { - upb_msg *msg = upb_malloc(a, upb_msg_sizeof(l)); - - if (msg) { - upb_msg_init(msg, l, a); - } - - return msg; -} - -void upb_msg_free(upb_msg *msg, const upb_msglayout *l) { - upb_msg_uninit(msg, l); - upb_free(upb_msg_alloc(msg, l), msg); -} - -upb_alloc *upb_msg_alloc(const upb_msg *msg, const upb_msglayout *l) { - upb_alloc *alloc; - UPB_UNUSED(l); - memcpy(&alloc, msg, sizeof(alloc)); - return alloc; -} - -bool upb_msg_has(const upb_msg *msg, - const upb_fielddef *f, - const upb_msglayout *l) { - const upb_oneofdef *o; - upb_msg_checkfield(l, f); - UPB_ASSERT(upb_fielddef_haspresence(f)); - - if (upb_fielddef_isextension(f)) { - /* Extensions are set when they are present in the extension dict. */ - upb_inttable *ext_dict = upb_msg_trygetextdict(msg, l); - upb_value v; - return ext_dict != NULL && - upb_inttable_lookup32(ext_dict, upb_fielddef_number(f), &v); - } else if ((o = upb_fielddef_containingoneof(f)) != NULL) { - /* Oneofs are set when the oneof number is set to this field. */ - return upb_msg_getoneofint(msg, o, l) == upb_fielddef_number(f); - } else { - /* Other fields are set when their hasbit is set. */ - uint32_t hasbit = l->hasbits[upb_fielddef_index(f)]; - return DEREF(msg, hasbit / 8, char) | (1 << (hasbit % 8)); - } -} - -upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f, - const upb_msglayout *l) { - upb_msg_checkfield(l, f); - - if (upb_fielddef_isextension(f)) { - upb_inttable *ext_dict = upb_msg_trygetextdict(msg, l); - upb_value val; - if (upb_inttable_lookup32(ext_dict, upb_fielddef_number(f), &val)) { - return upb_msgval_fromval(val); - } else { - return upb_msgval_fromdefault(f); - } - } else { - size_t ofs = l->field_offsets[upb_fielddef_index(f)]; - const upb_oneofdef *o = upb_fielddef_containingoneof(f); - upb_msgval ret; - - if (o && !upb_msg_oneofis(msg, l, o, f)) { - /* Oneof defaults can't come from the message because the memory is reused - * by all types in the oneof. */ - return upb_msgval_fromdefault(f); - } - - ret = upb_msgval_read(msg, ofs, upb_msg_fieldsize(f)); - return ret; - } -} - -bool upb_msg_set(upb_msg *msg, - const upb_fielddef *f, - upb_msgval val, - const upb_msglayout *l) { - upb_alloc *a = upb_msg_alloc(msg, l); - upb_msg_checkfield(l, f); - - if (upb_fielddef_isextension(f)) { - /* TODO(haberman): introduce table API that can do this in one call. */ - upb_inttable *ext = upb_msg_getextdict(msg, l, a); - upb_value val2 = upb_toval(val); - if (!upb_inttable_replace(ext, upb_fielddef_number(f), val2) && - !upb_inttable_insert2(ext, upb_fielddef_number(f), val2, a)) { - return false; - } - } else { - size_t ofs = l->field_offsets[upb_fielddef_index(f)]; - const upb_oneofdef *o = upb_fielddef_containingoneof(f); - - if (o) { - upb_msg_setoneofcase(msg, o, l, upb_fielddef_number(f)); - } - - upb_msgval_write(msg, ofs, val, upb_msg_fieldsize(f)); - } - return true; -} - - -/** upb_array *****************************************************************/ - -struct upb_array { - upb_fieldtype_t type; - uint8_t element_size; - void *data; /* Each element is element_size. */ - size_t len; /* Measured in elements. */ - size_t size; /* Measured in elements. */ - upb_alloc *alloc; -}; - -#define DEREF_ARR(arr, i, type) ((type*)arr->data)[i] - -size_t upb_array_sizeof(upb_fieldtype_t type) { - UPB_UNUSED(type); - return sizeof(upb_array); -} - -void upb_array_init(upb_array *arr, upb_fieldtype_t type, upb_alloc *alloc) { - arr->type = type; - arr->data = NULL; - arr->len = 0; - arr->size = 0; - arr->element_size = upb_msgval_sizeof(type); - arr->alloc = alloc; -} - -void upb_array_uninit(upb_array *arr) { - upb_free(arr->alloc, arr->data); -} - -upb_array *upb_array_new(upb_fieldtype_t type, upb_alloc *a) { - upb_array *ret = upb_malloc(a, upb_array_sizeof(type)); - - if (ret) { - upb_array_init(ret, type, a); - } - - return ret; -} - -void upb_array_free(upb_array *arr) { - upb_array_uninit(arr); - upb_free(arr->alloc, arr); -} - -size_t upb_array_size(const upb_array *arr) { - return arr->len; -} - -upb_fieldtype_t upb_array_type(const upb_array *arr) { - return arr->type; -} - -upb_msgval upb_array_get(const upb_array *arr, size_t i) { - UPB_ASSERT(i < arr->len); - return upb_msgval_read(arr->data, i * arr->element_size, arr->element_size); -} - -bool upb_array_set(upb_array *arr, size_t i, upb_msgval val) { - UPB_ASSERT(i <= arr->len); - - if (i == arr->len) { - /* Extending the array. */ - - if (i == arr->size) { - /* Need to reallocate. */ - size_t new_size = UPB_MAX(arr->size * 2, 8); - size_t new_bytes = new_size * arr->element_size; - size_t old_bytes = arr->size * arr->element_size; - upb_msgval *new_data = - upb_realloc(arr->alloc, arr->data, old_bytes, new_bytes); - - if (!new_data) { - return false; - } - - arr->data = new_data; - arr->size = new_size; - } - - arr->len = i + 1; - } - - upb_msgval_write(arr->data, i * arr->element_size, val, arr->element_size); - return true; -} - - -/** upb_map *******************************************************************/ - -struct upb_map { - upb_fieldtype_t key_type; - upb_fieldtype_t val_type; - /* We may want to optimize this to use inttable where possible, for greater - * efficiency and lower memory footprint. */ - upb_strtable strtab; - upb_alloc *alloc; -}; - -static void upb_map_tokey(upb_fieldtype_t type, upb_msgval *key, - const char **out_key, size_t *out_len) { - switch (type) { - case UPB_TYPE_STRING: - /* Point to string data of the input key. */ - *out_key = key->str.ptr; - *out_len = key->str.len; - return; - case UPB_TYPE_BOOL: - case UPB_TYPE_INT32: - case UPB_TYPE_UINT32: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT64: - /* Point to the key itself. XXX: big-endian. */ - *out_key = (const char*)key; - *out_len = upb_msgval_sizeof(type); - return; - case UPB_TYPE_BYTES: - case UPB_TYPE_DOUBLE: - case UPB_TYPE_ENUM: - case UPB_TYPE_FLOAT: - case UPB_TYPE_MESSAGE: - break; /* Cannot be a map key. */ - } - UPB_UNREACHABLE(); -} - -static upb_msgval upb_map_fromkey(upb_fieldtype_t type, const char *key, - size_t len) { - switch (type) { - case UPB_TYPE_STRING: - return upb_msgval_str(key, len); - case UPB_TYPE_BOOL: - case UPB_TYPE_INT32: - case UPB_TYPE_UINT32: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT64: - return upb_msgval_read(key, 0, upb_msgval_sizeof(type)); - case UPB_TYPE_BYTES: - case UPB_TYPE_DOUBLE: - case UPB_TYPE_ENUM: - case UPB_TYPE_FLOAT: - case UPB_TYPE_MESSAGE: - break; /* Cannot be a map key. */ - } - UPB_UNREACHABLE(); -} - -size_t upb_map_sizeof(upb_fieldtype_t ktype, upb_fieldtype_t vtype) { - /* Size does not currently depend on key/value type. */ - UPB_UNUSED(ktype); - UPB_UNUSED(vtype); - return sizeof(upb_map); -} - -bool upb_map_init(upb_map *map, upb_fieldtype_t ktype, upb_fieldtype_t vtype, - upb_alloc *a) { - upb_ctype_t vtabtype = upb_fieldtotabtype(vtype); - UPB_ASSERT(upb_fieldtype_mapkeyok(ktype)); - map->key_type = ktype; - map->val_type = vtype; - map->alloc = a; - - if (!upb_strtable_init2(&map->strtab, vtabtype, a)) { - return false; - } - - return true; -} - -void upb_map_uninit(upb_map *map) { - upb_strtable_uninit2(&map->strtab, map->alloc); -} - -upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype, - upb_alloc *a) { - upb_map *map = upb_malloc(a, upb_map_sizeof(ktype, vtype)); - - if (!map) { - return NULL; - } - - if (!upb_map_init(map, ktype, vtype, a)) { - return NULL; - } - - return map; -} - -void upb_map_free(upb_map *map) { - upb_map_uninit(map); - upb_free(map->alloc, map); -} - -size_t upb_map_size(const upb_map *map) { - return upb_strtable_count(&map->strtab); -} - -upb_fieldtype_t upb_map_keytype(const upb_map *map) { - return map->key_type; -} - -upb_fieldtype_t upb_map_valuetype(const upb_map *map) { - return map->val_type; -} - -bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) { - upb_value tabval; - const char *key_str; - size_t key_len; - bool ret; - - upb_map_tokey(map->key_type, &key, &key_str, &key_len); - ret = upb_strtable_lookup2(&map->strtab, key_str, key_len, &tabval); - if (ret) { - memcpy(val, &tabval, sizeof(tabval)); - } - - return ret; -} - -bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, - upb_msgval *removed) { - const char *key_str; - size_t key_len; - upb_value tabval = upb_toval(val); - upb_value removedtabval; - upb_alloc *a = map->alloc; - - upb_map_tokey(map->key_type, &key, &key_str, &key_len); - - /* TODO(haberman): add overwrite operation to minimize number of lookups. */ - if (upb_strtable_lookup2(&map->strtab, key_str, key_len, NULL)) { - upb_strtable_remove3(&map->strtab, key_str, key_len, &removedtabval, a); - memcpy(&removed, &removedtabval, sizeof(removed)); - } - - return upb_strtable_insert3(&map->strtab, key_str, key_len, tabval, a); -} - -bool upb_map_del(upb_map *map, upb_msgval key) { - const char *key_str; - size_t key_len; - upb_alloc *a = map->alloc; - - upb_map_tokey(map->key_type, &key, &key_str, &key_len); - return upb_strtable_remove3(&map->strtab, key_str, key_len, NULL, a); -} - - -/** upb_mapiter ***************************************************************/ - -struct upb_mapiter { - upb_strtable_iter iter; - upb_fieldtype_t key_type; -}; - -size_t upb_mapiter_sizeof() { - return sizeof(upb_mapiter); -} - -void upb_mapiter_begin(upb_mapiter *i, const upb_map *map) { - upb_strtable_begin(&i->iter, &map->strtab); - i->key_type = map->key_type; -} - -upb_mapiter *upb_mapiter_new(const upb_map *t, upb_alloc *a) { - upb_mapiter *ret = upb_malloc(a, upb_mapiter_sizeof()); - - if (!ret) { - return NULL; - } - - upb_mapiter_begin(ret, t); - return ret; -} - -void upb_mapiter_free(upb_mapiter *i, upb_alloc *a) { - upb_free(a, i); -} - -void upb_mapiter_next(upb_mapiter *i) { - upb_strtable_next(&i->iter); -} - -bool upb_mapiter_done(const upb_mapiter *i) { - return upb_strtable_done(&i->iter); -} - -upb_msgval upb_mapiter_key(const upb_mapiter *i) { - return upb_map_fromkey(i->key_type, upb_strtable_iter_key(&i->iter), - upb_strtable_iter_keylength(&i->iter)); -} - -upb_msgval upb_mapiter_value(const upb_mapiter *i) { - return upb_msgval_fromval(upb_strtable_iter_value(&i->iter)); -} - -void upb_mapiter_setdone(upb_mapiter *i) { - upb_strtable_iter_setdone(&i->iter); -} - -bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2) { - return upb_strtable_iter_isequal(&i1->iter, &i2->iter); -} - - -/** Handlers for upb_msg ******************************************************/ - -typedef struct { - size_t offset; - int32_t hasbit; -} upb_msg_handlerdata; - -/* Fallback implementation if the handler is not specialized by the producer. */ -#define MSG_WRITER(type, ctype) \ - bool upb_msg_set ## type (void *c, const void *hd, ctype val) { \ - uint8_t *m = c; \ - const upb_msg_handlerdata *d = hd; \ - if (d->hasbit > 0) \ - *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8); \ - *(ctype*)&m[d->offset] = val; \ - return true; \ - } \ - -MSG_WRITER(double, double) -MSG_WRITER(float, float) -MSG_WRITER(int32, int32_t) -MSG_WRITER(int64, int64_t) -MSG_WRITER(uint32, uint32_t) -MSG_WRITER(uint64, uint64_t) -MSG_WRITER(bool, bool) - -bool upb_msg_setscalarhandler(upb_handlers *h, const upb_fielddef *f, - size_t offset, int32_t hasbit) { - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - bool ok; - - upb_msg_handlerdata *d = upb_gmalloc(sizeof(*d)); - if (!d) return false; - d->offset = offset; - d->hasbit = hasbit; - - upb_handlerattr_sethandlerdata(&attr, d); - upb_handlerattr_setalwaysok(&attr, true); - upb_handlers_addcleanup(h, d, upb_gfree); - -#define TYPE(u, l) \ - case UPB_TYPE_##u: \ - ok = upb_handlers_set##l(h, f, upb_msg_set##l, &attr); break; - - ok = false; - - switch (upb_fielddef_type(f)) { - TYPE(INT64, int64); - TYPE(INT32, int32); - TYPE(ENUM, int32); - TYPE(UINT64, uint64); - TYPE(UINT32, uint32); - TYPE(DOUBLE, double); - TYPE(FLOAT, float); - TYPE(BOOL, bool); - default: UPB_ASSERT(false); break; - } -#undef TYPE - - upb_handlerattr_uninit(&attr); - return ok; -} - -bool upb_msg_getscalarhandlerdata(const upb_handlers *h, - upb_selector_t s, - upb_fieldtype_t *type, - size_t *offset, - int32_t *hasbit) { - const upb_msg_handlerdata *d; - upb_func *f = upb_handlers_gethandler(h, s); - - if ((upb_int64_handlerfunc*)f == upb_msg_setint64) { - *type = UPB_TYPE_INT64; - } else if ((upb_int32_handlerfunc*)f == upb_msg_setint32) { - *type = UPB_TYPE_INT32; - } else if ((upb_uint64_handlerfunc*)f == upb_msg_setuint64) { - *type = UPB_TYPE_UINT64; - } else if ((upb_uint32_handlerfunc*)f == upb_msg_setuint32) { - *type = UPB_TYPE_UINT32; - } else if ((upb_double_handlerfunc*)f == upb_msg_setdouble) { - *type = UPB_TYPE_DOUBLE; - } else if ((upb_float_handlerfunc*)f == upb_msg_setfloat) { - *type = UPB_TYPE_FLOAT; - } else if ((upb_bool_handlerfunc*)f == upb_msg_setbool) { - *type = UPB_TYPE_BOOL; - } else { - return false; - } - - d = upb_handlers_gethandlerdata(h, s); - *offset = d->offset; - *hasbit = d->hasbit; - return true; -} -/* -** upb::RefCounted Implementation -** -** Our key invariants are: -** 1. reference cycles never span groups -** 2. for ref2(to, from), we increment to's count iff group(from) != group(to) -** -** The previous two are how we avoid leaking cycles. Other important -** invariants are: -** 3. for mutable objects "from" and "to", if there exists a ref2(to, from) -** this implies group(from) == group(to). (In practice, what we implement -** is even stronger; "from" and "to" will share a group if there has *ever* -** been a ref2(to, from), but all that is necessary for correctness is the -** weaker one). -** 4. mutable and immutable objects are never in the same group. -*/ - - -#include - -static void freeobj(upb_refcounted *o); - -const char untracked_val; -const void *UPB_UNTRACKED_REF = &untracked_val; - -/* arch-specific atomic primitives *******************************************/ - -#ifdef UPB_THREAD_UNSAFE /*---------------------------------------------------*/ - -static void atomic_inc(uint32_t *a) { (*a)++; } -static bool atomic_dec(uint32_t *a) { return --(*a) == 0; } - -#elif defined(__GNUC__) || defined(__clang__) /*------------------------------*/ - -static void atomic_inc(uint32_t *a) { __sync_fetch_and_add(a, 1); } -static bool atomic_dec(uint32_t *a) { return __sync_sub_and_fetch(a, 1) == 0; } - -#elif defined(WIN32) /*-------------------------------------------------------*/ - -#include - -static void atomic_inc(upb_atomic_t *a) { InterlockedIncrement(&a->val); } -static bool atomic_dec(upb_atomic_t *a) { - return InterlockedDecrement(&a->val) == 0; -} - -#else -#error Atomic primitives not defined for your platform/CPU. \ - Implement them or compile with UPB_THREAD_UNSAFE. -#endif - -/* All static objects point to this refcount. - * It is special-cased in ref/unref below. */ -uint32_t static_refcount = -1; - -/* We can avoid atomic ops for statically-declared objects. - * This is a minor optimization but nice since we can avoid degrading under - * contention in this case. */ - -static void refgroup(uint32_t *group) { - if (group != &static_refcount) - atomic_inc(group); -} - -static bool unrefgroup(uint32_t *group) { - if (group == &static_refcount) { - return false; - } else { - return atomic_dec(group); - } -} - - -/* Reference tracking (debug only) ********************************************/ - -#ifdef UPB_DEBUG_REFS - -#ifdef UPB_THREAD_UNSAFE - -static void upb_lock() {} -static void upb_unlock() {} - -#else - -/* User must define functions that lock/unlock a global mutex and link this - * file against them. */ -void upb_lock(); -void upb_unlock(); - -#endif - -/* UPB_DEBUG_REFS mode counts on being able to malloc() memory in some - * code-paths that can normally never fail, like upb_refcounted_ref(). Since - * we have no way to propagage out-of-memory errors back to the user, and since - * these errors can only occur in UPB_DEBUG_REFS mode, we use an allocator that - * immediately aborts on failure (avoiding the global allocator, which might - * inject failures). */ - -#include - -static void *upb_debugrefs_allocfunc(upb_alloc *alloc, void *ptr, - size_t oldsize, size_t size) { - UPB_UNUSED(alloc); - UPB_UNUSED(oldsize); - if (size == 0) { - free(ptr); - return NULL; - } else { - void *ret = realloc(ptr, size); - - if (!ret) { - abort(); - } - - return ret; - } -} - -upb_alloc upb_alloc_debugrefs = {&upb_debugrefs_allocfunc}; - -typedef struct { - int count; /* How many refs there are (duplicates only allowed for ref2). */ - bool is_ref2; -} trackedref; - -static trackedref *trackedref_new(bool is_ref2) { - trackedref *ret = upb_malloc(&upb_alloc_debugrefs, sizeof(*ret)); - ret->count = 1; - ret->is_ref2 = is_ref2; - return ret; -} - -static void track(const upb_refcounted *r, const void *owner, bool ref2) { - upb_value v; - - UPB_ASSERT(owner); - if (owner == UPB_UNTRACKED_REF) return; - - upb_lock(); - if (upb_inttable_lookupptr(r->refs, owner, &v)) { - trackedref *ref = upb_value_getptr(v); - /* Since we allow multiple ref2's for the same to/from pair without - * allocating separate memory for each one, we lose the fine-grained - * tracking behavior we get with regular refs. Since ref2s only happen - * inside upb, we'll accept this limitation until/unless there is a really - * difficult upb-internal bug that can't be figured out without it. */ - UPB_ASSERT(ref2); - UPB_ASSERT(ref->is_ref2); - ref->count++; - } else { - trackedref *ref = trackedref_new(ref2); - upb_inttable_insertptr2(r->refs, owner, upb_value_ptr(ref), - &upb_alloc_debugrefs); - if (ref2) { - /* We know this cast is safe when it is a ref2, because it's coming from - * another refcounted object. */ - const upb_refcounted *from = owner; - UPB_ASSERT(!upb_inttable_lookupptr(from->ref2s, r, NULL)); - upb_inttable_insertptr2(from->ref2s, r, upb_value_ptr(NULL), - &upb_alloc_debugrefs); - } - } - upb_unlock(); -} - -static void untrack(const upb_refcounted *r, const void *owner, bool ref2) { - upb_value v; - bool found; - trackedref *ref; - - UPB_ASSERT(owner); - if (owner == UPB_UNTRACKED_REF) return; - - upb_lock(); - found = upb_inttable_lookupptr(r->refs, owner, &v); - /* This assert will fail if an owner attempts to release a ref it didn't have. */ - UPB_ASSERT(found); - ref = upb_value_getptr(v); - UPB_ASSERT(ref->is_ref2 == ref2); - if (--ref->count == 0) { - free(ref); - upb_inttable_removeptr(r->refs, owner, NULL); - if (ref2) { - /* We know this cast is safe when it is a ref2, because it's coming from - * another refcounted object. */ - const upb_refcounted *from = owner; - bool removed = upb_inttable_removeptr(from->ref2s, r, NULL); - UPB_ASSERT(removed); - } - } - upb_unlock(); -} - -static void checkref(const upb_refcounted *r, const void *owner, bool ref2) { - upb_value v; - bool found; - trackedref *ref; - - upb_lock(); - found = upb_inttable_lookupptr(r->refs, owner, &v); - UPB_ASSERT(found); - ref = upb_value_getptr(v); - UPB_ASSERT(ref->is_ref2 == ref2); - upb_unlock(); -} - -/* Populates the given UPB_CTYPE_INT32 inttable with counts of ref2's that - * originate from the given owner. */ -static void getref2s(const upb_refcounted *owner, upb_inttable *tab) { - upb_inttable_iter i; - - upb_lock(); - upb_inttable_begin(&i, owner->ref2s); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_value v; - upb_value count; - trackedref *ref; - bool found; - - upb_refcounted *to = (upb_refcounted*)upb_inttable_iter_key(&i); - - /* To get the count we need to look in the target's table. */ - found = upb_inttable_lookupptr(to->refs, owner, &v); - UPB_ASSERT(found); - ref = upb_value_getptr(v); - count = upb_value_int32(ref->count); - - upb_inttable_insertptr2(tab, to, count, &upb_alloc_debugrefs); - } - upb_unlock(); -} - -typedef struct { - upb_inttable ref2; - const upb_refcounted *obj; -} check_state; - -static void visit_check(const upb_refcounted *obj, const upb_refcounted *subobj, - void *closure) { - check_state *s = closure; - upb_inttable *ref2 = &s->ref2; - upb_value v; - bool removed; - int32_t newcount; - - UPB_ASSERT(obj == s->obj); - UPB_ASSERT(subobj); - removed = upb_inttable_removeptr(ref2, subobj, &v); - /* The following assertion will fail if the visit() function visits a subobj - * that it did not have a ref2 on, or visits the same subobj too many times. */ - UPB_ASSERT(removed); - newcount = upb_value_getint32(v) - 1; - if (newcount > 0) { - upb_inttable_insert2(ref2, (uintptr_t)subobj, upb_value_int32(newcount), - &upb_alloc_debugrefs); - } -} - -static void visit(const upb_refcounted *r, upb_refcounted_visit *v, - void *closure) { - /* In DEBUG_REFS mode we know what existing ref2 refs there are, so we know - * exactly the set of nodes that visit() should visit. So we verify visit()'s - * correctness here. */ - check_state state; - state.obj = r; - upb_inttable_init2(&state.ref2, UPB_CTYPE_INT32, &upb_alloc_debugrefs); - getref2s(r, &state.ref2); - - /* This should visit any children in the ref2 table. */ - if (r->vtbl->visit) r->vtbl->visit(r, visit_check, &state); - - /* This assertion will fail if the visit() function missed any children. */ - UPB_ASSERT(upb_inttable_count(&state.ref2) == 0); - upb_inttable_uninit2(&state.ref2, &upb_alloc_debugrefs); - if (r->vtbl->visit) r->vtbl->visit(r, v, closure); -} - -static void trackinit(upb_refcounted *r) { - r->refs = upb_malloc(&upb_alloc_debugrefs, sizeof(*r->refs)); - r->ref2s = upb_malloc(&upb_alloc_debugrefs, sizeof(*r->ref2s)); - upb_inttable_init2(r->refs, UPB_CTYPE_PTR, &upb_alloc_debugrefs); - upb_inttable_init2(r->ref2s, UPB_CTYPE_PTR, &upb_alloc_debugrefs); -} - -static void trackfree(const upb_refcounted *r) { - upb_inttable_uninit2(r->refs, &upb_alloc_debugrefs); - upb_inttable_uninit2(r->ref2s, &upb_alloc_debugrefs); - upb_free(&upb_alloc_debugrefs, r->refs); - upb_free(&upb_alloc_debugrefs, r->ref2s); -} - -#else - -static void track(const upb_refcounted *r, const void *owner, bool ref2) { - UPB_UNUSED(r); - UPB_UNUSED(owner); - UPB_UNUSED(ref2); -} - -static void untrack(const upb_refcounted *r, const void *owner, bool ref2) { - UPB_UNUSED(r); - UPB_UNUSED(owner); - UPB_UNUSED(ref2); -} - -static void checkref(const upb_refcounted *r, const void *owner, bool ref2) { - UPB_UNUSED(r); - UPB_UNUSED(owner); - UPB_UNUSED(ref2); -} - -static void trackinit(upb_refcounted *r) { - UPB_UNUSED(r); -} - -static void trackfree(const upb_refcounted *r) { - UPB_UNUSED(r); -} - -static void visit(const upb_refcounted *r, upb_refcounted_visit *v, - void *closure) { - if (r->vtbl->visit) r->vtbl->visit(r, v, closure); -} - -#endif /* UPB_DEBUG_REFS */ - - -/* freeze() *******************************************************************/ - -/* The freeze() operation is by far the most complicated part of this scheme. - * We compute strongly-connected components and then mutate the graph such that - * we preserve the invariants documented at the top of this file. And we must - * handle out-of-memory errors gracefully (without leaving the graph - * inconsistent), which adds to the fun. */ - -/* The state used by the freeze operation (shared across many functions). */ -typedef struct { - int depth; - int maxdepth; - uint64_t index; - /* Maps upb_refcounted* -> attributes (color, etc). attr layout varies by - * color. */ - upb_inttable objattr; - upb_inttable stack; /* stack of upb_refcounted* for Tarjan's algorithm. */ - upb_inttable groups; /* array of uint32_t*, malloc'd refcounts for new groups */ - upb_status *status; - jmp_buf err; -} tarjan; - -static void release_ref2(const upb_refcounted *obj, - const upb_refcounted *subobj, - void *closure); - -/* Node attributes -----------------------------------------------------------*/ - -/* After our analysis phase all nodes will be either GRAY or WHITE. */ - -typedef enum { - BLACK = 0, /* Object has not been seen. */ - GRAY, /* Object has been found via a refgroup but may not be reachable. */ - GREEN, /* Object is reachable and is currently on the Tarjan stack. */ - WHITE /* Object is reachable and has been assigned a group (SCC). */ -} color_t; - -UPB_NORETURN static void err(tarjan *t) { longjmp(t->err, 1); } -UPB_NORETURN static void oom(tarjan *t) { - upb_status_seterrmsg(t->status, "out of memory"); - err(t); -} - -static uint64_t trygetattr(const tarjan *t, const upb_refcounted *r) { - upb_value v; - return upb_inttable_lookupptr(&t->objattr, r, &v) ? - upb_value_getuint64(v) : 0; -} - -static uint64_t getattr(const tarjan *t, const upb_refcounted *r) { - upb_value v; - bool found = upb_inttable_lookupptr(&t->objattr, r, &v); - UPB_ASSERT(found); - return upb_value_getuint64(v); -} - -static void setattr(tarjan *t, const upb_refcounted *r, uint64_t attr) { - upb_inttable_removeptr(&t->objattr, r, NULL); - upb_inttable_insertptr(&t->objattr, r, upb_value_uint64(attr)); -} - -static color_t color(tarjan *t, const upb_refcounted *r) { - return trygetattr(t, r) & 0x3; /* Color is always stored in the low 2 bits. */ -} - -static void set_gray(tarjan *t, const upb_refcounted *r) { - UPB_ASSERT(color(t, r) == BLACK); - setattr(t, r, GRAY); -} - -/* Pushes an obj onto the Tarjan stack and sets it to GREEN. */ -static void push(tarjan *t, const upb_refcounted *r) { - UPB_ASSERT(color(t, r) == BLACK || color(t, r) == GRAY); - /* This defines the attr layout for the GREEN state. "index" and "lowlink" - * get 31 bits, which is plenty (limit of 2B objects frozen at a time). */ - setattr(t, r, GREEN | (t->index << 2) | (t->index << 33)); - if (++t->index == 0x80000000) { - upb_status_seterrmsg(t->status, "too many objects to freeze"); - err(t); - } - upb_inttable_push(&t->stack, upb_value_ptr((void*)r)); -} - -/* Pops an obj from the Tarjan stack and sets it to WHITE, with a ptr to its - * SCC group. */ -static upb_refcounted *pop(tarjan *t) { - upb_refcounted *r = upb_value_getptr(upb_inttable_pop(&t->stack)); - UPB_ASSERT(color(t, r) == GREEN); - /* This defines the attr layout for nodes in the WHITE state. - * Top of group stack is [group, NULL]; we point at group. */ - setattr(t, r, WHITE | (upb_inttable_count(&t->groups) - 2) << 8); - return r; -} - -static void tarjan_newgroup(tarjan *t) { - uint32_t *group = upb_gmalloc(sizeof(*group)); - if (!group) oom(t); - /* Push group and empty group leader (we'll fill in leader later). */ - if (!upb_inttable_push(&t->groups, upb_value_ptr(group)) || - !upb_inttable_push(&t->groups, upb_value_ptr(NULL))) { - upb_gfree(group); - oom(t); - } - *group = 0; -} - -static uint32_t idx(tarjan *t, const upb_refcounted *r) { - UPB_ASSERT(color(t, r) == GREEN); - return (getattr(t, r) >> 2) & 0x7FFFFFFF; -} - -static uint32_t lowlink(tarjan *t, const upb_refcounted *r) { - if (color(t, r) == GREEN) { - return getattr(t, r) >> 33; - } else { - return UINT32_MAX; - } -} - -static void set_lowlink(tarjan *t, const upb_refcounted *r, uint32_t lowlink) { - UPB_ASSERT(color(t, r) == GREEN); - setattr(t, r, ((uint64_t)lowlink << 33) | (getattr(t, r) & 0x1FFFFFFFF)); -} - -static uint32_t *group(tarjan *t, upb_refcounted *r) { - uint64_t groupnum; - upb_value v; - bool found; - - UPB_ASSERT(color(t, r) == WHITE); - groupnum = getattr(t, r) >> 8; - found = upb_inttable_lookup(&t->groups, groupnum, &v); - UPB_ASSERT(found); - return upb_value_getptr(v); -} - -/* If the group leader for this object's group has not previously been set, - * the given object is assigned to be its leader. */ -static upb_refcounted *groupleader(tarjan *t, upb_refcounted *r) { - uint64_t leader_slot; - upb_value v; - bool found; - - UPB_ASSERT(color(t, r) == WHITE); - leader_slot = (getattr(t, r) >> 8) + 1; - found = upb_inttable_lookup(&t->groups, leader_slot, &v); - UPB_ASSERT(found); - if (upb_value_getptr(v)) { - return upb_value_getptr(v); - } else { - upb_inttable_remove(&t->groups, leader_slot, NULL); - upb_inttable_insert(&t->groups, leader_slot, upb_value_ptr(r)); - return r; - } -} - - -/* Tarjan's algorithm --------------------------------------------------------*/ - -/* See: - * http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm */ -static void do_tarjan(const upb_refcounted *obj, tarjan *t); - -static void tarjan_visit(const upb_refcounted *obj, - const upb_refcounted *subobj, - void *closure) { - tarjan *t = closure; - if (++t->depth > t->maxdepth) { - upb_status_seterrf(t->status, "graph too deep to freeze (%d)", t->maxdepth); - err(t); - } else if (subobj->is_frozen || color(t, subobj) == WHITE) { - /* Do nothing: we don't want to visit or color already-frozen nodes, - * and WHITE nodes have already been assigned a SCC. */ - } else if (color(t, subobj) < GREEN) { - /* Subdef has not yet been visited; recurse on it. */ - do_tarjan(subobj, t); - set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), lowlink(t, subobj))); - } else if (color(t, subobj) == GREEN) { - /* Subdef is in the stack and hence in the current SCC. */ - set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), idx(t, subobj))); - } - --t->depth; -} - -static void do_tarjan(const upb_refcounted *obj, tarjan *t) { - if (color(t, obj) == BLACK) { - /* We haven't seen this object's group; mark the whole group GRAY. */ - const upb_refcounted *o = obj; - do { set_gray(t, o); } while ((o = o->next) != obj); - } - - push(t, obj); - visit(obj, tarjan_visit, t); - if (lowlink(t, obj) == idx(t, obj)) { - tarjan_newgroup(t); - while (pop(t) != obj) - ; - } -} - - -/* freeze() ------------------------------------------------------------------*/ - -static void crossref(const upb_refcounted *r, const upb_refcounted *subobj, - void *_t) { - tarjan *t = _t; - UPB_ASSERT(color(t, r) > BLACK); - if (color(t, subobj) > BLACK && r->group != subobj->group) { - /* Previously this ref was not reflected in subobj->group because they - * were in the same group; now that they are split a ref must be taken. */ - refgroup(subobj->group); - } -} - -static bool freeze(upb_refcounted *const*roots, int n, upb_status *s, - int maxdepth) { - volatile bool ret = false; - int i; - upb_inttable_iter iter; - - /* We run in two passes so that we can allocate all memory before performing - * any mutation of the input -- this allows us to leave the input unchanged - * in the case of memory allocation failure. */ - tarjan t; - t.index = 0; - t.depth = 0; - t.maxdepth = maxdepth; - t.status = s; - if (!upb_inttable_init(&t.objattr, UPB_CTYPE_UINT64)) goto err1; - if (!upb_inttable_init(&t.stack, UPB_CTYPE_PTR)) goto err2; - if (!upb_inttable_init(&t.groups, UPB_CTYPE_PTR)) goto err3; - if (setjmp(t.err) != 0) goto err4; - - - for (i = 0; i < n; i++) { - if (color(&t, roots[i]) < GREEN) { - do_tarjan(roots[i], &t); - } - } - - /* If we've made it this far, no further errors are possible so it's safe to - * mutate the objects without risk of leaving them in an inconsistent state. */ - ret = true; - - /* The transformation that follows requires care. The preconditions are: - * - all objects in attr map are WHITE or GRAY, and are in mutable groups - * (groups of all mutable objs) - * - no ref2(to, from) refs have incremented count(to) if both "to" and - * "from" are in our attr map (this follows from invariants (2) and (3)) */ - - /* Pass 1: we remove WHITE objects from their mutable groups, and add them to - * new groups according to the SCC's we computed. These new groups will - * consist of only frozen objects. None will be immediately collectible, - * because WHITE objects are by definition reachable from one of "roots", - * which the caller must own refs on. */ - upb_inttable_begin(&iter, &t.objattr); - for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) { - upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter); - /* Since removal from a singly-linked list requires access to the object's - * predecessor, we consider obj->next instead of obj for moving. With the - * while() loop we guarantee that we will visit every node's predecessor. - * Proof: - * 1. every node's predecessor is in our attr map. - * 2. though the loop body may change a node's predecessor, it will only - * change it to be the node we are currently operating on, so with a - * while() loop we guarantee ourselves the chance to remove each node. */ - while (color(&t, obj->next) == WHITE && - group(&t, obj->next) != obj->next->group) { - upb_refcounted *leader; - - /* Remove from old group. */ - upb_refcounted *move = obj->next; - if (obj == move) { - /* Removing the last object from a group. */ - UPB_ASSERT(*obj->group == obj->individual_count); - upb_gfree(obj->group); - } else { - obj->next = move->next; - /* This may decrease to zero; we'll collect GRAY objects (if any) that - * remain in the group in the third pass. */ - UPB_ASSERT(*move->group >= move->individual_count); - *move->group -= move->individual_count; - } - - /* Add to new group. */ - leader = groupleader(&t, move); - if (move == leader) { - /* First object added to new group is its leader. */ - move->group = group(&t, move); - move->next = move; - *move->group = move->individual_count; - } else { - /* Group already has at least one object in it. */ - UPB_ASSERT(leader->group == group(&t, move)); - move->group = group(&t, move); - move->next = leader->next; - leader->next = move; - *move->group += move->individual_count; - } - - move->is_frozen = true; - } - } - - /* Pass 2: GRAY and WHITE objects "obj" with ref2(to, obj) references must - * increment count(to) if group(obj) != group(to) (which could now be the - * case if "to" was just frozen). */ - upb_inttable_begin(&iter, &t.objattr); - for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) { - upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter); - visit(obj, crossref, &t); - } - - /* Pass 3: GRAY objects are collected if their group's refcount dropped to - * zero when we removed its white nodes. This can happen if they had only - * been kept alive by virtue of sharing a group with an object that was just - * frozen. - * - * It is important that we do this last, since the GRAY object's free() - * function could call unref2() on just-frozen objects, which will decrement - * refs that were added in pass 2. */ - upb_inttable_begin(&iter, &t.objattr); - for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) { - upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter); - if (obj->group == NULL || *obj->group == 0) { - if (obj->group) { - upb_refcounted *o; - - /* We eagerly free() the group's count (since we can't easily determine - * the group's remaining size it's the easiest way to ensure it gets - * done). */ - upb_gfree(obj->group); - - /* Visit to release ref2's (done in a separate pass since release_ref2 - * depends on o->group being unmodified so it can test merged()). */ - o = obj; - do { visit(o, release_ref2, NULL); } while ((o = o->next) != obj); - - /* Mark "group" fields as NULL so we know to free the objects later in - * this loop, but also don't try to delete the group twice. */ - o = obj; - do { o->group = NULL; } while ((o = o->next) != obj); - } - freeobj(obj); - } - } - -err4: - if (!ret) { - upb_inttable_begin(&iter, &t.groups); - for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) - upb_gfree(upb_value_getptr(upb_inttable_iter_value(&iter))); - } - upb_inttable_uninit(&t.groups); -err3: - upb_inttable_uninit(&t.stack); -err2: - upb_inttable_uninit(&t.objattr); -err1: - return ret; -} - - -/* Misc internal functions ***************************************************/ - -static bool merged(const upb_refcounted *r, const upb_refcounted *r2) { - return r->group == r2->group; -} - -static void merge(upb_refcounted *r, upb_refcounted *from) { - upb_refcounted *base; - upb_refcounted *tmp; - - if (merged(r, from)) return; - *r->group += *from->group; - upb_gfree(from->group); - base = from; - - /* Set all refcount pointers in the "from" chain to the merged refcount. - * - * TODO(haberman): this linear algorithm can result in an overall O(n^2) bound - * if the user continuously extends a group by one object. Prevent this by - * using one of the techniques in this paper: - * http://bioinfo.ict.ac.cn/~dbu/AlgorithmCourses/Lectures/Union-Find-Tarjan.pdf */ - do { from->group = r->group; } while ((from = from->next) != base); - - /* Merge the two circularly linked lists by swapping their next pointers. */ - tmp = r->next; - r->next = base->next; - base->next = tmp; -} - -static void unref(const upb_refcounted *r); - -static void release_ref2(const upb_refcounted *obj, - const upb_refcounted *subobj, - void *closure) { - UPB_UNUSED(closure); - untrack(subobj, obj, true); - if (!merged(obj, subobj)) { - UPB_ASSERT(subobj->is_frozen); - unref(subobj); - } -} - -static void unref(const upb_refcounted *r) { - if (unrefgroup(r->group)) { - const upb_refcounted *o; - - upb_gfree(r->group); - - /* In two passes, since release_ref2 needs a guarantee that any subobjs - * are alive. */ - o = r; - do { visit(o, release_ref2, NULL); } while((o = o->next) != r); - - o = r; - do { - const upb_refcounted *next = o->next; - UPB_ASSERT(o->is_frozen || o->individual_count == 0); - freeobj((upb_refcounted*)o); - o = next; - } while(o != r); - } -} - -static void freeobj(upb_refcounted *o) { - trackfree(o); - o->vtbl->free((upb_refcounted*)o); -} - - -/* Public interface ***********************************************************/ - -bool upb_refcounted_init(upb_refcounted *r, - const struct upb_refcounted_vtbl *vtbl, - const void *owner) { -#ifndef NDEBUG - /* Endianness check. This is unrelated to upb_refcounted, it's just a - * convenient place to put the check that we can be assured will run for - * basically every program using upb. */ - const int x = 1; -#ifdef UPB_BIG_ENDIAN - UPB_ASSERT(*(char*)&x != 1); -#else - UPB_ASSERT(*(char*)&x == 1); -#endif -#endif - - r->next = r; - r->vtbl = vtbl; - r->individual_count = 0; - r->is_frozen = false; - r->group = upb_gmalloc(sizeof(*r->group)); - if (!r->group) return false; - *r->group = 0; - trackinit(r); - upb_refcounted_ref(r, owner); - return true; -} - -bool upb_refcounted_isfrozen(const upb_refcounted *r) { - return r->is_frozen; -} - -void upb_refcounted_ref(const upb_refcounted *r, const void *owner) { - track(r, owner, false); - if (!r->is_frozen) - ((upb_refcounted*)r)->individual_count++; - refgroup(r->group); -} - -void upb_refcounted_unref(const upb_refcounted *r, const void *owner) { - untrack(r, owner, false); - if (!r->is_frozen) - ((upb_refcounted*)r)->individual_count--; - unref(r); -} - -void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from) { - UPB_ASSERT(!from->is_frozen); /* Non-const pointer implies this. */ - track(r, from, true); - if (r->is_frozen) { - refgroup(r->group); - } else { - merge((upb_refcounted*)r, from); - } -} - -void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from) { - UPB_ASSERT(!from->is_frozen); /* Non-const pointer implies this. */ - untrack(r, from, true); - if (r->is_frozen) { - unref(r); - } else { - UPB_ASSERT(merged(r, from)); - } -} - -void upb_refcounted_donateref( - const upb_refcounted *r, const void *from, const void *to) { - UPB_ASSERT(from != to); - if (to != NULL) - upb_refcounted_ref(r, to); - if (from != NULL) - upb_refcounted_unref(r, from); -} - -void upb_refcounted_checkref(const upb_refcounted *r, const void *owner) { - checkref(r, owner, false); -} - -bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s, - int maxdepth) { - int i; - bool ret; - for (i = 0; i < n; i++) { - UPB_ASSERT(!roots[i]->is_frozen); - } - ret = freeze(roots, n, s, maxdepth); - UPB_ASSERT(!s || ret == upb_ok(s)); - return ret; -} - - -bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink *sink) { - void *subc; - bool ret; - upb_bufhandle handle; - upb_bufhandle_init(&handle); - upb_bufhandle_setbuf(&handle, buf, 0); - ret = upb_bytessink_start(sink, len, &subc); - if (ret && len != 0) { - ret = (upb_bytessink_putbuf(sink, subc, buf, len, &handle) >= len); - } - if (ret) { - ret = upb_bytessink_end(sink); - } - upb_bufhandle_uninit(&handle); - return ret; -} - -struct upb_bufsink { - upb_byteshandler handler; - upb_bytessink sink; - upb_env *env; - char *ptr; - size_t len, size; -}; - -static void *upb_bufsink_start(void *_sink, const void *hd, size_t size_hint) { - upb_bufsink *sink = _sink; - UPB_UNUSED(hd); - UPB_UNUSED(size_hint); - sink->len = 0; - return sink; -} - -static size_t upb_bufsink_string(void *_sink, const void *hd, const char *ptr, - size_t len, const upb_bufhandle *handle) { - upb_bufsink *sink = _sink; - size_t new_size = sink->size; - - UPB_ASSERT(new_size > 0); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - while (sink->len + len > new_size) { - new_size *= 2; - } - - if (new_size != sink->size) { - sink->ptr = upb_env_realloc(sink->env, sink->ptr, sink->size, new_size); - sink->size = new_size; - } - - memcpy(sink->ptr + sink->len, ptr, len); - sink->len += len; - - return len; -} - -upb_bufsink *upb_bufsink_new(upb_env *env) { - upb_bufsink *sink = upb_env_malloc(env, sizeof(upb_bufsink)); - upb_byteshandler_init(&sink->handler); - upb_byteshandler_setstartstr(&sink->handler, upb_bufsink_start, NULL); - upb_byteshandler_setstring(&sink->handler, upb_bufsink_string, NULL); - - upb_bytessink_reset(&sink->sink, &sink->handler, sink); - - sink->env = env; - sink->size = 32; - sink->ptr = upb_env_malloc(env, sink->size); - sink->len = 0; - - return sink; -} - -void upb_bufsink_free(upb_bufsink *sink) { - upb_env_free(sink->env, sink->ptr); - upb_env_free(sink->env, sink); -} - -upb_bytessink *upb_bufsink_sink(upb_bufsink *sink) { - return &sink->sink; -} - -const char *upb_bufsink_getdata(const upb_bufsink *sink, size_t *len) { - *len = sink->len; - return sink->ptr; -} -/* -** upb_table Implementation -** -** Implementation is heavily inspired by Lua's ltable.c. -*/ - - -#include - -#define UPB_MAXARRSIZE 16 /* 64k. */ - -/* From Chromium. */ -#define ARRAY_SIZE(x) \ - ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) - -static void upb_check_alloc(upb_table *t, upb_alloc *a) { - UPB_UNUSED(t); - UPB_UNUSED(a); - UPB_ASSERT_DEBUGVAR(t->alloc == a); -} - -static const double MAX_LOAD = 0.85; - -/* The minimum utilization of the array part of a mixed hash/array table. This - * is a speed/memory-usage tradeoff (though it's not straightforward because of - * cache effects). The lower this is, the more memory we'll use. */ -static const double MIN_DENSITY = 0.1; - -bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; } - -int log2ceil(uint64_t v) { - int ret = 0; - bool pow2 = is_pow2(v); - while (v >>= 1) ret++; - ret = pow2 ? ret : ret + 1; /* Ceiling. */ - return UPB_MIN(UPB_MAXARRSIZE, ret); -} - -char *upb_strdup(const char *s, upb_alloc *a) { - return upb_strdup2(s, strlen(s), a); -} - -char *upb_strdup2(const char *s, size_t len, upb_alloc *a) { - size_t n; - char *p; - - /* Prevent overflow errors. */ - if (len == SIZE_MAX) return NULL; - /* Always null-terminate, even if binary data; but don't rely on the input to - * have a null-terminating byte since it may be a raw binary buffer. */ - n = len + 1; - p = upb_malloc(a, n); - if (p) { - memcpy(p, s, len); - p[len] = 0; - } - return p; -} - -/* A type to represent the lookup key of either a strtable or an inttable. */ -typedef union { - uintptr_t num; - struct { - const char *str; - size_t len; - } str; -} lookupkey_t; - -static lookupkey_t strkey2(const char *str, size_t len) { - lookupkey_t k; - k.str.str = str; - k.str.len = len; - return k; -} - -static lookupkey_t intkey(uintptr_t key) { - lookupkey_t k; - k.num = key; - return k; -} - -typedef uint32_t hashfunc_t(upb_tabkey key); -typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2); - -/* Base table (shared code) ***************************************************/ - -/* For when we need to cast away const. */ -static upb_tabent *mutable_entries(upb_table *t) { - return (upb_tabent*)t->entries; -} - -static bool isfull(upb_table *t) { - if (upb_table_size(t) == 0) { - return true; - } else { - return ((double)(t->count + 1) / upb_table_size(t)) > MAX_LOAD; - } -} - -static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2, - upb_alloc *a) { - size_t bytes; - - t->count = 0; - t->ctype = ctype; - t->size_lg2 = size_lg2; - t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0; -#ifndef NDEBUG - t->alloc = a; -#endif - bytes = upb_table_size(t) * sizeof(upb_tabent); - if (bytes > 0) { - t->entries = upb_malloc(a, bytes); - if (!t->entries) return false; - memset(mutable_entries(t), 0, bytes); - } else { - t->entries = NULL; - } - return true; -} - -static void uninit(upb_table *t, upb_alloc *a) { - upb_check_alloc(t, a); - upb_free(a, mutable_entries(t)); -} - -static upb_tabent *emptyent(upb_table *t) { - upb_tabent *e = mutable_entries(t) + upb_table_size(t); - while (1) { if (upb_tabent_isempty(--e)) return e; UPB_ASSERT(e > t->entries); } -} - -static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) { - return (upb_tabent*)upb_getentry(t, hash); -} - -static const upb_tabent *findentry(const upb_table *t, lookupkey_t key, - uint32_t hash, eqlfunc_t *eql) { - const upb_tabent *e; - - if (t->size_lg2 == 0) return NULL; - e = upb_getentry(t, hash); - if (upb_tabent_isempty(e)) return NULL; - while (1) { - if (eql(e->key, key)) return e; - if ((e = e->next) == NULL) return NULL; - } -} - -static upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key, - uint32_t hash, eqlfunc_t *eql) { - return (upb_tabent*)findentry(t, key, hash, eql); -} - -static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v, - uint32_t hash, eqlfunc_t *eql) { - const upb_tabent *e = findentry(t, key, hash, eql); - if (e) { - if (v) { - _upb_value_setval(v, e->val.val, t->ctype); - } - return true; - } else { - return false; - } -} - -/* The given key must not already exist in the table. */ -static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey, - upb_value val, uint32_t hash, - hashfunc_t *hashfunc, eqlfunc_t *eql) { - upb_tabent *mainpos_e; - upb_tabent *our_e; - - UPB_ASSERT(findentry(t, key, hash, eql) == NULL); - UPB_ASSERT_DEBUGVAR(val.ctype == t->ctype); - - t->count++; - mainpos_e = getentry_mutable(t, hash); - our_e = mainpos_e; - - if (upb_tabent_isempty(mainpos_e)) { - /* Our main position is empty; use it. */ - our_e->next = NULL; - } else { - /* Collision. */ - upb_tabent *new_e = emptyent(t); - /* Head of collider's chain. */ - upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key)); - if (chain == mainpos_e) { - /* Existing ent is in its main posisiton (it has the same hash as us, and - * is the head of our chain). Insert to new ent and append to this chain. */ - new_e->next = mainpos_e->next; - mainpos_e->next = new_e; - our_e = new_e; - } else { - /* Existing ent is not in its main position (it is a node in some other - * chain). This implies that no existing ent in the table has our hash. - * Evict it (updating its chain) and use its ent for head of our chain. */ - *new_e = *mainpos_e; /* copies next. */ - while (chain->next != mainpos_e) { - chain = (upb_tabent*)chain->next; - UPB_ASSERT(chain); - } - chain->next = new_e; - our_e = mainpos_e; - our_e->next = NULL; - } - } - our_e->key = tabkey; - our_e->val.val = val.val; - UPB_ASSERT(findentry(t, key, hash, eql) == our_e); -} - -static bool rm(upb_table *t, lookupkey_t key, upb_value *val, - upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) { - upb_tabent *chain = getentry_mutable(t, hash); - if (upb_tabent_isempty(chain)) return false; - if (eql(chain->key, key)) { - /* Element to remove is at the head of its chain. */ - t->count--; - if (val) _upb_value_setval(val, chain->val.val, t->ctype); - if (removed) *removed = chain->key; - if (chain->next) { - upb_tabent *move = (upb_tabent*)chain->next; - *chain = *move; - move->key = 0; /* Make the slot empty. */ - } else { - chain->key = 0; /* Make the slot empty. */ - } - return true; - } else { - /* Element to remove is either in a non-head position or not in the - * table. */ - while (chain->next && !eql(chain->next->key, key)) { - chain = (upb_tabent*)chain->next; - } - if (chain->next) { - /* Found element to remove. */ - upb_tabent *rm = (upb_tabent*)chain->next; - t->count--; - if (val) _upb_value_setval(val, chain->next->val.val, t->ctype); - if (removed) *removed = rm->key; - rm->key = 0; /* Make the slot empty. */ - chain->next = rm->next; - return true; - } else { - /* Element to remove is not in the table. */ - return false; - } - } -} - -static size_t next(const upb_table *t, size_t i) { - do { - if (++i >= upb_table_size(t)) - return SIZE_MAX; - } while(upb_tabent_isempty(&t->entries[i])); - - return i; -} - -static size_t begin(const upb_table *t) { - return next(t, -1); -} - - -/* upb_strtable ***************************************************************/ - -/* A simple "subclass" of upb_table that only adds a hash function for strings. */ - -static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) { - char *str = upb_malloc(a, k2.str.len + sizeof(uint32_t) + 1); - if (str == NULL) return 0; - memcpy(str, &k2.str.len, sizeof(uint32_t)); - memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len + 1); - return (uintptr_t)str; -} - -static uint32_t strhash(upb_tabkey key) { - uint32_t len; - char *str = upb_tabstr(key, &len); - return MurmurHash2(str, len, 0); -} - -static bool streql(upb_tabkey k1, lookupkey_t k2) { - uint32_t len; - char *str = upb_tabstr(k1, &len); - return len == k2.str.len && memcmp(str, k2.str.str, len) == 0; -} - -bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) { - return init(&t->t, ctype, 2, a); -} - -void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) { - size_t i; - for (i = 0; i < upb_table_size(&t->t); i++) - upb_free(a, (void*)t->t.entries[i].key); - uninit(&t->t, a); -} - -bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) { - upb_strtable new_table; - upb_strtable_iter i; - - upb_check_alloc(&t->t, a); - - if (!init(&new_table.t, t->t.ctype, size_lg2, a)) - return false; - upb_strtable_begin(&i, t); - for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) { - upb_strtable_insert3( - &new_table, - upb_strtable_iter_key(&i), - upb_strtable_iter_keylength(&i), - upb_strtable_iter_value(&i), - a); - } - upb_strtable_uninit2(t, a); - *t = new_table; - return true; -} - -bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len, - upb_value v, upb_alloc *a) { - lookupkey_t key; - upb_tabkey tabkey; - uint32_t hash; - - upb_check_alloc(&t->t, a); - - if (isfull(&t->t)) { - /* Need to resize. New table of double the size, add old elements to it. */ - if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) { - return false; - } - } - - key = strkey2(k, len); - tabkey = strcopy(key, a); - if (tabkey == 0) return false; - - hash = MurmurHash2(key.str.str, key.str.len, 0); - insert(&t->t, key, tabkey, v, hash, &strhash, &streql); - return true; -} - -bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len, - upb_value *v) { - uint32_t hash = MurmurHash2(key, len, 0); - return lookup(&t->t, strkey2(key, len), v, hash, &streql); -} - -bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len, - upb_value *val, upb_alloc *alloc) { - uint32_t hash = MurmurHash2(key, len, 0); - upb_tabkey tabkey; - if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) { - upb_free(alloc, (void*)tabkey); - return true; - } else { - return false; - } -} - -/* Iteration */ - -static const upb_tabent *str_tabent(const upb_strtable_iter *i) { - return &i->t->t.entries[i->index]; -} - -void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) { - i->t = t; - i->index = begin(&t->t); -} - -void upb_strtable_next(upb_strtable_iter *i) { - i->index = next(&i->t->t, i->index); -} - -bool upb_strtable_done(const upb_strtable_iter *i) { - return i->index >= upb_table_size(&i->t->t) || - upb_tabent_isempty(str_tabent(i)); -} - -const char *upb_strtable_iter_key(const upb_strtable_iter *i) { - UPB_ASSERT(!upb_strtable_done(i)); - return upb_tabstr(str_tabent(i)->key, NULL); -} - -size_t upb_strtable_iter_keylength(const upb_strtable_iter *i) { - uint32_t len; - UPB_ASSERT(!upb_strtable_done(i)); - upb_tabstr(str_tabent(i)->key, &len); - return len; -} - -upb_value upb_strtable_iter_value(const upb_strtable_iter *i) { - UPB_ASSERT(!upb_strtable_done(i)); - return _upb_value_val(str_tabent(i)->val.val, i->t->t.ctype); -} - -void upb_strtable_iter_setdone(upb_strtable_iter *i) { - i->index = SIZE_MAX; -} - -bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, - const upb_strtable_iter *i2) { - if (upb_strtable_done(i1) && upb_strtable_done(i2)) - return true; - return i1->t == i2->t && i1->index == i2->index; -} - - -/* upb_inttable ***************************************************************/ - -/* For inttables we use a hybrid structure where small keys are kept in an - * array and large keys are put in the hash table. */ - -static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); } - -static bool inteql(upb_tabkey k1, lookupkey_t k2) { - return k1 == k2.num; -} - -static upb_tabval *mutable_array(upb_inttable *t) { - return (upb_tabval*)t->array; -} - -static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) { - if (key < t->array_size) { - return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL; - } else { - upb_tabent *e = - findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql); - return e ? &e->val : NULL; - } -} - -static const upb_tabval *inttable_val_const(const upb_inttable *t, - uintptr_t key) { - return inttable_val((upb_inttable*)t, key); -} - -size_t upb_inttable_count(const upb_inttable *t) { - return t->t.count + t->array_count; -} - -static void check(upb_inttable *t) { - UPB_UNUSED(t); -#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG) - { - /* This check is very expensive (makes inserts/deletes O(N)). */ - size_t count = 0; - upb_inttable_iter i; - upb_inttable_begin(&i, t); - for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) { - UPB_ASSERT(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL)); - } - UPB_ASSERT(count == upb_inttable_count(t)); - } -#endif -} - -bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype, - size_t asize, int hsize_lg2, upb_alloc *a) { - size_t array_bytes; - - if (!init(&t->t, ctype, hsize_lg2, a)) return false; - /* Always make the array part at least 1 long, so that we know key 0 - * won't be in the hash part, which simplifies things. */ - t->array_size = UPB_MAX(1, asize); - t->array_count = 0; - array_bytes = t->array_size * sizeof(upb_value); - t->array = upb_malloc(a, array_bytes); - if (!t->array) { - uninit(&t->t, a); - return false; - } - memset(mutable_array(t), 0xff, array_bytes); - check(t); - return true; -} - -bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) { - return upb_inttable_sizedinit(t, ctype, 0, 4, a); -} - -void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) { - uninit(&t->t, a); - upb_free(a, mutable_array(t)); -} - -bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, - upb_alloc *a) { - upb_tabval tabval; - tabval.val = val.val; - UPB_ASSERT(upb_arrhas(tabval)); /* This will reject (uint64_t)-1. Fix this. */ - - upb_check_alloc(&t->t, a); - - if (key < t->array_size) { - UPB_ASSERT(!upb_arrhas(t->array[key])); - t->array_count++; - mutable_array(t)[key].val = val.val; - } else { - if (isfull(&t->t)) { - /* Need to resize the hash part, but we re-use the array part. */ - size_t i; - upb_table new_table; - - if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1, a)) { - return false; - } - - for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) { - const upb_tabent *e = &t->t.entries[i]; - uint32_t hash; - upb_value v; - - _upb_value_setval(&v, e->val.val, t->t.ctype); - hash = upb_inthash(e->key); - insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql); - } - - UPB_ASSERT(t->t.count == new_table.count); - - uninit(&t->t, a); - t->t = new_table; - } - insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql); - } - check(t); - return true; -} - -bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) { - const upb_tabval *table_v = inttable_val_const(t, key); - if (!table_v) return false; - if (v) _upb_value_setval(v, table_v->val, t->t.ctype); - return true; -} - -bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) { - upb_tabval *table_v = inttable_val(t, key); - if (!table_v) return false; - table_v->val = val.val; - return true; -} - -bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) { - bool success; - if (key < t->array_size) { - if (upb_arrhas(t->array[key])) { - upb_tabval empty = UPB_TABVALUE_EMPTY_INIT; - t->array_count--; - if (val) { - _upb_value_setval(val, t->array[key].val, t->t.ctype); - } - mutable_array(t)[key] = empty; - success = true; - } else { - success = false; - } - } else { - success = rm(&t->t, intkey(key), val, NULL, upb_inthash(key), &inteql); - } - check(t); - return success; -} - -bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a) { - upb_check_alloc(&t->t, a); - return upb_inttable_insert2(t, upb_inttable_count(t), val, a); -} - -upb_value upb_inttable_pop(upb_inttable *t) { - upb_value val; - bool ok = upb_inttable_remove(t, upb_inttable_count(t) - 1, &val); - UPB_ASSERT(ok); - return val; -} - -bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val, - upb_alloc *a) { - upb_check_alloc(&t->t, a); - return upb_inttable_insert2(t, (uintptr_t)key, val, a); -} - -bool upb_inttable_lookupptr(const upb_inttable *t, const void *key, - upb_value *v) { - return upb_inttable_lookup(t, (uintptr_t)key, v); -} - -bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) { - return upb_inttable_remove(t, (uintptr_t)key, val); -} - -void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) { - /* A power-of-two histogram of the table keys. */ - size_t counts[UPB_MAXARRSIZE + 1] = {0}; - - /* The max key in each bucket. */ - uintptr_t max[UPB_MAXARRSIZE + 1] = {0}; - - upb_inttable_iter i; - size_t arr_count; - int size_lg2; - upb_inttable new_t; - - upb_check_alloc(&t->t, a); - - upb_inttable_begin(&i, t); - for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { - uintptr_t key = upb_inttable_iter_key(&i); - int bucket = log2ceil(key); - max[bucket] = UPB_MAX(max[bucket], key); - counts[bucket]++; - } - - /* Find the largest power of two that satisfies the MIN_DENSITY - * definition (while actually having some keys). */ - arr_count = upb_inttable_count(t); - - for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) { - if (counts[size_lg2] == 0) { - /* We can halve again without losing any entries. */ - continue; - } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) { - break; - } - - arr_count -= counts[size_lg2]; - } - - UPB_ASSERT(arr_count <= upb_inttable_count(t)); - - { - /* Insert all elements into new, perfectly-sized table. */ - size_t arr_size = max[size_lg2] + 1; /* +1 so arr[max] will fit. */ - size_t hash_count = upb_inttable_count(t) - arr_count; - size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0; - size_t hashsize_lg2 = log2ceil(hash_size); - - upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2, a); - upb_inttable_begin(&i, t); - for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { - uintptr_t k = upb_inttable_iter_key(&i); - upb_inttable_insert2(&new_t, k, upb_inttable_iter_value(&i), a); - } - UPB_ASSERT(new_t.array_size == arr_size); - UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2); - } - upb_inttable_uninit2(t, a); - *t = new_t; -} - -/* Iteration. */ - -static const upb_tabent *int_tabent(const upb_inttable_iter *i) { - UPB_ASSERT(!i->array_part); - return &i->t->t.entries[i->index]; -} - -static upb_tabval int_arrent(const upb_inttable_iter *i) { - UPB_ASSERT(i->array_part); - return i->t->array[i->index]; -} - -void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) { - i->t = t; - i->index = -1; - i->array_part = true; - upb_inttable_next(i); -} - -void upb_inttable_next(upb_inttable_iter *iter) { - const upb_inttable *t = iter->t; - if (iter->array_part) { - while (++iter->index < t->array_size) { - if (upb_arrhas(int_arrent(iter))) { - return; - } - } - iter->array_part = false; - iter->index = begin(&t->t); - } else { - iter->index = next(&t->t, iter->index); - } -} - -bool upb_inttable_done(const upb_inttable_iter *i) { - if (i->array_part) { - return i->index >= i->t->array_size || - !upb_arrhas(int_arrent(i)); - } else { - return i->index >= upb_table_size(&i->t->t) || - upb_tabent_isempty(int_tabent(i)); - } -} - -uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) { - UPB_ASSERT(!upb_inttable_done(i)); - return i->array_part ? i->index : int_tabent(i)->key; -} - -upb_value upb_inttable_iter_value(const upb_inttable_iter *i) { - UPB_ASSERT(!upb_inttable_done(i)); - return _upb_value_val( - i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val, - i->t->t.ctype); -} - -void upb_inttable_iter_setdone(upb_inttable_iter *i) { - i->index = SIZE_MAX; - i->array_part = false; -} - -bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, - const upb_inttable_iter *i2) { - if (upb_inttable_done(i1) && upb_inttable_done(i2)) - return true; - return i1->t == i2->t && i1->index == i2->index && - i1->array_part == i2->array_part; -} - -#ifdef UPB_UNALIGNED_READS_OK -/* ----------------------------------------------------------------------------- - * MurmurHash2, by Austin Appleby (released as public domain). - * Reformatted and C99-ified by Joshua Haberman. - * Note - This code makes a few assumptions about how your machine behaves - - * 1. We can read a 4-byte value from any address without crashing - * 2. sizeof(int) == 4 (in upb this limitation is removed by using uint32_t - * And it has a few limitations - - * 1. It will not work incrementally. - * 2. It will not produce the same results on little-endian and big-endian - * machines. */ -uint32_t MurmurHash2(const void *key, size_t len, uint32_t seed) { - /* 'm' and 'r' are mixing constants generated offline. - * They're not really 'magic', they just happen to work well. */ - const uint32_t m = 0x5bd1e995; - const int32_t r = 24; - - /* Initialize the hash to a 'random' value */ - uint32_t h = seed ^ len; - - /* Mix 4 bytes at a time into the hash */ - const uint8_t * data = (const uint8_t *)key; - while(len >= 4) { - uint32_t k = *(uint32_t *)data; - - k *= m; - k ^= k >> r; - k *= m; - - h *= m; - h ^= k; - - data += 4; - len -= 4; - } - - /* Handle the last few bytes of the input array */ - switch(len) { - case 3: h ^= data[2] << 16; - case 2: h ^= data[1] << 8; - case 1: h ^= data[0]; h *= m; - }; - - /* Do a few final mixes of the hash to ensure the last few - * bytes are well-incorporated. */ - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return h; -} - -#else /* !UPB_UNALIGNED_READS_OK */ - -/* ----------------------------------------------------------------------------- - * MurmurHashAligned2, by Austin Appleby - * Same algorithm as MurmurHash2, but only does aligned reads - should be safer - * on certain platforms. - * Performance will be lower than MurmurHash2 */ - -#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; } - -uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed) { - const uint32_t m = 0x5bd1e995; - const int32_t r = 24; - const uint8_t * data = (const uint8_t *)key; - uint32_t h = seed ^ len; - uint8_t align = (uintptr_t)data & 3; - - if(align && (len >= 4)) { - /* Pre-load the temp registers */ - uint32_t t = 0, d = 0; - int32_t sl; - int32_t sr; - - switch(align) { - case 1: t |= data[2] << 16; - case 2: t |= data[1] << 8; - case 3: t |= data[0]; - } - - t <<= (8 * align); - - data += 4-align; - len -= 4-align; - - sl = 8 * (4-align); - sr = 8 * align; - - /* Mix */ - - while(len >= 4) { - uint32_t k; - - d = *(uint32_t *)data; - t = (t >> sr) | (d << sl); - - k = t; - - MIX(h,k,m); - - t = d; - - data += 4; - len -= 4; - } - - /* Handle leftover data in temp registers */ - - d = 0; - - if(len >= align) { - uint32_t k; - - switch(align) { - case 3: d |= data[2] << 16; - case 2: d |= data[1] << 8; - case 1: d |= data[0]; - } - - k = (t >> sr) | (d << sl); - MIX(h,k,m); - - data += align; - len -= align; - - /* ---------- - * Handle tail bytes */ - - switch(len) { - case 3: h ^= data[2] << 16; - case 2: h ^= data[1] << 8; - case 1: h ^= data[0]; h *= m; - }; - } else { - switch(len) { - case 3: d |= data[2] << 16; - case 2: d |= data[1] << 8; - case 1: d |= data[0]; - case 0: h ^= (t >> sr) | (d << sl); h *= m; - } - } - - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return h; - } else { - while(len >= 4) { - uint32_t k = *(uint32_t *)data; - - MIX(h,k,m); - - data += 4; - len -= 4; - } - - /* ---------- - * Handle tail bytes */ - - switch(len) { - case 3: h ^= data[2] << 16; - case 2: h ^= data[1] << 8; - case 1: h ^= data[0]; h *= m; - }; - - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return h; - } -} -#undef MIX - -#endif /* UPB_UNALIGNED_READS_OK */ - -#include -#include -#include -#include -#include -#include -#include - -bool upb_dumptostderr(void *closure, const upb_status* status) { - UPB_UNUSED(closure); - fprintf(stderr, "%s\n", upb_status_errmsg(status)); - return false; -} - -/* Guarantee null-termination and provide ellipsis truncation. - * It may be tempting to "optimize" this by initializing these final - * four bytes up-front and then being careful never to overwrite them, - * this is safer and simpler. */ -static void nullz(upb_status *status) { - const char *ellipsis = "..."; - size_t len = strlen(ellipsis); - UPB_ASSERT(sizeof(status->msg) > len); - memcpy(status->msg + sizeof(status->msg) - len, ellipsis, len); -} - - -/* upb_upberr *****************************************************************/ - -upb_errorspace upb_upberr = {"upb error"}; - -void upb_upberr_setoom(upb_status *status) { - status->error_space_ = &upb_upberr; - upb_status_seterrmsg(status, "Out of memory"); -} - - -/* upb_status *****************************************************************/ - -void upb_status_clear(upb_status *status) { - if (!status) return; - status->ok_ = true; - status->code_ = 0; - status->msg[0] = '\0'; -} - -bool upb_ok(const upb_status *status) { return status->ok_; } - -upb_errorspace *upb_status_errspace(const upb_status *status) { - return status->error_space_; -} - -int upb_status_errcode(const upb_status *status) { return status->code_; } - -const char *upb_status_errmsg(const upb_status *status) { return status->msg; } - -void upb_status_seterrmsg(upb_status *status, const char *msg) { - if (!status) return; - status->ok_ = false; - strncpy(status->msg, msg, sizeof(status->msg)); - nullz(status); -} - -void upb_status_seterrf(upb_status *status, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - upb_status_vseterrf(status, fmt, args); - va_end(args); -} - -void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) { - if (!status) return; - status->ok_ = false; - _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args); - nullz(status); -} - -void upb_status_copy(upb_status *to, const upb_status *from) { - if (!to) return; - *to = *from; -} - - -/* upb_alloc ******************************************************************/ - -static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize, - size_t size) { - UPB_UNUSED(alloc); - UPB_UNUSED(oldsize); - if (size == 0) { - free(ptr); - return NULL; - } else { - return realloc(ptr, size); - } -} - -upb_alloc upb_alloc_global = {&upb_global_allocfunc}; - - -/* upb_arena ******************************************************************/ - -/* Be conservative and choose 16 in case anyone is using SSE. */ -static const size_t maxalign = 16; - -static size_t align_up_max(size_t size) { - return ((size + maxalign - 1) / maxalign) * maxalign; -} - -typedef struct mem_block { - struct mem_block *next; - size_t size; - size_t used; - bool owned; - /* Data follows. */ -} mem_block; - -typedef struct cleanup_ent { - struct cleanup_ent *next; - upb_cleanup_func *cleanup; - void *ud; -} cleanup_ent; - -static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size, - bool owned) { - mem_block *block = ptr; - - block->next = a->block_head; - block->size = size; - block->used = align_up_max(sizeof(mem_block)); - block->owned = owned; - - a->block_head = block; - - /* TODO(haberman): ASAN poison. */ -} - - -static mem_block *upb_arena_allocblock(upb_arena *a, size_t size) { - size_t block_size = UPB_MAX(size, a->next_block_size) + sizeof(mem_block); - mem_block *block = upb_malloc(a->block_alloc, block_size); - - if (!block) { - return NULL; - } - - upb_arena_addblock(a, block, block_size, true); - a->next_block_size = UPB_MIN(block_size * 2, a->max_block_size); - - return block; -} - -static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize, - size_t size) { - upb_arena *a = (upb_arena*)alloc; /* upb_alloc is initial member. */ - mem_block *block = a->block_head; - void *ret; - - if (size == 0) { - return NULL; /* We are an arena, don't need individual frees. */ - } - - size = align_up_max(size); - - /* TODO(haberman): special-case if this is a realloc of the last alloc? */ - - if (!block || block->size - block->used < size) { - /* Slow path: have to allocate a new block. */ - block = upb_arena_allocblock(a, size); - - if (!block) { - return NULL; /* Out of memory. */ - } - } - - ret = (char*)block + block->used; - block->used += size; - - if (oldsize > 0) { - memcpy(ret, ptr, oldsize); /* Preserve existing data. */ - } - - /* TODO(haberman): ASAN unpoison. */ - - a->bytes_allocated += size; - return ret; -} - -/* Public Arena API ***********************************************************/ - -void upb_arena_init(upb_arena *a) { - a->alloc.func = &upb_arena_doalloc; - a->block_alloc = &upb_alloc_global; - a->bytes_allocated = 0; - a->next_block_size = 256; - a->max_block_size = 16384; - a->cleanup_head = NULL; - a->block_head = NULL; -} - -void upb_arena_init2(upb_arena *a, void *mem, size_t size, upb_alloc *alloc) { - upb_arena_init(a); - - if (size > sizeof(mem_block)) { - upb_arena_addblock(a, mem, size, false); - } - - if (alloc) { - a->block_alloc = alloc; - } -} - -void upb_arena_uninit(upb_arena *a) { - cleanup_ent *ent = a->cleanup_head; - mem_block *block = a->block_head; - - while (ent) { - ent->cleanup(ent->ud); - ent = ent->next; - } - - /* Must do this after running cleanup functions, because this will delete - * the memory we store our cleanup entries in! */ - while (block) { - mem_block *next = block->next; - - if (block->owned) { - upb_free(a->block_alloc, block); - } - - block = next; - } - - /* Protect against multiple-uninit. */ - a->cleanup_head = NULL; - a->block_head = NULL; -} - -bool upb_arena_addcleanup(upb_arena *a, upb_cleanup_func *func, void *ud) { - cleanup_ent *ent = upb_malloc(&a->alloc, sizeof(cleanup_ent)); - if (!ent) { - return false; /* Out of memory. */ - } - - ent->cleanup = func; - ent->ud = ud; - ent->next = a->cleanup_head; - a->cleanup_head = ent; - - return true; -} - -size_t upb_arena_bytesallocated(const upb_arena *a) { - return a->bytes_allocated; -} - - -/* Standard error functions ***************************************************/ - -static bool default_err(void *ud, const upb_status *status) { - UPB_UNUSED(ud); - UPB_UNUSED(status); - return false; -} - -static bool write_err_to(void *ud, const upb_status *status) { - upb_status *copy_to = ud; - upb_status_copy(copy_to, status); - return false; -} - - -/* upb_env ********************************************************************/ - -void upb_env_initonly(upb_env *e) { - e->ok_ = true; - e->error_func_ = &default_err; - e->error_ud_ = NULL; -} - -void upb_env_init(upb_env *e) { - upb_arena_init(&e->arena_); - upb_env_initonly(e); -} - -void upb_env_init2(upb_env *e, void *mem, size_t n, upb_alloc *alloc) { - upb_arena_init2(&e->arena_, mem, n, alloc); - upb_env_initonly(e); -} - -void upb_env_uninit(upb_env *e) { - upb_arena_uninit(&e->arena_); -} - -void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud) { - e->error_func_ = func; - e->error_ud_ = ud; -} - -void upb_env_reporterrorsto(upb_env *e, upb_status *s) { - e->error_func_ = &write_err_to; - e->error_ud_ = s; -} - -bool upb_env_reporterror(upb_env *e, const upb_status *status) { - e->ok_ = false; - return e->error_func_(e->error_ud_, status); -} - -void *upb_env_malloc(upb_env *e, size_t size) { - return upb_malloc(&e->arena_.alloc, size); -} - -void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size) { - return upb_realloc(&e->arena_.alloc, ptr, oldsize, size); -} - -void upb_env_free(upb_env *e, void *ptr) { - upb_free(&e->arena_.alloc, ptr); -} - -bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud) { - return upb_arena_addcleanup(&e->arena_, func, ud); -} - -size_t upb_env_bytesallocated(const upb_env *e) { - return upb_arena_bytesallocated(&e->arena_); -} -/* This file was generated by upbc (the upb compiler) from the input - * file: - * - * upb/descriptor/descriptor.proto - * - * Do not edit -- your changes will be discarded when the file is - * regenerated. */ - - -static const upb_msgdef msgs[22]; -static const upb_fielddef fields[107]; -static const upb_enumdef enums[5]; -static const upb_tabent strentries[236]; -static const upb_tabent intentries[18]; -static const upb_tabval arrays[187]; - -#ifdef UPB_DEBUG_REFS -static upb_inttable reftables[268]; -#endif - -static const upb_msgdef msgs[22] = { - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", 40, 8, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[0], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[0]), false, UPB_SYNTAX_PROTO2, &reftables[0], &reftables[1]), - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", 4, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[11], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[16]), false, UPB_SYNTAX_PROTO2, &reftables[2], &reftables[3]), - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ReservedRange", 4, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[14], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[20]), false, UPB_SYNTAX_PROTO2, &reftables[4], &reftables[5]), - UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[17], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[24]), false, UPB_SYNTAX_PROTO2, &reftables[6], &reftables[7]), - UPB_MSGDEF_INIT("google.protobuf.EnumOptions", 8, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[0], &arrays[21], 4, 2), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[28]), false, UPB_SYNTAX_PROTO2, &reftables[8], &reftables[9]), - UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", 8, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[25], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[32]), false, UPB_SYNTAX_PROTO2, &reftables[10], &reftables[11]), - UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", 7, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[2], &arrays[29], 2, 1), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[36]), false, UPB_SYNTAX_PROTO2, &reftables[12], &reftables[13]), - UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", 23, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[31], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[40]), false, UPB_SYNTAX_PROTO2, &reftables[14], &reftables[15]), - UPB_MSGDEF_INIT("google.protobuf.FieldOptions", 12, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[4], &arrays[42], 11, 6), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[56]), false, UPB_SYNTAX_PROTO2, &reftables[16], &reftables[17]), - UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", 42, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[53], 13, 12), UPB_STRTABLE_INIT(12, 15, UPB_CTYPE_PTR, 4, &strentries[72]), false, UPB_SYNTAX_PROTO2, &reftables[18], &reftables[19]), - UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[66], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[88]), false, UPB_SYNTAX_PROTO2, &reftables[20], &reftables[21]), - UPB_MSGDEF_INIT("google.protobuf.FileOptions", 37, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 42, 17), UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_PTR, 5, &strentries[92]), false, UPB_SYNTAX_PROTO2, &reftables[22], &reftables[23]), - UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 10, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[110], 8, 4), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[124]), false, UPB_SYNTAX_PROTO2, &reftables[24], &reftables[25]), - UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 15, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[118], 7, 6), UPB_STRTABLE_INIT(6, 7, UPB_CTYPE_PTR, 3, &strentries[132]), false, UPB_SYNTAX_PROTO2, &reftables[26], &reftables[27]), - UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[10], &arrays[125], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[140]), false, UPB_SYNTAX_PROTO2, &reftables[28], &reftables[29]), - UPB_MSGDEF_INIT("google.protobuf.OneofDescriptorProto", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[126], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[144]), false, UPB_SYNTAX_PROTO2, &reftables[30], &reftables[31]), - UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[128], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[148]), false, UPB_SYNTAX_PROTO2, &reftables[32], &reftables[33]), - UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[14], &arrays[132], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[152]), false, UPB_SYNTAX_PROTO2, &reftables[34], &reftables[35]), - UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[133], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[156]), false, UPB_SYNTAX_PROTO2, &reftables[36], &reftables[37]), - UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 19, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[135], 7, 5), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[160]), false, UPB_SYNTAX_PROTO2, &reftables[38], &reftables[39]), - UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 18, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[142], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[168]), false, UPB_SYNTAX_PROTO2, &reftables[40], &reftables[41]), - UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[151], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[184]), false, UPB_SYNTAX_PROTO2, &reftables[42], &reftables[43]), -}; - -static const upb_fielddef fields[107] = { - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "aggregate_value", 8, &msgs[20], NULL, 15, 6, {0},&reftables[44], &reftables[45]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "allow_alias", 2, &msgs[4], NULL, 6, 1, {0},&reftables[46], &reftables[47]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_enable_arenas", 31, &msgs[11], NULL, 23, 12, {0},&reftables[48], &reftables[49]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_generic_services", 16, &msgs[11], NULL, 17, 6, {0},&reftables[50], &reftables[51]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "client_streaming", 5, &msgs[13], NULL, 13, 4, {0},&reftables[52], &reftables[53]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "csharp_namespace", 37, &msgs[11], NULL, 27, 14, {0},&reftables[54], &reftables[55]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "ctype", 1, &msgs[8], (const upb_def*)(&enums[2]), 6, 1, {0},&reftables[56], &reftables[57]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "default_value", 7, &msgs[7], NULL, 16, 7, {0},&reftables[58], &reftables[59]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "dependency", 3, &msgs[9], NULL, 30, 8, {0},&reftables[60], &reftables[61]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[8], NULL, 8, 3, {0},&reftables[62], &reftables[63]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[14], NULL, 6, 1, {0},&reftables[64], &reftables[65]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[12], NULL, 8, 3, {0},&reftables[66], &reftables[67]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 23, &msgs[11], NULL, 21, 10, {0},&reftables[68], &reftables[69]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 1, &msgs[6], NULL, 6, 1, {0},&reftables[70], &reftables[71]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[4], NULL, 7, 2, {0},&reftables[72], &reftables[73]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[17], NULL, 6, 1, {0},&reftables[74], &reftables[75]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, false, false, false, "double_value", 6, &msgs[20], NULL, 11, 4, {0},&reftables[76], &reftables[77]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[2], NULL, 3, 1, {0},&reftables[78], &reftables[79]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[1], NULL, 3, 1, {0},&reftables[80], &reftables[81]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 5, &msgs[9], (const upb_def*)(&msgs[3]), 13, 1, {0},&reftables[82], &reftables[83]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 4, &msgs[0], (const upb_def*)(&msgs[3]), 18, 2, {0},&reftables[84], &reftables[85]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "extendee", 2, &msgs[7], NULL, 7, 2, {0},&reftables[86], &reftables[87]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 6, &msgs[0], (const upb_def*)(&msgs[7]), 24, 4, {0},&reftables[88], &reftables[89]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 7, &msgs[9], (const upb_def*)(&msgs[7]), 19, 3, {0},&reftables[90], &reftables[91]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension_range", 5, &msgs[0], (const upb_def*)(&msgs[1]), 21, 3, {0},&reftables[92], &reftables[93]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "field", 2, &msgs[0], (const upb_def*)(&msgs[7]), 12, 0, {0},&reftables[94], &reftables[95]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "file", 1, &msgs[10], (const upb_def*)(&msgs[9]), 5, 0, {0},&reftables[96], &reftables[97]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "go_package", 11, &msgs[11], NULL, 14, 5, {0},&reftables[98], &reftables[99]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "identifier_value", 3, &msgs[20], NULL, 6, 1, {0},&reftables[100], &reftables[101]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "input_type", 2, &msgs[13], NULL, 7, 2, {0},&reftables[102], &reftables[103]), - UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, false, false, false, "is_extension", 2, &msgs[21], NULL, 5, 1, {0},&reftables[104], &reftables[105]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generate_equals_and_hash", 20, &msgs[11], NULL, 20, 9, {0},&reftables[106], &reftables[107]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generic_services", 17, &msgs[11], NULL, 18, 7, {0},&reftables[108], &reftables[109]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_multiple_files", 10, &msgs[11], NULL, 13, 4, {0},&reftables[110], &reftables[111]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_outer_classname", 8, &msgs[11], NULL, 9, 2, {0},&reftables[112], &reftables[113]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_package", 1, &msgs[11], NULL, 6, 1, {0},&reftables[114], &reftables[115]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_string_check_utf8", 27, &msgs[11], NULL, 22, 11, {0},&reftables[116], &reftables[117]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "javanano_use_deprecated_package", 38, &msgs[11], NULL, 30, 15, {0},&reftables[118], &reftables[119]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "json_name", 10, &msgs[7], NULL, 20, 9, {0},&reftables[120], &reftables[121]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "jstype", 6, &msgs[8], (const upb_def*)(&enums[3]), 10, 5, {0},&reftables[122], &reftables[123]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "label", 4, &msgs[7], (const upb_def*)(&enums[0]), 11, 4, {0},&reftables[124], &reftables[125]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "lazy", 5, &msgs[8], NULL, 9, 4, {0},&reftables[126], &reftables[127]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "leading_comments", 3, &msgs[19], NULL, 8, 2, {0},&reftables[128], &reftables[129]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "leading_detached_comments", 6, &msgs[19], NULL, 16, 4, {0},&reftables[130], &reftables[131]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "location", 1, &msgs[18], (const upb_def*)(&msgs[19]), 5, 0, {0},&reftables[132], &reftables[133]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "map_entry", 7, &msgs[12], NULL, 9, 4, {0},&reftables[134], &reftables[135]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "message_set_wire_format", 1, &msgs[12], NULL, 6, 1, {0},&reftables[136], &reftables[137]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "message_type", 4, &msgs[9], (const upb_def*)(&msgs[0]), 10, 0, {0},&reftables[138], &reftables[139]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "method", 2, &msgs[16], (const upb_def*)(&msgs[13]), 6, 0, {0},&reftables[140], &reftables[141]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "name", 2, &msgs[20], (const upb_def*)(&msgs[21]), 5, 0, {0},&reftables[142], &reftables[143]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[5], NULL, 4, 1, {0},&reftables[144], &reftables[145]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[9], NULL, 22, 6, {0},&reftables[146], &reftables[147]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[3], NULL, 8, 2, {0},&reftables[148], &reftables[149]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[16], NULL, 8, 2, {0},&reftables[150], &reftables[151]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[15], NULL, 2, 0, {0},&reftables[152], &reftables[153]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[13], NULL, 4, 1, {0},&reftables[154], &reftables[155]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[7], NULL, 4, 1, {0},&reftables[156], &reftables[157]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 32, 8, {0},&reftables[158], &reftables[159]), - UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, false, false, false, "name_part", 1, &msgs[21], NULL, 2, 0, {0},&reftables[160], &reftables[161]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, false, false, false, "negative_int_value", 5, &msgs[20], NULL, 10, 3, {0},&reftables[162], &reftables[163]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "nested_type", 3, &msgs[0], (const upb_def*)(&msgs[0]), 15, 1, {0},&reftables[164], &reftables[165]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "no_standard_descriptor_accessor", 2, &msgs[12], NULL, 7, 2, {0},&reftables[166], &reftables[167]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 3, &msgs[7], NULL, 10, 3, {0},&reftables[168], &reftables[169]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 2, &msgs[5], NULL, 7, 2, {0},&reftables[170], &reftables[171]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "objc_class_prefix", 36, &msgs[11], NULL, 24, 13, {0},&reftables[172], &reftables[173]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "oneof_decl", 8, &msgs[0], (const upb_def*)(&msgs[15]), 28, 6, {0},&reftables[174], &reftables[175]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "oneof_index", 9, &msgs[7], NULL, 19, 8, {0},&reftables[176], &reftables[177]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "optimize_for", 9, &msgs[11], (const upb_def*)(&enums[4]), 12, 3, {0},&reftables[178], &reftables[179]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 7, &msgs[0], (const upb_def*)(&msgs[12]), 25, 5, {0},&reftables[180], &reftables[181]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[9], (const upb_def*)(&msgs[11]), 20, 4, {0},&reftables[182], &reftables[183]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[7], (const upb_def*)(&msgs[8]), 3, 0, {0},&reftables[184], &reftables[185]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 4, &msgs[13], (const upb_def*)(&msgs[14]), 3, 0, {0},&reftables[186], &reftables[187]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[16], (const upb_def*)(&msgs[17]), 7, 1, {0},&reftables[188], &reftables[189]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[3], (const upb_def*)(&msgs[4]), 7, 1, {0},&reftables[190], &reftables[191]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[5], (const upb_def*)(&msgs[6]), 3, 0, {0},&reftables[192], &reftables[193]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "output_type", 3, &msgs[13], NULL, 10, 3, {0},&reftables[194], &reftables[195]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "package", 2, &msgs[9], NULL, 25, 7, {0},&reftables[196], &reftables[197]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "packed", 2, &msgs[8], NULL, 7, 2, {0},&reftables[198], &reftables[199]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "path", 1, &msgs[19], NULL, 4, 0, {0},&reftables[200], &reftables[201]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "php_class_prefix", 40, &msgs[11], NULL, 31, 16, {0},&reftables[202], &reftables[203]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "php_namespace", 41, &msgs[11], NULL, 34, 17, {0},&reftables[204], &reftables[205]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, false, "positive_int_value", 4, &msgs[20], NULL, 9, 2, {0},&reftables[206], &reftables[207]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "public_dependency", 10, &msgs[9], NULL, 35, 9, {0},&reftables[208], &reftables[209]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "py_generic_services", 18, &msgs[11], NULL, 19, 8, {0},&reftables[210], &reftables[211]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "reserved_name", 10, &msgs[0], NULL, 37, 9, {0},&reftables[212], &reftables[213]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "reserved_range", 9, &msgs[0], (const upb_def*)(&msgs[2]), 31, 7, {0},&reftables[214], &reftables[215]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "server_streaming", 6, &msgs[13], NULL, 14, 5, {0},&reftables[216], &reftables[217]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "service", 6, &msgs[9], (const upb_def*)(&msgs[16]), 16, 2, {0},&reftables[218], &reftables[219]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "source_code_info", 9, &msgs[9], (const upb_def*)(&msgs[18]), 21, 5, {0},&reftables[220], &reftables[221]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "span", 2, &msgs[19], NULL, 7, 1, {0},&reftables[222], &reftables[223]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[2], NULL, 2, 0, {0},&reftables[224], &reftables[225]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[1], NULL, 2, 0, {0},&reftables[226], &reftables[227]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[20], NULL, 12, 5, {0},&reftables[228], &reftables[229]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "syntax", 12, &msgs[9], NULL, 39, 11, {0},&reftables[230], &reftables[231]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[19], NULL, 11, 3, {0},&reftables[232], &reftables[233]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "type", 5, &msgs[7], (const upb_def*)(&enums[1]), 12, 5, {0},&reftables[234], &reftables[235]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[7], NULL, 13, 6, {0},&reftables[236], &reftables[237]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[12], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[238], &reftables[239]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[17], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[240], &reftables[241]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[11], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[242], &reftables[243]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[14], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[244], &reftables[245]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[8], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[246], &reftables[247]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[6], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[248], &reftables[249]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[4], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[250], &reftables[251]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "value", 2, &msgs[3], (const upb_def*)(&msgs[5]), 6, 0, {0},&reftables[252], &reftables[253]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[8], NULL, 11, 6, {0},&reftables[254], &reftables[255]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "weak_dependency", 11, &msgs[9], NULL, 38, 10, {0},&reftables[256], &reftables[257]), -}; - -static const upb_enumdef enums[5] = { - UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[188]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[154], 4, 3), 0, &reftables[258], &reftables[259]), - UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_INT32, 5, &strentries[192]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[158], 19, 18), 0, &reftables[260], &reftables[261]), - UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[224]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[177], 3, 3), 0, &reftables[262], &reftables[263]), - UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.JSType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[228]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[180], 3, 3), 0, &reftables[264], &reftables[265]), - UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[232]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[183], 4, 3), 0, &reftables[266], &reftables[267]), -}; - -static const upb_tabent strentries[236] = { - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[22]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "reserved_name"), UPB_TABVALUE_PTR_INIT(&fields[84]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[57]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "field"), UPB_TABVALUE_PTR_INIT(&fields[25]), &strentries[12]}, - {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "extension_range"), UPB_TABVALUE_PTR_INIT(&fields[24]), &strentries[14]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "nested_type"), UPB_TABVALUE_PTR_INIT(&fields[60]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "reserved_range"), UPB_TABVALUE_PTR_INIT(&fields[85]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[68]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "oneof_decl"), UPB_TABVALUE_PTR_INIT(&fields[65]), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[20]), &strentries[13]}, - {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[91]), NULL}, - {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[18]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[90]), NULL}, - {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[17]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "value"), UPB_TABVALUE_PTR_INIT(&fields[104]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[52]), &strentries[26]}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "allow_alias"), UPB_TABVALUE_PTR_INIT(&fields[1]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[63]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[50]), &strentries[34]}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[102]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[13]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "oneof_index"), UPB_TABVALUE_PTR_INIT(&fields[66]), NULL}, - {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "label"), UPB_TABVALUE_PTR_INIT(&fields[40]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[56]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[62]), &strentries[53]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "extendee"), UPB_TABVALUE_PTR_INIT(&fields[21]), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "type_name"), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "json_name"), UPB_TABVALUE_PTR_INIT(&fields[38]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "type"), UPB_TABVALUE_PTR_INIT(&fields[95]), &strentries[50]}, - {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "default_value"), UPB_TABVALUE_PTR_INIT(&fields[7]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[70]), NULL}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "weak"), UPB_TABVALUE_PTR_INIT(&fields[105]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "packed"), UPB_TABVALUE_PTR_INIT(&fields[77]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "lazy"), UPB_TABVALUE_PTR_INIT(&fields[41]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "ctype"), UPB_TABVALUE_PTR_INIT(&fields[6]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "jstype"), UPB_TABVALUE_PTR_INIT(&fields[39]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[9]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[23]), NULL}, - {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "weak_dependency"), UPB_TABVALUE_PTR_INIT(&fields[106]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[51]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "service"), UPB_TABVALUE_PTR_INIT(&fields[87]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "source_code_info"), UPB_TABVALUE_PTR_INIT(&fields[88]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "syntax"), UPB_TABVALUE_PTR_INIT(&fields[93]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "dependency"), UPB_TABVALUE_PTR_INIT(&fields[8]), NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "message_type"), UPB_TABVALUE_PTR_INIT(&fields[47]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "package"), UPB_TABVALUE_PTR_INIT(&fields[76]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[69]), &strentries[86]}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[19]), NULL}, - {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "public_dependency"), UPB_TABVALUE_PTR_INIT(&fields[82]), &strentries[85]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "file"), UPB_TABVALUE_PTR_INIT(&fields[26]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "cc_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[3]), NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "csharp_namespace"), UPB_TABVALUE_PTR_INIT(&fields[5]), &strentries[116]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "go_package"), UPB_TABVALUE_PTR_INIT(&fields[27]), NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "java_package"), UPB_TABVALUE_PTR_INIT(&fields[35]), &strentries[120]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "java_outer_classname"), UPB_TABVALUE_PTR_INIT(&fields[34]), NULL}, - {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "php_namespace"), UPB_TABVALUE_PTR_INIT(&fields[80]), &strentries[113]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "java_multiple_files"), UPB_TABVALUE_PTR_INIT(&fields[33]), &strentries[117]}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL}, - {UPB_TABKEY_STR("\025", "\000", "\000", "\000", "java_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[32]), &strentries[118]}, - {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "java_generate_equals_and_hash"), UPB_TABVALUE_PTR_INIT(&fields[31]), NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "php_class_prefix"), UPB_TABVALUE_PTR_INIT(&fields[79]), NULL}, - {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "javanano_use_deprecated_package"), UPB_TABVALUE_PTR_INIT(&fields[37]), &strentries[123]}, - {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "py_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[83]), NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "optimize_for"), UPB_TABVALUE_PTR_INIT(&fields[67]), NULL}, - {UPB_TABKEY_STR("\026", "\000", "\000", "\000", "java_string_check_utf8"), UPB_TABVALUE_PTR_INIT(&fields[36]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[12]), &strentries[119]}, - {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "objc_class_prefix"), UPB_TABVALUE_PTR_INIT(&fields[64]), NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "cc_enable_arenas"), UPB_TABVALUE_PTR_INIT(&fields[2]), NULL}, - {UPB_TABKEY_STR("\027", "\000", "\000", "\000", "message_set_wire_format"), UPB_TABVALUE_PTR_INIT(&fields[46]), &strentries[128]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "map_entry"), UPB_TABVALUE_PTR_INIT(&fields[45]), NULL}, - {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "no_standard_descriptor_accessor"), UPB_TABVALUE_PTR_INIT(&fields[61]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "client_streaming"), UPB_TABVALUE_PTR_INIT(&fields[4]), NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "server_streaming"), UPB_TABVALUE_PTR_INIT(&fields[86]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[55]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "input_type"), UPB_TABVALUE_PTR_INIT(&fields[29]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "output_type"), UPB_TABVALUE_PTR_INIT(&fields[75]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[54]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[72]), &strentries[150]}, - {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "method"), UPB_TABVALUE_PTR_INIT(&fields[48]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[53]), &strentries[149]}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "location"), UPB_TABVALUE_PTR_INIT(&fields[44]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "span"), UPB_TABVALUE_PTR_INIT(&fields[89]), &strentries[167]}, - {UPB_TABKEY_STR("\031", "\000", "\000", "\000", "leading_detached_comments"), UPB_TABVALUE_PTR_INIT(&fields[43]), &strentries[165]}, - {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "trailing_comments"), UPB_TABVALUE_PTR_INIT(&fields[94]), NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "leading_comments"), UPB_TABVALUE_PTR_INIT(&fields[42]), &strentries[164]}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "path"), UPB_TABVALUE_PTR_INIT(&fields[78]), NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "double_value"), UPB_TABVALUE_PTR_INIT(&fields[16]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[49]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "negative_int_value"), UPB_TABVALUE_PTR_INIT(&fields[59]), NULL}, - {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "aggregate_value"), UPB_TABVALUE_PTR_INIT(&fields[0]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "positive_int_value"), UPB_TABVALUE_PTR_INIT(&fields[81]), NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "identifier_value"), UPB_TABVALUE_PTR_INIT(&fields[28]), NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "string_value"), UPB_TABVALUE_PTR_INIT(&fields[92]), &strentries[182]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "is_extension"), UPB_TABVALUE_PTR_INIT(&fields[30]), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "name_part"), UPB_TABVALUE_PTR_INIT(&fields[58]), NULL}, - {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REQUIRED"), UPB_TABVALUE_INT_INIT(2), &strentries[190]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REPEATED"), UPB_TABVALUE_INT_INIT(3), NULL}, - {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_OPTIONAL"), UPB_TABVALUE_INT_INIT(1), NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED64"), UPB_TABVALUE_INT_INIT(6), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_STRING"), UPB_TABVALUE_INT_INIT(9), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_FLOAT"), UPB_TABVALUE_INT_INIT(2), &strentries[221]}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_DOUBLE"), UPB_TABVALUE_INT_INIT(1), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT32"), UPB_TABVALUE_INT_INIT(5), NULL}, - {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED32"), UPB_TABVALUE_INT_INIT(15), NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED32"), UPB_TABVALUE_INT_INIT(7), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_MESSAGE"), UPB_TABVALUE_INT_INIT(11), &strentries[222]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT64"), UPB_TABVALUE_INT_INIT(3), &strentries[219]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_ENUM"), UPB_TABVALUE_INT_INIT(14), NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT32"), UPB_TABVALUE_INT_INIT(13), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT64"), UPB_TABVALUE_INT_INIT(4), &strentries[218]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED64"), UPB_TABVALUE_INT_INIT(16), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_BYTES"), UPB_TABVALUE_INT_INIT(12), NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT64"), UPB_TABVALUE_INT_INIT(18), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_BOOL"), UPB_TABVALUE_INT_INIT(8), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_GROUP"), UPB_TABVALUE_INT_INIT(10), NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT32"), UPB_TABVALUE_INT_INIT(17), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "CORD"), UPB_TABVALUE_INT_INIT(1), NULL}, - {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "STRING"), UPB_TABVALUE_INT_INIT(0), &strentries[225]}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "STRING_PIECE"), UPB_TABVALUE_INT_INIT(2), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_NORMAL"), UPB_TABVALUE_INT_INIT(0), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_NUMBER"), UPB_TABVALUE_INT_INIT(2), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_STRING"), UPB_TABVALUE_INT_INIT(1), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "CODE_SIZE"), UPB_TABVALUE_INT_INIT(2), NULL}, - {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "SPEED"), UPB_TABVALUE_INT_INIT(1), &strentries[235]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "LITE_RUNTIME"), UPB_TABVALUE_INT_INIT(3), NULL}, -}; - -static const upb_tabent intentries[18] = { - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[102]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL}, -}; - -static const upb_tabval arrays[187] = { - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[57]), - UPB_TABVALUE_PTR_INIT(&fields[25]), - UPB_TABVALUE_PTR_INIT(&fields[60]), - UPB_TABVALUE_PTR_INIT(&fields[20]), - UPB_TABVALUE_PTR_INIT(&fields[24]), - UPB_TABVALUE_PTR_INIT(&fields[22]), - UPB_TABVALUE_PTR_INIT(&fields[68]), - UPB_TABVALUE_PTR_INIT(&fields[65]), - UPB_TABVALUE_PTR_INIT(&fields[85]), - UPB_TABVALUE_PTR_INIT(&fields[84]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[91]), - UPB_TABVALUE_PTR_INIT(&fields[18]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[90]), - UPB_TABVALUE_PTR_INIT(&fields[17]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[52]), - UPB_TABVALUE_PTR_INIT(&fields[104]), - UPB_TABVALUE_PTR_INIT(&fields[73]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[1]), - UPB_TABVALUE_PTR_INIT(&fields[14]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[50]), - UPB_TABVALUE_PTR_INIT(&fields[63]), - UPB_TABVALUE_PTR_INIT(&fields[74]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[13]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[56]), - UPB_TABVALUE_PTR_INIT(&fields[21]), - UPB_TABVALUE_PTR_INIT(&fields[62]), - UPB_TABVALUE_PTR_INIT(&fields[40]), - UPB_TABVALUE_PTR_INIT(&fields[95]), - UPB_TABVALUE_PTR_INIT(&fields[96]), - UPB_TABVALUE_PTR_INIT(&fields[7]), - UPB_TABVALUE_PTR_INIT(&fields[70]), - UPB_TABVALUE_PTR_INIT(&fields[66]), - UPB_TABVALUE_PTR_INIT(&fields[38]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[6]), - UPB_TABVALUE_PTR_INIT(&fields[77]), - UPB_TABVALUE_PTR_INIT(&fields[9]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[41]), - UPB_TABVALUE_PTR_INIT(&fields[39]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[105]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[51]), - UPB_TABVALUE_PTR_INIT(&fields[76]), - UPB_TABVALUE_PTR_INIT(&fields[8]), - UPB_TABVALUE_PTR_INIT(&fields[47]), - UPB_TABVALUE_PTR_INIT(&fields[19]), - UPB_TABVALUE_PTR_INIT(&fields[87]), - UPB_TABVALUE_PTR_INIT(&fields[23]), - UPB_TABVALUE_PTR_INIT(&fields[69]), - UPB_TABVALUE_PTR_INIT(&fields[88]), - UPB_TABVALUE_PTR_INIT(&fields[82]), - UPB_TABVALUE_PTR_INIT(&fields[106]), - UPB_TABVALUE_PTR_INIT(&fields[93]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[26]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[35]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[34]), - UPB_TABVALUE_PTR_INIT(&fields[67]), - UPB_TABVALUE_PTR_INIT(&fields[33]), - UPB_TABVALUE_PTR_INIT(&fields[27]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[3]), - UPB_TABVALUE_PTR_INIT(&fields[32]), - UPB_TABVALUE_PTR_INIT(&fields[83]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[31]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[12]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[36]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[2]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[64]), - UPB_TABVALUE_PTR_INIT(&fields[5]), - UPB_TABVALUE_PTR_INIT(&fields[37]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[79]), - UPB_TABVALUE_PTR_INIT(&fields[80]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[46]), - UPB_TABVALUE_PTR_INIT(&fields[61]), - UPB_TABVALUE_PTR_INIT(&fields[11]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[45]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[55]), - UPB_TABVALUE_PTR_INIT(&fields[29]), - UPB_TABVALUE_PTR_INIT(&fields[75]), - UPB_TABVALUE_PTR_INIT(&fields[71]), - UPB_TABVALUE_PTR_INIT(&fields[4]), - UPB_TABVALUE_PTR_INIT(&fields[86]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[54]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[53]), - UPB_TABVALUE_PTR_INIT(&fields[48]), - UPB_TABVALUE_PTR_INIT(&fields[72]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[44]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[78]), - UPB_TABVALUE_PTR_INIT(&fields[89]), - UPB_TABVALUE_PTR_INIT(&fields[42]), - UPB_TABVALUE_PTR_INIT(&fields[94]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[43]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[49]), - UPB_TABVALUE_PTR_INIT(&fields[28]), - UPB_TABVALUE_PTR_INIT(&fields[81]), - UPB_TABVALUE_PTR_INIT(&fields[59]), - UPB_TABVALUE_PTR_INIT(&fields[16]), - UPB_TABVALUE_PTR_INIT(&fields[92]), - UPB_TABVALUE_PTR_INIT(&fields[0]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[58]), - UPB_TABVALUE_PTR_INIT(&fields[30]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT("LABEL_OPTIONAL"), - UPB_TABVALUE_PTR_INIT("LABEL_REQUIRED"), - UPB_TABVALUE_PTR_INIT("LABEL_REPEATED"), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT("TYPE_DOUBLE"), - UPB_TABVALUE_PTR_INIT("TYPE_FLOAT"), - UPB_TABVALUE_PTR_INIT("TYPE_INT64"), - UPB_TABVALUE_PTR_INIT("TYPE_UINT64"), - UPB_TABVALUE_PTR_INIT("TYPE_INT32"), - UPB_TABVALUE_PTR_INIT("TYPE_FIXED64"), - UPB_TABVALUE_PTR_INIT("TYPE_FIXED32"), - UPB_TABVALUE_PTR_INIT("TYPE_BOOL"), - UPB_TABVALUE_PTR_INIT("TYPE_STRING"), - UPB_TABVALUE_PTR_INIT("TYPE_GROUP"), - UPB_TABVALUE_PTR_INIT("TYPE_MESSAGE"), - UPB_TABVALUE_PTR_INIT("TYPE_BYTES"), - UPB_TABVALUE_PTR_INIT("TYPE_UINT32"), - UPB_TABVALUE_PTR_INIT("TYPE_ENUM"), - UPB_TABVALUE_PTR_INIT("TYPE_SFIXED32"), - UPB_TABVALUE_PTR_INIT("TYPE_SFIXED64"), - UPB_TABVALUE_PTR_INIT("TYPE_SINT32"), - UPB_TABVALUE_PTR_INIT("TYPE_SINT64"), - UPB_TABVALUE_PTR_INIT("STRING"), - UPB_TABVALUE_PTR_INIT("CORD"), - UPB_TABVALUE_PTR_INIT("STRING_PIECE"), - UPB_TABVALUE_PTR_INIT("JS_NORMAL"), - UPB_TABVALUE_PTR_INIT("JS_STRING"), - UPB_TABVALUE_PTR_INIT("JS_NUMBER"), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT("SPEED"), - UPB_TABVALUE_PTR_INIT("CODE_SIZE"), - UPB_TABVALUE_PTR_INIT("LITE_RUNTIME"), -}; - -#ifdef UPB_DEBUG_REFS -static upb_inttable reftables[268] = { - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), -}; -#endif - -static const upb_msgdef *refm(const upb_msgdef *m, const void *owner) { - upb_msgdef_ref(m, owner); - return m; -} - -static const upb_enumdef *refe(const upb_enumdef *e, const void *owner) { - upb_enumdef_ref(e, owner); - return e; -} - -/* Public API. */ -const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_get(const void *owner) { return refm(&msgs[0], owner); } -const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(const void *owner) { return refm(&msgs[1], owner); } -const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(const void *owner) { return refm(&msgs[2], owner); } -const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto_get(const void *owner) { return refm(&msgs[3], owner); } -const upb_msgdef *upbdefs_google_protobuf_EnumOptions_get(const void *owner) { return refm(&msgs[4], owner); } -const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto_get(const void *owner) { return refm(&msgs[5], owner); } -const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions_get(const void *owner) { return refm(&msgs[6], owner); } -const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto_get(const void *owner) { return refm(&msgs[7], owner); } -const upb_msgdef *upbdefs_google_protobuf_FieldOptions_get(const void *owner) { return refm(&msgs[8], owner); } -const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto_get(const void *owner) { return refm(&msgs[9], owner); } -const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet_get(const void *owner) { return refm(&msgs[10], owner); } -const upb_msgdef *upbdefs_google_protobuf_FileOptions_get(const void *owner) { return refm(&msgs[11], owner); } -const upb_msgdef *upbdefs_google_protobuf_MessageOptions_get(const void *owner) { return refm(&msgs[12], owner); } -const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto_get(const void *owner) { return refm(&msgs[13], owner); } -const upb_msgdef *upbdefs_google_protobuf_MethodOptions_get(const void *owner) { return refm(&msgs[14], owner); } -const upb_msgdef *upbdefs_google_protobuf_OneofDescriptorProto_get(const void *owner) { return refm(&msgs[15], owner); } -const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto_get(const void *owner) { return refm(&msgs[16], owner); } -const upb_msgdef *upbdefs_google_protobuf_ServiceOptions_get(const void *owner) { return refm(&msgs[17], owner); } -const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_get(const void *owner) { return refm(&msgs[18], owner); } -const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location_get(const void *owner) { return refm(&msgs[19], owner); } -const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_get(const void *owner) { return refm(&msgs[20], owner); } -const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart_get(const void *owner) { return refm(&msgs[21], owner); } - -const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label_get(const void *owner) { return refe(&enums[0], owner); } -const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type_get(const void *owner) { return refe(&enums[1], owner); } -const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType_get(const void *owner) { return refe(&enums[2], owner); } -const upb_enumdef *upbdefs_google_protobuf_FieldOptions_JSType_get(const void *owner) { return refe(&enums[3], owner); } -const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode_get(const void *owner) { return refe(&enums[4], owner); } -/* -** XXX: The routines in this file that consume a string do not currently -** support having the string span buffers. In the future, as upb_sink and -** its buffering/sharing functionality evolve there should be an easy and -** idiomatic way of correctly handling this case. For now, we accept this -** limitation since we currently only parse descriptors from single strings. -*/ - - -#include -#include -#include - -/* Compares a NULL-terminated string with a non-NULL-terminated string. */ -static bool upb_streq(const char *str, const char *buf, size_t n) { - return strlen(str) == n && memcmp(str, buf, n) == 0; -} - -/* We keep a stack of all the messages scopes we are currently in, as well as - * the top-level file scope. This is necessary to correctly qualify the - * definitions that are contained inside. "name" tracks the name of the - * message or package (a bare name -- not qualified by any enclosing scopes). */ -typedef struct { - char *name; - /* Index of the first def that is under this scope. For msgdefs, the - * msgdef itself is at start-1. */ - int start; - uint32_t oneof_start; - uint32_t oneof_index; -} upb_descreader_frame; - -/* The maximum number of nested declarations that are allowed, ie. - * message Foo { - * message Bar { - * message Baz { - * } - * } - * } - * - * This is a resource limit that affects how big our runtime stack can grow. - * TODO: make this a runtime-settable property of the Reader instance. */ -#define UPB_MAX_MESSAGE_NESTING 64 - -struct upb_descreader { - upb_sink sink; - upb_inttable files; - upb_filedef *file; /* The last file in files. */ - upb_descreader_frame stack[UPB_MAX_MESSAGE_NESTING]; - int stack_len; - upb_inttable oneofs; - - uint32_t number; - char *name; - bool saw_number; - bool saw_name; - - char *default_string; - - upb_fielddef *f; -}; - -static char *upb_gstrndup(const char *buf, size_t n) { - char *ret = upb_gmalloc(n + 1); - if (!ret) return NULL; - memcpy(ret, buf, n); - ret[n] = '\0'; - return ret; -} - -/* Returns a newly allocated string that joins input strings together, for - * example: - * join("Foo.Bar", "Baz") -> "Foo.Bar.Baz" - * join("", "Baz") -> "Baz" - * Caller owns a ref on the returned string. */ -static char *upb_join(const char *base, const char *name) { - if (!base || strlen(base) == 0) { - return upb_gstrdup(name); - } else { - char *ret = upb_gmalloc(strlen(base) + strlen(name) + 2); - if (!ret) { - return NULL; - } - ret[0] = '\0'; - strcat(ret, base); - strcat(ret, "."); - strcat(ret, name); - return ret; - } -} - -/* Qualify the defname for all defs starting with offset "start" with "str". */ -static bool upb_descreader_qualify(upb_filedef *f, char *str, int32_t start) { - size_t i; - for (i = start; i < upb_filedef_defcount(f); i++) { - upb_def *def = upb_filedef_mutabledef(f, i); - char *name = upb_join(str, upb_def_fullname(def)); - if (!name) { - /* Need better logic here; at this point we've qualified some names but - * not others. */ - return false; - } - upb_def_setfullname(def, name, NULL); - upb_gfree(name); - } - return true; -} - - -/* upb_descreader ************************************************************/ - -static upb_msgdef *upb_descreader_top(upb_descreader *r) { - int index; - UPB_ASSERT(r->stack_len > 1); - index = r->stack[r->stack_len-1].start - 1; - UPB_ASSERT(index >= 0); - return upb_downcast_msgdef_mutable(upb_filedef_mutabledef(r->file, index)); -} - -static upb_def *upb_descreader_last(upb_descreader *r) { - return upb_filedef_mutabledef(r->file, upb_filedef_defcount(r->file) - 1); -} - -/* Start/end handlers for FileDescriptorProto and DescriptorProto (the two - * entities that have names and can contain sub-definitions. */ -void upb_descreader_startcontainer(upb_descreader *r) { - upb_descreader_frame *f = &r->stack[r->stack_len++]; - f->start = upb_filedef_defcount(r->file); - f->oneof_start = upb_inttable_count(&r->oneofs); - f->oneof_index = 0; - f->name = NULL; -} - -bool upb_descreader_endcontainer(upb_descreader *r) { - upb_descreader_frame *f = &r->stack[r->stack_len - 1]; - - while (upb_inttable_count(&r->oneofs) > f->oneof_start) { - upb_oneofdef *o = upb_value_getptr(upb_inttable_pop(&r->oneofs)); - bool ok = upb_msgdef_addoneof(upb_descreader_top(r), o, &r->oneofs, NULL); - UPB_ASSERT(ok); - } - - if (!upb_descreader_qualify(r->file, f->name, f->start)) { - return false; - } - upb_gfree(f->name); - f->name = NULL; - - r->stack_len--; - return true; -} - -void upb_descreader_setscopename(upb_descreader *r, char *str) { - upb_descreader_frame *f = &r->stack[r->stack_len-1]; - upb_gfree(f->name); - f->name = str; -} - -static upb_oneofdef *upb_descreader_getoneof(upb_descreader *r, - uint32_t index) { - bool found; - upb_value val; - upb_descreader_frame *f = &r->stack[r->stack_len-1]; - - /* DescriptorProto messages can be nested, so we will see the nested messages - * between when we see the FieldDescriptorProto and the OneofDescriptorProto. - * We need to preserve the oneofs in between these two things. */ - index += f->oneof_start; - - while (upb_inttable_count(&r->oneofs) <= index) { - upb_inttable_push(&r->oneofs, upb_value_ptr(upb_oneofdef_new(&r->oneofs))); - } - - found = upb_inttable_lookup(&r->oneofs, index, &val); - UPB_ASSERT(found); - return upb_value_getptr(val); -} - -/** Handlers for google.protobuf.FileDescriptorSet. ***************************/ - -static void *fileset_startfile(void *closure, const void *hd) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - r->file = upb_filedef_new(&r->files); - upb_inttable_push(&r->files, upb_value_ptr(r->file)); - return r; -} - -/** Handlers for google.protobuf.FileDescriptorProto. *************************/ - -static bool file_start(void *closure, const void *hd) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - upb_descreader_startcontainer(r); - return true; -} - -static bool file_end(void *closure, const void *hd, upb_status *status) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - UPB_UNUSED(status); - return upb_descreader_endcontainer(r); -} - -static size_t file_onname(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *name; - bool ok; - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - name = upb_gstrndup(buf, n); - /* XXX: see comment at the top of the file. */ - ok = upb_filedef_setname(r->file, name, NULL); - upb_gfree(name); - UPB_ASSERT(ok); - return n; -} - -static size_t file_onpackage(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *package; - bool ok; - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - package = upb_gstrndup(buf, n); - /* XXX: see comment at the top of the file. */ - upb_descreader_setscopename(r, package); - ok = upb_filedef_setpackage(r->file, package, NULL); - UPB_ASSERT(ok); - return n; -} - -static void *file_startphpnamespace(void *closure, const void *hd, - size_t size_hint) { - upb_descreader *r = closure; - bool ok; - UPB_UNUSED(hd); - UPB_UNUSED(size_hint); - - ok = upb_filedef_setphpnamespace(r->file, "", NULL); - UPB_ASSERT(ok); - return closure; -} - -static size_t file_onphpnamespace(void *closure, const void *hd, - const char *buf, size_t n, - const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *php_namespace; - bool ok; - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - php_namespace = upb_gstrndup(buf, n); - ok = upb_filedef_setphpnamespace(r->file, php_namespace, NULL); - upb_gfree(php_namespace); - UPB_ASSERT(ok); - return n; -} - -static size_t file_onphpprefix(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *prefix; - bool ok; - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - prefix = upb_gstrndup(buf, n); - ok = upb_filedef_setphpprefix(r->file, prefix, NULL); - upb_gfree(prefix); - UPB_ASSERT(ok); - return n; -} - -static size_t file_onsyntax(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - bool ok; - UPB_UNUSED(hd); - UPB_UNUSED(handle); - /* XXX: see comment at the top of the file. */ - if (upb_streq("proto2", buf, n)) { - ok = upb_filedef_setsyntax(r->file, UPB_SYNTAX_PROTO2, NULL); - } else if (upb_streq("proto3", buf, n)) { - ok = upb_filedef_setsyntax(r->file, UPB_SYNTAX_PROTO3, NULL); - } else { - ok = false; - } - - UPB_ASSERT(ok); - return n; -} - -static void *file_startmsg(void *closure, const void *hd) { - upb_descreader *r = closure; - upb_msgdef *m = upb_msgdef_new(&m); - bool ok = upb_filedef_addmsg(r->file, m, &m, NULL); - UPB_UNUSED(hd); - UPB_ASSERT(ok); - return r; -} - -static void *file_startenum(void *closure, const void *hd) { - upb_descreader *r = closure; - upb_enumdef *e = upb_enumdef_new(&e); - bool ok = upb_filedef_addenum(r->file, e, &e, NULL); - UPB_UNUSED(hd); - UPB_ASSERT(ok); - return r; -} - -static void *file_startext(void *closure, const void *hd) { - upb_descreader *r = closure; - bool ok; - r->f = upb_fielddef_new(r); - ok = upb_filedef_addext(r->file, r->f, r, NULL); - UPB_UNUSED(hd); - UPB_ASSERT(ok); - return r; -} - -/** Handlers for google.protobuf.EnumValueDescriptorProto. *********************/ - -static bool enumval_startmsg(void *closure, const void *hd) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - r->saw_number = false; - r->saw_name = false; - return true; -} - -static size_t enumval_onname(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - UPB_UNUSED(handle); - /* XXX: see comment at the top of the file. */ - upb_gfree(r->name); - r->name = upb_gstrndup(buf, n); - r->saw_name = true; - return n; -} - -static bool enumval_onnumber(void *closure, const void *hd, int32_t val) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - r->number = val; - r->saw_number = true; - return true; -} - -static bool enumval_endmsg(void *closure, const void *hd, upb_status *status) { - upb_descreader *r = closure; - upb_enumdef *e; - UPB_UNUSED(hd); - - if(!r->saw_number || !r->saw_name) { - upb_status_seterrmsg(status, "Enum value missing name or number."); - return false; - } - e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); - upb_enumdef_addval(e, r->name, r->number, status); - upb_gfree(r->name); - r->name = NULL; - return true; -} - -/** Handlers for google.protobuf.EnumDescriptorProto. *************************/ - -static bool enum_endmsg(void *closure, const void *hd, upb_status *status) { - upb_descreader *r = closure; - upb_enumdef *e; - UPB_UNUSED(hd); - - e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); - if (upb_def_fullname(upb_descreader_last(r)) == NULL) { - upb_status_seterrmsg(status, "Enum had no name."); - return false; - } - if (upb_enumdef_numvals(e) == 0) { - upb_status_seterrmsg(status, "Enum had no values."); - return false; - } - return true; -} - -static size_t enum_onname(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *fullname = upb_gstrndup(buf, n); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - /* XXX: see comment at the top of the file. */ - upb_def_setfullname(upb_descreader_last(r), fullname, NULL); - upb_gfree(fullname); - return n; -} - -/** Handlers for google.protobuf.FieldDescriptorProto *************************/ - -static bool field_startmsg(void *closure, const void *hd) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - UPB_ASSERT(r->f); - upb_gfree(r->default_string); - r->default_string = NULL; - - /* fielddefs default to packed, but descriptors default to non-packed. */ - upb_fielddef_setpacked(r->f, false); - return true; -} - -/* Converts the default value in string "str" into "d". Passes a ref on str. - * Returns true on success. */ -static bool parse_default(char *str, upb_fielddef *f) { - bool success = true; - char *end; - switch (upb_fielddef_type(f)) { - case UPB_TYPE_INT32: { - long val = strtol(str, &end, 0); - if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end) - success = false; - else - upb_fielddef_setdefaultint32(f, val); - break; - } - case UPB_TYPE_INT64: { - /* XXX: Need to write our own strtoll, since it's not available in c89. */ - long long val = strtol(str, &end, 0); - if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end) - success = false; - else - upb_fielddef_setdefaultint64(f, val); - break; - } - case UPB_TYPE_UINT32: { - unsigned long val = strtoul(str, &end, 0); - if (val > UINT32_MAX || errno == ERANGE || *end) - success = false; - else - upb_fielddef_setdefaultuint32(f, val); - break; - } - case UPB_TYPE_UINT64: { - /* XXX: Need to write our own strtoull, since it's not available in c89. */ - unsigned long long val = strtoul(str, &end, 0); - if (val > UINT64_MAX || errno == ERANGE || *end) - success = false; - else - upb_fielddef_setdefaultuint64(f, val); - break; - } - case UPB_TYPE_DOUBLE: { - double val = strtod(str, &end); - if (errno == ERANGE || *end) - success = false; - else - upb_fielddef_setdefaultdouble(f, val); - break; - } - case UPB_TYPE_FLOAT: { - /* XXX: Need to write our own strtof, since it's not available in c89. */ - float val = strtod(str, &end); - if (errno == ERANGE || *end) - success = false; - else - upb_fielddef_setdefaultfloat(f, val); - break; - } - case UPB_TYPE_BOOL: { - if (strcmp(str, "false") == 0) - upb_fielddef_setdefaultbool(f, false); - else if (strcmp(str, "true") == 0) - upb_fielddef_setdefaultbool(f, true); - else - success = false; - break; - } - default: abort(); - } - return success; -} - -static bool field_endmsg(void *closure, const void *hd, upb_status *status) { - upb_descreader *r = closure; - upb_fielddef *f = r->f; - UPB_UNUSED(hd); - - /* TODO: verify that all required fields were present. */ - UPB_ASSERT(upb_fielddef_number(f) != 0); - UPB_ASSERT(upb_fielddef_name(f) != NULL); - UPB_ASSERT((upb_fielddef_subdefname(f) != NULL) == upb_fielddef_hassubdef(f)); - - if (r->default_string) { - if (upb_fielddef_issubmsg(f)) { - upb_status_seterrmsg(status, "Submessages cannot have defaults."); - return false; - } - if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM) { - upb_fielddef_setdefaultcstr(f, r->default_string, NULL); - } else { - if (r->default_string && !parse_default(r->default_string, f)) { - /* We don't worry too much about giving a great error message since the - * compiler should have ensured this was correct. */ - upb_status_seterrmsg(status, "Error converting default value."); - return false; - } - } - } - return true; -} - -static bool field_onlazy(void *closure, const void *hd, bool val) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - - upb_fielddef_setlazy(r->f, val); - return true; -} - -static bool field_onpacked(void *closure, const void *hd, bool val) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - - upb_fielddef_setpacked(r->f, val); - return true; -} - -static bool field_ontype(void *closure, const void *hd, int32_t val) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - - upb_fielddef_setdescriptortype(r->f, val); - return true; -} - -static bool field_onlabel(void *closure, const void *hd, int32_t val) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - - upb_fielddef_setlabel(r->f, val); - return true; -} - -static bool field_onnumber(void *closure, const void *hd, int32_t val) { - upb_descreader *r = closure; - bool ok; - UPB_UNUSED(hd); - - ok = upb_fielddef_setnumber(r->f, val, NULL); - UPB_ASSERT(ok); - return true; -} - -static size_t field_onname(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *name = upb_gstrndup(buf, n); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - /* XXX: see comment at the top of the file. */ - upb_fielddef_setname(r->f, name, NULL); - upb_gfree(name); - return n; -} - -static size_t field_ontypename(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *name = upb_gstrndup(buf, n); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - /* XXX: see comment at the top of the file. */ - upb_fielddef_setsubdefname(r->f, name, NULL); - upb_gfree(name); - return n; -} - -static size_t field_onextendee(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *name = upb_gstrndup(buf, n); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - /* XXX: see comment at the top of the file. */ - upb_fielddef_setcontainingtypename(r->f, name, NULL); - upb_gfree(name); - return n; -} - -static size_t field_ondefaultval(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - /* Have to convert from string to the correct type, but we might not know the - * type yet, so we save it as a string until the end of the field. - * XXX: see comment at the top of the file. */ - upb_gfree(r->default_string); - r->default_string = upb_gstrndup(buf, n); - return n; -} - -static bool field_ononeofindex(void *closure, const void *hd, int32_t index) { - upb_descreader *r = closure; - upb_oneofdef *o = upb_descreader_getoneof(r, index); - bool ok = upb_oneofdef_addfield(o, r->f, &r->f, NULL); - UPB_UNUSED(hd); - - UPB_ASSERT(ok); - return true; -} - -/** Handlers for google.protobuf.OneofDescriptorProto. ************************/ - -static size_t oneof_name(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - upb_descreader_frame *f = &r->stack[r->stack_len-1]; - upb_oneofdef *o = upb_descreader_getoneof(r, f->oneof_index++); - char *name_null_terminated = upb_gstrndup(buf, n); - bool ok = upb_oneofdef_setname(o, name_null_terminated, NULL); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - UPB_ASSERT(ok); - free(name_null_terminated); - return n; -} - -/** Handlers for google.protobuf.DescriptorProto ******************************/ - -static bool msg_start(void *closure, const void *hd) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - - upb_descreader_startcontainer(r); - return true; -} - -static bool msg_end(void *closure, const void *hd, upb_status *status) { - upb_descreader *r = closure; - upb_msgdef *m = upb_descreader_top(r); - UPB_UNUSED(hd); - - if(!upb_def_fullname(upb_msgdef_upcast_mutable(m))) { - upb_status_seterrmsg(status, "Encountered message with no name."); - return false; - } - return upb_descreader_endcontainer(r); -} - -static size_t msg_name(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - upb_msgdef *m = upb_descreader_top(r); - /* XXX: see comment at the top of the file. */ - char *name = upb_gstrndup(buf, n); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - upb_def_setfullname(upb_msgdef_upcast_mutable(m), name, NULL); - upb_descreader_setscopename(r, name); /* Passes ownership of name. */ - return n; -} - -static void *msg_startmsg(void *closure, const void *hd) { - upb_descreader *r = closure; - upb_msgdef *m = upb_msgdef_new(&m); - bool ok = upb_filedef_addmsg(r->file, m, &m, NULL); - UPB_UNUSED(hd); - UPB_ASSERT(ok); - return r; -} - -static void *msg_startext(void *closure, const void *hd) { - upb_descreader *r = closure; - upb_fielddef *f = upb_fielddef_new(&f); - bool ok = upb_filedef_addext(r->file, f, &f, NULL); - UPB_UNUSED(hd); - UPB_ASSERT(ok); - return r; -} - -static void *msg_startfield(void *closure, const void *hd) { - upb_descreader *r = closure; - r->f = upb_fielddef_new(&r->f); - /* We can't add the new field to the message until its name/number are - * filled in. */ - UPB_UNUSED(hd); - return r; -} - -static bool msg_endfield(void *closure, const void *hd) { - upb_descreader *r = closure; - upb_msgdef *m = upb_descreader_top(r); - bool ok; - UPB_UNUSED(hd); - - /* Oneof fields are added to the msgdef through their oneof, so don't need to - * be added here. */ - if (upb_fielddef_containingoneof(r->f) == NULL) { - ok = upb_msgdef_addfield(m, r->f, &r->f, NULL); - UPB_ASSERT(ok); - } - r->f = NULL; - return true; -} - -static bool msg_onmapentry(void *closure, const void *hd, bool mapentry) { - upb_descreader *r = closure; - upb_msgdef *m = upb_descreader_top(r); - UPB_UNUSED(hd); - - upb_msgdef_setmapentry(m, mapentry); - r->f = NULL; - return true; -} - - - -/** Code to register handlers *************************************************/ - -#define F(msg, field) upbdefs_google_protobuf_ ## msg ## _f_ ## field(m) - -static void reghandlers(const void *closure, upb_handlers *h) { - const upb_msgdef *m = upb_handlers_msgdef(h); - UPB_UNUSED(closure); - - if (upbdefs_google_protobuf_FileDescriptorSet_is(m)) { - upb_handlers_setstartsubmsg(h, F(FileDescriptorSet, file), - &fileset_startfile, NULL); - } else if (upbdefs_google_protobuf_DescriptorProto_is(m)) { - upb_handlers_setstartmsg(h, &msg_start, NULL); - upb_handlers_setendmsg(h, &msg_end, NULL); - upb_handlers_setstring(h, F(DescriptorProto, name), &msg_name, NULL); - upb_handlers_setstartsubmsg(h, F(DescriptorProto, extension), &msg_startext, - NULL); - upb_handlers_setstartsubmsg(h, F(DescriptorProto, nested_type), - &msg_startmsg, NULL); - upb_handlers_setstartsubmsg(h, F(DescriptorProto, field), - &msg_startfield, NULL); - upb_handlers_setendsubmsg(h, F(DescriptorProto, field), - &msg_endfield, NULL); - upb_handlers_setstartsubmsg(h, F(DescriptorProto, enum_type), - &file_startenum, NULL); - } else if (upbdefs_google_protobuf_FileDescriptorProto_is(m)) { - upb_handlers_setstartmsg(h, &file_start, NULL); - upb_handlers_setendmsg(h, &file_end, NULL); - upb_handlers_setstring(h, F(FileDescriptorProto, name), &file_onname, - NULL); - upb_handlers_setstring(h, F(FileDescriptorProto, package), &file_onpackage, - NULL); - upb_handlers_setstring(h, F(FileDescriptorProto, syntax), &file_onsyntax, - NULL); - upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, message_type), - &file_startmsg, NULL); - upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, enum_type), - &file_startenum, NULL); - upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, extension), - &file_startext, NULL); - } else if (upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)) { - upb_handlers_setstartmsg(h, &enumval_startmsg, NULL); - upb_handlers_setendmsg(h, &enumval_endmsg, NULL); - upb_handlers_setstring(h, F(EnumValueDescriptorProto, name), &enumval_onname, NULL); - upb_handlers_setint32(h, F(EnumValueDescriptorProto, number), &enumval_onnumber, - NULL); - } else if (upbdefs_google_protobuf_EnumDescriptorProto_is(m)) { - upb_handlers_setendmsg(h, &enum_endmsg, NULL); - upb_handlers_setstring(h, F(EnumDescriptorProto, name), &enum_onname, NULL); - } else if (upbdefs_google_protobuf_FieldDescriptorProto_is(m)) { - upb_handlers_setstartmsg(h, &field_startmsg, NULL); - upb_handlers_setendmsg(h, &field_endmsg, NULL); - upb_handlers_setint32(h, F(FieldDescriptorProto, type), &field_ontype, - NULL); - upb_handlers_setint32(h, F(FieldDescriptorProto, label), &field_onlabel, - NULL); - upb_handlers_setint32(h, F(FieldDescriptorProto, number), &field_onnumber, - NULL); - upb_handlers_setstring(h, F(FieldDescriptorProto, name), &field_onname, - NULL); - upb_handlers_setstring(h, F(FieldDescriptorProto, type_name), - &field_ontypename, NULL); - upb_handlers_setstring(h, F(FieldDescriptorProto, extendee), - &field_onextendee, NULL); - upb_handlers_setstring(h, F(FieldDescriptorProto, default_value), - &field_ondefaultval, NULL); - upb_handlers_setint32(h, F(FieldDescriptorProto, oneof_index), - &field_ononeofindex, NULL); - } else if (upbdefs_google_protobuf_OneofDescriptorProto_is(m)) { - upb_handlers_setstring(h, F(OneofDescriptorProto, name), &oneof_name, NULL); - } else if (upbdefs_google_protobuf_FieldOptions_is(m)) { - upb_handlers_setbool(h, F(FieldOptions, lazy), &field_onlazy, NULL); - upb_handlers_setbool(h, F(FieldOptions, packed), &field_onpacked, NULL); - } else if (upbdefs_google_protobuf_MessageOptions_is(m)) { - upb_handlers_setbool(h, F(MessageOptions, map_entry), &msg_onmapentry, NULL); - } else if (upbdefs_google_protobuf_FileOptions_is(m)) { - upb_handlers_setstring(h, F(FileOptions, php_class_prefix), - &file_onphpprefix, NULL); - upb_handlers_setstartstr(h, F(FileOptions, php_namespace), - &file_startphpnamespace, NULL); - upb_handlers_setstring(h, F(FileOptions, php_namespace), - &file_onphpnamespace, NULL); - } - - UPB_ASSERT(upb_ok(upb_handlers_status(h))); -} - -#undef F - -void descreader_cleanup(void *_r) { - upb_descreader *r = _r; - size_t i; - - for (i = 0; i < upb_descreader_filecount(r); i++) { - upb_filedef_unref(upb_descreader_file(r, i), &r->files); - } - - upb_gfree(r->name); - upb_inttable_uninit(&r->files); - upb_inttable_uninit(&r->oneofs); - upb_gfree(r->default_string); - while (r->stack_len > 0) { - upb_descreader_frame *f = &r->stack[--r->stack_len]; - upb_gfree(f->name); - } -} - - -/* Public API ****************************************************************/ - -upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h) { - upb_descreader *r = upb_env_malloc(e, sizeof(upb_descreader)); - if (!r || !upb_env_addcleanup(e, descreader_cleanup, r)) { - return NULL; - } - - upb_inttable_init(&r->files, UPB_CTYPE_PTR); - upb_inttable_init(&r->oneofs, UPB_CTYPE_PTR); - upb_sink_reset(upb_descreader_input(r), h, r); - r->stack_len = 0; - r->name = NULL; - r->default_string = NULL; - - return r; -} - -size_t upb_descreader_filecount(const upb_descreader *r) { - return upb_inttable_count(&r->files); -} - -upb_filedef *upb_descreader_file(const upb_descreader *r, size_t i) { - upb_value v; - if (upb_inttable_lookup(&r->files, i, &v)) { - return upb_value_getptr(v); - } else { - return NULL; - } -} - -upb_sink *upb_descreader_input(upb_descreader *r) { - return &r->sink; -} - -const upb_handlers *upb_descreader_newhandlers(const void *owner) { - const upb_msgdef *m = upbdefs_google_protobuf_FileDescriptorSet_get(&m); - const upb_handlers *h = upb_handlers_newfrozen(m, owner, reghandlers, NULL); - upb_msgdef_unref(m, &m); - return h; -} -/* -** protobuf decoder bytecode compiler -** -** Code to compile a upb::Handlers into bytecode for decoding a protobuf -** according to that specific schema and destination handlers. -** -** Compiling to bytecode is always the first step. If we are using the -** interpreted decoder we leave it as bytecode and interpret that. If we are -** using a JIT decoder we use a code generator to turn the bytecode into native -** code, LLVM IR, etc. -** -** Bytecode definition is in decoder.int.h. -*/ - -#include - -#ifdef UPB_DUMP_BYTECODE -#include -#endif - -#define MAXLABEL 5 -#define EMPTYLABEL -1 - -/* mgroup *********************************************************************/ - -static void freegroup(upb_refcounted *r) { - mgroup *g = (mgroup*)r; - upb_inttable_uninit(&g->methods); -#ifdef UPB_USE_JIT_X64 - upb_pbdecoder_freejit(g); -#endif - upb_gfree(g->bytecode); - upb_gfree(g); -} - -static void visitgroup(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const mgroup *g = (const mgroup*)r; - upb_inttable_iter i; - upb_inttable_begin(&i, &g->methods); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i)); - visit(r, upb_pbdecodermethod_upcast(method), closure); - } -} - -mgroup *newgroup(const void *owner) { - mgroup *g = upb_gmalloc(sizeof(*g)); - static const struct upb_refcounted_vtbl vtbl = {visitgroup, freegroup}; - upb_refcounted_init(mgroup_upcast_mutable(g), &vtbl, owner); - upb_inttable_init(&g->methods, UPB_CTYPE_PTR); - g->bytecode = NULL; - g->bytecode_end = NULL; - return g; -} - - -/* upb_pbdecodermethod ********************************************************/ - -static void freemethod(upb_refcounted *r) { - upb_pbdecodermethod *method = (upb_pbdecodermethod*)r; - - if (method->dest_handlers_) { - upb_handlers_unref(method->dest_handlers_, method); - } - - upb_inttable_uninit(&method->dispatch); - upb_gfree(method); -} - -static void visitmethod(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_pbdecodermethod *m = (const upb_pbdecodermethod*)r; - visit(r, m->group, closure); -} - -static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers, - mgroup *group) { - static const struct upb_refcounted_vtbl vtbl = {visitmethod, freemethod}; - upb_pbdecodermethod *ret = upb_gmalloc(sizeof(*ret)); - upb_refcounted_init(upb_pbdecodermethod_upcast_mutable(ret), &vtbl, &ret); - upb_byteshandler_init(&ret->input_handler_); - - /* The method references the group and vice-versa, in a circular reference. */ - upb_ref2(ret, group); - upb_ref2(group, ret); - upb_inttable_insertptr(&group->methods, dest_handlers, upb_value_ptr(ret)); - upb_pbdecodermethod_unref(ret, &ret); - - ret->group = mgroup_upcast_mutable(group); - ret->dest_handlers_ = dest_handlers; - ret->is_native_ = false; /* If we JIT, it will update this later. */ - upb_inttable_init(&ret->dispatch, UPB_CTYPE_UINT64); - - if (ret->dest_handlers_) { - upb_handlers_ref(ret->dest_handlers_, ret); - } - return ret; -} - -const upb_handlers *upb_pbdecodermethod_desthandlers( - const upb_pbdecodermethod *m) { - return m->dest_handlers_; -} - -const upb_byteshandler *upb_pbdecodermethod_inputhandler( - const upb_pbdecodermethod *m) { - return &m->input_handler_; -} - -bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m) { - return m->is_native_; -} - -const upb_pbdecodermethod *upb_pbdecodermethod_new( - const upb_pbdecodermethodopts *opts, const void *owner) { - const upb_pbdecodermethod *ret; - upb_pbcodecache cache; - - upb_pbcodecache_init(&cache); - ret = upb_pbcodecache_getdecodermethod(&cache, opts); - upb_pbdecodermethod_ref(ret, owner); - upb_pbcodecache_uninit(&cache); - return ret; -} - - -/* bytecode compiler **********************************************************/ - -/* Data used only at compilation time. */ -typedef struct { - mgroup *group; - - uint32_t *pc; - int fwd_labels[MAXLABEL]; - int back_labels[MAXLABEL]; - - /* For fields marked "lazy", parse them lazily or eagerly? */ - bool lazy; -} compiler; - -static compiler *newcompiler(mgroup *group, bool lazy) { - compiler *ret = upb_gmalloc(sizeof(*ret)); - int i; - - ret->group = group; - ret->lazy = lazy; - for (i = 0; i < MAXLABEL; i++) { - ret->fwd_labels[i] = EMPTYLABEL; - ret->back_labels[i] = EMPTYLABEL; - } - return ret; -} - -static void freecompiler(compiler *c) { - upb_gfree(c); -} - -const size_t ptr_words = sizeof(void*) / sizeof(uint32_t); - -/* How many words an instruction is. */ -static int instruction_len(uint32_t instr) { - switch (getop(instr)) { - case OP_SETDISPATCH: return 1 + ptr_words; - case OP_TAGN: return 3; - case OP_SETBIGGROUPNUM: return 2; - default: return 1; - } -} - -bool op_has_longofs(int32_t instruction) { - switch (getop(instruction)) { - case OP_CALL: - case OP_BRANCH: - case OP_CHECKDELIM: - return true; - /* The "tag" instructions only have 8 bytes available for the jump target, - * but that is ok because these opcodes only require short jumps. */ - case OP_TAG1: - case OP_TAG2: - case OP_TAGN: - return false; - default: - UPB_ASSERT(false); - return false; - } -} - -static int32_t getofs(uint32_t instruction) { - if (op_has_longofs(instruction)) { - return (int32_t)instruction >> 8; - } else { - return (int8_t)(instruction >> 8); - } -} - -static void setofs(uint32_t *instruction, int32_t ofs) { - if (op_has_longofs(*instruction)) { - *instruction = getop(*instruction) | ofs << 8; - } else { - *instruction = (*instruction & ~0xff00) | ((ofs & 0xff) << 8); - } - UPB_ASSERT(getofs(*instruction) == ofs); /* Would fail in cases of overflow. */ -} - -static uint32_t pcofs(compiler *c) { return c->pc - c->group->bytecode; } - -/* Defines a local label at the current PC location. All previous forward - * references are updated to point to this location. The location is noted - * for any future backward references. */ -static void label(compiler *c, unsigned int label) { - int val; - uint32_t *codep; - - UPB_ASSERT(label < MAXLABEL); - val = c->fwd_labels[label]; - codep = (val == EMPTYLABEL) ? NULL : c->group->bytecode + val; - while (codep) { - int ofs = getofs(*codep); - setofs(codep, c->pc - codep - instruction_len(*codep)); - codep = ofs ? codep + ofs : NULL; - } - c->fwd_labels[label] = EMPTYLABEL; - c->back_labels[label] = pcofs(c); -} - -/* Creates a reference to a numbered label; either a forward reference - * (positive arg) or backward reference (negative arg). For forward references - * the value returned now is actually a "next" pointer into a linked list of all - * instructions that use this label and will be patched later when the label is - * defined with label(). - * - * The returned value is the offset that should be written into the instruction. - */ -static int32_t labelref(compiler *c, int label) { - UPB_ASSERT(label < MAXLABEL); - if (label == LABEL_DISPATCH) { - /* No resolving required. */ - return 0; - } else if (label < 0) { - /* Backward local label. Relative to the next instruction. */ - uint32_t from = (c->pc + 1) - c->group->bytecode; - return c->back_labels[-label] - from; - } else { - /* Forward local label: prepend to (possibly-empty) linked list. */ - int *lptr = &c->fwd_labels[label]; - int32_t ret = (*lptr == EMPTYLABEL) ? 0 : *lptr - pcofs(c); - *lptr = pcofs(c); - return ret; - } -} - -static void put32(compiler *c, uint32_t v) { - mgroup *g = c->group; - if (c->pc == g->bytecode_end) { - int ofs = pcofs(c); - size_t oldsize = g->bytecode_end - g->bytecode; - size_t newsize = UPB_MAX(oldsize * 2, 64); - /* TODO(haberman): handle OOM. */ - g->bytecode = upb_grealloc(g->bytecode, oldsize * sizeof(uint32_t), - newsize * sizeof(uint32_t)); - g->bytecode_end = g->bytecode + newsize; - c->pc = g->bytecode + ofs; - } - *c->pc++ = v; -} - -static void putop(compiler *c, opcode op, ...) { - va_list ap; - va_start(ap, op); - - switch (op) { - case OP_SETDISPATCH: { - uintptr_t ptr = (uintptr_t)va_arg(ap, void*); - put32(c, OP_SETDISPATCH); - put32(c, ptr); - if (sizeof(uintptr_t) > sizeof(uint32_t)) - put32(c, (uint64_t)ptr >> 32); - break; - } - case OP_STARTMSG: - case OP_ENDMSG: - case OP_PUSHLENDELIM: - case OP_POP: - case OP_SETDELIM: - case OP_HALT: - case OP_RET: - case OP_DISPATCH: - put32(c, op); - break; - case OP_PARSE_DOUBLE: - case OP_PARSE_FLOAT: - case OP_PARSE_INT64: - case OP_PARSE_UINT64: - case OP_PARSE_INT32: - case OP_PARSE_FIXED64: - case OP_PARSE_FIXED32: - case OP_PARSE_BOOL: - case OP_PARSE_UINT32: - case OP_PARSE_SFIXED32: - case OP_PARSE_SFIXED64: - case OP_PARSE_SINT32: - case OP_PARSE_SINT64: - case OP_STARTSEQ: - case OP_ENDSEQ: - case OP_STARTSUBMSG: - case OP_ENDSUBMSG: - case OP_STARTSTR: - case OP_STRING: - case OP_ENDSTR: - case OP_PUSHTAGDELIM: - put32(c, op | va_arg(ap, upb_selector_t) << 8); - break; - case OP_SETBIGGROUPNUM: - put32(c, op); - put32(c, va_arg(ap, int)); - break; - case OP_CALL: { - const upb_pbdecodermethod *method = va_arg(ap, upb_pbdecodermethod *); - put32(c, op | (method->code_base.ofs - (pcofs(c) + 1)) << 8); - break; - } - case OP_CHECKDELIM: - case OP_BRANCH: { - uint32_t instruction = op; - int label = va_arg(ap, int); - setofs(&instruction, labelref(c, label)); - put32(c, instruction); - break; - } - case OP_TAG1: - case OP_TAG2: { - int label = va_arg(ap, int); - uint64_t tag = va_arg(ap, uint64_t); - uint32_t instruction = op | (tag << 16); - UPB_ASSERT(tag <= 0xffff); - setofs(&instruction, labelref(c, label)); - put32(c, instruction); - break; - } - case OP_TAGN: { - int label = va_arg(ap, int); - uint64_t tag = va_arg(ap, uint64_t); - uint32_t instruction = op | (upb_value_size(tag) << 16); - setofs(&instruction, labelref(c, label)); - put32(c, instruction); - put32(c, tag); - put32(c, tag >> 32); - break; - } - } - - va_end(ap); -} - -#if defined(UPB_USE_JIT_X64) || defined(UPB_DUMP_BYTECODE) - -const char *upb_pbdecoder_getopname(unsigned int op) { -#define QUOTE(x) #x -#define EXPAND_AND_QUOTE(x) QUOTE(x) -#define OPNAME(x) OP_##x -#define OP(x) case OPNAME(x): return EXPAND_AND_QUOTE(OPNAME(x)); -#define T(x) OP(PARSE_##x) - /* Keep in sync with list in decoder.int.h. */ - switch ((opcode)op) { - T(DOUBLE) T(FLOAT) T(INT64) T(UINT64) T(INT32) T(FIXED64) T(FIXED32) - T(BOOL) T(UINT32) T(SFIXED32) T(SFIXED64) T(SINT32) T(SINT64) - OP(STARTMSG) OP(ENDMSG) OP(STARTSEQ) OP(ENDSEQ) OP(STARTSUBMSG) - OP(ENDSUBMSG) OP(STARTSTR) OP(STRING) OP(ENDSTR) OP(CALL) OP(RET) - OP(PUSHLENDELIM) OP(PUSHTAGDELIM) OP(SETDELIM) OP(CHECKDELIM) - OP(BRANCH) OP(TAG1) OP(TAG2) OP(TAGN) OP(SETDISPATCH) OP(POP) - OP(SETBIGGROUPNUM) OP(DISPATCH) OP(HALT) - } - return ""; -#undef OP -#undef T -} - -#endif - -#ifdef UPB_DUMP_BYTECODE - -static void dumpbc(uint32_t *p, uint32_t *end, FILE *f) { - - uint32_t *begin = p; - - while (p < end) { - fprintf(f, "%p %8tx", p, p - begin); - uint32_t instr = *p++; - uint8_t op = getop(instr); - fprintf(f, " %s", upb_pbdecoder_getopname(op)); - switch ((opcode)op) { - case OP_SETDISPATCH: { - const upb_inttable *dispatch; - memcpy(&dispatch, p, sizeof(void*)); - p += ptr_words; - const upb_pbdecodermethod *method = - (void *)((char *)dispatch - - offsetof(upb_pbdecodermethod, dispatch)); - fprintf(f, " %s", upb_msgdef_fullname( - upb_handlers_msgdef(method->dest_handlers_))); - break; - } - case OP_DISPATCH: - case OP_STARTMSG: - case OP_ENDMSG: - case OP_PUSHLENDELIM: - case OP_POP: - case OP_SETDELIM: - case OP_HALT: - case OP_RET: - break; - case OP_PARSE_DOUBLE: - case OP_PARSE_FLOAT: - case OP_PARSE_INT64: - case OP_PARSE_UINT64: - case OP_PARSE_INT32: - case OP_PARSE_FIXED64: - case OP_PARSE_FIXED32: - case OP_PARSE_BOOL: - case OP_PARSE_UINT32: - case OP_PARSE_SFIXED32: - case OP_PARSE_SFIXED64: - case OP_PARSE_SINT32: - case OP_PARSE_SINT64: - case OP_STARTSEQ: - case OP_ENDSEQ: - case OP_STARTSUBMSG: - case OP_ENDSUBMSG: - case OP_STARTSTR: - case OP_STRING: - case OP_ENDSTR: - case OP_PUSHTAGDELIM: - fprintf(f, " %d", instr >> 8); - break; - case OP_SETBIGGROUPNUM: - fprintf(f, " %d", *p++); - break; - case OP_CHECKDELIM: - case OP_CALL: - case OP_BRANCH: - fprintf(f, " =>0x%tx", p + getofs(instr) - begin); - break; - case OP_TAG1: - case OP_TAG2: { - fprintf(f, " tag:0x%x", instr >> 16); - if (getofs(instr)) { - fprintf(f, " =>0x%tx", p + getofs(instr) - begin); - } - break; - } - case OP_TAGN: { - uint64_t tag = *p++; - tag |= (uint64_t)*p++ << 32; - fprintf(f, " tag:0x%llx", (long long)tag); - fprintf(f, " n:%d", instr >> 16); - if (getofs(instr)) { - fprintf(f, " =>0x%tx", p + getofs(instr) - begin); - } - break; - } - } - fputs("\n", f); - } -} - -#endif - -static uint64_t get_encoded_tag(const upb_fielddef *f, int wire_type) { - uint32_t tag = (upb_fielddef_number(f) << 3) | wire_type; - uint64_t encoded_tag = upb_vencode32(tag); - /* No tag should be greater than 5 bytes. */ - UPB_ASSERT(encoded_tag <= 0xffffffffff); - return encoded_tag; -} - -static void putchecktag(compiler *c, const upb_fielddef *f, - int wire_type, int dest) { - uint64_t tag = get_encoded_tag(f, wire_type); - switch (upb_value_size(tag)) { - case 1: - putop(c, OP_TAG1, dest, tag); - break; - case 2: - putop(c, OP_TAG2, dest, tag); - break; - default: - putop(c, OP_TAGN, dest, tag); - break; - } -} - -static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) { - upb_selector_t selector; - bool ok = upb_handlers_getselector(f, type, &selector); - UPB_ASSERT(ok); - return selector; -} - -/* Takes an existing, primary dispatch table entry and repacks it with a - * different alternate wire type. Called when we are inserting a secondary - * dispatch table entry for an alternate wire type. */ -static uint64_t repack(uint64_t dispatch, int new_wt2) { - uint64_t ofs; - uint8_t wt1; - uint8_t old_wt2; - upb_pbdecoder_unpackdispatch(dispatch, &ofs, &wt1, &old_wt2); - UPB_ASSERT(old_wt2 == NO_WIRE_TYPE); /* wt2 should not be set yet. */ - return upb_pbdecoder_packdispatch(ofs, wt1, new_wt2); -} - -/* Marks the current bytecode position as the dispatch target for this message, - * field, and wire type. */ -static void dispatchtarget(compiler *c, upb_pbdecodermethod *method, - const upb_fielddef *f, int wire_type) { - /* Offset is relative to msg base. */ - uint64_t ofs = pcofs(c) - method->code_base.ofs; - uint32_t fn = upb_fielddef_number(f); - upb_inttable *d = &method->dispatch; - upb_value v; - if (upb_inttable_remove(d, fn, &v)) { - /* TODO: prioritize based on packed setting in .proto file. */ - uint64_t repacked = repack(upb_value_getuint64(v), wire_type); - upb_inttable_insert(d, fn, upb_value_uint64(repacked)); - upb_inttable_insert(d, fn + UPB_MAX_FIELDNUMBER, upb_value_uint64(ofs)); - } else { - uint64_t val = upb_pbdecoder_packdispatch(ofs, wire_type, NO_WIRE_TYPE); - upb_inttable_insert(d, fn, upb_value_uint64(val)); - } -} - -static void putpush(compiler *c, const upb_fielddef *f) { - if (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) { - putop(c, OP_PUSHLENDELIM); - } else { - uint32_t fn = upb_fielddef_number(f); - if (fn >= 1 << 24) { - putop(c, OP_PUSHTAGDELIM, 0); - putop(c, OP_SETBIGGROUPNUM, fn); - } else { - putop(c, OP_PUSHTAGDELIM, fn); - } - } -} - -static upb_pbdecodermethod *find_submethod(const compiler *c, - const upb_pbdecodermethod *method, - const upb_fielddef *f) { - const upb_handlers *sub = - upb_handlers_getsubhandlers(method->dest_handlers_, f); - upb_value v; - return upb_inttable_lookupptr(&c->group->methods, sub, &v) - ? upb_value_getptr(v) - : NULL; -} - -static void putsel(compiler *c, opcode op, upb_selector_t sel, - const upb_handlers *h) { - if (upb_handlers_gethandler(h, sel)) { - putop(c, op, sel); - } -} - -/* Puts an opcode to call a callback, but only if a callback actually exists for - * this field and handler type. */ -static void maybeput(compiler *c, opcode op, const upb_handlers *h, - const upb_fielddef *f, upb_handlertype_t type) { - putsel(c, op, getsel(f, type), h); -} - -static bool haslazyhandlers(const upb_handlers *h, const upb_fielddef *f) { - if (!upb_fielddef_lazy(f)) - return false; - - return upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STARTSTR)) || - upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STRING)) || - upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_ENDSTR)); -} - - -/* bytecode compiler code generation ******************************************/ - -/* Symbolic names for our local labels. */ -#define LABEL_LOOPSTART 1 /* Top of a repeated field loop. */ -#define LABEL_LOOPBREAK 2 /* To jump out of a repeated loop */ -#define LABEL_FIELD 3 /* Jump backward to find the most recent field. */ -#define LABEL_ENDMSG 4 /* To reach the OP_ENDMSG instr for this msg. */ - -/* Generates bytecode to parse a single non-lazy message field. */ -static void generate_msgfield(compiler *c, const upb_fielddef *f, - upb_pbdecodermethod *method) { - const upb_handlers *h = upb_pbdecodermethod_desthandlers(method); - const upb_pbdecodermethod *sub_m = find_submethod(c, method, f); - int wire_type; - - if (!sub_m) { - /* Don't emit any code for this field at all; it will be parsed as an - * unknown field. - * - * TODO(haberman): we should change this to parse it as a string field - * instead. It will probably be faster, but more importantly, once we - * start vending unknown fields, a field shouldn't be treated as unknown - * just because it doesn't have subhandlers registered. */ - return; - } - - label(c, LABEL_FIELD); - - wire_type = - (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) - ? UPB_WIRE_TYPE_DELIMITED - : UPB_WIRE_TYPE_START_GROUP; - - if (upb_fielddef_isseq(f)) { - putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - putchecktag(c, f, wire_type, LABEL_DISPATCH); - dispatchtarget(c, method, f, wire_type); - putop(c, OP_PUSHTAGDELIM, 0); - putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); - label(c, LABEL_LOOPSTART); - putpush(c, f); - putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG)); - putop(c, OP_CALL, sub_m); - putop(c, OP_POP); - maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG); - if (wire_type == UPB_WIRE_TYPE_DELIMITED) { - putop(c, OP_SETDELIM); - } - putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK); - putchecktag(c, f, wire_type, LABEL_LOOPBREAK); - putop(c, OP_BRANCH, -LABEL_LOOPSTART); - label(c, LABEL_LOOPBREAK); - putop(c, OP_POP); - maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ); - } else { - putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - putchecktag(c, f, wire_type, LABEL_DISPATCH); - dispatchtarget(c, method, f, wire_type); - putpush(c, f); - putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG)); - putop(c, OP_CALL, sub_m); - putop(c, OP_POP); - maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG); - if (wire_type == UPB_WIRE_TYPE_DELIMITED) { - putop(c, OP_SETDELIM); - } - } -} - -/* Generates bytecode to parse a single string or lazy submessage field. */ -static void generate_delimfield(compiler *c, const upb_fielddef *f, - upb_pbdecodermethod *method) { - const upb_handlers *h = upb_pbdecodermethod_desthandlers(method); - - label(c, LABEL_FIELD); - if (upb_fielddef_isseq(f)) { - putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH); - dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED); - putop(c, OP_PUSHTAGDELIM, 0); - putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); - label(c, LABEL_LOOPSTART); - putop(c, OP_PUSHLENDELIM); - putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR)); - /* Need to emit even if no handler to skip past the string. */ - putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING)); - putop(c, OP_POP); - maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR); - putop(c, OP_SETDELIM); - putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK); - putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_LOOPBREAK); - putop(c, OP_BRANCH, -LABEL_LOOPSTART); - label(c, LABEL_LOOPBREAK); - putop(c, OP_POP); - maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ); - } else { - putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH); - dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED); - putop(c, OP_PUSHLENDELIM); - putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR)); - putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING)); - putop(c, OP_POP); - maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR); - putop(c, OP_SETDELIM); - } -} - -/* Generates bytecode to parse a single primitive field. */ -static void generate_primitivefield(compiler *c, const upb_fielddef *f, - upb_pbdecodermethod *method) { - const upb_handlers *h = upb_pbdecodermethod_desthandlers(method); - upb_descriptortype_t descriptor_type = upb_fielddef_descriptortype(f); - opcode parse_type; - upb_selector_t sel; - int wire_type; - - label(c, LABEL_FIELD); - - /* From a decoding perspective, ENUM is the same as INT32. */ - if (descriptor_type == UPB_DESCRIPTOR_TYPE_ENUM) - descriptor_type = UPB_DESCRIPTOR_TYPE_INT32; - - parse_type = (opcode)descriptor_type; - - /* TODO(haberman): generate packed or non-packed first depending on "packed" - * setting in the fielddef. This will favor (in speed) whichever was - * specified. */ - - UPB_ASSERT((int)parse_type >= 0 && parse_type <= OP_MAX); - sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); - wire_type = upb_pb_native_wire_types[upb_fielddef_descriptortype(f)]; - if (upb_fielddef_isseq(f)) { - putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH); - dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED); - putop(c, OP_PUSHLENDELIM); - putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); /* Packed */ - label(c, LABEL_LOOPSTART); - putop(c, parse_type, sel); - putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK); - putop(c, OP_BRANCH, -LABEL_LOOPSTART); - dispatchtarget(c, method, f, wire_type); - putop(c, OP_PUSHTAGDELIM, 0); - putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); /* Non-packed */ - label(c, LABEL_LOOPSTART); - putop(c, parse_type, sel); - putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK); - putchecktag(c, f, wire_type, LABEL_LOOPBREAK); - putop(c, OP_BRANCH, -LABEL_LOOPSTART); - label(c, LABEL_LOOPBREAK); - putop(c, OP_POP); /* Packed and non-packed join. */ - maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ); - putop(c, OP_SETDELIM); /* Could remove for non-packed by dup ENDSEQ. */ - } else { - putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - putchecktag(c, f, wire_type, LABEL_DISPATCH); - dispatchtarget(c, method, f, wire_type); - putop(c, parse_type, sel); - } -} - -/* Adds bytecode for parsing the given message to the given decoderplan, - * while adding all dispatch targets to this message's dispatch table. */ -static void compile_method(compiler *c, upb_pbdecodermethod *method) { - const upb_handlers *h; - const upb_msgdef *md; - uint32_t* start_pc; - upb_msg_field_iter i; - upb_value val; - - UPB_ASSERT(method); - - /* Clear all entries in the dispatch table. */ - upb_inttable_uninit(&method->dispatch); - upb_inttable_init(&method->dispatch, UPB_CTYPE_UINT64); - - h = upb_pbdecodermethod_desthandlers(method); - md = upb_handlers_msgdef(h); - - method->code_base.ofs = pcofs(c); - putop(c, OP_SETDISPATCH, &method->dispatch); - putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h); - label(c, LABEL_FIELD); - start_pc = c->pc; - for(upb_msg_field_begin(&i, md); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - upb_fieldtype_t type = upb_fielddef_type(f); - - if (type == UPB_TYPE_MESSAGE && !(haslazyhandlers(h, f) && c->lazy)) { - generate_msgfield(c, f, method); - } else if (type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES || - type == UPB_TYPE_MESSAGE) { - generate_delimfield(c, f, method); - } else { - generate_primitivefield(c, f, method); - } - } - - /* If there were no fields, or if no handlers were defined, we need to - * generate a non-empty loop body so that we can at least dispatch for unknown - * fields and check for the end of the message. */ - if (c->pc == start_pc) { - /* Check for end-of-message. */ - putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - /* Unconditionally dispatch. */ - putop(c, OP_DISPATCH, 0); - } - - /* For now we just loop back to the last field of the message (or if none, - * the DISPATCH opcode for the message). */ - putop(c, OP_BRANCH, -LABEL_FIELD); - - /* Insert both a label and a dispatch table entry for this end-of-msg. */ - label(c, LABEL_ENDMSG); - val = upb_value_uint64(pcofs(c) - method->code_base.ofs); - upb_inttable_insert(&method->dispatch, DISPATCH_ENDMSG, val); - - putsel(c, OP_ENDMSG, UPB_ENDMSG_SELECTOR, h); - putop(c, OP_RET); - - upb_inttable_compact(&method->dispatch); -} - -/* Populate "methods" with new upb_pbdecodermethod objects reachable from "h". - * Returns the method for these handlers. - * - * Generates a new method for every destination handlers reachable from "h". */ -static void find_methods(compiler *c, const upb_handlers *h) { - upb_value v; - upb_msg_field_iter i; - const upb_msgdef *md; - - if (upb_inttable_lookupptr(&c->group->methods, h, &v)) - return; - newmethod(h, c->group); - - /* Find submethods. */ - md = upb_handlers_msgdef(h); - for(upb_msg_field_begin(&i, md); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - const upb_handlers *sub_h; - if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE && - (sub_h = upb_handlers_getsubhandlers(h, f)) != NULL) { - /* We only generate a decoder method for submessages with handlers. - * Others will be parsed as unknown fields. */ - find_methods(c, sub_h); - } - } -} - -/* (Re-)compile bytecode for all messages in "msgs." - * Overwrites any existing bytecode in "c". */ -static void compile_methods(compiler *c) { - upb_inttable_iter i; - - /* Start over at the beginning of the bytecode. */ - c->pc = c->group->bytecode; - - upb_inttable_begin(&i, &c->group->methods); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i)); - compile_method(c, method); - } -} - -static void set_bytecode_handlers(mgroup *g) { - upb_inttable_iter i; - upb_inttable_begin(&i, &g->methods); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_pbdecodermethod *m = upb_value_getptr(upb_inttable_iter_value(&i)); - upb_byteshandler *h = &m->input_handler_; - - m->code_base.ptr = g->bytecode + m->code_base.ofs; - - upb_byteshandler_setstartstr(h, upb_pbdecoder_startbc, m->code_base.ptr); - upb_byteshandler_setstring(h, upb_pbdecoder_decode, g); - upb_byteshandler_setendstr(h, upb_pbdecoder_end, m); - } -} - - -/* JIT setup. *****************************************************************/ - -#ifdef UPB_USE_JIT_X64 - -static void sethandlers(mgroup *g, bool allowjit) { - g->jit_code = NULL; - if (allowjit) { - /* Compile byte-code into machine code, create handlers. */ - upb_pbdecoder_jit(g); - } else { - set_bytecode_handlers(g); - } -} - -#else /* UPB_USE_JIT_X64 */ - -static void sethandlers(mgroup *g, bool allowjit) { - /* No JIT compiled in; use bytecode handlers unconditionally. */ - UPB_UNUSED(allowjit); - set_bytecode_handlers(g); -} - -#endif /* UPB_USE_JIT_X64 */ - - -/* TODO(haberman): allow this to be constructed for an arbitrary set of dest - * handlers and other mgroups (but verify we have a transitive closure). */ -const mgroup *mgroup_new(const upb_handlers *dest, bool allowjit, bool lazy, - const void *owner) { - mgroup *g; - compiler *c; - - UPB_UNUSED(allowjit); - UPB_ASSERT(upb_handlers_isfrozen(dest)); - - g = newgroup(owner); - c = newcompiler(g, lazy); - find_methods(c, dest); - - /* We compile in two passes: - * 1. all messages are assigned relative offsets from the beginning of the - * bytecode (saved in method->code_base). - * 2. forwards OP_CALL instructions can be correctly linked since message - * offsets have been previously assigned. - * - * Could avoid the second pass by linking OP_CALL instructions somehow. */ - compile_methods(c); - compile_methods(c); - g->bytecode_end = c->pc; - freecompiler(c); - -#ifdef UPB_DUMP_BYTECODE - { - FILE *f = fopen("/tmp/upb-bytecode", "w"); - UPB_ASSERT(f); - dumpbc(g->bytecode, g->bytecode_end, stderr); - dumpbc(g->bytecode, g->bytecode_end, f); - fclose(f); - - f = fopen("/tmp/upb-bytecode.bin", "wb"); - UPB_ASSERT(f); - fwrite(g->bytecode, 1, g->bytecode_end - g->bytecode, f); - fclose(f); - } -#endif - - sethandlers(g, allowjit); - return g; -} - - -/* upb_pbcodecache ************************************************************/ - -void upb_pbcodecache_init(upb_pbcodecache *c) { - upb_inttable_init(&c->groups, UPB_CTYPE_CONSTPTR); - c->allow_jit_ = true; -} - -void upb_pbcodecache_uninit(upb_pbcodecache *c) { - upb_inttable_iter i; - upb_inttable_begin(&i, &c->groups); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - const mgroup *group = upb_value_getconstptr(upb_inttable_iter_value(&i)); - mgroup_unref(group, c); - } - upb_inttable_uninit(&c->groups); -} - -bool upb_pbcodecache_allowjit(const upb_pbcodecache *c) { - return c->allow_jit_; -} - -bool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow) { - if (upb_inttable_count(&c->groups) > 0) - return false; - c->allow_jit_ = allow; - return true; -} - -const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod( - upb_pbcodecache *c, const upb_pbdecodermethodopts *opts) { - upb_value v; - bool ok; - - /* Right now we build a new DecoderMethod every time. - * TODO(haberman): properly cache methods by their true key. */ - const mgroup *g = mgroup_new(opts->handlers, c->allow_jit_, opts->lazy, c); - upb_inttable_push(&c->groups, upb_value_constptr(g)); - - ok = upb_inttable_lookupptr(&g->methods, opts->handlers, &v); - UPB_ASSERT(ok); - return upb_value_getptr(v); -} - - -/* upb_pbdecodermethodopts ****************************************************/ - -void upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts, - const upb_handlers *h) { - opts->handlers = h; - opts->lazy = false; -} - -void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy) { - opts->lazy = lazy; -} -/* -** upb::Decoder (Bytecode Decoder VM) -** -** Bytecode must previously have been generated using the bytecode compiler in -** compile_decoder.c. This decoder then walks through the bytecode op-by-op to -** parse the input. -** -** Decoding is fully resumable; we just keep a pointer to the current bytecode -** instruction and resume from there. A fair amount of the logic here is to -** handle the fact that values can span buffer seams and we have to be able to -** be capable of suspending/resuming from any byte in the stream. This -** sometimes requires keeping a few trailing bytes from the last buffer around -** in the "residual" buffer. -*/ - -#include -#include - -#ifdef UPB_DUMP_BYTECODE -#include -#endif - -#define CHECK_SUSPEND(x) if (!(x)) return upb_pbdecoder_suspend(d); - -/* Error messages that are shared between the bytecode and JIT decoders. */ -const char *kPbDecoderStackOverflow = "Nesting too deep."; -const char *kPbDecoderSubmessageTooLong = - "Submessage end extends past enclosing submessage."; - -/* Error messages shared within this file. */ -static const char *kUnterminatedVarint = "Unterminated varint."; - -/* upb_pbdecoder **************************************************************/ - -static opcode halt = OP_HALT; - -/* A dummy character we can point to when the user passes us a NULL buffer. - * We need this because in C (NULL + 0) and (NULL - NULL) are undefined - * behavior, which would invalidate functions like curbufleft(). */ -static const char dummy_char; - -/* Whether an op consumes any of the input buffer. */ -static bool consumes_input(opcode op) { - switch (op) { - case OP_SETDISPATCH: - case OP_STARTMSG: - case OP_ENDMSG: - case OP_STARTSEQ: - case OP_ENDSEQ: - case OP_STARTSUBMSG: - case OP_ENDSUBMSG: - case OP_STARTSTR: - case OP_ENDSTR: - case OP_PUSHTAGDELIM: - case OP_POP: - case OP_SETDELIM: - case OP_SETBIGGROUPNUM: - case OP_CHECKDELIM: - case OP_CALL: - case OP_RET: - case OP_BRANCH: - return false; - default: - return true; - } -} - -static size_t stacksize(upb_pbdecoder *d, size_t entries) { - UPB_UNUSED(d); - return entries * sizeof(upb_pbdecoder_frame); -} - -static size_t callstacksize(upb_pbdecoder *d, size_t entries) { - UPB_UNUSED(d); - -#ifdef UPB_USE_JIT_X64 - if (d->method_->is_native_) { - /* Each native stack frame needs two pointers, plus we need a few frames for - * the enter/exit trampolines. */ - size_t ret = entries * sizeof(void*) * 2; - ret += sizeof(void*) * 10; - return ret; - } -#endif - - return entries * sizeof(uint32_t*); -} - - -static bool in_residual_buf(const upb_pbdecoder *d, const char *p); - -/* It's unfortunate that we have to micro-manage the compiler with - * UPB_FORCEINLINE and UPB_NOINLINE, especially since this tuning is necessarily - * specific to one hardware configuration. But empirically on a Core i7, - * performance increases 30-50% with these annotations. Every instance where - * these appear, gcc 4.2.1 made the wrong decision and degraded performance in - * benchmarks. */ - -static void seterr(upb_pbdecoder *d, const char *msg) { - upb_status status = UPB_STATUS_INIT; - upb_status_seterrmsg(&status, msg); - upb_env_reporterror(d->env, &status); -} - -void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) { - seterr(d, msg); -} - - -/* Buffering ******************************************************************/ - -/* We operate on one buffer at a time, which is either the user's buffer passed - * to our "decode" callback or some residual bytes from the previous buffer. */ - -/* How many bytes can be safely read from d->ptr without reading past end-of-buf - * or past the current delimited end. */ -static size_t curbufleft(const upb_pbdecoder *d) { - UPB_ASSERT(d->data_end >= d->ptr); - return d->data_end - d->ptr; -} - -/* How many bytes are available before end-of-buffer. */ -static size_t bufleft(const upb_pbdecoder *d) { - return d->end - d->ptr; -} - -/* Overall stream offset of d->ptr. */ -uint64_t offset(const upb_pbdecoder *d) { - return d->bufstart_ofs + (d->ptr - d->buf); -} - -/* How many bytes are available before the end of this delimited region. */ -size_t delim_remaining(const upb_pbdecoder *d) { - return d->top->end_ofs - offset(d); -} - -/* Advances d->ptr. */ -static void advance(upb_pbdecoder *d, size_t len) { - UPB_ASSERT(curbufleft(d) >= len); - d->ptr += len; -} - -static bool in_buf(const char *p, const char *buf, const char *end) { - return p >= buf && p <= end; -} - -static bool in_residual_buf(const upb_pbdecoder *d, const char *p) { - return in_buf(p, d->residual, d->residual_end); -} - -/* Calculates the delim_end value, which is affected by both the current buffer - * and the parsing stack, so must be called whenever either is updated. */ -static void set_delim_end(upb_pbdecoder *d) { - size_t delim_ofs = d->top->end_ofs - d->bufstart_ofs; - if (delim_ofs <= (size_t)(d->end - d->buf)) { - d->delim_end = d->buf + delim_ofs; - d->data_end = d->delim_end; - } else { - d->data_end = d->end; - d->delim_end = NULL; - } -} - -static void switchtobuf(upb_pbdecoder *d, const char *buf, const char *end) { - d->ptr = buf; - d->buf = buf; - d->end = end; - set_delim_end(d); -} - -static void advancetobuf(upb_pbdecoder *d, const char *buf, size_t len) { - UPB_ASSERT(curbufleft(d) == 0); - d->bufstart_ofs += (d->end - d->buf); - switchtobuf(d, buf, buf + len); -} - -static void checkpoint(upb_pbdecoder *d) { - /* The assertion here is in the interests of efficiency, not correctness. - * We are trying to ensure that we don't checkpoint() more often than - * necessary. */ - UPB_ASSERT(d->checkpoint != d->ptr); - d->checkpoint = d->ptr; -} - -/* Skips "bytes" bytes in the stream, which may be more than available. If we - * skip more bytes than are available, we return a long read count to the caller - * indicating how many bytes can be skipped over before passing actual data - * again. Skipped bytes can pass a NULL buffer and the decoder guarantees they - * won't actually be read. - */ -static int32_t skip(upb_pbdecoder *d, size_t bytes) { - UPB_ASSERT(!in_residual_buf(d, d->ptr) || d->size_param == 0); - UPB_ASSERT(d->skip == 0); - if (bytes > delim_remaining(d)) { - seterr(d, "Skipped value extended beyond enclosing submessage."); - return upb_pbdecoder_suspend(d); - } else if (bufleft(d) >= bytes) { - /* Skipped data is all in current buffer, and more is still available. */ - advance(d, bytes); - d->skip = 0; - return DECODE_OK; - } else { - /* Skipped data extends beyond currently available buffers. */ - d->pc = d->last; - d->skip = bytes - curbufleft(d); - d->bufstart_ofs += (d->end - d->buf); - d->residual_end = d->residual; - switchtobuf(d, d->residual, d->residual_end); - return d->size_param + d->skip; - } -} - - -/* Resumes the decoder from an initial state or from a previous suspend. */ -int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf, - size_t size, const upb_bufhandle *handle) { - UPB_UNUSED(p); /* Useless; just for the benefit of the JIT. */ - - /* d->skip and d->residual_end could probably elegantly be represented - * as a single variable, to more easily represent this invariant. */ - UPB_ASSERT(!(d->skip && d->residual_end > d->residual)); - - /* We need to remember the original size_param, so that the value we return - * is relative to it, even if we do some skipping first. */ - d->size_param = size; - d->handle = handle; - - /* Have to handle this case specially (ie. not with skip()) because the user - * is allowed to pass a NULL buffer here, which won't allow us to safely - * calculate a d->end or use our normal functions like curbufleft(). */ - if (d->skip && d->skip >= size) { - d->skip -= size; - d->bufstart_ofs += size; - buf = &dummy_char; - size = 0; - - /* We can't just return now, because we might need to execute some ops - * like CHECKDELIM, which could call some callbacks and pop the stack. */ - } - - /* We need to pretend that this was the actual buffer param, since some of the - * calculations assume that d->ptr/d->buf is relative to this. */ - d->buf_param = buf; - - if (!buf) { - /* NULL buf is ok if its entire span is covered by the "skip" above, but - * by this point we know that "skip" doesn't cover the buffer. */ - seterr(d, "Passed NULL buffer over non-skippable region."); - return upb_pbdecoder_suspend(d); - } - - if (d->residual_end > d->residual) { - /* We have residual bytes from the last buffer. */ - UPB_ASSERT(d->ptr == d->residual); - } else { - switchtobuf(d, buf, buf + size); - } - - d->checkpoint = d->ptr; - - /* Handle skips that don't cover the whole buffer (as above). */ - if (d->skip) { - size_t skip_bytes = d->skip; - d->skip = 0; - CHECK_RETURN(skip(d, skip_bytes)); - checkpoint(d); - } - - /* If we're inside an unknown group, continue to parse unknown values. */ - if (d->top->groupnum < 0) { - CHECK_RETURN(upb_pbdecoder_skipunknown(d, -1, 0)); - checkpoint(d); - } - - return DECODE_OK; -} - -/* Suspends the decoder at the last checkpoint, without saving any residual - * bytes. If there are any unconsumed bytes, returns a short byte count. */ -size_t upb_pbdecoder_suspend(upb_pbdecoder *d) { - d->pc = d->last; - if (d->checkpoint == d->residual) { - /* Checkpoint was in residual buf; no user bytes were consumed. */ - d->ptr = d->residual; - return 0; - } else { - size_t ret = d->size_param - (d->end - d->checkpoint); - UPB_ASSERT(!in_residual_buf(d, d->checkpoint)); - UPB_ASSERT(d->buf == d->buf_param || d->buf == &dummy_char); - - d->bufstart_ofs += (d->checkpoint - d->buf); - d->residual_end = d->residual; - switchtobuf(d, d->residual, d->residual_end); - return ret; - } -} - -/* Suspends the decoder at the last checkpoint, and saves any unconsumed - * bytes in our residual buffer. This is necessary if we need more user - * bytes to form a complete value, which might not be contiguous in the - * user's buffers. Always consumes all user bytes. */ -static size_t suspend_save(upb_pbdecoder *d) { - /* We hit end-of-buffer before we could parse a full value. - * Save any unconsumed bytes (if any) to the residual buffer. */ - d->pc = d->last; - - if (d->checkpoint == d->residual) { - /* Checkpoint was in residual buf; append user byte(s) to residual buf. */ - UPB_ASSERT((d->residual_end - d->residual) + d->size_param <= - sizeof(d->residual)); - if (!in_residual_buf(d, d->ptr)) { - d->bufstart_ofs -= (d->residual_end - d->residual); - } - memcpy(d->residual_end, d->buf_param, d->size_param); - d->residual_end += d->size_param; - } else { - /* Checkpoint was in user buf; old residual bytes not needed. */ - size_t save; - UPB_ASSERT(!in_residual_buf(d, d->checkpoint)); - - d->ptr = d->checkpoint; - save = curbufleft(d); - UPB_ASSERT(save <= sizeof(d->residual)); - memcpy(d->residual, d->ptr, save); - d->residual_end = d->residual + save; - d->bufstart_ofs = offset(d); - } - - switchtobuf(d, d->residual, d->residual_end); - return d->size_param; -} - -/* Copies the next "bytes" bytes into "buf" and advances the stream. - * Requires that this many bytes are available in the current buffer. */ -UPB_FORCEINLINE static void consumebytes(upb_pbdecoder *d, void *buf, - size_t bytes) { - UPB_ASSERT(bytes <= curbufleft(d)); - memcpy(buf, d->ptr, bytes); - advance(d, bytes); -} - -/* Slow path for getting the next "bytes" bytes, regardless of whether they are - * available in the current buffer or not. Returns a status code as described - * in decoder.int.h. */ -UPB_NOINLINE static int32_t getbytes_slow(upb_pbdecoder *d, void *buf, - size_t bytes) { - const size_t avail = curbufleft(d); - consumebytes(d, buf, avail); - bytes -= avail; - UPB_ASSERT(bytes > 0); - if (in_residual_buf(d, d->ptr)) { - advancetobuf(d, d->buf_param, d->size_param); - } - if (curbufleft(d) >= bytes) { - consumebytes(d, (char *)buf + avail, bytes); - return DECODE_OK; - } else if (d->data_end == d->delim_end) { - seterr(d, "Submessage ended in the middle of a value or group"); - return upb_pbdecoder_suspend(d); - } else { - return suspend_save(d); - } -} - -/* Gets the next "bytes" bytes, regardless of whether they are available in the - * current buffer or not. Returns a status code as described in decoder.int.h. - */ -UPB_FORCEINLINE static int32_t getbytes(upb_pbdecoder *d, void *buf, - size_t bytes) { - if (curbufleft(d) >= bytes) { - /* Buffer has enough data to satisfy. */ - consumebytes(d, buf, bytes); - return DECODE_OK; - } else { - return getbytes_slow(d, buf, bytes); - } -} - -UPB_NOINLINE static size_t peekbytes_slow(upb_pbdecoder *d, void *buf, - size_t bytes) { - size_t ret = curbufleft(d); - memcpy(buf, d->ptr, ret); - if (in_residual_buf(d, d->ptr)) { - size_t copy = UPB_MIN(bytes - ret, d->size_param); - memcpy((char *)buf + ret, d->buf_param, copy); - ret += copy; - } - return ret; -} - -UPB_FORCEINLINE static size_t peekbytes(upb_pbdecoder *d, void *buf, - size_t bytes) { - if (curbufleft(d) >= bytes) { - memcpy(buf, d->ptr, bytes); - return bytes; - } else { - return peekbytes_slow(d, buf, bytes); - } -} - - -/* Decoding of wire types *****************************************************/ - -/* Slow path for decoding a varint from the current buffer position. - * Returns a status code as described in decoder.int.h. */ -UPB_NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, - uint64_t *u64) { - uint8_t byte = 0x80; - int bitpos; - *u64 = 0; - for(bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) { - CHECK_RETURN(getbytes(d, &byte, 1)); - *u64 |= (uint64_t)(byte & 0x7F) << bitpos; - } - if(bitpos == 70 && (byte & 0x80)) { - seterr(d, kUnterminatedVarint); - return upb_pbdecoder_suspend(d); - } - return DECODE_OK; -} - -/* Decodes a varint from the current buffer position. - * Returns a status code as described in decoder.int.h. */ -UPB_FORCEINLINE static int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) { - if (curbufleft(d) > 0 && !(*d->ptr & 0x80)) { - *u64 = *d->ptr; - advance(d, 1); - return DECODE_OK; - } else if (curbufleft(d) >= 10) { - /* Fast case. */ - upb_decoderet r = upb_vdecode_fast(d->ptr); - if (r.p == NULL) { - seterr(d, kUnterminatedVarint); - return upb_pbdecoder_suspend(d); - } - advance(d, r.p - d->ptr); - *u64 = r.val; - return DECODE_OK; - } else { - /* Slow case -- varint spans buffer seam. */ - return upb_pbdecoder_decode_varint_slow(d, u64); - } -} - -/* Decodes a 32-bit varint from the current buffer position. - * Returns a status code as described in decoder.int.h. */ -UPB_FORCEINLINE static int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) { - uint64_t u64; - int32_t ret = decode_varint(d, &u64); - if (ret >= 0) return ret; - if (u64 > UINT32_MAX) { - seterr(d, "Unterminated 32-bit varint"); - /* TODO(haberman) guarantee that this function return is >= 0 somehow, - * so we know this path will always be treated as error by our caller. - * Right now the size_t -> int32_t can overflow and produce negative values. - */ - *u32 = 0; - return upb_pbdecoder_suspend(d); - } - *u32 = u64; - return DECODE_OK; -} - -/* Decodes a fixed32 from the current buffer position. - * Returns a status code as described in decoder.int.h. - * TODO: proper byte swapping for big-endian machines. */ -UPB_FORCEINLINE static int32_t decode_fixed32(upb_pbdecoder *d, uint32_t *u32) { - return getbytes(d, u32, 4); -} - -/* Decodes a fixed64 from the current buffer position. - * Returns a status code as described in decoder.int.h. - * TODO: proper byte swapping for big-endian machines. */ -UPB_FORCEINLINE static int32_t decode_fixed64(upb_pbdecoder *d, uint64_t *u64) { - return getbytes(d, u64, 8); -} - -/* Non-static versions of the above functions. - * These are called by the JIT for fallback paths. */ -int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32) { - return decode_fixed32(d, u32); -} - -int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64) { - return decode_fixed64(d, u64); -} - -static double as_double(uint64_t n) { double d; memcpy(&d, &n, 8); return d; } -static float as_float(uint32_t n) { float f; memcpy(&f, &n, 4); return f; } - -/* Pushes a frame onto the decoder stack. */ -static bool decoder_push(upb_pbdecoder *d, uint64_t end) { - upb_pbdecoder_frame *fr = d->top; - - if (end > fr->end_ofs) { - seterr(d, kPbDecoderSubmessageTooLong); - return false; - } else if (fr == d->limit) { - seterr(d, kPbDecoderStackOverflow); - return false; - } - - fr++; - fr->end_ofs = end; - fr->dispatch = NULL; - fr->groupnum = 0; - d->top = fr; - return true; -} - -static bool pushtagdelim(upb_pbdecoder *d, uint32_t arg) { - /* While we expect to see an "end" tag (either ENDGROUP or a non-sequence - * field number) prior to hitting any enclosing submessage end, pushing our - * existing delim end prevents us from continuing to parse values from a - * corrupt proto that doesn't give us an END tag in time. */ - if (!decoder_push(d, d->top->end_ofs)) - return false; - d->top->groupnum = arg; - return true; -} - -/* Pops a frame from the decoder stack. */ -static void decoder_pop(upb_pbdecoder *d) { d->top--; } - -UPB_NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d, - uint64_t expected) { - uint64_t data = 0; - size_t bytes = upb_value_size(expected); - size_t read = peekbytes(d, &data, bytes); - if (read == bytes && data == expected) { - /* Advance past matched bytes. */ - int32_t ok = getbytes(d, &data, read); - UPB_ASSERT(ok < 0); - return DECODE_OK; - } else if (read < bytes && memcmp(&data, &expected, read) == 0) { - return suspend_save(d); - } else { - return DECODE_MISMATCH; - } -} - -int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum, - uint8_t wire_type) { - if (fieldnum >= 0) - goto have_tag; - - while (true) { - uint32_t tag; - CHECK_RETURN(decode_v32(d, &tag)); - wire_type = tag & 0x7; - fieldnum = tag >> 3; - -have_tag: - if (fieldnum == 0) { - seterr(d, "Saw invalid field number (0)"); - return upb_pbdecoder_suspend(d); - } - - /* TODO: deliver to unknown field callback. */ - switch (wire_type) { - case UPB_WIRE_TYPE_32BIT: - CHECK_RETURN(skip(d, 4)); - break; - case UPB_WIRE_TYPE_64BIT: - CHECK_RETURN(skip(d, 8)); - break; - case UPB_WIRE_TYPE_VARINT: { - uint64_t u64; - CHECK_RETURN(decode_varint(d, &u64)); - break; - } - case UPB_WIRE_TYPE_DELIMITED: { - uint32_t len; - CHECK_RETURN(decode_v32(d, &len)); - CHECK_RETURN(skip(d, len)); - break; - } - case UPB_WIRE_TYPE_START_GROUP: - CHECK_SUSPEND(pushtagdelim(d, -fieldnum)); - break; - case UPB_WIRE_TYPE_END_GROUP: - if (fieldnum == -d->top->groupnum) { - decoder_pop(d); - } else if (fieldnum == d->top->groupnum) { - return DECODE_ENDGROUP; - } else { - seterr(d, "Unmatched ENDGROUP tag."); - return upb_pbdecoder_suspend(d); - } - break; - default: - seterr(d, "Invalid wire type"); - return upb_pbdecoder_suspend(d); - } - - if (d->top->groupnum >= 0) { - return DECODE_OK; - } - - /* Unknown group -- continue looping over unknown fields. */ - checkpoint(d); - } -} - -static void goto_endmsg(upb_pbdecoder *d) { - upb_value v; - bool found = upb_inttable_lookup32(d->top->dispatch, DISPATCH_ENDMSG, &v); - UPB_ASSERT(found); - d->pc = d->top->base + upb_value_getuint64(v); -} - -/* Parses a tag and jumps to the corresponding bytecode instruction for this - * field. - * - * If the tag is unknown (or the wire type doesn't match), parses the field as - * unknown. If the tag is a valid ENDGROUP tag, jumps to the bytecode - * instruction for the end of message. */ -static int32_t dispatch(upb_pbdecoder *d) { - upb_inttable *dispatch = d->top->dispatch; - uint32_t tag; - uint8_t wire_type; - uint32_t fieldnum; - upb_value val; - int32_t retval; - - /* Decode tag. */ - CHECK_RETURN(decode_v32(d, &tag)); - wire_type = tag & 0x7; - fieldnum = tag >> 3; - - /* Lookup tag. Because of packed/non-packed compatibility, we have to - * check the wire type against two possibilities. */ - if (fieldnum != DISPATCH_ENDMSG && - upb_inttable_lookup32(dispatch, fieldnum, &val)) { - uint64_t v = upb_value_getuint64(val); - if (wire_type == (v & 0xff)) { - d->pc = d->top->base + (v >> 16); - return DECODE_OK; - } else if (wire_type == ((v >> 8) & 0xff)) { - bool found = - upb_inttable_lookup(dispatch, fieldnum + UPB_MAX_FIELDNUMBER, &val); - UPB_ASSERT(found); - d->pc = d->top->base + upb_value_getuint64(val); - return DECODE_OK; - } - } - - /* We have some unknown fields (or ENDGROUP) to parse. The DISPATCH or TAG - * bytecode that triggered this is preceded by a CHECKDELIM bytecode which - * we need to back up to, so that when we're done skipping unknown data we - * can re-check the delimited end. */ - d->last--; /* Necessary if we get suspended */ - d->pc = d->last; - UPB_ASSERT(getop(*d->last) == OP_CHECKDELIM); - - /* Unknown field or ENDGROUP. */ - retval = upb_pbdecoder_skipunknown(d, fieldnum, wire_type); - - CHECK_RETURN(retval); - - if (retval == DECODE_ENDGROUP) { - goto_endmsg(d); - return DECODE_OK; - } - - return DECODE_OK; -} - -/* Callers know that the stack is more than one deep because the opcodes that - * call this only occur after PUSH operations. */ -upb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) { - UPB_ASSERT(d->top != d->stack); - return d->top - 1; -} - - -/* The main decoding loop *****************************************************/ - -/* The main decoder VM function. Uses traditional bytecode dispatch loop with a - * switch() statement. */ -size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group, - const upb_bufhandle* handle) { - -#define VMCASE(op, code) \ - case op: { code; if (consumes_input(op)) checkpoint(d); break; } -#define PRIMITIVE_OP(type, wt, name, convfunc, ctype) \ - VMCASE(OP_PARSE_ ## type, { \ - ctype val; \ - CHECK_RETURN(decode_ ## wt(d, &val)); \ - upb_sink_put ## name(&d->top->sink, arg, (convfunc)(val)); \ - }) - - while(1) { - int32_t instruction; - opcode op; - uint32_t arg; - int32_t longofs; - - d->last = d->pc; - instruction = *d->pc++; - op = getop(instruction); - arg = instruction >> 8; - longofs = arg; - UPB_ASSERT(d->ptr != d->residual_end); - UPB_UNUSED(group); -#ifdef UPB_DUMP_BYTECODE - fprintf(stderr, "s_ofs=%d buf_ofs=%d data_rem=%d buf_rem=%d delim_rem=%d " - "%x %s (%d)\n", - (int)offset(d), - (int)(d->ptr - d->buf), - (int)(d->data_end - d->ptr), - (int)(d->end - d->ptr), - (int)((d->top->end_ofs - d->bufstart_ofs) - (d->ptr - d->buf)), - (int)(d->pc - 1 - group->bytecode), - upb_pbdecoder_getopname(op), - arg); -#endif - switch (op) { - /* Technically, we are losing data if we see a 32-bit varint that is not - * properly sign-extended. We could detect this and error about the data - * loss, but proto2 does not do this, so we pass. */ - PRIMITIVE_OP(INT32, varint, int32, int32_t, uint64_t) - PRIMITIVE_OP(INT64, varint, int64, int64_t, uint64_t) - PRIMITIVE_OP(UINT32, varint, uint32, uint32_t, uint64_t) - PRIMITIVE_OP(UINT64, varint, uint64, uint64_t, uint64_t) - PRIMITIVE_OP(FIXED32, fixed32, uint32, uint32_t, uint32_t) - PRIMITIVE_OP(FIXED64, fixed64, uint64, uint64_t, uint64_t) - PRIMITIVE_OP(SFIXED32, fixed32, int32, int32_t, uint32_t) - PRIMITIVE_OP(SFIXED64, fixed64, int64, int64_t, uint64_t) - PRIMITIVE_OP(BOOL, varint, bool, bool, uint64_t) - PRIMITIVE_OP(DOUBLE, fixed64, double, as_double, uint64_t) - PRIMITIVE_OP(FLOAT, fixed32, float, as_float, uint32_t) - PRIMITIVE_OP(SINT32, varint, int32, upb_zzdec_32, uint64_t) - PRIMITIVE_OP(SINT64, varint, int64, upb_zzdec_64, uint64_t) - - VMCASE(OP_SETDISPATCH, - d->top->base = d->pc - 1; - memcpy(&d->top->dispatch, d->pc, sizeof(void*)); - d->pc += sizeof(void*) / sizeof(uint32_t); - ) - VMCASE(OP_STARTMSG, - CHECK_SUSPEND(upb_sink_startmsg(&d->top->sink)); - ) - VMCASE(OP_ENDMSG, - CHECK_SUSPEND(upb_sink_endmsg(&d->top->sink, d->status)); - ) - VMCASE(OP_STARTSEQ, - upb_pbdecoder_frame *outer = outer_frame(d); - CHECK_SUSPEND(upb_sink_startseq(&outer->sink, arg, &d->top->sink)); - ) - VMCASE(OP_ENDSEQ, - CHECK_SUSPEND(upb_sink_endseq(&d->top->sink, arg)); - ) - VMCASE(OP_STARTSUBMSG, - upb_pbdecoder_frame *outer = outer_frame(d); - CHECK_SUSPEND(upb_sink_startsubmsg(&outer->sink, arg, &d->top->sink)); - ) - VMCASE(OP_ENDSUBMSG, - CHECK_SUSPEND(upb_sink_endsubmsg(&d->top->sink, arg)); - ) - VMCASE(OP_STARTSTR, - uint32_t len = delim_remaining(d); - upb_pbdecoder_frame *outer = outer_frame(d); - CHECK_SUSPEND(upb_sink_startstr(&outer->sink, arg, len, &d->top->sink)); - if (len == 0) { - d->pc++; /* Skip OP_STRING. */ - } - ) - VMCASE(OP_STRING, - uint32_t len = curbufleft(d); - size_t n = upb_sink_putstring(&d->top->sink, arg, d->ptr, len, handle); - if (n > len) { - if (n > delim_remaining(d)) { - seterr(d, "Tried to skip past end of string."); - return upb_pbdecoder_suspend(d); - } else { - int32_t ret = skip(d, n); - /* This shouldn't return DECODE_OK, because n > len. */ - UPB_ASSERT(ret >= 0); - return ret; - } - } - advance(d, n); - if (n < len || d->delim_end == NULL) { - /* We aren't finished with this string yet. */ - d->pc--; /* Repeat OP_STRING. */ - if (n > 0) checkpoint(d); - return upb_pbdecoder_suspend(d); - } - ) - VMCASE(OP_ENDSTR, - CHECK_SUSPEND(upb_sink_endstr(&d->top->sink, arg)); - ) - VMCASE(OP_PUSHTAGDELIM, - CHECK_SUSPEND(pushtagdelim(d, arg)); - ) - VMCASE(OP_SETBIGGROUPNUM, - d->top->groupnum = *d->pc++; - ) - VMCASE(OP_POP, - UPB_ASSERT(d->top > d->stack); - decoder_pop(d); - ) - VMCASE(OP_PUSHLENDELIM, - uint32_t len; - CHECK_RETURN(decode_v32(d, &len)); - CHECK_SUSPEND(decoder_push(d, offset(d) + len)); - set_delim_end(d); - ) - VMCASE(OP_SETDELIM, - set_delim_end(d); - ) - VMCASE(OP_CHECKDELIM, - /* We are guaranteed of this assert because we never allow ourselves to - * consume bytes beyond data_end, which covers delim_end when non-NULL. - */ - UPB_ASSERT(!(d->delim_end && d->ptr > d->delim_end)); - if (d->ptr == d->delim_end) - d->pc += longofs; - ) - VMCASE(OP_CALL, - d->callstack[d->call_len++] = d->pc; - d->pc += longofs; - ) - VMCASE(OP_RET, - UPB_ASSERT(d->call_len > 0); - d->pc = d->callstack[--d->call_len]; - ) - VMCASE(OP_BRANCH, - d->pc += longofs; - ) - VMCASE(OP_TAG1, - uint8_t expected; - CHECK_SUSPEND(curbufleft(d) > 0); - expected = (arg >> 8) & 0xff; - if (*d->ptr == expected) { - advance(d, 1); - } else { - int8_t shortofs; - badtag: - shortofs = arg; - if (shortofs == LABEL_DISPATCH) { - CHECK_RETURN(dispatch(d)); - } else { - d->pc += shortofs; - break; /* Avoid checkpoint(). */ - } - } - ) - VMCASE(OP_TAG2, - uint16_t expected; - CHECK_SUSPEND(curbufleft(d) > 0); - expected = (arg >> 8) & 0xffff; - if (curbufleft(d) >= 2) { - uint16_t actual; - memcpy(&actual, d->ptr, 2); - if (expected == actual) { - advance(d, 2); - } else { - goto badtag; - } - } else { - int32_t result = upb_pbdecoder_checktag_slow(d, expected); - if (result == DECODE_MISMATCH) goto badtag; - if (result >= 0) return result; - } - ) - VMCASE(OP_TAGN, { - uint64_t expected; - int32_t result; - memcpy(&expected, d->pc, 8); - d->pc += 2; - result = upb_pbdecoder_checktag_slow(d, expected); - if (result == DECODE_MISMATCH) goto badtag; - if (result >= 0) return result; - }) - VMCASE(OP_DISPATCH, { - CHECK_RETURN(dispatch(d)); - }) - VMCASE(OP_HALT, { - return d->size_param; - }) - } - } -} - - -/* BytesHandler handlers ******************************************************/ - -void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint) { - upb_pbdecoder *d = closure; - UPB_UNUSED(size_hint); - d->top->end_ofs = UINT64_MAX; - d->bufstart_ofs = 0; - d->call_len = 1; - d->callstack[0] = &halt; - d->pc = pc; - d->skip = 0; - return d; -} - -void *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint) { - upb_pbdecoder *d = closure; - UPB_UNUSED(hd); - UPB_UNUSED(size_hint); - d->top->end_ofs = UINT64_MAX; - d->bufstart_ofs = 0; - d->call_len = 0; - d->skip = 0; - return d; -} - -bool upb_pbdecoder_end(void *closure, const void *handler_data) { - upb_pbdecoder *d = closure; - const upb_pbdecodermethod *method = handler_data; - uint64_t end; - char dummy; - - if (d->residual_end > d->residual) { - seterr(d, "Unexpected EOF: decoder still has buffered unparsed data"); - return false; - } - - if (d->skip) { - seterr(d, "Unexpected EOF inside skipped data"); - return false; - } - - if (d->top->end_ofs != UINT64_MAX) { - seterr(d, "Unexpected EOF inside delimited string"); - return false; - } - - /* The user's end() call indicates that the message ends here. */ - end = offset(d); - d->top->end_ofs = end; - -#ifdef UPB_USE_JIT_X64 - if (method->is_native_) { - const mgroup *group = (const mgroup*)method->group; - if (d->top != d->stack) - d->stack->end_ofs = 0; - group->jit_code(closure, method->code_base.ptr, &dummy, 0, NULL); - } else -#endif - { - const uint32_t *p = d->pc; - d->stack->end_ofs = end; - /* Check the previous bytecode, but guard against beginning. */ - if (p != method->code_base.ptr) p--; - if (getop(*p) == OP_CHECKDELIM) { - /* Rewind from OP_TAG* to OP_CHECKDELIM. */ - UPB_ASSERT(getop(*d->pc) == OP_TAG1 || - getop(*d->pc) == OP_TAG2 || - getop(*d->pc) == OP_TAGN || - getop(*d->pc) == OP_DISPATCH); - d->pc = p; - } - upb_pbdecoder_decode(closure, handler_data, &dummy, 0, NULL); - } - - if (d->call_len != 0) { - seterr(d, "Unexpected EOF inside submessage or group"); - return false; - } - - return true; -} - -size_t upb_pbdecoder_decode(void *decoder, const void *group, const char *buf, - size_t size, const upb_bufhandle *handle) { - int32_t result = upb_pbdecoder_resume(decoder, NULL, buf, size, handle); - - if (result == DECODE_ENDGROUP) goto_endmsg(decoder); - CHECK_RETURN(result); - - return run_decoder_vm(decoder, group, handle); -} - - -/* Public API *****************************************************************/ - -void upb_pbdecoder_reset(upb_pbdecoder *d) { - d->top = d->stack; - d->top->groupnum = 0; - d->ptr = d->residual; - d->buf = d->residual; - d->end = d->residual; - d->residual_end = d->residual; -} - -upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m, - upb_sink *sink) { - const size_t default_max_nesting = 64; -#ifndef NDEBUG - size_t size_before = upb_env_bytesallocated(e); -#endif - - upb_pbdecoder *d = upb_env_malloc(e, sizeof(upb_pbdecoder)); - if (!d) return NULL; - - d->method_ = m; - d->callstack = upb_env_malloc(e, callstacksize(d, default_max_nesting)); - d->stack = upb_env_malloc(e, stacksize(d, default_max_nesting)); - if (!d->stack || !d->callstack) { - return NULL; - } - - d->env = e; - d->limit = d->stack + default_max_nesting - 1; - d->stack_size = default_max_nesting; - d->status = NULL; - - upb_pbdecoder_reset(d); - upb_bytessink_reset(&d->input_, &m->input_handler_, d); - - UPB_ASSERT(sink); - if (d->method_->dest_handlers_) { - if (sink->handlers != d->method_->dest_handlers_) - return NULL; - } - upb_sink_reset(&d->top->sink, sink->handlers, sink->closure); - - /* If this fails, increase the value in decoder.h. */ - UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(e) - size_before <= - UPB_PB_DECODER_SIZE); - return d; -} - -uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d) { - return offset(d); -} - -const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d) { - return d->method_; -} - -upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d) { - return &d->input_; -} - -size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d) { - return d->stack_size; -} - -bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) { - UPB_ASSERT(d->top >= d->stack); - - if (max < (size_t)(d->top - d->stack)) { - /* Can't set a limit smaller than what we are currently at. */ - return false; - } - - if (max > d->stack_size) { - /* Need to reallocate stack and callstack to accommodate. */ - size_t old_size = stacksize(d, d->stack_size); - size_t new_size = stacksize(d, max); - void *p = upb_env_realloc(d->env, d->stack, old_size, new_size); - if (!p) { - return false; - } - d->stack = p; - - old_size = callstacksize(d, d->stack_size); - new_size = callstacksize(d, max); - p = upb_env_realloc(d->env, d->callstack, old_size, new_size); - if (!p) { - return false; - } - d->callstack = p; - - d->stack_size = max; - } - - d->limit = d->stack + max - 1; - return true; -} -/* -** upb::Encoder -** -** Since we are implementing pure handlers (ie. without any out-of-band access -** to pre-computed lengths), we have to buffer all submessages before we can -** emit even their first byte. -** -** Not knowing the size of submessages also means we can't write a perfect -** zero-copy implementation, even with buffering. Lengths are stored as -** varints, which means that we don't know how many bytes to reserve for the -** length until we know what the length is. -** -** This leaves us with three main choices: -** -** 1. buffer all submessage data in a temporary buffer, then copy it exactly -** once into the output buffer. -** -** 2. attempt to buffer data directly into the output buffer, estimating how -** many bytes each length will take. When our guesses are wrong, use -** memmove() to grow or shrink the allotted space. -** -** 3. buffer directly into the output buffer, allocating a max length -** ahead-of-time for each submessage length. If we overallocated, we waste -** space, but no memcpy() or memmove() is required. This approach requires -** defining a maximum size for submessages and rejecting submessages that -** exceed that size. -** -** (2) and (3) have the potential to have better performance, but they are more -** complicated and subtle to implement: -** -** (3) requires making an arbitrary choice of the maximum message size; it -** wastes space when submessages are shorter than this and fails -** completely when they are longer. This makes it more finicky and -** requires configuration based on the input. It also makes it impossible -** to perfectly match the output of reference encoders that always use the -** optimal amount of space for each length. -** -** (2) requires guessing the the size upfront, and if multiple lengths are -** guessed wrong the minimum required number of memmove() operations may -** be complicated to compute correctly. Implemented properly, it may have -** a useful amortized or average cost, but more investigation is required -** to determine this and what the optimal algorithm is to achieve it. -** -** (1) makes you always pay for exactly one copy, but its implementation is -** the simplest and its performance is predictable. -** -** So for now, we implement (1) only. If we wish to optimize later, we should -** be able to do it without affecting users. -** -** The strategy is to buffer the segments of data that do *not* depend on -** unknown lengths in one buffer, and keep a separate buffer of segment pointers -** and lengths. When the top-level submessage ends, we can go beginning to end, -** alternating the writing of lengths with memcpy() of the rest of the data. -** At the top level though, no buffering is required. -*/ - - - -/* The output buffer is divided into segments; a segment is a string of data - * that is "ready to go" -- it does not need any varint lengths inserted into - * the middle. The seams between segments are where varints will be inserted - * once they are known. - * - * We also use the concept of a "run", which is a range of encoded bytes that - * occur at a single submessage level. Every segment contains one or more runs. - * - * A segment can span messages. Consider: - * - * .--Submessage lengths---------. - * | | | - * | V V - * V | |--------------- | |----------------- - * Submessages: | |----------------------------------------------- - * Top-level msg: ------------------------------------------------------------ - * - * Segments: ----- ------------------- ----------------- - * Runs: *---- *--------------*--- *---------------- - * (* marks the start) - * - * Note that the top-level menssage is not in any segment because it does not - * have any length preceding it. - * - * A segment is only interrupted when another length needs to be inserted. So - * observe how the second segment spans both the inner submessage and part of - * the next enclosing message. */ -typedef struct { - uint32_t msglen; /* The length to varint-encode before this segment. */ - uint32_t seglen; /* Length of the segment. */ -} upb_pb_encoder_segment; - -struct upb_pb_encoder { - upb_env *env; - - /* Our input and output. */ - upb_sink input_; - upb_bytessink *output_; - - /* The "subclosure" -- used as the inner closure as part of the bytessink - * protocol. */ - void *subc; - - /* The output buffer and limit, and our current write position. "buf" - * initially points to "initbuf", but is dynamically allocated if we need to - * grow beyond the initial size. */ - char *buf, *ptr, *limit; - - /* The beginning of the current run, or undefined if we are at the top - * level. */ - char *runbegin; - - /* The list of segments we are accumulating. */ - upb_pb_encoder_segment *segbuf, *segptr, *seglimit; - - /* The stack of enclosing submessages. Each entry in the stack points to the - * segment where this submessage's length is being accumulated. */ - int *stack, *top, *stacklimit; - - /* Depth of startmsg/endmsg calls. */ - int depth; -}; - -/* low-level buffering ********************************************************/ - -/* Low-level functions for interacting with the output buffer. */ - -/* TODO(haberman): handle pushback */ -static void putbuf(upb_pb_encoder *e, const char *buf, size_t len) { - size_t n = upb_bytessink_putbuf(e->output_, e->subc, buf, len, NULL); - UPB_ASSERT(n == len); -} - -static upb_pb_encoder_segment *top(upb_pb_encoder *e) { - return &e->segbuf[*e->top]; -} - -/* Call to ensure that at least "bytes" bytes are available for writing at - * e->ptr. Returns false if the bytes could not be allocated. */ -static bool reserve(upb_pb_encoder *e, size_t bytes) { - if ((size_t)(e->limit - e->ptr) < bytes) { - /* Grow buffer. */ - char *new_buf; - size_t needed = bytes + (e->ptr - e->buf); - size_t old_size = e->limit - e->buf; - - size_t new_size = old_size; - - while (new_size < needed) { - new_size *= 2; - } - - new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size); - - if (new_buf == NULL) { - return false; - } - - e->ptr = new_buf + (e->ptr - e->buf); - e->runbegin = new_buf + (e->runbegin - e->buf); - e->limit = new_buf + new_size; - e->buf = new_buf; - } - - return true; -} - -/* Call when "bytes" bytes have been writte at e->ptr. The caller *must* have - * previously called reserve() with at least this many bytes. */ -static void encoder_advance(upb_pb_encoder *e, size_t bytes) { - UPB_ASSERT((size_t)(e->limit - e->ptr) >= bytes); - e->ptr += bytes; -} - -/* Call when all of the bytes for a handler have been written. Flushes the - * bytes if possible and necessary, returning false if this failed. */ -static bool commit(upb_pb_encoder *e) { - if (!e->top) { - /* We aren't inside a delimited region. Flush our accumulated bytes to - * the output. - * - * TODO(haberman): in the future we may want to delay flushing for - * efficiency reasons. */ - putbuf(e, e->buf, e->ptr - e->buf); - e->ptr = e->buf; - } - - return true; -} - -/* Writes the given bytes to the buffer, handling reserve/advance. */ -static bool encode_bytes(upb_pb_encoder *e, const void *data, size_t len) { - if (!reserve(e, len)) { - return false; - } - - memcpy(e->ptr, data, len); - encoder_advance(e, len); - return true; -} - -/* Finish the current run by adding the run totals to the segment and message - * length. */ -static void accumulate(upb_pb_encoder *e) { - size_t run_len; - UPB_ASSERT(e->ptr >= e->runbegin); - run_len = e->ptr - e->runbegin; - e->segptr->seglen += run_len; - top(e)->msglen += run_len; - e->runbegin = e->ptr; -} - -/* Call to indicate the start of delimited region for which the full length is - * not yet known. All data will be buffered until the length is known. - * Delimited regions may be nested; their lengths will all be tracked properly. */ -static bool start_delim(upb_pb_encoder *e) { - if (e->top) { - /* We are already buffering, advance to the next segment and push it on the - * stack. */ - accumulate(e); - - if (++e->top == e->stacklimit) { - /* TODO(haberman): grow stack? */ - return false; - } - - if (++e->segptr == e->seglimit) { - /* Grow segment buffer. */ - size_t old_size = - (e->seglimit - e->segbuf) * sizeof(upb_pb_encoder_segment); - size_t new_size = old_size * 2; - upb_pb_encoder_segment *new_buf = - upb_env_realloc(e->env, e->segbuf, old_size, new_size); - - if (new_buf == NULL) { - return false; - } - - e->segptr = new_buf + (e->segptr - e->segbuf); - e->seglimit = new_buf + (new_size / sizeof(upb_pb_encoder_segment)); - e->segbuf = new_buf; - } - } else { - /* We were previously at the top level, start buffering. */ - e->segptr = e->segbuf; - e->top = e->stack; - e->runbegin = e->ptr; - } - - *e->top = e->segptr - e->segbuf; - e->segptr->seglen = 0; - e->segptr->msglen = 0; - - return true; -} - -/* Call to indicate the end of a delimited region. We now know the length of - * the delimited region. If we are not nested inside any other delimited - * regions, we can now emit all of the buffered data we accumulated. */ -static bool end_delim(upb_pb_encoder *e) { - size_t msglen; - accumulate(e); - msglen = top(e)->msglen; - - if (e->top == e->stack) { - /* All lengths are now available, emit all buffered data. */ - char buf[UPB_PB_VARINT_MAX_LEN]; - upb_pb_encoder_segment *s; - const char *ptr = e->buf; - for (s = e->segbuf; s <= e->segptr; s++) { - size_t lenbytes = upb_vencode64(s->msglen, buf); - putbuf(e, buf, lenbytes); - putbuf(e, ptr, s->seglen); - ptr += s->seglen; - } - - e->ptr = e->buf; - e->top = NULL; - } else { - /* Need to keep buffering; propagate length info into enclosing - * submessages. */ - --e->top; - top(e)->msglen += msglen + upb_varint_size(msglen); - } - - return true; -} - - -/* tag_t **********************************************************************/ - -/* A precomputed (pre-encoded) tag and length. */ - -typedef struct { - uint8_t bytes; - char tag[7]; -} tag_t; - -/* Allocates a new tag for this field, and sets it in these handlerattr. */ -static void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt, - upb_handlerattr *attr) { - uint32_t n = upb_fielddef_number(f); - - tag_t *tag = upb_gmalloc(sizeof(tag_t)); - tag->bytes = upb_vencode64((n << 3) | wt, tag->tag); - - upb_handlerattr_init(attr); - upb_handlerattr_sethandlerdata(attr, tag); - upb_handlers_addcleanup(h, tag, upb_gfree); -} - -static bool encode_tag(upb_pb_encoder *e, const tag_t *tag) { - return encode_bytes(e, tag->tag, tag->bytes); -} - - -/* encoding of wire types *****************************************************/ - -static bool encode_fixed64(upb_pb_encoder *e, uint64_t val) { - /* TODO(haberman): byte-swap for big endian. */ - return encode_bytes(e, &val, sizeof(uint64_t)); -} - -static bool encode_fixed32(upb_pb_encoder *e, uint32_t val) { - /* TODO(haberman): byte-swap for big endian. */ - return encode_bytes(e, &val, sizeof(uint32_t)); -} - -static bool encode_varint(upb_pb_encoder *e, uint64_t val) { - if (!reserve(e, UPB_PB_VARINT_MAX_LEN)) { - return false; - } - - encoder_advance(e, upb_vencode64(val, e->ptr)); - return true; -} - -static uint64_t dbl2uint64(double d) { - uint64_t ret; - memcpy(&ret, &d, sizeof(uint64_t)); - return ret; -} - -static uint32_t flt2uint32(float d) { - uint32_t ret; - memcpy(&ret, &d, sizeof(uint32_t)); - return ret; -} - - -/* encoding of proto types ****************************************************/ - -static bool startmsg(void *c, const void *hd) { - upb_pb_encoder *e = c; - UPB_UNUSED(hd); - if (e->depth++ == 0) { - upb_bytessink_start(e->output_, 0, &e->subc); - } - return true; -} - -static bool endmsg(void *c, const void *hd, upb_status *status) { - upb_pb_encoder *e = c; - UPB_UNUSED(hd); - UPB_UNUSED(status); - if (--e->depth == 0) { - upb_bytessink_end(e->output_); - } - return true; -} - -static void *encode_startdelimfield(void *c, const void *hd) { - bool ok = encode_tag(c, hd) && commit(c) && start_delim(c); - return ok ? c : UPB_BREAK; -} - -static bool encode_enddelimfield(void *c, const void *hd) { - UPB_UNUSED(hd); - return end_delim(c); -} - -static void *encode_startgroup(void *c, const void *hd) { - return (encode_tag(c, hd) && commit(c)) ? c : UPB_BREAK; -} - -static bool encode_endgroup(void *c, const void *hd) { - return encode_tag(c, hd) && commit(c); -} - -static void *encode_startstr(void *c, const void *hd, size_t size_hint) { - UPB_UNUSED(size_hint); - return encode_startdelimfield(c, hd); -} - -static size_t encode_strbuf(void *c, const void *hd, const char *buf, - size_t len, const upb_bufhandle *h) { - UPB_UNUSED(hd); - UPB_UNUSED(h); - return encode_bytes(c, buf, len) ? len : 0; -} - -#define T(type, ctype, convert, encode) \ - static bool encode_scalar_##type(void *e, const void *hd, ctype val) { \ - return encode_tag(e, hd) && encode(e, (convert)(val)) && commit(e); \ - } \ - static bool encode_packed_##type(void *e, const void *hd, ctype val) { \ - UPB_UNUSED(hd); \ - return encode(e, (convert)(val)); \ - } - -T(double, double, dbl2uint64, encode_fixed64) -T(float, float, flt2uint32, encode_fixed32) -T(int64, int64_t, uint64_t, encode_varint) -T(int32, int32_t, int64_t, encode_varint) -T(fixed64, uint64_t, uint64_t, encode_fixed64) -T(fixed32, uint32_t, uint32_t, encode_fixed32) -T(bool, bool, bool, encode_varint) -T(uint32, uint32_t, uint32_t, encode_varint) -T(uint64, uint64_t, uint64_t, encode_varint) -T(enum, int32_t, uint32_t, encode_varint) -T(sfixed32, int32_t, uint32_t, encode_fixed32) -T(sfixed64, int64_t, uint64_t, encode_fixed64) -T(sint32, int32_t, upb_zzenc_32, encode_varint) -T(sint64, int64_t, upb_zzenc_64, encode_varint) - -#undef T - - -/* code to build the handlers *************************************************/ - -static void newhandlers_callback(const void *closure, upb_handlers *h) { - const upb_msgdef *m; - upb_msg_field_iter i; - - UPB_UNUSED(closure); - - upb_handlers_setstartmsg(h, startmsg, NULL); - upb_handlers_setendmsg(h, endmsg, NULL); - - m = upb_handlers_msgdef(h); - for(upb_msg_field_begin(&i, m); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) && - upb_fielddef_packed(f); - upb_handlerattr attr; - upb_wiretype_t wt = - packed ? UPB_WIRE_TYPE_DELIMITED - : upb_pb_native_wire_types[upb_fielddef_descriptortype(f)]; - - /* Pre-encode the tag for this field. */ - new_tag(h, f, wt, &attr); - - if (packed) { - upb_handlers_setstartseq(h, f, encode_startdelimfield, &attr); - upb_handlers_setendseq(h, f, encode_enddelimfield, &attr); - } - -#define T(upper, lower, upbtype) \ - case UPB_DESCRIPTOR_TYPE_##upper: \ - if (packed) { \ - upb_handlers_set##upbtype(h, f, encode_packed_##lower, &attr); \ - } else { \ - upb_handlers_set##upbtype(h, f, encode_scalar_##lower, &attr); \ - } \ - break; - - switch (upb_fielddef_descriptortype(f)) { - T(DOUBLE, double, double); - T(FLOAT, float, float); - T(INT64, int64, int64); - T(INT32, int32, int32); - T(FIXED64, fixed64, uint64); - T(FIXED32, fixed32, uint32); - T(BOOL, bool, bool); - T(UINT32, uint32, uint32); - T(UINT64, uint64, uint64); - T(ENUM, enum, int32); - T(SFIXED32, sfixed32, int32); - T(SFIXED64, sfixed64, int64); - T(SINT32, sint32, int32); - T(SINT64, sint64, int64); - case UPB_DESCRIPTOR_TYPE_STRING: - case UPB_DESCRIPTOR_TYPE_BYTES: - upb_handlers_setstartstr(h, f, encode_startstr, &attr); - upb_handlers_setendstr(h, f, encode_enddelimfield, &attr); - upb_handlers_setstring(h, f, encode_strbuf, &attr); - break; - case UPB_DESCRIPTOR_TYPE_MESSAGE: - upb_handlers_setstartsubmsg(h, f, encode_startdelimfield, &attr); - upb_handlers_setendsubmsg(h, f, encode_enddelimfield, &attr); - break; - case UPB_DESCRIPTOR_TYPE_GROUP: { - /* Endgroup takes a different tag (wire_type = END_GROUP). */ - upb_handlerattr attr2; - new_tag(h, f, UPB_WIRE_TYPE_END_GROUP, &attr2); - - upb_handlers_setstartsubmsg(h, f, encode_startgroup, &attr); - upb_handlers_setendsubmsg(h, f, encode_endgroup, &attr2); - - upb_handlerattr_uninit(&attr2); - break; - } - } - -#undef T - - upb_handlerattr_uninit(&attr); - } -} - -void upb_pb_encoder_reset(upb_pb_encoder *e) { - e->segptr = NULL; - e->top = NULL; - e->depth = 0; -} - - -/* public API *****************************************************************/ - -const upb_handlers *upb_pb_encoder_newhandlers(const upb_msgdef *m, - const void *owner) { - return upb_handlers_newfrozen(m, owner, newhandlers_callback, NULL); -} - -upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h, - upb_bytessink *output) { - const size_t initial_bufsize = 256; - const size_t initial_segbufsize = 16; - /* TODO(haberman): make this configurable. */ - const size_t stack_size = 64; -#ifndef NDEBUG - const size_t size_before = upb_env_bytesallocated(env); -#endif - - upb_pb_encoder *e = upb_env_malloc(env, sizeof(upb_pb_encoder)); - if (!e) return NULL; - - e->buf = upb_env_malloc(env, initial_bufsize); - e->segbuf = upb_env_malloc(env, initial_segbufsize * sizeof(*e->segbuf)); - e->stack = upb_env_malloc(env, stack_size * sizeof(*e->stack)); - - if (!e->buf || !e->segbuf || !e->stack) { - return NULL; - } - - e->limit = e->buf + initial_bufsize; - e->seglimit = e->segbuf + initial_segbufsize; - e->stacklimit = e->stack + stack_size; - - upb_pb_encoder_reset(e); - upb_sink_reset(&e->input_, h, e); - - e->env = env; - e->output_ = output; - e->subc = output->closure; - e->ptr = e->buf; - - /* If this fails, increase the value in encoder.h. */ - UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <= - UPB_PB_ENCODER_SIZE); - return e; -} - -upb_sink *upb_pb_encoder_input(upb_pb_encoder *e) { return &e->input_; } - - - -upb_filedef **upb_loaddescriptor(const char *buf, size_t n, const void *owner, - upb_status *status) { - /* Create handlers. */ - const upb_pbdecodermethod *decoder_m; - const upb_handlers *reader_h = upb_descreader_newhandlers(&reader_h); - upb_env env; - upb_pbdecodermethodopts opts; - upb_pbdecoder *decoder; - upb_descreader *reader; - bool ok; - size_t i; - upb_filedef **ret = NULL; - - upb_pbdecodermethodopts_init(&opts, reader_h); - decoder_m = upb_pbdecodermethod_new(&opts, &decoder_m); - - upb_env_init(&env); - upb_env_reporterrorsto(&env, status); - - reader = upb_descreader_create(&env, reader_h); - decoder = upb_pbdecoder_create(&env, decoder_m, upb_descreader_input(reader)); - - /* Push input data. */ - ok = upb_bufsrc_putbuf(buf, n, upb_pbdecoder_input(decoder)); - - if (!ok) { - goto cleanup; - } - - ret = upb_gmalloc(sizeof (*ret) * (upb_descreader_filecount(reader) + 1)); - - if (!ret) { - goto cleanup; - } - - for (i = 0; i < upb_descreader_filecount(reader); i++) { - ret[i] = upb_descreader_file(reader, i); - upb_filedef_ref(ret[i], owner); - } - - ret[i] = NULL; - -cleanup: - upb_env_uninit(&env); - upb_handlers_unref(reader_h, &reader_h); - upb_pbdecodermethod_unref(decoder_m, &decoder_m); - return ret; -} -/* - * upb::pb::TextPrinter - * - * OPT: This is not optimized at all. It uses printf() which parses the format - * string every time, and it allocates memory for every put. - */ - - -#include -#include -#include -#include -#include -#include - - -struct upb_textprinter { - upb_sink input_; - upb_bytessink *output_; - int indent_depth_; - bool single_line_; - void *subc; -}; - -#define CHECK(x) if ((x) < 0) goto err; - -static const char *shortname(const char *longname) { - const char *last = strrchr(longname, '.'); - return last ? last + 1 : longname; -} - -static int indent(upb_textprinter *p) { - int i; - if (!p->single_line_) - for (i = 0; i < p->indent_depth_; i++) - upb_bytessink_putbuf(p->output_, p->subc, " ", 2, NULL); - return 0; -} - -static int endfield(upb_textprinter *p) { - const char ch = (p->single_line_ ? ' ' : '\n'); - upb_bytessink_putbuf(p->output_, p->subc, &ch, 1, NULL); - return 0; -} - -static int putescaped(upb_textprinter *p, const char *buf, size_t len, - bool preserve_utf8) { - /* Based on CEscapeInternal() from Google's protobuf release. */ - char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf); - const char *end = buf + len; - - /* I think hex is prettier and more useful, but proto2 uses octal; should - * investigate whether it can parse hex also. */ - const bool use_hex = false; - bool last_hex_escape = false; /* true if last output char was \xNN */ - - for (; buf < end; buf++) { - bool is_hex_escape; - - if (dstend - dst < 4) { - upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL); - dst = dstbuf; - } - - is_hex_escape = false; - switch (*buf) { - case '\n': *(dst++) = '\\'; *(dst++) = 'n'; break; - case '\r': *(dst++) = '\\'; *(dst++) = 'r'; break; - case '\t': *(dst++) = '\\'; *(dst++) = 't'; break; - case '\"': *(dst++) = '\\'; *(dst++) = '\"'; break; - case '\'': *(dst++) = '\\'; *(dst++) = '\''; break; - case '\\': *(dst++) = '\\'; *(dst++) = '\\'; break; - default: - /* Note that if we emit \xNN and the buf character after that is a hex - * digit then that digit must be escaped too to prevent it being - * interpreted as part of the character code by C. */ - if ((!preserve_utf8 || (uint8_t)*buf < 0x80) && - (!isprint(*buf) || (last_hex_escape && isxdigit(*buf)))) { - sprintf(dst, (use_hex ? "\\x%02x" : "\\%03o"), (uint8_t)*buf); - is_hex_escape = use_hex; - dst += 4; - } else { - *(dst++) = *buf; break; - } - } - last_hex_escape = is_hex_escape; - } - /* Flush remaining data. */ - upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL); - return 0; -} - -bool putf(upb_textprinter *p, const char *fmt, ...) { - va_list args; - va_list args_copy; - char *str; - int written; - int len; - bool ok; - - va_start(args, fmt); - - /* Run once to get the length of the string. */ - _upb_va_copy(args_copy, args); - len = _upb_vsnprintf(NULL, 0, fmt, args_copy); - va_end(args_copy); - - /* + 1 for NULL terminator (vsprintf() requires it even if we don't). */ - str = upb_gmalloc(len + 1); - if (!str) return false; - written = vsprintf(str, fmt, args); - va_end(args); - UPB_ASSERT(written == len); - - ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL); - upb_gfree(str); - return ok; -} - - -/* handlers *******************************************************************/ - -static bool textprinter_startmsg(void *c, const void *hd) { - upb_textprinter *p = c; - UPB_UNUSED(hd); - if (p->indent_depth_ == 0) { - upb_bytessink_start(p->output_, 0, &p->subc); - } - return true; -} - -static bool textprinter_endmsg(void *c, const void *hd, upb_status *s) { - upb_textprinter *p = c; - UPB_UNUSED(hd); - UPB_UNUSED(s); - if (p->indent_depth_ == 0) { - upb_bytessink_end(p->output_); - } - return true; -} - -#define TYPE(name, ctype, fmt) \ - static bool textprinter_put ## name(void *closure, const void *handler_data, \ - ctype val) { \ - upb_textprinter *p = closure; \ - const upb_fielddef *f = handler_data; \ - CHECK(indent(p)); \ - putf(p, "%s: " fmt, upb_fielddef_name(f), val); \ - CHECK(endfield(p)); \ - return true; \ - err: \ - return false; \ -} - -static bool textprinter_putbool(void *closure, const void *handler_data, - bool val) { - upb_textprinter *p = closure; - const upb_fielddef *f = handler_data; - CHECK(indent(p)); - putf(p, "%s: %s", upb_fielddef_name(f), val ? "true" : "false"); - CHECK(endfield(p)); - return true; -err: - return false; -} - -#define STRINGIFY_HELPER(x) #x -#define STRINGIFY_MACROVAL(x) STRINGIFY_HELPER(x) - -TYPE(int32, int32_t, "%" PRId32) -TYPE(int64, int64_t, "%" PRId64) -TYPE(uint32, uint32_t, "%" PRIu32) -TYPE(uint64, uint64_t, "%" PRIu64) -TYPE(float, float, "%." STRINGIFY_MACROVAL(FLT_DIG) "g") -TYPE(double, double, "%." STRINGIFY_MACROVAL(DBL_DIG) "g") - -#undef TYPE - -/* Output a symbolic value from the enum if found, else just print as int32. */ -static bool textprinter_putenum(void *closure, const void *handler_data, - int32_t val) { - upb_textprinter *p = closure; - const upb_fielddef *f = handler_data; - const upb_enumdef *enum_def = upb_downcast_enumdef(upb_fielddef_subdef(f)); - const char *label = upb_enumdef_iton(enum_def, val); - if (label) { - indent(p); - putf(p, "%s: %s", upb_fielddef_name(f), label); - endfield(p); - } else { - if (!textprinter_putint32(closure, handler_data, val)) - return false; - } - return true; -} - -static void *textprinter_startstr(void *closure, const void *handler_data, - size_t size_hint) { - upb_textprinter *p = closure; - const upb_fielddef *f = handler_data; - UPB_UNUSED(size_hint); - indent(p); - putf(p, "%s: \"", upb_fielddef_name(f)); - return p; -} - -static bool textprinter_endstr(void *closure, const void *handler_data) { - upb_textprinter *p = closure; - UPB_UNUSED(handler_data); - putf(p, "\""); - endfield(p); - return true; -} - -static size_t textprinter_putstr(void *closure, const void *hd, const char *buf, - size_t len, const upb_bufhandle *handle) { - upb_textprinter *p = closure; - const upb_fielddef *f = hd; - UPB_UNUSED(handle); - CHECK(putescaped(p, buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING)); - return len; -err: - return 0; -} - -static void *textprinter_startsubmsg(void *closure, const void *handler_data) { - upb_textprinter *p = closure; - const char *name = handler_data; - CHECK(indent(p)); - putf(p, "%s {%c", name, p->single_line_ ? ' ' : '\n'); - p->indent_depth_++; - return p; -err: - return UPB_BREAK; -} - -static bool textprinter_endsubmsg(void *closure, const void *handler_data) { - upb_textprinter *p = closure; - UPB_UNUSED(handler_data); - p->indent_depth_--; - CHECK(indent(p)); - upb_bytessink_putbuf(p->output_, p->subc, "}", 1, NULL); - CHECK(endfield(p)); - return true; -err: - return false; -} - -static void onmreg(const void *c, upb_handlers *h) { - const upb_msgdef *m = upb_handlers_msgdef(h); - upb_msg_field_iter i; - UPB_UNUSED(c); - - upb_handlers_setstartmsg(h, textprinter_startmsg, NULL); - upb_handlers_setendmsg(h, textprinter_endmsg, NULL); - - for(upb_msg_field_begin(&i, m); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, f); - switch (upb_fielddef_type(f)) { - case UPB_TYPE_INT32: - upb_handlers_setint32(h, f, textprinter_putint32, &attr); - break; - case UPB_TYPE_INT64: - upb_handlers_setint64(h, f, textprinter_putint64, &attr); - break; - case UPB_TYPE_UINT32: - upb_handlers_setuint32(h, f, textprinter_putuint32, &attr); - break; - case UPB_TYPE_UINT64: - upb_handlers_setuint64(h, f, textprinter_putuint64, &attr); - break; - case UPB_TYPE_FLOAT: - upb_handlers_setfloat(h, f, textprinter_putfloat, &attr); - break; - case UPB_TYPE_DOUBLE: - upb_handlers_setdouble(h, f, textprinter_putdouble, &attr); - break; - case UPB_TYPE_BOOL: - upb_handlers_setbool(h, f, textprinter_putbool, &attr); - break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - upb_handlers_setstartstr(h, f, textprinter_startstr, &attr); - upb_handlers_setstring(h, f, textprinter_putstr, &attr); - upb_handlers_setendstr(h, f, textprinter_endstr, &attr); - break; - case UPB_TYPE_MESSAGE: { - const char *name = - upb_fielddef_istagdelim(f) - ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f))) - : upb_fielddef_name(f); - upb_handlerattr_sethandlerdata(&attr, name); - upb_handlers_setstartsubmsg(h, f, textprinter_startsubmsg, &attr); - upb_handlers_setendsubmsg(h, f, textprinter_endsubmsg, &attr); - break; - } - case UPB_TYPE_ENUM: - upb_handlers_setint32(h, f, textprinter_putenum, &attr); - break; - } - } -} - -static void textprinter_reset(upb_textprinter *p, bool single_line) { - p->single_line_ = single_line; - p->indent_depth_ = 0; -} - - -/* Public API *****************************************************************/ - -upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h, - upb_bytessink *output) { - upb_textprinter *p = upb_env_malloc(env, sizeof(upb_textprinter)); - if (!p) return NULL; - - p->output_ = output; - upb_sink_reset(&p->input_, h, p); - textprinter_reset(p, false); - - return p; -} - -const upb_handlers *upb_textprinter_newhandlers(const upb_msgdef *m, - const void *owner) { - return upb_handlers_newfrozen(m, owner, &onmreg, NULL); -} - -upb_sink *upb_textprinter_input(upb_textprinter *p) { return &p->input_; } - -void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) { - p->single_line_ = single_line; -} - - -/* Index is descriptor type. */ -const uint8_t upb_pb_native_wire_types[] = { - UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */ - UPB_WIRE_TYPE_64BIT, /* DOUBLE */ - UPB_WIRE_TYPE_32BIT, /* FLOAT */ - UPB_WIRE_TYPE_VARINT, /* INT64 */ - UPB_WIRE_TYPE_VARINT, /* UINT64 */ - UPB_WIRE_TYPE_VARINT, /* INT32 */ - UPB_WIRE_TYPE_64BIT, /* FIXED64 */ - UPB_WIRE_TYPE_32BIT, /* FIXED32 */ - UPB_WIRE_TYPE_VARINT, /* BOOL */ - UPB_WIRE_TYPE_DELIMITED, /* STRING */ - UPB_WIRE_TYPE_START_GROUP, /* GROUP */ - UPB_WIRE_TYPE_DELIMITED, /* MESSAGE */ - UPB_WIRE_TYPE_DELIMITED, /* BYTES */ - UPB_WIRE_TYPE_VARINT, /* UINT32 */ - UPB_WIRE_TYPE_VARINT, /* ENUM */ - UPB_WIRE_TYPE_32BIT, /* SFIXED32 */ - UPB_WIRE_TYPE_64BIT, /* SFIXED64 */ - UPB_WIRE_TYPE_VARINT, /* SINT32 */ - UPB_WIRE_TYPE_VARINT, /* SINT64 */ -}; - -/* A basic branch-based decoder, uses 32-bit values to get good performance - * on 32-bit architectures (but performs well on 64-bits also). - * This scheme comes from the original Google Protobuf implementation - * (proto2). */ -upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r) { - upb_decoderet err = {NULL, 0}; - const char *p = r.p; - uint32_t low = (uint32_t)r.val; - uint32_t high = 0; - uint32_t b; - b = *(p++); low |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done; - b = *(p++); low |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done; - b = *(p++); low |= (b & 0x7fU) << 28; - high = (b & 0x7fU) >> 4; if (!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7fU) << 3; if (!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7fU) << 10; if (!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7fU) << 17; if (!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7fU) << 24; if (!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7fU) << 31; if (!(b & 0x80)) goto done; - return err; - -done: - r.val = ((uint64_t)high << 32) | low; - r.p = p; - return r; -} - -/* Like the previous, but uses 64-bit values. */ -upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r) { - const char *p = r.p; - uint64_t val = r.val; - uint64_t b; - upb_decoderet err = {NULL, 0}; - b = *(p++); val |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7fU) << 28; if (!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7fU) << 35; if (!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7fU) << 42; if (!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7fU) << 49; if (!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7fU) << 56; if (!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7fU) << 63; if (!(b & 0x80)) goto done; - return err; - -done: - r.val = val; - r.p = p; - return r; -} - -#line 1 "upb/json/parser.rl" -/* -** upb::json::Parser (upb_json_parser) -** -** A parser that uses the Ragel State Machine Compiler to generate -** the finite automata. -** -** Ragel only natively handles regular languages, but we can manually -** program it a bit to handle context-free languages like JSON, by using -** the "fcall" and "fret" constructs. -** -** This parser can handle the basics, but needs several things to be fleshed -** out: -** -** - handling of unicode escape sequences (including high surrogate pairs). -** - properly check and report errors for unknown fields, stack overflow, -** improper array nesting (or lack of nesting). -** - handling of base64 sequences with padding characters. -** - handling of push-back (non-success returns from sink functions). -** - handling of keys/escape-sequences/etc that span input buffers. -*/ - -#include -#include -#include -#include -#include - - -#define UPB_JSON_MAX_DEPTH 64 - -typedef struct { - upb_sink sink; - - /* The current message in which we're parsing, and the field whose value we're - * expecting next. */ - const upb_msgdef *m; - const upb_fielddef *f; - - /* The table mapping json name to fielddef for this message. */ - upb_strtable *name_table; - - /* We are in a repeated-field context, ready to emit mapentries as - * submessages. This flag alters the start-of-object (open-brace) behavior to - * begin a sequence of mapentry messages rather than a single submessage. */ - bool is_map; - - /* We are in a map-entry message context. This flag is set when parsing the - * value field of a single map entry and indicates to all value-field parsers - * (subobjects, strings, numbers, and bools) that the map-entry submessage - * should end as soon as the value is parsed. */ - bool is_mapentry; - - /* If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent - * message's map field that we're currently parsing. This differs from |f| - * because |f| is the field in the *current* message (i.e., the map-entry - * message itself), not the parent's field that leads to this map. */ - const upb_fielddef *mapfield; -} upb_jsonparser_frame; - -struct upb_json_parser { - upb_env *env; - const upb_json_parsermethod *method; - upb_bytessink input_; - - /* Stack to track the JSON scopes we are in. */ - upb_jsonparser_frame stack[UPB_JSON_MAX_DEPTH]; - upb_jsonparser_frame *top; - upb_jsonparser_frame *limit; - - upb_status status; - - /* Ragel's internal parsing stack for the parsing state machine. */ - int current_state; - int parser_stack[UPB_JSON_MAX_DEPTH]; - int parser_top; - - /* The handle for the current buffer. */ - const upb_bufhandle *handle; - - /* Accumulate buffer. See details in parser.rl. */ - const char *accumulated; - size_t accumulated_len; - char *accumulate_buf; - size_t accumulate_buf_size; - - /* Multi-part text data. See details in parser.rl. */ - int multipart_state; - upb_selector_t string_selector; - - /* Input capture. See details in parser.rl. */ - const char *capture; - - /* Intermediate result of parsing a unicode escape sequence. */ - uint32_t digit; -}; - -struct upb_json_parsermethod { - upb_refcounted base; - - upb_byteshandler input_handler_; - - /* Mainly for the purposes of refcounting, so all the fielddefs we point - * to stay alive. */ - const upb_msgdef *msg; - - /* Keys are upb_msgdef*, values are upb_strtable (json_name -> fielddef) */ - upb_inttable name_tables; -}; - -#define PARSER_CHECK_RETURN(x) if (!(x)) return false - -/* Used to signal that a capture has been suspended. */ -static char suspend_capture; - -static upb_selector_t getsel_for_handlertype(upb_json_parser *p, - upb_handlertype_t type) { - upb_selector_t sel; - bool ok = upb_handlers_getselector(p->top->f, type, &sel); - UPB_ASSERT(ok); - return sel; -} - -static upb_selector_t parser_getsel(upb_json_parser *p) { - return getsel_for_handlertype( - p, upb_handlers_getprimitivehandlertype(p->top->f)); -} - -static bool check_stack(upb_json_parser *p) { - if ((p->top + 1) == p->limit) { - upb_status_seterrmsg(&p->status, "Nesting too deep"); - upb_env_reporterror(p->env, &p->status); - return false; - } - - return true; -} - -static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) { - upb_value v; - bool ok = upb_inttable_lookupptr(&p->method->name_tables, frame->m, &v); - UPB_ASSERT(ok); - frame->name_table = upb_value_getptr(v); -} - -/* There are GCC/Clang built-ins for overflow checking which we could start - * using if there was any performance benefit to it. */ - -static bool checked_add(size_t a, size_t b, size_t *c) { - if (SIZE_MAX - a < b) return false; - *c = a + b; - return true; -} - -static size_t saturating_multiply(size_t a, size_t b) { - /* size_t is unsigned, so this is defined behavior even on overflow. */ - size_t ret = a * b; - if (b != 0 && ret / b != a) { - ret = SIZE_MAX; - } - return ret; -} - - -/* Base64 decoding ************************************************************/ - -/* TODO(haberman): make this streaming. */ - -static const signed char b64table[] = { - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */, - 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, - 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1, - -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, - 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, - 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, - 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1, - -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, - 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, - 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, - 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 -}; - -/* Returns the table value sign-extended to 32 bits. Knowing that the upper - * bits will be 1 for unrecognized characters makes it easier to check for - * this error condition later (see below). */ -int32_t b64lookup(unsigned char ch) { return b64table[ch]; } - -/* Returns true if the given character is not a valid base64 character or - * padding. */ -bool nonbase64(unsigned char ch) { return b64lookup(ch) == -1 && ch != '='; } - -static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr, - size_t len) { - const char *limit = ptr + len; - for (; ptr < limit; ptr += 4) { - uint32_t val; - char output[3]; - - if (limit - ptr < 4) { - upb_status_seterrf(&p->status, - "Base64 input for bytes field not a multiple of 4: %s", - upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); - return false; - } - - val = b64lookup(ptr[0]) << 18 | - b64lookup(ptr[1]) << 12 | - b64lookup(ptr[2]) << 6 | - b64lookup(ptr[3]); - - /* Test the upper bit; returns true if any of the characters returned -1. */ - if (val & 0x80000000) { - goto otherchar; - } - - output[0] = val >> 16; - output[1] = (val >> 8) & 0xff; - output[2] = val & 0xff; - upb_sink_putstring(&p->top->sink, sel, output, 3, NULL); - } - return true; - -otherchar: - if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) || - nonbase64(ptr[3]) ) { - upb_status_seterrf(&p->status, - "Non-base64 characters in bytes field: %s", - upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); - return false; - } if (ptr[2] == '=') { - uint32_t val; - char output; - - /* Last group contains only two input bytes, one output byte. */ - if (ptr[0] == '=' || ptr[1] == '=' || ptr[3] != '=') { - goto badpadding; - } - - val = b64lookup(ptr[0]) << 18 | - b64lookup(ptr[1]) << 12; - - UPB_ASSERT(!(val & 0x80000000)); - output = val >> 16; - upb_sink_putstring(&p->top->sink, sel, &output, 1, NULL); - return true; - } else { - uint32_t val; - char output[2]; - - /* Last group contains only three input bytes, two output bytes. */ - if (ptr[0] == '=' || ptr[1] == '=' || ptr[2] == '=') { - goto badpadding; - } - - val = b64lookup(ptr[0]) << 18 | - b64lookup(ptr[1]) << 12 | - b64lookup(ptr[2]) << 6; - - output[0] = val >> 16; - output[1] = (val >> 8) & 0xff; - upb_sink_putstring(&p->top->sink, sel, output, 2, NULL); - return true; - } - -badpadding: - upb_status_seterrf(&p->status, - "Incorrect base64 padding for field: %s (%.*s)", - upb_fielddef_name(p->top->f), - 4, ptr); - upb_env_reporterror(p->env, &p->status); - return false; -} - - -/* Accumulate buffer **********************************************************/ - -/* Functionality for accumulating a buffer. - * - * Some parts of the parser need an entire value as a contiguous string. For - * example, to look up a member name in a hash table, or to turn a string into - * a number, the relevant library routines need the input string to be in - * contiguous memory, even if the value spanned two or more buffers in the - * input. These routines handle that. - * - * In the common case we can just point to the input buffer to get this - * contiguous string and avoid any actual copy. So we optimistically begin - * this way. But there are a few cases where we must instead copy into a - * separate buffer: - * - * 1. The string was not contiguous in the input (it spanned buffers). - * - * 2. The string included escape sequences that need to be interpreted to get - * the true value in a contiguous buffer. */ - -static void assert_accumulate_empty(upb_json_parser *p) { - UPB_ASSERT(p->accumulated == NULL); - UPB_ASSERT(p->accumulated_len == 0); -} - -static void accumulate_clear(upb_json_parser *p) { - p->accumulated = NULL; - p->accumulated_len = 0; -} - -/* Used internally by accumulate_append(). */ -static bool accumulate_realloc(upb_json_parser *p, size_t need) { - void *mem; - size_t old_size = p->accumulate_buf_size; - size_t new_size = UPB_MAX(old_size, 128); - while (new_size < need) { - new_size = saturating_multiply(new_size, 2); - } - - mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size); - if (!mem) { - upb_status_seterrmsg(&p->status, "Out of memory allocating buffer."); - upb_env_reporterror(p->env, &p->status); - return false; - } - - p->accumulate_buf = mem; - p->accumulate_buf_size = new_size; - return true; -} - -/* Logically appends the given data to the append buffer. - * If "can_alias" is true, we will try to avoid actually copying, but the buffer - * must be valid until the next accumulate_append() call (if any). */ -static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len, - bool can_alias) { - size_t need; - - if (!p->accumulated && can_alias) { - p->accumulated = buf; - p->accumulated_len = len; - return true; - } - - if (!checked_add(p->accumulated_len, len, &need)) { - upb_status_seterrmsg(&p->status, "Integer overflow."); - upb_env_reporterror(p->env, &p->status); - return false; - } - - if (need > p->accumulate_buf_size && !accumulate_realloc(p, need)) { - return false; - } - - if (p->accumulated != p->accumulate_buf) { - memcpy(p->accumulate_buf, p->accumulated, p->accumulated_len); - p->accumulated = p->accumulate_buf; - } - - memcpy(p->accumulate_buf + p->accumulated_len, buf, len); - p->accumulated_len += len; - return true; -} - -/* Returns a pointer to the data accumulated since the last accumulate_clear() - * call, and writes the length to *len. This with point either to the input - * buffer or a temporary accumulate buffer. */ -static const char *accumulate_getptr(upb_json_parser *p, size_t *len) { - UPB_ASSERT(p->accumulated); - *len = p->accumulated_len; - return p->accumulated; -} - - -/* Mult-part text data ********************************************************/ - -/* When we have text data in the input, it can often come in multiple segments. - * For example, there may be some raw string data followed by an escape - * sequence. The two segments are processed with different logic. Also buffer - * seams in the input can cause multiple segments. - * - * As we see segments, there are two main cases for how we want to process them: - * - * 1. we want to push the captured input directly to string handlers. - * - * 2. we need to accumulate all the parts into a contiguous buffer for further - * processing (field name lookup, string->number conversion, etc). */ - -/* This is the set of states for p->multipart_state. */ -enum { - /* We are not currently processing multipart data. */ - MULTIPART_INACTIVE = 0, - - /* We are processing multipart data by accumulating it into a contiguous - * buffer. */ - MULTIPART_ACCUMULATE = 1, - - /* We are processing multipart data by pushing each part directly to the - * current string handlers. */ - MULTIPART_PUSHEAGERLY = 2 -}; - -/* Start a multi-part text value where we accumulate the data for processing at - * the end. */ -static void multipart_startaccum(upb_json_parser *p) { - assert_accumulate_empty(p); - UPB_ASSERT(p->multipart_state == MULTIPART_INACTIVE); - p->multipart_state = MULTIPART_ACCUMULATE; -} - -/* Start a multi-part text value where we immediately push text data to a string - * value with the given selector. */ -static void multipart_start(upb_json_parser *p, upb_selector_t sel) { - assert_accumulate_empty(p); - UPB_ASSERT(p->multipart_state == MULTIPART_INACTIVE); - p->multipart_state = MULTIPART_PUSHEAGERLY; - p->string_selector = sel; -} - -static bool multipart_text(upb_json_parser *p, const char *buf, size_t len, - bool can_alias) { - switch (p->multipart_state) { - case MULTIPART_INACTIVE: - upb_status_seterrmsg( - &p->status, "Internal error: unexpected state MULTIPART_INACTIVE"); - upb_env_reporterror(p->env, &p->status); - return false; - - case MULTIPART_ACCUMULATE: - if (!accumulate_append(p, buf, len, can_alias)) { - return false; - } - break; - - case MULTIPART_PUSHEAGERLY: { - const upb_bufhandle *handle = can_alias ? p->handle : NULL; - upb_sink_putstring(&p->top->sink, p->string_selector, buf, len, handle); - break; - } - } - - return true; -} - -/* Note: this invalidates the accumulate buffer! Call only after reading its - * contents. */ -static void multipart_end(upb_json_parser *p) { - UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE); - p->multipart_state = MULTIPART_INACTIVE; - accumulate_clear(p); -} - - -/* Input capture **************************************************************/ - -/* Functionality for capturing a region of the input as text. Gracefully - * handles the case where a buffer seam occurs in the middle of the captured - * region. */ - -static void capture_begin(upb_json_parser *p, const char *ptr) { - UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE); - UPB_ASSERT(p->capture == NULL); - p->capture = ptr; -} - -static bool capture_end(upb_json_parser *p, const char *ptr) { - UPB_ASSERT(p->capture); - if (multipart_text(p, p->capture, ptr - p->capture, true)) { - p->capture = NULL; - return true; - } else { - return false; - } -} - -/* This is called at the end of each input buffer (ie. when we have hit a - * buffer seam). If we are in the middle of capturing the input, this - * processes the unprocessed capture region. */ -static void capture_suspend(upb_json_parser *p, const char **ptr) { - if (!p->capture) return; - - if (multipart_text(p, p->capture, *ptr - p->capture, false)) { - /* We use this as a signal that we were in the middle of capturing, and - * that capturing should resume at the beginning of the next buffer. - * - * We can't use *ptr here, because we have no guarantee that this pointer - * will be valid when we resume (if the underlying memory is freed, then - * using the pointer at all, even to compare to NULL, is likely undefined - * behavior). */ - p->capture = &suspend_capture; - } else { - /* Need to back up the pointer to the beginning of the capture, since - * we were not able to actually preserve it. */ - *ptr = p->capture; - } -} - -static void capture_resume(upb_json_parser *p, const char *ptr) { - if (p->capture) { - UPB_ASSERT(p->capture == &suspend_capture); - p->capture = ptr; - } -} - - -/* Callbacks from the parser **************************************************/ - -/* These are the functions called directly from the parser itself. - * We define these in the same order as their declarations in the parser. */ - -static char escape_char(char in) { - switch (in) { - case 'r': return '\r'; - case 't': return '\t'; - case 'n': return '\n'; - case 'f': return '\f'; - case 'b': return '\b'; - case '/': return '/'; - case '"': return '"'; - case '\\': return '\\'; - default: - UPB_ASSERT(0); - return 'x'; - } -} - -static bool escape(upb_json_parser *p, const char *ptr) { - char ch = escape_char(*ptr); - return multipart_text(p, &ch, 1, false); -} - -static void start_hex(upb_json_parser *p) { - p->digit = 0; -} - -static void hexdigit(upb_json_parser *p, const char *ptr) { - char ch = *ptr; - - p->digit <<= 4; - - if (ch >= '0' && ch <= '9') { - p->digit += (ch - '0'); - } else if (ch >= 'a' && ch <= 'f') { - p->digit += ((ch - 'a') + 10); - } else { - UPB_ASSERT(ch >= 'A' && ch <= 'F'); - p->digit += ((ch - 'A') + 10); - } -} - -static bool end_hex(upb_json_parser *p) { - uint32_t codepoint = p->digit; - - /* emit the codepoint as UTF-8. */ - char utf8[3]; /* support \u0000 -- \uFFFF -- need only three bytes. */ - int length = 0; - if (codepoint <= 0x7F) { - utf8[0] = codepoint; - length = 1; - } else if (codepoint <= 0x07FF) { - utf8[1] = (codepoint & 0x3F) | 0x80; - codepoint >>= 6; - utf8[0] = (codepoint & 0x1F) | 0xC0; - length = 2; - } else /* codepoint <= 0xFFFF */ { - utf8[2] = (codepoint & 0x3F) | 0x80; - codepoint >>= 6; - utf8[1] = (codepoint & 0x3F) | 0x80; - codepoint >>= 6; - utf8[0] = (codepoint & 0x0F) | 0xE0; - length = 3; - } - /* TODO(haberman): Handle high surrogates: if codepoint is a high surrogate - * we have to wait for the next escape to get the full code point). */ - - return multipart_text(p, utf8, length, false); -} - -static void start_text(upb_json_parser *p, const char *ptr) { - capture_begin(p, ptr); -} - -static bool end_text(upb_json_parser *p, const char *ptr) { - return capture_end(p, ptr); -} - -static void start_number(upb_json_parser *p, const char *ptr) { - multipart_startaccum(p); - capture_begin(p, ptr); -} - -static bool parse_number(upb_json_parser *p); - -static bool end_number(upb_json_parser *p, const char *ptr) { - if (!capture_end(p, ptr)) { - return false; - } - - return parse_number(p); -} - -static bool parse_number(upb_json_parser *p) { - size_t len; - const char *buf; - const char *myend; - char *end; - - /* strtol() and friends unfortunately do not support specifying the length of - * the input string, so we need to force a copy into a NULL-terminated buffer. */ - if (!multipart_text(p, "\0", 1, false)) { - return false; - } - - buf = accumulate_getptr(p, &len); - myend = buf + len - 1; /* One for NULL. */ - - /* XXX: We are using strtol to parse integers, but this is wrong as even - * integers can be represented as 1e6 (for example), which strtol can't - * handle correctly. - * - * XXX: Also, we can't handle large integers properly because strto[u]ll - * isn't in C89. - * - * XXX: Also, we don't properly check floats for overflow, since strtof - * isn't in C89. */ - switch (upb_fielddef_type(p->top->f)) { - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: { - long val = strtol(p->accumulated, &end, 0); - if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || end != myend) - goto err; - else - upb_sink_putint32(&p->top->sink, parser_getsel(p), val); - break; - } - case UPB_TYPE_INT64: { - long long val = strtol(p->accumulated, &end, 0); - if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || end != myend) - goto err; - else - upb_sink_putint64(&p->top->sink, parser_getsel(p), val); - break; - } - case UPB_TYPE_UINT32: { - unsigned long val = strtoul(p->accumulated, &end, 0); - if (val > UINT32_MAX || errno == ERANGE || end != myend) - goto err; - else - upb_sink_putuint32(&p->top->sink, parser_getsel(p), val); - break; - } - case UPB_TYPE_UINT64: { - unsigned long long val = strtoul(p->accumulated, &end, 0); - if (val > UINT64_MAX || errno == ERANGE || end != myend) - goto err; - else - upb_sink_putuint64(&p->top->sink, parser_getsel(p), val); - break; - } - case UPB_TYPE_DOUBLE: { - double val = strtod(p->accumulated, &end); - if (errno == ERANGE || end != myend) - goto err; - else - upb_sink_putdouble(&p->top->sink, parser_getsel(p), val); - break; - } - case UPB_TYPE_FLOAT: { - float val = strtod(p->accumulated, &end); - if (errno == ERANGE || end != myend) - goto err; - else - upb_sink_putfloat(&p->top->sink, parser_getsel(p), val); - break; - } - default: - UPB_ASSERT(false); - } - - multipart_end(p); - - return true; - -err: - upb_status_seterrf(&p->status, "error parsing number: %s", buf); - upb_env_reporterror(p->env, &p->status); - multipart_end(p); - return false; -} - -static bool parser_putbool(upb_json_parser *p, bool val) { - bool ok; - - if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) { - upb_status_seterrf(&p->status, - "Boolean value specified for non-bool field: %s", - upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); - return false; - } - - ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val); - UPB_ASSERT(ok); - - return true; -} - -static bool start_stringval(upb_json_parser *p) { - UPB_ASSERT(p->top->f); - - if (upb_fielddef_isstring(p->top->f)) { - upb_jsonparser_frame *inner; - upb_selector_t sel; - - if (!check_stack(p)) return false; - - /* Start a new parser frame: parser frames correspond one-to-one with - * handler frames, and string events occur in a sub-frame. */ - inner = p->top + 1; - sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR); - upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink); - inner->m = p->top->m; - inner->f = p->top->f; - inner->name_table = NULL; - inner->is_map = false; - inner->is_mapentry = false; - p->top = inner; - - if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) { - /* For STRING fields we push data directly to the handlers as it is - * parsed. We don't do this yet for BYTES fields, because our base64 - * decoder is not streaming. - * - * TODO(haberman): make base64 decoding streaming also. */ - multipart_start(p, getsel_for_handlertype(p, UPB_HANDLER_STRING)); - return true; - } else { - multipart_startaccum(p); - return true; - } - } else if (upb_fielddef_type(p->top->f) == UPB_TYPE_ENUM) { - /* No need to push a frame -- symbolic enum names in quotes remain in the - * current parser frame. - * - * Enum string values must accumulate so we can look up the value in a table - * once it is complete. */ - multipart_startaccum(p); - return true; - } else { - upb_status_seterrf(&p->status, - "String specified for non-string/non-enum field: %s", - upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); - return false; - } -} - -static bool end_stringval(upb_json_parser *p) { - bool ok = true; - - switch (upb_fielddef_type(p->top->f)) { - case UPB_TYPE_BYTES: - if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING), - p->accumulated, p->accumulated_len)) { - return false; - } - /* Fall through. */ - - case UPB_TYPE_STRING: { - upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR); - p->top--; - upb_sink_endstr(&p->top->sink, sel); - break; - } - - case UPB_TYPE_ENUM: { - /* Resolve enum symbolic name to integer value. */ - const upb_enumdef *enumdef = - (const upb_enumdef*)upb_fielddef_subdef(p->top->f); - - size_t len; - const char *buf = accumulate_getptr(p, &len); - - int32_t int_val = 0; - ok = upb_enumdef_ntoi(enumdef, buf, len, &int_val); - - if (ok) { - upb_selector_t sel = parser_getsel(p); - upb_sink_putint32(&p->top->sink, sel, int_val); - } else { - upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf); - upb_env_reporterror(p->env, &p->status); - } - - break; - } - - default: - UPB_ASSERT(false); - upb_status_seterrmsg(&p->status, "Internal error in JSON decoder"); - upb_env_reporterror(p->env, &p->status); - ok = false; - break; - } - - multipart_end(p); - - return ok; -} - -static void start_member(upb_json_parser *p) { - UPB_ASSERT(!p->top->f); - multipart_startaccum(p); -} - -/* Helper: invoked during parse_mapentry() to emit the mapentry message's key - * field based on the current contents of the accumulate buffer. */ -static bool parse_mapentry_key(upb_json_parser *p) { - - size_t len; - const char *buf = accumulate_getptr(p, &len); - - /* Emit the key field. We do a bit of ad-hoc parsing here because the - * parser state machine has already decided that this is a string field - * name, and we are reinterpreting it as some arbitrary key type. In - * particular, integer and bool keys are quoted, so we need to parse the - * quoted string contents here. */ - - p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY); - if (p->top->f == NULL) { - upb_status_seterrmsg(&p->status, "mapentry message has no key"); - upb_env_reporterror(p->env, &p->status); - return false; - } - switch (upb_fielddef_type(p->top->f)) { - case UPB_TYPE_INT32: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT32: - case UPB_TYPE_UINT64: - /* Invoke end_number. The accum buffer has the number's text already. */ - if (!parse_number(p)) { - return false; - } - break; - case UPB_TYPE_BOOL: - if (len == 4 && !strncmp(buf, "true", 4)) { - if (!parser_putbool(p, true)) { - return false; - } - } else if (len == 5 && !strncmp(buf, "false", 5)) { - if (!parser_putbool(p, false)) { - return false; - } - } else { - upb_status_seterrmsg(&p->status, - "Map bool key not 'true' or 'false'"); - upb_env_reporterror(p->env, &p->status); - return false; - } - multipart_end(p); - break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - upb_sink subsink; - upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR); - upb_sink_startstr(&p->top->sink, sel, len, &subsink); - sel = getsel_for_handlertype(p, UPB_HANDLER_STRING); - upb_sink_putstring(&subsink, sel, buf, len, NULL); - sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR); - upb_sink_endstr(&p->top->sink, sel); - multipart_end(p); - break; - } - default: - upb_status_seterrmsg(&p->status, "Invalid field type for map key"); - upb_env_reporterror(p->env, &p->status); - return false; - } - - return true; -} - -/* Helper: emit one map entry (as a submessage in the map field sequence). This - * is invoked from end_membername(), at the end of the map entry's key string, - * with the map key in the accumulate buffer. It parses the key from that - * buffer, emits the handler calls to start the mapentry submessage (setting up - * its subframe in the process), and sets up state in the subframe so that the - * value parser (invoked next) will emit the mapentry's value field and then - * end the mapentry message. */ - -static bool handle_mapentry(upb_json_parser *p) { - const upb_fielddef *mapfield; - const upb_msgdef *mapentrymsg; - upb_jsonparser_frame *inner; - upb_selector_t sel; - - /* Map entry: p->top->sink is the seq frame, so we need to start a frame - * for the mapentry itself, and then set |f| in that frame so that the map - * value field is parsed, and also set a flag to end the frame after the - * map-entry value is parsed. */ - if (!check_stack(p)) return false; - - mapfield = p->top->mapfield; - mapentrymsg = upb_fielddef_msgsubdef(mapfield); - - inner = p->top + 1; - p->top->f = mapfield; - sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG); - upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink); - inner->m = mapentrymsg; - inner->name_table = NULL; - inner->mapfield = mapfield; - inner->is_map = false; - - /* Don't set this to true *yet* -- we reuse parsing handlers below to push - * the key field value to the sink, and these handlers will pop the frame - * if they see is_mapentry (when invoked by the parser state machine, they - * would have just seen the map-entry value, not key). */ - inner->is_mapentry = false; - p->top = inner; - - /* send STARTMSG in submsg frame. */ - upb_sink_startmsg(&p->top->sink); - - parse_mapentry_key(p); - - /* Set up the value field to receive the map-entry value. */ - p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_VALUE); - p->top->is_mapentry = true; /* set up to pop frame after value is parsed. */ - p->top->mapfield = mapfield; - if (p->top->f == NULL) { - upb_status_seterrmsg(&p->status, "mapentry message has no value"); - upb_env_reporterror(p->env, &p->status); - return false; - } - - return true; -} - -static bool end_membername(upb_json_parser *p) { - UPB_ASSERT(!p->top->f); - - if (p->top->is_map) { - return handle_mapentry(p); - } else { - size_t len; - const char *buf = accumulate_getptr(p, &len); - upb_value v; - - if (upb_strtable_lookup2(p->top->name_table, buf, len, &v)) { - p->top->f = upb_value_getconstptr(v); - multipart_end(p); - - return true; - } else { - /* TODO(haberman): Ignore unknown fields if requested/configured to do - * so. */ - upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf); - upb_env_reporterror(p->env, &p->status); - return false; - } - } -} - -static void end_member(upb_json_parser *p) { - /* If we just parsed a map-entry value, end that frame too. */ - if (p->top->is_mapentry) { - upb_status s = UPB_STATUS_INIT; - upb_selector_t sel; - bool ok; - const upb_fielddef *mapfield; - - UPB_ASSERT(p->top > p->stack); - /* send ENDMSG on submsg. */ - upb_sink_endmsg(&p->top->sink, &s); - mapfield = p->top->mapfield; - - /* send ENDSUBMSG in repeated-field-of-mapentries frame. */ - p->top--; - ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel); - UPB_ASSERT(ok); - upb_sink_endsubmsg(&p->top->sink, sel); - } - - p->top->f = NULL; -} - -static bool start_subobject(upb_json_parser *p) { - UPB_ASSERT(p->top->f); - - if (upb_fielddef_ismap(p->top->f)) { - upb_jsonparser_frame *inner; - upb_selector_t sel; - - /* Beginning of a map. Start a new parser frame in a repeated-field - * context. */ - if (!check_stack(p)) return false; - - inner = p->top + 1; - sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ); - upb_sink_startseq(&p->top->sink, sel, &inner->sink); - inner->m = upb_fielddef_msgsubdef(p->top->f); - inner->name_table = NULL; - inner->mapfield = p->top->f; - inner->f = NULL; - inner->is_map = true; - inner->is_mapentry = false; - p->top = inner; - - return true; - } else if (upb_fielddef_issubmsg(p->top->f)) { - upb_jsonparser_frame *inner; - upb_selector_t sel; - - /* Beginning of a subobject. Start a new parser frame in the submsg - * context. */ - if (!check_stack(p)) return false; - - inner = p->top + 1; - - sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG); - upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink); - inner->m = upb_fielddef_msgsubdef(p->top->f); - set_name_table(p, inner); - inner->f = NULL; - inner->is_map = false; - inner->is_mapentry = false; - p->top = inner; - - return true; - } else { - upb_status_seterrf(&p->status, - "Object specified for non-message/group field: %s", - upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); - return false; - } -} - -static void end_subobject(upb_json_parser *p) { - if (p->top->is_map) { - upb_selector_t sel; - p->top--; - sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ); - upb_sink_endseq(&p->top->sink, sel); - } else { - upb_selector_t sel; - p->top--; - sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG); - upb_sink_endsubmsg(&p->top->sink, sel); - } -} - -static bool start_array(upb_json_parser *p) { - upb_jsonparser_frame *inner; - upb_selector_t sel; - - UPB_ASSERT(p->top->f); - - if (!upb_fielddef_isseq(p->top->f)) { - upb_status_seterrf(&p->status, - "Array specified for non-repeated field: %s", - upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); - return false; - } - - if (!check_stack(p)) return false; - - inner = p->top + 1; - sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ); - upb_sink_startseq(&p->top->sink, sel, &inner->sink); - inner->m = p->top->m; - inner->name_table = NULL; - inner->f = p->top->f; - inner->is_map = false; - inner->is_mapentry = false; - p->top = inner; - - return true; -} - -static void end_array(upb_json_parser *p) { - upb_selector_t sel; - - UPB_ASSERT(p->top > p->stack); - - p->top--; - sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ); - upb_sink_endseq(&p->top->sink, sel); -} - -static void start_object(upb_json_parser *p) { - if (!p->top->is_map) { - upb_sink_startmsg(&p->top->sink); - } -} - -static void end_object(upb_json_parser *p) { - if (!p->top->is_map) { - upb_status status; - upb_status_clear(&status); - upb_sink_endmsg(&p->top->sink, &status); - if (!upb_ok(&status)) { - upb_env_reporterror(p->env, &status); - } - } -} - - -#define CHECK_RETURN_TOP(x) if (!(x)) goto error - - -/* The actual parser **********************************************************/ - -/* What follows is the Ragel parser itself. The language is specified in Ragel - * and the actions call our C functions above. - * - * Ragel has an extensive set of functionality, and we use only a small part of - * it. There are many action types but we only use a few: - * - * ">" -- transition into a machine - * "%" -- transition out of a machine - * "@" -- transition into a final state of a machine. - * - * "@" transitions are tricky because a machine can transition into a final - * state repeatedly. But in some cases we know this can't happen, for example - * a string which is delimited by a final '"' can only transition into its - * final state once, when the closing '"' is seen. */ - - -#line 1244 "upb/json/parser.rl" - - - -#line 1156 "upb/json/parser.c" -static const char _json_actions[] = { - 0, 1, 0, 1, 2, 1, 3, 1, - 5, 1, 6, 1, 7, 1, 8, 1, - 10, 1, 12, 1, 13, 1, 14, 1, - 15, 1, 16, 1, 17, 1, 21, 1, - 25, 1, 27, 2, 3, 8, 2, 4, - 5, 2, 6, 2, 2, 6, 8, 2, - 11, 9, 2, 13, 15, 2, 14, 15, - 2, 18, 1, 2, 19, 27, 2, 20, - 9, 2, 22, 27, 2, 23, 27, 2, - 24, 27, 2, 26, 27, 3, 14, 11, - 9 -}; - -static const unsigned char _json_key_offsets[] = { - 0, 0, 4, 9, 14, 15, 19, 24, - 29, 34, 38, 42, 45, 48, 50, 54, - 58, 60, 62, 67, 69, 71, 80, 86, - 92, 98, 104, 106, 115, 116, 116, 116, - 121, 126, 131, 132, 133, 134, 135, 135, - 136, 137, 138, 138, 139, 140, 141, 141, - 146, 151, 152, 156, 161, 166, 171, 175, - 175, 178, 178, 178 -}; - -static const char _json_trans_keys[] = { - 32, 123, 9, 13, 32, 34, 125, 9, - 13, 32, 34, 125, 9, 13, 34, 32, - 58, 9, 13, 32, 93, 125, 9, 13, - 32, 44, 125, 9, 13, 32, 44, 125, - 9, 13, 32, 34, 9, 13, 45, 48, - 49, 57, 48, 49, 57, 46, 69, 101, - 48, 57, 69, 101, 48, 57, 43, 45, - 48, 57, 48, 57, 48, 57, 46, 69, - 101, 48, 57, 34, 92, 34, 92, 34, - 47, 92, 98, 102, 110, 114, 116, 117, - 48, 57, 65, 70, 97, 102, 48, 57, - 65, 70, 97, 102, 48, 57, 65, 70, - 97, 102, 48, 57, 65, 70, 97, 102, - 34, 92, 34, 45, 91, 102, 110, 116, - 123, 48, 57, 34, 32, 93, 125, 9, - 13, 32, 44, 93, 9, 13, 32, 93, - 125, 9, 13, 97, 108, 115, 101, 117, - 108, 108, 114, 117, 101, 32, 34, 125, - 9, 13, 32, 34, 125, 9, 13, 34, - 32, 58, 9, 13, 32, 93, 125, 9, - 13, 32, 44, 125, 9, 13, 32, 44, - 125, 9, 13, 32, 34, 9, 13, 32, - 9, 13, 0 -}; - -static const char _json_single_lengths[] = { - 0, 2, 3, 3, 1, 2, 3, 3, - 3, 2, 2, 1, 3, 0, 2, 2, - 0, 0, 3, 2, 2, 9, 0, 0, - 0, 0, 2, 7, 1, 0, 0, 3, - 3, 3, 1, 1, 1, 1, 0, 1, - 1, 1, 0, 1, 1, 1, 0, 3, - 3, 1, 2, 3, 3, 3, 2, 0, - 1, 0, 0, 0 -}; - -static const char _json_range_lengths[] = { - 0, 1, 1, 1, 0, 1, 1, 1, - 1, 1, 1, 1, 0, 1, 1, 1, - 1, 1, 1, 0, 0, 0, 3, 3, - 3, 3, 0, 1, 0, 0, 0, 1, - 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, - 1, 0, 1, 1, 1, 1, 1, 0, - 1, 0, 0, 0 -}; - -static const short _json_index_offsets[] = { - 0, 0, 4, 9, 14, 16, 20, 25, - 30, 35, 39, 43, 46, 50, 52, 56, - 60, 62, 64, 69, 72, 75, 85, 89, - 93, 97, 101, 104, 113, 115, 116, 117, - 122, 127, 132, 134, 136, 138, 140, 141, - 143, 145, 147, 148, 150, 152, 154, 155, - 160, 165, 167, 171, 176, 181, 186, 190, - 191, 194, 195, 196 -}; - -static const char _json_indicies[] = { - 0, 2, 0, 1, 3, 4, 5, 3, - 1, 6, 7, 8, 6, 1, 9, 1, - 10, 11, 10, 1, 11, 1, 1, 11, - 12, 13, 14, 15, 13, 1, 16, 17, - 8, 16, 1, 17, 7, 17, 1, 18, - 19, 20, 1, 19, 20, 1, 22, 23, - 23, 21, 24, 1, 23, 23, 24, 21, - 25, 25, 26, 1, 26, 1, 26, 21, - 22, 23, 23, 20, 21, 28, 29, 27, - 31, 32, 30, 33, 33, 33, 33, 33, - 33, 33, 33, 34, 1, 35, 35, 35, - 1, 36, 36, 36, 1, 37, 37, 37, - 1, 38, 38, 38, 1, 40, 41, 39, - 42, 43, 44, 45, 46, 47, 48, 43, - 1, 49, 1, 50, 51, 53, 54, 1, - 53, 52, 55, 56, 54, 55, 1, 56, - 1, 1, 56, 52, 57, 1, 58, 1, - 59, 1, 60, 1, 61, 62, 1, 63, - 1, 64, 1, 65, 66, 1, 67, 1, - 68, 1, 69, 70, 71, 72, 70, 1, - 73, 74, 75, 73, 1, 76, 1, 77, - 78, 77, 1, 78, 1, 1, 78, 79, - 80, 81, 82, 80, 1, 83, 84, 75, - 83, 1, 84, 74, 84, 1, 85, 86, - 86, 1, 1, 1, 1, 0 -}; - -static const char _json_trans_targs[] = { - 1, 0, 2, 3, 4, 56, 3, 4, - 56, 5, 5, 6, 7, 8, 9, 56, - 8, 9, 11, 12, 18, 57, 13, 15, - 14, 16, 17, 20, 58, 21, 20, 58, - 21, 19, 22, 23, 24, 25, 26, 20, - 58, 21, 28, 30, 31, 34, 39, 43, - 47, 29, 59, 59, 32, 31, 29, 32, - 33, 35, 36, 37, 38, 59, 40, 41, - 42, 59, 44, 45, 46, 59, 48, 49, - 55, 48, 49, 55, 50, 50, 51, 52, - 53, 54, 55, 53, 54, 59, 56 -}; - -static const char _json_trans_actions[] = { - 0, 0, 0, 21, 77, 53, 0, 47, - 23, 17, 0, 0, 15, 19, 19, 50, - 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 3, 13, 0, 0, 35, - 5, 11, 0, 38, 7, 7, 7, 41, - 44, 9, 62, 56, 25, 0, 0, 0, - 31, 29, 33, 59, 15, 0, 27, 0, - 0, 0, 0, 0, 0, 68, 0, 0, - 0, 71, 0, 0, 0, 65, 21, 77, - 53, 0, 47, 23, 17, 0, 0, 15, - 19, 19, 50, 0, 0, 74, 0 -}; - -static const int json_start = 1; - -static const int json_en_number_machine = 10; -static const int json_en_string_machine = 19; -static const int json_en_value_machine = 27; -static const int json_en_main = 1; - - -#line 1247 "upb/json/parser.rl" - -size_t parse(void *closure, const void *hd, const char *buf, size_t size, - const upb_bufhandle *handle) { - upb_json_parser *parser = closure; - - /* Variables used by Ragel's generated code. */ - int cs = parser->current_state; - int *stack = parser->parser_stack; - int top = parser->parser_top; - - const char *p = buf; - const char *pe = buf + size; - - parser->handle = handle; - - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - capture_resume(parser, buf); - - -#line 1327 "upb/json/parser.c" - { - int _klen; - unsigned int _trans; - const char *_acts; - unsigned int _nacts; - const char *_keys; - - if ( p == pe ) - goto _test_eof; - if ( cs == 0 ) - goto _out; -_resume: - _keys = _json_trans_keys + _json_key_offsets[cs]; - _trans = _json_index_offsets[cs]; - - _klen = _json_single_lengths[cs]; - if ( _klen > 0 ) { - const char *_lower = _keys; - const char *_mid; - const char *_upper = _keys + _klen - 1; - while (1) { - if ( _upper < _lower ) - break; - - _mid = _lower + ((_upper-_lower) >> 1); - if ( (*p) < *_mid ) - _upper = _mid - 1; - else if ( (*p) > *_mid ) - _lower = _mid + 1; - else { - _trans += (unsigned int)(_mid - _keys); - goto _match; - } - } - _keys += _klen; - _trans += _klen; - } - - _klen = _json_range_lengths[cs]; - if ( _klen > 0 ) { - const char *_lower = _keys; - const char *_mid; - const char *_upper = _keys + (_klen<<1) - 2; - while (1) { - if ( _upper < _lower ) - break; - - _mid = _lower + (((_upper-_lower) >> 1) & ~1); - if ( (*p) < _mid[0] ) - _upper = _mid - 2; - else if ( (*p) > _mid[1] ) - _lower = _mid + 2; - else { - _trans += (unsigned int)((_mid - _keys)>>1); - goto _match; - } - } - _trans += _klen; - } - -_match: - _trans = _json_indicies[_trans]; - cs = _json_trans_targs[_trans]; - - if ( _json_trans_actions[_trans] == 0 ) - goto _again; - - _acts = _json_actions + _json_trans_actions[_trans]; - _nacts = (unsigned int) *_acts++; - while ( _nacts-- > 0 ) - { - switch ( *_acts++ ) - { - case 0: -#line 1159 "upb/json/parser.rl" - { p--; {cs = stack[--top]; goto _again;} } - break; - case 1: -#line 1160 "upb/json/parser.rl" - { p--; {stack[top++] = cs; cs = 10; goto _again;} } - break; - case 2: -#line 1164 "upb/json/parser.rl" - { start_text(parser, p); } - break; - case 3: -#line 1165 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_text(parser, p)); } - break; - case 4: -#line 1171 "upb/json/parser.rl" - { start_hex(parser); } - break; - case 5: -#line 1172 "upb/json/parser.rl" - { hexdigit(parser, p); } - break; - case 6: -#line 1173 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_hex(parser)); } - break; - case 7: -#line 1179 "upb/json/parser.rl" - { CHECK_RETURN_TOP(escape(parser, p)); } - break; - case 8: -#line 1185 "upb/json/parser.rl" - { p--; {cs = stack[--top]; goto _again;} } - break; - case 9: -#line 1188 "upb/json/parser.rl" - { {stack[top++] = cs; cs = 19; goto _again;} } - break; - case 10: -#line 1190 "upb/json/parser.rl" - { p--; {stack[top++] = cs; cs = 27; goto _again;} } - break; - case 11: -#line 1195 "upb/json/parser.rl" - { start_member(parser); } - break; - case 12: -#line 1196 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_membername(parser)); } - break; - case 13: -#line 1199 "upb/json/parser.rl" - { end_member(parser); } - break; - case 14: -#line 1205 "upb/json/parser.rl" - { start_object(parser); } - break; - case 15: -#line 1208 "upb/json/parser.rl" - { end_object(parser); } - break; - case 16: -#line 1214 "upb/json/parser.rl" - { CHECK_RETURN_TOP(start_array(parser)); } - break; - case 17: -#line 1218 "upb/json/parser.rl" - { end_array(parser); } - break; - case 18: -#line 1223 "upb/json/parser.rl" - { start_number(parser, p); } - break; - case 19: -#line 1224 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_number(parser, p)); } - break; - case 20: -#line 1226 "upb/json/parser.rl" - { CHECK_RETURN_TOP(start_stringval(parser)); } - break; - case 21: -#line 1227 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_stringval(parser)); } - break; - case 22: -#line 1229 "upb/json/parser.rl" - { CHECK_RETURN_TOP(parser_putbool(parser, true)); } - break; - case 23: -#line 1231 "upb/json/parser.rl" - { CHECK_RETURN_TOP(parser_putbool(parser, false)); } - break; - case 24: -#line 1233 "upb/json/parser.rl" - { /* null value */ } - break; - case 25: -#line 1235 "upb/json/parser.rl" - { CHECK_RETURN_TOP(start_subobject(parser)); } - break; - case 26: -#line 1236 "upb/json/parser.rl" - { end_subobject(parser); } - break; - case 27: -#line 1241 "upb/json/parser.rl" - { p--; {cs = stack[--top]; goto _again;} } - break; -#line 1513 "upb/json/parser.c" - } - } - -_again: - if ( cs == 0 ) - goto _out; - if ( ++p != pe ) - goto _resume; - _test_eof: {} - _out: {} - } - -#line 1268 "upb/json/parser.rl" - - if (p != pe) { - upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p); - upb_env_reporterror(parser->env, &parser->status); - } else { - capture_suspend(parser, &p); - } - -error: - /* Save parsing state back to parser. */ - parser->current_state = cs; - parser->parser_top = top; - - return p - buf; -} - -bool end(void *closure, const void *hd) { - UPB_UNUSED(closure); - UPB_UNUSED(hd); - - /* Prevent compile warning on unused static constants. */ - UPB_UNUSED(json_start); - UPB_UNUSED(json_en_number_machine); - UPB_UNUSED(json_en_string_machine); - UPB_UNUSED(json_en_value_machine); - UPB_UNUSED(json_en_main); - return true; -} - -static void json_parser_reset(upb_json_parser *p) { - int cs; - int top; - - p->top = p->stack; - p->top->f = NULL; - p->top->is_map = false; - p->top->is_mapentry = false; - - /* Emit Ragel initialization of the parser. */ - -#line 1567 "upb/json/parser.c" - { - cs = json_start; - top = 0; - } - -#line 1308 "upb/json/parser.rl" - p->current_state = cs; - p->parser_top = top; - accumulate_clear(p); - p->multipart_state = MULTIPART_INACTIVE; - p->capture = NULL; - p->accumulated = NULL; - upb_status_clear(&p->status); -} - -static void visit_json_parsermethod(const upb_refcounted *r, - upb_refcounted_visit *visit, - void *closure) { - const upb_json_parsermethod *method = (upb_json_parsermethod*)r; - visit(r, upb_msgdef_upcast2(method->msg), closure); -} - -static void free_json_parsermethod(upb_refcounted *r) { - upb_json_parsermethod *method = (upb_json_parsermethod*)r; - - upb_inttable_iter i; - upb_inttable_begin(&i, &method->name_tables); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_value val = upb_inttable_iter_value(&i); - upb_strtable *t = upb_value_getptr(val); - upb_strtable_uninit(t); - upb_gfree(t); - } - - upb_inttable_uninit(&method->name_tables); - - upb_gfree(r); -} - -static void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* md) { - upb_msg_field_iter i; - upb_strtable *t; - - /* It would be nice to stack-allocate this, but protobufs do not limit the - * length of fields to any reasonable limit. */ - char *buf = NULL; - size_t len = 0; - - if (upb_inttable_lookupptr(&m->name_tables, md, NULL)) { - return; - } - - /* TODO(haberman): handle malloc failure. */ - t = upb_gmalloc(sizeof(*t)); - upb_strtable_init(t, UPB_CTYPE_CONSTPTR); - upb_inttable_insertptr(&m->name_tables, md, upb_value_ptr(t)); - - for(upb_msg_field_begin(&i, md); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - - /* Add an entry for the JSON name. */ - size_t field_len = upb_fielddef_getjsonname(f, buf, len); - if (field_len > len) { - size_t len2; - buf = upb_grealloc(buf, 0, field_len); - len = field_len; - len2 = upb_fielddef_getjsonname(f, buf, len); - UPB_ASSERT(len == len2); - } - upb_strtable_insert(t, buf, upb_value_constptr(f)); - - if (strcmp(buf, upb_fielddef_name(f)) != 0) { - /* Since the JSON name is different from the regular field name, add an - * entry for the raw name (compliant proto3 JSON parsers must accept - * both). */ - upb_strtable_insert(t, upb_fielddef_name(f), upb_value_constptr(f)); - } - - if (upb_fielddef_issubmsg(f)) { - add_jsonname_table(m, upb_fielddef_msgsubdef(f)); - } - } - - upb_gfree(buf); -} - -/* Public API *****************************************************************/ - -upb_json_parser *upb_json_parser_create(upb_env *env, - const upb_json_parsermethod *method, - upb_sink *output) { -#ifndef NDEBUG - const size_t size_before = upb_env_bytesallocated(env); -#endif - upb_json_parser *p = upb_env_malloc(env, sizeof(upb_json_parser)); - if (!p) return false; - - p->env = env; - p->method = method; - p->limit = p->stack + UPB_JSON_MAX_DEPTH; - p->accumulate_buf = NULL; - p->accumulate_buf_size = 0; - upb_bytessink_reset(&p->input_, &method->input_handler_, p); - - json_parser_reset(p); - upb_sink_reset(&p->top->sink, output->handlers, output->closure); - p->top->m = upb_handlers_msgdef(output->handlers); - set_name_table(p, p->top); - - /* If this fails, uncomment and increase the value in parser.h. */ - /* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */ - UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <= - UPB_JSON_PARSER_SIZE); - return p; -} - -upb_bytessink *upb_json_parser_input(upb_json_parser *p) { - return &p->input_; -} - -upb_json_parsermethod *upb_json_parsermethod_new(const upb_msgdef* md, - const void* owner) { - static const struct upb_refcounted_vtbl vtbl = {visit_json_parsermethod, - free_json_parsermethod}; - upb_json_parsermethod *ret = upb_gmalloc(sizeof(*ret)); - upb_refcounted_init(upb_json_parsermethod_upcast_mutable(ret), &vtbl, owner); - - ret->msg = md; - upb_ref2(md, ret); - - upb_byteshandler_init(&ret->input_handler_); - upb_byteshandler_setstring(&ret->input_handler_, parse, ret); - upb_byteshandler_setendstr(&ret->input_handler_, end, ret); - - upb_inttable_init(&ret->name_tables, UPB_CTYPE_PTR); - - add_jsonname_table(ret, md); - - return ret; -} - -const upb_byteshandler *upb_json_parsermethod_inputhandler( - const upb_json_parsermethod *m) { - return &m->input_handler_; -} -/* -** This currently uses snprintf() to format primitives, and could be optimized -** further. -*/ - - -#include -#include - -struct upb_json_printer { - upb_sink input_; - /* BytesSink closure. */ - void *subc_; - upb_bytessink *output_; - - /* We track the depth so that we know when to emit startstr/endstr on the - * output. */ - int depth_; - - /* Have we emitted the first element? This state is necessary to emit commas - * without leaving a trailing comma in arrays/maps. We keep this state per - * frame depth. - * - * Why max_depth * 2? UPB_MAX_HANDLER_DEPTH counts depth as nested messages. - * We count frames (contexts in which we separate elements by commas) as both - * repeated fields and messages (maps), and the worst case is a - * message->repeated field->submessage->repeated field->... nesting. */ - bool first_elem_[UPB_MAX_HANDLER_DEPTH * 2]; -}; - -/* StringPiece; a pointer plus a length. */ -typedef struct { - char *ptr; - size_t len; -} strpc; - -void freestrpc(void *ptr) { - strpc *pc = ptr; - upb_gfree(pc->ptr); - upb_gfree(pc); -} - -/* Convert fielddef name to JSON name and return as a string piece. */ -strpc *newstrpc(upb_handlers *h, const upb_fielddef *f, - bool preserve_fieldnames) { - /* TODO(haberman): handle malloc failure. */ - strpc *ret = upb_gmalloc(sizeof(*ret)); - if (preserve_fieldnames) { - ret->ptr = upb_gstrdup(upb_fielddef_name(f)); - ret->len = strlen(ret->ptr); - } else { - size_t len; - ret->len = upb_fielddef_getjsonname(f, NULL, 0); - ret->ptr = upb_gmalloc(ret->len); - len = upb_fielddef_getjsonname(f, ret->ptr, ret->len); - UPB_ASSERT(len == ret->len); - ret->len--; /* NULL */ - } - - upb_handlers_addcleanup(h, ret, freestrpc); - return ret; -} - -/* ------------ JSON string printing: values, maps, arrays ------------------ */ - -static void print_data( - upb_json_printer *p, const char *buf, unsigned int len) { - /* TODO: Will need to change if we support pushback from the sink. */ - size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL); - UPB_ASSERT(n == len); -} - -static void print_comma(upb_json_printer *p) { - if (!p->first_elem_[p->depth_]) { - print_data(p, ",", 1); - } - p->first_elem_[p->depth_] = false; -} - -/* Helpers that print properly formatted elements to the JSON output stream. */ - -/* Used for escaping control chars in strings. */ -static const char kControlCharLimit = 0x20; - -UPB_INLINE bool is_json_escaped(char c) { - /* See RFC 4627. */ - unsigned char uc = (unsigned char)c; - return uc < kControlCharLimit || uc == '"' || uc == '\\'; -} - -UPB_INLINE const char* json_nice_escape(char c) { - switch (c) { - case '"': return "\\\""; - case '\\': return "\\\\"; - case '\b': return "\\b"; - case '\f': return "\\f"; - case '\n': return "\\n"; - case '\r': return "\\r"; - case '\t': return "\\t"; - default: return NULL; - } -} - -/* Write a properly escaped string chunk. The surrounding quotes are *not* - * printed; this is so that the caller has the option of emitting the string - * content in chunks. */ -static void putstring(upb_json_printer *p, const char *buf, unsigned int len) { - const char* unescaped_run = NULL; - unsigned int i; - for (i = 0; i < len; i++) { - char c = buf[i]; - /* Handle escaping. */ - if (is_json_escaped(c)) { - /* Use a "nice" escape, like \n, if one exists for this character. */ - const char* escape = json_nice_escape(c); - /* If we don't have a specific 'nice' escape code, use a \uXXXX-style - * escape. */ - char escape_buf[8]; - if (!escape) { - unsigned char byte = (unsigned char)c; - _upb_snprintf(escape_buf, sizeof(escape_buf), "\\u%04x", (int)byte); - escape = escape_buf; - } - - /* N.B. that we assume that the input encoding is equal to the output - * encoding (both UTF-8 for now), so for chars >= 0x20 and != \, ", we - * can simply pass the bytes through. */ - - /* If there's a current run of unescaped chars, print that run first. */ - if (unescaped_run) { - print_data(p, unescaped_run, &buf[i] - unescaped_run); - unescaped_run = NULL; - } - /* Then print the escape code. */ - print_data(p, escape, strlen(escape)); - } else { - /* Add to the current unescaped run of characters. */ - if (unescaped_run == NULL) { - unescaped_run = &buf[i]; - } - } - } - - /* If the string ended in a run of unescaped characters, print that last run. */ - if (unescaped_run) { - print_data(p, unescaped_run, &buf[len] - unescaped_run); - } -} - -#define CHKLENGTH(x) if (!(x)) return -1; - -/* Helpers that format floating point values according to our custom formats. - * Right now we use %.8g and %.17g for float/double, respectively, to match - * proto2::util::JsonFormat's defaults. May want to change this later. */ - -static size_t fmt_double(double val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "%.17g", val); - CHKLENGTH(n > 0 && n < length); - return n; -} - -static size_t fmt_float(float val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "%.8g", val); - CHKLENGTH(n > 0 && n < length); - return n; -} - -static size_t fmt_bool(bool val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "%s", (val ? "true" : "false")); - CHKLENGTH(n > 0 && n < length); - return n; -} - -static size_t fmt_int64(long val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "%ld", val); - CHKLENGTH(n > 0 && n < length); - return n; -} - -static size_t fmt_uint64(unsigned long long val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "%llu", val); - CHKLENGTH(n > 0 && n < length); - return n; -} - -/* Print a map key given a field name. Called by scalar field handlers and by - * startseq for repeated fields. */ -static bool putkey(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - const strpc *key = handler_data; - print_comma(p); - print_data(p, "\"", 1); - putstring(p, key->ptr, key->len); - print_data(p, "\":", 2); - return true; -} - -#define CHKFMT(val) if ((val) == (size_t)-1) return false; -#define CHK(val) if (!(val)) return false; - -#define TYPE_HANDLERS(type, fmt_func) \ - static bool put##type(void *closure, const void *handler_data, type val) { \ - upb_json_printer *p = closure; \ - char data[64]; \ - size_t length = fmt_func(val, data, sizeof(data)); \ - UPB_UNUSED(handler_data); \ - CHKFMT(length); \ - print_data(p, data, length); \ - return true; \ - } \ - static bool scalar_##type(void *closure, const void *handler_data, \ - type val) { \ - CHK(putkey(closure, handler_data)); \ - CHK(put##type(closure, handler_data, val)); \ - return true; \ - } \ - static bool repeated_##type(void *closure, const void *handler_data, \ - type val) { \ - upb_json_printer *p = closure; \ - print_comma(p); \ - CHK(put##type(closure, handler_data, val)); \ - return true; \ - } - -#define TYPE_HANDLERS_MAPKEY(type, fmt_func) \ - static bool putmapkey_##type(void *closure, const void *handler_data, \ - type val) { \ - upb_json_printer *p = closure; \ - print_data(p, "\"", 1); \ - CHK(put##type(closure, handler_data, val)); \ - print_data(p, "\":", 2); \ - return true; \ - } - -TYPE_HANDLERS(double, fmt_double) -TYPE_HANDLERS(float, fmt_float) -TYPE_HANDLERS(bool, fmt_bool) -TYPE_HANDLERS(int32_t, fmt_int64) -TYPE_HANDLERS(uint32_t, fmt_int64) -TYPE_HANDLERS(int64_t, fmt_int64) -TYPE_HANDLERS(uint64_t, fmt_uint64) - -/* double and float are not allowed to be map keys. */ -TYPE_HANDLERS_MAPKEY(bool, fmt_bool) -TYPE_HANDLERS_MAPKEY(int32_t, fmt_int64) -TYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64) -TYPE_HANDLERS_MAPKEY(int64_t, fmt_int64) -TYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64) - -#undef TYPE_HANDLERS -#undef TYPE_HANDLERS_MAPKEY - -typedef struct { - void *keyname; - const upb_enumdef *enumdef; -} EnumHandlerData; - -static bool scalar_enum(void *closure, const void *handler_data, - int32_t val) { - const EnumHandlerData *hd = handler_data; - upb_json_printer *p = closure; - const char *symbolic_name; - - CHK(putkey(closure, hd->keyname)); - - symbolic_name = upb_enumdef_iton(hd->enumdef, val); - if (symbolic_name) { - print_data(p, "\"", 1); - putstring(p, symbolic_name, strlen(symbolic_name)); - print_data(p, "\"", 1); - } else { - putint32_t(closure, NULL, val); - } - - return true; -} - -static void print_enum_symbolic_name(upb_json_printer *p, - const upb_enumdef *def, - int32_t val) { - const char *symbolic_name = upb_enumdef_iton(def, val); - if (symbolic_name) { - print_data(p, "\"", 1); - putstring(p, symbolic_name, strlen(symbolic_name)); - print_data(p, "\"", 1); - } else { - putint32_t(p, NULL, val); - } -} - -static bool repeated_enum(void *closure, const void *handler_data, - int32_t val) { - const EnumHandlerData *hd = handler_data; - upb_json_printer *p = closure; - print_comma(p); - - print_enum_symbolic_name(p, hd->enumdef, val); - - return true; -} - -static bool mapvalue_enum(void *closure, const void *handler_data, - int32_t val) { - const EnumHandlerData *hd = handler_data; - upb_json_printer *p = closure; - - print_enum_symbolic_name(p, hd->enumdef, val); - - return true; -} - -static void *scalar_startsubmsg(void *closure, const void *handler_data) { - return putkey(closure, handler_data) ? closure : UPB_BREAK; -} - -static void *repeated_startsubmsg(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - print_comma(p); - return closure; -} - -static void start_frame(upb_json_printer *p) { - p->depth_++; - p->first_elem_[p->depth_] = true; - print_data(p, "{", 1); -} - -static void end_frame(upb_json_printer *p) { - print_data(p, "}", 1); - p->depth_--; -} - -static bool printer_startmsg(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - if (p->depth_ == 0) { - upb_bytessink_start(p->output_, 0, &p->subc_); - } - start_frame(p); - return true; -} - -static bool printer_endmsg(void *closure, const void *handler_data, upb_status *s) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - UPB_UNUSED(s); - end_frame(p); - if (p->depth_ == 0) { - upb_bytessink_end(p->output_); - } - return true; -} - -static void *startseq(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - CHK(putkey(closure, handler_data)); - p->depth_++; - p->first_elem_[p->depth_] = true; - print_data(p, "[", 1); - return closure; -} - -static bool endseq(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - print_data(p, "]", 1); - p->depth_--; - return true; -} - -static void *startmap(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - CHK(putkey(closure, handler_data)); - p->depth_++; - p->first_elem_[p->depth_] = true; - print_data(p, "{", 1); - return closure; -} - -static bool endmap(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - print_data(p, "}", 1); - p->depth_--; - return true; -} - -static size_t putstr(void *closure, const void *handler_data, const char *str, - size_t len, const upb_bufhandle *handle) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - UPB_UNUSED(handle); - putstring(p, str, len); - return len; -} - -/* This has to Base64 encode the bytes, because JSON has no "bytes" type. */ -static size_t putbytes(void *closure, const void *handler_data, const char *str, - size_t len, const upb_bufhandle *handle) { - upb_json_printer *p = closure; - - /* This is the regular base64, not the "web-safe" version. */ - static const char base64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - /* Base64-encode. */ - char data[16000]; - const char *limit = data + sizeof(data); - const unsigned char *from = (const unsigned char*)str; - char *to = data; - size_t remaining = len; - size_t bytes; - - UPB_UNUSED(handler_data); - UPB_UNUSED(handle); - - while (remaining > 2) { - /* TODO(haberman): handle encoded lengths > sizeof(data) */ - UPB_ASSERT((limit - to) >= 4); - - to[0] = base64[from[0] >> 2]; - to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)]; - to[2] = base64[((from[1] & 0xf) << 2) | (from[2] >> 6)]; - to[3] = base64[from[2] & 0x3f]; - - remaining -= 3; - to += 4; - from += 3; - } - - switch (remaining) { - case 2: - to[0] = base64[from[0] >> 2]; - to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)]; - to[2] = base64[(from[1] & 0xf) << 2]; - to[3] = '='; - to += 4; - from += 2; - break; - case 1: - to[0] = base64[from[0] >> 2]; - to[1] = base64[((from[0] & 0x3) << 4)]; - to[2] = '='; - to[3] = '='; - to += 4; - from += 1; - break; - } - - bytes = to - data; - print_data(p, "\"", 1); - putstring(p, data, bytes); - print_data(p, "\"", 1); - return len; -} - -static void *scalar_startstr(void *closure, const void *handler_data, - size_t size_hint) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - UPB_UNUSED(size_hint); - CHK(putkey(closure, handler_data)); - print_data(p, "\"", 1); - return p; -} - -static size_t scalar_str(void *closure, const void *handler_data, - const char *str, size_t len, - const upb_bufhandle *handle) { - CHK(putstr(closure, handler_data, str, len, handle)); - return len; -} - -static bool scalar_endstr(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - print_data(p, "\"", 1); - return true; -} - -static void *repeated_startstr(void *closure, const void *handler_data, - size_t size_hint) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - UPB_UNUSED(size_hint); - print_comma(p); - print_data(p, "\"", 1); - return p; -} - -static size_t repeated_str(void *closure, const void *handler_data, - const char *str, size_t len, - const upb_bufhandle *handle) { - CHK(putstr(closure, handler_data, str, len, handle)); - return len; -} - -static bool repeated_endstr(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - print_data(p, "\"", 1); - return true; -} - -static void *mapkeyval_startstr(void *closure, const void *handler_data, - size_t size_hint) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - UPB_UNUSED(size_hint); - print_data(p, "\"", 1); - return p; -} - -static size_t mapkey_str(void *closure, const void *handler_data, - const char *str, size_t len, - const upb_bufhandle *handle) { - CHK(putstr(closure, handler_data, str, len, handle)); - return len; -} - -static bool mapkey_endstr(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - print_data(p, "\":", 2); - return true; -} - -static bool mapvalue_endstr(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - print_data(p, "\"", 1); - return true; -} - -static size_t scalar_bytes(void *closure, const void *handler_data, - const char *str, size_t len, - const upb_bufhandle *handle) { - CHK(putkey(closure, handler_data)); - CHK(putbytes(closure, handler_data, str, len, handle)); - return len; -} - -static size_t repeated_bytes(void *closure, const void *handler_data, - const char *str, size_t len, - const upb_bufhandle *handle) { - upb_json_printer *p = closure; - print_comma(p); - CHK(putbytes(closure, handler_data, str, len, handle)); - return len; -} - -static size_t mapkey_bytes(void *closure, const void *handler_data, - const char *str, size_t len, - const upb_bufhandle *handle) { - upb_json_printer *p = closure; - CHK(putbytes(closure, handler_data, str, len, handle)); - print_data(p, ":", 1); - return len; -} - -static void set_enum_hd(upb_handlers *h, - const upb_fielddef *f, - bool preserve_fieldnames, - upb_handlerattr *attr) { - EnumHandlerData *hd = upb_gmalloc(sizeof(EnumHandlerData)); - hd->enumdef = (const upb_enumdef *)upb_fielddef_subdef(f); - hd->keyname = newstrpc(h, f, preserve_fieldnames); - upb_handlers_addcleanup(h, hd, upb_gfree); - upb_handlerattr_sethandlerdata(attr, hd); -} - -/* Set up handlers for a mapentry submessage (i.e., an individual key/value pair - * in a map). - * - * TODO: Handle missing key, missing value, out-of-order key/value, or repeated - * key or value cases properly. The right way to do this is to allocate a - * temporary structure at the start of a mapentry submessage, store key and - * value data in it as key and value handlers are called, and then print the - * key/value pair once at the end of the submessage. If we don't do this, we - * should at least detect the case and throw an error. However, so far all of - * our sources that emit mapentry messages do so canonically (with one key - * field, and then one value field), so this is not a pressing concern at the - * moment. */ -void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames, - upb_handlers *h) { - const upb_msgdef *md = upb_handlers_msgdef(h); - - /* A mapentry message is printed simply as '"key": value'. Rather than - * special-case key and value for every type below, we just handle both - * fields explicitly here. */ - const upb_fielddef* key_field = upb_msgdef_itof(md, UPB_MAPENTRY_KEY); - const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_MAPENTRY_VALUE); - - upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; - - UPB_UNUSED(closure); - - switch (upb_fielddef_type(key_field)) { - case UPB_TYPE_INT32: - upb_handlers_setint32(h, key_field, putmapkey_int32_t, &empty_attr); - break; - case UPB_TYPE_INT64: - upb_handlers_setint64(h, key_field, putmapkey_int64_t, &empty_attr); - break; - case UPB_TYPE_UINT32: - upb_handlers_setuint32(h, key_field, putmapkey_uint32_t, &empty_attr); - break; - case UPB_TYPE_UINT64: - upb_handlers_setuint64(h, key_field, putmapkey_uint64_t, &empty_attr); - break; - case UPB_TYPE_BOOL: - upb_handlers_setbool(h, key_field, putmapkey_bool, &empty_attr); - break; - case UPB_TYPE_STRING: - upb_handlers_setstartstr(h, key_field, mapkeyval_startstr, &empty_attr); - upb_handlers_setstring(h, key_field, mapkey_str, &empty_attr); - upb_handlers_setendstr(h, key_field, mapkey_endstr, &empty_attr); - break; - case UPB_TYPE_BYTES: - upb_handlers_setstring(h, key_field, mapkey_bytes, &empty_attr); - break; - default: - UPB_ASSERT(false); - break; - } - - switch (upb_fielddef_type(value_field)) { - case UPB_TYPE_INT32: - upb_handlers_setint32(h, value_field, putint32_t, &empty_attr); - break; - case UPB_TYPE_INT64: - upb_handlers_setint64(h, value_field, putint64_t, &empty_attr); - break; - case UPB_TYPE_UINT32: - upb_handlers_setuint32(h, value_field, putuint32_t, &empty_attr); - break; - case UPB_TYPE_UINT64: - upb_handlers_setuint64(h, value_field, putuint64_t, &empty_attr); - break; - case UPB_TYPE_BOOL: - upb_handlers_setbool(h, value_field, putbool, &empty_attr); - break; - case UPB_TYPE_FLOAT: - upb_handlers_setfloat(h, value_field, putfloat, &empty_attr); - break; - case UPB_TYPE_DOUBLE: - upb_handlers_setdouble(h, value_field, putdouble, &empty_attr); - break; - case UPB_TYPE_STRING: - upb_handlers_setstartstr(h, value_field, mapkeyval_startstr, &empty_attr); - upb_handlers_setstring(h, value_field, putstr, &empty_attr); - upb_handlers_setendstr(h, value_field, mapvalue_endstr, &empty_attr); - break; - case UPB_TYPE_BYTES: - upb_handlers_setstring(h, value_field, putbytes, &empty_attr); - break; - case UPB_TYPE_ENUM: { - upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER; - set_enum_hd(h, value_field, preserve_fieldnames, &enum_attr); - upb_handlers_setint32(h, value_field, mapvalue_enum, &enum_attr); - upb_handlerattr_uninit(&enum_attr); - break; - } - case UPB_TYPE_MESSAGE: - /* No handler necessary -- the submsg handlers will print the message - * as appropriate. */ - break; - } - - upb_handlerattr_uninit(&empty_attr); -} - -void printer_sethandlers(const void *closure, upb_handlers *h) { - const upb_msgdef *md = upb_handlers_msgdef(h); - bool is_mapentry = upb_msgdef_mapentry(md); - upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; - upb_msg_field_iter i; - const bool *preserve_fieldnames_ptr = closure; - const bool preserve_fieldnames = *preserve_fieldnames_ptr; - - if (is_mapentry) { - /* mapentry messages are sufficiently different that we handle them - * separately. */ - printer_sethandlers_mapentry(closure, preserve_fieldnames, h); - return; - } - - upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr); - upb_handlers_setendmsg(h, printer_endmsg, &empty_attr); - -#define TYPE(type, name, ctype) \ - case type: \ - if (upb_fielddef_isseq(f)) { \ - upb_handlers_set##name(h, f, repeated_##ctype, &empty_attr); \ - } else { \ - upb_handlers_set##name(h, f, scalar_##ctype, &name_attr); \ - } \ - break; - - upb_msg_field_begin(&i, md); - for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - - upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&name_attr, - newstrpc(h, f, preserve_fieldnames)); - - if (upb_fielddef_ismap(f)) { - upb_handlers_setstartseq(h, f, startmap, &name_attr); - upb_handlers_setendseq(h, f, endmap, &name_attr); - } else if (upb_fielddef_isseq(f)) { - upb_handlers_setstartseq(h, f, startseq, &name_attr); - upb_handlers_setendseq(h, f, endseq, &empty_attr); - } - - switch (upb_fielddef_type(f)) { - TYPE(UPB_TYPE_FLOAT, float, float); - TYPE(UPB_TYPE_DOUBLE, double, double); - TYPE(UPB_TYPE_BOOL, bool, bool); - TYPE(UPB_TYPE_INT32, int32, int32_t); - TYPE(UPB_TYPE_UINT32, uint32, uint32_t); - TYPE(UPB_TYPE_INT64, int64, int64_t); - TYPE(UPB_TYPE_UINT64, uint64, uint64_t); - case UPB_TYPE_ENUM: { - /* For now, we always emit symbolic names for enums. We may want an - * option later to control this behavior, but we will wait for a real - * need first. */ - upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER; - set_enum_hd(h, f, preserve_fieldnames, &enum_attr); - - if (upb_fielddef_isseq(f)) { - upb_handlers_setint32(h, f, repeated_enum, &enum_attr); - } else { - upb_handlers_setint32(h, f, scalar_enum, &enum_attr); - } - - upb_handlerattr_uninit(&enum_attr); - break; - } - case UPB_TYPE_STRING: - if (upb_fielddef_isseq(f)) { - upb_handlers_setstartstr(h, f, repeated_startstr, &empty_attr); - upb_handlers_setstring(h, f, repeated_str, &empty_attr); - upb_handlers_setendstr(h, f, repeated_endstr, &empty_attr); - } else { - upb_handlers_setstartstr(h, f, scalar_startstr, &name_attr); - upb_handlers_setstring(h, f, scalar_str, &empty_attr); - upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr); - } - break; - case UPB_TYPE_BYTES: - /* XXX: this doesn't support strings that span buffers yet. The base64 - * encoder will need to be made resumable for this to work properly. */ - if (upb_fielddef_isseq(f)) { - upb_handlers_setstring(h, f, repeated_bytes, &empty_attr); - } else { - upb_handlers_setstring(h, f, scalar_bytes, &name_attr); - } - break; - case UPB_TYPE_MESSAGE: - if (upb_fielddef_isseq(f)) { - upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &name_attr); - } else { - upb_handlers_setstartsubmsg(h, f, scalar_startsubmsg, &name_attr); - } - break; - } - - upb_handlerattr_uninit(&name_attr); - } - - upb_handlerattr_uninit(&empty_attr); -#undef TYPE -} - -static void json_printer_reset(upb_json_printer *p) { - p->depth_ = 0; -} - - -/* Public API *****************************************************************/ - -upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h, - upb_bytessink *output) { -#ifndef NDEBUG - size_t size_before = upb_env_bytesallocated(e); -#endif - - upb_json_printer *p = upb_env_malloc(e, sizeof(upb_json_printer)); - if (!p) return NULL; - - p->output_ = output; - json_printer_reset(p); - upb_sink_reset(&p->input_, h, p); - - /* If this fails, increase the value in printer.h. */ - UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(e) - size_before <= - UPB_JSON_PRINTER_SIZE); - return p; -} - -upb_sink *upb_json_printer_input(upb_json_printer *p) { - return &p->input_; -} - -const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md, - bool preserve_fieldnames, - const void *owner) { - return upb_handlers_newfrozen( - md, owner, printer_sethandlers, &preserve_fieldnames); -} diff --git a/php/ext/google/protobuf/upb.h b/php/ext/google/protobuf/upb.h deleted file mode 100644 index 4b51275dbbf63..0000000000000 --- a/php/ext/google/protobuf/upb.h +++ /dev/null @@ -1,8878 +0,0 @@ -// Amalgamated source file -/* -** Defs are upb's internal representation of the constructs that can appear -** in a .proto file: -** -** - upb::MessageDef (upb_msgdef): describes a "message" construct. -** - upb::FieldDef (upb_fielddef): describes a message field. -** - upb::FileDef (upb_filedef): describes a .proto file and its defs. -** - upb::EnumDef (upb_enumdef): describes an enum. -** - upb::OneofDef (upb_oneofdef): describes a oneof. -** - upb::Def (upb_def): base class of all the others. -** -** TODO: definitions of services. -** -** Like upb_refcounted objects, defs are mutable only until frozen, and are -** only thread-safe once frozen. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. -*/ - -#ifndef UPB_DEF_H_ -#define UPB_DEF_H_ - -/* -** upb::RefCounted (upb_refcounted) -** -** A refcounting scheme that supports circular refs. It accomplishes this by -** partitioning the set of objects into groups such that no cycle spans groups; -** we can then reference-count the group as a whole and ignore refs within the -** group. When objects are mutable, these groups are computed very -** conservatively; we group any objects that have ever had a link between them. -** When objects are frozen, we compute strongly-connected components which -** allows us to be precise and only group objects that are actually cyclic. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. -*/ - -#ifndef UPB_REFCOUNTED_H_ -#define UPB_REFCOUNTED_H_ - -/* -** upb_table -** -** This header is INTERNAL-ONLY! Its interfaces are not public or stable! -** This file defines very fast int->upb_value (inttable) and string->upb_value -** (strtable) hash tables. -** -** The table uses chained scatter with Brent's variation (inspired by the Lua -** implementation of hash tables). The hash function for strings is Austin -** Appleby's "MurmurHash." -** -** The inttable uses uintptr_t as its key, which guarantees it can be used to -** store pointers or integers of at least 32 bits (upb isn't really useful on -** systems where sizeof(void*) < 4). -** -** The table must be homogenous (all values of the same type). In debug -** mode, we check this on insert and lookup. -*/ - -#ifndef UPB_TABLE_H_ -#define UPB_TABLE_H_ - -// php.h intentionally defined NDEBUG. We have to define this macro in order to -// be used together with php.h -#ifndef NDEBUG -#define NDEBUG -#endif - -#include -#include -/* -** This file contains shared definitions that are widely used across upb. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. -*/ - -#ifndef UPB_H_ -#define UPB_H_ - -#include -#include -#include -#include - -#ifdef __cplusplus -namespace upb { -class Allocator; -class Arena; -class Environment; -class ErrorSpace; -class Status; -template class InlinedArena; -template class InlinedEnvironment; -} -#endif - -/* UPB_INLINE: inline if possible, emit standalone code if required. */ -#ifdef __cplusplus -#define UPB_INLINE inline -#elif defined (__GNUC__) -#define UPB_INLINE static __inline__ -#else -#define UPB_INLINE static -#endif - -/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler - * doesn't provide these preprocessor symbols. */ -#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) -#define UPB_BIG_ENDIAN -#endif - -/* Macros for function attributes on compilers that support them. */ -#ifdef __GNUC__ -#define UPB_FORCEINLINE __inline__ __attribute__((always_inline)) -#define UPB_NOINLINE __attribute__((noinline)) -#define UPB_NORETURN __attribute__((__noreturn__)) -#else /* !defined(__GNUC__) */ -#define UPB_FORCEINLINE -#define UPB_NOINLINE -#define UPB_NORETURN -#endif - -#if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L -/* C99/C++11 versions. */ -#include -#define _upb_snprintf snprintf -#define _upb_vsnprintf vsnprintf -#define _upb_va_copy(a, b) va_copy(a, b) -#elif defined __GNUC__ -/* A few hacky workarounds for functions not in C89. - * For internal use only! - * TODO(haberman): fix these by including our own implementations, or finding - * another workaround. - */ -#define _upb_snprintf __builtin_snprintf -#define _upb_vsnprintf __builtin_vsnprintf -#define _upb_va_copy(a, b) __va_copy(a, b) -#else -#error Need implementations of [v]snprintf and va_copy -#endif - - -#if ((defined(__cplusplus) && __cplusplus >= 201103L) || \ - defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(UPB_NO_CXX11) -#define UPB_CXX11 -#endif - -/* UPB_DISALLOW_COPY_AND_ASSIGN() - * UPB_DISALLOW_POD_OPS() - * - * Declare these in the "private" section of a C++ class to forbid copy/assign - * or all POD ops (construct, destruct, copy, assign) on that class. */ -#ifdef UPB_CXX11 -#include -#define UPB_DISALLOW_COPY_AND_ASSIGN(class_name) \ - class_name(const class_name&) = delete; \ - void operator=(const class_name&) = delete; -#define UPB_DISALLOW_POD_OPS(class_name, full_class_name) \ - class_name() = delete; \ - ~class_name() = delete; \ - UPB_DISALLOW_COPY_AND_ASSIGN(class_name) -#define UPB_ASSERT_STDLAYOUT(type) \ - static_assert(std::is_standard_layout::value, \ - #type " must be standard layout"); -#define UPB_FINAL final -#else /* !defined(UPB_CXX11) */ -#define UPB_DISALLOW_COPY_AND_ASSIGN(class_name) \ - class_name(const class_name&); \ - void operator=(const class_name&); -#define UPB_DISALLOW_POD_OPS(class_name, full_class_name) \ - class_name(); \ - ~class_name(); \ - UPB_DISALLOW_COPY_AND_ASSIGN(class_name) -#define UPB_ASSERT_STDLAYOUT(type) -#define UPB_FINAL -#endif - -/* UPB_DECLARE_TYPE() - * UPB_DECLARE_DERIVED_TYPE() - * UPB_DECLARE_DERIVED_TYPE2() - * - * Macros for declaring C and C++ types both, including inheritance. - * The inheritance doesn't use real C++ inheritance, to stay compatible with C. - * - * These macros also provide upcasts: - * - in C: types-specific functions (ie. upb_foo_upcast(foo)) - * - in C++: upb::upcast(foo) along with implicit conversions - * - * Downcasts are not provided, but upb/def.h defines downcasts for upb::Def. */ - -#define UPB_C_UPCASTS(ty, base) \ - UPB_INLINE base *ty ## _upcast_mutable(ty *p) { return (base*)p; } \ - UPB_INLINE const base *ty ## _upcast(const ty *p) { return (const base*)p; } - -#define UPB_C_UPCASTS2(ty, base, base2) \ - UPB_C_UPCASTS(ty, base) \ - UPB_INLINE base2 *ty ## _upcast2_mutable(ty *p) { return (base2*)p; } \ - UPB_INLINE const base2 *ty ## _upcast2(const ty *p) { return (const base2*)p; } - -#ifdef __cplusplus - -#define UPB_BEGIN_EXTERN_C extern "C" { -#define UPB_END_EXTERN_C } -#define UPB_PRIVATE_FOR_CPP private: -#define UPB_DECLARE_TYPE(cppname, cname) typedef cppname cname; - -#define UPB_DECLARE_DERIVED_TYPE(cppname, cppbase, cname, cbase) \ - UPB_DECLARE_TYPE(cppname, cname) \ - UPB_C_UPCASTS(cname, cbase) \ - namespace upb { \ - template <> \ - class Pointer : public PointerBase { \ - public: \ - explicit Pointer(cppname* ptr) \ - : PointerBase(ptr) {} \ - }; \ - template <> \ - class Pointer \ - : public PointerBase { \ - public: \ - explicit Pointer(const cppname* ptr) \ - : PointerBase(ptr) {} \ - }; \ - } - -#define UPB_DECLARE_DERIVED_TYPE2(cppname, cppbase, cppbase2, cname, cbase, \ - cbase2) \ - UPB_DECLARE_TYPE(cppname, cname) \ - UPB_C_UPCASTS2(cname, cbase, cbase2) \ - namespace upb { \ - template <> \ - class Pointer : public PointerBase2 { \ - public: \ - explicit Pointer(cppname* ptr) \ - : PointerBase2(ptr) {} \ - }; \ - template <> \ - class Pointer \ - : public PointerBase2 { \ - public: \ - explicit Pointer(const cppname* ptr) \ - : PointerBase2(ptr) {} \ - }; \ - } - -#else /* !defined(__cplusplus) */ - -#define UPB_BEGIN_EXTERN_C -#define UPB_END_EXTERN_C -#define UPB_PRIVATE_FOR_CPP -#define UPB_DECLARE_TYPE(cppname, cname) \ - struct cname; \ - typedef struct cname cname; -#define UPB_DECLARE_DERIVED_TYPE(cppname, cppbase, cname, cbase) \ - UPB_DECLARE_TYPE(cppname, cname) \ - UPB_C_UPCASTS(cname, cbase) -#define UPB_DECLARE_DERIVED_TYPE2(cppname, cppbase, cppbase2, \ - cname, cbase, cbase2) \ - UPB_DECLARE_TYPE(cppname, cname) \ - UPB_C_UPCASTS2(cname, cbase, cbase2) - -#endif /* defined(__cplusplus) */ - -#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) -#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y)) - -#define UPB_UNUSED(var) (void)var - -/* UPB_ASSERT(): in release mode, we use the expression without letting it be - * evaluated. This prevents "unused variable" warnings. */ -#ifdef NDEBUG -#define UPB_ASSERT(expr) do {} while (false && (expr)) -#else -#define UPB_ASSERT(expr) assert(expr) -#endif - -/* UPB_ASSERT_DEBUGVAR(): assert that uses functions or variables that only - * exist in debug mode. This turns into regular assert. */ -#define UPB_ASSERT_DEBUGVAR(expr) assert(expr) - -#ifdef __GNUC__ -#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0) -#else -#define UPB_UNREACHABLE() do { assert(0); } while(0) -#endif - -/* Generic function type. */ -typedef void upb_func(); - - -/* C++ Casts ******************************************************************/ - -#ifdef __cplusplus - -namespace upb { - -template class Pointer; - -/* Casts to a subclass. The caller must know that cast is correct; an - * incorrect cast will throw an assertion failure in debug mode. - * - * Example: - * upb::Def* def = GetDef(); - * // Assert-fails if this was not actually a MessageDef. - * upb::MessgeDef* md = upb::down_cast(def); - * - * Note that downcasts are only defined for some types (at the moment you can - * only downcast from a upb::Def to a specific Def type). */ -template To down_cast(From* f); - -/* Casts to a subclass. If the class does not actually match the given To type, - * returns NULL. - * - * Example: - * upb::Def* def = GetDef(); - * // md will be NULL if this was not actually a MessageDef. - * upb::MessgeDef* md = upb::down_cast(def); - * - * Note that dynamic casts are only defined for some types (at the moment you - * can only downcast from a upb::Def to a specific Def type).. */ -template To dyn_cast(From* f); - -/* Casts to any base class, or the type itself (ie. can be a no-op). - * - * Example: - * upb::MessageDef* md = GetDef(); - * // This will fail to compile if this wasn't actually a base class. - * upb::Def* def = upb::upcast(md); - */ -template inline Pointer upcast(T *f) { return Pointer(f); } - -/* Attempt upcast to specific base class. - * - * Example: - * upb::MessageDef* md = GetDef(); - * upb::upcast_to(md)->MethodOnDef(); - */ -template inline T* upcast_to(F *f) { - return static_cast(upcast(f)); -} - -/* PointerBase: implementation detail of upb::upcast(). - * It is implicitly convertable to pointers to the Base class(es). - */ -template -class PointerBase { - public: - explicit PointerBase(T* ptr) : ptr_(ptr) {} - operator T*() { return ptr_; } - operator Base*() { return (Base*)ptr_; } - - private: - T* ptr_; -}; - -template -class PointerBase2 : public PointerBase { - public: - explicit PointerBase2(T* ptr) : PointerBase(ptr) {} - operator Base2*() { return Pointer(*this); } -}; - -} - -#endif - - -/* upb::ErrorSpace ************************************************************/ - -/* A upb::ErrorSpace represents some domain of possible error values. This lets - * upb::Status attach specific error codes to operations, like POSIX/C errno, - * Win32 error codes, etc. Clients who want to know the very specific error - * code can check the error space and then know the type of the integer code. - * - * NOTE: upb::ErrorSpace is currently not used and should be considered - * experimental. It is important primarily in cases where upb is performing - * I/O, but upb doesn't currently have any components that do this. */ - -UPB_DECLARE_TYPE(upb::ErrorSpace, upb_errorspace) - -#ifdef __cplusplus -class upb::ErrorSpace { -#else -struct upb_errorspace { -#endif - const char *name; -}; - - -/* upb::Status ****************************************************************/ - -/* upb::Status represents a success or failure status and error message. - * It owns no resources and allocates no memory, so it should work - * even in OOM situations. */ -UPB_DECLARE_TYPE(upb::Status, upb_status) - -/* The maximum length of an error message before it will get truncated. */ -#define UPB_STATUS_MAX_MESSAGE 128 - -UPB_BEGIN_EXTERN_C - -const char *upb_status_errmsg(const upb_status *status); -bool upb_ok(const upb_status *status); -upb_errorspace *upb_status_errspace(const upb_status *status); -int upb_status_errcode(const upb_status *status); - -/* Any of the functions that write to a status object allow status to be NULL, - * to support use cases where the function's caller does not care about the - * status message. */ -void upb_status_clear(upb_status *status); -void upb_status_seterrmsg(upb_status *status, const char *msg); -void upb_status_seterrf(upb_status *status, const char *fmt, ...); -void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args); -void upb_status_copy(upb_status *to, const upb_status *from); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -class upb::Status { - public: - Status() { upb_status_clear(this); } - - /* Returns true if there is no error. */ - bool ok() const { return upb_ok(this); } - - /* Optional error space and code, useful if the caller wants to - * programmatically check the specific kind of error. */ - ErrorSpace* error_space() { return upb_status_errspace(this); } - int error_code() const { return upb_status_errcode(this); } - - /* The returned string is invalidated by any other call into the status. */ - const char *error_message() const { return upb_status_errmsg(this); } - - /* The error message will be truncated if it is longer than - * UPB_STATUS_MAX_MESSAGE-4. */ - void SetErrorMessage(const char* msg) { upb_status_seterrmsg(this, msg); } - void SetFormattedErrorMessage(const char* fmt, ...) { - va_list args; - va_start(args, fmt); - upb_status_vseterrf(this, fmt, args); - va_end(args); - } - - /* Resets the status to a successful state with no message. */ - void Clear() { upb_status_clear(this); } - - void CopyFrom(const Status& other) { upb_status_copy(this, &other); } - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(Status) -#else -struct upb_status { -#endif - bool ok_; - - /* Specific status code defined by some error space (optional). */ - int code_; - upb_errorspace *error_space_; - - /* TODO(haberman): add file/line of error? */ - - /* Error message; NULL-terminated. */ - char msg[UPB_STATUS_MAX_MESSAGE]; -}; - -#define UPB_STATUS_INIT {true, 0, NULL, {0}} - - -/** Built-in error spaces. ****************************************************/ - -/* Errors raised by upb that we want to be able to detect programmatically. */ -typedef enum { - UPB_NOMEM /* Can't reuse ENOMEM because it is POSIX, not ISO C. */ -} upb_errcode_t; - -extern upb_errorspace upb_upberr; - -void upb_upberr_setoom(upb_status *s); - -/* Since errno is defined by standard C, we define an error space for it in - * core upb. Other error spaces should be defined in other, platform-specific - * modules. */ - -extern upb_errorspace upb_errnoerr; - - -/** upb::Allocator ************************************************************/ - -/* A upb::Allocator is a possibly-stateful allocator object. - * - * It could either be an arena allocator (which doesn't require individual - * free() calls) or a regular malloc() (which does). The client must therefore - * free memory unless it knows that the allocator is an arena allocator. */ -UPB_DECLARE_TYPE(upb::Allocator, upb_alloc) - -/* A malloc()/free() function. - * If "size" is 0 then the function acts like free(), otherwise it acts like - * realloc(). Only "oldsize" bytes from a previous allocation are preserved. */ -typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize, - size_t size); - -#ifdef __cplusplus - -class upb::Allocator UPB_FINAL { - public: - Allocator() {} - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(Allocator) - - public: -#else -struct upb_alloc { -#endif /* __cplusplus */ - upb_alloc_func *func; -}; - -UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) { - UPB_ASSERT(alloc); - return alloc->func(alloc, NULL, 0, size); -} - -UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize, - size_t size) { - UPB_ASSERT(alloc); - return alloc->func(alloc, ptr, oldsize, size); -} - -UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) { - assert(alloc); - alloc->func(alloc, ptr, 0, 0); -} - -/* The global allocator used by upb. Uses the standard malloc()/free(). */ - -extern upb_alloc upb_alloc_global; - -/* Functions that hard-code the global malloc. - * - * We still get benefit because we can put custom logic into our global - * allocator, like injecting out-of-memory faults in debug/testing builds. */ - -UPB_INLINE void *upb_gmalloc(size_t size) { - return upb_malloc(&upb_alloc_global, size); -} - -UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) { - return upb_realloc(&upb_alloc_global, ptr, oldsize, size); -} - -UPB_INLINE void upb_gfree(void *ptr) { - upb_free(&upb_alloc_global, ptr); -} - -/* upb::Arena *****************************************************************/ - -/* upb::Arena is a specific allocator implementation that uses arena allocation. - * The user provides an allocator that will be used to allocate the underlying - * arena blocks. Arenas by nature do not require the individual allocations - * to be freed. However the Arena does allow users to register cleanup - * functions that will run when the arena is destroyed. - * - * A upb::Arena is *not* thread-safe. - * - * You could write a thread-safe arena allocator that satisfies the - * upb::Allocator interface, but it would not be as efficient for the - * single-threaded case. */ -UPB_DECLARE_TYPE(upb::Arena, upb_arena) - -typedef void upb_cleanup_func(void *ud); - -#define UPB_ARENA_BLOCK_OVERHEAD (sizeof(size_t)*4) - -UPB_BEGIN_EXTERN_C - -void upb_arena_init(upb_arena *a); -void upb_arena_init2(upb_arena *a, void *mem, size_t n, upb_alloc *alloc); -void upb_arena_uninit(upb_arena *a); -bool upb_arena_addcleanup(upb_arena *a, upb_cleanup_func *func, void *ud); -size_t upb_arena_bytesallocated(const upb_arena *a); -void upb_arena_setnextblocksize(upb_arena *a, size_t size); -void upb_arena_setmaxblocksize(upb_arena *a, size_t size); -UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; } - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -class upb::Arena { - public: - /* A simple arena with no initial memory block and the default allocator. */ - Arena() { upb_arena_init(this); } - - /* Constructs an arena with the given initial block which allocates blocks - * with the given allocator. The given allocator must outlive the Arena. - * - * If you pass NULL for the allocator it will default to the global allocator - * upb_alloc_global, and NULL/0 for the initial block will cause there to be - * no initial block. */ - Arena(void *mem, size_t len, Allocator* a) { - upb_arena_init2(this, mem, len, a); - } - - ~Arena() { upb_arena_uninit(this); } - - /* Sets the size of the next block the Arena will request (unless the - * requested allocation is larger). Each block will double in size until the - * max limit is reached. */ - void SetNextBlockSize(size_t size) { upb_arena_setnextblocksize(this, size); } - - /* Sets the maximum block size. No blocks larger than this will be requested - * from the underlying allocator unless individual arena allocations are - * larger. */ - void SetMaxBlockSize(size_t size) { upb_arena_setmaxblocksize(this, size); } - - /* Allows this arena to be used as a generic allocator. - * - * The arena does not need free() calls so when using Arena as an allocator - * it is safe to skip them. However they are no-ops so there is no harm in - * calling free() either. */ - Allocator* allocator() { return upb_arena_alloc(this); } - - /* Add a cleanup function to run when the arena is destroyed. - * Returns false on out-of-memory. */ - bool AddCleanup(upb_cleanup_func* func, void* ud) { - return upb_arena_addcleanup(this, func, ud); - } - - /* Total number of bytes that have been allocated. It is undefined what - * Realloc() does to this counter. */ - size_t BytesAllocated() const { - return upb_arena_bytesallocated(this); - } - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(Arena) - -#else -struct upb_arena { -#endif /* __cplusplus */ - /* We implement the allocator interface. - * This must be the first member of upb_arena! */ - upb_alloc alloc; - - /* Allocator to allocate arena blocks. We are responsible for freeing these - * when we are destroyed. */ - upb_alloc *block_alloc; - - size_t bytes_allocated; - size_t next_block_size; - size_t max_block_size; - - /* Linked list of blocks. Points to an arena_block, defined in env.c */ - void *block_head; - - /* Cleanup entries. Pointer to a cleanup_ent, defined in env.c */ - void *cleanup_head; - - /* For future expansion, since the size of this struct is exposed to users. */ - void *future1; - void *future2; -}; - - -/* upb::Environment ***********************************************************/ - -/* A upb::Environment provides a means for injecting malloc and an - * error-reporting callback into encoders/decoders. This allows them to be - * independent of nearly all assumptions about their actual environment. - * - * It is also a container for allocating the encoders/decoders themselves that - * insulates clients from knowing their actual size. This provides ABI - * compatibility even if the size of the objects change. And this allows the - * structure definitions to be in the .c files instead of the .h files, making - * the .h files smaller and more readable. - * - * We might want to consider renaming this to "Pipeline" if/when the concept of - * a pipeline element becomes more formalized. */ -UPB_DECLARE_TYPE(upb::Environment, upb_env) - -/* A function that receives an error report from an encoder or decoder. The - * callback can return true to request that the error should be recovered, but - * if the error is not recoverable this has no effect. */ -typedef bool upb_error_func(void *ud, const upb_status *status); - -UPB_BEGIN_EXTERN_C - -void upb_env_init(upb_env *e); -void upb_env_init2(upb_env *e, void *mem, size_t n, upb_alloc *alloc); -void upb_env_uninit(upb_env *e); - -void upb_env_initonly(upb_env *e); - -upb_arena *upb_env_arena(upb_env *e); -bool upb_env_ok(const upb_env *e); -void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud); - -/* Convenience wrappers around the methods of the contained arena. */ -void upb_env_reporterrorsto(upb_env *e, upb_status *s); -bool upb_env_reporterror(upb_env *e, const upb_status *s); -void *upb_env_malloc(upb_env *e, size_t size); -void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size); -void upb_env_free(upb_env *e, void *ptr); -bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud); -size_t upb_env_bytesallocated(const upb_env *e); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -class upb::Environment { - public: - /* The given Arena must outlive this environment. */ - Environment() { upb_env_initonly(this); } - - Environment(void *mem, size_t len, Allocator *a) : arena_(mem, len, a) { - upb_env_initonly(this); - } - - Arena* arena() { return upb_env_arena(this); } - - /* Set a custom error reporting function. */ - void SetErrorFunction(upb_error_func* func, void* ud) { - upb_env_seterrorfunc(this, func, ud); - } - - /* Set the error reporting function to simply copy the status to the given - * status and abort. */ - void ReportErrorsTo(Status* status) { upb_env_reporterrorsto(this, status); } - - /* Returns true if all allocations and AddCleanup() calls have succeeded, - * and no errors were reported with ReportError() (except ones that recovered - * successfully). */ - bool ok() const { return upb_env_ok(this); } - - /* Reports an error to this environment's callback, returning true if - * the caller should try to recover. */ - bool ReportError(const Status* status) { - return upb_env_reporterror(this, status); - } - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(Environment) - -#else -struct upb_env { -#endif /* __cplusplus */ - upb_arena arena_; - upb_error_func *error_func_; - void *error_ud_; - bool ok_; -}; - - -/* upb::InlinedArena **********************************************************/ -/* upb::InlinedEnvironment ****************************************************/ - -/* upb::InlinedArena and upb::InlinedEnvironment seed their arenas with a - * predefined amount of memory. No heap memory will be allocated until the - * initial block is exceeded. - * - * These types only exist in C++ */ - -#ifdef __cplusplus - -template class upb::InlinedArena : public upb::Arena { - public: - InlinedArena() : Arena(initial_block_, N, NULL) {} - explicit InlinedArena(Allocator* a) : Arena(initial_block_, N, a) {} - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(InlinedArena) - - char initial_block_[N + UPB_ARENA_BLOCK_OVERHEAD]; -}; - -template class upb::InlinedEnvironment : public upb::Environment { - public: - InlinedEnvironment() : Environment(initial_block_, N, NULL) {} - explicit InlinedEnvironment(Allocator *a) - : Environment(initial_block_, N, a) {} - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(InlinedEnvironment) - - char initial_block_[N + UPB_ARENA_BLOCK_OVERHEAD]; -}; - -#endif /* __cplusplus */ - - - -#endif /* UPB_H_ */ - -#ifdef __cplusplus -extern "C" { -#endif - - -/* upb_value ******************************************************************/ - -/* A tagged union (stored untagged inside the table) so that we can check that - * clients calling table accessors are correctly typed without having to have - * an explosion of accessors. */ -typedef enum { - UPB_CTYPE_INT32 = 1, - UPB_CTYPE_INT64 = 2, - UPB_CTYPE_UINT32 = 3, - UPB_CTYPE_UINT64 = 4, - UPB_CTYPE_BOOL = 5, - UPB_CTYPE_CSTR = 6, - UPB_CTYPE_PTR = 7, - UPB_CTYPE_CONSTPTR = 8, - UPB_CTYPE_FPTR = 9, - UPB_CTYPE_FLOAT = 10, - UPB_CTYPE_DOUBLE = 11 -} upb_ctype_t; - -typedef struct { - uint64_t val; -#ifndef NDEBUG - /* In debug mode we carry the value type around also so we can check accesses - * to be sure the right member is being read. */ - upb_ctype_t ctype; -#endif -} upb_value; - -#ifdef NDEBUG -#define SET_TYPE(dest, val) UPB_UNUSED(val) -#else -#define SET_TYPE(dest, val) dest = val -#endif - -/* Like strdup(), which isn't always available since it's not ANSI C. */ -char *upb_strdup(const char *s, upb_alloc *a); -/* Variant that works with a length-delimited rather than NULL-delimited string, - * as supported by strtable. */ -char *upb_strdup2(const char *s, size_t len, upb_alloc *a); - -UPB_INLINE char *upb_gstrdup(const char *s) { - return upb_strdup(s, &upb_alloc_global); -} - -UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val, - upb_ctype_t ctype) { - v->val = val; - SET_TYPE(v->ctype, ctype); -} - -UPB_INLINE upb_value _upb_value_val(uint64_t val, upb_ctype_t ctype) { - upb_value ret; - _upb_value_setval(&ret, val, ctype); - return ret; -} - -/* For each value ctype, define the following set of functions: - * - * // Get/set an int32 from a upb_value. - * int32_t upb_value_getint32(upb_value val); - * void upb_value_setint32(upb_value *val, int32_t cval); - * - * // Construct a new upb_value from an int32. - * upb_value upb_value_int32(int32_t val); */ -#define FUNCS(name, membername, type_t, converter, proto_type) \ - UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \ - val->val = (converter)cval; \ - SET_TYPE(val->ctype, proto_type); \ - } \ - UPB_INLINE upb_value upb_value_ ## name(type_t val) { \ - upb_value ret; \ - upb_value_set ## name(&ret, val); \ - return ret; \ - } \ - UPB_INLINE type_t upb_value_get ## name(upb_value val) { \ - UPB_ASSERT_DEBUGVAR(val.ctype == proto_type); \ - return (type_t)(converter)val.val; \ - } - -FUNCS(int32, int32, int32_t, int32_t, UPB_CTYPE_INT32) -FUNCS(int64, int64, int64_t, int64_t, UPB_CTYPE_INT64) -FUNCS(uint32, uint32, uint32_t, uint32_t, UPB_CTYPE_UINT32) -FUNCS(uint64, uint64, uint64_t, uint64_t, UPB_CTYPE_UINT64) -FUNCS(bool, _bool, bool, bool, UPB_CTYPE_BOOL) -FUNCS(cstr, cstr, char*, uintptr_t, UPB_CTYPE_CSTR) -FUNCS(ptr, ptr, void*, uintptr_t, UPB_CTYPE_PTR) -FUNCS(constptr, constptr, const void*, uintptr_t, UPB_CTYPE_CONSTPTR) -FUNCS(fptr, fptr, upb_func*, uintptr_t, UPB_CTYPE_FPTR) - -#undef FUNCS - -UPB_INLINE void upb_value_setfloat(upb_value *val, float cval) { - memcpy(&val->val, &cval, sizeof(cval)); - SET_TYPE(val->ctype, UPB_CTYPE_FLOAT); -} - -UPB_INLINE void upb_value_setdouble(upb_value *val, double cval) { - memcpy(&val->val, &cval, sizeof(cval)); - SET_TYPE(val->ctype, UPB_CTYPE_DOUBLE); -} - -UPB_INLINE upb_value upb_value_float(float cval) { - upb_value ret; - upb_value_setfloat(&ret, cval); - return ret; -} - -UPB_INLINE upb_value upb_value_double(double cval) { - upb_value ret; - upb_value_setdouble(&ret, cval); - return ret; -} - -#undef SET_TYPE - - -/* upb_tabkey *****************************************************************/ - -/* Either: - * 1. an actual integer key, or - * 2. a pointer to a string prefixed by its uint32_t length, owned by us. - * - * ...depending on whether this is a string table or an int table. We would - * make this a union of those two types, but C89 doesn't support statically - * initializing a non-first union member. */ -typedef uintptr_t upb_tabkey; - -#define UPB_TABKEY_NUM(n) n -#define UPB_TABKEY_NONE 0 -/* The preprocessor isn't quite powerful enough to turn the compile-time string - * length into a byte-wise string representation, so code generation needs to - * help it along. - * - * "len1" is the low byte and len4 is the high byte. */ -#ifdef UPB_BIG_ENDIAN -#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \ - (uintptr_t)(len4 len3 len2 len1 strval) -#else -#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \ - (uintptr_t)(len1 len2 len3 len4 strval) -#endif - -UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) { - char* mem = (char*)key; - if (len) memcpy(len, mem, sizeof(*len)); - return mem + sizeof(*len); -} - - -/* upb_tabval *****************************************************************/ - -#ifdef __cplusplus - -/* Status initialization not supported. - * - * This separate definition is necessary because in C++, UINTPTR_MAX isn't - * reliably available. */ -typedef struct { - uint64_t val; -} upb_tabval; - -#else - -/* C -- supports static initialization, but to support static initialization of - * both integers and points for both 32 and 64 bit targets, it takes a little - * bit of doing. */ - -#if UINTPTR_MAX == 0xffffffffffffffffULL -#define UPB_PTR_IS_64BITS -#elif UINTPTR_MAX != 0xffffffff -#error Could not determine how many bits pointers are. -#endif - -typedef union { - /* For static initialization. - * - * Unfortunately this ugliness is necessary -- it is the only way that we can, - * with -std=c89 -pedantic, statically initialize this to either a pointer or - * an integer on 32-bit platforms. */ - struct { -#ifdef UPB_PTR_IS_64BITS - uintptr_t val; -#else - uintptr_t val1; - uintptr_t val2; -#endif - } staticinit; - - /* The normal accessor that we use for everything at runtime. */ - uint64_t val; -} upb_tabval; - -#ifdef UPB_PTR_IS_64BITS -#define UPB_TABVALUE_INT_INIT(v) {{v}} -#define UPB_TABVALUE_EMPTY_INIT {{-1}} -#else - -/* 32-bit pointers */ - -#ifdef UPB_BIG_ENDIAN -#define UPB_TABVALUE_INT_INIT(v) {{0, v}} -#define UPB_TABVALUE_EMPTY_INIT {{-1, -1}} -#else -#define UPB_TABVALUE_INT_INIT(v) {{v, 0}} -#define UPB_TABVALUE_EMPTY_INIT {{-1, -1}} -#endif - -#endif - -#define UPB_TABVALUE_PTR_INIT(v) UPB_TABVALUE_INT_INIT((uintptr_t)v) - -#undef UPB_PTR_IS_64BITS - -#endif /* __cplusplus */ - - -/* upb_table ******************************************************************/ - -typedef struct _upb_tabent { - upb_tabkey key; - upb_tabval val; - - /* Internal chaining. This is const so we can create static initializers for - * tables. We cast away const sometimes, but *only* when the containing - * upb_table is known to be non-const. This requires a bit of care, but - * the subtlety is confined to table.c. */ - const struct _upb_tabent *next; -} upb_tabent; - -typedef struct { - size_t count; /* Number of entries in the hash part. */ - size_t mask; /* Mask to turn hash value -> bucket. */ - upb_ctype_t ctype; /* Type of all values. */ - uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ - - /* Hash table entries. - * Making this const isn't entirely accurate; what we really want is for it to - * have the same const-ness as the table it's inside. But there's no way to - * declare that in C. So we have to make it const so that we can statically - * initialize const hash tables. Then we cast away const when we have to. - */ - const upb_tabent *entries; - -#ifndef NDEBUG - /* This table's allocator. We make the user pass it in to every relevant - * function and only use this to check it in debug mode. We do this solely - * to keep upb_table as small as possible. This might seem slightly paranoid - * but the plan is to use upb_table for all map fields and extension sets in - * a forthcoming message representation, so there could be a lot of these. - * If this turns out to be too annoying later, we can change it (since this - * is an internal-only header file). */ - upb_alloc *alloc; -#endif -} upb_table; - -#ifdef NDEBUG -# define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \ - {count, mask, ctype, size_lg2, entries} -#else -# ifdef UPB_DEBUG_REFS -/* At the moment the only mutable tables we statically initialize are debug - * ref tables. */ -# define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \ - {count, mask, ctype, size_lg2, entries, &upb_alloc_debugrefs} -# else -# define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \ - {count, mask, ctype, size_lg2, entries, NULL} -# endif -#endif - -typedef struct { - upb_table t; -} upb_strtable; - -#define UPB_STRTABLE_INIT(count, mask, ctype, size_lg2, entries) \ - {UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries)} - -#define UPB_EMPTY_STRTABLE_INIT(ctype) \ - UPB_STRTABLE_INIT(0, 0, ctype, 0, NULL) - -typedef struct { - upb_table t; /* For entries that don't fit in the array part. */ - const upb_tabval *array; /* Array part of the table. See const note above. */ - size_t array_size; /* Array part size. */ - size_t array_count; /* Array part number of elements. */ -} upb_inttable; - -#define UPB_INTTABLE_INIT(count, mask, ctype, size_lg2, ent, a, asize, acount) \ - {UPB_TABLE_INIT(count, mask, ctype, size_lg2, ent), a, asize, acount} - -#define UPB_EMPTY_INTTABLE_INIT(ctype) \ - UPB_INTTABLE_INIT(0, 0, ctype, 0, NULL, NULL, 0, 0) - -#define UPB_ARRAY_EMPTYENT -1 - -UPB_INLINE size_t upb_table_size(const upb_table *t) { - if (t->size_lg2 == 0) - return 0; - else - return 1 << t->size_lg2; -} - -/* Internal-only functions, in .h file only out of necessity. */ -UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) { - return e->key == 0; -} - -/* Used by some of the unit tests for generic hashing functionality. */ -uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed); - -UPB_INLINE uintptr_t upb_intkey(uintptr_t key) { - return key; -} - -UPB_INLINE uint32_t upb_inthash(uintptr_t key) { - return (uint32_t)key; -} - -static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) { - return t->entries + (hash & t->mask); -} - -UPB_INLINE bool upb_arrhas(upb_tabval key) { - return key.val != (uint64_t)-1; -} - -/* Initialize and uninitialize a table, respectively. If memory allocation - * failed, false is returned that the table is uninitialized. */ -bool upb_inttable_init2(upb_inttable *table, upb_ctype_t ctype, upb_alloc *a); -bool upb_strtable_init2(upb_strtable *table, upb_ctype_t ctype, upb_alloc *a); -void upb_inttable_uninit2(upb_inttable *table, upb_alloc *a); -void upb_strtable_uninit2(upb_strtable *table, upb_alloc *a); - -UPB_INLINE bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype) { - return upb_inttable_init2(table, ctype, &upb_alloc_global); -} - -UPB_INLINE bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype) { - return upb_strtable_init2(table, ctype, &upb_alloc_global); -} - -UPB_INLINE void upb_inttable_uninit(upb_inttable *table) { - upb_inttable_uninit2(table, &upb_alloc_global); -} - -UPB_INLINE void upb_strtable_uninit(upb_strtable *table) { - upb_strtable_uninit2(table, &upb_alloc_global); -} - -/* Returns the number of values in the table. */ -size_t upb_inttable_count(const upb_inttable *t); -UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) { - return t->t.count; -} - -void upb_inttable_packedsize(const upb_inttable *t, size_t *size); -void upb_strtable_packedsize(const upb_strtable *t, size_t *size); -upb_inttable *upb_inttable_pack(const upb_inttable *t, void *p, size_t *ofs, - size_t size); -upb_strtable *upb_strtable_pack(const upb_strtable *t, void *p, size_t *ofs, - size_t size); - -/* Inserts the given key into the hashtable with the given value. The key must - * not already exist in the hash table. For string tables, the key must be - * NULL-terminated, and the table will make an internal copy of the key. - * Inttables must not insert a value of UINTPTR_MAX. - * - * If a table resize was required but memory allocation failed, false is - * returned and the table is unchanged. */ -bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, - upb_alloc *a); -bool upb_strtable_insert3(upb_strtable *t, const char *key, size_t len, - upb_value val, upb_alloc *a); - -UPB_INLINE bool upb_inttable_insert(upb_inttable *t, uintptr_t key, - upb_value val) { - return upb_inttable_insert2(t, key, val, &upb_alloc_global); -} - -UPB_INLINE bool upb_strtable_insert2(upb_strtable *t, const char *key, - size_t len, upb_value val) { - return upb_strtable_insert3(t, key, len, val, &upb_alloc_global); -} - -/* For NULL-terminated strings. */ -UPB_INLINE bool upb_strtable_insert(upb_strtable *t, const char *key, - upb_value val) { - return upb_strtable_insert2(t, key, strlen(key), val); -} - -/* Looks up key in this table, returning "true" if the key was found. - * If v is non-NULL, copies the value for this key into *v. */ -bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v); -bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len, - upb_value *v); - -/* For NULL-terminated strings. */ -UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key, - upb_value *v) { - return upb_strtable_lookup2(t, key, strlen(key), v); -} - -/* Removes an item from the table. Returns true if the remove was successful, - * and stores the removed item in *val if non-NULL. */ -bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val); -bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len, - upb_value *val, upb_alloc *alloc); - -UPB_INLINE bool upb_strtable_remove2(upb_strtable *t, const char *key, - size_t len, upb_value *val) { - return upb_strtable_remove3(t, key, len, val, &upb_alloc_global); -} - -/* For NULL-terminated strings. */ -UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key, - upb_value *v) { - return upb_strtable_remove2(t, key, strlen(key), v); -} - -/* Updates an existing entry in an inttable. If the entry does not exist, - * returns false and does nothing. Unlike insert/remove, this does not - * invalidate iterators. */ -bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val); - -/* Handy routines for treating an inttable like a stack. May not be mixed with - * other insert/remove calls. */ -bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a); -upb_value upb_inttable_pop(upb_inttable *t); - -UPB_INLINE bool upb_inttable_push(upb_inttable *t, upb_value val) { - return upb_inttable_push2(t, val, &upb_alloc_global); -} - -/* Convenience routines for inttables with pointer keys. */ -bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val, - upb_alloc *a); -bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val); -bool upb_inttable_lookupptr( - const upb_inttable *t, const void *key, upb_value *val); - -UPB_INLINE bool upb_inttable_insertptr(upb_inttable *t, const void *key, - upb_value val) { - return upb_inttable_insertptr2(t, key, val, &upb_alloc_global); -} - -/* Optimizes the table for the current set of entries, for both memory use and - * lookup time. Client should call this after all entries have been inserted; - * inserting more entries is legal, but will likely require a table resize. */ -void upb_inttable_compact2(upb_inttable *t, upb_alloc *a); - -UPB_INLINE void upb_inttable_compact(upb_inttable *t) { - upb_inttable_compact2(t, &upb_alloc_global); -} - -/* A special-case inlinable version of the lookup routine for 32-bit - * integers. */ -UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, - upb_value *v) { - *v = upb_value_int32(0); /* Silence compiler warnings. */ - if (key < t->array_size) { - upb_tabval arrval = t->array[key]; - if (upb_arrhas(arrval)) { - _upb_value_setval(v, arrval.val, t->t.ctype); - return true; - } else { - return false; - } - } else { - const upb_tabent *e; - if (t->t.entries == NULL) return false; - for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) { - if ((uint32_t)e->key == key) { - _upb_value_setval(v, e->val.val, t->t.ctype); - return true; - } - if (e->next == NULL) return false; - } - } -} - -/* Exposed for testing only. */ -bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a); - -/* Iterators ******************************************************************/ - -/* Iterators for int and string tables. We are subject to some kind of unusual - * design constraints: - * - * For high-level languages: - * - we must be able to guarantee that we don't crash or corrupt memory even if - * the program accesses an invalidated iterator. - * - * For C++11 range-based for: - * - iterators must be copyable - * - iterators must be comparable - * - it must be possible to construct an "end" value. - * - * Iteration order is undefined. - * - * Modifying the table invalidates iterators. upb_{str,int}table_done() is - * guaranteed to work even on an invalidated iterator, as long as the table it - * is iterating over has not been freed. Calling next() or accessing data from - * an invalidated iterator yields unspecified elements from the table, but it is - * guaranteed not to crash and to return real table elements (except when done() - * is true). */ - - -/* upb_strtable_iter **********************************************************/ - -/* upb_strtable_iter i; - * upb_strtable_begin(&i, t); - * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { - * const char *key = upb_strtable_iter_key(&i); - * const upb_value val = upb_strtable_iter_value(&i); - * // ... - * } - */ - -typedef struct { - const upb_strtable *t; - size_t index; -} upb_strtable_iter; - -void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t); -void upb_strtable_next(upb_strtable_iter *i); -bool upb_strtable_done(const upb_strtable_iter *i); -const char *upb_strtable_iter_key(const upb_strtable_iter *i); -size_t upb_strtable_iter_keylength(const upb_strtable_iter *i); -upb_value upb_strtable_iter_value(const upb_strtable_iter *i); -void upb_strtable_iter_setdone(upb_strtable_iter *i); -bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, - const upb_strtable_iter *i2); - - -/* upb_inttable_iter **********************************************************/ - -/* upb_inttable_iter i; - * upb_inttable_begin(&i, t); - * for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - * uintptr_t key = upb_inttable_iter_key(&i); - * upb_value val = upb_inttable_iter_value(&i); - * // ... - * } - */ - -typedef struct { - const upb_inttable *t; - size_t index; - bool array_part; -} upb_inttable_iter; - -void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t); -void upb_inttable_next(upb_inttable_iter *i); -bool upb_inttable_done(const upb_inttable_iter *i); -uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i); -upb_value upb_inttable_iter_value(const upb_inttable_iter *i); -void upb_inttable_iter_setdone(upb_inttable_iter *i); -bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, - const upb_inttable_iter *i2); - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_TABLE_H_ */ - -/* Reference tracking will check ref()/unref() operations to make sure the - * ref ownership is correct. Where possible it will also make tools like - * Valgrind attribute ref leaks to the code that took the leaked ref, not - * the code that originally created the object. - * - * Enabling this requires the application to define upb_lock()/upb_unlock() - * functions that acquire/release a global mutex (or #define UPB_THREAD_UNSAFE). - * For this reason we don't enable it by default, even in debug builds. - */ - -/* #define UPB_DEBUG_REFS */ - -#ifdef __cplusplus -namespace upb { -class RefCounted; -template class reffed_ptr; -} -#endif - -UPB_DECLARE_TYPE(upb::RefCounted, upb_refcounted) - -struct upb_refcounted_vtbl; - -#ifdef __cplusplus - -class upb::RefCounted { - public: - /* Returns true if the given object is frozen. */ - bool IsFrozen() const; - - /* Increases the ref count, the new ref is owned by "owner" which must not - * already own a ref (and should not itself be a refcounted object if the ref - * could possibly be circular; see below). - * Thread-safe iff "this" is frozen. */ - void Ref(const void *owner) const; - - /* Release a ref that was acquired from upb_refcounted_ref() and collects any - * objects it can. */ - void Unref(const void *owner) const; - - /* Moves an existing ref from "from" to "to", without changing the overall - * ref count. DonateRef(foo, NULL, owner) is the same as Ref(foo, owner), - * but "to" may not be NULL. */ - void DonateRef(const void *from, const void *to) const; - - /* Verifies that a ref to the given object is currently held by the given - * owner. Only effective in UPB_DEBUG_REFS builds. */ - void CheckRef(const void *owner) const; - - private: - UPB_DISALLOW_POD_OPS(RefCounted, upb::RefCounted) -#else -struct upb_refcounted { -#endif - /* TODO(haberman): move the actual structure definition to structdefs.int.h. - * The only reason they are here is because inline functions need to see the - * definition of upb_handlers, which needs to see this definition. But we - * can change the upb_handlers inline functions to deal in raw offsets - * instead. - */ - - /* A single reference count shared by all objects in the group. */ - uint32_t *group; - - /* A singly-linked list of all objects in the group. */ - upb_refcounted *next; - - /* Table of function pointers for this type. */ - const struct upb_refcounted_vtbl *vtbl; - - /* Maintained only when mutable, this tracks the number of refs (but not - * ref2's) to this object. *group should be the sum of all individual_count - * in the group. */ - uint32_t individual_count; - - bool is_frozen; - -#ifdef UPB_DEBUG_REFS - upb_inttable *refs; /* Maps owner -> trackedref for incoming refs. */ - upb_inttable *ref2s; /* Set of targets for outgoing ref2s. */ -#endif -}; - -#ifdef UPB_DEBUG_REFS -extern upb_alloc upb_alloc_debugrefs; -#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \ - {&static_refcount, NULL, vtbl, 0, true, refs, ref2s} -#else -#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \ - {&static_refcount, NULL, vtbl, 0, true} -#endif - -UPB_BEGIN_EXTERN_C - -/* It is better to use tracked refs when possible, for the extra debugging - * capability. But if this is not possible (because you don't have easy access - * to a stable pointer value that is associated with the ref), you can pass - * UPB_UNTRACKED_REF instead. */ -extern const void *UPB_UNTRACKED_REF; - -/* Native C API. */ -bool upb_refcounted_isfrozen(const upb_refcounted *r); -void upb_refcounted_ref(const upb_refcounted *r, const void *owner); -void upb_refcounted_unref(const upb_refcounted *r, const void *owner); -void upb_refcounted_donateref( - const upb_refcounted *r, const void *from, const void *to); -void upb_refcounted_checkref(const upb_refcounted *r, const void *owner); - -#define UPB_REFCOUNTED_CMETHODS(type, upcastfunc) \ - UPB_INLINE bool type ## _isfrozen(const type *v) { \ - return upb_refcounted_isfrozen(upcastfunc(v)); \ - } \ - UPB_INLINE void type ## _ref(const type *v, const void *owner) { \ - upb_refcounted_ref(upcastfunc(v), owner); \ - } \ - UPB_INLINE void type ## _unref(const type *v, const void *owner) { \ - upb_refcounted_unref(upcastfunc(v), owner); \ - } \ - UPB_INLINE void type ## _donateref(const type *v, const void *from, const void *to) { \ - upb_refcounted_donateref(upcastfunc(v), from, to); \ - } \ - UPB_INLINE void type ## _checkref(const type *v, const void *owner) { \ - upb_refcounted_checkref(upcastfunc(v), owner); \ - } - -#define UPB_REFCOUNTED_CPPMETHODS \ - bool IsFrozen() const { \ - return upb::upcast_to(this)->IsFrozen(); \ - } \ - void Ref(const void *owner) const { \ - return upb::upcast_to(this)->Ref(owner); \ - } \ - void Unref(const void *owner) const { \ - return upb::upcast_to(this)->Unref(owner); \ - } \ - void DonateRef(const void *from, const void *to) const { \ - return upb::upcast_to(this)->DonateRef(from, to); \ - } \ - void CheckRef(const void *owner) const { \ - return upb::upcast_to(this)->CheckRef(owner); \ - } - -/* Internal-to-upb Interface **************************************************/ - -typedef void upb_refcounted_visit(const upb_refcounted *r, - const upb_refcounted *subobj, - void *closure); - -struct upb_refcounted_vtbl { - /* Must visit all subobjects that are currently ref'd via upb_refcounted_ref2. - * Must be longjmp()-safe. */ - void (*visit)(const upb_refcounted *r, upb_refcounted_visit *visit, void *c); - - /* Must free the object and release all references to other objects. */ - void (*free)(upb_refcounted *r); -}; - -/* Initializes the refcounted with a single ref for the given owner. Returns - * false if memory could not be allocated. */ -bool upb_refcounted_init(upb_refcounted *r, - const struct upb_refcounted_vtbl *vtbl, - const void *owner); - -/* Adds a ref from one refcounted object to another ("from" must not already - * own a ref). These refs may be circular; cycles will be collected correctly - * (if conservatively). These refs do not need to be freed in from's free() - * function. */ -void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from); - -/* Removes a ref that was acquired from upb_refcounted_ref2(), and collects any - * object it can. This is only necessary when "from" no longer points to "r", - * and not from from's "free" function. */ -void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from); - -#define upb_ref2(r, from) \ - upb_refcounted_ref2((const upb_refcounted*)r, (upb_refcounted*)from) -#define upb_unref2(r, from) \ - upb_refcounted_unref2((const upb_refcounted*)r, (upb_refcounted*)from) - -/* Freezes all mutable object reachable by ref2() refs from the given roots. - * This will split refcounting groups into precise SCC groups, so that - * refcounting of frozen objects can be more aggressive. If memory allocation - * fails, or if more than 2**31 mutable objects are reachable from "roots", or - * if the maximum depth of the graph exceeds "maxdepth", false is returned and - * the objects are unchanged. - * - * After this operation succeeds, the objects are frozen/const, and may not be - * used through non-const pointers. In particular, they may not be passed as - * the second parameter of upb_refcounted_{ref,unref}2(). On the upside, all - * operations on frozen refcounteds are threadsafe, and objects will be freed - * at the precise moment that they become unreachable. - * - * Caller must own refs on each object in the "roots" list. */ -bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s, - int maxdepth); - -/* Shared by all compiled-in refcounted objects. */ -extern uint32_t static_refcount; - -UPB_END_EXTERN_C - -#ifdef __cplusplus -/* C++ Wrappers. */ -namespace upb { -inline bool RefCounted::IsFrozen() const { - return upb_refcounted_isfrozen(this); -} -inline void RefCounted::Ref(const void *owner) const { - upb_refcounted_ref(this, owner); -} -inline void RefCounted::Unref(const void *owner) const { - upb_refcounted_unref(this, owner); -} -inline void RefCounted::DonateRef(const void *from, const void *to) const { - upb_refcounted_donateref(this, from, to); -} -inline void RefCounted::CheckRef(const void *owner) const { - upb_refcounted_checkref(this, owner); -} -} /* namespace upb */ -#endif - - -/* upb::reffed_ptr ************************************************************/ - -#ifdef __cplusplus - -#include /* For std::swap(). */ - -/* Provides RAII semantics for upb refcounted objects. Each reffed_ptr owns a - * ref on whatever object it points to (if any). */ -template class upb::reffed_ptr { - public: - reffed_ptr() : ptr_(NULL) {} - - /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */ - template - reffed_ptr(U* val, const void* ref_donor = NULL) - : ptr_(upb::upcast(val)) { - if (ref_donor) { - UPB_ASSERT(ptr_); - ptr_->DonateRef(ref_donor, this); - } else if (ptr_) { - ptr_->Ref(this); - } - } - - template - reffed_ptr(const reffed_ptr& other) - : ptr_(upb::upcast(other.get())) { - if (ptr_) ptr_->Ref(this); - } - - reffed_ptr(const reffed_ptr& other) - : ptr_(upb::upcast(other.get())) { - if (ptr_) ptr_->Ref(this); - } - - ~reffed_ptr() { if (ptr_) ptr_->Unref(this); } - - template - reffed_ptr& operator=(const reffed_ptr& other) { - reset(other.get()); - return *this; - } - - reffed_ptr& operator=(const reffed_ptr& other) { - reset(other.get()); - return *this; - } - - /* TODO(haberman): add C++11 move construction/assignment for greater - * efficiency. */ - - void swap(reffed_ptr& other) { - if (ptr_ == other.ptr_) { - return; - } - - if (ptr_) ptr_->DonateRef(this, &other); - if (other.ptr_) other.ptr_->DonateRef(&other, this); - std::swap(ptr_, other.ptr_); - } - - T& operator*() const { - UPB_ASSERT(ptr_); - return *ptr_; - } - - T* operator->() const { - UPB_ASSERT(ptr_); - return ptr_; - } - - T* get() const { return ptr_; } - - /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */ - template - void reset(U* ptr = NULL, const void* ref_donor = NULL) { - reffed_ptr(ptr, ref_donor).swap(*this); - } - - template - reffed_ptr down_cast() { - return reffed_ptr(upb::down_cast(get())); - } - - template - reffed_ptr dyn_cast() { - return reffed_ptr(upb::dyn_cast(get())); - } - - /* Plain release() is unsafe; if we were the only owner, it would leak the - * object. Instead we provide this: */ - T* ReleaseTo(const void* new_owner) { - T* ret = NULL; - ptr_->DonateRef(this, new_owner); - std::swap(ret, ptr_); - return ret; - } - - private: - T* ptr_; -}; - -#endif /* __cplusplus */ - -#endif /* UPB_REFCOUNT_H_ */ - -#ifdef __cplusplus -#include -#include -#include - -namespace upb { -class Def; -class EnumDef; -class FieldDef; -class FileDef; -class MessageDef; -class OneofDef; -class SymbolTable; -} -#endif - -UPB_DECLARE_DERIVED_TYPE(upb::Def, upb::RefCounted, upb_def, upb_refcounted) -UPB_DECLARE_DERIVED_TYPE(upb::OneofDef, upb::RefCounted, upb_oneofdef, - upb_refcounted) -UPB_DECLARE_DERIVED_TYPE(upb::FileDef, upb::RefCounted, upb_filedef, - upb_refcounted) -UPB_DECLARE_TYPE(upb::SymbolTable, upb_symtab) - - -/* The maximum message depth that the type graph can have. This is a resource - * limit for the C stack since we sometimes need to recursively traverse the - * graph. Cycles are ok; the traversal will stop when it detects a cycle, but - * we must hit the cycle before the maximum depth is reached. - * - * If having a single static limit is too inflexible, we can add another variant - * of Def::Freeze that allows specifying this as a parameter. */ -#define UPB_MAX_MESSAGE_DEPTH 64 - - -/* upb::Def: base class for top-level defs ***********************************/ - -/* All the different kind of defs that can be defined at the top-level and put - * in a SymbolTable or appear in a FileDef::defs() list. This excludes some - * defs (like oneofs and files). It only includes fields because they can be - * defined as extensions. */ -typedef enum { - UPB_DEF_MSG, - UPB_DEF_FIELD, - UPB_DEF_ENUM, - UPB_DEF_SERVICE, /* Not yet implemented. */ - UPB_DEF_ANY = -1 /* Wildcard for upb_symtab_get*() */ -} upb_deftype_t; - -#ifdef __cplusplus - -/* The base class of all defs. Its base is upb::RefCounted (use upb::upcast() - * to convert). */ -class upb::Def { - public: - typedef upb_deftype_t Type; - - /* upb::RefCounted methods like Ref()/Unref(). */ - UPB_REFCOUNTED_CPPMETHODS - - Type def_type() const; - - /* "fullname" is the def's fully-qualified name (eg. foo.bar.Message). */ - const char *full_name() const; - - /* The final part of a def's name (eg. Message). */ - const char *name() const; - - /* The def must be mutable. Caller retains ownership of fullname. Defs are - * not required to have a name; if a def has no name when it is frozen, it - * will remain an anonymous def. On failure, returns false and details in "s" - * if non-NULL. */ - bool set_full_name(const char* fullname, upb::Status* s); - bool set_full_name(const std::string &fullname, upb::Status* s); - - /* The file in which this def appears. It is not necessary to add a def to a - * file (and consequently the accessor may return NULL). Set this by calling - * file->Add(def). */ - FileDef* file() const; - - /* Freezes the given defs; this validates all constraints and marks the defs - * as frozen (read-only). "defs" may not contain any fielddefs, but fields - * of any msgdefs will be frozen. - * - * Symbolic references to sub-types and enum defaults must have already been - * resolved. Any mutable defs reachable from any of "defs" must also be in - * the list; more formally, "defs" must be a transitive closure of mutable - * defs. - * - * After this operation succeeds, the finalized defs must only be accessed - * through a const pointer! */ - static bool Freeze(Def* const* defs, size_t n, Status* status); - static bool Freeze(const std::vector& defs, Status* status); - - private: - UPB_DISALLOW_POD_OPS(Def, upb::Def) -}; - -#endif /* __cplusplus */ - -UPB_BEGIN_EXTERN_C - -/* Include upb_refcounted methods like upb_def_ref()/upb_def_unref(). */ -UPB_REFCOUNTED_CMETHODS(upb_def, upb_def_upcast) - -upb_deftype_t upb_def_type(const upb_def *d); -const char *upb_def_fullname(const upb_def *d); -const char *upb_def_name(const upb_def *d); -const upb_filedef *upb_def_file(const upb_def *d); -bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s); -bool upb_def_freeze(upb_def *const *defs, size_t n, upb_status *s); - -/* Temporary API: for internal use only. */ -bool _upb_def_validate(upb_def *const*defs, size_t n, upb_status *s); - -UPB_END_EXTERN_C - - -/* upb::Def casts *************************************************************/ - -#ifdef __cplusplus -#define UPB_CPP_CASTS(cname, cpptype) \ - namespace upb { \ - template <> \ - inline cpptype *down_cast(Def * def) { \ - return upb_downcast_##cname##_mutable(def); \ - } \ - template <> \ - inline cpptype *dyn_cast(Def * def) { \ - return upb_dyncast_##cname##_mutable(def); \ - } \ - template <> \ - inline const cpptype *down_cast( \ - const Def *def) { \ - return upb_downcast_##cname(def); \ - } \ - template <> \ - inline const cpptype *dyn_cast(const Def *def) { \ - return upb_dyncast_##cname(def); \ - } \ - template <> \ - inline const cpptype *down_cast(Def * def) { \ - return upb_downcast_##cname(def); \ - } \ - template <> \ - inline const cpptype *dyn_cast(Def * def) { \ - return upb_dyncast_##cname(def); \ - } \ - } /* namespace upb */ -#else -#define UPB_CPP_CASTS(cname, cpptype) -#endif /* __cplusplus */ - -/* Dynamic casts, for determining if a def is of a particular type at runtime. - * Downcasts, for when some wants to assert that a def is of a particular type. - * These are only checked if we are building debug. */ -#define UPB_DEF_CASTS(lower, upper, cpptype) \ - UPB_INLINE const upb_##lower *upb_dyncast_##lower(const upb_def *def) { \ - if (upb_def_type(def) != UPB_DEF_##upper) return NULL; \ - return (upb_##lower *)def; \ - } \ - UPB_INLINE const upb_##lower *upb_downcast_##lower(const upb_def *def) { \ - UPB_ASSERT(upb_def_type(def) == UPB_DEF_##upper); \ - return (const upb_##lower *)def; \ - } \ - UPB_INLINE upb_##lower *upb_dyncast_##lower##_mutable(upb_def *def) { \ - return (upb_##lower *)upb_dyncast_##lower(def); \ - } \ - UPB_INLINE upb_##lower *upb_downcast_##lower##_mutable(upb_def *def) { \ - return (upb_##lower *)upb_downcast_##lower(def); \ - } \ - UPB_CPP_CASTS(lower, cpptype) - -#define UPB_DEFINE_DEF(cppname, lower, upper, cppmethods, members) \ - UPB_DEFINE_CLASS2(cppname, upb::Def, upb::RefCounted, cppmethods, \ - members) \ - UPB_DEF_CASTS(lower, upper, cppname) - -#define UPB_DECLARE_DEF_TYPE(cppname, lower, upper) \ - UPB_DECLARE_DERIVED_TYPE2(cppname, upb::Def, upb::RefCounted, \ - upb_ ## lower, upb_def, upb_refcounted) \ - UPB_DEF_CASTS(lower, upper, cppname) - -UPB_DECLARE_DEF_TYPE(upb::FieldDef, fielddef, FIELD) -UPB_DECLARE_DEF_TYPE(upb::MessageDef, msgdef, MSG) -UPB_DECLARE_DEF_TYPE(upb::EnumDef, enumdef, ENUM) - -#undef UPB_DECLARE_DEF_TYPE -#undef UPB_DEF_CASTS -#undef UPB_CPP_CASTS - - -/* upb::FieldDef **************************************************************/ - -/* The types a field can have. Note that this list is not identical to the - * types defined in descriptor.proto, which gives INT32 and SINT32 separate - * types (we distinguish the two with the "integer encoding" enum below). */ -typedef enum { - /* Types stored in 1 byte. */ - UPB_TYPE_BOOL = 1, - /* Types stored in 4 bytes. */ - UPB_TYPE_FLOAT = 2, - UPB_TYPE_INT32 = 3, - UPB_TYPE_UINT32 = 4, - UPB_TYPE_ENUM = 5, /* Enum values are int32. */ - /* Types stored as pointers (probably 4 or 8 bytes). */ - UPB_TYPE_STRING = 6, - UPB_TYPE_BYTES = 7, - UPB_TYPE_MESSAGE = 8, - /* Types stored as 8 bytes. */ - UPB_TYPE_DOUBLE = 9, - UPB_TYPE_INT64 = 10, - UPB_TYPE_UINT64 = 11 -} upb_fieldtype_t; - -/* The repeated-ness of each field; this matches descriptor.proto. */ -typedef enum { - UPB_LABEL_OPTIONAL = 1, - UPB_LABEL_REQUIRED = 2, - UPB_LABEL_REPEATED = 3 -} upb_label_t; - -/* How integers should be encoded in serializations that offer multiple - * integer encoding methods. */ -typedef enum { - UPB_INTFMT_VARIABLE = 1, - UPB_INTFMT_FIXED = 2, - UPB_INTFMT_ZIGZAG = 3 /* Only for signed types (INT32/INT64). */ -} upb_intfmt_t; - -/* Descriptor types, as defined in descriptor.proto. */ -typedef enum { - UPB_DESCRIPTOR_TYPE_DOUBLE = 1, - UPB_DESCRIPTOR_TYPE_FLOAT = 2, - UPB_DESCRIPTOR_TYPE_INT64 = 3, - UPB_DESCRIPTOR_TYPE_UINT64 = 4, - UPB_DESCRIPTOR_TYPE_INT32 = 5, - UPB_DESCRIPTOR_TYPE_FIXED64 = 6, - UPB_DESCRIPTOR_TYPE_FIXED32 = 7, - UPB_DESCRIPTOR_TYPE_BOOL = 8, - UPB_DESCRIPTOR_TYPE_STRING = 9, - UPB_DESCRIPTOR_TYPE_GROUP = 10, - UPB_DESCRIPTOR_TYPE_MESSAGE = 11, - UPB_DESCRIPTOR_TYPE_BYTES = 12, - UPB_DESCRIPTOR_TYPE_UINT32 = 13, - UPB_DESCRIPTOR_TYPE_ENUM = 14, - UPB_DESCRIPTOR_TYPE_SFIXED32 = 15, - UPB_DESCRIPTOR_TYPE_SFIXED64 = 16, - UPB_DESCRIPTOR_TYPE_SINT32 = 17, - UPB_DESCRIPTOR_TYPE_SINT64 = 18 -} upb_descriptortype_t; - -typedef enum { - UPB_SYNTAX_PROTO2 = 2, - UPB_SYNTAX_PROTO3 = 3 -} upb_syntax_t; - -/* Maximum field number allowed for FieldDefs. This is an inherent limit of the - * protobuf wire format. */ -#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1) - -#ifdef __cplusplus - -/* A upb_fielddef describes a single field in a message. It is most often - * found as a part of a upb_msgdef, but can also stand alone to represent - * an extension. - * - * Its base class is upb::Def (use upb::upcast() to convert). */ -class upb::FieldDef { - public: - typedef upb_fieldtype_t Type; - typedef upb_label_t Label; - typedef upb_intfmt_t IntegerFormat; - typedef upb_descriptortype_t DescriptorType; - - /* These return true if the given value is a valid member of the enumeration. */ - static bool CheckType(int32_t val); - static bool CheckLabel(int32_t val); - static bool CheckDescriptorType(int32_t val); - static bool CheckIntegerFormat(int32_t val); - - /* These convert to the given enumeration; they require that the value is - * valid. */ - static Type ConvertType(int32_t val); - static Label ConvertLabel(int32_t val); - static DescriptorType ConvertDescriptorType(int32_t val); - static IntegerFormat ConvertIntegerFormat(int32_t val); - - /* Returns NULL if memory allocation failed. */ - static reffed_ptr New(); - - /* upb::RefCounted methods like Ref()/Unref(). */ - UPB_REFCOUNTED_CPPMETHODS - - /* Functionality from upb::Def. */ - const char* full_name() const; - - bool type_is_set() const; /* set_[descriptor_]type() has been called? */ - Type type() const; /* Requires that type_is_set() == true. */ - Label label() const; /* Defaults to UPB_LABEL_OPTIONAL. */ - const char* name() const; /* NULL if uninitialized. */ - uint32_t number() const; /* Returns 0 if uninitialized. */ - bool is_extension() const; - - /* Copies the JSON name for this field into the given buffer. Returns the - * actual size of the JSON name, including the NULL terminator. If the - * return value is 0, the JSON name is unset. If the return value is - * greater than len, the JSON name was truncated. The buffer is always - * NULL-terminated if len > 0. - * - * The JSON name always defaults to a camelCased version of the regular - * name. However if the regular name is unset, the JSON name will be unset - * also. - */ - size_t GetJsonName(char* buf, size_t len) const; - - /* Convenience version of the above function which copies the JSON name - * into the given string, returning false if the name is not set. */ - template - bool GetJsonName(T* str) { - str->resize(GetJsonName(NULL, 0)); - GetJsonName(&(*str)[0], str->size()); - return str->size() > 0; - } - - /* For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false, - * indicates whether this field should have lazy parsing handlers that yield - * the unparsed string for the submessage. - * - * TODO(haberman): I think we want to move this into a FieldOptions container - * when we add support for custom options (the FieldOptions struct will - * contain both regular FieldOptions like "lazy" *and* custom options). */ - bool lazy() const; - - /* For non-string, non-submessage fields, this indicates whether binary - * protobufs are encoded in packed or non-packed format. - * - * TODO(haberman): see note above about putting options like this into a - * FieldOptions container. */ - bool packed() const; - - /* An integer that can be used as an index into an array of fields for - * whatever message this field belongs to. Guaranteed to be less than - * f->containing_type()->field_count(). May only be accessed once the def has - * been finalized. */ - uint32_t index() const; - - /* The MessageDef to which this field belongs. - * - * If this field has been added to a MessageDef, that message can be retrieved - * directly (this is always the case for frozen FieldDefs). - * - * If the field has not yet been added to a MessageDef, you can set the name - * of the containing type symbolically instead. This is mostly useful for - * extensions, where the extension is declared separately from the message. */ - const MessageDef* containing_type() const; - const char* containing_type_name(); - - /* The OneofDef to which this field belongs, or NULL if this field is not part - * of a oneof. */ - const OneofDef* containing_oneof() const; - - /* The field's type according to the enum in descriptor.proto. This is not - * the same as UPB_TYPE_*, because it distinguishes between (for example) - * INT32 and SINT32, whereas our "type" enum does not. This return of - * descriptor_type() is a function of type(), integer_format(), and - * is_tag_delimited(). Likewise set_descriptor_type() sets all three - * appropriately. */ - DescriptorType descriptor_type() const; - - /* Convenient field type tests. */ - bool IsSubMessage() const; - bool IsString() const; - bool IsSequence() const; - bool IsPrimitive() const; - bool IsMap() const; - - /* Returns whether this field explicitly represents presence. - * - * For proto2 messages: Returns true for any scalar (non-repeated) field. - * For proto3 messages: Returns true for scalar submessage or oneof fields. */ - bool HasPresence() const; - - /* How integers are encoded. Only meaningful for integer types. - * Defaults to UPB_INTFMT_VARIABLE, and is reset when "type" changes. */ - IntegerFormat integer_format() const; - - /* Whether a submessage field is tag-delimited or not (if false, then - * length-delimited). May only be set when type() == UPB_TYPE_MESSAGE. */ - bool is_tag_delimited() const; - - /* Returns the non-string default value for this fielddef, which may either - * be something the client set explicitly or the "default default" (0 for - * numbers, empty for strings). The field's type indicates the type of the - * returned value, except for enum fields that are still mutable. - * - * Requires that the given function matches the field's current type. */ - int64_t default_int64() const; - int32_t default_int32() const; - uint64_t default_uint64() const; - uint32_t default_uint32() const; - bool default_bool() const; - float default_float() const; - double default_double() const; - - /* The resulting string is always NULL-terminated. If non-NULL, the length - * will be stored in *len. */ - const char *default_string(size_t* len) const; - - /* For frozen UPB_TYPE_ENUM fields, enum defaults can always be read as either - * string or int32, and both of these methods will always return true. - * - * For mutable UPB_TYPE_ENUM fields, the story is a bit more complicated. - * Enum defaults are unusual. They can be specified either as string or int32, - * but to be valid the enum must have that value as a member. And if no - * default is specified, the "default default" comes from the EnumDef. - * - * We allow reading the default as either an int32 or a string, but only if - * we have a meaningful value to report. We have a meaningful value if it was - * set explicitly, or if we could get the "default default" from the EnumDef. - * Also if you explicitly set the name and we find the number in the EnumDef */ - bool EnumHasStringDefault() const; - bool EnumHasInt32Default() const; - - /* Submessage and enum fields must reference a "subdef", which is the - * upb::MessageDef or upb::EnumDef that defines their type. Note that when - * the FieldDef is mutable it may not have a subdef *yet*, but this function - * still returns true to indicate that the field's type requires a subdef. */ - bool HasSubDef() const; - - /* Returns the enum or submessage def for this field, if any. The field's - * type must match (ie. you may only call enum_subdef() for fields where - * type() == UPB_TYPE_ENUM). Returns NULL if the subdef has not been set or - * is currently set symbolically. */ - const EnumDef* enum_subdef() const; - const MessageDef* message_subdef() const; - - /* Returns the generic subdef for this field. Requires that HasSubDef() (ie. - * only works for UPB_TYPE_ENUM and UPB_TYPE_MESSAGE fields). */ - const Def* subdef() const; - - /* Returns the symbolic name of the subdef. If the subdef is currently set - * unresolved (ie. set symbolically) returns the symbolic name. If it has - * been resolved to a specific subdef, returns the name from that subdef. */ - const char* subdef_name() const; - - /* Setters (non-const methods), only valid for mutable FieldDefs! ***********/ - - bool set_full_name(const char* fullname, upb::Status* s); - bool set_full_name(const std::string& fullname, upb::Status* s); - - /* This may only be called if containing_type() == NULL (ie. the field has not - * been added to a message yet). */ - bool set_containing_type_name(const char *name, Status* status); - bool set_containing_type_name(const std::string& name, Status* status); - - /* Defaults to false. When we freeze, we ensure that this can only be true - * for length-delimited message fields. Prior to freezing this can be true or - * false with no restrictions. */ - void set_lazy(bool lazy); - - /* Defaults to true. Sets whether this field is encoded in packed format. */ - void set_packed(bool packed); - - /* "type" or "descriptor_type" MUST be set explicitly before the fielddef is - * finalized. These setters require that the enum value is valid; if the - * value did not come directly from an enum constant, the caller should - * validate it first with the functions above (CheckFieldType(), etc). */ - void set_type(Type type); - void set_label(Label label); - void set_descriptor_type(DescriptorType type); - void set_is_extension(bool is_extension); - - /* "number" and "name" must be set before the FieldDef is added to a - * MessageDef, and may not be set after that. - * - * "name" is the same as full_name()/set_full_name(), but since fielddefs - * most often use simple, non-qualified names, we provide this accessor - * also. Generally only extensions will want to think of this name as - * fully-qualified. */ - bool set_number(uint32_t number, upb::Status* s); - bool set_name(const char* name, upb::Status* s); - bool set_name(const std::string& name, upb::Status* s); - - /* Sets the JSON name to the given string. */ - /* TODO(haberman): implement. Right now only default json_name (camelCase) - * is supported. */ - bool set_json_name(const char* json_name, upb::Status* s); - bool set_json_name(const std::string& name, upb::Status* s); - - /* Clears the JSON name. This will make it revert to its default, which is - * a camelCased version of the regular field name. */ - void clear_json_name(); - - void set_integer_format(IntegerFormat format); - bool set_tag_delimited(bool tag_delimited, upb::Status* s); - - /* Sets default value for the field. The call must exactly match the type - * of the field. Enum fields may use either setint32 or setstring to set - * the default numerically or symbolically, respectively, but symbolic - * defaults must be resolved before finalizing (see ResolveEnumDefault()). - * - * Changing the type of a field will reset its default. */ - void set_default_int64(int64_t val); - void set_default_int32(int32_t val); - void set_default_uint64(uint64_t val); - void set_default_uint32(uint32_t val); - void set_default_bool(bool val); - void set_default_float(float val); - void set_default_double(double val); - bool set_default_string(const void *str, size_t len, Status *s); - bool set_default_string(const std::string &str, Status *s); - void set_default_cstr(const char *str, Status *s); - - /* Before a fielddef is frozen, its subdef may be set either directly (with a - * upb::Def*) or symbolically. Symbolic refs must be resolved before the - * containing msgdef can be frozen (see upb_resolve() above). upb always - * guarantees that any def reachable from a live def will also be kept alive. - * - * Both methods require that upb_hassubdef(f) (so the type must be set prior - * to calling these methods). Returns false if this is not the case, or if - * the given subdef is not of the correct type. The subdef is reset if the - * field's type is changed. The subdef can be set to NULL to clear it. */ - bool set_subdef(const Def* subdef, Status* s); - bool set_enum_subdef(const EnumDef* subdef, Status* s); - bool set_message_subdef(const MessageDef* subdef, Status* s); - bool set_subdef_name(const char* name, Status* s); - bool set_subdef_name(const std::string &name, Status* s); - - private: - UPB_DISALLOW_POD_OPS(FieldDef, upb::FieldDef) -}; - -# endif /* defined(__cplusplus) */ - -UPB_BEGIN_EXTERN_C - -/* Native C API. */ -upb_fielddef *upb_fielddef_new(const void *owner); - -/* Include upb_refcounted methods like upb_fielddef_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_fielddef, upb_fielddef_upcast2) - -/* Methods from upb_def. */ -const char *upb_fielddef_fullname(const upb_fielddef *f); -bool upb_fielddef_setfullname(upb_fielddef *f, const char *fullname, - upb_status *s); - -bool upb_fielddef_typeisset(const upb_fielddef *f); -upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f); -upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f); -upb_label_t upb_fielddef_label(const upb_fielddef *f); -uint32_t upb_fielddef_number(const upb_fielddef *f); -const char *upb_fielddef_name(const upb_fielddef *f); -bool upb_fielddef_isextension(const upb_fielddef *f); -bool upb_fielddef_lazy(const upb_fielddef *f); -bool upb_fielddef_packed(const upb_fielddef *f); -size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len); -const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f); -const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f); -upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f); -const char *upb_fielddef_containingtypename(upb_fielddef *f); -upb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f); -uint32_t upb_fielddef_index(const upb_fielddef *f); -bool upb_fielddef_istagdelim(const upb_fielddef *f); -bool upb_fielddef_issubmsg(const upb_fielddef *f); -bool upb_fielddef_isstring(const upb_fielddef *f); -bool upb_fielddef_isseq(const upb_fielddef *f); -bool upb_fielddef_isprimitive(const upb_fielddef *f); -bool upb_fielddef_ismap(const upb_fielddef *f); -bool upb_fielddef_haspresence(const upb_fielddef *f); -int64_t upb_fielddef_defaultint64(const upb_fielddef *f); -int32_t upb_fielddef_defaultint32(const upb_fielddef *f); -uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f); -uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f); -bool upb_fielddef_defaultbool(const upb_fielddef *f); -float upb_fielddef_defaultfloat(const upb_fielddef *f); -double upb_fielddef_defaultdouble(const upb_fielddef *f); -const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len); -bool upb_fielddef_enumhasdefaultint32(const upb_fielddef *f); -bool upb_fielddef_enumhasdefaultstr(const upb_fielddef *f); -bool upb_fielddef_hassubdef(const upb_fielddef *f); -const upb_def *upb_fielddef_subdef(const upb_fielddef *f); -const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f); -const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f); -const char *upb_fielddef_subdefname(const upb_fielddef *f); - -void upb_fielddef_settype(upb_fielddef *f, upb_fieldtype_t type); -void upb_fielddef_setdescriptortype(upb_fielddef *f, int type); -void upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label); -bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s); -bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s); -bool upb_fielddef_setjsonname(upb_fielddef *f, const char *name, upb_status *s); -bool upb_fielddef_clearjsonname(upb_fielddef *f); -bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name, - upb_status *s); -void upb_fielddef_setisextension(upb_fielddef *f, bool is_extension); -void upb_fielddef_setlazy(upb_fielddef *f, bool lazy); -void upb_fielddef_setpacked(upb_fielddef *f, bool packed); -void upb_fielddef_setintfmt(upb_fielddef *f, upb_intfmt_t fmt); -void upb_fielddef_settagdelim(upb_fielddef *f, bool tag_delim); -void upb_fielddef_setdefaultint64(upb_fielddef *f, int64_t val); -void upb_fielddef_setdefaultint32(upb_fielddef *f, int32_t val); -void upb_fielddef_setdefaultuint64(upb_fielddef *f, uint64_t val); -void upb_fielddef_setdefaultuint32(upb_fielddef *f, uint32_t val); -void upb_fielddef_setdefaultbool(upb_fielddef *f, bool val); -void upb_fielddef_setdefaultfloat(upb_fielddef *f, float val); -void upb_fielddef_setdefaultdouble(upb_fielddef *f, double val); -bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len, - upb_status *s); -void upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str, - upb_status *s); -bool upb_fielddef_setsubdef(upb_fielddef *f, const upb_def *subdef, - upb_status *s); -bool upb_fielddef_setmsgsubdef(upb_fielddef *f, const upb_msgdef *subdef, - upb_status *s); -bool upb_fielddef_setenumsubdef(upb_fielddef *f, const upb_enumdef *subdef, - upb_status *s); -bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name, - upb_status *s); - -bool upb_fielddef_checklabel(int32_t label); -bool upb_fielddef_checktype(int32_t type); -bool upb_fielddef_checkdescriptortype(int32_t type); -bool upb_fielddef_checkintfmt(int32_t fmt); - -UPB_END_EXTERN_C - - -/* upb::MessageDef ************************************************************/ - -typedef upb_inttable_iter upb_msg_field_iter; -typedef upb_strtable_iter upb_msg_oneof_iter; - -/* Well-known field tag numbers for map-entry messages. */ -#define UPB_MAPENTRY_KEY 1 -#define UPB_MAPENTRY_VALUE 2 - -#ifdef __cplusplus - -/* Structure that describes a single .proto message type. - * - * Its base class is upb::Def (use upb::upcast() to convert). */ -class upb::MessageDef { - public: - /* Returns NULL if memory allocation failed. */ - static reffed_ptr New(); - - /* upb::RefCounted methods like Ref()/Unref(). */ - UPB_REFCOUNTED_CPPMETHODS - - /* Functionality from upb::Def. */ - const char* full_name() const; - const char* name() const; - bool set_full_name(const char* fullname, Status* s); - bool set_full_name(const std::string& fullname, Status* s); - - /* Call to freeze this MessageDef. - * WARNING: this will fail if this message has any unfrozen submessages! - * Messages with cycles must be frozen as a batch using upb::Def::Freeze(). */ - bool Freeze(Status* s); - - /* The number of fields that belong to the MessageDef. */ - int field_count() const; - - /* The number of oneofs that belong to the MessageDef. */ - int oneof_count() const; - - /* Adds a field (upb_fielddef object) to a msgdef. Requires that the msgdef - * and the fielddefs are mutable. The fielddef's name and number must be - * set, and the message may not already contain any field with this name or - * number, and this fielddef may not be part of another message. In error - * cases false is returned and the msgdef is unchanged. - * - * If the given field is part of a oneof, this call succeeds if and only if - * that oneof is already part of this msgdef. (Note that adding a oneof to a - * msgdef automatically adds all of its fields to the msgdef at the time that - * the oneof is added, so it is usually more idiomatic to add the oneof's - * fields first then add the oneof to the msgdef. This case is supported for - * convenience.) - * - * If |f| is already part of this MessageDef, this method performs no action - * and returns true (success). Thus, this method is idempotent. */ - bool AddField(FieldDef* f, Status* s); - bool AddField(const reffed_ptr& f, Status* s); - - /* Adds a oneof (upb_oneofdef object) to a msgdef. Requires that the msgdef, - * oneof, and any fielddefs are mutable, that the fielddefs contained in the - * oneof do not have any name or number conflicts with existing fields in the - * msgdef, and that the oneof's name is unique among all oneofs in the msgdef. - * If the oneof is added successfully, all of its fields will be added - * directly to the msgdef as well. In error cases, false is returned and the - * msgdef is unchanged. */ - bool AddOneof(OneofDef* o, Status* s); - bool AddOneof(const reffed_ptr& o, Status* s); - - upb_syntax_t syntax() const; - - /* Returns false if we don't support this syntax value. */ - bool set_syntax(upb_syntax_t syntax); - - /* Set this to false to indicate that primitive fields should not have - * explicit presence information associated with them. This will affect all - * fields added to this message. Defaults to true. */ - void SetPrimitivesHavePresence(bool have_presence); - - /* These return NULL if the field is not found. */ - FieldDef* FindFieldByNumber(uint32_t number); - FieldDef* FindFieldByName(const char *name, size_t len); - const FieldDef* FindFieldByNumber(uint32_t number) const; - const FieldDef* FindFieldByName(const char* name, size_t len) const; - - - FieldDef* FindFieldByName(const char *name) { - return FindFieldByName(name, strlen(name)); - } - const FieldDef* FindFieldByName(const char *name) const { - return FindFieldByName(name, strlen(name)); - } - - template - FieldDef* FindFieldByName(const T& str) { - return FindFieldByName(str.c_str(), str.size()); - } - template - const FieldDef* FindFieldByName(const T& str) const { - return FindFieldByName(str.c_str(), str.size()); - } - - OneofDef* FindOneofByName(const char* name, size_t len); - const OneofDef* FindOneofByName(const char* name, size_t len) const; - - OneofDef* FindOneofByName(const char* name) { - return FindOneofByName(name, strlen(name)); - } - const OneofDef* FindOneofByName(const char* name) const { - return FindOneofByName(name, strlen(name)); - } - - template - OneofDef* FindOneofByName(const T& str) { - return FindOneofByName(str.c_str(), str.size()); - } - template - const OneofDef* FindOneofByName(const T& str) const { - return FindOneofByName(str.c_str(), str.size()); - } - - /* Is this message a map entry? */ - void setmapentry(bool map_entry); - bool mapentry() const; - - /* Iteration over fields. The order is undefined. */ - class field_iterator - : public std::iterator { - public: - explicit field_iterator(MessageDef* md); - static field_iterator end(MessageDef* md); - - void operator++(); - FieldDef* operator*() const; - bool operator!=(const field_iterator& other) const; - bool operator==(const field_iterator& other) const; - - private: - upb_msg_field_iter iter_; - }; - - class const_field_iterator - : public std::iterator { - public: - explicit const_field_iterator(const MessageDef* md); - static const_field_iterator end(const MessageDef* md); - - void operator++(); - const FieldDef* operator*() const; - bool operator!=(const const_field_iterator& other) const; - bool operator==(const const_field_iterator& other) const; - - private: - upb_msg_field_iter iter_; - }; - - /* Iteration over oneofs. The order is undefined. */ - class oneof_iterator - : public std::iterator { - public: - explicit oneof_iterator(MessageDef* md); - static oneof_iterator end(MessageDef* md); - - void operator++(); - OneofDef* operator*() const; - bool operator!=(const oneof_iterator& other) const; - bool operator==(const oneof_iterator& other) const; - - private: - upb_msg_oneof_iter iter_; - }; - - class const_oneof_iterator - : public std::iterator { - public: - explicit const_oneof_iterator(const MessageDef* md); - static const_oneof_iterator end(const MessageDef* md); - - void operator++(); - const OneofDef* operator*() const; - bool operator!=(const const_oneof_iterator& other) const; - bool operator==(const const_oneof_iterator& other) const; - - private: - upb_msg_oneof_iter iter_; - }; - - class FieldAccessor { - public: - explicit FieldAccessor(MessageDef* msg) : msg_(msg) {} - field_iterator begin() { return msg_->field_begin(); } - field_iterator end() { return msg_->field_end(); } - private: - MessageDef* msg_; - }; - - class ConstFieldAccessor { - public: - explicit ConstFieldAccessor(const MessageDef* msg) : msg_(msg) {} - const_field_iterator begin() { return msg_->field_begin(); } - const_field_iterator end() { return msg_->field_end(); } - private: - const MessageDef* msg_; - }; - - class OneofAccessor { - public: - explicit OneofAccessor(MessageDef* msg) : msg_(msg) {} - oneof_iterator begin() { return msg_->oneof_begin(); } - oneof_iterator end() { return msg_->oneof_end(); } - private: - MessageDef* msg_; - }; - - class ConstOneofAccessor { - public: - explicit ConstOneofAccessor(const MessageDef* msg) : msg_(msg) {} - const_oneof_iterator begin() { return msg_->oneof_begin(); } - const_oneof_iterator end() { return msg_->oneof_end(); } - private: - const MessageDef* msg_; - }; - - field_iterator field_begin(); - field_iterator field_end(); - const_field_iterator field_begin() const; - const_field_iterator field_end() const; - - oneof_iterator oneof_begin(); - oneof_iterator oneof_end(); - const_oneof_iterator oneof_begin() const; - const_oneof_iterator oneof_end() const; - - FieldAccessor fields() { return FieldAccessor(this); } - ConstFieldAccessor fields() const { return ConstFieldAccessor(this); } - OneofAccessor oneofs() { return OneofAccessor(this); } - ConstOneofAccessor oneofs() const { return ConstOneofAccessor(this); } - - private: - UPB_DISALLOW_POD_OPS(MessageDef, upb::MessageDef) -}; - -#endif /* __cplusplus */ - -UPB_BEGIN_EXTERN_C - -/* Returns NULL if memory allocation failed. */ -upb_msgdef *upb_msgdef_new(const void *owner); - -/* Include upb_refcounted methods like upb_msgdef_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_msgdef, upb_msgdef_upcast2) - -bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status); - -const char *upb_msgdef_fullname(const upb_msgdef *m); -const char *upb_msgdef_name(const upb_msgdef *m); -int upb_msgdef_numoneofs(const upb_msgdef *m); -upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m); - -bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor, - upb_status *s); -bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, - upb_status *s); -bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, upb_status *s); -void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry); -bool upb_msgdef_mapentry(const upb_msgdef *m); -bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax); - -/* Field lookup in a couple of different variations: - * - itof = int to field - * - ntof = name to field - * - ntofz = name to field, null-terminated string. */ -const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i); -const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name, - size_t len); -int upb_msgdef_numfields(const upb_msgdef *m); - -UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m, - const char *name) { - return upb_msgdef_ntof(m, name, strlen(name)); -} - -UPB_INLINE upb_fielddef *upb_msgdef_itof_mutable(upb_msgdef *m, uint32_t i) { - return (upb_fielddef*)upb_msgdef_itof(m, i); -} - -UPB_INLINE upb_fielddef *upb_msgdef_ntof_mutable(upb_msgdef *m, - const char *name, size_t len) { - return (upb_fielddef *)upb_msgdef_ntof(m, name, len); -} - -/* Oneof lookup: - * - ntoo = name to oneof - * - ntooz = name to oneof, null-terminated string. */ -const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, - size_t len); -int upb_msgdef_numoneofs(const upb_msgdef *m); - -UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m, - const char *name) { - return upb_msgdef_ntoo(m, name, strlen(name)); -} - -UPB_INLINE upb_oneofdef *upb_msgdef_ntoo_mutable(upb_msgdef *m, - const char *name, size_t len) { - return (upb_oneofdef *)upb_msgdef_ntoo(m, name, len); -} - -/* Lookup of either field or oneof by name. Returns whether either was found. - * If the return is true, then the found def will be set, and the non-found - * one set to NULL. */ -bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len, - const upb_fielddef **f, const upb_oneofdef **o); - -UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name, - const upb_fielddef **f, - const upb_oneofdef **o) { - return upb_msgdef_lookupname(m, name, strlen(name), f, o); -} - -/* Iteration over fields and oneofs. For example: - * - * upb_msg_field_iter i; - * for(upb_msg_field_begin(&i, m); - * !upb_msg_field_done(&i); - * upb_msg_field_next(&i)) { - * upb_fielddef *f = upb_msg_iter_field(&i); - * // ... - * } - * - * For C we don't have separate iterators for const and non-const. - * It is the caller's responsibility to cast the upb_fielddef* to - * const if the upb_msgdef* is const. */ -void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m); -void upb_msg_field_next(upb_msg_field_iter *iter); -bool upb_msg_field_done(const upb_msg_field_iter *iter); -upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter); -void upb_msg_field_iter_setdone(upb_msg_field_iter *iter); - -/* Similar to above, we also support iterating through the oneofs in a - * msgdef. */ -void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m); -void upb_msg_oneof_next(upb_msg_oneof_iter *iter); -bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter); -upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter); -void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter); - -UPB_END_EXTERN_C - - -/* upb::EnumDef ***************************************************************/ - -typedef upb_strtable_iter upb_enum_iter; - -#ifdef __cplusplus - -/* Class that represents an enum. Its base class is upb::Def (convert with - * upb::upcast()). */ -class upb::EnumDef { - public: - /* Returns NULL if memory allocation failed. */ - static reffed_ptr New(); - - /* upb::RefCounted methods like Ref()/Unref(). */ - UPB_REFCOUNTED_CPPMETHODS - - /* Functionality from upb::Def. */ - const char* full_name() const; - const char* name() const; - bool set_full_name(const char* fullname, Status* s); - bool set_full_name(const std::string& fullname, Status* s); - - /* Call to freeze this EnumDef. */ - bool Freeze(Status* s); - - /* 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. - * Requires that value_count() > 0. */ - int32_t default_value() const; - - /* Sets the default value. If this value is not valid, returns false and an - * error message in status. */ - bool set_default_value(int32_t val, Status* status); - - /* Returns the number of values currently defined in the enum. Note that - * multiple names can refer to the same number, so this may be greater than - * the total number of unique numbers. */ - int value_count() const; - - /* Adds a single name/number pair to the enum. Fails if this name has - * already been used by another value. */ - bool AddValue(const char* name, int32_t num, Status* status); - bool AddValue(const std::string& name, int32_t num, Status* status); - - /* Lookups from name to integer, returning true if found. */ - bool FindValueByName(const char* name, int32_t* num) const; - - /* Finds the name corresponding to the given number, or NULL if none was - * found. If more than one name corresponds to this number, returns the - * first one that was added. */ - const char* FindValueByNumber(int32_t num) const; - - /* Iteration over name/value pairs. The order is undefined. - * Adding an enum val invalidates any iterators. - * - * TODO: make compatible with range-for, with elements as pairs? */ - class Iterator { - public: - explicit Iterator(const EnumDef*); - - int32_t number(); - const char *name(); - bool Done(); - void Next(); - - private: - upb_enum_iter iter_; - }; - - private: - UPB_DISALLOW_POD_OPS(EnumDef, upb::EnumDef) -}; - -#endif /* __cplusplus */ - -UPB_BEGIN_EXTERN_C - -/* Native C API. */ -upb_enumdef *upb_enumdef_new(const void *owner); - -/* Include upb_refcounted methods like upb_enumdef_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_enumdef, upb_enumdef_upcast2) - -bool upb_enumdef_freeze(upb_enumdef *e, upb_status *status); - -/* From upb_def. */ -const char *upb_enumdef_fullname(const upb_enumdef *e); -const char *upb_enumdef_name(const upb_enumdef *e); -bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname, - upb_status *s); - -int32_t upb_enumdef_default(const upb_enumdef *e); -bool upb_enumdef_setdefault(upb_enumdef *e, int32_t val, upb_status *s); -int upb_enumdef_numvals(const upb_enumdef *e); -bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num, - upb_status *status); - -/* Enum lookups: - * - ntoi: look up a name with specified length. - * - ntoiz: look up a name provided as a null-terminated string. - * - iton: look up an integer, returning the name as a null-terminated - * string. */ -bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len, - int32_t *num); -UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e, - const char *name, int32_t *num) { - return upb_enumdef_ntoi(e, name, strlen(name), num); -} -const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num); - -/* upb_enum_iter i; - * for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) { - * // ... - * } - */ -void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e); -void upb_enum_next(upb_enum_iter *iter); -bool upb_enum_done(upb_enum_iter *iter); -const char *upb_enum_iter_name(upb_enum_iter *iter); -int32_t upb_enum_iter_number(upb_enum_iter *iter); - -UPB_END_EXTERN_C - - -/* upb::OneofDef **************************************************************/ - -typedef upb_inttable_iter upb_oneof_iter; - -#ifdef __cplusplus - -/* Class that represents a oneof. */ -class upb::OneofDef { - public: - /* Returns NULL if memory allocation failed. */ - static reffed_ptr New(); - - /* upb::RefCounted methods like Ref()/Unref(). */ - UPB_REFCOUNTED_CPPMETHODS - - /* Returns the MessageDef that owns this OneofDef. */ - const MessageDef* containing_type() const; - - /* Returns the name of this oneof. This is the name used to look up the oneof - * by name once added to a message def. */ - const char* name() const; - bool set_name(const char* name, Status* s); - bool set_name(const std::string& name, Status* s); - - /* Returns the number of fields currently defined in the oneof. */ - int field_count() const; - - /* Adds a field to the oneof. The field must not have been added to any other - * oneof or msgdef. If the oneof is not yet part of a msgdef, then when the - * oneof is eventually added to a msgdef, all fields added to the oneof will - * also be added to the msgdef at that time. If the oneof is already part of a - * msgdef, the field must either be a part of that msgdef already, or must not - * be a part of any msgdef; in the latter case, the field is added to the - * msgdef as a part of this operation. - * - * The field may only have an OPTIONAL label, never REQUIRED or REPEATED. - * - * If |f| is already part of this MessageDef, this method performs no action - * and returns true (success). Thus, this method is idempotent. */ - bool AddField(FieldDef* field, Status* s); - bool AddField(const reffed_ptr& field, Status* s); - - /* Looks up by name. */ - const FieldDef* FindFieldByName(const char* name, size_t len) const; - FieldDef* FindFieldByName(const char* name, size_t len); - const FieldDef* FindFieldByName(const char* name) const { - return FindFieldByName(name, strlen(name)); - } - FieldDef* FindFieldByName(const char* name) { - return FindFieldByName(name, strlen(name)); - } - - template - FieldDef* FindFieldByName(const T& str) { - return FindFieldByName(str.c_str(), str.size()); - } - template - const FieldDef* FindFieldByName(const T& str) const { - return FindFieldByName(str.c_str(), str.size()); - } - - /* Looks up by tag number. */ - const FieldDef* FindFieldByNumber(uint32_t num) const; - - /* Iteration over fields. The order is undefined. */ - class iterator : public std::iterator { - public: - explicit iterator(OneofDef* md); - static iterator end(OneofDef* md); - - void operator++(); - FieldDef* operator*() const; - bool operator!=(const iterator& other) const; - bool operator==(const iterator& other) const; - - private: - upb_oneof_iter iter_; - }; - - class const_iterator - : public std::iterator { - public: - explicit const_iterator(const OneofDef* md); - static const_iterator end(const OneofDef* md); - - void operator++(); - const FieldDef* operator*() const; - bool operator!=(const const_iterator& other) const; - bool operator==(const const_iterator& other) const; - - private: - upb_oneof_iter iter_; - }; - - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; - - private: - UPB_DISALLOW_POD_OPS(OneofDef, upb::OneofDef) -}; - -#endif /* __cplusplus */ - -UPB_BEGIN_EXTERN_C - -/* Native C API. */ -upb_oneofdef *upb_oneofdef_new(const void *owner); - -/* Include upb_refcounted methods like upb_oneofdef_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_oneofdef, upb_oneofdef_upcast) - -const char *upb_oneofdef_name(const upb_oneofdef *o); -const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o); -int upb_oneofdef_numfields(const upb_oneofdef *o); -uint32_t upb_oneofdef_index(const upb_oneofdef *o); - -bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s); -bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f, - const void *ref_donor, - upb_status *s); - -/* Oneof lookups: - * - ntof: look up a field by name. - * - ntofz: look up a field by name (as a null-terminated string). - * - itof: look up a field by number. */ -const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, - const char *name, size_t length); -UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o, - const char *name) { - return upb_oneofdef_ntof(o, name, strlen(name)); -} -const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num); - -/* upb_oneof_iter i; - * for(upb_oneof_begin(&i, e); !upb_oneof_done(&i); upb_oneof_next(&i)) { - * // ... - * } - */ -void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o); -void upb_oneof_next(upb_oneof_iter *iter); -bool upb_oneof_done(upb_oneof_iter *iter); -upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter); -void upb_oneof_iter_setdone(upb_oneof_iter *iter); - -UPB_END_EXTERN_C - - -/* upb::FileDef ***************************************************************/ - -#ifdef __cplusplus - -/* Class that represents a .proto file with some things defined in it. - * - * Many users won't care about FileDefs, but they are necessary if you want to - * read the values of file-level options. */ -class upb::FileDef { - public: - /* Returns NULL if memory allocation failed. */ - static reffed_ptr New(); - - /* upb::RefCounted methods like Ref()/Unref(). */ - UPB_REFCOUNTED_CPPMETHODS - - /* Get/set name of the file (eg. "foo/bar.proto"). */ - const char* name() const; - bool set_name(const char* name, Status* s); - bool set_name(const std::string& name, Status* s); - - /* Package name for definitions inside the file (eg. "foo.bar"). */ - const char* package() const; - bool set_package(const char* package, Status* s); - - /* Sets the php class prefix which is prepended to all php generated classes - * from this .proto. Default is empty. */ - const char* phpprefix() const; - bool set_phpprefix(const char* phpprefix, Status* s); - - /* Use this option to change the namespace of php generated classes. Default - * is empty. When this option is empty, the package name will be used for - * determining the namespace. */ - const char* phpnamespace() const; - bool set_phpnamespace(const char* phpnamespace, Status* s); - - /* Syntax for the file. Defaults to proto2. */ - upb_syntax_t syntax() const; - void set_syntax(upb_syntax_t syntax); - - /* Get the list of defs from the file. These are returned in the order that - * they were added to the FileDef. */ - int def_count() const; - const Def* def(int index) const; - Def* def(int index); - - /* Get the list of dependencies from the file. These are returned in the - * order that they were added to the FileDef. */ - int dependency_count() const; - const FileDef* dependency(int index) const; - - /* Adds defs to this file. The def must not already belong to another - * file. - * - * Note: this does *not* ensure that this def's name is unique in this file! - * Use a SymbolTable if you want to check this property. Especially since - * properly checking uniqueness would require a check across *all* files - * (including dependencies). */ - bool AddDef(Def* def, Status* s); - bool AddMessage(MessageDef* m, Status* s); - bool AddEnum(EnumDef* e, Status* s); - bool AddExtension(FieldDef* f, Status* s); - - /* Adds a dependency of this file. */ - bool AddDependency(const FileDef* file); - - /* Freezes this FileDef and all messages/enums under it. All subdefs must be - * resolved and all messages/enums must validate. Returns true if this - * succeeded. - * - * TODO(haberman): should we care whether the file's dependencies are frozen - * already? */ - bool Freeze(Status* s); - - private: - UPB_DISALLOW_POD_OPS(FileDef, upb::FileDef) -}; - -#endif - -UPB_BEGIN_EXTERN_C - -upb_filedef *upb_filedef_new(const void *owner); - -/* Include upb_refcounted methods like upb_msgdef_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_filedef, upb_filedef_upcast) - -const char *upb_filedef_name(const upb_filedef *f); -const char *upb_filedef_package(const upb_filedef *f); -const char *upb_filedef_phpprefix(const upb_filedef *f); -const char *upb_filedef_phpnamespace(const upb_filedef *f); -upb_syntax_t upb_filedef_syntax(const upb_filedef *f); -size_t upb_filedef_defcount(const upb_filedef *f); -size_t upb_filedef_depcount(const upb_filedef *f); -const upb_def *upb_filedef_def(const upb_filedef *f, size_t i); -const upb_filedef *upb_filedef_dep(const upb_filedef *f, size_t i); - -bool upb_filedef_freeze(upb_filedef *f, upb_status *s); -bool upb_filedef_setname(upb_filedef *f, const char *name, upb_status *s); -bool upb_filedef_setpackage(upb_filedef *f, const char *package, upb_status *s); -bool upb_filedef_setphpprefix(upb_filedef *f, const char *phpprefix, - upb_status *s); -bool upb_filedef_setphpnamespace(upb_filedef *f, const char *phpnamespace, - upb_status *s); -bool upb_filedef_setsyntax(upb_filedef *f, upb_syntax_t syntax, upb_status *s); - -bool upb_filedef_adddef(upb_filedef *f, upb_def *def, const void *ref_donor, - upb_status *s); -bool upb_filedef_adddep(upb_filedef *f, const upb_filedef *dep); - -UPB_INLINE bool upb_filedef_addmsg(upb_filedef *f, upb_msgdef *m, - const void *ref_donor, upb_status *s) { - return upb_filedef_adddef(f, upb_msgdef_upcast_mutable(m), ref_donor, s); -} - -UPB_INLINE bool upb_filedef_addenum(upb_filedef *f, upb_enumdef *e, - const void *ref_donor, upb_status *s) { - return upb_filedef_adddef(f, upb_enumdef_upcast_mutable(e), ref_donor, s); -} - -UPB_INLINE bool upb_filedef_addext(upb_filedef *file, upb_fielddef *f, - const void *ref_donor, upb_status *s) { - return upb_filedef_adddef(file, upb_fielddef_upcast_mutable(f), ref_donor, s); -} -UPB_INLINE upb_def *upb_filedef_mutabledef(upb_filedef *f, int i) { - return (upb_def*)upb_filedef_def(f, i); -} - -UPB_END_EXTERN_C - -typedef struct { - UPB_PRIVATE_FOR_CPP - upb_strtable_iter iter; - upb_deftype_t type; -} upb_symtab_iter; - -#ifdef __cplusplus - -/* Non-const methods in upb::SymbolTable are NOT thread-safe. */ -class upb::SymbolTable { - public: - /* Returns a new symbol table with a single ref owned by "owner." - * Returns NULL if memory allocation failed. */ - static SymbolTable* New(); - static void Free(upb::SymbolTable* table); - - /* For all lookup functions, the returned pointer is not owned by the - * caller; it may be invalidated by any non-const call or unref of the - * SymbolTable! To protect against this, take a ref if desired. */ - - /* Freezes the symbol table: prevents further modification of it. - * After the Freeze() operation is successful, the SymbolTable must only be - * accessed via a const pointer. - * - * Unlike with upb::MessageDef/upb::EnumDef/etc, freezing a SymbolTable is not - * a necessary step in using a SymbolTable. If you have no need for it to be - * immutable, there is no need to freeze it ever. However sometimes it is - * useful, and SymbolTables that are statically compiled into the binary are - * always frozen by nature. */ - void Freeze(); - - /* Resolves the given symbol using the rules described in descriptor.proto, - * namely: - * - * If the name starts with a '.', it is fully-qualified. Otherwise, - * C++-like scoping rules are used to find the type (i.e. first the nested - * types within this message are searched, then within the parent, on up - * to the root namespace). - * - * If not found, returns NULL. */ - const Def* Resolve(const char* base, const char* sym) const; - - /* Finds an entry in the symbol table with this exact name. If not found, - * returns NULL. */ - const Def* Lookup(const char *sym) const; - const MessageDef* LookupMessage(const char *sym) const; - const EnumDef* LookupEnum(const char *sym) const; - - /* TODO: introduce a C++ iterator, but make it nice and templated so that if - * you ask for an iterator of MessageDef the iterated elements are strongly - * typed as MessageDef*. */ - - /* Adds the given mutable defs to the symtab, resolving all symbols (including - * enum default values) and finalizing the defs. Only one def per name may be - * in the list, and the defs may not duplicate any name already in the symtab. - * All defs must have a name -- anonymous defs are not allowed. Anonymous - * defs can still be frozen by calling upb_def_freeze() directly. - * - * The entire operation either succeeds or fails. If the operation fails, - * the symtab is unchanged, false is returned, and status indicates the - * error. The caller passes a ref on all defs to the symtab (even if the - * operation fails). - * - * TODO(haberman): currently failure will leave the symtab unchanged, but may - * leave the defs themselves partially resolved. Does this matter? If so we - * could do a prepass that ensures that all symbols are resolvable and bail - * if not, so we don't mutate anything until we know the operation will - * succeed. */ - bool Add(Def*const* defs, size_t n, void* ref_donor, Status* status); - - bool Add(const std::vector& defs, void *owner, Status* status) { - return Add((Def*const*)&defs[0], defs.size(), owner, status); - } - - /* Resolves all subdefs for messages in this file and attempts to freeze the - * file. If this succeeds, adds all the symbols to this SymbolTable - * (replacing any existing ones with the same names). */ - bool AddFile(FileDef* file, Status* s); - - private: - UPB_DISALLOW_POD_OPS(SymbolTable, upb::SymbolTable) -}; - -#endif /* __cplusplus */ - -UPB_BEGIN_EXTERN_C - -/* Native C API. */ - -upb_symtab *upb_symtab_new(); -void upb_symtab_free(upb_symtab* s); -const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, - const char *sym); -const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym); -const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym); -const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym); -bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, size_t n, - void *ref_donor, upb_status *status); -bool upb_symtab_addfile(upb_symtab *s, upb_filedef *file, upb_status* status); - -/* upb_symtab_iter i; - * for(upb_symtab_begin(&i, s, type); !upb_symtab_done(&i); - * upb_symtab_next(&i)) { - * const upb_def *def = upb_symtab_iter_def(&i); - * // ... - * } - * - * For C we don't have separate iterators for const and non-const. - * It is the caller's responsibility to cast the upb_fielddef* to - * const if the upb_msgdef* is const. */ -void upb_symtab_begin(upb_symtab_iter *iter, const upb_symtab *s, - upb_deftype_t type); -void upb_symtab_next(upb_symtab_iter *iter); -bool upb_symtab_done(const upb_symtab_iter *iter); -const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter); - -UPB_END_EXTERN_C - -#ifdef __cplusplus -/* C++ inline wrappers. */ -namespace upb { -inline SymbolTable* SymbolTable::New() { - return upb_symtab_new(); -} -inline void SymbolTable::Free(SymbolTable* s) { - upb_symtab_free(s); -} -inline const Def *SymbolTable::Resolve(const char *base, - const char *sym) const { - return upb_symtab_resolve(this, base, sym); -} -inline const Def* SymbolTable::Lookup(const char *sym) const { - return upb_symtab_lookup(this, sym); -} -inline const MessageDef *SymbolTable::LookupMessage(const char *sym) const { - return upb_symtab_lookupmsg(this, sym); -} -inline bool SymbolTable::Add( - Def*const* defs, size_t n, void* ref_donor, Status* status) { - return upb_symtab_add(this, (upb_def*const*)defs, n, ref_donor, status); -} -inline bool SymbolTable::AddFile(FileDef* file, Status* s) { - return upb_symtab_addfile(this, file, s); -} -} /* namespace upb */ -#endif - -#ifdef __cplusplus - -UPB_INLINE const char* upb_safecstr(const std::string& str) { - UPB_ASSERT(str.size() == std::strlen(str.c_str())); - return str.c_str(); -} - -/* Inline C++ wrappers. */ -namespace upb { - -inline Def::Type Def::def_type() const { return upb_def_type(this); } -inline const char* Def::full_name() const { return upb_def_fullname(this); } -inline const char* Def::name() const { return upb_def_name(this); } -inline bool Def::set_full_name(const char* fullname, Status* s) { - return upb_def_setfullname(this, fullname, s); -} -inline bool Def::set_full_name(const std::string& fullname, Status* s) { - return upb_def_setfullname(this, upb_safecstr(fullname), s); -} -inline bool Def::Freeze(Def* const* defs, size_t n, Status* status) { - return upb_def_freeze(defs, n, status); -} -inline bool Def::Freeze(const std::vector& defs, Status* status) { - return upb_def_freeze((Def* const*)&defs[0], defs.size(), status); -} - -inline bool FieldDef::CheckType(int32_t val) { - return upb_fielddef_checktype(val); -} -inline bool FieldDef::CheckLabel(int32_t val) { - return upb_fielddef_checklabel(val); -} -inline bool FieldDef::CheckDescriptorType(int32_t val) { - return upb_fielddef_checkdescriptortype(val); -} -inline bool FieldDef::CheckIntegerFormat(int32_t val) { - return upb_fielddef_checkintfmt(val); -} -inline FieldDef::Type FieldDef::ConvertType(int32_t val) { - UPB_ASSERT(CheckType(val)); - return static_cast(val); -} -inline FieldDef::Label FieldDef::ConvertLabel(int32_t val) { - UPB_ASSERT(CheckLabel(val)); - return static_cast(val); -} -inline FieldDef::DescriptorType FieldDef::ConvertDescriptorType(int32_t val) { - UPB_ASSERT(CheckDescriptorType(val)); - return static_cast(val); -} -inline FieldDef::IntegerFormat FieldDef::ConvertIntegerFormat(int32_t val) { - UPB_ASSERT(CheckIntegerFormat(val)); - return static_cast(val); -} - -inline reffed_ptr FieldDef::New() { - upb_fielddef *f = upb_fielddef_new(&f); - return reffed_ptr(f, &f); -} -inline const char* FieldDef::full_name() const { - return upb_fielddef_fullname(this); -} -inline bool FieldDef::set_full_name(const char* fullname, Status* s) { - return upb_fielddef_setfullname(this, fullname, s); -} -inline bool FieldDef::set_full_name(const std::string& fullname, Status* s) { - return upb_fielddef_setfullname(this, upb_safecstr(fullname), s); -} -inline bool FieldDef::type_is_set() const { - return upb_fielddef_typeisset(this); -} -inline FieldDef::Type FieldDef::type() const { return upb_fielddef_type(this); } -inline FieldDef::DescriptorType FieldDef::descriptor_type() const { - return upb_fielddef_descriptortype(this); -} -inline FieldDef::Label FieldDef::label() const { - return upb_fielddef_label(this); -} -inline uint32_t FieldDef::number() const { return upb_fielddef_number(this); } -inline const char* FieldDef::name() const { return upb_fielddef_name(this); } -inline bool FieldDef::is_extension() const { - return upb_fielddef_isextension(this); -} -inline size_t FieldDef::GetJsonName(char* buf, size_t len) const { - return upb_fielddef_getjsonname(this, buf, len); -} -inline bool FieldDef::lazy() const { - return upb_fielddef_lazy(this); -} -inline void FieldDef::set_lazy(bool lazy) { - upb_fielddef_setlazy(this, lazy); -} -inline bool FieldDef::packed() const { - return upb_fielddef_packed(this); -} -inline uint32_t FieldDef::index() const { - return upb_fielddef_index(this); -} -inline void FieldDef::set_packed(bool packed) { - upb_fielddef_setpacked(this, packed); -} -inline const MessageDef* FieldDef::containing_type() const { - return upb_fielddef_containingtype(this); -} -inline const OneofDef* FieldDef::containing_oneof() const { - return upb_fielddef_containingoneof(this); -} -inline const char* FieldDef::containing_type_name() { - return upb_fielddef_containingtypename(this); -} -inline bool FieldDef::set_number(uint32_t number, Status* s) { - return upb_fielddef_setnumber(this, number, s); -} -inline bool FieldDef::set_name(const char *name, Status* s) { - return upb_fielddef_setname(this, name, s); -} -inline bool FieldDef::set_name(const std::string& name, Status* s) { - return upb_fielddef_setname(this, upb_safecstr(name), s); -} -inline bool FieldDef::set_json_name(const char *name, Status* s) { - return upb_fielddef_setjsonname(this, name, s); -} -inline bool FieldDef::set_json_name(const std::string& name, Status* s) { - return upb_fielddef_setjsonname(this, upb_safecstr(name), s); -} -inline void FieldDef::clear_json_name() { - upb_fielddef_clearjsonname(this); -} -inline bool FieldDef::set_containing_type_name(const char *name, Status* s) { - return upb_fielddef_setcontainingtypename(this, name, s); -} -inline bool FieldDef::set_containing_type_name(const std::string &name, - Status *s) { - return upb_fielddef_setcontainingtypename(this, upb_safecstr(name), s); -} -inline void FieldDef::set_type(upb_fieldtype_t type) { - upb_fielddef_settype(this, type); -} -inline void FieldDef::set_is_extension(bool is_extension) { - upb_fielddef_setisextension(this, is_extension); -} -inline void FieldDef::set_descriptor_type(FieldDef::DescriptorType type) { - upb_fielddef_setdescriptortype(this, type); -} -inline void FieldDef::set_label(upb_label_t label) { - upb_fielddef_setlabel(this, label); -} -inline bool FieldDef::IsSubMessage() const { - return upb_fielddef_issubmsg(this); -} -inline bool FieldDef::IsString() const { return upb_fielddef_isstring(this); } -inline bool FieldDef::IsSequence() const { return upb_fielddef_isseq(this); } -inline bool FieldDef::IsMap() const { return upb_fielddef_ismap(this); } -inline int64_t FieldDef::default_int64() const { - return upb_fielddef_defaultint64(this); -} -inline int32_t FieldDef::default_int32() const { - return upb_fielddef_defaultint32(this); -} -inline uint64_t FieldDef::default_uint64() const { - return upb_fielddef_defaultuint64(this); -} -inline uint32_t FieldDef::default_uint32() const { - return upb_fielddef_defaultuint32(this); -} -inline bool FieldDef::default_bool() const { - return upb_fielddef_defaultbool(this); -} -inline float FieldDef::default_float() const { - return upb_fielddef_defaultfloat(this); -} -inline double FieldDef::default_double() const { - return upb_fielddef_defaultdouble(this); -} -inline const char* FieldDef::default_string(size_t* len) const { - return upb_fielddef_defaultstr(this, len); -} -inline void FieldDef::set_default_int64(int64_t value) { - upb_fielddef_setdefaultint64(this, value); -} -inline void FieldDef::set_default_int32(int32_t value) { - upb_fielddef_setdefaultint32(this, value); -} -inline void FieldDef::set_default_uint64(uint64_t value) { - upb_fielddef_setdefaultuint64(this, value); -} -inline void FieldDef::set_default_uint32(uint32_t value) { - upb_fielddef_setdefaultuint32(this, value); -} -inline void FieldDef::set_default_bool(bool value) { - upb_fielddef_setdefaultbool(this, value); -} -inline void FieldDef::set_default_float(float value) { - upb_fielddef_setdefaultfloat(this, value); -} -inline void FieldDef::set_default_double(double value) { - upb_fielddef_setdefaultdouble(this, value); -} -inline bool FieldDef::set_default_string(const void *str, size_t len, - Status *s) { - return upb_fielddef_setdefaultstr(this, str, len, s); -} -inline bool FieldDef::set_default_string(const std::string& str, Status* s) { - return upb_fielddef_setdefaultstr(this, str.c_str(), str.size(), s); -} -inline void FieldDef::set_default_cstr(const char* str, Status* s) { - return upb_fielddef_setdefaultcstr(this, str, s); -} -inline bool FieldDef::HasSubDef() const { return upb_fielddef_hassubdef(this); } -inline const Def* FieldDef::subdef() const { return upb_fielddef_subdef(this); } -inline const MessageDef *FieldDef::message_subdef() const { - return upb_fielddef_msgsubdef(this); -} -inline const EnumDef *FieldDef::enum_subdef() const { - return upb_fielddef_enumsubdef(this); -} -inline const char* FieldDef::subdef_name() const { - return upb_fielddef_subdefname(this); -} -inline bool FieldDef::set_subdef(const Def* subdef, Status* s) { - return upb_fielddef_setsubdef(this, subdef, s); -} -inline bool FieldDef::set_enum_subdef(const EnumDef* subdef, Status* s) { - return upb_fielddef_setenumsubdef(this, subdef, s); -} -inline bool FieldDef::set_message_subdef(const MessageDef* subdef, Status* s) { - return upb_fielddef_setmsgsubdef(this, subdef, s); -} -inline bool FieldDef::set_subdef_name(const char* name, Status* s) { - return upb_fielddef_setsubdefname(this, name, s); -} -inline bool FieldDef::set_subdef_name(const std::string& name, Status* s) { - return upb_fielddef_setsubdefname(this, upb_safecstr(name), s); -} - -inline reffed_ptr MessageDef::New() { - upb_msgdef *m = upb_msgdef_new(&m); - return reffed_ptr(m, &m); -} -inline const char *MessageDef::full_name() const { - return upb_msgdef_fullname(this); -} -inline const char *MessageDef::name() const { - return upb_msgdef_name(this); -} -inline upb_syntax_t MessageDef::syntax() const { - return upb_msgdef_syntax(this); -} -inline bool MessageDef::set_full_name(const char* fullname, Status* s) { - return upb_msgdef_setfullname(this, fullname, s); -} -inline bool MessageDef::set_full_name(const std::string& fullname, Status* s) { - return upb_msgdef_setfullname(this, upb_safecstr(fullname), s); -} -inline bool MessageDef::set_syntax(upb_syntax_t syntax) { - return upb_msgdef_setsyntax(this, syntax); -} -inline bool MessageDef::Freeze(Status* status) { - return upb_msgdef_freeze(this, status); -} -inline int MessageDef::field_count() const { - return upb_msgdef_numfields(this); -} -inline int MessageDef::oneof_count() const { - return upb_msgdef_numoneofs(this); -} -inline bool MessageDef::AddField(upb_fielddef* f, Status* s) { - return upb_msgdef_addfield(this, f, NULL, s); -} -inline bool MessageDef::AddField(const reffed_ptr& f, Status* s) { - return upb_msgdef_addfield(this, f.get(), NULL, s); -} -inline bool MessageDef::AddOneof(upb_oneofdef* o, Status* s) { - return upb_msgdef_addoneof(this, o, NULL, s); -} -inline bool MessageDef::AddOneof(const reffed_ptr& o, Status* s) { - return upb_msgdef_addoneof(this, o.get(), NULL, s); -} -inline FieldDef* MessageDef::FindFieldByNumber(uint32_t number) { - return upb_msgdef_itof_mutable(this, number); -} -inline FieldDef* MessageDef::FindFieldByName(const char* name, size_t len) { - return upb_msgdef_ntof_mutable(this, name, len); -} -inline const FieldDef* MessageDef::FindFieldByNumber(uint32_t number) const { - return upb_msgdef_itof(this, number); -} -inline const FieldDef *MessageDef::FindFieldByName(const char *name, - size_t len) const { - return upb_msgdef_ntof(this, name, len); -} -inline OneofDef* MessageDef::FindOneofByName(const char* name, size_t len) { - return upb_msgdef_ntoo_mutable(this, name, len); -} -inline const OneofDef* MessageDef::FindOneofByName(const char* name, - size_t len) const { - return upb_msgdef_ntoo(this, name, len); -} -inline void MessageDef::setmapentry(bool map_entry) { - upb_msgdef_setmapentry(this, map_entry); -} -inline bool MessageDef::mapentry() const { - return upb_msgdef_mapentry(this); -} -inline MessageDef::field_iterator MessageDef::field_begin() { - return field_iterator(this); -} -inline MessageDef::field_iterator MessageDef::field_end() { - return field_iterator::end(this); -} -inline MessageDef::const_field_iterator MessageDef::field_begin() const { - return const_field_iterator(this); -} -inline MessageDef::const_field_iterator MessageDef::field_end() const { - return const_field_iterator::end(this); -} - -inline MessageDef::oneof_iterator MessageDef::oneof_begin() { - return oneof_iterator(this); -} -inline MessageDef::oneof_iterator MessageDef::oneof_end() { - return oneof_iterator::end(this); -} -inline MessageDef::const_oneof_iterator MessageDef::oneof_begin() const { - return const_oneof_iterator(this); -} -inline MessageDef::const_oneof_iterator MessageDef::oneof_end() const { - return const_oneof_iterator::end(this); -} - -inline MessageDef::field_iterator::field_iterator(MessageDef* md) { - upb_msg_field_begin(&iter_, md); -} -inline MessageDef::field_iterator MessageDef::field_iterator::end( - MessageDef* md) { - MessageDef::field_iterator iter(md); - upb_msg_field_iter_setdone(&iter.iter_); - return iter; -} -inline FieldDef* MessageDef::field_iterator::operator*() const { - return upb_msg_iter_field(&iter_); -} -inline void MessageDef::field_iterator::operator++() { - return upb_msg_field_next(&iter_); -} -inline bool MessageDef::field_iterator::operator==( - const field_iterator &other) const { - return upb_inttable_iter_isequal(&iter_, &other.iter_); -} -inline bool MessageDef::field_iterator::operator!=( - const field_iterator &other) const { - return !(*this == other); -} - -inline MessageDef::const_field_iterator::const_field_iterator( - const MessageDef* md) { - upb_msg_field_begin(&iter_, md); -} -inline MessageDef::const_field_iterator MessageDef::const_field_iterator::end( - const MessageDef *md) { - MessageDef::const_field_iterator iter(md); - upb_msg_field_iter_setdone(&iter.iter_); - return iter; -} -inline const FieldDef* MessageDef::const_field_iterator::operator*() const { - return upb_msg_iter_field(&iter_); -} -inline void MessageDef::const_field_iterator::operator++() { - return upb_msg_field_next(&iter_); -} -inline bool MessageDef::const_field_iterator::operator==( - const const_field_iterator &other) const { - return upb_inttable_iter_isequal(&iter_, &other.iter_); -} -inline bool MessageDef::const_field_iterator::operator!=( - const const_field_iterator &other) const { - return !(*this == other); -} - -inline MessageDef::oneof_iterator::oneof_iterator(MessageDef* md) { - upb_msg_oneof_begin(&iter_, md); -} -inline MessageDef::oneof_iterator MessageDef::oneof_iterator::end( - MessageDef* md) { - MessageDef::oneof_iterator iter(md); - upb_msg_oneof_iter_setdone(&iter.iter_); - return iter; -} -inline OneofDef* MessageDef::oneof_iterator::operator*() const { - return upb_msg_iter_oneof(&iter_); -} -inline void MessageDef::oneof_iterator::operator++() { - return upb_msg_oneof_next(&iter_); -} -inline bool MessageDef::oneof_iterator::operator==( - const oneof_iterator &other) const { - return upb_strtable_iter_isequal(&iter_, &other.iter_); -} -inline bool MessageDef::oneof_iterator::operator!=( - const oneof_iterator &other) const { - return !(*this == other); -} - -inline MessageDef::const_oneof_iterator::const_oneof_iterator( - const MessageDef* md) { - upb_msg_oneof_begin(&iter_, md); -} -inline MessageDef::const_oneof_iterator MessageDef::const_oneof_iterator::end( - const MessageDef *md) { - MessageDef::const_oneof_iterator iter(md); - upb_msg_oneof_iter_setdone(&iter.iter_); - return iter; -} -inline const OneofDef* MessageDef::const_oneof_iterator::operator*() const { - return upb_msg_iter_oneof(&iter_); -} -inline void MessageDef::const_oneof_iterator::operator++() { - return upb_msg_oneof_next(&iter_); -} -inline bool MessageDef::const_oneof_iterator::operator==( - const const_oneof_iterator &other) const { - return upb_strtable_iter_isequal(&iter_, &other.iter_); -} -inline bool MessageDef::const_oneof_iterator::operator!=( - const const_oneof_iterator &other) const { - return !(*this == other); -} - -inline reffed_ptr EnumDef::New() { - upb_enumdef *e = upb_enumdef_new(&e); - return reffed_ptr(e, &e); -} -inline const char* EnumDef::full_name() const { - return upb_enumdef_fullname(this); -} -inline const char* EnumDef::name() const { - return upb_enumdef_name(this); -} -inline bool EnumDef::set_full_name(const char* fullname, Status* s) { - return upb_enumdef_setfullname(this, fullname, s); -} -inline bool EnumDef::set_full_name(const std::string& fullname, Status* s) { - return upb_enumdef_setfullname(this, upb_safecstr(fullname), s); -} -inline bool EnumDef::Freeze(Status* status) { - return upb_enumdef_freeze(this, status); -} -inline int32_t EnumDef::default_value() const { - return upb_enumdef_default(this); -} -inline bool EnumDef::set_default_value(int32_t val, Status* status) { - return upb_enumdef_setdefault(this, val, status); -} -inline int EnumDef::value_count() const { return upb_enumdef_numvals(this); } -inline bool EnumDef::AddValue(const char* name, int32_t num, Status* status) { - return upb_enumdef_addval(this, name, num, status); -} -inline bool EnumDef::AddValue(const std::string& name, int32_t num, - Status* status) { - return upb_enumdef_addval(this, upb_safecstr(name), num, status); -} -inline bool EnumDef::FindValueByName(const char* name, int32_t *num) const { - return upb_enumdef_ntoiz(this, name, num); -} -inline const char* EnumDef::FindValueByNumber(int32_t num) const { - return upb_enumdef_iton(this, num); -} - -inline EnumDef::Iterator::Iterator(const EnumDef* e) { - upb_enum_begin(&iter_, e); -} -inline int32_t EnumDef::Iterator::number() { - return upb_enum_iter_number(&iter_); -} -inline const char* EnumDef::Iterator::name() { - return upb_enum_iter_name(&iter_); -} -inline bool EnumDef::Iterator::Done() { return upb_enum_done(&iter_); } -inline void EnumDef::Iterator::Next() { return upb_enum_next(&iter_); } - -inline reffed_ptr OneofDef::New() { - upb_oneofdef *o = upb_oneofdef_new(&o); - return reffed_ptr(o, &o); -} - -inline const MessageDef* OneofDef::containing_type() const { - return upb_oneofdef_containingtype(this); -} -inline const char* OneofDef::name() const { - return upb_oneofdef_name(this); -} -inline bool OneofDef::set_name(const char* name, Status* s) { - return upb_oneofdef_setname(this, name, s); -} -inline bool OneofDef::set_name(const std::string& name, Status* s) { - return upb_oneofdef_setname(this, upb_safecstr(name), s); -} -inline int OneofDef::field_count() const { - return upb_oneofdef_numfields(this); -} -inline bool OneofDef::AddField(FieldDef* field, Status* s) { - return upb_oneofdef_addfield(this, field, NULL, s); -} -inline bool OneofDef::AddField(const reffed_ptr& field, Status* s) { - return upb_oneofdef_addfield(this, field.get(), NULL, s); -} -inline const FieldDef* OneofDef::FindFieldByName(const char* name, - size_t len) const { - return upb_oneofdef_ntof(this, name, len); -} -inline const FieldDef* OneofDef::FindFieldByNumber(uint32_t num) const { - return upb_oneofdef_itof(this, num); -} -inline OneofDef::iterator OneofDef::begin() { return iterator(this); } -inline OneofDef::iterator OneofDef::end() { return iterator::end(this); } -inline OneofDef::const_iterator OneofDef::begin() const { - return const_iterator(this); -} -inline OneofDef::const_iterator OneofDef::end() const { - return const_iterator::end(this); -} - -inline OneofDef::iterator::iterator(OneofDef* o) { - upb_oneof_begin(&iter_, o); -} -inline OneofDef::iterator OneofDef::iterator::end(OneofDef* o) { - OneofDef::iterator iter(o); - upb_oneof_iter_setdone(&iter.iter_); - return iter; -} -inline FieldDef* OneofDef::iterator::operator*() const { - return upb_oneof_iter_field(&iter_); -} -inline void OneofDef::iterator::operator++() { return upb_oneof_next(&iter_); } -inline bool OneofDef::iterator::operator==(const iterator &other) const { - return upb_inttable_iter_isequal(&iter_, &other.iter_); -} -inline bool OneofDef::iterator::operator!=(const iterator &other) const { - return !(*this == other); -} - -inline OneofDef::const_iterator::const_iterator(const OneofDef* md) { - upb_oneof_begin(&iter_, md); -} -inline OneofDef::const_iterator OneofDef::const_iterator::end( - const OneofDef *md) { - OneofDef::const_iterator iter(md); - upb_oneof_iter_setdone(&iter.iter_); - return iter; -} -inline const FieldDef* OneofDef::const_iterator::operator*() const { - return upb_msg_iter_field(&iter_); -} -inline void OneofDef::const_iterator::operator++() { - return upb_oneof_next(&iter_); -} -inline bool OneofDef::const_iterator::operator==( - const const_iterator &other) const { - return upb_inttable_iter_isequal(&iter_, &other.iter_); -} -inline bool OneofDef::const_iterator::operator!=( - const const_iterator &other) const { - return !(*this == other); -} - -inline reffed_ptr FileDef::New() { - upb_filedef *f = upb_filedef_new(&f); - return reffed_ptr(f, &f); -} - -inline const char* FileDef::name() const { - return upb_filedef_name(this); -} -inline bool FileDef::set_name(const char* name, Status* s) { - return upb_filedef_setname(this, name, s); -} -inline bool FileDef::set_name(const std::string& name, Status* s) { - return upb_filedef_setname(this, upb_safecstr(name), s); -} -inline const char* FileDef::package() const { - return upb_filedef_package(this); -} -inline bool FileDef::set_package(const char* package, Status* s) { - return upb_filedef_setpackage(this, package, s); -} -inline const char* FileDef::phpprefix() const { - return upb_filedef_phpprefix(this); -} -inline bool FileDef::set_phpprefix(const char* phpprefix, Status* s) { - return upb_filedef_setphpprefix(this, phpprefix, s); -} -inline const char* FileDef::phpnamespace() const { - return upb_filedef_phpnamespace(this); -} -inline bool FileDef::set_phpnamespace(const char* phpnamespace, Status* s) { - return upb_filedef_setphpnamespace(this, phpnamespace, s); -} -inline int FileDef::def_count() const { - return upb_filedef_defcount(this); -} -inline const Def* FileDef::def(int index) const { - return upb_filedef_def(this, index); -} -inline Def* FileDef::def(int index) { - return const_cast(upb_filedef_def(this, index)); -} -inline int FileDef::dependency_count() const { - return upb_filedef_depcount(this); -} -inline const FileDef* FileDef::dependency(int index) const { - return upb_filedef_dep(this, index); -} -inline bool FileDef::AddDef(Def* def, Status* s) { - return upb_filedef_adddef(this, def, NULL, s); -} -inline bool FileDef::AddMessage(MessageDef* m, Status* s) { - return upb_filedef_addmsg(this, m, NULL, s); -} -inline bool FileDef::AddEnum(EnumDef* e, Status* s) { - return upb_filedef_addenum(this, e, NULL, s); -} -inline bool FileDef::AddExtension(FieldDef* f, Status* s) { - return upb_filedef_addext(this, f, NULL, s); -} -inline bool FileDef::AddDependency(const FileDef* file) { - return upb_filedef_adddep(this, file); -} - -} /* namespace upb */ -#endif - -#endif /* UPB_DEF_H_ */ -/* -** This file contains definitions of structs that should be considered private -** and NOT stable across versions of upb. -** -** The only reason they are declared here and not in .c files is to allow upb -** and the application (if desired) to embed statically-initialized instances -** of structures like defs. -** -** If you include this file, all guarantees of ABI compatibility go out the -** window! Any code that includes this file needs to recompile against the -** exact same version of upb that they are linking against. -** -** You also need to recompile if you change the value of the UPB_DEBUG_REFS -** flag. -*/ - - -#ifndef UPB_STATICINIT_H_ -#define UPB_STATICINIT_H_ - -#ifdef __cplusplus -/* Because of how we do our typedefs, this header can't be included from C++. */ -#error This file cannot be included from C++ -#endif - -/* upb_refcounted *************************************************************/ - - -/* upb_def ********************************************************************/ - -struct upb_def { - upb_refcounted base; - - const char *fullname; - const upb_filedef* file; - char type; /* A upb_deftype_t (char to save space) */ - - /* Used as a flag during the def's mutable stage. Must be false unless - * it is currently being used by a function on the stack. This allows - * us to easily determine which defs were passed into the function's - * current invocation. */ - bool came_from_user; -}; - -#define UPB_DEF_INIT(name, type, vtbl, refs, ref2s) \ - { UPB_REFCOUNT_INIT(vtbl, refs, ref2s), name, NULL, type, false } - - -/* upb_fielddef ***************************************************************/ - -struct upb_fielddef { - upb_def base; - - union { - int64_t sint; - uint64_t uint; - double dbl; - float flt; - void *bytes; - } defaultval; - union { - const upb_msgdef *def; /* If !msg_is_symbolic. */ - char *name; /* If msg_is_symbolic. */ - } msg; - union { - const upb_def *def; /* If !subdef_is_symbolic. */ - char *name; /* If subdef_is_symbolic. */ - } sub; /* The msgdef or enumdef for this field, if upb_hassubdef(f). */ - bool subdef_is_symbolic; - bool msg_is_symbolic; - const upb_oneofdef *oneof; - bool default_is_string; - bool type_is_set_; /* False until type is explicitly set. */ - bool is_extension_; - bool lazy_; - bool packed_; - upb_intfmt_t intfmt; - bool tagdelim; - upb_fieldtype_t type_; - upb_label_t label_; - uint32_t number_; - uint32_t selector_base; /* Used to index into a upb::Handlers table. */ - uint32_t index_; -}; - -extern const struct upb_refcounted_vtbl upb_fielddef_vtbl; - -#define UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, lazy, \ - packed, name, num, msgdef, subdef, selector_base, \ - index, defaultval, refs, ref2s) \ - { \ - UPB_DEF_INIT(name, UPB_DEF_FIELD, &upb_fielddef_vtbl, refs, ref2s), \ - defaultval, {msgdef}, {subdef}, NULL, false, false, \ - type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES, true, is_extension, \ - lazy, packed, intfmt, tagdelim, type, label, num, selector_base, index \ - } - - -/* upb_msgdef *****************************************************************/ - -struct upb_msgdef { - upb_def base; - - size_t selector_count; - uint32_t submsg_field_count; - - /* Tables for looking up fields by number and name. */ - upb_inttable itof; /* int to field */ - upb_strtable ntof; /* name to field/oneof */ - - /* Is this a map-entry message? */ - bool map_entry; - - /* Whether this message has proto2 or proto3 semantics. */ - upb_syntax_t syntax; - - /* TODO(haberman): proper extension ranges (there can be multiple). */ -}; - -extern const struct upb_refcounted_vtbl upb_msgdef_vtbl; - -/* TODO: also support static initialization of the oneofs table. This will be - * needed if we compile in descriptors that contain oneofs. */ -#define UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof, \ - map_entry, syntax, refs, ref2s) \ - { \ - UPB_DEF_INIT(name, UPB_DEF_MSG, &upb_fielddef_vtbl, refs, ref2s), \ - selector_count, submsg_field_count, itof, ntof, map_entry, syntax \ - } - - -/* upb_enumdef ****************************************************************/ - -struct upb_enumdef { - upb_def base; - - upb_strtable ntoi; - upb_inttable iton; - int32_t defaultval; -}; - -extern const struct upb_refcounted_vtbl upb_enumdef_vtbl; - -#define UPB_ENUMDEF_INIT(name, ntoi, iton, defaultval, refs, ref2s) \ - { UPB_DEF_INIT(name, UPB_DEF_ENUM, &upb_enumdef_vtbl, refs, ref2s), ntoi, \ - iton, defaultval } - - -/* upb_oneofdef ***************************************************************/ - -struct upb_oneofdef { - upb_refcounted base; - - uint32_t index; /* Index within oneofs. */ - const char *name; - upb_strtable ntof; - upb_inttable itof; - const upb_msgdef *parent; -}; - -extern const struct upb_refcounted_vtbl upb_oneofdef_vtbl; - -#define UPB_ONEOFDEF_INIT(name, ntof, itof, refs, ref2s) \ - { UPB_REFCOUNT_INIT(&upb_oneofdef_vtbl, refs, ref2s), 0, name, ntof, itof } - - -/* upb_symtab *****************************************************************/ - -struct upb_symtab { - upb_refcounted base; - - upb_strtable symtab; -}; - -struct upb_filedef { - upb_refcounted base; - - const char *name; - const char *package; - const char *phpprefix; - const char *phpnamespace; - upb_syntax_t syntax; - - upb_inttable defs; - upb_inttable deps; -}; - -extern const struct upb_refcounted_vtbl upb_filedef_vtbl; - -#endif /* UPB_STATICINIT_H_ */ -/* -** upb::Handlers (upb_handlers) -** -** A upb_handlers is like a virtual table for a upb_msgdef. Each field of the -** message can have associated functions that will be called when we are -** parsing or visiting a stream of data. This is similar to how handlers work -** in SAX (the Simple API for XML). -** -** The handlers have no idea where the data is coming from, so a single set of -** handlers could be used with two completely different data sources (for -** example, a parser and a visitor over in-memory objects). This decoupling is -** the most important feature of upb, because it allows parsers and serializers -** to be highly reusable. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. -*/ - -#ifndef UPB_HANDLERS_H -#define UPB_HANDLERS_H - - -#ifdef __cplusplus -namespace upb { -class BufferHandle; -class BytesHandler; -class HandlerAttributes; -class Handlers; -template class Handler; -template struct CanonicalType; -} /* namespace upb */ -#endif - -UPB_DECLARE_TYPE(upb::BufferHandle, upb_bufhandle) -UPB_DECLARE_TYPE(upb::BytesHandler, upb_byteshandler) -UPB_DECLARE_TYPE(upb::HandlerAttributes, upb_handlerattr) -UPB_DECLARE_DERIVED_TYPE(upb::Handlers, upb::RefCounted, - upb_handlers, upb_refcounted) - -/* The maximum depth that the handler graph can have. This is a resource limit - * for the C stack since we sometimes need to recursively traverse the graph. - * Cycles are ok; the traversal will stop when it detects a cycle, but we must - * hit the cycle before the maximum depth is reached. - * - * If having a single static limit is too inflexible, we can add another variant - * of Handlers::Freeze that allows specifying this as a parameter. */ -#define UPB_MAX_HANDLER_DEPTH 64 - -/* All the different types of handlers that can be registered. - * Only needed for the advanced functions in upb::Handlers. */ -typedef enum { - UPB_HANDLER_INT32, - UPB_HANDLER_INT64, - UPB_HANDLER_UINT32, - UPB_HANDLER_UINT64, - UPB_HANDLER_FLOAT, - UPB_HANDLER_DOUBLE, - UPB_HANDLER_BOOL, - UPB_HANDLER_STARTSTR, - UPB_HANDLER_STRING, - UPB_HANDLER_ENDSTR, - UPB_HANDLER_STARTSUBMSG, - UPB_HANDLER_ENDSUBMSG, - UPB_HANDLER_STARTSEQ, - UPB_HANDLER_ENDSEQ -} upb_handlertype_t; - -#define UPB_HANDLER_MAX (UPB_HANDLER_ENDSEQ+1) - -#define UPB_BREAK NULL - -/* A convenient definition for when no closure is needed. */ -extern char _upb_noclosure; -#define UPB_NO_CLOSURE &_upb_noclosure - -/* A selector refers to a specific field handler in the Handlers object - * (for example: the STARTSUBMSG handler for field "field15"). */ -typedef int32_t upb_selector_t; - -UPB_BEGIN_EXTERN_C - -/* Forward-declares for C inline accessors. We need to declare these here - * so we can "friend" them in the class declarations in C++. */ -UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h, - upb_selector_t s); -UPB_INLINE const void *upb_handlerattr_handlerdata(const upb_handlerattr *attr); -UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h, - upb_selector_t s); - -UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h); -UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj, - const void *type); -UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf, - size_t ofs); -UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h); -UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h); -UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h); - -UPB_END_EXTERN_C - - -/* Static selectors for upb::Handlers. */ -#define UPB_STARTMSG_SELECTOR 0 -#define UPB_ENDMSG_SELECTOR 1 -#define UPB_STATIC_SELECTOR_COUNT 2 - -/* Static selectors for upb::BytesHandler. */ -#define UPB_STARTSTR_SELECTOR 0 -#define UPB_STRING_SELECTOR 1 -#define UPB_ENDSTR_SELECTOR 2 - -typedef void upb_handlerfree(void *d); - -#ifdef __cplusplus - -/* A set of attributes that accompanies a handler's function pointer. */ -class upb::HandlerAttributes { - public: - HandlerAttributes(); - ~HandlerAttributes(); - - /* Sets the handler data that will be passed as the second parameter of the - * handler. To free this pointer when the handlers are freed, call - * Handlers::AddCleanup(). */ - bool SetHandlerData(const void *handler_data); - const void* handler_data() const; - - /* Use this to specify the type of the closure. This will be checked against - * all other closure types for handler that use the same closure. - * Registration will fail if this does not match all other non-NULL closure - * types. */ - bool SetClosureType(const void *closure_type); - const void* closure_type() const; - - /* Use this to specify the type of the returned closure. Only used for - * Start*{String,SubMessage,Sequence} handlers. This must match the closure - * type of any handlers that use it (for example, the StringBuf handler must - * match the closure returned from StartString). */ - bool SetReturnClosureType(const void *return_closure_type); - const void* return_closure_type() const; - - /* Set to indicate that the handler always returns "ok" (either "true" or a - * non-NULL closure). This is a hint that can allow code generators to - * generate more efficient code. */ - bool SetAlwaysOk(bool always_ok); - bool always_ok() const; - - private: - friend UPB_INLINE const void * ::upb_handlerattr_handlerdata( - const upb_handlerattr *attr); -#else -struct upb_handlerattr { -#endif - const void *handler_data_; - const void *closure_type_; - const void *return_closure_type_; - bool alwaysok_; -}; - -#define UPB_HANDLERATTR_INITIALIZER {NULL, NULL, NULL, false} - -typedef struct { - upb_func *func; - - /* It is wasteful to include the entire attributes here: - * - * * Some of the information is redundant (like storing the closure type - * separately for each handler that must match). - * * Some of the info is only needed prior to freeze() (like closure types). - * * alignment padding wastes a lot of space for alwaysok_. - * - * If/when the size and locality of handlers is an issue, we can optimize this - * not to store the entire attr like this. We do not expose the table's - * layout to allow this optimization in the future. */ - upb_handlerattr attr; -} upb_handlers_tabent; - -#ifdef __cplusplus - -/* Extra information about a buffer that is passed to a StringBuf handler. - * TODO(haberman): allow the handle to be pinned so that it will outlive - * the handler invocation. */ -class upb::BufferHandle { - public: - BufferHandle(); - ~BufferHandle(); - - /* The beginning of the buffer. This may be different than the pointer - * passed to a StringBuf handler because the handler may receive data - * that is from the middle or end of a larger buffer. */ - const char* buffer() const; - - /* The offset within the attached object where this buffer begins. Only - * meaningful if there is an attached object. */ - size_t object_offset() const; - - /* Note that object_offset is the offset of "buf" within the attached - * object. */ - void SetBuffer(const char* buf, size_t object_offset); - - /* The BufferHandle can have an "attached object", which can be used to - * tunnel through a pointer to the buffer's underlying representation. */ - template - void SetAttachedObject(const T* obj); - - /* Returns NULL if the attached object is not of this type. */ - template - const T* GetAttachedObject() const; - - private: - friend UPB_INLINE void ::upb_bufhandle_init(upb_bufhandle *h); - friend UPB_INLINE void ::upb_bufhandle_setobj(upb_bufhandle *h, - const void *obj, - const void *type); - friend UPB_INLINE void ::upb_bufhandle_setbuf(upb_bufhandle *h, - const char *buf, size_t ofs); - friend UPB_INLINE const void* ::upb_bufhandle_obj(const upb_bufhandle *h); - friend UPB_INLINE const void* ::upb_bufhandle_objtype( - const upb_bufhandle *h); - friend UPB_INLINE const char* ::upb_bufhandle_buf(const upb_bufhandle *h); -#else -struct upb_bufhandle { -#endif - const char *buf_; - const void *obj_; - const void *objtype_; - size_t objofs_; -}; - -#ifdef __cplusplus - -/* A upb::Handlers object represents the set of handlers associated with a - * message in the graph of messages. You can think of it as a big virtual - * table with functions corresponding to all the events that can fire while - * parsing or visiting a message of a specific type. - * - * Any handlers that are not set behave as if they had successfully consumed - * the value. Any unset Start* handlers will propagate their closure to the - * inner frame. - * - * The easiest way to create the *Handler objects needed by the Set* methods is - * with the UpbBind() and UpbMakeHandler() macros; see below. */ -class upb::Handlers { - public: - typedef upb_selector_t Selector; - typedef upb_handlertype_t Type; - - typedef Handler StartFieldHandler; - typedef Handler EndFieldHandler; - typedef Handler StartMessageHandler; - typedef Handler EndMessageHandler; - typedef Handler StartStringHandler; - typedef Handler StringHandler; - - template struct ValueHandler { - typedef Handler H; - }; - - typedef ValueHandler::H Int32Handler; - typedef ValueHandler::H Int64Handler; - typedef ValueHandler::H UInt32Handler; - typedef ValueHandler::H UInt64Handler; - typedef ValueHandler::H FloatHandler; - typedef ValueHandler::H DoubleHandler; - typedef ValueHandler::H BoolHandler; - - /* Any function pointer can be converted to this and converted back to its - * correct type. */ - typedef void GenericFunction(); - - typedef void HandlersCallback(const void *closure, upb_handlers *h); - - /* Returns a new handlers object for the given frozen msgdef. - * Returns NULL if memory allocation failed. */ - static reffed_ptr New(const MessageDef *m); - - /* Convenience function for registering a graph of handlers that mirrors the - * graph of msgdefs for some message. For "m" and all its children a new set - * of handlers will be created and the given callback will be invoked, - * allowing the client to register handlers for this message. Note that any - * subhandlers set by the callback will be overwritten. */ - static reffed_ptr NewFrozen(const MessageDef *m, - HandlersCallback *callback, - const void *closure); - - /* Functionality from upb::RefCounted. */ - UPB_REFCOUNTED_CPPMETHODS - - /* All handler registration functions return bool to indicate success or - * failure; details about failures are stored in this status object. If a - * failure does occur, it must be cleared before the Handlers are frozen, - * otherwise the freeze() operation will fail. The functions may *only* be - * used while the Handlers are mutable. */ - const Status* status(); - void ClearError(); - - /* Call to freeze these Handlers. Requires that any SubHandlers are already - * frozen. For cycles, you must use the static version below and freeze the - * whole graph at once. */ - bool Freeze(Status* s); - - /* Freezes the given set of handlers. You may not freeze a handler without - * also freezing any handlers they point to. */ - static bool Freeze(Handlers*const* handlers, int n, Status* s); - static bool Freeze(const std::vector& handlers, Status* s); - - /* Returns the msgdef associated with this handlers object. */ - const MessageDef* message_def() const; - - /* Adds the given pointer and function to the list of cleanup functions that - * will be run when these handlers are freed. If this pointer has previously - * been registered, the function returns false and does nothing. */ - bool AddCleanup(void *ptr, upb_handlerfree *cleanup); - - /* Sets the startmsg handler for the message, which is defined as follows: - * - * bool startmsg(MyType* closure) { - * // Called when the message begins. Returns true if processing should - * // continue. - * return true; - * } - */ - bool SetStartMessageHandler(const StartMessageHandler& handler); - - /* Sets the endmsg handler for the message, which is defined as follows: - * - * bool endmsg(MyType* closure, upb_status *status) { - * // Called when processing of this message ends, whether in success or - * // failure. "status" indicates the final status of processing, and - * // can also be modified in-place to update the final status. - * } - */ - bool SetEndMessageHandler(const EndMessageHandler& handler); - - /* Sets the value handler for the given field, which is defined as follows - * (this is for an int32 field; other field types will pass their native - * C/C++ type for "val"): - * - * bool OnValue(MyClosure* c, const MyHandlerData* d, int32_t val) { - * // Called when the field's value is encountered. "d" contains - * // whatever data was bound to this field when it was registered. - * // Returns true if processing should continue. - * return true; - * } - * - * handers->SetInt32Handler(f, UpbBind(OnValue, new MyHandlerData(...))); - * - * The value type must exactly match f->type(). - * For example, a handler that takes an int32_t parameter may only be used for - * fields of type UPB_TYPE_INT32 and UPB_TYPE_ENUM. - * - * Returns false if the handler failed to register; in this case the cleanup - * handler (if any) will be called immediately. - */ - bool SetInt32Handler (const FieldDef* f, const Int32Handler& h); - bool SetInt64Handler (const FieldDef* f, const Int64Handler& h); - bool SetUInt32Handler(const FieldDef* f, const UInt32Handler& h); - bool SetUInt64Handler(const FieldDef* f, const UInt64Handler& h); - bool SetFloatHandler (const FieldDef* f, const FloatHandler& h); - bool SetDoubleHandler(const FieldDef* f, const DoubleHandler& h); - bool SetBoolHandler (const FieldDef* f, const BoolHandler& h); - - /* Like the previous, but templated on the type on the value (ie. int32). - * This is mostly useful to call from other templates. To call this you must - * specify the template parameter explicitly, ie: - * h->SetValueHandler(f, UpbBind(MyHandler, MyData)); */ - template - bool SetValueHandler( - const FieldDef *f, - const typename ValueHandler::Type>::H& handler); - - /* Sets handlers for a string field, which are defined as follows: - * - * MySubClosure* startstr(MyClosure* c, const MyHandlerData* d, - * size_t size_hint) { - * // Called when a string value begins. The return value indicates the - * // closure for the string. "size_hint" indicates the size of the - * // string if it is known, however if the string is length-delimited - * // and the end-of-string is not available size_hint will be zero. - * // This case is indistinguishable from the case where the size is - * // known to be zero. - * // - * // TODO(haberman): is it important to distinguish these cases? - * // If we had ssize_t as a type we could make -1 "unknown", but - * // ssize_t is POSIX (not ANSI) and therefore less portable. - * // In practice I suspect it won't be important to distinguish. - * return closure; - * } - * - * size_t str(MyClosure* closure, const MyHandlerData* d, - * const char *str, size_t len) { - * // Called for each buffer of string data; the multiple physical buffers - * // are all part of the same logical string. The return value indicates - * // how many bytes were consumed. If this number is less than "len", - * // this will also indicate that processing should be halted for now, - * // like returning false or UPB_BREAK from any other callback. If - * // number is greater than "len", the excess bytes will be skipped over - * // and not passed to the callback. - * return len; - * } - * - * bool endstr(MyClosure* c, const MyHandlerData* d) { - * // Called when a string value ends. Return value indicates whether - * // processing should continue. - * return true; - * } - */ - bool SetStartStringHandler(const FieldDef* f, const StartStringHandler& h); - bool SetStringHandler(const FieldDef* f, const StringHandler& h); - bool SetEndStringHandler(const FieldDef* f, const EndFieldHandler& h); - - /* Sets the startseq handler, which is defined as follows: - * - * MySubClosure *startseq(MyClosure* c, const MyHandlerData* d) { - * // Called when a sequence (repeated field) begins. The returned - * // pointer indicates the closure for the sequence (or UPB_BREAK - * // to interrupt processing). - * return closure; - * } - * - * h->SetStartSequenceHandler(f, UpbBind(startseq, new MyHandlerData(...))); - * - * Returns "false" if "f" does not belong to this message or is not a - * repeated field. - */ - bool SetStartSequenceHandler(const FieldDef* f, const StartFieldHandler& h); - - /* Sets the startsubmsg handler for the given field, which is defined as - * follows: - * - * MySubClosure* startsubmsg(MyClosure* c, const MyHandlerData* d) { - * // Called when a submessage begins. The returned pointer indicates the - * // closure for the sequence (or UPB_BREAK to interrupt processing). - * return closure; - * } - * - * h->SetStartSubMessageHandler(f, UpbBind(startsubmsg, - * new MyHandlerData(...))); - * - * Returns "false" if "f" does not belong to this message or is not a - * submessage/group field. - */ - bool SetStartSubMessageHandler(const FieldDef* f, const StartFieldHandler& h); - - /* Sets the endsubmsg handler for the given field, which is defined as - * follows: - * - * bool endsubmsg(MyClosure* c, const MyHandlerData* d) { - * // Called when a submessage ends. Returns true to continue processing. - * return true; - * } - * - * Returns "false" if "f" does not belong to this message or is not a - * submessage/group field. - */ - bool SetEndSubMessageHandler(const FieldDef *f, const EndFieldHandler &h); - - /* Starts the endsubseq handler for the given field, which is defined as - * follows: - * - * bool endseq(MyClosure* c, const MyHandlerData* d) { - * // Called when a sequence ends. Returns true continue processing. - * return true; - * } - * - * Returns "false" if "f" does not belong to this message or is not a - * repeated field. - */ - bool SetEndSequenceHandler(const FieldDef* f, const EndFieldHandler& h); - - /* Sets or gets the object that specifies handlers for the given field, which - * must be a submessage or group. Returns NULL if no handlers are set. */ - bool SetSubHandlers(const FieldDef* f, const Handlers* sub); - const Handlers* GetSubHandlers(const FieldDef* f) const; - - /* Equivalent to GetSubHandlers, but takes the STARTSUBMSG selector for the - * field. */ - const Handlers* GetSubHandlers(Selector startsubmsg) const; - - /* A selector refers to a specific field handler in the Handlers object - * (for example: the STARTSUBMSG handler for field "field15"). - * On success, returns true and stores the selector in "s". - * If the FieldDef or Type are invalid, returns false. - * The returned selector is ONLY valid for Handlers whose MessageDef - * contains this FieldDef. */ - static bool GetSelector(const FieldDef* f, Type type, Selector* s); - - /* Given a START selector of any kind, returns the corresponding END selector. */ - static Selector GetEndSelector(Selector start_selector); - - /* Returns the function pointer for this handler. It is the client's - * responsibility to cast to the correct function type before calling it. */ - GenericFunction* GetHandler(Selector selector); - - /* Sets the given attributes to the attributes for this selector. */ - bool GetAttributes(Selector selector, HandlerAttributes* attr); - - /* Returns the handler data that was registered with this handler. */ - const void* GetHandlerData(Selector selector); - - /* Could add any of the following functions as-needed, with some minor - * implementation changes: - * - * const FieldDef* GetFieldDef(Selector selector); - * static bool IsSequence(Selector selector); */ - - private: - UPB_DISALLOW_POD_OPS(Handlers, upb::Handlers) - - friend UPB_INLINE GenericFunction *::upb_handlers_gethandler( - const upb_handlers *h, upb_selector_t s); - friend UPB_INLINE const void *::upb_handlers_gethandlerdata( - const upb_handlers *h, upb_selector_t s); -#else -struct upb_handlers { -#endif - upb_refcounted base; - - const upb_msgdef *msg; - const upb_handlers **sub; - const void *top_closure_type; - upb_inttable cleanup_; - upb_status status_; /* Used only when mutable. */ - upb_handlers_tabent table[1]; /* Dynamically-sized field handler array. */ -}; - -#ifdef __cplusplus - -namespace upb { - -/* Convenience macros for creating a Handler object that is wrapped with a - * type-safe wrapper function that converts the "void*" parameters/returns - * of the underlying C API into nice C++ function. - * - * Sample usage: - * void OnValue1(MyClosure* c, const MyHandlerData* d, int32_t val) { - * // do stuff ... - * } - * - * // Handler that doesn't need any data bound to it. - * void OnValue2(MyClosure* c, int32_t val) { - * // do stuff ... - * } - * - * // Handler that returns bool so it can return failure if necessary. - * bool OnValue3(MyClosure* c, int32_t val) { - * // do stuff ... - * return ok; - * } - * - * // Member function handler. - * class MyClosure { - * public: - * void OnValue(int32_t val) { - * // do stuff ... - * } - * }; - * - * // Takes ownership of the MyHandlerData. - * handlers->SetInt32Handler(f1, UpbBind(OnValue1, new MyHandlerData(...))); - * handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue2)); - * handlers->SetInt32Handler(f1, UpbMakeHandler(OnValue3)); - * handlers->SetInt32Handler(f2, UpbMakeHandler(&MyClosure::OnValue)); - */ - -#ifdef UPB_CXX11 - -/* In C++11, the "template" disambiguator can appear even outside templates, - * so all calls can safely use this pair of macros. */ - -#define UpbMakeHandler(f) upb::MatchFunc(f).template GetFunc() - -/* We have to be careful to only evaluate "d" once. */ -#define UpbBind(f, d) upb::MatchFunc(f).template GetFunc((d)) - -#else - -/* Prior to C++11, the "template" disambiguator may only appear inside a - * template, so the regular macro must not use "template" */ - -#define UpbMakeHandler(f) upb::MatchFunc(f).GetFunc() - -#define UpbBind(f, d) upb::MatchFunc(f).GetFunc((d)) - -#endif /* UPB_CXX11 */ - -/* This macro must be used in C++98 for calls from inside a template. But we - * define this variant in all cases; code that wants to be compatible with both - * C++98 and C++11 should always use this macro when calling from a template. */ -#define UpbMakeHandlerT(f) upb::MatchFunc(f).template GetFunc() - -/* We have to be careful to only evaluate "d" once. */ -#define UpbBindT(f, d) upb::MatchFunc(f).template GetFunc((d)) - -/* Handler: a struct that contains the (handler, data, deleter) tuple that is - * used to register all handlers. Users can Make() these directly but it's - * more convenient to use the UpbMakeHandler/UpbBind macros above. */ -template class Handler { - public: - /* The underlying, handler function signature that upb uses internally. */ - typedef T FuncPtr; - - /* Intentionally implicit. */ - template Handler(F func); - ~Handler(); - - private: - void AddCleanup(Handlers* h) const { - if (cleanup_func_) { - bool ok = h->AddCleanup(cleanup_data_, cleanup_func_); - UPB_ASSERT(ok); - } - } - - UPB_DISALLOW_COPY_AND_ASSIGN(Handler) - friend class Handlers; - FuncPtr handler_; - mutable HandlerAttributes attr_; - mutable bool registered_; - void *cleanup_data_; - upb_handlerfree *cleanup_func_; -}; - -} /* namespace upb */ - -#endif /* __cplusplus */ - -UPB_BEGIN_EXTERN_C - -/* Native C API. */ - -/* Handler function typedefs. */ -typedef bool upb_startmsg_handlerfunc(void *c, const void*); -typedef bool upb_endmsg_handlerfunc(void *c, const void *, upb_status *status); -typedef void* upb_startfield_handlerfunc(void *c, const void *hd); -typedef bool upb_endfield_handlerfunc(void *c, const void *hd); -typedef bool upb_int32_handlerfunc(void *c, const void *hd, int32_t val); -typedef bool upb_int64_handlerfunc(void *c, const void *hd, int64_t val); -typedef bool upb_uint32_handlerfunc(void *c, const void *hd, uint32_t val); -typedef bool upb_uint64_handlerfunc(void *c, const void *hd, uint64_t val); -typedef bool upb_float_handlerfunc(void *c, const void *hd, float val); -typedef bool upb_double_handlerfunc(void *c, const void *hd, double val); -typedef bool upb_bool_handlerfunc(void *c, const void *hd, bool val); -typedef void *upb_startstr_handlerfunc(void *c, const void *hd, - size_t size_hint); -typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf, - size_t n, const upb_bufhandle* handle); - -/* upb_bufhandle */ -size_t upb_bufhandle_objofs(const upb_bufhandle *h); - -/* upb_handlerattr */ -void upb_handlerattr_init(upb_handlerattr *attr); -void upb_handlerattr_uninit(upb_handlerattr *attr); - -bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, const void *hd); -bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type); -const void *upb_handlerattr_closuretype(const upb_handlerattr *attr); -bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr, - const void *type); -const void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr); -bool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok); -bool upb_handlerattr_alwaysok(const upb_handlerattr *attr); - -UPB_INLINE const void *upb_handlerattr_handlerdata( - const upb_handlerattr *attr) { - return attr->handler_data_; -} - -/* upb_handlers */ -typedef void upb_handlers_callback(const void *closure, upb_handlers *h); -upb_handlers *upb_handlers_new(const upb_msgdef *m, - const void *owner); -const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m, - const void *owner, - upb_handlers_callback *callback, - const void *closure); - -/* Include refcounted methods like upb_handlers_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_handlers, upb_handlers_upcast) - -const upb_status *upb_handlers_status(upb_handlers *h); -void upb_handlers_clearerr(upb_handlers *h); -const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h); -bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *hfree); - -bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setint32(upb_handlers *h, const upb_fielddef *f, - upb_int32_handlerfunc *func, upb_handlerattr *attr); -bool upb_handlers_setint64(upb_handlers *h, const upb_fielddef *f, - upb_int64_handlerfunc *func, upb_handlerattr *attr); -bool upb_handlers_setuint32(upb_handlers *h, const upb_fielddef *f, - upb_uint32_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setuint64(upb_handlers *h, const upb_fielddef *f, - upb_uint64_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setfloat(upb_handlers *h, const upb_fielddef *f, - upb_float_handlerfunc *func, upb_handlerattr *attr); -bool upb_handlers_setdouble(upb_handlers *h, const upb_fielddef *f, - upb_double_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setbool(upb_handlers *h, const upb_fielddef *f, - upb_bool_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setstartstr(upb_handlers *h, const upb_fielddef *f, - upb_startstr_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setstring(upb_handlers *h, const upb_fielddef *f, - upb_string_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setendstr(upb_handlers *h, const upb_fielddef *f, - upb_endfield_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setstartseq(upb_handlers *h, const upb_fielddef *f, - upb_startfield_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setstartsubmsg(upb_handlers *h, const upb_fielddef *f, - upb_startfield_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setendsubmsg(upb_handlers *h, const upb_fielddef *f, - upb_endfield_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f, - upb_endfield_handlerfunc *func, - upb_handlerattr *attr); - -bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f, - const upb_handlers *sub); -const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h, - const upb_fielddef *f); -const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h, - upb_selector_t sel); - -UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h, - upb_selector_t s) { - return (upb_func *)h->table[s].func; -} - -bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t s, - upb_handlerattr *attr); - -UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h, - upb_selector_t s) { - return upb_handlerattr_handlerdata(&h->table[s].attr); -} - -#ifdef __cplusplus - -/* Handler types for single fields. - * Right now we only have one for TYPE_BYTES but ones for other types - * should follow. - * - * These follow the same handlers protocol for fields of a message. */ -class upb::BytesHandler { - public: - BytesHandler(); - ~BytesHandler(); -#else -struct upb_byteshandler { -#endif - upb_handlers_tabent table[3]; -}; - -void upb_byteshandler_init(upb_byteshandler *h); - -/* Caller must ensure that "d" outlives the handlers. - * TODO(haberman): should this have a "freeze" operation? It's not necessary - * for memory management, but could be useful to force immutability and provide - * a convenient moment to verify that all registration succeeded. */ -bool upb_byteshandler_setstartstr(upb_byteshandler *h, - upb_startstr_handlerfunc *func, void *d); -bool upb_byteshandler_setstring(upb_byteshandler *h, - upb_string_handlerfunc *func, void *d); -bool upb_byteshandler_setendstr(upb_byteshandler *h, - upb_endfield_handlerfunc *func, void *d); - -/* "Static" methods */ -bool upb_handlers_freeze(upb_handlers *const *handlers, int n, upb_status *s); -upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f); -bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type, - upb_selector_t *s); -UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) { - return start + 1; -} - -/* Internal-only. */ -uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f); -uint32_t upb_handlers_selectorcount(const upb_fielddef *f); - -UPB_END_EXTERN_C - -/* -** Inline definitions for handlers.h, which are particularly long and a bit -** tricky. -*/ - -#ifndef UPB_HANDLERS_INL_H_ -#define UPB_HANDLERS_INL_H_ - -#include - -/* C inline methods. */ - -/* upb_bufhandle */ -UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h) { - h->obj_ = NULL; - h->objtype_ = NULL; - h->buf_ = NULL; - h->objofs_ = 0; -} -UPB_INLINE void upb_bufhandle_uninit(upb_bufhandle *h) { - UPB_UNUSED(h); -} -UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj, - const void *type) { - h->obj_ = obj; - h->objtype_ = type; -} -UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf, - size_t ofs) { - h->buf_ = buf; - h->objofs_ = ofs; -} -UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h) { - return h->obj_; -} -UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h) { - return h->objtype_; -} -UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h) { - return h->buf_; -} - - -#ifdef __cplusplus - -/* Type detection and typedefs for integer types. - * For platforms where there are multiple 32-bit or 64-bit types, we need to be - * able to enumerate them so we can properly create overloads for all variants. - * - * If any platform existed where there were three integer types with the same - * size, this would have to become more complicated. For example, short, int, - * and long could all be 32-bits. Even more diabolically, short, int, long, - * and long long could all be 64 bits and still be standard-compliant. - * However, few platforms are this strange, and it's unlikely that upb will be - * used on the strangest ones. */ - -/* Can't count on stdint.h limits like INT32_MAX, because in C++ these are - * only defined when __STDC_LIMIT_MACROS are defined before the *first* include - * of stdint.h. We can't guarantee that someone else didn't include these first - * without defining __STDC_LIMIT_MACROS. */ -#define UPB_INT32_MAX 0x7fffffffLL -#define UPB_INT32_MIN (-UPB_INT32_MAX - 1) -#define UPB_INT64_MAX 0x7fffffffffffffffLL -#define UPB_INT64_MIN (-UPB_INT64_MAX - 1) - -#if INT_MAX == UPB_INT32_MAX && INT_MIN == UPB_INT32_MIN -#define UPB_INT_IS_32BITS 1 -#endif - -#if LONG_MAX == UPB_INT32_MAX && LONG_MIN == UPB_INT32_MIN -#define UPB_LONG_IS_32BITS 1 -#endif - -#if LONG_MAX == UPB_INT64_MAX && LONG_MIN == UPB_INT64_MIN -#define UPB_LONG_IS_64BITS 1 -#endif - -#if LLONG_MAX == UPB_INT64_MAX && LLONG_MIN == UPB_INT64_MIN -#define UPB_LLONG_IS_64BITS 1 -#endif - -/* We use macros instead of typedefs so we can undefine them later and avoid - * leaking them outside this header file. */ -#if UPB_INT_IS_32BITS -#define UPB_INT32_T int -#define UPB_UINT32_T unsigned int - -#if UPB_LONG_IS_32BITS -#define UPB_TWO_32BIT_TYPES 1 -#define UPB_INT32ALT_T long -#define UPB_UINT32ALT_T unsigned long -#endif /* UPB_LONG_IS_32BITS */ - -#elif UPB_LONG_IS_32BITS /* && !UPB_INT_IS_32BITS */ -#define UPB_INT32_T long -#define UPB_UINT32_T unsigned long -#endif /* UPB_INT_IS_32BITS */ - - -#if UPB_LONG_IS_64BITS -#define UPB_INT64_T long -#define UPB_UINT64_T unsigned long - -#if UPB_LLONG_IS_64BITS -#define UPB_TWO_64BIT_TYPES 1 -#define UPB_INT64ALT_T long long -#define UPB_UINT64ALT_T unsigned long long -#endif /* UPB_LLONG_IS_64BITS */ - -#elif UPB_LLONG_IS_64BITS /* && !UPB_LONG_IS_64BITS */ -#define UPB_INT64_T long long -#define UPB_UINT64_T unsigned long long -#endif /* UPB_LONG_IS_64BITS */ - -#undef UPB_INT32_MAX -#undef UPB_INT32_MIN -#undef UPB_INT64_MAX -#undef UPB_INT64_MIN -#undef UPB_INT_IS_32BITS -#undef UPB_LONG_IS_32BITS -#undef UPB_LONG_IS_64BITS -#undef UPB_LLONG_IS_64BITS - - -namespace upb { - -typedef void CleanupFunc(void *ptr); - -/* Template to remove "const" from "const T*" and just return "T*". - * - * We define a nonsense default because otherwise it will fail to instantiate as - * a function parameter type even in cases where we don't expect any caller to - * actually match the overload. */ -class CouldntRemoveConst {}; -template struct remove_constptr { typedef CouldntRemoveConst type; }; -template struct remove_constptr { typedef T *type; }; - -/* Template that we use below to remove a template specialization from - * consideration if it matches a specific type. */ -template struct disable_if_same { typedef void Type; }; -template struct disable_if_same {}; - -template void DeletePointer(void *p) { delete static_cast(p); } - -template -struct FirstUnlessVoidOrBool { - typedef T1 value; -}; - -template -struct FirstUnlessVoidOrBool { - typedef T2 value; -}; - -template -struct FirstUnlessVoidOrBool { - typedef T2 value; -}; - -template -struct is_same { - static bool value; -}; - -template -struct is_same { - static bool value; -}; - -template -bool is_same::value = false; - -template -bool is_same::value = true; - -/* FuncInfo *******************************************************************/ - -/* Info about the user's original, pre-wrapped function. */ -template -struct FuncInfo { - /* The type of the closure that the function takes (its first param). */ - typedef C Closure; - - /* The return type. */ - typedef R Return; -}; - -/* Func ***********************************************************************/ - -/* Func1, Func2, Func3: Template classes representing a function and its - * signature. - * - * Since the function is a template parameter, calling the function can be - * inlined at compile-time and does not require a function pointer at runtime. - * These functions are not bound to a handler data so have no data or cleanup - * handler. */ -struct UnboundFunc { - CleanupFunc *GetCleanup() { return NULL; } - void *GetData() { return NULL; } -}; - -template -struct Func1 : public UnboundFunc { - typedef R Return; - typedef I FuncInfo; - static R Call(P1 p1) { return F(p1); } -}; - -template -struct Func2 : public UnboundFunc { - typedef R Return; - typedef I FuncInfo; - static R Call(P1 p1, P2 p2) { return F(p1, p2); } -}; - -template -struct Func3 : public UnboundFunc { - typedef R Return; - typedef I FuncInfo; - static R Call(P1 p1, P2 p2, P3 p3) { return F(p1, p2, p3); } -}; - -template -struct Func4 : public UnboundFunc { - typedef R Return; - typedef I FuncInfo; - static R Call(P1 p1, P2 p2, P3 p3, P4 p4) { return F(p1, p2, p3, p4); } -}; - -template -struct Func5 : public UnboundFunc { - typedef R Return; - typedef I FuncInfo; - static R Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { - return F(p1, p2, p3, p4, p5); - } -}; - -/* BoundFunc ******************************************************************/ - -/* BoundFunc2, BoundFunc3: Like Func2/Func3 except also contains a value that - * shall be bound to the function's second parameter. - * - * Note that the second parameter is a const pointer, but our stored bound value - * is non-const so we can free it when the handlers are destroyed. */ -template -struct BoundFunc { - typedef typename remove_constptr::type MutableP2; - explicit BoundFunc(MutableP2 data_) : data(data_) {} - CleanupFunc *GetCleanup() { return &DeletePointer; } - MutableP2 GetData() { return data; } - MutableP2 data; -}; - -template -struct BoundFunc2 : public BoundFunc { - typedef BoundFunc Base; - typedef I FuncInfo; - explicit BoundFunc2(typename Base::MutableP2 arg) : Base(arg) {} -}; - -template -struct BoundFunc3 : public BoundFunc { - typedef BoundFunc Base; - typedef I FuncInfo; - explicit BoundFunc3(typename Base::MutableP2 arg) : Base(arg) {} -}; - -template -struct BoundFunc4 : public BoundFunc { - typedef BoundFunc Base; - typedef I FuncInfo; - explicit BoundFunc4(typename Base::MutableP2 arg) : Base(arg) {} -}; - -template -struct BoundFunc5 : public BoundFunc { - typedef BoundFunc Base; - typedef I FuncInfo; - explicit BoundFunc5(typename Base::MutableP2 arg) : Base(arg) {} -}; - -/* FuncSig ********************************************************************/ - -/* FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function - * *signature*, but without a specific function attached. - * - * These classes contain member functions that can be invoked with a - * specific function to return a Func/BoundFunc class. */ -template -struct FuncSig1 { - template - Func1 > GetFunc() { - return Func1 >(); - } -}; - -template -struct FuncSig2 { - template - Func2 > GetFunc() { - return Func2 >(); - } - - template - BoundFunc2 > GetFunc( - typename remove_constptr::type param2) { - return BoundFunc2 >(param2); - } -}; - -template -struct FuncSig3 { - template - Func3 > GetFunc() { - return Func3 >(); - } - - template - BoundFunc3 > GetFunc( - typename remove_constptr::type param2) { - return BoundFunc3 >(param2); - } -}; - -template -struct FuncSig4 { - template - Func4 > GetFunc() { - return Func4 >(); - } - - template - BoundFunc4 > GetFunc( - typename remove_constptr::type param2) { - return BoundFunc4 >(param2); - } -}; - -template -struct FuncSig5 { - template - Func5 > GetFunc() { - return Func5 >(); - } - - template - BoundFunc5 > GetFunc( - typename remove_constptr::type param2) { - return BoundFunc5 >(param2); - } -}; - -/* Overloaded template function that can construct the appropriate FuncSig* - * class given a function pointer by deducing the template parameters. */ -template -inline FuncSig1 MatchFunc(R (*f)(P1)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return FuncSig1(); -} - -template -inline FuncSig2 MatchFunc(R (*f)(P1, P2)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return FuncSig2(); -} - -template -inline FuncSig3 MatchFunc(R (*f)(P1, P2, P3)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return FuncSig3(); -} - -template -inline FuncSig4 MatchFunc(R (*f)(P1, P2, P3, P4)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return FuncSig4(); -} - -template -inline FuncSig5 MatchFunc(R (*f)(P1, P2, P3, P4, P5)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return FuncSig5(); -} - -/* MethodSig ******************************************************************/ - -/* CallMethod*: a function template that calls a given method. */ -template -R CallMethod0(C *obj) { - return ((*obj).*F)(); -} - -template -R CallMethod1(C *obj, P1 arg1) { - return ((*obj).*F)(arg1); -} - -template -R CallMethod2(C *obj, P1 arg1, P2 arg2) { - return ((*obj).*F)(arg1, arg2); -} - -template -R CallMethod3(C *obj, P1 arg1, P2 arg2, P3 arg3) { - return ((*obj).*F)(arg1, arg2, arg3); -} - -template -R CallMethod4(C *obj, P1 arg1, P2 arg2, P3 arg3, P4 arg4) { - return ((*obj).*F)(arg1, arg2, arg3, arg4); -} - -/* MethodSig: like FuncSig, but for member functions. - * - * GetFunc() returns a normal FuncN object, so after calling GetFunc() no - * more logic is required to special-case methods. */ -template -struct MethodSig0 { - template - Func1, FuncInfo > GetFunc() { - return Func1, FuncInfo >(); - } -}; - -template -struct MethodSig1 { - template - Func2, FuncInfo > GetFunc() { - return Func2, FuncInfo >(); - } - - template - BoundFunc2, FuncInfo > GetFunc( - typename remove_constptr::type param1) { - return BoundFunc2, FuncInfo >( - param1); - } -}; - -template -struct MethodSig2 { - template - Func3, FuncInfo > - GetFunc() { - return Func3, - FuncInfo >(); - } - - template - BoundFunc3, FuncInfo > - GetFunc(typename remove_constptr::type param1) { - return BoundFunc3, - FuncInfo >(param1); - } -}; - -template -struct MethodSig3 { - template - Func4, FuncInfo > - GetFunc() { - return Func4, - FuncInfo >(); - } - - template - BoundFunc4, - FuncInfo > - GetFunc(typename remove_constptr::type param1) { - return BoundFunc4, - FuncInfo >(param1); - } -}; - -template -struct MethodSig4 { - template - Func5, - FuncInfo > - GetFunc() { - return Func5, - FuncInfo >(); - } - - template - BoundFunc5, - FuncInfo > - GetFunc(typename remove_constptr::type param1) { - return BoundFunc5, FuncInfo >( - param1); - } -}; - -template -inline MethodSig0 MatchFunc(R (C::*f)()) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return MethodSig0(); -} - -template -inline MethodSig1 MatchFunc(R (C::*f)(P1)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return MethodSig1(); -} - -template -inline MethodSig2 MatchFunc(R (C::*f)(P1, P2)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return MethodSig2(); -} - -template -inline MethodSig3 MatchFunc(R (C::*f)(P1, P2, P3)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return MethodSig3(); -} - -template -inline MethodSig4 MatchFunc(R (C::*f)(P1, P2, P3, P4)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return MethodSig4(); -} - -/* MaybeWrapReturn ************************************************************/ - -/* Template class that attempts to wrap the return value of the function so it - * matches the expected type. There are two main adjustments it may make: - * - * 1. If the function returns void, make it return the expected type and with - * a value that always indicates success. - * 2. If the function returns bool, make it return the expected type with a - * value that indicates success or failure. - * - * The "expected type" for return is: - * 1. void* for start handlers. If the closure parameter has a different type - * we will cast it to void* for the return in the success case. - * 2. size_t for string buffer handlers. - * 3. bool for everything else. */ - -/* Template parameters are FuncN type and desired return type. */ -template -struct MaybeWrapReturn; - -/* If the return type matches, return the given function unwrapped. */ -template -struct MaybeWrapReturn { - typedef F Func; -}; - -/* Function wrapper that munges the return value from void to (bool)true. */ -template -bool ReturnTrue2(P1 p1, P2 p2) { - F(p1, p2); - return true; -} - -template -bool ReturnTrue3(P1 p1, P2 p2, P3 p3) { - F(p1, p2, p3); - return true; -} - -/* Function wrapper that munges the return value from void to (void*)arg1 */ -template -void *ReturnClosure2(P1 p1, P2 p2) { - F(p1, p2); - return p1; -} - -template -void *ReturnClosure3(P1 p1, P2 p2, P3 p3) { - F(p1, p2, p3); - return p1; -} - -/* Function wrapper that munges the return value from R to void*. */ -template -void *CastReturnToVoidPtr2(P1 p1, P2 p2) { - return F(p1, p2); -} - -template -void *CastReturnToVoidPtr3(P1 p1, P2 p2, P3 p3) { - return F(p1, p2, p3); -} - -/* Function wrapper that munges the return value from bool to void*. */ -template -void *ReturnClosureOrBreak2(P1 p1, P2 p2) { - return F(p1, p2) ? p1 : UPB_BREAK; -} - -template -void *ReturnClosureOrBreak3(P1 p1, P2 p2, P3 p3) { - return F(p1, p2, p3) ? p1 : UPB_BREAK; -} - -/* For the string callback, which takes five params, returns the size param. */ -template -size_t ReturnStringLen(P1 p1, P2 p2, const char *p3, size_t p4, - const BufferHandle *p5) { - F(p1, p2, p3, p4, p5); - return p4; -} - -/* For the string callback, which takes five params, returns the size param or - * zero. */ -template -size_t ReturnNOr0(P1 p1, P2 p2, const char *p3, size_t p4, - const BufferHandle *p5) { - return F(p1, p2, p3, p4, p5) ? p4 : 0; -} - -/* If we have a function returning void but want a function returning bool, wrap - * it in a function that returns true. */ -template -struct MaybeWrapReturn, bool> { - typedef Func2, I> Func; -}; - -template -struct MaybeWrapReturn, bool> { - typedef Func3, I> Func; -}; - -/* If our function returns void but we want one returning void*, wrap it in a - * function that returns the first argument. */ -template -struct MaybeWrapReturn, void *> { - typedef Func2, I> Func; -}; - -template -struct MaybeWrapReturn, void *> { - typedef Func3, I> Func; -}; - -/* If our function returns R* but we want one returning void*, wrap it in a - * function that casts to void*. */ -template -struct MaybeWrapReturn, void *, - typename disable_if_same::Type> { - typedef Func2, I> Func; -}; - -template -struct MaybeWrapReturn, void *, - typename disable_if_same::Type> { - typedef Func3, I> - Func; -}; - -/* If our function returns bool but we want one returning void*, wrap it in a - * function that returns either the first param or UPB_BREAK. */ -template -struct MaybeWrapReturn, void *> { - typedef Func2, I> Func; -}; - -template -struct MaybeWrapReturn, void *> { - typedef Func3, I> - Func; -}; - -/* If our function returns void but we want one returning size_t, wrap it in a - * function that returns the size argument. */ -template -struct MaybeWrapReturn< - Func5, - size_t> { - typedef Func5, I> Func; -}; - -/* If our function returns bool but we want one returning size_t, wrap it in a - * function that returns either 0 or the buf size. */ -template -struct MaybeWrapReturn< - Func5, - size_t> { - typedef Func5, I> Func; -}; - -/* ConvertParams **************************************************************/ - -/* Template class that converts the function parameters if necessary, and - * ignores the HandlerData parameter if appropriate. - * - * Template parameter is the are FuncN function type. */ -template -struct ConvertParams; - -/* Function that discards the handler data parameter. */ -template -R IgnoreHandlerData2(void *p1, const void *hd) { - UPB_UNUSED(hd); - return F(static_cast(p1)); -} - -template -R IgnoreHandlerData3(void *p1, const void *hd, P2Wrapper p2) { - UPB_UNUSED(hd); - return F(static_cast(p1), p2); -} - -template -R IgnoreHandlerData4(void *p1, const void *hd, P2 p2, P3 p3) { - UPB_UNUSED(hd); - return F(static_cast(p1), p2, p3); -} - -template -R IgnoreHandlerData5(void *p1, const void *hd, P2 p2, P3 p3, P4 p4) { - UPB_UNUSED(hd); - return F(static_cast(p1), p2, p3, p4); -} - -template -R IgnoreHandlerDataIgnoreHandle(void *p1, const void *hd, const char *p2, - size_t p3, const BufferHandle *handle) { - UPB_UNUSED(hd); - UPB_UNUSED(handle); - return F(static_cast(p1), p2, p3); -} - -/* Function that casts the handler data parameter. */ -template -R CastHandlerData2(void *c, const void *hd) { - return F(static_cast(c), static_cast(hd)); -} - -template -R CastHandlerData3(void *c, const void *hd, P3Wrapper p3) { - return F(static_cast(c), static_cast(hd), p3); -} - -template -R CastHandlerData5(void *c, const void *hd, P3 p3, P4 p4, P5 p5) { - return F(static_cast(c), static_cast(hd), p3, p4, p5); -} - -template -R CastHandlerDataIgnoreHandle(void *c, const void *hd, const char *p3, - size_t p4, const BufferHandle *handle) { - UPB_UNUSED(handle); - return F(static_cast(c), static_cast(hd), p3, p4); -} - -/* For unbound functions, ignore the handler data. */ -template -struct ConvertParams, T> { - typedef Func2, I> Func; -}; - -template -struct ConvertParams, - R2 (*)(P1_2, P2_2, P3_2)> { - typedef Func3, I> Func; -}; - -/* For StringBuffer only; this ignores both the handler data and the - * BufferHandle. */ -template -struct ConvertParams, T> { - typedef Func5, - I> Func; -}; - -template -struct ConvertParams, T> { - typedef Func5, I> Func; -}; - -/* For bound functions, cast the handler data. */ -template -struct ConvertParams, T> { - typedef Func2, I> - Func; -}; - -template -struct ConvertParams, - R2 (*)(P1_2, P2_2, P3_2)> { - typedef Func3, I> Func; -}; - -/* For StringBuffer only; this ignores the BufferHandle. */ -template -struct ConvertParams, T> { - typedef Func5, - I> Func; -}; - -template -struct ConvertParams, T> { - typedef Func5, I> Func; -}; - -/* utype/ltype are upper/lower-case, ctype is canonical C type, vtype is - * variant C type. */ -#define TYPE_METHODS(utype, ltype, ctype, vtype) \ - template <> struct CanonicalType { \ - typedef ctype Type; \ - }; \ - template <> \ - inline bool Handlers::SetValueHandler( \ - const FieldDef *f, \ - const Handlers::utype ## Handler& handler) { \ - UPB_ASSERT(!handler.registered_); \ - handler.AddCleanup(this); \ - handler.registered_ = true; \ - return upb_handlers_set##ltype(this, f, handler.handler_, &handler.attr_); \ - } \ - -TYPE_METHODS(Double, double, double, double) -TYPE_METHODS(Float, float, float, float) -TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64_T) -TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32_T) -TYPE_METHODS(Int64, int64, int64_t, UPB_INT64_T) -TYPE_METHODS(Int32, int32, int32_t, UPB_INT32_T) -TYPE_METHODS(Bool, bool, bool, bool) - -#ifdef UPB_TWO_32BIT_TYPES -TYPE_METHODS(Int32, int32, int32_t, UPB_INT32ALT_T) -TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32ALT_T) -#endif - -#ifdef UPB_TWO_64BIT_TYPES -TYPE_METHODS(Int64, int64, int64_t, UPB_INT64ALT_T) -TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64ALT_T) -#endif -#undef TYPE_METHODS - -template <> struct CanonicalType { - typedef Status* Type; -}; - -/* Type methods that are only one-per-canonical-type and not - * one-per-cvariant. */ - -#define TYPE_METHODS(utype, ctype) \ - inline bool Handlers::Set##utype##Handler(const FieldDef *f, \ - const utype##Handler &h) { \ - return SetValueHandler(f, h); \ - } \ - -TYPE_METHODS(Double, double) -TYPE_METHODS(Float, float) -TYPE_METHODS(UInt64, uint64_t) -TYPE_METHODS(UInt32, uint32_t) -TYPE_METHODS(Int64, int64_t) -TYPE_METHODS(Int32, int32_t) -TYPE_METHODS(Bool, bool) -#undef TYPE_METHODS - -template struct ReturnOf; - -template -struct ReturnOf { - typedef R Return; -}; - -template -struct ReturnOf { - typedef R Return; -}; - -template -struct ReturnOf { - typedef R Return; -}; - -template -struct ReturnOf { - typedef R Return; -}; - -template const void *UniquePtrForType() { - static const char ch = 0; - return &ch; -} - -template -template -inline Handler::Handler(F func) - : registered_(false), - cleanup_data_(func.GetData()), - cleanup_func_(func.GetCleanup()) { - upb_handlerattr_sethandlerdata(&attr_, func.GetData()); - typedef typename ReturnOf::Return Return; - typedef typename ConvertParams::Func ConvertedParamsFunc; - typedef typename MaybeWrapReturn::Func - ReturnWrappedFunc; - handler_ = ReturnWrappedFunc().Call; - - /* Set attributes based on what templates can statically tell us about the - * user's function. */ - - /* If the original function returns void, then we know that we wrapped it to - * always return ok. */ - bool always_ok = is_same::value; - attr_.SetAlwaysOk(always_ok); - - /* Closure parameter and return type. */ - attr_.SetClosureType(UniquePtrForType()); - - /* We use the closure type (from the first parameter) if the return type is - * void or bool, since these are the two cases we wrap to return the closure's - * type anyway. - * - * This is all nonsense for non START* handlers, but it doesn't matter because - * in that case the value will be ignored. */ - typedef typename FirstUnlessVoidOrBool::value - EffectiveReturn; - attr_.SetReturnClosureType(UniquePtrForType()); -} - -template -inline Handler::~Handler() { - UPB_ASSERT(registered_); -} - -inline HandlerAttributes::HandlerAttributes() { upb_handlerattr_init(this); } -inline HandlerAttributes::~HandlerAttributes() { upb_handlerattr_uninit(this); } -inline bool HandlerAttributes::SetHandlerData(const void *hd) { - return upb_handlerattr_sethandlerdata(this, hd); -} -inline const void* HandlerAttributes::handler_data() const { - return upb_handlerattr_handlerdata(this); -} -inline bool HandlerAttributes::SetClosureType(const void *type) { - return upb_handlerattr_setclosuretype(this, type); -} -inline const void* HandlerAttributes::closure_type() const { - return upb_handlerattr_closuretype(this); -} -inline bool HandlerAttributes::SetReturnClosureType(const void *type) { - return upb_handlerattr_setreturnclosuretype(this, type); -} -inline const void* HandlerAttributes::return_closure_type() const { - return upb_handlerattr_returnclosuretype(this); -} -inline bool HandlerAttributes::SetAlwaysOk(bool always_ok) { - return upb_handlerattr_setalwaysok(this, always_ok); -} -inline bool HandlerAttributes::always_ok() const { - return upb_handlerattr_alwaysok(this); -} - -inline BufferHandle::BufferHandle() { upb_bufhandle_init(this); } -inline BufferHandle::~BufferHandle() { upb_bufhandle_uninit(this); } -inline const char* BufferHandle::buffer() const { - return upb_bufhandle_buf(this); -} -inline size_t BufferHandle::object_offset() const { - return upb_bufhandle_objofs(this); -} -inline void BufferHandle::SetBuffer(const char* buf, size_t ofs) { - upb_bufhandle_setbuf(this, buf, ofs); -} -template -void BufferHandle::SetAttachedObject(const T* obj) { - upb_bufhandle_setobj(this, obj, UniquePtrForType()); -} -template -const T* BufferHandle::GetAttachedObject() const { - return upb_bufhandle_objtype(this) == UniquePtrForType() - ? static_cast(upb_bufhandle_obj(this)) - : NULL; -} - -inline reffed_ptr Handlers::New(const MessageDef *m) { - upb_handlers *h = upb_handlers_new(m, &h); - return reffed_ptr(h, &h); -} -inline reffed_ptr Handlers::NewFrozen( - const MessageDef *m, upb_handlers_callback *callback, - const void *closure) { - const upb_handlers *h = upb_handlers_newfrozen(m, &h, callback, closure); - return reffed_ptr(h, &h); -} -inline const Status* Handlers::status() { - return upb_handlers_status(this); -} -inline void Handlers::ClearError() { - return upb_handlers_clearerr(this); -} -inline bool Handlers::Freeze(Status *s) { - upb::Handlers* h = this; - return upb_handlers_freeze(&h, 1, s); -} -inline bool Handlers::Freeze(Handlers *const *handlers, int n, Status *s) { - return upb_handlers_freeze(handlers, n, s); -} -inline bool Handlers::Freeze(const std::vector& h, Status* status) { - return upb_handlers_freeze((Handlers* const*)&h[0], h.size(), status); -} -inline const MessageDef *Handlers::message_def() const { - return upb_handlers_msgdef(this); -} -inline bool Handlers::AddCleanup(void *p, upb_handlerfree *func) { - return upb_handlers_addcleanup(this, p, func); -} -inline bool Handlers::SetStartMessageHandler( - const Handlers::StartMessageHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstartmsg(this, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetEndMessageHandler( - const Handlers::EndMessageHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setendmsg(this, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetStartStringHandler(const FieldDef *f, - const StartStringHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstartstr(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetEndStringHandler(const FieldDef *f, - const EndFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setendstr(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetStringHandler(const FieldDef *f, - const StringHandler& handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstring(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetStartSequenceHandler( - const FieldDef *f, const StartFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstartseq(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetStartSubMessageHandler( - const FieldDef *f, const StartFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstartsubmsg(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetEndSubMessageHandler(const FieldDef *f, - const EndFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setendsubmsg(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetEndSequenceHandler(const FieldDef *f, - const EndFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setendseq(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetSubHandlers(const FieldDef *f, const Handlers *sub) { - return upb_handlers_setsubhandlers(this, f, sub); -} -inline const Handlers *Handlers::GetSubHandlers(const FieldDef *f) const { - return upb_handlers_getsubhandlers(this, f); -} -inline const Handlers *Handlers::GetSubHandlers(Handlers::Selector sel) const { - return upb_handlers_getsubhandlers_sel(this, sel); -} -inline bool Handlers::GetSelector(const FieldDef *f, Handlers::Type type, - Handlers::Selector *s) { - return upb_handlers_getselector(f, type, s); -} -inline Handlers::Selector Handlers::GetEndSelector(Handlers::Selector start) { - return upb_handlers_getendselector(start); -} -inline Handlers::GenericFunction *Handlers::GetHandler( - Handlers::Selector selector) { - return upb_handlers_gethandler(this, selector); -} -inline const void *Handlers::GetHandlerData(Handlers::Selector selector) { - return upb_handlers_gethandlerdata(this, selector); -} - -inline BytesHandler::BytesHandler() { - upb_byteshandler_init(this); -} - -inline BytesHandler::~BytesHandler() {} - -} /* namespace upb */ - -#endif /* __cplusplus */ - - -#undef UPB_TWO_32BIT_TYPES -#undef UPB_TWO_64BIT_TYPES -#undef UPB_INT32_T -#undef UPB_UINT32_T -#undef UPB_INT32ALT_T -#undef UPB_UINT32ALT_T -#undef UPB_INT64_T -#undef UPB_UINT64_T -#undef UPB_INT64ALT_T -#undef UPB_UINT64ALT_T - -#endif /* UPB_HANDLERS_INL_H_ */ - -#endif /* UPB_HANDLERS_H */ -/* -** upb::Sink (upb_sink) -** upb::BytesSink (upb_bytessink) -** -** A upb_sink is an object that binds a upb_handlers object to some runtime -** state. It is the object that can actually receive data via the upb_handlers -** interface. -** -** Unlike upb_def and upb_handlers, upb_sink is never frozen, immutable, or -** thread-safe. You can create as many of them as you want, but each one may -** only be used in a single thread at a time. -** -** If we compare with class-based OOP, a you can think of a upb_def as an -** abstract base class, a upb_handlers as a concrete derived class, and a -** upb_sink as an object (class instance). -*/ - -#ifndef UPB_SINK_H -#define UPB_SINK_H - - -#ifdef __cplusplus -namespace upb { -class BufferSink; -class BufferSource; -class BytesSink; -class Sink; -} -#endif - -UPB_DECLARE_TYPE(upb::BufferSink, upb_bufsink) -UPB_DECLARE_TYPE(upb::BufferSource, upb_bufsrc) -UPB_DECLARE_TYPE(upb::BytesSink, upb_bytessink) -UPB_DECLARE_TYPE(upb::Sink, upb_sink) - -#ifdef __cplusplus - -/* A upb::Sink is an object that binds a upb::Handlers object to some runtime - * state. It represents an endpoint to which data can be sent. - * - * TODO(haberman): right now all of these functions take selectors. Should they - * take selectorbase instead? - * - * ie. instead of calling: - * sink->StartString(FOO_FIELD_START_STRING, ...) - * a selector base would let you say: - * sink->StartString(FOO_FIELD, ...) - * - * This would make call sites a little nicer and require emitting fewer selector - * definitions in .h files. - * - * But the current scheme has the benefit that you can retrieve a function - * pointer for any handler with handlers->GetHandler(selector), without having - * to have a separate GetHandler() function for each handler type. The JIT - * compiler uses this. To accommodate we'd have to expose a separate - * GetHandler() for every handler type. - * - * Also to ponder: selectors right now are independent of a specific Handlers - * instance. In other words, they allocate a number to every possible handler - * that *could* be registered, without knowing anything about what handlers - * *are* registered. That means that using selectors as table offsets prohibits - * us from compacting the handler table at Freeze() time. If the table is very - * sparse, this could be wasteful. - * - * Having another selector-like thing that is specific to a Handlers instance - * would allow this compacting, but then it would be impossible to write code - * ahead-of-time that can be bound to any Handlers instance at runtime. For - * example, a .proto file parser written as straight C will not know what - * Handlers it will be bound to, so when it calls sink->StartString() what - * selector will it pass? It needs a selector like we have today, that is - * independent of any particular upb::Handlers. - * - * Is there a way then to allow Handlers table compaction? */ -class upb::Sink { - public: - /* Constructor with no initialization; must be Reset() before use. */ - Sink() {} - - /* Constructs a new sink for the given frozen handlers and closure. - * - * TODO: once the Handlers know the expected closure type, verify that T - * matches it. */ - template Sink(const Handlers* handlers, T* closure); - - /* Resets the value of the sink. */ - template void Reset(const Handlers* handlers, T* closure); - - /* Returns the top-level object that is bound to this sink. - * - * TODO: once the Handlers know the expected closure type, verify that T - * matches it. */ - template T* GetObject() const; - - /* Functions for pushing data into the sink. - * - * These return false if processing should stop (either due to error or just - * to suspend). - * - * These may not be called from within one of the same sink's handlers (in - * other words, handlers are not re-entrant). */ - - /* Should be called at the start and end of every message; both the top-level - * message and submessages. This means that submessages should use the - * following sequence: - * sink->StartSubMessage(startsubmsg_selector); - * sink->StartMessage(); - * // ... - * sink->EndMessage(&status); - * sink->EndSubMessage(endsubmsg_selector); */ - bool StartMessage(); - bool EndMessage(Status* status); - - /* Putting of individual values. These work for both repeated and - * non-repeated fields, but for repeated fields you must wrap them in - * calls to StartSequence()/EndSequence(). */ - bool PutInt32(Handlers::Selector s, int32_t val); - bool PutInt64(Handlers::Selector s, int64_t val); - bool PutUInt32(Handlers::Selector s, uint32_t val); - bool PutUInt64(Handlers::Selector s, uint64_t val); - bool PutFloat(Handlers::Selector s, float val); - bool PutDouble(Handlers::Selector s, double val); - bool PutBool(Handlers::Selector s, bool val); - - /* Putting of string/bytes values. Each string can consist of zero or more - * non-contiguous buffers of data. - * - * For StartString(), the function will write a sink for the string to "sub." - * The sub-sink must be used for any/all PutStringBuffer() calls. */ - bool StartString(Handlers::Selector s, size_t size_hint, Sink* sub); - size_t PutStringBuffer(Handlers::Selector s, const char *buf, size_t len, - const BufferHandle *handle); - bool EndString(Handlers::Selector s); - - /* For submessage fields. - * - * For StartSubMessage(), the function will write a sink for the string to - * "sub." The sub-sink must be used for any/all handlers called within the - * submessage. */ - bool StartSubMessage(Handlers::Selector s, Sink* sub); - bool EndSubMessage(Handlers::Selector s); - - /* For repeated fields of any type, the sequence of values must be wrapped in - * these calls. - * - * For StartSequence(), the function will write a sink for the string to - * "sub." The sub-sink must be used for any/all handlers called within the - * sequence. */ - bool StartSequence(Handlers::Selector s, Sink* sub); - bool EndSequence(Handlers::Selector s); - - /* Copy and assign specifically allowed. - * We don't even bother making these members private because so many - * functions need them and this is mainly just a dumb data container anyway. - */ -#else -struct upb_sink { -#endif - const upb_handlers *handlers; - void *closure; -}; - -#ifdef __cplusplus -class upb::BytesSink { - public: - BytesSink() {} - - /* Constructs a new sink for the given frozen handlers and closure. - * - * TODO(haberman): once the Handlers know the expected closure type, verify - * that T matches it. */ - template BytesSink(const BytesHandler* handler, T* closure); - - /* Resets the value of the sink. */ - template void Reset(const BytesHandler* handler, T* closure); - - bool Start(size_t size_hint, void **subc); - size_t PutBuffer(void *subc, const char *buf, size_t len, - const BufferHandle *handle); - bool End(); -#else -struct upb_bytessink { -#endif - const upb_byteshandler *handler; - void *closure; -}; - -#ifdef __cplusplus - -/* A class for pushing a flat buffer of data to a BytesSink. - * You can construct an instance of this to get a resumable source, - * or just call the static PutBuffer() to do a non-resumable push all in one - * go. */ -class upb::BufferSource { - public: - BufferSource(); - BufferSource(const char* buf, size_t len, BytesSink* sink); - - /* Returns true if the entire buffer was pushed successfully. Otherwise the - * next call to PutNext() will resume where the previous one left off. - * TODO(haberman): implement this. */ - bool PutNext(); - - /* A static version; with this version is it not possible to resume in the - * case of failure or a partially-consumed buffer. */ - static bool PutBuffer(const char* buf, size_t len, BytesSink* sink); - - template static bool PutBuffer(const T& str, BytesSink* sink) { - return PutBuffer(str.c_str(), str.size(), sink); - } -#else -struct upb_bufsrc { - char dummy; -#endif -}; - -UPB_BEGIN_EXTERN_C - -/* A class for accumulating output string data in a flat buffer. */ - -upb_bufsink *upb_bufsink_new(upb_env *env); -void upb_bufsink_free(upb_bufsink *sink); -upb_bytessink *upb_bufsink_sink(upb_bufsink *sink); -const char *upb_bufsink_getdata(const upb_bufsink *sink, size_t *len); - -/* Inline definitions. */ - -UPB_INLINE void upb_bytessink_reset(upb_bytessink *s, const upb_byteshandler *h, - void *closure) { - s->handler = h; - s->closure = closure; -} - -UPB_INLINE bool upb_bytessink_start(upb_bytessink *s, size_t size_hint, - void **subc) { - typedef upb_startstr_handlerfunc func; - func *start; - *subc = s->closure; - if (!s->handler) return true; - start = (func *)s->handler->table[UPB_STARTSTR_SELECTOR].func; - - if (!start) return true; - *subc = start(s->closure, upb_handlerattr_handlerdata( - &s->handler->table[UPB_STARTSTR_SELECTOR].attr), - size_hint); - return *subc != NULL; -} - -UPB_INLINE size_t upb_bytessink_putbuf(upb_bytessink *s, void *subc, - const char *buf, size_t size, - const upb_bufhandle* handle) { - typedef upb_string_handlerfunc func; - func *putbuf; - if (!s->handler) return true; - putbuf = (func *)s->handler->table[UPB_STRING_SELECTOR].func; - - if (!putbuf) return true; - return putbuf(subc, upb_handlerattr_handlerdata( - &s->handler->table[UPB_STRING_SELECTOR].attr), - buf, size, handle); -} - -UPB_INLINE bool upb_bytessink_end(upb_bytessink *s) { - typedef upb_endfield_handlerfunc func; - func *end; - if (!s->handler) return true; - end = (func *)s->handler->table[UPB_ENDSTR_SELECTOR].func; - - if (!end) return true; - return end(s->closure, - upb_handlerattr_handlerdata( - &s->handler->table[UPB_ENDSTR_SELECTOR].attr)); -} - -bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink *sink); - -#define PUTVAL(type, ctype) \ - UPB_INLINE bool upb_sink_put##type(upb_sink *s, upb_selector_t sel, \ - ctype val) { \ - typedef upb_##type##_handlerfunc functype; \ - functype *func; \ - const void *hd; \ - if (!s->handlers) return true; \ - func = (functype *)upb_handlers_gethandler(s->handlers, sel); \ - if (!func) return true; \ - hd = upb_handlers_gethandlerdata(s->handlers, sel); \ - return func(s->closure, hd, val); \ - } - -PUTVAL(int32, int32_t) -PUTVAL(int64, int64_t) -PUTVAL(uint32, uint32_t) -PUTVAL(uint64, uint64_t) -PUTVAL(float, float) -PUTVAL(double, double) -PUTVAL(bool, bool) -#undef PUTVAL - -UPB_INLINE void upb_sink_reset(upb_sink *s, const upb_handlers *h, void *c) { - s->handlers = h; - s->closure = c; -} - -UPB_INLINE size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel, - const char *buf, size_t n, - const upb_bufhandle *handle) { - typedef upb_string_handlerfunc func; - func *handler; - const void *hd; - if (!s->handlers) return n; - handler = (func *)upb_handlers_gethandler(s->handlers, sel); - - if (!handler) return n; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - return handler(s->closure, hd, buf, n, handle); -} - -UPB_INLINE bool upb_sink_startmsg(upb_sink *s) { - typedef upb_startmsg_handlerfunc func; - func *startmsg; - const void *hd; - if (!s->handlers) return true; - startmsg = (func*)upb_handlers_gethandler(s->handlers, UPB_STARTMSG_SELECTOR); - - if (!startmsg) return true; - hd = upb_handlers_gethandlerdata(s->handlers, UPB_STARTMSG_SELECTOR); - return startmsg(s->closure, hd); -} - -UPB_INLINE bool upb_sink_endmsg(upb_sink *s, upb_status *status) { - typedef upb_endmsg_handlerfunc func; - func *endmsg; - const void *hd; - if (!s->handlers) return true; - endmsg = (func *)upb_handlers_gethandler(s->handlers, UPB_ENDMSG_SELECTOR); - - if (!endmsg) return true; - hd = upb_handlers_gethandlerdata(s->handlers, UPB_ENDMSG_SELECTOR); - return endmsg(s->closure, hd, status); -} - -UPB_INLINE bool upb_sink_startseq(upb_sink *s, upb_selector_t sel, - upb_sink *sub) { - typedef upb_startfield_handlerfunc func; - func *startseq; - const void *hd; - sub->closure = s->closure; - sub->handlers = s->handlers; - if (!s->handlers) return true; - startseq = (func*)upb_handlers_gethandler(s->handlers, sel); - - if (!startseq) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - sub->closure = startseq(s->closure, hd); - return sub->closure ? true : false; -} - -UPB_INLINE bool upb_sink_endseq(upb_sink *s, upb_selector_t sel) { - typedef upb_endfield_handlerfunc func; - func *endseq; - const void *hd; - if (!s->handlers) return true; - endseq = (func*)upb_handlers_gethandler(s->handlers, sel); - - if (!endseq) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - return endseq(s->closure, hd); -} - -UPB_INLINE bool upb_sink_startstr(upb_sink *s, upb_selector_t sel, - size_t size_hint, upb_sink *sub) { - typedef upb_startstr_handlerfunc func; - func *startstr; - const void *hd; - sub->closure = s->closure; - sub->handlers = s->handlers; - if (!s->handlers) return true; - startstr = (func*)upb_handlers_gethandler(s->handlers, sel); - - if (!startstr) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - sub->closure = startstr(s->closure, hd, size_hint); - return sub->closure ? true : false; -} - -UPB_INLINE bool upb_sink_endstr(upb_sink *s, upb_selector_t sel) { - typedef upb_endfield_handlerfunc func; - func *endstr; - const void *hd; - if (!s->handlers) return true; - endstr = (func*)upb_handlers_gethandler(s->handlers, sel); - - if (!endstr) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - return endstr(s->closure, hd); -} - -UPB_INLINE bool upb_sink_startsubmsg(upb_sink *s, upb_selector_t sel, - upb_sink *sub) { - typedef upb_startfield_handlerfunc func; - func *startsubmsg; - const void *hd; - sub->closure = s->closure; - if (!s->handlers) { - sub->handlers = NULL; - return true; - } - sub->handlers = upb_handlers_getsubhandlers_sel(s->handlers, sel); - startsubmsg = (func*)upb_handlers_gethandler(s->handlers, sel); - - if (!startsubmsg) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - sub->closure = startsubmsg(s->closure, hd); - return sub->closure ? true : false; -} - -UPB_INLINE bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) { - typedef upb_endfield_handlerfunc func; - func *endsubmsg; - const void *hd; - if (!s->handlers) return true; - endsubmsg = (func*)upb_handlers_gethandler(s->handlers, sel); - - if (!endsubmsg) return s->closure; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - return endsubmsg(s->closure, hd); -} - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { - -template Sink::Sink(const Handlers* handlers, T* closure) { - upb_sink_reset(this, handlers, closure); -} -template -inline void Sink::Reset(const Handlers* handlers, T* closure) { - upb_sink_reset(this, handlers, closure); -} -inline bool Sink::StartMessage() { - return upb_sink_startmsg(this); -} -inline bool Sink::EndMessage(Status* status) { - return upb_sink_endmsg(this, status); -} -inline bool Sink::PutInt32(Handlers::Selector sel, int32_t val) { - return upb_sink_putint32(this, sel, val); -} -inline bool Sink::PutInt64(Handlers::Selector sel, int64_t val) { - return upb_sink_putint64(this, sel, val); -} -inline bool Sink::PutUInt32(Handlers::Selector sel, uint32_t val) { - return upb_sink_putuint32(this, sel, val); -} -inline bool Sink::PutUInt64(Handlers::Selector sel, uint64_t val) { - return upb_sink_putuint64(this, sel, val); -} -inline bool Sink::PutFloat(Handlers::Selector sel, float val) { - return upb_sink_putfloat(this, sel, val); -} -inline bool Sink::PutDouble(Handlers::Selector sel, double val) { - return upb_sink_putdouble(this, sel, val); -} -inline bool Sink::PutBool(Handlers::Selector sel, bool val) { - return upb_sink_putbool(this, sel, val); -} -inline bool Sink::StartString(Handlers::Selector sel, size_t size_hint, - Sink *sub) { - return upb_sink_startstr(this, sel, size_hint, sub); -} -inline size_t Sink::PutStringBuffer(Handlers::Selector sel, const char *buf, - size_t len, const BufferHandle* handle) { - return upb_sink_putstring(this, sel, buf, len, handle); -} -inline bool Sink::EndString(Handlers::Selector sel) { - return upb_sink_endstr(this, sel); -} -inline bool Sink::StartSubMessage(Handlers::Selector sel, Sink* sub) { - return upb_sink_startsubmsg(this, sel, sub); -} -inline bool Sink::EndSubMessage(Handlers::Selector sel) { - return upb_sink_endsubmsg(this, sel); -} -inline bool Sink::StartSequence(Handlers::Selector sel, Sink* sub) { - return upb_sink_startseq(this, sel, sub); -} -inline bool Sink::EndSequence(Handlers::Selector sel) { - return upb_sink_endseq(this, sel); -} - -template -BytesSink::BytesSink(const BytesHandler* handler, T* closure) { - Reset(handler, closure); -} - -template -void BytesSink::Reset(const BytesHandler *handler, T *closure) { - upb_bytessink_reset(this, handler, closure); -} -inline bool BytesSink::Start(size_t size_hint, void **subc) { - return upb_bytessink_start(this, size_hint, subc); -} -inline size_t BytesSink::PutBuffer(void *subc, const char *buf, size_t len, - const BufferHandle *handle) { - return upb_bytessink_putbuf(this, subc, buf, len, handle); -} -inline bool BytesSink::End() { - return upb_bytessink_end(this); -} - -inline bool BufferSource::PutBuffer(const char *buf, size_t len, - BytesSink *sink) { - return upb_bufsrc_putbuf(buf, len, sink); -} - -} /* namespace upb */ -#endif - -#endif -/* -** upb::Message is a representation for protobuf messages. -** -** However it differs from other common representations like -** google::protobuf::Message in one key way: it does not prescribe any -** ownership between messages and submessages, and it relies on the -** client to delete each message/submessage/array/map at the appropriate -** time. -** -** A client can access a upb::Message without knowing anything about -** ownership semantics, but to create or mutate a message a user needs -** to implement the memory management themselves. -** -** Currently all messages, arrays, and maps store a upb_alloc* internally. -** Mutating operations use this when they require dynamically-allocated -** memory. We could potentially eliminate this size overhead later by -** letting the user flip a bit on the factory that prevents this from -** being stored. The user would then need to use separate functions where -** the upb_alloc* is passed explicitly. However for handlers to populate -** such structures, they would need a place to store this upb_alloc* during -** parsing; upb_handlers don't currently have a good way to accommodate this. -** -** TODO: UTF-8 checking? -**/ - -#ifndef UPB_MSG_H_ -#define UPB_MSG_H_ - - -#ifdef __cplusplus - -namespace upb { -class Array; -class Map; -class MapIterator; -class MessageFactory; -class MessageLayout; -class Visitor; -class VisitorPlan; -} - -#endif - -UPB_DECLARE_TYPE(upb::MessageFactory, upb_msgfactory) -UPB_DECLARE_TYPE(upb::MessageLayout, upb_msglayout) -UPB_DECLARE_TYPE(upb::Array, upb_array) -UPB_DECLARE_TYPE(upb::Map, upb_map) -UPB_DECLARE_TYPE(upb::MapIterator, upb_mapiter) -UPB_DECLARE_TYPE(upb::Visitor, upb_visitor) -UPB_DECLARE_TYPE(upb::VisitorPlan, upb_visitorplan) - -/* TODO(haberman): C++ accessors */ - -UPB_BEGIN_EXTERN_C - -typedef void upb_msg; - - -/** upb_msglayout *************************************************************/ - -/* upb_msglayout represents the memory layout of a given upb_msgdef. You get - * instances of this from a upb_msgfactory, and the factory always owns the - * msglayout. */ - -/* Gets the factory for this layout */ -upb_msgfactory *upb_msglayout_factory(const upb_msglayout *l); - -/* Get the msglayout for a submessage. This requires that this field is a - * submessage, ie. upb_fielddef_issubmsg(upb_msglayout_msgdef(l)) == true. - * - * Since map entry messages don't have layouts, if upb_fielddef_ismap(f) == true - * then this function will return the layout for the map's value. It requires - * that the value type of the map field is a submessage. */ -const upb_msglayout *upb_msglayout_sublayout(const upb_msglayout *l, - const upb_fielddef *f); - -/* Returns the msgdef for this msglayout. */ -const upb_msgdef *upb_msglayout_msgdef(const upb_msglayout *l); - - -/** upb_visitor ***************************************************************/ - -/* upb_visitor will visit all the fields of a message and its submessages. It - * uses a upb_visitorplan which you can obtain from a upb_msgfactory. */ - -upb_visitor *upb_visitor_create(upb_env *e, const upb_visitorplan *vp, - upb_sink *output); -bool upb_visitor_visitmsg(upb_visitor *v, const upb_msg *msg); - - -/** upb_msgfactory ************************************************************/ - -/* A upb_msgfactory contains a cache of upb_msglayout, upb_handlers, and - * upb_visitorplan objects. These are the objects necessary to represent, - * populate, and and visit upb_msg objects. - * - * These caches are all populated by upb_msgdef, and lazily created on demand. - */ - -/* Creates and destroys a msgfactory, respectively. The messages for this - * msgfactory must come from |symtab| (which should outlive the msgfactory). */ -upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab); -void upb_msgfactory_free(upb_msgfactory *f); - -const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f); - -/* The functions to get cached objects, lazily creating them on demand. These - * all require: - * - * - m is in upb_msgfactory_symtab(f) - * - upb_msgdef_mapentry(m) == false (since map messages can't have layouts). - * - * The returned objects will live for as long as the msgfactory does. - * - * TODO(haberman): consider making this thread-safe and take a const - * upb_msgfactory. */ -const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f, - const upb_msgdef *m); -const upb_handlers *upb_msgfactory_getmergehandlers(upb_msgfactory *f, - const upb_msgdef *m); -const upb_visitorplan *upb_msgfactory_getvisitorplan(upb_msgfactory *f, - const upb_handlers *h); - - -/** upb_msgval ****************************************************************/ - -/* A union representing all possible protobuf values. Used for generic get/set - * operations. */ - -typedef union { - bool b; - float flt; - double dbl; - int32_t i32; - int64_t i64; - uint32_t u32; - uint64_t u64; - const upb_map* map; - const upb_msg* msg; - const upb_array* arr; - const void* ptr; - struct { - const char *ptr; - size_t len; - } str; -} upb_msgval; - -#define ACCESSORS(name, membername, ctype) \ - UPB_INLINE ctype upb_msgval_get ## name(upb_msgval v) { \ - return v.membername; \ - } \ - UPB_INLINE void upb_msgval_set ## name(upb_msgval *v, ctype cval) { \ - v->membername = cval; \ - } \ - UPB_INLINE upb_msgval upb_msgval_ ## name(ctype v) { \ - upb_msgval ret; \ - ret.membername = v; \ - return ret; \ - } - -ACCESSORS(bool, b, bool) -ACCESSORS(float, flt, float) -ACCESSORS(double, dbl, double) -ACCESSORS(int32, i32, int32_t) -ACCESSORS(int64, i64, int64_t) -ACCESSORS(uint32, u32, uint32_t) -ACCESSORS(uint64, u64, uint64_t) -ACCESSORS(map, map, const upb_map*) -ACCESSORS(msg, msg, const upb_msg*) -ACCESSORS(ptr, ptr, const void*) -ACCESSORS(arr, arr, const upb_array*) - -#undef ACCESSORS - -UPB_INLINE upb_msgval upb_msgval_str(const char *ptr, size_t len) { - upb_msgval ret; - ret.str.ptr = ptr; - ret.str.len = len; - return ret; -} - -UPB_INLINE const char* upb_msgval_getstr(upb_msgval val) { - return val.str.ptr; -} - -UPB_INLINE size_t upb_msgval_getstrlen(upb_msgval val) { - return val.str.len; -} - - -/** upb_msg *******************************************************************/ - -/* A upb_msg represents a protobuf message. It always corresponds to a specific - * upb_msglayout, which describes how it is laid out in memory. - * - * The message will have a fixed size, as returned by upb_msg_sizeof(), which - * will be used to store fixed-length fields. The upb_msg may also allocate - * dynamic memory internally to store data such as: - * - * - extensions - * - unknown fields - */ - -/* Returns the size of a message given this layout. */ -size_t upb_msg_sizeof(const upb_msglayout *l); - -/* upb_msg_init() / upb_msg_uninit() allow the user to use a pre-allocated - * block of memory as a message. The block's size should be upb_msg_sizeof(). - * upb_msg_uninit() must be called to release internally-allocated memory - * unless the allocator is an arena that does not require freeing. - * - * Please note that upb_msg_uninit() does *not* free any submessages, maps, - * or arrays referred to by this message's fields. You must free them manually - * yourself. */ -void upb_msg_init(upb_msg *msg, const upb_msglayout *l, upb_alloc *a); -void upb_msg_uninit(upb_msg *msg, const upb_msglayout *l); - -/* Like upb_msg_init() / upb_msg_uninit(), except the message's memory is - * allocated / freed from the given upb_alloc. */ -upb_msg *upb_msg_new(const upb_msglayout *l, upb_alloc *a); -void upb_msg_free(upb_msg *msg, const upb_msglayout *l); - -/* Returns the upb_alloc for the given message. */ -upb_alloc *upb_msg_alloc(const upb_msg *msg, const upb_msglayout *l); - -/* Packs the tree of messages rooted at "msg" into a single hunk of memory, - * allocated from the given allocator. */ -void *upb_msg_pack(const upb_msg *msg, const upb_msglayout *l, - void *p, size_t *ofs, size_t size); - -/* Read-only message API. Can be safely called by anyone. */ - -/* Returns the value associated with this field: - * - for scalar fields (including strings), the value directly. - * - return upb_msg*, or upb_map* for msg/map. - * If the field is unset for these field types, returns NULL. - * - * TODO(haberman): should we let users store cached array/map/msg - * pointers here for fields that are unset? Could be useful for the - * strongly-owned submessage model (ie. generated C API that doesn't use - * arenas). - */ -upb_msgval upb_msg_get(const upb_msg *msg, - const upb_fielddef *f, - const upb_msglayout *l); - -/* May only be called for fields where upb_fielddef_haspresence(f) == true. */ -bool upb_msg_has(const upb_msg *msg, - const upb_fielddef *f, - const upb_msglayout *l); - -/* Returns NULL if no field in the oneof is set. */ -const upb_fielddef *upb_msg_getoneofcase(const upb_msg *msg, - const upb_oneofdef *o, - const upb_msglayout *l); - -/* Returns true if any field in the oneof is set. */ -bool upb_msg_hasoneof(const upb_msg *msg, - const upb_oneofdef *o, - const upb_msglayout *l); - - -/* Mutable message API. May only be called by the owner of the message who - * knows its ownership scheme and how to keep it consistent. */ - -/* Sets the given field to the given value. Does not perform any memory - * management: if you overwrite a pointer to a msg/array/map/string without - * cleaning it up (or using an arena) it will leak. - */ -bool upb_msg_set(upb_msg *msg, - const upb_fielddef *f, - upb_msgval val, - const upb_msglayout *l); - -/* For a primitive field, set it back to its default. For repeated, string, and - * submessage fields set it back to NULL. This could involve releasing some - * internal memory (for example, from an extension dictionary), but it is not - * recursive in any way and will not recover any memory that may be used by - * arrays/maps/strings/msgs that this field may have pointed to. - */ -bool upb_msg_clearfield(upb_msg *msg, - const upb_fielddef *f, - const upb_msglayout *l); - -/* Clears all fields in the oneof such that none of them are set. */ -bool upb_msg_clearoneof(upb_msg *msg, - const upb_oneofdef *o, - const upb_msglayout *l); - -/* TODO(haberman): copyfrom()/mergefrom()? */ - - -/** upb_array *****************************************************************/ - -/* A upb_array stores data for a repeated field. The memory management - * semantics are the same as upb_msg. A upb_array allocates dynamic - * memory internally for the array elements. */ - -size_t upb_array_sizeof(upb_fieldtype_t type); -void upb_array_init(upb_array *arr, upb_fieldtype_t type, upb_alloc *a); -void upb_array_uninit(upb_array *arr); -upb_array *upb_array_new(upb_fieldtype_t type, upb_alloc *a); -void upb_array_free(upb_array *arr); - -/* Read-only interface. Safe for anyone to call. */ - -size_t upb_array_size(const upb_array *arr); -upb_fieldtype_t upb_array_type(const upb_array *arr); -upb_msgval upb_array_get(const upb_array *arr, size_t i); - -/* Write interface. May only be called by the message's owner who can enforce - * its memory management invariants. */ - -bool upb_array_set(upb_array *arr, size_t i, upb_msgval val); - - -/** upb_map *******************************************************************/ - -/* A upb_map stores data for a map field. The memory management semantics are - * the same as upb_msg, with one notable exception. upb_map will internally - * store a copy of all string keys, but *not* any string values or submessages. - * So you must ensure that any string or message values outlive the map, and you - * must delete them manually when they are no longer required. */ - -size_t upb_map_sizeof(upb_fieldtype_t ktype, upb_fieldtype_t vtype); -bool upb_map_init(upb_map *map, upb_fieldtype_t ktype, upb_fieldtype_t vtype, - upb_alloc *a); -void upb_map_uninit(upb_map *map); -upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype, upb_alloc *a); -void upb_map_free(upb_map *map); - -/* Read-only interface. Safe for anyone to call. */ - -size_t upb_map_size(const upb_map *map); -upb_fieldtype_t upb_map_keytype(const upb_map *map); -upb_fieldtype_t upb_map_valuetype(const upb_map *map); -bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val); - -/* Write interface. May only be called by the message's owner who can enforce - * its memory management invariants. */ - -/* Sets or overwrites an entry in the map. Return value indicates whether - * the operation succeeded or failed with OOM, and also whether an existing - * key was replaced or not. */ -bool upb_map_set(upb_map *map, - upb_msgval key, upb_msgval val, - upb_msgval *valremoved); - -/* Deletes an entry in the map. Returns true if the key was present. */ -bool upb_map_del(upb_map *map, upb_msgval key); - - -/** upb_mapiter ***************************************************************/ - -/* For iterating over a map. Map iterators are invalidated by mutations to the - * map, but an invalidated iterator will never return junk or crash the process. - * An invalidated iterator may return entries that were already returned though, - * and if you keep invalidating the iterator during iteration, the program may - * enter an infinite loop. */ - -size_t upb_mapiter_sizeof(); - -void upb_mapiter_begin(upb_mapiter *i, const upb_map *t); -upb_mapiter *upb_mapiter_new(const upb_map *t, upb_alloc *a); -void upb_mapiter_free(upb_mapiter *i, upb_alloc *a); -void upb_mapiter_next(upb_mapiter *i); -bool upb_mapiter_done(const upb_mapiter *i); - -upb_msgval upb_mapiter_key(const upb_mapiter *i); -upb_msgval upb_mapiter_value(const upb_mapiter *i); -void upb_mapiter_setdone(upb_mapiter *i); -bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2); - - -/** Handlers ******************************************************************/ - -/* These are the handlers used internally by upb_msgfactory_getmergehandlers(). - * They write scalar data to a known offset from the message pointer. - * - * These would be trivial for anyone to implement themselves, but it's better - * to use these because some JITs will recognize and specialize these instead - * of actually calling the function. */ - -/* Sets a handler for the given primitive field that will write the data at the - * given offset. If hasbit > 0, also sets a hasbit at the given bit offset - * (addressing each byte low to high). */ -bool upb_msg_setscalarhandler(upb_handlers *h, - const upb_fielddef *f, - size_t offset, - int32_t hasbit); - -/* If the given handler is a msghandlers_primitive field, returns true and sets - * *type, *offset and *hasbit. Otherwise returns false. */ -bool upb_msg_getscalarhandlerdata(const upb_handlers *h, - upb_selector_t s, - upb_fieldtype_t *type, - size_t *offset, - int32_t *hasbit); - -UPB_END_EXTERN_C - -#endif /* UPB_MSG_H_ */ -/* -** upb::descriptor::Reader (upb_descreader) -** -** Provides a way of building upb::Defs from data in descriptor.proto format. -*/ - -#ifndef UPB_DESCRIPTOR_H -#define UPB_DESCRIPTOR_H - - -#ifdef __cplusplus -namespace upb { -namespace descriptor { -class Reader; -} /* namespace descriptor */ -} /* namespace upb */ -#endif - -UPB_DECLARE_TYPE(upb::descriptor::Reader, upb_descreader) - -#ifdef __cplusplus - -/* Class that receives descriptor data according to the descriptor.proto schema - * and use it to build upb::Defs corresponding to that schema. */ -class upb::descriptor::Reader { - public: - /* These handlers must have come from NewHandlers() and must outlive the - * Reader. - * - * TODO: generate the handlers statically (like we do with the - * descriptor.proto defs) so that there is no need to pass this parameter (or - * to build/memory-manage the handlers at runtime at all). Unfortunately this - * is a bit tricky to implement for Handlers, but necessary to simplify this - * interface. */ - static Reader* Create(Environment* env, const Handlers* handlers); - - /* The reader's input; this is where descriptor.proto data should be sent. */ - Sink* input(); - - /* Use to get the FileDefs that have been parsed. */ - size_t file_count() const; - FileDef* file(size_t i) const; - - /* Builds and returns handlers for the reader, owned by "owner." */ - static Handlers* NewHandlers(const void* owner); - - private: - UPB_DISALLOW_POD_OPS(Reader, upb::descriptor::Reader) -}; - -#endif - -UPB_BEGIN_EXTERN_C - -/* C API. */ -upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h); -upb_sink *upb_descreader_input(upb_descreader *r); -size_t upb_descreader_filecount(const upb_descreader *r); -upb_filedef *upb_descreader_file(const upb_descreader *r, size_t i); -const upb_handlers *upb_descreader_newhandlers(const void *owner); - -UPB_END_EXTERN_C - -#ifdef __cplusplus -/* C++ implementation details. ************************************************/ -namespace upb { -namespace descriptor { -inline Reader* Reader::Create(Environment* e, const Handlers *h) { - return upb_descreader_create(e, h); -} -inline Sink* Reader::input() { return upb_descreader_input(this); } -inline size_t Reader::file_count() const { - return upb_descreader_filecount(this); -} -inline FileDef* Reader::file(size_t i) const { - return upb_descreader_file(this, i); -} -} /* namespace descriptor */ -} /* namespace upb */ -#endif - -#endif /* UPB_DESCRIPTOR_H */ -/* This file contains accessors for a set of compiled-in defs. - * Note that unlike Google's protobuf, it does *not* define - * generated classes or any other kind of data structure for - * actually storing protobufs. It only contains *defs* which - * let you reflect over a protobuf *schema*. - */ -/* This file was generated by upbc (the upb compiler) from the input - * file: - * - * upb/descriptor/descriptor.proto - * - * Do not edit -- your changes will be discarded when the file is - * regenerated. */ - -#ifndef UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_ -#define UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_ - - -UPB_BEGIN_EXTERN_C - -/* Enums */ - -typedef enum { - google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1, - google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2, - google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3 -} google_protobuf_FieldDescriptorProto_Label; - -typedef enum { - google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1, - google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2, - google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3, - google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4, - google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5, - google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6, - google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7, - google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8, - google_protobuf_FieldDescriptorProto_TYPE_STRING = 9, - google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10, - google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11, - google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12, - google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13, - google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14, - google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15, - google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16, - google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17, - google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18 -} google_protobuf_FieldDescriptorProto_Type; - -typedef enum { - google_protobuf_FieldOptions_STRING = 0, - google_protobuf_FieldOptions_CORD = 1, - google_protobuf_FieldOptions_STRING_PIECE = 2 -} google_protobuf_FieldOptions_CType; - -typedef enum { - google_protobuf_FieldOptions_JS_NORMAL = 0, - google_protobuf_FieldOptions_JS_STRING = 1, - google_protobuf_FieldOptions_JS_NUMBER = 2 -} google_protobuf_FieldOptions_JSType; - -typedef enum { - google_protobuf_FileOptions_SPEED = 1, - google_protobuf_FileOptions_CODE_SIZE = 2, - google_protobuf_FileOptions_LITE_RUNTIME = 3 -} google_protobuf_FileOptions_OptimizeMode; - -/* MessageDefs: call these functions to get a ref to a msgdef. */ -const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_EnumOptions_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_FieldOptions_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_FileOptions_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_MessageOptions_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_MethodOptions_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_OneofDescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_ServiceOptions_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart_get(const void *owner); - -/* EnumDefs: call these functions to get a ref to an enumdef. */ -const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label_get(const void *owner); -const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type_get(const void *owner); -const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType_get(const void *owner); -const upb_enumdef *upbdefs_google_protobuf_FieldOptions_JSType_get(const void *owner); -const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode_get(const void *owner); - -/* Functions to test whether this message is of a certain type. */ -UPB_INLINE bool upbdefs_google_protobuf_DescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.DescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.DescriptorProto.ExtensionRange") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.DescriptorProto.ReservedRange") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_EnumDescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumDescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_EnumOptions_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumOptions") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_EnumValueDescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumValueDescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_EnumValueOptions_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumValueOptions") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FieldDescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.FieldDescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FieldOptions_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.FieldOptions") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FileDescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.FileDescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FileDescriptorSet_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.FileDescriptorSet") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FileOptions_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.FileOptions") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_MessageOptions_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.MessageOptions") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_MethodDescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.MethodDescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_MethodOptions_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.MethodOptions") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_OneofDescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.OneofDescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_ServiceDescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.ServiceDescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_ServiceOptions_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.ServiceOptions") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_SourceCodeInfo_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.SourceCodeInfo") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_SourceCodeInfo_Location_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.SourceCodeInfo.Location") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_UninterpretedOption_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.UninterpretedOption") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_UninterpretedOption_NamePart_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.UninterpretedOption.NamePart") == 0; -} - -/* Functions to test whether this enum is of a certain type. */ -UPB_INLINE bool upbdefs_google_protobuf_FieldDescriptorProto_Label_is(const upb_enumdef *e) { - return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldDescriptorProto.Label") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FieldDescriptorProto_Type_is(const upb_enumdef *e) { - return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldDescriptorProto.Type") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FieldOptions_CType_is(const upb_enumdef *e) { - return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldOptions.CType") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FieldOptions_JSType_is(const upb_enumdef *e) { - return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldOptions.JSType") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FileOptions_OptimizeMode_is(const upb_enumdef *e) { - return strcmp(upb_enumdef_fullname(e), "google.protobuf.FileOptions.OptimizeMode") == 0; -} - - -/* Functions to get a fielddef from a msgdef reference. */ -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_f_end(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_f_start(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_f_end(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_f_start(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_enum_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_extension(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_extension_range(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_field(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_nested_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_oneof_decl(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_reserved_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_reserved_range(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_f_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_f_allow_alias(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumOptions_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumOptions_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumOptions_is(m)); return upb_msgdef_itof(m, 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_f_number(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueOptions_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueOptions_is(m)); return upb_msgdef_itof(m, 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_default_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_extendee(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_json_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_label(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_number(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_oneof_index(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_type_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_ctype(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_jstype(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_lazy(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_packed(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_weak(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_dependency(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_enum_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_extension(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_message_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_package(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_public_dependency(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_service(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_source_code_info(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_syntax(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 12); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_weak_dependency(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 11); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorSet_f_file(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorSet_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_cc_enable_arenas(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 31); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_cc_generic_services(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 16); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_csharp_namespace(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 37); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 23); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_go_package(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 11); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_generate_equals_and_hash(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 20); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_generic_services(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 17); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_multiple_files(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_outer_classname(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_package(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_string_check_utf8(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 27); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_javanano_use_deprecated_package(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 38); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_objc_class_prefix(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 36); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_optimize_for(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_php_class_prefix(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 40); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_php_namespace(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 41); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_py_generic_services(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 18); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_map_entry(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_message_set_wire_format(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_no_standard_descriptor_accessor(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_client_streaming(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_input_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_output_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_server_streaming(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodOptions_is(m)); return upb_msgdef_itof(m, 33); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodOptions_is(m)); return upb_msgdef_itof(m, 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_OneofDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_OneofDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_f_method(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceOptions_is(m)); return upb_msgdef_itof(m, 33); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceOptions_is(m)); return upb_msgdef_itof(m, 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_leading_comments(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_leading_detached_comments(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_path(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_span(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_trailing_comments(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_f_location(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_f_is_extension(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_NamePart_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_f_name_part(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_NamePart_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_aggregate_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_double_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_identifier_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_negative_int_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_positive_int_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_string_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 7); } - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upbdefs { -namespace google { -namespace protobuf { - -class DescriptorProto : public ::upb::reffed_ptr { - public: - DescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); - } - - static DescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_get(&m); - return DescriptorProto(m, &m); - } - - class ExtensionRange : public ::upb::reffed_ptr { - public: - ExtensionRange(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(m)); - } - - static ExtensionRange get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(&m); - return ExtensionRange(m, &m); - } - }; - - class ReservedRange : public ::upb::reffed_ptr { - public: - ReservedRange(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(m)); - } - - static ReservedRange get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(&m); - return ReservedRange(m, &m); - } - }; -}; - -class EnumDescriptorProto : public ::upb::reffed_ptr { - public: - EnumDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); - } - - static EnumDescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumDescriptorProto_get(&m); - return EnumDescriptorProto(m, &m); - } -}; - -class EnumOptions : public ::upb::reffed_ptr { - public: - EnumOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_EnumOptions_is(m)); - } - - static EnumOptions get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumOptions_get(&m); - return EnumOptions(m, &m); - } -}; - -class EnumValueDescriptorProto : public ::upb::reffed_ptr { - public: - EnumValueDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); - } - - static EnumValueDescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumValueDescriptorProto_get(&m); - return EnumValueDescriptorProto(m, &m); - } -}; - -class EnumValueOptions : public ::upb::reffed_ptr { - public: - EnumValueOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_EnumValueOptions_is(m)); - } - - static EnumValueOptions get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumValueOptions_get(&m); - return EnumValueOptions(m, &m); - } -}; - -class FieldDescriptorProto : public ::upb::reffed_ptr { - public: - FieldDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); - } - - static FieldDescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_FieldDescriptorProto_get(&m); - return FieldDescriptorProto(m, &m); - } - - class Label : public ::upb::reffed_ptr { - public: - Label(const ::upb::EnumDef* e, const void *ref_donor = NULL) - : reffed_ptr(e, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_Label_is(e)); - } - static Label get() { - const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldDescriptorProto_Label_get(&e); - return Label(e, &e); - } - }; - - class Type : public ::upb::reffed_ptr { - public: - Type(const ::upb::EnumDef* e, const void *ref_donor = NULL) - : reffed_ptr(e, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_Type_is(e)); - } - static Type get() { - const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldDescriptorProto_Type_get(&e); - return Type(e, &e); - } - }; -}; - -class FieldOptions : public ::upb::reffed_ptr { - public: - FieldOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); - } - - static FieldOptions get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_FieldOptions_get(&m); - return FieldOptions(m, &m); - } - - class CType : public ::upb::reffed_ptr { - public: - CType(const ::upb::EnumDef* e, const void *ref_donor = NULL) - : reffed_ptr(e, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_CType_is(e)); - } - static CType get() { - const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldOptions_CType_get(&e); - return CType(e, &e); - } - }; - - class JSType : public ::upb::reffed_ptr { - public: - JSType(const ::upb::EnumDef* e, const void *ref_donor = NULL) - : reffed_ptr(e, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_JSType_is(e)); - } - static JSType get() { - const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldOptions_JSType_get(&e); - return JSType(e, &e); - } - }; -}; - -class FileDescriptorProto : public ::upb::reffed_ptr { - public: - FileDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); - } - - static FileDescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_FileDescriptorProto_get(&m); - return FileDescriptorProto(m, &m); - } -}; - -class FileDescriptorSet : public ::upb::reffed_ptr { - public: - FileDescriptorSet(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorSet_is(m)); - } - - static FileDescriptorSet get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_FileDescriptorSet_get(&m); - return FileDescriptorSet(m, &m); - } -}; - -class FileOptions : public ::upb::reffed_ptr { - public: - FileOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); - } - - static FileOptions get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_FileOptions_get(&m); - return FileOptions(m, &m); - } - - class OptimizeMode : public ::upb::reffed_ptr { - public: - OptimizeMode(const ::upb::EnumDef* e, const void *ref_donor = NULL) - : reffed_ptr(e, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FileOptions_OptimizeMode_is(e)); - } - static OptimizeMode get() { - const ::upb::EnumDef* e = upbdefs_google_protobuf_FileOptions_OptimizeMode_get(&e); - return OptimizeMode(e, &e); - } - }; -}; - -class MessageOptions : public ::upb::reffed_ptr { - public: - MessageOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); - } - - static MessageOptions get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_MessageOptions_get(&m); - return MessageOptions(m, &m); - } -}; - -class MethodDescriptorProto : public ::upb::reffed_ptr { - public: - MethodDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); - } - - static MethodDescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_MethodDescriptorProto_get(&m); - return MethodDescriptorProto(m, &m); - } -}; - -class MethodOptions : public ::upb::reffed_ptr { - public: - MethodOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_MethodOptions_is(m)); - } - - static MethodOptions get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_MethodOptions_get(&m); - return MethodOptions(m, &m); - } -}; - -class OneofDescriptorProto : public ::upb::reffed_ptr { - public: - OneofDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_OneofDescriptorProto_is(m)); - } - - static OneofDescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_OneofDescriptorProto_get(&m); - return OneofDescriptorProto(m, &m); - } -}; - -class ServiceDescriptorProto : public ::upb::reffed_ptr { - public: - ServiceDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_ServiceDescriptorProto_is(m)); - } - - static ServiceDescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_ServiceDescriptorProto_get(&m); - return ServiceDescriptorProto(m, &m); - } -}; - -class ServiceOptions : public ::upb::reffed_ptr { - public: - ServiceOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_ServiceOptions_is(m)); - } - - static ServiceOptions get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_ServiceOptions_get(&m); - return ServiceOptions(m, &m); - } -}; - -class SourceCodeInfo : public ::upb::reffed_ptr { - public: - SourceCodeInfo(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_is(m)); - } - - static SourceCodeInfo get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_SourceCodeInfo_get(&m); - return SourceCodeInfo(m, &m); - } - - class Location : public ::upb::reffed_ptr { - public: - Location(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); - } - - static Location get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_SourceCodeInfo_Location_get(&m); - return Location(m, &m); - } - }; -}; - -class UninterpretedOption : public ::upb::reffed_ptr { - public: - UninterpretedOption(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); - } - - static UninterpretedOption get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_UninterpretedOption_get(&m); - return UninterpretedOption(m, &m); - } - - class NamePart : public ::upb::reffed_ptr { - public: - NamePart(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_NamePart_is(m)); - } - - static NamePart get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_UninterpretedOption_NamePart_get(&m); - return NamePart(m, &m); - } - }; -}; - -} /* namespace protobuf */ -} /* namespace google */ -} /* namespace upbdefs */ - -#endif /* __cplusplus */ - -#endif /* UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_ */ -/* -** Internal-only definitions for the decoder. -*/ - -#ifndef UPB_DECODER_INT_H_ -#define UPB_DECODER_INT_H_ - -/* -** upb::pb::Decoder -** -** A high performance, streaming, resumable decoder for the binary protobuf -** format. -** -** This interface works the same regardless of what decoder backend is being -** used. A client of this class does not need to know whether decoding is using -** a JITted decoder (DynASM, LLVM, etc) or an interpreted decoder. By default, -** it will always use the fastest available decoder. However, you can call -** set_allow_jit(false) to disable any JIT decoder that might be available. -** This is primarily useful for testing purposes. -*/ - -#ifndef UPB_DECODER_H_ -#define UPB_DECODER_H_ - - -#ifdef __cplusplus -namespace upb { -namespace pb { -class CodeCache; -class Decoder; -class DecoderMethod; -class DecoderMethodOptions; -} /* namespace pb */ -} /* namespace upb */ -#endif - -UPB_DECLARE_TYPE(upb::pb::CodeCache, upb_pbcodecache) -UPB_DECLARE_TYPE(upb::pb::Decoder, upb_pbdecoder) -UPB_DECLARE_TYPE(upb::pb::DecoderMethodOptions, upb_pbdecodermethodopts) - -UPB_DECLARE_DERIVED_TYPE(upb::pb::DecoderMethod, upb::RefCounted, - upb_pbdecodermethod, upb_refcounted) - -/* The maximum number of bytes we are required to buffer internally between - * calls to the decoder. The value is 14: a 5 byte unknown tag plus ten-byte - * varint, less one because we are buffering an incomplete value. - * - * Should only be used by unit tests. */ -#define UPB_DECODER_MAX_RESIDUAL_BYTES 14 - -#ifdef __cplusplus - -/* The parameters one uses to construct a DecoderMethod. - * TODO(haberman): move allowjit here? Seems more convenient for users. - * TODO(haberman): move this to be heap allocated for ABI stability. */ -class upb::pb::DecoderMethodOptions { - public: - /* Parameter represents the destination handlers that this method will push - * to. */ - explicit DecoderMethodOptions(const Handlers* dest_handlers); - - /* Should the decoder push submessages to lazy handlers for fields that have - * them? The caller should set this iff the lazy handlers expect data that is - * in protobuf binary format and the caller wishes to lazy parse it. */ - void set_lazy(bool lazy); -#else -struct upb_pbdecodermethodopts { -#endif - const upb_handlers *handlers; - bool lazy; -}; - -#ifdef __cplusplus - -/* Represents the code to parse a protobuf according to a destination - * Handlers. */ -class upb::pb::DecoderMethod { - public: - /* Include base methods from upb::ReferenceCounted. */ - UPB_REFCOUNTED_CPPMETHODS - - /* The destination handlers that are statically bound to this method. - * This method is only capable of outputting to a sink that uses these - * handlers. */ - const Handlers* dest_handlers() const; - - /* The input handlers for this decoder method. */ - const BytesHandler* input_handler() const; - - /* Whether this method is native. */ - bool is_native() const; - - /* Convenience method for generating a DecoderMethod without explicitly - * creating a CodeCache. */ - static reffed_ptr New(const DecoderMethodOptions& opts); - - private: - UPB_DISALLOW_POD_OPS(DecoderMethod, upb::pb::DecoderMethod) -}; - -#endif - -/* Preallocation hint: decoder won't allocate more bytes than this when first - * constructed. This hint may be an overestimate for some build configurations. - * But if the decoder library is upgraded without recompiling the application, - * it may be an underestimate. */ -#define UPB_PB_DECODER_SIZE 4416 - -#ifdef __cplusplus - -/* A Decoder receives binary protobuf data on its input sink and pushes the - * decoded data to its output sink. */ -class upb::pb::Decoder { - public: - /* Constructs a decoder instance for the given method, which must outlive this - * decoder. Any errors during parsing will be set on the given status, which - * must also outlive this decoder. - * - * The sink must match the given method. */ - static Decoder* Create(Environment* env, const DecoderMethod* method, - Sink* output); - - /* Returns the DecoderMethod this decoder is parsing from. */ - const DecoderMethod* method() const; - - /* The sink on which this decoder receives input. */ - BytesSink* input(); - - /* Returns number of bytes successfully parsed. - * - * This can be useful for determining the stream position where an error - * occurred. - * - * This value may not be up-to-date when called from inside a parsing - * callback. */ - uint64_t BytesParsed() const; - - /* Gets/sets the parsing nexting limit. If the total number of nested - * submessages and repeated fields hits this limit, parsing will fail. This - * is a resource limit that controls the amount of memory used by the parsing - * stack. - * - * Setting the limit will fail if the parser is currently suspended at a depth - * greater than this, or if memory allocation of the stack fails. */ - size_t max_nesting() const; - bool set_max_nesting(size_t max); - - void Reset(); - - static const size_t kSize = UPB_PB_DECODER_SIZE; - - private: - UPB_DISALLOW_POD_OPS(Decoder, upb::pb::Decoder) -}; - -#endif /* __cplusplus */ - -#ifdef __cplusplus - -/* A class for caching protobuf processing code, whether bytecode for the - * interpreted decoder or machine code for the JIT. - * - * This class is not thread-safe. - * - * TODO(haberman): move this to be heap allocated for ABI stability. */ -class upb::pb::CodeCache { - public: - CodeCache(); - ~CodeCache(); - - /* Whether the cache is allowed to generate machine code. Defaults to true. - * There is no real reason to turn it off except for testing or if you are - * having a specific problem with the JIT. - * - * Note that allow_jit = true does not *guarantee* that the code will be JIT - * compiled. If this platform is not supported or the JIT was not compiled - * in, the code may still be interpreted. */ - bool allow_jit() const; - - /* This may only be called when the object is first constructed, and prior to - * any code generation, otherwise returns false and does nothing. */ - bool set_allow_jit(bool allow); - - /* Returns a DecoderMethod that can push data to the given handlers. - * If a suitable method already exists, it will be returned from the cache. - * - * Specifying the destination handlers here allows the DecoderMethod to be - * statically bound to the destination handlers if possible, which can allow - * more efficient decoding. However the returned method may or may not - * actually be statically bound. But in all cases, the returned method can - * push data to the given handlers. */ - const DecoderMethod *GetDecoderMethod(const DecoderMethodOptions& opts); - - /* If/when someone needs to explicitly create a dynamically-bound - * DecoderMethod*, we can add a method to get it here. */ - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(CodeCache) -#else -struct upb_pbcodecache { -#endif - bool allow_jit_; - - /* Array of mgroups. */ - upb_inttable groups; -}; - -UPB_BEGIN_EXTERN_C - -upb_pbdecoder *upb_pbdecoder_create(upb_env *e, - const upb_pbdecodermethod *method, - upb_sink *output); -const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d); -upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d); -uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d); -size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d); -bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max); -void upb_pbdecoder_reset(upb_pbdecoder *d); - -void upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts, - const upb_handlers *h); -void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy); - - -/* Include refcounted methods like upb_pbdecodermethod_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_pbdecodermethod, upb_pbdecodermethod_upcast) - -const upb_handlers *upb_pbdecodermethod_desthandlers( - const upb_pbdecodermethod *m); -const upb_byteshandler *upb_pbdecodermethod_inputhandler( - const upb_pbdecodermethod *m); -bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m); -const upb_pbdecodermethod *upb_pbdecodermethod_new( - const upb_pbdecodermethodopts *opts, const void *owner); - -void upb_pbcodecache_init(upb_pbcodecache *c); -void upb_pbcodecache_uninit(upb_pbcodecache *c); -bool upb_pbcodecache_allowjit(const upb_pbcodecache *c); -bool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow); -const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod( - upb_pbcodecache *c, const upb_pbdecodermethodopts *opts); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { - -namespace pb { - -/* static */ -inline Decoder* Decoder::Create(Environment* env, const DecoderMethod* m, - Sink* sink) { - return upb_pbdecoder_create(env, m, sink); -} -inline const DecoderMethod* Decoder::method() const { - return upb_pbdecoder_method(this); -} -inline BytesSink* Decoder::input() { - return upb_pbdecoder_input(this); -} -inline uint64_t Decoder::BytesParsed() const { - return upb_pbdecoder_bytesparsed(this); -} -inline size_t Decoder::max_nesting() const { - return upb_pbdecoder_maxnesting(this); -} -inline bool Decoder::set_max_nesting(size_t max) { - return upb_pbdecoder_setmaxnesting(this, max); -} -inline void Decoder::Reset() { upb_pbdecoder_reset(this); } - -inline DecoderMethodOptions::DecoderMethodOptions(const Handlers* h) { - upb_pbdecodermethodopts_init(this, h); -} -inline void DecoderMethodOptions::set_lazy(bool lazy) { - upb_pbdecodermethodopts_setlazy(this, lazy); -} - -inline const Handlers* DecoderMethod::dest_handlers() const { - return upb_pbdecodermethod_desthandlers(this); -} -inline const BytesHandler* DecoderMethod::input_handler() const { - return upb_pbdecodermethod_inputhandler(this); -} -inline bool DecoderMethod::is_native() const { - return upb_pbdecodermethod_isnative(this); -} -/* static */ -inline reffed_ptr DecoderMethod::New( - const DecoderMethodOptions &opts) { - const upb_pbdecodermethod *m = upb_pbdecodermethod_new(&opts, &m); - return reffed_ptr(m, &m); -} - -inline CodeCache::CodeCache() { - upb_pbcodecache_init(this); -} -inline CodeCache::~CodeCache() { - upb_pbcodecache_uninit(this); -} -inline bool CodeCache::allow_jit() const { - return upb_pbcodecache_allowjit(this); -} -inline bool CodeCache::set_allow_jit(bool allow) { - return upb_pbcodecache_setallowjit(this, allow); -} -inline const DecoderMethod *CodeCache::GetDecoderMethod( - const DecoderMethodOptions& opts) { - return upb_pbcodecache_getdecodermethod(this, &opts); -} - -} /* namespace pb */ -} /* namespace upb */ - -#endif /* __cplusplus */ - -#endif /* UPB_DECODER_H_ */ - -/* C++ names are not actually used since this type isn't exposed to users. */ -#ifdef __cplusplus -namespace upb { -namespace pb { -class MessageGroup; -} /* namespace pb */ -} /* namespace upb */ -#endif -UPB_DECLARE_DERIVED_TYPE(upb::pb::MessageGroup, upb::RefCounted, - mgroup, upb_refcounted) - -/* Opcode definitions. The canonical meaning of each opcode is its - * implementation in the interpreter (the JIT is written to match this). - * - * All instructions have the opcode in the low byte. - * Instruction format for most instructions is: - * - * +-------------------+--------+ - * | arg (24) | op (8) | - * +-------------------+--------+ - * - * Exceptions are indicated below. A few opcodes are multi-word. */ -typedef enum { - /* Opcodes 1-8, 13, 15-18 parse their respective descriptor types. - * Arg for all of these is the upb selector for this field. */ -#define T(type) OP_PARSE_ ## type = UPB_DESCRIPTOR_TYPE_ ## type - T(DOUBLE), T(FLOAT), T(INT64), T(UINT64), T(INT32), T(FIXED64), T(FIXED32), - T(BOOL), T(UINT32), T(SFIXED32), T(SFIXED64), T(SINT32), T(SINT64), -#undef T - OP_STARTMSG = 9, /* No arg. */ - OP_ENDMSG = 10, /* No arg. */ - OP_STARTSEQ = 11, - OP_ENDSEQ = 12, - OP_STARTSUBMSG = 14, - OP_ENDSUBMSG = 19, - OP_STARTSTR = 20, - OP_STRING = 21, - OP_ENDSTR = 22, - - OP_PUSHTAGDELIM = 23, /* No arg. */ - OP_PUSHLENDELIM = 24, /* No arg. */ - OP_POP = 25, /* No arg. */ - OP_SETDELIM = 26, /* No arg. */ - OP_SETBIGGROUPNUM = 27, /* two words: - * | unused (24) | opc (8) | - * | groupnum (32) | */ - OP_CHECKDELIM = 28, - OP_CALL = 29, - OP_RET = 30, - OP_BRANCH = 31, - - /* Different opcodes depending on how many bytes expected. */ - OP_TAG1 = 32, /* | match tag (16) | jump target (8) | opc (8) | */ - OP_TAG2 = 33, /* | match tag (16) | jump target (8) | opc (8) | */ - OP_TAGN = 34, /* three words: */ - /* | unused (16) | jump target(8) | opc (8) | */ - /* | match tag 1 (32) | */ - /* | match tag 2 (32) | */ - - OP_SETDISPATCH = 35, /* N words: */ - /* | unused (24) | opc | */ - /* | upb_inttable* (32 or 64) | */ - - OP_DISPATCH = 36, /* No arg. */ - - OP_HALT = 37 /* No arg. */ -} opcode; - -#define OP_MAX OP_HALT - -UPB_INLINE opcode getop(uint32_t instr) { return instr & 0xff; } - -/* Method group; represents a set of decoder methods that had their code - * emitted together, and must therefore be freed together. Immutable once - * created. It is possible we may want to expose this to users at some point. - * - * Overall ownership of Decoder objects looks like this: - * - * +----------+ - * | | <---> DecoderMethod - * | method | - * CodeCache ---> | group | <---> DecoderMethod - * | | - * | (mgroup) | <---> DecoderMethod - * +----------+ - */ -struct mgroup { - upb_refcounted base; - - /* Maps upb_msgdef/upb_handlers -> upb_pbdecodermethod. We own refs on the - * methods. */ - upb_inttable methods; - - /* When we add the ability to link to previously existing mgroups, we'll - * need an array of mgroups we reference here, and own refs on them. */ - - /* The bytecode for our methods, if any exists. Owned by us. */ - uint32_t *bytecode; - uint32_t *bytecode_end; - -#ifdef UPB_USE_JIT_X64 - /* JIT-generated machine code, if any. */ - upb_string_handlerfunc *jit_code; - /* The size of the jit_code (required to munmap()). */ - size_t jit_size; - char *debug_info; - void *dl; -#endif -}; - -/* The maximum that any submessages can be nested. Matches proto2's limit. - * This specifies the size of the decoder's statically-sized array and therefore - * setting it high will cause the upb::pb::Decoder object to be larger. - * - * If necessary we can add a runtime-settable property to Decoder that allow - * this to be larger than the compile-time setting, but this would add - * complexity, particularly since we would have to decide how/if to give users - * the ability to set a custom memory allocation function. */ -#define UPB_DECODER_MAX_NESTING 64 - -/* Internal-only struct used by the decoder. */ -typedef struct { - /* Space optimization note: we store two pointers here that the JIT - * doesn't need at all; the upb_handlers* inside the sink and - * the dispatch table pointer. We can optimze so that the JIT uses - * smaller stack frames than the interpreter. The only thing we need - * to guarantee is that the fallback routines can find end_ofs. */ - upb_sink sink; - - /* The absolute stream offset of the end-of-frame delimiter. - * Non-delimited frames (groups and non-packed repeated fields) reuse the - * delimiter of their parent, even though the frame may not end there. - * - * NOTE: the JIT stores a slightly different value here for non-top frames. - * It stores the value relative to the end of the enclosed message. But the - * top frame is still stored the same way, which is important for ensuring - * that calls from the JIT into C work correctly. */ - uint64_t end_ofs; - const uint32_t *base; - - /* 0 indicates a length-delimited field. - * A positive number indicates a known group. - * A negative number indicates an unknown group. */ - int32_t groupnum; - upb_inttable *dispatch; /* Not used by the JIT. */ -} upb_pbdecoder_frame; - -struct upb_pbdecodermethod { - upb_refcounted base; - - /* While compiling, the base is relative in "ofs", after compiling it is - * absolute in "ptr". */ - union { - uint32_t ofs; /* PC offset of method. */ - void *ptr; /* Pointer to bytecode or machine code for this method. */ - } code_base; - - /* The decoder method group to which this method belongs. We own a ref. - * Owning a ref on the entire group is more coarse-grained than is strictly - * necessary; all we truly require is that methods we directly reference - * outlive us, while the group could contain many other messages we don't - * require. But the group represents the messages that were - * allocated+compiled together, so it makes the most sense to free them - * together also. */ - const upb_refcounted *group; - - /* Whether this method is native code or bytecode. */ - bool is_native_; - - /* The handler one calls to invoke this method. */ - upb_byteshandler input_handler_; - - /* The destination handlers this method is bound to. We own a ref. */ - const upb_handlers *dest_handlers_; - - /* Dispatch table -- used by both bytecode decoder and JIT when encountering a - * field number that wasn't the one we were expecting to see. See - * decoder.int.h for the layout of this table. */ - upb_inttable dispatch; -}; - -struct upb_pbdecoder { - upb_env *env; - - /* Our input sink. */ - upb_bytessink input_; - - /* The decoder method we are parsing with (owned). */ - const upb_pbdecodermethod *method_; - - size_t call_len; - const uint32_t *pc, *last; - - /* Current input buffer and its stream offset. */ - const char *buf, *ptr, *end, *checkpoint; - - /* End of the delimited region, relative to ptr, NULL if not in this buf. */ - const char *delim_end; - - /* End of the delimited region, relative to ptr, end if not in this buf. */ - const char *data_end; - - /* Overall stream offset of "buf." */ - uint64_t bufstart_ofs; - - /* Buffer for residual bytes not parsed from the previous buffer. */ - char residual[UPB_DECODER_MAX_RESIDUAL_BYTES]; - char *residual_end; - - /* Bytes of data that should be discarded from the input beore we start - * parsing again. We set this when we internally determine that we can - * safely skip the next N bytes, but this region extends past the current - * user buffer. */ - size_t skip; - - /* Stores the user buffer passed to our decode function. */ - const char *buf_param; - size_t size_param; - const upb_bufhandle *handle; - - /* Our internal stack. */ - upb_pbdecoder_frame *stack, *top, *limit; - const uint32_t **callstack; - size_t stack_size; - - upb_status *status; - -#ifdef UPB_USE_JIT_X64 - /* Used momentarily by the generated code to store a value while a user - * function is called. */ - uint32_t tmp_len; - - const void *saved_rsp; -#endif -}; - -/* Decoder entry points; used as handlers. */ -void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint); -void *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint); -size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, - size_t size, const upb_bufhandle *handle); -bool upb_pbdecoder_end(void *closure, const void *handler_data); - -/* Decoder-internal functions that the JIT calls to handle fallback paths. */ -int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf, - size_t size, const upb_bufhandle *handle); -size_t upb_pbdecoder_suspend(upb_pbdecoder *d); -int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum, - uint8_t wire_type); -int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d, uint64_t expected); -int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, uint64_t *u64); -int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32); -int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64); -void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg); - -/* Error messages that are shared between the bytecode and JIT decoders. */ -extern const char *kPbDecoderStackOverflow; -extern const char *kPbDecoderSubmessageTooLong; - -/* Access to decoderplan members needed by the decoder. */ -const char *upb_pbdecoder_getopname(unsigned int op); - -/* JIT codegen entry point. */ -void upb_pbdecoder_jit(mgroup *group); -void upb_pbdecoder_freejit(mgroup *group); -UPB_REFCOUNTED_CMETHODS(mgroup, mgroup_upcast) - -/* A special label that means "do field dispatch for this message and branch to - * wherever that takes you." */ -#define LABEL_DISPATCH 0 - -/* A special slot in the dispatch table that stores the epilogue (ENDMSG and/or - * RET) for branching to when we find an appropriate ENDGROUP tag. */ -#define DISPATCH_ENDMSG 0 - -/* It's important to use this invalid wire type instead of 0 (which is a valid - * wire type). */ -#define NO_WIRE_TYPE 0xff - -/* The dispatch table layout is: - * [field number] -> [ 48-bit offset ][ 8-bit wt2 ][ 8-bit wt1 ] - * - * If wt1 matches, jump to the 48-bit offset. If wt2 matches, lookup - * (UPB_MAX_FIELDNUMBER + fieldnum) and jump there. - * - * We need two wire types because of packed/non-packed compatibility. A - * primitive repeated field can use either wire type and be valid. While we - * could key the table on fieldnum+wiretype, the table would be 8x sparser. - * - * Storing two wire types in the primary value allows us to quickly rule out - * the second wire type without needing to do a separate lookup (this case is - * less common than an unknown field). */ -UPB_INLINE uint64_t upb_pbdecoder_packdispatch(uint64_t ofs, uint8_t wt1, - uint8_t wt2) { - return (ofs << 16) | (wt2 << 8) | wt1; -} - -UPB_INLINE void upb_pbdecoder_unpackdispatch(uint64_t dispatch, uint64_t *ofs, - uint8_t *wt1, uint8_t *wt2) { - *wt1 = (uint8_t)dispatch; - *wt2 = (uint8_t)(dispatch >> 8); - *ofs = dispatch >> 16; -} - -/* All of the functions in decoder.c that return int32_t return values according - * to the following scheme: - * 1. negative values indicate a return code from the following list. - * 2. positive values indicate that error or end of buffer was hit, and - * that the decode function should immediately return the given value - * (the decoder state has already been suspended and is ready to be - * resumed). */ -#define DECODE_OK -1 -#define DECODE_MISMATCH -2 /* Used only from checktag_slow(). */ -#define DECODE_ENDGROUP -3 /* Used only from checkunknown(). */ - -#define CHECK_RETURN(x) { int32_t ret = x; if (ret >= 0) return ret; } - -#endif /* UPB_DECODER_INT_H_ */ -/* -** A number of routines for varint manipulation (we keep them all around to -** have multiple approaches available for benchmarking). -*/ - -#ifndef UPB_VARINT_DECODER_H_ -#define UPB_VARINT_DECODER_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* A list of types as they are encoded on-the-wire. */ -typedef enum { - UPB_WIRE_TYPE_VARINT = 0, - UPB_WIRE_TYPE_64BIT = 1, - UPB_WIRE_TYPE_DELIMITED = 2, - UPB_WIRE_TYPE_START_GROUP = 3, - UPB_WIRE_TYPE_END_GROUP = 4, - UPB_WIRE_TYPE_32BIT = 5 -} upb_wiretype_t; - -#define UPB_MAX_WIRE_TYPE 5 - -/* The maximum number of bytes that it takes to encode a 64-bit varint. - * Note that with a better encoding this could be 9 (TODO: write up a - * wiki document about this). */ -#define UPB_PB_VARINT_MAX_LEN 10 - -/* Array of the "native" (ie. non-packed-repeated) wire type for the given a - * descriptor type (upb_descriptortype_t). */ -extern const uint8_t upb_pb_native_wire_types[]; - -/* Zig-zag encoding/decoding **************************************************/ - -UPB_INLINE int32_t upb_zzdec_32(uint32_t n) { - return (n >> 1) ^ -(int32_t)(n & 1); -} -UPB_INLINE int64_t upb_zzdec_64(uint64_t n) { - return (n >> 1) ^ -(int64_t)(n & 1); -} -UPB_INLINE uint32_t upb_zzenc_32(int32_t n) { return (n << 1) ^ (n >> 31); } -UPB_INLINE uint64_t upb_zzenc_64(int64_t n) { return (n << 1) ^ (n >> 63); } - -/* Decoding *******************************************************************/ - -/* All decoding functions return this struct by value. */ -typedef struct { - const char *p; /* NULL if the varint was unterminated. */ - uint64_t val; -} upb_decoderet; - -UPB_INLINE upb_decoderet upb_decoderet_make(const char *p, uint64_t val) { - upb_decoderet ret; - ret.p = p; - ret.val = val; - return ret; -} - -upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r); -upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r); - -/* Template for a function that checks the first two bytes with branching - * and dispatches 2-10 bytes with a separate function. Note that this may read - * up to 10 bytes, so it must not be used unless there are at least ten bytes - * left in the buffer! */ -#define UPB_VARINT_DECODER_CHECK2(name, decode_max8_function) \ -UPB_INLINE upb_decoderet upb_vdecode_check2_ ## name(const char *_p) { \ - uint8_t *p = (uint8_t*)_p; \ - upb_decoderet r; \ - if ((*p & 0x80) == 0) { \ - /* Common case: one-byte varint. */ \ - return upb_decoderet_make(_p + 1, *p & 0x7fU); \ - } \ - r = upb_decoderet_make(_p + 2, (*p & 0x7fU) | ((*(p + 1) & 0x7fU) << 7)); \ - if ((*(p + 1) & 0x80) == 0) { \ - /* Two-byte varint. */ \ - return r; \ - } \ - /* Longer varint, fallback to out-of-line function. */ \ - return decode_max8_function(r); \ -} - -UPB_VARINT_DECODER_CHECK2(branch32, upb_vdecode_max8_branch32) -UPB_VARINT_DECODER_CHECK2(branch64, upb_vdecode_max8_branch64) -#undef UPB_VARINT_DECODER_CHECK2 - -/* Our canonical functions for decoding varints, based on the currently - * favored best-performing implementations. */ -UPB_INLINE upb_decoderet upb_vdecode_fast(const char *p) { - if (sizeof(long) == 8) - return upb_vdecode_check2_branch64(p); - else - return upb_vdecode_check2_branch32(p); -} - - -/* Encoding *******************************************************************/ - -UPB_INLINE int upb_value_size(uint64_t val) { -#ifdef __GNUC__ - int high_bit = 63 - __builtin_clzll(val); /* 0-based, undef if val == 0. */ -#else - int high_bit = 0; - uint64_t tmp = val; - while(tmp >>= 1) high_bit++; -#endif - return val == 0 ? 1 : high_bit / 8 + 1; -} - -/* Encodes a 64-bit varint into buf (which must be >=UPB_PB_VARINT_MAX_LEN - * bytes long), returning how many bytes were used. - * - * TODO: benchmark and optimize if necessary. */ -UPB_INLINE size_t upb_vencode64(uint64_t val, char *buf) { - size_t i; - if (val == 0) { buf[0] = 0; return 1; } - i = 0; - while (val) { - uint8_t byte = val & 0x7fU; - val >>= 7; - if (val) byte |= 0x80U; - buf[i++] = byte; - } - return i; -} - -UPB_INLINE size_t upb_varint_size(uint64_t val) { - char buf[UPB_PB_VARINT_MAX_LEN]; - return upb_vencode64(val, buf); -} - -/* Encodes a 32-bit varint, *not* sign-extended. */ -UPB_INLINE uint64_t upb_vencode32(uint32_t val) { - char buf[UPB_PB_VARINT_MAX_LEN]; - size_t bytes = upb_vencode64(val, buf); - uint64_t ret = 0; - UPB_ASSERT(bytes <= 5); - memcpy(&ret, buf, bytes); - UPB_ASSERT(ret <= 0xffffffffffU); - return ret; -} - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_VARINT_DECODER_H_ */ -/* -** upb::pb::Encoder (upb_pb_encoder) -** -** Implements a set of upb_handlers that write protobuf data to the binary wire -** format. -** -** This encoder implementation does not have any access to any out-of-band or -** precomputed lengths for submessages, so it must buffer submessages internally -** before it can emit the first byte. -*/ - -#ifndef UPB_ENCODER_H_ -#define UPB_ENCODER_H_ - - -#ifdef __cplusplus -namespace upb { -namespace pb { -class Encoder; -} /* namespace pb */ -} /* namespace upb */ -#endif - -UPB_DECLARE_TYPE(upb::pb::Encoder, upb_pb_encoder) - -#define UPB_PBENCODER_MAX_NESTING 100 - -/* upb::pb::Encoder ***********************************************************/ - -/* Preallocation hint: decoder won't allocate more bytes than this when first - * constructed. This hint may be an overestimate for some build configurations. - * But if the decoder library is upgraded without recompiling the application, - * it may be an underestimate. */ -#define UPB_PB_ENCODER_SIZE 768 - -#ifdef __cplusplus - -class upb::pb::Encoder { - public: - /* Creates a new encoder in the given environment. The Handlers must have - * come from NewHandlers() below. */ - static Encoder* Create(Environment* env, const Handlers* handlers, - BytesSink* output); - - /* The input to the encoder. */ - Sink* input(); - - /* Creates a new set of handlers for this MessageDef. */ - static reffed_ptr NewHandlers(const MessageDef* msg); - - static const size_t kSize = UPB_PB_ENCODER_SIZE; - - private: - UPB_DISALLOW_POD_OPS(Encoder, upb::pb::Encoder) -}; - -#endif - -UPB_BEGIN_EXTERN_C - -const upb_handlers *upb_pb_encoder_newhandlers(const upb_msgdef *m, - const void *owner); -upb_sink *upb_pb_encoder_input(upb_pb_encoder *p); -upb_pb_encoder* upb_pb_encoder_create(upb_env* e, const upb_handlers* h, - upb_bytessink* output); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { -namespace pb { -inline Encoder* Encoder::Create(Environment* env, const Handlers* handlers, - BytesSink* output) { - return upb_pb_encoder_create(env, handlers, output); -} -inline Sink* Encoder::input() { - return upb_pb_encoder_input(this); -} -inline reffed_ptr Encoder::NewHandlers( - const upb::MessageDef *md) { - const Handlers* h = upb_pb_encoder_newhandlers(md, &h); - return reffed_ptr(h, &h); -} -} /* namespace pb */ -} /* namespace upb */ - -#endif - -#endif /* UPB_ENCODER_H_ */ -/* -** upb's core components like upb_decoder and upb_msg are carefully designed to -** avoid depending on each other for maximum orthogonality. In other words, -** you can use a upb_decoder to decode into *any* kind of structure; upb_msg is -** just one such structure. A upb_msg can be serialized/deserialized into any -** format, protobuf binary format is just one such format. -** -** However, for convenience we provide functions here for doing common -** operations like deserializing protobuf binary format into a upb_msg. The -** compromise is that this file drags in almost all of upb as a dependency, -** which could be undesirable if you're trying to use a trimmed-down build of -** upb. -** -** While these routines are convenient, they do not reuse any encoding/decoding -** state. For example, if a decoder is JIT-based, it will be re-JITted every -** time these functions are called. For this reason, if you are parsing lots -** of data and efficiency is an issue, these may not be the best functions to -** use (though they are useful for prototyping, before optimizing). -*/ - -#ifndef UPB_GLUE_H -#define UPB_GLUE_H - -#include - -#ifdef __cplusplus -#include - -extern "C" { -#endif - -/* Loads a binary descriptor and returns a NULL-terminated array of unfrozen - * filedefs. The caller owns the returned array, which must be freed with - * upb_gfree(). */ -upb_filedef **upb_loaddescriptor(const char *buf, size_t n, const void *owner, - upb_status *status); - -#ifdef __cplusplus -} /* extern "C" */ - -namespace upb { - -inline bool LoadDescriptor(const char* buf, size_t n, Status* status, - std::vector >* files) { - FileDef** parsed_files = upb_loaddescriptor(buf, n, &parsed_files, status); - - if (parsed_files) { - FileDef** p = parsed_files; - while (*p) { - files->push_back(reffed_ptr(*p, &parsed_files)); - ++p; - } - free(parsed_files); - return true; - } else { - return false; - } -} - -/* Templated so it can accept both string and std::string. */ -template -bool LoadDescriptor(const T& desc, Status* status, - std::vector >* files) { - return LoadDescriptor(desc.c_str(), desc.size(), status, files); -} - -} /* namespace upb */ - -#endif - -#endif /* UPB_GLUE_H */ -/* -** upb::pb::TextPrinter (upb_textprinter) -** -** Handlers for writing to protobuf text format. -*/ - -#ifndef UPB_TEXT_H_ -#define UPB_TEXT_H_ - - -#ifdef __cplusplus -namespace upb { -namespace pb { -class TextPrinter; -} /* namespace pb */ -} /* namespace upb */ -#endif - -UPB_DECLARE_TYPE(upb::pb::TextPrinter, upb_textprinter) - -#ifdef __cplusplus - -class upb::pb::TextPrinter { - public: - /* The given handlers must have come from NewHandlers(). It must outlive the - * TextPrinter. */ - static TextPrinter *Create(Environment *env, const upb::Handlers *handlers, - BytesSink *output); - - void SetSingleLineMode(bool single_line); - - Sink* input(); - - /* If handler caching becomes a requirement we can add a code cache as in - * decoder.h */ - static reffed_ptr NewHandlers(const MessageDef* md); -}; - -#endif - -UPB_BEGIN_EXTERN_C - -/* C API. */ -upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h, - upb_bytessink *output); -void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line); -upb_sink *upb_textprinter_input(upb_textprinter *p); - -const upb_handlers *upb_textprinter_newhandlers(const upb_msgdef *m, - const void *owner); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { -namespace pb { -inline TextPrinter *TextPrinter::Create(Environment *env, - const upb::Handlers *handlers, - BytesSink *output) { - return upb_textprinter_create(env, handlers, output); -} -inline void TextPrinter::SetSingleLineMode(bool single_line) { - upb_textprinter_setsingleline(this, single_line); -} -inline Sink* TextPrinter::input() { - return upb_textprinter_input(this); -} -inline reffed_ptr TextPrinter::NewHandlers( - const MessageDef *md) { - const Handlers* h = upb_textprinter_newhandlers(md, &h); - return reffed_ptr(h, &h); -} -} /* namespace pb */ -} /* namespace upb */ - -#endif - -#endif /* UPB_TEXT_H_ */ -/* -** upb::json::Parser (upb_json_parser) -** -** Parses JSON according to a specific schema. -** Support for parsing arbitrary JSON (schema-less) will be added later. -*/ - -#ifndef UPB_JSON_PARSER_H_ -#define UPB_JSON_PARSER_H_ - - -#ifdef __cplusplus -namespace upb { -namespace json { -class Parser; -class ParserMethod; -} /* namespace json */ -} /* namespace upb */ -#endif - -UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser) -UPB_DECLARE_DERIVED_TYPE(upb::json::ParserMethod, upb::RefCounted, - upb_json_parsermethod, upb_refcounted) - -/* upb::json::Parser **********************************************************/ - -/* Preallocation hint: parser won't allocate more bytes than this when first - * constructed. This hint may be an overestimate for some build configurations. - * But if the parser library is upgraded without recompiling the application, - * it may be an underestimate. */ -#define UPB_JSON_PARSER_SIZE 4112 - -#ifdef __cplusplus - -/* Parses an incoming BytesStream, pushing the results to the destination - * sink. */ -class upb::json::Parser { - public: - static Parser* Create(Environment* env, const ParserMethod* method, - Sink* output); - - BytesSink* input(); - - private: - UPB_DISALLOW_POD_OPS(Parser, upb::json::Parser) -}; - -class upb::json::ParserMethod { - public: - /* Include base methods from upb::ReferenceCounted. */ - UPB_REFCOUNTED_CPPMETHODS - - /* Returns handlers for parsing according to the specified schema. */ - static reffed_ptr New(const upb::MessageDef* md); - - /* The destination handlers that are statically bound to this method. - * This method is only capable of outputting to a sink that uses these - * handlers. */ - const Handlers* dest_handlers() const; - - /* The input handlers for this decoder method. */ - const BytesHandler* input_handler() const; - - private: - UPB_DISALLOW_POD_OPS(ParserMethod, upb::json::ParserMethod) -}; - -#endif - -UPB_BEGIN_EXTERN_C - -upb_json_parser* upb_json_parser_create(upb_env* e, - const upb_json_parsermethod* m, - upb_sink* output); -upb_bytessink *upb_json_parser_input(upb_json_parser *p); - -upb_json_parsermethod* upb_json_parsermethod_new(const upb_msgdef* md, - const void* owner); -const upb_handlers *upb_json_parsermethod_desthandlers( - const upb_json_parsermethod *m); -const upb_byteshandler *upb_json_parsermethod_inputhandler( - const upb_json_parsermethod *m); - -/* Include refcounted methods like upb_json_parsermethod_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_json_parsermethod, upb_json_parsermethod_upcast) - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { -namespace json { -inline Parser* Parser::Create(Environment* env, const ParserMethod* method, - Sink* output) { - return upb_json_parser_create(env, method, output); -} -inline BytesSink* Parser::input() { - return upb_json_parser_input(this); -} - -inline const Handlers* ParserMethod::dest_handlers() const { - return upb_json_parsermethod_desthandlers(this); -} -inline const BytesHandler* ParserMethod::input_handler() const { - return upb_json_parsermethod_inputhandler(this); -} -/* static */ -inline reffed_ptr ParserMethod::New( - const MessageDef* md) { - const upb_json_parsermethod *m = upb_json_parsermethod_new(md, &m); - return reffed_ptr(m, &m); -} - -} /* namespace json */ -} /* namespace upb */ - -#endif - - -#endif /* UPB_JSON_PARSER_H_ */ -/* -** upb::json::Printer -** -** Handlers that emit JSON according to a specific protobuf schema. -*/ - -#ifndef UPB_JSON_TYPED_PRINTER_H_ -#define UPB_JSON_TYPED_PRINTER_H_ - - -#ifdef __cplusplus -namespace upb { -namespace json { -class Printer; -} /* namespace json */ -} /* namespace upb */ -#endif - -UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer) - - -/* upb::json::Printer *********************************************************/ - -#define UPB_JSON_PRINTER_SIZE 176 - -#ifdef __cplusplus - -/* Prints an incoming stream of data to a BytesSink in JSON format. */ -class upb::json::Printer { - public: - static Printer* Create(Environment* env, const upb::Handlers* handlers, - BytesSink* output); - - /* The input to the printer. */ - Sink* input(); - - /* Returns handlers for printing according to the specified schema. - * If preserve_proto_fieldnames is true, the output JSON will use the - * original .proto field names (ie. {"my_field":3}) instead of using - * camelCased names, which is the default: (eg. {"myField":3}). */ - static reffed_ptr NewHandlers(const upb::MessageDef* md, - bool preserve_proto_fieldnames); - - static const size_t kSize = UPB_JSON_PRINTER_SIZE; - - private: - UPB_DISALLOW_POD_OPS(Printer, upb::json::Printer) -}; - -#endif - -UPB_BEGIN_EXTERN_C - -/* Native C API. */ -upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h, - upb_bytessink *output); -upb_sink *upb_json_printer_input(upb_json_printer *p); -const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md, - bool preserve_fieldnames, - const void *owner); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { -namespace json { -inline Printer* Printer::Create(Environment* env, const upb::Handlers* handlers, - BytesSink* output) { - return upb_json_printer_create(env, handlers, output); -} -inline Sink* Printer::input() { return upb_json_printer_input(this); } -inline reffed_ptr Printer::NewHandlers( - const upb::MessageDef *md, bool preserve_proto_fieldnames) { - const Handlers* h = upb_json_printer_newhandlers( - md, preserve_proto_fieldnames, &h); - return reffed_ptr(h, &h); -} -} /* namespace json */ -} /* namespace upb */ - -#endif - -#endif /* UPB_JSON_TYPED_PRINTER_H_ */ diff --git a/php/ext/google/protobuf/utf8.c b/php/ext/google/protobuf/utf8.c deleted file mode 100644 index 2752a08b05937..0000000000000 --- a/php/ext/google/protobuf/utf8.c +++ /dev/null @@ -1,68 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include -#include - -#include "utf8.h" - -static const uint8_t utf8_offset[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, -}; - -bool is_structurally_valid_utf8(const char* buf, int len) { - int i, j; - uint8_t offset; - - i = 0; - while (i < len) { - offset = utf8_offset[(uint8_t)buf[i]]; - if (offset == 0 || i + offset > len) { - return false; - } - for (j = i + 1; j < i + offset; j++) { - if ((buf[j] & 0xc0) != 0x80) { - return false; - } - } - i += offset; - } - return i == len; -} diff --git a/php/ext/google/protobuf/utf8.h b/php/ext/google/protobuf/utf8.h deleted file mode 100644 index 28b8d874a8b53..0000000000000 --- a/php/ext/google/protobuf/utf8.h +++ /dev/null @@ -1,36 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_UTF8_H_ -#define GOOGLE_PROTOBUF_UTF8_H_ - -bool is_structurally_valid_utf8(const char* buf, int len); - -#endif // GOOGLE_PROTOBUF_UTF8_H_ diff --git a/php/ext/google/protobuf/wkt.inc b/php/ext/google/protobuf/wkt.inc new file mode 100644 index 0000000000000..401f2e825b0ce --- /dev/null +++ b/php/ext/google/protobuf/wkt.inc @@ -0,0 +1,3240 @@ +// This file is generated from the .proto files for the well-known +// types. Do not edit! +static void google_protobuf_any_proto_AddDescriptor(); +static void google_protobuf_api_proto_AddDescriptor(); +static void google_protobuf_duration_proto_AddDescriptor(); +static void google_protobuf_empty_proto_AddDescriptor(); +static void google_protobuf_field_mask_proto_AddDescriptor(); +static void google_protobuf_source_context_proto_AddDescriptor(); +static void google_protobuf_struct_proto_AddDescriptor(); +static void google_protobuf_type_proto_AddDescriptor(); +static void google_protobuf_timestamp_proto_AddDescriptor(); +static void google_protobuf_wrappers_proto_AddDescriptor(); +/* google/protobuf/any.proto */ + +zend_class_entry* GPBMetadata_Google_Protobuf_Any_ce; + +const char google_protobuf_any_proto_descriptor [212] = { +'\n', '\031', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'a', 'n', 'y', '.', 'p', 'r', 'o', +'t', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\"', '&', '\n', '\003', 'A', 'n', +'y', '\022', '\020', '\n', '\010', 't', 'y', 'p', 'e', '_', 'u', 'r', 'l', '\030', '\001', ' ', '\001', '(', '\t', '\022', '\r', '\n', '\005', 'v', 'a', +'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\014', 'B', 'v', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', +'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\010', 'A', 'n', 'y', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', ',', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', +'p', 'e', 's', '/', 'k', 'n', 'o', 'w', 'n', '/', 'a', 'n', 'y', 'p', 'b', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\036', 'G', +'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', +'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static void google_protobuf_any_proto_AddDescriptor() { + if (DescriptorPool_HasFile("google/protobuf/any.proto")) return; + DescriptorPool_AddDescriptor("google/protobuf/any.proto", google_protobuf_any_proto_descriptor, + sizeof(google_protobuf_any_proto_descriptor)); +} + +static PHP_METHOD(GPBMetadata_Google_Protobuf_Any, initOnce) { + google_protobuf_any_proto_AddDescriptor(); +} + +static zend_function_entry GPBMetadata_Google_Protobuf_Any_methods[] = { + PHP_ME(GPBMetadata_Google_Protobuf_Any, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void GPBMetadata_Google_Protobuf_Any_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Any", + GPBMetadata_Google_Protobuf_Any_methods); + + GPBMetadata_Google_Protobuf_Any_ce = zend_register_internal_class(&tmp_ce); +} + +/* google_protobuf_Any */ + +zend_class_entry* google_protobuf_Any_ce; + +static PHP_METHOD(google_protobuf_Any, __construct) { + google_protobuf_any_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Any, getTypeUrl) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "type_url"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Any, setTypeUrl) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "type_url"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Any, getValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Any, setValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +ZEND_BEGIN_ARG_INFO_EX(arginfo_is, 0, 0, 1) + ZEND_ARG_INFO(0, proto) +ZEND_END_ARG_INFO() + +static zend_function_entry google_protobuf_Any_phpmethods[] = { + PHP_ME(google_protobuf_Any, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Any, getTypeUrl, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Any, setTypeUrl, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Any, getValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Any, setValue, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Any, is, arginfo_is, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Any, pack, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Any, unpack, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Any_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Any", + google_protobuf_Any_phpmethods); + + google_protobuf_Any_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Any_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Any_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Any_ce, message_ce); +} + +/* google/protobuf/api.proto */ + +zend_class_entry* GPBMetadata_Google_Protobuf_Api_ce; + +const char google_protobuf_api_proto_descriptor [751] = { +'\n', '\031', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'a', 'p', 'i', '.', 'p', 'r', 'o', +'t', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\032', '$', 'g', 'o', 'o', 'g', +'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'n', 't', 'e', 'x', +'t', '.', 'p', 'r', 'o', 't', 'o', '\032', '\032', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', +'t', 'y', 'p', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\201', '\002', '\n', '\003', 'A', 'p', 'i', '\022', '\014', '\n', '\004', 'n', 'a', 'm', +'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', '(', '\n', '\007', 'm', 'e', 't', 'h', 'o', 'd', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', +'\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 't', 'h', 'o', 'd', '\022', +'(', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', +'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', '\022', '\017', '\n', '\007', 'v', 'e', 'r', 's', 'i', +'o', 'n', '\030', '\004', ' ', '\001', '(', '\t', '\022', '6', '\n', '\016', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'n', 't', 'e', 'x', +'t', '\030', '\005', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', +'.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', '&', '\n', '\006', 'm', 'i', 'x', 'i', 'n', 's', '\030', +'\006', ' ', '\003', '(', '\013', '2', '\026', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', +'i', 'x', 'i', 'n', '\022', '\'', '\n', '\006', 's', 'y', 'n', 't', 'a', 'x', '\030', '\007', ' ', '\001', '(', '\016', '2', '\027', '.', 'g', 'o', +'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'y', 'n', 't', 'a', 'x', '\"', '\325', '\001', '\n', '\006', +'M', 'e', 't', 'h', 'o', 'd', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', '\030', '\n', '\020', 'r', +'e', 'q', 'u', 'e', 's', 't', '_', 't', 'y', 'p', 'e', '_', 'u', 'r', 'l', '\030', '\002', ' ', '\001', '(', '\t', '\022', '\031', '\n', '\021', +'r', 'e', 'q', 'u', 'e', 's', 't', '_', 's', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\030', '\003', ' ', '\001', '(', '\010', '\022', '\031', +'\n', '\021', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', 't', 'y', 'p', 'e', '_', 'u', 'r', 'l', '\030', '\004', ' ', '\001', '(', '\t', +'\022', '\032', '\n', '\022', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', 's', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\030', '\005', ' ', +'\001', '(', '\010', '\022', '(', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\006', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', +'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', '\022', '\'', '\n', '\006', 's', +'y', 'n', 't', 'a', 'x', '\030', '\007', ' ', '\001', '(', '\016', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', +'o', 'b', 'u', 'f', '.', 'S', 'y', 'n', 't', 'a', 'x', '\"', '#', '\n', '\005', 'M', 'i', 'x', 'i', 'n', '\022', '\014', '\n', '\004', 'n', +'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', '\014', '\n', '\004', 'r', 'o', 'o', 't', '\030', '\002', ' ', '\001', '(', '\t', 'B', 'v', +'\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\010', 'A', 'p', +'i', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', ',', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', +'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', 'w', 'n', '/', 'a', +'p', 'i', 'p', 'b', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', +'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', +'3', +}; + +static void google_protobuf_api_proto_AddDescriptor() { + if (DescriptorPool_HasFile("google/protobuf/api.proto")) return; + google_protobuf_source_context_proto_AddDescriptor(); + google_protobuf_type_proto_AddDescriptor(); + DescriptorPool_AddDescriptor("google/protobuf/api.proto", google_protobuf_api_proto_descriptor, + sizeof(google_protobuf_api_proto_descriptor)); +} + +static PHP_METHOD(GPBMetadata_Google_Protobuf_Api, initOnce) { + google_protobuf_api_proto_AddDescriptor(); +} + +static zend_function_entry GPBMetadata_Google_Protobuf_Api_methods[] = { + PHP_ME(GPBMetadata_Google_Protobuf_Api, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void GPBMetadata_Google_Protobuf_Api_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Api", + GPBMetadata_Google_Protobuf_Api_methods); + + GPBMetadata_Google_Protobuf_Api_ce = zend_register_internal_class(&tmp_ce); +} + +/* google_protobuf_Api */ + +zend_class_entry* google_protobuf_Api_ce; + +static PHP_METHOD(google_protobuf_Api, __construct) { + google_protobuf_api_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Api, getName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Api, setName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Api, getMethods) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "methods"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Api, setMethods) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "methods"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Api, getOptions) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "options"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Api, setOptions) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "options"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Api, getVersion) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "version"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Api, setVersion) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "version"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Api, getSourceContext) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "source_context"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Api, setSourceContext) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "source_context"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Api, getMixins) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "mixins"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Api, setMixins) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "mixins"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Api, getSyntax) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "syntax"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Api, setSyntax) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "syntax"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_Api_phpmethods[] = { + PHP_ME(google_protobuf_Api, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Api, getName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Api, setName, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Api, getMethods, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Api, setMethods, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Api, getOptions, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Api, setOptions, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Api, getVersion, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Api, setVersion, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Api, getSourceContext, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Api, setSourceContext, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Api, getMixins, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Api, setMixins, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Api, getSyntax, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Api, setSyntax, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Api_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Api", + google_protobuf_Api_phpmethods); + + google_protobuf_Api_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Api_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Api_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Api_ce, message_ce); +} + +/* google_protobuf_Method */ + +zend_class_entry* google_protobuf_Method_ce; + +static PHP_METHOD(google_protobuf_Method, __construct) { + google_protobuf_api_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Method, getName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Method, setName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Method, getRequestTypeUrl) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "request_type_url"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Method, setRequestTypeUrl) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "request_type_url"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Method, getRequestStreaming) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "request_streaming"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Method, setRequestStreaming) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "request_streaming"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Method, getResponseTypeUrl) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "response_type_url"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Method, setResponseTypeUrl) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "response_type_url"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Method, getResponseStreaming) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "response_streaming"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Method, setResponseStreaming) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "response_streaming"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Method, getOptions) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "options"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Method, setOptions) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "options"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Method, getSyntax) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "syntax"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Method, setSyntax) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "syntax"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_Method_phpmethods[] = { + PHP_ME(google_protobuf_Method, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Method, getName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Method, setName, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Method, getRequestTypeUrl, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Method, setRequestTypeUrl, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Method, getRequestStreaming, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Method, setRequestStreaming, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Method, getResponseTypeUrl, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Method, setResponseTypeUrl, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Method, getResponseStreaming, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Method, setResponseStreaming, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Method, getOptions, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Method, setOptions, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Method, getSyntax, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Method, setSyntax, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Method_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Method", + google_protobuf_Method_phpmethods); + + google_protobuf_Method_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Method_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Method_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Method_ce, message_ce); +} + +/* google_protobuf_Mixin */ + +zend_class_entry* google_protobuf_Mixin_ce; + +static PHP_METHOD(google_protobuf_Mixin, __construct) { + google_protobuf_api_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Mixin, getName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Mixin, setName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Mixin, getRoot) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "root"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Mixin, setRoot) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "root"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_Mixin_phpmethods[] = { + PHP_ME(google_protobuf_Mixin, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Mixin, getName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Mixin, setName, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Mixin, getRoot, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Mixin, setRoot, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Mixin_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Mixin", + google_protobuf_Mixin_phpmethods); + + google_protobuf_Mixin_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Mixin_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Mixin_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Mixin_ce, message_ce); +} + +/* google/protobuf/duration.proto */ + +zend_class_entry* GPBMetadata_Google_Protobuf_Duration_ce; + +const char google_protobuf_duration_proto_descriptor [235] = { +'\n', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'u', 'r', 'a', 't', 'i', 'o', +'n', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\"', +'*', '\n', '\010', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', '\022', '\017', '\n', '\007', 's', 'e', 'c', 'o', 'n', 'd', 's', '\030', '\001', ' ', +'\001', '(', '\003', '\022', '\r', '\n', '\005', 'n', 'a', 'n', 'o', 's', '\030', '\002', ' ', '\001', '(', '\005', 'B', '\203', '\001', '\n', '\023', 'c', 'o', +'m', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\r', 'D', 'u', 'r', 'a', 't', 'i', +'o', 'n', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '1', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', +'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', 'w', 'n', '/', +'d', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\036', 'G', 'o', 'o', +'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 'y', 'p', +'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static void google_protobuf_duration_proto_AddDescriptor() { + if (DescriptorPool_HasFile("google/protobuf/duration.proto")) return; + DescriptorPool_AddDescriptor("google/protobuf/duration.proto", google_protobuf_duration_proto_descriptor, + sizeof(google_protobuf_duration_proto_descriptor)); +} + +static PHP_METHOD(GPBMetadata_Google_Protobuf_Duration, initOnce) { + google_protobuf_duration_proto_AddDescriptor(); +} + +static zend_function_entry GPBMetadata_Google_Protobuf_Duration_methods[] = { + PHP_ME(GPBMetadata_Google_Protobuf_Duration, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void GPBMetadata_Google_Protobuf_Duration_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Duration", + GPBMetadata_Google_Protobuf_Duration_methods); + + GPBMetadata_Google_Protobuf_Duration_ce = zend_register_internal_class(&tmp_ce); +} + +/* google_protobuf_Duration */ + +zend_class_entry* google_protobuf_Duration_ce; + +static PHP_METHOD(google_protobuf_Duration, __construct) { + google_protobuf_duration_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Duration, getSeconds) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "seconds"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Duration, setSeconds) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "seconds"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Duration, getNanos) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "nanos"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Duration, setNanos) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "nanos"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_Duration_phpmethods[] = { + PHP_ME(google_protobuf_Duration, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Duration, getSeconds, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Duration, setSeconds, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Duration, getNanos, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Duration, setNanos, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Duration_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Duration", + google_protobuf_Duration_phpmethods); + + google_protobuf_Duration_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Duration_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Duration_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Duration_ce, message_ce); +} + +/* google/protobuf/empty.proto */ + +zend_class_entry* GPBMetadata_Google_Protobuf_GPBEmpty_ce; + +const char google_protobuf_empty_proto_descriptor [190] = { +'\n', '\033', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'e', 'm', 'p', 't', 'y', '.', 'p', +'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\"', '\007', '\n', '\005', +'E', 'm', 'p', 't', 'y', 'B', '}', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', +'b', 'u', 'f', 'B', '\n', 'E', 'm', 'p', 't', 'y', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '.', 'g', 'o', 'o', 'g', 'l', 'e', +'.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', +'s', '/', 'k', 'n', 'o', 'w', 'n', '/', 'e', 'm', 'p', 't', 'y', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', +'\002', '\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', +'w', 'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static void google_protobuf_empty_proto_AddDescriptor() { + if (DescriptorPool_HasFile("google/protobuf/empty.proto")) return; + DescriptorPool_AddDescriptor("google/protobuf/empty.proto", google_protobuf_empty_proto_descriptor, + sizeof(google_protobuf_empty_proto_descriptor)); +} + +static PHP_METHOD(GPBMetadata_Google_Protobuf_GPBEmpty, initOnce) { + google_protobuf_empty_proto_AddDescriptor(); +} + +static zend_function_entry GPBMetadata_Google_Protobuf_GPBEmpty_methods[] = { + PHP_ME(GPBMetadata_Google_Protobuf_GPBEmpty, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void GPBMetadata_Google_Protobuf_GPBEmpty_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\GPBEmpty", + GPBMetadata_Google_Protobuf_GPBEmpty_methods); + + GPBMetadata_Google_Protobuf_GPBEmpty_ce = zend_register_internal_class(&tmp_ce); +} + +/* google_protobuf_Empty */ + +zend_class_entry* google_protobuf_Empty_ce; + +static PHP_METHOD(google_protobuf_Empty, __construct) { + google_protobuf_empty_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static zend_function_entry google_protobuf_Empty_phpmethods[] = { + PHP_ME(google_protobuf_Empty, __construct, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Empty_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\GPBEmpty", + google_protobuf_Empty_phpmethods); + + google_protobuf_Empty_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Empty_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Empty_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Empty_ce, message_ce); +} + +/* google/protobuf/field_mask.proto */ + +zend_class_entry* GPBMetadata_Google_Protobuf_FieldMask_ce; + +const char google_protobuf_field_mask_proto_descriptor [223] = { +'\n', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'f', 'i', 'e', 'l', 'd', '_', 'm', +'a', 's', 'k', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '\"', '\032', '\n', '\t', 'F', 'i', 'e', 'l', 'd', 'M', 'a', 's', 'k', '\022', '\r', '\n', '\005', 'p', 'a', 't', 'h', 's', '\030', '\001', +' ', '\003', '(', '\t', 'B', '\205', '\001', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', +'b', 'u', 'f', 'B', '\016', 'F', 'i', 'e', 'l', 'd', 'M', 'a', 's', 'k', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '2', 'g', 'o', +'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', +'t', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', 'w', 'n', '/', 'f', 'i', 'e', 'l', 'd', 'm', 'a', 's', 'k', 'p', 'b', '\370', '\001', +'\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', +'.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static void google_protobuf_field_mask_proto_AddDescriptor() { + if (DescriptorPool_HasFile("google/protobuf/field_mask.proto")) return; + DescriptorPool_AddDescriptor("google/protobuf/field_mask.proto", google_protobuf_field_mask_proto_descriptor, + sizeof(google_protobuf_field_mask_proto_descriptor)); +} + +static PHP_METHOD(GPBMetadata_Google_Protobuf_FieldMask, initOnce) { + google_protobuf_field_mask_proto_AddDescriptor(); +} + +static zend_function_entry GPBMetadata_Google_Protobuf_FieldMask_methods[] = { + PHP_ME(GPBMetadata_Google_Protobuf_FieldMask, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void GPBMetadata_Google_Protobuf_FieldMask_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\FieldMask", + GPBMetadata_Google_Protobuf_FieldMask_methods); + + GPBMetadata_Google_Protobuf_FieldMask_ce = zend_register_internal_class(&tmp_ce); +} + +/* google_protobuf_FieldMask */ + +zend_class_entry* google_protobuf_FieldMask_ce; + +static PHP_METHOD(google_protobuf_FieldMask, __construct) { + google_protobuf_field_mask_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_FieldMask, getPaths) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "paths"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_FieldMask, setPaths) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "paths"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_FieldMask_phpmethods[] = { + PHP_ME(google_protobuf_FieldMask, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_FieldMask, getPaths, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_FieldMask, setPaths, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_FieldMask_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\FieldMask", + google_protobuf_FieldMask_phpmethods); + + google_protobuf_FieldMask_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_FieldMask_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_FieldMask_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_FieldMask_ce, message_ce); +} + +/* google/protobuf/source_context.proto */ + +zend_class_entry* GPBMetadata_Google_Protobuf_SourceContext_ce; + +const char google_protobuf_source_context_proto_descriptor [240] = { +'\n', '$', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 's', 'o', 'u', 'r', 'c', 'e', '_', +'c', 'o', 'n', 't', 'e', 'x', 't', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', +'t', 'o', 'b', 'u', 'f', '\"', '\"', '\n', '\r', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', '\021', '\n', +'\t', 'f', 'i', 'l', 'e', '_', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\212', '\001', '\n', '\023', 'c', 'o', 'm', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\022', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', +'n', 't', 'e', 'x', 't', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '6', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', +'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', +'w', 'n', '/', 's', 'o', 'u', 'r', 'c', 'e', 'c', 'o', 'n', 't', 'e', 'x', 't', 'p', 'b', '\242', '\002', '\003', 'G', 'P', 'B', '\252', +'\002', '\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', +'w', 'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static void google_protobuf_source_context_proto_AddDescriptor() { + if (DescriptorPool_HasFile("google/protobuf/source_context.proto")) return; + DescriptorPool_AddDescriptor("google/protobuf/source_context.proto", google_protobuf_source_context_proto_descriptor, + sizeof(google_protobuf_source_context_proto_descriptor)); +} + +static PHP_METHOD(GPBMetadata_Google_Protobuf_SourceContext, initOnce) { + google_protobuf_source_context_proto_AddDescriptor(); +} + +static zend_function_entry GPBMetadata_Google_Protobuf_SourceContext_methods[] = { + PHP_ME(GPBMetadata_Google_Protobuf_SourceContext, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void GPBMetadata_Google_Protobuf_SourceContext_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\SourceContext", + GPBMetadata_Google_Protobuf_SourceContext_methods); + + GPBMetadata_Google_Protobuf_SourceContext_ce = zend_register_internal_class(&tmp_ce); +} + +/* google_protobuf_SourceContext */ + +zend_class_entry* google_protobuf_SourceContext_ce; + +static PHP_METHOD(google_protobuf_SourceContext, __construct) { + google_protobuf_source_context_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_SourceContext, getFileName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "file_name"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_SourceContext, setFileName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "file_name"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_SourceContext_phpmethods[] = { + PHP_ME(google_protobuf_SourceContext, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_SourceContext, getFileName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_SourceContext, setFileName, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_SourceContext_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\SourceContext", + google_protobuf_SourceContext_phpmethods); + + google_protobuf_SourceContext_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_SourceContext_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_SourceContext_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_SourceContext_ce, message_ce); +} + +/* google/protobuf/struct.proto */ + +zend_class_entry* GPBMetadata_Google_Protobuf_Struct_ce; + +const char google_protobuf_struct_proto_descriptor [638] = { +'\n', '\034', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 's', 't', 'r', 'u', 'c', 't', '.', +'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\"', '\204', '\001', +'\n', '\006', 'S', 't', 'r', 'u', 'c', 't', '\022', '3', '\n', '\006', 'f', 'i', 'e', 'l', 'd', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', +'#', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 't', 'r', 'u', 'c', 't', '.', +'F', 'i', 'e', 'l', 'd', 's', 'E', 'n', 't', 'r', 'y', '\032', 'E', '\n', '\013', 'F', 'i', 'e', 'l', 'd', 's', 'E', 'n', 't', 'r', +'y', '\022', '\013', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', '\022', '%', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', +' ', '\001', '(', '\013', '2', '\026', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'V', 'a', +'l', 'u', 'e', ':', '\002', '8', '\001', '\"', '\352', '\001', '\n', '\005', 'V', 'a', 'l', 'u', 'e', '\022', '0', '\n', '\n', 'n', 'u', 'l', 'l', +'_', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\016', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', +'t', 'o', 'b', 'u', 'f', '.', 'N', 'u', 'l', 'l', 'V', 'a', 'l', 'u', 'e', 'H', '\000', '\022', '\026', '\n', '\014', 'n', 'u', 'm', 'b', +'e', 'r', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\001', 'H', '\000', '\022', '\026', '\n', '\014', 's', 't', 'r', 'i', 'n', +'g', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'H', '\000', '\022', '\024', '\n', '\n', 'b', 'o', 'o', 'l', '_', 'v', +'a', 'l', 'u', 'e', '\030', '\004', ' ', '\001', '(', '\010', 'H', '\000', '\022', '/', '\n', '\014', 's', 't', 'r', 'u', 'c', 't', '_', 'v', 'a', +'l', 'u', 'e', '\030', '\005', ' ', '\001', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', +'u', 'f', '.', 'S', 't', 'r', 'u', 'c', 't', 'H', '\000', '\022', '0', '\n', '\n', 'l', 'i', 's', 't', '_', 'v', 'a', 'l', 'u', 'e', +'\030', '\006', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'L', 'i', 's', 't', 'V', 'a', 'l', 'u', 'e', 'H', '\000', 'B', '\006', '\n', '\004', 'k', 'i', 'n', 'd', '\"', '3', '\n', '\t', 'L', 'i', +'s', 't', 'V', 'a', 'l', 'u', 'e', '\022', '&', '\n', '\006', 'v', 'a', 'l', 'u', 'e', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '\026', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'V', 'a', 'l', 'u', 'e', '*', '\033', '\n', +'\t', 'N', 'u', 'l', 'l', 'V', 'a', 'l', 'u', 'e', '\022', '\016', '\n', '\n', 'N', 'U', 'L', 'L', '_', 'V', 'A', 'L', 'U', 'E', '\020', +'\000', 'B', '\177', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', +'\013', 'S', 't', 'r', 'u', 'c', 't', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '/', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', +'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', +'n', 'o', 'w', 'n', '/', 's', 't', 'r', 'u', 'c', 't', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\036', +'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', +'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static void google_protobuf_struct_proto_AddDescriptor() { + if (DescriptorPool_HasFile("google/protobuf/struct.proto")) return; + DescriptorPool_AddDescriptor("google/protobuf/struct.proto", google_protobuf_struct_proto_descriptor, + sizeof(google_protobuf_struct_proto_descriptor)); +} + +static PHP_METHOD(GPBMetadata_Google_Protobuf_Struct, initOnce) { + google_protobuf_struct_proto_AddDescriptor(); +} + +static zend_function_entry GPBMetadata_Google_Protobuf_Struct_methods[] = { + PHP_ME(GPBMetadata_Google_Protobuf_Struct, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void GPBMetadata_Google_Protobuf_Struct_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Struct", + GPBMetadata_Google_Protobuf_Struct_methods); + + GPBMetadata_Google_Protobuf_Struct_ce = zend_register_internal_class(&tmp_ce); +} + +/* google_protobuf_Struct */ + +zend_class_entry* google_protobuf_Struct_ce; + +static PHP_METHOD(google_protobuf_Struct, __construct) { + google_protobuf_struct_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Struct, getFields) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "fields"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Struct, setFields) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "fields"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_Struct_phpmethods[] = { + PHP_ME(google_protobuf_Struct, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Struct, getFields, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Struct, setFields, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Struct_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Struct", + google_protobuf_Struct_phpmethods); + + google_protobuf_Struct_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Struct_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Struct_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Struct_ce, message_ce); +} + +/* google_protobuf_Struct_FieldsEntry */ + +zend_class_entry* google_protobuf_Struct_FieldsEntry_ce; + +static PHP_METHOD(google_protobuf_Struct_FieldsEntry, __construct) { + google_protobuf_struct_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Struct_FieldsEntry, getKey) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "key"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Struct_FieldsEntry, setKey) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "key"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Struct_FieldsEntry, getValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Struct_FieldsEntry, setValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_Struct_FieldsEntry_phpmethods[] = { + PHP_ME(google_protobuf_Struct_FieldsEntry, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Struct_FieldsEntry, getKey, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Struct_FieldsEntry, setKey, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Struct_FieldsEntry, getValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Struct_FieldsEntry, setValue, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Struct_FieldsEntry_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Struct\\FieldsEntry", + google_protobuf_Struct_FieldsEntry_phpmethods); + + google_protobuf_Struct_FieldsEntry_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Struct_FieldsEntry_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Struct_FieldsEntry_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Struct_FieldsEntry_ce, message_ce); +} + +/* google_protobuf_Value */ + +zend_class_entry* google_protobuf_Value_ce; + +static PHP_METHOD(google_protobuf_Value, __construct) { + google_protobuf_struct_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Value, getNullValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "null_value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Value, setNullValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "null_value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Value, getNumberValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "number_value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Value, setNumberValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "number_value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Value, getStringValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "string_value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Value, setStringValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "string_value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Value, getBoolValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "bool_value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Value, setBoolValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "bool_value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Value, getStructValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "struct_value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Value, setStructValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "struct_value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Value, getListValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "list_value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Value, setListValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "list_value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Value, getKind) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_oneofdef *oneof = upb_msgdef_ntooz(intern->desc->msgdef, + "kind"); + const upb_fielddef *field = upb_msg_whichoneof(intern->msg, oneof); + RETURN_STRING(field ? upb_fielddef_name(field) : ""); +} +static zend_function_entry google_protobuf_Value_phpmethods[] = { + PHP_ME(google_protobuf_Value, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Value, getNullValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Value, setNullValue, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Value, getNumberValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Value, setNumberValue, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Value, getStringValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Value, setStringValue, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Value, getBoolValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Value, setBoolValue, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Value, getStructValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Value, setStructValue, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Value, getListValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Value, setListValue, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Value, getKind, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Value_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Value", + google_protobuf_Value_phpmethods); + + google_protobuf_Value_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Value_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Value_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Value_ce, message_ce); +} + +/* google_protobuf_ListValue */ + +zend_class_entry* google_protobuf_ListValue_ce; + +static PHP_METHOD(google_protobuf_ListValue, __construct) { + google_protobuf_struct_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_ListValue, getValues) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "values"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_ListValue, setValues) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "values"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_ListValue_phpmethods[] = { + PHP_ME(google_protobuf_ListValue, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_ListValue, getValues, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_ListValue, setValues, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_ListValue_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\ListValue", + google_protobuf_ListValue_phpmethods); + + google_protobuf_ListValue_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_ListValue_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_ListValue_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_ListValue_ce, message_ce); +} + +/* google_protobuf_NullValue */ + +zend_class_entry* google_protobuf_NullValue_ce; + +PHP_METHOD(google_protobuf_NullValue, name) { + google_protobuf_struct_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.NullValue"); + const char *name; + zend_long value; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &value) == + FAILURE) { + return; + } + name = upb_enumdef_iton(e, value); + if (!name) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\NullValue has no name " + "defined for value " ZEND_LONG_FMT ".", + value); + return; + } + RETURN_STRING(name); +} + +PHP_METHOD(google_protobuf_NullValue, value) { + google_protobuf_struct_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.NullValue"); + char *name = NULL; + size_t name_len; + int32_t num; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, + &name_len) == FAILURE) { + return; + } + if (!upb_enumdef_ntoi(e, name, name_len, &num)) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\NullValue has no value " + "defined for name %s.", + name); + return; + } + RETURN_LONG(num); +} + +static zend_function_entry google_protobuf_NullValue_phpmethods[] = { + PHP_ME(google_protobuf_NullValue, name, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(google_protobuf_NullValue, value, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void google_protobuf_NullValue_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\NullValue", + google_protobuf_NullValue_phpmethods); + + google_protobuf_NullValue_ce = zend_register_internal_class(&tmp_ce); + zend_declare_class_constant_long(google_protobuf_NullValue_ce, "NULL_VALUE", + strlen("NULL_VALUE"), 0); +} + +/* google/protobuf/type.proto */ + +zend_class_entry* GPBMetadata_Google_Protobuf_Type_ce; + +const char google_protobuf_type_proto_descriptor [1592] = { +'\n', '\032', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', '.', 'p', 'r', +'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\032', '\031', 'g', 'o', 'o', +'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'a', 'n', 'y', '.', 'p', 'r', 'o', 't', 'o', '\032', '$', 'g', +'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'n', +'t', 'e', 'x', 't', '.', 'p', 'r', 'o', 't', 'o', '\"', '\327', '\001', '\n', '\004', 'T', 'y', 'p', 'e', '\022', '\014', '\n', '\004', 'n', 'a', +'m', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', '&', '\n', '\006', 'f', 'i', 'e', 'l', 'd', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', +'\026', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', '\022', '\016', +'\n', '\006', 'o', 'n', 'e', 'o', 'f', 's', '\030', '\003', ' ', '\003', '(', '\t', '\022', '(', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', +'\030', '\004', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'O', 'p', 't', 'i', 'o', 'n', '\022', '6', '\n', '\016', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '\030', +'\005', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', +'o', 'u', 'r', 'c', 'e', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', '\'', '\n', '\006', 's', 'y', 'n', 't', 'a', 'x', '\030', '\006', ' ', +'\001', '(', '\016', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'y', 'n', +'t', 'a', 'x', '\"', '\325', '\005', '\n', '\005', 'F', 'i', 'e', 'l', 'd', '\022', ')', '\n', '\004', 'k', 'i', 'n', 'd', '\030', '\001', ' ', '\001', +'(', '\016', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', +'d', '.', 'K', 'i', 'n', 'd', '\022', '7', '\n', '\013', 'c', 'a', 'r', 'd', 'i', 'n', 'a', 'l', 'i', 't', 'y', '\030', '\002', ' ', '\001', +'(', '\016', '2', '\"', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', +'d', '.', 'C', 'a', 'r', 'd', 'i', 'n', 'a', 'l', 'i', 't', 'y', '\022', '\016', '\n', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\030', '\003', +' ', '\001', '(', '\005', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\004', ' ', '\001', '(', '\t', '\022', '\020', '\n', '\010', 't', 'y', 'p', +'e', '_', 'u', 'r', 'l', '\030', '\006', ' ', '\001', '(', '\t', '\022', '\023', '\n', '\013', 'o', 'n', 'e', 'o', 'f', '_', 'i', 'n', 'd', 'e', +'x', '\030', '\007', ' ', '\001', '(', '\005', '\022', '\016', '\n', '\006', 'p', 'a', 'c', 'k', 'e', 'd', '\030', '\010', ' ', '\001', '(', '\010', '\022', '(', +'\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\t', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', '\022', '\021', '\n', '\t', 'j', 's', 'o', 'n', '_', 'n', +'a', 'm', 'e', '\030', '\n', ' ', '\001', '(', '\t', '\022', '\025', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'v', 'a', 'l', 'u', +'e', '\030', '\013', ' ', '\001', '(', '\t', '\"', '\310', '\002', '\n', '\004', 'K', 'i', 'n', 'd', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', +'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'D', 'O', 'U', 'B', 'L', 'E', '\020', +'\001', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'F', 'L', 'O', 'A', 'T', '\020', '\002', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', +'_', 'I', 'N', 'T', '6', '4', '\020', '\003', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', '6', '4', '\020', '\004', +'\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'I', 'N', 'T', '3', '2', '\020', '\005', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', +'F', 'I', 'X', 'E', 'D', '6', '4', '\020', '\006', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'F', 'I', 'X', 'E', 'D', '3', '2', +'\020', '\007', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', 'E', '_', 'B', 'O', 'O', 'L', '\020', '\010', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', +'_', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\t', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'G', 'R', 'O', 'U', 'P', '\020', '\n', +'\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'M', 'E', 'S', 'S', 'A', 'G', 'E', '\020', '\013', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', +'E', '_', 'B', 'Y', 'T', 'E', 'S', '\020', '\014', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', '3', '2', '\020', +'\r', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', 'E', '_', 'E', 'N', 'U', 'M', '\020', '\016', '\022', '\021', '\n', '\r', 'T', 'Y', 'P', 'E', '_', +'S', 'F', 'I', 'X', 'E', 'D', '3', '2', '\020', '\017', '\022', '\021', '\n', '\r', 'T', 'Y', 'P', 'E', '_', 'S', 'F', 'I', 'X', 'E', 'D', +'6', '4', '\020', '\020', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '3', '2', '\020', '\021', '\022', '\017', '\n', '\013', +'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '6', '4', '\020', '\022', '\"', 't', '\n', '\013', 'C', 'a', 'r', 'd', 'i', 'n', 'a', 'l', +'i', 't', 'y', '\022', '\027', '\n', '\023', 'C', 'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'U', 'N', 'K', 'N', 'O', 'W', +'N', '\020', '\000', '\022', '\030', '\n', '\024', 'C', 'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'O', 'P', 'T', 'I', 'O', 'N', +'A', 'L', '\020', '\001', '\022', '\030', '\n', '\024', 'C', 'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'R', 'E', 'Q', 'U', 'I', +'R', 'E', 'D', '\020', '\002', '\022', '\030', '\n', '\024', 'C', 'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'R', 'E', 'P', 'E', +'A', 'T', 'E', 'D', '\020', '\003', '\"', '\316', '\001', '\n', '\004', 'E', 'n', 'u', 'm', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', +' ', '\001', '(', '\t', '\022', '-', '\n', '\t', 'e', 'n', 'u', 'm', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\003', '(', '\013', '2', '\032', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', +'e', '\022', '(', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', '\022', '6', '\n', '\016', 's', 'o', 'u', +'r', 'c', 'e', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', +'\'', '\n', '\006', 's', 'y', 'n', 't', 'a', 'x', '\030', '\005', ' ', '\001', '(', '\016', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'y', 'n', 't', 'a', 'x', '\"', 'S', '\n', '\t', 'E', 'n', 'u', 'm', 'V', 'a', +'l', 'u', 'e', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', '\016', '\n', '\006', 'n', 'u', 'm', 'b', +'e', 'r', '\030', '\002', ' ', '\001', '(', '\005', '\022', '(', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\003', '(', '\013', +'2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', +'\"', ';', '\n', '\006', 'O', 'p', 't', 'i', 'o', 'n', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', +'#', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', +'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', '*', '.', '\n', '\006', 'S', 'y', 'n', 't', 'a', 'x', '\022', '\021', '\n', '\r', +'S', 'Y', 'N', 'T', 'A', 'X', '_', 'P', 'R', 'O', 'T', 'O', '2', '\020', '\000', '\022', '\021', '\n', '\r', 'S', 'Y', 'N', 'T', 'A', 'X', +'_', 'P', 'R', 'O', 'T', 'O', '3', '\020', '\001', 'B', '{', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', +'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\t', 'T', 'y', 'p', 'e', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '-', 'g', 'o', 'o', +'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', +'y', 'p', 'e', 's', '/', 'k', 'n', 'o', 'w', 'n', '/', 't', 'y', 'p', 'e', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', +'B', '\252', '\002', '\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', +'n', 'o', 'w', 'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static void google_protobuf_type_proto_AddDescriptor() { + if (DescriptorPool_HasFile("google/protobuf/type.proto")) return; + google_protobuf_any_proto_AddDescriptor(); + google_protobuf_source_context_proto_AddDescriptor(); + DescriptorPool_AddDescriptor("google/protobuf/type.proto", google_protobuf_type_proto_descriptor, + sizeof(google_protobuf_type_proto_descriptor)); +} + +static PHP_METHOD(GPBMetadata_Google_Protobuf_Type, initOnce) { + google_protobuf_type_proto_AddDescriptor(); +} + +static zend_function_entry GPBMetadata_Google_Protobuf_Type_methods[] = { + PHP_ME(GPBMetadata_Google_Protobuf_Type, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void GPBMetadata_Google_Protobuf_Type_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Type", + GPBMetadata_Google_Protobuf_Type_methods); + + GPBMetadata_Google_Protobuf_Type_ce = zend_register_internal_class(&tmp_ce); +} + +/* google_protobuf_Type */ + +zend_class_entry* google_protobuf_Type_ce; + +static PHP_METHOD(google_protobuf_Type, __construct) { + google_protobuf_type_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Type, getName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Type, setName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Type, getFields) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "fields"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Type, setFields) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "fields"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Type, getOneofs) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "oneofs"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Type, setOneofs) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "oneofs"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Type, getOptions) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "options"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Type, setOptions) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "options"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Type, getSourceContext) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "source_context"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Type, setSourceContext) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "source_context"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Type, getSyntax) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "syntax"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Type, setSyntax) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "syntax"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_Type_phpmethods[] = { + PHP_ME(google_protobuf_Type, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Type, getName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Type, setName, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Type, getFields, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Type, setFields, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Type, getOneofs, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Type, setOneofs, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Type, getOptions, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Type, setOptions, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Type, getSourceContext, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Type, setSourceContext, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Type, getSyntax, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Type, setSyntax, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Type_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Type", + google_protobuf_Type_phpmethods); + + google_protobuf_Type_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Type_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Type_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Type_ce, message_ce); +} + +/* google_protobuf_Field */ + +zend_class_entry* google_protobuf_Field_ce; + +static PHP_METHOD(google_protobuf_Field, __construct) { + google_protobuf_type_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Field, getKind) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "kind"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, setKind) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "kind"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, getCardinality) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "cardinality"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, setCardinality) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "cardinality"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, getNumber) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "number"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, setNumber) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "number"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, getName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, setName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, getTypeUrl) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "type_url"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, setTypeUrl) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "type_url"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, getOneofIndex) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "oneof_index"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, setOneofIndex) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "oneof_index"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, getPacked) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "packed"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, setPacked) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "packed"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, getOptions) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "options"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, setOptions) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "options"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, getJsonName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "json_name"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, setJsonName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "json_name"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, getDefaultValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "default_value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Field, setDefaultValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "default_value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_Field_phpmethods[] = { + PHP_ME(google_protobuf_Field, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, getKind, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, setKind, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, getCardinality, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, setCardinality, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, getNumber, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, setNumber, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, getName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, setName, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, getTypeUrl, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, setTypeUrl, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, getOneofIndex, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, setOneofIndex, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, getPacked, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, setPacked, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, getOptions, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, setOptions, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, getJsonName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, setJsonName, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, getDefaultValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Field, setDefaultValue, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Field_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Field", + google_protobuf_Field_phpmethods); + + google_protobuf_Field_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Field_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Field_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Field_ce, message_ce); +} + +/* google_protobuf_Field_Kind */ + +zend_class_entry* google_protobuf_Field_Kind_ce; + +PHP_METHOD(google_protobuf_Field_Kind, name) { + google_protobuf_type_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Field.Kind"); + const char *name; + zend_long value; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &value) == + FAILURE) { + return; + } + name = upb_enumdef_iton(e, value); + if (!name) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\Field\\Kind has no name " + "defined for value " ZEND_LONG_FMT ".", + value); + return; + } + RETURN_STRING(name); +} + +PHP_METHOD(google_protobuf_Field_Kind, value) { + google_protobuf_type_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Field.Kind"); + char *name = NULL; + size_t name_len; + int32_t num; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, + &name_len) == FAILURE) { + return; + } + if (!upb_enumdef_ntoi(e, name, name_len, &num)) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\Field\\Kind has no value " + "defined for name %s.", + name); + return; + } + RETURN_LONG(num); +} + +static zend_function_entry google_protobuf_Field_Kind_phpmethods[] = { + PHP_ME(google_protobuf_Field_Kind, name, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(google_protobuf_Field_Kind, value, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void google_protobuf_Field_Kind_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Field\\Kind", + google_protobuf_Field_Kind_phpmethods); + + google_protobuf_Field_Kind_ce = zend_register_internal_class(&tmp_ce); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_UNKNOWN", + strlen("TYPE_UNKNOWN"), 0); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_DOUBLE", + strlen("TYPE_DOUBLE"), 1); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_FLOAT", + strlen("TYPE_FLOAT"), 2); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_INT64", + strlen("TYPE_INT64"), 3); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_UINT64", + strlen("TYPE_UINT64"), 4); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_INT32", + strlen("TYPE_INT32"), 5); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_FIXED64", + strlen("TYPE_FIXED64"), 6); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_FIXED32", + strlen("TYPE_FIXED32"), 7); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_BOOL", + strlen("TYPE_BOOL"), 8); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_STRING", + strlen("TYPE_STRING"), 9); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_GROUP", + strlen("TYPE_GROUP"), 10); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_MESSAGE", + strlen("TYPE_MESSAGE"), 11); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_BYTES", + strlen("TYPE_BYTES"), 12); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_UINT32", + strlen("TYPE_UINT32"), 13); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_ENUM", + strlen("TYPE_ENUM"), 14); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_SFIXED32", + strlen("TYPE_SFIXED32"), 15); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_SFIXED64", + strlen("TYPE_SFIXED64"), 16); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_SINT32", + strlen("TYPE_SINT32"), 17); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_SINT64", + strlen("TYPE_SINT64"), 18); +} + +/* google_protobuf_Field_Cardinality */ + +zend_class_entry* google_protobuf_Field_Cardinality_ce; + +PHP_METHOD(google_protobuf_Field_Cardinality, name) { + google_protobuf_type_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Field.Cardinality"); + const char *name; + zend_long value; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &value) == + FAILURE) { + return; + } + name = upb_enumdef_iton(e, value); + if (!name) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\Field\\Cardinality has no name " + "defined for value " ZEND_LONG_FMT ".", + value); + return; + } + RETURN_STRING(name); +} + +PHP_METHOD(google_protobuf_Field_Cardinality, value) { + google_protobuf_type_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Field.Cardinality"); + char *name = NULL; + size_t name_len; + int32_t num; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, + &name_len) == FAILURE) { + return; + } + if (!upb_enumdef_ntoi(e, name, name_len, &num)) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\Field\\Cardinality has no value " + "defined for name %s.", + name); + return; + } + RETURN_LONG(num); +} + +static zend_function_entry google_protobuf_Field_Cardinality_phpmethods[] = { + PHP_ME(google_protobuf_Field_Cardinality, name, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(google_protobuf_Field_Cardinality, value, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void google_protobuf_Field_Cardinality_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Field\\Cardinality", + google_protobuf_Field_Cardinality_phpmethods); + + google_protobuf_Field_Cardinality_ce = zend_register_internal_class(&tmp_ce); + zend_declare_class_constant_long(google_protobuf_Field_Cardinality_ce, "CARDINALITY_UNKNOWN", + strlen("CARDINALITY_UNKNOWN"), 0); + zend_declare_class_constant_long(google_protobuf_Field_Cardinality_ce, "CARDINALITY_OPTIONAL", + strlen("CARDINALITY_OPTIONAL"), 1); + zend_declare_class_constant_long(google_protobuf_Field_Cardinality_ce, "CARDINALITY_REQUIRED", + strlen("CARDINALITY_REQUIRED"), 2); + zend_declare_class_constant_long(google_protobuf_Field_Cardinality_ce, "CARDINALITY_REPEATED", + strlen("CARDINALITY_REPEATED"), 3); +} + +/* google_protobuf_Enum */ + +zend_class_entry* google_protobuf_Enum_ce; + +static PHP_METHOD(google_protobuf_Enum, __construct) { + google_protobuf_type_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Enum, getName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Enum, setName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Enum, getEnumvalue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "enumvalue"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Enum, setEnumvalue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "enumvalue"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Enum, getOptions) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "options"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Enum, setOptions) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "options"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Enum, getSourceContext) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "source_context"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Enum, setSourceContext) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "source_context"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Enum, getSyntax) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "syntax"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Enum, setSyntax) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "syntax"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_Enum_phpmethods[] = { + PHP_ME(google_protobuf_Enum, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Enum, getName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Enum, setName, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Enum, getEnumvalue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Enum, setEnumvalue, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Enum, getOptions, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Enum, setOptions, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Enum, getSourceContext, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Enum, setSourceContext, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Enum, getSyntax, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Enum, setSyntax, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Enum_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Enum", + google_protobuf_Enum_phpmethods); + + google_protobuf_Enum_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Enum_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Enum_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Enum_ce, message_ce); +} + +/* google_protobuf_EnumValue */ + +zend_class_entry* google_protobuf_EnumValue_ce; + +static PHP_METHOD(google_protobuf_EnumValue, __construct) { + google_protobuf_type_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_EnumValue, getName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_EnumValue, setName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_EnumValue, getNumber) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "number"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_EnumValue, setNumber) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "number"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_EnumValue, getOptions) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "options"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_EnumValue, setOptions) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "options"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_EnumValue_phpmethods[] = { + PHP_ME(google_protobuf_EnumValue, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_EnumValue, getName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_EnumValue, setName, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_EnumValue, getNumber, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_EnumValue, setNumber, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_EnumValue, getOptions, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_EnumValue, setOptions, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_EnumValue_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumValue", + google_protobuf_EnumValue_phpmethods); + + google_protobuf_EnumValue_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_EnumValue_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_EnumValue_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_EnumValue_ce, message_ce); +} + +/* google_protobuf_Option */ + +zend_class_entry* google_protobuf_Option_ce; + +static PHP_METHOD(google_protobuf_Option, __construct) { + google_protobuf_type_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Option, getName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Option, setName) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "name"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Option, getValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Option, setValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_Option_phpmethods[] = { + PHP_ME(google_protobuf_Option, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Option, getName, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Option, setName, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Option, getValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Option, setValue, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Option_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Option", + google_protobuf_Option_phpmethods); + + google_protobuf_Option_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Option_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Option_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Option_ce, message_ce); +} + +/* google_protobuf_Syntax */ + +zend_class_entry* google_protobuf_Syntax_ce; + +PHP_METHOD(google_protobuf_Syntax, name) { + google_protobuf_type_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Syntax"); + const char *name; + zend_long value; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &value) == + FAILURE) { + return; + } + name = upb_enumdef_iton(e, value); + if (!name) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\Syntax has no name " + "defined for value " ZEND_LONG_FMT ".", + value); + return; + } + RETURN_STRING(name); +} + +PHP_METHOD(google_protobuf_Syntax, value) { + google_protobuf_type_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Syntax"); + char *name = NULL; + size_t name_len; + int32_t num; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, + &name_len) == FAILURE) { + return; + } + if (!upb_enumdef_ntoi(e, name, name_len, &num)) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\Syntax has no value " + "defined for name %s.", + name); + return; + } + RETURN_LONG(num); +} + +static zend_function_entry google_protobuf_Syntax_phpmethods[] = { + PHP_ME(google_protobuf_Syntax, name, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(google_protobuf_Syntax, value, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void google_protobuf_Syntax_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Syntax", + google_protobuf_Syntax_phpmethods); + + google_protobuf_Syntax_ce = zend_register_internal_class(&tmp_ce); + zend_declare_class_constant_long(google_protobuf_Syntax_ce, "SYNTAX_PROTO2", + strlen("SYNTAX_PROTO2"), 0); + zend_declare_class_constant_long(google_protobuf_Syntax_ce, "SYNTAX_PROTO3", + strlen("SYNTAX_PROTO3"), 1); +} + +/* google/protobuf/timestamp.proto */ + +zend_class_entry* GPBMetadata_Google_Protobuf_Timestamp_ce; + +const char google_protobuf_timestamp_proto_descriptor [239] = { +'\n', '\037', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'i', 'm', 'e', 's', 't', 'a', +'m', 'p', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', +'\"', '+', '\n', '\t', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', '\022', '\017', '\n', '\007', 's', 'e', 'c', 'o', 'n', 'd', 's', '\030', +'\001', ' ', '\001', '(', '\003', '\022', '\r', '\n', '\005', 'n', 'a', 'n', 'o', 's', '\030', '\002', ' ', '\001', '(', '\005', 'B', '\205', '\001', '\n', '\023', +'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\016', 'T', 'i', 'm', 'e', +'s', 't', 'a', 'm', 'p', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '2', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', +'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', +'w', 'n', '/', 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', +'\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', +'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static void google_protobuf_timestamp_proto_AddDescriptor() { + if (DescriptorPool_HasFile("google/protobuf/timestamp.proto")) return; + DescriptorPool_AddDescriptor("google/protobuf/timestamp.proto", google_protobuf_timestamp_proto_descriptor, + sizeof(google_protobuf_timestamp_proto_descriptor)); +} + +static PHP_METHOD(GPBMetadata_Google_Protobuf_Timestamp, initOnce) { + google_protobuf_timestamp_proto_AddDescriptor(); +} + +static zend_function_entry GPBMetadata_Google_Protobuf_Timestamp_methods[] = { + PHP_ME(GPBMetadata_Google_Protobuf_Timestamp, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void GPBMetadata_Google_Protobuf_Timestamp_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Timestamp", + GPBMetadata_Google_Protobuf_Timestamp_methods); + + GPBMetadata_Google_Protobuf_Timestamp_ce = zend_register_internal_class(&tmp_ce); +} + +/* google_protobuf_Timestamp */ + +zend_class_entry* google_protobuf_Timestamp_ce; + +static PHP_METHOD(google_protobuf_Timestamp, __construct) { + google_protobuf_timestamp_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Timestamp, getSeconds) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "seconds"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Timestamp, setSeconds) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "seconds"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static PHP_METHOD(google_protobuf_Timestamp, getNanos) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "nanos"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Timestamp, setNanos) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "nanos"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +ZEND_BEGIN_ARG_INFO_EX(arginfo_timestamp_fromdatetime, 0, 0, 1) + ZEND_ARG_INFO(0, datetime) +ZEND_END_ARG_INFO() + +static zend_function_entry google_protobuf_Timestamp_phpmethods[] = { + PHP_ME(google_protobuf_Timestamp, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Timestamp, getSeconds, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Timestamp, setSeconds, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Timestamp, getNanos, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Timestamp, setNanos, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Timestamp, fromDateTime, arginfo_timestamp_fromdatetime, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Timestamp, toDateTime, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Timestamp_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Timestamp", + google_protobuf_Timestamp_phpmethods); + + google_protobuf_Timestamp_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Timestamp_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Timestamp_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Timestamp_ce, message_ce); +} + +/* google/protobuf/wrappers.proto */ + +zend_class_entry* GPBMetadata_Google_Protobuf_Wrappers_ce; + +const char google_protobuf_wrappers_proto_descriptor [455] = { +'\n', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'w', 'r', 'a', 'p', 'p', 'e', 'r', +'s', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\"', +'\034', '\n', '\013', 'D', 'o', 'u', 'b', 'l', 'e', 'V', 'a', 'l', 'u', 'e', '\022', '\r', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', +' ', '\001', '(', '\001', '\"', '\033', '\n', '\n', 'F', 'l', 'o', 'a', 't', 'V', 'a', 'l', 'u', 'e', '\022', '\r', '\n', '\005', 'v', 'a', 'l', +'u', 'e', '\030', '\001', ' ', '\001', '(', '\002', '\"', '\033', '\n', '\n', 'I', 'n', 't', '6', '4', 'V', 'a', 'l', 'u', 'e', '\022', '\r', '\n', +'\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\003', '\"', '\034', '\n', '\013', 'U', 'I', 'n', 't', '6', '4', 'V', 'a', 'l', +'u', 'e', '\022', '\r', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\004', '\"', '\033', '\n', '\n', 'I', 'n', 't', '3', +'2', 'V', 'a', 'l', 'u', 'e', '\022', '\r', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\005', '\"', '\034', '\n', '\013', +'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', '\022', '\r', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', +'\r', '\"', '\032', '\n', '\t', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', '\022', '\r', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', +' ', '\001', '(', '\010', '\"', '\034', '\n', '\013', 'S', 't', 'r', 'i', 'n', 'g', 'V', 'a', 'l', 'u', 'e', '\022', '\r', '\n', '\005', 'v', 'a', +'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\"', '\033', '\n', '\n', 'B', 'y', 't', 'e', 's', 'V', 'a', 'l', 'u', 'e', '\022', '\r', +'\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\014', 'B', '\203', '\001', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', +'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\r', 'W', 'r', 'a', 'p', 'p', 'e', 'r', 's', 'P', 'r', 'o', +'t', 'o', 'P', '\001', 'Z', '1', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', +'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', 'w', 'n', '/', 'w', 'r', 'a', 'p', 'p', +'e', 'r', 's', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', +'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', +'r', 'o', 't', 'o', '3', +}; + +static void google_protobuf_wrappers_proto_AddDescriptor() { + if (DescriptorPool_HasFile("google/protobuf/wrappers.proto")) return; + DescriptorPool_AddDescriptor("google/protobuf/wrappers.proto", google_protobuf_wrappers_proto_descriptor, + sizeof(google_protobuf_wrappers_proto_descriptor)); +} + +static PHP_METHOD(GPBMetadata_Google_Protobuf_Wrappers, initOnce) { + google_protobuf_wrappers_proto_AddDescriptor(); +} + +static zend_function_entry GPBMetadata_Google_Protobuf_Wrappers_methods[] = { + PHP_ME(GPBMetadata_Google_Protobuf_Wrappers, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void GPBMetadata_Google_Protobuf_Wrappers_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Wrappers", + GPBMetadata_Google_Protobuf_Wrappers_methods); + + GPBMetadata_Google_Protobuf_Wrappers_ce = zend_register_internal_class(&tmp_ce); +} + +/* google_protobuf_DoubleValue */ + +zend_class_entry* google_protobuf_DoubleValue_ce; + +static PHP_METHOD(google_protobuf_DoubleValue, __construct) { + google_protobuf_wrappers_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_DoubleValue, getValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_DoubleValue, setValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_DoubleValue_phpmethods[] = { + PHP_ME(google_protobuf_DoubleValue, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_DoubleValue, getValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_DoubleValue, setValue, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_DoubleValue_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\DoubleValue", + google_protobuf_DoubleValue_phpmethods); + + google_protobuf_DoubleValue_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_DoubleValue_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_DoubleValue_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_DoubleValue_ce, message_ce); +} + +/* google_protobuf_FloatValue */ + +zend_class_entry* google_protobuf_FloatValue_ce; + +static PHP_METHOD(google_protobuf_FloatValue, __construct) { + google_protobuf_wrappers_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_FloatValue, getValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_FloatValue, setValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_FloatValue_phpmethods[] = { + PHP_ME(google_protobuf_FloatValue, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_FloatValue, getValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_FloatValue, setValue, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_FloatValue_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\FloatValue", + google_protobuf_FloatValue_phpmethods); + + google_protobuf_FloatValue_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_FloatValue_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_FloatValue_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_FloatValue_ce, message_ce); +} + +/* google_protobuf_Int64Value */ + +zend_class_entry* google_protobuf_Int64Value_ce; + +static PHP_METHOD(google_protobuf_Int64Value, __construct) { + google_protobuf_wrappers_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Int64Value, getValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Int64Value, setValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_Int64Value_phpmethods[] = { + PHP_ME(google_protobuf_Int64Value, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Int64Value, getValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Int64Value, setValue, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Int64Value_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Int64Value", + google_protobuf_Int64Value_phpmethods); + + google_protobuf_Int64Value_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Int64Value_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Int64Value_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Int64Value_ce, message_ce); +} + +/* google_protobuf_UInt64Value */ + +zend_class_entry* google_protobuf_UInt64Value_ce; + +static PHP_METHOD(google_protobuf_UInt64Value, __construct) { + google_protobuf_wrappers_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_UInt64Value, getValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_UInt64Value, setValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_UInt64Value_phpmethods[] = { + PHP_ME(google_protobuf_UInt64Value, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_UInt64Value, getValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_UInt64Value, setValue, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_UInt64Value_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\UInt64Value", + google_protobuf_UInt64Value_phpmethods); + + google_protobuf_UInt64Value_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_UInt64Value_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_UInt64Value_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_UInt64Value_ce, message_ce); +} + +/* google_protobuf_Int32Value */ + +zend_class_entry* google_protobuf_Int32Value_ce; + +static PHP_METHOD(google_protobuf_Int32Value, __construct) { + google_protobuf_wrappers_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Int32Value, getValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_Int32Value, setValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_Int32Value_phpmethods[] = { + PHP_ME(google_protobuf_Int32Value, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Int32Value, getValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Int32Value, setValue, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Int32Value_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Int32Value", + google_protobuf_Int32Value_phpmethods); + + google_protobuf_Int32Value_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Int32Value_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Int32Value_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Int32Value_ce, message_ce); +} + +/* google_protobuf_UInt32Value */ + +zend_class_entry* google_protobuf_UInt32Value_ce; + +static PHP_METHOD(google_protobuf_UInt32Value, __construct) { + google_protobuf_wrappers_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_UInt32Value, getValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_UInt32Value, setValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_UInt32Value_phpmethods[] = { + PHP_ME(google_protobuf_UInt32Value, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_UInt32Value, getValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_UInt32Value, setValue, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_UInt32Value_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\UInt32Value", + google_protobuf_UInt32Value_phpmethods); + + google_protobuf_UInt32Value_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_UInt32Value_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_UInt32Value_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_UInt32Value_ce, message_ce); +} + +/* google_protobuf_BoolValue */ + +zend_class_entry* google_protobuf_BoolValue_ce; + +static PHP_METHOD(google_protobuf_BoolValue, __construct) { + google_protobuf_wrappers_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_BoolValue, getValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_BoolValue, setValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_BoolValue_phpmethods[] = { + PHP_ME(google_protobuf_BoolValue, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_BoolValue, getValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_BoolValue, setValue, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_BoolValue_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\BoolValue", + google_protobuf_BoolValue_phpmethods); + + google_protobuf_BoolValue_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_BoolValue_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_BoolValue_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_BoolValue_ce, message_ce); +} + +/* google_protobuf_StringValue */ + +zend_class_entry* google_protobuf_StringValue_ce; + +static PHP_METHOD(google_protobuf_StringValue, __construct) { + google_protobuf_wrappers_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_StringValue, getValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_StringValue, setValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_StringValue_phpmethods[] = { + PHP_ME(google_protobuf_StringValue, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_StringValue, getValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_StringValue, setValue, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_StringValue_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\StringValue", + google_protobuf_StringValue_phpmethods); + + google_protobuf_StringValue_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_StringValue_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_StringValue_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_StringValue_ce, message_ce); +} + +/* google_protobuf_BytesValue */ + +zend_class_entry* google_protobuf_BytesValue_ce; + +static PHP_METHOD(google_protobuf_BytesValue, __construct) { + google_protobuf_wrappers_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_BytesValue, getValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval ret; + Message_get(intern, f, &ret); + RETURN_ZVAL(&ret, 1, 0); +} + +static PHP_METHOD(google_protobuf_BytesValue, setValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, + "value"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry google_protobuf_BytesValue_phpmethods[] = { + PHP_ME(google_protobuf_BytesValue, __construct, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_BytesValue, getValue, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_BytesValue, setValue, arginfo_setter, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_BytesValue_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\BytesValue", + google_protobuf_BytesValue_phpmethods); + + google_protobuf_BytesValue_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_BytesValue_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_BytesValue_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_BytesValue_ce, message_ce); +} + +static void WellKnownTypes_ModuleInit() { + GPBMetadata_Google_Protobuf_Any_ModuleInit(); + google_protobuf_Any_ModuleInit(); + GPBMetadata_Google_Protobuf_Api_ModuleInit(); + google_protobuf_Api_ModuleInit(); + google_protobuf_Method_ModuleInit(); + google_protobuf_Mixin_ModuleInit(); + GPBMetadata_Google_Protobuf_Duration_ModuleInit(); + google_protobuf_Duration_ModuleInit(); + GPBMetadata_Google_Protobuf_GPBEmpty_ModuleInit(); + google_protobuf_Empty_ModuleInit(); + GPBMetadata_Google_Protobuf_FieldMask_ModuleInit(); + google_protobuf_FieldMask_ModuleInit(); + GPBMetadata_Google_Protobuf_SourceContext_ModuleInit(); + google_protobuf_SourceContext_ModuleInit(); + GPBMetadata_Google_Protobuf_Struct_ModuleInit(); + google_protobuf_Struct_ModuleInit(); + google_protobuf_Struct_FieldsEntry_ModuleInit(); + google_protobuf_Value_ModuleInit(); + google_protobuf_ListValue_ModuleInit(); + google_protobuf_NullValue_ModuleInit(); + GPBMetadata_Google_Protobuf_Type_ModuleInit(); + google_protobuf_Type_ModuleInit(); + google_protobuf_Field_ModuleInit(); + google_protobuf_Field_Kind_ModuleInit(); + google_protobuf_Field_Cardinality_ModuleInit(); + google_protobuf_Enum_ModuleInit(); + google_protobuf_EnumValue_ModuleInit(); + google_protobuf_Option_ModuleInit(); + google_protobuf_Syntax_ModuleInit(); + GPBMetadata_Google_Protobuf_Timestamp_ModuleInit(); + google_protobuf_Timestamp_ModuleInit(); + GPBMetadata_Google_Protobuf_Wrappers_ModuleInit(); + google_protobuf_DoubleValue_ModuleInit(); + google_protobuf_FloatValue_ModuleInit(); + google_protobuf_Int64Value_ModuleInit(); + google_protobuf_UInt64Value_ModuleInit(); + google_protobuf_Int32Value_ModuleInit(); + google_protobuf_UInt32Value_ModuleInit(); + google_protobuf_BoolValue_ModuleInit(); + google_protobuf_StringValue_ModuleInit(); + google_protobuf_BytesValue_ModuleInit(); +} diff --git a/php/generate_descriptor_protos.sh b/php/generate_descriptor_protos.sh index 372ad69c6c26c..9feaa96c8b51e 100755 --- a/php/generate_descriptor_protos.sh +++ b/php/generate_descriptor_protos.sh @@ -1,8 +1,10 @@ #!/usr/bin/env bash -# Run this script to regenerate desriptor protos after the protocol compiler +# Run this script to regenerate descriptor protos after the protocol compiler # changes. +set -e + if test ! -e src/google/protobuf/stubs/common.h; then cat >&2 << __EOF__ Could not find source code. Make sure you are running this script from the @@ -13,4 +15,15 @@ fi pushd src ./protoc --php_out=internal:../php/src google/protobuf/descriptor.proto +./protoc --php_out=internal_generate_c_wkt:../php/src \ + google/protobuf/any.proto \ + google/protobuf/api.proto \ + google/protobuf/duration.proto \ + google/protobuf/empty.proto \ + google/protobuf/field_mask.proto \ + google/protobuf/source_context.proto \ + google/protobuf/struct.proto \ + google/protobuf/type.proto \ + google/protobuf/timestamp.proto \ + google/protobuf/wrappers.proto popd diff --git a/php/phpunit.xml b/php/phpunit.xml index d7077038ddeca..8e7583596bfb2 100644 --- a/php/phpunit.xml +++ b/php/phpunit.xml @@ -1,17 +1,18 @@ - - tests/php_implementation_test.php - tests/array_test.php - tests/encode_decode_test.php - tests/generated_class_test.php - tests/generated_phpdoc_test.php - tests/map_field_test.php - tests/well_known_test.php - tests/descriptors_test.php - tests/generated_service_test.php + tests/PhpImplementationTest.php + tests/ArrayTest.php + tests/EncodeDecodeTest.php + tests/GeneratedClassTest.php + tests/GeneratedPhpdocTest.php + tests/MapFieldTest.php + tests/WellKnownTest.php + tests/DescriptorsTest.php + tests/GeneratedServiceTest.php + tests/WrapperTypeSettersTest.php diff --git a/php/prepare_c_extension.sh b/php/prepare_c_extension.sh new file mode 100755 index 0000000000000..84cd1aa3d1552 --- /dev/null +++ b/php/prepare_c_extension.sh @@ -0,0 +1,6 @@ + +# wyhash has to live in the base third_party directory. +# We copy it into the ext/google/protobuf directory for the build +# (and for the release to PECL). +mkdir -p ../ext/google/protobuf/third_party/wyhash +cp ../../third_party/wyhash/* ../ext/google/protobuf/third_party/wyhash diff --git a/php/release.sh b/php/release.sh new file mode 100755 index 0000000000000..6b0baac78ff57 --- /dev/null +++ b/php/release.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +set -ex + +# Make sure we are in a protobuf source tree. +[ -f "php/release.sh" ] || { + echo "This script must be ran under root of protobuf source tree." + exit 1 +} + +VERSION=$1 + +git clone https://github.com/protocolbuffers/protobuf-php.git +git clone https://github.com/protocolbuffers/protobuf.git + +# Clean old files +pushd protobuf-php +rm -rf src +popd + +# Checkout the target version +pushd protobuf/php +git checkout -b $VERSION +popd + +# Copy files +pushd protobuf-php +mv ../protobuf/php/src src +mv ../protobuf/composer.json composer.json +sed -i 's|php/src|src|g' composer.json +git add . +git commit -m "$VERSION" +git tag "$VERSION" +popd + +# Clean up +rm -rf protobuf diff --git a/php/src/GPBMetadata/Google/Protobuf/Any.php b/php/src/GPBMetadata/Google/Protobuf/Any.php new file mode 100644 index 0000000000000..fbce4bfdb10f9 --- /dev/null +++ b/php/src/GPBMetadata/Google/Protobuf/Any.php @@ -0,0 +1,30 @@ +internalAddGeneratedFile( + ' +� +google/protobuf/any.protogoogle.protobuf"& +Any +type_url (  +value ( Bv +com.google.protobufBAnyProtoPZ,google.golang.org/protobuf/types/known/anypb�GPB�Google.Protobuf.WellKnownTypesbproto3' + , true); + + static::$is_initialized = true; + } +} + diff --git a/php/src/GPBMetadata/Google/Protobuf/Api.php b/php/src/GPBMetadata/Google/Protobuf/Api.php new file mode 100644 index 0000000000000..75e0ec6318056 --- /dev/null +++ b/php/src/GPBMetadata/Google/Protobuf/Api.php @@ -0,0 +1,48 @@ +internalAddGeneratedFile( + ' +� +google/protobuf/api.protogoogle.protobufgoogle/protobuf/type.proto"� +Api +name ( ( +methods ( 2.google.protobuf.Method( +options ( 2.google.protobuf.Option +version ( 6 +source_context ( 2.google.protobuf.SourceContext& +mixins ( 2.google.protobuf.Mixin\' +syntax (2.google.protobuf.Syntax"� +Method +name (  +request_type_url (  +request_streaming ( +response_type_url (  +response_streaming (( +options ( 2.google.protobuf.Option\' +syntax (2.google.protobuf.Syntax"# +Mixin +name (  +root ( Bv +com.google.protobufBApiProtoPZ,google.golang.org/protobuf/types/known/apipb�GPB�Google.Protobuf.WellKnownTypesbproto3' + , true); + + static::$is_initialized = true; + } +} + diff --git a/php/src/GPBMetadata/Google/Protobuf/Duration.php b/php/src/GPBMetadata/Google/Protobuf/Duration.php new file mode 100644 index 0000000000000..5d8023e4db9e6 --- /dev/null +++ b/php/src/GPBMetadata/Google/Protobuf/Duration.php @@ -0,0 +1,30 @@ +internalAddGeneratedFile( + ' +� +google/protobuf/duration.protogoogle.protobuf"* +Duration +seconds ( +nanos (B� +com.google.protobufB DurationProtoPZ1google.golang.org/protobuf/types/known/durationpb��GPB�Google.Protobuf.WellKnownTypesbproto3' + , true); + + static::$is_initialized = true; + } +} + diff --git a/php/src/GPBMetadata/Google/Protobuf/FieldMask.php b/php/src/GPBMetadata/Google/Protobuf/FieldMask.php new file mode 100644 index 0000000000000..f31bcc0012450 --- /dev/null +++ b/php/src/GPBMetadata/Google/Protobuf/FieldMask.php @@ -0,0 +1,29 @@ +internalAddGeneratedFile( + ' +� + google/protobuf/field_mask.protogoogle.protobuf" + FieldMask +paths ( B� +com.google.protobufBFieldMaskProtoPZ2google.golang.org/protobuf/types/known/fieldmaskpb��GPB�Google.Protobuf.WellKnownTypesbproto3' + , true); + + static::$is_initialized = true; + } +} + diff --git a/php/src/GPBMetadata/Google/Protobuf/GPBEmpty.php b/php/src/GPBMetadata/Google/Protobuf/GPBEmpty.php new file mode 100644 index 0000000000000..5e42536f270c9 --- /dev/null +++ b/php/src/GPBMetadata/Google/Protobuf/GPBEmpty.php @@ -0,0 +1,29 @@ +internalAddGeneratedFile( + ' +� +google/protobuf/empty.protogoogle.protobuf" +EmptyB} +com.google.protobufB +EmptyProtoPZ.google.golang.org/protobuf/types/known/emptypb��GPB�Google.Protobuf.WellKnownTypesbproto3' + , true); + + static::$is_initialized = true; + } +} + diff --git a/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php b/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php index 60722d00aad46..ea0edc55575aa 100644 --- a/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php +++ b/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php @@ -46,13 +46,13 @@ public static function initOnce() { ->repeated('reserved_name', \Google\Protobuf\Internal\GPBType::STRING, 10) ->finalizeToPool(); - $pool->addMessage('google.protobuf.internal.DescriptorProto.ExtensionRange', \Google\Protobuf\Internal\DescriptorProto_ExtensionRange::class) + $pool->addMessage('google.protobuf.internal.DescriptorProto.ExtensionRange', \Google\Protobuf\Internal\DescriptorProto\ExtensionRange::class) ->optional('start', \Google\Protobuf\Internal\GPBType::INT32, 1) ->optional('end', \Google\Protobuf\Internal\GPBType::INT32, 2) ->optional('options', \Google\Protobuf\Internal\GPBType::MESSAGE, 3, 'google.protobuf.internal.ExtensionRangeOptions') ->finalizeToPool(); - $pool->addMessage('google.protobuf.internal.DescriptorProto.ReservedRange', \Google\Protobuf\Internal\DescriptorProto_ReservedRange::class) + $pool->addMessage('google.protobuf.internal.DescriptorProto.ReservedRange', \Google\Protobuf\Internal\DescriptorProto\ReservedRange::class) ->optional('start', \Google\Protobuf\Internal\GPBType::INT32, 1) ->optional('end', \Google\Protobuf\Internal\GPBType::INT32, 2) ->finalizeToPool(); @@ -72,6 +72,7 @@ public static function initOnce() { ->optional('oneof_index', \Google\Protobuf\Internal\GPBType::INT32, 9) ->optional('json_name', \Google\Protobuf\Internal\GPBType::STRING, 10) ->optional('options', \Google\Protobuf\Internal\GPBType::MESSAGE, 8, 'google.protobuf.internal.FieldOptions') + ->optional('proto3_optional', \Google\Protobuf\Internal\GPBType::BOOL, 17) ->finalizeToPool(); $pool->addEnum('google.protobuf.internal.FieldDescriptorProto.Type', \Google\Protobuf\Internal\Type::class) @@ -110,6 +111,13 @@ public static function initOnce() { ->optional('name', \Google\Protobuf\Internal\GPBType::STRING, 1) ->repeated('value', \Google\Protobuf\Internal\GPBType::MESSAGE, 2, 'google.protobuf.internal.EnumValueDescriptorProto') ->optional('options', \Google\Protobuf\Internal\GPBType::MESSAGE, 3, 'google.protobuf.internal.EnumOptions') + ->repeated('reserved_range', \Google\Protobuf\Internal\GPBType::MESSAGE, 4, 'google.protobuf.internal.EnumDescriptorProto.EnumReservedRange') + ->repeated('reserved_name', \Google\Protobuf\Internal\GPBType::STRING, 5) + ->finalizeToPool(); + + $pool->addMessage('google.protobuf.internal.EnumDescriptorProto.EnumReservedRange', \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange::class) + ->optional('start', \Google\Protobuf\Internal\GPBType::INT32, 1) + ->optional('end', \Google\Protobuf\Internal\GPBType::INT32, 2) ->finalizeToPool(); $pool->addMessage('google.protobuf.internal.EnumValueDescriptorProto', \Google\Protobuf\Internal\EnumValueDescriptorProto::class) @@ -144,7 +152,7 @@ public static function initOnce() { ->optional('cc_generic_services', \Google\Protobuf\Internal\GPBType::BOOL, 16) ->optional('java_generic_services', \Google\Protobuf\Internal\GPBType::BOOL, 17) ->optional('py_generic_services', \Google\Protobuf\Internal\GPBType::BOOL, 18) - ->optional('php_generic_services', \Google\Protobuf\Internal\GPBType::BOOL, 19) + ->optional('php_generic_services', \Google\Protobuf\Internal\GPBType::BOOL, 42) ->optional('deprecated', \Google\Protobuf\Internal\GPBType::BOOL, 23) ->optional('cc_enable_arenas', \Google\Protobuf\Internal\GPBType::BOOL, 31) ->optional('objc_class_prefix', \Google\Protobuf\Internal\GPBType::STRING, 36) @@ -152,6 +160,8 @@ public static function initOnce() { ->optional('swift_prefix', \Google\Protobuf\Internal\GPBType::STRING, 39) ->optional('php_class_prefix', \Google\Protobuf\Internal\GPBType::STRING, 40) ->optional('php_namespace', \Google\Protobuf\Internal\GPBType::STRING, 41) + ->optional('php_metadata_namespace', \Google\Protobuf\Internal\GPBType::STRING, 44) + ->optional('ruby_package', \Google\Protobuf\Internal\GPBType::STRING, 45) ->repeated('uninterpreted_option', \Google\Protobuf\Internal\GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption') ->finalizeToPool(); @@ -233,7 +243,7 @@ public static function initOnce() { ->optional('aggregate_value', \Google\Protobuf\Internal\GPBType::STRING, 8) ->finalizeToPool(); - $pool->addMessage('google.protobuf.internal.UninterpretedOption.NamePart', \Google\Protobuf\Internal\UninterpretedOption_NamePart::class) + $pool->addMessage('google.protobuf.internal.UninterpretedOption.NamePart', \Google\Protobuf\Internal\UninterpretedOption\NamePart::class) ->required('name_part', \Google\Protobuf\Internal\GPBType::STRING, 1) ->required('is_extension', \Google\Protobuf\Internal\GPBType::BOOL, 2) ->finalizeToPool(); @@ -242,7 +252,7 @@ public static function initOnce() { ->repeated('location', \Google\Protobuf\Internal\GPBType::MESSAGE, 1, 'google.protobuf.internal.SourceCodeInfo.Location') ->finalizeToPool(); - $pool->addMessage('google.protobuf.internal.SourceCodeInfo.Location', \Google\Protobuf\Internal\SourceCodeInfo_Location::class) + $pool->addMessage('google.protobuf.internal.SourceCodeInfo.Location', \Google\Protobuf\Internal\SourceCodeInfo\Location::class) ->repeated('path', \Google\Protobuf\Internal\GPBType::INT32, 1) ->repeated('span', \Google\Protobuf\Internal\GPBType::INT32, 2) ->optional('leading_comments', \Google\Protobuf\Internal\GPBType::STRING, 3) @@ -254,7 +264,7 @@ public static function initOnce() { ->repeated('annotation', \Google\Protobuf\Internal\GPBType::MESSAGE, 1, 'google.protobuf.internal.GeneratedCodeInfo.Annotation') ->finalizeToPool(); - $pool->addMessage('google.protobuf.internal.GeneratedCodeInfo.Annotation', \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation::class) + $pool->addMessage('google.protobuf.internal.GeneratedCodeInfo.Annotation', \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation::class) ->repeated('path', \Google\Protobuf\Internal\GPBType::INT32, 1) ->optional('source_file', \Google\Protobuf\Internal\GPBType::STRING, 2) ->optional('begin', \Google\Protobuf\Internal\GPBType::INT32, 3) diff --git a/php/src/GPBMetadata/Google/Protobuf/SourceContext.php b/php/src/GPBMetadata/Google/Protobuf/SourceContext.php new file mode 100644 index 0000000000000..797732d9f3261 --- /dev/null +++ b/php/src/GPBMetadata/Google/Protobuf/SourceContext.php @@ -0,0 +1,29 @@ +internalAddGeneratedFile( + ' +� +$google/protobuf/source_context.protogoogle.protobuf"" + SourceContext + file_name ( B� +com.google.protobufBSourceContextProtoPZ6google.golang.org/protobuf/types/known/sourcecontextpb�GPB�Google.Protobuf.WellKnownTypesbproto3' + , true); + + static::$is_initialized = true; + } +} + diff --git a/php/src/GPBMetadata/Google/Protobuf/Struct.php b/php/src/GPBMetadata/Google/Protobuf/Struct.php new file mode 100644 index 0000000000000..888a81adee407 Binary files /dev/null and b/php/src/GPBMetadata/Google/Protobuf/Struct.php differ diff --git a/php/src/GPBMetadata/Google/Protobuf/Timestamp.php b/php/src/GPBMetadata/Google/Protobuf/Timestamp.php new file mode 100644 index 0000000000000..09437271a91c0 --- /dev/null +++ b/php/src/GPBMetadata/Google/Protobuf/Timestamp.php @@ -0,0 +1,30 @@ +internalAddGeneratedFile( + ' +� +google/protobuf/timestamp.protogoogle.protobuf"+ + Timestamp +seconds ( +nanos (B� +com.google.protobufBTimestampProtoPZ2google.golang.org/protobuf/types/known/timestamppb��GPB�Google.Protobuf.WellKnownTypesbproto3' + , true); + + static::$is_initialized = true; + } +} + diff --git a/php/src/GPBMetadata/Google/Protobuf/Type.php b/php/src/GPBMetadata/Google/Protobuf/Type.php new file mode 100644 index 0000000000000..7d0bfbb533a2a Binary files /dev/null and b/php/src/GPBMetadata/Google/Protobuf/Type.php differ diff --git a/php/src/GPBMetadata/Google/Protobuf/Wrappers.php b/php/src/GPBMetadata/Google/Protobuf/Wrappers.php new file mode 100644 index 0000000000000..e7ea1a3b95162 --- /dev/null +++ b/php/src/GPBMetadata/Google/Protobuf/Wrappers.php @@ -0,0 +1,49 @@ +internalAddGeneratedFile( + ' +� +google/protobuf/wrappers.protogoogle.protobuf" + DoubleValue +value (" + +FloatValue +value (" + +Int64Value +value (" + UInt64Value +value (" + +Int32Value +value (" + UInt32Value +value ( " + BoolValue +value (" + StringValue +value ( " + +BytesValue +value ( B� +com.google.protobufB WrappersProtoPZ1google.golang.org/protobuf/types/known/wrapperspb��GPB�Google.Protobuf.WellKnownTypesbproto3' + , true); + + static::$is_initialized = true; + } +} + diff --git a/php/src/Google/Protobuf/Any.php b/php/src/Google/Protobuf/Any.php new file mode 100644 index 0000000000000..8fdc3c483d22a --- /dev/null +++ b/php/src/Google/Protobuf/Any.php @@ -0,0 +1,254 @@ +, + * "lastName": + * } + * If the embedded message type is well-known and has a custom JSON + * representation, that representation will be embedded adding a field + * `value` which holds the custom JSON in addition to the `@type` + * field. Example (for message [google.protobuf.Duration][]): + * { + * "@type": "type.googleapis.com/google.protobuf.Duration", + * "value": "1.212s" + * } + * + * Generated from protobuf message google.protobuf.Any + */ +class Any extends \Google\Protobuf\Internal\AnyBase +{ + /** + * A URL/resource name that uniquely identifies the type of the serialized + * protocol buffer message. This string must contain at least + * one "/" character. The last segment of the URL's path must represent + * the fully qualified name of the type (as in + * `path/google.protobuf.Duration`). The name should be in a canonical form + * (e.g., leading "." is not accepted). + * In practice, teams usually precompile into the binary all types that they + * expect it to use in the context of Any. However, for URLs which use the + * scheme `http`, `https`, or no scheme, one can optionally set up a type + * server that maps type URLs to message definitions as follows: + * * If no scheme is provided, `https` is assumed. + * * An HTTP GET on the URL must yield a [google.protobuf.Type][] + * value in binary format, or produce an error. + * * Applications are allowed to cache lookup results based on the + * URL, or have them precompiled into a binary to avoid any + * lookup. Therefore, binary compatibility needs to be preserved + * on changes to types. (Use versioned type names to manage + * breaking changes.) + * Note: this functionality is not currently available in the official + * protobuf release, and it is not used for type URLs beginning with + * type.googleapis.com. + * Schemes other than `http`, `https` (or the empty scheme) might be + * used with implementation specific semantics. + * + * Generated from protobuf field string type_url = 1; + */ + protected $type_url = ''; + /** + * Must be a valid serialized protocol buffer of the above specified type. + * + * Generated from protobuf field bytes value = 2; + */ + protected $value = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $type_url + * A URL/resource name that uniquely identifies the type of the serialized + * protocol buffer message. This string must contain at least + * one "/" character. The last segment of the URL's path must represent + * the fully qualified name of the type (as in + * `path/google.protobuf.Duration`). The name should be in a canonical form + * (e.g., leading "." is not accepted). + * In practice, teams usually precompile into the binary all types that they + * expect it to use in the context of Any. However, for URLs which use the + * scheme `http`, `https`, or no scheme, one can optionally set up a type + * server that maps type URLs to message definitions as follows: + * * If no scheme is provided, `https` is assumed. + * * An HTTP GET on the URL must yield a [google.protobuf.Type][] + * value in binary format, or produce an error. + * * Applications are allowed to cache lookup results based on the + * URL, or have them precompiled into a binary to avoid any + * lookup. Therefore, binary compatibility needs to be preserved + * on changes to types. (Use versioned type names to manage + * breaking changes.) + * Note: this functionality is not currently available in the official + * protobuf release, and it is not used for type URLs beginning with + * type.googleapis.com. + * Schemes other than `http`, `https` (or the empty scheme) might be + * used with implementation specific semantics. + * @type string $value + * Must be a valid serialized protocol buffer of the above specified type. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Any::initOnce(); + parent::__construct($data); + } + + /** + * A URL/resource name that uniquely identifies the type of the serialized + * protocol buffer message. This string must contain at least + * one "/" character. The last segment of the URL's path must represent + * the fully qualified name of the type (as in + * `path/google.protobuf.Duration`). The name should be in a canonical form + * (e.g., leading "." is not accepted). + * In practice, teams usually precompile into the binary all types that they + * expect it to use in the context of Any. However, for URLs which use the + * scheme `http`, `https`, or no scheme, one can optionally set up a type + * server that maps type URLs to message definitions as follows: + * * If no scheme is provided, `https` is assumed. + * * An HTTP GET on the URL must yield a [google.protobuf.Type][] + * value in binary format, or produce an error. + * * Applications are allowed to cache lookup results based on the + * URL, or have them precompiled into a binary to avoid any + * lookup. Therefore, binary compatibility needs to be preserved + * on changes to types. (Use versioned type names to manage + * breaking changes.) + * Note: this functionality is not currently available in the official + * protobuf release, and it is not used for type URLs beginning with + * type.googleapis.com. + * Schemes other than `http`, `https` (or the empty scheme) might be + * used with implementation specific semantics. + * + * Generated from protobuf field string type_url = 1; + * @return string + */ + public function getTypeUrl() + { + return $this->type_url; + } + + /** + * A URL/resource name that uniquely identifies the type of the serialized + * protocol buffer message. This string must contain at least + * one "/" character. The last segment of the URL's path must represent + * the fully qualified name of the type (as in + * `path/google.protobuf.Duration`). The name should be in a canonical form + * (e.g., leading "." is not accepted). + * In practice, teams usually precompile into the binary all types that they + * expect it to use in the context of Any. However, for URLs which use the + * scheme `http`, `https`, or no scheme, one can optionally set up a type + * server that maps type URLs to message definitions as follows: + * * If no scheme is provided, `https` is assumed. + * * An HTTP GET on the URL must yield a [google.protobuf.Type][] + * value in binary format, or produce an error. + * * Applications are allowed to cache lookup results based on the + * URL, or have them precompiled into a binary to avoid any + * lookup. Therefore, binary compatibility needs to be preserved + * on changes to types. (Use versioned type names to manage + * breaking changes.) + * Note: this functionality is not currently available in the official + * protobuf release, and it is not used for type URLs beginning with + * type.googleapis.com. + * Schemes other than `http`, `https` (or the empty scheme) might be + * used with implementation specific semantics. + * + * Generated from protobuf field string type_url = 1; + * @param string $var + * @return $this + */ + public function setTypeUrl($var) + { + GPBUtil::checkString($var, True); + $this->type_url = $var; + + return $this; + } + + /** + * Must be a valid serialized protocol buffer of the above specified type. + * + * Generated from protobuf field bytes value = 2; + * @return string + */ + public function getValue() + { + return $this->value; + } + + /** + * Must be a valid serialized protocol buffer of the above specified type. + * + * Generated from protobuf field bytes value = 2; + * @param string $var + * @return $this + */ + public function setValue($var) + { + GPBUtil::checkString($var, False); + $this->value = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Api.php b/php/src/Google/Protobuf/Api.php new file mode 100644 index 0000000000000..7cbb30eb42846 --- /dev/null +++ b/php/src/Google/Protobuf/Api.php @@ -0,0 +1,360 @@ +google.protobuf.Api + */ +class Api extends \Google\Protobuf\Internal\Message +{ + /** + * The fully qualified name of this interface, including package name + * followed by the interface's simple name. + * + * Generated from protobuf field string name = 1; + */ + protected $name = ''; + /** + * The methods of this interface, in unspecified order. + * + * Generated from protobuf field repeated .google.protobuf.Method methods = 2; + */ + private $methods; + /** + * Any metadata attached to the interface. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 3; + */ + private $options; + /** + * A version string for this interface. If specified, must have the form + * `major-version.minor-version`, as in `1.10`. If the minor version is + * omitted, it defaults to zero. If the entire version field is empty, the + * major version is derived from the package name, as outlined below. If the + * field is not empty, the version in the package name will be verified to be + * consistent with what is provided here. + * The versioning schema uses [semantic + * versioning](http://semver.org) where the major version number + * indicates a breaking change and the minor version an additive, + * non-breaking change. Both version numbers are signals to users + * what to expect from different versions, and should be carefully + * chosen based on the product plan. + * The major version is also reflected in the package name of the + * interface, which must end in `v`, as in + * `google.feature.v1`. For major versions 0 and 1, the suffix can + * be omitted. Zero major versions must only be used for + * experimental, non-GA interfaces. + * + * Generated from protobuf field string version = 4; + */ + protected $version = ''; + /** + * Source context for the protocol buffer service represented by this + * message. + * + * Generated from protobuf field .google.protobuf.SourceContext source_context = 5; + */ + protected $source_context = null; + /** + * Included interfaces. See [Mixin][]. + * + * Generated from protobuf field repeated .google.protobuf.Mixin mixins = 6; + */ + private $mixins; + /** + * The source syntax of the service. + * + * Generated from protobuf field .google.protobuf.Syntax syntax = 7; + */ + protected $syntax = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * The fully qualified name of this interface, including package name + * followed by the interface's simple name. + * @type \Google\Protobuf\Method[]|\Google\Protobuf\Internal\RepeatedField $methods + * The methods of this interface, in unspecified order. + * @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options + * Any metadata attached to the interface. + * @type string $version + * A version string for this interface. If specified, must have the form + * `major-version.minor-version`, as in `1.10`. If the minor version is + * omitted, it defaults to zero. If the entire version field is empty, the + * major version is derived from the package name, as outlined below. If the + * field is not empty, the version in the package name will be verified to be + * consistent with what is provided here. + * The versioning schema uses [semantic + * versioning](http://semver.org) where the major version number + * indicates a breaking change and the minor version an additive, + * non-breaking change. Both version numbers are signals to users + * what to expect from different versions, and should be carefully + * chosen based on the product plan. + * The major version is also reflected in the package name of the + * interface, which must end in `v`, as in + * `google.feature.v1`. For major versions 0 and 1, the suffix can + * be omitted. Zero major versions must only be used for + * experimental, non-GA interfaces. + * @type \Google\Protobuf\SourceContext $source_context + * Source context for the protocol buffer service represented by this + * message. + * @type \Google\Protobuf\Mixin[]|\Google\Protobuf\Internal\RepeatedField $mixins + * Included interfaces. See [Mixin][]. + * @type int $syntax + * The source syntax of the service. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Api::initOnce(); + parent::__construct($data); + } + + /** + * The fully qualified name of this interface, including package name + * followed by the interface's simple name. + * + * Generated from protobuf field string name = 1; + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * The fully qualified name of this interface, including package name + * followed by the interface's simple name. + * + * Generated from protobuf field string name = 1; + * @param string $var + * @return $this + */ + public function setName($var) + { + GPBUtil::checkString($var, True); + $this->name = $var; + + return $this; + } + + /** + * The methods of this interface, in unspecified order. + * + * Generated from protobuf field repeated .google.protobuf.Method methods = 2; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getMethods() + { + return $this->methods; + } + + /** + * The methods of this interface, in unspecified order. + * + * Generated from protobuf field repeated .google.protobuf.Method methods = 2; + * @param \Google\Protobuf\Method[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setMethods($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Method::class); + $this->methods = $arr; + + return $this; + } + + /** + * Any metadata attached to the interface. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 3; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getOptions() + { + return $this->options; + } + + /** + * Any metadata attached to the interface. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 3; + * @param \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setOptions($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Option::class); + $this->options = $arr; + + return $this; + } + + /** + * A version string for this interface. If specified, must have the form + * `major-version.minor-version`, as in `1.10`. If the minor version is + * omitted, it defaults to zero. If the entire version field is empty, the + * major version is derived from the package name, as outlined below. If the + * field is not empty, the version in the package name will be verified to be + * consistent with what is provided here. + * The versioning schema uses [semantic + * versioning](http://semver.org) where the major version number + * indicates a breaking change and the minor version an additive, + * non-breaking change. Both version numbers are signals to users + * what to expect from different versions, and should be carefully + * chosen based on the product plan. + * The major version is also reflected in the package name of the + * interface, which must end in `v`, as in + * `google.feature.v1`. For major versions 0 and 1, the suffix can + * be omitted. Zero major versions must only be used for + * experimental, non-GA interfaces. + * + * Generated from protobuf field string version = 4; + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * A version string for this interface. If specified, must have the form + * `major-version.minor-version`, as in `1.10`. If the minor version is + * omitted, it defaults to zero. If the entire version field is empty, the + * major version is derived from the package name, as outlined below. If the + * field is not empty, the version in the package name will be verified to be + * consistent with what is provided here. + * The versioning schema uses [semantic + * versioning](http://semver.org) where the major version number + * indicates a breaking change and the minor version an additive, + * non-breaking change. Both version numbers are signals to users + * what to expect from different versions, and should be carefully + * chosen based on the product plan. + * The major version is also reflected in the package name of the + * interface, which must end in `v`, as in + * `google.feature.v1`. For major versions 0 and 1, the suffix can + * be omitted. Zero major versions must only be used for + * experimental, non-GA interfaces. + * + * Generated from protobuf field string version = 4; + * @param string $var + * @return $this + */ + public function setVersion($var) + { + GPBUtil::checkString($var, True); + $this->version = $var; + + return $this; + } + + /** + * Source context for the protocol buffer service represented by this + * message. + * + * Generated from protobuf field .google.protobuf.SourceContext source_context = 5; + * @return \Google\Protobuf\SourceContext|null + */ + public function getSourceContext() + { + return isset($this->source_context) ? $this->source_context : null; + } + + public function hasSourceContext() + { + return isset($this->source_context); + } + + public function clearSourceContext() + { + unset($this->source_context); + } + + /** + * Source context for the protocol buffer service represented by this + * message. + * + * Generated from protobuf field .google.protobuf.SourceContext source_context = 5; + * @param \Google\Protobuf\SourceContext $var + * @return $this + */ + public function setSourceContext($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\SourceContext::class); + $this->source_context = $var; + + return $this; + } + + /** + * Included interfaces. See [Mixin][]. + * + * Generated from protobuf field repeated .google.protobuf.Mixin mixins = 6; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getMixins() + { + return $this->mixins; + } + + /** + * Included interfaces. See [Mixin][]. + * + * Generated from protobuf field repeated .google.protobuf.Mixin mixins = 6; + * @param \Google\Protobuf\Mixin[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setMixins($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Mixin::class); + $this->mixins = $arr; + + return $this; + } + + /** + * The source syntax of the service. + * + * Generated from protobuf field .google.protobuf.Syntax syntax = 7; + * @return int + */ + public function getSyntax() + { + return $this->syntax; + } + + /** + * The source syntax of the service. + * + * Generated from protobuf field .google.protobuf.Syntax syntax = 7; + * @param int $var + * @return $this + */ + public function setSyntax($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Syntax::class); + $this->syntax = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/BoolValue.php b/php/src/Google/Protobuf/BoolValue.php new file mode 100644 index 0000000000000..ecdbf4dcc2656 --- /dev/null +++ b/php/src/Google/Protobuf/BoolValue.php @@ -0,0 +1,68 @@ +google.protobuf.BoolValue + */ +class BoolValue extends \Google\Protobuf\Internal\Message +{ + /** + * The bool value. + * + * Generated from protobuf field bool value = 1; + */ + protected $value = false; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type bool $value + * The bool value. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Wrappers::initOnce(); + parent::__construct($data); + } + + /** + * The bool value. + * + * Generated from protobuf field bool value = 1; + * @return bool + */ + public function getValue() + { + return $this->value; + } + + /** + * The bool value. + * + * Generated from protobuf field bool value = 1; + * @param bool $var + * @return $this + */ + public function setValue($var) + { + GPBUtil::checkBool($var); + $this->value = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/BytesValue.php b/php/src/Google/Protobuf/BytesValue.php new file mode 100644 index 0000000000000..1582e14acd903 --- /dev/null +++ b/php/src/Google/Protobuf/BytesValue.php @@ -0,0 +1,68 @@ +google.protobuf.BytesValue + */ +class BytesValue extends \Google\Protobuf\Internal\Message +{ + /** + * The bytes value. + * + * Generated from protobuf field bytes value = 1; + */ + protected $value = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $value + * The bytes value. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Wrappers::initOnce(); + parent::__construct($data); + } + + /** + * The bytes value. + * + * Generated from protobuf field bytes value = 1; + * @return string + */ + public function getValue() + { + return $this->value; + } + + /** + * The bytes value. + * + * Generated from protobuf field bytes value = 1; + * @param string $var + * @return $this + */ + public function setValue($var) + { + GPBUtil::checkString($var, False); + $this->value = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Descriptor.php b/php/src/Google/Protobuf/Descriptor.php index 986b81e12d61b..36436e2b70b52 100644 --- a/php/src/Google/Protobuf/Descriptor.php +++ b/php/src/Google/Protobuf/Descriptor.php @@ -97,4 +97,12 @@ public function getOneofDeclCount() { return count($this->internal_desc->getOneofDecl()); } + + /** + * @return int Number of real oneofs in message + */ + public function getRealOneofDeclCount() + { + return $this->internal_desc->getRealOneofDeclCount(); + } } diff --git a/php/src/Google/Protobuf/DoubleValue.php b/php/src/Google/Protobuf/DoubleValue.php new file mode 100644 index 0000000000000..b72399f460d68 --- /dev/null +++ b/php/src/Google/Protobuf/DoubleValue.php @@ -0,0 +1,68 @@ +google.protobuf.DoubleValue + */ +class DoubleValue extends \Google\Protobuf\Internal\Message +{ + /** + * The double value. + * + * Generated from protobuf field double value = 1; + */ + protected $value = 0.0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type float $value + * The double value. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Wrappers::initOnce(); + parent::__construct($data); + } + + /** + * The double value. + * + * Generated from protobuf field double value = 1; + * @return float + */ + public function getValue() + { + return $this->value; + } + + /** + * The double value. + * + * Generated from protobuf field double value = 1; + * @param float $var + * @return $this + */ + public function setValue($var) + { + GPBUtil::checkDouble($var); + $this->value = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Duration.php b/php/src/Google/Protobuf/Duration.php new file mode 100644 index 0000000000000..531cd50b57915 --- /dev/null +++ b/php/src/Google/Protobuf/Duration.php @@ -0,0 +1,173 @@ + 0) { + * duration.seconds += 1; + * duration.nanos -= 1000000000; + * } else if (duration.seconds > 0 && duration.nanos < 0) { + * duration.seconds -= 1; + * duration.nanos += 1000000000; + * } + * Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. + * Timestamp start = ...; + * Duration duration = ...; + * Timestamp end = ...; + * end.seconds = start.seconds + duration.seconds; + * end.nanos = start.nanos + duration.nanos; + * if (end.nanos < 0) { + * end.seconds -= 1; + * end.nanos += 1000000000; + * } else if (end.nanos >= 1000000000) { + * end.seconds += 1; + * end.nanos -= 1000000000; + * } + * Example 3: Compute Duration from datetime.timedelta in Python. + * td = datetime.timedelta(days=3, minutes=10) + * duration = Duration() + * duration.FromTimedelta(td) + * # JSON Mapping + * In JSON format, the Duration type is encoded as a string rather than an + * object, where the string ends in the suffix "s" (indicating seconds) and + * is preceded by the number of seconds, with nanoseconds expressed as + * fractional seconds. For example, 3 seconds with 0 nanoseconds should be + * encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should + * be expressed in JSON format as "3.000000001s", and 3 seconds and 1 + * microsecond should be expressed in JSON format as "3.000001s". + * + * Generated from protobuf message google.protobuf.Duration + */ +class Duration extends \Google\Protobuf\Internal\Message +{ + /** + * Signed seconds of the span of time. Must be from -315,576,000,000 + * to +315,576,000,000 inclusive. Note: these bounds are computed from: + * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + * + * Generated from protobuf field int64 seconds = 1; + */ + protected $seconds = 0; + /** + * Signed fractions of a second at nanosecond resolution of the span + * of time. Durations less than one second are represented with a 0 + * `seconds` field and a positive or negative `nanos` field. For durations + * of one second or more, a non-zero value for the `nanos` field must be + * of the same sign as the `seconds` field. Must be from -999,999,999 + * to +999,999,999 inclusive. + * + * Generated from protobuf field int32 nanos = 2; + */ + protected $nanos = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int|string $seconds + * Signed seconds of the span of time. Must be from -315,576,000,000 + * to +315,576,000,000 inclusive. Note: these bounds are computed from: + * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + * @type int $nanos + * Signed fractions of a second at nanosecond resolution of the span + * of time. Durations less than one second are represented with a 0 + * `seconds` field and a positive or negative `nanos` field. For durations + * of one second or more, a non-zero value for the `nanos` field must be + * of the same sign as the `seconds` field. Must be from -999,999,999 + * to +999,999,999 inclusive. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Duration::initOnce(); + parent::__construct($data); + } + + /** + * Signed seconds of the span of time. Must be from -315,576,000,000 + * to +315,576,000,000 inclusive. Note: these bounds are computed from: + * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + * + * Generated from protobuf field int64 seconds = 1; + * @return int|string + */ + public function getSeconds() + { + return $this->seconds; + } + + /** + * Signed seconds of the span of time. Must be from -315,576,000,000 + * to +315,576,000,000 inclusive. Note: these bounds are computed from: + * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + * + * Generated from protobuf field int64 seconds = 1; + * @param int|string $var + * @return $this + */ + public function setSeconds($var) + { + GPBUtil::checkInt64($var); + $this->seconds = $var; + + return $this; + } + + /** + * Signed fractions of a second at nanosecond resolution of the span + * of time. Durations less than one second are represented with a 0 + * `seconds` field and a positive or negative `nanos` field. For durations + * of one second or more, a non-zero value for the `nanos` field must be + * of the same sign as the `seconds` field. Must be from -999,999,999 + * to +999,999,999 inclusive. + * + * Generated from protobuf field int32 nanos = 2; + * @return int + */ + public function getNanos() + { + return $this->nanos; + } + + /** + * Signed fractions of a second at nanosecond resolution of the span + * of time. Durations less than one second are represented with a 0 + * `seconds` field and a positive or negative `nanos` field. For durations + * of one second or more, a non-zero value for the `nanos` field must be + * of the same sign as the `seconds` field. Must be from -999,999,999 + * to +999,999,999 inclusive. + * + * Generated from protobuf field int32 nanos = 2; + * @param int $var + * @return $this + */ + public function setNanos($var) + { + GPBUtil::checkInt32($var); + $this->nanos = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Enum.php b/php/src/Google/Protobuf/Enum.php new file mode 100644 index 0000000000000..2e0ac9987b6b8 --- /dev/null +++ b/php/src/Google/Protobuf/Enum.php @@ -0,0 +1,213 @@ +google.protobuf.Enum + */ +class Enum extends \Google\Protobuf\Internal\Message +{ + /** + * Enum type name. + * + * Generated from protobuf field string name = 1; + */ + protected $name = ''; + /** + * Enum value definitions. + * + * Generated from protobuf field repeated .google.protobuf.EnumValue enumvalue = 2; + */ + private $enumvalue; + /** + * Protocol buffer options. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 3; + */ + private $options; + /** + * The source context. + * + * Generated from protobuf field .google.protobuf.SourceContext source_context = 4; + */ + protected $source_context = null; + /** + * The source syntax. + * + * Generated from protobuf field .google.protobuf.Syntax syntax = 5; + */ + protected $syntax = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * Enum type name. + * @type \Google\Protobuf\EnumValue[]|\Google\Protobuf\Internal\RepeatedField $enumvalue + * Enum value definitions. + * @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options + * Protocol buffer options. + * @type \Google\Protobuf\SourceContext $source_context + * The source context. + * @type int $syntax + * The source syntax. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Type::initOnce(); + parent::__construct($data); + } + + /** + * Enum type name. + * + * Generated from protobuf field string name = 1; + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Enum type name. + * + * Generated from protobuf field string name = 1; + * @param string $var + * @return $this + */ + public function setName($var) + { + GPBUtil::checkString($var, True); + $this->name = $var; + + return $this; + } + + /** + * Enum value definitions. + * + * Generated from protobuf field repeated .google.protobuf.EnumValue enumvalue = 2; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getEnumvalue() + { + return $this->enumvalue; + } + + /** + * Enum value definitions. + * + * Generated from protobuf field repeated .google.protobuf.EnumValue enumvalue = 2; + * @param \Google\Protobuf\EnumValue[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setEnumvalue($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\EnumValue::class); + $this->enumvalue = $arr; + + return $this; + } + + /** + * Protocol buffer options. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 3; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getOptions() + { + return $this->options; + } + + /** + * Protocol buffer options. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 3; + * @param \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setOptions($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Option::class); + $this->options = $arr; + + return $this; + } + + /** + * The source context. + * + * Generated from protobuf field .google.protobuf.SourceContext source_context = 4; + * @return \Google\Protobuf\SourceContext|null + */ + public function getSourceContext() + { + return isset($this->source_context) ? $this->source_context : null; + } + + public function hasSourceContext() + { + return isset($this->source_context); + } + + public function clearSourceContext() + { + unset($this->source_context); + } + + /** + * The source context. + * + * Generated from protobuf field .google.protobuf.SourceContext source_context = 4; + * @param \Google\Protobuf\SourceContext $var + * @return $this + */ + public function setSourceContext($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\SourceContext::class); + $this->source_context = $var; + + return $this; + } + + /** + * The source syntax. + * + * Generated from protobuf field .google.protobuf.Syntax syntax = 5; + * @return int + */ + public function getSyntax() + { + return $this->syntax; + } + + /** + * The source syntax. + * + * Generated from protobuf field .google.protobuf.Syntax syntax = 5; + * @param int $var + * @return $this + */ + public function setSyntax($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Syntax::class); + $this->syntax = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/EnumValue.php b/php/src/Google/Protobuf/EnumValue.php new file mode 100644 index 0000000000000..905f4ad14b298 --- /dev/null +++ b/php/src/Google/Protobuf/EnumValue.php @@ -0,0 +1,135 @@ +google.protobuf.EnumValue + */ +class EnumValue extends \Google\Protobuf\Internal\Message +{ + /** + * Enum value name. + * + * Generated from protobuf field string name = 1; + */ + protected $name = ''; + /** + * Enum value number. + * + * Generated from protobuf field int32 number = 2; + */ + protected $number = 0; + /** + * Protocol buffer options. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 3; + */ + private $options; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * Enum value name. + * @type int $number + * Enum value number. + * @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options + * Protocol buffer options. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Type::initOnce(); + parent::__construct($data); + } + + /** + * Enum value name. + * + * Generated from protobuf field string name = 1; + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Enum value name. + * + * Generated from protobuf field string name = 1; + * @param string $var + * @return $this + */ + public function setName($var) + { + GPBUtil::checkString($var, True); + $this->name = $var; + + return $this; + } + + /** + * Enum value number. + * + * Generated from protobuf field int32 number = 2; + * @return int + */ + public function getNumber() + { + return $this->number; + } + + /** + * Enum value number. + * + * Generated from protobuf field int32 number = 2; + * @param int $var + * @return $this + */ + public function setNumber($var) + { + GPBUtil::checkInt32($var); + $this->number = $var; + + return $this; + } + + /** + * Protocol buffer options. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 3; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getOptions() + { + return $this->options; + } + + /** + * Protocol buffer options. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 3; + * @param \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setOptions($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Option::class); + $this->options = $arr; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Field.php b/php/src/Google/Protobuf/Field.php new file mode 100644 index 0000000000000..76a505ea567d8 --- /dev/null +++ b/php/src/Google/Protobuf/Field.php @@ -0,0 +1,381 @@ +google.protobuf.Field + */ +class Field extends \Google\Protobuf\Internal\Message +{ + /** + * The field type. + * + * Generated from protobuf field .google.protobuf.Field.Kind kind = 1; + */ + protected $kind = 0; + /** + * The field cardinality. + * + * Generated from protobuf field .google.protobuf.Field.Cardinality cardinality = 2; + */ + protected $cardinality = 0; + /** + * The field number. + * + * Generated from protobuf field int32 number = 3; + */ + protected $number = 0; + /** + * The field name. + * + * Generated from protobuf field string name = 4; + */ + protected $name = ''; + /** + * The field type URL, without the scheme, for message or enumeration + * types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. + * + * Generated from protobuf field string type_url = 6; + */ + protected $type_url = ''; + /** + * The index of the field type in `Type.oneofs`, for message or enumeration + * types. The first type has index 1; zero means the type is not in the list. + * + * Generated from protobuf field int32 oneof_index = 7; + */ + protected $oneof_index = 0; + /** + * Whether to use alternative packed wire representation. + * + * Generated from protobuf field bool packed = 8; + */ + protected $packed = false; + /** + * The protocol buffer options. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 9; + */ + private $options; + /** + * The field JSON name. + * + * Generated from protobuf field string json_name = 10; + */ + protected $json_name = ''; + /** + * The string value of the default value of this field. Proto2 syntax only. + * + * Generated from protobuf field string default_value = 11; + */ + protected $default_value = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $kind + * The field type. + * @type int $cardinality + * The field cardinality. + * @type int $number + * The field number. + * @type string $name + * The field name. + * @type string $type_url + * The field type URL, without the scheme, for message or enumeration + * types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. + * @type int $oneof_index + * The index of the field type in `Type.oneofs`, for message or enumeration + * types. The first type has index 1; zero means the type is not in the list. + * @type bool $packed + * Whether to use alternative packed wire representation. + * @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options + * The protocol buffer options. + * @type string $json_name + * The field JSON name. + * @type string $default_value + * The string value of the default value of this field. Proto2 syntax only. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Type::initOnce(); + parent::__construct($data); + } + + /** + * The field type. + * + * Generated from protobuf field .google.protobuf.Field.Kind kind = 1; + * @return int + */ + public function getKind() + { + return $this->kind; + } + + /** + * The field type. + * + * Generated from protobuf field .google.protobuf.Field.Kind kind = 1; + * @param int $var + * @return $this + */ + public function setKind($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Field\Kind::class); + $this->kind = $var; + + return $this; + } + + /** + * The field cardinality. + * + * Generated from protobuf field .google.protobuf.Field.Cardinality cardinality = 2; + * @return int + */ + public function getCardinality() + { + return $this->cardinality; + } + + /** + * The field cardinality. + * + * Generated from protobuf field .google.protobuf.Field.Cardinality cardinality = 2; + * @param int $var + * @return $this + */ + public function setCardinality($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Field\Cardinality::class); + $this->cardinality = $var; + + return $this; + } + + /** + * The field number. + * + * Generated from protobuf field int32 number = 3; + * @return int + */ + public function getNumber() + { + return $this->number; + } + + /** + * The field number. + * + * Generated from protobuf field int32 number = 3; + * @param int $var + * @return $this + */ + public function setNumber($var) + { + GPBUtil::checkInt32($var); + $this->number = $var; + + return $this; + } + + /** + * The field name. + * + * Generated from protobuf field string name = 4; + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * The field name. + * + * Generated from protobuf field string name = 4; + * @param string $var + * @return $this + */ + public function setName($var) + { + GPBUtil::checkString($var, True); + $this->name = $var; + + return $this; + } + + /** + * The field type URL, without the scheme, for message or enumeration + * types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. + * + * Generated from protobuf field string type_url = 6; + * @return string + */ + public function getTypeUrl() + { + return $this->type_url; + } + + /** + * The field type URL, without the scheme, for message or enumeration + * types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. + * + * Generated from protobuf field string type_url = 6; + * @param string $var + * @return $this + */ + public function setTypeUrl($var) + { + GPBUtil::checkString($var, True); + $this->type_url = $var; + + return $this; + } + + /** + * The index of the field type in `Type.oneofs`, for message or enumeration + * types. The first type has index 1; zero means the type is not in the list. + * + * Generated from protobuf field int32 oneof_index = 7; + * @return int + */ + public function getOneofIndex() + { + return $this->oneof_index; + } + + /** + * The index of the field type in `Type.oneofs`, for message or enumeration + * types. The first type has index 1; zero means the type is not in the list. + * + * Generated from protobuf field int32 oneof_index = 7; + * @param int $var + * @return $this + */ + public function setOneofIndex($var) + { + GPBUtil::checkInt32($var); + $this->oneof_index = $var; + + return $this; + } + + /** + * Whether to use alternative packed wire representation. + * + * Generated from protobuf field bool packed = 8; + * @return bool + */ + public function getPacked() + { + return $this->packed; + } + + /** + * Whether to use alternative packed wire representation. + * + * Generated from protobuf field bool packed = 8; + * @param bool $var + * @return $this + */ + public function setPacked($var) + { + GPBUtil::checkBool($var); + $this->packed = $var; + + return $this; + } + + /** + * The protocol buffer options. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 9; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getOptions() + { + return $this->options; + } + + /** + * The protocol buffer options. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 9; + * @param \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setOptions($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Option::class); + $this->options = $arr; + + return $this; + } + + /** + * The field JSON name. + * + * Generated from protobuf field string json_name = 10; + * @return string + */ + public function getJsonName() + { + return $this->json_name; + } + + /** + * The field JSON name. + * + * Generated from protobuf field string json_name = 10; + * @param string $var + * @return $this + */ + public function setJsonName($var) + { + GPBUtil::checkString($var, True); + $this->json_name = $var; + + return $this; + } + + /** + * The string value of the default value of this field. Proto2 syntax only. + * + * Generated from protobuf field string default_value = 11; + * @return string + */ + public function getDefaultValue() + { + return $this->default_value; + } + + /** + * The string value of the default value of this field. Proto2 syntax only. + * + * Generated from protobuf field string default_value = 11; + * @param string $var + * @return $this + */ + public function setDefaultValue($var) + { + GPBUtil::checkString($var, True); + $this->default_value = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Field/Cardinality.php b/php/src/Google/Protobuf/Field/Cardinality.php new file mode 100644 index 0000000000000..a42219957696e --- /dev/null +++ b/php/src/Google/Protobuf/Field/Cardinality.php @@ -0,0 +1,71 @@ +google.protobuf.Field.Cardinality + */ +class Cardinality +{ + /** + * For fields with unknown cardinality. + * + * Generated from protobuf enum CARDINALITY_UNKNOWN = 0; + */ + const CARDINALITY_UNKNOWN = 0; + /** + * For optional fields. + * + * Generated from protobuf enum CARDINALITY_OPTIONAL = 1; + */ + const CARDINALITY_OPTIONAL = 1; + /** + * For required fields. Proto2 syntax only. + * + * Generated from protobuf enum CARDINALITY_REQUIRED = 2; + */ + const CARDINALITY_REQUIRED = 2; + /** + * For repeated fields. + * + * Generated from protobuf enum CARDINALITY_REPEATED = 3; + */ + const CARDINALITY_REPEATED = 3; + + private static $valueToName = [ + self::CARDINALITY_UNKNOWN => 'CARDINALITY_UNKNOWN', + self::CARDINALITY_OPTIONAL => 'CARDINALITY_OPTIONAL', + self::CARDINALITY_REQUIRED => 'CARDINALITY_REQUIRED', + self::CARDINALITY_REPEATED => 'CARDINALITY_REPEATED', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(Cardinality::class, \Google\Protobuf\Field_Cardinality::class); + diff --git a/php/src/Google/Protobuf/Field/Kind.php b/php/src/Google/Protobuf/Field/Kind.php new file mode 100644 index 0000000000000..2d8dd77c1cb46 --- /dev/null +++ b/php/src/Google/Protobuf/Field/Kind.php @@ -0,0 +1,176 @@ +google.protobuf.Field.Kind + */ +class Kind +{ + /** + * Field type unknown. + * + * Generated from protobuf enum TYPE_UNKNOWN = 0; + */ + const TYPE_UNKNOWN = 0; + /** + * Field type double. + * + * Generated from protobuf enum TYPE_DOUBLE = 1; + */ + const TYPE_DOUBLE = 1; + /** + * Field type float. + * + * Generated from protobuf enum TYPE_FLOAT = 2; + */ + const TYPE_FLOAT = 2; + /** + * Field type int64. + * + * Generated from protobuf enum TYPE_INT64 = 3; + */ + const TYPE_INT64 = 3; + /** + * Field type uint64. + * + * Generated from protobuf enum TYPE_UINT64 = 4; + */ + const TYPE_UINT64 = 4; + /** + * Field type int32. + * + * Generated from protobuf enum TYPE_INT32 = 5; + */ + const TYPE_INT32 = 5; + /** + * Field type fixed64. + * + * Generated from protobuf enum TYPE_FIXED64 = 6; + */ + const TYPE_FIXED64 = 6; + /** + * Field type fixed32. + * + * Generated from protobuf enum TYPE_FIXED32 = 7; + */ + const TYPE_FIXED32 = 7; + /** + * Field type bool. + * + * Generated from protobuf enum TYPE_BOOL = 8; + */ + const TYPE_BOOL = 8; + /** + * Field type string. + * + * Generated from protobuf enum TYPE_STRING = 9; + */ + const TYPE_STRING = 9; + /** + * Field type group. Proto2 syntax only, and deprecated. + * + * Generated from protobuf enum TYPE_GROUP = 10; + */ + const TYPE_GROUP = 10; + /** + * Field type message. + * + * Generated from protobuf enum TYPE_MESSAGE = 11; + */ + const TYPE_MESSAGE = 11; + /** + * Field type bytes. + * + * Generated from protobuf enum TYPE_BYTES = 12; + */ + const TYPE_BYTES = 12; + /** + * Field type uint32. + * + * Generated from protobuf enum TYPE_UINT32 = 13; + */ + const TYPE_UINT32 = 13; + /** + * Field type enum. + * + * Generated from protobuf enum TYPE_ENUM = 14; + */ + const TYPE_ENUM = 14; + /** + * Field type sfixed32. + * + * Generated from protobuf enum TYPE_SFIXED32 = 15; + */ + const TYPE_SFIXED32 = 15; + /** + * Field type sfixed64. + * + * Generated from protobuf enum TYPE_SFIXED64 = 16; + */ + const TYPE_SFIXED64 = 16; + /** + * Field type sint32. + * + * Generated from protobuf enum TYPE_SINT32 = 17; + */ + const TYPE_SINT32 = 17; + /** + * Field type sint64. + * + * Generated from protobuf enum TYPE_SINT64 = 18; + */ + const TYPE_SINT64 = 18; + + private static $valueToName = [ + self::TYPE_UNKNOWN => 'TYPE_UNKNOWN', + self::TYPE_DOUBLE => 'TYPE_DOUBLE', + self::TYPE_FLOAT => 'TYPE_FLOAT', + self::TYPE_INT64 => 'TYPE_INT64', + self::TYPE_UINT64 => 'TYPE_UINT64', + self::TYPE_INT32 => 'TYPE_INT32', + self::TYPE_FIXED64 => 'TYPE_FIXED64', + self::TYPE_FIXED32 => 'TYPE_FIXED32', + self::TYPE_BOOL => 'TYPE_BOOL', + self::TYPE_STRING => 'TYPE_STRING', + self::TYPE_GROUP => 'TYPE_GROUP', + self::TYPE_MESSAGE => 'TYPE_MESSAGE', + self::TYPE_BYTES => 'TYPE_BYTES', + self::TYPE_UINT32 => 'TYPE_UINT32', + self::TYPE_ENUM => 'TYPE_ENUM', + self::TYPE_SFIXED32 => 'TYPE_SFIXED32', + self::TYPE_SFIXED64 => 'TYPE_SFIXED64', + self::TYPE_SINT32 => 'TYPE_SINT32', + self::TYPE_SINT64 => 'TYPE_SINT64', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(Kind::class, \Google\Protobuf\Field_Kind::class); + diff --git a/php/src/Google/Protobuf/FieldDescriptor.php b/php/src/Google/Protobuf/FieldDescriptor.php index ac9271f98b250..6d08cea9da975 100644 --- a/php/src/Google/Protobuf/FieldDescriptor.php +++ b/php/src/Google/Protobuf/FieldDescriptor.php @@ -114,4 +114,12 @@ public function isMap() { return $this->internal_desc->isMap(); } + + /** + * @return boolean + */ + public function hasOptionalKeyword() + { + return $this->internal_desc->hasOptionalKeyword(); + } } diff --git a/php/src/Google/Protobuf/FieldMask.php b/php/src/Google/Protobuf/FieldMask.php new file mode 100644 index 0000000000000..0b9659d38f5cb --- /dev/null +++ b/php/src/Google/Protobuf/FieldMask.php @@ -0,0 +1,217 @@ +google.protobuf.FieldMask + */ +class FieldMask extends \Google\Protobuf\Internal\Message +{ + /** + * The set of field mask paths. + * + * Generated from protobuf field repeated string paths = 1; + */ + private $paths; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string[]|\Google\Protobuf\Internal\RepeatedField $paths + * The set of field mask paths. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\FieldMask::initOnce(); + parent::__construct($data); + } + + /** + * The set of field mask paths. + * + * Generated from protobuf field repeated string paths = 1; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getPaths() + { + return $this->paths; + } + + /** + * The set of field mask paths. + * + * Generated from protobuf field repeated string paths = 1; + * @param string[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setPaths($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING); + $this->paths = $arr; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Field_Cardinality.php b/php/src/Google/Protobuf/Field_Cardinality.php new file mode 100644 index 0000000000000..dff8f8931b5ae --- /dev/null +++ b/php/src/Google/Protobuf/Field_Cardinality.php @@ -0,0 +1,16 @@ +google.protobuf.FloatValue + */ +class FloatValue extends \Google\Protobuf\Internal\Message +{ + /** + * The float value. + * + * Generated from protobuf field float value = 1; + */ + protected $value = 0.0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type float $value + * The float value. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Wrappers::initOnce(); + parent::__construct($data); + } + + /** + * The float value. + * + * Generated from protobuf field float value = 1; + * @return float + */ + public function getValue() + { + return $this->value; + } + + /** + * The float value. + * + * Generated from protobuf field float value = 1; + * @param float $var + * @return $this + */ + public function setValue($var) + { + GPBUtil::checkFloat($var); + $this->value = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/GPBEmpty.php b/php/src/Google/Protobuf/GPBEmpty.php new file mode 100644 index 0000000000000..2de9c3bc06529 --- /dev/null +++ b/php/src/Google/Protobuf/GPBEmpty.php @@ -0,0 +1,39 @@ +google.protobuf.Empty + */ +class GPBEmpty extends \Google\Protobuf\Internal\Message +{ + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\GPBEmpty::initOnce(); + parent::__construct($data); + } + +} + diff --git a/php/src/Google/Protobuf/Int32Value.php b/php/src/Google/Protobuf/Int32Value.php new file mode 100644 index 0000000000000..cfd73cdc90f50 --- /dev/null +++ b/php/src/Google/Protobuf/Int32Value.php @@ -0,0 +1,68 @@ +google.protobuf.Int32Value + */ +class Int32Value extends \Google\Protobuf\Internal\Message +{ + /** + * The int32 value. + * + * Generated from protobuf field int32 value = 1; + */ + protected $value = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $value + * The int32 value. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Wrappers::initOnce(); + parent::__construct($data); + } + + /** + * The int32 value. + * + * Generated from protobuf field int32 value = 1; + * @return int + */ + public function getValue() + { + return $this->value; + } + + /** + * The int32 value. + * + * Generated from protobuf field int32 value = 1; + * @param int $var + * @return $this + */ + public function setValue($var) + { + GPBUtil::checkInt32($var); + $this->value = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Int64Value.php b/php/src/Google/Protobuf/Int64Value.php new file mode 100644 index 0000000000000..143474fcd7cff --- /dev/null +++ b/php/src/Google/Protobuf/Int64Value.php @@ -0,0 +1,68 @@ +google.protobuf.Int64Value + */ +class Int64Value extends \Google\Protobuf\Internal\Message +{ + /** + * The int64 value. + * + * Generated from protobuf field int64 value = 1; + */ + protected $value = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int|string $value + * The int64 value. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Wrappers::initOnce(); + parent::__construct($data); + } + + /** + * The int64 value. + * + * Generated from protobuf field int64 value = 1; + * @return int|string + */ + public function getValue() + { + return $this->value; + } + + /** + * The int64 value. + * + * Generated from protobuf field int64 value = 1; + * @param int|string $var + * @return $this + */ + public function setValue($var) + { + GPBUtil::checkInt64($var); + $this->value = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Internal/AnyBase.php b/php/src/Google/Protobuf/Internal/AnyBase.php new file mode 100644 index 0000000000000..cba922d475474 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/AnyBase.php @@ -0,0 +1,86 @@ +type_url, 0, $url_prifix_len) != + GPBUtil::TYPE_URL_PREFIX) { + throw new \Exception( + "Type url needs to be type.googleapis.com/fully-qulified"); + } + $fully_qualifed_name = + substr($this->type_url, $url_prifix_len); + + // Create message according to fully qualified name. + $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); + $desc = $pool->getDescriptorByProtoName($fully_qualifed_name); + if (is_null($desc)) { + throw new \Exception("Class ".$fully_qualifed_name + ." hasn't been added to descriptor pool"); + } + $klass = $desc->getClass(); + $msg = new $klass(); + + // Merge data into message. + $msg->mergeFromString($this->value); + return $msg; + } + + /** + * The type_url will be created according to the given message’s type and + * the value is encoded data from the given message.. + * @param message: A proto message. + */ + public function pack($msg) + { + if (!$msg instanceof Message) { + trigger_error("Given parameter is not a message instance.", + E_USER_ERROR); + return; + } + + // Set value using serialized message. + $this->value = $msg->serializeToString(); + + // Set type url. + $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); + $desc = $pool->getDescriptorByClassName(get_class($msg)); + $fully_qualifed_name = $desc->getFullName(); + $this->type_url = GPBUtil::TYPE_URL_PREFIX . $fully_qualifed_name; + } + + /** + * This method returns whether the type_url in any_message is corresponded + * to the given class. + * @param klass: The fully qualified PHP class name of a proto message type. + */ + public function is($klass) + { + $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); + $desc = $pool->getDescriptorByClassName($klass); + $fully_qualifed_name = $desc->getFullName(); + $type_url = GPBUtil::TYPE_URL_PREFIX . $fully_qualifed_name; + return $this->type_url === $type_url; + } +} diff --git a/php/src/Google/Protobuf/Internal/CodedInputStream.php b/php/src/Google/Protobuf/Internal/CodedInputStream.php index 6131d5d1f9db0..2ed2dfde20663 100644 --- a/php/src/Google/Protobuf/Internal/CodedInputStream.php +++ b/php/src/Google/Protobuf/Internal/CodedInputStream.php @@ -78,13 +78,18 @@ public function bufferSize() return $this->buffer_end - $this->current; } - private function current() + public function current() { return $this->total_bytes_read - ($this->buffer_end - $this->current + $this->buffer_size_after_limit); } + public function substr($start, $end) + { + return substr($this->buffer, $start, $end - $start); + } + private function recomputeBufferLimits() { $this->buffer_end += $this->buffer_size_after_limit; @@ -215,7 +220,7 @@ public function readVarintSizeAsInt(&$var) } /** - * Read 32-bit unsiged integer to $var. If the buffer has less than 4 bytes, + * Read 32-bit unsigned integer to $var. If the buffer has less than 4 bytes, * return false. Advance buffer with consumed bytes. * @param $var. */ @@ -231,7 +236,7 @@ public function readLittleEndian32(&$var) } /** - * Read 64-bit unsiged integer to $var. If the buffer has less than 8 bytes, + * Read 64-bit unsigned integer to $var. If the buffer has less than 8 bytes, * return false. Advance buffer with consumed bytes. * @param $var. */ @@ -278,7 +283,7 @@ public function readTag() } $result = 0; - // The larget tag is 2^29 - 1, which can be represented by int32. + // The largest tag is 2^29 - 1, which can be represented by int32. $success = $this->readVarint32($result); if ($success) { return $result; @@ -294,8 +299,12 @@ public function readRaw($size, &$buffer) return false; } - $buffer = substr($this->buffer, $this->current, $size); - $this->advance($size); + if ($size === 0) { + $buffer = ""; + } else { + $buffer = substr($this->buffer, $this->current, $size); + $this->advance($size); + } return true; } @@ -312,7 +321,7 @@ public function readRaw($size, &$buffer) * passed unchanged to the corresponding call to popLimit(). * * @param integer $byte_limit - * @throws Exception Fail to push limit. + * @throws \Exception Fail to push limit. */ public function pushLimit($byte_limit) { diff --git a/php/src/Google/Protobuf/Internal/CodedOutputStream.php b/php/src/Google/Protobuf/Internal/CodedOutputStream.php index 4525d8dd299d0..f75e9c6626fa5 100644 --- a/php/src/Google/Protobuf/Internal/CodedOutputStream.php +++ b/php/src/Google/Protobuf/Internal/CodedOutputStream.php @@ -101,7 +101,7 @@ public function writeRaw($data, $size) return true; } - private static function writeVarintToArray($value, &$buffer, $trim = false) + public static function writeVarintToArray($value, &$buffer, $trim = false) { $current = 0; diff --git a/php/src/Google/Protobuf/Internal/Descriptor.php b/php/src/Google/Protobuf/Internal/Descriptor.php index ee3a8bdec5ed6..a7f80d534e01e 100644 --- a/php/src/Google/Protobuf/Internal/Descriptor.php +++ b/php/src/Google/Protobuf/Internal/Descriptor.php @@ -44,6 +44,7 @@ class Descriptor private $nested_type = []; private $enum_type = []; private $klass; + private $legacy_klass; private $options; private $oneof_decl = []; @@ -151,6 +152,16 @@ public function getClass() return $this->klass; } + public function setLegacyClass($klass) + { + $this->legacy_klass = $klass; + } + + public function getLegacyClass() + { + return $this->legacy_klass; + } + public function setOptions($options) { $this->options = $options; @@ -167,6 +178,7 @@ public static function buildFromProto($proto, $file_proto, $containing) $message_name_without_package = ""; $classname = ""; + $legacy_classname = ""; $fullname = ""; GPBUtil::getFullClassName( $proto, @@ -174,9 +186,11 @@ public static function buildFromProto($proto, $file_proto, $containing) $file_proto, $message_name_without_package, $classname, + $legacy_classname, $fullname); $desc->setFullName($fullname); $desc->setClass($classname); + $desc->setLegacyClass($legacy_classname); $desc->setOptions($proto->getOptions()); foreach ($proto->getField() as $field_proto) { diff --git a/php/src/Google/Protobuf/Internal/DescriptorPool.php b/php/src/Google/Protobuf/Internal/DescriptorPool.php index 65d1a884eb365..2880cee641b2a 100644 --- a/php/src/Google/Protobuf/Internal/DescriptorPool.php +++ b/php/src/Google/Protobuf/Internal/DescriptorPool.php @@ -55,26 +55,29 @@ public static function getGeneratedPool() return self::$pool; } - public function internalAddGeneratedFile($data) + public function internalAddGeneratedFile($data, $use_nested = false) { $files = new FileDescriptorSet(); $files->mergeFromString($data); - $file = FileDescriptor::buildFromProto($files->getFile()[0]); - foreach ($file->getMessageType() as $desc) { - $this->addDescriptor($desc); - } - unset($desc); + foreach($files->getFile() as $file_proto) { + $file = FileDescriptor::buildFromProto($file_proto); - foreach ($file->getEnumType() as $desc) { - $this->addEnumDescriptor($desc); - } - unset($desc); + foreach ($file->getMessageType() as $desc) { + $this->addDescriptor($desc); + } + unset($desc); - foreach ($file->getMessageType() as $desc) { - $this->crossLink($desc); + foreach ($file->getEnumType() as $desc) { + $this->addEnumDescriptor($desc); + } + unset($desc); + + foreach ($file->getMessageType() as $desc) { + $this->crossLink($desc); + } + unset($desc); } - unset($desc); } public function addMessage($name, $klass) @@ -92,6 +95,7 @@ public function addDescriptor($descriptor) $this->proto_to_class[$descriptor->getFullName()] = $descriptor->getClass(); $this->class_to_desc[$descriptor->getClass()] = $descriptor; + $this->class_to_desc[$descriptor->getLegacyClass()] = $descriptor; foreach ($descriptor->getNestedType() as $nested_type) { $this->addDescriptor($nested_type); } @@ -105,22 +109,35 @@ public function addEnumDescriptor($descriptor) $this->proto_to_class[$descriptor->getFullName()] = $descriptor->getClass(); $this->class_to_enum_desc[$descriptor->getClass()] = $descriptor; + $this->class_to_enum_desc[$descriptor->getLegacyClass()] = $descriptor; } public function getDescriptorByClassName($klass) { - return $this->class_to_desc[$klass]; + if (isset($this->class_to_desc[$klass])) { + return $this->class_to_desc[$klass]; + } else { + return null; + } } public function getEnumDescriptorByClassName($klass) { - return $this->class_to_enum_desc[$klass]; + if (isset($this->class_to_enum_desc[$klass])) { + return $this->class_to_enum_desc[$klass]; + } else { + return null; + } } public function getDescriptorByProtoName($proto) { - $klass = $this->proto_to_class[$proto]; - return $this->class_to_desc[$klass]; + if (isset($this->proto_to_class[$proto])) { + $klass = $this->proto_to_class[$proto]; + return $this->class_to_desc[$klass]; + } else { + return null; + } } public function getEnumDescriptorByProtoName($proto) @@ -135,11 +152,22 @@ private function crossLink(Descriptor $desc) switch ($field->getType()) { case GPBType::MESSAGE: $proto = $field->getMessageType(); - $field->setMessageType( - $this->getDescriptorByProtoName($proto)); + if ($proto[0] == '.') { + $proto = substr($proto, 1); + } + $subdesc = $this->getDescriptorByProtoName($proto); + if (is_null($subdesc)) { + trigger_error( + 'proto not added: ' . $proto + . " for " . $desc->getFullName(), E_ERROR); + } + $field->setMessageType($subdesc); break; case GPBType::ENUM: $proto = $field->getEnumType(); + if ($proto[0] == '.') { + $proto = substr($proto, 1); + } $field->setEnumType( $this->getEnumDescriptorByProtoName($proto)); break; diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto.php b/php/src/Google/Protobuf/Internal/DescriptorProto.php index 1d6959b71db1d..ff308e7eeb146 100644 --- a/php/src/Google/Protobuf/Internal/DescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/DescriptorProto.php @@ -20,48 +20,39 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field optional string name = 1; */ - private $name = ''; - private $has_name = false; + protected $name = null; /** * Generated from protobuf field repeated .google.protobuf.FieldDescriptorProto field = 2; */ private $field; - private $has_field = false; /** * Generated from protobuf field repeated .google.protobuf.FieldDescriptorProto extension = 6; */ private $extension; - private $has_extension = false; /** * Generated from protobuf field repeated .google.protobuf.DescriptorProto nested_type = 3; */ private $nested_type; - private $has_nested_type = false; /** * Generated from protobuf field repeated .google.protobuf.EnumDescriptorProto enum_type = 4; */ private $enum_type; - private $has_enum_type = false; /** * Generated from protobuf field repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; */ private $extension_range; - private $has_extension_range = false; /** * Generated from protobuf field repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; */ private $oneof_decl; - private $has_oneof_decl = false; /** * Generated from protobuf field optional .google.protobuf.MessageOptions options = 7; */ - private $options = null; - private $has_options = false; + protected $options = null; /** * Generated from protobuf field repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; */ private $reserved_range; - private $has_reserved_range = false; /** * Reserved field names, which may not be used by fields in the same message. * A given name may only be reserved once. @@ -69,11 +60,30 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated string reserved_name = 10; */ private $reserved_name; - private $has_reserved_name = false; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * @type \Google\Protobuf\Internal\FieldDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $field + * @type \Google\Protobuf\Internal\FieldDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $extension + * @type \Google\Protobuf\Internal\DescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $nested_type + * @type \Google\Protobuf\Internal\EnumDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $enum_type + * @type \Google\Protobuf\Internal\DescriptorProto\ExtensionRange[]|\Google\Protobuf\Internal\RepeatedField $extension_range + * @type \Google\Protobuf\Internal\OneofDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $oneof_decl + * @type \Google\Protobuf\Internal\MessageOptions $options + * @type \Google\Protobuf\Internal\DescriptorProto\ReservedRange[]|\Google\Protobuf\Internal\RepeatedField $reserved_range + * @type string[]|\Google\Protobuf\Internal\RepeatedField $reserved_name + * Reserved field names, which may not be used by fields in the same message. + * A given name may only be reserved once. + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -82,7 +92,17 @@ public function __construct() { */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -94,16 +114,10 @@ public function setName($var) { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * Generated from protobuf field repeated .google.protobuf.FieldDescriptorProto field = 2; * @return \Google\Protobuf\Internal\RepeatedField @@ -122,16 +136,10 @@ public function setField($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class); $this->field = $arr; - $this->has_field = true; return $this; } - public function hasField() - { - return $this->has_field; - } - /** * Generated from protobuf field repeated .google.protobuf.FieldDescriptorProto extension = 6; * @return \Google\Protobuf\Internal\RepeatedField @@ -150,16 +158,10 @@ public function setExtension($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class); $this->extension = $arr; - $this->has_extension = true; return $this; } - public function hasExtension() - { - return $this->has_extension; - } - /** * Generated from protobuf field repeated .google.protobuf.DescriptorProto nested_type = 3; * @return \Google\Protobuf\Internal\RepeatedField @@ -178,16 +180,10 @@ public function setNestedType($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto::class); $this->nested_type = $arr; - $this->has_nested_type = true; return $this; } - public function hasNestedType() - { - return $this->has_nested_type; - } - /** * Generated from protobuf field repeated .google.protobuf.EnumDescriptorProto enum_type = 4; * @return \Google\Protobuf\Internal\RepeatedField @@ -206,16 +202,10 @@ public function setEnumType($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto::class); $this->enum_type = $arr; - $this->has_enum_type = true; return $this; } - public function hasEnumType() - { - return $this->has_enum_type; - } - /** * Generated from protobuf field repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; * @return \Google\Protobuf\Internal\RepeatedField @@ -227,23 +217,17 @@ public function getExtensionRange() /** * Generated from protobuf field repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; - * @param \Google\Protobuf\Internal\DescriptorProto_ExtensionRange[]|\Google\Protobuf\Internal\RepeatedField $var + * @param \Google\Protobuf\Internal\DescriptorProto\ExtensionRange[]|\Google\Protobuf\Internal\RepeatedField $var * @return $this */ public function setExtensionRange($var) { - $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto_ExtensionRange::class); + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto\ExtensionRange::class); $this->extension_range = $arr; - $this->has_extension_range = true; return $this; } - public function hasExtensionRange() - { - return $this->has_extension_range; - } - /** * Generated from protobuf field repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; * @return \Google\Protobuf\Internal\RepeatedField @@ -262,23 +246,27 @@ public function setOneofDecl($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\OneofDescriptorProto::class); $this->oneof_decl = $arr; - $this->has_oneof_decl = true; return $this; } - public function hasOneofDecl() - { - return $this->has_oneof_decl; - } - /** * Generated from protobuf field optional .google.protobuf.MessageOptions options = 7; - * @return \Google\Protobuf\Internal\MessageOptions + * @return \Google\Protobuf\Internal\MessageOptions|null */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -290,16 +278,10 @@ public function setOptions($var) { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\MessageOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - /** * Generated from protobuf field repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; * @return \Google\Protobuf\Internal\RepeatedField @@ -311,23 +293,17 @@ public function getReservedRange() /** * Generated from protobuf field repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; - * @param \Google\Protobuf\Internal\DescriptorProto_ReservedRange[]|\Google\Protobuf\Internal\RepeatedField $var + * @param \Google\Protobuf\Internal\DescriptorProto\ReservedRange[]|\Google\Protobuf\Internal\RepeatedField $var * @return $this */ public function setReservedRange($var) { - $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto_ReservedRange::class); + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto\ReservedRange::class); $this->reserved_range = $arr; - $this->has_reserved_range = true; return $this; } - public function hasReservedRange() - { - return $this->has_reserved_range; - } - /** * Reserved field names, which may not be used by fields in the same message. * A given name may only be reserved once. @@ -352,15 +328,9 @@ public function setReservedName($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING); $this->reserved_name = $arr; - $this->has_reserved_name = true; return $this; } - public function hasReservedName() - { - return $this->has_reserved_name; - } - } diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php new file mode 100644 index 0000000000000..bbe4a6a84f9f8 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php @@ -0,0 +1,161 @@ +google.protobuf.DescriptorProto.ExtensionRange + */ +class ExtensionRange extends \Google\Protobuf\Internal\Message +{ + /** + * Inclusive. + * + * Generated from protobuf field optional int32 start = 1; + */ + protected $start = null; + /** + * Exclusive. + * + * Generated from protobuf field optional int32 end = 2; + */ + protected $end = null; + /** + * Generated from protobuf field optional .google.protobuf.ExtensionRangeOptions options = 3; + */ + protected $options = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $start + * Inclusive. + * @type int $end + * Exclusive. + * @type \Google\Protobuf\Internal\ExtensionRangeOptions $options + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); + parent::__construct($data); + } + + /** + * Inclusive. + * + * Generated from protobuf field optional int32 start = 1; + * @return int + */ + public function getStart() + { + return isset($this->start) ? $this->start : 0; + } + + public function hasStart() + { + return isset($this->start); + } + + public function clearStart() + { + unset($this->start); + } + + /** + * Inclusive. + * + * Generated from protobuf field optional int32 start = 1; + * @param int $var + * @return $this + */ + public function setStart($var) + { + GPBUtil::checkInt32($var); + $this->start = $var; + + return $this; + } + + /** + * Exclusive. + * + * Generated from protobuf field optional int32 end = 2; + * @return int + */ + public function getEnd() + { + return isset($this->end) ? $this->end : 0; + } + + public function hasEnd() + { + return isset($this->end); + } + + public function clearEnd() + { + unset($this->end); + } + + /** + * Exclusive. + * + * Generated from protobuf field optional int32 end = 2; + * @param int $var + * @return $this + */ + public function setEnd($var) + { + GPBUtil::checkInt32($var); + $this->end = $var; + + return $this; + } + + /** + * Generated from protobuf field optional .google.protobuf.ExtensionRangeOptions options = 3; + * @return \Google\Protobuf\Internal\ExtensionRangeOptions|null + */ + public function getOptions() + { + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); + } + + /** + * Generated from protobuf field optional .google.protobuf.ExtensionRangeOptions options = 3; + * @param \Google\Protobuf\Internal\ExtensionRangeOptions $var + * @return $this + */ + public function setOptions($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Internal\ExtensionRangeOptions::class); + $this->options = $var; + + return $this; + } + +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(ExtensionRange::class, \Google\Protobuf\Internal\DescriptorProto_ExtensionRange::class); + diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php new file mode 100644 index 0000000000000..f099cc345abe0 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php @@ -0,0 +1,128 @@ +google.protobuf.DescriptorProto.ReservedRange + */ +class ReservedRange extends \Google\Protobuf\Internal\Message +{ + /** + * Inclusive. + * + * Generated from protobuf field optional int32 start = 1; + */ + protected $start = null; + /** + * Exclusive. + * + * Generated from protobuf field optional int32 end = 2; + */ + protected $end = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $start + * Inclusive. + * @type int $end + * Exclusive. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); + parent::__construct($data); + } + + /** + * Inclusive. + * + * Generated from protobuf field optional int32 start = 1; + * @return int + */ + public function getStart() + { + return isset($this->start) ? $this->start : 0; + } + + public function hasStart() + { + return isset($this->start); + } + + public function clearStart() + { + unset($this->start); + } + + /** + * Inclusive. + * + * Generated from protobuf field optional int32 start = 1; + * @param int $var + * @return $this + */ + public function setStart($var) + { + GPBUtil::checkInt32($var); + $this->start = $var; + + return $this; + } + + /** + * Exclusive. + * + * Generated from protobuf field optional int32 end = 2; + * @return int + */ + public function getEnd() + { + return isset($this->end) ? $this->end : 0; + } + + public function hasEnd() + { + return isset($this->end); + } + + public function clearEnd() + { + unset($this->end); + } + + /** + * Exclusive. + * + * Generated from protobuf field optional int32 end = 2; + * @param int $var + * @return $this + */ + public function setEnd($var) + { + GPBUtil::checkInt32($var); + $this->end = $var; + + return $this; + } + +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(ReservedRange::class, \Google\Protobuf\Internal\DescriptorProto_ReservedRange::class); + diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php index 1d455995775f0..c928fbe5b1d04 100644 --- a/php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php +++ b/php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php @@ -4,121 +4,13 @@ namespace Google\Protobuf\Internal; -use Google\Protobuf\Internal\GPBType; -use Google\Protobuf\Internal\GPBWire; -use Google\Protobuf\Internal\RepeatedField; -use Google\Protobuf\Internal\InputStream; -use Google\Protobuf\Internal\GPBUtil; - -/** - * Generated from protobuf message google.protobuf.DescriptorProto.ExtensionRange - */ -class DescriptorProto_ExtensionRange extends \Google\Protobuf\Internal\Message -{ - /** - * Generated from protobuf field optional int32 start = 1; - */ - private $start = 0; - private $has_start = false; - /** - * Generated from protobuf field optional int32 end = 2; - */ - private $end = 0; - private $has_end = false; - /** - * Generated from protobuf field optional .google.protobuf.ExtensionRangeOptions options = 3; - */ - private $options = null; - private $has_options = false; - - public function __construct() { - \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); - } - - /** - * Generated from protobuf field optional int32 start = 1; - * @return int - */ - public function getStart() - { - return $this->start; - } - +if (false) { /** - * Generated from protobuf field optional int32 start = 1; - * @param int $var - * @return $this + * This class is deprecated. Use Google\Protobuf\Internal\DescriptorProto\ExtensionRange instead. + * @deprecated */ - public function setStart($var) - { - GPBUtil::checkInt32($var); - $this->start = $var; - $this->has_start = true; - - return $this; - } - - public function hasStart() - { - return $this->has_start; - } - - /** - * Generated from protobuf field optional int32 end = 2; - * @return int - */ - public function getEnd() - { - return $this->end; - } - - /** - * Generated from protobuf field optional int32 end = 2; - * @param int $var - * @return $this - */ - public function setEnd($var) - { - GPBUtil::checkInt32($var); - $this->end = $var; - $this->has_end = true; - - return $this; - } - - public function hasEnd() - { - return $this->has_end; - } - - /** - * Generated from protobuf field optional .google.protobuf.ExtensionRangeOptions options = 3; - * @return \Google\Protobuf\Internal\ExtensionRangeOptions - */ - public function getOptions() - { - return $this->options; - } - - /** - * Generated from protobuf field optional .google.protobuf.ExtensionRangeOptions options = 3; - * @param \Google\Protobuf\Internal\ExtensionRangeOptions $var - * @return $this - */ - public function setOptions($var) - { - GPBUtil::checkMessage($var, \Google\Protobuf\Internal\ExtensionRangeOptions::class); - $this->options = $var; - $this->has_options = true; - - return $this; - } - - public function hasOptions() - { - return $this->has_options; - } - + class DescriptorProto_ExtensionRange {} } +class_exists(DescriptorProto\ExtensionRange::class); +@trigger_error('Google\Protobuf\Internal\DescriptorProto_ExtensionRange is deprecated and will be removed in the next major release. Use Google\Protobuf\Internal\DescriptorProto\ExtensionRange instead', E_USER_DEPRECATED); diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php index b1022d6154eff..e49e945f9745a 100644 --- a/php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php +++ b/php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php @@ -4,104 +4,13 @@ namespace Google\Protobuf\Internal; -use Google\Protobuf\Internal\GPBType; -use Google\Protobuf\Internal\GPBWire; -use Google\Protobuf\Internal\RepeatedField; -use Google\Protobuf\Internal\InputStream; -use Google\Protobuf\Internal\GPBUtil; - -/** - * Range of reserved tag numbers. Reserved tag numbers may not be used by - * fields or extension ranges in the same message. Reserved ranges may - * not overlap. - * - * Generated from protobuf message google.protobuf.DescriptorProto.ReservedRange - */ -class DescriptorProto_ReservedRange extends \Google\Protobuf\Internal\Message -{ - /** - * Inclusive. - * - * Generated from protobuf field optional int32 start = 1; - */ - private $start = 0; - private $has_start = false; +if (false) { /** - * Exclusive. - * - * Generated from protobuf field optional int32 end = 2; + * This class is deprecated. Use Google\Protobuf\Internal\DescriptorProto\ReservedRange instead. + * @deprecated */ - private $end = 0; - private $has_end = false; - - public function __construct() { - \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); - } - - /** - * Inclusive. - * - * Generated from protobuf field optional int32 start = 1; - * @return int - */ - public function getStart() - { - return $this->start; - } - - /** - * Inclusive. - * - * Generated from protobuf field optional int32 start = 1; - * @param int $var - * @return $this - */ - public function setStart($var) - { - GPBUtil::checkInt32($var); - $this->start = $var; - $this->has_start = true; - - return $this; - } - - public function hasStart() - { - return $this->has_start; - } - - /** - * Exclusive. - * - * Generated from protobuf field optional int32 end = 2; - * @return int - */ - public function getEnd() - { - return $this->end; - } - - /** - * Exclusive. - * - * Generated from protobuf field optional int32 end = 2; - * @param int $var - * @return $this - */ - public function setEnd($var) - { - GPBUtil::checkInt32($var); - $this->end = $var; - $this->has_end = true; - - return $this; - } - - public function hasEnd() - { - return $this->has_end; - } - + class DescriptorProto_ReservedRange {} } +class_exists(DescriptorProto\ReservedRange::class); +@trigger_error('Google\Protobuf\Internal\DescriptorProto_ReservedRange is deprecated and will be removed in the next major release. Use Google\Protobuf\Internal\DescriptorProto\ReservedRange instead', E_USER_DEPRECATED); diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptor.php b/php/src/Google/Protobuf/Internal/EnumDescriptor.php index 01649fec4fa39..7af4f84012e59 100644 --- a/php/src/Google/Protobuf/Internal/EnumDescriptor.php +++ b/php/src/Google/Protobuf/Internal/EnumDescriptor.php @@ -9,6 +9,7 @@ class EnumDescriptor use HasPublicDescriptorTrait; private $klass; + private $legacy_klass; private $full_name; private $value; private $name_to_value; @@ -38,17 +39,26 @@ public function addValue($number, $value) public function getValueByNumber($number) { - return $this->value[$number]; + if (isset($this->value[$number])) { + return $this->value[$number]; + } + return null; } public function getValueByName($name) { - return $this->name_to_value[$name]; + if (isset($this->name_to_value[$name])) { + return $this->name_to_value[$name]; + } + return null; } public function getValueDescriptorByIndex($index) { - return $this->value_descriptor[$index]; + if (isset($this->value_descriptor[$index])) { + return $this->value_descriptor[$index]; + } + return null; } public function getValueCount() @@ -66,12 +76,23 @@ public function getClass() return $this->klass; } + public function setLegacyClass($klass) + { + $this->legacy_klass = $klass; + } + + public function getLegacyClass() + { + return $this->legacy_klass; + } + public static function buildFromProto($proto, $file_proto, $containing) { $desc = new EnumDescriptor(); $enum_name_without_package = ""; $classname = ""; + $legacy_classname = ""; $fullname = ""; GPBUtil::getFullClassName( $proto, @@ -79,9 +100,11 @@ public static function buildFromProto($proto, $file_proto, $containing) $file_proto, $enum_name_without_package, $classname, + $legacy_classname, $fullname); $desc->setFullName($fullname); $desc->setClass($classname); + $desc->setLegacyClass($legacy_classname); $values = $proto->getValue(); foreach ($values as $value) { $desc->addValue($value->getNumber(), $value); diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php index 816fbae54420c..b9b634282906e 100644 --- a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php @@ -20,22 +20,52 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field optional string name = 1; */ - private $name = ''; - private $has_name = false; + protected $name = null; /** * Generated from protobuf field repeated .google.protobuf.EnumValueDescriptorProto value = 2; */ private $value; - private $has_value = false; /** * Generated from protobuf field optional .google.protobuf.EnumOptions options = 3; */ - private $options = null; - private $has_options = false; + protected $options = null; + /** + * Range of reserved numeric values. Reserved numeric values may not be used + * by enum values in the same enum declaration. Reserved ranges may not + * overlap. + * + * Generated from protobuf field repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; + */ + private $reserved_range; + /** + * Reserved enum value names, which may not be reused. A given name may only + * be reserved once. + * + * Generated from protobuf field repeated string reserved_name = 5; + */ + private $reserved_name; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * @type \Google\Protobuf\Internal\EnumValueDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $value + * @type \Google\Protobuf\Internal\EnumOptions $options + * @type \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange[]|\Google\Protobuf\Internal\RepeatedField $reserved_range + * Range of reserved numeric values. Reserved numeric values may not be used + * by enum values in the same enum declaration. Reserved ranges may not + * overlap. + * @type string[]|\Google\Protobuf\Internal\RepeatedField $reserved_name + * Reserved enum value names, which may not be reused. A given name may only + * be reserved once. + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -44,7 +74,17 @@ public function __construct() { */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -56,16 +96,10 @@ public function setName($var) { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * Generated from protobuf field repeated .google.protobuf.EnumValueDescriptorProto value = 2; * @return \Google\Protobuf\Internal\RepeatedField @@ -84,23 +118,27 @@ public function setValue($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumValueDescriptorProto::class); $this->value = $arr; - $this->has_value = true; return $this; } - public function hasValue() - { - return $this->has_value; - } - /** * Generated from protobuf field optional .google.protobuf.EnumOptions options = 3; - * @return \Google\Protobuf\Internal\EnumOptions + * @return \Google\Protobuf\Internal\EnumOptions|null */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -112,14 +150,66 @@ public function setOptions($var) { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\EnumOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() + /** + * Range of reserved numeric values. Reserved numeric values may not be used + * by enum values in the same enum declaration. Reserved ranges may not + * overlap. + * + * Generated from protobuf field repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getReservedRange() + { + return $this->reserved_range; + } + + /** + * Range of reserved numeric values. Reserved numeric values may not be used + * by enum values in the same enum declaration. Reserved ranges may not + * overlap. + * + * Generated from protobuf field repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; + * @param \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setReservedRange($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange::class); + $this->reserved_range = $arr; + + return $this; + } + + /** + * Reserved enum value names, which may not be reused. A given name may only + * be reserved once. + * + * Generated from protobuf field repeated string reserved_name = 5; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getReservedName() { - return $this->has_options; + return $this->reserved_name; + } + + /** + * Reserved enum value names, which may not be reused. A given name may only + * be reserved once. + * + * Generated from protobuf field repeated string reserved_name = 5; + * @param string[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setReservedName($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING); + $this->reserved_name = $arr; + + return $this; } } diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php b/php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php new file mode 100644 index 0000000000000..7282fccb0788c --- /dev/null +++ b/php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php @@ -0,0 +1,130 @@ +google.protobuf.EnumDescriptorProto.EnumReservedRange + */ +class EnumReservedRange extends \Google\Protobuf\Internal\Message +{ + /** + * Inclusive. + * + * Generated from protobuf field optional int32 start = 1; + */ + protected $start = null; + /** + * Inclusive. + * + * Generated from protobuf field optional int32 end = 2; + */ + protected $end = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $start + * Inclusive. + * @type int $end + * Inclusive. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); + parent::__construct($data); + } + + /** + * Inclusive. + * + * Generated from protobuf field optional int32 start = 1; + * @return int + */ + public function getStart() + { + return isset($this->start) ? $this->start : 0; + } + + public function hasStart() + { + return isset($this->start); + } + + public function clearStart() + { + unset($this->start); + } + + /** + * Inclusive. + * + * Generated from protobuf field optional int32 start = 1; + * @param int $var + * @return $this + */ + public function setStart($var) + { + GPBUtil::checkInt32($var); + $this->start = $var; + + return $this; + } + + /** + * Inclusive. + * + * Generated from protobuf field optional int32 end = 2; + * @return int + */ + public function getEnd() + { + return isset($this->end) ? $this->end : 0; + } + + public function hasEnd() + { + return isset($this->end); + } + + public function clearEnd() + { + unset($this->end); + } + + /** + * Inclusive. + * + * Generated from protobuf field optional int32 end = 2; + * @param int $var + * @return $this + */ + public function setEnd($var) + { + GPBUtil::checkInt32($var); + $this->end = $var; + + return $this; + } + +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(EnumReservedRange::class, \Google\Protobuf\Internal\EnumDescriptorProto_EnumReservedRange::class); + diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php b/php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php new file mode 100644 index 0000000000000..b1b59ed91f48b --- /dev/null +++ b/php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php @@ -0,0 +1,16 @@ +optional bool allow_alias = 2; */ - private $allow_alias = false; - private $has_allow_alias = false; + protected $allow_alias = null; /** * Is this enum deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -31,19 +30,35 @@ class EnumOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool deprecated = 3 [default = false]; */ - private $deprecated = false; - private $has_deprecated = false; + protected $deprecated = null; /** * The parser stores options it doesn't recognize here. See above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type bool $allow_alias + * Set this option to true to allow mapping different tag names to the same + * value. + * @type bool $deprecated + * Is this enum deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the enum, or it will be completely ignored; in the very least, this + * is a formalization for deprecating enums. + * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option + * The parser stores options it doesn't recognize here. See above. + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -55,7 +70,17 @@ public function __construct() { */ public function getAllowAlias() { - return $this->allow_alias; + return isset($this->allow_alias) ? $this->allow_alias : false; + } + + public function hasAllowAlias() + { + return isset($this->allow_alias); + } + + public function clearAllowAlias() + { + unset($this->allow_alias); } /** @@ -70,16 +95,10 @@ public function setAllowAlias($var) { GPBUtil::checkBool($var); $this->allow_alias = $var; - $this->has_allow_alias = true; return $this; } - public function hasAllowAlias() - { - return $this->has_allow_alias; - } - /** * Is this enum deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -91,7 +110,17 @@ public function hasAllowAlias() */ public function getDeprecated() { - return $this->deprecated; + return isset($this->deprecated) ? $this->deprecated : false; + } + + public function hasDeprecated() + { + return isset($this->deprecated); + } + + public function clearDeprecated() + { + unset($this->deprecated); } /** @@ -108,16 +137,10 @@ public function setDeprecated($var) { GPBUtil::checkBool($var); $this->deprecated = $var; - $this->has_deprecated = true; return $this; } - public function hasDeprecated() - { - return $this->has_deprecated; - } - /** * The parser stores options it doesn't recognize here. See above. * @@ -140,15 +163,9 @@ public function setUninterpretedOption($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php index e363220fc1b90..eff1452eed4eb 100644 --- a/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php @@ -20,22 +20,30 @@ class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field optional string name = 1; */ - private $name = ''; - private $has_name = false; + protected $name = null; /** * Generated from protobuf field optional int32 number = 2; */ - private $number = 0; - private $has_number = false; + protected $number = null; /** * Generated from protobuf field optional .google.protobuf.EnumValueOptions options = 3; */ - private $options = null; - private $has_options = false; + protected $options = null; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * @type int $number + * @type \Google\Protobuf\Internal\EnumValueOptions $options + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -44,7 +52,17 @@ public function __construct() { */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -56,23 +74,27 @@ public function setName($var) { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * Generated from protobuf field optional int32 number = 2; * @return int */ public function getNumber() { - return $this->number; + return isset($this->number) ? $this->number : 0; + } + + public function hasNumber() + { + return isset($this->number); + } + + public function clearNumber() + { + unset($this->number); } /** @@ -84,23 +106,27 @@ public function setNumber($var) { GPBUtil::checkInt32($var); $this->number = $var; - $this->has_number = true; return $this; } - public function hasNumber() - { - return $this->has_number; - } - /** * Generated from protobuf field optional .google.protobuf.EnumValueOptions options = 3; - * @return \Google\Protobuf\Internal\EnumValueOptions + * @return \Google\Protobuf\Internal\EnumValueOptions|null */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -112,15 +138,9 @@ public function setOptions($var) { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\EnumValueOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - } diff --git a/php/src/Google/Protobuf/Internal/EnumValueOptions.php b/php/src/Google/Protobuf/Internal/EnumValueOptions.php index db8de174d726d..84ba7bc85bfcf 100644 --- a/php/src/Google/Protobuf/Internal/EnumValueOptions.php +++ b/php/src/Google/Protobuf/Internal/EnumValueOptions.php @@ -23,19 +23,32 @@ class EnumValueOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool deprecated = 1 [default = false]; */ - private $deprecated = false; - private $has_deprecated = false; + protected $deprecated = null; /** * The parser stores options it doesn't recognize here. See above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type bool $deprecated + * Is this enum value deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the enum value, or it will be completely ignored; in the very least, + * this is a formalization for deprecating enum values. + * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option + * The parser stores options it doesn't recognize here. See above. + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -49,7 +62,17 @@ public function __construct() { */ public function getDeprecated() { - return $this->deprecated; + return isset($this->deprecated) ? $this->deprecated : false; + } + + public function hasDeprecated() + { + return isset($this->deprecated); + } + + public function clearDeprecated() + { + unset($this->deprecated); } /** @@ -66,16 +89,10 @@ public function setDeprecated($var) { GPBUtil::checkBool($var); $this->deprecated = $var; - $this->has_deprecated = true; return $this; } - public function hasDeprecated() - { - return $this->has_deprecated; - } - /** * The parser stores options it doesn't recognize here. See above. * @@ -98,15 +115,9 @@ public function setUninterpretedOption($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php b/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php new file mode 100644 index 0000000000000..b5e27c3e27835 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php @@ -0,0 +1,67 @@ +google.protobuf.ExtensionRangeOptions + */ +class ExtensionRangeOptions extends \Google\Protobuf\Internal\Message +{ + /** + * The parser stores options it doesn't recognize here. See above. + * + * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + */ + private $uninterpreted_option; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option + * The parser stores options it doesn't recognize here. See above. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); + parent::__construct($data); + } + + /** + * The parser stores options it doesn't recognize here. See above. + * + * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getUninterpretedOption() + { + return $this->uninterpreted_option; + } + + /** + * The parser stores options it doesn't recognize here. See above. + * + * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + * @param \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setUninterpretedOption($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); + $this->uninterpreted_option = $arr; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptor.php b/php/src/Google/Protobuf/Internal/FieldDescriptor.php index 1443c6fd0b7cc..ce83f63a2b267 100644 --- a/php/src/Google/Protobuf/Internal/FieldDescriptor.php +++ b/php/src/Google/Protobuf/Internal/FieldDescriptor.php @@ -181,6 +181,31 @@ public function isMap() $this->getMessageType()->getOptions()->getMapEntry(); } + public function isTimestamp() + { + return $this->getType() == GPBType::MESSAGE && + $this->getMessageType()->getClass() === "Google\Protobuf\Timestamp"; + } + + public function isWrapperType() + { + if ($this->getType() == GPBType::MESSAGE) { + $class = $this->getMessageType()->getClass(); + return in_array($class, [ + "Google\Protobuf\DoubleValue", + "Google\Protobuf\FloatValue", + "Google\Protobuf\Int64Value", + "Google\Protobuf\UInt64Value", + "Google\Protobuf\Int32Value", + "Google\Protobuf\UInt32Value", + "Google\Protobuf\BoolValue", + "Google\Protobuf\StringValue", + "Google\Protobuf\BytesValue", + ]); + } + return false; + } + private static function isTypePackable($field_type) { return ($field_type !== GPBType::STRING && @@ -204,7 +229,17 @@ public static function getFieldDescriptor($proto) } $oneof_index = $proto->hasOneofIndex() ? $proto->getOneofIndex() : -1; - $packed = false; + // TODO: once proto2 is supported, this default should be false + // for proto2. + if ($proto->getLabel() === GPBLabel::REPEATED && + $proto->getType() !== GPBType::MESSAGE && + $proto->getType() !== GPBType::GROUP && + $proto->getType() !== GPBType::STRING && + $proto->getType() !== GPBType::BYTES) { + $packed = true; + } else { + $packed = false; + } $options = $proto->getOptions(); if ($options !== null) { $packed = $options->getPacked(); diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php index 10c27593302ad..94e5fe12ecc9e 100644 --- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php @@ -20,26 +20,22 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field optional string name = 1; */ - private $name = ''; - private $has_name = false; + protected $name = null; /** * Generated from protobuf field optional int32 number = 3; */ - private $number = 0; - private $has_number = false; + protected $number = null; /** * Generated from protobuf field optional .google.protobuf.FieldDescriptorProto.Label label = 4; */ - private $label = 0; - private $has_label = false; + protected $label = null; /** * If type_name is set, this need not be set. If both this and type_name * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. * * Generated from protobuf field optional .google.protobuf.FieldDescriptorProto.Type type = 5; */ - private $type = 0; - private $has_type = false; + protected $type = null; /** * For message and enum types, this is the name of the type. If the name * starts with a '.', it is fully-qualified. Otherwise, C++-like scoping @@ -49,16 +45,14 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string type_name = 6; */ - private $type_name = ''; - private $has_type_name = false; + protected $type_name = null; /** * For extensions, this is the name of the type being extended. It is * resolved in the same manner as type_name. * * Generated from protobuf field optional string extendee = 2; */ - private $extendee = ''; - private $has_extendee = false; + protected $extendee = null; /** * For numeric types, contains the original text representation of the value. * For booleans, "true" or "false". @@ -68,16 +62,14 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string default_value = 7; */ - private $default_value = ''; - private $has_default_value = false; + protected $default_value = null; /** * If set, gives the index of a oneof in the containing type's oneof_decl * list. This field is a member of that oneof. * * Generated from protobuf field optional int32 oneof_index = 9; */ - private $oneof_index = 0; - private $has_oneof_index = false; + protected $oneof_index = null; /** * JSON name of this field. The value is set by protocol compiler. If the * user has set a "json_name" option on this field, that option's value @@ -86,17 +78,95 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string json_name = 10; */ - private $json_name = ''; - private $has_json_name = false; + protected $json_name = null; /** * Generated from protobuf field optional .google.protobuf.FieldOptions options = 8; */ - private $options = null; - private $has_options = false; + protected $options = null; + /** + * If true, this is a proto3 "optional". When a proto3 field is optional, it + * tracks presence regardless of field type. + * When proto3_optional is true, this field must be belong to a oneof to + * signal to old proto3 clients that presence is tracked for this field. This + * oneof is known as a "synthetic" oneof, and this field must be its sole + * member (each proto3 optional field gets its own synthetic oneof). Synthetic + * oneofs exist in the descriptor only, and do not generate any API. Synthetic + * oneofs must be ordered after all "real" oneofs. + * For message fields, proto3_optional doesn't create any semantic change, + * since non-repeated message fields always track presence. However it still + * indicates the semantic detail of whether the user wrote "optional" or not. + * This can be useful for round-tripping the .proto file. For consistency we + * give message fields a synthetic oneof also, even though it is not required + * to track presence. This is especially important because the parser can't + * tell if a field is a message or an enum, so it must always create a + * synthetic oneof. + * Proto2 optional fields do not set this flag, because they already indicate + * optional with `LABEL_OPTIONAL`. + * + * Generated from protobuf field optional bool proto3_optional = 17; + */ + protected $proto3_optional = null; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * @type int $number + * @type int $label + * @type int $type + * If type_name is set, this need not be set. If both this and type_name + * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + * @type string $type_name + * For message and enum types, this is the name of the type. If the name + * starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + * rules are used to find the type (i.e. first the nested types within this + * message are searched, then within the parent, on up to the root + * namespace). + * @type string $extendee + * For extensions, this is the name of the type being extended. It is + * resolved in the same manner as type_name. + * @type string $default_value + * For numeric types, contains the original text representation of the value. + * For booleans, "true" or "false". + * For strings, contains the default text contents (not escaped in any way). + * For bytes, contains the C escaped value. All bytes >= 128 are escaped. + * TODO(kenton): Base-64 encode? + * @type int $oneof_index + * If set, gives the index of a oneof in the containing type's oneof_decl + * list. This field is a member of that oneof. + * @type string $json_name + * JSON name of this field. The value is set by protocol compiler. If the + * user has set a "json_name" option on this field, that option's value + * will be used. Otherwise, it's deduced from the field's name by converting + * it to camelCase. + * @type \Google\Protobuf\Internal\FieldOptions $options + * @type bool $proto3_optional + * If true, this is a proto3 "optional". When a proto3 field is optional, it + * tracks presence regardless of field type. + * When proto3_optional is true, this field must be belong to a oneof to + * signal to old proto3 clients that presence is tracked for this field. This + * oneof is known as a "synthetic" oneof, and this field must be its sole + * member (each proto3 optional field gets its own synthetic oneof). Synthetic + * oneofs exist in the descriptor only, and do not generate any API. Synthetic + * oneofs must be ordered after all "real" oneofs. + * For message fields, proto3_optional doesn't create any semantic change, + * since non-repeated message fields always track presence. However it still + * indicates the semantic detail of whether the user wrote "optional" or not. + * This can be useful for round-tripping the .proto file. For consistency we + * give message fields a synthetic oneof also, even though it is not required + * to track presence. This is especially important because the parser can't + * tell if a field is a message or an enum, so it must always create a + * synthetic oneof. + * Proto2 optional fields do not set this flag, because they already indicate + * optional with `LABEL_OPTIONAL`. + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -105,7 +175,17 @@ public function __construct() { */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -117,23 +197,27 @@ public function setName($var) { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * Generated from protobuf field optional int32 number = 3; * @return int */ public function getNumber() { - return $this->number; + return isset($this->number) ? $this->number : 0; + } + + public function hasNumber() + { + return isset($this->number); + } + + public function clearNumber() + { + unset($this->number); } /** @@ -145,23 +229,27 @@ public function setNumber($var) { GPBUtil::checkInt32($var); $this->number = $var; - $this->has_number = true; return $this; } - public function hasNumber() - { - return $this->has_number; - } - /** * Generated from protobuf field optional .google.protobuf.FieldDescriptorProto.Label label = 4; * @return int */ public function getLabel() { - return $this->label; + return isset($this->label) ? $this->label : 0; + } + + public function hasLabel() + { + return isset($this->label); + } + + public function clearLabel() + { + unset($this->label); } /** @@ -171,18 +259,12 @@ public function getLabel() */ public function setLabel($var) { - GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto_Label::class); + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto\Label::class); $this->label = $var; - $this->has_label = true; return $this; } - public function hasLabel() - { - return $this->has_label; - } - /** * If type_name is set, this need not be set. If both this and type_name * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. @@ -192,7 +274,17 @@ public function hasLabel() */ public function getType() { - return $this->type; + return isset($this->type) ? $this->type : 0; + } + + public function hasType() + { + return isset($this->type); + } + + public function clearType() + { + unset($this->type); } /** @@ -205,18 +297,12 @@ public function getType() */ public function setType($var) { - GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto_Type::class); + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto\Type::class); $this->type = $var; - $this->has_type = true; return $this; } - public function hasType() - { - return $this->has_type; - } - /** * For message and enum types, this is the name of the type. If the name * starts with a '.', it is fully-qualified. Otherwise, C++-like scoping @@ -229,7 +315,17 @@ public function hasType() */ public function getTypeName() { - return $this->type_name; + return isset($this->type_name) ? $this->type_name : ''; + } + + public function hasTypeName() + { + return isset($this->type_name); + } + + public function clearTypeName() + { + unset($this->type_name); } /** @@ -247,16 +343,10 @@ public function setTypeName($var) { GPBUtil::checkString($var, True); $this->type_name = $var; - $this->has_type_name = true; return $this; } - public function hasTypeName() - { - return $this->has_type_name; - } - /** * For extensions, this is the name of the type being extended. It is * resolved in the same manner as type_name. @@ -266,7 +356,17 @@ public function hasTypeName() */ public function getExtendee() { - return $this->extendee; + return isset($this->extendee) ? $this->extendee : ''; + } + + public function hasExtendee() + { + return isset($this->extendee); + } + + public function clearExtendee() + { + unset($this->extendee); } /** @@ -281,16 +381,10 @@ public function setExtendee($var) { GPBUtil::checkString($var, True); $this->extendee = $var; - $this->has_extendee = true; return $this; } - public function hasExtendee() - { - return $this->has_extendee; - } - /** * For numeric types, contains the original text representation of the value. * For booleans, "true" or "false". @@ -303,7 +397,17 @@ public function hasExtendee() */ public function getDefaultValue() { - return $this->default_value; + return isset($this->default_value) ? $this->default_value : ''; + } + + public function hasDefaultValue() + { + return isset($this->default_value); + } + + public function clearDefaultValue() + { + unset($this->default_value); } /** @@ -321,16 +425,10 @@ public function setDefaultValue($var) { GPBUtil::checkString($var, True); $this->default_value = $var; - $this->has_default_value = true; return $this; } - public function hasDefaultValue() - { - return $this->has_default_value; - } - /** * If set, gives the index of a oneof in the containing type's oneof_decl * list. This field is a member of that oneof. @@ -340,7 +438,17 @@ public function hasDefaultValue() */ public function getOneofIndex() { - return $this->oneof_index; + return isset($this->oneof_index) ? $this->oneof_index : 0; + } + + public function hasOneofIndex() + { + return isset($this->oneof_index); + } + + public function clearOneofIndex() + { + unset($this->oneof_index); } /** @@ -355,16 +463,10 @@ public function setOneofIndex($var) { GPBUtil::checkInt32($var); $this->oneof_index = $var; - $this->has_oneof_index = true; return $this; } - public function hasOneofIndex() - { - return $this->has_oneof_index; - } - /** * JSON name of this field. The value is set by protocol compiler. If the * user has set a "json_name" option on this field, that option's value @@ -376,7 +478,17 @@ public function hasOneofIndex() */ public function getJsonName() { - return $this->json_name; + return isset($this->json_name) ? $this->json_name : ''; + } + + public function hasJsonName() + { + return isset($this->json_name); + } + + public function clearJsonName() + { + unset($this->json_name); } /** @@ -393,23 +505,27 @@ public function setJsonName($var) { GPBUtil::checkString($var, True); $this->json_name = $var; - $this->has_json_name = true; return $this; } - public function hasJsonName() - { - return $this->has_json_name; - } - /** * Generated from protobuf field optional .google.protobuf.FieldOptions options = 8; - * @return \Google\Protobuf\Internal\FieldOptions + * @return \Google\Protobuf\Internal\FieldOptions|null */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -421,14 +537,78 @@ public function setOptions($var) { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FieldOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() + /** + * If true, this is a proto3 "optional". When a proto3 field is optional, it + * tracks presence regardless of field type. + * When proto3_optional is true, this field must be belong to a oneof to + * signal to old proto3 clients that presence is tracked for this field. This + * oneof is known as a "synthetic" oneof, and this field must be its sole + * member (each proto3 optional field gets its own synthetic oneof). Synthetic + * oneofs exist in the descriptor only, and do not generate any API. Synthetic + * oneofs must be ordered after all "real" oneofs. + * For message fields, proto3_optional doesn't create any semantic change, + * since non-repeated message fields always track presence. However it still + * indicates the semantic detail of whether the user wrote "optional" or not. + * This can be useful for round-tripping the .proto file. For consistency we + * give message fields a synthetic oneof also, even though it is not required + * to track presence. This is especially important because the parser can't + * tell if a field is a message or an enum, so it must always create a + * synthetic oneof. + * Proto2 optional fields do not set this flag, because they already indicate + * optional with `LABEL_OPTIONAL`. + * + * Generated from protobuf field optional bool proto3_optional = 17; + * @return bool + */ + public function getProto3Optional() + { + return isset($this->proto3_optional) ? $this->proto3_optional : false; + } + + public function hasProto3Optional() + { + return isset($this->proto3_optional); + } + + public function clearProto3Optional() + { + unset($this->proto3_optional); + } + + /** + * If true, this is a proto3 "optional". When a proto3 field is optional, it + * tracks presence regardless of field type. + * When proto3_optional is true, this field must be belong to a oneof to + * signal to old proto3 clients that presence is tracked for this field. This + * oneof is known as a "synthetic" oneof, and this field must be its sole + * member (each proto3 optional field gets its own synthetic oneof). Synthetic + * oneofs exist in the descriptor only, and do not generate any API. Synthetic + * oneofs must be ordered after all "real" oneofs. + * For message fields, proto3_optional doesn't create any semantic change, + * since non-repeated message fields always track presence. However it still + * indicates the semantic detail of whether the user wrote "optional" or not. + * This can be useful for round-tripping the .proto file. For consistency we + * give message fields a synthetic oneof also, even though it is not required + * to track presence. This is especially important because the parser can't + * tell if a field is a message or an enum, so it must always create a + * synthetic oneof. + * Proto2 optional fields do not set this flag, because they already indicate + * optional with `LABEL_OPTIONAL`. + * + * Generated from protobuf field optional bool proto3_optional = 17; + * @param bool $var + * @return $this + */ + public function setProto3Optional($var) { - return $this->has_options; + GPBUtil::checkBool($var); + $this->proto3_optional = $var; + + return $this; } } diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto/Label.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto/Label.php new file mode 100644 index 0000000000000..a54b228f1bfb3 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto/Label.php @@ -0,0 +1,58 @@ +google.protobuf.FieldDescriptorProto.Label + */ +class Label +{ + /** + * 0 is reserved for errors + * + * Generated from protobuf enum LABEL_OPTIONAL = 1; + */ + const LABEL_OPTIONAL = 1; + /** + * Generated from protobuf enum LABEL_REQUIRED = 2; + */ + const LABEL_REQUIRED = 2; + /** + * Generated from protobuf enum LABEL_REPEATED = 3; + */ + const LABEL_REPEATED = 3; + + private static $valueToName = [ + self::LABEL_OPTIONAL => 'LABEL_OPTIONAL', + self::LABEL_REQUIRED => 'LABEL_REQUIRED', + self::LABEL_REPEATED => 'LABEL_REPEATED', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(Label::class, \Google\Protobuf\Internal\FieldDescriptorProto_Label::class); + diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php new file mode 100644 index 0000000000000..6072e9990fb30 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php @@ -0,0 +1,153 @@ +google.protobuf.FieldDescriptorProto.Type + */ +class Type +{ + /** + * 0 is reserved for errors. + * Order is weird for historical reasons. + * + * Generated from protobuf enum TYPE_DOUBLE = 1; + */ + const TYPE_DOUBLE = 1; + /** + * Generated from protobuf enum TYPE_FLOAT = 2; + */ + const TYPE_FLOAT = 2; + /** + * Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + * negative values are likely. + * + * Generated from protobuf enum TYPE_INT64 = 3; + */ + const TYPE_INT64 = 3; + /** + * Generated from protobuf enum TYPE_UINT64 = 4; + */ + const TYPE_UINT64 = 4; + /** + * Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + * negative values are likely. + * + * Generated from protobuf enum TYPE_INT32 = 5; + */ + const TYPE_INT32 = 5; + /** + * Generated from protobuf enum TYPE_FIXED64 = 6; + */ + const TYPE_FIXED64 = 6; + /** + * Generated from protobuf enum TYPE_FIXED32 = 7; + */ + const TYPE_FIXED32 = 7; + /** + * Generated from protobuf enum TYPE_BOOL = 8; + */ + const TYPE_BOOL = 8; + /** + * Generated from protobuf enum TYPE_STRING = 9; + */ + const TYPE_STRING = 9; + /** + * Tag-delimited aggregate. + * Group type is deprecated and not supported in proto3. However, Proto3 + * implementations should still be able to parse the group wire format and + * treat group fields as unknown fields. + * + * Generated from protobuf enum TYPE_GROUP = 10; + */ + const TYPE_GROUP = 10; + /** + * Length-delimited aggregate. + * + * Generated from protobuf enum TYPE_MESSAGE = 11; + */ + const TYPE_MESSAGE = 11; + /** + * New in version 2. + * + * Generated from protobuf enum TYPE_BYTES = 12; + */ + const TYPE_BYTES = 12; + /** + * Generated from protobuf enum TYPE_UINT32 = 13; + */ + const TYPE_UINT32 = 13; + /** + * Generated from protobuf enum TYPE_ENUM = 14; + */ + const TYPE_ENUM = 14; + /** + * Generated from protobuf enum TYPE_SFIXED32 = 15; + */ + const TYPE_SFIXED32 = 15; + /** + * Generated from protobuf enum TYPE_SFIXED64 = 16; + */ + const TYPE_SFIXED64 = 16; + /** + * Uses ZigZag encoding. + * + * Generated from protobuf enum TYPE_SINT32 = 17; + */ + const TYPE_SINT32 = 17; + /** + * Uses ZigZag encoding. + * + * Generated from protobuf enum TYPE_SINT64 = 18; + */ + const TYPE_SINT64 = 18; + + private static $valueToName = [ + self::TYPE_DOUBLE => 'TYPE_DOUBLE', + self::TYPE_FLOAT => 'TYPE_FLOAT', + self::TYPE_INT64 => 'TYPE_INT64', + self::TYPE_UINT64 => 'TYPE_UINT64', + self::TYPE_INT32 => 'TYPE_INT32', + self::TYPE_FIXED64 => 'TYPE_FIXED64', + self::TYPE_FIXED32 => 'TYPE_FIXED32', + self::TYPE_BOOL => 'TYPE_BOOL', + self::TYPE_STRING => 'TYPE_STRING', + self::TYPE_GROUP => 'TYPE_GROUP', + self::TYPE_MESSAGE => 'TYPE_MESSAGE', + self::TYPE_BYTES => 'TYPE_BYTES', + self::TYPE_UINT32 => 'TYPE_UINT32', + self::TYPE_ENUM => 'TYPE_ENUM', + self::TYPE_SFIXED32 => 'TYPE_SFIXED32', + self::TYPE_SFIXED64 => 'TYPE_SFIXED64', + self::TYPE_SINT32 => 'TYPE_SINT32', + self::TYPE_SINT64 => 'TYPE_SINT64', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(Type::class, \Google\Protobuf\Internal\FieldDescriptorProto_Type::class); + diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php index f2a32fdf214b6..218a846e1e764 100644 --- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php +++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php @@ -4,24 +4,13 @@ namespace Google\Protobuf\Internal; -/** - * Protobuf enum Google\Protobuf\Internal - */ -class FieldDescriptorProto_Label -{ +if (false) { /** - * 0 is reserved for errors - * - * Generated from protobuf enum LABEL_OPTIONAL = 1; + * This class is deprecated. Use Google\Protobuf\Internal\FieldDescriptorProto\Label instead. + * @deprecated */ - const LABEL_OPTIONAL = 1; - /** - * Generated from protobuf enum LABEL_REQUIRED = 2; - */ - const LABEL_REQUIRED = 2; - /** - * Generated from protobuf enum LABEL_REPEATED = 3; - */ - const LABEL_REPEATED = 3; + class FieldDescriptorProto_Label {} } +class_exists(FieldDescriptorProto\Label::class); +@trigger_error('Google\Protobuf\Internal\FieldDescriptorProto_Label is deprecated and will be removed in the next major release. Use Google\Protobuf\Internal\FieldDescriptorProto\Label instead', E_USER_DEPRECATED); diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php index 1b022debe85eb..fd8d449a57205 100644 --- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php +++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php @@ -4,104 +4,13 @@ namespace Google\Protobuf\Internal; -/** - * Protobuf enum Google\Protobuf\Internal - */ -class FieldDescriptorProto_Type -{ +if (false) { /** - * 0 is reserved for errors. - * Order is weird for historical reasons. - * - * Generated from protobuf enum TYPE_DOUBLE = 1; + * This class is deprecated. Use Google\Protobuf\Internal\FieldDescriptorProto\Type instead. + * @deprecated */ - const TYPE_DOUBLE = 1; - /** - * Generated from protobuf enum TYPE_FLOAT = 2; - */ - const TYPE_FLOAT = 2; - /** - * Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if - * negative values are likely. - * - * Generated from protobuf enum TYPE_INT64 = 3; - */ - const TYPE_INT64 = 3; - /** - * Generated from protobuf enum TYPE_UINT64 = 4; - */ - const TYPE_UINT64 = 4; - /** - * Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if - * negative values are likely. - * - * Generated from protobuf enum TYPE_INT32 = 5; - */ - const TYPE_INT32 = 5; - /** - * Generated from protobuf enum TYPE_FIXED64 = 6; - */ - const TYPE_FIXED64 = 6; - /** - * Generated from protobuf enum TYPE_FIXED32 = 7; - */ - const TYPE_FIXED32 = 7; - /** - * Generated from protobuf enum TYPE_BOOL = 8; - */ - const TYPE_BOOL = 8; - /** - * Generated from protobuf enum TYPE_STRING = 9; - */ - const TYPE_STRING = 9; - /** - * Tag-delimited aggregate. - * Group type is deprecated and not supported in proto3. However, Proto3 - * implementations should still be able to parse the group wire format and - * treat group fields as unknown fields. - * - * Generated from protobuf enum TYPE_GROUP = 10; - */ - const TYPE_GROUP = 10; - /** - * Length-delimited aggregate. - * - * Generated from protobuf enum TYPE_MESSAGE = 11; - */ - const TYPE_MESSAGE = 11; - /** - * New in version 2. - * - * Generated from protobuf enum TYPE_BYTES = 12; - */ - const TYPE_BYTES = 12; - /** - * Generated from protobuf enum TYPE_UINT32 = 13; - */ - const TYPE_UINT32 = 13; - /** - * Generated from protobuf enum TYPE_ENUM = 14; - */ - const TYPE_ENUM = 14; - /** - * Generated from protobuf enum TYPE_SFIXED32 = 15; - */ - const TYPE_SFIXED32 = 15; - /** - * Generated from protobuf enum TYPE_SFIXED64 = 16; - */ - const TYPE_SFIXED64 = 16; - /** - * Uses ZigZag encoding. - * - * Generated from protobuf enum TYPE_SINT32 = 17; - */ - const TYPE_SINT32 = 17; - /** - * Uses ZigZag encoding. - * - * Generated from protobuf enum TYPE_SINT64 = 18; - */ - const TYPE_SINT64 = 18; + class FieldDescriptorProto_Type {} } +class_exists(FieldDescriptorProto\Type::class); +@trigger_error('Google\Protobuf\Internal\FieldDescriptorProto_Type is deprecated and will be removed in the next major release. Use Google\Protobuf\Internal\FieldDescriptorProto\Type instead', E_USER_DEPRECATED); diff --git a/php/src/Google/Protobuf/Internal/FieldOptions.php b/php/src/Google/Protobuf/Internal/FieldOptions.php index 169f860be0ec6..c6c63a9665acc 100644 --- a/php/src/Google/Protobuf/Internal/FieldOptions.php +++ b/php/src/Google/Protobuf/Internal/FieldOptions.php @@ -23,8 +23,7 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; */ - private $ctype = 0; - private $has_ctype = false; + protected $ctype = null; /** * The packed option can be enabled for repeated primitive fields to enable * a more efficient representation on the wire. Rather than repeatedly @@ -34,8 +33,7 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool packed = 2; */ - private $packed = false; - private $has_packed = false; + protected $packed = null; /** * The jstype option determines the JavaScript type used for values of the * field. The option is permitted only for 64 bit integral and fixed types @@ -50,8 +48,7 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; */ - private $jstype = 0; - private $has_jstype = false; + protected $jstype = null; /** * Should this field be parsed lazily? Lazy applies only to message-type * fields. It means that when the outer message is initially parsed, the @@ -80,8 +77,7 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool lazy = 5 [default = false]; */ - private $lazy = false; - private $has_lazy = false; + protected $lazy = null; /** * Is this field deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -90,26 +86,87 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool deprecated = 3 [default = false]; */ - private $deprecated = false; - private $has_deprecated = false; + protected $deprecated = null; /** * For Google-internal migration only. Do not use. * * Generated from protobuf field optional bool weak = 10 [default = false]; */ - private $weak = false; - private $has_weak = false; + protected $weak = null; /** * The parser stores options it doesn't recognize here. See above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $ctype + * The ctype option instructs the C++ code generator to use a different + * representation of the field than it normally would. See the specific + * options below. This option is not yet implemented in the open source + * release -- sorry, we'll try to include it in a future version! + * @type bool $packed + * The packed option can be enabled for repeated primitive fields to enable + * a more efficient representation on the wire. Rather than repeatedly + * writing the tag and type for each element, the entire array is encoded as + * a single length-delimited blob. In proto3, only explicit setting it to + * false will avoid using packed encoding. + * @type int $jstype + * The jstype option determines the JavaScript type used for values of the + * field. The option is permitted only for 64 bit integral and fixed types + * (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + * is represented as JavaScript string, which avoids loss of precision that + * can happen when a large value is converted to a floating point JavaScript. + * Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + * use the JavaScript "number" type. The behavior of the default option + * JS_NORMAL is implementation dependent. + * This option is an enum to permit additional types to be added, e.g. + * goog.math.Integer. + * @type bool $lazy + * Should this field be parsed lazily? Lazy applies only to message-type + * fields. It means that when the outer message is initially parsed, the + * inner message's contents will not be parsed but instead stored in encoded + * form. The inner message will actually be parsed when it is first accessed. + * This is only a hint. Implementations are free to choose whether to use + * eager or lazy parsing regardless of the value of this option. However, + * setting this option true suggests that the protocol author believes that + * using lazy parsing on this field is worth the additional bookkeeping + * overhead typically needed to implement it. + * This option does not affect the public interface of any generated code; + * all method signatures remain the same. Furthermore, thread-safety of the + * interface is not affected by this option; const methods remain safe to + * call from multiple threads concurrently, while non-const methods continue + * to require exclusive access. + * Note that implementations may choose not to check required fields within + * a lazy sub-message. That is, calling IsInitialized() on the outer message + * may return true even if the inner message has missing required fields. + * This is necessary because otherwise the inner message would have to be + * parsed in order to perform the check, defeating the purpose of lazy + * parsing. An implementation which chooses not to check required fields + * must be consistent about it. That is, for any particular sub-message, the + * implementation must either *always* check its required fields, or *never* + * check its required fields, regardless of whether or not the message has + * been parsed. + * @type bool $deprecated + * Is this field deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for accessors, or it will be completely ignored; in the very least, this + * is a formalization for deprecating fields. + * @type bool $weak + * For Google-internal migration only. Do not use. + * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option + * The parser stores options it doesn't recognize here. See above. + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -123,7 +180,17 @@ public function __construct() { */ public function getCtype() { - return $this->ctype; + return isset($this->ctype) ? $this->ctype : 0; + } + + public function hasCtype() + { + return isset($this->ctype); + } + + public function clearCtype() + { + unset($this->ctype); } /** @@ -138,18 +205,12 @@ public function getCtype() */ public function setCtype($var) { - GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions_CType::class); + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions\CType::class); $this->ctype = $var; - $this->has_ctype = true; return $this; } - public function hasCtype() - { - return $this->has_ctype; - } - /** * The packed option can be enabled for repeated primitive fields to enable * a more efficient representation on the wire. Rather than repeatedly @@ -162,7 +223,17 @@ public function hasCtype() */ public function getPacked() { - return $this->packed; + return isset($this->packed) ? $this->packed : false; + } + + public function hasPacked() + { + return isset($this->packed); + } + + public function clearPacked() + { + unset($this->packed); } /** @@ -180,16 +251,10 @@ public function setPacked($var) { GPBUtil::checkBool($var); $this->packed = $var; - $this->has_packed = true; return $this; } - public function hasPacked() - { - return $this->has_packed; - } - /** * The jstype option determines the JavaScript type used for values of the * field. The option is permitted only for 64 bit integral and fixed types @@ -207,7 +272,17 @@ public function hasPacked() */ public function getJstype() { - return $this->jstype; + return isset($this->jstype) ? $this->jstype : 0; + } + + public function hasJstype() + { + return isset($this->jstype); + } + + public function clearJstype() + { + unset($this->jstype); } /** @@ -228,18 +303,12 @@ public function getJstype() */ public function setJstype($var) { - GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions_JSType::class); + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions\JSType::class); $this->jstype = $var; - $this->has_jstype = true; return $this; } - public function hasJstype() - { - return $this->has_jstype; - } - /** * Should this field be parsed lazily? Lazy applies only to message-type * fields. It means that when the outer message is initially parsed, the @@ -271,7 +340,17 @@ public function hasJstype() */ public function getLazy() { - return $this->lazy; + return isset($this->lazy) ? $this->lazy : false; + } + + public function hasLazy() + { + return isset($this->lazy); + } + + public function clearLazy() + { + unset($this->lazy); } /** @@ -308,16 +387,10 @@ public function setLazy($var) { GPBUtil::checkBool($var); $this->lazy = $var; - $this->has_lazy = true; return $this; } - public function hasLazy() - { - return $this->has_lazy; - } - /** * Is this field deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -329,7 +402,17 @@ public function hasLazy() */ public function getDeprecated() { - return $this->deprecated; + return isset($this->deprecated) ? $this->deprecated : false; + } + + public function hasDeprecated() + { + return isset($this->deprecated); + } + + public function clearDeprecated() + { + unset($this->deprecated); } /** @@ -346,16 +429,10 @@ public function setDeprecated($var) { GPBUtil::checkBool($var); $this->deprecated = $var; - $this->has_deprecated = true; return $this; } - public function hasDeprecated() - { - return $this->has_deprecated; - } - /** * For Google-internal migration only. Do not use. * @@ -364,7 +441,17 @@ public function hasDeprecated() */ public function getWeak() { - return $this->weak; + return isset($this->weak) ? $this->weak : false; + } + + public function hasWeak() + { + return isset($this->weak); + } + + public function clearWeak() + { + unset($this->weak); } /** @@ -378,16 +465,10 @@ public function setWeak($var) { GPBUtil::checkBool($var); $this->weak = $var; - $this->has_weak = true; return $this; } - public function hasWeak() - { - return $this->has_weak; - } - /** * The parser stores options it doesn't recognize here. See above. * @@ -410,15 +491,9 @@ public function setUninterpretedOption($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/FieldOptions/CType.php b/php/src/Google/Protobuf/Internal/FieldOptions/CType.php new file mode 100644 index 0000000000000..ba9eb4adb8f9a --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FieldOptions/CType.php @@ -0,0 +1,58 @@ +google.protobuf.FieldOptions.CType + */ +class CType +{ + /** + * Default mode. + * + * Generated from protobuf enum STRING = 0; + */ + const STRING = 0; + /** + * Generated from protobuf enum CORD = 1; + */ + const CORD = 1; + /** + * Generated from protobuf enum STRING_PIECE = 2; + */ + const STRING_PIECE = 2; + + private static $valueToName = [ + self::STRING => 'STRING', + self::CORD => 'CORD', + self::STRING_PIECE => 'STRING_PIECE', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(CType::class, \Google\Protobuf\Internal\FieldOptions_CType::class); + diff --git a/php/src/Google/Protobuf/Internal/FieldOptions/JSType.php b/php/src/Google/Protobuf/Internal/FieldOptions/JSType.php new file mode 100644 index 0000000000000..175a4330bbc1f --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FieldOptions/JSType.php @@ -0,0 +1,62 @@ +google.protobuf.FieldOptions.JSType + */ +class JSType +{ + /** + * Use the default type. + * + * Generated from protobuf enum JS_NORMAL = 0; + */ + const JS_NORMAL = 0; + /** + * Use JavaScript strings. + * + * Generated from protobuf enum JS_STRING = 1; + */ + const JS_STRING = 1; + /** + * Use JavaScript numbers. + * + * Generated from protobuf enum JS_NUMBER = 2; + */ + const JS_NUMBER = 2; + + private static $valueToName = [ + self::JS_NORMAL => 'JS_NORMAL', + self::JS_STRING => 'JS_STRING', + self::JS_NUMBER => 'JS_NUMBER', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(JSType::class, \Google\Protobuf\Internal\FieldOptions_JSType::class); + diff --git a/php/src/Google/Protobuf/Internal/FieldOptions_CType.php b/php/src/Google/Protobuf/Internal/FieldOptions_CType.php index 0f33072d11e3a..4d18783ee2ebb 100644 --- a/php/src/Google/Protobuf/Internal/FieldOptions_CType.php +++ b/php/src/Google/Protobuf/Internal/FieldOptions_CType.php @@ -4,24 +4,13 @@ namespace Google\Protobuf\Internal; -/** - * Protobuf enum Google\Protobuf\Internal - */ -class FieldOptions_CType -{ +if (false) { /** - * Default mode. - * - * Generated from protobuf enum STRING = 0; + * This class is deprecated. Use Google\Protobuf\Internal\FieldOptions\CType instead. + * @deprecated */ - const STRING = 0; - /** - * Generated from protobuf enum CORD = 1; - */ - const CORD = 1; - /** - * Generated from protobuf enum STRING_PIECE = 2; - */ - const STRING_PIECE = 2; + class FieldOptions_CType {} } +class_exists(FieldOptions\CType::class); +@trigger_error('Google\Protobuf\Internal\FieldOptions_CType is deprecated and will be removed in the next major release. Use Google\Protobuf\Internal\FieldOptions\CType instead', E_USER_DEPRECATED); diff --git a/php/src/Google/Protobuf/Internal/FieldOptions_JSType.php b/php/src/Google/Protobuf/Internal/FieldOptions_JSType.php index 73bdf3f20eb12..9db07822212db 100644 --- a/php/src/Google/Protobuf/Internal/FieldOptions_JSType.php +++ b/php/src/Google/Protobuf/Internal/FieldOptions_JSType.php @@ -4,28 +4,13 @@ namespace Google\Protobuf\Internal; -/** - * Protobuf enum Google\Protobuf\Internal - */ -class FieldOptions_JSType -{ +if (false) { /** - * Use the default type. - * - * Generated from protobuf enum JS_NORMAL = 0; + * This class is deprecated. Use Google\Protobuf\Internal\FieldOptions\JSType instead. + * @deprecated */ - const JS_NORMAL = 0; - /** - * Use JavaScript strings. - * - * Generated from protobuf enum JS_STRING = 1; - */ - const JS_STRING = 1; - /** - * Use JavaScript numbers. - * - * Generated from protobuf enum JS_NUMBER = 2; - */ - const JS_NUMBER = 2; + class FieldOptions_JSType {} } +class_exists(FieldOptions\JSType::class); +@trigger_error('Google\Protobuf\Internal\FieldOptions_JSType is deprecated and will be removed in the next major release. Use Google\Protobuf\Internal\FieldOptions\JSType instead', E_USER_DEPRECATED); diff --git a/php/src/Google/Protobuf/Internal/FileDescriptorProto.php b/php/src/Google/Protobuf/Internal/FileDescriptorProto.php index 9ee222d19b485..d96c7a78ecc51 100644 --- a/php/src/Google/Protobuf/Internal/FileDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/FileDescriptorProto.php @@ -22,29 +22,25 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string name = 1; */ - private $name = ''; - private $has_name = false; + protected $name = null; /** * e.g. "foo", "foo.bar", etc. * * Generated from protobuf field optional string package = 2; */ - private $package = ''; - private $has_package = false; + protected $package = null; /** * Names of files imported by this file. * * Generated from protobuf field repeated string dependency = 3; */ private $dependency; - private $has_dependency = false; /** * Indexes of the public imported files in the dependency list above. * * Generated from protobuf field repeated int32 public_dependency = 10; */ private $public_dependency; - private $has_public_dependency = false; /** * Indexes of the weak imported files in the dependency list. * For Google-internal migration only. Do not use. @@ -52,34 +48,28 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated int32 weak_dependency = 11; */ private $weak_dependency; - private $has_weak_dependency = false; /** * All top-level definitions in this file. * * Generated from protobuf field repeated .google.protobuf.DescriptorProto message_type = 4; */ private $message_type; - private $has_message_type = false; /** * Generated from protobuf field repeated .google.protobuf.EnumDescriptorProto enum_type = 5; */ private $enum_type; - private $has_enum_type = false; /** * Generated from protobuf field repeated .google.protobuf.ServiceDescriptorProto service = 6; */ private $service; - private $has_service = false; /** * Generated from protobuf field repeated .google.protobuf.FieldDescriptorProto extension = 7; */ private $extension; - private $has_extension = false; /** * Generated from protobuf field optional .google.protobuf.FileOptions options = 8; */ - private $options = null; - private $has_options = false; + protected $options = null; /** * This field contains optional information about the original source code. * You may safely remove this entire field without harming runtime @@ -88,20 +78,51 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional .google.protobuf.SourceCodeInfo source_code_info = 9; */ - private $source_code_info = null; - private $has_source_code_info = false; + protected $source_code_info = null; /** * The syntax of the proto file. * The supported values are "proto2" and "proto3". * * Generated from protobuf field optional string syntax = 12; */ - private $syntax = ''; - private $has_syntax = false; + protected $syntax = null; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * file name, relative to root of source tree + * @type string $package + * e.g. "foo", "foo.bar", etc. + * @type string[]|\Google\Protobuf\Internal\RepeatedField $dependency + * Names of files imported by this file. + * @type int[]|\Google\Protobuf\Internal\RepeatedField $public_dependency + * Indexes of the public imported files in the dependency list above. + * @type int[]|\Google\Protobuf\Internal\RepeatedField $weak_dependency + * Indexes of the weak imported files in the dependency list. + * For Google-internal migration only. Do not use. + * @type \Google\Protobuf\Internal\DescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $message_type + * All top-level definitions in this file. + * @type \Google\Protobuf\Internal\EnumDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $enum_type + * @type \Google\Protobuf\Internal\ServiceDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $service + * @type \Google\Protobuf\Internal\FieldDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $extension + * @type \Google\Protobuf\Internal\FileOptions $options + * @type \Google\Protobuf\Internal\SourceCodeInfo $source_code_info + * This field contains optional information about the original source code. + * You may safely remove this entire field without harming runtime + * functionality of the descriptors -- the information is needed only by + * development tools. + * @type string $syntax + * The syntax of the proto file. + * The supported values are "proto2" and "proto3". + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -112,7 +133,17 @@ public function __construct() { */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -126,16 +157,10 @@ public function setName($var) { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * e.g. "foo", "foo.bar", etc. * @@ -144,7 +169,17 @@ public function hasName() */ public function getPackage() { - return $this->package; + return isset($this->package) ? $this->package : ''; + } + + public function hasPackage() + { + return isset($this->package); + } + + public function clearPackage() + { + unset($this->package); } /** @@ -158,16 +193,10 @@ public function setPackage($var) { GPBUtil::checkString($var, True); $this->package = $var; - $this->has_package = true; return $this; } - public function hasPackage() - { - return $this->has_package; - } - /** * Names of files imported by this file. * @@ -190,16 +219,10 @@ public function setDependency($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING); $this->dependency = $arr; - $this->has_dependency = true; return $this; } - public function hasDependency() - { - return $this->has_dependency; - } - /** * Indexes of the public imported files in the dependency list above. * @@ -222,16 +245,10 @@ public function setPublicDependency($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); $this->public_dependency = $arr; - $this->has_public_dependency = true; return $this; } - public function hasPublicDependency() - { - return $this->has_public_dependency; - } - /** * Indexes of the weak imported files in the dependency list. * For Google-internal migration only. Do not use. @@ -256,16 +273,10 @@ public function setWeakDependency($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); $this->weak_dependency = $arr; - $this->has_weak_dependency = true; return $this; } - public function hasWeakDependency() - { - return $this->has_weak_dependency; - } - /** * All top-level definitions in this file. * @@ -288,16 +299,10 @@ public function setMessageType($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto::class); $this->message_type = $arr; - $this->has_message_type = true; return $this; } - public function hasMessageType() - { - return $this->has_message_type; - } - /** * Generated from protobuf field repeated .google.protobuf.EnumDescriptorProto enum_type = 5; * @return \Google\Protobuf\Internal\RepeatedField @@ -316,16 +321,10 @@ public function setEnumType($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto::class); $this->enum_type = $arr; - $this->has_enum_type = true; return $this; } - public function hasEnumType() - { - return $this->has_enum_type; - } - /** * Generated from protobuf field repeated .google.protobuf.ServiceDescriptorProto service = 6; * @return \Google\Protobuf\Internal\RepeatedField @@ -344,16 +343,10 @@ public function setService($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\ServiceDescriptorProto::class); $this->service = $arr; - $this->has_service = true; return $this; } - public function hasService() - { - return $this->has_service; - } - /** * Generated from protobuf field repeated .google.protobuf.FieldDescriptorProto extension = 7; * @return \Google\Protobuf\Internal\RepeatedField @@ -372,23 +365,27 @@ public function setExtension($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class); $this->extension = $arr; - $this->has_extension = true; return $this; } - public function hasExtension() - { - return $this->has_extension; - } - /** * Generated from protobuf field optional .google.protobuf.FileOptions options = 8; - * @return \Google\Protobuf\Internal\FileOptions + * @return \Google\Protobuf\Internal\FileOptions|null */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -400,16 +397,10 @@ public function setOptions($var) { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FileOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - /** * This field contains optional information about the original source code. * You may safely remove this entire field without harming runtime @@ -417,11 +408,21 @@ public function hasOptions() * development tools. * * Generated from protobuf field optional .google.protobuf.SourceCodeInfo source_code_info = 9; - * @return \Google\Protobuf\Internal\SourceCodeInfo + * @return \Google\Protobuf\Internal\SourceCodeInfo|null */ public function getSourceCodeInfo() { - return $this->source_code_info; + return isset($this->source_code_info) ? $this->source_code_info : null; + } + + public function hasSourceCodeInfo() + { + return isset($this->source_code_info); + } + + public function clearSourceCodeInfo() + { + unset($this->source_code_info); } /** @@ -438,16 +439,10 @@ public function setSourceCodeInfo($var) { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\SourceCodeInfo::class); $this->source_code_info = $var; - $this->has_source_code_info = true; return $this; } - public function hasSourceCodeInfo() - { - return $this->has_source_code_info; - } - /** * The syntax of the proto file. * The supported values are "proto2" and "proto3". @@ -457,7 +452,17 @@ public function hasSourceCodeInfo() */ public function getSyntax() { - return $this->syntax; + return isset($this->syntax) ? $this->syntax : ''; + } + + public function hasSyntax() + { + return isset($this->syntax); + } + + public function clearSyntax() + { + unset($this->syntax); } /** @@ -472,15 +477,9 @@ public function setSyntax($var) { GPBUtil::checkString($var, True); $this->syntax = $var; - $this->has_syntax = true; return $this; } - public function hasSyntax() - { - return $this->has_syntax; - } - } diff --git a/php/src/Google/Protobuf/Internal/FileDescriptorSet.php b/php/src/Google/Protobuf/Internal/FileDescriptorSet.php index 0b2cf95766da7..794e6347a35f7 100644 --- a/php/src/Google/Protobuf/Internal/FileDescriptorSet.php +++ b/php/src/Google/Protobuf/Internal/FileDescriptorSet.php @@ -22,11 +22,19 @@ class FileDescriptorSet extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated .google.protobuf.FileDescriptorProto file = 1; */ private $file; - private $has_file = false; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Google\Protobuf\Internal\FileDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $file + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -47,15 +55,9 @@ public function setFile($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FileDescriptorProto::class); $this->file = $arr; - $this->has_file = true; return $this; } - public function hasFile() - { - return $this->has_file; - } - } diff --git a/php/src/Google/Protobuf/Internal/FileOptions.php b/php/src/Google/Protobuf/Internal/FileOptions.php index c2dd5e08f38b4..6283b2ad7a2be 100644 --- a/php/src/Google/Protobuf/Internal/FileOptions.php +++ b/php/src/Google/Protobuf/Internal/FileOptions.php @@ -23,8 +23,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string java_package = 1; */ - private $java_package = ''; - private $has_java_package = false; + protected $java_package = null; /** * If set, all the classes from the .proto file are wrapped in a single * outer class with the given name. This applies to both Proto1 @@ -34,8 +33,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string java_outer_classname = 8; */ - private $java_outer_classname = ''; - private $has_java_outer_classname = false; + protected $java_outer_classname = null; /** * If set true, then the Java code generator will generate a separate .java * file for each top-level message, enum, and service defined in the .proto @@ -46,15 +44,14 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool java_multiple_files = 10 [default = false]; */ - private $java_multiple_files = false; - private $has_java_multiple_files = false; + protected $java_multiple_files = null; /** * This option does nothing. * * Generated from protobuf field optional bool java_generate_equals_and_hash = 20 [deprecated = true]; + * @deprecated */ - private $java_generate_equals_and_hash = false; - private $has_java_generate_equals_and_hash = false; + protected $java_generate_equals_and_hash = null; /** * If set true, then the Java2 code generator will generate code that * throws an exception whenever an attempt is made to assign a non-UTF-8 @@ -65,13 +62,11 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool java_string_check_utf8 = 27 [default = false]; */ - private $java_string_check_utf8 = false; - private $has_java_string_check_utf8 = false; + protected $java_string_check_utf8 = null; /** * Generated from protobuf field optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; */ - private $optimize_for = 0; - private $has_optimize_for = false; + protected $optimize_for = null; /** * Sets the Go package where structs generated from this .proto will be * placed. If omitted, the Go package will be derived from the following: @@ -81,8 +76,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string go_package = 11; */ - private $go_package = ''; - private $has_go_package = false; + protected $go_package = null; /** * Should generic services be generated in each language? "Generic" services * are not specific to any particular RPC system. They are generated by the @@ -96,23 +90,19 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool cc_generic_services = 16 [default = false]; */ - private $cc_generic_services = false; - private $has_cc_generic_services = false; + protected $cc_generic_services = null; /** * Generated from protobuf field optional bool java_generic_services = 17 [default = false]; */ - private $java_generic_services = false; - private $has_java_generic_services = false; + protected $java_generic_services = null; /** * Generated from protobuf field optional bool py_generic_services = 18 [default = false]; */ - private $py_generic_services = false; - private $has_py_generic_services = false; + protected $py_generic_services = null; /** - * Generated from protobuf field optional bool php_generic_services = 19 [default = false]; + * Generated from protobuf field optional bool php_generic_services = 42 [default = false]; */ - private $php_generic_services = false; - private $has_php_generic_services = false; + protected $php_generic_services = null; /** * Is this file deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -121,31 +111,27 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool deprecated = 23 [default = false]; */ - private $deprecated = false; - private $has_deprecated = false; + protected $deprecated = null; /** * Enables the use of arenas for the proto messages in this file. This applies * only to generated classes for C++. * - * Generated from protobuf field optional bool cc_enable_arenas = 31 [default = false]; + * Generated from protobuf field optional bool cc_enable_arenas = 31 [default = true]; */ - private $cc_enable_arenas = false; - private $has_cc_enable_arenas = false; + protected $cc_enable_arenas = null; /** * Sets the objective c class prefix which is prepended to all objective c * generated classes from this .proto. There is no default. * * Generated from protobuf field optional string objc_class_prefix = 36; */ - private $objc_class_prefix = ''; - private $has_objc_class_prefix = false; + protected $objc_class_prefix = null; /** * Namespace for generated classes; defaults to the package. * * Generated from protobuf field optional string csharp_namespace = 37; */ - private $csharp_namespace = ''; - private $has_csharp_namespace = false; + protected $csharp_namespace = null; /** * By default Swift generators will take the proto package and CamelCase it * replacing '.' with underscore and use that to prefix the types/symbols @@ -154,16 +140,14 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string swift_prefix = 39; */ - private $swift_prefix = ''; - private $has_swift_prefix = false; + protected $swift_prefix = null; /** * Sets the php class prefix which is prepended to all php generated classes * from this .proto. Default is empty. * * Generated from protobuf field optional string php_class_prefix = 40; */ - private $php_class_prefix = ''; - private $has_php_class_prefix = false; + protected $php_class_prefix = null; /** * Use this option to change the namespace of php generated classes. Default * is empty. When this option is empty, the package name will be used for @@ -171,19 +155,125 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string php_namespace = 41; */ - private $php_namespace = ''; - private $has_php_namespace = false; + protected $php_namespace = null; /** - * The parser stores options it doesn't recognize here. See above. + * Use this option to change the namespace of php generated metadata classes. + * Default is empty. When this option is empty, the proto file name will be + * used for determining the namespace. + * + * Generated from protobuf field optional string php_metadata_namespace = 44; + */ + protected $php_metadata_namespace = null; + /** + * Use this option to change the package of ruby generated classes. Default + * is empty. When this option is not set, the package name will be used for + * determining the ruby package. + * + * Generated from protobuf field optional string ruby_package = 45; + */ + protected $ruby_package = null; + /** + * The parser stores options it doesn't recognize here. + * See the documentation for the "Options" section above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $java_package + * Sets the Java package where classes generated from this .proto will be + * placed. By default, the proto package is used, but this is often + * inappropriate because proto packages do not normally start with backwards + * domain names. + * @type string $java_outer_classname + * If set, all the classes from the .proto file are wrapped in a single + * outer class with the given name. This applies to both Proto1 + * (equivalent to the old "--one_java_file" option) and Proto2 (where + * a .proto always translates to a single class, but you may want to + * explicitly choose the class name). + * @type bool $java_multiple_files + * If set true, then the Java code generator will generate a separate .java + * file for each top-level message, enum, and service defined in the .proto + * file. Thus, these types will *not* be nested inside the outer class + * named by java_outer_classname. However, the outer class will still be + * generated to contain the file's getDescriptor() method as well as any + * top-level extensions defined in the file. + * @type bool $java_generate_equals_and_hash + * This option does nothing. + * @type bool $java_string_check_utf8 + * If set true, then the Java2 code generator will generate code that + * throws an exception whenever an attempt is made to assign a non-UTF-8 + * byte sequence to a string field. + * Message reflection will do the same. + * However, an extension field still accepts non-UTF-8 byte sequences. + * This option has no effect on when used with the lite runtime. + * @type int $optimize_for + * @type string $go_package + * Sets the Go package where structs generated from this .proto will be + * placed. If omitted, the Go package will be derived from the following: + * - The basename of the package import path, if provided. + * - Otherwise, the package statement in the .proto file, if present. + * - Otherwise, the basename of the .proto file, without extension. + * @type bool $cc_generic_services + * Should generic services be generated in each language? "Generic" services + * are not specific to any particular RPC system. They are generated by the + * main code generators in each language (without additional plugins). + * Generic services were the only kind of service generation supported by + * early versions of google.protobuf. + * Generic services are now considered deprecated in favor of using plugins + * that generate code specific to your particular RPC system. Therefore, + * these default to false. Old code which depends on generic services should + * explicitly set them to true. + * @type bool $java_generic_services + * @type bool $py_generic_services + * @type bool $php_generic_services + * @type bool $deprecated + * Is this file deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for everything in the file, or it will be completely ignored; in the very + * least, this is a formalization for deprecating files. + * @type bool $cc_enable_arenas + * Enables the use of arenas for the proto messages in this file. This applies + * only to generated classes for C++. + * @type string $objc_class_prefix + * Sets the objective c class prefix which is prepended to all objective c + * generated classes from this .proto. There is no default. + * @type string $csharp_namespace + * Namespace for generated classes; defaults to the package. + * @type string $swift_prefix + * By default Swift generators will take the proto package and CamelCase it + * replacing '.' with underscore and use that to prefix the types/symbols + * defined. When this options is provided, they will use this value instead + * to prefix the types/symbols defined. + * @type string $php_class_prefix + * Sets the php class prefix which is prepended to all php generated classes + * from this .proto. Default is empty. + * @type string $php_namespace + * Use this option to change the namespace of php generated classes. Default + * is empty. When this option is empty, the package name will be used for + * determining the namespace. + * @type string $php_metadata_namespace + * Use this option to change the namespace of php generated metadata classes. + * Default is empty. When this option is empty, the proto file name will be + * used for determining the namespace. + * @type string $ruby_package + * Use this option to change the package of ruby generated classes. Default + * is empty. When this option is not set, the package name will be used for + * determining the ruby package. + * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option + * The parser stores options it doesn't recognize here. + * See the documentation for the "Options" section above. + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -197,7 +287,17 @@ public function __construct() { */ public function getJavaPackage() { - return $this->java_package; + return isset($this->java_package) ? $this->java_package : ''; + } + + public function hasJavaPackage() + { + return isset($this->java_package); + } + + public function clearJavaPackage() + { + unset($this->java_package); } /** @@ -214,16 +314,10 @@ public function setJavaPackage($var) { GPBUtil::checkString($var, True); $this->java_package = $var; - $this->has_java_package = true; return $this; } - public function hasJavaPackage() - { - return $this->has_java_package; - } - /** * If set, all the classes from the .proto file are wrapped in a single * outer class with the given name. This applies to both Proto1 @@ -236,7 +330,17 @@ public function hasJavaPackage() */ public function getJavaOuterClassname() { - return $this->java_outer_classname; + return isset($this->java_outer_classname) ? $this->java_outer_classname : ''; + } + + public function hasJavaOuterClassname() + { + return isset($this->java_outer_classname); + } + + public function clearJavaOuterClassname() + { + unset($this->java_outer_classname); } /** @@ -254,16 +358,10 @@ public function setJavaOuterClassname($var) { GPBUtil::checkString($var, True); $this->java_outer_classname = $var; - $this->has_java_outer_classname = true; return $this; } - public function hasJavaOuterClassname() - { - return $this->has_java_outer_classname; - } - /** * If set true, then the Java code generator will generate a separate .java * file for each top-level message, enum, and service defined in the .proto @@ -277,7 +375,17 @@ public function hasJavaOuterClassname() */ public function getJavaMultipleFiles() { - return $this->java_multiple_files; + return isset($this->java_multiple_files) ? $this->java_multiple_files : false; + } + + public function hasJavaMultipleFiles() + { + return isset($this->java_multiple_files); + } + + public function clearJavaMultipleFiles() + { + unset($this->java_multiple_files); } /** @@ -296,25 +404,33 @@ public function setJavaMultipleFiles($var) { GPBUtil::checkBool($var); $this->java_multiple_files = $var; - $this->has_java_multiple_files = true; return $this; } - public function hasJavaMultipleFiles() - { - return $this->has_java_multiple_files; - } - /** * This option does nothing. * * Generated from protobuf field optional bool java_generate_equals_and_hash = 20 [deprecated = true]; * @return bool + * @deprecated */ public function getJavaGenerateEqualsAndHash() { - return $this->java_generate_equals_and_hash; + @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED); + return isset($this->java_generate_equals_and_hash) ? $this->java_generate_equals_and_hash : false; + } + + public function hasJavaGenerateEqualsAndHash() + { + @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED); + return isset($this->java_generate_equals_and_hash); + } + + public function clearJavaGenerateEqualsAndHash() + { + @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED); + unset($this->java_generate_equals_and_hash); } /** @@ -323,21 +439,17 @@ public function getJavaGenerateEqualsAndHash() * Generated from protobuf field optional bool java_generate_equals_and_hash = 20 [deprecated = true]; * @param bool $var * @return $this + * @deprecated */ public function setJavaGenerateEqualsAndHash($var) { + @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED); GPBUtil::checkBool($var); $this->java_generate_equals_and_hash = $var; - $this->has_java_generate_equals_and_hash = true; return $this; } - public function hasJavaGenerateEqualsAndHash() - { - return $this->has_java_generate_equals_and_hash; - } - /** * If set true, then the Java2 code generator will generate code that * throws an exception whenever an attempt is made to assign a non-UTF-8 @@ -351,7 +463,17 @@ public function hasJavaGenerateEqualsAndHash() */ public function getJavaStringCheckUtf8() { - return $this->java_string_check_utf8; + return isset($this->java_string_check_utf8) ? $this->java_string_check_utf8 : false; + } + + public function hasJavaStringCheckUtf8() + { + return isset($this->java_string_check_utf8); + } + + public function clearJavaStringCheckUtf8() + { + unset($this->java_string_check_utf8); } /** @@ -370,23 +492,27 @@ public function setJavaStringCheckUtf8($var) { GPBUtil::checkBool($var); $this->java_string_check_utf8 = $var; - $this->has_java_string_check_utf8 = true; return $this; } - public function hasJavaStringCheckUtf8() - { - return $this->has_java_string_check_utf8; - } - /** * Generated from protobuf field optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; * @return int */ public function getOptimizeFor() { - return $this->optimize_for; + return isset($this->optimize_for) ? $this->optimize_for : 0; + } + + public function hasOptimizeFor() + { + return isset($this->optimize_for); + } + + public function clearOptimizeFor() + { + unset($this->optimize_for); } /** @@ -396,18 +522,12 @@ public function getOptimizeFor() */ public function setOptimizeFor($var) { - GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FileOptions_OptimizeMode::class); + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FileOptions\OptimizeMode::class); $this->optimize_for = $var; - $this->has_optimize_for = true; return $this; } - public function hasOptimizeFor() - { - return $this->has_optimize_for; - } - /** * Sets the Go package where structs generated from this .proto will be * placed. If omitted, the Go package will be derived from the following: @@ -420,7 +540,17 @@ public function hasOptimizeFor() */ public function getGoPackage() { - return $this->go_package; + return isset($this->go_package) ? $this->go_package : ''; + } + + public function hasGoPackage() + { + return isset($this->go_package); + } + + public function clearGoPackage() + { + unset($this->go_package); } /** @@ -438,16 +568,10 @@ public function setGoPackage($var) { GPBUtil::checkString($var, True); $this->go_package = $var; - $this->has_go_package = true; return $this; } - public function hasGoPackage() - { - return $this->has_go_package; - } - /** * Should generic services be generated in each language? "Generic" services * are not specific to any particular RPC system. They are generated by the @@ -464,7 +588,17 @@ public function hasGoPackage() */ public function getCcGenericServices() { - return $this->cc_generic_services; + return isset($this->cc_generic_services) ? $this->cc_generic_services : false; + } + + public function hasCcGenericServices() + { + return isset($this->cc_generic_services); + } + + public function clearCcGenericServices() + { + unset($this->cc_generic_services); } /** @@ -486,23 +620,27 @@ public function setCcGenericServices($var) { GPBUtil::checkBool($var); $this->cc_generic_services = $var; - $this->has_cc_generic_services = true; return $this; } - public function hasCcGenericServices() - { - return $this->has_cc_generic_services; - } - /** * Generated from protobuf field optional bool java_generic_services = 17 [default = false]; * @return bool */ public function getJavaGenericServices() { - return $this->java_generic_services; + return isset($this->java_generic_services) ? $this->java_generic_services : false; + } + + public function hasJavaGenericServices() + { + return isset($this->java_generic_services); + } + + public function clearJavaGenericServices() + { + unset($this->java_generic_services); } /** @@ -514,23 +652,27 @@ public function setJavaGenericServices($var) { GPBUtil::checkBool($var); $this->java_generic_services = $var; - $this->has_java_generic_services = true; return $this; } - public function hasJavaGenericServices() - { - return $this->has_java_generic_services; - } - /** * Generated from protobuf field optional bool py_generic_services = 18 [default = false]; * @return bool */ public function getPyGenericServices() { - return $this->py_generic_services; + return isset($this->py_generic_services) ? $this->py_generic_services : false; + } + + public function hasPyGenericServices() + { + return isset($this->py_generic_services); + } + + public function clearPyGenericServices() + { + unset($this->py_generic_services); } /** @@ -542,27 +684,31 @@ public function setPyGenericServices($var) { GPBUtil::checkBool($var); $this->py_generic_services = $var; - $this->has_py_generic_services = true; return $this; } - public function hasPyGenericServices() - { - return $this->has_py_generic_services; - } - /** - * Generated from protobuf field optional bool php_generic_services = 19 [default = false]; + * Generated from protobuf field optional bool php_generic_services = 42 [default = false]; * @return bool */ public function getPhpGenericServices() { - return $this->php_generic_services; + return isset($this->php_generic_services) ? $this->php_generic_services : false; + } + + public function hasPhpGenericServices() + { + return isset($this->php_generic_services); + } + + public function clearPhpGenericServices() + { + unset($this->php_generic_services); } /** - * Generated from protobuf field optional bool php_generic_services = 19 [default = false]; + * Generated from protobuf field optional bool php_generic_services = 42 [default = false]; * @param bool $var * @return $this */ @@ -570,16 +716,10 @@ public function setPhpGenericServices($var) { GPBUtil::checkBool($var); $this->php_generic_services = $var; - $this->has_php_generic_services = true; return $this; } - public function hasPhpGenericServices() - { - return $this->has_php_generic_services; - } - /** * Is this file deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -591,7 +731,17 @@ public function hasPhpGenericServices() */ public function getDeprecated() { - return $this->deprecated; + return isset($this->deprecated) ? $this->deprecated : false; + } + + public function hasDeprecated() + { + return isset($this->deprecated); + } + + public function clearDeprecated() + { + unset($this->deprecated); } /** @@ -608,33 +758,37 @@ public function setDeprecated($var) { GPBUtil::checkBool($var); $this->deprecated = $var; - $this->has_deprecated = true; return $this; } - public function hasDeprecated() - { - return $this->has_deprecated; - } - /** * Enables the use of arenas for the proto messages in this file. This applies * only to generated classes for C++. * - * Generated from protobuf field optional bool cc_enable_arenas = 31 [default = false]; + * Generated from protobuf field optional bool cc_enable_arenas = 31 [default = true]; * @return bool */ public function getCcEnableArenas() { - return $this->cc_enable_arenas; + return isset($this->cc_enable_arenas) ? $this->cc_enable_arenas : false; + } + + public function hasCcEnableArenas() + { + return isset($this->cc_enable_arenas); + } + + public function clearCcEnableArenas() + { + unset($this->cc_enable_arenas); } /** * Enables the use of arenas for the proto messages in this file. This applies * only to generated classes for C++. * - * Generated from protobuf field optional bool cc_enable_arenas = 31 [default = false]; + * Generated from protobuf field optional bool cc_enable_arenas = 31 [default = true]; * @param bool $var * @return $this */ @@ -642,16 +796,10 @@ public function setCcEnableArenas($var) { GPBUtil::checkBool($var); $this->cc_enable_arenas = $var; - $this->has_cc_enable_arenas = true; return $this; } - public function hasCcEnableArenas() - { - return $this->has_cc_enable_arenas; - } - /** * Sets the objective c class prefix which is prepended to all objective c * generated classes from this .proto. There is no default. @@ -661,7 +809,17 @@ public function hasCcEnableArenas() */ public function getObjcClassPrefix() { - return $this->objc_class_prefix; + return isset($this->objc_class_prefix) ? $this->objc_class_prefix : ''; + } + + public function hasObjcClassPrefix() + { + return isset($this->objc_class_prefix); + } + + public function clearObjcClassPrefix() + { + unset($this->objc_class_prefix); } /** @@ -676,16 +834,10 @@ public function setObjcClassPrefix($var) { GPBUtil::checkString($var, True); $this->objc_class_prefix = $var; - $this->has_objc_class_prefix = true; return $this; } - public function hasObjcClassPrefix() - { - return $this->has_objc_class_prefix; - } - /** * Namespace for generated classes; defaults to the package. * @@ -694,7 +846,17 @@ public function hasObjcClassPrefix() */ public function getCsharpNamespace() { - return $this->csharp_namespace; + return isset($this->csharp_namespace) ? $this->csharp_namespace : ''; + } + + public function hasCsharpNamespace() + { + return isset($this->csharp_namespace); + } + + public function clearCsharpNamespace() + { + unset($this->csharp_namespace); } /** @@ -708,16 +870,10 @@ public function setCsharpNamespace($var) { GPBUtil::checkString($var, True); $this->csharp_namespace = $var; - $this->has_csharp_namespace = true; return $this; } - public function hasCsharpNamespace() - { - return $this->has_csharp_namespace; - } - /** * By default Swift generators will take the proto package and CamelCase it * replacing '.' with underscore and use that to prefix the types/symbols @@ -729,7 +885,17 @@ public function hasCsharpNamespace() */ public function getSwiftPrefix() { - return $this->swift_prefix; + return isset($this->swift_prefix) ? $this->swift_prefix : ''; + } + + public function hasSwiftPrefix() + { + return isset($this->swift_prefix); + } + + public function clearSwiftPrefix() + { + unset($this->swift_prefix); } /** @@ -746,16 +912,10 @@ public function setSwiftPrefix($var) { GPBUtil::checkString($var, True); $this->swift_prefix = $var; - $this->has_swift_prefix = true; return $this; } - public function hasSwiftPrefix() - { - return $this->has_swift_prefix; - } - /** * Sets the php class prefix which is prepended to all php generated classes * from this .proto. Default is empty. @@ -765,7 +925,17 @@ public function hasSwiftPrefix() */ public function getPhpClassPrefix() { - return $this->php_class_prefix; + return isset($this->php_class_prefix) ? $this->php_class_prefix : ''; + } + + public function hasPhpClassPrefix() + { + return isset($this->php_class_prefix); + } + + public function clearPhpClassPrefix() + { + unset($this->php_class_prefix); } /** @@ -780,16 +950,10 @@ public function setPhpClassPrefix($var) { GPBUtil::checkString($var, True); $this->php_class_prefix = $var; - $this->has_php_class_prefix = true; return $this; } - public function hasPhpClassPrefix() - { - return $this->has_php_class_prefix; - } - /** * Use this option to change the namespace of php generated classes. Default * is empty. When this option is empty, the package name will be used for @@ -800,7 +964,17 @@ public function hasPhpClassPrefix() */ public function getPhpNamespace() { - return $this->php_namespace; + return isset($this->php_namespace) ? $this->php_namespace : ''; + } + + public function hasPhpNamespace() + { + return isset($this->php_namespace); + } + + public function clearPhpNamespace() + { + unset($this->php_namespace); } /** @@ -816,18 +990,93 @@ public function setPhpNamespace($var) { GPBUtil::checkString($var, True); $this->php_namespace = $var; - $this->has_php_namespace = true; return $this; } - public function hasPhpNamespace() + /** + * Use this option to change the namespace of php generated metadata classes. + * Default is empty. When this option is empty, the proto file name will be + * used for determining the namespace. + * + * Generated from protobuf field optional string php_metadata_namespace = 44; + * @return string + */ + public function getPhpMetadataNamespace() + { + return isset($this->php_metadata_namespace) ? $this->php_metadata_namespace : ''; + } + + public function hasPhpMetadataNamespace() + { + return isset($this->php_metadata_namespace); + } + + public function clearPhpMetadataNamespace() { - return $this->has_php_namespace; + unset($this->php_metadata_namespace); } /** - * The parser stores options it doesn't recognize here. See above. + * Use this option to change the namespace of php generated metadata classes. + * Default is empty. When this option is empty, the proto file name will be + * used for determining the namespace. + * + * Generated from protobuf field optional string php_metadata_namespace = 44; + * @param string $var + * @return $this + */ + public function setPhpMetadataNamespace($var) + { + GPBUtil::checkString($var, True); + $this->php_metadata_namespace = $var; + + return $this; + } + + /** + * Use this option to change the package of ruby generated classes. Default + * is empty. When this option is not set, the package name will be used for + * determining the ruby package. + * + * Generated from protobuf field optional string ruby_package = 45; + * @return string + */ + public function getRubyPackage() + { + return isset($this->ruby_package) ? $this->ruby_package : ''; + } + + public function hasRubyPackage() + { + return isset($this->ruby_package); + } + + public function clearRubyPackage() + { + unset($this->ruby_package); + } + + /** + * Use this option to change the package of ruby generated classes. Default + * is empty. When this option is not set, the package name will be used for + * determining the ruby package. + * + * Generated from protobuf field optional string ruby_package = 45; + * @param string $var + * @return $this + */ + public function setRubyPackage($var) + { + GPBUtil::checkString($var, True); + $this->ruby_package = $var; + + return $this; + } + + /** + * The parser stores options it doesn't recognize here. + * See the documentation for the "Options" section above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; * @return \Google\Protobuf\Internal\RepeatedField @@ -838,7 +1087,8 @@ public function getUninterpretedOption() } /** - * The parser stores options it doesn't recognize here. See above. + * The parser stores options it doesn't recognize here. + * See the documentation for the "Options" section above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; * @param \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $var @@ -848,15 +1098,9 @@ public function setUninterpretedOption($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php b/php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php new file mode 100644 index 0000000000000..0df27b53359dd --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php @@ -0,0 +1,64 @@ +google.protobuf.FileOptions.OptimizeMode + */ +class OptimizeMode +{ + /** + * Generate complete code for parsing, serialization, + * + * Generated from protobuf enum SPEED = 1; + */ + const SPEED = 1; + /** + * etc. + * + * Generated from protobuf enum CODE_SIZE = 2; + */ + const CODE_SIZE = 2; + /** + * Generate code using MessageLite and the lite runtime. + * + * Generated from protobuf enum LITE_RUNTIME = 3; + */ + const LITE_RUNTIME = 3; + + private static $valueToName = [ + self::SPEED => 'SPEED', + self::CODE_SIZE => 'CODE_SIZE', + self::LITE_RUNTIME => 'LITE_RUNTIME', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(OptimizeMode::class, \Google\Protobuf\Internal\FileOptions_OptimizeMode::class); + diff --git a/php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php b/php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php index 4dd56ef89336e..8926e63baa01f 100644 --- a/php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php +++ b/php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php @@ -4,30 +4,13 @@ namespace Google\Protobuf\Internal; -/** - * Generated classes can be optimized for speed or code size. - * - * Protobuf enum Google\Protobuf\Internal - */ -class FileOptions_OptimizeMode -{ +if (false) { /** - * Generate complete code for parsing, serialization, - * - * Generated from protobuf enum SPEED = 1; + * This class is deprecated. Use Google\Protobuf\Internal\FileOptions\OptimizeMode instead. + * @deprecated */ - const SPEED = 1; - /** - * etc. - * - * Generated from protobuf enum CODE_SIZE = 2; - */ - const CODE_SIZE = 2; - /** - * Generate code using MessageLite and the lite runtime. - * - * Generated from protobuf enum LITE_RUNTIME = 3; - */ - const LITE_RUNTIME = 3; + class FileOptions_OptimizeMode {} } +class_exists(FileOptions\OptimizeMode::class); +@trigger_error('Google\Protobuf\Internal\FileOptions_OptimizeMode is deprecated and will be removed in the next major release. Use Google\Protobuf\Internal\FileOptions\OptimizeMode instead', E_USER_DEPRECATED); diff --git a/php/src/Google/Protobuf/Internal/GPBJsonWire.php b/php/src/Google/Protobuf/Internal/GPBJsonWire.php index 97789356c2efc..43f4745dd1907 100644 --- a/php/src/Google/Protobuf/Internal/GPBJsonWire.php +++ b/php/src/Google/Protobuf/Internal/GPBJsonWire.php @@ -38,19 +38,26 @@ class GPBJsonWire public static function serializeFieldToStream( $value, $field, - &$output) + &$output, $has_field_name = true) { - $output->writeRaw("\"", 1); - $field_name = GPBJsonWire::formatFieldName($field); - $output->writeRaw($field_name, strlen($field_name)); - $output->writeRaw("\":", 2); - return static::serializeFieldValueToStream($value, $field, $output); + if ($has_field_name) { + $output->writeRaw("\"", 1); + $field_name = GPBJsonWire::formatFieldName($field); + $output->writeRaw($field_name, strlen($field_name)); + $output->writeRaw("\":", 2); + } + return static::serializeFieldValueToStream( + $value, + $field, + $output, + !$has_field_name); } - private static function serializeFieldValueToStream( + public static function serializeFieldValueToStream( $values, $field, - &$output) + &$output, + $is_well_known = false) { if ($field->isMap()) { $output->writeRaw("{", 1); @@ -84,7 +91,8 @@ private static function serializeFieldValueToStream( if (!static::serializeSingularFieldValueToStream( $key, $key_field, - $output)) { + $output, + $is_well_known)) { return false; } if ($additional_quote) { @@ -94,7 +102,8 @@ private static function serializeFieldValueToStream( if (!static::serializeSingularFieldValueToStream( $value, $value_field, - $output)) { + $output, + $is_well_known)) { return false; } } @@ -112,7 +121,8 @@ private static function serializeFieldValueToStream( if (!static::serializeSingularFieldValueToStream( $value, $field, - $output)) { + $output, + $is_well_known)) { return false; } } @@ -122,14 +132,15 @@ private static function serializeFieldValueToStream( return static::serializeSingularFieldValueToStream( $values, $field, - $output); + $output, + $is_well_known); } } private static function serializeSingularFieldValueToStream( $value, $field, - &$output) + &$output, $is_well_known = false) { switch ($field->getType()) { case GPBType::SFIXED32: @@ -186,6 +197,10 @@ private static function serializeSingularFieldValueToStream( break; case GPBType::ENUM: $enum_desc = $field->getEnumType(); + if ($enum_desc->getClass() === "Google\Protobuf\NullValue") { + $output->writeRaw("null", 4); + break; + } $enum_value_desc = $enum_desc->getValueByNumber($value); if (!is_null($enum_value_desc)) { $str_value = $enum_value_desc->getName(); @@ -205,9 +220,13 @@ private static function serializeSingularFieldValueToStream( } break; case GPBType::BYTES: - $value = base64_encode($value); + $bytes_value = base64_encode($value); + $output->writeRaw("\"", 1); + $output->writeRaw($bytes_value, strlen($bytes_value)); + $output->writeRaw("\"", 1); + break; case GPBType::STRING: - $value = json_encode($value); + $value = json_encode($value, JSON_UNESCAPED_UNICODE); $output->writeRaw($value, strlen($value)); break; // case GPBType::GROUP: diff --git a/php/src/Google/Protobuf/Internal/GPBUtil.php b/php/src/Google/Protobuf/Internal/GPBUtil.php index 6fe360687dfc4..cd65d8b7d4536 100644 --- a/php/src/Google/Protobuf/Internal/GPBUtil.php +++ b/php/src/Google/Protobuf/Internal/GPBUtil.php @@ -32,12 +32,30 @@ namespace Google\Protobuf\Internal; +use Google\Protobuf\Duration; +use Google\Protobuf\FieldMask; use Google\Protobuf\Internal\GPBType; use Google\Protobuf\Internal\RepeatedField; use Google\Protobuf\Internal\MapField; +function camel2underscore($input) { + preg_match_all( + '!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', + $input, + $matches); + $ret = $matches[0]; + foreach ($ret as &$match) { + $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match); + } + return implode('_', $ret); +} + class GPBUtil { + const NANOS_PER_MILLISECOND = 1000000; + const NANOS_PER_MICROSECOND = 1000; + const TYPE_URL_PREFIX = 'type.googleapis.com/'; + public static function divideInt64ToInt32($value, &$high, &$low, $trim = false) { $isNeg = (bccomp($value, 0) < 0); @@ -150,7 +168,7 @@ public static function checkUint64(&$var) public static function checkFloat(&$var) { if (is_float($var) || is_numeric($var)) { - $var = floatval($var); + $var = unpack("f", pack("f", $var))[1]; } else { throw new \Exception("Expect float."); } @@ -173,10 +191,10 @@ public static function checkBool(&$var) $var = boolval($var); } - public static function checkMessage(&$var, $klass) + public static function checkMessage(&$var, $klass, $newClass = null) { if (!$var instanceof $klass && !is_null($var)) { - throw new \Exception("Expect message."); + throw new \Exception("Expect $klass."); } } @@ -197,9 +215,10 @@ public static function checkRepeatedField(&$var, $type, $klass = null) "Expect repeated field of different type."); } if ($var->getType() === GPBType::MESSAGE && - $var->getClass() !== $klass) { + $var->getClass() !== $klass && + $var->getLegacyClass() !== $klass) { throw new \Exception( - "Expect repeated field of different message."); + "Expect repeated field of " . $klass . "."); } return $var; } @@ -224,9 +243,10 @@ public static function checkMapField(&$var, $key_type, $value_type, $klass = nul throw new \Exception("Expect map field of value type."); } if ($var->getValueType() === GPBType::MESSAGE && - $var->getValueClass() !== $klass) { + $var->getValueClass() !== $klass && + $var->getLegacyValueClass() !== $klass) { throw new \Exception( - "Expect map field of different value message."); + "Expect map field of " . $klass . "."); } return $var; } @@ -252,34 +272,61 @@ public static function getClassNamePrefix( return $prefix; } - $reserved_words = array("Empty", "ECHO", "ARRAY"); - foreach ($reserved_words as $reserved_word) { - if ($classname === $reserved_word) { - if ($file_proto->getPackage() === "google.protobuf") { - return "GPB"; - } else { - return "PB"; - } + $reserved_words = array( + "abstract"=>0, "and"=>0, "array"=>0, "as"=>0, "break"=>0, + "callable"=>0, "case"=>0, "catch"=>0, "class"=>0, "clone"=>0, + "const"=>0, "continue"=>0, "declare"=>0, "default"=>0, "die"=>0, + "do"=>0, "echo"=>0, "else"=>0, "elseif"=>0, "empty"=>0, + "enddeclare"=>0, "endfor"=>0, "endforeach"=>0, "endif"=>0, + "endswitch"=>0, "endwhile"=>0, "eval"=>0, "exit"=>0, "extends"=>0, + "final"=>0, "for"=>0, "foreach"=>0, "function"=>0, "global"=>0, + "goto"=>0, "if"=>0, "implements"=>0, "include"=>0, + "include_once"=>0, "instanceof"=>0, "insteadof"=>0, "interface"=>0, + "isset"=>0, "list"=>0, "namespace"=>0, "new"=>0, "or"=>0, + "print"=>0, "private"=>0, "protected"=>0, "public"=>0, "require"=>0, + "require_once"=>0, "return"=>0, "static"=>0, "switch"=>0, + "throw"=>0, "trait"=>0, "try"=>0, "unset"=>0, "use"=>0, "var"=>0, + "while"=>0, "xor"=>0, "int"=>0, "float"=>0, "bool"=>0, "string"=>0, + "true"=>0, "false"=>0, "null"=>0, "void"=>0, "iterable"=>0 + ); + + if (array_key_exists(strtolower($classname), $reserved_words)) { + if ($file_proto->getPackage() === "google.protobuf") { + return "GPB"; + } else { + return "PB"; } } return ""; } - public static function getClassNameWithoutPackage( + public static function getLegacyClassNameWithoutPackage( $name, $file_proto) { - $classname = implode('_', array_map('ucwords', explode('.', $name))); + $classname = implode('_', explode('.', $name)); return static::getClassNamePrefix($classname, $file_proto) . $classname; } + public static function getClassNameWithoutPackage( + $name, + $file_proto) + { + $parts = explode('.', $name); + foreach ($parts as $i => $part) { + $parts[$i] = static::getClassNamePrefix($parts[$i], $file_proto) . $parts[$i]; + } + return implode('\\', $parts); + } + public static function getFullClassName( $proto, $containing, $file_proto, &$message_name_without_package, &$classname, + &$legacy_classname, &$fullname) { // Full name needs to start with '.'. @@ -291,32 +338,47 @@ public static function getFullClassName( $package = $file_proto->getPackage(); if ($package === "") { - $fullname = "." . $message_name_without_package; + $fullname = $message_name_without_package; } else { - $fullname = "." . $package . "." . $message_name_without_package; + $fullname = $package . "." . $message_name_without_package; } $class_name_without_package = static::getClassNameWithoutPackage($message_name_without_package, $file_proto); + $legacy_class_name_without_package = + static::getLegacyClassNameWithoutPackage( + $message_name_without_package, $file_proto); $option = $file_proto->getOptions(); if (!is_null($option) && $option->hasPhpNamespace()) { $namespace = $option->getPhpNamespace(); if ($namespace !== "") { $classname = $namespace . "\\" . $class_name_without_package; + $legacy_classname = + $namespace . "\\" . $legacy_class_name_without_package; return; } else { $classname = $class_name_without_package; + $legacy_classname = $legacy_class_name_without_package; return; } } if ($package === "") { $classname = $class_name_without_package; + $legacy_classname = $legacy_class_name_without_package; } else { + $parts = array_map('ucwords', explode('.', $package)); + foreach ($parts as $i => $part) { + $parts[$i] = self::getClassNamePrefix($part, $file_proto).$part; + } $classname = + implode('\\', $parts) . + "\\".self::getClassNamePrefix($class_name_without_package,$file_proto). + $class_name_without_package; + $legacy_classname = implode('\\', array_map('ucwords', explode('.', $package))). - "\\".$class_name_without_package; + "\\".$legacy_class_name_without_package; } } @@ -340,4 +402,214 @@ public static function combineInt32ToInt64($high, $low) } return $result; } + + public static function parseTimestamp($timestamp) + { + // prevent parsing timestamps containing with the non-existent year "0000" + // DateTime::createFromFormat parses without failing but as a nonsensical date + if (substr($timestamp, 0, 4) === "0000") { + throw new \Exception("Year cannot be zero."); + } + // prevent parsing timestamps ending with a lowercase z + if (substr($timestamp, -1, 1) === "z") { + throw new \Exception("Timezone cannot be a lowercase z."); + } + + $nanoseconds = 0; + $periodIndex = strpos($timestamp, "."); + if ($periodIndex !== false) { + $nanosecondsLength = 0; + // find the next non-numeric character in the timestamp to calculate + // the length of the nanoseconds text + for ($i = $periodIndex + 1, $length = strlen($timestamp); $i < $length; $i++) { + if (!is_numeric($timestamp[$i])) { + $nanosecondsLength = $i - ($periodIndex + 1); + break; + } + } + if ($nanosecondsLength % 3 !== 0) { + throw new \Exception("Nanoseconds must be disible by 3."); + } + if ($nanosecondsLength > 9) { + throw new \Exception("Nanoseconds must be in the range of 0 to 999,999,999 nanoseconds."); + } + if ($nanosecondsLength > 0) { + $nanoseconds = substr($timestamp, $periodIndex + 1, $nanosecondsLength); + $nanoseconds = intval($nanoseconds); + + // remove the nanoseconds and preceding period from the timestamp + $date = substr($timestamp, 0, $periodIndex); + $timezone = substr($timestamp, $periodIndex + $nanosecondsLength + 1); + $timestamp = $date.$timezone; + } + } + + $date = \DateTime::createFromFormat(\DateTime::RFC3339, $timestamp, new \DateTimeZone("UTC")); + if ($date === false) { + throw new \Exception("Invalid RFC 3339 timestamp."); + } + + $value = new \Google\Protobuf\Timestamp(); + $seconds = $date->format("U"); + $value->setSeconds($seconds); + $value->setNanos($nanoseconds); + return $value; + } + + public static function formatTimestamp($value) + { + if (bccomp($value->getSeconds(), "253402300800") != -1) { + throw new GPBDecodeException("Duration number too large."); + } + if (bccomp($value->getSeconds(), "-62135596801") != 1) { + throw new GPBDecodeException("Duration number too small."); + } + $nanoseconds = static::getNanosecondsForTimestamp($value->getNanos()); + if (!empty($nanoseconds)) { + $nanoseconds = ".".$nanoseconds; + } + $date = new \DateTime('@'.$value->getSeconds(), new \DateTimeZone("UTC")); + return $date->format("Y-m-d\TH:i:s".$nanoseconds."\Z"); + } + + public static function parseDuration($value) + { + if (strlen($value) < 2 || substr($value, -1) !== "s") { + throw new GPBDecodeException("Missing s after duration string"); + } + $number = substr($value, 0, -1); + if (bccomp($number, "315576000001") != -1) { + throw new GPBDecodeException("Duration number too large."); + } + if (bccomp($number, "-315576000001") != 1) { + throw new GPBDecodeException("Duration number too small."); + } + $pos = strrpos($number, "."); + if ($pos !== false) { + $seconds = substr($number, 0, $pos); + if (bccomp($seconds, 0) < 0) { + $nanos = bcmul("0" . substr($number, $pos), -1000000000); + } else { + $nanos = bcmul("0" . substr($number, $pos), 1000000000); + } + } else { + $seconds = $number; + $nanos = 0; + } + $duration = new Duration(); + $duration->setSeconds($seconds); + $duration->setNanos($nanos); + return $duration; + } + + public static function formatDuration($value) + { + if (bccomp($value->getSeconds(), '315576000001') != -1) { + throw new GPBDecodeException('Duration number too large.'); + } + if (bccomp($value->getSeconds(), '-315576000001') != 1) { + throw new GPBDecodeException('Duration number too small.'); + } + + $nanos = $value->getNanos(); + if ($nanos === 0) { + return (string) $value->getSeconds(); + } + + if ($nanos % 1000000 === 0) { + $digits = 3; + } elseif ($nanos % 1000 === 0) { + $digits = 6; + } else { + $digits = 9; + } + + $nanos = bcdiv($nanos, '1000000000', $digits); + return bcadd($value->getSeconds(), $nanos, $digits); + } + + public static function parseFieldMask($paths_string) + { + $field_mask = new FieldMask(); + if (strlen($paths_string) === 0) { + return $field_mask; + } + $path_strings = explode(",", $paths_string); + $paths = $field_mask->getPaths(); + foreach($path_strings as &$path_string) { + $field_strings = explode(".", $path_string); + foreach($field_strings as &$field_string) { + $field_string = camel2underscore($field_string); + } + $path_string = implode(".", $field_strings); + $paths[] = $path_string; + } + return $field_mask; + } + + public static function formatFieldMask($field_mask) + { + $converted_paths = []; + foreach($field_mask->getPaths() as $path) { + $fields = explode('.', $path); + $converted_path = []; + foreach ($fields as $field) { + $segments = explode('_', $field); + $start = true; + $converted_segments = ""; + foreach($segments as $segment) { + if (!$start) { + $converted = ucfirst($segment); + } else { + $converted = $segment; + $start = false; + } + $converted_segments .= $converted; + } + $converted_path []= $converted_segments; + } + $converted_path = implode(".", $converted_path); + $converted_paths []= $converted_path; + } + return implode(",", $converted_paths); + } + + public static function getNanosecondsForTimestamp($nanoseconds) + { + if ($nanoseconds == 0) { + return ''; + } + if ($nanoseconds % static::NANOS_PER_MILLISECOND == 0) { + return sprintf('%03d', $nanoseconds / static::NANOS_PER_MILLISECOND); + } + if ($nanoseconds % static::NANOS_PER_MICROSECOND == 0) { + return sprintf('%06d', $nanoseconds / static::NANOS_PER_MICROSECOND); + } + return sprintf('%09d', $nanoseconds); + } + + public static function hasSpecialJsonMapping($msg) + { + return is_a($msg, 'Google\Protobuf\Any') || + is_a($msg, "Google\Protobuf\ListValue") || + is_a($msg, "Google\Protobuf\Struct") || + is_a($msg, "Google\Protobuf\Value") || + is_a($msg, "Google\Protobuf\Duration") || + is_a($msg, "Google\Protobuf\Timestamp") || + is_a($msg, "Google\Protobuf\FieldMask") || + static::hasJsonValue($msg); + } + + public static function hasJsonValue($msg) + { + return is_a($msg, "Google\Protobuf\DoubleValue") || + is_a($msg, "Google\Protobuf\FloatValue") || + is_a($msg, "Google\Protobuf\Int64Value") || + is_a($msg, "Google\Protobuf\UInt64Value") || + is_a($msg, "Google\Protobuf\Int32Value") || + is_a($msg, "Google\Protobuf\UInt32Value") || + is_a($msg, "Google\Protobuf\BoolValue") || + is_a($msg, "Google\Protobuf\StringValue") || + is_a($msg, "Google\Protobuf\BytesValue"); + } } diff --git a/php/src/Google/Protobuf/Internal/GPBWire.php b/php/src/Google/Protobuf/Internal/GPBWire.php index e7eec552c85c7..29569530fdac6 100644 --- a/php/src/Google/Protobuf/Internal/GPBWire.php +++ b/php/src/Google/Protobuf/Internal/GPBWire.php @@ -50,8 +50,8 @@ class GPBWire public static function getTagFieldNumber($tag) { - return ($tag >> self::TAG_TYPE_BITS) & - (1 << ((PHP_INT_SIZE * 8) - self::TAG_TYPE_BITS)) - 1; + // We have to mask because PHP has no arithmetic shift. + return ($tag >> self::TAG_TYPE_BITS) & 0x1fffffff; } public static function getTagWireType($tag) @@ -446,7 +446,7 @@ public static function varint64Size($value) if (bccomp($value, 0) < 0 || bccomp($value, "9223372036854775807") > 0) { return 10; - } + } if (bccomp($value, 1 << 7) < 0) { return 1; } @@ -475,7 +475,7 @@ public static function varint64Size($value) } else { if ($value < 0) { return 10; - } + } if ($value < (1 << 7)) { return 1; } diff --git a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php index ae2ad74558a73..c261ed6ec944f 100644 --- a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php +++ b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php @@ -26,11 +26,21 @@ class GeneratedCodeInfo extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; */ private $annotation; - private $has_annotation = false; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation[]|\Google\Protobuf\Internal\RepeatedField $annotation + * An Annotation connects some span of text in generated code to an element + * of its generating .proto file. + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -50,22 +60,16 @@ public function getAnnotation() * of its generating .proto file. * * Generated from protobuf field repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; - * @param \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation[]|\Google\Protobuf\Internal\RepeatedField $var + * @param \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation[]|\Google\Protobuf\Internal\RepeatedField $var * @return $this */ public function setAnnotation($var) { - $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation::class); + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation::class); $this->annotation = $arr; - $this->has_annotation = true; return $this; } - public function hasAnnotation() - { - return $this->has_annotation; - } - } diff --git a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php new file mode 100644 index 0000000000000..0b043d0665be9 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php @@ -0,0 +1,218 @@ +google.protobuf.GeneratedCodeInfo.Annotation + */ +class Annotation extends \Google\Protobuf\Internal\Message +{ + /** + * Identifies the element in the original source .proto file. This field + * is formatted the same as SourceCodeInfo.Location.path. + * + * Generated from protobuf field repeated int32 path = 1 [packed = true]; + */ + private $path; + /** + * Identifies the filesystem path to the original source .proto. + * + * Generated from protobuf field optional string source_file = 2; + */ + protected $source_file = null; + /** + * Identifies the starting offset in bytes in the generated code + * that relates to the identified object. + * + * Generated from protobuf field optional int32 begin = 3; + */ + protected $begin = null; + /** + * Identifies the ending offset in bytes in the generated code that + * relates to the identified offset. The end offset should be one past + * the last relevant byte (so the length of the text = end - begin). + * + * Generated from protobuf field optional int32 end = 4; + */ + protected $end = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int[]|\Google\Protobuf\Internal\RepeatedField $path + * Identifies the element in the original source .proto file. This field + * is formatted the same as SourceCodeInfo.Location.path. + * @type string $source_file + * Identifies the filesystem path to the original source .proto. + * @type int $begin + * Identifies the starting offset in bytes in the generated code + * that relates to the identified object. + * @type int $end + * Identifies the ending offset in bytes in the generated code that + * relates to the identified offset. The end offset should be one past + * the last relevant byte (so the length of the text = end - begin). + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); + parent::__construct($data); + } + + /** + * Identifies the element in the original source .proto file. This field + * is formatted the same as SourceCodeInfo.Location.path. + * + * Generated from protobuf field repeated int32 path = 1 [packed = true]; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getPath() + { + return $this->path; + } + + /** + * Identifies the element in the original source .proto file. This field + * is formatted the same as SourceCodeInfo.Location.path. + * + * Generated from protobuf field repeated int32 path = 1 [packed = true]; + * @param int[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setPath($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); + $this->path = $arr; + + return $this; + } + + /** + * Identifies the filesystem path to the original source .proto. + * + * Generated from protobuf field optional string source_file = 2; + * @return string + */ + public function getSourceFile() + { + return isset($this->source_file) ? $this->source_file : ''; + } + + public function hasSourceFile() + { + return isset($this->source_file); + } + + public function clearSourceFile() + { + unset($this->source_file); + } + + /** + * Identifies the filesystem path to the original source .proto. + * + * Generated from protobuf field optional string source_file = 2; + * @param string $var + * @return $this + */ + public function setSourceFile($var) + { + GPBUtil::checkString($var, True); + $this->source_file = $var; + + return $this; + } + + /** + * Identifies the starting offset in bytes in the generated code + * that relates to the identified object. + * + * Generated from protobuf field optional int32 begin = 3; + * @return int + */ + public function getBegin() + { + return isset($this->begin) ? $this->begin : 0; + } + + public function hasBegin() + { + return isset($this->begin); + } + + public function clearBegin() + { + unset($this->begin); + } + + /** + * Identifies the starting offset in bytes in the generated code + * that relates to the identified object. + * + * Generated from protobuf field optional int32 begin = 3; + * @param int $var + * @return $this + */ + public function setBegin($var) + { + GPBUtil::checkInt32($var); + $this->begin = $var; + + return $this; + } + + /** + * Identifies the ending offset in bytes in the generated code that + * relates to the identified offset. The end offset should be one past + * the last relevant byte (so the length of the text = end - begin). + * + * Generated from protobuf field optional int32 end = 4; + * @return int + */ + public function getEnd() + { + return isset($this->end) ? $this->end : 0; + } + + public function hasEnd() + { + return isset($this->end); + } + + public function clearEnd() + { + unset($this->end); + } + + /** + * Identifies the ending offset in bytes in the generated code that + * relates to the identified offset. The end offset should be one past + * the last relevant byte (so the length of the text = end - begin). + * + * Generated from protobuf field optional int32 end = 4; + * @param int $var + * @return $this + */ + public function setEnd($var) + { + GPBUtil::checkInt32($var); + $this->end = $var; + + return $this; + } + +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(Annotation::class, \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation::class); + diff --git a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php index 22ac2337c60b2..e36f1e573de4f 100644 --- a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php +++ b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php @@ -4,190 +4,13 @@ namespace Google\Protobuf\Internal; -use Google\Protobuf\Internal\GPBType; -use Google\Protobuf\Internal\GPBWire; -use Google\Protobuf\Internal\RepeatedField; -use Google\Protobuf\Internal\InputStream; -use Google\Protobuf\Internal\GPBUtil; - -/** - * Generated from protobuf message google.protobuf.GeneratedCodeInfo.Annotation - */ -class GeneratedCodeInfo_Annotation extends \Google\Protobuf\Internal\Message -{ - /** - * Identifies the element in the original source .proto file. This field - * is formatted the same as SourceCodeInfo.Location.path. - * - * Generated from protobuf field repeated int32 path = 1 [packed = true]; - */ - private $path; - private $has_path = false; - /** - * Identifies the filesystem path to the original source .proto. - * - * Generated from protobuf field optional string source_file = 2; - */ - private $source_file = ''; - private $has_source_file = false; - /** - * Identifies the starting offset in bytes in the generated code - * that relates to the identified object. - * - * Generated from protobuf field optional int32 begin = 3; - */ - private $begin = 0; - private $has_begin = false; - /** - * Identifies the ending offset in bytes in the generated code that - * relates to the identified offset. The end offset should be one past - * the last relevant byte (so the length of the text = end - begin). - * - * Generated from protobuf field optional int32 end = 4; - */ - private $end = 0; - private $has_end = false; - - public function __construct() { - \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); - } - +if (false) { /** - * Identifies the element in the original source .proto file. This field - * is formatted the same as SourceCodeInfo.Location.path. - * - * Generated from protobuf field repeated int32 path = 1 [packed = true]; - * @return \Google\Protobuf\Internal\RepeatedField + * This class is deprecated. Use Google\Protobuf\Internal\GeneratedCodeInfo\Annotation instead. + * @deprecated */ - public function getPath() - { - return $this->path; - } - - /** - * Identifies the element in the original source .proto file. This field - * is formatted the same as SourceCodeInfo.Location.path. - * - * Generated from protobuf field repeated int32 path = 1 [packed = true]; - * @param int[]|\Google\Protobuf\Internal\RepeatedField $var - * @return $this - */ - public function setPath($var) - { - $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); - $this->path = $arr; - $this->has_path = true; - - return $this; - } - - public function hasPath() - { - return $this->has_path; - } - - /** - * Identifies the filesystem path to the original source .proto. - * - * Generated from protobuf field optional string source_file = 2; - * @return string - */ - public function getSourceFile() - { - return $this->source_file; - } - - /** - * Identifies the filesystem path to the original source .proto. - * - * Generated from protobuf field optional string source_file = 2; - * @param string $var - * @return $this - */ - public function setSourceFile($var) - { - GPBUtil::checkString($var, True); - $this->source_file = $var; - $this->has_source_file = true; - - return $this; - } - - public function hasSourceFile() - { - return $this->has_source_file; - } - - /** - * Identifies the starting offset in bytes in the generated code - * that relates to the identified object. - * - * Generated from protobuf field optional int32 begin = 3; - * @return int - */ - public function getBegin() - { - return $this->begin; - } - - /** - * Identifies the starting offset in bytes in the generated code - * that relates to the identified object. - * - * Generated from protobuf field optional int32 begin = 3; - * @param int $var - * @return $this - */ - public function setBegin($var) - { - GPBUtil::checkInt32($var); - $this->begin = $var; - $this->has_begin = true; - - return $this; - } - - public function hasBegin() - { - return $this->has_begin; - } - - /** - * Identifies the ending offset in bytes in the generated code that - * relates to the identified offset. The end offset should be one past - * the last relevant byte (so the length of the text = end - begin). - * - * Generated from protobuf field optional int32 end = 4; - * @return int - */ - public function getEnd() - { - return $this->end; - } - - /** - * Identifies the ending offset in bytes in the generated code that - * relates to the identified offset. The end offset should be one past - * the last relevant byte (so the length of the text = end - begin). - * - * Generated from protobuf field optional int32 end = 4; - * @param int $var - * @return $this - */ - public function setEnd($var) - { - GPBUtil::checkInt32($var); - $this->end = $var; - $this->has_end = true; - - return $this; - } - - public function hasEnd() - { - return $this->has_end; - } - + class GeneratedCodeInfo_Annotation {} } +class_exists(GeneratedCodeInfo\Annotation::class); +@trigger_error('Google\Protobuf\Internal\GeneratedCodeInfo_Annotation is deprecated and will be removed in the next major release. Use Google\Protobuf\Internal\GeneratedCodeInfo\Annotation instead', E_USER_DEPRECATED); diff --git a/php/src/Google/Protobuf/Internal/MapEntry.php b/php/src/Google/Protobuf/Internal/MapEntry.php index 9c32f1eac7020..e89481f0a42f4 100644 --- a/php/src/Google/Protobuf/Internal/MapEntry.php +++ b/php/src/Google/Protobuf/Internal/MapEntry.php @@ -32,6 +32,7 @@ namespace Google\Protobuf\Internal; +use Google\Protobuf\Internal\GPBType; use Google\Protobuf\Internal\Message; class MapEntry extends Message @@ -39,6 +40,19 @@ class MapEntry extends Message public $key; public $value; + public function __construct($desc) { + parent::__construct($desc); + // For MapEntry, getValue should always return a valid value. Thus, we + // need to create a default instance value if the value type is + // message, in case no value is provided in data. + $value_field = $desc->getFieldByNumber(2); + if ($value_field->getType() == GPBType::MESSAGE) { + $klass = $value_field->getMessageType()->getClass(); + $value = new $klass; + $this->setValue($value); + } + } + public function setKey($key) { $this->key = $key; } diff --git a/php/src/Google/Protobuf/Internal/MapField.php b/php/src/Google/Protobuf/Internal/MapField.php index 38736dad88f15..719fb350bd646 100644 --- a/php/src/Google/Protobuf/Internal/MapField.php +++ b/php/src/Google/Protobuf/Internal/MapField.php @@ -58,7 +58,11 @@ class MapField implements \ArrayAccess, \IteratorAggregate, \Countable /** * @ignore */ - private $value_klass; + private $klass; + /** + * @ignore + */ + private $legacy_klass; /** * Constructs an instance of MapField. @@ -75,6 +79,17 @@ public function __construct($key_type, $value_type, $klass = null) $this->key_type = $key_type; $this->value_type = $value_type; $this->klass = $klass; + + if ($this->value_type == GPBType::MESSAGE) { + $pool = DescriptorPool::getGeneratedPool(); + $desc = $pool->getDescriptorByClassName($klass); + if ($desc == NULL) { + new $klass; // No msg class instance has been created before. + $desc = $pool->getDescriptorByClassName($klass); + } + $this->klass = $desc->getClass(); + $this->legacy_klass = $desc->getLegacyClass(); + } } /** @@ -101,15 +116,23 @@ public function getValueClass() return $this->klass; } + /** + * @ignore + */ + public function getLegacyValueClass() + { + return $this->legacy_klass; + } + /** * Return the element at the given key. * * This will also be called for: $ele = $arr[$key] * - * @param object $key The key of the element to be fetched. + * @param int|bool|string $key The key of the element to be fetched. * @return object The stored element at given key. - * @throws ErrorException Invalid type for index. - * @throws ErrorException Non-existing index. + * @throws \ErrorException Invalid type for index. + * @throws \ErrorException Non-existing index. */ public function offsetGet($key) { @@ -124,24 +147,31 @@ public function offsetGet($key) * @param object $key The key of the element to be fetched. * @param object $value The element to be assigned. * @return void - * @throws ErrorException Invalid type for key. - * @throws ErrorException Invalid type for value. - * @throws ErrorException Non-existing key. + * @throws \ErrorException Invalid type for key. + * @throws \ErrorException Invalid type for value. + * @throws \ErrorException Non-existing key. */ public function offsetSet($key, $value) { $this->checkKey($this->key_type, $key); switch ($this->value_type) { + case GPBType::SFIXED32: + case GPBType::SINT32: case GPBType::INT32: + case GPBType::ENUM: GPBUtil::checkInt32($value); break; + case GPBType::FIXED32: case GPBType::UINT32: GPBUtil::checkUint32($value); break; + case GPBType::SFIXED64: + case GPBType::SINT64: case GPBType::INT64: GPBUtil::checkInt64($value); break; + case GPBType::FIXED64: case GPBType::UINT64: GPBUtil::checkUint64($value); break; @@ -177,7 +207,7 @@ public function offsetSet($key, $value) * * @param object $key The key of the element to be removed. * @return void - * @throws ErrorException Invalid type for key. + * @throws \ErrorException Invalid type for key. */ public function offsetUnset($key) { @@ -192,7 +222,7 @@ public function offsetUnset($key) * * @param object $key The key of the element to be removed. * @return bool True if the element at the given key exists. - * @throws ErrorException Invalid type for key. + * @throws \ErrorException Invalid type for key. */ public function offsetExists($key) { @@ -226,36 +256,24 @@ public function count() private function checkKey($key_type, &$key) { switch ($key_type) { + case GPBType::SFIXED32: + case GPBType::SINT32: case GPBType::INT32: GPBUtil::checkInt32($key); break; + case GPBType::FIXED32: case GPBType::UINT32: GPBUtil::checkUint32($key); break; + case GPBType::SFIXED64: + case GPBType::SINT64: case GPBType::INT64: GPBUtil::checkInt64($key); break; - case GPBType::UINT64: - GPBUtil::checkUint64($key); - break; case GPBType::FIXED64: + case GPBType::UINT64: GPBUtil::checkUint64($key); break; - case GPBType::FIXED32: - GPBUtil::checkUint32($key); - break; - case GPBType::SFIXED64: - GPBUtil::checkInt64($key); - break; - case GPBType::SFIXED32: - GPBUtil::checkInt32($key); - break; - case GPBType::SINT64: - GPBUtil::checkInt64($key); - break; - case GPBType::SINT32: - GPBUtil::checkInt32($key); - break; case GPBType::BOOL: GPBUtil::checkBool($key); break; diff --git a/php/src/Google/Protobuf/Internal/MapFieldIter.php b/php/src/Google/Protobuf/Internal/MapFieldIter.php index 88e6c8b25531d..4e18005ea879d 100644 --- a/php/src/Google/Protobuf/Internal/MapFieldIter.php +++ b/php/src/Google/Protobuf/Internal/MapFieldIter.php @@ -91,14 +91,24 @@ public function current() public function key() { $key = key($this->container); - if ($this->key_type === GPBType::BOOL) { - // PHP associative array stores bool as integer for key. - return boolval($key); - } elseif ($this->key_type === GPBType::STRING) { - // PHP associative array stores int string as int for key. - return strval($key); - } else { - return $key; + switch ($this->key_type) { + case GPBType::INT64: + case GPBType::UINT64: + case GPBType::FIXED64: + case GPBType::SFIXED64: + case GPBType::SINT64: + if (PHP_INT_SIZE === 8) { + return $key; + } + // Intentionally fall through + case GPBType::STRING: + // PHP associative array stores int string as int for key. + return strval($key); + case GPBType::BOOL: + // PHP associative array stores bool as integer for key. + return boolval($key); + default: + return $key; } } diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php index e1009f2f901ce..64aadf9d260c4 100644 --- a/php/src/Google/Protobuf/Internal/Message.php +++ b/php/src/Google/Protobuf/Internal/Message.php @@ -44,6 +44,10 @@ use Google\Protobuf\Internal\GPBWire; use Google\Protobuf\Internal\MapEntry; use Google\Protobuf\Internal\RepeatedField; +use Google\Protobuf\ListValue; +use Google\Protobuf\Value; +use Google\Protobuf\Struct; +use Google\Protobuf\NullValue; /** * Parent class of all proto messages. Users should not instantiate this class @@ -57,25 +61,42 @@ class Message * @ignore */ private $desc; + private $unknown = ""; /** * @ignore */ - public function __construct($desc = NULL) + public function __construct($data = NULL) { // MapEntry message is shared by all types of map fields, whose // descriptors are different from each other. Thus, we cannot find a // specific descriptor from the descriptor pool. - if (get_class($this) === 'Google\Protobuf\Internal\MapEntry') { - $this->desc = $desc; - foreach ($desc->getField() as $field) { - $setter = $field->getSetter(); - $this->$setter($this->defaultValue($field)); + if ($this instanceof MapEntry) { + $this->initWithDescriptor($data); + } else { + $this->initWithGeneratedPool(); + if (is_array($data)) { + $this->mergeFromArray($data); + } else if (!empty($data)) { + throw new \InvalidArgumentException( + 'Message constructor must be an array or null.' + ); } - return; } + } + + /** + * @ignore + */ + private function initWithGeneratedPool() + { $pool = DescriptorPool::getGeneratedPool(); $this->desc = $pool->getDescriptorByClassName(get_class($this)); + if (is_null($this->desc)) { + throw new \InvalidArgumentException( + get_class($this) ." is not found in descriptor pool. " . + 'Only generated classes may derive from Message.'); + } foreach ($this->desc->getField() as $field) { $setter = $field->getSetter(); if ($field->isMap()) { @@ -143,6 +164,55 @@ public function __construct($desc = NULL) } } + /** + * @ignore + */ + private function initWithDescriptor(Descriptor $desc) + { + $this->desc = $desc; + foreach ($desc->getField() as $field) { + $setter = $field->getSetter(); + $defaultValue = $this->defaultValue($field); + $this->$setter($defaultValue); + } + } + + protected function readWrapperValue($member) + { + $field = $this->desc->getFieldByName($member); + $oneof_index = $field->getOneofIndex(); + if ($oneof_index === -1) { + $wrapper = $this->$member; + } else { + $wrapper = $this->readOneof($field->getNumber()); + } + + if (is_null($wrapper)) { + return NULL; + } else { + return $wrapper->getValue(); + } + } + + protected function writeWrapperValue($member, $value) + { + $field = $this->desc->getFieldByName($member); + $wrapped_value = $value; + if (!is_null($value)) { + $desc = $field->getMessageType(); + $klass = $desc->getClass(); + $wrapped_value = new $klass; + $wrapped_value->setValue($value); + } + + $oneof_index = $field->getOneofIndex(); + if ($oneof_index === -1) { + $this->$member = $wrapped_value; + } else { + $this->writeOneof($field->getNumber(), $wrapped_value); + } + } + protected function readOneof($number) { $field = $this->desc->getFieldByNumber($number); @@ -156,6 +226,15 @@ protected function readOneof($number) } } + protected function hasOneof($number) + { + $field = $this->desc->getFieldByNumber($number); + $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()]; + $oneof_name = $oneof->getName(); + $oneof_field = $this->$oneof_name; + return $number === $oneof_field->getNumber(); + } + protected function writeOneof($number, $value) { $field = $this->desc->getFieldByNumber($number); @@ -223,13 +302,14 @@ private function defaultValue($field) /** * @ignore */ - private static function skipField($input, $tag) + private function skipField($input, $tag) { $number = GPBWire::getTagFieldNumber($tag); if ($number === 0) { throw new GPBDecodeException("Illegal field number zero."); } + $start = $input->current(); switch (GPBWire::getTagWireType($tag)) { case GPBWireType::VARINT: $uint64 = 0; @@ -237,21 +317,21 @@ private static function skipField($input, $tag) throw new GPBDecodeException( "Unexpected EOF inside varint."); } - return; + break; case GPBWireType::FIXED64: $uint64 = 0; if (!$input->readLittleEndian64($uint64)) { throw new GPBDecodeException( "Unexpected EOF inside fixed64."); } - return; + break; case GPBWireType::FIXED32: $uint32 = 0; if (!$input->readLittleEndian32($uint32)) { throw new GPBDecodeException( "Unexpected EOF inside fixed32."); } - return; + break; case GPBWireType::LENGTH_DELIMITED: $length = 0; if (!$input->readVarint32($length)) { @@ -263,13 +343,18 @@ private static function skipField($input, $tag) throw new GPBDecodeException( "Unexpected EOF inside length delimited data."); } - return; + break; case GPBWireType::START_GROUP: case GPBWireType::END_GROUP: throw new GPBDecodeException("Unexpected wire type."); default: throw new GPBDecodeException("Unexpected wire type."); } + $end = $input->current(); + + $bytes = str_repeat(chr(0), CodedOutputStream::MAX_VARINT64_BYTES); + $size = CodedOutputStream::writeVarintToArray($tag, $bytes, true); + $this->unknown .= substr($bytes, 0, $size) . $input->substr($start, $end); } /** @@ -420,7 +505,7 @@ private function parseFieldFromStream($tag, $input, $field) } if ($value_format === GPBWire::UNKNOWN) { - self::skipField($input, $tag); + $this->skipField($input, $tag); return; } elseif ($value_format === GPBWire::NORMAL_FORMAT) { self::parseFieldFromStreamNoTag($input, $field, $value); @@ -458,6 +543,7 @@ private function parseFieldFromStream($tag, $input, $field) */ public function clear() { + $this->unknown = ""; foreach ($this->desc->getField() as $field) { $setter = $field->getSetter(); if ($field->isMap()) { @@ -561,14 +647,51 @@ public function clear() } } + /** + * Clear all unknown fields previously parsed. + * @return null. + */ + public function discardUnknownFields() + { + $this->unknown = ""; + foreach ($this->desc->getField() as $field) { + if ($field->getType() != GPBType::MESSAGE) { + continue; + } + if ($field->isMap()) { + $value_field = $field->getMessageType()->getFieldByNumber(2); + if ($value_field->getType() != GPBType::MESSAGE) { + continue; + } + $getter = $field->getGetter(); + $map = $this->$getter(); + foreach ($map as $key => $value) { + $value->discardUnknownFields(); + } + } else if ($field->getLabel() === GPBLabel::REPEATED) { + $getter = $field->getGetter(); + $arr = $this->$getter(); + foreach ($arr as $sub) { + $sub->discardUnknownFields(); + } + } else if ($field->getLabel() === GPBLabel::OPTIONAL) { + $getter = $field->getGetter(); + $sub = $this->$getter(); + if (!is_null($sub)) { + $sub->discardUnknownFields(); + } + } + } + } + /** * Merges the contents of the specified message into current message. * * This method merges the contents of the specified message into the * current message. Singular fields that are set in the specified message * overwrite the corresponding fields in the current message. Repeated - * fields are appended. Map fields key-value pairs are overritten. - * Singular/Oneof sub-messages are recursively merged. All overritten + * fields are appended. Map fields key-value pairs are overwritten. + * Singular/Oneof sub-messages are recursively merged. All overwritten * sub-messages are deep-copied. * * @param object $msg Protobuf message to be merged from. @@ -576,58 +699,58 @@ public function clear() */ public function mergeFrom($msg) { - if (get_class($this) !== get_class($msg)) { - user_error("Cannot merge messages with different class."); - return; - } - - foreach ($this->desc->getField() as $field) { - $setter = $field->getSetter(); - $getter = $field->getGetter(); - if ($field->isMap()) { - if (count($msg->$getter()) != 0) { - $value_field = $field->getMessageType()->getFieldByNumber(2); - foreach ($msg->$getter() as $key => $value) { - if ($value_field->getType() == GPBType::MESSAGE) { - $klass = $value_field->getMessageType()->getClass(); - $copy = new $klass; - $copy->mergeFrom($value); - - $this->kvUpdateHelper($field, $key, $copy); - } else { - $this->kvUpdateHelper($field, $key, $value); - } - } - } - } else if ($field->getLabel() === GPBLabel::REPEATED) { - if (count($msg->$getter()) != 0) { - foreach ($msg->$getter() as $tmp) { - if ($field->getType() == GPBType::MESSAGE) { - $klass = $field->getMessageType()->getClass(); - $copy = new $klass; - $copy->mergeFrom($tmp); - $this->appendHelper($field, $copy); - } else { - $this->appendHelper($field, $tmp); - } - } - } - } else if ($field->getLabel() === GPBLabel::OPTIONAL) { - if($msg->$getter() !== $this->defaultValue($field)) { - $tmp = $msg->$getter(); - if ($field->getType() == GPBType::MESSAGE) { - if (is_null($this->$getter())) { - $klass = $field->getMessageType()->getClass(); - $new_msg = new $klass; - $this->$setter($new_msg); - } - $this->$getter()->mergeFrom($tmp); - } else { - $this->$setter($tmp); - } - } - } - } + if (get_class($this) !== get_class($msg)) { + user_error("Cannot merge messages with different class."); + return; + } + + foreach ($this->desc->getField() as $field) { + $setter = $field->getSetter(); + $getter = $field->getGetter(); + if ($field->isMap()) { + if (count($msg->$getter()) != 0) { + $value_field = $field->getMessageType()->getFieldByNumber(2); + foreach ($msg->$getter() as $key => $value) { + if ($value_field->getType() == GPBType::MESSAGE) { + $klass = $value_field->getMessageType()->getClass(); + $copy = new $klass; + $copy->mergeFrom($value); + + $this->kvUpdateHelper($field, $key, $copy); + } else { + $this->kvUpdateHelper($field, $key, $value); + } + } + } + } else if ($field->getLabel() === GPBLabel::REPEATED) { + if (count($msg->$getter()) != 0) { + foreach ($msg->$getter() as $tmp) { + if ($field->getType() == GPBType::MESSAGE) { + $klass = $field->getMessageType()->getClass(); + $copy = new $klass; + $copy->mergeFrom($tmp); + $this->appendHelper($field, $copy); + } else { + $this->appendHelper($field, $tmp); + } + } + } + } else if ($field->getLabel() === GPBLabel::OPTIONAL) { + if($msg->$getter() !== $this->defaultValue($field)) { + $tmp = $msg->$getter(); + if ($field->getType() == GPBType::MESSAGE) { + if (is_null($this->$getter())) { + $klass = $field->getMessageType()->getClass(); + $new_msg = new $klass; + $this->$setter($new_msg); + } + $this->$getter()->mergeFrom($tmp); + } else { + $this->$setter($tmp); + } + } + } + } } /** @@ -640,7 +763,7 @@ public function mergeFrom($msg) * * @param string $data Binary protobuf data. * @return null. - * @throws Exception Invalid data. + * @throws \Exception Invalid data. */ public function mergeFromString($data) { @@ -658,12 +781,12 @@ public function mergeFromString($data) * * @param string $data Json protobuf data. * @return null. - * @throws Exception Invalid data. + * @throws \Exception Invalid data. */ - public function mergeFromJsonString($data) + public function mergeFromJsonString($data, $ignore_unknown = false) { $input = new RawInputStream($data); - $this->parseFromJsonStream($input); + $this->parseFromJsonStream($input, $ignore_unknown); } /** @@ -688,49 +811,103 @@ public function parseFromStream($input) private function convertJsonValueToProtoValue( $value, $field, + $ignore_unknown, $is_map_key = false) { - if (is_null($value)) { - return $this->defaultValue($field); - } switch ($field->getType()) { case GPBType::MESSAGE: $klass = $field->getMessageType()->getClass(); - if (!is_object($value) && !is_array($value)) { - throw new \Exception("Expect message."); - } $submsg = new $klass; - if (!is_null($value) && - $klass !== "Google\Protobuf\Any") { - $submsg->mergeFromJsonArray($value); + + if (is_a($submsg, "Google\Protobuf\Duration")) { + if (is_null($value)) { + return $this->defaultValue($field); + } else if (!is_string($value)) { + throw new GPBDecodeException("Expect string."); + } + return GPBUtil::parseDuration($value); + } else if ($field->isTimestamp()) { + if (is_null($value)) { + return $this->defaultValue($field); + } else if (!is_string($value)) { + throw new GPBDecodeException("Expect string."); + } + try { + $timestamp = GPBUtil::parseTimestamp($value); + } catch (\Exception $e) { + throw new GPBDecodeException( + "Invalid RFC 3339 timestamp: ".$e->getMessage()); + } + + $submsg->setSeconds($timestamp->getSeconds()); + $submsg->setNanos($timestamp->getNanos()); + } else if (is_a($submsg, "Google\Protobuf\FieldMask")) { + if (is_null($value)) { + return $this->defaultValue($field); + } + try { + return GPBUtil::parseFieldMask($value); + } catch (\Exception $e) { + throw new GPBDecodeException( + "Invalid FieldMask: ".$e->getMessage()); + } + } else { + if (is_null($value) && + !is_a($submsg, "Google\Protobuf\Value")) { + return $this->defaultValue($field); + } + if (GPBUtil::hasSpecialJsonMapping($submsg)) { + } elseif (!is_object($value) && !is_array($value)) { + throw new GPBDecodeException("Expect message."); + } + $submsg->mergeFromJsonArray($value, $ignore_unknown); } return $submsg; case GPBType::ENUM: + if (is_null($value)) { + return $this->defaultValue($field); + } if (is_integer($value)) { return $value; - } else { - $enum_value = - $field->getEnumType()->getValueByName($value); } + $enum_value = $field->getEnumType()->getValueByName($value); if (!is_null($enum_value)) { return $enum_value->getNumber(); + } else if ($ignore_unknown) { + return $this->defaultValue($field); + } else { + throw new GPBDecodeException( + "Enum field only accepts integer or enum value name"); } case GPBType::STRING: + if (is_null($value)) { + return $this->defaultValue($field); + } + if (is_numeric($value)) { + return strval($value); + } if (!is_string($value)) { - throw new GPBDecodeException("Expect string"); + throw new GPBDecodeException( + "String field only accepts string value"); } return $value; case GPBType::BYTES: + if (is_null($value)) { + return $this->defaultValue($field); + } if (!is_string($value)) { - throw new GPBDecodeException("Expect string"); + throw new GPBDecodeException( + "Byte field only accepts string value"); } $proto_value = base64_decode($value, true); if ($proto_value === false) { - throw new GPBDecodeException( - "Invalid base64 characters"); + throw new GPBDecodeException("Invalid base64 characters"); } return $proto_value; case GPBType::BOOL: + if (is_null($value)) { + return $this->defaultValue($field); + } if ($is_map_key) { if ($value === "true") { return true; @@ -739,25 +916,18 @@ private function convertJsonValueToProtoValue( return false; } throw new GPBDecodeException( - "Bool field only accept bool value"); + "Bool field only accepts bool value"); } if (!is_bool($value)) { throw new GPBDecodeException( - "Bool field only accept bool value"); + "Bool field only accepts bool value"); } return $value; case GPBType::FLOAT: - if ($value === "Infinity") { - return INF; - } - if ($value === "-Infinity") { - return -INF; - } - if ($value === "NaN") { - return NAN; - } - return $value; case GPBType::DOUBLE: + if (is_null($value)) { + return $this->defaultValue($field); + } if ($value === "Infinity") { return INF; } @@ -769,10 +939,19 @@ private function convertJsonValueToProtoValue( } return $value; case GPBType::INT32: + case GPBType::SINT32: + case GPBType::SFIXED32: + if (is_null($value)) { + return $this->defaultValue($field); + } if (!is_numeric($value)) { throw new GPBDecodeException( "Invalid data type for int32 field"); } + if (is_string($value) && trim($value) !== $value) { + throw new GPBDecodeException( + "Invalid data type for int32 field"); + } if (bccomp($value, "2147483647") > 0) { throw new GPBDecodeException( "Int32 too large"); @@ -783,20 +962,37 @@ private function convertJsonValueToProtoValue( } return $value; case GPBType::UINT32: + case GPBType::FIXED32: + if (is_null($value)) { + return $this->defaultValue($field); + } if (!is_numeric($value)) { throw new GPBDecodeException( "Invalid data type for uint32 field"); } + if (is_string($value) && trim($value) !== $value) { + throw new GPBDecodeException( + "Invalid data type for int32 field"); + } if (bccomp($value, 4294967295) > 0) { throw new GPBDecodeException( "Uint32 too large"); } return $value; case GPBType::INT64: + case GPBType::SINT64: + case GPBType::SFIXED64: + if (is_null($value)) { + return $this->defaultValue($field); + } if (!is_numeric($value)) { throw new GPBDecodeException( "Invalid data type for int64 field"); } + if (is_string($value) && trim($value) !== $value) { + throw new GPBDecodeException( + "Invalid data type for int64 field"); + } if (bccomp($value, "9223372036854775807") > 0) { throw new GPBDecodeException( "Int64 too large"); @@ -807,10 +1003,18 @@ private function convertJsonValueToProtoValue( } return $value; case GPBType::UINT64: + case GPBType::FIXED64: + if (is_null($value)) { + return $this->defaultValue($field); + } if (!is_numeric($value)) { throw new GPBDecodeException( "Invalid data type for int64 field"); } + if (is_string($value) && trim($value) !== $value) { + throw new GPBDecodeException( + "Invalid data type for int64 field"); + } if (bccomp($value, "18446744073709551615") > 0) { throw new GPBDecodeException( "Uint64 too large"); @@ -819,14 +1023,218 @@ private function convertJsonValueToProtoValue( $value = bcsub($value, "18446744073709551616"); } return $value; - case GPBType::FIXED64: - return $value; default: return $value; } } - private function mergeFromJsonArray($array) + /** + * Populates the message from a user-supplied PHP array. Array keys + * correspond to Message properties and nested message properties. + * + * Example: + * ``` + * $message->mergeFromArray([ + * 'name' => 'This is a message name', + * 'interval' => [ + * 'startTime' => time() - 60, + * 'endTime' => time(), + * ] + * ]); + * ``` + * + * This method will trigger an error if it is passed data that cannot + * be converted to the correct type. For example, a StringValue field + * must receive data that is either a string or a StringValue object. + * + * @param array $array An array containing message properties and values. + * @return null. + */ + protected function mergeFromArray(array $array) + { + // Just call the setters for the field names + foreach ($array as $key => $value) { + $field = $this->desc->getFieldByName($key); + if (is_null($field)) { + throw new \UnexpectedValueException( + 'Invalid message property: ' . $key); + } + $setter = $field->getSetter(); + if ($field->isMap()) { + $valueField = $field->getMessageType()->getFieldByName('value'); + if (!is_null($valueField) && $valueField->isWrapperType()) { + self::normalizeArrayElementsToMessageType($value, $valueField->getMessageType()->getClass()); + } + } elseif ($field->isWrapperType()) { + $class = $field->getMessageType()->getClass(); + if ($field->isRepeated()) { + self::normalizeArrayElementsToMessageType($value, $class); + } else { + self::normalizeToMessageType($value, $class); + } + } + $this->$setter($value); + } + } + + /** + * Tries to normalize the elements in $value into a provided protobuf + * wrapper type $class. If $value is any type other than array, we do + * not do any conversion, and instead rely on the existing protobuf + * type checking. If $value is an array, we process each element and + * try to convert it to an instance of $class. + * + * @param mixed $value The array of values to normalize. + * @param string $class The expected wrapper class name + */ + private static function normalizeArrayElementsToMessageType(&$value, $class) + { + if (!is_array($value)) { + // In the case that $value is not an array, we do not want to + // attempt any conversion. Note that this includes the cases + // when $value is a RepeatedField of MapField. In those cases, + // we do not need to convert the elements, as they should + // already be the correct types. + return; + } else { + // Normalize each element in the array. + foreach ($value as $key => &$elementValue) { + self::normalizeToMessageType($elementValue, $class); + } + } + } + + /** + * Tries to normalize $value into a provided protobuf wrapper type $class. + * If $value is any type other than an object, we attempt to construct an + * instance of $class and assign $value to it using the setValue method + * shared by all wrapper types. + * + * This method will raise an error if it receives a type that cannot be + * assigned to the wrapper type via setValue. + * + * @param mixed $value The value to normalize. + * @param string $class The expected wrapper class name + */ + private static function normalizeToMessageType(&$value, $class) + { + if (is_null($value) || is_object($value)) { + // This handles the case that $value is an instance of $class. We + // choose not to do any more strict checking here, relying on the + // existing type checking done by GPBUtil. + return; + } else { + // Try to instantiate $class and set the value + try { + $msg = new $class; + $msg->setValue($value); + $value = $msg; + return; + } catch (\Exception $exception) { + trigger_error( + "Error normalizing value to type '$class': " . $exception->getMessage(), + E_USER_ERROR + ); + } + } + } + + protected function mergeFromJsonArray($array, $ignore_unknown) + { + if (is_a($this, "Google\Protobuf\Any")) { + $this->clear(); + $this->setTypeUrl($array["@type"]); + $msg = $this->unpack(); + if (GPBUtil::hasSpecialJsonMapping($msg)) { + $msg->mergeFromJsonArray($array["value"], $ignore_unknown); + } else { + unset($array["@type"]); + $msg->mergeFromJsonArray($array, $ignore_unknown); + } + $this->setValue($msg->serializeToString()); + return; + } + if (is_a($this, "Google\Protobuf\DoubleValue") || + is_a($this, "Google\Protobuf\FloatValue") || + is_a($this, "Google\Protobuf\Int64Value") || + is_a($this, "Google\Protobuf\UInt64Value") || + is_a($this, "Google\Protobuf\Int32Value") || + is_a($this, "Google\Protobuf\UInt32Value") || + is_a($this, "Google\Protobuf\BoolValue") || + is_a($this, "Google\Protobuf\StringValue")) { + $this->setValue($array); + return; + } + if (is_a($this, "Google\Protobuf\BytesValue")) { + $this->setValue(base64_decode($array)); + return; + } + if (is_a($this, "Google\Protobuf\Duration")) { + $this->mergeFrom(GPBUtil::parseDuration($array)); + return; + } + if (is_a($this, "Google\Protobuf\FieldMask")) { + $this->mergeFrom(GPBUtil::parseFieldMask($array)); + return; + } + if (is_a($this, "Google\Protobuf\Timestamp")) { + $this->mergeFrom(GPBUtil::parseTimestamp($array)); + return; + } + if (is_a($this, "Google\Protobuf\Struct")) { + $fields = $this->getFields(); + foreach($array as $key => $value) { + $v = new Value(); + $v->mergeFromJsonArray($value, $ignore_unknown); + $fields[$key] = $v; + } + } + if (is_a($this, "Google\Protobuf\Value")) { + if (is_bool($array)) { + $this->setBoolValue($array); + } elseif (is_string($array)) { + $this->setStringValue($array); + } elseif (is_null($array)) { + $this->setNullValue(0); + } elseif (is_double($array) || is_integer($array)) { + $this->setNumberValue($array); + } elseif (is_array($array)) { + if (array_values($array) !== $array) { + // Associative array + $struct_value = $this->getStructValue(); + if (is_null($struct_value)) { + $struct_value = new Struct(); + $this->setStructValue($struct_value); + } + foreach ($array as $key => $v) { + $value = new Value(); + $value->mergeFromJsonArray($v, $ignore_unknown); + $values = $struct_value->getFields(); + $values[$key]= $value; + } + } else { + // Array + $list_value = $this->getListValue(); + if (is_null($list_value)) { + $list_value = new ListValue(); + $this->setListValue($list_value); + } + foreach ($array as $v) { + $value = new Value(); + $value->mergeFromJsonArray($v, $ignore_unknown); + $values = $list_value->getValues(); + $values[]= $value; + } + } + } else { + throw new GPBDecodeException("Invalid type for Value."); + } + return; + } + $this->mergeFromArrayJsonImpl($array, $ignore_unknown); + } + + private function mergeFromArrayJsonImpl($array, $ignore_unknown) { foreach ($array as $key => $value) { $field = $this->desc->getFieldByJsonName($key); @@ -836,7 +1244,6 @@ private function mergeFromJsonArray($array) continue; } } - $setter = $field->getSetter(); if ($field->isMap()) { if (is_null($value)) { continue; @@ -848,15 +1255,15 @@ private function mergeFromJsonArray($array) throw new \Exception( "Map value field element cannot be null."); } - $proto_key = - $this->convertJsonValueToProtoValue( - $tmp_key, - $key_field, - true); - $proto_value = - $this->convertJsonValueToProtoValue( - $tmp_value, - $value_field); + $proto_key = $this->convertJsonValueToProtoValue( + $tmp_key, + $key_field, + $ignore_unknown, + true); + $proto_value = $this->convertJsonValueToProtoValue( + $tmp_value, + $value_field, + $ignore_unknown); self::kvUpdateHelper($field, $proto_key, $proto_value); } } else if ($field->isRepeated()) { @@ -868,14 +1275,18 @@ private function mergeFromJsonArray($array) throw new \Exception( "Repeated field elements cannot be null."); } - $proto_value = - $this->convertJsonValueToProtoValue($tmp, $field); + $proto_value = $this->convertJsonValueToProtoValue( + $tmp, + $field, + $ignore_unknown); self::appendHelper($field, $proto_value); } } else { $setter = $field->getSetter(); - $proto_value = - $this->convertJsonValueToProtoValue($value, $field); + $proto_value = $this->convertJsonValueToProtoValue( + $value, + $field, + $ignore_unknown); if ($field->getType() === GPBType::MESSAGE) { if (is_null($proto_value)) { continue; @@ -895,16 +1306,24 @@ private function mergeFromJsonArray($array) /** * @ignore */ - public function parseFromJsonStream($input) + public function parseFromJsonStream($input, $ignore_unknown) { - $array = json_decode($input->getData(), JSON_BIGINT_AS_STRING); + $array = json_decode($input->getData(), true, 512, JSON_BIGINT_AS_STRING); + if ($this instanceof \Google\Protobuf\ListValue) { + $array = ["values"=>$array]; + } if (is_null($array)) { - throw new GPBDecodeException( - "Cannot decode json string."); + if ($this instanceof \Google\Protobuf\Value) { + $this->setNullValue(\Google\Protobuf\NullValue::NULL_VALUE); + return; + } else { + throw new GPBDecodeException( + "Cannot decode json string: " . $input->getData()); + } } try { - $this->mergeFromJsonArray($array); - } catch (Exception $e) { + $this->mergeFromJsonArray($array, $ignore_unknown); + } catch (\Exception $e) { throw new GPBDecodeException($e->getMessage()); } } @@ -1013,7 +1432,8 @@ private function serializeFieldToJsonStream(&$output, $field) { $getter = $field->getGetter(); $values = $this->$getter(); - return GPBJsonWire::serializeFieldToStream($values, $field, $output); + return GPBJsonWire::serializeFieldToStream( + $values, $field, $output, !GPBUtil::hasSpecialJsonMapping($this)); } /** @@ -1027,6 +1447,7 @@ public function serializeToStream(&$output) return false; } } + $output->writeRaw($this->unknown, strlen($this->unknown)); return true; } @@ -1035,22 +1456,89 @@ public function serializeToStream(&$output) */ public function serializeToJsonStream(&$output) { - $output->writeRaw("{", 1); - $fields = $this->desc->getField(); - $first = true; - foreach ($fields as $field) { - if ($this->existField($field)) { - if ($first) { - $first = false; - } else { - $output->writeRaw(",", 1); + if (is_a($this, 'Google\Protobuf\Any')) { + $output->writeRaw("{", 1); + $type_field = $this->desc->getFieldByNumber(1); + $value_msg = $this->unpack(); + + // Serialize type url. + $output->writeRaw("\"@type\":", 8); + $output->writeRaw("\"", 1); + $output->writeRaw($this->getTypeUrl(), strlen($this->getTypeUrl())); + $output->writeRaw("\"", 1); + + // Serialize value + if (GPBUtil::hasSpecialJsonMapping($value_msg)) { + $output->writeRaw(",\"value\":", 9); + $value_msg->serializeToJsonStream($output); + } else { + $value_fields = $value_msg->desc->getField(); + foreach ($value_fields as $field) { + if ($value_msg->existField($field)) { + $output->writeRaw(",", 1); + if (!$value_msg->serializeFieldToJsonStream($output, $field)) { + return false; + } + } } + } + + $output->writeRaw("}", 1); + } elseif (is_a($this, 'Google\Protobuf\FieldMask')) { + $field_mask = GPBUtil::formatFieldMask($this); + $output->writeRaw("\"", 1); + $output->writeRaw($field_mask, strlen($field_mask)); + $output->writeRaw("\"", 1); + } elseif (is_a($this, 'Google\Protobuf\Duration')) { + $duration = GPBUtil::formatDuration($this) . "s"; + $output->writeRaw("\"", 1); + $output->writeRaw($duration, strlen($duration)); + $output->writeRaw("\"", 1); + } elseif (get_class($this) === 'Google\Protobuf\Timestamp') { + $timestamp = GPBUtil::formatTimestamp($this); + $timestamp = json_encode($timestamp); + $output->writeRaw($timestamp, strlen($timestamp)); + } elseif (get_class($this) === 'Google\Protobuf\ListValue') { + $field = $this->desc->getField()[1]; + if (!$this->existField($field)) { + $output->writeRaw("[]", 2); + } else { + if (!$this->serializeFieldToJsonStream($output, $field)) { + return false; + } + } + } elseif (get_class($this) === 'Google\Protobuf\Struct') { + $field = $this->desc->getField()[1]; + if (!$this->existField($field)) { + $output->writeRaw("{}", 2); + } else { if (!$this->serializeFieldToJsonStream($output, $field)) { return false; } } + } else { + if (!GPBUtil::hasSpecialJsonMapping($this)) { + $output->writeRaw("{", 1); + } + $fields = $this->desc->getField(); + $first = true; + foreach ($fields as $field) { + if ($this->existField($field) || + GPBUtil::hasJsonValue($this)) { + if ($first) { + $first = false; + } else { + $output->writeRaw(",", 1); + } + if (!$this->serializeFieldToJsonStream($output, $field)) { + return false; + } + } + } + if (!GPBUtil::hasSpecialJsonMapping($this)) { + $output->writeRaw("}", 1); + } } - $output->writeRaw("}", 1); return true; } @@ -1081,14 +1569,19 @@ public function serializeToJsonString() */ private function existField($field) { - $oneof_index = $field->getOneofIndex(); - if ($oneof_index !== -1) { - $oneof = $this->desc->getOneofDecl()[$oneof_index]; - $oneof_name = $oneof->getName(); - return $this->$oneof_name->getNumber() === $field->getNumber(); + $getter = $field->getGetter(); + $hazzer = "has" . substr($getter, 3); + + if (method_exists($this, $hazzer)) { + return $this->$hazzer(); + } else if ($field->getOneofIndex() !== -1) { + // For old generated code, which does not have hazzers for oneof + // fields. + $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()]; + $oneof_name = $oneof->getName(); + return $this->$oneof_name->getNumber() === $field->getNumber(); } - $getter = $field->getGetter(); $values = $this->$getter(); if ($field->isMap()) { return count($values) !== 0; @@ -1232,6 +1725,10 @@ private function fieldDataOnlyJsonByteSize($field, $value) break; case GPBType::ENUM: $enum_desc = $field->getEnumType(); + if ($enum_desc->getClass() === "Google\Protobuf\NullValue") { + $size += 4; + break; + } $enum_value_desc = $enum_desc->getValueByNumber($value); if (!is_null($enum_value_desc)) { $size += 2; // size for "" @@ -1249,10 +1746,16 @@ private function fieldDataOnlyJsonByteSize($field, $value) } break; case GPBType::STRING: - $value = json_encode($value); + $value = json_encode($value, JSON_UNESCAPED_UNICODE); $size += strlen($value); break; case GPBType::BYTES: + # if (is_a($this, "Google\Protobuf\BytesValue")) { + # $size += strlen(json_encode($value)); + # } else { + # $size += strlen(base64_encode($value)); + # $size += 2; // size for \"\" + # } $size += strlen(base64_encode($value)); $size += 2; // size for \"\" break; @@ -1338,13 +1841,17 @@ private function fieldByteSize($field) private function fieldJsonByteSize($field) { $size = 0; + if ($field->isMap()) { $getter = $field->getGetter(); $values = $this->$getter(); $count = count($values); if ($count !== 0) { - $size += 5; // size for "\"\":{}". - $size += strlen($field->getJsonName()); // size for field name + if (!GPBUtil::hasSpecialJsonMapping($this)) { + $size += 3; // size for "\"\":". + $size += strlen($field->getJsonName()); // size for field name + } + $size += 2; // size for "{}". $size += $count - 1; // size for commas $getter = $field->getGetter(); $map_entry = $field->getMessageType(); @@ -1376,17 +1883,22 @@ private function fieldJsonByteSize($field) $values = $this->$getter(); $count = count($values); if ($count !== 0) { - $size += 5; // size for "\"\":[]". - $size += strlen($field->getJsonName()); // size for field name + if (!GPBUtil::hasSpecialJsonMapping($this)) { + $size += 3; // size for "\"\":". + $size += strlen($field->getJsonName()); // size for field name + } + $size += 2; // size for "[]". $size += $count - 1; // size for commas $getter = $field->getGetter(); foreach ($values as $value) { $size += $this->fieldDataOnlyJsonByteSize($field, $value); } } - } elseif ($this->existField($field)) { - $size += 3; // size for "\"\":". - $size += strlen($field->getJsonName()); // size for field name + } elseif ($this->existField($field) || GPBUtil::hasJsonValue($this)) { + if (!GPBUtil::hasSpecialJsonMapping($this)) { + $size += 3; // size for "\"\":". + $size += strlen($field->getJsonName()); // size for field name + } $getter = $field->getGetter(); $value = $this->$getter(); $size += $this->fieldDataOnlyJsonByteSize($field, $value); @@ -1405,6 +1917,7 @@ public function byteSize() foreach ($fields as $field) { $size += $this->fieldByteSize($field); } + $size += strlen($this->unknown); return $size; } @@ -1440,21 +1953,71 @@ private function kvUpdateHelper($field, $update_key, $update_value) public function jsonByteSize() { $size = 0; + if (is_a($this, 'Google\Protobuf\Any')) { + // Size for "{}". + $size += 2; - // Size for "{}". - $size += 2; + // Size for "\"@type\":". + $size += 8; - $fields = $this->desc->getField(); - $count = 0; - foreach ($fields as $field) { - $field_size = $this->fieldJsonByteSize($field); - $size += $field_size; - if ($field_size != 0) { - $count++; + // Size for url. +2 for "" /. + $size += strlen($this->getTypeUrl()) + 2; + + $value_msg = $this->unpack(); + if (GPBUtil::hasSpecialJsonMapping($value_msg)) { + // Size for "\",value\":". + $size += 9; + $size += $value_msg->jsonByteSize(); + } else { + // Size for value. +1 for comma, -2 for "{}". + $size += $value_msg->jsonByteSize() -1; + } + } elseif (get_class($this) === 'Google\Protobuf\FieldMask') { + $field_mask = GPBUtil::formatFieldMask($this); + $size += strlen($field_mask) + 2; // 2 for "" + } elseif (get_class($this) === 'Google\Protobuf\Duration') { + $duration = GPBUtil::formatDuration($this) . "s"; + $size += strlen($duration) + 2; // 2 for "" + } elseif (get_class($this) === 'Google\Protobuf\Timestamp') { + $timestamp = GPBUtil::formatTimestamp($this); + $timestamp = json_encode($timestamp); + $size += strlen($timestamp); + } elseif (get_class($this) === 'Google\Protobuf\ListValue') { + $field = $this->desc->getField()[1]; + if ($this->existField($field)) { + $field_size = $this->fieldJsonByteSize($field); + $size += $field_size; + } else { + // Size for "[]". + $size += 2; + } + } elseif (get_class($this) === 'Google\Protobuf\Struct') { + $field = $this->desc->getField()[1]; + if ($this->existField($field)) { + $field_size = $this->fieldJsonByteSize($field); + $size += $field_size; + } else { + // Size for "{}". + $size += 2; + } + } else { + if (!GPBUtil::hasSpecialJsonMapping($this)) { + // Size for "{}". + $size += 2; + } + + $fields = $this->desc->getField(); + $count = 0; + foreach ($fields as $field) { + $field_size = $this->fieldJsonByteSize($field); + $size += $field_size; + if ($field_size != 0) { + $count++; + } } + // size for comma + $size += $count > 0 ? ($count - 1) : 0; } - // size for comma - $size += $count > 0 ? ($count - 1) : 0; return $size; } } diff --git a/php/src/Google/Protobuf/Internal/MessageOptions.php b/php/src/Google/Protobuf/Internal/MessageOptions.php index 99ff3d0ee2d51..2f4e3cb7f4fd1 100644 --- a/php/src/Google/Protobuf/Internal/MessageOptions.php +++ b/php/src/Google/Protobuf/Internal/MessageOptions.php @@ -34,8 +34,7 @@ class MessageOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool message_set_wire_format = 1 [default = false]; */ - private $message_set_wire_format = false; - private $has_message_set_wire_format = false; + protected $message_set_wire_format = null; /** * Disables the generation of the standard "descriptor()" accessor, which can * conflict with a field of the same name. This is meant to make migration @@ -43,8 +42,7 @@ class MessageOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool no_standard_descriptor_accessor = 2 [default = false]; */ - private $no_standard_descriptor_accessor = false; - private $has_no_standard_descriptor_accessor = false; + protected $no_standard_descriptor_accessor = null; /** * Is this message deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -53,8 +51,7 @@ class MessageOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool deprecated = 3 [default = false]; */ - private $deprecated = false; - private $has_deprecated = false; + protected $deprecated = null; /** * Whether the message is an automatically generated map entry type for the * maps field. @@ -69,7 +66,7 @@ class MessageOptions extends \Google\Protobuf\Internal\Message * repeated MapFieldEntry map_field = 1; * Implementations may choose not to generate the map_entry=true message, but * use a native map in the target language to hold the keys and values. - * The reflection APIs in such implementions still need to work as + * The reflection APIs in such implementations still need to work as * if the field is a repeated message field. * NOTE: Do not set the option in .proto files. Always use the maps syntax * instead. The option should only be implicitly set by the proto compiler @@ -77,19 +74,71 @@ class MessageOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool map_entry = 7; */ - private $map_entry = false; - private $has_map_entry = false; + protected $map_entry = null; /** * The parser stores options it doesn't recognize here. See above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type bool $message_set_wire_format + * Set true to use the old proto1 MessageSet wire format for extensions. + * This is provided for backwards-compatibility with the MessageSet wire + * format. You should not use this for any other reason: It's less + * efficient, has fewer features, and is more complicated. + * The message must be defined exactly as follows: + * message Foo { + * option message_set_wire_format = true; + * extensions 4 to max; + * } + * Note that the message cannot have any defined fields; MessageSets only + * have extensions. + * All extensions of your type must be singular messages; e.g. they cannot + * be int32s, enums, or repeated messages. + * Because this is an option, the above two restrictions are not enforced by + * the protocol compiler. + * @type bool $no_standard_descriptor_accessor + * Disables the generation of the standard "descriptor()" accessor, which can + * conflict with a field of the same name. This is meant to make migration + * from proto1 easier; new code should avoid fields named "descriptor". + * @type bool $deprecated + * Is this message deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the message, or it will be completely ignored; in the very least, + * this is a formalization for deprecating messages. + * @type bool $map_entry + * Whether the message is an automatically generated map entry type for the + * maps field. + * For maps fields: + * map map_field = 1; + * The parsed descriptor looks like: + * message MapFieldEntry { + * option map_entry = true; + * optional KeyType key = 1; + * optional ValueType value = 2; + * } + * repeated MapFieldEntry map_field = 1; + * Implementations may choose not to generate the map_entry=true message, but + * use a native map in the target language to hold the keys and values. + * The reflection APIs in such implementations still need to work as + * if the field is a repeated message field. + * NOTE: Do not set the option in .proto files. Always use the maps syntax + * instead. The option should only be implicitly set by the proto compiler + * parser. + * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option + * The parser stores options it doesn't recognize here. See above. + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -114,7 +163,17 @@ public function __construct() { */ public function getMessageSetWireFormat() { - return $this->message_set_wire_format; + return isset($this->message_set_wire_format) ? $this->message_set_wire_format : false; + } + + public function hasMessageSetWireFormat() + { + return isset($this->message_set_wire_format); + } + + public function clearMessageSetWireFormat() + { + unset($this->message_set_wire_format); } /** @@ -142,16 +201,10 @@ public function setMessageSetWireFormat($var) { GPBUtil::checkBool($var); $this->message_set_wire_format = $var; - $this->has_message_set_wire_format = true; return $this; } - public function hasMessageSetWireFormat() - { - return $this->has_message_set_wire_format; - } - /** * Disables the generation of the standard "descriptor()" accessor, which can * conflict with a field of the same name. This is meant to make migration @@ -162,7 +215,17 @@ public function hasMessageSetWireFormat() */ public function getNoStandardDescriptorAccessor() { - return $this->no_standard_descriptor_accessor; + return isset($this->no_standard_descriptor_accessor) ? $this->no_standard_descriptor_accessor : false; + } + + public function hasNoStandardDescriptorAccessor() + { + return isset($this->no_standard_descriptor_accessor); + } + + public function clearNoStandardDescriptorAccessor() + { + unset($this->no_standard_descriptor_accessor); } /** @@ -178,16 +241,10 @@ public function setNoStandardDescriptorAccessor($var) { GPBUtil::checkBool($var); $this->no_standard_descriptor_accessor = $var; - $this->has_no_standard_descriptor_accessor = true; return $this; } - public function hasNoStandardDescriptorAccessor() - { - return $this->has_no_standard_descriptor_accessor; - } - /** * Is this message deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -199,7 +256,17 @@ public function hasNoStandardDescriptorAccessor() */ public function getDeprecated() { - return $this->deprecated; + return isset($this->deprecated) ? $this->deprecated : false; + } + + public function hasDeprecated() + { + return isset($this->deprecated); + } + + public function clearDeprecated() + { + unset($this->deprecated); } /** @@ -216,16 +283,10 @@ public function setDeprecated($var) { GPBUtil::checkBool($var); $this->deprecated = $var; - $this->has_deprecated = true; return $this; } - public function hasDeprecated() - { - return $this->has_deprecated; - } - /** * Whether the message is an automatically generated map entry type for the * maps field. @@ -240,7 +301,7 @@ public function hasDeprecated() * repeated MapFieldEntry map_field = 1; * Implementations may choose not to generate the map_entry=true message, but * use a native map in the target language to hold the keys and values. - * The reflection APIs in such implementions still need to work as + * The reflection APIs in such implementations still need to work as * if the field is a repeated message field. * NOTE: Do not set the option in .proto files. Always use the maps syntax * instead. The option should only be implicitly set by the proto compiler @@ -251,7 +312,17 @@ public function hasDeprecated() */ public function getMapEntry() { - return $this->map_entry; + return isset($this->map_entry) ? $this->map_entry : false; + } + + public function hasMapEntry() + { + return isset($this->map_entry); + } + + public function clearMapEntry() + { + unset($this->map_entry); } /** @@ -268,7 +339,7 @@ public function getMapEntry() * repeated MapFieldEntry map_field = 1; * Implementations may choose not to generate the map_entry=true message, but * use a native map in the target language to hold the keys and values. - * The reflection APIs in such implementions still need to work as + * The reflection APIs in such implementations still need to work as * if the field is a repeated message field. * NOTE: Do not set the option in .proto files. Always use the maps syntax * instead. The option should only be implicitly set by the proto compiler @@ -282,16 +353,10 @@ public function setMapEntry($var) { GPBUtil::checkBool($var); $this->map_entry = $var; - $this->has_map_entry = true; return $this; } - public function hasMapEntry() - { - return $this->has_map_entry; - } - /** * The parser stores options it doesn't recognize here. See above. * @@ -314,15 +379,9 @@ public function setUninterpretedOption($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php b/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php index ccfce2dbd6d13..5814f08852961 100644 --- a/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php @@ -20,44 +20,56 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field optional string name = 1; */ - private $name = ''; - private $has_name = false; + protected $name = null; /** * Input and output type names. These are resolved in the same way as * FieldDescriptorProto.type_name, but must refer to a message type. * * Generated from protobuf field optional string input_type = 2; */ - private $input_type = ''; - private $has_input_type = false; + protected $input_type = null; /** * Generated from protobuf field optional string output_type = 3; */ - private $output_type = ''; - private $has_output_type = false; + protected $output_type = null; /** * Generated from protobuf field optional .google.protobuf.MethodOptions options = 4; */ - private $options = null; - private $has_options = false; + protected $options = null; /** * Identifies if client streams multiple client messages * * Generated from protobuf field optional bool client_streaming = 5 [default = false]; */ - private $client_streaming = false; - private $has_client_streaming = false; + protected $client_streaming = null; /** * Identifies if server streams multiple server messages * * Generated from protobuf field optional bool server_streaming = 6 [default = false]; */ - private $server_streaming = false; - private $has_server_streaming = false; + protected $server_streaming = null; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * @type string $input_type + * Input and output type names. These are resolved in the same way as + * FieldDescriptorProto.type_name, but must refer to a message type. + * @type string $output_type + * @type \Google\Protobuf\Internal\MethodOptions $options + * @type bool $client_streaming + * Identifies if client streams multiple client messages + * @type bool $server_streaming + * Identifies if server streams multiple server messages + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -66,7 +78,17 @@ public function __construct() { */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -78,16 +100,10 @@ public function setName($var) { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * Input and output type names. These are resolved in the same way as * FieldDescriptorProto.type_name, but must refer to a message type. @@ -97,7 +113,17 @@ public function hasName() */ public function getInputType() { - return $this->input_type; + return isset($this->input_type) ? $this->input_type : ''; + } + + public function hasInputType() + { + return isset($this->input_type); + } + + public function clearInputType() + { + unset($this->input_type); } /** @@ -112,23 +138,27 @@ public function setInputType($var) { GPBUtil::checkString($var, True); $this->input_type = $var; - $this->has_input_type = true; return $this; } - public function hasInputType() - { - return $this->has_input_type; - } - /** * Generated from protobuf field optional string output_type = 3; * @return string */ public function getOutputType() { - return $this->output_type; + return isset($this->output_type) ? $this->output_type : ''; + } + + public function hasOutputType() + { + return isset($this->output_type); + } + + public function clearOutputType() + { + unset($this->output_type); } /** @@ -140,23 +170,27 @@ public function setOutputType($var) { GPBUtil::checkString($var, True); $this->output_type = $var; - $this->has_output_type = true; return $this; } - public function hasOutputType() - { - return $this->has_output_type; - } - /** * Generated from protobuf field optional .google.protobuf.MethodOptions options = 4; - * @return \Google\Protobuf\Internal\MethodOptions + * @return \Google\Protobuf\Internal\MethodOptions|null */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -168,16 +202,10 @@ public function setOptions($var) { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\MethodOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - /** * Identifies if client streams multiple client messages * @@ -186,7 +214,17 @@ public function hasOptions() */ public function getClientStreaming() { - return $this->client_streaming; + return isset($this->client_streaming) ? $this->client_streaming : false; + } + + public function hasClientStreaming() + { + return isset($this->client_streaming); + } + + public function clearClientStreaming() + { + unset($this->client_streaming); } /** @@ -200,16 +238,10 @@ public function setClientStreaming($var) { GPBUtil::checkBool($var); $this->client_streaming = $var; - $this->has_client_streaming = true; return $this; } - public function hasClientStreaming() - { - return $this->has_client_streaming; - } - /** * Identifies if server streams multiple server messages * @@ -218,7 +250,17 @@ public function hasClientStreaming() */ public function getServerStreaming() { - return $this->server_streaming; + return isset($this->server_streaming) ? $this->server_streaming : false; + } + + public function hasServerStreaming() + { + return isset($this->server_streaming); + } + + public function clearServerStreaming() + { + unset($this->server_streaming); } /** @@ -232,15 +274,9 @@ public function setServerStreaming($var) { GPBUtil::checkBool($var); $this->server_streaming = $var; - $this->has_server_streaming = true; return $this; } - public function hasServerStreaming() - { - return $this->has_server_streaming; - } - } diff --git a/php/src/Google/Protobuf/Internal/MethodOptions.php b/php/src/Google/Protobuf/Internal/MethodOptions.php index baa806b7aaab6..a4595b7448228 100644 --- a/php/src/Google/Protobuf/Internal/MethodOptions.php +++ b/php/src/Google/Protobuf/Internal/MethodOptions.php @@ -23,24 +23,37 @@ class MethodOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool deprecated = 33 [default = false]; */ - private $deprecated = false; - private $has_deprecated = false; + protected $deprecated = null; /** * Generated from protobuf field optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; */ - private $idempotency_level = 0; - private $has_idempotency_level = false; + protected $idempotency_level = null; /** * The parser stores options it doesn't recognize here. See above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type bool $deprecated + * Is this method deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the method, or it will be completely ignored; in the very least, + * this is a formalization for deprecating methods. + * @type int $idempotency_level + * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option + * The parser stores options it doesn't recognize here. See above. + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -54,7 +67,17 @@ public function __construct() { */ public function getDeprecated() { - return $this->deprecated; + return isset($this->deprecated) ? $this->deprecated : false; + } + + public function hasDeprecated() + { + return isset($this->deprecated); + } + + public function clearDeprecated() + { + unset($this->deprecated); } /** @@ -71,23 +94,27 @@ public function setDeprecated($var) { GPBUtil::checkBool($var); $this->deprecated = $var; - $this->has_deprecated = true; return $this; } - public function hasDeprecated() - { - return $this->has_deprecated; - } - /** * Generated from protobuf field optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; * @return int */ public function getIdempotencyLevel() { - return $this->idempotency_level; + return isset($this->idempotency_level) ? $this->idempotency_level : 0; + } + + public function hasIdempotencyLevel() + { + return isset($this->idempotency_level); + } + + public function clearIdempotencyLevel() + { + unset($this->idempotency_level); } /** @@ -97,18 +124,12 @@ public function getIdempotencyLevel() */ public function setIdempotencyLevel($var) { - GPBUtil::checkEnum($var, \Google\Protobuf\Internal\MethodOptions_IdempotencyLevel::class); + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\MethodOptions\IdempotencyLevel::class); $this->idempotency_level = $var; - $this->has_idempotency_level = true; return $this; } - public function hasIdempotencyLevel() - { - return $this->has_idempotency_level; - } - /** * The parser stores options it doesn't recognize here. See above. * @@ -131,15 +152,9 @@ public function setUninterpretedOption($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php b/php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php new file mode 100644 index 0000000000000..ce3c062c691df --- /dev/null +++ b/php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php @@ -0,0 +1,64 @@ +google.protobuf.MethodOptions.IdempotencyLevel + */ +class IdempotencyLevel +{ + /** + * Generated from protobuf enum IDEMPOTENCY_UNKNOWN = 0; + */ + const IDEMPOTENCY_UNKNOWN = 0; + /** + * implies idempotent + * + * Generated from protobuf enum NO_SIDE_EFFECTS = 1; + */ + const NO_SIDE_EFFECTS = 1; + /** + * idempotent, but may have side effects + * + * Generated from protobuf enum IDEMPOTENT = 2; + */ + const IDEMPOTENT = 2; + + private static $valueToName = [ + self::IDEMPOTENCY_UNKNOWN => 'IDEMPOTENCY_UNKNOWN', + self::NO_SIDE_EFFECTS => 'NO_SIDE_EFFECTS', + self::IDEMPOTENT => 'IDEMPOTENT', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(IdempotencyLevel::class, \Google\Protobuf\Internal\MethodOptions_IdempotencyLevel::class); + diff --git a/php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php b/php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php index 9e06d8eea5cb0..a2913114559ad 100644 --- a/php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php +++ b/php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php @@ -4,30 +4,13 @@ namespace Google\Protobuf\Internal; -/** - * Is this method side-effect-free (or safe in HTTP parlance), or idempotent, - * or neither? HTTP based RPC implementation may choose GET verb for safe - * methods, and PUT verb for idempotent methods instead of the default POST. - * - * Protobuf enum Google\Protobuf\Internal - */ -class MethodOptions_IdempotencyLevel -{ +if (false) { /** - * Generated from protobuf enum IDEMPOTENCY_UNKNOWN = 0; + * This class is deprecated. Use Google\Protobuf\Internal\MethodOptions\IdempotencyLevel instead. + * @deprecated */ - const IDEMPOTENCY_UNKNOWN = 0; - /** - * implies idempotent - * - * Generated from protobuf enum NO_SIDE_EFFECTS = 1; - */ - const NO_SIDE_EFFECTS = 1; - /** - * idempotent, but may have side effects - * - * Generated from protobuf enum IDEMPOTENT = 2; - */ - const IDEMPOTENT = 2; + class MethodOptions_IdempotencyLevel {} } +class_exists(MethodOptions\IdempotencyLevel::class); +@trigger_error('Google\Protobuf\Internal\MethodOptions_IdempotencyLevel is deprecated and will be removed in the next major release. Use Google\Protobuf\Internal\MethodOptions\IdempotencyLevel instead', E_USER_DEPRECATED); diff --git a/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php b/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php index 15ff061074639..33cf487a8a2ba 100644 --- a/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php @@ -20,17 +20,25 @@ class OneofDescriptorProto extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field optional string name = 1; */ - private $name = ''; - private $has_name = false; + protected $name = null; /** * Generated from protobuf field optional .google.protobuf.OneofOptions options = 2; */ - private $options = null; - private $has_options = false; + protected $options = null; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * @type \Google\Protobuf\Internal\OneofOptions $options + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -39,7 +47,17 @@ public function __construct() { */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -51,23 +69,27 @@ public function setName($var) { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * Generated from protobuf field optional .google.protobuf.OneofOptions options = 2; - * @return \Google\Protobuf\Internal\OneofOptions + * @return \Google\Protobuf\Internal\OneofOptions|null */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -79,15 +101,9 @@ public function setOptions($var) { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\OneofOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - } diff --git a/php/src/Google/Protobuf/Internal/OneofOptions.php b/php/src/Google/Protobuf/Internal/OneofOptions.php index e5b4633d59c94..8dde8f3b17156 100644 --- a/php/src/Google/Protobuf/Internal/OneofOptions.php +++ b/php/src/Google/Protobuf/Internal/OneofOptions.php @@ -21,11 +21,20 @@ class OneofOptions extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option + * The parser stores options it doesn't recognize here. See above. + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -50,15 +59,9 @@ public function setUninterpretedOption($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/RepeatedField.php b/php/src/Google/Protobuf/Internal/RepeatedField.php index 797b3b3a9ceff..ec7a3a6d0791b 100644 --- a/php/src/Google/Protobuf/Internal/RepeatedField.php +++ b/php/src/Google/Protobuf/Internal/RepeatedField.php @@ -59,6 +59,10 @@ class RepeatedField implements \ArrayAccess, \IteratorAggregate, \Countable * @ignore */ private $klass; + /** + * @ignore + */ + private $legacy_klass; /** * Constructs an instance of RepeatedField. @@ -71,7 +75,16 @@ public function __construct($type, $klass = null) { $this->container = []; $this->type = $type; - $this->klass = $klass; + if ($this->type == GPBType::MESSAGE) { + $pool = DescriptorPool::getGeneratedPool(); + $desc = $pool->getDescriptorByClassName($klass); + if ($desc == NULL) { + new $klass; // No msg class instance has been created before. + $desc = $pool->getDescriptorByClassName($klass); + } + $this->klass = $desc->getClass(); + $this->legacy_klass = $desc->getLegacyClass(); + } } /** @@ -90,6 +103,14 @@ public function getClass() return $this->klass; } + /** + * @ignore + */ + public function getLegacyClass() + { + return $this->legacy_klass; + } + /** * Return the element at the given index. * @@ -97,8 +118,8 @@ public function getClass() * * @param long $offset The index of the element to be fetched. * @return object The stored element at given index. - * @throws ErrorException Invalid type for index. - * @throws ErrorException Non-existing index. + * @throws \ErrorException Invalid type for index. + * @throws \ErrorException Non-existing index. */ public function offsetGet($offset) { @@ -113,22 +134,29 @@ public function offsetGet($offset) * @param long $offset The index of the element to be assigned. * @param object $value The element to be assigned. * @return void - * @throws ErrorException Invalid type for index. - * @throws ErrorException Non-existing index. - * @throws ErrorException Incorrect type of the element. + * @throws \ErrorException Invalid type for index. + * @throws \ErrorException Non-existing index. + * @throws \ErrorException Incorrect type of the element. */ public function offsetSet($offset, $value) { switch ($this->type) { + case GPBType::SFIXED32: + case GPBType::SINT32: case GPBType::INT32: + case GPBType::ENUM: GPBUtil::checkInt32($value); break; + case GPBType::FIXED32: case GPBType::UINT32: GPBUtil::checkUint32($value); break; + case GPBType::SFIXED64: + case GPBType::SINT64: case GPBType::INT64: GPBUtil::checkInt64($value); break; + case GPBType::FIXED64: case GPBType::UINT64: GPBUtil::checkUint64($value); break; @@ -141,6 +169,9 @@ public function offsetSet($offset, $value) case GPBType::BOOL: GPBUtil::checkBool($value); break; + case GPBType::BYTES: + GPBUtil::checkString($value, false); + break; case GPBType::STRING: GPBUtil::checkString($value, true); break; @@ -175,8 +206,8 @@ public function offsetSet($offset, $value) * * @param long $offset The index of the element to be removed. * @return void - * @throws ErrorException Invalid type for index. - * @throws ErrorException The element to be removed is not at the end of the + * @throws \ErrorException Invalid type for index. + * @throws \ErrorException The element to be removed is not at the end of the * RepeatedField. */ public function offsetUnset($offset) @@ -198,7 +229,7 @@ public function offsetUnset($offset) * * @param long $offset The index of the element to be removed. * @return bool True if the element at the given offset exists. - * @throws ErrorException Invalid type for index. + * @throws \ErrorException Invalid type for index. */ public function offsetExists($offset) { diff --git a/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php b/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php index da88e9c44473d..f60561c1822cb 100644 --- a/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php @@ -20,22 +20,30 @@ class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field optional string name = 1; */ - private $name = ''; - private $has_name = false; + protected $name = null; /** * Generated from protobuf field repeated .google.protobuf.MethodDescriptorProto method = 2; */ private $method; - private $has_method = false; /** * Generated from protobuf field optional .google.protobuf.ServiceOptions options = 3; */ - private $options = null; - private $has_options = false; + protected $options = null; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * @type \Google\Protobuf\Internal\MethodDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $method + * @type \Google\Protobuf\Internal\ServiceOptions $options + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -44,7 +52,17 @@ public function __construct() { */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -56,16 +74,10 @@ public function setName($var) { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * Generated from protobuf field repeated .google.protobuf.MethodDescriptorProto method = 2; * @return \Google\Protobuf\Internal\RepeatedField @@ -84,23 +96,27 @@ public function setMethod($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\MethodDescriptorProto::class); $this->method = $arr; - $this->has_method = true; return $this; } - public function hasMethod() - { - return $this->has_method; - } - /** * Generated from protobuf field optional .google.protobuf.ServiceOptions options = 3; - * @return \Google\Protobuf\Internal\ServiceOptions + * @return \Google\Protobuf\Internal\ServiceOptions|null */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -112,15 +128,9 @@ public function setOptions($var) { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\ServiceOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - } diff --git a/php/src/Google/Protobuf/Internal/ServiceOptions.php b/php/src/Google/Protobuf/Internal/ServiceOptions.php index 3e7214a1ebe8a..d15a36ae0a5e7 100644 --- a/php/src/Google/Protobuf/Internal/ServiceOptions.php +++ b/php/src/Google/Protobuf/Internal/ServiceOptions.php @@ -23,19 +23,32 @@ class ServiceOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool deprecated = 33 [default = false]; */ - private $deprecated = false; - private $has_deprecated = false; + protected $deprecated = null; /** * The parser stores options it doesn't recognize here. See above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type bool $deprecated + * Is this service deprecated? + * Depending on the target platform, this can emit Deprecated annotations + * for the service, or it will be completely ignored; in the very least, + * this is a formalization for deprecating services. + * @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option + * The parser stores options it doesn't recognize here. See above. + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -49,7 +62,17 @@ public function __construct() { */ public function getDeprecated() { - return $this->deprecated; + return isset($this->deprecated) ? $this->deprecated : false; + } + + public function hasDeprecated() + { + return isset($this->deprecated); + } + + public function clearDeprecated() + { + unset($this->deprecated); } /** @@ -66,16 +89,10 @@ public function setDeprecated($var) { GPBUtil::checkBool($var); $this->deprecated = $var; - $this->has_deprecated = true; return $this; } - public function hasDeprecated() - { - return $this->has_deprecated; - } - /** * The parser stores options it doesn't recognize here. See above. * @@ -98,15 +115,9 @@ public function setUninterpretedOption($var) { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/SourceCodeInfo.php b/php/src/Google/Protobuf/Internal/SourceCodeInfo.php index 6ce05ed420194..1c572e75ebf1a 100644 --- a/php/src/Google/Protobuf/Internal/SourceCodeInfo.php +++ b/php/src/Google/Protobuf/Internal/SourceCodeInfo.php @@ -54,7 +54,7 @@ class SourceCodeInfo extends \Google\Protobuf\Internal\Message * beginning of the "extend" block and is shared by all extensions within * the block. * - Just because a location's span is a subset of some other location's span - * does not mean that it is a descendent. For example, a "group" defines + * does not mean that it is a descendant. For example, a "group" defines * both a type and a field in a single declaration. Thus, the locations * corresponding to the type and field and their components will overlap. * - Code which tries to interpret locations should probably be designed to @@ -64,11 +64,60 @@ class SourceCodeInfo extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated .google.protobuf.SourceCodeInfo.Location location = 1; */ private $location; - private $has_location = false; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Google\Protobuf\Internal\SourceCodeInfo\Location[]|\Google\Protobuf\Internal\RepeatedField $location + * A Location identifies a piece of source code in a .proto file which + * corresponds to a particular definition. This information is intended + * to be useful to IDEs, code indexers, documentation generators, and similar + * tools. + * For example, say we have a file like: + * message Foo { + * optional string foo = 1; + * } + * Let's look at just the field definition: + * optional string foo = 1; + * ^ ^^ ^^ ^ ^^^ + * a bc de f ghi + * We have the following locations: + * span path represents + * [a,i) [ 4, 0, 2, 0 ] The whole field definition. + * [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + * [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + * [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + * [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + * Notes: + * - A location may refer to a repeated field itself (i.e. not to any + * particular index within it). This is used whenever a set of elements are + * logically enclosed in a single code segment. For example, an entire + * extend block (possibly containing multiple extension definitions) will + * have an outer location whose path refers to the "extensions" repeated + * field without an index. + * - Multiple locations may have the same path. This happens when a single + * logical declaration is spread out across multiple places. The most + * obvious example is the "extend" block again -- there may be multiple + * extend blocks in the same scope, each of which will have the same path. + * - A location's span is not always a subset of its parent's span. For + * example, the "extendee" of an extension declaration appears at the + * beginning of the "extend" block and is shared by all extensions within + * the block. + * - Just because a location's span is a subset of some other location's span + * does not mean that it is a descendant. For example, a "group" defines + * both a type and a field in a single declaration. Thus, the locations + * corresponding to the type and field and their components will overlap. + * - Code which tries to interpret locations should probably be designed to + * ignore those that it doesn't understand, as more types of locations could + * be recorded in the future. + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -107,7 +156,7 @@ public function __construct() { * beginning of the "extend" block and is shared by all extensions within * the block. * - Just because a location's span is a subset of some other location's span - * does not mean that it is a descendent. For example, a "group" defines + * does not mean that it is a descendant. For example, a "group" defines * both a type and a field in a single declaration. Thus, the locations * corresponding to the type and field and their components will overlap. * - Code which tries to interpret locations should probably be designed to @@ -158,7 +207,7 @@ public function getLocation() * beginning of the "extend" block and is shared by all extensions within * the block. * - Just because a location's span is a subset of some other location's span - * does not mean that it is a descendent. For example, a "group" defines + * does not mean that it is a descendant. For example, a "group" defines * both a type and a field in a single declaration. Thus, the locations * corresponding to the type and field and their components will overlap. * - Code which tries to interpret locations should probably be designed to @@ -166,22 +215,16 @@ public function getLocation() * be recorded in the future. * * Generated from protobuf field repeated .google.protobuf.SourceCodeInfo.Location location = 1; - * @param \Google\Protobuf\Internal\SourceCodeInfo_Location[]|\Google\Protobuf\Internal\RepeatedField $var + * @param \Google\Protobuf\Internal\SourceCodeInfo\Location[]|\Google\Protobuf\Internal\RepeatedField $var * @return $this */ public function setLocation($var) { - $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\SourceCodeInfo_Location::class); + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\SourceCodeInfo\Location::class); $this->location = $arr; - $this->has_location = true; return $this; } - public function hasLocation() - { - return $this->has_location; - } - } diff --git a/php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php b/php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php new file mode 100644 index 0000000000000..c4cc667e3a4bf --- /dev/null +++ b/php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php @@ -0,0 +1,448 @@ +google.protobuf.SourceCodeInfo.Location + */ +class Location extends \Google\Protobuf\Internal\Message +{ + /** + * Identifies which part of the FileDescriptorProto was defined at this + * location. + * Each element is a field number or an index. They form a path from + * the root FileDescriptorProto to the place where the definition. For + * example, this path: + * [ 4, 3, 2, 7, 1 ] + * refers to: + * file.message_type(3) // 4, 3 + * .field(7) // 2, 7 + * .name() // 1 + * This is because FileDescriptorProto.message_type has field number 4: + * repeated DescriptorProto message_type = 4; + * and DescriptorProto.field has field number 2: + * repeated FieldDescriptorProto field = 2; + * and FieldDescriptorProto.name has field number 1: + * optional string name = 1; + * Thus, the above path gives the location of a field name. If we removed + * the last element: + * [ 4, 3, 2, 7 ] + * this path refers to the whole field declaration (from the beginning + * of the label to the terminating semicolon). + * + * Generated from protobuf field repeated int32 path = 1 [packed = true]; + */ + private $path; + /** + * Always has exactly three or four elements: start line, start column, + * end line (optional, otherwise assumed same as start line), end column. + * These are packed into a single field for efficiency. Note that line + * and column numbers are zero-based -- typically you will want to add + * 1 to each before displaying to a user. + * + * Generated from protobuf field repeated int32 span = 2 [packed = true]; + */ + private $span; + /** + * If this SourceCodeInfo represents a complete declaration, these are any + * comments appearing before and after the declaration which appear to be + * attached to the declaration. + * A series of line comments appearing on consecutive lines, with no other + * tokens appearing on those lines, will be treated as a single comment. + * leading_detached_comments will keep paragraphs of comments that appear + * before (but not connected to) the current element. Each paragraph, + * separated by empty lines, will be one comment element in the repeated + * field. + * Only the comment content is provided; comment markers (e.g. //) are + * stripped out. For block comments, leading whitespace and an asterisk + * will be stripped from the beginning of each line other than the first. + * Newlines are included in the output. + * Examples: + * optional int32 foo = 1; // Comment attached to foo. + * // Comment attached to bar. + * optional int32 bar = 2; + * optional string baz = 3; + * // Comment attached to baz. + * // Another line attached to baz. + * // Comment attached to qux. + * // + * // Another line attached to qux. + * optional double qux = 4; + * // Detached comment for corge. This is not leading or trailing comments + * // to qux or corge because there are blank lines separating it from + * // both. + * // Detached comment for corge paragraph 2. + * optional string corge = 5; + * /* Block comment attached + * * to corge. Leading asterisks + * * will be removed. */ + * /* Block comment attached to + * * grault. */ + * optional int32 grault = 6; + * // ignored detached comments. + * + * Generated from protobuf field optional string leading_comments = 3; + */ + protected $leading_comments = null; + /** + * Generated from protobuf field optional string trailing_comments = 4; + */ + protected $trailing_comments = null; + /** + * Generated from protobuf field repeated string leading_detached_comments = 6; + */ + private $leading_detached_comments; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int[]|\Google\Protobuf\Internal\RepeatedField $path + * Identifies which part of the FileDescriptorProto was defined at this + * location. + * Each element is a field number or an index. They form a path from + * the root FileDescriptorProto to the place where the definition. For + * example, this path: + * [ 4, 3, 2, 7, 1 ] + * refers to: + * file.message_type(3) // 4, 3 + * .field(7) // 2, 7 + * .name() // 1 + * This is because FileDescriptorProto.message_type has field number 4: + * repeated DescriptorProto message_type = 4; + * and DescriptorProto.field has field number 2: + * repeated FieldDescriptorProto field = 2; + * and FieldDescriptorProto.name has field number 1: + * optional string name = 1; + * Thus, the above path gives the location of a field name. If we removed + * the last element: + * [ 4, 3, 2, 7 ] + * this path refers to the whole field declaration (from the beginning + * of the label to the terminating semicolon). + * @type int[]|\Google\Protobuf\Internal\RepeatedField $span + * Always has exactly three or four elements: start line, start column, + * end line (optional, otherwise assumed same as start line), end column. + * These are packed into a single field for efficiency. Note that line + * and column numbers are zero-based -- typically you will want to add + * 1 to each before displaying to a user. + * @type string $leading_comments + * If this SourceCodeInfo represents a complete declaration, these are any + * comments appearing before and after the declaration which appear to be + * attached to the declaration. + * A series of line comments appearing on consecutive lines, with no other + * tokens appearing on those lines, will be treated as a single comment. + * leading_detached_comments will keep paragraphs of comments that appear + * before (but not connected to) the current element. Each paragraph, + * separated by empty lines, will be one comment element in the repeated + * field. + * Only the comment content is provided; comment markers (e.g. //) are + * stripped out. For block comments, leading whitespace and an asterisk + * will be stripped from the beginning of each line other than the first. + * Newlines are included in the output. + * Examples: + * optional int32 foo = 1; // Comment attached to foo. + * // Comment attached to bar. + * optional int32 bar = 2; + * optional string baz = 3; + * // Comment attached to baz. + * // Another line attached to baz. + * // Comment attached to qux. + * // + * // Another line attached to qux. + * optional double qux = 4; + * // Detached comment for corge. This is not leading or trailing comments + * // to qux or corge because there are blank lines separating it from + * // both. + * // Detached comment for corge paragraph 2. + * optional string corge = 5; + * /* Block comment attached + * * to corge. Leading asterisks + * * will be removed. */ + * /* Block comment attached to + * * grault. */ + * optional int32 grault = 6; + * // ignored detached comments. + * @type string $trailing_comments + * @type string[]|\Google\Protobuf\Internal\RepeatedField $leading_detached_comments + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); + parent::__construct($data); + } + + /** + * Identifies which part of the FileDescriptorProto was defined at this + * location. + * Each element is a field number or an index. They form a path from + * the root FileDescriptorProto to the place where the definition. For + * example, this path: + * [ 4, 3, 2, 7, 1 ] + * refers to: + * file.message_type(3) // 4, 3 + * .field(7) // 2, 7 + * .name() // 1 + * This is because FileDescriptorProto.message_type has field number 4: + * repeated DescriptorProto message_type = 4; + * and DescriptorProto.field has field number 2: + * repeated FieldDescriptorProto field = 2; + * and FieldDescriptorProto.name has field number 1: + * optional string name = 1; + * Thus, the above path gives the location of a field name. If we removed + * the last element: + * [ 4, 3, 2, 7 ] + * this path refers to the whole field declaration (from the beginning + * of the label to the terminating semicolon). + * + * Generated from protobuf field repeated int32 path = 1 [packed = true]; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getPath() + { + return $this->path; + } + + /** + * Identifies which part of the FileDescriptorProto was defined at this + * location. + * Each element is a field number or an index. They form a path from + * the root FileDescriptorProto to the place where the definition. For + * example, this path: + * [ 4, 3, 2, 7, 1 ] + * refers to: + * file.message_type(3) // 4, 3 + * .field(7) // 2, 7 + * .name() // 1 + * This is because FileDescriptorProto.message_type has field number 4: + * repeated DescriptorProto message_type = 4; + * and DescriptorProto.field has field number 2: + * repeated FieldDescriptorProto field = 2; + * and FieldDescriptorProto.name has field number 1: + * optional string name = 1; + * Thus, the above path gives the location of a field name. If we removed + * the last element: + * [ 4, 3, 2, 7 ] + * this path refers to the whole field declaration (from the beginning + * of the label to the terminating semicolon). + * + * Generated from protobuf field repeated int32 path = 1 [packed = true]; + * @param int[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setPath($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); + $this->path = $arr; + + return $this; + } + + /** + * Always has exactly three or four elements: start line, start column, + * end line (optional, otherwise assumed same as start line), end column. + * These are packed into a single field for efficiency. Note that line + * and column numbers are zero-based -- typically you will want to add + * 1 to each before displaying to a user. + * + * Generated from protobuf field repeated int32 span = 2 [packed = true]; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getSpan() + { + return $this->span; + } + + /** + * Always has exactly three or four elements: start line, start column, + * end line (optional, otherwise assumed same as start line), end column. + * These are packed into a single field for efficiency. Note that line + * and column numbers are zero-based -- typically you will want to add + * 1 to each before displaying to a user. + * + * Generated from protobuf field repeated int32 span = 2 [packed = true]; + * @param int[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setSpan($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); + $this->span = $arr; + + return $this; + } + + /** + * If this SourceCodeInfo represents a complete declaration, these are any + * comments appearing before and after the declaration which appear to be + * attached to the declaration. + * A series of line comments appearing on consecutive lines, with no other + * tokens appearing on those lines, will be treated as a single comment. + * leading_detached_comments will keep paragraphs of comments that appear + * before (but not connected to) the current element. Each paragraph, + * separated by empty lines, will be one comment element in the repeated + * field. + * Only the comment content is provided; comment markers (e.g. //) are + * stripped out. For block comments, leading whitespace and an asterisk + * will be stripped from the beginning of each line other than the first. + * Newlines are included in the output. + * Examples: + * optional int32 foo = 1; // Comment attached to foo. + * // Comment attached to bar. + * optional int32 bar = 2; + * optional string baz = 3; + * // Comment attached to baz. + * // Another line attached to baz. + * // Comment attached to qux. + * // + * // Another line attached to qux. + * optional double qux = 4; + * // Detached comment for corge. This is not leading or trailing comments + * // to qux or corge because there are blank lines separating it from + * // both. + * // Detached comment for corge paragraph 2. + * optional string corge = 5; + * /* Block comment attached + * * to corge. Leading asterisks + * * will be removed. */ + * /* Block comment attached to + * * grault. */ + * optional int32 grault = 6; + * // ignored detached comments. + * + * Generated from protobuf field optional string leading_comments = 3; + * @return string + */ + public function getLeadingComments() + { + return isset($this->leading_comments) ? $this->leading_comments : ''; + } + + public function hasLeadingComments() + { + return isset($this->leading_comments); + } + + public function clearLeadingComments() + { + unset($this->leading_comments); + } + + /** + * If this SourceCodeInfo represents a complete declaration, these are any + * comments appearing before and after the declaration which appear to be + * attached to the declaration. + * A series of line comments appearing on consecutive lines, with no other + * tokens appearing on those lines, will be treated as a single comment. + * leading_detached_comments will keep paragraphs of comments that appear + * before (but not connected to) the current element. Each paragraph, + * separated by empty lines, will be one comment element in the repeated + * field. + * Only the comment content is provided; comment markers (e.g. //) are + * stripped out. For block comments, leading whitespace and an asterisk + * will be stripped from the beginning of each line other than the first. + * Newlines are included in the output. + * Examples: + * optional int32 foo = 1; // Comment attached to foo. + * // Comment attached to bar. + * optional int32 bar = 2; + * optional string baz = 3; + * // Comment attached to baz. + * // Another line attached to baz. + * // Comment attached to qux. + * // + * // Another line attached to qux. + * optional double qux = 4; + * // Detached comment for corge. This is not leading or trailing comments + * // to qux or corge because there are blank lines separating it from + * // both. + * // Detached comment for corge paragraph 2. + * optional string corge = 5; + * /* Block comment attached + * * to corge. Leading asterisks + * * will be removed. */ + * /* Block comment attached to + * * grault. */ + * optional int32 grault = 6; + * // ignored detached comments. + * + * Generated from protobuf field optional string leading_comments = 3; + * @param string $var + * @return $this + */ + public function setLeadingComments($var) + { + GPBUtil::checkString($var, True); + $this->leading_comments = $var; + + return $this; + } + + /** + * Generated from protobuf field optional string trailing_comments = 4; + * @return string + */ + public function getTrailingComments() + { + return isset($this->trailing_comments) ? $this->trailing_comments : ''; + } + + public function hasTrailingComments() + { + return isset($this->trailing_comments); + } + + public function clearTrailingComments() + { + unset($this->trailing_comments); + } + + /** + * Generated from protobuf field optional string trailing_comments = 4; + * @param string $var + * @return $this + */ + public function setTrailingComments($var) + { + GPBUtil::checkString($var, True); + $this->trailing_comments = $var; + + return $this; + } + + /** + * Generated from protobuf field repeated string leading_detached_comments = 6; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getLeadingDetachedComments() + { + return $this->leading_detached_comments; + } + + /** + * Generated from protobuf field repeated string leading_detached_comments = 6; + * @param string[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setLeadingDetachedComments($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING); + $this->leading_detached_comments = $arr; + + return $this; + } + +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(Location::class, \Google\Protobuf\Internal\SourceCodeInfo_Location::class); + diff --git a/php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php b/php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php index 19ed2bc2291e8..1346492d25c9e 100644 --- a/php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php +++ b/php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php @@ -4,382 +4,13 @@ namespace Google\Protobuf\Internal; -use Google\Protobuf\Internal\GPBType; -use Google\Protobuf\Internal\GPBWire; -use Google\Protobuf\Internal\RepeatedField; -use Google\Protobuf\Internal\InputStream; -use Google\Protobuf\Internal\GPBUtil; - -/** - * Generated from protobuf message google.protobuf.SourceCodeInfo.Location - */ -class SourceCodeInfo_Location extends \Google\Protobuf\Internal\Message -{ - /** - * Identifies which part of the FileDescriptorProto was defined at this - * location. - * Each element is a field number or an index. They form a path from - * the root FileDescriptorProto to the place where the definition. For - * example, this path: - * [ 4, 3, 2, 7, 1 ] - * refers to: - * file.message_type(3) // 4, 3 - * .field(7) // 2, 7 - * .name() // 1 - * This is because FileDescriptorProto.message_type has field number 4: - * repeated DescriptorProto message_type = 4; - * and DescriptorProto.field has field number 2: - * repeated FieldDescriptorProto field = 2; - * and FieldDescriptorProto.name has field number 1: - * optional string name = 1; - * Thus, the above path gives the location of a field name. If we removed - * the last element: - * [ 4, 3, 2, 7 ] - * this path refers to the whole field declaration (from the beginning - * of the label to the terminating semicolon). - * - * Generated from protobuf field repeated int32 path = 1 [packed = true]; - */ - private $path; - private $has_path = false; - /** - * Always has exactly three or four elements: start line, start column, - * end line (optional, otherwise assumed same as start line), end column. - * These are packed into a single field for efficiency. Note that line - * and column numbers are zero-based -- typically you will want to add - * 1 to each before displaying to a user. - * - * Generated from protobuf field repeated int32 span = 2 [packed = true]; - */ - private $span; - private $has_span = false; - /** - * If this SourceCodeInfo represents a complete declaration, these are any - * comments appearing before and after the declaration which appear to be - * attached to the declaration. - * A series of line comments appearing on consecutive lines, with no other - * tokens appearing on those lines, will be treated as a single comment. - * leading_detached_comments will keep paragraphs of comments that appear - * before (but not connected to) the current element. Each paragraph, - * separated by empty lines, will be one comment element in the repeated - * field. - * Only the comment content is provided; comment markers (e.g. //) are - * stripped out. For block comments, leading whitespace and an asterisk - * will be stripped from the beginning of each line other than the first. - * Newlines are included in the output. - * Examples: - * optional int32 foo = 1; // Comment attached to foo. - * // Comment attached to bar. - * optional int32 bar = 2; - * optional string baz = 3; - * // Comment attached to baz. - * // Another line attached to baz. - * // Comment attached to qux. - * // - * // Another line attached to qux. - * optional double qux = 4; - * // Detached comment for corge. This is not leading or trailing comments - * // to qux or corge because there are blank lines separating it from - * // both. - * // Detached comment for corge paragraph 2. - * optional string corge = 5; - * /* Block comment attached - * * to corge. Leading asterisks - * * will be removed. */ - * /* Block comment attached to - * * grault. */ - * optional int32 grault = 6; - * // ignored detached comments. - * - * Generated from protobuf field optional string leading_comments = 3; - */ - private $leading_comments = ''; - private $has_leading_comments = false; - /** - * Generated from protobuf field optional string trailing_comments = 4; - */ - private $trailing_comments = ''; - private $has_trailing_comments = false; - /** - * Generated from protobuf field repeated string leading_detached_comments = 6; - */ - private $leading_detached_comments; - private $has_leading_detached_comments = false; - - public function __construct() { - \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); - } - +if (false) { /** - * Identifies which part of the FileDescriptorProto was defined at this - * location. - * Each element is a field number or an index. They form a path from - * the root FileDescriptorProto to the place where the definition. For - * example, this path: - * [ 4, 3, 2, 7, 1 ] - * refers to: - * file.message_type(3) // 4, 3 - * .field(7) // 2, 7 - * .name() // 1 - * This is because FileDescriptorProto.message_type has field number 4: - * repeated DescriptorProto message_type = 4; - * and DescriptorProto.field has field number 2: - * repeated FieldDescriptorProto field = 2; - * and FieldDescriptorProto.name has field number 1: - * optional string name = 1; - * Thus, the above path gives the location of a field name. If we removed - * the last element: - * [ 4, 3, 2, 7 ] - * this path refers to the whole field declaration (from the beginning - * of the label to the terminating semicolon). - * - * Generated from protobuf field repeated int32 path = 1 [packed = true]; - * @return \Google\Protobuf\Internal\RepeatedField + * This class is deprecated. Use Google\Protobuf\Internal\SourceCodeInfo\Location instead. + * @deprecated */ - public function getPath() - { - return $this->path; - } - - /** - * Identifies which part of the FileDescriptorProto was defined at this - * location. - * Each element is a field number or an index. They form a path from - * the root FileDescriptorProto to the place where the definition. For - * example, this path: - * [ 4, 3, 2, 7, 1 ] - * refers to: - * file.message_type(3) // 4, 3 - * .field(7) // 2, 7 - * .name() // 1 - * This is because FileDescriptorProto.message_type has field number 4: - * repeated DescriptorProto message_type = 4; - * and DescriptorProto.field has field number 2: - * repeated FieldDescriptorProto field = 2; - * and FieldDescriptorProto.name has field number 1: - * optional string name = 1; - * Thus, the above path gives the location of a field name. If we removed - * the last element: - * [ 4, 3, 2, 7 ] - * this path refers to the whole field declaration (from the beginning - * of the label to the terminating semicolon). - * - * Generated from protobuf field repeated int32 path = 1 [packed = true]; - * @param int[]|\Google\Protobuf\Internal\RepeatedField $var - * @return $this - */ - public function setPath($var) - { - $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); - $this->path = $arr; - $this->has_path = true; - - return $this; - } - - public function hasPath() - { - return $this->has_path; - } - - /** - * Always has exactly three or four elements: start line, start column, - * end line (optional, otherwise assumed same as start line), end column. - * These are packed into a single field for efficiency. Note that line - * and column numbers are zero-based -- typically you will want to add - * 1 to each before displaying to a user. - * - * Generated from protobuf field repeated int32 span = 2 [packed = true]; - * @return \Google\Protobuf\Internal\RepeatedField - */ - public function getSpan() - { - return $this->span; - } - - /** - * Always has exactly three or four elements: start line, start column, - * end line (optional, otherwise assumed same as start line), end column. - * These are packed into a single field for efficiency. Note that line - * and column numbers are zero-based -- typically you will want to add - * 1 to each before displaying to a user. - * - * Generated from protobuf field repeated int32 span = 2 [packed = true]; - * @param int[]|\Google\Protobuf\Internal\RepeatedField $var - * @return $this - */ - public function setSpan($var) - { - $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); - $this->span = $arr; - $this->has_span = true; - - return $this; - } - - public function hasSpan() - { - return $this->has_span; - } - - /** - * If this SourceCodeInfo represents a complete declaration, these are any - * comments appearing before and after the declaration which appear to be - * attached to the declaration. - * A series of line comments appearing on consecutive lines, with no other - * tokens appearing on those lines, will be treated as a single comment. - * leading_detached_comments will keep paragraphs of comments that appear - * before (but not connected to) the current element. Each paragraph, - * separated by empty lines, will be one comment element in the repeated - * field. - * Only the comment content is provided; comment markers (e.g. //) are - * stripped out. For block comments, leading whitespace and an asterisk - * will be stripped from the beginning of each line other than the first. - * Newlines are included in the output. - * Examples: - * optional int32 foo = 1; // Comment attached to foo. - * // Comment attached to bar. - * optional int32 bar = 2; - * optional string baz = 3; - * // Comment attached to baz. - * // Another line attached to baz. - * // Comment attached to qux. - * // - * // Another line attached to qux. - * optional double qux = 4; - * // Detached comment for corge. This is not leading or trailing comments - * // to qux or corge because there are blank lines separating it from - * // both. - * // Detached comment for corge paragraph 2. - * optional string corge = 5; - * /* Block comment attached - * * to corge. Leading asterisks - * * will be removed. */ - * /* Block comment attached to - * * grault. */ - * optional int32 grault = 6; - * // ignored detached comments. - * - * Generated from protobuf field optional string leading_comments = 3; - * @return string - */ - public function getLeadingComments() - { - return $this->leading_comments; - } - - /** - * If this SourceCodeInfo represents a complete declaration, these are any - * comments appearing before and after the declaration which appear to be - * attached to the declaration. - * A series of line comments appearing on consecutive lines, with no other - * tokens appearing on those lines, will be treated as a single comment. - * leading_detached_comments will keep paragraphs of comments that appear - * before (but not connected to) the current element. Each paragraph, - * separated by empty lines, will be one comment element in the repeated - * field. - * Only the comment content is provided; comment markers (e.g. //) are - * stripped out. For block comments, leading whitespace and an asterisk - * will be stripped from the beginning of each line other than the first. - * Newlines are included in the output. - * Examples: - * optional int32 foo = 1; // Comment attached to foo. - * // Comment attached to bar. - * optional int32 bar = 2; - * optional string baz = 3; - * // Comment attached to baz. - * // Another line attached to baz. - * // Comment attached to qux. - * // - * // Another line attached to qux. - * optional double qux = 4; - * // Detached comment for corge. This is not leading or trailing comments - * // to qux or corge because there are blank lines separating it from - * // both. - * // Detached comment for corge paragraph 2. - * optional string corge = 5; - * /* Block comment attached - * * to corge. Leading asterisks - * * will be removed. */ - * /* Block comment attached to - * * grault. */ - * optional int32 grault = 6; - * // ignored detached comments. - * - * Generated from protobuf field optional string leading_comments = 3; - * @param string $var - * @return $this - */ - public function setLeadingComments($var) - { - GPBUtil::checkString($var, True); - $this->leading_comments = $var; - $this->has_leading_comments = true; - - return $this; - } - - public function hasLeadingComments() - { - return $this->has_leading_comments; - } - - /** - * Generated from protobuf field optional string trailing_comments = 4; - * @return string - */ - public function getTrailingComments() - { - return $this->trailing_comments; - } - - /** - * Generated from protobuf field optional string trailing_comments = 4; - * @param string $var - * @return $this - */ - public function setTrailingComments($var) - { - GPBUtil::checkString($var, True); - $this->trailing_comments = $var; - $this->has_trailing_comments = true; - - return $this; - } - - public function hasTrailingComments() - { - return $this->has_trailing_comments; - } - - /** - * Generated from protobuf field repeated string leading_detached_comments = 6; - * @return \Google\Protobuf\Internal\RepeatedField - */ - public function getLeadingDetachedComments() - { - return $this->leading_detached_comments; - } - - /** - * Generated from protobuf field repeated string leading_detached_comments = 6; - * @param string[]|\Google\Protobuf\Internal\RepeatedField $var - * @return $this - */ - public function setLeadingDetachedComments($var) - { - $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING); - $this->leading_detached_comments = $arr; - $this->has_leading_detached_comments = true; - - return $this; - } - - public function hasLeadingDetachedComments() - { - return $this->has_leading_detached_comments; - } - + class SourceCodeInfo_Location {} } +class_exists(SourceCodeInfo\Location::class); +@trigger_error('Google\Protobuf\Internal\SourceCodeInfo_Location is deprecated and will be removed in the next major release. Use Google\Protobuf\Internal\SourceCodeInfo\Location instead', E_USER_DEPRECATED); diff --git a/php/src/Google/Protobuf/Internal/TimestampBase.php b/php/src/Google/Protobuf/Internal/TimestampBase.php new file mode 100644 index 0000000000000..653d1e99d71c0 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/TimestampBase.php @@ -0,0 +1,32 @@ +seconds = $datetime->getTimestamp(); + $this->nanos = 1000 * $datetime->format('u'); + } + + /** + * Converts Timestamp to PHP DateTime. + * + * @return \DateTime $datetime + */ + public function toDateTime() + { + $time = sprintf('%s.%06d', $this->seconds, $this->nanos / 1000); + return \DateTime::createFromFormat('U.u', $time); + } +} diff --git a/php/src/Google/Protobuf/Internal/UninterpretedOption.php b/php/src/Google/Protobuf/Internal/UninterpretedOption.php index 4d342eb33b310..a2aae3e0a7413 100644 --- a/php/src/Google/Protobuf/Internal/UninterpretedOption.php +++ b/php/src/Google/Protobuf/Internal/UninterpretedOption.php @@ -26,44 +26,54 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated .google.protobuf.UninterpretedOption.NamePart name = 2; */ private $name; - private $has_name = false; /** * The value of the uninterpreted option, in whatever type the tokenizer * identified it as during parsing. Exactly one of these should be set. * * Generated from protobuf field optional string identifier_value = 3; */ - private $identifier_value = ''; - private $has_identifier_value = false; + protected $identifier_value = null; /** * Generated from protobuf field optional uint64 positive_int_value = 4; */ - private $positive_int_value = 0; - private $has_positive_int_value = false; + protected $positive_int_value = null; /** * Generated from protobuf field optional int64 negative_int_value = 5; */ - private $negative_int_value = 0; - private $has_negative_int_value = false; + protected $negative_int_value = null; /** * Generated from protobuf field optional double double_value = 6; */ - private $double_value = 0.0; - private $has_double_value = false; + protected $double_value = null; /** * Generated from protobuf field optional bytes string_value = 7; */ - private $string_value = ''; - private $has_string_value = false; + protected $string_value = null; /** * Generated from protobuf field optional string aggregate_value = 8; */ - private $aggregate_value = ''; - private $has_aggregate_value = false; + protected $aggregate_value = null; - public function __construct() { + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Google\Protobuf\Internal\UninterpretedOption\NamePart[]|\Google\Protobuf\Internal\RepeatedField $name + * @type string $identifier_value + * The value of the uninterpreted option, in whatever type the tokenizer + * identified it as during parsing. Exactly one of these should be set. + * @type int|string $positive_int_value + * @type int|string $negative_int_value + * @type float $double_value + * @type string $string_value + * @type string $aggregate_value + * } + */ + public function __construct($data = NULL) { \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); + parent::__construct($data); } /** @@ -77,23 +87,17 @@ public function getName() /** * Generated from protobuf field repeated .google.protobuf.UninterpretedOption.NamePart name = 2; - * @param \Google\Protobuf\Internal\UninterpretedOption_NamePart[]|\Google\Protobuf\Internal\RepeatedField $var + * @param \Google\Protobuf\Internal\UninterpretedOption\NamePart[]|\Google\Protobuf\Internal\RepeatedField $var * @return $this */ public function setName($var) { - $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption_NamePart::class); + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption\NamePart::class); $this->name = $arr; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * The value of the uninterpreted option, in whatever type the tokenizer * identified it as during parsing. Exactly one of these should be set. @@ -103,7 +107,17 @@ public function hasName() */ public function getIdentifierValue() { - return $this->identifier_value; + return isset($this->identifier_value) ? $this->identifier_value : ''; + } + + public function hasIdentifierValue() + { + return isset($this->identifier_value); + } + + public function clearIdentifierValue() + { + unset($this->identifier_value); } /** @@ -118,23 +132,27 @@ public function setIdentifierValue($var) { GPBUtil::checkString($var, True); $this->identifier_value = $var; - $this->has_identifier_value = true; return $this; } - public function hasIdentifierValue() - { - return $this->has_identifier_value; - } - /** * Generated from protobuf field optional uint64 positive_int_value = 4; * @return int|string */ public function getPositiveIntValue() { - return $this->positive_int_value; + return isset($this->positive_int_value) ? $this->positive_int_value : 0; + } + + public function hasPositiveIntValue() + { + return isset($this->positive_int_value); + } + + public function clearPositiveIntValue() + { + unset($this->positive_int_value); } /** @@ -146,23 +164,27 @@ public function setPositiveIntValue($var) { GPBUtil::checkUint64($var); $this->positive_int_value = $var; - $this->has_positive_int_value = true; return $this; } - public function hasPositiveIntValue() - { - return $this->has_positive_int_value; - } - /** * Generated from protobuf field optional int64 negative_int_value = 5; * @return int|string */ public function getNegativeIntValue() { - return $this->negative_int_value; + return isset($this->negative_int_value) ? $this->negative_int_value : 0; + } + + public function hasNegativeIntValue() + { + return isset($this->negative_int_value); + } + + public function clearNegativeIntValue() + { + unset($this->negative_int_value); } /** @@ -174,23 +196,27 @@ public function setNegativeIntValue($var) { GPBUtil::checkInt64($var); $this->negative_int_value = $var; - $this->has_negative_int_value = true; return $this; } - public function hasNegativeIntValue() - { - return $this->has_negative_int_value; - } - /** * Generated from protobuf field optional double double_value = 6; * @return float */ public function getDoubleValue() { - return $this->double_value; + return isset($this->double_value) ? $this->double_value : 0.0; + } + + public function hasDoubleValue() + { + return isset($this->double_value); + } + + public function clearDoubleValue() + { + unset($this->double_value); } /** @@ -202,23 +228,27 @@ public function setDoubleValue($var) { GPBUtil::checkDouble($var); $this->double_value = $var; - $this->has_double_value = true; return $this; } - public function hasDoubleValue() - { - return $this->has_double_value; - } - /** * Generated from protobuf field optional bytes string_value = 7; * @return string */ public function getStringValue() { - return $this->string_value; + return isset($this->string_value) ? $this->string_value : ''; + } + + public function hasStringValue() + { + return isset($this->string_value); + } + + public function clearStringValue() + { + unset($this->string_value); } /** @@ -230,23 +260,27 @@ public function setStringValue($var) { GPBUtil::checkString($var, False); $this->string_value = $var; - $this->has_string_value = true; return $this; } - public function hasStringValue() - { - return $this->has_string_value; - } - /** * Generated from protobuf field optional string aggregate_value = 8; * @return string */ public function getAggregateValue() { - return $this->aggregate_value; + return isset($this->aggregate_value) ? $this->aggregate_value : ''; + } + + public function hasAggregateValue() + { + return isset($this->aggregate_value); + } + + public function clearAggregateValue() + { + unset($this->aggregate_value); } /** @@ -258,15 +292,9 @@ public function setAggregateValue($var) { GPBUtil::checkString($var, True); $this->aggregate_value = $var; - $this->has_aggregate_value = true; return $this; } - public function hasAggregateValue() - { - return $this->has_aggregate_value; - } - } diff --git a/php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php b/php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php new file mode 100644 index 0000000000000..6212d1e4577e2 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php @@ -0,0 +1,116 @@ +google.protobuf.UninterpretedOption.NamePart + */ +class NamePart extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field required string name_part = 1; + */ + protected $name_part = null; + /** + * Generated from protobuf field required bool is_extension = 2; + */ + protected $is_extension = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name_part + * @type bool $is_extension + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field required string name_part = 1; + * @return string + */ + public function getNamePart() + { + return isset($this->name_part) ? $this->name_part : ''; + } + + public function hasNamePart() + { + return isset($this->name_part); + } + + public function clearNamePart() + { + unset($this->name_part); + } + + /** + * Generated from protobuf field required string name_part = 1; + * @param string $var + * @return $this + */ + public function setNamePart($var) + { + GPBUtil::checkString($var, True); + $this->name_part = $var; + + return $this; + } + + /** + * Generated from protobuf field required bool is_extension = 2; + * @return bool + */ + public function getIsExtension() + { + return isset($this->is_extension) ? $this->is_extension : false; + } + + public function hasIsExtension() + { + return isset($this->is_extension); + } + + public function clearIsExtension() + { + unset($this->is_extension); + } + + /** + * Generated from protobuf field required bool is_extension = 2; + * @param bool $var + * @return $this + */ + public function setIsExtension($var) + { + GPBUtil::checkBool($var); + $this->is_extension = $var; + + return $this; + } + +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(NamePart::class, \Google\Protobuf\Internal\UninterpretedOption_NamePart::class); + diff --git a/php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php b/php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php index c9a6fc3c7ff6f..9750eb010d645 100644 --- a/php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php +++ b/php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php @@ -4,94 +4,13 @@ namespace Google\Protobuf\Internal; -use Google\Protobuf\Internal\GPBType; -use Google\Protobuf\Internal\GPBWire; -use Google\Protobuf\Internal\RepeatedField; -use Google\Protobuf\Internal\InputStream; -use Google\Protobuf\Internal\GPBUtil; - -/** - * The name of the uninterpreted option. Each string represents a segment in - * a dot-separated name. is_extension is true iff a segment represents an - * extension (denoted with parentheses in options specs in .proto files). - * E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents - * "foo.(bar.baz).qux". - * - * Generated from protobuf message google.protobuf.UninterpretedOption.NamePart - */ -class UninterpretedOption_NamePart extends \Google\Protobuf\Internal\Message -{ - /** - * Generated from protobuf field required string name_part = 1; - */ - private $name_part = ''; - private $has_name_part = false; +if (false) { /** - * Generated from protobuf field required bool is_extension = 2; + * This class is deprecated. Use Google\Protobuf\Internal\UninterpretedOption\NamePart instead. + * @deprecated */ - private $is_extension = false; - private $has_is_extension = false; - - public function __construct() { - \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); - parent::__construct(); - } - - /** - * Generated from protobuf field required string name_part = 1; - * @return string - */ - public function getNamePart() - { - return $this->name_part; - } - - /** - * Generated from protobuf field required string name_part = 1; - * @param string $var - * @return $this - */ - public function setNamePart($var) - { - GPBUtil::checkString($var, True); - $this->name_part = $var; - $this->has_name_part = true; - - return $this; - } - - public function hasNamePart() - { - return $this->has_name_part; - } - - /** - * Generated from protobuf field required bool is_extension = 2; - * @return bool - */ - public function getIsExtension() - { - return $this->is_extension; - } - - /** - * Generated from protobuf field required bool is_extension = 2; - * @param bool $var - * @return $this - */ - public function setIsExtension($var) - { - GPBUtil::checkBool($var); - $this->is_extension = $var; - $this->has_is_extension = true; - - return $this; - } - - public function hasIsExtension() - { - return $this->has_is_extension; - } - + class UninterpretedOption_NamePart {} } +class_exists(UninterpretedOption\NamePart::class); +@trigger_error('Google\Protobuf\Internal\UninterpretedOption_NamePart is deprecated and will be removed in the next major release. Use Google\Protobuf\Internal\UninterpretedOption\NamePart instead', E_USER_DEPRECATED); diff --git a/php/src/Google/Protobuf/ListValue.php b/php/src/Google/Protobuf/ListValue.php new file mode 100644 index 0000000000000..70f542326f760 --- /dev/null +++ b/php/src/Google/Protobuf/ListValue.php @@ -0,0 +1,68 @@ +google.protobuf.ListValue + */ +class ListValue extends \Google\Protobuf\Internal\Message +{ + /** + * Repeated field of dynamically typed values. + * + * Generated from protobuf field repeated .google.protobuf.Value values = 1; + */ + private $values; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Google\Protobuf\Value[]|\Google\Protobuf\Internal\RepeatedField $values + * Repeated field of dynamically typed values. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Struct::initOnce(); + parent::__construct($data); + } + + /** + * Repeated field of dynamically typed values. + * + * Generated from protobuf field repeated .google.protobuf.Value values = 1; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getValues() + { + return $this->values; + } + + /** + * Repeated field of dynamically typed values. + * + * Generated from protobuf field repeated .google.protobuf.Value values = 1; + * @param \Google\Protobuf\Value[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setValues($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Value::class); + $this->values = $arr; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Method.php b/php/src/Google/Protobuf/Method.php new file mode 100644 index 0000000000000..2755baa0e8b07 --- /dev/null +++ b/php/src/Google/Protobuf/Method.php @@ -0,0 +1,271 @@ +google.protobuf.Method + */ +class Method extends \Google\Protobuf\Internal\Message +{ + /** + * The simple name of this method. + * + * Generated from protobuf field string name = 1; + */ + protected $name = ''; + /** + * A URL of the input message type. + * + * Generated from protobuf field string request_type_url = 2; + */ + protected $request_type_url = ''; + /** + * If true, the request is streamed. + * + * Generated from protobuf field bool request_streaming = 3; + */ + protected $request_streaming = false; + /** + * The URL of the output message type. + * + * Generated from protobuf field string response_type_url = 4; + */ + protected $response_type_url = ''; + /** + * If true, the response is streamed. + * + * Generated from protobuf field bool response_streaming = 5; + */ + protected $response_streaming = false; + /** + * Any metadata attached to the method. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 6; + */ + private $options; + /** + * The source syntax of this method. + * + * Generated from protobuf field .google.protobuf.Syntax syntax = 7; + */ + protected $syntax = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * The simple name of this method. + * @type string $request_type_url + * A URL of the input message type. + * @type bool $request_streaming + * If true, the request is streamed. + * @type string $response_type_url + * The URL of the output message type. + * @type bool $response_streaming + * If true, the response is streamed. + * @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options + * Any metadata attached to the method. + * @type int $syntax + * The source syntax of this method. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Api::initOnce(); + parent::__construct($data); + } + + /** + * The simple name of this method. + * + * Generated from protobuf field string name = 1; + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * The simple name of this method. + * + * Generated from protobuf field string name = 1; + * @param string $var + * @return $this + */ + public function setName($var) + { + GPBUtil::checkString($var, True); + $this->name = $var; + + return $this; + } + + /** + * A URL of the input message type. + * + * Generated from protobuf field string request_type_url = 2; + * @return string + */ + public function getRequestTypeUrl() + { + return $this->request_type_url; + } + + /** + * A URL of the input message type. + * + * Generated from protobuf field string request_type_url = 2; + * @param string $var + * @return $this + */ + public function setRequestTypeUrl($var) + { + GPBUtil::checkString($var, True); + $this->request_type_url = $var; + + return $this; + } + + /** + * If true, the request is streamed. + * + * Generated from protobuf field bool request_streaming = 3; + * @return bool + */ + public function getRequestStreaming() + { + return $this->request_streaming; + } + + /** + * If true, the request is streamed. + * + * Generated from protobuf field bool request_streaming = 3; + * @param bool $var + * @return $this + */ + public function setRequestStreaming($var) + { + GPBUtil::checkBool($var); + $this->request_streaming = $var; + + return $this; + } + + /** + * The URL of the output message type. + * + * Generated from protobuf field string response_type_url = 4; + * @return string + */ + public function getResponseTypeUrl() + { + return $this->response_type_url; + } + + /** + * The URL of the output message type. + * + * Generated from protobuf field string response_type_url = 4; + * @param string $var + * @return $this + */ + public function setResponseTypeUrl($var) + { + GPBUtil::checkString($var, True); + $this->response_type_url = $var; + + return $this; + } + + /** + * If true, the response is streamed. + * + * Generated from protobuf field bool response_streaming = 5; + * @return bool + */ + public function getResponseStreaming() + { + return $this->response_streaming; + } + + /** + * If true, the response is streamed. + * + * Generated from protobuf field bool response_streaming = 5; + * @param bool $var + * @return $this + */ + public function setResponseStreaming($var) + { + GPBUtil::checkBool($var); + $this->response_streaming = $var; + + return $this; + } + + /** + * Any metadata attached to the method. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 6; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getOptions() + { + return $this->options; + } + + /** + * Any metadata attached to the method. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 6; + * @param \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setOptions($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Option::class); + $this->options = $arr; + + return $this; + } + + /** + * The source syntax of this method. + * + * Generated from protobuf field .google.protobuf.Syntax syntax = 7; + * @return int + */ + public function getSyntax() + { + return $this->syntax; + } + + /** + * The source syntax of this method. + * + * Generated from protobuf field .google.protobuf.Syntax syntax = 7; + * @param int $var + * @return $this + */ + public function setSyntax($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Syntax::class); + $this->syntax = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Mixin.php b/php/src/Google/Protobuf/Mixin.php new file mode 100644 index 0000000000000..4f7bf844ccfe1 --- /dev/null +++ b/php/src/Google/Protobuf/Mixin.php @@ -0,0 +1,166 @@ +google.protobuf.Mixin + */ +class Mixin extends \Google\Protobuf\Internal\Message +{ + /** + * The fully qualified name of the interface which is included. + * + * Generated from protobuf field string name = 1; + */ + protected $name = ''; + /** + * If non-empty specifies a path under which inherited HTTP paths + * are rooted. + * + * Generated from protobuf field string root = 2; + */ + protected $root = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * The fully qualified name of the interface which is included. + * @type string $root + * If non-empty specifies a path under which inherited HTTP paths + * are rooted. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Api::initOnce(); + parent::__construct($data); + } + + /** + * The fully qualified name of the interface which is included. + * + * Generated from protobuf field string name = 1; + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * The fully qualified name of the interface which is included. + * + * Generated from protobuf field string name = 1; + * @param string $var + * @return $this + */ + public function setName($var) + { + GPBUtil::checkString($var, True); + $this->name = $var; + + return $this; + } + + /** + * If non-empty specifies a path under which inherited HTTP paths + * are rooted. + * + * Generated from protobuf field string root = 2; + * @return string + */ + public function getRoot() + { + return $this->root; + } + + /** + * If non-empty specifies a path under which inherited HTTP paths + * are rooted. + * + * Generated from protobuf field string root = 2; + * @param string $var + * @return $this + */ + public function setRoot($var) + { + GPBUtil::checkString($var, True); + $this->root = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/NullValue.php b/php/src/Google/Protobuf/NullValue.php new file mode 100644 index 0000000000000..61569f8a36f74 --- /dev/null +++ b/php/src/Google/Protobuf/NullValue.php @@ -0,0 +1,49 @@ +google.protobuf.NullValue + */ +class NullValue +{ + /** + * Null value. + * + * Generated from protobuf enum NULL_VALUE = 0; + */ + const NULL_VALUE = 0; + + private static $valueToName = [ + self::NULL_VALUE => 'NULL_VALUE', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + diff --git a/php/src/Google/Protobuf/OneofDescriptor.php b/php/src/Google/Protobuf/OneofDescriptor.php index d9736634e352c..92b4e279dac33 100644 --- a/php/src/Google/Protobuf/OneofDescriptor.php +++ b/php/src/Google/Protobuf/OneofDescriptor.php @@ -72,4 +72,9 @@ public function getFieldCount() { return count($this->internal_desc->getFields()); } + + public function isSynthetic() + { + return $this->internal_desc->isSynthetic(); + } } diff --git a/php/src/Google/Protobuf/Option.php b/php/src/Google/Protobuf/Option.php new file mode 100644 index 0000000000000..5166a08db6157 --- /dev/null +++ b/php/src/Google/Protobuf/Option.php @@ -0,0 +1,136 @@ +google.protobuf.Option + */ +class Option extends \Google\Protobuf\Internal\Message +{ + /** + * The option's name. For protobuf built-in options (options defined in + * descriptor.proto), this is the short name. For example, `"map_entry"`. + * For custom options, it should be the fully-qualified name. For example, + * `"google.api.http"`. + * + * Generated from protobuf field string name = 1; + */ + protected $name = ''; + /** + * The option's value packed in an Any message. If the value is a primitive, + * the corresponding wrapper type defined in google/protobuf/wrappers.proto + * should be used. If the value is an enum, it should be stored as an int32 + * value using the google.protobuf.Int32Value type. + * + * Generated from protobuf field .google.protobuf.Any value = 2; + */ + protected $value = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * The option's name. For protobuf built-in options (options defined in + * descriptor.proto), this is the short name. For example, `"map_entry"`. + * For custom options, it should be the fully-qualified name. For example, + * `"google.api.http"`. + * @type \Google\Protobuf\Any $value + * The option's value packed in an Any message. If the value is a primitive, + * the corresponding wrapper type defined in google/protobuf/wrappers.proto + * should be used. If the value is an enum, it should be stored as an int32 + * value using the google.protobuf.Int32Value type. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Type::initOnce(); + parent::__construct($data); + } + + /** + * The option's name. For protobuf built-in options (options defined in + * descriptor.proto), this is the short name. For example, `"map_entry"`. + * For custom options, it should be the fully-qualified name. For example, + * `"google.api.http"`. + * + * Generated from protobuf field string name = 1; + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * The option's name. For protobuf built-in options (options defined in + * descriptor.proto), this is the short name. For example, `"map_entry"`. + * For custom options, it should be the fully-qualified name. For example, + * `"google.api.http"`. + * + * Generated from protobuf field string name = 1; + * @param string $var + * @return $this + */ + public function setName($var) + { + GPBUtil::checkString($var, True); + $this->name = $var; + + return $this; + } + + /** + * The option's value packed in an Any message. If the value is a primitive, + * the corresponding wrapper type defined in google/protobuf/wrappers.proto + * should be used. If the value is an enum, it should be stored as an int32 + * value using the google.protobuf.Int32Value type. + * + * Generated from protobuf field .google.protobuf.Any value = 2; + * @return \Google\Protobuf\Any|null + */ + public function getValue() + { + return isset($this->value) ? $this->value : null; + } + + public function hasValue() + { + return isset($this->value); + } + + public function clearValue() + { + unset($this->value); + } + + /** + * The option's value packed in an Any message. If the value is a primitive, + * the corresponding wrapper type defined in google/protobuf/wrappers.proto + * should be used. If the value is an enum, it should be stored as an int32 + * value using the google.protobuf.Int32Value type. + * + * Generated from protobuf field .google.protobuf.Any value = 2; + * @param \Google\Protobuf\Any $var + * @return $this + */ + public function setValue($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Any::class); + $this->value = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/SourceContext.php b/php/src/Google/Protobuf/SourceContext.php new file mode 100644 index 0000000000000..8b3ea11220cd5 --- /dev/null +++ b/php/src/Google/Protobuf/SourceContext.php @@ -0,0 +1,72 @@ +google.protobuf.SourceContext + */ +class SourceContext extends \Google\Protobuf\Internal\Message +{ + /** + * The path-qualified name of the .proto file that contained the associated + * protobuf element. For example: `"google/protobuf/source_context.proto"`. + * + * Generated from protobuf field string file_name = 1; + */ + protected $file_name = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $file_name + * The path-qualified name of the .proto file that contained the associated + * protobuf element. For example: `"google/protobuf/source_context.proto"`. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\SourceContext::initOnce(); + parent::__construct($data); + } + + /** + * The path-qualified name of the .proto file that contained the associated + * protobuf element. For example: `"google/protobuf/source_context.proto"`. + * + * Generated from protobuf field string file_name = 1; + * @return string + */ + public function getFileName() + { + return $this->file_name; + } + + /** + * The path-qualified name of the .proto file that contained the associated + * protobuf element. For example: `"google/protobuf/source_context.proto"`. + * + * Generated from protobuf field string file_name = 1; + * @param string $var + * @return $this + */ + public function setFileName($var) + { + GPBUtil::checkString($var, True); + $this->file_name = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/StringValue.php b/php/src/Google/Protobuf/StringValue.php new file mode 100644 index 0000000000000..ad98316b22475 --- /dev/null +++ b/php/src/Google/Protobuf/StringValue.php @@ -0,0 +1,68 @@ +google.protobuf.StringValue + */ +class StringValue extends \Google\Protobuf\Internal\Message +{ + /** + * The string value. + * + * Generated from protobuf field string value = 1; + */ + protected $value = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $value + * The string value. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Wrappers::initOnce(); + parent::__construct($data); + } + + /** + * The string value. + * + * Generated from protobuf field string value = 1; + * @return string + */ + public function getValue() + { + return $this->value; + } + + /** + * The string value. + * + * Generated from protobuf field string value = 1; + * @param string $var + * @return $this + */ + public function setValue($var) + { + GPBUtil::checkString($var, True); + $this->value = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Struct.php b/php/src/Google/Protobuf/Struct.php new file mode 100644 index 0000000000000..0456541cbd2c9 --- /dev/null +++ b/php/src/Google/Protobuf/Struct.php @@ -0,0 +1,73 @@ +google.protobuf.Struct + */ +class Struct extends \Google\Protobuf\Internal\Message +{ + /** + * Unordered map of dynamically typed values. + * + * Generated from protobuf field map fields = 1; + */ + private $fields; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type array|\Google\Protobuf\Internal\MapField $fields + * Unordered map of dynamically typed values. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Struct::initOnce(); + parent::__construct($data); + } + + /** + * Unordered map of dynamically typed values. + * + * Generated from protobuf field map fields = 1; + * @return \Google\Protobuf\Internal\MapField + */ + public function getFields() + { + return $this->fields; + } + + /** + * Unordered map of dynamically typed values. + * + * Generated from protobuf field map fields = 1; + * @param array|\Google\Protobuf\Internal\MapField $var + * @return $this + */ + public function setFields($var) + { + $arr = GPBUtil::checkMapField($var, \Google\Protobuf\Internal\GPBType::STRING, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Value::class); + $this->fields = $arr; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Syntax.php b/php/src/Google/Protobuf/Syntax.php new file mode 100644 index 0000000000000..10952bfd42cea --- /dev/null +++ b/php/src/Google/Protobuf/Syntax.php @@ -0,0 +1,54 @@ +google.protobuf.Syntax + */ +class Syntax +{ + /** + * Syntax `proto2`. + * + * Generated from protobuf enum SYNTAX_PROTO2 = 0; + */ + const SYNTAX_PROTO2 = 0; + /** + * Syntax `proto3`. + * + * Generated from protobuf enum SYNTAX_PROTO3 = 1; + */ + const SYNTAX_PROTO3 = 1; + + private static $valueToName = [ + self::SYNTAX_PROTO2 => 'SYNTAX_PROTO2', + self::SYNTAX_PROTO3 => 'SYNTAX_PROTO3', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + diff --git a/php/src/Google/Protobuf/Timestamp.php b/php/src/Google/Protobuf/Timestamp.php new file mode 100644 index 0000000000000..a12f48520bf2f --- /dev/null +++ b/php/src/Google/Protobuf/Timestamp.php @@ -0,0 +1,186 @@ +google.protobuf.Timestamp + */ +class Timestamp extends \Google\Protobuf\Internal\TimestampBase +{ + /** + * Represents seconds of UTC time since Unix epoch + * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59Z inclusive. + * + * Generated from protobuf field int64 seconds = 1; + */ + protected $seconds = 0; + /** + * Non-negative fractions of a second at nanosecond resolution. Negative + * second values with fractions must still have non-negative nanos values + * that count forward in time. Must be from 0 to 999,999,999 + * inclusive. + * + * Generated from protobuf field int32 nanos = 2; + */ + protected $nanos = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int|string $seconds + * Represents seconds of UTC time since Unix epoch + * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59Z inclusive. + * @type int $nanos + * Non-negative fractions of a second at nanosecond resolution. Negative + * second values with fractions must still have non-negative nanos values + * that count forward in time. Must be from 0 to 999,999,999 + * inclusive. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Timestamp::initOnce(); + parent::__construct($data); + } + + /** + * Represents seconds of UTC time since Unix epoch + * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59Z inclusive. + * + * Generated from protobuf field int64 seconds = 1; + * @return int|string + */ + public function getSeconds() + { + return $this->seconds; + } + + /** + * Represents seconds of UTC time since Unix epoch + * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59Z inclusive. + * + * Generated from protobuf field int64 seconds = 1; + * @param int|string $var + * @return $this + */ + public function setSeconds($var) + { + GPBUtil::checkInt64($var); + $this->seconds = $var; + + return $this; + } + + /** + * Non-negative fractions of a second at nanosecond resolution. Negative + * second values with fractions must still have non-negative nanos values + * that count forward in time. Must be from 0 to 999,999,999 + * inclusive. + * + * Generated from protobuf field int32 nanos = 2; + * @return int + */ + public function getNanos() + { + return $this->nanos; + } + + /** + * Non-negative fractions of a second at nanosecond resolution. Negative + * second values with fractions must still have non-negative nanos values + * that count forward in time. Must be from 0 to 999,999,999 + * inclusive. + * + * Generated from protobuf field int32 nanos = 2; + * @param int $var + * @return $this + */ + public function setNanos($var) + { + GPBUtil::checkInt32($var); + $this->nanos = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Type.php b/php/src/Google/Protobuf/Type.php new file mode 100644 index 0000000000000..3f2835927396c --- /dev/null +++ b/php/src/Google/Protobuf/Type.php @@ -0,0 +1,247 @@ +google.protobuf.Type + */ +class Type extends \Google\Protobuf\Internal\Message +{ + /** + * The fully qualified message name. + * + * Generated from protobuf field string name = 1; + */ + protected $name = ''; + /** + * The list of fields. + * + * Generated from protobuf field repeated .google.protobuf.Field fields = 2; + */ + private $fields; + /** + * The list of types appearing in `oneof` definitions in this type. + * + * Generated from protobuf field repeated string oneofs = 3; + */ + private $oneofs; + /** + * The protocol buffer options. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 4; + */ + private $options; + /** + * The source context. + * + * Generated from protobuf field .google.protobuf.SourceContext source_context = 5; + */ + protected $source_context = null; + /** + * The source syntax. + * + * Generated from protobuf field .google.protobuf.Syntax syntax = 6; + */ + protected $syntax = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * The fully qualified message name. + * @type \Google\Protobuf\Field[]|\Google\Protobuf\Internal\RepeatedField $fields + * The list of fields. + * @type string[]|\Google\Protobuf\Internal\RepeatedField $oneofs + * The list of types appearing in `oneof` definitions in this type. + * @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options + * The protocol buffer options. + * @type \Google\Protobuf\SourceContext $source_context + * The source context. + * @type int $syntax + * The source syntax. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Type::initOnce(); + parent::__construct($data); + } + + /** + * The fully qualified message name. + * + * Generated from protobuf field string name = 1; + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * The fully qualified message name. + * + * Generated from protobuf field string name = 1; + * @param string $var + * @return $this + */ + public function setName($var) + { + GPBUtil::checkString($var, True); + $this->name = $var; + + return $this; + } + + /** + * The list of fields. + * + * Generated from protobuf field repeated .google.protobuf.Field fields = 2; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getFields() + { + return $this->fields; + } + + /** + * The list of fields. + * + * Generated from protobuf field repeated .google.protobuf.Field fields = 2; + * @param \Google\Protobuf\Field[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setFields($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Field::class); + $this->fields = $arr; + + return $this; + } + + /** + * The list of types appearing in `oneof` definitions in this type. + * + * Generated from protobuf field repeated string oneofs = 3; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getOneofs() + { + return $this->oneofs; + } + + /** + * The list of types appearing in `oneof` definitions in this type. + * + * Generated from protobuf field repeated string oneofs = 3; + * @param string[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setOneofs($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING); + $this->oneofs = $arr; + + return $this; + } + + /** + * The protocol buffer options. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 4; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getOptions() + { + return $this->options; + } + + /** + * The protocol buffer options. + * + * Generated from protobuf field repeated .google.protobuf.Option options = 4; + * @param \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setOptions($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Option::class); + $this->options = $arr; + + return $this; + } + + /** + * The source context. + * + * Generated from protobuf field .google.protobuf.SourceContext source_context = 5; + * @return \Google\Protobuf\SourceContext|null + */ + public function getSourceContext() + { + return isset($this->source_context) ? $this->source_context : null; + } + + public function hasSourceContext() + { + return isset($this->source_context); + } + + public function clearSourceContext() + { + unset($this->source_context); + } + + /** + * The source context. + * + * Generated from protobuf field .google.protobuf.SourceContext source_context = 5; + * @param \Google\Protobuf\SourceContext $var + * @return $this + */ + public function setSourceContext($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\SourceContext::class); + $this->source_context = $var; + + return $this; + } + + /** + * The source syntax. + * + * Generated from protobuf field .google.protobuf.Syntax syntax = 6; + * @return int + */ + public function getSyntax() + { + return $this->syntax; + } + + /** + * The source syntax. + * + * Generated from protobuf field .google.protobuf.Syntax syntax = 6; + * @param int $var + * @return $this + */ + public function setSyntax($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Syntax::class); + $this->syntax = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/UInt32Value.php b/php/src/Google/Protobuf/UInt32Value.php new file mode 100644 index 0000000000000..ae5fc5b42c8d1 --- /dev/null +++ b/php/src/Google/Protobuf/UInt32Value.php @@ -0,0 +1,68 @@ +google.protobuf.UInt32Value + */ +class UInt32Value extends \Google\Protobuf\Internal\Message +{ + /** + * The uint32 value. + * + * Generated from protobuf field uint32 value = 1; + */ + protected $value = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $value + * The uint32 value. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Wrappers::initOnce(); + parent::__construct($data); + } + + /** + * The uint32 value. + * + * Generated from protobuf field uint32 value = 1; + * @return int + */ + public function getValue() + { + return $this->value; + } + + /** + * The uint32 value. + * + * Generated from protobuf field uint32 value = 1; + * @param int $var + * @return $this + */ + public function setValue($var) + { + GPBUtil::checkUint32($var); + $this->value = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/UInt64Value.php b/php/src/Google/Protobuf/UInt64Value.php new file mode 100644 index 0000000000000..aa9686726b935 --- /dev/null +++ b/php/src/Google/Protobuf/UInt64Value.php @@ -0,0 +1,68 @@ +google.protobuf.UInt64Value + */ +class UInt64Value extends \Google\Protobuf\Internal\Message +{ + /** + * The uint64 value. + * + * Generated from protobuf field uint64 value = 1; + */ + protected $value = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int|string $value + * The uint64 value. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Wrappers::initOnce(); + parent::__construct($data); + } + + /** + * The uint64 value. + * + * Generated from protobuf field uint64 value = 1; + * @return int|string + */ + public function getValue() + { + return $this->value; + } + + /** + * The uint64 value. + * + * Generated from protobuf field uint64 value = 1; + * @param int|string $var + * @return $this + */ + public function setValue($var) + { + GPBUtil::checkUint64($var); + $this->value = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Value.php b/php/src/Google/Protobuf/Value.php new file mode 100644 index 0000000000000..7bebb998843bf --- /dev/null +++ b/php/src/Google/Protobuf/Value.php @@ -0,0 +1,244 @@ +google.protobuf.Value + */ +class Value extends \Google\Protobuf\Internal\Message +{ + protected $kind; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $null_value + * Represents a null value. + * @type float $number_value + * Represents a double value. + * @type string $string_value + * Represents a string value. + * @type bool $bool_value + * Represents a boolean value. + * @type \Google\Protobuf\Struct $struct_value + * Represents a structured value. + * @type \Google\Protobuf\ListValue $list_value + * Represents a repeated `Value`. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Struct::initOnce(); + parent::__construct($data); + } + + /** + * Represents a null value. + * + * Generated from protobuf field .google.protobuf.NullValue null_value = 1; + * @return int + */ + public function getNullValue() + { + return $this->readOneof(1); + } + + public function hasNullValue() + { + return $this->hasOneof(1); + } + + /** + * Represents a null value. + * + * Generated from protobuf field .google.protobuf.NullValue null_value = 1; + * @param int $var + * @return $this + */ + public function setNullValue($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\NullValue::class); + $this->writeOneof(1, $var); + + return $this; + } + + /** + * Represents a double value. + * + * Generated from protobuf field double number_value = 2; + * @return float + */ + public function getNumberValue() + { + return $this->readOneof(2); + } + + public function hasNumberValue() + { + return $this->hasOneof(2); + } + + /** + * Represents a double value. + * + * Generated from protobuf field double number_value = 2; + * @param float $var + * @return $this + */ + public function setNumberValue($var) + { + GPBUtil::checkDouble($var); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * Represents a string value. + * + * Generated from protobuf field string string_value = 3; + * @return string + */ + public function getStringValue() + { + return $this->readOneof(3); + } + + public function hasStringValue() + { + return $this->hasOneof(3); + } + + /** + * Represents a string value. + * + * Generated from protobuf field string string_value = 3; + * @param string $var + * @return $this + */ + public function setStringValue($var) + { + GPBUtil::checkString($var, True); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * Represents a boolean value. + * + * Generated from protobuf field bool bool_value = 4; + * @return bool + */ + public function getBoolValue() + { + return $this->readOneof(4); + } + + public function hasBoolValue() + { + return $this->hasOneof(4); + } + + /** + * Represents a boolean value. + * + * Generated from protobuf field bool bool_value = 4; + * @param bool $var + * @return $this + */ + public function setBoolValue($var) + { + GPBUtil::checkBool($var); + $this->writeOneof(4, $var); + + return $this; + } + + /** + * Represents a structured value. + * + * Generated from protobuf field .google.protobuf.Struct struct_value = 5; + * @return \Google\Protobuf\Struct|null + */ + public function getStructValue() + { + return $this->readOneof(5); + } + + public function hasStructValue() + { + return $this->hasOneof(5); + } + + /** + * Represents a structured value. + * + * Generated from protobuf field .google.protobuf.Struct struct_value = 5; + * @param \Google\Protobuf\Struct $var + * @return $this + */ + public function setStructValue($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Struct::class); + $this->writeOneof(5, $var); + + return $this; + } + + /** + * Represents a repeated `Value`. + * + * Generated from protobuf field .google.protobuf.ListValue list_value = 6; + * @return \Google\Protobuf\ListValue|null + */ + public function getListValue() + { + return $this->readOneof(6); + } + + public function hasListValue() + { + return $this->hasOneof(6); + } + + /** + * Represents a repeated `Value`. + * + * Generated from protobuf field .google.protobuf.ListValue list_value = 6; + * @param \Google\Protobuf\ListValue $var + * @return $this + */ + public function setListValue($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\ListValue::class); + $this->writeOneof(6, $var); + + return $this; + } + + /** + * @return string + */ + public function getKind() + { + return $this->whichOneof("kind"); + } + +} + diff --git a/php/tests/ArrayTest.php b/php/tests/ArrayTest.php new file mode 100644 index 0000000000000..0585ca5b1c8f5 --- /dev/null +++ b/php/tests/ArrayTest.php @@ -0,0 +1,639 @@ +assertSame(MAX_INT32, $arr[0]); + $arr[] = MIN_INT32; + $this->assertSame(MIN_INT32, $arr[1]); + + $arr[] = 1.1; + $this->assertSame(1, $arr[2]); + $arr[] = MAX_INT32_FLOAT; + $this->assertSame(MAX_INT32, $arr[3]); + $arr[] = MAX_INT32_FLOAT; + $this->assertSame(MAX_INT32, $arr[4]); + + $arr[] = '2'; + $this->assertSame(2, $arr[5]); + $arr[] = '3.1'; + $this->assertSame(3, $arr[6]); + $arr[] = MAX_INT32_STRING; + $this->assertSame(MAX_INT32, $arr[7]); + + $this->assertEquals(8, count($arr)); + + for ($i = 0; $i < count($arr); $i++) { + $arr[$i] = 0; + $this->assertSame(0, $arr[$i]); + } + + // Test set. + $arr[0] = MAX_INT32; + $this->assertSame(MAX_INT32, $arr[0]); + $arr[1] = MIN_INT32; + $this->assertSame(MIN_INT32, $arr[1]); + + $arr[2] = 1.1; + $this->assertSame(1, $arr[2]); + $arr[3] = MAX_INT32_FLOAT; + $this->assertSame(MAX_INT32, $arr[3]); + $arr[4] = MAX_INT32_FLOAT; + $this->assertSame(MAX_INT32, $arr[4]); + + $arr[5] = '2'; + $this->assertSame(2, $arr[5]); + $arr[6] = '3.1'; + $this->assertSame(3, $arr[6]); + $arr[7] = MAX_INT32_STRING; + $this->assertSame(MAX_INT32, $arr[7]); + + // Test foreach. + $arr = new RepeatedField(GPBType::INT32); + for ($i = 0; $i < 3; $i++) { + $arr[] = $i; + } + $i = 0; + foreach ($arr as $val) { + $this->assertSame($i++, $val); + } + $this->assertSame(3, $i); + } + + ######################################################### + # Test uint32 field. + ######################################################### + + public function testUint32() + { + $arr = new RepeatedField(GPBType::UINT32); + + // Test append. + $arr[] = MAX_UINT32; + $this->assertSame(-1, $arr[0]); + $arr[] = -1; + $this->assertSame(-1, $arr[1]); + $arr[] = MIN_UINT32; + $this->assertSame(MIN_UINT32, $arr[2]); + + $arr[] = 1.1; + $this->assertSame(1, $arr[3]); + $arr[] = MAX_UINT32_FLOAT; + $this->assertSame(-1, $arr[4]); + $arr[] = -1.0; + $this->assertSame(-1, $arr[5]); + $arr[] = MIN_UINT32_FLOAT; + $this->assertSame(MIN_UINT32, $arr[6]); + + $arr[] = '2'; + $this->assertSame(2, $arr[7]); + $arr[] = '3.1'; + $this->assertSame(3, $arr[8]); + $arr[] = MAX_UINT32_STRING; + $this->assertSame(-1, $arr[9]); + $arr[] = '-1.0'; + $this->assertSame(-1, $arr[10]); + $arr[] = MIN_UINT32_STRING; + $this->assertSame(MIN_UINT32, $arr[11]); + + $this->assertEquals(12, count($arr)); + + for ($i = 0; $i < count($arr); $i++) { + $arr[$i] = 0; + $this->assertSame(0, $arr[$i]); + } + + // Test set. + $arr[0] = MAX_UINT32; + $this->assertSame(-1, $arr[0]); + $arr[1] = -1; + $this->assertSame(-1, $arr[1]); + $arr[2] = MIN_UINT32; + $this->assertSame(MIN_UINT32, $arr[2]); + + $arr[3] = 1.1; + $this->assertSame(1, $arr[3]); + $arr[4] = MAX_UINT32_FLOAT; + $this->assertSame(-1, $arr[4]); + $arr[5] = -1.0; + $this->assertSame(-1, $arr[5]); + $arr[6] = MIN_UINT32_FLOAT; + $this->assertSame(MIN_UINT32, $arr[6]); + + $arr[7] = '2'; + $this->assertSame(2, $arr[7]); + $arr[8] = '3.1'; + $this->assertSame(3, $arr[8]); + $arr[9] = MAX_UINT32_STRING; + $this->assertSame(-1, $arr[9]); + $arr[10] = '-1.0'; + $this->assertSame(-1, $arr[10]); + $arr[11] = MIN_UINT32_STRING; + $this->assertSame(MIN_UINT32, $arr[11]); + } + + ######################################################### + # Test int64 field. + ######################################################### + + public function testInt64() + { + $arr = new RepeatedField(GPBType::INT64); + + // Test append. + $arr[] = MAX_INT64; + $arr[] = MIN_INT64; + $arr[] = 1.1; + $arr[] = '2'; + $arr[] = '3.1'; + $arr[] = MAX_INT64_STRING; + $arr[] = MIN_INT64_STRING; + if (PHP_INT_SIZE == 4) { + $this->assertSame(MAX_INT64, $arr[0]); + $this->assertSame(MIN_INT64, $arr[1]); + $this->assertSame('1', $arr[2]); + $this->assertSame('2', $arr[3]); + $this->assertSame('3', $arr[4]); + $this->assertSame(MAX_INT64_STRING, $arr[5]); + $this->assertSame(MIN_INT64_STRING, $arr[6]); + } else { + $this->assertSame(MAX_INT64, $arr[0]); + $this->assertSame(MIN_INT64, $arr[1]); + $this->assertSame(1, $arr[2]); + $this->assertSame(2, $arr[3]); + $this->assertSame(3, $arr[4]); + $this->assertSame(MAX_INT64, $arr[5]); + $this->assertSame(MIN_INT64, $arr[6]); + } + + + $this->assertEquals(7, count($arr)); + + for ($i = 0; $i < count($arr); $i++) { + $arr[$i] = 0; + if (PHP_INT_SIZE == 4) { + $this->assertSame('0', $arr[$i]); + } else { + $this->assertSame(0, $arr[$i]); + } + } + + // Test set. + $arr[0] = MAX_INT64; + $arr[1] = MIN_INT64; + $arr[2] = 1.1; + $arr[3] = '2'; + $arr[4] = '3.1'; + $arr[5] = MAX_INT64_STRING; + $arr[6] = MIN_INT64_STRING; + + if (PHP_INT_SIZE == 4) { + $this->assertSame(MAX_INT64_STRING, $arr[0]); + $this->assertSame(MIN_INT64_STRING, $arr[1]); + $this->assertSame('1', $arr[2]); + $this->assertSame('2', $arr[3]); + $this->assertSame('3', $arr[4]); + $this->assertSame(MAX_INT64_STRING, $arr[5]); + $this->assertEquals(MIN_INT64_STRING, $arr[6]); + } else { + $this->assertSame(MAX_INT64, $arr[0]); + $this->assertSame(MIN_INT64, $arr[1]); + $this->assertSame(1, $arr[2]); + $this->assertSame(2, $arr[3]); + $this->assertSame(3, $arr[4]); + $this->assertSame(MAX_INT64, $arr[5]); + $this->assertEquals(MIN_INT64, $arr[6]); + } + } + + ######################################################### + # Test uint64 field. + ######################################################### + + public function testUint64() + { + $arr = new RepeatedField(GPBType::UINT64); + + // Test append. + $arr[] = MAX_UINT64; + $arr[] = 1.1; + $arr[] = '2'; + $arr[] = '3.1'; + $arr[] = MAX_UINT64_STRING; + + if (PHP_INT_SIZE == 4) { + $this->assertSame(MAX_UINT64_STRING, $arr[0]); + $this->assertSame('1', $arr[1]); + $this->assertSame('2', $arr[2]); + $this->assertSame('3', $arr[3]); + $this->assertSame(MAX_UINT64_STRING, $arr[4]); + } else { + $this->assertSame(MAX_UINT64, $arr[0]); + $this->assertSame(1, $arr[1]); + $this->assertSame(2, $arr[2]); + $this->assertSame(3, $arr[3]); + $this->assertSame(MAX_UINT64, $arr[4]); + $this->assertSame(5, count($arr)); + } + + $this->assertSame(5, count($arr)); + + for ($i = 0; $i < count($arr); $i++) { + $arr[$i] = 0; + if (PHP_INT_SIZE == 4) { + $this->assertSame('0', $arr[$i]); + } else { + $this->assertSame(0, $arr[$i]); + } + } + + // Test set. + $arr[0] = MAX_UINT64; + $arr[1] = 1.1; + $arr[2] = '2'; + $arr[3] = '3.1'; + $arr[4] = MAX_UINT64_STRING; + + if (PHP_INT_SIZE == 4) { + $this->assertSame(MAX_UINT64_STRING, $arr[0]); + $this->assertSame('1', $arr[1]); + $this->assertSame('2', $arr[2]); + $this->assertSame('3', $arr[3]); + $this->assertSame(MAX_UINT64_STRING, $arr[4]); + } else { + $this->assertSame(MAX_UINT64, $arr[0]); + $this->assertSame(1, $arr[1]); + $this->assertSame(2, $arr[2]); + $this->assertSame(3, $arr[3]); + $this->assertSame(MAX_UINT64, $arr[4]); + } + } + + ######################################################### + # Test float field. + ######################################################### + + public function testFloat() + { + $arr = new RepeatedField(GPBType::FLOAT); + + // Test append. + $arr[] = 1; + $this->assertFloatEquals(1.0, $arr[0], MAX_FLOAT_DIFF); + + $arr[] = 1.1; + $this->assertFloatEquals(1.1, $arr[1], MAX_FLOAT_DIFF); + + $arr[] = '2'; + $this->assertFloatEquals(2.0, $arr[2], MAX_FLOAT_DIFF); + $arr[] = '3.1'; + $this->assertFloatEquals(3.1, $arr[3], MAX_FLOAT_DIFF); + + $this->assertEquals(4, count($arr)); + + for ($i = 0; $i < count($arr); $i++) { + $arr[$i] = 0; + $this->assertSame(0.0, $arr[$i]); + } + + // Test set. + $arr[0] = 1; + $this->assertFloatEquals(1.0, $arr[0], MAX_FLOAT_DIFF); + + $arr[1] = 1.1; + $this->assertFloatEquals(1.1, $arr[1], MAX_FLOAT_DIFF); + + $arr[2] = '2'; + $this->assertFloatEquals(2.0, $arr[2], MAX_FLOAT_DIFF); + $arr[3] = '3.1'; + $this->assertFloatEquals(3.1, $arr[3], MAX_FLOAT_DIFF); + } + + ######################################################### + # Test double field. + ######################################################### + + public function testDouble() + { + $arr = new RepeatedField(GPBType::DOUBLE); + + // Test append. + $arr[] = 1; + $this->assertFloatEquals(1.0, $arr[0], MAX_FLOAT_DIFF); + + $arr[] = 1.1; + $this->assertFloatEquals(1.1, $arr[1], MAX_FLOAT_DIFF); + + $arr[] = '2'; + $this->assertFloatEquals(2.0, $arr[2], MAX_FLOAT_DIFF); + $arr[] = '3.1'; + $this->assertFloatEquals(3.1, $arr[3], MAX_FLOAT_DIFF); + + $this->assertEquals(4, count($arr)); + + for ($i = 0; $i < count($arr); $i++) { + $arr[$i] = 0; + $this->assertSame(0.0, $arr[$i]); + } + + // Test set. + $arr[0] = 1; + $this->assertFloatEquals(1.0, $arr[0], MAX_FLOAT_DIFF); + + $arr[1] = 1.1; + $this->assertFloatEquals(1.1, $arr[1], MAX_FLOAT_DIFF); + + $arr[2] = '2'; + $this->assertFloatEquals(2.0, $arr[2], MAX_FLOAT_DIFF); + $arr[3] = '3.1'; + $this->assertFloatEquals(3.1, $arr[3], MAX_FLOAT_DIFF); + } + + ######################################################### + # Test bool field. + ######################################################### + + public function testBool() + { + $arr = new RepeatedField(GPBType::BOOL); + + // Test append. + $arr[] = true; + $this->assertSame(true, $arr[0]); + + $arr[] = -1; + $this->assertSame(true, $arr[1]); + + $arr[] = 1.1; + $this->assertSame(true, $arr[2]); + + $arr[] = ''; + $this->assertSame(false, $arr[3]); + + $this->assertEquals(4, count($arr)); + + for ($i = 0; $i < count($arr); $i++) { + $arr[$i] = 0; + $this->assertSame(false, $arr[$i]); + } + + // Test set. + $arr[0] = true; + $this->assertSame(true, $arr[0]); + + $arr[1] = -1; + $this->assertSame(true, $arr[1]); + + $arr[2] = 1.1; + $this->assertSame(true, $arr[2]); + + $arr[3] = ''; + $this->assertSame(false, $arr[3]); + } + + ######################################################### + # Test string field. + ######################################################### + + public function testString() + { + $arr = new RepeatedField(GPBType::STRING); + + // Test append. + $arr[] = 'abc'; + $this->assertSame('abc', $arr[0]); + + $arr[] = 1; + $this->assertSame('1', $arr[1]); + + $arr[] = 1.1; + $this->assertSame('1.1', $arr[2]); + + $arr[] = true; + $this->assertSame('1', $arr[3]); + + $this->assertEquals(4, count($arr)); + + for ($i = 0; $i < count($arr); $i++) { + $arr[$i] = ''; + $this->assertSame('', $arr[$i]); + } + + // Test set. + $arr[0] = 'abc'; + $this->assertSame('abc', $arr[0]); + + $arr[1] = 1; + $this->assertSame('1', $arr[1]); + + $arr[2] = 1.1; + $this->assertSame('1.1', $arr[2]); + + $arr[3] = true; + $this->assertSame('1', $arr[3]); + } + + ######################################################### + # Test message field. + ######################################################### + + public function testMessage() + { + $arr = new RepeatedField(GPBType::MESSAGE, Sub::class); + + // Test append. + $sub_m = new Sub(); + $sub_m->setA(1); + $arr[] = $sub_m; + $this->assertSame(1, $arr[0]->getA()); + + $this->assertEquals(1, count($arr)); + + // Test set. + $sub_m = new Sub(); + $sub_m->setA(2); + $arr[0] = $sub_m; + $this->assertSame(2, $arr[0]->getA()); + + // Test foreach. + $arr = new RepeatedField(GPBType::MESSAGE, Sub::class); + for ($i = 0; $i < 3; $i++) { + $arr[] = new Sub(); + $arr[$i]->setA($i); + } + $i = 0; + foreach ($arr as $val) { + $this->assertSame($i++, $val->getA()); + } + $this->assertSame(3, $i); + } + + ######################################################### + # Test offset type + ######################################################### + + public function testOffset() + { + $arr = new RepeatedField(GPBType::INT32); + $arr[] = 0; + + $arr[0] = 1; + $this->assertSame(1, $arr[0]); + $this->assertSame(1, count($arr)); + + $arr['0'] = 2; + $this->assertSame(2, $arr['0']); + $this->assertSame(2, $arr[0]); + $this->assertSame(1, count($arr)); + + $arr[0.0] = 3; + $this->assertSame(3, $arr[0.0]); + $this->assertSame(1, count($arr)); + } + + public function testInsertRemoval() + { + $arr = new RepeatedField(GPBType::INT32); + + $arr[] = 0; + $arr[] = 1; + $arr[] = 2; + $this->assertSame(3, count($arr)); + + unset($arr[2]); + $this->assertSame(2, count($arr)); + $this->assertSame(0, $arr[0]); + $this->assertSame(1, $arr[1]); + + $arr[] = 3; + $this->assertSame(3, count($arr)); + $this->assertSame(0, $arr[0]); + $this->assertSame(1, $arr[1]); + $this->assertSame(3, $arr[2]); + } + + ######################################################### + # Test reference in array + ######################################################### + + public function testArrayElementIsReferenceInSetters() + { + // Bool elements + $values = [true]; + array_walk($values, function (&$value) {}); + $m = new TestMessage(); + $m->setRepeatedBool($values); + + // Int32 elements + $values = [1]; + array_walk($values, function (&$value) {}); + $m = new TestMessage(); + $m->setRepeatedInt32($values); + + // Double elements + $values = [1.0]; + array_walk($values, function (&$value) {}); + $m = new TestMessage(); + $m->setRepeatedDouble($values); + + // String elements + $values = ['a']; + array_walk($values, function (&$value) {}); + $m = new TestMessage(); + $m->setRepeatedString($values); + + // Message elements + $m = new TestMessage(); + $subs = [1, 2]; + foreach ($subs as &$sub) { + $sub = new Sub(['a' => $sub]); + } + $m->setRepeatedMessage($subs); + + $this->assertTrue(true); + } + + ######################################################### + # Test memory leak + ######################################################### + + public function testCycleLeak() + { + gc_collect_cycles(); + $arr = new RepeatedField(GPBType::MESSAGE, TestMessage::class); + $arr[] = new TestMessage; + $arr[0]->SetRepeatedRecursive($arr); + + // Clean up memory before test. + gc_collect_cycles(); + $start = memory_get_usage(); + unset($arr); + + // Explicitly trigger garbage collection. + gc_collect_cycles(); + + $end = memory_get_usage(); + $this->assertLessThan($start, $end); + } + + ######################################################### + # Test equality + ######################################################### + + public function testEquality() + { + $arr = new RepeatedField(GPBType::INT32); + $arr2 = new RepeatedField(GPBType::INT32); + + $this->assertTrue($arr == $arr2); + + $arr[] = 0; + $arr[] = 1; + $arr[] = 2; + + $this->assertFalse($arr == $arr2); + + $arr2[] = 0; + $arr2[] = 1; + $arr2[] = 2; + + $this->assertTrue($arr == $arr2); + + // Arrays of different types always compare false. + $this->assertFalse(new RepeatedField(GPBType::INT32) == + new RepeatedField(GPBType::INT64)); + $this->assertFalse( + new RepeatedField(GPBType::MESSAGE, TestMessage::class) == + new RepeatedField(GPBType::MESSAGE, Sub::class)); + } + + ######################################################### + # Test clone + ######################################################### + + public function testClone() + { + $arr = new RepeatedField(GPBType::MESSAGE, TestMessage::class); + $arr[] = new TestMessage; + $arr2 = clone $arr; + $this->assertSame($arr[0], $arr2[0]); + } +} diff --git a/php/tests/DescriptorsTest.php b/php/tests/DescriptorsTest.php new file mode 100644 index 0000000000000..ca7e8f3690614 --- /dev/null +++ b/php/tests/DescriptorsTest.php @@ -0,0 +1,257 @@ +getDescriptorByClassName(get_class(new TestDescriptorsMessage())); + $this->assertInstanceOf('\Google\Protobuf\Descriptor', $desc); + + $enumDesc = $pool->getEnumDescriptorByClassName(get_class(new TestDescriptorsEnum())); + $this->assertInstanceOf('\Google\Protobuf\EnumDescriptor', $enumDesc); + } + + public function testDescriptorPoolIncorrectArgs() + { + $pool = DescriptorPool::getGeneratedPool(); + + $desc = $pool->getDescriptorByClassName('NotAClass'); + $this->assertNull($desc); + + $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsEnum())); + $this->assertNull($desc); + + $enumDesc = $pool->getEnumDescriptorByClassName(get_class(new TestDescriptorsMessage())); + $this->assertNull($enumDesc); + } + + ######################################################### + # Test descriptor. + ######################################################### + + public function testDescriptor() + { + $pool = DescriptorPool::getGeneratedPool(); + $class = get_class(new TestDescriptorsMessage()); + $this->assertSame('Descriptors\TestDescriptorsMessage', $class); + $desc = $pool->getDescriptorByClassName($class); + + $this->assertSame('descriptors.TestDescriptorsMessage', $desc->getFullName()); + $this->assertSame($class, $desc->getClass()); + + $this->assertInstanceOf('\Google\Protobuf\FieldDescriptor', $desc->getField(0)); + $this->assertSame(7, $desc->getFieldCount()); + + $this->assertInstanceOf('\Google\Protobuf\OneofDescriptor', $desc->getOneofDecl(0)); + $this->assertSame(1, $desc->getOneofDeclCount()); + } + + public function testDescriptorForIncludedMessage() + { + $pool = DescriptorPool::getGeneratedPool(); + $class = get_class(new TestMessage()); + $this->assertSame('Foo\TestMessage', $class); + $desc = $pool->getDescriptorByClassName($class); + $fielddesc = $desc->getField(17); + $subdesc = $fielddesc->getMessageType(); + $this->assertSame('Bar\TestInclude', $subdesc->getClass()); + } + + ######################################################### + # Test enum descriptor. + ######################################################### + + public function testEnumDescriptor() + { + // WARNING - we need to do this so that TestDescriptorsEnum is registered!!? + new TestDescriptorsMessage(); + + $pool = DescriptorPool::getGeneratedPool(); + + $enumDesc = $pool->getEnumDescriptorByClassName(get_class(new TestDescriptorsEnum())); + + // Build map of enum values + $enumDescMap = []; + for ($i = 0; $i < $enumDesc->getValueCount(); $i++) { + $enumValueDesc = $enumDesc->getValue($i); + $this->assertInstanceOf('\Google\Protobuf\EnumValueDescriptor', $enumValueDesc); + $enumDescMap[$enumValueDesc->getNumber()] = $enumValueDesc->getName(); + } + + $this->assertSame('ZERO', $enumDescMap[0]); + $this->assertSame('ONE', $enumDescMap[1]); + + $this->assertSame(2, $enumDesc->getValueCount()); + } + + ######################################################### + # Test field descriptor. + ######################################################### + + public function testFieldDescriptor() + { + $pool = DescriptorPool::getGeneratedPool(); + $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage())); + + $fieldDescMap = $this->buildFieldMap($desc); + + // Optional int field + $fieldDesc = $fieldDescMap[1]; + $this->assertSame('optional_int32', $fieldDesc->getName()); + $this->assertSame(1, $fieldDesc->getNumber()); + $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel()); + $this->assertSame(self::GPBTYPE_INT32, $fieldDesc->getType()); + $this->assertFalse($fieldDesc->isMap()); + + // Optional enum field + $fieldDesc = $fieldDescMap[16]; + $this->assertSame('optional_enum', $fieldDesc->getName()); + $this->assertSame(16, $fieldDesc->getNumber()); + $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel()); + $this->assertSame(self::GPBTYPE_ENUM, $fieldDesc->getType()); + $this->assertInstanceOf('\Google\Protobuf\EnumDescriptor', $fieldDesc->getEnumType()); + $this->assertFalse($fieldDesc->isMap()); + + // Optional message field + $fieldDesc = $fieldDescMap[17]; + $this->assertSame('optional_message', $fieldDesc->getName()); + $this->assertSame(17, $fieldDesc->getNumber()); + $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel()); + $this->assertSame(self::GPBTYPE_MESSAGE, $fieldDesc->getType()); + $this->assertInstanceOf('\Google\Protobuf\Descriptor', $fieldDesc->getMessageType()); + $this->assertFalse($fieldDesc->isMap()); + + // Repeated int field + $fieldDesc = $fieldDescMap[31]; + $this->assertSame('repeated_int32', $fieldDesc->getName()); + $this->assertSame(31, $fieldDesc->getNumber()); + $this->assertSame(self::GPBLABEL_REPEATED, $fieldDesc->getLabel()); + $this->assertSame(self::GPBTYPE_INT32, $fieldDesc->getType()); + $this->assertFalse($fieldDesc->isMap()); + + // Repeated message field + $fieldDesc = $fieldDescMap[47]; + $this->assertSame('repeated_message', $fieldDesc->getName()); + $this->assertSame(47, $fieldDesc->getNumber()); + $this->assertSame(self::GPBLABEL_REPEATED, $fieldDesc->getLabel()); + $this->assertSame(self::GPBTYPE_MESSAGE, $fieldDesc->getType()); + $this->assertInstanceOf('\Google\Protobuf\Descriptor', $fieldDesc->getMessageType()); + $this->assertFalse($fieldDesc->isMap()); + + // Oneof int field + // Tested further in testOneofDescriptor() + $fieldDesc = $fieldDescMap[51]; + $this->assertSame('oneof_int32', $fieldDesc->getName()); + $this->assertSame(51, $fieldDesc->getNumber()); + $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel()); + $this->assertSame(self::GPBTYPE_INT32, $fieldDesc->getType()); + $this->assertFalse($fieldDesc->isMap()); + + // Map int-enum field + $fieldDesc = $fieldDescMap[71]; + $this->assertSame('map_int32_enum', $fieldDesc->getName()); + $this->assertSame(71, $fieldDesc->getNumber()); + $this->assertSame(self::GPBLABEL_REPEATED, $fieldDesc->getLabel()); + $this->assertSame(self::GPBTYPE_MESSAGE, $fieldDesc->getType()); + $this->assertTrue($fieldDesc->isMap()); + $mapDesc = $fieldDesc->getMessageType(); + $this->assertSame('descriptors.TestDescriptorsMessage.MapInt32EnumEntry', $mapDesc->getFullName()); + $this->assertSame(self::GPBTYPE_INT32, $mapDesc->getField(0)->getType()); + $this->assertSame(self::GPBTYPE_ENUM, $mapDesc->getField(1)->getType()); + } + + public function testFieldDescriptorEnumException() + { + $this->expectException(Exception::class); + + $pool = DescriptorPool::getGeneratedPool(); + $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage())); + $fieldDesc = $desc->getField(0); + $fieldDesc->getEnumType(); + } + + public function testFieldDescriptorMessageException() + { + $this->expectException(Exception::class); + + $pool = DescriptorPool::getGeneratedPool(); + $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage())); + $fieldDesc = $desc->getField(0); + $fieldDesc->getMessageType(); + } + + ######################################################### + # Test oneof descriptor. + ######################################################### + + public function testOneofDescriptor() + { + $pool = DescriptorPool::getGeneratedPool(); + $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage())); + + $fieldDescMap = $this->buildFieldMap($desc); + $fieldDesc = $fieldDescMap[51]; + + $oneofDesc = $desc->getOneofDecl(0); + + $this->assertSame('my_oneof', $oneofDesc->getName()); + $fieldDescFromOneof = $oneofDesc->getField(0); + $this->assertSame($fieldDesc, $fieldDescFromOneof); + $this->assertSame(1, $oneofDesc->getFieldCount()); + } + + private function buildFieldMap($desc) + { + $fieldDescMap = []; + for ($i = 0; $i < $desc->getFieldCount(); $i++) { + $fieldDesc = $desc->getField($i); + $fieldDescMap[$fieldDesc->getNumber()] = $fieldDesc; + } + return $fieldDescMap; + } +} diff --git a/php/tests/EncodeDecodeTest.php b/php/tests/EncodeDecodeTest.php new file mode 100644 index 0000000000000..d471a5a17a070 --- /dev/null +++ b/php/tests/EncodeDecodeTest.php @@ -0,0 +1,1483 @@ +mergeFromJsonString("{\"optionalInt32\":1}"); + $this->assertEquals(1, $m->getOptionalInt32()); + } + + public function testDecodeTopLevelBoolValue() + { + $m = new BoolValue(); + + $m->mergeFromJsonString("true"); + $this->assertEquals(true, $m->getValue()); + + $m->mergeFromJsonString("false"); + $this->assertEquals(false, $m->getValue()); + } + + public function testEncodeTopLevelBoolValue() + { + $m = new BoolValue(); + $m->setValue(true); + $this->assertSame("true", $m->serializeToJsonString()); + } + + public function testDecodeTopLevelDoubleValue() + { + $m = new DoubleValue(); + $m->mergeFromJsonString("1.5"); + $this->assertEquals(1.5, $m->getValue()); + } + + public function testEncodeTopLevelDoubleValue() + { + $m = new DoubleValue(); + $m->setValue(1.5); + $this->assertSame("1.5", $m->serializeToJsonString()); + } + + public function testDecodeTopLevelFloatValue() + { + $m = new FloatValue(); + $m->mergeFromJsonString("1.5"); + $this->assertEquals(1.5, $m->getValue()); + } + + public function testEncodeTopLevelFloatValue() + { + $m = new FloatValue(); + $m->setValue(1.5); + $this->assertSame("1.5", $m->serializeToJsonString()); + } + + public function testDecodeTopLevelInt32Value() + { + $m = new Int32Value(); + $m->mergeFromJsonString("1"); + $this->assertEquals(1, $m->getValue()); + } + + public function testEncodeTopLevelInt32Value() + { + $m = new Int32Value(); + $m->setValue(1); + $this->assertSame("1", $m->serializeToJsonString()); + } + + public function testDecodeRepeatedInt32Value() + { + $m = new TestInt32Value(); + $m->mergeFromJsonString("{\"repeated_field\":[12345]}"); + $this->assertSame(12345, $m->getRepeatedField()[0]->getValue()); + } + + public function testDecodeTopLevelUInt32Value() + { + $m = new UInt32Value(); + $m->mergeFromJsonString("1"); + $this->assertEquals(1, $m->getValue()); + } + + public function testEncodeTopLevelUInt32Value() + { + $m = new UInt32Value(); + $m->setValue(1); + $this->assertSame("1", $m->serializeToJsonString()); + } + + public function testDecodeTopLevelInt64Value() + { + $m = new Int64Value(); + $m->mergeFromJsonString("1"); + $this->assertEquals(1, $m->getValue()); + } + + public function testDecodeTopLevelInt64ValueAsString() + { + $m = new Int64Value(); + $m->mergeFromJsonString("\"1\""); + $this->assertEquals(1, $m->getValue()); + } + + public function testEncodeTopLevelInt64Value() + { + $m = new Int64Value(); + $m->setValue(1); + $this->assertSame("\"1\"", $m->serializeToJsonString()); + } + + public function testDecodeTopLevelUInt64Value() + { + $m = new UInt64Value(); + $m->mergeFromJsonString("1"); + $this->assertEquals(1, $m->getValue()); + } + + public function testDecodeTopLevelUInt64ValueAsString() + { + $m = new UInt64Value(); + $m->mergeFromJsonString("\"1\""); + $this->assertEquals(1, $m->getValue()); + } + + public function testEncodeTopLevelUInt64Value() + { + $m = new UInt64Value(); + $m->setValue(1); + $this->assertSame("\"1\"", $m->serializeToJsonString()); + } + + public function testDecodeTopLevelStringValue() + { + $m = new StringValue(); + $m->mergeFromJsonString("\"a\""); + $this->assertSame("a", $m->getValue()); + } + + public function testEncodeTopLevelStringValue() + { + $m = new StringValue(); + $m->setValue("a"); + $this->assertSame("\"a\"", $m->serializeToJsonString()); + } + + public function testDecodeRepeatedStringValue() + { + $m = new TestStringValue(); + $m->mergeFromJsonString("{\"repeated_field\":[\"a\"]}"); + $this->assertSame("a", $m->getRepeatedField()[0]->getValue()); + } + + public function testDecodeMapStringValue() + { + $m = new TestStringValue(); + $m->mergeFromJsonString("{\"map_field\":{\"1\": \"a\"}}"); + $this->assertSame("a", $m->getMapField()[1]->getValue()); + } + + public function testDecodeTopLevelBytesValue() + { + $m = new BytesValue(); + $m->mergeFromJsonString("\"YQ==\""); + $this->assertSame("a", $m->getValue()); + } + + public function testEncodeTopLevelBytesValue() + { + $m = new BytesValue(); + $m->setValue("a"); + $this->assertSame("\"YQ==\"", $m->serializeToJsonString()); + } + + public function generateRandomString($length = 10) { + $randomString = str_repeat("+", $length); + for ($i = 0; $i < $length; $i++) { + $randomString[$i] = chr(rand(0, 255)); + } + return $randomString; + } + + public function testEncodeTopLevelLongBytesValue() + { + $m = new BytesValue(); + $data = $this->generateRandomString(12007); + $m->setValue($data); + $expected = "\"" . base64_encode($data) . "\""; + $this->assertSame(strlen($expected), strlen($m->serializeToJsonString())); + } + + public function testEncode() + { + $from = new TestMessage(); + $this->expectEmptyFields($from); + $this->setFields($from); + $this->expectFields($from); + + $data = $from->serializeToString(); + $this->assertSame(bin2hex(TestUtil::getGoldenTestMessage()), + bin2hex($data)); + } + + public function testDecode() + { + $to = new TestMessage(); + $to->mergeFromString(TestUtil::getGoldenTestMessage()); + $this->expectFields($to); + } + + public function testEncodeDecode() + { + $from = new TestMessage(); + $this->expectEmptyFields($from); + $this->setFields($from); + $this->expectFields($from); + + $data = $from->serializeToString(); + + $to = new TestMessage(); + $to->mergeFromString($data); + $this->expectFields($to); + } + + public function testEncodeDecodeEmpty() + { + $from = new TestMessage(); + $this->expectEmptyFields($from); + + $data = $from->serializeToString(); + + $to = new TestMessage(); + $to->mergeFromString($data); + $this->expectEmptyFields($to); + } + + public function testEncodeDecodeOneof() + { + $m = new TestMessage(); + + $m->setOneofInt32(1); + $data = $m->serializeToString(); + $n = new TestMessage(); + $n->mergeFromString($data); + $this->assertSame(1, $n->getOneofInt32()); + + $m->setOneofFloat(2.0); + $data = $m->serializeToString(); + $n = new TestMessage(); + $n->mergeFromString($data); + $this->assertSame(2.0, $n->getOneofFloat()); + + $m->setOneofString('abc'); + $data = $m->serializeToString(); + $n = new TestMessage(); + $n->mergeFromString($data); + $this->assertSame('abc', $n->getOneofString()); + + $sub_m = new Sub(); + $sub_m->setA(1); + $m->setOneofMessage($sub_m); + $data = $m->serializeToString(); + $n = new TestMessage(); + $n->mergeFromString($data); + $this->assertSame(1, $n->getOneofMessage()->getA()); + + // Encode default value + $m->setOneofEnum(TestEnum::ZERO); + $data = $m->serializeToString(); + $n = new TestMessage(); + $n->mergeFromString($data); + $this->assertSame("oneof_enum", $n->getMyOneof()); + $this->assertSame(TestEnum::ZERO, $n->getOneofEnum()); + + $m->setOneofString(""); + $data = $m->serializeToString(); + $n = new TestMessage(); + $n->mergeFromString($data); + $this->assertSame("oneof_string", $n->getMyOneof()); + $this->assertSame("", $n->getOneofString()); + + $sub_m = new Sub(); + $m->setOneofMessage($sub_m); + $data = $m->serializeToString(); + $n = new TestMessage(); + $n->mergeFromString($data); + $this->assertSame("oneof_message", $n->getMyOneof()); + $this->assertFalse(is_null($n->getOneofMessage())); + + } + + public function testEncodeDecodeOptional() + { + $m = new TestMessage(); + $this->assertFalse($m->hasTrueOptionalInt32()); + $data = $m->serializeToString(); + $this->assertSame("", $data); + + $m->setTrueOptionalInt32(0); + $this->assertTrue($m->hasTrueOptionalInt32()); + $data = $m->serializeToString(); + $this->assertNotSame("", $data); + + $m2 = new TestMessage(); + $m2->mergeFromString($data); + $this->assertTrue($m2->hasTrueOptionalInt32()); + $this->assertSame(0, $m2->getTrueOptionalInt32()); + } + + public function testJsonEncodeDecodeOptional() + { + $m = new TestMessage(); + $this->assertFalse($m->hasTrueOptionalInt32()); + $data = $m->serializeToJsonString(); + $this->assertSame("{}", $data); + + $m->setTrueOptionalInt32(0); + $this->assertTrue($m->hasTrueOptionalInt32()); + $data = $m->serializeToJsonString(); + $this->assertNotSame("{}", $data); + + $m2 = new TestMessage(); + $m2->mergeFromJsonString($data); + $this->assertTrue($m2->hasTrueOptionalInt32()); + $this->assertSame(0, $m2->getTrueOptionalInt32()); + } + + public function testJsonEncodeDecodeOneof() + { + $m = new TestMessage(); + + $m->setOneofEnum(TestEnum::ONE); + $data = $m->serializeToJsonString(); + $n = new TestMessage(); + $n->mergeFromJsonString($data); + $this->assertSame("oneof_enum", $n->getMyOneof()); + $this->assertSame(TestEnum::ONE, $n->getOneofEnum()); + + $m->setOneofString("a"); + $data = $m->serializeToJsonString(); + $n = new TestMessage(); + $n->mergeFromJsonString($data); + $this->assertSame("oneof_string", $n->getMyOneof()); + $this->assertSame("a", $n->getOneofString()); + + $m->setOneofBytes("bbbb"); + $data = $m->serializeToJsonString(); + $n = new TestMessage(); + $n->mergeFromJsonString($data); + $this->assertSame("oneof_bytes", $n->getMyOneof()); + $this->assertSame("bbbb", $n->getOneofBytes()); + + $sub_m = new Sub(); + $m->setOneofMessage($sub_m); + $data = $m->serializeToJsonString(); + $n = new TestMessage(); + $n->mergeFromJsonString($data); + $this->assertSame("oneof_message", $n->getMyOneof()); + $this->assertFalse(is_null($n->getOneofMessage())); + } + + public function testPackedEncode() + { + $from = new TestPackedMessage(); + TestUtil::setTestPackedMessage($from); + $this->assertSame(TestUtil::getGoldenTestPackedMessage(), + $from->serializeToString()); + } + + public function testPackedDecodePacked() + { + $to = new TestPackedMessage(); + $to->mergeFromString(TestUtil::getGoldenTestPackedMessage()); + TestUtil::assertTestPackedMessage($to); + $this->assertTrue(true); + } + + public function testPackedDecodeUnpacked() + { + $to = new TestPackedMessage(); + $to->mergeFromString(TestUtil::getGoldenTestUnpackedMessage()); + TestUtil::assertTestPackedMessage($to); + $this->assertTrue(true); + } + + public function testUnpackedEncode() + { + $from = new TestUnpackedMessage(); + TestUtil::setTestPackedMessage($from); + $this->assertSame(TestUtil::getGoldenTestUnpackedMessage(), + $from->serializeToString()); + } + + public function testUnpackedDecodePacked() + { + $to = new TestUnpackedMessage(); + $to->mergeFromString(TestUtil::getGoldenTestPackedMessage()); + TestUtil::assertTestPackedMessage($to); + $this->assertTrue(true); + } + + public function testUnpackedDecodeUnpacked() + { + $to = new TestUnpackedMessage(); + $to->mergeFromString(TestUtil::getGoldenTestUnpackedMessage()); + TestUtil::assertTestPackedMessage($to); + $this->assertTrue(true); + } + + public function testDecodeInt64() + { + // Read 64 testing + $testVals = array( + '10' => '100a', + '100' => '1064', + '800' => '10a006', + '6400' => '108032', + '70400' => '1080a604', + '774400' => '1080a22f', + '9292800' => '108098b704', + '74342400' => '1080c0b923', + '743424000' => '108080bfe202', + '8177664000' => '108080b5bb1e', + '65421312000' => '108080a8dbf301', + '785055744000' => '108080e0c7ec16', + '9420668928000' => '10808080dd969202', + '103627358208000' => '10808080fff9c717', + '1139900940288000' => '10808080f5bd978302', + '13678811283456000' => '10808080fce699a618', + '109430490267648000' => '10808080e0b7ceb1c201', + '984874412408832000' => '10808080e0f5c1bed50d', + ); + + $msg = new TestMessage(); + foreach ($testVals as $original => $encoded) { + $msg->setOptionalInt64($original); + $data = $msg->serializeToString(); + $this->assertSame($encoded, bin2hex($data)); + $msg->setOptionalInt64(0); + $msg->mergeFromString($data); + $this->assertEquals($original, $msg->getOptionalInt64()); + } + } + + public function testDecodeToExistingMessage() + { + $m1 = new TestMessage(); + $this->setFields($m1); + $this->expectFields($m1); + + $m2 = new TestMessage(); + $this->setFields2($m2); + $data = $m2->serializeToString(); + + $m1->mergeFromString($data); + $this->expectFieldsMerged($m1); + } + + public function testDecodeFieldNonExist() + { + $data = hex2bin('c80501'); + $m = new TestMessage(); + $m->mergeFromString($data); + $this->assertTrue(true); + } + + public function testEncodeNegativeInt32() + { + $m = new TestMessage(); + $m->setOptionalInt32(-1); + $data = $m->serializeToString(); + $this->assertSame("08ffffffffffffffffff01", bin2hex($data)); + } + + public function testDecodeNegativeInt32() + { + $m = new TestMessage(); + $this->assertEquals(0, $m->getOptionalInt32()); + $m->mergeFromString(hex2bin("08ffffffffffffffffff01")); + $this->assertEquals(-1, $m->getOptionalInt32()); + + $m = new TestMessage(); + $this->assertEquals(0, $m->getOptionalInt32()); + $m->mergeFromString(hex2bin("08ffffffff0f")); + $this->assertEquals(-1, $m->getOptionalInt32()); + } + + public function testRandomFieldOrder() + { + $m = new TestRandomFieldOrder(); + $data = $m->serializeToString(); + $this->assertSame("", $data); + } + + public function testLargeFieldNumber() + { + $m = new TestLargeFieldNumber(['large_field_number' => 5]); + $data = $m->serializeToString(); + $m2 = new TestLargeFieldNumber(); + $m2->mergeFromString($data); + $this->assertSame(5, $m2->getLargeFieldNumber()); + } + + public function testDecodeInvalidInt32() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('08')); + } + + public function testDecodeInvalidSubMessage() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('9A010108')); + } + + public function testDecodeInvalidInt64() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('10')); + } + + public function testDecodeInvalidUInt32() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('18')); + } + + public function testDecodeInvalidUInt64() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('20')); + } + + public function testDecodeInvalidSInt32() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('28')); + } + + public function testDecodeInvalidSInt64() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('30')); + } + + public function testDecodeInvalidFixed32() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('3D')); + } + + public function testDecodeInvalidFixed64() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('41')); + } + + public function testDecodeInvalidSFixed32() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('4D')); + } + + public function testDecodeInvalidSFixed64() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('51')); + } + + public function testDecodeInvalidFloat() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('5D')); + } + + public function testDecodeInvalidDouble() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('61')); + } + + public function testDecodeInvalidBool() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('68')); + } + + public function testDecodeInvalidStringLengthMiss() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('72')); + } + + public function testDecodeInvalidStringDataMiss() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('7201')); + } + + public function testDecodeInvalidBytesLengthMiss() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('7A')); + } + + public function testDecodeInvalidBytesDataMiss() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('7A01')); + } + + public function testDecodeInvalidEnum() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('8001')); + } + + public function testDecodeInvalidMessageLengthMiss() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('8A01')); + } + + public function testDecodeInvalidMessageDataMiss() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('8A0101')); + } + + public function testDecodeInvalidPackedMessageLength() + { + $this->expectException(Exception::class); + + $m = new TestPackedMessage(); + $m->mergeFromString(hex2bin('D205')); + } + + public function testUnknown() + { + // Test preserve unknown for varint. + $m = new TestMessage(); + $from = hex2bin('F80601'); // TODO(teboring): Add a util to encode + // varint for better readability + $m->mergeFromString($from); + $to = $m->serializeToString(); + $this->assertSame(bin2hex($from), bin2hex($to)); + + // Test preserve unknown for 64-bit. + $m = new TestMessage(); + $from = hex2bin('F9060000000000000000'); + $m->mergeFromString($from); + $to = $m->serializeToString(); + $this->assertSame(bin2hex($from), bin2hex($to)); + + // Test preserve unknown for length delimited. + $m = new TestMessage(); + $from = hex2bin('FA0600'); + $m->mergeFromString($from); + $to = $m->serializeToString(); + $this->assertSame(bin2hex($from), bin2hex($to)); + + // Test preserve unknown for 32-bit. + $m = new TestMessage(); + $from = hex2bin('FD0600000000'); + $m->mergeFromString($from); + $to = $m->serializeToString(); + $this->assertSame(bin2hex($from), bin2hex($to)); + + // Test discard unknown in message. + $m = new TestMessage(); + $from = hex2bin('F80601'); + $m->mergeFromString($from); + $m->discardUnknownFields(); + $to = $m->serializeToString(); + $this->assertSame("", bin2hex($to)); + + // Test discard unknown for singular message field. + $m = new TestMessage(); + $from = hex2bin('8A0103F80601'); + $m->mergeFromString($from); + $m->discardUnknownFields(); + $to = $m->serializeToString(); + $this->assertSame("8a0100", bin2hex($to)); + + // Test discard unknown for repeated message field. + $m = new TestMessage(); + $from = hex2bin('FA0203F80601'); + $m->mergeFromString($from); + $m->discardUnknownFields(); + $to = $m->serializeToString(); + $this->assertSame("fa0200", bin2hex($to)); + + // Test discard unknown for map message value field. + $m = new TestMessage(); + $from = hex2bin("BA050708011203F80601"); + $m->mergeFromString($from); + $m->discardUnknownFields(); + $to = $m->serializeToString(); + $this->assertSame("ba050408011200", bin2hex($to)); + + // Test discard unknown for singular message field. + $m = new TestMessage(); + $from = hex2bin('9A0403F80601'); + $m->mergeFromString($from); + $m->discardUnknownFields(); + $to = $m->serializeToString(); + $this->assertSame("9a0400", bin2hex($to)); + } + + public function testJsonUnknown() + { + // Test unknown number + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":1, + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown bool + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":true, + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown string + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":\"abc\", + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown null + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":null, + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown array + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":[], + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown number array + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":[1], + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown bool array + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":[true], + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown string array + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":[\"a\"], + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown null array + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":[null], + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown array array + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":[[]], + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown object array + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":[{}], + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown double value array + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":[1, 2], + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown object + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":{}, + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown number object + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":{\"a\":1}, + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown bool object + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":{\"a\":true}, + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown string object + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":{\"a\":\"a\"}, + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown null object + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":{\"a\":null}, + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown array object + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":{\"a\":[]}, + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown object object + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":{\"a\":{}}, + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown double value object + $m = new TestMessage(); + $m->mergeFromJsonString("{\"unknown\":{\"a\":1, \"b\":1}, + \"optionalInt32\":1}", true); + $this->assertSame(1, $m->getOptionalInt32()); + + // Test unknown enum value + $m = new TestMessage(); + $m->mergeFromJsonString("{\"optionalEnum\":\"UNKNOWN\"}", true); + $this->assertSame(0, $m->getOptionalEnum()); + } + + public function testJsonEncode() + { + $from = new TestMessage(); + $this->setFields($from); + $data = $from->serializeToJsonString(); + $to = new TestMessage(); + $to->mergeFromJsonString($data); + $this->expectFields($to); + } + + public function testDecodeDuration() + { + $m = new Google\Protobuf\Duration(); + $m->mergeFromJsonString("\"1234.5678s\""); + $this->assertEquals(1234, $m->getSeconds()); + $this->assertEquals(567800000, $m->getNanos()); + } + + public function testEncodeDuration() + { + $m = new Google\Protobuf\Duration(); + $m->setSeconds(1234); + $m->setNanos(999999999); + $this->assertEquals("\"1234.999999999s\"", $m->serializeToJsonString()); + } + + public function testDecodeTimestamp() + { + $m = new Google\Protobuf\Timestamp(); + $m->mergeFromJsonString("\"2000-01-01T00:00:00.123456789Z\""); + $this->assertEquals(946684800, $m->getSeconds()); + $this->assertEquals(123456789, $m->getNanos()); + } + + public function testEncodeTimestamp() + { + $m = new Google\Protobuf\Timestamp(); + $m->setSeconds(946684800); + $m->setNanos(123456789); + $this->assertEquals("\"2000-01-01T00:00:00.123456789Z\"", + $m->serializeToJsonString()); + } + + public function testDecodeTopLevelValue() + { + $m = new Value(); + $m->mergeFromJsonString("\"a\""); + $this->assertSame("a", $m->getStringValue()); + + $m = new Value(); + $m->mergeFromJsonString("1.5"); + $this->assertSame(1.5, $m->getNumberValue()); + + $m = new Value(); + $m->mergeFromJsonString("true"); + $this->assertSame(true, $m->getBoolValue()); + + $m = new Value(); + $m->mergeFromJsonString("null"); + $this->assertSame("null_value", $m->getKind()); + + $m = new Value(); + $m->mergeFromJsonString("[1]"); + $this->assertSame("list_value", $m->getKind()); + + $m = new Value(); + $m->mergeFromJsonString("{\"a\":1}"); + $this->assertSame("struct_value", $m->getKind()); + } + + public function testEncodeTopLevelValue() + { + $m = new Value(); + $m->setStringValue("a"); + $this->assertSame("\"a\"", $m->serializeToJsonString()); + + $m = new Value(); + $m->setNumberValue(1.5); + $this->assertSame("1.5", $m->serializeToJsonString()); + + $m = new Value(); + $m->setBoolValue(true); + $this->assertSame("true", $m->serializeToJsonString()); + + $m = new Value(); + $m->setNullValue(0); + $this->assertSame("null", $m->serializeToJsonString()); + } + + public function testDecodeTopLevelListValue() + { + $m = new ListValue(); + $m->mergeFromJsonString("[1]"); + $this->assertSame(1.0, $m->getValues()[0]->getNumberValue()); + } + + public function testEncodeTopLevelListValue() + { + $m = new ListValue(); + $arr = $m->getValues(); + $sub = new Value(); + $sub->setNumberValue(1.5); + $arr[] = $sub; + $this->assertSame("[1.5]", $m->serializeToJsonString()); + } + + public function testEncodeEmptyListValue() + { + $m = new Struct(); + $m->setFields(['test' => (new Value())->setListValue(new ListValue())]); + $this->assertSame('{"test":[]}', $m->serializeToJsonString()); + } + + public function testDecodeTopLevelStruct() + { + $m = new Struct(); + $m->mergeFromJsonString("{\"a\":{\"b\":1}}"); + $this->assertSame(1.0, $m->getFields()["a"] + ->getStructValue() + ->getFields()["b"]->getNumberValue()); + } + + public function testEncodeTopLevelStruct() + { + $m = new Struct(); + $map = $m->getFields(); + $sub = new Value(); + $sub->setNumberValue(1.5); + $map["a"] = $sub; + $this->assertSame("{\"a\":1.5}", $m->serializeToJsonString()); + } + + public function testEncodeEmptyStruct() + { + $m = new Struct(); + $m->setFields(['test' => (new Value())->setStructValue(new Struct())]); + $this->assertSame('{"test":{}}', $m->serializeToJsonString()); + } + + public function testDecodeTopLevelAny() + { + // Make sure packed message has been created at least once. + $packed = new TestMessage(); + + $m1 = new Any(); + $m1->mergeFromJsonString( + "{\"optionalInt32\": 1, " . + "\"@type\":\"type.googleapis.com/foo.TestMessage\"}"); + $this->assertSame("type.googleapis.com/foo.TestMessage", + $m1->getTypeUrl()); + $this->assertSame("0801", bin2hex($m1->getValue())); + + $m2 = new Any(); + $m2->mergeFromJsonString( + "{\"@type\":\"type.googleapis.com/foo.TestMessage\", " . + "\"optionalInt32\": 1}"); + $this->assertSame("type.googleapis.com/foo.TestMessage", + $m2->getTypeUrl()); + $this->assertSame("0801", bin2hex($m2->getValue())); + + $m3 = new Any(); + $m3->mergeFromJsonString( + "{\"optionalInt32\": 1, " . + "\"@type\":\"type.googleapis.com/foo.TestMessage\", " . + "\"optionalInt64\": 2}"); + $this->assertSame("type.googleapis.com/foo.TestMessage", + $m3->getTypeUrl()); + $this->assertSame("08011002", bin2hex($m3->getValue())); + } + + public function testDecodeAny() + { + // Make sure packed message has been created at least once. + $packed = new TestMessage(); + + $m1 = new TestAny(); + $m1->mergeFromJsonString( + "{\"any\": {\"optionalInt32\": 1, " . + "\"@type\":\"type.googleapis.com/foo.TestMessage\"}}"); + $this->assertSame("type.googleapis.com/foo.TestMessage", + $m1->getAny()->getTypeUrl()); + $this->assertSame("0801", bin2hex($m1->getAny()->getValue())); + + $m2 = new TestAny(); + $m2->mergeFromJsonString( + "{\"any\":{\"@type\":\"type.googleapis.com/foo.TestMessage\", " . + "\"optionalInt32\": 1}}"); + $this->assertSame("type.googleapis.com/foo.TestMessage", + $m2->getAny()->getTypeUrl()); + $this->assertSame("0801", bin2hex($m2->getAny()->getValue())); + + $m3 = new TestAny(); + $m3->mergeFromJsonString( + "{\"any\":{\"optionalInt32\": 1, " . + "\"@type\":\"type.googleapis.com/foo.TestMessage\", " . + "\"optionalInt64\": 2}}"); + $this->assertSame("type.googleapis.com/foo.TestMessage", + $m3->getAny()->getTypeUrl()); + $this->assertSame("08011002", bin2hex($m3->getAny()->getValue())); + } + + public function testDecodeAnyWithWellKnownPacked() + { + // Make sure packed message has been created at least once. + $packed = new Int32Value(); + + $m1 = new TestAny(); + $m1->mergeFromJsonString( + "{\"any\":" . + " {\"@type\":\"type.googleapis.com/google.protobuf.Int32Value\"," . + " \"value\":1}}"); + $this->assertSame("type.googleapis.com/google.protobuf.Int32Value", + $m1->getAny()->getTypeUrl()); + $this->assertSame("0801", bin2hex($m1->getAny()->getValue())); + } + + public function testDecodeAnyWithUnknownPacked() + { + $this->expectException(Exception::class); + + $m = new TestAny(); + $m->mergeFromJsonString( + "{\"any\":" . + " {\"@type\":\"type.googleapis.com/unknown\"," . + " \"value\":1}}"); + } + + public function testEncodeTopLevelAny() + { + // Test a normal message. + $packed = new TestMessage(); + $packed->setOptionalInt32(123); + $packed->setOptionalString("abc"); + + $m = new Any(); + $m->pack($packed); + $expected1 = + "{\"@type\":\"type.googleapis.com/foo.TestMessage\"," . + "\"optional_int32\":123,\"optional_string\":\"abc\"}"; + $expected2 = + "{\"@type\":\"type.googleapis.com/foo.TestMessage\"," . + "\"optionalInt32\":123,\"optionalString\":\"abc\"}"; + $result = $m->serializeToJsonString(); + $this->assertTrue($expected1 === $result || $expected2 === $result); + + // Test a well known message. + $packed = new Int32Value(); + $packed->setValue(123); + + $m = new Any(); + $m->pack($packed); + $this->assertSame( + "{\"@type\":\"type.googleapis.com/google.protobuf.Int32Value\"," . + "\"value\":123}", + $m->serializeToJsonString()); + + // Test an Any message. + $outer = new Any(); + $outer->pack($m); + $this->assertSame( + "{\"@type\":\"type.googleapis.com/google.protobuf.Any\"," . + "\"value\":{\"@type\":\"type.googleapis.com/google.protobuf.Int32Value\"," . + "\"value\":123}}", + $outer->serializeToJsonString()); + + // Test a Timestamp message. + $packed = new Google\Protobuf\Timestamp(); + $packed->setSeconds(946684800); + $packed->setNanos(123456789); + $m = new Any(); + $m->pack($packed); + $this->assertSame( + "{\"@type\":\"type.googleapis.com/google.protobuf.Timestamp\"," . + "\"value\":\"2000-01-01T00:00:00.123456789Z\"}", + $m->serializeToJsonString()); + } + + public function testEncodeAnyWithDefaultWrapperMessagePacked() + { + $any = new Any(); + $any->pack(new TestInt32Value([ + 'field' => new Int32Value(['value' => 0]), + ])); + $this->assertSame( + "{\"@type\":\"type.googleapis.com/foo.TestInt32Value\"," . + "\"field\":0}", + $any->serializeToJsonString()); + } + + public function testDecodeTopLevelFieldMask() + { + $m = new TestMessage(); + $m->setMapStringString(['a'=>'abcdefg']); + $data1 = $m->serializeToJsonString(); + $n = new TestMessage(); + $n->mergeFromJsonString($data1); + $data2 = $n->serializeToJsonString(); + $this->assertSame($data1, $data2); + + $m = new FieldMask(); + $m->mergeFromJsonString("\"foo.barBaz,qux\""); + $this->assertSame("foo.bar_baz", $m->getPaths()[0]); + $this->assertSame("qux", $m->getPaths()[1]); + } + + public function testEncodeTopLevelFieldMask() + { + $m = new FieldMask(); + $m->setPaths(["foo.bar_baz", "qux"]); + $this->assertSame("\"foo.barBaz,qux\"", $m->serializeToJsonString()); + } + + public function testDecodeEmptyFieldMask() + { + $m = new FieldMask(); + $m->mergeFromJsonString("\"\""); + $this->assertEquals("", $m->serializeToString()); + } + + public function testJsonDecodeMapWithDefaultValueKey() + { + $m = new TestMessage(); + $m->getMapInt32Int32()[0] = 0; + $this->assertSame("{\"mapInt32Int32\":{\"0\":0}}", + $m->serializeToJsonString()); + + $m = new TestMessage(); + $m->getMapStringString()[""] = ""; + $this->assertSame("{\"mapStringString\":{\"\":\"\"}}", + $m->serializeToJsonString()); + } + + public function testJsonDecodeNumericStringMapKey() + { + $m = new TestMessage(); + $m->getMapStringString()["1"] = "1"; + $data = $m->serializeToJsonString(); + $this->assertSame("{\"mapStringString\":{\"1\":\"1\"}}", $data); + $n = new TestMessage(); + $n->mergeFromJsonString($data); + } + + public function testMessageMapNoValue() + { + $m = new TestMessage(); + $m->mergeFromString(hex2bin("CA0700")); + $m->serializeToString(); + $this->assertTrue(true); + } + + public function testAnyMapNoValue() + { + $m = new TestMessage(); + $m->mergeFromString(hex2bin("D20700")); + $m->serializeToString(); + $this->assertTrue(true); + } + + public function testListValueMapNoValue() + { + $m = new TestMessage(); + $m->mergeFromString(hex2bin("DA0700")); + $m->serializeToString(); + $this->assertTrue(true); + } + + public function testStructMapNoValue() + { + $m = new TestMessage(); + $m->mergeFromString(hex2bin("E20700")); + $m->serializeToString(); + $this->assertTrue(true); + } + + /** + * @dataProvider wrappersDataProvider + */ + public function testWrapperJsonDecodeAndGet( + $class, + $nonDefaultValue, + $nonDefaultValueData, + $defaultValue, + $defaultValueData + ) + { + // Singular with non-default + $m = new $class(); + $m->mergeFromJsonString("{\"field\":" . $nonDefaultValueData . "}"); + $wrapper = $m->getField(); + $this->assertEquals($nonDefaultValue, $wrapper->getValue()); + + // Singular with default + $m = new $class(); + $m->mergeFromJsonString("{\"field\":" . $defaultValueData . "}"); + $wrapper = $m->getField(); + $this->assertEquals($defaultValue, $wrapper->getValue()); + + // Repeated with empty + $m = new $class(); + $m->mergeFromJsonString("{\"repeated_field\":[]}"); + $repeatedWrapper = $m->getRepeatedField(); + $this->assertSame(0, count($repeatedWrapper)); + + // Repeated with non-default + $m = new $class(); + $m->mergeFromJsonString("{\"repeated_field\":[" . $defaultValueData . "]}"); + $repeatedWrapper = $m->getRepeatedField(); + $this->assertSame(1, count($repeatedWrapper)); + $this->assertEquals($defaultValue, $repeatedWrapper[0]->getValue()); + + // Repeated with default + $m = new $class(); + $m->mergeFromJsonString("{\"repeated_field\":[" . $defaultValueData . "]}"); + $repeatedWrapper = $m->getRepeatedField(); + $this->assertSame(1, count($repeatedWrapper)); + $this->assertEquals($defaultValue, $repeatedWrapper[0]->getValue()); + + // Oneof with non-default + $m = new $class(); + $m->mergeFromJsonString("{\"oneof_field\":" . $nonDefaultValueData . "}"); + $wrapper = $m->getOneofField(); + $this->assertEquals($nonDefaultValue, $wrapper->getValue()); + $this->assertEquals("oneof_field", $m->getOneofFields()); + $this->assertEquals(0, $m->getInt32Field()); + + // Oneof with default + $m = new $class(); + $m->mergeFromJsonString("{\"oneof_field\":" . $defaultValueData . "}"); + $wrapper = $m->getOneofField(); + $this->assertEquals($defaultValue, $wrapper->getValue()); + $this->assertEquals("oneof_field", $m->getOneofFields()); + $this->assertEquals(0, $m->getInt32Field()); + } + + /** + * @dataProvider wrappersDataProvider + */ + public function testWrapperJsonDecodeAndGetUnwrapped( + $class, + $nonDefaultValue, + $nonDefaultValueData, + $defaultValue, + $defaultValueData + ) + { + // Singular with non-default + $m = new $class(); + $m->mergeFromJsonString("{\"field\":" . $nonDefaultValueData . "}"); + $this->assertEquals($nonDefaultValue, $m->getFieldUnwrapped()); + + // Singular with default + $m = new $class(); + $m->mergeFromJsonString("{\"field\":" . $defaultValueData . "}"); + $this->assertEquals($defaultValue, $m->getFieldUnwrapped()); + + // Oneof with non-default + $m = new $class(); + $m->mergeFromJsonString("{\"oneof_field\":" . $nonDefaultValueData . "}"); + $this->assertEquals($nonDefaultValue, $m->getOneofFieldUnwrapped()); + $this->assertEquals("oneof_field", $m->getOneofFields()); + $this->assertEquals(0, $m->getInt32Field()); + + // Oneof with default + $m = new $class(); + $m->mergeFromJsonString("{\"oneof_field\":" . $defaultValueData . "}"); + $this->assertEquals($defaultValue, $m->getOneofFieldUnwrapped()); + $this->assertEquals("oneof_field", $m->getOneofFields()); + $this->assertEquals(0, $m->getInt32Field()); + } + + /** + * @dataProvider wrappersDataProvider + */ + public function testWrapperJsonDecodeEncode( + $class, + $nonDefaultValue, + $nonDefaultValueData, + $defaultValue, + $defaultValueData + ) + { + // Singular with non-default + $from = new $class(); + $to = new $class(); + $from->mergeFromJsonString("{\"field\":" . $nonDefaultValueData . "}"); + $data = $from->serializeToJsonString(); + $to->mergeFromJsonString($data); + $this->assertEquals($nonDefaultValue, $to->getFieldUnwrapped()); + + // Singular with default + $from = new $class(); + $to = new $class(); + $from->mergeFromJsonString("{\"field\":" . $defaultValueData . "}"); + $data = $from->serializeToJsonString(); + $to->mergeFromJsonString($data); + $this->assertEquals($defaultValue, $to->getFieldUnwrapped()); + + // Oneof with non-default + $from = new $class(); + $to = new $class(); + $from->mergeFromJsonString("{\"oneof_field\":" . $nonDefaultValueData . "}"); + $data = $from->serializeToJsonString(); + $to->mergeFromJsonString($data); + $this->assertEquals($nonDefaultValue, $to->getOneofFieldUnwrapped()); + + // Oneof with default + $from = new $class(); + $to = new $class(); + $from->mergeFromJsonString("{\"oneof_field\":" . $defaultValueData . "}"); + $data = $from->serializeToJsonString(); + $to->mergeFromJsonString($data); + $this->assertEquals($defaultValue, $to->getOneofFieldUnwrapped()); + } + + /** + * @dataProvider wrappersDataProvider + */ + public function testWrapperSetUnwrappedJsonEncode( + $class, + $nonDefaultValue, + $nonDefaultValueData, + $defaultValue, + $defaultValueData + ) + { + // Singular with non-default + $from = new $class(); + $to = new $class(); + $from->setFieldUnwrapped($nonDefaultValue); + $data = $from->serializeToJsonString(); + $to->mergeFromJsonString($data); + $this->assertEquals($nonDefaultValue, $to->getFieldUnwrapped()); + + // Singular with default + $from = new $class(); + $to = new $class(); + $from->setFieldUnwrapped($defaultValue); + $data = $from->serializeToJsonString(); + $to->mergeFromJsonString($data); + $this->assertEquals($defaultValue, $to->getFieldUnwrapped()); + + // Oneof with non-default + $from = new $class(); + $to = new $class(); + $from->setOneofFieldUnwrapped($nonDefaultValue); + $data = $from->serializeToJsonString(); + $to->mergeFromJsonString($data); + $this->assertEquals($nonDefaultValue, $to->getOneofFieldUnwrapped()); + + // Oneof with default + $from = new $class(); + $to = new $class(); + $from->setOneofFieldUnwrapped($defaultValue); + $data = $from->serializeToJsonString(); + $to->mergeFromJsonString($data); + $this->assertEquals($defaultValue, $to->getOneofFieldUnwrapped()); + } + + public function wrappersDataProvider() + { + return [ + [TestInt32Value::class, 1, "1", 0, "0"], + [TestStringValue::class, "a", "\"a\"", "", "\"\""], + ]; + } +} diff --git a/php/tests/GeneratedClassTest.php b/php/tests/GeneratedClassTest.php new file mode 100644 index 0000000000000..f2a9fb057d132 --- /dev/null +++ b/php/tests/GeneratedClassTest.php @@ -0,0 +1,1803 @@ +setOptionalInt32(1); + $this->assertSame(1, $m->getOptionalInt32()); + } + + ######################################################### + # Test int32 field. + ######################################################### + + public function testInt32Field() + { + $m = new TestMessage(); + + // Set integer. + $m->setOptionalInt32(MAX_INT32); + $this->assertSame(MAX_INT32, $m->getOptionalInt32()); + $m->setOptionalInt32(MIN_INT32); + $this->assertSame(MIN_INT32, $m->getOptionalInt32()); + + // Set float. + $m->setOptionalInt32(1.1); + $this->assertSame(1, $m->getOptionalInt32()); + $m->setOptionalInt32(MAX_INT32_FLOAT); + $this->assertSame(MAX_INT32, $m->getOptionalInt32()); + $m->setOptionalInt32(MIN_INT32_FLOAT); + $this->assertSame(MIN_INT32, $m->getOptionalInt32()); + + // Set string. + $m->setOptionalInt32('2'); + $this->assertSame(2, $m->getOptionalInt32()); + $m->setOptionalInt32('3.1'); + $this->assertSame(3, $m->getOptionalInt32()); + $m->setOptionalInt32(MAX_INT32_STRING); + $this->assertSame(MAX_INT32, $m->getOptionalInt32()); + $m->setOptionalInt32(MIN_INT32_STRING); + $this->assertSame(MIN_INT32, $m->getOptionalInt32()); + } + + ######################################################### + # Test deprecated int32 field. + ######################################################### + + public function testDeprecatedInt32Field() + { + $m = new TestMessage(); + + // temporarily change error handler to capture the deprecated errors + $deprecationCount = 0; + set_error_handler(function ($errno, $errstr) use (&$deprecationCount) { + if ($errstr === 'deprecated_optional_int32 is deprecated.') { + $deprecationCount++; + } + }, E_USER_DEPRECATED); + + // default test set + $m->setDeprecatedOptionalInt32(MAX_INT32); + $this->assertSame(MAX_INT32, $m->getDeprecatedOptionalInt32()); + $m->setDeprecatedOptionalInt32(MIN_INT32); + $this->assertSame(MIN_INT32, $m->getDeprecatedOptionalInt32()); + + restore_error_handler(); + + $this->assertSame(4, $deprecationCount); + } + + ######################################################### + # Test optional int32 field. + ######################################################### + + public function testOptionalInt32Field() + { + $m = new TestMessage(); + + $this->assertFalse($m->hasTrueOptionalInt32()); + $this->assertSame(0, $m->getTrueOptionalInt32()); + + // Set integer. + $m->setTrueOptionalInt32(MAX_INT32); + $this->assertTrue($m->hasTrueOptionalInt32()); + $this->assertSame(MAX_INT32, $m->getTrueOptionalInt32()); + + // Clear integer. + $m->clearTrueOptionalInt32(); + $this->assertFalse($m->hasTrueOptionalInt32()); + $this->assertSame(0, $m->getTrueOptionalInt32()); + } + + ######################################################### + # Test uint32 field. + ######################################################### + + public function testUint32Field() + { + $m = new TestMessage(); + + // Set integer. + $m->setOptionalUint32(MAX_UINT32); + $this->assertSame(-1, $m->getOptionalUint32()); + $m->setOptionalUint32(-1); + $this->assertSame(-1, $m->getOptionalUint32()); + $m->setOptionalUint32(MIN_UINT32); + $this->assertSame(MIN_INT32, $m->getOptionalUint32()); + + // Set float. + $m->setOptionalUint32(1.1); + $this->assertSame(1, $m->getOptionalUint32()); + $m->setOptionalUint32(MAX_UINT32_FLOAT); + $this->assertSame(-1, $m->getOptionalUint32()); + $m->setOptionalUint32(-1.0); + $this->assertSame(-1, $m->getOptionalUint32()); + $m->setOptionalUint32(MIN_UINT32_FLOAT); + $this->assertSame(MIN_INT32, $m->getOptionalUint32()); + + // Set string. + $m->setOptionalUint32('2'); + $this->assertSame(2, $m->getOptionalUint32()); + $m->setOptionalUint32('3.1'); + $this->assertSame(3, $m->getOptionalUint32()); + $m->setOptionalUint32(MAX_UINT32_STRING); + $this->assertSame(-1, $m->getOptionalUint32()); + $m->setOptionalUint32('-1.0'); + $this->assertSame(-1, $m->getOptionalUint32()); + $m->setOptionalUint32(MIN_UINT32_STRING); + $this->assertSame(MIN_INT32, $m->getOptionalUint32()); + } + + ######################################################### + # Test int64 field. + ######################################################### + + public function testInt64Field() + { + $m = new TestMessage(); + + // Set integer. + $m->setOptionalInt64(MAX_INT64); + $this->assertSame(MAX_INT64, $m->getOptionalInt64()); + $m->setOptionalInt64(MIN_INT64); + $this->assertEquals(MIN_INT64, $m->getOptionalInt64()); + + // Set float. + $m->setOptionalInt64(1.1); + if (PHP_INT_SIZE == 4) { + $this->assertSame('1', $m->getOptionalInt64()); + } else { + $this->assertSame(1, $m->getOptionalInt64()); + } + + // Set string. + $m->setOptionalInt64('2'); + if (PHP_INT_SIZE == 4) { + $this->assertSame('2', $m->getOptionalInt64()); + } else { + $this->assertSame(2, $m->getOptionalInt64()); + } + + $m->setOptionalInt64('3.1'); + if (PHP_INT_SIZE == 4) { + $this->assertSame('3', $m->getOptionalInt64()); + } else { + $this->assertSame(3, $m->getOptionalInt64()); + } + + $m->setOptionalInt64(MAX_INT64_STRING); + if (PHP_INT_SIZE == 4) { + $this->assertSame(MAX_INT64_STRING, $m->getOptionalInt64()); + } else { + $this->assertSame(MAX_INT64, $m->getOptionalInt64()); + } + + $m->setOptionalInt64(MIN_INT64_STRING); + if (PHP_INT_SIZE == 4) { + $this->assertSame(MIN_INT64_STRING, $m->getOptionalInt64()); + } else { + $this->assertSame(MIN_INT64, $m->getOptionalInt64()); + } + } + + ######################################################### + # Test uint64 field. + ######################################################### + + public function testUint64Field() + { + $m = new TestMessage(); + + // Set integer. + $m->setOptionalUint64(MAX_UINT64); + if (PHP_INT_SIZE == 4) { + $this->assertSame(MAX_UINT64_STRING, $m->getOptionalUint64()); + } else { + $this->assertSame(MAX_UINT64, $m->getOptionalUint64()); + } + + // Set float. + $m->setOptionalUint64(1.1); + if (PHP_INT_SIZE == 4) { + $this->assertSame('1', $m->getOptionalUint64()); + } else { + $this->assertSame(1, $m->getOptionalUint64()); + } + + // Set string. + $m->setOptionalUint64('2'); + if (PHP_INT_SIZE == 4) { + $this->assertSame('2', $m->getOptionalUint64()); + } else { + $this->assertSame(2, $m->getOptionalUint64()); + } + + $m->setOptionalUint64('3.1'); + if (PHP_INT_SIZE == 4) { + $this->assertSame('3', $m->getOptionalUint64()); + } else { + $this->assertSame(3, $m->getOptionalUint64()); + } + + $m->setOptionalUint64(MAX_UINT64_STRING); + if (PHP_INT_SIZE == 4) { + $this->assertSame(MAX_UINT64_STRING, $m->getOptionalUint64()); + } else { + $this->assertSame(MAX_UINT64, $m->getOptionalUint64()); + } + } + + ######################################################### + # Test enum field. + ######################################################### + + public function testEnumField() + { + $m = new TestMessage(); + + // Set enum. + $m->setOptionalEnum(TestEnum::ONE); + $this->assertEquals(TestEnum::ONE, $m->getOptionalEnum()); + + // Set integer. + $m->setOptionalEnum(1); + $this->assertEquals(TestEnum::ONE, $m->getOptionalEnum()); + + // Set float. + $m->setOptionalEnum(1.1); + $this->assertEquals(TestEnum::ONE, $m->getOptionalEnum()); + + // Set string. + $m->setOptionalEnum("1"); + $this->assertEquals(TestEnum::ONE, $m->getOptionalEnum()); + + // Test Enum methods + $this->assertEquals('ONE', TestEnum::name(1)); + $this->assertEquals(1, TestEnum::value('ONE')); + } + + public function testInvalidEnumValueThrowsException() + { + $this->expectException(UnexpectedValueException::class); + $this->expectExceptionMessage( + 'Enum Foo\TestEnum has no name defined for value -1'); + + TestEnum::name(-1); + } + + public function testInvalidEnumNameThrowsException() + { + $this->expectException(UnexpectedValueException::class); + $this->expectExceptionMessage( + 'Enum Foo\TestEnum has no value defined for name DOES_NOT_EXIST'); + + TestEnum::value('DOES_NOT_EXIST'); + } + + public function testNestedEnum() + { + $m = new TestMessage(); + $m->setOptionalNestedEnum(NestedEnum::ZERO); + $this->assertTrue(true); + } + + public function testLegacyNestedEnum() + { + $m = new TestMessage(); + $m->setOptionalNestedEnum(\Foo\TestMessage_NestedEnum::ZERO); + $this->assertTrue(true); + } + + public function testLegacyTypehintWithNestedEnums() + { + $this->legacyEnum(new TestLegacyMessage\NestedEnum); + } + + private function legacyEnum(TestLegacyMessage_NestedEnum $enum) + { + // If we made it here without a PHP Fatal error, the typehint worked + $this->assertTrue(true); + } + + ######################################################### + # Test float field. + ######################################################### + + public function testFloatField() + { + $m = new TestMessage(); + + // Set integer. + $m->setOptionalFloat(1); + $this->assertFloatEquals(1.0, $m->getOptionalFloat(), MAX_FLOAT_DIFF); + + // Set float. + $m->setOptionalFloat(1.1); + $this->assertFloatEquals(1.1, $m->getOptionalFloat(), MAX_FLOAT_DIFF); + + // Set string. + $m->setOptionalFloat('2'); + $this->assertFloatEquals(2.0, $m->getOptionalFloat(), MAX_FLOAT_DIFF); + $m->setOptionalFloat('3.1'); + $this->assertFloatEquals(3.1, $m->getOptionalFloat(), MAX_FLOAT_DIFF); + } + + ######################################################### + # Test double field. + ######################################################### + + public function testDoubleField() + { + $m = new TestMessage(); + + // Set integer. + $m->setOptionalDouble(1); + $this->assertFloatEquals(1.0, $m->getOptionalDouble(), MAX_FLOAT_DIFF); + + // Set float. + $m->setOptionalDouble(1.1); + $this->assertFloatEquals(1.1, $m->getOptionalDouble(), MAX_FLOAT_DIFF); + + // Set string. + $m->setOptionalDouble('2'); + $this->assertFloatEquals(2.0, $m->getOptionalDouble(), MAX_FLOAT_DIFF); + $m->setOptionalDouble('3.1'); + $this->assertFloatEquals(3.1, $m->getOptionalDouble(), MAX_FLOAT_DIFF); + } + + ######################################################### + # Test bool field. + ######################################################### + + public function testBoolField() + { + $m = new TestMessage(); + + // Set bool. + $m->setOptionalBool(true); + $this->assertSame(true, $m->getOptionalBool()); + + // Set integer. + $m->setOptionalBool(-1); + $this->assertSame(true, $m->getOptionalBool()); + + // Set float. + $m->setOptionalBool(1.1); + $this->assertSame(true, $m->getOptionalBool()); + + // Set string. + $m->setOptionalBool(''); + $this->assertSame(false, $m->getOptionalBool()); + } + + ######################################################### + # Test string field. + ######################################################### + + public function testStringField() + { + $m = new TestMessage(); + + // Set string. + $m->setOptionalString('abc'); + $this->assertSame('abc', $m->getOptionalString()); + + // Set integer. + $m->setOptionalString(1); + $this->assertSame('1', $m->getOptionalString()); + + // Set double. + $m->setOptionalString(1.1); + $this->assertSame('1.1', $m->getOptionalString()); + + // Set bool. + $m->setOptionalString(true); + $this->assertSame('1', $m->getOptionalString()); + } + + ######################################################### + # Test bytes field. + ######################################################### + + public function testBytesField() + { + $m = new TestMessage(); + + // Set string. + $m->setOptionalBytes('abc'); + $this->assertSame('abc', $m->getOptionalBytes()); + + // Set integer. + $m->setOptionalBytes(1); + $this->assertSame('1', $m->getOptionalBytes()); + + // Set double. + $m->setOptionalBytes(1.1); + $this->assertSame('1.1', $m->getOptionalBytes()); + + // Set bool. + $m->setOptionalBytes(true); + $this->assertSame('1', $m->getOptionalBytes()); + } + + public function testBytesFieldInvalidUTF8Success() + { + $m = new TestMessage(); + $hex = hex2bin("ff"); + $m->setOptionalBytes($hex); + $this->assertTrue(true); + } + + ######################################################### + # Test message field. + ######################################################### + + public function testMessageField() + { + $m = new TestMessage(); + + $sub_m = new Sub(); + $sub_m->setA(1); + $m->setOptionalMessage($sub_m); + $this->assertSame(1, $m->getOptionalMessage()->getA()); + + $null = null; + $m->setOptionalMessage($null); + $this->assertNull($m->getOptionalMessage()); + } + + public function testLegacyMessageField() + { + $m = new TestMessage(); + + $sub_m = new TestMessage_Sub(); + $sub_m->setA(1); + $m->setOptionalMessage($sub_m); + $this->assertSame(1, $m->getOptionalMessage()->getA()); + + $null = null; + $m->setOptionalMessage($null); + $this->assertNull($m->getOptionalMessage()); + } + + public function testLegacyTypehintWithNestedMessages() + { + $this->legacyMessage(new TestLegacyMessage\NestedMessage); + } + + private function legacyMessage(TestLegacyMessage_NestedMessage $sub) + { + // If we made it here without a PHP Fatal error, the typehint worked + $this->assertTrue(true); + } + + ######################################################### + # Test repeated field. + ######################################################### + + public function testRepeatedField() + { + $m = new TestMessage(); + + $repeated_int32 = new RepeatedField(GPBType::INT32); + $m->setRepeatedInt32($repeated_int32); + $this->assertSame($repeated_int32, $m->getRepeatedInt32()); + } + + public function testRepeatedFieldViaArray() + { + $m = new TestMessage(); + + $arr = array(); + $m->setRepeatedInt32($arr); + $this->assertSame(0, count($m->getRepeatedInt32())); + + $arr = array(1, 2.1, "3"); + $m->setRepeatedInt32($arr); + $this->assertTrue($m->getRepeatedInt32() instanceof RepeatedField); + $this->assertSame("Google\Protobuf\Internal\RepeatedField", + get_class($m->getRepeatedInt32())); + $this->assertSame(3, count($m->getRepeatedInt32())); + $this->assertSame(1, $m->getRepeatedInt32()[0]); + $this->assertSame(2, $m->getRepeatedInt32()[1]); + $this->assertSame(3, $m->getRepeatedInt32()[2]); + $this->assertFalse($arr instanceof RepeatedField); + } + + ######################################################### + # Test map field. + ######################################################### + + public function testMapField() + { + $m = new TestMessage(); + + $map_int32_int32 = new MapField(GPBType::INT32, GPBType::INT32); + $m->setMapInt32Int32($map_int32_int32); + $this->assertSame($map_int32_int32, $m->getMapInt32Int32()); + } + + public function testMapFieldViaArray() + { + $m = new TestMessage(); + + $dict = array(); + $m->setMapInt32Int32($dict); + $this->assertSame(0, count($m->getMapInt32Int32())); + + $dict = array(5 => 5, 6.1 => 6.1, "7" => "7"); + $m->setMapInt32Int32($dict); + $this->assertTrue($m->getMapInt32Int32() instanceof MapField); + $this->assertSame(3, count($m->getMapInt32Int32())); + $this->assertSame(5, $m->getMapInt32Int32()[5]); + $this->assertSame(6, $m->getMapInt32Int32()[6]); + $this->assertSame(7, $m->getMapInt32Int32()[7]); + $this->assertFalse($dict instanceof MapField); + } + + ######################################################### + # Test oneof field. + ######################################################### + + public function testOneofField() { + $m = new TestMessage(); + + $this->assertSame("", $m->getMyOneof()); + + $m->setOneofInt32(1); + $this->assertSame(1, $m->getOneofInt32()); + $this->assertSame(0.0, $m->getOneofFloat()); + $this->assertSame('', $m->getOneofString()); + $this->assertSame(NULL, $m->getOneofMessage()); + $this->assertSame("oneof_int32", $m->getMyOneof()); + + $m->setOneofFloat(2.0); + $this->assertSame(0, $m->getOneofInt32()); + $this->assertSame(2.0, $m->getOneofFloat()); + $this->assertSame('', $m->getOneofString()); + $this->assertSame(NULL, $m->getOneofMessage()); + $this->assertSame("oneof_float", $m->getMyOneof()); + + $m->setOneofString('abc'); + $this->assertSame(0, $m->getOneofInt32()); + $this->assertSame(0.0, $m->getOneofFloat()); + $this->assertSame('abc', $m->getOneofString()); + $this->assertSame(NULL, $m->getOneofMessage()); + $this->assertSame("oneof_string", $m->getMyOneof()); + + $sub_m = new Sub(); + $sub_m->setA(1); + $m->setOneofMessage($sub_m); + $this->assertSame(0, $m->getOneofInt32()); + $this->assertSame(0.0, $m->getOneofFloat()); + $this->assertSame('', $m->getOneofString()); + $this->assertSame(1, $m->getOneofMessage()->getA()); + $this->assertSame("oneof_message", $m->getMyOneof()); + } + + ######################################################### + # Test clear method. + ######################################################### + + public function testMessageClear() + { + $m = new TestMessage(); + $this->setFields($m); + $this->expectFields($m); + $m->clear(); + $this->expectEmptyFields($m); + } + + ######################################################### + # Test mergeFrom method. + ######################################################### + + public function testMessageMergeFrom() + { + $m = new TestMessage(); + $this->setFields($m); + $this->expectFields($m); + $arr = $m->getOptionalMessage()->getB(); + $arr[] = 1; + + $n = new TestMessage(); + + // Singular + $n->setOptionalInt32(100); + $sub1 = new Sub(); + $sub1->setA(101); + + $b = $sub1->getB(); + $b[] = 102; + $sub1->setB($b); + + $n->setOptionalMessage($sub1); + + // Repeated + $repeatedInt32 = $n->getRepeatedInt32(); + $repeatedInt32[] = 200; + $n->setRepeatedInt32($repeatedInt32); + + $repeatedString = $n->getRepeatedString(); + $repeatedString[] = 'abc'; + $n->setRepeatedString($repeatedString); + + $sub2 = new Sub(); + $sub2->setA(201); + $repeatedMessage = $n->getRepeatedMessage(); + $repeatedMessage[] = $sub2; + $n->setRepeatedMessage($repeatedMessage); + + // Map + $mapInt32Int32 = $n->getMapInt32Int32(); + $mapInt32Int32[1] = 300; + $mapInt32Int32[-62] = 301; + $n->setMapInt32Int32($mapInt32Int32); + + $mapStringString = $n->getMapStringString(); + $mapStringString['def'] = 'def'; + $n->setMapStringString($mapStringString); + + $mapInt32Message = $n->getMapInt32Message(); + $mapInt32Message[1] = new Sub(); + $mapInt32Message[1]->setA(302); + $mapInt32Message[2] = new Sub(); + $mapInt32Message[2]->setA(303); + $n->setMapInt32Message($mapInt32Message); + + $m->mergeFrom($n); + + $this->assertSame(100, $m->getOptionalInt32()); + $this->assertSame(42, $m->getOptionalUint32()); + $this->assertSame(101, $m->getOptionalMessage()->getA()); + $this->assertSame(2, count($m->getOptionalMessage()->getB())); + $this->assertSame(1, $m->getOptionalMessage()->getB()[0]); + $this->assertSame(102, $m->getOptionalMessage()->getB()[1]); + + $this->assertSame(3, count($m->getRepeatedInt32())); + $this->assertSame(200, $m->getRepeatedInt32()[2]); + $this->assertSame(2, count($m->getRepeatedUint32())); + $this->assertSame(3, count($m->getRepeatedString())); + $this->assertSame('abc', $m->getRepeatedString()[2]); + $this->assertSame(3, count($m->getRepeatedMessage())); + $this->assertSame(201, $m->getRepeatedMessage()[2]->getA()); + + $this->assertSame(2, count($m->getMapInt32Int32())); + $this->assertSame(300, $m->getMapInt32Int32()[1]); + $this->assertSame(301, $m->getMapInt32Int32()[-62]); + $this->assertSame(1, count($m->getMapUint32Uint32())); + $this->assertSame(2, count($m->getMapStringString())); + $this->assertSame('def', $m->getMapStringString()['def']); + + $this->assertSame(2, count($m->getMapInt32Message())); + $this->assertSame(302, $m->getMapInt32Message()[1]->getA()); + $this->assertSame(303, $m->getMapInt32Message()[2]->getA()); + + $this->assertSame("", $m->getMyOneof()); + + // Check sub-messages are copied by value. + $n->getOptionalMessage()->setA(-101); + $this->assertSame(101, $m->getOptionalMessage()->getA()); + + $repeatedMessage = $n->getRepeatedMessage(); + $repeatedMessage[0]->setA(-201); + $n->setRepeatedMessage($repeatedMessage); + $this->assertSame(201, $m->getRepeatedMessage()[2]->getA()); + + $mapInt32Message = $n->getMapInt32Message(); + $mapInt32Message[1]->setA(-302); + $n->setMapInt32Message($mapInt32Message); + + $this->assertSame(302, $m->getMapInt32Message()[1]->getA()); + + // Test merge oneof. + $m = new TestMessage(); + + $n = new TestMessage(); + $n->setOneofInt32(1); + $m->mergeFrom($n); + $this->assertSame(1, $m->getOneofInt32()); + + $sub = new Sub(); + $n->setOneofMessage($sub); + $n->getOneofMessage()->setA(400); + $m->mergeFrom($n); + $this->assertSame(400, $m->getOneofMessage()->getA()); + $n->getOneofMessage()->setA(-400); + $this->assertSame(400, $m->getOneofMessage()->getA()); + + // Test all fields + $m = new TestMessage(); + $n = new TestMessage(); + $this->setFields($m); + $n->mergeFrom($m); + $this->expectFields($n); + } + + ######################################################### + # Test message/enum without namespace. + ######################################################### + + public function testMessageWithoutNamespace() + { + $m = new TestMessage(); + $n = new NoNameSpaceMessage(); + $m->setOptionalNoNamespaceMessage($n); + $repeatedNoNamespaceMessage = $m->getRepeatedNoNamespaceMessage(); + $repeatedNoNamespaceMessage[] = new NoNameSpaceMessage(); + $m->setRepeatedNoNamespaceMessage($repeatedNoNamespaceMessage); + + // test nested messages + $sub = new NoNamespaceMessage\NestedMessage(); + $n->setNestedMessage($sub); + + $this->assertTrue(true); + } + + public function testEnumWithoutNamespace() + { + $m = new TestMessage(); + $m->setOptionalNoNamespaceEnum(NoNameSpaceEnum::VALUE_A); + $repeatedNoNamespaceEnum = $m->getRepeatedNoNamespaceEnum(); + $repeatedNoNamespaceEnum[] = NoNameSpaceEnum::VALUE_A; + $m->setRepeatedNoNamespaceEnum($repeatedNoNamespaceEnum); + $this->assertTrue(true); + } + + ######################################################### + # Test message with given namespace. + ######################################################### + + public function testNestedMessagesAndEnums() + { + $m = new TestMessage(); + $n = new TestMessage\Sub(); + $m->setOptionalMessage($n); + $m->setOptionalNestedEnum(TestMessage\NestedEnum::ZERO); + $this->assertSame($n, $m->getOptionalMessage()); + $this->assertSame(TestMessage\NestedEnum::ZERO, $m->getOptionalNestedEnum()); + } + + public function testMessagesAndEnumsWithPrefix() + { + // Test message prefix + $m = new TestIncludePrefixMessage(); + $n = new PrefixTestPrefix(); + $n->setA(1); + $m->setPrefixMessage($n); + $this->assertSame(1, $m->getPrefixMessage()->getA()); + + // Test nested message prefix + $o = new PrefixTestPrefix(); + $p = new PrefixTestPrefix\PrefixNestedMessage(); + $o->setNestedMessage($p); + $o->setNestedEnum(PrefixTestPrefix\PrefixNestedEnum::ZERO); + $this->assertSame($p, $o->getNestedMessage()); + $this->assertSame(PrefixTestPrefix\PrefixNestedEnum::ZERO, $o->getNestedEnum()); + } + + public function testMessagesAndEnumsWithPhpNamespace() + { + $m = new TestNamespace(); + $n = new TestNamespace\NestedMessage(); + $m->setNestedMessage($n); + $m->setNestedEnum(TestNamespace\NestedEnum::ZERO); + $this->assertSame($n, $m->getNestedMessage()); + $this->assertSame(TestNamespace\NestedEnum::ZERO, $m->getNestedEnum()); + } + + public function testMesssagesAndEnumsWithEmptyPhpNamespace() + { + $m = new TestEmptyNamespace(); + $n = new TestEmptyNamespace\NestedMessage(); + $m->setNestedMessage($n); + $m->setNestedEnum(TestEmptyNamespace\NestedEnum::ZERO); + $this->assertSame($n, $m->getNestedMessage()); + $this->assertSame(TestEmptyNamespace\NestedEnum::ZERO, $m->getNestedEnum()); + } + + public function testMessagesAndEnumsWithNoNamespace() + { + $m = new NoNamespaceMessage(); + $n = new NoNamespaceMessage\NestedMessage(); + $m->setNestedMessage($n); + $m->setNestedEnum(NoNamespaceMessage\NestedEnum::ZERO); + $this->assertSame($n, $m->getNestedMessage()); + $this->assertSame(NoNamespaceMessage\NestedEnum::ZERO, $m->getNestedEnum()); + } + + public function testReservedWordsInPackageName() + { + $m = new TestEmptyPackage(); + $n = new TestEmptyPackage\NestedMessage(); + $m->setNestedMessage($n); + $m->setNestedEnum(TestEmptyPackage\NestedEnum::ZERO); + $this->assertSame($n, $m->getNestedMessage()); + $this->assertSame(TestEmptyPackage\NestedEnum::ZERO, $m->getNestedEnum()); + } + + public function testReservedWordsInNamespace() + { + $m = new TestNamespace(); + $n = new TestNamespace\PBEmpty(); + $o = new TestNamespace\PBEmpty\NestedMessage(); + $n->setNestedMessage($o); + $n->setNestedEnum(TestNamespace\PBEmpty\NestedEnum::ZERO); + $m->setReservedName($n); + $this->assertSame($n, $m->getReservedName()); + $this->assertSame($o, $n->getNestedMessage()); + $this->assertSame( + TestNamespace\PBEmpty\NestedEnum::ZERO, + $n->getNestedEnum() + ); + } + + ######################################################### + # Test prefix for reserved words. + ######################################################### + + public function testPrefixForReservedWords() + { + $m = new \Foo\TestMessage\PBEmpty(); + $m = new \Foo\PBEmpty(); + $m = new \PrefixEmpty(); + $m = new \Foo\PBARRAY(); + + $m = new \Lower\PBabstract(); + $m = new \Lower\PBand(); + $m = new \Lower\PBarray(); + $m = new \Lower\PBas(); + $m = new \Lower\PBbreak(); + $m = new \Lower\PBcallable(); + $m = new \Lower\PBcase(); + $m = new \Lower\PBcatch(); + $m = new \Lower\PBclass(); + $m = new \Lower\PBclone(); + $m = new \Lower\PBconst(); + $m = new \Lower\PBcontinue(); + $m = new \Lower\PBdeclare(); + $m = new \Lower\PBdefault(); + $m = new \Lower\PBdie(); + $m = new \Lower\PBdo(); + $m = new \Lower\PBecho(); + $m = new \Lower\PBelse(); + $m = new \Lower\PBelseif(); + $m = new \Lower\PBempty(); + $m = new \Lower\PBenddeclare(); + $m = new \Lower\PBendfor(); + $m = new \Lower\PBendforeach(); + $m = new \Lower\PBendif(); + $m = new \Lower\PBendswitch(); + $m = new \Lower\PBendwhile(); + $m = new \Lower\PBeval(); + $m = new \Lower\PBexit(); + $m = new \Lower\PBextends(); + $m = new \Lower\PBfinal(); + $m = new \Lower\PBfor(); + $m = new \Lower\PBforeach(); + $m = new \Lower\PBfunction(); + $m = new \Lower\PBglobal(); + $m = new \Lower\PBgoto(); + $m = new \Lower\PBif(); + $m = new \Lower\PBimplements(); + $m = new \Lower\PBinclude(); + $m = new \Lower\PBinclude_once(); + $m = new \Lower\PBinstanceof(); + $m = new \Lower\PBinsteadof(); + $m = new \Lower\PBinterface(); + $m = new \Lower\PBisset(); + $m = new \Lower\PBlist(); + $m = new \Lower\PBnamespace(); + $m = new \Lower\PBnew(); + $m = new \Lower\PBor(); + $m = new \Lower\PBprint(); + $m = new \Lower\PBprivate(); + $m = new \Lower\PBprotected(); + $m = new \Lower\PBpublic(); + $m = new \Lower\PBrequire(); + $m = new \Lower\PBrequire_once(); + $m = new \Lower\PBreturn(); + $m = new \Lower\PBstatic(); + $m = new \Lower\PBswitch(); + $m = new \Lower\PBthrow(); + $m = new \Lower\PBtrait(); + $m = new \Lower\PBtry(); + $m = new \Lower\PBunset(); + $m = new \Lower\PBuse(); + $m = new \Lower\PBvar(); + $m = new \Lower\PBwhile(); + $m = new \Lower\PBxor(); + $m = new \Lower\PBint(); + $m = new \Lower\PBfloat(); + $m = new \Lower\PBbool(); + $m = new \Lower\PBstring(); + $m = new \Lower\PBtrue(); + $m = new \Lower\PBfalse(); + $m = new \Lower\PBnull(); + $m = new \Lower\PBvoid(); + $m = new \Lower\PBiterable(); + + $m = new \Upper\PBABSTRACT(); + $m = new \Upper\PBAND(); + $m = new \Upper\PBARRAY(); + $m = new \Upper\PBAS(); + $m = new \Upper\PBBREAK(); + $m = new \Upper\PBCALLABLE(); + $m = new \Upper\PBCASE(); + $m = new \Upper\PBCATCH(); + $m = new \Upper\PBCLASS(); + $m = new \Upper\PBCLONE(); + $m = new \Upper\PBCONST(); + $m = new \Upper\PBCONTINUE(); + $m = new \Upper\PBDECLARE(); + $m = new \Upper\PBDEFAULT(); + $m = new \Upper\PBDIE(); + $m = new \Upper\PBDO(); + $m = new \Upper\PBECHO(); + $m = new \Upper\PBELSE(); + $m = new \Upper\PBELSEIF(); + $m = new \Upper\PBEMPTY(); + $m = new \Upper\PBENDDECLARE(); + $m = new \Upper\PBENDFOR(); + $m = new \Upper\PBENDFOREACH(); + $m = new \Upper\PBENDIF(); + $m = new \Upper\PBENDSWITCH(); + $m = new \Upper\PBENDWHILE(); + $m = new \Upper\PBEVAL(); + $m = new \Upper\PBEXIT(); + $m = new \Upper\PBEXTENDS(); + $m = new \Upper\PBFINAL(); + $m = new \Upper\PBFOR(); + $m = new \Upper\PBFOREACH(); + $m = new \Upper\PBFUNCTION(); + $m = new \Upper\PBGLOBAL(); + $m = new \Upper\PBGOTO(); + $m = new \Upper\PBIF(); + $m = new \Upper\PBIMPLEMENTS(); + $m = new \Upper\PBINCLUDE(); + $m = new \Upper\PBINCLUDE_ONCE(); + $m = new \Upper\PBINSTANCEOF(); + $m = new \Upper\PBINSTEADOF(); + $m = new \Upper\PBINTERFACE(); + $m = new \Upper\PBISSET(); + $m = new \Upper\PBLIST(); + $m = new \Upper\PBNAMESPACE(); + $m = new \Upper\PBNEW(); + $m = new \Upper\PBOR(); + $m = new \Upper\PBPRINT(); + $m = new \Upper\PBPRIVATE(); + $m = new \Upper\PBPROTECTED(); + $m = new \Upper\PBPUBLIC(); + $m = new \Upper\PBREQUIRE(); + $m = new \Upper\PBREQUIRE_ONCE(); + $m = new \Upper\PBRETURN(); + $m = new \Upper\PBSTATIC(); + $m = new \Upper\PBSWITCH(); + $m = new \Upper\PBTHROW(); + $m = new \Upper\PBTRAIT(); + $m = new \Upper\PBTRY(); + $m = new \Upper\PBUNSET(); + $m = new \Upper\PBUSE(); + $m = new \Upper\PBVAR(); + $m = new \Upper\PBWHILE(); + $m = new \Upper\PBXOR(); + $m = new \Upper\PBINT(); + $m = new \Upper\PBFLOAT(); + $m = new \Upper\PBBOOL(); + $m = new \Upper\PBSTRING(); + $m = new \Upper\PBTRUE(); + $m = new \Upper\PBFALSE(); + $m = new \Upper\PBNULL(); + $m = new \Upper\PBVOID(); + $m = new \Upper\PBITERABLE(); + + $m = new \Lower_enum\PBabstract(); + $m = new \Lower_enum\PBand(); + $m = new \Lower_enum\PBarray(); + $m = new \Lower_enum\PBas(); + $m = new \Lower_enum\PBbreak(); + $m = new \Lower_enum\PBcallable(); + $m = new \Lower_enum\PBcase(); + $m = new \Lower_enum\PBcatch(); + $m = new \Lower_enum\PBclass(); + $m = new \Lower_enum\PBclone(); + $m = new \Lower_enum\PBconst(); + $m = new \Lower_enum\PBcontinue(); + $m = new \Lower_enum\PBdeclare(); + $m = new \Lower_enum\PBdefault(); + $m = new \Lower_enum\PBdie(); + $m = new \Lower_enum\PBdo(); + $m = new \Lower_enum\PBecho(); + $m = new \Lower_enum\PBelse(); + $m = new \Lower_enum\PBelseif(); + $m = new \Lower_enum\PBempty(); + $m = new \Lower_enum\PBenddeclare(); + $m = new \Lower_enum\PBendfor(); + $m = new \Lower_enum\PBendforeach(); + $m = new \Lower_enum\PBendif(); + $m = new \Lower_enum\PBendswitch(); + $m = new \Lower_enum\PBendwhile(); + $m = new \Lower_enum\PBeval(); + $m = new \Lower_enum\PBexit(); + $m = new \Lower_enum\PBextends(); + $m = new \Lower_enum\PBfinal(); + $m = new \Lower_enum\PBfor(); + $m = new \Lower_enum\PBforeach(); + $m = new \Lower_enum\PBfunction(); + $m = new \Lower_enum\PBglobal(); + $m = new \Lower_enum\PBgoto(); + $m = new \Lower_enum\PBif(); + $m = new \Lower_enum\PBimplements(); + $m = new \Lower_enum\PBinclude(); + $m = new \Lower_enum\PBinclude_once(); + $m = new \Lower_enum\PBinstanceof(); + $m = new \Lower_enum\PBinsteadof(); + $m = new \Lower_enum\PBinterface(); + $m = new \Lower_enum\PBisset(); + $m = new \Lower_enum\PBlist(); + $m = new \Lower_enum\PBnamespace(); + $m = new \Lower_enum\PBnew(); + $m = new \Lower_enum\PBor(); + $m = new \Lower_enum\PBprint(); + $m = new \Lower_enum\PBprivate(); + $m = new \Lower_enum\PBprotected(); + $m = new \Lower_enum\PBpublic(); + $m = new \Lower_enum\PBrequire(); + $m = new \Lower_enum\PBrequire_once(); + $m = new \Lower_enum\PBreturn(); + $m = new \Lower_enum\PBstatic(); + $m = new \Lower_enum\PBswitch(); + $m = new \Lower_enum\PBthrow(); + $m = new \Lower_enum\PBtrait(); + $m = new \Lower_enum\PBtry(); + $m = new \Lower_enum\PBunset(); + $m = new \Lower_enum\PBuse(); + $m = new \Lower_enum\PBvar(); + $m = new \Lower_enum\PBwhile(); + $m = new \Lower_enum\PBxor(); + $m = new \Lower_enum\PBint(); + $m = new \Lower_enum\PBfloat(); + $m = new \Lower_enum\PBbool(); + $m = new \Lower_enum\PBstring(); + $m = new \Lower_enum\PBtrue(); + $m = new \Lower_enum\PBfalse(); + $m = new \Lower_enum\PBnull(); + $m = new \Lower_enum\PBvoid(); + $m = new \Lower_enum\PBiterable(); + + $m = new \Upper_enum\PBABSTRACT(); + $m = new \Upper_enum\PBAND(); + $m = new \Upper_enum\PBARRAY(); + $m = new \Upper_enum\PBAS(); + $m = new \Upper_enum\PBBREAK(); + $m = new \Upper_enum\PBCALLABLE(); + $m = new \Upper_enum\PBCASE(); + $m = new \Upper_enum\PBCATCH(); + $m = new \Upper_enum\PBCLASS(); + $m = new \Upper_enum\PBCLONE(); + $m = new \Upper_enum\PBCONST(); + $m = new \Upper_enum\PBCONTINUE(); + $m = new \Upper_enum\PBDECLARE(); + $m = new \Upper_enum\PBDEFAULT(); + $m = new \Upper_enum\PBDIE(); + $m = new \Upper_enum\PBDO(); + $m = new \Upper_enum\PBECHO(); + $m = new \Upper_enum\PBELSE(); + $m = new \Upper_enum\PBELSEIF(); + $m = new \Upper_enum\PBEMPTY(); + $m = new \Upper_enum\PBENDDECLARE(); + $m = new \Upper_enum\PBENDFOR(); + $m = new \Upper_enum\PBENDFOREACH(); + $m = new \Upper_enum\PBENDIF(); + $m = new \Upper_enum\PBENDSWITCH(); + $m = new \Upper_enum\PBENDWHILE(); + $m = new \Upper_enum\PBEVAL(); + $m = new \Upper_enum\PBEXIT(); + $m = new \Upper_enum\PBEXTENDS(); + $m = new \Upper_enum\PBFINAL(); + $m = new \Upper_enum\PBFOR(); + $m = new \Upper_enum\PBFOREACH(); + $m = new \Upper_enum\PBFUNCTION(); + $m = new \Upper_enum\PBGLOBAL(); + $m = new \Upper_enum\PBGOTO(); + $m = new \Upper_enum\PBIF(); + $m = new \Upper_enum\PBIMPLEMENTS(); + $m = new \Upper_enum\PBINCLUDE(); + $m = new \Upper_enum\PBINCLUDE_ONCE(); + $m = new \Upper_enum\PBINSTANCEOF(); + $m = new \Upper_enum\PBINSTEADOF(); + $m = new \Upper_enum\PBINTERFACE(); + $m = new \Upper_enum\PBISSET(); + $m = new \Upper_enum\PBLIST(); + $m = new \Upper_enum\PBNAMESPACE(); + $m = new \Upper_enum\PBNEW(); + $m = new \Upper_enum\PBOR(); + $m = new \Upper_enum\PBPRINT(); + $m = new \Upper_enum\PBPRIVATE(); + $m = new \Upper_enum\PBPROTECTED(); + $m = new \Upper_enum\PBPUBLIC(); + $m = new \Upper_enum\PBREQUIRE(); + $m = new \Upper_enum\PBREQUIRE_ONCE(); + $m = new \Upper_enum\PBRETURN(); + $m = new \Upper_enum\PBSTATIC(); + $m = new \Upper_enum\PBSWITCH(); + $m = new \Upper_enum\PBTHROW(); + $m = new \Upper_enum\PBTRAIT(); + $m = new \Upper_enum\PBTRY(); + $m = new \Upper_enum\PBUNSET(); + $m = new \Upper_enum\PBUSE(); + $m = new \Upper_enum\PBVAR(); + $m = new \Upper_enum\PBWHILE(); + $m = new \Upper_enum\PBXOR(); + $m = new \Upper_enum\PBINT(); + $m = new \Upper_enum\PBFLOAT(); + $m = new \Upper_enum\PBBOOL(); + $m = new \Upper_enum\PBSTRING(); + $m = new \Upper_enum\PBTRUE(); + $m = new \Upper_enum\PBFALSE(); + $m = new \Upper_enum\PBNULL(); + $m = new \Upper_enum\PBVOID(); + $m = new \Upper_enum\PBITERABLE(); + + $m = \Lower_enum_value\NotAllowed::PBabstract; + $m = \Lower_enum_value\NotAllowed::PBand; + $m = \Lower_enum_value\NotAllowed::PBarray; + $m = \Lower_enum_value\NotAllowed::PBas; + $m = \Lower_enum_value\NotAllowed::PBbreak; + $m = \Lower_enum_value\NotAllowed::PBcallable; + $m = \Lower_enum_value\NotAllowed::PBcase; + $m = \Lower_enum_value\NotAllowed::PBcatch; + $m = \Lower_enum_value\NotAllowed::PBclass; + $m = \Lower_enum_value\NotAllowed::PBclone; + $m = \Lower_enum_value\NotAllowed::PBconst; + $m = \Lower_enum_value\NotAllowed::PBcontinue; + $m = \Lower_enum_value\NotAllowed::PBdeclare; + $m = \Lower_enum_value\NotAllowed::PBdefault; + $m = \Lower_enum_value\NotAllowed::PBdie; + $m = \Lower_enum_value\NotAllowed::PBdo; + $m = \Lower_enum_value\NotAllowed::PBecho; + $m = \Lower_enum_value\NotAllowed::PBelse; + $m = \Lower_enum_value\NotAllowed::PBelseif; + $m = \Lower_enum_value\NotAllowed::PBempty; + $m = \Lower_enum_value\NotAllowed::PBenddeclare; + $m = \Lower_enum_value\NotAllowed::PBendfor; + $m = \Lower_enum_value\NotAllowed::PBendforeach; + $m = \Lower_enum_value\NotAllowed::PBendif; + $m = \Lower_enum_value\NotAllowed::PBendswitch; + $m = \Lower_enum_value\NotAllowed::PBendwhile; + $m = \Lower_enum_value\NotAllowed::PBeval; + $m = \Lower_enum_value\NotAllowed::PBexit; + $m = \Lower_enum_value\NotAllowed::PBextends; + $m = \Lower_enum_value\NotAllowed::PBfinal; + $m = \Lower_enum_value\NotAllowed::PBfor; + $m = \Lower_enum_value\NotAllowed::PBforeach; + $m = \Lower_enum_value\NotAllowed::PBfunction; + $m = \Lower_enum_value\NotAllowed::PBglobal; + $m = \Lower_enum_value\NotAllowed::PBgoto; + $m = \Lower_enum_value\NotAllowed::PBif; + $m = \Lower_enum_value\NotAllowed::PBimplements; + $m = \Lower_enum_value\NotAllowed::PBinclude; + $m = \Lower_enum_value\NotAllowed::PBinclude_once; + $m = \Lower_enum_value\NotAllowed::PBinstanceof; + $m = \Lower_enum_value\NotAllowed::PBinsteadof; + $m = \Lower_enum_value\NotAllowed::PBinterface; + $m = \Lower_enum_value\NotAllowed::PBisset; + $m = \Lower_enum_value\NotAllowed::PBlist; + $m = \Lower_enum_value\NotAllowed::PBnamespace; + $m = \Lower_enum_value\NotAllowed::PBnew; + $m = \Lower_enum_value\NotAllowed::PBor; + $m = \Lower_enum_value\NotAllowed::PBprint; + $m = \Lower_enum_value\NotAllowed::PBprivate; + $m = \Lower_enum_value\NotAllowed::PBprotected; + $m = \Lower_enum_value\NotAllowed::PBpublic; + $m = \Lower_enum_value\NotAllowed::PBrequire; + $m = \Lower_enum_value\NotAllowed::PBrequire_once; + $m = \Lower_enum_value\NotAllowed::PBreturn; + $m = \Lower_enum_value\NotAllowed::PBstatic; + $m = \Lower_enum_value\NotAllowed::PBswitch; + $m = \Lower_enum_value\NotAllowed::PBthrow; + $m = \Lower_enum_value\NotAllowed::PBtrait; + $m = \Lower_enum_value\NotAllowed::PBtry; + $m = \Lower_enum_value\NotAllowed::PBunset; + $m = \Lower_enum_value\NotAllowed::PBuse; + $m = \Lower_enum_value\NotAllowed::PBvar; + $m = \Lower_enum_value\NotAllowed::PBwhile; + $m = \Lower_enum_value\NotAllowed::PBxor; + $m = \Lower_enum_value\NotAllowed::int; + $m = \Lower_enum_value\NotAllowed::float; + $m = \Lower_enum_value\NotAllowed::bool; + $m = \Lower_enum_value\NotAllowed::string; + $m = \Lower_enum_value\NotAllowed::true; + $m = \Lower_enum_value\NotAllowed::false; + $m = \Lower_enum_value\NotAllowed::null; + $m = \Lower_enum_value\NotAllowed::void; + $m = \Lower_enum_value\NotAllowed::iterable; + + $m = \Upper_enum_value\NotAllowed::PBABSTRACT; + $m = \Upper_enum_value\NotAllowed::PBAND; + $m = \Upper_enum_value\NotAllowed::PBARRAY; + $m = \Upper_enum_value\NotAllowed::PBAS; + $m = \Upper_enum_value\NotAllowed::PBBREAK; + $m = \Upper_enum_value\NotAllowed::PBCALLABLE; + $m = \Upper_enum_value\NotAllowed::PBCASE; + $m = \Upper_enum_value\NotAllowed::PBCATCH; + $m = \Upper_enum_value\NotAllowed::PBCLASS; + $m = \Upper_enum_value\NotAllowed::PBCLONE; + $m = \Upper_enum_value\NotAllowed::PBCONST; + $m = \Upper_enum_value\NotAllowed::PBCONTINUE; + $m = \Upper_enum_value\NotAllowed::PBDECLARE; + $m = \Upper_enum_value\NotAllowed::PBDEFAULT; + $m = \Upper_enum_value\NotAllowed::PBDIE; + $m = \Upper_enum_value\NotAllowed::PBDO; + $m = \Upper_enum_value\NotAllowed::PBECHO; + $m = \Upper_enum_value\NotAllowed::PBELSE; + $m = \Upper_enum_value\NotAllowed::PBELSEIF; + $m = \Upper_enum_value\NotAllowed::PBEMPTY; + $m = \Upper_enum_value\NotAllowed::PBENDDECLARE; + $m = \Upper_enum_value\NotAllowed::PBENDFOR; + $m = \Upper_enum_value\NotAllowed::PBENDFOREACH; + $m = \Upper_enum_value\NotAllowed::PBENDIF; + $m = \Upper_enum_value\NotAllowed::PBENDSWITCH; + $m = \Upper_enum_value\NotAllowed::PBENDWHILE; + $m = \Upper_enum_value\NotAllowed::PBEVAL; + $m = \Upper_enum_value\NotAllowed::PBEXIT; + $m = \Upper_enum_value\NotAllowed::PBEXTENDS; + $m = \Upper_enum_value\NotAllowed::PBFINAL; + $m = \Upper_enum_value\NotAllowed::PBFOR; + $m = \Upper_enum_value\NotAllowed::PBFOREACH; + $m = \Upper_enum_value\NotAllowed::PBFUNCTION; + $m = \Upper_enum_value\NotAllowed::PBGLOBAL; + $m = \Upper_enum_value\NotAllowed::PBGOTO; + $m = \Upper_enum_value\NotAllowed::PBIF; + $m = \Upper_enum_value\NotAllowed::PBIMPLEMENTS; + $m = \Upper_enum_value\NotAllowed::PBINCLUDE; + $m = \Upper_enum_value\NotAllowed::PBINCLUDE_ONCE; + $m = \Upper_enum_value\NotAllowed::PBINSTANCEOF; + $m = \Upper_enum_value\NotAllowed::PBINSTEADOF; + $m = \Upper_enum_value\NotAllowed::PBINTERFACE; + $m = \Upper_enum_value\NotAllowed::PBISSET; + $m = \Upper_enum_value\NotAllowed::PBLIST; + $m = \Upper_enum_value\NotAllowed::PBNAMESPACE; + $m = \Upper_enum_value\NotAllowed::PBNEW; + $m = \Upper_enum_value\NotAllowed::PBOR; + $m = \Upper_enum_value\NotAllowed::PBPRINT; + $m = \Upper_enum_value\NotAllowed::PBPRIVATE; + $m = \Upper_enum_value\NotAllowed::PBPROTECTED; + $m = \Upper_enum_value\NotAllowed::PBPUBLIC; + $m = \Upper_enum_value\NotAllowed::PBREQUIRE; + $m = \Upper_enum_value\NotAllowed::PBREQUIRE_ONCE; + $m = \Upper_enum_value\NotAllowed::PBRETURN; + $m = \Upper_enum_value\NotAllowed::PBSTATIC; + $m = \Upper_enum_value\NotAllowed::PBSWITCH; + $m = \Upper_enum_value\NotAllowed::PBTHROW; + $m = \Upper_enum_value\NotAllowed::PBTRAIT; + $m = \Upper_enum_value\NotAllowed::PBTRY; + $m = \Upper_enum_value\NotAllowed::PBUNSET; + $m = \Upper_enum_value\NotAllowed::PBUSE; + $m = \Upper_enum_value\NotAllowed::PBVAR; + $m = \Upper_enum_value\NotAllowed::PBWHILE; + $m = \Upper_enum_value\NotAllowed::PBXOR; + $m = \Upper_enum_value\NotAllowed::INT; + $m = \Upper_enum_value\NotAllowed::FLOAT; + $m = \Upper_enum_value\NotAllowed::BOOL; + $m = \Upper_enum_value\NotAllowed::STRING; + $m = \Upper_enum_value\NotAllowed::TRUE; + $m = \Upper_enum_value\NotAllowed::FALSE; + $m = \Upper_enum_value\NotAllowed::NULL; + $m = \Upper_enum_value\NotAllowed::VOID; + $m = \Upper_enum_value\NotAllowed::ITERABLE; + + $this->assertTrue(true); + } + + ######################################################### + # Test fluent setters. + ######################################################### + + public function testFluentSetters() + { + $m = (new TestMessage()) + ->setOptionalInt32(1) + ->setOptionalUInt32(2); + $this->assertSame(1, $m->getOptionalInt32()); + $this->assertSame(2, $m->getOptionalUInt32()); + } + + ######################################################### + # Test Reverse Field Order. + ######################################################### + + public function testReverseFieldOrder() + { + $m = new TestReverseFieldOrder(); + $m->setB("abc"); + $this->assertSame("abc", $m->getB()); + $this->assertNotSame("abc", $m->getA()); + } + + ######################################################### + # Test Reverse Field Order. + ######################################################### + + public function testLowerCase() + { + $m = new testLowerCaseMessage(); + $n = testLowerCaseEnum::VALUE; + $this->assertTrue(true); + } + + ######################################################### + # Test Array Constructor. + ######################################################### + + public function testArrayConstructor() + { + $m = new TestMessage([ + 'optional_int32' => -42, + 'optional_int64' => -43, + 'optional_uint32' => 42, + 'optional_uint64' => 43, + 'optional_sint32' => -44, + 'optional_sint64' => -45, + 'optional_fixed32' => 46, + 'optional_fixed64' => 47, + 'optional_sfixed32' => -46, + 'optional_sfixed64' => -47, + 'optional_float' => 1.5, + 'optional_double' => 1.6, + 'optional_bool' => true, + 'optional_string' => 'a', + 'optional_bytes' => 'bbbb', + 'optional_enum' => TestEnum::ONE, + 'optional_message' => new Sub([ + 'a' => 33 + ]), + 'repeated_int32' => [-42, -52], + 'repeated_int64' => [-43, -53], + 'repeated_uint32' => [42, 52], + 'repeated_uint64' => [43, 53], + 'repeated_sint32' => [-44, -54], + 'repeated_sint64' => [-45, -55], + 'repeated_fixed32' => [46, 56], + 'repeated_fixed64' => [47, 57], + 'repeated_sfixed32' => [-46, -56], + 'repeated_sfixed64' => [-47, -57], + 'repeated_float' => [1.5, 2.5], + 'repeated_double' => [1.6, 2.6], + 'repeated_bool' => [true, false], + 'repeated_string' => ['a', 'c'], + 'repeated_bytes' => ['bbbb', 'dddd'], + 'repeated_enum' => [TestEnum::ZERO, TestEnum::ONE], + 'repeated_message' => [new Sub(['a' => 34]), + new Sub(['a' => 35])], + 'map_int32_int32' => [-62 => -62], + 'map_int64_int64' => [-63 => -63], + 'map_uint32_uint32' => [62 => 62], + 'map_uint64_uint64' => [63 => 63], + 'map_sint32_sint32' => [-64 => -64], + 'map_sint64_sint64' => [-65 => -65], + 'map_fixed32_fixed32' => [66 => 66], + 'map_fixed64_fixed64' => [67 => 67], + 'map_sfixed32_sfixed32' => [-68 => -68], + 'map_sfixed64_sfixed64' => [-69 => -69], + 'map_int32_float' => [1 => 3.5], + 'map_int32_double' => [1 => 3.6], + 'map_bool_bool' => [true => true], + 'map_string_string' => ['e' => 'e'], + 'map_int32_bytes' => [1 => 'ffff'], + 'map_int32_enum' => [1 => TestEnum::ONE], + 'map_int32_message' => [1 => new Sub(['a' => 36])], + ]); + + TestUtil::assertTestMessage($m); + $this->assertTrue(true); + } + + public function testReferenceInArrayConstructor() + { + $keys = [[ + 'optional_bool' => true, + 'repeated_bool' => [true], + 'map_bool_bool' => [true => true], + 'optional_double' => 1.0, + 'repeated_double' => [1.0], + 'map_int32_double' => [1 => 1.0], + 'optional_int32' => 1, + 'repeated_int32' => [1], + 'map_int32_int32' => [1 => 1], + 'optional_string' => 'a', + 'repeated_string' => ['a'], + 'map_string_string' => ['a' => 'a'], + 'optional_message' => ['a' => 1], + 'repeated_message' => [['a' => 1]], + 'map_int32_message' => [1 => ['a' => 1]], + ]]; + + foreach ($keys as &$key) { + foreach ($key as $id => &$value) { + if ($id === 'repeated_bool') { + foreach ($value as &$element) { + } + } + if ($id === 'map_bool_bool') { + foreach ($value as $mapKey => &$element) { + } + } + if ($id === 'repeated_double') { + foreach ($value as &$element) { + } + } + if ($id === 'map_int32_double') { + foreach ($value as $mapKey => &$element) { + } + } + if ($id === 'repeated_int32') { + foreach ($value as &$element) { + } + } + if ($id === 'map_int32_int32') { + foreach ($value as $mapKey => &$element) { + } + } + if ($id === 'repeated_string') { + foreach ($value as &$element) { + } + } + if ($id === 'map_string_string') { + foreach ($value as $mapKey => &$element) { + } + } + if ($id === 'optional_message') { + $value = new Sub($value); + } + if ($id === 'repeated_message') { + foreach ($value as &$element) { + $element = new Sub($element); + } + } + if ($id === 'map_int32_message') { + foreach ($value as $mapKey => &$element) { + $element = new Sub($element); + } + } + } + $key = new TestMessage($key); + } + + $this->assertTrue(true); + } + + public function testOneofMessageInArrayConstructor() + { + $m = new TestMessage([ + 'oneof_message' => new Sub(), + ]); + $this->assertSame('oneof_message', $m->getMyOneof()); + $this->assertNotNull($m->getOneofMessage()); + + $this->assertTrue(true); + } + + public function testOneofStringInArrayConstructor() + { + $m = new TestMessage([ + 'oneof_string' => 'abc', + ]); + + $this->assertTrue(true); + } + + ######################################################### + # Test clone. + ######################################################### + + public function testClone() + { + $m = new TestMessage([ + 'optional_int32' => -42, + 'optional_int64' => -43, + 'optional_message' => new Sub([ + 'a' => 33 + ]), + 'map_int32_message' => [1 => new Sub(['a' => 36])], + ]); + $m2 = clone $m; + $this->assertEquals($m->getOptionalInt32(), $m2->getOptionalInt32()); + $this->assertEquals($m->getOptionalInt64(), $m2->getOptionalInt64()); + $this->assertSame($m->getOptionalMessage(), $m2->getOptionalMessage()); + $this->assertSame($m->getMapInt32Message()[1], $m2->getMapInt32Message()[1]); + $this->assertEquals($m->serializeToJsonString(), $m2->serializeToJsonString()); + } + + ######################################################### + # Test message equals. + ######################################################### + + public function testMessageEquals() + { + $m = new TestMessage(); + TestUtil::setTestMessage($m); + $n = new TestMessage(); + TestUtil::setTestMessage($n); + $this->assertEquals($m, $n); + } + + ######################################################### + # Test reference of value + ######################################################### + + public function testValueIsReference() + { + // Bool element + $values = [true]; + array_walk($values, function (&$value) {}); + $m = new TestMessage(); + $m->setOptionalBool($values[0]); + + // Int32 element + $values = [1]; + array_walk($values, function (&$value) {}); + $m = new TestMessage(); + $m->setOptionalInt32($values[0]); + + // Double element + $values = [1.0]; + array_walk($values, function (&$value) {}); + $m = new TestMessage(); + $m->setOptionalDouble($values[0]); + + // String element + $values = ['a']; + array_walk($values, function (&$value) {}); + $m = new TestMessage(); + $m->setOptionalString($values[0]); + + $this->assertTrue(true); + } + + ######################################################### + # Test equality + ######################################################### + + public function testShallowEquality() + { + $m1 = new TestMessage([ + 'optional_int32' => -42, + 'optional_int64' => -43, + 'optional_uint32' => 42, + 'optional_uint64' => 43, + 'optional_sint32' => -44, + 'optional_sint64' => -45, + 'optional_fixed32' => 46, + 'optional_fixed64' => 47, + 'optional_sfixed32' => -46, + 'optional_sfixed64' => -47, + 'optional_float' => 1.5, + 'optional_double' => 1.6, + 'optional_bool' => true, + 'optional_string' => 'a', + 'optional_bytes' => 'bbbb', + 'optional_enum' => TestEnum::ONE, + ]); + $data = $m1->serializeToString(); + $m2 = new TestMessage(); + $m2->mergeFromString($data); + $this->assertTrue($m1 == $m2); + + $m1->setOptionalInt32(1234); + $this->assertTrue($m1 != $m2); + } + + public function testDeepEquality() + { + $m1 = new TestMessage([ + 'optional_int32' => -42, + 'optional_int64' => -43, + 'optional_uint32' => 42, + 'optional_uint64' => 43, + 'optional_sint32' => -44, + 'optional_sint64' => -45, + 'optional_fixed32' => 46, + 'optional_fixed64' => 47, + 'optional_sfixed32' => -46, + 'optional_sfixed64' => -47, + 'optional_float' => 1.5, + 'optional_double' => 1.6, + 'optional_bool' => true, + 'optional_string' => 'a', + 'optional_bytes' => 'bbbb', + 'optional_enum' => TestEnum::ONE, + 'optional_message' => new Sub([ + 'a' => 33 + ]), + 'repeated_int32' => [-42, -52], + 'repeated_int64' => [-43, -53], + 'repeated_uint32' => [42, 52], + 'repeated_uint64' => [43, 53], + 'repeated_sint32' => [-44, -54], + 'repeated_sint64' => [-45, -55], + 'repeated_fixed32' => [46, 56], + 'repeated_fixed64' => [47, 57], + 'repeated_sfixed32' => [-46, -56], + 'repeated_sfixed64' => [-47, -57], + 'repeated_float' => [1.5, 2.5], + 'repeated_double' => [1.6, 2.6], + 'repeated_bool' => [true, false], + 'repeated_string' => ['a', 'c'], + 'repeated_bytes' => ['bbbb', 'dddd'], + 'repeated_enum' => [TestEnum::ZERO, TestEnum::ONE], + 'repeated_message' => [new Sub(['a' => 34]), + new Sub(['a' => 35])], + 'map_int32_int32' => [-62 => -62], + 'map_int64_int64' => [-63 => -63], + 'map_uint32_uint32' => [62 => 62], + 'map_uint64_uint64' => [63 => 63], + 'map_sint32_sint32' => [-64 => -64], + 'map_sint64_sint64' => [-65 => -65], + 'map_fixed32_fixed32' => [66 => 66], + 'map_fixed64_fixed64' => [67 => 67], + 'map_sfixed32_sfixed32' => [-68 => -68], + 'map_sfixed64_sfixed64' => [-69 => -69], + 'map_int32_float' => [1 => 3.5], + 'map_int32_double' => [1 => 3.6], + 'map_bool_bool' => [true => true], + 'map_string_string' => ['e' => 'e'], + 'map_int32_bytes' => [1 => 'ffff'], + 'map_int32_enum' => [1 => TestEnum::ONE], + 'map_int32_message' => [1 => new Sub(['a' => 36])], + ]); + $data = $m1->serializeToString(); + + $m2 = new TestMessage(); + $m2->mergeFromString($data); + $this->assertTrue($m1 == $m2); + + # Nested sub-message is checked. + $m2 = new TestMessage(); + $m2->mergeFromString($data); + $m2->getOptionalMessage()->setA(1234); + $this->assertTrue($m1 != $m2); + + # Repeated field element is checked. + $m2 = new TestMessage(); + $m2->mergeFromString($data); + $m2->getRepeatedInt32()[0] = 1234; + $this->assertTrue($m1 != $m2); + + # Repeated field length is checked. + $m2 = new TestMessage(); + $m2->mergeFromString($data); + $m2->getRepeatedInt32()[] = 1234; + $this->assertTrue($m1 != $m2); + + # SubMessage inside repeated field is checked. + $m2 = new TestMessage(); + $m2->mergeFromString($data); + $m2->getRepeatedMessage()[0]->setA(1234); + $this->assertTrue($m1 != $m2); + + # Map value is checked. + $m2 = new TestMessage(); + $m2->mergeFromString($data); + $m2->getMapInt32Int32()[-62] = 1234; + $this->assertTrue($m1 != $m2); + + # Map size is checked. + $m2 = new TestMessage(); + $m2->mergeFromString($data); + $m2->getMapInt32Int32()[1234] = 1234; + $this->assertTrue($m1 != $m2); + + # SubMessage inside map field is checked. + $m2 = new TestMessage(); + $m2->mergeFromString($data); + $m2->getMapInt32Message()[1]->setA(1234); + $this->assertTrue($m1 != $m2); + + # TODO: what about unknown fields? + } + + ######################################################### + # Test hasOneof methods exists and working + ######################################################### + + public function testHasOneof() { + $m = new TestMessage(); + $this->assertFalse($m->hasOneofInt32()); + $m->setOneofInt32(42); + $this->assertTrue($m->hasOneofInt32()); + $m->setOneofString("bar"); + $this->assertFalse($m->hasOneofInt32()); + $this->assertTrue($m->hasOneofString()); + $m->clear(); + $this->assertFalse($m->hasOneofInt32()); + $this->assertFalse($m->hasOneofString()); + } + + ######################################################### + # Test that we don't crash if users create their own messages. + ######################################################### + + public function testUserDefinedClass() { + # This is not allowed, but at least we shouldn't crash. + $this->expectException(Exception::class); + $p = new C(); + } + + ######################################################### + # Test no segfault when error happens + ######################################################### + + function throwIntendedException() + { + throw new Exception('Intended'); + } + + public function testNoSegfaultWithError() + { + $this->expectException(Exception::class); + + new TestMessage(['optional_int32' => $this->throwIntendedException()]); + } + + public function testNoExceptionWithVarDump() + { + $m = new Sub(['a' => 1]); + /* + * This line currently segfaults on macOS with: + * + * frame #0: 0x00000001029936cc xdebug.so`xdebug_zend_hash_is_recursive + 4 + * frame #1: 0x00000001029a6736 xdebug.so`xdebug_var_export_text_ansi + 1006 + * frame #2: 0x00000001029a715d xdebug.so`xdebug_get_zval_value_text_ansi + 273 + * frame #3: 0x000000010298a441 xdebug.so`zif_xdebug_var_dump + 297 + * frame #4: 0x000000010298d558 xdebug.so`xdebug_execute_internal + 640 + * frame #5: 0x000000010046d47f php`ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER + 364 + * frame #6: 0x000000010043cabc php`execute_ex + 44 + * frame #7: 0x000000010298d151 xdebug.so`xdebug_execute_ex + 1662 + * frame #8: 0x000000010046d865 php`ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER + 426 + * + * The value we are passing to var_dump() appears to be corrupt somehow. + */ + /* var_dump($m); */ + + $this->assertTrue(true); + } +} diff --git a/php/tests/GeneratedPhpdocTest.php b/php/tests/GeneratedPhpdocTest.php new file mode 100644 index 0000000000000..18963a9b39cf2 --- /dev/null +++ b/php/tests/GeneratedPhpdocTest.php @@ -0,0 +1,352 @@ +getDocComment(); + $this->assertStringContains('foo.TestMessage', $doc); + } + + public function testPhpDocForConstructor() + { + $class = new ReflectionClass('Foo\TestMessage'); + $doc = $class->getMethod('__construct')->getDocComment(); + $this->assertStringContains('@param array $data', $doc); + $this->assertStringContains('@type int $optional_int32', $doc); + } + + /** + * @dataProvider providePhpDocForGettersAndSetters + */ + public function testPhpDocForIntGetters($methods, $expectedDoc) + { + $class = new ReflectionClass('Foo\TestMessage'); + foreach ($methods as $method) { + $doc = $class->getMethod($method)->getDocComment(); + $this->assertStringContains($expectedDoc, $doc); + } + } + + public function providePhpDocForGettersAndSetters() + { + return [ + [ + [ + 'setOptionalInt32', + 'setOptionalUint32', + 'setOptionalSint32', + 'setOptionalFixed32', + 'setOptionalSfixed32', + 'setOneofInt32', + 'setOneofUint32', + 'setOneofSint32', + 'setOneofFixed32', + 'setOneofSfixed32', + 'setOptionalEnum', + 'setOptionalNoNamespaceEnum', + 'setOptionalNestedEnum', + 'setOneofEnum' + ], + '@param int $var' + ], + [ + [ + 'setOptionalInt64', + 'setOptionalUint64', + 'setOptionalSint64', + 'setOptionalFixed64', + 'setOptionalSfixed64', + 'setOneofInt64', + 'setOneofUint64', + 'setOneofSint64', + 'setOneofFixed64', + 'setOneofSfixed64', + ], + '@param int|string $var' + ], + [ + [ + 'getOptionalInt32', + 'getOptionalUint32', + 'getOptionalSint32', + 'getOptionalFixed32', + 'getOptionalSfixed32', + 'getOneofInt32', + 'getOneofUint32', + 'getOneofSint32', + 'getOneofFixed32', + 'getOneofSfixed32', + 'getOptionalEnum', + 'getOptionalNoNamespaceEnum', + 'getOptionalNestedEnum', + 'getOneofEnum', + ], + '@return int' + ], + [ + [ + 'setOptionalInt64', + 'setOptionalUint64', + 'setOptionalSint64', + 'setOptionalFixed64', + 'setOptionalSfixed64', + 'setOneofInt64', + 'setOneofUint64', + 'setOneofSint64', + 'setOneofFixed64', + 'setOneofSfixed64', + ], + '@param int|string $var' + ], + [ + [ + 'getRepeatedInt32', + 'getRepeatedInt64', + 'getRepeatedUint32', + 'getRepeatedUint64', + 'getRepeatedSint32', + 'getRepeatedSint64', + 'getRepeatedFixed32', + 'getRepeatedFixed64', + 'getRepeatedSfixed32', + 'getRepeatedSfixed64', + 'getRepeatedFloat', + 'getRepeatedDouble', + 'getRepeatedBool', + 'getRepeatedString', + 'getRepeatedBytes', + 'getRepeatedEnum', + 'getRepeatedMessage', + 'getRepeatedRecursive', + 'getRepeatedNoNamespaceMessage', + 'getRepeatedNoNamespaceEnum', + ], + '@return \Google\Protobuf\Internal\RepeatedField' + ], + [ + [ + 'getMapInt32Int32', + 'getMapInt64Int64', + 'getMapUint32Uint32', + 'getMapUint64Uint64', + 'getMapSint32Sint32', + 'getMapSint64Sint64', + 'getMapFixed32Fixed32', + 'getMapFixed64Fixed64', + 'getMapSfixed32Sfixed32', + 'getMapSfixed64Sfixed64', + 'getMapInt32Float', + 'getMapInt32Double', + 'getMapBoolBool', + 'getMapStringString', + 'getMapInt32Bytes', + 'getMapInt32Enum', + 'getMapInt32Message', + 'getMapRecursive', + ], + '@return \Google\Protobuf\Internal\MapField' + ], + [ + [ + 'setRepeatedInt32', + 'setRepeatedUint32', + 'setRepeatedSint32', + 'setRepeatedFixed32', + 'setRepeatedSfixed32', + 'setRepeatedEnum', + 'setRepeatedNoNamespaceEnum', + ], + '@param int[]|\Google\Protobuf\Internal\RepeatedField $var' + ], + [ + [ + 'setRepeatedInt64', + 'setRepeatedUint64', + 'setRepeatedSint64', + 'setRepeatedFixed64', + 'setRepeatedSfixed64', + ], + '@param int[]|string[]|\Google\Protobuf\Internal\RepeatedField $var' + ], + [ + [ + 'setRepeatedFloat', + 'setRepeatedDouble', + ], + '@param float[]|\Google\Protobuf\Internal\RepeatedField $var' + ], + [ + [ + 'setRepeatedBool', + ], + '@param bool[]|\Google\Protobuf\Internal\RepeatedField $var' + ], + [ + [ + 'setRepeatedString', + 'setRepeatedBytes', + ], + '@param string[]|\Google\Protobuf\Internal\RepeatedField $var' + ], + [ + [ + 'setRepeatedMessage', + ], + '@param \Foo\TestMessage\Sub[]|\Google\Protobuf\Internal\RepeatedField $var' + ], + [ + [ + 'setRepeatedRecursive', + ], + '@param \Foo\TestMessage[]|\Google\Protobuf\Internal\RepeatedField $var' + ], + [ + [ + 'setRepeatedNoNamespaceMessage', + ], + '@param \NoNamespaceMessage[]|\Google\Protobuf\Internal\RepeatedField $var' + ], + [ + [ + 'setMapInt32Int32', + 'setMapInt64Int64', + 'setMapUint32Uint32', + 'setMapUint64Uint64', + 'setMapSint32Sint32', + 'setMapSint64Sint64', + 'setMapFixed32Fixed32', + 'setMapFixed64Fixed64', + 'setMapSfixed32Sfixed32', + 'setMapSfixed64Sfixed64', + 'setMapInt32Float', + 'setMapInt32Double', + 'setMapBoolBool', + 'setMapStringString', + 'setMapInt32Bytes', + 'setMapInt32Enum', + 'setMapInt32Message', + 'setMapRecursive', + ], + '@param array|\Google\Protobuf\Internal\MapField $var' + ], + [ + [ + 'getOptionalFloat', + 'getOptionalDouble', + 'getOneofDouble', + 'getOneofFloat', + ], + '@return float' + ], + [ + [ + 'setOptionalFloat', + 'setOptionalDouble', + 'setOneofDouble', + 'setOneofFloat', + ], + '@param float $var' + ], + [ + [ + 'getOptionalBool', + 'getOneofBool', + ], + '@return bool'], + [ + [ + 'setOptionalBool', + 'setOneofBool', + ], + '@param bool $var' + ], + [ + [ + 'getOptionalString', + 'getOptionalBytes', + 'getOneofString', + 'getOneofBytes', + 'getMyOneof', + ], + '@return string' + ], + [ + [ + 'setOptionalString', + 'setOptionalBytes', + 'setOneofString', + 'setOneofBytes', + ], + '@param string $var' + ], + + [ + [ + 'getOptionalMessage', + 'getOneofMessage' + ], + '@return \Foo\TestMessage\Sub' + ], + [ + [ + 'setOptionalMessage', + 'setOneofMessage' + ], + '@param \Foo\TestMessage\Sub $var' + ], + [ + [ + 'getOptionalIncludedMessage' + ], + '@return \Bar\TestInclude' + ], + [ + [ + 'setOptionalIncludedMessage' + ], + '@param \Bar\TestInclude $var' + ], + [ + [ + 'getRecursive' + ], + '@return \Foo\TestMessage' + ], + [ + [ + 'setRecursive' + ], + '@param \Foo\TestMessage $var' + ], + + [ + [ + 'getOptionalNoNamespaceMessage' + ], + '@return \NoNamespaceMessage' + ], + [ + [ + 'setOptionalNoNamespaceMessage' + ], + '@param \NoNamespaceMessage $var' + ], + [ + [ + 'setDeprecatedOptionalInt32', + 'getDeprecatedOptionalInt32', + ], + '@deprecated' + ], + ]; + } +} diff --git a/php/tests/GeneratedServiceTest.php b/php/tests/GeneratedServiceTest.php new file mode 100644 index 0000000000000..be9234c1ab0d2 --- /dev/null +++ b/php/tests/GeneratedServiceTest.php @@ -0,0 +1,127 @@ +serviceClass = new ReflectionClass('Foo\GreeterInterface'); + + $this->namespacedServiceClass = new ReflectionClass('Bar\OtherGreeterInterface'); + } + + public function testIsInterface() + { + $this->assertTrue($this->serviceClass->isInterface()); + } + + public function testPhpDocForClass() + { + $this->assertStringContains( + 'foo.Greeter', $this->serviceClass->getDocComment()); + } + + public function testPhpDocForNamespacedClass() + { + $this->assertStringContains( + 'foo.OtherGreeter', $this->namespacedServiceClass->getDocComment()); + } + + public function testServiceMethodsAreGenerated() + { + $this->assertCount( + count($this->methodNames), $this->serviceClass->getMethods()); + foreach ($this->methodNames as $methodName) { + $this->assertTrue($this->serviceClass->hasMethod($methodName)); + } + } + + public function testPhpDocForServiceMethod() + { + foreach ($this->methodNames as $methodName) { + $docComment = + $this->serviceClass->getMethod($methodName)->getDocComment(); + $this->assertStringContains($methodName, $docComment); + $this->assertStringContains( + '@param \Foo\HelloRequest $request', $docComment); + $this->assertStringContains( + '@return \Foo\HelloReply', $docComment); + } + } + + public function testPhpDocForServiceMethodInNamespacedClass() + { + foreach ($this->methodNames as $methodName) { + $docComment = + $this->namespacedServiceClass->getMethod( + $methodName)->getDocComment(); + $this->assertStringContains($methodName, $docComment); + $this->assertStringContains( + '@param \Foo\HelloRequest $request', $docComment); + $this->assertStringContains( + '@return \Foo\HelloReply', $docComment); + } + } + + public function testParamForServiceMethod() + { + foreach ($this->methodNames as $methodName) { + $method = $this->serviceClass->getMethod($methodName); + $this->assertCount(1, $method->getParameters()); + $param = $method->getParameters()[0]; + $this->assertFalse($param->isOptional()); + $this->assertSame('request', $param->getName()); + // ReflectionParameter::getType only exists in PHP 7+, so get the + // type from __toString + $this->assertStringContains( + 'Foo\HelloRequest $request', (string) $param); + } + } + + public function testParamForServiceMethodInNamespacedClass() + { + foreach ($this->methodNames as $methodName) { + $method = $this->serviceClass->getMethod($methodName); + $this->assertCount(1, $method->getParameters()); + $param = $method->getParameters()[0]; + $this->assertFalse($param->isOptional()); + $this->assertSame('request', $param->getName()); + // ReflectionParameter::getType only exists in PHP 7+, so get the + // type from __toString + $this->assertStringContains( + 'Foo\HelloRequest $request', (string) $param); + } + } +} diff --git a/php/tests/MapFieldTest.php b/php/tests/MapFieldTest.php new file mode 100644 index 0000000000000..2d8ae61c7bf41 --- /dev/null +++ b/php/tests/MapFieldTest.php @@ -0,0 +1,555 @@ +assertSame(MAX_INT32, $arr[MAX_INT32]); + $arr[MIN_INT32] = MIN_INT32; + $this->assertSame(MIN_INT32, $arr[MIN_INT32]); + $this->assertEquals(2, count($arr)); + $this->assertTrue(isset($arr[MAX_INT32])); + $this->assertTrue(isset($arr[MIN_INT32])); + unset($arr[MAX_INT32]); + unset($arr[MIN_INT32]); + $this->assertEquals(0, count($arr)); + + // Test float argument. + $arr[1.9] = 1.9; + $arr[2.1] = 2.1; + $this->assertSame(1, $arr[1]); + $this->assertSame(2, $arr[2]); + $arr[MAX_INT32_FLOAT] = MAX_INT32_FLOAT; + $this->assertSame(MAX_INT32, $arr[MAX_INT32]); + $arr[MIN_INT32_FLOAT] = MIN_INT32_FLOAT; + $this->assertSame(MIN_INT32, $arr[MIN_INT32]); + $this->assertEquals(4, count($arr)); + unset($arr[1.9]); + unset($arr[2.9]); + unset($arr[MAX_INT32_FLOAT]); + unset($arr[MIN_INT32_FLOAT]); + $this->assertEquals(0, count($arr)); + + // Test string argument. + $arr['2'] = '2'; + $this->assertSame(2, $arr[2]); + $arr['3.1'] = '3.1'; + $this->assertSame(3, $arr[3]); + $arr[MAX_INT32_STRING] = MAX_INT32_STRING; + $this->assertSame(MAX_INT32, $arr[MAX_INT32]); + $this->assertEquals(3, count($arr)); + unset($arr['2']); + unset($arr['3.1']); + unset($arr[MAX_INT32_STRING]); + $this->assertEquals(0, count($arr)); + + // Test foreach. + $arr = new MapField(GPBType::INT32, GPBType::INT32); + for ($i = 0; $i < 3; $i++) { + $arr[$i] = $i; + } + $i = 0; + $arr_test = []; + foreach ($arr as $key => $val) { + $this->assertSame($key, $val); + $arr_test[] = $key; + $i++; + } + $this->assertTrue(isset($arr_test[0])); + $this->assertTrue(isset($arr_test[1])); + $this->assertTrue(isset($arr_test[2])); + $this->assertSame(3, $i); + } + + ######################################################### + # Test uint32 field. + ######################################################### + + public function testUint32() { + $arr = new MapField(GPBType::UINT32, GPBType::UINT32); + + // Test integer argument. + $arr[MAX_UINT32] = MAX_UINT32; + $this->assertSame(-1, $arr[-1]); + $this->assertEquals(1, count($arr)); + unset($arr[MAX_UINT32]); + $this->assertEquals(0, count($arr)); + + $arr[-1] = -1; + $this->assertSame(-1, $arr[-1]); + $arr[MIN_UINT32] = MIN_UINT32; + $this->assertSame(MIN_UINT32, $arr[MIN_UINT32]); + $this->assertEquals(2, count($arr)); + unset($arr[-1]); + unset($arr[MIN_UINT32]); + $this->assertEquals(0, count($arr)); + + // Test float argument. + $arr[MAX_UINT32_FLOAT] = MAX_UINT32_FLOAT; + $this->assertSame(-1, $arr[-1]); + $this->assertEquals(1, count($arr)); + unset($arr[MAX_UINT32_FLOAT]); + $this->assertEquals(0, count($arr)); + + $arr[3.1] = 3.1; + $this->assertSame(3, $arr[3]); + $arr[-1.0] = -1.0; + $this->assertSame(-1, $arr[-1]); + $arr[MIN_UINT32_FLOAT] = MIN_UINT32_FLOAT; + $this->assertSame(MIN_UINT32, $arr[MIN_UINT32]); + $this->assertEquals(3, count($arr)); + unset($arr[3.1]); + unset($arr[-1.0]); + unset($arr[MIN_UINT32_FLOAT]); + $this->assertEquals(0, count($arr)); + + // Test string argument. + $arr[MAX_UINT32_STRING] = MAX_UINT32_STRING; + $this->assertSame(-1, $arr[-1]); + $this->assertEquals(1, count($arr)); + unset($arr[MAX_UINT32_STRING]); + $this->assertEquals(0, count($arr)); + + $arr['7'] = '7'; + $this->assertSame(7, $arr[7]); + $arr['3.1'] = '3.1'; + $this->assertSame(3, $arr[3]); + $arr['-1.0'] = '-1.0'; + $this->assertSame(-1, $arr[-1]); + $arr[MIN_UINT32_STRING] = MIN_UINT32_STRING; + $this->assertSame(MIN_UINT32, $arr[MIN_UINT32]); + $this->assertEquals(4, count($arr)); + unset($arr['7']); + unset($arr['3.1']); + unset($arr['-1.0']); + unset($arr[MIN_UINT32_STRING]); + $this->assertEquals(0, count($arr)); + } + + ######################################################### + # Test int64 field. + ######################################################### + + public function testInt64() { + $arr = new MapField(GPBType::INT64, GPBType::INT64); + + // Test integer argument. + $arr[MAX_INT64] = MAX_INT64; + $arr[MIN_INT64] = MIN_INT64; + if (PHP_INT_SIZE == 4) { + $this->assertSame(MAX_INT64_STRING, $arr[MAX_INT64_STRING]); + $this->assertSame(MIN_INT64_STRING, $arr[MIN_INT64_STRING]); + } else { + $this->assertSame(MAX_INT64, $arr[MAX_INT64]); + $this->assertSame(MIN_INT64, $arr[MIN_INT64]); + } + $this->assertEquals(2, count($arr)); + unset($arr[MAX_INT64]); + unset($arr[MIN_INT64]); + $this->assertEquals(0, count($arr)); + + // Test float argument. + $arr[1.1] = 1.1; + if (PHP_INT_SIZE == 4) { + $this->assertSame('1', $arr['1']); + } else { + $this->assertSame(1, $arr[1]); + } + $this->assertEquals(1, count($arr)); + unset($arr[1.1]); + $this->assertEquals(0, count($arr)); + + // Test string argument. + $arr['2'] = '2'; + $arr['3.1'] = '3.1'; + $arr[MAX_INT64_STRING] = MAX_INT64_STRING; + $arr[MIN_INT64_STRING] = MIN_INT64_STRING; + if (PHP_INT_SIZE == 4) { + $this->assertSame('2', $arr['2']); + $this->assertSame('3', $arr['3']); + $this->assertSame(MAX_INT64_STRING, $arr[MAX_INT64_STRING]); + $this->assertSame(MIN_INT64_STRING, $arr[MIN_INT64_STRING]); + } else { + $this->assertSame(2, $arr[2]); + $this->assertSame(3, $arr[3]); + $this->assertSame(MAX_INT64, $arr[MAX_INT64]); + $this->assertSame(MIN_INT64, $arr[MIN_INT64]); + } + $this->assertEquals(4, count($arr)); + unset($arr['2']); + unset($arr['3.1']); + unset($arr[MAX_INT64_STRING]); + unset($arr[MIN_INT64_STRING]); + $this->assertEquals(0, count($arr)); + } + + ######################################################### + # Test uint64 field. + ######################################################### + + public function testUint64() { + $arr = new MapField(GPBType::UINT64, GPBType::UINT64); + + // Test integer argument. + $arr[MAX_UINT64] = MAX_UINT64; + if (PHP_INT_SIZE == 4) { + $this->assertSame(MAX_UINT64_STRING, $arr[MAX_UINT64_STRING]); + } else { + $this->assertSame(MAX_UINT64, $arr[MAX_UINT64]); + } + $this->assertEquals(1, count($arr)); + unset($arr[MAX_UINT64]); + $this->assertEquals(0, count($arr)); + + // Test float argument. + $arr[1.1] = 1.1; + if (PHP_INT_SIZE == 4) { + $this->assertSame('1', $arr['1']); + } else { + $this->assertSame(1, $arr[1]); + } + $this->assertEquals(1, count($arr)); + unset($arr[1.1]); + $this->assertEquals(0, count($arr)); + + // Test string argument. + $arr['2'] = '2'; + $arr['3.1'] = '3.1'; + $arr[MAX_UINT64_STRING] = MAX_UINT64_STRING; + + if (PHP_INT_SIZE == 4) { + $this->assertSame('2', $arr['2']); + $this->assertSame('3', $arr['3']); + $this->assertSame(MAX_UINT64_STRING, $arr[MAX_UINT64_STRING]); + } else { + $this->assertSame(2, $arr[2]); + $this->assertSame(3, $arr[3]); + $this->assertSame(MAX_UINT64, $arr[MAX_UINT64]); + } + + $this->assertEquals(3, count($arr)); + unset($arr['2']); + unset($arr['3.1']); + unset($arr[MAX_UINT64_STRING]); + $this->assertEquals(0, count($arr)); + } + + ######################################################### + # Test float field. + ######################################################### + + public function testFloat() { + $arr = new MapField(GPBType::INT32, GPBType::FLOAT); + + // Test set. + $arr[0] = 1; + $this->assertFloatEquals(1.0, $arr[0], MAX_FLOAT_DIFF); + + $arr[1] = 1.1; + $this->assertFloatEquals(1.1, $arr[1], MAX_FLOAT_DIFF); + + $arr[2] = '2'; + $this->assertFloatEquals(2.0, $arr[2], MAX_FLOAT_DIFF); + $arr[3] = '3.1'; + $this->assertFloatEquals(3.1, $arr[3], MAX_FLOAT_DIFF); + + $this->assertEquals(4, count($arr)); + } + + ######################################################### + # Test double field. + ######################################################### + + public function testDouble() { + $arr = new MapField(GPBType::INT32, GPBType::DOUBLE); + + // Test set. + $arr[0] = 1; + $this->assertFloatEquals(1.0, $arr[0], MAX_FLOAT_DIFF); + + $arr[1] = 1.1; + $this->assertFloatEquals(1.1, $arr[1], MAX_FLOAT_DIFF); + + $arr[2] = '2'; + $this->assertFloatEquals(2.0, $arr[2], MAX_FLOAT_DIFF); + $arr[3] = '3.1'; + $this->assertFloatEquals(3.1, $arr[3], MAX_FLOAT_DIFF); + + $this->assertEquals(4, count($arr)); + } + + ######################################################### + # Test bool field. + ######################################################### + + public function testBool() { + $arr = new MapField(GPBType::BOOL, GPBType::BOOL); + + // Test boolean. + $arr[True] = True; + $this->assertSame(True, $arr[True]); + $this->assertEquals(1, count($arr)); + unset($arr[True]); + $this->assertEquals(0, count($arr)); + + $arr[False] = False; + $this->assertSame(False, $arr[False]); + $this->assertEquals(1, count($arr)); + unset($arr[False]); + $this->assertEquals(0, count($arr)); + + // Test integer. + $arr[-1] = -1; + $this->assertSame(True, $arr[True]); + $this->assertEquals(1, count($arr)); + unset($arr[-1]); + $this->assertEquals(0, count($arr)); + + $arr[0] = 0; + $this->assertSame(False, $arr[False]); + $this->assertEquals(1, count($arr)); + unset($arr[0]); + $this->assertEquals(0, count($arr)); + + // Test float. + $arr[1.1] = 1.1; + $this->assertSame(True, $arr[True]); + $this->assertEquals(1, count($arr)); + unset($arr[1.1]); + $this->assertEquals(0, count($arr)); + + $arr[0.0] = 0.0; + $this->assertSame(False, $arr[False]); + $this->assertEquals(1, count($arr)); + unset($arr[0.0]); + $this->assertEquals(0, count($arr)); + + // Test string. + $arr['a'] = 'a'; + $this->assertSame(True, $arr[True]); + $this->assertEquals(1, count($arr)); + unset($arr['a']); + $this->assertEquals(0, count($arr)); + + $arr[''] = ''; + $this->assertSame(False, $arr[False]); + $this->assertEquals(1, count($arr)); + unset($arr['']); + $this->assertEquals(0, count($arr)); + } + + ######################################################### + # Test string field. + ######################################################### + + public function testString() { + $arr = new MapField(GPBType::STRING, GPBType::STRING); + + // Test set. + $arr['abc'] = 'abc'; + $this->assertSame('abc', $arr['abc']); + $this->assertEquals(1, count($arr)); + unset($arr['abc']); + $this->assertEquals(0, count($arr)); + + $arr[1] = 1; + $this->assertSame('1', $arr['1']); + $this->assertEquals(1, count($arr)); + unset($arr[1]); + $this->assertEquals(0, count($arr)); + + $arr[1.1] = 1.1; + $this->assertSame('1.1', $arr['1.1']); + $this->assertEquals(1, count($arr)); + unset($arr[1.1]); + $this->assertEquals(0, count($arr)); + + $arr[True] = True; + $this->assertSame('1', $arr['1']); + $this->assertEquals(1, count($arr)); + unset($arr[True]); + $this->assertEquals(0, count($arr)); + + // Test foreach. + $arr = new MapField(GPBType::STRING, GPBType::STRING); + for ($i = 0; $i < 3; $i++) { + $arr[$i] = $i; + } + $i = 0; + $arr_test = []; + foreach ($arr as $key => $val) { + $this->assertSame($key, $val); + $arr_test[] = $key; + $i++; + } + $this->assertTrue(isset($arr_test['0'])); + $this->assertTrue(isset($arr_test['1'])); + $this->assertTrue(isset($arr_test['2'])); + $this->assertSame(3, $i); + } + + ######################################################### + # Test message field. + ######################################################### + + public function testMessage() { + $arr = new MapField(GPBType::INT32, + GPBType::MESSAGE, Sub::class); + + // Test append. + $sub_m = new Sub(); + $sub_m->setA(1); + $arr[0] = $sub_m; + $this->assertSame(1, $arr[0]->getA()); + + $this->assertEquals(1, count($arr)); + + // Test foreach. + $arr = new MapField(GPBType::INT32, + GPBType::MESSAGE, Sub::class); + for ($i = 0; $i < 3; $i++) { + $arr[$i] = new Sub();; + $arr[$i]->setA($i); + } + $i = 0; + $key_test = []; + $value_test = []; + foreach ($arr as $key => $val) { + $key_test[] = $key; + $value_test[] = $val->getA(); + $i++; + } + $this->assertTrue(isset($key_test['0'])); + $this->assertTrue(isset($key_test['1'])); + $this->assertTrue(isset($key_test['2'])); + $this->assertTrue(isset($value_test['0'])); + $this->assertTrue(isset($value_test['1'])); + $this->assertTrue(isset($value_test['2'])); + $this->assertSame(3, $i); + } + + ######################################################### + # Test reference in map + ######################################################### + + public function testMapElementIsReference() + { + // Bool elements + $values = [true => true]; + array_walk($values, function (&$value) {}); + $m = new TestMessage(); + $m->setMapBoolBool($values); + + // Int32 elements + $values = [1 => 1]; + array_walk($values, function (&$value) {}); + $m = new TestMessage(); + $m->setMapInt32Int32($values); + + // Double elements + $values = [1 => 1.0]; + array_walk($values, function (&$value) {}); + $m = new TestMessage(); + $m->setMapInt32Double($values); + + // String elements + $values = ['a' => 'a']; + array_walk($values, function (&$value) {}); + $m = new TestMessage(); + $m->setMapStringString($values); + + // Message elements + $values = [1 => new Sub()]; + array_walk($values, function (&$value) {}); + $m = new TestMessage(); + $m->setMapInt32Message($values); + + $this->assertTrue(true); + } + + ######################################################### + # Test equality + ######################################################### + + public function testEquality() + { + $map = new MapField(GPBType::INT32, GPBType::INT32); + $map2 = new MapField(GPBType::INT32, GPBType::INT32); + + $this->assertTrue($map == $map2); + + $map[1] = 2; + + $this->assertFalse($map == $map2); + + $map2[1] = 2; + + $this->assertTrue($map == $map2); + + // Arrays of different types always compare false. + $this->assertFalse(new MapField(GPBType::INT32, GPBType::INT32) == + new MapField(GPBType::INT32, GPBType::INT64)); + $this->assertFalse(new MapField(GPBType::INT32, GPBType::INT32) == + new MapField(GPBType::INT64, GPBType::INT32)); + $this->assertFalse( + new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class) == + new MapField(GPBType::INT32, GPBType::MESSAGE, Sub::class)); + } + + ######################################################### + # Test clone + ######################################################### + + public function testClone() + { + $map = new MapField(GPBType::INT32, + GPBType::MESSAGE, Sub::class); + + // Test append. + $sub_m = new Sub(); + $sub_m->setA(1); + $map[0] = $sub_m; + + $map2 = clone $map; + $this->assertSame($map[0], $map2[0]); + } + + ######################################################### + # Test memory leak + ######################################################### + + // TODO(teboring): Add it back. + // public function testCycleLeak() + // { + // $arr = new MapField(GPBType::INT32, + // GPBType::MESSAGE, TestMessage::class); + // $arr[0] = new TestMessage; + // $arr[0]->SetMapRecursive($arr); + + // // Clean up memory before test. + // gc_collect_cycles(); + // $start = memory_get_usage(); + // unset($arr); + + // // Explicitly trigger garbage collection. + // gc_collect_cycles(); + + // $end = memory_get_usage(); + // $this->assertLessThan($start, $end); + // } +} diff --git a/php/tests/PhpImplementationTest.php b/php/tests/PhpImplementationTest.php new file mode 100644 index 0000000000000..82d0c5aff25a7 --- /dev/null +++ b/php/tests/PhpImplementationTest.php @@ -0,0 +1,605 @@ +markTestSkipped(); + } + } + + public function testReadInt32() + { + $value = null; + + // Positive number. + $input = new CodedInputStream(hex2bin("01")); + GPBWire::readInt32($input, $value); + $this->assertSame(1, $value); + + // Negative number. + $input = new CodedInputStream(hex2bin("ffffffff0f")); + GPBWire::readInt32($input, $value); + $this->assertSame(-1, $value); + + // Discard overflow bits. + $input = new CodedInputStream(hex2bin("ffffffff7f")); + GPBWire::readInt32($input, $value); + $this->assertSame(-1, $value); + } + + public function testReadUint32() + { + $value = null; + + // Positive number. + $input = new CodedInputStream(hex2bin("01")); + GPBWire::readUint32($input, $value); + $this->assertSame(1, $value); + + // Max uint32. + $input = new CodedInputStream(hex2bin("ffffffff0f")); + GPBWire::readUint32($input, $value); + $this->assertSame(-1, $value); + + // Discard overflow bits. + $input = new CodedInputStream(hex2bin("ffffffff7f")); + GPBWire::readUint32($input, $value); + $this->assertSame(-1, $value); + } + + public function testReadInt64() + { + $value = null; + + // Positive number. + $input = new CodedInputStream(hex2bin("01")); + GPBWire::readInt64($input, $value); + $this->assertEquals(1, $value); + + // Negative number. + $input = new CodedInputStream(hex2bin("ffffffffffffffffff01")); + GPBWire::readInt64($input, $value); + $this->assertEquals(-1, $value); + + // Discard overflow bits. + $input = new CodedInputStream(hex2bin("ffffffffffffffffff0f")); + GPBWire::readInt64($input, $value); + $this->assertEquals(-1, $value); + } + + public function testReadUint64() + { + $value = null; + + // Positive number. + $input = new CodedInputStream(hex2bin("01")); + GPBWire::readUint64($input, $value); + $this->assertEquals(1, $value); + + // Negative number. + $input = new CodedInputStream(hex2bin("FFFFFFFFFFFFFFFFFF01")); + GPBWire::readUint64($input, $value); + $this->assertEquals(-1, $value); + + // Discard overflow bits. + $input = new CodedInputStream(hex2bin("FFFFFFFFFFFFFFFFFF0F")); + GPBWire::readUint64($input, $value); + $this->assertEquals(-1, $value); + } + + public function testReadSint32() + { + $value = null; + + $input = new CodedInputStream(hex2bin("00")); + GPBWire::readSint32($input, $value); + $this->assertSame(0, $value); + + $input = new CodedInputStream(hex2bin("01")); + GPBWire::readSint32($input, $value); + $this->assertSame(-1, $value); + + $input = new CodedInputStream(hex2bin("02")); + GPBWire::readSint32($input, $value); + $this->assertSame(1, $value); + } + + public function testReadSint64() + { + $value = null; + + $input = new CodedInputStream(hex2bin("00")); + GPBWire::readSint64($input, $value); + $this->assertEquals(0, $value); + + $input = new CodedInputStream(hex2bin("01")); + GPBWire::readSint64($input, $value); + $this->assertEquals(-1, $value); + + $input = new CodedInputStream(hex2bin("02")); + GPBWire::readSint64($input, $value); + $this->assertEquals(1, $value); + } + + public function testReadFixed32() + { + $value = null; + $input = new CodedInputStream(hex2bin("12345678")); + GPBWire::readFixed32($input, $value); + $this->assertSame(0x78563412, $value); + } + + public function testReadFixed64() + { + $value = null; + $input = new CodedInputStream(hex2bin("1234567812345678")); + GPBWire::readFixed64($input, $value); + if (PHP_INT_SIZE == 4) { + $this->assertSame("8671175386481439762", $value); + } else { + $this->assertSame(0x7856341278563412, $value); + } + } + + public function testReadSfixed32() + { + $value = null; + $input = new CodedInputStream(hex2bin("12345678")); + GPBWire::readSfixed32($input, $value); + $this->assertSame(0x78563412, $value); + } + + public function testReadFloat() + { + $value = null; + $input = new CodedInputStream(hex2bin("0000803F")); + GPBWire::readFloat($input, $value); + $this->assertSame(1.0, $value); + } + + public function testReadBool() + { + $value = null; + + $input = new CodedInputStream(hex2bin("00")); + GPBWire::readBool($input, $value); + $this->assertSame(false, $value); + + $input = new CodedInputStream(hex2bin("01")); + GPBWire::readBool($input, $value); + $this->assertSame(true, $value); + } + + public function testReadDouble() + { + $value = null; + $input = new CodedInputStream(hex2bin("000000000000F03F")); + GPBWire::readDouble($input, $value); + $this->assertSame(1.0, $value); + } + + public function testReadSfixed64() + { + $value = null; + $input = new CodedInputStream(hex2bin("1234567812345678")); + GPBWire::readSfixed64($input, $value); + if (PHP_INT_SIZE == 4) { + $this->assertSame("8671175386481439762", $value); + } else { + $this->assertSame(0x7856341278563412, $value); + } + } + + public function testZigZagEncodeDecode() + { + $this->assertSame(0, GPBWire::zigZagEncode32(0)); + $this->assertSame(1, GPBWire::zigZagEncode32(-1)); + $this->assertSame(2, GPBWire::zigZagEncode32(1)); + $this->assertSame(3, GPBWire::zigZagEncode32(-2)); + $this->assertSame(0x7FFFFFFE, GPBWire::zigZagEncode32(0x3FFFFFFF)); + $this->assertSame(0x7FFFFFFF, GPBWire::zigZagEncode32(0xC0000000)); + $this->assertSame(0x7FFFFFFF, GPBWire::zigZagEncode32(-1073741824)); + + $this->assertSame(0, GPBWire::zigZagDecode32(0)); + $this->assertSame(-1, GPBWire::zigZagDecode32(1)); + $this->assertSame(1, GPBWire::zigZagDecode32(2)); + $this->assertSame(-2, GPBWire::zigZagDecode32(3)); + $this->assertSame(0x3FFFFFFF, GPBWire::zigZagDecode32(0x7FFFFFFE)); + $this->assertSame(-1073741824, GPBWire::zigZagDecode32(0x7FFFFFFF)); + $this->assertSame(0x7FFFFFFF, GPBWire::zigZagDecode32(0xFFFFFFFE)); + $this->assertSame((int)-2147483648,GPBWire::zigZagDecode32(0xFFFFFFFF)); + + if (PHP_INT_SIZE == 4) { + $this->assertSame(-2, GPBWire::zigZagEncode32(0x7FFFFFFF)); + $this->assertSame(-1, GPBWire::zigZagEncode32(0x80000000)); + $this->assertSame('0', GPBWire::zigZagEncode64(0)); + $this->assertSame('1', GPBWire::zigZagEncode64(-1)); + $this->assertSame('2', GPBWire::zigZagEncode64(1)); + $this->assertSame('3', GPBWire::zigZagEncode64(-2)); + $this->assertSame( + '2147483646', // 0x7FFFFFE + GPBWire::zigZagEncode64(0x3FFFFFFF)); + $this->assertSame( + '2147483647', // 0x7FFFFFF + GPBWire::zigZagEncode64(-1073741824)); // 0xFFFFFFFFC0000000 + $this->assertSame( + '4294967294', // 0xFFFFFFFE + GPBWire::zigZagEncode64(2147483647)); // 0x7FFFFFFF + $this->assertSame( + '4294967295', // 0xFFFFFFFF + GPBWire::zigZagEncode64(-2147483648)); // 0xFFFFFFFF80000000 + $this->assertSame( + '18446744073709551614', // 0xFFFFFFFFFFFFFFFE + // 0x7FFFFFFFFFFFFFFF + GPBWire::zigZagEncode64("9223372036854775807")); + $this->assertSame( + '18446744073709551615', // 0xFFFFFFFFFFFFFFFF + // 0x8000000000000000 + GPBWire::zigZagEncode64("-9223372036854775808")); + + $this->assertSame('0', GPBWire::zigZagDecode64(0)); + $this->assertSame('-1', GPBWire::zigZagDecode64(1)); + $this->assertSame('1', GPBWire::zigZagDecode64(2)); + $this->assertSame('-2', GPBWire::zigZagDecode64(3)); + } else { + $this->assertSame(4294967294, GPBWire::zigZagEncode32(0x7FFFFFFF)); + $this->assertSame(4294967295, GPBWire::zigZagEncode32(0x80000000)); + $this->assertSame(0, GPBWire::zigZagEncode64(0)); + $this->assertSame(1, GPBWire::zigZagEncode64(-1)); + $this->assertSame(2, GPBWire::zigZagEncode64(1)); + $this->assertSame(3, GPBWire::zigZagEncode64(-2)); + $this->assertSame(0x7FFFFFFE, GPBWire::zigZagEncode64(0x3FFFFFFF)); + $this->assertSame( + 0x7FFFFFFF, + GPBWire::zigZagEncode64(0xFFFFFFFFC0000000)); + $this->assertSame( + 0xFFFFFFFE, + GPBWire::zigZagEncode64(0x7FFFFFFF)); + $this->assertSame( + 0xFFFFFFFF, + GPBWire::zigZagEncode64(0xFFFFFFFF80000000)); + $this->assertSame( + -2, // 0xFFFFFFFFFFFFFFFE + GPBWire::zigZagEncode64(0x7FFFFFFFFFFFFFFF)); + $this->assertSame( + -1, // 0xFFFFFFFFFFFFFFFF + GPBWire::zigZagEncode64(0x8000000000000000)); + + $this->assertSame(0, GPBWire::zigZagDecode64(0)); + $this->assertSame(-1, GPBWire::zigZagDecode64(1)); + $this->assertSame(1, GPBWire::zigZagDecode64(2)); + $this->assertSame(-2, GPBWire::zigZagDecode64(3)); + } + + // Round trip + $this->assertSame(0, GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(0))); + $this->assertSame(1, GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(1))); + $this->assertSame(-1, GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(-1))); + $this->assertSame(14927, + GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(14927))); + $this->assertSame(-3612, + GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(-3612))); + } + + public function testDecode() + { + $m = new TestMessage(); + $m->mergeFromString(TestUtil::getGoldenTestMessage()); + TestUtil::assertTestMessage($m); + + $this->assertTrue(true); + } + + public function testDescriptorDecode() + { + $file_desc_set = new FileDescriptorSet(); + $file_desc_set->mergeFromString(hex2bin( + "0a3b0a12746573745f696e636c7564652e70726f746f120362617222180a" . + "0b54657374496e636c75646512090a0161180120012805620670726f746f33")); + + $this->assertSame(1, sizeof($file_desc_set->getFile())); + + $file_desc = $file_desc_set->getFile()[0]; + $this->assertSame("test_include.proto", $file_desc->getName()); + $this->assertSame("bar", $file_desc->getPackage()); + $this->assertSame(0, sizeof($file_desc->getDependency())); + $this->assertSame(1, sizeof($file_desc->getMessageType())); + $this->assertSame(0, sizeof($file_desc->getEnumType())); + $this->assertSame("proto3", $file_desc->getSyntax()); + + $desc = $file_desc->getMessageType()[0]; + $this->assertSame("TestInclude", $desc->getName()); + $this->assertSame(1, sizeof($desc->getField())); + $this->assertSame(0, sizeof($desc->getNestedType())); + $this->assertSame(0, sizeof($desc->getEnumType())); + $this->assertSame(0, sizeof($desc->getOneofDecl())); + + $field = $desc->getField()[0]; + $this->assertSame("a", $field->getName()); + $this->assertSame(1, $field->getNumber()); + $this->assertSame(GPBLabel::OPTIONAL, $field->getLabel()); + $this->assertSame(GPBType::INT32, $field->getType()); + } + + public function testReadVarint64() + { + $var = 0; + + // Empty buffer. + $input = new CodedInputStream(hex2bin('')); + $this->assertFalse($input->readVarint64($var)); + + // The largest varint is 10 bytes long. + $input = new CodedInputStream(hex2bin('8080808080808080808001')); + $this->assertFalse($input->readVarint64($var)); + + // Corrupted varint. + $input = new CodedInputStream(hex2bin('808080')); + $this->assertFalse($input->readVarint64($var)); + + // Normal case. + $input = new CodedInputStream(hex2bin('808001')); + $this->assertTrue($input->readVarint64($var)); + if (PHP_INT_SIZE == 4) { + $this->assertSame('16384', $var); + } else { + $this->assertSame(16384, $var); + } + $this->assertFalse($input->readVarint64($var)); + + // Read two varint. + $input = new CodedInputStream(hex2bin('808001808002')); + $this->assertTrue($input->readVarint64($var)); + if (PHP_INT_SIZE == 4) { + $this->assertSame('16384', $var); + } else { + $this->assertSame(16384, $var); + } + $this->assertTrue($input->readVarint64($var)); + if (PHP_INT_SIZE == 4) { + $this->assertSame('32768', $var); + } else { + $this->assertSame(32768, $var); + } + $this->assertFalse($input->readVarint64($var)); + + // Read 64 testing + $testVals = array( + '10' => '0a000000000000000000', + '100' => '64000000000000000000', + '800' => 'a0060000000000000000', + '6400' => '80320000000000000000', + '70400' => '80a60400000000000000', + '774400' => '80a22f00000000000000', + '9292800' => '8098b704000000000000', + '74342400' => '80c0b923000000000000', + '743424000' => '8080bfe2020000000000', + '8177664000' => '8080b5bb1e0000000000', + '65421312000' => '8080a8dbf30100000000', + '785055744000' => '8080e0c7ec1600000000', + '9420668928000' => '808080dd969202000000', + '103627358208000' => '808080fff9c717000000', + '1139900940288000' => '808080f5bd9783020000', + '13678811283456000' => '808080fce699a6180000', + '109430490267648000' => '808080e0b7ceb1c20100', + '984874412408832000' => '808080e0f5c1bed50d00', + ); + + foreach ($testVals as $original => $encoded) { + $input = new CodedInputStream(hex2bin($encoded)); + $this->assertTrue($input->readVarint64($var)); + $this->assertEquals($original, $var); + } + } + + public function testReadVarint32() + { + $var = 0; + + // Empty buffer. + $input = new CodedInputStream(hex2bin('')); + $this->assertFalse($input->readVarint32($var)); + + // The largest varint is 10 bytes long. + $input = new CodedInputStream(hex2bin('8080808080808080808001')); + $this->assertFalse($input->readVarint32($var)); + + // Corrupted varint. + $input = new CodedInputStream(hex2bin('808080')); + $this->assertFalse($input->readVarint32($var)); + + // Normal case. + $input = new CodedInputStream(hex2bin('808001')); + $this->assertTrue($input->readVarint32($var)); + $this->assertSame(16384, $var); + $this->assertFalse($input->readVarint32($var)); + + // Read two varint. + $input = new CodedInputStream(hex2bin('808001808002')); + $this->assertTrue($input->readVarint32($var)); + $this->assertSame(16384, $var); + $this->assertTrue($input->readVarint32($var)); + $this->assertSame(32768, $var); + $this->assertFalse($input->readVarint32($var)); + + // Read a 64-bit integer. High-order bits should be discarded. + $input = new CodedInputStream(hex2bin('808081808001')); + $this->assertTrue($input->readVarint32($var)); + $this->assertSame(16384, $var); + $this->assertFalse($input->readVarint32($var)); + } + + public function testReadTag() + { + $input = new CodedInputStream(hex2bin('808001')); + $tag = $input->readTag(); + $this->assertSame(16384, $tag); + $tag = $input->readTag(); + $this->assertSame(0, $tag); + } + + public function testPushPopLimit() + { + $input = new CodedInputStream(hex2bin('808001')); + $old_limit = $input->pushLimit(0); + $tag = $input->readTag(); + $this->assertSame(0, $tag); + $input->popLimit($old_limit); + $tag = $input->readTag(); + $this->assertSame(16384, $tag); + } + + public function testReadRaw() + { + $input = new CodedInputStream(hex2bin('808001')); + $buffer = null; + + $this->assertTrue($input->readRaw(3, $buffer)); + $this->assertSame(hex2bin('808001'), $buffer); + + $this->assertFalse($input->readRaw(1, $buffer)); + } + + public function testWriteVarint32() + { + $output = new CodedOutputStream(3); + $output->writeVarint32(16384, true); + $this->assertSame(hex2bin('808001'), $output->getData()); + + // Negative numbers are padded to be compatible with int64. + $output = new CodedOutputStream(10); + $output->writeVarint32(-43, false); + $this->assertSame(hex2bin('D5FFFFFFFFFFFFFFFF01'), $output->getData()); + } + + public function testWriteVarint64() + { + $output = new CodedOutputStream(10); + $output->writeVarint64(-43); + $this->assertSame(hex2bin('D5FFFFFFFFFFFFFFFF01'), $output->getData()); + } + + public function testWriteLittleEndian32() + { + $output = new CodedOutputStream(4); + $output->writeLittleEndian32(46); + $this->assertSame(hex2bin('2E000000'), $output->getData()); + } + + public function testWriteLittleEndian64() + { + $output = new CodedOutputStream(8); + $output->writeLittleEndian64(47); + $this->assertSame(hex2bin('2F00000000000000'), $output->getData()); + } + + public function testByteSize() + { + $m = new TestMessage(); + TestUtil::setTestMessage($m); + $this->assertSame(504, $m->byteSize()); + } + + public function testPackedByteSize() + { + $m = new TestPackedMessage(); + TestUtil::setTestPackedMessage($m); + $this->assertSame(166, $m->byteSize()); + } + + public function testArrayConstructorJsonCaseThrowsException() + { + $this->expectException(UnexpectedValueException::class); + $this->expectExceptionMessage( + 'Invalid message property: optionalInt32'); + + $m = new TestMessage([ + 'optionalInt32' => -42, + ]); + } + + public function testArraysForMessagesThrowsException() + { + $this->expectException(Exception::class); + $this->expectExceptionMessage( + 'Expect Foo\TestMessage\Sub.'); + + $m = new TestMessage([ + 'optional_message' => [ + 'a' => 33 + ] + ]); + } + + public function testArrayConstructorWithNullValues() + { + $requestData = [ + 'optional_bool' => null, + 'optional_string' => null, + 'optional_bytes' => null, + 'optional_message' => null, + ]; + + $m = new TestMessage($requestData); + + $this->assertSame(false, $m->getOptionalBool()); + $this->assertSame('', $m->getOptionalString()); + $this->assertSame('', $m->getOptionalBytes()); + $this->assertSame(null, $m->getOptionalMessage()); + } + + /** + * @dataProvider provideArrayConstructorWithNullValuesThrowsException + */ + public function testArrayConstructorWithNullValuesThrowsException($requestData) + { + $this->expectException(Exception::class); + + $m = new TestMessage($requestData); + } + + public function provideArrayConstructorWithNullValuesThrowsException() + { + return [ + [['optional_int32' => null]], + [['optional_int64' => null]], + [['optional_uint32' => null]], + [['optional_uint64' => null]], + [['optional_sint32' => null]], + [['optional_sint64' => null]], + [['optional_fixed32' => null]], + [['optional_fixed64' => null]], + [['optional_sfixed32' => null]], + [['optional_sfixed64' => null]], + [['optional_float' => null]], + [['optional_double' => null]], + [['optional_enum' => null]], + [['repeated_int32' => null]], + [['map_int32_int32' => null]], + ]; + } +} diff --git a/php/tests/WellKnownTest.php b/php/tests/WellKnownTest.php new file mode 100644 index 0000000000000..27b7e1463cec8 --- /dev/null +++ b/php/tests/WellKnownTest.php @@ -0,0 +1,417 @@ +assertTrue($msg instanceof \Google\Protobuf\Internal\Message); + } + + public function testImportDescriptorProto() + { + $msg = new TestImportDescriptorProto(); + $this->assertTrue(true); + } + + public function testAny() + { + // Create embed message + $embed = new TestMessage(); + $this->setFields($embed); + $data = $embed->serializeToString(); + + // Set any via normal setter. + $any = new Any(); + + $this->assertSame( + $any, $any->setTypeUrl("type.googleapis.com/foo.TestMessage")); + $this->assertSame("type.googleapis.com/foo.TestMessage", + $any->getTypeUrl()); + + $this->assertSame($any, $any->setValue($data)); + $this->assertSame($data, $any->getValue()); + + // Test unpack. + $msg = $any->unpack(); + $this->assertTrue($msg instanceof TestMessage); + $this->expectFields($msg); + + // Test pack. + $any = new Any(); + $any->pack($embed); + $this->assertSame($data, $any->getValue()); + $this->assertSame("type.googleapis.com/foo.TestMessage", $any->getTypeUrl()); + + // Test is. + $this->assertTrue($any->is(TestMessage::class)); + $this->assertFalse($any->is(Any::class)); + } + + public function testAnyUnpackInvalidTypeUrl() + { + $this->expectException(Exception::class); + + $any = new Any(); + $any->setTypeUrl("invalid"); + $any->unpack(); + } + + public function testAnyUnpackMessageNotAdded() + { + $this->expectException(Exception::class); + + $any = new Any(); + $any->setTypeUrl("type.googleapis.com/MessageNotAdded"); + $any->unpack(); + } + + public function testAnyUnpackDecodeError() + { + $this->expectException(Exception::class); + + $any = new Any(); + $any->setTypeUrl("type.googleapis.com/foo.TestMessage"); + $any->setValue("abc"); + $any->unpack(); + } + + public function testApi() + { + $m = new Api(); + + $m->setName("a"); + $this->assertSame("a", $m->getName()); + + $m->setMethods([new Method()]); + $this->assertSame(1, count($m->getMethods())); + + $m->setOptions([new Option()]); + $this->assertSame(1, count($m->getOptions())); + + $m->setVersion("a"); + $this->assertSame("a", $m->getVersion()); + + $m->setSourceContext(new SourceContext()); + $this->assertFalse(is_null($m->getSourceContext())); + + $m->setMixins([new Mixin()]); + $this->assertSame(1, count($m->getMixins())); + + $m->setSyntax(Syntax::SYNTAX_PROTO2); + $this->assertSame(Syntax::SYNTAX_PROTO2, $m->getSyntax()); + + $m = new Method(); + + $m->setName("a"); + $this->assertSame("a", $m->getName()); + + $m->setRequestTypeUrl("a"); + $this->assertSame("a", $m->getRequestTypeUrl()); + + $m->setRequestStreaming(true); + $this->assertSame(true, $m->getRequestStreaming()); + + $m->setResponseTypeUrl("a"); + $this->assertSame("a", $m->getResponseTypeUrl()); + + $m->setResponseStreaming(true); + $this->assertSame(true, $m->getResponseStreaming()); + + $m->setOptions([new Option()]); + $this->assertSame(1, count($m->getOptions())); + + $m = new Mixin(); + + $m->setName("a"); + $this->assertSame("a", $m->getName()); + + $m->setRoot("a"); + $this->assertSame("a", $m->getRoot()); + } + + public function testEnum() + { + $m = new Enum(); + + $m->setName("a"); + $this->assertSame("a", $m->getName()); + + $m->setEnumvalue([new EnumValue()]); + $this->assertSame(1, count($m->getEnumvalue())); + + $m->setOptions([new Option()]); + $this->assertSame(1, count($m->getOptions())); + + $m->setSourceContext(new SourceContext()); + $this->assertFalse(is_null($m->getSourceContext())); + + $m->setSyntax(Syntax::SYNTAX_PROTO2); + $this->assertSame(Syntax::SYNTAX_PROTO2, $m->getSyntax()); + } + + public function testEnumValue() + { + $m = new EnumValue(); + + $m->setName("a"); + $this->assertSame("a", $m->getName()); + + $m->setNumber(1); + $this->assertSame(1, $m->getNumber()); + + $m->setOptions([new Option()]); + $this->assertSame(1, count($m->getOptions())); + } + + public function testField() + { + $m = new Field(); + + $m->setKind(Kind::TYPE_DOUBLE); + $this->assertSame(Kind::TYPE_DOUBLE, $m->getKind()); + + $m->setCardinality(Cardinality::CARDINALITY_OPTIONAL); + $this->assertSame(Cardinality::CARDINALITY_OPTIONAL, $m->getCardinality()); + + $m->setNumber(1); + $this->assertSame(1, $m->getNumber()); + + $m->setName("a"); + $this->assertSame("a", $m->getName()); + + $m->setTypeUrl("a"); + $this->assertSame("a", $m->getTypeUrl()); + + $m->setOneofIndex(1); + $this->assertSame(1, $m->getOneofIndex()); + + $m->setPacked(true); + $this->assertSame(true, $m->getPacked()); + + $m->setOptions([new Option()]); + $this->assertSame(1, count($m->getOptions())); + + $m->setJsonName("a"); + $this->assertSame("a", $m->getJsonName()); + + $m->setDefaultValue("a"); + $this->assertSame("a", $m->getDefaultValue()); + } + + public function testFieldMask() + { + $m = new FieldMask(); + $m->setPaths(["a"]); + $this->assertSame(1, count($m->getPaths())); + } + + public function testOption() + { + $m = new Option(); + + $m->setName("a"); + $this->assertSame("a", $m->getName()); + + $m->setValue(new Any()); + $this->assertFalse(is_null($m->getValue())); + } + + public function testSourceContext() + { + $m = new SourceContext(); + $m->setFileName("a"); + $this->assertSame("a", $m->getFileName()); + } + + public function testStruct() + { + $m = new ListValue(); + $m->setValues([new Value()]); + $this->assertSame(1, count($m->getValues())); + + $m = new Value(); + + $m->setNullValue(NullValue::NULL_VALUE); + $this->assertSame(NullValue::NULL_VALUE, $m->getNullValue()); + $this->assertSame("null_value", $m->getKind()); + + $m->setNumberValue(1.0); + $this->assertSame(1.0, $m->getNumberValue()); + $this->assertSame("number_value", $m->getKind()); + + $m->setStringValue("a"); + $this->assertSame("a", $m->getStringValue()); + $this->assertSame("string_value", $m->getKind()); + + $m->setBoolValue(true); + $this->assertSame(true, $m->getBoolValue()); + $this->assertSame("bool_value", $m->getKind()); + + $m->setStructValue(new Struct()); + $this->assertFalse(is_null($m->getStructValue())); + $this->assertSame("struct_value", $m->getKind()); + + $m->setListValue(new ListValue()); + $this->assertFalse(is_null($m->getListValue())); + $this->assertSame("list_value", $m->getKind()); + + $m = new Struct(); + $m->setFields(array("a"=>new Value())); + $this->assertSame(1, count($m->getFields())); + } + + public function testTimestamp() + { + $timestamp = new Timestamp(); + + $timestamp->setSeconds(1); + $timestamp->setNanos(2); + $this->assertEquals(1, $timestamp->getSeconds()); + $this->assertSame(2, $timestamp->getNanos()); + + date_default_timezone_set('UTC'); + $from = new DateTime('2011-01-01T15:03:01.012345UTC'); + $timestamp->fromDateTime($from); + $this->assertEquals($from->format('U'), $timestamp->getSeconds()); + $this->assertEquals(1000 * $from->format('u'), $timestamp->getNanos()); + + $to = $timestamp->toDateTime(); + $this->assertSame(\DateTime::class, get_class($to)); + $this->assertSame($from->format('U'), $to->format('U')); + $this->assertSame($from->format('u'), $to->format('u')); + } + + public function testType() + { + $m = new Type(); + + $m->setName("a"); + $this->assertSame("a", $m->getName()); + + $m->setFields([new Field()]); + $this->assertSame(1, count($m->getFields())); + + $m->setOneofs(["a"]); + $this->assertSame(1, count($m->getOneofs())); + + $m->setOptions([new Option()]); + $this->assertSame(1, count($m->getOptions())); + + $m->setSourceContext(new SourceContext()); + $this->assertFalse(is_null($m->getSourceContext())); + + $m->setSyntax(Syntax::SYNTAX_PROTO2); + $this->assertSame(Syntax::SYNTAX_PROTO2, $m->getSyntax()); + } + + public function testDuration() + { + $duration = new Duration(); + + $duration->setSeconds(1); + $duration->setNanos(2); + $this->assertEquals(1, $duration->getSeconds()); + $this->assertSame(2, $duration->getNanos()); + } + + public function testWrappers() + { + $m = new DoubleValue(); + $m->setValue(1.0); + $this->assertSame(1.0, $m->getValue()); + + $m = new FloatValue(); + $m->setValue(1.0); + $this->assertSame(1.0, $m->getValue()); + + $m = new Int64Value(); + $m->setValue(1); + $this->assertEquals(1, $m->getValue()); + + $m = new UInt64Value(); + $m->setValue(1); + $this->assertEquals(1, $m->getValue()); + + $m = new Int32Value(); + $m->setValue(1); + $this->assertSame(1, $m->getValue()); + + $m = new UInt32Value(); + $m->setValue(1); + $this->assertSame(1, $m->getValue()); + + $m = new BoolValue(); + $m->setValue(true); + $this->assertSame(true, $m->getValue()); + + $m = new StringValue(); + $m->setValue("a"); + $this->assertSame("a", $m->getValue()); + + $m = new BytesValue(); + $m->setValue("a"); + $this->assertSame("a", $m->getValue()); + } + + /** + * @dataProvider enumNameValueConversionDataProvider + */ + public function testEnumNameValueConversion($class) + { + $reflectionClass = new ReflectionClass($class); + $constants = $reflectionClass->getConstants(); + foreach ($constants as $k => $v) { + $this->assertSame($k, $class::name($v)); + $this->assertSame($v, $class::value($k)); + } + } + + public function enumNameValueConversionDataProvider() + { + return [ + ['\Google\Protobuf\Field\Cardinality'], + ['\Google\Protobuf\Field\Kind'], + ['\Google\Protobuf\NullValue'], + ['\Google\Protobuf\Syntax'], + ]; + } +} diff --git a/php/tests/WrapperTypeSettersTest.php b/php/tests/WrapperTypeSettersTest.php new file mode 100644 index 0000000000000..045fa66ef2d40 --- /dev/null +++ b/php/tests/WrapperTypeSettersTest.php @@ -0,0 +1,317 @@ + $value]); + + // Set values using new and old setters + $oldSetterMsg->$setter($wrappedValue); + $newSetterMsg->$valueSetter($value); + + // Get expected values old getter + $expectedValue = $oldSetterMsg->$getter(); + + // Check that old getter returns the same value after using the + // new setter + $actualValue = $newSetterMsg->$getter(); + $this->assertEquals($expectedValue, $actualValue); + + // Check that new getter returns the unwrapped value from + // $expectedValue + $actualValueNewGetter = $newSetterMsg->$valueGetter(); + if (is_null($expectedValue)) { + $this->assertNull($actualValueNewGetter); + } else { + $this->assertEquals($expectedValue->getValue(), $actualValueNewGetter); + } + } + } + + public function gettersAndSettersDataProvider() + { + return [ + [TestWrapperSetters::class, DoubleValue::class, "setDoubleValue", "setDoubleValueUnwrapped", "getDoubleValue", "getDoubleValueUnwrapped", [ + [1.1, new DoubleValue(["value" => 1.1])], + [2.2, new DoubleValue(["value" => 2.2])], + [null, null], + [0, new DoubleValue()], + ]], + [TestWrapperSetters::class, FloatValue::class, "setFloatValue", "setFloatValueUnwrapped", "getFloatValue", "getFloatValueUnwrapped", [ + [1.1, new FloatValue(["value" => 1.1])], + [2.2, new FloatValue(["value" => 2.2])], + [null, null], + [0, new FloatValue()], + ]], + [TestWrapperSetters::class, Int64Value::class, "setInt64Value", "setInt64ValueUnwrapped", "getInt64Value", "getInt64ValueUnwrapped", [ + [123, new Int64Value(["value" => 123])], + [-789, new Int64Value(["value" => -789])], + [null, null], + [0, new Int64Value()], + [5.5, new Int64Value(["value" => 5])], // Test conversion from float to int + ]], + [TestWrapperSetters::class, UInt64Value::class, "setUInt64Value", "setUInt64ValueUnwrapped", "getUInt64Value", "getUInt64ValueUnwrapped", [ + [123, new UInt64Value(["value" => 123])], + [789, new UInt64Value(["value" => 789])], + [null, null], + [0, new UInt64Value()], + [5.5, new UInt64Value(["value" => 5])], // Test conversion from float to int + [-7, new UInt64Value(["value" => -7])], // Test conversion from -ve to +ve + ]], + [TestWrapperSetters::class, Int32Value::class, "setInt32Value", "setInt32ValueUnwrapped", "getInt32Value", "getInt32ValueUnwrapped", [ + [123, new Int32Value(["value" => 123])], + [-789, new Int32Value(["value" => -789])], + [null, null], + [0, new Int32Value()], + [5.5, new Int32Value(["value" => 5])], // Test conversion from float to int + ]], + [TestWrapperSetters::class, UInt32Value::class, "setUInt32Value", "setUInt32ValueUnwrapped", "getUInt32Value", "getUInt32ValueUnwrapped", [ + [123, new UInt32Value(["value" => 123])], + [789, new UInt32Value(["value" => 789])], + [null, null], + [0, new UInt32Value()], + [5.5, new UInt32Value(["value" => 5])], // Test conversion from float to int + [-7, new UInt32Value(["value" => -7])], // Test conversion from -ve to +ve + ]], + [TestWrapperSetters::class, BoolValue::class, "setBoolValue", "setBoolValueUnwrapped", "getBoolValue", "getBoolValueUnwrapped", [ + [true, new BoolValue(["value" => true])], + [false, new BoolValue(["value" => false])], + [null, null], + ]], + [TestWrapperSetters::class, StringValue::class, "setStringValue", "setStringValueUnwrapped", "getStringValue", "getStringValueUnwrapped", [ + ["asdf", new StringValue(["value" => "asdf"])], + ["", new StringValue(["value" => ""])], + [null, null], + ["", new StringValue()], + [5, new StringValue(["value" => "5"])], // Test conversion from number to string + [5.5, new StringValue(["value" => "5.5"])], // Test conversion from number to string + [-7, new StringValue(["value" => "-7"])], // Test conversion from number to string + [-7.5, new StringValue(["value" => "-7.5"])], // Test conversion from number to string + ]], + [TestWrapperSetters::class, BytesValue::class, "setBytesValue", "setBytesValueUnwrapped", "getBytesValue", "getBytesValueUnwrapped", [ + ["asdf", new BytesValue(["value" => "asdf"])], + ["", new BytesValue(["value" => ""])], + [null, null], + ["", new BytesValue()], + [5, new BytesValue(["value" => "5"])], // Test conversion from number to bytes + [5.5, new BytesValue(["value" => "5.5"])], // Test conversion from number to bytes + [-7, new BytesValue(["value" => "-7"])], // Test conversion from number to bytes + [-7.5, new BytesValue(["value" => "-7.5"])], // Test conversion from number to bytes + ]], + [TestWrapperSetters::class, DoubleValue::class, "setDoubleValueOneof", "setDoubleValueOneofUnwrapped", "getDoubleValueOneof", "getDoubleValueOneofUnwrapped", [ + [1.1, new DoubleValue(["value" => 1.1])], + [2.2, new DoubleValue(["value" => 2.2])], + [null, null], + [0, new DoubleValue()], + ]], + [TestWrapperSetters::class, StringValue::class, "setStringValueOneof", "setStringValueOneofUnwrapped", "getStringValueOneof", "getStringValueOneofUnwrapped", [ + ["asdf", new StringValue(["value" => "asdf"])], + ["", new StringValue(["value" => ""])], + [null, null], + ["", new StringValue()], + [5, new StringValue(["value" => "5"])], // Test conversion from number to string + [5.5, new StringValue(["value" => "5.5"])], // Test conversion from number to string + [-7, new StringValue(["value" => "-7"])], // Test conversion from number to string + [-7.5, new StringValue(["value" => "-7.5"])], // Test conversion from number to string + ]], + ]; + } + + /** + * @dataProvider invalidSettersDataProvider + */ + public function testInvalidSetters($class, $setter, $value) + { + $this->expectException(Exception::class); + (new $class())->$setter($value); + } + + public function invalidSettersDataProvider() + { + return [ + [TestWrapperSetters::class, "setDoubleValueUnwrapped", "abc"], + [TestWrapperSetters::class, "setDoubleValueUnwrapped", []], + [TestWrapperSetters::class, "setDoubleValueUnwrapped", new stdClass()], + [TestWrapperSetters::class, "setDoubleValueUnwrapped", new DoubleValue()], + + [TestWrapperSetters::class, "setFloatValueUnwrapped", "abc"], + [TestWrapperSetters::class, "setFloatValueUnwrapped", []], + [TestWrapperSetters::class, "setFloatValueUnwrapped", new stdClass()], + [TestWrapperSetters::class, "setFloatValueUnwrapped", new FloatValue()], + + [TestWrapperSetters::class, "setInt64ValueUnwrapped", "abc"], + [TestWrapperSetters::class, "setInt64ValueUnwrapped", []], + [TestWrapperSetters::class, "setInt64ValueUnwrapped", new stdClass()], + [TestWrapperSetters::class, "setInt64ValueUnwrapped", new Int64Value()], + + [TestWrapperSetters::class, "setUInt64ValueUnwrapped", "abc"], + [TestWrapperSetters::class, "setUInt64ValueUnwrapped", []], + [TestWrapperSetters::class, "setUInt64ValueUnwrapped", new stdClass()], + [TestWrapperSetters::class, "setUInt64ValueUnwrapped", new UInt64Value()], + + [TestWrapperSetters::class, "setInt32ValueUnwrapped", "abc"], + [TestWrapperSetters::class, "setInt32ValueUnwrapped", []], + [TestWrapperSetters::class, "setInt32ValueUnwrapped", new stdClass()], + [TestWrapperSetters::class, "setInt32ValueUnwrapped", new Int32Value()], + + [TestWrapperSetters::class, "setUInt32ValueUnwrapped", "abc"], + [TestWrapperSetters::class, "setUInt32ValueUnwrapped", []], + [TestWrapperSetters::class, "setUInt32ValueUnwrapped", new stdClass()], + [TestWrapperSetters::class, "setUInt32ValueUnwrapped", new UInt32Value()], + + [TestWrapperSetters::class, "setBoolValueUnwrapped", []], + [TestWrapperSetters::class, "setBoolValueUnwrapped", new stdClass()], + [TestWrapperSetters::class, "setBoolValueUnwrapped", new BoolValue()], + + [TestWrapperSetters::class, "setStringValueUnwrapped", []], + [TestWrapperSetters::class, "setStringValueUnwrapped", new stdClass()], + [TestWrapperSetters::class, "setStringValueUnwrapped", new StringValue()], + + [TestWrapperSetters::class, "setBytesValueUnwrapped", []], + [TestWrapperSetters::class, "setBytesValueUnwrapped", new stdClass()], + [TestWrapperSetters::class, "setBytesValueUnwrapped", new BytesValue()], + ]; + } + + /** + * @dataProvider constructorWithWrapperTypeDataProvider + */ + public function testConstructorWithWrapperType($class, $wrapperClass, $wrapperField, $getter, $value) + { + $actualInstance = new $class([$wrapperField => $value]); + $expectedInstance = new $class([$wrapperField => new $wrapperClass(['value' => $value])]); + $this->assertEquals($expectedInstance->$getter()->getValue(), $actualInstance->$getter()->getValue()); + } + + public function constructorWithWrapperTypeDataProvider() + { + return [ + [TestWrapperSetters::class, DoubleValue::class, 'double_value', 'getDoubleValue', 1.1], + [TestWrapperSetters::class, FloatValue::class, 'float_value', 'getFloatValue', 2.2], + [TestWrapperSetters::class, Int64Value::class, 'int64_value', 'getInt64Value', 3], + [TestWrapperSetters::class, UInt64Value::class, 'uint64_value', 'getUInt64Value', 4], + [TestWrapperSetters::class, Int32Value::class, 'int32_value', 'getInt32Value', 5], + [TestWrapperSetters::class, UInt32Value::class, 'uint32_value', 'getUInt32Value', 6], + [TestWrapperSetters::class, BoolValue::class, 'bool_value', 'getBoolValue', true], + [TestWrapperSetters::class, StringValue::class, 'string_value', 'getStringValue', "eight"], + [TestWrapperSetters::class, BytesValue::class, 'bytes_value', 'getBytesValue', "nine"], + ]; + } + + /** + * @dataProvider constructorWithRepeatedWrapperTypeDataProvider + */ + public function testConstructorWithRepeatedWrapperType($wrapperField, $getter, $value) + { + $actualInstance = new TestWrapperSetters([$wrapperField => $value]); + foreach ($actualInstance->$getter() as $key => $actualWrapperValue) { + $actualInnerValue = $actualWrapperValue->getValue(); + $expectedElement = $value[$key]; + if (is_object($expectedElement) && is_a($expectedElement, '\Google\Protobuf\StringValue')) { + $expectedInnerValue = $expectedElement->getValue(); + } else { + $expectedInnerValue = $expectedElement; + } + $this->assertEquals($expectedInnerValue, $actualInnerValue); + } + + $this->assertTrue(true); + } + + public function constructorWithRepeatedWrapperTypeDataProvider() + { + $sv7 = new StringValue(['value' => 'seven']); + $sv8 = new StringValue(['value' => 'eight']); + + $testWrapperSetters = new TestWrapperSetters(); + $testWrapperSetters->setRepeatedStringValue([$sv7, $sv8]); + $repeatedField = $testWrapperSetters->getRepeatedStringValue(); + + return [ + ['repeated_string_value', 'getRepeatedStringValue', []], + ['repeated_string_value', 'getRepeatedStringValue', [$sv7]], + ['repeated_string_value', 'getRepeatedStringValue', [$sv7, $sv8]], + ['repeated_string_value', 'getRepeatedStringValue', ['seven']], + ['repeated_string_value', 'getRepeatedStringValue', [7]], + ['repeated_string_value', 'getRepeatedStringValue', [7.7]], + ['repeated_string_value', 'getRepeatedStringValue', ['seven', 'eight']], + ['repeated_string_value', 'getRepeatedStringValue', [$sv7, 'eight']], + ['repeated_string_value', 'getRepeatedStringValue', ['seven', $sv8]], + ['repeated_string_value', 'getRepeatedStringValue', $repeatedField], + ]; + } + + /** + * @dataProvider constructorWithMapWrapperTypeDataProvider + */ + public function testConstructorWithMapWrapperType($wrapperField, $getter, $value) + { + $actualInstance = new TestWrapperSetters([$wrapperField => $value]); + foreach ($actualInstance->$getter() as $key => $actualWrapperValue) { + $actualInnerValue = $actualWrapperValue->getValue(); + $expectedElement = $value[$key]; + if (is_object($expectedElement) && is_a($expectedElement, '\Google\Protobuf\StringValue')) { + $expectedInnerValue = $expectedElement->getValue(); + } elseif (is_object($expectedElement) && is_a($expectedElement, '\Google\Protobuf\Internal\MapEntry')) { + $expectedInnerValue = $expectedElement->getValue()->getValue(); + } else { + $expectedInnerValue = $expectedElement; + } + $this->assertEquals($expectedInnerValue, $actualInnerValue); + } + + $this->assertTrue(true); + } + + public function constructorWithMapWrapperTypeDataProvider() + { + $sv7 = new StringValue(['value' => 'seven']); + $sv8 = new StringValue(['value' => 'eight']); + + $testWrapperSetters = new TestWrapperSetters(); + $testWrapperSetters->setMapStringValue(['key' => $sv7, 'key2' => $sv8]); + $mapField = $testWrapperSetters->getMapStringValue(); + + return [ + ['map_string_value', 'getMapStringValue', []], + ['map_string_value', 'getMapStringValue', ['key' => $sv7]], + ['map_string_value', 'getMapStringValue', ['key' => $sv7, 'key2' => $sv8]], + ['map_string_value', 'getMapStringValue', ['key' => 'seven']], + ['map_string_value', 'getMapStringValue', ['key' => 7]], + ['map_string_value', 'getMapStringValue', ['key' => 7.7]], + ['map_string_value', 'getMapStringValue', ['key' => 'seven', 'key2' => 'eight']], + ['map_string_value', 'getMapStringValue', ['key' => $sv7, 'key2' => 'eight']], + ['map_string_value', 'getMapStringValue', ['key' => 'seven', 'key2' => $sv8]], + ['map_string_value', 'getMapStringValue', $mapField], + ]; + } +} diff --git a/php/tests/array_test.php b/php/tests/array_test.php deleted file mode 100644 index 1a26d72a88b61..0000000000000 --- a/php/tests/array_test.php +++ /dev/null @@ -1,554 +0,0 @@ -assertSame(MAX_INT32, $arr[0]); - $arr[] = MIN_INT32; - $this->assertSame(MIN_INT32, $arr[1]); - - $arr[] = 1.1; - $this->assertSame(1, $arr[2]); - $arr[] = MAX_INT32_FLOAT; - $this->assertSame(MAX_INT32, $arr[3]); - $arr[] = MAX_INT32_FLOAT; - $this->assertSame(MAX_INT32, $arr[4]); - - $arr[] = '2'; - $this->assertSame(2, $arr[5]); - $arr[] = '3.1'; - $this->assertSame(3, $arr[6]); - $arr[] = MAX_INT32_STRING; - $this->assertSame(MAX_INT32, $arr[7]); - - $this->assertEquals(8, count($arr)); - - for ($i = 0; $i < count($arr); $i++) { - $arr[$i] = 0; - $this->assertSame(0, $arr[$i]); - } - - // Test set. - $arr[0] = MAX_INT32; - $this->assertSame(MAX_INT32, $arr[0]); - $arr[1] = MIN_INT32; - $this->assertSame(MIN_INT32, $arr[1]); - - $arr[2] = 1.1; - $this->assertSame(1, $arr[2]); - $arr[3] = MAX_INT32_FLOAT; - $this->assertSame(MAX_INT32, $arr[3]); - $arr[4] = MAX_INT32_FLOAT; - $this->assertSame(MAX_INT32, $arr[4]); - - $arr[5] = '2'; - $this->assertSame(2, $arr[5]); - $arr[6] = '3.1'; - $this->assertSame(3, $arr[6]); - $arr[7] = MAX_INT32_STRING; - $this->assertSame(MAX_INT32, $arr[7]); - - // Test foreach. - $arr = new RepeatedField(GPBType::INT32); - for ($i = 0; $i < 3; $i++) { - $arr[] = $i; - } - $i = 0; - foreach ($arr as $val) { - $this->assertSame($i++, $val); - } - $this->assertSame(3, $i); - } - - ######################################################### - # Test uint32 field. - ######################################################### - - public function testUint32() - { - $arr = new RepeatedField(GPBType::UINT32); - - // Test append. - $arr[] = MAX_UINT32; - $this->assertSame(-1, $arr[0]); - $arr[] = -1; - $this->assertSame(-1, $arr[1]); - $arr[] = MIN_UINT32; - $this->assertSame(MIN_UINT32, $arr[2]); - - $arr[] = 1.1; - $this->assertSame(1, $arr[3]); - $arr[] = MAX_UINT32_FLOAT; - $this->assertSame(-1, $arr[4]); - $arr[] = -1.0; - $this->assertSame(-1, $arr[5]); - $arr[] = MIN_UINT32_FLOAT; - $this->assertSame(MIN_UINT32, $arr[6]); - - $arr[] = '2'; - $this->assertSame(2, $arr[7]); - $arr[] = '3.1'; - $this->assertSame(3, $arr[8]); - $arr[] = MAX_UINT32_STRING; - $this->assertSame(-1, $arr[9]); - $arr[] = '-1.0'; - $this->assertSame(-1, $arr[10]); - $arr[] = MIN_UINT32_STRING; - $this->assertSame(MIN_UINT32, $arr[11]); - - $this->assertEquals(12, count($arr)); - - for ($i = 0; $i < count($arr); $i++) { - $arr[$i] = 0; - $this->assertSame(0, $arr[$i]); - } - - // Test set. - $arr[0] = MAX_UINT32; - $this->assertSame(-1, $arr[0]); - $arr[1] = -1; - $this->assertSame(-1, $arr[1]); - $arr[2] = MIN_UINT32; - $this->assertSame(MIN_UINT32, $arr[2]); - - $arr[3] = 1.1; - $this->assertSame(1, $arr[3]); - $arr[4] = MAX_UINT32_FLOAT; - $this->assertSame(-1, $arr[4]); - $arr[5] = -1.0; - $this->assertSame(-1, $arr[5]); - $arr[6] = MIN_UINT32_FLOAT; - $this->assertSame(MIN_UINT32, $arr[6]); - - $arr[7] = '2'; - $this->assertSame(2, $arr[7]); - $arr[8] = '3.1'; - $this->assertSame(3, $arr[8]); - $arr[9] = MAX_UINT32_STRING; - $this->assertSame(-1, $arr[9]); - $arr[10] = '-1.0'; - $this->assertSame(-1, $arr[10]); - $arr[11] = MIN_UINT32_STRING; - $this->assertSame(MIN_UINT32, $arr[11]); - } - - ######################################################### - # Test int64 field. - ######################################################### - - public function testInt64() - { - $arr = new RepeatedField(GPBType::INT64); - - // Test append. - $arr[] = MAX_INT64; - $arr[] = MIN_INT64; - $arr[] = 1.1; - $arr[] = '2'; - $arr[] = '3.1'; - $arr[] = MAX_INT64_STRING; - $arr[] = MIN_INT64_STRING; - if (PHP_INT_SIZE == 4) { - $this->assertSame(MAX_INT64, $arr[0]); - $this->assertSame(MIN_INT64, $arr[1]); - $this->assertSame('1', $arr[2]); - $this->assertSame('2', $arr[3]); - $this->assertSame('3', $arr[4]); - $this->assertSame(MAX_INT64_STRING, $arr[5]); - $this->assertSame(MIN_INT64_STRING, $arr[6]); - } else { - $this->assertSame(MAX_INT64, $arr[0]); - $this->assertSame(MIN_INT64, $arr[1]); - $this->assertSame(1, $arr[2]); - $this->assertSame(2, $arr[3]); - $this->assertSame(3, $arr[4]); - $this->assertSame(MAX_INT64, $arr[5]); - $this->assertSame(MIN_INT64, $arr[6]); - } - - - $this->assertEquals(7, count($arr)); - - for ($i = 0; $i < count($arr); $i++) { - $arr[$i] = 0; - if (PHP_INT_SIZE == 4) { - $this->assertSame('0', $arr[$i]); - } else { - $this->assertSame(0, $arr[$i]); - } - } - - // Test set. - $arr[0] = MAX_INT64; - $arr[1] = MIN_INT64; - $arr[2] = 1.1; - $arr[3] = '2'; - $arr[4] = '3.1'; - $arr[5] = MAX_INT64_STRING; - $arr[6] = MIN_INT64_STRING; - - if (PHP_INT_SIZE == 4) { - $this->assertSame(MAX_INT64_STRING, $arr[0]); - $this->assertSame(MIN_INT64_STRING, $arr[1]); - $this->assertSame('1', $arr[2]); - $this->assertSame('2', $arr[3]); - $this->assertSame('3', $arr[4]); - $this->assertSame(MAX_INT64_STRING, $arr[5]); - $this->assertEquals(MIN_INT64_STRING, $arr[6]); - } else { - $this->assertSame(MAX_INT64, $arr[0]); - $this->assertSame(MIN_INT64, $arr[1]); - $this->assertSame(1, $arr[2]); - $this->assertSame(2, $arr[3]); - $this->assertSame(3, $arr[4]); - $this->assertSame(MAX_INT64, $arr[5]); - $this->assertEquals(MIN_INT64, $arr[6]); - } - } - - ######################################################### - # Test uint64 field. - ######################################################### - - public function testUint64() - { - $arr = new RepeatedField(GPBType::UINT64); - - // Test append. - $arr[] = MAX_UINT64; - $arr[] = 1.1; - $arr[] = '2'; - $arr[] = '3.1'; - $arr[] = MAX_UINT64_STRING; - - if (PHP_INT_SIZE == 4) { - $this->assertSame(MAX_UINT64_STRING, $arr[0]); - $this->assertSame('1', $arr[1]); - $this->assertSame('2', $arr[2]); - $this->assertSame('3', $arr[3]); - $this->assertSame(MAX_UINT64_STRING, $arr[4]); - } else { - $this->assertSame(MAX_UINT64, $arr[0]); - $this->assertSame(1, $arr[1]); - $this->assertSame(2, $arr[2]); - $this->assertSame(3, $arr[3]); - $this->assertSame(MAX_UINT64, $arr[4]); - $this->assertSame(5, count($arr)); - } - - $this->assertSame(5, count($arr)); - - for ($i = 0; $i < count($arr); $i++) { - $arr[$i] = 0; - if (PHP_INT_SIZE == 4) { - $this->assertSame('0', $arr[$i]); - } else { - $this->assertSame(0, $arr[$i]); - } - } - - // Test set. - $arr[0] = MAX_UINT64; - $arr[1] = 1.1; - $arr[2] = '2'; - $arr[3] = '3.1'; - $arr[4] = MAX_UINT64_STRING; - - if (PHP_INT_SIZE == 4) { - $this->assertSame(MAX_UINT64_STRING, $arr[0]); - $this->assertSame('1', $arr[1]); - $this->assertSame('2', $arr[2]); - $this->assertSame('3', $arr[3]); - $this->assertSame(MAX_UINT64_STRING, $arr[4]); - } else { - $this->assertSame(MAX_UINT64, $arr[0]); - $this->assertSame(1, $arr[1]); - $this->assertSame(2, $arr[2]); - $this->assertSame(3, $arr[3]); - $this->assertSame(MAX_UINT64, $arr[4]); - } - } - - ######################################################### - # Test float field. - ######################################################### - - public function testFloat() - { - $arr = new RepeatedField(GPBType::FLOAT); - - // Test append. - $arr[] = 1; - $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF); - - $arr[] = 1.1; - $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF); - - $arr[] = '2'; - $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF); - $arr[] = '3.1'; - $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF); - - $this->assertEquals(4, count($arr)); - - for ($i = 0; $i < count($arr); $i++) { - $arr[$i] = 0; - $this->assertSame(0.0, $arr[$i]); - } - - // Test set. - $arr[0] = 1; - $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF); - - $arr[1] = 1.1; - $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF); - - $arr[2] = '2'; - $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF); - $arr[3] = '3.1'; - $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF); - } - - ######################################################### - # Test double field. - ######################################################### - - public function testDouble() - { - $arr = new RepeatedField(GPBType::DOUBLE); - - // Test append. - $arr[] = 1; - $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF); - - $arr[] = 1.1; - $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF); - - $arr[] = '2'; - $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF); - $arr[] = '3.1'; - $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF); - - $this->assertEquals(4, count($arr)); - - for ($i = 0; $i < count($arr); $i++) { - $arr[$i] = 0; - $this->assertSame(0.0, $arr[$i]); - } - - // Test set. - $arr[0] = 1; - $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF); - - $arr[1] = 1.1; - $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF); - - $arr[2] = '2'; - $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF); - $arr[3] = '3.1'; - $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF); - } - - ######################################################### - # Test bool field. - ######################################################### - - public function testBool() - { - $arr = new RepeatedField(GPBType::BOOL); - - // Test append. - $arr[] = true; - $this->assertSame(true, $arr[0]); - - $arr[] = -1; - $this->assertSame(true, $arr[1]); - - $arr[] = 1.1; - $this->assertSame(true, $arr[2]); - - $arr[] = ''; - $this->assertSame(false, $arr[3]); - - $this->assertEquals(4, count($arr)); - - for ($i = 0; $i < count($arr); $i++) { - $arr[$i] = 0; - $this->assertSame(false, $arr[$i]); - } - - // Test set. - $arr[0] = true; - $this->assertSame(true, $arr[0]); - - $arr[1] = -1; - $this->assertSame(true, $arr[1]); - - $arr[2] = 1.1; - $this->assertSame(true, $arr[2]); - - $arr[3] = ''; - $this->assertSame(false, $arr[3]); - } - - ######################################################### - # Test string field. - ######################################################### - - public function testString() - { - $arr = new RepeatedField(GPBType::STRING); - - // Test append. - $arr[] = 'abc'; - $this->assertSame('abc', $arr[0]); - - $arr[] = 1; - $this->assertSame('1', $arr[1]); - - $arr[] = 1.1; - $this->assertSame('1.1', $arr[2]); - - $arr[] = true; - $this->assertSame('1', $arr[3]); - - $this->assertEquals(4, count($arr)); - - for ($i = 0; $i < count($arr); $i++) { - $arr[$i] = ''; - $this->assertSame('', $arr[$i]); - } - - // Test set. - $arr[0] = 'abc'; - $this->assertSame('abc', $arr[0]); - - $arr[1] = 1; - $this->assertSame('1', $arr[1]); - - $arr[2] = 1.1; - $this->assertSame('1.1', $arr[2]); - - $arr[3] = true; - $this->assertSame('1', $arr[3]); - } - - ######################################################### - # Test message field. - ######################################################### - - public function testMessage() - { - $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class); - - // Test append. - $sub_m = new TestMessage_Sub(); - $sub_m->setA(1); - $arr[] = $sub_m; - $this->assertSame(1, $arr[0]->getA()); - - $this->assertEquals(1, count($arr)); - - // Test set. - $sub_m = new TestMessage_Sub(); - $sub_m->setA(2); - $arr[0] = $sub_m; - $this->assertSame(2, $arr[0]->getA()); - - // Test foreach. - $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class); - for ($i = 0; $i < 3; $i++) { - $arr[] = new TestMessage_Sub(); - $arr[$i]->setA($i); - } - $i = 0; - foreach ($arr as $val) { - $this->assertSame($i++, $val->getA()); - } - $this->assertSame(3, $i); - } - - ######################################################### - # Test offset type - ######################################################### - - public function testOffset() - { - $arr = new RepeatedField(GPBType::INT32); - $arr[] = 0; - - $arr[0] = 1; - $this->assertSame(1, $arr[0]); - $this->assertSame(1, count($arr)); - - $arr['0'] = 2; - $this->assertSame(2, $arr['0']); - $this->assertSame(2, $arr[0]); - $this->assertSame(1, count($arr)); - - $arr[0.0] = 3; - $this->assertSame(3, $arr[0.0]); - $this->assertSame(1, count($arr)); - } - - public function testInsertRemoval() - { - $arr = new RepeatedField(GPBType::INT32); - - $arr[] = 0; - $arr[] = 1; - $arr[] = 2; - $this->assertSame(3, count($arr)); - - unset($arr[2]); - $this->assertSame(2, count($arr)); - $this->assertSame(0, $arr[0]); - $this->assertSame(1, $arr[1]); - - $arr[] = 3; - $this->assertSame(3, count($arr)); - $this->assertSame(0, $arr[0]); - $this->assertSame(1, $arr[1]); - $this->assertSame(3, $arr[2]); - } - - ######################################################### - # Test memory leak - ######################################################### - - public function testCycleLeak() - { - gc_collect_cycles(); - $arr = new RepeatedField(GPBType::MESSAGE, TestMessage::class); - $arr[] = new TestMessage; - $arr[0]->SetRepeatedRecursive($arr); - - // Clean up memory before test. - gc_collect_cycles(); - $start = memory_get_usage(); - unset($arr); - - // Explicitly trigger garbage collection. - gc_collect_cycles(); - - $end = memory_get_usage(); - $this->assertLessThan($start, $end); - } -} diff --git a/php/tests/autoload.php b/php/tests/autoload.php old mode 100755 new mode 100644 index 0a917fc51a4a5..b98b13abdfc47 --- a/php/tests/autoload.php +++ b/php/tests/autoload.php @@ -1,5 +1,7 @@ getDescriptorByClassName(get_class(new TestDescriptorsMessage())); - $this->assertInstanceOf('\Google\Protobuf\Descriptor', $desc); - - $enumDesc = $pool->getEnumDescriptorByClassName(get_class(new TestDescriptorsEnum())); - $this->assertInstanceOf('\Google\Protobuf\EnumDescriptor', $enumDesc); - } - - public function testDescriptorPoolIncorrectArgs() - { - $pool = DescriptorPool::getGeneratedPool(); - - $desc = $pool->getDescriptorByClassName('NotAClass'); - $this->assertNull($desc); - - $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsEnum())); - $this->assertNull($desc); - - $enumDesc = $pool->getEnumDescriptorByClassName(get_class(new TestDescriptorsMessage())); - $this->assertNull($enumDesc); - } - - ######################################################### - # Test descriptor. - ######################################################### - - public function testDescriptor() - { - $pool = DescriptorPool::getGeneratedPool(); - $class = get_class(new TestDescriptorsMessage()); - $this->assertSame('Descriptors\TestDescriptorsMessage', $class); - $desc = $pool->getDescriptorByClassName($class); - - $this->assertSame('descriptors.TestDescriptorsMessage', $desc->getFullName()); - $this->assertSame($class, $desc->getClass()); - - $this->assertInstanceOf('\Google\Protobuf\FieldDescriptor', $desc->getField(0)); - $this->assertSame(7, $desc->getFieldCount()); - - $this->assertInstanceOf('\Google\Protobuf\OneofDescriptor', $desc->getOneofDecl(0)); - $this->assertSame(1, $desc->getOneofDeclCount()); - } - - ######################################################### - # Test enum descriptor. - ######################################################### - - public function testEnumDescriptor() - { - // WARNINIG - we need to do this so that TestDescriptorsEnum is registered!!? - new TestDescriptorsMessage(); - - $pool = DescriptorPool::getGeneratedPool(); - - $enumDesc = $pool->getEnumDescriptorByClassName(get_class(new TestDescriptorsEnum())); - - // Build map of enum values - $enumDescMap = []; - for ($i = 0; $i < $enumDesc->getValueCount(); $i++) { - $enumValueDesc = $enumDesc->getValue($i); - $this->assertInstanceOf('\Google\Protobuf\EnumValueDescriptor', $enumValueDesc); - $enumDescMap[$enumValueDesc->getNumber()] = $enumValueDesc->getName(); - } - - $this->assertSame('ZERO', $enumDescMap[0]); - $this->assertSame('ONE', $enumDescMap[1]); - - $this->assertSame(2, $enumDesc->getValueCount()); - } - - ######################################################### - # Test field descriptor. - ######################################################### - - public function testFieldDescriptor() - { - $pool = DescriptorPool::getGeneratedPool(); - $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage())); - - $fieldDescMap = $this->buildFieldMap($desc); - - // Optional int field - $fieldDesc = $fieldDescMap[1]; - $this->assertSame('optional_int32', $fieldDesc->getName()); - $this->assertSame(1, $fieldDesc->getNumber()); - $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel()); - $this->assertSame(self::GPBTYPE_INT32, $fieldDesc->getType()); - $this->assertFalse($fieldDesc->isMap()); - - // Optional enum field - $fieldDesc = $fieldDescMap[16]; - $this->assertSame('optional_enum', $fieldDesc->getName()); - $this->assertSame(16, $fieldDesc->getNumber()); - $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel()); - $this->assertSame(self::GPBTYPE_ENUM, $fieldDesc->getType()); - $this->assertInstanceOf('\Google\Protobuf\EnumDescriptor', $fieldDesc->getEnumType()); - $this->assertFalse($fieldDesc->isMap()); - - // Optional message field - $fieldDesc = $fieldDescMap[17]; - $this->assertSame('optional_message', $fieldDesc->getName()); - $this->assertSame(17, $fieldDesc->getNumber()); - $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel()); - $this->assertSame(self::GPBTYPE_MESSAGE, $fieldDesc->getType()); - $this->assertInstanceOf('\Google\Protobuf\Descriptor', $fieldDesc->getMessageType()); - $this->assertFalse($fieldDesc->isMap()); - - // Repeated int field - $fieldDesc = $fieldDescMap[31]; - $this->assertSame('repeated_int32', $fieldDesc->getName()); - $this->assertSame(31, $fieldDesc->getNumber()); - $this->assertSame(self::GPBLABEL_REPEATED, $fieldDesc->getLabel()); - $this->assertSame(self::GPBTYPE_INT32, $fieldDesc->getType()); - $this->assertFalse($fieldDesc->isMap()); - - // Repeated message field - $fieldDesc = $fieldDescMap[47]; - $this->assertSame('repeated_message', $fieldDesc->getName()); - $this->assertSame(47, $fieldDesc->getNumber()); - $this->assertSame(self::GPBLABEL_REPEATED, $fieldDesc->getLabel()); - $this->assertSame(self::GPBTYPE_MESSAGE, $fieldDesc->getType()); - $this->assertInstanceOf('\Google\Protobuf\Descriptor', $fieldDesc->getMessageType()); - $this->assertFalse($fieldDesc->isMap()); - - // Oneof int field - // Tested further in testOneofDescriptor() - $fieldDesc = $fieldDescMap[51]; - $this->assertSame('oneof_int32', $fieldDesc->getName()); - $this->assertSame(51, $fieldDesc->getNumber()); - $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel()); - $this->assertSame(self::GPBTYPE_INT32, $fieldDesc->getType()); - $this->assertFalse($fieldDesc->isMap()); - - // Map int-enum field - $fieldDesc = $fieldDescMap[71]; - $this->assertSame('map_int32_enum', $fieldDesc->getName()); - $this->assertSame(71, $fieldDesc->getNumber()); - $this->assertSame(self::GPBLABEL_REPEATED, $fieldDesc->getLabel()); - $this->assertSame(self::GPBTYPE_MESSAGE, $fieldDesc->getType()); - $this->assertTrue($fieldDesc->isMap()); - $mapDesc = $fieldDesc->getMessageType(); - $this->assertSame('descriptors.TestDescriptorsMessage.MapInt32EnumEntry', $mapDesc->getFullName()); - $this->assertSame(self::GPBTYPE_INT32, $mapDesc->getField(0)->getType()); - $this->assertSame(self::GPBTYPE_ENUM, $mapDesc->getField(1)->getType()); - } - - /** - * @expectedException \Exception - */ - public function testFieldDescriptorEnumException() - { - $pool = DescriptorPool::getGeneratedPool(); - $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage())); - $fieldDesc = $desc->getField(0); - $fieldDesc->getEnumType(); - } - - /** - * @expectedException \Exception - */ - public function testFieldDescriptorMessageException() - { - $pool = DescriptorPool::getGeneratedPool(); - $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage())); - $fieldDesc = $desc->getField(0); - $fieldDesc->getMessageType(); - } - - ######################################################### - # Test oneof descriptor. - ######################################################### - - public function testOneofDescriptor() - { - $pool = DescriptorPool::getGeneratedPool(); - $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage())); - - $fieldDescMap = $this->buildFieldMap($desc); - $fieldDesc = $fieldDescMap[51]; - - $oneofDesc = $desc->getOneofDecl(0); - - $this->assertSame('my_oneof', $oneofDesc->getName()); - $fieldDescFromOneof = $oneofDesc->getField(0); - $this->assertSame($fieldDesc, $fieldDescFromOneof); - $this->assertSame(1, $oneofDesc->getFieldCount()); - } - - private function buildFieldMap($desc) - { - $fieldDescMap = []; - for ($i = 0; $i < $desc->getFieldCount(); $i++) { - $fieldDesc = $desc->getField($i); - $fieldDescMap[$fieldDesc->getNumber()] = $fieldDesc; - } - return $fieldDescMap; - } -} diff --git a/php/tests/encode_decode_test.php b/php/tests/encode_decode_test.php deleted file mode 100644 index b43dffb4fe8d8..0000000000000 --- a/php/tests/encode_decode_test.php +++ /dev/null @@ -1,453 +0,0 @@ -expectEmptyFields($from); - $this->setFields($from); - $this->expectFields($from); - - $data = $from->serializeToString(); - $this->assertSame(bin2hex(TestUtil::getGoldenTestMessage()), - bin2hex($data)); - } - - public function testDecode() - { - $to = new TestMessage(); - $to->mergeFromString(TestUtil::getGoldenTestMessage()); - $this->expectFields($to); - } - - public function testEncodeDecode() - { - $from = new TestMessage(); - $this->expectEmptyFields($from); - $this->setFields($from); - $this->expectFields($from); - - $data = $from->serializeToString(); - - $to = new TestMessage(); - $to->mergeFromString($data); - $this->expectFields($to); - } - - public function testEncodeDecodeEmpty() - { - $from = new TestMessage(); - $this->expectEmptyFields($from); - - $data = $from->serializeToString(); - - $to = new TestMessage(); - $to->mergeFromString($data); - $this->expectEmptyFields($to); - } - - public function testEncodeDecodeOneof() - { - $m = new TestMessage(); - - $m->setOneofInt32(1); - $data = $m->serializeToString(); - $n = new TestMessage(); - $n->mergeFromString($data); - $this->assertSame(1, $n->getOneofInt32()); - - $m->setOneofFloat(2.0); - $data = $m->serializeToString(); - $n = new TestMessage(); - $n->mergeFromString($data); - $this->assertSame(2.0, $n->getOneofFloat()); - - $m->setOneofString('abc'); - $data = $m->serializeToString(); - $n = new TestMessage(); - $n->mergeFromString($data); - $this->assertSame('abc', $n->getOneofString()); - - $sub_m = new TestMessage_Sub(); - $sub_m->setA(1); - $m->setOneofMessage($sub_m); - $data = $m->serializeToString(); - $n = new TestMessage(); - $n->mergeFromString($data); - $this->assertSame(1, $n->getOneofMessage()->getA()); - - // Encode default value - $m->setOneofEnum(TestEnum::ZERO); - $data = $m->serializeToString(); - $n = new TestMessage(); - $n->mergeFromString($data); - $this->assertSame("oneof_enum", $n->getMyOneof()); - $this->assertSame(TestEnum::ZERO, $n->getOneofEnum()); - - $m->setOneofString(""); - $data = $m->serializeToString(); - $n = new TestMessage(); - $n->mergeFromString($data); - $this->assertSame("oneof_string", $n->getMyOneof()); - $this->assertSame("", $n->getOneofString()); - - $sub_m = new TestMessage_Sub(); - $m->setOneofMessage($sub_m); - $data = $m->serializeToString(); - $n = new TestMessage(); - $n->mergeFromString($data); - $this->assertSame("oneof_message", $n->getMyOneof()); - $this->assertFalse(is_null($n->getOneofMessage())); - - } - - public function testPackedEncode() - { - $from = new TestPackedMessage(); - TestUtil::setTestPackedMessage($from); - $this->assertSame(TestUtil::getGoldenTestPackedMessage(), - $from->serializeToString()); - } - - public function testPackedDecodePacked() - { - $to = new TestPackedMessage(); - $to->mergeFromString(TestUtil::getGoldenTestPackedMessage()); - TestUtil::assertTestPackedMessage($to); - } - - public function testPackedDecodeUnpacked() - { - $to = new TestPackedMessage(); - $to->mergeFromString(TestUtil::getGoldenTestUnpackedMessage()); - TestUtil::assertTestPackedMessage($to); - } - - public function testUnpackedEncode() - { - $from = new TestUnpackedMessage(); - TestUtil::setTestPackedMessage($from); - $this->assertSame(TestUtil::getGoldenTestUnpackedMessage(), - $from->serializeToString()); - } - - public function testUnpackedDecodePacked() - { - $to = new TestUnpackedMessage(); - $to->mergeFromString(TestUtil::getGoldenTestPackedMessage()); - TestUtil::assertTestPackedMessage($to); - } - - public function testUnpackedDecodeUnpacked() - { - $to = new TestUnpackedMessage(); - $to->mergeFromString(TestUtil::getGoldenTestUnpackedMessage()); - TestUtil::assertTestPackedMessage($to); - } - - public function testDecodeInt64() - { - // Read 64 testing - $testVals = array( - '10' => '100a', - '100' => '1064', - '800' => '10a006', - '6400' => '108032', - '70400' => '1080a604', - '774400' => '1080a22f', - '9292800' => '108098b704', - '74342400' => '1080c0b923', - '743424000' => '108080bfe202', - '8177664000' => '108080b5bb1e', - '65421312000' => '108080a8dbf301', - '785055744000' => '108080e0c7ec16', - '9420668928000' => '10808080dd969202', - '103627358208000' => '10808080fff9c717', - '1139900940288000' => '10808080f5bd978302', - '13678811283456000' => '10808080fce699a618', - '109430490267648000' => '10808080e0b7ceb1c201', - '984874412408832000' => '10808080e0f5c1bed50d', - ); - - $msg = new TestMessage(); - foreach ($testVals as $original => $encoded) { - $msg->setOptionalInt64($original); - $data = $msg->serializeToString(); - $this->assertSame($encoded, bin2hex($data)); - $msg->setOptionalInt64(0); - $msg->mergeFromString($data); - $this->assertEquals($original, $msg->getOptionalInt64()); - } - } - - public function testDecodeToExistingMessage() - { - $m1 = new TestMessage(); - $this->setFields($m1); - $this->expectFields($m1); - - $m2 = new TestMessage(); - $this->setFields2($m2); - $data = $m2->serializeToString(); - - $m1->mergeFromString($data); - $this->expectFieldsMerged($m1); - } - - public function testDecodeFieldNonExist() - { - $data = hex2bin('c80501'); - $m = new TestMessage(); - $m->mergeFromString($data); - } - - public function testEncodeNegativeInt32() - { - $m = new TestMessage(); - $m->setOptionalInt32(-1); - $data = $m->serializeToString(); - $this->assertSame("08ffffffffffffffffff01", bin2hex($data)); - } - - public function testDecodeNegativeInt32() - { - $m = new TestMessage(); - $this->assertEquals(0, $m->getOptionalInt32()); - $m->mergeFromString(hex2bin("08ffffffffffffffffff01")); - $this->assertEquals(-1, $m->getOptionalInt32()); - - $m = new TestMessage(); - $this->assertEquals(0, $m->getOptionalInt32()); - $m->mergeFromString(hex2bin("08ffffffff0f")); - $this->assertEquals(-1, $m->getOptionalInt32()); - } - - public function testRandomFieldOrder() - { - $m = new TestRandomFieldOrder(); - $data = $m->serializeToString(); - $this->assertSame("", $data); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidInt32() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('08')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidSubMessage() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('9A010108')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidInt64() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('10')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidUInt32() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('18')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidUInt64() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('20')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidSInt32() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('28')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidSInt64() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('30')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidFixed32() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('3D')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidFixed64() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('41')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidSFixed32() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('4D')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidSFixed64() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('51')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidFloat() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('5D')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidDouble() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('61')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidBool() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('68')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidStringLengthMiss() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('72')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidStringDataMiss() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('7201')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidBytesLengthMiss() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('7A')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidBytesDataMiss() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('7A01')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidEnum() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('8001')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidMessageLengthMiss() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('8A01')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidMessageDataMiss() - { - $m = new TestMessage(); - $m->mergeFromString(hex2bin('8A0101')); - } - - /** - * @expectedException Exception - */ - public function testDecodeInvalidPackedMessageLength() - { - $m = new TestPackedMessage(); - $m->mergeFromString(hex2bin('D205')); - } - - public function testJsonEncode() - { - $from = new TestMessage(); - $this->setFields($from); - $data = $from->serializeToJsonString(); - $to = new TestMessage(); - $to->mergeFromJsonString($data); - $this->expectFields($to); - } -} diff --git a/php/tests/gdb_test.sh b/php/tests/gdb_test.sh index 484e2edfbbc0e..76a0fc3b1989f 100755 --- a/php/tests/gdb_test.sh +++ b/php/tests/gdb_test.sh @@ -1,8 +1,11 @@ #!/bin/bash +php -i | grep "Configuration" + # gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which # phpunit` --bootstrap autoload.php tmp_test.php # +# gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php generated_class_test.php gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php encode_decode_test.php # # gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php diff --git a/php/tests/generate_protos.sh b/php/tests/generate_protos.sh new file mode 100755 index 0000000000000..e83c3c1c068de --- /dev/null +++ b/php/tests/generate_protos.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -ex + +cd `dirname $0` + +rm -rf generated +mkdir -p generated + +find proto -type f -name "*.proto"| xargs ../../src/protoc --experimental_allow_proto3_optional --php_out=generated -I../../src -I. + +if [ "$1" = "--aggregate_metadata" ]; then + # Overwrite some of the files to use aggregation. + AGGREGATED_FILES="proto/test.proto proto/test_include.proto proto/test_import_descriptor_proto.proto" + ../../src/protoc --experimental_allow_proto3_optional --php_out=aggregate_metadata=foo#bar:generated -I../../src -I. $AGGREGATED_FILES +fi diff --git a/php/tests/generated_class_test.php b/php/tests/generated_class_test.php deleted file mode 100644 index 86e68683c00d4..0000000000000 --- a/php/tests/generated_class_test.php +++ /dev/null @@ -1,718 +0,0 @@ -setOptionalInt32(1); - $this->assertSame(1, $m->getOptionalInt32()); - } - - ######################################################### - # Test int32 field. - ######################################################### - - public function testInt32Field() - { - $m = new TestMessage(); - - // Set integer. - $m->setOptionalInt32(MAX_INT32); - $this->assertSame(MAX_INT32, $m->getOptionalInt32()); - $m->setOptionalInt32(MIN_INT32); - $this->assertSame(MIN_INT32, $m->getOptionalInt32()); - - // Set float. - $m->setOptionalInt32(1.1); - $this->assertSame(1, $m->getOptionalInt32()); - $m->setOptionalInt32(MAX_INT32_FLOAT); - $this->assertSame(MAX_INT32, $m->getOptionalInt32()); - $m->setOptionalInt32(MIN_INT32_FLOAT); - $this->assertSame(MIN_INT32, $m->getOptionalInt32()); - - // Set string. - $m->setOptionalInt32('2'); - $this->assertSame(2, $m->getOptionalInt32()); - $m->setOptionalInt32('3.1'); - $this->assertSame(3, $m->getOptionalInt32()); - $m->setOptionalInt32(MAX_INT32_STRING); - $this->assertSame(MAX_INT32, $m->getOptionalInt32()); - $m->setOptionalInt32(MIN_INT32_STRING); - $this->assertSame(MIN_INT32, $m->getOptionalInt32()); - } - - ######################################################### - # Test uint32 field. - ######################################################### - - public function testUint32Field() - { - $m = new TestMessage(); - - // Set integer. - $m->setOptionalUint32(MAX_UINT32); - $this->assertSame(-1, $m->getOptionalUint32()); - $m->setOptionalUint32(-1); - $this->assertSame(-1, $m->getOptionalUint32()); - $m->setOptionalUint32(MIN_UINT32); - $this->assertSame(MIN_INT32, $m->getOptionalUint32()); - - // Set float. - $m->setOptionalUint32(1.1); - $this->assertSame(1, $m->getOptionalUint32()); - $m->setOptionalUint32(MAX_UINT32_FLOAT); - $this->assertSame(-1, $m->getOptionalUint32()); - $m->setOptionalUint32(-1.0); - $this->assertSame(-1, $m->getOptionalUint32()); - $m->setOptionalUint32(MIN_UINT32_FLOAT); - $this->assertSame(MIN_INT32, $m->getOptionalUint32()); - - // Set string. - $m->setOptionalUint32('2'); - $this->assertSame(2, $m->getOptionalUint32()); - $m->setOptionalUint32('3.1'); - $this->assertSame(3, $m->getOptionalUint32()); - $m->setOptionalUint32(MAX_UINT32_STRING); - $this->assertSame(-1, $m->getOptionalUint32()); - $m->setOptionalUint32('-1.0'); - $this->assertSame(-1, $m->getOptionalUint32()); - $m->setOptionalUint32(MIN_UINT32_STRING); - $this->assertSame(MIN_INT32, $m->getOptionalUint32()); - } - - ######################################################### - # Test int64 field. - ######################################################### - - public function testInt64Field() - { - $m = new TestMessage(); - - // Set integer. - $m->setOptionalInt64(MAX_INT64); - $this->assertSame(MAX_INT64, $m->getOptionalInt64()); - $m->setOptionalInt64(MIN_INT64); - $this->assertEquals(MIN_INT64, $m->getOptionalInt64()); - - // Set float. - $m->setOptionalInt64(1.1); - if (PHP_INT_SIZE == 4) { - $this->assertSame('1', $m->getOptionalInt64()); - } else { - $this->assertSame(1, $m->getOptionalInt64()); - } - - // Set string. - $m->setOptionalInt64('2'); - if (PHP_INT_SIZE == 4) { - $this->assertSame('2', $m->getOptionalInt64()); - } else { - $this->assertSame(2, $m->getOptionalInt64()); - } - - $m->setOptionalInt64('3.1'); - if (PHP_INT_SIZE == 4) { - $this->assertSame('3', $m->getOptionalInt64()); - } else { - $this->assertSame(3, $m->getOptionalInt64()); - } - - $m->setOptionalInt64(MAX_INT64_STRING); - if (PHP_INT_SIZE == 4) { - $this->assertSame(MAX_INT64_STRING, $m->getOptionalInt64()); - } else { - $this->assertSame(MAX_INT64, $m->getOptionalInt64()); - } - - $m->setOptionalInt64(MIN_INT64_STRING); - if (PHP_INT_SIZE == 4) { - $this->assertSame(MIN_INT64_STRING, $m->getOptionalInt64()); - } else { - $this->assertSame(MIN_INT64, $m->getOptionalInt64()); - } - } - - ######################################################### - # Test uint64 field. - ######################################################### - - public function testUint64Field() - { - $m = new TestMessage(); - - // Set integer. - $m->setOptionalUint64(MAX_UINT64); - if (PHP_INT_SIZE == 4) { - $this->assertSame(MAX_UINT64_STRING, $m->getOptionalUint64()); - } else { - $this->assertSame(MAX_UINT64, $m->getOptionalUint64()); - } - - // Set float. - $m->setOptionalUint64(1.1); - if (PHP_INT_SIZE == 4) { - $this->assertSame('1', $m->getOptionalUint64()); - } else { - $this->assertSame(1, $m->getOptionalUint64()); - } - - // Set string. - $m->setOptionalUint64('2'); - if (PHP_INT_SIZE == 4) { - $this->assertSame('2', $m->getOptionalUint64()); - } else { - $this->assertSame(2, $m->getOptionalUint64()); - } - - $m->setOptionalUint64('3.1'); - if (PHP_INT_SIZE == 4) { - $this->assertSame('3', $m->getOptionalUint64()); - } else { - $this->assertSame(3, $m->getOptionalUint64()); - } - - $m->setOptionalUint64(MAX_UINT64_STRING); - if (PHP_INT_SIZE == 4) { - $this->assertSame(MAX_UINT64_STRING, $m->getOptionalUint64()); - } else { - $this->assertSame(MAX_UINT64, $m->getOptionalUint64()); - } - } - - ######################################################### - # Test enum field. - ######################################################### - - public function testEnumField() - { - $m = new TestMessage(); - - // Set enum. - $m->setOptionalEnum(TestEnum::ONE); - $this->assertEquals(TestEnum::ONE, $m->getOptionalEnum()); - - // Set integer. - $m->setOptionalEnum(1); - $this->assertEquals(TestEnum::ONE, $m->getOptionalEnum()); - - // Set float. - $m->setOptionalEnum(1.1); - $this->assertEquals(TestEnum::ONE, $m->getOptionalEnum()); - - // Set string. - $m->setOptionalEnum("1"); - $this->assertEquals(TestEnum::ONE, $m->getOptionalEnum()); - } - - public function testNestedEnum() - { - $m = new TestMessage(); - $m->setOptionalNestedEnum(\Foo\TestMessage_NestedEnum::ZERO); - } - - ######################################################### - # Test float field. - ######################################################### - - public function testFloatField() - { - $m = new TestMessage(); - - // Set integer. - $m->setOptionalFloat(1); - $this->assertEquals(1.0, $m->getOptionalFloat(), '', MAX_FLOAT_DIFF); - - // Set float. - $m->setOptionalFloat(1.1); - $this->assertEquals(1.1, $m->getOptionalFloat(), '', MAX_FLOAT_DIFF); - - // Set string. - $m->setOptionalFloat('2'); - $this->assertEquals(2.0, $m->getOptionalFloat(), '', MAX_FLOAT_DIFF); - $m->setOptionalFloat('3.1'); - $this->assertEquals(3.1, $m->getOptionalFloat(), '', MAX_FLOAT_DIFF); - } - - ######################################################### - # Test double field. - ######################################################### - - public function testDoubleField() - { - $m = new TestMessage(); - - // Set integer. - $m->setOptionalDouble(1); - $this->assertEquals(1.0, $m->getOptionalDouble(), '', MAX_FLOAT_DIFF); - - // Set float. - $m->setOptionalDouble(1.1); - $this->assertEquals(1.1, $m->getOptionalDouble(), '', MAX_FLOAT_DIFF); - - // Set string. - $m->setOptionalDouble('2'); - $this->assertEquals(2.0, $m->getOptionalDouble(), '', MAX_FLOAT_DIFF); - $m->setOptionalDouble('3.1'); - $this->assertEquals(3.1, $m->getOptionalDouble(), '', MAX_FLOAT_DIFF); - } - - ######################################################### - # Test bool field. - ######################################################### - - public function testBoolField() - { - $m = new TestMessage(); - - // Set bool. - $m->setOptionalBool(true); - $this->assertSame(true, $m->getOptionalBool()); - - // Set integer. - $m->setOptionalBool(-1); - $this->assertSame(true, $m->getOptionalBool()); - - // Set float. - $m->setOptionalBool(1.1); - $this->assertSame(true, $m->getOptionalBool()); - - // Set string. - $m->setOptionalBool(''); - $this->assertSame(false, $m->getOptionalBool()); - } - - ######################################################### - # Test string field. - ######################################################### - - public function testStringField() - { - $m = new TestMessage(); - - // Set string. - $m->setOptionalString('abc'); - $this->assertSame('abc', $m->getOptionalString()); - - // Set integer. - $m->setOptionalString(1); - $this->assertSame('1', $m->getOptionalString()); - - // Set double. - $m->setOptionalString(1.1); - $this->assertSame('1.1', $m->getOptionalString()); - - // Set bool. - $m->setOptionalString(true); - $this->assertSame('1', $m->getOptionalString()); - } - - ######################################################### - # Test bytes field. - ######################################################### - - public function testBytesField() - { - $m = new TestMessage(); - - // Set string. - $m->setOptionalBytes('abc'); - $this->assertSame('abc', $m->getOptionalBytes()); - - // Set integer. - $m->setOptionalBytes(1); - $this->assertSame('1', $m->getOptionalBytes()); - - // Set double. - $m->setOptionalBytes(1.1); - $this->assertSame('1.1', $m->getOptionalBytes()); - - // Set bool. - $m->setOptionalBytes(true); - $this->assertSame('1', $m->getOptionalBytes()); - } - - public function testBytesFieldInvalidUTF8Success() - { - $m = new TestMessage(); - $hex = hex2bin("ff"); - $m->setOptionalBytes($hex); - } - - ######################################################### - # Test message field. - ######################################################### - - public function testMessageField() - { - $m = new TestMessage(); - - $sub_m = new TestMessage_Sub(); - $sub_m->setA(1); - $m->setOptionalMessage($sub_m); - $this->assertSame(1, $m->getOptionalMessage()->getA()); - - $null = null; - $m->setOptionalMessage($null); - $this->assertNull($m->getOptionalMessage()); - } - - ######################################################### - # Test repeated field. - ######################################################### - - public function testRepeatedField() - { - $m = new TestMessage(); - - $repeated_int32 = new RepeatedField(GPBType::INT32); - $m->setRepeatedInt32($repeated_int32); - $this->assertSame($repeated_int32, $m->getRepeatedInt32()); - } - - public function testRepeatedFieldViaArray() - { - $m = new TestMessage(); - - $arr = array(); - $m->setRepeatedInt32($arr); - $this->assertSame(0, count($m->getRepeatedInt32())); - - $arr = array(1, 2.1, "3"); - $m->setRepeatedInt32($arr); - $this->assertTrue($m->getRepeatedInt32() instanceof RepeatedField); - $this->assertSame("Google\Protobuf\Internal\RepeatedField", - get_class($m->getRepeatedInt32())); - $this->assertSame(3, count($m->getRepeatedInt32())); - $this->assertSame(1, $m->getRepeatedInt32()[0]); - $this->assertSame(2, $m->getRepeatedInt32()[1]); - $this->assertSame(3, $m->getRepeatedInt32()[2]); - $this->assertFalse($arr instanceof RepeatedField); - } - - ######################################################### - # Test map field. - ######################################################### - - public function testMapField() - { - $m = new TestMessage(); - - $map_int32_int32 = new MapField(GPBType::INT32, GPBType::INT32); - $m->setMapInt32Int32($map_int32_int32); - $this->assertSame($map_int32_int32, $m->getMapInt32Int32()); - } - - public function testMapFieldViaArray() - { - $m = new TestMessage(); - - $dict = array(); - $m->setMapInt32Int32($dict); - $this->assertSame(0, count($m->getMapInt32Int32())); - - $dict = array(5 => 5, 6.1 => 6.1, "7" => "7"); - $m->setMapInt32Int32($dict); - $this->assertTrue($m->getMapInt32Int32() instanceof MapField); - $this->assertSame(3, count($m->getMapInt32Int32())); - $this->assertSame(5, $m->getMapInt32Int32()[5]); - $this->assertSame(6, $m->getMapInt32Int32()[6]); - $this->assertSame(7, $m->getMapInt32Int32()[7]); - $this->assertFalse($dict instanceof MapField); - } - - ######################################################### - # Test oneof field. - ######################################################### - - public function testOneofField() { - $m = new TestMessage(); - - $this->assertSame("", $m->getMyOneof()); - - $m->setOneofInt32(1); - $this->assertSame(1, $m->getOneofInt32()); - $this->assertSame(0.0, $m->getOneofFloat()); - $this->assertSame('', $m->getOneofString()); - $this->assertSame(NULL, $m->getOneofMessage()); - $this->assertSame("oneof_int32", $m->getMyOneof()); - - $m->setOneofFloat(2.0); - $this->assertSame(0, $m->getOneofInt32()); - $this->assertSame(2.0, $m->getOneofFloat()); - $this->assertSame('', $m->getOneofString()); - $this->assertSame(NULL, $m->getOneofMessage()); - $this->assertSame("oneof_float", $m->getMyOneof()); - - $m->setOneofString('abc'); - $this->assertSame(0, $m->getOneofInt32()); - $this->assertSame(0.0, $m->getOneofFloat()); - $this->assertSame('abc', $m->getOneofString()); - $this->assertSame(NULL, $m->getOneofMessage()); - $this->assertSame("oneof_string", $m->getMyOneof()); - - $sub_m = new TestMessage_Sub(); - $sub_m->setA(1); - $m->setOneofMessage($sub_m); - $this->assertSame(0, $m->getOneofInt32()); - $this->assertSame(0.0, $m->getOneofFloat()); - $this->assertSame('', $m->getOneofString()); - $this->assertSame(1, $m->getOneofMessage()->getA()); - $this->assertSame("oneof_message", $m->getMyOneof()); - } - - ######################################################### - # Test clear method. - ######################################################### - - public function testMessageClear() - { - $m = new TestMessage(); - $this->setFields($m); - $this->expectFields($m); - $m->clear(); - $this->expectEmptyFields($m); - } - - ######################################################### - # Test mergeFrom method. - ######################################################### - - public function testMessageMergeFrom() - { - $m = new TestMessage(); - $this->setFields($m); - $this->expectFields($m); - $arr = $m->getOptionalMessage()->getB(); - $arr[] = 1; - - $n = new TestMessage(); - - // Singular - $n->setOptionalInt32(100); - $sub1 = new TestMessage_Sub(); - $sub1->setA(101); - - $b = $sub1->getB(); - $b[] = 102; - $sub1->setB($b); - - $n->setOptionalMessage($sub1); - - // Repeated - $repeatedInt32 = $n->getRepeatedInt32(); - $repeatedInt32[] = 200; - $n->setRepeatedInt32($repeatedInt32); - - $repeatedString = $n->getRepeatedString(); - $repeatedString[] = 'abc'; - $n->setRepeatedString($repeatedString); - - $sub2 = new TestMessage_Sub(); - $sub2->setA(201); - $repeatedMessage = $n->getRepeatedMessage(); - $repeatedMessage[] = $sub2; - $n->setRepeatedMessage($repeatedMessage); - - // Map - $mapInt32Int32 = $n->getMapInt32Int32(); - $mapInt32Int32[1] = 300; - $mapInt32Int32[-62] = 301; - $n->setMapInt32Int32($mapInt32Int32); - - $mapStringString = $n->getMapStringString(); - $mapStringString['def'] = 'def'; - $n->setMapStringString($mapStringString); - - $mapInt32Message = $n->getMapInt32Message(); - $mapInt32Message[1] = new TestMessage_Sub(); - $mapInt32Message[1]->setA(302); - $mapInt32Message[2] = new TestMessage_Sub(); - $mapInt32Message[2]->setA(303); - $n->setMapInt32Message($mapInt32Message); - - $m->mergeFrom($n); - - $this->assertSame(100, $m->getOptionalInt32()); - $this->assertSame(42, $m->getOptionalUint32()); - $this->assertSame(101, $m->getOptionalMessage()->getA()); - $this->assertSame(2, count($m->getOptionalMessage()->getB())); - $this->assertSame(1, $m->getOptionalMessage()->getB()[0]); - $this->assertSame(102, $m->getOptionalMessage()->getB()[1]); - - $this->assertSame(3, count($m->getRepeatedInt32())); - $this->assertSame(200, $m->getRepeatedInt32()[2]); - $this->assertSame(2, count($m->getRepeatedUint32())); - $this->assertSame(3, count($m->getRepeatedString())); - $this->assertSame('abc', $m->getRepeatedString()[2]); - $this->assertSame(3, count($m->getRepeatedMessage())); - $this->assertSame(201, $m->getRepeatedMessage()[2]->getA()); - - $this->assertSame(2, count($m->getMapInt32Int32())); - $this->assertSame(300, $m->getMapInt32Int32()[1]); - $this->assertSame(301, $m->getMapInt32Int32()[-62]); - $this->assertSame(1, count($m->getMapUint32Uint32())); - $this->assertSame(2, count($m->getMapStringString())); - $this->assertSame('def', $m->getMapStringString()['def']); - - $this->assertSame(2, count($m->getMapInt32Message())); - $this->assertSame(302, $m->getMapInt32Message()[1]->getA()); - $this->assertSame(303, $m->getMapInt32Message()[2]->getA()); - - $this->assertSame("", $m->getMyOneof()); - - // Check sub-messages are copied by value. - $n->getOptionalMessage()->setA(-101); - $this->assertSame(101, $m->getOptionalMessage()->getA()); - - $repeatedMessage = $n->getRepeatedMessage(); - $repeatedMessage[0]->setA(-201); - $n->setRepeatedMessage($repeatedMessage); - $this->assertSame(201, $m->getRepeatedMessage()[2]->getA()); - - $mapInt32Message = $n->getMapInt32Message(); - $mapInt32Message[1]->setA(-302); - $n->setMapInt32Message($mapInt32Message); - - $this->assertSame(302, $m->getMapInt32Message()[1]->getA()); - - // Test merge oneof. - $m = new TestMessage(); - - $n = new TestMessage(); - $n->setOneofInt32(1); - $m->mergeFrom($n); - $this->assertSame(1, $m->getOneofInt32()); - - $sub = new TestMessage_Sub(); - $n->setOneofMessage($sub); - $n->getOneofMessage()->setA(400); - $m->mergeFrom($n); - $this->assertSame(400, $m->getOneofMessage()->getA()); - $n->getOneofMessage()->setA(-400); - $this->assertSame(400, $m->getOneofMessage()->getA()); - - // Test all fields - $m = new TestMessage(); - $n = new TestMessage(); - $this->setFields($m); - $n->mergeFrom($m); - $this->expectFields($n); - } - - ######################################################### - # Test message/enum without namespace. - ######################################################### - - public function testMessageWithoutNamespace() - { - $m = new TestMessage(); - $sub = new NoNameSpaceMessage(); - $m->setOptionalNoNamespaceMessage($sub); - $repeatedNoNamespaceMessage = $m->getRepeatedNoNamespaceMessage(); - $repeatedNoNamespaceMessage[] = new NoNameSpaceMessage(); - $m->setRepeatedNoNamespaceMessage($repeatedNoNamespaceMessage); - - $n = new NoNamespaceMessage(); - $n->setB(NoNamespaceMessage_NestedEnum::ZERO); - } - - public function testEnumWithoutNamespace() - { - $m = new TestMessage(); - $m->setOptionalNoNamespaceEnum(NoNameSpaceEnum::VALUE_A); - $repeatedNoNamespaceEnum = $m->getRepeatedNoNamespaceEnum(); - $repeatedNoNamespaceEnum[] = NoNameSpaceEnum::VALUE_A; - $m->setRepeatedNoNamespaceEnum($repeatedNoNamespaceEnum); - } - - ######################################################### - # Test message with given prefix. - ######################################################### - - public function testPrefixMessage() - { - $m = new TestIncludePrefixMessage(); - $n = new PrefixTestPrefix(); - $n->setA(1); - $m->setPrefixMessage($n); - $this->assertSame(1, $m->getPrefixMessage()->getA()); - } - - ######################################################### - # Test message with given namespace. - ######################################################### - - public function testNamespaceMessage() - { - $m = new TestIncludeNamespaceMessage(); - - $n = new TestNamespace(); - $n->setA(1); - $m->setNamespaceMessage($n); - $this->assertSame(1, $m->getNamespaceMessage()->getA()); - - $n = new TestEmptyNamespace(); - $n->setA(1); - $m->setEmptyNamespaceMessage($n); - $this->assertSame(1, $m->getEmptyNamespaceMessage()->getA()); - } - - ######################################################### - # Test prefix for reserved words. - ######################################################### - - public function testPrefixForReservedWords() - { - $m = new \Foo\TestMessage_Empty(); - $m = new \Foo\PBEmpty(); - $m = new \PrefixEmpty(); - $m = new \Foo\PBARRAY(); - } - - ######################################################### - # Test fluent setters. - ######################################################### - - public function testFluentSetters() - { - $m = (new TestMessage()) - ->setOptionalInt32(1) - ->setOptionalUInt32(2); - $this->assertSame(1, $m->getOptionalInt32()); - $this->assertSame(2, $m->getOptionalUInt32()); - } - - ######################################################### - # Test Reverse Field Order. - ######################################################### - - public function testReverseFieldOrder() - { - $m = new TestReverseFieldOrder(); - $m->setB("abc"); - $this->assertSame("abc", $m->getB()); - $this->assertNotSame("abc", $m->getA()); - } -} diff --git a/php/tests/generated_phpdoc_test.php b/php/tests/generated_phpdoc_test.php deleted file mode 100644 index 6c1a26f7a2194..0000000000000 --- a/php/tests/generated_phpdoc_test.php +++ /dev/null @@ -1,337 +0,0 @@ -getDocComment(); - $this->assertContains('foo.TestMessage', $doc); - } - - /** - * @dataProvider providePhpDocForGettersAndSetters - */ - public function testPhpDocForIntGetters($methods, $expectedDoc) - { - $class = new ReflectionClass('Foo\TestMessage'); - foreach ($methods as $method) { - $doc = $class->getMethod($method)->getDocComment(); - $this->assertContains($expectedDoc, $doc); - } - } - - public function providePhpDocForGettersAndSetters() - { - return [ - [ - [ - 'setOptionalInt32', - 'setOptionalUint32', - 'setOptionalSint32', - 'setOptionalFixed32', - 'setOptionalSfixed32', - 'setOneofInt32', - 'setOneofUint32', - 'setOneofSint32', - 'setOneofFixed32', - 'setOneofSfixed32', - 'setOptionalEnum', - 'setOptionalNoNamespaceEnum', - 'setOptionalNestedEnum', - 'setOneofEnum' - ], - '@param int $var' - ], - [ - [ - 'setOptionalInt64', - 'setOptionalUint64', - 'setOptionalSint64', - 'setOptionalFixed64', - 'setOptionalSfixed64', - 'setOneofInt64', - 'setOneofUint64', - 'setOneofSint64', - 'setOneofFixed64', - 'setOneofSfixed64', - ], - '@param int|string $var' - ], - [ - [ - 'getOptionalInt32', - 'getOptionalUint32', - 'getOptionalSint32', - 'getOptionalFixed32', - 'getOptionalSfixed32', - 'getOneofInt32', - 'getOneofUint32', - 'getOneofSint32', - 'getOneofFixed32', - 'getOneofSfixed32', - 'getOptionalEnum', - 'getOptionalNoNamespaceEnum', - 'getOptionalNestedEnum', - 'getOneofEnum', - ], - '@return int' - ], - [ - [ - 'setOptionalInt64', - 'setOptionalUint64', - 'setOptionalSint64', - 'setOptionalFixed64', - 'setOptionalSfixed64', - 'setOneofInt64', - 'setOneofUint64', - 'setOneofSint64', - 'setOneofFixed64', - 'setOneofSfixed64', - ], - '@param int|string $var' - ], - [ - [ - 'getRepeatedInt32', - 'getRepeatedInt64', - 'getRepeatedUint32', - 'getRepeatedUint64', - 'getRepeatedSint32', - 'getRepeatedSint64', - 'getRepeatedFixed32', - 'getRepeatedFixed64', - 'getRepeatedSfixed32', - 'getRepeatedSfixed64', - 'getRepeatedFloat', - 'getRepeatedDouble', - 'getRepeatedBool', - 'getRepeatedString', - 'getRepeatedBytes', - 'getRepeatedEnum', - 'getRepeatedMessage', - 'getRepeatedRecursive', - 'getRepeatedNoNamespaceMessage', - 'getRepeatedNoNamespaceEnum', - ], - '@return \Google\Protobuf\Internal\RepeatedField' - ], - [ - [ - 'getMapInt32Int32', - 'getMapInt64Int64', - 'getMapUint32Uint32', - 'getMapUint64Uint64', - 'getMapSint32Sint32', - 'getMapSint64Sint64', - 'getMapFixed32Fixed32', - 'getMapFixed64Fixed64', - 'getMapSfixed32Sfixed32', - 'getMapSfixed64Sfixed64', - 'getMapInt32Float', - 'getMapInt32Double', - 'getMapBoolBool', - 'getMapStringString', - 'getMapInt32Bytes', - 'getMapInt32Enum', - 'getMapInt32Message', - 'getMapRecursive', - ], - '@return \Google\Protobuf\Internal\MapField' - ], - [ - [ - 'setRepeatedInt32', - 'setRepeatedUint32', - 'setRepeatedSint32', - 'setRepeatedFixed32', - 'setRepeatedSfixed32', - 'setRepeatedEnum', - 'setRepeatedNoNamespaceEnum', - ], - '@param int[]|\Google\Protobuf\Internal\RepeatedField $var' - ], - [ - [ - 'setRepeatedInt64', - 'setRepeatedUint64', - 'setRepeatedSint64', - 'setRepeatedFixed64', - 'setRepeatedSfixed64', - ], - '@param int[]|string[]|\Google\Protobuf\Internal\RepeatedField $var' - ], - [ - [ - 'setRepeatedFloat', - 'setRepeatedDouble', - ], - '@param float[]|\Google\Protobuf\Internal\RepeatedField $var' - ], - [ - [ - 'setRepeatedBool', - ], - '@param bool[]|\Google\Protobuf\Internal\RepeatedField $var' - ], - [ - [ - 'setRepeatedString', - 'setRepeatedBytes', - ], - '@param string[]|\Google\Protobuf\Internal\RepeatedField $var' - ], - [ - [ - 'setRepeatedMessage', - ], - '@param \Foo\TestMessage_Sub[]|\Google\Protobuf\Internal\RepeatedField $var' - ], - [ - [ - 'setRepeatedRecursive', - ], - '@param \Foo\TestMessage[]|\Google\Protobuf\Internal\RepeatedField $var' - ], - [ - [ - 'setRepeatedNoNamespaceMessage', - ], - '@param \NoNamespaceMessage[]|\Google\Protobuf\Internal\RepeatedField $var' - ], - [ - [ - 'setMapInt32Int32', - 'setMapInt64Int64', - 'setMapUint32Uint32', - 'setMapUint64Uint64', - 'setMapSint32Sint32', - 'setMapSint64Sint64', - 'setMapFixed32Fixed32', - 'setMapFixed64Fixed64', - 'setMapSfixed32Sfixed32', - 'setMapSfixed64Sfixed64', - 'setMapInt32Float', - 'setMapInt32Double', - 'setMapBoolBool', - 'setMapStringString', - 'setMapInt32Bytes', - 'setMapInt32Enum', - 'setMapInt32Message', - 'setMapRecursive', - ], - '@param array|\Google\Protobuf\Internal\MapField $var' - ], - [ - [ - 'getOptionalFloat', - 'getOptionalDouble', - 'getOneofDouble', - 'getOneofFloat', - ], - '@return float' - ], - [ - [ - 'setOptionalFloat', - 'setOptionalDouble', - 'setOneofDouble', - 'setOneofFloat', - ], - '@param float $var' - ], - [ - [ - 'getOptionalBool', - 'getOneofBool', - ], - '@return bool'], - [ - [ - 'setOptionalBool', - 'setOneofBool', - ], - '@param bool $var' - ], - [ - [ - 'getOptionalString', - 'getOptionalBytes', - 'getOneofString', - 'getOneofBytes', - 'getMyOneof', - ], - '@return string' - ], - [ - [ - 'setOptionalString', - 'setOptionalBytes', - 'setOneofString', - 'setOneofBytes', - ], - '@param string $var' - ], - - [ - [ - 'getOptionalMessage', - 'getOneofMessage' - ], - '@return \Foo\TestMessage_Sub' - ], - [ - [ - 'setOptionalMessage', - 'setOneofMessage' - ], - '@param \Foo\TestMessage_Sub $var' - ], - [ - [ - 'getOptionalIncludedMessage' - ], - '@return \Bar\TestInclude' - ], - [ - [ - 'setOptionalIncludedMessage' - ], - '@param \Bar\TestInclude $var' - ], - [ - [ - 'getRecursive' - ], - '@return \Foo\TestMessage' - ], - [ - [ - 'setRecursive' - ], - '@param \Foo\TestMessage $var' - ], - - [ - [ - 'getOptionalNoNamespaceMessage' - ], - '@return \NoNamespaceMessage' - ], - [ - [ - 'setOptionalNoNamespaceMessage' - ], - '@param \NoNamespaceMessage $var' - ], - ]; - } -} diff --git a/php/tests/generated_service_test.php b/php/tests/generated_service_test.php deleted file mode 100644 index 5407db9a3e4aa..0000000000000 --- a/php/tests/generated_service_test.php +++ /dev/null @@ -1,110 +0,0 @@ -serviceClass = new ReflectionClass('Foo\GreeterInterface'); - - $this->namespacedServiceClass = new ReflectionClass('Bar\OtherGreeterInterface'); - } - - public function testIsInterface() - { - $this->assertTrue($this->serviceClass->isInterface()); - } - - public function testPhpDocForClass() - { - $this->assertContains('foo.Greeter', $this->serviceClass->getDocComment()); - } - - public function testPhpDocForNamespacedClass() - { - $this->assertContains('foo.OtherGreeter', $this->namespacedServiceClass->getDocComment()); - } - - public function testServiceMethodsAreGenerated() - { - $this->assertCount(count($this->methodNames), $this->serviceClass->getMethods()); - foreach ($this->methodNames as $methodName) { - $this->assertTrue($this->serviceClass->hasMethod($methodName)); - } - } - - public function testPhpDocForServiceMethod() - { - foreach ($this->methodNames as $methodName) { - $docComment = $this->serviceClass->getMethod($methodName)->getDocComment(); - $this->assertContains($methodName, $docComment); - $this->assertContains('@param \Foo\HelloRequest $request', $docComment); - $this->assertContains('@return \Foo\HelloReply', $docComment); - } - } - - public function testPhpDocForServiceMethodInNamespacedClass() - { - foreach ($this->methodNames as $methodName) { - $docComment = $this->namespacedServiceClass->getMethod($methodName)->getDocComment(); - $this->assertContains($methodName, $docComment); - $this->assertContains('@param \Foo\HelloRequest $request', $docComment); - $this->assertContains('@return \Foo\HelloReply', $docComment); - } - } - - public function testParamForServiceMethod() - { - foreach ($this->methodNames as $methodName) { - $method = $this->serviceClass->getMethod($methodName); - $this->assertCount(1, $method->getParameters()); - $param = $method->getParameters()[0]; - $this->assertFalse($param->isOptional()); - $this->assertSame('request', $param->getName()); - // ReflectionParameter::getType only exists in PHP 7+, so get the type from __toString - $this->assertContains('Foo\HelloRequest $request', (string) $param); - } - } - - public function testParamForServiceMethodInNamespacedClass() - { - foreach ($this->methodNames as $methodName) { - $method = $this->serviceClass->getMethod($methodName); - $this->assertCount(1, $method->getParameters()); - $param = $method->getParameters()[0]; - $this->assertFalse($param->isOptional()); - $this->assertSame('request', $param->getName()); - // ReflectionParameter::getType only exists in PHP 7+, so get the type from __toString - $this->assertContains('Foo\HelloRequest $request', (string) $param); - } - } -} diff --git a/php/tests/map_field_test.php b/php/tests/map_field_test.php deleted file mode 100644 index cffa2526d00da..0000000000000 --- a/php/tests/map_field_test.php +++ /dev/null @@ -1,468 +0,0 @@ -assertSame(MAX_INT32, $arr[MAX_INT32]); - $arr[MIN_INT32] = MIN_INT32; - $this->assertSame(MIN_INT32, $arr[MIN_INT32]); - $this->assertEquals(2, count($arr)); - $this->assertTrue(isset($arr[MAX_INT32])); - $this->assertTrue(isset($arr[MIN_INT32])); - unset($arr[MAX_INT32]); - unset($arr[MIN_INT32]); - $this->assertEquals(0, count($arr)); - - // Test float argument. - $arr[1.9] = 1.9; - $arr[2.1] = 2.1; - $this->assertSame(1, $arr[1]); - $this->assertSame(2, $arr[2]); - $arr[MAX_INT32_FLOAT] = MAX_INT32_FLOAT; - $this->assertSame(MAX_INT32, $arr[MAX_INT32]); - $arr[MIN_INT32_FLOAT] = MIN_INT32_FLOAT; - $this->assertSame(MIN_INT32, $arr[MIN_INT32]); - $this->assertEquals(4, count($arr)); - unset($arr[1.9]); - unset($arr[2.9]); - unset($arr[MAX_INT32_FLOAT]); - unset($arr[MIN_INT32_FLOAT]); - $this->assertEquals(0, count($arr)); - - // Test string argument. - $arr['2'] = '2'; - $this->assertSame(2, $arr[2]); - $arr['3.1'] = '3.1'; - $this->assertSame(3, $arr[3]); - $arr[MAX_INT32_STRING] = MAX_INT32_STRING; - $this->assertSame(MAX_INT32, $arr[MAX_INT32]); - $this->assertEquals(3, count($arr)); - unset($arr['2']); - unset($arr['3.1']); - unset($arr[MAX_INT32_STRING]); - $this->assertEquals(0, count($arr)); - - // Test foreach. - $arr = new MapField(GPBType::INT32, GPBType::INT32); - for ($i = 0; $i < 3; $i++) { - $arr[$i] = $i; - } - $i = 0; - $arr_test = []; - foreach ($arr as $key => $val) { - $this->assertSame($key, $val); - $arr_test[] = $key; - $i++; - } - $this->assertTrue(isset($arr_test[0])); - $this->assertTrue(isset($arr_test[1])); - $this->assertTrue(isset($arr_test[2])); - $this->assertSame(3, $i); - } - - ######################################################### - # Test uint32 field. - ######################################################### - - public function testUint32() { - $arr = new MapField(GPBType::UINT32, GPBType::UINT32); - - // Test integer argument. - $arr[MAX_UINT32] = MAX_UINT32; - $this->assertSame(-1, $arr[-1]); - $this->assertEquals(1, count($arr)); - unset($arr[MAX_UINT32]); - $this->assertEquals(0, count($arr)); - - $arr[-1] = -1; - $this->assertSame(-1, $arr[-1]); - $arr[MIN_UINT32] = MIN_UINT32; - $this->assertSame(MIN_UINT32, $arr[MIN_UINT32]); - $this->assertEquals(2, count($arr)); - unset($arr[-1]); - unset($arr[MIN_UINT32]); - $this->assertEquals(0, count($arr)); - - // Test float argument. - $arr[MAX_UINT32_FLOAT] = MAX_UINT32_FLOAT; - $this->assertSame(-1, $arr[-1]); - $this->assertEquals(1, count($arr)); - unset($arr[MAX_UINT32_FLOAT]); - $this->assertEquals(0, count($arr)); - - $arr[3.1] = 3.1; - $this->assertSame(3, $arr[3]); - $arr[-1.0] = -1.0; - $this->assertSame(-1, $arr[-1]); - $arr[MIN_UINT32_FLOAT] = MIN_UINT32_FLOAT; - $this->assertSame(MIN_UINT32, $arr[MIN_UINT32]); - $this->assertEquals(3, count($arr)); - unset($arr[3.1]); - unset($arr[-1.0]); - unset($arr[MIN_UINT32_FLOAT]); - $this->assertEquals(0, count($arr)); - - // Test string argument. - $arr[MAX_UINT32_STRING] = MAX_UINT32_STRING; - $this->assertSame(-1, $arr[-1]); - $this->assertEquals(1, count($arr)); - unset($arr[MAX_UINT32_STRING]); - $this->assertEquals(0, count($arr)); - - $arr['7'] = '7'; - $this->assertSame(7, $arr[7]); - $arr['3.1'] = '3.1'; - $this->assertSame(3, $arr[3]); - $arr['-1.0'] = '-1.0'; - $this->assertSame(-1, $arr[-1]); - $arr[MIN_UINT32_STRING] = MIN_UINT32_STRING; - $this->assertSame(MIN_UINT32, $arr[MIN_UINT32]); - $this->assertEquals(4, count($arr)); - unset($arr['7']); - unset($arr['3.1']); - unset($arr['-1.0']); - unset($arr[MIN_UINT32_STRING]); - $this->assertEquals(0, count($arr)); - } - - ######################################################### - # Test int64 field. - ######################################################### - - public function testInt64() { - $arr = new MapField(GPBType::INT64, GPBType::INT64); - - // Test integer argument. - $arr[MAX_INT64] = MAX_INT64; - $arr[MIN_INT64] = MIN_INT64; - if (PHP_INT_SIZE == 4) { - $this->assertSame(MAX_INT64_STRING, $arr[MAX_INT64_STRING]); - $this->assertSame(MIN_INT64_STRING, $arr[MIN_INT64_STRING]); - } else { - $this->assertSame(MAX_INT64, $arr[MAX_INT64]); - $this->assertSame(MIN_INT64, $arr[MIN_INT64]); - } - $this->assertEquals(2, count($arr)); - unset($arr[MAX_INT64]); - unset($arr[MIN_INT64]); - $this->assertEquals(0, count($arr)); - - // Test float argument. - $arr[1.1] = 1.1; - if (PHP_INT_SIZE == 4) { - $this->assertSame('1', $arr['1']); - } else { - $this->assertSame(1, $arr[1]); - } - $this->assertEquals(1, count($arr)); - unset($arr[1.1]); - $this->assertEquals(0, count($arr)); - - // Test string argument. - $arr['2'] = '2'; - $arr['3.1'] = '3.1'; - $arr[MAX_INT64_STRING] = MAX_INT64_STRING; - $arr[MIN_INT64_STRING] = MIN_INT64_STRING; - if (PHP_INT_SIZE == 4) { - $this->assertSame('2', $arr['2']); - $this->assertSame('3', $arr['3']); - $this->assertSame(MAX_INT64_STRING, $arr[MAX_INT64_STRING]); - $this->assertSame(MIN_INT64_STRING, $arr[MIN_INT64_STRING]); - } else { - $this->assertSame(2, $arr[2]); - $this->assertSame(3, $arr[3]); - $this->assertSame(MAX_INT64, $arr[MAX_INT64]); - $this->assertSame(MIN_INT64, $arr[MIN_INT64]); - } - $this->assertEquals(4, count($arr)); - unset($arr['2']); - unset($arr['3.1']); - unset($arr[MAX_INT64_STRING]); - unset($arr[MIN_INT64_STRING]); - $this->assertEquals(0, count($arr)); - } - - ######################################################### - # Test uint64 field. - ######################################################### - - public function testUint64() { - $arr = new MapField(GPBType::UINT64, GPBType::UINT64); - - // Test integer argument. - $arr[MAX_UINT64] = MAX_UINT64; - if (PHP_INT_SIZE == 4) { - $this->assertSame(MAX_UINT64_STRING, $arr[MAX_UINT64_STRING]); - } else { - $this->assertSame(MAX_UINT64, $arr[MAX_UINT64]); - } - $this->assertEquals(1, count($arr)); - unset($arr[MAX_UINT64]); - $this->assertEquals(0, count($arr)); - - // Test float argument. - $arr[1.1] = 1.1; - if (PHP_INT_SIZE == 4) { - $this->assertSame('1', $arr['1']); - } else { - $this->assertSame(1, $arr[1]); - } - $this->assertEquals(1, count($arr)); - unset($arr[1.1]); - $this->assertEquals(0, count($arr)); - - // Test string argument. - $arr['2'] = '2'; - $arr['3.1'] = '3.1'; - $arr[MAX_UINT64_STRING] = MAX_UINT64_STRING; - - if (PHP_INT_SIZE == 4) { - $this->assertSame('2', $arr['2']); - $this->assertSame('3', $arr['3']); - $this->assertSame(MAX_UINT64_STRING, $arr[MAX_UINT64_STRING]); - } else { - $this->assertSame(2, $arr[2]); - $this->assertSame(3, $arr[3]); - $this->assertSame(MAX_UINT64, $arr[MAX_UINT64]); - } - - $this->assertEquals(3, count($arr)); - unset($arr['2']); - unset($arr['3.1']); - unset($arr[MAX_UINT64_STRING]); - $this->assertEquals(0, count($arr)); - } - - ######################################################### - # Test float field. - ######################################################### - - public function testFloat() { - $arr = new MapField(GPBType::INT32, GPBType::FLOAT); - - // Test set. - $arr[0] = 1; - $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF); - - $arr[1] = 1.1; - $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF); - - $arr[2] = '2'; - $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF); - $arr[3] = '3.1'; - $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF); - - $this->assertEquals(4, count($arr)); - } - - ######################################################### - # Test double field. - ######################################################### - - public function testDouble() { - $arr = new MapField(GPBType::INT32, GPBType::DOUBLE); - - // Test set. - $arr[0] = 1; - $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF); - - $arr[1] = 1.1; - $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF); - - $arr[2] = '2'; - $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF); - $arr[3] = '3.1'; - $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF); - - $this->assertEquals(4, count($arr)); - } - - ######################################################### - # Test bool field. - ######################################################### - - public function testBool() { - $arr = new MapField(GPBType::BOOL, GPBType::BOOL); - - // Test boolean. - $arr[True] = True; - $this->assertSame(True, $arr[True]); - $this->assertEquals(1, count($arr)); - unset($arr[True]); - $this->assertEquals(0, count($arr)); - - $arr[False] = False; - $this->assertSame(False, $arr[False]); - $this->assertEquals(1, count($arr)); - unset($arr[False]); - $this->assertEquals(0, count($arr)); - - // Test integer. - $arr[-1] = -1; - $this->assertSame(True, $arr[True]); - $this->assertEquals(1, count($arr)); - unset($arr[-1]); - $this->assertEquals(0, count($arr)); - - $arr[0] = 0; - $this->assertSame(False, $arr[False]); - $this->assertEquals(1, count($arr)); - unset($arr[0]); - $this->assertEquals(0, count($arr)); - - // Test float. - $arr[1.1] = 1.1; - $this->assertSame(True, $arr[True]); - $this->assertEquals(1, count($arr)); - unset($arr[1.1]); - $this->assertEquals(0, count($arr)); - - $arr[0.0] = 0.0; - $this->assertSame(False, $arr[False]); - $this->assertEquals(1, count($arr)); - unset($arr[0.0]); - $this->assertEquals(0, count($arr)); - - // Test string. - $arr['a'] = 'a'; - $this->assertSame(True, $arr[True]); - $this->assertEquals(1, count($arr)); - unset($arr['a']); - $this->assertEquals(0, count($arr)); - - $arr[''] = ''; - $this->assertSame(False, $arr[False]); - $this->assertEquals(1, count($arr)); - unset($arr['']); - $this->assertEquals(0, count($arr)); - } - - ######################################################### - # Test string field. - ######################################################### - - public function testString() { - $arr = new MapField(GPBType::STRING, GPBType::STRING); - - // Test set. - $arr['abc'] = 'abc'; - $this->assertSame('abc', $arr['abc']); - $this->assertEquals(1, count($arr)); - unset($arr['abc']); - $this->assertEquals(0, count($arr)); - - $arr[1] = 1; - $this->assertSame('1', $arr['1']); - $this->assertEquals(1, count($arr)); - unset($arr[1]); - $this->assertEquals(0, count($arr)); - - $arr[1.1] = 1.1; - $this->assertSame('1.1', $arr['1.1']); - $this->assertEquals(1, count($arr)); - unset($arr[1.1]); - $this->assertEquals(0, count($arr)); - - $arr[True] = True; - $this->assertSame('1', $arr['1']); - $this->assertEquals(1, count($arr)); - unset($arr[True]); - $this->assertEquals(0, count($arr)); - - // Test foreach. - $arr = new MapField(GPBType::STRING, GPBType::STRING); - for ($i = 0; $i < 3; $i++) { - $arr[$i] = $i; - } - $i = 0; - $arr_test = []; - foreach ($arr as $key => $val) { - $this->assertSame($key, $val); - $arr_test[] = $key; - $i++; - } - $this->assertTrue(isset($arr_test['0'])); - $this->assertTrue(isset($arr_test['1'])); - $this->assertTrue(isset($arr_test['2'])); - $this->assertSame(3, $i); - } - - ######################################################### - # Test message field. - ######################################################### - - public function testMessage() { - $arr = new MapField(GPBType::INT32, - GPBType::MESSAGE, TestMessage_Sub::class); - - // Test append. - $sub_m = new TestMessage_Sub(); - $sub_m->setA(1); - $arr[0] = $sub_m; - $this->assertSame(1, $arr[0]->getA()); - - $this->assertEquals(1, count($arr)); - - // Test foreach. - $arr = new MapField(GPBType::INT32, - GPBType::MESSAGE, TestMessage_Sub::class); - for ($i = 0; $i < 3; $i++) { - $arr[$i] = new TestMessage_Sub();; - $arr[$i]->setA($i); - } - $i = 0; - $key_test = []; - $value_test = []; - foreach ($arr as $key => $val) { - $key_test[] = $key; - $value_test[] = $val->getA(); - $i++; - } - $this->assertTrue(isset($key_test['0'])); - $this->assertTrue(isset($key_test['1'])); - $this->assertTrue(isset($key_test['2'])); - $this->assertTrue(isset($value_test['0'])); - $this->assertTrue(isset($value_test['1'])); - $this->assertTrue(isset($value_test['2'])); - $this->assertSame(3, $i); - } - - ######################################################### - # Test memory leak - ######################################################### - - // TODO(teboring): Add it back. - // public function testCycleLeak() - // { - // $arr = new MapField(GPBType::INT32, - // GPBType::MESSAGE, TestMessage::class); - // $arr[0] = new TestMessage; - // $arr[0]->SetMapRecursive($arr); - - // // Clean up memory before test. - // gc_collect_cycles(); - // $start = memory_get_usage(); - // unset($arr); - - // // Explicitly trigger garbage collection. - // gc_collect_cycles(); - - // $end = memory_get_usage(); - // $this->assertLessThan($start, $end); - // } -} diff --git a/php/tests/memory_leak_test.php b/php/tests/memory_leak_test.php index a92694d05cbc7..a9c292d0b612d 100644 --- a/php/tests/memory_leak_test.php +++ b/php/tests/memory_leak_test.php @@ -4,38 +4,62 @@ require_once('generated/NoNamespaceEnum.php'); require_once('generated/NoNamespaceMessage.php'); -require_once('generated/NoNamespaceMessage_NestedEnum.php'); +require_once('generated/NoNamespaceMessage/NestedEnum.php'); +require_once('generated/NoNamespaceMessage/NestedMessage.php'); require_once('generated/PrefixEmpty.php'); require_once('generated/PrefixTestPrefix.php'); +require_once('generated/PrefixTestPrefix/PrefixNestedEnum.php'); +require_once('generated/PrefixTestPrefix/PrefixNestedMessage.php'); require_once('generated/TestEmptyNamespace.php'); +require_once('generated/TestEmptyNamespace/NestedEnum.php'); +require_once('generated/TestEmptyNamespace/NestedMessage.php'); require_once('generated/Bar/TestInclude.php'); +require_once('generated/Bar/TestLegacyMessage.php'); +require_once('generated/Bar/TestLegacyMessage/NestedEnum.php'); +require_once('generated/Bar/TestLegacyMessage/NestedMessage.php'); require_once('generated/Foo/PBARRAY.php'); require_once('generated/Foo/PBEmpty.php'); +require_once('generated/Foo/TestAny.php'); +require_once('generated/Foo/TestBoolValue.php'); +require_once('generated/Foo/TestBytesValue.php'); require_once('generated/Foo/TestEnum.php'); require_once('generated/Foo/TestIncludeNamespaceMessage.php'); require_once('generated/Foo/TestIncludePrefixMessage.php'); +require_once('generated/Foo/TestInt32Value.php'); +require_once('generated/Foo/TestInt64Value.php'); require_once('generated/Foo/TestMessage.php'); -require_once('generated/Foo/TestMessage_Empty.php'); -require_once('generated/Foo/TestMessage_NestedEnum.php'); -require_once('generated/Foo/TestMessage_Sub.php'); +require_once('generated/Foo/TestMessage/PBEmpty.php'); +require_once('generated/Foo/TestMessage/NestedEnum.php'); +require_once('generated/Foo/TestMessage/Sub.php'); require_once('generated/Foo/TestPackedMessage.php'); require_once('generated/Foo/TestPhpDoc.php'); require_once('generated/Foo/TestRandomFieldOrder.php'); require_once('generated/Foo/TestReverseFieldOrder.php'); +require_once('generated/Foo/TestStringValue.php'); +require_once('generated/Foo/TestUInt32Value.php'); +require_once('generated/Foo/TestUInt64Value.php'); require_once('generated/Foo/TestUnpackedMessage.php'); +require_once('generated/Foo/testLowerCaseMessage.php'); +require_once('generated/Foo/testLowerCaseEnum.php'); require_once('generated/GPBMetadata/Proto/Test.php'); -require_once('generated/GPBMetadata/Proto/TestEmptyPhpNamespace.php'); +require_once('generated/TestEmptyPhpNamespace.php'); require_once('generated/GPBMetadata/Proto/TestInclude.php'); -require_once('generated/GPBMetadata/Proto/TestNoNamespace.php'); -require_once('generated/GPBMetadata/Proto/TestPhpNamespace.php'); +require_once('generated/TestNoNamespace.php'); +require_once('generated/Metadata/Php/Test/TestPhpNamespace.php'); require_once('generated/GPBMetadata/Proto/TestPrefix.php'); require_once('generated/Php/Test/TestNamespace.php'); +require_once('generated/Php/Test/TestNamespace/PBEmpty.php'); +require_once('generated/Php/Test/TestNamespace/PBEmpty/NestedEnum.php'); +require_once('generated/Php/Test/TestNamespace/PBEmpty/NestedMessage.php'); +require_once('generated/Php/Test/TestNamespace/NestedEnum.php'); +require_once('generated/Php/Test/TestNamespace/NestedMessage.php'); require_once('test_util.php'); use Google\Protobuf\Internal\RepeatedField; use Google\Protobuf\Internal\GPBType; +use Foo\TestAny; use Foo\TestMessage; -use Foo\TestMessage_Sub; +use Foo\TestMessage\Sub; $from = new TestMessage(); TestUtil::setTestMessage($from); @@ -48,7 +72,15 @@ TestUtil::assertTestMessage($to); -$from->setRecursive($from); +$from = new TestMessage(); +TestUtil::setTestMessage2($from); + +$data = $from->serializeToString(); + +$to->mergeFromString($data); + +// TODO(teboring): This causes following tests fail in php7. +# $from->setRecursive($from); $arr = new RepeatedField(GPBType::MESSAGE, TestMessage::class); $arr[] = new TestMessage; @@ -87,7 +119,7 @@ $n->mergeFromString($data); assert('abc' === $n->getOneofString()); -$sub_m = new TestMessage_Sub(); +$sub_m = new Sub(); $sub_m->setA(1); $m->setOneofMessage($sub_m); assert(0 === $m->getOneofInt32()); @@ -99,8 +131,85 @@ $n->mergeFromString($data); assert(1 === $n->getOneofMessage()->getA()); -# $from = new TestMessage(); -# $to = new TestMessage(); -# TestUtil::setTestMessage($from); -# $to->mergeFrom($from); -# TestUtil::assertTestMessage($to); +$m = new TestMessage(); +$m->mergeFromString(hex2bin('F80601')); +assert('f80601' === bin2hex($m->serializeToString())); + +// Test create repeated field via array. +$str_arr = array("abc"); +$m = new TestMessage(); +$m->setRepeatedString($str_arr); + +// Test create map field via array. +$str_arr = array("abc"=>"abc"); +$m = new TestMessage(); +$m->setMapStringString($str_arr); + +// Test unset +$from = new TestMessage(); +TestUtil::setTestMessage($from); +unset($from); + +// Test wellknown +$from = new \Google\Protobuf\Timestamp(); +$from->setSeconds(1); +assert(1, $from->getSeconds()); + +$timestamp = new \Google\Protobuf\Timestamp(); + +date_default_timezone_set('UTC'); +$from = new DateTime('2011-01-01T15:03:01.012345UTC'); +$timestamp->fromDateTime($from); +assert($from->format('U') == $timestamp->getSeconds()); +assert(1000 * $from->format('u') == $timestamp->getNanos()); + +$to = $timestamp->toDateTime(); +assert(\DateTime::class == get_class($to)); +assert($from->format('U') == $to->format('U')); + +$from = new \Google\Protobuf\Value(); +$from->setNumberValue(1); +assert(1, $from->getNumberValue()); + +// Test discard unknown in message. +$m = new TestMessage(); +$from = hex2bin('F80601'); +$m->mergeFromString($from); +$m->discardUnknownFields(); +$to = $m->serializeToString(); +assert("" === bin2hex($to)); + +// Test clear +$m = new TestMessage(); +TestUtil::setTestMessage($m); +$m->clear(); + +// Test unset map element +$m = new TestMessage(); +$map = $m->getMapStringString(); +$map[1] = 1; +unset($map[1]); + +// Test descriptor +$pool = \Google\Protobuf\DescriptorPool::getGeneratedPool(); +$desc = $pool->getDescriptorByClassName("\Foo\TestMessage"); +$field = $desc->getField(1); + +$from = new TestMessage(); +$to = new TestMessage(); +TestUtil::setTestMessage($from); +$to->mergeFrom($from); +TestUtil::assertTestMessage($to); + +// Test decode Any +// Make sure packed message has been created at least once. +$packed = new TestMessage(); + +$m = new TestAny(); +$m->mergeFromJsonString( + "{\"any\":" . + " {\"@type\":\"type.googleapis.com/foo.TestMessage\"," . + " \"optionalInt32\":1}}"); +assert("type.googleapis.com/foo.TestMessage" === + $m->getAny()->getTypeUrl()); +assert("0801" === bin2hex($m->getAny()->getValue())); diff --git a/php/tests/multirequest.php b/php/tests/multirequest.php new file mode 100644 index 0000000000000..bbe8d7703d404 --- /dev/null +++ b/php/tests/multirequest.php @@ -0,0 +1,8 @@ +protobuf loaded

"; +} else { + echo "

protobuf not loaded

"; +} diff --git a/php/tests/multirequest.sh b/php/tests/multirequest.sh new file mode 100755 index 0000000000000..ec4a1ae51e35a --- /dev/null +++ b/php/tests/multirequest.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +cd $(dirname $0) + +set -e + +PORT=12345 + +./compile_extension.sh + +nohup php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so -S localhost:$PORT multirequest.php 2>&1 & + +sleep 1 + +wget http://localhost:$PORT/multirequest.result -O multirequest.result +wget http://localhost:$PORT/multirequest.result -O multirequest.result + +pushd ../ext/google/protobuf +phpize --clean +popd + +PID=`ps | grep "php" | awk '{print $1}'` +echo $PID + +if [[ -z "$PID" ]] +then + echo "Failed" + exit 1 +else + kill $PID + echo "Succeeded" +fi diff --git a/php/tests/php_implementation_test.php b/php/tests/php_implementation_test.php deleted file mode 100644 index 5dbc9233cf971..0000000000000 --- a/php/tests/php_implementation_test.php +++ /dev/null @@ -1,516 +0,0 @@ -assertSame(1, $value); - - // Negative number. - $input = new CodedInputStream(hex2bin("ffffffff0f")); - GPBWire::readInt32($input, $value); - $this->assertSame(-1, $value); - - // Discard overflow bits. - $input = new CodedInputStream(hex2bin("ffffffff7f")); - GPBWire::readInt32($input, $value); - $this->assertSame(-1, $value); - } - - public function testReadUint32() - { - $value = null; - - // Positive number. - $input = new CodedInputStream(hex2bin("01")); - GPBWire::readUint32($input, $value); - $this->assertSame(1, $value); - - // Max uint32. - $input = new CodedInputStream(hex2bin("ffffffff0f")); - GPBWire::readUint32($input, $value); - $this->assertSame(-1, $value); - - // Discard overflow bits. - $input = new CodedInputStream(hex2bin("ffffffff7f")); - GPBWire::readUint32($input, $value); - $this->assertSame(-1, $value); - } - - public function testReadInt64() - { - $value = null; - - // Positive number. - $input = new CodedInputStream(hex2bin("01")); - GPBWire::readInt64($input, $value); - $this->assertEquals(1, $value); - - // Negative number. - $input = new CodedInputStream(hex2bin("ffffffffffffffffff01")); - GPBWire::readInt64($input, $value); - $this->assertEquals(-1, $value); - - // Discard overflow bits. - $input = new CodedInputStream(hex2bin("ffffffffffffffffff0f")); - GPBWire::readInt64($input, $value); - $this->assertEquals(-1, $value); - } - - public function testReadUint64() - { - $value = null; - - // Positive number. - $input = new CodedInputStream(hex2bin("01")); - GPBWire::readUint64($input, $value); - $this->assertEquals(1, $value); - - // Negative number. - $input = new CodedInputStream(hex2bin("FFFFFFFFFFFFFFFFFF01")); - GPBWire::readUint64($input, $value); - $this->assertEquals(-1, $value); - - // Discard overflow bits. - $input = new CodedInputStream(hex2bin("FFFFFFFFFFFFFFFFFF0F")); - GPBWire::readUint64($input, $value); - $this->assertEquals(-1, $value); - } - - public function testReadSint32() - { - $value = null; - - $input = new CodedInputStream(hex2bin("00")); - GPBWire::readSint32($input, $value); - $this->assertSame(0, $value); - - $input = new CodedInputStream(hex2bin("01")); - GPBWire::readSint32($input, $value); - $this->assertSame(-1, $value); - - $input = new CodedInputStream(hex2bin("02")); - GPBWire::readSint32($input, $value); - $this->assertSame(1, $value); - } - - public function testReadSint64() - { - $value = null; - - $input = new CodedInputStream(hex2bin("00")); - GPBWire::readSint64($input, $value); - $this->assertEquals(0, $value); - - $input = new CodedInputStream(hex2bin("01")); - GPBWire::readSint64($input, $value); - $this->assertEquals(-1, $value); - - $input = new CodedInputStream(hex2bin("02")); - GPBWire::readSint64($input, $value); - $this->assertEquals(1, $value); - } - - public function testReadFixed32() - { - $value = null; - $input = new CodedInputStream(hex2bin("12345678")); - GPBWire::readFixed32($input, $value); - $this->assertSame(0x78563412, $value); - } - - public function testReadFixed64() - { - $value = null; - $input = new CodedInputStream(hex2bin("1234567812345678")); - GPBWire::readFixed64($input, $value); - if (PHP_INT_SIZE == 4) { - $this->assertSame("8671175386481439762", $value); - } else { - $this->assertSame(0x7856341278563412, $value); - } - } - - public function testReadSfixed32() - { - $value = null; - $input = new CodedInputStream(hex2bin("12345678")); - GPBWire::readSfixed32($input, $value); - $this->assertSame(0x78563412, $value); - } - - public function testReadFloat() - { - $value = null; - $input = new CodedInputStream(hex2bin("0000803F")); - GPBWire::readFloat($input, $value); - $this->assertSame(1.0, $value); - } - - public function testReadBool() - { - $value = null; - - $input = new CodedInputStream(hex2bin("00")); - GPBWire::readBool($input, $value); - $this->assertSame(false, $value); - - $input = new CodedInputStream(hex2bin("01")); - GPBWire::readBool($input, $value); - $this->assertSame(true, $value); - } - - public function testReadDouble() - { - $value = null; - $input = new CodedInputStream(hex2bin("000000000000F03F")); - GPBWire::readDouble($input, $value); - $this->assertSame(1.0, $value); - } - - public function testReadSfixed64() - { - $value = null; - $input = new CodedInputStream(hex2bin("1234567812345678")); - GPBWire::readSfixed64($input, $value); - if (PHP_INT_SIZE == 4) { - $this->assertSame("8671175386481439762", $value); - } else { - $this->assertSame(0x7856341278563412, $value); - } - } - - public function testZigZagEncodeDecode() - { - $this->assertSame(0, GPBWire::zigZagEncode32(0)); - $this->assertSame(1, GPBWire::zigZagEncode32(-1)); - $this->assertSame(2, GPBWire::zigZagEncode32(1)); - $this->assertSame(3, GPBWire::zigZagEncode32(-2)); - $this->assertSame(0x7FFFFFFE, GPBWire::zigZagEncode32(0x3FFFFFFF)); - $this->assertSame(0x7FFFFFFF, GPBWire::zigZagEncode32(0xC0000000)); - $this->assertSame(0x7FFFFFFF, GPBWire::zigZagEncode32(-1073741824)); - - $this->assertSame(0, GPBWire::zigZagDecode32(0)); - $this->assertSame(-1, GPBWire::zigZagDecode32(1)); - $this->assertSame(1, GPBWire::zigZagDecode32(2)); - $this->assertSame(-2, GPBWire::zigZagDecode32(3)); - $this->assertSame(0x3FFFFFFF, GPBWire::zigZagDecode32(0x7FFFFFFE)); - $this->assertSame(-1073741824, GPBWire::zigZagDecode32(0x7FFFFFFF)); - $this->assertSame(0x7FFFFFFF, GPBWire::zigZagDecode32(0xFFFFFFFE)); - $this->assertSame((int)-2147483648,GPBWire::zigZagDecode32(0xFFFFFFFF)); - - if (PHP_INT_SIZE == 4) { - $this->assertSame(-2, GPBWire::zigZagEncode32(0x7FFFFFFF)); - $this->assertSame(-1, GPBWire::zigZagEncode32(0x80000000)); - $this->assertSame('0', GPBWire::zigZagEncode64(0)); - $this->assertSame('1', GPBWire::zigZagEncode64(-1)); - $this->assertSame('2', GPBWire::zigZagEncode64(1)); - $this->assertSame('3', GPBWire::zigZagEncode64(-2)); - $this->assertSame( - '2147483646', // 0x7FFFFFE - GPBWire::zigZagEncode64(0x3FFFFFFF)); - $this->assertSame( - '2147483647', // 0x7FFFFFF - GPBWire::zigZagEncode64(-1073741824)); // 0xFFFFFFFFC0000000 - $this->assertSame( - '4294967294', // 0xFFFFFFFE - GPBWire::zigZagEncode64(2147483647)); // 0x7FFFFFFF - $this->assertSame( - '4294967295', // 0xFFFFFFFF - GPBWire::zigZagEncode64(-2147483648)); // 0xFFFFFFFF80000000 - $this->assertSame( - '18446744073709551614', // 0xFFFFFFFFFFFFFFFE - // 0x7FFFFFFFFFFFFFFF - GPBWire::zigZagEncode64("9223372036854775807")); - $this->assertSame( - '18446744073709551615', // 0xFFFFFFFFFFFFFFFF - // 0x8000000000000000 - GPBWire::zigZagEncode64("-9223372036854775808")); - - $this->assertSame('0', GPBWire::zigZagDecode64(0)); - $this->assertSame('-1', GPBWire::zigZagDecode64(1)); - $this->assertSame('1', GPBWire::zigZagDecode64(2)); - $this->assertSame('-2', GPBWire::zigZagDecode64(3)); - } else { - $this->assertSame(4294967294, GPBWire::zigZagEncode32(0x7FFFFFFF)); - $this->assertSame(4294967295, GPBWire::zigZagEncode32(0x80000000)); - $this->assertSame(0, GPBWire::zigZagEncode64(0)); - $this->assertSame(1, GPBWire::zigZagEncode64(-1)); - $this->assertSame(2, GPBWire::zigZagEncode64(1)); - $this->assertSame(3, GPBWire::zigZagEncode64(-2)); - $this->assertSame(0x7FFFFFFE, GPBWire::zigZagEncode64(0x3FFFFFFF)); - $this->assertSame( - 0x7FFFFFFF, - GPBWire::zigZagEncode64(0xFFFFFFFFC0000000)); - $this->assertSame( - 0xFFFFFFFE, - GPBWire::zigZagEncode64(0x7FFFFFFF)); - $this->assertSame( - 0xFFFFFFFF, - GPBWire::zigZagEncode64(0xFFFFFFFF80000000)); - $this->assertSame( - -2, // 0xFFFFFFFFFFFFFFFE - GPBWire::zigZagEncode64(0x7FFFFFFFFFFFFFFF)); - $this->assertSame( - -1, // 0xFFFFFFFFFFFFFFFF - GPBWire::zigZagEncode64(0x8000000000000000)); - - $this->assertSame(0, GPBWire::zigZagDecode64(0)); - $this->assertSame(-1, GPBWire::zigZagDecode64(1)); - $this->assertSame(1, GPBWire::zigZagDecode64(2)); - $this->assertSame(-2, GPBWire::zigZagDecode64(3)); - } - - // Round trip - $this->assertSame(0, GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(0))); - $this->assertSame(1, GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(1))); - $this->assertSame(-1, GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(-1))); - $this->assertSame(14927, - GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(14927))); - $this->assertSame(-3612, - GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(-3612))); - } - - public function testDecode() - { - $m = new TestMessage(); - $m->mergeFromString(TestUtil::getGoldenTestMessage()); - TestUtil::assertTestMessage($m); - } - - public function testDescriptorDecode() - { - $file_desc_set = new FileDescriptorSet(); - $file_desc_set->mergeFromString(hex2bin( - "0a3b0a12746573745f696e636c7564652e70726f746f120362617222180a" . - "0b54657374496e636c75646512090a0161180120012805620670726f746f33")); - - $this->assertSame(1, sizeof($file_desc_set->getFile())); - - $file_desc = $file_desc_set->getFile()[0]; - $this->assertSame("test_include.proto", $file_desc->getName()); - $this->assertSame("bar", $file_desc->getPackage()); - $this->assertSame(0, sizeof($file_desc->getDependency())); - $this->assertSame(1, sizeof($file_desc->getMessageType())); - $this->assertSame(0, sizeof($file_desc->getEnumType())); - $this->assertSame("proto3", $file_desc->getSyntax()); - - $desc = $file_desc->getMessageType()[0]; - $this->assertSame("TestInclude", $desc->getName()); - $this->assertSame(1, sizeof($desc->getField())); - $this->assertSame(0, sizeof($desc->getNestedType())); - $this->assertSame(0, sizeof($desc->getEnumType())); - $this->assertSame(0, sizeof($desc->getOneofDecl())); - - $field = $desc->getField()[0]; - $this->assertSame("a", $field->getName()); - $this->assertSame(1, $field->getNumber()); - $this->assertSame(GPBLabel::OPTIONAL, $field->getLabel()); - $this->assertSame(GPBType::INT32, $field->getType()); - } - - public function testReadVarint64() - { - $var = 0; - - // Empty buffer. - $input = new CodedInputStream(hex2bin('')); - $this->assertFalse($input->readVarint64($var)); - - // The largest varint is 10 bytes long. - $input = new CodedInputStream(hex2bin('8080808080808080808001')); - $this->assertFalse($input->readVarint64($var)); - - // Corrupted varint. - $input = new CodedInputStream(hex2bin('808080')); - $this->assertFalse($input->readVarint64($var)); - - // Normal case. - $input = new CodedInputStream(hex2bin('808001')); - $this->assertTrue($input->readVarint64($var)); - if (PHP_INT_SIZE == 4) { - $this->assertSame('16384', $var); - } else { - $this->assertSame(16384, $var); - } - $this->assertFalse($input->readVarint64($var)); - - // Read two varint. - $input = new CodedInputStream(hex2bin('808001808002')); - $this->assertTrue($input->readVarint64($var)); - if (PHP_INT_SIZE == 4) { - $this->assertSame('16384', $var); - } else { - $this->assertSame(16384, $var); - } - $this->assertTrue($input->readVarint64($var)); - if (PHP_INT_SIZE == 4) { - $this->assertSame('32768', $var); - } else { - $this->assertSame(32768, $var); - } - $this->assertFalse($input->readVarint64($var)); - - // Read 64 testing - $testVals = array( - '10' => '0a000000000000000000', - '100' => '64000000000000000000', - '800' => 'a0060000000000000000', - '6400' => '80320000000000000000', - '70400' => '80a60400000000000000', - '774400' => '80a22f00000000000000', - '9292800' => '8098b704000000000000', - '74342400' => '80c0b923000000000000', - '743424000' => '8080bfe2020000000000', - '8177664000' => '8080b5bb1e0000000000', - '65421312000' => '8080a8dbf30100000000', - '785055744000' => '8080e0c7ec1600000000', - '9420668928000' => '808080dd969202000000', - '103627358208000' => '808080fff9c717000000', - '1139900940288000' => '808080f5bd9783020000', - '13678811283456000' => '808080fce699a6180000', - '109430490267648000' => '808080e0b7ceb1c20100', - '984874412408832000' => '808080e0f5c1bed50d00', - ); - - foreach ($testVals as $original => $encoded) { - $input = new CodedInputStream(hex2bin($encoded)); - $this->assertTrue($input->readVarint64($var)); - $this->assertEquals($original, $var); - } - } - - public function testReadVarint32() - { - $var = 0; - - // Empty buffer. - $input = new CodedInputStream(hex2bin('')); - $this->assertFalse($input->readVarint32($var)); - - // The largest varint is 10 bytes long. - $input = new CodedInputStream(hex2bin('8080808080808080808001')); - $this->assertFalse($input->readVarint32($var)); - - // Corrupted varint. - $input = new CodedInputStream(hex2bin('808080')); - $this->assertFalse($input->readVarint32($var)); - - // Normal case. - $input = new CodedInputStream(hex2bin('808001')); - $this->assertTrue($input->readVarint32($var)); - $this->assertSame(16384, $var); - $this->assertFalse($input->readVarint32($var)); - - // Read two varint. - $input = new CodedInputStream(hex2bin('808001808002')); - $this->assertTrue($input->readVarint32($var)); - $this->assertSame(16384, $var); - $this->assertTrue($input->readVarint32($var)); - $this->assertSame(32768, $var); - $this->assertFalse($input->readVarint32($var)); - - // Read a 64-bit integer. High-order bits should be discarded. - $input = new CodedInputStream(hex2bin('808081808001')); - $this->assertTrue($input->readVarint32($var)); - $this->assertSame(16384, $var); - $this->assertFalse($input->readVarint32($var)); - } - - public function testReadTag() - { - $input = new CodedInputStream(hex2bin('808001')); - $tag = $input->readTag(); - $this->assertSame(16384, $tag); - $tag = $input->readTag(); - $this->assertSame(0, $tag); - } - - public function testPushPopLimit() - { - $input = new CodedInputStream(hex2bin('808001')); - $old_limit = $input->pushLimit(0); - $tag = $input->readTag(); - $this->assertSame(0, $tag); - $input->popLimit($old_limit); - $tag = $input->readTag(); - $this->assertSame(16384, $tag); - } - - public function testReadRaw() - { - $input = new CodedInputStream(hex2bin('808001')); - $buffer = null; - - $this->assertTrue($input->readRaw(3, $buffer)); - $this->assertSame(hex2bin('808001'), $buffer); - - $this->assertFalse($input->readRaw(1, $buffer)); - } - - public function testWriteVarint32() - { - $output = new CodedOutputStream(3); - $output->writeVarint32(16384, true); - $this->assertSame(hex2bin('808001'), $output->getData()); - - // Negative numbers are padded to be compatible with int64. - $output = new CodedOutputStream(10); - $output->writeVarint32(-43, false); - $this->assertSame(hex2bin('D5FFFFFFFFFFFFFFFF01'), $output->getData()); - } - - public function testWriteVarint64() - { - $output = new CodedOutputStream(10); - $output->writeVarint64(-43); - $this->assertSame(hex2bin('D5FFFFFFFFFFFFFFFF01'), $output->getData()); - } - - public function testWriteLittleEndian32() - { - $output = new CodedOutputStream(4); - $output->writeLittleEndian32(46); - $this->assertSame(hex2bin('2E000000'), $output->getData()); - } - - public function testWriteLittleEndian64() - { - $output = new CodedOutputStream(8); - $output->writeLittleEndian64(47); - $this->assertSame(hex2bin('2F00000000000000'), $output->getData()); - } - - public function testByteSize() - { - $m = new TestMessage(); - TestUtil::setTestMessage($m); - $this->assertSame(506, $m->byteSize()); - } - - public function testPackedByteSize() - { - $m = new TestPackedMessage(); - TestUtil::setTestPackedMessage($m); - $this->assertSame(166, $m->byteSize()); - } -} diff --git a/php/tests/proto/empty/echo.proto b/php/tests/proto/empty/echo.proto new file mode 100644 index 0000000000000..1817018dd213f --- /dev/null +++ b/php/tests/proto/empty/echo.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +package empty.echo; + +message TestEmptyPackage { + int32 a = 1; + + // Test nested messages, enums, and reserved names + NestedMessage nested_message = 2; + NestedEnum nested_enum = 3; + message NestedMessage { + int32 a = 1; + } + enum NestedEnum { + ZERO = 0; + }; +} diff --git a/php/tests/proto/test.proto b/php/tests/proto/test.proto index a90f3d1d7aa91..609b8cfe0cdc4 100644 --- a/php/tests/proto/test.proto +++ b/php/tests/proto/test.proto @@ -1,5 +1,8 @@ syntax = "proto3"; +import 'google/protobuf/any.proto'; +import 'google/protobuf/wrappers.proto'; +import 'google/protobuf/struct.proto'; import 'proto/test_include.proto'; import 'proto/test_no_namespace.proto'; import 'proto/test_php_namespace.proto'; @@ -31,6 +34,27 @@ message TestMessage { bar.TestInclude optional_included_message = 18; TestMessage recursive = 19; + // True optional + optional int32 true_optional_int32 = 201; + optional int64 true_optional_int64 = 202; + optional uint32 true_optional_uint32 = 203; + optional uint64 true_optional_uint64 = 204; + optional sint32 true_optional_sint32 = 205; + optional sint64 true_optional_sint64 = 206; + optional fixed32 true_optional_fixed32 = 207; + optional fixed64 true_optional_fixed64 = 208; + optional sfixed32 true_optional_sfixed32 = 209; + optional sfixed64 true_optional_sfixed64 = 210; + optional float true_optional_float = 211; + optional double true_optional_double = 212; + optional bool true_optional_bool = 213; + optional string true_optional_string = 214; + optional bytes true_optional_bytes = 215; + + optional TestEnum true_optional_enum = 216; + optional Sub true_optional_message = 217; + optional bar.TestInclude true_optional_included_message = 218; + // Repeated repeated int32 repeated_int32 = 31; repeated int64 repeated_int64 = 32; @@ -115,6 +139,17 @@ message TestMessage { message Empty { int32 a = 1; } + + reserved 111; + + // Test map with missing message value + map map_string_message = 121; + map map_string_any = 122; + map map_string_list = 123; + map map_string_struct = 124; + + // deprecated field + int32 deprecated_optional_int32 = 125 [deprecated=true]; } enum TestEnum { @@ -188,7 +223,86 @@ message TestRandomFieldOrder { string tag14 = 160; } +message TestLargeFieldNumber { + int32 large_field_number = 536870911; +} + message TestReverseFieldOrder { repeated int32 a = 2; string b = 1; } + +message testLowerCaseMessage { +} + +enum testLowerCaseEnum { + VALUE = 0; +} + +message TestAny { + google.protobuf.Any any = 1; +} + +message TestInt32Value { + google.protobuf.Int32Value field = 1; + repeated google.protobuf.Int32Value repeated_field = 2; + oneof oneof_fields { + google.protobuf.Int32Value oneof_field = 3; + int32 int32_field = 4; + } +} + +message TestInt64Value { + google.protobuf.Int64Value field = 1; + repeated google.protobuf.Int64Value repeated_field = 2; + oneof oneof_fields { + google.protobuf.Int64Value oneof_field = 3; + int32 int32_field = 4; + } +} + +message TestUInt32Value { + google.protobuf.UInt32Value field = 1; + repeated google.protobuf.UInt32Value repeated_field = 2; + oneof oneof_fields { + google.protobuf.UInt32Value oneof_field = 3; + int32 int32_field = 4; + } +} + +message TestUInt64Value { + google.protobuf.UInt64Value field = 1; + repeated google.protobuf.UInt64Value repeated_field = 2; + oneof oneof_fields { + google.protobuf.UInt64Value oneof_field = 3; + int32 int32_field = 4; + } +} + +message TestBoolValue { + google.protobuf.BoolValue field = 1; + repeated google.protobuf.BoolValue repeated_field = 2; + oneof oneof_fields { + google.protobuf.BoolValue oneof_field = 3; + int32 int32_field = 4; + } +} + +message TestStringValue { + google.protobuf.StringValue field = 1; + repeated google.protobuf.StringValue repeated_field = 2; + oneof oneof_fields { + google.protobuf.StringValue oneof_field = 3; + int32 int32_field = 4; + } + map map_field = 5; +} + +message TestBytesValue { + google.protobuf.BytesValue field = 1; + repeated google.protobuf.BytesValue repeated_field = 2; + oneof oneof_fields { + google.protobuf.BytesValue oneof_field = 3; + int32 int32_field = 4; + } +} diff --git a/php/tests/proto/test_empty_php_namespace.proto b/php/tests/proto/test_empty_php_namespace.proto index 7b4bc74d14e8b..c7ed16573e11e 100644 --- a/php/tests/proto/test_empty_php_namespace.proto +++ b/php/tests/proto/test_empty_php_namespace.proto @@ -2,7 +2,18 @@ syntax = "proto3"; package foo; option php_namespace = ""; +option php_metadata_namespace = ""; message TestEmptyNamespace { int32 a = 1; + + // Test nested messages, enums, and reserved names + NestedMessage nested_message = 2; + NestedEnum nested_enum = 3; + message NestedMessage { + int32 a = 1; + } + enum NestedEnum { + ZERO = 0; + }; } diff --git a/php/tests/proto/test_import_descriptor_proto.proto b/php/tests/proto/test_import_descriptor_proto.proto index 2a19940dece05..b06160153fb79 100644 --- a/php/tests/proto/test_import_descriptor_proto.proto +++ b/php/tests/proto/test_import_descriptor_proto.proto @@ -1,5 +1,7 @@ syntax = "proto3"; +package foo; + import "google/protobuf/descriptor.proto"; message TestImportDescriptorProto { diff --git a/php/tests/proto/test_include.proto b/php/tests/proto/test_include.proto index 9844617fa858e..a9072fe304371 100644 --- a/php/tests/proto/test_include.proto +++ b/php/tests/proto/test_include.proto @@ -5,3 +5,14 @@ package bar; message TestInclude { int32 a = 1; } + +message TestLegacyMessage { + NestedMessage message = 1; + NestedEnum enum = 2; + message NestedMessage { + int32 a = 1; + } + enum NestedEnum { + ZERO = 0; + } +} diff --git a/php/tests/proto/test_no_namespace.proto b/php/tests/proto/test_no_namespace.proto index 58f13d47bc27f..cce42ea2c3905 100644 --- a/php/tests/proto/test_no_namespace.proto +++ b/php/tests/proto/test_no_namespace.proto @@ -1,13 +1,19 @@ syntax = "proto3"; +option php_metadata_namespace = "\\"; + message NoNamespaceMessage { int32 a = 1; - enum NestedEnum { - ZERO = 0; + // Test nested messages, enums, and reserved names + NestedMessage nested_message = 2; + NestedEnum nested_enum = 3; + message NestedMessage { + int32 a = 1; } - NestedEnum b = 2; - repeated NestedEnum c = 3; + enum NestedEnum { + ZERO = 0; + }; } enum NoNamespaceEnum { diff --git a/php/tests/proto/test_php_namespace.proto b/php/tests/proto/test_php_namespace.proto index 713187b9b0730..61085bf75a93d 100644 --- a/php/tests/proto/test_php_namespace.proto +++ b/php/tests/proto/test_php_namespace.proto @@ -2,7 +2,30 @@ syntax = "proto3"; package foo; option php_namespace = "Php\\Test"; +option php_metadata_namespace = "Metadata\\Php\\Test"; message TestNamespace { int32 a = 1; + + // Test nested messages, enums, and reserved names + NestedMessage nested_message = 2; + NestedEnum nested_enum = 3; + Empty reserved_name = 4; + message NestedMessage { + int32 a = 1; + } + enum NestedEnum { + ZERO = 0; + }; + // Test reserved name + message Empty { + NestedMessage nested_message = 1; + NestedEnum nested_enum = 2; + message NestedMessage { + int32 a = 1; + } + enum NestedEnum { + ZERO = 0; + }; + } } diff --git a/php/tests/proto/test_prefix.proto b/php/tests/proto/test_prefix.proto index 9bfbad7f82d3e..3fa11381b09a0 100644 --- a/php/tests/proto/test_prefix.proto +++ b/php/tests/proto/test_prefix.proto @@ -4,6 +4,14 @@ option php_class_prefix = "Prefix"; message TestPrefix { int32 a = 1; + NestedMessage nested_message = 2; + NestedEnum nested_enum = 3; + message NestedMessage { + int32 a = 1; + } + enum NestedEnum { + ZERO = 0; + }; } // Test prefix for reserved words. diff --git a/php/tests/proto/test_reserved_enum_lower.proto b/php/tests/proto/test_reserved_enum_lower.proto new file mode 100644 index 0000000000000..d2daeaff4a734 --- /dev/null +++ b/php/tests/proto/test_reserved_enum_lower.proto @@ -0,0 +1,77 @@ +syntax = "proto3"; + +package lower_enum; + +enum abstract { ZERO1 = 0; } +enum and { ZERO2 = 0; } +enum array { ZERO3 = 0; } +enum as { ZERO4 = 0; } +enum break { ZERO5 = 0; } +enum callable { ZERO6 = 0; } +enum case { ZERO7 = 0; } +enum catch { ZERO8 = 0; } +enum class { ZERO9 = 0; } +enum clone { ZERO10 = 0; } +enum const { ZERO11 = 0; } +enum continue { ZERO12 = 0; } +enum declare { ZERO13 = 0; } +enum default { ZERO14 = 0; } +enum die { ZERO15 = 0; } +enum do { ZERO16 = 0; } +enum echo { ZERO17 = 0; } +enum else { ZERO18 = 0; } +enum elseif { ZERO19 = 0; } +enum empty { ZERO20 = 0; } +enum enddeclare { ZERO21 = 0; } +enum endfor { ZERO22 = 0; } +enum endforeach { ZERO23 = 0; } +enum endif { ZERO24 = 0; } +enum endswitch { ZERO25 = 0; } +enum endwhile { ZERO26 = 0; } +enum eval { ZERO27 = 0; } +enum exit { ZERO28 = 0; } +enum extends { ZERO29 = 0; } +enum final { ZERO30 = 0; } +enum for { ZERO31 = 0; } +enum foreach { ZERO32 = 0; } +enum function { ZERO33 = 0; } +enum global { ZERO34 = 0; } +enum goto { ZERO35 = 0; } +enum if { ZERO36 = 0; } +enum implements { ZERO37 = 0; } +enum include { ZERO38 = 0; } +enum include_once { ZERO39 = 0; } +enum instanceof { ZERO40 = 0; } +enum insteadof { ZERO41 = 0; } +enum interface { ZERO42 = 0; } +enum isset { ZERO43 = 0; } +enum list { ZERO44 = 0; } +enum namespace { ZERO45 = 0; } +enum new { ZERO46 = 0; } +enum or { ZERO47 = 0; } +enum print { ZERO48 = 0; } +enum private { ZERO49 = 0; } +enum protected { ZERO50 = 0; } +enum public { ZERO51 = 0; } +enum require { ZERO52 = 0; } +enum require_once { ZERO53 = 0; } +enum return { ZERO54 = 0; } +enum static { ZERO55 = 0; } +enum switch { ZERO56 = 0; } +enum throw { ZERO57 = 0; } +enum trait { ZERO58 = 0; } +enum try { ZERO59 = 0; } +enum unset { ZERO60 = 0; } +enum use { ZERO61 = 0; } +enum var { ZERO62 = 0; } +enum while { ZERO63 = 0; } +enum xor { ZERO64 = 0; } +enum int { ZERO65 = 0; } +enum float { ZERO66 = 0; } +enum bool { ZERO67 = 0; } +enum string { ZERO68 = 0; } +enum true { ZERO69 = 0; } +enum false { ZERO70 = 0; } +enum null { ZERO71 = 0; } +enum void { ZERO72 = 0; } +enum iterable { ZERO73 = 0; } diff --git a/php/tests/proto/test_reserved_enum_upper.proto b/php/tests/proto/test_reserved_enum_upper.proto new file mode 100644 index 0000000000000..a396fea31c9e0 --- /dev/null +++ b/php/tests/proto/test_reserved_enum_upper.proto @@ -0,0 +1,77 @@ +syntax = "proto3"; + +package upper_enum; + +enum ABSTRACT { ZERO1 = 0; } +enum AND { ZERO2 = 0; } +enum ARRAY { ZERO3 = 0; } +enum AS { ZERO4 = 0; } +enum BREAK { ZERO5 = 0; } +enum CALLABLE { ZERO6 = 0; } +enum CASE { ZERO7 = 0; } +enum CATCH { ZERO8 = 0; } +enum CLASS { ZERO9 = 0; } +enum CLONE { ZERO10 = 0; } +enum CONST { ZERO11 = 0; } +enum CONTINUE { ZERO12 = 0; } +enum DECLARE { ZERO13 = 0; } +enum DEFAULT { ZERO14 = 0; } +enum DIE { ZERO15 = 0; } +enum DO { ZERO16 = 0; } +enum ECHO { ZERO17 = 0; } +enum ELSE { ZERO18 = 0; } +enum ELSEIF { ZERO19 = 0; } +enum EMPTY { ZERO20 = 0; } +enum ENDDECLARE { ZERO21 = 0; } +enum ENDFOR { ZERO22 = 0; } +enum ENDFOREACH { ZERO23 = 0; } +enum ENDIF { ZERO24 = 0; } +enum ENDSWITCH { ZERO25 = 0; } +enum ENDWHILE { ZERO26 = 0; } +enum EVAL { ZERO27 = 0; } +enum EXIT { ZERO28 = 0; } +enum EXTENDS { ZERO29 = 0; } +enum FINAL { ZERO30 = 0; } +enum FOR { ZERO31 = 0; } +enum FOREACH { ZERO32 = 0; } +enum FUNCTION { ZERO33 = 0; } +enum GLOBAL { ZERO34 = 0; } +enum GOTO { ZERO35 = 0; } +enum IF { ZERO36 = 0; } +enum IMPLEMENTS { ZERO37 = 0; } +enum INCLUDE { ZERO38 = 0; } +enum INCLUDE_ONCE { ZERO39 = 0; } +enum INSTANCEOF { ZERO40 = 0; } +enum INSTEADOF { ZERO41 = 0; } +enum INTERFACE { ZERO42 = 0; } +enum ISSET { ZERO43 = 0; } +enum LIST { ZERO44 = 0; } +enum NAMESPACE { ZERO45 = 0; } +enum NEW { ZERO46 = 0; } +enum OR { ZERO47 = 0; } +enum PRINT { ZERO48 = 0; } +enum PRIVATE { ZERO49 = 0; } +enum PROTECTED { ZERO50 = 0; } +enum PUBLIC { ZERO51 = 0; } +enum REQUIRE { ZERO52 = 0; } +enum REQUIRE_ONCE { ZERO53 = 0; } +enum RETURN { ZERO54 = 0; } +enum STATIC { ZERO55 = 0; } +enum SWITCH { ZERO56 = 0; } +enum THROW { ZERO57 = 0; } +enum TRAIT { ZERO58 = 0; } +enum TRY { ZERO59 = 0; } +enum UNSET { ZERO60 = 0; } +enum USE { ZERO61 = 0; } +enum VAR { ZERO62 = 0; } +enum WHILE { ZERO63 = 0; } +enum XOR { ZERO64 = 0; } +enum INT { ZERO65 = 0; } +enum FLOAT { ZERO66 = 0; } +enum BOOL { ZERO67 = 0; } +enum STRING { ZERO68 = 0; } +enum TRUE { ZERO69 = 0; } +enum FALSE { ZERO70 = 0; } +enum NULL { ZERO71 = 0; } +enum VOID { ZERO72 = 0; } +enum ITERABLE { ZERO73 = 0; } diff --git a/php/tests/proto/test_reserved_enum_value_lower.proto b/php/tests/proto/test_reserved_enum_value_lower.proto new file mode 100644 index 0000000000000..96da319e553c3 --- /dev/null +++ b/php/tests/proto/test_reserved_enum_value_lower.proto @@ -0,0 +1,79 @@ +syntax = "proto3"; + +package lower_enum_value; + +enum NotAllowed { + abstract = 0; + and = 1; + array = 2; + as = 3; + break = 4; + callable = 5; + case = 6; + catch = 7; + class = 8; + clone = 9; + const = 10; + continue = 11; + declare = 12; + default = 13; + die = 14; + do = 15; + echo = 16; + else = 17; + elseif = 18; + empty = 19; + enddeclare = 20; + endfor = 21; + endforeach = 22; + endif = 23; + endswitch = 24; + endwhile = 25; + eval = 26; + exit = 27; + extends = 28; + final = 29; + for = 30; + foreach = 31; + function = 32; + global = 33; + goto = 34; + if = 35; + implements = 36; + include = 37; + include_once = 38; + instanceof = 39; + insteadof = 40; + interface = 41; + isset = 42; + list = 43; + namespace = 44; + new = 45; + or = 46; + print = 47; + private = 48; + protected = 49; + public = 50; + require = 51; + require_once = 52; + return = 53; + static = 54; + switch = 55; + throw = 56; + trait = 57; + try = 58; + unset = 59; + use = 60; + var = 61; + while = 62; + xor = 63; + int = 64; + float = 65; + bool = 66; + string = 67; + true = 68; + false = 69; + null = 70; + void = 71; + iterable = 72; +} diff --git a/php/tests/proto/test_reserved_enum_value_upper.proto b/php/tests/proto/test_reserved_enum_value_upper.proto new file mode 100644 index 0000000000000..b026a85855881 --- /dev/null +++ b/php/tests/proto/test_reserved_enum_value_upper.proto @@ -0,0 +1,79 @@ +syntax = "proto3"; + +package upper_enum_value; + +enum NotAllowed { + ABSTRACT = 0; + AND = 1; + ARRAY = 2; + AS = 3; + BREAK = 4; + CALLABLE = 5; + CASE = 6; + CATCH = 7; + CLASS = 8; + CLONE = 9; + CONST = 10; + CONTINUE = 11; + DECLARE = 12; + DEFAULT = 13; + DIE = 14; + DO = 15; + ECHO = 16; + ELSE = 17; + ELSEIF = 18; + EMPTY = 19; + ENDDECLARE = 20; + ENDFOR = 21; + ENDFOREACH = 22; + ENDIF = 23; + ENDSWITCH = 24; + ENDWHILE = 25; + EVAL = 26; + EXIT = 27; + EXTENDS = 28; + FINAL = 29; + FOR = 30; + FOREACH = 31; + FUNCTION = 32; + GLOBAL = 33; + GOTO = 34; + IF = 35; + IMPLEMENTS = 36; + INCLUDE = 37; + INCLUDE_ONCE = 38; + INSTANCEOF = 39; + INSTEADOF = 40; + INTERFACE = 41; + ISSET = 42; + LIST = 43; + NAMESPACE = 44; + NEW = 45; + OR = 46; + PRINT = 47; + PRIVATE = 48; + PROTECTED = 49; + PUBLIC = 50; + REQUIRE = 51; + REQUIRE_ONCE = 52; + RETURN = 53; + STATIC = 54; + SWITCH = 55; + THROW = 56; + TRAIT = 57; + TRY = 58; + UNSET = 59; + USE = 60; + VAR = 61; + WHILE = 62; + XOR = 63; + INT = 64; + FLOAT = 65; + BOOL = 66; + STRING = 67; + TRUE = 68; + FALSE = 69; + NULL = 70; + VOID = 71; + ITERABLE = 72; +} diff --git a/php/tests/proto/test_reserved_message_lower.proto b/php/tests/proto/test_reserved_message_lower.proto new file mode 100644 index 0000000000000..ed120808b7ce5 --- /dev/null +++ b/php/tests/proto/test_reserved_message_lower.proto @@ -0,0 +1,77 @@ +syntax = "proto3"; + +package lower; + +message abstract {} +message and {} +message array {} +message as {} +message break {} +message callable {} +message case {} +message catch {} +message class {} +message clone {} +message const {} +message continue {} +message declare {} +message default {} +message die {} +message do {} +message echo {} +message else {} +message elseif {} +message empty {} +message enddeclare {} +message endfor {} +message endforeach {} +message endif {} +message endswitch {} +message endwhile {} +message eval {} +message exit {} +message extends {} +message final {} +message for {} +message foreach {} +message function {} +message global {} +message goto {} +message if {} +message implements {} +message include {} +message include_once {} +message instanceof {} +message insteadof {} +message interface {} +message isset {} +message list {} +message namespace {} +message new {} +message or {} +message print {} +message private {} +message protected {} +message public {} +message require {} +message require_once {} +message return {} +message static {} +message switch {} +message throw {} +message trait {} +message try {} +message unset {} +message use {} +message var {} +message while {} +message xor {} +message int {} +message float {} +message bool {} +message string {} +message true {} +message false {} +message null {} +message void {} +message iterable {} diff --git a/php/tests/proto/test_reserved_message_upper.proto b/php/tests/proto/test_reserved_message_upper.proto new file mode 100644 index 0000000000000..2917fd11eaa66 --- /dev/null +++ b/php/tests/proto/test_reserved_message_upper.proto @@ -0,0 +1,77 @@ +syntax = "proto3"; + +package upper; + +message ABSTRACT {} +message AND {} +message ARRAY {} +message AS {} +message BREAK {} +message CALLABLE {} +message CASE {} +message CATCH {} +message CLASS {} +message CLONE {} +message CONST {} +message CONTINUE {} +message DECLARE {} +message DEFAULT {} +message DIE {} +message DO {} +message ECHO {} +message ELSE {} +message ELSEIF {} +message EMPTY {} +message ENDDECLARE {} +message ENDFOR {} +message ENDFOREACH {} +message ENDIF {} +message ENDSWITCH {} +message ENDWHILE {} +message EVAL {} +message EXIT {} +message EXTENDS {} +message FINAL {} +message FOR {} +message FOREACH {} +message FUNCTION {} +message GLOBAL {} +message GOTO {} +message IF {} +message IMPLEMENTS {} +message INCLUDE {} +message INCLUDE_ONCE {} +message INSTANCEOF {} +message INSTEADOF {} +message INTERFACE {} +message ISSET {} +message LIST {} +message NAMESPACE {} +message NEW {} +message OR {} +message PRINT {} +message PRIVATE {} +message PROTECTED {} +message PUBLIC {} +message REQUIRE {} +message REQUIRE_ONCE {} +message RETURN {} +message STATIC {} +message SWITCH {} +message THROW {} +message TRAIT {} +message TRY {} +message UNSET {} +message USE {} +message VAR {} +message WHILE {} +message XOR {} +message INT {} +message FLOAT {} +message BOOL {} +message STRING {} +message TRUE {} +message FALSE {} +message NULL {} +message VOID {} +message ITERABLE {} diff --git a/php/tests/proto/test_wrapper_type_setters.proto b/php/tests/proto/test_wrapper_type_setters.proto new file mode 100644 index 0000000000000..41ca7f3f311e7 --- /dev/null +++ b/php/tests/proto/test_wrapper_type_setters.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; + +import "google/protobuf/wrappers.proto"; + +package foo; + +message TestWrapperSetters { + google.protobuf.DoubleValue double_value = 1; + google.protobuf.FloatValue float_value = 2; + google.protobuf.Int64Value int64_value = 3; + google.protobuf.UInt64Value uint64_value = 4; + google.protobuf.Int32Value int32_value = 5; + google.protobuf.UInt32Value uint32_value = 6; + google.protobuf.BoolValue bool_value = 7; + google.protobuf.StringValue string_value = 8; + google.protobuf.BytesValue bytes_value = 9; + + oneof wrapped_oneofs { + google.protobuf.DoubleValue double_value_oneof = 10; + google.protobuf.StringValue string_value_oneof = 11; + } + + repeated google.protobuf.StringValue repeated_string_value = 12; + + map map_string_value = 13; +} diff --git a/php/tests/test.sh b/php/tests/test.sh index c35372d3082c4..d04f36aa907f8 100755 --- a/php/tests/test.sh +++ b/php/tests/test.sh @@ -1,21 +1,53 @@ #!/bin/bash -# Compile c extension -pushd ../ext/google/protobuf/ -make clean || true -set -e -# Add following in configure for debug: --enable-debug CFLAGS='-g -O0' -phpize && ./configure CFLAGS='-g -O0' && make -popd +set -ex -tests=( array_test.php encode_decode_test.php generated_class_test.php generated_phpdoc_test.php map_field_test.php well_known_test.php generated_service_test.php descriptors_test.php ) +cd $(dirname $0) + +./generate_protos.sh +./compile_extension.sh + +PHP_VERSION=$(php -r "echo PHP_VERSION;") + +# Each version of PHPUnit supports a fairly narrow range of PHP versions. +case "$PHP_VERSION" in + 7.0.*) + PHPUNIT=phpunit-6.phar + ;; + 7.1.*|7.2.*) + PHPUNIT=phpunit-7.5.0.phar + ;; + 7.3.*|7.4.*) + PHPUNIT=phpunit-8.phar + ;; + 8.0.*) + PHPUNIT=phpunit-9.phar + ;; + *) + echo "ERROR: Unsupported PHP version $PHP_VERSION" + exit 1 + ;; +esac + +[ -f $PHPUNIT ] || wget https://phar.phpunit.de/$PHPUNIT + +tests=( ArrayTest.php EncodeDecodeTest.php GeneratedClassTest.php MapFieldTest.php WellKnownTest.php DescriptorsTest.php WrapperTypeSettersTest.php) for t in "${tests[@]}" do echo "****************************" echo "* $t" echo "****************************" - php -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php $t + php -dextension=../ext/google/protobuf/modules/protobuf.so $PHPUNIT --bootstrap autoload.php $t + echo "" +done + +for t in "${tests[@]}" +do + echo "****************************" + echo "* $t persistent" + echo "****************************" + php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so $PHPUNIT --bootstrap autoload.php $t echo "" done @@ -24,4 +56,17 @@ done export ZEND_DONT_UNLOAD_MODULES=1 export USE_ZEND_ALLOC=0 -valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php +valgrind --suppressions=valgrind.supp --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php +valgrind --suppressions=valgrind.supp --leak-check=yes php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php + +# TODO(teboring): Only for debug (phpunit has memory leak which blocks this beging used by +# regression test.) + +# for t in "${tests[@]}" +# do +# echo "****************************" +# echo "* $t (memory leak)" +# echo "****************************" +# valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so $PHPUNIT --bootstrap autoload.php $t +# echo "" +# done diff --git a/php/tests/test_base.php b/php/tests/test_base.php index dc5e73f579fad..db884a8f21001 100644 --- a/php/tests/test_base.php +++ b/php/tests/test_base.php @@ -2,9 +2,9 @@ use Foo\TestMessage; use Foo\TestEnum; -use Foo\TestMessage_Sub; +use Foo\TestMessage\Sub; -class TestBase extends PHPUnit_Framework_TestCase +class TestBase extends \PHPUnit\Framework\TestCase { public function setFields(TestMessage $m) @@ -12,6 +12,30 @@ public function setFields(TestMessage $m) TestUtil::setTestMessage($m); } + /** + * Polyfill for phpunit6. + */ + static public function assertStringContains($needle, $haystack) + { + if (function_exists('PHPUnit\Framework\assertStringContainsString')) { + parent::assertStringContainsString($needle, $haystack); + } else { + parent::assertContains($needle, $haystack); + } + } + + /** + * Polyfill for phpunit6. + */ + static public function assertFloatEquals($expected, $actual, $delta) + { + if (function_exists('PHPUnit\Framework\assertEqualsWithDelta')) { + parent::assertEqualsWithDelta($expected, $actual, $delta); + } else { + parent::assertEquals($expected, $actual, '', $delta); + } + } + public function setFields2(TestMessage $m) { TestUtil::setTestMessage2($m); @@ -28,7 +52,7 @@ public function expectFields(TestMessage $m) $this->assertSame(1.6, $m->getOptionalDouble()); $this->assertSame(true, $m->getOptionalBool()); $this->assertSame('a', $m->getOptionalString()); - $this->assertSame('b', $m->getOptionalBytes()); + $this->assertSame('bbbb', $m->getOptionalBytes()); $this->assertSame(TestEnum::ONE, $m->getOptionalEnum()); $this->assertSame(33, $m->getOptionalMessage()->getA()); if (PHP_INT_SIZE == 4) { @@ -59,7 +83,7 @@ public function expectFields(TestMessage $m) $this->assertEquals(1.6, $m->getRepeatedDouble()[0]); $this->assertEquals(true, $m->getRepeatedBool()[0]); $this->assertEquals('a', $m->getRepeatedString()[0]); - $this->assertEquals('b', $m->getRepeatedBytes()[0]); + $this->assertEquals('bbbb', $m->getRepeatedBytes()[0]); $this->assertEquals(34, $m->getRepeatedMessage()[0]->GetA()); $this->assertEquals(-52, $m->getRepeatedInt32()[1]); @@ -76,7 +100,7 @@ public function expectFields(TestMessage $m) $this->assertEquals(2.6, $m->getRepeatedDouble()[1]); $this->assertEquals(false, $m->getRepeatedBool()[1]); $this->assertEquals('c', $m->getRepeatedString()[1]); - $this->assertEquals('d', $m->getRepeatedBytes()[1]); + $this->assertEquals('dddd', $m->getRepeatedBytes()[1]); $this->assertEquals(35, $m->getRepeatedMessage()[1]->GetA()); if (PHP_INT_SIZE == 4) { @@ -101,7 +125,7 @@ public function expectFields(TestMessage $m) $this->assertEquals(3.6, $m->getMapInt32Double()[1]); $this->assertEquals(true , $m->getMapBoolBool()[true]); $this->assertEquals('e', $m->getMapStringString()['e']); - $this->assertEquals('f', $m->getMapInt32Bytes()[1]); + $this->assertEquals('ffff', $m->getMapInt32Bytes()[1]); $this->assertEquals(TestEnum::ONE, $m->getMapInt32Enum()[1]); $this->assertEquals(36, $m->getMapInt32Message()[1]->GetA()); } @@ -146,7 +170,7 @@ public function expectFieldsMerged(TestMessage $m) $this->assertEquals(1.6, $m->getRepeatedDouble()[0]); $this->assertEquals(true, $m->getRepeatedBool()[0]); $this->assertEquals('a', $m->getRepeatedString()[0]); - $this->assertEquals('b', $m->getRepeatedBytes()[0]); + $this->assertEquals('bbbb', $m->getRepeatedBytes()[0]); $this->assertEquals(TestEnum::ZERO, $m->getRepeatedEnum()[0]); $this->assertEquals(34, $m->getRepeatedMessage()[0]->GetA()); @@ -164,7 +188,7 @@ public function expectFieldsMerged(TestMessage $m) $this->assertEquals(2.6, $m->getRepeatedDouble()[1]); $this->assertEquals(false, $m->getRepeatedBool()[1]); $this->assertEquals('c', $m->getRepeatedString()[1]); - $this->assertEquals('d', $m->getRepeatedBytes()[1]); + $this->assertEquals('dddd', $m->getRepeatedBytes()[1]); $this->assertEquals(TestEnum::ONE, $m->getRepeatedEnum()[1]); $this->assertEquals(35, $m->getRepeatedMessage()[1]->GetA()); @@ -338,5 +362,6 @@ public function expectEmptyFields(TestMessage $m) // This test is to avoid the warning of no test by php unit. public function testNone() { + $this->assertTrue(true); } } diff --git a/php/tests/test_util.php b/php/tests/test_util.php index c8afdd3e79d89..c47bf586a90d8 100644 --- a/php/tests/test_util.php +++ b/php/tests/test_util.php @@ -2,7 +2,7 @@ use Foo\TestEnum; use Foo\TestMessage; -use Foo\TestMessage_Sub; +use Foo\TestMessage\Sub; use Foo\TestPackedMessage; use Foo\TestUnpackedMessage; @@ -65,9 +65,9 @@ public static function setTestMessage(TestMessage $m) $m->setOptionalDouble(1.6); $m->setOptionalBool(true); $m->setOptionalString('a'); - $m->setOptionalBytes('b'); + $m->setOptionalBytes('bbbb'); $m->setOptionalEnum(TestEnum::ONE); - $sub = new TestMessage_Sub(); + $sub = new Sub(); $m->setOptionalMessage($sub); $m->getOptionalMessage()->SetA(33); @@ -85,9 +85,9 @@ public static function setTestMessage(TestMessage $m) self::appendHelper($m, 'RepeatedDouble', 1.6); self::appendHelper($m, 'RepeatedBool', true); self::appendHelper($m, 'RepeatedString', 'a'); - self::appendHelper($m, 'RepeatedBytes', 'b'); + self::appendHelper($m, 'RepeatedBytes', 'bbbb'); self::appendHelper($m, 'RepeatedEnum', TestEnum::ZERO); - self::appendHelper($m, 'RepeatedMessage', new TestMessage_Sub()); + self::appendHelper($m, 'RepeatedMessage', new Sub()); $m->getRepeatedMessage()[0]->setA(34); self::appendHelper($m, 'RepeatedInt32', -52); @@ -104,9 +104,9 @@ public static function setTestMessage(TestMessage $m) self::appendHelper($m, 'RepeatedDouble', 2.6); self::appendHelper($m, 'RepeatedBool', false); self::appendHelper($m, 'RepeatedString', 'c'); - self::appendHelper($m, 'RepeatedBytes', 'd'); + self::appendHelper($m, 'RepeatedBytes', 'dddd'); self::appendHelper($m, 'RepeatedEnum', TestEnum::ONE); - self::appendHelper($m, 'RepeatedMessage', new TestMessage_Sub()); + self::appendHelper($m, 'RepeatedMessage', new Sub()); $m->getRepeatedMessage()[1]->SetA(35); self::kvUpdateHelper($m, 'MapInt32Int32', -62, -62); @@ -123,15 +123,15 @@ public static function setTestMessage(TestMessage $m) self::kvUpdateHelper($m, 'MapInt32Double', 1, 3.6); self::kvUpdateHelper($m, 'MapBoolBool', true, true); self::kvUpdateHelper($m, 'MapStringString', 'e', 'e'); - self::kvUpdateHelper($m, 'MapInt32Bytes', 1, 'f'); + self::kvUpdateHelper($m, 'MapInt32Bytes', 1, 'ffff'); self::kvUpdateHelper($m, 'MapInt32Enum', 1, TestEnum::ONE); - self::kvUpdateHelper($m, 'MapInt32Message', 1, new TestMessage_Sub()); + self::kvUpdateHelper($m, 'MapInt32Message', 1, new Sub()); $m->getMapInt32Message()[1]->SetA(36); } public static function setTestMessage2(TestMessage $m) { - $sub = new TestMessage_Sub(); + $sub = new Sub(); $m->setOptionalInt32(-142); $m->setOptionalInt64(-143); @@ -168,7 +168,7 @@ public static function setTestMessage2(TestMessage $m) self::appendHelper($m, 'RepeatedString', 'aa'); self::appendHelper($m, 'RepeatedBytes', 'bb'); self::appendHelper($m, 'RepeatedEnum', TestEnum::TWO); - self::appendHelper($m, 'RepeatedMessage', new TestMessage_Sub()); + self::appendHelper($m, 'RepeatedMessage', new Sub()); $m->getRepeatedMessage()[0]->setA(134); self::kvUpdateHelper($m, 'MapInt32Int32', -62, -162); @@ -187,7 +187,7 @@ public static function setTestMessage2(TestMessage $m) self::kvUpdateHelper($m, 'MapStringString', 'e', 'ee'); self::kvUpdateHelper($m, 'MapInt32Bytes', 1, 'ff'); self::kvUpdateHelper($m, 'MapInt32Enum', 1, TestEnum::TWO); - self::kvUpdateHelper($m, 'MapInt32Message', 1, new TestMessage_Sub()); + self::kvUpdateHelper($m, 'MapInt32Message', 1, new Sub()); $m->getMapInt32Message()[1]->SetA(136); self::kvUpdateHelper($m, 'MapInt32Int32', -162, -162); @@ -206,7 +206,7 @@ public static function setTestMessage2(TestMessage $m) self::kvUpdateHelper($m, 'MapStringString', 'ee', 'ee'); self::kvUpdateHelper($m, 'MapInt32Bytes', 2, 'ff'); self::kvUpdateHelper($m, 'MapInt32Enum', 2, TestEnum::TWO); - self::kvUpdateHelper($m, 'MapInt32Message', 2, new TestMessage_Sub()); + self::kvUpdateHelper($m, 'MapInt32Message', 2, new Sub()); $m->getMapInt32Message()[2]->SetA(136); } @@ -234,7 +234,7 @@ public static function assertTestMessage(TestMessage $m) assert(1.6 === $m->getOptionalDouble()); assert(true=== $m->getOptionalBool()); assert('a' === $m->getOptionalString()); - assert('b' === $m->getOptionalBytes()); + assert('bbbb' === $m->getOptionalBytes()); assert(TestEnum::ONE === $m->getOptionalEnum()); assert(33 === $m->getOptionalMessage()->getA()); @@ -260,7 +260,7 @@ public static function assertTestMessage(TestMessage $m) assert(1.6 === $m->getRepeatedDouble()[0]); assert(true=== $m->getRepeatedBool()[0]); assert('a' === $m->getRepeatedString()[0]); - assert('b' === $m->getRepeatedBytes()[0]); + assert('bbbb' === $m->getRepeatedBytes()[0]); assert(TestEnum::ZERO === $m->getRepeatedEnum()[0]); assert(34 === $m->getRepeatedMessage()[0]->getA()); @@ -286,7 +286,7 @@ public static function assertTestMessage(TestMessage $m) assert(2.6 === $m->getRepeatedDouble()[1]); assert(false === $m->getRepeatedBool()[1]); assert('c' === $m->getRepeatedString()[1]); - assert('d' === $m->getRepeatedBytes()[1]); + assert('dddd' === $m->getRepeatedBytes()[1]); assert(TestEnum::ONE === $m->getRepeatedEnum()[1]); assert(35 === $m->getRepeatedMessage()[1]->getA()); @@ -312,7 +312,7 @@ public static function assertTestMessage(TestMessage $m) assert(3.6 === $m->getMapInt32Double()[1]); assert(true === $m->getMapBoolBool()[true]); assert('e' === $m->getMapStringString()['e']); - assert('f' === $m->getMapInt32Bytes()[1]); + assert('ffff' === $m->getMapInt32Bytes()[1]); assert(TestEnum::ONE === $m->getMapInt32Enum()[1]); assert(36 === $m->getMapInt32Message()[1]->GetA()); } @@ -334,42 +334,28 @@ public static function getGoldenTestMessage() "619A9999999999F93F" . "6801" . "720161" . - "7A0162" . + "7A0462626262" . "800101" . "8A01020821" . - "F801D6FFFFFFFFFFFFFFFF01" . - "F801CCFFFFFFFFFFFFFFFF01" . - "8002D5FFFFFFFFFFFFFFFF01" . - "8002CBFFFFFFFFFFFFFFFF01" . - "88022A" . - "880234" . - "90022B" . - "900235" . - "980257" . - "98026B" . - "A00259" . - "A0026D" . - "AD022E000000" . - "AD0238000000" . - "B1022F00000000000000" . - "B1023900000000000000" . - "BD02D2FFFFFF" . - "BD02C8FFFFFF" . - "C102D1FFFFFFFFFFFFFF" . - "C102C7FFFFFFFFFFFFFF" . - "CD020000C03F" . - "CD0200002040" . - "D1029A9999999999F93F" . - "D102CDCCCCCCCCCC0440" . - "D80201" . - "D80200" . + "FA0114D6FFFFFFFFFFFFFFFF01CCFFFFFFFFFFFFFFFF01" . + "820214D5FFFFFFFFFFFFFFFF01CBFFFFFFFFFFFFFFFF01" . + "8A02022A34" . + "9202022B35" . + "9A0202576B" . + "A20202596D" . + "AA02082E00000038000000" . + "B202102F000000000000003900000000000000" . + "BA0208D2FFFFFFC8FFFFFF" . + "C20210D1FFFFFFFFFFFFFFC7FFFFFFFFFFFFFF" . + "CA02080000C03F00002040" . + "D202109A9999999999F93FCDCCCCCCCCCC0440" . + "DA02020100" . "E2020161" . "E2020163" . - "EA020162" . - "EA020164" . - "F00200" . - "F00201" . + "EA020462626262" . + "EA020464646464" . + "F202020001" . "FA02020822" . "FA02020823" . @@ -387,7 +373,7 @@ public static function getGoldenTestMessage() "92050B080111CDCCCCCCCCCC0C40" . "9A050408011001" . "A205060a0165120165" . - "AA05050801120166" . + "AA05080801120466666666" . "B2050408011001" . "Ba0506080112020824" ); diff --git a/php/tests/undefined_test.php b/php/tests/undefined_test.php index dc6b708618aa0..935d8be7d4330 100644 --- a/php/tests/undefined_test.php +++ b/php/tests/undefined_test.php @@ -5,7 +5,7 @@ use Google\Protobuf\Internal\RepeatedField; use Google\Protobuf\Internal\GPBType; use Foo\TestMessage; -use Foo\TestMessage_Sub; +use Foo\TestMessage\Sub; class UndefinedTest extends PHPUnit_Framework_TestCase { @@ -35,7 +35,7 @@ public function testInt32SetStringFail() public function testInt32AppendMessageFail() { $arr = new RepeatedField(GPBType::INT32); - $arr[] = new TestMessage_Sub(); + $arr[] = new Sub(); } /** @@ -45,7 +45,7 @@ public function testInt32SetMessageFail() { $arr = new RepeatedField(GPBType::INT32); $arr[] = 0; - $arr[0] = new TestMessage_Sub(); + $arr[0] = new Sub(); } /** @@ -73,7 +73,7 @@ public function testUint32SetStringFail() public function testUint32AppendMessageFail() { $arr = new RepeatedField(GPBType::UINT32); - $arr[] = new TestMessage_Sub(); + $arr[] = new Sub(); } /** @@ -83,7 +83,7 @@ public function testUint32SetMessageFail() { $arr = new RepeatedField(GPBType::UINT32); $arr[] = 0; - $arr[0] = new TestMessage_Sub(); + $arr[0] = new Sub(); } /** @@ -111,7 +111,7 @@ public function testInt64SetStringFail() public function testInt64AppendMessageFail() { $arr = new RepeatedField(GPBType::INT64); - $arr[] = new TestMessage_Sub(); + $arr[] = new Sub(); } /** @@ -121,7 +121,7 @@ public function testInt64SetMessageFail() { $arr = new RepeatedField(GPBType::INT64); $arr[] = 0; - $arr[0] = new TestMessage_Sub(); + $arr[0] = new Sub(); } /** @@ -149,7 +149,7 @@ public function testUint64SetStringFail() public function testUint64AppendMessageFail() { $arr = new RepeatedField(GPBType::UINT64); - $arr[] = new TestMessage_Sub(); + $arr[] = new Sub(); } /** @@ -159,7 +159,7 @@ public function testUint64SetMessageFail() { $arr = new RepeatedField(GPBType::UINT64); $arr[] = 0; - $arr[0] = new TestMessage_Sub(); + $arr[0] = new Sub(); } /** @@ -187,7 +187,7 @@ public function testFloatSetStringFail() public function testFloatAppendMessageFail() { $arr = new RepeatedField(GPBType::FLOAT); - $arr[] = new TestMessage_Sub(); + $arr[] = new Sub(); } /** @@ -197,7 +197,7 @@ public function testFloatSetMessageFail() { $arr = new RepeatedField(GPBType::FLOAT); $arr[] = 0.0; - $arr[0] = new TestMessage_Sub(); + $arr[0] = new Sub(); } /** @@ -225,7 +225,7 @@ public function testDoubleSetStringFail() public function testDoubleAppendMessageFail() { $arr = new RepeatedField(GPBType::DOUBLE); - $arr[] = new TestMessage_Sub(); + $arr[] = new Sub(); } /** @@ -235,7 +235,7 @@ public function testDoubleSetMessageFail() { $arr = new RepeatedField(GPBType::DOUBLE); $arr[] = 0.0; - $arr[0] = new TestMessage_Sub(); + $arr[0] = new Sub(); } /** @@ -244,7 +244,7 @@ public function testDoubleSetMessageFail() public function testBoolAppendMessageFail() { $arr = new RepeatedField(GPBType::BOOL); - $arr[] = new TestMessage_Sub(); + $arr[] = new Sub(); } /** @@ -254,7 +254,7 @@ public function testBoolSetMessageFail() { $arr = new RepeatedField(GPBType::BOOL); $arr[] = true; - $arr[0] = new TestMessage_Sub(); + $arr[0] = new Sub(); } /** @@ -263,7 +263,7 @@ public function testBoolSetMessageFail() public function testStringAppendMessageFail() { $arr = new RepeatedField(GPBType::STRING); - $arr[] = new TestMessage_Sub(); + $arr[] = new Sub(); } /** @@ -273,7 +273,7 @@ public function testStringSetMessageFail() { $arr = new RepeatedField(GPBType::STRING); $arr[] = 'abc'; - $arr[0] = new TestMessage_Sub(); + $arr[0] = new Sub(); } /** @@ -302,7 +302,7 @@ public function testStringSetInvalidUTF8Fail() */ public function testMessageAppendIntFail() { - $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class); + $arr = new RepeatedField(GPBType::MESSAGE, Sub::class); $arr[] = 1; } @@ -311,8 +311,8 @@ public function testMessageAppendIntFail() */ public function testMessageSetIntFail() { - $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class); - $arr[] = new TestMessage_Sub; + $arr = new RepeatedField(GPBType::MESSAGE, Sub::class); + $arr[] = new Sub; $arr[0] = 'abc'; } @@ -321,7 +321,7 @@ public function testMessageSetIntFail() */ public function testMessageAppendStringFail() { - $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class); + $arr = new RepeatedField(GPBType::MESSAGE, Sub::class); $arr[] = 'abc'; } @@ -330,8 +330,8 @@ public function testMessageAppendStringFail() */ public function testMessageSetStringFail() { - $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class); - $arr[] = new TestMessage_Sub; + $arr = new RepeatedField(GPBType::MESSAGE, Sub::class); + $arr[] = new Sub; $arr[0] = 'abc'; } @@ -340,7 +340,7 @@ public function testMessageSetStringFail() */ public function testMessageAppendOtherMessageFail() { - $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class); + $arr = new RepeatedField(GPBType::MESSAGE, Sub::class); $arr[] = new TestMessage; } @@ -349,7 +349,7 @@ public function testMessageAppendOtherMessageFail() */ public function testMessageAppendNullFail() { - $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class); + $arr = new RepeatedField(GPBType::MESSAGE, Sub::class); $null = null; $arr[] = $null; } @@ -359,8 +359,8 @@ public function testMessageAppendNullFail() */ public function testMessageSetNullFail() { - $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class); - $arr[] = new TestMessage_Sub(); + $arr = new RepeatedField(GPBType::MESSAGE, Sub::class); + $arr[] = new Sub(); $null = null; $arr[0] = $null; } @@ -397,7 +397,7 @@ public function testMessageOffsetFail() { $arr = new RepeatedField(GPBType::INT32); $arr[] = 0; - $arr[new TestMessage_Sub()] = 0; + $arr[new Sub()] = 0; } /** @@ -656,7 +656,7 @@ public function testMapFieldWrongRepeatedMessageClassFail() public function testMessageMergeFromInvalidTypeFail() { $m = new TestMessage(); - $n = new TestMessage_Sub(); + $n = new Sub(); $m->mergeFrom($n); } @@ -684,7 +684,7 @@ public function testInt32SetStringValueFail() public function testInt32SetMessageKeyFail() { $arr = new MapField(GPBType::INT32, GPBType::INT32); - $arr[new TestMessage_Sub()] = 0; + $arr[new Sub()] = 0; } /** @@ -693,7 +693,7 @@ public function testInt32SetMessageKeyFail() public function testInt32SetMessageValueFail() { $arr = new MapField(GPBType::INT32, GPBType::INT32); - $arr[0] = new TestMessage_Sub(); + $arr[0] = new Sub(); } /** @@ -720,7 +720,7 @@ public function testUint32SetStringValueFail() public function testUint32SetMessageKeyFail() { $arr = new MapField(GPBType::UINT32, GPBType::UINT32); - $arr[new TestMessage_Sub()] = 0; + $arr[new Sub()] = 0; } /** @@ -729,7 +729,7 @@ public function testUint32SetMessageKeyFail() public function testUint32SetMessageValueFail() { $arr = new MapField(GPBType::UINT32, GPBType::UINT32); - $arr[0] = new TestMessage_Sub(); + $arr[0] = new Sub(); } /** @@ -756,7 +756,7 @@ public function testInt64SetStringValueFail() public function testInt64SetMessageKeyFail() { $arr = new MapField(GPBType::INT64, GPBType::INT64); - $arr[new TestMessage_Sub()] = 0; + $arr[new Sub()] = 0; } /** @@ -765,7 +765,7 @@ public function testInt64SetMessageKeyFail() public function testInt64SetMessageValueFail() { $arr = new MapField(GPBType::INT64, GPBType::INT64); - $arr[0] = new TestMessage_Sub(); + $arr[0] = new Sub(); } /** @@ -792,7 +792,7 @@ public function testUint64SetStringValueFail() public function testUint64SetMessageKeyFail() { $arr = new MapField(GPBType::UINT64, GPBType::UINT64); - $arr[new TestMessage_Sub()] = 0; + $arr[new Sub()] = 0; } /** @@ -801,7 +801,7 @@ public function testUint64SetMessageKeyFail() public function testUint64SetMessageValueFail() { $arr = new MapField(GPBType::UINT64, GPBType::UINT64); - $arr[0] = new TestMessage_Sub(); + $arr[0] = new Sub(); } /** @@ -819,7 +819,7 @@ public function testDoubleSetStringValueFail() public function testDoubleSetMessageValueFail() { $arr = new MapField(GPBType::INT64, GPBType::DOUBLE); - $arr[0] = new TestMessage_Sub(); + $arr[0] = new Sub(); } /** @@ -828,7 +828,7 @@ public function testDoubleSetMessageValueFail() public function testBoolSetMessageKeyFail() { $arr = new MapField(GPBType::BOOL, GPBType::BOOL); - $arr[new TestMessage_Sub()] = true; + $arr[new Sub()] = true; } /** @@ -837,7 +837,7 @@ public function testBoolSetMessageKeyFail() public function testBoolSetMessageValueFail() { $arr = new MapField(GPBType::BOOL, GPBType::BOOL); - $arr[true] = new TestMessage_Sub(); + $arr[true] = new Sub(); } /** @@ -864,7 +864,7 @@ public function testStringSetInvalidUTF8ValueFail() public function testStringSetMessageKeyFail() { $arr = new MapField(GPBType::STRING, GPBType::STRING); - $arr[new TestMessage_Sub()] = 'abc'; + $arr[new Sub()] = 'abc'; } /** @@ -873,7 +873,7 @@ public function testStringSetMessageKeyFail() public function testStringSetMessageValueFail() { $arr = new MapField(GPBType::STRING, GPBType::STRING); - $arr['abc'] = new TestMessage_Sub(); + $arr['abc'] = new Sub(); } /** @@ -903,13 +903,13 @@ public function testMessageSetOtherMessageValueFail() { $arr = new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class); - $arr[0] = new TestMessage_Sub(); + $arr[0] = new Sub(); } /** * @expectedException PHPUnit_Framework_Error */ - public function testMessageSetNullFail() + public function testMessageSetNullFailMap() { $arr = new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class); diff --git a/php/tests/valgrind.supp b/php/tests/valgrind.supp new file mode 100644 index 0000000000000..e83b0a3dfa0ec --- /dev/null +++ b/php/tests/valgrind.supp @@ -0,0 +1,12 @@ +{ + PHP_Equal_Val + Memcheck:Cond + fun:zend_string_equal_val +} + +{ + PHP_ScanDir_Tail + Memcheck:Cond + obj:/usr/bin/php7.3 + fun:__scandir64_tail +} diff --git a/php/tests/well_known_test.php b/php/tests/well_known_test.php deleted file mode 100644 index 0c2aec13a9267..0000000000000 --- a/php/tests/well_known_test.php +++ /dev/null @@ -1,17 +0,0 @@ -> /etc/yum.repos.d/devtools-1.1.repo' -RUN bash -c "sed -e 's/\$basearch/i386/g' /etc/yum.repos.d/devtools-1.1.repo > /etc/yum.repos.d/devtools-i386-1.1.repo" -RUN sed -e 's/testing-/testing-i386-/g' -i /etc/yum.repos.d/devtools-i386-1.1.repo -RUN rpm --rebuilddb && yum install -y devtoolset-1.1 \ - devtoolset-1.1-libstdc++-devel \ - devtoolset-1.1-libstdc++-devel.i686 +# Install GCC 4.8 to support -static-libstdc++ +RUN wget http://people.centos.org/tru/devtools-2/devtools-2.repo -P /etc/yum.repos.d && \ + bash -c 'echo "enabled=1" >> /etc/yum.repos.d/devtools-2.repo' && \ + bash -c "sed -e 's/\$basearch/i386/g' /etc/yum.repos.d/devtools-2.repo > /etc/yum.repos.d/devtools-i386-2.repo" && \ + sed -e 's/testing-/testing-i386-/g' -i /etc/yum.repos.d/devtools-i386-2.repo && \ + rpm --rebuilddb -RUN git clone --depth 1 https://github.com/google/protobuf.git +RUN yum install -y devtoolset-2-gcc \ + devtoolset-2-gcc-c++ \ + devtoolset-2-binutils \ + devtoolset-2-libstdc++-devel \ + devtoolset-2-libatomic-devel \ + libatomic \ + devtoolset-2-gcc.i686 \ + devtoolset-2-gcc-c++.i686 \ + devtoolset-2-binutils.i686 \ + devtoolset-2-libstdc++-devel.i686 \ + devtoolset-2-libatomic-devel.i686 \ + libatomic.i686 && \ + yum clean all + +COPY scl-enable-devtoolset.sh /var/local/ # Start in devtoolset environment that uses GCC 4.7 -CMD ["scl", "enable", "devtoolset-1.1", "bash"] +ENTRYPOINT ["/var/local/scl-enable-devtoolset.sh"] diff --git a/protoc-artifacts/README.md b/protoc-artifacts/README.md index 17eb77f84093b..2c45fefe780e8 100644 --- a/protoc-artifacts/README.md +++ b/protoc-artifacts/README.md @@ -7,13 +7,31 @@ build and publish a ``protoc`` executable (a.k.a. artifact) to Maven repositories. The artifact can be used by build automation tools so that users would not need to compile and install ``protoc`` for their systems. +If you would like us to publish protoc artifact for a new platform, please send +us a pull request to add support for the new platform. You would need to change +the following files: + +* [build-protoc.sh](build-protoc.sh): script to cross-build the protoc for your + platform. +* [pom.xml](pom.xml): script to upload artifacts to maven. +* [build-zip.sh](build-zip.sh): script to package published maven artifacts in + our release page. + +## Maven Location +The published protoc artifacts are available on Maven here: + + http://central.maven.org/maven2/com/google/protobuf/protoc/ + ## Versioning The version of the ``protoc`` artifact must be the same as the version of the Protobuf project. ## Artifact name The name of a published ``protoc`` artifact is in the following format: -``protoc---.exe``, e.g., ``protoc-3.0.0-alpha-3-windows-x86_64.exe``. +``protoc---.exe``, e.g., ``protoc-3.6.1-linux-x86_64.exe``. + +Note that artifacts for linux/macos also have the `.exe` suffix but they are +not windows binaries. ## System requirement Install [Apache Maven](http://maven.apache.org/) if you don't have it. @@ -29,155 +47,115 @@ generate the configure script. Under the protobuf project directory: -``` -$ ./autogen.sh && ./configure && make -``` - -## To install artifacts locally -The following command will install the ``protoc`` artifact to your local Maven repository. -``` -$ mvn install -``` -## Cross-compilation -The Maven script will try to detect the OS and the architecture from Java -system properties. It's possible to build a protoc binary for an architecture -that is different from what Java has detected, as long as you have the proper -compilers installed. - -You can override the Maven properties ``os.detected.name`` and -``os.detected.arch`` to force the script to generate binaries for a specific OS -and/or architecture. Valid values are defined as the return values of -``normalizeOs()`` and ``normalizeArch()`` of ``Detector`` from -[os-maven-plugin](https://github.com/trustin/os-maven-plugin/blob/master/src/main/java/kr/motd/maven/os/Detector.java). -Frequently used values are: -- ``os.detected.name``: ``linux``, ``osx``, ``windows``. -- ``os.detected.arch``: ``x86_32``, ``x86_64`` - -For example, MinGW32 only ships with 32-bit compilers, but you can still build -32-bit protoc under 64-bit Windows, with the following command: ``` -$ mvn install -Dos.detected.arch=x86_32 +$ ./autogen.sh ``` -## To push artifacts to Maven Central -Before you can upload artifacts to Maven Central repository, make sure you have -read [this page](http://central.sonatype.org/pages/apache-maven.html) on how to -configure GPG and Sonatype account. - -You need to perform the deployment for every platform that you want to -support. DO NOT close the staging repository until you have done the -deployment for all platforms. Currently the following platforms are supported: -- Linux (x86_32 and x86_64) -- Windows (x86_32 and x86_64) with - - Cygwin64 with MinGW compilers (x86_64) - - MSYS with MinGW32 (x86_32) - - Cross compile in Linux with MinGW-w64 (x86_32, x86_64) -- MacOSX (x86_32 and x86_64) +### Build the artifact for each platform -As for MSYS2/MinGW64 for Windows: protoc will build, but it insists on -adding a dependency of `libwinpthread-1.dll`, which isn't shipped with -Windows. +Run the build-protoc.sh script under this protoc-artifacts directory to build the protoc +artifact for each platform. For example: -Use the following command to deploy artifacts for the host platform to a -staging repository. ``` -$ mvn clean deploy -P release +$ cd protoc-artifacts +$ ./build-protoc.sh linux x86_64 protoc ``` -It creates a new staging repository. Go to -https://oss.sonatype.org/#stagingRepositories and find the repository, usually -in the name like ``comgoogle-123``. -You will want to run this command on a different platform. Remember, in -subsequent deployments you will need to provide the repository name that you -have found in the first deployment so that all artifacts go to the same -repository: -``` -$ mvn clean deploy -P release -Dstaging.repository=comgoogle-123 -``` +The above command will produce a `target/linux/x86_64/protoc` binary under the +protoc-artifacts directory. -A 32-bit artifact can be deployed from a 64-bit host with -``-Dos.detected.arch=x86_32`` +For a list of supported platforms, see the comments in the build-protoc.sh +script. We only use this script to build artifacts on Ubuntu and MacOS (both +with x86_64, and do cross-compilation for other platforms. -A windows artifact can be deployed from a linux machine with -``-Dos.detected.name=windows`` +### Tips for building for Linux +We build on Centos 6.9 to provide a good compatibility for not very new +systems. We have provided a ``Dockerfile`` under this directory to build the +environment. It has been tested with Docker 1.6.1. -When you have done deployment for all platforms, go to -https://oss.sonatype.org/#stagingRepositories, verify that the staging -repository has all the binaries, close and release this repository. +To build a image: -## Upload zip packages to github release page. -After uploading protoc artifacts to Maven Central repository, run the -build-zip.sh script to bulid zip packages for these protoc binaries -and upload these zip packages to the download section of the github -release. For example: ``` -$ ./build-zip.sh 3.0.0-beta-4 +$ docker build -t protoc-artifacts . ``` -The above command will create 5 zip files: + +To run the image: + ``` -dist/protoc-3.0.0-beta-4-win32.zip -dist/protoc-3.0.0-beta-4-osx-x86_32.zip -dist/protoc-3.0.0-beta-4-osx-x86_64.zip -dist/protoc-3.0.0-beta-4-linux-x86_32.zip -dist/protoc-3.0.0-beta-4-linux-x86_64.zip +$ docker run -it --rm=true protoc-artifacts bash ``` -Before running the script, make sure the artifacts are accessible from: -http://repo1.maven.org/maven2/com/google/protobuf/protoc/ -### Tips for deploying on Linux -We build on Centos 6.6 to provide a good compatibility for not very new -systems. We have provided a ``Dockerfile`` under this directory to build the -environment. It has been tested with Docker 1.6.1. +To checkout protobuf (run within the container): -To build a image: ``` -$ docker build -t protoc-artifacts . +$ # Replace v3.5.1 with the version you want +$ wget -O - https://github.com/protocolbuffers/protobuf/archive/v3.5.1.tar.gz | tar xvzp ``` -To run the image: +### Windows build +We no longer use scripts in this directory to build windows artifacts. Instead, +we use Visual Studio 2015 to build our windows release artifacts. See our +[kokoro windows build scripts here](../kokoro/release/protoc/windows/build.bat). + +To upload windows artifacts, copy the built binaries into this directory and +put it into the target/windows/(x86_64|x86_32) directory the same way as the +artifacts for other platforms. That will allow the maven script to find and +upload the artifacts to maven. + +## To push artifacts to Maven Central +Before you can upload artifacts to Maven Central repository, make sure you have +read [this page](http://central.sonatype.org/pages/apache-maven.html) on how to +configure GPG and Sonatype account. + +Before you do the deployment, make sure you have built the protoc artifacts for +every supported platform and put them under the target directory. Example +target directory layout: + + + pom.xml + + target + + linux + + x86_64 + protoc.exe + + x86_32 + protoc.exe + + aarch_64 + protoc.exe + + ppcle_64 + protoc.exe + + s390x + protoc.exe + + osx + + x86_64 + protoc.exe + + x86_32 + protoc.exe + + windows + + x86_64 + protoc.exe + + x86_32 + protoc.exe + +You will need to build the artifacts on multiple machines and gather them +together into one place. + +Use the following command to deploy artifacts for the host platform to a +staging repository. + ``` -$ docker run -it --rm=true protoc-artifacts +$ mvn deploy -P release ``` -The Protobuf repository has been cloned into ``/protobuf``. - -### Tips for deploying on Windows -Under Windows the following error may occur: ``gpg: cannot open tty `no tty': -No such file or directory``. This can be fixed by configuring gpg through an -active profile in ``.m2\settings.xml`` where also the Sonatype password is -stored: -```xml - - - - sonatype-nexus-staging - [username] - [password] - - - - - gpg - - gpg - [password] - - - - - gpg - - -``` +It creates a new staging repository. Go to +https://oss.sonatype.org/#stagingRepositories and find the repository, usually +in the name like ``comgoogle-123``. Verify that the staging repository has all +the binaries, close and release this repository. + -### Tested build environments +## Tested build environments We have successfully built artifacts on the following environments: - Linux x86_32 and x86_64: - - Centos 6.6 (within Docker 1.6.1) - - Ubuntu 14.04.2 64-bit -- Windows x86_32: MSYS with ``mingw32-gcc-g++ 4.8.1-4`` on Windows 7 64-bit -- Windows x86_32: Cross compile with ``i686-w64-mingw32-g++ 4.8.2`` on Ubuntu 14.04.2 64-bit -- Windows x86_64: Cygwin64 with ``mingw64-x86_64-gcc-g++ 4.8.3-1`` on Windows 7 64-bit -- Windows x86_64: Cross compile with ``x86_64-w64-mingw32-g++ 4.8.2`` on Ubuntu 14.04.2 64-bit + - Centos 6.9 (within Docker 1.6.1) + - Ubuntu 14.04.5 64-bit +- Linux aarch_64: Cross compiled with `g++-aarch64-linux-gnu` on Ubuntu 14.04.5 64-bit - Mac OS X x86_32 and x86_64: Mac OS X 10.9.5 diff --git a/protoc-artifacts/build-protoc.sh b/protoc-artifacts/build-protoc.sh index 57523a41bf990..7f65d37643370 100755 --- a/protoc-artifacts/build-protoc.sh +++ b/protoc-artifacts/build-protoc.sh @@ -1,17 +1,34 @@ #!/bin/bash -# Builds protoc executable into target/protoc.exe; optionally build protoc -# plugins into target/protoc-gen-*.exe -# To be run from Maven. -# Usage: build-protoc.sh -# and are ${os.detected.name} and ${os.detected.arch} from os-maven-plugin -# can be "protoc" or "protoc-gen-javalite" +# Builds protoc executable into target///protoc.exe; optionally builds +# protoc plugins into target///protoc-gen-*.exe +# +# Usage: ./build-protoc.sh +# +# can be "protoc" or "protoc-gen-javalite". Supported +# combinations: +# HOST +# cygwin windows x86_32 Requires: i686-w64-mingw32-gcc +# cygwin windows x86_64 Requires: x86_64-w64-mingw32-gcc +# linux linux aarch_64 Requires: g++-aarch64-linux-gnu +# linux linux x86_32 +# linux linux x86_64 +# linux windows x86_32 Requires: i686-w64-mingw32-gcc +# linux windows x86_64 Requires: x86_64-w64-mingw32-gcc +# macos osx x86_32 +# macos osx x86_64 +# mingw windows x86_32 +# mingw windows x86_64 +# +# Before running this script, make sure you have generated the configure script +# in the parent directory (i.e., run ./autogen.sh there). + OS=$1 ARCH=$2 MAKE_TARGET=$3 if [[ $# < 3 ]]; then - echo "No arguments provided. This script is intended to be run from Maven." + echo "Not enough arguments provided." exit 1 fi @@ -21,7 +38,7 @@ case $MAKE_TARGET in protoc) ;; *) - echo "Target ""$TARGET"" invalid." + echo "Target ""$MAKE_TARGET"" invalid." exit 1 esac @@ -69,10 +86,25 @@ checkArch () format="$(objdump -f "$1" | grep -o "file format .*$" | grep -o "[^ ]*$")" echo Format=$format if [[ "$OS" == linux ]]; then + host_machine="$(uname -m)"; if [[ "$ARCH" == x86_32 ]]; then assertEq $format "elf32-i386" $LINENO elif [[ "$ARCH" == x86_64 ]]; then assertEq $format "elf64-x86-64" $LINENO + elif [[ "$ARCH" == aarch_64 ]]; then + assertEq $format "elf64-little" $LINENO + elif [[ "$ARCH" == s390x ]]; then + if [[ $host_machine == s390x ]];then + assertEq $format "elf64-s390" $LINENO + else + assertEq $format "elf64-big" $LINENO + fi + elif [[ "$ARCH" == ppcle_64 ]]; then + if [[ $host_machine == ppc64le ]];then + assertEq $format "elf64-powerpcle" $LINENO + else + assertEq $format "elf64-little" $LINENO + fi else fail "Unsupported arch: $ARCH" fi @@ -111,11 +143,25 @@ checkDependencies () dump_cmd='objdump -x '"$1"' | fgrep "DLL Name"' white_list="KERNEL32\.dll\|msvcrt\.dll" elif [[ "$OS" == linux ]]; then + host_machine="$(uname -m)"; dump_cmd='ldd '"$1" if [[ "$ARCH" == x86_32 ]]; then white_list="linux-gate\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux\.so\.2" elif [[ "$ARCH" == x86_64 ]]; then white_list="linux-vdso\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux-x86-64\.so\.2" + elif [[ "$ARCH" == s390x ]]; then + if [[ $host_machine != s390x ]];then + dump_cmd='objdump -p '"$1"' | grep NEEDED' + fi + white_list="linux-vdso64\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|libz\.so\.1\|ld64\.so\.1" + elif [[ "$ARCH" == ppcle_64 ]]; then + if [[ $host_machine != ppc64le ]];then + dump_cmd='objdump -p '"$1"' | grep NEEDED' + fi + white_list="linux-vdso64\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|libz\.so\.1\|ld64\.so\.2" + elif [[ "$ARCH" == aarch_64 ]]; then + dump_cmd='objdump -p '"$1"' | grep NEEDED' + white_list="libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux-aarch64\.so\.1" fi elif [[ "$OS" == osx ]]; then dump_cmd='otool -L '"$1"' | fgrep dylib' @@ -139,15 +185,10 @@ checkDependencies () } ############################################################################ -echo "Building protoc, OS=$OS ARCH=$ARCH TARGET=$TARGET" - -# Nested double quotes are unintuitive, but it works. -cd "$(dirname "$0")" +echo "Building protoc, OS=$OS ARCH=$ARCH TARGET=$MAKE_TARGET" -WORKING_DIR=$(pwd) CONFIGURE_ARGS="--disable-shared" -TARGET_FILE=target/$MAKE_TARGET.exe if [[ "$OS" == windows ]]; then MAKE_TARGET="${MAKE_TARGET}.exe" fi @@ -180,6 +221,14 @@ elif [[ "$(uname)" == Linux* ]]; then CXXFLAGS="$CXXFLAGS -m64" elif [[ "$ARCH" == x86_32 ]]; then CXXFLAGS="$CXXFLAGS -m32" + elif [[ "$ARCH" == aarch_64 ]]; then + CONFIGURE_ARGS="$CONFIGURE_ARGS --host=aarch64-linux-gnu" + elif [[ "$ARCH" == ppcle_64 ]]; then + CXXFLAGS="$CXXFLAGS -m64" + CONFIGURE_ARGS="$CONFIGURE_ARGS --host=powerpc64le-linux-gnu" + elif [[ "$ARCH" == s390x ]]; then + CXXFLAGS="$CXXFLAGS -m64" + CONFIGURE_ARGS="$CONFIGURE_ARGS --host=s390x-linux-gnu" else fail "Unsupported arch: $ARCH" fi @@ -223,10 +272,18 @@ fi export CXXFLAGS LDFLAGS -cd "$WORKING_DIR"/.. && ./configure $CONFIGURE_ARGS && - cd src && make clean && make $MAKE_TARGET && - cd "$WORKING_DIR" && mkdir -p target && - cp ../src/$MAKE_TARGET $TARGET_FILE || +# Nested double quotes are unintuitive, but it works. +cd "$(dirname "$0")" + +WORKING_DIR="$(pwd)" +BUILD_DIR="build/$OS/$ARCH" +TARGET_FILE="target/$OS/$ARCH/$MAKE_TARGET.exe" + +mkdir -p "$BUILD_DIR" && cd "$BUILD_DIR" && + ../../../../configure $CONFIGURE_ARGS && + cd src && make $MAKE_TARGET -j8 && + cd "$WORKING_DIR" && mkdir -p $(dirname $TARGET_FILE) && + cp $BUILD_DIR/src/$MAKE_TARGET $TARGET_FILE || exit 1 if [[ "$OS" == osx ]]; then diff --git a/protoc-artifacts/build-zip.sh b/protoc-artifacts/build-zip.sh index a124ed7ccf4c7..2a25d3cd7e170 100755 --- a/protoc-artifacts/build-zip.sh +++ b/protoc-artifacts/build-zip.sh @@ -13,12 +13,15 @@ Example: This script will download pre-built protoc or protoc plugin binaries from maven repository and create .zip packages suitable to be included in the github release page. If the target is protoc, well-known type .proto files will also be -included. Each invocation will create 5 zip packages: +included. Each invocation will create 8 zip packages: dist/--win32.zip - dist/--osx-x86_32.zip + dist/--win64.zip dist/--osx-x86_64.zip dist/--linux-x86_32.zip dist/--linux-x86_64.zip + dist/--linux-aarch_64.zip + dist/--linux-ppcle_64.zip + dist/--linux-s390x.zip EOF exit 1 fi @@ -29,10 +32,13 @@ VERSION_NUMBER=$2 # pairs. declare -a FILE_NAMES=( \ win32.zip windows-x86_32.exe \ - osx-x86_32.zip osx-x86_32.exe \ + win64.zip windows-x86_64.exe \ osx-x86_64.zip osx-x86_64.exe \ linux-x86_32.zip linux-x86_32.exe \ linux-x86_64.zip linux-x86_64.exe \ + linux-aarch_64.zip linux-aarch_64.exe \ + linux-ppcle_64.zip linux-ppcle_64.exe \ + linux-s390x.zip linux-s390x.exe \ ) # List of all well-known types to be included. @@ -78,7 +84,7 @@ copy the contents of the 'include' directory somewhere as well, for example into '/usr/local/include/'. Please refer to our official github site for more installation instructions: - https://github.com/google/protobuf + https://github.com/protocolbuffers/protobuf EOF mkdir -p dist @@ -92,7 +98,7 @@ for((i=0;i<${#FILE_NAMES[@]};i+=2));do BINARY="$TARGET" fi BINARY_NAME=${FILE_NAMES[$(($i+1))]} - BINARY_URL=http://repo1.maven.org/maven2/com/google/protobuf/$TARGET/${VERSION_NUMBER}/$TARGET-${VERSION_NUMBER}-${BINARY_NAME} + BINARY_URL=https://repo1.maven.org/maven2/com/google/protobuf/$TARGET/${VERSION_NUMBER}/$TARGET-${VERSION_NUMBER}-${BINARY_NAME} if ! wget ${BINARY_URL} -O ${DIR}/bin/$BINARY &> /dev/null; then echo "[ERROR] Failed to download ${BINARY_URL}" >&2 echo "[ERROR] Skipped $TARGET-${VERSION_NAME}-${ZIP_NAME}" >&2 diff --git a/protoc-artifacts/pom.xml b/protoc-artifacts/pom.xml index d68709ea6e87c..cbe84bb43429c 100644 --- a/protoc-artifacts/pom.xml +++ b/protoc-artifacts/pom.xml @@ -1,7 +1,5 @@ - + 4.0.0 com.google @@ -10,7 +8,7 @@ com.google.protobuf protoc - 3.4.0 + 3.15.0 pom Protobuf Compiler @@ -27,42 +25,13 @@ - https://github.com/google/protobuf + https://github.com/protocolbuffers/protobuf - scm:git:https://github.com/google/protobuf.git + scm:git:https://github.com/protocolbuffers/protobuf.git - - - kr.motd.maven - os-maven-plugin - 1.2.3.Final - - - - org.codehaus.mojo - exec-maven-plugin - 1.1.1 - - - compile - - exec - - - - - bash - - build-protoc.sh - ${os.detected.name} - ${os.detected.arch} - protoc - - - org.codehaus.mojo build-helper-maven-plugin @@ -77,8 +46,43 @@ - ${basedir}/target/protoc.exe - ${os.detected.name}-${os.detected.arch} + ${basedir}/target/linux/x86_64/protoc.exe + linux-x86_64 + exe + + + ${basedir}/target/linux/x86_32/protoc.exe + linux-x86_32 + exe + + + ${basedir}/target/windows/x86_64/protoc.exe + windows-x86_64 + exe + + + ${basedir}/target/windows/x86_32/protoc.exe + windows-x86_32 + exe + + + ${basedir}/target/osx/x86_64/protoc.exe + osx-x86_64 + exe + + + ${basedir}/target/linux/aarch_64/protoc.exe + linux-aarch_64 + exe + + + ${basedir}/target/linux/ppcle_64/protoc.exe + linux-ppcle_64 + exe + + + ${basedir}/target/linux/s390x/protoc.exe + linux-s390x exe @@ -97,7 +101,7 @@ subsequent deployments it should be set to what Sonatype has created, so that all deployments will go to the same repository. --> - + diff --git a/protoc-artifacts/scl-enable-devtoolset.sh b/protoc-artifacts/scl-enable-devtoolset.sh new file mode 100755 index 0000000000000..30895585f3a9d --- /dev/null +++ b/protoc-artifacts/scl-enable-devtoolset.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -eu -o pipefail + +quote() { + local arg + for arg in "$@"; do + printf "'" + printf "%s" "$arg" | sed -e "s/'/'\\\\''/g" + printf "' " + done +} + +exec scl enable devtoolset-2 "$(quote "$@")" diff --git a/python/.repo-metadata.json b/python/.repo-metadata.json new file mode 100644 index 0000000000000..c8d71a84ec593 --- /dev/null +++ b/python/.repo-metadata.json @@ -0,0 +1,11 @@ +{ + "name": "protobuf", + "name_pretty": "Protocol Buffers", + "product_documentation": "https://developers.google.com/protocol-buffers ", + "client_documentation": "https://developers.google.com/protocol-buffers/docs/pythontutorial", + "issue_tracker": "https://github.com/protocolbuffers/protobuf/issues", + "release_level": "ga", + "language": "python", + "repo": "protocolbuffers/protobuf ", + "distribution_name": "protobuf" +} diff --git a/python/MANIFEST.in b/python/MANIFEST.in index 260888263be9e..5fb01922a0f60 100644 --- a/python/MANIFEST.in +++ b/python/MANIFEST.in @@ -4,6 +4,9 @@ exclude google/protobuf/internal/*_test.py exclude google/protobuf/internal/*.proto exclude google/protobuf/internal/test_util.py +recursive-include google *.cc +recursive-include google *.h + recursive-exclude google *_test.py recursive-exclude google *_test.proto recursive-exclude google unittest*_pb2.py diff --git a/python/README.md b/python/README.md index 4c19429700293..cb8b7e9892e67 100644 --- a/python/README.md +++ b/python/README.md @@ -1,7 +1,7 @@ Protocol Buffers - Google's data interchange format =================================================== -[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) +[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_compatibility%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_cpp%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_cpp%2Fcontinuous) [![Compat check PyPI](https://python-compatibility-tools.appspot.com/one_badge_image?package=protobuf)](https://python-compatibility-tools.appspot.com/one_badge_target?package=protobuf) Copyright 2008 Google Inc. @@ -22,15 +22,13 @@ package. Development Warning =================== -The Python implementation of Protocol Buffers is not as mature as the C++ -and Java implementations. It may be more buggy, and it is known to be -pretty slow at this time. If you would like to help fix these issues, -join the Protocol Buffers discussion list and let us know! +The pure python performance is slow. For better performance please +use python c++ implementation. Installation ============ -1) Make sure you have Python 2.6 or newer. If in doubt, run: +1) Make sure you have Python 2.7 or newer. If in doubt, run: $ python -V diff --git a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto b/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto index a785f79faf610..95c8d4d2e32b1 100644 --- a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto +++ b/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto @@ -74,7 +74,7 @@ message FileDescriptorProto { optional FileOptions options = 8; // This field contains optional information about the original source code. - // You may safely remove this entire field whithout harming runtime + // You may safely remove this entire field without harming runtime // functionality of the descriptors -- the information is needed only by // development tools. optional SourceCodeInfo source_code_info = 9; @@ -228,7 +228,7 @@ message MethodDescriptorProto { // * For options which will be published and used publicly by multiple // independent entities, e-mail protobuf-global-extension-registry@google.com // to reserve extension numbers. Simply provide your project name (e.g. -// Object-C plugin) and your porject website (if available) -- there's no need +// Object-C plugin) and your project website (if available) -- there's no need // to explain how you intend to use them. Usually you only need one extension // number. You can declare multiple options with only one extension number by // putting them in a sub-message. See the Custom Options section of the docs diff --git a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto b/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto index e591d29447505..2f4e3fdf95c42 100644 --- a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto +++ b/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto @@ -321,7 +321,7 @@ message Aggregate { } // Allow Aggregate to be used as an option at all possible locations -// in the .proto grammer. +// in the .proto grammar. extend google.protobuf.FileOptions { optional Aggregate fileopt = 15478479; } extend google.protobuf.MessageOptions { optional Aggregate msgopt = 15480088; } extend google.protobuf.FieldOptions { optional Aggregate fieldopt = 15481374; } diff --git a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto b/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto index c115b11171afa..ec36ccadbe846 100644 --- a/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto +++ b/python/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto @@ -43,7 +43,7 @@ package protobuf_unittest_import; option optimize_for = SPEED; -// Excercise the java_package option. +// Exercise the java_package option. option java_package = "com.google.protobuf.test"; // Do not set a java_outer_classname here to verify that Proto2 works without diff --git a/python/compatibility_tests/v2.5.0/setup.py b/python/compatibility_tests/v2.5.0/setup.py index b41d54d4fefff..bf675367331ea 100755 --- a/python/compatibility_tests/v2.5.0/setup.py +++ b/python/compatibility_tests/v2.5.0/setup.py @@ -59,7 +59,7 @@ def run(self): setup( name='protobuf', description='Protocol Buffers', - download_url='https://github.com/google/protobuf/releases', + download_url='https://github.com/protocolbuffers/protobuf/releases', long_description="Protocol Buffers are Google's data interchange format", url='https://developers.google.com/protocol-buffers/', maintainer='protobuf@googlegroups.com', diff --git a/python/compatibility_tests/v2.5.0/test.sh b/python/compatibility_tests/v2.5.0/test.sh index 78c16ad1ca2bc..740c132556817 100755 --- a/python/compatibility_tests/v2.5.0/test.sh +++ b/python/compatibility_tests/v2.5.0/test.sh @@ -12,43 +12,15 @@ TEST_VERSION=2.5.0 # The old version of protobuf that we are testing compatibility against. This # is usually the same as TEST_VERSION (i.e., we use the tests extracted from # that version to test compatibility of the newest runtime against it), but it -# is also possible to use this same test set to test the compatibiilty of the +# is also possible to use this same test set to test the compatibility of the # latest version against other versions. -case "$1" in - ""|2.5.0) - OLD_VERSION=2.5.0 - OLD_VERSION_PROTOC=https://github.com/xfxyjwf/protobuf-compiler-release/raw/master/v2.5.0/linux/protoc - ;; - 2.6.1) - OLD_VERSION=2.6.1 - OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/2.6.1-build2/protoc-2.6.1-build2-linux-x86_64.exe - ;; - 3.0.0-beta-1) - OLD_VERSION=3.0.0-beta-1 - OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-1/protoc-3.0.0-beta-1-linux-x86_64.exe - ;; - 3.0.0-beta-2) - OLD_VERSION=3.0.0-beta-2 - OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-2/protoc-3.0.0-beta-2-linux-x86_64.exe - ;; - 3.0.0-beta-3) - OLD_VERSION=3.0.0-beta-3 - OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-3/protoc-3.0.0-beta-3-linux-x86_64.exe - ;; - 3.0.0-beta-4) - OLD_VERSION=3.0.0-beta-4 - OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-4/protoc-3.0.0-beta-4-linux-x86_64.exe - ;; - *) - echo "[ERROR]: Unknown version number: $1" - exit 1 - ;; -esac +OLD_VERSION=$1 +OLD_VERSION_PROTOC=https://repo1.maven.org/maven2/com/google/protobuf/protoc/$OLD_VERSION/protoc-$OLD_VERSION-linux-x86_64.exe # Extract the latest protobuf version number. VERSION_NUMBER=`grep "^__version__ = '.*'" ../../google/protobuf/__init__.py | sed "s|__version__ = '\(.*\)'|\1|"` -echo "Running compatibility tests between $VERSION_NUMBER and $OLD_VERSION" +echo "Running compatibility tests between current $VERSION_NUMBER and released $OLD_VERSION" # Check protoc [ -f ../../../src/protoc ] || { diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/generator_test.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/generator_test.py index 8343aba1e176e..feb7752c5cc47 100755 --- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/generator_test.py +++ b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/generator_test.py @@ -148,7 +148,7 @@ def testMessageWithCustomOptions(self): proto = unittest_custom_options_pb2.TestMessageWithCustomOptions() enum_options = proto.DESCRIPTOR.enum_types_by_name['AnEnum'].GetOptions() self.assertTrue(enum_options is not None) - # TODO(gps): We really should test for the presense of the enum_opt1 + # TODO(gps): We really should test for the presence of the enum_opt1 # extension and for its value to be set to -789. def testNestedTypes(self): diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/message_test.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/message_test.py index 53e9d50780fb4..e71b295bb6e46 100755 --- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/message_test.py +++ b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/message_test.py @@ -55,6 +55,11 @@ from google.protobuf.internal import test_util from google.protobuf import message +try: + cmp # Python 2 +except NameError: + cmp = lambda x, y: (x > y) - (x < y) # Python 3 + # Python pre-2.6 does not have isinf() or isnan() functions, so we have # to provide our own. def isnan(val): diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/service_reflection_test.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/service_reflection_test.py index e04f8252c0400..9b7356ffa8dc7 100755 --- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/service_reflection_test.py +++ b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/service_reflection_test.py @@ -80,7 +80,7 @@ def MyCallback(response): self.assertEqual('Method Bar not implemented.', rpc_controller.failure_message) self.assertEqual(None, self.callback_response) - + class MyServiceImpl(unittest_pb2.TestService): def Foo(self, rpc_controller, request, done): self.foo_called = True @@ -118,7 +118,7 @@ def MyCallback(response): rpc_controller = 'controller' request = 'request' - # GetDescriptor now static, still works as instance method for compatability + # GetDescriptor now static, still works as instance method for compatibility self.assertEqual(unittest_pb2.TestService_Stub.GetDescriptor(), stub.GetDescriptor()) diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/test_util.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/test_util.py old mode 100755 new mode 100644 diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_test.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_test.py index 8267cd2c65b1f..0bee668a3e81c 100755 --- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_test.py +++ b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_test.py @@ -247,8 +247,8 @@ def RemoveRedundantZeros(self, text): text = text.replace('e+0','e+').replace('e+0','e+') \ .replace('e-0','e-').replace('e-0','e-') # Floating point fields are printed with .0 suffix even if they are - # actualy integer numbers. - text = re.compile('\.0$', re.MULTILINE).sub('', text) + # actually integer numbers. + text = re.compile(r'\.0$', re.MULTILINE).sub('', text) return text def testMergeGolden(self): @@ -410,7 +410,8 @@ def testMergeBadEnumValue(self): text = 'optional_nested_enum: BARR' self.assertRaisesWithMessage( text_format.ParseError, - ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" ' + ('1:23 : \'optional_nested_enum: BARR\': ' + 'Enum type "protobuf_unittest.TestAllTypes.NestedEnum" ' 'has no value named BARR.'), text_format.Merge, text, message) @@ -418,7 +419,8 @@ def testMergeBadEnumValue(self): text = 'optional_nested_enum: 100' self.assertRaisesWithMessage( text_format.ParseError, - ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" ' + ('1:23 : \'optional_nested_enum: 100\': ' + 'Enum type "protobuf_unittest.TestAllTypes.NestedEnum" ' 'has no value with number 100.'), text_format.Merge, text, message) @@ -427,7 +429,8 @@ def testMergeBadIntValue(self): text = 'optional_int32: bork' self.assertRaisesWithMessage( text_format.ParseError, - ('1:17 : Couldn\'t parse integer: bork'), + ('1:17 : \'optional_int32: bork\': ' + 'Couldn\'t parse integer: bork'), text_format.Merge, text, message) def testMergeStringFieldUnescape(self): diff --git a/python/docs/Makefile b/python/docs/Makefile new file mode 100644 index 0000000000000..298ea9e213e8c --- /dev/null +++ b/python/docs/Makefile @@ -0,0 +1,19 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/python/docs/conf.py b/python/docs/conf.py new file mode 100644 index 0000000000000..913f012838921 --- /dev/null +++ b/python/docs/conf.py @@ -0,0 +1,254 @@ +# -*- coding: utf-8 -*- +# Protocol Buffers - Google's data interchange format +# Copyright 2019 Google LLC. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google 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. + +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) +import google.protobuf + +# -- Project information ----------------------------------------------------- + +project = u"Protocol Buffers" +copyright = u"2008, Google LLC" +author = u"Google LLC" + +# The short X.Y version +version = u"" +# The full version, including alpha/beta/rc tags +release = google.protobuf.__version__ + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + "sphinx.ext.autosummary", + "sphinx.ext.ifconfig", + "sphinx.ext.intersphinx", + "sphinx.ext.napoleon", +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = ".rst" + +# The master toctree document. +master_doc = "index" + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [u"_build", "Thumbs.db", ".DS_Store"] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = None + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "alabaster" + +# Remove JavaScript. +html_js_files = [] + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] + +html_show_sourcelink = True + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. + +# Remove searchbox.html to avoid embedded JavaScript. +html_sidebars = { + "**": [ + "globaltoc.html", "localtoc.html", "relations.html", "sourcelink.html", + ], +} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = "ProtocolBuffersdoc" + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ( + master_doc, + "ProtocolBuffers.tex", + "Protocol Buffers Documentation", + "Google LLC", + "manual", + ) +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ( + master_doc, # source start file + "protocolbuffers", # name + "Protocol Buffers Documentation", # description + [author], # authors + 1, # manual section + ) +] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ( + master_doc, + "ProtocolBuffers", + u"Protocol Buffers Documentation", + author, + "ProtocolBuffers", + "One line description of project.", + "Miscellaneous", + ) +] + + +# -- Options for Epub output ------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +# +# epub_identifier = '' + +# A unique identification for the text. +# +# epub_uid = '' + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ["search.html"] + + +# -- Extension configuration ------------------------------------------------- + +# -- Options for autosummary extension --------------------------------------- +autosummary_generate = True + +# -- Options for intersphinx extension --------------------------------------- + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {"https://docs.python.org/": None} + +# -- Config values ----------------------------------------------------------- +# The setup() function is needed to add configuration values to the Sphinx +# builder. We use this to show a banner when built on Read the Docs. +# https://www.sphinx-doc.org/en/master/usage/extensions/ifconfig.html + +def setup(app): + app.add_config_value( + "build_env", + # Read the Docs sets a READTHEDOCS environment during builds. + # https://docs.readthedocs.io/en/stable/builds.html#build-environment + "readthedocs" if os.getenv("READTHEDOCS") else "", + "env" + ) diff --git a/python/docs/environment.yml b/python/docs/environment.yml new file mode 100644 index 0000000000000..0f6390e69861d --- /dev/null +++ b/python/docs/environment.yml @@ -0,0 +1,10 @@ +name: protobuf +channels: + - defaults +dependencies: + - libprotobuf=3.11.4 + - make=4.2.1 + - pip=19.3.1 + - python=3.7.6 + - sphinx=2.4.0 + - sphinx_rtd_theme=0.4.3 diff --git a/python/docs/generate_docs.py b/python/docs/generate_docs.py new file mode 100755 index 0000000000000..e024aaa47909d --- /dev/null +++ b/python/docs/generate_docs.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Script to generate a list of all modules to use in autosummary. + +This script creates a ReStructured Text file for each public module in the +protobuf Python package. The script also updates the table of contents in +``docs/index.rst`` to point to these module references. + +To build the docs with Sphinx: + +1. Install the needed packages (``sphinx``, ``sphinxcontrib-napoleon`` for + Google-style docstring support). I've created a conda environment file to + make this easier: + +.. code:: bash + + conda env create -f python/docs/environment.yml + +2. (Optional) Generate reference docs files and regenerate index: + +.. code:: bash + + cd python/docs + python generate_docs.py + +3. Run Sphinx. + +.. code:: bash + + make html +""" + +import pathlib +import re + + +DOCS_DIR = pathlib.Path(__file__).parent.resolve() +PYTHON_DIR = DOCS_DIR.parent +SOURCE_DIR = PYTHON_DIR / "google" / "protobuf" +SOURCE_POSIX = SOURCE_DIR.as_posix() + +# Modules which are always included: +INCLUDED_MODULES = ( + "google.protobuf.internal.containers", +) + +# Packages to ignore, including all modules (unless in INCLUDED_MODULES): +IGNORED_PACKAGES = ( + "compiler", + "docs", + "internal", + "pyext", + "util", +) + +# Ignored module stems in all packages (unless in INCLUDED_MODULES): +IGNORED_MODULES = ( + "any_test_pb2", + "api_pb2", + "unittest", + "source_context_pb2", + "test_messages_proto3_pb2", + "test_messages_proto2", +) + +TOC_REGEX = re.compile( + r"\.\. START REFTOC.*\.\. END REFTOC\.\n", + flags=re.DOTALL, +) +TOC_TEMPLATE = """.. START REFTOC, generated by generate_docs.py. +.. toctree:: + + {toctree} + +.. END REFTOC. +""" + +AUTOMODULE_TEMPLATE = """.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +{module} +{underline} + +.. automodule:: {module} + :members: + :inherited-members: + :undoc-members: +""" + + +def find_modules(): + modules = [] + for module_path in SOURCE_DIR.glob("**/*.py"): + # Determine the (dotted) relative package and module names. + package_path = module_path.parent.relative_to(PYTHON_DIR) + if package_path == SOURCE_DIR: + package_name = "" + module_name = module_path.stem + else: + package_name = package_path.as_posix().replace("/", ".") + module_name = package_name + "." + module_path.stem + + # Filter: first, accept anything in the whitelist; then, reject anything + # at package level, then module name level. + if any(include == module_name for include in INCLUDED_MODULES): + pass + elif any(ignored in package_name for ignored in IGNORED_PACKAGES): + continue + elif any(ignored in module_path.stem for ignored in IGNORED_MODULES): + continue + + if module_path.name == "__init__.py": + modules.append(package_name) + else: + modules.append(module_name) + + return modules + + +def write_automodule(module): + contents = AUTOMODULE_TEMPLATE.format(module=module, underline="=" * len(module),) + automodule_path = DOCS_DIR.joinpath(*module.split(".")).with_suffix(".rst") + try: + automodule_path.parent.mkdir(parents=True) + except FileExistsError: + pass + with open(automodule_path, "w") as automodule_file: + automodule_file.write(contents) + + +def replace_toc(modules): + toctree = [module.replace(".", "/") for module in modules] + with open(DOCS_DIR / "index.rst", "r") as index_file: + index_contents = index_file.read() + toc = TOC_TEMPLATE.format( + toctree="\n ".join(toctree) + ) + index_contents = re.sub(TOC_REGEX, toc, index_contents) + with open(DOCS_DIR / "index.rst", "w") as index_file: + index_file.write(index_contents) + + +def main(): + modules = list(sorted(find_modules())) + for module in modules: + print("Generating reference for {}".format(module)) + write_automodule(module) + print("Generating index.rst") + replace_toc(modules) + +if __name__ == "__main__": + main() diff --git a/python/docs/google/protobuf.rst b/python/docs/google/protobuf.rst new file mode 100644 index 0000000000000..b26102e110508 --- /dev/null +++ b/python/docs/google/protobuf.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf +=============== + +.. automodule:: google.protobuf + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/any_pb2.rst b/python/docs/google/protobuf/any_pb2.rst new file mode 100644 index 0000000000000..b6f47ef3fd387 --- /dev/null +++ b/python/docs/google/protobuf/any_pb2.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.any_pb2 +======================= + +.. automodule:: google.protobuf.any_pb2 + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/descriptor.rst b/python/docs/google/protobuf/descriptor.rst new file mode 100644 index 0000000000000..29b07746f4553 --- /dev/null +++ b/python/docs/google/protobuf/descriptor.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.descriptor +========================== + +.. automodule:: google.protobuf.descriptor + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/descriptor_database.rst b/python/docs/google/protobuf/descriptor_database.rst new file mode 100644 index 0000000000000..1b8b3904d8c49 --- /dev/null +++ b/python/docs/google/protobuf/descriptor_database.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.descriptor_database +=================================== + +.. automodule:: google.protobuf.descriptor_database + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/descriptor_pb2.rst b/python/docs/google/protobuf/descriptor_pb2.rst new file mode 100644 index 0000000000000..94eec35c347b0 --- /dev/null +++ b/python/docs/google/protobuf/descriptor_pb2.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.descriptor_pb2 +============================== + +.. automodule:: google.protobuf.descriptor_pb2 + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/descriptor_pool.rst b/python/docs/google/protobuf/descriptor_pool.rst new file mode 100644 index 0000000000000..c2ee33e7b3555 --- /dev/null +++ b/python/docs/google/protobuf/descriptor_pool.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.descriptor_pool +=============================== + +.. automodule:: google.protobuf.descriptor_pool + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/duration_pb2.rst b/python/docs/google/protobuf/duration_pb2.rst new file mode 100644 index 0000000000000..4233e3cb52b7c --- /dev/null +++ b/python/docs/google/protobuf/duration_pb2.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.duration_pb2 +============================ + +.. automodule:: google.protobuf.duration_pb2 + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/empty_pb2.rst b/python/docs/google/protobuf/empty_pb2.rst new file mode 100644 index 0000000000000..c386a4c5c9060 --- /dev/null +++ b/python/docs/google/protobuf/empty_pb2.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.empty_pb2 +========================= + +.. automodule:: google.protobuf.empty_pb2 + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/field_mask_pb2.rst b/python/docs/google/protobuf/field_mask_pb2.rst new file mode 100644 index 0000000000000..d9d807069ee45 --- /dev/null +++ b/python/docs/google/protobuf/field_mask_pb2.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.field_mask_pb2 +============================== + +.. automodule:: google.protobuf.field_mask_pb2 + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/internal/containers.rst b/python/docs/google/protobuf/internal/containers.rst new file mode 100644 index 0000000000000..c3b8e594a77f1 --- /dev/null +++ b/python/docs/google/protobuf/internal/containers.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.internal.containers +=================================== + +.. automodule:: google.protobuf.internal.containers + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/json_format.rst b/python/docs/google/protobuf/json_format.rst new file mode 100644 index 0000000000000..eb3b0c539967b --- /dev/null +++ b/python/docs/google/protobuf/json_format.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.json_format +=========================== + +.. automodule:: google.protobuf.json_format + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/message.rst b/python/docs/google/protobuf/message.rst new file mode 100644 index 0000000000000..a20424807cd36 --- /dev/null +++ b/python/docs/google/protobuf/message.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.message +======================= + +.. automodule:: google.protobuf.message + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/message_factory.rst b/python/docs/google/protobuf/message_factory.rst new file mode 100644 index 0000000000000..93183cc03d445 --- /dev/null +++ b/python/docs/google/protobuf/message_factory.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.message_factory +=============================== + +.. automodule:: google.protobuf.message_factory + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/proto_builder.rst b/python/docs/google/protobuf/proto_builder.rst new file mode 100644 index 0000000000000..36243a2ffff51 --- /dev/null +++ b/python/docs/google/protobuf/proto_builder.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.proto_builder +============================= + +.. automodule:: google.protobuf.proto_builder + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/reflection.rst b/python/docs/google/protobuf/reflection.rst new file mode 100644 index 0000000000000..d177fc02f65e6 --- /dev/null +++ b/python/docs/google/protobuf/reflection.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.reflection +========================== + +.. automodule:: google.protobuf.reflection + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/service.rst b/python/docs/google/protobuf/service.rst new file mode 100644 index 0000000000000..6d71f810887c8 --- /dev/null +++ b/python/docs/google/protobuf/service.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.service +======================= + +.. automodule:: google.protobuf.service + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/service_reflection.rst b/python/docs/google/protobuf/service_reflection.rst new file mode 100644 index 0000000000000..30f30dd29358a --- /dev/null +++ b/python/docs/google/protobuf/service_reflection.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.service_reflection +================================== + +.. automodule:: google.protobuf.service_reflection + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/struct_pb2.rst b/python/docs/google/protobuf/struct_pb2.rst new file mode 100644 index 0000000000000..9179eede3cc59 --- /dev/null +++ b/python/docs/google/protobuf/struct_pb2.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.struct_pb2 +========================== + +.. automodule:: google.protobuf.struct_pb2 + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/symbol_database.rst b/python/docs/google/protobuf/symbol_database.rst new file mode 100644 index 0000000000000..6ea73522f532c --- /dev/null +++ b/python/docs/google/protobuf/symbol_database.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.symbol_database +=============================== + +.. automodule:: google.protobuf.symbol_database + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/text_encoding.rst b/python/docs/google/protobuf/text_encoding.rst new file mode 100644 index 0000000000000..a2eb959dc0d04 --- /dev/null +++ b/python/docs/google/protobuf/text_encoding.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.text_encoding +============================= + +.. automodule:: google.protobuf.text_encoding + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/text_format.rst b/python/docs/google/protobuf/text_format.rst new file mode 100644 index 0000000000000..686b8fc002b1c --- /dev/null +++ b/python/docs/google/protobuf/text_format.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.text_format +=========================== + +.. automodule:: google.protobuf.text_format + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/timestamp_pb2.rst b/python/docs/google/protobuf/timestamp_pb2.rst new file mode 100644 index 0000000000000..540df8395d48e --- /dev/null +++ b/python/docs/google/protobuf/timestamp_pb2.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.timestamp_pb2 +============================= + +.. automodule:: google.protobuf.timestamp_pb2 + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/type_pb2.rst b/python/docs/google/protobuf/type_pb2.rst new file mode 100644 index 0000000000000..e9b19d7b8582b --- /dev/null +++ b/python/docs/google/protobuf/type_pb2.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.type_pb2 +======================== + +.. automodule:: google.protobuf.type_pb2 + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/google/protobuf/wrappers_pb2.rst b/python/docs/google/protobuf/wrappers_pb2.rst new file mode 100644 index 0000000000000..8f29aa7838b02 --- /dev/null +++ b/python/docs/google/protobuf/wrappers_pb2.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.wrappers_pb2 +============================ + +.. automodule:: google.protobuf.wrappers_pb2 + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/index.rst b/python/docs/index.rst new file mode 100644 index 0000000000000..5535b398a9521 --- /dev/null +++ b/python/docs/index.rst @@ -0,0 +1,63 @@ +.. Protocol Buffers documentation master file, created by + sphinx-quickstart on Thu Aug 15 13:56:43 2019. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +Protocol Buffers Python API Reference +===================================== + +The complete documentation for Protocol Buffers is available via the web at: + + https://developers.google.com/protocol-buffers/ + + +Modules and Packages +-------------------- + +.. START REFTOC, generated by generate_docs.py. +.. toctree:: + + google/protobuf + google/protobuf/any_pb2 + google/protobuf/descriptor + google/protobuf/descriptor_database + google/protobuf/descriptor_pb2 + google/protobuf/descriptor_pool + google/protobuf/duration_pb2 + google/protobuf/empty_pb2 + google/protobuf/field_mask_pb2 + google/protobuf/internal/containers + google/protobuf/json_format + google/protobuf/message + google/protobuf/message_factory + google/protobuf/proto_builder + google/protobuf/reflection + google/protobuf/service + google/protobuf/service_reflection + google/protobuf/struct_pb2 + google/protobuf/symbol_database + google/protobuf/text_encoding + google/protobuf/text_format + google/protobuf/timestamp_pb2 + google/protobuf/type_pb2 + google/protobuf/wrappers_pb2 + +.. END REFTOC. + +Indices and tables +------------------ + +* :ref:`genindex` +* :ref:`modindex` diff --git a/python/docs/make.bat b/python/docs/make.bat new file mode 100644 index 0000000000000..27f573b87af11 --- /dev/null +++ b/python/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/python/docs/requirements.txt b/python/docs/requirements.txt new file mode 100644 index 0000000000000..2b3e98925ec72 --- /dev/null +++ b/python/docs/requirements.txt @@ -0,0 +1,3 @@ +sphinx==2.3.1 +sphinx_rtd_theme==0.4.3 +sphinxcontrib-napoleon==0.7 diff --git a/python/google/__init__.py b/python/google/__init__.py old mode 100755 new mode 100644 diff --git a/python/google/protobuf/__init__.py b/python/google/protobuf/__init__.py old mode 100755 new mode 100644 index d26da0dfc1fa0..6c20545faeff0 --- a/python/google/protobuf/__init__.py +++ b/python/google/protobuf/__init__.py @@ -30,10 +30,4 @@ # Copyright 2007 Google Inc. All Rights Reserved. -__version__ = '3.4.0' - -if __name__ != '__main__': - try: - __import__('pkg_resources').declare_namespace(__name__) - except ImportError: - __path__ = __import__('pkgutil').extend_path(__path__, __name__) +__version__ = '3.15.0' diff --git a/python/google/protobuf/compiler/__init__.py b/python/google/protobuf/compiler/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py old mode 100755 new mode 100644 index b1f3ca38d7141..190b89536fdfd --- a/python/google/protobuf/descriptor.py +++ b/python/google/protobuf/descriptor.py @@ -34,6 +34,8 @@ __author__ = 'robinson@google.com (Will Robinson)' +import threading +import warnings import six from google.protobuf.internal import api_implementation @@ -41,10 +43,10 @@ _USE_C_DESCRIPTORS = False if api_implementation.Type() == 'cpp': # Used by MakeDescriptor in cpp mode + import binascii import os - import uuid from google.protobuf.pyext import _message - _USE_C_DESCRIPTORS = getattr(_message, '_USE_C_DESCRIPTORS', False) + _USE_C_DESCRIPTORS = True class Error(Exception): @@ -72,6 +74,43 @@ def __instancecheck__(cls, obj): DescriptorMetaclass = type +class _Lock(object): + """Wrapper class of threading.Lock(), which is allowed by 'with'.""" + + def __new__(cls): + self = object.__new__(cls) + self._lock = threading.Lock() # pylint: disable=protected-access + return self + + def __enter__(self): + self._lock.acquire() + + def __exit__(self, exc_type, exc_value, exc_tb): + self._lock.release() + + +_lock = threading.Lock() + + +def _Deprecated(name): + if _Deprecated.count > 0: + _Deprecated.count -= 1 + warnings.warn( + 'Call to deprecated create function %s(). Note: Create unlinked ' + 'descriptors is going to go away. Please use get/find descriptors from ' + 'generated code or query the descriptor_pool.' + % name, + category=DeprecationWarning, stacklevel=3) + + +# Deprecated warnings will print 100 times at most which should be enough for +# users to notice and do not cause timeout. +_Deprecated.count = 100 + + +_internal_create_key = object() + + class DescriptorBase(six.with_metaclass(DescriptorMetaclass)): """Descriptors base class. @@ -92,16 +131,17 @@ class DescriptorBase(six.with_metaclass(DescriptorMetaclass)): # subclasses" of this descriptor class. _C_DESCRIPTOR_CLASS = () - def __init__(self, options, options_class_name): + def __init__(self, options, serialized_options, options_class_name): """Initialize the descriptor given its options message and the name of the class of the options message. The name of the class is required in case the options message is None and has to be created. """ self._options = options self._options_class_name = options_class_name + self._serialized_options = serialized_options # Does this descriptor have non-default options? - self.has_options = options is not None + self.has_options = (options is not None) or (serialized_options is not None) def _SetOptions(self, options, options_class_name): """Sets the descriptor's options @@ -123,14 +163,23 @@ def GetOptions(self): """ if self._options: return self._options + from google.protobuf import descriptor_pb2 try: - options_class = getattr(descriptor_pb2, self._options_class_name) + options_class = getattr(descriptor_pb2, + self._options_class_name) except AttributeError: raise RuntimeError('Unknown options class name %s!' % (self._options_class_name)) - self._options = options_class() - return self._options + + with _lock: + if self._serialized_options is None: + self._options = options_class() + else: + self._options = _ParseOptions(options_class(), + self._serialized_options) + + return self._options class _NestedDescriptorBase(DescriptorBase): @@ -138,28 +187,28 @@ class _NestedDescriptorBase(DescriptorBase): def __init__(self, options, options_class_name, name, full_name, file, containing_type, serialized_start=None, - serialized_end=None): + serialized_end=None, serialized_options=None): """Constructor. Args: options: Protocol message options or None to use default message options. - options_class_name: (str) The class name of the above options. - - name: (str) Name of this protocol message type. - full_name: (str) Fully-qualified name of this protocol message type, + options_class_name (str): The class name of the above options. + name (str): Name of this protocol message type. + full_name (str): Fully-qualified name of this protocol message type, which will include protocol "package" name and the name of any enclosing types. - file: (FileDescriptor) Reference to file info. + file (FileDescriptor): Reference to file info. containing_type: if provided, this is a nested descriptor, with this descriptor as parent, otherwise None. serialized_start: The start index (inclusive) in block in the file.serialized_pb that describes this descriptor. serialized_end: The end index (exclusive) in block in the file.serialized_pb that describes this descriptor. + serialized_options: Protocol message serialized options or None. """ super(_NestedDescriptorBase, self).__init__( - options, options_class_name) + options, serialized_options, options_class_name) self.name = name # TODO(falk): Add function to calculate full_name instead of having it in @@ -178,7 +227,8 @@ def CopyToProto(self, proto): proto: An empty proto instance from descriptor_pb2. Raises: - Error: If self couldnt be serialized, due to to few constructor arguments. + Error: If self couldn't be serialized, due to to few constructor + arguments. """ if (self.file is not None and self._serialized_start is not None and @@ -193,66 +243,70 @@ class Descriptor(_NestedDescriptorBase): """Descriptor for a protocol message type. - A Descriptor instance has the following attributes: - - name: (str) Name of this protocol message type. - full_name: (str) Fully-qualified name of this protocol message type, - which will include protocol "package" name and the name of any - enclosing types. - - containing_type: (Descriptor) Reference to the descriptor of the - type containing us, or None if this is top-level. - - fields: (list of FieldDescriptors) Field descriptors for all - fields in this type. - fields_by_number: (dict int -> FieldDescriptor) Same FieldDescriptor - objects as in |fields|, but indexed by "number" attribute in each - FieldDescriptor. - fields_by_name: (dict str -> FieldDescriptor) Same FieldDescriptor - objects as in |fields|, but indexed by "name" attribute in each - FieldDescriptor. - fields_by_camelcase_name: (dict str -> FieldDescriptor) Same - FieldDescriptor objects as in |fields|, but indexed by - "camelcase_name" attribute in each FieldDescriptor. - - nested_types: (list of Descriptors) Descriptor references - for all protocol message types nested within this one. - nested_types_by_name: (dict str -> Descriptor) Same Descriptor - objects as in |nested_types|, but indexed by "name" attribute - in each Descriptor. - - enum_types: (list of EnumDescriptors) EnumDescriptor references - for all enums contained within this type. - enum_types_by_name: (dict str ->EnumDescriptor) Same EnumDescriptor - objects as in |enum_types|, but indexed by "name" attribute - in each EnumDescriptor. - enum_values_by_name: (dict str -> EnumValueDescriptor) Dict mapping - from enum value name to EnumValueDescriptor for that value. - - extensions: (list of FieldDescriptor) All extensions defined directly - within this message type (NOT within a nested type). - extensions_by_name: (dict, string -> FieldDescriptor) Same FieldDescriptor - objects as |extensions|, but indexed by "name" attribute of each - FieldDescriptor. - - is_extendable: Does this type define any extension ranges? - - oneofs: (list of OneofDescriptor) The list of descriptors for oneof fields - in this message. - oneofs_by_name: (dict str -> OneofDescriptor) Same objects as in |oneofs|, - but indexed by "name" attribute. - - file: (FileDescriptor) Reference to file descriptor. + Attributes: + name (str): Name of this protocol message type. + full_name (str): Fully-qualified name of this protocol message type, + which will include protocol "package" name and the name of any + enclosing types. + containing_type (Descriptor): Reference to the descriptor of the type + containing us, or None if this is top-level. + fields (list[FieldDescriptor]): Field descriptors for all fields in + this type. + fields_by_number (dict(int, FieldDescriptor)): Same + :class:`FieldDescriptor` objects as in :attr:`fields`, but indexed + by "number" attribute in each FieldDescriptor. + fields_by_name (dict(str, FieldDescriptor)): Same + :class:`FieldDescriptor` objects as in :attr:`fields`, but indexed by + "name" attribute in each :class:`FieldDescriptor`. + nested_types (list[Descriptor]): Descriptor references + for all protocol message types nested within this one. + nested_types_by_name (dict(str, Descriptor)): Same Descriptor + objects as in :attr:`nested_types`, but indexed by "name" attribute + in each Descriptor. + enum_types (list[EnumDescriptor]): :class:`EnumDescriptor` references + for all enums contained within this type. + enum_types_by_name (dict(str, EnumDescriptor)): Same + :class:`EnumDescriptor` objects as in :attr:`enum_types`, but + indexed by "name" attribute in each EnumDescriptor. + enum_values_by_name (dict(str, EnumValueDescriptor)): Dict mapping + from enum value name to :class:`EnumValueDescriptor` for that value. + extensions (list[FieldDescriptor]): All extensions defined directly + within this message type (NOT within a nested type). + extensions_by_name (dict(str, FieldDescriptor)): Same FieldDescriptor + objects as :attr:`extensions`, but indexed by "name" attribute of each + FieldDescriptor. + is_extendable (bool): Does this type define any extension ranges? + oneofs (list[OneofDescriptor]): The list of descriptors for oneof fields + in this message. + oneofs_by_name (dict(str, OneofDescriptor)): Same objects as in + :attr:`oneofs`, but indexed by "name" attribute. + file (FileDescriptor): Reference to file descriptor. + """ if _USE_C_DESCRIPTORS: _C_DESCRIPTOR_CLASS = _message.Descriptor - def __new__(cls, name, full_name, filename, containing_type, fields, - nested_types, enum_types, extensions, options=None, - is_extendable=True, extension_ranges=None, oneofs=None, - file=None, serialized_start=None, serialized_end=None, # pylint: disable=redefined-builtin - syntax=None): + def __new__( + cls, + name=None, + full_name=None, + filename=None, + containing_type=None, + fields=None, + nested_types=None, + enum_types=None, + extensions=None, + options=None, + serialized_options=None, + is_extendable=True, + extension_ranges=None, + oneofs=None, + file=None, # pylint: disable=redefined-builtin + serialized_start=None, + serialized_end=None, + syntax=None, + create_key=None): _message.Message._CheckCalledFromGeneratedFile() return _message.default_pool.FindMessageTypeByName(full_name) @@ -261,19 +315,23 @@ def __new__(cls, name, full_name, filename, containing_type, fields, # name of the argument. def __init__(self, name, full_name, filename, containing_type, fields, nested_types, enum_types, extensions, options=None, + serialized_options=None, is_extendable=True, extension_ranges=None, oneofs=None, file=None, serialized_start=None, serialized_end=None, # pylint: disable=redefined-builtin - syntax=None): + syntax=None, create_key=None): """Arguments to __init__() are as described in the description of Descriptor fields above. Note that filename is an obsolete argument, that is not used anymore. Please use file.name to access this as an attribute. """ + if create_key is not _internal_create_key: + _Deprecated('Descriptor') + super(Descriptor, self).__init__( options, 'MessageOptions', name, full_name, file, containing_type, serialized_start=serialized_start, - serialized_end=serialized_end) + serialized_end=serialized_end, serialized_options=serialized_options) # We have fields in addition to fields_by_name and fields_by_number, # so that: @@ -313,6 +371,9 @@ def __init__(self, name, full_name, filename, containing_type, fields, @property def fields_by_camelcase_name(self): + """Same FieldDescriptor objects as in :attr:`fields`, but indexed by + :attr:`FieldDescriptor.camelcase_name`. + """ if self._fields_by_camelcase_name is None: self._fields_by_camelcase_name = dict( (f.camelcase_name, f) for f in self.fields) @@ -361,53 +422,51 @@ class FieldDescriptor(DescriptorBase): """Descriptor for a single field in a .proto file. - A FieldDescriptor instance has the following attributes: - - name: (str) Name of this field, exactly as it appears in .proto. - full_name: (str) Name of this field, including containing scope. This is + Attributes: + name (str): Name of this field, exactly as it appears in .proto. + full_name (str): Name of this field, including containing scope. This is particularly relevant for extensions. - camelcase_name: (str) Camelcase name of this field. - index: (int) Dense, 0-indexed index giving the order that this + index (int): Dense, 0-indexed index giving the order that this field textually appears within its message in the .proto file. - number: (int) Tag number declared for this field in the .proto file. + number (int): Tag number declared for this field in the .proto file. - type: (One of the TYPE_* constants below) Declared type. - cpp_type: (One of the CPPTYPE_* constants below) C++ type used to + type (int): (One of the TYPE_* constants below) Declared type. + cpp_type (int): (One of the CPPTYPE_* constants below) C++ type used to represent this field. - label: (One of the LABEL_* constants below) Tells whether this + label (int): (One of the LABEL_* constants below) Tells whether this field is optional, required, or repeated. - has_default_value: (bool) True if this field has a default value defined, + has_default_value (bool): True if this field has a default value defined, otherwise false. - default_value: (Varies) Default value of this field. Only + default_value (Varies): Default value of this field. Only meaningful for non-repeated scalar fields. Repeated fields should always set this to [], and non-repeated composite fields should always set this to None. - containing_type: (Descriptor) Descriptor of the protocol message + containing_type (Descriptor): Descriptor of the protocol message type that contains this field. Set by the Descriptor constructor if we're passed into one. Somewhat confusingly, for extension fields, this is the descriptor of the EXTENDED message, not the descriptor of the message containing this field. (See is_extension and extension_scope below). - message_type: (Descriptor) If a composite field, a descriptor + message_type (Descriptor): If a composite field, a descriptor of the message type contained in this field. Otherwise, this is None. - enum_type: (EnumDescriptor) If this field contains an enum, a + enum_type (EnumDescriptor): If this field contains an enum, a descriptor of that enum. Otherwise, this is None. is_extension: True iff this describes an extension field. - extension_scope: (Descriptor) Only meaningful if is_extension is True. + extension_scope (Descriptor): Only meaningful if is_extension is True. Gives the message that immediately contains this extension field. Will be None iff we're a top-level (file-level) extension field. - options: (descriptor_pb2.FieldOptions) Protocol message field options or + options (descriptor_pb2.FieldOptions): Protocol message field options or None to use default field options. - containing_oneof: (OneofDescriptor) If the field is a member of a oneof + containing_oneof (OneofDescriptor): If the field is a member of a oneof union, contains its descriptor. Otherwise, None. - file: (FileDescriptor) Reference to file descriptor. + file (FileDescriptor): Reference to file descriptor. """ # Must be consistent with C++ FieldDescriptor::Type enum in @@ -492,8 +551,9 @@ class FieldDescriptor(DescriptorBase): def __new__(cls, name, full_name, index, number, type, cpp_type, label, default_value, message_type, enum_type, containing_type, is_extension, extension_scope, options=None, + serialized_options=None, has_default_value=True, containing_oneof=None, json_name=None, - file=None): + file=None, create_key=None): # pylint: disable=redefined-builtin _message.Message._CheckCalledFromGeneratedFile() if is_extension: return _message.default_pool.FindExtensionByName(full_name) @@ -503,8 +563,9 @@ def __new__(cls, name, full_name, index, number, type, cpp_type, label, def __init__(self, name, full_name, index, number, type, cpp_type, label, default_value, message_type, enum_type, containing_type, is_extension, extension_scope, options=None, + serialized_options=None, has_default_value=True, containing_oneof=None, json_name=None, - file=None): + file=None, create_key=None): # pylint: disable=redefined-builtin """The arguments are as described in the description of FieldDescriptor attributes above. @@ -512,7 +573,11 @@ def __init__(self, name, full_name, index, number, type, cpp_type, label, (to deal with circular references between message types, for example). Likewise for extension_scope. """ - super(FieldDescriptor, self).__init__(options, 'FieldOptions') + if create_key is not _internal_create_key: + _Deprecated('FieldDescriptor') + + super(FieldDescriptor, self).__init__( + options, serialized_options, 'FieldOptions') self.name = name self.full_name = full_name self.file = file @@ -544,6 +609,11 @@ def __init__(self, name, full_name, index, number, type, cpp_type, label, @property def camelcase_name(self): + """Camelcase name of this field. + + Returns: + str: the name in CamelCase. + """ if self._camelcase_name is None: self._camelcase_name = _ToCamelCase(self.name) return self._camelcase_name @@ -559,7 +629,7 @@ def ProtoTypeToCppProtoType(proto_type): Args: proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*) Returns: - descriptor.FieldDescriptor.CPPTYPE_*, the C++ type. + int: descriptor.FieldDescriptor.CPPTYPE_*, the C++ type. Raises: TypeTransformationError: when the Python proto type isn't known. """ @@ -573,24 +643,23 @@ class EnumDescriptor(_NestedDescriptorBase): """Descriptor for an enum defined in a .proto file. - An EnumDescriptor instance has the following attributes: - - name: (str) Name of the enum type. - full_name: (str) Full name of the type, including package name + Attributes: + name (str): Name of the enum type. + full_name (str): Full name of the type, including package name and any enclosing type(s). - values: (list of EnumValueDescriptors) List of the values + values (list[EnumValueDescriptors]): List of the values in this enum. - values_by_name: (dict str -> EnumValueDescriptor) Same as |values|, + values_by_name (dict(str, EnumValueDescriptor)): Same as :attr:`values`, but indexed by the "name" field of each EnumValueDescriptor. - values_by_number: (dict int -> EnumValueDescriptor) Same as |values|, + values_by_number (dict(int, EnumValueDescriptor)): Same as :attr:`values`, but indexed by the "number" field of each EnumValueDescriptor. - containing_type: (Descriptor) Descriptor of the immediate containing + containing_type (Descriptor): Descriptor of the immediate containing type of this enum, or None if this is an enum defined at the top level in a .proto file. Set by Descriptor's constructor if we're passed into one. - file: (FileDescriptor) Reference to file descriptor. - options: (descriptor_pb2.EnumOptions) Enum options message or + file (FileDescriptor): Reference to file descriptor. + options (descriptor_pb2.EnumOptions): Enum options message or None to use default enum options. """ @@ -598,35 +667,41 @@ class EnumDescriptor(_NestedDescriptorBase): _C_DESCRIPTOR_CLASS = _message.EnumDescriptor def __new__(cls, name, full_name, filename, values, - containing_type=None, options=None, file=None, - serialized_start=None, serialized_end=None): + containing_type=None, options=None, + serialized_options=None, file=None, # pylint: disable=redefined-builtin + serialized_start=None, serialized_end=None, create_key=None): _message.Message._CheckCalledFromGeneratedFile() return _message.default_pool.FindEnumTypeByName(full_name) def __init__(self, name, full_name, filename, values, - containing_type=None, options=None, file=None, - serialized_start=None, serialized_end=None): + containing_type=None, options=None, + serialized_options=None, file=None, # pylint: disable=redefined-builtin + serialized_start=None, serialized_end=None, create_key=None): """Arguments are as described in the attribute description above. Note that filename is an obsolete argument, that is not used anymore. Please use file.name to access this as an attribute. """ + if create_key is not _internal_create_key: + _Deprecated('EnumDescriptor') + super(EnumDescriptor, self).__init__( options, 'EnumOptions', name, full_name, file, containing_type, serialized_start=serialized_start, - serialized_end=serialized_end) + serialized_end=serialized_end, serialized_options=serialized_options) self.values = values for value in self.values: value.type = self self.values_by_name = dict((v.name, v) for v in values) - self.values_by_number = dict((v.number, v) for v in values) + # Values are reversed to ensure that the first alias is retained. + self.values_by_number = dict((v.number, v) for v in reversed(values)) def CopyToProto(self, proto): """Copies this to a descriptor_pb2.EnumDescriptorProto. Args: - proto: An empty descriptor_pb2.EnumDescriptorProto. + proto (descriptor_pb2.EnumDescriptorProto): An empty descriptor proto. """ # This function is overridden to give a better doc comment. super(EnumDescriptor, self).CopyToProto(proto) @@ -636,21 +711,24 @@ class EnumValueDescriptor(DescriptorBase): """Descriptor for a single value within an enum. - name: (str) Name of this value. - index: (int) Dense, 0-indexed index giving the order that this + Attributes: + name (str): Name of this value. + index (int): Dense, 0-indexed index giving the order that this value appears textually within its enum in the .proto file. - number: (int) Actual number assigned to this enum value. - type: (EnumDescriptor) EnumDescriptor to which this value - belongs. Set by EnumDescriptor's constructor if we're + number (int): Actual number assigned to this enum value. + type (EnumDescriptor): :class:`EnumDescriptor` to which this value + belongs. Set by :class:`EnumDescriptor`'s constructor if we're passed into one. - options: (descriptor_pb2.EnumValueOptions) Enum value options message or + options (descriptor_pb2.EnumValueOptions): Enum value options message or None to use default enum value options options. """ if _USE_C_DESCRIPTORS: _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor - def __new__(cls, name, index, number, type=None, options=None): + def __new__(cls, name, index, number, + type=None, # pylint: disable=redefined-builtin + options=None, serialized_options=None, create_key=None): _message.Message._CheckCalledFromGeneratedFile() # There is no way we can build a complete EnumValueDescriptor with the # given parameters (the name of the Enum is not known, for example). @@ -658,9 +736,15 @@ def __new__(cls, name, index, number, type=None, options=None): # constructor, which will ignore it, so returning None is good enough. return None - def __init__(self, name, index, number, type=None, options=None): + def __init__(self, name, index, number, + type=None, # pylint: disable=redefined-builtin + options=None, serialized_options=None, create_key=None): """Arguments are as described in the attribute description above.""" - super(EnumValueDescriptor, self).__init__(options, 'EnumValueOptions') + if create_key is not _internal_create_key: + _Deprecated('EnumValueDescriptor') + + super(EnumValueDescriptor, self).__init__( + options, serialized_options, 'EnumValueOptions') self.name = name self.index = index self.number = number @@ -670,14 +754,15 @@ def __init__(self, name, index, number, type=None, options=None): class OneofDescriptor(DescriptorBase): """Descriptor for a oneof field. - name: (str) Name of the oneof field. - full_name: (str) Full name of the oneof field, including package name. - index: (int) 0-based index giving the order of the oneof field inside + Attributes: + name (str): Name of the oneof field. + full_name (str): Full name of the oneof field, including package name. + index (int): 0-based index giving the order of the oneof field inside its containing type. - containing_type: (Descriptor) Descriptor of the protocol message - type that contains this field. Set by the Descriptor constructor + containing_type (Descriptor): :class:`Descriptor` of the protocol message + type that contains this field. Set by the :class:`Descriptor` constructor if we're passed into one. - fields: (list of FieldDescriptor) The list of field descriptors this + fields (list[FieldDescriptor]): The list of field descriptors this oneof can contain. """ @@ -685,14 +770,20 @@ class OneofDescriptor(DescriptorBase): _C_DESCRIPTOR_CLASS = _message.OneofDescriptor def __new__( - cls, name, full_name, index, containing_type, fields, options=None): + cls, name, full_name, index, containing_type, fields, options=None, + serialized_options=None, create_key=None): _message.Message._CheckCalledFromGeneratedFile() return _message.default_pool.FindOneofByName(full_name) def __init__( - self, name, full_name, index, containing_type, fields, options=None): + self, name, full_name, index, containing_type, fields, options=None, + serialized_options=None, create_key=None): """Arguments are as described in the attribute description above.""" - super(OneofDescriptor, self).__init__(options, 'OneofOptions') + if create_key is not _internal_create_key: + _Deprecated('OneofDescriptor') + + super(OneofDescriptor, self).__init__( + options, serialized_options, 'OneofOptions') self.name = name self.full_name = full_name self.index = index @@ -704,34 +795,49 @@ class ServiceDescriptor(_NestedDescriptorBase): """Descriptor for a service. - name: (str) Name of the service. - full_name: (str) Full name of the service, including package name. - index: (int) 0-indexed index giving the order that this services - definition appears withing the .proto file. - methods: (list of MethodDescriptor) List of methods provided by this + Attributes: + name (str): Name of the service. + full_name (str): Full name of the service, including package name. + index (int): 0-indexed index giving the order that this services + definition appears within the .proto file. + methods (list[MethodDescriptor]): List of methods provided by this service. - methods_by_name: (dict str -> MethodDescriptor) Same MethodDescriptor - objects as in |methods_by_name|, but indexed by "name" attribute in each - MethodDescriptor. - options: (descriptor_pb2.ServiceOptions) Service options message or + methods_by_name (dict(str, MethodDescriptor)): Same + :class:`MethodDescriptor` objects as in :attr:`methods_by_name`, but + indexed by "name" attribute in each :class:`MethodDescriptor`. + options (descriptor_pb2.ServiceOptions): Service options message or None to use default service options. - file: (FileDescriptor) Reference to file info. + file (FileDescriptor): Reference to file info. """ if _USE_C_DESCRIPTORS: _C_DESCRIPTOR_CLASS = _message.ServiceDescriptor - def __new__(cls, name, full_name, index, methods, options=None, file=None, # pylint: disable=redefined-builtin - serialized_start=None, serialized_end=None): + def __new__( + cls, + name=None, + full_name=None, + index=None, + methods=None, + options=None, + serialized_options=None, + file=None, # pylint: disable=redefined-builtin + serialized_start=None, + serialized_end=None, + create_key=None): _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access return _message.default_pool.FindServiceByName(full_name) - def __init__(self, name, full_name, index, methods, options=None, file=None, - serialized_start=None, serialized_end=None): + def __init__(self, name, full_name, index, methods, options=None, + serialized_options=None, file=None, # pylint: disable=redefined-builtin + serialized_start=None, serialized_end=None, create_key=None): + if create_key is not _internal_create_key: + _Deprecated('ServiceDescriptor') + super(ServiceDescriptor, self).__init__( options, 'ServiceOptions', name, full_name, file, None, serialized_start=serialized_start, - serialized_end=serialized_end) + serialized_end=serialized_end, serialized_options=serialized_options) self.index = index self.methods = methods self.methods_by_name = dict((m.name, m) for m in methods) @@ -740,14 +846,21 @@ def __init__(self, name, full_name, index, methods, options=None, file=None, method.containing_service = self def FindMethodByName(self, name): - """Searches for the specified method, and returns its descriptor.""" + """Searches for the specified method, and returns its descriptor. + + Args: + name (str): Name of the method. + Returns: + MethodDescriptor or None: the descriptor for the requested method, if + found. + """ return self.methods_by_name.get(name, None) def CopyToProto(self, proto): """Copies this to a descriptor_pb2.ServiceDescriptorProto. Args: - proto: An empty descriptor_pb2.ServiceDescriptorProto. + proto (descriptor_pb2.ServiceDescriptorProto): An empty descriptor proto. """ # This function is overridden to give a better doc comment. super(ServiceDescriptor, self).CopyToProto(proto) @@ -757,33 +870,42 @@ class MethodDescriptor(DescriptorBase): """Descriptor for a method in a service. - name: (str) Name of the method within the service. - full_name: (str) Full name of method. - index: (int) 0-indexed index of the method inside the service. - containing_service: (ServiceDescriptor) The service that contains this - method. - input_type: The descriptor of the message that this method accepts. - output_type: The descriptor of the message that this method returns. - options: (descriptor_pb2.MethodOptions) Method options message or - None to use default method options. + Attributes: + name (str): Name of the method within the service. + full_name (str): Full name of method. + index (int): 0-indexed index of the method inside the service. + containing_service (ServiceDescriptor): The service that contains this + method. + input_type (Descriptor): The descriptor of the message that this method + accepts. + output_type (Descriptor): The descriptor of the message that this method + returns. + options (descriptor_pb2.MethodOptions or None): Method options message, or + None to use default method options. """ if _USE_C_DESCRIPTORS: _C_DESCRIPTOR_CLASS = _message.MethodDescriptor def __new__(cls, name, full_name, index, containing_service, - input_type, output_type, options=None): + input_type, output_type, options=None, serialized_options=None, + create_key=None): _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access return _message.default_pool.FindMethodByName(full_name) def __init__(self, name, full_name, index, containing_service, - input_type, output_type, options=None): + input_type, output_type, options=None, serialized_options=None, + create_key=None): """The arguments are as described in the description of MethodDescriptor attributes above. Note that containing_service may be None, and may be set later if necessary. """ - super(MethodDescriptor, self).__init__(options, 'MethodOptions') + if create_key is not _internal_create_key: + _Deprecated('MethodDescriptor') + + super(MethodDescriptor, self).__init__( + options, serialized_options, 'MethodOptions') self.name = name self.full_name = full_name self.index = index @@ -795,46 +917,65 @@ def __init__(self, name, full_name, index, containing_service, class FileDescriptor(DescriptorBase): """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto. - Note that enum_types_by_name, extensions_by_name, and dependencies - fields are only set by the message_factory module, and not by the - generated proto code. - - name: name of file, relative to root of source tree. - package: name of the package - syntax: string indicating syntax of the file (can be "proto2" or "proto3") - serialized_pb: (str) Byte string of serialized - descriptor_pb2.FileDescriptorProto. - dependencies: List of other FileDescriptors this FileDescriptor depends on. - public_dependencies: A list of FileDescriptors, subset of the dependencies - above, which were declared as "public". - message_types_by_name: Dict of message names of their descriptors. - enum_types_by_name: Dict of enum names and their descriptors. - extensions_by_name: Dict of extension names and their descriptors. - services_by_name: Dict of services names and their descriptors. - pool: the DescriptorPool this descriptor belongs to. When not passed to the - constructor, the global default pool is used. + Note that :attr:`enum_types_by_name`, :attr:`extensions_by_name`, and + :attr:`dependencies` fields are only set by the + :py:mod:`google.protobuf.message_factory` module, and not by the generated + proto code. + + Attributes: + name (str): Name of file, relative to root of source tree. + package (str): Name of the package + syntax (str): string indicating syntax of the file (can be "proto2" or + "proto3") + serialized_pb (bytes): Byte string of serialized + :class:`descriptor_pb2.FileDescriptorProto`. + dependencies (list[FileDescriptor]): List of other :class:`FileDescriptor` + objects this :class:`FileDescriptor` depends on. + public_dependencies (list[FileDescriptor]): A subset of + :attr:`dependencies`, which were declared as "public". + message_types_by_name (dict(str, Descriptor)): Mapping from message names + to their :class:`Desctiptor`. + enum_types_by_name (dict(str, EnumDescriptor)): Mapping from enum names to + their :class:`EnumDescriptor`. + extensions_by_name (dict(str, FieldDescriptor)): Mapping from extension + names declared at file scope to their :class:`FieldDescriptor`. + services_by_name (dict(str, ServiceDescriptor)): Mapping from services' + names to their :class:`ServiceDescriptor`. + pool (DescriptorPool): The pool this descriptor belongs to. When not + passed to the constructor, the global default pool is used. """ if _USE_C_DESCRIPTORS: _C_DESCRIPTOR_CLASS = _message.FileDescriptor - def __new__(cls, name, package, options=None, serialized_pb=None, + def __new__(cls, name, package, options=None, + serialized_options=None, serialized_pb=None, dependencies=None, public_dependencies=None, - syntax=None, pool=None): + syntax=None, pool=None, create_key=None): # FileDescriptor() is called from various places, not only from generated # files, to register dynamic proto files and messages. - if serialized_pb: - # TODO(amauryfa): use the pool passed as argument. This will work only - # for C++-implemented DescriptorPools. + # pylint: disable=g-explicit-bool-comparison + if serialized_pb == b'': + # Cpp generated code must be linked in if serialized_pb is '' + try: + return _message.default_pool.FindFileByName(name) + except KeyError: + raise RuntimeError('Please link in cpp generated lib for %s' % (name)) + elif serialized_pb: return _message.default_pool.AddSerializedFile(serialized_pb) else: return super(FileDescriptor, cls).__new__(cls) - def __init__(self, name, package, options=None, serialized_pb=None, + def __init__(self, name, package, options=None, + serialized_options=None, serialized_pb=None, dependencies=None, public_dependencies=None, - syntax=None, pool=None): + syntax=None, pool=None, create_key=None): """Constructor.""" - super(FileDescriptor, self).__init__(options, 'FileOptions') + if create_key is not _internal_create_key: + _Deprecated('FileDescriptor') + + super(FileDescriptor, self).__init__( + options, serialized_options, 'FileOptions') if pool is None: from google.protobuf import descriptor_pool @@ -852,10 +993,6 @@ def __init__(self, name, package, options=None, serialized_pb=None, self.dependencies = (dependencies or []) self.public_dependencies = (public_dependencies or []) - if (api_implementation.Type() == 'cpp' and - self.serialized_pb is not None): - _message.default_pool.AddSerializedFile(self.serialized_pb) - def CopyToProto(self, proto): """Copies this to a descriptor_pb2.FileDescriptorProto. @@ -952,7 +1089,7 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True, # imported ones. We need to specify a file name so the descriptor pool # accepts our FileDescriptorProto, but it is not important what that file # name is actually set to. - proto_name = str(uuid.uuid4()) + proto_name = binascii.hexlify(os.urandom(16)).decode('ascii') if package: file_descriptor_proto.name = os.path.join(package.replace('.', '/'), @@ -975,9 +1112,11 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True, for enum_proto in desc_proto.enum_type: full_name = '.'.join(full_message_name + [enum_proto.name]) enum_desc = EnumDescriptor( - enum_proto.name, full_name, None, [ - EnumValueDescriptor(enum_val.name, ii, enum_val.number) - for ii, enum_val in enumerate(enum_proto.value)]) + enum_proto.name, full_name, None, [ + EnumValueDescriptor(enum_val.name, ii, enum_val.number, + create_key=_internal_create_key) + for ii, enum_val in enumerate(enum_proto.value)], + create_key=_internal_create_key) enum_types[full_name] = enum_desc # Create Descriptors for nested types @@ -1016,10 +1155,11 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True, FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type), field_proto.label, None, nested_desc, enum_desc, None, False, None, options=_OptionsOrNone(field_proto), has_default_value=False, - json_name=json_name) + json_name=json_name, create_key=_internal_create_key) fields.append(field) desc_name = '.'.join(full_message_name) return Descriptor(desc_proto.name, desc_name, None, None, fields, list(nested_types.values()), list(enum_types.values()), [], - options=_OptionsOrNone(desc_proto)) + options=_OptionsOrNone(desc_proto), + create_key=_internal_create_key) diff --git a/python/google/protobuf/descriptor_database.py b/python/google/protobuf/descriptor_database.py index eb45e1274c7ba..073eddc711571 100644 --- a/python/google/protobuf/descriptor_database.py +++ b/python/google/protobuf/descriptor_database.py @@ -32,6 +32,8 @@ __author__ = 'matthewtoia@google.com (Matt Toia)' +import warnings + class Error(Exception): pass @@ -56,7 +58,7 @@ def Add(self, file_desc_proto): Raises: DescriptorDatabaseConflictingDefinitionError: if an attempt is made to add a proto with the same name but different definition than an - exisiting proto in the database. + existing proto in the database. """ proto_name = file_desc_proto.name if proto_name not in self._file_desc_protos_by_file: @@ -64,21 +66,23 @@ def Add(self, file_desc_proto): elif self._file_desc_protos_by_file[proto_name] != file_desc_proto: raise DescriptorDatabaseConflictingDefinitionError( '%s already added, but with different descriptor.' % proto_name) + else: + return # Add all the top-level descriptors to the index. package = file_desc_proto.package for message in file_desc_proto.message_type: - self._file_desc_protos_by_symbol.update( - (name, file_desc_proto) for name in _ExtractSymbols(message, package)) + for name in _ExtractSymbols(message, package): + self._AddSymbol(name, file_desc_proto) for enum in file_desc_proto.enum_type: - self._file_desc_protos_by_symbol[ - '.'.join((package, enum.name))] = file_desc_proto + self._AddSymbol(('.'.join((package, enum.name))), file_desc_proto) + for enum_value in enum.value: + self._file_desc_protos_by_symbol[ + '.'.join((package, enum_value.name))] = file_desc_proto for extension in file_desc_proto.extension: - self._file_desc_protos_by_symbol[ - '.'.join((package, extension.name))] = file_desc_proto + self._AddSymbol(('.'.join((package, extension.name))), file_desc_proto) for service in file_desc_proto.service: - self._file_desc_protos_by_symbol[ - '.'.join((package, service.name))] = file_desc_proto + self._AddSymbol(('.'.join((package, service.name))), file_desc_proto) def FindFileByName(self, name): """Finds the file descriptor proto by file name. @@ -107,6 +111,7 @@ def FindFileContainingSymbol(self, symbol): 'some.package.name.Message' 'some.package.name.Message.NestedEnum' + 'some.package.name.Message.some_field' The file descriptor proto containing the specified symbol must be added to this database using the Add method or else an error will be raised. @@ -120,8 +125,37 @@ def FindFileContainingSymbol(self, symbol): Raises: KeyError if no file contains the specified symbol. """ - - return self._file_desc_protos_by_symbol[symbol] + try: + return self._file_desc_protos_by_symbol[symbol] + except KeyError: + # Fields, enum values, and nested extensions are not in + # _file_desc_protos_by_symbol. Try to find the top level + # descriptor. Non-existent nested symbol under a valid top level + # descriptor can also be found. The behavior is the same with + # protobuf C++. + top_level, _, _ = symbol.rpartition('.') + try: + return self._file_desc_protos_by_symbol[top_level] + except KeyError: + # Raise the original symbol as a KeyError for better diagnostics. + raise KeyError(symbol) + + def FindFileContainingExtension(self, extendee_name, extension_number): + # TODO(jieluo): implement this API. + return None + + def FindAllExtensionNumbers(self, extendee_name): + # TODO(jieluo): implement this API. + return [] + + def _AddSymbol(self, name, file_desc_proto): + if name in self._file_desc_protos_by_symbol: + warn_msg = ('Conflict register for file "' + file_desc_proto.name + + '": ' + name + + ' is already defined in file "' + + self._file_desc_protos_by_symbol[name].name + '"') + warnings.warn(warn_msg, RuntimeWarning) + self._file_desc_protos_by_symbol[name] = file_desc_proto def _ExtractSymbols(desc_proto, package): diff --git a/python/google/protobuf/descriptor_pool.py b/python/google/protobuf/descriptor_pool.py index 3dbe0fd024a63..de9100b09ca59 100644 --- a/python/google/protobuf/descriptor_pool.py +++ b/python/google/protobuf/descriptor_pool.py @@ -38,7 +38,7 @@ the protocol buffer compiler tool. This should only be used when the type of protocol buffers used in an application or library cannot be predetermined. -Below is a straightforward example on how to use this class: +Below is a straightforward example on how to use this class:: pool = DescriptorPool() file_descriptor_protos = [ ... ] @@ -58,6 +58,7 @@ __author__ = 'matthewtoia@google.com (Matt Toia)' import collections +import warnings from google.protobuf import descriptor from google.protobuf import descriptor_database @@ -67,6 +68,22 @@ _USE_C_DESCRIPTORS = descriptor._USE_C_DESCRIPTORS # pylint: disable=protected-access +def _Deprecated(func): + """Mark functions as deprecated.""" + + def NewFunc(*args, **kwargs): + warnings.warn( + 'Call to deprecated function %s(). Note: Do add unlinked descriptors ' + 'to descriptor_pool is wrong. Use Add() or AddSerializedFile() ' + 'instead.' % func.__name__, + category=DeprecationWarning) + return func(*args, **kwargs) + NewFunc.__name__ = func.__name__ + NewFunc.__doc__ = func.__doc__ + NewFunc.__dict__.update(func.__dict__) + return NewFunc + + def _NormalizeFullyQualifiedName(name): """Remove leading period from fully-qualified type name. @@ -74,10 +91,10 @@ def _NormalizeFullyQualifiedName(name): generated with a leading period. This function removes that prefix. Args: - name: A str, the fully-qualified symbol name. + name (str): The fully-qualified symbol name. Returns: - A str, the normalized fully-qualified symbol name. + str: The normalized fully-qualified symbol name. """ return name.lstrip('.') @@ -127,20 +144,59 @@ def __init__(self, descriptor_db=None): self._service_descriptors = {} self._file_descriptors = {} self._toplevel_extensions = {} - # TODO(jieluo): Remove _file_desc_by_toplevel_extension when - # FieldDescriptor.file is added in code gen. + # TODO(jieluo): Remove _file_desc_by_toplevel_extension after + # maybe year 2020 for compatibility issue (with 3.4.1 only). self._file_desc_by_toplevel_extension = {} + self._top_enum_values = {} # We store extensions in two two-level mappings: The first key is the # descriptor of the message being extended, the second key is the extension # full name or its tag number. self._extensions_by_name = collections.defaultdict(dict) self._extensions_by_number = collections.defaultdict(dict) + def _CheckConflictRegister(self, desc, desc_name, file_name): + """Check if the descriptor name conflicts with another of the same name. + + Args: + desc: Descriptor of a message, enum, service, extension or enum value. + desc_name (str): the full name of desc. + file_name (str): The file name of descriptor. + """ + for register, descriptor_type in [ + (self._descriptors, descriptor.Descriptor), + (self._enum_descriptors, descriptor.EnumDescriptor), + (self._service_descriptors, descriptor.ServiceDescriptor), + (self._toplevel_extensions, descriptor.FieldDescriptor), + (self._top_enum_values, descriptor.EnumValueDescriptor)]: + if desc_name in register: + old_desc = register[desc_name] + if isinstance(old_desc, descriptor.EnumValueDescriptor): + old_file = old_desc.type.file.name + else: + old_file = old_desc.file.name + + if not isinstance(desc, descriptor_type) or ( + old_file != file_name): + error_msg = ('Conflict register for file "' + file_name + + '": ' + desc_name + + ' is already defined in file "' + + old_file + '". Please fix the conflict by adding ' + 'package name on the proto file, or use different ' + 'name for the duplication.') + if isinstance(desc, descriptor.EnumValueDescriptor): + error_msg += ('\nNote: enum values appear as ' + 'siblings of the enum type instead of ' + 'children of it.') + + raise TypeError(error_msg) + + return + def Add(self, file_desc_proto): """Adds the FileDescriptorProto and its types to this pool. Args: - file_desc_proto: The FileDescriptorProto to add. + file_desc_proto (FileDescriptorProto): The file descriptor to add. """ self._internal_db.Add(file_desc_proto) @@ -149,8 +205,8 @@ def AddSerializedFile(self, serialized_file_desc_proto): """Adds the FileDescriptorProto and its types to this pool. Args: - serialized_file_desc_proto: A bytes string, serialization of the - FileDescriptorProto to add. + serialized_file_desc_proto (bytes): A bytes string, serialization of the + :class:`FileDescriptorProto` to add. """ # pylint: disable=g-import-not-at-top @@ -159,7 +215,14 @@ def AddSerializedFile(self, serialized_file_desc_proto): serialized_file_desc_proto) self.Add(file_desc_proto) + # Add Descriptor to descriptor pool is dreprecated. Please use Add() + # or AddSerializedFile() to add a FileDescriptorProto instead. + @_Deprecated def AddDescriptor(self, desc): + self._AddDescriptor(desc) + + # Never call this method. It is for internal usage only. + def _AddDescriptor(self, desc): """Adds a Descriptor to the pool, non-recursively. If the Descriptor contains nested messages or enums, the caller must @@ -172,10 +235,19 @@ def AddDescriptor(self, desc): if not isinstance(desc, descriptor.Descriptor): raise TypeError('Expected instance of descriptor.Descriptor.') + self._CheckConflictRegister(desc, desc.full_name, desc.file.name) + self._descriptors[desc.full_name] = desc self._AddFileDescriptor(desc.file) + # Add EnumDescriptor to descriptor pool is dreprecated. Please use Add() + # or AddSerializedFile() to add a FileDescriptorProto instead. + @_Deprecated def AddEnumDescriptor(self, enum_desc): + self._AddEnumDescriptor(enum_desc) + + # Never call this method. It is for internal usage only. + def _AddEnumDescriptor(self, enum_desc): """Adds an EnumDescriptor to the pool. This method also registers the FileDescriptor associated with the enum. @@ -187,10 +259,36 @@ def AddEnumDescriptor(self, enum_desc): if not isinstance(enum_desc, descriptor.EnumDescriptor): raise TypeError('Expected instance of descriptor.EnumDescriptor.') + file_name = enum_desc.file.name + self._CheckConflictRegister(enum_desc, enum_desc.full_name, file_name) self._enum_descriptors[enum_desc.full_name] = enum_desc + + # Top enum values need to be indexed. + # Count the number of dots to see whether the enum is toplevel or nested + # in a message. We cannot use enum_desc.containing_type at this stage. + if enum_desc.file.package: + top_level = (enum_desc.full_name.count('.') + - enum_desc.file.package.count('.') == 1) + else: + top_level = enum_desc.full_name.count('.') == 0 + if top_level: + file_name = enum_desc.file.name + package = enum_desc.file.package + for enum_value in enum_desc.values: + full_name = _NormalizeFullyQualifiedName( + '.'.join((package, enum_value.name))) + self._CheckConflictRegister(enum_value, full_name, file_name) + self._top_enum_values[full_name] = enum_value self._AddFileDescriptor(enum_desc.file) + # Add ServiceDescriptor to descriptor pool is dreprecated. Please use Add() + # or AddSerializedFile() to add a FileDescriptorProto instead. + @_Deprecated def AddServiceDescriptor(self, service_desc): + self._AddServiceDescriptor(service_desc) + + # Never call this method. It is for internal usage only. + def _AddServiceDescriptor(self, service_desc): """Adds a ServiceDescriptor to the pool. Args: @@ -200,9 +298,18 @@ def AddServiceDescriptor(self, service_desc): if not isinstance(service_desc, descriptor.ServiceDescriptor): raise TypeError('Expected instance of descriptor.ServiceDescriptor.') + self._CheckConflictRegister(service_desc, service_desc.full_name, + service_desc.file.name) self._service_descriptors[service_desc.full_name] = service_desc + # Add ExtensionDescriptor to descriptor pool is dreprecated. Please use Add() + # or AddSerializedFile() to add a FileDescriptorProto instead. + @_Deprecated def AddExtensionDescriptor(self, extension): + self._AddExtensionDescriptor(extension) + + # Never call this method. It is for internal usage only. + def _AddExtensionDescriptor(self, extension): """Adds a FieldDescriptor describing an extension to the pool. Args: @@ -244,7 +351,12 @@ def AddExtensionDescriptor(self, extension): self._extensions_by_name[extension.containing_type][ extension.message_type.full_name] = extension + @_Deprecated def AddFileDescriptor(self, file_desc): + self._InternalAddFileDescriptor(file_desc) + + # Never call this method. It is for internal usage only. + def _InternalAddFileDescriptor(self, file_desc): """Adds a FileDescriptor to the pool, non-recursively. If the FileDescriptor contains messages or enums, the caller must explicitly @@ -256,7 +368,8 @@ def AddFileDescriptor(self, file_desc): self._AddFileDescriptor(file_desc) # TODO(jieluo): This is a temporary solution for FieldDescriptor.file. - # Remove it when FieldDescriptor.file is added in code gen. + # FieldDescriptor.file is added in code gen. Remove this solution after + # maybe 2020 for compatibility reason (with 3.4.1 only). for extension in file_desc.extensions_by_name.values(): self._file_desc_by_toplevel_extension[ extension.full_name] = file_desc @@ -279,10 +392,10 @@ def FindFileByName(self, file_name): """Gets a FileDescriptor by file name. Args: - file_name: The path to the file to get a descriptor for. + file_name (str): The path to the file to get a descriptor for. Returns: - A FileDescriptor for the named file. + FileDescriptor: The descriptor for the named file. Raises: KeyError: if the file cannot be found in the pool. @@ -308,16 +421,42 @@ def FindFileContainingSymbol(self, symbol): """Gets the FileDescriptor for the file containing the specified symbol. Args: - symbol: The name of the symbol to search for. + symbol (str): The name of the symbol to search for. Returns: - A FileDescriptor that contains the specified symbol. + FileDescriptor: Descriptor for the file that contains the specified + symbol. Raises: KeyError: if the file cannot be found in the pool. """ symbol = _NormalizeFullyQualifiedName(symbol) + try: + return self._InternalFindFileContainingSymbol(symbol) + except KeyError: + pass + + try: + # Try fallback database. Build and find again if possible. + self._FindFileContainingSymbolInDb(symbol) + return self._InternalFindFileContainingSymbol(symbol) + except KeyError: + raise KeyError('Cannot find a file containing %s' % symbol) + + def _InternalFindFileContainingSymbol(self, symbol): + """Gets the already built FileDescriptor containing the specified symbol. + + Args: + symbol (str): The name of the symbol to search for. + + Returns: + FileDescriptor: Descriptor for the file that contains the specified + symbol. + + Raises: + KeyError: if the file cannot be found in the pool. + """ try: return self._descriptors[symbol].file except KeyError: @@ -334,7 +473,7 @@ def FindFileContainingSymbol(self, symbol): pass try: - return self._FindFileContainingSymbolInDb(symbol) + return self._top_enum_values[symbol].type.file except KeyError: pass @@ -343,23 +482,25 @@ def FindFileContainingSymbol(self, symbol): except KeyError: pass - # Try nested extensions inside a message. - message_name, _, extension_name = symbol.rpartition('.') + # Try fields, enum values and nested extensions inside a message. + top_name, _, sub_name = symbol.rpartition('.') try: - message = self.FindMessageTypeByName(message_name) - assert message.extensions_by_name[extension_name] + message = self.FindMessageTypeByName(top_name) + assert (sub_name in message.extensions_by_name or + sub_name in message.fields_by_name or + sub_name in message.enum_values_by_name) return message.file - except KeyError: + except (KeyError, AssertionError): raise KeyError('Cannot find a file containing %s' % symbol) def FindMessageTypeByName(self, full_name): """Loads the named descriptor from the pool. Args: - full_name: The full name of the descriptor to load. + full_name (str): The full name of the descriptor to load. Returns: - The descriptor for the named type. + Descriptor: The descriptor for the named type. Raises: KeyError: if the message cannot be found in the pool. @@ -374,10 +515,10 @@ def FindEnumTypeByName(self, full_name): """Loads the named enum descriptor from the pool. Args: - full_name: The full name of the enum descriptor to load. + full_name (str): The full name of the enum descriptor to load. Returns: - The enum descriptor for the named type. + EnumDescriptor: The enum descriptor for the named type. Raises: KeyError: if the enum cannot be found in the pool. @@ -392,10 +533,10 @@ def FindFieldByName(self, full_name): """Loads the named field descriptor from the pool. Args: - full_name: The full name of the field descriptor to load. + full_name (str): The full name of the field descriptor to load. Returns: - The field descriptor for the named field. + FieldDescriptor: The field descriptor for the named field. Raises: KeyError: if the field cannot be found in the pool. @@ -405,14 +546,31 @@ def FindFieldByName(self, full_name): message_descriptor = self.FindMessageTypeByName(message_name) return message_descriptor.fields_by_name[field_name] + def FindOneofByName(self, full_name): + """Loads the named oneof descriptor from the pool. + + Args: + full_name (str): The full name of the oneof descriptor to load. + + Returns: + OneofDescriptor: The oneof descriptor for the named oneof. + + Raises: + KeyError: if the oneof cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + message_name, _, oneof_name = full_name.rpartition('.') + message_descriptor = self.FindMessageTypeByName(message_name) + return message_descriptor.oneofs_by_name[oneof_name] + def FindExtensionByName(self, full_name): """Loads the named extension descriptor from the pool. Args: - full_name: The full name of the extension descriptor to load. + full_name (str): The full name of the extension descriptor to load. Returns: - A FieldDescriptor, describing the named extension. + FieldDescriptor: The field descriptor for the named extension. Raises: KeyError: if the extension cannot be found in the pool. @@ -438,44 +596,86 @@ def FindExtensionByName(self, full_name): def FindExtensionByNumber(self, message_descriptor, number): """Gets the extension of the specified message with the specified number. - Extensions have to be registered to this pool by calling - AddExtensionDescriptor. + Extensions have to be registered to this pool by calling :func:`Add` or + :func:`AddExtensionDescriptor`. Args: - message_descriptor: descriptor of the extended message. - number: integer, number of the extension field. + message_descriptor (Descriptor): descriptor of the extended message. + number (int): Number of the extension field. Returns: - A FieldDescriptor describing the extension. + FieldDescriptor: The descriptor for the extension. Raises: KeyError: when no extension with the given number is known for the specified message. """ - return self._extensions_by_number[message_descriptor][number] + try: + return self._extensions_by_number[message_descriptor][number] + except KeyError: + self._TryLoadExtensionFromDB(message_descriptor, number) + return self._extensions_by_number[message_descriptor][number] def FindAllExtensions(self, message_descriptor): - """Gets all the known extension of a given message. + """Gets all the known extensions of a given message. - Extensions have to be registered to this pool by calling - AddExtensionDescriptor. + Extensions have to be registered to this pool by build related + :func:`Add` or :func:`AddExtensionDescriptor`. Args: - message_descriptor: descriptor of the extended message. + message_descriptor (Descriptor): Descriptor of the extended message. Returns: - A list of FieldDescriptor describing the extensions. + list[FieldDescriptor]: Field descriptors describing the extensions. """ + # Fallback to descriptor db if FindAllExtensionNumbers is provided. + if self._descriptor_db and hasattr( + self._descriptor_db, 'FindAllExtensionNumbers'): + full_name = message_descriptor.full_name + all_numbers = self._descriptor_db.FindAllExtensionNumbers(full_name) + for number in all_numbers: + if number in self._extensions_by_number[message_descriptor]: + continue + self._TryLoadExtensionFromDB(message_descriptor, number) + return list(self._extensions_by_number[message_descriptor].values()) + def _TryLoadExtensionFromDB(self, message_descriptor, number): + """Try to Load extensions from descriptor db. + + Args: + message_descriptor: descriptor of the extended message. + number: the extension number that needs to be loaded. + """ + if not self._descriptor_db: + return + # Only supported when FindFileContainingExtension is provided. + if not hasattr( + self._descriptor_db, 'FindFileContainingExtension'): + return + + full_name = message_descriptor.full_name + file_proto = self._descriptor_db.FindFileContainingExtension( + full_name, number) + + if file_proto is None: + return + + try: + self._ConvertFileProtoToFileDescriptor(file_proto) + except: + warn_msg = ('Unable to load proto file %s for extension number %d.' % + (file_proto.name, number)) + warnings.warn(warn_msg, RuntimeWarning) + def FindServiceByName(self, full_name): """Loads the named service descriptor from the pool. Args: - full_name: The full name of the service descriptor to load. + full_name (str): The full name of the service descriptor to load. Returns: - The service descriptor for the named service. + ServiceDescriptor: The service descriptor for the named service. Raises: KeyError: if the service cannot be found in the pool. @@ -485,14 +685,31 @@ def FindServiceByName(self, full_name): self._FindFileContainingSymbolInDb(full_name) return self._service_descriptors[full_name] + def FindMethodByName(self, full_name): + """Loads the named service method descriptor from the pool. + + Args: + full_name (str): The full name of the method descriptor to load. + + Returns: + MethodDescriptor: The method descriptor for the service method. + + Raises: + KeyError: if the method cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + service_name, _, method_name = full_name.rpartition('.') + service_descriptor = self.FindServiceByName(service_name) + return service_descriptor.methods_by_name[method_name] + def _FindFileContainingSymbolInDb(self, symbol): """Finds the file in descriptor DB containing the specified symbol. Args: - symbol: The name of the symbol to search for. + symbol (str): The name of the symbol to search for. Returns: - A FileDescriptor that contains the specified symbol. + FileDescriptor: The file that contains the specified symbol. Raises: KeyError: if the file cannot be found in the descriptor database. @@ -520,7 +737,6 @@ def _ConvertFileProtoToFileDescriptor(self, file_proto): Returns: A FileDescriptor matching the passed in proto. """ - if file_proto.name not in self._file_descriptors: built_deps = list(self._GetDeps(file_proto.dependency)) direct_deps = [self.FindFileByName(n) for n in file_proto.dependency] @@ -534,7 +750,9 @@ def _ConvertFileProtoToFileDescriptor(self, file_proto): options=_OptionsOrNone(file_proto), serialized_pb=file_proto.SerializeToString(), dependencies=direct_deps, - public_dependencies=public_deps) + public_dependencies=public_deps, + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) scope = {} # This loop extracts all the message and enum types from all the @@ -557,7 +775,7 @@ def _ConvertFileProtoToFileDescriptor(self, file_proto): for enum_type in file_proto.enum_type: file_descriptor.enum_types_by_name[enum_type.name] = ( self._ConvertEnumDescriptor(enum_type, file_proto.package, - file_descriptor, None, scope)) + file_descriptor, None, scope, True)) for index, extension_proto in enumerate(file_proto.extension): extension_desc = self._MakeFieldDescriptor( @@ -569,6 +787,8 @@ def _ConvertFileProtoToFileDescriptor(self, file_proto): file_descriptor.package, scope) file_descriptor.extensions_by_name[extension_desc.name] = ( extension_desc) + self._file_desc_by_toplevel_extension[extension_desc.full_name] = ( + file_descriptor) for desc_proto in file_proto.message_type: self._SetAllFieldTypes(file_proto.package, desc_proto, scope) @@ -591,7 +811,15 @@ def _ConvertFileProtoToFileDescriptor(self, file_proto): self.Add(file_proto) self._file_descriptors[file_proto.name] = file_descriptor - return self._file_descriptors[file_proto.name] + # Add extensions to the pool + file_desc = self._file_descriptors[file_proto.name] + for extension in file_desc.extensions_by_name.values(): + self._AddExtensionDescriptor(extension) + for message_type in file_desc.message_types_by_name.values(): + for extension in message_type.extensions: + self._AddExtensionDescriptor(extension) + + return file_desc def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None, scope=None, syntax=None): @@ -626,7 +854,8 @@ def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None, nested, desc_name, file_desc, scope, syntax) for nested in desc_proto.nested_type] enums = [ - self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope) + self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, + scope, False) for enum in desc_proto.enum_type] fields = [self._MakeFieldDescriptor(field, desc_name, index, file_desc) for index, field in enumerate(desc_proto.field)] @@ -635,8 +864,11 @@ def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None, is_extension=True) for index, extension in enumerate(desc_proto.extension)] oneofs = [ + # pylint: disable=g-complex-comprehension descriptor.OneofDescriptor(desc.name, '.'.join((desc_name, desc.name)), - index, None, [], desc.options) + index, None, [], desc.options, + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) for index, desc in enumerate(desc_proto.oneof_decl)] extension_ranges = [(r.start, r.end) for r in desc_proto.extension_range] if extension_ranges: @@ -659,7 +891,9 @@ def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None, file=file_desc, serialized_start=None, serialized_end=None, - syntax=syntax) + syntax=syntax, + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) for nested in desc.nested_types: nested.containing_type = desc for enum in desc.enum_types: @@ -671,11 +905,12 @@ def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None, fields[field_index].containing_oneof = oneofs[oneof_index] scope[_PrefixWithDot(desc_name)] = desc + self._CheckConflictRegister(desc, desc.full_name, desc.file.name) self._descriptors[desc_name] = desc return desc def _ConvertEnumDescriptor(self, enum_proto, package=None, file_desc=None, - containing_type=None, scope=None): + containing_type=None, scope=None, top_level=False): """Make a protobuf EnumDescriptor given an EnumDescriptorProto protobuf. Args: @@ -684,6 +919,8 @@ def _ConvertEnumDescriptor(self, enum_proto, package=None, file_desc=None, file_desc: The file containing the enum descriptor. containing_type: The type containing this enum. scope: Scope containing available types. + top_level: If True, the enum is a top level symbol. If False, the enum + is defined inside a message. Returns: The added descriptor @@ -707,9 +944,21 @@ def _ConvertEnumDescriptor(self, enum_proto, package=None, file_desc=None, file=file_desc, values=values, containing_type=containing_type, - options=_OptionsOrNone(enum_proto)) + options=_OptionsOrNone(enum_proto), + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) scope['.%s' % enum_name] = desc + self._CheckConflictRegister(desc, desc.full_name, desc.file.name) self._enum_descriptors[enum_name] = desc + + # Add top level enum values. + if top_level: + for value in values: + full_name = _NormalizeFullyQualifiedName( + '.'.join((package, value.name))) + self._CheckConflictRegister(value, full_name, file_name) + self._top_enum_values[full_name] = value + return desc def _MakeFieldDescriptor(self, field_proto, message_name, index, @@ -754,7 +1003,9 @@ def _MakeFieldDescriptor(self, field_proto, message_name, index, is_extension=is_extension, extension_scope=None, options=_OptionsOrNone(field_proto), - file=file_desc) + file=file_desc, + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) def _SetAllFieldTypes(self, package, desc_proto, scope): """Sets all the descriptor's fields's types. @@ -793,7 +1044,7 @@ def _SetFieldType(self, field_proto, field_desc, package, scope): Args: field_proto: Data about the field in proto format. - field_desc: The descriptor to modiy. + field_desc: The descriptor to modify. package: The package the field's container is in. scope: Enclosing scope of available types. """ @@ -836,6 +1087,8 @@ def _SetFieldType(self, field_proto, field_desc, package, scope): elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES: field_desc.default_value = text_encoding.CUnescape( field_proto.default_value) + elif field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE: + field_desc.default_value = None else: # All other types are of the "int" type. field_desc.default_value = int(field_proto.default_value) @@ -852,6 +1105,8 @@ def _SetFieldType(self, field_proto, field_desc, package, scope): field_desc.default_value = field_desc.enum_type.values[0].number elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES: field_desc.default_value = b'' + elif field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE: + field_desc.default_value = None else: # All other types are of the "int" type. field_desc.default_value = 0 @@ -874,7 +1129,9 @@ def _MakeEnumValueDescriptor(self, value_proto, index): index=index, number=value_proto.number, options=_OptionsOrNone(value_proto), - type=None) + type=None, + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) def _MakeServiceDescriptor(self, service_proto, service_index, scope, package, file_desc): @@ -899,12 +1156,16 @@ def _MakeServiceDescriptor(self, service_proto, service_index, scope, methods = [self._MakeMethodDescriptor(method_proto, service_name, package, scope, index) for index, method_proto in enumerate(service_proto.method)] - desc = descriptor.ServiceDescriptor(name=service_proto.name, - full_name=service_name, - index=service_index, - methods=methods, - options=_OptionsOrNone(service_proto), - file=file_desc) + desc = descriptor.ServiceDescriptor( + name=service_proto.name, + full_name=service_name, + index=service_index, + methods=methods, + options=_OptionsOrNone(service_proto), + file=file_desc, + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) + self._CheckConflictRegister(desc, desc.full_name, desc.file.name) self._service_descriptors[service_name] = desc return desc @@ -927,13 +1188,16 @@ def _MakeMethodDescriptor(self, method_proto, service_name, package, scope, package, method_proto.input_type, scope) output_type = self._GetTypeFromScope( package, method_proto.output_type, scope) - return descriptor.MethodDescriptor(name=method_proto.name, - full_name=full_name, - index=index, - containing_service=None, - input_type=input_type, - output_type=output_type, - options=_OptionsOrNone(method_proto)) + return descriptor.MethodDescriptor( + name=method_proto.name, + full_name=full_name, + index=index, + containing_service=None, + input_type=input_type, + output_type=output_type, + options=_OptionsOrNone(method_proto), + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) def _ExtractSymbols(self, descriptors): """Pulls out all the symbols from descriptor protos. diff --git a/python/google/protobuf/internal/__init__.py b/python/google/protobuf/internal/__init__.py old mode 100755 new mode 100644 index e69de29bb2d1d..7d2e571a143a5 --- a/python/google/protobuf/internal/__init__.py +++ b/python/google/protobuf/internal/__init__.py @@ -0,0 +1,30 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/python/google/protobuf/internal/_parameterized.py b/python/google/protobuf/internal/_parameterized.py index 23a78f037e20d..4cba1d479d740 100755 --- a/python/google/protobuf/internal/_parameterized.py +++ b/python/google/protobuf/internal/_parameterized.py @@ -37,8 +37,8 @@ A simple example: - class AdditionExample(parameterized.ParameterizedTestCase): - @parameterized.Parameters( + class AdditionExample(parameterized.TestCase): + @parameterized.parameters( (1, 2, 3), (4, 5, 9), (1, 1, 3)) @@ -51,11 +51,11 @@ def testAddition(self, op1, op2, result): example above, there are three separate testcases, one of which will fail due to an assertion error (1 + 1 != 3). -Parameters for invididual test cases can be tuples (with positional parameters) +Parameters for individual test cases can be tuples (with positional parameters) or dictionaries (with named parameters): - class AdditionExample(parameterized.ParameterizedTestCase): - @parameterized.Parameters( + class AdditionExample(parameterized.TestCase): + @parameterized.parameters( {'op1': 1, 'op2': 2, 'result': 3}, {'op1': 4, 'op2': 5, 'result': 9}, ) @@ -77,13 +77,13 @@ def testAddition(self, op1, op2, result): '<__main__.Foo object at 0x23d8610>' are turned into '<__main__.Foo>'. For even more descriptive names, -especially in test logs, you can use the NamedParameters decorator. In +especially in test logs, you can use the named_parameters decorator. In this case, only tuples are supported, and the first parameters has to be a string (or an object that returns an apt name when converted via str()): - class NamedExample(parameterized.ParameterizedTestCase): - @parameterized.NamedParameters( + class NamedExample(parameterized.TestCase): + @parameterized.named_parameters( ('Normal', 'aa', 'aaa', True), ('EmptyPrefix', '', 'abc', True), ('BothEmpty', '', '', True)) @@ -103,13 +103,13 @@ def testStartsWith(self, prefix, string, result): Parameterized Classes ===================== If invocation arguments are shared across test methods in a single -ParameterizedTestCase class, instead of decorating all test methods +TestCase class, instead of decorating all test methods individually, the class itself can be decorated: - @parameterized.Parameters( + @parameterized.parameters( (1, 2, 3) (4, 5, 9)) - class ArithmeticTest(parameterized.ParameterizedTestCase): + class ArithmeticTest(parameterized.TestCase): def testAdd(self, arg1, arg2, result): self.assertEqual(arg1 + arg2, result) @@ -122,8 +122,8 @@ def testSubtract(self, arg2, arg2, result): created from other sources, a single non-tuple iterable can be passed into the decorator. This iterable will be used to obtain the test cases: - class AdditionExample(parameterized.ParameterizedTestCase): - @parameterized.Parameters( + class AdditionExample(parameterized.TestCase): + @parameterized.parameters( c.op1, c.op2, c.result for c in testcases ) def testAddition(self, op1, op2, result): @@ -135,8 +135,8 @@ def testAddition(self, op1, op2, result): If a test method takes only one argument, the single argument does not need to be wrapped into a tuple: - class NegativeNumberExample(parameterized.ParameterizedTestCase): - @parameterized.Parameters( + class NegativeNumberExample(parameterized.TestCase): + @parameterized.parameters( -1, -3, -4, -5 ) def testIsNegative(self, arg): @@ -145,7 +145,6 @@ def testIsNegative(self, arg): __author__ = 'tmarek@google.com (Torsten Marek)' -import collections import functools import re import types @@ -157,6 +156,13 @@ def testIsNegative(self, arg): import six +try: + # Since python 3 + import collections.abc as collections_abc +except ImportError: + # Won't work after python 3.8 + import collections as collections_abc + ADDR_RE = re.compile(r'\<([a-zA-Z0-9_\-\.]+) object at 0x[a-fA-F0-9]+\>') _SEPARATOR = uuid.uuid1().hex _FIRST_ARG = object() @@ -174,12 +180,12 @@ def _StrClass(cls): def _NonStringIterable(obj): - return (isinstance(obj, collections.Iterable) and not + return (isinstance(obj, collections_abc.Iterable) and not isinstance(obj, six.string_types)) def _FormatParameterList(testcase_params): - if isinstance(testcase_params, collections.Mapping): + if isinstance(testcase_params, collections_abc.Mapping): return ', '.join('%s=%s' % (argname, _CleanRepr(value)) for argname, value in testcase_params.items()) elif _NonStringIterable(testcase_params): @@ -212,7 +218,7 @@ def __init__(self, test_method, testcases, naming_type): def __call__(self, *args, **kwargs): raise RuntimeError('You appear to be running a parameterized test case ' 'without having inherited from parameterized.' - 'ParameterizedTestCase. This is bad because none of ' + 'TestCase. This is bad because none of ' 'your test cases are actually being run.') def __iter__(self): @@ -222,7 +228,7 @@ def __iter__(self): def MakeBoundParamTest(testcase_params): @functools.wraps(test_method) def BoundParamTest(self): - if isinstance(testcase_params, collections.Mapping): + if isinstance(testcase_params, collections_abc.Mapping): test_method(self, **testcase_params) elif _NonStringIterable(testcase_params): test_method(self, *testcase_params) @@ -263,7 +269,7 @@ def _ModifyClass(class_object, testcases, naming_type): 'Cannot add parameters to %s,' ' which already has parameterized methods.' % (class_object,)) class_object._id_suffix = id_suffix = {} - # We change the size of __dict__ while we iterate over it, + # We change the size of __dict__ while we iterate over it, # which Python 3.x will complain about, so use copy(). for name, obj in class_object.__dict__.copy().items(): if (name.startswith(unittest.TestLoader.testMethodPrefix) @@ -291,7 +297,7 @@ def _Apply(obj): if isinstance(obj, type): _ModifyClass( obj, - list(testcases) if not isinstance(testcases, collections.Sequence) + list(testcases) if not isinstance(testcases, collections_abc.Sequence) else testcases, naming_type) return obj @@ -306,7 +312,7 @@ def _Apply(obj): return _Apply -def Parameters(*testcases): +def parameters(*testcases): # pylint: disable=invalid-name """A decorator for creating parameterized tests. See the module docstring for a usage example. @@ -321,7 +327,7 @@ def Parameters(*testcases): return _ParameterDecorator(_ARGUMENT_REPR, testcases) -def NamedParameters(*testcases): +def named_parameters(*testcases): # pylint: disable=invalid-name """A decorator for creating parameterized tests. See the module docstring for a usage example. The first element of @@ -348,7 +354,7 @@ class TestGeneratorMetaclass(type): up as tests by the unittest framework. In general, it is supposed to be used in conjunction with the - Parameters decorator. + parameters decorator. """ def __new__(mcs, class_name, bases, dct): @@ -385,8 +391,8 @@ def _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator): id_suffix[new_name] = getattr(func, '__x_extra_id__', '') -class ParameterizedTestCase(unittest.TestCase): - """Base class for test cases using the Parameters decorator.""" +class TestCase(unittest.TestCase): + """Base class for test cases using the parameters decorator.""" __metaclass__ = TestGeneratorMetaclass def _OriginalName(self): @@ -409,10 +415,10 @@ def id(self): # pylint: disable=invalid-name self._id_suffix.get(self._testMethodName, '')) -def CoopParameterizedTestCase(other_base_class): +def CoopTestCase(other_base_class): """Returns a new base class with a cooperative metaclass base. - This enables the ParameterizedTestCase to be used in combination + This enables the TestCase to be used in combination with other base classes that have custom metaclasses, such as mox.MoxTestBase. @@ -425,7 +431,7 @@ def CoopParameterizedTestCase(other_base_class): from google3.testing.pybase import parameterized - class ExampleTest(parameterized.CoopParameterizedTestCase(mox.MoxTestBase)): + class ExampleTest(parameterized.CoopTestCase(mox.MoxTestBase)): ... Args: @@ -439,5 +445,5 @@ class ExampleTest(parameterized.CoopParameterizedTestCase(mox.MoxTestBase)): (other_base_class.__metaclass__, TestGeneratorMetaclass), {}) return metaclass( - 'CoopParameterizedTestCase', - (other_base_class, ParameterizedTestCase), {}) + 'CoopTestCase', + (other_base_class, TestCase), {}) diff --git a/python/google/protobuf/internal/any_test.proto b/python/google/protobuf/internal/any_test.proto index 76a7ebd68ded3..1a563fd948dfe 100644 --- a/python/google/protobuf/internal/any_test.proto +++ b/python/google/protobuf/internal/any_test.proto @@ -39,6 +39,7 @@ import "google/protobuf/any.proto"; message TestAny { optional google.protobuf.Any value = 1; optional int32 int_value = 2; + map map_value = 3; extensions 10 to max; } diff --git a/python/google/protobuf/internal/api_implementation.cc b/python/google/protobuf/internal/api_implementation.cc index 6db12e8dc6765..2a7f41d2d612a 100644 --- a/python/google/protobuf/internal/api_implementation.cc +++ b/python/google/protobuf/internal/api_implementation.cc @@ -69,25 +69,24 @@ static const char* kImplVersionName = "api_version"; static const char* kModuleName = "_api_implementation"; static const char kModuleDocstring[] = -"_api_implementation is a module that exposes compile-time constants that\n" -"determine the default API implementation to use for Python proto2.\n" -"\n" -"It complements api_implementation.py by setting defaults using compile-time\n" -"constants defined in C, such that one can set defaults at compilation\n" -"(e.g. with blaze flag --copt=-DPYTHON_PROTO2_CPP_IMPL_V2)."; + "_api_implementation is a module that exposes compile-time constants that\n" + "determine the default API implementation to use for Python proto2.\n" + "\n" + "It complements api_implementation.py by setting defaults using " + "compile-time\n" + "constants defined in C, such that one can set defaults at compilation\n" + "(e.g. with blaze flag --copt=-DPYTHON_PROTO2_CPP_IMPL_V2)."; #if PY_MAJOR_VERSION >= 3 -static struct PyModuleDef _module = { - PyModuleDef_HEAD_INIT, - kModuleName, - kModuleDocstring, - -1, - NULL, - NULL, - NULL, - NULL, - NULL -}; +static struct PyModuleDef _module = {PyModuleDef_HEAD_INIT, + kModuleName, + kModuleDocstring, + -1, + NULL, + NULL, + NULL, + NULL, + NULL}; #define INITFUNC PyInit__api_implementation #define INITFUNC_ERRORVAL NULL #else @@ -96,32 +95,31 @@ static struct PyModuleDef _module = { #endif extern "C" { - PyMODINIT_FUNC INITFUNC() { +PyMODINIT_FUNC INITFUNC() { #if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create(&_module); + PyObject* module = PyModule_Create(&_module); #else - PyObject *module = Py_InitModule3( - const_cast(kModuleName), - NULL, - const_cast(kModuleDocstring)); + PyObject* module = Py_InitModule3(const_cast(kModuleName), NULL, + const_cast(kModuleDocstring)); #endif - if (module == NULL) { - return INITFUNC_ERRORVAL; - } + if (module == NULL) { + return INITFUNC_ERRORVAL; + } - // Adds the module variable "api_version". - if (PyModule_AddIntConstant( - module, - const_cast(kImplVersionName), - kImplVersion)) + // Adds the module variable "api_version". + if (PyModule_AddIntConstant(module, const_cast(kImplVersionName), + kImplVersion)) #if PY_MAJOR_VERSION < 3 - return; + return; #else - { Py_DECREF(module); return NULL; } + { + Py_DECREF(module); + return NULL; + } - return module; + return module; #endif - } +} } } // namespace python diff --git a/python/google/protobuf/internal/api_implementation.py b/python/google/protobuf/internal/api_implementation.py old mode 100755 new mode 100644 index 422af5902d107..7592be4eed3d3 --- a/python/google/protobuf/internal/api_implementation.py +++ b/python/google/protobuf/internal/api_implementation.py @@ -60,11 +60,24 @@ raise ImportError('_use_fast_cpp_protos import succeeded but was None') del _use_fast_cpp_protos _api_version = 2 + # Can not import both use_fast_cpp_protos and use_pure_python. + from google.protobuf import use_pure_python + raise RuntimeError( + 'Conflict depend on both use_fast_cpp_protos and use_pure_python') except ImportError: - if _proto_extension_modules_exist_in_build: - if sys.version_info[0] >= 3: # Python 3 defaults to C++ impl v2. - _api_version = 2 - # TODO(b/17427486): Make Python 2 default to C++ impl v2. + try: + # pylint: disable=g-import-not-at-top + from google.protobuf import use_pure_python + del use_pure_python # Avoids a pylint error and namespace pollution. + _api_version = 0 + except ImportError: + # TODO(b/74017912): It's unsafe to enable :use_fast_cpp_protos by default; + # it can cause data loss if you have any Python-only extensions to any + # message passed back and forth with C++ code. + # + # TODO(b/17427486): Once that bug is fixed, we want to make both Python 2 + # and Python 3 default to `_api_version = 2` (C++ implementation V2). + pass _default_implementation_type = ( 'python' if _api_version <= 0 else 'cpp') @@ -129,6 +142,12 @@ def Type(): return _implementation_type +def _SetType(implementation_type): + """Never use! Only for protobuf benchmark.""" + global _implementation_type + _implementation_type = implementation_type + + # See comment on 'Type' above. def Version(): return _implementation_version diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py old mode 100755 new mode 100644 index 68be9e54a8d49..92793490bbc3e --- a/python/google/protobuf/internal/containers.py +++ b/python/google/protobuf/internal/containers.py @@ -33,20 +33,25 @@ This file defines container classes which represent categories of protocol buffer field types which need extra maintenance. Currently these categories are: - - Repeated scalar fields - These are all repeated fields which aren't + +- Repeated scalar fields - These are all repeated fields which aren't composite (e.g. they are of simple types like int32, string, etc). - - Repeated composite fields - Repeated fields which are composite. This +- Repeated composite fields - Repeated fields which are composite. This includes groups and nested messages. """ __author__ = 'petar@google.com (Petar Petrov)' -import collections import sys +try: + # This fallback applies for all versions of Python before 3.3 + import collections.abc as collections_abc +except ImportError: + import collections as collections_abc if sys.version_info[0] < 3: - # We would use collections.MutableMapping all the time, but in Python 2 it - # doesn't define __slots__. This causes two significant problems: + # We would use collections_abc.MutableMapping all the time, but in Python 2 + # it doesn't define __slots__. This causes two significant problems: # # 1. we can't disallow arbitrary attribute assignment, even if our derived # classes *do* define __slots__. @@ -59,7 +64,7 @@ # verbatim, except that: # 1. We declare __slots__. # 2. We don't declare this as a virtual base class. The classes defined - # in collections are the interesting base classes, not us. + # in collections_abc are the interesting base classes, not us. # # Note: deriving from object is critical. It is the only thing that makes # this a true type, allowing us to derive from it in C++ cleanly and making @@ -106,7 +111,7 @@ def values(self): __hash__ = None def __eq__(self, other): - if not isinstance(other, collections.Mapping): + if not isinstance(other, collections_abc.Mapping): return NotImplemented return dict(self.items()) == dict(other.items()) @@ -173,13 +178,13 @@ def setdefault(self, key, default=None): self[key] = default return default - collections.Mapping.register(Mapping) - collections.MutableMapping.register(MutableMapping) + collections_abc.Mapping.register(Mapping) + collections_abc.MutableMapping.register(MutableMapping) else: # In Python 3 we can just use MutableMapping directly, because it defines # __slots__. - MutableMapping = collections.MutableMapping + MutableMapping = collections_abc.MutableMapping class BaseContainer(object): @@ -226,22 +231,27 @@ def sort(self, *args, **kwargs): kwargs['cmp'] = kwargs.pop('sort_function') self._values.sort(*args, **kwargs) + def reverse(self): + self._values.reverse() -class RepeatedScalarFieldContainer(BaseContainer): +collections_abc.MutableSequence.register(BaseContainer) + + +class RepeatedScalarFieldContainer(BaseContainer): """Simple, type-checked, list-like container for holding repeated scalars.""" # Disallows assignment to other attributes. __slots__ = ['_type_checker'] def __init__(self, message_listener, type_checker): - """ - Args: - message_listener: A MessageListener implementation. - The RepeatedScalarFieldContainer will call this object's - Modified() method when it is modified. + """Args: + + message_listener: A MessageListener implementation. The + RepeatedScalarFieldContainer will call this object's Modified() method + when it is modified. type_checker: A type_checkers.ValueChecker instance to run on elements - inserted into this container. + inserted into this container. """ super(RepeatedScalarFieldContainer, self).__init__(message_listener) self._type_checker = type_checker @@ -337,8 +347,6 @@ def __eq__(self, other): # We are presumably comparing against some other sequence type. return other == self._values -collections.MutableSequence.register(BaseContainer) - class RepeatedCompositeFieldContainer(BaseContainer): @@ -376,8 +384,27 @@ def add(self, **kwargs): self._message_listener.Modified() return new_element + def append(self, value): + """Appends one element by copying the message.""" + new_element = self._message_descriptor._concrete_class() + new_element._SetListener(self._message_listener) + new_element.CopyFrom(value) + self._values.append(new_element) + if not self._message_listener.dirty: + self._message_listener.Modified() + + def insert(self, key, value): + """Inserts the item at the specified position by copying.""" + new_element = self._message_descriptor._concrete_class() + new_element._SetListener(self._message_listener) + new_element.CopyFrom(value) + self._values.insert(key, new_element) + if not self._message_listener.dirty: + self._message_listener.Modified() + def extend(self, elem_seq): """Extends by appending the given sequence of elements of the same type + as this one, copying each individual message. """ message_class = self._message_descriptor._concrete_class @@ -549,10 +576,10 @@ def __init__(self, message_listener, message_descriptor, key_checker, self._values = {} def __getitem__(self, key): + key = self._key_checker.CheckValue(key) try: return self._values[key] except KeyError: - key = self._key_checker.CheckValue(key) new_element = self._message_descriptor._concrete_class() new_element._SetListener(self._message_listener) self._values[key] = new_element @@ -584,12 +611,14 @@ def get(self, key, default=None): return default def __contains__(self, item): + item = self._key_checker.CheckValue(item) return item in self._values def __setitem__(self, key, value): raise ValueError('May not set values directly, call my_map[key].foo = 5') def __delitem__(self, key): + key = self._key_checker.CheckValue(key) del self._values[key] self._message_listener.Modified() @@ -603,7 +632,8 @@ def __repr__(self): return repr(self._values) def MergeFrom(self, other): - for key in other: + # pylint: disable=protected-access + for key in other._values: # According to documentation: "When parsing from the wire or when merging, # if there are duplicate map keys the last key seen is used". if key in self: @@ -626,3 +656,130 @@ def clear(self): def GetEntryClass(self): return self._entry_descriptor._concrete_class + + +class _UnknownField(object): + + """A parsed unknown field.""" + + # Disallows assignment to other attributes. + __slots__ = ['_field_number', '_wire_type', '_data'] + + def __init__(self, field_number, wire_type, data): + self._field_number = field_number + self._wire_type = wire_type + self._data = data + return + + def __lt__(self, other): + # pylint: disable=protected-access + return self._field_number < other._field_number + + def __eq__(self, other): + if self is other: + return True + # pylint: disable=protected-access + return (self._field_number == other._field_number and + self._wire_type == other._wire_type and + self._data == other._data) + + +class UnknownFieldRef(object): + + def __init__(self, parent, index): + self._parent = parent + self._index = index + return + + def _check_valid(self): + if not self._parent: + raise ValueError('UnknownField does not exist. ' + 'The parent message might be cleared.') + if self._index >= len(self._parent): + raise ValueError('UnknownField does not exist. ' + 'The parent message might be cleared.') + + @property + def field_number(self): + self._check_valid() + # pylint: disable=protected-access + return self._parent._internal_get(self._index)._field_number + + @property + def wire_type(self): + self._check_valid() + # pylint: disable=protected-access + return self._parent._internal_get(self._index)._wire_type + + @property + def data(self): + self._check_valid() + # pylint: disable=protected-access + return self._parent._internal_get(self._index)._data + + +class UnknownFieldSet(object): + + """UnknownField container""" + + # Disallows assignment to other attributes. + __slots__ = ['_values'] + + def __init__(self): + self._values = [] + + def __getitem__(self, index): + if self._values is None: + raise ValueError('UnknownFields does not exist. ' + 'The parent message might be cleared.') + size = len(self._values) + if index < 0: + index += size + if index < 0 or index >= size: + raise IndexError('index %d out of range'.index) + + return UnknownFieldRef(self, index) + + def _internal_get(self, index): + return self._values[index] + + def __len__(self): + if self._values is None: + raise ValueError('UnknownFields does not exist. ' + 'The parent message might be cleared.') + return len(self._values) + + def _add(self, field_number, wire_type, data): + unknown_field = _UnknownField(field_number, wire_type, data) + self._values.append(unknown_field) + return unknown_field + + def __iter__(self): + for i in range(len(self)): + yield UnknownFieldRef(self, i) + + def _extend(self, other): + if other is None: + return + # pylint: disable=protected-access + self._values.extend(other._values) + + def __eq__(self, other): + if self is other: + return True + # Sort unknown fields because their order shouldn't + # affect equality test. + values = list(self._values) + if other is None: + return not values + values.sort() + # pylint: disable=protected-access + other_values = sorted(other._values) + return values == other_values + + def _clear(self): + for value in self._values: + # pylint: disable=protected-access + if isinstance(value._data, UnknownFieldSet): + value._data._clear() # pylint: disable=protected-access + self._values = None diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py old mode 100755 new mode 100644 index ff3e6d306c5d4..6804986b6ebe2 --- a/python/google/protobuf/internal/decoder.py +++ b/python/google/protobuf/internal/decoder.py @@ -81,12 +81,17 @@ __author__ = 'kenton@google.com (Kenton Varda)' import struct - +import sys import six +_UCS2_MAXUNICODE = 65535 if six.PY3: long = int +else: + import re # pylint: disable=g-import-not-at-top + _SURROGATE_PATTERN = re.compile(six.u(r'[\ud800-\udfff]')) +from google.protobuf.internal import containers from google.protobuf.internal import encoder from google.protobuf.internal import wire_format from google.protobuf import message @@ -167,7 +172,7 @@ def DecodeVarint(buffer, pos): def ReadTag(buffer, pos): - """Read a tag from the buffer, and return a (tag_bytes, new_pos) tuple. + """Read a tag from the memoryview, and return a (tag_bytes, new_pos) tuple. We return the raw bytes of the tag rather than decoding them. The raw bytes can then be used to look up the proper decoder. This effectively allows @@ -175,13 +180,21 @@ def ReadTag(buffer, pos): for work that is done in C (searching for a byte string in a hash table). In a low-level language it would be much cheaper to decode the varint and use that, but not in Python. - """ + Args: + buffer: memoryview object of the encoded bytes + pos: int of the current position to start from + + Returns: + Tuple[bytes, int] of the tag data and new position. + """ start = pos while six.indexbytes(buffer, pos) & 0x80: pos += 1 pos += 1 - return (buffer[start:pos], pos) + + tag_bytes = buffer[start:pos].tobytes() + return tag_bytes, pos # -------------------------------------------------------------------- @@ -196,7 +209,8 @@ def _SimpleDecoder(wire_type, decode_value): _DecodeVarint() """ - def SpecificDecoder(field_number, is_repeated, is_packed, key, new_default): + def SpecificDecoder(field_number, is_repeated, is_packed, key, new_default, + clear_if_default=False): if is_packed: local_DecodeVarint = _DecodeVarint def DecodePackedField(buffer, pos, end, message, field_dict): @@ -236,10 +250,13 @@ def DecodeRepeatedField(buffer, pos, end, message, field_dict): return DecodeRepeatedField else: def DecodeField(buffer, pos, end, message, field_dict): - (field_dict[key], pos) = decode_value(buffer, pos) + (new_value, pos) = decode_value(buffer, pos) if pos > end: - del field_dict[key] # Discard corrupt value. raise _DecodeError('Truncated message.') + if clear_if_default and not new_value: + field_dict.pop(key, None) + else: + field_dict[key] = new_value return pos return DecodeField @@ -295,10 +312,20 @@ def _FloatDecoder(): local_unpack = struct.unpack def InnerDecode(buffer, pos): + """Decode serialized float to a float and new position. + + Args: + buffer: memoryview of the serialized bytes + pos: int, position in the memory view to start at. + + Returns: + Tuple[float, int] of the deserialized float value and new position + in the serialized data. + """ # We expect a 32-bit value in little-endian byte order. Bit 1 is the sign # bit, bits 2-9 represent the exponent, and bits 10-32 are the significand. new_pos = pos + 4 - float_bytes = buffer[pos:new_pos] + float_bytes = buffer[pos:new_pos].tobytes() # If this value has all its exponent bits set, then it's non-finite. # In Python 2.4, struct.unpack will convert it to a finite 64-bit value. @@ -329,10 +356,20 @@ def _DoubleDecoder(): local_unpack = struct.unpack def InnerDecode(buffer, pos): + """Decode serialized double to a double and new position. + + Args: + buffer: memoryview of the serialized bytes. + pos: int, position in the memory view to start at. + + Returns: + Tuple[float, int] of the decoded double value and new position + in the serialized data. + """ # We expect a 64-bit value in little-endian byte order. Bit 1 is the sign # bit, bits 2-12 represent the exponent, and bits 13-64 are the significand. new_pos = pos + 8 - double_bytes = buffer[pos:new_pos] + double_bytes = buffer[pos:new_pos].tobytes() # If this value has all its exponent bits set and at least one significand # bit set, it's not a number. In Python 2.4, struct.unpack will treat it @@ -350,11 +387,25 @@ def InnerDecode(buffer, pos): return _SimpleDecoder(wire_format.WIRETYPE_FIXED64, InnerDecode) -def EnumDecoder(field_number, is_repeated, is_packed, key, new_default): +def EnumDecoder(field_number, is_repeated, is_packed, key, new_default, + clear_if_default=False): + """Returns a decoder for enum field.""" enum_type = key.enum_type if is_packed: local_DecodeVarint = _DecodeVarint def DecodePackedField(buffer, pos, end, message, field_dict): + """Decode serialized packed enum to its value and a new position. + + Args: + buffer: memoryview of the serialized bytes. + pos: int, position in the memory view to start at. + end: int, end position of serialized data + message: Message object to store unknown fields in + field_dict: Map[Descriptor, Any] to store decoded values in. + + Returns: + int, new position in serialized data. + """ value = field_dict.get(key) if value is None: value = field_dict.setdefault(key, new_default(message)) @@ -365,6 +416,7 @@ def DecodePackedField(buffer, pos, end, message, field_dict): while pos < endpoint: value_start_pos = pos (element, pos) = _DecodeSignedVarint32(buffer, pos) + # pylint: disable=protected-access if element in enum_type.values_by_number: value.append(element) else: @@ -372,13 +424,22 @@ def DecodePackedField(buffer, pos, end, message, field_dict): message._unknown_fields = [] tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_VARINT) + message._unknown_fields.append( - (tag_bytes, buffer[value_start_pos:pos])) + (tag_bytes, buffer[value_start_pos:pos].tobytes())) + if message._unknown_field_set is None: + message._unknown_field_set = containers.UnknownFieldSet() + message._unknown_field_set._add( + field_number, wire_format.WIRETYPE_VARINT, element) + # pylint: enable=protected-access if pos > endpoint: if element in enum_type.values_by_number: del value[-1] # Discard corrupt value. else: del message._unknown_fields[-1] + # pylint: disable=protected-access + del message._unknown_field_set._values[-1] + # pylint: enable=protected-access raise _DecodeError('Packed element was truncated.') return pos return DecodePackedField @@ -386,18 +447,36 @@ def DecodePackedField(buffer, pos, end, message, field_dict): tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_VARINT) tag_len = len(tag_bytes) def DecodeRepeatedField(buffer, pos, end, message, field_dict): + """Decode serialized repeated enum to its value and a new position. + + Args: + buffer: memoryview of the serialized bytes. + pos: int, position in the memory view to start at. + end: int, end position of serialized data + message: Message object to store unknown fields in + field_dict: Map[Descriptor, Any] to store decoded values in. + + Returns: + int, new position in serialized data. + """ value = field_dict.get(key) if value is None: value = field_dict.setdefault(key, new_default(message)) while 1: (element, new_pos) = _DecodeSignedVarint32(buffer, pos) + # pylint: disable=protected-access if element in enum_type.values_by_number: value.append(element) else: if not message._unknown_fields: message._unknown_fields = [] message._unknown_fields.append( - (tag_bytes, buffer[pos:new_pos])) + (tag_bytes, buffer[pos:new_pos].tobytes())) + if message._unknown_field_set is None: + message._unknown_field_set = containers.UnknownFieldSet() + message._unknown_field_set._add( + field_number, wire_format.WIRETYPE_VARINT, element) + # pylint: enable=protected-access # Predict that the next tag is another copy of the same repeated # field. pos = new_pos + tag_len @@ -409,10 +488,26 @@ def DecodeRepeatedField(buffer, pos, end, message, field_dict): return DecodeRepeatedField else: def DecodeField(buffer, pos, end, message, field_dict): + """Decode serialized repeated enum to its value and a new position. + + Args: + buffer: memoryview of the serialized bytes. + pos: int, position in the memory view to start at. + end: int, end position of serialized data + message: Message object to store unknown fields in + field_dict: Map[Descriptor, Any] to store decoded values in. + + Returns: + int, new position in serialized data. + """ value_start_pos = pos (enum_value, pos) = _DecodeSignedVarint32(buffer, pos) if pos > end: raise _DecodeError('Truncated message.') + if clear_if_default and not enum_value: + field_dict.pop(key, None) + return pos + # pylint: disable=protected-access if enum_value in enum_type.values_by_number: field_dict[key] = enum_value else: @@ -421,7 +516,12 @@ def DecodeField(buffer, pos, end, message, field_dict): tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_VARINT) message._unknown_fields.append( - (tag_bytes, buffer[value_start_pos:pos])) + (tag_bytes, buffer[value_start_pos:pos].tobytes())) + if message._unknown_field_set is None: + message._unknown_field_set = containers.UnknownFieldSet() + message._unknown_field_set._add( + field_number, wire_format.WIRETYPE_VARINT, enum_value) + # pylint: enable=protected-access return pos return DecodeField @@ -458,20 +558,34 @@ def DecodeField(buffer, pos, end, message, field_dict): wire_format.WIRETYPE_VARINT, _DecodeVarint, bool) -def StringDecoder(field_number, is_repeated, is_packed, key, new_default): +def StringDecoder(field_number, is_repeated, is_packed, key, new_default, + is_strict_utf8=False, clear_if_default=False): """Returns a decoder for a string field.""" local_DecodeVarint = _DecodeVarint local_unicode = six.text_type - def _ConvertToUnicode(byte_str): + def _ConvertToUnicode(memview): + """Convert byte to unicode.""" + byte_str = memview.tobytes() try: - return local_unicode(byte_str, 'utf-8') + value = local_unicode(byte_str, 'utf-8') except UnicodeDecodeError as e: # add more information to the error message and re-raise it. e.reason = '%s in field: %s' % (e, key.full_name) raise + if is_strict_utf8 and six.PY2 and sys.maxunicode > _UCS2_MAXUNICODE: + # Only do the check for python2 ucs4 when is_strict_utf8 enabled + if _SURROGATE_PATTERN.search(value): + reason = ('String field %s contains invalid UTF-8 data when parsing' + 'a protocol buffer: surrogates not allowed. Use' + 'the bytes type if you intend to send raw bytes.') % ( + key.full_name) + raise message.DecodeError(reason) + + return value + assert not is_packed if is_repeated: tag_bytes = encoder.TagBytes(field_number, @@ -499,12 +613,16 @@ def DecodeField(buffer, pos, end, message, field_dict): new_pos = pos + size if new_pos > end: raise _DecodeError('Truncated string.') - field_dict[key] = _ConvertToUnicode(buffer[pos:new_pos]) + if clear_if_default and not size: + field_dict.pop(key, None) + else: + field_dict[key] = _ConvertToUnicode(buffer[pos:new_pos]) return new_pos return DecodeField -def BytesDecoder(field_number, is_repeated, is_packed, key, new_default): +def BytesDecoder(field_number, is_repeated, is_packed, key, new_default, + clear_if_default=False): """Returns a decoder for a bytes field.""" local_DecodeVarint = _DecodeVarint @@ -523,7 +641,7 @@ def DecodeRepeatedField(buffer, pos, end, message, field_dict): new_pos = pos + size if new_pos > end: raise _DecodeError('Truncated string.') - value.append(buffer[pos:new_pos]) + value.append(buffer[pos:new_pos].tobytes()) # Predict that the next tag is another copy of the same repeated field. pos = new_pos + tag_len if buffer[new_pos:pos] != tag_bytes or new_pos == end: @@ -536,7 +654,10 @@ def DecodeField(buffer, pos, end, message, field_dict): new_pos = pos + size if new_pos > end: raise _DecodeError('Truncated string.') - field_dict[key] = buffer[pos:new_pos] + if clear_if_default and not size: + field_dict.pop(key, None) + else: + field_dict[key] = buffer[pos:new_pos].tobytes() return new_pos return DecodeField @@ -665,6 +786,18 @@ def MessageSetItemDecoder(descriptor): local_SkipField = SkipField def DecodeItem(buffer, pos, end, message, field_dict): + """Decode serialized message set to its value and new position. + + Args: + buffer: memoryview of the serialized bytes. + pos: int, position in the memory view to start at. + end: int, end position of serialized data + message: Message object to store unknown fields in + field_dict: Map[Descriptor, Any] to store decoded values in. + + Returns: + int, new position in serialized data. + """ message_set_item_start = pos type_id = -1 message_start = -1 @@ -695,11 +828,16 @@ def DecodeItem(buffer, pos, end, message, field_dict): raise _DecodeError('MessageSet item missing message.') extension = message.Extensions._FindExtensionByNumber(type_id) + # pylint: disable=protected-access if extension is not None: value = field_dict.get(extension) if value is None: + message_type = extension.message_type + if not hasattr(message_type, '_concrete_class'): + # pylint: disable=protected-access + message._FACTORY.GetPrototype(message_type) value = field_dict.setdefault( - extension, extension.message_type._concrete_class()) + extension, message_type._concrete_class()) if value._InternalParse(buffer, message_start,message_end) != message_end: # The only reason _InternalParse would return early is if it encountered # an end-group tag. @@ -707,8 +845,15 @@ def DecodeItem(buffer, pos, end, message, field_dict): else: if not message._unknown_fields: message._unknown_fields = [] - message._unknown_fields.append((MESSAGE_SET_ITEM_TAG, - buffer[message_set_item_start:pos])) + message._unknown_fields.append( + (MESSAGE_SET_ITEM_TAG, buffer[message_set_item_start:pos].tobytes())) + if message._unknown_field_set is None: + message._unknown_field_set = containers.UnknownFieldSet() + message._unknown_field_set._add( + type_id, + wire_format.WIRETYPE_LENGTH_DELIMITED, + buffer[message_start:message_end].tobytes()) + # pylint: enable=protected-access return pos @@ -746,7 +891,7 @@ def DecodeMap(buffer, pos, end, message, field_dict): raise _DecodeError('Unexpected end-group tag.') if is_message_map: - value[submsg.key].MergeFrom(submsg.value) + value[submsg.key].CopyFrom(submsg.value) else: value[submsg.key] = submsg.value @@ -767,7 +912,7 @@ def _SkipVarint(buffer, pos, end): # Previously ord(buffer[pos]) raised IndexError when pos is out of range. # With this code, ord(b'') raises TypeError. Both are handled in # python_message.py to generate a 'Truncated message' error. - while ord(buffer[pos:pos+1]) & 0x80: + while ord(buffer[pos:pos+1].tobytes()) & 0x80: pos += 1 pos += 1 if pos > end: @@ -782,6 +927,13 @@ def _SkipFixed64(buffer, pos, end): raise _DecodeError('Truncated message.') return pos + +def _DecodeFixed64(buffer, pos): + """Decode a fixed64.""" + new_pos = pos + 8 + return (struct.unpack('= (3,): key, item = next(iter(mapping.items())) else: key, item = mapping.items()[0] self.assertIn(key, mapping) # Container self.assertEqual(mapping.get(key), item) + with self.assertRaises(TypeError): + mapping.get() + # TODO(jieluo): Fix python and cpp extension diff. + if api_implementation.Type() == 'python': + self.assertRaises(TypeError, mapping.get, []) + else: + self.assertEqual(None, mapping.get([])) # keys(), iterkeys() &co item = (next(iter(mapping.keys())), next(iter(mapping.values()))) self.assertEqual(item, next(iter(mapping.items()))) @@ -497,6 +605,18 @@ def CheckItems(seq, iterator): CheckItems(mapping.keys(), mapping.iterkeys()) CheckItems(mapping.values(), mapping.itervalues()) CheckItems(mapping.items(), mapping.iteritems()) + excepted_dict[key] = 'change value' + self.assertNotEqual(mapping, excepted_dict) + del excepted_dict[key] + excepted_dict['new_key'] = 'new' + self.assertNotEqual(mapping, excepted_dict) + self.assertRaises(KeyError, mapping.__getitem__, 'key_error') + self.assertRaises(KeyError, mapping.__getitem__, len(mapping) + 1) + # TODO(jieluo): Add __repr__ support for DescriptorMapping. + if api_implementation.Type() == 'python': + self.assertEqual(len(str(dict(mapping.items()))), len(str(mapping))) + else: + self.assertEqual(str(mapping)[0], '<') def testDescriptor(self): message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR @@ -506,13 +626,26 @@ def testDescriptor(self): field_descriptor = message_descriptor.fields_by_camelcase_name[ 'optionalInt32'] self.CheckFieldDescriptor(field_descriptor) + enum_descriptor = unittest_pb2.DESCRIPTOR.enum_types_by_name[ + 'ForeignEnum'] + self.assertEqual(None, enum_descriptor.containing_type) + # Test extension range + self.assertEqual( + unittest_pb2.TestAllExtensions.DESCRIPTOR.extension_ranges, + [(1, 536870912)]) + self.assertEqual( + unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR.extension_ranges, + [(42, 43), (4143, 4244), (65536, 536870912)]) def testCppDescriptorContainer(self): - # Check that the collection is still valid even if the parent disappeared. - enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum'] - values = enum.values - del enum - self.assertEqual('FOO', values[0].name) + containing_file = unittest_pb2.DESCRIPTOR + self.CheckDescriptorSequence(containing_file.dependencies) + self.CheckDescriptorMapping(containing_file.message_types_by_name) + self.CheckDescriptorMapping(containing_file.enum_types_by_name) + self.CheckDescriptorMapping(containing_file.services_by_name) + self.CheckDescriptorMapping(containing_file.extensions_by_name) + self.CheckDescriptorMapping( + unittest_pb2.TestNestedExtension.DESCRIPTOR.extensions_by_name) def testCppDescriptorContainer_Iterator(self): # Same test with the iterator @@ -521,11 +654,31 @@ def testCppDescriptorContainer_Iterator(self): del enum self.assertEqual('FOO', next(values_iter).name) + def testDescriptorNestedTypesContainer(self): + message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + nested_message_descriptor = unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR + self.assertEqual(len(message_descriptor.nested_types), 3) + self.assertFalse(None in message_descriptor.nested_types) + self.assertTrue( + nested_message_descriptor in message_descriptor.nested_types) + def testServiceDescriptor(self): service_descriptor = unittest_pb2.DESCRIPTOR.services_by_name['TestService'] self.assertEqual(service_descriptor.name, 'TestService') self.assertEqual(service_descriptor.methods[0].name, 'Foo') self.assertIs(service_descriptor.file, unittest_pb2.DESCRIPTOR) + self.assertEqual(service_descriptor.index, 0) + self.CheckDescriptorMapping(service_descriptor.methods_by_name) + + def testOneofDescriptor(self): + message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + oneof_descriptor = message_descriptor.oneofs_by_name['oneof_field'] + self.assertFalse(oneof_descriptor.has_options) + self.assertEqual(message_descriptor, oneof_descriptor.containing_type) + self.assertEqual('oneof_field', oneof_descriptor.name) + self.assertEqual('protobuf_unittest.TestAllTypes.oneof_field', + oneof_descriptor.full_name) + self.assertEqual(0, oneof_descriptor.index) class DescriptorCopyToProtoTest(unittest.TestCase): @@ -620,6 +773,19 @@ def testCopyToProto_Options(self): deprecated: true > > + field { + name: "deprecated_int32_in_oneof" + number: 2 + label: LABEL_OPTIONAL + type: TYPE_INT32 + options { + deprecated: true + } + oneof_index: 0 + } + oneof_decl { + name: "oneof_fields" + } """ self._InternalTestCopyToProto( @@ -663,49 +829,64 @@ def testCopyToProto_SeveralExtensions(self): descriptor_pb2.DescriptorProto, TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII) - # Disable this test so we can make changes to the proto file. - # TODO(xiaofeng): Enable this test after cl/55530659 is submitted. - # - # def testCopyToProto_FileDescriptor(self): - # UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = (""" - # name: 'google/protobuf/unittest_import.proto' - # package: 'protobuf_unittest_import' - # dependency: 'google/protobuf/unittest_import_public.proto' - # message_type: < - # name: 'ImportMessage' - # field: < - # name: 'd' - # number: 1 - # label: 1 # Optional - # type: 5 # TYPE_INT32 - # > - # > - # """ + - # """enum_type: < - # name: 'ImportEnum' - # value: < - # name: 'IMPORT_FOO' - # number: 7 - # > - # value: < - # name: 'IMPORT_BAR' - # number: 8 - # > - # value: < - # name: 'IMPORT_BAZ' - # number: 9 - # > - # > - # options: < - # java_package: 'com.google.protobuf.test' - # optimize_for: 1 # SPEED - # > - # public_dependency: 0 - # """) - # self._InternalTestCopyToProto( - # unittest_import_pb2.DESCRIPTOR, - # descriptor_pb2.FileDescriptorProto, - # UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII) + def testCopyToProto_FileDescriptor(self): + UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = (""" + name: 'google/protobuf/unittest_import.proto' + package: 'protobuf_unittest_import' + dependency: 'google/protobuf/unittest_import_public.proto' + message_type: < + name: 'ImportMessage' + field: < + name: 'd' + number: 1 + label: 1 # Optional + type: 5 # TYPE_INT32 + > + > + """ + + """enum_type: < + name: 'ImportEnum' + value: < + name: 'IMPORT_FOO' + number: 7 + > + value: < + name: 'IMPORT_BAR' + number: 8 + > + value: < + name: 'IMPORT_BAZ' + number: 9 + > + > + enum_type: < + name: 'ImportEnumForMap' + value: < + name: 'UNKNOWN' + number: 0 + > + value: < + name: 'FOO' + number: 1 + > + value: < + name: 'BAR' + number: 2 + > + > + options: < + java_package: 'com.google.protobuf.test' + optimize_for: 1 # SPEED + """ + + """ + cc_enable_arenas: true + > + public_dependency: 0 + """) + self._InternalTestCopyToProto( + unittest_import_pb2.DESCRIPTOR, + descriptor_pb2.FileDescriptorProto, + UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII) def testCopyToProto_ServiceDescriptor(self): TEST_SERVICE_ASCII = """ @@ -721,12 +902,47 @@ def testCopyToProto_ServiceDescriptor(self): output_type: '.protobuf_unittest.BarResponse' > """ - # TODO(rocking): enable this test after the proto descriptor change is - # checked in. - #self._InternalTestCopyToProto( - # unittest_pb2.TestService.DESCRIPTOR, - # descriptor_pb2.ServiceDescriptorProto, - # TEST_SERVICE_ASCII) + self._InternalTestCopyToProto( + unittest_pb2.TestService.DESCRIPTOR, + descriptor_pb2.ServiceDescriptorProto, + TEST_SERVICE_ASCII) + + @unittest.skipIf( + api_implementation.Type() == 'python', + 'It is not implemented in python.') + # TODO(jieluo): Add support for pure python or remove in c extension. + def testCopyToProto_MethodDescriptor(self): + expected_ascii = """ + name: 'Foo' + input_type: '.protobuf_unittest.FooRequest' + output_type: '.protobuf_unittest.FooResponse' + """ + method_descriptor = unittest_pb2.TestService.DESCRIPTOR.FindMethodByName( + 'Foo') + self._InternalTestCopyToProto( + method_descriptor, + descriptor_pb2.MethodDescriptorProto, + expected_ascii) + + @unittest.skipIf( + api_implementation.Type() == 'python', + 'Pure python does not raise error.') + # TODO(jieluo): Fix pure python to check with the proto type. + def testCopyToProto_TypeError(self): + file_proto = descriptor_pb2.FileDescriptorProto() + self.assertRaises(TypeError, + unittest_pb2.TestEmptyMessage.DESCRIPTOR.CopyToProto, + file_proto) + self.assertRaises(TypeError, + unittest_pb2.ForeignEnum.DESCRIPTOR.CopyToProto, + file_proto) + self.assertRaises(TypeError, + unittest_pb2.TestService.DESCRIPTOR.CopyToProto, + file_proto) + proto = descriptor_pb2.DescriptorProto() + self.assertRaises(TypeError, + unittest_import_pb2.DESCRIPTOR.CopyToProto, + proto) class MakeDescriptorTest(unittest.TestCase): @@ -774,6 +990,9 @@ def testMakeDescriptorWithNestedFields(self): result.nested_types[0].enum_types[0]) self.assertFalse(result.has_options) self.assertFalse(result.fields[0].has_options) + if api_implementation.Type() == 'cpp': + with self.assertRaises(AttributeError): + result.fields[0].has_options = False def testMakeDescriptorWithUnsignedIntField(self): file_descriptor_proto = descriptor_pb2.FileDescriptorProto() diff --git a/python/google/protobuf/internal/encoder.py b/python/google/protobuf/internal/encoder.py old mode 100755 new mode 100644 index ebec42e530883..0c016f3cfafd2 --- a/python/google/protobuf/internal/encoder.py +++ b/python/google/protobuf/internal/encoder.py @@ -372,14 +372,15 @@ def FieldSize(map_value): def _VarintEncoder(): """Return an encoder for a basic varint value (does not include tag).""" - def EncodeVarint(write, value, unused_deterministic): + local_int2byte = six.int2byte + def EncodeVarint(write, value, unused_deterministic=None): bits = value & 0x7f value >>= 7 while value: - write(six.int2byte(0x80|bits)) + write(local_int2byte(0x80|bits)) bits = value & 0x7f value >>= 7 - return write(six.int2byte(bits)) + return write(local_int2byte(bits)) return EncodeVarint @@ -388,16 +389,17 @@ def _SignedVarintEncoder(): """Return an encoder for a basic signed varint value (does not include tag).""" - def EncodeSignedVarint(write, value, unused_deterministic): + local_int2byte = six.int2byte + def EncodeSignedVarint(write, value, unused_deterministic=None): if value < 0: value += (1 << 64) bits = value & 0x7f value >>= 7 while value: - write(six.int2byte(0x80|bits)) + write(local_int2byte(0x80|bits)) bits = value & 0x7f value >>= 7 - return write(six.int2byte(bits)) + return write(local_int2byte(bits)) return EncodeSignedVarint @@ -418,7 +420,8 @@ def _VarintBytes(value): def TagBytes(field_number, wire_type): """Encode the given tag and return the bytes. Only called at startup.""" - return _VarintBytes(wire_format.PackTag(field_number, wire_type)) + return six.binary_type( + _VarintBytes(wire_format.PackTag(field_number, wire_type))) # -------------------------------------------------------------------- # As with sizers (see above), we have a number of common encoder @@ -523,14 +526,14 @@ def EncodePackedField(write, value, deterministic): return EncodePackedField elif is_repeated: tag_bytes = TagBytes(field_number, wire_type) - def EncodeRepeatedField(write, value, unused_deterministic): + def EncodeRepeatedField(write, value, unused_deterministic=None): for element in value: write(tag_bytes) write(local_struct_pack(format, element)) return EncodeRepeatedField else: tag_bytes = TagBytes(field_number, wire_type) - def EncodeField(write, value, unused_deterministic): + def EncodeField(write, value, unused_deterministic=None): write(tag_bytes) return write(local_struct_pack(format, value)) return EncodeField @@ -594,7 +597,7 @@ def EncodePackedField(write, value, deterministic): return EncodePackedField elif is_repeated: tag_bytes = TagBytes(field_number, wire_type) - def EncodeRepeatedField(write, value, unused_deterministic): + def EncodeRepeatedField(write, value, unused_deterministic=None): for element in value: write(tag_bytes) try: @@ -604,7 +607,7 @@ def EncodeRepeatedField(write, value, unused_deterministic): return EncodeRepeatedField else: tag_bytes = TagBytes(field_number, wire_type) - def EncodeField(write, value, unused_deterministic): + def EncodeField(write, value, unused_deterministic=None): write(tag_bytes) try: write(local_struct_pack(format, value)) @@ -661,7 +664,7 @@ def EncodePackedField(write, value, deterministic): return EncodePackedField elif is_repeated: tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT) - def EncodeRepeatedField(write, value, unused_deterministic): + def EncodeRepeatedField(write, value, unused_deterministic=None): for element in value: write(tag_bytes) if element: @@ -671,7 +674,7 @@ def EncodeRepeatedField(write, value, unused_deterministic): return EncodeRepeatedField else: tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT) - def EncodeField(write, value, unused_deterministic): + def EncodeField(write, value, unused_deterministic=None): write(tag_bytes) if value: return write(true_byte) @@ -819,7 +822,7 @@ def MapEncoder(field_descriptor): encode_message = MessageEncoder(field_descriptor.number, False, False) def EncodeField(write, value, deterministic): - value_keys = sorted(value.keys()) if deterministic else value.keys() + value_keys = sorted(value.keys()) if deterministic else value for key in value_keys: entry_msg = message_type._concrete_class(key=key, value=value[key]) encode_message(write, entry_msg, deterministic) diff --git a/python/google/protobuf/internal/enum_type_wrapper.py b/python/google/protobuf/internal/enum_type_wrapper.py index 1cffe3529596a..9ae0066584990 100644 --- a/python/google/protobuf/internal/enum_type_wrapper.py +++ b/python/google/protobuf/internal/enum_type_wrapper.py @@ -37,6 +37,8 @@ __author__ = 'rabsatt@google.com (Kevin Rabsatt)' +import six + class EnumTypeWrapper(object): """A utility for finding the names of enum values.""" @@ -46,26 +48,38 @@ class EnumTypeWrapper(object): def __init__(self, enum_type): """Inits EnumTypeWrapper with an EnumDescriptor.""" self._enum_type = enum_type - self.DESCRIPTOR = enum_type; + self.DESCRIPTOR = enum_type # pylint: disable=invalid-name - def Name(self, number): + def Name(self, number): # pylint: disable=invalid-name """Returns a string containing the name of an enum value.""" - if number in self._enum_type.values_by_number: + try: return self._enum_type.values_by_number[number].name - raise ValueError('Enum %s has no name defined for value %d' % ( - self._enum_type.name, number)) - - def Value(self, name): - """Returns the value coresponding to the given enum name.""" - if name in self._enum_type.values_by_name: + except KeyError: + pass # fall out to break exception chaining + + if not isinstance(number, six.integer_types): + raise TypeError( + 'Enum value for {} must be an int, but got {} {!r}.'.format( + self._enum_type.name, type(number), number)) + else: + # repr here to handle the odd case when you pass in a boolean. + raise ValueError('Enum {} has no name defined for value {!r}'.format( + self._enum_type.name, number)) + + def Value(self, name): # pylint: disable=invalid-name + """Returns the value corresponding to the given enum name.""" + try: return self._enum_type.values_by_name[name].number - raise ValueError('Enum %s has no value defined for name %s' % ( + except KeyError: + pass # fall out to break exception chaining + raise ValueError('Enum {} has no value defined for name {!r}'.format( self._enum_type.name, name)) def keys(self): """Return a list of the string names in the enum. - These are returned in the order they were defined in the .proto file. + Returns: + A list of strs, in the order they were defined in the .proto file. """ return [value_descriptor.name @@ -74,7 +88,8 @@ def keys(self): def values(self): """Return a list of the integer values in the enum. - These are returned in the order they were defined in the .proto file. + Returns: + A list of ints, in the order they were defined in the .proto file. """ return [value_descriptor.number @@ -83,7 +98,20 @@ def values(self): def items(self): """Return a list of the (name, value) pairs of the enum. - These are returned in the order they were defined in the .proto file. + Returns: + A list of (str, int) pairs, in the order they were defined + in the .proto file. """ return [(value_descriptor.name, value_descriptor.number) for value_descriptor in self._enum_type.values] + + def __getattr__(self, name): + """Returns the value corresponding to the given enum name.""" + try: + return super( + EnumTypeWrapper, + self).__getattribute__('_enum_type').values_by_name[name].number + except KeyError: + pass # fall out to break exception chaining + raise AttributeError('Enum {} has no value defined for name {!r}'.format( + self._enum_type.name, name)) diff --git a/python/google/protobuf/internal/extension_dict.py b/python/google/protobuf/internal/extension_dict.py new file mode 100644 index 0000000000000..b346cf283e2ca --- /dev/null +++ b/python/google/protobuf/internal/extension_dict.py @@ -0,0 +1,213 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Contains _ExtensionDict class to represent extensions. +""" + +from google.protobuf.internal import type_checkers +from google.protobuf.descriptor import FieldDescriptor + + +def _VerifyExtensionHandle(message, extension_handle): + """Verify that the given extension handle is valid.""" + + if not isinstance(extension_handle, FieldDescriptor): + raise KeyError('HasExtension() expects an extension handle, got: %s' % + extension_handle) + + if not extension_handle.is_extension: + raise KeyError('"%s" is not an extension.' % extension_handle.full_name) + + if not extension_handle.containing_type: + raise KeyError('"%s" is missing a containing_type.' + % extension_handle.full_name) + + if extension_handle.containing_type is not message.DESCRIPTOR: + raise KeyError('Extension "%s" extends message type "%s", but this ' + 'message is of type "%s".' % + (extension_handle.full_name, + extension_handle.containing_type.full_name, + message.DESCRIPTOR.full_name)) + + +# TODO(robinson): Unify error handling of "unknown extension" crap. +# TODO(robinson): Support iteritems()-style iteration over all +# extensions with the "has" bits turned on? +class _ExtensionDict(object): + + """Dict-like container for Extension fields on proto instances. + + Note that in all cases we expect extension handles to be + FieldDescriptors. + """ + + def __init__(self, extended_message): + """ + Args: + extended_message: Message instance for which we are the Extensions dict. + """ + self._extended_message = extended_message + + def __getitem__(self, extension_handle): + """Returns the current value of the given extension handle.""" + + _VerifyExtensionHandle(self._extended_message, extension_handle) + + result = self._extended_message._fields.get(extension_handle) + if result is not None: + return result + + if extension_handle.label == FieldDescriptor.LABEL_REPEATED: + result = extension_handle._default_constructor(self._extended_message) + elif extension_handle.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE: + message_type = extension_handle.message_type + if not hasattr(message_type, '_concrete_class'): + # pylint: disable=protected-access + self._extended_message._FACTORY.GetPrototype(message_type) + assert getattr(extension_handle.message_type, '_concrete_class', None), ( + 'Uninitialized concrete class found for field %r (message type %r)' + % (extension_handle.full_name, + extension_handle.message_type.full_name)) + result = extension_handle.message_type._concrete_class() + try: + result._SetListener(self._extended_message._listener_for_children) + except ReferenceError: + pass + else: + # Singular scalar -- just return the default without inserting into the + # dict. + return extension_handle.default_value + + # Atomically check if another thread has preempted us and, if not, swap + # in the new object we just created. If someone has preempted us, we + # take that object and discard ours. + # WARNING: We are relying on setdefault() being atomic. This is true + # in CPython but we haven't investigated others. This warning appears + # in several other locations in this file. + result = self._extended_message._fields.setdefault( + extension_handle, result) + + return result + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return False + + my_fields = self._extended_message.ListFields() + other_fields = other._extended_message.ListFields() + + # Get rid of non-extension fields. + my_fields = [field for field in my_fields if field.is_extension] + other_fields = [field for field in other_fields if field.is_extension] + + return my_fields == other_fields + + def __ne__(self, other): + return not self == other + + def __len__(self): + fields = self._extended_message.ListFields() + # Get rid of non-extension fields. + extension_fields = [field for field in fields if field[0].is_extension] + return len(extension_fields) + + def __hash__(self): + raise TypeError('unhashable object') + + # Note that this is only meaningful for non-repeated, scalar extension + # fields. Note also that we may have to call _Modified() when we do + # successfully set a field this way, to set any necessary "has" bits in the + # ancestors of the extended message. + def __setitem__(self, extension_handle, value): + """If extension_handle specifies a non-repeated, scalar extension + field, sets the value of that field. + """ + + _VerifyExtensionHandle(self._extended_message, extension_handle) + + if (extension_handle.label == FieldDescriptor.LABEL_REPEATED or + extension_handle.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE): + raise TypeError( + 'Cannot assign to extension "%s" because it is a repeated or ' + 'composite type.' % extension_handle.full_name) + + # It's slightly wasteful to lookup the type checker each time, + # but we expect this to be a vanishingly uncommon case anyway. + type_checker = type_checkers.GetTypeChecker(extension_handle) + # pylint: disable=protected-access + self._extended_message._fields[extension_handle] = ( + type_checker.CheckValue(value)) + self._extended_message._Modified() + + def __delitem__(self, extension_handle): + self._extended_message.ClearExtension(extension_handle) + + def _FindExtensionByName(self, name): + """Tries to find a known extension with the specified name. + + Args: + name: Extension full name. + + Returns: + Extension field descriptor. + """ + return self._extended_message._extensions_by_name.get(name, None) + + def _FindExtensionByNumber(self, number): + """Tries to find a known extension with the field number. + + Args: + number: Extension field number. + + Returns: + Extension field descriptor. + """ + return self._extended_message._extensions_by_number.get(number, None) + + def __iter__(self): + # Return a generator over the populated extension fields + return (f[0] for f in self._extended_message.ListFields() + if f[0].is_extension) + + def __contains__(self, extension_handle): + _VerifyExtensionHandle(self._extended_message, extension_handle) + + if extension_handle not in self._extended_message._fields: + return False + + if extension_handle.label == FieldDescriptor.LABEL_REPEATED: + return bool(self._extended_message._fields.get(extension_handle)) + + if extension_handle.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE: + value = self._extended_message._fields.get(extension_handle) + # pylint: disable=protected-access + return value is not None and value._is_present_in_parent + + return True diff --git a/python/google/protobuf/internal/factory_test1.proto b/python/google/protobuf/internal/factory_test1.proto index d2fbbeecf1c40..5e729f5b086d6 100644 --- a/python/google/protobuf/internal/factory_test1.proto +++ b/python/google/protobuf/internal/factory_test1.proto @@ -34,7 +34,6 @@ syntax = "proto2"; package google.protobuf.python.internal; - enum Factory1Enum { FACTORY_1_VALUE_0 = 0; FACTORY_1_VALUE_1 = 1; @@ -56,3 +55,16 @@ message Factory1Message { extensions 1000 to max; } + +message Factory1MethodRequest { + optional string argument = 1; +} + +message Factory1MethodResponse { + optional string result = 1; +} + +service Factory1Service { + // Dummy method for this dummy service. + rpc Factory1Method(Factory1MethodRequest) returns (Factory1MethodResponse) {} +} diff --git a/python/google/protobuf/internal/generator_test.py b/python/google/protobuf/internal/generator_test.py index 7f13f9da3ddf2..ab16d175d2495 100755 --- a/python/google/protobuf/internal/generator_test.py +++ b/python/google/protobuf/internal/generator_test.py @@ -306,6 +306,16 @@ def testOneof(self): else: self.assertIsNone(field_desc.containing_oneof) + def testEnumWithDupValue(self): + self.assertEqual('FOO1', + unittest_pb2.TestEnumWithDupValue.Name(unittest_pb2.FOO1)) + self.assertEqual('FOO1', + unittest_pb2.TestEnumWithDupValue.Name(unittest_pb2.FOO2)) + self.assertEqual('BAR1', + unittest_pb2.TestEnumWithDupValue.Name(unittest_pb2.BAR1)) + self.assertEqual('BAR1', + unittest_pb2.TestEnumWithDupValue.Name(unittest_pb2.BAR2)) + class SymbolDatabaseRegistrationTest(unittest.TestCase): """Checks that messages, enums and files are correctly registered.""" diff --git a/python/google/protobuf/internal/json_format_test.py b/python/google/protobuf/internal/json_format_test.py old mode 100644 new mode 100755 index 077b64dbab183..4310115a40250 --- a/python/google/protobuf/internal/json_format_test.py +++ b/python/google/protobuf/internal/json_format_test.py @@ -36,6 +36,7 @@ import json import math +import struct import sys try: @@ -49,9 +50,13 @@ from google.protobuf import struct_pb2 from google.protobuf import timestamp_pb2 from google.protobuf import wrappers_pb2 +from google.protobuf import any_test_pb2 from google.protobuf import unittest_mset_pb2 -from google.protobuf.internal import well_known_types +from google.protobuf import unittest_pb2 +from google.protobuf.internal import test_proto3_optional_pb2 +from google.protobuf import descriptor_pool from google.protobuf import json_format +from google.protobuf.util import json_format_pb2 from google.protobuf.util import json_format_proto3_pb2 @@ -159,6 +164,16 @@ def testAllFieldsToJson(self): json_format.Parse(text, parsed_message) self.assertEqual(message, parsed_message) + def testUnknownEnumToJsonAndBack(self): + text = '{\n "enumValue": 999\n}' + message = json_format_proto3_pb2.TestMessage() + message.enum_value = 999 + self.assertEqual(json_format.MessageToJson(message), + text) + parsed_message = json_format_proto3_pb2.TestMessage() + json_format.Parse(text, parsed_message) + self.assertEqual(message, parsed_message) + def testExtensionToJsonAndBack(self): message = unittest_mset_pb2.TestMessageSetContainer() ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension @@ -172,6 +187,10 @@ def testExtensionToJsonAndBack(self): json_format.Parse(message_text, parsed_message) self.assertEqual(message, parsed_message) + def testExtensionErrors(self): + self.CheckError('{"[extensionField]": {}}', + 'Message type proto3.TestMessage does not have extensions') + def testExtensionToDictAndBack(self): message = unittest_mset_pb2.TestMessageSetContainer() ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension @@ -185,6 +204,27 @@ def testExtensionToDictAndBack(self): json_format.ParseDict(message_dict, parsed_message) self.assertEqual(message, parsed_message) + def testExtensionToDictAndBackWithScalar(self): + message = unittest_pb2.TestAllExtensions() + ext1 = unittest_pb2.TestNestedExtension.test + message.Extensions[ext1] = 'data' + message_dict = json_format.MessageToDict( + message + ) + parsed_message = unittest_pb2.TestAllExtensions() + json_format.ParseDict(message_dict, parsed_message) + self.assertEqual(message, parsed_message) + + def testJsonParseDictToAnyDoesNotAlterInput(self): + orig_dict = { + 'int32Value': 20, + '@type': 'type.googleapis.com/proto3.TestMessage' + } + copied_dict = json.loads(json.dumps(orig_dict)) + parsed_message = any_pb2.Any() + json_format.ParseDict(copied_dict, parsed_message) + self.assertEqual(copied_dict, orig_dict) + def testExtensionSerializationDictMatchesProto3Spec(self): """See go/proto3-json-spec for spec. """ @@ -199,17 +239,35 @@ def testExtensionSerializationDictMatchesProto3Spec(self): golden_dict = { 'messageSet': { '[protobuf_unittest.' - 'TestMessageSetExtension1.messageSetExtension]': { + 'TestMessageSetExtension1.message_set_extension]': { 'i': 23, }, '[protobuf_unittest.' - 'TestMessageSetExtension2.messageSetExtension]': { + 'TestMessageSetExtension2.message_set_extension]': { 'str': u'foo', }, }, } self.assertEqual(golden_dict, message_dict) + parsed_msg = unittest_mset_pb2.TestMessageSetContainer() + json_format.ParseDict(golden_dict, parsed_msg) + self.assertEqual(message, parsed_msg) + def testExtensionSerializationDictMatchesProto3SpecMore(self): + """See go/proto3-json-spec for spec. + """ + message = json_format_pb2.TestMessageWithExtension() + ext = json_format_pb2.TestExtension.ext + message.Extensions[ext].value = 'stuff' + message_dict = json_format.MessageToDict( + message + ) + expected_dict = { + '[protobuf_unittest.TestExtension.ext]': { + 'value': u'stuff', + }, + } + self.assertEqual(expected_dict, message_dict) def testExtensionSerializationJsonMatchesProto3Spec(self): """See go/proto3-json-spec for spec. @@ -223,9 +281,9 @@ def testExtensionSerializationJsonMatchesProto3Spec(self): message ) ext1_text = ('protobuf_unittest.TestMessageSetExtension1.' - 'messageSetExtension') + 'message_set_extension') ext2_text = ('protobuf_unittest.TestMessageSetExtension2.' - 'messageSetExtension') + 'message_set_extension') golden_text = ('{"messageSet": {' ' "[%s]": {' ' "i": 23' @@ -236,7 +294,6 @@ def testExtensionSerializationJsonMatchesProto3Spec(self): '}}') % (ext1_text, ext2_text) self.assertEqual(json.loads(golden_text), json.loads(message_text)) - def testJsonEscapeString(self): message = json_format_proto3_pb2.TestMessage() if sys.version_info[0] < 3: @@ -284,6 +341,20 @@ def testAlwaysSeriliaze(self): parsed_message = json_format_proto3_pb2.TestMessage() self.CheckParseBack(message, parsed_message) + def testProto3Optional(self): + message = test_proto3_optional_pb2.TestProto3Optional() + self.assertEqual( + json.loads( + json_format.MessageToJson( + message, including_default_value_fields=True)), + json.loads('{}')) + message.optional_int32 = 0 + self.assertEqual( + json.loads( + json_format.MessageToJson( + message, including_default_value_fields=True)), + json.loads('{"optionalInt32": 0}')) + def testIntegersRepresentedAsFloat(self): message = json_format_proto3_pb2.TestMessage() json_format.Parse('{"int32Value": -2.147483648e9}', message) @@ -294,7 +365,18 @@ def testIntegersRepresentedAsFloat(self): self.assertEqual(message.int32_value, 1) def testMapFields(self): - message = json_format_proto3_pb2.TestMap() + message = json_format_proto3_pb2.TestNestedMap() + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads('{' + '"boolMap": {},' + '"int32Map": {},' + '"int64Map": {},' + '"uint32Map": {},' + '"uint64Map": {},' + '"stringMap": {},' + '"mapMap": {}' + '}')) message.bool_map[True] = 1 message.bool_map[False] = 2 message.int32_map[1] = 2 @@ -307,17 +389,19 @@ def testMapFields(self): message.uint64_map[2] = 3 message.string_map['1'] = 2 message.string_map['null'] = 3 + message.map_map['1'].bool_map[True] = 3 self.assertEqual( - json.loads(json_format.MessageToJson(message, True)), + json.loads(json_format.MessageToJson(message, False)), json.loads('{' '"boolMap": {"false": 2, "true": 1},' '"int32Map": {"1": 2, "2": 3},' '"int64Map": {"1": 2, "2": 3},' '"uint32Map": {"1": 2, "2": 3},' '"uint64Map": {"1": 2, "2": 3},' - '"stringMap": {"1": 2, "null": 3}' + '"stringMap": {"1": 2, "null": 3},' + '"mapMap": {"1": {"boolMap": {"true": 3}}}' '}')) - parsed_message = json_format_proto3_pb2.TestMap() + parsed_message = json_format_proto3_pb2.TestNestedMap() self.CheckParseBack(message, parsed_message) def testOneofFields(self): @@ -430,6 +514,14 @@ def testFieldMaskMessage(self): parsed_message = json_format_proto3_pb2.TestFieldMask() self.CheckParseBack(message, parsed_message) + message.value.Clear() + self.assertEqual( + json_format.MessageToJson(message, True), + '{\n' + ' "value": ""\n' + '}') + self.CheckParseBack(message, parsed_message) + def testWrapperMessage(self): message = json_format_proto3_pb2.TestWrapper() message.bool_value.value = False @@ -467,6 +559,8 @@ def testStructMessage(self): message.value['email'] = None message.value.get_or_create_struct('address')['city'] = 'SFO' message.value['address']['house_number'] = 1024 + message.value.get_or_create_struct('empty_struct') + message.value.get_or_create_list('empty_list') struct_list = message.value.get_or_create_list('list') struct_list.extend([6, 'seven', True, False, None]) struct_list.add_struct()['subkey2'] = 9 @@ -481,6 +575,8 @@ def testStructMessage(self): ' "city": "SFO", ' ' "house_number": 1024' ' }, ' + ' "empty_struct": {}, ' + ' "empty_list": [], ' ' "age": 10, ' ' "name": "Jim", ' ' "attend": true, ' @@ -491,6 +587,9 @@ def testStructMessage(self): '}')) parsed_message = json_format_proto3_pb2.TestStruct() self.CheckParseBack(message, parsed_message) + # check for regression; this used to raise + parsed_message.value['empty_struct'] + parsed_message.value['empty_list'] def testValueMessage(self): message = json_format_proto3_pb2.TestValue() @@ -537,6 +636,20 @@ def testListValueMessage(self): parsed_message = json_format_proto3_pb2.TestListValue() self.CheckParseBack(message, parsed_message) + def testNullValue(self): + message = json_format_proto3_pb2.TestOneof() + message.oneof_null_value = 0 + self.assertEqual(json_format.MessageToJson(message), + '{\n "oneofNullValue": null\n}') + parsed_message = json_format_proto3_pb2.TestOneof() + self.CheckParseBack(message, parsed_message) + # Check old format is also accepted + new_message = json_format_proto3_pb2.TestOneof() + json_format.Parse('{\n "oneofNullValue": "NULL_VALUE"\n}', + new_message) + self.assertEqual(json_format.MessageToJson(new_message), + '{\n "oneofNullValue": null\n}') + def testAnyMessage(self): message = json_format_proto3_pb2.TestAny() value1 = json_format_proto3_pb2.MessageType() @@ -583,6 +696,19 @@ def testAnyMessage(self): ' "value": {\n' ' "@type": "type.googleapis.com/proto3.TestMessage"') + def testAnyMessageDescriptorPoolMissingType(self): + packed_message = unittest_pb2.OneString() + packed_message.data = 'string' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + empty_pool = descriptor_pool.DescriptorPool() + with self.assertRaises(TypeError) as cm: + json_format.MessageToJson(message, True, descriptor_pool=empty_pool) + self.assertEqual( + 'Can not find message descriptor by type_url:' + ' type.googleapis.com/protobuf_unittest.OneString.', + str(cm.exception)) + def testWellKnownInAnyMessage(self): message = any_pb2.Any() int32_value = wrappers_pb2.Int32Value() @@ -703,6 +829,9 @@ def testParseNull(self): json_format.Parse, '{"repeatedInt32Value":[1, null]}', parsed_message) + self.CheckError('{"repeatedMessageValue":[null]}', + 'Failed to parse repeatedMessageValue field: null is not' + ' allowed to be used as an element in a repeated field.') def testNanFloat(self): message = json_format_proto3_pb2.TestMessage() @@ -713,6 +842,55 @@ def testNanFloat(self): json_format.Parse(text, parsed_message) self.assertTrue(math.isnan(parsed_message.float_value)) + def testParseDoubleToFloat(self): + message = json_format_proto3_pb2.TestMessage() + text = ('{"repeatedDoubleValue": [3.4028235e+39, 1.4028235e-39]\n}') + json_format.Parse(text, message) + self.assertEqual(message.repeated_double_value[0], 3.4028235e+39) + self.assertEqual(message.repeated_double_value[1], 1.4028235e-39) + text = ('{"repeatedFloatValue": [3.4028235e+39, 1.4028235e-39]\n}') + self.CheckError(text, + 'Failed to parse repeatedFloatValue field: ' + 'Float value too large.') + + def testFloatPrecision(self): + message = json_format_proto3_pb2.TestMessage() + message.float_value = 1.123456789 + # Set to 8 valid digits. + text = '{\n "floatValue": 1.1234568\n}' + self.assertEqual( + json_format.MessageToJson(message, float_precision=8), text) + # Set to 7 valid digits. + text = '{\n "floatValue": 1.123457\n}' + self.assertEqual( + json_format.MessageToJson(message, float_precision=7), text) + + # Default float_precision will automatic print shortest float. + message.float_value = 1.1000000011 + text = '{\n "floatValue": 1.1\n}' + self.assertEqual( + json_format.MessageToJson(message), text) + message.float_value = 1.00000075e-36 + text = '{\n "floatValue": 1.00000075e-36\n}' + self.assertEqual( + json_format.MessageToJson(message), text) + message.float_value = 12345678912345e+11 + text = '{\n "floatValue": 1.234568e+24\n}' + self.assertEqual( + json_format.MessageToJson(message), text) + + # Test a bunch of data and check json encode/decode do not + # lose precision + value_list = [0x00, 0xD8, 0x6E, 0x00] + msg2 = json_format_proto3_pb2.TestMessage() + for a in range(0, 256): + value_list[3] = a + for b in range(0, 256): + value_list[0] = b + byte_array = bytearray(value_list) + message.float_value = struct.unpack('.", + json_format.ParseDict, + {'value': UnknownClass()}, + message) + def testMessageToDict(self): message = json_format_proto3_pb2.TestMessage() message.int32_value = 12345 diff --git a/python/google/protobuf/internal/keywords_test.py b/python/google/protobuf/internal/keywords_test.py new file mode 100755 index 0000000000000..87449280a7f3c --- /dev/null +++ b/python/google/protobuf/internal/keywords_test.py @@ -0,0 +1,105 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Tests for google.protobuf.internal.keywords.""" + +import unittest + + +from google.protobuf.internal import more_messages_pb2 +from google.protobuf import descriptor_pool + + +class KeywordsConflictTest(unittest.TestCase): + + def setUp(self): + super(KeywordsConflictTest, self).setUp() + self.pool = descriptor_pool.Default() + + def testMessage(self): + message = getattr(more_messages_pb2, 'class')() + message.int_field = 123 + self.assertEqual(message.int_field, 123) + des = self.pool.FindMessageTypeByName('google.protobuf.internal.class') + self.assertEqual(des.name, 'class') + + def testNestedMessage(self): + message = getattr(more_messages_pb2, 'class')() + message.nested_message.field = 234 + self.assertEqual(message.nested_message.field, 234) + des = self.pool.FindMessageTypeByName('google.protobuf.internal.class.try') + self.assertEqual(des.name, 'try') + + def testField(self): + message = getattr(more_messages_pb2, 'class')() + setattr(message, 'if', 123) + setattr(message, 'as', 1) + self.assertEqual(getattr(message, 'if'), 123) + self.assertEqual(getattr(message, 'as'), 1) + + def testEnum(self): + class_ = getattr(more_messages_pb2, 'class') + message = class_() + # Normal enum value. + message.enum_field = more_messages_pb2.default + self.assertEqual(message.enum_field, more_messages_pb2.default) + # Top level enum value. + message.enum_field = getattr(more_messages_pb2, 'else') + self.assertEqual(message.enum_field, 1) + # Nested enum value + message.nested_enum_field = getattr(class_, 'True') + self.assertEqual(message.nested_enum_field, 1) + + def testExtension(self): + message = getattr(more_messages_pb2, 'class')() + # Top level extension + extension1 = getattr(more_messages_pb2, 'continue') + message.Extensions[extension1] = 456 + self.assertEqual(message.Extensions[extension1], 456) + # None top level extension + extension2 = getattr(more_messages_pb2.ExtendClass, 'return') + message.Extensions[extension2] = 789 + self.assertEqual(message.Extensions[extension2], 789) + + def testExtensionForNestedMessage(self): + message = getattr(more_messages_pb2, 'class')() + extension = getattr(more_messages_pb2, 'with') + message.nested_message.Extensions[extension] = 999 + self.assertEqual(message.nested_message.Extensions[extension], 999) + + def TestFullKeywordUsed(self): + message = more_messages_pb2.TestFullKeyword() + message.field2.int_field = 123 + + +if __name__ == '__main__': + unittest.main() diff --git a/python/google/protobuf/internal/message_factory_test.py b/python/google/protobuf/internal/message_factory_test.py old mode 100644 new mode 100755 index 4caa244344a59..42f91b2365bf9 --- a/python/google/protobuf/internal/message_factory_test.py +++ b/python/google/protobuf/internal/message_factory_test.py @@ -40,13 +40,16 @@ import unittest from google.protobuf import descriptor_pb2 +from google.protobuf.internal import api_implementation from google.protobuf.internal import factory_test1_pb2 from google.protobuf.internal import factory_test2_pb2 +from google.protobuf.internal import testing_refleaks from google.protobuf import descriptor_database from google.protobuf import descriptor_pool from google.protobuf import message_factory +@testing_refleaks.TestCase class MessageFactoryTest(unittest.TestCase): def setUp(self): @@ -103,11 +106,37 @@ def testGetPrototype(self): 'google.protobuf.python.internal.Factory2Message')) self.assertTrue(cls is cls2) + def testCreatePrototypeOverride(self): + class MyMessageFactory(message_factory.MessageFactory): + + def CreatePrototype(self, descriptor): + cls = super(MyMessageFactory, self).CreatePrototype(descriptor) + cls.additional_field = 'Some value' + return cls + + db = descriptor_database.DescriptorDatabase() + pool = descriptor_pool.DescriptorPool(db) + db.Add(self.factory_test1_fd) + db.Add(self.factory_test2_fd) + factory = MyMessageFactory() + cls = factory.GetPrototype(pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message')) + self.assertTrue(hasattr(cls, 'additional_field')) + def testGetMessages(self): # performed twice because multiple calls with the same input must be allowed for _ in range(2): - messages = message_factory.GetMessages([self.factory_test1_fd, - self.factory_test2_fd]) + # GetMessage should work regardless of the order the FileDescriptorProto + # are provided. In particular, the function should succeed when the files + # are not in the topological order of dependencies. + + # Assuming factory_test2_fd depends on factory_test1_fd. + self.assertIn(self.factory_test1_fd.name, + self.factory_test2_fd.dependency) + # Get messages should work when a file comes before its dependencies: + # factory_test2_fd comes before factory_test1_fd. + messages = message_factory.GetMessages([self.factory_test2_fd, + self.factory_test1_fd]) self.assertTrue( set(['google.protobuf.python.internal.Factory2Message', 'google.protobuf.python.internal.Factory1Message'], @@ -126,10 +155,24 @@ def testGetMessages(self): 'google.protobuf.python.internal.Factory2Message.one_more_field') ext2 = msg1.Extensions._FindExtensionByName( 'google.protobuf.python.internal.another_field') + self.assertEqual(0, len(msg1.Extensions)) msg1.Extensions[ext1] = 'test1' msg1.Extensions[ext2] = 'test2' self.assertEqual('test1', msg1.Extensions[ext1]) self.assertEqual('test2', msg1.Extensions[ext2]) + self.assertEqual(None, + msg1.Extensions._FindExtensionByNumber(12321)) + self.assertEqual(2, len(msg1.Extensions)) + if api_implementation.Type() == 'cpp': + self.assertRaises(TypeError, + msg1.Extensions._FindExtensionByName, 0) + self.assertRaises(TypeError, + msg1.Extensions._FindExtensionByNumber, '') + else: + self.assertEqual(None, + msg1.Extensions._FindExtensionByName(0)) + self.assertEqual(None, + msg1.Extensions._FindExtensionByNumber('')) def testDuplicateExtensionNumber(self): pool = descriptor_pool.DescriptorPool() @@ -183,7 +226,14 @@ def testDuplicateExtensionNumber(self): with self.assertRaises(Exception) as cm: factory.GetMessages([f.name]) - self.assertIsInstance(cm.exception, (AssertionError, ValueError)) + self.assertIn(str(cm.exception), + ['Extensions ' + '"google.protobuf.python.internal.Duplicate.extension_field" and' + ' "google.protobuf.python.internal.Extension.extension_field"' + ' both try to extend message type' + ' "google.protobuf.python.internal.Container"' + ' with field number 2.', + 'Double registration of Extensions']) if __name__ == '__main__': diff --git a/python/google/protobuf/internal/message_listener.py b/python/google/protobuf/internal/message_listener.py old mode 100755 new mode 100644 diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py index 29a515b2a301b..feff228fb62cf 100755 --- a/python/google/protobuf/internal/message_test.py +++ b/python/google/protobuf/internal/message_test.py @@ -1,4 +1,5 @@ #! /usr/bin/env python +# -*- coding: utf-8 -*- # # Protocol Buffers - Google's data interchange format # Copyright 2008 Google Inc. All rights reserved. @@ -44,19 +45,32 @@ __author__ = 'gps@google.com (Gregory P. Smith)' -import collections import copy import math import operator import pickle +import pydoc import six import sys +import warnings try: - import unittest2 as unittest #PY26 + # Since python 3 + import collections.abc as collections_abc +except ImportError: + # Won't work after python 3.8 + import collections as collections_abc + +try: + import unittest2 as unittest # PY26 except ImportError: import unittest +try: + cmp # Python 2 +except NameError: + cmp = lambda x, y: (x > y) - (x < y) # Python 3 +from google.protobuf import map_proto2_unittest_pb2 from google.protobuf import map_unittest_pb2 from google.protobuf import unittest_pb2 from google.protobuf import unittest_proto3_arena_pb2 @@ -65,12 +79,16 @@ from google.protobuf import message_factory from google.protobuf import text_format from google.protobuf.internal import api_implementation +from google.protobuf.internal import encoder +from google.protobuf.internal import more_extensions_pb2 from google.protobuf.internal import packed_field_test_pb2 from google.protobuf.internal import test_util +from google.protobuf.internal import test_proto3_optional_pb2 from google.protobuf.internal import testing_refleaks from google.protobuf import message from google.protobuf.internal import _parameterized +UCS2_MAXUNICODE = 65535 if six.PY3: long = int @@ -89,13 +107,14 @@ def IsNegInf(val): return isinf(val) and (val < 0) -BaseTestCase = testing_refleaks.BaseTestCase +warnings.simplefilter('error', DeprecationWarning) -@_parameterized.NamedParameters( +@_parameterized.named_parameters( ('_proto2', unittest_pb2), ('_proto3', unittest_proto3_arena_pb2)) -class MessageTest(BaseTestCase): +@testing_refleaks.TestCase +class MessageTest(unittest.TestCase): def testBadUtf8String(self, message_module): if api_implementation.Type() != 'python': @@ -128,14 +147,30 @@ def testGoldenMessage(self, message_module): def testGoldenPackedMessage(self, message_module): golden_data = test_util.GoldenFileData('golden_packed_fields_message') golden_message = message_module.TestPackedTypes() - golden_message.ParseFromString(golden_data) + parsed_bytes = golden_message.ParseFromString(golden_data) all_set = message_module.TestPackedTypes() test_util.SetAllPackedFields(all_set) + self.assertEqual(parsed_bytes, len(golden_data)) self.assertEqual(all_set, golden_message) self.assertEqual(golden_data, all_set.SerializeToString()) golden_copy = copy.deepcopy(golden_message) self.assertEqual(golden_data, golden_copy.SerializeToString()) + def testParseErrors(self, message_module): + msg = message_module.TestAllTypes() + self.assertRaises(TypeError, msg.FromString, 0) + self.assertRaises(Exception, msg.FromString, '0') + # TODO(jieluo): Fix cpp extension to raise error instead of warning. + # b/27494216 + end_tag = encoder.TagBytes(1, 4) + if api_implementation.Type() == 'python': + with self.assertRaises(message.DecodeError) as context: + msg.FromString(end_tag) + self.assertEqual('Unexpected end-group tag.', str(context.exception)) + + # Field number 0 is illegal. + self.assertRaises(message.DecodeError, msg.FromString, b'\3\4') + def testDeterminismParameters(self, message_module): # This message is always deterministically serialized, even if determinism # is disabled, so we can use it to verify that all the determinism @@ -181,6 +216,19 @@ def testPickleSupport(self, message_module): unpickled_message = pickle.loads(pickled_message) self.assertEqual(unpickled_message, golden_message) + def testPickleNestedMessage(self, message_module): + golden_message = message_module.TestPickleNestedMessage.NestedMessage(bb=1) + pickled_message = pickle.dumps(golden_message) + unpickled_message = pickle.loads(pickled_message) + self.assertEqual(unpickled_message, golden_message) + + def testPickleNestedNestedMessage(self, message_module): + cls = message_module.TestPickleNestedMessage.NestedMessage + golden_message = cls.NestedNestedMessage(cc=1) + pickled_message = pickle.dumps(golden_message) + unpickled_message = pickle.loads(pickled_message) + self.assertEqual(unpickled_message, golden_message) + def testPositiveInfinity(self, message_module): if message_module is unittest_pb2: golden_data = (b'\x5D\x00\x00\x80\x7F' @@ -322,6 +370,27 @@ def testExtremeFloatValues(self, message_module): message.ParseFromString(message.SerializeToString()) self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit) + # Max 4 bytes float value + max_float = float.fromhex('0x1.fffffep+127') + message.optional_float = max_float + self.assertAlmostEqual(message.optional_float, max_float) + serialized_data = message.SerializeToString() + message.ParseFromString(serialized_data) + self.assertAlmostEqual(message.optional_float, max_float) + + # Test set double to float field. + message.optional_float = 3.4028235e+39 + self.assertEqual(message.optional_float, float('inf')) + serialized_data = message.SerializeToString() + message.ParseFromString(serialized_data) + self.assertEqual(message.optional_float, float('inf')) + + message.optional_float = -3.4028235e+39 + self.assertEqual(message.optional_float, float('-inf')) + + message.optional_float = 1.4028235e-39 + self.assertAlmostEqual(message.optional_float, 1.4028235e-39) + def testExtremeDoubleValues(self, message_module): message = message_module.TestAllTypes() @@ -373,12 +442,19 @@ def testFloatPrinting(self, message_module): self.assertEqual(str(message), 'optional_float: 2.0\n') def testHighPrecisionFloatPrinting(self, message_module): - message = message_module.TestAllTypes() - message.optional_double = 0.12345678912345678 + msg = message_module.TestAllTypes() + msg.optional_float = 0.12345678912345678 + old_float = msg.optional_float + msg.ParseFromString(msg.SerializeToString()) + self.assertEqual(old_float, msg.optional_float) + + def testHighPrecisionDoublePrinting(self, message_module): + msg = message_module.TestAllTypes() + msg.optional_double = 0.12345678912345678 if sys.version_info >= (3,): - self.assertEqual(str(message), 'optional_double: 0.12345678912345678\n') + self.assertEqual(str(msg), 'optional_double: 0.12345678912345678\n') else: - self.assertEqual(str(message), 'optional_double: 0.123456789123\n') + self.assertEqual(str(msg), 'optional_double: 0.123456789123\n') def testUnknownFieldPrinting(self, message_module): populated = message_module.TestAllTypes() @@ -387,6 +463,113 @@ def testUnknownFieldPrinting(self, message_module): empty.ParseFromString(populated.SerializeToString()) self.assertEqual(str(empty), '') + def testAppendRepeatedCompositeField(self, message_module): + msg = message_module.TestAllTypes() + msg.repeated_nested_message.append( + message_module.TestAllTypes.NestedMessage(bb=1)) + nested = message_module.TestAllTypes.NestedMessage(bb=2) + msg.repeated_nested_message.append(nested) + try: + msg.repeated_nested_message.append(1) + except TypeError: + pass + self.assertEqual(2, len(msg.repeated_nested_message)) + self.assertEqual([1, 2], + [m.bb for m in msg.repeated_nested_message]) + + def testInsertRepeatedCompositeField(self, message_module): + msg = message_module.TestAllTypes() + msg.repeated_nested_message.insert( + -1, message_module.TestAllTypes.NestedMessage(bb=1)) + sub_msg = msg.repeated_nested_message[0] + msg.repeated_nested_message.insert( + 0, message_module.TestAllTypes.NestedMessage(bb=2)) + msg.repeated_nested_message.insert( + 99, message_module.TestAllTypes.NestedMessage(bb=3)) + msg.repeated_nested_message.insert( + -2, message_module.TestAllTypes.NestedMessage(bb=-1)) + msg.repeated_nested_message.insert( + -1000, message_module.TestAllTypes.NestedMessage(bb=-1000)) + try: + msg.repeated_nested_message.insert(1, 999) + except TypeError: + pass + self.assertEqual(5, len(msg.repeated_nested_message)) + self.assertEqual([-1000, 2, -1, 1, 3], + [m.bb for m in msg.repeated_nested_message]) + self.assertEqual(str(msg), + 'repeated_nested_message {\n' + ' bb: -1000\n' + '}\n' + 'repeated_nested_message {\n' + ' bb: 2\n' + '}\n' + 'repeated_nested_message {\n' + ' bb: -1\n' + '}\n' + 'repeated_nested_message {\n' + ' bb: 1\n' + '}\n' + 'repeated_nested_message {\n' + ' bb: 3\n' + '}\n') + self.assertEqual(sub_msg.bb, 1) + + def testMergeFromRepeatedField(self, message_module): + msg = message_module.TestAllTypes() + msg.repeated_int32.append(1) + msg.repeated_int32.append(3) + msg.repeated_nested_message.add(bb=1) + msg.repeated_nested_message.add(bb=2) + other_msg = message_module.TestAllTypes() + other_msg.repeated_nested_message.add(bb=3) + other_msg.repeated_nested_message.add(bb=4) + other_msg.repeated_int32.append(5) + other_msg.repeated_int32.append(7) + + msg.repeated_int32.MergeFrom(other_msg.repeated_int32) + self.assertEqual(4, len(msg.repeated_int32)) + + msg.repeated_nested_message.MergeFrom(other_msg.repeated_nested_message) + self.assertEqual([1, 2, 3, 4], + [m.bb for m in msg.repeated_nested_message]) + + def testAddWrongRepeatedNestedField(self, message_module): + msg = message_module.TestAllTypes() + try: + msg.repeated_nested_message.add('wrong') + except TypeError: + pass + try: + msg.repeated_nested_message.add(value_field='wrong') + except ValueError: + pass + self.assertEqual(len(msg.repeated_nested_message), 0) + + def testRepeatedContains(self, message_module): + msg = message_module.TestAllTypes() + msg.repeated_int32.extend([1, 2, 3]) + self.assertIn(2, msg.repeated_int32) + self.assertNotIn(0, msg.repeated_int32) + + msg.repeated_nested_message.add(bb=1) + sub_msg1 = msg.repeated_nested_message[0] + sub_msg2 = message_module.TestAllTypes.NestedMessage(bb=2) + sub_msg3 = message_module.TestAllTypes.NestedMessage(bb=3) + msg.repeated_nested_message.append(sub_msg2) + msg.repeated_nested_message.insert(0, sub_msg3) + self.assertIn(sub_msg1, msg.repeated_nested_message) + self.assertIn(sub_msg2, msg.repeated_nested_message) + self.assertIn(sub_msg3, msg.repeated_nested_message) + + def testRepeatedScalarIterable(self, message_module): + msg = message_module.TestAllTypes() + msg.repeated_int32.extend([1, 2, 3]) + add = 0 + for item in msg.repeated_int32: + add += item + self.assertEqual(add, 6) + def testRepeatedNestedFieldIteration(self, message_module): msg = message_module.TestAllTypes() msg.repeated_nested_message.add(bb=1) @@ -601,15 +784,101 @@ def testRepeatedFieldsComparable(self, message_module): def testRepeatedFieldsAreSequences(self, message_module): m = message_module.TestAllTypes() - self.assertIsInstance(m.repeated_int32, collections.MutableSequence) + self.assertIsInstance(m.repeated_int32, collections_abc.MutableSequence) self.assertIsInstance(m.repeated_nested_message, - collections.MutableSequence) + collections_abc.MutableSequence) + + def testRepeatedFieldsNotHashable(self, message_module): + m = message_module.TestAllTypes() + with self.assertRaises(TypeError): + hash(m.repeated_int32) + with self.assertRaises(TypeError): + hash(m.repeated_nested_message) def testRepeatedFieldInsideNestedMessage(self, message_module): m = message_module.NestedTestAllTypes() m.payload.repeated_int32.extend([]) self.assertTrue(m.HasField('payload')) + def testMergeFrom(self, message_module): + m1 = message_module.TestAllTypes() + m2 = message_module.TestAllTypes() + # Cpp extension will lazily create a sub message which is immutable. + nested = m1.optional_nested_message + self.assertEqual(0, nested.bb) + m2.optional_nested_message.bb = 1 + # Make sure cmessage pointing to a mutable message after merge instead of + # the lazily created message. + m1.MergeFrom(m2) + self.assertEqual(1, nested.bb) + + # Test more nested sub message. + msg1 = message_module.NestedTestAllTypes() + msg2 = message_module.NestedTestAllTypes() + nested = msg1.child.payload.optional_nested_message + self.assertEqual(0, nested.bb) + msg2.child.payload.optional_nested_message.bb = 1 + msg1.MergeFrom(msg2) + self.assertEqual(1, nested.bb) + + # Test repeated field. + self.assertEqual(msg1.payload.repeated_nested_message, + msg1.payload.repeated_nested_message) + nested = msg2.payload.repeated_nested_message.add() + nested.bb = 1 + msg1.MergeFrom(msg2) + self.assertEqual(1, len(msg1.payload.repeated_nested_message)) + self.assertEqual(1, nested.bb) + + def testMergeFromString(self, message_module): + m1 = message_module.TestAllTypes() + m2 = message_module.TestAllTypes() + # Cpp extension will lazily create a sub message which is immutable. + self.assertEqual(0, m1.optional_nested_message.bb) + m2.optional_nested_message.bb = 1 + # Make sure cmessage pointing to a mutable message after merge instead of + # the lazily created message. + m1.MergeFromString(m2.SerializeToString()) + self.assertEqual(1, m1.optional_nested_message.bb) + + @unittest.skipIf(six.PY2, 'memoryview objects are not supported on py2') + def testMergeFromStringUsingMemoryViewWorksInPy3(self, message_module): + m2 = message_module.TestAllTypes() + m2.optional_string = 'scalar string' + m2.repeated_string.append('repeated string') + m2.optional_bytes = b'scalar bytes' + m2.repeated_bytes.append(b'repeated bytes') + + serialized = m2.SerializeToString() + memview = memoryview(serialized) + m1 = message_module.TestAllTypes.FromString(memview) + + self.assertEqual(m1.optional_bytes, b'scalar bytes') + self.assertEqual(m1.repeated_bytes, [b'repeated bytes']) + self.assertEqual(m1.optional_string, 'scalar string') + self.assertEqual(m1.repeated_string, ['repeated string']) + # Make sure that the memoryview was correctly converted to bytes, and + # that a sub-sliced memoryview is not being used. + self.assertIsInstance(m1.optional_bytes, bytes) + self.assertIsInstance(m1.repeated_bytes[0], bytes) + self.assertIsInstance(m1.optional_string, six.text_type) + self.assertIsInstance(m1.repeated_string[0], six.text_type) + + @unittest.skipIf(six.PY3, 'memoryview is supported by py3') + def testMergeFromStringUsingMemoryViewIsPy2Error(self, message_module): + memview = memoryview(b'') + with self.assertRaises(TypeError): + message_module.TestAllTypes.FromString(memview) + + def testMergeFromEmpty(self, message_module): + m1 = message_module.TestAllTypes() + # Cpp extension will lazily create a sub message which is immutable. + self.assertEqual(0, m1.optional_nested_message.bb) + self.assertFalse(m1.HasField('optional_nested_message')) + # Make sure the sub message is still immutable after merge from empty. + m1.MergeFromString(b'') # field state should not change + self.assertFalse(m1.HasField('optional_nested_message')) + def ensureNestedMessageExists(self, msg, attribute): """Make sure that a nested message object exists. @@ -622,15 +891,18 @@ def ensureNestedMessageExists(self, msg, attribute): def testOneofGetCaseNonexistingField(self, message_module): m = message_module.TestAllTypes() self.assertRaises(ValueError, m.WhichOneof, 'no_such_oneof_field') + self.assertRaises(Exception, m.WhichOneof, 0) def testOneofDefaultValues(self, message_module): m = message_module.TestAllTypes() self.assertIs(None, m.WhichOneof('oneof_field')) + self.assertFalse(m.HasField('oneof_field')) self.assertFalse(m.HasField('oneof_uint32')) # Oneof is set even when setting it to a default value. m.oneof_uint32 = 0 self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + self.assertTrue(m.HasField('oneof_field')) self.assertTrue(m.HasField('oneof_uint32')) self.assertFalse(m.HasField('oneof_string')) @@ -787,7 +1059,7 @@ def testAssignByteStringToUnicodeField(self, message_module): self.assertIsInstance(m.optional_string, six.text_type) def testLongValuedSlice(self, message_module): - """It should be possible to use long-valued indicies in slices + """It should be possible to use long-valued indices in slices. This didn't used to work in the v2 C++ implementation. """ @@ -997,6 +1269,8 @@ def testRepeatedCompositeFieldPop(self, message_module): m = message_module.TestAllTypes() with self.assertRaises(IndexError) as _: m.repeated_nested_message.pop() + with self.assertRaises(TypeError) as _: + m.repeated_nested_message.pop('0') for i in range(5): n = m.repeated_nested_message.add() n.bb = i @@ -1005,9 +1279,58 @@ def testRepeatedCompositeFieldPop(self, message_module): self.assertEqual(2, m.repeated_nested_message.pop(1).bb) self.assertEqual([1, 3], [n.bb for n in m.repeated_nested_message]) + def testRepeatedCompareWithSelf(self, message_module): + m = message_module.TestAllTypes() + for i in range(5): + m.repeated_int32.insert(i, i) + n = m.repeated_nested_message.add() + n.bb = i + self.assertSequenceEqual(m.repeated_int32, m.repeated_int32) + self.assertEqual(m.repeated_nested_message, m.repeated_nested_message) + + def testReleasedNestedMessages(self, message_module): + """A case that lead to a segfault when a message detached from its parent + container has itself a child container. + """ + m = message_module.NestedTestAllTypes() + m = m.repeated_child.add() + m = m.child + m = m.repeated_child.add() + self.assertEqual(m.payload.optional_int32, 0) + + def testSetRepeatedComposite(self, message_module): + m = message_module.TestAllTypes() + with self.assertRaises(AttributeError): + m.repeated_int32 = [] + m.repeated_int32.append(1) + with self.assertRaises(AttributeError): + m.repeated_int32 = [] + + def testReturningType(self, message_module): + m = message_module.TestAllTypes() + self.assertEqual(float, type(m.optional_float)) + self.assertEqual(float, type(m.optional_double)) + self.assertEqual(bool, type(m.optional_bool)) + m.optional_float = 1 + m.optional_double = 1 + m.optional_bool = 1 + m.repeated_float.append(1) + m.repeated_double.append(1) + m.repeated_bool.append(1) + m.ParseFromString(m.SerializeToString()) + self.assertEqual(float, type(m.optional_float)) + self.assertEqual(float, type(m.optional_double)) + self.assertEqual('1.0', str(m.optional_double)) + self.assertEqual(bool, type(m.optional_bool)) + self.assertEqual(float, type(m.repeated_float[0])) + self.assertEqual(float, type(m.repeated_double[0])) + self.assertEqual(bool, type(m.repeated_bool[0])) + self.assertEqual(True, m.repeated_bool[0]) + # Class to test proto2-only features (required, extensions, etc.) -class Proto2Test(BaseTestCase): +@testing_refleaks.TestCase +class Proto2Test(unittest.TestCase): def testFieldPresence(self): message = unittest_pb2.TestAllTypes() @@ -1041,13 +1364,13 @@ def testFieldPresence(self): message.optional_bool = True message.optional_nested_message.bb = 15 - self.assertTrue(message.HasField("optional_int32")) + self.assertTrue(message.HasField(u"optional_int32")) self.assertTrue(message.HasField("optional_bool")) self.assertTrue(message.HasField("optional_nested_message")) # Clearing the fields unsets them and resets their value to default. message.ClearField("optional_int32") - message.ClearField("optional_bool") + message.ClearField(u"optional_bool") message.ClearField("optional_nested_message") self.assertFalse(message.HasField("optional_int32")) @@ -1057,18 +1380,61 @@ def testFieldPresence(self): self.assertEqual(False, message.optional_bool) self.assertEqual(0, message.optional_nested_message.bb) - # TODO(tibell): The C++ implementations actually allows assignment - # of unknown enum values to *scalar* fields (but not repeated - # fields). Once checked enum fields becomes the default in the - # Python implementation, the C++ implementation should follow suit. def testAssignInvalidEnum(self): - """It should not be possible to assign an invalid enum number to an - enum field.""" + """Assigning an invalid enum number is not allowed in proto2.""" m = unittest_pb2.TestAllTypes() + # Proto2 can not assign unknown enum. with self.assertRaises(ValueError) as _: m.optional_nested_enum = 1234567 self.assertRaises(ValueError, m.repeated_nested_enum.append, 1234567) + # Assignment is a different code path than append for the C++ impl. + m.repeated_nested_enum.append(2) + m.repeated_nested_enum[0] = 2 + with self.assertRaises(ValueError): + m.repeated_nested_enum[0] = 123456 + + # Unknown enum value can be parsed but is ignored. + m2 = unittest_proto3_arena_pb2.TestAllTypes() + m2.optional_nested_enum = 1234567 + m2.repeated_nested_enum.append(7654321) + serialized = m2.SerializeToString() + + m3 = unittest_pb2.TestAllTypes() + m3.ParseFromString(serialized) + self.assertFalse(m3.HasField('optional_nested_enum')) + # 1 is the default value for optional_nested_enum. + self.assertEqual(1, m3.optional_nested_enum) + self.assertEqual(0, len(m3.repeated_nested_enum)) + m2.Clear() + m2.ParseFromString(m3.SerializeToString()) + self.assertEqual(1234567, m2.optional_nested_enum) + self.assertEqual(7654321, m2.repeated_nested_enum[0]) + + def testUnknownEnumMap(self): + m = map_proto2_unittest_pb2.TestEnumMap() + m.known_map_field[123] = 0 + with self.assertRaises(ValueError): + m.unknown_map_field[1] = 123 + + def testExtensionsErrors(self): + msg = unittest_pb2.TestAllTypes() + self.assertRaises(AttributeError, getattr, msg, 'Extensions') + + def testMergeFromExtensions(self): + msg1 = more_extensions_pb2.TopLevelMessage() + msg2 = more_extensions_pb2.TopLevelMessage() + # Cpp extension will lazily create a sub message which is immutable. + self.assertEqual(0, msg1.submessage.Extensions[ + more_extensions_pb2.optional_int_extension]) + self.assertFalse(msg1.HasField('submessage')) + msg2.submessage.Extensions[ + more_extensions_pb2.optional_int_extension] = 123 + # Make sure cmessage and extensions pointing to a mutable message + # after merge instead of the lazily created message. + msg1.MergeFrom(msg2) + self.assertEqual(123, msg1.submessage.Extensions[ + more_extensions_pb2.optional_int_extension]) def testGoldenExtensions(self): golden_data = test_util.GoldenFileData('golden_message') @@ -1216,10 +1582,30 @@ def testPythonicInit(self): with self.assertRaises(ValueError): unittest_pb2.TestAllTypes(repeated_nested_enum='FOO') + def testPythonicInitWithDict(self): + # Both string/unicode field name keys should work. + kwargs = { + 'optional_int32': 100, + u'optional_fixed32': 200, + } + msg = unittest_pb2.TestAllTypes(**kwargs) + self.assertEqual(100, msg.optional_int32) + self.assertEqual(200, msg.optional_fixed32) + + + def test_documentation(self): + # Also used by the interactive help() function. + doc = pydoc.html.document(unittest_pb2.TestAllTypes, 'message') + self.assertIn('class TestAllTypes', doc) + self.assertIn('SerializePartialToString', doc) + self.assertIn('repeated_float', doc) + base = unittest_pb2.TestAllTypes.__bases__[0] + self.assertRaises(AttributeError, getattr, base, '_extensions_by_name') # Class to test proto3-only features/behavior (updated field presence & enums) -class Proto3Test(BaseTestCase): +@testing_refleaks.TestCase +class Proto3Test(unittest.TestCase): # Utility method for comparing equality with a map. def assertMapIterEquals(self, map_iter, dict_value): @@ -1289,10 +1675,75 @@ def testFieldPresence(self): self.assertEqual(False, message.optional_bool) self.assertEqual(0, message.optional_nested_message.bb) + def testProto3ParserDropDefaultScalar(self): + message_proto2 = unittest_pb2.TestAllTypes() + message_proto2.optional_int32 = 0 + message_proto2.optional_string = '' + message_proto2.optional_bytes = b'' + self.assertEqual(len(message_proto2.ListFields()), 3) + + message_proto3 = unittest_proto3_arena_pb2.TestAllTypes() + message_proto3.ParseFromString(message_proto2.SerializeToString()) + self.assertEqual(len(message_proto3.ListFields()), 0) + + def testProto3Optional(self): + msg = test_proto3_optional_pb2.TestProto3Optional() + self.assertFalse(msg.HasField('optional_int32')) + self.assertFalse(msg.HasField('optional_float')) + self.assertFalse(msg.HasField('optional_string')) + self.assertFalse(msg.HasField('optional_nested_message')) + self.assertFalse(msg.optional_nested_message.HasField('bb')) + + # Set fields. + msg.optional_int32 = 1 + msg.optional_float = 1.0 + msg.optional_string = '123' + msg.optional_nested_message.bb = 1 + self.assertTrue(msg.HasField('optional_int32')) + self.assertTrue(msg.HasField('optional_float')) + self.assertTrue(msg.HasField('optional_string')) + self.assertTrue(msg.HasField('optional_nested_message')) + self.assertTrue(msg.optional_nested_message.HasField('bb')) + # Set to default value does not clear the fields + msg.optional_int32 = 0 + msg.optional_float = 0.0 + msg.optional_string = '' + msg.optional_nested_message.bb = 0 + self.assertTrue(msg.HasField('optional_int32')) + self.assertTrue(msg.HasField('optional_float')) + self.assertTrue(msg.HasField('optional_string')) + self.assertTrue(msg.HasField('optional_nested_message')) + self.assertTrue(msg.optional_nested_message.HasField('bb')) + + # Test serialize + msg2 = test_proto3_optional_pb2.TestProto3Optional() + msg2.ParseFromString(msg.SerializeToString()) + self.assertTrue(msg2.HasField('optional_int32')) + self.assertTrue(msg2.HasField('optional_float')) + self.assertTrue(msg2.HasField('optional_string')) + self.assertTrue(msg2.HasField('optional_nested_message')) + self.assertTrue(msg2.optional_nested_message.HasField('bb')) + + self.assertEqual(msg.WhichOneof('_optional_int32'), 'optional_int32') + + # Clear these fields. + msg.ClearField('optional_int32') + msg.ClearField('optional_float') + msg.ClearField('optional_string') + msg.ClearField('optional_nested_message') + self.assertFalse(msg.HasField('optional_int32')) + self.assertFalse(msg.HasField('optional_float')) + self.assertFalse(msg.HasField('optional_string')) + self.assertFalse(msg.HasField('optional_nested_message')) + self.assertFalse(msg.optional_nested_message.HasField('bb')) + + self.assertEqual(msg.WhichOneof('_optional_int32'), None) + def testAssignUnknownEnum(self): """Assigning an unknown enum value is allowed and preserves the value.""" m = unittest_proto3_arena_pb2.TestAllTypes() + # Proto3 can assign unknown enums. m.optional_nested_enum = 1234567 self.assertEqual(1234567, m.optional_nested_enum) m.repeated_nested_enum.append(22334455) @@ -1307,18 +1758,10 @@ def testAssignUnknownEnum(self): self.assertEqual(1234567, m2.optional_nested_enum) self.assertEqual(7654321, m2.repeated_nested_enum[0]) - # ParseFromString in Proto2 should accept unknown enums too. - m3 = unittest_pb2.TestAllTypes() - m3.ParseFromString(serialized) - m2.Clear() - m2.ParseFromString(m3.SerializeToString()) - self.assertEqual(1234567, m2.optional_nested_enum) - self.assertEqual(7654321, m2.repeated_nested_enum[0]) - # Map isn't really a proto3-only feature. But there is no proto2 equivalent # of google/protobuf/map_unittest.proto right now, so it's not easy to # test both with the same test like we do for the other proto2/proto3 tests. - # (google/protobuf/map_protobuf_unittest.proto is very different in the set + # (google/protobuf/map_proto2_unittest.proto is very different in the set # of messages and fields it contains). def testScalarMapDefaults(self): msg = map_unittest_pb2.TestMap() @@ -1375,16 +1818,23 @@ def testMapGet(self): self.assertIsNone(msg.map_int32_int32.get(5)) self.assertEqual(10, msg.map_int32_int32.get(5, 10)) + self.assertEqual(10, msg.map_int32_int32.get(key=5, default=10)) self.assertIsNone(msg.map_int32_int32.get(5)) msg.map_int32_int32[5] = 15 self.assertEqual(15, msg.map_int32_int32.get(5)) + self.assertEqual(15, msg.map_int32_int32.get(5)) + with self.assertRaises(TypeError): + msg.map_int32_int32.get('') self.assertIsNone(msg.map_int32_foreign_message.get(5)) self.assertEqual(10, msg.map_int32_foreign_message.get(5, 10)) + self.assertEqual(10, msg.map_int32_foreign_message.get(key=5, default=10)) submsg = msg.map_int32_foreign_message[5] self.assertIs(submsg, msg.map_int32_foreign_message.get(5)) + with self.assertRaises(TypeError): + msg.map_int32_foreign_message.get('') def testScalarMap(self): msg = map_unittest_pb2.TestMap() @@ -1396,8 +1846,13 @@ def testScalarMap(self): msg.map_int64_int64[-2**33] = -2**34 msg.map_uint32_uint32[123] = 456 msg.map_uint64_uint64[2**33] = 2**34 + msg.map_int32_float[2] = 1.2 + msg.map_int32_double[1] = 3.3 msg.map_string_string['abc'] = '123' + msg.map_bool_bool[True] = True msg.map_int32_enum[888] = 2 + # Unknown numeric enum is supported in proto3. + msg.map_int32_enum[123] = 456 self.assertEqual([], msg.FindInitializationErrors()) @@ -1431,8 +1886,22 @@ def testScalarMap(self): self.assertEqual(-2**34, msg2.map_int64_int64[-2**33]) self.assertEqual(456, msg2.map_uint32_uint32[123]) self.assertEqual(2**34, msg2.map_uint64_uint64[2**33]) + self.assertAlmostEqual(1.2, msg.map_int32_float[2]) + self.assertEqual(3.3, msg.map_int32_double[1]) self.assertEqual('123', msg2.map_string_string['abc']) + self.assertEqual(True, msg2.map_bool_bool[True]) self.assertEqual(2, msg2.map_int32_enum[888]) + self.assertEqual(456, msg2.map_int32_enum[123]) + self.assertEqual('{-123: -456}', + str(msg2.map_int32_int32)) + + def testMapEntryAlwaysSerialized(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[0] = 0 + msg.map_string_string[''] = '' + self.assertEqual(msg.ByteSize(), 12) + self.assertEqual(b'\n\x04\x08\x00\x10\x00r\x04\n\x00\x12\x00', + msg.SerializeToString()) def testStringUnicodeConversionInMap(self): msg = map_unittest_pb2.TestMap() @@ -1485,6 +1954,10 @@ def testMessageMap(self): self.assertIn(123, msg2.map_int32_foreign_message) self.assertIn(-456, msg2.map_int32_foreign_message) self.assertEqual(2, len(msg2.map_int32_foreign_message)) + msg2.map_int32_foreign_message[123].c = 1 + # TODO(jieluo): Fix text format for message map. + self.assertIn(str(msg2.map_int32_foreign_message), + ('{-456: , 123: c: 1\n}', '{123: c: 1\n, -456: }')) def testNestedMessageMapItemDelete(self): msg = map_unittest_pb2.TestMap() @@ -1531,6 +2004,13 @@ def testMergeFrom(self): old_map_value = msg2.map_int32_foreign_message[222] msg2.MergeFrom(msg) + # Compare with expected message instead of call + # msg2.map_int32_foreign_message[222] to make sure MergeFrom does not + # sync with repeated field and there is no duplicated keys. + expected_msg = map_unittest_pb2.TestMap() + expected_msg.CopyFrom(msg) + expected_msg.map_int64_int64[88] = 99 + self.assertEqual(msg2, expected_msg) self.assertEqual(34, msg2.map_int32_int32[12]) self.assertEqual(78, msg2.map_int32_int32[56]) @@ -1568,6 +2048,69 @@ def testMergeFrom(self): del msg2.map_int32_foreign_message[222] self.assertFalse(222 in msg2.map_int32_foreign_message) + with self.assertRaises(TypeError): + del msg2.map_int32_foreign_message[''] + + def testMapMergeFrom(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[12] = 34 + msg.map_int32_int32[56] = 78 + msg.map_int64_int64[22] = 33 + msg.map_int32_foreign_message[111].c = 5 + msg.map_int32_foreign_message[222].c = 10 + + msg2 = map_unittest_pb2.TestMap() + msg2.map_int32_int32[12] = 55 + msg2.map_int64_int64[88] = 99 + msg2.map_int32_foreign_message[222].c = 15 + msg2.map_int32_foreign_message[222].d = 20 + + msg2.map_int32_int32.MergeFrom(msg.map_int32_int32) + self.assertEqual(34, msg2.map_int32_int32[12]) + self.assertEqual(78, msg2.map_int32_int32[56]) + + msg2.map_int64_int64.MergeFrom(msg.map_int64_int64) + self.assertEqual(33, msg2.map_int64_int64[22]) + self.assertEqual(99, msg2.map_int64_int64[88]) + + msg2.map_int32_foreign_message.MergeFrom(msg.map_int32_foreign_message) + # Compare with expected message instead of call + # msg.map_int32_foreign_message[222] to make sure MergeFrom does not + # sync with repeated field and no duplicated keys. + expected_msg = map_unittest_pb2.TestMap() + expected_msg.CopyFrom(msg) + expected_msg.map_int64_int64[88] = 99 + self.assertEqual(msg2, expected_msg) + + # Test when cpp extension cache a map. + m1 = map_unittest_pb2.TestMap() + m2 = map_unittest_pb2.TestMap() + self.assertEqual(m1.map_int32_foreign_message, + m1.map_int32_foreign_message) + m2.map_int32_foreign_message[123].c = 10 + m1.MergeFrom(m2) + self.assertEqual(10, m2.map_int32_foreign_message[123].c) + + # Test merge maps within different message types. + m1 = map_unittest_pb2.TestMap() + m2 = map_unittest_pb2.TestMessageMap() + m2.map_int32_message[123].optional_int32 = 10 + m1.map_int32_all_types.MergeFrom(m2.map_int32_message) + self.assertEqual(10, m1.map_int32_all_types[123].optional_int32) + + # Test overwrite message value map + msg = map_unittest_pb2.TestMap() + msg.map_int32_foreign_message[222].c = 123 + msg2 = map_unittest_pb2.TestMap() + msg2.map_int32_foreign_message[222].d = 20 + msg.MergeFromString(msg2.SerializeToString()) + self.assertEqual(msg.map_int32_foreign_message[222].d, 20) + self.assertNotEqual(msg.map_int32_foreign_message[222].c, 123) + + # Merge a dict to map field is not accepted + with self.assertRaises(AttributeError): + m1.map_int32_all_types.MergeFrom( + {1: unittest_proto3_arena_pb2.TestAllTypes()}) def testMergeFromBadType(self): msg = map_unittest_pb2.TestMap() @@ -1702,6 +2245,54 @@ def testMapIteration(self): matching_dict = {2: 4, 3: 6, 4: 8} self.assertMapIterEquals(msg.map_int32_int32.items(), matching_dict) + def testPython2Map(self): + if sys.version_info < (3,): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[2] = 4 + msg.map_int32_int32[3] = 6 + msg.map_int32_int32[4] = 8 + msg.map_int32_int32[5] = 10 + map_int32 = msg.map_int32_int32 + self.assertEqual(4, len(map_int32)) + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(msg.SerializeToString()) + + def CheckItems(seq, iterator): + self.assertEqual(next(iterator), seq[0]) + self.assertEqual(list(iterator), seq[1:]) + + CheckItems(map_int32.items(), map_int32.iteritems()) + CheckItems(map_int32.keys(), map_int32.iterkeys()) + CheckItems(map_int32.values(), map_int32.itervalues()) + + self.assertEqual(6, map_int32.get(3)) + self.assertEqual(None, map_int32.get(999)) + self.assertEqual(6, map_int32.pop(3)) + self.assertEqual(0, map_int32.pop(3)) + self.assertEqual(3, len(map_int32)) + key, value = map_int32.popitem() + self.assertEqual(2 * key, value) + self.assertEqual(2, len(map_int32)) + map_int32.clear() + self.assertEqual(0, len(map_int32)) + + with self.assertRaises(KeyError): + map_int32.popitem() + + self.assertEqual(0, map_int32.setdefault(2)) + self.assertEqual(1, len(map_int32)) + + map_int32.update(msg2.map_int32_int32) + self.assertEqual(4, len(map_int32)) + + with self.assertRaises(TypeError): + map_int32.update(msg2.map_int32_int32, + msg2.map_int32_int32) + with self.assertRaises(TypeError): + map_int32.update(0) + with self.assertRaises(TypeError): + map_int32.update(value=12) + def testMapItems(self): # Map items used to have strange behaviors when use c extension. Because # [] may reorder the map and invalidate any exsting iterators. @@ -1769,10 +2360,28 @@ def testMapConstruction(self): map_int32_foreign_message={3: unittest_pb2.ForeignMessage(c=5)}) self.assertEqual(5, msg.map_int32_foreign_message[3].c) + def testMapScalarFieldConstruction(self): + msg1 = map_unittest_pb2.TestMap() + msg1.map_int32_int32[1] = 42 + msg2 = map_unittest_pb2.TestMap(map_int32_int32=msg1.map_int32_int32) + self.assertEqual(42, msg2.map_int32_int32[1]) + + def testMapMessageFieldConstruction(self): + msg1 = map_unittest_pb2.TestMap() + msg1.map_string_foreign_message['test'].c = 42 + msg2 = map_unittest_pb2.TestMap( + map_string_foreign_message=msg1.map_string_foreign_message) + self.assertEqual(42, msg2.map_string_foreign_message['test'].c) + + def testMapFieldRaisesCorrectError(self): + # Should raise a TypeError when given a non-iterable. + with self.assertRaises(TypeError): + map_unittest_pb2.TestMap(map_string_foreign_message=1) + def testMapValidAfterFieldCleared(self): # Map needs to work even if field is cleared. # For the C++ implementation this tests the correctness of - # ScalarMapContainer::Release() + # MapContainer::Release() msg = map_unittest_pb2.TestMap() int32_map = msg.map_int32_int32 @@ -1788,7 +2397,7 @@ def testMapValidAfterFieldCleared(self): def testMessageMapValidAfterFieldCleared(self): # Map needs to work even if field is cleared. # For the C++ implementation this tests the correctness of - # ScalarMapContainer::Release() + # MapContainer::Release() msg = map_unittest_pb2.TestMap() int32_foreign_message = msg.map_int32_foreign_message @@ -1798,6 +2407,24 @@ def testMessageMapValidAfterFieldCleared(self): self.assertEqual(b'', msg.SerializeToString()) self.assertTrue(2 in int32_foreign_message.keys()) + def testMessageMapItemValidAfterTopMessageCleared(self): + # Message map item needs to work even if it is cleared. + # For the C++ implementation this tests the correctness of + # MapContainer::Release() + msg = map_unittest_pb2.TestMap() + msg.map_int32_all_types[2].optional_string = 'bar' + + if api_implementation.Type() == 'cpp': + # Need to keep the map reference because of b/27942626. + # TODO(jieluo): Remove it. + unused_map = msg.map_int32_all_types # pylint: disable=unused-variable + msg_value = msg.map_int32_all_types[2] + msg.Clear() + + # Reset to trigger sync between repeated field and map in c++. + msg.map_int32_all_types[3].optional_string = 'foo' + self.assertEqual(msg_value.optional_string, 'bar') + def testMapIterInvalidatedByClearField(self): # Map iterator is invalidated when field is cleared. # But this case does need to not crash the interpreter. @@ -1832,13 +2459,24 @@ def testMapDelete(self): del msg.map_int32_int32[4] self.assertEqual(0, len(msg.map_int32_int32)) + with self.assertRaises(KeyError): + del msg.map_int32_all_types[32] + def testMapsAreMapping(self): msg = map_unittest_pb2.TestMap() - self.assertIsInstance(msg.map_int32_int32, collections.Mapping) - self.assertIsInstance(msg.map_int32_int32, collections.MutableMapping) - self.assertIsInstance(msg.map_int32_foreign_message, collections.Mapping) + self.assertIsInstance(msg.map_int32_int32, collections_abc.Mapping) + self.assertIsInstance(msg.map_int32_int32, collections_abc.MutableMapping) + self.assertIsInstance(msg.map_int32_foreign_message, collections_abc.Mapping) self.assertIsInstance(msg.map_int32_foreign_message, - collections.MutableMapping) + collections_abc.MutableMapping) + + def testMapsCompare(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[-123] = -456 + self.assertEqual(msg.map_int32_int32, msg.map_int32_int32) + self.assertEqual(msg.map_int32_foreign_message, + msg.map_int32_foreign_message) + self.assertNotEqual(msg.map_int32_int32, 0) def testMapFindInitializationErrorsSmokeTest(self): msg = map_unittest_pb2.TestMap() @@ -1847,9 +2485,86 @@ def testMapFindInitializationErrorsSmokeTest(self): msg.map_string_foreign_message['foo'].c = 5 self.assertEqual(0, len(msg.FindInitializationErrors())) + @unittest.skipIf(sys.maxunicode == UCS2_MAXUNICODE, 'Skip for ucs2') + def testStrictUtf8Check(self): + # Test u'\ud801' is rejected at parser in both python2 and python3. + serialized = (b'r\x03\xed\xa0\x81') + msg = unittest_proto3_arena_pb2.TestAllTypes() + with self.assertRaises(Exception) as context: + msg.MergeFromString(serialized) + if api_implementation.Type() == 'python': + self.assertIn('optional_string', str(context.exception)) + else: + self.assertIn('Error parsing message', str(context.exception)) + + # Test optional_string=u'😍' is accepted. + serialized = unittest_proto3_arena_pb2.TestAllTypes( + optional_string=u'😍').SerializeToString() + msg2 = unittest_proto3_arena_pb2.TestAllTypes() + msg2.MergeFromString(serialized) + self.assertEqual(msg2.optional_string, u'😍') + + msg = unittest_proto3_arena_pb2.TestAllTypes( + optional_string=u'\ud001') + self.assertEqual(msg.optional_string, u'\ud001') + + @unittest.skipIf(six.PY2, 'Surrogates are acceptable in python2') + def testSurrogatesInPython3(self): + # Surrogates like U+D83D is an invalid unicode character, it is + # supported by Python2 only because in some builds, unicode strings + # use 2-bytes code units. Since Python 3.3, we don't have this problem. + # + # Surrogates are utf16 code units, in a unicode string they are invalid + # characters even when they appear in pairs like u'\ud801\udc01'. Protobuf + # Python3 reject such cases at setters and parsers. Python2 accpect it + # to keep same features with the language itself. 'Unpaired pairs' + # like u'\ud801' are rejected at parsers when strict utf8 check is enabled + # in proto3 to keep same behavior with c extension. + + # Surrogates are rejected at setters in Python3. + with self.assertRaises(ValueError): + unittest_proto3_arena_pb2.TestAllTypes( + optional_string=u'\ud801\udc01') + with self.assertRaises(ValueError): + unittest_proto3_arena_pb2.TestAllTypes( + optional_string=b'\xed\xa0\x81') + with self.assertRaises(ValueError): + unittest_proto3_arena_pb2.TestAllTypes( + optional_string=u'\ud801') + with self.assertRaises(ValueError): + unittest_proto3_arena_pb2.TestAllTypes( + optional_string=u'\ud801\ud801') + + @unittest.skipIf(six.PY3 or sys.maxunicode == UCS2_MAXUNICODE, + 'Surrogates are rejected at setters in Python3') + def testSurrogatesInPython2(self): + # Test optional_string=u'\ud801\udc01'. + # surrogate pair is acceptable in python2. + msg = unittest_proto3_arena_pb2.TestAllTypes( + optional_string=u'\ud801\udc01') + # TODO(jieluo): Change pure python to have same behavior with c extension. + # Some build in python2 consider u'\ud801\udc01' and u'\U00010401' are + # equal, some are not equal. + if api_implementation.Type() == 'python': + self.assertEqual(msg.optional_string, u'\ud801\udc01') + else: + self.assertEqual(msg.optional_string, u'\U00010401') + serialized = msg.SerializeToString() + msg2 = unittest_proto3_arena_pb2.TestAllTypes() + msg2.MergeFromString(serialized) + self.assertEqual(msg2.optional_string, u'\U00010401') + + # Python2 does not reject surrogates at setters. + msg = unittest_proto3_arena_pb2.TestAllTypes( + optional_string=b'\xed\xa0\x81') + unittest_proto3_arena_pb2.TestAllTypes( + optional_string=u'\ud801') + unittest_proto3_arena_pb2.TestAllTypes( + optional_string=u'\ud801\ud801') -class ValidTypeNamesTest(BaseTestCase): +@testing_refleaks.TestCase +class ValidTypeNamesTest(unittest.TestCase): def assertImportFromName(self, msg, base_name): # Parse to extra 'some.name' as a string. @@ -1870,7 +2585,8 @@ def testTypeNamesCanBeImported(self): self.assertImportFromName(pb.repeated_int32, 'Scalar') self.assertImportFromName(pb.repeated_nested_message, 'Composite') -class PackedFieldTest(BaseTestCase): +@testing_refleaks.TestCase +class PackedFieldTest(unittest.TestCase): def setMessage(self, message): message.repeated_int32.append(1) @@ -1927,9 +2643,11 @@ def testUnpackedFields(self): self.assertEqual(golden_data, message.SerializeToString()) -@unittest.skipIf(api_implementation.Type() != 'cpp', - 'explicit tests of the C++ implementation') -class OversizeProtosTest(BaseTestCase): +@unittest.skipIf(api_implementation.Type() != 'cpp' or + sys.version_info < (2, 7), + 'explicit tests of the C++ implementation for PY27 and above') +@testing_refleaks.TestCase +class OversizeProtosTest(unittest.TestCase): @classmethod def setUpClass(cls): diff --git a/python/google/protobuf/internal/missing_enum_values.proto b/python/google/protobuf/internal/missing_enum_values.proto index 1850be5bb7fdb..5c0f499dba069 100644 --- a/python/google/protobuf/internal/missing_enum_values.proto +++ b/python/google/protobuf/internal/missing_enum_values.proto @@ -30,6 +30,7 @@ syntax = "proto2"; + package google.protobuf.python.internal; message TestEnumValues { diff --git a/python/google/protobuf/internal/more_extensions.proto b/python/google/protobuf/internal/more_extensions.proto index 78f1467361c4c..5038fd244789e 100644 --- a/python/google/protobuf/internal/more_extensions.proto +++ b/python/google/protobuf/internal/more_extensions.proto @@ -41,7 +41,9 @@ message TopLevelMessage { message ExtendedMessage { - extensions 1 to max; + optional int32 optional_int32 = 1001; + repeated string repeated_string = 1002; + extensions 1 to 999; } diff --git a/python/google/protobuf/internal/more_messages.proto b/python/google/protobuf/internal/more_messages.proto index 2c6ab9efdfc22..c5889c481ff95 100644 --- a/python/google/protobuf/internal/more_messages.proto +++ b/python/google/protobuf/internal/more_messages.proto @@ -30,6 +30,8 @@ // Author: robinson@google.com (Will Robinson) +// LINT: LEGACY_NAMES + syntax = "proto2"; package google.protobuf.internal; @@ -50,3 +52,309 @@ extend OutOfOrderFields { optional uint64 optional_uint64 = 4; optional int64 optional_int64 = 2; } + +enum is { // top level enum keyword + default = 0; + else = 1; // top level enum value keyword +} + +message class { // message keyword + optional int32 int_field = 1; + optional int32 if = 2; // field keyword + optional is as = 3; // enum field keyword + optional is enum_field = 4; + enum for { // nested enum keyword + default = 0; + True = 1; // nested enum value keyword + } + optional for nested_enum_field = 5; + message try { + optional int32 field = 1; + extensions 999 to 9999; + } + optional try nested_message = 6; + extensions 999 to 9999; +} + +extend class { + optional int32 continue = 1001; // top level extension keyword +} + +extend class.try { + optional int32 with = 1001; +} + +message ExtendClass { + extend class { + optional int32 return = 1002; // nested extension keyword + } +} + +message TestFullKeyword { + optional google.protobuf.internal.OutOfOrderFields field1 = 1; + optional google.protobuf.internal.class field2 = 2; +} + +// TODO(jieluo): Add keyword support for service. +// service False { +// rpc Bar(class) returns (class); +// } + +message LotsNestedMessage { + message B0 {} + message B1 {} + message B2 {} + message B3 {} + message B4 {} + message B5 {} + message B6 {} + message B7 {} + message B8 {} + message B9 {} + message B10 {} + message B11 {} + message B12 {} + message B13 {} + message B14 {} + message B15 {} + message B16 {} + message B17 {} + message B18 {} + message B19 {} + message B20 {} + message B21 {} + message B22 {} + message B23 {} + message B24 {} + message B25 {} + message B26 {} + message B27 {} + message B28 {} + message B29 {} + message B30 {} + message B31 {} + message B32 {} + message B33 {} + message B34 {} + message B35 {} + message B36 {} + message B37 {} + message B38 {} + message B39 {} + message B40 {} + message B41 {} + message B42 {} + message B43 {} + message B44 {} + message B45 {} + message B46 {} + message B47 {} + message B48 {} + message B49 {} + message B50 {} + message B51 {} + message B52 {} + message B53 {} + message B54 {} + message B55 {} + message B56 {} + message B57 {} + message B58 {} + message B59 {} + message B60 {} + message B61 {} + message B62 {} + message B63 {} + message B64 {} + message B65 {} + message B66 {} + message B67 {} + message B68 {} + message B69 {} + message B70 {} + message B71 {} + message B72 {} + message B73 {} + message B74 {} + message B75 {} + message B76 {} + message B77 {} + message B78 {} + message B79 {} + message B80 {} + message B81 {} + message B82 {} + message B83 {} + message B84 {} + message B85 {} + message B86 {} + message B87 {} + message B88 {} + message B89 {} + message B90 {} + message B91 {} + message B92 {} + message B93 {} + message B94 {} + message B95 {} + message B96 {} + message B97 {} + message B98 {} + message B99 {} + message B100 {} + message B101 {} + message B102 {} + message B103 {} + message B104 {} + message B105 {} + message B106 {} + message B107 {} + message B108 {} + message B109 {} + message B110 {} + message B111 {} + message B112 {} + message B113 {} + message B114 {} + message B115 {} + message B116 {} + message B117 {} + message B118 {} + message B119 {} + message B120 {} + message B121 {} + message B122 {} + message B123 {} + message B124 {} + message B125 {} + message B126 {} + message B127 {} + message B128 {} + message B129 {} + message B130 {} + message B131 {} + message B132 {} + message B133 {} + message B134 {} + message B135 {} + message B136 {} + message B137 {} + message B138 {} + message B139 {} + message B140 {} + message B141 {} + message B142 {} + message B143 {} + message B144 {} + message B145 {} + message B146 {} + message B147 {} + message B148 {} + message B149 {} + message B150 {} + message B151 {} + message B152 {} + message B153 {} + message B154 {} + message B155 {} + message B156 {} + message B157 {} + message B158 {} + message B159 {} + message B160 {} + message B161 {} + message B162 {} + message B163 {} + message B164 {} + message B165 {} + message B166 {} + message B167 {} + message B168 {} + message B169 {} + message B170 {} + message B171 {} + message B172 {} + message B173 {} + message B174 {} + message B175 {} + message B176 {} + message B177 {} + message B178 {} + message B179 {} + message B180 {} + message B181 {} + message B182 {} + message B183 {} + message B184 {} + message B185 {} + message B186 {} + message B187 {} + message B188 {} + message B189 {} + message B190 {} + message B191 {} + message B192 {} + message B193 {} + message B194 {} + message B195 {} + message B196 {} + message B197 {} + message B198 {} + message B199 {} + message B200 {} + message B201 {} + message B202 {} + message B203 {} + message B204 {} + message B205 {} + message B206 {} + message B207 {} + message B208 {} + message B209 {} + message B210 {} + message B211 {} + message B212 {} + message B213 {} + message B214 {} + message B215 {} + message B216 {} + message B217 {} + message B218 {} + message B219 {} + message B220 {} + message B221 {} + message B222 {} + message B223 {} + message B224 {} + message B225 {} + message B226 {} + message B227 {} + message B228 {} + message B229 {} + message B230 {} + message B231 {} + message B232 {} + message B233 {} + message B234 {} + message B235 {} + message B236 {} + message B237 {} + message B238 {} + message B239 {} + message B240 {} + message B241 {} + message B242 {} + message B243 {} + message B244 {} + message B245 {} + message B246 {} + message B247 {} + message B248 {} + message B249 {} + message B250 {} + message B251 {} + message B252 {} + message B253 {} + message B254 {} + message B255 {} +} diff --git a/python/google/protobuf/internal/no_package.proto b/python/google/protobuf/internal/no_package.proto new file mode 100644 index 0000000000000..49eda95924255 --- /dev/null +++ b/python/google/protobuf/internal/no_package.proto @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +enum NoPackageEnum { + NO_PACKAGE_VALUE_0 = 0; + NO_PACKAGE_VALUE_1 = 1; +} + +message NoPackageMessage { + optional NoPackageEnum no_package_enum = 1; +} diff --git a/python/google/protobuf/internal/proto_builder_test.py b/python/google/protobuf/internal/proto_builder_test.py old mode 100644 new mode 100755 diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py old mode 100755 new mode 100644 index c363d8432432e..d1f4dcde8e5e6 --- a/python/google/protobuf/internal/python_message.py +++ b/python/google/protobuf/internal/python_message.py @@ -56,6 +56,7 @@ import weakref import six +from six.moves import range # We use "as" to avoid name collisions with variables. from google.protobuf.internal import api_implementation @@ -63,6 +64,7 @@ from google.protobuf.internal import decoder from google.protobuf.internal import encoder from google.protobuf.internal import enum_type_wrapper +from google.protobuf.internal import extension_dict from google.protobuf.internal import message_listener as message_listener_mod from google.protobuf.internal import type_checkers from google.protobuf.internal import well_known_types @@ -73,7 +75,7 @@ _FieldDescriptor = descriptor_mod.FieldDescriptor _AnyFullTypeName = 'google.protobuf.Any' - +_ExtensionDict = extension_dict._ExtensionDict class GeneratedProtocolMessageType(type): @@ -122,8 +124,30 @@ def __new__(cls, name, bases, dictionary): Returns: Newly-allocated class. + + Raises: + RuntimeError: Generated code only work with python cpp extension. """ descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY] + + if isinstance(descriptor, str): + raise RuntimeError('The generated code only work with python cpp ' + 'extension, but it is using pure python runtime.') + + # If a concrete class already exists for this descriptor, don't try to + # create another. Doing so will break any messages that already exist with + # the existing class. + # + # The C++ implementation appears to have its own internal `PyMessageFactory` + # to achieve similar results. + # + # This most commonly happens in `text_format.py` when using descriptors from + # a custom pool; it calls symbol_database.Global().getPrototype() on a + # descriptor which already has an existing concrete class. + new_class = getattr(descriptor, '_concrete_class', None) + if new_class: + return new_class + if descriptor.full_name in well_known_types.WKTBASES: bases += (well_known_types.WKTBASES[descriptor.full_name],) _AddClassAttributesForNestedExtensions(descriptor, dictionary) @@ -151,6 +175,16 @@ def __init__(cls, name, bases, dictionary): type. """ descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY] + + # If this is an _existing_ class looked up via `_concrete_class` in the + # __new__ method above, then we don't need to re-initialize anything. + existing_class = getattr(descriptor, '_concrete_class', None) + if existing_class: + assert existing_class is cls, ( + 'Duplicate `GeneratedProtocolMessageType` created for descriptor %r' + % (descriptor.full_name)) + return + cls._decoders_by_tag = {} if (descriptor.has_options and descriptor.GetOptions().message_set_wire_format): @@ -211,28 +245,6 @@ def _PropertyName(proto_field_name): return proto_field_name -def _VerifyExtensionHandle(message, extension_handle): - """Verify that the given extension handle is valid.""" - - if not isinstance(extension_handle, _FieldDescriptor): - raise KeyError('HasExtension() expects an extension handle, got: %s' % - extension_handle) - - if not extension_handle.is_extension: - raise KeyError('"%s" is not an extension.' % extension_handle.full_name) - - if not extension_handle.containing_type: - raise KeyError('"%s" is missing a containing_type.' - % extension_handle.full_name) - - if extension_handle.containing_type is not message.DESCRIPTOR: - raise KeyError('Extension "%s" extends message type "%s", but this ' - 'message is of type "%s".' % - (extension_handle.full_name, - extension_handle.containing_type.full_name, - message.DESCRIPTOR.full_name)) - - def _AddSlots(message_descriptor, dictionary): """Adds a __slots__ entry to dictionary, containing the names of all valid attributes for this message type. @@ -245,6 +257,7 @@ def _AddSlots(message_descriptor, dictionary): '_cached_byte_size_dirty', '_fields', '_unknown_fields', + '_unknown_field_set', '_is_present_in_parent', '_listener', '_listener_for_children', @@ -267,22 +280,30 @@ def _IsMapField(field): def _IsMessageMapField(field): - value_type = field.message_type.fields_by_name["value"] + value_type = field.message_type.fields_by_name['value'] return value_type.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE +def _IsStrictUtf8Check(field): + if field.containing_type.syntax != 'proto3': + return False + enforce_utf8 = True + return enforce_utf8 + + def _AttachFieldHelpers(cls, field_descriptor): is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED) is_packable = (is_repeated and wire_format.IsTypePackable(field_descriptor.type)) + is_proto3 = field_descriptor.containing_type.syntax == 'proto3' if not is_packable: is_packed = False - elif field_descriptor.containing_type.syntax == "proto2": + elif field_descriptor.containing_type.syntax == 'proto2': is_packed = (field_descriptor.has_options and field_descriptor.GetOptions().packed) else: has_packed_false = (field_descriptor.has_options and - field_descriptor.GetOptions().HasField("packed") and + field_descriptor.GetOptions().HasField('packed') and field_descriptor.GetOptions().packed == False) is_packed = not has_packed_false is_map_entry = _IsMapField(field_descriptor) @@ -313,8 +334,12 @@ def AddDecoder(wiretype, is_packed): decode_type = _FieldDescriptor.TYPE_INT32 oneof_descriptor = None + clear_if_default = False if field_descriptor.containing_oneof is not None: oneof_descriptor = field_descriptor + elif (is_proto3 and not is_repeated and + field_descriptor.cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE): + clear_if_default = True if is_map_entry: is_message_map = _IsMessageMapField(field_descriptor) @@ -322,10 +347,22 @@ def AddDecoder(wiretype, is_packed): field_decoder = decoder.MapDecoder( field_descriptor, _GetInitializeDefaultForMap(field_descriptor), is_message_map) + elif decode_type == _FieldDescriptor.TYPE_STRING: + is_strict_utf8_check = _IsStrictUtf8Check(field_descriptor) + field_decoder = decoder.StringDecoder( + field_descriptor.number, is_repeated, is_packed, + field_descriptor, field_descriptor._default_constructor, + is_strict_utf8_check, clear_if_default) + elif field_descriptor.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + field_decoder = type_checkers.TYPE_TO_DECODER[decode_type]( + field_descriptor.number, is_repeated, is_packed, + field_descriptor, field_descriptor._default_constructor) else: field_decoder = type_checkers.TYPE_TO_DECODER[decode_type]( - field_descriptor.number, is_repeated, is_packed, - field_descriptor, field_descriptor._default_constructor) + field_descriptor.number, is_repeated, is_packed, + # pylint: disable=protected-access + field_descriptor, field_descriptor._default_constructor, + clear_if_default) cls._decoders_by_tag[tag_bytes] = (field_decoder, oneof_descriptor) @@ -339,8 +376,8 @@ def AddDecoder(wiretype, is_packed): def _AddClassAttributesForNestedExtensions(descriptor, dictionary): - extension_dict = descriptor.extensions_by_name - for extension_name, extension_field in extension_dict.items(): + extensions = descriptor.extensions_by_name + for extension_name, extension_field in extensions.items(): assert extension_name not in dictionary dictionary[extension_name] = extension_field @@ -422,6 +459,9 @@ def MakeRepeatedScalarDefault(message): # _concrete_class may not yet be initialized. message_type = field.message_type def MakeSubMessageDefault(message): + assert getattr(message_type, '_concrete_class', None), ( + 'Uninitialized concrete class found for field %r (message type %r)' + % (field.full_name, message_type.full_name)) result = message_type._concrete_class() result._SetListener( _OneofListener(message, field) @@ -477,13 +517,16 @@ def init(self, **kwargs): # _unknown_fields is () when empty for efficiency, and will be turned into # a list if fields are added. self._unknown_fields = () + # _unknown_field_set is None when empty for efficiency, and will be + # turned into UnknownFieldSet struct if fields are added. + self._unknown_field_set = None # pylint: disable=protected-access self._is_present_in_parent = False self._listener = message_listener_mod.NullMessageListener() self._listener_for_children = _Listener(self) for field_name, field_value in kwargs.items(): field = _GetFieldByName(message_descriptor, field_name) if field is None: - raise TypeError("%s() got an unexpected keyword argument '%s'" % + raise TypeError('%s() got an unexpected keyword argument "%s"' % (message_descriptor.name, field_name)) if field_value is None: # field=None is the same as no field at all. @@ -573,7 +616,7 @@ def _AddPropertiesForField(field, cls): # handle specially here. assert _FieldDescriptor.MAX_CPPTYPE == 10 - constant_name = field.name.upper() + "_FIELD_NUMBER" + constant_name = field.name.upper() + '_FIELD_NUMBER' setattr(cls, constant_name, field.number) if field.label == _FieldDescriptor.LABEL_REPEATED: @@ -584,10 +627,18 @@ def _AddPropertiesForField(field, cls): _AddPropertiesForNonRepeatedScalarField(field, cls) +class _FieldProperty(property): + __slots__ = ('DESCRIPTOR',) + + def __init__(self, descriptor, getter, setter, doc): + property.__init__(self, getter, setter, doc=doc) + self.DESCRIPTOR = descriptor + + def _AddPropertiesForRepeatedField(field, cls): """Adds a public property for a "repeated" protocol message field. Clients can use this property to get the value of the field, which will be either a - _RepeatedScalarFieldContainer or _RepeatedCompositeFieldContainer (see + RepeatedScalarFieldContainer or RepeatedCompositeFieldContainer (see below). Note that when clients add values to these containers, we perform @@ -625,7 +676,7 @@ def setter(self, new_value): '"%s" in protocol message object.' % proto_field_name) doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name - setattr(cls, property_name, property(getter, setter, doc=doc)) + setattr(cls, property_name, _FieldProperty(field, getter, setter, doc=doc)) def _AddPropertiesForNonRepeatedScalarField(field, cls): @@ -643,8 +694,7 @@ def _AddPropertiesForNonRepeatedScalarField(field, cls): property_name = _PropertyName(proto_field_name) type_checker = type_checkers.GetTypeChecker(field) default_value = field.default_value - valid_values = set() - is_proto3 = field.containing_type.syntax == "proto3" + is_proto3 = field.containing_type.syntax == 'proto3' def getter(self): # TODO(protobuf-team): This may be broken since there may not be @@ -659,7 +709,11 @@ def field_setter(self, new_value): # pylint: disable=protected-access # Testing the value for truthiness captures all of the proto3 defaults # (0, 0.0, enum 0, and False). - new_value = type_checker.CheckValue(new_value) + try: + new_value = type_checker.CheckValue(new_value) + except TypeError as e: + raise TypeError( + 'Cannot set %s to %.1024r: %s' % (field.full_name, new_value, e)) if clear_when_set_to_default and not new_value: self._fields.pop(field, None) else: @@ -681,7 +735,7 @@ def setter(self, new_value): # Add a property to encapsulate the getter/setter. doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name - setattr(cls, property_name, property(getter, setter, doc=doc)) + setattr(cls, property_name, _FieldProperty(field, getter, setter, doc=doc)) def _AddPropertiesForNonRepeatedCompositeField(field, cls): @@ -725,14 +779,14 @@ def setter(self, new_value): # Add a property to encapsulate the getter. doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name - setattr(cls, property_name, property(getter, setter, doc=doc)) + setattr(cls, property_name, _FieldProperty(field, getter, setter, doc=doc)) def _AddPropertiesForExtensions(descriptor, cls): """Adds properties for all fields in this protocol message type.""" - extension_dict = descriptor.extensions_by_name - for extension_name, extension_field in extension_dict.items(): - constant_name = extension_name.upper() + "_FIELD_NUMBER" + extensions = descriptor.extensions_by_name + for extension_name, extension_field in extensions.items(): + constant_name = extension_name.upper() + '_FIELD_NUMBER' setattr(cls, constant_name, extension_field.number) # TODO(amauryfa): Migrate all users of these attributes to functions like @@ -748,7 +802,8 @@ def _AddStaticMethods(cls): def RegisterExtension(extension_handle): extension_handle.containing_type = cls.DESCRIPTOR # TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available. - cls.DESCRIPTOR.file.pool.AddExtensionDescriptor(extension_handle) + # pylint: disable=protected-access + cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle) _AttachFieldHelpers(cls, extension_handle) cls.RegisterExtension = staticmethod(RegisterExtension) @@ -781,14 +836,16 @@ def ListFields(self): cls.ListFields = ListFields -_Proto3HasError = 'Protocol message has no non-repeated submessage field "%s"' -_Proto2HasError = 'Protocol message has no non-repeated field "%s"' +_PROTO3_ERROR_TEMPLATE = \ + ('Protocol message %s has no non-repeated submessage field "%s" ' + 'nor marked as optional') +_PROTO2_ERROR_TEMPLATE = 'Protocol message %s has no non-repeated field "%s"' def _AddHasFieldMethod(message_descriptor, cls): """Helper for _AddMessageMethods().""" is_proto3 = (message_descriptor.syntax == "proto3") - error_msg = _Proto3HasError if is_proto3 else _Proto2HasError + error_msg = _PROTO3_ERROR_TEMPLATE if is_proto3 else _PROTO2_ERROR_TEMPLATE hassable_fields = {} for field in message_descriptor.fields: @@ -800,16 +857,15 @@ def _AddHasFieldMethod(message_descriptor, cls): continue hassable_fields[field.name] = field - if not is_proto3: - # Fields inside oneofs are never repeated (enforced by the compiler). - for oneof in message_descriptor.oneofs: - hassable_fields[oneof.name] = oneof + # Has methods are supported for oneof descriptors. + for oneof in message_descriptor.oneofs: + hassable_fields[oneof.name] = oneof def HasField(self, field_name): try: field = hassable_fields[field_name] except KeyError: - raise ValueError(error_msg % field_name) + raise ValueError(error_msg % (message_descriptor.full_name, field_name)) if isinstance(field, descriptor_mod.OneofDescriptor): try: @@ -839,7 +895,7 @@ def ClearField(self, field_name): else: return except KeyError: - raise ValueError('Protocol message %s() has no "%s" field.' % + raise ValueError('Protocol message %s has no "%s" field.' % (message_descriptor.name, field_name)) if field in self._fields: @@ -867,7 +923,7 @@ def ClearField(self, field_name): def _AddClearExtensionMethod(cls): """Helper for _AddMessageMethods().""" def ClearExtension(self, extension_handle): - _VerifyExtensionHandle(self, extension_handle) + extension_dict._VerifyExtensionHandle(self, extension_handle) # Similar to ClearField(), above. if extension_handle in self._fields: @@ -879,7 +935,7 @@ def ClearExtension(self, extension_handle): def _AddHasExtensionMethod(cls): """Helper for _AddMessageMethods().""" def HasExtension(self, extension_handle): - _VerifyExtensionHandle(self, extension_handle) + extension_dict._VerifyExtensionHandle(self, extension_handle) if extension_handle.label == _FieldDescriptor.LABEL_REPEATED: raise KeyError('"%s" is repeated.' % extension_handle.full_name) @@ -949,12 +1005,12 @@ def __eq__(self, other): if not self.ListFields() == other.ListFields(): return False - # Sort unknown fields because their order shouldn't affect equality test. + # TODO(jieluo): Fix UnknownFieldSet to consider MessageSet extensions, + # then use it for the comparison. unknown_fields = list(self._unknown_fields) unknown_fields.sort() other_unknown_fields = list(other._unknown_fields) other_unknown_fields.sort() - return unknown_fields == other_unknown_fields cls.__eq__ = __eq__ @@ -1010,11 +1066,16 @@ def ByteSize(self): return self._cached_byte_size size = 0 - for field_descriptor, field_value in self.ListFields(): - size += field_descriptor._sizer(field_value) - - for tag_bytes, value_bytes in self._unknown_fields: - size += len(tag_bytes) + len(value_bytes) + descriptor = self.DESCRIPTOR + if descriptor.GetOptions().map_entry: + # Fields of map entry should always be serialized. + size = descriptor.fields_by_name['key']._sizer(self.key) + size += descriptor.fields_by_name['value']._sizer(self.value) + else: + for field_descriptor, field_value in self.ListFields(): + size += field_descriptor._sizer(field_value) + for tag_bytes, value_bytes in self._unknown_fields: + size += len(tag_bytes) + len(value_bytes) self._cached_byte_size = size self._cached_byte_size_dirty = False @@ -1029,7 +1090,6 @@ def _AddSerializeToStringMethod(message_descriptor, cls): def SerializeToString(self, **kwargs): # Check if the message has all of its required fields set. - errors = [] if not self.IsInitialized(): raise message_mod.EncodeError( 'Message %s is missing required fields: %s' % ( @@ -1053,17 +1113,33 @@ def InternalSerialize(self, write_bytes, deterministic=None): api_implementation.IsPythonDefaultSerializationDeterministic()) else: deterministic = bool(deterministic) - for field_descriptor, field_value in self.ListFields(): - field_descriptor._encoder(write_bytes, field_value, deterministic) - for tag_bytes, value_bytes in self._unknown_fields: - write_bytes(tag_bytes) - write_bytes(value_bytes) + + descriptor = self.DESCRIPTOR + if descriptor.GetOptions().map_entry: + # Fields of map entry should always be serialized. + descriptor.fields_by_name['key']._encoder( + write_bytes, self.key, deterministic) + descriptor.fields_by_name['value']._encoder( + write_bytes, self.value, deterministic) + else: + for field_descriptor, field_value in self.ListFields(): + field_descriptor._encoder(write_bytes, field_value, deterministic) + for tag_bytes, value_bytes in self._unknown_fields: + write_bytes(tag_bytes) + write_bytes(value_bytes) cls._InternalSerialize = InternalSerialize def _AddMergeFromStringMethod(message_descriptor, cls): """Helper for _AddMessageMethods().""" def MergeFromString(self, serialized): + if isinstance(serialized, memoryview) and six.PY2: + raise TypeError( + 'memoryview not supported in Python 2 with the pure Python proto ' + 'implementation: this is to maintain compatibility with the C++ ' + 'implementation') + + serialized = memoryview(serialized) length = len(serialized) try: if self._InternalParse(serialized, 0, length) != length: @@ -1081,25 +1157,56 @@ def MergeFromString(self, serialized): local_ReadTag = decoder.ReadTag local_SkipField = decoder.SkipField decoders_by_tag = cls._decoders_by_tag - is_proto3 = message_descriptor.syntax == "proto3" def InternalParse(self, buffer, pos, end): + """Create a message from serialized bytes. + + Args: + self: Message, instance of the proto message object. + buffer: memoryview of the serialized data. + pos: int, position to start in the serialized data. + end: int, end position of the serialized data. + + Returns: + Message object. + """ + # Guard against internal misuse, since this function is called internally + # quite extensively, and its easy to accidentally pass bytes. + assert isinstance(buffer, memoryview) self._Modified() field_dict = self._fields - unknown_field_list = self._unknown_fields + # pylint: disable=protected-access + unknown_field_set = self._unknown_field_set while pos != end: (tag_bytes, new_pos) = local_ReadTag(buffer, pos) field_decoder, field_desc = decoders_by_tag.get(tag_bytes, (None, None)) if field_decoder is None: - value_start_pos = new_pos - new_pos = local_SkipField(buffer, new_pos, end, tag_bytes) + if not self._unknown_fields: # pylint: disable=protected-access + self._unknown_fields = [] # pylint: disable=protected-access + if unknown_field_set is None: + # pylint: disable=protected-access + self._unknown_field_set = containers.UnknownFieldSet() + # pylint: disable=protected-access + unknown_field_set = self._unknown_field_set + # pylint: disable=protected-access + (tag, _) = decoder._DecodeVarint(tag_bytes, 0) + field_number, wire_type = wire_format.UnpackTag(tag) + if field_number == 0: + raise message_mod.DecodeError('Field number 0 is illegal.') + # TODO(jieluo): remove old_pos. + old_pos = new_pos + (data, new_pos) = decoder._DecodeUnknownField( + buffer, new_pos, wire_type) # pylint: disable=protected-access + if new_pos == -1: + return pos + # pylint: disable=protected-access + unknown_field_set._add(field_number, wire_type, data) + # TODO(jieluo): remove _unknown_fields. + new_pos = local_SkipField(buffer, old_pos, end, tag_bytes) if new_pos == -1: return pos - if not is_proto3: - if not unknown_field_list: - unknown_field_list = self._unknown_fields = [] - unknown_field_list.append( - (tag_bytes, buffer[value_start_pos:new_pos])) + self._unknown_fields.append( + (tag_bytes, buffer[old_pos:new_pos].tobytes())) pos = new_pos else: pos = field_decoder(buffer, new_pos, end, self, field_dict) @@ -1174,7 +1281,7 @@ def FindInitializationErrors(self): for field, value in self.ListFields(): if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: if field.is_extension: - name = "(%s)" % field.full_name + name = '(%s)' % field.full_name else: name = field.name @@ -1182,7 +1289,7 @@ def FindInitializationErrors(self): if _IsMessageMapField(field): for key in value: element = value[key] - prefix = "%s[%s]." % (name, key) + prefix = '%s[%s].' % (name, key) sub_errors = element.FindInitializationErrors() errors += [prefix + error for error in sub_errors] else: @@ -1191,11 +1298,11 @@ def FindInitializationErrors(self): elif field.label == _FieldDescriptor.LABEL_REPEATED: for i in range(len(value)): element = value[i] - prefix = "%s[%d]." % (name, i) + prefix = '%s[%d].' % (name, i) sub_errors = element.FindInitializationErrors() errors += [prefix + error for error in sub_errors] else: - prefix = name + "." + prefix = name + '.' sub_errors = value.FindInitializationErrors() errors += [prefix + error for error in sub_errors] @@ -1211,7 +1318,7 @@ def _AddMergeFromMethod(cls): def MergeFrom(self, msg): if not isinstance(msg, cls): raise TypeError( - "Parameter to MergeFrom() must be instance of same class: " + 'Parameter to MergeFrom() must be instance of same class: ' 'expected %s got %s.' % (cls.__name__, msg.__class__.__name__)) assert msg is not self @@ -1244,6 +1351,10 @@ def MergeFrom(self, msg): if not self._unknown_fields: self._unknown_fields = [] self._unknown_fields.extend(msg._unknown_fields) + # pylint: disable=protected-access + if self._unknown_field_set is None: + self._unknown_field_set = containers.UnknownFieldSet() + self._unknown_field_set._extend(msg._unknown_field_set) cls.MergeFrom = MergeFrom @@ -1266,25 +1377,36 @@ def WhichOneof(self, oneof_name): cls.WhichOneof = WhichOneof -def _AddReduceMethod(cls): - def __reduce__(self): # pylint: disable=invalid-name - return (type(self), (), self.__getstate__()) - cls.__reduce__ = __reduce__ - - def _Clear(self): # Clear fields. self._fields = {} self._unknown_fields = () + # pylint: disable=protected-access + if self._unknown_field_set is not None: + self._unknown_field_set._clear() + self._unknown_field_set = None + self._oneofs = {} self._Modified() +def _UnknownFields(self): + if self._unknown_field_set is None: # pylint: disable=protected-access + # pylint: disable=protected-access + self._unknown_field_set = containers.UnknownFieldSet() + return self._unknown_field_set # pylint: disable=protected-access + + def _DiscardUnknownFields(self): self._unknown_fields = [] + self._unknown_field_set = None # pylint: disable=protected-access for field, value in self.ListFields(): if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: - if field.label == _FieldDescriptor.LABEL_REPEATED: + if _IsMapField(field): + if _IsMessageMapField(field): + for key in value: + value[key].DiscardUnknownFields() + elif field.label == _FieldDescriptor.LABEL_REPEATED: for sub_message in value: sub_message.DiscardUnknownFields() else: @@ -1317,9 +1439,9 @@ def _AddMessageMethods(message_descriptor, cls): _AddIsInitializedMethod(message_descriptor, cls) _AddMergeFromMethod(cls) _AddWhichOneofMethod(message_descriptor, cls) - _AddReduceMethod(cls) # Adds methods which do not depend on cls. cls.Clear = _Clear + cls.UnknownFields = _UnknownFields cls.DiscardUnknownFields = _DiscardUnknownFields cls._SetListener = _SetListener @@ -1423,122 +1545,3 @@ def Modified(self): super(_OneofListener, self).Modified() except ReferenceError: pass - - -# TODO(robinson): Move elsewhere? This file is getting pretty ridiculous... -# TODO(robinson): Unify error handling of "unknown extension" crap. -# TODO(robinson): Support iteritems()-style iteration over all -# extensions with the "has" bits turned on? -class _ExtensionDict(object): - - """Dict-like container for supporting an indexable "Extensions" - field on proto instances. - - Note that in all cases we expect extension handles to be - FieldDescriptors. - """ - - def __init__(self, extended_message): - """extended_message: Message instance for which we are the Extensions dict. - """ - - self._extended_message = extended_message - - def __getitem__(self, extension_handle): - """Returns the current value of the given extension handle.""" - - _VerifyExtensionHandle(self._extended_message, extension_handle) - - result = self._extended_message._fields.get(extension_handle) - if result is not None: - return result - - if extension_handle.label == _FieldDescriptor.LABEL_REPEATED: - result = extension_handle._default_constructor(self._extended_message) - elif extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: - result = extension_handle.message_type._concrete_class() - try: - result._SetListener(self._extended_message._listener_for_children) - except ReferenceError: - pass - else: - # Singular scalar -- just return the default without inserting into the - # dict. - return extension_handle.default_value - - # Atomically check if another thread has preempted us and, if not, swap - # in the new object we just created. If someone has preempted us, we - # take that object and discard ours. - # WARNING: We are relying on setdefault() being atomic. This is true - # in CPython but we haven't investigated others. This warning appears - # in several other locations in this file. - result = self._extended_message._fields.setdefault( - extension_handle, result) - - return result - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return False - - my_fields = self._extended_message.ListFields() - other_fields = other._extended_message.ListFields() - - # Get rid of non-extension fields. - my_fields = [ field for field in my_fields if field.is_extension ] - other_fields = [ field for field in other_fields if field.is_extension ] - - return my_fields == other_fields - - def __ne__(self, other): - return not self == other - - def __hash__(self): - raise TypeError('unhashable object') - - # Note that this is only meaningful for non-repeated, scalar extension - # fields. Note also that we may have to call _Modified() when we do - # successfully set a field this way, to set any necssary "has" bits in the - # ancestors of the extended message. - def __setitem__(self, extension_handle, value): - """If extension_handle specifies a non-repeated, scalar extension - field, sets the value of that field. - """ - - _VerifyExtensionHandle(self._extended_message, extension_handle) - - if (extension_handle.label == _FieldDescriptor.LABEL_REPEATED or - extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE): - raise TypeError( - 'Cannot assign to extension "%s" because it is a repeated or ' - 'composite type.' % extension_handle.full_name) - - # It's slightly wasteful to lookup the type checker each time, - # but we expect this to be a vanishingly uncommon case anyway. - type_checker = type_checkers.GetTypeChecker(extension_handle) - # pylint: disable=protected-access - self._extended_message._fields[extension_handle] = ( - type_checker.CheckValue(value)) - self._extended_message._Modified() - - def _FindExtensionByName(self, name): - """Tries to find a known extension with the specified name. - - Args: - name: Extension full name. - - Returns: - Extension field descriptor. - """ - return self._extended_message._extensions_by_name.get(name, None) - - def _FindExtensionByNumber(self, number): - """Tries to find a known extension with the field number. - - Args: - number: Extension field number. - - Returns: - Extension field descriptor. - """ - return self._extended_message._extensions_by_number.get(number, None) diff --git a/python/google/protobuf/internal/python_protobuf.cc b/python/google/protobuf/internal/python_protobuf.cc index f90cc4387efdd..e823bf228ca23 100644 --- a/python/google/protobuf/internal/python_protobuf.cc +++ b/python/google/protobuf/internal/python_protobuf.cc @@ -36,12 +36,8 @@ namespace google { namespace protobuf { namespace python { -static const Message* GetCProtoInsidePyProtoStub(PyObject* msg) { - return NULL; -} -static Message* MutableCProtoInsidePyProtoStub(PyObject* msg) { - return NULL; -} +static const Message* GetCProtoInsidePyProtoStub(PyObject* msg) { return NULL; } +static Message* MutableCProtoInsidePyProtoStub(PyObject* msg) { return NULL; } // This is initialized with a default, stub implementation. // If python-google.protobuf.cc is loaded, the function pointer is overridden diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py index 55b0d72e1e2d9..2b9ed1cb5a44c 100755 --- a/python/google/protobuf/internal/reflection_test.py +++ b/python/google/protobuf/internal/reflection_test.py @@ -40,6 +40,7 @@ import operator import six import struct +import warnings try: import unittest2 as unittest #PY26 @@ -49,6 +50,7 @@ from google.protobuf import unittest_import_pb2 from google.protobuf import unittest_mset_pb2 from google.protobuf import unittest_pb2 +from google.protobuf import unittest_proto3_arena_pb2 from google.protobuf import descriptor_pb2 from google.protobuf import descriptor from google.protobuf import message @@ -62,9 +64,14 @@ from google.protobuf.internal import test_util from google.protobuf.internal import testing_refleaks from google.protobuf.internal import decoder +from google.protobuf.internal import _parameterized -BaseTestCase = testing_refleaks.BaseTestCase +if six.PY3: + long = int # pylint: disable=redefined-builtin,invalid-name + + +warnings.simplefilter('error', DeprecationWarning) class _MiniDecoder(object): @@ -112,16 +119,20 @@ def EndOfStream(self): return self._pos == len(self._bytes) -class ReflectionTest(BaseTestCase): +@_parameterized.named_parameters( + ('_proto2', unittest_pb2), + ('_proto3', unittest_proto3_arena_pb2)) +@testing_refleaks.TestCase +class ReflectionTest(unittest.TestCase): def assertListsEqual(self, values, others): self.assertEqual(len(values), len(others)) for i in range(len(values)): self.assertEqual(values[i], others[i]) - def testScalarConstructor(self): + def testScalarConstructor(self, message_module): # Constructor with only scalar types should succeed. - proto = unittest_pb2.TestAllTypes( + proto = message_module.TestAllTypes( optional_int32=24, optional_double=54.321, optional_string='optional_string', @@ -130,11 +141,12 @@ def testScalarConstructor(self): self.assertEqual(24, proto.optional_int32) self.assertEqual(54.321, proto.optional_double) self.assertEqual('optional_string', proto.optional_string) - self.assertFalse(proto.HasField("optional_float")) + if message_module is unittest_pb2: + self.assertFalse(proto.HasField("optional_float")) - def testRepeatedScalarConstructor(self): + def testRepeatedScalarConstructor(self, message_module): # Constructor with only repeated scalar types should succeed. - proto = unittest_pb2.TestAllTypes( + proto = message_module.TestAllTypes( repeated_int32=[1, 2, 3, 4], repeated_double=[1.23, 54.321], repeated_bool=[True, False, False], @@ -147,56 +159,22 @@ def testRepeatedScalarConstructor(self): self.assertEqual(["optional_string"], list(proto.repeated_string)) self.assertEqual([], list(proto.repeated_float)) - def testRepeatedCompositeConstructor(self): - # Constructor with only repeated composite types should succeed. - proto = unittest_pb2.TestAllTypes( - repeated_nested_message=[ - unittest_pb2.TestAllTypes.NestedMessage( - bb=unittest_pb2.TestAllTypes.FOO), - unittest_pb2.TestAllTypes.NestedMessage( - bb=unittest_pb2.TestAllTypes.BAR)], - repeated_foreign_message=[ - unittest_pb2.ForeignMessage(c=-43), - unittest_pb2.ForeignMessage(c=45324), - unittest_pb2.ForeignMessage(c=12)], - repeatedgroup=[ - unittest_pb2.TestAllTypes.RepeatedGroup(), - unittest_pb2.TestAllTypes.RepeatedGroup(a=1), - unittest_pb2.TestAllTypes.RepeatedGroup(a=2)]) - - self.assertEqual( - [unittest_pb2.TestAllTypes.NestedMessage( - bb=unittest_pb2.TestAllTypes.FOO), - unittest_pb2.TestAllTypes.NestedMessage( - bb=unittest_pb2.TestAllTypes.BAR)], - list(proto.repeated_nested_message)) - self.assertEqual( - [unittest_pb2.ForeignMessage(c=-43), - unittest_pb2.ForeignMessage(c=45324), - unittest_pb2.ForeignMessage(c=12)], - list(proto.repeated_foreign_message)) - self.assertEqual( - [unittest_pb2.TestAllTypes.RepeatedGroup(), - unittest_pb2.TestAllTypes.RepeatedGroup(a=1), - unittest_pb2.TestAllTypes.RepeatedGroup(a=2)], - list(proto.repeatedgroup)) - - def testMixedConstructor(self): + def testMixedConstructor(self, message_module): # Constructor with only mixed types should succeed. - proto = unittest_pb2.TestAllTypes( + proto = message_module.TestAllTypes( optional_int32=24, optional_string='optional_string', repeated_double=[1.23, 54.321], repeated_bool=[True, False, False], repeated_nested_message=[ - unittest_pb2.TestAllTypes.NestedMessage( - bb=unittest_pb2.TestAllTypes.FOO), - unittest_pb2.TestAllTypes.NestedMessage( - bb=unittest_pb2.TestAllTypes.BAR)], + message_module.TestAllTypes.NestedMessage( + bb=message_module.TestAllTypes.FOO), + message_module.TestAllTypes.NestedMessage( + bb=message_module.TestAllTypes.BAR)], repeated_foreign_message=[ - unittest_pb2.ForeignMessage(c=-43), - unittest_pb2.ForeignMessage(c=45324), - unittest_pb2.ForeignMessage(c=12)], + message_module.ForeignMessage(c=-43), + message_module.ForeignMessage(c=45324), + message_module.ForeignMessage(c=12)], optional_nested_message=None) self.assertEqual(24, proto.optional_int32) @@ -204,168 +182,78 @@ def testMixedConstructor(self): self.assertEqual([1.23, 54.321], list(proto.repeated_double)) self.assertEqual([True, False, False], list(proto.repeated_bool)) self.assertEqual( - [unittest_pb2.TestAllTypes.NestedMessage( - bb=unittest_pb2.TestAllTypes.FOO), - unittest_pb2.TestAllTypes.NestedMessage( - bb=unittest_pb2.TestAllTypes.BAR)], + [message_module.TestAllTypes.NestedMessage( + bb=message_module.TestAllTypes.FOO), + message_module.TestAllTypes.NestedMessage( + bb=message_module.TestAllTypes.BAR)], list(proto.repeated_nested_message)) self.assertEqual( - [unittest_pb2.ForeignMessage(c=-43), - unittest_pb2.ForeignMessage(c=45324), - unittest_pb2.ForeignMessage(c=12)], + [message_module.ForeignMessage(c=-43), + message_module.ForeignMessage(c=45324), + message_module.ForeignMessage(c=12)], list(proto.repeated_foreign_message)) self.assertFalse(proto.HasField("optional_nested_message")) - def testConstructorTypeError(self): + def testConstructorTypeError(self, message_module): self.assertRaises( - TypeError, unittest_pb2.TestAllTypes, optional_int32="foo") + TypeError, message_module.TestAllTypes, optional_int32='foo') self.assertRaises( - TypeError, unittest_pb2.TestAllTypes, optional_string=1234) + TypeError, message_module.TestAllTypes, optional_string=1234) self.assertRaises( - TypeError, unittest_pb2.TestAllTypes, optional_nested_message=1234) + TypeError, message_module.TestAllTypes, optional_nested_message=1234) self.assertRaises( - TypeError, unittest_pb2.TestAllTypes, repeated_int32=1234) + TypeError, message_module.TestAllTypes, repeated_int32=1234) self.assertRaises( - TypeError, unittest_pb2.TestAllTypes, repeated_int32=["foo"]) + TypeError, message_module.TestAllTypes, repeated_int32=['foo']) self.assertRaises( - TypeError, unittest_pb2.TestAllTypes, repeated_string=1234) + TypeError, message_module.TestAllTypes, repeated_string=1234) self.assertRaises( - TypeError, unittest_pb2.TestAllTypes, repeated_string=[1234]) + TypeError, message_module.TestAllTypes, repeated_string=[1234]) self.assertRaises( - TypeError, unittest_pb2.TestAllTypes, repeated_nested_message=1234) + TypeError, message_module.TestAllTypes, repeated_nested_message=1234) self.assertRaises( - TypeError, unittest_pb2.TestAllTypes, repeated_nested_message=[1234]) + TypeError, message_module.TestAllTypes, repeated_nested_message=[1234]) - def testConstructorInvalidatesCachedByteSize(self): - message = unittest_pb2.TestAllTypes(optional_int32 = 12) + def testConstructorInvalidatesCachedByteSize(self, message_module): + message = message_module.TestAllTypes(optional_int32=12) self.assertEqual(2, message.ByteSize()) - message = unittest_pb2.TestAllTypes( - optional_nested_message = unittest_pb2.TestAllTypes.NestedMessage()) + message = message_module.TestAllTypes( + optional_nested_message=message_module.TestAllTypes.NestedMessage()) self.assertEqual(3, message.ByteSize()) - message = unittest_pb2.TestAllTypes(repeated_int32 = [12]) - self.assertEqual(3, message.ByteSize()) + message = message_module.TestAllTypes(repeated_int32=[12]) + # TODO(jieluo): Add this test back for proto3 + if message_module is unittest_pb2: + self.assertEqual(3, message.ByteSize()) - message = unittest_pb2.TestAllTypes( - repeated_nested_message = [unittest_pb2.TestAllTypes.NestedMessage()]) + message = message_module.TestAllTypes( + repeated_nested_message=[message_module.TestAllTypes.NestedMessage()]) self.assertEqual(3, message.ByteSize()) - def testSimpleHasBits(self): - # Test a scalar. - proto = unittest_pb2.TestAllTypes() - self.assertTrue(not proto.HasField('optional_int32')) - self.assertEqual(0, proto.optional_int32) - # HasField() shouldn't be true if all we've done is - # read the default value. - self.assertTrue(not proto.HasField('optional_int32')) - proto.optional_int32 = 1 - # Setting a value however *should* set the "has" bit. - self.assertTrue(proto.HasField('optional_int32')) - proto.ClearField('optional_int32') - # And clearing that value should unset the "has" bit. - self.assertTrue(not proto.HasField('optional_int32')) - - def testHasBitsWithSinglyNestedScalar(self): - # Helper used to test foreign messages and groups. - # - # composite_field_name should be the name of a non-repeated - # composite (i.e., foreign or group) field in TestAllTypes, - # and scalar_field_name should be the name of an integer-valued - # scalar field within that composite. - # - # I never thought I'd miss C++ macros and templates so much. :( - # This helper is semantically just: - # - # assert proto.composite_field.scalar_field == 0 - # assert not proto.composite_field.HasField('scalar_field') - # assert not proto.HasField('composite_field') - # - # proto.composite_field.scalar_field = 10 - # old_composite_field = proto.composite_field - # - # assert proto.composite_field.scalar_field == 10 - # assert proto.composite_field.HasField('scalar_field') - # assert proto.HasField('composite_field') - # - # proto.ClearField('composite_field') - # - # assert not proto.composite_field.HasField('scalar_field') - # assert not proto.HasField('composite_field') - # assert proto.composite_field.scalar_field == 0 - # - # # Now ensure that ClearField('composite_field') disconnected - # # the old field object from the object tree... - # assert old_composite_field is not proto.composite_field - # old_composite_field.scalar_field = 20 - # assert not proto.composite_field.HasField('scalar_field') - # assert not proto.HasField('composite_field') - def TestCompositeHasBits(composite_field_name, scalar_field_name): - proto = unittest_pb2.TestAllTypes() - # First, check that we can get the scalar value, and see that it's the - # default (0), but that proto.HasField('omposite') and - # proto.composite.HasField('scalar') will still return False. - composite_field = getattr(proto, composite_field_name) - original_scalar_value = getattr(composite_field, scalar_field_name) - self.assertEqual(0, original_scalar_value) - # Assert that the composite object does not "have" the scalar. - self.assertTrue(not composite_field.HasField(scalar_field_name)) - # Assert that proto does not "have" the composite field. - self.assertTrue(not proto.HasField(composite_field_name)) - - # Now set the scalar within the composite field. Ensure that the setting - # is reflected, and that proto.HasField('composite') and - # proto.composite.HasField('scalar') now both return True. - new_val = 20 - setattr(composite_field, scalar_field_name, new_val) - self.assertEqual(new_val, getattr(composite_field, scalar_field_name)) - # Hold on to a reference to the current composite_field object. - old_composite_field = composite_field - # Assert that the has methods now return true. - self.assertTrue(composite_field.HasField(scalar_field_name)) - self.assertTrue(proto.HasField(composite_field_name)) - - # Now call the clear method... - proto.ClearField(composite_field_name) - - # ...and ensure that the "has" bits are all back to False... - composite_field = getattr(proto, composite_field_name) - self.assertTrue(not composite_field.HasField(scalar_field_name)) - self.assertTrue(not proto.HasField(composite_field_name)) - # ...and ensure that the scalar field has returned to its default. - self.assertEqual(0, getattr(composite_field, scalar_field_name)) - - self.assertTrue(old_composite_field is not composite_field) - setattr(old_composite_field, scalar_field_name, new_val) - self.assertTrue(not composite_field.HasField(scalar_field_name)) - self.assertTrue(not proto.HasField(composite_field_name)) - self.assertEqual(0, getattr(composite_field, scalar_field_name)) - - # Test simple, single-level nesting when we set a scalar. - TestCompositeHasBits('optionalgroup', 'a') - TestCompositeHasBits('optional_nested_message', 'bb') - TestCompositeHasBits('optional_foreign_message', 'c') - TestCompositeHasBits('optional_import_message', 'd') - - def testReferencesToNestedMessage(self): - proto = unittest_pb2.TestAllTypes() + def testReferencesToNestedMessage(self, message_module): + proto = message_module.TestAllTypes() nested = proto.optional_nested_message del proto # A previous version had a bug where this would raise an exception when # hitting a now-dead weak reference. nested.bb = 23 - def testDisconnectingNestedMessageBeforeSettingField(self): - proto = unittest_pb2.TestAllTypes() - nested = proto.optional_nested_message - proto.ClearField('optional_nested_message') # Should disconnect from parent - self.assertTrue(nested is not proto.optional_nested_message) - nested.bb = 23 - self.assertTrue(not proto.HasField('optional_nested_message')) - self.assertEqual(0, proto.optional_nested_message.bb) + def testOneOf(self, message_module): + proto = message_module.TestAllTypes() + proto.oneof_uint32 = 10 + proto.oneof_nested_message.bb = 11 + self.assertEqual(11, proto.oneof_nested_message.bb) + self.assertFalse(proto.HasField('oneof_uint32')) + nested = proto.oneof_nested_message + proto.oneof_string = 'abc' + self.assertEqual('abc', proto.oneof_string) + self.assertEqual(11, nested.bb) + self.assertFalse(proto.HasField('oneof_nested_message')) - def testGetDefaultMessageAfterDisconnectingDefaultMessage(self): - proto = unittest_pb2.TestAllTypes() + def testGetDefaultMessageAfterDisconnectingDefaultMessage( + self, message_module): + proto = message_module.TestAllTypes() nested = proto.optional_nested_message proto.ClearField('optional_nested_message') del proto @@ -374,54 +262,788 @@ def testGetDefaultMessageAfterDisconnectingDefaultMessage(self): # with the Messages they point to. This is to make sure we're not deleting # default message instances. gc.collect() - proto = unittest_pb2.TestAllTypes() + proto = message_module.TestAllTypes() nested = proto.optional_nested_message - def testDisconnectingNestedMessageAfterSettingField(self): - proto = unittest_pb2.TestAllTypes() + def testDisconnectingNestedMessageAfterSettingField(self, message_module): + proto = message_module.TestAllTypes() nested = proto.optional_nested_message nested.bb = 5 self.assertTrue(proto.HasField('optional_nested_message')) proto.ClearField('optional_nested_message') # Should disconnect from parent self.assertEqual(5, nested.bb) self.assertEqual(0, proto.optional_nested_message.bb) - self.assertTrue(nested is not proto.optional_nested_message) + self.assertIsNot(nested, proto.optional_nested_message) nested.bb = 23 - self.assertTrue(not proto.HasField('optional_nested_message')) + self.assertFalse(proto.HasField('optional_nested_message')) self.assertEqual(0, proto.optional_nested_message.bb) - def testDisconnectingNestedMessageBeforeGettingField(self): - proto = unittest_pb2.TestAllTypes() - self.assertTrue(not proto.HasField('optional_nested_message')) + def testDisconnectingNestedMessageBeforeGettingField(self, message_module): + proto = message_module.TestAllTypes() + self.assertFalse(proto.HasField('optional_nested_message')) proto.ClearField('optional_nested_message') - self.assertTrue(not proto.HasField('optional_nested_message')) + self.assertFalse(proto.HasField('optional_nested_message')) - def testDisconnectingNestedMessageAfterMerge(self): + def testDisconnectingNestedMessageAfterMerge(self, message_module): # This test exercises the code path that does not use ReleaseMessage(). # The underlying fear is that if we use ReleaseMessage() incorrectly, # we will have memory leaks. It's hard to check that that doesn't happen, # but at least we can exercise that code path to make sure it works. - proto1 = unittest_pb2.TestAllTypes() - proto2 = unittest_pb2.TestAllTypes() + proto1 = message_module.TestAllTypes() + proto2 = message_module.TestAllTypes() proto2.optional_nested_message.bb = 5 proto1.MergeFrom(proto2) self.assertTrue(proto1.HasField('optional_nested_message')) proto1.ClearField('optional_nested_message') - self.assertTrue(not proto1.HasField('optional_nested_message')) + self.assertFalse(proto1.HasField('optional_nested_message')) - def testDisconnectingLazyNestedMessage(self): + def testDisconnectingLazyNestedMessage(self, message_module): # This test exercises releasing a nested message that is lazy. This test # only exercises real code in the C++ implementation as Python does not # support lazy parsing, but the current C++ implementation results in # memory corruption and a crash. if api_implementation.Type() != 'python': return - proto = unittest_pb2.TestAllTypes() + proto = message_module.TestAllTypes() proto.optional_lazy_message.bb = 5 proto.ClearField('optional_lazy_message') del proto gc.collect() + def testSingularListFields(self, message_module): + proto = message_module.TestAllTypes() + proto.optional_fixed32 = 1 + proto.optional_int32 = 5 + proto.optional_string = 'foo' + # Access sub-message but don't set it yet. + nested_message = proto.optional_nested_message + self.assertEqual( + [ (proto.DESCRIPTOR.fields_by_name['optional_int32' ], 5), + (proto.DESCRIPTOR.fields_by_name['optional_fixed32'], 1), + (proto.DESCRIPTOR.fields_by_name['optional_string' ], 'foo') ], + proto.ListFields()) + + proto.optional_nested_message.bb = 123 + self.assertEqual( + [ (proto.DESCRIPTOR.fields_by_name['optional_int32' ], 5), + (proto.DESCRIPTOR.fields_by_name['optional_fixed32'], 1), + (proto.DESCRIPTOR.fields_by_name['optional_string' ], 'foo'), + (proto.DESCRIPTOR.fields_by_name['optional_nested_message' ], + nested_message) ], + proto.ListFields()) + + def testRepeatedListFields(self, message_module): + proto = message_module.TestAllTypes() + proto.repeated_fixed32.append(1) + proto.repeated_int32.append(5) + proto.repeated_int32.append(11) + proto.repeated_string.extend(['foo', 'bar']) + proto.repeated_string.extend([]) + proto.repeated_string.append('baz') + proto.repeated_string.extend(str(x) for x in range(2)) + proto.optional_int32 = 21 + proto.repeated_bool # Access but don't set anything; should not be listed. + self.assertEqual( + [ (proto.DESCRIPTOR.fields_by_name['optional_int32' ], 21), + (proto.DESCRIPTOR.fields_by_name['repeated_int32' ], [5, 11]), + (proto.DESCRIPTOR.fields_by_name['repeated_fixed32'], [1]), + (proto.DESCRIPTOR.fields_by_name['repeated_string' ], + ['foo', 'bar', 'baz', '0', '1']) ], + proto.ListFields()) + + def testClearFieldWithUnknownFieldName(self, message_module): + proto = message_module.TestAllTypes() + self.assertRaises(ValueError, proto.ClearField, 'nonexistent_field') + self.assertRaises(ValueError, proto.ClearField, b'nonexistent_field') + + def testDisallowedAssignments(self, message_module): + # It's illegal to assign values directly to repeated fields + # or to nonrepeated composite fields. Ensure that this fails. + proto = message_module.TestAllTypes() + # Repeated fields. + self.assertRaises(AttributeError, setattr, proto, 'repeated_int32', 10) + # Lists shouldn't work, either. + self.assertRaises(AttributeError, setattr, proto, 'repeated_int32', [10]) + # Composite fields. + self.assertRaises(AttributeError, setattr, proto, + 'optional_nested_message', 23) + # Assignment to a repeated nested message field without specifying + # the index in the array of nested messages. + self.assertRaises(AttributeError, setattr, proto.repeated_nested_message, + 'bb', 34) + # Assignment to an attribute of a repeated field. + self.assertRaises(AttributeError, setattr, proto.repeated_float, + 'some_attribute', 34) + # proto.nonexistent_field = 23 should fail as well. + self.assertRaises(AttributeError, setattr, proto, 'nonexistent_field', 23) + + def testSingleScalarTypeSafety(self, message_module): + proto = message_module.TestAllTypes() + self.assertRaises(TypeError, setattr, proto, 'optional_int32', 1.1) + self.assertRaises(TypeError, setattr, proto, 'optional_int32', 'foo') + self.assertRaises(TypeError, setattr, proto, 'optional_string', 10) + self.assertRaises(TypeError, setattr, proto, 'optional_bytes', 10) + self.assertRaises(TypeError, setattr, proto, 'optional_bool', 'foo') + self.assertRaises(TypeError, setattr, proto, 'optional_float', 'foo') + self.assertRaises(TypeError, setattr, proto, 'optional_double', 'foo') + # TODO(jieluo): Fix type checking difference for python and c extension + if api_implementation.Type() == 'python': + self.assertRaises(TypeError, setattr, proto, 'optional_bool', 1.1) + else: + proto.optional_bool = 1.1 + + def assertIntegerTypes(self, integer_fn, message_module): + """Verifies setting of scalar integers. + + Args: + integer_fn: A function to wrap the integers that will be assigned. + message_module: unittest_pb2 or unittest_proto3_arena_pb2 + """ + def TestGetAndDeserialize(field_name, value, expected_type): + proto = message_module.TestAllTypes() + value = integer_fn(value) + setattr(proto, field_name, value) + self.assertIsInstance(getattr(proto, field_name), expected_type) + proto2 = message_module.TestAllTypes() + proto2.ParseFromString(proto.SerializeToString()) + self.assertIsInstance(getattr(proto2, field_name), expected_type) + + TestGetAndDeserialize('optional_int32', 1, int) + TestGetAndDeserialize('optional_int32', 1 << 30, int) + TestGetAndDeserialize('optional_uint32', 1 << 30, int) + integer_64 = long + if struct.calcsize('L') == 4: + # Python only has signed ints, so 32-bit python can't fit an uint32 + # in an int. + TestGetAndDeserialize('optional_uint32', 1 << 31, integer_64) + else: + # 64-bit python can fit uint32 inside an int + TestGetAndDeserialize('optional_uint32', 1 << 31, int) + TestGetAndDeserialize('optional_int64', 1 << 30, integer_64) + TestGetAndDeserialize('optional_int64', 1 << 60, integer_64) + TestGetAndDeserialize('optional_uint64', 1 << 30, integer_64) + TestGetAndDeserialize('optional_uint64', 1 << 60, integer_64) + + def testIntegerTypes(self, message_module): + self.assertIntegerTypes(lambda x: x, message_module) + + def testNonStandardIntegerTypes(self, message_module): + self.assertIntegerTypes(test_util.NonStandardInteger, message_module) + + def testIllegalValuesForIntegers(self, message_module): + pb = message_module.TestAllTypes() + + # Strings are illegal, even when the represent an integer. + with self.assertRaises(TypeError): + pb.optional_uint64 = '2' + + # The exact error should propagate with a poorly written custom integer. + with self.assertRaisesRegexp(RuntimeError, 'my_error'): + pb.optional_uint64 = test_util.NonStandardInteger(5, 'my_error') + + def assetIntegerBoundsChecking(self, integer_fn, message_module): + """Verifies bounds checking for scalar integer fields. + + Args: + integer_fn: A function to wrap the integers that will be assigned. + message_module: unittest_pb2 or unittest_proto3_arena_pb2 + """ + def TestMinAndMaxIntegers(field_name, expected_min, expected_max): + pb = message_module.TestAllTypes() + expected_min = integer_fn(expected_min) + expected_max = integer_fn(expected_max) + setattr(pb, field_name, expected_min) + self.assertEqual(expected_min, getattr(pb, field_name)) + setattr(pb, field_name, expected_max) + self.assertEqual(expected_max, getattr(pb, field_name)) + self.assertRaises((ValueError, TypeError), setattr, pb, field_name, + expected_min - 1) + self.assertRaises((ValueError, TypeError), setattr, pb, field_name, + expected_max + 1) + + TestMinAndMaxIntegers('optional_int32', -(1 << 31), (1 << 31) - 1) + TestMinAndMaxIntegers('optional_uint32', 0, 0xffffffff) + TestMinAndMaxIntegers('optional_int64', -(1 << 63), (1 << 63) - 1) + TestMinAndMaxIntegers('optional_uint64', 0, 0xffffffffffffffff) + # A bit of white-box testing since -1 is an int and not a long in C++ and + # so goes down a different path. + pb = message_module.TestAllTypes() + with self.assertRaises((ValueError, TypeError)): + pb.optional_uint64 = integer_fn(-(1 << 63)) + + pb = message_module.TestAllTypes() + pb.optional_nested_enum = integer_fn(1) + self.assertEqual(1, pb.optional_nested_enum) + + def testSingleScalarBoundsChecking(self, message_module): + self.assetIntegerBoundsChecking(lambda x: x, message_module) + + def testNonStandardSingleScalarBoundsChecking(self, message_module): + self.assetIntegerBoundsChecking( + test_util.NonStandardInteger, message_module) + + def testRepeatedScalarTypeSafety(self, message_module): + proto = message_module.TestAllTypes() + self.assertRaises(TypeError, proto.repeated_int32.append, 1.1) + self.assertRaises(TypeError, proto.repeated_int32.append, 'foo') + self.assertRaises(TypeError, proto.repeated_string, 10) + self.assertRaises(TypeError, proto.repeated_bytes, 10) + + proto.repeated_int32.append(10) + proto.repeated_int32[0] = 23 + self.assertRaises(IndexError, proto.repeated_int32.__setitem__, 500, 23) + self.assertRaises(TypeError, proto.repeated_int32.__setitem__, 0, 'abc') + self.assertRaises(TypeError, proto.repeated_int32.__setitem__, 0, []) + self.assertRaises(TypeError, proto.repeated_int32.__setitem__, + 'index', 23) + + proto.repeated_string.append('2') + self.assertRaises(TypeError, proto.repeated_string.__setitem__, 0, 10) + + # Repeated enums tests. + #proto.repeated_nested_enum.append(0) + + def testSingleScalarGettersAndSetters(self, message_module): + proto = message_module.TestAllTypes() + self.assertEqual(0, proto.optional_int32) + proto.optional_int32 = 1 + self.assertEqual(1, proto.optional_int32) + + proto.optional_uint64 = 0xffffffffffff + self.assertEqual(0xffffffffffff, proto.optional_uint64) + proto.optional_uint64 = 0xffffffffffffffff + self.assertEqual(0xffffffffffffffff, proto.optional_uint64) + # TODO(robinson): Test all other scalar field types. + + def testEnums(self, message_module): + proto = message_module.TestAllTypes() + self.assertEqual(1, proto.FOO) + self.assertEqual(1, message_module.TestAllTypes.FOO) + self.assertEqual(2, proto.BAR) + self.assertEqual(2, message_module.TestAllTypes.BAR) + self.assertEqual(3, proto.BAZ) + self.assertEqual(3, message_module.TestAllTypes.BAZ) + + def testEnum_Name(self, message_module): + self.assertEqual( + 'FOREIGN_FOO', + message_module.ForeignEnum.Name(message_module.FOREIGN_FOO)) + self.assertEqual( + 'FOREIGN_BAR', + message_module.ForeignEnum.Name(message_module.FOREIGN_BAR)) + self.assertEqual( + 'FOREIGN_BAZ', + message_module.ForeignEnum.Name(message_module.FOREIGN_BAZ)) + self.assertRaises(ValueError, + message_module.ForeignEnum.Name, 11312) + + proto = message_module.TestAllTypes() + self.assertEqual('FOO', + proto.NestedEnum.Name(proto.FOO)) + self.assertEqual('FOO', + message_module.TestAllTypes.NestedEnum.Name(proto.FOO)) + self.assertEqual('BAR', + proto.NestedEnum.Name(proto.BAR)) + self.assertEqual('BAR', + message_module.TestAllTypes.NestedEnum.Name(proto.BAR)) + self.assertEqual('BAZ', + proto.NestedEnum.Name(proto.BAZ)) + self.assertEqual('BAZ', + message_module.TestAllTypes.NestedEnum.Name(proto.BAZ)) + self.assertRaises(ValueError, + proto.NestedEnum.Name, 11312) + self.assertRaises(ValueError, + message_module.TestAllTypes.NestedEnum.Name, 11312) + + # Check some coercion cases. + self.assertRaises(TypeError, message_module.TestAllTypes.NestedEnum.Name, + 11312.0) + self.assertRaises(TypeError, message_module.TestAllTypes.NestedEnum.Name, + None) + self.assertEqual('FOO', message_module.TestAllTypes.NestedEnum.Name(True)) + + def testEnum_Value(self, message_module): + self.assertEqual(message_module.FOREIGN_FOO, + message_module.ForeignEnum.Value('FOREIGN_FOO')) + self.assertEqual(message_module.FOREIGN_FOO, + message_module.ForeignEnum.FOREIGN_FOO) + + self.assertEqual(message_module.FOREIGN_BAR, + message_module.ForeignEnum.Value('FOREIGN_BAR')) + self.assertEqual(message_module.FOREIGN_BAR, + message_module.ForeignEnum.FOREIGN_BAR) + + self.assertEqual(message_module.FOREIGN_BAZ, + message_module.ForeignEnum.Value('FOREIGN_BAZ')) + self.assertEqual(message_module.FOREIGN_BAZ, + message_module.ForeignEnum.FOREIGN_BAZ) + + self.assertRaises(ValueError, + message_module.ForeignEnum.Value, 'FO') + with self.assertRaises(AttributeError): + message_module.ForeignEnum.FO + + proto = message_module.TestAllTypes() + self.assertEqual(proto.FOO, + proto.NestedEnum.Value('FOO')) + self.assertEqual(proto.FOO, + proto.NestedEnum.FOO) + + self.assertEqual(proto.FOO, + message_module.TestAllTypes.NestedEnum.Value('FOO')) + self.assertEqual(proto.FOO, + message_module.TestAllTypes.NestedEnum.FOO) + + self.assertEqual(proto.BAR, + proto.NestedEnum.Value('BAR')) + self.assertEqual(proto.BAR, + proto.NestedEnum.BAR) + + self.assertEqual(proto.BAR, + message_module.TestAllTypes.NestedEnum.Value('BAR')) + self.assertEqual(proto.BAR, + message_module.TestAllTypes.NestedEnum.BAR) + + self.assertEqual(proto.BAZ, + proto.NestedEnum.Value('BAZ')) + self.assertEqual(proto.BAZ, + proto.NestedEnum.BAZ) + + self.assertEqual(proto.BAZ, + message_module.TestAllTypes.NestedEnum.Value('BAZ')) + self.assertEqual(proto.BAZ, + message_module.TestAllTypes.NestedEnum.BAZ) + + self.assertRaises(ValueError, + proto.NestedEnum.Value, 'Foo') + with self.assertRaises(AttributeError): + proto.NestedEnum.Value.Foo + + self.assertRaises(ValueError, + message_module.TestAllTypes.NestedEnum.Value, 'Foo') + with self.assertRaises(AttributeError): + message_module.TestAllTypes.NestedEnum.Value.Foo + + def testEnum_KeysAndValues(self, message_module): + if message_module == unittest_pb2: + keys = ['FOREIGN_FOO', 'FOREIGN_BAR', 'FOREIGN_BAZ'] + values = [4, 5, 6] + items = [('FOREIGN_FOO', 4), ('FOREIGN_BAR', 5), ('FOREIGN_BAZ', 6)] + else: + keys = ['FOREIGN_ZERO', 'FOREIGN_FOO', 'FOREIGN_BAR', 'FOREIGN_BAZ'] + values = [0, 4, 5, 6] + items = [('FOREIGN_ZERO', 0), ('FOREIGN_FOO', 4), + ('FOREIGN_BAR', 5), ('FOREIGN_BAZ', 6)] + self.assertEqual(keys, + list(message_module.ForeignEnum.keys())) + self.assertEqual(values, + list(message_module.ForeignEnum.values())) + self.assertEqual(items, + list(message_module.ForeignEnum.items())) + + proto = message_module.TestAllTypes() + if message_module == unittest_pb2: + keys = ['FOO', 'BAR', 'BAZ', 'NEG'] + values = [1, 2, 3, -1] + items = [('FOO', 1), ('BAR', 2), ('BAZ', 3), ('NEG', -1)] + else: + keys = ['ZERO', 'FOO', 'BAR', 'BAZ', 'NEG'] + values = [0, 1, 2, 3, -1] + items = [('ZERO', 0), ('FOO', 1), ('BAR', 2), ('BAZ', 3), ('NEG', -1)] + self.assertEqual(keys, list(proto.NestedEnum.keys())) + self.assertEqual(values, list(proto.NestedEnum.values())) + self.assertEqual(items, + list(proto.NestedEnum.items())) + + def testStaticParseFrom(self, message_module): + proto1 = message_module.TestAllTypes() + test_util.SetAllFields(proto1) + + string1 = proto1.SerializeToString() + proto2 = message_module.TestAllTypes.FromString(string1) + + # Messages should be equal. + self.assertEqual(proto2, proto1) + + def testMergeFromSingularField(self, message_module): + # Test merge with just a singular field. + proto1 = message_module.TestAllTypes() + proto1.optional_int32 = 1 + + proto2 = message_module.TestAllTypes() + # This shouldn't get overwritten. + proto2.optional_string = 'value' + + proto2.MergeFrom(proto1) + self.assertEqual(1, proto2.optional_int32) + self.assertEqual('value', proto2.optional_string) + + def testMergeFromRepeatedField(self, message_module): + # Test merge with just a repeated field. + proto1 = message_module.TestAllTypes() + proto1.repeated_int32.append(1) + proto1.repeated_int32.append(2) + + proto2 = message_module.TestAllTypes() + proto2.repeated_int32.append(0) + proto2.MergeFrom(proto1) + + self.assertEqual(0, proto2.repeated_int32[0]) + self.assertEqual(1, proto2.repeated_int32[1]) + self.assertEqual(2, proto2.repeated_int32[2]) + + def testMergeFromRepeatedNestedMessage(self, message_module): + # Test merge with a repeated nested message. + proto1 = message_module.TestAllTypes() + m = proto1.repeated_nested_message.add() + m.bb = 123 + m = proto1.repeated_nested_message.add() + m.bb = 321 + + proto2 = message_module.TestAllTypes() + m = proto2.repeated_nested_message.add() + m.bb = 999 + proto2.MergeFrom(proto1) + self.assertEqual(999, proto2.repeated_nested_message[0].bb) + self.assertEqual(123, proto2.repeated_nested_message[1].bb) + self.assertEqual(321, proto2.repeated_nested_message[2].bb) + + proto3 = message_module.TestAllTypes() + proto3.repeated_nested_message.MergeFrom(proto2.repeated_nested_message) + self.assertEqual(999, proto3.repeated_nested_message[0].bb) + self.assertEqual(123, proto3.repeated_nested_message[1].bb) + self.assertEqual(321, proto3.repeated_nested_message[2].bb) + + def testMergeFromAllFields(self, message_module): + # With all fields set. + proto1 = message_module.TestAllTypes() + test_util.SetAllFields(proto1) + proto2 = message_module.TestAllTypes() + proto2.MergeFrom(proto1) + + # Messages should be equal. + self.assertEqual(proto2, proto1) + + # Serialized string should be equal too. + string1 = proto1.SerializeToString() + string2 = proto2.SerializeToString() + self.assertEqual(string1, string2) + + def testMergeFromBug(self, message_module): + message1 = message_module.TestAllTypes() + message2 = message_module.TestAllTypes() + + # Cause optional_nested_message to be instantiated within message1, even + # though it is not considered to be "present". + message1.optional_nested_message + self.assertFalse(message1.HasField('optional_nested_message')) + + # Merge into message2. This should not instantiate the field is message2. + message2.MergeFrom(message1) + self.assertFalse(message2.HasField('optional_nested_message')) + + def testCopyFromSingularField(self, message_module): + # Test copy with just a singular field. + proto1 = message_module.TestAllTypes() + proto1.optional_int32 = 1 + proto1.optional_string = 'important-text' + + proto2 = message_module.TestAllTypes() + proto2.optional_string = 'value' + + proto2.CopyFrom(proto1) + self.assertEqual(1, proto2.optional_int32) + self.assertEqual('important-text', proto2.optional_string) + + def testCopyFromRepeatedField(self, message_module): + # Test copy with a repeated field. + proto1 = message_module.TestAllTypes() + proto1.repeated_int32.append(1) + proto1.repeated_int32.append(2) + + proto2 = message_module.TestAllTypes() + proto2.repeated_int32.append(0) + proto2.CopyFrom(proto1) + + self.assertEqual(1, proto2.repeated_int32[0]) + self.assertEqual(2, proto2.repeated_int32[1]) + + def testCopyFromAllFields(self, message_module): + # With all fields set. + proto1 = message_module.TestAllTypes() + test_util.SetAllFields(proto1) + proto2 = message_module.TestAllTypes() + proto2.CopyFrom(proto1) + + # Messages should be equal. + self.assertEqual(proto2, proto1) + + # Serialized string should be equal too. + string1 = proto1.SerializeToString() + string2 = proto2.SerializeToString() + self.assertEqual(string1, string2) + + def testCopyFromSelf(self, message_module): + proto1 = message_module.TestAllTypes() + proto1.repeated_int32.append(1) + proto1.optional_int32 = 2 + proto1.optional_string = 'important-text' + + proto1.CopyFrom(proto1) + self.assertEqual(1, proto1.repeated_int32[0]) + self.assertEqual(2, proto1.optional_int32) + self.assertEqual('important-text', proto1.optional_string) + + def testDeepCopy(self, message_module): + proto1 = message_module.TestAllTypes() + proto1.optional_int32 = 1 + proto2 = copy.deepcopy(proto1) + self.assertEqual(1, proto2.optional_int32) + + proto1.repeated_int32.append(2) + proto1.repeated_int32.append(3) + container = copy.deepcopy(proto1.repeated_int32) + self.assertEqual([2, 3], container) + container.remove(container[0]) + self.assertEqual([3], container) + + message1 = proto1.repeated_nested_message.add() + message1.bb = 1 + messages = copy.deepcopy(proto1.repeated_nested_message) + self.assertEqual(proto1.repeated_nested_message, messages) + message1.bb = 2 + self.assertNotEqual(proto1.repeated_nested_message, messages) + messages.remove(messages[0]) + self.assertEqual(len(messages), 0) + + # TODO(anuraag): Implement deepcopy for extension dict + + def testDisconnectingBeforeClear(self, message_module): + proto = message_module.TestAllTypes() + nested = proto.optional_nested_message + proto.Clear() + self.assertIsNot(nested, proto.optional_nested_message) + nested.bb = 23 + self.assertFalse(proto.HasField('optional_nested_message')) + self.assertEqual(0, proto.optional_nested_message.bb) + + proto = message_module.TestAllTypes() + nested = proto.optional_nested_message + nested.bb = 5 + foreign = proto.optional_foreign_message + foreign.c = 6 + proto.Clear() + self.assertIsNot(nested, proto.optional_nested_message) + self.assertIsNot(foreign, proto.optional_foreign_message) + self.assertEqual(5, nested.bb) + self.assertEqual(6, foreign.c) + nested.bb = 15 + foreign.c = 16 + self.assertFalse(proto.HasField('optional_nested_message')) + self.assertEqual(0, proto.optional_nested_message.bb) + self.assertFalse(proto.HasField('optional_foreign_message')) + self.assertEqual(0, proto.optional_foreign_message.c) + + def testStringUTF8Encoding(self, message_module): + proto = message_module.TestAllTypes() + + # Assignment of a unicode object to a field of type 'bytes' is not allowed. + self.assertRaises(TypeError, + setattr, proto, 'optional_bytes', u'unicode object') + + # Check that the default value is of python's 'unicode' type. + self.assertEqual(type(proto.optional_string), six.text_type) + + proto.optional_string = six.text_type('Testing') + self.assertEqual(proto.optional_string, str('Testing')) + + # Assign a value of type 'str' which can be encoded in UTF-8. + proto.optional_string = str('Testing') + self.assertEqual(proto.optional_string, six.text_type('Testing')) + + # Try to assign a 'bytes' object which contains non-UTF-8. + self.assertRaises(ValueError, + setattr, proto, 'optional_string', b'a\x80a') + # No exception: Assign already encoded UTF-8 bytes to a string field. + utf8_bytes = u'Тест'.encode('utf-8') + proto.optional_string = utf8_bytes + # No exception: Assign the a non-ascii unicode object. + proto.optional_string = u'Тест' + # No exception thrown (normal str assignment containing ASCII). + proto.optional_string = 'abc' + + def testBytesInTextFormat(self, message_module): + proto = message_module.TestAllTypes(optional_bytes=b'\x00\x7f\x80\xff') + self.assertEqual(u'optional_bytes: "\\000\\177\\200\\377"\n', + six.text_type(proto)) + + def testEmptyNestedMessage(self, message_module): + proto = message_module.TestAllTypes() + proto.optional_nested_message.MergeFrom( + message_module.TestAllTypes.NestedMessage()) + self.assertTrue(proto.HasField('optional_nested_message')) + + proto = message_module.TestAllTypes() + proto.optional_nested_message.CopyFrom( + message_module.TestAllTypes.NestedMessage()) + self.assertTrue(proto.HasField('optional_nested_message')) + + proto = message_module.TestAllTypes() + bytes_read = proto.optional_nested_message.MergeFromString(b'') + self.assertEqual(0, bytes_read) + self.assertTrue(proto.HasField('optional_nested_message')) + + proto = message_module.TestAllTypes() + proto.optional_nested_message.ParseFromString(b'') + self.assertTrue(proto.HasField('optional_nested_message')) + + serialized = proto.SerializeToString() + proto2 = message_module.TestAllTypes() + self.assertEqual( + len(serialized), + proto2.MergeFromString(serialized)) + self.assertTrue(proto2.HasField('optional_nested_message')) + + +# Class to test proto2-only features (required, extensions, etc.) +@testing_refleaks.TestCase +class Proto2ReflectionTest(unittest.TestCase): + + def testRepeatedCompositeConstructor(self): + # Constructor with only repeated composite types should succeed. + proto = unittest_pb2.TestAllTypes( + repeated_nested_message=[ + unittest_pb2.TestAllTypes.NestedMessage( + bb=unittest_pb2.TestAllTypes.FOO), + unittest_pb2.TestAllTypes.NestedMessage( + bb=unittest_pb2.TestAllTypes.BAR)], + repeated_foreign_message=[ + unittest_pb2.ForeignMessage(c=-43), + unittest_pb2.ForeignMessage(c=45324), + unittest_pb2.ForeignMessage(c=12)], + repeatedgroup=[ + unittest_pb2.TestAllTypes.RepeatedGroup(), + unittest_pb2.TestAllTypes.RepeatedGroup(a=1), + unittest_pb2.TestAllTypes.RepeatedGroup(a=2)]) + + self.assertEqual( + [unittest_pb2.TestAllTypes.NestedMessage( + bb=unittest_pb2.TestAllTypes.FOO), + unittest_pb2.TestAllTypes.NestedMessage( + bb=unittest_pb2.TestAllTypes.BAR)], + list(proto.repeated_nested_message)) + self.assertEqual( + [unittest_pb2.ForeignMessage(c=-43), + unittest_pb2.ForeignMessage(c=45324), + unittest_pb2.ForeignMessage(c=12)], + list(proto.repeated_foreign_message)) + self.assertEqual( + [unittest_pb2.TestAllTypes.RepeatedGroup(), + unittest_pb2.TestAllTypes.RepeatedGroup(a=1), + unittest_pb2.TestAllTypes.RepeatedGroup(a=2)], + list(proto.repeatedgroup)) + + def assertListsEqual(self, values, others): + self.assertEqual(len(values), len(others)) + for i in range(len(values)): + self.assertEqual(values[i], others[i]) + + def testSimpleHasBits(self): + # Test a scalar. + proto = unittest_pb2.TestAllTypes() + self.assertFalse(proto.HasField('optional_int32')) + self.assertEqual(0, proto.optional_int32) + # HasField() shouldn't be true if all we've done is + # read the default value. + self.assertFalse(proto.HasField('optional_int32')) + proto.optional_int32 = 1 + # Setting a value however *should* set the "has" bit. + self.assertTrue(proto.HasField('optional_int32')) + proto.ClearField('optional_int32') + # And clearing that value should unset the "has" bit. + self.assertFalse(proto.HasField('optional_int32')) + + def testHasBitsWithSinglyNestedScalar(self): + # Helper used to test foreign messages and groups. + # + # composite_field_name should be the name of a non-repeated + # composite (i.e., foreign or group) field in TestAllTypes, + # and scalar_field_name should be the name of an integer-valued + # scalar field within that composite. + # + # I never thought I'd miss C++ macros and templates so much. :( + # This helper is semantically just: + # + # assert proto.composite_field.scalar_field == 0 + # assert not proto.composite_field.HasField('scalar_field') + # assert not proto.HasField('composite_field') + # + # proto.composite_field.scalar_field = 10 + # old_composite_field = proto.composite_field + # + # assert proto.composite_field.scalar_field == 10 + # assert proto.composite_field.HasField('scalar_field') + # assert proto.HasField('composite_field') + # + # proto.ClearField('composite_field') + # + # assert not proto.composite_field.HasField('scalar_field') + # assert not proto.HasField('composite_field') + # assert proto.composite_field.scalar_field == 0 + # + # # Now ensure that ClearField('composite_field') disconnected + # # the old field object from the object tree... + # assert old_composite_field is not proto.composite_field + # old_composite_field.scalar_field = 20 + # assert not proto.composite_field.HasField('scalar_field') + # assert not proto.HasField('composite_field') + def TestCompositeHasBits(composite_field_name, scalar_field_name): + proto = unittest_pb2.TestAllTypes() + # First, check that we can get the scalar value, and see that it's the + # default (0), but that proto.HasField('omposite') and + # proto.composite.HasField('scalar') will still return False. + composite_field = getattr(proto, composite_field_name) + original_scalar_value = getattr(composite_field, scalar_field_name) + self.assertEqual(0, original_scalar_value) + # Assert that the composite object does not "have" the scalar. + self.assertFalse(composite_field.HasField(scalar_field_name)) + # Assert that proto does not "have" the composite field. + self.assertFalse(proto.HasField(composite_field_name)) + + # Now set the scalar within the composite field. Ensure that the setting + # is reflected, and that proto.HasField('composite') and + # proto.composite.HasField('scalar') now both return True. + new_val = 20 + setattr(composite_field, scalar_field_name, new_val) + self.assertEqual(new_val, getattr(composite_field, scalar_field_name)) + # Hold on to a reference to the current composite_field object. + old_composite_field = composite_field + # Assert that the has methods now return true. + self.assertTrue(composite_field.HasField(scalar_field_name)) + self.assertTrue(proto.HasField(composite_field_name)) + + # Now call the clear method... + proto.ClearField(composite_field_name) + + # ...and ensure that the "has" bits are all back to False... + composite_field = getattr(proto, composite_field_name) + self.assertFalse(composite_field.HasField(scalar_field_name)) + self.assertFalse(proto.HasField(composite_field_name)) + # ...and ensure that the scalar field has returned to its default. + self.assertEqual(0, getattr(composite_field, scalar_field_name)) + + self.assertIsNot(old_composite_field, composite_field) + setattr(old_composite_field, scalar_field_name, new_val) + self.assertFalse(composite_field.HasField(scalar_field_name)) + self.assertFalse(proto.HasField(composite_field_name)) + self.assertEqual(0, getattr(composite_field, scalar_field_name)) + + # Test simple, single-level nesting when we set a scalar. + TestCompositeHasBits('optionalgroup', 'a') + TestCompositeHasBits('optional_nested_message', 'bb') + TestCompositeHasBits('optional_foreign_message', 'c') + TestCompositeHasBits('optional_import_message', 'd') + def testHasBitsWhenModifyingRepeatedFields(self): # Test nesting when we add an element to a repeated field in a submessage. proto = unittest_pb2.TestNestedMessageHasBits() @@ -433,16 +1055,16 @@ def testHasBitsWhenModifyingRepeatedFields(self): # Do the same test, but with a repeated composite field within the # submessage. proto.ClearField('optional_nested_message') - self.assertTrue(not proto.HasField('optional_nested_message')) + self.assertFalse(proto.HasField('optional_nested_message')) proto.optional_nested_message.nestedmessage_repeated_foreignmessage.add() self.assertTrue(proto.HasField('optional_nested_message')) def testHasBitsForManyLevelsOfNesting(self): # Test nesting many levels deep. recursive_proto = unittest_pb2.TestMutualRecursionA() - self.assertTrue(not recursive_proto.HasField('bb')) + self.assertFalse(recursive_proto.HasField('bb')) self.assertEqual(0, recursive_proto.bb.a.bb.a.bb.optional_int32) - self.assertTrue(not recursive_proto.HasField('bb')) + self.assertFalse(recursive_proto.HasField('bb')) recursive_proto.bb.a.bb.a.bb.optional_int32 = 5 self.assertEqual(5, recursive_proto.bb.a.bb.a.bb.optional_int32) self.assertTrue(recursive_proto.HasField('bb')) @@ -450,50 +1072,9 @@ def testHasBitsForManyLevelsOfNesting(self): self.assertTrue(recursive_proto.bb.a.HasField('bb')) self.assertTrue(recursive_proto.bb.a.bb.HasField('a')) self.assertTrue(recursive_proto.bb.a.bb.a.HasField('bb')) - self.assertTrue(not recursive_proto.bb.a.bb.a.bb.HasField('a')) + self.assertFalse(recursive_proto.bb.a.bb.a.bb.HasField('a')) self.assertTrue(recursive_proto.bb.a.bb.a.bb.HasField('optional_int32')) - def testSingularListFields(self): - proto = unittest_pb2.TestAllTypes() - proto.optional_fixed32 = 1 - proto.optional_int32 = 5 - proto.optional_string = 'foo' - # Access sub-message but don't set it yet. - nested_message = proto.optional_nested_message - self.assertEqual( - [ (proto.DESCRIPTOR.fields_by_name['optional_int32' ], 5), - (proto.DESCRIPTOR.fields_by_name['optional_fixed32'], 1), - (proto.DESCRIPTOR.fields_by_name['optional_string' ], 'foo') ], - proto.ListFields()) - - proto.optional_nested_message.bb = 123 - self.assertEqual( - [ (proto.DESCRIPTOR.fields_by_name['optional_int32' ], 5), - (proto.DESCRIPTOR.fields_by_name['optional_fixed32'], 1), - (proto.DESCRIPTOR.fields_by_name['optional_string' ], 'foo'), - (proto.DESCRIPTOR.fields_by_name['optional_nested_message' ], - nested_message) ], - proto.ListFields()) - - def testRepeatedListFields(self): - proto = unittest_pb2.TestAllTypes() - proto.repeated_fixed32.append(1) - proto.repeated_int32.append(5) - proto.repeated_int32.append(11) - proto.repeated_string.extend(['foo', 'bar']) - proto.repeated_string.extend([]) - proto.repeated_string.append('baz') - proto.repeated_string.extend(str(x) for x in range(2)) - proto.optional_int32 = 21 - proto.repeated_bool # Access but don't set anything; should not be listed. - self.assertEqual( - [ (proto.DESCRIPTOR.fields_by_name['optional_int32' ], 21), - (proto.DESCRIPTOR.fields_by_name['repeated_int32' ], [5, 11]), - (proto.DESCRIPTOR.fields_by_name['repeated_fixed32'], [1]), - (proto.DESCRIPTOR.fields_by_name['repeated_string' ], - ['foo', 'bar', 'baz', '0', '1']) ], - proto.ListFields()) - def testSingularListExtensions(self): proto = unittest_pb2.TestAllExtensions() proto.Extensions[unittest_pb2.optional_fixed32_extension] = 1 @@ -504,6 +1085,11 @@ def testSingularListExtensions(self): (unittest_pb2.optional_fixed32_extension, 1), (unittest_pb2.optional_string_extension , 'foo') ], proto.ListFields()) + del proto.Extensions[unittest_pb2.optional_fixed32_extension] + self.assertEqual( + [(unittest_pb2.optional_int32_extension, 5), + (unittest_pb2.optional_string_extension, 'foo')], + proto.ListFields()) def testRepeatedListExtensions(self): proto = unittest_pb2.TestAllExtensions() @@ -520,6 +1106,12 @@ def testRepeatedListExtensions(self): (unittest_pb2.repeated_fixed32_extension, [1]), (unittest_pb2.repeated_string_extension , ['foo', 'bar', 'baz']) ], proto.ListFields()) + del proto.Extensions[unittest_pb2.repeated_int32_extension] + del proto.Extensions[unittest_pb2.repeated_string_extension] + self.assertEqual( + [(unittest_pb2.optional_int32_extension, 21), + (unittest_pb2.repeated_fixed32_extension, [1])], + proto.ListFields()) def testListFieldsAndExtensions(self): proto = unittest_pb2.TestFieldOrderings() @@ -578,10 +1170,6 @@ def testHasFieldWithUnknownFieldName(self): proto = unittest_pb2.TestAllTypes() self.assertRaises(ValueError, proto.HasField, 'nonexistent_field') - def testClearFieldWithUnknownFieldName(self): - proto = unittest_pb2.TestAllTypes() - self.assertRaises(ValueError, proto.ClearField, 'nonexistent_field') - def testClearRemovesChildren(self): # Make sure there aren't any implementation bugs that are only partially # clearing the message (which can happen in the more complex C++ @@ -593,149 +1181,6 @@ def testClearRemovesChildren(self): proto.CopyFrom(proto2) self.assertRaises(IndexError, lambda: proto.repeated_message[5]) - def testDisallowedAssignments(self): - # It's illegal to assign values directly to repeated fields - # or to nonrepeated composite fields. Ensure that this fails. - proto = unittest_pb2.TestAllTypes() - # Repeated fields. - self.assertRaises(AttributeError, setattr, proto, 'repeated_int32', 10) - # Lists shouldn't work, either. - self.assertRaises(AttributeError, setattr, proto, 'repeated_int32', [10]) - # Composite fields. - self.assertRaises(AttributeError, setattr, proto, - 'optional_nested_message', 23) - # Assignment to a repeated nested message field without specifying - # the index in the array of nested messages. - self.assertRaises(AttributeError, setattr, proto.repeated_nested_message, - 'bb', 34) - # Assignment to an attribute of a repeated field. - self.assertRaises(AttributeError, setattr, proto.repeated_float, - 'some_attribute', 34) - # proto.nonexistent_field = 23 should fail as well. - self.assertRaises(AttributeError, setattr, proto, 'nonexistent_field', 23) - - def testSingleScalarTypeSafety(self): - proto = unittest_pb2.TestAllTypes() - self.assertRaises(TypeError, setattr, proto, 'optional_int32', 1.1) - self.assertRaises(TypeError, setattr, proto, 'optional_int32', 'foo') - self.assertRaises(TypeError, setattr, proto, 'optional_string', 10) - self.assertRaises(TypeError, setattr, proto, 'optional_bytes', 10) - - def assertIntegerTypes(self, integer_fn): - """Verifies setting of scalar integers. - - Args: - integer_fn: A function to wrap the integers that will be assigned. - """ - def TestGetAndDeserialize(field_name, value, expected_type): - proto = unittest_pb2.TestAllTypes() - value = integer_fn(value) - setattr(proto, field_name, value) - self.assertIsInstance(getattr(proto, field_name), expected_type) - proto2 = unittest_pb2.TestAllTypes() - proto2.ParseFromString(proto.SerializeToString()) - self.assertIsInstance(getattr(proto2, field_name), expected_type) - - TestGetAndDeserialize('optional_int32', 1, int) - TestGetAndDeserialize('optional_int32', 1 << 30, int) - TestGetAndDeserialize('optional_uint32', 1 << 30, int) - try: - integer_64 = long - except NameError: # Python3 - integer_64 = int - if struct.calcsize('L') == 4: - # Python only has signed ints, so 32-bit python can't fit an uint32 - # in an int. - TestGetAndDeserialize('optional_uint32', 1 << 31, integer_64) - else: - # 64-bit python can fit uint32 inside an int - TestGetAndDeserialize('optional_uint32', 1 << 31, int) - TestGetAndDeserialize('optional_int64', 1 << 30, integer_64) - TestGetAndDeserialize('optional_int64', 1 << 60, integer_64) - TestGetAndDeserialize('optional_uint64', 1 << 30, integer_64) - TestGetAndDeserialize('optional_uint64', 1 << 60, integer_64) - - def testIntegerTypes(self): - self.assertIntegerTypes(lambda x: x) - - def testNonStandardIntegerTypes(self): - self.assertIntegerTypes(test_util.NonStandardInteger) - - def testIllegalValuesForIntegers(self): - pb = unittest_pb2.TestAllTypes() - - # Strings are illegal, even when the represent an integer. - with self.assertRaises(TypeError): - pb.optional_uint64 = '2' - - # The exact error should propagate with a poorly written custom integer. - with self.assertRaisesRegexp(RuntimeError, 'my_error'): - pb.optional_uint64 = test_util.NonStandardInteger(5, 'my_error') - - def assetIntegerBoundsChecking(self, integer_fn): - """Verifies bounds checking for scalar integer fields. - - Args: - integer_fn: A function to wrap the integers that will be assigned. - """ - def TestMinAndMaxIntegers(field_name, expected_min, expected_max): - pb = unittest_pb2.TestAllTypes() - expected_min = integer_fn(expected_min) - expected_max = integer_fn(expected_max) - setattr(pb, field_name, expected_min) - self.assertEqual(expected_min, getattr(pb, field_name)) - setattr(pb, field_name, expected_max) - self.assertEqual(expected_max, getattr(pb, field_name)) - self.assertRaises(ValueError, setattr, pb, field_name, expected_min - 1) - self.assertRaises(ValueError, setattr, pb, field_name, expected_max + 1) - - TestMinAndMaxIntegers('optional_int32', -(1 << 31), (1 << 31) - 1) - TestMinAndMaxIntegers('optional_uint32', 0, 0xffffffff) - TestMinAndMaxIntegers('optional_int64', -(1 << 63), (1 << 63) - 1) - TestMinAndMaxIntegers('optional_uint64', 0, 0xffffffffffffffff) - # A bit of white-box testing since -1 is an int and not a long in C++ and - # so goes down a different path. - pb = unittest_pb2.TestAllTypes() - with self.assertRaises(ValueError): - pb.optional_uint64 = integer_fn(-(1 << 63)) - - pb = unittest_pb2.TestAllTypes() - pb.optional_nested_enum = integer_fn(1) - self.assertEqual(1, pb.optional_nested_enum) - - def testSingleScalarBoundsChecking(self): - self.assetIntegerBoundsChecking(lambda x: x) - - def testNonStandardSingleScalarBoundsChecking(self): - self.assetIntegerBoundsChecking(test_util.NonStandardInteger) - - def testRepeatedScalarTypeSafety(self): - proto = unittest_pb2.TestAllTypes() - self.assertRaises(TypeError, proto.repeated_int32.append, 1.1) - self.assertRaises(TypeError, proto.repeated_int32.append, 'foo') - self.assertRaises(TypeError, proto.repeated_string, 10) - self.assertRaises(TypeError, proto.repeated_bytes, 10) - - proto.repeated_int32.append(10) - proto.repeated_int32[0] = 23 - self.assertRaises(IndexError, proto.repeated_int32.__setitem__, 500, 23) - self.assertRaises(TypeError, proto.repeated_int32.__setitem__, 0, 'abc') - - # Repeated enums tests. - #proto.repeated_nested_enum.append(0) - - def testSingleScalarGettersAndSetters(self): - proto = unittest_pb2.TestAllTypes() - self.assertEqual(0, proto.optional_int32) - proto.optional_int32 = 1 - self.assertEqual(1, proto.optional_int32) - - proto.optional_uint64 = 0xffffffffffff - self.assertEqual(0xffffffffffff, proto.optional_uint64) - proto.optional_uint64 = 0xffffffffffffffff - self.assertEqual(0xffffffffffffffff, proto.optional_uint64) - # TODO(robinson): Test all other scalar field types. - def testSingleScalarClearField(self): proto = unittest_pb2.TestAllTypes() # Should be allowed to clear something that's not there (a no-op). @@ -744,93 +1189,13 @@ def testSingleScalarClearField(self): self.assertTrue(proto.HasField('optional_int32')) proto.ClearField('optional_int32') self.assertEqual(0, proto.optional_int32) - self.assertTrue(not proto.HasField('optional_int32')) + self.assertFalse(proto.HasField('optional_int32')) # TODO(robinson): Test all other scalar field types. - def testEnums(self): - proto = unittest_pb2.TestAllTypes() - self.assertEqual(1, proto.FOO) - self.assertEqual(1, unittest_pb2.TestAllTypes.FOO) - self.assertEqual(2, proto.BAR) - self.assertEqual(2, unittest_pb2.TestAllTypes.BAR) - self.assertEqual(3, proto.BAZ) - self.assertEqual(3, unittest_pb2.TestAllTypes.BAZ) - - def testEnum_Name(self): - self.assertEqual('FOREIGN_FOO', - unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_FOO)) - self.assertEqual('FOREIGN_BAR', - unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_BAR)) - self.assertEqual('FOREIGN_BAZ', - unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_BAZ)) - self.assertRaises(ValueError, - unittest_pb2.ForeignEnum.Name, 11312) - - proto = unittest_pb2.TestAllTypes() - self.assertEqual('FOO', - proto.NestedEnum.Name(proto.FOO)) - self.assertEqual('FOO', - unittest_pb2.TestAllTypes.NestedEnum.Name(proto.FOO)) - self.assertEqual('BAR', - proto.NestedEnum.Name(proto.BAR)) - self.assertEqual('BAR', - unittest_pb2.TestAllTypes.NestedEnum.Name(proto.BAR)) - self.assertEqual('BAZ', - proto.NestedEnum.Name(proto.BAZ)) - self.assertEqual('BAZ', - unittest_pb2.TestAllTypes.NestedEnum.Name(proto.BAZ)) - self.assertRaises(ValueError, - proto.NestedEnum.Name, 11312) - self.assertRaises(ValueError, - unittest_pb2.TestAllTypes.NestedEnum.Name, 11312) - - def testEnum_Value(self): - self.assertEqual(unittest_pb2.FOREIGN_FOO, - unittest_pb2.ForeignEnum.Value('FOREIGN_FOO')) - self.assertEqual(unittest_pb2.FOREIGN_BAR, - unittest_pb2.ForeignEnum.Value('FOREIGN_BAR')) - self.assertEqual(unittest_pb2.FOREIGN_BAZ, - unittest_pb2.ForeignEnum.Value('FOREIGN_BAZ')) - self.assertRaises(ValueError, - unittest_pb2.ForeignEnum.Value, 'FO') - - proto = unittest_pb2.TestAllTypes() - self.assertEqual(proto.FOO, - proto.NestedEnum.Value('FOO')) - self.assertEqual(proto.FOO, - unittest_pb2.TestAllTypes.NestedEnum.Value('FOO')) - self.assertEqual(proto.BAR, - proto.NestedEnum.Value('BAR')) - self.assertEqual(proto.BAR, - unittest_pb2.TestAllTypes.NestedEnum.Value('BAR')) - self.assertEqual(proto.BAZ, - proto.NestedEnum.Value('BAZ')) - self.assertEqual(proto.BAZ, - unittest_pb2.TestAllTypes.NestedEnum.Value('BAZ')) - self.assertRaises(ValueError, - proto.NestedEnum.Value, 'Foo') - self.assertRaises(ValueError, - unittest_pb2.TestAllTypes.NestedEnum.Value, 'Foo') - - def testEnum_KeysAndValues(self): - self.assertEqual(['FOREIGN_FOO', 'FOREIGN_BAR', 'FOREIGN_BAZ'], - list(unittest_pb2.ForeignEnum.keys())) - self.assertEqual([4, 5, 6], - list(unittest_pb2.ForeignEnum.values())) - self.assertEqual([('FOREIGN_FOO', 4), ('FOREIGN_BAR', 5), - ('FOREIGN_BAZ', 6)], - list(unittest_pb2.ForeignEnum.items())) - - proto = unittest_pb2.TestAllTypes() - self.assertEqual(['FOO', 'BAR', 'BAZ', 'NEG'], list(proto.NestedEnum.keys())) - self.assertEqual([1, 2, 3, -1], list(proto.NestedEnum.values())) - self.assertEqual([('FOO', 1), ('BAR', 2), ('BAZ', 3), ('NEG', -1)], - list(proto.NestedEnum.items())) - def testRepeatedScalars(self): proto = unittest_pb2.TestAllTypes() - self.assertTrue(not proto.repeated_int32) + self.assertFalse(proto.repeated_int32) self.assertEqual(0, len(proto.repeated_int32)) proto.repeated_int32.append(5) proto.repeated_int32.append(10) @@ -891,7 +1256,7 @@ def testRepeatedScalars(self): # Test clearing. proto.ClearField('repeated_int32') - self.assertTrue(not proto.repeated_int32) + self.assertFalse(proto.repeated_int32) self.assertEqual(0, len(proto.repeated_int32)) proto.repeated_int32.append(1) @@ -920,7 +1285,7 @@ def testRepeatedScalars(self): def testRepeatedScalarsRemove(self): proto = unittest_pb2.TestAllTypes() - self.assertTrue(not proto.repeated_int32) + self.assertFalse(proto.repeated_int32) self.assertEqual(0, len(proto.repeated_int32)) proto.repeated_int32.append(5) proto.repeated_int32.append(10) @@ -946,9 +1311,41 @@ def testRepeatedScalarsRemove(self): # Remove a non-existent element. self.assertRaises(ValueError, proto.repeated_int32.remove, 123) + def testRepeatedScalarsReverse_Empty(self): + proto = unittest_pb2.TestAllTypes() + + self.assertFalse(proto.repeated_int32) + self.assertEqual(0, len(proto.repeated_int32)) + + self.assertIsNone(proto.repeated_int32.reverse()) + + self.assertFalse(proto.repeated_int32) + self.assertEqual(0, len(proto.repeated_int32)) + + def testRepeatedScalarsReverse_NonEmpty(self): + proto = unittest_pb2.TestAllTypes() + + self.assertFalse(proto.repeated_int32) + self.assertEqual(0, len(proto.repeated_int32)) + + proto.repeated_int32.append(1) + proto.repeated_int32.append(2) + proto.repeated_int32.append(3) + proto.repeated_int32.append(4) + + self.assertEqual(4, len(proto.repeated_int32)) + + self.assertIsNone(proto.repeated_int32.reverse()) + + self.assertEqual(4, len(proto.repeated_int32)) + self.assertEqual(4, proto.repeated_int32[0]) + self.assertEqual(3, proto.repeated_int32[1]) + self.assertEqual(2, proto.repeated_int32[2]) + self.assertEqual(1, proto.repeated_int32[3]) + def testRepeatedComposites(self): proto = unittest_pb2.TestAllTypes() - self.assertTrue(not proto.repeated_nested_message) + self.assertFalse(proto.repeated_nested_message) self.assertEqual(0, len(proto.repeated_nested_message)) m0 = proto.repeated_nested_message.add() m1 = proto.repeated_nested_message.add() @@ -1007,10 +1404,18 @@ def testRepeatedComposites(self): self.assertEqual(4, len(proto.repeated_nested_message)) self.assertEqual(n1, proto.repeated_nested_message[2]) self.assertEqual(n2, proto.repeated_nested_message[3]) + self.assertRaises(TypeError, + proto.repeated_nested_message.extend, n1) + self.assertRaises(TypeError, + proto.repeated_nested_message.extend, [0]) + wrong_message_type = unittest_pb2.TestAllTypes() + self.assertRaises(TypeError, + proto.repeated_nested_message.extend, + [wrong_message_type]) # Test clearing. proto.ClearField('repeated_nested_message') - self.assertTrue(not proto.repeated_nested_message) + self.assertFalse(proto.repeated_nested_message) self.assertEqual(0, len(proto.repeated_nested_message)) # Test constructing an element while adding it. @@ -1018,6 +1423,8 @@ def testRepeatedComposites(self): self.assertEqual(1, len(proto.repeated_nested_message)) self.assertEqual(23, proto.repeated_nested_message[0].bb) self.assertRaises(TypeError, proto.repeated_nested_message.add, 23) + with self.assertRaises(Exception): + proto.repeated_nested_message[0] = 23 def testRepeatedCompositeRemove(self): proto = unittest_pb2.TestAllTypes() @@ -1048,6 +1455,35 @@ def testRepeatedCompositeRemove(self): self.assertEqual(1, len(proto.repeated_nested_message)) self.assertEqual(m1, proto.repeated_nested_message[0]) + def testRepeatedCompositeReverse_Empty(self): + proto = unittest_pb2.TestAllTypes() + + self.assertFalse(proto.repeated_nested_message) + self.assertEqual(0, len(proto.repeated_nested_message)) + + self.assertIsNone(proto.repeated_nested_message.reverse()) + + self.assertFalse(proto.repeated_nested_message) + self.assertEqual(0, len(proto.repeated_nested_message)) + + def testRepeatedCompositeReverse_NonEmpty(self): + proto = unittest_pb2.TestAllTypes() + + self.assertFalse(proto.repeated_nested_message) + self.assertEqual(0, len(proto.repeated_nested_message)) + + m0 = proto.repeated_nested_message.add() + m0.bb = len(proto.repeated_nested_message) + m1 = proto.repeated_nested_message.add() + m1.bb = len(proto.repeated_nested_message) + m2 = proto.repeated_nested_message.add() + m2.bb = len(proto.repeated_nested_message) + self.assertListsEqual([m0, m1, m2], proto.repeated_nested_message) + + self.assertIsNone(proto.repeated_nested_message.reverse()) + + self.assertListsEqual([m2, m1, m0], proto.repeated_nested_message) + def testHandWrittenReflection(self): # Hand written extensions are only supported by the pure-Python # implementation of the API. @@ -1062,21 +1498,26 @@ def testHandWrittenReflection(self): label=FieldDescriptor.LABEL_OPTIONAL, default_value=0, containing_type=None, message_type=None, enum_type=None, is_extension=False, extension_scope=None, - options=descriptor_pb2.FieldOptions()) + options=descriptor_pb2.FieldOptions(), + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) mydescriptor = descriptor.Descriptor( name='MyProto', full_name='MyProto', filename='ignored', containing_type=None, nested_types=[], enum_types=[], fields=[foo_field_descriptor], extensions=[], - options=descriptor_pb2.MessageOptions()) + options=descriptor_pb2.MessageOptions(), + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) class MyProtoClass(six.with_metaclass(reflection.GeneratedProtocolMessageType, message.Message)): DESCRIPTOR = mydescriptor myproto_instance = MyProtoClass() self.assertEqual(0, myproto_instance.foo_field) - self.assertTrue(not myproto_instance.HasField('foo_field')) + self.assertFalse(myproto_instance.HasField('foo_field')) myproto_instance.foo_field = 23 self.assertEqual(23, myproto_instance.foo_field) self.assertTrue(myproto_instance.HasField('foo_field')) + @testing_refleaks.SkipReferenceLeakChecker('MakeDescriptor is not repeatable') def testDescriptorProtoSupport(self): # Hand written descriptors/reflection are only supported by the pure-Python # implementation of the API. @@ -1115,7 +1556,8 @@ def AddDescriptorField(proto, field_name, field_type): self.assertTrue('price' in desc.fields_by_name) self.assertTrue('owners' in desc.fields_by_name) - class CarMessage(six.with_metaclass(reflection.GeneratedProtocolMessageType, message.Message)): + class CarMessage(six.with_metaclass(reflection.GeneratedProtocolMessageType, + message.Message)): DESCRIPTOR = desc prius = CarMessage() @@ -1127,7 +1569,7 @@ class CarMessage(six.with_metaclass(reflection.GeneratedProtocolMessageType, mes serialized_prius = prius.SerializeToString() new_prius = reflection.ParseMessage(desc, serialized_prius) - self.assertTrue(new_prius is not prius) + self.assertIsNot(new_prius, prius) self.assertEqual(prius, new_prius) # these are unnecessary assuming message equality works as advertised but @@ -1138,33 +1580,98 @@ class CarMessage(six.with_metaclass(reflection.GeneratedProtocolMessageType, mes self.assertEqual(prius.price, new_prius.price) self.assertEqual(prius.owners, new_prius.owners) + def testExtensionDelete(self): + extendee_proto = more_extensions_pb2.ExtendedMessage() + + extension_int32 = more_extensions_pb2.optional_int_extension + extendee_proto.Extensions[extension_int32] = 23 + + extension_repeated = more_extensions_pb2.repeated_int_extension + extendee_proto.Extensions[extension_repeated].append(11) + + extension_msg = more_extensions_pb2.optional_message_extension + extendee_proto.Extensions[extension_msg].foreign_message_int = 56 + + self.assertEqual(len(extendee_proto.Extensions), 3) + del extendee_proto.Extensions[extension_msg] + self.assertEqual(len(extendee_proto.Extensions), 2) + del extendee_proto.Extensions[extension_repeated] + self.assertEqual(len(extendee_proto.Extensions), 1) + # Delete a none exist extension. It is OK to "del m.Extensions[ext]" + # even if the extension is not present in the message; we don't + # raise KeyError. This is consistent with "m.Extensions[ext]" + # returning a default value even if we did not set anything. + del extendee_proto.Extensions[extension_repeated] + self.assertEqual(len(extendee_proto.Extensions), 1) + del extendee_proto.Extensions[extension_int32] + self.assertEqual(len(extendee_proto.Extensions), 0) + + def testExtensionIter(self): + extendee_proto = more_extensions_pb2.ExtendedMessage() + + extension_int32 = more_extensions_pb2.optional_int_extension + extendee_proto.Extensions[extension_int32] = 23 + + extension_repeated = more_extensions_pb2.repeated_int_extension + extendee_proto.Extensions[extension_repeated].append(11) + + extension_msg = more_extensions_pb2.optional_message_extension + extendee_proto.Extensions[extension_msg].foreign_message_int = 56 + + # Set some normal fields. + extendee_proto.optional_int32 = 1 + extendee_proto.repeated_string.append('hi') + + expected = (extension_int32, extension_msg, extension_repeated) + count = 0 + for item in extendee_proto.Extensions: + self.assertEqual(item.name, expected[count].name) + self.assertIn(item, extendee_proto.Extensions) + count += 1 + self.assertEqual(count, 3) + + def testExtensionContainsError(self): + extendee_proto = more_extensions_pb2.ExtendedMessage() + self.assertRaises(KeyError, extendee_proto.Extensions.__contains__, 0) + + field = more_extensions_pb2.ExtendedMessage.DESCRIPTOR.fields_by_name[ + 'optional_int32'] + self.assertRaises(KeyError, extendee_proto.Extensions.__contains__, field) + def testTopLevelExtensionsForOptionalScalar(self): extendee_proto = unittest_pb2.TestAllExtensions() extension = unittest_pb2.optional_int32_extension - self.assertTrue(not extendee_proto.HasExtension(extension)) + self.assertFalse(extendee_proto.HasExtension(extension)) + self.assertNotIn(extension, extendee_proto.Extensions) self.assertEqual(0, extendee_proto.Extensions[extension]) # As with normal scalar fields, just doing a read doesn't actually set the # "has" bit. - self.assertTrue(not extendee_proto.HasExtension(extension)) + self.assertFalse(extendee_proto.HasExtension(extension)) + self.assertNotIn(extension, extendee_proto.Extensions) # Actually set the thing. extendee_proto.Extensions[extension] = 23 self.assertEqual(23, extendee_proto.Extensions[extension]) self.assertTrue(extendee_proto.HasExtension(extension)) + self.assertIn(extension, extendee_proto.Extensions) # Ensure that clearing works as well. extendee_proto.ClearExtension(extension) self.assertEqual(0, extendee_proto.Extensions[extension]) - self.assertTrue(not extendee_proto.HasExtension(extension)) + self.assertFalse(extendee_proto.HasExtension(extension)) + self.assertNotIn(extension, extendee_proto.Extensions) def testTopLevelExtensionsForRepeatedScalar(self): extendee_proto = unittest_pb2.TestAllExtensions() extension = unittest_pb2.repeated_string_extension self.assertEqual(0, len(extendee_proto.Extensions[extension])) + self.assertNotIn(extension, extendee_proto.Extensions) extendee_proto.Extensions[extension].append('foo') self.assertEqual(['foo'], extendee_proto.Extensions[extension]) + self.assertIn(extension, extendee_proto.Extensions) string_list = extendee_proto.Extensions[extension] extendee_proto.ClearExtension(extension) self.assertEqual(0, len(extendee_proto.Extensions[extension])) - self.assertTrue(string_list is not extendee_proto.Extensions[extension]) + self.assertNotIn(extension, extendee_proto.Extensions) + self.assertIsNot(string_list, extendee_proto.Extensions[extension]) # Shouldn't be allowed to do Extensions[extension] = 'a' self.assertRaises(TypeError, operator.setitem, extendee_proto.Extensions, extension, 'a') @@ -1172,24 +1679,28 @@ def testTopLevelExtensionsForRepeatedScalar(self): def testTopLevelExtensionsForOptionalMessage(self): extendee_proto = unittest_pb2.TestAllExtensions() extension = unittest_pb2.optional_foreign_message_extension - self.assertTrue(not extendee_proto.HasExtension(extension)) + self.assertFalse(extendee_proto.HasExtension(extension)) + self.assertNotIn(extension, extendee_proto.Extensions) self.assertEqual(0, extendee_proto.Extensions[extension].c) # As with normal (non-extension) fields, merely reading from the # thing shouldn't set the "has" bit. - self.assertTrue(not extendee_proto.HasExtension(extension)) + self.assertFalse(extendee_proto.HasExtension(extension)) + self.assertNotIn(extension, extendee_proto.Extensions) extendee_proto.Extensions[extension].c = 23 self.assertEqual(23, extendee_proto.Extensions[extension].c) self.assertTrue(extendee_proto.HasExtension(extension)) + self.assertIn(extension, extendee_proto.Extensions) # Save a reference here. foreign_message = extendee_proto.Extensions[extension] extendee_proto.ClearExtension(extension) - self.assertTrue(foreign_message is not extendee_proto.Extensions[extension]) + self.assertIsNot(foreign_message, extendee_proto.Extensions[extension]) # Setting a field on foreign_message now shouldn't set # any "has" bits on extendee_proto. foreign_message.c = 42 self.assertEqual(42, foreign_message.c) self.assertTrue(foreign_message.HasField('c')) - self.assertTrue(not extendee_proto.HasExtension(extension)) + self.assertFalse(extendee_proto.HasExtension(extension)) + self.assertNotIn(extension, extendee_proto.Extensions) # Shouldn't be allowed to do Extensions[extension] = 'a' self.assertRaises(TypeError, operator.setitem, extendee_proto.Extensions, extension, 'a') @@ -1206,7 +1717,7 @@ def testTopLevelExtensionsForRepeatedMessage(self): group_list = extendee_proto.Extensions[extension] extendee_proto.ClearExtension(extension) self.assertEqual(0, len(extendee_proto.Extensions[extension])) - self.assertTrue(group_list is not extendee_proto.Extensions[extension]) + self.assertIsNot(group_list, extendee_proto.Extensions[extension]) # Shouldn't be allowed to do Extensions[extension] = 'a' self.assertRaises(TypeError, operator.setitem, extendee_proto.Extensions, extension, 'a') @@ -1216,16 +1727,20 @@ def testNestedExtensions(self): extension = unittest_pb2.TestRequired.single # We just test the non-repeated case. - self.assertTrue(not extendee_proto.HasExtension(extension)) + self.assertFalse(extendee_proto.HasExtension(extension)) + self.assertNotIn(extension, extendee_proto.Extensions) required = extendee_proto.Extensions[extension] self.assertEqual(0, required.a) - self.assertTrue(not extendee_proto.HasExtension(extension)) + self.assertFalse(extendee_proto.HasExtension(extension)) + self.assertNotIn(extension, extendee_proto.Extensions) required.a = 23 self.assertEqual(23, extendee_proto.Extensions[extension].a) self.assertTrue(extendee_proto.HasExtension(extension)) + self.assertIn(extension, extendee_proto.Extensions) extendee_proto.ClearExtension(extension) - self.assertTrue(required is not extendee_proto.Extensions[extension]) - self.assertTrue(not extendee_proto.HasExtension(extension)) + self.assertIsNot(required, extendee_proto.Extensions[extension]) + self.assertFalse(extendee_proto.HasExtension(extension)) + self.assertNotIn(extension, extendee_proto.Extensions) def testRegisteredExtensions(self): pool = unittest_pb2.DESCRIPTOR.pool @@ -1248,10 +1763,10 @@ def testRegisteredExtensions(self): def testHasBitsForAncestorsOfExtendedMessage(self): # Optional scalar extension. toplevel = more_extensions_pb2.TopLevelMessage() - self.assertTrue(not toplevel.HasField('submessage')) + self.assertFalse(toplevel.HasField('submessage')) self.assertEqual(0, toplevel.submessage.Extensions[ more_extensions_pb2.optional_int_extension]) - self.assertTrue(not toplevel.HasField('submessage')) + self.assertFalse(toplevel.HasField('submessage')) toplevel.submessage.Extensions[ more_extensions_pb2.optional_int_extension] = 23 self.assertEqual(23, toplevel.submessage.Extensions[ @@ -1260,10 +1775,10 @@ def testHasBitsForAncestorsOfExtendedMessage(self): # Repeated scalar extension. toplevel = more_extensions_pb2.TopLevelMessage() - self.assertTrue(not toplevel.HasField('submessage')) + self.assertFalse(toplevel.HasField('submessage')) self.assertEqual([], toplevel.submessage.Extensions[ more_extensions_pb2.repeated_int_extension]) - self.assertTrue(not toplevel.HasField('submessage')) + self.assertFalse(toplevel.HasField('submessage')) toplevel.submessage.Extensions[ more_extensions_pb2.repeated_int_extension].append(23) self.assertEqual([23], toplevel.submessage.Extensions[ @@ -1272,10 +1787,10 @@ def testHasBitsForAncestorsOfExtendedMessage(self): # Optional message extension. toplevel = more_extensions_pb2.TopLevelMessage() - self.assertTrue(not toplevel.HasField('submessage')) + self.assertFalse(toplevel.HasField('submessage')) self.assertEqual(0, toplevel.submessage.Extensions[ more_extensions_pb2.optional_message_extension].foreign_message_int) - self.assertTrue(not toplevel.HasField('submessage')) + self.assertFalse(toplevel.HasField('submessage')) toplevel.submessage.Extensions[ more_extensions_pb2.optional_message_extension].foreign_message_int = 23 self.assertEqual(23, toplevel.submessage.Extensions[ @@ -1284,10 +1799,10 @@ def testHasBitsForAncestorsOfExtendedMessage(self): # Repeated message extension. toplevel = more_extensions_pb2.TopLevelMessage() - self.assertTrue(not toplevel.HasField('submessage')) + self.assertFalse(toplevel.HasField('submessage')) self.assertEqual(0, len(toplevel.submessage.Extensions[ more_extensions_pb2.repeated_message_extension])) - self.assertTrue(not toplevel.HasField('submessage')) + self.assertFalse(toplevel.HasField('submessage')) foreign = toplevel.submessage.Extensions[ more_extensions_pb2.repeated_message_extension].add() self.assertEqual(foreign, toplevel.submessage.Extensions[ @@ -1302,7 +1817,7 @@ def testDisconnectionAfterClearingEmptyMessage(self): extendee_proto.ClearExtension(extension) extension_proto.foreign_message_int = 23 - self.assertTrue(extension_proto is not extendee_proto.Extensions[extension]) + self.assertIsNot(extension_proto, extendee_proto.Extensions[extension]) def testExtensionFailureModes(self): extendee_proto = unittest_pb2.TestAllExtensions() @@ -1335,43 +1850,6 @@ def testExtensionFailureModes(self): self.assertRaises(KeyError, extendee_proto.HasExtension, unittest_pb2.repeated_string_extension) - def testStaticParseFrom(self): - proto1 = unittest_pb2.TestAllTypes() - test_util.SetAllFields(proto1) - - string1 = proto1.SerializeToString() - proto2 = unittest_pb2.TestAllTypes.FromString(string1) - - # Messages should be equal. - self.assertEqual(proto2, proto1) - - def testMergeFromSingularField(self): - # Test merge with just a singular field. - proto1 = unittest_pb2.TestAllTypes() - proto1.optional_int32 = 1 - - proto2 = unittest_pb2.TestAllTypes() - # This shouldn't get overwritten. - proto2.optional_string = 'value' - - proto2.MergeFrom(proto1) - self.assertEqual(1, proto2.optional_int32) - self.assertEqual('value', proto2.optional_string) - - def testMergeFromRepeatedField(self): - # Test merge with just a repeated field. - proto1 = unittest_pb2.TestAllTypes() - proto1.repeated_int32.append(1) - proto1.repeated_int32.append(2) - - proto2 = unittest_pb2.TestAllTypes() - proto2.repeated_int32.append(0) - proto2.MergeFrom(proto1) - - self.assertEqual(0, proto2.repeated_int32[0]) - self.assertEqual(1, proto2.repeated_int32[1]) - self.assertEqual(2, proto2.repeated_int32[2]) - def testMergeFromOptionalGroup(self): # Test merge with an optional group. proto1 = unittest_pb2.TestAllTypes() @@ -1380,43 +1858,6 @@ def testMergeFromOptionalGroup(self): proto2.MergeFrom(proto1) self.assertEqual(12, proto2.optionalgroup.a) - def testMergeFromRepeatedNestedMessage(self): - # Test merge with a repeated nested message. - proto1 = unittest_pb2.TestAllTypes() - m = proto1.repeated_nested_message.add() - m.bb = 123 - m = proto1.repeated_nested_message.add() - m.bb = 321 - - proto2 = unittest_pb2.TestAllTypes() - m = proto2.repeated_nested_message.add() - m.bb = 999 - proto2.MergeFrom(proto1) - self.assertEqual(999, proto2.repeated_nested_message[0].bb) - self.assertEqual(123, proto2.repeated_nested_message[1].bb) - self.assertEqual(321, proto2.repeated_nested_message[2].bb) - - proto3 = unittest_pb2.TestAllTypes() - proto3.repeated_nested_message.MergeFrom(proto2.repeated_nested_message) - self.assertEqual(999, proto3.repeated_nested_message[0].bb) - self.assertEqual(123, proto3.repeated_nested_message[1].bb) - self.assertEqual(321, proto3.repeated_nested_message[2].bb) - - def testMergeFromAllFields(self): - # With all fields set. - proto1 = unittest_pb2.TestAllTypes() - test_util.SetAllFields(proto1) - proto2 = unittest_pb2.TestAllTypes() - proto2.MergeFrom(proto1) - - # Messages should be equal. - self.assertEqual(proto2, proto1) - - # Serialized string should be equal too. - string1 = proto1.SerializeToString() - string2 = proto2.SerializeToString() - self.assertEqual(string1, string2) - def testMergeFromExtensionsSingular(self): proto1 = unittest_pb2.TestAllExtensions() proto1.Extensions[unittest_pb2.optional_int32_extension] = 1 @@ -1466,71 +1907,6 @@ def testMergeFromExtensionsNestedMessage(self): self.assertEqual(222, ext2[1].bb) self.assertEqual(333, ext2[2].bb) - def testMergeFromBug(self): - message1 = unittest_pb2.TestAllTypes() - message2 = unittest_pb2.TestAllTypes() - - # Cause optional_nested_message to be instantiated within message1, even - # though it is not considered to be "present". - message1.optional_nested_message - self.assertFalse(message1.HasField('optional_nested_message')) - - # Merge into message2. This should not instantiate the field is message2. - message2.MergeFrom(message1) - self.assertFalse(message2.HasField('optional_nested_message')) - - def testCopyFromSingularField(self): - # Test copy with just a singular field. - proto1 = unittest_pb2.TestAllTypes() - proto1.optional_int32 = 1 - proto1.optional_string = 'important-text' - - proto2 = unittest_pb2.TestAllTypes() - proto2.optional_string = 'value' - - proto2.CopyFrom(proto1) - self.assertEqual(1, proto2.optional_int32) - self.assertEqual('important-text', proto2.optional_string) - - def testCopyFromRepeatedField(self): - # Test copy with a repeated field. - proto1 = unittest_pb2.TestAllTypes() - proto1.repeated_int32.append(1) - proto1.repeated_int32.append(2) - - proto2 = unittest_pb2.TestAllTypes() - proto2.repeated_int32.append(0) - proto2.CopyFrom(proto1) - - self.assertEqual(1, proto2.repeated_int32[0]) - self.assertEqual(2, proto2.repeated_int32[1]) - - def testCopyFromAllFields(self): - # With all fields set. - proto1 = unittest_pb2.TestAllTypes() - test_util.SetAllFields(proto1) - proto2 = unittest_pb2.TestAllTypes() - proto2.CopyFrom(proto1) - - # Messages should be equal. - self.assertEqual(proto2, proto1) - - # Serialized string should be equal too. - string1 = proto1.SerializeToString() - string2 = proto2.SerializeToString() - self.assertEqual(string1, string2) - - def testCopyFromSelf(self): - proto1 = unittest_pb2.TestAllTypes() - proto1.repeated_int32.append(1) - proto1.optional_int32 = 2 - proto1.optional_string = 'important-text' - - proto1.CopyFrom(proto1) - self.assertEqual(1, proto1.repeated_int32[0]) - self.assertEqual(2, proto1.optional_int32) - self.assertEqual('important-text', proto1.optional_string) - def testCopyFromBadType(self): # The python implementation doesn't raise an exception in this # case. In theory it should. @@ -1540,26 +1916,6 @@ def testCopyFromBadType(self): proto2 = unittest_pb2.TestAllExtensions() self.assertRaises(TypeError, proto1.CopyFrom, proto2) - def testDeepCopy(self): - proto1 = unittest_pb2.TestAllTypes() - proto1.optional_int32 = 1 - proto2 = copy.deepcopy(proto1) - self.assertEqual(1, proto2.optional_int32) - - proto1.repeated_int32.append(2) - proto1.repeated_int32.append(3) - container = copy.deepcopy(proto1.repeated_int32) - self.assertEqual([2, 3], container) - - message1 = proto1.repeated_nested_message.add() - message1.bb = 1 - messages = copy.deepcopy(proto1.repeated_nested_message) - self.assertEqual(proto1.repeated_nested_message, messages) - message1.bb = 2 - self.assertNotEqual(proto1.repeated_nested_message, messages) - - # TODO(anuraag): Implement deepcopy for extension dict - def testClear(self): proto = unittest_pb2.TestAllTypes() # C++ implementation does not support lazy fields right now so leave it @@ -1583,33 +1939,6 @@ def testClear(self): empty_proto = unittest_pb2.TestAllExtensions() self.assertEqual(proto, empty_proto) - def testDisconnectingBeforeClear(self): - proto = unittest_pb2.TestAllTypes() - nested = proto.optional_nested_message - proto.Clear() - self.assertTrue(nested is not proto.optional_nested_message) - nested.bb = 23 - self.assertTrue(not proto.HasField('optional_nested_message')) - self.assertEqual(0, proto.optional_nested_message.bb) - - proto = unittest_pb2.TestAllTypes() - nested = proto.optional_nested_message - nested.bb = 5 - foreign = proto.optional_foreign_message - foreign.c = 6 - - proto.Clear() - self.assertTrue(nested is not proto.optional_nested_message) - self.assertTrue(foreign is not proto.optional_foreign_message) - self.assertEqual(5, nested.bb) - self.assertEqual(6, foreign.c) - nested.bb = 15 - foreign.c = 16 - self.assertFalse(proto.HasField('optional_nested_message')) - self.assertEqual(0, proto.optional_nested_message.bb) - self.assertFalse(proto.HasField('optional_foreign_message')) - self.assertEqual(0, proto.optional_foreign_message.c) - def testDisconnectingInOneof(self): m = unittest_pb2.TestOneof2() # This message has two messages in a oneof. m.foo_message.qux_int = 5 @@ -1624,26 +1953,17 @@ def testDisconnectingInOneof(self): self.assertEqual(sub_message.qux_int, 5) sub_message.qux_int = 7 - def testOneOf(self): - proto = unittest_pb2.TestAllTypes() - proto.oneof_uint32 = 10 - proto.oneof_nested_message.bb = 11 - self.assertEqual(11, proto.oneof_nested_message.bb) - self.assertFalse(proto.HasField('oneof_uint32')) - nested = proto.oneof_nested_message - proto.oneof_string = 'abc' - self.assertEqual('abc', proto.oneof_string) - self.assertEqual(11, nested.bb) - self.assertFalse(proto.HasField('oneof_nested_message')) - def assertInitialized(self, proto): self.assertTrue(proto.IsInitialized()) # Neither method should raise an exception. proto.SerializeToString() proto.SerializePartialToString() - def assertNotInitialized(self, proto): + def assertNotInitialized(self, proto, error_size=None): + errors = [] self.assertFalse(proto.IsInitialized()) + self.assertFalse(proto.IsInitialized(errors)) + self.assertEqual(error_size, len(errors)) self.assertRaises(message.EncodeError, proto.SerializeToString) # "Partial" serialization doesn't care if message is uninitialized. proto.SerializePartialToString() @@ -1657,7 +1977,7 @@ def testIsInitialized(self): # The case of uninitialized required fields. proto = unittest_pb2.TestRequired() - self.assertNotInitialized(proto) + self.assertNotInitialized(proto, 3) proto.a = proto.b = proto.c = 2 self.assertInitialized(proto) @@ -1665,14 +1985,14 @@ def testIsInitialized(self): proto = unittest_pb2.TestRequiredForeign() self.assertInitialized(proto) proto.optional_message.a = 1 - self.assertNotInitialized(proto) + self.assertNotInitialized(proto, 2) proto.optional_message.b = 0 proto.optional_message.c = 0 self.assertInitialized(proto) # Uninitialized repeated submessage. message1 = proto.repeated_message.add() - self.assertNotInitialized(proto) + self.assertNotInitialized(proto, 3) message1.a = message1.b = message1.c = 0 self.assertInitialized(proto) @@ -1681,11 +2001,11 @@ def testIsInitialized(self): extension = unittest_pb2.TestRequired.multi message1 = proto.Extensions[extension].add() message2 = proto.Extensions[extension].add() - self.assertNotInitialized(proto) + self.assertNotInitialized(proto, 6) message1.a = 1 message1.b = 1 message1.c = 1 - self.assertNotInitialized(proto) + self.assertNotInitialized(proto, 3) message2.a = 2 message2.b = 2 message2.c = 2 @@ -1695,7 +2015,7 @@ def testIsInitialized(self): proto = unittest_pb2.TestAllExtensions() extension = unittest_pb2.TestRequired.single proto.Extensions[extension].a = 1 - self.assertNotInitialized(proto) + self.assertNotInitialized(proto, 2) proto.Extensions[extension].b = 2 proto.Extensions[extension].c = 3 self.assertInitialized(proto) @@ -1705,6 +2025,7 @@ def testIsInitialized(self): proto = unittest_pb2.TestRequired() self.assertFalse(proto.IsInitialized(errors)) self.assertEqual(errors, ['a', 'b', 'c']) + self.assertRaises(TypeError, proto.IsInitialized, 1, 2, 3) @unittest.skipIf( api_implementation.Type() != 'cpp' or api_implementation.Version() != 2, @@ -1740,34 +2061,6 @@ def testFileDescriptorErrors(self): # dependency on the C++ logging code. self.assertIn('test_file_descriptor_errors.msg1', str(cm.exception)) - def testStringUTF8Encoding(self): - proto = unittest_pb2.TestAllTypes() - - # Assignment of a unicode object to a field of type 'bytes' is not allowed. - self.assertRaises(TypeError, - setattr, proto, 'optional_bytes', u'unicode object') - - # Check that the default value is of python's 'unicode' type. - self.assertEqual(type(proto.optional_string), six.text_type) - - proto.optional_string = six.text_type('Testing') - self.assertEqual(proto.optional_string, str('Testing')) - - # Assign a value of type 'str' which can be encoded in UTF-8. - proto.optional_string = str('Testing') - self.assertEqual(proto.optional_string, six.text_type('Testing')) - - # Try to assign a 'bytes' object which contains non-UTF-8. - self.assertRaises(ValueError, - setattr, proto, 'optional_string', b'a\x80a') - # No exception: Assign already encoded UTF-8 bytes to a string field. - utf8_bytes = u'Тест'.encode('utf-8') - proto.optional_string = utf8_bytes - # No exception: Assign the a non-ascii unicode object. - proto.optional_string = u'Тест' - # No exception thrown (normal str assignment containing ASCII). - proto.optional_string = 'abc' - def testStringUTF8Serialization(self): proto = message_set_extensions_pb2.TestMessageSet() extension_message = message_set_extensions_pb2.TestMessageSetExtension2 @@ -1822,38 +2115,6 @@ def testStringUTF8Serialization(self): string_field = message2.str self.assertTrue(unicode_decode_failed or type(string_field) is bytes) - def testBytesInTextFormat(self): - proto = unittest_pb2.TestAllTypes(optional_bytes=b'\x00\x7f\x80\xff') - self.assertEqual(u'optional_bytes: "\\000\\177\\200\\377"\n', - six.text_type(proto)) - - def testEmptyNestedMessage(self): - proto = unittest_pb2.TestAllTypes() - proto.optional_nested_message.MergeFrom( - unittest_pb2.TestAllTypes.NestedMessage()) - self.assertTrue(proto.HasField('optional_nested_message')) - - proto = unittest_pb2.TestAllTypes() - proto.optional_nested_message.CopyFrom( - unittest_pb2.TestAllTypes.NestedMessage()) - self.assertTrue(proto.HasField('optional_nested_message')) - - proto = unittest_pb2.TestAllTypes() - bytes_read = proto.optional_nested_message.MergeFromString(b'') - self.assertEqual(0, bytes_read) - self.assertTrue(proto.HasField('optional_nested_message')) - - proto = unittest_pb2.TestAllTypes() - proto.optional_nested_message.ParseFromString(b'') - self.assertTrue(proto.HasField('optional_nested_message')) - - serialized = proto.SerializeToString() - proto2 = unittest_pb2.TestAllTypes() - self.assertEqual( - len(serialized), - proto2.MergeFromString(serialized)) - self.assertTrue(proto2.HasField('optional_nested_message')) - def testSetInParent(self): proto = unittest_pb2.TestAllTypes() self.assertFalse(proto.HasField('optionalgroup')) @@ -1882,7 +2143,8 @@ def testPackageInitializationImport(self): # into separate TestCase classes. -class TestAllTypesEqualityTest(BaseTestCase): +@testing_refleaks.TestCase +class TestAllTypesEqualityTest(unittest.TestCase): def setUp(self): self.first_proto = unittest_pb2.TestAllTypes() @@ -1898,7 +2160,8 @@ def testEmptyProtosEqual(self): self.assertEqual(self.first_proto, self.second_proto) -class FullProtosEqualityTest(BaseTestCase): +@testing_refleaks.TestCase +class FullProtosEqualityTest(unittest.TestCase): """Equality tests using completely-full protos as a starting point.""" @@ -1984,7 +2247,8 @@ def testNonRepeatedCompositeHasBits(self): self.assertEqual(self.first_proto, self.second_proto) -class ExtensionEqualityTest(BaseTestCase): +@testing_refleaks.TestCase +class ExtensionEqualityTest(unittest.TestCase): def testExtensionEquality(self): first_proto = unittest_pb2.TestAllExtensions() @@ -2017,7 +2281,8 @@ def testExtensionEquality(self): self.assertEqual(first_proto, second_proto) -class MutualRecursionEqualityTest(BaseTestCase): +@testing_refleaks.TestCase +class MutualRecursionEqualityTest(unittest.TestCase): def testEqualityWithMutualRecursion(self): first_proto = unittest_pb2.TestMutualRecursionA() @@ -2029,7 +2294,8 @@ def testEqualityWithMutualRecursion(self): self.assertEqual(first_proto, second_proto) -class ByteSizeTest(BaseTestCase): +@testing_refleaks.TestCase +class ByteSizeTest(unittest.TestCase): def setUp(self): self.proto = unittest_pb2.TestAllTypes() @@ -2154,6 +2420,8 @@ def testRepeatedCompositesDelete(self): foreign_message_1 = self.proto.repeated_nested_message.add() foreign_message_1.bb = 9 self.assertEqual(2 + 1 + 2 + 1 + 1 + 1, self.Size()) + repeated_nested_message = copy.deepcopy( + self.proto.repeated_nested_message) # 2 bytes tag plus 1 byte length plus 1 byte bb tag 1 byte int. del self.proto.repeated_nested_message[0] @@ -2174,6 +2442,16 @@ def testRepeatedCompositesDelete(self): del self.proto.repeated_nested_message[0] self.assertEqual(0, self.Size()) + self.assertEqual(2, len(repeated_nested_message)) + del repeated_nested_message[0:1] + # TODO(jieluo): Fix cpp extension bug when delete repeated message. + if api_implementation.Type() == 'python': + self.assertEqual(1, len(repeated_nested_message)) + del repeated_nested_message[-1] + # TODO(jieluo): Fix cpp extension bug when delete repeated message. + if api_implementation.Type() == 'python': + self.assertEqual(0, len(repeated_nested_message)) + def testRepeatedGroups(self): # 2-byte START_GROUP plus 2-byte END_GROUP. group_0 = self.proto.repeatedgroup.add() @@ -2190,6 +2468,10 @@ def testExtensions(self): proto.Extensions[extension] = 23 # 1 byte for tag, 1 byte for value. self.assertEqual(2, proto.ByteSize()) + field = unittest_pb2.TestAllTypes.DESCRIPTOR.fields_by_name[ + 'optional_int32'] + with self.assertRaises(KeyError): + proto.Extensions[field] = 23 def testCacheInvalidationForNonrepeatedScalar(self): # Test non-extension. @@ -2325,7 +2607,8 @@ def testPackedExtensions(self): # * Handling of empty submessages (with and without "has" # bits set). -class SerializationTest(BaseTestCase): +@testing_refleaks.TestCase +class SerializationTest(unittest.TestCase): def testSerializeEmtpyMessage(self): first_proto = unittest_pb2.TestAllTypes() @@ -2390,7 +2673,7 @@ def testParseTruncated(self): first_proto = unittest_pb2.TestAllTypes() test_util.SetAllFields(first_proto) - serialized = first_proto.SerializeToString() + serialized = memoryview(first_proto.SerializeToString()) for truncation_point in range(len(serialized) + 1): try: @@ -2591,7 +2874,7 @@ def testUnknownFields(self): proto2.MergeFromString(serialized)) def _CheckRaises(self, exc_class, callable_obj, exception): - """This method checks if the excpetion type and message are as expected.""" + """This method checks if the exception type and message are as expected.""" try: callable_obj() except exc_class as ex: @@ -2812,6 +3095,38 @@ def testExtensionFieldNumbers(self): self.assertEqual(unittest_pb2.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 51) + def testFieldProperties(self): + cls = unittest_pb2.TestAllTypes + self.assertIs(cls.optional_int32.DESCRIPTOR, + cls.DESCRIPTOR.fields_by_name['optional_int32']) + self.assertEqual(cls.OPTIONAL_INT32_FIELD_NUMBER, + cls.optional_int32.DESCRIPTOR.number) + self.assertIs(cls.optional_nested_message.DESCRIPTOR, + cls.DESCRIPTOR.fields_by_name['optional_nested_message']) + self.assertEqual(cls.OPTIONAL_NESTED_MESSAGE_FIELD_NUMBER, + cls.optional_nested_message.DESCRIPTOR.number) + self.assertIs(cls.repeated_int32.DESCRIPTOR, + cls.DESCRIPTOR.fields_by_name['repeated_int32']) + self.assertEqual(cls.REPEATED_INT32_FIELD_NUMBER, + cls.repeated_int32.DESCRIPTOR.number) + + def testFieldDataDescriptor(self): + msg = unittest_pb2.TestAllTypes() + msg.optional_int32 = 42 + self.assertEqual(unittest_pb2.TestAllTypes.optional_int32.__get__(msg), 42) + unittest_pb2.TestAllTypes.optional_int32.__set__(msg, 25) + self.assertEqual(msg.optional_int32, 25) + with self.assertRaises(AttributeError): + del msg.optional_int32 + try: + unittest_pb2.ForeignMessage.c.__get__(msg) + except TypeError: + pass # The cpp implementation cannot mix fields from other messages. + # This test exercises a specific check that avoids a crash. + else: + pass # The python implementation allows fields from other messages. + # This is useless, but works. + def testInitKwargs(self): proto = unittest_pb2.TestAllTypes( optional_int32=1, @@ -2857,7 +3172,7 @@ def testInitRequiredKwargs(self): self.assertTrue(proto.HasField('a')) self.assertTrue(proto.HasField('b')) self.assertTrue(proto.HasField('c')) - self.assertTrue(not proto.HasField('dummy2')) + self.assertFalse(proto.HasField('dummy2')) self.assertEqual(1, proto.a) self.assertEqual(1, proto.b) self.assertEqual(1, proto.c) @@ -2871,7 +3186,7 @@ def testInitRequiredForeignKwargs(self): self.assertTrue(proto.optional_message.HasField('a')) self.assertTrue(proto.optional_message.HasField('b')) self.assertTrue(proto.optional_message.HasField('c')) - self.assertTrue(not proto.optional_message.HasField('dummy2')) + self.assertFalse(proto.optional_message.HasField('dummy2')) self.assertEqual(unittest_pb2.TestRequired(a=1, b=1, c=1), proto.optional_message) self.assertEqual(1, proto.optional_message.a) @@ -2886,7 +3201,8 @@ def testInitRepeatedKwargs(self): self.assertEqual(3, proto.repeated_int32[2]) -class OptionsTest(BaseTestCase): +@testing_refleaks.TestCase +class OptionsTest(unittest.TestCase): def testMessageOptions(self): proto = message_set_extensions_pb2.TestMessageSet() @@ -2913,32 +3229,43 @@ def testPackedOptions(self): -class ClassAPITest(BaseTestCase): +@testing_refleaks.TestCase +class ClassAPITest(unittest.TestCase): @unittest.skipIf( api_implementation.Type() == 'cpp' and api_implementation.Version() == 2, 'C++ implementation requires a call to MakeDescriptor()') + @testing_refleaks.SkipReferenceLeakChecker('MakeClass is not repeatable') def testMakeClassWithNestedDescriptor(self): - leaf_desc = descriptor.Descriptor('leaf', 'package.parent.child.leaf', '', - containing_type=None, fields=[], - nested_types=[], enum_types=[], - extensions=[]) - child_desc = descriptor.Descriptor('child', 'package.parent.child', '', - containing_type=None, fields=[], - nested_types=[leaf_desc], enum_types=[], - extensions=[]) - sibling_desc = descriptor.Descriptor('sibling', 'package.parent.sibling', - '', containing_type=None, fields=[], - nested_types=[], enum_types=[], - extensions=[]) - parent_desc = descriptor.Descriptor('parent', 'package.parent', '', - containing_type=None, fields=[], - nested_types=[child_desc, sibling_desc], - enum_types=[], extensions=[]) - message_class = reflection.MakeClass(parent_desc) - self.assertIn('child', message_class.__dict__) - self.assertIn('sibling', message_class.__dict__) - self.assertIn('leaf', message_class.child.__dict__) + leaf_desc = descriptor.Descriptor( + 'leaf', 'package.parent.child.leaf', '', + containing_type=None, fields=[], + nested_types=[], enum_types=[], + extensions=[], + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) + child_desc = descriptor.Descriptor( + 'child', 'package.parent.child', '', + containing_type=None, fields=[], + nested_types=[leaf_desc], enum_types=[], + extensions=[], + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) + sibling_desc = descriptor.Descriptor( + 'sibling', 'package.parent.sibling', + '', containing_type=None, fields=[], + nested_types=[], enum_types=[], + extensions=[], + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) + parent_desc = descriptor.Descriptor( + 'parent', 'package.parent', '', + containing_type=None, fields=[], + nested_types=[child_desc, sibling_desc], + enum_types=[], extensions=[], + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) + reflection.MakeClass(parent_desc) def _GetSerializedFileDescriptor(self, name): """Get a serialized representation of a test FileDescriptorProto. @@ -3001,7 +3328,7 @@ def _GetSerializedFileDescriptor(self, name): # conflicting message descriptors. def testParsingFlatClassWithExplicitClassDeclaration(self): """Test that the generated class can parse a flat message.""" - # TODO(xiaofeng): This test fails with cpp implemetnation in the call + # TODO(xiaofeng): This test fails with cpp implementation in the call # of six.with_metaclass(). The other two callsites of with_metaclass # in this file are both excluded from cpp test, so it might be expected # to fail. Need someone more familiar with the python code to take a diff --git a/python/google/protobuf/internal/service_reflection_test.py b/python/google/protobuf/internal/service_reflection_test.py index 62900b1d153ab..77239f4462621 100755 --- a/python/google/protobuf/internal/service_reflection_test.py +++ b/python/google/protobuf/internal/service_reflection_test.py @@ -82,6 +82,10 @@ def MyCallback(response): service_descriptor = unittest_pb2.TestService.GetDescriptor() srvc.CallMethod(service_descriptor.methods[1], rpc_controller, unittest_pb2.BarRequest(), MyCallback) + self.assertTrue(srvc.GetRequestClass(service_descriptor.methods[1]) is + unittest_pb2.BarRequest) + self.assertTrue(srvc.GetResponseClass(service_descriptor.methods[1]) is + unittest_pb2.BarResponse) self.assertEqual('Method Bar not implemented.', rpc_controller.failure_message) self.assertEqual(None, self.callback_response) diff --git a/python/google/protobuf/internal/symbol_database_test.py b/python/google/protobuf/internal/symbol_database_test.py old mode 100644 new mode 100755 diff --git a/python/google/protobuf/internal/test_bad_identifiers.proto b/python/google/protobuf/internal/test_bad_identifiers.proto index c4860ea88a22e..caf86b5f29e29 100644 --- a/python/google/protobuf/internal/test_bad_identifiers.proto +++ b/python/google/protobuf/internal/test_bad_identifiers.proto @@ -43,10 +43,10 @@ message TestBadIdentifiers { // Make sure these reasonable extension names don't conflict with internal // variables. extend TestBadIdentifiers { - optional string message = 100 [default="foo"]; - optional string descriptor = 101 [default="bar"]; - optional string reflection = 102 [default="baz"]; - optional string service = 103 [default="qux"]; + optional string message = 100 [default = "foo"]; + optional string descriptor = 101 [default = "bar"]; + optional string reflection = 102 [default = "baz"]; + optional string service = 103 [default = "qux"]; } message AnotherMessage {} diff --git a/python/google/protobuf/internal/test_proto3_optional.proto b/python/google/protobuf/internal/test_proto3_optional.proto new file mode 100644 index 0000000000000..f3e0a2e761cd4 --- /dev/null +++ b/python/google/protobuf/internal/test_proto3_optional.proto @@ -0,0 +1,70 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf.python.internal; + +message TestProto3Optional { + message NestedMessage { + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + optional int32 bb = 1; + } + + enum NestedEnum { + UNSPECIFIED = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + optional int32 optional_int32 = 1; + optional int64 optional_int64 = 2; + optional uint32 optional_uint32 = 3; + optional uint64 optional_uint64 = 4; + optional sint32 optional_sint32 = 5; + optional sint64 optional_sint64 = 6; + optional fixed32 optional_fixed32 = 7; + optional fixed64 optional_fixed64 = 8; + optional sfixed32 optional_sfixed32 = 9; + optional sfixed64 optional_sfixed64 = 10; + optional float optional_float = 11; + optional double optional_double = 12; + optional bool optional_bool = 13; + optional string optional_string = 14; + optional bytes optional_bytes = 15; + + optional NestedMessage optional_nested_message = 18; + optional NestedEnum optional_nested_enum = 21; +} diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py old mode 100755 new mode 100644 index 269d0e2d4f72c..a6e34ef56d7ee --- a/python/google/protobuf/internal/test_util.py +++ b/python/google/protobuf/internal/test_util.py @@ -39,11 +39,15 @@ import numbers import operator import os.path -import sys from google.protobuf import unittest_import_pb2 from google.protobuf import unittest_pb2 -from google.protobuf import descriptor_pb2 + +try: + long # Python 2 +except NameError: + long = int # Python 3 + # Tests whether the given TestAllTypes message is proto2 or not. # This is used to gate several fields/features that only exist @@ -51,6 +55,7 @@ def IsProto2(message): return message.DESCRIPTOR.syntax == "proto2" + def SetAllNonLazyFields(message): """Sets every non-lazy field in the message to a unique value. @@ -128,22 +133,37 @@ def SetAllNonLazyFields(message): message.repeated_string_piece.append(u'224') message.repeated_cord.append(u'225') - # Add a second one of each field. - message.repeated_int32.append(301) - message.repeated_int64.append(302) - message.repeated_uint32.append(303) - message.repeated_uint64.append(304) - message.repeated_sint32.append(305) - message.repeated_sint64.append(306) - message.repeated_fixed32.append(307) - message.repeated_fixed64.append(308) - message.repeated_sfixed32.append(309) - message.repeated_sfixed64.append(310) - message.repeated_float.append(311) - message.repeated_double.append(312) - message.repeated_bool.append(False) - message.repeated_string.append(u'315') - message.repeated_bytes.append(b'316') + # Add a second one of each field and set value by index. + message.repeated_int32.append(0) + message.repeated_int64.append(0) + message.repeated_uint32.append(0) + message.repeated_uint64.append(0) + message.repeated_sint32.append(0) + message.repeated_sint64.append(0) + message.repeated_fixed32.append(0) + message.repeated_fixed64.append(0) + message.repeated_sfixed32.append(0) + message.repeated_sfixed64.append(0) + message.repeated_float.append(0) + message.repeated_double.append(0) + message.repeated_bool.append(True) + message.repeated_string.append(u'0') + message.repeated_bytes.append(b'0') + message.repeated_int32[1] = 301 + message.repeated_int64[1] = 302 + message.repeated_uint32[1] = 303 + message.repeated_uint64[1] = 304 + message.repeated_sint32[1] = 305 + message.repeated_sint64[1] = 306 + message.repeated_fixed32[1] = 307 + message.repeated_fixed64[1] = 308 + message.repeated_sfixed32[1] = 309 + message.repeated_sfixed64[1] = 310 + message.repeated_float[1] = 311 + message.repeated_double[1] = 312 + message.repeated_bool[1] = False + message.repeated_string[1] = u'315' + message.repeated_bytes[1] = b'316' if IsProto2(message): message.repeatedgroup.add().a = 317 @@ -152,7 +172,8 @@ def SetAllNonLazyFields(message): message.repeated_import_message.add().d = 320 message.repeated_lazy_message.add().bb = 327 - message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAZ) + message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAR) + message.repeated_nested_enum[1] = unittest_pb2.TestAllTypes.BAZ message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAZ) if IsProto2(message): message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAZ) @@ -707,8 +728,8 @@ class NonStandardInteger(numbers.Integral): NonStandardInteger is the minimal legal specification for a custom Integral. As such, it does not support 0 < x < 5 and it is not hashable. - Note: This is added here instead of relying on numpy or a similar library with - custom integers to limit dependencies. + Note: This is added here instead of relying on numpy or a similar library + with custom integers to limit dependencies. """ def __init__(self, val, error_string_on_conversion=None): @@ -845,4 +866,3 @@ def __round__(self): def __repr__(self): return 'NonStandardInteger(%s)' % self.val - diff --git a/python/google/protobuf/internal/testing_refleaks.py b/python/google/protobuf/internal/testing_refleaks.py index 8ce06519bc7c0..e448fceef454a 100644 --- a/python/google/protobuf/internal/testing_refleaks.py +++ b/python/google/protobuf/internal/testing_refleaks.py @@ -69,8 +69,8 @@ def addSkip(self, test, reason): pass -class ReferenceLeakCheckerTestCase(unittest.TestCase): - """A TestCase which runs tests multiple times, collecting reference counts.""" +class ReferenceLeakCheckerMixin(object): + """A mixin class for TestCase, which checks reference counts.""" NB_RUNS = 3 @@ -81,8 +81,8 @@ def run(self, result=None): self._saved_pickle_registry = copyreg.dispatch_table.copy() # Run the test twice, to warm up the instance attributes. - super(ReferenceLeakCheckerTestCase, self).run(result=result) - super(ReferenceLeakCheckerTestCase, self).run(result=result) + super(ReferenceLeakCheckerMixin, self).run(result=result) + super(ReferenceLeakCheckerMixin, self).run(result=result) oldrefcount = 0 local_result = LocalTestResult(result) @@ -90,7 +90,7 @@ def run(self, result=None): refcount_deltas = [] for _ in range(self.NB_RUNS): oldrefcount = self._getRefcounts() - super(ReferenceLeakCheckerTestCase, self).run(result=local_result) + super(ReferenceLeakCheckerMixin, self).run(result=local_result) newrefcount = self._getRefcounts() refcount_deltas.append(newrefcount - oldrefcount) print(refcount_deltas, self) @@ -112,12 +112,19 @@ def _getRefcounts(self): if hasattr(sys, 'gettotalrefcount'): - BaseTestCase = ReferenceLeakCheckerTestCase + + def TestCase(test_class): + new_bases = (ReferenceLeakCheckerMixin,) + test_class.__bases__ + new_class = type(test_class)( + test_class.__name__, new_bases, dict(test_class.__dict__)) + return new_class SkipReferenceLeakChecker = unittest.skip else: # When PyDEBUG is not enabled, run the tests normally. - BaseTestCase = unittest.TestCase + + def TestCase(test_class): + return test_class def SkipReferenceLeakChecker(reason): del reason # Don't skip, so don't need a reason. diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py index 424b29ccb5062..987116a1061e6 100755 --- a/python/google/protobuf/internal/text_format_test.py +++ b/python/google/protobuf/internal/text_format_test.py @@ -1,4 +1,5 @@ #! /usr/bin/env python +# -*- coding: utf-8 -*- # # Protocol Buffers - Google's data interchange format # Copyright 2008 Google Inc. All rights reserved. @@ -32,31 +33,36 @@ """Test for google.protobuf.text_format.""" -__author__ = 'kenton@google.com (Kenton Varda)' - - +import io +import math import re -import six import string +import textwrap + +import six +# pylint: disable=g-import-not-at-top try: - import unittest2 as unittest # PY26, pylint: disable=g-import-not-at-top + import unittest2 as unittest # PY26 except ImportError: - import unittest # pylint: disable=g-import-not-at-top - -from google.protobuf.internal import _parameterized + import unittest +from google.protobuf import any_pb2 from google.protobuf import any_test_pb2 from google.protobuf import map_unittest_pb2 +from google.protobuf import unittest_custom_options_pb2 from google.protobuf import unittest_mset_pb2 from google.protobuf import unittest_pb2 from google.protobuf import unittest_proto3_arena_pb2 -from google.protobuf.internal import api_implementation +from google.protobuf import descriptor_pb2 from google.protobuf.internal import any_test_pb2 as test_extend_any -from google.protobuf.internal import test_util from google.protobuf.internal import message_set_extensions_pb2 +from google.protobuf.internal import test_proto3_optional_pb2 +from google.protobuf.internal import test_util from google.protobuf import descriptor_pool from google.protobuf import text_format +from google.protobuf.internal import _parameterized +# pylint: enable=g-import-not-at-top # Low-level nuts-n-bolts tests. @@ -92,13 +98,13 @@ def RemoveRedundantZeros(self, text): text = text.replace('e+0','e+').replace('e+0','e+') \ .replace('e-0','e-').replace('e-0','e-') # Floating point fields are printed with .0 suffix even if they are - # actualy integer numbers. + # actually integer numbers. text = re.compile(r'\.0$', re.MULTILINE).sub('', text) return text -@_parameterized.Parameters((unittest_pb2), (unittest_proto3_arena_pb2)) -class TextFormatTest(TextFormatBase): +@_parameterized.parameters(unittest_pb2, unittest_proto3_arena_pb2) +class TextFormatMessageToStringTests(TextFormatBase): def testPrintExotic(self, message_module): message = message_module.TestAllTypes() @@ -120,6 +126,114 @@ def testPrintExotic(self, message_module): ' "\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n' 'repeated_string: "\\303\\274\\352\\234\\237"\n') + def testPrintFloatPrecision(self, message_module): + message = message_module.TestAllTypes() + + message.repeated_float.append(0.0) + message.repeated_float.append(0.8) + message.repeated_float.append(1.0) + message.repeated_float.append(1.2) + message.repeated_float.append(1.23) + message.repeated_float.append(1.234) + message.repeated_float.append(1.2345) + message.repeated_float.append(1.23456) + message.repeated_float.append(1.2e10) + message.repeated_float.append(1.23e10) + message.repeated_float.append(1.234e10) + message.repeated_float.append(1.2345e10) + message.repeated_float.append(1.23456e10) + message.repeated_float.append(float('NaN')) + message.repeated_float.append(float('inf')) + message.repeated_double.append(0.0) + message.repeated_double.append(0.8) + message.repeated_double.append(1.0) + message.repeated_double.append(1.2) + message.repeated_double.append(1.23) + message.repeated_double.append(1.234) + message.repeated_double.append(1.2345) + message.repeated_double.append(1.23456) + message.repeated_double.append(1.234567) + message.repeated_double.append(1.2345678) + message.repeated_double.append(1.23456789) + message.repeated_double.append(1.234567898) + message.repeated_double.append(1.2345678987) + message.repeated_double.append(1.23456789876) + message.repeated_double.append(1.234567898765) + message.repeated_double.append(1.2345678987654) + message.repeated_double.append(1.23456789876543) + message.repeated_double.append(1.2e100) + message.repeated_double.append(1.23e100) + message.repeated_double.append(1.234e100) + message.repeated_double.append(1.2345e100) + message.repeated_double.append(1.23456e100) + message.repeated_double.append(1.234567e100) + message.repeated_double.append(1.2345678e100) + message.repeated_double.append(1.23456789e100) + message.repeated_double.append(1.234567898e100) + message.repeated_double.append(1.2345678987e100) + message.repeated_double.append(1.23456789876e100) + message.repeated_double.append(1.234567898765e100) + message.repeated_double.append(1.2345678987654e100) + message.repeated_double.append(1.23456789876543e100) + # pylint: disable=g-long-ternary + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_format.MessageToString(message)), + 'repeated_float: 0\n' + 'repeated_float: 0.8\n' + 'repeated_float: 1\n' + 'repeated_float: 1.2\n' + 'repeated_float: 1.23\n' + 'repeated_float: 1.234\n' + 'repeated_float: 1.2345\n' + 'repeated_float: 1.23456\n' + # Note that these don't use scientific notation. + 'repeated_float: 12000000000\n' + 'repeated_float: 12300000000\n' + 'repeated_float: 12340000000\n' + 'repeated_float: 12345000000\n' + 'repeated_float: 12345600000\n' + 'repeated_float: nan\n' + 'repeated_float: inf\n' + 'repeated_double: 0\n' + 'repeated_double: 0.8\n' + 'repeated_double: 1\n' + 'repeated_double: 1.2\n' + 'repeated_double: 1.23\n' + 'repeated_double: 1.234\n' + 'repeated_double: 1.2345\n' + 'repeated_double: 1.23456\n' + 'repeated_double: 1.234567\n' + 'repeated_double: 1.2345678\n' + 'repeated_double: 1.23456789\n' + 'repeated_double: 1.234567898\n' + 'repeated_double: 1.2345678987\n' + 'repeated_double: 1.23456789876\n' + + ('repeated_double: 1.23456789876\n' + 'repeated_double: 1.23456789877\n' + 'repeated_double: 1.23456789877\n' + if six.PY2 else + 'repeated_double: 1.234567898765\n' + 'repeated_double: 1.2345678987654\n' + 'repeated_double: 1.23456789876543\n') + + 'repeated_double: 1.2e+100\n' + 'repeated_double: 1.23e+100\n' + 'repeated_double: 1.234e+100\n' + 'repeated_double: 1.2345e+100\n' + 'repeated_double: 1.23456e+100\n' + 'repeated_double: 1.234567e+100\n' + 'repeated_double: 1.2345678e+100\n' + 'repeated_double: 1.23456789e+100\n' + 'repeated_double: 1.234567898e+100\n' + 'repeated_double: 1.2345678987e+100\n' + 'repeated_double: 1.23456789876e+100\n' + + ('repeated_double: 1.23456789877e+100\n' + 'repeated_double: 1.23456789877e+100\n' + 'repeated_double: 1.23456789877e+100\n' + if six.PY2 else + 'repeated_double: 1.234567898765e+100\n' + 'repeated_double: 1.2345678987654e+100\n' + 'repeated_double: 1.23456789876543e+100\n')) + def testPrintExoticUnicodeSubclass(self, message_module): class UnicodeSub(six.text_type): @@ -151,6 +265,43 @@ def testPrintRepeatedFieldsAsOneLine(self, message_module): 'repeated_int32: 1 repeated_int32: 1 repeated_int32: 3 ' 'repeated_string: "Google" repeated_string: "Zurich"') + def VerifyPrintShortFormatRepeatedFields(self, message_module, as_one_line): + message = message_module.TestAllTypes() + message.repeated_int32.append(1) + message.repeated_string.append('Google') + message.repeated_string.append('Hello,World') + message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_FOO) + message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAR) + message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAZ) + message.optional_nested_message.bb = 3 + for i in (21, 32): + msg = message.repeated_nested_message.add() + msg.bb = i + expected_ascii = ( + 'optional_nested_message {\n bb: 3\n}\n' + 'repeated_int32: [1]\n' + 'repeated_string: "Google"\n' + 'repeated_string: "Hello,World"\n' + 'repeated_nested_message {\n bb: 21\n}\n' + 'repeated_nested_message {\n bb: 32\n}\n' + 'repeated_foreign_enum: [FOREIGN_FOO, FOREIGN_BAR, FOREIGN_BAZ]\n') + if as_one_line: + expected_ascii = expected_ascii.replace('\n', ' ') + expected_ascii = re.sub(r'\s+', ' ', expected_ascii) + expected_ascii = re.sub(r'\s$', '', expected_ascii) + + actual_ascii = text_format.MessageToString( + message, use_short_repeated_primitives=True, + as_one_line=as_one_line) + self.CompareToGoldenText(actual_ascii, expected_ascii) + parsed_message = message_module.TestAllTypes() + text_format.Parse(actual_ascii, parsed_message) + self.assertEqual(parsed_message, message) + + def testPrintShortFormatRepeatedFields(self, message_module): + self.VerifyPrintShortFormatRepeatedFields(message_module, False) + self.VerifyPrintShortFormatRepeatedFields(message_module, True) + def testPrintNestedNewLineInStringAsOneLine(self, message_module): message = message_module.TestAllTypes() message.optional_string = 'a\nnew\nline' @@ -210,24 +361,22 @@ def testRoundTripExoticAsOneLine(self, message_module): def testPrintRawUtf8String(self, message_module): message = message_module.TestAllTypes() - message.repeated_string.append(u'\u00fc\ua71f') + message.repeated_string.append(u'\u00fc\t\ua71f') text = text_format.MessageToString(message, as_utf8=True) - self.CompareToGoldenText(text, 'repeated_string: "\303\274\352\234\237"\n') + golden_unicode = u'repeated_string: "\u00fc\\t\ua71f"\n' + golden_text = golden_unicode if six.PY3 else golden_unicode.encode('utf-8') + # MessageToString always returns a native str. + self.CompareToGoldenText(text, golden_text) parsed_message = message_module.TestAllTypes() text_format.Parse(text, parsed_message) - self.assertEqual(message, parsed_message, - '\n%s != %s' % (message, parsed_message)) + self.assertEqual( + message, parsed_message, '\n%s != %s (%s != %s)' % + (message, parsed_message, message.repeated_string[0], + parsed_message.repeated_string[0])) def testPrintFloatFormat(self, message_module): # Check that float_format argument is passed to sub-message formatting. message = message_module.NestedTestAllTypes() - # We use 1.25 as it is a round number in binary. The proto 32-bit float - # will not gain additional imprecise digits as a 64-bit Python float and - # show up in its str. 32-bit 1.2 is noisy when extended to 64-bit: - # >>> struct.unpack('f', struct.pack('f', 1.2))[0] - # 1.2000000476837158 - # >>> struct.unpack('f', struct.pack('f', 1.25))[0] - # 1.25 message.payload.optional_float = 1.25 # Check rounding at 15 significant digits message.payload.optional_double = -.000003456789012345678 @@ -251,11 +400,88 @@ def testPrintFloatFormat(self, message_module): self.RemoveRedundantZeros(text_message), 'payload {{ {0} {1} {2} {3} }}'.format(*formatted_fields)) + # 32-bit 1.2 is noisy when extended to 64-bit: + # >>> struct.unpack('f', struct.pack('f', 1.2))[0] + # 1.2000000476837158 + message.payload.optional_float = 1.2 + formatted_fields = ['optional_float: 1.2', + 'optional_double: -3.45678901234568e-6', + 'repeated_float: -5642', 'repeated_double: 7.89e-5'] + text_message = text_format.MessageToString(message, float_format='.7g', + double_format='.15g') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_message), + 'payload {{\n {0}\n {1}\n {2}\n {3}\n}}\n'.format( + *formatted_fields)) + + # Test only set float_format affect both float and double fields. + formatted_fields = ['optional_float: 1.2', + 'optional_double: -3.456789e-6', + 'repeated_float: -5642', 'repeated_double: 7.89e-5'] + text_message = text_format.MessageToString(message, float_format='.7g') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_message), + 'payload {{\n {0}\n {1}\n {2}\n {3}\n}}\n'.format( + *formatted_fields)) + + # Test default float_format will automatic print shortest float. + message.payload.optional_float = 1.2345678912 + message.payload.optional_double = 1.2345678912 + formatted_fields = ['optional_float: 1.2345679', + 'optional_double: 1.2345678912', + 'repeated_float: -5642', 'repeated_double: 7.89e-5'] + text_message = text_format.MessageToString(message) + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_message), + 'payload {{\n {0}\n {1}\n {2}\n {3}\n}}\n'.format( + *formatted_fields)) + + message.Clear() + message.payload.optional_float = 1.1000000000011 + self.assertEqual(text_format.MessageToString(message), + 'payload {\n optional_float: 1.1\n}\n') + message.payload.optional_float = 1.00000075e-36 + self.assertEqual(text_format.MessageToString(message), + 'payload {\n optional_float: 1.00000075e-36\n}\n') + message.payload.optional_float = 12345678912345e+11 + self.assertEqual(text_format.MessageToString(message), + 'payload {\n optional_float: 1.234568e+24\n}\n') + def testMessageToString(self, message_module): message = message_module.ForeignMessage() message.c = 123 self.assertEqual('c: 123\n', str(message)) + def testMessageToStringUnicode(self, message_module): + golden_unicode = u'Á short desçription and a 🍌.' + golden_bytes = golden_unicode.encode('utf-8') + message = message_module.TestAllTypes() + message.optional_string = golden_unicode + message.optional_bytes = golden_bytes + text = text_format.MessageToString(message, as_utf8=True) + golden_message = textwrap.dedent( + 'optional_string: "Á short desçription and a 🍌."\n' + 'optional_bytes: ' + r'"\303\201 short des\303\247ription and a \360\237\215\214."' + '\n') + self.CompareToGoldenText(text, golden_message) + + def testMessageToStringASCII(self, message_module): + golden_unicode = u'Á short desçription and a 🍌.' + golden_bytes = golden_unicode.encode('utf-8') + message = message_module.TestAllTypes() + message.optional_string = golden_unicode + message.optional_bytes = golden_bytes + text = text_format.MessageToString(message, as_utf8=False) # ASCII + golden_message = ( + 'optional_string: ' + r'"\303\201 short des\303\247ription and a \360\237\215\214."' + '\n' + 'optional_bytes: ' + r'"\303\201 short des\303\247ription and a \360\237\215\214."' + '\n') + self.CompareToGoldenText(text, golden_message) + def testPrintField(self, message_module): message = message_module.TestAllTypes() field = message.DESCRIPTOR.fields_by_name['optional_float'] @@ -286,6 +512,142 @@ def testPrintFieldValue(self, message_module): self.assertEqual('0.0', out.getvalue()) out.close() + def testCustomOptions(self, message_module): + message_descriptor = (unittest_custom_options_pb2. + TestMessageWithCustomOptions.DESCRIPTOR) + message_proto = descriptor_pb2.DescriptorProto() + message_descriptor.CopyToProto(message_proto) + expected_text = ( + 'name: "TestMessageWithCustomOptions"\n' + 'field {\n' + ' name: "field1"\n' + ' number: 1\n' + ' label: LABEL_OPTIONAL\n' + ' type: TYPE_STRING\n' + ' options {\n' + ' ctype: CORD\n' + ' [protobuf_unittest.field_opt1]: 8765432109\n' + ' }\n' + '}\n' + 'field {\n' + ' name: "oneof_field"\n' + ' number: 2\n' + ' label: LABEL_OPTIONAL\n' + ' type: TYPE_INT32\n' + ' oneof_index: 0\n' + '}\n' + 'enum_type {\n' + ' name: "AnEnum"\n' + ' value {\n' + ' name: "ANENUM_VAL1"\n' + ' number: 1\n' + ' }\n' + ' value {\n' + ' name: "ANENUM_VAL2"\n' + ' number: 2\n' + ' options {\n' + ' [protobuf_unittest.enum_value_opt1]: 123\n' + ' }\n' + ' }\n' + ' options {\n' + ' [protobuf_unittest.enum_opt1]: -789\n' + ' }\n' + '}\n' + 'options {\n' + ' message_set_wire_format: false\n' + ' [protobuf_unittest.message_opt1]: -56\n' + '}\n' + 'oneof_decl {\n' + ' name: "AnOneof"\n' + ' options {\n' + ' [protobuf_unittest.oneof_opt1]: -99\n' + ' }\n' + '}\n') + self.assertEqual(expected_text, + text_format.MessageToString(message_proto)) + parsed_proto = descriptor_pb2.DescriptorProto() + text_format.Parse(expected_text, parsed_proto) + self.assertEqual(message_proto, parsed_proto) + + def testPrintUnknownFieldsEmbeddedMessageInBytes(self, message_module): + inner_msg = message_module.TestAllTypes() + inner_msg.optional_int32 = 101 + inner_msg.optional_double = 102.0 + inner_msg.optional_string = u'hello' + inner_msg.optional_bytes = b'103' + inner_msg.optional_nested_message.bb = 105 + inner_data = inner_msg.SerializeToString() + outer_message = message_module.TestAllTypes() + outer_message.optional_int32 = 101 + outer_message.optional_bytes = inner_data + all_data = outer_message.SerializeToString() + empty_message = message_module.TestEmptyMessage() + empty_message.ParseFromString(all_data) + + self.assertEqual(' 1: 101\n' + ' 15 {\n' + ' 1: 101\n' + ' 12: 4636878028842991616\n' + ' 14: "hello"\n' + ' 15: "103"\n' + ' 18 {\n' + ' 1: 105\n' + ' }\n' + ' }\n', + text_format.MessageToString(empty_message, + indent=2, + print_unknown_fields=True)) + self.assertEqual('1: 101 ' + '15 { ' + '1: 101 ' + '12: 4636878028842991616 ' + '14: "hello" ' + '15: "103" ' + '18 { 1: 105 } ' + '}', + text_format.MessageToString(empty_message, + print_unknown_fields=True, + as_one_line=True)) + + +@_parameterized.parameters(unittest_pb2, unittest_proto3_arena_pb2) +class TextFormatMessageToTextBytesTests(TextFormatBase): + + def testMessageToBytes(self, message_module): + message = message_module.ForeignMessage() + message.c = 123 + self.assertEqual(b'c: 123\n', text_format.MessageToBytes(message)) + + def testRawUtf8RoundTrip(self, message_module): + message = message_module.TestAllTypes() + message.repeated_string.append(u'\u00fc\t\ua71f') + utf8_text = text_format.MessageToBytes(message, as_utf8=True) + golden_bytes = b'repeated_string: "\xc3\xbc\\t\xea\x9c\x9f"\n' + self.CompareToGoldenText(utf8_text, golden_bytes) + parsed_message = message_module.TestAllTypes() + text_format.Parse(utf8_text, parsed_message) + self.assertEqual( + message, parsed_message, '\n%s != %s (%s != %s)' % + (message, parsed_message, message.repeated_string[0], + parsed_message.repeated_string[0])) + + def testEscapedUtf8ASCIIRoundTrip(self, message_module): + message = message_module.TestAllTypes() + message.repeated_string.append(u'\u00fc\t\ua71f') + ascii_text = text_format.MessageToBytes(message) # as_utf8=False default + golden_bytes = b'repeated_string: "\\303\\274\\t\\352\\234\\237"\n' + self.CompareToGoldenText(ascii_text, golden_bytes) + parsed_message = message_module.TestAllTypes() + text_format.Parse(ascii_text, parsed_message) + self.assertEqual( + message, parsed_message, '\n%s != %s (%s != %s)' % + (message, parsed_message, message.repeated_string[0], + parsed_message.repeated_string[0])) + + +@_parameterized.parameters(unittest_pb2, unittest_proto3_arena_pb2) +class TextFormatParserTests(TextFormatBase): + def testParseAllFields(self, message_module): message = message_module.TestAllTypes() test_util.SetAllFields(message) @@ -297,6 +659,41 @@ def testParseAllFields(self, message_module): if message_module is unittest_pb2: test_util.ExpectAllFieldsSet(self, message) + def testParseAndMergeUtf8(self, message_module): + message = message_module.TestAllTypes() + test_util.SetAllFields(message) + ascii_text = text_format.MessageToString(message) + ascii_text = ascii_text.encode('utf-8') + + parsed_message = message_module.TestAllTypes() + text_format.Parse(ascii_text, parsed_message) + self.assertEqual(message, parsed_message) + if message_module is unittest_pb2: + test_util.ExpectAllFieldsSet(self, message) + + parsed_message.Clear() + text_format.Merge(ascii_text, parsed_message) + self.assertEqual(message, parsed_message) + if message_module is unittest_pb2: + test_util.ExpectAllFieldsSet(self, message) + + msg2 = message_module.TestAllTypes() + text = (u'optional_string: "café"') + text_format.Merge(text, msg2) + self.assertEqual(msg2.optional_string, u'café') + msg2.Clear() + self.assertEqual(msg2.optional_string, u'') + text_format.Parse(text, msg2) + self.assertEqual(msg2.optional_string, u'café') + + def testParseDoubleToFloat(self, message_module): + message = message_module.TestAllTypes() + text = ('repeated_float: 3.4028235e+39\n' + 'repeated_float: 1.4028235e-39\n') + text_format.Parse(text, message) + self.assertEqual(message.repeated_float[0], float('inf')) + self.assertAlmostEqual(message.repeated_float[1], 1.4028235e-39) + def testParseExotic(self, message_module): message = message_module.TestAllTypes() text = ('repeated_int64: -9223372036854775808\n' @@ -340,6 +737,7 @@ def testParseTrailingCommas(self, message_module): def testParseRepeatedScalarShortFormat(self, message_module): message = message_module.TestAllTypes() text = ('repeated_int64: [100, 200];\n' + 'repeated_int64: []\n' 'repeated_int64: 300,\n' 'repeated_string: ["one", "two"];\n') text_format.Parse(text, message) @@ -371,7 +769,10 @@ def testParseEmptyText(self, message_module): def testParseInvalidUtf8(self, message_module): message = message_module.TestAllTypes() text = 'repeated_string: "\\xc3\\xc3"' - self.assertRaises(text_format.ParseError, text_format.Parse, text, message) + with self.assertRaises(text_format.ParseError) as e: + text_format.Parse(text, message) + self.assertEqual(e.exception.GetLine(), 1) + self.assertEqual(e.exception.GetColumn(), 28) def testParseSingleWord(self, message_module): message = message_module.TestAllTypes() @@ -386,27 +787,28 @@ def testParseUnknownField(self, message_module): six.assertRaisesRegex(self, text_format.ParseError, ( r'1:1 : Message type "\w+.TestAllTypes" has no field named ' r'"unknown_field".'), text_format.Parse, text, message) + text = ('optional_int32: 123\n' + 'unknown_field: 8\n' + 'optional_nested_message { bb: 45 }') + text_format.Parse(text, message, allow_unknown_field=True) + self.assertEqual(message.optional_nested_message.bb, 45) + self.assertEqual(message.optional_int32, 123) def testParseBadEnumValue(self, message_module): message = message_module.TestAllTypes() text = 'optional_nested_enum: BARR' six.assertRaisesRegex(self, text_format.ParseError, - (r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" ' + (r'1:23 : \'optional_nested_enum: BARR\': ' + r'Enum type "\w+.TestAllTypes.NestedEnum" ' r'has no value named BARR.'), text_format.Parse, text, message) - message = message_module.TestAllTypes() - text = 'optional_nested_enum: 100' - six.assertRaisesRegex(self, text_format.ParseError, - (r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" ' - r'has no value with number 100.'), text_format.Parse, - text, message) - def testParseBadIntValue(self, message_module): message = message_module.TestAllTypes() text = 'optional_int32: bork' six.assertRaisesRegex(self, text_format.ParseError, - ('1:17 : Couldn\'t parse integer: bork'), + ('1:17 : \'optional_int32: bork\': ' + 'Couldn\'t parse integer: bork'), text_format.Parse, text, message) def testParseStringFieldUnescape(self, message_module): @@ -430,7 +832,123 @@ def testParseStringFieldUnescape(self, message_module): message.repeated_string[4]) self.assertEqual(SLASH + 'x20', message.repeated_string[5]) - def testMergeDuplicateScalars(self, message_module): + def testParseOneof(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + m2 = message_module.TestAllTypes() + text_format.Parse(text_format.MessageToString(m), m2) + self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field')) + + def testParseMultipleOneof(self, message_module): + m_string = '\n'.join(['oneof_uint32: 11', 'oneof_string: "foo"']) + m2 = message_module.TestAllTypes() + with six.assertRaisesRegex(self, text_format.ParseError, + ' is specified along with field '): + text_format.Parse(m_string, m2) + + # This example contains non-ASCII codepoint unicode data as literals + # which should come through as utf-8 for bytes, and as the unicode + # itself for string fields. It also demonstrates escaped binary data. + # The ur"" string prefix is unfortunately missing from Python 3 + # so we resort to double escaping our \s so that they come through. + _UNICODE_SAMPLE = u""" + optional_bytes: 'Á short desçription' + optional_string: 'Á short desçription' + repeated_bytes: '\\303\\201 short des\\303\\247ription' + repeated_bytes: '\\x12\\x34\\x56\\x78\\x90\\xab\\xcd\\xef' + repeated_string: '\\xd0\\x9f\\xd1\\x80\\xd0\\xb8\\xd0\\xb2\\xd0\\xb5\\xd1\\x82' + """ + _BYTES_SAMPLE = _UNICODE_SAMPLE.encode('utf-8') + _GOLDEN_UNICODE = u'Á short desçription' + _GOLDEN_BYTES = _GOLDEN_UNICODE.encode('utf-8') + _GOLDEN_BYTES_1 = b'\x12\x34\x56\x78\x90\xab\xcd\xef' + _GOLDEN_STR_0 = u'Привет' + + def testParseUnicode(self, message_module): + m = message_module.TestAllTypes() + text_format.Parse(self._UNICODE_SAMPLE, m) + self.assertEqual(m.optional_bytes, self._GOLDEN_BYTES) + self.assertEqual(m.optional_string, self._GOLDEN_UNICODE) + self.assertEqual(m.repeated_bytes[0], self._GOLDEN_BYTES) + # repeated_bytes[1] contained simple \ escaped non-UTF-8 raw binary data. + self.assertEqual(m.repeated_bytes[1], self._GOLDEN_BYTES_1) + # repeated_string[0] contained \ escaped data representing the UTF-8 + # representation of _GOLDEN_STR_0 - it needs to decode as such. + self.assertEqual(m.repeated_string[0], self._GOLDEN_STR_0) + + def testParseBytes(self, message_module): + m = message_module.TestAllTypes() + text_format.Parse(self._BYTES_SAMPLE, m) + self.assertEqual(m.optional_bytes, self._GOLDEN_BYTES) + self.assertEqual(m.optional_string, self._GOLDEN_UNICODE) + self.assertEqual(m.repeated_bytes[0], self._GOLDEN_BYTES) + # repeated_bytes[1] contained simple \ escaped non-UTF-8 raw binary data. + self.assertEqual(m.repeated_bytes[1], self._GOLDEN_BYTES_1) + # repeated_string[0] contained \ escaped data representing the UTF-8 + # representation of _GOLDEN_STR_0 - it needs to decode as such. + self.assertEqual(m.repeated_string[0], self._GOLDEN_STR_0) + + def testFromBytesFile(self, message_module): + m = message_module.TestAllTypes() + f = io.BytesIO(self._BYTES_SAMPLE) + text_format.ParseLines(f, m) + self.assertEqual(m.optional_bytes, self._GOLDEN_BYTES) + self.assertEqual(m.optional_string, self._GOLDEN_UNICODE) + self.assertEqual(m.repeated_bytes[0], self._GOLDEN_BYTES) + + def testFromUnicodeFile(self, message_module): + m = message_module.TestAllTypes() + f = io.StringIO(self._UNICODE_SAMPLE) + text_format.ParseLines(f, m) + self.assertEqual(m.optional_bytes, self._GOLDEN_BYTES) + self.assertEqual(m.optional_string, self._GOLDEN_UNICODE) + self.assertEqual(m.repeated_bytes[0], self._GOLDEN_BYTES) + + def testFromBytesLines(self, message_module): + m = message_module.TestAllTypes() + text_format.ParseLines(self._BYTES_SAMPLE.split(b'\n'), m) + self.assertEqual(m.optional_bytes, self._GOLDEN_BYTES) + self.assertEqual(m.optional_string, self._GOLDEN_UNICODE) + self.assertEqual(m.repeated_bytes[0], self._GOLDEN_BYTES) + + def testFromUnicodeLines(self, message_module): + m = message_module.TestAllTypes() + text_format.ParseLines(self._UNICODE_SAMPLE.split(u'\n'), m) + self.assertEqual(m.optional_bytes, self._GOLDEN_BYTES) + self.assertEqual(m.optional_string, self._GOLDEN_UNICODE) + self.assertEqual(m.repeated_bytes[0], self._GOLDEN_BYTES) + + def testParseDuplicateMessages(self, message_module): + message = message_module.TestAllTypes() + text = ('optional_nested_message { bb: 1 } ' + 'optional_nested_message { bb: 2 }') + six.assertRaisesRegex(self, text_format.ParseError, ( + r'1:59 : Message type "\w+.TestAllTypes" ' + r'should not have multiple "optional_nested_message" fields.'), + text_format.Parse, text, + message) + + def testParseDuplicateScalars(self, message_module): + message = message_module.TestAllTypes() + text = ('optional_int32: 42 ' 'optional_int32: 67') + six.assertRaisesRegex(self, text_format.ParseError, ( + r'1:36 : Message type "\w+.TestAllTypes" should not ' + r'have multiple "optional_int32" fields.'), text_format.Parse, text, + message) + + def testParseExistingScalarInMessage(self, message_module): + message = message_module.TestAllTypes(optional_int32=42) + text = 'optional_int32: 67' + six.assertRaisesRegex(self, text_format.ParseError, + (r'Message type "\w+.TestAllTypes" should not ' + r'have multiple "optional_int32" fields.'), + text_format.Parse, text, message) + + +@_parameterized.parameters(unittest_pb2, unittest_proto3_arena_pb2) +class TextFormatMergeTests(TextFormatBase): + + def testMergeDuplicateScalarsInText(self, message_module): message = message_module.TestAllTypes() text = ('optional_int32: 42 ' 'optional_int32: 67') r = text_format.Merge(text, message) @@ -445,12 +963,21 @@ def testMergeDuplicateNestedMessageScalars(self, message_module): self.assertTrue(r is message) self.assertEqual(2, message.optional_nested_message.bb) - def testParseOneof(self, message_module): - m = message_module.TestAllTypes() - m.oneof_uint32 = 11 - m2 = message_module.TestAllTypes() - text_format.Parse(text_format.MessageToString(m), m2) - self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field')) + def testReplaceScalarInMessage(self, message_module): + message = message_module.TestAllTypes(optional_int32=42) + text = 'optional_int32: 67' + r = text_format.Merge(text, message) + self.assertIs(r, message) + self.assertEqual(67, message.optional_int32) + + def testReplaceMessageInMessage(self, message_module): + message = message_module.TestAllTypes( + optional_int32=42, optional_nested_message=dict()) + self.assertTrue(message.HasField('optional_nested_message')) + text = 'optional_nested_message{ bb: 3 }' + r = text_format.Merge(text, message) + self.assertIs(r, message) + self.assertEqual(3, message.optional_nested_message.bb) def testMergeMultipleOneof(self, message_module): m_string = '\n'.join(['oneof_uint32: 11', 'oneof_string: "foo"']) @@ -458,13 +985,6 @@ def testMergeMultipleOneof(self, message_module): text_format.Merge(m_string, m2) self.assertEqual('oneof_string', m2.WhichOneof('oneof_field')) - def testParseMultipleOneof(self, message_module): - m_string = '\n'.join(['oneof_uint32: 11', 'oneof_string: "foo"']) - m2 = message_module.TestAllTypes() - with self.assertRaisesRegexp(text_format.ParseError, - ' is specified along with field '): - text_format.Parse(m_string, m2) - # These are tests that aren't fundamentally specific to proto2, but are at # the moment because of differences between the proto2 and proto3 test schemas. @@ -497,22 +1017,104 @@ def testPrintAllFields(self): self.RemoveRedundantZeros(text_format.MessageToString(message)), 'text_format_unittest_data_oneof_implemented.txt') + def testPrintUnknownFields(self): + message = unittest_pb2.TestAllTypes() + message.optional_int32 = 101 + message.optional_double = 102.0 + message.optional_string = u'hello' + message.optional_bytes = b'103' + message.optionalgroup.a = 104 + message.optional_nested_message.bb = 105 + all_data = message.SerializeToString() + empty_message = unittest_pb2.TestEmptyMessage() + empty_message.ParseFromString(all_data) + self.assertEqual(' 1: 101\n' + ' 12: 4636878028842991616\n' + ' 14: "hello"\n' + ' 15: "103"\n' + ' 16 {\n' + ' 17: 104\n' + ' }\n' + ' 18 {\n' + ' 1: 105\n' + ' }\n', + text_format.MessageToString(empty_message, + indent=2, + print_unknown_fields=True)) + self.assertEqual('1: 101 ' + '12: 4636878028842991616 ' + '14: "hello" ' + '15: "103" ' + '16 { 17: 104 } ' + '18 { 1: 105 }', + text_format.MessageToString(empty_message, + print_unknown_fields=True, + as_one_line=True)) + def testPrintInIndexOrder(self): message = unittest_pb2.TestFieldOrderings() - message.my_string = '115' + # Fields are listed in index order instead of field number. + message.my_string = 'str' message.my_int = 101 message.my_float = 111 message.optional_nested_message.oo = 0 message.optional_nested_message.bb = 1 + message.Extensions[unittest_pb2.my_extension_string] = 'ext_str0' + # Extensions are listed based on the order of extension number. + # Extension number 12. + message.Extensions[unittest_pb2.TestExtensionOrderings2. + test_ext_orderings2].my_string = 'ext_str2' + # Extension number 13. + message.Extensions[unittest_pb2.TestExtensionOrderings1. + test_ext_orderings1].my_string = 'ext_str1' + # Extension number 14. + message.Extensions[ + unittest_pb2.TestExtensionOrderings2.TestExtensionOrderings3. + test_ext_orderings3].my_string = 'ext_str3' + + # Print in index order. self.CompareToGoldenText( - self.RemoveRedundantZeros(text_format.MessageToString( - message, use_index_order=True)), - 'my_string: \"115\"\nmy_int: 101\nmy_float: 111\n' - 'optional_nested_message {\n oo: 0\n bb: 1\n}\n') + self.RemoveRedundantZeros( + text_format.MessageToString(message, use_index_order=True)), + 'my_string: "str"\n' + 'my_int: 101\n' + 'my_float: 111\n' + 'optional_nested_message {\n' + ' oo: 0\n' + ' bb: 1\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] {\n' + ' my_string: "ext_str2"\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings1.test_ext_orderings1] {\n' + ' my_string: "ext_str1"\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3' + '.test_ext_orderings3] {\n' + ' my_string: "ext_str3"\n' + '}\n' + '[protobuf_unittest.my_extension_string]: "ext_str0"\n') + # By default, print in field number order. self.CompareToGoldenText( self.RemoveRedundantZeros(text_format.MessageToString(message)), - 'my_int: 101\nmy_string: \"115\"\nmy_float: 111\n' - 'optional_nested_message {\n bb: 1\n oo: 0\n}\n') + 'my_int: 101\n' + 'my_string: "str"\n' + '[protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] {\n' + ' my_string: "ext_str2"\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings1.test_ext_orderings1] {\n' + ' my_string: "ext_str1"\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3' + '.test_ext_orderings3] {\n' + ' my_string: "ext_str3"\n' + '}\n' + '[protobuf_unittest.my_extension_string]: "ext_str0"\n' + 'my_float: 111\n' + 'optional_nested_message {\n' + ' bb: 1\n' + ' oo: 0\n' + '}\n') def testMergeLinesGolden(self): opened = self.ReadGolden('text_format_unittest_data_oneof_implemented.txt') @@ -574,6 +1176,29 @@ def testPrintMap(self): ' }\n' '}\n') + # In cpp implementation, __str__ calls the cpp implementation of text format. + def testPrintMapUsingCppImplementation(self): + message = map_unittest_pb2.TestMap() + inner_msg = message.map_int32_foreign_message[111] + inner_msg.c = 1 + self.assertEqual( + str(message), + 'map_int32_foreign_message {\n' + ' key: 111\n' + ' value {\n' + ' c: 1\n' + ' }\n' + '}\n') + inner_msg.c = 2 + self.assertEqual( + str(message), + 'map_int32_foreign_message {\n' + ' key: 111\n' + ' value {\n' + ' c: 2\n' + ' }\n' + '}\n') + def testMapOrderEnforcement(self): message = map_unittest_pb2.TestMap() for letter in string.ascii_uppercase[13:26]: @@ -784,13 +1409,14 @@ def testParseAllowedUnknownExtension(self): ' bin: "\xe0"' ' [nested_unknown_ext]: {\n' ' i: 23\n' + ' x: x\n' ' test: "test_string"\n' ' floaty_float: -0.315\n' ' num: -inf\n' ' multiline_str: "abc"\n' ' "def"\n' ' "xyz."\n' - ' [nested_unknown_ext]: <\n' + ' [nested_unknown_ext.ext]: <\n' ' i: 23\n' ' i: 24\n' ' pointfloat: .3\n' @@ -802,6 +1428,10 @@ def testParseAllowedUnknownExtension(self): ' }\n' ' }\n' ' [unknown_extension]: 5\n' + ' [unknown_extension_with_number_field] {\n' + ' 1: "some_field"\n' + ' 2: -0.451\n' + ' }\n' '}\n') text_format.Parse(text, message, allow_unknown_extension=True) golden = 'message_set {\n}\n' @@ -858,7 +1488,7 @@ def testParseAllowedUnknownExtension(self): '}\n') six.assertRaisesRegex(self, text_format.ParseError, - '5:1 : Expected ">".', + '5:1 : \'}\': Expected ">".', text_format.Parse, malformed, message, @@ -868,7 +1498,6 @@ def testParseAllowedUnknownExtension(self): message = unittest_mset_pb2.TestMessageSetContainer() malformed = ('message_set {\n' ' unknown_field: true\n' - ' \n' # Missing '>' here. '}\n') six.assertRaisesRegex(self, text_format.ParseError, @@ -880,7 +1509,7 @@ def testParseAllowedUnknownExtension(self): message, allow_unknown_extension=True) - # Parse known extension correcty. + # Parse known extension correctly. message = unittest_mset_pb2.TestMessageSetContainer() text = ('message_set {\n' ' [protobuf_unittest.TestMessageSetExtension1] {\n' @@ -896,6 +1525,15 @@ def testParseAllowedUnknownExtension(self): self.assertEqual(23, message.message_set.Extensions[ext1].i) self.assertEqual('foo', message.message_set.Extensions[ext2].str) + def testParseBadIdentifier(self): + message = unittest_pb2.TestAllTypes() + text = ('optional_nested_message { "bb": 1 }') + with self.assertRaises(text_format.ParseError) as e: + text_format.Parse(text, message) + self.assertEqual(str(e.exception), + '1:27 : \'optional_nested_message { "bb": 1 }\': ' + 'Expected identifier or number, got "bb".') + def testParseBadExtension(self): message = unittest_pb2.TestAllExtensions() text = '[unknown_extension]: 8\n' @@ -907,6 +1545,15 @@ def testParseBadExtension(self): '1:2 : Message type "protobuf_unittest.TestAllTypes" does not have ' 'extensions.'), text_format.Parse, text, message) + def testParseNumericUnknownEnum(self): + message = unittest_pb2.TestAllTypes() + text = 'optional_nested_enum: 100' + six.assertRaisesRegex(self, text_format.ParseError, + (r'1:23 : \'optional_nested_enum: 100\': ' + r'Enum type "\w+.TestAllTypes.NestedEnum" ' + r'has no value with number 100.'), text_format.Parse, + text, message) + def testMergeDuplicateExtensionScalars(self): message = unittest_pb2.TestAllExtensions() text = ('[protobuf_unittest.optional_int32_extension]: 42 ' @@ -925,22 +1572,15 @@ def testParseDuplicateExtensionScalars(self): '"protobuf_unittest.optional_int32_extension" extensions.'), text_format.Parse, text, message) - def testParseDuplicateNestedMessageScalars(self): - message = unittest_pb2.TestAllTypes() - text = ('optional_nested_message { bb: 1 } ' - 'optional_nested_message { bb: 2 }') - six.assertRaisesRegex(self, text_format.ParseError, ( - '1:65 : Message type "protobuf_unittest.TestAllTypes.NestedMessage" ' - 'should not have multiple "bb" fields.'), text_format.Parse, text, - message) - - def testParseDuplicateScalars(self): - message = unittest_pb2.TestAllTypes() - text = ('optional_int32: 42 ' 'optional_int32: 67') + def testParseDuplicateExtensionMessages(self): + message = unittest_pb2.TestAllExtensions() + text = ('[protobuf_unittest.optional_nested_message_extension]: {} ' + '[protobuf_unittest.optional_nested_message_extension]: {}') six.assertRaisesRegex(self, text_format.ParseError, ( - '1:36 : Message type "protobuf_unittest.TestAllTypes" should not ' - 'have multiple "optional_int32" fields.'), text_format.Parse, text, - message) + '1:114 : Message type "protobuf_unittest.TestAllExtensions" ' + 'should not have multiple ' + '"protobuf_unittest.optional_nested_message_extension" extensions.'), + text_format.Parse, text, message) def testParseGroupNotClosed(self): message = unittest_pb2.TestAllTypes() @@ -1020,6 +1660,14 @@ def testPrintMessageExpandAny(self): ' }\n' '}\n') + def testTopAnyMessage(self): + packed_msg = unittest_pb2.OneString() + msg = any_pb2.Any() + msg.Pack(packed_msg) + text = text_format.MessageToString(msg) + other_msg = text_format.Parse(text, any_pb2.Any()) + self.assertEqual(msg, other_msg) + def testPrintMessageExpandAnyRepeated(self): packed_message = unittest_pb2.OneString() message = any_test_pb2.TestAny() @@ -1095,6 +1743,32 @@ def testPrintMessageExpandAnyAsOneLinePointyBrackets(self): ' < data: "string" > ' '>') + def testPrintAndParseMessageInvalidAny(self): + packed_message = unittest_pb2.OneString() + packed_message.data = 'string' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + # Only include string after last '/' in type_url. + message.any_value.type_url = message.any_value.TypeName() + text = text_format.MessageToString(message) + self.assertEqual( + text, 'any_value {\n' + ' type_url: "protobuf_unittest.OneString"\n' + ' value: "\\n\\006string"\n' + '}\n') + + parsed_message = any_test_pb2.TestAny() + text_format.Parse(text, parsed_message) + self.assertEqual(message, parsed_message) + + def testUnknownEnums(self): + message = unittest_proto3_arena_pb2.TestAllTypes() + message2 = unittest_proto3_arena_pb2.TestAllTypes() + message.optional_nested_enum = 999 + text_string = text_format.MessageToString(message) + text_format.Parse(text_string, message2) + self.assertEqual(999, message2.optional_nested_enum) + def testMergeExpandedAny(self): message = any_test_pb2.TestAny() text = ('any_value {\n' @@ -1180,6 +1854,33 @@ def testMergeUnexpandedAny(self): message.any_value.Unpack(packed_message) self.assertEqual('string', packed_message.data) + def testMergeMissingAnyEndToken(self): + message = any_test_pb2.TestAny() + text = ('any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string"\n') + with self.assertRaises(text_format.ParseError) as e: + text_format.Merge(text, message) + self.assertEqual(str(e.exception), '3:11 : Expected "}".') + + def testProto3Optional(self): + msg = test_proto3_optional_pb2.TestProto3Optional() + self.assertEqual(text_format.MessageToString(msg), '') + msg.optional_int32 = 0 + msg.optional_float = 0.0 + msg.optional_string = '' + msg.optional_nested_message.bb = 0 + text = ('optional_int32: 0\n' + 'optional_float: 0.0\n' + 'optional_string: ""\n' + 'optional_nested_message {\n' + ' bb: 0\n' + '}\n') + self.assertEqual(text_format.MessageToString(msg), text) + msg2 = test_proto3_optional_pb2.TestProto3Optional() + text_format.Parse(text, msg2) + self.assertEqual(text_format.MessageToString(msg2), text) + class TokenizerTest(unittest.TestCase): @@ -1191,7 +1892,7 @@ def testSimpleTokenCases(self): 'ID9: 22 ID10: -111111111111111111 ID11: -22\n' 'ID12: 2222222222222222222 ID13: 1.23456f ID14: 1.2e+2f ' 'false_bool: 0 true_BOOL:t \n true_bool1: 1 false_BOOL1:f ' - 'False_bool: False True_bool: True') + 'False_bool: False True_bool: True X:iNf Y:-inF Z:nAN') tokenizer = text_format.Tokenizer(text.splitlines()) methods = [(tokenizer.ConsumeIdentifier, 'identifier1'), ':', (tokenizer.ConsumeString, 'string1'), @@ -1239,7 +1940,13 @@ def testSimpleTokenCases(self): (tokenizer.ConsumeIdentifier, 'False_bool'), ':', (tokenizer.ConsumeBool, False), (tokenizer.ConsumeIdentifier, 'True_bool'), ':', - (tokenizer.ConsumeBool, True)] + (tokenizer.ConsumeBool, True), + (tokenizer.ConsumeIdentifier, 'X'), ':', + (tokenizer.ConsumeFloat, float('inf')), + (tokenizer.ConsumeIdentifier, 'Y'), ':', + (tokenizer.ConsumeFloat, float('-inf')), + (tokenizer.ConsumeIdentifier, 'Z'), ':', + (tokenizer.ConsumeFloat, float('nan'))] i = 0 while not tokenizer.AtEnd(): @@ -1248,6 +1955,8 @@ def testSimpleTokenCases(self): token = tokenizer.token self.assertEqual(token, m) tokenizer.NextToken() + elif isinstance(m[1], float) and math.isnan(m[1]): + self.assertTrue(math.isnan(m[0]())) else: self.assertEqual(m[1], m[0]()) i += 1 @@ -1266,10 +1975,15 @@ def testConsumeAbstractIntegers(self): self.assertEqual(int64_max + 1, tokenizer.ConsumeInteger()) self.assertTrue(tokenizer.AtEnd()) - text = '-0 0' + text = '-0 0 0 1.2' tokenizer = text_format.Tokenizer(text.splitlines()) self.assertEqual(0, tokenizer.ConsumeInteger()) self.assertEqual(0, tokenizer.ConsumeInteger()) + self.assertEqual(True, tokenizer.TryConsumeInteger()) + self.assertEqual(False, tokenizer.TryConsumeInteger()) + with self.assertRaises(text_format.ParseError): + tokenizer.ConsumeInteger() + self.assertEqual(1.2, tokenizer.ConsumeFloat()) self.assertTrue(tokenizer.AtEnd()) def testConsumeIntegers(self): @@ -1304,6 +2018,26 @@ def testConsumeIntegers(self): self.assertEqual(0, text_format._ConsumeUint64(tokenizer)) self.assertTrue(tokenizer.AtEnd()) + def testConsumeOctalIntegers(self): + """Test support for C style octal integers.""" + text = '00 -00 04 0755 -010 007 -0033 08 -09 01' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertEqual(0, tokenizer.ConsumeInteger()) + self.assertEqual(0, tokenizer.ConsumeInteger()) + self.assertEqual(4, tokenizer.ConsumeInteger()) + self.assertEqual(0o755, tokenizer.ConsumeInteger()) + self.assertEqual(-0o10, tokenizer.ConsumeInteger()) + self.assertEqual(7, tokenizer.ConsumeInteger()) + self.assertEqual(-0o033, tokenizer.ConsumeInteger()) + with self.assertRaises(text_format.ParseError): + tokenizer.ConsumeInteger() # 08 + tokenizer.NextToken() + with self.assertRaises(text_format.ParseError): + tokenizer.ConsumeInteger() # -09 + tokenizer.NextToken() + self.assertEqual(1, tokenizer.ConsumeInteger()) + self.assertTrue(tokenizer.AtEnd()) + def testConsumeByteString(self): text = '"string1\'' tokenizer = text_format.Tokenizer(text.splitlines()) @@ -1412,9 +2146,15 @@ def testHashinComment(self): tokenizer.ConsumeCommentOrTrailingComment()) self.assertTrue(tokenizer.AtEnd()) + def testHugeString(self): + # With pathologic backtracking, fails with Forge OOM. + text = '"' + 'a' * (10 * 1024 * 1024) + '"' + tokenizer = text_format.Tokenizer(text.splitlines(), skip_comments=False) + tokenizer.ConsumeString() + # Tests for pretty printer functionality. -@_parameterized.Parameters((unittest_pb2), (unittest_proto3_arena_pb2)) +@_parameterized.parameters((unittest_pb2), (unittest_proto3_arena_pb2)) class PrettyPrinterTest(TextFormatBase): def testPrettyPrintNoMatch(self, message_module): @@ -1508,5 +2248,106 @@ def printer(m, indent, as_one_line): 'repeated_nested_message { My lucky number is 42 } ' 'repeated_nested_message { My lucky number is 99 }')) + out = text_format.TextWriter(False) + text_format.PrintField( + message_module.TestAllTypes.DESCRIPTOR.fields_by_name[ + 'optional_nested_message'], + message.optional_nested_message, + out, + message_formatter=printer) + self.assertEqual( + 'optional_nested_message {\n My lucky number is 1\n}\n', + out.getvalue()) + out.close() + + out = text_format.TextWriter(False) + text_format.PrintFieldValue( + message_module.TestAllTypes.DESCRIPTOR.fields_by_name[ + 'optional_nested_message'], + message.optional_nested_message, + out, + message_formatter=printer) + self.assertEqual( + '{\n My lucky number is 1\n}', + out.getvalue()) + out.close() + + +class WhitespaceTest(TextFormatBase): + + def setUp(self): + self.out = text_format.TextWriter(False) + self.addCleanup(self.out.close) + self.message = unittest_pb2.NestedTestAllTypes() + self.message.child.payload.optional_string = 'value' + self.field = self.message.DESCRIPTOR.fields_by_name['child'] + self.value = self.message.child + + def testMessageToString(self): + self.CompareToGoldenText( + text_format.MessageToString(self.message), + textwrap.dedent("""\ + child { + payload { + optional_string: "value" + } + } + """)) + + def testPrintMessage(self): + text_format.PrintMessage(self.message, self.out) + self.CompareToGoldenText( + self.out.getvalue(), + textwrap.dedent("""\ + child { + payload { + optional_string: "value" + } + } + """)) + + def testPrintField(self): + text_format.PrintField(self.field, self.value, self.out) + self.CompareToGoldenText( + self.out.getvalue(), + textwrap.dedent("""\ + child { + payload { + optional_string: "value" + } + } + """)) + + def testPrintFieldValue(self): + text_format.PrintFieldValue( + self.field, self.value, self.out) + self.CompareToGoldenText( + self.out.getvalue(), + textwrap.dedent("""\ + { + payload { + optional_string: "value" + } + }""")) + + +class OptionalColonMessageToStringTest(unittest.TestCase): + + def testForcePrintOptionalColon(self): + packed_message = unittest_pb2.OneString() + packed_message.data = 'string' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + output = text_format.MessageToString( + message, + force_colon=True) + expected = ('any_value: {\n' + ' [type.googleapis.com/protobuf_unittest.OneString]: {\n' + ' data: "string"\n' + ' }\n' + '}\n') + self.assertEqual(expected, output) + + if __name__ == '__main__': unittest.main() diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py old mode 100755 new mode 100644 index 4a76cd4ef6282..eb66f9f6fbaee --- a/python/google/protobuf/internal/type_checkers.py +++ b/python/google/protobuf/internal/type_checkers.py @@ -38,13 +38,18 @@ TYPE_TO_SERIALIZE_METHOD: A dictionary with field types and serialization function. FIELD_TYPE_TO_WIRE_TYPE: A dictionary with field typed and their - coresponding wire types. + corresponding wire types. TYPE_TO_DESERIALIZE_METHOD: A dictionary with field types and deserialization function. """ __author__ = 'robinson@google.com (Will Robinson)' +try: + import ctypes +except Exception: # pylint: disable=broad-except + ctypes = None + import struct import numbers import six @@ -59,6 +64,29 @@ _FieldDescriptor = descriptor.FieldDescriptor + +def TruncateToFourByteFloat(original): + if ctypes: + return ctypes.c_float(original).value + else: + return struct.unpack(' _FLOAT_MAX: + return _INF + if converted_value < _FLOAT_MIN: + return _NEG_INF + + return TruncateToFourByteFloat(converted_value) + + def DefaultValue(self): + return 0.0 + + # Type-checkers for all scalar CPPTYPEs. _VALUE_CHECKERS = { _FieldDescriptor.CPPTYPE_INT32: Int32ValueChecker(), @@ -224,9 +298,8 @@ class Uint64ValueChecker(IntValueChecker): _FieldDescriptor.CPPTYPE_UINT32: Uint32ValueChecker(), _FieldDescriptor.CPPTYPE_UINT64: Uint64ValueChecker(), _FieldDescriptor.CPPTYPE_DOUBLE: TypeCheckerWithDefault( - 0.0, numbers.Real), - _FieldDescriptor.CPPTYPE_FLOAT: TypeCheckerWithDefault( - 0.0, numbers.Real), + 0.0, float, numbers.Real), + _FieldDescriptor.CPPTYPE_FLOAT: FloatValueChecker(), _FieldDescriptor.CPPTYPE_BOOL: TypeCheckerWithDefault( False, bool, numbers.Integral), _FieldDescriptor.CPPTYPE_STRING: TypeCheckerWithDefault(b'', bytes), diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py index d614eaa8744f7..d0ac5d90520e8 100755 --- a/python/google/protobuf/internal/unknown_fields_test.py +++ b/python/google/protobuf/internal/unknown_fields_test.py @@ -39,6 +39,8 @@ import unittest2 as unittest #PY26 except ImportError: import unittest +import sys +from google.protobuf import map_unittest_pb2 from google.protobuf import unittest_mset_pb2 from google.protobuf import unittest_pb2 from google.protobuf import unittest_proto3_arena_pb2 @@ -49,18 +51,18 @@ from google.protobuf.internal import test_util from google.protobuf.internal import testing_refleaks from google.protobuf.internal import type_checkers +from google.protobuf.internal import wire_format +from google.protobuf import descriptor - -BaseTestCase = testing_refleaks.BaseTestCase - - -def SkipIfCppImplementation(func): - return unittest.skipIf( - api_implementation.Type() == 'cpp' and api_implementation.Version() == 2, - 'C++ implementation does not expose unknown fields to Python')(func) +try: + import tracemalloc # pylint: disable=g-import-not-at-top +except ImportError: + # Requires python 3.4+ + pass -class UnknownFieldsTest(BaseTestCase): +@testing_refleaks.TestCase +class UnknownFieldsTest(unittest.TestCase): def setUp(self): self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR @@ -78,10 +80,10 @@ def testSerialize(self): self.assertTrue(data == self.all_fields_data) def testSerializeProto3(self): - # Verify that proto3 doesn't preserve unknown fields. + # Verify proto3 unknown fields behavior. message = unittest_proto3_arena_pb2.TestEmptyMessage() message.ParseFromString(self.all_fields_data) - self.assertEqual(0, len(message.SerializeToString())) + self.assertEqual(self.all_fields_data, message.SerializeToString()) def testByteSize(self): self.assertEqual(self.all_fields.ByteSize(), self.empty_message.ByteSize()) @@ -97,7 +99,7 @@ def testSerializeMessageSetWireFormatUnknownExtension(self): # Add an unknown extension. item = raw.item.add() - item.type_id = 98418603 + item.type_id = 98218603 message1 = message_set_extensions_pb2.TestMessageSetExtension1() message1.i = 12345 item.message = message1.SerializeToString() @@ -108,6 +110,18 @@ def testSerializeMessageSetWireFormatUnknownExtension(self): proto = message_set_extensions_pb2.TestMessageSet() proto.MergeFromString(serialized) + unknown_fields = proto.UnknownFields() + self.assertEqual(len(unknown_fields), 1) + # Unknown field should have wire format data which can be parsed back to + # original message. + self.assertEqual(unknown_fields[0].field_number, item.type_id) + self.assertEqual(unknown_fields[0].wire_type, + wire_format.WIRETYPE_LENGTH_DELIMITED) + d = unknown_fields[0].data + message_new = message_set_extensions_pb2.TestMessageSetExtension1() + message_new.ParseFromString(d) + self.assertEqual(message1, message_new) + # Verify that the unknown extension is serialized unchanged reserialized = proto.SerializeToString() new_raw = unittest_mset_pb2.RawMessageSet() @@ -143,8 +157,21 @@ def testDiscardUnknownFields(self): self.assertEqual( b'', message.repeated_nested_message[0].SerializeToString()) + msg = map_unittest_pb2.TestMap() + msg.map_int32_all_types[1].optional_nested_message.ParseFromString( + other_message.SerializeToString()) + msg.map_string_string['1'] = 'test' + self.assertNotEqual( + b'', + msg.map_int32_all_types[1].optional_nested_message.SerializeToString()) + msg.DiscardUnknownFields() + self.assertEqual( + b'', + msg.map_int32_all_types[1].optional_nested_message.SerializeToString()) -class UnknownFieldsAccessorsTest(BaseTestCase): + +@testing_refleaks.TestCase +class UnknownFieldsAccessorsTest(unittest.TestCase): def setUp(self): self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR @@ -154,12 +181,15 @@ def setUp(self): self.empty_message = unittest_pb2.TestEmptyMessage() self.empty_message.ParseFromString(self.all_fields_data) - # GetUnknownField() checks a detail of the Python implementation, which stores - # unknown fields as serialized strings. It cannot be used by the C++ - # implementation: it's enough to check that the message is correctly - # serialized. - - def GetUnknownField(self, name): + # InternalCheckUnknownField() is an additional Pure Python check which checks + # a detail of unknown fields. It cannot be used by the C++ + # implementation because some protect members are called. + # The test is added for historical reasons. It is not necessary as + # serialized string is checked. + # TODO(jieluo): Remove message._unknown_fields. + def InternalCheckUnknownField(self, name, expected_value): + if api_implementation.Type() == 'cpp': + return field_descriptor = self.descriptor.fields_by_name[name] wire_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type] field_tag = encoder.TagBytes(field_descriptor.number, wire_type) @@ -167,43 +197,82 @@ def GetUnknownField(self, name): for tag_bytes, value in self.empty_message._unknown_fields: if tag_bytes == field_tag: decoder = unittest_pb2.TestAllTypes._decoders_by_tag[tag_bytes][0] - decoder(value, 0, len(value), self.all_fields, result_dict) - return result_dict[field_descriptor] - - @SkipIfCppImplementation - def testEnum(self): - value = self.GetUnknownField('optional_nested_enum') - self.assertEqual(self.all_fields.optional_nested_enum, value) - - @SkipIfCppImplementation - def testRepeatedEnum(self): - value = self.GetUnknownField('repeated_nested_enum') - self.assertEqual(self.all_fields.repeated_nested_enum, value) - - @SkipIfCppImplementation - def testVarint(self): - value = self.GetUnknownField('optional_int32') - self.assertEqual(self.all_fields.optional_int32, value) - - @SkipIfCppImplementation - def testFixed32(self): - value = self.GetUnknownField('optional_fixed32') - self.assertEqual(self.all_fields.optional_fixed32, value) - - @SkipIfCppImplementation - def testFixed64(self): - value = self.GetUnknownField('optional_fixed64') - self.assertEqual(self.all_fields.optional_fixed64, value) - - @SkipIfCppImplementation - def testLengthDelimited(self): - value = self.GetUnknownField('optional_string') - self.assertEqual(self.all_fields.optional_string, value) - - @SkipIfCppImplementation - def testGroup(self): - value = self.GetUnknownField('optionalgroup') - self.assertEqual(self.all_fields.optionalgroup, value) + decoder(memoryview(value), 0, len(value), self.all_fields, result_dict) + self.assertEqual(expected_value, result_dict[field_descriptor]) + + def CheckUnknownField(self, name, unknown_fields, expected_value): + field_descriptor = self.descriptor.fields_by_name[name] + expected_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[ + field_descriptor.type] + for unknown_field in unknown_fields: + if unknown_field.field_number == field_descriptor.number: + self.assertEqual(expected_type, unknown_field.wire_type) + if expected_type == 3: + # Check group + self.assertEqual(expected_value[0], + unknown_field.data[0].field_number) + self.assertEqual(expected_value[1], unknown_field.data[0].wire_type) + self.assertEqual(expected_value[2], unknown_field.data[0].data) + continue + if expected_type == wire_format.WIRETYPE_LENGTH_DELIMITED: + self.assertIn(type(unknown_field.data), (str, bytes)) + if field_descriptor.label == descriptor.FieldDescriptor.LABEL_REPEATED: + self.assertIn(unknown_field.data, expected_value) + else: + self.assertEqual(expected_value, unknown_field.data) + + def testCheckUnknownFieldValue(self): + unknown_fields = self.empty_message.UnknownFields() + # Test enum. + self.CheckUnknownField('optional_nested_enum', + unknown_fields, + self.all_fields.optional_nested_enum) + self.InternalCheckUnknownField('optional_nested_enum', + self.all_fields.optional_nested_enum) + + # Test repeated enum. + self.CheckUnknownField('repeated_nested_enum', + unknown_fields, + self.all_fields.repeated_nested_enum) + self.InternalCheckUnknownField('repeated_nested_enum', + self.all_fields.repeated_nested_enum) + + # Test varint. + self.CheckUnknownField('optional_int32', + unknown_fields, + self.all_fields.optional_int32) + self.InternalCheckUnknownField('optional_int32', + self.all_fields.optional_int32) + + # Test fixed32. + self.CheckUnknownField('optional_fixed32', + unknown_fields, + self.all_fields.optional_fixed32) + self.InternalCheckUnknownField('optional_fixed32', + self.all_fields.optional_fixed32) + + # Test fixed64. + self.CheckUnknownField('optional_fixed64', + unknown_fields, + self.all_fields.optional_fixed64) + self.InternalCheckUnknownField('optional_fixed64', + self.all_fields.optional_fixed64) + + # Test length delimited. + self.CheckUnknownField('optional_string', + unknown_fields, + self.all_fields.optional_string.encode('utf-8')) + self.InternalCheckUnknownField('optional_string', + self.all_fields.optional_string) + + # Test group. + self.CheckUnknownField('optionalgroup', + unknown_fields, + (17, 0, 117)) + self.InternalCheckUnknownField('optionalgroup', + self.all_fields.optionalgroup) + + self.assertEqual(97, len(unknown_fields)) def testCopyFrom(self): message = unittest_pb2.TestEmptyMessage() @@ -221,9 +290,18 @@ def testMergeFrom(self): message.optional_int64 = 3 message.optional_uint32 = 4 destination = unittest_pb2.TestEmptyMessage() + unknown_fields = destination.UnknownFields() + self.assertEqual(0, len(unknown_fields)) destination.ParseFromString(message.SerializeToString()) - + # ParseFromString clears the message thus unknown fields is invalid. + with self.assertRaises(ValueError) as context: + len(unknown_fields) + self.assertIn('UnknownFields does not exist.', + str(context.exception)) + unknown_fields = destination.UnknownFields() + self.assertEqual(2, len(unknown_fields)) destination.MergeFrom(source) + self.assertEqual(4, len(unknown_fields)) # Check that the fields where correctly merged, even stored in the unknown # fields set. message.ParseFromString(destination.SerializeToString()) @@ -232,17 +310,88 @@ def testMergeFrom(self): self.assertEqual(message.optional_int64, 3) def testClear(self): + unknown_fields = self.empty_message.UnknownFields() self.empty_message.Clear() # All cleared, even unknown fields. self.assertEqual(self.empty_message.SerializeToString(), b'') + with self.assertRaises(ValueError) as context: + len(unknown_fields) + self.assertIn('UnknownFields does not exist.', + str(context.exception)) + + @unittest.skipIf((sys.version_info.major, sys.version_info.minor) < (3, 4), + 'tracemalloc requires python 3.4+') + def testUnknownFieldsNoMemoryLeak(self): + # Call to UnknownFields must not leak memory + nb_leaks = 1234 + + def leaking_function(): + for _ in range(nb_leaks): + self.empty_message.UnknownFields() + + tracemalloc.start() + snapshot1 = tracemalloc.take_snapshot() + leaking_function() + snapshot2 = tracemalloc.take_snapshot() + top_stats = snapshot2.compare_to(snapshot1, 'lineno') + tracemalloc.stop() + # There's no easy way to look for a precise leak source. + # Rely on a "marker" count value while checking allocated memory. + self.assertEqual([], [x for x in top_stats if x.count_diff == nb_leaks]) + + def testSubUnknownFields(self): + message = unittest_pb2.TestAllTypes() + message.optionalgroup.a = 123 + destination = unittest_pb2.TestEmptyMessage() + destination.ParseFromString(message.SerializeToString()) + sub_unknown_fields = destination.UnknownFields()[0].data + self.assertEqual(1, len(sub_unknown_fields)) + self.assertEqual(sub_unknown_fields[0].data, 123) + destination.Clear() + with self.assertRaises(ValueError) as context: + len(sub_unknown_fields) + self.assertIn('UnknownFields does not exist.', + str(context.exception)) + with self.assertRaises(ValueError) as context: + # pylint: disable=pointless-statement + sub_unknown_fields[0] + self.assertIn('UnknownFields does not exist.', + str(context.exception)) + message.Clear() + message.optional_uint32 = 456 + nested_message = unittest_pb2.NestedTestAllTypes() + nested_message.payload.optional_nested_message.ParseFromString( + message.SerializeToString()) + unknown_fields = ( + nested_message.payload.optional_nested_message.UnknownFields()) + self.assertEqual(unknown_fields[0].data, 456) + nested_message.ClearField('payload') + self.assertEqual(unknown_fields[0].data, 456) + unknown_fields = ( + nested_message.payload.optional_nested_message.UnknownFields()) + self.assertEqual(0, len(unknown_fields)) + + def testUnknownField(self): + message = unittest_pb2.TestAllTypes() + message.optional_int32 = 123 + destination = unittest_pb2.TestEmptyMessage() + destination.ParseFromString(message.SerializeToString()) + unknown_field = destination.UnknownFields()[0] + destination.Clear() + with self.assertRaises(ValueError) as context: + unknown_field.data # pylint: disable=pointless-statement + self.assertIn('The parent message might be cleared.', + str(context.exception)) def testUnknownExtensions(self): message = unittest_pb2.TestEmptyMessageWithExtensions() message.ParseFromString(self.all_fields_data) + self.assertEqual(len(message.UnknownFields()), 97) self.assertEqual(message.SerializeToString(), self.all_fields_data) -class UnknownEnumValuesTest(BaseTestCase): +@testing_refleaks.TestCase +class UnknownEnumValuesTest(unittest.TestCase): def setUp(self): self.descriptor = missing_enum_values_pb2.TestEnumValues.DESCRIPTOR @@ -263,22 +412,27 @@ def setUp(self): self.missing_message = missing_enum_values_pb2.TestMissingEnumValues() self.missing_message.ParseFromString(self.message_data) - # GetUnknownField() checks a detail of the Python implementation, which stores - # unknown fields as serialized strings. It cannot be used by the C++ - # implementation: it's enough to check that the message is correctly - # serialized. + # CheckUnknownField() is an additional Pure Python check which checks + # a detail of unknown fields. It cannot be used by the C++ + # implementation because some protect members are called. + # The test is added for historical reasons. It is not necessary as + # serialized string is checked. - def GetUnknownField(self, name): + def CheckUnknownField(self, name, expected_value): field_descriptor = self.descriptor.fields_by_name[name] - wire_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type] - field_tag = encoder.TagBytes(field_descriptor.number, wire_type) - result_dict = {} - for tag_bytes, value in self.missing_message._unknown_fields: - if tag_bytes == field_tag: - decoder = missing_enum_values_pb2.TestEnumValues._decoders_by_tag[ - tag_bytes][0] - decoder(value, 0, len(value), self.message, result_dict) - return result_dict[field_descriptor] + unknown_fields = self.missing_message.UnknownFields() + count = 0 + for field in unknown_fields: + if field.field_number == field_descriptor.number: + count += 1 + if field_descriptor.label == descriptor.FieldDescriptor.LABEL_REPEATED: + self.assertIn(field.data, expected_value) + else: + self.assertEqual(expected_value, field.data) + if field_descriptor.label == descriptor.FieldDescriptor.LABEL_REPEATED: + self.assertEqual(count, len(expected_value)) + else: + self.assertEqual(count, 1) def testUnknownParseMismatchEnumValue(self): just_string = missing_enum_values_pb2.JustString() @@ -294,38 +448,28 @@ def testUnknownParseMismatchEnumValue(self): self.assertEqual(missing.optional_nested_enum, 0) def testUnknownEnumValue(self): - if api_implementation.Type() == 'cpp': - # The CPP implementation of protos (wrongly) allows unknown enum values - # for proto2. - self.assertTrue(self.missing_message.HasField('optional_nested_enum')) - self.assertEqual(self.message.optional_nested_enum, - self.missing_message.optional_nested_enum) - else: - # On the other hand, the Python implementation considers unknown values - # as unknown fields. This is the correct behavior. - self.assertFalse(self.missing_message.HasField('optional_nested_enum')) - value = self.GetUnknownField('optional_nested_enum') - self.assertEqual(self.message.optional_nested_enum, value) - self.missing_message.ClearField('optional_nested_enum') self.assertFalse(self.missing_message.HasField('optional_nested_enum')) + self.assertEqual(self.missing_message.optional_nested_enum, 2) + # Clear does not do anything. + serialized = self.missing_message.SerializeToString() + self.missing_message.ClearField('optional_nested_enum') + self.assertEqual(self.missing_message.SerializeToString(), serialized) def testUnknownRepeatedEnumValue(self): - if api_implementation.Type() == 'cpp': - # For repeated enums, both implementations agree. - self.assertEqual([], self.missing_message.repeated_nested_enum) - else: - self.assertEqual([], self.missing_message.repeated_nested_enum) - value = self.GetUnknownField('repeated_nested_enum') - self.assertEqual(self.message.repeated_nested_enum, value) + self.assertEqual([], self.missing_message.repeated_nested_enum) def testUnknownPackedEnumValue(self): - if api_implementation.Type() == 'cpp': - # For repeated enums, both implementations agree. - self.assertEqual([], self.missing_message.packed_nested_enum) - else: - self.assertEqual([], self.missing_message.packed_nested_enum) - value = self.GetUnknownField('packed_nested_enum') - self.assertEqual(self.message.packed_nested_enum, value) + self.assertEqual([], self.missing_message.packed_nested_enum) + + def testCheckUnknownFieldValueForEnum(self): + unknown_fields = self.missing_message.UnknownFields() + self.assertEqual(len(unknown_fields), 5) + self.CheckUnknownField('optional_nested_enum', + self.message.optional_nested_enum) + self.CheckUnknownField('repeated_nested_enum', + self.message.repeated_nested_enum) + self.CheckUnknownField('packed_nested_enum', + self.message.packed_nested_enum) def testRoundTrip(self): new_message = missing_enum_values_pb2.TestEnumValues() diff --git a/python/google/protobuf/internal/well_known_types.py b/python/google/protobuf/internal/well_known_types.py index d0c7ffda54d5a..6f55d6b17b425 100644 --- a/python/google/protobuf/internal/well_known_types.py +++ b/python/google/protobuf/internal/well_known_types.py @@ -40,10 +40,18 @@ __author__ = 'jieluo@google.com (Jie Luo)' +import calendar from datetime import datetime from datetime import timedelta import six +try: + # Since python 3 + import collections.abc as collections_abc +except ImportError: + # Won't work after python 3.8 + import collections as collections_abc + from google.protobuf.descriptor import FieldDescriptor _TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S' @@ -56,24 +64,19 @@ _DURATION_SECONDS_MAX = 315576000000 -class Error(Exception): - """Top-level module error.""" - - -class ParseError(Error): - """Thrown in case of parsing error.""" - - class Any(object): """Class for Any Message type.""" - def Pack(self, msg, type_url_prefix='type.googleapis.com/'): + __slots__ = () + + def Pack(self, msg, type_url_prefix='type.googleapis.com/', + deterministic=None): """Packs the specified message into current Any message.""" if len(type_url_prefix) < 1 or type_url_prefix[-1] != '/': self.type_url = '%s/%s' % (type_url_prefix, msg.DESCRIPTOR.full_name) else: self.type_url = '%s%s' % (type_url_prefix, msg.DESCRIPTOR.full_name) - self.value = msg.SerializeToString() + self.value = msg.SerializeToString(deterministic=deterministic) def Unpack(self, msg): """Unpacks the current Any message into specified message.""" @@ -90,12 +93,17 @@ def TypeName(self): def Is(self, descriptor): """Checks if this Any represents the given protobuf type.""" - return self.TypeName() == descriptor.full_name + return '/' in self.type_url and self.TypeName() == descriptor.full_name + + +_EPOCH_DATETIME = datetime.utcfromtimestamp(0) class Timestamp(object): """Class for Timestamp message type.""" + __slots__ = () + def ToJsonString(self): """Converts Timestamp to RFC 3339 date string format. @@ -133,7 +141,7 @@ def FromJsonString(self, value): Example of accepted format: '1972-01-01T10:00:20.021-05:00' Raises: - ParseError: On parsing problems. + ValueError: On parsing problems. """ timezone_offset = value.find('Z') if timezone_offset == -1: @@ -141,7 +149,7 @@ def FromJsonString(self, value): if timezone_offset == -1: timezone_offset = value.rfind('-') if timezone_offset == -1: - raise ParseError( + raise ValueError( 'Failed to parse timestamp: missing valid timezone offset.') time_value = value[0:timezone_offset] # Parse datetime and nanos. @@ -152,11 +160,15 @@ def FromJsonString(self, value): else: second_value = time_value[:point_position] nano_value = time_value[point_position + 1:] + if 't' in second_value: + raise ValueError( + 'time data \'{0}\' does not match format \'%Y-%m-%dT%H:%M:%S\', ' + 'lowercase \'t\' is not accepted'.format(second_value)) date_object = datetime.strptime(second_value, _TIMESTAMPFOMAT) td = date_object - datetime(1970, 1, 1) seconds = td.seconds + td.days * _SECONDS_PER_DAY if len(nano_value) > 9: - raise ParseError( + raise ValueError( 'Failed to parse Timestamp: nanos {0} more than ' '9 fractional digits.'.format(nano_value)) if nano_value: @@ -166,13 +178,13 @@ def FromJsonString(self, value): # Parse timezone offsets. if value[timezone_offset] == 'Z': if len(value) != timezone_offset + 1: - raise ParseError('Failed to parse timestamp: invalid trailing' + raise ValueError('Failed to parse timestamp: invalid trailing' ' data {0}.'.format(value)) else: timezone = value[timezone_offset:] pos = timezone.find(':') if pos == -1: - raise ParseError( + raise ValueError( 'Invalid timezone offset value: {0}.'.format(timezone)) if timezone[0] == '+': seconds -= (int(timezone[1:pos])*60+int(timezone[pos+1:]))*60 @@ -226,19 +238,28 @@ def FromSeconds(self, seconds): def ToDatetime(self): """Converts Timestamp to datetime.""" - return datetime.utcfromtimestamp( - self.seconds + self.nanos / float(_NANOS_PER_SECOND)) + return _EPOCH_DATETIME + timedelta( + seconds=self.seconds, microseconds=_RoundTowardZero( + self.nanos, _NANOS_PER_MICROSECOND)) def FromDatetime(self, dt): """Converts datetime to Timestamp.""" - td = dt - datetime(1970, 1, 1) - self.seconds = td.seconds + td.days * _SECONDS_PER_DAY - self.nanos = td.microseconds * _NANOS_PER_MICROSECOND + # Using this guide: http://wiki.python.org/moin/WorkingWithTime + # And this conversion guide: http://docs.python.org/library/time.html + + # Turn the date parameter into a tuple (struct_time) that can then be + # manipulated into a long value of seconds. During the conversion from + # struct_time to long, the source date in UTC, and so it follows that the + # correct transformation is calendar.timegm() + self.seconds = calendar.timegm(dt.utctimetuple()) + self.nanos = dt.microsecond * _NANOS_PER_MICROSECOND class Duration(object): """Class for Duration message type.""" + __slots__ = () + def ToJsonString(self): """Converts Duration to string format. @@ -280,10 +301,10 @@ def FromJsonString(self, value): precision. For example: "1s", "1.01s", "1.0000001s", "-3.100s Raises: - ParseError: On parsing problems. + ValueError: On parsing problems. """ if len(value) < 1 or value[-1] != 's': - raise ParseError( + raise ValueError( 'Duration must end with letter "s": {0}.'.format(value)) try: pos = value.find('.') @@ -299,9 +320,9 @@ def FromJsonString(self, value): _CheckDurationValid(seconds, nanos) self.seconds = seconds self.nanos = nanos - except ValueError: - raise ParseError( - 'Couldn\'t parse duration: {0}.'.format(value)) + except ValueError as e: + raise ValueError( + 'Couldn\'t parse duration: {0} : {1}.'.format(value, e)) def ToNanoseconds(self): """Converts a Duration to nanoseconds.""" @@ -366,18 +387,21 @@ def _NormalizeDuration(self, seconds, nanos): def _CheckDurationValid(seconds, nanos): if seconds < -_DURATION_SECONDS_MAX or seconds > _DURATION_SECONDS_MAX: - raise Error( + raise ValueError( 'Duration is not valid: Seconds {0} must be in range ' '[-315576000000, 315576000000].'.format(seconds)) if nanos <= -_NANOS_PER_SECOND or nanos >= _NANOS_PER_SECOND: - raise Error( + raise ValueError( 'Duration is not valid: Nanos {0} must be in range ' '[-999999999, 999999999].'.format(nanos)) + if (nanos < 0 and seconds > 0) or (nanos > 0 and seconds < 0): + raise ValueError( + 'Duration is not valid: Sign mismatch.') def _RoundTowardZero(value, divider): """Truncates the remainder part after division.""" - # For some languanges, the sign of the remainder is implementation + # For some languages, the sign of the remainder is implementation # dependent if any of the operands is negative. Here we enforce # "rounded toward zero" semantics. For example, for (-5) / 2 an # implementation may give -3 as the result with the remainder being @@ -393,6 +417,8 @@ def _RoundTowardZero(value, divider): class FieldMask(object): """Class for FieldMask message type.""" + __slots__ = () + def ToJsonString(self): """Converts FieldMask to string according to proto3 JSON spec.""" camelcase_paths = [] @@ -403,8 +429,9 @@ def ToJsonString(self): def FromJsonString(self, value): """Converts string to FieldMask according to proto3 JSON spec.""" self.Clear() - for path in value.split(','): - self.paths.append(_CamelCaseToSnakeCase(path)) + if value: + for path in value.split(','): + self.paths.append(_CamelCaseToSnakeCase(path)) def IsValidForDescriptor(self, message_descriptor): """Checks whether the FieldMask is valid for Message Descriptor.""" @@ -473,7 +500,7 @@ def _IsValidPath(message_descriptor, path): parts = path.split('.') last = parts.pop() for name in parts: - field = message_descriptor.fields_by_name[name] + field = message_descriptor.fields_by_name.get(name) if (field is None or field.label == FieldDescriptor.LABEL_REPEATED or field.type != FieldDescriptor.TYPE_MESSAGE): @@ -497,24 +524,26 @@ def _SnakeCaseToCamelCase(path_name): after_underscore = False for c in path_name: if c.isupper(): - raise Error('Fail to print FieldMask to Json string: Path name ' - '{0} must not contain uppercase letters.'.format(path_name)) + raise ValueError( + 'Fail to print FieldMask to Json string: Path name ' + '{0} must not contain uppercase letters.'.format(path_name)) if after_underscore: if c.islower(): result.append(c.upper()) after_underscore = False else: - raise Error('Fail to print FieldMask to Json string: The ' - 'character after a "_" must be a lowercase letter ' - 'in path name {0}.'.format(path_name)) + raise ValueError( + 'Fail to print FieldMask to Json string: The ' + 'character after a "_" must be a lowercase letter ' + 'in path name {0}.'.format(path_name)) elif c == '_': after_underscore = True else: result += c if after_underscore: - raise Error('Fail to print FieldMask to Json string: Trailing "_" ' - 'in path name {0}.'.format(path_name)) + raise ValueError('Fail to print FieldMask to Json string: Trailing "_" ' + 'in path name {0}.'.format(path_name)) return ''.join(result) @@ -523,7 +552,7 @@ def _CamelCaseToSnakeCase(path_name): result = [] for c in path_name: if c == '_': - raise ParseError('Fail to parse FieldMask: Path name ' + raise ValueError('Fail to parse FieldMask: Path name ' '{0} must not contain "_"s.'.format(path_name)) if c.isupper(): result += '_' @@ -546,6 +575,8 @@ class _FieldMaskTree(object): In the tree, each leaf node represents a field path. """ + __slots__ = ('_root',) + def __init__(self, field_mask=None): """Initializes the tree by FieldMask.""" self._root = {} @@ -647,20 +678,17 @@ def _MergeMessage( raise ValueError('Error: Field {0} in message {1} is not a singular ' 'message field and cannot have sub-fields.'.format( name, source_descriptor.full_name)) - _MergeMessage( - child, getattr(source, name), getattr(destination, name), - replace_message, replace_repeated) + if source.HasField(name): + _MergeMessage( + child, getattr(source, name), getattr(destination, name), + replace_message, replace_repeated) continue if field.label == FieldDescriptor.LABEL_REPEATED: if replace_repeated: destination.ClearField(_StrConvert(name)) repeated_source = getattr(source, name) repeated_destination = getattr(destination, name) - if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE: - for item in repeated_source: - repeated_destination.add().MergeFrom(item) - else: - repeated_destination.extend(repeated_source) + repeated_destination.MergeFrom(repeated_source) else: if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE: if replace_message: @@ -673,7 +701,7 @@ def _MergeMessage( def _AddFieldPaths(node, prefix, field_mask): """Adds the field paths descended from node to field_mask.""" - if not node: + if not node and prefix: field_mask.paths.append(prefix) return for name in sorted(node): @@ -698,6 +726,12 @@ def _SetStructValue(struct_value, value): struct_value.string_value = value elif isinstance(value, _INT_OR_FLOAT): struct_value.number_value = value + elif isinstance(value, (dict, Struct)): + struct_value.struct_value.Clear() + struct_value.struct_value.update(value) + elif isinstance(value, (list, ListValue)): + struct_value.list_value.Clear() + struct_value.list_value.extend(value) else: raise ValueError('Unexpected type') @@ -723,28 +757,61 @@ def _GetStructValue(struct_value): class Struct(object): """Class for Struct message type.""" - __slots__ = [] + __slots__ = () def __getitem__(self, key): return _GetStructValue(self.fields[key]) + def __contains__(self, item): + return item in self.fields + def __setitem__(self, key, value): _SetStructValue(self.fields[key], value) + def __delitem__(self, key): + del self.fields[key] + + def __len__(self): + return len(self.fields) + + def __iter__(self): + return iter(self.fields) + + def keys(self): # pylint: disable=invalid-name + return self.fields.keys() + + def values(self): # pylint: disable=invalid-name + return [self[key] for key in self] + + def items(self): # pylint: disable=invalid-name + return [(key, self[key]) for key in self] + def get_or_create_list(self, key): """Returns a list for this key, creating if it didn't exist already.""" + if not self.fields[key].HasField('list_value'): + # Clear will mark list_value modified which will indeed create a list. + self.fields[key].list_value.Clear() return self.fields[key].list_value def get_or_create_struct(self, key): """Returns a struct for this key, creating if it didn't exist already.""" + if not self.fields[key].HasField('struct_value'): + # Clear will mark struct_value modified which will indeed create a struct. + self.fields[key].struct_value.Clear() return self.fields[key].struct_value - # TODO(haberman): allow constructing/merging from dict. + def update(self, dictionary): # pylint: disable=invalid-name + for key, value in dictionary.items(): + _SetStructValue(self.fields[key], value) + +collections_abc.MutableMapping.register(Struct) class ListValue(object): """Class for ListValue message type.""" + __slots__ = () + def __len__(self): return len(self.values) @@ -762,17 +829,28 @@ def __getitem__(self, index): def __setitem__(self, index, value): _SetStructValue(self.values.__getitem__(index), value) + def __delitem__(self, key): + del self.values[key] + def items(self): for i in range(len(self)): yield self[i] def add_struct(self): """Appends and returns a struct value as the next value in the list.""" - return self.values.add().struct_value + struct_value = self.values.add().struct_value + # Clear will mark struct_value modified which will indeed create a struct. + struct_value.Clear() + return struct_value def add_list(self): """Appends and returns a list value as the next value in the list.""" - return self.values.add().list_value + list_value = self.values.add().list_value + # Clear will mark list_value modified which will indeed create a list. + list_value.Clear() + return list_value + +collections_abc.MutableSequence.register(ListValue) WKTBASES = { diff --git a/python/google/protobuf/internal/well_known_types_test.py b/python/google/protobuf/internal/well_known_types_test.py old mode 100644 new mode 100755 index 123a537cb0a43..8089f035c6a82 --- a/python/google/protobuf/internal/well_known_types_test.py +++ b/python/google/protobuf/internal/well_known_types_test.py @@ -34,7 +34,14 @@ __author__ = 'jieluo@google.com (Jie Luo)' -from datetime import datetime +import datetime + +try: + # Since python 3 + import collections.abc as collections_abc +except ImportError: + # Won't work after python 3.8 + import collections as collections_abc try: import unittest2 as unittest #PY26 @@ -46,6 +53,7 @@ from google.protobuf import field_mask_pb2 from google.protobuf import struct_pb2 from google.protobuf import timestamp_pb2 +from google.protobuf import map_unittest_pb2 from google.protobuf import unittest_pb2 from google.protobuf.internal import any_test_pb2 from google.protobuf.internal import test_util @@ -100,11 +108,15 @@ def testTimestampSerializeAndParse(self): message.FromJsonString('1970-01-01T00:00:00.1Z') self.assertEqual(0, message.seconds) self.assertEqual(100000000, message.nanos) - # Parsing accpets offsets. + # Parsing accepts offsets. message.FromJsonString('1970-01-01T00:00:00-08:00') self.assertEqual(8 * 3600, message.seconds) self.assertEqual(0, message.nanos) + # It is not easy to check with current time. For test coverage only. + message.GetCurrentTime() + self.assertNotEqual(8 * 3600, message.seconds) + def testDurationSerializeAndParse(self): message = duration_pb2.Duration() # Generated output should contain 3, 6, or 9 fractional digits. @@ -235,14 +247,42 @@ def testDurationIntegerConversion(self): def testDatetimeConverison(self): message = timestamp_pb2.Timestamp() - dt = datetime(1970, 1, 1) + dt = datetime.datetime(1970, 1, 1) message.FromDatetime(dt) self.assertEqual(dt, message.ToDatetime()) message.FromMilliseconds(1999) - self.assertEqual(datetime(1970, 1, 1, 0, 0, 1, 999000), + self.assertEqual(datetime.datetime(1970, 1, 1, 0, 0, 1, 999000), message.ToDatetime()) + dt = datetime.datetime(2555, 2, 22, 1, 2, 3, 456789) + message.FromDatetime(dt) + self.assertEqual(dt, message.ToDatetime()) + + dt = datetime.datetime.max + message.FromDatetime(dt) + self.assertEqual(dt, message.ToDatetime()) + + def testDatetimeConversionWithTimezone(self): + class TZ(datetime.tzinfo): + + def utcoffset(self, _): + return datetime.timedelta(hours=1) + + def dst(self, _): + return datetime.timedelta(0) + + def tzname(self, _): + return 'UTC+1' + + message1 = timestamp_pb2.Timestamp() + dt = datetime.datetime(1970, 1, 1, 1, tzinfo=TZ()) + message1.FromDatetime(dt) + message2 = timestamp_pb2.Timestamp() + dt = datetime.datetime(1970, 1, 1, 0) + message2.FromDatetime(dt) + self.assertEqual(message1, message2) + def testTimedeltaConversion(self): message = duration_pb2.Duration() message.FromNanoseconds(1999999999) @@ -267,18 +307,29 @@ def testTimedeltaConversion(self): def testInvalidTimestamp(self): message = timestamp_pb2.Timestamp() + self.assertRaisesRegexp( + ValueError, + 'Failed to parse timestamp: missing valid timezone offset.', + message.FromJsonString, + '') + self.assertRaisesRegexp( + ValueError, + 'Failed to parse timestamp: invalid trailing data ' + '1970-01-01T00:00:01Ztrail.', + message.FromJsonString, + '1970-01-01T00:00:01Ztrail') self.assertRaisesRegexp( ValueError, 'time data \'10000-01-01T00:00:00\' does not match' ' format \'%Y-%m-%dT%H:%M:%S\'', message.FromJsonString, '10000-01-01T00:00:00.00Z') self.assertRaisesRegexp( - well_known_types.ParseError, + ValueError, 'nanos 0123456789012 more than 9 fractional digits.', message.FromJsonString, '1970-01-01T00:00:00.0123456789012Z') self.assertRaisesRegexp( - well_known_types.ParseError, + ValueError, (r'Invalid timezone offset value: \+08.'), message.FromJsonString, '1972-01-01T01:00:00.01+08',) @@ -296,32 +347,45 @@ def testInvalidTimestamp(self): def testInvalidDuration(self): message = duration_pb2.Duration() self.assertRaisesRegexp( - well_known_types.ParseError, + ValueError, 'Duration must end with letter "s": 1.', message.FromJsonString, '1') self.assertRaisesRegexp( - well_known_types.ParseError, + ValueError, 'Couldn\'t parse duration: 1...2s.', message.FromJsonString, '1...2s') text = '-315576000001.000000000s' self.assertRaisesRegexp( - well_known_types.Error, + ValueError, r'Duration is not valid\: Seconds -315576000001 must be in range' r' \[-315576000000\, 315576000000\].', message.FromJsonString, text) text = '315576000001.000000000s' self.assertRaisesRegexp( - well_known_types.Error, + ValueError, r'Duration is not valid\: Seconds 315576000001 must be in range' r' \[-315576000000\, 315576000000\].', message.FromJsonString, text) message.seconds = -315576000001 message.nanos = 0 self.assertRaisesRegexp( - well_known_types.Error, + ValueError, r'Duration is not valid\: Seconds -315576000001 must be in range' r' \[-315576000000\, 315576000000\].', message.ToJsonString) + message.seconds = 0 + message.nanos = 999999999 + 1 + self.assertRaisesRegexp( + ValueError, + r'Duration is not valid\: Nanos 1000000000 must be in range' + r' \[-999999999\, 999999999\].', + message.ToJsonString) + message.seconds = -1 + message.nanos = 1 + self.assertRaisesRegexp( + ValueError, + r'Duration is not valid\: Sign mismatch.', + message.ToJsonString) class FieldMaskTest(unittest.TestCase): @@ -350,6 +414,7 @@ def testStringFormat(self): mask.FromJsonString('') self.assertEqual('', mask.ToJsonString()) + self.assertEqual([], mask.paths) mask.FromJsonString('fooBar') self.assertEqual(['foo_bar'], mask.paths) mask.FromJsonString('fooBar,barQuz') @@ -363,10 +428,37 @@ def testDescriptorToFieldMask(self): self.assertTrue(mask.IsValidForDescriptor(msg_descriptor)) for field in msg_descriptor.fields: self.assertTrue(field.name in mask.paths) + + def testIsValidForDescriptor(self): + msg_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + # Empty mask + mask = field_mask_pb2.FieldMask() + self.assertTrue(mask.IsValidForDescriptor(msg_descriptor)) + # All fields from descriptor + mask.AllFieldsFromDescriptor(msg_descriptor) + self.assertTrue(mask.IsValidForDescriptor(msg_descriptor)) + # Child under optional message mask.paths.append('optional_nested_message.bb') self.assertTrue(mask.IsValidForDescriptor(msg_descriptor)) + # Repeated field is only allowed in the last position of path mask.paths.append('repeated_nested_message.bb') self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) + # Invalid top level field + mask = field_mask_pb2.FieldMask() + mask.paths.append('xxx') + self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) + # Invalid field in root + mask = field_mask_pb2.FieldMask() + mask.paths.append('xxx.zzz') + self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) + # Invalid field in internal node + mask = field_mask_pb2.FieldMask() + mask.paths.append('optional_nested_message.xxx.zzz') + self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) + # Invalid field in leaf + mask = field_mask_pb2.FieldMask() + mask.paths.append('optional_nested_message.xxx') + self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) def testCanonicalFrom(self): mask = field_mask_pb2.FieldMask() @@ -422,6 +514,9 @@ def testUnion(self): mask2.FromJsonString('foo.bar,bar') out_mask.Union(mask1, mask2) self.assertEqual('bar,foo.bar,quz', out_mask.ToJsonString()) + src = unittest_pb2.TestAllTypes() + with self.assertRaises(ValueError): + out_mask.Union(src, mask2) def testIntersect(self): mask1 = field_mask_pb2.FieldMask() @@ -432,6 +527,8 @@ def testIntersect(self): mask2.FromJsonString('bar,quz') out_mask.Intersect(mask1, mask2) self.assertEqual('', out_mask.ToJsonString()) + self.assertEqual(len(out_mask.paths), 0) + self.assertEqual(out_mask.paths, []) # Overlap with duplicated paths. mask1.FromJsonString('foo,baz.bb') mask2.FromJsonString('baz.bb,quz') @@ -446,8 +543,17 @@ def testIntersect(self): mask2.FromJsonString('foo.bar.baz,quz') out_mask.Intersect(mask1, mask2) self.assertEqual('foo.bar.baz', out_mask.ToJsonString()) + # Intersect '' with '' + mask1.Clear() + mask2.Clear() + mask1.paths.append('') + mask2.paths.append('') + self.assertEqual(mask1.paths, ['']) + self.assertEqual('', mask1.ToJsonString()) + out_mask.Intersect(mask1, mask2) + self.assertEqual(out_mask.paths, []) - def testMergeMessage(self): + def testMergeMessageWithoutMapFields(self): # Test merge one field. src = unittest_pb2.TestAllTypes() test_util.SetAllFields(src) @@ -546,6 +652,52 @@ def testMergeMessage(self): self.assertEqual(1, len(nested_dst.payload.repeated_int32)) self.assertEqual(1234, nested_dst.payload.repeated_int32[0]) + # Test Merge oneof field. + new_msg = unittest_pb2.TestOneof2() + dst = unittest_pb2.TestOneof2() + dst.foo_message.qux_int = 1 + mask = field_mask_pb2.FieldMask() + mask.FromJsonString('fooMessage,fooLazyMessage.quxInt') + mask.MergeMessage(new_msg, dst) + self.assertTrue(dst.HasField('foo_message')) + self.assertFalse(dst.HasField('foo_lazy_message')) + + def testMergeMessageWithMapField(self): + empty_map = map_unittest_pb2.TestRecursiveMapMessage() + src_level_2 = map_unittest_pb2.TestRecursiveMapMessage() + src_level_2.a['src level 2'].CopyFrom(empty_map) + src = map_unittest_pb2.TestRecursiveMapMessage() + src.a['common key'].CopyFrom(src_level_2) + src.a['src level 1'].CopyFrom(src_level_2) + + dst_level_2 = map_unittest_pb2.TestRecursiveMapMessage() + dst_level_2.a['dst level 2'].CopyFrom(empty_map) + dst = map_unittest_pb2.TestRecursiveMapMessage() + dst.a['common key'].CopyFrom(dst_level_2) + dst.a['dst level 1'].CopyFrom(empty_map) + + mask = field_mask_pb2.FieldMask() + mask.FromJsonString('a') + mask.MergeMessage(src, dst) + + # map from dst is replaced with map from src. + self.assertEqual(dst.a['common key'], src_level_2) + self.assertEqual(dst.a['src level 1'], src_level_2) + self.assertEqual(dst.a['dst level 1'], empty_map) + + def testMergeErrors(self): + src = unittest_pb2.TestAllTypes() + dst = unittest_pb2.TestAllTypes() + mask = field_mask_pb2.FieldMask() + test_util.SetAllFields(src) + mask.FromJsonString('optionalInt32.field') + with self.assertRaises(ValueError) as e: + mask.MergeMessage(src, dst) + self.assertEqual('Error: Field optional_int32 in message ' + 'protobuf_unittest.TestAllTypes is not a singular ' + 'message field and cannot have sub-fields.', + str(e.exception)) + def testSnakeCaseToCamelCase(self): self.assertEqual('fooBar', well_known_types._SnakeCaseToCamelCase('foo_bar')) @@ -556,7 +708,7 @@ def testSnakeCaseToCamelCase(self): # No uppercase letter is allowed. self.assertRaisesRegexp( - well_known_types.Error, + ValueError, 'Fail to print FieldMask to Json string: Path name Foo must ' 'not contain uppercase letters.', well_known_types._SnakeCaseToCamelCase, @@ -566,19 +718,19 @@ def testSnakeCaseToCamelCase(self): # 2. "_" cannot be followed by a digit. # 3. "_" cannot appear as the last character. self.assertRaisesRegexp( - well_known_types.Error, + ValueError, 'Fail to print FieldMask to Json string: The character after a ' '"_" must be a lowercase letter in path name foo__bar.', well_known_types._SnakeCaseToCamelCase, 'foo__bar') self.assertRaisesRegexp( - well_known_types.Error, + ValueError, 'Fail to print FieldMask to Json string: The character after a ' '"_" must be a lowercase letter in path name foo_3bar.', well_known_types._SnakeCaseToCamelCase, 'foo_3bar') self.assertRaisesRegexp( - well_known_types.Error, + ValueError, 'Fail to print FieldMask to Json string: Trailing "_" in path ' 'name foo_bar_.', well_known_types._SnakeCaseToCamelCase, @@ -592,7 +744,7 @@ def testCamelCaseToSnakeCase(self): self.assertEqual('foo3_bar', well_known_types._CamelCaseToSnakeCase('foo3Bar')) self.assertRaisesRegexp( - well_known_types.ParseError, + ValueError, 'Fail to parse FieldMask: Path name foo_bar must not contain "_"s.', well_known_types._CamelCaseToSnakeCase, 'foo_bar') @@ -602,6 +754,8 @@ class StructTest(unittest.TestCase): def testStruct(self): struct = struct_pb2.Struct() + self.assertIsInstance(struct, collections_abc.Mapping) + self.assertEqual(0, len(struct)) struct_class = struct.__class__ struct['key1'] = 5 @@ -609,9 +763,13 @@ def testStruct(self): struct['key3'] = True struct.get_or_create_struct('key4')['subkey'] = 11.0 struct_list = struct.get_or_create_list('key5') + self.assertIsInstance(struct_list, collections_abc.Sequence) struct_list.extend([6, 'seven', True, False, None]) struct_list.add_struct()['subkey2'] = 9 + struct['key6'] = {'subkey': {}} + struct['key7'] = [2, False] + self.assertEqual(7, len(struct)) self.assertTrue(isinstance(struct, well_known_types.Struct)) self.assertEqual(5, struct['key1']) self.assertEqual('abc', struct['key2']) @@ -621,13 +779,28 @@ def testStruct(self): inner_struct['subkey2'] = 9 self.assertEqual([6, 'seven', True, False, None, inner_struct], list(struct['key5'].items())) + self.assertEqual({}, dict(struct['key6']['subkey'].fields)) + self.assertEqual([2, False], list(struct['key7'].items())) serialized = struct.SerializeToString() - struct2 = struct_pb2.Struct() struct2.ParseFromString(serialized) self.assertEqual(struct, struct2) + for key, value in struct.items(): + self.assertIn(key, struct) + self.assertIn(key, struct2) + self.assertEqual(value, struct2[key]) + + self.assertEqual(7, len(struct.keys())) + self.assertEqual(7, len(struct.values())) + for key in struct.keys(): + self.assertIn(key, struct) + self.assertIn(key, struct2) + self.assertEqual(struct[key], struct2[key]) + + item = (next(iter(struct.keys())), next(iter(struct.values()))) + self.assertEqual(item, next(iter(struct.items()))) self.assertTrue(isinstance(struct2, well_known_types.Struct)) self.assertEqual(5, struct2['key1']) @@ -651,6 +824,17 @@ def testStruct(self): struct_list.add_list().extend([1, 'two', True, False, None]) self.assertEqual([1, 'two', True, False, None], list(struct_list[6].items())) + struct_list.extend([{'nested_struct': 30}, ['nested_list', 99], {}, []]) + self.assertEqual(11, len(struct_list.values)) + self.assertEqual(30, struct_list[7]['nested_struct']) + self.assertEqual('nested_list', struct_list[8][0]) + self.assertEqual(99, struct_list[8][1]) + self.assertEqual({}, dict(struct_list[9].fields)) + self.assertEqual([], list(struct_list[10].items())) + struct_list[0] = {'replace': 'set'} + struct_list[1] = ['replace', 'set'] + self.assertEqual('set', struct_list[0]['replace']) + self.assertEqual(['replace', 'set'], list(struct_list[1].items())) text_serialized = str(struct) struct3 = struct_pb2.Struct() @@ -660,6 +844,86 @@ def testStruct(self): struct.get_or_create_struct('key3')['replace'] = 12 self.assertEqual(12, struct['key3']['replace']) + # Tests empty list. + struct.get_or_create_list('empty_list') + empty_list = struct['empty_list'] + self.assertEqual([], list(empty_list.items())) + list2 = struct_pb2.ListValue() + list2.add_list() + empty_list = list2[0] + self.assertEqual([], list(empty_list.items())) + + # Tests empty struct. + struct.get_or_create_struct('empty_struct') + empty_struct = struct['empty_struct'] + self.assertEqual({}, dict(empty_struct.fields)) + list2.add_struct() + empty_struct = list2[1] + self.assertEqual({}, dict(empty_struct.fields)) + + self.assertEqual(9, len(struct)) + del struct['key3'] + del struct['key4'] + self.assertEqual(7, len(struct)) + self.assertEqual(6, len(struct['key5'])) + del struct['key5'][1] + self.assertEqual(5, len(struct['key5'])) + self.assertEqual([6, True, False, None, inner_struct], + list(struct['key5'].items())) + + def testStructAssignment(self): + # Tests struct assignment from another struct + s1 = struct_pb2.Struct() + s2 = struct_pb2.Struct() + for value in [1, 'a', [1], ['a'], {'a': 'b'}]: + s1['x'] = value + s2['x'] = s1['x'] + self.assertEqual(s1['x'], s2['x']) + + def testMergeFrom(self): + struct = struct_pb2.Struct() + struct_class = struct.__class__ + + dictionary = { + 'key1': 5, + 'key2': 'abc', + 'key3': True, + 'key4': {'subkey': 11.0}, + 'key5': [6, 'seven', True, False, None, {'subkey2': 9}], + 'key6': [['nested_list', True]], + 'empty_struct': {}, + 'empty_list': [] + } + struct.update(dictionary) + self.assertEqual(5, struct['key1']) + self.assertEqual('abc', struct['key2']) + self.assertIs(True, struct['key3']) + self.assertEqual(11, struct['key4']['subkey']) + inner_struct = struct_class() + inner_struct['subkey2'] = 9 + self.assertEqual([6, 'seven', True, False, None, inner_struct], + list(struct['key5'].items())) + self.assertEqual(2, len(struct['key6'][0].values)) + self.assertEqual('nested_list', struct['key6'][0][0]) + self.assertEqual(True, struct['key6'][0][1]) + empty_list = struct['empty_list'] + self.assertEqual([], list(empty_list.items())) + empty_struct = struct['empty_struct'] + self.assertEqual({}, dict(empty_struct.fields)) + + # According to documentation: "When parsing from the wire or when merging, + # if there are duplicate map keys the last key seen is used". + duplicate = { + 'key4': {'replace': 20}, + 'key5': [[False, 5]] + } + struct.update(duplicate) + self.assertEqual(1, len(struct['key4'].fields)) + self.assertEqual(20, struct['key4']['replace']) + self.assertEqual(1, len(struct['key5'].values)) + self.assertEqual(False, struct['key5'][0][0]) + self.assertEqual(5, struct['key5'][0][1]) + class AnyTest(unittest.TestCase): @@ -694,6 +958,17 @@ def testAnyMessage(self): raise AttributeError('%s should not have Pack method.' % msg_descriptor.full_name) + def testUnpackWithNoSlashInTypeUrl(self): + msg = any_test_pb2.TestAny() + all_types = unittest_pb2.TestAllTypes() + all_descriptor = all_types.DESCRIPTOR + msg.value.Pack(all_types) + # Reset type_url to part of type_url after '/' + msg.value.type_url = msg.value.TypeName() + self.assertFalse(msg.value.Is(all_descriptor)) + unpacked_message = unittest_pb2.TestAllTypes() + self.assertFalse(msg.value.Unpack(unpacked_message)) + def testMessageName(self): # Creates and sets message. submessage = any_test_pb2.TestAny() @@ -723,6 +998,20 @@ def testPackWithCustomTypeUrl(self): self.assertTrue(msg.Unpack(unpacked_message)) self.assertEqual(submessage, unpacked_message) + def testPackDeterministic(self): + submessage = any_test_pb2.TestAny() + for i in range(10): + submessage.map_value[str(i)] = i * 2 + msg = any_pb2.Any() + msg.Pack(submessage, deterministic=True) + serialized = msg.SerializeToString(deterministic=True) + golden = (b'\n4type.googleapis.com/google.protobuf.internal.TestAny\x12F' + b'\x1a\x05\n\x010\x10\x00\x1a\x05\n\x011\x10\x02\x1a\x05\n\x01' + b'2\x10\x04\x1a\x05\n\x013\x10\x06\x1a\x05\n\x014\x10\x08\x1a' + b'\x05\n\x015\x10\n\x1a\x05\n\x016\x10\x0c\x1a\x05\n\x017\x10' + b'\x0e\x1a\x05\n\x018\x10\x10\x1a\x05\n\x019\x10\x12') + self.assertEqual(golden, serialized) + if __name__ == '__main__': unittest.main() diff --git a/python/google/protobuf/internal/wire_format.py b/python/google/protobuf/internal/wire_format.py old mode 100755 new mode 100644 diff --git a/python/google/protobuf/json_format.py b/python/google/protobuf/json_format.py index 801eed60e4780..c8f5602f36b11 100644 --- a/python/google/protobuf/json_format.py +++ b/python/google/protobuf/json_format.py @@ -42,21 +42,29 @@ __author__ = 'jieluo@google.com (Jie Luo)' +# pylint: disable=g-statement-before-imports,g-import-not-at-top try: from collections import OrderedDict except ImportError: - from ordereddict import OrderedDict #PY26 + from ordereddict import OrderedDict # PY26 +# pylint: enable=g-statement-before-imports,g-import-not-at-top + import base64 import json import math + +from operator import methodcaller + import re -import six import sys -from operator import methodcaller +import six + +from google.protobuf.internal import type_checkers from google.protobuf import descriptor from google.protobuf import symbol_database + _TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S' _INT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT32, descriptor.FieldDescriptor.CPPTYPE_UINT32, @@ -89,11 +97,15 @@ class ParseError(Error): """Thrown in case of parsing error.""" -def MessageToJson(message, - including_default_value_fields=False, - preserving_proto_field_name=False, - indent=2, - sort_keys=False): +def MessageToJson( + message, + including_default_value_fields=False, + preserving_proto_field_name=False, + indent=2, + sort_keys=False, + use_integers_for_enums=False, + descriptor_pool=None, + float_precision=None): """Converts protobuf message to JSON format. Args: @@ -108,18 +120,30 @@ def MessageToJson(message, indent: The JSON object will be pretty-printed with this indent level. An indent level of 0 or negative will only insert newlines. sort_keys: If True, then the output will be sorted by field names. + use_integers_for_enums: If true, print integers instead of enum names. + descriptor_pool: A Descriptor Pool for resolving types. If None use the + default. + float_precision: If set, use this to specify float field valid digits. Returns: A string containing the JSON formatted protocol buffer message. """ - printer = _Printer(including_default_value_fields, - preserving_proto_field_name) + printer = _Printer( + including_default_value_fields, + preserving_proto_field_name, + use_integers_for_enums, + descriptor_pool, + float_precision=float_precision) return printer.ToJsonString(message, indent, sort_keys) -def MessageToDict(message, - including_default_value_fields=False, - preserving_proto_field_name=False): +def MessageToDict( + message, + including_default_value_fields=False, + preserving_proto_field_name=False, + use_integers_for_enums=False, + descriptor_pool=None, + float_precision=None): """Converts protobuf message to a dictionary. When the dictionary is encoded to JSON, it conforms to proto3 JSON spec. @@ -133,12 +157,20 @@ def MessageToDict(message, preserving_proto_field_name: If True, use the original proto field names as defined in the .proto file. If False, convert the field names to lowerCamelCase. + use_integers_for_enums: If true, print integers instead of enum names. + descriptor_pool: A Descriptor Pool for resolving types. If None use the + default. + float_precision: If set, use this to specify float field valid digits. Returns: A dict representation of the protocol buffer message. """ - printer = _Printer(including_default_value_fields, - preserving_proto_field_name) + printer = _Printer( + including_default_value_fields, + preserving_proto_field_name, + use_integers_for_enums, + descriptor_pool, + float_precision=float_precision) # pylint: disable=protected-access return printer._MessageToJsonObject(message) @@ -152,11 +184,21 @@ def _IsMapEntry(field): class _Printer(object): """JSON format printer for protocol message.""" - def __init__(self, - including_default_value_fields=False, - preserving_proto_field_name=False): + def __init__( + self, + including_default_value_fields=False, + preserving_proto_field_name=False, + use_integers_for_enums=False, + descriptor_pool=None, + float_precision=None): self.including_default_value_fields = including_default_value_fields self.preserving_proto_field_name = preserving_proto_field_name + self.use_integers_for_enums = use_integers_for_enums + self.descriptor_pool = descriptor_pool + if float_precision: + self.float_format = '.{}g'.format(float_precision) + else: + self.float_format = None def ToJsonString(self, message, indent, sort_keys): js = self._MessageToJsonObject(message) @@ -203,12 +245,7 @@ def _RegularMessageToJsonObject(self, message, js): js[name] = [self._FieldToJsonObject(field, k) for k in value] elif field.is_extension: - f = field - if (f.containing_type.GetOptions().message_set_wire_format and - f.type == descriptor.FieldDescriptor.TYPE_MESSAGE and - f.label == descriptor.FieldDescriptor.LABEL_OPTIONAL): - f = f.message_type - name = '[%s.%s]' % (f.full_name, name) + name = '[%s]' % field.full_name js[name] = self._FieldToJsonObject(field, value) else: js[name] = self._FieldToJsonObject(field, value) @@ -227,7 +264,7 @@ def _RegularMessageToJsonObject(self, message, js): else: name = field.json_name if name in js: - # Skip the field which has been serailized already. + # Skip the field which has been serialized already. continue if _IsMapEntry(field): js[name] = {} @@ -247,10 +284,16 @@ def _FieldToJsonObject(self, field, value): if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: return self._MessageToJsonObject(value) elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM: + if self.use_integers_for_enums: + return value + if field.enum_type.full_name == 'google.protobuf.NullValue': + return None enum_value = field.enum_type.values_by_number.get(value, None) if enum_value is not None: return enum_value.name else: + if field.file.syntax == 'proto3': + return value raise SerializeToJsonError('Enum field contains an integer value ' 'which can not mapped to an enum value.') elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING: @@ -271,6 +314,12 @@ def _FieldToJsonObject(self, field, value): return _INFINITY if math.isnan(value): return _NAN + if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT: + if self.float_format: + return float(format(value, self.float_format)) + else: + return type_checkers.ToShortestFloat(value) + return value def _AnyMessageToJsonObject(self, message): @@ -281,7 +330,7 @@ def _AnyMessageToJsonObject(self, message): js = OrderedDict() type_url = message.type_url js['@type'] = type_url - sub_message = _CreateMessageFromTypeUrl(type_url) + sub_message = _CreateMessageFromTypeUrl(type_url, self.descriptor_pool) sub_message.ParseFromString(message.value) message_descriptor = sub_message.DESCRIPTOR full_name = message_descriptor.full_name @@ -347,13 +396,13 @@ def _DuplicateChecker(js): return result -def _CreateMessageFromTypeUrl(type_url): - # TODO(jieluo): Should add a way that users can register the type resolver - # instead of the default one. +def _CreateMessageFromTypeUrl(type_url, descriptor_pool): + """Creates a message from a type URL.""" db = symbol_database.Default() + pool = db.pool if descriptor_pool is None else descriptor_pool type_name = type_url.split('/')[-1] try: - message_descriptor = db.pool.FindMessageTypeByName(type_name) + message_descriptor = pool.FindMessageTypeByName(type_name) except KeyError: raise TypeError( 'Can not find message descriptor by type_url: {0}.'.format(type_url)) @@ -361,13 +410,15 @@ def _CreateMessageFromTypeUrl(type_url): return message_class() -def Parse(text, message, ignore_unknown_fields=False): +def Parse(text, message, ignore_unknown_fields=False, descriptor_pool=None): """Parses a JSON representation of a protocol message into a message. Args: text: Message JSON representation. message: A protocol buffer message to merge into. ignore_unknown_fields: If True, do not raise errors for unknown fields. + descriptor_pool: A Descriptor Pool for resolving types. If None use the + default. Returns: The same message passed as argument. @@ -377,28 +428,29 @@ def Parse(text, message, ignore_unknown_fields=False): """ if not isinstance(text, six.text_type): text = text.decode('utf-8') try: - if sys.version_info < (2, 7): - # object_pair_hook is not supported before python2.7 - js = json.loads(text) - else: - js = json.loads(text, object_pairs_hook=_DuplicateChecker) + js = json.loads(text, object_pairs_hook=_DuplicateChecker) except ValueError as e: raise ParseError('Failed to load JSON: {0}.'.format(str(e))) - return ParseDict(js, message, ignore_unknown_fields) + return ParseDict(js, message, ignore_unknown_fields, descriptor_pool) -def ParseDict(js_dict, message, ignore_unknown_fields=False): +def ParseDict(js_dict, + message, + ignore_unknown_fields=False, + descriptor_pool=None): """Parses a JSON dictionary representation into a message. Args: js_dict: Dict representation of a JSON message. message: A protocol buffer message to merge into. ignore_unknown_fields: If True, do not raise errors for unknown fields. + descriptor_pool: A Descriptor Pool for resolving types. If None use the + default. Returns: The same message passed as argument. """ - parser = _Parser(ignore_unknown_fields) + parser = _Parser(ignore_unknown_fields, descriptor_pool) parser.ConvertMessage(js_dict, message) return message @@ -409,9 +461,9 @@ def ParseDict(js_dict, message, ignore_unknown_fields=False): class _Parser(object): """JSON format parser for protocol message.""" - def __init__(self, - ignore_unknown_fields): + def __init__(self, ignore_unknown_fields, descriptor_pool): self.ignore_unknown_fields = ignore_unknown_fields + self.descriptor_pool = descriptor_pool def ConvertMessage(self, value, message): """Convert a JSON object into a message. @@ -456,10 +508,16 @@ def _ConvertFieldValuePair(self, js, message): raise ParseError('Message type {0} does not have extensions'.format( message_descriptor.full_name)) identifier = name[1:-1] # strip [] brackets - identifier = '.'.join(identifier.split('.')[:-1]) # pylint: disable=protected-access field = message.Extensions._FindExtensionByName(identifier) # pylint: enable=protected-access + if not field: + # Try looking for extension by the message type name, dropping the + # field name following the final . separator in full_name. + identifier = '.'.join(identifier.split('.')[:-1]) + # pylint: disable=protected-access + field = message.Extensions._FindExtensionByName(identifier) + # pylint: enable=protected-access if not field: if self.ignore_unknown_fields: continue @@ -467,7 +525,7 @@ def _ConvertFieldValuePair(self, js, message): ('Message type "{0}" has no field named "{1}".\n' ' Available Fields(except extensions): {2}').format( message_descriptor.full_name, name, - message_descriptor.fields)) + [f.json_name for f in message_descriptor.fields])) if name in names: raise ParseError('Message type "{0}" should not have multiple ' '"{1}" fields.'.format( @@ -488,6 +546,9 @@ def _ConvertFieldValuePair(self, js, message): and field.message_type.full_name == 'google.protobuf.Value'): sub_message = getattr(message, field.name) sub_message.null_value = 0 + elif (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM + and field.enum_type.full_name == 'google.protobuf.NullValue'): + setattr(message, field.name, 0) else: message.ClearField(field.name) continue @@ -527,10 +588,13 @@ def _ConvertFieldValuePair(self, js, message): sub_message.SetInParent() self.ConvertMessage(value, sub_message) else: - setattr(message, field.name, _ConvertScalarFieldValue(value, field)) + if field.is_extension: + message.Extensions[field] = _ConvertScalarFieldValue(value, field) + else: + setattr(message, field.name, _ConvertScalarFieldValue(value, field)) except ParseError as e: if field and field.containing_oneof is None: - raise ParseError('Failed to parse {0} field: {1}'.format(name, e)) + raise ParseError('Failed to parse {0} field: {1}.'.format(name, e)) else: raise ParseError(str(e)) except ValueError as e: @@ -547,7 +611,7 @@ def _ConvertAnyMessage(self, value, message): except KeyError: raise ParseError('@type is missing when parsing any message.') - sub_message = _CreateMessageFromTypeUrl(type_url) + sub_message = _CreateMessageFromTypeUrl(type_url, self.descriptor_pool) message_descriptor = sub_message.DESCRIPTOR full_name = message_descriptor.full_name if _IsWrapperMessage(message_descriptor): @@ -558,6 +622,7 @@ def _ConvertAnyMessage(self, value, message): else: del value['@type'] self._ConvertFieldValuePair(value, sub_message) + value['@type'] = type_url # Sets Any message message.value = sub_message.SerializeToString() message.type_url = type_url @@ -566,7 +631,10 @@ def _ConvertGenericMessage(self, value, message): """Convert a JSON representation into message with FromJsonString.""" # Duration, Timestamp, FieldMask have a FromJsonString method to do the # conversion. Users can also call the method directly. - message.FromJsonString(value) + try: + message.FromJsonString(value) + except ValueError as e: + raise ParseError(e) def _ConvertValueMessage(self, value, message): """Convert a JSON representation into Value message.""" @@ -583,7 +651,8 @@ def _ConvertValueMessage(self, value, message): elif isinstance(value, _INT_OR_FLOAT): message.number_value = value else: - raise ParseError('Unexpected type for Value message.') + raise ParseError('Value {0} has unexpected type {1}.'.format( + value, type(value))) def _ConvertListValueMessage(self, value, message): """Convert a JSON representation into ListValue message.""" @@ -599,6 +668,9 @@ def _ConvertStructMessage(self, value, message): if not isinstance(value, dict): raise ParseError( 'Struct must be in a dict which is {0}.'.format(value)) + # Clear will mark the struct as modified so it will be created even if + # there are no values. + message.Clear() for key in value: self._ConvertValueMessage(value[key], message.fields[key]) return @@ -652,12 +724,18 @@ def _ConvertScalarFieldValue(value, field, require_str=False): if field.cpp_type in _INT_TYPES: return _ConvertInteger(value) elif field.cpp_type in _FLOAT_TYPES: - return _ConvertFloat(value) + return _ConvertFloat(value, field) elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL: return _ConvertBool(value, require_str) elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING: if field.type == descriptor.FieldDescriptor.TYPE_BYTES: - return base64.b64decode(value) + if isinstance(value, six.text_type): + encoded = value.encode('utf-8') + else: + encoded = value + # Add extra padding '=' + padded_value = encoded + b'=' * (4 - len(encoded) % 4) + return base64.urlsafe_b64decode(padded_value) else: # Checking for unpaired surrogates appears to be unreliable, # depending on the specific Python version, so we check manually. @@ -675,6 +753,9 @@ def _ConvertScalarFieldValue(value, field, require_str=False): raise ParseError('Invalid enum value {0} for enum type {1}.'.format( value, field.enum_type.full_name)) if enum_value is None: + if field.file.syntax == 'proto3': + # Proto3 accepts unknown enums. + return number raise ParseError('Invalid enum value {0} for enum type {1}.'.format( value, field.enum_type.full_name)) return enum_value.number @@ -698,11 +779,32 @@ def _ConvertInteger(value): if isinstance(value, six.text_type) and value.find(' ') != -1: raise ParseError('Couldn\'t parse integer: "{0}".'.format(value)) + if isinstance(value, bool): + raise ParseError('Bool value {0} is not acceptable for ' + 'integer field.'.format(value)) + return int(value) -def _ConvertFloat(value): +def _ConvertFloat(value, field): """Convert an floating point number.""" + if isinstance(value, float): + if math.isnan(value): + raise ParseError('Couldn\'t parse NaN, use quoted "NaN" instead.') + if math.isinf(value): + if value > 0: + raise ParseError('Couldn\'t parse Infinity or value too large, ' + 'use quoted "Infinity" instead.') + else: + raise ParseError('Couldn\'t parse -Infinity or value too small, ' + 'use quoted "-Infinity" instead.') + if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT: + # pylint: disable=protected-access + if value > type_checkers._FLOAT_MAX: + raise ParseError('Float value too large') + # pylint: disable=protected-access + if value < type_checkers._FLOAT_MIN: + raise ParseError('Float value too small') if value == 'nan': raise ParseError('Couldn\'t parse float "nan", use "NaN" instead.') try: diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py old mode 100755 new mode 100644 index eeb0d5763fae3..224d2fc491781 --- a/python/google/protobuf/message.py +++ b/python/google/protobuf/message.py @@ -36,9 +36,19 @@ __author__ = 'robinson@google.com (Will Robinson)' -class Error(Exception): pass -class DecodeError(Error): pass -class EncodeError(Error): pass +class Error(Exception): + """Base error type for this module.""" + pass + + +class DecodeError(Error): + """Exception raised when deserializing messages.""" + pass + + +class EncodeError(Error): + """Exception raised when serializing messages.""" + pass class Message(object): @@ -48,22 +58,23 @@ class Message(object): Protocol message classes are almost always generated by the protocol compiler. These generated types subclass Message and implement the methods shown below. + """ - TODO(robinson): Link to an HTML document here. + # TODO(robinson): Link to an HTML document here. - TODO(robinson): Document that instances of this class will also - have an Extensions attribute with __getitem__ and __setitem__. - Again, not sure how to best convey this. + # TODO(robinson): Document that instances of this class will also + # have an Extensions attribute with __getitem__ and __setitem__. + # Again, not sure how to best convey this. - TODO(robinson): Document that the class must also have a static - RegisterExtension(extension_field) method. - Not sure how to best express at this point. - """ + # TODO(robinson): Document that the class must also have a static + # RegisterExtension(extension_field) method. + # Not sure how to best express at this point. # TODO(robinson): Document these fields and methods. __slots__ = [] + #: The :class:`google.protobuf.descriptor.Descriptor` for this message type. DESCRIPTOR = None def __deepcopy__(self, memo=None): @@ -99,7 +110,7 @@ def MergeFrom(self, other_msg): appended. Singular sub-messages and groups are recursively merged. Args: - other_msg: Message to merge into the current message. + other_msg (Message): A message to merge into the current message. """ raise NotImplementedError @@ -110,7 +121,7 @@ def CopyFrom(self, other_msg): message using MergeFrom. Args: - other_msg: Message to copy into the current one. + other_msg (Message): A message to copy into the current one. """ if self is other_msg: return @@ -127,15 +138,16 @@ def SetInParent(self): This normally happens automatically when you assign a field of a sub-message, but sometimes you want to make the sub-message present while keeping it empty. If you find yourself using this, - you may want to reconsider your design.""" + you may want to reconsider your design. + """ raise NotImplementedError def IsInitialized(self): """Checks if the message is initialized. Returns: - The method returns True if the message is initialized (i.e. all of its - required fields are set). + bool: The method returns True if the message is initialized (i.e. all of + its required fields are set). """ raise NotImplementedError @@ -148,57 +160,57 @@ def IsInitialized(self): def MergeFromString(self, serialized): """Merges serialized protocol buffer data into this message. - When we find a field in |serialized| that is already present + When we find a field in `serialized` that is already present in this message: - - If it's a "repeated" field, we append to the end of our list. - - Else, if it's a scalar, we overwrite our field. - - Else, (it's a nonrepeated composite), we recursively merge - into the existing composite. - TODO(robinson): Document handling of unknown fields. + - If it's a "repeated" field, we append to the end of our list. + - Else, if it's a scalar, we overwrite our field. + - Else, (it's a nonrepeated composite), we recursively merge + into the existing composite. Args: - serialized: Any object that allows us to call buffer(serialized) - to access a string of bytes using the buffer interface. - - TODO(robinson): When we switch to a helper, this will return None. + serialized (bytes): Any object that allows us to call + ``memoryview(serialized)`` to access a string of bytes using the + buffer interface. Returns: - The number of bytes read from |serialized|. - For non-group messages, this will always be len(serialized), + int: The number of bytes read from `serialized`. + For non-group messages, this will always be `len(serialized)`, but for messages which are actually groups, this will - generally be less than len(serialized), since we must - stop when we reach an END_GROUP tag. Note that if - we *do* stop because of an END_GROUP tag, the number + generally be less than `len(serialized)`, since we must + stop when we reach an ``END_GROUP`` tag. Note that if + we *do* stop because of an ``END_GROUP`` tag, the number of bytes returned does not include the bytes - for the END_GROUP tag information. + for the ``END_GROUP`` tag information. + + Raises: + DecodeError: if the input cannot be parsed. """ + # TODO(robinson): Document handling of unknown fields. + # TODO(robinson): When we switch to a helper, this will return None. raise NotImplementedError def ParseFromString(self, serialized): """Parse serialized protocol buffer data into this message. - Like MergeFromString(), except we clear the object first and - do not return the value that MergeFromString returns. + Like :func:`MergeFromString()`, except we clear the object first. """ self.Clear() - self.MergeFromString(serialized) + return self.MergeFromString(serialized) def SerializeToString(self, **kwargs): """Serializes the protocol message to a binary string. - Arguments: - **kwargs: Keyword arguments to the serialize method, accepts - the following keyword args: - deterministic: If true, requests deterministic serialization of the - protobuf, with predictable ordering of map keys. + Keyword Args: + deterministic (bool): If true, requests deterministic serialization + of the protobuf, with predictable ordering of map keys. Returns: A binary string representation of the message if all of the required fields in the message are set (i.e. the message is initialized). Raises: - message.EncodeError if the message isn't initialized. + EncodeError: if the message isn't initialized (see :func:`IsInitialized`). """ raise NotImplementedError @@ -208,14 +220,12 @@ def SerializePartialToString(self, **kwargs): This method is similar to SerializeToString but doesn't check if the message is initialized. - Arguments: - **kwargs: Keyword arguments to the serialize method, accepts - the following keyword args: - deterministic: If true, requests deterministic serialization of the - protobuf, with predictable ordering of map keys. + Keyword Args: + deterministic (bool): If true, requests deterministic serialization + of the protobuf, with predictable ordering of map keys. Returns: - A string representation of the partial message. + bytes: A serialized representation of the partial message. """ raise NotImplementedError @@ -236,44 +246,116 @@ def SerializePartialToString(self, **kwargs): # keywords. So they would become lambda_ or yield_. # """ def ListFields(self): - """Returns a list of (FieldDescriptor, value) tuples for all - fields in the message which are not empty. A message field is - non-empty if HasField() would return true. A singular primitive field - is non-empty if HasField() would return true in proto2 or it is non zero - in proto3. A repeated field is non-empty if it contains at least one - element. The fields are ordered by field number""" + """Returns a list of (FieldDescriptor, value) tuples for present fields. + + A message field is non-empty if HasField() would return true. A singular + primitive field is non-empty if HasField() would return true in proto2 or it + is non zero in proto3. A repeated field is non-empty if it contains at least + one element. The fields are ordered by field number. + + Returns: + list[tuple(FieldDescriptor, value)]: field descriptors and values + for all fields in the message which are not empty. The values vary by + field type. + """ raise NotImplementedError def HasField(self, field_name): - """Checks if a certain field is set for the message, or if any field inside - a oneof group is set. Note that if the field_name is not defined in the - message descriptor, ValueError will be raised.""" + """Checks if a certain field is set for the message. + + For a oneof group, checks if any field inside is set. Note that if the + field_name is not defined in the message descriptor, :exc:`ValueError` will + be raised. + + Args: + field_name (str): The name of the field to check for presence. + + Returns: + bool: Whether a value has been set for the named field. + + Raises: + ValueError: if the `field_name` is not a member of this message. + """ raise NotImplementedError def ClearField(self, field_name): - """Clears the contents of a given field, or the field set inside a oneof - group. If the name neither refers to a defined field or oneof group, - ValueError is raised.""" + """Clears the contents of a given field. + + Inside a oneof group, clears the field set. If the name neither refers to a + defined field or oneof group, :exc:`ValueError` is raised. + + Args: + field_name (str): The name of the field to check for presence. + + Raises: + ValueError: if the `field_name` is not a member of this message. + """ raise NotImplementedError def WhichOneof(self, oneof_group): - """Returns the name of the field that is set inside a oneof group, or - None if no field is set. If no group with the given name exists, ValueError - will be raised.""" + """Returns the name of the field that is set inside a oneof group. + + If no field is set, returns None. + + Args: + oneof_group (str): the name of the oneof group to check. + + Returns: + str or None: The name of the group that is set, or None. + + Raises: + ValueError: no group with the given name exists + """ raise NotImplementedError def HasExtension(self, extension_handle): + """Checks if a certain extension is present for this message. + + Extensions are retrieved using the :attr:`Extensions` mapping (if present). + + Args: + extension_handle: The handle for the extension to check. + + Returns: + bool: Whether the extension is present for this message. + + Raises: + KeyError: if the extension is repeated. Similar to repeated fields, + there is no separate notion of presence: a "not present" repeated + extension is an empty list. + """ raise NotImplementedError def ClearExtension(self, extension_handle): + """Clears the contents of a given extension. + + Args: + extension_handle: The handle for the extension to clear. + """ + raise NotImplementedError + + def UnknownFields(self): + """Returns the UnknownFieldSet. + + Returns: + UnknownFieldSet: The unknown fields stored in this message. + """ raise NotImplementedError def DiscardUnknownFields(self): + """Clears all fields in the :class:`UnknownFieldSet`. + + This operation is recursive for nested message. + """ raise NotImplementedError def ByteSize(self): """Returns the serialized size of this message. + Recursively calls ByteSize() on all contained messages. + + Returns: + int: The number of bytes required to serialize this message. """ raise NotImplementedError @@ -305,4 +387,27 @@ def __getstate__(self): def __setstate__(self, state): """Support the pickle protocol.""" self.__init__() - self.ParseFromString(state['serialized']) + serialized = state['serialized'] + # On Python 3, using encoding='latin1' is required for unpickling + # protos pickled by Python 2. + if not isinstance(serialized, bytes): + serialized = serialized.encode('latin1') + self.ParseFromString(serialized) + + def __reduce__(self): + message_descriptor = self.DESCRIPTOR + if message_descriptor.containing_type is None: + return type(self), (), self.__getstate__() + # the message type must be nested. + # Python does not pickle nested classes; use the symbol_database on the + # receiving end. + container = message_descriptor + return (_InternalConstructMessage, (container.full_name,), + self.__getstate__()) + + +def _InternalConstructMessage(full_name): + """Constructs a nested message.""" + from google.protobuf import symbol_database # pylint:disable=g-import-not-at-top + + return symbol_database.Default().GetSymbol(full_name)() diff --git a/python/google/protobuf/message_factory.py b/python/google/protobuf/message_factory.py index 1574028015ede..7dfaec88e15e1 100644 --- a/python/google/protobuf/message_factory.py +++ b/python/google/protobuf/message_factory.py @@ -39,9 +39,18 @@ __author__ = 'matthewtoia@google.com (Matt Toia)' +from google.protobuf.internal import api_implementation from google.protobuf import descriptor_pool from google.protobuf import message -from google.protobuf import reflection + +if api_implementation.Type() == 'cpp': + from google.protobuf.pyext import cpp_message as message_impl +else: + from google.protobuf.internal import python_message as message_impl + + +# The type of all Message classes. +_GENERATED_PROTOCOL_MESSAGE_TYPE = message_impl.GeneratedProtocolMessageType class MessageFactory(object): @@ -55,7 +64,7 @@ def __init__(self, pool=None): self._classes = {} def GetPrototype(self, descriptor): - """Builds a proto2 message class based on the passed in descriptor. + """Obtains a proto2 message class based on the passed in descriptor. Passing a descriptor with a fully qualified name matching a previous invocation will cause the same class to be returned. @@ -67,25 +76,52 @@ def GetPrototype(self, descriptor): A class describing the passed in descriptor. """ if descriptor not in self._classes: - descriptor_name = descriptor.name - if str is bytes: # PY2 - descriptor_name = descriptor.name.encode('ascii', 'ignore') - result_class = reflection.GeneratedProtocolMessageType( - descriptor_name, - (message.Message,), - {'DESCRIPTOR': descriptor, '__module__': None}) - # If module not set, it wrongly points to the reflection.py module. + result_class = self.CreatePrototype(descriptor) + # The assignment to _classes is redundant for the base implementation, but + # might avoid confusion in cases where CreatePrototype gets overridden and + # does not call the base implementation. self._classes[descriptor] = result_class - for field in descriptor.fields: - if field.message_type: - self.GetPrototype(field.message_type) - for extension in result_class.DESCRIPTOR.extensions: - if extension.containing_type not in self._classes: - self.GetPrototype(extension.containing_type) - extended_class = self._classes[extension.containing_type] - extended_class.RegisterExtension(extension) + return result_class return self._classes[descriptor] + def CreatePrototype(self, descriptor): + """Builds a proto2 message class based on the passed in descriptor. + + Don't call this function directly, it always creates a new class. Call + GetPrototype() instead. This method is meant to be overridden in subblasses + to perform additional operations on the newly constructed class. + + Args: + descriptor: The descriptor to build from. + + Returns: + A class describing the passed in descriptor. + """ + descriptor_name = descriptor.name + if str is bytes: # PY2 + descriptor_name = descriptor.name.encode('ascii', 'ignore') + result_class = _GENERATED_PROTOCOL_MESSAGE_TYPE( + descriptor_name, + (message.Message,), + { + 'DESCRIPTOR': descriptor, + # If module not set, it wrongly points to message_factory module. + '__module__': None, + }) + result_class._FACTORY = self # pylint: disable=protected-access + # Assign in _classes before doing recursive calls to avoid infinite + # recursion. + self._classes[descriptor] = result_class + for field in descriptor.fields: + if field.message_type: + self.GetPrototype(field.message_type) + for extension in result_class.DESCRIPTOR.extensions: + if extension.containing_type not in self._classes: + self.GetPrototype(extension.containing_type) + extended_class = self._classes[extension.containing_type] + extended_class.RegisterExtension(extension) + return result_class + def GetMessages(self, files): """Gets all the messages from a specified file. @@ -130,13 +166,22 @@ def GetMessages(file_protos): """Builds a dictionary of all the messages available in a set of files. Args: - file_protos: A sequence of file protos to build messages out of. + file_protos: Iterable of FileDescriptorProto to build messages out of. Returns: A dictionary mapping proto names to the message classes. This will include any dependent messages as well as any messages defined in the same file as a specified message. """ - for file_proto in file_protos: + # The cpp implementation of the protocol buffer library requires to add the + # message in topological order of the dependency graph. + file_by_name = {file_proto.name: file_proto for file_proto in file_protos} + def _AddFile(file_proto): + for dependency in file_proto.dependency: + if dependency in file_by_name: + # Remove from elements to be visited, in order to cut cycles. + _AddFile(file_by_name.pop(dependency)) _FACTORY.pool.Add(file_proto) + while file_by_name: + _AddFile(file_by_name.popitem()[1]) return _FACTORY.GetMessages([file_proto.name for file_proto in file_protos]) diff --git a/python/google/protobuf/proto_api.h b/python/google/protobuf/proto_api.h new file mode 100644 index 0000000000000..c869bce058fd3 --- /dev/null +++ b/python/google/protobuf/proto_api.h @@ -0,0 +1,123 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file can be included by other C++ libraries, typically extension modules +// which want to interact with the Python Messages coming from the "cpp" +// implementation of protocol buffers. +// +// Usage: +// Declare a (probably static) variable to hold the API: +// const PyProto_API* py_proto_api; +// In some initialization function, write: +// py_proto_api = static_cast(PyCapsule_Import( +// PyProtoAPICapsuleName(), 0)); +// if (!py_proto_api) { ...handle ImportError... } +// Then use the methods of the returned class: +// py_proto_api->GetMessagePointer(...); + +#ifndef GOOGLE_PROTOBUF_PYTHON_PROTO_API_H__ +#define GOOGLE_PROTOBUF_PYTHON_PROTO_API_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace python { + +// Note on the implementation: +// This API is designed after +// https://docs.python.org/3/extending/extending.html#providing-a-c-api-for-an-extension-module +// The class below contains no mutable state, and all methods are "const"; +// we use a C++ class instead of a C struct with functions pointers just because +// the code looks more readable. +struct PyProto_API { + // The API object is created at initialization time and never freed. + // This destructor is never called. + virtual ~PyProto_API() {} + + // Operations on Messages. + + // If the passed object is a Python Message, returns its internal pointer. + // Otherwise, returns NULL with an exception set. + virtual const Message* GetMessagePointer(PyObject* msg) const = 0; + + // If the passed object is a Python Message, returns a mutable pointer. + // Otherwise, returns NULL with an exception set. + // This function will succeed only if there are no other Python objects + // pointing to the message, like submessages or repeated containers. + // With the current implementation, only empty messages are in this case. + virtual Message* GetMutableMessagePointer(PyObject* msg) const = 0; + + // Expose the underlying DescriptorPool and MessageFactory to enable C++ code + // to create Python-compatible message. + virtual const DescriptorPool* GetDefaultDescriptorPool() const = 0; + virtual MessageFactory* GetDefaultMessageFactory() const = 0; + + // Allocate a new protocol buffer as a python object for the provided + // descriptor. This function works even if no Python module has been imported + // for the corresponding protocol buffer class. + // The factory is usually null; when provided, it is the MessageFactory which + // owns the Python class, and will be used to find and create Extensions for + // this message. + // When null is returned, a python error has already been set. + virtual PyObject* NewMessage(const Descriptor* descriptor, + PyObject* py_message_factory) const = 0; + + // Allocate a new protocol buffer where the underlying object is owned by C++. + // The factory must currently be null. This function works even if no Python + // module has been imported for the corresponding protocol buffer class. + // When null is returned, a python error has already been set. + // + // Since this call returns a python object owned by C++, some operations + // are risky, and it must be used carefully. In particular: + // * Avoid modifying the returned object from the C++ side while there are + // existing python references to it or it's subobjects. + // * Avoid using python references to this object or any subobjects after the + // C++ object has been freed. + // * Calling this with the same C++ pointer will result in multiple distinct + // python objects referencing the same C++ object. + virtual PyObject* NewMessageOwnedExternally( + Message* msg, PyObject* py_message_factory) const = 0; +}; + +inline const char* PyProtoAPICapsuleName() { + static const char kCapsuleName[] = + "google.protobuf.pyext._message.proto_API"; + return kCapsuleName; +} + +} // namespace python +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_PYTHON_PROTO_API_H__ diff --git a/python/google/protobuf/pyext/__init__.py b/python/google/protobuf/pyext/__init__.py index 5585614122997..e69de29bb2d1d 100644 --- a/python/google/protobuf/pyext/__init__.py +++ b/python/google/protobuf/pyext/__init__.py @@ -1,4 +0,0 @@ -try: - __import__('pkg_resources').declare_namespace(__name__) -except ImportError: - __path__ = __import__('pkgutil').extend_path(__path__, __name__) diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc index 9634ea05ff2eb..75f1760ccf459 100644 --- a/python/google/protobuf/pyext/descriptor.cc +++ b/python/google/protobuf/pyext/descriptor.cc @@ -32,8 +32,8 @@ #include #include -#include #include +#include #include #include @@ -44,6 +44,7 @@ #include #include #include +#include #if PY_MAJOR_VERSION >= 3 #define PyString_FromStringAndSize PyUnicode_FromStringAndSize @@ -54,10 +55,12 @@ #if PY_VERSION_HEX < 0x03030000 #error "Python 3.0 - 3.2 are not supported." #endif - #define PyString_AsStringAndSize(ob, charpp, sizep) \ - (PyUnicode_Check(ob)? \ - ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \ - PyBytes_AsStringAndSize(ob, (charpp), (sizep))) +#define PyString_AsStringAndSize(ob, charpp, sizep) \ + (PyUnicode_Check(ob) ? ((*(charpp) = const_cast( \ + PyUnicode_AsUTF8AndSize(ob, (sizep)))) == NULL \ + ? -1 \ + : 0) \ + : PyBytes_AsStringAndSize(ob, (charpp), (sizep))) #endif namespace google { @@ -70,9 +73,9 @@ namespace python { // released. // This is enough to support the "is" operator on live objects. // All descriptors are stored here. -hash_map interned_descriptors; +std::unordered_map* interned_descriptors; -PyObject* PyString_FromCppString(const string& str) { +PyObject* PyString_FromCppString(const std::string& str) { return PyString_FromStringAndSize(str.c_str(), str.size()); } @@ -107,10 +110,6 @@ bool _CalledFromGeneratedFile(int stacklevel) { return false; } } - if (frame->f_globals != frame->f_locals) { - // Not at global module scope - return false; - } if (frame->f_code->co_filename == NULL) { return false; @@ -123,6 +122,12 @@ bool _CalledFromGeneratedFile(int stacklevel) { PyErr_Clear(); return false; } + if ((filename_size < 3) || + (strcmp(&filename[filename_size - 3], ".py") != 0)) { + // Cython's stack does not have .py file name and is not at global module + // scope. + return true; + } if (filename_size < 7) { // filename is too short. return false; @@ -131,6 +136,11 @@ bool _CalledFromGeneratedFile(int stacklevel) { // Filename is not ending with _pb2. return false; } + + if (frame->f_globals != frame->f_locals) { + // Not at global module scope + return false; + } #endif return true; } @@ -179,6 +189,21 @@ const FileDescriptor* GetFileDescriptor(const MethodDescriptor* descriptor) { return descriptor->service()->file(); } +bool Reparse( + PyMessageFactory* message_factory, const Message& from, Message* to) { + // Reparse message. + std::string serialized; + from.SerializeToString(&serialized); + io::CodedInputStream input( + reinterpret_cast(serialized.c_str()), serialized.size()); + input.SetExtensionRegistry(message_factory->pool->pool, + message_factory->message_factory); + bool success = to->ParseFromCodedStream(&input); + if (!success) { + return false; + } + return true; +} // Converts options into a Python protobuf, and cache the result. // // This is a bit tricky because options can contain extension fields defined in @@ -188,38 +213,35 @@ const FileDescriptor* GetFileDescriptor(const MethodDescriptor* descriptor) { // Always returns a new reference. template static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) { - // Options (and their extensions) are completely resolved in the proto file - // containing the descriptor. - PyDescriptorPool* pool = GetDescriptorPool_FromPool( - GetFileDescriptor(descriptor)->pool()); - - hash_map* descriptor_options = - pool->descriptor_options; + // Options are cached in the pool that owns the descriptor. // First search in the cache. + PyDescriptorPool* caching_pool = GetDescriptorPool_FromPool( + GetFileDescriptor(descriptor)->pool()); + std::unordered_map* descriptor_options = + caching_pool->descriptor_options; if (descriptor_options->find(descriptor) != descriptor_options->end()) { PyObject *value = (*descriptor_options)[descriptor]; Py_INCREF(value); return value; } + // Similar to the C++ implementation, we return an Options object from the + // default (generated) factory, so that client code know that they can use + // extensions from generated files: + // d.GetOptions().Extensions[some_pb2.extension] + // + // The consequence is that extensions not defined in the default pool won't + // be available. If needed, we could add an optional 'message_factory' + // parameter to the GetOptions() function. + PyMessageFactory* message_factory = + GetDefaultDescriptorPool()->py_message_factory; + // Build the Options object: get its Python class, and make a copy of the C++ // read-only instance. const Message& options(descriptor->options()); const Descriptor *message_type = options.GetDescriptor(); - PyMessageFactory* message_factory = pool->py_message_factory; - CMessageClass* message_class = message_factory::GetMessageClass( - message_factory, message_type); - if (message_class == NULL) { - // The Options message was not found in the current DescriptorPool. - // This means that the pool cannot contain any extensions to the Options - // message either, so falling back to the basic pool we can only increase - // the chances of successfully parsing the options. - PyErr_Clear(); - pool = GetDefaultDescriptorPool(); - message_factory = pool->py_message_factory; - message_class = message_factory::GetMessageClass( + CMessageClass* message_class = message_factory::GetOrCreateMessageClass( message_factory, message_type); - } if (message_class == NULL) { PyErr_Format(PyExc_TypeError, "Could not retrieve class for Options: %s", message_type->full_name().c_str()); @@ -227,10 +249,11 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) { } ScopedPyObjectPtr value( PyEval_CallObject(message_class->AsPyObject(), NULL)); + Py_DECREF(message_class); if (value == NULL) { return NULL; } - if (!PyObject_TypeCheck(value.get(), &CMessage_Type)) { + if (!PyObject_TypeCheck(value.get(), CMessage_Type)) { PyErr_Format(PyExc_TypeError, "Invalid class for %s: %s", message_type->full_name().c_str(), Py_TYPE(value.get())->tp_name); @@ -244,14 +267,8 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) { cmsg->message->CopyFrom(options); } else { // Reparse options string! XXX call cmessage::MergeFromString - string serialized; - options.SerializeToString(&serialized); - io::CodedInputStream input( - reinterpret_cast(serialized.c_str()), serialized.size()); - input.SetExtensionRegistry(pool->pool, message_factory->message_factory); - bool success = cmsg->message->MergePartialFromCodedStream(&input); - if (!success) { - PyErr_Format(PyExc_ValueError, "Error parsing Options message"); + if (!Reparse(message_factory, options, cmsg->message)) { + PyErr_Format(PyExc_ValueError, "Error reparsing Options message"); return NULL; } } @@ -272,7 +289,7 @@ static PyObject* CopyToPythonProto(const DescriptorClass *descriptor, const Descriptor* self_descriptor = DescriptorProtoClass::default_instance().GetDescriptor(); CMessage* message = reinterpret_cast(target); - if (!PyObject_TypeCheck(target, &CMessage_Type) || + if (!PyObject_TypeCheck(target, CMessage_Type) || message->message->GetDescriptor() != self_descriptor) { PyErr_Format(PyExc_TypeError, "Not a %s message", self_descriptor->full_name().c_str()); @@ -282,6 +299,16 @@ static PyObject* CopyToPythonProto(const DescriptorClass *descriptor, DescriptorProtoClass* descriptor_message = static_cast(message->message); descriptor->CopyTo(descriptor_message); + // Custom options might in unknown extensions. Reparse + // the descriptor_message. Can't skip reparse when options unknown + // fields is empty, because they might in sub descriptors' options. + PyMessageFactory* message_factory = + GetDefaultDescriptorPool()->py_message_factory; + if (!Reparse(message_factory, *descriptor_message, descriptor_message)) { + PyErr_Format(PyExc_ValueError, "Error reparsing descriptor message"); + return nullptr; + } + Py_RETURN_NONE; } @@ -329,15 +356,15 @@ PyObject* NewInternedDescriptor(PyTypeObject* type, } // See if the object is in the map of interned descriptors - hash_map::iterator it = - interned_descriptors.find(descriptor); - if (it != interned_descriptors.end()) { + std::unordered_map::iterator it = + interned_descriptors->find(descriptor); + if (it != interned_descriptors->end()) { GOOGLE_DCHECK(Py_TYPE(it->second) == type); Py_INCREF(it->second); return it->second; } // Create a new descriptor object - PyBaseDescriptor* py_descriptor = PyObject_New( + PyBaseDescriptor* py_descriptor = PyObject_GC_New( PyBaseDescriptor, type); if (py_descriptor == NULL) { return NULL; @@ -345,7 +372,7 @@ PyObject* NewInternedDescriptor(PyTypeObject* type, py_descriptor->descriptor = descriptor; // and cache it. - interned_descriptors.insert( + interned_descriptors->insert( std::make_pair(descriptor, reinterpret_cast(py_descriptor))); // Ensures that the DescriptorPool stays alive. @@ -359,17 +386,32 @@ PyObject* NewInternedDescriptor(PyTypeObject* type, Py_INCREF(pool); py_descriptor->pool = pool; + PyObject_GC_Track(py_descriptor); + if (was_created) { *was_created = true; } return reinterpret_cast(py_descriptor); } -static void Dealloc(PyBaseDescriptor* self) { +static void Dealloc(PyObject* pself) { + PyBaseDescriptor* self = reinterpret_cast(pself); // Remove from interned dictionary - interned_descriptors.erase(self->descriptor); + interned_descriptors->erase(self->descriptor); + Py_CLEAR(self->pool); + Py_TYPE(self)->tp_free(pself); +} + +static int GcTraverse(PyObject* pself, visitproc visit, void* arg) { + PyBaseDescriptor* self = reinterpret_cast(pself); + Py_VISIT(self->pool); + return 0; +} + +static int GcClear(PyObject* pself) { + PyBaseDescriptor* self = reinterpret_cast(pself); Py_CLEAR(self->pool); - Py_TYPE(self)->tp_free(reinterpret_cast(self)); + return 0; } static PyGetSetDef Getters[] = { @@ -377,36 +419,36 @@ static PyGetSetDef Getters[] = { }; PyTypeObject PyBaseDescriptor_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - FULL_MODULE_NAME ".DescriptorBase", // tp_name - sizeof(PyBaseDescriptor), // tp_basicsize - 0, // tp_itemsize - (destructor)Dealloc, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - 0, // tp_repr - 0, // tp_as_number - 0, // tp_as_sequence - 0, // tp_as_mapping - 0, // tp_hash - 0, // tp_call - 0, // tp_str - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "Descriptors base class", // tp_doc - 0, // tp_traverse - 0, // tp_clear - 0, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - 0, // tp_methods - 0, // tp_members - Getters, // tp_getset + PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME + ".DescriptorBase", // tp_name + sizeof(PyBaseDescriptor), // tp_basicsize + 0, // tp_itemsize + (destructor)Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags + "Descriptors base class", // tp_doc + GcTraverse, // tp_traverse + GcClear, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + Getters, // tp_getset }; } // namespace descriptor @@ -439,7 +481,7 @@ static PyObject* GetFile(PyBaseDescriptor *self, void *closure) { } static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) { - // Retuns the canonical class for the given descriptor. + // Returns the canonical class for the given descriptor. // This is the class that was registered with the primary descriptor pool // which contains this descriptor. // This might not be the one you expect! For example the returned object does @@ -564,6 +606,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} + static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) { return CopyToPythonProto(_GetDescriptor(self), target); } @@ -623,6 +670,8 @@ static PyGetSetDef Getters[] = { { "is_extendable", (getter)IsExtendable, (setter)NULL}, { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, { "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"}, {NULL} }; @@ -748,6 +797,11 @@ static PyObject* HasDefaultValue(PyBaseDescriptor *self, void *closure) { static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) { PyObject *result; + if (_GetDescriptor(self)->is_repeated()) { + return PyList_New(0); + } + + switch (_GetDescriptor(self)->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: { int32 value = _GetDescriptor(self)->default_value_int32(); @@ -785,7 +839,7 @@ static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) { break; } case FieldDescriptor::CPPTYPE_STRING: { - string value = _GetDescriptor(self)->default_value_string(); + const std::string& value = _GetDescriptor(self)->default_value_string(); result = ToStringObject(_GetDescriptor(self), value); break; } @@ -795,6 +849,10 @@ static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) { result = PyInt_FromLong(value->number()); break; } + case FieldDescriptor::CPPTYPE_MESSAGE: { + Py_RETURN_NONE; + break; + } default: PyErr_Format(PyExc_NotImplementedError, "default value for %s", _GetDescriptor(self)->full_name().c_str()); @@ -897,6 +955,10 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} static PyGetSetDef Getters[] = { { "full_name", (getter)GetFullName, NULL, "Full name"}, @@ -926,6 +988,8 @@ static PyGetSetDef Getters[] = { "Containing oneof"}, { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, {NULL} }; @@ -1055,6 +1119,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} + static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) { return CopyToPythonProto(_GetDescriptor(self), target); } @@ -1079,6 +1148,8 @@ static PyGetSetDef Getters[] = { "Containing type"}, { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, {NULL} }; @@ -1179,6 +1250,10 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} static PyGetSetDef Getters[] = { { "name", (getter)GetName, NULL, "name"}, @@ -1188,6 +1263,8 @@ static PyGetSetDef Getters[] = { { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, {NULL} }; @@ -1247,7 +1324,7 @@ static const FileDescriptor* _GetDescriptor(PyFileDescriptor *self) { static void Dealloc(PyFileDescriptor* self) { Py_XDECREF(self->serialized_pb); - descriptor::Dealloc(&self->base); + descriptor::Dealloc(reinterpret_cast(self)); } static PyObject* GetPool(PyFileDescriptor *self, void *closure) { @@ -1273,7 +1350,7 @@ static PyObject* GetSerializedPb(PyFileDescriptor *self, void *closure) { } FileDescriptorProto file_proto; _GetDescriptor(self)->CopyTo(&file_proto); - string contents; + std::string contents; file_proto.SerializePartialToString(&contents); self->serialized_pb = PyBytes_FromStringAndSize( contents.c_str(), contents.size()); @@ -1330,6 +1407,11 @@ static int SetOptions(PyFileDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyFileDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} + static PyObject* GetSyntax(PyFileDescriptor *self, void *closure) { return PyString_InternFromString( FileDescriptor::SyntaxName(_GetDescriptor(self)->syntax())); @@ -1355,6 +1437,8 @@ static PyGetSetDef Getters[] = { { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, { "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"}, {NULL} }; @@ -1368,45 +1452,45 @@ static PyMethodDef Methods[] = { } // namespace file_descriptor PyTypeObject PyFileDescriptor_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - FULL_MODULE_NAME ".FileDescriptor", // tp_name - sizeof(PyFileDescriptor), // tp_basicsize - 0, // tp_itemsize - (destructor)file_descriptor::Dealloc, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - 0, // tp_repr - 0, // tp_as_number - 0, // tp_as_sequence - 0, // tp_as_mapping - 0, // tp_hash - 0, // tp_call - 0, // tp_str - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "A File Descriptor", // tp_doc - 0, // tp_traverse - 0, // tp_clear - 0, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - file_descriptor::Methods, // tp_methods - 0, // tp_members - file_descriptor::Getters, // tp_getset - &descriptor::PyBaseDescriptor_Type, // tp_base - 0, // tp_dict - 0, // tp_descr_get - 0, // tp_descr_set - 0, // tp_dictoffset - 0, // tp_init - 0, // tp_alloc - 0, // tp_new - PyObject_Del, // tp_free + PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME + ".FileDescriptor", // tp_name + sizeof(PyFileDescriptor), // tp_basicsize + 0, // tp_itemsize + (destructor)file_descriptor::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "A File Descriptor", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + file_descriptor::Methods, // tp_methods + 0, // tp_members + file_descriptor::Getters, // tp_getset + &descriptor::PyBaseDescriptor_Type, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + 0, // tp_new + PyObject_GC_Del, // tp_free }; PyObject* PyFileDescriptor_FromDescriptor( @@ -1500,6 +1584,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} + static PyGetSetDef Getters[] = { { "name", (getter)GetName, NULL, "Name"}, { "full_name", (getter)GetFullName, NULL, "Full name"}, @@ -1508,6 +1597,8 @@ static PyGetSetDef Getters[] = { { "containing_type", (getter)GetContainingType, NULL, "Containing type"}, { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, { "fields", (getter)GetFields, NULL, "Fields"}, {NULL} }; @@ -1599,7 +1690,7 @@ static PyObject* FindMethodByName(PyBaseDescriptor *self, PyObject* arg) { } const MethodDescriptor* method_descriptor = - _GetDescriptor(self)->FindMethodByName(string(name, name_size)); + _GetDescriptor(self)->FindMethodByName(StringParam(name, name_size)); if (method_descriptor == NULL) { PyErr_Format(PyExc_KeyError, "Couldn't find method %.200s", name); return NULL; @@ -1789,15 +1880,6 @@ PyObject* PyMethodDescriptor_FromDescriptor( &PyMethodDescriptor_Type, method_descriptor, NULL); } -const MethodDescriptor* PyMethodDescriptor_AsDescriptor(PyObject* obj) { - if (!PyObject_TypeCheck(obj, &PyMethodDescriptor_Type)) { - PyErr_SetString(PyExc_TypeError, "Not a MethodDescriptor"); - return NULL; - } - return reinterpret_cast( - reinterpret_cast(obj)->descriptor); -} - // Add a enum values to a type dictionary. static bool AddEnumValues(PyTypeObject *type, const EnumDescriptor* enum_descriptor) { @@ -1876,6 +1958,9 @@ bool InitDescriptor() { if (!InitDescriptorMappingTypes()) return false; + // Initialize globals defined in this file. + interned_descriptors = new std::unordered_map; + return true; } diff --git a/python/google/protobuf/pyext/descriptor.h b/python/google/protobuf/pyext/descriptor.h index f081df842d3a8..b99209dd1996d 100644 --- a/python/google/protobuf/pyext/descriptor.h +++ b/python/google/protobuf/pyext/descriptor.h @@ -41,6 +41,9 @@ namespace google { namespace protobuf { namespace python { +// Should match the type of ConstStringParam. +using StringParam = std::string; + extern PyTypeObject PyMessageDescriptor_Type; extern PyTypeObject PyFieldDescriptor_Type; extern PyTypeObject PyEnumDescriptor_Type; @@ -81,7 +84,6 @@ const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj); const EnumDescriptor* PyEnumDescriptor_AsDescriptor(PyObject* obj); const FileDescriptor* PyFileDescriptor_AsDescriptor(PyObject* obj); const ServiceDescriptor* PyServiceDescriptor_AsDescriptor(PyObject* obj); -const MethodDescriptor* PyMethodDescriptor_AsDescriptor(PyObject* obj); // Returns the raw C++ pointer. const void* PyDescriptor_AsVoidPtr(PyObject* obj); @@ -100,6 +102,6 @@ bool InitDescriptor(); } // namespace python } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_H__ diff --git a/python/google/protobuf/pyext/descriptor_containers.cc b/python/google/protobuf/pyext/descriptor_containers.cc index d0aae9c9b3a13..c6ec2583a09a0 100644 --- a/python/google/protobuf/pyext/descriptor_containers.cc +++ b/python/google/protobuf/pyext/descriptor_containers.cc @@ -33,7 +33,7 @@ // // They avoid the allocation of a full dictionary or a full list: they simply // store a pointer to the parent descriptor, use the C++ Descriptor methods (see -// google/protobuf/descriptor.h) to retrieve other descriptors, and create +// net/proto2/public/descriptor.h) to retrieve other descriptors, and create // Python objects on the fly. // // The containers fully conform to abc.Mapping and abc.Sequence, and behave just @@ -64,10 +64,12 @@ #if PY_VERSION_HEX < 0x03030000 #error "Python 3.0 - 3.2 are not supported." #endif - #define PyString_AsStringAndSize(ob, charpp, sizep) \ - (PyUnicode_Check(ob)? \ - ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \ - PyBytes_AsStringAndSize(ob, (charpp), (sizep))) +#define PyString_AsStringAndSize(ob, charpp, sizep) \ + (PyUnicode_Check(ob) ? ((*(charpp) = const_cast( \ + PyUnicode_AsUTF8AndSize(ob, (sizep)))) == NULL \ + ? -1 \ + : 0) \ + : PyBytes_AsStringAndSize(ob, (charpp), (sizep))) #endif namespace google { @@ -78,13 +80,15 @@ struct PyContainer; typedef int (*CountMethod)(PyContainer* self); typedef const void* (*GetByIndexMethod)(PyContainer* self, int index); -typedef const void* (*GetByNameMethod)(PyContainer* self, const string& name); +typedef const void* (*GetByNameMethod)(PyContainer* self, + ConstStringParam name); typedef const void* (*GetByCamelcaseNameMethod)(PyContainer* self, - const string& name); + ConstStringParam name); typedef const void* (*GetByNumberMethod)(PyContainer* self, int index); typedef PyObject* (*NewObjectFromItemMethod)(const void* descriptor); -typedef const string& (*GetItemNameMethod)(const void* descriptor); -typedef const string& (*GetItemCamelcaseNameMethod)(const void* descriptor); +typedef const std::string& (*GetItemNameMethod)(const void* descriptor); +typedef const std::string& (*GetItemCamelcaseNameMethod)( + const void* descriptor); typedef int (*GetItemNumberMethod)(const void* descriptor); typedef int (*GetItemIndexMethod)(const void* descriptor); @@ -179,7 +183,7 @@ static bool _GetItemByKey(PyContainer* self, PyObject* key, const void** item) { return false; } *item = self->container_def->get_by_name_fn( - self, string(name, name_size)); + self, StringParam(name, name_size)); return true; } case PyContainer::KIND_BYCAMELCASENAME: @@ -196,7 +200,7 @@ static bool _GetItemByKey(PyContainer* self, PyObject* key, const void** item) { return false; } *item = self->container_def->get_by_camelcase_name_fn( - self, string(camelcase_name, name_size)); + self, StringParam(camelcase_name, name_size)); return true; } case PyContainer::KIND_BYNUMBER: @@ -227,14 +231,14 @@ static PyObject* _NewKey_ByIndex(PyContainer* self, Py_ssize_t index) { switch (self->kind) { case PyContainer::KIND_BYNAME: { - const string& name(self->container_def->get_item_name_fn(item)); - return PyString_FromStringAndSize(name.c_str(), name.size()); + const std::string& name(self->container_def->get_item_name_fn(item)); + return PyString_FromStringAndSize(name.c_str(), name.size()); } case PyContainer::KIND_BYCAMELCASENAME: { - const string& name( - self->container_def->get_item_camelcase_name_fn(item)); - return PyString_FromStringAndSize(name.c_str(), name.size()); + const std::string& name( + self->container_def->get_item_camelcase_name_fn(item)); + return PyString_FromStringAndSize(name.c_str(), name.size()); } case PyContainer::KIND_BYNUMBER: { @@ -637,6 +641,7 @@ int Find(PyContainer* self, PyObject* item) { // the .proto file definition. const void* descriptor_ptr = PyDescriptor_AsVoidPtr(item); if (descriptor_ptr == NULL) { + PyErr_Clear(); // Not a descriptor, it cannot be in the list. return -1; } @@ -957,55 +962,55 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->field_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, ConstStringParam name) { return GetDescriptor(self)->FindFieldByName(name); } -static ItemDescriptor GetByCamelcaseName(PyContainer* self, - const string& name) { +static const void* GetByCamelcaseName(PyContainer* self, + ConstStringParam name) { return GetDescriptor(self)->FindFieldByCamelcaseName(name); } -static ItemDescriptor GetByNumber(PyContainer* self, int number) { +static const void* GetByNumber(PyContainer* self, int number) { return GetDescriptor(self)->FindFieldByNumber(number); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->field(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFieldDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyFieldDescriptor_FromDescriptor(static_cast(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const std::string& GetItemName(const void* item) { + return static_cast(item)->name(); } -static const string& GetItemCamelcaseName(ItemDescriptor item) { - return item->camelcase_name(); +static const std::string& GetItemCamelcaseName(const void* item) { + return static_cast(item)->camelcase_name(); } -static int GetItemNumber(ItemDescriptor item) { - return item->number(); +static int GetItemNumber(const void* item) { + return static_cast(item)->number(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast(item)->index(); } static DescriptorContainerDef ContainerDef = { "MessageFields", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)GetByCamelcaseName, - (GetByNumberMethod)GetByNumber, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)GetItemCamelcaseName, - (GetItemNumberMethod)GetItemNumber, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + GetByCamelcaseName, + GetByNumber, + NewObjectFromItem, + GetItemName, + GetItemCamelcaseName, + GetItemNumber, + GetItemIndex, }; } // namespace fields @@ -1035,38 +1040,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->nested_type_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, ConstStringParam name) { return GetDescriptor(self)->FindNestedTypeByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->nested_type(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyMessageDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyMessageDescriptor_FromDescriptor(static_cast(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const std::string& GetItemName(const void* item) { + return static_cast(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast(item)->index(); } static DescriptorContainerDef ContainerDef = { "MessageNestedTypes", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace nested_types @@ -1087,38 +1092,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->enum_type_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, ConstStringParam name) { return GetDescriptor(self)->FindEnumTypeByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->enum_type(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyEnumDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyEnumDescriptor_FromDescriptor(static_cast(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const std::string& GetItemName(const void* item) { + return static_cast(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast(item)->index(); } static DescriptorContainerDef ContainerDef = { "MessageNestedEnums", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace enums @@ -1150,11 +1155,11 @@ static int Count(PyContainer* self) { return count; } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, ConstStringParam name) { return GetDescriptor(self)->FindEnumValueByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { // This is not optimal, but the number of enums *types* in a given message // is small. This function is only used when iterating over the mapping. const EnumDescriptor* enum_type = NULL; @@ -1173,26 +1178,27 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) { return enum_type->value(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyEnumValueDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyEnumValueDescriptor_FromDescriptor( + static_cast(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const std::string& GetItemName(const void* item) { + return static_cast(item)->name(); } static DescriptorContainerDef ContainerDef = { "MessageEnumValues", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)NULL, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + NULL, }; } // namespace enumvalues @@ -1209,38 +1215,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->extension_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, ConstStringParam name) { return GetDescriptor(self)->FindExtensionByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->extension(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFieldDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyFieldDescriptor_FromDescriptor(static_cast(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const std::string& GetItemName(const void* item) { + return static_cast(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast(item)->index(); } static DescriptorContainerDef ContainerDef = { "MessageExtensions", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace extensions @@ -1261,38 +1267,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->oneof_decl_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, ConstStringParam name) { return GetDescriptor(self)->FindOneofByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->oneof_decl(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyOneofDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyOneofDescriptor_FromDescriptor(static_cast(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const std::string& GetItemName(const void* item) { + return static_cast(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast(item)->index(); } static DescriptorContainerDef ContainerDef = { "MessageOneofs", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace oneofs @@ -1323,46 +1329,47 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->value_count(); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->value(index); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, ConstStringParam name) { return GetDescriptor(self)->FindValueByName(name); } -static ItemDescriptor GetByNumber(PyContainer* self, int number) { +static const void* GetByNumber(PyContainer* self, int number) { return GetDescriptor(self)->FindValueByNumber(number); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyEnumValueDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyEnumValueDescriptor_FromDescriptor( + static_cast(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const std::string& GetItemName(const void* item) { + return static_cast(item)->name(); } -static int GetItemNumber(ItemDescriptor item) { - return item->number(); +static int GetItemNumber(const void* item) { + return static_cast(item)->number(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast(item)->index(); } static DescriptorContainerDef ContainerDef = { "EnumValues", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)GetByNumber, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)GetItemNumber, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + GetByNumber, + NewObjectFromItem, + GetItemName, + NULL, + GetItemNumber, + GetItemIndex, }; } // namespace enumvalues @@ -1397,30 +1404,30 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->field_count(); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->field(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFieldDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyFieldDescriptor_FromDescriptor(static_cast(item)); } -static int GetItemIndex(ItemDescriptor item) { - return item->index_in_oneof(); +static int GetItemIndex(const void* item) { + return static_cast(item)->index_in_oneof(); } static DescriptorContainerDef ContainerDef = { "OneofFields", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)NULL, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)NULL, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + NULL, + NULL, + NULL, + NewObjectFromItem, + NULL, + NULL, + NULL, + GetItemIndex, }; } // namespace fields @@ -1447,38 +1454,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->method_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, ConstStringParam name) { return GetDescriptor(self)->FindMethodByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->method(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyMethodDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyMethodDescriptor_FromDescriptor(static_cast(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const std::string& GetItemName(const void* item) { + return static_cast(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast(item)->index(); } static DescriptorContainerDef ContainerDef = { "ServiceMethods", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace methods @@ -1509,38 +1516,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->message_type_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, ConstStringParam name) { return GetDescriptor(self)->FindMessageTypeByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->message_type(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyMessageDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyMessageDescriptor_FromDescriptor(static_cast(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const std::string& GetItemName(const void* item) { + return static_cast(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast(item)->index(); } static DescriptorContainerDef ContainerDef = { "FileMessages", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace messages @@ -1557,38 +1564,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->enum_type_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, ConstStringParam name) { return GetDescriptor(self)->FindEnumTypeByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->enum_type(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyEnumDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyEnumDescriptor_FromDescriptor(static_cast(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const std::string& GetItemName(const void* item) { + return static_cast(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast(item)->index(); } static DescriptorContainerDef ContainerDef = { "FileEnums", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace enums @@ -1605,38 +1612,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->extension_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, ConstStringParam name) { return GetDescriptor(self)->FindExtensionByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->extension(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFieldDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyFieldDescriptor_FromDescriptor(static_cast(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const std::string& GetItemName(const void* item) { + return static_cast(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast(item)->index(); } static DescriptorContainerDef ContainerDef = { "FileExtensions", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace extensions @@ -1653,38 +1660,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->service_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, ConstStringParam name) { return GetDescriptor(self)->FindServiceByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->service(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyServiceDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyServiceDescriptor_FromDescriptor(static_cast(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const std::string& GetItemName(const void* item) { + return static_cast(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast(item)->index(); } static DescriptorContainerDef ContainerDef = { "FileServices", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace services @@ -1701,26 +1708,26 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->dependency_count(); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->dependency(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFileDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyFileDescriptor_FromDescriptor(static_cast(item)); } static DescriptorContainerDef ContainerDef = { "FileDependencies", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)NULL, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)NULL, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)NULL, + Count, + GetByIndex, + NULL, + NULL, + NULL, + NewObjectFromItem, + NULL, + NULL, + NULL, + NULL, }; } // namespace dependencies @@ -1737,26 +1744,26 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->public_dependency_count(); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->public_dependency(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFileDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyFileDescriptor_FromDescriptor(static_cast(item)); } static DescriptorContainerDef ContainerDef = { "FilePublicDependencies", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)NULL, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)NULL, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)NULL, + Count, + GetByIndex, + NULL, + NULL, + NULL, + NewObjectFromItem, + NULL, + NULL, + NULL, + NULL, }; } // namespace public_dependencies diff --git a/python/google/protobuf/pyext/descriptor_containers.h b/python/google/protobuf/pyext/descriptor_containers.h index 83de07b68c4e4..4e05c58e2b64d 100644 --- a/python/google/protobuf/pyext/descriptor_containers.h +++ b/python/google/protobuf/pyext/descriptor_containers.h @@ -104,6 +104,6 @@ PyObject* NewServiceMethodsByName(const ServiceDescriptor* descriptor); } // namespace python } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_CONTAINERS_H__ diff --git a/python/google/protobuf/pyext/descriptor_database.cc b/python/google/protobuf/pyext/descriptor_database.cc index daa40cc720ac9..26f1b5fb42fbc 100644 --- a/python/google/protobuf/pyext/descriptor_database.cc +++ b/python/google/protobuf/pyext/descriptor_database.cc @@ -70,7 +70,7 @@ static bool GetFileDescriptorProto(PyObject* py_descriptor, const Descriptor* filedescriptor_descriptor = FileDescriptorProto::default_instance().GetDescriptor(); CMessage* message = reinterpret_cast(py_descriptor); - if (PyObject_TypeCheck(py_descriptor, &CMessage_Type) && + if (PyObject_TypeCheck(py_descriptor, CMessage_Type) && message->message->GetDescriptor() == filedescriptor_descriptor) { // Fast path: Just use the pointer. FileDescriptorProto* file_proto = @@ -108,7 +108,7 @@ static bool GetFileDescriptorProto(PyObject* py_descriptor, } // Find a file by file name. -bool PyDescriptorDatabase::FindFileByName(const string& filename, +bool PyDescriptorDatabase::FindFileByName(const std::string& filename, FileDescriptorProto* output) { ScopedPyObjectPtr py_descriptor(PyObject_CallMethod( py_database_, "FindFileByName", "s#", filename.c_str(), filename.size())); @@ -117,7 +117,7 @@ bool PyDescriptorDatabase::FindFileByName(const string& filename, // Find the file that declares the given fully-qualified symbol name. bool PyDescriptorDatabase::FindFileContainingSymbol( - const string& symbol_name, FileDescriptorProto* output) { + const std::string& symbol_name, FileDescriptorProto* output) { ScopedPyObjectPtr py_descriptor( PyObject_CallMethod(py_database_, "FindFileContainingSymbol", "s#", symbol_name.c_str(), symbol_name.size())); @@ -128,7 +128,7 @@ bool PyDescriptorDatabase::FindFileContainingSymbol( // with the given field number. // Python DescriptorDatabases are not required to implement this method. bool PyDescriptorDatabase::FindFileContainingExtension( - const string& containing_type, int field_number, + const std::string& containing_type, int field_number, FileDescriptorProto* output) { ScopedPyObjectPtr py_method( PyObject_GetAttrString(py_database_, "FindFileContainingExtension")); @@ -143,6 +143,43 @@ bool PyDescriptorDatabase::FindFileContainingExtension( return GetFileDescriptorProto(py_descriptor.get(), output); } +// Finds the tag numbers used by all known extensions of +// containing_type, and appends them to output in an undefined +// order. +// Python DescriptorDatabases are not required to implement this method. +bool PyDescriptorDatabase::FindAllExtensionNumbers( + const std::string& containing_type, std::vector* output) { + ScopedPyObjectPtr py_method( + PyObject_GetAttrString(py_database_, "FindAllExtensionNumbers")); + if (py_method == NULL) { + // This method is not implemented, returns without error. + PyErr_Clear(); + return false; + } + ScopedPyObjectPtr py_list( + PyObject_CallFunction(py_method.get(), "s#", containing_type.c_str(), + containing_type.size())); + if (py_list == NULL) { + PyErr_Print(); + return false; + } + Py_ssize_t size = PyList_Size(py_list.get()); + int64 item_value; + for (Py_ssize_t i = 0 ; i < size; ++i) { + ScopedPyObjectPtr item(PySequence_GetItem(py_list.get(), i)); + item_value = PyLong_AsLong(item.get()); + if (item_value < 0) { + GOOGLE_LOG(ERROR) + << "FindAllExtensionNumbers method did not return " + << "valid extension numbers."; + PyErr_Print(); + return false; + } + output->push_back(item_value); + } + return true; +} + } // namespace python } // namespace protobuf } // namespace google diff --git a/python/google/protobuf/pyext/descriptor_database.h b/python/google/protobuf/pyext/descriptor_database.h index fc71c4bcb0b56..d2d9f8e506dff 100644 --- a/python/google/protobuf/pyext/descriptor_database.h +++ b/python/google/protobuf/pyext/descriptor_database.h @@ -48,21 +48,27 @@ class PyDescriptorDatabase : public DescriptorDatabase { // with a copy of FileDescriptorProto. // Find a file by file name. - bool FindFileByName(const string& filename, - FileDescriptorProto* output); + bool FindFileByName(const std::string& filename, FileDescriptorProto* output); // Find the file that declares the given fully-qualified symbol name. - bool FindFileContainingSymbol(const string& symbol_name, + bool FindFileContainingSymbol(const std::string& symbol_name, FileDescriptorProto* output); // Find the file which defines an extension extending the given message type // with the given field number. // Containing_type must be a fully-qualified type name. // Python objects are not required to implement this method. - bool FindFileContainingExtension(const string& containing_type, + bool FindFileContainingExtension(const std::string& containing_type, int field_number, FileDescriptorProto* output); + // Finds the tag numbers used by all known extensions of + // containing_type, and appends them to output in an undefined + // order. + // Python objects are not required to implement this method. + bool FindAllExtensionNumbers(const std::string& containing_type, + std::vector* output); + private: // The python object that implements the database. The reference is owned. PyObject* py_database_; @@ -70,6 +76,6 @@ class PyDescriptorDatabase : public DescriptorDatabase { } // namespace python } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_DATABASE_H__ diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc index 16f4d49d25cf4..6f1464e3212d7 100644 --- a/python/google/protobuf/pyext/descriptor_pool.cc +++ b/python/google/protobuf/pyext/descriptor_pool.cc @@ -30,6 +30,8 @@ // Implements the DescriptorPool, which collects all descriptors. +#include + #include #include @@ -46,10 +48,12 @@ #if PY_VERSION_HEX < 0x03030000 #error "Python 3.0 - 3.2 are not supported." #endif - #define PyString_AsStringAndSize(ob, charpp, sizep) \ - (PyUnicode_Check(ob)? \ - ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \ - PyBytes_AsStringAndSize(ob, (charpp), (sizep))) +#define PyString_AsStringAndSize(ob, charpp, sizep) \ + (PyUnicode_Check(ob) ? ((*(charpp) = const_cast( \ + PyUnicode_AsUTF8AndSize(ob, (sizep)))) == NULL \ + ? -1 \ + : 0) \ + : PyBytes_AsStringAndSize(ob, (charpp), (sizep))) #endif namespace google { @@ -58,24 +62,57 @@ namespace python { // A map to cache Python Pools per C++ pointer. // Pointers are not owned here, and belong to the PyDescriptorPool. -static hash_map descriptor_pool_map; +static std::unordered_map* + descriptor_pool_map; namespace cdescriptor_pool { +// Collects errors that occur during proto file building to allow them to be +// propagated in the python exception instead of only living in ERROR logs. +class BuildFileErrorCollector : public DescriptorPool::ErrorCollector { + public: + BuildFileErrorCollector() : error_message(""), had_errors_(false) {} + + void AddError(const std::string& filename, const std::string& element_name, + const Message* descriptor, ErrorLocation location, + const std::string& message) override { + // Replicates the logging behavior that happens in the C++ implementation + // when an error collector is not passed in. + if (!had_errors_) { + error_message += + ("Invalid proto descriptor for file \"" + filename + "\":\n"); + had_errors_ = true; + } + // As this only happens on failure and will result in the program not + // running at all, no effort is made to optimize this string manipulation. + error_message += (" " + element_name + ": " + message + "\n"); + } + + void Clear() { + had_errors_ = false; + error_message = ""; + } + + std::string error_message; + + private: + bool had_errors_; +}; + // Create a Python DescriptorPool object, but does not fill the "pool" // attribute. static PyDescriptorPool* _CreateDescriptorPool() { - PyDescriptorPool* cpool = PyObject_New( + PyDescriptorPool* cpool = PyObject_GC_New( PyDescriptorPool, &PyDescriptorPool_Type); if (cpool == NULL) { return NULL; } + cpool->error_collector = nullptr; cpool->underlay = NULL; cpool->database = NULL; - cpool->descriptor_options = - new hash_map(); + cpool->descriptor_options = new std::unordered_map(); cpool->py_message_factory = message_factory::NewMessageFactory( &PyMessageFactory_Type, cpool); @@ -84,6 +121,8 @@ static PyDescriptorPool* _CreateDescriptorPool() { return NULL; } + PyObject_GC_Track(cpool); + return cpool; } @@ -101,7 +140,7 @@ static PyDescriptorPool* PyDescriptorPool_NewWithUnderlay( cpool->pool = new DescriptorPool(underlay); cpool->underlay = underlay; - if (!descriptor_pool_map.insert( + if (!descriptor_pool_map->insert( std::make_pair(cpool->pool, cpool)).second) { // Should never happen -- would indicate an internal error / bug. PyErr_SetString(PyExc_ValueError, "DescriptorPool already registered"); @@ -118,13 +157,14 @@ static PyDescriptorPool* PyDescriptorPool_NewWithDatabase( return NULL; } if (database != NULL) { - cpool->pool = new DescriptorPool(database); + cpool->error_collector = new BuildFileErrorCollector(); + cpool->pool = new DescriptorPool(database, cpool->error_collector); cpool->database = database; } else { cpool->pool = new DescriptorPool(); } - if (!descriptor_pool_map.insert(std::make_pair(cpool->pool, cpool)).second) { + if (!descriptor_pool_map->insert(std::make_pair(cpool->pool, cpool)).second) { // Should never happen -- would indicate an internal error / bug. PyErr_SetString(PyExc_ValueError, "DescriptorPool already registered"); return NULL; @@ -149,10 +189,11 @@ static PyObject* New(PyTypeObject* type, PyDescriptorPool_NewWithDatabase(database)); } -static void Dealloc(PyDescriptorPool* self) { - descriptor_pool_map.erase(self->pool); +static void Dealloc(PyObject* pself) { + PyDescriptorPool* self = reinterpret_cast(pself); + descriptor_pool_map->erase(self->pool); Py_CLEAR(self->py_message_factory); - for (hash_map::iterator it = + for (std::unordered_map::iterator it = self->descriptor_options->begin(); it != self->descriptor_options->end(); ++it) { Py_DECREF(it->second); @@ -160,10 +201,37 @@ static void Dealloc(PyDescriptorPool* self) { delete self->descriptor_options; delete self->database; delete self->pool; - Py_TYPE(self)->tp_free(reinterpret_cast(self)); + delete self->error_collector; + Py_TYPE(self)->tp_free(pself); +} + +static int GcTraverse(PyObject* pself, visitproc visit, void* arg) { + PyDescriptorPool* self = reinterpret_cast(pself); + Py_VISIT(self->py_message_factory); + return 0; +} + +static int GcClear(PyObject* pself) { + PyDescriptorPool* self = reinterpret_cast(pself); + Py_CLEAR(self->py_message_factory); + return 0; +} + +PyObject* SetErrorFromCollector(DescriptorPool::ErrorCollector* self, + char* name, char* error_type) { + BuildFileErrorCollector* error_collector = + reinterpret_cast(self); + if (error_collector && !error_collector->error_message.empty()) { + PyErr_Format(PyExc_KeyError, "Couldn't build file for %s %.200s\n%s", + error_type, name, error_collector->error_message.c_str()); + error_collector->Clear(); + return NULL; + } + PyErr_Format(PyExc_KeyError, "Couldn't find %s %.200s", error_type, name); + return NULL; } -PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) { +static PyObject* FindMessageByName(PyObject* self, PyObject* arg) { Py_ssize_t name_size; char* name; if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { @@ -171,31 +239,35 @@ PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) { } const Descriptor* message_descriptor = - self->pool->FindMessageTypeByName(string(name, name_size)); + reinterpret_cast(self)->pool->FindMessageTypeByName( + StringParam(name, name_size)); if (message_descriptor == NULL) { - PyErr_Format(PyExc_KeyError, "Couldn't find message %.200s", name); - return NULL; + return SetErrorFromCollector( + reinterpret_cast(self)->error_collector, name, + "message"); } + return PyMessageDescriptor_FromDescriptor(message_descriptor); } -PyObject* FindFileByName(PyDescriptorPool* self, PyObject* arg) { +static PyObject* FindFileByName(PyObject* self, PyObject* arg) { Py_ssize_t name_size; char* name; if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { return NULL; } + PyDescriptorPool* py_pool = reinterpret_cast(self); const FileDescriptor* file_descriptor = - self->pool->FindFileByName(string(name, name_size)); + py_pool->pool->FindFileByName(StringParam(name, name_size)); + if (file_descriptor == NULL) { - PyErr_Format(PyExc_KeyError, "Couldn't find file %.200s", name); - return NULL; + return SetErrorFromCollector(py_pool->error_collector, name, "file"); } return PyFileDescriptor_FromDescriptor(file_descriptor); } @@ -208,16 +280,19 @@ PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* arg) { } const FieldDescriptor* field_descriptor = - self->pool->FindFieldByName(string(name, name_size)); + self->pool->FindFieldByName(StringParam(name, name_size)); if (field_descriptor == NULL) { - PyErr_Format(PyExc_KeyError, "Couldn't find field %.200s", - name); - return NULL; + return SetErrorFromCollector(self->error_collector, name, "field"); } + return PyFieldDescriptor_FromDescriptor(field_descriptor); } +static PyObject* FindFieldByNameMethod(PyObject* self, PyObject* arg) { + return FindFieldByName(reinterpret_cast(self), arg); +} + PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) { Py_ssize_t name_size; char* name; @@ -226,15 +301,20 @@ PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) { } const FieldDescriptor* field_descriptor = - self->pool->FindExtensionByName(string(name, name_size)); + self->pool->FindExtensionByName(StringParam(name, name_size)); if (field_descriptor == NULL) { - PyErr_Format(PyExc_KeyError, "Couldn't find extension field %.200s", name); - return NULL; + return SetErrorFromCollector(self->error_collector, name, + "extension field"); } + return PyFieldDescriptor_FromDescriptor(field_descriptor); } +static PyObject* FindExtensionByNameMethod(PyObject* self, PyObject* arg) { + return FindExtensionByName(reinterpret_cast(self), arg); +} + PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) { Py_ssize_t name_size; char* name; @@ -243,15 +323,19 @@ PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) { } const EnumDescriptor* enum_descriptor = - self->pool->FindEnumTypeByName(string(name, name_size)); + self->pool->FindEnumTypeByName(StringParam(name, name_size)); if (enum_descriptor == NULL) { - PyErr_Format(PyExc_KeyError, "Couldn't find enum %.200s", name); - return NULL; + return SetErrorFromCollector(self->error_collector, name, "enum"); } + return PyEnumDescriptor_FromDescriptor(enum_descriptor); } +static PyObject* FindEnumTypeByNameMethod(PyObject* self, PyObject* arg) { + return FindEnumTypeByName(reinterpret_cast(self), arg); +} + PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) { Py_ssize_t name_size; char* name; @@ -260,16 +344,20 @@ PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) { } const OneofDescriptor* oneof_descriptor = - self->pool->FindOneofByName(string(name, name_size)); + self->pool->FindOneofByName(StringParam(name, name_size)); if (oneof_descriptor == NULL) { - PyErr_Format(PyExc_KeyError, "Couldn't find oneof %.200s", name); - return NULL; + return SetErrorFromCollector(self->error_collector, name, "oneof"); } + return PyOneofDescriptor_FromDescriptor(oneof_descriptor); } -PyObject* FindServiceByName(PyDescriptorPool* self, PyObject* arg) { +static PyObject* FindOneofByNameMethod(PyObject* self, PyObject* arg) { + return FindOneofByName(reinterpret_cast(self), arg); +} + +static PyObject* FindServiceByName(PyObject* self, PyObject* arg) { Py_ssize_t name_size; char* name; if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { @@ -277,16 +365,19 @@ PyObject* FindServiceByName(PyDescriptorPool* self, PyObject* arg) { } const ServiceDescriptor* service_descriptor = - self->pool->FindServiceByName(string(name, name_size)); + reinterpret_cast(self)->pool->FindServiceByName( + StringParam(name, name_size)); if (service_descriptor == NULL) { - PyErr_Format(PyExc_KeyError, "Couldn't find service %.200s", name); - return NULL; + return SetErrorFromCollector( + reinterpret_cast(self)->error_collector, name, + "service"); } + return PyServiceDescriptor_FromDescriptor(service_descriptor); } -PyObject* FindMethodByName(PyDescriptorPool* self, PyObject* arg) { +static PyObject* FindMethodByName(PyObject* self, PyObject* arg) { Py_ssize_t name_size; char* name; if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { @@ -294,16 +385,19 @@ PyObject* FindMethodByName(PyDescriptorPool* self, PyObject* arg) { } const MethodDescriptor* method_descriptor = - self->pool->FindMethodByName(string(name, name_size)); + reinterpret_cast(self)->pool->FindMethodByName( + StringParam(name, name_size)); if (method_descriptor == NULL) { - PyErr_Format(PyExc_KeyError, "Couldn't find method %.200s", name); - return NULL; + return SetErrorFromCollector( + reinterpret_cast(self)->error_collector, name, + "method"); } + return PyMethodDescriptor_FromDescriptor(method_descriptor); } -PyObject* FindFileContainingSymbol(PyDescriptorPool* self, PyObject* arg) { +static PyObject* FindFileContainingSymbol(PyObject* self, PyObject* arg) { Py_ssize_t name_size; char* name; if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { @@ -311,16 +405,19 @@ PyObject* FindFileContainingSymbol(PyDescriptorPool* self, PyObject* arg) { } const FileDescriptor* file_descriptor = - self->pool->FindFileContainingSymbol(string(name, name_size)); + reinterpret_cast(self)->pool->FindFileContainingSymbol( + StringParam(name, name_size)); if (file_descriptor == NULL) { - PyErr_Format(PyExc_KeyError, "Couldn't find symbol %.200s", name); - return NULL; + return SetErrorFromCollector( + reinterpret_cast(self)->error_collector, name, + "symbol"); } + return PyFileDescriptor_FromDescriptor(file_descriptor); } -PyObject* FindExtensionByNumber(PyDescriptorPool* self, PyObject* args) { +static PyObject* FindExtensionByNumber(PyObject* self, PyObject* args) { PyObject* message_descriptor; int number; if (!PyArg_ParseTuple(args, "Oi", &message_descriptor, &number)) { @@ -333,23 +430,35 @@ PyObject* FindExtensionByNumber(PyDescriptorPool* self, PyObject* args) { } const FieldDescriptor* extension_descriptor = - self->pool->FindExtensionByNumber(descriptor, number); + reinterpret_cast(self)->pool->FindExtensionByNumber( + descriptor, number); if (extension_descriptor == NULL) { - PyErr_Format(PyExc_KeyError, "Couldn't find extension %d", number); + BuildFileErrorCollector* error_collector = + reinterpret_cast( + reinterpret_cast(self)->error_collector); + if (error_collector && !error_collector->error_message.empty()) { + PyErr_Format(PyExc_KeyError, "Couldn't build file for Extension %.d\n%s", + number, error_collector->error_message.c_str()); + error_collector->Clear(); + return NULL; + } + PyErr_Format(PyExc_KeyError, "Couldn't find Extension %d", number); return NULL; } + return PyFieldDescriptor_FromDescriptor(extension_descriptor); } -PyObject* FindAllExtensions(PyDescriptorPool* self, PyObject* arg) { +static PyObject* FindAllExtensions(PyObject* self, PyObject* arg) { const Descriptor* descriptor = PyMessageDescriptor_AsDescriptor(arg); if (descriptor == NULL) { return NULL; } std::vector extensions; - self->pool->FindAllExtensions(descriptor, &extensions); + reinterpret_cast(self)->pool->FindAllExtensions( + descriptor, &extensions); ScopedPyObjectPtr result(PyList_New(extensions.size())); if (result == NULL) { @@ -374,14 +483,15 @@ PyObject* FindAllExtensions(PyDescriptorPool* self, PyObject* arg) { // call a function that will just be a no-op? // TODO(amauryfa): Need to investigate further. -PyObject* AddFileDescriptor(PyDescriptorPool* self, PyObject* descriptor) { +static PyObject* AddFileDescriptor(PyObject* self, PyObject* descriptor) { const FileDescriptor* file_descriptor = PyFileDescriptor_AsDescriptor(descriptor); if (!file_descriptor) { return NULL; } if (file_descriptor != - self->pool->FindFileByName(file_descriptor->name())) { + reinterpret_cast(self)->pool->FindFileByName( + file_descriptor->name())) { PyErr_Format(PyExc_ValueError, "The file descriptor %s does not belong to this pool", file_descriptor->name().c_str()); @@ -390,14 +500,15 @@ PyObject* AddFileDescriptor(PyDescriptorPool* self, PyObject* descriptor) { Py_RETURN_NONE; } -PyObject* AddDescriptor(PyDescriptorPool* self, PyObject* descriptor) { +static PyObject* AddDescriptor(PyObject* self, PyObject* descriptor) { const Descriptor* message_descriptor = PyMessageDescriptor_AsDescriptor(descriptor); if (!message_descriptor) { return NULL; } if (message_descriptor != - self->pool->FindMessageTypeByName(message_descriptor->full_name())) { + reinterpret_cast(self)->pool->FindMessageTypeByName( + message_descriptor->full_name())) { PyErr_Format(PyExc_ValueError, "The message descriptor %s does not belong to this pool", message_descriptor->full_name().c_str()); @@ -406,14 +517,15 @@ PyObject* AddDescriptor(PyDescriptorPool* self, PyObject* descriptor) { Py_RETURN_NONE; } -PyObject* AddEnumDescriptor(PyDescriptorPool* self, PyObject* descriptor) { +static PyObject* AddEnumDescriptor(PyObject* self, PyObject* descriptor) { const EnumDescriptor* enum_descriptor = PyEnumDescriptor_AsDescriptor(descriptor); if (!enum_descriptor) { return NULL; } if (enum_descriptor != - self->pool->FindEnumTypeByName(enum_descriptor->full_name())) { + reinterpret_cast(self)->pool->FindEnumTypeByName( + enum_descriptor->full_name())) { PyErr_Format(PyExc_ValueError, "The enum descriptor %s does not belong to this pool", enum_descriptor->full_name().c_str()); @@ -422,14 +534,15 @@ PyObject* AddEnumDescriptor(PyDescriptorPool* self, PyObject* descriptor) { Py_RETURN_NONE; } -PyObject* AddExtensionDescriptor(PyDescriptorPool* self, PyObject* descriptor) { +static PyObject* AddExtensionDescriptor(PyObject* self, PyObject* descriptor) { const FieldDescriptor* extension_descriptor = PyFieldDescriptor_AsDescriptor(descriptor); if (!extension_descriptor) { return NULL; } if (extension_descriptor != - self->pool->FindExtensionByName(extension_descriptor->full_name())) { + reinterpret_cast(self)->pool->FindExtensionByName( + extension_descriptor->full_name())) { PyErr_Format(PyExc_ValueError, "The extension descriptor %s does not belong to this pool", extension_descriptor->full_name().c_str()); @@ -438,14 +551,15 @@ PyObject* AddExtensionDescriptor(PyDescriptorPool* self, PyObject* descriptor) { Py_RETURN_NONE; } -PyObject* AddServiceDescriptor(PyDescriptorPool* self, PyObject* descriptor) { +static PyObject* AddServiceDescriptor(PyObject* self, PyObject* descriptor) { const ServiceDescriptor* service_descriptor = PyServiceDescriptor_AsDescriptor(descriptor); if (!service_descriptor) { return NULL; } if (service_descriptor != - self->pool->FindServiceByName(service_descriptor->full_name())) { + reinterpret_cast(self)->pool->FindServiceByName( + service_descriptor->full_name())) { PyErr_Format(PyExc_ValueError, "The service descriptor %s does not belong to this pool", service_descriptor->full_name().c_str()); @@ -455,33 +569,8 @@ PyObject* AddServiceDescriptor(PyDescriptorPool* self, PyObject* descriptor) { } // The code below loads new Descriptors from a serialized FileDescriptorProto. - -// Collects errors that occur during proto file building to allow them to be -// propagated in the python exception instead of only living in ERROR logs. -class BuildFileErrorCollector : public DescriptorPool::ErrorCollector { - public: - BuildFileErrorCollector() : error_message(""), had_errors(false) {} - - void AddError(const string& filename, const string& element_name, - const Message* descriptor, ErrorLocation location, - const string& message) { - // Replicates the logging behavior that happens in the C++ implementation - // when an error collector is not passed in. - if (!had_errors) { - error_message += - ("Invalid proto descriptor for file \"" + filename + "\":\n"); - had_errors = true; - } - // As this only happens on failure and will result in the program not - // running at all, no effort is made to optimize this string manipulation. - error_message += (" " + element_name + ": " + message + "\n"); - } - - string error_message; - bool had_errors; -}; - -PyObject* AddSerializedFile(PyDescriptorPool* self, PyObject* serialized_pb) { +static PyObject* AddSerializedFile(PyObject* pself, PyObject* serialized_pb) { + PyDescriptorPool* self = reinterpret_cast(pself); char* message_type; Py_ssize_t message_len; @@ -529,7 +618,7 @@ PyObject* AddSerializedFile(PyDescriptorPool* self, PyObject* serialized_pb) { descriptor, serialized_pb); } -PyObject* Add(PyDescriptorPool* self, PyObject* file_descriptor_proto) { +static PyObject* Add(PyObject* self, PyObject* file_descriptor_proto) { ScopedPyObjectPtr serialized_pb( PyObject_CallMethod(file_descriptor_proto, "SerializeToString", NULL)); if (serialized_pb == NULL) { @@ -539,46 +628,46 @@ PyObject* Add(PyDescriptorPool* self, PyObject* file_descriptor_proto) { } static PyMethodDef Methods[] = { - { "Add", (PyCFunction)Add, METH_O, + { "Add", Add, METH_O, "Adds the FileDescriptorProto and its types to this pool." }, - { "AddSerializedFile", (PyCFunction)AddSerializedFile, METH_O, + { "AddSerializedFile", AddSerializedFile, METH_O, "Adds a serialized FileDescriptorProto to this pool." }, // TODO(amauryfa): Understand why the Python implementation differs from // this one, ask users to use another API and deprecate these functions. - { "AddFileDescriptor", (PyCFunction)AddFileDescriptor, METH_O, + { "AddFileDescriptor", AddFileDescriptor, METH_O, "No-op. Add() must have been called before." }, - { "AddDescriptor", (PyCFunction)AddDescriptor, METH_O, + { "AddDescriptor", AddDescriptor, METH_O, "No-op. Add() must have been called before." }, - { "AddEnumDescriptor", (PyCFunction)AddEnumDescriptor, METH_O, + { "AddEnumDescriptor", AddEnumDescriptor, METH_O, "No-op. Add() must have been called before." }, - { "AddExtensionDescriptor", (PyCFunction)AddExtensionDescriptor, METH_O, + { "AddExtensionDescriptor", AddExtensionDescriptor, METH_O, "No-op. Add() must have been called before." }, - { "AddServiceDescriptor", (PyCFunction)AddServiceDescriptor, METH_O, + { "AddServiceDescriptor", AddServiceDescriptor, METH_O, "No-op. Add() must have been called before." }, - { "FindFileByName", (PyCFunction)FindFileByName, METH_O, + { "FindFileByName", FindFileByName, METH_O, "Searches for a file descriptor by its .proto name." }, - { "FindMessageTypeByName", (PyCFunction)FindMessageByName, METH_O, + { "FindMessageTypeByName", FindMessageByName, METH_O, "Searches for a message descriptor by full name." }, - { "FindFieldByName", (PyCFunction)FindFieldByName, METH_O, + { "FindFieldByName", FindFieldByNameMethod, METH_O, "Searches for a field descriptor by full name." }, - { "FindExtensionByName", (PyCFunction)FindExtensionByName, METH_O, + { "FindExtensionByName", FindExtensionByNameMethod, METH_O, "Searches for extension descriptor by full name." }, - { "FindEnumTypeByName", (PyCFunction)FindEnumTypeByName, METH_O, + { "FindEnumTypeByName", FindEnumTypeByNameMethod, METH_O, "Searches for enum type descriptor by full name." }, - { "FindOneofByName", (PyCFunction)FindOneofByName, METH_O, + { "FindOneofByName", FindOneofByNameMethod, METH_O, "Searches for oneof descriptor by full name." }, - { "FindServiceByName", (PyCFunction)FindServiceByName, METH_O, + { "FindServiceByName", FindServiceByName, METH_O, "Searches for service descriptor by full name." }, - { "FindMethodByName", (PyCFunction)FindMethodByName, METH_O, + { "FindMethodByName", FindMethodByName, METH_O, "Searches for method descriptor by full name." }, - { "FindFileContainingSymbol", (PyCFunction)FindFileContainingSymbol, METH_O, + { "FindFileContainingSymbol", FindFileContainingSymbol, METH_O, "Gets the FileDescriptor containing the specified symbol." }, - { "FindExtensionByNumber", (PyCFunction)FindExtensionByNumber, METH_VARARGS, + { "FindExtensionByNumber", FindExtensionByNumber, METH_VARARGS, "Gets the extension descriptor for the given number." }, - { "FindAllExtensions", (PyCFunction)FindAllExtensions, METH_O, + { "FindAllExtensions", FindAllExtensions, METH_O, "Gets all known extensions of the given message descriptor." }, {NULL} }; @@ -586,45 +675,45 @@ static PyMethodDef Methods[] = { } // namespace cdescriptor_pool PyTypeObject PyDescriptorPool_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - FULL_MODULE_NAME ".DescriptorPool", // tp_name - sizeof(PyDescriptorPool), // tp_basicsize - 0, // tp_itemsize - (destructor)cdescriptor_pool::Dealloc, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - 0, // tp_repr - 0, // tp_as_number - 0, // tp_as_sequence - 0, // tp_as_mapping - 0, // tp_hash - 0, // tp_call - 0, // tp_str - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "A Descriptor Pool", // tp_doc - 0, // tp_traverse - 0, // tp_clear - 0, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - cdescriptor_pool::Methods, // tp_methods - 0, // tp_members - 0, // tp_getset - 0, // tp_base - 0, // tp_dict - 0, // tp_descr_get - 0, // tp_descr_set - 0, // tp_dictoffset - 0, // tp_init - 0, // tp_alloc - cdescriptor_pool::New, // tp_new - PyObject_Del, // tp_free + PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME + ".DescriptorPool", // tp_name + sizeof(PyDescriptorPool), // tp_basicsize + 0, // tp_itemsize + cdescriptor_pool::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags + "A Descriptor Pool", // tp_doc + cdescriptor_pool::GcTraverse, // tp_traverse + cdescriptor_pool::GcClear, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + cdescriptor_pool::Methods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + cdescriptor_pool::New, // tp_new + PyObject_GC_Del, // tp_free }; // This is the DescriptorPool which contains all the definitions from the @@ -638,13 +727,17 @@ bool InitDescriptorPool() { // The Pool of messages declared in Python libraries. // generated_pool() contains all messages already linked in C++ libraries, and // is used as underlay. + descriptor_pool_map = + new std::unordered_map; python_generated_pool = cdescriptor_pool::PyDescriptorPool_NewWithUnderlay( DescriptorPool::generated_pool()); if (python_generated_pool == NULL) { + delete descriptor_pool_map; return false; } + // Register this pool to be found for C++-generated descriptors. - descriptor_pool_map.insert( + descriptor_pool_map->insert( std::make_pair(DescriptorPool::generated_pool(), python_generated_pool)); @@ -665,9 +758,9 @@ PyDescriptorPool* GetDescriptorPool_FromPool(const DescriptorPool* pool) { pool == DescriptorPool::generated_pool()) { return python_generated_pool; } - hash_map::iterator it = - descriptor_pool_map.find(pool); - if (it == descriptor_pool_map.end()) { + std::unordered_map::iterator it = + descriptor_pool_map->find(pool); + if (it == descriptor_pool_map->end()) { PyErr_SetString(PyExc_KeyError, "Unknown descriptor pool"); return NULL; } diff --git a/python/google/protobuf/pyext/descriptor_pool.h b/python/google/protobuf/pyext/descriptor_pool.h index 53ee53dc5e853..2d456f9088edf 100644 --- a/python/google/protobuf/pyext/descriptor_pool.h +++ b/python/google/protobuf/pyext/descriptor_pool.h @@ -33,7 +33,7 @@ #include -#include +#include #include namespace google { @@ -50,8 +50,6 @@ struct CMessageClass; // // There is normally one pool per process. We make it a Python object only // because it contains many Python references. -// TODO(amauryfa): See whether such objects can appear in reference cycles, and -// consider adding support for the cyclic GC. // // "Methods" that interacts with this DescriptorPool are in the cdescriptor_pool // namespace. @@ -61,6 +59,10 @@ typedef struct PyDescriptorPool { // The C++ pool containing Descriptors. DescriptorPool* pool; + // The error collector to store error info. Can be NULL. This pointer is + // owned. + DescriptorPool::ErrorCollector* error_collector; + // The C++ pool acting as an underlay. Can be NULL. // This pointer is not owned and must stay alive. const DescriptorPool* underlay; @@ -77,7 +79,7 @@ typedef struct PyDescriptorPool { // Cache the options for any kind of descriptor. // Descriptor pointers are owned by the DescriptorPool above. // Python objects are owned by the map. - hash_map* descriptor_options; + std::unordered_map* descriptor_options; } PyDescriptorPool; @@ -86,19 +88,8 @@ extern PyTypeObject PyDescriptorPool_Type; namespace cdescriptor_pool { -// Looks up a message by name. -// Returns a message Descriptor, or NULL if not found. -const Descriptor* FindMessageTypeByName(PyDescriptorPool* self, - const string& name); - // The functions below are also exposed as methods of the DescriptorPool type. -// Looks up a message by name. Returns a PyMessageDescriptor corresponding to -// the field on success, or NULL on failure. -// -// Returns a new reference. -PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* name); - // Looks up a field by name. Returns a PyFieldDescriptor corresponding to // the field on success, or NULL on failure. // @@ -140,6 +131,6 @@ bool InitDescriptorPool(); } // namespace python } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_POOL_H__ diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc index 43ee5d15f4f61..e9ac71409e28a 100644 --- a/python/google/protobuf/pyext/extension_dict.cc +++ b/python/google/protobuf/pyext/extension_dict.cc @@ -32,6 +32,7 @@ // Author: tibell@google.com (Johan Tibell) #include +#include #include #include @@ -45,16 +46,17 @@ #include #include #include -#include #if PY_MAJOR_VERSION >= 3 #if PY_VERSION_HEX < 0x03030000 #error "Python 3.0 - 3.2 are not supported." #endif - #define PyString_AsStringAndSize(ob, charpp, sizep) \ - (PyUnicode_Check(ob)? \ - ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \ - PyBytes_AsStringAndSize(ob, (charpp), (sizep))) +#define PyString_AsStringAndSize(ob, charpp, sizep) \ + (PyUnicode_Check(ob) ? ((*(charpp) = const_cast( \ + PyUnicode_AsUTF8AndSize(ob, (sizep)))) == NULL \ + ? -1 \ + : 0) \ + : PyBytes_AsStringAndSize(ob, (charpp), (sizep))) #endif namespace google { @@ -63,12 +65,70 @@ namespace python { namespace extension_dict { -PyObject* len(ExtensionDict* self) { -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(PyDict_Size(self->values)); -#else - return PyInt_FromLong(PyDict_Size(self->values)); -#endif +static Py_ssize_t len(ExtensionDict* self) { + Py_ssize_t size = 0; + std::vector fields; + self->parent->message->GetReflection()->ListFields(*self->parent->message, + &fields); + + for (size_t i = 0; i < fields.size(); ++i) { + if (fields[i]->is_extension()) { + // With C++ descriptors, the field can always be retrieved, but for + // unknown extensions which have not been imported in Python code, there + // is no message class and we cannot retrieve the value. + // ListFields() has the same behavior. + if (fields[i]->message_type() != nullptr && + message_factory::GetMessageClass( + cmessage::GetFactoryForMessage(self->parent), + fields[i]->message_type()) == nullptr) { + PyErr_Clear(); + continue; + } + ++size; + } + } + return size; +} + +struct ExtensionIterator { + PyObject_HEAD; + Py_ssize_t index; + std::vector fields; + + // Owned reference, to keep the FieldDescriptors alive. + ExtensionDict* extension_dict; +}; + +PyObject* GetIter(PyObject* _self) { + ExtensionDict* self = reinterpret_cast(_self); + + ScopedPyObjectPtr obj(PyType_GenericAlloc(&ExtensionIterator_Type, 0)); + if (obj == nullptr) { + return PyErr_Format(PyExc_MemoryError, + "Could not allocate extension iterator"); + } + + ExtensionIterator* iter = reinterpret_cast(obj.get()); + + // Call "placement new" to initialize. So the constructor of + // std::vector<...> fields will be called. + new (iter) ExtensionIterator; + + self->parent->message->GetReflection()->ListFields(*self->parent->message, + &iter->fields); + iter->index = 0; + Py_INCREF(self); + iter->extension_dict = self; + + return obj.release(); +} + +static void DeallocExtensionIterator(PyObject* _self) { + ExtensionIterator* self = reinterpret_cast(_self); + self->fields.clear(); + Py_XDECREF(self->extension_dict); + self->~ExtensionIterator(); + Py_TYPE(_self)->tp_free(_self); } PyObject* subscript(ExtensionDict* self, PyObject* key) { @@ -76,39 +136,32 @@ PyObject* subscript(ExtensionDict* self, PyObject* key) { if (descriptor == NULL) { return NULL; } - if (!CheckFieldBelongsToMessage(descriptor, self->message)) { + if (!CheckFieldBelongsToMessage(descriptor, self->parent->message)) { return NULL; } if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { - return cmessage::InternalGetScalar(self->message, descriptor); + return cmessage::InternalGetScalar(self->parent->message, descriptor); } - PyObject* value = PyDict_GetItem(self->values, key); - if (value != NULL) { - Py_INCREF(value); - return value; - } - - if (self->parent == NULL) { - // We are in "detached" state. Don't allow further modifications. - // TODO(amauryfa): Support adding non-scalars to a detached extension dict. - // This probably requires to store the type of the main message. - PyErr_SetObject(PyExc_KeyError, key); - return NULL; + CMessage::CompositeFieldsMap::iterator iterator = + self->parent->composite_fields->find(descriptor); + if (iterator != self->parent->composite_fields->end()) { + Py_INCREF(iterator->second); + return iterator->second->AsPyObject(); } if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { // TODO(plabatut): consider building the class on the fly! - PyObject* sub_message = cmessage::InternalGetSubMessage( + ContainerBase* sub_message = cmessage::InternalGetSubMessage( self->parent, descriptor); if (sub_message == NULL) { return NULL; } - PyDict_SetItem(self->values, key, sub_message); - return sub_message; + (*self->parent->composite_fields)[descriptor] = sub_message; + return sub_message->AsPyObject(); } if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { @@ -131,21 +184,21 @@ PyObject* subscript(ExtensionDict* self, PyObject* key) { if (message_class == NULL) { return NULL; } - PyObject* py_container = repeated_composite_container::NewContainer( + ContainerBase* py_container = repeated_composite_container::NewContainer( self->parent, descriptor, message_class); if (py_container == NULL) { return NULL; } - PyDict_SetItem(self->values, key, py_container); - return py_container; + (*self->parent->composite_fields)[descriptor] = py_container; + return py_container->AsPyObject(); } else { - PyObject* py_container = repeated_scalar_container::NewContainer( + ContainerBase* py_container = repeated_scalar_container::NewContainer( self->parent, descriptor); if (py_container == NULL) { return NULL; } - PyDict_SetItem(self->values, key, py_container); - return py_container; + (*self->parent->composite_fields)[descriptor] = py_container; + return py_container->AsPyObject(); } } PyErr_SetString(PyExc_ValueError, "control reached unexpected line"); @@ -157,24 +210,24 @@ int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value) { if (descriptor == NULL) { return -1; } - if (!CheckFieldBelongsToMessage(descriptor, self->message)) { + if (!CheckFieldBelongsToMessage(descriptor, self->parent->message)) { return -1; } + if (value == nullptr) { + return cmessage::ClearFieldByDescriptor(self->parent, descriptor); + } + if (descriptor->label() != FieldDescriptor::LABEL_OPTIONAL || descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { PyErr_SetString(PyExc_TypeError, "Extension is repeated and/or composite " "type"); return -1; } - if (self->parent) { - cmessage::AssureWritable(self->parent); - if (cmessage::InternalSetScalar(self->parent, descriptor, value) < 0) { - return -1; - } + cmessage::AssureWritable(self->parent); + if (cmessage::InternalSetScalar(self->parent, descriptor, value) < 0) { + return -1; } - // TODO(tibell): We shouldn't write scalars to the cache. - PyDict_SetItem(self->values, key, value); return 0; } @@ -187,11 +240,11 @@ PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* arg) { PyDescriptorPool* pool = cmessage::GetFactoryForMessage(self->parent)->pool; const FieldDescriptor* message_extension = - pool->pool->FindExtensionByName(string(name, name_size)); + pool->pool->FindExtensionByName(StringParam(name, name_size)); if (message_extension == NULL) { // Is is the name of a message set extension? - const Descriptor* message_descriptor = pool->pool->FindMessageTypeByName( - string(name, name_size)); + const Descriptor* message_descriptor = + pool->pool->FindMessageTypeByName(StringParam(name, name_size)); if (message_descriptor && message_descriptor->extension_count() > 0) { const FieldDescriptor* extension = message_descriptor->extension(0); if (extension->is_extension() && @@ -225,6 +278,35 @@ PyObject* _FindExtensionByNumber(ExtensionDict* self, PyObject* arg) { return PyFieldDescriptor_FromDescriptor(message_extension); } +static int Contains(PyObject* _self, PyObject* key) { + ExtensionDict* self = reinterpret_cast(_self); + const FieldDescriptor* field_descriptor = + cmessage::GetExtensionDescriptor(key); + if (field_descriptor == nullptr) { + return -1; + } + + if (!field_descriptor->is_extension()) { + PyErr_Format(PyExc_KeyError, "%s is not an extension", + field_descriptor->full_name().c_str()); + return -1; + } + + const Message* message = self->parent->message; + const Reflection* reflection = message->GetReflection(); + if (field_descriptor->is_repeated()) { + if (reflection->FieldSize(*message, field_descriptor) > 0) { + return 1; + } + } else { + if (reflection->HasField(*message, field_descriptor)) { + return 1; + } + } + + return 0; +} + ExtensionDict* NewExtensionDict(CMessage *parent) { ExtensionDict* self = reinterpret_cast( PyType_GenericAlloc(&ExtensionDict_Type, 0)); @@ -232,75 +314,165 @@ ExtensionDict* NewExtensionDict(CMessage *parent) { return NULL; } - self->parent = parent; // Store a borrowed reference. - self->message = parent->message; - self->owner = parent->owner; - self->values = PyDict_New(); + Py_INCREF(parent); + self->parent = parent; return self; } -void dealloc(ExtensionDict* self) { - Py_CLEAR(self->values); - self->owner.reset(); +void dealloc(PyObject* pself) { + ExtensionDict* self = reinterpret_cast(pself); + Py_CLEAR(self->parent); Py_TYPE(self)->tp_free(reinterpret_cast(self)); } +static PyObject* RichCompare(ExtensionDict* self, PyObject* other, int opid) { + // Only equality comparisons are implemented. + if (opid != Py_EQ && opid != Py_NE) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + bool equals = false; + if (PyObject_TypeCheck(other, &ExtensionDict_Type)) { + equals = self->parent == reinterpret_cast(other)->parent;; + } + if (equals ^ (opid == Py_EQ)) { + Py_RETURN_FALSE; + } else { + Py_RETURN_TRUE; + } +} +static PySequenceMethods SeqMethods = { + (lenfunc)len, // sq_length + 0, // sq_concat + 0, // sq_repeat + 0, // sq_item + 0, // sq_slice + 0, // sq_ass_item + 0, // sq_ass_slice + (objobjproc)Contains, // sq_contains +}; + static PyMappingMethods MpMethods = { - (lenfunc)len, /* mp_length */ - (binaryfunc)subscript, /* mp_subscript */ + (lenfunc)len, /* mp_length */ + (binaryfunc)subscript, /* mp_subscript */ (objobjargproc)ass_subscript,/* mp_ass_subscript */ }; #define EDMETHOD(name, args, doc) { #name, (PyCFunction)name, args, doc } static PyMethodDef Methods[] = { - EDMETHOD(_FindExtensionByName, METH_O, - "Finds an extension by name."), - EDMETHOD(_FindExtensionByNumber, METH_O, - "Finds an extension by field number."), - { NULL, NULL } + EDMETHOD(_FindExtensionByName, METH_O, "Finds an extension by name."), + EDMETHOD(_FindExtensionByNumber, METH_O, + "Finds an extension by field number."), + {NULL, NULL}, }; } // namespace extension_dict PyTypeObject ExtensionDict_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - FULL_MODULE_NAME ".ExtensionDict", // tp_name - sizeof(ExtensionDict), // tp_basicsize - 0, // tp_itemsize - (destructor)extension_dict::dealloc, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - 0, // tp_repr - 0, // tp_as_number - 0, // tp_as_sequence - &extension_dict::MpMethods, // tp_as_mapping - PyObject_HashNotImplemented, // tp_hash - 0, // tp_call - 0, // tp_str - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "An extension dict", // tp_doc - 0, // tp_traverse - 0, // tp_clear - 0, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - extension_dict::Methods, // tp_methods - 0, // tp_members - 0, // tp_getset - 0, // tp_base - 0, // tp_dict - 0, // tp_descr_get - 0, // tp_descr_set - 0, // tp_dictoffset - 0, // tp_init + PyVarObject_HEAD_INIT(&PyType_Type, 0) // + FULL_MODULE_NAME ".ExtensionDict", // tp_name + sizeof(ExtensionDict), // tp_basicsize + 0, // tp_itemsize + (destructor)extension_dict::dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + &extension_dict::SeqMethods, // tp_as_sequence + &extension_dict::MpMethods, // tp_as_mapping + PyObject_HashNotImplemented, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "An extension dict", // tp_doc + 0, // tp_traverse + 0, // tp_clear + (richcmpfunc)extension_dict::RichCompare, // tp_richcompare + 0, // tp_weaklistoffset + extension_dict::GetIter, // tp_iter + 0, // tp_iternext + extension_dict::Methods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init }; +PyObject* IterNext(PyObject* _self) { + extension_dict::ExtensionIterator* self = + reinterpret_cast(_self); + Py_ssize_t total_size = self->fields.size(); + Py_ssize_t index = self->index; + while (self->index < total_size) { + index = self->index; + ++self->index; + if (self->fields[index]->is_extension()) { + // With C++ descriptors, the field can always be retrieved, but for + // unknown extensions which have not been imported in Python code, there + // is no message class and we cannot retrieve the value. + // ListFields() has the same behavior. + if (self->fields[index]->message_type() != nullptr && + message_factory::GetMessageClass( + cmessage::GetFactoryForMessage(self->extension_dict->parent), + self->fields[index]->message_type()) == nullptr) { + PyErr_Clear(); + continue; + } + + return PyFieldDescriptor_FromDescriptor(self->fields[index]); + } + } + + return nullptr; +} + +PyTypeObject ExtensionIterator_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) // + FULL_MODULE_NAME ".ExtensionIterator", // tp_name + sizeof(extension_dict::ExtensionIterator), // tp_basicsize + 0, // tp_itemsize + extension_dict::DeallocExtensionIterator, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "A scalar map iterator", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + PyObject_SelfIter, // tp_iter + IterNext, // tp_iternext + 0, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init +}; } // namespace python } // namespace protobuf } // namespace google diff --git a/python/google/protobuf/pyext/extension_dict.h b/python/google/protobuf/pyext/extension_dict.h index 65b878625a3cd..c9da4431613ac 100644 --- a/python/google/protobuf/pyext/extension_dict.h +++ b/python/google/protobuf/pyext/extension_dict.h @@ -37,9 +37,8 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif + +#include namespace google { namespace protobuf { @@ -47,39 +46,17 @@ namespace protobuf { class Message; class FieldDescriptor; -#ifdef _SHARED_PTR_H -using std::shared_ptr; -#else -using internal::shared_ptr; -#endif - namespace python { -struct CMessage; - typedef struct ExtensionDict { PyObject_HEAD; - // This is the top-level C++ Message object that owns the whole - // proto tree. Every Python container class holds a - // reference to it in order to keep it alive as long as there's a - // Python object that references any part of the tree. - shared_ptr owner; - - // Weak reference to parent message. Used to make sure - // the parent is writable when an extension field is modified. + // Strong, owned reference to the parent message. Never NULL. CMessage* parent; - - // Pointer to the C++ Message that this ExtensionDict extends. - // Not owned by us. - Message* message; - - // A dict of child messages, indexed by Extension descriptors. - // Similar to CMessage::composite_fields. - PyObject* values; } ExtensionDict; extern PyTypeObject ExtensionDict_Type; +extern PyTypeObject ExtensionIterator_Type; namespace extension_dict { @@ -89,6 +66,6 @@ ExtensionDict* NewExtensionDict(CMessage *parent); } // namespace extension_dict } // namespace python } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_PYTHON_CPP_EXTENSION_DICT_H__ diff --git a/python/google/protobuf/pyext/field.cc b/python/google/protobuf/pyext/field.cc new file mode 100644 index 0000000000000..1afd4583b3052 --- /dev/null +++ b/python/google/protobuf/pyext/field.cc @@ -0,0 +1,142 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include +#include +#include + +#if PY_MAJOR_VERSION >= 3 + #define PyString_FromFormat PyUnicode_FromFormat +#endif + +namespace google { +namespace protobuf { +namespace python { + +namespace field { + +static PyObject* Repr(PyMessageFieldProperty* self) { + return PyString_FromFormat("", + self->field_descriptor->full_name().c_str()); +} + +static PyObject* DescrGet(PyMessageFieldProperty* self, PyObject* obj, + PyObject* type) { + if (obj == NULL) { + Py_INCREF(self); + return reinterpret_cast(self); + } + return cmessage::GetFieldValue(reinterpret_cast(obj), + self->field_descriptor); +} + +static int DescrSet(PyMessageFieldProperty* self, PyObject* obj, + PyObject* value) { + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, "Cannot delete field attribute"); + return -1; + } + return cmessage::SetFieldValue(reinterpret_cast(obj), + self->field_descriptor, value); +} + +static PyObject* GetDescriptor(PyMessageFieldProperty* self, void* closure) { + return PyFieldDescriptor_FromDescriptor(self->field_descriptor); +} + +static PyObject* GetDoc(PyMessageFieldProperty* self, void* closure) { + return PyString_FromFormat("Field %s", + self->field_descriptor->full_name().c_str()); +} + +static PyGetSetDef Getters[] = { + {"DESCRIPTOR", (getter)GetDescriptor, NULL, "Field descriptor"}, + {"__doc__", (getter)GetDoc, NULL, NULL}, + {NULL}}; +} // namespace field + +static PyTypeObject _CFieldProperty_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) // head + FULL_MODULE_NAME ".FieldProperty", // tp_name + sizeof(PyMessageFieldProperty), // tp_basicsize + 0, // tp_itemsize + 0, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + (reprfunc)field::Repr, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "Field property of a Message", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + field::Getters, // tp_getset + 0, // tp_base + 0, // tp_dict + (descrgetfunc)field::DescrGet, // tp_descr_get + (descrsetfunc)field::DescrSet, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + 0, // tp_new +}; +PyTypeObject* CFieldProperty_Type = &_CFieldProperty_Type; + +PyObject* NewFieldProperty(const FieldDescriptor* field_descriptor) { + // Create a new descriptor object + PyMessageFieldProperty* property = + PyObject_New(PyMessageFieldProperty, CFieldProperty_Type); + if (property == NULL) { + return NULL; + } + property->field_descriptor = field_descriptor; + return reinterpret_cast(property); +} + +} // namespace python +} // namespace protobuf +} // namespace google diff --git a/python/google/protobuf/pyext/field.h b/python/google/protobuf/pyext/field.h new file mode 100644 index 0000000000000..7b4660cab50eb --- /dev/null +++ b/python/google/protobuf/pyext/field.h @@ -0,0 +1,59 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_FIELD_H__ +#define GOOGLE_PROTOBUF_PYTHON_CPP_FIELD_H__ + +#include + +namespace google { +namespace protobuf { + +class FieldDescriptor; + +namespace python { + +// A data descriptor that represents a field in a Message class. +struct PyMessageFieldProperty { + PyObject_HEAD; + + // This pointer is owned by the same pool as the Message class it belongs to. + const FieldDescriptor* field_descriptor; +}; + +extern PyTypeObject* CFieldProperty_Type; + +PyObject* NewFieldProperty(const FieldDescriptor* field_descriptor); + +} // namespace python +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_PYTHON_CPP_FIELD_H__ diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc index 43be0701bb856..a0ee16fe86346 100644 --- a/python/google/protobuf/pyext/map_container.cc +++ b/python/google/protobuf/pyext/map_container.cc @@ -33,9 +33,6 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include @@ -46,6 +43,7 @@ #include #include #include +#include #if PY_MAJOR_VERSION >= 3 #define PyInt_FromLong PyLong_FromLong @@ -65,55 +63,52 @@ class MapReflectionFriend { static Py_ssize_t Length(PyObject* _self); static PyObject* GetIterator(PyObject *_self); static PyObject* IterNext(PyObject* _self); + static PyObject* MergeFrom(PyObject* _self, PyObject* arg); // Methods that differ between the map types. static PyObject* ScalarMapGetItem(PyObject* _self, PyObject* key); static PyObject* MessageMapGetItem(PyObject* _self, PyObject* key); static int ScalarMapSetItem(PyObject* _self, PyObject* key, PyObject* v); static int MessageMapSetItem(PyObject* _self, PyObject* key, PyObject* v); + static PyObject* ScalarMapToStr(PyObject* _self); + static PyObject* MessageMapToStr(PyObject* _self); }; struct MapIterator { PyObject_HEAD; - google::protobuf::scoped_ptr< ::google::protobuf::MapIterator> iter; + std::unique_ptr<::google::protobuf::MapIterator> iter; // A pointer back to the container, so we can notice changes to the version. // We own a ref on this. MapContainer* container; - // We need to keep a ref on the Message* too, because + // We need to keep a ref on the parent Message too, because // MapIterator::~MapIterator() accesses it. Normally this would be ok because // the ref on container (above) would guarantee outlive semantics. However in - // the case of ClearField(), InitializeAndCopyToParentContainer() resets the - // message pointer (and the owner) to a different message, a copy of the - // original. But our iterator still points to the original, which could now - // get deleted before us. + // the case of ClearField(), the MapContainer points to a different message, + // a copy of the original. But our iterator still points to the original, + // which could now get deleted before us. // // To prevent this, we ensure that the Message will always stay alive as long // as this iterator does. This is solely for the benefit of the MapIterator // destructor -- we should never actually access the iterator in this state // except to delete it. - shared_ptr owner; - + CMessage* parent; // The version of the map when we took the iterator to it. // // We store this so that if the map is modified during iteration we can throw // an error. uint64 version; - - // True if the container is empty. We signal this separately to avoid calling - // any of the iteration methods, which are non-const. - bool empty; }; Message* MapContainer::GetMutableMessage() { cmessage::AssureWritable(parent); - return const_cast(message); + return parent->message; } // Consumes a reference on the Python string object. -static bool PyStringToSTL(PyObject* py_string, string* stl_string) { +static bool PyStringToSTL(PyObject* py_string, std::string* stl_string) { char *value; Py_ssize_t value_len; @@ -130,9 +125,9 @@ static bool PyStringToSTL(PyObject* py_string, string* stl_string) { } } -static bool PythonToMapKey(PyObject* obj, - const FieldDescriptor* field_descriptor, - MapKey* key) { +static bool PythonToMapKey(MapContainer* self, PyObject* obj, MapKey* key) { + const FieldDescriptor* field_descriptor = + self->parent_field_descriptor->message_type()->map_key(); switch (field_descriptor->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: { GOOGLE_CHECK_GET_INT32(obj, value, false); @@ -160,7 +155,7 @@ static bool PythonToMapKey(PyObject* obj, break; } case FieldDescriptor::CPPTYPE_STRING: { - string str; + std::string str; if (!PyStringToSTL(CheckString(obj, field_descriptor), &str)) { return false; } @@ -176,8 +171,9 @@ static bool PythonToMapKey(PyObject* obj, return true; } -static PyObject* MapKeyToPython(const FieldDescriptor* field_descriptor, - const MapKey& key) { +static PyObject* MapKeyToPython(MapContainer* self, const MapKey& key) { + const FieldDescriptor* field_descriptor = + self->parent_field_descriptor->message_type()->map_key(); switch (field_descriptor->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: return PyInt_FromLong(key.GetInt32Value()); @@ -201,27 +197,28 @@ static PyObject* MapKeyToPython(const FieldDescriptor* field_descriptor, // This is only used for ScalarMap, so we don't need to handle the // CPPTYPE_MESSAGE case. -PyObject* MapValueRefToPython(const FieldDescriptor* field_descriptor, - MapValueRef* value) { +PyObject* MapValueRefToPython(MapContainer* self, const MapValueRef& value) { + const FieldDescriptor* field_descriptor = + self->parent_field_descriptor->message_type()->map_value(); switch (field_descriptor->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: - return PyInt_FromLong(value->GetInt32Value()); + return PyInt_FromLong(value.GetInt32Value()); case FieldDescriptor::CPPTYPE_INT64: - return PyLong_FromLongLong(value->GetInt64Value()); + return PyLong_FromLongLong(value.GetInt64Value()); case FieldDescriptor::CPPTYPE_UINT32: - return PyInt_FromSize_t(value->GetUInt32Value()); + return PyInt_FromSize_t(value.GetUInt32Value()); case FieldDescriptor::CPPTYPE_UINT64: - return PyLong_FromUnsignedLongLong(value->GetUInt64Value()); + return PyLong_FromUnsignedLongLong(value.GetUInt64Value()); case FieldDescriptor::CPPTYPE_FLOAT: - return PyFloat_FromDouble(value->GetFloatValue()); + return PyFloat_FromDouble(value.GetFloatValue()); case FieldDescriptor::CPPTYPE_DOUBLE: - return PyFloat_FromDouble(value->GetDoubleValue()); + return PyFloat_FromDouble(value.GetDoubleValue()); case FieldDescriptor::CPPTYPE_BOOL: - return PyBool_FromLong(value->GetBoolValue()); + return PyBool_FromLong(value.GetBoolValue()); case FieldDescriptor::CPPTYPE_STRING: - return ToStringObject(field_descriptor, value->GetStringValue()); + return ToStringObject(field_descriptor, value.GetStringValue()); case FieldDescriptor::CPPTYPE_ENUM: - return PyInt_FromLong(value->GetEnumValue()); + return PyInt_FromLong(value.GetEnumValue()); default: PyErr_Format( PyExc_SystemError, "Couldn't convert type %d to value", @@ -232,10 +229,11 @@ PyObject* MapValueRefToPython(const FieldDescriptor* field_descriptor, // This is only used for ScalarMap, so we don't need to handle the // CPPTYPE_MESSAGE case. -static bool PythonToMapValueRef(PyObject* obj, - const FieldDescriptor* field_descriptor, +static bool PythonToMapValueRef(MapContainer* self, PyObject* obj, bool allow_unknown_enum_values, MapValueRef* value_ref) { + const FieldDescriptor* field_descriptor = + self->parent_field_descriptor->message_type()->map_value(); switch (field_descriptor->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: { GOOGLE_CHECK_GET_INT32(obj, value, false); @@ -273,7 +271,7 @@ static bool PythonToMapValueRef(PyObject* obj, return true;; } case FieldDescriptor::CPPTYPE_STRING: { - string str; + std::string str; if (!PyStringToSTL(CheckString(obj, field_descriptor), &str)) { return false; } @@ -315,7 +313,7 @@ static MapContainer* GetMap(PyObject* obj) { Py_ssize_t MapReflectionFriend::Length(PyObject* _self) { MapContainer* self = GetMap(_self); - const google::protobuf::Message* message = self->message; + const google::protobuf::Message* message = self->parent->message; return message->GetReflection()->MapSize(*message, self->parent_field_descriptor); } @@ -339,14 +337,35 @@ PyObject* GetEntryClass(PyObject* _self) { return reinterpret_cast(message_class); } +PyObject* MapReflectionFriend::MergeFrom(PyObject* _self, PyObject* arg) { + MapContainer* self = GetMap(_self); + if (!PyObject_TypeCheck(arg, ScalarMapContainer_Type) && + !PyObject_TypeCheck(arg, MessageMapContainer_Type)) { + PyErr_SetString(PyExc_AttributeError, "Not a map field"); + return nullptr; + } + MapContainer* other_map = GetMap(arg); + Message* message = self->GetMutableMessage(); + const Message* other_message = other_map->parent->message; + const Reflection* reflection = message->GetReflection(); + const Reflection* other_reflection = other_message->GetReflection(); + internal::MapFieldBase* field = reflection->MutableMapData( + message, self->parent_field_descriptor); + const internal::MapFieldBase* other_field = other_reflection->GetMapData( + *other_message, other_map->parent_field_descriptor); + field->MergeFrom(*other_field); + self->version++; + Py_RETURN_NONE; +} + PyObject* MapReflectionFriend::Contains(PyObject* _self, PyObject* key) { MapContainer* self = GetMap(_self); - const Message* message = self->message; + const Message* message = self->parent->message; const Reflection* reflection = message->GetReflection(); MapKey map_key; - if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) { + if (!PythonToMapKey(self, key, &map_key)) { return NULL; } @@ -358,85 +377,29 @@ PyObject* MapReflectionFriend::Contains(PyObject* _self, PyObject* key) { } } -// Initializes the underlying Message object of "to" so it becomes a new parent -// map container, and copies all the values from "from" to it. A child map -// container can be released by passing it as both from and to (e.g. making it -// the recipient of the new parent message and copying the values from itself). -// In fact, this is the only supported use at the moment. -static int InitializeAndCopyToParentContainer(MapContainer* from, - MapContainer* to) { - // For now we require from == to, re-evaluate if we want to support deep copy - // as in repeated_scalar_container.cc. - GOOGLE_DCHECK(from == to); - Message* new_message = from->message->New(); - - if (MapReflectionFriend::Length(reinterpret_cast(from)) > 0) { - // A somewhat roundabout way of copying just one field from old_message to - // new_message. This is the best we can do with what Reflection gives us. - Message* mutable_old = from->GetMutableMessage(); - std::vector fields; - fields.push_back(from->parent_field_descriptor); - - // Move the map field into the new message. - mutable_old->GetReflection()->SwapFields(mutable_old, new_message, fields); - - // If/when we support from != to, this will be required also to copy the - // map field back into the existing message: - // mutable_old->MergeFrom(*new_message); - } - - // If from == to this could delete old_message. - to->owner.reset(new_message); - - to->parent = NULL; - to->parent_field_descriptor = from->parent_field_descriptor; - to->message = new_message; - - // Invalidate iterators, since they point to the old copy of the field. - to->version++; - - return 0; -} - -int MapContainer::Release() { - return InitializeAndCopyToParentContainer(this, this); -} - - // ScalarMap /////////////////////////////////////////////////////////////////// -PyObject *NewScalarMapContainer( +MapContainer* NewScalarMapContainer( CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor) { if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) { return NULL; } - ScopedPyObjectPtr obj(PyType_GenericAlloc(ScalarMapContainer_Type, 0)); - if (obj.get() == NULL) { - return PyErr_Format(PyExc_RuntimeError, - "Could not allocate new container."); + PyObject* obj(PyType_GenericAlloc(ScalarMapContainer_Type, 0)); + if (obj == NULL) { + PyErr_Format(PyExc_RuntimeError, + "Could not allocate new container."); + return NULL; } - MapContainer* self = GetMap(obj.get()); + MapContainer* self = GetMap(obj); - self->message = parent->message; + Py_INCREF(parent); self->parent = parent; self->parent_field_descriptor = parent_field_descriptor; - self->owner = parent->owner; self->version = 0; - self->key_field_descriptor = - parent_field_descriptor->message_type()->FindFieldByName("key"); - self->value_field_descriptor = - parent_field_descriptor->message_type()->FindFieldByName("value"); - - if (self->key_field_descriptor == NULL || - self->value_field_descriptor == NULL) { - return PyErr_Format(PyExc_KeyError, - "Map entry descriptor did not have key/value fields"); - } - - return obj.release(); + return self; } PyObject* MapReflectionFriend::ScalarMapGetItem(PyObject* _self, @@ -448,7 +411,7 @@ PyObject* MapReflectionFriend::ScalarMapGetItem(PyObject* _self, MapKey map_key; MapValueRef value; - if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) { + if (!PythonToMapKey(self, key, &map_key)) { return NULL; } @@ -457,7 +420,7 @@ PyObject* MapReflectionFriend::ScalarMapGetItem(PyObject* _self, self->version++; } - return MapValueRefToPython(self->value_field_descriptor, &value); + return MapValueRefToPython(self, value); } int MapReflectionFriend::ScalarMapSetItem(PyObject* _self, PyObject* key, @@ -469,7 +432,7 @@ int MapReflectionFriend::ScalarMapSetItem(PyObject* _self, PyObject* key, MapKey map_key; MapValueRef value; - if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) { + if (!PythonToMapKey(self, key, &map_key)) { return -1; } @@ -480,10 +443,11 @@ int MapReflectionFriend::ScalarMapSetItem(PyObject* _self, PyObject* key, reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor, map_key, &value); - return PythonToMapValueRef(v, self->value_field_descriptor, - reflection->SupportsUnknownEnumValues(), &value) - ? 0 - : -1; + if (!PythonToMapValueRef(self, v, reflection->SupportsUnknownEnumValues(), + &value)) { + return -1; + } + return 0; } else { // Delete key from map. if (reflection->DeleteMapValue(message, self->parent_field_descriptor, @@ -496,10 +460,13 @@ int MapReflectionFriend::ScalarMapSetItem(PyObject* _self, PyObject* key, } } -static PyObject* ScalarMapGet(PyObject* self, PyObject* args) { +static PyObject* ScalarMapGet(PyObject* self, PyObject* args, + PyObject* kwargs) { + static char* kwlist[] = {"key", "default", nullptr}; PyObject* key; PyObject* default_value = NULL; - if (PyArg_ParseTuple(args, "O|O", &key, &default_value) < 0) { + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist, &key, + &default_value)) { return NULL; } @@ -520,28 +487,65 @@ static PyObject* ScalarMapGet(PyObject* self, PyObject* args) { } } +PyObject* MapReflectionFriend::ScalarMapToStr(PyObject* _self) { + ScopedPyObjectPtr dict(PyDict_New()); + if (dict == NULL) { + return NULL; + } + ScopedPyObjectPtr key; + ScopedPyObjectPtr value; + + MapContainer* self = GetMap(_self); + Message* message = self->GetMutableMessage(); + const Reflection* reflection = message->GetReflection(); + for (google::protobuf::MapIterator it = reflection->MapBegin( + message, self->parent_field_descriptor); + it != reflection->MapEnd(message, self->parent_field_descriptor); + ++it) { + key.reset(MapKeyToPython(self, it.GetKey())); + if (key == NULL) { + return NULL; + } + value.reset(MapValueRefToPython(self, it.GetValueRef())); + if (value == NULL) { + return NULL; + } + if (PyDict_SetItem(dict.get(), key.get(), value.get()) < 0) { + return NULL; + } + } + return PyObject_Repr(dict.get()); +} + static void ScalarMapDealloc(PyObject* _self) { MapContainer* self = GetMap(_self); - self->owner.reset(); - Py_TYPE(_self)->tp_free(_self); + self->RemoveFromParentCache(); + PyTypeObject *type = Py_TYPE(_self); + type->tp_free(_self); + if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { + // With Python3, the Map class is not static, and must be managed. + Py_DECREF(type); + } } static PyMethodDef ScalarMapMethods[] = { - { "__contains__", MapReflectionFriend::Contains, METH_O, - "Tests whether a key is a member of the map." }, - { "clear", (PyCFunction)Clear, METH_NOARGS, - "Removes all elements from the map." }, - { "get", ScalarMapGet, METH_VARARGS, - "Gets the value for the given key if present, or otherwise a default" }, - { "GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS, - "Return the class used to build Entries of (key, value) pairs." }, - /* - { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, - "Makes a deep copy of the class." }, - { "__reduce__", (PyCFunction)Reduce, METH_NOARGS, - "Outputs picklable representation of the repeated field." }, - */ - {NULL, NULL}, + {"__contains__", MapReflectionFriend::Contains, METH_O, + "Tests whether a key is a member of the map."}, + {"clear", (PyCFunction)Clear, METH_NOARGS, + "Removes all elements from the map."}, + {"get", (PyCFunction)ScalarMapGet, METH_VARARGS | METH_KEYWORDS, + "Gets the value for the given key if present, or otherwise a default"}, + {"GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS, + "Return the class used to build Entries of (key, value) pairs."}, + {"MergeFrom", (PyCFunction)MapReflectionFriend::MergeFrom, METH_O, + "Merges a map into the current map."}, + /* + { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, + "Makes a deep copy of the class." }, + { "__reduce__", (PyCFunction)Reduce, METH_NOARGS, + "Outputs picklable representation of the repeated field." }, + */ + {NULL, NULL}, }; PyTypeObject *ScalarMapContainer_Type; @@ -553,6 +557,7 @@ PyTypeObject *ScalarMapContainer_Type; {Py_mp_ass_subscript, (void *)MapReflectionFriend::ScalarMapSetItem}, {Py_tp_methods, (void *)ScalarMapMethods}, {Py_tp_iter, (void *)MapReflectionFriend::GetIterator}, + {Py_tp_repr, (void *)MapReflectionFriend::ScalarMapToStr}, {0, 0}, }; @@ -580,7 +585,7 @@ PyTypeObject *ScalarMapContainer_Type; 0, // tp_getattr 0, // tp_setattr 0, // tp_compare - 0, // tp_repr + MapReflectionFriend::ScalarMapToStr, // tp_repr 0, // tp_as_number 0, // tp_as_sequence &ScalarMapMappingMethods, // tp_as_mapping @@ -619,32 +624,13 @@ static MessageMapContainer* GetMessageMap(PyObject* obj) { static PyObject* GetCMessage(MessageMapContainer* self, Message* message) { // Get or create the CMessage object corresponding to this message. - ScopedPyObjectPtr key(PyLong_FromVoidPtr(message)); - PyObject* ret = PyDict_GetItem(self->message_dict, key.get()); - - if (ret == NULL) { - CMessage* cmsg = cmessage::NewEmptyMessage(self->message_class); - ret = reinterpret_cast(cmsg); - - if (cmsg == NULL) { - return NULL; - } - cmsg->owner = self->owner; - cmsg->message = message; - cmsg->parent = self->parent; - - if (PyDict_SetItem(self->message_dict, key.get(), ret) < 0) { - Py_DECREF(ret); - return NULL; - } - } else { - Py_INCREF(ret); - } - - return ret; + return self->parent + ->BuildSubMessageFromPointer(self->parent_field_descriptor, message, + self->message_class) + ->AsPyObject(); } -PyObject* NewMessageMapContainer( +MessageMapContainer* NewMessageMapContainer( CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor, CMessageClass* message_class) { if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) { @@ -653,40 +639,21 @@ PyObject* NewMessageMapContainer( PyObject* obj = PyType_GenericAlloc(MessageMapContainer_Type, 0); if (obj == NULL) { - return PyErr_Format(PyExc_RuntimeError, - "Could not allocate new container."); + PyErr_SetString(PyExc_RuntimeError, "Could not allocate new container."); + return NULL; } MessageMapContainer* self = GetMessageMap(obj); - self->message = parent->message; + Py_INCREF(parent); self->parent = parent; self->parent_field_descriptor = parent_field_descriptor; - self->owner = parent->owner; self->version = 0; - self->key_field_descriptor = - parent_field_descriptor->message_type()->FindFieldByName("key"); - self->value_field_descriptor = - parent_field_descriptor->message_type()->FindFieldByName("value"); - - self->message_dict = PyDict_New(); - if (self->message_dict == NULL) { - return PyErr_Format(PyExc_RuntimeError, - "Could not allocate message dict."); - } - Py_INCREF(message_class); self->message_class = message_class; - if (self->key_field_descriptor == NULL || - self->value_field_descriptor == NULL) { - Py_DECREF(obj); - return PyErr_Format(PyExc_KeyError, - "Map entry descriptor did not have key/value fields"); - } - - return obj; + return self; } int MapReflectionFriend::MessageMapSetItem(PyObject* _self, PyObject* key, @@ -707,7 +674,7 @@ int MapReflectionFriend::MessageMapSetItem(PyObject* _self, PyObject* key, self->version++; - if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) { + if (!PythonToMapKey(self, key, &map_key)) { return -1; } @@ -718,19 +685,14 @@ int MapReflectionFriend::MessageMapSetItem(PyObject* _self, PyObject* key, MapValueRef value; reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor, map_key, &value); - ScopedPyObjectPtr key(PyLong_FromVoidPtr(value.MutableMessageValue())); - - // PyDict_DelItem will have key error if the key is not in the map. We do - // not want to call PyErr_Clear() which may clear other errors. Thus - // PyDict_Contains() check is called before delete. - int contains = PyDict_Contains(self->message_dict, key.get()); - if (contains < 0) { - return -1; - } - if (contains) { - if (PyDict_DelItem(self->message_dict, key.get()) < 0) { - return -1; - } + Message* sub_message = value.MutableMessageValue(); + // If there is a living weak reference to an item, we "Release" it, + // otherwise we just discard the C++ value. + if (CMessage* released = + self->parent->MaybeReleaseSubMessage(sub_message)) { + Message* msg = released->message; + released->message = msg->New(); + msg->GetReflection()->Swap(msg, released->message); } // Delete key from map. @@ -752,7 +714,7 @@ PyObject* MapReflectionFriend::MessageMapGetItem(PyObject* _self, MapKey map_key; MapValueRef value; - if (!PythonToMapKey(key, self->key_field_descriptor, &map_key)) { + if (!PythonToMapKey(self, key, &map_key)) { return NULL; } @@ -764,10 +726,42 @@ PyObject* MapReflectionFriend::MessageMapGetItem(PyObject* _self, return GetCMessage(self, value.MutableMessageValue()); } -PyObject* MessageMapGet(PyObject* self, PyObject* args) { +PyObject* MapReflectionFriend::MessageMapToStr(PyObject* _self) { + ScopedPyObjectPtr dict(PyDict_New()); + if (dict == NULL) { + return NULL; + } + ScopedPyObjectPtr key; + ScopedPyObjectPtr value; + + MessageMapContainer* self = GetMessageMap(_self); + Message* message = self->GetMutableMessage(); + const Reflection* reflection = message->GetReflection(); + for (google::protobuf::MapIterator it = reflection->MapBegin( + message, self->parent_field_descriptor); + it != reflection->MapEnd(message, self->parent_field_descriptor); + ++it) { + key.reset(MapKeyToPython(self, it.GetKey())); + if (key == NULL) { + return NULL; + } + value.reset(GetCMessage(self, it.MutableValueRef()->MutableMessageValue())); + if (value == NULL) { + return NULL; + } + if (PyDict_SetItem(dict.get(), key.get(), value.get()) < 0) { + return NULL; + } + } + return PyObject_Repr(dict.get()); +} + +PyObject* MessageMapGet(PyObject* self, PyObject* args, PyObject* kwargs) { + static char* kwlist[] = {"key", "default", nullptr}; PyObject* key; PyObject* default_value = NULL; - if (PyArg_ParseTuple(args, "O|O", &key, &default_value) < 0) { + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist, &key, + &default_value)) { return NULL; } @@ -790,30 +784,36 @@ PyObject* MessageMapGet(PyObject* self, PyObject* args) { static void MessageMapDealloc(PyObject* _self) { MessageMapContainer* self = GetMessageMap(_self); - self->owner.reset(); - Py_DECREF(self->message_dict); + self->RemoveFromParentCache(); Py_DECREF(self->message_class); - Py_TYPE(_self)->tp_free(_self); + PyTypeObject *type = Py_TYPE(_self); + type->tp_free(_self); + if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { + // With Python3, the Map class is not static, and must be managed. + Py_DECREF(type); + } } static PyMethodDef MessageMapMethods[] = { - { "__contains__", (PyCFunction)MapReflectionFriend::Contains, METH_O, - "Tests whether the map contains this element."}, - { "clear", (PyCFunction)Clear, METH_NOARGS, - "Removes all elements from the map."}, - { "get", MessageMapGet, METH_VARARGS, - "Gets the value for the given key if present, or otherwise a default" }, - { "get_or_create", MapReflectionFriend::MessageMapGetItem, METH_O, - "Alias for getitem, useful to make explicit that the map is mutated." }, - { "GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS, - "Return the class used to build Entries of (key, value) pairs." }, - /* - { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, - "Makes a deep copy of the class." }, - { "__reduce__", (PyCFunction)Reduce, METH_NOARGS, - "Outputs picklable representation of the repeated field." }, - */ - {NULL, NULL}, + {"__contains__", (PyCFunction)MapReflectionFriend::Contains, METH_O, + "Tests whether the map contains this element."}, + {"clear", (PyCFunction)Clear, METH_NOARGS, + "Removes all elements from the map."}, + {"get", (PyCFunction)MessageMapGet, METH_VARARGS | METH_KEYWORDS, + "Gets the value for the given key if present, or otherwise a default"}, + {"get_or_create", MapReflectionFriend::MessageMapGetItem, METH_O, + "Alias for getitem, useful to make explicit that the map is mutated."}, + {"GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS, + "Return the class used to build Entries of (key, value) pairs."}, + {"MergeFrom", (PyCFunction)MapReflectionFriend::MergeFrom, METH_O, + "Merges a map into the current map."}, + /* + { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, + "Makes a deep copy of the class." }, + { "__reduce__", (PyCFunction)Reduce, METH_NOARGS, + "Outputs picklable representation of the repeated field." }, + */ + {NULL, NULL}, }; PyTypeObject *MessageMapContainer_Type; @@ -825,6 +825,7 @@ PyTypeObject *MessageMapContainer_Type; {Py_mp_ass_subscript, (void *)MapReflectionFriend::MessageMapSetItem}, {Py_tp_methods, (void *)MessageMapMethods}, {Py_tp_iter, (void *)MapReflectionFriend::GetIterator}, + {Py_tp_repr, (void *)MapReflectionFriend::MessageMapToStr}, {0, 0} }; @@ -852,7 +853,7 @@ PyTypeObject *MessageMapContainer_Type; 0, // tp_getattr 0, // tp_setattr 0, // tp_compare - 0, // tp_repr + MapReflectionFriend::MessageMapToStr, // tp_repr 0, // tp_as_number 0, // tp_as_sequence &MessageMapMappingMethods, // tp_as_mapping @@ -901,7 +902,8 @@ PyObject* MapReflectionFriend::GetIterator(PyObject *_self) { Py_INCREF(self); iter->container = self; iter->version = self->version; - iter->owner = self->owner; + Py_INCREF(self->parent); + iter->parent = self->parent; if (MapReflectionFriend::Length(_self) > 0) { Message* message = self->GetMutableMessage(); @@ -923,6 +925,10 @@ PyObject* MapReflectionFriend::IterNext(PyObject* _self) { return PyErr_Format(PyExc_RuntimeError, "Map modified during iteration."); } + if (self->parent != self->container->parent) { + return PyErr_Format(PyExc_RuntimeError, + "Map cleared during iteration."); + } if (self->iter.get() == NULL) { return NULL; @@ -936,8 +942,7 @@ PyObject* MapReflectionFriend::IterNext(PyObject* _self) { return NULL; } - PyObject* ret = MapKeyToPython(self->container->key_field_descriptor, - self->iter->GetKey()); + PyObject* ret = MapKeyToPython(self->container, self->iter->GetKey()); ++(*self->iter); @@ -947,8 +952,8 @@ PyObject* MapReflectionFriend::IterNext(PyObject* _self) { static void DeallocMapIterator(PyObject* _self) { MapIterator* self = GetIter(_self); self->iter.reset(); - self->owner.reset(); - Py_XDECREF(self->container); + Py_CLEAR(self->container); + Py_CLEAR(self->parent); Py_TYPE(_self)->tp_free(_self); } @@ -1005,17 +1010,15 @@ bool InitMapContainers() { return false; } - if (!PyObject_TypeCheck(mutable_mapping.get(), &PyType_Type)) { - return false; - } - Py_INCREF(mutable_mapping.get()); #if PY_MAJOR_VERSION >= 3 - PyObject* bases = PyTuple_New(1); - PyTuple_SET_ITEM(bases, 0, mutable_mapping.get()); + ScopedPyObjectPtr bases(PyTuple_Pack(1, mutable_mapping.get())); + if (bases == NULL) { + return false; + } ScalarMapContainer_Type = reinterpret_cast( - PyType_FromSpecWithBases(&ScalarMapContainer_Type_spec, bases)); + PyType_FromSpecWithBases(&ScalarMapContainer_Type_spec, bases.get())); #else _ScalarMapContainer_Type.tp_base = reinterpret_cast(mutable_mapping.get()); @@ -1033,7 +1036,7 @@ bool InitMapContainers() { #if PY_MAJOR_VERSION >= 3 MessageMapContainer_Type = reinterpret_cast( - PyType_FromSpecWithBases(&MessageMapContainer_Type_spec, bases)); + PyType_FromSpecWithBases(&MessageMapContainer_Type_spec, bases.get())); #else Py_INCREF(mutable_mapping.get()); _MessageMapContainer_Type.tp_base = diff --git a/python/google/protobuf/pyext/map_container.h b/python/google/protobuf/pyext/map_container.h index 615657b03b8df..a28945da07b20 100644 --- a/python/google/protobuf/pyext/map_container.h +++ b/python/google/protobuf/pyext/map_container.h @@ -34,82 +34,34 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include +#include namespace google { namespace protobuf { class Message; -#ifdef _SHARED_PTR_H -using std::shared_ptr; -#else -using internal::shared_ptr; -#endif - namespace python { -struct CMessage; struct CMessageClass; // This struct is used directly for ScalarMap, and is the base class of // MessageMapContainer, which is used for MessageMap. -struct MapContainer { - PyObject_HEAD; - - // This is the top-level C++ Message object that owns the whole - // proto tree. Every Python MapContainer holds a - // reference to it in order to keep it alive as long as there's a - // Python object that references any part of the tree. - shared_ptr owner; - - // Pointer to the C++ Message that contains this container. The - // MapContainer does not own this pointer. - const Message* message; - +struct MapContainer : public ContainerBase { // Use to get a mutable message when necessary. Message* GetMutableMessage(); - // Weak reference to a parent CMessage object (i.e. may be NULL.) - // - // Used to make sure all ancestors are also mutable when first - // modifying the container. - CMessage* parent; - - // Pointer to the parent's descriptor that describes this - // field. Used together with the parent's message when making a - // default message instance mutable. - // The pointer is owned by the global DescriptorPool. - const FieldDescriptor* parent_field_descriptor; - const FieldDescriptor* key_field_descriptor; - const FieldDescriptor* value_field_descriptor; - // We bump this whenever we perform a mutation, to invalidate existing // iterators. uint64 version; - - // Releases the messages in the container to a new message. - // - // Returns 0 on success, -1 on failure. - int Release(); - - // Set the owner field of self and any children of self. - void SetOwner(const shared_ptr& new_owner) { - owner = new_owner; - } }; struct MessageMapContainer : public MapContainer { // The type used to create new child messages. CMessageClass* message_class; - - // A dict mapping Message* -> CMessage. - PyObject* message_dict; }; bool InitMapContainers(); @@ -120,17 +72,17 @@ extern PyTypeObject MapIterator_Type; // Both map types use the same iterator. // Builds a MapContainer object, from a parent message and a // field descriptor. -extern PyObject* NewScalarMapContainer( +extern MapContainer* NewScalarMapContainer( CMessage* parent, const FieldDescriptor* parent_field_descriptor); // Builds a MessageMap object, from a parent message and a // field descriptor. -extern PyObject* NewMessageMapContainer( +extern MessageMapContainer* NewMessageMapContainer( CMessage* parent, const FieldDescriptor* parent_field_descriptor, CMessageClass* message_class); } // namespace python } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_PYTHON_CPP_MAP_CONTAINER_H__ diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc index 702c5d03d8e54..4e74386e2d1bc 100644 --- a/python/google/protobuf/pyext/message.cc +++ b/python/google/protobuf/pyext/message.cc @@ -33,14 +33,14 @@ #include +#include // A Python header file. + #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include -#include // A Python header file. + +#include #ifndef PyVarObject_HEAD_INIT #define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, @@ -48,12 +48,11 @@ #ifndef Py_TYPE #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) #endif -#include #include #include #include #include -#include +#include #include #include #include @@ -61,13 +60,21 @@ #include #include #include -#include -#include +#include #include #include +#include +#include #include #include -#include +#include +#include +#include +#include + +// clang-format off +#include +// clang-format on #if PY_MAJOR_VERSION >= 3 #define PyInt_AsLong PyLong_AsLong @@ -76,16 +83,19 @@ #define PyString_Check PyUnicode_Check #define PyString_FromString PyUnicode_FromString #define PyString_FromStringAndSize PyUnicode_FromStringAndSize + #define PyString_FromFormat PyUnicode_FromFormat #if PY_VERSION_HEX < 0x03030000 #error "Python 3.0 - 3.2 are not supported." #else #define PyString_AsString(ob) \ (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob)) - #define PyString_AsStringAndSize(ob, charpp, sizep) \ - (PyUnicode_Check(ob)? \ - ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \ - PyBytes_AsStringAndSize(ob, (charpp), (sizep))) - #endif +#define PyString_AsStringAndSize(ob, charpp, sizep) \ + (PyUnicode_Check(ob) ? ((*(charpp) = const_cast( \ + PyUnicode_AsUTF8AndSize(ob, (sizep)))) == NULL \ + ? -1 \ + : 0) \ + : PyBytes_AsStringAndSize(ob, (charpp), (sizep))) +#endif #endif namespace google { @@ -102,34 +112,28 @@ namespace message_meta { static int InsertEmptyWeakref(PyTypeObject* base); -// Add the number of a field descriptor to the containing message class. -// Equivalent to: -// _cls._FIELD_NUMBER = -static bool AddFieldNumberToClass( - PyObject* cls, const FieldDescriptor* field_descriptor) { - string constant_name = field_descriptor->name() + "_FIELD_NUMBER"; - UpperString(&constant_name); - ScopedPyObjectPtr attr_name(PyString_FromStringAndSize( - constant_name.c_str(), constant_name.size())); - if (attr_name == NULL) { - return false; - } - ScopedPyObjectPtr number(PyInt_FromLong(field_descriptor->number())); - if (number == NULL) { - return false; +namespace { +// Copied over from internal 'google/protobuf/stubs/strutil.h'. +inline void LowerString(std::string* s) { + std::string::iterator end = s->end(); + for (std::string::iterator i = s->begin(); i != end; ++i) { + // tolower() changes based on locale. We don't want this! + if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A'; } - if (PyObject_SetAttr(cls, attr_name.get(), number.get()) == -1) { - return false; - } - return true; } - +} // namespace // Finalize the creation of the Message class. static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) { // For each field set: cls._FIELD_NUMBER = for (int i = 0; i < descriptor->field_count(); ++i) { - if (!AddFieldNumberToClass(cls, descriptor->field(i))) { + const FieldDescriptor* field_descriptor = descriptor->field(i); + ScopedPyObjectPtr property(NewFieldProperty(field_descriptor)); + if (property == NULL) { + return -1; + } + if (PyObject_SetAttrString(cls, field_descriptor->name().c_str(), + property.get()) < 0) { return -1; } } @@ -141,7 +145,7 @@ static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) { PyEnumDescriptor_FromDescriptor(enum_descriptor)); if (enum_type == NULL) { return -1; - } + } // Add wrapped enum type to message class. ScopedPyObjectPtr wrapped(PyObject_CallFunctionObjArgs( EnumTypeWrapper_class, enum_type.get(), NULL)); @@ -186,18 +190,12 @@ static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) { cls, field->name().c_str(), extension_field.get()) == -1) { return -1; } - - // For each extension set cls._FIELD_NUMBER = . - if (!AddFieldNumberToClass(cls, field)) { - return -1; - } } return 0; } -static PyObject* New(PyTypeObject* type, - PyObject* args, PyObject* kwargs) { +static PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) { static char *kwlist[] = {"name", "bases", "dict", 0}; PyObject *bases, *dict; const char* name; @@ -221,14 +219,19 @@ static PyObject* New(PyTypeObject* type, // Check dict['DESCRIPTOR'] PyObject* py_descriptor = PyDict_GetItem(dict, kDESCRIPTOR); - if (py_descriptor == NULL) { + if (py_descriptor == nullptr) { PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR"); - return NULL; + return nullptr; } if (!PyObject_TypeCheck(py_descriptor, &PyMessageDescriptor_Type)) { PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s", py_descriptor->ob_type->tp_name); - return NULL; + return nullptr; + } + const Descriptor* message_descriptor = + PyMessageDescriptor_AsDescriptor(py_descriptor); + if (message_descriptor == nullptr) { + return nullptr; } // Messages have no __dict__ @@ -240,11 +243,6 @@ static PyObject* New(PyTypeObject* type, // Build the arguments to the base metaclass. // We change the __bases__ classes. ScopedPyObjectPtr new_args; - const Descriptor* message_descriptor = - PyMessageDescriptor_AsDescriptor(py_descriptor); - if (message_descriptor == NULL) { - return NULL; - } if (WKT_classes == NULL) { ScopedPyObjectPtr well_known_types(PyImport_ImportModule( @@ -258,10 +256,10 @@ static PyObject* New(PyTypeObject* type, PyObject* well_known_class = PyDict_GetItemString( WKT_classes, message_descriptor->full_name().c_str()); if (well_known_class == NULL) { - new_args.reset(Py_BuildValue("s(OO)O", name, &CMessage_Type, + new_args.reset(Py_BuildValue("s(OO)O", name, CMessage_Type, PythonMessage_class, dict)); } else { - new_args.reset(Py_BuildValue("s(OOO)O", name, &CMessage_Type, + new_args.reset(Py_BuildValue("s(OOO)O", name, CMessage_Type, PythonMessage_class, well_known_class, dict)); } @@ -278,7 +276,7 @@ static PyObject* New(PyTypeObject* type, // Insert the empty weakref into the base classes. if (InsertEmptyWeakref( reinterpret_cast(PythonMessage_class)) < 0 || - InsertEmptyWeakref(&CMessage_Type) < 0) { + InsertEmptyWeakref(CMessage_Type) < 0) { return NULL; } @@ -316,12 +314,25 @@ static PyObject* New(PyTypeObject* type, return result.release(); } -static void Dealloc(CMessageClass *self) { +static void Dealloc(PyObject* pself) { + CMessageClass* self = reinterpret_cast(pself); Py_XDECREF(self->py_message_descriptor); Py_XDECREF(self->py_message_factory); - Py_TYPE(self)->tp_free(reinterpret_cast(self)); + return PyType_Type.tp_dealloc(pself); +} + +static int GcTraverse(PyObject* pself, visitproc visit, void* arg) { + CMessageClass* self = reinterpret_cast(pself); + Py_VISIT(self->py_message_descriptor); + Py_VISIT(self->py_message_factory); + return PyType_Type.tp_traverse(pself, visit, arg); } +static int GcClear(PyObject* pself) { + // It's important to keep the descriptor and factory alive, until the + // C++ message is fully destructed. + return PyType_Type.tp_clear(pself); +} // This function inserts and empty weakref at the end of the list of // subclasses for the main protocol buffer Message class. @@ -334,11 +345,17 @@ static int InsertEmptyWeakref(PyTypeObject *base_type) { // hack addresses. For further background and the fix please see // https://bugs.python.org/issue17936. return 0; +#else +#ifdef Py_DEBUG + // The code below causes all new subclasses to append an entry, which is never + // cleared. This is a small memory leak, which we disable in Py_DEBUG mode + // to have stable refcounting checks. #else PyObject *subclasses = base_type->tp_subclasses; if (subclasses && PyList_CheckExact(subclasses)) { return PyList_Append(subclasses, kEmptyWeakref); } +#endif // !Py_DEBUG return 0; #endif // PY_MAJOR_VERSION >= 3 } @@ -346,6 +363,13 @@ static int InsertEmptyWeakref(PyTypeObject *base_type) { // The _extensions_by_name dictionary is built on every access. // TODO(amauryfa): Migrate all users to pool.FindAllExtensions() static PyObject* GetExtensionsByName(CMessageClass *self, void *closure) { + if (self->message_descriptor == NULL) { + // This is the base Message object, simply raise AttributeError. + PyErr_SetString(PyExc_AttributeError, + "Base Message class has no DESCRIPTOR"); + return NULL; + } + const PyDescriptorPool* pool = self->py_message_factory->pool; std::vector extensions; @@ -369,6 +393,13 @@ static PyObject* GetExtensionsByName(CMessageClass *self, void *closure) { // The _extensions_by_number dictionary is built on every access. // TODO(amauryfa): Migrate all users to pool.FindExtensionByNumber() static PyObject* GetExtensionsByNumber(CMessageClass *self, void *closure) { + if (self->message_descriptor == NULL) { + // This is the base Message object, simply raise AttributeError. + PyErr_SetString(PyExc_AttributeError, + "Base Message class has no DESCRIPTOR"); + return NULL; + } + const PyDescriptorPool* pool = self->py_message_factory->pool; std::vector extensions; @@ -398,51 +429,94 @@ static PyGetSetDef Getters[] = { {NULL} }; +// Compute some class attributes on the fly: +// - All the _FIELD_NUMBER attributes, for all fields and nested extensions. +// Returns a new reference, or NULL with an exception set. +static PyObject* GetClassAttribute(CMessageClass *self, PyObject* name) { + char* attr; + Py_ssize_t attr_size; + static const char kSuffix[] = "_FIELD_NUMBER"; + if (PyString_AsStringAndSize(name, &attr, &attr_size) >= 0 && + HasSuffixString(StringPiece(attr, attr_size), kSuffix)) { + std::string field_name(attr, attr_size - sizeof(kSuffix) + 1); + LowerString(&field_name); + + // Try to find a field with the given name, without the suffix. + const FieldDescriptor* field = + self->message_descriptor->FindFieldByLowercaseName(field_name); + if (!field) { + // Search nested extensions as well. + field = + self->message_descriptor->FindExtensionByLowercaseName(field_name); + } + if (field) { + return PyInt_FromLong(field->number()); + } + } + PyErr_SetObject(PyExc_AttributeError, name); + return NULL; +} + +static PyObject* GetAttr(CMessageClass* self, PyObject* name) { + PyObject* result = CMessageClass_Type->tp_base->tp_getattro( + reinterpret_cast(self), name); + if (result != NULL) { + return result; + } + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + return NULL; + } + + PyErr_Clear(); + return GetClassAttribute(self, name); +} + } // namespace message_meta -PyTypeObject CMessageClass_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - FULL_MODULE_NAME ".MessageMeta", // tp_name - sizeof(CMessageClass), // tp_basicsize - 0, // tp_itemsize - (destructor)message_meta::Dealloc, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - 0, // tp_repr - 0, // tp_as_number - 0, // tp_as_sequence - 0, // tp_as_mapping - 0, // tp_hash - 0, // tp_call - 0, // tp_str - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags - "The metaclass of ProtocolMessages", // tp_doc - 0, // tp_traverse - 0, // tp_clear - 0, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - 0, // tp_methods - 0, // tp_members - message_meta::Getters, // tp_getset - 0, // tp_base - 0, // tp_dict - 0, // tp_descr_get - 0, // tp_descr_set - 0, // tp_dictoffset - 0, // tp_init - 0, // tp_alloc - message_meta::New, // tp_new +static PyTypeObject _CMessageClass_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME + ".MessageMeta", // tp_name + sizeof(CMessageClass), // tp_basicsize + 0, // tp_itemsize + message_meta::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + (getattrofunc)message_meta::GetAttr, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, // tp_flags + "The metaclass of ProtocolMessages", // tp_doc + message_meta::GcTraverse, // tp_traverse + message_meta::GcClear, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + message_meta::Getters, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + message_meta::New, // tp_new }; +PyTypeObject* CMessageClass_Type = &_CMessageClass_Type; static CMessageClass* CheckMessageClass(PyTypeObject* cls) { - if (!PyObject_TypeCheck(cls, &CMessageClass_Type)) { + if (!PyObject_TypeCheck(cls, CMessageClass_Type)) { PyErr_Format(PyExc_TypeError, "Class %s is not a Message", cls->tp_name); return NULL; } @@ -461,117 +535,21 @@ static const Descriptor* GetMessageDescriptor(PyTypeObject* cls) { namespace cmessage { int InternalReleaseFieldByDescriptor( CMessage* self, - const FieldDescriptor* field_descriptor, - PyObject* composite_field); + const FieldDescriptor* field_descriptor); } // namespace cmessage -// --------------------------------------------------------------------- -// Visiting the composite children of a CMessage - -struct ChildVisitor { - // Returns 0 on success, -1 on failure. - int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { - return 0; - } - - // Returns 0 on success, -1 on failure. - int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { - return 0; - } - - // Returns 0 on success, -1 on failure. - int VisitCMessage(CMessage* cmessage, - const FieldDescriptor* field_descriptor) { - return 0; - } -}; - -// Apply a function to a composite field. Does nothing if child is of -// non-composite type. -template -static int VisitCompositeField(const FieldDescriptor* descriptor, - PyObject* child, - Visitor visitor) { - if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { - if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - if (descriptor->is_map()) { - MapContainer* container = reinterpret_cast(child); - if (visitor.VisitMapContainer(container) == -1) { - return -1; - } - } else { - RepeatedCompositeContainer* container = - reinterpret_cast(child); - if (visitor.VisitRepeatedCompositeContainer(container) == -1) - return -1; - } - } else { - RepeatedScalarContainer* container = - reinterpret_cast(child); - if (visitor.VisitRepeatedScalarContainer(container) == -1) - return -1; - } - } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - CMessage* cmsg = reinterpret_cast(child); - if (visitor.VisitCMessage(cmsg, descriptor) == -1) - return -1; - } - // The ExtensionDict might contain non-composite fields, which we - // skip here. - return 0; -} - -// Visit each composite field and extension field of this CMessage. -// Returns -1 on error and 0 on success. -template -int ForEachCompositeField(CMessage* self, Visitor visitor) { - Py_ssize_t pos = 0; - PyObject* key; - PyObject* field; - - // Visit normal fields. - if (self->composite_fields) { - // Never use self->message in this function, it may be already freed. - const Descriptor* message_descriptor = - GetMessageDescriptor(Py_TYPE(self)); - while (PyDict_Next(self->composite_fields, &pos, &key, &field)) { - Py_ssize_t key_str_size; - char *key_str_data; - if (PyString_AsStringAndSize(key, &key_str_data, &key_str_size) != 0) - return -1; - const string key_str(key_str_data, key_str_size); - const FieldDescriptor* descriptor = - message_descriptor->FindFieldByName(key_str); - if (descriptor != NULL) { - if (VisitCompositeField(descriptor, field, visitor) == -1) - return -1; - } - } - } - - // Visit extension fields. - if (self->extensions != NULL) { - pos = 0; - while (PyDict_Next(self->extensions->values, &pos, &key, &field)) { - const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key); - if (descriptor == NULL) - return -1; - if (VisitCompositeField(descriptor, field, visitor) == -1) - return -1; - } - } - - return 0; -} - // --------------------------------------------------------------------- PyObject* EncodeError_class; PyObject* DecodeError_class; PyObject* PickleError_class; -/* Is 64bit */ +// Format an error message for unexpected types. +// Always return with an exception set. void FormatTypeError(PyObject* arg, char* expected_types) { + // This function is often called with an exception set. + // Clear it to call PyObject_Repr() in good conditions. + PyErr_Clear(); PyObject* repr = PyObject_Repr(arg); if (repr) { PyErr_Format(PyExc_TypeError, @@ -595,7 +573,7 @@ void OutOfRangeError(PyObject* arg) { template bool VerifyIntegerCastAndRange(PyObject* arg, ValueType value) { - if GOOGLE_PREDICT_FALSE(value == -1 && PyErr_Occurred()) { + if (PROTOBUF_PREDICT_FALSE(value == -1 && PyErr_Occurred())) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) { // Replace it with the same ValueError as pure python protos instead of // the default one. @@ -604,21 +582,21 @@ bool VerifyIntegerCastAndRange(PyObject* arg, ValueType value) { } // Otherwise propagate existing error. return false; } - if GOOGLE_PREDICT_FALSE(!IsValidNumericCast(value)) { + if (PROTOBUF_PREDICT_FALSE(!IsValidNumericCast(value))) { OutOfRangeError(arg); return false; } return true; } -template +template bool CheckAndGetInteger(PyObject* arg, T* value) { // The fast path. #if PY_MAJOR_VERSION < 3 // For the typical case, offer a fast path. - if GOOGLE_PREDICT_TRUE(PyInt_Check(arg)) { - long int_result = PyInt_AsLong(arg); - if GOOGLE_PREDICT_TRUE(IsValidNumericCast(int_result)) { + if (PROTOBUF_PREDICT_TRUE(PyInt_Check(arg))) { + long int_result = PyInt_AsLong(arg); + if (PROTOBUF_PREDICT_TRUE(IsValidNumericCast(int_result))) { *value = static_cast(int_result); return true; } else { @@ -631,7 +609,7 @@ bool CheckAndGetInteger(PyObject* arg, T* value) { // an integer and can be used as an ordinal number". // This definition includes everything that implements numbers.Integral // and shouldn't cast the net too wide. - if GOOGLE_PREDICT_FALSE(!PyIndex_Check(arg)) { + if (PROTOBUF_PREDICT_FALSE(!PyIndex_Check(arg))) { FormatTypeError(arg, "int, long"); return false; } @@ -648,7 +626,7 @@ bool CheckAndGetInteger(PyObject* arg, T* value) { // Unlike PyLong_AsLongLong, PyLong_AsUnsignedLongLong is very // picky about the exact type. PyObject* casted = PyNumber_Long(arg); - if GOOGLE_PREDICT_FALSE(casted == NULL) { + if (PROTOBUF_PREDICT_FALSE(casted == nullptr)) { // Propagate existing error. return false; } @@ -673,7 +651,7 @@ bool CheckAndGetInteger(PyObject* arg, T* value) { // Valid subclasses of numbers.Integral should have a __long__() method // so fall back to that. PyObject* casted = PyNumber_Long(arg); - if GOOGLE_PREDICT_FALSE(casted == NULL) { + if (PROTOBUF_PREDICT_FALSE(casted == nullptr)) { // Propagate existing error. return false; } @@ -699,7 +677,7 @@ template bool CheckAndGetInteger(PyObject*, uint64*); bool CheckAndGetDouble(PyObject* arg, double* value) { *value = PyFloat_AsDouble(arg); - if GOOGLE_PREDICT_FALSE(*value == -1 && PyErr_Occurred()) { + if (PROTOBUF_PREDICT_FALSE(*value == -1 && PyErr_Occurred())) { FormatTypeError(arg, "int, long, float"); return false; } @@ -711,7 +689,7 @@ bool CheckAndGetFloat(PyObject* arg, float* value) { if (!CheckAndGetDouble(arg, &double_value)) { return false; } - *value = static_cast(double_value); + *value = io::SafeDoubleToFloat(double_value); return true; } @@ -809,18 +787,20 @@ bool CheckAndSetString( return false; } - string value_string(value, value_len); + std::string value_string(value, value_len); if (append) { - reflection->AddString(message, descriptor, value_string); + reflection->AddString(message, descriptor, std::move(value_string)); } else if (index < 0) { - reflection->SetString(message, descriptor, value_string); + reflection->SetString(message, descriptor, std::move(value_string)); } else { - reflection->SetRepeatedString(message, descriptor, index, value_string); + reflection->SetRepeatedString(message, descriptor, index, + std::move(value_string)); } return true; } -PyObject* ToStringObject(const FieldDescriptor* descriptor, string value) { +PyObject* ToStringObject(const FieldDescriptor* descriptor, + const std::string& value) { if (descriptor->type() != FieldDescriptor::TYPE_STRING) { return PyBytes_FromStringAndSize(value.c_str(), value.length()); } @@ -851,7 +831,7 @@ bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor, namespace cmessage { PyMessageFactory* GetFactoryForMessage(CMessage* message) { - GOOGLE_DCHECK(PyObject_TypeCheck(message, &CMessage_Type)); + GOOGLE_DCHECK(PyObject_TypeCheck(message, CMessage_Type)); return reinterpret_cast(Py_TYPE(message))->py_message_factory; } @@ -875,130 +855,84 @@ static int MaybeReleaseOverlappingOneofField( // Non-message fields don't need to be released. return 0; } - const char* field_name = existing_field->name().c_str(); - PyObject* child_message = cmessage->composite_fields ? - PyDict_GetItemString(cmessage->composite_fields, field_name) : NULL; - if (child_message == NULL) { - // No python reference to this field so no need to release. - return 0; - } - - if (InternalReleaseFieldByDescriptor( - cmessage, existing_field, child_message) < 0) { + if (InternalReleaseFieldByDescriptor(cmessage, existing_field) < 0) { return -1; } - return PyDict_DelItemString(cmessage->composite_fields, field_name); -#else - return 0; #endif + return 0; } -// --------------------------------------------------------------------- -// Making a message writable - -static Message* GetMutableMessage( - CMessage* parent, - const FieldDescriptor* parent_field) { - Message* parent_message = parent->message; - const Reflection* reflection = parent_message->GetReflection(); - if (MaybeReleaseOverlappingOneofField(parent, parent_field) < 0) { - return NULL; - } - return reflection->MutableMessage( - parent_message, parent_field, - GetFactoryForMessage(parent)->message_factory); -} - -struct FixupMessageReference : public ChildVisitor { - // message must outlive this object. - explicit FixupMessageReference(Message* message) : - message_(message) {} - - int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { - container->message = message_; +// After a Merge, visit every sub-message that was read-only, and +// eventually update their pointer if the Merge operation modified them. +int FixupMessageAfterMerge(CMessage* self) { + if (!self->composite_fields) { return 0; } - - int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { - container->message = message_; - return 0; + for (const auto& item : *self->composite_fields) { + const FieldDescriptor* descriptor = item.first; + if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !descriptor->is_repeated()) { + CMessage* cmsg = reinterpret_cast(item.second); + if (cmsg->read_only == false) { + return 0; + } + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); + if (reflection->HasField(*message, descriptor)) { + // Message used to be read_only, but is no longer. Get the new pointer + // and record it. + Message* mutable_message = + reflection->MutableMessage(message, descriptor, nullptr); + cmsg->message = mutable_message; + cmsg->read_only = false; + if (FixupMessageAfterMerge(cmsg) < 0) { + return -1; + } + } + } } - int VisitMapContainer(MapContainer* container) { - container->message = message_; - return 0; - } + return 0; +} - private: - Message* message_; -}; +// --------------------------------------------------------------------- +// Making a message writable int AssureWritable(CMessage* self) { if (self == NULL || !self->read_only) { return 0; } - if (self->parent == NULL) { - // If parent is NULL but we are trying to modify a read-only message, this - // is a reference to a constant default instance that needs to be replaced - // with a mutable top-level message. - self->message = self->message->New(); - self->owner.reset(self->message); - // Cascade the new owner to eventual children: even if this message is - // empty, some submessages or repeated containers might exist already. - SetOwner(self, self->owner); - } else { - // Otherwise, we need a mutable child message. - if (AssureWritable(self->parent) == -1) - return -1; + // Toplevel messages are always mutable. + GOOGLE_DCHECK(self->parent); - // Make self->message writable. - Message* mutable_message = GetMutableMessage( - self->parent, - self->parent_field_descriptor); - if (mutable_message == NULL) { - return -1; - } - self->message = mutable_message; + if (AssureWritable(self->parent) == -1) { + return -1; + } + // If this message is part of a oneof, there might be a field to release in + // the parent. + if (MaybeReleaseOverlappingOneofField(self->parent, + self->parent_field_descriptor) < 0) { + return -1; } - self->read_only = false; - // When a CMessage is made writable its Message pointer is updated - // to point to a new mutable Message. When that happens we need to - // update any references to the old, read-only CMessage. There are - // four places such references occur: RepeatedScalarContainer, - // RepeatedCompositeContainer, MapContainer, and ExtensionDict. - if (self->extensions != NULL) - self->extensions->message = self->message; - if (ForEachCompositeField(self, FixupMessageReference(self->message)) == -1) + // Make self->message writable. + Message* parent_message = self->parent->message; + const Reflection* reflection = parent_message->GetReflection(); + Message* mutable_message = reflection->MutableMessage( + parent_message, self->parent_field_descriptor, + GetFactoryForMessage(self->parent)->message_factory); + if (mutable_message == NULL) { return -1; + } + self->message = mutable_message; + self->read_only = false; return 0; } // --- Globals: -// Retrieve a C++ FieldDescriptor for a message attribute. -// The C++ message must be valid. -// TODO(amauryfa): This function should stay internal, because exception -// handling is not consistent. -static const FieldDescriptor* GetFieldDescriptor( - CMessage* self, PyObject* name) { - const Descriptor *message_descriptor = self->message->GetDescriptor(); - char* field_name; - Py_ssize_t size; - if (PyString_AsStringAndSize(name, &field_name, &size) < 0) { - return NULL; - } - const FieldDescriptor *field_descriptor = - message_descriptor->FindFieldByName(string(field_name, size)); - if (field_descriptor == NULL) { - // Note: No exception is set! - return NULL; - } - return field_descriptor; -} - // Retrieve a C++ FieldDescriptor for an extension handle. const FieldDescriptor* GetExtensionDescriptor(PyObject* extension) { ScopedPyObjectPtr cdescriptor; @@ -1028,9 +962,9 @@ static PyObject* GetIntegerEnumValue(const FieldDescriptor& descriptor, return NULL; } const EnumValueDescriptor* enum_value_descriptor = - enum_descriptor->FindValueByName(string(enum_label, size)); + enum_descriptor->FindValueByName(StringParam(enum_label, size)); if (enum_value_descriptor == NULL) { - PyErr_SetString(PyExc_ValueError, "unknown enum label"); + PyErr_Format(PyExc_ValueError, "unknown enum label \"%s\"", enum_label); return NULL; } return PyInt_FromLong(enum_value_descriptor->number()); @@ -1039,17 +973,16 @@ static PyObject* GetIntegerEnumValue(const FieldDescriptor& descriptor, return value; } -// If cmessage_list is not NULL, this function releases values into the -// container CMessages instead of just removing. Repeated composite container -// needs to do this to make sure CMessages stay alive if they're still -// referenced after deletion. Repeated scalar container doesn't need to worry. -int InternalDeleteRepeatedField( +// Delete a slice from a repeated field. +// The only way to remove items in C++ protos is to delete the last one, +// so we swap items to move the deleted ones at the end, and then strip the +// sequence. +int DeleteRepeatedField( CMessage* self, const FieldDescriptor* field_descriptor, - PyObject* slice, - PyObject* cmessage_list) { - Message* message = self->message; + PyObject* slice) { Py_ssize_t length, from, to, step, slice_length; + Message* message = self->message; const Reflection* reflection = message->GetReflection(); int min, max; length = reflection->FieldSize(*message, field_descriptor); @@ -1099,39 +1032,34 @@ int InternalDeleteRepeatedField( i += step; } + // Swap elements so that items to delete are at the end. to = 0; for (i = 0; i < length; ++i) { if (!to_delete[i]) { if (i != to) { reflection->SwapElements(message, field_descriptor, i, to); - if (cmessage_list != NULL) { - // If a list of cmessages is passed in (i.e. from a repeated - // composite container), swap those as well to correspond to the - // swaps in the underlying message so they're in the right order - // when we start releasing. - PyObject* tmp = PyList_GET_ITEM(cmessage_list, i); - PyList_SET_ITEM(cmessage_list, i, - PyList_GET_ITEM(cmessage_list, to)); - PyList_SET_ITEM(cmessage_list, to, tmp); - } } ++to; } } - while (i > to) { - if (cmessage_list == NULL) { + // Remove items, starting from the end. + for (; length > to; length--) { + if (field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { reflection->RemoveLast(message, field_descriptor); + continue; + } + // It seems that RemoveLast() is less efficient for sub-messages, and + // the memory is not completely released. Prefer ReleaseLast(). + Message* sub_message = reflection->ReleaseLast(message, field_descriptor); + // If there is a live weak reference to an item being removed, we "Release" + // it, and it takes ownership of the message. + if (CMessage* released = self->MaybeReleaseSubMessage(sub_message)) { + released->message = sub_message; } else { - CMessage* last_cmessage = reinterpret_cast( - PyList_GET_ITEM(cmessage_list, PyList_GET_SIZE(cmessage_list) - 1)); - repeated_composite_container::ReleaseLastTo( - self, field_descriptor, last_cmessage); - if (PySequence_DelItem(cmessage_list, -1) < 0) { - return -1; - } + // sub_message was not transferred, delete it. + delete sub_message; } - --i; } return 0; @@ -1152,37 +1080,45 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { PyObject* name; PyObject* value; while (PyDict_Next(kwargs, &pos, &name, &value)) { - if (!PyString_Check(name)) { + if (!(PyString_Check(name) || PyUnicode_Check(name))) { PyErr_SetString(PyExc_ValueError, "Field name must be a string"); return -1; } - const FieldDescriptor* descriptor = GetFieldDescriptor(self, name); - if (descriptor == NULL) { + ScopedPyObjectPtr property( + PyObject_GetAttr(reinterpret_cast(Py_TYPE(self)), name)); + if (property == NULL || + !PyObject_TypeCheck(property.get(), CFieldProperty_Type)) { PyErr_Format(PyExc_ValueError, "Protocol message %s has no \"%s\" field.", self->message->GetDescriptor()->name().c_str(), PyString_AsString(name)); return -1; } + const FieldDescriptor* descriptor = + reinterpret_cast(property.get()) + ->field_descriptor; if (value == Py_None) { // field=None is the same as no field at all. continue; } if (descriptor->is_map()) { - ScopedPyObjectPtr map(GetAttr(self, name)); + ScopedPyObjectPtr map(GetFieldValue(self, descriptor)); const FieldDescriptor* value_descriptor = descriptor->message_type()->FindFieldByName("value"); if (value_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - Py_ssize_t map_pos = 0; - PyObject* map_key; - PyObject* map_value; - while (PyDict_Next(value, &map_pos, &map_key, &map_value)) { - ScopedPyObjectPtr function_return; - function_return.reset(PyObject_GetItem(map.get(), map_key)); - if (function_return.get() == NULL) { + ScopedPyObjectPtr iter(PyObject_GetIter(value)); + if (iter == NULL) { + PyErr_Format(PyExc_TypeError, "Argument %s is not iterable", PyString_AsString(name)); + return -1; + } + ScopedPyObjectPtr next; + while ((next.reset(PyIter_Next(iter.get()))) != NULL) { + ScopedPyObjectPtr source_value(PyObject_GetItem(value, next.get())); + ScopedPyObjectPtr dest_value(PyObject_GetItem(map.get(), next.get())); + if (source_value.get() == NULL || dest_value.get() == NULL) { return -1; } ScopedPyObjectPtr ok(PyObject_CallMethod( - function_return.get(), "MergeFrom", "O", map_value)); + dest_value.get(), "MergeFrom", "O", source_value.get())); if (ok.get() == NULL) { return -1; } @@ -1196,7 +1132,7 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { } } } else if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { - ScopedPyObjectPtr container(GetAttr(self, name)); + ScopedPyObjectPtr container(GetFieldValue(self, descriptor)); if (container == NULL) { return -1; } @@ -1263,7 +1199,7 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { } } } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - ScopedPyObjectPtr message(GetAttr(self, name)); + ScopedPyObjectPtr message(GetFieldValue(self, descriptor)); if (message == NULL) { return -1; } @@ -1287,9 +1223,9 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { if (new_val == NULL) { return -1; } + value = new_val.get(); } - if (SetAttr(self, name, (new_val.get() == NULL) ? value : new_val.get()) < - 0) { + if (SetFieldValue(self, descriptor, value) < 0) { return -1; } } @@ -1297,8 +1233,8 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { return 0; } -// Allocates an incomplete Python Message: the caller must fill self->message, -// self->owner and eventually self->parent. +// Allocates an incomplete Python Message: the caller must fill self->message +// and eventually self->parent. CMessage* NewEmptyMessage(CMessageClass* type) { CMessage* self = reinterpret_cast( PyType_GenericAlloc(&type->super.ht_type, 0)); @@ -1310,40 +1246,52 @@ CMessage* NewEmptyMessage(CMessageClass* type) { self->parent = NULL; self->parent_field_descriptor = NULL; self->read_only = false; - self->extensions = NULL; self->composite_fields = NULL; + self->child_submessages = NULL; + + self->unknown_field_set = NULL; return self; } // The __new__ method of Message classes. // Creates a new C++ message and takes ownership. -static PyObject* New(PyTypeObject* cls, - PyObject* unused_args, PyObject* unused_kwargs) { - CMessageClass* type = CheckMessageClass(cls); - if (type == NULL) { - return NULL; - } +static CMessage* NewCMessage(CMessageClass* type) { // Retrieve the message descriptor and the default instance (=prototype). const Descriptor* message_descriptor = type->message_descriptor; - if (message_descriptor == NULL) { - return NULL; - } - const Message* default_message = type->py_message_factory->message_factory - ->GetPrototype(message_descriptor); - if (default_message == NULL) { + if (message_descriptor == nullptr) { + // This would be very unexpected since the CMessageClass has already + // been checked. + PyErr_Format(PyExc_TypeError, + "CMessageClass object '%s' has no descriptor.", + Py_TYPE(type)->tp_name); + return nullptr; + } + const Message* prototype = + type->py_message_factory->message_factory->GetPrototype( + message_descriptor); + if (prototype == nullptr) { PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str()); - return NULL; + return nullptr; } CMessage* self = NewEmptyMessage(type); - if (self == NULL) { - return NULL; + if (self == nullptr) { + return nullptr; } - self->message = default_message->New(); - self->owner.reset(self->message); - return reinterpret_cast(self); + self->message = prototype->New(); + self->parent = nullptr; // This message owns its data. + return self; +} + +static PyObject* New(PyTypeObject* cls, PyObject* unused_args, + PyObject* unused_kwargs) { + CMessageClass* type = CheckMessageClass(cls); + if (type == nullptr) { + return nullptr; + } + return reinterpret_cast(NewCMessage(type)); } // The __init__ method of Message classes. @@ -1354,55 +1302,39 @@ static int Init(CMessage* self, PyObject* args, PyObject* kwargs) { // --------------------------------------------------------------------- // Deallocating a CMessage -// -// Deallocating a CMessage requires that we clear any weak references -// from children to the message being deallocated. - -// Clear the weak reference from the child to the parent. -struct ClearWeakReferences : public ChildVisitor { - int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { - container->parent = NULL; - // The elements in the container have the same parent as the - // container itself, so NULL out that pointer as well. - const Py_ssize_t n = PyList_GET_SIZE(container->child_messages); - for (Py_ssize_t i = 0; i < n; ++i) { - CMessage* child_cmessage = reinterpret_cast( - PyList_GET_ITEM(container->child_messages, i)); - child_cmessage->parent = NULL; - } - return 0; - } - - int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { - container->parent = NULL; - return 0; - } - - int VisitMapContainer(MapContainer* container) { - container->parent = NULL; - return 0; - } - - int VisitCMessage(CMessage* cmessage, - const FieldDescriptor* field_descriptor) { - cmessage->parent = NULL; - return 0; - } -}; static void Dealloc(CMessage* self) { if (self->weakreflist) { PyObject_ClearWeakRefs(reinterpret_cast(self)); } - // Null out all weak references from children to this message. - GOOGLE_CHECK_EQ(0, ForEachCompositeField(self, ClearWeakReferences())); - if (self->extensions) { - self->extensions->parent = NULL; + // At this point all dependent objects have been removed. + GOOGLE_DCHECK(!self->child_submessages || self->child_submessages->empty()); + GOOGLE_DCHECK(!self->composite_fields || self->composite_fields->empty()); + delete self->child_submessages; + delete self->composite_fields; + if (self->unknown_field_set) { + unknown_fields::Clear( + reinterpret_cast(self->unknown_field_set)); + } + + CMessage* parent = self->parent; + if (!parent) { + // No parent, we own the message. + delete self->message; + } else if (parent->AsPyObject() == Py_None) { + // Message owned externally: Nothing to dealloc + Py_CLEAR(self->parent); + } else { + // Clear this message from its parent's map. + if (self->parent_field_descriptor->is_repeated()) { + if (parent->child_submessages) + parent->child_submessages->erase(self->message); + } else { + if (parent->composite_fields) + parent->composite_fields->erase(self->parent_field_descriptor); + } + Py_CLEAR(self->parent); } - - Py_CLEAR(self->extensions); - Py_CLEAR(self->composite_fields); - self->owner.reset(); Py_TYPE(self)->tp_free(reinterpret_cast(self)); } @@ -1411,7 +1343,7 @@ static void Dealloc(CMessage* self) { PyObject* IsInitialized(CMessage* self, PyObject* args) { PyObject* errors = NULL; - if (PyArg_ParseTuple(args, "|O", &errors) < 0) { + if (!PyArg_ParseTuple(args, "|O", &errors)) { return NULL; } if (self->message->IsInitialized()) { @@ -1439,24 +1371,23 @@ PyObject* IsInitialized(CMessage* self, PyObject* args) { Py_RETURN_FALSE; } -PyObject* HasFieldByDescriptor( - CMessage* self, const FieldDescriptor* field_descriptor) { +int HasFieldByDescriptor(CMessage* self, + const FieldDescriptor* field_descriptor) { Message* message = self->message; if (!CheckFieldBelongsToMessage(field_descriptor, message)) { - return NULL; + return -1; } if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { PyErr_SetString(PyExc_KeyError, "Field is repeated. A singular method is required."); - return NULL; + return -1; } - bool has_field = - message->GetReflection()->HasField(*message, field_descriptor); - return PyBool_FromLong(has_field ? 1 : 0); + return message->GetReflection()->HasField(*message, field_descriptor); } -const FieldDescriptor* FindFieldWithOneofs( - const Message* message, const string& field_name, bool* in_oneof) { +const FieldDescriptor* FindFieldWithOneofs(const Message* message, + ConstStringParam field_name, + bool* in_oneof) { *in_oneof = false; const Descriptor* descriptor = message->GetDescriptor(); const FieldDescriptor* field_descriptor = @@ -1475,35 +1406,20 @@ const FieldDescriptor* FindFieldWithOneofs( } bool CheckHasPresence(const FieldDescriptor* field_descriptor, bool in_oneof) { + auto message_name = field_descriptor->containing_type()->name(); if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { PyErr_Format(PyExc_ValueError, - "Protocol message has no singular \"%s\" field.", - field_descriptor->name().c_str()); + "Protocol message %s has no singular \"%s\" field.", + message_name.c_str(), field_descriptor->name().c_str()); return false; } - if (field_descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { - // HasField() for a oneof *itself* isn't supported. - if (in_oneof) { - PyErr_Format(PyExc_ValueError, - "Can't test oneof field \"%s\" for presence in proto3, use " - "WhichOneof instead.", - field_descriptor->containing_oneof()->name().c_str()); - return false; - } - - // ...but HasField() for fields *in* a oneof is supported. - if (field_descriptor->containing_oneof() != NULL) { - return true; - } - - if (field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { - PyErr_Format( - PyExc_ValueError, - "Can't test non-submessage field \"%s\" for presence in proto3.", - field_descriptor->name().c_str()); - return false; - } + if (!field_descriptor->has_presence()) { + PyErr_Format(PyExc_ValueError, + "Can't test non-optional, non-submessage field \"%s.%s\" for " + "presence in proto3.", + message_name.c_str(), field_descriptor->name().c_str()); + return false; } return true; @@ -1517,7 +1433,7 @@ PyObject* HasField(CMessage* self, PyObject* arg) { return NULL; } #else - field_name = PyUnicode_AsUTF8AndSize(arg, &size); + field_name = const_cast(PyUnicode_AsUTF8AndSize(arg, &size)); if (!field_name) { return NULL; } @@ -1526,10 +1442,11 @@ PyObject* HasField(CMessage* self, PyObject* arg) { Message* message = self->message; bool is_in_oneof; const FieldDescriptor* field_descriptor = - FindFieldWithOneofs(message, string(field_name, size), &is_in_oneof); + FindFieldWithOneofs(message, StringParam(field_name, size), &is_in_oneof); if (field_descriptor == NULL) { if (!is_in_oneof) { - PyErr_Format(PyExc_ValueError, "Unknown field %s.", field_name); + PyErr_Format(PyExc_ValueError, "Protocol message %s has no field %s.", + message->GetDescriptor()->name().c_str(), field_name); return NULL; } else { Py_RETURN_FALSE; @@ -1543,20 +1460,7 @@ PyObject* HasField(CMessage* self, PyObject* arg) { if (message->GetReflection()->HasField(*message, field_descriptor)) { Py_RETURN_TRUE; } - if (!message->GetReflection()->SupportsUnknownEnumValues() && - field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { - // Special case: Python HasField() differs in semantics from C++ - // slightly: we return HasField('enum_field') == true if there is - // an unknown enum value present. To implement this we have to - // look in the UnknownFieldSet. - const UnknownFieldSet& unknown_field_set = - message->GetReflection()->GetUnknownFields(*message); - for (int i = 0; i < unknown_field_set.field_count(); ++i) { - if (unknown_field_set.field(i).number() == field_descriptor->number()) { - Py_RETURN_TRUE; - } - } - } + Py_RETURN_FALSE; } @@ -1565,16 +1469,10 @@ PyObject* ClearExtension(CMessage* self, PyObject* extension) { if (descriptor == NULL) { return NULL; } - if (self->extensions != NULL) { - PyObject* value = PyDict_GetItem(self->extensions->values, extension); - if (value != NULL) { - if (InternalReleaseFieldByDescriptor(self, descriptor, value) < 0) { - return NULL; - } - PyDict_DelItem(self->extensions->values, extension); - } + if (ClearFieldByDescriptor(self, descriptor) < 0) { + return nullptr; } - return ClearFieldByDescriptor(self, descriptor); + Py_RETURN_NONE; } PyObject* HasExtension(CMessage* self, PyObject* extension) { @@ -1582,7 +1480,12 @@ PyObject* HasExtension(CMessage* self, PyObject* extension) { if (descriptor == NULL) { return NULL; } - return HasFieldByDescriptor(self, descriptor); + int has_field = HasFieldByDescriptor(self, descriptor); + if (has_field < 0) { + return nullptr; + } else { + return PyBool_FromLong(has_field); + } } // --------------------------------------------------------------------- @@ -1590,212 +1493,173 @@ PyObject* HasExtension(CMessage* self, PyObject* extension) { // // The Python API's ClearField() and Clear() methods behave // differently than their C++ counterparts. While the C++ versions -// clears the children the Python versions detaches the children, +// clears the children, the Python versions detaches the children, // without touching their content. This impedance mismatch causes // some complexity in the implementation, which is captured in this // section. // -// When a CMessage field is cleared we need to: -// -// * Release the Message used as the backing store for the CMessage -// from its parent. +// When one or multiple fields are cleared we need to: // -// * Change the owner field of the released CMessage and all of its -// children to point to the newly released Message. +// * Gather all child objects that need to be detached from the message. +// In composite_fields and child_submessages. // -// * Clear the weak references from the released CMessage to the -// parent. +// * Create a new Python message of the same kind. Use SwapFields() to move +// data from the original message. // -// When a RepeatedCompositeContainer field is cleared we need to: -// -// * Release all the Message used as the backing store for the -// CMessages stored in the container. -// -// * Change the owner field of all the released CMessage and all of -// their children to point to the newly released Messages. -// -// * Clear the weak references from the released container to the -// parent. +// * Change the parent of all child objects: update their strong reference +// to their parent, and move their presence in composite_fields and +// child_submessages. -struct SetOwnerVisitor : public ChildVisitor { - // new_owner must outlive this object. - explicit SetOwnerVisitor(const shared_ptr& new_owner) - : new_owner_(new_owner) {} +// --------------------------------------------------------------------- +// Release a composite child of a CMessage - int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { - repeated_composite_container::SetOwner(container, new_owner_); +static int InternalReparentFields( + CMessage* self, const std::vector& messages_to_release, + const std::vector& containers_to_release) { + if (messages_to_release.empty() && containers_to_release.empty()) { return 0; } - int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { - repeated_scalar_container::SetOwner(container, new_owner_); - return 0; + // Move all the passed sub_messages to another message. + CMessage* new_message = cmessage::NewEmptyMessage(self->GetMessageClass()); + if (new_message == nullptr) { + return -1; } + new_message->message = self->message->New(); + ScopedPyObjectPtr holder(reinterpret_cast(new_message)); + new_message->child_submessages = new CMessage::SubMessagesMap(); + new_message->composite_fields = new CMessage::CompositeFieldsMap(); + std::set fields_to_swap; - int VisitMapContainer(MapContainer* container) { - container->SetOwner(new_owner_); - return 0; - } + // In case this the removed fields are the last reference to a message, keep + // a reference. + Py_INCREF(self); - int VisitCMessage(CMessage* cmessage, - const FieldDescriptor* field_descriptor) { - return SetOwner(cmessage, new_owner_); + for (const auto& to_release : messages_to_release) { + fields_to_swap.insert(to_release->parent_field_descriptor); + // Reparent + Py_INCREF(new_message); + Py_DECREF(to_release->parent); + to_release->parent = new_message; + self->child_submessages->erase(to_release->message); + new_message->child_submessages->emplace(to_release->message, to_release); } - private: - const shared_ptr& new_owner_; -}; - -// Change the owner of this CMessage and all its children, recursively. -int SetOwner(CMessage* self, const shared_ptr& new_owner) { - self->owner = new_owner; - if (ForEachCompositeField(self, SetOwnerVisitor(new_owner)) == -1) - return -1; - return 0; -} - -// Releases the message specified by 'field' and returns the -// pointer. If the field does not exist a new message is created using -// 'descriptor'. The caller takes ownership of the returned pointer. -Message* ReleaseMessage(CMessage* self, - const Descriptor* descriptor, - const FieldDescriptor* field_descriptor) { - MessageFactory* message_factory = GetFactoryForMessage(self)->message_factory; - Message* released_message = self->message->GetReflection()->ReleaseMessage( - self->message, field_descriptor, message_factory); - // ReleaseMessage will return NULL which differs from - // child_cmessage->message, if the field does not exist. In this case, - // the latter points to the default instance via a const_cast<>, so we - // have to reset it to a new mutable object since we are taking ownership. - if (released_message == NULL) { - const Message* prototype = message_factory->GetPrototype(descriptor); - GOOGLE_DCHECK(prototype != NULL); - released_message = prototype->New(); + for (const auto& to_release : containers_to_release) { + fields_to_swap.insert(to_release->parent_field_descriptor); + Py_INCREF(new_message); + Py_DECREF(to_release->parent); + to_release->parent = new_message; + self->composite_fields->erase(to_release->parent_field_descriptor); + new_message->composite_fields->emplace(to_release->parent_field_descriptor, + to_release); } - return released_message; -} - -int ReleaseSubMessage(CMessage* self, - const FieldDescriptor* field_descriptor, - CMessage* child_cmessage) { - // Release the Message - shared_ptr released_message(ReleaseMessage( - self, child_cmessage->message->GetDescriptor(), field_descriptor)); - child_cmessage->message = released_message.get(); - child_cmessage->owner.swap(released_message); - child_cmessage->parent = NULL; - child_cmessage->parent_field_descriptor = NULL; - child_cmessage->read_only = false; - return ForEachCompositeField(child_cmessage, - SetOwnerVisitor(child_cmessage->owner)); -} + self->message->GetReflection()->SwapFields( + self->message, new_message->message, + std::vector(fields_to_swap.begin(), + fields_to_swap.end())); -struct ReleaseChild : public ChildVisitor { - // message must outlive this object. - explicit ReleaseChild(CMessage* parent) : - parent_(parent) {} + // This might delete the Python message completely if all children were moved. + Py_DECREF(self); - int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { - return repeated_composite_container::Release(container); - } + return 0; +} - int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { - return repeated_scalar_container::Release(container); +int InternalReleaseFieldByDescriptor( + CMessage* self, + const FieldDescriptor* field_descriptor) { + if (!field_descriptor->is_repeated() && + field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + // Single scalars are not in any cache. + return 0; } - - int VisitMapContainer(MapContainer* container) { - return container->Release(); + std::vector messages_to_release; + std::vector containers_to_release; + if (self->child_submessages && field_descriptor->is_repeated() && + field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + for (const auto& child_item : *self->child_submessages) { + if (child_item.second->parent_field_descriptor == field_descriptor) { + messages_to_release.push_back(child_item.second); + } + } } - - int VisitCMessage(CMessage* cmessage, - const FieldDescriptor* field_descriptor) { - return ReleaseSubMessage(parent_, field_descriptor, cmessage); + if (self->composite_fields) { + CMessage::CompositeFieldsMap::iterator it = + self->composite_fields->find(field_descriptor); + if (it != self->composite_fields->end()) { + containers_to_release.push_back(it->second); + } } - CMessage* parent_; -}; - -int InternalReleaseFieldByDescriptor( - CMessage* self, - const FieldDescriptor* field_descriptor, - PyObject* composite_field) { - return VisitCompositeField( - field_descriptor, - composite_field, - ReleaseChild(self)); + return InternalReparentFields(self, messages_to_release, + containers_to_release); } -PyObject* ClearFieldByDescriptor( - CMessage* self, - const FieldDescriptor* field_descriptor) { +int ClearFieldByDescriptor(CMessage* self, + const FieldDescriptor* field_descriptor) { if (!CheckFieldBelongsToMessage(field_descriptor, self->message)) { - return NULL; + return -1; + } + if (InternalReleaseFieldByDescriptor(self, field_descriptor) < 0) { + return -1; } AssureWritable(self); Message* message = self->message; message->GetReflection()->ClearField(message, field_descriptor); - if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM && - !message->GetReflection()->SupportsUnknownEnumValues()) { - UnknownFieldSet* unknown_field_set = - message->GetReflection()->MutableUnknownFields(message); - unknown_field_set->DeleteByNumber(field_descriptor->number()); - } - Py_RETURN_NONE; + return 0; } PyObject* ClearField(CMessage* self, PyObject* arg) { - if (!PyString_Check(arg)) { - PyErr_SetString(PyExc_TypeError, "field name must be a string"); + char* field_name; + Py_ssize_t field_size; + if (PyString_AsStringAndSize(arg, &field_name, &field_size) < 0) { return NULL; } -#if PY_MAJOR_VERSION < 3 - const char* field_name = PyString_AS_STRING(arg); - Py_ssize_t size = PyString_GET_SIZE(arg); -#else - Py_ssize_t size; - const char* field_name = PyUnicode_AsUTF8AndSize(arg, &size); -#endif AssureWritable(self); - Message* message = self->message; - ScopedPyObjectPtr arg_in_oneof; bool is_in_oneof; - const FieldDescriptor* field_descriptor = - FindFieldWithOneofs(message, string(field_name, size), &is_in_oneof); + const FieldDescriptor* field_descriptor = FindFieldWithOneofs( + self->message, StringParam(field_name, field_size), &is_in_oneof); if (field_descriptor == NULL) { - if (!is_in_oneof) { + if (is_in_oneof) { + // We gave the name of a oneof, and none of its fields are set. + Py_RETURN_NONE; + } else { PyErr_Format(PyExc_ValueError, "Protocol message has no \"%s\" field.", field_name); return NULL; - } else { - Py_RETURN_NONE; } - } else if (is_in_oneof) { - const string& name = field_descriptor->name(); - arg_in_oneof.reset(PyString_FromStringAndSize(name.c_str(), name.size())); - arg = arg_in_oneof.get(); } - // Release the field if it exists in the dict of composite fields. - if (self->composite_fields) { - PyObject* value = PyDict_GetItem(self->composite_fields, arg); - if (value != NULL) { - if (InternalReleaseFieldByDescriptor(self, field_descriptor, value) < 0) { - return NULL; - } - PyDict_DelItem(self->composite_fields, arg); - } + if (ClearFieldByDescriptor(self, field_descriptor) < 0) { + return nullptr; } - return ClearFieldByDescriptor(self, field_descriptor); + Py_RETURN_NONE; } PyObject* Clear(CMessage* self) { AssureWritable(self); - if (ForEachCompositeField(self, ReleaseChild(self)) == -1) - return NULL; - Py_CLEAR(self->extensions); + // Detach all current fields of this message + std::vector messages_to_release; + std::vector containers_to_release; + if (self->child_submessages) { + for (const auto& item : *self->child_submessages) { + messages_to_release.push_back(item.second); + } + } if (self->composite_fields) { - PyDict_Clear(self->composite_fields); + for (const auto& item : *self->composite_fields) { + containers_to_release.push_back(item.second); + } + } + if (InternalReparentFields(self, messages_to_release, containers_to_release) < + 0) { + return NULL; + } + if (self->unknown_field_set) { + unknown_fields::Clear( + reinterpret_cast(self->unknown_field_set)); + self->unknown_field_set = nullptr; } self->message->Clear(); Py_RETURN_NONE; @@ -1803,7 +1667,7 @@ PyObject* Clear(CMessage* self) { // --------------------------------------------------------------------- -static string GetMessageName(CMessage* self) { +static std::string GetMessageName(CMessage* self) { if (self->parent_field_descriptor != NULL) { return self->parent_field_descriptor->full_name(); } else { @@ -1873,6 +1737,15 @@ static PyObject* InternalSerializeToString( if (size == 0) { return PyBytes_FromString(""); } + + if (size > INT_MAX) { + PyErr_Format(PyExc_ValueError, + "Message %s exceeds maximum protobuf " + "size of 2GB: %zu", + GetMessageName(self).c_str(), size); + return nullptr; + } + PyObject* result = PyBytes_FromStringAndSize(NULL, size); if (result == NULL) { return NULL; @@ -1901,7 +1774,7 @@ static PyObject* SerializePartialToString( // Formats proto fields for ascii dumps using python formatting functions where // appropriate. -class PythonFieldValuePrinter : public TextFormat::FieldValuePrinter { +class PythonFieldValuePrinter : public TextFormat::FastFieldValuePrinter { public: // Python has some differences from C++ when printing floating point numbers. // @@ -1913,8 +1786,12 @@ class PythonFieldValuePrinter : public TextFormat::FieldValuePrinter { // // We override floating point printing with the C-API function for printing // Python floats to ensure consistency. - string PrintFloat(float value) const { return PrintDouble(value); } - string PrintDouble(double value) const { + void PrintFloat(float val, + TextFormat::BaseTextGenerator* generator) const override { + PrintDouble(val, generator); + } + void PrintDouble(double val, + TextFormat::BaseTextGenerator* generator) const override { // This implementation is not highly optimized (it allocates two temporary // Python objects) but it is simple and portable. If this is shown to be a // performance bottleneck, we can optimize it, but the results will likely @@ -1923,17 +1800,17 @@ class PythonFieldValuePrinter : public TextFormat::FieldValuePrinter { // // (Though a valid question is: do we really want to make out output // dependent on the Python version?) - ScopedPyObjectPtr py_value(PyFloat_FromDouble(value)); + ScopedPyObjectPtr py_value(PyFloat_FromDouble(val)); if (!py_value.get()) { - return string(); + return; } ScopedPyObjectPtr py_str(PyObject_Str(py_value.get())); if (!py_str.get()) { - return string(); + return; } - return string(PyString_AsString(py_str.get())); + generator->PrintString(PyString_AsString(py_str.get())); } }; @@ -1942,7 +1819,7 @@ static PyObject* ToStr(CMessage* self) { // Passes ownership printer.SetDefaultFieldValuePrinter(new PythonFieldValuePrinter()); printer.SetHideUnknownFields(true); - string output; + std::string output; if (!printer.PrintToString(*self->message, &output)) { PyErr_SetString(PyExc_ValueError, "Unable to convert message to str"); return NULL; @@ -1952,7 +1829,7 @@ static PyObject* ToStr(CMessage* self) { PyObject* MergeFrom(CMessage* self, PyObject* arg) { CMessage* other_message; - if (!PyObject_TypeCheck(arg, &CMessage_Type)) { + if (!PyObject_TypeCheck(arg, CMessage_Type)) { PyErr_Format(PyExc_TypeError, "Parameter to MergeFrom() must be instance of same class: " "expected %s got %s.", @@ -1973,18 +1850,19 @@ PyObject* MergeFrom(CMessage* self, PyObject* arg) { } AssureWritable(self); - // TODO(tibell): Message::MergeFrom might turn some child Messages - // into mutable messages, invalidating the message field in the - // corresponding CMessages. We should run a FixupMessageReferences - // pass here. - self->message->MergeFrom(*other_message->message); + // Child message might be lazily created before MergeFrom. Make sure they + // are mutable at this point if child messages are really created. + if (FixupMessageAfterMerge(self) < 0) { + return NULL; + } + Py_RETURN_NONE; } static PyObject* CopyFrom(CMessage* self, PyObject* arg) { CMessage* other_message; - if (!PyObject_TypeCheck(arg, &CMessage_Type)) { + if (!PyObject_TypeCheck(arg, CMessage_Type)) { PyErr_Format(PyExc_TypeError, "Parameter to CopyFrom() must be instance of same class: " "expected %s got %s.", @@ -2056,20 +1934,43 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) { } AssureWritable(self); - io::CodedInputStream input( - reinterpret_cast(data), data_length); - if (allow_oversize_protos) { - input.SetTotalBytesLimit(INT_MAX, INT_MAX); - } + PyMessageFactory* factory = GetFactoryForMessage(self); - input.SetExtensionRegistry(factory->pool->pool, factory->message_factory); - bool success = self->message->MergePartialFromCodedStream(&input); - if (success) { - return PyInt_FromLong(input.CurrentPosition()); - } else { + int depth = allow_oversize_protos + ? INT_MAX + : io::CodedInputStream::GetDefaultRecursionLimit(); + const char* ptr; + internal::ParseContext ctx( + depth, false, &ptr, + StringPiece(static_cast(data), data_length)); + ctx.data().pool = factory->pool->pool; + ctx.data().factory = factory->message_factory; + + ptr = self->message->_InternalParse(ptr, &ctx); + + // Child message might be lazily created before MergeFrom. Make sure they + // are mutable at this point if child messages are really created. + if (FixupMessageAfterMerge(self) < 0) { + return NULL; + } + + // Python makes distinction in error message, between a general parse failure + // and in-correct ending on a terminating tag. Hence we need to be a bit more + // explicit in our correctness checks. + if (ptr == nullptr || ctx.BytesUntilLimit(ptr) < 0) { + // Parse error or the parser overshoot the limit. PyErr_Format(DecodeError_class, "Error parsing message"); return NULL; } + // ctx has an explicit limit set (length of string_view), so we have to + // check we ended at that limit. + if (!ctx.EndedAtLimit()) { + // TODO(jieluo): Raise error and return NULL instead. + // b/27494216 + PyErr_Warn(nullptr, "Unexpected end-group tag: Not all data was converted"); + return PyInt_FromLong(data_length - ctx.BytesUntilLimit(ptr)); + } + return PyInt_FromLong(data_length); } static PyObject* ParseFromString(CMessage* self, PyObject* arg) { @@ -2080,7 +1981,7 @@ static PyObject* ParseFromString(CMessage* self, PyObject* arg) { } static PyObject* ByteSize(CMessage* self, PyObject* args) { - return PyLong_FromLong(self->message->ByteSize()); + return PyLong_FromLong(self->message->ByteSizeLong()); } PyObject* RegisterExtension(PyObject* cls, PyObject* extension_handle) { @@ -2089,7 +1990,7 @@ PyObject* RegisterExtension(PyObject* cls, PyObject* extension_handle) { if (descriptor == NULL) { return NULL; } - if (!PyObject_TypeCheck(cls, &CMessageClass_Type)) { + if (!PyObject_TypeCheck(cls, CMessageClass_Type)) { PyErr_Format(PyExc_TypeError, "Expected a message class, got %s", cls->ob_type->tp_name); return NULL; @@ -2119,13 +2020,12 @@ static PyObject* WhichOneof(CMessage* self, PyObject* arg) { char *name_data; if (PyString_AsStringAndSize(arg, &name_data, &name_size) < 0) return NULL; - string oneof_name = string(name_data, name_size); const OneofDescriptor* oneof_desc = - self->message->GetDescriptor()->FindOneofByName(oneof_name); + self->message->GetDescriptor()->FindOneofByName( + StringParam(name_data, name_size)); if (oneof_desc == NULL) { PyErr_Format(PyExc_ValueError, - "Protocol message has no oneof \"%s\" field.", - oneof_name.c_str()); + "Protocol message has no oneof \"%s\" field.", name_data); return NULL; } const FieldDescriptor* field_in_oneof = @@ -2134,7 +2034,7 @@ static PyObject* WhichOneof(CMessage* self, PyObject* arg) { if (field_in_oneof == NULL) { Py_RETURN_NONE; } else { - const string& name = field_in_oneof->name(); + const std::string& name = field_in_oneof->name(); return PyString_FromStringAndSize(name.c_str(), name.size()); } } @@ -2193,22 +2093,15 @@ static PyObject* ListFields(CMessage* self) { PyTuple_SET_ITEM(t.get(), 1, extension); } else { // Normal field - const string& field_name = fields[i]->name(); - ScopedPyObjectPtr py_field_name(PyString_FromStringAndSize( - field_name.c_str(), field_name.length())); - if (py_field_name == NULL) { - PyErr_SetString(PyExc_ValueError, "bad string"); - return NULL; - } ScopedPyObjectPtr field_descriptor( PyFieldDescriptor_FromDescriptor(fields[i])); if (field_descriptor == NULL) { return NULL; } - PyObject* field_value = GetAttr(self, py_field_name.get()); + PyObject* field_value = GetFieldValue(self, fields[i]); if (field_value == NULL) { - PyErr_SetObject(PyExc_ValueError, py_field_name.get()); + PyErr_SetString(PyExc_ValueError, fields[i]->name().c_str()); return NULL; } PyTuple_SET_ITEM(t.get(), 0, field_descriptor.release()); @@ -2233,7 +2126,7 @@ static PyObject* DiscardUnknownFields(CMessage* self) { PyObject* FindInitializationErrors(CMessage* self) { Message* message = self->message; - std::vector errors; + std::vector errors; message->FindInitializationErrors(&errors); PyObject* error_list = PyList_New(errors.size()); @@ -2241,7 +2134,7 @@ PyObject* FindInitializationErrors(CMessage* self) { return NULL; } for (size_t i = 0; i < errors.size(); ++i) { - const string& error = errors[i]; + const std::string& error = errors[i]; PyObject* error_string = PyString_FromStringAndSize( error.c_str(), error.length()); if (error_string == NULL) { @@ -2261,22 +2154,25 @@ static PyObject* RichCompare(CMessage* self, PyObject* other, int opid) { } bool equals = true; // If other is not a message, it cannot be equal. - if (!PyObject_TypeCheck(other, &CMessage_Type)) { - equals = false; - } - const google::protobuf::Message* other_message = - reinterpret_cast(other)->message; - // If messages don't have the same descriptors, they are not equal. - if (equals && - self->message->GetDescriptor() != other_message->GetDescriptor()) { - equals = false; - } - // Check the message contents. - if (equals && !google::protobuf::util::MessageDifferencer::Equals( - *self->message, - *reinterpret_cast(other)->message)) { + if (!PyObject_TypeCheck(other, CMessage_Type)) { equals = false; + } else { + // Otherwise, we have a CMessage whose message we can inspect. + const google::protobuf::Message* other_message = + reinterpret_cast(other)->message; + // If messages don't have the same descriptors, they are not equal. + if (equals && + self->message->GetDescriptor() != other_message->GetDescriptor()) { + equals = false; + } + // Check the message contents. + if (equals && + !google::protobuf::util::MessageDifferencer::Equals( + *self->message, *reinterpret_cast(other)->message)) { + equals = false; + } } + if (equals ^ (opid == Py_EQ)) { Py_RETURN_FALSE; } else { @@ -2330,32 +2226,16 @@ PyObject* InternalGetScalar(const Message* message, break; } case FieldDescriptor::CPPTYPE_STRING: { - string value = reflection->GetString(*message, field_descriptor); + std::string scratch; + const std::string& value = + reflection->GetStringReference(*message, field_descriptor, &scratch); result = ToStringObject(field_descriptor, value); break; } case FieldDescriptor::CPPTYPE_ENUM: { - if (!message->GetReflection()->SupportsUnknownEnumValues() && - !message->GetReflection()->HasField(*message, field_descriptor)) { - // Look for the value in the unknown fields. - const UnknownFieldSet& unknown_field_set = - message->GetReflection()->GetUnknownFields(*message); - for (int i = 0; i < unknown_field_set.field_count(); ++i) { - if (unknown_field_set.field(i).number() == - field_descriptor->number() && - unknown_field_set.field(i).type() == - google::protobuf::UnknownField::TYPE_VARINT) { - result = PyInt_FromLong(unknown_field_set.field(i).varint()); - break; - } - } - } - - if (result == NULL) { - const EnumValueDescriptor* enum_value = - message->GetReflection()->GetEnum(*message, field_descriptor); - result = PyInt_FromLong(enum_value->number()); - } + const EnumValueDescriptor* enum_value = + message->GetReflection()->GetEnum(*message, field_descriptor); + result = PyInt_FromLong(enum_value->number()); break; } default: @@ -2367,7 +2247,7 @@ PyObject* InternalGetScalar(const Message* message, return result; } -PyObject* InternalGetSubMessage( +CMessage* InternalGetSubMessage( CMessage* self, const FieldDescriptor* field_descriptor) { const Reflection* reflection = self->message->GetReflection(); PyMessageFactory* factory = GetFactoryForMessage(self); @@ -2376,7 +2256,7 @@ PyObject* InternalGetSubMessage( CMessageClass* message_class = message_factory::GetOrCreateMessageClass( factory, field_descriptor->message_type()); - ScopedPyObjectPtr message_class_handler( + ScopedPyObjectPtr message_class_owner( reinterpret_cast(message_class)); if (message_class == NULL) { return NULL; @@ -2387,13 +2267,12 @@ PyObject* InternalGetSubMessage( return NULL; } - cmsg->owner = self->owner; + Py_INCREF(self); cmsg->parent = self; cmsg->parent_field_descriptor = field_descriptor; cmsg->read_only = !reflection->HasField(*self->message, field_descriptor); cmsg->message = const_cast(&sub_message); - - return reinterpret_cast(cmsg); + return cmsg; } int InternalSetNonOneofScalar( @@ -2514,7 +2393,7 @@ PyObject* DeepCopy(CMessage* self, PyObject* arg) { if (clone == NULL) { return NULL; } - if (!PyObject_TypeCheck(clone, &CMessage_Type)) { + if (!PyObject_TypeCheck(clone, CMessage_Type)) { Py_DECREF(clone); return NULL; } @@ -2556,45 +2435,6 @@ PyObject* ToUnicode(CMessage* self) { return decoded; } -PyObject* Reduce(CMessage* self) { - ScopedPyObjectPtr constructor(reinterpret_cast(Py_TYPE(self))); - constructor.inc(); - ScopedPyObjectPtr args(PyTuple_New(0)); - if (args == NULL) { - return NULL; - } - ScopedPyObjectPtr state(PyDict_New()); - if (state == NULL) { - return NULL; - } - string contents; - self->message->SerializePartialToString(&contents); - ScopedPyObjectPtr serialized( - PyBytes_FromStringAndSize(contents.c_str(), contents.size())); - if (serialized == NULL) { - return NULL; - } - if (PyDict_SetItemString(state.get(), "serialized", serialized.get()) < 0) { - return NULL; - } - return Py_BuildValue("OOO", constructor.get(), args.get(), state.get()); -} - -PyObject* SetState(CMessage* self, PyObject* state) { - if (!PyDict_Check(state)) { - PyErr_SetString(PyExc_TypeError, "state not a dict"); - return NULL; - } - PyObject* serialized = PyDict_GetItemString(state, "serialized"); - if (serialized == NULL) { - return NULL; - } - if (ScopedPyObjectPtr(ParseFromString(self, serialized)) == NULL) { - return NULL; - } - Py_RETURN_NONE; -} - // CMessage static methods: PyObject* _CheckCalledFromGeneratedFile(PyObject* unused, PyObject* unused_arg) { @@ -2608,26 +2448,30 @@ PyObject* _CheckCalledFromGeneratedFile(PyObject* unused, } static PyObject* GetExtensionDict(CMessage* self, void *closure) { - if (self->extensions) { - Py_INCREF(self->extensions); - return reinterpret_cast(self->extensions); - } - // If there are extension_ranges, the message is "extendable". Allocate a // dictionary to store the extension fields. const Descriptor* descriptor = GetMessageDescriptor(Py_TYPE(self)); - if (descriptor->extension_range_count() > 0) { - ExtensionDict* extension_dict = extension_dict::NewExtensionDict(self); - if (extension_dict == NULL) { - return NULL; - } - self->extensions = extension_dict; - Py_INCREF(self->extensions); - return reinterpret_cast(self->extensions); + if (!descriptor->extension_range_count()) { + PyErr_SetNone(PyExc_AttributeError); + return NULL; } + if (!self->composite_fields) { + self->composite_fields = new CMessage::CompositeFieldsMap(); + } + if (!self->composite_fields) { + return NULL; + } + ExtensionDict* extension_dict = extension_dict::NewExtensionDict(self); + return reinterpret_cast(extension_dict); +} - PyErr_SetNone(PyExc_AttributeError); - return NULL; +static PyObject* UnknownFieldSet(CMessage* self) { + if (self->unknown_field_set == NULL) { + self->unknown_field_set = unknown_fields::NewPyUnknownFields(self); + } else { + Py_INCREF(self->unknown_field_set); + } + return self->unknown_field_set; } static PyObject* GetExtensionsByName(CMessage *self, void *closure) { @@ -2651,10 +2495,6 @@ static PyGetSetDef Getters[] = { static PyMethodDef Methods[] = { { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, "Makes a deep copy of the class." }, - { "__reduce__", (PyCFunction)Reduce, METH_NOARGS, - "Outputs picklable representation of the message." }, - { "__setstate__", (PyCFunction)SetState, METH_O, - "Inputs picklable representation of the message." }, { "__unicode__", (PyCFunction)ToUnicode, METH_NOARGS, "Outputs a unicode representation of the message." }, { "ByteSize", (PyCFunction)ByteSize, METH_NOARGS, @@ -2698,6 +2538,8 @@ static PyMethodDef Methods[] = { "Serializes the message to a string, only for initialized messages." }, { "SetInParent", (PyCFunction)SetInParent, METH_NOARGS, "Sets the has bit of the given field in its parent message." }, + { "UnknownFields", (PyCFunction)UnknownFieldSet, METH_NOARGS, + "Parse unknown field set"}, { "WhichOneof", (PyCFunction)WhichOneof, METH_O, "Returns the name of the field set inside a oneof, " "or None if no field is set." }, @@ -2709,33 +2551,66 @@ static PyMethodDef Methods[] = { { NULL, NULL} }; -static bool SetCompositeField( - CMessage* self, PyObject* name, PyObject* value) { +bool SetCompositeField(CMessage* self, const FieldDescriptor* field, + ContainerBase* value) { if (self->composite_fields == NULL) { - self->composite_fields = PyDict_New(); - if (self->composite_fields == NULL) { - return false; - } + self->composite_fields = new CMessage::CompositeFieldsMap(); } - return PyDict_SetItem(self->composite_fields, name, value) == 0; + (*self->composite_fields)[field] = value; + return true; } -PyObject* GetAttr(CMessage* self, PyObject* name) { - PyObject* value = self->composite_fields ? - PyDict_GetItem(self->composite_fields, name) : NULL; - if (value != NULL) { - Py_INCREF(value); - return value; +bool SetSubmessage(CMessage* self, CMessage* submessage) { + if (self->child_submessages == NULL) { + self->child_submessages = new CMessage::SubMessagesMap(); } + (*self->child_submessages)[submessage->message] = submessage; + return true; +} - const FieldDescriptor* field_descriptor = GetFieldDescriptor(self, name); - if (field_descriptor == NULL) { - return CMessage_Type.tp_base->tp_getattro( - reinterpret_cast(self), name); +PyObject* GetAttr(PyObject* pself, PyObject* name) { + CMessage* self = reinterpret_cast(pself); + PyObject* result = PyObject_GenericGetAttr( + reinterpret_cast(self), name); + if (result != NULL) { + return result; + } + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + return NULL; + } + + PyErr_Clear(); + return message_meta::GetClassAttribute( + CheckMessageClass(Py_TYPE(self)), name); +} + +PyObject* GetFieldValue(CMessage* self, + const FieldDescriptor* field_descriptor) { + if (self->composite_fields) { + CMessage::CompositeFieldsMap::iterator it = + self->composite_fields->find(field_descriptor); + if (it != self->composite_fields->end()) { + ContainerBase* value = it->second; + Py_INCREF(value); + return value->AsPyObject(); + } } + if (self->message->GetDescriptor() != field_descriptor->containing_type()) { + PyErr_Format(PyExc_TypeError, + "descriptor to field '%s' doesn't apply to '%s' object", + field_descriptor->full_name().c_str(), + Py_TYPE(self)->tp_name); + return NULL; + } + + if (!field_descriptor->is_repeated() && + field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + return InternalGetScalar(self->message, field_descriptor); + } + + ContainerBase* py_container = nullptr; if (field_descriptor->is_map()) { - PyObject* py_container = NULL; const Descriptor* entry_type = field_descriptor->message_type(); const FieldDescriptor* value_type = entry_type->FindFieldByName("value"); if (value_type->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { @@ -2749,18 +2624,7 @@ PyObject* GetAttr(CMessage* self, PyObject* name) { } else { py_container = NewScalarMapContainer(self, field_descriptor); } - if (py_container == NULL) { - return NULL; - } - if (!SetCompositeField(self, name, py_container)) { - Py_DECREF(py_container); - return NULL; - } - return py_container; - } - - if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { - PyObject* py_container = NULL; + } else if (field_descriptor->is_repeated()) { if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { CMessageClass* message_class = message_factory::GetMessageClass( GetFactoryForMessage(self), field_descriptor->message_type()); @@ -2770,71 +2634,129 @@ PyObject* GetAttr(CMessage* self, PyObject* name) { py_container = repeated_composite_container::NewContainer( self, field_descriptor, message_class); } else { - py_container = repeated_scalar_container::NewContainer( - self, field_descriptor); - } - if (py_container == NULL) { - return NULL; - } - if (!SetCompositeField(self, name, py_container)) { - Py_DECREF(py_container); - return NULL; + py_container = + repeated_scalar_container::NewContainer(self, field_descriptor); } - return py_container; + } else if (field_descriptor->cpp_type() == + FieldDescriptor::CPPTYPE_MESSAGE) { + py_container = InternalGetSubMessage(self, field_descriptor); + } else { + PyErr_SetString(PyExc_SystemError, "Should never happen"); } - if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - PyObject* sub_message = InternalGetSubMessage(self, field_descriptor); - if (sub_message == NULL) { - return NULL; - } - if (!SetCompositeField(self, name, sub_message)) { - Py_DECREF(sub_message); - return NULL; - } - return sub_message; + if (py_container == NULL) { + return NULL; } - - return InternalGetScalar(self->message, field_descriptor); + if (!SetCompositeField(self, field_descriptor, py_container)) { + Py_DECREF(py_container); + return NULL; + } + return py_container->AsPyObject(); } -int SetAttr(CMessage* self, PyObject* name, PyObject* value) { - if (self->composite_fields && PyDict_Contains(self->composite_fields, name)) { - PyErr_SetString(PyExc_TypeError, "Can't set composite field"); +int SetFieldValue(CMessage* self, const FieldDescriptor* field_descriptor, + PyObject* value) { + if (self->message->GetDescriptor() != field_descriptor->containing_type()) { + PyErr_Format(PyExc_TypeError, + "descriptor to field '%s' doesn't apply to '%s' object", + field_descriptor->full_name().c_str(), + Py_TYPE(self)->tp_name); + return -1; + } else if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { + PyErr_Format(PyExc_AttributeError, + "Assignment not allowed to repeated " + "field \"%s\" in protocol message object.", + field_descriptor->name().c_str()); return -1; + } else if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + PyErr_Format(PyExc_AttributeError, + "Assignment not allowed to " + "field \"%s\" in protocol message object.", + field_descriptor->name().c_str()); + return -1; + } else { + AssureWritable(self); + return InternalSetScalar(self, field_descriptor, value); } +} - const FieldDescriptor* field_descriptor = GetFieldDescriptor(self, name); - if (field_descriptor != NULL) { - AssureWritable(self); - if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { - PyErr_Format(PyExc_AttributeError, "Assignment not allowed to repeated " - "field \"%s\" in protocol message object.", - field_descriptor->name().c_str()); - return -1; - } else { - if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - PyErr_Format(PyExc_AttributeError, "Assignment not allowed to " - "field \"%s\" in protocol message object.", - field_descriptor->name().c_str()); - return -1; - } else { - return InternalSetScalar(self, field_descriptor, value); - } - } +} // namespace cmessage + +// All containers which are not messages: +// - Make a new parent message +// - Copy the field +// - return the field. +PyObject* ContainerBase::DeepCopy() { + CMessage* new_parent = + cmessage::NewEmptyMessage(this->parent->GetMessageClass()); + new_parent->message = this->parent->message->New(); + + // Copy the map field into the new message. + this->parent->message->GetReflection()->SwapFields( + this->parent->message, new_parent->message, + {this->parent_field_descriptor}); + this->parent->message->MergeFrom(*new_parent->message); + + PyObject* result = + cmessage::GetFieldValue(new_parent, this->parent_field_descriptor); + Py_DECREF(new_parent); + return result; +} + +void ContainerBase::RemoveFromParentCache() { + CMessage* parent = this->parent; + if (parent) { + if (parent->composite_fields) + parent->composite_fields->erase(this->parent_field_descriptor); + Py_CLEAR(parent); } +} + +CMessage* CMessage::BuildSubMessageFromPointer( + const FieldDescriptor* field_descriptor, Message* sub_message, + CMessageClass* message_class) { + if (!this->child_submessages) { + this->child_submessages = new CMessage::SubMessagesMap(); + } + CMessage* cmsg = FindPtrOrNull( + *this->child_submessages, sub_message); + if (cmsg) { + Py_INCREF(cmsg); + } else { + cmsg = cmessage::NewEmptyMessage(message_class); - PyErr_Format(PyExc_AttributeError, - "Assignment not allowed " - "(no field \"%s\" in protocol message object).", - PyString_AsString(name)); - return -1; + if (cmsg == NULL) { + return NULL; + } + cmsg->message = sub_message; + Py_INCREF(this); + cmsg->parent = this; + cmsg->parent_field_descriptor = field_descriptor; + cmessage::SetSubmessage(this, cmsg); + } + return cmsg; } -} // namespace cmessage +CMessage* CMessage::MaybeReleaseSubMessage(Message* sub_message) { + if (!this->child_submessages) { + return nullptr; + } + CMessage* released = FindPtrOrNull( + *this->child_submessages, sub_message); + if (!released) { + return nullptr; + } + // The target message will now own its content. + Py_CLEAR(released->parent); + released->parent_field_descriptor = nullptr; + released->read_only = false; + // Delete it from the cache. + this->child_submessages->erase(sub_message); + return released; +} -PyTypeObject CMessage_Type = { - PyVarObject_HEAD_INIT(&CMessageClass_Type, 0) +static CMessageClass _CMessage_Type = { { { + PyVarObject_HEAD_INIT(&_CMessageClass_Type, 0) FULL_MODULE_NAME ".CMessage", // tp_name sizeof(CMessage), // tp_basicsize 0, // tp_itemsize @@ -2850,10 +2772,11 @@ PyTypeObject CMessage_Type = { PyObject_HashNotImplemented, // tp_hash 0, // tp_call (reprfunc)cmessage::ToStr, // tp_str - (getattrofunc)cmessage::GetAttr, // tp_getattro - (setattrofunc)cmessage::SetAttr, // tp_setattro + cmessage::GetAttr, // tp_getattro + 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE + | Py_TPFLAGS_HAVE_VERSION_TAG, // tp_flags "A ProtocolMessage", // tp_doc 0, // tp_traverse 0, // tp_clear @@ -2872,7 +2795,8 @@ PyTypeObject CMessage_Type = { (initproc)cmessage::Init, // tp_init 0, // tp_alloc cmessage::New, // tp_new -}; +} } }; +PyTypeObject* CMessage_Type = &_CMessage_Type.super.ht_type; // --- Exposing the C proto living inside Python proto to C code: @@ -2880,31 +2804,112 @@ const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg); Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg); static const Message* GetCProtoInsidePyProtoImpl(PyObject* msg) { - if (!PyObject_TypeCheck(msg, &CMessage_Type)) { + const Message* message = PyMessage_GetMessagePointer(msg); + if (message == NULL) { + PyErr_Clear(); + return NULL; + } + return message; +} + +static Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) { + Message* message = PyMessage_GetMutableMessagePointer(msg); + if (message == NULL) { + PyErr_Clear(); + return NULL; + } + return message; +} + +const Message* PyMessage_GetMessagePointer(PyObject* msg) { + if (!PyObject_TypeCheck(msg, CMessage_Type)) { + PyErr_SetString(PyExc_TypeError, "Not a Message instance"); return NULL; } CMessage* cmsg = reinterpret_cast(msg); return cmsg->message; } -static Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) { - if (!PyObject_TypeCheck(msg, &CMessage_Type)) { +Message* PyMessage_GetMutableMessagePointer(PyObject* msg) { + if (!PyObject_TypeCheck(msg, CMessage_Type)) { + PyErr_SetString(PyExc_TypeError, "Not a Message instance"); return NULL; } CMessage* cmsg = reinterpret_cast(msg); - if ((cmsg->composite_fields && PyDict_Size(cmsg->composite_fields) != 0) || - (cmsg->extensions != NULL && - PyDict_Size(cmsg->extensions->values) != 0)) { + + + if ((cmsg->composite_fields && !cmsg->composite_fields->empty()) || + (cmsg->child_submessages && !cmsg->child_submessages->empty())) { // There is currently no way of accurately syncing arbitrary changes to // the underlying C++ message back to the CMessage (e.g. removed repeated // composite containers). We only allow direct mutation of the underlying // C++ message if there is no child data in the CMessage. + PyErr_SetString(PyExc_ValueError, + "Cannot reliably get a mutable pointer " + "to a message with extra references"); return NULL; } cmessage::AssureWritable(cmsg); return cmsg->message; } +PyObject* PyMessage_New(const Descriptor* descriptor, + PyObject* py_message_factory) { + PyMessageFactory* factory = nullptr; + if (py_message_factory == nullptr) { + factory = GetDescriptorPool_FromPool(descriptor->file()->pool()) + ->py_message_factory; + } else if (PyObject_TypeCheck(py_message_factory, &PyMessageFactory_Type)) { + factory = reinterpret_cast(py_message_factory); + } else { + PyErr_SetString(PyExc_TypeError, "Expected a MessageFactory"); + return nullptr; + } + auto* message_class = + message_factory::GetOrCreateMessageClass(factory, descriptor); + if (message_class == nullptr) { + return nullptr; + } + + CMessage* self = cmessage::NewCMessage(message_class); + Py_DECREF(message_class); + if (self == nullptr) { + return nullptr; + } + return self->AsPyObject(); +} + +PyObject* PyMessage_NewMessageOwnedExternally(Message* message, + PyObject* py_message_factory) { + if (py_message_factory) { + PyErr_SetString(PyExc_NotImplementedError, + "Default message_factory=NULL is the only supported value"); + return nullptr; + } + if (message->GetReflection()->GetMessageFactory() != + MessageFactory::generated_factory()) { + PyErr_SetString(PyExc_TypeError, + "Message pointer was not created from the default factory"); + return nullptr; + } + + CMessageClass* message_class = message_factory::GetOrCreateMessageClass( + GetDefaultDescriptorPool()->py_message_factory, message->GetDescriptor()); + if (message_class == nullptr) { + return nullptr; + } + + CMessage* self = cmessage::NewEmptyMessage(message_class); + Py_DECREF(message_class); + if (self == nullptr) { + return nullptr; + } + self->message = message; + Py_INCREF(Py_None); + self->parent = reinterpret_cast(Py_None); + return self->AsPyObject(); +} + void InitGlobals() { // TODO(gps): Check all return values in this function for NULL and propagate // the error (MemoryError) on up to result in an import failure. These should @@ -2935,22 +2940,29 @@ bool InitProto2MessageModule(PyObject *m) { // Initialize constants defined in this file. InitGlobals(); - CMessageClass_Type.tp_base = &PyType_Type; - if (PyType_Ready(&CMessageClass_Type) < 0) { + CMessageClass_Type->tp_base = &PyType_Type; + if (PyType_Ready(CMessageClass_Type) < 0) { return false; } PyModule_AddObject(m, "MessageMeta", - reinterpret_cast(&CMessageClass_Type)); + reinterpret_cast(CMessageClass_Type)); - if (PyType_Ready(&CMessage_Type) < 0) { + if (PyType_Ready(CMessage_Type) < 0) { + return false; + } + if (PyType_Ready(CFieldProperty_Type) < 0) { return false; } // DESCRIPTOR is set on each protocol buffer message class elsewhere, but set // it here as well to document that subclasses need to set it. - PyDict_SetItem(CMessage_Type.tp_dict, kDESCRIPTOR, Py_None); + PyDict_SetItem(CMessage_Type->tp_dict, kDESCRIPTOR, Py_None); + // Invalidate any cached data for the CMessage type. + // This call is necessary to correctly support Py_TPFLAGS_HAVE_VERSION_TAG, + // after we have modified CMessage_Type.tp_dict. + PyType_Modified(CMessage_Type); - PyModule_AddObject(m, "Message", reinterpret_cast(&CMessage_Type)); + PyModule_AddObject(m, "Message", reinterpret_cast(CMessage_Type)); // Initialize Repeated container types. { @@ -2958,9 +2970,9 @@ bool InitProto2MessageModule(PyObject *m) { return false; } - PyModule_AddObject(m, "RepeatedScalarContainer", - reinterpret_cast( - &RepeatedScalarContainer_Type)); + PyModule_AddObject( + m, "RepeatedScalarContainer", + reinterpret_cast(&RepeatedScalarContainer_Type)); if (PyType_Ready(&RepeatedCompositeContainer_Type) < 0) { return false; @@ -2968,11 +2980,14 @@ bool InitProto2MessageModule(PyObject *m) { PyModule_AddObject( m, "RepeatedCompositeContainer", - reinterpret_cast( - &RepeatedCompositeContainer_Type)); + reinterpret_cast(&RepeatedCompositeContainer_Type)); - // Register them as collections.Sequence + // Register them as MutableSequence. +#if PY_MAJOR_VERSION >= 3 + ScopedPyObjectPtr collections(PyImport_ImportModule("collections.abc")); +#else ScopedPyObjectPtr collections(PyImport_ImportModule("collections")); +#endif if (collections == NULL) { return false; } @@ -2993,6 +3008,20 @@ bool InitProto2MessageModule(PyObject *m) { } } + if (PyType_Ready(&PyUnknownFields_Type) < 0) { + return false; + } + + PyModule_AddObject(m, "UnknownFieldSet", + reinterpret_cast(&PyUnknownFields_Type)); + + if (PyType_Ready(&PyUnknownFieldRef_Type) < 0) { + return false; + } + + PyModule_AddObject(m, "UnknownField", + reinterpret_cast(&PyUnknownFieldRef_Type)); + // Initialize Map container types. if (!InitMapContainers()) { return false; @@ -3007,9 +3036,13 @@ bool InitProto2MessageModule(PyObject *m) { if (PyType_Ready(&ExtensionDict_Type) < 0) { return false; } - PyModule_AddObject( - m, "ExtensionDict", - reinterpret_cast(&ExtensionDict_Type)); + PyModule_AddObject(m, "ExtensionDict", + reinterpret_cast(&ExtensionDict_Type)); + if (PyType_Ready(&ExtensionIterator_Type) < 0) { + return false; + } + PyModule_AddObject(m, "ExtensionIterator", + reinterpret_cast(&ExtensionIterator_Type)); // Expose the DescriptorPool used to hold all descriptors added from generated // pb2.py files. @@ -3018,29 +3051,24 @@ bool InitProto2MessageModule(PyObject *m) { PyModule_AddObject(m, "default_pool", reinterpret_cast(GetDefaultDescriptorPool())); - PyModule_AddObject(m, "DescriptorPool", reinterpret_cast( - &PyDescriptorPool_Type)); - - // This implementation provides full Descriptor types, we advertise it so that - // descriptor.py can use them in replacement of the Python classes. - PyModule_AddIntConstant(m, "_USE_C_DESCRIPTORS", 1); - - PyModule_AddObject(m, "Descriptor", reinterpret_cast( - &PyMessageDescriptor_Type)); - PyModule_AddObject(m, "FieldDescriptor", reinterpret_cast( - &PyFieldDescriptor_Type)); - PyModule_AddObject(m, "EnumDescriptor", reinterpret_cast( - &PyEnumDescriptor_Type)); - PyModule_AddObject(m, "EnumValueDescriptor", reinterpret_cast( - &PyEnumValueDescriptor_Type)); - PyModule_AddObject(m, "FileDescriptor", reinterpret_cast( - &PyFileDescriptor_Type)); - PyModule_AddObject(m, "OneofDescriptor", reinterpret_cast( - &PyOneofDescriptor_Type)); - PyModule_AddObject(m, "ServiceDescriptor", reinterpret_cast( - &PyServiceDescriptor_Type)); - PyModule_AddObject(m, "MethodDescriptor", reinterpret_cast( - &PyMethodDescriptor_Type)); + PyModule_AddObject(m, "DescriptorPool", + reinterpret_cast(&PyDescriptorPool_Type)); + PyModule_AddObject(m, "Descriptor", + reinterpret_cast(&PyMessageDescriptor_Type)); + PyModule_AddObject(m, "FieldDescriptor", + reinterpret_cast(&PyFieldDescriptor_Type)); + PyModule_AddObject(m, "EnumDescriptor", + reinterpret_cast(&PyEnumDescriptor_Type)); + PyModule_AddObject(m, "EnumValueDescriptor", + reinterpret_cast(&PyEnumValueDescriptor_Type)); + PyModule_AddObject(m, "FileDescriptor", + reinterpret_cast(&PyFileDescriptor_Type)); + PyModule_AddObject(m, "OneofDescriptor", + reinterpret_cast(&PyOneofDescriptor_Type)); + PyModule_AddObject(m, "ServiceDescriptor", + reinterpret_cast(&PyServiceDescriptor_Type)); + PyModule_AddObject(m, "MethodDescriptor", + reinterpret_cast(&PyMethodDescriptor_Type)); PyObject* enum_type_wrapper = PyImport_ImportModule( "google.protobuf.internal.enum_type_wrapper"); @@ -3077,5 +3105,4 @@ bool InitProto2MessageModule(PyObject *m) { } // namespace python } // namespace protobuf - } // namespace google diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h index ce80497e6b4c7..a1e8326512376 100644 --- a/python/google/protobuf/pyext/message.h +++ b/python/google/protobuf/pyext/message.h @@ -37,10 +37,10 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include +#include + +#include namespace google { namespace protobuf { @@ -52,48 +52,55 @@ class Descriptor; class DescriptorPool; class MessageFactory; -#ifdef _SHARED_PTR_H -using std::shared_ptr; -using std::string; -#else -using internal::shared_ptr; -#endif - namespace python { struct ExtensionDict; struct PyMessageFactory; +struct CMessageClass; -typedef struct CMessage { - PyObject_HEAD; +// Most of the complexity of the Message class comes from the "Release" +// behavior: +// +// When a field is cleared, it is only detached from its message. Existing +// references to submessages, to repeated container etc. won't see any change, +// as if the data was effectively managed by these containers. +// +// ExtensionDicts and UnknownFields containers do NOT follow this rule. They +// don't store any data, and always refer to their parent message. - // This is the top-level C++ Message object that owns the whole - // proto tree. Every Python CMessage holds a reference to it in - // order to keep it alive as long as there's a Python object that - // references any part of the tree. - shared_ptr owner; +struct ContainerBase { + PyObject_HEAD; - // Weak reference to a parent CMessage object. This is NULL for any top-level - // message and is set for any child message (i.e. a child submessage or a - // part of a repeated composite field). + // Strong reference to a parent message object. For a CMessage there are three + // cases: + // - For a top-level message, this pointer is NULL. + // - For a sub-message, this points to the parent message. + // - For a message managed externally, this is a owned reference to Py_None. // - // Used to make sure all ancestors are also mutable when first modifying - // a child submessage (in other words, turning a default message instance - // into a mutable one). - // - // If a submessage is released (becomes a new top-level message), this field - // MUST be set to NULL. The parent may get deallocated and further attempts - // to use this pointer will result in a crash. + // For all other types: repeated containers, maps, it always point to a + // valid parent CMessage. struct CMessage* parent; - // Pointer to the parent's descriptor that describes this submessage. - // Used together with the parent's message when making a default message - // instance mutable. - // The pointer is owned by the global DescriptorPool. + // If this object belongs to a parent message, describes which field it comes + // from. + // The pointer is owned by the DescriptorPool (which is kept alive + // through the message's Python class) const FieldDescriptor* parent_field_descriptor; - // Pointer to the C++ Message object for this CMessage. The - // CMessage does not own this pointer. + PyObject* AsPyObject() { return reinterpret_cast(this); } + + // The Three methods below are only used by Repeated containers, and Maps. + + // This implementation works for all containers which have a parent. + PyObject* DeepCopy(); + // Delete this container object from its parent. Does not work for messages. + void RemoveFromParentCache(); +}; + +typedef struct CMessage : public ContainerBase { + // Pointer to the C++ Message object for this CMessage. + // - If this object has no parent, we own this pointer. + // - If this object has a parent message, the parent owns this pointer. Message* message; // Indicates this submessage is pointing to a default instance of a message. @@ -101,25 +108,38 @@ typedef struct CMessage { // made writable, at which point this field is set to false. bool read_only; - // A reference to a Python dictionary containing CMessage, - // RepeatedCompositeContainer, and RepeatedScalarContainer - // objects. Used as a cache to make sure we don't have to make a - // Python wrapper for the C++ Message objects on every access, or - // deal with the synchronization nightmare that could create. - PyObject* composite_fields; + // A mapping indexed by field, containing weak references to contained objects + // which need to implement the "Release" mechanism: + // direct submessages, RepeatedCompositeContainer, RepeatedScalarContainer + // and MapContainer. + typedef std::unordered_map + CompositeFieldsMap; + CompositeFieldsMap* composite_fields; - // A reference to the dictionary containing the message's extensions. - // Similar to composite_fields, acting as a cache, but also contains the - // required extension dict logic. - ExtensionDict* extensions; + // A mapping containing weak references to indirect child messages, accessed + // through containers: repeated messages, and values of message maps. + // This avoid the creation of similar maps in each of those containers. + typedef std::unordered_map SubMessagesMap; + SubMessagesMap* child_submessages; + + // A reference to PyUnknownFields. + PyObject* unknown_field_set; // Implements the "weakref" protocol for this object. PyObject* weakreflist; -} CMessage; -extern PyTypeObject CMessageClass_Type; -extern PyTypeObject CMessage_Type; + // Return a *borrowed* reference to the message class. + CMessageClass* GetMessageClass() { + return reinterpret_cast(Py_TYPE(this)); + } + // For container containing messages, return a Python object for the given + // pointer to a message. + CMessage* BuildSubMessageFromPointer(const FieldDescriptor* field_descriptor, + Message* sub_message, + CMessageClass* message_class); + CMessage* MaybeReleaseSubMessage(Message* sub_message); +} CMessage; // The (meta) type of all Messages classes. // It allows us to cache some C++ pointers in the class object itself, they are @@ -134,12 +154,13 @@ struct CMessageClass { const Descriptor* message_descriptor; // Owned reference, used to keep the pointer above alive. + // This reference must stay alive until all message pointers are destructed. PyObject* py_message_descriptor; // The Python MessageFactory used to create the class. It is needed to resolve // fields descriptors, including extensions fields; its C++ MessageFactory is // used to instantiate submessages. - // We own the reference, because it's important to keep the factory alive. + // This reference must stay alive until all message pointers are destructed. PyMessageFactory* py_message_factory; PyObject* AsPyObject() { @@ -147,6 +168,8 @@ struct CMessageClass { } }; +extern PyTypeObject* CMessageClass_Type; +extern PyTypeObject* CMessage_Type; namespace cmessage { @@ -163,21 +186,16 @@ const FieldDescriptor* GetExtensionDescriptor(PyObject* extension); // submessage as the result is cached in composite_fields. // // Corresponds to reflection api method GetMessage. -PyObject* InternalGetSubMessage( +CMessage* InternalGetSubMessage( CMessage* self, const FieldDescriptor* field_descriptor); -// Deletes a range of C++ submessages in a repeated field (following a +// Deletes a range of items in a repeated field (following a // removal in a RepeatedCompositeContainer). // -// Releases messages to the provided cmessage_list if it is not NULL rather -// than just removing them from the underlying proto. This cmessage_list must -// have a CMessage for each underlying submessage. The CMessages referred to -// by slice will be removed from cmessage_list by this function. -// // Corresponds to reflection api method RemoveLast. -int InternalDeleteRepeatedField(CMessage* self, - const FieldDescriptor* field_descriptor, - PyObject* slice, PyObject* cmessage_list); +int DeleteRepeatedField(CMessage* self, + const FieldDescriptor* field_descriptor, + PyObject* slice); // Sets the specified scalar value to the message. int InternalSetScalar(CMessage* self, @@ -195,34 +213,30 @@ int InternalSetNonOneofScalar(Message* message, PyObject* InternalGetScalar(const Message* message, const FieldDescriptor* field_descriptor); +bool SetCompositeField(CMessage* self, const FieldDescriptor* field, + ContainerBase* value); + +bool SetSubmessage(CMessage* self, CMessage* submessage); + // Clears the message, removing all contained data. Extension dictionary and // submessages are released first if there are remaining external references. // // Corresponds to message api method Clear. PyObject* Clear(CMessage* self); -// Clears the data described by the given descriptor. Used to clear extensions -// (which don't have names). Extension release is handled by ExtensionDict -// class, not this function. -// TODO(anuraag): Try to make this discrepancy in release semantics with -// ClearField less confusing. -// -// Corresponds to reflection api method ClearField. -PyObject* ClearFieldByDescriptor( - CMessage* self, const FieldDescriptor* descriptor); - -// Clears the data for the given field name. The message is released if there -// are any external references. +// Clears the data described by the given descriptor. +// Returns -1 on error. // // Corresponds to reflection api method ClearField. -PyObject* ClearField(CMessage* self, PyObject* arg); +int ClearFieldByDescriptor(CMessage* self, const FieldDescriptor* descriptor); // Checks if the message has the field described by the descriptor. Used for // extensions (which have no name). +// Returns 1 if true, 0 if false, and -1 on error. // // Corresponds to reflection api method HasField -PyObject* HasFieldByDescriptor( - CMessage* self, const FieldDescriptor* field_descriptor); +int HasFieldByDescriptor(CMessage* self, + const FieldDescriptor* field_descriptor); // Checks if the message has the named field. // @@ -240,23 +254,16 @@ PyObject* MergeFrom(CMessage* self, PyObject* arg); // has been registered with the same field number on this class. PyObject* RegisterExtension(PyObject* cls, PyObject* extension_handle); -// Retrieves an attribute named 'name' from CMessage 'self'. Returns -// the attribute value on success, or NULL on failure. -// -// Returns a new reference. -PyObject* GetAttr(CMessage* self, PyObject* name); - -// Set the value of the attribute named 'name', for CMessage 'self', -// to the value 'value'. Returns -1 on failure. -int SetAttr(CMessage* self, PyObject* name, PyObject* value); +// Get a field from a message. +PyObject* GetFieldValue(CMessage* self, + const FieldDescriptor* field_descriptor); +// Sets the value of a scalar field in a message. +// On error, return -1 with an extension set. +int SetFieldValue(CMessage* self, const FieldDescriptor* field_descriptor, + PyObject* value); PyObject* FindInitializationErrors(CMessage* self); -// Set the owner field of self and any children of self, recursively. -// Used when self is being released and thus has a new owner (the -// released Message.) -int SetOwner(CMessage* self, const shared_ptr& new_owner); - int AssureWritable(CMessage* self); // Returns the message factory for the given message. @@ -275,51 +282,50 @@ PyObject* SetAllowOversizeProtos(PyObject* m, PyObject* arg); /* Is 64bit */ #define IS_64BIT (SIZEOF_LONG == 8) -#define FIELD_IS_REPEATED(field_descriptor) \ - ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED) - -#define GOOGLE_CHECK_GET_INT32(arg, value, err) \ - int32 value; \ - if (!CheckAndGetInteger(arg, &value)) { \ - return err; \ - } - -#define GOOGLE_CHECK_GET_INT64(arg, value, err) \ - int64 value; \ - if (!CheckAndGetInteger(arg, &value)) { \ - return err; \ - } - -#define GOOGLE_CHECK_GET_UINT32(arg, value, err) \ - uint32 value; \ - if (!CheckAndGetInteger(arg, &value)) { \ - return err; \ - } - -#define GOOGLE_CHECK_GET_UINT64(arg, value, err) \ - uint64 value; \ - if (!CheckAndGetInteger(arg, &value)) { \ - return err; \ - } - -#define GOOGLE_CHECK_GET_FLOAT(arg, value, err) \ - float value; \ - if (!CheckAndGetFloat(arg, &value)) { \ - return err; \ - } \ - -#define GOOGLE_CHECK_GET_DOUBLE(arg, value, err) \ - double value; \ - if (!CheckAndGetDouble(arg, &value)) { \ - return err; \ - } - -#define GOOGLE_CHECK_GET_BOOL(arg, value, err) \ - bool value; \ - if (!CheckAndGetBool(arg, &value)) { \ - return err; \ - } +#define FIELD_IS_REPEATED(field_descriptor) \ + ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED) + +#define GOOGLE_CHECK_GET_INT32(arg, value, err) \ + int32 value; \ + if (!CheckAndGetInteger(arg, &value)) { \ + return err; \ + } +#define GOOGLE_CHECK_GET_INT64(arg, value, err) \ + int64 value; \ + if (!CheckAndGetInteger(arg, &value)) { \ + return err; \ + } + +#define GOOGLE_CHECK_GET_UINT32(arg, value, err) \ + uint32 value; \ + if (!CheckAndGetInteger(arg, &value)) { \ + return err; \ + } + +#define GOOGLE_CHECK_GET_UINT64(arg, value, err) \ + uint64 value; \ + if (!CheckAndGetInteger(arg, &value)) { \ + return err; \ + } + +#define GOOGLE_CHECK_GET_FLOAT(arg, value, err) \ + float value; \ + if (!CheckAndGetFloat(arg, &value)) { \ + return err; \ + } + +#define GOOGLE_CHECK_GET_DOUBLE(arg, value, err) \ + double value; \ + if (!CheckAndGetDouble(arg, &value)) { \ + return err; \ + } + +#define GOOGLE_CHECK_GET_BOOL(arg, value, err) \ + bool value; \ + if (!CheckAndGetBool(arg, &value)) { \ + return err; \ + } #define FULL_MODULE_NAME "google.protobuf.pyext._message" @@ -336,7 +342,8 @@ bool CheckAndSetString( const Reflection* reflection, bool append, int index); -PyObject* ToStringObject(const FieldDescriptor* descriptor, string value); +PyObject* ToStringObject(const FieldDescriptor* descriptor, + const std::string& value); // Check if the passed field descriptor belongs to the given message. // If not, return false and set a Python exception (a KeyError) @@ -345,10 +352,24 @@ bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor, extern PyObject* PickleError_class; +PyObject* PyMessage_New(const Descriptor* descriptor, + PyObject* py_message_factory); +const Message* PyMessage_GetMessagePointer(PyObject* msg); +Message* PyMessage_GetMutableMessagePointer(PyObject* msg); +PyObject* PyMessage_NewMessageOwnedExternally(Message* message, + PyObject* py_message_factory); + bool InitProto2MessageModule(PyObject *m); +// These are referenced by repeated_scalar_container, and must +// be explicitly instantiated. +extern template bool CheckAndGetInteger(PyObject*, int32*); +extern template bool CheckAndGetInteger(PyObject*, int64*); +extern template bool CheckAndGetInteger(PyObject*, uint32*); +extern template bool CheckAndGetInteger(PyObject*, uint64*); + } // namespace python } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_H__ diff --git a/python/google/protobuf/pyext/message_factory.cc b/python/google/protobuf/pyext/message_factory.cc index 571bae2be4a17..5fed13b9430b5 100644 --- a/python/google/protobuf/pyext/message_factory.cc +++ b/python/google/protobuf/pyext/message_factory.cc @@ -28,6 +28,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include + #include #include @@ -41,9 +43,11 @@ #error "Python 3.0 - 3.2 are not supported." #endif #define PyString_AsStringAndSize(ob, charpp, sizep) \ - (PyUnicode_Check(ob)? \ - ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \ - PyBytes_AsStringAndSize(ob, (charpp), (sizep))) + (PyUnicode_Check(ob) ? ((*(charpp) = const_cast( \ + PyUnicode_AsUTF8AndSize(ob, (sizep)))) == NULL \ + ? -1 \ + : 0) \ + : PyBytes_AsStringAndSize(ob, (charpp), (sizep))) #endif namespace google { @@ -65,9 +69,7 @@ PyMessageFactory* NewMessageFactory(PyTypeObject* type, PyDescriptorPool* pool) factory->message_factory = message_factory; factory->pool = pool; - // TODO(amauryfa): When the MessageFactory is not created from the - // DescriptorPool this reference should be owned, not borrowed. - // Py_INCREF(pool); + Py_INCREF(pool); factory->classes_by_descriptor = new PyMessageFactory::ClassesByMessageMap(); @@ -100,18 +102,38 @@ PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) { NewMessageFactory(type, reinterpret_cast(pool))); } -static void Dealloc(PyMessageFactory* self) { - // TODO(amauryfa): When the MessageFactory is not created from the - // DescriptorPool this reference should be owned, not borrowed. - // Py_CLEAR(self->pool); +static void Dealloc(PyObject* pself) { + PyMessageFactory* self = reinterpret_cast(pself); + typedef PyMessageFactory::ClassesByMessageMap::iterator iterator; for (iterator it = self->classes_by_descriptor->begin(); it != self->classes_by_descriptor->end(); ++it) { - Py_DECREF(it->second); + Py_CLEAR(it->second); } delete self->classes_by_descriptor; delete self->message_factory; - Py_TYPE(self)->tp_free(reinterpret_cast(self)); + Py_CLEAR(self->pool); + Py_TYPE(self)->tp_free(pself); +} + +static int GcTraverse(PyObject* pself, visitproc visit, void* arg) { + PyMessageFactory* self = reinterpret_cast(pself); + Py_VISIT(self->pool); + for (const auto& desc_and_class : *self->classes_by_descriptor) { + Py_VISIT(desc_and_class.second); + } + return 0; +} + +static int GcClear(PyObject* pself) { + PyMessageFactory* self = reinterpret_cast(pself); + // Here it's important to not clear self->pool, so that the C++ DescriptorPool + // is still alive when self->message_factory is destructed. + for (auto& desc_and_class : *self->classes_by_descriptor) { + Py_CLEAR(desc_and_class.second); + } + + return 0; } // Add a message class to our database. @@ -135,7 +157,7 @@ CMessageClass* GetOrCreateMessageClass(PyMessageFactory* self, // This is the same implementation as MessageFactory.GetPrototype(). // Do not create a MessageClass that already exists. - hash_map::iterator it = + std::unordered_map::iterator it = self->classes_by_descriptor->find(descriptor); if (it != self->classes_by_descriptor->end()) { Py_INCREF(it->second); @@ -156,7 +178,7 @@ CMessageClass* GetOrCreateMessageClass(PyMessageFactory* self, return NULL; } ScopedPyObjectPtr message_class(PyObject_CallObject( - reinterpret_cast(&CMessageClass_Type), args.get())); + reinterpret_cast(CMessageClass_Type), args.get())); if (message_class == NULL) { return NULL; } @@ -228,44 +250,44 @@ static PyGetSetDef Getters[] = { PyTypeObject PyMessageFactory_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME - ".MessageFactory", // tp_name - sizeof(PyMessageFactory), // tp_basicsize - 0, // tp_itemsize - (destructor)message_factory::Dealloc, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - 0, // tp_repr - 0, // tp_as_number - 0, // tp_as_sequence - 0, // tp_as_mapping - 0, // tp_hash - 0, // tp_call - 0, // tp_str - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags - "A static Message Factory", // tp_doc - 0, // tp_traverse - 0, // tp_clear - 0, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - message_factory::Methods, // tp_methods - 0, // tp_members - message_factory::Getters, // tp_getset - 0, // tp_base - 0, // tp_dict - 0, // tp_descr_get - 0, // tp_descr_set - 0, // tp_dictoffset - 0, // tp_init - 0, // tp_alloc - message_factory::New, // tp_new - PyObject_Del, // tp_free + ".MessageFactory", // tp_name + sizeof(PyMessageFactory), // tp_basicsize + 0, // tp_itemsize + message_factory::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, // tp_flags + "A static Message Factory", // tp_doc + message_factory::GcTraverse, // tp_traverse + message_factory::GcClear, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + message_factory::Methods, // tp_methods + 0, // tp_members + message_factory::Getters, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + message_factory::New, // tp_new + PyObject_GC_Del, // tp_free }; bool InitMessageFactory() { diff --git a/python/google/protobuf/pyext/message_factory.h b/python/google/protobuf/pyext/message_factory.h index 36092f7e40a60..515c29cdb82ab 100644 --- a/python/google/protobuf/pyext/message_factory.h +++ b/python/google/protobuf/pyext/message_factory.h @@ -33,7 +33,7 @@ #include -#include +#include #include #include @@ -57,16 +57,16 @@ struct PyMessageFactory { // The C++ one creates messages, when the Python one creates classes. MessageFactory* message_factory; - // borrowed reference to a Python DescriptorPool. - // TODO(amauryfa): invert the dependency: the MessageFactory owns the - // DescriptorPool, not the opposite. + // Owned reference to a Python DescriptorPool. + // This reference must stay until the message_factory is destructed. PyDescriptorPool* pool; // Make our own mapping to retrieve Python classes from C++ descriptors. // // Descriptor pointers stored here are owned by the DescriptorPool above. // Python references to classes are owned by this PyDescriptorPool. - typedef hash_map ClassesByMessageMap; + typedef std::unordered_map + ClassesByMessageMap; ClassesByMessageMap* classes_by_descriptor; }; @@ -98,6 +98,6 @@ bool InitMessageFactory(); } // namespace python } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_FACTORY_H__ diff --git a/python/google/protobuf/pyext/message_module.cc b/python/google/protobuf/pyext/message_module.cc index d90d9de35a84b..b5975f76c5628 100644 --- a/python/google/protobuf/pyext/message_module.cc +++ b/python/google/protobuf/pyext/message_module.cc @@ -28,34 +28,69 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include + +#include +#include #include +#include +#include + +namespace { + +// C++ API. Clients get at this via proto_api.h +struct ApiImplementation : google::protobuf::python::PyProto_API { + const google::protobuf::Message* GetMessagePointer(PyObject* msg) const override { + return google::protobuf::python::PyMessage_GetMessagePointer(msg); + } + google::protobuf::Message* GetMutableMessagePointer(PyObject* msg) const override { + return google::protobuf::python::PyMessage_GetMutableMessagePointer(msg); + } + const google::protobuf::DescriptorPool* GetDefaultDescriptorPool() const override { + return google::protobuf::python::GetDefaultDescriptorPool()->pool; + } + + google::protobuf::MessageFactory* GetDefaultMessageFactory() const override { + return google::protobuf::python::GetDefaultDescriptorPool() + ->py_message_factory->message_factory; + } + PyObject* NewMessage(const google::protobuf::Descriptor* descriptor, + PyObject* py_message_factory) const override { + return google::protobuf::python::PyMessage_New(descriptor, py_message_factory); + } + PyObject* NewMessageOwnedExternally( + google::protobuf::Message* msg, PyObject* py_message_factory) const override { + return google::protobuf::python::PyMessage_NewMessageOwnedExternally( + msg, py_message_factory); + } +}; + +} // namespace static const char module_docstring[] = -"python-proto2 is a module that can be used to enhance proto2 Python API\n" -"performance.\n" -"\n" -"It provides access to the protocol buffers C++ reflection API that\n" -"implements the basic protocol buffer functions."; + "python-proto2 is a module that can be used to enhance proto2 Python API\n" + "performance.\n" + "\n" + "It provides access to the protocol buffers C++ reflection API that\n" + "implements the basic protocol buffer functions."; static PyMethodDef ModuleMethods[] = { - {"SetAllowOversizeProtos", - (PyCFunction)google::protobuf::python::cmessage::SetAllowOversizeProtos, - METH_O, "Enable/disable oversize proto parsing."}, - { NULL, NULL} -}; + {"SetAllowOversizeProtos", + (PyCFunction)google::protobuf::python::cmessage::SetAllowOversizeProtos, METH_O, + "Enable/disable oversize proto parsing."}, + // DO NOT USE: For migration and testing only. + {NULL, NULL}}; #if PY_MAJOR_VERSION >= 3 -static struct PyModuleDef _module = { - PyModuleDef_HEAD_INIT, - "_message", - module_docstring, - -1, - ModuleMethods, /* m_methods */ - NULL, - NULL, - NULL, - NULL -}; +static struct PyModuleDef _module = {PyModuleDef_HEAD_INIT, + "_message", + module_docstring, + -1, + ModuleMethods, /* m_methods */ + NULL, + NULL, + NULL, + NULL}; #define INITFUNC PyInit__message #define INITFUNC_ERRORVAL NULL #else // Python 2 @@ -63,26 +98,35 @@ static struct PyModuleDef _module = { #define INITFUNC_ERRORVAL #endif -extern "C" { - PyMODINIT_FUNC INITFUNC(void) { - PyObject* m; +PyMODINIT_FUNC INITFUNC() { + PyObject* m; #if PY_MAJOR_VERSION >= 3 - m = PyModule_Create(&_module); + m = PyModule_Create(&_module); #else - m = Py_InitModule3("_message", ModuleMethods, - module_docstring); + m = Py_InitModule3("_message", ModuleMethods, module_docstring); #endif - if (m == NULL) { - return INITFUNC_ERRORVAL; - } + if (m == NULL) { + return INITFUNC_ERRORVAL; + } - if (!google::protobuf::python::InitProto2MessageModule(m)) { - Py_DECREF(m); - return INITFUNC_ERRORVAL; - } + if (!google::protobuf::python::InitProto2MessageModule(m)) { + Py_DECREF(m); + return INITFUNC_ERRORVAL; + } + + // Adds the C++ API + if (PyObject* api = PyCapsule_New( + new ApiImplementation(), google::protobuf::python::PyProtoAPICapsuleName(), + [](PyObject* o) { + delete (ApiImplementation*)PyCapsule_GetPointer( + o, google::protobuf::python::PyProtoAPICapsuleName()); + })) { + PyModule_AddObject(m, "proto_API", api); + } else { + return INITFUNC_ERRORVAL; + } #if PY_MAJOR_VERSION >= 3 - return m; + return m; #endif - } } diff --git a/python/google/protobuf/pyext/proto2_api_test.proto b/python/google/protobuf/pyext/proto2_api_test.proto index 18aecfb7d6202..1fd78e8402005 100644 --- a/python/google/protobuf/pyext/proto2_api_test.proto +++ b/python/google/protobuf/pyext/proto2_api_test.proto @@ -30,10 +30,10 @@ syntax = "proto2"; -import "google/protobuf/internal/cpp/proto1_api_test.proto"; - package google.protobuf.python.internal; +import "google/protobuf/internal/cpp/proto1_api_test.proto"; + message TestNestedProto1APIMessage { optional int32 a = 1; optional TestMessage.NestedMessage b = 2; diff --git a/python/google/protobuf/pyext/python.proto b/python/google/protobuf/pyext/python.proto index cce645d71ad9d..2e50df7401582 100644 --- a/python/google/protobuf/pyext/python.proto +++ b/python/google/protobuf/pyext/python.proto @@ -58,11 +58,11 @@ message ForeignMessage { repeated int32 d = 2; } -message TestAllExtensions { +message TestAllExtensions { // extension begin extensions 1 to max; -} +} // extension end -extend TestAllExtensions { +extend TestAllExtensions { // extension begin optional TestAllTypes.NestedMessage optional_nested_message_extension = 1; repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 2; -} +} // extension end diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc index 5ad71db598ba8..cbc0f9f8af9b2 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.cc +++ b/python/google/protobuf/pyext/repeated_composite_container.cc @@ -34,9 +34,6 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include @@ -49,6 +46,7 @@ #include #include #include +#include #if PY_MAJOR_VERSION >= 3 #define PyInt_Check PyLong_Check @@ -62,133 +60,109 @@ namespace python { namespace repeated_composite_container { -// TODO(tibell): We might also want to check: -// GOOGLE_CHECK_NOTNULL((self)->owner.get()); -#define GOOGLE_CHECK_ATTACHED(self) \ - do { \ - GOOGLE_CHECK_NOTNULL((self)->message); \ - GOOGLE_CHECK_NOTNULL((self)->parent_field_descriptor); \ - } while (0); - -#define GOOGLE_CHECK_RELEASED(self) \ - do { \ - GOOGLE_CHECK((self)->owner.get() == NULL); \ - GOOGLE_CHECK((self)->message == NULL); \ - GOOGLE_CHECK((self)->parent_field_descriptor == NULL); \ - GOOGLE_CHECK((self)->parent == NULL); \ - } while (0); - // --------------------------------------------------------------------- // len() -static Py_ssize_t Length(RepeatedCompositeContainer* self) { - Message* message = self->message; - if (message != NULL) { - return message->GetReflection()->FieldSize(*message, - self->parent_field_descriptor); - } else { - // The container has been released (i.e. by a call to Clear() or - // ClearField() on the parent) and thus there's no message. - return PyList_GET_SIZE(self->child_messages); - } -} +static Py_ssize_t Length(PyObject* pself) { + RepeatedCompositeContainer* self = + reinterpret_cast(pself); -// Returns 0 if successful; returns -1 and sets an exception if -// unsuccessful. -static int UpdateChildMessages(RepeatedCompositeContainer* self) { - if (self->message == NULL) - return 0; - - // A MergeFrom on a parent message could have caused extra messages to be - // added in the underlying protobuf so add them to our list. They can never - // be removed in such a way so there's no need to worry about that. - Py_ssize_t message_length = Length(self); - Py_ssize_t child_length = PyList_GET_SIZE(self->child_messages); - Message* message = self->message; - const Reflection* reflection = message->GetReflection(); - for (Py_ssize_t i = child_length; i < message_length; ++i) { - const Message& sub_message = reflection->GetRepeatedMessage( - *(self->message), self->parent_field_descriptor, i); - CMessage* cmsg = cmessage::NewEmptyMessage(self->child_message_class); - ScopedPyObjectPtr py_cmsg(reinterpret_cast(cmsg)); - if (cmsg == NULL) { - return -1; - } - cmsg->owner = self->owner; - cmsg->message = const_cast(&sub_message); - cmsg->parent = self->parent; - if (PyList_Append(self->child_messages, py_cmsg.get()) < 0) { - return -1; - } - } - return 0; + Message* message = self->parent->message; + return message->GetReflection()->FieldSize(*message, + self->parent_field_descriptor); } // --------------------------------------------------------------------- // add() -static PyObject* AddToAttached(RepeatedCompositeContainer* self, - PyObject* args, - PyObject* kwargs) { - GOOGLE_CHECK_ATTACHED(self); - - if (UpdateChildMessages(self) < 0) { - return NULL; - } - if (cmessage::AssureWritable(self->parent) == -1) - return NULL; - Message* message = self->message; +PyObject* Add(RepeatedCompositeContainer* self, PyObject* args, + PyObject* kwargs) { + if (cmessage::AssureWritable(self->parent) == -1) return nullptr; + Message* message = self->parent->message; Message* sub_message = message->GetReflection()->AddMessage( message, self->parent_field_descriptor, self->child_message_class->py_message_factory->message_factory); - CMessage* cmsg = cmessage::NewEmptyMessage(self->child_message_class); - if (cmsg == NULL) - return NULL; + CMessage* cmsg = self->parent->BuildSubMessageFromPointer( + self->parent_field_descriptor, sub_message, self->child_message_class); - cmsg->owner = self->owner; - cmsg->message = sub_message; - cmsg->parent = self->parent; if (cmessage::InitAttributes(cmsg, args, kwargs) < 0) { + message->GetReflection()->RemoveLast( + message, self->parent_field_descriptor); Py_DECREF(cmsg); - return NULL; + return nullptr; } - PyObject* py_cmsg = reinterpret_cast(cmsg); - if (PyList_Append(self->child_messages, py_cmsg) < 0) { - Py_DECREF(py_cmsg); - return NULL; + return cmsg->AsPyObject(); +} + +static PyObject* AddMethod(PyObject* self, PyObject* args, PyObject* kwargs) { + return Add(reinterpret_cast(self), args, kwargs); +} + +// --------------------------------------------------------------------- +// append() + +static PyObject* AddMessage(RepeatedCompositeContainer* self, PyObject* value) { + cmessage::AssureWritable(self->parent); + PyObject* py_cmsg; + Message* message = self->parent->message; + const Reflection* reflection = message->GetReflection(); + py_cmsg = Add(self, nullptr, nullptr); + if (py_cmsg == nullptr) return nullptr; + CMessage* cmsg = reinterpret_cast(py_cmsg); + if (ScopedPyObjectPtr(cmessage::MergeFrom(cmsg, value)) == nullptr) { + reflection->RemoveLast( + message, self->parent_field_descriptor); + Py_DECREF(cmsg); + return nullptr; } return py_cmsg; } -static PyObject* AddToReleased(RepeatedCompositeContainer* self, - PyObject* args, - PyObject* kwargs) { - GOOGLE_CHECK_RELEASED(self); - - // Create a new Message detached from the rest. - PyObject* py_cmsg = PyEval_CallObjectWithKeywords( - self->child_message_class->AsPyObject(), args, kwargs); - if (py_cmsg == NULL) - return NULL; - - if (PyList_Append(self->child_messages, py_cmsg) < 0) { - Py_DECREF(py_cmsg); - return NULL; +static PyObject* AppendMethod(PyObject* pself, PyObject* value) { + RepeatedCompositeContainer* self = + reinterpret_cast(pself); + ScopedPyObjectPtr py_cmsg(AddMessage(self, value)); + if (py_cmsg == nullptr) { + return nullptr; } - return py_cmsg; + + Py_RETURN_NONE; } -PyObject* Add(RepeatedCompositeContainer* self, - PyObject* args, - PyObject* kwargs) { - if (self->message == NULL) - return AddToReleased(self, args, kwargs); - else - return AddToAttached(self, args, kwargs); +// --------------------------------------------------------------------- +// insert() +static PyObject* Insert(PyObject* pself, PyObject* args) { + RepeatedCompositeContainer* self = + reinterpret_cast(pself); + + Py_ssize_t index; + PyObject* value; + if (!PyArg_ParseTuple(args, "nO", &index, &value)) { + return nullptr; + } + + ScopedPyObjectPtr py_cmsg(AddMessage(self, value)); + if (py_cmsg == nullptr) { + return nullptr; + } + + // Swap the element to right position. + Message* message = self->parent->message; + const Reflection* reflection = message->GetReflection(); + const FieldDescriptor* field_descriptor = self->parent_field_descriptor; + Py_ssize_t length = reflection->FieldSize(*message, field_descriptor) - 1; + Py_ssize_t end_index = index; + if (end_index < 0) end_index += length; + if (end_index < 0) end_index = 0; + for (Py_ssize_t i = length; i > end_index; i --) { + reflection->SwapElements(message, field_descriptor, i, i - 1); + } + + Py_RETURN_NONE; } // --------------------------------------------------------------------- @@ -196,142 +170,184 @@ PyObject* Add(RepeatedCompositeContainer* self, PyObject* Extend(RepeatedCompositeContainer* self, PyObject* value) { cmessage::AssureWritable(self->parent); - if (UpdateChildMessages(self) < 0) { - return NULL; - } ScopedPyObjectPtr iter(PyObject_GetIter(value)); - if (iter == NULL) { + if (iter == nullptr) { PyErr_SetString(PyExc_TypeError, "Value must be iterable"); - return NULL; + return nullptr; } ScopedPyObjectPtr next; - while ((next.reset(PyIter_Next(iter.get()))) != NULL) { - if (!PyObject_TypeCheck(next.get(), &CMessage_Type)) { + while ((next.reset(PyIter_Next(iter.get()))) != nullptr) { + if (!PyObject_TypeCheck(next.get(), CMessage_Type)) { PyErr_SetString(PyExc_TypeError, "Not a cmessage"); - return NULL; + return nullptr; } - ScopedPyObjectPtr new_message(Add(self, NULL, NULL)); - if (new_message == NULL) { - return NULL; + ScopedPyObjectPtr new_message(Add(self, nullptr, nullptr)); + if (new_message == nullptr) { + return nullptr; } CMessage* new_cmessage = reinterpret_cast(new_message.get()); if (ScopedPyObjectPtr(cmessage::MergeFrom(new_cmessage, next.get())) == - NULL) { - return NULL; + nullptr) { + return nullptr; } } if (PyErr_Occurred()) { - return NULL; + return nullptr; } Py_RETURN_NONE; } +static PyObject* ExtendMethod(PyObject* self, PyObject* value) { + return Extend(reinterpret_cast(self), value); +} + PyObject* MergeFrom(RepeatedCompositeContainer* self, PyObject* other) { - if (UpdateChildMessages(self) < 0) { - return NULL; - } return Extend(self, other); } -PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* slice) { - if (UpdateChildMessages(self) < 0) { - return NULL; +static PyObject* MergeFromMethod(PyObject* self, PyObject* other) { + return MergeFrom(reinterpret_cast(self), other); +} + +// This function does not check the bounds. +static PyObject* GetItem(RepeatedCompositeContainer* self, Py_ssize_t index, + Py_ssize_t length = -1) { + if (length == -1) { + Message* message = self->parent->message; + const Reflection* reflection = message->GetReflection(); + length = reflection->FieldSize(*message, self->parent_field_descriptor); + } + if (index < 0 || index >= length) { + PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index); + return nullptr; + } + Message* message = self->parent->message; + Message* sub_message = message->GetReflection()->MutableRepeatedMessage( + message, self->parent_field_descriptor, index); + return self->parent + ->BuildSubMessageFromPointer(self->parent_field_descriptor, sub_message, + self->child_message_class) + ->AsPyObject(); +} + +PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* item) { + Message* message = self->parent->message; + const Reflection* reflection = message->GetReflection(); + Py_ssize_t length = + reflection->FieldSize(*message, self->parent_field_descriptor); + + if (PyIndex_Check(item)) { + Py_ssize_t index; + index = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (index == -1 && PyErr_Occurred()) return nullptr; + if (index < 0) index += length; + return GetItem(self, index, length); + } else if (PySlice_Check(item)) { + Py_ssize_t from, to, step, slicelength, cur, i; + PyObject* result; + +#if PY_MAJOR_VERSION >= 3 + if (PySlice_GetIndicesEx(item, + length, &from, &to, &step, &slicelength) == -1) { +#else + if (PySlice_GetIndicesEx(reinterpret_cast(item), + length, &from, &to, &step, &slicelength) == -1) { +#endif + return nullptr; + } + + if (slicelength <= 0) { + return PyList_New(0); + } else { + result = PyList_New(slicelength); + if (!result) return nullptr; + + for (cur = from, i = 0; i < slicelength; cur += step, i++) { + PyList_SET_ITEM(result, i, GetItem(self, cur, length)); + } + + return result; + } + } else { + PyErr_Format(PyExc_TypeError, "indices must be integers, not %.200s", + item->ob_type->tp_name); + return nullptr; } - // Just forward the call to the subscript-handling function of the - // list containing the child messages. - return PyObject_GetItem(self->child_messages, slice); +} + +static PyObject* SubscriptMethod(PyObject* self, PyObject* slice) { + return Subscript(reinterpret_cast(self), slice); } int AssignSubscript(RepeatedCompositeContainer* self, PyObject* slice, PyObject* value) { - if (UpdateChildMessages(self) < 0) { - return -1; - } - if (value != NULL) { + if (value != nullptr) { PyErr_SetString(PyExc_TypeError, "does not support assignment"); return -1; } - // Delete from the underlying Message, if any. - if (self->parent != NULL) { - if (cmessage::InternalDeleteRepeatedField(self->parent, - self->parent_field_descriptor, - slice, - self->child_messages) < 0) { - return -1; + return cmessage::DeleteRepeatedField(self->parent, + self->parent_field_descriptor, slice); +} + +static int AssignSubscriptMethod(PyObject* self, PyObject* slice, + PyObject* value) { + return AssignSubscript(reinterpret_cast(self), + slice, value); +} + +static PyObject* Remove(PyObject* pself, PyObject* value) { + RepeatedCompositeContainer* self = + reinterpret_cast(pself); + Py_ssize_t len = Length(reinterpret_cast(self)); + + for (Py_ssize_t i = 0; i < len; i++) { + ScopedPyObjectPtr item(GetItem(self, i, len)); + if (item == nullptr) { + return nullptr; } - } else { - Py_ssize_t from; - Py_ssize_t to; - Py_ssize_t step; - Py_ssize_t length = Length(self); - Py_ssize_t slicelength; - if (PySlice_Check(slice)) { -#if PY_MAJOR_VERSION >= 3 - if (PySlice_GetIndicesEx(slice, - length, &from, &to, &step, &slicelength) == -1) { -#else - if (PySlice_GetIndicesEx(reinterpret_cast(slice), - length, &from, &to, &step, &slicelength) == -1) { -#endif - return -1; - } - return PySequence_DelSlice(self->child_messages, from, to); - } else if (PyInt_Check(slice) || PyLong_Check(slice)) { - from = to = PyLong_AsLong(slice); - if (from < 0) { - from = to = length + from; + int result = PyObject_RichCompareBool(item.get(), value, Py_EQ); + if (result < 0) { + return nullptr; + } + if (result) { + ScopedPyObjectPtr py_index(PyLong_FromSsize_t(i)); + if (AssignSubscript(self, py_index.get(), nullptr) < 0) { + return nullptr; } - return PySequence_DelItem(self->child_messages, from); + Py_RETURN_NONE; } } - - return 0; + PyErr_SetString(PyExc_ValueError, "Item to delete not in list"); + return nullptr; } -static PyObject* Remove(RepeatedCompositeContainer* self, PyObject* value) { - if (UpdateChildMessages(self) < 0) { - return NULL; - } - Py_ssize_t index = PySequence_Index(self->child_messages, value); - if (index == -1) { - return NULL; - } - ScopedPyObjectPtr py_index(PyLong_FromLong(index)); - if (AssignSubscript(self, py_index.get(), NULL) < 0) { - return NULL; - } - Py_RETURN_NONE; -} +static PyObject* RichCompare(PyObject* pself, PyObject* other, int opid) { + RepeatedCompositeContainer* self = + reinterpret_cast(pself); -static PyObject* RichCompare(RepeatedCompositeContainer* self, - PyObject* other, - int opid) { - if (UpdateChildMessages(self) < 0) { - return NULL; - } if (!PyObject_TypeCheck(other, &RepeatedCompositeContainer_Type)) { PyErr_SetString(PyExc_TypeError, "Can only compare repeated composite fields " "against other repeated composite fields."); - return NULL; + return nullptr; } if (opid == Py_EQ || opid == Py_NE) { // TODO(anuraag): Don't make new lists just for this... - ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); - if (full_slice == NULL) { - return NULL; + ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr)); + if (full_slice == nullptr) { + return nullptr; } ScopedPyObjectPtr list(Subscript(self, full_slice.get())); - if (list == NULL) { - return NULL; + if (list == nullptr) { + return nullptr; } ScopedPyObjectPtr other_list( Subscript(reinterpret_cast(other), full_slice.get())); - if (other_list == NULL) { - return NULL; + if (other_list == nullptr) { + return nullptr; } return PyObject_RichCompare(list.get(), other_list.get(), opid); } else { @@ -340,14 +356,15 @@ static PyObject* RichCompare(RepeatedCompositeContainer* self, } } -static PyObject* ToStr(RepeatedCompositeContainer* self) { - ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); - if (full_slice == NULL) { - return NULL; +static PyObject* ToStr(PyObject* pself) { + ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr)); + if (full_slice == nullptr) { + return nullptr; } - ScopedPyObjectPtr list(Subscript(self, full_slice.get())); - if (list == NULL) { - return NULL; + ScopedPyObjectPtr list(Subscript( + reinterpret_cast(pself), full_slice.get())); + if (list == nullptr) { + return nullptr; } return PyObject_Repr(list.get()); } @@ -355,11 +372,12 @@ static PyObject* ToStr(RepeatedCompositeContainer* self) { // --------------------------------------------------------------------- // sort() -static void ReorderAttached(RepeatedCompositeContainer* self) { - Message* message = self->message; +static void ReorderAttached(RepeatedCompositeContainer* self, + PyObject* child_list) { + Message* message = self->parent->message; const Reflection* reflection = message->GetReflection(); const FieldDescriptor* descriptor = self->parent_field_descriptor; - const Py_ssize_t length = Length(self); + const Py_ssize_t length = Length(reinterpret_cast(self)); // Since Python protobuf objects are never arena-allocated, adding and // removing message pointers to the underlying array is just updating @@ -369,7 +387,7 @@ static void ReorderAttached(RepeatedCompositeContainer* self) { for (Py_ssize_t i = 0; i < length; ++i) { CMessage* py_cmsg = reinterpret_cast( - PyList_GET_ITEM(self->child_messages, i)); + PyList_GET_ITEM(child_list, i)); reflection->AddAllocatedMessage(message, descriptor, py_cmsg->message); } } @@ -379,25 +397,28 @@ static void ReorderAttached(RepeatedCompositeContainer* self) { static int SortPythonMessages(RepeatedCompositeContainer* self, PyObject* args, PyObject* kwds) { - ScopedPyObjectPtr m(PyObject_GetAttrString(self->child_messages, "sort")); - if (m == NULL) + ScopedPyObjectPtr child_list( + PySequence_List(reinterpret_cast(self))); + if (child_list == nullptr) { return -1; - if (ScopedPyObjectPtr(PyObject_Call(m.get(), args, kwds)) == NULL) - return -1; - if (self->message != NULL) { - ReorderAttached(self); } + ScopedPyObjectPtr m(PyObject_GetAttrString(child_list.get(), "sort")); + if (m == nullptr) return -1; + if (ScopedPyObjectPtr(PyObject_Call(m.get(), args, kwds)) == nullptr) + return -1; + ReorderAttached(self, child_list.get()); return 0; } -static PyObject* Sort(RepeatedCompositeContainer* self, - PyObject* args, - PyObject* kwds) { +static PyObject* Sort(PyObject* pself, PyObject* args, PyObject* kwds) { + RepeatedCompositeContainer* self = + reinterpret_cast(pself); + // Support the old sort_function argument for backwards // compatibility. - if (kwds != NULL) { + if (kwds != nullptr) { PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function"); - if (sort_func != NULL) { + if (sort_func != nullptr) { // Must set before deleting as sort_func is a borrowed reference // and kwds might be the only thing keeping it alive. PyDict_SetItemString(kwds, "cmp", sort_func); @@ -405,252 +426,182 @@ static PyObject* Sort(RepeatedCompositeContainer* self, } } - if (UpdateChildMessages(self) < 0) { - return NULL; - } if (SortPythonMessages(self, args, kwds) < 0) { - return NULL; + return nullptr; } Py_RETURN_NONE; } // --------------------------------------------------------------------- +// reverse() -static PyObject* Item(RepeatedCompositeContainer* self, Py_ssize_t index) { - if (UpdateChildMessages(self) < 0) { - return NULL; - } - Py_ssize_t length = Length(self); - if (index < 0) { - index = length + index; - } - PyObject* item = PyList_GetItem(self->child_messages, index); - if (item == NULL) { - return NULL; +// Returns 0 if successful; returns -1 and sets an exception if +// unsuccessful. +static int ReversePythonMessages(RepeatedCompositeContainer* self) { + ScopedPyObjectPtr child_list( + PySequence_List(reinterpret_cast(self))); + if (child_list == nullptr) { + return -1; } - Py_INCREF(item); - return item; + if (ScopedPyObjectPtr( + PyObject_CallMethod(child_list.get(), "reverse", nullptr)) == nullptr) + return -1; + ReorderAttached(self, child_list.get()); + return 0; } -static PyObject* Pop(RepeatedCompositeContainer* self, - PyObject* args) { - Py_ssize_t index = -1; - if (!PyArg_ParseTuple(args, "|n", &index)) { - return NULL; - } - PyObject* item = Item(self, index); - if (item == NULL) { - PyErr_Format(PyExc_IndexError, - "list index (%zd) out of range", - index); - return NULL; - } - ScopedPyObjectPtr py_index(PyLong_FromSsize_t(index)); - if (AssignSubscript(self, py_index.get(), NULL) < 0) { - return NULL; +static PyObject* Reverse(PyObject* pself) { + RepeatedCompositeContainer* self = + reinterpret_cast(pself); + + if (ReversePythonMessages(self) < 0) { + return nullptr; } - return item; + Py_RETURN_NONE; } -// Release field of parent message and transfer the ownership to target. -void ReleaseLastTo(CMessage* parent, - const FieldDescriptor* field, - CMessage* target) { - GOOGLE_CHECK_NOTNULL(parent); - GOOGLE_CHECK_NOTNULL(field); - GOOGLE_CHECK_NOTNULL(target); - - shared_ptr released_message( - parent->message->GetReflection()->ReleaseLast(parent->message, field)); - // TODO(tibell): Deal with proto1. - - target->parent = NULL; - target->parent_field_descriptor = NULL; - target->message = released_message.get(); - target->read_only = false; - cmessage::SetOwner(target, released_message); +// --------------------------------------------------------------------- + +static PyObject* Item(PyObject* pself, Py_ssize_t index) { + RepeatedCompositeContainer* self = + reinterpret_cast(pself); + return GetItem(self, index); } -// Called to release a container using -// ClearField('container_field_name') on the parent. -int Release(RepeatedCompositeContainer* self) { - if (UpdateChildMessages(self) < 0) { - PyErr_WriteUnraisable(PyBytes_FromString("Failed to update released " - "messages")); - return -1; - } +static PyObject* Pop(PyObject* pself, PyObject* args) { + RepeatedCompositeContainer* self = + reinterpret_cast(pself); - Message* message = self->message; - const FieldDescriptor* field = self->parent_field_descriptor; - - // The reflection API only lets us release the last message in a - // repeated field. Therefore we iterate through the children - // starting with the last one. - const Py_ssize_t size = PyList_GET_SIZE(self->child_messages); - GOOGLE_DCHECK_EQ(size, message->GetReflection()->FieldSize(*message, field)); - for (Py_ssize_t i = size - 1; i >= 0; --i) { - CMessage* child_cmessage = reinterpret_cast( - PyList_GET_ITEM(self->child_messages, i)); - ReleaseLastTo(self->parent, field, child_cmessage); + Py_ssize_t index = -1; + if (!PyArg_ParseTuple(args, "|n", &index)) { + return nullptr; } - - // Detach from containing message. - self->parent = NULL; - self->parent_field_descriptor = NULL; - self->message = NULL; - self->owner.reset(); - - return 0; -} - -PyObject* DeepCopy(RepeatedCompositeContainer* self, PyObject* arg) { - ScopedPyObjectPtr cloneObj( - PyType_GenericAlloc(&RepeatedCompositeContainer_Type, 0)); - if (cloneObj == NULL) { - return NULL; + Py_ssize_t length = Length(pself); + if (index < 0) index += length; + PyObject* item = GetItem(self, index, length); + if (item == nullptr) { + return nullptr; } - RepeatedCompositeContainer* clone = - reinterpret_cast(cloneObj.get()); - - Message* new_message = self->message->New(); - clone->parent = NULL; - clone->parent_field_descriptor = self->parent_field_descriptor; - clone->message = new_message; - clone->owner.reset(new_message); - Py_INCREF(self->child_message_class); - clone->child_message_class = self->child_message_class; - clone->child_messages = PyList_New(0); - - new_message->GetReflection() - ->GetMutableRepeatedFieldRef(new_message, - self->parent_field_descriptor) - .MergeFrom(self->message->GetReflection()->GetRepeatedFieldRef( - *self->message, self->parent_field_descriptor)); - return cloneObj.release(); + ScopedPyObjectPtr py_index(PyLong_FromSsize_t(index)); + if (AssignSubscript(self, py_index.get(), nullptr) < 0) { + return nullptr; + } + return item; } -int SetOwner(RepeatedCompositeContainer* self, - const shared_ptr& new_owner) { - GOOGLE_CHECK_ATTACHED(self); - - self->owner = new_owner; - const Py_ssize_t n = PyList_GET_SIZE(self->child_messages); - for (Py_ssize_t i = 0; i < n; ++i) { - PyObject* msg = PyList_GET_ITEM(self->child_messages, i); - if (cmessage::SetOwner(reinterpret_cast(msg), new_owner) == -1) { - return -1; - } - } - return 0; +PyObject* DeepCopy(PyObject* pself, PyObject* arg) { + return reinterpret_cast(pself)->DeepCopy(); } // The private constructor of RepeatedCompositeContainer objects. -PyObject *NewContainer( +RepeatedCompositeContainer *NewContainer( CMessage* parent, const FieldDescriptor* parent_field_descriptor, - CMessageClass* concrete_class) { + CMessageClass* child_message_class) { if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) { - return NULL; + return nullptr; } RepeatedCompositeContainer* self = reinterpret_cast( PyType_GenericAlloc(&RepeatedCompositeContainer_Type, 0)); - if (self == NULL) { - return NULL; + if (self == nullptr) { + return nullptr; } - self->message = parent->message; + Py_INCREF(parent); self->parent = parent; self->parent_field_descriptor = parent_field_descriptor; - self->owner = parent->owner; - Py_INCREF(concrete_class); - self->child_message_class = concrete_class; - self->child_messages = PyList_New(0); - - return reinterpret_cast(self); + Py_INCREF(child_message_class); + self->child_message_class = child_message_class; + return self; } -static void Dealloc(RepeatedCompositeContainer* self) { - Py_CLEAR(self->child_messages); +static void Dealloc(PyObject* pself) { + RepeatedCompositeContainer* self = + reinterpret_cast(pself); + self->RemoveFromParentCache(); Py_CLEAR(self->child_message_class); - // TODO(tibell): Do we need to call delete on these objects to make - // sure their destructors are called? - self->owner.reset(); - - Py_TYPE(self)->tp_free(reinterpret_cast(self)); + Py_TYPE(self)->tp_free(pself); } static PySequenceMethods SqMethods = { - (lenfunc)Length, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - (ssizeargfunc)Item /* sq_item */ + Length, /* sq_length */ + nullptr, /* sq_concat */ + nullptr, /* sq_repeat */ + Item /* sq_item */ }; static PyMappingMethods MpMethods = { - (lenfunc)Length, /* mp_length */ - (binaryfunc)Subscript, /* mp_subscript */ - (objobjargproc)AssignSubscript,/* mp_ass_subscript */ + Length, /* mp_length */ + SubscriptMethod, /* mp_subscript */ + AssignSubscriptMethod, /* mp_ass_subscript */ }; static PyMethodDef Methods[] = { - { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, - "Makes a deep copy of the class." }, - { "add", (PyCFunction) Add, METH_VARARGS | METH_KEYWORDS, - "Adds an object to the repeated container." }, - { "extend", (PyCFunction) Extend, METH_O, - "Adds objects to the repeated container." }, - { "pop", (PyCFunction)Pop, METH_VARARGS, - "Removes an object from the repeated container and returns it." }, - { "remove", (PyCFunction) Remove, METH_O, - "Removes an object from the repeated container." }, - { "sort", (PyCFunction) Sort, METH_VARARGS | METH_KEYWORDS, - "Sorts the repeated container." }, - { "MergeFrom", (PyCFunction) MergeFrom, METH_O, - "Adds objects to the repeated container." }, - { NULL, NULL } -}; + {"__deepcopy__", DeepCopy, METH_VARARGS, "Makes a deep copy of the class."}, + {"add", reinterpret_cast(AddMethod), + METH_VARARGS | METH_KEYWORDS, "Adds an object to the repeated container."}, + {"append", AppendMethod, METH_O, + "Appends a message to the end of the repeated container."}, + {"insert", Insert, METH_VARARGS, + "Inserts a message before the specified index."}, + {"extend", ExtendMethod, METH_O, "Adds objects to the repeated container."}, + {"pop", Pop, METH_VARARGS, + "Removes an object from the repeated container and returns it."}, + {"remove", Remove, METH_O, + "Removes an object from the repeated container."}, + {"sort", reinterpret_cast(Sort), METH_VARARGS | METH_KEYWORDS, + "Sorts the repeated container."}, + {"reverse", reinterpret_cast(Reverse), METH_NOARGS, + "Reverses elements order of the repeated container."}, + {"MergeFrom", MergeFromMethod, METH_O, + "Adds objects to the repeated container."}, + {nullptr, nullptr}}; } // namespace repeated_composite_container PyTypeObject RepeatedCompositeContainer_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - FULL_MODULE_NAME ".RepeatedCompositeContainer", // tp_name - sizeof(RepeatedCompositeContainer), // tp_basicsize - 0, // tp_itemsize - (destructor)repeated_composite_container::Dealloc, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - (reprfunc)repeated_composite_container::ToStr, // tp_repr - 0, // tp_as_number - &repeated_composite_container::SqMethods, // tp_as_sequence - &repeated_composite_container::MpMethods, // tp_as_mapping - PyObject_HashNotImplemented, // tp_hash - 0, // tp_call - 0, // tp_str - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "A Repeated scalar container", // tp_doc - 0, // tp_traverse - 0, // tp_clear - (richcmpfunc)repeated_composite_container::RichCompare, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - repeated_composite_container::Methods, // tp_methods - 0, // tp_members - 0, // tp_getset - 0, // tp_base - 0, // tp_dict - 0, // tp_descr_get - 0, // tp_descr_set - 0, // tp_dictoffset - 0, // tp_init + PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME + ".RepeatedCompositeContainer", // tp_name + sizeof(RepeatedCompositeContainer), // tp_basicsize + 0, // tp_itemsize + repeated_composite_container::Dealloc, // tp_dealloc +#if PY_VERSION_HEX >= 0x03080000 + 0, // tp_vectorcall_offset +#else + nullptr, // tp_print +#endif + nullptr, // tp_getattr + nullptr, // tp_setattr + nullptr, // tp_compare + repeated_composite_container::ToStr, // tp_repr + nullptr, // tp_as_number + &repeated_composite_container::SqMethods, // tp_as_sequence + &repeated_composite_container::MpMethods, // tp_as_mapping + PyObject_HashNotImplemented, // tp_hash + nullptr, // tp_call + nullptr, // tp_str + nullptr, // tp_getattro + nullptr, // tp_setattro + nullptr, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "A Repeated scalar container", // tp_doc + nullptr, // tp_traverse + nullptr, // tp_clear + repeated_composite_container::RichCompare, // tp_richcompare + 0, // tp_weaklistoffset + nullptr, // tp_iter + nullptr, // tp_iternext + repeated_composite_container::Methods, // tp_methods + nullptr, // tp_members + nullptr, // tp_getset + nullptr, // tp_base + nullptr, // tp_dict + nullptr, // tp_descr_get + nullptr, // tp_descr_set + 0, // tp_dictoffset + nullptr, // tp_init }; } // namespace python diff --git a/python/google/protobuf/pyext/repeated_composite_container.h b/python/google/protobuf/pyext/repeated_composite_container.h index a7b56b61b363d..e241827ef53be 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.h +++ b/python/google/protobuf/pyext/repeated_composite_container.h @@ -37,69 +37,26 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include +#include + namespace google { namespace protobuf { class FieldDescriptor; class Message; -#ifdef _SHARED_PTR_H -using std::shared_ptr; -#else -using internal::shared_ptr; -#endif - namespace python { -struct CMessage; struct CMessageClass; -// A RepeatedCompositeContainer can be in one of two states: attached -// or released. -// -// When in the attached state all modifications to the container are -// done both on the 'message' and on the 'child_messages' -// list. In this state all Messages referred to by the children in -// 'child_messages' are owner by the 'owner'. -// -// When in the released state 'message', 'owner', 'parent', and -// 'parent_field_descriptor' are NULL. -typedef struct RepeatedCompositeContainer { - PyObject_HEAD; - - // This is the top-level C++ Message object that owns the whole - // proto tree. Every Python RepeatedCompositeContainer holds a - // reference to it in order to keep it alive as long as there's a - // Python object that references any part of the tree. - shared_ptr owner; - - // Weak reference to parent object. May be NULL. Used to make sure - // the parent is writable before modifying the - // RepeatedCompositeContainer. - CMessage* parent; - - // A descriptor used to modify the underlying 'message'. - // The pointer is owned by the global DescriptorPool. - const FieldDescriptor* parent_field_descriptor; - - // Pointer to the C++ Message that contains this container. The - // RepeatedCompositeContainer does not own this pointer. - // - // If NULL, this message has been released from its parent (by - // calling Clear() or ClearField() on the parent. - Message* message; - +// A RepeatedCompositeContainer always has a parent message. +// The parent message also caches reference to items of the container. +typedef struct RepeatedCompositeContainer : public ContainerBase { // The type used to create new child messages. CMessageClass* child_message_class; - - // A list of child messages. - PyObject* child_messages; } RepeatedCompositeContainer; extern PyTypeObject RepeatedCompositeContainer_Type; @@ -108,7 +65,7 @@ namespace repeated_composite_container { // Builds a RepeatedCompositeContainer object, from a parent message and a // field descriptor. -PyObject *NewContainer( +RepeatedCompositeContainer* NewContainer( CMessage* parent, const FieldDescriptor* parent_field_descriptor, CMessageClass *child_message_class); @@ -147,33 +104,9 @@ PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* slice); int AssignSubscript(RepeatedCompositeContainer* self, PyObject* slice, PyObject* value); - -// Releases the messages in the container to the given message. -// -// Returns 0 on success, -1 on failure. -int ReleaseToMessage(RepeatedCompositeContainer* self, Message* new_message); - -// Releases the messages in the container to a new message. -// -// Returns 0 on success, -1 on failure. -int Release(RepeatedCompositeContainer* self); - -// Returns 0 on success, -1 on failure. -int SetOwner(RepeatedCompositeContainer* self, - const shared_ptr& new_owner); - -// Removes the last element of the repeated message field 'field' on -// the Message 'parent', and transfers the ownership of the released -// Message to 'target'. -// -// Corresponds to reflection api method ReleaseMessage. -void ReleaseLastTo(CMessage* parent, - const FieldDescriptor* field, - CMessage* target); - } // namespace repeated_composite_container } // namespace python } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_COMPOSITE_CONTAINER_H__ diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc index 549988009c6b8..5a5c4db16e29c 100644 --- a/python/google/protobuf/pyext/repeated_scalar_container.cc +++ b/python/google/protobuf/pyext/repeated_scalar_container.cc @@ -34,9 +34,6 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include @@ -49,13 +46,13 @@ #include #if PY_MAJOR_VERSION >= 3 - #define PyInt_FromLong PyLong_FromLong - #if PY_VERSION_HEX < 0x03030000 - #error "Python 3.0 - 3.2 are not supported." - #else - #define PyString_AsString(ob) \ - (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob)) - #endif +#define PyInt_FromLong PyLong_FromLong +#if PY_VERSION_HEX < 0x03030000 +#error "Python 3.0 - 3.2 are not supported." +#else +#define PyString_AsString(ob) \ + (PyUnicode_Check(ob) ? PyUnicode_AsUTF8(ob) : PyBytes_AsString(ob)) +#endif #endif namespace google { @@ -64,30 +61,33 @@ namespace python { namespace repeated_scalar_container { -static int InternalAssignRepeatedField( - RepeatedScalarContainer* self, PyObject* list) { - self->message->GetReflection()->ClearField(self->message, - self->parent_field_descriptor); +static int InternalAssignRepeatedField(RepeatedScalarContainer* self, + PyObject* list) { + Message* message = self->parent->message; + message->GetReflection()->ClearField(message, self->parent_field_descriptor); for (Py_ssize_t i = 0; i < PyList_GET_SIZE(list); ++i) { PyObject* value = PyList_GET_ITEM(list, i); - if (ScopedPyObjectPtr(Append(self, value)) == NULL) { + if (ScopedPyObjectPtr(Append(self, value)) == nullptr) { return -1; } } return 0; } -static Py_ssize_t Len(RepeatedScalarContainer* self) { - Message* message = self->message; +static Py_ssize_t Len(PyObject* pself) { + RepeatedScalarContainer* self = + reinterpret_cast(pself); + Message* message = self->parent->message; return message->GetReflection()->FieldSize(*message, self->parent_field_descriptor); } -static int AssignItem(RepeatedScalarContainer* self, - Py_ssize_t index, - PyObject* arg) { +static int AssignItem(PyObject* pself, Py_ssize_t index, PyObject* arg) { + RepeatedScalarContainer* self = + reinterpret_cast(pself); + cmessage::AssureWritable(self->parent); - Message* message = self->message; + Message* message = self->parent->message; const FieldDescriptor* field_descriptor = self->parent_field_descriptor; const Reflection* reflection = message->GetReflection(); @@ -96,16 +96,15 @@ static int AssignItem(RepeatedScalarContainer* self, index = field_size + index; } if (index < 0 || index >= field_size) { - PyErr_Format(PyExc_IndexError, - "list assignment index (%d) out of range", + PyErr_Format(PyExc_IndexError, "list assignment index (%d) out of range", static_cast(index)); return -1; } - if (arg == NULL) { + if (arg == nullptr) { ScopedPyObjectPtr py_index(PyLong_FromLong(index)); - return cmessage::InternalDeleteRepeatedField(self->parent, field_descriptor, - py_index.get(), NULL); + return cmessage::DeleteRepeatedField(self->parent, field_descriptor, + py_index.get()); } if (PySequence_Check(arg) && !(PyBytes_Check(arg) || PyUnicode_Check(arg))) { @@ -150,8 +149,8 @@ static int AssignItem(RepeatedScalarContainer* self, break; } case FieldDescriptor::CPPTYPE_STRING: { - if (!CheckAndSetString( - arg, message, field_descriptor, reflection, false, index)) { + if (!CheckAndSetString(arg, message, field_descriptor, reflection, false, + index)) { return -1; } break; @@ -165,12 +164,12 @@ static int AssignItem(RepeatedScalarContainer* self, const EnumDescriptor* enum_descriptor = field_descriptor->enum_type(); const EnumValueDescriptor* enum_value = enum_descriptor->FindValueByNumber(value); - if (enum_value != NULL) { + if (enum_value != nullptr) { reflection->SetRepeatedEnum(message, field_descriptor, index, enum_value); } else { ScopedPyObjectPtr s(PyObject_Str(arg)); - if (s != NULL) { + if (s != nullptr) { PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", PyString_AsString(s.get())); } @@ -180,16 +179,19 @@ static int AssignItem(RepeatedScalarContainer* self, break; } default: - PyErr_Format( - PyExc_SystemError, "Adding value to a field of unknown type %d", - field_descriptor->cpp_type()); + PyErr_Format(PyExc_SystemError, + "Adding value to a field of unknown type %d", + field_descriptor->cpp_type()); return -1; } return 0; } -static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) { - Message* message = self->message; +static PyObject* Item(PyObject* pself, Py_ssize_t index) { + RepeatedScalarContainer* self = + reinterpret_cast(pself); + + Message* message = self->parent->message; const FieldDescriptor* field_descriptor = self->parent_field_descriptor; const Reflection* reflection = message->GetReflection(); @@ -198,96 +200,78 @@ static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) { index = field_size + index; } if (index < 0 || index >= field_size) { - PyErr_Format(PyExc_IndexError, - "list index (%zd) out of range", - index); - return NULL; + PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index); + return nullptr; } - PyObject* result = NULL; + PyObject* result = nullptr; switch (field_descriptor->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: { - int32 value = reflection->GetRepeatedInt32( - *message, field_descriptor, index); + int32 value = + reflection->GetRepeatedInt32(*message, field_descriptor, index); result = PyInt_FromLong(value); break; } case FieldDescriptor::CPPTYPE_INT64: { - int64 value = reflection->GetRepeatedInt64( - *message, field_descriptor, index); + int64 value = + reflection->GetRepeatedInt64(*message, field_descriptor, index); result = PyLong_FromLongLong(value); break; } case FieldDescriptor::CPPTYPE_UINT32: { - uint32 value = reflection->GetRepeatedUInt32( - *message, field_descriptor, index); + uint32 value = + reflection->GetRepeatedUInt32(*message, field_descriptor, index); result = PyLong_FromLongLong(value); break; } case FieldDescriptor::CPPTYPE_UINT64: { - uint64 value = reflection->GetRepeatedUInt64( - *message, field_descriptor, index); + uint64 value = + reflection->GetRepeatedUInt64(*message, field_descriptor, index); result = PyLong_FromUnsignedLongLong(value); break; } case FieldDescriptor::CPPTYPE_FLOAT: { - float value = reflection->GetRepeatedFloat( - *message, field_descriptor, index); + float value = + reflection->GetRepeatedFloat(*message, field_descriptor, index); result = PyFloat_FromDouble(value); break; } case FieldDescriptor::CPPTYPE_DOUBLE: { - double value = reflection->GetRepeatedDouble( - *message, field_descriptor, index); + double value = + reflection->GetRepeatedDouble(*message, field_descriptor, index); result = PyFloat_FromDouble(value); break; } case FieldDescriptor::CPPTYPE_BOOL: { - bool value = reflection->GetRepeatedBool( - *message, field_descriptor, index); + bool value = + reflection->GetRepeatedBool(*message, field_descriptor, index); result = PyBool_FromLong(value ? 1 : 0); break; } case FieldDescriptor::CPPTYPE_ENUM: { const EnumValueDescriptor* enum_value = - message->GetReflection()->GetRepeatedEnum( - *message, field_descriptor, index); + message->GetReflection()->GetRepeatedEnum(*message, field_descriptor, + index); result = PyInt_FromLong(enum_value->number()); break; } case FieldDescriptor::CPPTYPE_STRING: { - string value = reflection->GetRepeatedString( - *message, field_descriptor, index); + std::string scratch; + const std::string& value = reflection->GetRepeatedStringReference( + *message, field_descriptor, index, &scratch); result = ToStringObject(field_descriptor, value); break; } - case FieldDescriptor::CPPTYPE_MESSAGE: { - PyObject* py_cmsg = PyObject_CallObject(reinterpret_cast( - &CMessage_Type), NULL); - if (py_cmsg == NULL) { - return NULL; - } - CMessage* cmsg = reinterpret_cast(py_cmsg); - const Message& msg = reflection->GetRepeatedMessage( - *message, field_descriptor, index); - cmsg->owner = self->owner; - cmsg->parent = self->parent; - cmsg->message = const_cast(&msg); - cmsg->read_only = false; - result = reinterpret_cast(py_cmsg); - break; - } default: - PyErr_Format( - PyExc_SystemError, - "Getting value from a repeated field of unknown type %d", - field_descriptor->cpp_type()); + PyErr_Format(PyExc_SystemError, + "Getting value from a repeated field of unknown type %d", + field_descriptor->cpp_type()); } return result; } -static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) { +static PyObject* Subscript(PyObject* pself, PyObject* slice) { Py_ssize_t from; Py_ssize_t to; Py_ssize_t step; @@ -299,33 +283,32 @@ static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) { from = to = PyInt_AsLong(slice); } else // NOLINT #endif - if (PyLong_Check(slice)) { + if (PyLong_Check(slice)) { from = to = PyLong_AsLong(slice); } else if (PySlice_Check(slice)) { - length = Len(self); + length = Len(pself); #if PY_MAJOR_VERSION >= 3 - if (PySlice_GetIndicesEx(slice, - length, &from, &to, &step, &slicelength) == -1) { + if (PySlice_GetIndicesEx(slice, length, &from, &to, &step, &slicelength) == + -1) { #else - if (PySlice_GetIndicesEx(reinterpret_cast(slice), - length, &from, &to, &step, &slicelength) == -1) { - + if (PySlice_GetIndicesEx(reinterpret_cast(slice), length, + &from, &to, &step, &slicelength) == -1) { #endif - return NULL; + return nullptr; } return_list = true; } else { PyErr_SetString(PyExc_TypeError, "list indices must be integers"); - return NULL; + return nullptr; } if (!return_list) { - return Item(self, from); + return Item(pself, from); } PyObject* list = PyList_New(0); - if (list == NULL) { - return NULL; + if (list == nullptr) { + return nullptr; } if (from <= to) { if (step < 0) { @@ -335,7 +318,7 @@ static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) { if (index < 0 || index >= length) { break; } - ScopedPyObjectPtr s(Item(self, index)); + ScopedPyObjectPtr s(Item(pself, index)); PyList_Append(list, s.get()); } } else { @@ -346,7 +329,7 @@ static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) { if (index < 0 || index >= length) { break; } - ScopedPyObjectPtr s(Item(self, index)); + ScopedPyObjectPtr s(Item(pself, index)); PyList_Append(list, s.get()); } } @@ -355,87 +338,92 @@ static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) { PyObject* Append(RepeatedScalarContainer* self, PyObject* item) { cmessage::AssureWritable(self->parent); - Message* message = self->message; + Message* message = self->parent->message; const FieldDescriptor* field_descriptor = self->parent_field_descriptor; const Reflection* reflection = message->GetReflection(); switch (field_descriptor->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: { - GOOGLE_CHECK_GET_INT32(item, value, NULL); + GOOGLE_CHECK_GET_INT32(item, value, nullptr); reflection->AddInt32(message, field_descriptor, value); break; } case FieldDescriptor::CPPTYPE_INT64: { - GOOGLE_CHECK_GET_INT64(item, value, NULL); + GOOGLE_CHECK_GET_INT64(item, value, nullptr); reflection->AddInt64(message, field_descriptor, value); break; } case FieldDescriptor::CPPTYPE_UINT32: { - GOOGLE_CHECK_GET_UINT32(item, value, NULL); + GOOGLE_CHECK_GET_UINT32(item, value, nullptr); reflection->AddUInt32(message, field_descriptor, value); break; } case FieldDescriptor::CPPTYPE_UINT64: { - GOOGLE_CHECK_GET_UINT64(item, value, NULL); + GOOGLE_CHECK_GET_UINT64(item, value, nullptr); reflection->AddUInt64(message, field_descriptor, value); break; } case FieldDescriptor::CPPTYPE_FLOAT: { - GOOGLE_CHECK_GET_FLOAT(item, value, NULL); + GOOGLE_CHECK_GET_FLOAT(item, value, nullptr); reflection->AddFloat(message, field_descriptor, value); break; } case FieldDescriptor::CPPTYPE_DOUBLE: { - GOOGLE_CHECK_GET_DOUBLE(item, value, NULL); + GOOGLE_CHECK_GET_DOUBLE(item, value, nullptr); reflection->AddDouble(message, field_descriptor, value); break; } case FieldDescriptor::CPPTYPE_BOOL: { - GOOGLE_CHECK_GET_BOOL(item, value, NULL); + GOOGLE_CHECK_GET_BOOL(item, value, nullptr); reflection->AddBool(message, field_descriptor, value); break; } case FieldDescriptor::CPPTYPE_STRING: { - if (!CheckAndSetString( - item, message, field_descriptor, reflection, true, -1)) { - return NULL; + if (!CheckAndSetString(item, message, field_descriptor, reflection, true, + -1)) { + return nullptr; } break; } case FieldDescriptor::CPPTYPE_ENUM: { - GOOGLE_CHECK_GET_INT32(item, value, NULL); + GOOGLE_CHECK_GET_INT32(item, value, nullptr); if (reflection->SupportsUnknownEnumValues()) { reflection->AddEnumValue(message, field_descriptor, value); } else { const EnumDescriptor* enum_descriptor = field_descriptor->enum_type(); const EnumValueDescriptor* enum_value = enum_descriptor->FindValueByNumber(value); - if (enum_value != NULL) { + if (enum_value != nullptr) { reflection->AddEnum(message, field_descriptor, enum_value); } else { ScopedPyObjectPtr s(PyObject_Str(item)); - if (s != NULL) { + if (s != nullptr) { PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", PyString_AsString(s.get())); } - return NULL; + return nullptr; } } break; } default: - PyErr_Format( - PyExc_SystemError, "Adding value to a field of unknown type %d", - field_descriptor->cpp_type()); - return NULL; + PyErr_Format(PyExc_SystemError, + "Adding value to a field of unknown type %d", + field_descriptor->cpp_type()); + return nullptr; } Py_RETURN_NONE; } -static int AssSubscript(RepeatedScalarContainer* self, - PyObject* slice, - PyObject* value) { +static PyObject* AppendMethod(PyObject* self, PyObject* item) { + return Append(reinterpret_cast(self), item); +} + +static int AssSubscript(PyObject* pself, PyObject* slice, PyObject* value) { + RepeatedScalarContainer* self = + reinterpret_cast(pself); + Py_ssize_t from; Py_ssize_t to; Py_ssize_t step; @@ -444,26 +432,25 @@ static int AssSubscript(RepeatedScalarContainer* self, bool create_list = false; cmessage::AssureWritable(self->parent); - Message* message = self->message; - const FieldDescriptor* field_descriptor = - self->parent_field_descriptor; + Message* message = self->parent->message; + const FieldDescriptor* field_descriptor = self->parent_field_descriptor; #if PY_MAJOR_VERSION < 3 if (PyInt_Check(slice)) { from = to = PyInt_AsLong(slice); - } else + } else // NOLINT #endif - if (PyLong_Check(slice)) { + if (PyLong_Check(slice)) { from = to = PyLong_AsLong(slice); } else if (PySlice_Check(slice)) { const Reflection* reflection = message->GetReflection(); length = reflection->FieldSize(*message, field_descriptor); #if PY_MAJOR_VERSION >= 3 - if (PySlice_GetIndicesEx(slice, - length, &from, &to, &step, &slicelength) == -1) { + if (PySlice_GetIndicesEx(slice, length, &from, &to, &step, &slicelength) == + -1) { #else - if (PySlice_GetIndicesEx(reinterpret_cast(slice), - length, &from, &to, &step, &slicelength) == -1) { + if (PySlice_GetIndicesEx(reinterpret_cast(slice), length, + &from, &to, &step, &slicelength) == -1) { #endif return -1; } @@ -473,21 +460,20 @@ static int AssSubscript(RepeatedScalarContainer* self, return -1; } - if (value == NULL) { - return cmessage::InternalDeleteRepeatedField( - self->parent, field_descriptor, slice, NULL); + if (value == nullptr) { + return cmessage::DeleteRepeatedField(self->parent, field_descriptor, slice); } if (!create_list) { - return AssignItem(self, from, value); + return AssignItem(pself, from, value); } - ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); - if (full_slice == NULL) { + ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr)); + if (full_slice == nullptr) { return -1; } - ScopedPyObjectPtr new_list(Subscript(self, full_slice.get())); - if (new_list == NULL) { + ScopedPyObjectPtr new_list(Subscript(pself, full_slice.get())); + if (new_list == nullptr) { return -1; } if (PySequence_SetSlice(new_list.get(), from, to, value) < 0) { @@ -504,49 +490,52 @@ PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) { if (value == Py_None) { Py_RETURN_NONE; } - if ((Py_TYPE(value)->tp_as_sequence == NULL) && PyObject_Not(value)) { + if ((Py_TYPE(value)->tp_as_sequence == nullptr) && PyObject_Not(value)) { Py_RETURN_NONE; } ScopedPyObjectPtr iter(PyObject_GetIter(value)); - if (iter == NULL) { + if (iter == nullptr) { PyErr_SetString(PyExc_TypeError, "Value must be iterable"); - return NULL; + return nullptr; } ScopedPyObjectPtr next; - while ((next.reset(PyIter_Next(iter.get()))) != NULL) { - if (ScopedPyObjectPtr(Append(self, next.get())) == NULL) { - return NULL; + while ((next.reset(PyIter_Next(iter.get()))) != nullptr) { + if (ScopedPyObjectPtr(Append(self, next.get())) == nullptr) { + return nullptr; } } if (PyErr_Occurred()) { - return NULL; + return nullptr; } Py_RETURN_NONE; } -static PyObject* Insert(RepeatedScalarContainer* self, PyObject* args) { +static PyObject* Insert(PyObject* pself, PyObject* args) { + RepeatedScalarContainer* self = + reinterpret_cast(pself); + Py_ssize_t index; PyObject* value; if (!PyArg_ParseTuple(args, "lO", &index, &value)) { - return NULL; + return nullptr; } - ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); - ScopedPyObjectPtr new_list(Subscript(self, full_slice.get())); + ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr)); + ScopedPyObjectPtr new_list(Subscript(pself, full_slice.get())); if (PyList_Insert(new_list.get(), index, value) < 0) { - return NULL; + return nullptr; } int ret = InternalAssignRepeatedField(self, new_list.get()); if (ret < 0) { - return NULL; + return nullptr; } Py_RETURN_NONE; } -static PyObject* Remove(RepeatedScalarContainer* self, PyObject* value) { +static PyObject* Remove(PyObject* pself, PyObject* value) { Py_ssize_t match_index = -1; - for (Py_ssize_t i = 0; i < Len(self); ++i) { - ScopedPyObjectPtr elem(Item(self, i)); + for (Py_ssize_t i = 0; i < Len(pself); ++i) { + ScopedPyObjectPtr elem(Item(pself, i)); if (PyObject_RichCompareBool(elem.get(), value, Py_EQ)) { match_index = i; break; @@ -554,17 +543,19 @@ static PyObject* Remove(RepeatedScalarContainer* self, PyObject* value) { } if (match_index == -1) { PyErr_SetString(PyExc_ValueError, "remove(x): x not in container"); - return NULL; + return nullptr; } - if (AssignItem(self, match_index, NULL) < 0) { - return NULL; + if (AssignItem(pself, match_index, nullptr) < 0) { + return nullptr; } Py_RETURN_NONE; } -static PyObject* RichCompare(RepeatedScalarContainer* self, - PyObject* other, - int opid) { +static PyObject* ExtendMethod(PyObject* self, PyObject* value) { + return Extend(reinterpret_cast(self), value); +} + +static PyObject* RichCompare(PyObject* pself, PyObject* other, int opid) { if (opid != Py_EQ && opid != Py_NE) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; @@ -574,252 +565,229 @@ static PyObject* RichCompare(RepeatedScalarContainer* self, // also a repeated scalar container, into Python lists so we can delegate // to the list's compare method. - ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); - if (full_slice == NULL) { - return NULL; + ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr)); + if (full_slice == nullptr) { + return nullptr; } ScopedPyObjectPtr other_list_deleter; if (PyObject_TypeCheck(other, &RepeatedScalarContainer_Type)) { - other_list_deleter.reset(Subscript( - reinterpret_cast(other), full_slice.get())); + other_list_deleter.reset(Subscript(other, full_slice.get())); other = other_list_deleter.get(); } - ScopedPyObjectPtr list(Subscript(self, full_slice.get())); - if (list == NULL) { - return NULL; + ScopedPyObjectPtr list(Subscript(pself, full_slice.get())); + if (list == nullptr) { + return nullptr; } return PyObject_RichCompare(list.get(), other, opid); } -PyObject* Reduce(RepeatedScalarContainer* unused_self) { - PyErr_Format( - PickleError_class, - "can't pickle repeated message fields, convert to list first"); - return NULL; +PyObject* Reduce(PyObject* unused_self, PyObject* unused_other) { + PyErr_Format(PickleError_class, + "can't pickle repeated message fields, convert to list first"); + return nullptr; } -static PyObject* Sort(RepeatedScalarContainer* self, - PyObject* args, - PyObject* kwds) { +static PyObject* Sort(PyObject* pself, PyObject* args, PyObject* kwds) { // Support the old sort_function argument for backwards // compatibility. - if (kwds != NULL) { + if (kwds != nullptr) { PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function"); - if (sort_func != NULL) { + if (sort_func != nullptr) { // Must set before deleting as sort_func is a borrowed reference // and kwds might be the only thing keeping it alive. - if (PyDict_SetItemString(kwds, "cmp", sort_func) == -1) - return NULL; - if (PyDict_DelItemString(kwds, "sort_function") == -1) - return NULL; + if (PyDict_SetItemString(kwds, "cmp", sort_func) == -1) return nullptr; + if (PyDict_DelItemString(kwds, "sort_function") == -1) return nullptr; } } - ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); - if (full_slice == NULL) { - return NULL; + ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr)); + if (full_slice == nullptr) { + return nullptr; } - ScopedPyObjectPtr list(Subscript(self, full_slice.get())); - if (list == NULL) { - return NULL; + ScopedPyObjectPtr list(Subscript(pself, full_slice.get())); + if (list == nullptr) { + return nullptr; } ScopedPyObjectPtr m(PyObject_GetAttrString(list.get(), "sort")); - if (m == NULL) { - return NULL; + if (m == nullptr) { + return nullptr; } ScopedPyObjectPtr res(PyObject_Call(m.get(), args, kwds)); - if (res == NULL) { - return NULL; + if (res == nullptr) { + return nullptr; + } + int ret = InternalAssignRepeatedField( + reinterpret_cast(pself), list.get()); + if (ret < 0) { + return nullptr; + } + Py_RETURN_NONE; +} + +static PyObject* Reverse(PyObject* pself) { + ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr)); + if (full_slice == nullptr) { + return nullptr; } - int ret = InternalAssignRepeatedField(self, list.get()); + ScopedPyObjectPtr list(Subscript(pself, full_slice.get())); + if (list == nullptr) { + return nullptr; + } + ScopedPyObjectPtr res(PyObject_CallMethod(list.get(), "reverse", nullptr)); + if (res == nullptr) { + return nullptr; + } + int ret = InternalAssignRepeatedField( + reinterpret_cast(pself), list.get()); if (ret < 0) { - return NULL; + return nullptr; } Py_RETURN_NONE; } -static PyObject* Pop(RepeatedScalarContainer* self, - PyObject* args) { +static PyObject* Pop(PyObject* pself, PyObject* args) { Py_ssize_t index = -1; if (!PyArg_ParseTuple(args, "|n", &index)) { - return NULL; + return nullptr; } - PyObject* item = Item(self, index); - if (item == NULL) { - PyErr_Format(PyExc_IndexError, - "list index (%zd) out of range", - index); - return NULL; + PyObject* item = Item(pself, index); + if (item == nullptr) { + PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index); + return nullptr; } - if (AssignItem(self, index, NULL) < 0) { - return NULL; + if (AssignItem(pself, index, nullptr) < 0) { + return nullptr; } return item; } -static PyObject* ToStr(RepeatedScalarContainer* self) { - ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); - if (full_slice == NULL) { - return NULL; +static PyObject* ToStr(PyObject* pself) { + ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr)); + if (full_slice == nullptr) { + return nullptr; } - ScopedPyObjectPtr list(Subscript(self, full_slice.get())); - if (list == NULL) { - return NULL; + ScopedPyObjectPtr list(Subscript(pself, full_slice.get())); + if (list == nullptr) { + return nullptr; } return PyObject_Repr(list.get()); } +static PyObject* MergeFrom(PyObject* pself, PyObject* arg) { + return Extend(reinterpret_cast(pself), arg); +} + // The private constructor of RepeatedScalarContainer objects. -PyObject *NewContainer( +RepeatedScalarContainer* NewContainer( CMessage* parent, const FieldDescriptor* parent_field_descriptor) { if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) { - return NULL; + return nullptr; } RepeatedScalarContainer* self = reinterpret_cast( PyType_GenericAlloc(&RepeatedScalarContainer_Type, 0)); - if (self == NULL) { - return NULL; + if (self == nullptr) { + return nullptr; } - self->message = parent->message; + Py_INCREF(parent); self->parent = parent; self->parent_field_descriptor = parent_field_descriptor; - self->owner = parent->owner; - - return reinterpret_cast(self); -} - -// Initializes the underlying Message object of "to" so it becomes a new parent -// repeated scalar, and copies all the values from "from" to it. A child scalar -// container can be released by passing it as both from and to (e.g. making it -// the recipient of the new parent message and copying the values from itself). -static int InitializeAndCopyToParentContainer( - RepeatedScalarContainer* from, - RepeatedScalarContainer* to) { - ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); - if (full_slice == NULL) { - return -1; - } - ScopedPyObjectPtr values(Subscript(from, full_slice.get())); - if (values == NULL) { - return -1; - } - Message* new_message = from->message->New(); - to->parent = NULL; - to->parent_field_descriptor = from->parent_field_descriptor; - to->message = new_message; - to->owner.reset(new_message); - if (InternalAssignRepeatedField(to, values.get()) < 0) { - return -1; - } - return 0; -} - -int Release(RepeatedScalarContainer* self) { - return InitializeAndCopyToParentContainer(self, self); -} - -PyObject* DeepCopy(RepeatedScalarContainer* self, PyObject* arg) { - RepeatedScalarContainer* clone = reinterpret_cast( - PyType_GenericAlloc(&RepeatedScalarContainer_Type, 0)); - if (clone == NULL) { - return NULL; - } - if (InitializeAndCopyToParentContainer(self, clone) < 0) { - Py_DECREF(clone); - return NULL; - } - return reinterpret_cast(clone); + return self; } -static void Dealloc(RepeatedScalarContainer* self) { - self->owner.reset(); - Py_TYPE(self)->tp_free(reinterpret_cast(self)); +PyObject* DeepCopy(PyObject* pself, PyObject* arg) { + return reinterpret_cast(pself)->DeepCopy(); } -void SetOwner(RepeatedScalarContainer* self, - const shared_ptr& new_owner) { - self->owner = new_owner; +static void Dealloc(PyObject* pself) { + reinterpret_cast(pself)->RemoveFromParentCache(); + Py_TYPE(pself)->tp_free(pself); } static PySequenceMethods SqMethods = { - (lenfunc)Len, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - (ssizeargfunc)Item, /* sq_item */ - 0, /* sq_slice */ - (ssizeobjargproc)AssignItem /* sq_ass_item */ + Len, /* sq_length */ + nullptr, /* sq_concat */ + nullptr, /* sq_repeat */ + Item, /* sq_item */ + nullptr, /* sq_slice */ + AssignItem /* sq_ass_item */ }; static PyMappingMethods MpMethods = { - (lenfunc)Len, /* mp_length */ - (binaryfunc)Subscript, /* mp_subscript */ - (objobjargproc)AssSubscript, /* mp_ass_subscript */ + Len, /* mp_length */ + Subscript, /* mp_subscript */ + AssSubscript, /* mp_ass_subscript */ }; static PyMethodDef Methods[] = { - { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, - "Makes a deep copy of the class." }, - { "__reduce__", (PyCFunction)Reduce, METH_NOARGS, - "Outputs picklable representation of the repeated field." }, - { "append", (PyCFunction)Append, METH_O, - "Appends an object to the repeated container." }, - { "extend", (PyCFunction)Extend, METH_O, - "Appends objects to the repeated container." }, - { "insert", (PyCFunction)Insert, METH_VARARGS, - "Appends objects to the repeated container." }, - { "pop", (PyCFunction)Pop, METH_VARARGS, - "Removes an object from the repeated container and returns it." }, - { "remove", (PyCFunction)Remove, METH_O, - "Removes an object from the repeated container." }, - { "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS, - "Sorts the repeated container."}, - { NULL, NULL } -}; + {"__deepcopy__", DeepCopy, METH_VARARGS, "Makes a deep copy of the class."}, + {"__reduce__", Reduce, METH_NOARGS, + "Outputs picklable representation of the repeated field."}, + {"append", AppendMethod, METH_O, + "Appends an object to the repeated container."}, + {"extend", ExtendMethod, METH_O, + "Appends objects to the repeated container."}, + {"insert", Insert, METH_VARARGS, + "Inserts an object at the specified position in the container."}, + {"pop", Pop, METH_VARARGS, + "Removes an object from the repeated container and returns it."}, + {"remove", Remove, METH_O, + "Removes an object from the repeated container."}, + {"sort", reinterpret_cast(Sort), METH_VARARGS | METH_KEYWORDS, + "Sorts the repeated container."}, + {"reverse", reinterpret_cast(Reverse), METH_NOARGS, + "Reverses elements order of the repeated container."}, + {"MergeFrom", static_cast(MergeFrom), METH_O, + "Merges a repeated container into the current container."}, + {nullptr, nullptr}}; } // namespace repeated_scalar_container PyTypeObject RepeatedScalarContainer_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - FULL_MODULE_NAME ".RepeatedScalarContainer", // tp_name - sizeof(RepeatedScalarContainer), // tp_basicsize - 0, // tp_itemsize - (destructor)repeated_scalar_container::Dealloc, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - (reprfunc)repeated_scalar_container::ToStr, // tp_repr - 0, // tp_as_number - &repeated_scalar_container::SqMethods, // tp_as_sequence - &repeated_scalar_container::MpMethods, // tp_as_mapping - PyObject_HashNotImplemented, // tp_hash - 0, // tp_call - 0, // tp_str - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - "A Repeated scalar container", // tp_doc - 0, // tp_traverse - 0, // tp_clear - (richcmpfunc)repeated_scalar_container::RichCompare, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - repeated_scalar_container::Methods, // tp_methods - 0, // tp_members - 0, // tp_getset - 0, // tp_base - 0, // tp_dict - 0, // tp_descr_get - 0, // tp_descr_set - 0, // tp_dictoffset - 0, // tp_init + PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME + ".RepeatedScalarContainer", // tp_name + sizeof(RepeatedScalarContainer), // tp_basicsize + 0, // tp_itemsize + repeated_scalar_container::Dealloc, // tp_dealloc +#if PY_VERSION_HEX >= 0x03080000 + 0, // tp_vectorcall_offset +#else + nullptr, // tp_print +#endif + nullptr, // tp_getattr + nullptr, // tp_setattr + nullptr, // tp_compare + repeated_scalar_container::ToStr, // tp_repr + nullptr, // tp_as_number + &repeated_scalar_container::SqMethods, // tp_as_sequence + &repeated_scalar_container::MpMethods, // tp_as_mapping + PyObject_HashNotImplemented, // tp_hash + nullptr, // tp_call + nullptr, // tp_str + nullptr, // tp_getattro + nullptr, // tp_setattro + nullptr, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "A Repeated scalar container", // tp_doc + nullptr, // tp_traverse + nullptr, // tp_clear + repeated_scalar_container::RichCompare, // tp_richcompare + 0, // tp_weaklistoffset + nullptr, // tp_iter + nullptr, // tp_iternext + repeated_scalar_container::Methods, // tp_methods + nullptr, // tp_members + nullptr, // tp_getset + nullptr, // tp_base + nullptr, // tp_dict + nullptr, // tp_descr_get + nullptr, // tp_descr_set + 0, // tp_dictoffset + nullptr, // tp_init }; } // namespace python diff --git a/python/google/protobuf/pyext/repeated_scalar_container.h b/python/google/protobuf/pyext/repeated_scalar_container.h index 555e621c9bf71..f9f0ea8f313a9 100644 --- a/python/google/protobuf/pyext/repeated_scalar_container.h +++ b/python/google/protobuf/pyext/repeated_scalar_container.h @@ -37,51 +37,15 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include +#include namespace google { namespace protobuf { - -class Message; - -#ifdef _SHARED_PTR_H -using std::shared_ptr; -#else -using internal::shared_ptr; -#endif - namespace python { -struct CMessage; - -typedef struct RepeatedScalarContainer { - PyObject_HEAD; - - // This is the top-level C++ Message object that owns the whole - // proto tree. Every Python RepeatedScalarContainer holds a - // reference to it in order to keep it alive as long as there's a - // Python object that references any part of the tree. - shared_ptr owner; - - // Pointer to the C++ Message that contains this container. The - // RepeatedScalarContainer does not own this pointer. - Message* message; - - // Weak reference to a parent CMessage object (i.e. may be NULL.) - // - // Used to make sure all ancestors are also mutable when first - // modifying the container. - CMessage* parent; - - // Pointer to the parent's descriptor that describes this - // field. Used together with the parent's message when making a - // default message instance mutable. - // The pointer is owned by the global DescriptorPool. - const FieldDescriptor* parent_field_descriptor; +typedef struct RepeatedScalarContainer : public ContainerBase { } RepeatedScalarContainer; extern PyTypeObject RepeatedScalarContainer_Type; @@ -90,7 +54,7 @@ namespace repeated_scalar_container { // Builds a RepeatedScalarContainer object, from a parent message and a // field descriptor. -extern PyObject *NewContainer( +extern RepeatedScalarContainer* NewContainer( CMessage* parent, const FieldDescriptor* parent_field_descriptor); // Appends the scalar 'item' to the end of the container 'self'. @@ -99,24 +63,15 @@ extern PyObject *NewContainer( // unsuccessful. PyObject* Append(RepeatedScalarContainer* self, PyObject* item); -// Releases the messages in the container to a new message. -// -// Returns 0 on success, -1 on failure. -int Release(RepeatedScalarContainer* self); - // Appends all the elements in the input iterator to the container. // // Returns None if successful; returns NULL and sets an exception if // unsuccessful. PyObject* Extend(RepeatedScalarContainer* self, PyObject* value); -// Set the owner field of self and any children of self. -void SetOwner(RepeatedScalarContainer* self, - const shared_ptr& new_owner); - } // namespace repeated_scalar_container } // namespace python } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_PYTHON_CPP_REPEATED_SCALAR_CONTAINER_H__ diff --git a/python/google/protobuf/pyext/safe_numerics.h b/python/google/protobuf/pyext/safe_numerics.h index 639ba2c8e3e91..93ae640e8b7e5 100644 --- a/python/google/protobuf/pyext/safe_numerics.h +++ b/python/google/protobuf/pyext/safe_numerics.h @@ -132,10 +132,10 @@ template inline bool IsValidNumericCast(Source source) { typedef std::numeric_limits SourceLimits; typedef std::numeric_limits DestLimits; - GOOGLE_COMPILE_ASSERT(SourceLimits::is_specialized, argument_must_be_numeric); - GOOGLE_COMPILE_ASSERT(SourceLimits::is_integer, argument_must_be_integral); - GOOGLE_COMPILE_ASSERT(DestLimits::is_specialized, result_must_be_numeric); - GOOGLE_COMPILE_ASSERT(DestLimits::is_integer, result_must_be_integral); + static_assert(SourceLimits::is_specialized, "argument must be numeric"); + static_assert(SourceLimits::is_integer, "argument must be integral"); + static_assert(DestLimits::is_specialized, "result must be numeric"); + static_assert(DestLimits::is_integer, "result must be integral"); return IsValidNumericCastImpl< sizeof(Dest) == sizeof(Source), @@ -150,7 +150,7 @@ inline bool IsValidNumericCast(Source source) { // checked_numeric_cast<> is analogous to static_cast<> for numeric types, // except that it CHECKs that the specified numeric conversion will not // overflow or underflow. Floating point arguments are not currently allowed -// (this is COMPILE_ASSERTd), though this could be supported if necessary. +// (this is static_asserted), though this could be supported if necessary. template inline Dest checked_numeric_cast(Source source) { GOOGLE_CHECK(IsValidNumericCast(source)); @@ -159,6 +159,6 @@ inline Dest checked_numeric_cast(Source source) { } // namespace python } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_PYTHON_CPP_SAFE_NUMERICS_H__ diff --git a/python/google/protobuf/pyext/scoped_pyobject_ptr.h b/python/google/protobuf/pyext/scoped_pyobject_ptr.h index a2afa7f19de25..6f7fc29813f98 100644 --- a/python/google/protobuf/pyext/scoped_pyobject_ptr.h +++ b/python/google/protobuf/pyext/scoped_pyobject_ptr.h @@ -73,16 +73,11 @@ class ScopedPythonPtr { return p; } - PyObjectStruct* operator->() const { - assert(ptr_ != NULL); - return ptr_; - } - PyObjectStruct* get() const { return ptr_; } PyObject* as_pyobject() const { return reinterpret_cast(ptr_); } - // Increments the reference count fo the current object. + // Increments the reference count of the current object. // Should not be called when no object is held. void inc() const { Py_INCREF(ptr_); } diff --git a/python/google/protobuf/pyext/unknown_fields.cc b/python/google/protobuf/pyext/unknown_fields.cc new file mode 100644 index 0000000000000..deb86e6916823 --- /dev/null +++ b/python/google/protobuf/pyext/unknown_fields.cc @@ -0,0 +1,358 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#if PY_MAJOR_VERSION >= 3 + #define PyInt_FromLong PyLong_FromLong +#endif + +namespace google { +namespace protobuf { +namespace python { + +namespace unknown_fields { + +static Py_ssize_t Len(PyObject* pself) { + PyUnknownFields* self = + reinterpret_cast(pself); + if (self->fields == NULL) { + PyErr_Format(PyExc_ValueError, + "UnknownFields does not exist. " + "The parent message might be cleared."); + return -1; + } + return self->fields->field_count(); +} + +void Clear(PyUnknownFields* self) { + for (std::set::iterator it = + self->sub_unknown_fields.begin(); + it != self->sub_unknown_fields.end(); it++) { + Clear(*it); + } + self->fields = NULL; + self->sub_unknown_fields.clear(); +} + +PyObject* NewPyUnknownFieldRef(PyUnknownFields* parent, + Py_ssize_t index); + +static PyObject* Item(PyObject* pself, Py_ssize_t index) { + PyUnknownFields* self = + reinterpret_cast(pself); + if (self->fields == NULL) { + PyErr_Format(PyExc_ValueError, + "UnknownFields does not exist. " + "The parent message might be cleared."); + return NULL; + } + Py_ssize_t total_size = self->fields->field_count(); + if (index < 0) { + index = total_size + index; + } + if (index < 0 || index >= total_size) { + PyErr_Format(PyExc_IndexError, + "index (%zd) out of range", + index); + return NULL; + } + + return unknown_fields::NewPyUnknownFieldRef(self, index); +} + +PyObject* NewPyUnknownFields(CMessage* c_message) { + PyUnknownFields* self = reinterpret_cast( + PyType_GenericAlloc(&PyUnknownFields_Type, 0)); + if (self == NULL) { + return NULL; + } + // Call "placement new" to initialize PyUnknownFields. + new (self) PyUnknownFields; + + Py_INCREF(c_message); + self->parent = reinterpret_cast(c_message); + Message* message = c_message->message; + const Reflection* reflection = message->GetReflection(); + self->fields = &reflection->GetUnknownFields(*message); + + return reinterpret_cast(self); +} + +PyObject* NewPyUnknownFieldRef(PyUnknownFields* parent, + Py_ssize_t index) { + PyUnknownFieldRef* self = reinterpret_cast( + PyType_GenericAlloc(&PyUnknownFieldRef_Type, 0)); + if (self == NULL) { + return NULL; + } + + Py_INCREF(parent); + self->parent = parent; + self->index = index; + + return reinterpret_cast(self); +} + +static void Dealloc(PyObject* pself) { + PyUnknownFields* self = + reinterpret_cast(pself); + if (PyObject_TypeCheck(self->parent, &PyUnknownFields_Type)) { + reinterpret_cast( + self->parent)->sub_unknown_fields.erase(self); + } else { + reinterpret_cast(self->parent)->unknown_field_set = nullptr; + } + Py_CLEAR(self->parent); + self->~PyUnknownFields(); + Py_TYPE(pself)->tp_free(pself); +} + +static PySequenceMethods SqMethods = { + Len, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + Item, /* sq_item */ + 0, /* sq_slice */ + 0, /* sq_ass_item */ +}; + +} // namespace unknown_fields + +PyTypeObject PyUnknownFields_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + FULL_MODULE_NAME ".PyUnknownFields", // tp_name + sizeof(PyUnknownFields), // tp_basicsize + 0, // tp_itemsize + unknown_fields::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + &unknown_fields::SqMethods, // tp_as_sequence + 0, // tp_as_mapping + PyObject_HashNotImplemented, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "unknown field set", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init +}; + +namespace unknown_field { +static PyObject* PyUnknownFields_FromUnknownFieldSet( + PyUnknownFields* parent, const UnknownFieldSet& fields) { + PyUnknownFields* self = reinterpret_cast( + PyType_GenericAlloc(&PyUnknownFields_Type, 0)); + if (self == NULL) { + return NULL; + } + // Call "placement new" to initialize PyUnknownFields. + new (self) PyUnknownFields; + + Py_INCREF(parent); + self->parent = reinterpret_cast(parent); + self->fields = &fields; + parent->sub_unknown_fields.emplace(self); + + return reinterpret_cast(self); +} + +const UnknownField* GetUnknownField(PyUnknownFieldRef* self) { + const UnknownFieldSet* fields = self->parent->fields; + if (fields == NULL) { + PyErr_Format(PyExc_ValueError, + "UnknownField does not exist. " + "The parent message might be cleared."); + return NULL; + } + ssize_t total_size = fields->field_count(); + if (self->index >= total_size) { + PyErr_Format(PyExc_ValueError, + "UnknownField does not exist. " + "The parent message might be cleared."); + return NULL; + } + return &fields->field(self->index); +} + +static PyObject* GetFieldNumber(PyUnknownFieldRef* self, void *closure) { + const UnknownField* unknown_field = GetUnknownField(self); + if (unknown_field == NULL) { + return NULL; + } + return PyInt_FromLong(unknown_field->number()); +} + +using internal::WireFormatLite; +static PyObject* GetWireType(PyUnknownFieldRef* self, void *closure) { + const UnknownField* unknown_field = GetUnknownField(self); + if (unknown_field == NULL) { + return NULL; + } + + // Assign a default value to suppress may-uninitialized warnings (errors + // when built in some places). + WireFormatLite::WireType wire_type = WireFormatLite::WIRETYPE_VARINT; + switch (unknown_field->type()) { + case UnknownField::TYPE_VARINT: + wire_type = WireFormatLite::WIRETYPE_VARINT; + break; + case UnknownField::TYPE_FIXED32: + wire_type = WireFormatLite::WIRETYPE_FIXED32; + break; + case UnknownField::TYPE_FIXED64: + wire_type = WireFormatLite::WIRETYPE_FIXED64; + break; + case UnknownField::TYPE_LENGTH_DELIMITED: + wire_type = WireFormatLite::WIRETYPE_LENGTH_DELIMITED; + break; + case UnknownField::TYPE_GROUP: + wire_type = WireFormatLite::WIRETYPE_START_GROUP; + break; + } + return PyInt_FromLong(wire_type); +} + +static PyObject* GetData(PyUnknownFieldRef* self, void *closure) { + const UnknownField* field = GetUnknownField(self); + if (field == NULL) { + return NULL; + } + PyObject* data = NULL; + switch (field->type()) { + case UnknownField::TYPE_VARINT: + data = PyInt_FromLong(field->varint()); + break; + case UnknownField::TYPE_FIXED32: + data = PyInt_FromLong(field->fixed32()); + break; + case UnknownField::TYPE_FIXED64: + data = PyInt_FromLong(field->fixed64()); + break; + case UnknownField::TYPE_LENGTH_DELIMITED: + data = PyBytes_FromStringAndSize(field->length_delimited().data(), + field->GetLengthDelimitedSize()); + break; + case UnknownField::TYPE_GROUP: + data = PyUnknownFields_FromUnknownFieldSet( + self->parent, field->group()); + break; + } + return data; +} + +static void Dealloc(PyObject* pself) { + PyUnknownFieldRef* self = + reinterpret_cast(pself); + Py_CLEAR(self->parent); +} + +static PyGetSetDef Getters[] = { + {"field_number", (getter)GetFieldNumber, NULL}, + {"wire_type", (getter)GetWireType, NULL}, + {"data", (getter)GetData, NULL}, + {NULL} +}; + +} // namespace unknown_field + +PyTypeObject PyUnknownFieldRef_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + FULL_MODULE_NAME ".PyUnknownFieldRef", // tp_name + sizeof(PyUnknownFieldRef), // tp_basicsize + 0, // tp_itemsize + unknown_field::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + PyObject_HashNotImplemented, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "unknown field", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + unknown_field::Getters, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init +}; + + +} // namespace python +} // namespace protobuf +} // namespace google diff --git a/python/google/protobuf/pyext/unknown_fields.h b/python/google/protobuf/pyext/unknown_fields.h new file mode 100644 index 0000000000000..94d55e148db69 --- /dev/null +++ b/python/google/protobuf/pyext/unknown_fields.h @@ -0,0 +1,90 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_UNKNOWN_FIELDS_H__ +#define GOOGLE_PROTOBUF_PYTHON_CPP_UNKNOWN_FIELDS_H__ + +#include + +#include +#include + +#include + +namespace google { +namespace protobuf { + +class UnknownField; +class UnknownFieldSet; + +namespace python { +struct CMessage; + +typedef struct PyUnknownFields { + PyObject_HEAD; + // Strong pointer to the parent CMessage or PyUnknownFields. + // The top PyUnknownFields holds a reference to its parent CMessage + // object before release. + // Sub PyUnknownFields holds reference to parent PyUnknownFields. + PyObject* parent; + + // Pointer to the C++ UnknownFieldSet. + // PyUnknownFields does not own this pointer. + const UnknownFieldSet* fields; + + // Weak references to child unknown fields. + std::set sub_unknown_fields; +} PyUnknownFields; + +typedef struct PyUnknownFieldRef { + PyObject_HEAD; + // Every Python PyUnknownFieldRef holds a reference to its parent + // PyUnknownFields in order to keep it alive. + PyUnknownFields* parent; + + // The UnknownField index in UnknownFields. + Py_ssize_t index; +} UknownFieldRef; + +extern PyTypeObject PyUnknownFields_Type; +extern PyTypeObject PyUnknownFieldRef_Type; + +namespace unknown_fields { + +// Builds an PyUnknownFields for a specific message. +PyObject* NewPyUnknownFields(CMessage *parent); +void Clear(PyUnknownFields* self); + +} // namespace unknown_fields +} // namespace python +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_PYTHON_CPP_UNKNOWN_FIELDS_H__ diff --git a/python/google/protobuf/python_protobuf.h b/python/google/protobuf/python_protobuf.h index beb6e4604a6f4..8db1ffb7503b4 100644 --- a/python/google/protobuf/python_protobuf.h +++ b/python/google/protobuf/python_protobuf.h @@ -52,6 +52,6 @@ Message* MutableCProtoInsidePyProto(PyObject* msg); } // namespace python } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__ diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py old mode 100755 new mode 100644 index f4ce8caf9be68..81e18859a804d --- a/python/google/protobuf/reflection.py +++ b/python/google/protobuf/reflection.py @@ -48,25 +48,23 @@ __author__ = 'robinson@google.com (Will Robinson)' -from google.protobuf.internal import api_implementation -from google.protobuf import message - - -if api_implementation.Type() == 'cpp': - from google.protobuf.pyext import cpp_message as message_impl -else: - from google.protobuf.internal import python_message as message_impl +from google.protobuf import message_factory +from google.protobuf import symbol_database # The type of all Message classes. # Part of the public interface, but normally only used by message factories. -GeneratedProtocolMessageType = message_impl.GeneratedProtocolMessageType +GeneratedProtocolMessageType = message_factory._GENERATED_PROTOCOL_MESSAGE_TYPE MESSAGE_CLASS_CACHE = {} +# Deprecated. Please NEVER use reflection.ParseMessage(). def ParseMessage(descriptor, byte_str): """Generate a new Message instance from this Descriptor and a byte string. + DEPRECATED: ParseMessage is deprecated because it is using MakeClass(). + Please use MessageFactory.GetPrototype() instead. + Args: descriptor: Protobuf Descriptor object byte_str: Serialized protocol buffer byte string @@ -80,42 +78,18 @@ def ParseMessage(descriptor, byte_str): return new_msg +# Deprecated. Please NEVER use reflection.MakeClass(). def MakeClass(descriptor): """Construct a class object for a protobuf described by descriptor. - Composite descriptors are handled by defining the new class as a member of the - parent class, recursing as deep as necessary. - This is the dynamic equivalent to: - - class Parent(message.Message): - __metaclass__ = GeneratedProtocolMessageType - DESCRIPTOR = descriptor - class Child(message.Message): - __metaclass__ = GeneratedProtocolMessageType - DESCRIPTOR = descriptor.nested_types[0] - - Sample usage: - file_descriptor = descriptor_pb2.FileDescriptorProto() - file_descriptor.ParseFromString(proto2_string) - msg_descriptor = descriptor.MakeDescriptor(file_descriptor.message_type[0]) - msg_class = reflection.MakeClass(msg_descriptor) - msg = msg_class() + DEPRECATED: use MessageFactory.GetPrototype() instead. Args: descriptor: A descriptor.Descriptor object describing the protobuf. Returns: The Message class object described by the descriptor. """ - if descriptor in MESSAGE_CLASS_CACHE: - return MESSAGE_CLASS_CACHE[descriptor] - - attributes = {} - for name, nested_type in descriptor.nested_types_by_name.items(): - attributes[name] = MakeClass(nested_type) - - attributes[GeneratedProtocolMessageType._DESCRIPTOR_KEY] = descriptor - - result = GeneratedProtocolMessageType( - str(descriptor.name), (message.Message,), attributes) - MESSAGE_CLASS_CACHE[descriptor] = result - return result + # Original implementation leads to duplicate message classes, which won't play + # well with extensions. Message factory info is also missing. + # Redirect to message_factory. + return symbol_database.Default().GetPrototype(descriptor) diff --git a/python/google/protobuf/service.py b/python/google/protobuf/service.py old mode 100755 new mode 100644 index 9e00de704257d..5625246324cad --- a/python/google/protobuf/service.py +++ b/python/google/protobuf/service.py @@ -73,6 +73,7 @@ def CallMethod(self, method_descriptor, rpc_controller, In the blocking case, RpcException will be raised on error. Preconditions: + * method_descriptor.service == GetDescriptor * request is of the exact same classes as returned by GetRequestClass(method). @@ -82,6 +83,7 @@ def CallMethod(self, method_descriptor, rpc_controller, RpcChannel which the stub is using. Postconditions: + * "done" will be called when the method is complete. This may be before CallMethod() returns or it may be at some point in the future. * If the RPC failed, the response value passed to "done" will be None. diff --git a/python/google/protobuf/service_reflection.py b/python/google/protobuf/service_reflection.py old mode 100755 new mode 100644 index 1c3636afe0472..75c51ff3221af --- a/python/google/protobuf/service_reflection.py +++ b/python/google/protobuf/service_reflection.py @@ -49,14 +49,14 @@ class GeneratedServiceType(type): The protocol compiler currently uses this metaclass to create protocol service classes at runtime. Clients can also manually create their own classes at - runtime, as in this example: - - mydescriptor = ServiceDescriptor(.....) - class MyProtoService(service.Service): - __metaclass__ = GeneratedServiceType - DESCRIPTOR = mydescriptor - myservice_instance = MyProtoService() - ... + runtime, as in this example:: + + mydescriptor = ServiceDescriptor(.....) + class MyProtoService(service.Service): + __metaclass__ = GeneratedServiceType + DESCRIPTOR = mydescriptor + myservice_instance = MyProtoService() + # ... """ _DESCRIPTOR_KEY = 'DESCRIPTOR' @@ -76,9 +76,11 @@ def __init__(cls, name, bases, dictionary): # when a service class is subclassed. if GeneratedServiceType._DESCRIPTOR_KEY not in dictionary: return + descriptor = dictionary[GeneratedServiceType._DESCRIPTOR_KEY] service_builder = _ServiceBuilder(descriptor) service_builder.BuildService(cls) + cls.DESCRIPTOR = descriptor class GeneratedServiceStubType(GeneratedServiceType): @@ -106,6 +108,7 @@ def __init__(cls, name, bases, dictionary): # when a service stub is subclassed. if GeneratedServiceStubType._DESCRIPTOR_KEY not in dictionary: return + descriptor = dictionary[GeneratedServiceStubType._DESCRIPTOR_KEY] service_stub_builder = _ServiceStubBuilder(descriptor) service_stub_builder.BuildServiceStub(cls) diff --git a/python/google/protobuf/symbol_database.py b/python/google/protobuf/symbol_database.py index 5ad869f49a76d..fdcf8cf06ced7 100644 --- a/python/google/protobuf/symbol_database.py +++ b/python/google/protobuf/symbol_database.py @@ -34,7 +34,7 @@ and makes it easy to create new instances of a registered type, given only the type's protocol buffer symbol name. -Example usage: +Example usage:: db = symbol_database.SymbolDatabase() @@ -58,6 +58,7 @@ """ +from google.protobuf.internal import api_implementation from google.protobuf import descriptor_pool from google.protobuf import message_factory @@ -71,7 +72,8 @@ def RegisterMessage(self, message): Calls to GetSymbol() and GetMessages() will return messages registered here. Args: - message: a message.Message, to be registered. + message: A :class:`google.protobuf.message.Message` subclass (or + instance); its descriptor will be registered. Returns: The provided message. @@ -86,43 +88,46 @@ def RegisterMessageDescriptor(self, message_descriptor): """Registers the given message descriptor in the local database. Args: - message_descriptor: a descriptor.MessageDescriptor. + message_descriptor (Descriptor): the message descriptor to add. """ - self.pool.AddDescriptor(message_descriptor) + if api_implementation.Type() == 'python': + # pylint: disable=protected-access + self.pool._AddDescriptor(message_descriptor) def RegisterEnumDescriptor(self, enum_descriptor): """Registers the given enum descriptor in the local database. Args: - enum_descriptor: a descriptor.EnumDescriptor. + enum_descriptor (EnumDescriptor): The enum descriptor to register. Returns: - The provided descriptor. + EnumDescriptor: The provided descriptor. """ - self.pool.AddEnumDescriptor(enum_descriptor) + if api_implementation.Type() == 'python': + # pylint: disable=protected-access + self.pool._AddEnumDescriptor(enum_descriptor) return enum_descriptor def RegisterServiceDescriptor(self, service_descriptor): """Registers the given service descriptor in the local database. Args: - service_descriptor: a descriptor.ServiceDescriptor. - - Returns: - The provided descriptor. + service_descriptor (ServiceDescriptor): the service descriptor to + register. """ - self.pool.AddServiceDescriptor(service_descriptor) + if api_implementation.Type() == 'python': + # pylint: disable=protected-access + self.pool._AddServiceDescriptor(service_descriptor) def RegisterFileDescriptor(self, file_descriptor): """Registers the given file descriptor in the local database. Args: - file_descriptor: a descriptor.FileDescriptor. - - Returns: - The provided descriptor. + file_descriptor (FileDescriptor): The file descriptor to register. """ - self.pool.AddFileDescriptor(file_descriptor) + if api_implementation.Type() == 'python': + # pylint: disable=protected-access + self.pool._InternalAddFileDescriptor(file_descriptor) def GetSymbol(self, symbol): """Tries to find a symbol in the local database. @@ -131,7 +136,7 @@ def GetSymbol(self, symbol): may be extended in future to support other symbol types. Args: - symbol: A str, a protocol buffer symbol. + symbol (str): a protocol buffer symbol. Returns: A Python class corresponding to the symbol. @@ -152,7 +157,7 @@ def GetMessages(self, files): messages, but does not register any message extensions. Args: - files: The file names to extract messages from. + files (list[str]): The file names to extract messages from. Returns: A dictionary mapping proto names to the message classes. diff --git a/python/google/protobuf/text_encoding.py b/python/google/protobuf/text_encoding.py index 98995638257e8..39898765f28f2 100644 --- a/python/google/protobuf/text_encoding.py +++ b/python/google/protobuf/text_encoding.py @@ -33,59 +33,70 @@ import six -# Lookup table for utf8 -_cescape_utf8_to_str = [chr(i) for i in range(0, 256)] -_cescape_utf8_to_str[9] = r'\t' # optional escape -_cescape_utf8_to_str[10] = r'\n' # optional escape -_cescape_utf8_to_str[13] = r'\r' # optional escape -_cescape_utf8_to_str[39] = r"\'" # optional escape - -_cescape_utf8_to_str[34] = r'\"' # necessary escape -_cescape_utf8_to_str[92] = r'\\' # necessary escape +_cescape_chr_to_symbol_map = {} +_cescape_chr_to_symbol_map[9] = r'\t' # optional escape +_cescape_chr_to_symbol_map[10] = r'\n' # optional escape +_cescape_chr_to_symbol_map[13] = r'\r' # optional escape +_cescape_chr_to_symbol_map[34] = r'\"' # necessary escape +_cescape_chr_to_symbol_map[39] = r"\'" # optional escape +_cescape_chr_to_symbol_map[92] = r'\\' # necessary escape + +# Lookup table for unicode +_cescape_unicode_to_str = [chr(i) for i in range(0, 256)] +for byte, string in _cescape_chr_to_symbol_map.items(): + _cescape_unicode_to_str[byte] = string # Lookup table for non-utf8, with necessary escapes at (o >= 127 or o < 32) _cescape_byte_to_str = ([r'\%03o' % i for i in range(0, 32)] + [chr(i) for i in range(32, 127)] + [r'\%03o' % i for i in range(127, 256)]) -_cescape_byte_to_str[9] = r'\t' # optional escape -_cescape_byte_to_str[10] = r'\n' # optional escape -_cescape_byte_to_str[13] = r'\r' # optional escape -_cescape_byte_to_str[39] = r"\'" # optional escape - -_cescape_byte_to_str[34] = r'\"' # necessary escape -_cescape_byte_to_str[92] = r'\\' # necessary escape +for byte, string in _cescape_chr_to_symbol_map.items(): + _cescape_byte_to_str[byte] = string +del byte, string def CEscape(text, as_utf8): - """Escape a bytes string for use in an ascii protocol buffer. - - text.encode('string_escape') does not seem to satisfy our needs as it - encodes unprintable characters using two-digit hex escapes whereas our - C++ unescaping function allows hex escapes to be any length. So, - "\0011".encode('string_escape') ends up being "\\x011", which will be - decoded in C++ as a single-character string with char code 0x11. + # type: (...) -> str + """Escape a bytes string for use in an text protocol buffer. Args: - text: A byte string to be escaped - as_utf8: Specifies if result should be returned in UTF-8 encoding + text: A byte string to be escaped. + as_utf8: Specifies if result may contain non-ASCII characters. + In Python 3 this allows unescaped non-ASCII Unicode characters. + In Python 2 the return value will be valid UTF-8 rather than only ASCII. Returns: - Escaped string + Escaped string (str). """ - # PY3 hack: make Ord work for str and bytes: - # //platforms/networking/data uses unicode here, hence basestring. - Ord = ord if isinstance(text, six.string_types) else lambda x: x + # Python's text.encode() 'string_escape' or 'unicode_escape' codecs do not + # satisfy our needs; they encodes unprintable characters using two-digit hex + # escapes whereas our C++ unescaping function allows hex escapes to be any + # length. So, "\0011".encode('string_escape') ends up being "\\x011", which + # will be decoded in C++ as a single-character string with char code 0x11. + if six.PY3: + text_is_unicode = isinstance(text, str) + if as_utf8 and text_is_unicode: + # We're already unicode, no processing beyond control char escapes. + return text.translate(_cescape_chr_to_symbol_map) + ord_ = ord if text_is_unicode else lambda x: x # bytes iterate as ints. + else: + ord_ = ord # PY2 if as_utf8: - return ''.join(_cescape_utf8_to_str[Ord(c)] for c in text) - return ''.join(_cescape_byte_to_str[Ord(c)] for c in text) + return ''.join(_cescape_unicode_to_str[ord_(c)] for c in text) + return ''.join(_cescape_byte_to_str[ord_(c)] for c in text) _CUNESCAPE_HEX = re.compile(r'(\\+)x([0-9a-fA-F])(?![0-9a-fA-F])') -_cescape_highbit_to_str = ([chr(i) for i in range(0, 127)] + - [r'\%03o' % i for i in range(127, 256)]) def CUnescape(text): - """Unescape a text string with C-style escape sequences to UTF-8 bytes.""" + # type: (str) -> bytes + """Unescape a text string with C-style escape sequences to UTF-8 bytes. + + Args: + text: The data to parse in a str. + Returns: + A byte string. + """ def ReplaceHex(m): # Only replace the match if the number of leading back slashes is odd. i.e. @@ -98,10 +109,9 @@ def ReplaceHex(m): # allow single-digit hex escapes (like '\xf'). result = _CUNESCAPE_HEX.sub(ReplaceHex, text) - if str is bytes: # PY2 + if six.PY2: return result.decode('string_escape') - result = ''.join(_cescape_highbit_to_str[ord(c)] for c in result) - return (result.encode('ascii') # Make it bytes to allow decode. + return (result.encode('utf-8') # PY3: Make it bytes to allow decode. .decode('unicode_escape') # Make it bytes again to return the proper type. .encode('raw_unicode_escape')) diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py old mode 100755 new mode 100644 index aaca78ad07913..c376c7bac78aa --- a/python/google/protobuf/text_format.py +++ b/python/google/protobuf/text_format.py @@ -30,7 +30,7 @@ """Contains routines for printing protocol messages in text format. -Simple usage example: +Simple usage example:: # Create a proto object and serialize it to a text proto string. message = my_proto_pb2.MyMessage(foo='bar') @@ -42,30 +42,32 @@ __author__ = 'kenton@google.com (Kenton Varda)' +# TODO(b/129989314) Import thread contention leads to test failures. +import encodings.raw_unicode_escape # pylint: disable=unused-import +import encodings.unicode_escape # pylint: disable=unused-import import io +import math import re - import six -if six.PY3: - long = int # pylint: disable=redefined-builtin,invalid-name - -# pylint: disable=g-import-not-at-top +from google.protobuf.internal import decoder from google.protobuf.internal import type_checkers from google.protobuf import descriptor from google.protobuf import text_encoding -__all__ = ['MessageToString', 'PrintMessage', 'PrintField', 'PrintFieldValue', - 'Merge'] +if six.PY3: + long = int # pylint: disable=redefined-builtin,invalid-name + +# pylint: disable=g-import-not-at-top +__all__ = ['MessageToString', 'Parse', 'PrintMessage', 'PrintField', + 'PrintFieldValue', 'Merge', 'MessageToBytes'] _INTEGER_CHECKERS = (type_checkers.Uint32ValueChecker(), type_checkers.Int32ValueChecker(), type_checkers.Uint64ValueChecker(), type_checkers.Int64ValueChecker()) -_FLOAT_INFINITY = re.compile('-?inf(?:inity)?f?', re.IGNORECASE) -_FLOAT_NAN = re.compile('nanf?', re.IGNORECASE) -_FLOAT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_FLOAT, - descriptor.FieldDescriptor.CPPTYPE_DOUBLE]) +_FLOAT_INFINITY = re.compile('-?inf(?:inity)?f?$', re.IGNORECASE) +_FLOAT_NAN = re.compile('nanf?$', re.IGNORECASE) _QUOTES = frozenset(("'", '"')) _ANY_FULL_TYPE_NAME = 'google.protobuf.Any' @@ -118,48 +120,80 @@ def getvalue(self): return self._writer.getvalue() -def MessageToString(message, - as_utf8=False, - as_one_line=False, - pointy_brackets=False, - use_index_order=False, - float_format=None, - use_field_number=False, - descriptor_pool=None, - indent=0, - message_formatter=None): +def MessageToString( + message, + as_utf8=False, + as_one_line=False, + use_short_repeated_primitives=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + double_format=None, + use_field_number=False, + descriptor_pool=None, + indent=0, + message_formatter=None, + print_unknown_fields=False, + force_colon=False): + # type: (...) -> str """Convert protobuf message to text format. - Floating point values can be formatted compactly with 15 digits of + Double values can be formatted compactly with 15 digits of precision (which is the most that IEEE 754 "double" can guarantee) - using float_format='.15g'. To ensure that converting to text and back to a - proto will result in an identical value, float_format='.17g' should be used. + using double_format='.15g'. To ensure that converting to text and back to a + proto will result in an identical value, double_format='.17g' should be used. Args: message: The protocol buffers message. - as_utf8: Produce text output in UTF8 format. + as_utf8: Return unescaped Unicode for non-ASCII characters. + In Python 3 actual Unicode characters may appear as is in strings. + In Python 2 the return value will be valid UTF-8 rather than only ASCII. as_one_line: Don't introduce newlines between fields. + use_short_repeated_primitives: Use short repeated format for primitives. pointy_brackets: If True, use angle brackets instead of curly braces for nesting. - use_index_order: If True, print fields of a proto message using the order - defined in source code instead of the field number. By default, use the - field number order. - float_format: If set, use this to specify floating point number formatting - (per the "Format Specification Mini-Language"); otherwise, str() is used. + use_index_order: If True, fields of a proto message will be printed using + the order defined in source code instead of the field number, extensions + will be printed at the end of the message and their relative order is + determined by the extension number. By default, use the field number + order. + float_format (str): If set, use this to specify float field formatting + (per the "Format Specification Mini-Language"); otherwise, shortest float + that has same value in wire will be printed. Also affect double field + if double_format is not set but float_format is set. + double_format (str): If set, use this to specify double field formatting + (per the "Format Specification Mini-Language"); if it is not set but + float_format is set, use float_format. Otherwise, use ``str()`` use_field_number: If True, print field numbers instead of names. - descriptor_pool: A DescriptorPool used to resolve Any types. - indent: The indent level, in terms of spaces, for pretty print. - message_formatter: A function(message, indent, as_one_line): unicode|None - to custom format selected sub-messages (usually based on message type). - Use to pretty print parts of the protobuf for easier diffing. + descriptor_pool (DescriptorPool): Descriptor pool used to resolve Any types. + indent (int): The initial indent level, in terms of spaces, for pretty + print. + message_formatter (function(message, indent, as_one_line) -> unicode|None): + Custom formatter for selected sub-messages (usually based on message + type). Use to pretty print parts of the protobuf for easier diffing. + print_unknown_fields: If True, unknown fields will be printed. + force_colon: If set, a colon will be added after the field name even if the + field is a proto message. Returns: - A string of the text formatted protocol buffer message. + str: A string of the text formatted protocol buffer message. """ out = TextWriter(as_utf8) - printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets, - use_index_order, float_format, use_field_number, - descriptor_pool, message_formatter) + printer = _Printer( + out, + indent, + as_utf8, + as_one_line, + use_short_repeated_primitives, + pointy_brackets, + use_index_order, + float_format, + double_format, + use_field_number, + descriptor_pool, + message_formatter, + print_unknown_fields=print_unknown_fields, + force_colon=force_colon) printer.PrintMessage(message) result = out.getvalue() out.close() @@ -168,6 +202,16 @@ def MessageToString(message, return result +def MessageToBytes(message, **kwargs): + # type: (...) -> bytes + """Convert protobuf message to encoded text format. See MessageToString.""" + text = MessageToString(message, **kwargs) + if isinstance(text, bytes): + return text + codec = 'utf-8' if kwargs.get('as_utf8') else 'ascii' + return text.encode(codec) + + def _IsMapEntry(field): return (field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and field.message_type.has_options and @@ -179,15 +223,29 @@ def PrintMessage(message, indent=0, as_utf8=False, as_one_line=False, + use_short_repeated_primitives=False, pointy_brackets=False, use_index_order=False, float_format=None, + double_format=None, use_field_number=False, descriptor_pool=None, - message_formatter=None): - printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets, - use_index_order, float_format, use_field_number, - descriptor_pool, message_formatter) + message_formatter=None, + print_unknown_fields=False, + force_colon=False): + printer = _Printer( + out=out, indent=indent, as_utf8=as_utf8, + as_one_line=as_one_line, + use_short_repeated_primitives=use_short_repeated_primitives, + pointy_brackets=pointy_brackets, + use_index_order=use_index_order, + float_format=float_format, + double_format=double_format, + use_field_number=use_field_number, + descriptor_pool=descriptor_pool, + message_formatter=message_formatter, + print_unknown_fields=print_unknown_fields, + force_colon=force_colon) printer.PrintMessage(message) @@ -197,13 +255,21 @@ def PrintField(field, indent=0, as_utf8=False, as_one_line=False, + use_short_repeated_primitives=False, pointy_brackets=False, use_index_order=False, float_format=None, - message_formatter=None): + double_format=None, + message_formatter=None, + print_unknown_fields=False, + force_colon=False): """Print a single field name/value pair.""" - printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets, - use_index_order, float_format, message_formatter) + printer = _Printer(out, indent, as_utf8, as_one_line, + use_short_repeated_primitives, pointy_brackets, + use_index_order, float_format, double_format, + message_formatter=message_formatter, + print_unknown_fields=print_unknown_fields, + force_colon=force_colon) printer.PrintField(field, value) @@ -213,13 +279,21 @@ def PrintFieldValue(field, indent=0, as_utf8=False, as_one_line=False, + use_short_repeated_primitives=False, pointy_brackets=False, use_index_order=False, float_format=None, - message_formatter=None): + double_format=None, + message_formatter=None, + print_unknown_fields=False, + force_colon=False): """Print a single field value (not including name).""" - printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets, - use_index_order, float_format, message_formatter) + printer = _Printer(out, indent, as_utf8, as_one_line, + use_short_repeated_primitives, pointy_brackets, + use_index_order, float_format, double_format, + message_formatter=message_formatter, + print_unknown_fields=print_unknown_fields, + force_colon=force_colon) printer.PrintFieldValue(field, value) @@ -248,64 +322,94 @@ def _BuildMessageFromTypeName(type_name, descriptor_pool): return message_type() +# These values must match WireType enum in google/protobuf/wire_format.h. +WIRETYPE_LENGTH_DELIMITED = 2 +WIRETYPE_START_GROUP = 3 + + class _Printer(object): """Text format printer for protocol message.""" - def __init__(self, - out, - indent=0, - as_utf8=False, - as_one_line=False, - pointy_brackets=False, - use_index_order=False, - float_format=None, - use_field_number=False, - descriptor_pool=None, - message_formatter=None): + def __init__( + self, + out, + indent=0, + as_utf8=False, + as_one_line=False, + use_short_repeated_primitives=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + double_format=None, + use_field_number=False, + descriptor_pool=None, + message_formatter=None, + print_unknown_fields=False, + force_colon=False): """Initialize the Printer. - Floating point values can be formatted compactly with 15 digits of - precision (which is the most that IEEE 754 "double" can guarantee) - using float_format='.15g'. To ensure that converting to text and back to a - proto will result in an identical value, float_format='.17g' should be used. + Double values can be formatted compactly with 15 digits of precision + (which is the most that IEEE 754 "double" can guarantee) using + double_format='.15g'. To ensure that converting to text and back to a proto + will result in an identical value, double_format='.17g' should be used. Args: out: To record the text format result. - indent: The indent level for pretty print. - as_utf8: Produce text output in UTF8 format. + indent: The initial indent level for pretty print. + as_utf8: Return unescaped Unicode for non-ASCII characters. + In Python 3 actual Unicode characters may appear as is in strings. + In Python 2 the return value will be valid UTF-8 rather than ASCII. as_one_line: Don't introduce newlines between fields. + use_short_repeated_primitives: Use short repeated format for primitives. pointy_brackets: If True, use angle brackets instead of curly braces for nesting. use_index_order: If True, print fields of a proto message using the order defined in source code instead of the field number. By default, use the field number order. - float_format: If set, use this to specify floating point number formatting - (per the "Format Specification Mini-Language"); otherwise, str() is - used. + float_format: If set, use this to specify float field formatting + (per the "Format Specification Mini-Language"); otherwise, shortest + float that has same value in wire will be printed. Also affect double + field if double_format is not set but float_format is set. + double_format: If set, use this to specify double field formatting + (per the "Format Specification Mini-Language"); if it is not set but + float_format is set, use float_format. Otherwise, str() is used. use_field_number: If True, print field numbers instead of names. descriptor_pool: A DescriptorPool used to resolve Any types. message_formatter: A function(message, indent, as_one_line): unicode|None to custom format selected sub-messages (usually based on message type). Use to pretty print parts of the protobuf for easier diffing. + print_unknown_fields: If True, unknown fields will be printed. + force_colon: If set, a colon will be added after the field name even if + the field is a proto message. """ self.out = out self.indent = indent self.as_utf8 = as_utf8 self.as_one_line = as_one_line + self.use_short_repeated_primitives = use_short_repeated_primitives self.pointy_brackets = pointy_brackets self.use_index_order = use_index_order self.float_format = float_format + if double_format is not None: + self.double_format = double_format + else: + self.double_format = float_format self.use_field_number = use_field_number self.descriptor_pool = descriptor_pool self.message_formatter = message_formatter + self.print_unknown_fields = print_unknown_fields + self.force_colon = force_colon def _TryPrintAsAnyMessage(self, message): """Serializes if message is a google.protobuf.Any field.""" + if '/' not in message.type_url: + return False packed_message = _BuildMessageFromTypeName(message.TypeName(), self.descriptor_pool) if packed_message: packed_message.MergeFromString(message.value) - self.out.write('%s[%s]' % (self.indent * ' ', message.type_url)) + colon = ':' if self.force_colon else '' + self.out.write('%s[%s]%s ' % (self.indent * ' ', message.type_url, colon)) self._PrintMessageFieldValue(packed_message) self.out.write(' ' if self.as_one_line else '\n') return True @@ -336,11 +440,12 @@ def PrintMessage(self, message): return fields = message.ListFields() if self.use_index_order: - fields.sort(key=lambda x: x[0].index) + fields.sort( + key=lambda x: x[0].number if x[0].is_extension else x[0].index) for field, value in fields: if _IsMapEntry(field): for key in sorted(value): - # This is slow for maps with submessage entires because it copies the + # This is slow for maps with submessage entries because it copies the # entire tree. Unfortunately this would take significant refactoring # of this file to work around. # @@ -348,13 +453,76 @@ def PrintMessage(self, message): entry_submsg = value.GetEntryClass()(key=key, value=value[key]) self.PrintField(field, entry_submsg) elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED: - for element in value: - self.PrintField(field, element) + if (self.use_short_repeated_primitives + and field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE + and field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_STRING): + self._PrintShortRepeatedPrimitivesValue(field, value) + else: + for element in value: + self.PrintField(field, element) else: self.PrintField(field, value) - def PrintField(self, field, value): - """Print a single field name/value pair.""" + if self.print_unknown_fields: + self._PrintUnknownFields(message.UnknownFields()) + + def _PrintUnknownFields(self, unknown_fields): + """Print unknown fields.""" + out = self.out + for field in unknown_fields: + out.write(' ' * self.indent) + out.write(str(field.field_number)) + if field.wire_type == WIRETYPE_START_GROUP: + if self.as_one_line: + out.write(' { ') + else: + out.write(' {\n') + self.indent += 2 + + self._PrintUnknownFields(field.data) + + if self.as_one_line: + out.write('} ') + else: + self.indent -= 2 + out.write(' ' * self.indent + '}\n') + elif field.wire_type == WIRETYPE_LENGTH_DELIMITED: + try: + # If this field is parseable as a Message, it is probably + # an embedded message. + # pylint: disable=protected-access + (embedded_unknown_message, pos) = decoder._DecodeUnknownFieldSet( + memoryview(field.data), 0, len(field.data)) + except Exception: # pylint: disable=broad-except + pos = 0 + + if pos == len(field.data): + if self.as_one_line: + out.write(' { ') + else: + out.write(' {\n') + self.indent += 2 + + self._PrintUnknownFields(embedded_unknown_message) + + if self.as_one_line: + out.write('} ') + else: + self.indent -= 2 + out.write(' ' * self.indent + '}\n') + else: + # A string or bytes field. self.as_utf8 may not work. + out.write(': \"') + out.write(text_encoding.CEscape(field.data, False)) + out.write('\" ' if self.as_one_line else '\"\n') + else: + # varint, fixed32, fixed64 + out.write(': ') + out.write(str(field.data)) + out.write(' ' if self.as_one_line else '\n') + + def _PrintFieldName(self, field): + """Print field name.""" out = self.out out.write(' ' * self.indent) if self.use_field_number: @@ -373,18 +541,35 @@ def PrintField(self, field, value): # For groups, use the capitalized name. out.write(field.message_type.name) else: - out.write(field.name) + out.write(field.name) - if field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + if (self.force_colon or + field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE): # The colon is optional in this case, but our cross-language golden files - # don't include it. - out.write(': ') + # don't include it. Here, the colon is only included if force_colon is + # set to True + out.write(':') + def PrintField(self, field, value): + """Print a single field name/value pair.""" + self._PrintFieldName(field) + self.out.write(' ') self.PrintFieldValue(field, value) - if self.as_one_line: - out.write(' ') - else: - out.write('\n') + self.out.write(' ' if self.as_one_line else '\n') + + def _PrintShortRepeatedPrimitivesValue(self, field, value): + """"Prints short repeated primitives value.""" + # Note: this is called only when value has at least one element. + self._PrintFieldName(field) + self.out.write(' [') + for i in six.moves.range(len(value) - 1): + self.PrintFieldValue(field, value[i]) + self.out.write(', ') + self.PrintFieldValue(field, value[-1]) + self.out.write(']') + if self.force_colon: + self.out.write(':') + self.out.write(' ' if self.as_one_line else '\n') def _PrintMessageFieldValue(self, value): if self.pointy_brackets: @@ -395,11 +580,11 @@ def _PrintMessageFieldValue(self, value): closeb = '}' if self.as_one_line: - self.out.write(' %s ' % openb) + self.out.write('%s ' % openb) self.PrintMessage(value) self.out.write(closeb) else: - self.out.write(' %s\n' % openb) + self.out.write('%s\n' % openb) self.indent += 2 self.PrintMessage(value) self.indent -= 2 @@ -425,12 +610,12 @@ def PrintFieldValue(self, field, value): out.write(str(value)) elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING: out.write('\"') - if isinstance(value, six.text_type): + if isinstance(value, six.text_type) and (six.PY2 or not self.as_utf8): out_value = value.encode('utf-8') else: out_value = value if field.type == descriptor.FieldDescriptor.TYPE_BYTES: - # We need to escape non-UTF8 chars in TYPE_BYTES field. + # We always need to escape all binary data in TYPE_BYTES fields. out_as_utf8 = False else: out_as_utf8 = self.as_utf8 @@ -441,8 +626,17 @@ def PrintFieldValue(self, field, value): out.write('true') else: out.write('false') - elif field.cpp_type in _FLOAT_TYPES and self.float_format is not None: - out.write('{1:{0}}'.format(self.float_format, value)) + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT: + if self.float_format is not None: + out.write('{1:{0}}'.format(self.float_format, value)) + else: + if math.isnan(value): + out.write(str(value)) + else: + out.write(str(type_checkers.ToShortestFloat(value))) + elif (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_DOUBLE and + self.double_format is not None): + out.write('{1:{0}}'.format(self.double_format, value)) else: out.write(str(value)) @@ -451,87 +645,108 @@ def Parse(text, message, allow_unknown_extension=False, allow_field_number=False, - descriptor_pool=None): + descriptor_pool=None, + allow_unknown_field=False): """Parses a text representation of a protocol message into a message. NOTE: for historical reasons this function does not clear the input message. This is different from what the binary msg.ParseFrom(...) does. + If text contains a field already set in message, the value is appended if the + field is repeated. Otherwise, an error is raised. + + Example:: - Example a = MyProto() a.repeated_field.append('test') b = MyProto() + # Repeated fields are combined text_format.Parse(repr(a), b) text_format.Parse(repr(a), b) # repeated_field contains ["test", "test"] + # Non-repeated fields cannot be overwritten + a.singular_field = 1 + b.singular_field = 2 + text_format.Parse(repr(a), b) # ParseError + # Binary version: b.ParseFromString(a.SerializeToString()) # repeated_field is now "test" Caller is responsible for clearing the message as needed. Args: - text: Message text representation. - message: A protocol buffer message to merge into. + text (str): Message text representation. + message (Message): A protocol buffer message to merge into. allow_unknown_extension: if True, skip over missing extensions and keep parsing allow_field_number: if True, both field number and field name are allowed. - descriptor_pool: A DescriptorPool used to resolve Any types. + descriptor_pool (DescriptorPool): Descriptor pool used to resolve Any types. + allow_unknown_field: if True, skip over unknown field and keep + parsing. Avoid to use this option if possible. It may hide some + errors (e.g. spelling error on field name) Returns: - The same message passed as argument. + Message: The same message passed as argument. Raises: ParseError: On text parsing problems. """ - if not isinstance(text, str): - text = text.decode('utf-8') - return ParseLines(text.split('\n'), + return ParseLines(text.split(b'\n' if isinstance(text, bytes) else u'\n'), message, allow_unknown_extension, allow_field_number, - descriptor_pool=descriptor_pool) + descriptor_pool=descriptor_pool, + allow_unknown_field=allow_unknown_field) def Merge(text, message, allow_unknown_extension=False, allow_field_number=False, - descriptor_pool=None): + descriptor_pool=None, + allow_unknown_field=False): """Parses a text representation of a protocol message into a message. Like Parse(), but allows repeated values for a non-repeated field, and uses - the last one. + the last one. This means any non-repeated, top-level fields specified in text + replace those in the message. Args: - text: Message text representation. - message: A protocol buffer message to merge into. + text (str): Message text representation. + message (Message): A protocol buffer message to merge into. allow_unknown_extension: if True, skip over missing extensions and keep parsing allow_field_number: if True, both field number and field name are allowed. - descriptor_pool: A DescriptorPool used to resolve Any types. + descriptor_pool (DescriptorPool): Descriptor pool used to resolve Any types. + allow_unknown_field: if True, skip over unknown field and keep + parsing. Avoid to use this option if possible. It may hide some + errors (e.g. spelling error on field name) Returns: - The same message passed as argument. + Message: The same message passed as argument. Raises: ParseError: On text parsing problems. """ return MergeLines( - text.split('\n'), + text.split(b'\n' if isinstance(text, bytes) else u'\n'), message, allow_unknown_extension, allow_field_number, - descriptor_pool=descriptor_pool) + descriptor_pool=descriptor_pool, + allow_unknown_field=allow_unknown_field) def ParseLines(lines, message, allow_unknown_extension=False, allow_field_number=False, - descriptor_pool=None): + descriptor_pool=None, + allow_unknown_field=False): """Parses a text representation of a protocol message into a message. + See Parse() for caveats. + Args: lines: An iterable of lines of a message's text representation. message: A protocol buffer message to merge into. @@ -539,6 +754,9 @@ def ParseLines(lines, parsing allow_field_number: if True, both field number and field name are allowed. descriptor_pool: A DescriptorPool used to resolve Any types. + allow_unknown_field: if True, skip over unknown field and keep + parsing. Avoid to use this option if possible. It may hide some + errors (e.g. spelling error on field name) Returns: The same message passed as argument. @@ -548,7 +766,8 @@ def ParseLines(lines, """ parser = _Parser(allow_unknown_extension, allow_field_number, - descriptor_pool=descriptor_pool) + descriptor_pool=descriptor_pool, + allow_unknown_field=allow_unknown_field) return parser.ParseLines(lines, message) @@ -556,9 +775,12 @@ def MergeLines(lines, message, allow_unknown_extension=False, allow_field_number=False, - descriptor_pool=None): + descriptor_pool=None, + allow_unknown_field=False): """Parses a text representation of a protocol message into a message. + See Merge() for more details. + Args: lines: An iterable of lines of a message's text representation. message: A protocol buffer message to merge into. @@ -566,6 +788,9 @@ def MergeLines(lines, parsing allow_field_number: if True, both field number and field name are allowed. descriptor_pool: A DescriptorPool used to resolve Any types. + allow_unknown_field: if True, skip over unknown field and keep + parsing. Avoid to use this option if possible. It may hide some + errors (e.g. spelling error on field name) Returns: The same message passed as argument. @@ -575,7 +800,8 @@ def MergeLines(lines, """ parser = _Parser(allow_unknown_extension, allow_field_number, - descriptor_pool=descriptor_pool) + descriptor_pool=descriptor_pool, + allow_unknown_field=allow_unknown_field) return parser.MergeLines(lines, message) @@ -585,16 +811,12 @@ class _Parser(object): def __init__(self, allow_unknown_extension=False, allow_field_number=False, - descriptor_pool=None): + descriptor_pool=None, + allow_unknown_field=False): self.allow_unknown_extension = allow_unknown_extension self.allow_field_number = allow_field_number self.descriptor_pool = descriptor_pool - - def ParseFromString(self, text, message): - """Parses a text representation of a protocol message into a message.""" - if not isinstance(text, str): - text = text.decode('utf-8') - return self.ParseLines(text.split('\n'), message) + self.allow_unknown_field = allow_unknown_field def ParseLines(self, lines, message): """Parses a text representation of a protocol message into a message.""" @@ -602,10 +824,6 @@ def ParseLines(self, lines, message): self._ParseOrMerge(lines, message) return message - def MergeFromString(self, text, message): - """Merges a text representation of a protocol message into a message.""" - return self._MergeLines(text.split('\n'), message) - def MergeLines(self, lines, message): """Merges a text representation of a protocol message into a message.""" self._allow_multiple_scalars = True @@ -622,7 +840,14 @@ def _ParseOrMerge(self, lines, message): Raises: ParseError: On text parsing problems. """ - tokenizer = Tokenizer(lines) + # Tokenize expects native str lines. + if six.PY2: + str_lines = (line if isinstance(line, str) else line.encode('utf-8') + for line in lines) + else: + str_lines = (line if isinstance(line, str) else line.decode('utf-8') + for line in lines) + tokenizer = Tokenizer(str_lines) while not tokenizer.AtEnd(): self._MergeField(tokenizer, message) @@ -637,6 +862,33 @@ def _MergeField(self, tokenizer, message): ParseError: In case of text parsing problems. """ message_descriptor = message.DESCRIPTOR + if (message_descriptor.full_name == _ANY_FULL_TYPE_NAME and + tokenizer.TryConsume('[')): + type_url_prefix, packed_type_name = self._ConsumeAnyTypeUrl(tokenizer) + tokenizer.Consume(']') + tokenizer.TryConsume(':') + if tokenizer.TryConsume('<'): + expanded_any_end_token = '>' + else: + tokenizer.Consume('{') + expanded_any_end_token = '}' + expanded_any_sub_message = _BuildMessageFromTypeName(packed_type_name, + self.descriptor_pool) + if not expanded_any_sub_message: + raise ParseError('Type %s not found in descriptor pool' % + packed_type_name) + while not tokenizer.TryConsume(expanded_any_end_token): + if tokenizer.AtEnd(): + raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % + (expanded_any_end_token,)) + self._MergeField(tokenizer, expanded_any_sub_message) + deterministic = False + + message.Pack(expanded_any_sub_message, + type_url_prefix=type_url_prefix, + deterministic=deterministic) + return + if tokenizer.TryConsume('['): name = [tokenizer.ConsumeIdentifier()] while tokenizer.TryConsume('.'): @@ -650,6 +902,8 @@ def _MergeField(self, tokenizer, message): # pylint: disable=protected-access field = message.Extensions._FindExtensionByName(name) # pylint: enable=protected-access + + if not field: if self.allow_unknown_extension: field = None @@ -689,7 +943,7 @@ def _MergeField(self, tokenizer, message): field.message_type.name != name): field = None - if not field: + if not field and not self.allow_unknown_field: raise tokenizer.ParseErrorPreviousToken( 'Message type "%s" has no field named "%s".' % (message_descriptor.full_name, name)) @@ -717,17 +971,18 @@ def _MergeField(self, tokenizer, message): if (field.label == descriptor.FieldDescriptor.LABEL_REPEATED and tokenizer.TryConsume('[')): # Short repeated format, e.g. "foo: [1, 2, 3]" - while True: - merger(tokenizer, message, field) - if tokenizer.TryConsume(']'): - break - tokenizer.Consume(',') + if not tokenizer.TryConsume(']'): + while True: + merger(tokenizer, message, field) + if tokenizer.TryConsume(']'): + break + tokenizer.Consume(',') else: merger(tokenizer, message, field) else: # Proto field is unknown. - assert self.allow_unknown_extension + assert (self.allow_unknown_extension or self.allow_unknown_field) _SkipFieldContents(tokenizer) # For historical reasons, fields may optionally be separated by commas or @@ -735,6 +990,7 @@ def _MergeField(self, tokenizer, message): if not tokenizer.TryConsume(','): tokenizer.TryConsume(';') + def _ConsumeAnyTypeUrl(self, tokenizer): """Consumes a google.protobuf.Any type URL and returns the type name.""" # Consume "type.googleapis.com/". @@ -769,33 +1025,7 @@ def _MergeMessageField(self, tokenizer, message, field): tokenizer.Consume('{') end_token = '}' - if (field.message_type.full_name == _ANY_FULL_TYPE_NAME and - tokenizer.TryConsume('[')): - type_url_prefix, packed_type_name = self._ConsumeAnyTypeUrl(tokenizer) - tokenizer.Consume(']') - tokenizer.TryConsume(':') - if tokenizer.TryConsume('<'): - expanded_any_end_token = '>' - else: - tokenizer.Consume('{') - expanded_any_end_token = '}' - expanded_any_sub_message = _BuildMessageFromTypeName(packed_type_name, - self.descriptor_pool) - if not expanded_any_sub_message: - raise ParseError('Type %s not found in descriptor pool' % - packed_type_name) - while not tokenizer.TryConsume(expanded_any_end_token): - if tokenizer.AtEnd(): - raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % - (expanded_any_end_token,)) - self._MergeField(tokenizer, expanded_any_sub_message) - if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: - any_message = getattr(message, field.name).add() - else: - any_message = getattr(message, field.name) - any_message.Pack(expanded_any_sub_message, - type_url_prefix=type_url_prefix) - elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: if field.is_extension: sub_message = message.Extensions[field].add() elif is_map_entry: @@ -804,8 +1034,20 @@ def _MergeMessageField(self, tokenizer, message, field): sub_message = getattr(message, field.name).add() else: if field.is_extension: + if (not self._allow_multiple_scalars and + message.HasExtension(field)): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" extensions.' % + (message.DESCRIPTOR.full_name, field.full_name)) sub_message = message.Extensions[field] else: + # Also apply _allow_multiple_scalars to message field. + # TODO(jieluo): Change to _allow_singular_overwrites. + if (not self._allow_multiple_scalars and + message.HasField(field.name)): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" fields.' % + (message.DESCRIPTOR.full_name, field.name)) sub_message = getattr(message, field.name) sub_message.SetInParent() @@ -877,11 +1119,9 @@ def _MergeScalarField(self, tokenizer, message, field): else: getattr(message, field.name).append(value) else: - # Proto3 doesn't represent presence so we can't test if multiple scalars - # have occurred. We have to allow them. - can_check_presence = not self._IsProto3Syntax(message) if field.is_extension: - if (not self._allow_multiple_scalars and can_check_presence and + if (not self._allow_multiple_scalars and + not self._IsProto3Syntax(message) and message.HasExtension(field)): raise tokenizer.ParseErrorPreviousToken( 'Message type "%s" should not have multiple "%s" extensions.' % @@ -889,8 +1129,16 @@ def _MergeScalarField(self, tokenizer, message, field): else: message.Extensions[field] = value else: - if (not self._allow_multiple_scalars and can_check_presence and - message.HasField(field.name)): + duplicate_error = False + if not self._allow_multiple_scalars: + if self._IsProto3Syntax(message): + # Proto3 doesn't represent presence so we try best effort to check + # multiple scalars by compare to default values. + duplicate_error = bool(getattr(message, field.name)) + else: + duplicate_error = message.HasField(field.name) + + if duplicate_error: raise tokenizer.ParseErrorPreviousToken( 'Message type "%s" should not have multiple "%s" fields.' % (message.DESCRIPTOR.full_name, field.name)) @@ -930,7 +1178,7 @@ def _SkipField(tokenizer): tokenizer.ConsumeIdentifier() tokenizer.Consume(']') else: - tokenizer.ConsumeIdentifier() + tokenizer.ConsumeIdentifierOrNumber() _SkipFieldContents(tokenizer) @@ -997,7 +1245,9 @@ class Tokenizer(object): r'[a-zA-Z_][0-9a-zA-Z_+-]*', # an identifier r'([0-9+-]|(\.[0-9]))[0-9a-zA-Z_.+-]*', # a number ] + [ # quoted str for each quote mark - r'{qt}([^{qt}\n\\]|\\.)*({qt}|\\?$)'.format(qt=mark) for mark in _QUOTES + # Avoid backtracking! https://stackoverflow.com/a/844267 + r'{qt}[^{qt}\n\\]*((\\.)+[^{qt}\n\\]*)*({qt}|\\?$)'.format(qt=mark) + for mark in _QUOTES ])) _IDENTIFIER = re.compile(r'[^\d\W]\w*') @@ -1294,7 +1544,8 @@ def ParseErrorPreviousToken(self, message): def ParseError(self, message): """Creates and *returns* a ParseError for the current token.""" - return ParseError(message, self._line + 1, self._column + 1) + return ParseError('\'' + self._current_line + '\': ' + message, + self._line + 1, self._column + 1) def _StringParseError(self, e): return self.ParseError('Couldn\'t parse string: ' + str(e)) @@ -1468,6 +1719,12 @@ def _ParseAbstractInteger(text, is_long=False): ValueError: Thrown Iff the text is not a valid integer. """ # Do the actual parsing. Exception handling is propagated to caller. + orig_text = text + c_octal_match = re.match(r'(-?)0(\d+)$', text) + if c_octal_match: + # Python 3 no longer supports 0755 octal syntax without the 'o', so + # we always use the '0o' prefix for multi-digit numbers starting with 0. + text = c_octal_match.group(1) + '0o' + c_octal_match.group(2) try: # We force 32-bit values to int and 64-bit values to long to make # alternate implementations where the distinction is more significant @@ -1477,7 +1734,7 @@ def _ParseAbstractInteger(text, is_long=False): else: return int(text, 0) except ValueError: - raise ValueError('Couldn\'t parse integer: %s' % text) + raise ValueError('Couldn\'t parse integer: %s' % orig_text) def ParseFloat(text): @@ -1559,6 +1816,11 @@ def ParseEnum(field, value): (enum_descriptor.full_name, value)) else: # Numeric value. + if hasattr(field.file, 'syntax'): + # Attribute is checked for compatibility. + if field.file.syntax == 'proto3': + # Proto3 accept numeric unknown enums. + return number enum_value = enum_descriptor.values_by_number.get(number, None) if enum_value is None: raise ValueError('Enum type "%s" has no value with number %d.' % diff --git a/python/google/protobuf/util/__init__.py b/python/google/protobuf/util/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/python/mox.py b/python/mox.py index 257468e52d728..9dd8ac7eb4613 100755 --- a/python/mox.py +++ b/python/mox.py @@ -705,7 +705,7 @@ def MultipleTimes(self, group_name="default"): """Move this method into group of calls which may be called multiple times. A group of repeating calls must be defined together, and must be executed in - full before the next expected mehtod can be called. + full before the next expected method can be called. Args: group_name: the name of the unordered group. @@ -778,7 +778,7 @@ def equals(self, rhs): rhs: any python object """ - raise NotImplementedError, 'method must be implemented by a subclass.' + raise NotImplementedError('method must be implemented by a subclass.') def __eq__(self, rhs): return self.equals(rhs) diff --git a/python/protobuf_distutils/README.md b/python/protobuf_distutils/README.md new file mode 100644 index 0000000000000..63d12b5200b5f --- /dev/null +++ b/python/protobuf_distutils/README.md @@ -0,0 +1,121 @@ +# Python setuptools extension + +This is an extension for Python setuptools which uses an installed protobuf +compiler (`protoc`) to generate Python sources. + +## Installing + +To use this extension, it needs to be installed so it can be imported by other +projects' setup.py. + +```shell +$ python setup.py build +$ python -m pip install . +``` + +(If you want to test changes to the extension, you can use `python setup.py +develop`.) + +## Usage + +### Example setup.py configuration + +```python +from setuptools import setup +setup( + # ... + name='example_project', + + # Require this package, but only for setup (not installation): + setup_requires=['protobuf_distutils'], + + options={ + # See below for details. + 'generate_py_protobufs': { + 'source_dir': 'path/to/protos', + 'extra_proto_paths': ['path/to/other/project/protos'], + 'output_dir': 'path/to/project/sources', # default '.' + 'proto_files': ['relative/path/to/just_this_file.proto'], + 'protoc': 'path/to/protoc.exe', + }, + }, +) +``` + +### Example build invocation + +These steps will generate protobuf sources so they are included when building +and installing `example_project` (see above): + +```shell +$ python setup.py generate_py_protobufs +$ python setup.py build +$ python -m pip install . +``` + +## Options + +- `source_dir`: + + This is the directory holding .proto files to be processed. + + The default behavior is to generate sources for all .proto files found under + `source_dir`, recursively. This behavior can be controlled with options below. + +- `proto_root_path`: + + This is the root path for resolving imports in source .proto files. + + The default is the shortest prefix of `source_dir` among `[source_dir] + + self.extra_proto_paths`. + +- `extra_proto_paths`: + + Specifies additional paths that should be used to find imports, in + addition to `source_dir`. + + This option can be used to specify the path to other protobuf sources, + which are imported by files under `source_dir`. No Python code will + be generated for .proto files under `extra_proto_paths`. + +- `output_dir`: + + Specifies where generated code should be placed. + + Typically, this should be the root package that generated Python modules + should be below. + + The generated files will be placed under `output_dir` according to the + relative source paths under `proto_root_path`. For example, the source file + `${proto_root_path}/subdir/message.proto` will be generated as the Python + module `${output_dir}/subdir/message_pb2.py`. + +- `proto_files`: + + A list of strings, specific .proto file paths for generating code, instead of + searching for all .proto files under `source_path`. + + These paths are relative to `source_dir`. For example, to generate code + for just `${source_dir}/subdir/message.proto`, specify + `['subdir/message.proto']`. + +- `protoc`: + + By default, the protoc binary (the Protobuf compiler) is found by + searching the environment path. To use a specific protoc binary, its + path can be specified. Resolution of the `protoc` value is as follows: + 1. If the `--protoc=VALUE` flag is passed to `generate_py_protobufs`, + then `VALUE` will be used. + For example: + ```shell + $ python setup.py generate_py_protobufs --protoc=/path/to/protoc + ``` + 2. Otherwise, if a value was set in the `options`, it will be used. + (See "Example setup.py configuration," above.) + 3. Otherwise, if the `PROTOC` environment variable is set, it will be + used. For example: + For example: + ```shell + $ PROTOC=/path/to/protoc python setup.py generate_py_protobufs + ``` + 4. Otherwise, `$PATH` will be searched. diff --git a/python/protobuf_distutils/protobuf_distutils/__init__.py b/python/protobuf_distutils/protobuf_distutils/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/python/protobuf_distutils/protobuf_distutils/generate_py_protobufs.py b/python/protobuf_distutils/protobuf_distutils/generate_py_protobufs.py new file mode 100644 index 0000000000000..515ded2334e38 --- /dev/null +++ b/python/protobuf_distutils/protobuf_distutils/generate_py_protobufs.py @@ -0,0 +1,147 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Implements the generate_py_protobufs command.""" + +__author__ = 'dlj@google.com (David L. Jones)' + +import glob +import sys +import os +import distutils.spawn as spawn +from distutils.cmd import Command +from distutils.errors import DistutilsOptionError, DistutilsExecError + +class generate_py_protobufs(Command): + """Generates Python sources for .proto files.""" + + description = 'Generate Python sources for .proto files' + user_options = [ + ('extra-proto-paths=', None, + 'Additional paths to resolve imports in .proto files.'), + + ('protoc=', None, + 'Path to a specific `protoc` command to use.'), + ] + boolean_options = ['recurse'] + + def initialize_options(self): + """Sets the defaults for the command options.""" + self.source_dir = None + self.proto_root_path = None + self.extra_proto_paths = [] + self.output_dir = '.' + self.proto_files = None + self.recurse = True + self.protoc = None + + def finalize_options(self): + """Sets the final values for the command options. + + Defaults were set in `initialize_options`, but could have been changed + by command-line options or by other commands. + """ + self.ensure_dirname('source_dir') + self.ensure_string_list('extra_proto_paths') + + if self.output_dir is None: + self.output_dir = '.' + self.ensure_dirname('output_dir') + + # SUBTLE: if 'source_dir' is a subdirectory of any entry in + # 'extra_proto_paths', then in general, the shortest --proto_path prefix + # (and the longest relative .proto filenames) must be used for + # correctness. For example, consider: + # + # source_dir = 'a/b/c' + # extra_proto_paths = ['a/b', 'x/y'] + # + # In this case, we must ensure that a/b/c/d/foo.proto resolves + # canonically as c/d/foo.proto, not just d/foo.proto. Otherwise, this + # import: + # + # import "c/d/foo.proto"; + # + # would result in different FileDescriptor.name keys from "d/foo.proto". + # That will cause all the definitions in the file to be flagged as + # duplicates, with an error similar to: + # + # c/d/foo.proto: "packagename.MessageName" is already defined in file "d/foo.proto" + # + # For paths in self.proto_files, we transform them to be relative to + # self.proto_root_path, which may be different from self.source_dir. + # + # Although the order of --proto_paths is significant, shadowed filenames + # are errors: if 'a/b/c.proto' resolves to different files under two + # different --proto_path arguments, then the path is rejected as an + # error. (Implementation note: this is enforced in protoc's + # DiskSourceTree class.) + + if self.proto_root_path is None: + self.proto_root_path = os.path.normpath(self.source_dir) + for root_candidate in self.extra_proto_paths: + root_candidate = os.path.normpath(root_candidate) + if self.proto_root_path.startswith(root_candidate): + self.proto_root_path = root_candidate + if self.proto_root_path != self.source_dir: + self.announce('using computed proto_root_path: ' + self.proto_root_path, level=2) + + if not self.source_dir.startswith(self.proto_root_path): + raise DistutilsOptionError('source_dir ' + self.source_dir + + ' is not under proto_root_path ' + self.proto_root_path) + + if self.proto_files is None: + files = glob.glob(os.path.join(self.source_dir, '*.proto')) + if self.recurse: + files.extend(glob.glob(os.path.join(self.source_dir, '**', '*.proto'))) + self.proto_files = [f.partition(self.proto_root_path + os.path.sep)[-1] for f in files] + if not self.proto_files: + raise DistutilsOptionError('no .proto files were found under ' + self.source_dir) + + self.ensure_string_list('proto_files') + + if self.protoc is None: + self.protoc = os.getenv('PROTOC') + if self.protoc is None: + self.protoc = spawn.find_executable('protoc') + + def run(self): + # All proto file paths were adjusted in finalize_options to be relative + # to self.proto_root_path. + proto_paths = ['--proto_path=' + self.proto_root_path] + proto_paths.extend(['--proto_path=' + x for x in self.extra_proto_paths]) + + # Run protoc. It was already resolved, so don't try to resolve + # through PATH. + spawn.spawn( + [self.protoc, + '--python_out=' + self.output_dir, + ] + proto_paths + self.proto_files, + search_path=0) diff --git a/python/protobuf_distutils/setup.py b/python/protobuf_distutils/setup.py new file mode 100644 index 0000000000000..96259a91e0cc8 --- /dev/null +++ b/python/protobuf_distutils/setup.py @@ -0,0 +1,77 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Setuptools/distutils extension for generating Python protobuf code.""" + +__author__ = 'dlj@google.com (David L. Jones)' + +from os import path +from setuptools import setup, find_packages + +# Use README.md as the source for long_description. +this_directory = path.abspath(path.dirname(__file__)) +with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f: + _readme = f.read() + +setup( + name='protobuf_distutils', + version='1.0', + packages=find_packages(), + maintainer='protobuf@googlegroups.com', + maintainer_email='protobuf@googlegroups.com', + license='3-Clause BSD License', + classifiers=[ + "Framework :: Setuptools Plugin", + "Operating System :: OS Independent", + # These Python versions should match the protobuf package: + "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Topic :: Software Development :: Code Generators", + ], + description=('This is a distutils extension to generate Python code for ' + '.proto files using an installed protoc binary.'), + long_description=_readme, + long_description_content_type='text/markdown', + url='https://github.com/protocolbuffers/protobuf/', + entry_points={ + 'distutils.commands': [ + ('generate_py_protobufs = ' + 'protobuf_distutils.generate_py_protobufs:generate_py_protobufs'), + ], + }, +) diff --git a/python/release.sh b/python/release.sh index e7b1a4aafc818..fc88b08e3eee0 100755 --- a/python/release.sh +++ b/python/release.sh @@ -11,7 +11,10 @@ function run_install_test() { local PYTHON=$2 local PYPI=$3 - virtualenv --no-site-packages -p `which $PYTHON` test-venv + # Setuptools 45.0 removed support for Python 2, so to test with Python 2 we + # pass --no-setuptools here and then install an older setuptools version + # below. + virtualenv -p `which $PYTHON` --no-setuptools test-venv # Intentionally put a broken protoc in the path to make sure installation # doesn't require protoc installed. @@ -19,7 +22,8 @@ function run_install_test() { chmod +x test-venv/bin/protoc source test-venv/bin/activate - pip install -i ${PYPI} protobuf==${VERSION} + pip install "setuptools<45" + pip install -i ${PYPI} protobuf==${VERSION} --no-cache-dir deactivate rm -fr test-venv } @@ -47,6 +51,7 @@ DEV=$2 # Make sure all files are world-readable. find python -type d -exec chmod a+r,a+x {} + find python -type f -exec chmod a+r {} + +umask 0022 # Check that the supplied version number matches what's inside the source code. SOURCE_VERSION=`get_source_version` @@ -75,20 +80,23 @@ fi cd python # Run tests locally. -python setup.py build -python setup.py test +python3 setup.py build +python3 setup.py test # Deploy source package to testing PyPI -python setup.py sdist upload -r https://testpypi.python.org/pypi +python3 setup.py sdist +twine upload --skip-existing -r testpypi -u protobuf-wheel-test dist/* # Test locally with different python versions. -run_install_test ${TESTING_VERSION} python2.7 https://testpypi.python.org/simple -run_install_test ${TESTING_VERSION} python3.4 https://testpypi.python.org/simple +run_install_test ${TESTING_VERSION} python2.7 https://test.pypi.org/simple +run_install_test ${TESTING_VERSION} python3 https://test.pypi.org/simple # Deploy egg/wheel packages to testing PyPI and test again. -python setup.py bdist_egg bdist_wheel upload -r https://testpypi.python.org/pypi -run_install_test ${TESTING_VERSION} python2.7 https://testpypi.python.org/simple -run_install_test ${TESTING_VERSION} python3.4 https://testpypi.python.org/simple +python3 setup.py clean build bdist_wheel +twine upload --skip-existing -r testpypi -u protobuf-wheel-test dist/* + +run_install_test ${TESTING_VERSION} python2.7 https://test.pypi.org/simple +run_install_test ${TESTING_VERSION} python3 https://test.pypi.org/simple echo "All install tests have passed using testing PyPI." @@ -101,13 +109,15 @@ if [ $TESTING_ONLY -eq 0 ]; then echo "Publishing to PyPI..." # Be sure to run build before sdist, because otherwise sdist will not include # well-known types. - python setup.py clean build sdist upload + python3 setup.py clean build sdist + twine upload --skip-existing -u protobuf-packages dist/* # Be sure to run clean before bdist_xxx, because otherwise bdist_xxx will # include files you may not want in the package. E.g., if you have built # and tested with --cpp_implemenation, bdist_xxx will include the _message.so # file even when you no longer pass the --cpp_implemenation flag. See: - # https://github.com/google/protobuf/issues/3042 - python setup.py clean build bdist_egg bdist_wheel upload + # https://github.com/protocolbuffers/protobuf/issues/3042 + python3 setup.py clean build bdist_wheel + twine upload --skip-existing -u protobuf-packages dist/* else # Set the version number back (i.e., remove dev suffix). sed -i -r "s/__version__ = '.*'/__version__ = '${VERSION}'/" google/protobuf/__init__.py diff --git a/python/release/wheel/Dockerfile b/python/release/wheel/Dockerfile deleted file mode 100644 index f38ec2f5847a6..0000000000000 --- a/python/release/wheel/Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -FROM quay.io/pypa/manylinux1_x86_64 - -RUN yum install -y libtool -RUN /opt/python/cp27-cp27mu/bin/pip install twine - -COPY protobuf_optimized_pip.sh / diff --git a/python/release/wheel/README.md b/python/release/wheel/README.md deleted file mode 100644 index edda2cd701d90..0000000000000 --- a/python/release/wheel/README.md +++ /dev/null @@ -1,17 +0,0 @@ -Description ------------------------------- -This directory is used to build released wheels according to PEP513 and upload -them to pypi. - -Usage ------------------------------- -For example, to release 3.3.0: - ./protobuf_optimized_pip.sh 3.3.0 PYPI_USERNAME PYPI_PASSWORD - -Structure ------------------------------- -| Source | Source | -|--------------------------------------|---------------------------------------------------| -| protobuf_optimized_pip.sh | Entry point. Calling Dockerfile and build_wheel_manylinux.sh | -| Dockerfile | Build docker image according to PEP513. | -| build_wheel_manylinux.sh | Build wheel packages in the docker container. | diff --git a/python/release/wheel/build_wheel_manylinux.sh b/python/release/wheel/build_wheel_manylinux.sh deleted file mode 100755 index 39fd8c1273884..0000000000000 --- a/python/release/wheel/build_wheel_manylinux.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -# Print usage and fail. -function usage() { - echo "Usage: protobuf_optimized_pip.sh PROTOBUF_VERSION PYPI_USERNAME PYPI_PASSWORD" >&2 - exit 1 # Causes caller to exit because we use -e. -} - -# Validate arguments. -if [ $0 != ./build_wheel_manylinux.sh ]; then - echo "Please run this script from the directory in which it is located." >&2 - exit 1 -fi - -if [ $# -lt 3 ]; then - usage - exit 1 -fi - -PROTOBUF_VERSION=$1 -PYPI_USERNAME=$2 -PYPI_PASSWORD=$3 - -docker rmi protobuf-python-wheel -docker build . -t protobuf-python-wheel -docker run --rm protobuf-python-wheel ./protobuf_optimized_pip.sh $PROTOBUF_VERSION $PYPI_USERNAME $PYPI_PASSWORD -docker rmi protobuf-python-wheel diff --git a/python/release/wheel/protobuf_optimized_pip.sh b/python/release/wheel/protobuf_optimized_pip.sh deleted file mode 100755 index 469661aa89775..0000000000000 --- a/python/release/wheel/protobuf_optimized_pip.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash - -# DO NOT use this script manually! Called by docker. - -set -ex - -# Print usage and fail. -function usage() { - echo "Usage: protobuf_optimized_pip.sh PROTOBUF_VERSION PYPI_USERNAME PYPI_PASSWORD" >&2 - exit 1 # Causes caller to exit because we use -e. -} - -# Build wheel -function build_wheel() { - PYTHON_VERSION=$1 - PYTHON_BIN=/opt/python/${PYTHON_VERSION}/bin/python - - $PYTHON_BIN setup.py bdist_wheel --cpp_implementation --compile_static_extension - auditwheel repair dist/protobuf-${PROTOBUF_VERSION}-${PYTHON_VERSION}-linux_x86_64.whl -} - -# Validate arguments. -if [ $0 != ./protobuf_optimized_pip.sh ]; then - echo "Please run this script from the directory in which it is located." >&2 - exit 1 -fi - -if [ $# -lt 3 ]; then - usage - exit 1 -fi - -PROTOBUF_VERSION=$1 -PYPI_USERNAME=$2 -PYPI_PASSWORD=$3 - -DIR=${PWD}/'protobuf-python-build' -PYTHON_VERSIONS=('cp27-cp27mu' 'cp33-cp33m' 'cp34-cp34m' 'cp35-cp35m' 'cp36-cp36m') - -mkdir -p ${DIR} -cd ${DIR} -curl -SsL -O https://github.com/google/protobuf/archive/v${PROTOBUF_VERSION}.tar.gz -tar xzf v${PROTOBUF_VERSION}.tar.gz -cd $DIR/protobuf-${PROTOBUF_VERSION} - -# Autoconf on centos 5.11 cannot recognize AC_PROG_OBJC. -sed -i '/AC_PROG_OBJC/d' configure.ac -sed -i 's/conformance\/Makefile//g' configure.ac - -# Build protoc -./autogen.sh -CXXFLAGS="-fPIC -g -O2" ./configure -make -j8 -export PROTOC=$DIR/src/protoc - -cd python - -for PYTHON_VERSION in "${PYTHON_VERSIONS[@]}" -do - build_wheel $PYTHON_VERSION -done - -/opt/python/cp27-cp27mu/bin/twine upload wheelhouse/* <= (2, 7): - # Python 2.6 dodges these extra failures. - os.environ["CONFORMANCE_PYTHON_EXTRA_FAILURES"] = ( - "--failure_list failure_list_python-post26.txt") + # Python 2.6 dodges these extra failures. + os.environ["CONFORMANCE_PYTHON_EXTRA_FAILURES"] = ( + "--failure_list failure_list_python-post26.txt") cmd = 'cd ../conformance && make %s' % (test_conformance.target) status = subprocess.check_call(cmd, shell=True) @@ -177,9 +182,6 @@ def get_option_from_sys_argv(option_str): # extension. Note that those libraries have to be compiled with # -fPIC for this to work. compile_static_ext = get_option_from_sys_argv('--compile_static_extension') - extra_compile_args = ['-Wno-write-strings', - '-Wno-invalid-offsetof', - '-Wno-sign-compare'] libraries = ['protobuf'] extra_objects = None if compile_static_ext: @@ -188,15 +190,46 @@ def get_option_from_sys_argv(option_str): '../src/.libs/libprotobuf-lite.a'] test_conformance.target = 'test_python_cpp' - if "clang" in os.popen('$CC --version 2> /dev/null').read(): - extra_compile_args.append('-Wno-shorten-64-to-32') + extra_compile_args = [] - v, _, _ = platform.mac_ver() - if v: - v = float('.'.join(v.split('.')[:2])) - if v >= 10.12: + if sys.platform != 'win32': + extra_compile_args.append('-Wno-write-strings') + extra_compile_args.append('-Wno-invalid-offsetof') + extra_compile_args.append('-Wno-sign-compare') + extra_compile_args.append('-Wno-unused-variable') extra_compile_args.append('-std=c++11') + if sys.platform == 'darwin': + extra_compile_args.append("-Wno-shorten-64-to-32"); + extra_compile_args.append("-Wno-deprecated-register"); + + # https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes + # C++ projects must now migrate to libc++ and are recommended to set a + # deployment target of macOS 10.9 or later, or iOS 7 or later. + if sys.platform == 'darwin': + mac_target = str(sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')) + if mac_target and (pkg_resources.parse_version(mac_target) < + pkg_resources.parse_version('10.9.0')): + os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.9' + os.environ['_PYTHON_HOST_PLATFORM'] = re.sub( + r'macosx-[0-9]+\.[0-9]+-(.+)', r'macosx-10.9-\1', + util.get_platform()) + + # https://github.com/Theano/Theano/issues/4926 + if sys.platform == 'win32': + extra_compile_args.append('-D_hypot=hypot') + + # https://github.com/tpaviot/pythonocc-core/issues/48 + if sys.platform == 'win32' and '64 bit' in sys.version: + extra_compile_args.append('-DMS_WIN64') + + # MSVS default is dymanic + if (sys.platform == 'win32'): + extra_compile_args.append('/MT') + + if "clang" in os.popen('$CC --version 2> /dev/null').read(): + extra_compile_args.append('-Wno-shorten-64-to-32') + if warnings_as_errors in sys.argv: extra_compile_args.append('-Werror') sys.argv.remove(warnings_as_errors) @@ -215,13 +248,13 @@ def get_option_from_sys_argv(option_str): Extension( "google.protobuf.internal._api_implementation", glob.glob('google/protobuf/internal/api_implementation.cc'), - extra_compile_args=['-DPYTHON_PROTO2_CPP_IMPL_V2'], + extra_compile_args=extra_compile_args + ['-DPYTHON_PROTO2_CPP_IMPL_V2'], ), ]) os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp' # Keep this list of dependencies in sync with tox.ini. - install_requires = ['six>=1.9', 'setuptools'] + install_requires = ['six>=1.9'] if sys.version_info <= (2,7): install_requires.append('ordereddict') install_requires.append('unittest2') @@ -230,7 +263,7 @@ def get_option_from_sys_argv(option_str): name='protobuf', version=GetVersion(), description='Protocol Buffers', - download_url='https://github.com/google/protobuf/releases', + download_url='https://github.com/protocolbuffers/protobuf/releases', long_description="Protocol Buffers are Google's data interchange format", url='https://developers.google.com/protocol-buffers/', maintainer='protobuf@googlegroups.com', @@ -239,16 +272,21 @@ def get_option_from_sys_argv(option_str): classifiers=[ "Programming Language :: Python", "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", ], namespace_packages=['google'], packages=find_packages( exclude=[ 'import_test_package', + 'protobuf_distutils', ], ), test_suite='google.protobuf.internal', diff --git a/python/stubout.py b/python/stubout.py index aee4f2da20dc0..ba391045b6d69 100755 --- a/python/stubout.py +++ b/python/stubout.py @@ -17,6 +17,9 @@ # This file is used for testing. The original is at: # http://code.google.com/p/pymox/ +import inspect + + class StubOutForTesting: """Sample Usage: You want os.path.exists() to always return true during testing. diff --git a/python/tox.ini b/python/tox.ini index baa96dba0b386..9fabb6ddbb25b 100644 --- a/python/tox.ini +++ b/python/tox.ini @@ -1,10 +1,11 @@ [tox] envlist = - py{26,27,33,34}-{cpp,python} + py{27,33,34,35,36,37,38,39}-{cpp,python} [testenv] usedevelop=true -passenv = CC +passenv = + CC KOKORO_BUILD_ID KOKORO_BUILD_NUMBER setenv = cpp: LD_LIBRARY_PATH={toxinidir}/../src/.libs cpp: DYLD_LIBRARY_PATH={toxinidir}/../src/.libs @@ -13,7 +14,10 @@ setenv = commands = python setup.py -q build_py python: python setup.py -q build - cpp: python setup.py -q build --cpp_implementation --warnings_as_errors --compile_static_extension + # --warnings_as_errors disabled until we update the Python C extension. See: + # https://github.com/protocolbuffers/protobuf/issues/7930 + # cpp: python setup.py -q build --cpp_implementation --warnings_as_errors --compile_static_extension + cpp: python setup.py -q build --cpp_implementation --compile_static_extension python: python setup.py -q test -q cpp: python setup.py -q test -q --cpp_implementation python: python setup.py -q test_conformance diff --git a/ruby/.gitignore b/ruby/.gitignore index bd8745dd85672..653309818f32b 100644 --- a/ruby/.gitignore +++ b/ruby/.gitignore @@ -6,3 +6,4 @@ protobuf-jruby.iml target/ pkg/ tmp/ +tests/google/ \ No newline at end of file diff --git a/ruby/README.md b/ruby/README.md index f28e05a72b8f4..42a1ffaad4147 100644 --- a/ruby/README.md +++ b/ruby/README.md @@ -9,16 +9,13 @@ install protoc as well to have Ruby code generation functionality. Installation from Gem --------------------- +In Gemfile (Please check a version of Protocol Buffers you needed [RubyGems](https://rubygems.org/gems/google-protobuf)): -When we release a version of Protocol Buffers, we will upload a Gem to -[RubyGems](https://www.rubygems.org/). To use this pre-packaged gem, simply -install it as you would any other gem: + gem 'google-protobuf' - $ gem install [--prerelease] google-protobuf +Or for using this pre-packaged gem, simply install it as you would any other gem: -The `--pre` flag is necessary if we have not yet made a non-alpha/beta release -of the Ruby extension; it allows `gem` to consider these "pre-release" -alpha/beta versions. + $ gem install [--prerelease] google-protobuf Once the gem is installed, you may or may not need `protoc`. If you write your message type descriptions directly in the Ruby DSL, you do not need it. diff --git a/ruby/Rakefile b/ruby/Rakefile index a329a777b4e0a..3e3da055d3f2b 100644 --- a/ruby/Rakefile +++ b/ruby/Rakefile @@ -51,7 +51,19 @@ if RUBY_PLATFORM == "java" system("mvn --batch-mode package") end else + unless ENV['IN_DOCKER'] == 'true' + # We need wyhash in-tree. + FileUtils.mkdir_p("ext/google/protobuf_c/third_party/wyhash") + FileUtils.cp("../third_party/wyhash/wyhash.h", "ext/google/protobuf_c/third_party/wyhash/wyhash.h") + end + Rake::ExtensionTask.new("protobuf_c", spec) do |ext| + unless RUBY_PLATFORM =~ /darwin/ + # TODO: also set "no_native to true" for mac if possible. As is, + # "no_native" can only be set if the RUBY_PLATFORM doing + # cross-compilation is contained in the "ext.cross_platform" array. + ext.no_native = true + end ext.ext_dir = "ext/google/protobuf_c" ext.lib_dir = "lib/google" ext.cross_compile = true @@ -64,13 +76,18 @@ else task 'gem:windows' do require 'rake_compiler_dock' - RakeCompilerDock.sh "bundle && IN_DOCKER=true rake cross native gem RUBY_CC_VERSION=2.4.0:2.3.0:2.2.2:2.1.5:2.0.0" + ['x86-mingw32', 'x64-mingw32', 'x86_64-linux', 'x86-linux'].each do |plat| + RakeCompilerDock.sh <<-"EOT", platform: plat + bundle && \ + IN_DOCKER=true rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem RUBY_CC_VERSION=3.0.0:2.7.0:2.6.0:2.5.0:2.4.0:2.3.0 + EOT + end end if RUBY_PLATFORM =~ /darwin/ task 'gem:native' do system "rake genproto" - system "rake cross native gem RUBY_CC_VERSION=2.4.0:2.3.0:2.2.2:2.1.5:2.0.0" + system "rake cross native gem RUBY_CC_VERSION=3.0.0:2.7.0:2.6.0:2.5.1:2.4.0:2.3.0" end else task 'gem:native' => [:genproto, 'gem:windows'] @@ -80,15 +97,56 @@ end # Proto for tests. genproto_output << "tests/generated_code.rb" +genproto_output << "tests/generated_code_proto2.rb" genproto_output << "tests/test_import.rb" +genproto_output << "tests/test_import_proto2.rb" +genproto_output << "tests/test_ruby_package.rb" +genproto_output << "tests/test_ruby_package_proto2.rb" +genproto_output << "tests/basic_test.rb" +genproto_output << "tests/basic_test_proto2.rb" +genproto_output << "tests/multi_level_nesting_test.rb" +genproto_output << "tests/wrappers.rb" + file "tests/generated_code.rb" => "tests/generated_code.proto" do |file_task| sh "../src/protoc --ruby_out=. tests/generated_code.proto" end +file "tests/generated_code_proto2.rb" => "tests/generated_code_proto2.proto" do |file_task| + sh "../src/protoc --ruby_out=. tests/generated_code_proto2.proto" +end + file "tests/test_import.rb" => "tests/test_import.proto" do |file_task| sh "../src/protoc --ruby_out=. tests/test_import.proto" end +file "tests/test_import_proto2.rb" => "tests/test_import_proto2.proto" do |file_task| + sh "../src/protoc --ruby_out=. tests/test_import_proto2.proto" +end + +file "tests/test_ruby_package.rb" => "tests/test_ruby_package.proto" do |file_task| + sh "../src/protoc --ruby_out=. tests/test_ruby_package.proto" +end + +file "tests/test_ruby_package_proto2.rb" => "tests/test_ruby_package_proto2.proto" do |file_task| + sh "../src/protoc --ruby_out=. tests/test_ruby_package_proto2.proto" +end + +file "tests/basic_test.rb" => "tests/basic_test.proto" do |file_task| + sh "../src/protoc --experimental_allow_proto3_optional -I../src -I. --ruby_out=. tests/basic_test.proto" +end + +file "tests/basic_test_proto2.rb" => "tests/basic_test_proto2.proto" do |file_task| + sh "../src/protoc -I../src -I. --ruby_out=. tests/basic_test_proto2.proto" +end + +file "tests/multi_level_nesting_test.rb" => "tests/multi_level_nesting_test.proto" do |file_task| + sh "../src/protoc -I../src -I. --ruby_out=. tests/multi_level_nesting_test.proto" +end + +file "tests/wrappers.rb" => "../src/google/protobuf/wrappers.proto" do |file_task| + sh "../src/protoc -I../src -I. --ruby_out=tests ../src/google/protobuf/wrappers.proto" +end + task :genproto => genproto_output task :clean do @@ -99,7 +157,13 @@ Gem::PackageTask.new(spec) do |pkg| end Rake::TestTask.new(:test => :build) do |t| - t.test_files = FileList["tests/*.rb"] + t.test_files = FileList["tests/*.rb"].exclude("tests/gc_test.rb", "tests/common_tests.rb") +end + +# gc_test needs to be split out to ensure the generated file hasn't been +# imported by other tests. +Rake::TestTask.new(:gc_test => :build) do |t| + t.test_files = FileList["tests/gc_test.rb"] end task :build => [:clean, :compile, :genproto] diff --git a/ruby/compatibility_tests/v3.0.0/README.md b/ruby/compatibility_tests/v3.0.0/README.md index eb341228cf542..06d981c90ddbc 100644 --- a/ruby/compatibility_tests/v3.0.0/README.md +++ b/ruby/compatibility_tests/v3.0.0/README.md @@ -1,5 +1,5 @@ # Protobuf Ruby Compatibility Tests -This drectory contains a snapshot of protobuf ruby 3.0.0 unittest code and +This directory contains a snapshot of protobuf ruby 3.0.0 unittest code and test scripts used to verifies whether the latest version of protobuf is still compatible with 3.0.0 generated code. diff --git a/ruby/compatibility_tests/v3.0.0/test.sh b/ruby/compatibility_tests/v3.0.0/test.sh index 996dc020c2873..d5a8fd74d7a5a 100755 --- a/ruby/compatibility_tests/v3.0.0/test.sh +++ b/ruby/compatibility_tests/v3.0.0/test.sh @@ -10,7 +10,7 @@ PROTOC_BINARY_NAME="protoc-3.0.0-linux-x86_64.exe" if [ `uname` = "Darwin" ]; then PROTOC_BINARY_NAME="protoc-3.0.0-osx-x86_64.exe" fi -wget http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0/${PROTOC_BINARY_NAME} -O protoc +wget https://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0/${PROTOC_BINARY_NAME} -O protoc chmod +x protoc # Run tests diff --git a/ruby/compatibility_tests/v3.0.0/tests/basic.rb b/ruby/compatibility_tests/v3.0.0/tests/basic.rb old mode 100644 new mode 100755 index f81e456c3f54b..7228144cb165b --- a/ruby/compatibility_tests/v3.0.0/tests/basic.rb +++ b/ruby/compatibility_tests/v3.0.0/tests/basic.rb @@ -67,7 +67,6 @@ module BasicTest add_message "BadFieldNames" do optional :dup, :int32, 1 optional :class, :int32, 2 - optional :"a.b", :int32, 3 end add_message "MapMessage" do @@ -212,43 +211,65 @@ def test_initialization_map_errors e = assert_raise ArgumentError do MapMessage.new(:map_string_int32 => "hello") end - assert_equal e.message, "Expected Hash object as initializer value for map field 'map_string_int32'." + assert_equal e.message, "Expected Hash object as initializer value for map field 'map_string_int32' (given String)." e = assert_raise ArgumentError do TestMessage.new(:repeated_uint32 => "hello") end - assert_equal e.message, "Expected array as initializer value for repeated field 'repeated_uint32'." + assert_equal e.message, "Expected array as initializer value for repeated field 'repeated_uint32' (given String)." end def test_type_errors m = TestMessage.new - assert_raise TypeError do + + # Use rescue to allow subclasses of error + success = false + begin m.optional_int32 = "hello" + rescue TypeError + success = true end - assert_raise TypeError do - m.optional_string = 42 - end - assert_raise TypeError do + assert(success) + + success = false + begin m.optional_string = nil + rescue TypeError + success = true end - assert_raise TypeError do + assert(success) + + success = false + begin m.optional_bool = 42 + rescue TypeError + success = true end - assert_raise TypeError do + assert(success) + + success = false + begin m.optional_msg = TestMessage.new # expects TestMessage2 + rescue TypeError + success = true end + assert(success) - assert_raise TypeError do + success = false + begin m.repeated_int32 = [] # needs RepeatedField + rescue TypeError + success = true end + assert(success) - assert_raise TypeError do - m.repeated_int32.push "hello" - end - - assert_raise TypeError do + success = false + begin m.repeated_msg.push TestMessage.new + rescue TypeError + success = true end + assert(success) end def test_string_encoding @@ -275,7 +296,7 @@ def test_string_encoding # strings are immutable so we can't do this, but serialize should catch it. m.optional_string = "asdf".encode!('UTF-8') - assert_raise RuntimeError do + assert_raise do m.optional_string.encode!('ASCII-8BIT') end end @@ -312,10 +333,14 @@ def test_rptfield_int32 assert l.pop == 9 assert l == [5, 2, 3, 4, 7, 8] - assert_raise TypeError do + success = false + begin m = TestMessage.new l.push m + rescue TypeError + success = true end + assert(success) m = TestMessage.new m.repeated_int32 = l @@ -362,12 +387,22 @@ def test_rptfield_msg l = Google::Protobuf::RepeatedField.new(:message, TestMessage) l.push TestMessage.new assert l.count == 1 - assert_raise TypeError do + + success = false + begin l.push TestMessage2.new + rescue TypeError + success = true end - assert_raise TypeError do + assert(success) + + success = false + begin l.push 42 + rescue TypeError + success = true end + assert(success) l2 = l.dup assert l2[0] == l[0] @@ -493,9 +528,14 @@ def test_map_basic assert m.length == 0 assert m == {} - assert_raise TypeError do + success = false + begin m[1] = 1 + rescue TypeError + success = true end + assert(success) + assert_raise RangeError do m["asdf"] = 0x1_0000_0000 end @@ -514,18 +554,28 @@ def test_map_keytypes assert_raise RangeError do m[0x8000_0000] = 1 end - assert_raise TypeError do + + success = false + begin m["asdf"] = 1 + rescue TypeError + success = true end + assert(success) m = Google::Protobuf::Map.new(:int64, :int32) m[0x1000_0000_0000_0000] = 1 assert_raise RangeError do m[0x1_0000_0000_0000_0000] = 1 end - assert_raise TypeError do + + success = false + begin m["asdf"] = 1 + rescue TypeError + success = true end + assert(success) m = Google::Protobuf::Map.new(:uint32, :int32) m[0x8000_0000] = 1 @@ -548,18 +598,32 @@ def test_map_keytypes m = Google::Protobuf::Map.new(:bool, :int32) m[true] = 1 m[false] = 2 - assert_raise TypeError do + + success = false + begin m[1] = 1 + rescue TypeError + success = true end - assert_raise TypeError do + assert(success) + + success = false + begin m["asdf"] = 1 + rescue TypeError + success = true end + assert(success) m = Google::Protobuf::Map.new(:string, :int32) m["asdf"] = 1 - assert_raise TypeError do + success = false + begin m[1] = 1 + rescue TypeError + success = true end + assert(success) assert_raise Encoding::UndefinedConversionError do bytestring = ["FFFF"].pack("H*") m[bytestring] = 1 @@ -570,17 +634,25 @@ def test_map_keytypes m[bytestring] = 1 # Allowed -- we will automatically convert to ASCII-8BIT. m["asdf"] = 1 - assert_raise TypeError do + success = false + begin m[1] = 1 + rescue TypeError + success = true end + assert(success) end def test_map_msg_enum_valuetypes m = Google::Protobuf::Map.new(:string, :message, TestMessage) m["asdf"] = TestMessage.new - assert_raise TypeError do + success = false + begin m["jkl;"] = TestMessage2.new + rescue TypeError + success = true end + assert(success) m = Google::Protobuf::Map.new( :string, :message, TestMessage, @@ -600,7 +672,7 @@ def test_map_msg_enum_valuetypes assert_raise RangeError do m["z"] = :Z end - assert_raise TypeError do + assert_raise RangeError do m["z"] = "z" end end @@ -645,23 +717,39 @@ def test_map_field m.map_string_msg.delete("c") assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) } - assert_raise TypeError do + success = false + begin m.map_string_msg["e"] = TestMessage.new # wrong value type + rescue TypeError + success = true end + assert(success) # ensure nothing was added by the above assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) } m.map_string_int32 = Google::Protobuf::Map.new(:string, :int32) - assert_raise TypeError do + success = false + begin m.map_string_int32 = Google::Protobuf::Map.new(:string, :int64) + rescue TypeError + success = true end - assert_raise TypeError do + assert(success) + success = false + begin m.map_string_int32 = {} + rescue TypeError + success = true end + assert(success) - assert_raise TypeError do + success = false + begin m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" }) + rescue TypeError + success = true end + assert(success) end def test_map_encode_decode @@ -922,22 +1010,30 @@ def test_to_h def test_def_errors s = Google::Protobuf::DescriptorPool.new - assert_raise TypeError do + success = false + begin s.build do # enum with no default (integer value 0) add_enum "MyEnum" do value :A, 1 end end + rescue TypeError + success = true end - assert_raise TypeError do + assert(success) + success = false + begin s.build do # message with required field (unsupported in proto3) add_message "MyMessage" do required :foo, :int32, 1 end end + rescue TypeError + success = true end + assert(success) end def test_corecursive @@ -970,8 +1066,6 @@ def test_bad_field_names assert m['class'] == 2 m['dup'] = 3 assert m['dup'] == 3 - m['a.b'] = 4 - assert m['a.b'] == 4 end def test_int_ranges @@ -1170,10 +1264,10 @@ def test_json_maps m = MapMessage.new(:map_string_int32 => {"a" => 1}) expected = '{"mapStringInt32":{"a":1},"mapStringMsg":{}}' expected_preserve = '{"map_string_int32":{"a":1},"map_string_msg":{}}' - assert MapMessage.encode_json(m) == expected + assert_equal expected, MapMessage.encode_json(m, :emit_defaults => true) - json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true) - assert json == expected_preserve + json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true, :emit_defaults => true) + assert_equal expected_preserve, json m2 = MapMessage.decode_json(MapMessage.encode_json(m)) assert m == m2 diff --git a/ruby/compatibility_tests/v3.0.0/tests/generated_code_test.rb b/ruby/compatibility_tests/v3.0.0/tests/generated_code_test.rb old mode 100644 new mode 100755 diff --git a/ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb b/ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb old mode 100644 new mode 100755 index 25727b7b282c9..b4a158f37ccd4 --- a/ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb +++ b/ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb @@ -18,7 +18,9 @@ def test_acts_like_an_array # jRuby additions to the Array class that we can ignore arr_methods -= [ :indices, :iter_for_each, :iter_for_each_index, :iter_for_each_with_index, :dimensions, :copy_data, :copy_data_simple, - :nitems, :iter_for_reverse_each, :indexes] + :nitems, :iter_for_reverse_each, :indexes, :append, :prepend] + arr_methods -= [:union, :difference, :filter!] + arr_methods -= [:intersection, :deconstruct] # ruby 2.7 methods we can ignore arr_methods.each do |method_name| assert m.repeated_string.respond_to?(method_name) == true, "does not respond to #{method_name}" end diff --git a/ruby/compatibility_tests/v3.0.0/tests/stress.rb b/ruby/compatibility_tests/v3.0.0/tests/stress.rb old mode 100644 new mode 100755 diff --git a/ruby/ext/google/protobuf_c/convert.c b/ruby/ext/google/protobuf_c/convert.c new file mode 100644 index 0000000000000..bc3e35a5ed264 --- /dev/null +++ b/ruby/ext/google/protobuf_c/convert.c @@ -0,0 +1,349 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ----------------------------------------------------------------------------- +// Ruby <-> upb data conversion functions. +// +// This file Also contains a few other assorted algorithms on upb_msgval. +// +// None of the algorithms in this file require any access to the internal +// representation of Ruby or upb objects. +// ----------------------------------------------------------------------------- + +#include "convert.h" + +#include "message.h" +#include "protobuf.h" +#include "third_party/wyhash/wyhash.h" + +static upb_strview Convert_StringData(VALUE str, upb_arena *arena) { + upb_strview ret; + if (arena) { + char *ptr = upb_arena_malloc(arena, RSTRING_LEN(str)); + memcpy(ptr, RSTRING_PTR(str), RSTRING_LEN(str)); + ret.data = ptr; + } else { + // Data is only needed temporarily (within map lookup). + ret.data = RSTRING_PTR(str); + } + ret.size = RSTRING_LEN(str); + return ret; +} + +static bool is_ruby_num(VALUE value) { + return (TYPE(value) == T_FLOAT || + TYPE(value) == T_FIXNUM || + TYPE(value) == T_BIGNUM); +} + +static void Convert_CheckInt(const char* name, upb_fieldtype_t type, + VALUE val) { + if (!is_ruby_num(val)) { + rb_raise(cTypeError, + "Expected number type for integral field '%s' (given %s).", name, + rb_class2name(CLASS_OF(val))); + } + + // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper + // bound; we just need to do precision checks (i.e., disallow rounding) and + // check for < 0 on unsigned types. + if (TYPE(val) == T_FLOAT) { + double dbl_val = NUM2DBL(val); + if (floor(dbl_val) != dbl_val) { + rb_raise(rb_eRangeError, + "Non-integral floating point value assigned to integer field " + "'%s' (given %s).", + name, rb_class2name(CLASS_OF(val))); + } + } + if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) { + if (NUM2DBL(val) < 0) { + rb_raise( + rb_eRangeError, + "Assigning negative value to unsigned integer field '%s' (given %s).", + name, rb_class2name(CLASS_OF(val))); + } + } +} + +static int32_t Convert_ToEnum(VALUE value, const char* name, + const upb_enumdef* e) { + int32_t val; + + switch (TYPE(value)) { + case T_FLOAT: + case T_FIXNUM: + case T_BIGNUM: + Convert_CheckInt(name, UPB_TYPE_INT32, value); + val = NUM2INT(value); + break; + case T_STRING: + if (!upb_enumdef_ntoi(e, RSTRING_PTR(value), RSTRING_LEN(value), &val)) { + goto unknownval; + } + break; + case T_SYMBOL: + if (!upb_enumdef_ntoiz(e, rb_id2name(SYM2ID(value)), &val)) { + goto unknownval; + } + break; + default: + rb_raise(cTypeError, + "Expected number or symbol type for enum field '%s'.", name); + } + + return val; + +unknownval: + rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name); +} + +upb_msgval Convert_RubyToUpb(VALUE value, const char* name, TypeInfo type_info, + upb_arena* arena) { + upb_msgval ret; + + switch (type_info.type) { + case UPB_TYPE_FLOAT: + if (!is_ruby_num(value)) { + rb_raise(cTypeError, "Expected number type for float field '%s' (given %s).", + name, rb_class2name(CLASS_OF(value))); + } + ret.float_val = NUM2DBL(value); + break; + case UPB_TYPE_DOUBLE: + if (!is_ruby_num(value)) { + rb_raise(cTypeError, "Expected number type for double field '%s' (given %s).", + name, rb_class2name(CLASS_OF(value))); + } + ret.double_val = NUM2DBL(value); + break; + case UPB_TYPE_BOOL: { + if (value == Qtrue) { + ret.bool_val = 1; + } else if (value == Qfalse) { + ret.bool_val = 0; + } else { + rb_raise(cTypeError, "Invalid argument for boolean field '%s' (given %s).", + name, rb_class2name(CLASS_OF(value))); + } + break; + } + case UPB_TYPE_STRING: { + VALUE utf8 = rb_enc_from_encoding(rb_utf8_encoding()); + if (CLASS_OF(value) == rb_cSymbol) { + value = rb_funcall(value, rb_intern("to_s"), 0); + } else if (CLASS_OF(value) != rb_cString) { + rb_raise(cTypeError, "Invalid argument for string field '%s' (given %s).", + name, rb_class2name(CLASS_OF(value))); + } + + if (rb_obj_encoding(value) != utf8) { + // Note: this will not duplicate underlying string data unless necessary. + value = rb_str_encode(value, utf8, 0, Qnil); + + if (rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) { + rb_raise(rb_eEncodingError, "String is invalid UTF-8"); + } + } + + ret.str_val = Convert_StringData(value, arena); + break; + } + case UPB_TYPE_BYTES: { + VALUE bytes = rb_enc_from_encoding(rb_ascii8bit_encoding()); + if (CLASS_OF(value) != rb_cString) { + rb_raise(cTypeError, "Invalid argument for bytes field '%s' (given %s).", + name, rb_class2name(CLASS_OF(value))); + } + + if (rb_obj_encoding(value) != bytes) { + // Note: this will not duplicate underlying string data unless necessary. + // TODO(haberman): is this really necessary to get raw bytes? + value = rb_str_encode(value, bytes, 0, Qnil); + } + + ret.str_val = Convert_StringData(value, arena); + break; + } + case UPB_TYPE_MESSAGE: + ret.msg_val = + Message_GetUpbMessage(value, type_info.def.msgdef, name, arena); + break; + case UPB_TYPE_ENUM: + ret.int32_val = Convert_ToEnum(value, name, type_info.def.enumdef); + break; + case UPB_TYPE_INT32: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT32: + case UPB_TYPE_UINT64: + Convert_CheckInt(name, type_info.type, value); + switch (type_info.type) { + case UPB_TYPE_INT32: + ret.int32_val = NUM2INT(value); + break; + case UPB_TYPE_INT64: + ret.int64_val = NUM2LL(value); + break; + case UPB_TYPE_UINT32: + ret.uint32_val = NUM2UINT(value); + break; + case UPB_TYPE_UINT64: + ret.uint64_val = NUM2ULL(value); + break; + default: + break; + } + break; + default: + break; + } + + return ret; +} + +VALUE Convert_UpbToRuby(upb_msgval upb_val, TypeInfo type_info, VALUE arena) { + switch (type_info.type) { + case UPB_TYPE_FLOAT: + return DBL2NUM(upb_val.float_val); + case UPB_TYPE_DOUBLE: + return DBL2NUM(upb_val.double_val); + case UPB_TYPE_BOOL: + return upb_val.bool_val ? Qtrue : Qfalse; + case UPB_TYPE_INT32: + return INT2NUM(upb_val.int32_val); + case UPB_TYPE_INT64: + return LL2NUM(upb_val.int64_val); + case UPB_TYPE_UINT32: + return UINT2NUM(upb_val.uint32_val); + case UPB_TYPE_UINT64: + return ULL2NUM(upb_val.int64_val); + case UPB_TYPE_ENUM: { + const char* name = + upb_enumdef_iton(type_info.def.enumdef, upb_val.int32_val); + if (name) { + return ID2SYM(rb_intern(name)); + } else { + return INT2NUM(upb_val.int32_val); + } + } + case UPB_TYPE_STRING: { + VALUE str_rb = rb_str_new(upb_val.str_val.data, upb_val.str_val.size); + rb_enc_associate(str_rb, rb_utf8_encoding()); + rb_obj_freeze(str_rb); + return str_rb; + } + case UPB_TYPE_BYTES: { + VALUE str_rb = rb_str_new(upb_val.str_val.data, upb_val.str_val.size); + rb_enc_associate(str_rb, rb_ascii8bit_encoding()); + rb_obj_freeze(str_rb); + return str_rb; + } + case UPB_TYPE_MESSAGE: + return Message_GetRubyWrapper((upb_msg*)upb_val.msg_val, + type_info.def.msgdef, arena); + default: + rb_raise(rb_eRuntimeError, "Convert_UpbToRuby(): Unexpected type %d", + (int)type_info.type); + } +} + +upb_msgval Msgval_DeepCopy(upb_msgval msgval, TypeInfo type_info, + upb_arena* arena) { + upb_msgval new_msgval; + + switch (type_info.type) { + default: + memcpy(&new_msgval, &msgval, sizeof(msgval)); + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: { + size_t n = msgval.str_val.size; + char *mem = upb_arena_malloc(arena, n); + new_msgval.str_val.data = mem; + new_msgval.str_val.size = n; + memcpy(mem, msgval.str_val.data, n); + break; + } + case UPB_TYPE_MESSAGE: + new_msgval.msg_val = + Message_deep_copy(msgval.msg_val, type_info.def.msgdef, arena); + break; + } + + return new_msgval; +} + +bool Msgval_IsEqual(upb_msgval val1, upb_msgval val2, TypeInfo type_info) { + switch (type_info.type) { + case UPB_TYPE_BOOL: + return memcmp(&val1, &val2, 1) == 0; + case UPB_TYPE_FLOAT: + case UPB_TYPE_INT32: + case UPB_TYPE_UINT32: + case UPB_TYPE_ENUM: + return memcmp(&val1, &val2, 4) == 0; + case UPB_TYPE_DOUBLE: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT64: + return memcmp(&val1, &val2, 8) == 0; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + return val1.str_val.size != val2.str_val.size || + memcmp(val1.str_val.data, val2.str_val.data, + val1.str_val.size) == 0; + case UPB_TYPE_MESSAGE: + return Message_Equal(val1.msg_val, val2.msg_val, type_info.def.msgdef); + default: + rb_raise(rb_eRuntimeError, "Internal error, unexpected type"); + } +} + +uint64_t Msgval_GetHash(upb_msgval val, TypeInfo type_info, uint64_t seed) { + switch (type_info.type) { + case UPB_TYPE_BOOL: + return wyhash(&val, 1, seed, _wyp); + case UPB_TYPE_FLOAT: + case UPB_TYPE_INT32: + case UPB_TYPE_UINT32: + case UPB_TYPE_ENUM: + return wyhash(&val, 4, seed, _wyp); + case UPB_TYPE_DOUBLE: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT64: + return wyhash(&val, 8, seed, _wyp); + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + return wyhash(val.str_val.data, val.str_val.size, seed, _wyp); + case UPB_TYPE_MESSAGE: + return Message_Hash(val.msg_val, type_info.def.msgdef, seed); + default: + rb_raise(rb_eRuntimeError, "Internal error, unexpected type"); + } +} diff --git a/ruby/ext/google/protobuf_c/convert.h b/ruby/ext/google/protobuf_c/convert.h new file mode 100644 index 0000000000000..cda18a0547f48 --- /dev/null +++ b/ruby/ext/google/protobuf_c/convert.h @@ -0,0 +1,72 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef RUBY_PROTOBUF_CONVERT_H_ +#define RUBY_PROTOBUF_CONVERT_H_ + +#include + +#include "protobuf.h" +#include "ruby-upb.h" + +// Converts |ruby_val| to a upb_msgval according to |type_info|. +// +// The |arena| parameter indicates the lifetime of the container where this +// value will be assigned. It is used as follows: +// - If type is string or bytes, the string data will be copied into |arena|. +// - If type is message, and we need to auto-construct a message due to implicit +// conversions (eg. Time -> Google::Protobuf::Timestamp), the new message +// will be created in |arena|. +// - If type is message and the Ruby value is a message instance, we will fuse +// the message's arena into |arena|, to ensure that this message outlives the +// container. +upb_msgval Convert_RubyToUpb(VALUE ruby_val, const char *name, + TypeInfo type_info, upb_arena *arena); + +// Converts |upb_val| to a Ruby VALUE according to |type_info|. This may involve +// creating a Ruby wrapper object. +// +// The |arena| parameter indicates the arena that owns the lifetime of +// |upb_val|. Any Ruby wrapper object that is created will reference |arena| +// and ensure it outlives the wrapper. +VALUE Convert_UpbToRuby(upb_msgval upb_val, TypeInfo type_info, VALUE arena); + +// Creates a deep copy of |msgval| in |arena|. +upb_msgval Msgval_DeepCopy(upb_msgval msgval, TypeInfo type_info, + upb_arena *arena); + +// Returns true if |val1| and |val2| are equal. Their type is given by +// |type_info|. +bool Msgval_IsEqual(upb_msgval val1, upb_msgval val2, TypeInfo type_info); + +// Returns a hash value for the given upb_msgval. +uint64_t Msgval_GetHash(upb_msgval val, TypeInfo type_info, uint64_t seed); + +#endif // RUBY_PROTOBUF_CONVERT_H_ diff --git a/ruby/ext/google/protobuf_c/defs.c b/ruby/ext/google/protobuf_c/defs.c index 845c02257fc49..6cf8174ccd56b 100644 --- a/ruby/ext/google/protobuf_c/defs.c +++ b/ruby/ext/google/protobuf_c/defs.c @@ -28,8 +28,37 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include +#include +#include + +#include "convert.h" +#include "message.h" #include "protobuf.h" +static VALUE Builder_build(VALUE _self); + +static VALUE cMessageBuilderContext; +static VALUE cOneofBuilderContext; +static VALUE cEnumBuilderContext; +static VALUE cBuilder; + +// ----------------------------------------------------------------------------- +// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor +// instances. +// ----------------------------------------------------------------------------- + +static VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def); +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); + +// 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 +// Ruby. +VALUE c_only_cookie = Qnil; + // ----------------------------------------------------------------------------- // Common utilities. // ----------------------------------------------------------------------------- @@ -46,129 +75,229 @@ static VALUE rb_str_maybe_null(const char* s) { return rb_str_new2(s); } -static upb_def* check_notfrozen(const upb_def* def) { - if (upb_def_isfrozen(def)) { - rb_raise(rb_eRuntimeError, - "Attempt to modify a frozen descriptor. Once descriptors are " - "added to the descriptor pool, they may not be modified."); +// ----------------------------------------------------------------------------- +// Backward compatibility code. +// ----------------------------------------------------------------------------- + +static void rewrite_enum_default(const upb_symtab* symtab, + google_protobuf_FileDescriptorProto* file, + google_protobuf_FieldDescriptorProto* field) { + upb_strview defaultval; + const char *type_name_str; + char *end; + long val; + const upb_enumdef *e; + upb_strview type_name; + + /* Look for TYPE_ENUM fields that have a default. */ + if (google_protobuf_FieldDescriptorProto_type(field) != + google_protobuf_FieldDescriptorProto_TYPE_ENUM || + !google_protobuf_FieldDescriptorProto_has_default_value(field) || + !google_protobuf_FieldDescriptorProto_has_type_name(field)) { + return; + } + + defaultval = google_protobuf_FieldDescriptorProto_default_value(field); + type_name = google_protobuf_FieldDescriptorProto_type_name(field); + + if (defaultval.size == 0 || !isdigit(defaultval.data[0])) { + return; } - return (upb_def*)def; -} -static upb_msgdef* check_msg_notfrozen(const upb_msgdef* def) { - return upb_downcast_msgdef_mutable(check_notfrozen((const upb_def*)def)); + if (type_name.size == 0 || type_name.data[0] != '.') { + return; + } + + type_name_str = type_name.data + 1; + + errno = 0; + val = strtol(defaultval.data, &end, 10); + + if (errno != 0 || *end != 0 || val < INT32_MIN || val > INT32_MAX) { + return; + } + + /* Now find the corresponding enum definition. */ + e = upb_symtab_lookupenum(symtab, type_name_str); + if (e) { + /* Look in previously loaded files. */ + const char *label = upb_enumdef_iton(e, val); + if (!label) { + return; + } + google_protobuf_FieldDescriptorProto_set_default_value( + field, upb_strview_makez(label)); + } else { + /* Look in enums defined in this file. */ + const google_protobuf_EnumDescriptorProto* matching_enum = NULL; + size_t i, n; + const google_protobuf_EnumDescriptorProto* const* enums = + google_protobuf_FileDescriptorProto_enum_type(file, &n); + const google_protobuf_EnumValueDescriptorProto* const* values; + + for (i = 0; i < n; i++) { + if (upb_strview_eql(google_protobuf_EnumDescriptorProto_name(enums[i]), + upb_strview_makez(type_name_str))) { + matching_enum = enums[i]; + break; + } + } + + if (!matching_enum) { + return; + } + + values = google_protobuf_EnumDescriptorProto_value(matching_enum, &n); + for (i = 0; i < n; i++) { + if (google_protobuf_EnumValueDescriptorProto_number(values[i]) == val) { + google_protobuf_FieldDescriptorProto_set_default_value( + field, google_protobuf_EnumValueDescriptorProto_name(values[i])); + return; + } + } + + /* We failed to find an enum default. But we'll just leave the enum + * untouched and let the normal def-building code catch it. */ + } } -static upb_fielddef* check_field_notfrozen(const upb_fielddef* def) { - return upb_downcast_fielddef_mutable(check_notfrozen((const upb_def*)def)); +/* Historically we allowed enum defaults to be specified as a number. In + * retrospect this was a mistake as descriptors require defaults to be + * specified as a label. This can make a difference if multiple labels have the + * same number. + * + * Here we do a pass over all enum defaults and rewrite numeric defaults by + * looking up their labels. This is complicated by the fact that the enum + * definition can live in either the symtab or the file_proto. + * */ +static void rewrite_enum_defaults( + const upb_symtab* symtab, google_protobuf_FileDescriptorProto* file_proto) { + size_t i, n; + google_protobuf_DescriptorProto** msgs = + google_protobuf_FileDescriptorProto_mutable_message_type(file_proto, &n); + + for (i = 0; i < n; i++) { + size_t j, m; + google_protobuf_FieldDescriptorProto** fields = + google_protobuf_DescriptorProto_mutable_field(msgs[i], &m); + for (j = 0; j < m; j++) { + rewrite_enum_default(symtab, file_proto, fields[j]); + } + } } -static upb_oneofdef* check_oneof_notfrozen(const upb_oneofdef* def) { - return (upb_oneofdef*)check_notfrozen((const upb_def*)def); +static void remove_path(upb_strview *name) { + const char* last = strrchr(name->data, '.'); + if (last) { + size_t remove = last - name->data + 1; + name->data += remove; + name->size -= remove; + } } -static upb_enumdef* check_enum_notfrozen(const upb_enumdef* def) { - return (upb_enumdef*)check_notfrozen((const upb_def*)def); +static void rewrite_nesting(VALUE msg_ent, google_protobuf_DescriptorProto* msg, + google_protobuf_DescriptorProto* const* msgs, + google_protobuf_EnumDescriptorProto* const* enums, + upb_arena *arena) { + VALUE submsgs = rb_hash_aref(msg_ent, ID2SYM(rb_intern("msgs"))); + VALUE enum_pos = rb_hash_aref(msg_ent, ID2SYM(rb_intern("enums"))); + int submsg_count; + int enum_count; + int i; + google_protobuf_DescriptorProto** msg_msgs; + google_protobuf_EnumDescriptorProto** msg_enums; + + Check_Type(submsgs, T_ARRAY); + Check_Type(enum_pos, T_ARRAY); + + submsg_count = RARRAY_LEN(submsgs); + enum_count = RARRAY_LEN(enum_pos); + + msg_msgs = google_protobuf_DescriptorProto_resize_nested_type( + msg, submsg_count, arena); + msg_enums = + google_protobuf_DescriptorProto_resize_enum_type(msg, enum_count, arena); + + for (i = 0; i < submsg_count; i++) { + VALUE submsg_ent = RARRAY_PTR(submsgs)[i]; + VALUE pos = rb_hash_aref(submsg_ent, ID2SYM(rb_intern("pos"))); + upb_strview name; + + msg_msgs[i] = msgs[NUM2INT(pos)]; + name = google_protobuf_DescriptorProto_name(msg_msgs[i]); + remove_path(&name); + google_protobuf_DescriptorProto_set_name(msg_msgs[i], name); + rewrite_nesting(submsg_ent, msg_msgs[i], msgs, enums, arena); + } + + for (i = 0; i < enum_count; i++) { + VALUE pos = RARRAY_PTR(enum_pos)[i]; + msg_enums[i] = enums[NUM2INT(pos)]; + } } // ----------------------------------------------------------------------------- // DescriptorPool. // ----------------------------------------------------------------------------- -#define DEFINE_CLASS(name, string_name) \ - VALUE c ## name; \ - const rb_data_type_t _ ## name ## _type = { \ - string_name, \ - { name ## _mark, name ## _free, NULL }, \ - }; \ - name* ruby_to_ ## name(VALUE val) { \ - name* ret; \ - TypedData_Get_Struct(val, name, &_ ## name ## _type, ret); \ - return ret; \ - } \ - -#define DEFINE_SELF(type, var, rb_var) \ - type* var = ruby_to_ ## type(rb_var) +typedef struct { + VALUE def_to_descriptor; // Hash table of def* -> Ruby descriptor. + upb_symtab* symtab; +} DescriptorPool; + +VALUE cDescriptorPool = Qnil; // Global singleton DescriptorPool. The user is free to create others, but this // is used by generated code. -VALUE generated_pool; +VALUE generated_pool = Qnil; -DEFINE_CLASS(DescriptorPool, "Google::Protobuf::DescriptorPool"); - -void DescriptorPool_mark(void* _self) { +static void DescriptorPool_mark(void* _self) { + DescriptorPool* self = _self; + rb_gc_mark(self->def_to_descriptor); } -void DescriptorPool_free(void* _self) { +static void DescriptorPool_free(void* _self) { DescriptorPool* self = _self; upb_symtab_free(self->symtab); xfree(self); } +static const rb_data_type_t DescriptorPool_type = { + "Google::Protobuf::DescriptorPool", + {DescriptorPool_mark, DescriptorPool_free, NULL}, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static DescriptorPool* ruby_to_DescriptorPool(VALUE val) { + DescriptorPool* ret; + TypedData_Get_Struct(val, DescriptorPool, &DescriptorPool_type, ret); + return ret; +} + +// Exposed to other modules in defs.h. +const upb_symtab *DescriptorPool_GetSymtab(VALUE desc_pool_rb) { + DescriptorPool *pool = ruby_to_DescriptorPool(desc_pool_rb); + return pool->symtab; +} + /* * call-seq: * DescriptorPool.new => pool * * Creates a new, empty, descriptor pool. */ -VALUE DescriptorPool_alloc(VALUE klass) { +static VALUE DescriptorPool_alloc(VALUE klass) { DescriptorPool* self = ALLOC(DescriptorPool); - self->symtab = upb_symtab_new(); - return TypedData_Wrap_Struct(klass, &_DescriptorPool_type, self); -} + VALUE ret; -void DescriptorPool_register(VALUE module) { - VALUE klass = rb_define_class_under( - module, "DescriptorPool", rb_cObject); - rb_define_alloc_func(klass, DescriptorPool_alloc); - rb_define_method(klass, "add", DescriptorPool_add, 1); - rb_define_method(klass, "build", DescriptorPool_build, 0); - rb_define_method(klass, "lookup", DescriptorPool_lookup, 1); - rb_define_singleton_method(klass, "generated_pool", - DescriptorPool_generated_pool, 0); - cDescriptorPool = klass; - rb_gc_register_address(&cDescriptorPool); + self->def_to_descriptor = Qnil; + ret = TypedData_Wrap_Struct(klass, &DescriptorPool_type, self); - generated_pool = rb_class_new_instance(0, NULL, klass); - rb_gc_register_address(&generated_pool); -} - -static void add_descriptor_to_pool(DescriptorPool* self, - Descriptor* descriptor) { - CHECK_UPB( - upb_symtab_add(self->symtab, (upb_def**)&descriptor->msgdef, 1, - NULL, &status), - "Adding Descriptor to DescriptorPool failed"); -} - -static void add_enumdesc_to_pool(DescriptorPool* self, - EnumDescriptor* enumdesc) { - CHECK_UPB( - upb_symtab_add(self->symtab, (upb_def**)&enumdesc->enumdef, 1, - NULL, &status), - "Adding EnumDescriptor to DescriptorPool failed"); -} + self->def_to_descriptor = rb_hash_new(); + self->symtab = upb_symtab_new(); + ObjectCache_Add(self->symtab, ret, _upb_symtab_arena(self->symtab)); -/* - * call-seq: - * DescriptorPool.add(descriptor) - * - * Adds the given Descriptor or EnumDescriptor to this pool. All references to - * other types in a Descriptor's fields must be resolvable within this pool or - * an exception will be raised. - */ -VALUE DescriptorPool_add(VALUE _self, VALUE def) { - DEFINE_SELF(DescriptorPool, self, _self); - VALUE def_klass = rb_obj_class(def); - if (def_klass == cDescriptor) { - add_descriptor_to_pool(self, ruby_to_Descriptor(def)); - } else if (def_klass == cEnumDescriptor) { - add_enumdesc_to_pool(self, ruby_to_EnumDescriptor(def)); - } else { - rb_raise(rb_eArgError, - "Second argument must be a Descriptor or EnumDescriptor."); - } - return Qnil; + return ret; } /* @@ -181,11 +310,11 @@ VALUE DescriptorPool_add(VALUE _self, VALUE def) { * Builder#add_enum within the block as appropriate. This is the recommended, * idiomatic way to define new message and enum types. */ -VALUE DescriptorPool_build(VALUE _self) { - VALUE ctx = rb_class_new_instance(0, NULL, cBuilder); +static VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) { + VALUE ctx = rb_class_new_instance(1, &_self, cBuilder); VALUE block = rb_block_proc(); rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block); - rb_funcall(ctx, rb_intern("finalize_to_pool"), 1, _self); + Builder_build(ctx); return Qnil; } @@ -196,14 +325,23 @@ VALUE DescriptorPool_build(VALUE _self) { * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none * exists with the given name. */ -VALUE DescriptorPool_lookup(VALUE _self, VALUE name) { - DEFINE_SELF(DescriptorPool, self, _self); +static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) { + DescriptorPool* self = ruby_to_DescriptorPool(_self); const char* name_str = get_str(name); - const upb_def* def = upb_symtab_lookup(self->symtab, name_str); - if (!def) { - return Qnil; + const upb_msgdef* msgdef; + const upb_enumdef* enumdef; + + msgdef = upb_symtab_lookupmsg(self->symtab, name_str); + if (msgdef) { + return get_msgdef_obj(_self, msgdef); + } + + enumdef = upb_symtab_lookupenum(self->symtab, name_str); + if (enumdef) { + return get_enumdef_obj(_self, enumdef); } - return get_def_obj(def); + + return Qnil; } /* @@ -215,51 +353,53 @@ VALUE DescriptorPool_lookup(VALUE _self, VALUE name) { * register types in this pool for convenience so that they do not have to hold * a reference to a private pool instance. */ -VALUE DescriptorPool_generated_pool(VALUE _self) { +static VALUE DescriptorPool_generated_pool(VALUE _self) { return generated_pool; } +static void DescriptorPool_register(VALUE module) { + VALUE klass = rb_define_class_under( + module, "DescriptorPool", rb_cObject); + rb_define_alloc_func(klass, DescriptorPool_alloc); + rb_define_method(klass, "build", DescriptorPool_build, -1); + rb_define_method(klass, "lookup", DescriptorPool_lookup, 1); + rb_define_singleton_method(klass, "generated_pool", + DescriptorPool_generated_pool, 0); + rb_gc_register_address(&cDescriptorPool); + cDescriptorPool = klass; + + rb_gc_register_address(&generated_pool); + generated_pool = rb_class_new_instance(0, NULL, klass); +} + // ----------------------------------------------------------------------------- // Descriptor. // ----------------------------------------------------------------------------- -DEFINE_CLASS(Descriptor, "Google::Protobuf::Descriptor"); +typedef struct { + const upb_msgdef* msgdef; + VALUE klass; + VALUE descriptor_pool; +} Descriptor; -void Descriptor_mark(void* _self) { +VALUE cDescriptor = Qnil; + +static void Descriptor_mark(void* _self) { Descriptor* self = _self; rb_gc_mark(self->klass); - rb_gc_mark(self->typeclass_references); + rb_gc_mark(self->descriptor_pool); } -void Descriptor_free(void* _self) { - Descriptor* self = _self; - upb_msgdef_unref(self->msgdef, &self->msgdef); - if (self->layout) { - free_layout(self->layout); - } - if (self->fill_handlers) { - upb_handlers_unref(self->fill_handlers, &self->fill_handlers); - } - if (self->fill_method) { - upb_pbdecodermethod_unref(self->fill_method, &self->fill_method); - } - if (self->json_fill_method) { - upb_json_parsermethod_unref(self->json_fill_method, - &self->json_fill_method); - } - if (self->pb_serialize_handlers) { - upb_handlers_unref(self->pb_serialize_handlers, - &self->pb_serialize_handlers); - } - if (self->json_serialize_handlers) { - upb_handlers_unref(self->json_serialize_handlers, - &self->json_serialize_handlers); - } - if (self->json_serialize_handlers_preserve) { - upb_handlers_unref(self->json_serialize_handlers_preserve, - &self->json_serialize_handlers_preserve); - } - xfree(self); +static const rb_data_type_t Descriptor_type = { + "Google::Protobuf::Descriptor", + {Descriptor_mark, RUBY_DEFAULT_FREE, NULL}, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static Descriptor* ruby_to_Descriptor(VALUE val) { + Descriptor* ret; + TypedData_Get_Struct(val, Descriptor, &Descriptor_type, ret); + return ret; } /* @@ -271,67 +411,57 @@ void Descriptor_free(void* _self) { * it is added to a pool, after which it becomes immutable (as part of a * finalization process). */ -VALUE Descriptor_alloc(VALUE klass) { +static VALUE Descriptor_alloc(VALUE klass) { Descriptor* self = ALLOC(Descriptor); - VALUE ret = TypedData_Wrap_Struct(klass, &_Descriptor_type, self); - self->msgdef = upb_msgdef_new(&self->msgdef); + VALUE ret = TypedData_Wrap_Struct(klass, &Descriptor_type, self); + self->msgdef = NULL; self->klass = Qnil; - self->layout = NULL; - self->fill_handlers = NULL; - self->fill_method = NULL; - self->json_fill_method = NULL; - self->pb_serialize_handlers = NULL; - self->json_serialize_handlers = NULL; - self->json_serialize_handlers_preserve = NULL; - self->typeclass_references = rb_ary_new(); + self->descriptor_pool = Qnil; return ret; } -void Descriptor_register(VALUE module) { - VALUE klass = rb_define_class_under( - module, "Descriptor", rb_cObject); - rb_define_alloc_func(klass, Descriptor_alloc); - rb_define_method(klass, "each", Descriptor_each, 0); - rb_define_method(klass, "lookup", Descriptor_lookup, 1); - rb_define_method(klass, "add_field", Descriptor_add_field, 1); - rb_define_method(klass, "add_oneof", Descriptor_add_oneof, 1); - rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0); - rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1); - rb_define_method(klass, "msgclass", Descriptor_msgclass, 0); - rb_define_method(klass, "name", Descriptor_name, 0); - rb_define_method(klass, "name=", Descriptor_name_set, 1); - rb_include_module(klass, rb_mEnumerable); - cDescriptor = klass; - rb_gc_register_address(&cDescriptor); +/* + * call-seq: + * Descriptor.new(c_only_cookie, ptr) => Descriptor + * + * Creates a descriptor wrapper object. May only be called from C. + */ +static VALUE Descriptor_initialize(VALUE _self, VALUE cookie, + VALUE descriptor_pool, VALUE ptr) { + Descriptor* self = ruby_to_Descriptor(_self); + + if (cookie != c_only_cookie) { + rb_raise(rb_eRuntimeError, + "Descriptor objects may not be created from Ruby."); + } + + self->descriptor_pool = descriptor_pool; + self->msgdef = (const upb_msgdef*)NUM2ULL(ptr); + + return Qnil; } /* * call-seq: - * Descriptor.name => name + * Descriptor.file_descriptor * - * Returns the name of this message type as a fully-qualfied string (e.g., - * My.Package.MessageType). + * Returns the FileDescriptor object this message belongs to. */ -VALUE Descriptor_name(VALUE _self) { - DEFINE_SELF(Descriptor, self, _self); - return rb_str_maybe_null(upb_msgdef_fullname(self->msgdef)); +static VALUE Descriptor_file_descriptor(VALUE _self) { + Descriptor* self = ruby_to_Descriptor(_self); + return get_filedef_obj(self->descriptor_pool, upb_msgdef_file(self->msgdef)); } /* * call-seq: - * Descriptor.name = name + * Descriptor.name => name * - * Assigns a name to this message type. The descriptor must not have been added - * to a pool yet. + * Returns the name of this message type as a fully-qualified string (e.g., + * My.Package.MessageType). */ -VALUE Descriptor_name_set(VALUE _self, VALUE str) { - DEFINE_SELF(Descriptor, self, _self); - upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef); - const char* name = get_str(str); - CHECK_UPB( - upb_msgdef_setfullname(mut_def, name, &status), - "Error setting Descriptor name"); - return Qnil; +static VALUE Descriptor_name(VALUE _self) { + Descriptor* self = ruby_to_Descriptor(_self); + return rb_str_maybe_null(upb_msgdef_fullname(self->msgdef)); } /* @@ -340,15 +470,15 @@ VALUE Descriptor_name_set(VALUE _self, VALUE str) { * * Iterates over fields in this message type, yielding to the block on each one. */ -VALUE Descriptor_each(VALUE _self) { - DEFINE_SELF(Descriptor, self, _self); +static VALUE Descriptor_each(VALUE _self) { + Descriptor* self = ruby_to_Descriptor(_self); upb_msg_field_iter it; for (upb_msg_field_begin(&it, self->msgdef); !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* field = upb_msg_iter_field(&it); - VALUE obj = get_def_obj(field); + VALUE obj = get_fielddef_obj(self->descriptor_pool, field); rb_yield(obj); } return Qnil; @@ -361,58 +491,14 @@ VALUE Descriptor_each(VALUE _self) { * Returns the field descriptor for the field with the given name, if present, * or nil if none. */ -VALUE Descriptor_lookup(VALUE _self, VALUE name) { - DEFINE_SELF(Descriptor, self, _self); +static VALUE Descriptor_lookup(VALUE _self, VALUE name) { + Descriptor* self = ruby_to_Descriptor(_self); const char* s = get_str(name); const upb_fielddef* field = upb_msgdef_ntofz(self->msgdef, s); if (field == NULL) { return Qnil; } - return get_def_obj(field); -} - -/* - * call-seq: - * Descriptor.add_field(field) => nil - * - * Adds the given FieldDescriptor to this message type. This descriptor must not - * have been added to a pool yet. Raises an exception if a field with the same - * name or number already exists. Sub-type references (e.g. for fields of type - * message) are not resolved at this point. - */ -VALUE Descriptor_add_field(VALUE _self, VALUE obj) { - DEFINE_SELF(Descriptor, self, _self); - upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef); - FieldDescriptor* def = ruby_to_FieldDescriptor(obj); - upb_fielddef* mut_field_def = check_field_notfrozen(def->fielddef); - CHECK_UPB( - upb_msgdef_addfield(mut_def, mut_field_def, NULL, &status), - "Adding field to Descriptor failed"); - add_def_obj(def->fielddef, obj); - return Qnil; -} - -/* - * call-seq: - * Descriptor.add_oneof(oneof) => nil - * - * Adds the given OneofDescriptor to this message type. This descriptor must not - * have been added to a pool yet. Raises an exception if a oneof with the same - * name already exists, or if any of the oneof's fields' names or numbers - * conflict with an existing field in this message type. All fields in the oneof - * are added to the message descriptor. Sub-type references (e.g. for fields of - * type message) are not resolved at this point. - */ -VALUE Descriptor_add_oneof(VALUE _self, VALUE obj) { - DEFINE_SELF(Descriptor, self, _self); - upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef); - OneofDescriptor* def = ruby_to_OneofDescriptor(obj); - upb_oneofdef* mut_oneof_def = check_oneof_notfrozen(def->oneofdef); - CHECK_UPB( - upb_msgdef_addoneof(mut_def, mut_oneof_def, NULL, &status), - "Adding oneof to Descriptor failed"); - add_def_obj(def->oneofdef, obj); - return Qnil; + return get_fielddef_obj(self->descriptor_pool, field); } /* @@ -422,15 +508,15 @@ VALUE Descriptor_add_oneof(VALUE _self, VALUE obj) { * Invokes the given block for each oneof in this message type, passing the * corresponding OneofDescriptor. */ -VALUE Descriptor_each_oneof(VALUE _self) { - DEFINE_SELF(Descriptor, self, _self); +static VALUE Descriptor_each_oneof(VALUE _self) { + Descriptor* self = ruby_to_Descriptor(_self); upb_msg_oneof_iter it; for (upb_msg_oneof_begin(&it, self->msgdef); !upb_msg_oneof_done(&it); upb_msg_oneof_next(&it)) { const upb_oneofdef* oneof = upb_msg_iter_oneof(&it); - VALUE obj = get_def_obj(oneof); + VALUE obj = get_oneofdef_obj(self->descriptor_pool, oneof); rb_yield(obj); } return Qnil; @@ -443,48 +529,173 @@ VALUE Descriptor_each_oneof(VALUE _self) { * Returns the oneof descriptor for the oneof with the given name, if present, * or nil if none. */ -VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) { - DEFINE_SELF(Descriptor, self, _self); +static VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) { + Descriptor* self = ruby_to_Descriptor(_self); const char* s = get_str(name); const upb_oneofdef* oneof = upb_msgdef_ntooz(self->msgdef, s); if (oneof == NULL) { return Qnil; } - return get_def_obj(oneof); + return get_oneofdef_obj(self->descriptor_pool, oneof); } /* * call-seq: * Descriptor.msgclass => message_klass * - * Returns the Ruby class created for this message type. Valid only once the - * message type has been added to a pool. + * Returns the Ruby class created for this message type. */ -VALUE Descriptor_msgclass(VALUE _self) { - DEFINE_SELF(Descriptor, self, _self); - if (!upb_def_isfrozen((const upb_def*)self->msgdef)) { - rb_raise(rb_eRuntimeError, - "Cannot fetch message class from a Descriptor not yet in a pool."); - } +static VALUE Descriptor_msgclass(VALUE _self) { + Descriptor* self = ruby_to_Descriptor(_self); if (self->klass == Qnil) { - self->klass = build_class_from_descriptor(self); + self->klass = build_class_from_descriptor(_self); } return self->klass; } +static void Descriptor_register(VALUE module) { + VALUE klass = rb_define_class_under( + module, "Descriptor", rb_cObject); + rb_define_alloc_func(klass, Descriptor_alloc); + rb_define_method(klass, "initialize", Descriptor_initialize, 3); + rb_define_method(klass, "each", Descriptor_each, 0); + rb_define_method(klass, "lookup", Descriptor_lookup, 1); + rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0); + rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1); + rb_define_method(klass, "msgclass", Descriptor_msgclass, 0); + rb_define_method(klass, "name", Descriptor_name, 0); + rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0); + rb_include_module(klass, rb_mEnumerable); + rb_gc_register_address(&cDescriptor); + cDescriptor = klass; +} + // ----------------------------------------------------------------------------- -// FieldDescriptor. +// FileDescriptor. // ----------------------------------------------------------------------------- -DEFINE_CLASS(FieldDescriptor, "Google::Protobuf::FieldDescriptor"); +typedef struct { + const upb_filedef* filedef; + VALUE descriptor_pool; // Owns the upb_filedef. +} FileDescriptor; + +static VALUE cFileDescriptor = Qnil; + +static void FileDescriptor_mark(void* _self) { + FileDescriptor* self = _self; + rb_gc_mark(self->descriptor_pool); +} + +static const rb_data_type_t FileDescriptor_type = { + "Google::Protobuf::FileDescriptor", + {FileDescriptor_mark, RUBY_DEFAULT_FREE, NULL}, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static FileDescriptor* ruby_to_FileDescriptor(VALUE val) { + FileDescriptor* ret; + TypedData_Get_Struct(val, FileDescriptor, &FileDescriptor_type, ret); + return ret; +} + +static VALUE FileDescriptor_alloc(VALUE klass) { + FileDescriptor* self = ALLOC(FileDescriptor); + VALUE ret = TypedData_Wrap_Struct(klass, &FileDescriptor_type, self); + self->descriptor_pool = Qnil; + self->filedef = NULL; + return ret; +} + +/* + * call-seq: + * FileDescriptor.new => file + * + * Returns a new file descriptor. The syntax must be set before it's passed + * to a builder. + */ +static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie, + VALUE descriptor_pool, VALUE ptr) { + FileDescriptor* self = ruby_to_FileDescriptor(_self); + + if (cookie != c_only_cookie) { + rb_raise(rb_eRuntimeError, + "Descriptor objects may not be created from Ruby."); + } + + self->descriptor_pool = descriptor_pool; + self->filedef = (const upb_filedef*)NUM2ULL(ptr); + + return Qnil; +} + +/* + * call-seq: + * FileDescriptor.name => name + * + * Returns the name of the file. + */ +static VALUE FileDescriptor_name(VALUE _self) { + FileDescriptor* self = ruby_to_FileDescriptor(_self); + const char* name = upb_filedef_name(self->filedef); + return name == NULL ? Qnil : rb_str_new2(name); +} + +/* + * call-seq: + * FileDescriptor.syntax => syntax + * + * Returns this file descriptors syntax. + * + * Valid syntax versions are: + * :proto2 or :proto3. + */ +static VALUE FileDescriptor_syntax(VALUE _self) { + FileDescriptor* self = ruby_to_FileDescriptor(_self); + + switch (upb_filedef_syntax(self->filedef)) { + case UPB_SYNTAX_PROTO3: return ID2SYM(rb_intern("proto3")); + case UPB_SYNTAX_PROTO2: return ID2SYM(rb_intern("proto2")); + default: return Qnil; + } +} -void FieldDescriptor_mark(void* _self) { +static void FileDescriptor_register(VALUE module) { + VALUE klass = rb_define_class_under( + module, "FileDescriptor", rb_cObject); + rb_define_alloc_func(klass, FileDescriptor_alloc); + rb_define_method(klass, "initialize", FileDescriptor_initialize, 3); + rb_define_method(klass, "name", FileDescriptor_name, 0); + rb_define_method(klass, "syntax", FileDescriptor_syntax, 0); + rb_gc_register_address(&cFileDescriptor); + cFileDescriptor = klass; } -void FieldDescriptor_free(void* _self) { +// ----------------------------------------------------------------------------- +// FieldDescriptor. +// ----------------------------------------------------------------------------- + +typedef struct { + const upb_fielddef* fielddef; + VALUE descriptor_pool; // Owns the upb_fielddef. +} FieldDescriptor; + +static VALUE cFieldDescriptor = Qnil; + +static void FieldDescriptor_mark(void* _self) { FieldDescriptor* self = _self; - upb_fielddef_unref(self->fielddef, &self->fielddef); - xfree(self); + rb_gc_mark(self->descriptor_pool); +} + +static const rb_data_type_t FieldDescriptor_type = { + "Google::Protobuf::FieldDescriptor", + {FieldDescriptor_mark, RUBY_DEFAULT_FREE, NULL}, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static FieldDescriptor* ruby_to_FieldDescriptor(VALUE val) { + FieldDescriptor* ret; + TypedData_Get_Struct(val, FieldDescriptor, &FieldDescriptor_type, ret); + return ret; } /* @@ -494,63 +705,46 @@ void FieldDescriptor_free(void* _self) { * Returns a new field descriptor. Its name, type, etc. must be set before it is * added to a message type. */ -VALUE FieldDescriptor_alloc(VALUE klass) { +static VALUE FieldDescriptor_alloc(VALUE klass) { FieldDescriptor* self = ALLOC(FieldDescriptor); - VALUE ret = TypedData_Wrap_Struct(klass, &_FieldDescriptor_type, self); - upb_fielddef* fielddef = upb_fielddef_new(&self->fielddef); - upb_fielddef_setpacked(fielddef, false); - self->fielddef = fielddef; + VALUE ret = TypedData_Wrap_Struct(klass, &FieldDescriptor_type, self); + self->fielddef = NULL; return ret; } -void FieldDescriptor_register(VALUE module) { - VALUE klass = rb_define_class_under( - module, "FieldDescriptor", rb_cObject); - rb_define_alloc_func(klass, FieldDescriptor_alloc); - rb_define_method(klass, "name", FieldDescriptor_name, 0); - rb_define_method(klass, "name=", FieldDescriptor_name_set, 1); - rb_define_method(klass, "type", FieldDescriptor_type, 0); - rb_define_method(klass, "type=", FieldDescriptor_type_set, 1); - rb_define_method(klass, "label", FieldDescriptor_label, 0); - rb_define_method(klass, "label=", FieldDescriptor_label_set, 1); - rb_define_method(klass, "number", FieldDescriptor_number, 0); - rb_define_method(klass, "number=", FieldDescriptor_number_set, 1); - rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0); - rb_define_method(klass, "submsg_name=", FieldDescriptor_submsg_name_set, 1); - rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0); - rb_define_method(klass, "get", FieldDescriptor_get, 1); - rb_define_method(klass, "set", FieldDescriptor_set, 2); - cFieldDescriptor = klass; - rb_gc_register_address(&cFieldDescriptor); -} - /* * call-seq: - * FieldDescriptor.name => name + * EnumDescriptor.new(c_only_cookie, pool, ptr) => EnumDescriptor * - * Returns the name of this field. + * Creates a descriptor wrapper object. May only be called from C. */ -VALUE FieldDescriptor_name(VALUE _self) { - DEFINE_SELF(FieldDescriptor, self, _self); - return rb_str_maybe_null(upb_fielddef_name(self->fielddef)); +static VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie, + VALUE descriptor_pool, VALUE ptr) { + FieldDescriptor* self = ruby_to_FieldDescriptor(_self); + + if (cookie != c_only_cookie) { + rb_raise(rb_eRuntimeError, + "Descriptor objects may not be created from Ruby."); + } + + self->descriptor_pool = descriptor_pool; + self->fielddef = (const upb_fielddef*)NUM2ULL(ptr); + + return Qnil; } /* * call-seq: - * FieldDescriptor.name = name + * FieldDescriptor.name => name * - * Sets the name of this field. Cannot be called once the containing message - * type, if any, is added to a pool. + * Returns the name of this field. */ -VALUE FieldDescriptor_name_set(VALUE _self, VALUE str) { - DEFINE_SELF(FieldDescriptor, self, _self); - upb_fielddef* mut_def = check_field_notfrozen(self->fielddef); - const char* name = get_str(str); - CHECK_UPB(upb_fielddef_setname(mut_def, name, &status), - "Error setting FieldDescriptor name"); - return Qnil; +static VALUE FieldDescriptor_name(VALUE _self) { + FieldDescriptor* self = ruby_to_FieldDescriptor(_self); + return rb_str_maybe_null(upb_fielddef_name(self->fielddef)); } +// Non-static, exposed to other .c files. upb_fieldtype_t ruby_to_fieldtype(VALUE type) { if (TYPE(type) != T_SYMBOL) { rb_raise(rb_eArgError, "Expected symbol for field type."); @@ -579,29 +773,9 @@ upb_fieldtype_t ruby_to_fieldtype(VALUE type) { return 0; } -VALUE fieldtype_to_ruby(upb_fieldtype_t type) { - switch (type) { -#define CONVERT(upb, ruby) \ - case UPB_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby )); - CONVERT(FLOAT, float); - CONVERT(DOUBLE, double); - CONVERT(BOOL, bool); - CONVERT(STRING, string); - CONVERT(BYTES, bytes); - CONVERT(MESSAGE, message); - CONVERT(ENUM, enum); - CONVERT(INT32, int32); - CONVERT(INT64, int64); - CONVERT(UINT32, uint32); - CONVERT(UINT64, uint64); -#undef CONVERT - } - return Qnil; -} - -upb_descriptortype_t ruby_to_descriptortype(VALUE type) { - if (TYPE(type) != T_SYMBOL) { - rb_raise(rb_eArgError, "Expected symbol for field type."); +static upb_descriptortype_t ruby_to_descriptortype(VALUE type) { + if (TYPE(type) != T_SYMBOL) { + rb_raise(rb_eArgError, "Expected symbol for field type."); } #define CONVERT(upb, ruby) \ @@ -634,7 +808,7 @@ upb_descriptortype_t ruby_to_descriptortype(VALUE type) { return 0; } -VALUE descriptortype_to_ruby(upb_descriptortype_t type) { +static VALUE descriptortype_to_ruby(upb_descriptortype_t type) { switch (type) { #define CONVERT(upb, ruby) \ case UPB_DESCRIPTOR_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby )); @@ -671,26 +845,27 @@ VALUE descriptortype_to_ruby(upb_descriptortype_t type) { * :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string, * :bytes, :message. */ -VALUE FieldDescriptor_type(VALUE _self) { - DEFINE_SELF(FieldDescriptor, self, _self); - if (!upb_fielddef_typeisset(self->fielddef)) { - return Qnil; - } +static VALUE FieldDescriptor__type(VALUE _self) { + FieldDescriptor* self = ruby_to_FieldDescriptor(_self); return descriptortype_to_ruby(upb_fielddef_descriptortype(self->fielddef)); } /* * call-seq: - * FieldDescriptor.type = type + * FieldDescriptor.default => default * - * Sets this field's type. Cannot be called if field is part of a message type - * already in a pool. + * Returns this field's default, as a Ruby object, or nil if not yet set. */ -VALUE FieldDescriptor_type_set(VALUE _self, VALUE type) { - DEFINE_SELF(FieldDescriptor, self, _self); - upb_fielddef* mut_def = check_field_notfrozen(self->fielddef); - upb_fielddef_setdescriptortype(mut_def, ruby_to_descriptortype(type)); - return Qnil; +static VALUE FieldDescriptor_default(VALUE _self) { + FieldDescriptor* self = ruby_to_FieldDescriptor(_self); + const upb_fielddef *f = self->fielddef; + upb_msgval default_val = {0}; + if (upb_fielddef_issubmsg(f)) { + return Qnil; + } else if (!upb_fielddef_isseq(f)) { + default_val = upb_fielddef_default(f); + } + return Convert_UpbToRuby(default_val, TypeInfo_get(self->fielddef), Qnil); } /* @@ -702,8 +877,8 @@ VALUE FieldDescriptor_type_set(VALUE _self, VALUE type) { * Valid field labels are: * :optional, :repeated */ -VALUE FieldDescriptor_label(VALUE _self) { - DEFINE_SELF(FieldDescriptor, self, _self); +static VALUE FieldDescriptor_label(VALUE _self) { + FieldDescriptor* self = ruby_to_FieldDescriptor(_self); switch (upb_fielddef_label(self->fielddef)) { #define CONVERT(upb, ruby) \ case UPB_LABEL_ ## upb : return ID2SYM(rb_intern( # ruby )); @@ -718,70 +893,17 @@ VALUE FieldDescriptor_label(VALUE _self) { return Qnil; } -/* - * call-seq: - * FieldDescriptor.label = label - * - * Sets the label on this field. Cannot be called if field is part of a message - * type already in a pool. - */ -VALUE FieldDescriptor_label_set(VALUE _self, VALUE label) { - DEFINE_SELF(FieldDescriptor, self, _self); - upb_fielddef* mut_def = check_field_notfrozen(self->fielddef); - upb_label_t upb_label = -1; - bool converted = false; - - if (TYPE(label) != T_SYMBOL) { - rb_raise(rb_eArgError, "Expected symbol for field label."); - } - -#define CONVERT(upb, ruby) \ - if (SYM2ID(label) == rb_intern( # ruby )) { \ - upb_label = UPB_LABEL_ ## upb; \ - converted = true; \ - } - - CONVERT(OPTIONAL, optional); - CONVERT(REQUIRED, required); - CONVERT(REPEATED, repeated); - -#undef CONVERT - - if (!converted) { - rb_raise(rb_eArgError, "Unknown field label."); - } - - upb_fielddef_setlabel(mut_def, upb_label); - - return Qnil; -} - /* * call-seq: * FieldDescriptor.number => number * * Returns the tag number for this field. */ -VALUE FieldDescriptor_number(VALUE _self) { - DEFINE_SELF(FieldDescriptor, self, _self); +static VALUE FieldDescriptor_number(VALUE _self) { + FieldDescriptor* self = ruby_to_FieldDescriptor(_self); return INT2NUM(upb_fielddef_number(self->fielddef)); } -/* - * call-seq: - * FieldDescriptor.number = number - * - * Sets the tag number for this field. Cannot be called if field is part of a - * message type already in a pool. - */ -VALUE FieldDescriptor_number_set(VALUE _self, VALUE number) { - DEFINE_SELF(FieldDescriptor, self, _self); - upb_fielddef* mut_def = check_field_notfrozen(self->fielddef); - CHECK_UPB(upb_fielddef_setnumber(mut_def, NUM2INT(number), &status), - "Error setting field number"); - return Qnil; -} - /* * call-seq: * FieldDescriptor.submsg_name => submsg_name @@ -791,34 +913,18 @@ VALUE FieldDescriptor_number_set(VALUE _self, VALUE number) { * name will be resolved within the context of the pool to which the containing * message type is added. */ -VALUE FieldDescriptor_submsg_name(VALUE _self) { - DEFINE_SELF(FieldDescriptor, self, _self); - if (!upb_fielddef_hassubdef(self->fielddef)) { - return Qnil; +static VALUE FieldDescriptor_submsg_name(VALUE _self) { + FieldDescriptor* self = ruby_to_FieldDescriptor(_self); + switch (upb_fielddef_type(self->fielddef)) { + case UPB_TYPE_ENUM: + return rb_str_new2( + upb_enumdef_fullname(upb_fielddef_enumsubdef(self->fielddef))); + case UPB_TYPE_MESSAGE: + return rb_str_new2( + upb_msgdef_fullname(upb_fielddef_msgsubdef(self->fielddef))); + default: + return Qnil; } - return rb_str_maybe_null(upb_fielddef_subdefname(self->fielddef)); -} - -/* - * call-seq: - * FieldDescriptor.submsg_name = submsg_name - * - * Sets the name of the message or enum type corresponding to this field, if it - * is a message or enum field (respectively). This type name will be resolved - * within the context of the pool to which the containing message type is added. - * Cannot be called on field that are not of message or enum type, or on fields - * that are part of a message type already added to a pool. - */ -VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value) { - DEFINE_SELF(FieldDescriptor, self, _self); - upb_fielddef* mut_def = check_field_notfrozen(self->fielddef); - const char* str = get_str(value); - if (!upb_fielddef_hassubdef(self->fielddef)) { - rb_raise(rb_eTypeError, "FieldDescriptor does not have subdef."); - } - CHECK_UPB(upb_fielddef_setsubdefname(mut_def, str, &status), - "Error setting submessage name"); - return Qnil; } /* @@ -830,18 +936,18 @@ VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value) { * called *until* the containing message type is added to a pool (and thus * resolved). */ -VALUE FieldDescriptor_subtype(VALUE _self) { - DEFINE_SELF(FieldDescriptor, self, _self); - const upb_def* def; - - if (!upb_fielddef_hassubdef(self->fielddef)) { - return Qnil; - } - def = upb_fielddef_subdef(self->fielddef); - if (def == NULL) { - return Qnil; +static VALUE FieldDescriptor_subtype(VALUE _self) { + FieldDescriptor* self = ruby_to_FieldDescriptor(_self); + switch (upb_fielddef_type(self->fielddef)) { + case UPB_TYPE_ENUM: + return get_enumdef_obj(self->descriptor_pool, + upb_fielddef_enumsubdef(self->fielddef)); + case UPB_TYPE_MESSAGE: + return get_msgdef_obj(self->descriptor_pool, + upb_fielddef_msgsubdef(self->fielddef)); + default: + return Qnil; } - return get_def_obj(def); } /* @@ -851,14 +957,59 @@ VALUE FieldDescriptor_subtype(VALUE _self) { * Returns the value set for this field on the given message. Raises an * exception if message is of the wrong type. */ -VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) { - DEFINE_SELF(FieldDescriptor, self, _self); - MessageHeader* msg; - TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); - if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) { - rb_raise(rb_eTypeError, "get method called on wrong message type"); +static VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) { + FieldDescriptor* self = ruby_to_FieldDescriptor(_self); + const upb_msgdef *m; + const upb_msgdef *msg = Message_Get(msg_rb, &m); + VALUE arena = Message_GetArena(msg_rb); + upb_msgval msgval; + + if (m != upb_fielddef_containingtype(self->fielddef)) { + rb_raise(cTypeError, "get method called on wrong message type"); + } + + msgval = upb_msg_get(msg, self->fielddef); + return Convert_UpbToRuby(msgval, TypeInfo_get(self->fielddef), arena); +} + +/* + * call-seq: + * FieldDescriptor.has?(message) => boolean + * + * Returns whether the value is set on the given message. Raises an + * exception when calling for fields that do not have presence. + */ +static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) { + FieldDescriptor* self = ruby_to_FieldDescriptor(_self); + const upb_msgdef *m; + const upb_msgdef *msg = Message_Get(msg_rb, &m); + + if (m != upb_fielddef_containingtype(self->fielddef)) { + rb_raise(cTypeError, "has method called on wrong message type"); + } else if (!upb_fielddef_haspresence(self->fielddef)) { + rb_raise(rb_eArgError, "does not track presence"); + } + + return upb_msg_has(msg, self->fielddef) ? Qtrue : Qfalse; +} + +/* + * call-seq: + * FieldDescriptor.clear(message) + * + * Clears the field from the message if it's set. + */ +static VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) { + FieldDescriptor* self = ruby_to_FieldDescriptor(_self); + const upb_msgdef *m; + upb_msgdef *msg = Message_GetMutable(msg_rb, &m); + + if (m != upb_fielddef_containingtype(self->fielddef)) { + rb_raise(cTypeError, "has method called on wrong message type"); } - return layout_get(msg->descriptor->layout, Message_data(msg), self->fielddef); + + upb_msg_clearfield(msg, self->fielddef); + return Qnil; } /* @@ -869,30 +1020,69 @@ VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) { * message. Raises an exception if message is of the wrong type. Performs the * ordinary type-checks for field setting. */ -VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) { - DEFINE_SELF(FieldDescriptor, self, _self); - MessageHeader* msg; - TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); - if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) { - rb_raise(rb_eTypeError, "set method called on wrong message type"); - } - layout_set(msg->descriptor->layout, Message_data(msg), self->fielddef, value); +static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) { + FieldDescriptor* self = ruby_to_FieldDescriptor(_self); + const upb_msgdef *m; + upb_msgdef *msg = Message_GetMutable(msg_rb, &m); + upb_arena *arena = Arena_get(Message_GetArena(msg_rb)); + upb_msgval msgval; + + if (m != upb_fielddef_containingtype(self->fielddef)) { + rb_raise(cTypeError, "set method called on wrong message type"); + } + + msgval = Convert_RubyToUpb(value, upb_fielddef_name(self->fielddef), + TypeInfo_get(self->fielddef), arena); + upb_msg_set(msg, self->fielddef, msgval, arena); return Qnil; } +static void FieldDescriptor_register(VALUE module) { + VALUE klass = rb_define_class_under( + module, "FieldDescriptor", rb_cObject); + rb_define_alloc_func(klass, FieldDescriptor_alloc); + rb_define_method(klass, "initialize", FieldDescriptor_initialize, 3); + rb_define_method(klass, "name", FieldDescriptor_name, 0); + rb_define_method(klass, "type", FieldDescriptor__type, 0); + rb_define_method(klass, "default", FieldDescriptor_default, 0); + rb_define_method(klass, "label", FieldDescriptor_label, 0); + rb_define_method(klass, "number", FieldDescriptor_number, 0); + rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0); + rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0); + rb_define_method(klass, "has?", FieldDescriptor_has, 1); + rb_define_method(klass, "clear", FieldDescriptor_clear, 1); + rb_define_method(klass, "get", FieldDescriptor_get, 1); + rb_define_method(klass, "set", FieldDescriptor_set, 2); + rb_gc_register_address(&cFieldDescriptor); + cFieldDescriptor = klass; +} + // ----------------------------------------------------------------------------- // OneofDescriptor. // ----------------------------------------------------------------------------- -DEFINE_CLASS(OneofDescriptor, "Google::Protobuf::OneofDescriptor"); +typedef struct { + const upb_oneofdef* oneofdef; + VALUE descriptor_pool; // Owns the upb_oneofdef. +} OneofDescriptor; -void OneofDescriptor_mark(void* _self) { -} +static VALUE cOneofDescriptor = Qnil; -void OneofDescriptor_free(void* _self) { +static void OneofDescriptor_mark(void* _self) { OneofDescriptor* self = _self; - upb_oneofdef_unref(self->oneofdef, &self->oneofdef); - xfree(self); + rb_gc_mark(self->descriptor_pool); +} + +static const rb_data_type_t OneofDescriptor_type = { + "Google::Protobuf::OneofDescriptor", + {OneofDescriptor_mark, RUBY_DEFAULT_FREE, NULL}, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static OneofDescriptor* ruby_to_OneofDescriptor(VALUE val) { + OneofDescriptor* ret; + TypedData_Get_Struct(val, OneofDescriptor, &OneofDescriptor_type, ret); + return ret; } /* @@ -902,77 +1092,44 @@ void OneofDescriptor_free(void* _self) { * Creates a new, empty, oneof descriptor. The oneof may only be modified prior * to being added to a message descriptor which is subsequently added to a pool. */ -VALUE OneofDescriptor_alloc(VALUE klass) { +static VALUE OneofDescriptor_alloc(VALUE klass) { OneofDescriptor* self = ALLOC(OneofDescriptor); - VALUE ret = TypedData_Wrap_Struct(klass, &_OneofDescriptor_type, self); - self->oneofdef = upb_oneofdef_new(&self->oneofdef); + VALUE ret = TypedData_Wrap_Struct(klass, &OneofDescriptor_type, self); + self->oneofdef = NULL; + self->descriptor_pool = Qnil; return ret; } -void OneofDescriptor_register(VALUE module) { - VALUE klass = rb_define_class_under( - module, "OneofDescriptor", rb_cObject); - rb_define_alloc_func(klass, OneofDescriptor_alloc); - rb_define_method(klass, "name", OneofDescriptor_name, 0); - rb_define_method(klass, "name=", OneofDescriptor_name_set, 1); - rb_define_method(klass, "add_field", OneofDescriptor_add_field, 1); - rb_define_method(klass, "each", OneofDescriptor_each, 0); - rb_include_module(klass, rb_mEnumerable); - cOneofDescriptor = klass; - rb_gc_register_address(&cOneofDescriptor); -} - /* * call-seq: - * OneofDescriptor.name => name + * OneofDescriptor.new(c_only_cookie, pool, ptr) => OneofDescriptor * - * Returns the name of this oneof. + * Creates a descriptor wrapper object. May only be called from C. */ -VALUE OneofDescriptor_name(VALUE _self) { - DEFINE_SELF(OneofDescriptor, self, _self); - return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef)); -} +static VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie, + VALUE descriptor_pool, VALUE ptr) { + OneofDescriptor* self = ruby_to_OneofDescriptor(_self); + + if (cookie != c_only_cookie) { + rb_raise(rb_eRuntimeError, + "Descriptor objects may not be created from Ruby."); + } + + self->descriptor_pool = descriptor_pool; + self->oneofdef = (const upb_oneofdef*)NUM2ULL(ptr); -/* - * call-seq: - * OneofDescriptor.name = name - * - * Sets a new name for this oneof. The oneof must not have been added to a - * message descriptor yet. - */ -VALUE OneofDescriptor_name_set(VALUE _self, VALUE value) { - DEFINE_SELF(OneofDescriptor, self, _self); - upb_oneofdef* mut_def = check_oneof_notfrozen(self->oneofdef); - const char* str = get_str(value); - CHECK_UPB(upb_oneofdef_setname(mut_def, str, &status), - "Error setting oneof name"); return Qnil; } /* * call-seq: - * OneofDescriptor.add_field(field) => nil - * - * Adds a field to this oneof. The field may have been added to this oneof in - * the past, or the message to which this oneof belongs (if any), but may not - * have already been added to any other oneof or message. Otherwise, an - * exception is raised. + * OneofDescriptor.name => name * - * All fields added to the oneof via this method will be automatically added to - * the message to which this oneof belongs, if it belongs to one currently, or - * else will be added to any message to which the oneof is later added at the - * time that it is added. + * Returns the name of this oneof. */ -VALUE OneofDescriptor_add_field(VALUE _self, VALUE obj) { - DEFINE_SELF(OneofDescriptor, self, _self); - upb_oneofdef* mut_def = check_oneof_notfrozen(self->oneofdef); - FieldDescriptor* def = ruby_to_FieldDescriptor(obj); - upb_fielddef* mut_field_def = check_field_notfrozen(def->fielddef); - CHECK_UPB( - upb_oneofdef_addfield(mut_def, mut_field_def, NULL, &status), - "Adding field to OneofDescriptor failed"); - add_def_obj(def->fielddef, obj); - return Qnil; +static VALUE OneofDescriptor_name(VALUE _self) { + OneofDescriptor* self = ruby_to_OneofDescriptor(_self); + return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef)); } /* @@ -981,111 +1138,118 @@ VALUE OneofDescriptor_add_field(VALUE _self, VALUE obj) { * * Iterates through fields in this oneof, yielding to the block on each one. */ -VALUE OneofDescriptor_each(VALUE _self, VALUE field) { - DEFINE_SELF(OneofDescriptor, self, _self); +static VALUE OneofDescriptor_each(VALUE _self) { + OneofDescriptor* self = ruby_to_OneofDescriptor(_self); upb_oneof_iter it; for (upb_oneof_begin(&it, self->oneofdef); !upb_oneof_done(&it); upb_oneof_next(&it)) { const upb_fielddef* f = upb_oneof_iter_field(&it); - VALUE obj = get_def_obj(f); + VALUE obj = get_fielddef_obj(self->descriptor_pool, f); rb_yield(obj); } return Qnil; } +static void OneofDescriptor_register(VALUE module) { + VALUE klass = rb_define_class_under( + module, "OneofDescriptor", rb_cObject); + rb_define_alloc_func(klass, OneofDescriptor_alloc); + rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3); + rb_define_method(klass, "name", OneofDescriptor_name, 0); + rb_define_method(klass, "each", OneofDescriptor_each, 0); + rb_include_module(klass, rb_mEnumerable); + rb_gc_register_address(&cOneofDescriptor); + cOneofDescriptor = klass; +} + // ----------------------------------------------------------------------------- // EnumDescriptor. // ----------------------------------------------------------------------------- -DEFINE_CLASS(EnumDescriptor, "Google::Protobuf::EnumDescriptor"); +typedef struct { + const upb_enumdef* enumdef; + VALUE module; // begins as nil + VALUE descriptor_pool; // Owns the upb_enumdef. +} EnumDescriptor; -void EnumDescriptor_mark(void* _self) { +static VALUE cEnumDescriptor = Qnil; + +static void EnumDescriptor_mark(void* _self) { EnumDescriptor* self = _self; rb_gc_mark(self->module); + rb_gc_mark(self->descriptor_pool); } -void EnumDescriptor_free(void* _self) { - EnumDescriptor* self = _self; - upb_enumdef_unref(self->enumdef, &self->enumdef); - xfree(self); +static const rb_data_type_t EnumDescriptor_type = { + "Google::Protobuf::EnumDescriptor", + {EnumDescriptor_mark, RUBY_DEFAULT_FREE, NULL}, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static EnumDescriptor* ruby_to_EnumDescriptor(VALUE val) { + EnumDescriptor* ret; + TypedData_Get_Struct(val, EnumDescriptor, &EnumDescriptor_type, ret); + return ret; } -/* - * call-seq: - * EnumDescriptor.new => enum_descriptor - * - * Creates a new, empty, enum descriptor. Must be added to a pool before the - * enum type can be used. The enum type may only be modified prior to adding to - * a pool. - */ -VALUE EnumDescriptor_alloc(VALUE klass) { +static VALUE EnumDescriptor_alloc(VALUE klass) { EnumDescriptor* self = ALLOC(EnumDescriptor); - VALUE ret = TypedData_Wrap_Struct(klass, &_EnumDescriptor_type, self); - self->enumdef = upb_enumdef_new(&self->enumdef); + VALUE ret = TypedData_Wrap_Struct(klass, &EnumDescriptor_type, self); + self->enumdef = NULL; self->module = Qnil; + self->descriptor_pool = Qnil; return ret; } -void EnumDescriptor_register(VALUE module) { - VALUE klass = rb_define_class_under( - module, "EnumDescriptor", rb_cObject); - rb_define_alloc_func(klass, EnumDescriptor_alloc); - rb_define_method(klass, "name", EnumDescriptor_name, 0); - rb_define_method(klass, "name=", EnumDescriptor_name_set, 1); - rb_define_method(klass, "add_value", EnumDescriptor_add_value, 2); - rb_define_method(klass, "lookup_name", EnumDescriptor_lookup_name, 1); - rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1); - rb_define_method(klass, "each", EnumDescriptor_each, 0); - rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0); - rb_include_module(klass, rb_mEnumerable); - cEnumDescriptor = klass; - rb_gc_register_address(&cEnumDescriptor); +// Exposed to other modules in defs.h. +const upb_enumdef *EnumDescriptor_GetEnumDef(VALUE enum_desc_rb) { + EnumDescriptor *desc = ruby_to_EnumDescriptor(enum_desc_rb); + return desc->enumdef; } /* * call-seq: - * EnumDescriptor.name => name + * EnumDescriptor.new(c_only_cookie, ptr) => EnumDescriptor * - * Returns the name of this enum type. + * Creates a descriptor wrapper object. May only be called from C. */ -VALUE EnumDescriptor_name(VALUE _self) { - DEFINE_SELF(EnumDescriptor, self, _self); - return rb_str_maybe_null(upb_enumdef_fullname(self->enumdef)); +static VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie, + VALUE descriptor_pool, VALUE ptr) { + EnumDescriptor* self = ruby_to_EnumDescriptor(_self); + + if (cookie != c_only_cookie) { + rb_raise(rb_eRuntimeError, + "Descriptor objects may not be created from Ruby."); + } + + self->descriptor_pool = descriptor_pool; + self->enumdef = (const upb_enumdef*)NUM2ULL(ptr); + + return Qnil; } /* * call-seq: - * EnumDescriptor.name = name + * EnumDescriptor.file_descriptor * - * Sets the name of this enum type. Cannot be called if the enum type has - * already been added to a pool. + * Returns the FileDescriptor object this enum belongs to. */ -VALUE EnumDescriptor_name_set(VALUE _self, VALUE str) { - DEFINE_SELF(EnumDescriptor, self, _self); - upb_enumdef* mut_def = check_enum_notfrozen(self->enumdef); - const char* name = get_str(str); - CHECK_UPB(upb_enumdef_setfullname(mut_def, name, &status), - "Error setting EnumDescriptor name"); - return Qnil; +static VALUE EnumDescriptor_file_descriptor(VALUE _self) { + EnumDescriptor* self = ruby_to_EnumDescriptor(_self); + return get_filedef_obj(self->descriptor_pool, + upb_enumdef_file(self->enumdef)); } /* * call-seq: - * EnumDescriptor.add_value(key, value) + * EnumDescriptor.name => name * - * Adds a new key => value mapping to this enum type. Key must be given as a - * Ruby symbol. Cannot be called if the enum type has already been added to a - * pool. Will raise an exception if the key or value is already in use. + * Returns the name of this enum type. */ -VALUE EnumDescriptor_add_value(VALUE _self, VALUE name, VALUE number) { - DEFINE_SELF(EnumDescriptor, self, _self); - upb_enumdef* mut_def = check_enum_notfrozen(self->enumdef); - const char* name_str = rb_id2name(SYM2ID(name)); - int32_t val = NUM2INT(number); - CHECK_UPB(upb_enumdef_addval(mut_def, name_str, val, &status), - "Error adding value to enum"); - return Qnil; +static VALUE EnumDescriptor_name(VALUE _self) { + EnumDescriptor* self = ruby_to_EnumDescriptor(_self); + return rb_str_maybe_null(upb_enumdef_fullname(self->enumdef)); } /* @@ -1095,8 +1259,8 @@ VALUE EnumDescriptor_add_value(VALUE _self, VALUE name, VALUE number) { * Returns the numeric value corresponding to the given key name (as a Ruby * symbol), or nil if none. */ -VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) { - DEFINE_SELF(EnumDescriptor, self, _self); +static VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) { + EnumDescriptor* self = ruby_to_EnumDescriptor(_self); const char* name_str= rb_id2name(SYM2ID(name)); int32_t val = 0; if (upb_enumdef_ntoiz(self->enumdef, name_str, &val)) { @@ -1113,8 +1277,8 @@ VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) { * Returns the key name (as a Ruby symbol) corresponding to the integer value, * or nil if none. */ -VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) { - DEFINE_SELF(EnumDescriptor, self, _self); +static VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) { + EnumDescriptor* self = ruby_to_EnumDescriptor(_self); int32_t val = NUM2INT(number); const char* name = upb_enumdef_iton(self->enumdef, val); if (name != NULL) { @@ -1131,8 +1295,8 @@ VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) { * Iterates over key => value mappings in this enum's definition, yielding to * the block with (key, value) arguments for each one. */ -VALUE EnumDescriptor_each(VALUE _self) { - DEFINE_SELF(EnumDescriptor, self, _self); +static VALUE EnumDescriptor_each(VALUE _self) { + EnumDescriptor* self = ruby_to_EnumDescriptor(_self); upb_enum_iter it; for (upb_enum_begin(&it, self->enumdef); @@ -1150,159 +1314,581 @@ VALUE EnumDescriptor_each(VALUE _self) { * call-seq: * EnumDescriptor.enummodule => module * - * Returns the Ruby module corresponding to this enum type. Cannot be called - * until the enum descriptor has been added to a pool. + * Returns the Ruby module corresponding to this enum type. */ -VALUE EnumDescriptor_enummodule(VALUE _self) { - DEFINE_SELF(EnumDescriptor, self, _self); - if (!upb_def_isfrozen((const upb_def*)self->enumdef)) { - rb_raise(rb_eRuntimeError, - "Cannot fetch enum module from an EnumDescriptor not yet " - "in a pool."); - } +static VALUE EnumDescriptor_enummodule(VALUE _self) { + EnumDescriptor* self = ruby_to_EnumDescriptor(_self); if (self->module == Qnil) { - self->module = build_module_from_enumdesc(self); + self->module = build_module_from_enumdesc(_self); } return self->module; } +static void EnumDescriptor_register(VALUE module) { + VALUE klass = rb_define_class_under( + module, "EnumDescriptor", rb_cObject); + rb_define_alloc_func(klass, EnumDescriptor_alloc); + rb_define_method(klass, "initialize", EnumDescriptor_initialize, 3); + rb_define_method(klass, "name", EnumDescriptor_name, 0); + rb_define_method(klass, "lookup_name", EnumDescriptor_lookup_name, 1); + rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1); + rb_define_method(klass, "each", EnumDescriptor_each, 0); + rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0); + rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0); + rb_include_module(klass, rb_mEnumerable); + rb_gc_register_address(&cEnumDescriptor); + cEnumDescriptor = klass; +} + // ----------------------------------------------------------------------------- -// MessageBuilderContext. +// FileBuilderContext. // ----------------------------------------------------------------------------- -DEFINE_CLASS(MessageBuilderContext, - "Google::Protobuf::Internal::MessageBuilderContext"); +typedef struct { + upb_arena *arena; + google_protobuf_FileDescriptorProto* file_proto; + VALUE descriptor_pool; +} FileBuilderContext; -void MessageBuilderContext_mark(void* _self) { - MessageBuilderContext* self = _self; - rb_gc_mark(self->descriptor); - rb_gc_mark(self->builder); +static VALUE cFileBuilderContext = Qnil; + +static void FileBuilderContext_mark(void* _self) { + FileBuilderContext* self = _self; + rb_gc_mark(self->descriptor_pool); } -void MessageBuilderContext_free(void* _self) { - MessageBuilderContext* self = _self; +static void FileBuilderContext_free(void* _self) { + FileBuilderContext* self = _self; + upb_arena_free(self->arena); xfree(self); } -VALUE MessageBuilderContext_alloc(VALUE klass) { - MessageBuilderContext* self = ALLOC(MessageBuilderContext); - VALUE ret = TypedData_Wrap_Struct( - klass, &_MessageBuilderContext_type, self); - self->descriptor = Qnil; - self->builder = Qnil; +static const rb_data_type_t FileBuilderContext_type = { + "Google::Protobuf::Internal::FileBuilderContext", + {FileBuilderContext_mark, FileBuilderContext_free, NULL}, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static FileBuilderContext* ruby_to_FileBuilderContext(VALUE val) { + FileBuilderContext* ret; + TypedData_Get_Struct(val, FileBuilderContext, &FileBuilderContext_type, ret); return ret; } -void MessageBuilderContext_register(VALUE module) { - VALUE klass = rb_define_class_under( - module, "MessageBuilderContext", rb_cObject); - rb_define_alloc_func(klass, MessageBuilderContext_alloc); - rb_define_method(klass, "initialize", - MessageBuilderContext_initialize, 2); - rb_define_method(klass, "optional", MessageBuilderContext_optional, -1); - rb_define_method(klass, "required", MessageBuilderContext_required, -1); - rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1); - rb_define_method(klass, "map", MessageBuilderContext_map, -1); - rb_define_method(klass, "oneof", MessageBuilderContext_oneof, 1); - cMessageBuilderContext = klass; - rb_gc_register_address(&cMessageBuilderContext); +static upb_strview FileBuilderContext_strdup2(VALUE _self, const char *str) { + FileBuilderContext* self = ruby_to_FileBuilderContext(_self); + upb_strview ret; + char *data; + + ret.size = strlen(str); + data = upb_malloc(upb_arena_alloc(self->arena), ret.size + 1); + ret.data = data; + memcpy(data, str, ret.size); + /* Null-terminate required by rewrite_enum_defaults() above. */ + data[ret.size] = '\0'; + return ret; +} + +static upb_strview FileBuilderContext_strdup(VALUE _self, VALUE rb_str) { + return FileBuilderContext_strdup2(_self, get_str(rb_str)); +} + +static upb_strview FileBuilderContext_strdup_sym(VALUE _self, VALUE rb_sym) { + Check_Type(rb_sym, T_SYMBOL); + return FileBuilderContext_strdup(_self, rb_id2str(SYM2ID(rb_sym))); +} + +static VALUE FileBuilderContext_alloc(VALUE klass) { + FileBuilderContext* self = ALLOC(FileBuilderContext); + VALUE ret = TypedData_Wrap_Struct(klass, &FileBuilderContext_type, self); + self->arena = upb_arena_new(); + self->file_proto = google_protobuf_FileDescriptorProto_new(self->arena); + self->descriptor_pool = Qnil; + return ret; } /* * call-seq: - * MessageBuilderContext.new(desc, builder) => context + * FileBuilderContext.new(descriptor_pool) => context * - * Create a new message builder context around the given message descriptor and + * Create a new file builder context for the given file descriptor and * builder context. This class is intended to serve as a DSL context to be used * with #instance_eval. */ -VALUE MessageBuilderContext_initialize(VALUE _self, - VALUE msgdef, - VALUE builder) { - DEFINE_SELF(MessageBuilderContext, self, _self); - self->descriptor = msgdef; - self->builder = builder; - return Qnil; -} +static VALUE FileBuilderContext_initialize(VALUE _self, VALUE descriptor_pool, + VALUE name, VALUE options) { + FileBuilderContext* self = ruby_to_FileBuilderContext(_self); + self->descriptor_pool = descriptor_pool; -static VALUE msgdef_add_field(VALUE msgdef, - const char* label, VALUE name, - VALUE type, VALUE number, - VALUE type_class) { - VALUE fielddef = rb_class_new_instance(0, NULL, cFieldDescriptor); - VALUE name_str = rb_str_new2(rb_id2name(SYM2ID(name))); + google_protobuf_FileDescriptorProto_set_name( + self->file_proto, FileBuilderContext_strdup(_self, name)); - rb_funcall(fielddef, rb_intern("label="), 1, ID2SYM(rb_intern(label))); - rb_funcall(fielddef, rb_intern("name="), 1, name_str); - rb_funcall(fielddef, rb_intern("type="), 1, type); - rb_funcall(fielddef, rb_intern("number="), 1, number); + // Default syntax for Ruby is proto3. + google_protobuf_FileDescriptorProto_set_syntax( + self->file_proto, + FileBuilderContext_strdup(_self, rb_str_new2("proto3"))); - if (type_class != Qnil) { - if (TYPE(type_class) != T_STRING) { - rb_raise(rb_eArgError, "Expected string for type class"); - } - // Make it an absolute type name by prepending a dot. - type_class = rb_str_append(rb_str_new2("."), type_class); - rb_funcall(fielddef, rb_intern("submsg_name="), 1, type_class); - } + if (options != Qnil) { + VALUE syntax; - rb_funcall(msgdef, rb_intern("add_field"), 1, fielddef); - return fielddef; -} + Check_Type(options, T_HASH); + syntax = rb_hash_lookup2(options, ID2SYM(rb_intern("syntax")), Qnil); -/* - * call-seq: - * MessageBuilderContext.optional(name, type, number, type_class = nil) - * - * Defines a new optional field on this message type with the given type, tag - * number, and type class (for message and enum fields). The type must be a Ruby - * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a - * string, if present (as accepted by FieldDescriptor#submsg_name=). - */ -VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) { - DEFINE_SELF(MessageBuilderContext, self, _self); - VALUE name, type, number, type_class; + if (syntax != Qnil) { + VALUE syntax_str; - if (argc < 3) { - rb_raise(rb_eArgError, "Expected at least 3 arguments."); + Check_Type(syntax, T_SYMBOL); + syntax_str = rb_id2str(SYM2ID(syntax)); + google_protobuf_FileDescriptorProto_set_syntax( + self->file_proto, FileBuilderContext_strdup(_self, syntax_str)); + } } - name = argv[0]; - type = argv[1]; - number = argv[2]; - type_class = (argc > 3) ? argv[3] : Qnil; - return msgdef_add_field(self->descriptor, "optional", - name, type, number, type_class); + return Qnil; } +static void MessageBuilderContext_add_synthetic_oneofs(VALUE _self); + /* * call-seq: - * MessageBuilderContext.required(name, type, number, type_class = nil) + * FileBuilderContext.add_message(name, &block) * - * Defines a new required field on this message type with the given type, tag - * number, and type class (for message and enum fields). The type must be a Ruby - * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a - * string, if present (as accepted by FieldDescriptor#submsg_name=). + * Creates a new, empty descriptor with the given name, and invokes the block in + * the context of a MessageBuilderContext on that descriptor. The block can then + * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated + * methods to define the message fields. * - * Proto3 does not have required fields, but this method exists for - * completeness. Any attempt to add a message type with required fields to a - * pool will currently result in an error. + * This is the recommended, idiomatic way to build message definitions. */ -VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) { - DEFINE_SELF(MessageBuilderContext, self, _self); - VALUE name, type, number, type_class; +static VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) { + VALUE args[2] = { _self, name }; + VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext); + VALUE block = rb_block_proc(); + rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block); + MessageBuilderContext_add_synthetic_oneofs(ctx); + return Qnil; +} - if (argc < 3) { - rb_raise(rb_eArgError, "Expected at least 3 arguments."); +/* We have to do some relatively complicated logic here for backward + * compatibility. + * + * In descriptor.proto, messages are nested inside other messages if that is + * what the original .proto file looks like. For example, suppose we have this + * foo.proto: + * + * package foo; + * message Bar { + * message Baz {} + * } + * + * The descriptor for this must look like this: + * + * file { + * name: "test.proto" + * package: "foo" + * message_type { + * name: "Bar" + * nested_type { + * name: "Baz" + * } + * } + * } + * + * However, the Ruby generated code has always generated messages in a flat, + * non-nested way: + * + * Google::Protobuf::DescriptorPool.generated_pool.build do + * add_message "foo.Bar" do + * end + * add_message "foo.Bar.Baz" do + * end + * end + * + * Here we need to do a translation where we turn this generated code into the + * above descriptor. We need to infer that "foo" is the package name, and not + * a message itself. + * + * We delegate to Ruby to compute the transformation, for more concice and + * readable code than we can do in C */ +static void rewrite_names(VALUE _file_builder, + google_protobuf_FileDescriptorProto* file_proto) { + FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder); + upb_arena *arena = file_builder->arena; + // Build params (package, msg_names, enum_names). + VALUE package = Qnil; + VALUE msg_names = rb_ary_new(); + VALUE enum_names = rb_ary_new(); + size_t msg_count, enum_count, i; + VALUE new_package, nesting, msg_ents, enum_ents; + google_protobuf_DescriptorProto** msgs; + google_protobuf_EnumDescriptorProto** enums; + + if (google_protobuf_FileDescriptorProto_has_package(file_proto)) { + upb_strview package_str = + google_protobuf_FileDescriptorProto_package(file_proto); + package = rb_str_new(package_str.data, package_str.size); } - name = argv[0]; - type = argv[1]; - number = argv[2]; - type_class = (argc > 3) ? argv[3] : Qnil; - return msgdef_add_field(self->descriptor, "required", - name, type, number, type_class); -} + msgs = google_protobuf_FileDescriptorProto_mutable_message_type(file_proto, + &msg_count); + for (i = 0; i < msg_count; i++) { + upb_strview name = google_protobuf_DescriptorProto_name(msgs[i]); + rb_ary_push(msg_names, rb_str_new(name.data, name.size)); + } + + enums = google_protobuf_FileDescriptorProto_mutable_enum_type(file_proto, + &enum_count); + for (i = 0; i < enum_count; i++) { + upb_strview name = google_protobuf_EnumDescriptorProto_name(enums[i]); + rb_ary_push(enum_names, rb_str_new(name.data, name.size)); + } + + { + // Call Ruby code to calculate package name and nesting. + VALUE args[3] = { package, msg_names, enum_names }; + VALUE internal = rb_eval_string("Google::Protobuf::Internal"); + VALUE ret = rb_funcallv(internal, rb_intern("fixup_descriptor"), 3, args); + + new_package = rb_ary_entry(ret, 0); + nesting = rb_ary_entry(ret, 1); + } + + // Rewrite package and names. + if (new_package != Qnil) { + upb_strview new_package_str = + FileBuilderContext_strdup(_file_builder, new_package); + google_protobuf_FileDescriptorProto_set_package(file_proto, + new_package_str); + } + + for (i = 0; i < msg_count; i++) { + upb_strview name = google_protobuf_DescriptorProto_name(msgs[i]); + remove_path(&name); + google_protobuf_DescriptorProto_set_name(msgs[i], name); + } + + for (i = 0; i < enum_count; i++) { + upb_strview name = google_protobuf_EnumDescriptorProto_name(enums[i]); + remove_path(&name); + google_protobuf_EnumDescriptorProto_set_name(enums[i], name); + } + + // Rewrite nesting. + msg_ents = rb_hash_aref(nesting, ID2SYM(rb_intern("msgs"))); + enum_ents = rb_hash_aref(nesting, ID2SYM(rb_intern("enums"))); + + Check_Type(msg_ents, T_ARRAY); + Check_Type(enum_ents, T_ARRAY); + + for (i = 0; i < (size_t)RARRAY_LEN(msg_ents); i++) { + VALUE msg_ent = rb_ary_entry(msg_ents, i); + VALUE pos = rb_hash_aref(msg_ent, ID2SYM(rb_intern("pos"))); + msgs[i] = msgs[NUM2INT(pos)]; + rewrite_nesting(msg_ent, msgs[i], msgs, enums, arena); + } + + for (i = 0; i < (size_t)RARRAY_LEN(enum_ents); i++) { + VALUE enum_pos = rb_ary_entry(enum_ents, i); + enums[i] = enums[NUM2INT(enum_pos)]; + } + + google_protobuf_FileDescriptorProto_resize_message_type( + file_proto, RARRAY_LEN(msg_ents), arena); + google_protobuf_FileDescriptorProto_resize_enum_type( + file_proto, RARRAY_LEN(enum_ents), arena); +} + +/* + * call-seq: + * FileBuilderContext.add_enum(name, &block) + * + * Creates a new, empty enum descriptor with the given name, and invokes the + * block in the context of an EnumBuilderContext on that descriptor. The block + * can then call EnumBuilderContext#add_value to define the enum values. + * + * This is the recommended, idiomatic way to build enum definitions. + */ +static VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name) { + VALUE args[2] = { _self, name }; + VALUE ctx = rb_class_new_instance(2, args, cEnumBuilderContext); + VALUE block = rb_block_proc(); + rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block); + return Qnil; +} + +static void FileBuilderContext_build(VALUE _self) { + FileBuilderContext* self = ruby_to_FileBuilderContext(_self); + DescriptorPool* pool = ruby_to_DescriptorPool(self->descriptor_pool); + upb_status status; + + rewrite_enum_defaults(pool->symtab, self->file_proto); + rewrite_names(_self, self->file_proto); + + upb_status_clear(&status); + if (!upb_symtab_addfile(pool->symtab, self->file_proto, &status)) { + rb_raise(cTypeError, "Unable to add defs to DescriptorPool: %s", + upb_status_errmsg(&status)); + } +} + +static void FileBuilderContext_register(VALUE module) { + VALUE klass = rb_define_class_under(module, "FileBuilderContext", rb_cObject); + rb_define_alloc_func(klass, FileBuilderContext_alloc); + rb_define_method(klass, "initialize", FileBuilderContext_initialize, 3); + rb_define_method(klass, "add_message", FileBuilderContext_add_message, 1); + rb_define_method(klass, "add_enum", FileBuilderContext_add_enum, 1); + rb_gc_register_address(&cFileBuilderContext); + cFileBuilderContext = klass; +} + +// ----------------------------------------------------------------------------- +// MessageBuilderContext. +// ----------------------------------------------------------------------------- + +typedef struct { + google_protobuf_DescriptorProto* msg_proto; + VALUE file_builder; +} MessageBuilderContext; + +static VALUE cMessageBuilderContext = Qnil; + +static void MessageBuilderContext_mark(void* _self) { + MessageBuilderContext* self = _self; + rb_gc_mark(self->file_builder); +} + +static const rb_data_type_t MessageBuilderContext_type = { + "Google::Protobuf::Internal::MessageBuilderContext", + {MessageBuilderContext_mark, RUBY_DEFAULT_FREE, NULL}, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static MessageBuilderContext* ruby_to_MessageBuilderContext(VALUE val) { + MessageBuilderContext* ret; + TypedData_Get_Struct(val, MessageBuilderContext, &MessageBuilderContext_type, + ret); + return ret; +} + +static VALUE MessageBuilderContext_alloc(VALUE klass) { + MessageBuilderContext* self = ALLOC(MessageBuilderContext); + VALUE ret = TypedData_Wrap_Struct(klass, &MessageBuilderContext_type, self); + self->file_builder = Qnil; + return ret; +} + +/* + * call-seq: + * MessageBuilderContext.new(file_builder, name) => context + * + * Create a new message builder context around the given message descriptor and + * builder context. This class is intended to serve as a DSL context to be used + * with #instance_eval. + */ +static VALUE MessageBuilderContext_initialize(VALUE _self, VALUE _file_builder, + VALUE name) { + MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self); + FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder); + google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto; + + self->file_builder = _file_builder; + self->msg_proto = google_protobuf_FileDescriptorProto_add_message_type( + file_proto, file_builder->arena); + + google_protobuf_DescriptorProto_set_name( + self->msg_proto, FileBuilderContext_strdup(_file_builder, name)); + + return Qnil; +} + +static void msgdef_add_field(VALUE msgbuilder_rb, upb_label_t label, VALUE name, + VALUE type, VALUE number, VALUE type_class, + VALUE options, int oneof_index, + bool proto3_optional) { + MessageBuilderContext* self = ruby_to_MessageBuilderContext(msgbuilder_rb); + FileBuilderContext* file_context = + ruby_to_FileBuilderContext(self->file_builder); + google_protobuf_FieldDescriptorProto* field_proto; + VALUE name_str; + + field_proto = google_protobuf_DescriptorProto_add_field(self->msg_proto, + file_context->arena); + + Check_Type(name, T_SYMBOL); + name_str = rb_id2str(SYM2ID(name)); + + google_protobuf_FieldDescriptorProto_set_name( + field_proto, FileBuilderContext_strdup(self->file_builder, name_str)); + google_protobuf_FieldDescriptorProto_set_number(field_proto, NUM2INT(number)); + google_protobuf_FieldDescriptorProto_set_label(field_proto, (int)label); + google_protobuf_FieldDescriptorProto_set_type( + field_proto, (int)ruby_to_descriptortype(type)); + + if (proto3_optional) { + google_protobuf_FieldDescriptorProto_set_proto3_optional(field_proto, true); + } + + if (type_class != Qnil) { + Check_Type(type_class, T_STRING); + + // Make it an absolute type name by prepending a dot. + type_class = rb_str_append(rb_str_new2("."), type_class); + google_protobuf_FieldDescriptorProto_set_type_name( + field_proto, FileBuilderContext_strdup(self->file_builder, type_class)); + } + + if (options != Qnil) { + Check_Type(options, T_HASH); + + if (rb_funcall(options, rb_intern("key?"), 1, + ID2SYM(rb_intern("default"))) == Qtrue) { + VALUE default_value = + rb_hash_lookup(options, ID2SYM(rb_intern("default"))); + + /* Call #to_s since all defaults are strings in the descriptor. */ + default_value = rb_funcall(default_value, rb_intern("to_s"), 0); + + google_protobuf_FieldDescriptorProto_set_default_value( + field_proto, + FileBuilderContext_strdup(self->file_builder, default_value)); + } + } + + if (oneof_index >= 0) { + google_protobuf_FieldDescriptorProto_set_oneof_index(field_proto, + oneof_index); + } +} + +#if RUBY_API_VERSION_CODE >= 20700 +static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc, + const VALUE* argv, VALUE blockarg) { + (void)blockarg; +#else +static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc, + VALUE* argv) { +#endif + MessageBuilderContext* message_builder = + ruby_to_MessageBuilderContext(_message_builder); + VALUE type_class = rb_ary_entry(types, 2); + FileBuilderContext* file_context = + ruby_to_FileBuilderContext(message_builder->file_builder); + google_protobuf_MessageOptions* options = + google_protobuf_DescriptorProto_mutable_options( + message_builder->msg_proto, file_context->arena); + + google_protobuf_MessageOptions_set_map_entry(options, true); + + // optional key = 1; + rb_funcall(_message_builder, rb_intern("optional"), 3, + ID2SYM(rb_intern("key")), rb_ary_entry(types, 0), INT2NUM(1)); + + // optional value = 2; + if (type_class == Qnil) { + rb_funcall(_message_builder, rb_intern("optional"), 3, + ID2SYM(rb_intern("value")), rb_ary_entry(types, 1), INT2NUM(2)); + } else { + rb_funcall(_message_builder, rb_intern("optional"), 4, + ID2SYM(rb_intern("value")), rb_ary_entry(types, 1), INT2NUM(2), + type_class); + } + + return Qnil; +} + +/* + * call-seq: + * MessageBuilderContext.optional(name, type, number, type_class = nil, + * options = nil) + * + * Defines a new optional field on this message type with the given type, tag + * number, and type class (for message and enum fields). The type must be a Ruby + * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a + * string, if present (as accepted by FieldDescriptor#submsg_name=). + */ +VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) { + VALUE name, type, number; + VALUE type_class, options = Qnil; + + rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options); + + // Allow passing (name, type, number, options) or + // (name, type, number, type_class, options) + if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) { + options = type_class; + type_class = Qnil; + } + + msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class, + options, -1, false); + + return Qnil; +} + +/* + * call-seq: + * MessageBuilderContext.proto3_optional(name, type, number, + * type_class = nil, options = nil) + * + * Defines a true proto3 optional field (that tracks presence) on this message + * type with the given type, tag number, and type class (for message and enum + * fields). The type must be a Ruby symbol (as accepted by + * FieldDescriptor#type=) and the type_class must be a string, if present (as + * accepted by FieldDescriptor#submsg_name=). + */ +static VALUE MessageBuilderContext_proto3_optional(int argc, VALUE* argv, + VALUE _self) { + VALUE name, type, number; + VALUE type_class, options = Qnil; + + rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options); + + // Allow passing (name, type, number, options) or + // (name, type, number, type_class, options) + if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) { + options = type_class; + type_class = Qnil; + } + + msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class, + options, -1, true); + + return Qnil; +} + +/* + * call-seq: + * MessageBuilderContext.required(name, type, number, type_class = nil, + * options = nil) + * + * Defines a new required field on this message type with the given type, tag + * number, and type class (for message and enum fields). The type must be a Ruby + * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a + * string, if present (as accepted by FieldDescriptor#submsg_name=). + * + * Proto3 does not have required fields, but this method exists for + * completeness. Any attempt to add a message type with required fields to a + * pool will currently result in an error. + */ +static VALUE MessageBuilderContext_required(int argc, VALUE* argv, + VALUE _self) { + VALUE name, type, number; + VALUE type_class, options = Qnil; + + rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options); + + // Allow passing (name, type, number, options) or + // (name, type, number, type_class, options) + if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) { + options = type_class; + type_class = Qnil; + } + + msgdef_add_field(_self, UPB_LABEL_REQUIRED, name, type, number, type_class, + options, -1, false); + + return Qnil; +} /* * call-seq: @@ -1313,8 +1899,8 @@ VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) { * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a * string, if present (as accepted by FieldDescriptor#submsg_name=). */ -VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) { - DEFINE_SELF(MessageBuilderContext, self, _self); +static VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, + VALUE _self) { VALUE name, type, number, type_class; if (argc < 3) { @@ -1325,8 +1911,10 @@ VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) { number = argv[2]; type_class = (argc > 3) ? argv[3] : Qnil; - return msgdef_add_field(self->descriptor, "repeated", - name, type, number, type_class); + msgdef_add_field(_self, UPB_LABEL_REPEATED, name, type, number, type_class, + Qnil, -1, false); + + return Qnil; } /* @@ -1341,10 +1929,12 @@ VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) { * type_class must be a string, if present (as accepted by * FieldDescriptor#submsg_name=). */ -VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) { - DEFINE_SELF(MessageBuilderContext, self, _self); +static VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) { + MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self); VALUE name, key_type, value_type, number, type_class; - VALUE mapentry_desc, mapentry_desc_name; + VALUE mapentry_desc_name; + FileBuilderContext* file_builder; + upb_strview msg_name; if (argc < 4) { rb_raise(rb_eArgError, "Expected at least 4 arguments."); @@ -1367,69 +1957,36 @@ VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) { "type."); } + file_builder = ruby_to_FileBuilderContext(self->file_builder); + // Create a new message descriptor for the map entry message, and create a // repeated submessage field here with that type. - mapentry_desc = rb_class_new_instance(0, NULL, cDescriptor); - mapentry_desc_name = rb_funcall(self->descriptor, rb_intern("name"), 0); + msg_name = google_protobuf_DescriptorProto_name(self->msg_proto); + mapentry_desc_name = rb_str_new(msg_name.data, msg_name.size); mapentry_desc_name = rb_str_cat2(mapentry_desc_name, "_MapEntry_"); - mapentry_desc_name = rb_str_cat2(mapentry_desc_name, - rb_id2name(SYM2ID(name))); - Descriptor_name_set(mapentry_desc, mapentry_desc_name); - - { - // The 'mapentry' attribute has no Ruby setter because we do not want the - // user attempting to DIY the setup below; we want to ensure that the fields - // are correct. So we reach into the msgdef here to set the bit manually. - Descriptor* mapentry_desc_self = ruby_to_Descriptor(mapentry_desc); - upb_msgdef_setmapentry((upb_msgdef*)mapentry_desc_self->msgdef, true); - } + mapentry_desc_name = + rb_str_cat2(mapentry_desc_name, rb_id2name(SYM2ID(name))); { - // optional key = 1; - VALUE key_field = rb_class_new_instance(0, NULL, cFieldDescriptor); - FieldDescriptor_name_set(key_field, rb_str_new2("key")); - FieldDescriptor_label_set(key_field, ID2SYM(rb_intern("optional"))); - FieldDescriptor_number_set(key_field, INT2NUM(1)); - FieldDescriptor_type_set(key_field, key_type); - Descriptor_add_field(mapentry_desc, key_field); + // message _MapEntry_ { /* ... */ } + VALUE args[1] = {mapentry_desc_name}; + VALUE types = rb_ary_new3(3, key_type, value_type, type_class); + rb_block_call(self->file_builder, rb_intern("add_message"), 1, args, + make_mapentry, types); } - { - // optional value = 2; - VALUE value_field = rb_class_new_instance(0, NULL, cFieldDescriptor); - FieldDescriptor_name_set(value_field, rb_str_new2("value")); - FieldDescriptor_label_set(value_field, ID2SYM(rb_intern("optional"))); - FieldDescriptor_number_set(value_field, INT2NUM(2)); - FieldDescriptor_type_set(value_field, value_type); - if (type_class != Qnil) { - VALUE submsg_name = rb_str_new2("."); // prepend '.' to make absolute. - submsg_name = rb_str_append(submsg_name, type_class); - FieldDescriptor_submsg_name_set(value_field, submsg_name); - } - Descriptor_add_field(mapentry_desc, value_field); + // If this file is in a package, we need to qualify the map entry type. + if (google_protobuf_FileDescriptorProto_has_package(file_builder->file_proto)) { + upb_strview package_view = + google_protobuf_FileDescriptorProto_package(file_builder->file_proto); + VALUE package = rb_str_new(package_view.data, package_view.size); + package = rb_str_cat2(package, "."); + mapentry_desc_name = rb_str_concat(package, mapentry_desc_name); } - { - // Add the map-entry message type to the current builder, and use the type - // to create the map field itself. - Builder* builder_self = ruby_to_Builder(self->builder); - rb_ary_push(builder_self->pending_list, mapentry_desc); - } - - { - VALUE map_field = rb_class_new_instance(0, NULL, cFieldDescriptor); - VALUE name_str = rb_str_new2(rb_id2name(SYM2ID(name))); - VALUE submsg_name; - - FieldDescriptor_name_set(map_field, name_str); - FieldDescriptor_number_set(map_field, number); - FieldDescriptor_label_set(map_field, ID2SYM(rb_intern("repeated"))); - FieldDescriptor_type_set(map_field, ID2SYM(rb_intern("message"))); - submsg_name = rb_str_new2("."); // prepend '.' to make name absolute. - submsg_name = rb_str_append(submsg_name, mapentry_desc_name); - FieldDescriptor_submsg_name_set(map_field, submsg_name); - Descriptor_add_field(self->descriptor, map_field); - } + // repeated MapEntry = ; + rb_funcall(_self, rb_intern("repeated"), 4, name, + ID2SYM(rb_intern("message")), number, mapentry_desc_name); return Qnil; } @@ -1445,152 +2002,242 @@ VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) { * * This is the recommended, idiomatic way to build oneof definitions. */ -VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) { - DEFINE_SELF(MessageBuilderContext, self, _self); - VALUE oneofdef = rb_class_new_instance(0, NULL, cOneofDescriptor); - VALUE args[2] = { oneofdef, self->builder }; - VALUE ctx = rb_class_new_instance(2, args, cOneofBuilderContext); - VALUE block = rb_block_proc(); - VALUE name_str = rb_str_new2(rb_id2name(SYM2ID(name))); - rb_funcall(oneofdef, rb_intern("name="), 1, name_str); - rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block); - Descriptor_add_oneof(self->descriptor, oneofdef); +static VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) { + MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self); + size_t oneof_count; + FileBuilderContext* file_context = + ruby_to_FileBuilderContext(self->file_builder); + google_protobuf_OneofDescriptorProto* oneof_proto; + + // Existing oneof_count becomes oneof_index. + google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count); + + // Create oneof_proto and set its name. + oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl( + self->msg_proto, file_context->arena); + google_protobuf_OneofDescriptorProto_set_name( + oneof_proto, FileBuilderContext_strdup_sym(self->file_builder, name)); + + // Evaluate the block with the builder as argument. + { + VALUE args[2] = { INT2NUM(oneof_count), _self }; + VALUE ctx = rb_class_new_instance(2, args, cOneofBuilderContext); + VALUE block = rb_block_proc(); + rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block); + } return Qnil; } +static void MessageBuilderContext_add_synthetic_oneofs(VALUE _self) { + MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self); + FileBuilderContext* file_context = + ruby_to_FileBuilderContext(self->file_builder); + size_t field_count, oneof_count; + google_protobuf_FieldDescriptorProto** fields = + google_protobuf_DescriptorProto_mutable_field(self->msg_proto, &field_count); + const google_protobuf_OneofDescriptorProto*const* oneofs = + google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count); + VALUE names = rb_hash_new(); + VALUE underscore = rb_str_new2("_"); + size_t i; + + // We have to build a set of all names, to ensure that synthetic oneofs are + // not creating conflicts. + for (i = 0; i < field_count; i++) { + upb_strview name = google_protobuf_FieldDescriptorProto_name(fields[i]); + rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue); + } + for (i = 0; i < oneof_count; i++) { + upb_strview name = google_protobuf_OneofDescriptorProto_name(oneofs[i]); + rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue); + } + + for (i = 0; i < field_count; i++) { + google_protobuf_OneofDescriptorProto* oneof_proto; + VALUE oneof_name; + upb_strview field_name; + + if (!google_protobuf_FieldDescriptorProto_proto3_optional(fields[i])) { + continue; + } + + // Prepend '_' until we are no longer conflicting. + field_name = google_protobuf_FieldDescriptorProto_name(fields[i]); + oneof_name = rb_str_new(field_name.data, field_name.size); + while (rb_hash_lookup(names, oneof_name) != Qnil) { + oneof_name = rb_str_plus(underscore, oneof_name); + } + + rb_hash_aset(names, oneof_name, Qtrue); + google_protobuf_FieldDescriptorProto_set_oneof_index(fields[i], + oneof_count++); + oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl( + self->msg_proto, file_context->arena); + google_protobuf_OneofDescriptorProto_set_name( + oneof_proto, FileBuilderContext_strdup(self->file_builder, oneof_name)); + } +} + +static void MessageBuilderContext_register(VALUE module) { + VALUE klass = rb_define_class_under( + module, "MessageBuilderContext", rb_cObject); + rb_define_alloc_func(klass, MessageBuilderContext_alloc); + rb_define_method(klass, "initialize", + MessageBuilderContext_initialize, 2); + rb_define_method(klass, "optional", MessageBuilderContext_optional, -1); + rb_define_method(klass, "proto3_optional", MessageBuilderContext_proto3_optional, -1); + rb_define_method(klass, "required", MessageBuilderContext_required, -1); + rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1); + rb_define_method(klass, "map", MessageBuilderContext_map, -1); + rb_define_method(klass, "oneof", MessageBuilderContext_oneof, 1); + rb_gc_register_address(&cMessageBuilderContext); + cMessageBuilderContext = klass; +} + // ----------------------------------------------------------------------------- // OneofBuilderContext. // ----------------------------------------------------------------------------- -DEFINE_CLASS(OneofBuilderContext, - "Google::Protobuf::Internal::OneofBuilderContext"); +typedef struct { + int oneof_index; + VALUE message_builder; +} OneofBuilderContext; + +static VALUE cOneofBuilderContext = Qnil; void OneofBuilderContext_mark(void* _self) { OneofBuilderContext* self = _self; - rb_gc_mark(self->descriptor); - rb_gc_mark(self->builder); + rb_gc_mark(self->message_builder); } -void OneofBuilderContext_free(void* _self) { - OneofBuilderContext* self = _self; - xfree(self); -} +static const rb_data_type_t OneofBuilderContext_type = { + "Google::Protobuf::Internal::OneofBuilderContext", + {OneofBuilderContext_mark, RUBY_DEFAULT_FREE, NULL}, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; -VALUE OneofBuilderContext_alloc(VALUE klass) { - OneofBuilderContext* self = ALLOC(OneofBuilderContext); - VALUE ret = TypedData_Wrap_Struct( - klass, &_OneofBuilderContext_type, self); - self->descriptor = Qnil; - self->builder = Qnil; +static OneofBuilderContext* ruby_to_OneofBuilderContext(VALUE val) { + OneofBuilderContext* ret; + TypedData_Get_Struct(val, OneofBuilderContext, &OneofBuilderContext_type, + ret); return ret; } -void OneofBuilderContext_register(VALUE module) { - VALUE klass = rb_define_class_under( - module, "OneofBuilderContext", rb_cObject); - rb_define_alloc_func(klass, OneofBuilderContext_alloc); - rb_define_method(klass, "initialize", - OneofBuilderContext_initialize, 2); - rb_define_method(klass, "optional", OneofBuilderContext_optional, -1); - cOneofBuilderContext = klass; - rb_gc_register_address(&cOneofBuilderContext); +static VALUE OneofBuilderContext_alloc(VALUE klass) { + OneofBuilderContext* self = ALLOC(OneofBuilderContext); + VALUE ret = TypedData_Wrap_Struct(klass, &OneofBuilderContext_type, self); + self->oneof_index = 0; + self->message_builder = Qnil; + return ret; } /* * call-seq: - * OneofBuilderContext.new(desc, builder) => context + * OneofBuilderContext.new(oneof_index, message_builder) => context * * Create a new oneof builder context around the given oneof descriptor and * builder context. This class is intended to serve as a DSL context to be used * with #instance_eval. */ -VALUE OneofBuilderContext_initialize(VALUE _self, - VALUE oneofdef, - VALUE builder) { - DEFINE_SELF(OneofBuilderContext, self, _self); - self->descriptor = oneofdef; - self->builder = builder; +static VALUE OneofBuilderContext_initialize(VALUE _self, VALUE oneof_index, + VALUE message_builder) { + OneofBuilderContext* self = ruby_to_OneofBuilderContext(_self); + self->oneof_index = NUM2INT(oneof_index); + self->message_builder = message_builder; return Qnil; } /* * call-seq: - * OneofBuilderContext.optional(name, type, number, type_class = nil) + * OneofBuilderContext.optional(name, type, number, type_class = nil, + * default_value = nil) * * Defines a new optional field in this oneof with the given type, tag number, * and type class (for message and enum fields). The type must be a Ruby symbol * (as accepted by FieldDescriptor#type=) and the type_class must be a string, * if present (as accepted by FieldDescriptor#submsg_name=). */ -VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) { - DEFINE_SELF(OneofBuilderContext, self, _self); - VALUE name, type, number, type_class; +static VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) { + OneofBuilderContext* self = ruby_to_OneofBuilderContext(_self); + VALUE name, type, number; + VALUE type_class, options = Qnil; - if (argc < 3) { - rb_raise(rb_eArgError, "Expected at least 3 arguments."); - } - name = argv[0]; - type = argv[1]; - number = argv[2]; - type_class = (argc > 3) ? argv[3] : Qnil; + rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options); + + msgdef_add_field(self->message_builder, UPB_LABEL_OPTIONAL, name, type, + number, type_class, options, self->oneof_index, false); + + return Qnil; +} - return msgdef_add_field(self->descriptor, "optional", - name, type, number, type_class); +static void OneofBuilderContext_register(VALUE module) { + VALUE klass = rb_define_class_under( + module, "OneofBuilderContext", rb_cObject); + rb_define_alloc_func(klass, OneofBuilderContext_alloc); + rb_define_method(klass, "initialize", + OneofBuilderContext_initialize, 2); + rb_define_method(klass, "optional", OneofBuilderContext_optional, -1); + rb_gc_register_address(&cOneofBuilderContext); + cOneofBuilderContext = klass; } // ----------------------------------------------------------------------------- // EnumBuilderContext. // ----------------------------------------------------------------------------- -DEFINE_CLASS(EnumBuilderContext, - "Google::Protobuf::Internal::EnumBuilderContext"); +typedef struct { + google_protobuf_EnumDescriptorProto* enum_proto; + VALUE file_builder; +} EnumBuilderContext; + +static VALUE cEnumBuilderContext = Qnil; void EnumBuilderContext_mark(void* _self) { EnumBuilderContext* self = _self; - rb_gc_mark(self->enumdesc); + rb_gc_mark(self->file_builder); } -void EnumBuilderContext_free(void* _self) { - EnumBuilderContext* self = _self; - xfree(self); -} +static const rb_data_type_t EnumBuilderContext_type = { + "Google::Protobuf::Internal::EnumBuilderContext", + {EnumBuilderContext_mark, RUBY_DEFAULT_FREE, NULL}, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; -VALUE EnumBuilderContext_alloc(VALUE klass) { - EnumBuilderContext* self = ALLOC(EnumBuilderContext); - VALUE ret = TypedData_Wrap_Struct( - klass, &_EnumBuilderContext_type, self); - self->enumdesc = Qnil; +static EnumBuilderContext* ruby_to_EnumBuilderContext(VALUE val) { + EnumBuilderContext* ret; + TypedData_Get_Struct(val, EnumBuilderContext, &EnumBuilderContext_type, ret); return ret; } -void EnumBuilderContext_register(VALUE module) { - VALUE klass = rb_define_class_under( - module, "EnumBuilderContext", rb_cObject); - rb_define_alloc_func(klass, EnumBuilderContext_alloc); - rb_define_method(klass, "initialize", - EnumBuilderContext_initialize, 1); - rb_define_method(klass, "value", EnumBuilderContext_value, 2); - cEnumBuilderContext = klass; - rb_gc_register_address(&cEnumBuilderContext); +static VALUE EnumBuilderContext_alloc(VALUE klass) { + EnumBuilderContext* self = ALLOC(EnumBuilderContext); + VALUE ret = TypedData_Wrap_Struct(klass, &EnumBuilderContext_type, self); + self->enum_proto = NULL; + self->file_builder = Qnil; + return ret; } /* * call-seq: - * EnumBuilderContext.new(enumdesc) => context + * EnumBuilderContext.new(file_builder) => context * * Create a new builder context around the given enum descriptor. This class is * intended to serve as a DSL context to be used with #instance_eval. */ -VALUE EnumBuilderContext_initialize(VALUE _self, VALUE enumdef) { - DEFINE_SELF(EnumBuilderContext, self, _self); - self->enumdesc = enumdef; - return Qnil; -} +static VALUE EnumBuilderContext_initialize(VALUE _self, VALUE _file_builder, + VALUE name) { + EnumBuilderContext* self = ruby_to_EnumBuilderContext(_self); + FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder); + google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto; + + self->file_builder = _file_builder; + self->enum_proto = google_protobuf_FileDescriptorProto_add_enum_type( + file_proto, file_builder->arena); + + google_protobuf_EnumDescriptorProto_set_name( + self->enum_proto, FileBuilderContext_strdup(_file_builder, name)); -static VALUE enumdef_add_value(VALUE enumdef, - VALUE name, VALUE number) { - rb_funcall(enumdef, rb_intern("add_value"), 2, name, number); return Qnil; } @@ -1601,75 +2248,145 @@ static VALUE enumdef_add_value(VALUE enumdef, * Adds the given name => number mapping to the enum type. Name must be a Ruby * symbol. */ -VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) { - DEFINE_SELF(EnumBuilderContext, self, _self); - return enumdef_add_value(self->enumdesc, name, number); +static VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) { + EnumBuilderContext* self = ruby_to_EnumBuilderContext(_self); + FileBuilderContext* file_builder = + ruby_to_FileBuilderContext(self->file_builder); + google_protobuf_EnumValueDescriptorProto* enum_value; + + enum_value = google_protobuf_EnumDescriptorProto_add_value( + self->enum_proto, file_builder->arena); + + google_protobuf_EnumValueDescriptorProto_set_name( + enum_value, FileBuilderContext_strdup_sym(self->file_builder, name)); + google_protobuf_EnumValueDescriptorProto_set_number(enum_value, + NUM2INT(number)); + + return Qnil; +} + +static void EnumBuilderContext_register(VALUE module) { + VALUE klass = rb_define_class_under( + module, "EnumBuilderContext", rb_cObject); + rb_define_alloc_func(klass, EnumBuilderContext_alloc); + rb_define_method(klass, "initialize", EnumBuilderContext_initialize, 2); + rb_define_method(klass, "value", EnumBuilderContext_value, 2); + rb_gc_register_address(&cEnumBuilderContext); + cEnumBuilderContext = klass; } // ----------------------------------------------------------------------------- // Builder. // ----------------------------------------------------------------------------- -DEFINE_CLASS(Builder, "Google::Protobuf::Internal::Builder"); +typedef struct { + VALUE descriptor_pool; + VALUE default_file_builder; +} Builder; -void Builder_mark(void* _self) { +static VALUE cBuilder = Qnil; + +static void Builder_mark(void* _self) { Builder* self = _self; - rb_gc_mark(self->pending_list); + rb_gc_mark(self->descriptor_pool); + rb_gc_mark(self->default_file_builder); } -void Builder_free(void* _self) { - Builder* self = _self; - xfree(self->defs); - xfree(self); +static const rb_data_type_t Builder_type = { + "Google::Protobuf::Internal::Builder", + {Builder_mark, RUBY_DEFAULT_FREE, NULL}, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static Builder* ruby_to_Builder(VALUE val) { + Builder* ret; + TypedData_Get_Struct(val, Builder, &Builder_type, ret); + return ret; +} + +static VALUE Builder_alloc(VALUE klass) { + Builder* self = ALLOC(Builder); + VALUE ret = TypedData_Wrap_Struct(klass, &Builder_type, self); + self->descriptor_pool = Qnil; + self->default_file_builder = Qnil; + return ret; } /* * call-seq: - * Builder.new => builder + * Builder.new(descriptor_pool) => builder * * Creates a new Builder. A Builder can accumulate a set of new message and enum * descriptors and atomically register them into a pool in a way that allows for * (co)recursive type references. */ -VALUE Builder_alloc(VALUE klass) { - Builder* self = ALLOC(Builder); - VALUE ret = TypedData_Wrap_Struct( - klass, &_Builder_type, self); - self->pending_list = rb_ary_new(); - self->defs = NULL; - return ret; +static VALUE Builder_initialize(VALUE _self, VALUE pool) { + Builder* self = ruby_to_Builder(_self); + self->descriptor_pool = pool; + self->default_file_builder = Qnil; // Created lazily if needed. + return Qnil; } -void Builder_register(VALUE module) { - VALUE klass = rb_define_class_under(module, "Builder", rb_cObject); - rb_define_alloc_func(klass, Builder_alloc); - rb_define_method(klass, "add_message", Builder_add_message, 1); - rb_define_method(klass, "add_enum", Builder_add_enum, 1); - rb_define_method(klass, "finalize_to_pool", Builder_finalize_to_pool, 1); - cBuilder = klass; - rb_gc_register_address(&cBuilder); +/* + * call-seq: + * Builder.add_file(name, options = nil, &block) + * + * Creates a new, file descriptor with the given name and options and invokes + * the block in the context of a FileBuilderContext on that descriptor. The + * block can then call FileBuilderContext#add_message or + * FileBuilderContext#add_enum to define new messages or enums, respectively. + * + * This is the recommended, idiomatic way to build file descriptors. + */ +static VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) { + Builder* self = ruby_to_Builder(_self); + VALUE name, options; + VALUE ctx; + VALUE block; + + rb_scan_args(argc, argv, "11", &name, &options); + + { + VALUE args[3] = { self->descriptor_pool, name, options }; + ctx = rb_class_new_instance(3, args, cFileBuilderContext); + } + + block = rb_block_proc(); + rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block); + FileBuilderContext_build(ctx); + + return Qnil; +} + +static VALUE Builder_get_default_file(VALUE _self) { + Builder* self = ruby_to_Builder(_self); + + /* Lazily create only if legacy builder-level methods are called. */ + if (self->default_file_builder == Qnil) { + VALUE name = rb_str_new2("ruby_default_file.proto"); + VALUE args [3] = { self->descriptor_pool, name, rb_hash_new() }; + self->default_file_builder = + rb_class_new_instance(3, args, cFileBuilderContext); + } + + return self->default_file_builder; } /* * call-seq: * Builder.add_message(name, &block) * - * Creates a new, empty descriptor with the given name, and invokes the block in - * the context of a MessageBuilderContext on that descriptor. The block can then - * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated - * methods to define the message fields. + * Old and deprecated way to create a new descriptor. + * See FileBuilderContext.add_message for the recommended way. * - * This is the recommended, idiomatic way to build message definitions. + * Exists for backwards compatibility to allow building descriptor pool for + * files generated by protoc which don't add messages within "add_file" block. + * Descriptors created this way get assigned to a default empty FileDescriptor. */ -VALUE Builder_add_message(VALUE _self, VALUE name) { - DEFINE_SELF(Builder, self, _self); - VALUE msgdef = rb_class_new_instance(0, NULL, cDescriptor); - VALUE args[2] = { msgdef, _self }; - VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext); - VALUE block = rb_block_proc(); - rb_funcall(msgdef, rb_intern("name="), 1, name); - rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block); - rb_ary_push(self->pending_list, msgdef); +static VALUE Builder_add_message(VALUE _self, VALUE name) { + VALUE file_builder = Builder_get_default_file(_self); + rb_funcall_with_block(file_builder, rb_intern("add_message"), 1, &name, + rb_block_proc()); return Qnil; } @@ -1677,87 +2394,166 @@ VALUE Builder_add_message(VALUE _self, VALUE name) { * call-seq: * Builder.add_enum(name, &block) * - * Creates a new, empty enum descriptor with the given name, and invokes the - * block in the context of an EnumBuilderContext on that descriptor. The block - * can then call EnumBuilderContext#add_value to define the enum values. + * Old and deprecated way to create a new enum descriptor. + * See FileBuilderContext.add_enum for the recommended way. * - * This is the recommended, idiomatic way to build enum definitions. + * Exists for backwards compatibility to allow building descriptor pool for + * files generated by protoc which don't add enums within "add_file" block. + * Enum descriptors created this way get assigned to a default empty + * FileDescriptor. */ -VALUE Builder_add_enum(VALUE _self, VALUE name) { - DEFINE_SELF(Builder, self, _self); - VALUE enumdef = rb_class_new_instance(0, NULL, cEnumDescriptor); - VALUE ctx = rb_class_new_instance(1, &enumdef, cEnumBuilderContext); - VALUE block = rb_block_proc(); - rb_funcall(enumdef, rb_intern("name="), 1, name); - rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block); - rb_ary_push(self->pending_list, enumdef); +static VALUE Builder_add_enum(VALUE _self, VALUE name) { + VALUE file_builder = Builder_get_default_file(_self); + rb_funcall_with_block(file_builder, rb_intern("add_enum"), 1, &name, + rb_block_proc()); return Qnil; } -static void validate_msgdef(const upb_msgdef* msgdef) { - // Verify that no required fields exist. proto3 does not support these. - upb_msg_field_iter it; - for (upb_msg_field_begin(&it, msgdef); - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* field = upb_msg_iter_field(&it); - if (upb_fielddef_label(field) == UPB_LABEL_REQUIRED) { - rb_raise(rb_eTypeError, "Required fields are unsupported in proto3."); - } +/* This method is hidden from Ruby, and only called directly from + * DescriptorPool_build(). */ +static VALUE Builder_build(VALUE _self) { + Builder* self = ruby_to_Builder(_self); + + if (self->default_file_builder != Qnil) { + FileBuilderContext_build(self->default_file_builder); + self->default_file_builder = Qnil; } + + return Qnil; } -static void validate_enumdef(const upb_enumdef* enumdef) { - // Verify that an entry exists with integer value 0. (This is the default - // value.) - const char* lookup = upb_enumdef_iton(enumdef, 0); - if (lookup == NULL) { - rb_raise(rb_eTypeError, - "Enum definition does not contain a value for '0'."); +static void Builder_register(VALUE module) { + VALUE klass = rb_define_class_under(module, "Builder", rb_cObject); + rb_define_alloc_func(klass, Builder_alloc); + rb_define_method(klass, "initialize", Builder_initialize, 1); + rb_define_method(klass, "add_file", Builder_add_file, -1); + rb_define_method(klass, "add_message", Builder_add_message, 1); + rb_define_method(klass, "add_enum", Builder_add_enum, 1); + rb_gc_register_address(&cBuilder); + cBuilder = 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); + VALUE def; + + def = rb_hash_aref(descriptor_pool->def_to_descriptor, key); + + if (ptr == NULL) { + return Qnil; } + + if (def == Qnil) { + // Lazily create wrapper object. + VALUE args[3] = { c_only_cookie, _descriptor_pool, key }; + def = rb_class_new_instance(3, args, klass); + rb_hash_aset(descriptor_pool->def_to_descriptor, key, def); + } + + return def; } -/* - * call-seq: - * Builder.finalize_to_pool(pool) - * - * Adds all accumulated message and enum descriptors created in this builder - * context to the given pool. The operation occurs atomically, and all - * descriptors can refer to each other (including in cycles). This is the only - * way to build (co)recursive message definitions. - * - * This method is usually called automatically by DescriptorPool#build after it - * invokes the given user block in the context of the builder. The user should - * not normally need to call this manually because a Builder is not normally - * created manually. - */ -VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb) { - DEFINE_SELF(Builder, self, _self); +static VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def) { + return get_def_obj(descriptor_pool, def, cDescriptor); +} + +static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def) { + return get_def_obj(descriptor_pool, def, cEnumDescriptor); +} + +static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def) { + return get_def_obj(descriptor_pool, def, cFieldDescriptor); +} + +static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def) { + return get_def_obj(descriptor_pool, def, cFileDescriptor); +} + +static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def) { + return get_def_obj(descriptor_pool, def, cOneofDescriptor); +} + +// ----------------------------------------------------------------------------- +// Shared functions +// ----------------------------------------------------------------------------- - DescriptorPool* pool = ruby_to_DescriptorPool(pool_rb); +// Functions exposed to other modules in defs.h. - REALLOC_N(self->defs, upb_def*, RARRAY_LEN(self->pending_list)); +VALUE Descriptor_DefToClass(const upb_msgdef *m) { + const upb_symtab *symtab = upb_filedef_symtab(upb_msgdef_file(m)); + VALUE pool = ObjectCache_Get(symtab); + PBRUBY_ASSERT(pool != Qnil); + VALUE desc_rb = get_msgdef_obj(pool, m); + const Descriptor* desc = ruby_to_Descriptor(desc_rb); + return desc->klass; +} - for (int i = 0; i < RARRAY_LEN(self->pending_list); i++) { - VALUE def_rb = rb_ary_entry(self->pending_list, i); - if (CLASS_OF(def_rb) == cDescriptor) { - self->defs[i] = (upb_def*)ruby_to_Descriptor(def_rb)->msgdef; - validate_msgdef((const upb_msgdef*)self->defs[i]); - } else if (CLASS_OF(def_rb) == cEnumDescriptor) { - self->defs[i] = (upb_def*)ruby_to_EnumDescriptor(def_rb)->enumdef; - validate_enumdef((const upb_enumdef*)self->defs[i]); +const upb_msgdef *Descriptor_GetMsgDef(VALUE desc_rb) { + const Descriptor* desc = ruby_to_Descriptor(desc_rb); + return desc->msgdef; +} + +VALUE TypeInfo_InitArg(int argc, VALUE *argv, int skip_arg) { + if (argc > skip_arg) { + if (argc > 1 + skip_arg) { + rb_raise(rb_eArgError, "Expected a maximum of %d arguments.", skip_arg + 1); } + return argv[skip_arg]; + } else { + return Qnil; } +} + +TypeInfo TypeInfo_FromClass(int argc, VALUE* argv, int skip_arg, + VALUE* type_class, VALUE* init_arg) { + TypeInfo ret = {ruby_to_fieldtype(argv[skip_arg])}; - CHECK_UPB(upb_symtab_add(pool->symtab, (upb_def**)self->defs, - RARRAY_LEN(self->pending_list), NULL, &status), - "Unable to add defs to DescriptorPool"); + if (ret.type == UPB_TYPE_MESSAGE || ret.type == UPB_TYPE_ENUM) { + *init_arg = TypeInfo_InitArg(argc, argv, skip_arg + 2); - for (int i = 0; i < RARRAY_LEN(self->pending_list); i++) { - VALUE def_rb = rb_ary_entry(self->pending_list, i); - add_def_obj(self->defs[i], def_rb); + if (argc < 2 + skip_arg) { + rb_raise(rb_eArgError, "Expected at least %d arguments for message/enum.", + 2 + skip_arg); + } + + VALUE klass = argv[1 + skip_arg]; + VALUE desc = MessageOrEnum_GetDescriptor(klass); + *type_class = klass; + + if (desc == Qnil) { + rb_raise(rb_eArgError, + "Type class has no descriptor. Please pass a " + "class or enum as returned by the DescriptorPool."); + } + + if (ret.type == UPB_TYPE_MESSAGE) { + ret.def.msgdef = ruby_to_Descriptor(desc)->msgdef; + Message_CheckClass(klass); + } else { + PBRUBY_ASSERT(ret.type == UPB_TYPE_ENUM); + ret.def.enumdef = ruby_to_EnumDescriptor(desc)->enumdef; + } + } else { + *init_arg = TypeInfo_InitArg(argc, argv, skip_arg + 1); } - self->pending_list = rb_ary_new(); - return Qnil; + return ret; +} + +void Defs_register(VALUE module) { + DescriptorPool_register(module); + Descriptor_register(module); + FileDescriptor_register(module); + FieldDescriptor_register(module); + OneofDescriptor_register(module); + EnumDescriptor_register(module); + FileBuilderContext_register(module); + MessageBuilderContext_register(module); + OneofBuilderContext_register(module); + EnumBuilderContext_register(module); + Builder_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/defs.h b/ruby/ext/google/protobuf_c/defs.h new file mode 100644 index 0000000000000..97a94bb7b5453 --- /dev/null +++ b/ruby/ext/google/protobuf_c/defs.h @@ -0,0 +1,107 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef RUBY_PROTOBUF_DEFS_H_ +#define RUBY_PROTOBUF_DEFS_H_ + +#include + +#include "protobuf.h" +#include "ruby-upb.h" + +// ----------------------------------------------------------------------------- +// TypeInfo +// ----------------------------------------------------------------------------- + +// This bundles a upb_fieldtype_t and msgdef/enumdef when appropriate. This is +// convenient for functions that need type information but cannot necessarily +// assume a upb_fielddef will be available. +// +// For example, Google::Protobuf::Map and Google::Protobuf::RepeatedField can +// be constructed with type information alone: +// +// # RepeatedField will internally store the type information in a TypeInfo. +// Google::Protobuf::RepeatedField.new(:message, FooMessage) + +typedef struct { + upb_fieldtype_t type; + union { + const upb_msgdef* msgdef; // When type == UPB_TYPE_MESSAGE + const upb_enumdef* enumdef; // When type == UPB_TYPE_ENUM + } def; +} TypeInfo; + +static inline TypeInfo TypeInfo_get(const upb_fielddef *f) { + TypeInfo ret = {upb_fielddef_type(f), {NULL}}; + switch (ret.type) { + case UPB_TYPE_MESSAGE: + ret.def.msgdef = upb_fielddef_msgsubdef(f); + break; + case UPB_TYPE_ENUM: + ret.def.enumdef = upb_fielddef_enumsubdef(f); + break; + default: + break; + } + return ret; +} + +TypeInfo TypeInfo_FromClass(int argc, VALUE* argv, int skip_arg, + VALUE* type_class, VALUE* init_arg); + +static inline TypeInfo TypeInfo_from_type(upb_fieldtype_t type) { + TypeInfo ret = {type}; + assert(type != UPB_TYPE_MESSAGE && type != UPB_TYPE_ENUM); + return ret; +} + +// ----------------------------------------------------------------------------- +// Other utilities +// ----------------------------------------------------------------------------- + +VALUE Descriptor_DefToClass(const upb_msgdef *m); + +// Returns the underlying msgdef, enumdef, or symtab (respectively) for the +// given Descriptor, EnumDescriptor, or DescriptorPool Ruby object. +const upb_enumdef *EnumDescriptor_GetEnumDef(VALUE enum_desc_rb); +const upb_symtab *DescriptorPool_GetSymtab(VALUE desc_pool_rb); +const upb_msgdef *Descriptor_GetMsgDef(VALUE desc_rb); + +// Returns a upb field type for the given Ruby symbol +// (eg. :float => UPB_TYPE_FLOAT). +upb_fieldtype_t ruby_to_fieldtype(VALUE type); + +// The singleton generated pool (a DescriptorPool object). +extern VALUE generated_pool; + +// Call at startup to register all types in this module. +void Defs_register(VALUE module); + +#endif // RUBY_PROTOBUF_DEFS_H_ diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c deleted file mode 100644 index 6ce6d0837e9fc..0000000000000 --- a/ruby/ext/google/protobuf_c/encode_decode.c +++ /dev/null @@ -1,1311 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2014 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "protobuf.h" - -// This function is equivalent to rb_str_cat(), but unlike the real -// rb_str_cat(), it doesn't leak memory in some versions of Ruby. -// For more information, see: -// https://bugs.ruby-lang.org/issues/11328 -VALUE noleak_rb_str_cat(VALUE rb_str, const char *str, long len) { - char *p; - size_t oldlen = RSTRING_LEN(rb_str); - rb_str_modify_expand(rb_str, len); - p = RSTRING_PTR(rb_str); - memcpy(p + oldlen, str, len); - rb_str_set_len(rb_str, oldlen + len); - return rb_str; -} - -// ----------------------------------------------------------------------------- -// Parsing. -// ----------------------------------------------------------------------------- - -#define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs) - -// Creates a handlerdata that simply contains the offset for this field. -static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) { - size_t* hd_ofs = ALLOC(size_t); - *hd_ofs = ofs; - upb_handlers_addcleanup(h, hd_ofs, xfree); - return hd_ofs; -} - -typedef struct { - size_t ofs; - const upb_msgdef *md; -} submsg_handlerdata_t; - -// Creates a handlerdata that contains offset and submessage type information. -static const void *newsubmsghandlerdata(upb_handlers* h, uint32_t ofs, - const upb_fielddef* f) { - submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t); - hd->ofs = ofs; - hd->md = upb_fielddef_msgsubdef(f); - upb_handlers_addcleanup(h, hd, xfree); - return hd; -} - -typedef struct { - size_t ofs; // union data slot - size_t case_ofs; // oneof_case field - uint32_t oneof_case_num; // oneof-case number to place in oneof_case field - const upb_msgdef *md; // msgdef, for oneof submessage handler -} oneof_handlerdata_t; - -static const void *newoneofhandlerdata(upb_handlers *h, - uint32_t ofs, - uint32_t case_ofs, - const upb_fielddef *f) { - oneof_handlerdata_t *hd = ALLOC(oneof_handlerdata_t); - hd->ofs = ofs; - hd->case_ofs = case_ofs; - // We reuse the field tag number as a oneof union discriminant tag. Note that - // we don't expose these numbers to the user, so the only requirement is that - // we have some unique ID for each union case/possibility. The field tag - // numbers are already present and are easy to use so there's no reason to - // create a separate ID space. In addition, using the field tag number here - // lets us easily look up the field in the oneof accessor. - hd->oneof_case_num = upb_fielddef_number(f); - if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) { - hd->md = upb_fielddef_msgsubdef(f); - } else { - hd->md = NULL; - } - upb_handlers_addcleanup(h, hd, xfree); - return hd; -} - -// A handler that starts a repeated field. Gets the Repeated*Field instance for -// this field (such an instance always exists even in an empty message). -static void *startseq_handler(void* closure, const void* hd) { - MessageHeader* msg = closure; - const size_t *ofs = hd; - return (void*)DEREF(msg, *ofs, VALUE); -} - -// Handlers that append primitive values to a repeated field. -#define DEFINE_APPEND_HANDLER(type, ctype) \ - static bool append##type##_handler(void *closure, const void *hd, \ - ctype val) { \ - VALUE ary = (VALUE)closure; \ - RepeatedField_push_native(ary, &val); \ - return true; \ - } - -DEFINE_APPEND_HANDLER(bool, bool) -DEFINE_APPEND_HANDLER(int32, int32_t) -DEFINE_APPEND_HANDLER(uint32, uint32_t) -DEFINE_APPEND_HANDLER(float, float) -DEFINE_APPEND_HANDLER(int64, int64_t) -DEFINE_APPEND_HANDLER(uint64, uint64_t) -DEFINE_APPEND_HANDLER(double, double) - -// Appends a string to a repeated field. -static void* appendstr_handler(void *closure, - const void *hd, - size_t size_hint) { - VALUE ary = (VALUE)closure; - VALUE str = rb_str_new2(""); - rb_enc_associate(str, kRubyStringUtf8Encoding); - RepeatedField_push_native(ary, &str); - return (void*)str; -} - -// Appends a 'bytes' string to a repeated field. -static void* appendbytes_handler(void *closure, - const void *hd, - size_t size_hint) { - VALUE ary = (VALUE)closure; - VALUE str = rb_str_new2(""); - rb_enc_associate(str, kRubyString8bitEncoding); - RepeatedField_push_native(ary, &str); - return (void*)str; -} - -// Sets a non-repeated string field in a message. -static void* str_handler(void *closure, - const void *hd, - size_t size_hint) { - MessageHeader* msg = closure; - const size_t *ofs = hd; - VALUE str = rb_str_new2(""); - rb_enc_associate(str, kRubyStringUtf8Encoding); - DEREF(msg, *ofs, VALUE) = str; - return (void*)str; -} - -// Sets a non-repeated 'bytes' field in a message. -static void* bytes_handler(void *closure, - const void *hd, - size_t size_hint) { - MessageHeader* msg = closure; - const size_t *ofs = hd; - VALUE str = rb_str_new2(""); - rb_enc_associate(str, kRubyString8bitEncoding); - DEREF(msg, *ofs, VALUE) = str; - return (void*)str; -} - -static size_t stringdata_handler(void* closure, const void* hd, - const char* str, size_t len, - const upb_bufhandle* handle) { - VALUE rb_str = (VALUE)closure; - noleak_rb_str_cat(rb_str, str, len); - return len; -} - -static bool stringdata_end_handler(void* closure, const void* hd) { - MessageHeader* msg = closure; - const size_t *ofs = hd; - VALUE rb_str = DEREF(msg, *ofs, VALUE); - rb_obj_freeze(rb_str); - return true; -} - -static bool appendstring_end_handler(void* closure, const void* hd) { - VALUE ary = (VALUE)closure; - int size = RepeatedField_size(ary); - VALUE* last = RepeatedField_index_native(ary, size - 1); - VALUE rb_str = *last; - rb_obj_freeze(rb_str); - return true; -} - -// Appends a submessage to a repeated field (a regular Ruby array for now). -static void *appendsubmsg_handler(void *closure, const void *hd) { - VALUE ary = (VALUE)closure; - const submsg_handlerdata_t *submsgdata = hd; - VALUE subdesc = - get_def_obj((void*)submsgdata->md); - VALUE subklass = Descriptor_msgclass(subdesc); - MessageHeader* submsg; - - VALUE submsg_rb = rb_class_new_instance(0, NULL, subklass); - RepeatedField_push(ary, submsg_rb); - - TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg); - return submsg; -} - -// Sets a non-repeated submessage field in a message. -static void *submsg_handler(void *closure, const void *hd) { - MessageHeader* msg = closure; - const submsg_handlerdata_t* submsgdata = hd; - VALUE subdesc = - get_def_obj((void*)submsgdata->md); - VALUE subklass = Descriptor_msgclass(subdesc); - VALUE submsg_rb; - MessageHeader* submsg; - - if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) { - DEREF(msg, submsgdata->ofs, VALUE) = - rb_class_new_instance(0, NULL, subklass); - } - - submsg_rb = DEREF(msg, submsgdata->ofs, VALUE); - TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg); - return submsg; -} - -// Handler data for startmap/endmap handlers. -typedef struct { - size_t ofs; - upb_fieldtype_t key_field_type; - upb_fieldtype_t value_field_type; - - // We know that we can hold this reference because the handlerdata has the - // same lifetime as the upb_handlers struct, and the upb_handlers struct holds - // a reference to the upb_msgdef, which in turn has references to its subdefs. - const upb_def* value_field_subdef; -} map_handlerdata_t; - -// Temporary frame for map parsing: at the beginning of a map entry message, a -// submsg handler allocates a frame to hold (i) a reference to the Map object -// into which this message will be inserted and (ii) storage slots to -// temporarily hold the key and value for this map entry until the end of the -// submessage. When the submessage ends, another handler is called to insert the -// value into the map. -typedef struct { - VALUE map; - const map_handlerdata_t* handlerdata; - char key_storage[NATIVE_SLOT_MAX_SIZE]; - char value_storage[NATIVE_SLOT_MAX_SIZE]; -} map_parse_frame_t; - -static void MapParseFrame_mark(void* _self) { - map_parse_frame_t* frame = _self; - - // This shouldn't strictly be necessary since this should be rooted by the - // message itself, but it can't hurt. - rb_gc_mark(frame->map); - - native_slot_mark(frame->handlerdata->key_field_type, &frame->key_storage); - native_slot_mark(frame->handlerdata->value_field_type, &frame->value_storage); -} - -void MapParseFrame_free(void* self) { - xfree(self); -} - -rb_data_type_t MapParseFrame_type = { - "MapParseFrame", - { MapParseFrame_mark, MapParseFrame_free, NULL }, -}; - -// Array of Ruby objects wrapping map_parse_frame_t. -// We don't allow multiple concurrent decodes, so we assume that this global -// variable is specific to the "current" decode. -VALUE map_parse_frames; - -static map_parse_frame_t* map_push_frame(VALUE map, - const map_handlerdata_t* handlerdata) { - map_parse_frame_t* frame = ALLOC(map_parse_frame_t); - frame->handlerdata = handlerdata; - frame->map = map; - native_slot_init(handlerdata->key_field_type, &frame->key_storage); - native_slot_init(handlerdata->value_field_type, &frame->value_storage); - - rb_ary_push(map_parse_frames, - TypedData_Wrap_Struct(rb_cObject, &MapParseFrame_type, frame)); - - return frame; -} - -static void map_pop_frame() { - rb_ary_pop(map_parse_frames); -} - -// Handler to begin a map entry: allocates a temporary frame. This is the -// 'startsubmsg' handler on the msgdef that contains the map field. -static void *startmapentry_handler(void *closure, const void *hd) { - MessageHeader* msg = closure; - const map_handlerdata_t* mapdata = hd; - VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE); - - return map_push_frame(map_rb, mapdata); -} - -// Handler to end a map entry: inserts the value defined during the message into -// the map. This is the 'endmsg' handler on the map entry msgdef. -static bool endmap_handler(void *closure, const void *hd, upb_status* s) { - map_parse_frame_t* frame = closure; - const map_handlerdata_t* mapdata = hd; - - VALUE key = native_slot_get( - mapdata->key_field_type, Qnil, - &frame->key_storage); - - VALUE value_field_typeclass = Qnil; - VALUE value; - - if (mapdata->value_field_type == UPB_TYPE_MESSAGE || - mapdata->value_field_type == UPB_TYPE_ENUM) { - value_field_typeclass = get_def_obj(mapdata->value_field_subdef); - } - - value = native_slot_get( - mapdata->value_field_type, value_field_typeclass, - &frame->value_storage); - - Map_index_set(frame->map, key, value); - map_pop_frame(); - - return true; -} - -// Allocates a new map_handlerdata_t given the map entry message definition. If -// the offset of the field within the parent message is also given, that is -// added to the handler data as well. Note that this is called *twice* per map -// field: once in the parent message handler setup when setting the startsubmsg -// handler and once in the map entry message handler setup when setting the -// key/value and endmsg handlers. The reason is that there is no easy way to -// pass the handlerdata down to the sub-message handler setup. -static map_handlerdata_t* new_map_handlerdata( - size_t ofs, - const upb_msgdef* mapentry_def, - Descriptor* desc) { - const upb_fielddef* key_field; - const upb_fielddef* value_field; - map_handlerdata_t* hd = ALLOC(map_handlerdata_t); - hd->ofs = ofs; - key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD); - assert(key_field != NULL); - hd->key_field_type = upb_fielddef_type(key_field); - value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD); - assert(value_field != NULL); - hd->value_field_type = upb_fielddef_type(value_field); - hd->value_field_subdef = upb_fielddef_subdef(value_field); - - return hd; -} - -// Handlers that set primitive values in oneofs. -#define DEFINE_ONEOF_HANDLER(type, ctype) \ - static bool oneof##type##_handler(void *closure, const void *hd, \ - ctype val) { \ - const oneof_handlerdata_t *oneofdata = hd; \ - DEREF(closure, oneofdata->case_ofs, uint32_t) = \ - oneofdata->oneof_case_num; \ - DEREF(closure, oneofdata->ofs, ctype) = val; \ - return true; \ - } - -DEFINE_ONEOF_HANDLER(bool, bool) -DEFINE_ONEOF_HANDLER(int32, int32_t) -DEFINE_ONEOF_HANDLER(uint32, uint32_t) -DEFINE_ONEOF_HANDLER(float, float) -DEFINE_ONEOF_HANDLER(int64, int64_t) -DEFINE_ONEOF_HANDLER(uint64, uint64_t) -DEFINE_ONEOF_HANDLER(double, double) - -#undef DEFINE_ONEOF_HANDLER - -// Handlers for strings in a oneof. -static void *oneofstr_handler(void *closure, - const void *hd, - size_t size_hint) { - MessageHeader* msg = closure; - const oneof_handlerdata_t *oneofdata = hd; - VALUE str = rb_str_new2(""); - rb_enc_associate(str, kRubyStringUtf8Encoding); - DEREF(msg, oneofdata->case_ofs, uint32_t) = - oneofdata->oneof_case_num; - DEREF(msg, oneofdata->ofs, VALUE) = str; - return (void*)str; -} - -static void *oneofbytes_handler(void *closure, - const void *hd, - size_t size_hint) { - MessageHeader* msg = closure; - const oneof_handlerdata_t *oneofdata = hd; - VALUE str = rb_str_new2(""); - rb_enc_associate(str, kRubyString8bitEncoding); - DEREF(msg, oneofdata->case_ofs, uint32_t) = - oneofdata->oneof_case_num; - DEREF(msg, oneofdata->ofs, VALUE) = str; - return (void*)str; -} - -static bool oneofstring_end_handler(void* closure, const void* hd) { - MessageHeader* msg = closure; - const oneof_handlerdata_t *oneofdata = hd; - rb_obj_freeze(DEREF(msg, oneofdata->ofs, VALUE)); - return true; -} - -// Handler for a submessage field in a oneof. -static void *oneofsubmsg_handler(void *closure, - const void *hd) { - MessageHeader* msg = closure; - const oneof_handlerdata_t *oneofdata = hd; - uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t); - - VALUE subdesc = - get_def_obj((void*)oneofdata->md); - VALUE subklass = Descriptor_msgclass(subdesc); - VALUE submsg_rb; - MessageHeader* submsg; - - if (oldcase != oneofdata->oneof_case_num || - DEREF(msg, oneofdata->ofs, VALUE) == Qnil) { - DEREF(msg, oneofdata->ofs, VALUE) = - rb_class_new_instance(0, NULL, subklass); - } - // Set the oneof case *after* allocating the new class instance -- otherwise, - // if the Ruby GC is invoked as part of a call into the VM, it might invoke - // our mark routines, and our mark routines might see the case value - // indicating a VALUE is present and expect a valid VALUE. See comment in - // layout_set() for more detail: basically, the change to the value and the - // case must be atomic w.r.t. the Ruby VM. - DEREF(msg, oneofdata->case_ofs, uint32_t) = - oneofdata->oneof_case_num; - - submsg_rb = DEREF(msg, oneofdata->ofs, VALUE); - TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg); - return submsg; -} - -// Set up handlers for a repeated field. -static void add_handlers_for_repeated_field(upb_handlers *h, - const upb_fielddef *f, - size_t offset) { - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset)); - upb_handlers_setstartseq(h, f, startseq_handler, &attr); - upb_handlerattr_uninit(&attr); - - switch (upb_fielddef_type(f)) { - -#define SET_HANDLER(utype, ltype) \ - case utype: \ - upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \ - break; - - SET_HANDLER(UPB_TYPE_BOOL, bool); - SET_HANDLER(UPB_TYPE_INT32, int32); - SET_HANDLER(UPB_TYPE_UINT32, uint32); - SET_HANDLER(UPB_TYPE_ENUM, int32); - SET_HANDLER(UPB_TYPE_FLOAT, float); - SET_HANDLER(UPB_TYPE_INT64, int64); - SET_HANDLER(UPB_TYPE_UINT64, uint64); - SET_HANDLER(UPB_TYPE_DOUBLE, double); - -#undef SET_HANDLER - - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; - upb_handlers_setstartstr(h, f, is_bytes ? - appendbytes_handler : appendstr_handler, - NULL); - upb_handlers_setstring(h, f, stringdata_handler, NULL); - upb_handlers_setendstr(h, f, appendstring_end_handler, NULL); - break; - } - case UPB_TYPE_MESSAGE: { - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, 0, f)); - upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr); - upb_handlerattr_uninit(&attr); - break; - } - } -} - -// Set up handlers for a singular field. -static void add_handlers_for_singular_field(upb_handlers *h, - const upb_fielddef *f, - size_t offset) { - switch (upb_fielddef_type(f)) { - case UPB_TYPE_BOOL: - case UPB_TYPE_INT32: - case UPB_TYPE_UINT32: - case UPB_TYPE_ENUM: - case UPB_TYPE_FLOAT: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT64: - case UPB_TYPE_DOUBLE: - upb_msg_setscalarhandler(h, f, offset, -1); - break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset)); - upb_handlers_setstartstr(h, f, - is_bytes ? bytes_handler : str_handler, - &attr); - upb_handlers_setstring(h, f, stringdata_handler, &attr); - upb_handlers_setendstr(h, f, stringdata_end_handler, &attr); - upb_handlerattr_uninit(&attr); - break; - } - case UPB_TYPE_MESSAGE: { - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, offset, f)); - upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr); - upb_handlerattr_uninit(&attr); - break; - } - } -} - -// Adds handlers to a map field. -static void add_handlers_for_mapfield(upb_handlers* h, - const upb_fielddef* fielddef, - size_t offset, - Descriptor* desc) { - const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef); - map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc); - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - - upb_handlers_addcleanup(h, hd, xfree); - upb_handlerattr_sethandlerdata(&attr, hd); - upb_handlers_setstartsubmsg(h, fielddef, startmapentry_handler, &attr); - upb_handlerattr_uninit(&attr); -} - -// Adds handlers to a map-entry msgdef. -static void add_handlers_for_mapentry(const upb_msgdef* msgdef, - upb_handlers* h, - Descriptor* desc) { - const upb_fielddef* key_field = map_entry_key(msgdef); - const upb_fielddef* value_field = map_entry_value(msgdef); - map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc); - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - - upb_handlers_addcleanup(h, hd, xfree); - upb_handlerattr_sethandlerdata(&attr, hd); - upb_handlers_setendmsg(h, endmap_handler, &attr); - - add_handlers_for_singular_field( - h, key_field, - offsetof(map_parse_frame_t, key_storage)); - add_handlers_for_singular_field( - h, value_field, - offsetof(map_parse_frame_t, value_storage)); -} - -// Set up handlers for a oneof field. -static void add_handlers_for_oneof_field(upb_handlers *h, - const upb_fielddef *f, - size_t offset, - size_t oneof_case_offset) { - - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata( - &attr, newoneofhandlerdata(h, offset, oneof_case_offset, f)); - - switch (upb_fielddef_type(f)) { - -#define SET_HANDLER(utype, ltype) \ - case utype: \ - upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \ - break; - - SET_HANDLER(UPB_TYPE_BOOL, bool); - SET_HANDLER(UPB_TYPE_INT32, int32); - SET_HANDLER(UPB_TYPE_UINT32, uint32); - SET_HANDLER(UPB_TYPE_ENUM, int32); - SET_HANDLER(UPB_TYPE_FLOAT, float); - SET_HANDLER(UPB_TYPE_INT64, int64); - SET_HANDLER(UPB_TYPE_UINT64, uint64); - SET_HANDLER(UPB_TYPE_DOUBLE, double); - -#undef SET_HANDLER - - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; - upb_handlers_setstartstr(h, f, is_bytes ? - oneofbytes_handler : oneofstr_handler, - &attr); - upb_handlers_setstring(h, f, stringdata_handler, NULL); - upb_handlers_setendstr(h, f, oneofstring_end_handler, &attr); - break; - } - case UPB_TYPE_MESSAGE: { - upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr); - break; - } - } - - upb_handlerattr_uninit(&attr); -} - - -static void add_handlers_for_message(const void *closure, upb_handlers *h) { - const upb_msgdef* msgdef = upb_handlers_msgdef(h); - Descriptor* desc = ruby_to_Descriptor(get_def_obj((void*)msgdef)); - upb_msg_field_iter i; - - // If this is a mapentry message type, set up a special set of handlers and - // bail out of the normal (user-defined) message type handling. - if (upb_msgdef_mapentry(msgdef)) { - add_handlers_for_mapentry(msgdef, h, desc); - return; - } - - // Ensure layout exists. We may be invoked to create handlers for a given - // message if we are included as a submsg of another message type before our - // class is actually built, so to work around this, we just create the layout - // (and handlers, in the class-building function) on-demand. - if (desc->layout == NULL) { - desc->layout = create_layout(desc->msgdef); - } - - for (upb_msg_field_begin(&i, desc->msgdef); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset + - sizeof(MessageHeader); - - if (upb_fielddef_containingoneof(f)) { - size_t oneof_case_offset = - desc->layout->fields[upb_fielddef_index(f)].case_offset + - sizeof(MessageHeader); - add_handlers_for_oneof_field(h, f, offset, oneof_case_offset); - } else if (is_map_field(f)) { - add_handlers_for_mapfield(h, f, offset, desc); - } else if (upb_fielddef_isseq(f)) { - add_handlers_for_repeated_field(h, f, offset); - } else { - add_handlers_for_singular_field(h, f, offset); - } - } -} - -// Creates upb handlers for populating a message. -static const upb_handlers *new_fill_handlers(Descriptor* desc, - const void* owner) { - // TODO(cfallin, haberman): once upb gets a caching/memoization layer for - // handlers, reuse subdef handlers so that e.g. if we already parse - // B-with-field-of-type-C, we don't have to rebuild the whole hierarchy to - // parse A-with-field-of-type-B-with-field-of-type-C. - return upb_handlers_newfrozen(desc->msgdef, owner, - add_handlers_for_message, NULL); -} - -// Constructs the handlers for filling a message's data into an in-memory -// object. -const upb_handlers* get_fill_handlers(Descriptor* desc) { - if (!desc->fill_handlers) { - desc->fill_handlers = - new_fill_handlers(desc, &desc->fill_handlers); - } - return desc->fill_handlers; -} - -// Constructs the upb decoder method for parsing messages of this type. -// This is called from the message class creation code. -const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor* desc, - const void* owner) { - const upb_handlers* handlers = get_fill_handlers(desc); - upb_pbdecodermethodopts opts; - upb_pbdecodermethodopts_init(&opts, handlers); - - return upb_pbdecodermethod_new(&opts, owner); -} - -static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) { - if (desc->fill_method == NULL) { - desc->fill_method = new_fillmsg_decodermethod( - desc, &desc->fill_method); - } - return desc->fill_method; -} - -static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) { - if (desc->json_fill_method == NULL) { - desc->json_fill_method = - upb_json_parsermethod_new(desc->msgdef, &desc->json_fill_method); - } - return desc->json_fill_method; -} - - -// Stack-allocated context during an encode/decode operation. Contains the upb -// environment and its stack-based allocator, an initial buffer for allocations -// to avoid malloc() when possible, and a template for Ruby exception messages -// if any error occurs. -#define STACK_ENV_STACKBYTES 4096 -typedef struct { - upb_env env; - const char* ruby_error_template; - char allocbuf[STACK_ENV_STACKBYTES]; -} stackenv; - -static void stackenv_init(stackenv* se, const char* errmsg); -static void stackenv_uninit(stackenv* se); - -// Callback invoked by upb if any error occurs during parsing or serialization. -static bool env_error_func(void* ud, const upb_status* status) { - stackenv* se = ud; - // Free the env -- rb_raise will longjmp up the stack past the encode/decode - // function so it would not otherwise have been freed. - stackenv_uninit(se); - - // TODO(haberman): have a way to verify that this is actually a parse error, - // instead of just throwing "parse error" unconditionally. - rb_raise(cParseError, se->ruby_error_template, upb_status_errmsg(status)); - // Never reached: rb_raise() always longjmp()s up the stack, past all of our - // code, back to Ruby. - return false; -} - -static void stackenv_init(stackenv* se, const char* errmsg) { - se->ruby_error_template = errmsg; - upb_env_init2(&se->env, se->allocbuf, sizeof(se->allocbuf), NULL); - upb_env_seterrorfunc(&se->env, env_error_func, se); -} - -static void stackenv_uninit(stackenv* se) { - upb_env_uninit(&se->env); -} - -/* - * call-seq: - * MessageClass.decode(data) => message - * - * Decodes the given data (as a string containing bytes in protocol buffers wire - * format) under the interpretration given by this message class's definition - * and returns a message object with the corresponding field values. - */ -VALUE Message_decode(VALUE klass, VALUE data) { - VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); - Descriptor* desc = ruby_to_Descriptor(descriptor); - VALUE msgklass = Descriptor_msgclass(descriptor); - VALUE msg_rb; - MessageHeader* msg; - - if (TYPE(data) != T_STRING) { - rb_raise(rb_eArgError, "Expected string for binary protobuf data."); - } - - msg_rb = rb_class_new_instance(0, NULL, msgklass); - TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); - - // We generally expect this to be clear already, but clear it in case parsing - // previously got interrupted somehow. - rb_ary_clear(map_parse_frames); - - { - const upb_pbdecodermethod* method = msgdef_decodermethod(desc); - const upb_handlers* h = upb_pbdecodermethod_desthandlers(method); - stackenv se; - upb_sink sink; - upb_pbdecoder* decoder; - stackenv_init(&se, "Error occurred during parsing: %s"); - - upb_sink_reset(&sink, h, msg); - decoder = upb_pbdecoder_create(&se.env, method, &sink); - upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data), - upb_pbdecoder_input(decoder)); - - stackenv_uninit(&se); - } - - return msg_rb; -} - -/* - * call-seq: - * MessageClass.decode_json(data) => message - * - * Decodes the given data (as a string containing bytes in protocol buffers wire - * format) under the interpretration given by this message class's definition - * and returns a message object with the corresponding field values. - */ -VALUE Message_decode_json(VALUE klass, VALUE data) { - VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); - Descriptor* desc = ruby_to_Descriptor(descriptor); - VALUE msgklass = Descriptor_msgclass(descriptor); - VALUE msg_rb; - MessageHeader* msg; - - if (TYPE(data) != T_STRING) { - rb_raise(rb_eArgError, "Expected string for JSON data."); - } - // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to - // convert, because string handlers pass data directly to message string - // fields. - - msg_rb = rb_class_new_instance(0, NULL, msgklass); - TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); - - // We generally expect this to be clear already, but clear it in case parsing - // previously got interrupted somehow. - rb_ary_clear(map_parse_frames); - - { - const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc); - stackenv se; - upb_sink sink; - upb_json_parser* parser; - stackenv_init(&se, "Error occurred during parsing: %s"); - - upb_sink_reset(&sink, get_fill_handlers(desc), msg); - parser = upb_json_parser_create(&se.env, method, &sink); - upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data), - upb_json_parser_input(parser)); - - stackenv_uninit(&se); - } - - return msg_rb; -} - -// ----------------------------------------------------------------------------- -// Serializing. -// ----------------------------------------------------------------------------- -// -// The code below also comes from upb's prototype Ruby binding, developed by -// haberman@. - -/* stringsink *****************************************************************/ - -// This should probably be factored into a common upb component. - -typedef struct { - upb_byteshandler handler; - upb_bytessink sink; - char *ptr; - size_t len, size; -} stringsink; - -static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) { - stringsink *sink = _sink; - sink->len = 0; - return sink; -} - -static size_t stringsink_string(void *_sink, const void *hd, const char *ptr, - size_t len, const upb_bufhandle *handle) { - stringsink *sink = _sink; - size_t new_size = sink->size; - - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - while (sink->len + len > new_size) { - new_size *= 2; - } - - if (new_size != sink->size) { - sink->ptr = realloc(sink->ptr, new_size); - sink->size = new_size; - } - - memcpy(sink->ptr + sink->len, ptr, len); - sink->len += len; - - return len; -} - -void stringsink_init(stringsink *sink) { - upb_byteshandler_init(&sink->handler); - upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL); - upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL); - - upb_bytessink_reset(&sink->sink, &sink->handler, sink); - - sink->size = 32; - sink->ptr = malloc(sink->size); - sink->len = 0; -} - -void stringsink_uninit(stringsink *sink) { - free(sink->ptr); -} - -/* msgvisitor *****************************************************************/ - -// TODO: If/when we support proto2 semantics in addition to the current proto3 -// semantics, which means that we have true field presence, we will want to -// modify msgvisitor so that it emits all present fields rather than all -// non-default-value fields. - -static void putmsg(VALUE msg, const Descriptor* desc, - upb_sink *sink, int depth, bool emit_defaults); - -static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) { - upb_selector_t ret; - bool ok = upb_handlers_getselector(f, type, &ret); - UPB_ASSERT(ok); - return ret; -} - -static void putstr(VALUE str, const upb_fielddef *f, upb_sink *sink) { - upb_sink subsink; - - if (str == Qnil) return; - - assert(BUILTIN_TYPE(str) == RUBY_T_STRING); - - // We should be guaranteed that the string has the correct encoding because - // we ensured this at assignment time and then froze the string. - if (upb_fielddef_type(f) == UPB_TYPE_STRING) { - assert(rb_enc_from_index(ENCODING_GET(str)) == kRubyStringUtf8Encoding); - } else { - assert(rb_enc_from_index(ENCODING_GET(str)) == kRubyString8bitEncoding); - } - - upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), RSTRING_LEN(str), - &subsink); - upb_sink_putstring(&subsink, getsel(f, UPB_HANDLER_STRING), RSTRING_PTR(str), - RSTRING_LEN(str), NULL); - upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR)); -} - -static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink, - int depth, bool emit_defaults) { - upb_sink subsink; - VALUE descriptor; - Descriptor* subdesc; - - if (submsg == Qnil) return; - - descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned); - subdesc = ruby_to_Descriptor(descriptor); - - upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink); - putmsg(submsg, subdesc, &subsink, depth + 1, emit_defaults); - upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG)); -} - -static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink, - int depth, bool emit_defaults) { - upb_sink subsink; - upb_fieldtype_t type = upb_fielddef_type(f); - upb_selector_t sel = 0; - int size; - - if (ary == Qnil) return; - - upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink); - - if (upb_fielddef_isprimitive(f)) { - sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); - } - - size = NUM2INT(RepeatedField_length(ary)); - for (int i = 0; i < size; i++) { - void* memory = RepeatedField_index_native(ary, i); - switch (type) { -#define T(upbtypeconst, upbtype, ctype) \ - case upbtypeconst: \ - upb_sink_put##upbtype(&subsink, sel, *((ctype *)memory)); \ - break; - - T(UPB_TYPE_FLOAT, float, float) - T(UPB_TYPE_DOUBLE, double, double) - T(UPB_TYPE_BOOL, bool, int8_t) - case UPB_TYPE_ENUM: - T(UPB_TYPE_INT32, int32, int32_t) - T(UPB_TYPE_UINT32, uint32, uint32_t) - T(UPB_TYPE_INT64, int64, int64_t) - T(UPB_TYPE_UINT64, uint64, uint64_t) - - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - putstr(*((VALUE *)memory), f, &subsink); - break; - case UPB_TYPE_MESSAGE: - putsubmsg(*((VALUE *)memory), f, &subsink, depth, emit_defaults); - break; - -#undef T - - } - } - upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); -} - -static void put_ruby_value(VALUE value, - const upb_fielddef *f, - VALUE type_class, - int depth, - upb_sink *sink, - bool emit_defaults) { - upb_selector_t sel = 0; - if (upb_fielddef_isprimitive(f)) { - sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); - } - - switch (upb_fielddef_type(f)) { - case UPB_TYPE_INT32: - upb_sink_putint32(sink, sel, NUM2INT(value)); - break; - case UPB_TYPE_INT64: - upb_sink_putint64(sink, sel, NUM2LL(value)); - break; - case UPB_TYPE_UINT32: - upb_sink_putuint32(sink, sel, NUM2UINT(value)); - break; - case UPB_TYPE_UINT64: - upb_sink_putuint64(sink, sel, NUM2ULL(value)); - break; - case UPB_TYPE_FLOAT: - upb_sink_putfloat(sink, sel, NUM2DBL(value)); - break; - case UPB_TYPE_DOUBLE: - upb_sink_putdouble(sink, sel, NUM2DBL(value)); - break; - case UPB_TYPE_ENUM: { - if (TYPE(value) == T_SYMBOL) { - value = rb_funcall(type_class, rb_intern("resolve"), 1, value); - } - upb_sink_putint32(sink, sel, NUM2INT(value)); - break; - } - case UPB_TYPE_BOOL: - upb_sink_putbool(sink, sel, value == Qtrue); - break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - putstr(value, f, sink); - break; - case UPB_TYPE_MESSAGE: - putsubmsg(value, f, sink, depth, emit_defaults); - } -} - -static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink, - int depth, bool emit_defaults) { - Map* self; - upb_sink subsink; - const upb_fielddef* key_field; - const upb_fielddef* value_field; - Map_iter it; - - if (map == Qnil) return; - self = ruby_to_Map(map); - - upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink); - - assert(upb_fielddef_type(f) == UPB_TYPE_MESSAGE); - key_field = map_field_key(f); - value_field = map_field_value(f); - - for (Map_begin(map, &it); !Map_done(&it); Map_next(&it)) { - VALUE key = Map_iter_key(&it); - VALUE value = Map_iter_value(&it); - upb_status status; - - upb_sink entry_sink; - upb_sink_startsubmsg(&subsink, getsel(f, UPB_HANDLER_STARTSUBMSG), - &entry_sink); - upb_sink_startmsg(&entry_sink); - - put_ruby_value(key, key_field, Qnil, depth + 1, &entry_sink, emit_defaults); - put_ruby_value(value, value_field, self->value_type_class, depth + 1, - &entry_sink, emit_defaults); - - upb_sink_endmsg(&entry_sink, &status); - upb_sink_endsubmsg(&subsink, getsel(f, UPB_HANDLER_ENDSUBMSG)); - } - - upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); -} - -static void putmsg(VALUE msg_rb, const Descriptor* desc, - upb_sink *sink, int depth, bool emit_defaults) { - MessageHeader* msg; - upb_msg_field_iter i; - upb_status status; - - upb_sink_startmsg(sink); - - // Protect against cycles (possible because users may freely reassign message - // and repeated fields) by imposing a maximum recursion depth. - if (depth > ENCODE_MAX_NESTING) { - rb_raise(rb_eRuntimeError, - "Maximum recursion depth exceeded during encoding."); - } - - TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); - - for (upb_msg_field_begin(&i, desc->msgdef); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - bool is_matching_oneof = false; - uint32_t offset = - desc->layout->fields[upb_fielddef_index(f)].offset + - sizeof(MessageHeader); - - if (upb_fielddef_containingoneof(f)) { - uint32_t oneof_case_offset = - desc->layout->fields[upb_fielddef_index(f)].case_offset + - sizeof(MessageHeader); - // For a oneof, check that this field is actually present -- skip all the - // below if not. - if (DEREF(msg, oneof_case_offset, uint32_t) != - upb_fielddef_number(f)) { - continue; - } - // Otherwise, fall through to the appropriate singular-field handler - // below. - is_matching_oneof = true; - } - - if (is_map_field(f)) { - VALUE map = DEREF(msg, offset, VALUE); - if (map != Qnil || emit_defaults) { - putmap(map, f, sink, depth, emit_defaults); - } - } else if (upb_fielddef_isseq(f)) { - VALUE ary = DEREF(msg, offset, VALUE); - if (ary != Qnil) { - putary(ary, f, sink, depth, emit_defaults); - } - } else if (upb_fielddef_isstring(f)) { - VALUE str = DEREF(msg, offset, VALUE); - if (is_matching_oneof || emit_defaults || RSTRING_LEN(str) > 0) { - putstr(str, f, sink); - } - } else if (upb_fielddef_issubmsg(f)) { - putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth, emit_defaults); - } else { - upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); - -#define T(upbtypeconst, upbtype, ctype, default_value) \ - case upbtypeconst: { \ - ctype value = DEREF(msg, offset, ctype); \ - if (is_matching_oneof || emit_defaults || value != default_value) { \ - upb_sink_put##upbtype(sink, sel, value); \ - } \ - } \ - break; - - switch (upb_fielddef_type(f)) { - T(UPB_TYPE_FLOAT, float, float, 0.0) - T(UPB_TYPE_DOUBLE, double, double, 0.0) - T(UPB_TYPE_BOOL, bool, uint8_t, 0) - case UPB_TYPE_ENUM: - T(UPB_TYPE_INT32, int32, int32_t, 0) - T(UPB_TYPE_UINT32, uint32, uint32_t, 0) - T(UPB_TYPE_INT64, int64, int64_t, 0) - T(UPB_TYPE_UINT64, uint64, uint64_t, 0) - - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: rb_raise(rb_eRuntimeError, "Internal error."); - } - -#undef T - - } - } - - upb_sink_endmsg(sink, &status); -} - -static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) { - if (desc->pb_serialize_handlers == NULL) { - desc->pb_serialize_handlers = - upb_pb_encoder_newhandlers(desc->msgdef, &desc->pb_serialize_handlers); - } - return desc->pb_serialize_handlers; -} - -static const upb_handlers* msgdef_json_serialize_handlers( - Descriptor* desc, bool preserve_proto_fieldnames) { - if (preserve_proto_fieldnames) { - if (desc->json_serialize_handlers == NULL) { - desc->json_serialize_handlers = - upb_json_printer_newhandlers( - desc->msgdef, true, &desc->json_serialize_handlers); - } - return desc->json_serialize_handlers; - } else { - if (desc->json_serialize_handlers_preserve == NULL) { - desc->json_serialize_handlers_preserve = - upb_json_printer_newhandlers( - desc->msgdef, false, &desc->json_serialize_handlers_preserve); - } - return desc->json_serialize_handlers_preserve; - } -} - -/* - * call-seq: - * MessageClass.encode(msg) => bytes - * - * Encodes the given message object to its serialized form in protocol buffers - * wire format. - */ -VALUE Message_encode(VALUE klass, VALUE msg_rb) { - VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); - Descriptor* desc = ruby_to_Descriptor(descriptor); - - stringsink sink; - stringsink_init(&sink); - - { - const upb_handlers* serialize_handlers = - msgdef_pb_serialize_handlers(desc); - - stackenv se; - upb_pb_encoder* encoder; - VALUE ret; - - stackenv_init(&se, "Error occurred during encoding: %s"); - encoder = upb_pb_encoder_create(&se.env, serialize_handlers, &sink.sink); - - putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0, false); - - ret = rb_str_new(sink.ptr, sink.len); - - stackenv_uninit(&se); - stringsink_uninit(&sink); - - return ret; - } -} - -/* - * call-seq: - * MessageClass.encode_json(msg) => json_string - * - * Encodes the given message object into its serialized JSON representation. - */ -VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) { - VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); - Descriptor* desc = ruby_to_Descriptor(descriptor); - VALUE msg_rb; - VALUE preserve_proto_fieldnames = Qfalse; - VALUE emit_defaults = Qfalse; - stringsink sink; - - if (argc < 1 || argc > 2) { - rb_raise(rb_eArgError, "Expected 1 or 2 arguments."); - } - - msg_rb = argv[0]; - - if (argc == 2) { - VALUE hash_args = argv[1]; - if (TYPE(hash_args) != T_HASH) { - rb_raise(rb_eArgError, "Expected hash arguments."); - } - preserve_proto_fieldnames = rb_hash_lookup2( - hash_args, ID2SYM(rb_intern("preserve_proto_fieldnames")), Qfalse); - - emit_defaults = rb_hash_lookup2( - hash_args, ID2SYM(rb_intern("emit_defaults")), Qfalse); - } - - stringsink_init(&sink); - - { - const upb_handlers* serialize_handlers = - msgdef_json_serialize_handlers(desc, RTEST(preserve_proto_fieldnames)); - upb_json_printer* printer; - stackenv se; - VALUE ret; - - stackenv_init(&se, "Error occurred during encoding: %s"); - printer = upb_json_printer_create(&se.env, serialize_handlers, &sink.sink); - - putmsg(msg_rb, desc, upb_json_printer_input(printer), 0, RTEST(emit_defaults)); - - ret = rb_enc_str_new(sink.ptr, sink.len, rb_utf8_encoding()); - - stackenv_uninit(&se); - stringsink_uninit(&sink); - - return ret; - } -} - diff --git a/ruby/ext/google/protobuf_c/extconf.rb b/ruby/ext/google/protobuf_c/extconf.rb old mode 100644 new mode 100755 index 0886e60708738..ec17787f79fd4 --- a/ruby/ext/google/protobuf_c/extconf.rb +++ b/ruby/ext/google/protobuf_c/extconf.rb @@ -2,7 +2,11 @@ require 'mkmf' -$CFLAGS += " -std=c99 -O3 -DNDEBUG" +if RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/ + $CFLAGS += " -std=gnu99 -O3 -DNDEBUG -fvisibility=hidden -Wall -Wsign-compare -Wno-declaration-after-statement" +else + $CFLAGS += " -std=gnu99 -O3 -DNDEBUG" +end if RUBY_PLATFORM =~ /linux/ @@ -10,8 +14,7 @@ $LDFLAGS += " -Wl,-wrap,memcpy" end -$objs = ["protobuf.o", "defs.o", "storage.o", "message.o", - "repeated_field.o", "map.o", "encode_decode.o", "upb.o", - "wrap_memcpy.o"] +$objs = ["protobuf.o", "convert.o", "defs.o", "message.o", + "repeated_field.o", "map.o", "ruby-upb.o", "wrap_memcpy.o"] create_makefile("google/protobuf_c") diff --git a/ruby/ext/google/protobuf_c/map.c b/ruby/ext/google/protobuf_c/map.c index 4be54c39d12f9..9d7d16b529233 100644 --- a/ruby/ext/google/protobuf_c/map.c +++ b/ruby/ext/google/protobuf_c/map.c @@ -28,160 +28,231 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include "convert.h" +#include "defs.h" +#include "message.h" #include "protobuf.h" // ----------------------------------------------------------------------------- -// Basic map operations on top of upb's strtable. +// Basic map operations on top of upb_map. // // Note that we roll our own `Map` container here because, as for // `RepeatedField`, we want a strongly-typed container. This is so that any user // errors due to incorrect map key or value types are raised as close as // possible to the error site, rather than at some deferred point (e.g., // serialization). -// -// We build our `Map` on top of upb_strtable so that we're able to take -// advantage of the native_slot storage abstraction, as RepeatedField does. -// (This is not quite a perfect mapping -- see the key conversions below -- but -// gives us full support and error-checking for all value types for free.) // ----------------------------------------------------------------------------- -// Map values are stored using the native_slot abstraction (as with repeated -// field values), but keys are a bit special. Since we use a strtable, we need -// to store keys as sequences of bytes such that equality of those bytes maps -// one-to-one to equality of keys. We store strings directly (i.e., they map to -// their own bytes) and integers as native integers (using the native_slot -// abstraction). - -// Note that there is another tradeoff here in keeping string keys as native -// strings rather than Ruby strings: traversing the Map requires conversion to -// Ruby string values on every traversal, potentially creating more garbage. We -// should consider ways to cache a Ruby version of the key if this becomes an -// issue later. - -// Forms a key to use with the underlying strtable from a Ruby key value. |buf| -// must point to TABLE_KEY_BUF_LENGTH bytes of temporary space, used to -// construct a key byte sequence if needed. |out_key| and |out_length| provide -// the resulting key data/length. -#define TABLE_KEY_BUF_LENGTH 8 // sizeof(uint64_t) -static VALUE table_key(Map* self, VALUE key, - char* buf, - const char** out_key, - size_t* out_length) { - switch (self->key_type) { - case UPB_TYPE_BYTES: - case UPB_TYPE_STRING: - // Strings: use string content directly. - Check_Type(key, T_STRING); - key = native_slot_encode_and_freeze_string(self->key_type, key); - *out_key = RSTRING_PTR(key); - *out_length = RSTRING_LEN(key); - break; +// ----------------------------------------------------------------------------- +// Map container type. +// ----------------------------------------------------------------------------- - case UPB_TYPE_BOOL: - case UPB_TYPE_INT32: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT32: - case UPB_TYPE_UINT64: - native_slot_set(self->key_type, Qnil, buf, key); - *out_key = buf; - *out_length = native_slot_size(self->key_type); - break; +typedef struct { + const upb_map *map; // Can convert to mutable when non-frozen. + upb_fieldtype_t key_type; + TypeInfo value_type_info; + VALUE value_type_class; + VALUE arena; +} Map; - default: - // Map constructor should not allow a Map with another key type to be - // constructed. - assert(false); - break; - } +static void Map_mark(void* _self) { + Map* self = _self; + rb_gc_mark(self->value_type_class); + rb_gc_mark(self->arena); +} + +const rb_data_type_t Map_type = { + "Google::Protobuf::Map", + { Map_mark, RUBY_DEFAULT_FREE, NULL }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; + +VALUE cMap; - return key; +static Map* ruby_to_Map(VALUE _self) { + Map* self; + TypedData_Get_Struct(_self, Map, &Map_type, self); + return self; } -static VALUE table_key_to_ruby(Map* self, const char* buf, size_t length) { - switch (self->key_type) { - case UPB_TYPE_BYTES: - case UPB_TYPE_STRING: { - VALUE ret = rb_str_new(buf, length); - rb_enc_associate(ret, - (self->key_type == UPB_TYPE_BYTES) ? - kRubyString8bitEncoding : kRubyStringUtf8Encoding); - return ret; +static VALUE Map_alloc(VALUE klass) { + Map* self = ALLOC(Map); + self->map = NULL; + self->value_type_class = Qnil; + self->value_type_info.def.msgdef = NULL; + self->arena = Qnil; + return TypedData_Wrap_Struct(klass, &Map_type, self); +} + +VALUE Map_GetRubyWrapper(upb_map* map, upb_fieldtype_t key_type, + TypeInfo value_type, VALUE arena) { + PBRUBY_ASSERT(map); + + VALUE val = ObjectCache_Get(map); + + if (val == Qnil) { + val = Map_alloc(cMap); + Map* self; + ObjectCache_Add(map, val, Arena_get(arena)); + TypedData_Get_Struct(val, Map, &Map_type, self); + self->map = map; + self->arena = arena; + self->key_type = key_type; + self->value_type_info = value_type; + if (self->value_type_info.type == UPB_TYPE_MESSAGE) { + const upb_msgdef *val_m = self->value_type_info.def.msgdef; + self->value_type_class = Descriptor_DefToClass(val_m); } + } - case UPB_TYPE_BOOL: - case UPB_TYPE_INT32: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT32: - case UPB_TYPE_UINT64: - return native_slot_get(self->key_type, Qnil, buf); + return val; +} - default: - assert(false); - return Qnil; - } +static VALUE Map_new_this_type(Map *from) { + VALUE arena_rb = Arena_new(); + upb_map* map = upb_map_new(Arena_get(arena_rb), from->key_type, + from->value_type_info.type); + VALUE ret = + Map_GetRubyWrapper(map, from->key_type, from->value_type_info, arena_rb); + PBRUBY_ASSERT(ruby_to_Map(ret)->value_type_class == from->value_type_class); + return ret; } -static void* value_memory(upb_value* v) { - return (void*)(&v->val); +static TypeInfo Map_keyinfo(Map* self) { + TypeInfo ret; + ret.type = self->key_type; + ret.def.msgdef = NULL; + return ret; } -// ----------------------------------------------------------------------------- -// Map container type. -// ----------------------------------------------------------------------------- +static upb_map *Map_GetMutable(VALUE _self) { + rb_check_frozen(_self); + return (upb_map*)ruby_to_Map(_self)->map; +} -const rb_data_type_t Map_type = { - "Google::Protobuf::Map", - { Map_mark, Map_free, NULL }, -}; +VALUE Map_CreateHash(const upb_map* map, upb_fieldtype_t key_type, + TypeInfo val_info) { + VALUE hash = rb_hash_new(); + size_t iter = UPB_MAP_BEGIN; + TypeInfo key_info = TypeInfo_from_type(key_type); -VALUE cMap; + if (!map) return hash; -Map* ruby_to_Map(VALUE _self) { - Map* self; - TypedData_Get_Struct(_self, Map, &Map_type, self); - return self; + while (upb_mapiter_next(map, &iter)) { + upb_msgval key = upb_mapiter_key(map, iter); + upb_msgval val = upb_mapiter_value(map, iter); + VALUE key_val = Convert_UpbToRuby(key, key_info, Qnil); + VALUE val_val = Scalar_CreateHash(val, val_info); + rb_hash_aset(hash, key_val, val_val); + } + + return hash; } -void Map_mark(void* _self) { - Map* self = _self; +VALUE Map_deep_copy(VALUE obj) { + Map* self = ruby_to_Map(obj); + VALUE new_arena_rb = Arena_new(); + upb_arena *arena = Arena_get(new_arena_rb); + upb_map* new_map = + upb_map_new(arena, self->key_type, self->value_type_info.type); + size_t iter = UPB_MAP_BEGIN; + while (upb_mapiter_next(self->map, &iter)) { + upb_msgval key = upb_mapiter_key(self->map, iter); + upb_msgval val = upb_mapiter_value(self->map, iter); + upb_msgval val_copy = Msgval_DeepCopy(val, self->value_type_info, arena); + upb_map_set(new_map, key, val_copy, arena); + } - rb_gc_mark(self->value_type_class); + return Map_GetRubyWrapper(new_map, self->key_type, self->value_type_info, + new_arena_rb); +} - if (self->value_type == UPB_TYPE_STRING || - self->value_type == UPB_TYPE_BYTES || - self->value_type == UPB_TYPE_MESSAGE) { - upb_strtable_iter it; - for (upb_strtable_begin(&it, &self->table); - !upb_strtable_done(&it); - upb_strtable_next(&it)) { - upb_value v = upb_strtable_iter_value(&it); - void* mem = value_memory(&v); - native_slot_mark(self->value_type, mem); - } +const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef *field) { + const upb_fielddef* key_field = map_field_key(field); + const upb_fielddef* value_field = map_field_value(field); + TypeInfo value_type_info = TypeInfo_get(value_field); + Map* self; + + if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) || + RTYPEDDATA_TYPE(val) != &Map_type) { + rb_raise(cTypeError, "Expected Map instance"); } + + self = ruby_to_Map(val); + if (self->key_type != upb_fielddef_type(key_field)) { + rb_raise(cTypeError, "Map key type does not match field's key type"); + } + if (self->value_type_info.type != value_type_info.type) { + rb_raise(cTypeError, "Map value type does not match field's value type"); + } + if (self->value_type_info.def.msgdef != value_type_info.def.msgdef) { + rb_raise(cTypeError, "Map value type has wrong message/enum class"); + } + + return self->map; } -void Map_free(void* _self) { - Map* self = _self; - upb_strtable_uninit(&self->table); - xfree(self); +void Map_Inspect(StringBuilder* b, const upb_map* map, upb_fieldtype_t key_type, + TypeInfo val_type) { + bool first = true; + TypeInfo key_type_info = {key_type}; + StringBuilder_Printf(b, "{"); + if (map) { + size_t iter = UPB_MAP_BEGIN; + while (upb_mapiter_next(map, &iter)) { + upb_msgval key = upb_mapiter_key(map, iter); + upb_msgval val = upb_mapiter_value(map, iter); + if (first) { + first = false; + } else { + StringBuilder_Printf(b, ", "); + } + StringBuilder_PrintMsgval(b, key, key_type_info); + StringBuilder_Printf(b, "=>"); + StringBuilder_PrintMsgval(b, val, val_type); + } + } + StringBuilder_Printf(b, "}"); } -VALUE Map_alloc(VALUE klass) { - Map* self = ALLOC(Map); - memset(self, 0, sizeof(Map)); - self->value_type_class = Qnil; - return TypedData_Wrap_Struct(klass, &Map_type, self); +static int merge_into_self_callback(VALUE key, VALUE val, VALUE _self) { + Map* self = ruby_to_Map(_self); + upb_arena *arena = Arena_get(self->arena); + upb_msgval key_val = Convert_RubyToUpb(key, "", Map_keyinfo(self), arena); + upb_msgval val_val = Convert_RubyToUpb(val, "", self->value_type_info, arena); + upb_map_set(Map_GetMutable(_self), key_val, val_val, arena); + return ST_CONTINUE; } -static bool needs_typeclass(upb_fieldtype_t type) { - switch (type) { - case UPB_TYPE_MESSAGE: - case UPB_TYPE_ENUM: - return true; - default: - return false; +// Used only internally -- shared by #merge and #initialize. +static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) { + if (TYPE(hashmap) == T_HASH) { + rb_hash_foreach(hashmap, merge_into_self_callback, _self); + } else if (RB_TYPE_P(hashmap, T_DATA) && RTYPEDDATA_P(hashmap) && + RTYPEDDATA_TYPE(hashmap) == &Map_type) { + Map* self = ruby_to_Map(_self); + Map* other = ruby_to_Map(hashmap); + upb_arena *arena = Arena_get(self->arena); + upb_msg *self_msg = Map_GetMutable(_self); + size_t iter = UPB_MAP_BEGIN; + + upb_arena_fuse(arena, Arena_get(other->arena)); + + if (self->key_type != other->key_type || + self->value_type_info.type != other->value_type_info.type || + self->value_type_class != other->value_type_class) { + rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types"); + } + + while (upb_mapiter_next(other->map, &iter)) { + upb_msgval key = upb_mapiter_key(other->map, iter); + upb_msgval val = upb_mapiter_value(other->map, iter); + upb_map_set(self_msg, key, val, arena); + } + } else { + rb_raise(rb_eArgError, "Unknown type merging into Map"); } + return _self; } /* @@ -214,9 +285,9 @@ static bool needs_typeclass(upb_fieldtype_t type) { * references to underlying objects will be shared if the value type is a * message type. */ -VALUE Map_init(int argc, VALUE* argv, VALUE _self) { +static VALUE Map_init(int argc, VALUE* argv, VALUE _self) { Map* self = ruby_to_Map(_self); - int init_value_arg; + VALUE init_arg; // We take either two args (:key_type, :value_type), three args (:key_type, // :value_type, "ValueMessageType"), or four args (the above plus an initial @@ -226,7 +297,9 @@ VALUE Map_init(int argc, VALUE* argv, VALUE _self) { } self->key_type = ruby_to_fieldtype(argv[0]); - self->value_type = ruby_to_fieldtype(argv[1]); + self->value_type_info = + TypeInfo_FromClass(argc, argv, 1, &self->value_type_class, &init_arg); + self->arena = Arena_new(); // Check that the key type is an allowed type. switch (self->key_type) { @@ -243,21 +316,12 @@ VALUE Map_init(int argc, VALUE* argv, VALUE _self) { rb_raise(rb_eArgError, "Invalid key type for map."); } - init_value_arg = 2; - if (needs_typeclass(self->value_type) && argc > 2) { - self->value_type_class = argv[2]; - validate_type_class(self->value_type, self->value_type_class); - init_value_arg = 3; - } + self->map = upb_map_new(Arena_get(self->arena), self->key_type, + self->value_type_info.type); + ObjectCache_Add(self->map, _self, Arena_get(self->arena)); - // Table value type is always UINT64: this ensures enough space to store the - // native_slot value. - if (!upb_strtable_init(&self->table, UPB_CTYPE_UINT64)) { - rb_raise(rb_eRuntimeError, "Could not allocate table."); - } - - if (argc > init_value_arg) { - Map_merge_into_self(_self, argv[init_value_arg]); + if (init_arg != Qnil) { + Map_merge_into_self(_self, init_arg); } return Qnil; @@ -271,24 +335,16 @@ VALUE Map_init(int argc, VALUE* argv, VALUE _self) { * Note that Map also includes Enumerable; map thus acts like a normal Ruby * sequence. */ -VALUE Map_each(VALUE _self) { +static VALUE Map_each(VALUE _self) { Map* self = ruby_to_Map(_self); - - upb_strtable_iter it; - for (upb_strtable_begin(&it, &self->table); - !upb_strtable_done(&it); - upb_strtable_next(&it)) { - - VALUE key = table_key_to_ruby( - self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it)); - - upb_value v = upb_strtable_iter_value(&it); - void* mem = value_memory(&v); - VALUE value = native_slot_get(self->value_type, - self->value_type_class, - mem); - - rb_yield_values(2, key, value); + size_t iter = UPB_MAP_BEGIN; + + while (upb_mapiter_next(self->map, &iter)) { + upb_msgval key = upb_mapiter_key(self->map, iter); + upb_msgval val = upb_mapiter_value(self->map, iter); + VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena); + VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena); + rb_yield_values(2, key_val, val_val); } return Qnil; @@ -300,19 +356,15 @@ VALUE Map_each(VALUE _self) { * * Returns the list of keys contained in the map, in unspecified order. */ -VALUE Map_keys(VALUE _self) { +static VALUE Map_keys(VALUE _self) { Map* self = ruby_to_Map(_self); - + size_t iter = UPB_MAP_BEGIN; VALUE ret = rb_ary_new(); - upb_strtable_iter it; - for (upb_strtable_begin(&it, &self->table); - !upb_strtable_done(&it); - upb_strtable_next(&it)) { - - VALUE key = table_key_to_ruby( - self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it)); - rb_ary_push(ret, key); + while (upb_mapiter_next(self->map, &iter)) { + upb_msgval key = upb_mapiter_key(self->map, iter); + VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena); + rb_ary_push(ret, key_val); } return ret; @@ -324,22 +376,15 @@ VALUE Map_keys(VALUE _self) { * * Returns the list of values contained in the map, in unspecified order. */ -VALUE Map_values(VALUE _self) { +static VALUE Map_values(VALUE _self) { Map* self = ruby_to_Map(_self); - + size_t iter = UPB_MAP_BEGIN; VALUE ret = rb_ary_new(); - upb_strtable_iter it; - for (upb_strtable_begin(&it, &self->table); - !upb_strtable_done(&it); - upb_strtable_next(&it)) { - - upb_value v = upb_strtable_iter_value(&it); - void* mem = value_memory(&v); - VALUE value = native_slot_get(self->value_type, - self->value_type_class, - mem); - - rb_ary_push(ret, value); + + while (upb_mapiter_next(self->map, &iter)) { + upb_msgval val = upb_mapiter_value(self->map, iter); + VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena); + rb_ary_push(ret, val_val); } return ret; @@ -352,18 +397,13 @@ VALUE Map_values(VALUE _self) { * Accesses the element at the given key. Throws an exception if the key type is * incorrect. Returns nil when the key is not present in the map. */ -VALUE Map_index(VALUE _self, VALUE key) { +static VALUE Map_index(VALUE _self, VALUE key) { Map* self = ruby_to_Map(_self); + upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL); + upb_msgval val; - char keybuf[TABLE_KEY_BUF_LENGTH]; - const char* keyval = NULL; - size_t length = 0; - upb_value v; - key = table_key(self, key, keybuf, &keyval, &length); - - if (upb_strtable_lookup2(&self->table, keyval, length, &v)) { - void* mem = value_memory(&v); - return native_slot_get(self->value_type, self->value_type_class, mem); + if (upb_map_get(self->map, key_upb, &val)) { + return Convert_UpbToRuby(val, self->value_type_info, self->arena); } else { return Qnil; } @@ -377,27 +417,15 @@ VALUE Map_index(VALUE _self, VALUE key) { * Throws an exception if the key type is incorrect. Returns the new value that * was just inserted. */ -VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) { +static VALUE Map_index_set(VALUE _self, VALUE key, VALUE val) { Map* self = ruby_to_Map(_self); + upb_arena *arena = Arena_get(self->arena); + upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL); + upb_msgval val_upb = Convert_RubyToUpb(val, "", self->value_type_info, arena); - char keybuf[TABLE_KEY_BUF_LENGTH]; - const char* keyval = NULL; - size_t length = 0; - upb_value v; - void* mem; - key = table_key(self, key, keybuf, &keyval, &length); - - mem = value_memory(&v); - native_slot_set(self->value_type, self->value_type_class, mem, value); + upb_map_set(Map_GetMutable(_self), key_upb, val_upb, arena); - // Replace any existing value by issuing a 'remove' operation first. - upb_strtable_remove2(&self->table, keyval, length, NULL); - if (!upb_strtable_insert2(&self->table, keyval, length, v)) { - rb_raise(rb_eRuntimeError, "Could not insert into table"); - } - - // Ruby hashmap's :[]= method also returns the inserted value. - return value; + return val; } /* @@ -407,15 +435,11 @@ VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) { * Returns true if the given key is present in the map. Throws an exception if * the key has the wrong type. */ -VALUE Map_has_key(VALUE _self, VALUE key) { +static VALUE Map_has_key(VALUE _self, VALUE key) { Map* self = ruby_to_Map(_self); + upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL); - char keybuf[TABLE_KEY_BUF_LENGTH]; - const char* keyval = NULL; - size_t length = 0; - key = table_key(self, key, keybuf, &keyval, &length); - - if (upb_strtable_lookup2(&self->table, keyval, length, NULL)) { + if (upb_map_get(self->map, key_upb, NULL)) { return Qtrue; } else { return Qfalse; @@ -429,21 +453,25 @@ VALUE Map_has_key(VALUE _self, VALUE key) { * Deletes the value at the given key, if any, returning either the old value or * nil if none was present. Throws an exception if the key is of the wrong type. */ -VALUE Map_delete(VALUE _self, VALUE key) { +static VALUE Map_delete(VALUE _self, VALUE key) { Map* self = ruby_to_Map(_self); + upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL); + upb_msgval val_upb; + VALUE ret; - char keybuf[TABLE_KEY_BUF_LENGTH]; - const char* keyval = NULL; - size_t length = 0; - upb_value v; - key = table_key(self, key, keybuf, &keyval, &length); + rb_check_frozen(_self); - if (upb_strtable_remove2(&self->table, keyval, length, &v)) { - void* mem = value_memory(&v); - return native_slot_get(self->value_type, self->value_type_class, mem); + // TODO(haberman): make upb_map_delete() also capable of returning the deleted + // value. + if (upb_map_get(self->map, key_upb, &val_upb)) { + ret = Convert_UpbToRuby(val_upb, self->value_type_info, self->arena); } else { - return Qnil; + ret = Qnil; } + + upb_map_delete(Map_GetMutable(_self), key_upb); + + return ret; } /* @@ -452,15 +480,8 @@ VALUE Map_delete(VALUE _self, VALUE key) { * * Removes all entries from the map. */ -VALUE Map_clear(VALUE _self) { - Map* self = ruby_to_Map(_self); - - // Uninit and reinit the table -- this is faster than iterating and doing a - // delete-lookup on each key. - upb_strtable_uninit(&self->table); - if (!upb_strtable_init(&self->table, UPB_CTYPE_INT64)) { - rb_raise(rb_eRuntimeError, "Unable to re-initialize table"); - } +static VALUE Map_clear(VALUE _self) { + upb_map_clear(Map_GetMutable(_self)); return Qnil; } @@ -470,24 +491,9 @@ VALUE Map_clear(VALUE _self) { * * Returns the number of entries (key-value pairs) in the map. */ -VALUE Map_length(VALUE _self) { +static VALUE Map_length(VALUE _self) { Map* self = ruby_to_Map(_self); - return ULL2NUM(upb_strtable_count(&self->table)); -} - -static VALUE Map_new_this_type(VALUE _self) { - Map* self = ruby_to_Map(_self); - VALUE new_map = Qnil; - VALUE key_type = fieldtype_to_ruby(self->key_type); - VALUE value_type = fieldtype_to_ruby(self->value_type); - if (self->value_type_class != Qnil) { - new_map = rb_funcall(CLASS_OF(_self), rb_intern("new"), 3, - key_type, value_type, self->value_type_class); - } else { - new_map = rb_funcall(CLASS_OF(_self), rb_intern("new"), 2, - key_type, value_type); - } - return new_map; + return ULL2NUM(upb_map_size(self->map)); } /* @@ -497,59 +503,23 @@ static VALUE Map_new_this_type(VALUE _self) { * Duplicates this map with a shallow copy. References to all non-primitive * element objects (e.g., submessages) are shared. */ -VALUE Map_dup(VALUE _self) { +static VALUE Map_dup(VALUE _self) { Map* self = ruby_to_Map(_self); - VALUE new_map = Map_new_this_type(_self); - Map* new_self = ruby_to_Map(new_map); - - upb_strtable_iter it; - for (upb_strtable_begin(&it, &self->table); - !upb_strtable_done(&it); - upb_strtable_next(&it)) { - - upb_value v = upb_strtable_iter_value(&it); - void* mem = value_memory(&v); - upb_value dup; - void* dup_mem = value_memory(&dup); - native_slot_dup(self->value_type, dup_mem, mem); - - if (!upb_strtable_insert2(&new_self->table, - upb_strtable_iter_key(&it), - upb_strtable_iter_keylength(&it), - dup)) { - rb_raise(rb_eRuntimeError, "Error inserting value into new table"); - } - } - - return new_map; -} - -// Used by Google::Protobuf.deep_copy but not exposed directly. -VALUE Map_deep_copy(VALUE _self) { - Map* self = ruby_to_Map(_self); - VALUE new_map = Map_new_this_type(_self); - Map* new_self = ruby_to_Map(new_map); - - upb_strtable_iter it; - for (upb_strtable_begin(&it, &self->table); - !upb_strtable_done(&it); - upb_strtable_next(&it)) { - - upb_value v = upb_strtable_iter_value(&it); - void* mem = value_memory(&v); - upb_value dup; - void* dup_mem = value_memory(&dup); - native_slot_deep_copy(self->value_type, dup_mem, mem); - - if (!upb_strtable_insert2(&new_self->table, - upb_strtable_iter_key(&it), - upb_strtable_iter_keylength(&it), - dup)) { - rb_raise(rb_eRuntimeError, "Error inserting value into new table"); - } + VALUE new_map_rb = Map_new_this_type(self); + Map* new_self = ruby_to_Map(new_map_rb); + size_t iter = UPB_MAP_BEGIN; + upb_arena *arena = Arena_get(new_self->arena); + upb_map *new_map = Map_GetMutable(new_map_rb); + + upb_arena_fuse(arena, Arena_get(self->arena)); + + while (upb_mapiter_next(self->map, &iter)) { + upb_msgval key = upb_mapiter_key(self->map, iter); + upb_msgval val = upb_mapiter_value(self->map, iter); + upb_map_set(new_map, key, val, arena); } - return new_map; + return new_map_rb; } /* @@ -568,12 +538,11 @@ VALUE Map_deep_copy(VALUE _self) { VALUE Map_eq(VALUE _self, VALUE _other) { Map* self = ruby_to_Map(_self); Map* other; - upb_strtable_iter it; // Allow comparisons to Ruby hashmaps by converting to a temporary Map // instance. Slow, but workable. if (TYPE(_other) == T_HASH) { - VALUE other_map = Map_new_this_type(_self); + VALUE other_map = Map_new_this_type(self); Map_merge_into_self(other_map, _other); _other = other_map; } @@ -584,35 +553,27 @@ VALUE Map_eq(VALUE _self, VALUE _other) { return Qtrue; } if (self->key_type != other->key_type || - self->value_type != other->value_type || + self->value_type_info.type != other->value_type_info.type || self->value_type_class != other->value_type_class) { return Qfalse; } - if (upb_strtable_count(&self->table) != upb_strtable_count(&other->table)) { + if (upb_map_size(self->map) != upb_map_size(other->map)) { return Qfalse; } // For each member of self, check that an equal member exists at the same key // in other. - for (upb_strtable_begin(&it, &self->table); - !upb_strtable_done(&it); - upb_strtable_next(&it)) { - - upb_value v = upb_strtable_iter_value(&it); - void* mem = value_memory(&v); - upb_value other_v; - void* other_mem = value_memory(&other_v); - - if (!upb_strtable_lookup2(&other->table, - upb_strtable_iter_key(&it), - upb_strtable_iter_keylength(&it), - &other_v)) { + size_t iter = UPB_MAP_BEGIN; + while (upb_mapiter_next(self->map, &iter)) { + upb_msgval key = upb_mapiter_key(self->map, iter); + upb_msgval val = upb_mapiter_value(self->map, iter); + upb_msgval other_val; + if (!upb_map_get(other->map, key, &other_val)) { // Not present in other map. return Qfalse; } - - if (!native_slot_eq(self->value_type, mem, other_mem)) { - // Present, but value not equal. + if (!Msgval_IsEqual(val, other_val, self->value_type_info)) { + // Present but different value. return Qfalse; } } @@ -620,6 +581,21 @@ VALUE Map_eq(VALUE _self, VALUE _other) { return Qtrue; } +/* + * call-seq: + * Message.freeze => self + * + * Freezes the message object. We have to intercept this so we can pin the + * Ruby object into memory so we don't forget it's frozen. + */ +static VALUE Map_freeze(VALUE _self) { + Map* self = ruby_to_Map(_self); + + ObjectCache_Pin(self->map, _self, Arena_get(self->arena)); + RB_OBJ_FREEZE(_self); + return _self; +} + /* * call-seq: * Map.hash => hash_value @@ -628,28 +604,18 @@ VALUE Map_eq(VALUE _self, VALUE _other) { */ VALUE Map_hash(VALUE _self) { Map* self = ruby_to_Map(_self); - - st_index_t h = rb_hash_start(0); - VALUE hash_sym = rb_intern("hash"); - - upb_strtable_iter it; - for (upb_strtable_begin(&it, &self->table); - !upb_strtable_done(&it); - upb_strtable_next(&it)) { - VALUE key = table_key_to_ruby( - self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it)); - - upb_value v = upb_strtable_iter_value(&it); - void* mem = value_memory(&v); - VALUE value = native_slot_get(self->value_type, - self->value_type_class, - mem); - - h = rb_hash_uint(h, NUM2LONG(rb_funcall(key, hash_sym, 0))); - h = rb_hash_uint(h, NUM2LONG(rb_funcall(value, hash_sym, 0))); + uint64_t hash = 0; + + size_t iter = UPB_MAP_BEGIN; + TypeInfo key_info = {self->key_type}; + while (upb_mapiter_next(self->map, &iter)) { + upb_msgval key = upb_mapiter_key(self->map, iter); + upb_msgval val = upb_mapiter_value(self->map, iter); + hash = Msgval_GetHash(key, key_info, hash); + hash = Msgval_GetHash(val, self->value_type_info, hash); } - return INT2FIX(h); + return LL2NUM(hash); } /* @@ -660,25 +626,7 @@ VALUE Map_hash(VALUE _self) { */ VALUE Map_to_h(VALUE _self) { Map* self = ruby_to_Map(_self); - VALUE hash = rb_hash_new(); - upb_strtable_iter it; - for (upb_strtable_begin(&it, &self->table); - !upb_strtable_done(&it); - upb_strtable_next(&it)) { - VALUE key = table_key_to_ruby( - self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it)); - upb_value v = upb_strtable_iter_value(&it); - void* mem = value_memory(&v); - VALUE value = native_slot_get(self->value_type, - self->value_type_class, - mem); - - if (self->value_type == UPB_TYPE_MESSAGE) { - value = Message_to_h(value); - } - rb_hash_aset(hash, key, value); - } - return hash; + return Map_CreateHash(self->map, self->key_type, self->value_type_info); } /* @@ -692,36 +640,11 @@ VALUE Map_to_h(VALUE _self) { VALUE Map_inspect(VALUE _self) { Map* self = ruby_to_Map(_self); - VALUE str = rb_str_new2("{"); - - bool first = true; - VALUE inspect_sym = rb_intern("inspect"); - - upb_strtable_iter it; - for (upb_strtable_begin(&it, &self->table); - !upb_strtable_done(&it); - upb_strtable_next(&it)) { - VALUE key = table_key_to_ruby( - self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it)); - - upb_value v = upb_strtable_iter_value(&it); - void* mem = value_memory(&v); - VALUE value = native_slot_get(self->value_type, - self->value_type_class, - mem); - - if (!first) { - str = rb_str_cat2(str, ", "); - } else { - first = false; - } - str = rb_str_append(str, rb_funcall(key, inspect_sym, 0)); - str = rb_str_cat2(str, "=>"); - str = rb_str_append(str, rb_funcall(value, inspect_sym, 0)); - } - - str = rb_str_cat2(str, "}"); - return str; + StringBuilder* builder = StringBuilder_New(); + Map_Inspect(builder, self->map, self->key_type, self->value_type_info); + VALUE ret = StringBuilder_ToRubyString(builder); + StringBuilder_Free(builder); + return ret; } /* @@ -733,92 +656,16 @@ VALUE Map_inspect(VALUE _self) { * in the new copy of this map. Returns the new copy of this map with merged * contents. */ -VALUE Map_merge(VALUE _self, VALUE hashmap) { +static VALUE Map_merge(VALUE _self, VALUE hashmap) { VALUE dupped = Map_dup(_self); return Map_merge_into_self(dupped, hashmap); } -static int merge_into_self_callback(VALUE key, VALUE value, VALUE self) { - Map_index_set(self, key, value); - return ST_CONTINUE; -} - -// Used only internally -- shared by #merge and #initialize. -VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) { - if (TYPE(hashmap) == T_HASH) { - rb_hash_foreach(hashmap, merge_into_self_callback, _self); - } else if (RB_TYPE_P(hashmap, T_DATA) && RTYPEDDATA_P(hashmap) && - RTYPEDDATA_TYPE(hashmap) == &Map_type) { - - Map* self = ruby_to_Map(_self); - Map* other = ruby_to_Map(hashmap); - upb_strtable_iter it; - - if (self->key_type != other->key_type || - self->value_type != other->value_type || - self->value_type_class != other->value_type_class) { - rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types"); - } - - for (upb_strtable_begin(&it, &other->table); - !upb_strtable_done(&it); - upb_strtable_next(&it)) { - - // Replace any existing value by issuing a 'remove' operation first. - upb_value v; - upb_value oldv; - upb_strtable_remove2(&self->table, - upb_strtable_iter_key(&it), - upb_strtable_iter_keylength(&it), - &oldv); - - v = upb_strtable_iter_value(&it); - upb_strtable_insert2(&self->table, - upb_strtable_iter_key(&it), - upb_strtable_iter_keylength(&it), - v); - } - } else { - rb_raise(rb_eArgError, "Unknown type merging into Map"); - } - return _self; -} - -// Internal method: map iterator initialization (used for serialization). -void Map_begin(VALUE _self, Map_iter* iter) { - Map* self = ruby_to_Map(_self); - iter->self = self; - upb_strtable_begin(&iter->it, &self->table); -} - -void Map_next(Map_iter* iter) { - upb_strtable_next(&iter->it); -} - -bool Map_done(Map_iter* iter) { - return upb_strtable_done(&iter->it); -} - -VALUE Map_iter_key(Map_iter* iter) { - return table_key_to_ruby( - iter->self, - upb_strtable_iter_key(&iter->it), - upb_strtable_iter_keylength(&iter->it)); -} - -VALUE Map_iter_value(Map_iter* iter) { - upb_value v = upb_strtable_iter_value(&iter->it); - void* mem = value_memory(&v); - return native_slot_get(iter->self->value_type, - iter->self->value_type_class, - mem); -} - void Map_register(VALUE module) { VALUE klass = rb_define_class_under(module, "Map", rb_cObject); rb_define_alloc_func(klass, Map_alloc); - cMap = klass; rb_gc_register_address(&cMap); + cMap = klass; rb_define_method(klass, "initialize", Map_init, -1); rb_define_method(klass, "each", Map_each, 0); @@ -832,8 +679,8 @@ void Map_register(VALUE module) { rb_define_method(klass, "length", Map_length, 0); rb_define_method(klass, "dup", Map_dup, 0); rb_define_method(klass, "==", Map_eq, 1); + rb_define_method(klass, "freeze", Map_freeze, 0); rb_define_method(klass, "hash", Map_hash, 0); - rb_define_method(klass, "to_hash", Map_to_h, 0); rb_define_method(klass, "to_h", Map_to_h, 0); rb_define_method(klass, "inspect", Map_inspect, 0); rb_define_method(klass, "merge", Map_merge, 1); diff --git a/ruby/ext/google/protobuf_c/map.h b/ruby/ext/google/protobuf_c/map.h new file mode 100644 index 0000000000000..1b840c3da77e8 --- /dev/null +++ b/ruby/ext/google/protobuf_c/map.h @@ -0,0 +1,66 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef RUBY_PROTOBUF_MAP_H_ +#define RUBY_PROTOBUF_MAP_H_ + +#include + +#include "protobuf.h" +#include "ruby-upb.h" + +// Returns a Ruby wrapper object for the given map, which will be created if +// one does not exist already. +VALUE Map_GetRubyWrapper(upb_map *map, upb_fieldtype_t key_type, + TypeInfo value_type, VALUE arena); + +// Gets the underlying upb_map for this Ruby map object, which must have +// key/value type that match |field|. If this is not a map or the type doesn't +// match, raises an exception. +const upb_map *Map_GetUpbMap(VALUE val, const upb_fielddef *field); + +// Implements #inspect for this map by appending its contents to |b|. +void Map_Inspect(StringBuilder *b, const upb_map *map, upb_fieldtype_t key_type, + TypeInfo val_type); + +// Returns a new Hash object containing the contents of this Map. +VALUE Map_CreateHash(const upb_map* map, upb_fieldtype_t key_type, + TypeInfo val_info); + +// Returns a deep copy of this Map object. +VALUE Map_deep_copy(VALUE obj); + +// Ruby class of Google::Protobuf::Map. +extern VALUE cMap; + +// Call at startup to register all types in this module. +void Map_register(VALUE module); + +#endif // RUBY_PROTOBUF_MAP_H_ diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c index 299111404db66..22a21c129e6e5 100644 --- a/ruby/ext/google/protobuf_c/message.c +++ b/ruby/ext/google/protobuf_c/message.c @@ -28,90 +28,369 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include "message.h" + +#include "convert.h" +#include "defs.h" +#include "map.h" #include "protobuf.h" +#include "repeated_field.h" +#include "third_party/wyhash/wyhash.h" -// ----------------------------------------------------------------------------- -// Class/module creation from msgdefs and enumdefs, respectively. -// ----------------------------------------------------------------------------- +static VALUE cParseError = Qnil; +static ID descriptor_instancevar_interned; -void* Message_data(void* msg) { - return ((uint8_t *)msg) + sizeof(MessageHeader); +static VALUE initialize_rb_class_with_no_args(VALUE klass) { + return rb_funcall(klass, rb_intern("new"), 0); } -void Message_mark(void* _self) { - MessageHeader* self = (MessageHeader *)_self; - layout_mark(self->descriptor->layout, Message_data(self)); +VALUE MessageOrEnum_GetDescriptor(VALUE klass) { + return rb_ivar_get(klass, descriptor_instancevar_interned); } -void Message_free(void* self) { - xfree(self); +// ----------------------------------------------------------------------------- +// Class/module creation from msgdefs and enumdefs, respectively. +// ----------------------------------------------------------------------------- + +typedef struct { + VALUE arena; + const upb_msg* msg; // Can get as mutable when non-frozen. + const upb_msgdef* msgdef; // kept alive by self.class.descriptor reference. +} Message; + +static void Message_mark(void* _self) { + Message* self = (Message *)_self; + rb_gc_mark(self->arena); } -rb_data_type_t Message_type = { +static rb_data_type_t Message_type = { "Message", - { Message_mark, Message_free, NULL }, + { Message_mark, RUBY_DEFAULT_FREE, NULL }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, }; -VALUE Message_alloc(VALUE klass) { +static Message* ruby_to_Message(VALUE msg_rb) { + Message* msg; + TypedData_Get_Struct(msg_rb, Message, &Message_type, msg); + return msg; +} + +static VALUE Message_alloc(VALUE klass) { VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); - Descriptor* desc = ruby_to_Descriptor(descriptor); - MessageHeader* msg = (MessageHeader*)ALLOC_N( - uint8_t, sizeof(MessageHeader) + desc->layout->size); + Message* msg = ALLOC(Message); VALUE ret; - memset(Message_data(msg), 0, desc->layout->size); + msg->msgdef = Descriptor_GetMsgDef(descriptor); + msg->arena = Qnil; + msg->msg = NULL; - // We wrap first so that everything in the message object is GC-rooted in case - // a collection happens during object creation in layout_init(). ret = TypedData_Wrap_Struct(klass, &Message_type, msg); - msg->descriptor = desc; rb_ivar_set(ret, descriptor_instancevar_interned, descriptor); - layout_init(desc->layout, Message_data(msg)); - return ret; } -static VALUE which_oneof_field(MessageHeader* self, const upb_oneofdef* o) { - upb_oneof_iter it; - size_t case_ofs; - uint32_t oneof_case; - const upb_fielddef* first_field; - const upb_fielddef* f; +const upb_msg *Message_Get(VALUE msg_rb, const upb_msgdef **m) { + Message* msg = ruby_to_Message(msg_rb); + if (m) *m = msg->msgdef; + return msg->msg; +} - // If no fields in the oneof, always nil. - if (upb_oneofdef_numfields(o) == 0) { - return Qnil; +upb_msg *Message_GetMutable(VALUE msg_rb, const upb_msgdef **m) { + rb_check_frozen(msg_rb); + return (upb_msg*)Message_Get(msg_rb, m); +} + +void Message_InitPtr(VALUE self_, upb_msg *msg, VALUE arena) { + Message* self = ruby_to_Message(self_); + self->msg = msg; + self->arena = arena; + ObjectCache_Add(msg, self_, Arena_get(arena)); +} + +VALUE Message_GetArena(VALUE msg_rb) { + Message* msg = ruby_to_Message(msg_rb); + return msg->arena; +} + +void Message_CheckClass(VALUE klass) { + if (rb_get_alloc_func(klass) != &Message_alloc) { + rb_raise(rb_eArgError, + "Message class was not returned by the DescriptorPool."); } - // Grab the first field in the oneof so we can get its layout info to find the - // oneof_case field. - upb_oneof_begin(&it, o); - assert(!upb_oneof_done(&it)); - first_field = upb_oneof_iter_field(&it); - assert(upb_fielddef_containingoneof(first_field) != NULL); +} - case_ofs = - self->descriptor->layout-> - fields[upb_fielddef_index(first_field)].case_offset; - oneof_case = *((uint32_t*)((char*)Message_data(self) + case_ofs)); +VALUE Message_GetRubyWrapper(upb_msg* msg, const upb_msgdef* m, VALUE arena) { + if (msg == NULL) return Qnil; - if (oneof_case == ONEOF_CASE_NONE) { - return Qnil; + VALUE val = ObjectCache_Get(msg); + + if (val == Qnil) { + VALUE klass = Descriptor_DefToClass(m); + val = Message_alloc(klass); + Message_InitPtr(val, msg, arena); + } + + return val; +} + +void Message_PrintMessage(StringBuilder* b, const upb_msg* msg, + const upb_msgdef* m) { + bool first = true; + int n = upb_msgdef_fieldcount(m); + VALUE klass = Descriptor_DefToClass(m); + StringBuilder_Printf(b, "<%s: ", rb_class2name(klass)); + + for (int i = 0; i < n; i++) { + const upb_fielddef* field = upb_msgdef_field(m, i); + + if (upb_fielddef_haspresence(field) && !upb_msg_has(msg, field)) { + continue; + } + + if (!first) { + StringBuilder_Printf(b, ", "); + } else { + first = false; + } + + upb_msgval msgval = upb_msg_get(msg, field); + + StringBuilder_Printf(b, "%s: ", upb_fielddef_name(field)); + + if (upb_fielddef_ismap(field)) { + const upb_msgdef* entry_m = upb_fielddef_msgsubdef(field); + const upb_fielddef* key_f = upb_msgdef_itof(entry_m, 1); + const upb_fielddef* val_f = upb_msgdef_itof(entry_m, 2); + TypeInfo val_info = TypeInfo_get(val_f); + Map_Inspect(b, msgval.map_val, upb_fielddef_type(key_f), val_info); + } else if (upb_fielddef_isseq(field)) { + RepeatedField_Inspect(b, msgval.array_val, TypeInfo_get(field)); + } else { + StringBuilder_PrintMsgval(b, msgval, TypeInfo_get(field)); + } + } + + StringBuilder_Printf(b, ">"); +} + +// Helper functions for #method_missing //////////////////////////////////////// + +enum { + METHOD_UNKNOWN = 0, + METHOD_GETTER = 1, + METHOD_SETTER = 2, + METHOD_CLEAR = 3, + METHOD_PRESENCE = 4, + METHOD_ENUM_GETTER = 5, + METHOD_WRAPPER_GETTER = 6, + METHOD_WRAPPER_SETTER = 7 +}; + +// Check if the field is a well known wrapper type +static bool IsWrapper(const upb_fielddef* f) { + return upb_fielddef_issubmsg(f) && + upb_msgdef_iswrapper(upb_fielddef_msgsubdef(f)); +} + +static bool Match(const upb_msgdef* m, const char* name, const upb_fielddef** f, + const upb_oneofdef** o, const char* prefix, + const char* suffix) { + size_t sp = strlen(prefix); + size_t ss = strlen(suffix); + size_t sn = strlen(name); + + if (sn <= sp + ss) return false; + + if (memcmp(name, prefix, sp) != 0 || + memcmp(name + sn - ss, suffix, ss) != 0) { + return false; + } + + return upb_msgdef_lookupname(m, name + sp, sn - sp - ss, f, o); +} + +static int extract_method_call(VALUE method_name, Message* self, + const upb_fielddef** f, const upb_oneofdef** o) { + const upb_msgdef* m = self->msgdef; + const char* name; + + Check_Type(method_name, T_SYMBOL); + name = rb_id2name(SYM2ID(method_name)); + + if (Match(m, name, f, o, "", "")) return METHOD_GETTER; + if (Match(m, name, f, o, "", "=")) return METHOD_SETTER; + if (Match(m, name, f, o, "clear_", "")) return METHOD_CLEAR; + if (Match(m, name, f, o, "has_", "?") && + (*o || (*f && upb_fielddef_haspresence(*f)))) { + // Disallow oneof hazzers for proto3. + // TODO(haberman): remove this test when we are enabling oneof hazzers for + // proto3. + if (*f && !upb_fielddef_issubmsg(*f) && + upb_fielddef_realcontainingoneof(*f) && + upb_msgdef_syntax(upb_fielddef_containingtype(*f)) != + UPB_SYNTAX_PROTO2) { + return METHOD_UNKNOWN; + } + return METHOD_PRESENCE; + } + if (Match(m, name, f, o, "", "_as_value") && *f && !upb_fielddef_isseq(*f) && + IsWrapper(*f)) { + return METHOD_WRAPPER_GETTER; + } + if (Match(m, name, f, o, "", "_as_value=") && *f && !upb_fielddef_isseq(*f) && + IsWrapper(*f)) { + return METHOD_WRAPPER_SETTER; + } + if (Match(m, name, f, o, "", "_const") && *f && + upb_fielddef_type(*f) == UPB_TYPE_ENUM) { + return METHOD_ENUM_GETTER; } - // oneof_case is a field index, so find that field. - f = upb_oneofdef_itof(o, oneof_case); - assert(f != NULL); + return METHOD_UNKNOWN; +} - return ID2SYM(rb_intern(upb_fielddef_name(f))); +static VALUE Message_oneof_accessor(VALUE _self, const upb_oneofdef* o, + int accessor_type) { + Message* self = ruby_to_Message(_self); + const upb_fielddef* oneof_field = upb_msg_whichoneof(self->msg, o); + + switch (accessor_type) { + case METHOD_PRESENCE: + return oneof_field == NULL ? Qfalse : Qtrue; + case METHOD_CLEAR: + if (oneof_field != NULL) { + upb_msg_clearfield(Message_GetMutable(_self, NULL), oneof_field); + } + return Qnil; + case METHOD_GETTER: + return oneof_field == NULL + ? Qnil + : ID2SYM(rb_intern(upb_fielddef_name(oneof_field))); + case METHOD_SETTER: + rb_raise(rb_eRuntimeError, "Oneof accessors are read-only."); + } + rb_raise(rb_eRuntimeError, "Invalid access of oneof field."); +} + +static void Message_setfield(upb_msg* msg, const upb_fielddef* f, VALUE val, + upb_arena* arena) { + upb_msgval msgval; + if (upb_fielddef_ismap(f)) { + msgval.map_val = Map_GetUpbMap(val, f); + } else if (upb_fielddef_isseq(f)) { + msgval.array_val = RepeatedField_GetUpbArray(val, f); + } else { + if (val == Qnil && + (upb_fielddef_issubmsg(f) || upb_fielddef_realcontainingoneof(f))) { + upb_msg_clearfield(msg, f); + return; + } + msgval = + Convert_RubyToUpb(val, upb_fielddef_name(f), TypeInfo_get(f), arena); + } + upb_msg_set(msg, f, msgval, arena); +} + +static VALUE Message_field_accessor(VALUE _self, const upb_fielddef* f, + int accessor_type, int argc, VALUE* argv) { + upb_arena *arena = Arena_get(Message_GetArena(_self)); + + switch (accessor_type) { + case METHOD_SETTER: + Message_setfield(Message_GetMutable(_self, NULL), f, argv[1], arena); + return Qnil; + case METHOD_CLEAR: + upb_msg_clearfield(Message_GetMutable(_self, NULL), f); + return Qnil; + case METHOD_PRESENCE: + if (!upb_fielddef_haspresence(f)) { + rb_raise(rb_eRuntimeError, "Field does not have presence."); + } + return upb_msg_has(Message_Get(_self, NULL), f); + case METHOD_WRAPPER_GETTER: { + Message* self = ruby_to_Message(_self); + if (upb_msg_has(self->msg, f)) { + PBRUBY_ASSERT(upb_fielddef_issubmsg(f) && !upb_fielddef_isseq(f)); + upb_msgval wrapper = upb_msg_get(self->msg, f); + const upb_msgdef *wrapper_m = upb_fielddef_msgsubdef(f); + const upb_fielddef *value_f = upb_msgdef_itof(wrapper_m, 1); + upb_msgval value = upb_msg_get(wrapper.msg_val, value_f); + return Convert_UpbToRuby(value, TypeInfo_get(value_f), self->arena); + } else { + return Qnil; + } + } + case METHOD_WRAPPER_SETTER: { + upb_msg *msg = Message_GetMutable(_self, NULL); + if (argv[1] == Qnil) { + upb_msg_clearfield(msg, f); + } else { + const upb_fielddef *val_f = upb_msgdef_itof(upb_fielddef_msgsubdef(f), 1); + upb_msgval msgval = Convert_RubyToUpb(argv[1], upb_fielddef_name(f), + TypeInfo_get(val_f), arena); + upb_msg *wrapper = upb_msg_mutable(msg, f, arena).msg; + upb_msg_set(wrapper, val_f, msgval, arena); + } + return Qnil; + } + case METHOD_ENUM_GETTER: { + upb_msgval msgval = upb_msg_get(Message_Get(_self, NULL), f); + + if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) { + // Map repeated fields to a new type with ints + VALUE arr = rb_ary_new(); + size_t i, n = upb_array_size(msgval.array_val); + for (i = 0; i < n; i++) { + upb_msgval elem = upb_array_get(msgval.array_val, i); + rb_ary_push(arr, INT2NUM(elem.int32_val)); + } + return arr; + } else { + return INT2NUM(msgval.int32_val); + } + } + case METHOD_GETTER: { + Message* self = ruby_to_Message(_self); + // This is a special-case: upb_msg_mutable() for map & array are logically + // const (they will not change what is serialized) but physically + // non-const, as they do allocate a repeated field or map. The logical + // constness means it's ok to do even if the message is frozen. + upb_msg *msg = (upb_msg*)self->msg; + if (upb_fielddef_ismap(f)) { + upb_map *map = upb_msg_mutable(msg, f, arena).map; + const upb_fielddef *key_f = map_field_key(f); + const upb_fielddef *val_f = map_field_value(f); + upb_fieldtype_t key_type = upb_fielddef_type(key_f); + TypeInfo value_type_info = TypeInfo_get(val_f); + return Map_GetRubyWrapper(map, key_type, value_type_info, self->arena); + } else if (upb_fielddef_isseq(f)) { + upb_array *arr = upb_msg_mutable(msg, f, arena).array; + return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena); + } else if (upb_fielddef_issubmsg(f)) { + if (!upb_msg_has(self->msg, f)) return Qnil; + upb_msg *submsg = upb_msg_mutable(msg, f, arena).msg; + const upb_msgdef *m = upb_fielddef_msgsubdef(f); + return Message_GetRubyWrapper(submsg, m, self->arena); + } else { + upb_msgval msgval = upb_msg_get(self->msg, f); + return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena); + } + default: + rb_raise(rb_eRuntimeError, "Internal error, no such accessor: %d", + accessor_type); + } + } } /* * call-seq: * Message.method_missing(*args) * - * Provides accessors and setters for message fields according to their field - * names. For any field whose name does not conflict with a built-in method, an + * Provides accessors and setters and methods to clear and check for presence of + * message fields according to their field names. + * + * For any field whose name does not conflict with a built-in method, an * accessor is provided with the same name as the field, and a setter is * provided with the name of the field plus the '=' suffix. Thus, given a * message instance 'msg' with field 'foo', the following code is valid: @@ -122,145 +401,214 @@ static VALUE which_oneof_field(MessageHeader* self, const upb_oneofdef* o) { * This method also provides read-only accessors for oneofs. If a oneof exists * with name 'my_oneof', then msg.my_oneof will return a Ruby symbol equal to * the name of the field in that oneof that is currently set, or nil if none. + * + * It also provides methods of the form 'clear_fieldname' to clear the value + * of the field 'fieldname'. For basic data types, this will set the default + * value of the field. + * + * Additionally, it provides methods of the form 'has_fieldname?', which returns + * true if the field 'fieldname' is set in the message object, else false. For + * 'proto3' syntax, calling this for a basic type field will result in an error. */ -VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) { - MessageHeader* self; - VALUE method_name, method_str; - char* name; - size_t name_len; - bool setter; +static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) { + Message* self = ruby_to_Message(_self); const upb_oneofdef* o; const upb_fielddef* f; + int accessor_type; - TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); if (argc < 1) { rb_raise(rb_eArgError, "Expected method name as first argument."); } - method_name = argv[0]; - if (!SYMBOL_P(method_name)) { - rb_raise(rb_eArgError, "Expected symbol as method name."); - } - method_str = rb_id2str(SYM2ID(method_name)); - name = RSTRING_PTR(method_str); - name_len = RSTRING_LEN(method_str); - setter = false; - // Setters have names that end in '='. - if (name[name_len - 1] == '=') { - setter = true; - name_len--; - } + accessor_type = extract_method_call(argv[0], self, &f, &o); - // See if this name corresponds to either a oneof or field in this message. - if (!upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len, &f, - &o)) { - return rb_call_super(argc, argv); + if (accessor_type == METHOD_UNKNOWN) return rb_call_super(argc, argv); + + // Validate argument count. + switch (accessor_type) { + case METHOD_SETTER: + case METHOD_WRAPPER_SETTER: + if (argc != 2) { + rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc); + } + rb_check_frozen(_self); + break; + default: + if (argc != 1) { + rb_raise(rb_eArgError, "Expected 1 argument, received %d", argc); + } + break; } + // Dispatch accessor. if (o != NULL) { - // This is a oneof -- return which field inside the oneof is set. - if (setter) { - rb_raise(rb_eRuntimeError, "Oneof accessors are read-only."); - } - return which_oneof_field(self, o); + return Message_oneof_accessor(_self, o, accessor_type); } else { - // This is a field -- get or set the field's value. - assert(f); - if (setter) { - if (argc < 2) { - rb_raise(rb_eArgError, "No value provided to setter."); - } - layout_set(self->descriptor->layout, Message_data(self), f, argv[1]); - return Qnil; - } else { - return layout_get(self->descriptor->layout, Message_data(self), f); - } + return Message_field_accessor(_self, f, accessor_type, argc, argv); } } -VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) { - MessageHeader* self; - VALUE method_name, method_str; - char* name; - size_t name_len; - bool setter; +static VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) { + Message* self = ruby_to_Message(_self); const upb_oneofdef* o; const upb_fielddef* f; + int accessor_type; - TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); if (argc < 1) { rb_raise(rb_eArgError, "Expected method name as first argument."); } - method_name = argv[0]; - if (!SYMBOL_P(method_name)) { - rb_raise(rb_eArgError, "Expected symbol as method name."); + + accessor_type = extract_method_call(argv[0], self, &f, &o); + + if (accessor_type == METHOD_UNKNOWN) { + return rb_call_super(argc, argv); + } else if (o != NULL) { + return accessor_type == METHOD_SETTER ? Qfalse : Qtrue; + } else { + return Qtrue; } - method_str = rb_id2str(SYM2ID(method_name)); - name = RSTRING_PTR(method_str); - name_len = RSTRING_LEN(method_str); - setter = false; +} - // Setters have names that end in '='. - if (name[name_len - 1] == '=') { - setter = true; - name_len--; +void Message_InitFromValue(upb_msg* msg, const upb_msgdef* m, VALUE val, + upb_arena* arena); + +typedef struct { + upb_map *map; + TypeInfo key_type; + TypeInfo val_type; + upb_arena *arena; +} MapInit; + +static int Map_initialize_kwarg(VALUE key, VALUE val, VALUE _self) { + MapInit *map_init = (MapInit*)_self; + upb_msgval k, v; + k = Convert_RubyToUpb(key, "", map_init->key_type, NULL); + + if (map_init->val_type.type == UPB_TYPE_MESSAGE && TYPE(val) == T_HASH) { + upb_msg *msg = upb_msg_new(map_init->val_type.def.msgdef, map_init->arena); + Message_InitFromValue(msg, map_init->val_type.def.msgdef, val, + map_init->arena); + v.msg_val = msg; + } else { + v = Convert_RubyToUpb(val, "", map_init->val_type, map_init->arena); } + upb_map_set(map_init->map, k, v, map_init->arena); + return ST_CONTINUE; +} - // See if this name corresponds to either a oneof or field in this message. - if (!upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len, &f, - &o)) { - return rb_call_super(argc, argv); +static void Map_InitFromValue(upb_map* map, const upb_fielddef* f, VALUE val, + upb_arena* arena) { + const upb_msgdef* entry_m = upb_fielddef_msgsubdef(f); + const upb_fielddef* key_f = upb_msgdef_itof(entry_m, 1); + const upb_fielddef* val_f = upb_msgdef_itof(entry_m, 2); + if (TYPE(val) != T_HASH) { + rb_raise(rb_eArgError, + "Expected Hash object as initializer value for map field '%s' " + "(given %s).", + upb_fielddef_name(f), rb_class2name(CLASS_OF(val))); } - if (o != NULL) { - return setter ? Qfalse : Qtrue; + MapInit map_init = {map, TypeInfo_get(key_f), TypeInfo_get(val_f), arena}; + rb_hash_foreach(val, Map_initialize_kwarg, (VALUE)&map_init); +} + +static upb_msgval MessageValue_FromValue(VALUE val, TypeInfo info, + upb_arena* arena) { + if (info.type == UPB_TYPE_MESSAGE) { + upb_msgval msgval; + upb_msg* msg = upb_msg_new(info.def.msgdef, arena); + Message_InitFromValue(msg, info.def.msgdef, val, arena); + msgval.msg_val = msg; + return msgval; + } else { + return Convert_RubyToUpb(val, "", info, arena); } - return Qtrue; } -int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) { - MessageHeader* self; - VALUE method_str; - char* name; - const upb_fielddef* f; - TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); +static void RepeatedField_InitFromValue(upb_array* arr, const upb_fielddef* f, + VALUE val, upb_arena* arena) { + TypeInfo type_info = TypeInfo_get(f); - if (!SYMBOL_P(key)) { + if (TYPE(val) != T_ARRAY) { rb_raise(rb_eArgError, - "Expected symbols as hash keys in initialization map."); + "Expected array as initializer value for repeated field '%s' (given %s).", + upb_fielddef_name(f), rb_class2name(CLASS_OF(val))); + } + + for (int i = 0; i < RARRAY_LEN(val); i++) { + VALUE entry = rb_ary_entry(val, i); + upb_msgval msgval; + if (upb_fielddef_issubmsg(f) && TYPE(entry) == T_HASH) { + msgval = MessageValue_FromValue(entry, type_info, arena); + } else { + msgval = Convert_RubyToUpb(entry, upb_fielddef_name(f), type_info, arena); + } + upb_array_append(arr, msgval, arena); } +} + +static void Message_InitFieldFromValue(upb_msg* msg, const upb_fielddef* f, + VALUE val, upb_arena* arena) { + if (TYPE(val) == T_NIL) return; + + if (upb_fielddef_ismap(f)) { + upb_map *map = upb_msg_mutable(msg, f, arena).map; + Map_InitFromValue(map, f, val, arena); + } else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) { + upb_array *arr = upb_msg_mutable(msg, f, arena).array; + RepeatedField_InitFromValue(arr, f, val, arena); + } else if (upb_fielddef_issubmsg(f)) { + if (TYPE(val) == T_HASH) { + upb_msg *submsg = upb_msg_mutable(msg, f, arena).msg; + Message_InitFromValue(submsg, upb_fielddef_msgsubdef(f), val, arena); + } else { + Message_setfield(msg, f, val, arena); + } + } else { + upb_msgval msgval = + Convert_RubyToUpb(val, upb_fielddef_name(f), TypeInfo_get(f), arena); + upb_msg_set(msg, f, msgval, arena); + } +} + +typedef struct { + upb_msg *msg; + const upb_msgdef *msgdef; + upb_arena *arena; +} MsgInit; + +static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) { + MsgInit *msg_init = (MsgInit*)_self; + const char *name; + + if (TYPE(key) == T_STRING) { + name = RSTRING_PTR(key); + } else if (TYPE(key) == T_SYMBOL) { + name = RSTRING_PTR(rb_id2str(SYM2ID(key))); + } else { + rb_raise(rb_eArgError, + "Expected string or symbols as hash keys when initializing proto from hash."); + } + + const upb_fielddef* f = upb_msgdef_ntofz(msg_init->msgdef, name); - method_str = rb_id2str(SYM2ID(key)); - name = RSTRING_PTR(method_str); - f = upb_msgdef_ntofz(self->descriptor->msgdef, name); if (f == NULL) { rb_raise(rb_eArgError, "Unknown field name '%s' in initialization map entry.", name); } - if (is_map_field(f)) { - VALUE map; - - if (TYPE(val) != T_HASH) { - rb_raise(rb_eArgError, - "Expected Hash object as initializer value for map field '%s'.", name); - } - map = layout_get(self->descriptor->layout, Message_data(self), f); - Map_merge_into_self(map, val); - } else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) { - VALUE ary; + Message_InitFieldFromValue(msg_init->msg, f, val, msg_init->arena); + return ST_CONTINUE; +} - if (TYPE(val) != T_ARRAY) { - rb_raise(rb_eArgError, - "Expected array as initializer value for repeated field '%s'.", name); - } - ary = layout_get(self->descriptor->layout, Message_data(self), f); - for (int i = 0; i < RARRAY_LEN(val); i++) { - RepeatedField_push(ary, rb_ary_entry(val, i)); - } +void Message_InitFromValue(upb_msg* msg, const upb_msgdef* m, VALUE val, + upb_arena* arena) { + MsgInit msg_init = {msg, m, arena}; + if (TYPE(val) == T_HASH) { + rb_hash_foreach(val, Message_initialize_kwarg, (VALUE)&msg_init); } else { - layout_set(self->descriptor->layout, Message_data(self), f, val); + rb_raise(rb_eArgError, "Expected hash arguments or message, not %s", + rb_class2name(CLASS_OF(val))); } - return 0; } /* @@ -275,8 +623,13 @@ int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) { * have been added to a pool. The method definitions described here on the * Message class are provided on each concrete message class. */ -VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) { - VALUE hash_args; +static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) { + Message* self = ruby_to_Message(_self); + VALUE arena_rb = Arena_new(); + upb_arena *arena = Arena_get(arena_rb); + upb_msg *msg = upb_msg_new(self->msgdef, arena); + + Message_InitPtr(_self, msg, arena_rb); if (argc == 0) { return Qnil; @@ -284,12 +637,7 @@ VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) { if (argc != 1) { rb_raise(rb_eArgError, "Expected 0 or 1 arguments."); } - hash_args = argv[0]; - if (TYPE(hash_args) != T_HASH) { - rb_raise(rb_eArgError, "Expected hash arguments."); - } - - rb_hash_foreach(hash_args, Message_initialize_kwarg, _self); + Message_InitFromValue((upb_msg*)self->msg, self->msgdef, argv[0], arena); return Qnil; } @@ -299,37 +647,40 @@ VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) { * * Performs a shallow copy of this message and returns the new copy. */ -VALUE Message_dup(VALUE _self) { - MessageHeader* self; - VALUE new_msg; - MessageHeader* new_msg_self; - TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); - - new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self)); - TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self); - - layout_dup(self->descriptor->layout, - Message_data(new_msg_self), - Message_data(self)); - +static VALUE Message_dup(VALUE _self) { + Message* self = ruby_to_Message(_self); + VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self)); + Message* new_msg_self = ruby_to_Message(new_msg); + size_t size = upb_msgdef_layout(self->msgdef)->size; + + // TODO(copy unknown fields?) + // TODO(use official upb msg copy function) + memcpy((upb_msg*)new_msg_self->msg, self->msg, size); + upb_arena_fuse(Arena_get(new_msg_self->arena), Arena_get(self->arena)); return new_msg; } -// Internal only; used by Google::Protobuf.deep_copy. -VALUE Message_deep_copy(VALUE _self) { - MessageHeader* self; - MessageHeader* new_msg_self; - VALUE new_msg; - TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); +// Support function for Message_eq, and also used by other #eq functions. +bool Message_Equal(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m) { + if (m1 == m2) return true; - new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self)); - TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self); + size_t size1, size2; + int encode_opts = UPB_ENCODE_SKIPUNKNOWN | UPB_ENCODE_DETERMINISTIC; + upb_arena *arena_tmp = upb_arena_new(); + const upb_msglayout *layout = upb_msgdef_layout(m); - layout_deep_copy(self->descriptor->layout, - Message_data(new_msg_self), - Message_data(self)); + // Compare deterministically serialized payloads with no unknown fields. + char *data1 = upb_encode_ex(m1, layout, encode_opts, arena_tmp, &size1); + char *data2 = upb_encode_ex(m2, layout, encode_opts, arena_tmp, &size2); - return new_msg; + if (data1 && data2) { + bool ret = (size1 == size2) && (memcmp(data1, data2, size1) == 0); + upb_arena_free(arena_tmp); + return ret; + } else { + upb_arena_free(arena_tmp); + rb_raise(cParseError, "Error comparing messages"); + } } /* @@ -341,22 +692,37 @@ VALUE Message_deep_copy(VALUE _self) { * method's semantics (a more efficient comparison may actually be done if the * field is of a primitive type). */ -VALUE Message_eq(VALUE _self, VALUE _other) { - MessageHeader* self; - MessageHeader* other; +static VALUE Message_eq(VALUE _self, VALUE _other) { if (TYPE(_self) != TYPE(_other)) { return Qfalse; } - TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); - TypedData_Get_Struct(_other, MessageHeader, &Message_type, other); - if (self->descriptor != other->descriptor) { - return Qfalse; - } + Message* self = ruby_to_Message(_self); + Message* other = ruby_to_Message(_other); + + return Message_Equal(self->msg, other->msg, self->msgdef) + ? Qtrue + : Qfalse; +} - return layout_eq(self->descriptor->layout, - Message_data(self), - Message_data(other)); +uint64_t Message_Hash(const upb_msg* msg, const upb_msgdef* m, uint64_t seed) { + upb_arena *arena = upb_arena_new(); + const char *data; + size_t size; + + // Hash a deterministically serialized payloads with no unknown fields. + data = upb_encode_ex(msg, upb_msgdef_layout(m), + UPB_ENCODE_SKIPUNKNOWN | UPB_ENCODE_DETERMINISTIC, arena, + &size); + + if (data) { + uint64_t ret = wyhash(data, size, seed, _wyp); + upb_arena_free(arena); + return ret; + } else { + upb_arena_free(arena); + rb_raise(cParseError, "Error calculating hash"); + } } /* @@ -365,11 +731,9 @@ VALUE Message_eq(VALUE _self, VALUE _other) { * * Returns a hash value that represents this message's field values. */ -VALUE Message_hash(VALUE _self) { - MessageHeader* self; - TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); - - return layout_hash(self->descriptor->layout, Message_data(self)); +static VALUE Message_hash(VALUE _self) { + Message* self = ruby_to_Message(_self); + return INT2FIX(Message_Hash(self->msg, self->msgdef, 0)); } /* @@ -380,55 +744,117 @@ VALUE Message_hash(VALUE _self) { * formatted as "". Each * field's value is represented according to its own #inspect method. */ -VALUE Message_inspect(VALUE _self) { - MessageHeader* self; - VALUE str; - TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); +static VALUE Message_inspect(VALUE _self) { + Message* self = ruby_to_Message(_self); - str = rb_str_new2("<"); - str = rb_str_append(str, rb_str_new2(rb_class2name(CLASS_OF(_self)))); - str = rb_str_cat2(str, ": "); - str = rb_str_append(str, layout_inspect( - self->descriptor->layout, Message_data(self))); - str = rb_str_cat2(str, ">"); - return str; + StringBuilder* builder = StringBuilder_New(); + Message_PrintMessage(builder, self->msg, self->msgdef); + VALUE ret = StringBuilder_ToRubyString(builder); + StringBuilder_Free(builder); + return ret; } -/* - * call-seq: - * Message.to_h => {} - * - * Returns the message as a Ruby Hash object, with keys as symbols. - */ -VALUE Message_to_h(VALUE _self) { - MessageHeader* self; - VALUE hash; - upb_msg_field_iter it; - TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); - - hash = rb_hash_new(); - - for (upb_msg_field_begin(&it, self->descriptor->msgdef); - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* field = upb_msg_iter_field(&it); - VALUE msg_value = layout_get(self->descriptor->layout, Message_data(self), - field); - VALUE msg_key = ID2SYM(rb_intern(upb_fielddef_name(field))); +// Support functions for Message_to_h ////////////////////////////////////////// + +static VALUE RepeatedField_CreateArray(const upb_array* arr, + TypeInfo type_info) { + int size = arr ? upb_array_size(arr) : 0; + VALUE ary = rb_ary_new2(size); + + for (int i = 0; i < size; i++) { + upb_msgval msgval = upb_array_get(arr, i); + VALUE val = Scalar_CreateHash(msgval, type_info); + rb_ary_push(ary, val); + } + + return ary; +} + +static VALUE Message_CreateHash(const upb_msg *msg, const upb_msgdef *m) { + if (!msg) return Qnil; + + VALUE hash = rb_hash_new(); + int n = upb_msgdef_fieldcount(m); + bool is_proto2; + + // We currently have a few behaviors that are specific to proto2. + // This is unfortunate, we should key behaviors off field attributes (like + // whether a field has presence), not proto2 vs. proto3. We should see if we + // can change this without breaking users. + is_proto2 = upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2; + + for (int i = 0; i < n; i++) { + const upb_fielddef* field = upb_msgdef_field(m, i); + TypeInfo type_info = TypeInfo_get(field); + upb_msgval msgval; + VALUE msg_value; + VALUE msg_key; + + // Do not include fields that are not present (oneof or optional fields). + if (is_proto2 && upb_fielddef_haspresence(field) && + !upb_msg_has(msg, field)) { + continue; + } + + msg_key = ID2SYM(rb_intern(upb_fielddef_name(field))); + msgval = upb_msg_get(msg, field); + + // Proto2 omits empty map/repeated filds also. + if (upb_fielddef_ismap(field)) { - msg_value = Map_to_h(msg_value); - } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - msg_value = RepeatedField_to_ary(msg_value); - } else if (msg_value != Qnil && - upb_fielddef_type(field) == UPB_TYPE_MESSAGE) { - msg_value = Message_to_h(msg_value); + const upb_msgdef *entry_m = upb_fielddef_msgsubdef(field); + const upb_fielddef *key_f = upb_msgdef_itof(entry_m, 1); + const upb_fielddef *val_f = upb_msgdef_itof(entry_m, 2); + upb_fieldtype_t key_type = upb_fielddef_type(key_f); + msg_value = Map_CreateHash(msgval.map_val, key_type, TypeInfo_get(val_f)); + } else if (upb_fielddef_isseq(field)) { + if (is_proto2 && + (!msgval.array_val || upb_array_size(msgval.array_val) == 0)) { + continue; + } + msg_value = RepeatedField_CreateArray(msgval.array_val, type_info); + } else { + msg_value = Scalar_CreateHash(msgval, type_info); } + rb_hash_aset(hash, msg_key, msg_value); } + return hash; } +VALUE Scalar_CreateHash(upb_msgval msgval, TypeInfo type_info) { + if (type_info.type == UPB_TYPE_MESSAGE) { + return Message_CreateHash(msgval.msg_val, type_info.def.msgdef); + } else { + return Convert_UpbToRuby(msgval, type_info, Qnil); + } +} +/* + * call-seq: + * Message.to_h => {} + * + * Returns the message as a Ruby Hash object, with keys as symbols. + */ +static VALUE Message_to_h(VALUE _self) { + Message* self = ruby_to_Message(_self); + return Message_CreateHash(self->msg, self->msgdef); +} + +/* + * call-seq: + * Message.freeze => self + * + * Freezes the message object. We have to intercept this so we can pin the + * Ruby object into memory so we don't forget it's frozen. + */ +static VALUE Message_freeze(VALUE _self) { + Message* self = ruby_to_Message(_self); + ObjectCache_Pin(self->msg, _self, Arena_get(self->arena)); + RB_OBJ_FREEZE(_self); + return _self; +} /* * call-seq: @@ -437,16 +863,20 @@ VALUE Message_to_h(VALUE _self) { * Accesses a field's value by field name. The provided field name should be a * string. */ -VALUE Message_index(VALUE _self, VALUE field_name) { - MessageHeader* self; +static VALUE Message_index(VALUE _self, VALUE field_name) { + Message* self = ruby_to_Message(_self); const upb_fielddef* field; - TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); + upb_msgval val; + Check_Type(field_name, T_STRING); - field = upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name)); + field = upb_msgdef_ntofz(self->msgdef, RSTRING_PTR(field_name)); + if (field == NULL) { return Qnil; } - return layout_get(self->descriptor->layout, Message_data(self), field); + + val = upb_msg_get(self->msg, field); + return Convert_UpbToRuby(val, TypeInfo_get(field), self->arena); } /* @@ -456,19 +886,208 @@ VALUE Message_index(VALUE _self, VALUE field_name) { * Sets a field's value by field name. The provided field name should be a * string. */ -VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) { - MessageHeader* self; - const upb_fielddef* field; - TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); +static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) { + Message* self = ruby_to_Message(_self); + const upb_fielddef* f; + upb_msgval val; + upb_arena *arena = Arena_get(self->arena); + Check_Type(field_name, T_STRING); - field = upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name)); - if (field == NULL) { + f = upb_msgdef_ntofz(self->msgdef, RSTRING_PTR(field_name)); + + if (f == NULL) { rb_raise(rb_eArgError, "Unknown field: %s", RSTRING_PTR(field_name)); } - layout_set(self->descriptor->layout, Message_data(self), field, value); + + val = Convert_RubyToUpb(value, upb_fielddef_name(f), TypeInfo_get(f), arena); + upb_msg_set(Message_GetMutable(_self, NULL), f, val, arena); + return Qnil; } +/* + * call-seq: + * MessageClass.decode(data) => message + * + * Decodes the given data (as a string containing bytes in protocol buffers wire + * format) under the interpretration given by this message class's definition + * and returns a message object with the corresponding field values. + */ +static VALUE Message_decode(VALUE klass, VALUE data) { + if (TYPE(data) != T_STRING) { + rb_raise(rb_eArgError, "Expected string for binary protobuf data."); + } + + VALUE msg_rb = initialize_rb_class_with_no_args(klass); + Message* msg = ruby_to_Message(msg_rb); + + if (!upb_decode(RSTRING_PTR(data), RSTRING_LEN(data), (upb_msg*)msg->msg, + upb_msgdef_layout(msg->msgdef), + Arena_get(msg->arena))) { + rb_raise(cParseError, "Error occurred during parsing"); + } + + return msg_rb; +} + +/* + * call-seq: + * MessageClass.decode_json(data, options = {}) => message + * + * Decodes the given data (as a string containing bytes in protocol buffers wire + * format) under the interpretration given by this message class's definition + * and returns a message object with the corresponding field values. + * + * @param options [Hash] options for the decoder + * ignore_unknown_fields: set true to ignore unknown fields (default is to + * raise an error) + */ +static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) { + VALUE data = argv[0]; + int options = 0; + upb_status status; + + // TODO(haberman): use this message's pool instead. + const upb_symtab *symtab = DescriptorPool_GetSymtab(generated_pool); + + if (argc < 1 || argc > 2) { + rb_raise(rb_eArgError, "Expected 1 or 2 arguments."); + } + + if (argc == 2) { + VALUE hash_args = argv[1]; + if (TYPE(hash_args) != T_HASH) { + rb_raise(rb_eArgError, "Expected hash arguments."); + } + + if (RTEST(rb_hash_lookup2( hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse))) { + options |= UPB_JSONDEC_IGNOREUNKNOWN; + } + } + + if (TYPE(data) != T_STRING) { + rb_raise(rb_eArgError, "Expected string for JSON data."); + } + + // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to + // convert, because string handlers pass data directly to message string + // fields. + + VALUE msg_rb = initialize_rb_class_with_no_args(klass); + Message* msg = ruby_to_Message(msg_rb); + + // We don't allow users to decode a wrapper type directly. + if (upb_msgdef_iswrapper(msg->msgdef)) { + rb_raise(rb_eRuntimeError, "Cannot parse a wrapper directly."); + } + + upb_status_clear(&status); + if (!upb_json_decode(RSTRING_PTR(data), RSTRING_LEN(data), (upb_msg*)msg->msg, + msg->msgdef, symtab, options, + Arena_get(msg->arena), &status)) { + rb_raise(cParseError, "Error occurred during parsing: %s", + upb_status_errmsg(&status)); + } + + return msg_rb; +} + +/* + * call-seq: + * MessageClass.encode(msg) => bytes + * + * Encodes the given message object to its serialized form in protocol buffers + * wire format. + */ +static VALUE Message_encode(VALUE klass, VALUE msg_rb) { + Message* msg = ruby_to_Message(msg_rb); + upb_arena *arena = upb_arena_new(); + const char *data; + size_t size; + + if (CLASS_OF(msg_rb) != klass) { + rb_raise(rb_eArgError, "Message of wrong type."); + } + + data = upb_encode(msg->msg, upb_msgdef_layout(msg->msgdef), arena, + &size); + + if (data) { + VALUE ret = rb_str_new(data, size); + rb_enc_associate(ret, rb_ascii8bit_encoding()); + upb_arena_free(arena); + return ret; + } else { + upb_arena_free(arena); + rb_raise(rb_eRuntimeError, "Exceeded maximum depth (possibly cycle)"); + } +} + +/* + * call-seq: + * MessageClass.encode_json(msg, options = {}) => json_string + * + * Encodes the given message object into its serialized JSON representation. + * @param options [Hash] options for the decoder + * preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase) + * emit_defaults: set true to emit 0/false values (default is to omit them) + */ +static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) { + Message* msg = ruby_to_Message(argv[0]); + int options = 0; + char buf[1024]; + size_t size; + upb_status status; + + // TODO(haberman): use this message's pool instead. + const upb_symtab *symtab = DescriptorPool_GetSymtab(generated_pool); + + if (argc < 1 || argc > 2) { + rb_raise(rb_eArgError, "Expected 1 or 2 arguments."); + } + + if (argc == 2) { + VALUE hash_args = argv[1]; + if (TYPE(hash_args) != T_HASH) { + rb_raise(rb_eArgError, "Expected hash arguments."); + } + + if (RTEST(rb_hash_lookup2(hash_args, + ID2SYM(rb_intern("preserve_proto_fieldnames")), + Qfalse))) { + options |= UPB_JSONENC_PROTONAMES; + } + + if (RTEST(rb_hash_lookup2(hash_args, ID2SYM(rb_intern("emit_defaults")), + Qfalse))) { + options |= UPB_JSONENC_EMITDEFAULTS; + } + } + + upb_status_clear(&status); + size = upb_json_encode(msg->msg, msg->msgdef, symtab, options, buf, + sizeof(buf), &status); + + if (!upb_ok(&status)) { + rb_raise(cParseError, "Error occurred during encoding: %s", + upb_status_errmsg(&status)); + } + + VALUE ret; + if (size >= sizeof(buf)) { + char* buf2 = malloc(size + 1); + upb_json_encode(msg->msg, msg->msgdef, symtab, options, buf2, size + 1, + &status); + ret = rb_str_new(buf2, size); + free(buf2); + } else { + ret = rb_str_new(buf, size); + } + + rb_enc_associate(ret, rb_utf8_encoding()); + return ret; +} + /* * call-seq: * Message.descriptor => descriptor @@ -476,22 +1095,15 @@ VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) { * Class method that returns the Descriptor instance corresponding to this * message class's type. */ -VALUE Message_descriptor(VALUE klass) { +static VALUE Message_descriptor(VALUE klass) { return rb_ivar_get(klass, descriptor_instancevar_interned); } -VALUE build_class_from_descriptor(Descriptor* desc) { +VALUE build_class_from_descriptor(VALUE descriptor) { const char *name; VALUE klass; - if (desc->layout == NULL) { - desc->layout = create_layout(desc->msgdef); - } - if (desc->fill_method == NULL) { - desc->fill_method = new_fillmsg_decodermethod(desc, &desc->fill_method); - } - - name = upb_msgdef_fullname(desc->msgdef); + name = upb_msgdef_fullname(Descriptor_GetMsgDef(descriptor)); if (name == NULL) { rb_raise(rb_eRuntimeError, "Descriptor does not have assigned name."); } @@ -501,13 +1113,12 @@ VALUE build_class_from_descriptor(Descriptor* desc) { // their own toplevel constant class name. rb_intern("Message"), rb_cObject); - rb_ivar_set(klass, descriptor_instancevar_interned, - get_def_obj(desc->msgdef)); + rb_ivar_set(klass, descriptor_instancevar_interned, descriptor); rb_define_alloc_func(klass, Message_alloc); rb_require("google/protobuf/message_exts"); - rb_include_module(klass, rb_eval_string("Google::Protobuf::MessageExts")); + rb_include_module(klass, rb_eval_string("::Google::Protobuf::MessageExts")); rb_extend_object( - klass, rb_eval_string("Google::Protobuf::MessageExts::ClassMethods")); + klass, rb_eval_string("::Google::Protobuf::MessageExts::ClassMethods")); rb_define_method(klass, "method_missing", Message_method_missing, -1); @@ -518,15 +1129,17 @@ VALUE build_class_from_descriptor(Descriptor* desc) { // Also define #clone so that we don't inherit Object#clone. rb_define_method(klass, "clone", Message_dup, 0); rb_define_method(klass, "==", Message_eq, 1); + rb_define_method(klass, "eql?", Message_eq, 1); + rb_define_method(klass, "freeze", Message_freeze, 0); rb_define_method(klass, "hash", Message_hash, 0); rb_define_method(klass, "to_h", Message_to_h, 0); - rb_define_method(klass, "to_hash", Message_to_h, 0); rb_define_method(klass, "inspect", Message_inspect, 0); + rb_define_method(klass, "to_s", Message_inspect, 0); rb_define_method(klass, "[]", Message_index, 1); rb_define_method(klass, "[]=", Message_index_set, 2); rb_define_singleton_method(klass, "decode", Message_decode, 1); rb_define_singleton_method(klass, "encode", Message_encode, 1); - rb_define_singleton_method(klass, "decode_json", Message_decode_json, 1); + rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1); rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1); rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0); @@ -540,12 +1153,12 @@ VALUE build_class_from_descriptor(Descriptor* desc) { * This module method, provided on each generated enum module, looks up an enum * value by number and returns its name as a Ruby symbol, or nil if not found. */ -VALUE enum_lookup(VALUE self, VALUE number) { +static VALUE enum_lookup(VALUE self, VALUE number) { int32_t num = NUM2INT(number); VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned); - EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc); + const upb_enumdef *e = EnumDescriptor_GetEnumDef(desc); - const char* name = upb_enumdef_iton(enumdesc->enumdef, num); + const char* name = upb_enumdef_iton(e, num); if (name == NULL) { return Qnil; } else { @@ -560,13 +1173,13 @@ VALUE enum_lookup(VALUE self, VALUE number) { * This module method, provided on each generated enum module, looks up an enum * value by name (as a Ruby symbol) and returns its name, or nil if not found. */ -VALUE enum_resolve(VALUE self, VALUE sym) { +static VALUE enum_resolve(VALUE self, VALUE sym) { const char* name = rb_id2name(SYM2ID(sym)); VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned); - EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc); + const upb_enumdef *e = EnumDescriptor_GetEnumDef(desc); int32_t num = 0; - bool found = upb_enumdef_ntoiz(enumdesc->enumdef, name, &num); + bool found = upb_enumdef_ntoiz(e, name, &num); if (!found) { return Qnil; } else { @@ -581,25 +1194,24 @@ VALUE enum_resolve(VALUE self, VALUE sym) { * This module method, provided on each generated enum module, returns the * EnumDescriptor corresponding to this enum type. */ -VALUE enum_descriptor(VALUE self) { +static VALUE enum_descriptor(VALUE self) { return rb_ivar_get(self, descriptor_instancevar_interned); } -VALUE build_module_from_enumdesc(EnumDescriptor* enumdesc) { - VALUE mod = rb_define_module_id( - rb_intern(upb_enumdef_fullname(enumdesc->enumdef))); +VALUE build_module_from_enumdesc(VALUE _enumdesc) { + const upb_enumdef *e = EnumDescriptor_GetEnumDef(_enumdesc); + VALUE mod = rb_define_module_id(rb_intern(upb_enumdef_fullname(e))); upb_enum_iter it; - for (upb_enum_begin(&it, enumdesc->enumdef); + for (upb_enum_begin(&it, e); !upb_enum_done(&it); upb_enum_next(&it)) { const char* name = upb_enum_iter_name(&it); int32_t value = upb_enum_iter_number(&it); if (name[0] < 'A' || name[0] > 'Z') { - rb_raise(rb_eTypeError, - "Enum value '%s' does not start with an uppercase letter " - "as is required for Ruby constants.", - name); + rb_warn("Enum value '%s' does not start with an uppercase letter " + "as is required for Ruby constants.", + name); } rb_define_const(mod, name, INT2NUM(value)); } @@ -607,26 +1219,97 @@ VALUE build_module_from_enumdesc(EnumDescriptor* enumdesc) { rb_define_singleton_method(mod, "lookup", enum_lookup, 1); rb_define_singleton_method(mod, "resolve", enum_resolve, 1); rb_define_singleton_method(mod, "descriptor", enum_descriptor, 0); - rb_ivar_set(mod, descriptor_instancevar_interned, - get_def_obj(enumdesc->enumdef)); + rb_ivar_set(mod, descriptor_instancevar_interned, _enumdesc); return mod; } -/* - * call-seq: - * Google::Protobuf.deep_copy(obj) => copy_of_obj - * - * Performs a deep copy of a RepeatedField instance, a Map instance, or a - * message object, recursively copying its members. - */ -VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) { - VALUE klass = CLASS_OF(obj); - if (klass == cRepeatedField) { - return RepeatedField_deep_copy(obj); - } else if (klass == cMap) { - return Map_deep_copy(obj); - } else { - return Message_deep_copy(obj); +// Internal only; used by Google::Protobuf.deep_copy. +upb_msg* Message_deep_copy(const upb_msg* msg, const upb_msgdef* m, + upb_arena *arena) { + // Serialize and parse. + upb_arena *tmp_arena = upb_arena_new(); + const upb_msglayout *layout = upb_msgdef_layout(m); + size_t size; + + char* data = upb_encode_ex(msg, layout, 0, tmp_arena, &size); + upb_msg* new_msg = upb_msg_new(m, arena); + + if (!data || !upb_decode(data, size, new_msg, layout, arena)) { + upb_arena_free(tmp_arena); + rb_raise(cParseError, "Error occurred copying proto"); + } + + upb_arena_free(tmp_arena); + return new_msg; +} + +const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m, + const char* name, upb_arena* arena) { + if (value == Qnil) return NULL; + + VALUE klass = CLASS_OF(value); + VALUE desc_rb = rb_ivar_get(klass, descriptor_instancevar_interned); + const upb_msgdef* val_m = + desc_rb == Qnil ? NULL : Descriptor_GetMsgDef(desc_rb); + + if (val_m != m) { + // Check for possible implicit conversions + // TODO: hash conversion? + + switch (upb_msgdef_wellknowntype(m)) { + case UPB_WELLKNOWN_TIMESTAMP: { + // Time -> Google::Protobuf::Timestamp + upb_msg *msg = upb_msg_new(m, arena); + upb_msgval sec, nsec; + struct timespec time; + const upb_fielddef *sec_f = upb_msgdef_itof(m, 1); + const upb_fielddef *nsec_f = upb_msgdef_itof(m, 2); + + if (!rb_obj_is_kind_of(value, rb_cTime)) goto badtype; + + time = rb_time_timespec(value); + sec.int64_val = time.tv_sec; + nsec.int32_val = time.tv_nsec; + upb_msg_set(msg, sec_f, sec, arena); + upb_msg_set(msg, nsec_f, nsec, arena); + return msg; + } + case UPB_WELLKNOWN_DURATION: { + // Numeric -> Google::Protobuf::Duration + upb_msg *msg = upb_msg_new(m, arena); + upb_msgval sec, nsec; + const upb_fielddef *sec_f = upb_msgdef_itof(m, 1); + const upb_fielddef *nsec_f = upb_msgdef_itof(m, 2); + + if (!rb_obj_is_kind_of(value, rb_cNumeric)) goto badtype; + + sec.int64_val = NUM2LL(value); + nsec.int32_val = (NUM2DBL(value) - NUM2LL(value)) * 1000000000; + upb_msg_set(msg, sec_f, sec, arena); + upb_msg_set(msg, nsec_f, nsec, arena); + return msg; + } + default: + badtype: + rb_raise(cTypeError, + "Invalid type %s to assign to submessage field '%s'.", + rb_class2name(CLASS_OF(value)), name); + } + } + + Message* self = ruby_to_Message(value); + upb_arena_fuse(arena, Arena_get(self->arena)); + + return self->msg; +} + +void Message_register(VALUE protobuf) { + cParseError = rb_const_get(protobuf, rb_intern("ParseError")); + + // Ruby-interned string: "descriptor". We use this identifier to store an + // instance variable on message classes we create in order to link them back + // to their descriptors. + descriptor_instancevar_interned = rb_intern("descriptor"); } diff --git a/ruby/ext/google/protobuf_c/message.h b/ruby/ext/google/protobuf_c/message.h new file mode 100644 index 0000000000000..551f41f96d82f --- /dev/null +++ b/ruby/ext/google/protobuf_c/message.h @@ -0,0 +1,98 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef RUBY_PROTOBUF_MESSAGE_H_ +#define RUBY_PROTOBUF_MESSAGE_H_ + +#include + +#include "protobuf.h" +#include "ruby-upb.h" + +// Gets the underlying upb_msg* and upb_msgdef for the given Ruby message +// wrapper. Requires that |value| is indeed a message object. +const upb_msg *Message_Get(VALUE value, const upb_msgdef **m); + +// Like Message_Get(), but checks that the object is not frozen and returns a +// mutable pointer. +upb_msg *Message_GetMutable(VALUE value, const upb_msgdef **m); + +// Returns the Arena object for this message. +VALUE Message_GetArena(VALUE value); + +// Converts |value| into a upb_msg value of the expected upb_msgdef type, +// raising an error if this is not possible. Used when assigning |value| to a +// field of another message, which means the message must be of a particular +// type. +// +// This will perform automatic conversions in some cases (for example, Time -> +// Google::Protobuf::Timestamp). If any new message is created, it will be +// created on |arena|, and any existing message will have its arena fused with +// |arena|. +const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m, + const char* name, upb_arena* arena); + +// Gets or constructs a Ruby wrapper object for the given message. The wrapper +// object will reference |arena| and ensure that it outlives this object. +VALUE Message_GetRubyWrapper(upb_msg* msg, const upb_msgdef* m, VALUE arena); + +// Implements #inspect for this message, printing the text to |b|. +void Message_PrintMessage(StringBuilder* b, const upb_msg* msg, + const upb_msgdef* m); + +// Returns a hash value for the given message. +uint64_t Message_Hash(const upb_msg *msg, const upb_msgdef *m, uint64_t seed); + +// Returns a deep copy of the given message. +upb_msg* Message_deep_copy(const upb_msg* msg, const upb_msgdef* m, + upb_arena *arena); + +// Returns true if these two messages are equal. +bool Message_Equal(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m); + +// Checks that this Ruby object is a message, and raises an exception if not. +void Message_CheckClass(VALUE klass); + +// Returns a new Hash object containing the contents of this message. +VALUE Scalar_CreateHash(upb_msgval val, TypeInfo type_info); + +// Creates a message class or enum module for this descriptor, respectively. +VALUE build_class_from_descriptor(VALUE descriptor); +VALUE build_module_from_enumdesc(VALUE _enumdesc); + +// Returns the Descriptor/EnumDescriptor for the given message class or enum +// module, respectively. Returns nil if this is not a message class or enum +// module. +VALUE MessageOrEnum_GetDescriptor(VALUE klass); + +// Call at startup to register all types in this module. +void Message_register(VALUE protobuf); + +#endif // RUBY_PROTOBUF_MESSAGE_H_ diff --git a/ruby/ext/google/protobuf_c/protobuf.c b/ruby/ext/google/protobuf_c/protobuf.c index 98963667604df..737cd284b868d 100644 --- a/ruby/ext/google/protobuf_c/protobuf.c +++ b/ruby/ext/google/protobuf_c/protobuf.c @@ -30,51 +30,342 @@ #include "protobuf.h" -// ----------------------------------------------------------------------------- -// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor -// instances. -// ----------------------------------------------------------------------------- +#include -// This is a hash table from def objects (encoded by converting pointers to -// Ruby integers) to MessageDef/EnumDef instances (as Ruby values). -VALUE upb_def_to_ruby_obj_map; +#include "defs.h" +#include "map.h" +#include "message.h" +#include "repeated_field.h" VALUE cError; -VALUE cParseError; +VALUE cTypeError; -void add_def_obj(const void* def, VALUE value) { - rb_hash_aset(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def), value); +const upb_fielddef* map_field_key(const upb_fielddef* field) { + const upb_msgdef *entry = upb_fielddef_msgsubdef(field); + return upb_msgdef_itof(entry, 1); } -VALUE get_def_obj(const void* def) { - return rb_hash_aref(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def)); +const upb_fielddef* map_field_value(const upb_fielddef* field) { + const upb_msgdef *entry = upb_fielddef_msgsubdef(field); + return upb_msgdef_itof(entry, 2); } // ----------------------------------------------------------------------------- -// Utilities. +// StringBuilder, for inspect // ----------------------------------------------------------------------------- -// Raises a Ruby error if |status| is not OK, using its error message. -void check_upb_status(const upb_status* status, const char* msg) { - if (!upb_ok(status)) { - rb_raise(rb_eRuntimeError, "%s: %s\n", msg, upb_status_errmsg(status)); +struct StringBuilder { + size_t size; + size_t cap; + char *data; +}; + +typedef struct StringBuilder StringBuilder; + +static size_t StringBuilder_SizeOf(size_t cap) { + return sizeof(StringBuilder) + cap; +} + +StringBuilder* StringBuilder_New() { + const size_t cap = 128; + StringBuilder* builder = malloc(sizeof(*builder)); + builder->size = 0; + builder->cap = cap; + builder->data = malloc(builder->cap); + return builder; +} + +void StringBuilder_Free(StringBuilder* b) { + free(b->data); + free(b); +} + +void StringBuilder_Printf(StringBuilder* b, const char *fmt, ...) { + size_t have = b->cap - b->size; + size_t n; + va_list args; + + va_start(args, fmt); + n = vsnprintf(&b->data[b->size], have, fmt, args); + va_end(args); + + if (have <= n) { + while (have <= n) { + b->cap *= 2; + have = b->cap - b->size; + } + b->data = realloc(b->data, StringBuilder_SizeOf(b->cap)); + va_start(args, fmt); + n = vsnprintf(&b->data[b->size], have, fmt, args); + va_end(args); + PBRUBY_ASSERT(n < have); + } + + b->size += n; +} + +VALUE StringBuilder_ToRubyString(StringBuilder* b) { + VALUE ret = rb_str_new(b->data, b->size); + rb_enc_associate(ret, rb_utf8_encoding()); + return ret; +} + +static void StringBuilder_PrintEnum(StringBuilder* b, int32_t val, + const upb_enumdef* e) { + const char *name = upb_enumdef_iton(e, val); + if (name) { + StringBuilder_Printf(b, ":%s", name); + } else { + StringBuilder_Printf(b, "%" PRId32, val); + } +} + +void StringBuilder_PrintMsgval(StringBuilder* b, upb_msgval val, + TypeInfo info) { + switch (info.type) { + case UPB_TYPE_BOOL: + StringBuilder_Printf(b, "%s", val.bool_val ? "true" : "false"); + break; + case UPB_TYPE_FLOAT: { + VALUE str = rb_inspect(DBL2NUM(val.float_val)); + StringBuilder_Printf(b, "%s", RSTRING_PTR(str)); + break; + } + case UPB_TYPE_DOUBLE: { + VALUE str = rb_inspect(DBL2NUM(val.double_val)); + StringBuilder_Printf(b, "%s", RSTRING_PTR(str)); + break; + } + case UPB_TYPE_INT32: + StringBuilder_Printf(b, "%" PRId32, val.int32_val); + break; + case UPB_TYPE_UINT32: + StringBuilder_Printf(b, "%" PRIu32, val.uint32_val); + break; + case UPB_TYPE_INT64: + StringBuilder_Printf(b, "%" PRId64, val.int64_val); + break; + case UPB_TYPE_UINT64: + StringBuilder_Printf(b, "%" PRIu64, val.uint64_val); + break; + case UPB_TYPE_STRING: + StringBuilder_Printf(b, "\"%.*s\"", (int)val.str_val.size, val.str_val.data); + break; + case UPB_TYPE_BYTES: + StringBuilder_Printf(b, "\"%.*s\"", (int)val.str_val.size, val.str_val.data); + break; + case UPB_TYPE_ENUM: + StringBuilder_PrintEnum(b, val.int32_val, info.def.enumdef); + break; + case UPB_TYPE_MESSAGE: + Message_PrintMessage(b, val.msg_val, info.def.msgdef); + break; } } -// String encodings: we look these up once, at load time, and then cache them -// here. -rb_encoding* kRubyStringUtf8Encoding; -rb_encoding* kRubyStringASCIIEncoding; -rb_encoding* kRubyString8bitEncoding; +// ----------------------------------------------------------------------------- +// Arena +// ----------------------------------------------------------------------------- + +void Arena_free(void* data) { upb_arena_free(data); } + +static VALUE cArena; + +const rb_data_type_t Arena_type = { + "Google::Protobuf::Internal::Arena", + { NULL, Arena_free, NULL }, +}; + +static VALUE Arena_alloc(VALUE klass) { + upb_arena *arena = upb_arena_new(); + return TypedData_Wrap_Struct(klass, &Arena_type, arena); +} + +upb_arena *Arena_get(VALUE _arena) { + upb_arena *arena; + TypedData_Get_Struct(_arena, upb_arena, &Arena_type, arena); + return arena; +} + +VALUE Arena_new() { + return Arena_alloc(cArena); +} + +void Arena_register(VALUE module) { + VALUE internal = rb_define_module_under(module, "Internal"); + VALUE klass = rb_define_class_under(internal, "Arena", rb_cObject); + rb_define_alloc_func(klass, Arena_alloc); + rb_gc_register_address(&cArena); + cArena = klass; +} + +// ----------------------------------------------------------------------------- +// Object Cache +// ----------------------------------------------------------------------------- -// Ruby-interned string: "descriptor". We use this identifier to store an -// instance variable on message classes we create in order to link them back to -// their descriptors. +// A pointer -> Ruby Object cache that keeps references to Ruby wrapper +// objects. This allows us to look up any Ruby wrapper object by the address +// of the object it is wrapping. That way we can avoid ever creating two +// different wrapper objects for the same C object, which saves memory and +// preserves object identity. // -// We intern this once at module load time then use the interned identifier at -// runtime in order to avoid the cost of repeatedly interning in hot paths. -const char* kDescriptorInstanceVar = "descriptor"; -ID descriptor_instancevar_interned; +// We use Hash and/or WeakMap for the cache. WeakMap is faster overall +// (probably due to removal being integrated with GC) but doesn't work for Ruby +// <2.7 (see note below). We need Hash for Ruby <2.7 and for cases where we +// need to GC-root the object (notably when the object has been frozen). + +#if RUBY_API_VERSION_CODE >= 20700 +#define USE_WEAK_MAP 1 +#else +#define USE_WEAK_MAP 0 +#endif + +static VALUE ObjectCache_GetKey(const void* key) { + char buf[sizeof(key)]; + memcpy(&buf, &key, sizeof(key)); + intptr_t key_int = (intptr_t)key; + PBRUBY_ASSERT((key_int & 3) == 0); + return LL2NUM(key_int >> 2); +} + +// Strong object cache, uses regular Hash and GC-roots objects. +// - For Ruby <2.7, used for all objects. +// - For Ruby >=2.7, used only for frozen objects, so we preserve the "frozen" +// bit (since this information is not preserved at the upb level). + +VALUE strong_obj_cache = Qnil; + +static void StrongObjectCache_Init() { + rb_gc_register_address(&strong_obj_cache); + strong_obj_cache = rb_hash_new(); +} + +static void StrongObjectCache_Remove(void* key) { + VALUE key_rb = ObjectCache_GetKey(key); + PBRUBY_ASSERT(rb_hash_lookup(strong_obj_cache, key_rb) != Qnil); + rb_hash_delete(strong_obj_cache, key_rb); +} + +static VALUE StrongObjectCache_Get(const void* key) { + VALUE key_rb = ObjectCache_GetKey(key); + return rb_hash_lookup(strong_obj_cache, key_rb); +} + +static void StrongObjectCache_Add(const void* key, VALUE val, + upb_arena* arena) { + PBRUBY_ASSERT(StrongObjectCache_Get(key) == Qnil); + VALUE key_rb = ObjectCache_GetKey(key); + rb_hash_aset(strong_obj_cache, key_rb, val); + upb_arena_addcleanup(arena, (void*)key, StrongObjectCache_Remove); +} + +// Weak object cache. This speeds up the test suite significantly, so we +// presume it speeds up real code also. However we can only use it in Ruby +// >=2.7 due to: +// https://bugs.ruby-lang.org/issues/16035 + +#if USE_WEAK_MAP + +VALUE weak_obj_cache = Qnil; + +static void WeakObjectCache_Init() { + rb_gc_register_address(&weak_obj_cache); + VALUE klass = rb_eval_string("ObjectSpace::WeakMap"); + weak_obj_cache = rb_class_new_instance(0, NULL, klass); +} + +static VALUE WeakObjectCache_Get(const void* key) { + VALUE key_rb = ObjectCache_GetKey(key); + VALUE ret = rb_funcall(weak_obj_cache, rb_intern("[]"), 1, key_rb); + return ret; +} + +static void WeakObjectCache_Add(const void* key, VALUE val) { + PBRUBY_ASSERT(WeakObjectCache_Get(key) == Qnil); + VALUE key_rb = ObjectCache_GetKey(key); + rb_funcall(weak_obj_cache, rb_intern("[]="), 2, key_rb, val); + PBRUBY_ASSERT(WeakObjectCache_Get(key) == val); +} + +#endif + +// Public ObjectCache API. + +static void ObjectCache_Init() { + StrongObjectCache_Init(); +#if USE_WEAK_MAP + WeakObjectCache_Init(); +#endif +} + +void ObjectCache_Add(const void* key, VALUE val, upb_arena *arena) { +#if USE_WEAK_MAP + (void)arena; + WeakObjectCache_Add(key, val); +#else + StrongObjectCache_Add(key, val, arena); +#endif +} + +// Returns the cached object for this key, if any. Otherwise returns Qnil. +VALUE ObjectCache_Get(const void* key) { +#if USE_WEAK_MAP + return WeakObjectCache_Get(key); +#else + return StrongObjectCache_Get(key); +#endif +} + +void ObjectCache_Pin(const void* key, VALUE val, upb_arena *arena) { +#if USE_WEAK_MAP + PBRUBY_ASSERT(WeakObjectCache_Get(key) == val); + // This will GC-root the object, but we'll still use the weak map for + // actual lookup. + StrongObjectCache_Add(key, val, arena); +#else + // Value is already pinned, nothing to do. +#endif +} + +/* + * call-seq: + * Google::Protobuf.discard_unknown(msg) + * + * Discard unknown fields in the given message object and recursively discard + * unknown fields in submessages. + */ +static VALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb) { + const upb_msgdef *m; + upb_msg *msg = Message_GetMutable(msg_rb, &m); + if (!upb_msg_discardunknown(msg, m, 128)) { + rb_raise(rb_eRuntimeError, "Messages nested too deeply."); + } + + return Qnil; +} + +/* + * call-seq: + * Google::Protobuf.deep_copy(obj) => copy_of_obj + * + * Performs a deep copy of a RepeatedField instance, a Map instance, or a + * message object, recursively copying its members. + */ +VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) { + VALUE klass = CLASS_OF(obj); + if (klass == cRepeatedField) { + return RepeatedField_deep_copy(obj); + } else if (klass == cMap) { + return Map_deep_copy(obj); + } else { + VALUE new_arena_rb = Arena_new(); + upb_arena *new_arena = Arena_get(new_arena_rb); + const upb_msgdef *m; + const upb_msg *msg = Message_Get(obj, &m); + upb_msg* new_msg = Message_deep_copy(msg, m, new_arena); + return Message_GetRubyWrapper(new_msg, m, new_arena_rb); + } +} // ----------------------------------------------------------------------------- // Initialization/entry point. @@ -82,36 +373,24 @@ ID descriptor_instancevar_interned; // This must be named "Init_protobuf_c" because the Ruby module is named // "protobuf_c" -- the VM looks for this symbol in our .so. +__attribute__ ((visibility ("default"))) void Init_protobuf_c() { + ObjectCache_Init(); + VALUE google = rb_define_module("Google"); VALUE protobuf = rb_define_module_under(google, "Protobuf"); - VALUE internal = rb_define_module_under(protobuf, "Internal"); - - descriptor_instancevar_interned = rb_intern(kDescriptorInstanceVar); - DescriptorPool_register(protobuf); - Descriptor_register(protobuf); - FieldDescriptor_register(protobuf); - OneofDescriptor_register(protobuf); - EnumDescriptor_register(protobuf); - MessageBuilderContext_register(internal); - OneofBuilderContext_register(internal); - EnumBuilderContext_register(internal); - Builder_register(internal); + + Arena_register(protobuf); + Defs_register(protobuf); RepeatedField_register(protobuf); Map_register(protobuf); + Message_register(protobuf); cError = rb_const_get(protobuf, rb_intern("Error")); - cParseError = rb_const_get(protobuf, rb_intern("ParseError")); + cTypeError = rb_const_get(protobuf, rb_intern("TypeError")); + rb_define_singleton_method(protobuf, "discard_unknown", + Google_Protobuf_discard_unknown, 1); rb_define_singleton_method(protobuf, "deep_copy", Google_Protobuf_deep_copy, 1); - - kRubyStringUtf8Encoding = rb_utf8_encoding(); - kRubyStringASCIIEncoding = rb_usascii_encoding(); - kRubyString8bitEncoding = rb_ascii8bit_encoding(); - - upb_def_to_ruby_obj_map = rb_hash_new(); - rb_gc_register_address(&upb_def_to_ruby_obj_map); - map_parse_frames = rb_ary_new(); - rb_gc_register_address(&map_parse_frames); } diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h index 520e9d9b84fc9..90fb0a2093353 100644 --- a/ruby/ext/google/protobuf_c/protobuf.h +++ b/ruby/ext/google/protobuf_c/protobuf.h @@ -35,509 +35,78 @@ #include #include -#include "upb.h" - -// Forward decls. -struct DescriptorPool; -struct Descriptor; -struct FieldDescriptor; -struct EnumDescriptor; -struct MessageLayout; -struct MessageField; -struct MessageHeader; -struct MessageBuilderContext; -struct EnumBuilderContext; -struct Builder; - -typedef struct DescriptorPool DescriptorPool; -typedef struct Descriptor Descriptor; -typedef struct FieldDescriptor FieldDescriptor; -typedef struct OneofDescriptor OneofDescriptor; -typedef struct EnumDescriptor EnumDescriptor; -typedef struct MessageLayout MessageLayout; -typedef struct MessageField MessageField; -typedef struct MessageHeader MessageHeader; -typedef struct MessageBuilderContext MessageBuilderContext; -typedef struct OneofBuilderContext OneofBuilderContext; -typedef struct EnumBuilderContext EnumBuilderContext; -typedef struct Builder Builder; - -/* - It can be a bit confusing how the C structs defined below and the Ruby - objects interact and hold references to each other. First, a few principles: - - - Ruby's "TypedData" abstraction lets a Ruby VALUE hold a pointer to a C - struct (or arbitrary memory chunk), own it, and free it when collected. - Thus, each struct below will have a corresponding Ruby object - wrapping/owning it. - - - To get back from an underlying upb {msg,enum}def to the Ruby object, we - keep a global hashmap, accessed by get_def_obj/add_def_obj below. - - The in-memory structure is then something like: - - Ruby | upb - | - DescriptorPool ------------|-----------> upb_symtab____________________ - | | (message types) \ - | v \ - Descriptor ---------------|-----------> upb_msgdef (enum types)| - |--> msgclass | | ^ | - | (dynamically built) | | | (submsg fields) | - |--> MessageLayout | | | / - |--------------------------|> decoder method| | / - \--------------------------|> serialize | | / - | handlers v | / - FieldDescriptor -----------|-----------> upb_fielddef / - | | / - | v (enum fields) / - EnumDescriptor ------------|-----------> upb_enumdef <----------' - | - | - ^ | \___/ - `---------------|-----------------' (get_def_obj map) - */ - -// ----------------------------------------------------------------------------- -// Ruby class structure definitions. -// ----------------------------------------------------------------------------- - -struct DescriptorPool { - upb_symtab* symtab; -}; - -struct Descriptor { - const upb_msgdef* msgdef; - MessageLayout* layout; - VALUE klass; // begins as nil - const upb_handlers* fill_handlers; - const upb_pbdecodermethod* fill_method; - const upb_json_parsermethod* json_fill_method; - const upb_handlers* pb_serialize_handlers; - const upb_handlers* json_serialize_handlers; - const upb_handlers* json_serialize_handlers_preserve; - // Handlers hold type class references for sub-message fields directly in some - // cases. We need to keep these rooted because they might otherwise be - // collected. - VALUE typeclass_references; -}; - -struct FieldDescriptor { - const upb_fielddef* fielddef; -}; - -struct OneofDescriptor { - const upb_oneofdef* oneofdef; -}; - -struct EnumDescriptor { - const upb_enumdef* enumdef; - VALUE module; // begins as nil -}; - -struct MessageBuilderContext { - VALUE descriptor; - VALUE builder; -}; - -struct OneofBuilderContext { - VALUE descriptor; - VALUE builder; -}; - -struct EnumBuilderContext { - VALUE enumdesc; -}; - -struct Builder { - VALUE pending_list; - upb_def** defs; // used only while finalizing -}; - -extern VALUE cDescriptorPool; -extern VALUE cDescriptor; -extern VALUE cFieldDescriptor; -extern VALUE cEnumDescriptor; -extern VALUE cMessageBuilderContext; -extern VALUE cOneofBuilderContext; -extern VALUE cEnumBuilderContext; -extern VALUE cBuilder; - -extern VALUE cError; -extern VALUE cParseError; - -extern VALUE map_parse_frames; - -// We forward-declare all of the Ruby method implementations here because we -// sometimes call the methods directly across .c files, rather than going -// through Ruby's method dispatching (e.g. during message parse). It's cleaner -// to keep the list of object methods together than to split them between -// static-in-file definitions and header declarations. - -void DescriptorPool_mark(void* _self); -void DescriptorPool_free(void* _self); -VALUE DescriptorPool_alloc(VALUE klass); -void DescriptorPool_register(VALUE module); -DescriptorPool* ruby_to_DescriptorPool(VALUE value); -VALUE DescriptorPool_add(VALUE _self, VALUE def); -VALUE DescriptorPool_build(VALUE _self); -VALUE DescriptorPool_lookup(VALUE _self, VALUE name); -VALUE DescriptorPool_generated_pool(VALUE _self); - -void Descriptor_mark(void* _self); -void Descriptor_free(void* _self); -VALUE Descriptor_alloc(VALUE klass); -void Descriptor_register(VALUE module); -Descriptor* ruby_to_Descriptor(VALUE value); -VALUE Descriptor_name(VALUE _self); -VALUE Descriptor_name_set(VALUE _self, VALUE str); -VALUE Descriptor_each(VALUE _self); -VALUE Descriptor_lookup(VALUE _self, VALUE name); -VALUE Descriptor_add_field(VALUE _self, VALUE obj); -VALUE Descriptor_add_oneof(VALUE _self, VALUE obj); -VALUE Descriptor_each_oneof(VALUE _self); -VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name); -VALUE Descriptor_msgclass(VALUE _self); -extern const rb_data_type_t _Descriptor_type; - -void FieldDescriptor_mark(void* _self); -void FieldDescriptor_free(void* _self); -VALUE FieldDescriptor_alloc(VALUE klass); -void FieldDescriptor_register(VALUE module); -FieldDescriptor* ruby_to_FieldDescriptor(VALUE value); -VALUE FieldDescriptor_name(VALUE _self); -VALUE FieldDescriptor_name_set(VALUE _self, VALUE str); -VALUE FieldDescriptor_type(VALUE _self); -VALUE FieldDescriptor_type_set(VALUE _self, VALUE type); -VALUE FieldDescriptor_label(VALUE _self); -VALUE FieldDescriptor_label_set(VALUE _self, VALUE label); -VALUE FieldDescriptor_number(VALUE _self); -VALUE FieldDescriptor_number_set(VALUE _self, VALUE number); -VALUE FieldDescriptor_submsg_name(VALUE _self); -VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value); -VALUE FieldDescriptor_subtype(VALUE _self); -VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb); -VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value); -upb_fieldtype_t ruby_to_fieldtype(VALUE type); -VALUE fieldtype_to_ruby(upb_fieldtype_t type); - -void OneofDescriptor_mark(void* _self); -void OneofDescriptor_free(void* _self); -VALUE OneofDescriptor_alloc(VALUE klass); -void OneofDescriptor_register(VALUE module); -OneofDescriptor* ruby_to_OneofDescriptor(VALUE value); -VALUE OneofDescriptor_name(VALUE _self); -VALUE OneofDescriptor_name_set(VALUE _self, VALUE value); -VALUE OneofDescriptor_add_field(VALUE _self, VALUE field); -VALUE OneofDescriptor_each(VALUE _self, VALUE field); - -void EnumDescriptor_mark(void* _self); -void EnumDescriptor_free(void* _self); -VALUE EnumDescriptor_alloc(VALUE klass); -void EnumDescriptor_register(VALUE module); -EnumDescriptor* ruby_to_EnumDescriptor(VALUE value); -VALUE EnumDescriptor_name(VALUE _self); -VALUE EnumDescriptor_name_set(VALUE _self, VALUE str); -VALUE EnumDescriptor_add_value(VALUE _self, VALUE name, VALUE number); -VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name); -VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number); -VALUE EnumDescriptor_each(VALUE _self); -VALUE EnumDescriptor_enummodule(VALUE _self); -extern const rb_data_type_t _EnumDescriptor_type; - -void MessageBuilderContext_mark(void* _self); -void MessageBuilderContext_free(void* _self); -VALUE MessageBuilderContext_alloc(VALUE klass); -void MessageBuilderContext_register(VALUE module); -MessageBuilderContext* ruby_to_MessageBuilderContext(VALUE value); -VALUE MessageBuilderContext_initialize(VALUE _self, - VALUE descriptor, - VALUE builder); -VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self); -VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self); -VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self); -VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self); -VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name); - -void OneofBuilderContext_mark(void* _self); -void OneofBuilderContext_free(void* _self); -VALUE OneofBuilderContext_alloc(VALUE klass); -void OneofBuilderContext_register(VALUE module); -OneofBuilderContext* ruby_to_OneofBuilderContext(VALUE value); -VALUE OneofBuilderContext_initialize(VALUE _self, - VALUE descriptor, - VALUE builder); -VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self); - -void EnumBuilderContext_mark(void* _self); -void EnumBuilderContext_free(void* _self); -VALUE EnumBuilderContext_alloc(VALUE klass); -void EnumBuilderContext_register(VALUE module); -EnumBuilderContext* ruby_to_EnumBuilderContext(VALUE value); -VALUE EnumBuilderContext_initialize(VALUE _self, VALUE enumdesc); -VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number); - -void Builder_mark(void* _self); -void Builder_free(void* _self); -VALUE Builder_alloc(VALUE klass); -void Builder_register(VALUE module); -Builder* ruby_to_Builder(VALUE value); -VALUE Builder_add_message(VALUE _self, VALUE name); -VALUE Builder_add_enum(VALUE _self, VALUE name); -VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb); - -// ----------------------------------------------------------------------------- -// Native slot storage abstraction. -// ----------------------------------------------------------------------------- - -#define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t) - -size_t native_slot_size(upb_fieldtype_t type); -void native_slot_set(upb_fieldtype_t type, - VALUE type_class, - void* memory, - VALUE value); -// Atomically (with respect to Ruby VM calls) either update the value and set a -// oneof case, or do neither. If |case_memory| is null, then no case value is -// set. -void native_slot_set_value_and_case(upb_fieldtype_t type, - VALUE type_class, - void* memory, - VALUE value, - uint32_t* case_memory, - uint32_t case_number); -VALUE native_slot_get(upb_fieldtype_t type, - VALUE type_class, - const void* memory); -void native_slot_init(upb_fieldtype_t type, void* memory); -void native_slot_mark(upb_fieldtype_t type, void* memory); -void native_slot_dup(upb_fieldtype_t type, void* to, void* from); -void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from); -bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2); - -VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value); -void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE value); - -extern rb_encoding* kRubyStringUtf8Encoding; -extern rb_encoding* kRubyStringASCIIEncoding; -extern rb_encoding* kRubyString8bitEncoding; - -VALUE field_type_class(const upb_fielddef* field); - -#define MAP_KEY_FIELD 1 -#define MAP_VALUE_FIELD 2 - -// Oneof case slot value to indicate that no oneof case is set. The value `0` is -// safe because field numbers are used as case identifiers, and no field can -// have a number of 0. -#define ONEOF_CASE_NONE 0 +#include "ruby-upb.h" +#include "defs.h" // These operate on a map field (i.e., a repeated field of submessages whose // submessage type is a map-entry msgdef). -bool is_map_field(const upb_fielddef* field); const upb_fielddef* map_field_key(const upb_fielddef* field); const upb_fielddef* map_field_value(const upb_fielddef* field); -// These operate on a map-entry msgdef. -const upb_fielddef* map_entry_key(const upb_msgdef* msgdef); -const upb_fielddef* map_entry_value(const upb_msgdef* msgdef); - -// ----------------------------------------------------------------------------- -// Repeated field container type. -// ----------------------------------------------------------------------------- - -typedef struct { - upb_fieldtype_t field_type; - VALUE field_type_class; - void* elements; - int size; - int capacity; -} RepeatedField; - -void RepeatedField_mark(void* self); -void RepeatedField_free(void* self); -VALUE RepeatedField_alloc(VALUE klass); -VALUE RepeatedField_init(int argc, VALUE* argv, VALUE self); -void RepeatedField_register(VALUE module); - -extern const rb_data_type_t RepeatedField_type; -extern VALUE cRepeatedField; - -RepeatedField* ruby_to_RepeatedField(VALUE value); - -VALUE RepeatedField_each(VALUE _self); -VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self); -void* RepeatedField_index_native(VALUE _self, int index); -int RepeatedField_size(VALUE _self); -VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val); -void RepeatedField_reserve(RepeatedField* self, int new_size); -VALUE RepeatedField_push(VALUE _self, VALUE val); -void RepeatedField_push_native(VALUE _self, void* data); -VALUE RepeatedField_pop_one(VALUE _self); -VALUE RepeatedField_insert(int argc, VALUE* argv, VALUE _self); -VALUE RepeatedField_replace(VALUE _self, VALUE list); -VALUE RepeatedField_clear(VALUE _self); -VALUE RepeatedField_length(VALUE _self); -VALUE RepeatedField_dup(VALUE _self); -VALUE RepeatedField_deep_copy(VALUE _self); -VALUE RepeatedField_to_ary(VALUE _self); -VALUE RepeatedField_eq(VALUE _self, VALUE _other); -VALUE RepeatedField_hash(VALUE _self); -VALUE RepeatedField_inspect(VALUE _self); -VALUE RepeatedField_plus(VALUE _self, VALUE list); - -// Defined in repeated_field.c; also used by Map. -void validate_type_class(upb_fieldtype_t type, VALUE klass); - // ----------------------------------------------------------------------------- -// Map container type. +// Arena // ----------------------------------------------------------------------------- -typedef struct { - upb_fieldtype_t key_type; - upb_fieldtype_t value_type; - VALUE value_type_class; - upb_strtable table; -} Map; +// A Ruby object that wraps an underlying upb_arena. Any objects that are +// allocated from this arena should reference the Arena in rb_gc_mark(), to +// ensure that the object's underlying memory outlives any Ruby object that can +// reach it. -void Map_mark(void* self); -void Map_free(void* self); -VALUE Map_alloc(VALUE klass); -VALUE Map_init(int argc, VALUE* argv, VALUE self); -void Map_register(VALUE module); - -extern const rb_data_type_t Map_type; -extern VALUE cMap; - -Map* ruby_to_Map(VALUE value); - -VALUE Map_each(VALUE _self); -VALUE Map_keys(VALUE _self); -VALUE Map_values(VALUE _self); -VALUE Map_index(VALUE _self, VALUE key); -VALUE Map_index_set(VALUE _self, VALUE key, VALUE value); -VALUE Map_has_key(VALUE _self, VALUE key); -VALUE Map_delete(VALUE _self, VALUE key); -VALUE Map_clear(VALUE _self); -VALUE Map_length(VALUE _self); -VALUE Map_dup(VALUE _self); -VALUE Map_deep_copy(VALUE _self); -VALUE Map_eq(VALUE _self, VALUE _other); -VALUE Map_hash(VALUE _self); -VALUE Map_to_h(VALUE _self); -VALUE Map_inspect(VALUE _self); -VALUE Map_merge(VALUE _self, VALUE hashmap); -VALUE Map_merge_into_self(VALUE _self, VALUE hashmap); - -typedef struct { - Map* self; - upb_strtable_iter it; -} Map_iter; - -void Map_begin(VALUE _self, Map_iter* iter); -void Map_next(Map_iter* iter); -bool Map_done(Map_iter* iter); -VALUE Map_iter_key(Map_iter* iter); -VALUE Map_iter_value(Map_iter* iter); +VALUE Arena_new(); +upb_arena *Arena_get(VALUE arena); // ----------------------------------------------------------------------------- -// Message layout / storage. +// ObjectCache // ----------------------------------------------------------------------------- -#define MESSAGE_FIELD_NO_CASE ((size_t)-1) - -struct MessageField { - size_t offset; - size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE. -}; - -struct MessageLayout { - const upb_msgdef* msgdef; - MessageField* fields; - size_t size; -}; - -MessageLayout* create_layout(const upb_msgdef* msgdef); -void free_layout(MessageLayout* layout); -VALUE layout_get(MessageLayout* layout, - const void* storage, - const upb_fielddef* field); -void layout_set(MessageLayout* layout, - void* storage, - const upb_fielddef* field, - VALUE val); -void layout_init(MessageLayout* layout, void* storage); -void layout_mark(MessageLayout* layout, void* storage); -void layout_dup(MessageLayout* layout, void* to, void* from); -void layout_deep_copy(MessageLayout* layout, void* to, void* from); -VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2); -VALUE layout_hash(MessageLayout* layout, void* storage); -VALUE layout_inspect(MessageLayout* layout, void* storage); +// Global object cache from upb array/map/message/symtab to wrapper object. +// +// This is a conceptually "weak" cache, in that it does not prevent "val" from +// being collected (though in Ruby <2.7 is it effectively strong, due to +// implementation limitations). + +// Adds an entry to the cache. The "arena" parameter must give the arena that +// "key" was allocated from. In Ruby <2.7.0, it will be used to remove the key +// from the cache when the arena is destroyed. +void ObjectCache_Add(const void* key, VALUE val, upb_arena *arena); + +// Returns the cached object for this key, if any. Otherwise returns Qnil. +VALUE ObjectCache_Get(const void* key); + +// Pins the previously added object so it is GC-rooted. This turns the +// reference to "val" from weak to strong. We use this to guarantee that the +// "frozen" bit on the object will be remembered, even if the user drops their +// reference to this precise object. +// +// The "arena" parameter must give the arena that "key" was allocated from. +void ObjectCache_Pin(const void* key, VALUE val, upb_arena *arena); // ----------------------------------------------------------------------------- -// Message class creation. +// StringBuilder, for inspect // ----------------------------------------------------------------------------- -struct MessageHeader { - Descriptor* descriptor; // kept alive by self.class.descriptor reference. - // Data comes after this. -}; - -extern rb_data_type_t Message_type; - -VALUE build_class_from_descriptor(Descriptor* descriptor); -void* Message_data(void* msg); -void Message_mark(void* self); -void Message_free(void* self); -VALUE Message_alloc(VALUE klass); -VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self); -VALUE Message_initialize(int argc, VALUE* argv, VALUE _self); -VALUE Message_dup(VALUE _self); -VALUE Message_deep_copy(VALUE _self); -VALUE Message_eq(VALUE _self, VALUE _other); -VALUE Message_hash(VALUE _self); -VALUE Message_inspect(VALUE _self); -VALUE Message_to_h(VALUE _self); -VALUE Message_index(VALUE _self, VALUE field_name); -VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value); -VALUE Message_descriptor(VALUE klass); -VALUE Message_decode(VALUE klass, VALUE data); -VALUE Message_encode(VALUE klass, VALUE msg_rb); -VALUE Message_decode_json(VALUE klass, VALUE data); -VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass); - -VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj); +struct StringBuilder; +typedef struct StringBuilder StringBuilder; -VALUE build_module_from_enumdesc(EnumDescriptor* enumdef); -VALUE enum_lookup(VALUE self, VALUE number); -VALUE enum_resolve(VALUE self, VALUE sym); +StringBuilder* StringBuilder_New(); +void StringBuilder_Free(StringBuilder* b); +void StringBuilder_Printf(StringBuilder* b, const char *fmt, ...); +VALUE StringBuilder_ToRubyString(StringBuilder* b); -const upb_pbdecodermethod *new_fillmsg_decodermethod( - Descriptor* descriptor, const void *owner); - -// Maximum depth allowed during encoding, to avoid stack overflows due to -// cycles. -#define ENCODE_MAX_NESTING 63 - -// ----------------------------------------------------------------------------- -// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor -// instances. -// ----------------------------------------------------------------------------- -void add_def_obj(const void* def, VALUE value); -VALUE get_def_obj(const void* def); +void StringBuilder_PrintMsgval(StringBuilder* b, upb_msgval val, TypeInfo info); // ----------------------------------------------------------------------------- // Utilities. // ----------------------------------------------------------------------------- -void check_upb_status(const upb_status* status, const char* msg); +extern VALUE cTypeError; -#define CHECK_UPB(code, msg) do { \ - upb_status status = UPB_STATUS_INIT; \ - code; \ - check_upb_status(&status, msg); \ -} while (0) +#ifdef NDEBUG +#define PBRUBY_ASSERT(expr) do {} while (false && (expr)) +#else +#define PBRUBY_ASSERT(expr) assert(expr) +#endif -extern ID descriptor_instancevar_interned; +#define UPB_UNUSED(var) (void)var #endif // __GOOGLE_PROTOBUF_RUBY_PROTOBUF_H__ diff --git a/ruby/ext/google/protobuf_c/repeated_field.c b/ruby/ext/google/protobuf_c/repeated_field.c index 1c651c192ddcf..65ca3c664791d 100644 --- a/ruby/ext/google/protobuf_c/repeated_field.c +++ b/ruby/ext/google/protobuf_c/repeated_field.c @@ -28,48 +28,162 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include "repeated_field.h" + +#include "convert.h" +#include "defs.h" +#include "message.h" #include "protobuf.h" +#include "third_party/wyhash/wyhash.h" // ----------------------------------------------------------------------------- // Repeated field container type. // ----------------------------------------------------------------------------- +typedef struct { + const upb_array *array; // Can get as mutable when non-frozen. + TypeInfo type_info; + VALUE type_class; // To GC-root the msgdef/enumdef in type_info. + VALUE arena; // To GC-root the upb_array. +} RepeatedField; + +VALUE cRepeatedField; + +static void RepeatedField_mark(void* _self) { + RepeatedField* self = (RepeatedField*)_self; + rb_gc_mark(self->type_class); + rb_gc_mark(self->arena); +} + const rb_data_type_t RepeatedField_type = { "Google::Protobuf::RepeatedField", - { RepeatedField_mark, RepeatedField_free, NULL }, + { RepeatedField_mark, RUBY_DEFAULT_FREE, NULL }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, }; -VALUE cRepeatedField; - -RepeatedField* ruby_to_RepeatedField(VALUE _self) { +static RepeatedField* ruby_to_RepeatedField(VALUE _self) { RepeatedField* self; TypedData_Get_Struct(_self, RepeatedField, &RepeatedField_type, self); return self; } -void* RepeatedField_memoryat(RepeatedField* self, int index, int element_size) { - return ((uint8_t *)self->elements) + index * element_size; +static upb_array *RepeatedField_GetMutable(VALUE _self) { + rb_check_frozen(_self); + return (upb_array*)ruby_to_RepeatedField(_self)->array; +} + +VALUE RepeatedField_alloc(VALUE klass) { + RepeatedField* self = ALLOC(RepeatedField); + self->arena = Qnil; + self->type_class = Qnil; + self->array = NULL; + return TypedData_Wrap_Struct(klass, &RepeatedField_type, self); +} + +VALUE RepeatedField_GetRubyWrapper(upb_array* array, TypeInfo type_info, + VALUE arena) { + PBRUBY_ASSERT(array); + VALUE val = ObjectCache_Get(array); + + if (val == Qnil) { + val = RepeatedField_alloc(cRepeatedField); + RepeatedField* self; + ObjectCache_Add(array, val, Arena_get(arena)); + TypedData_Get_Struct(val, RepeatedField, &RepeatedField_type, self); + self->array = array; + self->arena = arena; + self->type_info = type_info; + if (self->type_info.type == UPB_TYPE_MESSAGE) { + self->type_class = Descriptor_DefToClass(type_info.def.msgdef); + } + } + + PBRUBY_ASSERT(ruby_to_RepeatedField(val)->type_info.type == type_info.type); + PBRUBY_ASSERT(ruby_to_RepeatedField(val)->type_info.def.msgdef == + type_info.def.msgdef); + return val; +} + +static VALUE RepeatedField_new_this_type(RepeatedField* from) { + VALUE arena_rb = Arena_new(); + upb_array *array = upb_array_new(Arena_get(arena_rb), from->type_info.type); + VALUE ret = RepeatedField_GetRubyWrapper(array, from->type_info, arena_rb); + PBRUBY_ASSERT(ruby_to_RepeatedField(ret)->type_class == from->type_class); + return ret; +} + +void RepeatedField_Inspect(StringBuilder* b, const upb_array* array, + TypeInfo info) { + bool first = true; + StringBuilder_Printf(b, "["); + size_t n = array ? upb_array_size(array) : 0; + for (size_t i = 0; i < n; i++) { + if (first) { + first = false; + } else { + StringBuilder_Printf(b, ", "); + } + StringBuilder_PrintMsgval(b, upb_array_get(array, i), info); + } + StringBuilder_Printf(b, "]"); +} + +VALUE RepeatedField_deep_copy(VALUE _self) { + RepeatedField* self = ruby_to_RepeatedField(_self); + VALUE new_rptfield = RepeatedField_new_this_type(self); + RepeatedField* new_self = ruby_to_RepeatedField(new_rptfield); + VALUE arena_rb = new_self->arena; + upb_array *new_array = RepeatedField_GetMutable(new_rptfield); + upb_arena *arena = Arena_get(arena_rb); + size_t elements = upb_array_size(self->array); + + upb_array_resize(new_array, elements, arena); + + size_t size = upb_array_size(self->array); + for (size_t i = 0; i < size; i++) { + upb_msgval msgval = upb_array_get(self->array, i); + upb_msgval copy = Msgval_DeepCopy(msgval, self->type_info, arena); + upb_array_set(new_array, i, copy); + } + + return new_rptfield; +} + +const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef *field) { + RepeatedField* self; + TypeInfo type_info = TypeInfo_get(field); + + if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) || + RTYPEDDATA_TYPE(val) != &RepeatedField_type) { + rb_raise(cTypeError, "Expected repeated field array"); + } + + self = ruby_to_RepeatedField(val); + if (self->type_info.type != type_info.type) { + rb_raise(cTypeError, "Repeated field array has wrong element type"); + } + + if (self->type_info.def.msgdef != type_info.def.msgdef) { + rb_raise(cTypeError, "Repeated field array has wrong message/enum class"); + } + + return self->array; } static int index_position(VALUE _index, RepeatedField* repeated_field) { int index = NUM2INT(_index); - if (index < 0 && repeated_field->size > 0) { - index = repeated_field->size + index; - } + if (index < 0) index += upb_array_size(repeated_field->array); return index; } -VALUE RepeatedField_subarray(VALUE _self, long beg, long len) { - RepeatedField* self = ruby_to_RepeatedField(_self); - int element_size = native_slot_size(self->field_type); - upb_fieldtype_t field_type = self->field_type; - VALUE field_type_class = self->field_type_class; - - size_t off = beg * element_size; - VALUE ary = rb_ary_new2(len); - for (int i = beg; i < beg + len; i++, off += element_size) { - void* mem = ((uint8_t *)self->elements) + off; - VALUE elem = native_slot_get(field_type, field_type_class, mem); +static VALUE RepeatedField_subarray(RepeatedField* self, long beg, long len) { + size_t size = upb_array_size(self->array); + VALUE ary = rb_ary_new2(size); + long i; + + for (i = beg; i < beg + len; i++) { + upb_msgval msgval = upb_array_get(self->array, i); + VALUE elem = Convert_UpbToRuby(msgval, self->type_info, self->arena); rb_ary_push(ary, elem); } return ary; @@ -83,16 +197,14 @@ VALUE RepeatedField_subarray(VALUE _self, long beg, long len) { * also includes Enumerable; combined with this method, the repeated field thus * acts like an ordinary Ruby sequence. */ -VALUE RepeatedField_each(VALUE _self) { +static VALUE RepeatedField_each(VALUE _self) { RepeatedField* self = ruby_to_RepeatedField(_self); - upb_fieldtype_t field_type = self->field_type; - VALUE field_type_class = self->field_type_class; - int element_size = native_slot_size(field_type); - - size_t off = 0; - for (int i = 0; i < self->size; i++, off += element_size) { - void* memory = (void *) (((uint8_t *)self->elements) + off); - VALUE val = native_slot_get(field_type, field_type_class, memory); + int size = upb_array_size(self->array); + int i; + + for (i = 0; i < size; i++) { + upb_msgval msgval = upb_array_get(self->array, i); + VALUE val = Convert_UpbToRuby(msgval, self->type_info, self->arena); rb_yield(val); } return _self; @@ -105,11 +217,9 @@ VALUE RepeatedField_each(VALUE _self) { * * Accesses the element at the given index. Returns nil on out-of-bounds */ -VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) { +static VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) { RepeatedField* self = ruby_to_RepeatedField(_self); - int element_size = native_slot_size(self->field_type); - upb_fieldtype_t field_type = self->field_type; - VALUE field_type_class = self->field_type_class; + long size = upb_array_size(self->array); VALUE arg = argv[0]; long beg, len; @@ -117,35 +227,36 @@ VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) { if (argc == 1){ if (FIXNUM_P(arg)) { /* standard case */ - void* memory; + upb_msgval msgval; int index = index_position(argv[0], self); - if (index < 0 || index >= self->size) { + if (index < 0 || (size_t)index >= upb_array_size(self->array)) { return Qnil; } - memory = RepeatedField_memoryat(self, index, element_size); - return native_slot_get(field_type, field_type_class, memory); - }else{ + msgval = upb_array_get(self->array, index); + return Convert_UpbToRuby(msgval, self->type_info, self->arena); + } else { /* check if idx is Range */ - switch (rb_range_beg_len(arg, &beg, &len, self->size, 0)) { + switch (rb_range_beg_len(arg, &beg, &len, size, 0)) { case Qfalse: break; case Qnil: return Qnil; default: - return RepeatedField_subarray(_self, beg, len); + return RepeatedField_subarray(self, beg, len); } } } + /* assume 2 arguments */ beg = NUM2LONG(argv[0]); len = NUM2LONG(argv[1]); if (beg < 0) { - beg += self->size; + beg += size; } - if (beg >= self->size) { + if (beg >= size) { return Qnil; } - return RepeatedField_subarray(_self, beg, len); + return RepeatedField_subarray(self, beg, len); } /* @@ -155,119 +266,88 @@ VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) { * Sets the element at the given index. On out-of-bounds assignments, extends * the array and fills the hole (if any) with default values. */ -VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) { +static VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) { RepeatedField* self = ruby_to_RepeatedField(_self); - upb_fieldtype_t field_type = self->field_type; - VALUE field_type_class = self->field_type_class; - int element_size = native_slot_size(field_type); - void* memory; + int size = upb_array_size(self->array); + upb_array *array = RepeatedField_GetMutable(_self); + upb_arena *arena = Arena_get(self->arena); + upb_msgval msgval = Convert_RubyToUpb(val, "", self->type_info, arena); int index = index_position(_index, self); if (index < 0 || index >= (INT_MAX - 1)) { return Qnil; } - if (index >= self->size) { - upb_fieldtype_t field_type = self->field_type; - int element_size = native_slot_size(field_type); - RepeatedField_reserve(self, index + 1); - for (int i = self->size; i <= index; i++) { - void* elem = RepeatedField_memoryat(self, i, element_size); - native_slot_init(field_type, elem); + + if (index >= size) { + upb_array_resize(array, index + 1, arena); + upb_msgval fill; + memset(&fill, 0, sizeof(fill)); + for (int i = size; i < index; i++) { + // Fill default values. + // TODO(haberman): should this happen at the upb level? + upb_array_set(array, i, fill); } - self->size = index + 1; } - memory = RepeatedField_memoryat(self, index, element_size); - native_slot_set(field_type, field_type_class, memory, val); + upb_array_set(array, index, msgval); return Qnil; } -static int kInitialSize = 8; - -void RepeatedField_reserve(RepeatedField* self, int new_size) { - void* old_elems = self->elements; - int elem_size = native_slot_size(self->field_type); - if (new_size <= self->capacity) { - return; - } - if (self->capacity == 0) { - self->capacity = kInitialSize; - } - while (self->capacity < new_size) { - self->capacity *= 2; - } - self->elements = ALLOC_N(uint8_t, elem_size * self->capacity); - if (old_elems != NULL) { - memcpy(self->elements, old_elems, self->size * elem_size); - xfree(old_elems); - } -} - /* * call-seq: - * RepeatedField.push(value) + * RepeatedField.push(value, ...) * * Adds a new element to the repeated field. */ -VALUE RepeatedField_push(VALUE _self, VALUE val) { +static VALUE RepeatedField_push_vararg(int argc, VALUE* argv, VALUE _self) { RepeatedField* self = ruby_to_RepeatedField(_self); - upb_fieldtype_t field_type = self->field_type; - int element_size = native_slot_size(field_type); - void* memory; - - RepeatedField_reserve(self, self->size + 1); - memory = (void *) (((uint8_t *)self->elements) + self->size * element_size); - native_slot_set(field_type, self->field_type_class, memory, val); - // native_slot_set may raise an error; bump size only after set. - self->size++; - return _self; -} + upb_arena *arena = Arena_get(self->arena); + upb_array *array = RepeatedField_GetMutable(_self); + int i; + for (i = 0; i < argc; i++) { + upb_msgval msgval = Convert_RubyToUpb(argv[i], "", self->type_info, arena); + upb_array_append(array, msgval, arena); + } -// Used by parsing handlers. -void RepeatedField_push_native(VALUE _self, void* data) { - RepeatedField* self = ruby_to_RepeatedField(_self); - upb_fieldtype_t field_type = self->field_type; - int element_size = native_slot_size(field_type); - void* memory; - - RepeatedField_reserve(self, self->size + 1); - memory = (void *) (((uint8_t *)self->elements) + self->size * element_size); - memcpy(memory, data, element_size); - self->size++; + return _self; } -void* RepeatedField_index_native(VALUE _self, int index) { +/* + * call-seq: + * RepeatedField.<<(value) + * + * Adds a new element to the repeated field. + */ +static VALUE RepeatedField_push(VALUE _self, VALUE val) { RepeatedField* self = ruby_to_RepeatedField(_self); - upb_fieldtype_t field_type = self->field_type; - int element_size = native_slot_size(field_type); - return RepeatedField_memoryat(self, index, element_size); -} + upb_arena *arena = Arena_get(self->arena); + upb_array *array = RepeatedField_GetMutable(_self); -int RepeatedField_size(VALUE _self) { - RepeatedField* self = ruby_to_RepeatedField(_self); - return self->size; + upb_msgval msgval = Convert_RubyToUpb(val, "", self->type_info, arena); + upb_array_append(array, msgval, arena); + + return _self; } /* * Private ruby method, used by RepeatedField.pop */ -VALUE RepeatedField_pop_one(VALUE _self) { +static VALUE RepeatedField_pop_one(VALUE _self) { RepeatedField* self = ruby_to_RepeatedField(_self); - upb_fieldtype_t field_type = self->field_type; - VALUE field_type_class = self->field_type_class; - int element_size = native_slot_size(field_type); - int index; - void* memory; + size_t size = upb_array_size(self->array); + upb_array *array = RepeatedField_GetMutable(_self); + upb_msgval last; VALUE ret; - if (self->size == 0) { + if (size == 0) { return Qnil; } - index = self->size - 1; - memory = RepeatedField_memoryat(self, index, element_size); - ret = native_slot_get(field_type, field_type_class, memory); - self->size--; + + last = upb_array_get(self->array, size - 1); + ret = Convert_UpbToRuby(last, self->type_info, self->arena); + + upb_array_resize(array, size - 1, Arena_get(self->arena)); return ret; } @@ -277,13 +357,18 @@ VALUE RepeatedField_pop_one(VALUE _self) { * * Replaces the contents of the repeated field with the given list of elements. */ -VALUE RepeatedField_replace(VALUE _self, VALUE list) { +static VALUE RepeatedField_replace(VALUE _self, VALUE list) { RepeatedField* self = ruby_to_RepeatedField(_self); + upb_array *array = RepeatedField_GetMutable(_self); + int i; + Check_Type(list, T_ARRAY); - self->size = 0; - for (int i = 0; i < RARRAY_LEN(list); i++) { + upb_array_resize(array, 0, Arena_get(self->arena)); + + for (i = 0; i < RARRAY_LEN(list); i++) { RepeatedField_push(_self, rb_ary_entry(list, i)); } + return list; } @@ -293,9 +378,10 @@ VALUE RepeatedField_replace(VALUE _self, VALUE list) { * * Clears (removes all elements from) this repeated field. */ -VALUE RepeatedField_clear(VALUE _self) { +static VALUE RepeatedField_clear(VALUE _self) { RepeatedField* self = ruby_to_RepeatedField(_self); - self->size = 0; + upb_array *array = RepeatedField_GetMutable(_self); + upb_array_resize(array, 0, Arena_get(self->arena)); return _self; } @@ -305,23 +391,9 @@ VALUE RepeatedField_clear(VALUE _self) { * * Returns the length of this repeated field. */ -VALUE RepeatedField_length(VALUE _self) { - RepeatedField* self = ruby_to_RepeatedField(_self); - return INT2NUM(self->size); -} - -static VALUE RepeatedField_new_this_type(VALUE _self) { +static VALUE RepeatedField_length(VALUE _self) { RepeatedField* self = ruby_to_RepeatedField(_self); - VALUE new_rptfield = Qnil; - VALUE element_type = fieldtype_to_ruby(self->field_type); - if (self->field_type_class != Qnil) { - new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 2, - element_type, self->field_type_class); - } else { - new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 1, - element_type); - } - return new_rptfield; + return INT2NUM(upb_array_size(self->array)); } /* @@ -331,38 +403,20 @@ static VALUE RepeatedField_new_this_type(VALUE _self) { * Duplicates this repeated field with a shallow copy. References to all * non-primitive element objects (e.g., submessages) are shared. */ -VALUE RepeatedField_dup(VALUE _self) { +static VALUE RepeatedField_dup(VALUE _self) { RepeatedField* self = ruby_to_RepeatedField(_self); - VALUE new_rptfield = RepeatedField_new_this_type(_self); + VALUE new_rptfield = RepeatedField_new_this_type(self); RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield); - upb_fieldtype_t field_type = self->field_type; - size_t elem_size = native_slot_size(field_type); - size_t off = 0; - RepeatedField_reserve(new_rptfield_self, self->size); - for (int i = 0; i < self->size; i++, off += elem_size) { - void* to_mem = (uint8_t *)new_rptfield_self->elements + off; - void* from_mem = (uint8_t *)self->elements + off; - native_slot_dup(field_type, to_mem, from_mem); - new_rptfield_self->size++; - } + upb_array *new_array = RepeatedField_GetMutable(new_rptfield); + upb_arena* arena = Arena_get(new_rptfield_self->arena); + int size = upb_array_size(self->array); + int i; - return new_rptfield; -} + upb_arena_fuse(arena, Arena_get(self->arena)); -// Internal only: used by Google::Protobuf.deep_copy. -VALUE RepeatedField_deep_copy(VALUE _self) { - RepeatedField* self = ruby_to_RepeatedField(_self); - VALUE new_rptfield = RepeatedField_new_this_type(_self); - RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield); - upb_fieldtype_t field_type = self->field_type; - size_t elem_size = native_slot_size(field_type); - size_t off = 0; - RepeatedField_reserve(new_rptfield_self, self->size); - for (int i = 0; i < self->size; i++, off += elem_size) { - void* to_mem = (uint8_t *)new_rptfield_self->elements + off; - void* from_mem = (uint8_t *)self->elements + off; - native_slot_deep_copy(field_type, to_mem, from_mem); - new_rptfield_self->size++; + for (i = 0; i < size; i++) { + upb_msgval msgval = upb_array_get(self->array, i); + upb_array_append(new_array, msgval, arena); } return new_rptfield; @@ -377,16 +431,16 @@ VALUE RepeatedField_deep_copy(VALUE _self) { */ VALUE RepeatedField_to_ary(VALUE _self) { RepeatedField* self = ruby_to_RepeatedField(_self); - upb_fieldtype_t field_type = self->field_type; - - size_t elem_size = native_slot_size(field_type); - size_t off = 0; - VALUE ary = rb_ary_new2(self->size); - for (int i = 0; i < self->size; i++, off += elem_size) { - void* mem = ((uint8_t *)self->elements) + off; - VALUE elem = native_slot_get(field_type, self->field_type_class, mem); - rb_ary_push(ary, elem); + int size = upb_array_size(self->array); + VALUE ary = rb_ary_new2(size); + int i; + + for (i = 0; i < size; i++) { + upb_msgval msgval = upb_array_get(self->array, i); + VALUE val = Convert_UpbToRuby(msgval, self->type_info, self->arena); + rb_ary_push(ary, val); } + return ary; } @@ -418,25 +472,38 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) { self = ruby_to_RepeatedField(_self); other = ruby_to_RepeatedField(_other); - if (self->field_type != other->field_type || - self->field_type_class != other->field_type_class || - self->size != other->size) { + size_t n = upb_array_size(self->array); + + if (self->type_info.type != other->type_info.type || + self->type_class != other->type_class || + upb_array_size(other->array) != n) { return Qfalse; } - { - upb_fieldtype_t field_type = self->field_type; - size_t elem_size = native_slot_size(field_type); - size_t off = 0; - for (int i = 0; i < self->size; i++, off += elem_size) { - void* self_mem = ((uint8_t *)self->elements) + off; - void* other_mem = ((uint8_t *)other->elements) + off; - if (!native_slot_eq(field_type, self_mem, other_mem)) { - return Qfalse; - } + for (size_t i = 0; i < n; i++) { + upb_msgval val1 = upb_array_get(self->array, i); + upb_msgval val2 = upb_array_get(other->array, i); + if (!Msgval_IsEqual(val1, val2, self->type_info)) { + return Qfalse; } - return Qtrue; } + + return Qtrue; +} + +/* + * call-seq: + * RepeatedField.freeze => self + * + * Freezes the repeated field. We have to intercept this so we can pin the Ruby + * object into memory so we don't forget it's frozen. + */ +static VALUE RepeatedField_freeze(VALUE _self) { + RepeatedField* self = ruby_to_RepeatedField(_self); + + ObjectCache_Pin(self->array, _self, Arena_get(self->arena)); + RB_OBJ_FREEZE(_self); + return _self; } /* @@ -447,20 +514,15 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) { */ VALUE RepeatedField_hash(VALUE _self) { RepeatedField* self = ruby_to_RepeatedField(_self); - st_index_t h = rb_hash_start(0); - VALUE hash_sym = rb_intern("hash"); - upb_fieldtype_t field_type = self->field_type; - VALUE field_type_class = self->field_type_class; - size_t elem_size = native_slot_size(field_type); - size_t off = 0; - for (int i = 0; i < self->size; i++, off += elem_size) { - void* mem = ((uint8_t *)self->elements) + off; - VALUE elem = native_slot_get(field_type, field_type_class, mem); - h = rb_hash_uint(h, NUM2LONG(rb_funcall(elem, hash_sym, 0))); + uint64_t hash = 0; + size_t n = upb_array_size(self->array); + + for (size_t i = 0; i < n; i++) { + upb_msgval val = upb_array_get(self->array, i); + hash = Msgval_GetHash(val, self->type_info, hash); } - h = rb_hash_end(h); - return INT2FIX(h); + return LL2NUM(hash); } /* @@ -472,31 +534,39 @@ VALUE RepeatedField_hash(VALUE _self) { * be either another repeated field or a Ruby array. */ VALUE RepeatedField_plus(VALUE _self, VALUE list) { - VALUE dupped = RepeatedField_dup(_self); + VALUE dupped_ = RepeatedField_dup(_self); if (TYPE(list) == T_ARRAY) { - for (int i = 0; i < RARRAY_LEN(list); i++) { + int i; + for (i = 0; i < RARRAY_LEN(list); i++) { VALUE elem = rb_ary_entry(list, i); - RepeatedField_push(dupped, elem); + RepeatedField_push(dupped_, elem); } } else if (RB_TYPE_P(list, T_DATA) && RTYPEDDATA_P(list) && RTYPEDDATA_TYPE(list) == &RepeatedField_type) { RepeatedField* self = ruby_to_RepeatedField(_self); RepeatedField* list_rptfield = ruby_to_RepeatedField(list); - if (self->field_type != list_rptfield->field_type || - self->field_type_class != list_rptfield->field_type_class) { + RepeatedField* dupped = ruby_to_RepeatedField(dupped_); + upb_array *dupped_array = RepeatedField_GetMutable(dupped_); + upb_arena* arena = Arena_get(dupped->arena); + int size = upb_array_size(list_rptfield->array); + int i; + + if (self->type_info.type != list_rptfield->type_info.type || + self->type_class != list_rptfield->type_class) { rb_raise(rb_eArgError, "Attempt to append RepeatedField with different element type."); } - for (int i = 0; i < list_rptfield->size; i++) { - void* mem = RepeatedField_index_native(list, i); - RepeatedField_push_native(dupped, mem); + + for (i = 0; i < size; i++) { + upb_msgval msgval = upb_array_get(list_rptfield->array, i); + upb_array_append(dupped_array, msgval, arena); } } else { rb_raise(rb_eArgError, "Unknown type appending to RepeatedField"); } - return dupped; + return dupped_; } /* @@ -506,66 +576,41 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) { * concats the passed in array to self. Returns a Ruby array. */ VALUE RepeatedField_concat(VALUE _self, VALUE list) { + int i; + Check_Type(list, T_ARRAY); - for (int i = 0; i < RARRAY_LEN(list); i++) { + for (i = 0; i < RARRAY_LEN(list); i++) { RepeatedField_push(_self, rb_ary_entry(list, i)); } return _self; } - -void validate_type_class(upb_fieldtype_t type, VALUE klass) { - if (rb_ivar_get(klass, descriptor_instancevar_interned) == Qnil) { - rb_raise(rb_eArgError, - "Type class has no descriptor. Please pass a " - "class or enum as returned by the DescriptorPool."); - } - if (type == UPB_TYPE_MESSAGE) { - VALUE desc = rb_ivar_get(klass, descriptor_instancevar_interned); - if (!RB_TYPE_P(desc, T_DATA) || !RTYPEDDATA_P(desc) || - RTYPEDDATA_TYPE(desc) != &_Descriptor_type) { - rb_raise(rb_eArgError, "Descriptor has an incorrect type."); - } - if (rb_get_alloc_func(klass) != &Message_alloc) { - rb_raise(rb_eArgError, - "Message class was not returned by the DescriptorPool."); - } - } else if (type == UPB_TYPE_ENUM) { - VALUE enumdesc = rb_ivar_get(klass, descriptor_instancevar_interned); - if (!RB_TYPE_P(enumdesc, T_DATA) || !RTYPEDDATA_P(enumdesc) || - RTYPEDDATA_TYPE(enumdesc) != &_EnumDescriptor_type) { - rb_raise(rb_eArgError, "Descriptor has an incorrect type."); - } - } -} - -void RepeatedField_init_args(int argc, VALUE* argv, - VALUE _self) { +/* + * call-seq: + * RepeatedField.new(type, type_class = nil, initial_elems = []) + * + * Creates a new repeated field. The provided type must be a Ruby symbol, and + * can take on the same values as those accepted by FieldDescriptor#type=. If + * the type is :message or :enum, type_class must be non-nil, and must be the + * Ruby class or module returned by Descriptor#msgclass or + * EnumDescriptor#enummodule, respectively. An initial list of elements may also + * be provided. + */ +VALUE RepeatedField_init(int argc, VALUE* argv, VALUE _self) { RepeatedField* self = ruby_to_RepeatedField(_self); + upb_arena *arena; VALUE ary = Qnil; + + self->arena = Arena_new(); + arena = Arena_get(self->arena); + if (argc < 1) { rb_raise(rb_eArgError, "Expected at least 1 argument."); } - self->field_type = ruby_to_fieldtype(argv[0]); - if (self->field_type == UPB_TYPE_MESSAGE || - self->field_type == UPB_TYPE_ENUM) { - if (argc < 2) { - rb_raise(rb_eArgError, "Expected at least 2 arguments for message/enum."); - } - self->field_type_class = argv[1]; - if (argc > 2) { - ary = argv[2]; - } - validate_type_class(self->field_type, self->field_type_class); - } else { - if (argc > 2) { - rb_raise(rb_eArgError, "Too many arguments: expected 1 or 2."); - } - if (argc > 1) { - ary = argv[1]; - } - } + self->type_info = TypeInfo_FromClass(argc, argv, 0, &self->type_class, &ary); + self->array = upb_array_new(arena, self->type_info.type); + ObjectCache_Add(self->array, _self, arena); if (ary != Qnil) { if (!RB_TYPE_P(ary, T_ARRAY)) { @@ -575,50 +620,6 @@ void RepeatedField_init_args(int argc, VALUE* argv, RepeatedField_push(_self, rb_ary_entry(ary, i)); } } -} - -// Mark, free, alloc, init and class setup functions. - -void RepeatedField_mark(void* _self) { - RepeatedField* self = (RepeatedField*)_self; - upb_fieldtype_t field_type = self->field_type; - int element_size = native_slot_size(field_type); - rb_gc_mark(self->field_type_class); - for (int i = 0; i < self->size; i++) { - void* memory = (((uint8_t *)self->elements) + i * element_size); - native_slot_mark(self->field_type, memory); - } -} - -void RepeatedField_free(void* _self) { - RepeatedField* self = (RepeatedField*)_self; - xfree(self->elements); - xfree(self); -} - -/* - * call-seq: - * RepeatedField.new(type, type_class = nil, initial_elems = []) - * - * Creates a new repeated field. The provided type must be a Ruby symbol, and - * can take on the same values as those accepted by FieldDescriptor#type=. If - * the type is :message or :enum, type_class must be non-nil, and must be the - * Ruby class or module returned by Descriptor#msgclass or - * EnumDescriptor#enummodule, respectively. An initial list of elements may also - * be provided. - */ -VALUE RepeatedField_alloc(VALUE klass) { - RepeatedField* self = ALLOC(RepeatedField); - self->elements = NULL; - self->size = 0; - self->capacity = 0; - self->field_type = -1; - self->field_type_class = Qnil; - return TypedData_Wrap_Struct(klass, &RepeatedField_type, self); -} - -VALUE RepeatedField_init(int argc, VALUE* argv, VALUE self) { - RepeatedField_init_args(argc, argv, self); return Qnil; } @@ -626,8 +627,8 @@ void RepeatedField_register(VALUE module) { VALUE klass = rb_define_class_under( module, "RepeatedField", rb_cObject); rb_define_alloc_func(klass, RepeatedField_alloc); - cRepeatedField = klass; rb_gc_register_address(&cRepeatedField); + cRepeatedField = klass; rb_define_method(klass, "initialize", RepeatedField_init, -1); @@ -635,7 +636,7 @@ void RepeatedField_register(VALUE module) { rb_define_method(klass, "[]", RepeatedField_index, -1); rb_define_method(klass, "at", RepeatedField_index, -1); rb_define_method(klass, "[]=", RepeatedField_index_set, 2); - rb_define_method(klass, "push", RepeatedField_push, 1); + rb_define_method(klass, "push", RepeatedField_push_vararg, -1); rb_define_method(klass, "<<", RepeatedField_push, 1); rb_define_private_method(klass, "pop_one", RepeatedField_pop_one, 0); rb_define_method(klass, "replace", RepeatedField_replace, 1); @@ -647,6 +648,7 @@ void RepeatedField_register(VALUE module) { rb_define_method(klass, "clone", RepeatedField_dup, 0); rb_define_method(klass, "==", RepeatedField_eq, 1); rb_define_method(klass, "to_ary", RepeatedField_to_ary, 0); + rb_define_method(klass, "freeze", RepeatedField_freeze, 0); rb_define_method(klass, "hash", RepeatedField_hash, 0); rb_define_method(klass, "+", RepeatedField_plus, 1); rb_define_method(klass, "concat", RepeatedField_concat, 1); diff --git a/ruby/ext/google/protobuf_c/repeated_field.h b/ruby/ext/google/protobuf_c/repeated_field.h new file mode 100644 index 0000000000000..5a5959dd837b1 --- /dev/null +++ b/ruby/ext/google/protobuf_c/repeated_field.h @@ -0,0 +1,62 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef RUBY_PROTOBUF_REPEATED_FIELD_H_ +#define RUBY_PROTOBUF_REPEATED_FIELD_H_ + +#include + +#include "protobuf.h" +#include "ruby-upb.h" + +// Returns a Ruby wrapper object for the given upb_array, which will be created +// if one does not exist already. +VALUE RepeatedField_GetRubyWrapper(upb_array* msg, TypeInfo type_info, + VALUE arena); + +// Gets the underlying upb_array for this Ruby RepeatedField object, which must +// have a type that matches |f|. If this is not a repeated field or the type +// doesn't match, raises an exception. +const upb_array* RepeatedField_GetUpbArray(VALUE value, const upb_fielddef* f); + +// Implements #inspect for this repeated field by appending its contents to |b|. +void RepeatedField_Inspect(StringBuilder* b, const upb_array* array, + TypeInfo info); + +// Returns a deep copy of this RepeatedField object. +VALUE RepeatedField_deep_copy(VALUE obj); + +// Ruby class of Google::Protobuf::RepeatedField. +extern VALUE cRepeatedField; + +// Call at startup to register all types in this module. +void RepeatedField_register(VALUE module); + +#endif // RUBY_PROTOBUF_REPEATED_FIELD_H_ diff --git a/ruby/ext/google/protobuf_c/ruby-upb.c b/ruby/ext/google/protobuf_c/ruby-upb.c new file mode 100755 index 0000000000000..a7aeda2df2532 --- /dev/null +++ b/ruby/ext/google/protobuf_c/ruby-upb.c @@ -0,0 +1,8915 @@ +/* Amalgamated source file */ +#include "ruby-upb.h" +/* +* This is where we define macros used across upb. +* +* All of these macros are undef'd in port_undef.inc to avoid leaking them to +* users. +* +* The correct usage is: +* +* #include "upb/foobar.h" +* #include "upb/baz.h" +* +* // MUST be last included header. +* #include "upb/port_def.inc" +* +* // Code for this file. +* // <...> +* +* // Can be omitted for .c files, required for .h. +* #include "upb/port_undef.inc" +* +* This file is private and must not be included by users! +*/ + +#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) || \ + (defined(_MSC_VER) && _MSC_VER >= 1900)) +#error upb requires C99 or C++11 or MSVC >= 2015. +#endif + +#include +#include + +#if UINTPTR_MAX == 0xffffffff +#define UPB_SIZE(size32, size64) size32 +#else +#define UPB_SIZE(size32, size64) size64 +#endif + +/* If we always read/write as a consistent type to each address, this shouldn't + * violate aliasing. + */ +#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs))) + +#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \ + *UPB_PTR_AT(msg, case_offset, int) == case_val \ + ? *UPB_PTR_AT(msg, offset, fieldtype) \ + : default + +#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \ + *UPB_PTR_AT(msg, case_offset, int) = case_val; \ + *UPB_PTR_AT(msg, offset, fieldtype) = value; + +#define UPB_MAPTYPE_STRING 0 + +/* UPB_INLINE: inline if possible, emit standalone code if required. */ +#ifdef __cplusplus +#define UPB_INLINE inline +#elif defined (__GNUC__) || defined(__clang__) +#define UPB_INLINE static __inline__ +#else +#define UPB_INLINE static +#endif + +#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align)) +#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align)) +#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16) +#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member) + +/* Hints to the compiler about likely/unlikely branches. */ +#if defined (__GNUC__) || defined(__clang__) +#define UPB_LIKELY(x) __builtin_expect((x),1) +#define UPB_UNLIKELY(x) __builtin_expect((x),0) +#else +#define UPB_LIKELY(x) (x) +#define UPB_UNLIKELY(x) (x) +#endif + +/* Macros for function attributes on compilers that support them. */ +#ifdef __GNUC__ +#define UPB_FORCEINLINE __inline__ __attribute__((always_inline)) +#define UPB_NOINLINE __attribute__((noinline)) +#define UPB_NORETURN __attribute__((__noreturn__)) +#define UPB_PRINTF(str, first_vararg) __attribute__((format (printf, str, first_vararg))) +#elif defined(_MSC_VER) +#define UPB_NOINLINE +#define UPB_FORCEINLINE +#define UPB_NORETURN __declspec(noreturn) +#define UPB_PRINTF(str, first_vararg) +#else /* !defined(__GNUC__) */ +#define UPB_FORCEINLINE +#define UPB_NOINLINE +#define UPB_NORETURN +#define UPB_PRINTF(str, first_vararg) +#endif + +#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) +#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y)) + +#define UPB_UNUSED(var) (void)var + +/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true. + */ +#ifdef NDEBUG +#ifdef __GNUC__ +#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable() +#elif defined _MSC_VER +#define UPB_ASSUME(expr) if (!(expr)) __assume(0) +#else +#define UPB_ASSUME(expr) do {} while (false && (expr)) +#endif +#else +#define UPB_ASSUME(expr) assert(expr) +#endif + +/* UPB_ASSERT(): in release mode, we use the expression without letting it be + * evaluated. This prevents "unused variable" warnings. */ +#ifdef NDEBUG +#define UPB_ASSERT(expr) do {} while (false && (expr)) +#else +#define UPB_ASSERT(expr) assert(expr) +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0) +#else +#define UPB_UNREACHABLE() do { assert(0); } while(0) +#endif + +/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */ +#ifdef __APPLE__ +#define UPB_SETJMP(buf) _setjmp(buf) +#define UPB_LONGJMP(buf, val) _longjmp(buf, val) +#else +#define UPB_SETJMP(buf) setjmp(buf) +#define UPB_LONGJMP(buf, val) longjmp(buf, val) +#endif + +/* Configure whether fasttable is switched on or not. *************************/ + +#if defined(__x86_64__) && defined(__GNUC__) +#define UPB_FASTTABLE_SUPPORTED 1 +#else +#define UPB_FASTTABLE_SUPPORTED 0 +#endif + +/* define UPB_ENABLE_FASTTABLE to force fast table support. + * This is useful when we want to ensure we are really getting fasttable, + * for example for testing or benchmarking. */ +#if defined(UPB_ENABLE_FASTTABLE) +#if !UPB_FASTTABLE_SUPPORTED +#error fasttable is x86-64 + Clang/GCC only +#endif +#define UPB_FASTTABLE 1 +/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible. + * This is useful for releasing code that might be used on multiple platforms, + * for example the PHP or Ruby C extensions. */ +#elif defined(UPB_TRY_ENABLE_FASTTABLE) +#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED +#else +#define UPB_FASTTABLE 0 +#endif + +/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully + * degrade to non-fasttable if we are using UPB_TRY_ENABLE_FASTTABLE. */ +#if !UPB_FASTTABLE && defined(UPB_TRY_ENABLE_FASTTABLE) +#define UPB_FASTTABLE_INIT(...) +#else +#define UPB_FASTTABLE_INIT(...) __VA_ARGS__ +#endif + +#undef UPB_FASTTABLE_SUPPORTED + +/* ASAN poisoning (for arena) *************************************************/ + +#if defined(__SANITIZE_ADDRESS__) +#define UPB_ASAN 1 +#ifdef __cplusplus +extern "C" { +#endif +void __asan_poison_memory_region(void const volatile *addr, size_t size); +void __asan_unpoison_memory_region(void const volatile *addr, size_t size); +#ifdef __cplusplus +} /* extern "C" */ +#endif +#define UPB_POISON_MEMORY_REGION(addr, size) \ + __asan_poison_memory_region((addr), (size)) +#define UPB_UNPOISON_MEMORY_REGION(addr, size) \ + __asan_unpoison_memory_region((addr), (size)) +#else +#define UPB_ASAN 0 +#define UPB_POISON_MEMORY_REGION(addr, size) \ + ((void)(addr), (void)(size)) +#define UPB_UNPOISON_MEMORY_REGION(addr, size) \ + ((void)(addr), (void)(size)) +#endif + + +#include +#include + + +/* Must be last. */ + +/* Maps descriptor type -> elem_size_lg2. */ +static const uint8_t desctype_to_elem_size_lg2[] = { + -1, /* invalid descriptor type */ + 3, /* DOUBLE */ + 2, /* FLOAT */ + 3, /* INT64 */ + 3, /* UINT64 */ + 2, /* INT32 */ + 3, /* FIXED64 */ + 2, /* FIXED32 */ + 0, /* BOOL */ + UPB_SIZE(3, 4), /* STRING */ + UPB_SIZE(2, 3), /* GROUP */ + UPB_SIZE(2, 3), /* MESSAGE */ + UPB_SIZE(3, 4), /* BYTES */ + 2, /* UINT32 */ + 2, /* ENUM */ + 2, /* SFIXED32 */ + 3, /* SFIXED64 */ + 2, /* SINT32 */ + 3, /* SINT64 */ +}; + +/* Maps descriptor type -> upb map size. */ +static const uint8_t desctype_to_mapsize[] = { + -1, /* invalid descriptor type */ + 8, /* DOUBLE */ + 4, /* FLOAT */ + 8, /* INT64 */ + 8, /* UINT64 */ + 4, /* INT32 */ + 8, /* FIXED64 */ + 4, /* FIXED32 */ + 1, /* BOOL */ + UPB_MAPTYPE_STRING, /* STRING */ + sizeof(void *), /* GROUP */ + sizeof(void *), /* MESSAGE */ + UPB_MAPTYPE_STRING, /* BYTES */ + 4, /* UINT32 */ + 4, /* ENUM */ + 4, /* SFIXED32 */ + 8, /* SFIXED64 */ + 4, /* SINT32 */ + 8, /* SINT64 */ +}; + +static const unsigned fixed32_ok = (1 << UPB_DTYPE_FLOAT) | + (1 << UPB_DTYPE_FIXED32) | + (1 << UPB_DTYPE_SFIXED32); + +static const unsigned fixed64_ok = (1 << UPB_DTYPE_DOUBLE) | + (1 << UPB_DTYPE_FIXED64) | + (1 << UPB_DTYPE_SFIXED64); + +/* Op: an action to be performed for a wire-type/field-type combination. */ +#define OP_SCALAR_LG2(n) (n) /* n in [0, 2, 3] => op in [0, 2, 3] */ +#define OP_STRING 4 +#define OP_BYTES 5 +#define OP_SUBMSG 6 +/* Ops above are scalar-only. Repeated fields can use any op. */ +#define OP_FIXPCK_LG2(n) (n + 5) /* n in [2, 3] => op in [7, 8] */ +#define OP_VARPCK_LG2(n) (n + 9) /* n in [0, 2, 3] => op in [9, 11, 12] */ + +static const int8_t varint_ops[19] = { + -1, /* field not found */ + -1, /* DOUBLE */ + -1, /* FLOAT */ + OP_SCALAR_LG2(3), /* INT64 */ + OP_SCALAR_LG2(3), /* UINT64 */ + OP_SCALAR_LG2(2), /* INT32 */ + -1, /* FIXED64 */ + -1, /* FIXED32 */ + OP_SCALAR_LG2(0), /* BOOL */ + -1, /* STRING */ + -1, /* GROUP */ + -1, /* MESSAGE */ + -1, /* BYTES */ + OP_SCALAR_LG2(2), /* UINT32 */ + OP_SCALAR_LG2(2), /* ENUM */ + -1, /* SFIXED32 */ + -1, /* SFIXED64 */ + OP_SCALAR_LG2(2), /* SINT32 */ + OP_SCALAR_LG2(3), /* SINT64 */ +}; + +static const int8_t delim_ops[37] = { + /* For non-repeated field type. */ + -1, /* field not found */ + -1, /* DOUBLE */ + -1, /* FLOAT */ + -1, /* INT64 */ + -1, /* UINT64 */ + -1, /* INT32 */ + -1, /* FIXED64 */ + -1, /* FIXED32 */ + -1, /* BOOL */ + OP_STRING, /* STRING */ + -1, /* GROUP */ + OP_SUBMSG, /* MESSAGE */ + OP_BYTES, /* BYTES */ + -1, /* UINT32 */ + -1, /* ENUM */ + -1, /* SFIXED32 */ + -1, /* SFIXED64 */ + -1, /* SINT32 */ + -1, /* SINT64 */ + /* For repeated field type. */ + OP_FIXPCK_LG2(3), /* REPEATED DOUBLE */ + OP_FIXPCK_LG2(2), /* REPEATED FLOAT */ + OP_VARPCK_LG2(3), /* REPEATED INT64 */ + OP_VARPCK_LG2(3), /* REPEATED UINT64 */ + OP_VARPCK_LG2(2), /* REPEATED INT32 */ + OP_FIXPCK_LG2(3), /* REPEATED FIXED64 */ + OP_FIXPCK_LG2(2), /* REPEATED FIXED32 */ + OP_VARPCK_LG2(0), /* REPEATED BOOL */ + OP_STRING, /* REPEATED STRING */ + OP_SUBMSG, /* REPEATED GROUP */ + OP_SUBMSG, /* REPEATED MESSAGE */ + OP_BYTES, /* REPEATED BYTES */ + OP_VARPCK_LG2(2), /* REPEATED UINT32 */ + OP_VARPCK_LG2(2), /* REPEATED ENUM */ + OP_FIXPCK_LG2(2), /* REPEATED SFIXED32 */ + OP_FIXPCK_LG2(3), /* REPEATED SFIXED64 */ + OP_VARPCK_LG2(2), /* REPEATED SINT32 */ + OP_VARPCK_LG2(3), /* REPEATED SINT64 */ +}; + +typedef union { + bool bool_val; + uint32_t uint32_val; + uint64_t uint64_val; + uint32_t size; +} wireval; + +static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *layout); + +UPB_NORETURN static void decode_err(upb_decstate *d) { UPB_LONGJMP(d->err, 1); } + +// We don't want to mark this NORETURN, see comment in .h. +// Unfortunately this code to suppress the warning doesn't appear to be working. +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma clang diagnostic ignored "-Wsuggest-attribute" +#endif + +const char *fastdecode_err(upb_decstate *d) { + longjmp(d->err, 1); + return NULL; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +const uint8_t upb_utf8_offsets[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static void decode_verifyutf8(upb_decstate *d, const char *buf, int len) { + if (!decode_verifyutf8_inl(buf, len)) decode_err(d); +} + +static bool decode_reserve(upb_decstate *d, upb_array *arr, size_t elem) { + bool need_realloc = arr->size - arr->len < elem; + if (need_realloc && !_upb_array_realloc(arr, arr->len + elem, &d->arena)) { + decode_err(d); + } + return need_realloc; +} + +typedef struct { + const char *ptr; + uint64_t val; +} decode_vret; + +UPB_NOINLINE +static decode_vret decode_longvarint64(const char *ptr, uint64_t val) { + decode_vret ret = {NULL, 0}; + uint64_t byte; + int i; + for (i = 1; i < 10; i++) { + byte = (uint8_t)ptr[i]; + val += (byte - 1) << (i * 7); + if (!(byte & 0x80)) { + ret.ptr = ptr + i + 1; + ret.val = val; + return ret; + } + } + return ret; +} + +UPB_FORCEINLINE +static const char *decode_varint64(upb_decstate *d, const char *ptr, + uint64_t *val) { + uint64_t byte = (uint8_t)*ptr; + if (UPB_LIKELY((byte & 0x80) == 0)) { + *val = byte; + return ptr + 1; + } else { + decode_vret res = decode_longvarint64(ptr, byte); + if (!res.ptr) decode_err(d); + *val = res.val; + return res.ptr; + } +} + +UPB_FORCEINLINE +static const char *decode_tag(upb_decstate *d, const char *ptr, + uint32_t *val) { + uint64_t byte = (uint8_t)*ptr; + if (UPB_LIKELY((byte & 0x80) == 0)) { + *val = byte; + return ptr + 1; + } else { + const char *start = ptr; + decode_vret res = decode_longvarint64(ptr, byte); + ptr = res.ptr; + *val = res.val; + if (!ptr || *val > UINT32_MAX || ptr - start > 5) decode_err(d); + return ptr; + } +} + +static void decode_munge(int type, wireval *val) { + switch (type) { + case UPB_DESCRIPTOR_TYPE_BOOL: + val->bool_val = val->uint64_val != 0; + break; + case UPB_DESCRIPTOR_TYPE_SINT32: { + uint32_t n = val->uint32_val; + val->uint32_val = (n >> 1) ^ -(int32_t)(n & 1); + break; + } + case UPB_DESCRIPTOR_TYPE_SINT64: { + uint64_t n = val->uint64_val; + val->uint64_val = (n >> 1) ^ -(int64_t)(n & 1); + break; + } + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_UINT32: + if (!_upb_isle()) { + /* The next stage will memcpy(dst, &val, 4) */ + val->uint32_val = val->uint64_val; + } + break; + } +} + +static const upb_msglayout_field *upb_find_field(const upb_msglayout *l, + uint32_t field_number) { + static upb_msglayout_field none = {0, 0, 0, 0, 0, 0}; + + /* Lots of optimization opportunities here. */ + int i; + if (l == NULL) return &none; + for (i = 0; i < l->field_count; i++) { + if (l->fields[i].number == field_number) { + return &l->fields[i]; + } + } + + return &none; /* Unknown field. */ +} + +static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout, + const upb_msglayout_field *field) { + const upb_msglayout *subl = layout->submsgs[field->submsg_index]; + return _upb_msg_new_inl(subl, &d->arena); +} + +UPB_NOINLINE +const char *decode_isdonefallback(upb_decstate *d, const char *ptr, + int overrun) { + ptr = decode_isdonefallback_inl(d, ptr, overrun); + if (ptr == NULL) { + decode_err(d); + } + return ptr; +} + +static const char *decode_readstr(upb_decstate *d, const char *ptr, int size, + upb_strview *str) { + if (d->alias) { + str->data = ptr; + } else { + char *data = upb_arena_malloc(&d->arena, size); + if (!data) decode_err(d); + memcpy(data, ptr, size); + str->data = data; + } + str->size = size; + return ptr + size; +} + +UPB_FORCEINLINE +static const char *decode_tosubmsg(upb_decstate *d, const char *ptr, + upb_msg *submsg, const upb_msglayout *layout, + const upb_msglayout_field *field, int size) { + const upb_msglayout *subl = layout->submsgs[field->submsg_index]; + int saved_delta = decode_pushlimit(d, ptr, size); + if (--d->depth < 0) decode_err(d); + if (!decode_isdone(d, &ptr)) { + ptr = decode_msg(d, ptr, submsg, subl); + } + if (d->end_group != DECODE_NOGROUP) decode_err(d); + decode_poplimit(d, ptr, saved_delta); + d->depth++; + return ptr; +} + +UPB_FORCEINLINE +static const char *decode_group(upb_decstate *d, const char *ptr, + upb_msg *submsg, const upb_msglayout *subl, + uint32_t number) { + if (--d->depth < 0) decode_err(d); + if (decode_isdone(d, &ptr)) { + decode_err(d); + } + ptr = decode_msg(d, ptr, submsg, subl); + if (d->end_group != number) decode_err(d); + d->end_group = DECODE_NOGROUP; + d->depth++; + return ptr; +} + +UPB_FORCEINLINE +static const char *decode_togroup(upb_decstate *d, const char *ptr, + upb_msg *submsg, const upb_msglayout *layout, + const upb_msglayout_field *field) { + const upb_msglayout *subl = layout->submsgs[field->submsg_index]; + return decode_group(d, ptr, submsg, subl, field->number); +} + +static const char *decode_toarray(upb_decstate *d, const char *ptr, + upb_msg *msg, const upb_msglayout *layout, + const upb_msglayout_field *field, wireval val, + int op) { + upb_array **arrp = UPB_PTR_AT(msg, field->offset, void); + upb_array *arr = *arrp; + void *mem; + + if (arr) { + decode_reserve(d, arr, 1); + } else { + size_t lg2 = desctype_to_elem_size_lg2[field->descriptortype]; + arr = _upb_array_new(&d->arena, 4, lg2); + if (!arr) decode_err(d); + *arrp = arr; + } + + switch (op) { + case OP_SCALAR_LG2(0): + case OP_SCALAR_LG2(2): + case OP_SCALAR_LG2(3): + /* Append scalar value. */ + mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << op, void); + arr->len++; + memcpy(mem, &val, 1 << op); + return ptr; + case OP_STRING: + decode_verifyutf8(d, ptr, val.size); + /* Fallthrough. */ + case OP_BYTES: { + /* Append bytes. */ + upb_strview *str = (upb_strview*)_upb_array_ptr(arr) + arr->len; + arr->len++; + return decode_readstr(d, ptr, val.size, str); + } + case OP_SUBMSG: { + /* Append submessage / group. */ + upb_msg *submsg = decode_newsubmsg(d, layout, field); + *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void *), upb_msg *) = + submsg; + arr->len++; + if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) { + return decode_togroup(d, ptr, submsg, layout, field); + } else { + return decode_tosubmsg(d, ptr, submsg, layout, field, val.size); + } + } + case OP_FIXPCK_LG2(2): + case OP_FIXPCK_LG2(3): { + /* Fixed packed. */ + int lg2 = op - OP_FIXPCK_LG2(0); + int mask = (1 << lg2) - 1; + size_t count = val.size >> lg2; + if ((val.size & mask) != 0) { + decode_err(d); /* Length isn't a round multiple of elem size. */ + } + decode_reserve(d, arr, count); + mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void); + arr->len += count; + memcpy(mem, ptr, val.size); /* XXX: ptr boundary. */ + return ptr + val.size; + } + case OP_VARPCK_LG2(0): + case OP_VARPCK_LG2(2): + case OP_VARPCK_LG2(3): { + /* Varint packed. */ + int lg2 = op - OP_VARPCK_LG2(0); + int scale = 1 << lg2; + int saved_limit = decode_pushlimit(d, ptr, val.size); + char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void); + while (!decode_isdone(d, &ptr)) { + wireval elem; + ptr = decode_varint64(d, ptr, &elem.uint64_val); + decode_munge(field->descriptortype, &elem); + if (decode_reserve(d, arr, 1)) { + out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void); + } + arr->len++; + memcpy(out, &elem, scale); + out += scale; + } + decode_poplimit(d, ptr, saved_limit); + return ptr; + } + default: + UPB_UNREACHABLE(); + } +} + +static const char *decode_tomap(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *layout, + const upb_msglayout_field *field, wireval val) { + upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *); + upb_map *map = *map_p; + upb_map_entry ent; + const upb_msglayout *entry = layout->submsgs[field->submsg_index]; + + if (!map) { + /* Lazily create map. */ + const upb_msglayout *entry = layout->submsgs[field->submsg_index]; + const upb_msglayout_field *key_field = &entry->fields[0]; + const upb_msglayout_field *val_field = &entry->fields[1]; + char key_size = desctype_to_mapsize[key_field->descriptortype]; + char val_size = desctype_to_mapsize[val_field->descriptortype]; + UPB_ASSERT(key_field->offset == 0); + UPB_ASSERT(val_field->offset == sizeof(upb_strview)); + map = _upb_map_new(&d->arena, key_size, val_size); + *map_p = map; + } + + /* Parse map entry. */ + memset(&ent, 0, sizeof(ent)); + + if (entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE || + entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_GROUP) { + /* Create proactively to handle the case where it doesn't appear. */ + ent.v.val = upb_value_ptr(_upb_msg_new(entry->submsgs[0], &d->arena)); + } + + ptr = decode_tosubmsg(d, ptr, &ent.k, layout, field, val.size); + _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, &d->arena); + return ptr; +} + +static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *layout, + const upb_msglayout_field *field, wireval val, + int op) { + void *mem = UPB_PTR_AT(msg, field->offset, void); + int type = field->descriptortype; + + /* Set presence if necessary. */ + if (field->presence < 0) { + /* Oneof case */ + uint32_t *oneof_case = _upb_oneofcase_field(msg, field); + if (op == OP_SUBMSG && *oneof_case != field->number) { + memset(mem, 0, sizeof(void*)); + } + *oneof_case = field->number; + } else if (field->presence > 0) { + _upb_sethas_field(msg, field); + } + + /* Store into message. */ + switch (op) { + case OP_SUBMSG: { + upb_msg **submsgp = mem; + upb_msg *submsg = *submsgp; + if (!submsg) { + submsg = decode_newsubmsg(d, layout, field); + *submsgp = submsg; + } + if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) { + ptr = decode_togroup(d, ptr, submsg, layout, field); + } else { + ptr = decode_tosubmsg(d, ptr, submsg, layout, field, val.size); + } + break; + } + case OP_STRING: + decode_verifyutf8(d, ptr, val.size); + /* Fallthrough. */ + case OP_BYTES: + return decode_readstr(d, ptr, val.size, mem); + case OP_SCALAR_LG2(3): + memcpy(mem, &val, 8); + break; + case OP_SCALAR_LG2(2): + memcpy(mem, &val, 4); + break; + case OP_SCALAR_LG2(0): + memcpy(mem, &val, 1); + break; + default: + UPB_UNREACHABLE(); + } + + return ptr; +} + +UPB_FORCEINLINE +static bool decode_tryfastdispatch(upb_decstate *d, const char **ptr, + upb_msg *msg, const upb_msglayout *layout) { +#if UPB_FASTTABLE + if (layout && layout->table_mask != (unsigned char)-1) { + uint16_t tag = fastdecode_loadtag(*ptr); + intptr_t table = decode_totable(layout); + *ptr = fastdecode_tagdispatch(d, *ptr, msg, table, 0, tag); + return true; + } +#endif + return false; +} + +UPB_NOINLINE +static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *layout) { + while (true) { + uint32_t tag; + const upb_msglayout_field *field; + int field_number; + int wire_type; + const char *field_start = ptr; + wireval val; + int op; + + UPB_ASSERT(ptr < d->limit_ptr); + ptr = decode_tag(d, ptr, &tag); + field_number = tag >> 3; + wire_type = tag & 7; + + field = upb_find_field(layout, field_number); + + switch (wire_type) { + case UPB_WIRE_TYPE_VARINT: + ptr = decode_varint64(d, ptr, &val.uint64_val); + op = varint_ops[field->descriptortype]; + decode_munge(field->descriptortype, &val); + break; + case UPB_WIRE_TYPE_32BIT: + memcpy(&val.uint32_val, ptr, 4); + val.uint32_val = _upb_be_swap32(val.uint32_val); + ptr += 4; + op = OP_SCALAR_LG2(2); + if (((1 << field->descriptortype) & fixed32_ok) == 0) goto unknown; + break; + case UPB_WIRE_TYPE_64BIT: + memcpy(&val.uint64_val, ptr, 8); + val.uint64_val = _upb_be_swap64(val.uint64_val); + ptr += 8; + op = OP_SCALAR_LG2(3); + if (((1 << field->descriptortype) & fixed64_ok) == 0) goto unknown; + break; + case UPB_WIRE_TYPE_DELIMITED: { + int ndx = field->descriptortype; + uint64_t size; + if (_upb_isrepeated(field)) ndx += 18; + ptr = decode_varint64(d, ptr, &size); + if (size >= INT32_MAX || + ptr - d->end + (int32_t)size > d->limit) { + decode_err(d); /* Length overflow. */ + } + op = delim_ops[ndx]; + val.size = size; + break; + } + case UPB_WIRE_TYPE_START_GROUP: + val.uint32_val = field_number; + op = OP_SUBMSG; + if (field->descriptortype != UPB_DTYPE_GROUP) goto unknown; + break; + case UPB_WIRE_TYPE_END_GROUP: + d->end_group = field_number; + return ptr; + default: + decode_err(d); + } + + if (op >= 0) { + /* Parse, using op for dispatch. */ + switch (field->label) { + case UPB_LABEL_REPEATED: + case _UPB_LABEL_PACKED: + ptr = decode_toarray(d, ptr, msg, layout, field, val, op); + break; + case _UPB_LABEL_MAP: + ptr = decode_tomap(d, ptr, msg, layout, field, val); + break; + default: + ptr = decode_tomsg(d, ptr, msg, layout, field, val, op); + break; + } + } else { + unknown: + /* Skip unknown field. */ + if (field_number == 0) decode_err(d); + if (wire_type == UPB_WIRE_TYPE_DELIMITED) ptr += val.size; + if (msg) { + if (wire_type == UPB_WIRE_TYPE_START_GROUP) { + d->unknown = field_start; + d->unknown_msg = msg; + ptr = decode_group(d, ptr, NULL, NULL, field_number); + d->unknown_msg = NULL; + field_start = d->unknown; + } + if (!_upb_msg_addunknown(msg, field_start, ptr - field_start, + &d->arena)) { + decode_err(d); + } + } else if (wire_type == UPB_WIRE_TYPE_START_GROUP) { + ptr = decode_group(d, ptr, NULL, NULL, field_number); + } + } + + if (decode_isdone(d, &ptr)) return ptr; + if (decode_tryfastdispatch(d, &ptr, msg, layout)) return ptr; + } +} + +const char *fastdecode_generic(struct upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, uint64_t hasbits, + uint64_t data) { + (void)data; + *(uint32_t*)msg |= hasbits; + return decode_msg(d, ptr, msg, decode_totablep(table)); +} + +static bool decode_top(struct upb_decstate *d, const char *buf, void *msg, + const upb_msglayout *l) { + if (!decode_tryfastdispatch(d, &buf, msg, l)) { + decode_msg(d, buf, msg, l); + } + return d->end_group == DECODE_NOGROUP; +} + +bool _upb_decode(const char *buf, size_t size, void *msg, + const upb_msglayout *l, upb_arena *arena, int options) { + bool ok; + upb_decstate state; + unsigned depth = (unsigned)options >> 16; + + if (size == 0) { + return true; + } else if (size <= 16) { + memset(&state.patch, 0, 32); + memcpy(&state.patch, buf, size); + buf = state.patch; + state.end = buf + size; + state.limit = 0; + state.alias = false; + } else { + state.end = buf + size - 16; + state.limit = 16; + state.alias = options & UPB_DECODE_ALIAS; + } + + state.limit_ptr = state.end; + state.unknown_msg = NULL; + state.depth = depth ? depth : 64; + state.end_group = DECODE_NOGROUP; + state.arena.head = arena->head; + state.arena.last_size = arena->last_size; + state.arena.cleanups = arena->cleanups; + state.arena.parent = arena; + + if (UPB_UNLIKELY(UPB_SETJMP(state.err))) { + ok = false; + } else { + ok = decode_top(&state, buf, msg, l); + } + + arena->head.ptr = state.arena.head.ptr; + arena->head.end = state.arena.head.end; + arena->cleanups = state.arena.cleanups; + return ok; +} + +#undef OP_SCALAR_LG2 +#undef OP_FIXPCK_LG2 +#undef OP_VARPCK_LG2 +#undef OP_STRING +#undef OP_SUBMSG +/* We encode backwards, to avoid pre-computing lengths (one-pass encode). */ + + +#include +#include + + +/* Must be last. */ + +#define UPB_PB_VARINT_MAX_LEN 10 + +UPB_NOINLINE +static size_t encode_varint64(uint64_t val, char *buf) { + size_t i = 0; + do { + uint8_t byte = val & 0x7fU; + val >>= 7; + if (val) byte |= 0x80U; + buf[i++] = byte; + } while (val); + return i; +} + +static uint32_t encode_zz32(int32_t n) { return ((uint32_t)n << 1) ^ (n >> 31); } +static uint64_t encode_zz64(int64_t n) { return ((uint64_t)n << 1) ^ (n >> 63); } + +typedef struct { + jmp_buf err; + upb_alloc *alloc; + char *buf, *ptr, *limit; + int options; + int depth; + _upb_mapsorter sorter; +} upb_encstate; + +static size_t upb_roundup_pow2(size_t bytes) { + size_t ret = 128; + while (ret < bytes) { + ret *= 2; + } + return ret; +} + +UPB_NORETURN static void encode_err(upb_encstate *e) { + UPB_LONGJMP(e->err, 1); +} + +UPB_NOINLINE +static void encode_growbuffer(upb_encstate *e, size_t bytes) { + size_t old_size = e->limit - e->buf; + size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr)); + char *new_buf = upb_realloc(e->alloc, e->buf, old_size, new_size); + + if (!new_buf) encode_err(e); + + /* We want previous data at the end, realloc() put it at the beginning. */ + if (old_size > 0) { + memmove(new_buf + new_size - old_size, e->buf, old_size); + } + + e->ptr = new_buf + new_size - (e->limit - e->ptr); + e->limit = new_buf + new_size; + e->buf = new_buf; + + e->ptr -= bytes; +} + +/* Call to ensure that at least "bytes" bytes are available for writing at + * e->ptr. Returns false if the bytes could not be allocated. */ +UPB_FORCEINLINE +static void encode_reserve(upb_encstate *e, size_t bytes) { + if ((size_t)(e->ptr - e->buf) < bytes) { + encode_growbuffer(e, bytes); + return; + } + + e->ptr -= bytes; +} + +/* Writes the given bytes to the buffer, handling reserve/advance. */ +static void encode_bytes(upb_encstate *e, const void *data, size_t len) { + if (len == 0) return; /* memcpy() with zero size is UB */ + encode_reserve(e, len); + memcpy(e->ptr, data, len); +} + +static void encode_fixed64(upb_encstate *e, uint64_t val) { + val = _upb_be_swap64(val); + encode_bytes(e, &val, sizeof(uint64_t)); +} + +static void encode_fixed32(upb_encstate *e, uint32_t val) { + val = _upb_be_swap32(val); + encode_bytes(e, &val, sizeof(uint32_t)); +} + +UPB_NOINLINE +static void encode_longvarint(upb_encstate *e, uint64_t val) { + size_t len; + char *start; + + encode_reserve(e, UPB_PB_VARINT_MAX_LEN); + len = encode_varint64(val, e->ptr); + start = e->ptr + UPB_PB_VARINT_MAX_LEN - len; + memmove(start, e->ptr, len); + e->ptr = start; +} + +UPB_FORCEINLINE +static void encode_varint(upb_encstate *e, uint64_t val) { + if (val < 128 && e->ptr != e->buf) { + --e->ptr; + *e->ptr = val; + } else { + encode_longvarint(e, val); + } +} + +static void encode_double(upb_encstate *e, double d) { + uint64_t u64; + UPB_ASSERT(sizeof(double) == sizeof(uint64_t)); + memcpy(&u64, &d, sizeof(uint64_t)); + encode_fixed64(e, u64); +} + +static void encode_float(upb_encstate *e, float d) { + uint32_t u32; + UPB_ASSERT(sizeof(float) == sizeof(uint32_t)); + memcpy(&u32, &d, sizeof(uint32_t)); + encode_fixed32(e, u32); +} + +static void encode_tag(upb_encstate *e, uint32_t field_number, + uint8_t wire_type) { + encode_varint(e, (field_number << 3) | wire_type); +} + +static void encode_fixedarray(upb_encstate *e, const upb_array *arr, + size_t elem_size, uint32_t tag) { + size_t bytes = arr->len * elem_size; + const char* data = _upb_array_constptr(arr); + const char* ptr = data + bytes - elem_size; + if (tag) { + while (true) { + encode_bytes(e, ptr, elem_size); + encode_varint(e, tag); + if (ptr == data) break; + ptr -= elem_size; + } + } else { + encode_bytes(e, data, bytes); + } +} + +static void encode_message(upb_encstate *e, const char *msg, + const upb_msglayout *m, size_t *size); + +static void encode_scalar(upb_encstate *e, const void *_field_mem, + const upb_msglayout *m, const upb_msglayout_field *f, + bool skip_zero_value) { + const char *field_mem = _field_mem; + int wire_type; + +#define CASE(ctype, type, wtype, encodeval) \ + { \ + ctype val = *(ctype *)field_mem; \ + if (skip_zero_value && val == 0) { \ + return; \ + } \ + encode_##type(e, encodeval); \ + wire_type = wtype; \ + break; \ + } + + switch (f->descriptortype) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + CASE(double, double, UPB_WIRE_TYPE_64BIT, val); + case UPB_DESCRIPTOR_TYPE_FLOAT: + CASE(float, float, UPB_WIRE_TYPE_32BIT, val); + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val); + case UPB_DESCRIPTOR_TYPE_UINT32: + CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val); + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_ENUM: + CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, (int64_t)val); + case UPB_DESCRIPTOR_TYPE_SFIXED64: + case UPB_DESCRIPTOR_TYPE_FIXED64: + CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val); + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val); + case UPB_DESCRIPTOR_TYPE_BOOL: + CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val); + case UPB_DESCRIPTOR_TYPE_SINT32: + CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, encode_zz32(val)); + case UPB_DESCRIPTOR_TYPE_SINT64: + CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, encode_zz64(val)); + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: { + upb_strview view = *(upb_strview*)field_mem; + if (skip_zero_value && view.size == 0) { + return; + } + encode_bytes(e, view.data, view.size); + encode_varint(e, view.size); + wire_type = UPB_WIRE_TYPE_DELIMITED; + break; + } + case UPB_DESCRIPTOR_TYPE_GROUP: { + size_t size; + void *submsg = *(void **)field_mem; + const upb_msglayout *subm = m->submsgs[f->submsg_index]; + if (submsg == NULL) { + return; + } + if (--e->depth == 0) encode_err(e); + encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP); + encode_message(e, submsg, subm, &size); + wire_type = UPB_WIRE_TYPE_START_GROUP; + e->depth++; + break; + } + case UPB_DESCRIPTOR_TYPE_MESSAGE: { + size_t size; + void *submsg = *(void **)field_mem; + const upb_msglayout *subm = m->submsgs[f->submsg_index]; + if (submsg == NULL) { + return; + } + if (--e->depth == 0) encode_err(e); + encode_message(e, submsg, subm, &size); + encode_varint(e, size); + wire_type = UPB_WIRE_TYPE_DELIMITED; + e->depth++; + break; + } + default: + UPB_UNREACHABLE(); + } +#undef CASE + + encode_tag(e, f->number, wire_type); +} + +static void encode_array(upb_encstate *e, const char *field_mem, + const upb_msglayout *m, const upb_msglayout_field *f) { + const upb_array *arr = *(const upb_array**)field_mem; + bool packed = f->label == _UPB_LABEL_PACKED; + size_t pre_len = e->limit - e->ptr; + + if (arr == NULL || arr->len == 0) { + return; + } + +#define VARINT_CASE(ctype, encode) \ + { \ + const ctype *start = _upb_array_constptr(arr); \ + const ctype *ptr = start + arr->len; \ + uint32_t tag = packed ? 0 : (f->number << 3) | UPB_WIRE_TYPE_VARINT; \ + do { \ + ptr--; \ + encode_varint(e, encode); \ + if (tag) encode_varint(e, tag); \ + } while (ptr != start); \ + } \ + break; + +#define TAG(wire_type) (packed ? 0 : (f->number << 3 | wire_type)) + + switch (f->descriptortype) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + encode_fixedarray(e, arr, sizeof(double), TAG(UPB_WIRE_TYPE_64BIT)); + break; + case UPB_DESCRIPTOR_TYPE_FLOAT: + encode_fixedarray(e, arr, sizeof(float), TAG(UPB_WIRE_TYPE_32BIT)); + break; + case UPB_DESCRIPTOR_TYPE_SFIXED64: + case UPB_DESCRIPTOR_TYPE_FIXED64: + encode_fixedarray(e, arr, sizeof(uint64_t), TAG(UPB_WIRE_TYPE_64BIT)); + break; + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + encode_fixedarray(e, arr, sizeof(uint32_t), TAG(UPB_WIRE_TYPE_32BIT)); + break; + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + VARINT_CASE(uint64_t, *ptr); + case UPB_DESCRIPTOR_TYPE_UINT32: + VARINT_CASE(uint32_t, *ptr); + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_ENUM: + VARINT_CASE(int32_t, (int64_t)*ptr); + case UPB_DESCRIPTOR_TYPE_BOOL: + VARINT_CASE(bool, *ptr); + case UPB_DESCRIPTOR_TYPE_SINT32: + VARINT_CASE(int32_t, encode_zz32(*ptr)); + case UPB_DESCRIPTOR_TYPE_SINT64: + VARINT_CASE(int64_t, encode_zz64(*ptr)); + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: { + const upb_strview *start = _upb_array_constptr(arr); + const upb_strview *ptr = start + arr->len; + do { + ptr--; + encode_bytes(e, ptr->data, ptr->size); + encode_varint(e, ptr->size); + encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); + } while (ptr != start); + return; + } + case UPB_DESCRIPTOR_TYPE_GROUP: { + const void *const*start = _upb_array_constptr(arr); + const void *const*ptr = start + arr->len; + const upb_msglayout *subm = m->submsgs[f->submsg_index]; + if (--e->depth == 0) encode_err(e); + do { + size_t size; + ptr--; + encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP); + encode_message(e, *ptr, subm, &size); + encode_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP); + } while (ptr != start); + e->depth++; + return; + } + case UPB_DESCRIPTOR_TYPE_MESSAGE: { + const void *const*start = _upb_array_constptr(arr); + const void *const*ptr = start + arr->len; + const upb_msglayout *subm = m->submsgs[f->submsg_index]; + if (--e->depth == 0) encode_err(e); + do { + size_t size; + ptr--; + encode_message(e, *ptr, subm, &size); + encode_varint(e, size); + encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); + } while (ptr != start); + e->depth++; + return; + } + } +#undef VARINT_CASE + + if (packed) { + encode_varint(e, e->limit - e->ptr - pre_len); + encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); + } +} + +static void encode_mapentry(upb_encstate *e, uint32_t number, + const upb_msglayout *layout, + const upb_map_entry *ent) { + const upb_msglayout_field *key_field = &layout->fields[0]; + const upb_msglayout_field *val_field = &layout->fields[1]; + size_t pre_len = e->limit - e->ptr; + size_t size; + encode_scalar(e, &ent->v, layout, val_field, false); + encode_scalar(e, &ent->k, layout, key_field, false); + size = (e->limit - e->ptr) - pre_len; + encode_varint(e, size); + encode_tag(e, number, UPB_WIRE_TYPE_DELIMITED); +} + +static void encode_map(upb_encstate *e, const char *field_mem, + const upb_msglayout *m, const upb_msglayout_field *f) { + const upb_map *map = *(const upb_map**)field_mem; + const upb_msglayout *layout = m->submsgs[f->submsg_index]; + UPB_ASSERT(layout->field_count == 2); + + if (map == NULL) return; + + if (e->options & UPB_ENCODE_DETERMINISTIC) { + _upb_sortedmap sorted; + _upb_mapsorter_pushmap(&e->sorter, layout->fields[0].descriptortype, map, + &sorted); + upb_map_entry ent; + while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) { + encode_mapentry(e, f->number, layout, &ent); + } + _upb_mapsorter_popmap(&e->sorter, &sorted); + } else { + upb_strtable_iter i; + upb_strtable_begin(&i, &map->table); + for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { + upb_strview key = upb_strtable_iter_key(&i); + const upb_value val = upb_strtable_iter_value(&i); + upb_map_entry ent; + _upb_map_fromkey(key, &ent.k, map->key_size); + _upb_map_fromvalue(val, &ent.v, map->val_size); + encode_mapentry(e, f->number, layout, &ent); + } + } +} + +static void encode_scalarfield(upb_encstate *e, const char *msg, + const upb_msglayout *m, + const upb_msglayout_field *f) { + bool skip_empty = false; + if (f->presence == 0) { + /* Proto3 presence. */ + skip_empty = true; + } else if (f->presence > 0) { + /* Proto2 presence: hasbit. */ + if (!_upb_hasbit_field(msg, f)) return; + } else { + /* Field is in a oneof. */ + if (_upb_getoneofcase_field(msg, f) != f->number) return; + } + encode_scalar(e, msg + f->offset, m, f, skip_empty); +} + +static void encode_message(upb_encstate *e, const char *msg, + const upb_msglayout *m, size_t *size) { + size_t pre_len = e->limit - e->ptr; + const upb_msglayout_field *f = &m->fields[m->field_count]; + const upb_msglayout_field *first = &m->fields[0]; + + if ((e->options & UPB_ENCODE_SKIPUNKNOWN) == 0) { + size_t unknown_size; + const char *unknown = upb_msg_getunknown(msg, &unknown_size); + + if (unknown) { + encode_bytes(e, unknown, unknown_size); + } + } + + while (f != first) { + f--; + if (_upb_isrepeated(f)) { + encode_array(e, msg + f->offset, m, f); + } else if (f->label == _UPB_LABEL_MAP) { + encode_map(e, msg + f->offset, m, f); + } else { + encode_scalarfield(e, msg, m, f); + } + } + + *size = (e->limit - e->ptr) - pre_len; +} + +char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options, + upb_arena *arena, size_t *size) { + upb_encstate e; + unsigned depth = (unsigned)options >> 16; + + e.alloc = upb_arena_alloc(arena); + e.buf = NULL; + e.limit = NULL; + e.ptr = NULL; + e.depth = depth ? depth : 64; + e.options = options; + _upb_mapsorter_init(&e.sorter); + char *ret = NULL; + + if (UPB_SETJMP(e.err)) { + *size = 0; + ret = NULL; + } else { + encode_message(&e, msg, l, size); + *size = e.limit - e.ptr; + if (*size == 0) { + static char ch; + ret = &ch; + } else { + UPB_ASSERT(e.ptr); + ret = e.ptr; + } + } + + _upb_mapsorter_destroy(&e.sorter); + return ret; +} + + + + +/** upb_msg *******************************************************************/ + +static const size_t overhead = sizeof(upb_msg_internal); + +static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) { + ptrdiff_t size = sizeof(upb_msg_internal); + return (upb_msg_internal*)((char*)msg - size); +} + +upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a) { + return _upb_msg_new_inl(l, a); +} + +void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l) { + void *mem = UPB_PTR_AT(msg, -sizeof(upb_msg_internal), char); + memset(mem, 0, upb_msg_sizeof(l)); +} + +bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, + upb_arena *arena) { + + upb_msg_internal *in = upb_msg_getinternal(msg); + if (!in->unknown) { + size_t size = 128; + while (size < len) size *= 2; + in->unknown = upb_arena_malloc(arena, size + overhead); + if (!in->unknown) return false; + in->unknown->size = size; + in->unknown->len = 0; + } else if (in->unknown->size - in->unknown->len < len) { + size_t need = in->unknown->len + len; + size_t size = in->unknown->size; + while (size < need) size *= 2; + in->unknown = upb_arena_realloc( + arena, in->unknown, in->unknown->size + overhead, size + overhead); + if (!in->unknown) return false; + in->unknown->size = size; + } + memcpy(UPB_PTR_AT(in->unknown + 1, in->unknown->len, char), data, len); + in->unknown->len += len; + return true; +} + +void _upb_msg_discardunknown_shallow(upb_msg *msg) { + upb_msg_internal *in = upb_msg_getinternal(msg); + if (in->unknown) { + in->unknown->len = 0; + } +} + +const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) { + const upb_msg_internal *in = upb_msg_getinternal_const(msg); + if (in->unknown) { + *len = in->unknown->len; + return (char*)(in->unknown + 1); + } else { + *len = 0; + return NULL; + } +} + +/** upb_array *****************************************************************/ + +bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena) { + size_t new_size = UPB_MAX(arr->size, 4); + int elem_size_lg2 = arr->data & 7; + size_t old_bytes = arr->size << elem_size_lg2; + size_t new_bytes; + void* ptr = _upb_array_ptr(arr); + + /* Log2 ceiling of size. */ + while (new_size < min_size) new_size *= 2; + + new_bytes = new_size << elem_size_lg2; + ptr = upb_arena_realloc(arena, ptr, old_bytes, new_bytes); + + if (!ptr) { + return false; + } + + arr->data = _upb_tag_arrptr(ptr, elem_size_lg2); + arr->size = new_size; + return true; +} + +static upb_array *getorcreate_array(upb_array **arr_ptr, int elem_size_lg2, + upb_arena *arena) { + upb_array *arr = *arr_ptr; + if (!arr) { + arr = _upb_array_new(arena, 4, elem_size_lg2); + if (!arr) return NULL; + *arr_ptr = arr; + } + return arr; +} + +void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size, + int elem_size_lg2, upb_arena *arena) { + upb_array *arr = getorcreate_array(arr_ptr, elem_size_lg2, arena); + return arr && _upb_array_resize(arr, size, arena) ? _upb_array_ptr(arr) + : NULL; +} + +bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value, + int elem_size_lg2, upb_arena *arena) { + upb_array *arr = getorcreate_array(arr_ptr, elem_size_lg2, arena); + if (!arr) return false; + + size_t elems = arr->len; + + if (!_upb_array_resize(arr, elems + 1, arena)) { + return false; + } + + char *data = _upb_array_ptr(arr); + memcpy(data + (elems << elem_size_lg2), value, 1 << elem_size_lg2); + return true; +} + +/** upb_map *******************************************************************/ + +upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) { + upb_map *map = upb_arena_malloc(a, sizeof(upb_map)); + + if (!map) { + return NULL; + } + + upb_strtable_init2(&map->table, UPB_CTYPE_INT32, 4, upb_arena_alloc(a)); + map->key_size = key_size; + map->val_size = value_size; + + return map; +} + +static void _upb_mapsorter_getkeys(const void *_a, const void *_b, void *a_key, + void *b_key, size_t size) { + const upb_tabent *const*a = _a; + const upb_tabent *const*b = _b; + upb_strview a_tabkey = upb_tabstrview((*a)->key); + upb_strview b_tabkey = upb_tabstrview((*b)->key); + _upb_map_fromkey(a_tabkey, a_key, size); + _upb_map_fromkey(b_tabkey, b_key, size); +} + +static int _upb_mapsorter_cmpi64(const void *_a, const void *_b) { + int64_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 8); + return a - b; +} + +static int _upb_mapsorter_cmpu64(const void *_a, const void *_b) { + uint64_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 8); + return a - b; +} + +static int _upb_mapsorter_cmpi32(const void *_a, const void *_b) { + int32_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 4); + return a - b; +} + +static int _upb_mapsorter_cmpu32(const void *_a, const void *_b) { + uint32_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 4); + return a - b; +} + +static int _upb_mapsorter_cmpbool(const void *_a, const void *_b) { + bool a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 1); + return a - b; +} + +static int _upb_mapsorter_cmpstr(const void *_a, const void *_b) { + upb_strview a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, UPB_MAPTYPE_STRING); + size_t common_size = UPB_MIN(a.size, b.size); + int cmp = memcmp(a.data, b.data, common_size); + if (cmp) return cmp; + return a.size - b.size; +} + +bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type, + const upb_map *map, _upb_sortedmap *sorted) { + int map_size = _upb_map_size(map); + sorted->start = s->size; + sorted->pos = sorted->start; + sorted->end = sorted->start + map_size; + + /* Grow s->entries if necessary. */ + if (sorted->end > s->cap) { + s->cap = _upb_lg2ceilsize(sorted->end); + s->entries = realloc(s->entries, s->cap * sizeof(*s->entries)); + if (!s->entries) return false; + } + + s->size = sorted->end; + + /* Copy non-empty entries from the table to s->entries. */ + upb_tabent const**dst = &s->entries[sorted->start]; + const upb_tabent *src = map->table.t.entries; + const upb_tabent *end = src + upb_table_size(&map->table.t); + for (; src < end; src++) { + if (!upb_tabent_isempty(src)) { + *dst = src; + dst++; + } + } + UPB_ASSERT(dst == &s->entries[sorted->end]); + + /* Sort entries according to the key type. */ + + int (*compar)(const void *, const void *); + + switch (key_type) { + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_SFIXED64: + case UPB_DESCRIPTOR_TYPE_SINT64: + compar = _upb_mapsorter_cmpi64; + break; + case UPB_DESCRIPTOR_TYPE_UINT64: + case UPB_DESCRIPTOR_TYPE_FIXED64: + compar = _upb_mapsorter_cmpu64; + break; + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_SINT32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + case UPB_DESCRIPTOR_TYPE_ENUM: + compar = _upb_mapsorter_cmpi32; + break; + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_FIXED32: + compar = _upb_mapsorter_cmpu32; + break; + case UPB_DESCRIPTOR_TYPE_BOOL: + compar = _upb_mapsorter_cmpbool; + break; + case UPB_DESCRIPTOR_TYPE_STRING: + compar = _upb_mapsorter_cmpstr; + break; + default: + UPB_UNREACHABLE(); + } + + qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), compar); + return true; +} +/* +** upb_table Implementation +** +** Implementation is heavily inspired by Lua's ltable.c. +*/ + +#include + +#include "third_party/wyhash/wyhash.h" + +/* Must be last. */ + +#define UPB_MAXARRSIZE 16 /* 64k. */ + +/* From Chromium. */ +#define ARRAY_SIZE(x) \ + ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) + +static const double MAX_LOAD = 0.85; + +/* The minimum utilization of the array part of a mixed hash/array table. This + * is a speed/memory-usage tradeoff (though it's not straightforward because of + * cache effects). The lower this is, the more memory we'll use. */ +static const double MIN_DENSITY = 0.1; + +bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; } + +int log2ceil(uint64_t v) { + int ret = 0; + bool pow2 = is_pow2(v); + while (v >>= 1) ret++; + ret = pow2 ? ret : ret + 1; /* Ceiling. */ + return UPB_MIN(UPB_MAXARRSIZE, ret); +} + +char *upb_strdup(const char *s, upb_alloc *a) { + return upb_strdup2(s, strlen(s), a); +} + +char *upb_strdup2(const char *s, size_t len, upb_alloc *a) { + size_t n; + char *p; + + /* Prevent overflow errors. */ + if (len == SIZE_MAX) return NULL; + /* Always null-terminate, even if binary data; but don't rely on the input to + * have a null-terminating byte since it may be a raw binary buffer. */ + n = len + 1; + p = upb_malloc(a, n); + if (p) { + memcpy(p, s, len); + p[len] = 0; + } + return p; +} + +/* A type to represent the lookup key of either a strtable or an inttable. */ +typedef union { + uintptr_t num; + struct { + const char *str; + size_t len; + } str; +} lookupkey_t; + +static lookupkey_t strkey2(const char *str, size_t len) { + lookupkey_t k; + k.str.str = str; + k.str.len = len; + return k; +} + +static lookupkey_t intkey(uintptr_t key) { + lookupkey_t k; + k.num = key; + return k; +} + +typedef uint32_t hashfunc_t(upb_tabkey key); +typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2); + +/* Base table (shared code) ***************************************************/ + +/* For when we need to cast away const. */ +static upb_tabent *mutable_entries(upb_table *t) { + return (upb_tabent*)t->entries; +} + +static bool isfull(upb_table *t) { + return t->count == t->max_count; +} + +static bool init(upb_table *t, uint8_t size_lg2, upb_alloc *a) { + size_t bytes; + + t->count = 0; + t->size_lg2 = size_lg2; + t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0; + t->max_count = upb_table_size(t) * MAX_LOAD; + bytes = upb_table_size(t) * sizeof(upb_tabent); + if (bytes > 0) { + t->entries = upb_malloc(a, bytes); + if (!t->entries) return false; + memset(mutable_entries(t), 0, bytes); + } else { + t->entries = NULL; + } + return true; +} + +static void uninit(upb_table *t, upb_alloc *a) { + upb_free(a, mutable_entries(t)); +} + +static upb_tabent *emptyent(upb_table *t, upb_tabent *e) { + upb_tabent *begin = mutable_entries(t); + upb_tabent *end = begin + upb_table_size(t); + for (e = e + 1; e < end; e++) { + if (upb_tabent_isempty(e)) return e; + } + for (e = begin; e < end; e++) { + if (upb_tabent_isempty(e)) return e; + } + UPB_ASSERT(false); + return NULL; +} + +static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) { + return (upb_tabent*)upb_getentry(t, hash); +} + +static const upb_tabent *findentry(const upb_table *t, lookupkey_t key, + uint32_t hash, eqlfunc_t *eql) { + const upb_tabent *e; + + if (t->size_lg2 == 0) return NULL; + e = upb_getentry(t, hash); + if (upb_tabent_isempty(e)) return NULL; + while (1) { + if (eql(e->key, key)) return e; + if ((e = e->next) == NULL) return NULL; + } +} + +static upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key, + uint32_t hash, eqlfunc_t *eql) { + return (upb_tabent*)findentry(t, key, hash, eql); +} + +static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v, + uint32_t hash, eqlfunc_t *eql) { + const upb_tabent *e = findentry(t, key, hash, eql); + if (e) { + if (v) { + _upb_value_setval(v, e->val.val); + } + return true; + } else { + return false; + } +} + +/* The given key must not already exist in the table. */ +static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey, + upb_value val, uint32_t hash, + hashfunc_t *hashfunc, eqlfunc_t *eql) { + upb_tabent *mainpos_e; + upb_tabent *our_e; + + UPB_ASSERT(findentry(t, key, hash, eql) == NULL); + + t->count++; + mainpos_e = getentry_mutable(t, hash); + our_e = mainpos_e; + + if (upb_tabent_isempty(mainpos_e)) { + /* Our main position is empty; use it. */ + our_e->next = NULL; + } else { + /* Collision. */ + upb_tabent *new_e = emptyent(t, mainpos_e); + /* Head of collider's chain. */ + upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key)); + if (chain == mainpos_e) { + /* Existing ent is in its main position (it has the same hash as us, and + * is the head of our chain). Insert to new ent and append to this chain. */ + new_e->next = mainpos_e->next; + mainpos_e->next = new_e; + our_e = new_e; + } else { + /* Existing ent is not in its main position (it is a node in some other + * chain). This implies that no existing ent in the table has our hash. + * Evict it (updating its chain) and use its ent for head of our chain. */ + *new_e = *mainpos_e; /* copies next. */ + while (chain->next != mainpos_e) { + chain = (upb_tabent*)chain->next; + UPB_ASSERT(chain); + } + chain->next = new_e; + our_e = mainpos_e; + our_e->next = NULL; + } + } + our_e->key = tabkey; + our_e->val.val = val.val; + UPB_ASSERT(findentry(t, key, hash, eql) == our_e); +} + +static bool rm(upb_table *t, lookupkey_t key, upb_value *val, + upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) { + upb_tabent *chain = getentry_mutable(t, hash); + if (upb_tabent_isempty(chain)) return false; + if (eql(chain->key, key)) { + /* Element to remove is at the head of its chain. */ + t->count--; + if (val) _upb_value_setval(val, chain->val.val); + if (removed) *removed = chain->key; + if (chain->next) { + upb_tabent *move = (upb_tabent*)chain->next; + *chain = *move; + move->key = 0; /* Make the slot empty. */ + } else { + chain->key = 0; /* Make the slot empty. */ + } + return true; + } else { + /* Element to remove is either in a non-head position or not in the + * table. */ + while (chain->next && !eql(chain->next->key, key)) { + chain = (upb_tabent*)chain->next; + } + if (chain->next) { + /* Found element to remove. */ + upb_tabent *rm = (upb_tabent*)chain->next; + t->count--; + if (val) _upb_value_setval(val, chain->next->val.val); + if (removed) *removed = rm->key; + rm->key = 0; /* Make the slot empty. */ + chain->next = rm->next; + return true; + } else { + /* Element to remove is not in the table. */ + return false; + } + } +} + +static size_t next(const upb_table *t, size_t i) { + do { + if (++i >= upb_table_size(t)) + return SIZE_MAX - 1; /* Distinct from -1. */ + } while(upb_tabent_isempty(&t->entries[i])); + + return i; +} + +static size_t begin(const upb_table *t) { + return next(t, -1); +} + + +/* upb_strtable ***************************************************************/ + +/* A simple "subclass" of upb_table that only adds a hash function for strings. */ + +static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) { + uint32_t len = (uint32_t) k2.str.len; + char *str = upb_malloc(a, k2.str.len + sizeof(uint32_t) + 1); + if (str == NULL) return 0; + memcpy(str, &len, sizeof(uint32_t)); + if (k2.str.len) memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len); + str[sizeof(uint32_t) + k2.str.len] = '\0'; + return (uintptr_t)str; +} + +static uint32_t table_hash(const char *p, size_t n) { + return wyhash(p, n, 0, _wyp); +} + +static uint32_t strhash(upb_tabkey key) { + uint32_t len; + char *str = upb_tabstr(key, &len); + return table_hash(str, len); +} + +static bool streql(upb_tabkey k1, lookupkey_t k2) { + uint32_t len; + char *str = upb_tabstr(k1, &len); + return len == k2.str.len && (len == 0 || memcmp(str, k2.str.str, len) == 0); +} + +bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, + size_t expected_size, upb_alloc *a) { + UPB_UNUSED(ctype); /* TODO(haberman): rm */ + // Multiply by approximate reciprocal of MAX_LOAD (0.85), with pow2 denominator. + size_t need_entries = (expected_size + 1) * 1204 / 1024; + UPB_ASSERT(need_entries >= expected_size * 0.85); + int size_lg2 = _upb_lg2ceil(need_entries); + return init(&t->t, size_lg2, a); +} + +void upb_strtable_clear(upb_strtable *t) { + size_t bytes = upb_table_size(&t->t) * sizeof(upb_tabent); + t->t.count = 0; + memset((char*)t->t.entries, 0, bytes); +} + +void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) { + size_t i; + for (i = 0; i < upb_table_size(&t->t); i++) + upb_free(a, (void*)t->t.entries[i].key); + uninit(&t->t, a); +} + +bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) { + upb_strtable new_table; + upb_strtable_iter i; + + if (!init(&new_table.t, size_lg2, a)) + return false; + upb_strtable_begin(&i, t); + for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) { + upb_strview key = upb_strtable_iter_key(&i); + upb_strtable_insert3( + &new_table, key.data, key.size, + upb_strtable_iter_value(&i), a); + } + upb_strtable_uninit2(t, a); + *t = new_table; + return true; +} + +bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len, + upb_value v, upb_alloc *a) { + lookupkey_t key; + upb_tabkey tabkey; + uint32_t hash; + + if (isfull(&t->t)) { + /* Need to resize. New table of double the size, add old elements to it. */ + if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) { + return false; + } + } + + key = strkey2(k, len); + tabkey = strcopy(key, a); + if (tabkey == 0) return false; + + hash = table_hash(key.str.str, key.str.len); + insert(&t->t, key, tabkey, v, hash, &strhash, &streql); + return true; +} + +bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len, + upb_value *v) { + uint32_t hash = table_hash(key, len); + return lookup(&t->t, strkey2(key, len), v, hash, &streql); +} + +bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len, + upb_value *val, upb_alloc *alloc) { + uint32_t hash = table_hash(key, len); + upb_tabkey tabkey; + if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) { + if (alloc) { + /* Arena-based allocs don't need to free and won't pass this. */ + upb_free(alloc, (void*)tabkey); + } + return true; + } else { + return false; + } +} + +/* Iteration */ + +void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) { + i->t = t; + i->index = begin(&t->t); +} + +void upb_strtable_next(upb_strtable_iter *i) { + i->index = next(&i->t->t, i->index); +} + +bool upb_strtable_done(const upb_strtable_iter *i) { + if (!i->t) return true; + return i->index >= upb_table_size(&i->t->t) || + upb_tabent_isempty(str_tabent(i)); +} + +upb_strview upb_strtable_iter_key(const upb_strtable_iter *i) { + upb_strview key; + uint32_t len; + UPB_ASSERT(!upb_strtable_done(i)); + key.data = upb_tabstr(str_tabent(i)->key, &len); + key.size = len; + return key; +} + +upb_value upb_strtable_iter_value(const upb_strtable_iter *i) { + UPB_ASSERT(!upb_strtable_done(i)); + return _upb_value_val(str_tabent(i)->val.val); +} + +void upb_strtable_iter_setdone(upb_strtable_iter *i) { + i->t = NULL; + i->index = SIZE_MAX; +} + +bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, + const upb_strtable_iter *i2) { + if (upb_strtable_done(i1) && upb_strtable_done(i2)) + return true; + return i1->t == i2->t && i1->index == i2->index; +} + + +/* upb_inttable ***************************************************************/ + +/* For inttables we use a hybrid structure where small keys are kept in an + * array and large keys are put in the hash table. */ + +static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); } + +static bool inteql(upb_tabkey k1, lookupkey_t k2) { + return k1 == k2.num; +} + +static upb_tabval *mutable_array(upb_inttable *t) { + return (upb_tabval*)t->array; +} + +static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) { + if (key < t->array_size) { + return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL; + } else { + upb_tabent *e = + findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql); + return e ? &e->val : NULL; + } +} + +static const upb_tabval *inttable_val_const(const upb_inttable *t, + uintptr_t key) { + return inttable_val((upb_inttable*)t, key); +} + +size_t upb_inttable_count(const upb_inttable *t) { + return t->t.count + t->array_count; +} + +static void check(upb_inttable *t) { + UPB_UNUSED(t); +#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG) + { + /* This check is very expensive (makes inserts/deletes O(N)). */ + size_t count = 0; + upb_inttable_iter i; + upb_inttable_begin(&i, t); + for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) { + UPB_ASSERT(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL)); + } + UPB_ASSERT(count == upb_inttable_count(t)); + } +#endif +} + +bool upb_inttable_sizedinit(upb_inttable *t, size_t asize, int hsize_lg2, + upb_alloc *a) { + size_t array_bytes; + + if (!init(&t->t, hsize_lg2, a)) return false; + /* Always make the array part at least 1 long, so that we know key 0 + * won't be in the hash part, which simplifies things. */ + t->array_size = UPB_MAX(1, asize); + t->array_count = 0; + array_bytes = t->array_size * sizeof(upb_value); + t->array = upb_malloc(a, array_bytes); + if (!t->array) { + uninit(&t->t, a); + return false; + } + memset(mutable_array(t), 0xff, array_bytes); + check(t); + return true; +} + +bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) { + UPB_UNUSED(ctype); /* TODO(haberman): rm */ + return upb_inttable_sizedinit(t, 0, 4, a); +} + +void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) { + uninit(&t->t, a); + upb_free(a, mutable_array(t)); +} + +bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, + upb_alloc *a) { + upb_tabval tabval; + tabval.val = val.val; + UPB_ASSERT(upb_arrhas(tabval)); /* This will reject (uint64_t)-1. Fix this. */ + + if (key < t->array_size) { + UPB_ASSERT(!upb_arrhas(t->array[key])); + t->array_count++; + mutable_array(t)[key].val = val.val; + } else { + if (isfull(&t->t)) { + /* Need to resize the hash part, but we re-use the array part. */ + size_t i; + upb_table new_table; + + if (!init(&new_table, t->t.size_lg2 + 1, a)) { + return false; + } + + for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) { + const upb_tabent *e = &t->t.entries[i]; + uint32_t hash; + upb_value v; + + _upb_value_setval(&v, e->val.val); + hash = upb_inthash(e->key); + insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql); + } + + UPB_ASSERT(t->t.count == new_table.count); + + uninit(&t->t, a); + t->t = new_table; + } + insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql); + } + check(t); + return true; +} + +bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) { + const upb_tabval *table_v = inttable_val_const(t, key); + if (!table_v) return false; + if (v) _upb_value_setval(v, table_v->val); + return true; +} + +bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) { + upb_tabval *table_v = inttable_val(t, key); + if (!table_v) return false; + table_v->val = val.val; + return true; +} + +bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) { + bool success; + if (key < t->array_size) { + if (upb_arrhas(t->array[key])) { + upb_tabval empty = UPB_TABVALUE_EMPTY_INIT; + t->array_count--; + if (val) { + _upb_value_setval(val, t->array[key].val); + } + mutable_array(t)[key] = empty; + success = true; + } else { + success = false; + } + } else { + success = rm(&t->t, intkey(key), val, NULL, upb_inthash(key), &inteql); + } + check(t); + return success; +} + +bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val, + upb_alloc *a) { + return upb_inttable_insert2(t, (uintptr_t)key, val, a); +} + +bool upb_inttable_lookupptr(const upb_inttable *t, const void *key, + upb_value *v) { + return upb_inttable_lookup(t, (uintptr_t)key, v); +} + +bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) { + return upb_inttable_remove(t, (uintptr_t)key, val); +} + +void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) { + /* A power-of-two histogram of the table keys. */ + size_t counts[UPB_MAXARRSIZE + 1] = {0}; + + /* The max key in each bucket. */ + uintptr_t max[UPB_MAXARRSIZE + 1] = {0}; + + upb_inttable_iter i; + size_t arr_count; + int size_lg2; + upb_inttable new_t; + + upb_inttable_begin(&i, t); + for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { + uintptr_t key = upb_inttable_iter_key(&i); + int bucket = log2ceil(key); + max[bucket] = UPB_MAX(max[bucket], key); + counts[bucket]++; + } + + /* Find the largest power of two that satisfies the MIN_DENSITY + * definition (while actually having some keys). */ + arr_count = upb_inttable_count(t); + + for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) { + if (counts[size_lg2] == 0) { + /* We can halve again without losing any entries. */ + continue; + } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) { + break; + } + + arr_count -= counts[size_lg2]; + } + + UPB_ASSERT(arr_count <= upb_inttable_count(t)); + + { + /* Insert all elements into new, perfectly-sized table. */ + size_t arr_size = max[size_lg2] + 1; /* +1 so arr[max] will fit. */ + size_t hash_count = upb_inttable_count(t) - arr_count; + size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0; + int hashsize_lg2 = log2ceil(hash_size); + + upb_inttable_sizedinit(&new_t, arr_size, hashsize_lg2, a); + upb_inttable_begin(&i, t); + for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { + uintptr_t k = upb_inttable_iter_key(&i); + upb_inttable_insert2(&new_t, k, upb_inttable_iter_value(&i), a); + } + UPB_ASSERT(new_t.array_size == arr_size); + UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2); + } + upb_inttable_uninit2(t, a); + *t = new_t; +} + +/* Iteration. */ + +static const upb_tabent *int_tabent(const upb_inttable_iter *i) { + UPB_ASSERT(!i->array_part); + return &i->t->t.entries[i->index]; +} + +static upb_tabval int_arrent(const upb_inttable_iter *i) { + UPB_ASSERT(i->array_part); + return i->t->array[i->index]; +} + +void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) { + i->t = t; + i->index = -1; + i->array_part = true; + upb_inttable_next(i); +} + +void upb_inttable_next(upb_inttable_iter *iter) { + const upb_inttable *t = iter->t; + if (iter->array_part) { + while (++iter->index < t->array_size) { + if (upb_arrhas(int_arrent(iter))) { + return; + } + } + iter->array_part = false; + iter->index = begin(&t->t); + } else { + iter->index = next(&t->t, iter->index); + } +} + +bool upb_inttable_done(const upb_inttable_iter *i) { + if (!i->t) return true; + if (i->array_part) { + return i->index >= i->t->array_size || + !upb_arrhas(int_arrent(i)); + } else { + return i->index >= upb_table_size(&i->t->t) || + upb_tabent_isempty(int_tabent(i)); + } +} + +uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) { + UPB_ASSERT(!upb_inttable_done(i)); + return i->array_part ? i->index : int_tabent(i)->key; +} + +upb_value upb_inttable_iter_value(const upb_inttable_iter *i) { + UPB_ASSERT(!upb_inttable_done(i)); + return _upb_value_val( + i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val); +} + +void upb_inttable_iter_setdone(upb_inttable_iter *i) { + i->t = NULL; + i->index = SIZE_MAX; + i->array_part = false; +} + +bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, + const upb_inttable_iter *i2) { + if (upb_inttable_done(i1) && upb_inttable_done(i2)) + return true; + return i1->t == i2->t && i1->index == i2->index && + i1->array_part == i2->array_part; +} + + +#include +#include +#include +#include +#include +#include +#include + + +/* upb_status *****************************************************************/ + +void upb_status_clear(upb_status *status) { + if (!status) return; + status->ok = true; + status->msg[0] = '\0'; +} + +bool upb_ok(const upb_status *status) { return status->ok; } + +const char *upb_status_errmsg(const upb_status *status) { return status->msg; } + +void upb_status_seterrmsg(upb_status *status, const char *msg) { + if (!status) return; + status->ok = false; + strncpy(status->msg, msg, UPB_STATUS_MAX_MESSAGE - 1); + status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0'; +} + +void upb_status_seterrf(upb_status *status, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + upb_status_vseterrf(status, fmt, args); + va_end(args); +} + +void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) { + if (!status) return; + status->ok = false; + vsnprintf(status->msg, sizeof(status->msg), fmt, args); + status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0'; +} + +void upb_status_vappenderrf(upb_status *status, const char *fmt, va_list args) { + size_t len; + if (!status) return; + status->ok = false; + len = strlen(status->msg); + vsnprintf(status->msg + len, sizeof(status->msg) - len, fmt, args); + status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0'; +} + +/* upb_alloc ******************************************************************/ + +static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize, + size_t size) { + UPB_UNUSED(alloc); + UPB_UNUSED(oldsize); + if (size == 0) { + free(ptr); + return NULL; + } else { + return realloc(ptr, size); + } +} + +upb_alloc upb_alloc_global = {&upb_global_allocfunc}; + +/* upb_arena ******************************************************************/ + +/* Be conservative and choose 16 in case anyone is using SSE. */ + +struct mem_block { + struct mem_block *next; + uint32_t size; + uint32_t cleanups; + /* Data follows. */ +}; + +typedef struct cleanup_ent { + upb_cleanup_func *cleanup; + void *ud; +} cleanup_ent; + +static const size_t memblock_reserve = UPB_ALIGN_UP(sizeof(mem_block), 16); + +static upb_arena *arena_findroot(upb_arena *a) { + /* Path splitting keeps time complexity down, see: + * https://en.wikipedia.org/wiki/Disjoint-set_data_structure */ + while (a->parent != a) { + upb_arena *next = a->parent; + a->parent = next->parent; + a = next; + } + return a; +} + +static void upb_arena_addblock(upb_arena *a, upb_arena *root, void *ptr, + size_t size) { + mem_block *block = ptr; + + /* The block is for arena |a|, but should appear in the freelist of |root|. */ + block->next = root->freelist; + block->size = (uint32_t)size; + block->cleanups = 0; + root->freelist = block; + a->last_size = block->size; + if (!root->freelist_tail) root->freelist_tail = block; + + a->head.ptr = UPB_PTR_AT(block, memblock_reserve, char); + a->head.end = UPB_PTR_AT(block, size, char); + a->cleanups = &block->cleanups; + + UPB_POISON_MEMORY_REGION(a->head.ptr, a->head.end - a->head.ptr); +} + +static bool upb_arena_allocblock(upb_arena *a, size_t size) { + upb_arena *root = arena_findroot(a); + size_t block_size = UPB_MAX(size, a->last_size * 2) + memblock_reserve; + mem_block *block = upb_malloc(root->block_alloc, block_size); + + if (!block) return false; + upb_arena_addblock(a, root, block, block_size); + return true; +} + +void *_upb_arena_slowmalloc(upb_arena *a, size_t size) { + if (!upb_arena_allocblock(a, size)) return NULL; /* Out of memory. */ + UPB_ASSERT(_upb_arenahas(a) >= size); + return upb_arena_malloc(a, size); +} + +static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize, + size_t size) { + upb_arena *a = (upb_arena*)alloc; /* upb_alloc is initial member. */ + return upb_arena_realloc(a, ptr, oldsize, size); +} + +/* Public Arena API ***********************************************************/ + +upb_arena *arena_initslow(void *mem, size_t n, upb_alloc *alloc) { + const size_t first_block_overhead = sizeof(upb_arena) + memblock_reserve; + upb_arena *a; + + /* We need to malloc the initial block. */ + n = first_block_overhead + 256; + if (!alloc || !(mem = upb_malloc(alloc, n))) { + return NULL; + } + + a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena); + n -= sizeof(*a); + + a->head.alloc.func = &upb_arena_doalloc; + a->block_alloc = alloc; + a->parent = a; + a->refcount = 1; + a->freelist = NULL; + a->freelist_tail = NULL; + + upb_arena_addblock(a, a, mem, n); + + return a; +} + +upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) { + upb_arena *a; + + /* Round block size down to alignof(*a) since we will allocate the arena + * itself at the end. */ + n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_arena)); + + if (UPB_UNLIKELY(n < sizeof(upb_arena))) { + return arena_initslow(mem, n, alloc); + } + + a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena); + + a->head.alloc.func = &upb_arena_doalloc; + a->block_alloc = alloc; + a->parent = a; + a->refcount = 1; + a->last_size = UPB_MAX(128, n); + a->head.ptr = mem; + a->head.end = UPB_PTR_AT(mem, n - sizeof(*a), char); + a->freelist = NULL; + a->cleanups = NULL; + + return a; +} + +static void arena_dofree(upb_arena *a) { + mem_block *block = a->freelist; + UPB_ASSERT(a->parent == a); + UPB_ASSERT(a->refcount == 0); + + while (block) { + /* Load first since we are deleting block. */ + mem_block *next = block->next; + + if (block->cleanups > 0) { + cleanup_ent *end = UPB_PTR_AT(block, block->size, void); + cleanup_ent *ptr = end - block->cleanups; + + for (; ptr < end; ptr++) { + ptr->cleanup(ptr->ud); + } + } + + upb_free(a->block_alloc, block); + block = next; + } +} + +void upb_arena_free(upb_arena *a) { + a = arena_findroot(a); + if (--a->refcount == 0) arena_dofree(a); +} + +bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) { + cleanup_ent *ent; + + if (!a->cleanups || _upb_arenahas(a) < sizeof(cleanup_ent)) { + if (!upb_arena_allocblock(a, 128)) return false; /* Out of memory. */ + UPB_ASSERT(_upb_arenahas(a) >= sizeof(cleanup_ent)); + } + + a->head.end -= sizeof(cleanup_ent); + ent = (cleanup_ent*)a->head.end; + (*a->cleanups)++; + UPB_UNPOISON_MEMORY_REGION(ent, sizeof(cleanup_ent)); + + ent->cleanup = func; + ent->ud = ud; + + return true; +} + +void upb_arena_fuse(upb_arena *a1, upb_arena *a2) { + upb_arena *r1 = arena_findroot(a1); + upb_arena *r2 = arena_findroot(a2); + + if (r1 == r2) return; /* Already fused. */ + + /* We want to join the smaller tree to the larger tree. + * So swap first if they are backwards. */ + if (r1->refcount < r2->refcount) { + upb_arena *tmp = r1; + r1 = r2; + r2 = tmp; + } + + /* r1 takes over r2's freelist and refcount. */ + r1->refcount += r2->refcount; + if (r2->freelist_tail) { + UPB_ASSERT(r2->freelist_tail->next == NULL); + r2->freelist_tail->next = r1->freelist; + r1->freelist = r2->freelist; + } + r2->parent = r1; +} +// Fast decoder: ~3x the speed of decode.c, but x86-64 specific. +// Also the table size grows by 2x. +// +// Could potentially be ported to ARM64 or other 64-bit archs that pass at +// least six arguments in registers. +// +// The overall design is to create specialized functions for every possible +// field type (eg. oneof boolean field with a 1 byte tag) and then dispatch +// to the specialized function as quickly as possible. + + + +/* Must be last. */ + +#if UPB_FASTTABLE + +// The standard set of arguments passed to each parsing function. +// Thanks to x86-64 calling conventions, these will stay in registers. +#define UPB_PARSE_PARAMS \ + upb_decstate *d, const char *ptr, upb_msg *msg, intptr_t table, \ + uint64_t hasbits, uint64_t data + +#define UPB_PARSE_ARGS d, ptr, msg, table, hasbits, data + +#define RETURN_GENERIC(m) \ + /* fprintf(stderr, m); */ \ + return fastdecode_generic(d, ptr, msg, table, hasbits, 0); + +typedef enum { + CARD_s = 0, /* Singular (optional, non-repeated) */ + CARD_o = 1, /* Oneof */ + CARD_r = 2, /* Repeated */ + CARD_p = 3 /* Packed Repeated */ +} upb_card; + +UPB_NOINLINE +static const char *fastdecode_isdonefallback(upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits, int overrun) { + ptr = decode_isdonefallback_inl(d, ptr, overrun); + if (ptr == NULL) { + return fastdecode_err(d); + } + uint16_t tag = fastdecode_loadtag(ptr); + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, tag); +} + +UPB_FORCEINLINE +static const char *fastdecode_dispatch(upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits) { + if (UPB_UNLIKELY(ptr >= d->limit_ptr)) { + int overrun = ptr - d->end; + if (UPB_LIKELY(overrun == d->limit)) { + // Parse is finished. + *(uint32_t*)msg |= hasbits; // Sync hasbits. + return ptr; + } else { + return fastdecode_isdonefallback(d, ptr, msg, table, hasbits, overrun); + } + } + + // Read two bytes of tag data (for a one-byte tag, the high byte is junk). + uint16_t tag = fastdecode_loadtag(ptr); + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, tag); +} + +UPB_FORCEINLINE +static bool fastdecode_checktag(uint64_t data, int tagbytes) { + if (tagbytes == 1) { + return (data & 0xff) == 0; + } else { + return (data & 0xffff) == 0; + } +} + +UPB_FORCEINLINE +static const char *fastdecode_longsize(const char *ptr, int *size) { + int i; + UPB_ASSERT(*size & 0x80); + *size &= 0xff; + for (i = 0; i < 3; i++) { + ptr++; + size_t byte = (uint8_t)ptr[-1]; + *size += (byte - 1) << (7 + 7 * i); + if (UPB_LIKELY((byte & 0x80) == 0)) return ptr; + } + ptr++; + size_t byte = (uint8_t)ptr[-1]; + // len is limited by 2gb not 4gb, hence 8 and not 16 as normally expected + // for a 32 bit varint. + if (UPB_UNLIKELY(byte >= 8)) return NULL; + *size += (byte - 1) << 28; + return ptr; +} + +UPB_FORCEINLINE +static bool fastdecode_boundscheck(const char *ptr, size_t len, + const char *end) { + uintptr_t uptr = (uintptr_t)ptr; + uintptr_t uend = (uintptr_t)end + 16; + uintptr_t res = uptr + len; + return res < uptr || res > uend; +} + +UPB_FORCEINLINE +static bool fastdecode_boundscheck2(const char *ptr, size_t len, + const char *end) { + // This is one extra branch compared to the more normal: + // return (size_t)(end - ptr) < size; + // However it is one less computation if we are just about to use "ptr + len": + // https://godbolt.org/z/35YGPz + // In microbenchmarks this shows an overall 4% improvement. + uintptr_t uptr = (uintptr_t)ptr; + uintptr_t uend = (uintptr_t)end; + uintptr_t res = uptr + len; + return res < uptr || res > uend; +} + +typedef const char *fastdecode_delimfunc(upb_decstate *d, const char *ptr, + void *ctx); + +UPB_FORCEINLINE +static const char *fastdecode_delimited(upb_decstate *d, const char *ptr, + fastdecode_delimfunc *func, void *ctx) { + ptr++; + int len = (int8_t)ptr[-1]; + if (fastdecode_boundscheck2(ptr, len, d->limit_ptr)) { + // Slow case: Sub-message is >=128 bytes and/or exceeds the current buffer. + // If it exceeds the buffer limit, limit/limit_ptr will change during + // sub-message parsing, so we need to preserve delta, not limit. + if (UPB_UNLIKELY(len & 0x80)) { + // Size varint >1 byte (length >= 128). + ptr = fastdecode_longsize(ptr, &len); + if (!ptr) { + // Corrupt wire format: size exceeded INT_MAX. + return NULL; + } + } + if (ptr - d->end + (int)len > d->limit) { + // Corrupt wire format: invalid limit. + return NULL; + } + int delta = decode_pushlimit(d, ptr, len); + ptr = func(d, ptr, ctx); + decode_poplimit(d, ptr, delta); + } else { + // Fast case: Sub-message is <128 bytes and fits in the current buffer. + // This means we can preserve limit/limit_ptr verbatim. + const char *saved_limit_ptr = d->limit_ptr; + int saved_limit = d->limit; + d->limit_ptr = ptr + len; + d->limit = d->limit_ptr - d->end; + UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit)); + ptr = func(d, ptr, ctx); + d->limit_ptr = saved_limit_ptr; + d->limit = saved_limit; + UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit)); + } + return ptr; +} + +/* singular, oneof, repeated field handling ***********************************/ + +typedef struct { + upb_array *arr; + void *end; +} fastdecode_arr; + +typedef enum { + FD_NEXT_ATLIMIT, + FD_NEXT_SAMEFIELD, + FD_NEXT_OTHERFIELD +} fastdecode_next; + +typedef struct { + void *dst; + fastdecode_next next; + uint32_t tag; +} fastdecode_nextret; + +UPB_FORCEINLINE +static void *fastdecode_resizearr(upb_decstate *d, void *dst, + fastdecode_arr *farr, int valbytes) { + if (UPB_UNLIKELY(dst == farr->end)) { + size_t old_size = farr->arr->size; + size_t old_bytes = old_size * valbytes; + size_t new_size = old_size * 2; + size_t new_bytes = new_size * valbytes; + char *old_ptr = _upb_array_ptr(farr->arr); + char *new_ptr = upb_arena_realloc(&d->arena, old_ptr, old_bytes, new_bytes); + uint8_t elem_size_lg2 = __builtin_ctz(valbytes); + farr->arr->size = new_size; + farr->arr->data = _upb_array_tagptr(new_ptr, elem_size_lg2); + dst = (void*)(new_ptr + (old_size * valbytes)); + farr->end = (void*)(new_ptr + (new_size * valbytes)); + } + return dst; +} + +UPB_FORCEINLINE +static bool fastdecode_tagmatch(uint32_t tag, uint64_t data, int tagbytes) { + if (tagbytes == 1) { + return (uint8_t)tag == (uint8_t)data; + } else { + return (uint16_t)tag == (uint16_t)data; + } +} + +UPB_FORCEINLINE +static void fastdecode_commitarr(void *dst, fastdecode_arr *farr, + int valbytes) { + farr->arr->len = + (size_t)((char *)dst - (char *)_upb_array_ptr(farr->arr)) / valbytes; +} + +UPB_FORCEINLINE +static fastdecode_nextret fastdecode_nextrepeated(upb_decstate *d, void *dst, + const char **ptr, + fastdecode_arr *farr, + uint64_t data, int tagbytes, + int valbytes) { + fastdecode_nextret ret; + dst = (char *)dst + valbytes; + + if (UPB_LIKELY(!decode_isdone(d, ptr))) { + ret.tag = fastdecode_loadtag(*ptr); + if (fastdecode_tagmatch(ret.tag, data, tagbytes)) { + ret.next = FD_NEXT_SAMEFIELD; + } else { + fastdecode_commitarr(dst, farr, valbytes); + ret.next = FD_NEXT_OTHERFIELD; + } + } else { + fastdecode_commitarr(dst, farr, valbytes); + ret.next = FD_NEXT_ATLIMIT; + } + + ret.dst = dst; + return ret; +} + +UPB_FORCEINLINE +static void *fastdecode_fieldmem(upb_msg *msg, uint64_t data) { + size_t ofs = data >> 48; + return (char *)msg + ofs; +} + +UPB_FORCEINLINE +static void *fastdecode_getfield(upb_decstate *d, const char *ptr, upb_msg *msg, + uint64_t *data, uint64_t *hasbits, + fastdecode_arr *farr, int valbytes, + upb_card card) { + switch (card) { + case CARD_s: { + uint8_t hasbit_index = *data >> 24; + // Set hasbit and return pointer to scalar field. + *hasbits |= 1ull << hasbit_index; + return fastdecode_fieldmem(msg, *data); + } + case CARD_o: { + uint16_t case_ofs = *data >> 32; + uint32_t *oneof_case = UPB_PTR_AT(msg, case_ofs, uint32_t); + uint8_t field_number = *data >> 24; + *oneof_case = field_number; + return fastdecode_fieldmem(msg, *data); + } + case CARD_r: { + // Get pointer to upb_array and allocate/expand if necessary. + uint8_t elem_size_lg2 = __builtin_ctz(valbytes); + upb_array **arr_p = fastdecode_fieldmem(msg, *data); + char *begin; + *(uint32_t*)msg |= *hasbits; + *hasbits = 0; + if (UPB_LIKELY(!*arr_p)) { + farr->arr = _upb_array_new(&d->arena, 8, elem_size_lg2); + *arr_p = farr->arr; + } else { + farr->arr = *arr_p; + } + begin = _upb_array_ptr(farr->arr); + farr->end = begin + (farr->arr->size * valbytes); + *data = fastdecode_loadtag(ptr); + return begin + (farr->arr->len * valbytes); + } + default: + UPB_UNREACHABLE(); + } +} + +UPB_FORCEINLINE +static bool fastdecode_flippacked(uint64_t *data, int tagbytes) { + *data ^= (0x2 ^ 0x0); // Patch data to match packed wiretype. + return fastdecode_checktag(*data, tagbytes); +} + +/* varint fields **************************************************************/ + +UPB_FORCEINLINE +static uint64_t fastdecode_munge(uint64_t val, int valbytes, bool zigzag) { + if (valbytes == 1) { + return val != 0; + } else if (zigzag) { + if (valbytes == 4) { + uint32_t n = val; + return (n >> 1) ^ -(int32_t)(n & 1); + } else if (valbytes == 8) { + return (val >> 1) ^ -(int64_t)(val & 1); + } + UPB_UNREACHABLE(); + } + return val; +} + +UPB_FORCEINLINE +static const char *fastdecode_varint64(const char *ptr, uint64_t *val) { + ptr++; + *val = (uint8_t)ptr[-1]; + if (UPB_UNLIKELY(*val & 0x80)) { + int i; + for (i = 0; i < 8; i++) { + ptr++; + uint64_t byte = (uint8_t)ptr[-1]; + *val += (byte - 1) << (7 + 7 * i); + if (UPB_LIKELY((byte & 0x80) == 0)) goto done; + } + ptr++; + uint64_t byte = (uint8_t)ptr[-1]; + if (byte > 1) { + return NULL; + } + *val += (byte - 1) << 63; + } +done: + UPB_ASSUME(ptr != NULL); + return ptr; +} + +UPB_FORCEINLINE +static const char *fastdecode_unpackedvarint(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, upb_card card, + bool zigzag, + _upb_field_parser *packed) { + uint64_t val; + void *dst; + fastdecode_arr farr; + + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) { + return packed(UPB_PARSE_ARGS); + } + RETURN_GENERIC("varint field tag mismatch\n"); + } + + dst = + fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, card); + if (card == CARD_r) { + if (UPB_UNLIKELY(!dst)) { + RETURN_GENERIC("need array resize\n"); + } + } + +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, valbytes); + } + + ptr += tagbytes; + ptr = fastdecode_varint64(ptr, &val); + if (ptr == NULL) return fastdecode_err(d); + val = fastdecode_munge(val, valbytes, zigzag); + memcpy(dst, &val, valbytes); + + if (card == CARD_r) { + fastdecode_nextret ret = + fastdecode_nextrepeated(d, dst, &ptr, &farr, data, tagbytes, valbytes); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + goto again; + case FD_NEXT_OTHERFIELD: + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + return ptr; + } + } + + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +typedef struct { + uint8_t valbytes; + bool zigzag; + void *dst; + fastdecode_arr farr; +} fastdecode_varintdata; + +UPB_FORCEINLINE +static const char *fastdecode_topackedvarint(upb_decstate *d, const char *ptr, + void *ctx) { + fastdecode_varintdata *data = ctx; + void *dst = data->dst; + uint64_t val; + + while (!decode_isdone(d, &ptr)) { + dst = fastdecode_resizearr(d, dst, &data->farr, data->valbytes); + ptr = fastdecode_varint64(ptr, &val); + if (ptr == NULL) return NULL; + val = fastdecode_munge(val, data->valbytes, data->zigzag); + memcpy(dst, &val, data->valbytes); + dst = (char *)dst + data->valbytes; + } + + fastdecode_commitarr(dst, &data->farr, data->valbytes); + return ptr; +} + +UPB_FORCEINLINE +static const char *fastdecode_packedvarint(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, bool zigzag, + _upb_field_parser *unpacked) { + fastdecode_varintdata ctx = {valbytes, zigzag}; + + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + if (fastdecode_flippacked(&data, tagbytes)) { + return unpacked(UPB_PARSE_ARGS); + } else { + RETURN_GENERIC("varint field tag mismatch\n"); + } + } + + ctx.dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &ctx.farr, + valbytes, CARD_r); + if (UPB_UNLIKELY(!ctx.dst)) { + RETURN_GENERIC("need array resize\n"); + } + + ptr += tagbytes; + ptr = fastdecode_delimited(d, ptr, &fastdecode_topackedvarint, &ctx); + + if (UPB_UNLIKELY(ptr == NULL)) { + return fastdecode_err(d); + } + + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +UPB_FORCEINLINE +static const char *fastdecode_varint(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, upb_card card, bool zigzag, + _upb_field_parser *unpacked, + _upb_field_parser *packed) { + if (card == CARD_p) { + return fastdecode_packedvarint(UPB_PARSE_ARGS, tagbytes, valbytes, zigzag, + unpacked); + } else { + return fastdecode_unpackedvarint(UPB_PARSE_ARGS, tagbytes, valbytes, card, + zigzag, packed); + } +} + +#define z_ZZ true +#define b_ZZ false +#define v_ZZ false + +/* Generate all combinations: + * {s,o,r,p} x {b1,v4,z4,v8,z8} x {1bt,2bt} */ + +#define F(card, type, valbytes, tagbytes) \ + UPB_NOINLINE \ + const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \ + return fastdecode_varint(UPB_PARSE_ARGS, tagbytes, valbytes, CARD_##card, \ + type##_ZZ, \ + &upb_pr##type##valbytes##_##tagbytes##bt, \ + &upb_pp##type##valbytes##_##tagbytes##bt); \ + } + +#define TYPES(card, tagbytes) \ + F(card, b, 1, tagbytes) \ + F(card, v, 4, tagbytes) \ + F(card, v, 8, tagbytes) \ + F(card, z, 4, tagbytes) \ + F(card, z, 8, tagbytes) + +#define TAGBYTES(card) \ + TYPES(card, 1) \ + TYPES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) +TAGBYTES(p) + +#undef z_ZZ +#undef b_ZZ +#undef v_ZZ +#undef o_ONEOF +#undef s_ONEOF +#undef r_ONEOF +#undef F +#undef TYPES +#undef TAGBYTES + + +/* fixed fields ***************************************************************/ + +UPB_FORCEINLINE +static const char *fastdecode_unpackedfixed(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, upb_card card, + _upb_field_parser *packed) { + void *dst; + fastdecode_arr farr; + + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) { + return packed(UPB_PARSE_ARGS); + } + RETURN_GENERIC("fixed field tag mismatch\n"); + } + + dst = + fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, card); + if (card == CARD_r) { + if (UPB_UNLIKELY(!dst)) { + RETURN_GENERIC("couldn't allocate array in arena\n"); + } + } + + +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, valbytes); + } + + ptr += tagbytes; + memcpy(dst, ptr, valbytes); + ptr += valbytes; + + if (card == CARD_r) { + fastdecode_nextret ret = + fastdecode_nextrepeated(d, dst, &ptr, &farr, data, tagbytes, valbytes); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + goto again; + case FD_NEXT_OTHERFIELD: + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + return ptr; + } + } + + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +UPB_FORCEINLINE +static const char *fastdecode_packedfixed(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, + _upb_field_parser *unpacked) { + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + if (fastdecode_flippacked(&data, tagbytes)) { + return unpacked(UPB_PARSE_ARGS); + } else { + RETURN_GENERIC("varint field tag mismatch\n"); + } + } + + ptr += tagbytes; + int size = (uint8_t)ptr[0]; + ptr++; + if (size & 0x80) { + ptr = fastdecode_longsize(ptr, &size); + } + + if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr)) || + (size % valbytes) != 0) { + return fastdecode_err(d); + } + + upb_array **arr_p = fastdecode_fieldmem(msg, data); + upb_array *arr = *arr_p; + uint8_t elem_size_lg2 = __builtin_ctz(valbytes); + int elems = size / valbytes; + + if (UPB_LIKELY(!arr)) { + *arr_p = arr = _upb_array_new(&d->arena, elems, elem_size_lg2); + if (!arr) { + return fastdecode_err(d); + } + } else { + _upb_array_resize(arr, elems, &d->arena); + } + + char *dst = _upb_array_ptr(arr); + memcpy(dst, ptr, size); + arr->len = elems; + + return fastdecode_dispatch(d, ptr + size, msg, table, hasbits); +} + +UPB_FORCEINLINE +static const char *fastdecode_fixed(UPB_PARSE_PARAMS, int tagbytes, + int valbytes, upb_card card, + _upb_field_parser *unpacked, + _upb_field_parser *packed) { + if (card == CARD_p) { + return fastdecode_packedfixed(UPB_PARSE_ARGS, tagbytes, valbytes, unpacked); + } else { + return fastdecode_unpackedfixed(UPB_PARSE_ARGS, tagbytes, valbytes, card, + packed); + } +} + +/* Generate all combinations: + * {s,o,r,p} x {f4,f8} x {1bt,2bt} */ + +#define F(card, valbytes, tagbytes) \ + UPB_NOINLINE \ + const char *upb_p##card##f##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \ + return fastdecode_fixed(UPB_PARSE_ARGS, tagbytes, valbytes, CARD_##card, \ + &upb_ppf##valbytes##_##tagbytes##bt, \ + &upb_prf##valbytes##_##tagbytes##bt); \ + } + +#define TYPES(card, tagbytes) \ + F(card, 4, tagbytes) \ + F(card, 8, tagbytes) + +#define TAGBYTES(card) \ + TYPES(card, 1) \ + TYPES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) +TAGBYTES(p) + +#undef F +#undef TYPES +#undef TAGBYTES + +/* string fields **************************************************************/ + +typedef const char *fastdecode_copystr_func(struct upb_decstate *d, + const char *ptr, upb_msg *msg, + const upb_msglayout *table, + uint64_t hasbits, upb_strview *dst); + +UPB_NOINLINE +static const char *fastdecode_verifyutf8(upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits, upb_strview *dst) { + if (!decode_verifyutf8_inl(dst->data, dst->size)) { + return fastdecode_err(d); + } + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +UPB_FORCEINLINE +static const char *fastdecode_longstring(struct upb_decstate *d, + const char *ptr, upb_msg *msg, + intptr_t table, uint64_t hasbits, + upb_strview *dst, + bool validate_utf8) { + int size = (uint8_t)ptr[0]; // Could plumb through hasbits. + ptr++; + if (size & 0x80) { + ptr = fastdecode_longsize(ptr, &size); + } + + if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr))) { + dst->size = 0; + return fastdecode_err(d); + } + + if (d->alias) { + dst->data = ptr; + dst->size = size; + } else { + char *data = upb_arena_malloc(&d->arena, size); + if (!data) { + return fastdecode_err(d); + } + memcpy(data, ptr, size); + dst->data = data; + dst->size = size; + } + + if (validate_utf8) { + return fastdecode_verifyutf8(d, ptr + size, msg, table, hasbits, dst); + } else { + return fastdecode_dispatch(d, ptr + size, msg, table, hasbits); + } +} + +UPB_NOINLINE +static const char *fastdecode_longstring_utf8(struct upb_decstate *d, + const char *ptr, upb_msg *msg, + intptr_t table, uint64_t hasbits, + upb_strview *dst) { + return fastdecode_longstring(d, ptr, msg, table, hasbits, dst, true); +} + +UPB_NOINLINE +static const char *fastdecode_longstring_noutf8(struct upb_decstate *d, + const char *ptr, upb_msg *msg, + intptr_t table, + uint64_t hasbits, + upb_strview *dst) { + return fastdecode_longstring(d, ptr, msg, table, hasbits, dst, false); +} + +UPB_FORCEINLINE +static void fastdecode_docopy(upb_decstate *d, const char *ptr, uint32_t size, + int copy, char *data, upb_strview *dst) { + d->arena.head.ptr += copy; + dst->data = data; + UPB_UNPOISON_MEMORY_REGION(data, copy); + memcpy(data, ptr, copy); + UPB_POISON_MEMORY_REGION(data + size, copy - size); +} + +UPB_FORCEINLINE +static const char *fastdecode_copystring(UPB_PARSE_PARAMS, int tagbytes, + upb_card card, bool validate_utf8) { + upb_strview *dst; + fastdecode_arr farr; + int64_t size; + size_t arena_has; + size_t common_has; + char *buf; + + UPB_ASSERT(!d->alias); + UPB_ASSERT(fastdecode_checktag(data, tagbytes)); + + dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, + sizeof(upb_strview), card); + +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview)); + } + + size = (uint8_t)ptr[tagbytes]; + ptr += tagbytes + 1; + dst->size = size; + + buf = d->arena.head.ptr; + arena_has = _upb_arenahas(&d->arena); + common_has = UPB_MIN(arena_has, (d->end - ptr) + 16); + + if (UPB_LIKELY(size <= 15 - tagbytes)) { + if (arena_has < 16) goto longstr; + d->arena.head.ptr += 16; + memcpy(buf, ptr - tagbytes - 1, 16); + dst->data = buf + tagbytes + 1; + } else if (UPB_LIKELY(size <= 32)) { + if (UPB_UNLIKELY(common_has < 32)) goto longstr; + fastdecode_docopy(d, ptr, size, 32, buf, dst); + } else if (UPB_LIKELY(size <= 64)) { + if (UPB_UNLIKELY(common_has < 64)) goto longstr; + fastdecode_docopy(d, ptr, size, 64, buf, dst); + } else if (UPB_LIKELY(size < 128)) { + if (UPB_UNLIKELY(common_has < 128)) goto longstr; + fastdecode_docopy(d, ptr, size, 128, buf, dst); + } else { + goto longstr; + } + + ptr += size; + + if (card == CARD_r) { + if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) { + return fastdecode_err(d); + } + fastdecode_nextret ret = fastdecode_nextrepeated( + d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview)); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + goto again; + case FD_NEXT_OTHERFIELD: + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + return ptr; + } + } + + if (card != CARD_r && validate_utf8) { + return fastdecode_verifyutf8(d, ptr, msg, table, hasbits, dst); + } + + return fastdecode_dispatch(d, ptr, msg, table, hasbits); + +longstr: + ptr--; + if (validate_utf8) { + return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, dst); + } else { + return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, dst); + } +} + +UPB_FORCEINLINE +static const char *fastdecode_string(UPB_PARSE_PARAMS, int tagbytes, + upb_card card, _upb_field_parser *copyfunc, + bool validate_utf8) { + upb_strview *dst; + fastdecode_arr farr; + int64_t size; + + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + RETURN_GENERIC("string field tag mismatch\n"); + } + + if (UPB_UNLIKELY(!d->alias)) { + return copyfunc(UPB_PARSE_ARGS); + } + + dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, + sizeof(upb_strview), card); + +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview)); + } + + size = (int8_t)ptr[tagbytes]; + ptr += tagbytes + 1; + dst->data = ptr; + dst->size = size; + + if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->end))) { + ptr--; + if (validate_utf8) { + return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, dst); + } else { + return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, dst); + } + } + + ptr += size; + + if (card == CARD_r) { + if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) { + return fastdecode_err(d); + } + fastdecode_nextret ret = fastdecode_nextrepeated( + d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview)); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + if (UPB_UNLIKELY(!d->alias)) { + // Buffer flipped and we can't alias any more. Bounce to copyfunc(), + // but via dispatch since we need to reload table data also. + fastdecode_commitarr(dst, &farr, sizeof(upb_strview)); + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + } + goto again; + case FD_NEXT_OTHERFIELD: + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + return ptr; + } + } + + if (card != CARD_r && validate_utf8) { + return fastdecode_verifyutf8(d, ptr, msg, table, hasbits, dst); + } + + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +/* Generate all combinations: + * {p,c} x {s,o,r} x {s, b} x {1bt,2bt} */ + +#define s_VALIDATE true +#define b_VALIDATE false + +#define F(card, tagbytes, type) \ + UPB_NOINLINE \ + const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \ + return fastdecode_copystring(UPB_PARSE_ARGS, tagbytes, CARD_##card, \ + type##_VALIDATE); \ + } \ + const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \ + return fastdecode_string(UPB_PARSE_ARGS, tagbytes, CARD_##card, \ + &upb_c##card##type##_##tagbytes##bt, \ + type##_VALIDATE); \ + } + +#define UTF8(card, tagbytes) \ + F(card, tagbytes, s) \ + F(card, tagbytes, b) + +#define TAGBYTES(card) \ + UTF8(card, 1) \ + UTF8(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef s_VALIDATE +#undef b_VALIDATE +#undef F +#undef TAGBYTES + +/* message fields *************************************************************/ + +UPB_INLINE +upb_msg *decode_newmsg_ceil(upb_decstate *d, const upb_msglayout *l, + int msg_ceil_bytes) { + size_t size = l->size + sizeof(upb_msg_internal); + char *msg_data; + if (UPB_LIKELY(msg_ceil_bytes > 0 && + _upb_arenahas(&d->arena) >= msg_ceil_bytes)) { + UPB_ASSERT(size <= (size_t)msg_ceil_bytes); + msg_data = d->arena.head.ptr; + d->arena.head.ptr += size; + UPB_UNPOISON_MEMORY_REGION(msg_data, msg_ceil_bytes); + memset(msg_data, 0, msg_ceil_bytes); + UPB_POISON_MEMORY_REGION(msg_data + size, msg_ceil_bytes - size); + } else { + msg_data = (char*)upb_arena_malloc(&d->arena, size); + memset(msg_data, 0, size); + } + return msg_data + sizeof(upb_msg_internal); +} + +typedef struct { + intptr_t table; + upb_msg *msg; +} fastdecode_submsgdata; + +UPB_FORCEINLINE +static const char *fastdecode_tosubmsg(upb_decstate *d, const char *ptr, + void *ctx) { + fastdecode_submsgdata *submsg = ctx; + ptr = fastdecode_dispatch(d, ptr, submsg->msg, submsg->table, 0); + UPB_ASSUME(ptr != NULL); + return ptr; +} + +UPB_FORCEINLINE +static const char *fastdecode_submsg(UPB_PARSE_PARAMS, int tagbytes, + int msg_ceil_bytes, upb_card card) { + + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { + RETURN_GENERIC("submessage field tag mismatch\n"); + } + + if (--d->depth == 0) return fastdecode_err(d); + + upb_msg **dst; + uint32_t submsg_idx = (data >> 16) & 0xff; + const upb_msglayout *tablep = decode_totablep(table); + const upb_msglayout *subtablep = tablep->submsgs[submsg_idx]; + fastdecode_submsgdata submsg = {decode_totable(subtablep)}; + fastdecode_arr farr; + + if (subtablep->table_mask == (uint8_t)-1) { + RETURN_GENERIC("submessage doesn't have fast tables."); + } + + dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, + sizeof(upb_msg *), card); + + if (card == CARD_s) { + *(uint32_t*)msg |= hasbits; + hasbits = 0; + } + +again: + if (card == CARD_r) { + dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_msg*)); + } + + submsg.msg = *dst; + + if (card == CARD_r || UPB_LIKELY(!submsg.msg)) { + *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes); + } + + ptr += tagbytes; + ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg); + + if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) { + return fastdecode_err(d); + } + + if (card == CARD_r) { + fastdecode_nextret ret = fastdecode_nextrepeated( + d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_msg *)); + switch (ret.next) { + case FD_NEXT_SAMEFIELD: + dst = ret.dst; + goto again; + case FD_NEXT_OTHERFIELD: + d->depth++; + return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag); + case FD_NEXT_ATLIMIT: + d->depth++; + return ptr; + } + } + + d->depth++; + return fastdecode_dispatch(d, ptr, msg, table, hasbits); +} + +#define F(card, tagbytes, size_ceil, ceil_arg) \ + const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b( \ + UPB_PARSE_PARAMS) { \ + return fastdecode_submsg(UPB_PARSE_ARGS, tagbytes, ceil_arg, CARD_##card); \ + } + +#define SIZES(card, tagbytes) \ + F(card, tagbytes, 64, 64) \ + F(card, tagbytes, 128, 128) \ + F(card, tagbytes, 192, 192) \ + F(card, tagbytes, 256, 256) \ + F(card, tagbytes, max, -1) + +#define TAGBYTES(card) \ + SIZES(card, 1) \ + SIZES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef TAGBYTES +#undef SIZES +#undef F + +#endif /* UPB_FASTTABLE */ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include + + +static const upb_msglayout *const google_protobuf_FileDescriptorSet_submsgs[1] = { + &google_protobuf_FileDescriptorProto_msginit, +}; + +static const upb_msglayout_field google_protobuf_FileDescriptorSet__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_FileDescriptorSet_msginit = { + &google_protobuf_FileDescriptorSet_submsgs[0], + &google_protobuf_FileDescriptorSet__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] = { + &google_protobuf_DescriptorProto_msginit, + &google_protobuf_EnumDescriptorProto_msginit, + &google_protobuf_FieldDescriptorProto_msginit, + &google_protobuf_FileOptions_msginit, + &google_protobuf_ServiceDescriptorProto_msginit, + &google_protobuf_SourceCodeInfo_msginit, +}; + +static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12] = { + {1, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(12, 24), 2, 0, 12, 1}, + {3, UPB_SIZE(36, 72), 0, 0, 12, 3}, + {4, UPB_SIZE(40, 80), 0, 0, 11, 3}, + {5, UPB_SIZE(44, 88), 0, 1, 11, 3}, + {6, UPB_SIZE(48, 96), 0, 4, 11, 3}, + {7, UPB_SIZE(52, 104), 0, 2, 11, 3}, + {8, UPB_SIZE(28, 56), 3, 3, 11, 1}, + {9, UPB_SIZE(32, 64), 4, 5, 11, 1}, + {10, UPB_SIZE(56, 112), 0, 0, 5, 3}, + {11, UPB_SIZE(60, 120), 0, 0, 5, 3}, + {12, UPB_SIZE(20, 40), 5, 0, 12, 1}, +}; + +const upb_msglayout google_protobuf_FileDescriptorProto_msginit = { + &google_protobuf_FileDescriptorProto_submsgs[0], + &google_protobuf_FileDescriptorProto__fields[0], + UPB_SIZE(64, 128), 12, false, 255, +}; + +static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[7] = { + &google_protobuf_DescriptorProto_msginit, + &google_protobuf_DescriptorProto_ExtensionRange_msginit, + &google_protobuf_DescriptorProto_ReservedRange_msginit, + &google_protobuf_EnumDescriptorProto_msginit, + &google_protobuf_FieldDescriptorProto_msginit, + &google_protobuf_MessageOptions_msginit, + &google_protobuf_OneofDescriptorProto_msginit, +}; + +static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = { + {1, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(16, 32), 0, 4, 11, 3}, + {3, UPB_SIZE(20, 40), 0, 0, 11, 3}, + {4, UPB_SIZE(24, 48), 0, 3, 11, 3}, + {5, UPB_SIZE(28, 56), 0, 1, 11, 3}, + {6, UPB_SIZE(32, 64), 0, 4, 11, 3}, + {7, UPB_SIZE(12, 24), 2, 5, 11, 1}, + {8, UPB_SIZE(36, 72), 0, 6, 11, 3}, + {9, UPB_SIZE(40, 80), 0, 2, 11, 3}, + {10, UPB_SIZE(44, 88), 0, 0, 12, 3}, +}; + +const upb_msglayout google_protobuf_DescriptorProto_msginit = { + &google_protobuf_DescriptorProto_submsgs[0], + &google_protobuf_DescriptorProto__fields[0], + UPB_SIZE(48, 96), 10, false, 255, +}; + +static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = { + &google_protobuf_ExtensionRangeOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_DescriptorProto_ExtensionRange__fields[3] = { + {1, UPB_SIZE(4, 4), 1, 0, 5, 1}, + {2, UPB_SIZE(8, 8), 2, 0, 5, 1}, + {3, UPB_SIZE(12, 16), 3, 0, 11, 1}, +}; + +const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit = { + &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0], + &google_protobuf_DescriptorProto_ExtensionRange__fields[0], + UPB_SIZE(16, 24), 3, false, 255, +}; + +static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__fields[2] = { + {1, UPB_SIZE(4, 4), 1, 0, 5, 1}, + {2, UPB_SIZE(8, 8), 2, 0, 5, 1}, +}; + +const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit = { + NULL, + &google_protobuf_DescriptorProto_ReservedRange__fields[0], + UPB_SIZE(16, 16), 2, false, 255, +}; + +static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_ExtensionRangeOptions__fields[1] = { + {999, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit = { + &google_protobuf_ExtensionRangeOptions_submsgs[0], + &google_protobuf_ExtensionRangeOptions__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1] = { + &google_protobuf_FieldOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = { + {1, UPB_SIZE(24, 24), 1, 0, 12, 1}, + {2, UPB_SIZE(32, 40), 2, 0, 12, 1}, + {3, UPB_SIZE(12, 12), 3, 0, 5, 1}, + {4, UPB_SIZE(4, 4), 4, 0, 14, 1}, + {5, UPB_SIZE(8, 8), 5, 0, 14, 1}, + {6, UPB_SIZE(40, 56), 6, 0, 12, 1}, + {7, UPB_SIZE(48, 72), 7, 0, 12, 1}, + {8, UPB_SIZE(64, 104), 8, 0, 11, 1}, + {9, UPB_SIZE(16, 16), 9, 0, 5, 1}, + {10, UPB_SIZE(56, 88), 10, 0, 12, 1}, + {17, UPB_SIZE(20, 20), 11, 0, 8, 1}, +}; + +const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = { + &google_protobuf_FieldDescriptorProto_submsgs[0], + &google_protobuf_FieldDescriptorProto__fields[0], + UPB_SIZE(72, 112), 11, false, 255, +}; + +static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = { + &google_protobuf_OneofOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2] = { + {1, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(12, 24), 2, 0, 11, 1}, +}; + +const upb_msglayout google_protobuf_OneofDescriptorProto_msginit = { + &google_protobuf_OneofDescriptorProto_submsgs[0], + &google_protobuf_OneofDescriptorProto__fields[0], + UPB_SIZE(16, 32), 2, false, 255, +}; + +static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] = { + &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, + &google_protobuf_EnumOptions_msginit, + &google_protobuf_EnumValueDescriptorProto_msginit, +}; + +static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5] = { + {1, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(16, 32), 0, 2, 11, 3}, + {3, UPB_SIZE(12, 24), 2, 1, 11, 1}, + {4, UPB_SIZE(20, 40), 0, 0, 11, 3}, + {5, UPB_SIZE(24, 48), 0, 0, 12, 3}, +}; + +const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = { + &google_protobuf_EnumDescriptorProto_submsgs[0], + &google_protobuf_EnumDescriptorProto__fields[0], + UPB_SIZE(32, 64), 5, false, 255, +}; + +static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = { + {1, UPB_SIZE(4, 4), 1, 0, 5, 1}, + {2, UPB_SIZE(8, 8), 2, 0, 5, 1}, +}; + +const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = { + NULL, + &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0], + UPB_SIZE(16, 16), 2, false, 255, +}; + +static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_submsgs[1] = { + &google_protobuf_EnumValueOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__fields[3] = { + {1, UPB_SIZE(8, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(4, 4), 2, 0, 5, 1}, + {3, UPB_SIZE(16, 24), 3, 0, 11, 1}, +}; + +const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit = { + &google_protobuf_EnumValueDescriptorProto_submsgs[0], + &google_protobuf_EnumValueDescriptorProto__fields[0], + UPB_SIZE(24, 32), 3, false, 255, +}; + +static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs[2] = { + &google_protobuf_MethodDescriptorProto_msginit, + &google_protobuf_ServiceOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[3] = { + {1, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(16, 32), 0, 0, 11, 3}, + {3, UPB_SIZE(12, 24), 2, 1, 11, 1}, +}; + +const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit = { + &google_protobuf_ServiceDescriptorProto_submsgs[0], + &google_protobuf_ServiceDescriptorProto__fields[0], + UPB_SIZE(24, 48), 3, false, 255, +}; + +static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[1] = { + &google_protobuf_MethodOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_MethodDescriptorProto__fields[6] = { + {1, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {2, UPB_SIZE(12, 24), 2, 0, 12, 1}, + {3, UPB_SIZE(20, 40), 3, 0, 12, 1}, + {4, UPB_SIZE(28, 56), 4, 0, 11, 1}, + {5, UPB_SIZE(1, 1), 5, 0, 8, 1}, + {6, UPB_SIZE(2, 2), 6, 0, 8, 1}, +}; + +const upb_msglayout google_protobuf_MethodDescriptorProto_msginit = { + &google_protobuf_MethodDescriptorProto_submsgs[0], + &google_protobuf_MethodDescriptorProto__fields[0], + UPB_SIZE(32, 64), 6, false, 255, +}; + +static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = { + {1, UPB_SIZE(20, 24), 1, 0, 12, 1}, + {8, UPB_SIZE(28, 40), 2, 0, 12, 1}, + {9, UPB_SIZE(4, 4), 3, 0, 14, 1}, + {10, UPB_SIZE(8, 8), 4, 0, 8, 1}, + {11, UPB_SIZE(36, 56), 5, 0, 12, 1}, + {16, UPB_SIZE(9, 9), 6, 0, 8, 1}, + {17, UPB_SIZE(10, 10), 7, 0, 8, 1}, + {18, UPB_SIZE(11, 11), 8, 0, 8, 1}, + {20, UPB_SIZE(12, 12), 9, 0, 8, 1}, + {23, UPB_SIZE(13, 13), 10, 0, 8, 1}, + {27, UPB_SIZE(14, 14), 11, 0, 8, 1}, + {31, UPB_SIZE(15, 15), 12, 0, 8, 1}, + {36, UPB_SIZE(44, 72), 13, 0, 12, 1}, + {37, UPB_SIZE(52, 88), 14, 0, 12, 1}, + {39, UPB_SIZE(60, 104), 15, 0, 12, 1}, + {40, UPB_SIZE(68, 120), 16, 0, 12, 1}, + {41, UPB_SIZE(76, 136), 17, 0, 12, 1}, + {42, UPB_SIZE(16, 16), 18, 0, 8, 1}, + {44, UPB_SIZE(84, 152), 19, 0, 12, 1}, + {45, UPB_SIZE(92, 168), 20, 0, 12, 1}, + {999, UPB_SIZE(100, 184), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_FileOptions_msginit = { + &google_protobuf_FileOptions_submsgs[0], + &google_protobuf_FileOptions__fields[0], + UPB_SIZE(104, 192), 21, false, 255, +}; + +static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_MessageOptions__fields[5] = { + {1, UPB_SIZE(1, 1), 1, 0, 8, 1}, + {2, UPB_SIZE(2, 2), 2, 0, 8, 1}, + {3, UPB_SIZE(3, 3), 3, 0, 8, 1}, + {7, UPB_SIZE(4, 4), 4, 0, 8, 1}, + {999, UPB_SIZE(8, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_MessageOptions_msginit = { + &google_protobuf_MessageOptions_submsgs[0], + &google_protobuf_MessageOptions__fields[0], + UPB_SIZE(16, 16), 5, false, 255, +}; + +static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_FieldOptions__fields[7] = { + {1, UPB_SIZE(4, 4), 1, 0, 14, 1}, + {2, UPB_SIZE(12, 12), 2, 0, 8, 1}, + {3, UPB_SIZE(13, 13), 3, 0, 8, 1}, + {5, UPB_SIZE(14, 14), 4, 0, 8, 1}, + {6, UPB_SIZE(8, 8), 5, 0, 14, 1}, + {10, UPB_SIZE(15, 15), 6, 0, 8, 1}, + {999, UPB_SIZE(16, 16), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_FieldOptions_msginit = { + &google_protobuf_FieldOptions_submsgs[0], + &google_protobuf_FieldOptions__fields[0], + UPB_SIZE(24, 24), 7, false, 255, +}; + +static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_OneofOptions__fields[1] = { + {999, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_OneofOptions_msginit = { + &google_protobuf_OneofOptions_submsgs[0], + &google_protobuf_OneofOptions__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_EnumOptions__fields[3] = { + {2, UPB_SIZE(1, 1), 1, 0, 8, 1}, + {3, UPB_SIZE(2, 2), 2, 0, 8, 1}, + {999, UPB_SIZE(4, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_EnumOptions_msginit = { + &google_protobuf_EnumOptions_submsgs[0], + &google_protobuf_EnumOptions__fields[0], + UPB_SIZE(8, 16), 3, false, 255, +}; + +static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_EnumValueOptions__fields[2] = { + {1, UPB_SIZE(1, 1), 1, 0, 8, 1}, + {999, UPB_SIZE(4, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_EnumValueOptions_msginit = { + &google_protobuf_EnumValueOptions_submsgs[0], + &google_protobuf_EnumValueOptions__fields[0], + UPB_SIZE(8, 16), 2, false, 255, +}; + +static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_ServiceOptions__fields[2] = { + {33, UPB_SIZE(1, 1), 1, 0, 8, 1}, + {999, UPB_SIZE(4, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_ServiceOptions_msginit = { + &google_protobuf_ServiceOptions_submsgs[0], + &google_protobuf_ServiceOptions__fields[0], + UPB_SIZE(8, 16), 2, false, 255, +}; + +static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_MethodOptions__fields[3] = { + {33, UPB_SIZE(8, 8), 1, 0, 8, 1}, + {34, UPB_SIZE(4, 4), 2, 0, 14, 1}, + {999, UPB_SIZE(12, 16), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_MethodOptions_msginit = { + &google_protobuf_MethodOptions_submsgs[0], + &google_protobuf_MethodOptions__fields[0], + UPB_SIZE(16, 24), 3, false, 255, +}; + +static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] = { + &google_protobuf_UninterpretedOption_NamePart_msginit, +}; + +static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7] = { + {2, UPB_SIZE(56, 80), 0, 0, 11, 3}, + {3, UPB_SIZE(32, 32), 1, 0, 12, 1}, + {4, UPB_SIZE(8, 8), 2, 0, 4, 1}, + {5, UPB_SIZE(16, 16), 3, 0, 3, 1}, + {6, UPB_SIZE(24, 24), 4, 0, 1, 1}, + {7, UPB_SIZE(40, 48), 5, 0, 12, 1}, + {8, UPB_SIZE(48, 64), 6, 0, 12, 1}, +}; + +const upb_msglayout google_protobuf_UninterpretedOption_msginit = { + &google_protobuf_UninterpretedOption_submsgs[0], + &google_protobuf_UninterpretedOption__fields[0], + UPB_SIZE(64, 96), 7, false, 255, +}; + +static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = { + {1, UPB_SIZE(4, 8), 1, 0, 12, 2}, + {2, UPB_SIZE(1, 1), 2, 0, 8, 2}, +}; + +const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit = { + NULL, + &google_protobuf_UninterpretedOption_NamePart__fields[0], + UPB_SIZE(16, 32), 2, false, 255, +}; + +static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = { + &google_protobuf_SourceCodeInfo_Location_msginit, +}; + +static const upb_msglayout_field google_protobuf_SourceCodeInfo__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_SourceCodeInfo_msginit = { + &google_protobuf_SourceCodeInfo_submsgs[0], + &google_protobuf_SourceCodeInfo__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = { + {1, UPB_SIZE(20, 40), 0, 0, 5, _UPB_LABEL_PACKED}, + {2, UPB_SIZE(24, 48), 0, 0, 5, _UPB_LABEL_PACKED}, + {3, UPB_SIZE(4, 8), 1, 0, 12, 1}, + {4, UPB_SIZE(12, 24), 2, 0, 12, 1}, + {6, UPB_SIZE(28, 56), 0, 0, 12, 3}, +}; + +const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = { + NULL, + &google_protobuf_SourceCodeInfo_Location__fields[0], + UPB_SIZE(32, 64), 5, false, 255, +}; + +static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] = { + &google_protobuf_GeneratedCodeInfo_Annotation_msginit, +}; + +static const upb_msglayout_field google_protobuf_GeneratedCodeInfo__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = { + &google_protobuf_GeneratedCodeInfo_submsgs[0], + &google_protobuf_GeneratedCodeInfo__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = { + {1, UPB_SIZE(20, 32), 0, 0, 5, _UPB_LABEL_PACKED}, + {2, UPB_SIZE(12, 16), 1, 0, 12, 1}, + {3, UPB_SIZE(4, 4), 2, 0, 5, 1}, + {4, UPB_SIZE(8, 8), 3, 0, 5, 1}, +}; + +const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit = { + NULL, + &google_protobuf_GeneratedCodeInfo_Annotation__fields[0], + UPB_SIZE(24, 48), 4, false, 255, +}; + + + + +#include +#include +#include +#include +#include + + +/* Must be last. */ + +typedef struct { + size_t len; + char str[1]; /* Null-terminated string data follows. */ +} str_t; + +struct upb_fielddef { + const upb_filedef *file; + const upb_msgdef *msgdef; + const char *full_name; + const char *json_name; + union { + int64_t sint; + uint64_t uint; + double dbl; + float flt; + bool boolean; + str_t *str; + } defaultval; + const upb_oneofdef *oneof; + union { + const upb_msgdef *msgdef; + const upb_enumdef *enumdef; + const google_protobuf_FieldDescriptorProto *unresolved; + } sub; + uint32_t number_; + uint16_t index_; + uint16_t layout_index; + uint32_t selector_base; /* Used to index into a upb::Handlers table. */ + bool is_extension_; + bool lazy_; + bool packed_; + bool proto3_optional_; + upb_descriptortype_t type_; + upb_label_t label_; +}; + +struct upb_msgdef { + const upb_msglayout *layout; + const upb_filedef *file; + const char *full_name; + uint32_t selector_count; + uint32_t submsg_field_count; + + /* Tables for looking up fields by number and name. */ + upb_inttable itof; + upb_strtable ntof; + + const upb_fielddef *fields; + const upb_oneofdef *oneofs; + int field_count; + int oneof_count; + int real_oneof_count; + + /* Is this a map-entry message? */ + bool map_entry; + upb_wellknowntype_t well_known_type; + + /* TODO(haberman): proper extension ranges (there can be multiple). */ +}; + +struct upb_enumdef { + const upb_filedef *file; + const char *full_name; + upb_strtable ntoi; + upb_inttable iton; + int32_t defaultval; +}; + +struct upb_oneofdef { + const upb_msgdef *parent; + const char *full_name; + int field_count; + bool synthetic; + const upb_fielddef **fields; + upb_strtable ntof; + upb_inttable itof; +}; + +struct upb_filedef { + const char *name; + const char *package; + const char *phpprefix; + const char *phpnamespace; + + const upb_filedef **deps; + const upb_msgdef *msgs; + const upb_enumdef *enums; + const upb_fielddef *exts; + const upb_symtab *symtab; + + int dep_count; + int msg_count; + int enum_count; + int ext_count; + upb_syntax_t syntax; +}; + +struct upb_symtab { + upb_arena *arena; + upb_strtable syms; /* full_name -> packed def ptr */ + upb_strtable files; /* file_name -> upb_filedef* */ + size_t bytes_loaded; +}; + +/* Inside a symtab we store tagged pointers to specific def types. */ +typedef enum { + UPB_DEFTYPE_FIELD = 0, + + /* Only inside symtab table. */ + UPB_DEFTYPE_MSG = 1, + UPB_DEFTYPE_ENUM = 2, + + /* Only inside message table. */ + UPB_DEFTYPE_ONEOF = 1, + UPB_DEFTYPE_FIELD_JSONNAME = 2 +} upb_deftype_t; + +static const void *unpack_def(upb_value v, upb_deftype_t type) { + uintptr_t num = (uintptr_t)upb_value_getconstptr(v); + return (num & 3) == type ? (const void*)(num & ~3) : NULL; +} + +static upb_value pack_def(const void *ptr, upb_deftype_t type) { + uintptr_t num = (uintptr_t)ptr | type; + return upb_value_constptr((const void*)num); +} + +/* isalpha() etc. from are locale-dependent, which we don't want. */ +static bool upb_isbetween(char c, char low, char high) { + return c >= low && c <= high; +} + +static bool upb_isletter(char c) { + return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_'; +} + +static bool upb_isalphanum(char c) { + return upb_isletter(c) || upb_isbetween(c, '0', '9'); +} + +static const char *shortdefname(const char *fullname) { + const char *p; + + if (fullname == NULL) { + return NULL; + } else if ((p = strrchr(fullname, '.')) == NULL) { + /* No '.' in the name, return the full string. */ + return fullname; + } else { + /* Return one past the last '.'. */ + return p + 1; + } +} + +/* All submessage fields are lower than all other fields. + * Secondly, fields are increasing in order. */ +uint32_t field_rank(const upb_fielddef *f) { + uint32_t ret = upb_fielddef_number(f); + const uint32_t high_bit = 1 << 30; + UPB_ASSERT(ret < high_bit); + if (!upb_fielddef_issubmsg(f)) + ret |= high_bit; + return ret; +} + +int cmp_fields(const void *p1, const void *p2) { + const upb_fielddef *f1 = *(upb_fielddef*const*)p1; + const upb_fielddef *f2 = *(upb_fielddef*const*)p2; + return field_rank(f1) - field_rank(f2); +} + +/* A few implementation details of handlers. We put these here to avoid + * a def -> handlers dependency. */ + +#define UPB_STATIC_SELECTOR_COUNT 3 /* Warning: also in upb/handlers.h. */ + +static uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) { + return upb_fielddef_isseq(f) ? 2 : 0; +} + +static uint32_t upb_handlers_selectorcount(const upb_fielddef *f) { + uint32_t ret = 1; + if (upb_fielddef_isseq(f)) ret += 2; /* STARTSEQ/ENDSEQ */ + if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */ + if (upb_fielddef_issubmsg(f)) { + /* ENDSUBMSG (STARTSUBMSG is at table beginning) */ + ret += 0; + if (upb_fielddef_lazy(f)) { + /* STARTSTR/ENDSTR/STRING (for lazy) */ + ret += 3; + } + } + return ret; +} + +static void upb_status_setoom(upb_status *status) { + upb_status_seterrmsg(status, "out of memory"); +} + +static void assign_msg_wellknowntype(upb_msgdef *m) { + const char *name = upb_msgdef_fullname(m); + if (name == NULL) { + m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED; + return; + } + if (!strcmp(name, "google.protobuf.Any")) { + m->well_known_type = UPB_WELLKNOWN_ANY; + } else if (!strcmp(name, "google.protobuf.FieldMask")) { + m->well_known_type = UPB_WELLKNOWN_FIELDMASK; + } else if (!strcmp(name, "google.protobuf.Duration")) { + m->well_known_type = UPB_WELLKNOWN_DURATION; + } else if (!strcmp(name, "google.protobuf.Timestamp")) { + m->well_known_type = UPB_WELLKNOWN_TIMESTAMP; + } else if (!strcmp(name, "google.protobuf.DoubleValue")) { + m->well_known_type = UPB_WELLKNOWN_DOUBLEVALUE; + } else if (!strcmp(name, "google.protobuf.FloatValue")) { + m->well_known_type = UPB_WELLKNOWN_FLOATVALUE; + } else if (!strcmp(name, "google.protobuf.Int64Value")) { + m->well_known_type = UPB_WELLKNOWN_INT64VALUE; + } else if (!strcmp(name, "google.protobuf.UInt64Value")) { + m->well_known_type = UPB_WELLKNOWN_UINT64VALUE; + } else if (!strcmp(name, "google.protobuf.Int32Value")) { + m->well_known_type = UPB_WELLKNOWN_INT32VALUE; + } else if (!strcmp(name, "google.protobuf.UInt32Value")) { + m->well_known_type = UPB_WELLKNOWN_UINT32VALUE; + } else if (!strcmp(name, "google.protobuf.BoolValue")) { + m->well_known_type = UPB_WELLKNOWN_BOOLVALUE; + } else if (!strcmp(name, "google.protobuf.StringValue")) { + m->well_known_type = UPB_WELLKNOWN_STRINGVALUE; + } else if (!strcmp(name, "google.protobuf.BytesValue")) { + m->well_known_type = UPB_WELLKNOWN_BYTESVALUE; + } else if (!strcmp(name, "google.protobuf.Value")) { + m->well_known_type = UPB_WELLKNOWN_VALUE; + } else if (!strcmp(name, "google.protobuf.ListValue")) { + m->well_known_type = UPB_WELLKNOWN_LISTVALUE; + } else if (!strcmp(name, "google.protobuf.Struct")) { + m->well_known_type = UPB_WELLKNOWN_STRUCT; + } else { + m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED; + } +} + + +/* upb_enumdef ****************************************************************/ + +const char *upb_enumdef_fullname(const upb_enumdef *e) { + return e->full_name; +} + +const char *upb_enumdef_name(const upb_enumdef *e) { + return shortdefname(e->full_name); +} + +const upb_filedef *upb_enumdef_file(const upb_enumdef *e) { + return e->file; +} + +int32_t upb_enumdef_default(const upb_enumdef *e) { + UPB_ASSERT(upb_enumdef_iton(e, e->defaultval)); + return e->defaultval; +} + +int upb_enumdef_numvals(const upb_enumdef *e) { + return (int)upb_strtable_count(&e->ntoi); +} + +void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) { + /* We iterate over the ntoi table, to account for duplicate numbers. */ + upb_strtable_begin(i, &e->ntoi); +} + +void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); } +bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); } + +bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name, + size_t len, int32_t *num) { + upb_value v; + if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) { + return false; + } + if (num) *num = upb_value_getint32(v); + return true; +} + +const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) { + upb_value v; + return upb_inttable_lookup32(&def->iton, num, &v) ? + upb_value_getcstr(v) : NULL; +} + +const char *upb_enum_iter_name(upb_enum_iter *iter) { + return upb_strtable_iter_key(iter).data; +} + +int32_t upb_enum_iter_number(upb_enum_iter *iter) { + return upb_value_getint32(upb_strtable_iter_value(iter)); +} + + +/* upb_fielddef ***************************************************************/ + +const char *upb_fielddef_fullname(const upb_fielddef *f) { + return f->full_name; +} + +upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) { + switch (f->type_) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + return UPB_TYPE_DOUBLE; + case UPB_DESCRIPTOR_TYPE_FLOAT: + return UPB_TYPE_FLOAT; + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_SINT64: + case UPB_DESCRIPTOR_TYPE_SFIXED64: + return UPB_TYPE_INT64; + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + case UPB_DESCRIPTOR_TYPE_SINT32: + return UPB_TYPE_INT32; + case UPB_DESCRIPTOR_TYPE_UINT64: + case UPB_DESCRIPTOR_TYPE_FIXED64: + return UPB_TYPE_UINT64; + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_FIXED32: + return UPB_TYPE_UINT32; + case UPB_DESCRIPTOR_TYPE_ENUM: + return UPB_TYPE_ENUM; + case UPB_DESCRIPTOR_TYPE_BOOL: + return UPB_TYPE_BOOL; + case UPB_DESCRIPTOR_TYPE_STRING: + return UPB_TYPE_STRING; + case UPB_DESCRIPTOR_TYPE_BYTES: + return UPB_TYPE_BYTES; + case UPB_DESCRIPTOR_TYPE_GROUP: + case UPB_DESCRIPTOR_TYPE_MESSAGE: + return UPB_TYPE_MESSAGE; + } + UPB_UNREACHABLE(); +} + +upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) { + return f->type_; +} + +uint32_t upb_fielddef_index(const upb_fielddef *f) { + return f->index_; +} + +upb_label_t upb_fielddef_label(const upb_fielddef *f) { + return f->label_; +} + +uint32_t upb_fielddef_number(const upb_fielddef *f) { + return f->number_; +} + +bool upb_fielddef_isextension(const upb_fielddef *f) { + return f->is_extension_; +} + +bool upb_fielddef_lazy(const upb_fielddef *f) { + return f->lazy_; +} + +bool upb_fielddef_packed(const upb_fielddef *f) { + return f->packed_; +} + +const char *upb_fielddef_name(const upb_fielddef *f) { + return shortdefname(f->full_name); +} + +const char *upb_fielddef_jsonname(const upb_fielddef *f) { + return f->json_name; +} + +uint32_t upb_fielddef_selectorbase(const upb_fielddef *f) { + return f->selector_base; +} + +const upb_filedef *upb_fielddef_file(const upb_fielddef *f) { + return f->file; +} + +const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) { + return f->msgdef; +} + +const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) { + return f->oneof; +} + +const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f) { + if (!f->oneof || upb_oneofdef_issynthetic(f->oneof)) return NULL; + return f->oneof; +} + +upb_msgval upb_fielddef_default(const upb_fielddef *f) { + UPB_ASSERT(!upb_fielddef_issubmsg(f)); + upb_msgval ret; + if (upb_fielddef_isstring(f)) { + str_t *str = f->defaultval.str; + if (str) { + ret.str_val.data = str->str; + ret.str_val.size = str->len; + } else { + ret.str_val.size = 0; + } + } else { + memcpy(&ret, &f->defaultval, 8); + } + return ret; +} + +static void chkdefaulttype(const upb_fielddef *f, int ctype) { + UPB_UNUSED(f); + UPB_UNUSED(ctype); +} + +int64_t upb_fielddef_defaultint64(const upb_fielddef *f) { + chkdefaulttype(f, UPB_TYPE_INT64); + return f->defaultval.sint; +} + +int32_t upb_fielddef_defaultint32(const upb_fielddef *f) { + chkdefaulttype(f, UPB_TYPE_INT32); + return (int32_t)f->defaultval.sint; +} + +uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) { + chkdefaulttype(f, UPB_TYPE_UINT64); + return f->defaultval.uint; +} + +uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) { + chkdefaulttype(f, UPB_TYPE_UINT32); + return (uint32_t)f->defaultval.uint; +} + +bool upb_fielddef_defaultbool(const upb_fielddef *f) { + chkdefaulttype(f, UPB_TYPE_BOOL); + return f->defaultval.boolean; +} + +float upb_fielddef_defaultfloat(const upb_fielddef *f) { + chkdefaulttype(f, UPB_TYPE_FLOAT); + return f->defaultval.flt; +} + +double upb_fielddef_defaultdouble(const upb_fielddef *f) { + chkdefaulttype(f, UPB_TYPE_DOUBLE); + return f->defaultval.dbl; +} + +const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) { + str_t *str = f->defaultval.str; + UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_STRING || + upb_fielddef_type(f) == UPB_TYPE_BYTES || + upb_fielddef_type(f) == UPB_TYPE_ENUM); + if (str) { + if (len) *len = str->len; + return str->str; + } else { + if (len) *len = 0; + return NULL; + } +} + +const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) { + return upb_fielddef_type(f) == UPB_TYPE_MESSAGE ? f->sub.msgdef : NULL; +} + +const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) { + return upb_fielddef_type(f) == UPB_TYPE_ENUM ? f->sub.enumdef : NULL; +} + +const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f) { + return &f->msgdef->layout->fields[f->layout_index]; +} + +bool upb_fielddef_issubmsg(const upb_fielddef *f) { + return upb_fielddef_type(f) == UPB_TYPE_MESSAGE; +} + +bool upb_fielddef_isstring(const upb_fielddef *f) { + return upb_fielddef_type(f) == UPB_TYPE_STRING || + upb_fielddef_type(f) == UPB_TYPE_BYTES; +} + +bool upb_fielddef_isseq(const upb_fielddef *f) { + return upb_fielddef_label(f) == UPB_LABEL_REPEATED; +} + +bool upb_fielddef_isprimitive(const upb_fielddef *f) { + return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f); +} + +bool upb_fielddef_ismap(const upb_fielddef *f) { + return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) && + upb_msgdef_mapentry(upb_fielddef_msgsubdef(f)); +} + +bool upb_fielddef_hassubdef(const upb_fielddef *f) { + return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM; +} + +bool upb_fielddef_haspresence(const upb_fielddef *f) { + if (upb_fielddef_isseq(f)) return false; + return upb_fielddef_issubmsg(f) || upb_fielddef_containingoneof(f) || + f->file->syntax == UPB_SYNTAX_PROTO2; +} + +static bool between(int32_t x, int32_t low, int32_t high) { + return x >= low && x <= high; +} + +bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); } +bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); } +bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); } + +bool upb_fielddef_checkdescriptortype(int32_t type) { + return between(type, 1, 18); +} + +/* upb_msgdef *****************************************************************/ + +const char *upb_msgdef_fullname(const upb_msgdef *m) { + return m->full_name; +} + +const upb_filedef *upb_msgdef_file(const upb_msgdef *m) { + return m->file; +} + +const char *upb_msgdef_name(const upb_msgdef *m) { + return shortdefname(m->full_name); +} + +upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) { + return m->file->syntax; +} + +size_t upb_msgdef_selectorcount(const upb_msgdef *m) { + return m->selector_count; +} + +uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m) { + return m->submsg_field_count; +} + +const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) { + upb_value val; + return upb_inttable_lookup32(&m->itof, i, &val) ? + upb_value_getconstptr(val) : NULL; +} + +const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name, + size_t len) { + upb_value val; + + if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { + return NULL; + } + + return unpack_def(val, UPB_DEFTYPE_FIELD); +} + +const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, + size_t len) { + upb_value val; + + if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { + return NULL; + } + + return unpack_def(val, UPB_DEFTYPE_ONEOF); +} + +bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len, + const upb_fielddef **f, const upb_oneofdef **o) { + upb_value val; + + if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { + return false; + } + + *o = unpack_def(val, UPB_DEFTYPE_ONEOF); + *f = unpack_def(val, UPB_DEFTYPE_FIELD); + return *o || *f; /* False if this was a JSON name. */ +} + +const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m, + const char *name, size_t len) { + upb_value val; + const upb_fielddef* f; + + if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { + return NULL; + } + + f = unpack_def(val, UPB_DEFTYPE_FIELD); + if (!f) f = unpack_def(val, UPB_DEFTYPE_FIELD_JSONNAME); + + return f; +} + +int upb_msgdef_numfields(const upb_msgdef *m) { + return m->field_count; +} + +int upb_msgdef_numoneofs(const upb_msgdef *m) { + return m->oneof_count; +} + +int upb_msgdef_numrealoneofs(const upb_msgdef *m) { + return m->real_oneof_count; +} + +int upb_msgdef_fieldcount(const upb_msgdef *m) { + return m->field_count; +} + +int upb_msgdef_oneofcount(const upb_msgdef *m) { + return m->oneof_count; +} + +int upb_msgdef_realoneofcount(const upb_msgdef *m) { + return m->real_oneof_count; +} + +const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m) { + return m->layout; +} + +const upb_fielddef *upb_msgdef_field(const upb_msgdef *m, int i) { + UPB_ASSERT(i >= 0 && i < m->field_count); + return &m->fields[i]; +} + +const upb_oneofdef *upb_msgdef_oneof(const upb_msgdef *m, int i) { + UPB_ASSERT(i >= 0 && i < m->oneof_count); + return &m->oneofs[i]; +} + +bool upb_msgdef_mapentry(const upb_msgdef *m) { + return m->map_entry; +} + +upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m) { + return m->well_known_type; +} + +bool upb_msgdef_isnumberwrapper(const upb_msgdef *m) { + upb_wellknowntype_t type = upb_msgdef_wellknowntype(m); + return type >= UPB_WELLKNOWN_DOUBLEVALUE && + type <= UPB_WELLKNOWN_UINT32VALUE; +} + +bool upb_msgdef_iswrapper(const upb_msgdef *m) { + upb_wellknowntype_t type = upb_msgdef_wellknowntype(m); + return type >= UPB_WELLKNOWN_DOUBLEVALUE && + type <= UPB_WELLKNOWN_BOOLVALUE; +} + +void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) { + upb_inttable_begin(iter, &m->itof); +} + +void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); } + +bool upb_msg_field_done(const upb_msg_field_iter *iter) { + return upb_inttable_done(iter); +} + +upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) { + return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter)); +} + +void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) { + upb_inttable_iter_setdone(iter); +} + +bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1, + const upb_msg_field_iter * iter2) { + return upb_inttable_iter_isequal(iter1, iter2); +} + +void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) { + upb_strtable_begin(iter, &m->ntof); + /* We need to skip past any initial fields. */ + while (!upb_strtable_done(iter) && + !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF)) { + upb_strtable_next(iter); + } +} + +void upb_msg_oneof_next(upb_msg_oneof_iter *iter) { + /* We need to skip past fields to return only oneofs. */ + do { + upb_strtable_next(iter); + } while (!upb_strtable_done(iter) && + !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF)); +} + +bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) { + return upb_strtable_done(iter); +} + +const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) { + return unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF); +} + +void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) { + upb_strtable_iter_setdone(iter); +} + +bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1, + const upb_msg_oneof_iter *iter2) { + return upb_strtable_iter_isequal(iter1, iter2); +} + +/* upb_oneofdef ***************************************************************/ + +const char *upb_oneofdef_name(const upb_oneofdef *o) { + return shortdefname(o->full_name); +} + +const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) { + return o->parent; +} + +int upb_oneofdef_fieldcount(const upb_oneofdef *o) { + return o->field_count; +} + +const upb_fielddef *upb_oneofdef_field(const upb_oneofdef *o, int i) { + UPB_ASSERT(i < o->field_count); + return o->fields[i]; +} + +int upb_oneofdef_numfields(const upb_oneofdef *o) { + return o->field_count; +} + +uint32_t upb_oneofdef_index(const upb_oneofdef *o) { + return o - o->parent->oneofs; +} + +bool upb_oneofdef_issynthetic(const upb_oneofdef *o) { + return o->synthetic; +} + +const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, + const char *name, size_t length) { + upb_value val; + return upb_strtable_lookup2(&o->ntof, name, length, &val) ? + upb_value_getptr(val) : NULL; +} + +const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) { + upb_value val; + return upb_inttable_lookup32(&o->itof, num, &val) ? + upb_value_getptr(val) : NULL; +} + +void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) { + upb_inttable_begin(iter, &o->itof); +} + +void upb_oneof_next(upb_oneof_iter *iter) { + upb_inttable_next(iter); +} + +bool upb_oneof_done(upb_oneof_iter *iter) { + return upb_inttable_done(iter); +} + +upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) { + return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter)); +} + +void upb_oneof_iter_setdone(upb_oneof_iter *iter) { + upb_inttable_iter_setdone(iter); +} + +/* upb_filedef ****************************************************************/ + +const char *upb_filedef_name(const upb_filedef *f) { + return f->name; +} + +const char *upb_filedef_package(const upb_filedef *f) { + return f->package; +} + +const char *upb_filedef_phpprefix(const upb_filedef *f) { + return f->phpprefix; +} + +const char *upb_filedef_phpnamespace(const upb_filedef *f) { + return f->phpnamespace; +} + +upb_syntax_t upb_filedef_syntax(const upb_filedef *f) { + return f->syntax; +} + +int upb_filedef_msgcount(const upb_filedef *f) { + return f->msg_count; +} + +int upb_filedef_depcount(const upb_filedef *f) { + return f->dep_count; +} + +int upb_filedef_enumcount(const upb_filedef *f) { + return f->enum_count; +} + +const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i) { + return i < 0 || i >= f->dep_count ? NULL : f->deps[i]; +} + +const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i) { + return i < 0 || i >= f->msg_count ? NULL : &f->msgs[i]; +} + +const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i) { + return i < 0 || i >= f->enum_count ? NULL : &f->enums[i]; +} + +const upb_symtab *upb_filedef_symtab(const upb_filedef *f) { + return f->symtab; +} + +void upb_symtab_free(upb_symtab *s) { + upb_arena_free(s->arena); + upb_gfree(s); +} + +upb_symtab *upb_symtab_new(void) { + upb_symtab *s = upb_gmalloc(sizeof(*s)); + upb_alloc *alloc; + + if (!s) { + return NULL; + } + + s->arena = upb_arena_new(); + s->bytes_loaded = 0; + alloc = upb_arena_alloc(s->arena); + + if (!upb_strtable_init2(&s->syms, UPB_CTYPE_CONSTPTR, 32, alloc) || + !upb_strtable_init2(&s->files, UPB_CTYPE_CONSTPTR, 4, alloc)) { + upb_arena_free(s->arena); + upb_gfree(s); + s = NULL; + } + return s; +} + +const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) { + upb_value v; + return upb_strtable_lookup(&s->syms, sym, &v) ? + unpack_def(v, UPB_DEFTYPE_MSG) : NULL; +} + +const upb_msgdef *upb_symtab_lookupmsg2(const upb_symtab *s, const char *sym, + size_t len) { + upb_value v; + return upb_strtable_lookup2(&s->syms, sym, len, &v) ? + unpack_def(v, UPB_DEFTYPE_MSG) : NULL; +} + +const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) { + upb_value v; + return upb_strtable_lookup(&s->syms, sym, &v) ? + unpack_def(v, UPB_DEFTYPE_ENUM) : NULL; +} + +const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name) { + upb_value v; + return upb_strtable_lookup(&s->files, name, &v) ? upb_value_getconstptr(v) + : NULL; +} + +const upb_filedef *upb_symtab_lookupfile2( + const upb_symtab *s, const char *name, size_t len) { + upb_value v; + return upb_strtable_lookup2(&s->files, name, len, &v) ? + upb_value_getconstptr(v) : NULL; +} + +int upb_symtab_filecount(const upb_symtab *s) { + return (int)upb_strtable_count(&s->files); +} + +/* Code to build defs from descriptor protos. *********************************/ + +/* There is a question of how much validation to do here. It will be difficult + * to perfectly match the amount of validation performed by proto2. But since + * this code is used to directly build defs from Ruby (for example) we do need + * to validate important constraints like uniqueness of names and numbers. */ + +#define CHK_OOM(x) if (!(x)) { symtab_oomerr(ctx); } + +typedef struct { + upb_symtab *symtab; + upb_filedef *file; /* File we are building. */ + upb_arena *file_arena; /* Allocate defs here. */ + upb_alloc *alloc; /* Alloc of file_arena, for tables. */ + const upb_msglayout **layouts; /* NULL if we should build layouts. */ + upb_status *status; /* Record errors here. */ + jmp_buf err; /* longjmp() on error. */ +} symtab_addctx; + +UPB_NORETURN UPB_NOINLINE UPB_PRINTF(2, 3) +static void symtab_errf(symtab_addctx *ctx, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + upb_status_vseterrf(ctx->status, fmt, argp); + va_end(argp); + UPB_LONGJMP(ctx->err, 1); +} + +UPB_NORETURN UPB_NOINLINE +static void symtab_oomerr(symtab_addctx *ctx) { + upb_status_setoom(ctx->status); + UPB_LONGJMP(ctx->err, 1); +} + +void *symtab_alloc(symtab_addctx *ctx, size_t bytes) { + void *ret = upb_arena_malloc(ctx->file_arena, bytes); + if (!ret) symtab_oomerr(ctx); + return ret; +} + +static void check_ident(symtab_addctx *ctx, upb_strview name, bool full) { + const char *str = name.data; + size_t len = name.size; + bool start = true; + size_t i; + for (i = 0; i < len; i++) { + char c = str[i]; + if (c == '.') { + if (start || !full) { + symtab_errf(ctx, "invalid name: unexpected '.' (%.*s)", (int)len, str); + } + start = true; + } else if (start) { + if (!upb_isletter(c)) { + symtab_errf( + ctx, + "invalid name: path components must start with a letter (%.*s)", + (int)len, str); + } + start = false; + } else { + if (!upb_isalphanum(c)) { + symtab_errf(ctx, "invalid name: non-alphanumeric character (%.*s)", + (int)len, str); + } + } + } + if (start) { + symtab_errf(ctx, "invalid name: empty part (%.*s)", (int)len, str); + } +} + +static size_t div_round_up(size_t n, size_t d) { + return (n + d - 1) / d; +} + +static size_t upb_msgval_sizeof(upb_fieldtype_t type) { + switch (type) { + case UPB_TYPE_DOUBLE: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT64: + return 8; + case UPB_TYPE_ENUM: + case UPB_TYPE_INT32: + case UPB_TYPE_UINT32: + case UPB_TYPE_FLOAT: + return 4; + case UPB_TYPE_BOOL: + return 1; + case UPB_TYPE_MESSAGE: + return sizeof(void*); + case UPB_TYPE_BYTES: + case UPB_TYPE_STRING: + return sizeof(upb_strview); + } + UPB_UNREACHABLE(); +} + +static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) { + if (upb_msgdef_mapentry(upb_fielddef_containingtype(f))) { + upb_map_entry ent; + UPB_ASSERT(sizeof(ent.k) == sizeof(ent.v)); + return sizeof(ent.k); + } else if (upb_fielddef_isseq(f)) { + return sizeof(void*); + } else { + return upb_msgval_sizeof(upb_fielddef_type(f)); + } +} + +static uint32_t upb_msglayout_place(upb_msglayout *l, size_t size) { + uint32_t ret; + + l->size = UPB_ALIGN_UP(l->size, size); + ret = l->size; + l->size += size; + return ret; +} + +static int field_number_cmp(const void *p1, const void *p2) { + const upb_msglayout_field *f1 = p1; + const upb_msglayout_field *f2 = p2; + return f1->number - f2->number; +} + +static void assign_layout_indices(const upb_msgdef *m, upb_msglayout_field *fields) { + int i; + int n = upb_msgdef_numfields(m); + for (i = 0; i < n; i++) { + upb_fielddef *f = (upb_fielddef*)upb_msgdef_itof(m, fields[i].number); + UPB_ASSERT(f); + f->layout_index = i; + } +} + +/* This function is the dynamic equivalent of message_layout.{cc,h} in upbc. + * It computes a dynamic layout for all of the fields in |m|. */ +static void make_layout(symtab_addctx *ctx, const upb_msgdef *m) { + upb_msglayout *l = (upb_msglayout*)m->layout; + upb_msg_field_iter it; + upb_msg_oneof_iter oit; + size_t hasbit; + size_t submsg_count = m->submsg_field_count; + const upb_msglayout **submsgs; + upb_msglayout_field *fields; + + memset(l, 0, sizeof(*l) + sizeof(_upb_fasttable_entry)); + + fields = symtab_alloc(ctx, upb_msgdef_numfields(m) * sizeof(*fields)); + submsgs = symtab_alloc(ctx, submsg_count * sizeof(*submsgs)); + + l->field_count = upb_msgdef_numfields(m); + l->fields = fields; + l->submsgs = submsgs; + l->table_mask = 0; + + /* TODO(haberman): initialize fast tables so that reflection-based parsing + * can get the same speeds as linked-in types. */ + l->fasttable[0].field_parser = &fastdecode_generic; + l->fasttable[0].field_data = 0; + + if (upb_msgdef_mapentry(m)) { + /* TODO(haberman): refactor this method so this special case is more + * elegant. */ + const upb_fielddef *key = upb_msgdef_itof(m, 1); + const upb_fielddef *val = upb_msgdef_itof(m, 2); + fields[0].number = 1; + fields[1].number = 2; + fields[0].label = UPB_LABEL_OPTIONAL; + fields[1].label = UPB_LABEL_OPTIONAL; + fields[0].presence = 0; + fields[1].presence = 0; + fields[0].descriptortype = upb_fielddef_descriptortype(key); + fields[1].descriptortype = upb_fielddef_descriptortype(val); + fields[0].offset = 0; + fields[1].offset = sizeof(upb_strview); + fields[1].submsg_index = 0; + + if (upb_fielddef_type(val) == UPB_TYPE_MESSAGE) { + submsgs[0] = upb_fielddef_msgsubdef(val)->layout; + } + + l->field_count = 2; + l->size = 2 * sizeof(upb_strview); + l->size = UPB_ALIGN_UP(l->size, 8); + return; + } + + /* Allocate data offsets in three stages: + * + * 1. hasbits. + * 2. regular fields. + * 3. oneof fields. + * + * OPT: There is a lot of room for optimization here to minimize the size. + */ + + /* Allocate hasbits and set basic field attributes. */ + submsg_count = 0; + for (upb_msg_field_begin(&it, m), hasbit = 0; + !upb_msg_field_done(&it); + upb_msg_field_next(&it)) { + upb_fielddef* f = upb_msg_iter_field(&it); + upb_msglayout_field *field = &fields[upb_fielddef_index(f)]; + + field->number = upb_fielddef_number(f); + field->descriptortype = upb_fielddef_descriptortype(f); + field->label = upb_fielddef_label(f); + + if (field->descriptortype == UPB_DTYPE_STRING && + f->file->syntax == UPB_SYNTAX_PROTO2) { + /* See TableDescriptorType() in upbc/generator.cc for details and + * rationale. */ + field->descriptortype = UPB_DTYPE_BYTES; + } + + if (upb_fielddef_ismap(f)) { + field->label = _UPB_LABEL_MAP; + } else if (upb_fielddef_packed(f)) { + field->label = _UPB_LABEL_PACKED; + } + + if (upb_fielddef_issubmsg(f)) { + const upb_msgdef *subm = upb_fielddef_msgsubdef(f); + field->submsg_index = submsg_count++; + submsgs[field->submsg_index] = subm->layout; + } + + if (upb_fielddef_haspresence(f) && !upb_fielddef_realcontainingoneof(f)) { + /* We don't use hasbit 0, so that 0 can indicate "no presence" in the + * table. This wastes one hasbit, but we don't worry about it for now. */ + field->presence = ++hasbit; + } else { + field->presence = 0; + } + } + + /* Account for space used by hasbits. */ + l->size = div_round_up(hasbit, 8); + + /* Allocate non-oneof fields. */ + for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); + upb_msg_field_next(&it)) { + const upb_fielddef* f = upb_msg_iter_field(&it); + size_t field_size = upb_msg_fielddefsize(f); + size_t index = upb_fielddef_index(f); + + if (upb_fielddef_realcontainingoneof(f)) { + /* Oneofs are handled separately below. */ + continue; + } + + fields[index].offset = upb_msglayout_place(l, field_size); + } + + /* Allocate oneof fields. Each oneof field consists of a uint32 for the case + * and space for the actual data. */ + for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit); + upb_msg_oneof_next(&oit)) { + const upb_oneofdef* o = upb_msg_iter_oneof(&oit); + upb_oneof_iter fit; + + size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */ + size_t field_size = 0; + uint32_t case_offset; + uint32_t data_offset; + + if (upb_oneofdef_issynthetic(o)) continue; + + /* Calculate field size: the max of all field sizes. */ + for (upb_oneof_begin(&fit, o); + !upb_oneof_done(&fit); + upb_oneof_next(&fit)) { + const upb_fielddef* f = upb_oneof_iter_field(&fit); + field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f)); + } + + /* Align and allocate case offset. */ + case_offset = upb_msglayout_place(l, case_size); + data_offset = upb_msglayout_place(l, field_size); + + for (upb_oneof_begin(&fit, o); + !upb_oneof_done(&fit); + upb_oneof_next(&fit)) { + const upb_fielddef* f = upb_oneof_iter_field(&fit); + fields[upb_fielddef_index(f)].offset = data_offset; + fields[upb_fielddef_index(f)].presence = ~case_offset; + } + } + + /* Size of the entire structure should be a multiple of its greatest + * alignment. TODO: track overall alignment for real? */ + l->size = UPB_ALIGN_UP(l->size, 8); + + /* Sort fields by number. */ + qsort(fields, upb_msgdef_numfields(m), sizeof(*fields), field_number_cmp); + assign_layout_indices(m, fields); +} + +static void assign_msg_indices(symtab_addctx *ctx, upb_msgdef *m) { + /* Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the + * lowest indexes, but we do not publicly guarantee this. */ + upb_msg_field_iter j; + int i; + uint32_t selector; + int n = upb_msgdef_numfields(m); + upb_fielddef **fields; + + if (n == 0) { + m->selector_count = UPB_STATIC_SELECTOR_COUNT; + m->submsg_field_count = 0; + return; + } + + fields = upb_gmalloc(n * sizeof(*fields)); + + m->submsg_field_count = 0; + for(i = 0, upb_msg_field_begin(&j, m); + !upb_msg_field_done(&j); + upb_msg_field_next(&j), i++) { + upb_fielddef *f = upb_msg_iter_field(&j); + UPB_ASSERT(f->msgdef == m); + if (upb_fielddef_issubmsg(f)) { + m->submsg_field_count++; + } + fields[i] = f; + } + + qsort(fields, n, sizeof(*fields), cmp_fields); + + selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count; + for (i = 0; i < n; i++) { + upb_fielddef *f = fields[i]; + f->index_ = i; + f->selector_base = selector + upb_handlers_selectorbaseoffset(f); + selector += upb_handlers_selectorcount(f); + } + m->selector_count = selector; + + upb_gfree(fields); +} + +static char *strviewdup(symtab_addctx *ctx, upb_strview view) { + return upb_strdup2(view.data, view.size, ctx->alloc); +} + +static bool streql2(const char *a, size_t n, const char *b) { + return n == strlen(b) && memcmp(a, b, n) == 0; +} + +static bool streql_view(upb_strview view, const char *b) { + return streql2(view.data, view.size, b); +} + +static const char *makefullname(symtab_addctx *ctx, const char *prefix, + upb_strview name) { + if (prefix) { + /* ret = prefix + '.' + name; */ + size_t n = strlen(prefix); + char *ret = symtab_alloc(ctx, n + name.size + 2); + strcpy(ret, prefix); + ret[n] = '.'; + memcpy(&ret[n + 1], name.data, name.size); + ret[n + 1 + name.size] = '\0'; + return ret; + } else { + return strviewdup(ctx, name); + } +} + +static void finalize_oneofs(symtab_addctx *ctx, upb_msgdef *m) { + int i; + int synthetic_count = 0; + upb_oneofdef *mutable_oneofs = (upb_oneofdef*)m->oneofs; + + for (i = 0; i < m->oneof_count; i++) { + upb_oneofdef *o = &mutable_oneofs[i]; + + if (o->synthetic && o->field_count != 1) { + symtab_errf(ctx, "Synthetic oneofs must have one field, not %d: %s", + o->field_count, upb_oneofdef_name(o)); + } + + if (o->synthetic) { + synthetic_count++; + } else if (synthetic_count != 0) { + symtab_errf(ctx, "Synthetic oneofs must be after all other oneofs: %s", + upb_oneofdef_name(o)); + } + + o->fields = symtab_alloc(ctx, sizeof(upb_fielddef *) * o->field_count); + o->field_count = 0; + } + + for (i = 0; i < m->field_count; i++) { + const upb_fielddef *f = &m->fields[i]; + upb_oneofdef *o = (upb_oneofdef*)f->oneof; + if (o) { + o->fields[o->field_count++] = f; + } + } + + m->real_oneof_count = m->oneof_count - synthetic_count; +} + +size_t getjsonname(const char *name, char *buf, size_t len) { + size_t src, dst = 0; + bool ucase_next = false; + +#define WRITE(byte) \ + ++dst; \ + if (dst < len) buf[dst - 1] = byte; \ + else if (dst == len) buf[dst - 1] = '\0' + + if (!name) { + WRITE('\0'); + return 0; + } + + /* Implement the transformation as described in the spec: + * 1. upper case all letters after an underscore. + * 2. remove all underscores. + */ + for (src = 0; name[src]; src++) { + if (name[src] == '_') { + ucase_next = true; + continue; + } + + if (ucase_next) { + WRITE(toupper(name[src])); + ucase_next = false; + } else { + WRITE(name[src]); + } + } + + WRITE('\0'); + return dst; + +#undef WRITE +} + +static char* makejsonname(symtab_addctx *ctx, const char* name) { + size_t size = getjsonname(name, NULL, 0); + char* json_name = symtab_alloc(ctx, size); + getjsonname(name, json_name, size); + return json_name; +} + +static void symtab_add(symtab_addctx *ctx, const char *name, upb_value v) { + if (upb_strtable_lookup(&ctx->symtab->syms, name, NULL)) { + symtab_errf(ctx, "duplicate symbol '%s'", name); + } + upb_alloc *alloc = upb_arena_alloc(ctx->symtab->arena); + size_t len = strlen(name); + CHK_OOM(upb_strtable_insert3(&ctx->symtab->syms, name, len, v, alloc)); +} + +/* Given a symbol and the base symbol inside which it is defined, find the + * symbol's definition in t. */ +static const void *symtab_resolve(symtab_addctx *ctx, const upb_fielddef *f, + const char *base, upb_strview sym, + upb_deftype_t type) { + const upb_strtable *t = &ctx->symtab->syms; + if(sym.size == 0) goto notfound; + if(sym.data[0] == '.') { + /* Symbols starting with '.' are absolute, so we do a single lookup. + * Slice to omit the leading '.' */ + upb_value v; + if (!upb_strtable_lookup2(t, sym.data + 1, sym.size - 1, &v)) { + goto notfound; + } + + const void *ret = unpack_def(v, type); + if (!ret) { + symtab_errf(ctx, "type mismatch when resolving field %s, name %s", + f->full_name, sym.data); + } + return ret; + } else { + /* Remove components from base until we find an entry or run out. + * TODO: This branch is totally broken, but currently not used. */ + (void)base; + UPB_ASSERT(false); + goto notfound; + } + +notfound: + symtab_errf(ctx, "couldn't resolve name '%s'", sym.data); +} + +static void create_oneofdef( + symtab_addctx *ctx, upb_msgdef *m, + const google_protobuf_OneofDescriptorProto *oneof_proto) { + upb_oneofdef *o; + upb_strview name = google_protobuf_OneofDescriptorProto_name(oneof_proto); + upb_value v; + + o = (upb_oneofdef*)&m->oneofs[m->oneof_count++]; + o->parent = m; + o->full_name = makefullname(ctx, m->full_name, name); + o->field_count = 0; + o->synthetic = false; + + v = pack_def(o, UPB_DEFTYPE_ONEOF); + symtab_add(ctx, o->full_name, v); + CHK_OOM(upb_strtable_insert3(&m->ntof, name.data, name.size, v, ctx->alloc)); + + CHK_OOM(upb_inttable_init2(&o->itof, UPB_CTYPE_CONSTPTR, ctx->alloc)); + CHK_OOM(upb_strtable_init2(&o->ntof, UPB_CTYPE_CONSTPTR, 4, ctx->alloc)); +} + +static str_t *newstr(symtab_addctx *ctx, const char *data, size_t len) { + str_t *ret = symtab_alloc(ctx, sizeof(*ret) + len); + if (!ret) return NULL; + ret->len = len; + if (len) memcpy(ret->str, data, len); + ret->str[len] = '\0'; + return ret; +} + +static void parse_default(symtab_addctx *ctx, const char *str, size_t len, + upb_fielddef *f) { + char *end; + char nullz[64]; + errno = 0; + + switch (upb_fielddef_type(f)) { + case UPB_TYPE_INT32: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT32: + case UPB_TYPE_UINT64: + case UPB_TYPE_DOUBLE: + case UPB_TYPE_FLOAT: + /* Standard C number parsing functions expect null-terminated strings. */ + if (len >= sizeof(nullz) - 1) { + symtab_errf(ctx, "Default too long: %.*s", (int)len, str); + } + memcpy(nullz, str, len); + nullz[len] = '\0'; + str = nullz; + break; + default: + break; + } + + switch (upb_fielddef_type(f)) { + case UPB_TYPE_INT32: { + long val = strtol(str, &end, 0); + if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end) { + goto invalid; + } + f->defaultval.sint = val; + break; + } + case UPB_TYPE_ENUM: { + const upb_enumdef *e = f->sub.enumdef; + int32_t val; + if (!upb_enumdef_ntoi(e, str, len, &val)) { + goto invalid; + } + f->defaultval.sint = val; + break; + } + case UPB_TYPE_INT64: { + /* XXX: Need to write our own strtoll, since it's not available in c89. */ + int64_t val = strtol(str, &end, 0); + if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end) { + goto invalid; + } + f->defaultval.sint = val; + break; + } + case UPB_TYPE_UINT32: { + unsigned long val = strtoul(str, &end, 0); + if (val > UINT32_MAX || errno == ERANGE || *end) { + goto invalid; + } + f->defaultval.uint = val; + break; + } + case UPB_TYPE_UINT64: { + /* XXX: Need to write our own strtoull, since it's not available in c89. */ + uint64_t val = strtoul(str, &end, 0); + if (val > UINT64_MAX || errno == ERANGE || *end) { + goto invalid; + } + f->defaultval.uint = val; + break; + } + case UPB_TYPE_DOUBLE: { + double val = strtod(str, &end); + if (errno == ERANGE || *end) { + goto invalid; + } + f->defaultval.dbl = val; + break; + } + case UPB_TYPE_FLOAT: { + /* XXX: Need to write our own strtof, since it's not available in c89. */ + float val = strtod(str, &end); + if (errno == ERANGE || *end) { + goto invalid; + } + f->defaultval.flt = val; + break; + } + case UPB_TYPE_BOOL: { + if (streql2(str, len, "false")) { + f->defaultval.boolean = false; + } else if (streql2(str, len, "true")) { + f->defaultval.boolean = true; + } else { + } + break; + } + case UPB_TYPE_STRING: + f->defaultval.str = newstr(ctx, str, len); + break; + case UPB_TYPE_BYTES: + /* XXX: need to interpret the C-escaped value. */ + f->defaultval.str = newstr(ctx, str, len); + break; + case UPB_TYPE_MESSAGE: + /* Should not have a default value. */ + symtab_errf(ctx, "Message should not have a default (%s)", + upb_fielddef_fullname(f)); + } + + return; + +invalid: + symtab_errf(ctx, "Invalid default '%.*s' for field %s", (int)len, str, + upb_fielddef_fullname(f)); +} + +static void set_default_default(symtab_addctx *ctx, upb_fielddef *f) { + switch (upb_fielddef_type(f)) { + case UPB_TYPE_INT32: + case UPB_TYPE_INT64: + case UPB_TYPE_ENUM: + f->defaultval.sint = 0; + break; + case UPB_TYPE_UINT64: + case UPB_TYPE_UINT32: + f->defaultval.uint = 0; + break; + case UPB_TYPE_DOUBLE: + case UPB_TYPE_FLOAT: + f->defaultval.dbl = 0; + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + f->defaultval.str = newstr(ctx, NULL, 0); + break; + case UPB_TYPE_BOOL: + f->defaultval.boolean = false; + break; + case UPB_TYPE_MESSAGE: + break; + } +} + +static void create_fielddef( + symtab_addctx *ctx, const char *prefix, upb_msgdef *m, + const google_protobuf_FieldDescriptorProto *field_proto) { + upb_alloc *alloc = ctx->alloc; + upb_fielddef *f; + const google_protobuf_FieldOptions *options; + upb_strview name; + const char *full_name; + const char *json_name; + const char *shortname; + uint32_t field_number; + + if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) { + symtab_errf(ctx, "field has no name (%s)", upb_msgdef_fullname(m)); + } + + name = google_protobuf_FieldDescriptorProto_name(field_proto); + check_ident(ctx, name, false); + full_name = makefullname(ctx, prefix, name); + shortname = shortdefname(full_name); + + if (google_protobuf_FieldDescriptorProto_has_json_name(field_proto)) { + json_name = strviewdup( + ctx, google_protobuf_FieldDescriptorProto_json_name(field_proto)); + } else { + json_name = makejsonname(ctx, shortname); + } + + field_number = google_protobuf_FieldDescriptorProto_number(field_proto); + + if (field_number == 0 || field_number > UPB_MAX_FIELDNUMBER) { + symtab_errf(ctx, "invalid field number (%u)", field_number); + } + + if (m) { + /* direct message field. */ + upb_value v, field_v, json_v; + size_t json_size; + + f = (upb_fielddef*)&m->fields[m->field_count++]; + f->msgdef = m; + f->is_extension_ = false; + + if (upb_strtable_lookup(&m->ntof, shortname, NULL)) { + symtab_errf(ctx, "duplicate field name (%s)", shortname); + } + + if (upb_strtable_lookup(&m->ntof, json_name, NULL)) { + symtab_errf(ctx, "duplicate json_name (%s)", json_name); + } + + if (upb_inttable_lookup(&m->itof, field_number, NULL)) { + symtab_errf(ctx, "duplicate field number (%u)", field_number); + } + + field_v = pack_def(f, UPB_DEFTYPE_FIELD); + json_v = pack_def(f, UPB_DEFTYPE_FIELD_JSONNAME); + v = upb_value_constptr(f); + json_size = strlen(json_name); + + CHK_OOM( + upb_strtable_insert3(&m->ntof, name.data, name.size, field_v, alloc)); + CHK_OOM(upb_inttable_insert2(&m->itof, field_number, v, alloc)); + + if (strcmp(shortname, json_name) != 0) { + upb_strtable_insert3(&m->ntof, json_name, json_size, json_v, alloc); + } + + if (ctx->layouts) { + const upb_msglayout_field *fields = m->layout->fields; + int count = m->layout->field_count; + bool found = false; + int i; + for (i = 0; i < count; i++) { + if (fields[i].number == field_number) { + f->layout_index = i; + found = true; + break; + } + } + UPB_ASSERT(found); + } + } else { + /* extension field. */ + f = (upb_fielddef*)&ctx->file->exts[ctx->file->ext_count++]; + f->is_extension_ = true; + symtab_add(ctx, full_name, pack_def(f, UPB_DEFTYPE_FIELD)); + } + + f->full_name = full_name; + f->json_name = json_name; + f->file = ctx->file; + f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto); + f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto); + f->number_ = field_number; + f->oneof = NULL; + f->proto3_optional_ = + google_protobuf_FieldDescriptorProto_proto3_optional(field_proto); + + /* We can't resolve the subdef or (in the case of extensions) the containing + * message yet, because it may not have been defined yet. We stash a pointer + * to the field_proto until later when we can properly resolve it. */ + f->sub.unresolved = field_proto; + + if (f->label_ == UPB_LABEL_REQUIRED && f->file->syntax == UPB_SYNTAX_PROTO3) { + symtab_errf(ctx, "proto3 fields cannot be required (%s)", f->full_name); + } + + if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) { + int oneof_index = + google_protobuf_FieldDescriptorProto_oneof_index(field_proto); + upb_oneofdef *oneof; + upb_value v = upb_value_constptr(f); + + if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) { + symtab_errf(ctx, "fields in oneof must have OPTIONAL label (%s)", + f->full_name); + } + + if (!m) { + symtab_errf(ctx, "oneof_index provided for extension field (%s)", + f->full_name); + } + + if (oneof_index >= m->oneof_count) { + symtab_errf(ctx, "oneof_index out of range (%s)", f->full_name); + } + + oneof = (upb_oneofdef*)&m->oneofs[oneof_index]; + f->oneof = oneof; + + oneof->field_count++; + if (f->proto3_optional_) { + oneof->synthetic = true; + } + CHK_OOM(upb_inttable_insert2(&oneof->itof, f->number_, v, alloc)); + CHK_OOM(upb_strtable_insert3(&oneof->ntof, name.data, name.size, v, alloc)); + } else { + f->oneof = NULL; + if (f->proto3_optional_) { + symtab_errf(ctx, "field with proto3_optional was not in a oneof (%s)", + f->full_name); + } + } + + options = google_protobuf_FieldDescriptorProto_has_options(field_proto) ? + google_protobuf_FieldDescriptorProto_options(field_proto) : NULL; + + if (options && google_protobuf_FieldOptions_has_packed(options)) { + f->packed_ = google_protobuf_FieldOptions_packed(options); + } else { + /* Repeated fields default to packed for proto3 only. */ + f->packed_ = upb_fielddef_isprimitive(f) && + f->label_ == UPB_LABEL_REPEATED && f->file->syntax == UPB_SYNTAX_PROTO3; + } + + if (options) { + f->lazy_ = google_protobuf_FieldOptions_lazy(options); + } else { + f->lazy_ = false; + } +} + +static void create_enumdef( + symtab_addctx *ctx, const char *prefix, + const google_protobuf_EnumDescriptorProto *enum_proto) { + upb_enumdef *e; + const google_protobuf_EnumValueDescriptorProto *const *values; + upb_strview name; + size_t i, n; + + name = google_protobuf_EnumDescriptorProto_name(enum_proto); + check_ident(ctx, name, false); + + e = (upb_enumdef*)&ctx->file->enums[ctx->file->enum_count++]; + e->full_name = makefullname(ctx, prefix, name); + symtab_add(ctx, e->full_name, pack_def(e, UPB_DEFTYPE_ENUM)); + + values = google_protobuf_EnumDescriptorProto_value(enum_proto, &n); + CHK_OOM(upb_strtable_init2(&e->ntoi, UPB_CTYPE_INT32, n, ctx->alloc)); + CHK_OOM(upb_inttable_init2(&e->iton, UPB_CTYPE_CSTR, ctx->alloc)); + + e->file = ctx->file; + e->defaultval = 0; + + if (n == 0) { + symtab_errf(ctx, "enums must contain at least one value (%s)", + e->full_name); + } + + for (i = 0; i < n; i++) { + const google_protobuf_EnumValueDescriptorProto *value = values[i]; + upb_strview name = google_protobuf_EnumValueDescriptorProto_name(value); + char *name2 = strviewdup(ctx, name); + int32_t num = google_protobuf_EnumValueDescriptorProto_number(value); + upb_value v = upb_value_int32(num); + + if (i == 0 && e->file->syntax == UPB_SYNTAX_PROTO3 && num != 0) { + symtab_errf(ctx, "for proto3, the first enum value must be zero (%s)", + e->full_name); + } + + if (upb_strtable_lookup(&e->ntoi, name2, NULL)) { + symtab_errf(ctx, "duplicate enum label '%s'", name2); + } + + CHK_OOM(name2) + CHK_OOM( + upb_strtable_insert3(&e->ntoi, name2, strlen(name2), v, ctx->alloc)); + + if (!upb_inttable_lookup(&e->iton, num, NULL)) { + upb_value v = upb_value_cstr(name2); + CHK_OOM(upb_inttable_insert2(&e->iton, num, v, ctx->alloc)); + } + } + + upb_inttable_compact2(&e->iton, ctx->alloc); +} + +static void create_msgdef(symtab_addctx *ctx, const char *prefix, + const google_protobuf_DescriptorProto *msg_proto) { + upb_msgdef *m; + const google_protobuf_MessageOptions *options; + const google_protobuf_OneofDescriptorProto *const *oneofs; + const google_protobuf_FieldDescriptorProto *const *fields; + const google_protobuf_EnumDescriptorProto *const *enums; + const google_protobuf_DescriptorProto *const *msgs; + size_t i, n_oneof, n_field, n; + upb_strview name; + + name = google_protobuf_DescriptorProto_name(msg_proto); + check_ident(ctx, name, false); + + m = (upb_msgdef*)&ctx->file->msgs[ctx->file->msg_count++]; + m->full_name = makefullname(ctx, prefix, name); + symtab_add(ctx, m->full_name, pack_def(m, UPB_DEFTYPE_MSG)); + + oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n_oneof); + fields = google_protobuf_DescriptorProto_field(msg_proto, &n_field); + + CHK_OOM(upb_inttable_init2(&m->itof, UPB_CTYPE_CONSTPTR, ctx->alloc)); + CHK_OOM(upb_strtable_init2(&m->ntof, UPB_CTYPE_CONSTPTR, n_oneof + n_field, + ctx->alloc)); + + m->file = ctx->file; + m->map_entry = false; + + options = google_protobuf_DescriptorProto_options(msg_proto); + + if (options) { + m->map_entry = google_protobuf_MessageOptions_map_entry(options); + } + + if (ctx->layouts) { + m->layout = *ctx->layouts; + ctx->layouts++; + } else { + /* Allocate now (to allow cross-linking), populate later. */ + m->layout = symtab_alloc( + ctx, sizeof(*m->layout) + sizeof(_upb_fasttable_entry)); + } + + m->oneof_count = 0; + m->oneofs = symtab_alloc(ctx, sizeof(*m->oneofs) * n_oneof); + for (i = 0; i < n_oneof; i++) { + create_oneofdef(ctx, m, oneofs[i]); + } + + m->field_count = 0; + m->fields = symtab_alloc(ctx, sizeof(*m->fields) * n_field); + for (i = 0; i < n_field; i++) { + create_fielddef(ctx, m->full_name, m, fields[i]); + } + + assign_msg_indices(ctx, m); + finalize_oneofs(ctx, m); + assign_msg_wellknowntype(m); + upb_inttable_compact2(&m->itof, ctx->alloc); + + /* This message is built. Now build nested messages and enums. */ + + enums = google_protobuf_DescriptorProto_enum_type(msg_proto, &n); + for (i = 0; i < n; i++) { + create_enumdef(ctx, m->full_name, enums[i]); + } + + msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n); + for (i = 0; i < n; i++) { + create_msgdef(ctx, m->full_name, msgs[i]); + } +} + +static void count_types_in_msg(const google_protobuf_DescriptorProto *msg_proto, + upb_filedef *file) { + const google_protobuf_DescriptorProto *const *msgs; + size_t i, n; + + file->msg_count++; + + msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n); + for (i = 0; i < n; i++) { + count_types_in_msg(msgs[i], file); + } + + google_protobuf_DescriptorProto_enum_type(msg_proto, &n); + file->enum_count += n; + + google_protobuf_DescriptorProto_extension(msg_proto, &n); + file->ext_count += n; +} + +static void count_types_in_file( + const google_protobuf_FileDescriptorProto *file_proto, + upb_filedef *file) { + const google_protobuf_DescriptorProto *const *msgs; + size_t i, n; + + msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n); + for (i = 0; i < n; i++) { + count_types_in_msg(msgs[i], file); + } + + google_protobuf_FileDescriptorProto_enum_type(file_proto, &n); + file->enum_count += n; + + google_protobuf_FileDescriptorProto_extension(file_proto, &n); + file->ext_count += n; +} + +static void resolve_fielddef(symtab_addctx *ctx, const char *prefix, + upb_fielddef *f) { + upb_strview name; + const google_protobuf_FieldDescriptorProto *field_proto = f->sub.unresolved; + + if (f->is_extension_) { + if (!google_protobuf_FieldDescriptorProto_has_extendee(field_proto)) { + symtab_errf(ctx, "extension for field '%s' had no extendee", + f->full_name); + } + + name = google_protobuf_FieldDescriptorProto_extendee(field_proto); + f->msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG); + } + + if ((upb_fielddef_issubmsg(f) || f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) && + !google_protobuf_FieldDescriptorProto_has_type_name(field_proto)) { + symtab_errf(ctx, "field '%s' is missing type name", f->full_name); + } + + name = google_protobuf_FieldDescriptorProto_type_name(field_proto); + + if (upb_fielddef_issubmsg(f)) { + f->sub.msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG); + } else if (f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) { + f->sub.enumdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_ENUM); + } + + /* Have to delay resolving of the default value until now because of the enum + * case, since enum defaults are specified with a label. */ + if (google_protobuf_FieldDescriptorProto_has_default_value(field_proto)) { + upb_strview defaultval = + google_protobuf_FieldDescriptorProto_default_value(field_proto); + + if (f->file->syntax == UPB_SYNTAX_PROTO3) { + symtab_errf(ctx, "proto3 fields cannot have explicit defaults (%s)", + f->full_name); + } + + if (upb_fielddef_issubmsg(f)) { + symtab_errf(ctx, "message fields cannot have explicit defaults (%s)", + f->full_name); + } + + parse_default(ctx, defaultval.data, defaultval.size, f); + } else { + set_default_default(ctx, f); + } +} + +static void build_filedef( + symtab_addctx *ctx, upb_filedef *file, + const google_protobuf_FileDescriptorProto *file_proto) { + const google_protobuf_FileOptions *file_options_proto; + const google_protobuf_DescriptorProto *const *msgs; + const google_protobuf_EnumDescriptorProto *const *enums; + const google_protobuf_FieldDescriptorProto *const *exts; + const upb_strview* strs; + size_t i, n; + + count_types_in_file(file_proto, file); + + file->msgs = symtab_alloc(ctx, sizeof(*file->msgs) * file->msg_count); + file->enums = symtab_alloc(ctx, sizeof(*file->enums) * file->enum_count); + file->exts = symtab_alloc(ctx, sizeof(*file->exts) * file->ext_count); + + /* We increment these as defs are added. */ + file->msg_count = 0; + file->enum_count = 0; + file->ext_count = 0; + + if (!google_protobuf_FileDescriptorProto_has_name(file_proto)) { + symtab_errf(ctx, "File has no name"); + } + + file->name = + strviewdup(ctx, google_protobuf_FileDescriptorProto_name(file_proto)); + file->phpprefix = NULL; + file->phpnamespace = NULL; + + if (google_protobuf_FileDescriptorProto_has_package(file_proto)) { + upb_strview package = + google_protobuf_FileDescriptorProto_package(file_proto); + check_ident(ctx, package, true); + file->package = strviewdup(ctx, package); + } else { + file->package = NULL; + } + + if (google_protobuf_FileDescriptorProto_has_syntax(file_proto)) { + upb_strview syntax = + google_protobuf_FileDescriptorProto_syntax(file_proto); + + if (streql_view(syntax, "proto2")) { + file->syntax = UPB_SYNTAX_PROTO2; + } else if (streql_view(syntax, "proto3")) { + file->syntax = UPB_SYNTAX_PROTO3; + } else { + symtab_errf(ctx, "Invalid syntax '" UPB_STRVIEW_FORMAT "'", + UPB_STRVIEW_ARGS(syntax)); + } + } else { + file->syntax = UPB_SYNTAX_PROTO2; + } + + /* Read options. */ + file_options_proto = google_protobuf_FileDescriptorProto_options(file_proto); + if (file_options_proto) { + if (google_protobuf_FileOptions_has_php_class_prefix(file_options_proto)) { + file->phpprefix = strviewdup( + ctx, + google_protobuf_FileOptions_php_class_prefix(file_options_proto)); + } + if (google_protobuf_FileOptions_has_php_namespace(file_options_proto)) { + file->phpnamespace = strviewdup( + ctx, google_protobuf_FileOptions_php_namespace(file_options_proto)); + } + } + + /* Verify dependencies. */ + strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n); + file->deps = symtab_alloc(ctx, sizeof(*file->deps) * n); + + for (i = 0; i < n; i++) { + upb_strview dep_name = strs[i]; + upb_value v; + if (!upb_strtable_lookup2(&ctx->symtab->files, dep_name.data, + dep_name.size, &v)) { + symtab_errf(ctx, + "Depends on file '" UPB_STRVIEW_FORMAT + "', but it has not been loaded", + UPB_STRVIEW_ARGS(dep_name)); + } + file->deps[i] = upb_value_getconstptr(v); + } + + /* Create messages. */ + msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n); + for (i = 0; i < n; i++) { + create_msgdef(ctx, file->package, msgs[i]); + } + + /* Create enums. */ + enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n); + for (i = 0; i < n; i++) { + create_enumdef(ctx, file->package, enums[i]); + } + + /* Create extensions. */ + exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n); + file->exts = symtab_alloc(ctx, sizeof(*file->exts) * n); + for (i = 0; i < n; i++) { + create_fielddef(ctx, file->package, NULL, exts[i]); + } + + /* Now that all names are in the table, build layouts and resolve refs. */ + for (i = 0; i < (size_t)file->ext_count; i++) { + resolve_fielddef(ctx, file->package, (upb_fielddef*)&file->exts[i]); + } + + for (i = 0; i < (size_t)file->msg_count; i++) { + const upb_msgdef *m = &file->msgs[i]; + int j; + for (j = 0; j < m->field_count; j++) { + resolve_fielddef(ctx, m->full_name, (upb_fielddef*)&m->fields[j]); + } + } + + if (!ctx->layouts) { + for (i = 0; i < (size_t)file->msg_count; i++) { + const upb_msgdef *m = &file->msgs[i]; + make_layout(ctx, m); + } + } +} + +static void remove_filedef(upb_symtab *s, upb_filedef *file) { + upb_alloc *alloc = upb_arena_alloc(s->arena); + int i; + for (i = 0; i < file->msg_count; i++) { + const char *name = file->msgs[i].full_name; + upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc); + } + for (i = 0; i < file->enum_count; i++) { + const char *name = file->enums[i].full_name; + upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc); + } + for (i = 0; i < file->ext_count; i++) { + const char *name = file->exts[i].full_name; + upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc); + } +} + +static const upb_filedef *_upb_symtab_addfile( + upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto, + const upb_msglayout **layouts, upb_status *status) { + upb_arena *file_arena = upb_arena_new(); + upb_filedef *file; + symtab_addctx ctx; + + if (!file_arena) return NULL; + + file = upb_arena_malloc(file_arena, sizeof(*file)); + if (!file) goto done; + + ctx.file = file; + ctx.symtab = s; + ctx.file_arena = file_arena; + ctx.alloc = upb_arena_alloc(file_arena); + ctx.layouts = layouts; + ctx.status = status; + + file->msg_count = 0; + file->enum_count = 0; + file->ext_count = 0; + file->symtab = s; + + if (UPB_UNLIKELY(UPB_SETJMP(ctx.err))) { + UPB_ASSERT(!upb_ok(status)); + remove_filedef(s, file); + file = NULL; + } else { + build_filedef(&ctx, file, file_proto); + upb_strtable_insert3(&s->files, file->name, strlen(file->name), + upb_value_constptr(file), ctx.alloc); + UPB_ASSERT(upb_ok(status)); + upb_arena_fuse(s->arena, file_arena); + } + +done: + upb_arena_free(file_arena); + return file; +} + +const upb_filedef *upb_symtab_addfile( + upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto, + upb_status *status) { + return _upb_symtab_addfile(s, file_proto, NULL, status); +} + +/* Include here since we want most of this file to be stdio-free. */ +#include + +bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) { + /* Since this function should never fail (it would indicate a bug in upb) we + * print errors to stderr instead of returning error status to the user. */ + upb_def_init **deps = init->deps; + google_protobuf_FileDescriptorProto *file; + upb_arena *arena; + upb_status status; + + upb_status_clear(&status); + + if (upb_strtable_lookup(&s->files, init->filename, NULL)) { + return true; + } + + arena = upb_arena_new(); + + for (; *deps; deps++) { + if (!_upb_symtab_loaddefinit(s, *deps)) goto err; + } + + file = google_protobuf_FileDescriptorProto_parse_ex( + init->descriptor.data, init->descriptor.size, arena, UPB_DECODE_ALIAS); + s->bytes_loaded += init->descriptor.size; + + if (!file) { + upb_status_seterrf( + &status, + "Failed to parse compiled-in descriptor for file '%s'. This should " + "never happen.", + init->filename); + goto err; + } + + if (!_upb_symtab_addfile(s, file, init->layouts, &status)) goto err; + + upb_arena_free(arena); + return true; + +err: + fprintf(stderr, "Error loading compiled-in descriptor: %s\n", + upb_status_errmsg(&status)); + upb_arena_free(arena); + return false; +} + +size_t _upb_symtab_bytesloaded(const upb_symtab *s) { + return s->bytes_loaded; +} + +upb_arena *_upb_symtab_arena(const upb_symtab *s) { + return s->arena; +} + +#undef CHK_OOM + + +#include + + +static size_t get_field_size(const upb_msglayout_field *f) { + static unsigned char sizes[] = { + 0,/* 0 */ + 8, /* UPB_DESCRIPTOR_TYPE_DOUBLE */ + 4, /* UPB_DESCRIPTOR_TYPE_FLOAT */ + 8, /* UPB_DESCRIPTOR_TYPE_INT64 */ + 8, /* UPB_DESCRIPTOR_TYPE_UINT64 */ + 4, /* UPB_DESCRIPTOR_TYPE_INT32 */ + 8, /* UPB_DESCRIPTOR_TYPE_FIXED64 */ + 4, /* UPB_DESCRIPTOR_TYPE_FIXED32 */ + 1, /* UPB_DESCRIPTOR_TYPE_BOOL */ + sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_STRING */ + sizeof(void*), /* UPB_DESCRIPTOR_TYPE_GROUP */ + sizeof(void*), /* UPB_DESCRIPTOR_TYPE_MESSAGE */ + sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_BYTES */ + 4, /* UPB_DESCRIPTOR_TYPE_UINT32 */ + 4, /* UPB_DESCRIPTOR_TYPE_ENUM */ + 4, /* UPB_DESCRIPTOR_TYPE_SFIXED32 */ + 8, /* UPB_DESCRIPTOR_TYPE_SFIXED64 */ + 4, /* UPB_DESCRIPTOR_TYPE_SINT32 */ + 8, /* UPB_DESCRIPTOR_TYPE_SINT64 */ + }; + return _upb_repeated_or_map(f) ? sizeof(void *) : sizes[f->descriptortype]; +} + +/* Strings/bytes are special-cased in maps. */ +static char _upb_fieldtype_to_mapsize[12] = { + 0, + 1, /* UPB_TYPE_BOOL */ + 4, /* UPB_TYPE_FLOAT */ + 4, /* UPB_TYPE_INT32 */ + 4, /* UPB_TYPE_UINT32 */ + 4, /* UPB_TYPE_ENUM */ + sizeof(void*), /* UPB_TYPE_MESSAGE */ + 8, /* UPB_TYPE_DOUBLE */ + 8, /* UPB_TYPE_INT64 */ + 8, /* UPB_TYPE_UINT64 */ + 0, /* UPB_TYPE_STRING */ + 0, /* UPB_TYPE_BYTES */ +}; + +static const char _upb_fieldtype_to_sizelg2[12] = { + 0, + 0, /* UPB_TYPE_BOOL */ + 2, /* UPB_TYPE_FLOAT */ + 2, /* UPB_TYPE_INT32 */ + 2, /* UPB_TYPE_UINT32 */ + 2, /* UPB_TYPE_ENUM */ + UPB_SIZE(2, 3), /* UPB_TYPE_MESSAGE */ + 3, /* UPB_TYPE_DOUBLE */ + 3, /* UPB_TYPE_INT64 */ + 3, /* UPB_TYPE_UINT64 */ + UPB_SIZE(3, 4), /* UPB_TYPE_STRING */ + UPB_SIZE(3, 4), /* UPB_TYPE_BYTES */ +}; + +/** upb_msg *******************************************************************/ + +upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a) { + return _upb_msg_new(upb_msgdef_layout(m), a); +} + +static bool in_oneof(const upb_msglayout_field *field) { + return field->presence < 0; +} + +static upb_msgval _upb_msg_getraw(const upb_msg *msg, const upb_fielddef *f) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + const char *mem = UPB_PTR_AT(msg, field->offset, char); + upb_msgval val = {0}; + memcpy(&val, mem, get_field_size(field)); + return val; +} + +bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + if (in_oneof(field)) { + return _upb_getoneofcase_field(msg, field) == field->number; + } else if (field->presence > 0) { + return _upb_hasbit_field(msg, field); + } else { + UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE || + field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP); + return _upb_msg_getraw(msg, f).msg_val != NULL; + } +} + +const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg, + const upb_oneofdef *o) { + const upb_fielddef *f = upb_oneofdef_field(o, 0); + if (upb_oneofdef_issynthetic(o)) { + UPB_ASSERT(upb_oneofdef_fieldcount(o) == 1); + return upb_msg_has(msg, f) ? f : NULL; + } else { + const upb_msglayout_field *field = upb_fielddef_layout(f); + uint32_t oneof_case = _upb_getoneofcase_field(msg, field); + f = oneof_case ? upb_oneofdef_itof(o, oneof_case) : NULL; + UPB_ASSERT((f != NULL) == (oneof_case != 0)); + return f; + } +} + +upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f) { + if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) { + return _upb_msg_getraw(msg, f); + } else { + /* TODO(haberman): change upb_fielddef to not require this switch(). */ + upb_msgval val = {0}; + switch (upb_fielddef_type(f)) { + case UPB_TYPE_INT32: + case UPB_TYPE_ENUM: + val.int32_val = upb_fielddef_defaultint32(f); + break; + case UPB_TYPE_INT64: + val.int64_val = upb_fielddef_defaultint64(f); + break; + case UPB_TYPE_UINT32: + val.uint32_val = upb_fielddef_defaultuint32(f); + break; + case UPB_TYPE_UINT64: + val.uint64_val = upb_fielddef_defaultuint64(f); + break; + case UPB_TYPE_FLOAT: + val.float_val = upb_fielddef_defaultfloat(f); + break; + case UPB_TYPE_DOUBLE: + val.double_val = upb_fielddef_defaultdouble(f); + break; + case UPB_TYPE_BOOL: + val.bool_val = upb_fielddef_defaultbool(f); + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + val.str_val.data = upb_fielddef_defaultstr(f, &val.str_val.size); + break; + case UPB_TYPE_MESSAGE: + val.msg_val = NULL; + break; + } + return val; + } +} + +upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, + upb_arena *a) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + upb_mutmsgval ret; + char *mem = UPB_PTR_AT(msg, field->offset, char); + bool wrong_oneof = + in_oneof(field) && _upb_getoneofcase_field(msg, field) != field->number; + + memcpy(&ret, mem, sizeof(void*)); + + if (a && (!ret.msg || wrong_oneof)) { + if (upb_fielddef_ismap(f)) { + const upb_msgdef *entry = upb_fielddef_msgsubdef(f); + const upb_fielddef *key = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY); + const upb_fielddef *value = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE); + ret.map = upb_map_new(a, upb_fielddef_type(key), upb_fielddef_type(value)); + } else if (upb_fielddef_isseq(f)) { + ret.array = upb_array_new(a, upb_fielddef_type(f)); + } else { + UPB_ASSERT(upb_fielddef_issubmsg(f)); + ret.msg = upb_msg_new(upb_fielddef_msgsubdef(f), a); + } + + memcpy(mem, &ret, sizeof(void*)); + + if (wrong_oneof) { + *_upb_oneofcase_field(msg, field) = field->number; + } else if (field->presence > 0) { + _upb_sethas_field(msg, field); + } + } + return ret; +} + +void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val, + upb_arena *a) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + char *mem = UPB_PTR_AT(msg, field->offset, char); + UPB_UNUSED(a); /* We reserve the right to make set insert into a map. */ + memcpy(mem, &val, get_field_size(field)); + if (field->presence > 0) { + _upb_sethas_field(msg, field); + } else if (in_oneof(field)) { + *_upb_oneofcase_field(msg, field) = field->number; + } +} + +void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + char *mem = UPB_PTR_AT(msg, field->offset, char); + + if (field->presence > 0) { + _upb_clearhas_field(msg, field); + } else if (in_oneof(field)) { + uint32_t *oneof_case = _upb_oneofcase_field(msg, field); + if (*oneof_case != field->number) return; + *oneof_case = 0; + } + + memset(mem, 0, get_field_size(field)); +} + +void upb_msg_clear(upb_msg *msg, const upb_msgdef *m) { + _upb_msg_clear(msg, upb_msgdef_layout(m)); +} + +bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m, + const upb_symtab *ext_pool, const upb_fielddef **out_f, + upb_msgval *out_val, size_t *iter) { + int i = *iter; + int n = upb_msgdef_fieldcount(m); + const upb_msgval zero = {0}; + UPB_UNUSED(ext_pool); + while (++i < n) { + const upb_fielddef *f = upb_msgdef_field(m, i); + upb_msgval val = _upb_msg_getraw(msg, f); + + /* Skip field if unset or empty. */ + if (upb_fielddef_haspresence(f)) { + if (!upb_msg_has(msg, f)) continue; + } else { + upb_msgval test = val; + if (upb_fielddef_isstring(f) && !upb_fielddef_isseq(f)) { + /* Clear string pointer, only size matters (ptr could be non-NULL). */ + test.str_val.data = NULL; + } + /* Continue if NULL or 0. */ + if (memcmp(&test, &zero, sizeof(test)) == 0) continue; + + /* Continue on empty array or map. */ + if (upb_fielddef_ismap(f)) { + if (upb_map_size(test.map_val) == 0) continue; + } else if (upb_fielddef_isseq(f)) { + if (upb_array_size(test.array_val) == 0) continue; + } + } + + *out_val = val; + *out_f = f; + *iter = i; + return true; + } + *iter = i; + return false; +} + +bool _upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int depth) { + size_t iter = UPB_MSG_BEGIN; + const upb_fielddef *f; + upb_msgval val; + bool ret = true; + + if (--depth == 0) return false; + + _upb_msg_discardunknown_shallow(msg); + + while (upb_msg_next(msg, m, NULL /*ext_pool*/, &f, &val, &iter)) { + const upb_msgdef *subm = upb_fielddef_msgsubdef(f); + if (!subm) continue; + if (upb_fielddef_ismap(f)) { + const upb_fielddef *val_f = upb_msgdef_itof(subm, 2); + const upb_msgdef *val_m = upb_fielddef_msgsubdef(val_f); + upb_map *map = (upb_map*)val.map_val; + size_t iter = UPB_MAP_BEGIN; + + if (!val_m) continue; + + while (upb_mapiter_next(map, &iter)) { + upb_msgval map_val = upb_mapiter_value(map, iter); + if (!_upb_msg_discardunknown((upb_msg*)map_val.msg_val, val_m, depth)) { + ret = false; + } + } + } else if (upb_fielddef_isseq(f)) { + const upb_array *arr = val.array_val; + size_t i, n = upb_array_size(arr); + for (i = 0; i < n; i++) { + upb_msgval elem = upb_array_get(arr, i); + if (!_upb_msg_discardunknown((upb_msg*)elem.msg_val, subm, depth)) { + ret = false; + } + } + } else { + if (!_upb_msg_discardunknown((upb_msg*)val.msg_val, subm, depth)) { + ret = false; + } + } + } + + return ret; +} + +bool upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int maxdepth) { + return _upb_msg_discardunknown(msg, m, maxdepth); +} + +/** upb_array *****************************************************************/ + +upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type) { + return _upb_array_new(a, 4, _upb_fieldtype_to_sizelg2[type]); +} + +size_t upb_array_size(const upb_array *arr) { + return arr->len; +} + +upb_msgval upb_array_get(const upb_array *arr, size_t i) { + upb_msgval ret; + const char* data = _upb_array_constptr(arr); + int lg2 = arr->data & 7; + UPB_ASSERT(i < arr->len); + memcpy(&ret, data + (i << lg2), 1 << lg2); + return ret; +} + +void upb_array_set(upb_array *arr, size_t i, upb_msgval val) { + char* data = _upb_array_ptr(arr); + int lg2 = arr->data & 7; + UPB_ASSERT(i < arr->len); + memcpy(data + (i << lg2), &val, 1 << lg2); +} + +bool upb_array_append(upb_array *arr, upb_msgval val, upb_arena *arena) { + if (!_upb_array_realloc(arr, arr->len + 1, arena)) { + return false; + } + arr->len++; + upb_array_set(arr, arr->len - 1, val); + return true; +} + +bool upb_array_resize(upb_array *arr, size_t size, upb_arena *arena) { + return _upb_array_resize(arr, size, arena); +} + +/** upb_map *******************************************************************/ + +upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type, + upb_fieldtype_t value_type) { + return _upb_map_new(a, _upb_fieldtype_to_mapsize[key_type], + _upb_fieldtype_to_mapsize[value_type]); +} + +size_t upb_map_size(const upb_map *map) { + return _upb_map_size(map); +} + +bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) { + return _upb_map_get(map, &key, map->key_size, val, map->val_size); +} + +void upb_map_clear(upb_map *map) { + _upb_map_clear(map); +} + +bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, + upb_arena *arena) { + return _upb_map_set(map, &key, map->key_size, &val, map->val_size, arena); +} + +bool upb_map_delete(upb_map *map, upb_msgval key) { + return _upb_map_delete(map, &key, map->key_size); +} + +bool upb_mapiter_next(const upb_map *map, size_t *iter) { + return _upb_map_next(map, iter); +} + +bool upb_mapiter_done(const upb_map *map, size_t iter) { + upb_strtable_iter i; + UPB_ASSERT(iter != UPB_MAP_BEGIN); + i.t = &map->table; + i.index = iter; + return upb_strtable_done(&i); +} + +/* Returns the key and value for this entry of the map. */ +upb_msgval upb_mapiter_key(const upb_map *map, size_t iter) { + upb_strtable_iter i; + upb_msgval ret; + i.t = &map->table; + i.index = iter; + _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size); + return ret; +} + +upb_msgval upb_mapiter_value(const upb_map *map, size_t iter) { + upb_strtable_iter i; + upb_msgval ret; + i.t = &map->table; + i.index = iter; + _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size); + return ret; +} + +/* void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Special header, must be included last. */ + +typedef struct { + const char *ptr, *end; + upb_arena *arena; /* TODO: should we have a tmp arena for tmp data? */ + const upb_symtab *any_pool; + int depth; + upb_status *status; + jmp_buf err; + int line; + const char *line_begin; + bool is_first; + int options; + const upb_fielddef *debug_field; +} jsondec; + +enum { JD_OBJECT, JD_ARRAY, JD_STRING, JD_NUMBER, JD_TRUE, JD_FALSE, JD_NULL }; + +/* Forward declarations of mutually-recursive functions. */ +static void jsondec_wellknown(jsondec *d, upb_msg *msg, const upb_msgdef *m); +static upb_msgval jsondec_value(jsondec *d, const upb_fielddef *f); +static void jsondec_wellknownvalue(jsondec *d, upb_msg *msg, + const upb_msgdef *m); +static void jsondec_object(jsondec *d, upb_msg *msg, const upb_msgdef *m); + +static bool jsondec_streql(upb_strview str, const char *lit) { + return str.size == strlen(lit) && memcmp(str.data, lit, str.size) == 0; +} + +static bool jsondec_isnullvalue(const upb_fielddef *f) { + return upb_fielddef_type(f) == UPB_TYPE_ENUM && + strcmp(upb_enumdef_fullname(upb_fielddef_enumsubdef(f)), + "google.protobuf.NullValue") == 0; +} + +static bool jsondec_isvalue(const upb_fielddef *f) { + return (upb_fielddef_type(f) == UPB_TYPE_MESSAGE && + upb_msgdef_wellknowntype(upb_fielddef_msgsubdef(f)) == + UPB_WELLKNOWN_VALUE) || + jsondec_isnullvalue(f); +} + +UPB_NORETURN static void jsondec_err(jsondec *d, const char *msg) { + upb_status_seterrf(d->status, "Error parsing JSON @%d:%d: %s", d->line, + (int)(d->ptr - d->line_begin), msg); + UPB_LONGJMP(d->err, 1); +} + +UPB_PRINTF(2, 3) +UPB_NORETURN static void jsondec_errf(jsondec *d, const char *fmt, ...) { + va_list argp; + upb_status_seterrf(d->status, "Error parsing JSON @%d:%d: ", d->line, + (int)(d->ptr - d->line_begin)); + va_start(argp, fmt); + upb_status_vappenderrf(d->status, fmt, argp); + va_end(argp); + UPB_LONGJMP(d->err, 1); +} + +static void jsondec_skipws(jsondec *d) { + while (d->ptr != d->end) { + switch (*d->ptr) { + case '\n': + d->line++; + d->line_begin = d->ptr; + /* Fallthrough. */ + case '\r': + case '\t': + case ' ': + d->ptr++; + break; + default: + return; + } + } + jsondec_err(d, "Unexpected EOF"); +} + +static bool jsondec_tryparsech(jsondec *d, char ch) { + if (d->ptr == d->end || *d->ptr != ch) return false; + d->ptr++; + return true; +} + +static void jsondec_parselit(jsondec *d, const char *lit) { + size_t avail = d->end - d->ptr; + size_t len = strlen(lit); + if (avail < len || memcmp(d->ptr, lit, len) != 0) { + jsondec_errf(d, "Expected: '%s'", lit); + } + d->ptr += len; +} + +static void jsondec_wsch(jsondec *d, char ch) { + jsondec_skipws(d); + if (!jsondec_tryparsech(d, ch)) { + jsondec_errf(d, "Expected: '%c'", ch); + } +} + +static void jsondec_true(jsondec *d) { jsondec_parselit(d, "true"); } +static void jsondec_false(jsondec *d) { jsondec_parselit(d, "false"); } +static void jsondec_null(jsondec *d) { jsondec_parselit(d, "null"); } + +static void jsondec_entrysep(jsondec *d) { + jsondec_skipws(d); + jsondec_parselit(d, ":"); +} + +static int jsondec_rawpeek(jsondec *d) { + switch (*d->ptr) { + case '{': + return JD_OBJECT; + case '[': + return JD_ARRAY; + case '"': + return JD_STRING; + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return JD_NUMBER; + case 't': + return JD_TRUE; + case 'f': + return JD_FALSE; + case 'n': + return JD_NULL; + default: + jsondec_errf(d, "Unexpected character: '%c'", *d->ptr); + } +} + +/* JSON object/array **********************************************************/ + +/* These are used like so: + * + * jsondec_objstart(d); + * while (jsondec_objnext(d)) { + * ... + * } + * jsondec_objend(d) */ + +static int jsondec_peek(jsondec *d) { + jsondec_skipws(d); + return jsondec_rawpeek(d); +} + +static void jsondec_push(jsondec *d) { + if (--d->depth < 0) { + jsondec_err(d, "Recursion limit exceeded"); + } + d->is_first = true; +} + +static bool jsondec_seqnext(jsondec *d, char end_ch) { + bool is_first = d->is_first; + d->is_first = false; + jsondec_skipws(d); + if (*d->ptr == end_ch) return false; + if (!is_first) jsondec_parselit(d, ","); + return true; +} + +static void jsondec_arrstart(jsondec *d) { + jsondec_push(d); + jsondec_wsch(d, '['); +} + +static void jsondec_arrend(jsondec *d) { + d->depth++; + jsondec_wsch(d, ']'); +} + +static bool jsondec_arrnext(jsondec *d) { + return jsondec_seqnext(d, ']'); +} + +static void jsondec_objstart(jsondec *d) { + jsondec_push(d); + jsondec_wsch(d, '{'); +} + +static void jsondec_objend(jsondec *d) { + d->depth++; + jsondec_wsch(d, '}'); +} + +static bool jsondec_objnext(jsondec *d) { + if (!jsondec_seqnext(d, '}')) return false; + if (jsondec_peek(d) != JD_STRING) { + jsondec_err(d, "Object must start with string"); + } + return true; +} + +/* JSON number ****************************************************************/ + +static bool jsondec_tryskipdigits(jsondec *d) { + const char *start = d->ptr; + + while (d->ptr < d->end) { + if (*d->ptr < '0' || *d->ptr > '9') { + break; + } + d->ptr++; + } + + return d->ptr != start; +} + +static void jsondec_skipdigits(jsondec *d) { + if (!jsondec_tryskipdigits(d)) { + jsondec_err(d, "Expected one or more digits"); + } +} + +static double jsondec_number(jsondec *d) { + const char *start = d->ptr; + + assert(jsondec_rawpeek(d) == JD_NUMBER); + + /* Skip over the syntax of a number, as specified by JSON. */ + if (*d->ptr == '-') d->ptr++; + + if (jsondec_tryparsech(d, '0')) { + if (jsondec_tryskipdigits(d)) { + jsondec_err(d, "number cannot have leading zero"); + } + } else { + jsondec_skipdigits(d); + } + + if (d->ptr == d->end) goto parse; + if (jsondec_tryparsech(d, '.')) { + jsondec_skipdigits(d); + } + if (d->ptr == d->end) goto parse; + + if (*d->ptr == 'e' || *d->ptr == 'E') { + d->ptr++; + if (d->ptr == d->end) { + jsondec_err(d, "Unexpected EOF in number"); + } + if (*d->ptr == '+' || *d->ptr == '-') { + d->ptr++; + } + jsondec_skipdigits(d); + } + +parse: + /* Having verified the syntax of a JSON number, use strtod() to parse + * (strtod() accepts a superset of JSON syntax). */ + errno = 0; + { + char* end; + double val = strtod(start, &end); + assert(end == d->ptr); + + /* Currently the min/max-val conformance tests fail if we check this. Does + * this mean the conformance tests are wrong or strtod() is wrong, or + * something else? Investigate further. */ + /* + if (errno == ERANGE) { + jsondec_err(d, "Number out of range"); + } + */ + + if (val > DBL_MAX || val < -DBL_MAX) { + jsondec_err(d, "Number out of range"); + } + + return val; + } +} + +/* JSON string ****************************************************************/ + +static char jsondec_escape(jsondec *d) { + switch (*d->ptr++) { + case '"': + return '\"'; + case '\\': + return '\\'; + case '/': + return '/'; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + default: + jsondec_err(d, "Invalid escape char"); + } +} + +static uint32_t jsondec_codepoint(jsondec *d) { + uint32_t cp = 0; + const char *end; + + if (d->end - d->ptr < 4) { + jsondec_err(d, "EOF inside string"); + } + + end = d->ptr + 4; + while (d->ptr < end) { + char ch = *d->ptr++; + if (ch >= '0' && ch <= '9') { + ch -= '0'; + } else if (ch >= 'a' && ch <= 'f') { + ch = ch - 'a' + 10; + } else if (ch >= 'A' && ch <= 'F') { + ch = ch - 'A' + 10; + } else { + jsondec_err(d, "Invalid hex digit"); + } + cp = (cp << 4) | ch; + } + + return cp; +} + +/* Parses a \uXXXX unicode escape (possibly a surrogate pair). */ +static size_t jsondec_unicode(jsondec *d, char* out) { + uint32_t cp = jsondec_codepoint(d); + if (cp >= 0xd800 && cp <= 0xdbff) { + /* Surrogate pair: two 16-bit codepoints become a 32-bit codepoint. */ + uint32_t high = cp; + uint32_t low; + jsondec_parselit(d, "\\u"); + low = jsondec_codepoint(d); + if (low < 0xdc00 || low > 0xdfff) { + jsondec_err(d, "Invalid low surrogate"); + } + cp = (high & 0x3ff) << 10; + cp |= (low & 0x3ff); + cp += 0x10000; + } else if (cp >= 0xdc00 && cp <= 0xdfff) { + jsondec_err(d, "Unpaired low surrogate"); + } + + /* Write to UTF-8 */ + if (cp <= 0x7f) { + out[0] = cp; + return 1; + } else if (cp <= 0x07FF) { + out[0] = ((cp >> 6) & 0x1F) | 0xC0; + out[1] = ((cp >> 0) & 0x3F) | 0x80; + return 2; + } else if (cp <= 0xFFFF) { + out[0] = ((cp >> 12) & 0x0F) | 0xE0; + out[1] = ((cp >> 6) & 0x3F) | 0x80; + out[2] = ((cp >> 0) & 0x3F) | 0x80; + return 3; + } else if (cp < 0x10FFFF) { + out[0] = ((cp >> 18) & 0x07) | 0xF0; + out[1] = ((cp >> 12) & 0x3f) | 0x80; + out[2] = ((cp >> 6) & 0x3f) | 0x80; + out[3] = ((cp >> 0) & 0x3f) | 0x80; + return 4; + } else { + jsondec_err(d, "Invalid codepoint"); + } +} + +static void jsondec_resize(jsondec *d, char **buf, char **end, char **buf_end) { + size_t oldsize = *buf_end - *buf; + size_t len = *end - *buf; + size_t size = UPB_MAX(8, 2 * oldsize); + + *buf = upb_arena_realloc(d->arena, *buf, len, size); + if (!*buf) jsondec_err(d, "Out of memory"); + + *end = *buf + len; + *buf_end = *buf + size; +} + +static upb_strview jsondec_string(jsondec *d) { + char *buf = NULL; + char *end = NULL; + char *buf_end = NULL; + + jsondec_skipws(d); + + if (*d->ptr++ != '"') { + jsondec_err(d, "Expected string"); + } + + while (d->ptr < d->end) { + char ch = *d->ptr++; + + if (end == buf_end) { + jsondec_resize(d, &buf, &end, &buf_end); + } + + switch (ch) { + case '"': { + upb_strview ret; + ret.data = buf; + ret.size = end - buf; + *end = '\0'; /* Needed for possible strtod(). */ + return ret; + } + case '\\': + if (d->ptr == d->end) goto eof; + if (*d->ptr == 'u') { + d->ptr++; + if (buf_end - end < 4) { + /* Allow space for maximum-sized code point (4 bytes). */ + jsondec_resize(d, &buf, &end, &buf_end); + } + end += jsondec_unicode(d, end); + } else { + *end++ = jsondec_escape(d); + } + break; + default: + if ((unsigned char)*d->ptr < 0x20) { + jsondec_err(d, "Invalid char in JSON string"); + } + *end++ = ch; + break; + } + } + +eof: + jsondec_err(d, "EOF inside string"); +} + +static void jsondec_skipval(jsondec *d) { + switch (jsondec_peek(d)) { + case JD_OBJECT: + jsondec_objstart(d); + while (jsondec_objnext(d)) { + jsondec_string(d); + jsondec_entrysep(d); + jsondec_skipval(d); + } + jsondec_objend(d); + break; + case JD_ARRAY: + jsondec_arrstart(d); + while (jsondec_arrnext(d)) { + jsondec_skipval(d); + } + jsondec_arrend(d); + break; + case JD_TRUE: + jsondec_true(d); + break; + case JD_FALSE: + jsondec_false(d); + break; + case JD_NULL: + jsondec_null(d); + break; + case JD_STRING: + jsondec_string(d); + break; + case JD_NUMBER: + jsondec_number(d); + break; + } +} + +/* Base64 decoding for bytes fields. ******************************************/ + +static unsigned int jsondec_base64_tablelookup(const char ch) { + /* Table includes the normal base64 chars plus the URL-safe variant. */ + const signed char table[256] = { + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, 62 /*+*/, -1, 62 /*-*/, -1, 63 /*/ */, 52 /*0*/, + 53 /*1*/, 54 /*2*/, 55 /*3*/, 56 /*4*/, 57 /*5*/, 58 /*6*/, 59 /*7*/, + 60 /*8*/, 61 /*9*/, -1, -1, -1, -1, -1, + -1, -1, 0 /*A*/, 1 /*B*/, 2 /*C*/, 3 /*D*/, 4 /*E*/, + 5 /*F*/, 6 /*G*/, 07 /*H*/, 8 /*I*/, 9 /*J*/, 10 /*K*/, 11 /*L*/, + 12 /*M*/, 13 /*N*/, 14 /*O*/, 15 /*P*/, 16 /*Q*/, 17 /*R*/, 18 /*S*/, + 19 /*T*/, 20 /*U*/, 21 /*V*/, 22 /*W*/, 23 /*X*/, 24 /*Y*/, 25 /*Z*/, + -1, -1, -1, -1, 63 /*_*/, -1, 26 /*a*/, + 27 /*b*/, 28 /*c*/, 29 /*d*/, 30 /*e*/, 31 /*f*/, 32 /*g*/, 33 /*h*/, + 34 /*i*/, 35 /*j*/, 36 /*k*/, 37 /*l*/, 38 /*m*/, 39 /*n*/, 40 /*o*/, + 41 /*p*/, 42 /*q*/, 43 /*r*/, 44 /*s*/, 45 /*t*/, 46 /*u*/, 47 /*v*/, + 48 /*w*/, 49 /*x*/, 50 /*y*/, 51 /*z*/, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1}; + + /* Sign-extend return value so high bit will be set on any unexpected char. */ + return table[(unsigned)ch]; +} + +static char *jsondec_partialbase64(jsondec *d, const char *ptr, const char *end, + char *out) { + int32_t val = -1; + + switch (end - ptr) { + case 2: + val = jsondec_base64_tablelookup(ptr[0]) << 18 | + jsondec_base64_tablelookup(ptr[1]) << 12; + out[0] = val >> 16; + out += 1; + break; + case 3: + val = jsondec_base64_tablelookup(ptr[0]) << 18 | + jsondec_base64_tablelookup(ptr[1]) << 12 | + jsondec_base64_tablelookup(ptr[2]) << 6; + out[0] = val >> 16; + out[1] = (val >> 8) & 0xff; + out += 2; + break; + } + + if (val < 0) { + jsondec_err(d, "Corrupt base64"); + } + + return out; +} + +static size_t jsondec_base64(jsondec *d, upb_strview str) { + /* We decode in place. This is safe because this is a new buffer (not + * aliasing the input) and because base64 decoding shrinks 4 bytes into 3. */ + char *out = (char*)str.data; + const char *ptr = str.data; + const char *end = ptr + str.size; + const char *end4 = ptr + (str.size & -4); /* Round down to multiple of 4. */ + + for (; ptr < end4; ptr += 4, out += 3) { + int val = jsondec_base64_tablelookup(ptr[0]) << 18 | + jsondec_base64_tablelookup(ptr[1]) << 12 | + jsondec_base64_tablelookup(ptr[2]) << 6 | + jsondec_base64_tablelookup(ptr[3]) << 0; + + if (val < 0) { + /* Junk chars or padding. Remove trailing padding, if any. */ + if (end - ptr == 4 && ptr[3] == '=') { + if (ptr[2] == '=') { + end -= 2; + } else { + end -= 1; + } + } + break; + } + + out[0] = val >> 16; + out[1] = (val >> 8) & 0xff; + out[2] = val & 0xff; + } + + if (ptr < end) { + /* Process remaining chars. We do not require padding. */ + out = jsondec_partialbase64(d, ptr, end, out); + } + + return out - str.data; +} + +/* Low-level integer parsing **************************************************/ + +/* We use these hand-written routines instead of strto[u]l() because the "long + * long" variants aren't in c89. Also our version allows setting a ptr limit. */ + +static const char *jsondec_buftouint64(jsondec *d, const char *ptr, + const char *end, uint64_t *val) { + uint64_t u64 = 0; + while (ptr < end) { + unsigned ch = *ptr - '0'; + if (ch >= 10) break; + if (u64 > UINT64_MAX / 10 || u64 * 10 > UINT64_MAX - ch) { + jsondec_err(d, "Integer overflow"); + } + u64 *= 10; + u64 += ch; + ptr++; + } + + *val = u64; + return ptr; +} + +static const char *jsondec_buftoint64(jsondec *d, const char *ptr, + const char *end, int64_t *val) { + bool neg = false; + uint64_t u64; + + if (ptr != end && *ptr == '-') { + ptr++; + neg = true; + } + + ptr = jsondec_buftouint64(d, ptr, end, &u64); + if (u64 > (uint64_t)INT64_MAX + neg) { + jsondec_err(d, "Integer overflow"); + } + + *val = neg ? -u64 : u64; + return ptr; +} + +static uint64_t jsondec_strtouint64(jsondec *d, upb_strview str) { + const char *end = str.data + str.size; + uint64_t ret; + if (jsondec_buftouint64(d, str.data, end, &ret) != end) { + jsondec_err(d, "Non-number characters in quoted integer"); + } + return ret; +} + +static int64_t jsondec_strtoint64(jsondec *d, upb_strview str) { + const char *end = str.data + str.size; + int64_t ret; + if (jsondec_buftoint64(d, str.data, end, &ret) != end) { + jsondec_err(d, "Non-number characters in quoted integer"); + } + return ret; +} + +/* Primitive value types ******************************************************/ + +/* Parse INT32 or INT64 value. */ +static upb_msgval jsondec_int(jsondec *d, const upb_fielddef *f) { + upb_msgval val; + + switch (jsondec_peek(d)) { + case JD_NUMBER: { + double dbl = jsondec_number(d); + if (dbl > 9223372036854774784.0 || dbl < -9223372036854775808.0) { + jsondec_err(d, "JSON number is out of range."); + } + val.int64_val = dbl; /* must be guarded, overflow here is UB */ + if (val.int64_val != dbl) { + jsondec_errf(d, "JSON number was not integral (%f != %" PRId64 ")", dbl, + val.int64_val); + } + break; + } + case JD_STRING: { + upb_strview str = jsondec_string(d); + val.int64_val = jsondec_strtoint64(d, str); + break; + } + default: + jsondec_err(d, "Expected number or string"); + } + + if (upb_fielddef_type(f) == UPB_TYPE_INT32) { + if (val.int64_val > INT32_MAX || val.int64_val < INT32_MIN) { + jsondec_err(d, "Integer out of range."); + } + val.int32_val = (int32_t)val.int64_val; + } + + return val; +} + +/* Parse UINT32 or UINT64 value. */ +static upb_msgval jsondec_uint(jsondec *d, const upb_fielddef *f) { + upb_msgval val = {0}; + + switch (jsondec_peek(d)) { + case JD_NUMBER: { + double dbl = jsondec_number(d); + if (dbl > 18446744073709549568.0 || dbl < 0) { + jsondec_err(d, "JSON number is out of range."); + } + val.uint64_val = dbl; /* must be guarded, overflow here is UB */ + if (val.uint64_val != dbl) { + jsondec_errf(d, "JSON number was not integral (%f != %" PRIu64 ")", dbl, + val.uint64_val); + } + break; + } + case JD_STRING: { + upb_strview str = jsondec_string(d); + val.uint64_val = jsondec_strtouint64(d, str); + break; + } + default: + jsondec_err(d, "Expected number or string"); + } + + if (upb_fielddef_type(f) == UPB_TYPE_UINT32) { + if (val.uint64_val > UINT32_MAX) { + jsondec_err(d, "Integer out of range."); + } + val.uint32_val = (uint32_t)val.uint64_val; + } + + return val; +} + +/* Parse DOUBLE or FLOAT value. */ +static upb_msgval jsondec_double(jsondec *d, const upb_fielddef *f) { + upb_strview str; + upb_msgval val = {0}; + + switch (jsondec_peek(d)) { + case JD_NUMBER: + val.double_val = jsondec_number(d); + break; + case JD_STRING: + str = jsondec_string(d); + if (jsondec_streql(str, "NaN")) { + val.double_val = NAN; + } else if (jsondec_streql(str, "Infinity")) { + val.double_val = INFINITY; + } else if (jsondec_streql(str, "-Infinity")) { + val.double_val = -INFINITY; + } else { + val.double_val = strtod(str.data, NULL); + } + break; + default: + jsondec_err(d, "Expected number or string"); + } + + if (upb_fielddef_type(f) == UPB_TYPE_FLOAT) { + if (val.double_val != INFINITY && val.double_val != -INFINITY && + (val.double_val > FLT_MAX || val.double_val < -FLT_MAX)) { + jsondec_err(d, "Float out of range"); + } + val.float_val = val.double_val; + } + + return val; +} + +/* Parse STRING or BYTES value. */ +static upb_msgval jsondec_strfield(jsondec *d, const upb_fielddef *f) { + upb_msgval val; + val.str_val = jsondec_string(d); + if (upb_fielddef_type(f) == UPB_TYPE_BYTES) { + val.str_val.size = jsondec_base64(d, val.str_val); + } + return val; +} + +static upb_msgval jsondec_enum(jsondec *d, const upb_fielddef *f) { + switch (jsondec_peek(d)) { + case JD_STRING: { + const upb_enumdef *e = upb_fielddef_enumsubdef(f); + upb_strview str = jsondec_string(d); + upb_msgval val; + if (!upb_enumdef_ntoi(e, str.data, str.size, &val.int32_val)) { + if (d->options & UPB_JSONDEC_IGNOREUNKNOWN) { + val.int32_val = 0; + } else { + jsondec_errf(d, "Unknown enumerator: '" UPB_STRVIEW_FORMAT "'", + UPB_STRVIEW_ARGS(str)); + } + } + return val; + } + case JD_NULL: { + if (jsondec_isnullvalue(f)) { + upb_msgval val; + jsondec_null(d); + val.int32_val = 0; + return val; + } + } + /* Fallthrough. */ + default: + return jsondec_int(d, f); + } +} + +static upb_msgval jsondec_bool(jsondec *d, const upb_fielddef *f) { + bool is_map_key = upb_fielddef_number(f) == 1 && + upb_msgdef_mapentry(upb_fielddef_containingtype(f)); + upb_msgval val; + + if (is_map_key) { + upb_strview str = jsondec_string(d); + if (jsondec_streql(str, "true")) { + val.bool_val = true; + } else if (jsondec_streql(str, "false")) { + val.bool_val = false; + } else { + jsondec_err(d, "Invalid boolean map key"); + } + } else { + switch (jsondec_peek(d)) { + case JD_TRUE: + val.bool_val = true; + jsondec_true(d); + break; + case JD_FALSE: + val.bool_val = false; + jsondec_false(d); + break; + default: + jsondec_err(d, "Expected true or false"); + } + } + + return val; +} + +/* Composite types (array/message/map) ****************************************/ + +static void jsondec_array(jsondec *d, upb_msg *msg, const upb_fielddef *f) { + upb_array *arr = upb_msg_mutable(msg, f, d->arena).array; + + jsondec_arrstart(d); + while (jsondec_arrnext(d)) { + upb_msgval elem = jsondec_value(d, f); + upb_array_append(arr, elem, d->arena); + } + jsondec_arrend(d); +} + +static void jsondec_map(jsondec *d, upb_msg *msg, const upb_fielddef *f) { + upb_map *map = upb_msg_mutable(msg, f, d->arena).map; + const upb_msgdef *entry = upb_fielddef_msgsubdef(f); + const upb_fielddef *key_f = upb_msgdef_itof(entry, 1); + const upb_fielddef *val_f = upb_msgdef_itof(entry, 2); + + jsondec_objstart(d); + while (jsondec_objnext(d)) { + upb_msgval key, val; + key = jsondec_value(d, key_f); + jsondec_entrysep(d); + val = jsondec_value(d, val_f); + upb_map_set(map, key, val, d->arena); + } + jsondec_objend(d); +} + +static void jsondec_tomsg(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + if (upb_msgdef_wellknowntype(m) == UPB_WELLKNOWN_UNSPECIFIED) { + jsondec_object(d, msg, m); + } else { + jsondec_wellknown(d, msg, m); + } +} + +static upb_msgval jsondec_msg(jsondec *d, const upb_fielddef *f) { + const upb_msgdef *m = upb_fielddef_msgsubdef(f); + upb_msg *msg = upb_msg_new(m, d->arena); + upb_msgval val; + + jsondec_tomsg(d, msg, m); + val.msg_val = msg; + return val; +} + +static void jsondec_field(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + upb_strview name; + const upb_fielddef *f; + const upb_fielddef *preserved; + + name = jsondec_string(d); + jsondec_entrysep(d); + f = upb_msgdef_lookupjsonname(m, name.data, name.size); + + if (!f) { + if ((d->options & UPB_JSONDEC_IGNOREUNKNOWN) == 0) { + jsondec_errf(d, "No such field: " UPB_STRVIEW_FORMAT, + UPB_STRVIEW_ARGS(name)); + } + jsondec_skipval(d); + return; + } + + if (upb_fielddef_realcontainingoneof(f) && + upb_msg_whichoneof(msg, upb_fielddef_containingoneof(f))) { + jsondec_err(d, "More than one field for this oneof."); + } + + if (jsondec_peek(d) == JD_NULL && !jsondec_isvalue(f)) { + /* JSON "null" indicates a default value, so no need to set anything. */ + jsondec_null(d); + return; + } + + preserved = d->debug_field; + d->debug_field = f; + + if (upb_fielddef_ismap(f)) { + jsondec_map(d, msg, f); + } else if (upb_fielddef_isseq(f)) { + jsondec_array(d, msg, f); + } else if (upb_fielddef_issubmsg(f)) { + upb_msg *submsg = upb_msg_mutable(msg, f, d->arena).msg; + const upb_msgdef *subm = upb_fielddef_msgsubdef(f); + jsondec_tomsg(d, submsg, subm); + } else { + upb_msgval val = jsondec_value(d, f); + upb_msg_set(msg, f, val, d->arena); + } + + d->debug_field = preserved; +} + +static void jsondec_object(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + jsondec_objstart(d); + while (jsondec_objnext(d)) { + jsondec_field(d, msg, m); + } + jsondec_objend(d); +} + +static upb_msgval jsondec_value(jsondec *d, const upb_fielddef *f) { + switch (upb_fielddef_type(f)) { + case UPB_TYPE_BOOL: + return jsondec_bool(d, f); + case UPB_TYPE_FLOAT: + case UPB_TYPE_DOUBLE: + return jsondec_double(d, f); + case UPB_TYPE_UINT32: + case UPB_TYPE_UINT64: + return jsondec_uint(d, f); + case UPB_TYPE_INT32: + case UPB_TYPE_INT64: + return jsondec_int(d, f); + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + return jsondec_strfield(d, f); + case UPB_TYPE_ENUM: + return jsondec_enum(d, f); + case UPB_TYPE_MESSAGE: + return jsondec_msg(d, f); + default: + UPB_UNREACHABLE(); + } +} + +/* Well-known types ***********************************************************/ + +static int jsondec_tsdigits(jsondec *d, const char **ptr, size_t digits, + const char *after) { + uint64_t val; + const char *p = *ptr; + const char *end = p + digits; + size_t after_len = after ? strlen(after) : 0; + + UPB_ASSERT(digits <= 9); /* int can't overflow. */ + + if (jsondec_buftouint64(d, p, end, &val) != end || + (after_len && memcmp(end, after, after_len) != 0)) { + jsondec_err(d, "Malformed timestamp"); + } + + UPB_ASSERT(val < INT_MAX); + + *ptr = end + after_len; + return (int)val; +} + +static int jsondec_nanos(jsondec *d, const char **ptr, const char *end) { + uint64_t nanos = 0; + const char *p = *ptr; + + if (p != end && *p == '.') { + const char *nano_end = jsondec_buftouint64(d, p + 1, end, &nanos); + int digits = (int)(nano_end - p - 1); + int exp_lg10 = 9 - digits; + if (digits > 9) { + jsondec_err(d, "Too many digits for partial seconds"); + } + while (exp_lg10--) nanos *= 10; + *ptr = nano_end; + } + + UPB_ASSERT(nanos < INT_MAX); + + return (int)nanos; +} + +/* jsondec_epochdays(1970, 1, 1) == 1970-01-01 == 0. */ +int jsondec_epochdays(int y, int m, int d) { + const uint32_t year_base = 4800; /* Before min year, multiple of 400. */ + const uint32_t m_adj = m - 3; /* March-based month. */ + const uint32_t carry = m_adj > (uint32_t)m ? 1 : 0; + const uint32_t adjust = carry ? 12 : 0; + const uint32_t y_adj = y + year_base - carry; + const uint32_t month_days = ((m_adj + adjust) * 62719 + 769) / 2048; + const uint32_t leap_days = y_adj / 4 - y_adj / 100 + y_adj / 400; + return y_adj * 365 + leap_days + month_days + (d - 1) - 2472632; +} + +static int64_t jsondec_unixtime(int y, int m, int d, int h, int min, int s) { + return (int64_t)jsondec_epochdays(y, m, d) * 86400 + h * 3600 + min * 60 + s; +} + +static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + upb_msgval seconds; + upb_msgval nanos; + upb_strview str = jsondec_string(d); + const char *ptr = str.data; + const char *end = ptr + str.size; + + if (str.size < 20) goto malformed; + + { + /* 1972-01-01T01:00:00 */ + int year = jsondec_tsdigits(d, &ptr, 4, "-"); + int mon = jsondec_tsdigits(d, &ptr, 2, "-"); + int day = jsondec_tsdigits(d, &ptr, 2, "T"); + int hour = jsondec_tsdigits(d, &ptr, 2, ":"); + int min = jsondec_tsdigits(d, &ptr, 2, ":"); + int sec = jsondec_tsdigits(d, &ptr, 2, NULL); + + seconds.int64_val = jsondec_unixtime(year, mon, day, hour, min, sec); + } + + nanos.int32_val = jsondec_nanos(d, &ptr, end); + + { + /* [+-]08:00 or Z */ + int ofs_hour = 0; + int ofs_min = 0; + bool neg = false; + + if (ptr == end) goto malformed; + + switch (*ptr++) { + case '-': + neg = true; + /* fallthrough */ + case '+': + if ((end - ptr) != 5) goto malformed; + ofs_hour = jsondec_tsdigits(d, &ptr, 2, ":"); + ofs_min = jsondec_tsdigits(d, &ptr, 2, NULL); + ofs_min = ((ofs_hour * 60) + ofs_min) * 60; + seconds.int64_val += (neg ? ofs_min : -ofs_min); + break; + case 'Z': + if (ptr != end) goto malformed; + break; + default: + goto malformed; + } + } + + if (seconds.int64_val < -62135596800) { + jsondec_err(d, "Timestamp out of range"); + } + + upb_msg_set(msg, upb_msgdef_itof(m, 1), seconds, d->arena); + upb_msg_set(msg, upb_msgdef_itof(m, 2), nanos, d->arena); + return; + +malformed: + jsondec_err(d, "Malformed timestamp"); +} + +static void jsondec_duration(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + upb_msgval seconds; + upb_msgval nanos; + upb_strview str = jsondec_string(d); + const char *ptr = str.data; + const char *end = ptr + str.size; + const int64_t max = (uint64_t)3652500 * 86400; + + /* "3.000000001s", "3s", etc. */ + ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val); + nanos.int32_val = jsondec_nanos(d, &ptr, end); + + if (end - ptr != 1 || *ptr != 's') { + jsondec_err(d, "Malformed duration"); + } + + if (seconds.int64_val < -max || seconds.int64_val > max) { + jsondec_err(d, "Duration out of range"); + } + + if (seconds.int64_val < 0) { + nanos.int32_val = - nanos.int32_val; + } + + upb_msg_set(msg, upb_msgdef_itof(m, 1), seconds, d->arena); + upb_msg_set(msg, upb_msgdef_itof(m, 2), nanos, d->arena); +} + +static void jsondec_listvalue(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + const upb_fielddef *values_f = upb_msgdef_itof(m, 1); + const upb_msgdef *value_m = upb_fielddef_msgsubdef(values_f); + upb_array *values = upb_msg_mutable(msg, values_f, d->arena).array; + + jsondec_arrstart(d); + while (jsondec_arrnext(d)) { + upb_msg *value_msg = upb_msg_new(value_m, d->arena); + upb_msgval value; + value.msg_val = value_msg; + upb_array_append(values, value, d->arena); + jsondec_wellknownvalue(d, value_msg, value_m); + } + jsondec_arrend(d); +} + +static void jsondec_struct(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + const upb_fielddef *fields_f = upb_msgdef_itof(m, 1); + const upb_msgdef *entry_m = upb_fielddef_msgsubdef(fields_f); + const upb_fielddef *value_f = upb_msgdef_itof(entry_m, 2); + const upb_msgdef *value_m = upb_fielddef_msgsubdef(value_f); + upb_map *fields = upb_msg_mutable(msg, fields_f, d->arena).map; + + jsondec_objstart(d); + while (jsondec_objnext(d)) { + upb_msgval key, value; + upb_msg *value_msg = upb_msg_new(value_m, d->arena); + key.str_val = jsondec_string(d); + value.msg_val = value_msg; + upb_map_set(fields, key, value, d->arena); + jsondec_entrysep(d); + jsondec_wellknownvalue(d, value_msg, value_m); + } + jsondec_objend(d); +} + +static void jsondec_wellknownvalue(jsondec *d, upb_msg *msg, + const upb_msgdef *m) { + upb_msgval val; + const upb_fielddef *f; + upb_msg *submsg; + + switch (jsondec_peek(d)) { + case JD_NUMBER: + /* double number_value = 2; */ + f = upb_msgdef_itof(m, 2); + val.double_val = jsondec_number(d); + break; + case JD_STRING: + /* string string_value = 3; */ + f = upb_msgdef_itof(m, 3); + val.str_val = jsondec_string(d); + break; + case JD_FALSE: + /* bool bool_value = 4; */ + f = upb_msgdef_itof(m, 4); + val.bool_val = false; + jsondec_false(d); + break; + case JD_TRUE: + /* bool bool_value = 4; */ + f = upb_msgdef_itof(m, 4); + val.bool_val = true; + jsondec_true(d); + break; + case JD_NULL: + /* NullValue null_value = 1; */ + f = upb_msgdef_itof(m, 1); + val.int32_val = 0; + jsondec_null(d); + break; + /* Note: these cases return, because upb_msg_mutable() is enough. */ + case JD_OBJECT: + /* Struct struct_value = 5; */ + f = upb_msgdef_itof(m, 5); + submsg = upb_msg_mutable(msg, f, d->arena).msg; + jsondec_struct(d, submsg, upb_fielddef_msgsubdef(f)); + return; + case JD_ARRAY: + /* ListValue list_value = 6; */ + f = upb_msgdef_itof(m, 6); + submsg = upb_msg_mutable(msg, f, d->arena).msg; + jsondec_listvalue(d, submsg, upb_fielddef_msgsubdef(f)); + return; + default: + UPB_UNREACHABLE(); + } + + upb_msg_set(msg, f, val, d->arena); +} + +static upb_strview jsondec_mask(jsondec *d, const char *buf, const char *end) { + /* FieldMask fields grow due to inserted '_' characters, so we can't do the + * transform in place. */ + const char *ptr = buf; + upb_strview ret; + char *out; + + ret.size = end - ptr; + while (ptr < end) { + ret.size += (*ptr >= 'A' && *ptr <= 'Z'); + ptr++; + } + + out = upb_arena_malloc(d->arena, ret.size); + ptr = buf; + ret.data = out; + + while (ptr < end) { + char ch = *ptr++; + if (ch >= 'A' && ch <= 'Z') { + *out++ = '_'; + *out++ = ch + 32; + } else if (ch == '_') { + jsondec_err(d, "field mask may not contain '_'"); + } else { + *out++ = ch; + } + } + + return ret; +} + +static void jsondec_fieldmask(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + /* repeated string paths = 1; */ + const upb_fielddef *paths_f = upb_msgdef_itof(m, 1); + upb_array *arr = upb_msg_mutable(msg, paths_f, d->arena).array; + upb_strview str = jsondec_string(d); + const char *ptr = str.data; + const char *end = ptr + str.size; + upb_msgval val; + + while (ptr < end) { + const char *elem_end = memchr(ptr, ',', end - ptr); + if (elem_end) { + val.str_val = jsondec_mask(d, ptr, elem_end); + ptr = elem_end + 1; + } else { + val.str_val = jsondec_mask(d, ptr, end); + ptr = end; + } + upb_array_append(arr, val, d->arena); + } +} + +static void jsondec_anyfield(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + if (upb_msgdef_wellknowntype(m) == UPB_WELLKNOWN_UNSPECIFIED) { + /* For regular types: {"@type": "[user type]", "f1": , "f2": } + * where f1, f2, etc. are the normal fields of this type. */ + jsondec_field(d, msg, m); + } else { + /* For well-known types: {"@type": "[well-known type]", "value": } + * where is whatever encoding the WKT normally uses. */ + upb_strview str = jsondec_string(d); + jsondec_entrysep(d); + if (!jsondec_streql(str, "value")) { + jsondec_err(d, "Key for well-known type must be 'value'"); + } + jsondec_wellknown(d, msg, m); + } +} + +static const upb_msgdef *jsondec_typeurl(jsondec *d, upb_msg *msg, + const upb_msgdef *m) { + const upb_fielddef *type_url_f = upb_msgdef_itof(m, 1); + const upb_msgdef *type_m; + upb_strview type_url = jsondec_string(d); + const char *end = type_url.data + type_url.size; + const char *ptr = end; + upb_msgval val; + + val.str_val = type_url; + upb_msg_set(msg, type_url_f, val, d->arena); + + /* Find message name after the last '/' */ + while (ptr > type_url.data && *--ptr != '/') {} + + if (ptr == type_url.data || ptr == end) { + jsondec_err(d, "Type url must have at least one '/' and non-empty host"); + } + + ptr++; + type_m = upb_symtab_lookupmsg2(d->any_pool, ptr, end - ptr); + + if (!type_m) { + jsondec_err(d, "Type was not found"); + } + + return type_m; +} + +static void jsondec_any(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + /* string type_url = 1; + * bytes value = 2; */ + const upb_fielddef *value_f = upb_msgdef_itof(m, 2); + upb_msg *any_msg; + const upb_msgdef *any_m = NULL; + const char *pre_type_data = NULL; + const char *pre_type_end = NULL; + upb_msgval encoded; + + jsondec_objstart(d); + + /* Scan looking for "@type", which is not necessarily first. */ + while (!any_m && jsondec_objnext(d)) { + const char *start = d->ptr; + upb_strview name = jsondec_string(d); + jsondec_entrysep(d); + if (jsondec_streql(name, "@type")) { + any_m = jsondec_typeurl(d, msg, m); + if (pre_type_data) { + pre_type_end = start; + while (*pre_type_end != ',') pre_type_end--; + } + } else { + if (!pre_type_data) pre_type_data = start; + jsondec_skipval(d); + } + } + + if (!any_m) { + jsondec_err(d, "Any object didn't contain a '@type' field"); + } + + any_msg = upb_msg_new(any_m, d->arena); + + if (pre_type_data) { + size_t len = pre_type_end - pre_type_data + 1; + char *tmp = upb_arena_malloc(d->arena, len); + const char *saved_ptr = d->ptr; + const char *saved_end = d->end; + memcpy(tmp, pre_type_data, len - 1); + tmp[len - 1] = '}'; + d->ptr = tmp; + d->end = tmp + len; + d->is_first = true; + while (jsondec_objnext(d)) { + jsondec_anyfield(d, any_msg, any_m); + } + d->ptr = saved_ptr; + d->end = saved_end; + } + + while (jsondec_objnext(d)) { + jsondec_anyfield(d, any_msg, any_m); + } + + jsondec_objend(d); + + encoded.str_val.data = upb_encode(any_msg, upb_msgdef_layout(any_m), d->arena, + &encoded.str_val.size); + upb_msg_set(msg, value_f, encoded, d->arena); +} + +static void jsondec_wrapper(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + const upb_fielddef *value_f = upb_msgdef_itof(m, 1); + upb_msgval val = jsondec_value(d, value_f); + upb_msg_set(msg, value_f, val, d->arena); +} + +static void jsondec_wellknown(jsondec *d, upb_msg *msg, const upb_msgdef *m) { + switch (upb_msgdef_wellknowntype(m)) { + case UPB_WELLKNOWN_ANY: + jsondec_any(d, msg, m); + break; + case UPB_WELLKNOWN_FIELDMASK: + jsondec_fieldmask(d, msg, m); + break; + case UPB_WELLKNOWN_DURATION: + jsondec_duration(d, msg, m); + break; + case UPB_WELLKNOWN_TIMESTAMP: + jsondec_timestamp(d, msg, m); + break; + case UPB_WELLKNOWN_VALUE: + jsondec_wellknownvalue(d, msg, m); + break; + case UPB_WELLKNOWN_LISTVALUE: + jsondec_listvalue(d, msg, m); + break; + case UPB_WELLKNOWN_STRUCT: + jsondec_struct(d, msg, m); + break; + case UPB_WELLKNOWN_DOUBLEVALUE: + case UPB_WELLKNOWN_FLOATVALUE: + case UPB_WELLKNOWN_INT64VALUE: + case UPB_WELLKNOWN_UINT64VALUE: + case UPB_WELLKNOWN_INT32VALUE: + case UPB_WELLKNOWN_UINT32VALUE: + case UPB_WELLKNOWN_STRINGVALUE: + case UPB_WELLKNOWN_BYTESVALUE: + case UPB_WELLKNOWN_BOOLVALUE: + jsondec_wrapper(d, msg, m); + break; + default: + UPB_UNREACHABLE(); + } +} + +bool upb_json_decode(const char *buf, size_t size, upb_msg *msg, + const upb_msgdef *m, const upb_symtab *any_pool, + int options, upb_arena *arena, upb_status *status) { + jsondec d; + d.ptr = buf; + d.end = buf + size; + d.arena = arena; + d.any_pool = any_pool; + d.status = status; + d.options = options; + d.depth = 64; + d.line = 1; + d.line_begin = d.ptr; + d.debug_field = NULL; + d.is_first = false; + + if (UPB_SETJMP(d.err)) return false; + + jsondec_tomsg(&d, msg, m); + return true; +} + + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Must be last. */ + +typedef struct { + char *buf, *ptr, *end; + size_t overflow; + int indent_depth; + int options; + const upb_symtab *ext_pool; + jmp_buf err; + upb_status *status; + upb_arena *arena; +} jsonenc; + +static void jsonenc_msg(jsonenc *e, const upb_msg *msg, const upb_msgdef *m); +static void jsonenc_scalar(jsonenc *e, upb_msgval val, const upb_fielddef *f); +static void jsonenc_msgfield(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m); +static void jsonenc_msgfields(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m); +static void jsonenc_value(jsonenc *e, const upb_msg *msg, const upb_msgdef *m); + +UPB_NORETURN static void jsonenc_err(jsonenc *e, const char *msg) { + upb_status_seterrmsg(e->status, msg); + longjmp(e->err, 1); +} + +UPB_PRINTF(2, 3) +UPB_NORETURN static void jsonenc_errf(jsonenc *e, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + upb_status_vseterrf(e->status, fmt, argp); + va_end(argp); + longjmp(e->err, 1); +} + +static upb_arena *jsonenc_arena(jsonenc *e) { + /* Create lazily, since it's only needed for Any */ + if (!e->arena) { + e->arena = upb_arena_new(); + } + return e->arena; +} + +static void jsonenc_putbytes(jsonenc *e, const void *data, size_t len) { + size_t have = e->end - e->ptr; + if (UPB_LIKELY(have >= len)) { + memcpy(e->ptr, data, len); + e->ptr += len; + } else { + if (have) memcpy(e->ptr, data, have); + e->ptr += have; + e->overflow += (len - have); + } +} + +static void jsonenc_putstr(jsonenc *e, const char *str) { + jsonenc_putbytes(e, str, strlen(str)); +} + +UPB_PRINTF(2, 3) +static void jsonenc_printf(jsonenc *e, const char *fmt, ...) { + size_t n; + size_t have = e->end - e->ptr; + va_list args; + + va_start(args, fmt); + n = vsnprintf(e->ptr, have, fmt, args); + va_end(args); + + if (UPB_LIKELY(have > n)) { + e->ptr += n; + } else { + e->ptr += have; + e->overflow += (n - have); + } +} + +static void jsonenc_nanos(jsonenc *e, int32_t nanos) { + int digits = 9; + + if (nanos == 0) return; + if (nanos < 0 || nanos >= 1000000000) { + jsonenc_err(e, "error formatting timestamp as JSON: invalid nanos"); + } + + while (nanos % 1000 == 0) { + nanos /= 1000; + digits -= 3; + } + + jsonenc_printf(e, ".%.*" PRId32, digits, nanos); +} + +static void jsonenc_timestamp(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m) { + const upb_fielddef *seconds_f = upb_msgdef_itof(m, 1); + const upb_fielddef *nanos_f = upb_msgdef_itof(m, 2); + int64_t seconds = upb_msg_get(msg, seconds_f).int64_val; + int32_t nanos = upb_msg_get(msg, nanos_f).int32_val; + int L, N, I, J, K, hour, min, sec; + + if (seconds < -62135596800) { + jsonenc_err(e, + "error formatting timestamp as JSON: minimum acceptable value " + "is 0001-01-01T00:00:00Z"); + } else if (seconds > 253402300799) { + jsonenc_err(e, + "error formatting timestamp as JSON: maximum acceptable value " + "is 9999-12-31T23:59:59Z"); + } + + /* Julian Day -> Y/M/D, Algorithm from: + * Fliegel, H. F., and Van Flandern, T. C., "A Machine Algorithm for + * Processing Calendar Dates," Communications of the Association of + * Computing Machines, vol. 11 (1968), p. 657. */ + L = (int)(seconds / 86400) + 68569 + 2440588; + N = 4 * L / 146097; + L = L - (146097 * N + 3) / 4; + I = 4000 * (L + 1) / 1461001; + L = L - 1461 * I / 4 + 31; + J = 80 * L / 2447; + K = L - 2447 * J / 80; + L = J / 11; + J = J + 2 - 12 * L; + I = 100 * (N - 49) + I + L; + + sec = seconds % 60; + min = (seconds / 60) % 60; + hour = (seconds / 3600) % 24; + + jsonenc_printf(e, "\"%04d-%02d-%02dT%02d:%02d:%02d", I, J, K, hour, min, sec); + jsonenc_nanos(e, nanos); + jsonenc_putstr(e, "Z\""); +} + +static void jsonenc_duration(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) { + const upb_fielddef *seconds_f = upb_msgdef_itof(m, 1); + const upb_fielddef *nanos_f = upb_msgdef_itof(m, 2); + int64_t seconds = upb_msg_get(msg, seconds_f).int64_val; + int32_t nanos = upb_msg_get(msg, nanos_f).int32_val; + + if (seconds > 315576000000 || seconds < -315576000000 || + (seconds < 0) != (nanos < 0)) { + jsonenc_err(e, "bad duration"); + } + + if (nanos < 0) { + nanos = -nanos; + } + + jsonenc_printf(e, "\"%" PRId64, seconds); + jsonenc_nanos(e, nanos); + jsonenc_putstr(e, "s\""); +} + +static void jsonenc_enum(int32_t val, const upb_fielddef *f, jsonenc *e) { + const upb_enumdef *e_def = upb_fielddef_enumsubdef(f); + + if (strcmp(upb_enumdef_fullname(e_def), "google.protobuf.NullValue") == 0) { + jsonenc_putstr(e, "null"); + } else { + const char *name = upb_enumdef_iton(e_def, val); + + if (name) { + jsonenc_printf(e, "\"%s\"", name); + } else { + jsonenc_printf(e, "%" PRId32, val); + } + } +} + +static void jsonenc_bytes(jsonenc *e, upb_strview str) { + /* This is the regular base64, not the "web-safe" version. */ + static const char base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + const unsigned char *ptr = (unsigned char*)str.data; + const unsigned char *end = ptr + str.size; + char buf[4]; + + jsonenc_putstr(e, "\""); + + while (end - ptr >= 3) { + buf[0] = base64[ptr[0] >> 2]; + buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)]; + buf[2] = base64[((ptr[1] & 0xf) << 2) | (ptr[2] >> 6)]; + buf[3] = base64[ptr[2] & 0x3f]; + jsonenc_putbytes(e, buf, 4); + ptr += 3; + } + + switch (end - ptr) { + case 2: + buf[0] = base64[ptr[0] >> 2]; + buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)]; + buf[2] = base64[(ptr[1] & 0xf) << 2]; + buf[3] = '='; + jsonenc_putbytes(e, buf, 4); + break; + case 1: + buf[0] = base64[ptr[0] >> 2]; + buf[1] = base64[((ptr[0] & 0x3) << 4)]; + buf[2] = '='; + buf[3] = '='; + jsonenc_putbytes(e, buf, 4); + break; + } + + jsonenc_putstr(e, "\""); +} + +static void jsonenc_stringbody(jsonenc *e, upb_strview str) { + const char *ptr = str.data; + const char *end = ptr + str.size; + + while (ptr < end) { + switch (*ptr) { + case '\n': + jsonenc_putstr(e, "\\n"); + break; + case '\r': + jsonenc_putstr(e, "\\r"); + break; + case '\t': + jsonenc_putstr(e, "\\t"); + break; + case '\"': + jsonenc_putstr(e, "\\\""); + break; + case '\f': + jsonenc_putstr(e, "\\f"); + break; + case '\b': + jsonenc_putstr(e, "\\b"); + break; + case '\\': + jsonenc_putstr(e, "\\\\"); + break; + default: + if ((uint8_t)*ptr < 0x20) { + jsonenc_printf(e, "\\u%04x", (int)(uint8_t)*ptr); + } else { + /* This could be a non-ASCII byte. We rely on the string being valid + * UTF-8. */ + jsonenc_putbytes(e, ptr, 1); + } + break; + } + ptr++; + } +} + +static void jsonenc_string(jsonenc *e, upb_strview str) { + jsonenc_putstr(e, "\""); + jsonenc_stringbody(e, str); + jsonenc_putstr(e, "\""); +} + +static void jsonenc_double(jsonenc *e, const char *fmt, double val) { + if (val == INFINITY) { + jsonenc_putstr(e, "\"Infinity\""); + } else if (val == -INFINITY) { + jsonenc_putstr(e, "\"-Infinity\""); + } else if (val != val) { + jsonenc_putstr(e, "\"NaN\""); + } else { + jsonenc_printf(e, fmt, val); + } +} + +static void jsonenc_wrapper(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m) { + const upb_fielddef *val_f = upb_msgdef_itof(m, 1); + upb_msgval val = upb_msg_get(msg, val_f); + jsonenc_scalar(e, val, val_f); +} + +static const upb_msgdef *jsonenc_getanymsg(jsonenc *e, upb_strview type_url) { + /* Find last '/', if any. */ + const char *end = type_url.data + type_url.size; + const char *ptr = end; + const upb_msgdef *ret; + + if (!e->ext_pool) { + jsonenc_err(e, "Tried to encode Any, but no symtab was provided"); + } + + if (type_url.size == 0) goto badurl; + + while (true) { + if (--ptr == type_url.data) { + /* Type URL must contain at least one '/', with host before. */ + goto badurl; + } + if (*ptr == '/') { + ptr++; + break; + } + } + + ret = upb_symtab_lookupmsg2(e->ext_pool, ptr, end - ptr); + + if (!ret) { + jsonenc_errf(e, "Couldn't find Any type: %.*s", (int)(end - ptr), ptr); + } + + return ret; + +badurl: + jsonenc_errf( + e, "Bad type URL: " UPB_STRVIEW_FORMAT, UPB_STRVIEW_ARGS(type_url)); +} + +static void jsonenc_any(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) { + const upb_fielddef *type_url_f = upb_msgdef_itof(m, 1); + const upb_fielddef *value_f = upb_msgdef_itof(m, 2); + upb_strview type_url = upb_msg_get(msg, type_url_f).str_val; + upb_strview value = upb_msg_get(msg, value_f).str_val; + const upb_msgdef *any_m = jsonenc_getanymsg(e, type_url); + const upb_msglayout *any_layout = upb_msgdef_layout(any_m); + upb_arena *arena = jsonenc_arena(e); + upb_msg *any = upb_msg_new(any_m, arena); + + if (!upb_decode(value.data, value.size, any, any_layout, arena)) { + jsonenc_err(e, "Error decoding message in Any"); + } + + jsonenc_putstr(e, "{\"@type\":"); + jsonenc_string(e, type_url); + jsonenc_putstr(e, ","); + + if (upb_msgdef_wellknowntype(any_m) == UPB_WELLKNOWN_UNSPECIFIED) { + /* Regular messages: {"@type": "...","foo": 1, "bar": 2} */ + jsonenc_msgfields(e, any, any_m); + } else { + /* Well-known type: {"@type": "...","value": } */ + jsonenc_putstr(e, "\"value\":"); + jsonenc_msgfield(e, any, any_m); + } + + jsonenc_putstr(e, "}"); +} + +static void jsonenc_putsep(jsonenc *e, const char *str, bool *first) { + if (*first) { + *first = false; + } else { + jsonenc_putstr(e, str); + } +} + +static void jsonenc_fieldpath(jsonenc *e, upb_strview path) { + const char *ptr = path.data; + const char *end = ptr + path.size; + + while (ptr < end) { + char ch = *ptr; + + if (ch >= 'A' && ch <= 'Z') { + jsonenc_err(e, "Field mask element may not have upper-case letter."); + } else if (ch == '_') { + if (ptr == end - 1 || *(ptr + 1) < 'a' || *(ptr + 1) > 'z') { + jsonenc_err(e, "Underscore must be followed by a lowercase letter."); + } + ch = *++ptr - 32; + } + + jsonenc_putbytes(e, &ch, 1); + ptr++; + } +} + +static void jsonenc_fieldmask(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m) { + const upb_fielddef *paths_f = upb_msgdef_itof(m, 1); + const upb_array *paths = upb_msg_get(msg, paths_f).array_val; + bool first = true; + size_t i, n = 0; + + if (paths) n = upb_array_size(paths); + + jsonenc_putstr(e, "\""); + + for (i = 0; i < n; i++) { + jsonenc_putsep(e, ",", &first); + jsonenc_fieldpath(e, upb_array_get(paths, i).str_val); + } + + jsonenc_putstr(e, "\""); +} + +static void jsonenc_struct(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m) { + const upb_fielddef *fields_f = upb_msgdef_itof(m, 1); + const upb_map *fields = upb_msg_get(msg, fields_f).map_val; + const upb_msgdef *entry_m = upb_fielddef_msgsubdef(fields_f); + const upb_fielddef *value_f = upb_msgdef_itof(entry_m, 2); + size_t iter = UPB_MAP_BEGIN; + bool first = true; + + jsonenc_putstr(e, "{"); + + if (fields) { + while (upb_mapiter_next(fields, &iter)) { + upb_msgval key = upb_mapiter_key(fields, iter); + upb_msgval val = upb_mapiter_value(fields, iter); + + jsonenc_putsep(e, ",", &first); + jsonenc_string(e, key.str_val); + jsonenc_putstr(e, ":"); + jsonenc_value(e, val.msg_val, upb_fielddef_msgsubdef(value_f)); + } + } + + jsonenc_putstr(e, "}"); +} + +static void jsonenc_listvalue(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m) { + const upb_fielddef *values_f = upb_msgdef_itof(m, 1); + const upb_msgdef *values_m = upb_fielddef_msgsubdef(values_f); + const upb_array *values = upb_msg_get(msg, values_f).array_val; + size_t i; + bool first = true; + + jsonenc_putstr(e, "["); + + if (values) { + const size_t size = upb_array_size(values); + for (i = 0; i < size; i++) { + upb_msgval elem = upb_array_get(values, i); + + jsonenc_putsep(e, ",", &first); + jsonenc_value(e, elem.msg_val, values_m); + } + } + + jsonenc_putstr(e, "]"); +} + +static void jsonenc_value(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) { + /* TODO(haberman): do we want a reflection method to get oneof case? */ + size_t iter = UPB_MSG_BEGIN; + const upb_fielddef *f; + upb_msgval val; + + if (!upb_msg_next(msg, m, NULL, &f, &val, &iter)) { + jsonenc_err(e, "No value set in Value proto"); + } + + switch (upb_fielddef_number(f)) { + case 1: + jsonenc_putstr(e, "null"); + break; + case 2: + jsonenc_double(e, "%.17g", val.double_val); + break; + case 3: + jsonenc_string(e, val.str_val); + break; + case 4: + jsonenc_putstr(e, val.bool_val ? "true" : "false"); + break; + case 5: + jsonenc_struct(e, val.msg_val, upb_fielddef_msgsubdef(f)); + break; + case 6: + jsonenc_listvalue(e, val.msg_val, upb_fielddef_msgsubdef(f)); + break; + } +} + +static void jsonenc_msgfield(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m) { + switch (upb_msgdef_wellknowntype(m)) { + case UPB_WELLKNOWN_UNSPECIFIED: + jsonenc_msg(e, msg, m); + break; + case UPB_WELLKNOWN_ANY: + jsonenc_any(e, msg, m); + break; + case UPB_WELLKNOWN_FIELDMASK: + jsonenc_fieldmask(e, msg, m); + break; + case UPB_WELLKNOWN_DURATION: + jsonenc_duration(e, msg, m); + break; + case UPB_WELLKNOWN_TIMESTAMP: + jsonenc_timestamp(e, msg, m); + break; + case UPB_WELLKNOWN_DOUBLEVALUE: + case UPB_WELLKNOWN_FLOATVALUE: + case UPB_WELLKNOWN_INT64VALUE: + case UPB_WELLKNOWN_UINT64VALUE: + case UPB_WELLKNOWN_INT32VALUE: + case UPB_WELLKNOWN_UINT32VALUE: + case UPB_WELLKNOWN_STRINGVALUE: + case UPB_WELLKNOWN_BYTESVALUE: + case UPB_WELLKNOWN_BOOLVALUE: + jsonenc_wrapper(e, msg, m); + break; + case UPB_WELLKNOWN_VALUE: + jsonenc_value(e, msg, m); + break; + case UPB_WELLKNOWN_LISTVALUE: + jsonenc_listvalue(e, msg, m); + break; + case UPB_WELLKNOWN_STRUCT: + jsonenc_struct(e, msg, m); + break; + } +} + +static void jsonenc_scalar(jsonenc *e, upb_msgval val, const upb_fielddef *f) { + switch (upb_fielddef_type(f)) { + case UPB_TYPE_BOOL: + jsonenc_putstr(e, val.bool_val ? "true" : "false"); + break; + case UPB_TYPE_FLOAT: + jsonenc_double(e, "%.9g", val.float_val); + break; + case UPB_TYPE_DOUBLE: + jsonenc_double(e, "%.17g", val.double_val); + break; + case UPB_TYPE_INT32: + jsonenc_printf(e, "%" PRId32, val.int32_val); + break; + case UPB_TYPE_UINT32: + jsonenc_printf(e, "%" PRIu32, val.uint32_val); + break; + case UPB_TYPE_INT64: + jsonenc_printf(e, "\"%" PRId64 "\"", val.int64_val); + break; + case UPB_TYPE_UINT64: + jsonenc_printf(e, "\"%" PRIu64 "\"", val.uint64_val); + break; + case UPB_TYPE_STRING: + jsonenc_string(e, val.str_val); + break; + case UPB_TYPE_BYTES: + jsonenc_bytes(e, val.str_val); + break; + case UPB_TYPE_ENUM: + jsonenc_enum(val.int32_val, f, e); + break; + case UPB_TYPE_MESSAGE: + jsonenc_msgfield(e, val.msg_val, upb_fielddef_msgsubdef(f)); + break; + } +} + +static void jsonenc_mapkey(jsonenc *e, upb_msgval val, const upb_fielddef *f) { + jsonenc_putstr(e, "\""); + + switch (upb_fielddef_type(f)) { + case UPB_TYPE_BOOL: + jsonenc_putstr(e, val.bool_val ? "true" : "false"); + break; + case UPB_TYPE_INT32: + jsonenc_printf(e, "%" PRId32, val.int32_val); + break; + case UPB_TYPE_UINT32: + jsonenc_printf(e, "%" PRIu32, val.uint32_val); + break; + case UPB_TYPE_INT64: + jsonenc_printf(e, "%" PRId64, val.int64_val); + break; + case UPB_TYPE_UINT64: + jsonenc_printf(e, "%" PRIu64, val.uint64_val); + break; + case UPB_TYPE_STRING: + jsonenc_stringbody(e, val.str_val); + break; + default: + UPB_UNREACHABLE(); + } + + jsonenc_putstr(e, "\":"); +} + +static void jsonenc_array(jsonenc *e, const upb_array *arr, + const upb_fielddef *f) { + size_t i; + size_t size = arr ? upb_array_size(arr) : 0; + bool first = true; + + jsonenc_putstr(e, "["); + + for (i = 0; i < size; i++) { + jsonenc_putsep(e, ",", &first); + jsonenc_scalar(e, upb_array_get(arr, i), f); + } + + jsonenc_putstr(e, "]"); +} + +static void jsonenc_map(jsonenc *e, const upb_map *map, const upb_fielddef *f) { + const upb_msgdef *entry = upb_fielddef_msgsubdef(f); + const upb_fielddef *key_f = upb_msgdef_itof(entry, 1); + const upb_fielddef *val_f = upb_msgdef_itof(entry, 2); + size_t iter = UPB_MAP_BEGIN; + bool first = true; + + jsonenc_putstr(e, "{"); + + if (map) { + while (upb_mapiter_next(map, &iter)) { + jsonenc_putsep(e, ",", &first); + jsonenc_mapkey(e, upb_mapiter_key(map, iter), key_f); + jsonenc_scalar(e, upb_mapiter_value(map, iter), val_f); + } + } + + jsonenc_putstr(e, "}"); +} + +static void jsonenc_fieldval(jsonenc *e, const upb_fielddef *f, + upb_msgval val, bool *first) { + const char *name; + + if (e->options & UPB_JSONENC_PROTONAMES) { + name = upb_fielddef_name(f); + } else { + name = upb_fielddef_jsonname(f); + } + + jsonenc_putsep(e, ",", first); + jsonenc_printf(e, "\"%s\":", name); + + if (upb_fielddef_ismap(f)) { + jsonenc_map(e, val.map_val, f); + } else if (upb_fielddef_isseq(f)) { + jsonenc_array(e, val.array_val, f); + } else { + jsonenc_scalar(e, val, f); + } +} + +static void jsonenc_msgfields(jsonenc *e, const upb_msg *msg, + const upb_msgdef *m) { + upb_msgval val; + const upb_fielddef *f; + bool first = true; + + if (e->options & UPB_JSONENC_EMITDEFAULTS) { + /* Iterate over all fields. */ + int i = 0; + int n = upb_msgdef_fieldcount(m); + for (i = 0; i < n; i++) { + f = upb_msgdef_field(m, i); + if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) { + jsonenc_fieldval(e, f, upb_msg_get(msg, f), &first); + } + } + } else { + /* Iterate over non-empty fields. */ + size_t iter = UPB_MSG_BEGIN; + while (upb_msg_next(msg, m, e->ext_pool, &f, &val, &iter)) { + jsonenc_fieldval(e, f, val, &first); + } + } +} + +static void jsonenc_msg(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) { + jsonenc_putstr(e, "{"); + jsonenc_msgfields(e, msg, m); + jsonenc_putstr(e, "}"); +} + +static size_t jsonenc_nullz(jsonenc *e, size_t size) { + size_t ret = e->ptr - e->buf + e->overflow; + + if (size > 0) { + if (e->ptr == e->end) e->ptr--; + *e->ptr = '\0'; + } + + return ret; +} + +size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m, + const upb_symtab *ext_pool, int options, char *buf, + size_t size, upb_status *status) { + jsonenc e; + + e.buf = buf; + e.ptr = buf; + e.end = buf + size; + e.overflow = 0; + e.options = options; + e.ext_pool = ext_pool; + e.status = status; + e.arena = NULL; + + if (setjmp(e.err)) return -1; + + jsonenc_msgfield(&e, msg, m); + if (e.arena) upb_arena_free(e.arena); + return jsonenc_nullz(&e, size); +} +/* See port_def.inc. This should #undef all macros #defined there. */ + +#undef UPB_MAPTYPE_STRING +#undef UPB_SIZE +#undef UPB_PTR_AT +#undef UPB_READ_ONEOF +#undef UPB_WRITE_ONEOF +#undef UPB_INLINE +#undef UPB_ALIGN_UP +#undef UPB_ALIGN_DOWN +#undef UPB_ALIGN_MALLOC +#undef UPB_ALIGN_OF +#undef UPB_FORCEINLINE +#undef UPB_NOINLINE +#undef UPB_NORETURN +#undef UPB_MAX +#undef UPB_MIN +#undef UPB_UNUSED +#undef UPB_ASSUME +#undef UPB_ASSERT +#undef UPB_UNREACHABLE +#undef UPB_POISON_MEMORY_REGION +#undef UPB_UNPOISON_MEMORY_REGION +#undef UPB_ASAN diff --git a/ruby/ext/google/protobuf_c/ruby-upb.h b/ruby/ext/google/protobuf_c/ruby-upb.h new file mode 100755 index 0000000000000..fa04393558975 --- /dev/null +++ b/ruby/ext/google/protobuf_c/ruby-upb.h @@ -0,0 +1,4452 @@ +/* Amalgamated source file */ +#include /* +* This is where we define macros used across upb. +* +* All of these macros are undef'd in port_undef.inc to avoid leaking them to +* users. +* +* The correct usage is: +* +* #include "upb/foobar.h" +* #include "upb/baz.h" +* +* // MUST be last included header. +* #include "upb/port_def.inc" +* +* // Code for this file. +* // <...> +* +* // Can be omitted for .c files, required for .h. +* #include "upb/port_undef.inc" +* +* This file is private and must not be included by users! +*/ + +#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) || \ + (defined(_MSC_VER) && _MSC_VER >= 1900)) +#error upb requires C99 or C++11 or MSVC >= 2015. +#endif + +#include +#include + +#if UINTPTR_MAX == 0xffffffff +#define UPB_SIZE(size32, size64) size32 +#else +#define UPB_SIZE(size32, size64) size64 +#endif + +/* If we always read/write as a consistent type to each address, this shouldn't + * violate aliasing. + */ +#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs))) + +#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \ + *UPB_PTR_AT(msg, case_offset, int) == case_val \ + ? *UPB_PTR_AT(msg, offset, fieldtype) \ + : default + +#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \ + *UPB_PTR_AT(msg, case_offset, int) = case_val; \ + *UPB_PTR_AT(msg, offset, fieldtype) = value; + +#define UPB_MAPTYPE_STRING 0 + +/* UPB_INLINE: inline if possible, emit standalone code if required. */ +#ifdef __cplusplus +#define UPB_INLINE inline +#elif defined (__GNUC__) || defined(__clang__) +#define UPB_INLINE static __inline__ +#else +#define UPB_INLINE static +#endif + +#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align)) +#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align)) +#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16) +#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member) + +/* Hints to the compiler about likely/unlikely branches. */ +#if defined (__GNUC__) || defined(__clang__) +#define UPB_LIKELY(x) __builtin_expect((x),1) +#define UPB_UNLIKELY(x) __builtin_expect((x),0) +#else +#define UPB_LIKELY(x) (x) +#define UPB_UNLIKELY(x) (x) +#endif + +/* Macros for function attributes on compilers that support them. */ +#ifdef __GNUC__ +#define UPB_FORCEINLINE __inline__ __attribute__((always_inline)) +#define UPB_NOINLINE __attribute__((noinline)) +#define UPB_NORETURN __attribute__((__noreturn__)) +#define UPB_PRINTF(str, first_vararg) __attribute__((format (printf, str, first_vararg))) +#elif defined(_MSC_VER) +#define UPB_NOINLINE +#define UPB_FORCEINLINE +#define UPB_NORETURN __declspec(noreturn) +#define UPB_PRINTF(str, first_vararg) +#else /* !defined(__GNUC__) */ +#define UPB_FORCEINLINE +#define UPB_NOINLINE +#define UPB_NORETURN +#define UPB_PRINTF(str, first_vararg) +#endif + +#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) +#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y)) + +#define UPB_UNUSED(var) (void)var + +/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true. + */ +#ifdef NDEBUG +#ifdef __GNUC__ +#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable() +#elif defined _MSC_VER +#define UPB_ASSUME(expr) if (!(expr)) __assume(0) +#else +#define UPB_ASSUME(expr) do {} while (false && (expr)) +#endif +#else +#define UPB_ASSUME(expr) assert(expr) +#endif + +/* UPB_ASSERT(): in release mode, we use the expression without letting it be + * evaluated. This prevents "unused variable" warnings. */ +#ifdef NDEBUG +#define UPB_ASSERT(expr) do {} while (false && (expr)) +#else +#define UPB_ASSERT(expr) assert(expr) +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0) +#else +#define UPB_UNREACHABLE() do { assert(0); } while(0) +#endif + +/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */ +#ifdef __APPLE__ +#define UPB_SETJMP(buf) _setjmp(buf) +#define UPB_LONGJMP(buf, val) _longjmp(buf, val) +#else +#define UPB_SETJMP(buf) setjmp(buf) +#define UPB_LONGJMP(buf, val) longjmp(buf, val) +#endif + +/* Configure whether fasttable is switched on or not. *************************/ + +#if defined(__x86_64__) && defined(__GNUC__) +#define UPB_FASTTABLE_SUPPORTED 1 +#else +#define UPB_FASTTABLE_SUPPORTED 0 +#endif + +/* define UPB_ENABLE_FASTTABLE to force fast table support. + * This is useful when we want to ensure we are really getting fasttable, + * for example for testing or benchmarking. */ +#if defined(UPB_ENABLE_FASTTABLE) +#if !UPB_FASTTABLE_SUPPORTED +#error fasttable is x86-64 + Clang/GCC only +#endif +#define UPB_FASTTABLE 1 +/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible. + * This is useful for releasing code that might be used on multiple platforms, + * for example the PHP or Ruby C extensions. */ +#elif defined(UPB_TRY_ENABLE_FASTTABLE) +#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED +#else +#define UPB_FASTTABLE 0 +#endif + +/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully + * degrade to non-fasttable if we are using UPB_TRY_ENABLE_FASTTABLE. */ +#if !UPB_FASTTABLE && defined(UPB_TRY_ENABLE_FASTTABLE) +#define UPB_FASTTABLE_INIT(...) +#else +#define UPB_FASTTABLE_INIT(...) __VA_ARGS__ +#endif + +#undef UPB_FASTTABLE_SUPPORTED + +/* ASAN poisoning (for arena) *************************************************/ + +#if defined(__SANITIZE_ADDRESS__) +#define UPB_ASAN 1 +#ifdef __cplusplus +extern "C" { +#endif +void __asan_poison_memory_region(void const volatile *addr, size_t size); +void __asan_unpoison_memory_region(void const volatile *addr, size_t size); +#ifdef __cplusplus +} /* extern "C" */ +#endif +#define UPB_POISON_MEMORY_REGION(addr, size) \ + __asan_poison_memory_region((addr), (size)) +#define UPB_UNPOISON_MEMORY_REGION(addr, size) \ + __asan_unpoison_memory_region((addr), (size)) +#else +#define UPB_ASAN 0 +#define UPB_POISON_MEMORY_REGION(addr, size) \ + ((void)(addr), (void)(size)) +#define UPB_UNPOISON_MEMORY_REGION(addr, size) \ + ((void)(addr), (void)(size)) +#endif +/* +** upb_decode: parsing into a upb_msg using a upb_msglayout. +*/ + +#ifndef UPB_DECODE_H_ +#define UPB_DECODE_H_ + +/* +** Our memory representation for parsing tables and messages themselves. +** Functions in this file are used by generated code and possibly reflection. +** +** The definitions in this file are internal to upb. +**/ + +#ifndef UPB_MSG_H_ +#define UPB_MSG_H_ + +#include +#include +#include + +/* +** upb_table +** +** This header is INTERNAL-ONLY! Its interfaces are not public or stable! +** This file defines very fast int->upb_value (inttable) and string->upb_value +** (strtable) hash tables. +** +** The table uses chained scatter with Brent's variation (inspired by the Lua +** implementation of hash tables). The hash function for strings is Austin +** Appleby's "MurmurHash." +** +** The inttable uses uintptr_t as its key, which guarantees it can be used to +** store pointers or integers of at least 32 bits (upb isn't really useful on +** systems where sizeof(void*) < 4). +** +** The table must be homogeneous (all values of the same type). In debug +** mode, we check this on insert and lookup. +*/ + +#ifndef UPB_TABLE_H_ +#define UPB_TABLE_H_ + +#include +#include +/* +** This file contains shared definitions that are widely used across upb. +*/ + +#ifndef UPB_H_ +#define UPB_H_ + +#include +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/* upb_status *****************************************************************/ + +#define UPB_STATUS_MAX_MESSAGE 127 + +typedef struct { + bool ok; + char msg[UPB_STATUS_MAX_MESSAGE]; /* Error message; NULL-terminated. */ +} upb_status; + +const char *upb_status_errmsg(const upb_status *status); +bool upb_ok(const upb_status *status); + +/* These are no-op if |status| is NULL. */ +void upb_status_clear(upb_status *status); +void upb_status_seterrmsg(upb_status *status, const char *msg); +void upb_status_seterrf(upb_status *status, const char *fmt, ...) + UPB_PRINTF(2, 3); +void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) + UPB_PRINTF(2, 0); +void upb_status_vappenderrf(upb_status *status, const char *fmt, va_list args) + UPB_PRINTF(2, 0); + +/** upb_strview ************************************************************/ + +typedef struct { + const char *data; + size_t size; +} upb_strview; + +UPB_INLINE upb_strview upb_strview_make(const char *data, size_t size) { + upb_strview ret; + ret.data = data; + ret.size = size; + return ret; +} + +UPB_INLINE upb_strview upb_strview_makez(const char *data) { + return upb_strview_make(data, strlen(data)); +} + +UPB_INLINE bool upb_strview_eql(upb_strview a, upb_strview b) { + return a.size == b.size && memcmp(a.data, b.data, a.size) == 0; +} + +#define UPB_STRVIEW_INIT(ptr, len) {ptr, len} + +#define UPB_STRVIEW_FORMAT "%.*s" +#define UPB_STRVIEW_ARGS(view) (int)(view).size, (view).data + +/** upb_alloc *****************************************************************/ + +/* A upb_alloc is a possibly-stateful allocator object. + * + * It could either be an arena allocator (which doesn't require individual + * free() calls) or a regular malloc() (which does). The client must therefore + * free memory unless it knows that the allocator is an arena allocator. */ + +struct upb_alloc; +typedef struct upb_alloc upb_alloc; + +/* A malloc()/free() function. + * If "size" is 0 then the function acts like free(), otherwise it acts like + * realloc(). Only "oldsize" bytes from a previous allocation are preserved. */ +typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize, + size_t size); + +struct upb_alloc { + upb_alloc_func *func; +}; + +UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) { + UPB_ASSERT(alloc); + return alloc->func(alloc, NULL, 0, size); +} + +UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize, + size_t size) { + UPB_ASSERT(alloc); + return alloc->func(alloc, ptr, oldsize, size); +} + +UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) { + assert(alloc); + alloc->func(alloc, ptr, 0, 0); +} + +/* The global allocator used by upb. Uses the standard malloc()/free(). */ + +extern upb_alloc upb_alloc_global; + +/* Functions that hard-code the global malloc. + * + * We still get benefit because we can put custom logic into our global + * allocator, like injecting out-of-memory faults in debug/testing builds. */ + +UPB_INLINE void *upb_gmalloc(size_t size) { + return upb_malloc(&upb_alloc_global, size); +} + +UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) { + return upb_realloc(&upb_alloc_global, ptr, oldsize, size); +} + +UPB_INLINE void upb_gfree(void *ptr) { + upb_free(&upb_alloc_global, ptr); +} + +/* upb_arena ******************************************************************/ + +/* upb_arena is a specific allocator implementation that uses arena allocation. + * The user provides an allocator that will be used to allocate the underlying + * arena blocks. Arenas by nature do not require the individual allocations + * to be freed. However the Arena does allow users to register cleanup + * functions that will run when the arena is destroyed. + * + * A upb_arena is *not* thread-safe. + * + * You could write a thread-safe arena allocator that satisfies the + * upb_alloc interface, but it would not be as efficient for the + * single-threaded case. */ + +typedef void upb_cleanup_func(void *ud); + +struct upb_arena; +typedef struct upb_arena upb_arena; + +typedef struct { + /* We implement the allocator interface. + * This must be the first member of upb_arena! + * TODO(haberman): remove once handlers are gone. */ + upb_alloc alloc; + + char *ptr, *end; +} _upb_arena_head; + +/* Creates an arena from the given initial block (if any -- n may be 0). + * Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this + * is a fixed-size arena and cannot grow. */ +upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc); +void upb_arena_free(upb_arena *a); +bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func); +void upb_arena_fuse(upb_arena *a, upb_arena *b); +void *_upb_arena_slowmalloc(upb_arena *a, size_t size); + +UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; } + +UPB_INLINE size_t _upb_arenahas(upb_arena *a) { + _upb_arena_head *h = (_upb_arena_head*)a; + return (size_t)(h->end - h->ptr); +} + +UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) { + _upb_arena_head *h = (_upb_arena_head*)a; + void* ret; + size = UPB_ALIGN_MALLOC(size); + + if (UPB_UNLIKELY(_upb_arenahas(a) < size)) { + return _upb_arena_slowmalloc(a, size); + } + + ret = h->ptr; + h->ptr += size; + UPB_UNPOISON_MEMORY_REGION(ret, size); + +#if UPB_ASAN + { + size_t guard_size = 32; + if (_upb_arenahas(a) >= guard_size) { + h->ptr += guard_size; + } else { + h->ptr = h->end; + } + } +#endif + + return ret; +} + +UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize, + size_t size) { + void *ret = upb_arena_malloc(a, size); + + if (ret && oldsize > 0) { + memcpy(ret, ptr, oldsize); + } + + return ret; +} + +UPB_INLINE upb_arena *upb_arena_new(void) { + return upb_arena_init(NULL, 0, &upb_alloc_global); +} + +/* Constants ******************************************************************/ + +/* Generic function type. */ +typedef void upb_func(void); + +/* A list of types as they are encoded on-the-wire. */ +typedef enum { + UPB_WIRE_TYPE_VARINT = 0, + UPB_WIRE_TYPE_64BIT = 1, + UPB_WIRE_TYPE_DELIMITED = 2, + UPB_WIRE_TYPE_START_GROUP = 3, + UPB_WIRE_TYPE_END_GROUP = 4, + UPB_WIRE_TYPE_32BIT = 5 +} upb_wiretype_t; + +/* The types a field can have. Note that this list is not identical to the + * types defined in descriptor.proto, which gives INT32 and SINT32 separate + * types (we distinguish the two with the "integer encoding" enum below). */ +typedef enum { + UPB_TYPE_BOOL = 1, + UPB_TYPE_FLOAT = 2, + UPB_TYPE_INT32 = 3, + UPB_TYPE_UINT32 = 4, + UPB_TYPE_ENUM = 5, /* Enum values are int32. */ + UPB_TYPE_MESSAGE = 6, + UPB_TYPE_DOUBLE = 7, + UPB_TYPE_INT64 = 8, + UPB_TYPE_UINT64 = 9, + UPB_TYPE_STRING = 10, + UPB_TYPE_BYTES = 11 +} upb_fieldtype_t; + +/* The repeated-ness of each field; this matches descriptor.proto. */ +typedef enum { + UPB_LABEL_OPTIONAL = 1, + UPB_LABEL_REQUIRED = 2, + UPB_LABEL_REPEATED = 3 +} upb_label_t; + +/* Descriptor types, as defined in descriptor.proto. */ +typedef enum { + /* Old (long) names. TODO(haberman): remove */ + UPB_DESCRIPTOR_TYPE_DOUBLE = 1, + UPB_DESCRIPTOR_TYPE_FLOAT = 2, + UPB_DESCRIPTOR_TYPE_INT64 = 3, + UPB_DESCRIPTOR_TYPE_UINT64 = 4, + UPB_DESCRIPTOR_TYPE_INT32 = 5, + UPB_DESCRIPTOR_TYPE_FIXED64 = 6, + UPB_DESCRIPTOR_TYPE_FIXED32 = 7, + UPB_DESCRIPTOR_TYPE_BOOL = 8, + UPB_DESCRIPTOR_TYPE_STRING = 9, + UPB_DESCRIPTOR_TYPE_GROUP = 10, + UPB_DESCRIPTOR_TYPE_MESSAGE = 11, + UPB_DESCRIPTOR_TYPE_BYTES = 12, + UPB_DESCRIPTOR_TYPE_UINT32 = 13, + UPB_DESCRIPTOR_TYPE_ENUM = 14, + UPB_DESCRIPTOR_TYPE_SFIXED32 = 15, + UPB_DESCRIPTOR_TYPE_SFIXED64 = 16, + UPB_DESCRIPTOR_TYPE_SINT32 = 17, + UPB_DESCRIPTOR_TYPE_SINT64 = 18, + + UPB_DTYPE_DOUBLE = 1, + UPB_DTYPE_FLOAT = 2, + UPB_DTYPE_INT64 = 3, + UPB_DTYPE_UINT64 = 4, + UPB_DTYPE_INT32 = 5, + UPB_DTYPE_FIXED64 = 6, + UPB_DTYPE_FIXED32 = 7, + UPB_DTYPE_BOOL = 8, + UPB_DTYPE_STRING = 9, + UPB_DTYPE_GROUP = 10, + UPB_DTYPE_MESSAGE = 11, + UPB_DTYPE_BYTES = 12, + UPB_DTYPE_UINT32 = 13, + UPB_DTYPE_ENUM = 14, + UPB_DTYPE_SFIXED32 = 15, + UPB_DTYPE_SFIXED64 = 16, + UPB_DTYPE_SINT32 = 17, + UPB_DTYPE_SINT64 = 18 +} upb_descriptortype_t; + +#define UPB_MAP_BEGIN ((size_t)-1) + +UPB_INLINE bool _upb_isle(void) { + int x = 1; + return *(char*)&x == 1; +} + +UPB_INLINE uint32_t _upb_be_swap32(uint32_t val) { + if (_upb_isle()) { + return val; + } else { + return ((val & 0xff) << 24) | ((val & 0xff00) << 8) | + ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24); + } +} + +UPB_INLINE uint64_t _upb_be_swap64(uint64_t val) { + if (_upb_isle()) { + return val; + } else { + return ((uint64_t)_upb_be_swap32(val) << 32) | _upb_be_swap32(val >> 32); + } +} + +UPB_INLINE int _upb_lg2ceil(int x) { + if (x <= 1) return 0; +#ifdef __GNUC__ + return 32 - __builtin_clz(x - 1); +#else + int lg2 = 0; + while (1 << lg2 < x) lg2++; + return lg2; +#endif +} + +UPB_INLINE int _upb_lg2ceilsize(int x) { + return 1 << _upb_lg2ceil(x); +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* UPB_H_ */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* upb_value ******************************************************************/ + +/* A tagged union (stored untagged inside the table) so that we can check that + * clients calling table accessors are correctly typed without having to have + * an explosion of accessors. */ +typedef enum { + UPB_CTYPE_INT32 = 1, + UPB_CTYPE_INT64 = 2, + UPB_CTYPE_UINT32 = 3, + UPB_CTYPE_UINT64 = 4, + UPB_CTYPE_BOOL = 5, + UPB_CTYPE_CSTR = 6, + UPB_CTYPE_PTR = 7, + UPB_CTYPE_CONSTPTR = 8, + UPB_CTYPE_FPTR = 9, + UPB_CTYPE_FLOAT = 10, + UPB_CTYPE_DOUBLE = 11 +} upb_ctype_t; + +typedef struct { + uint64_t val; +} upb_value; + +/* Like strdup(), which isn't always available since it's not ANSI C. */ +char *upb_strdup(const char *s, upb_alloc *a); +/* Variant that works with a length-delimited rather than NULL-delimited string, + * as supported by strtable. */ +char *upb_strdup2(const char *s, size_t len, upb_alloc *a); + +UPB_INLINE char *upb_gstrdup(const char *s) { + return upb_strdup(s, &upb_alloc_global); +} + +UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val) { + v->val = val; +} + +UPB_INLINE upb_value _upb_value_val(uint64_t val) { + upb_value ret; + _upb_value_setval(&ret, val); + return ret; +} + +/* For each value ctype, define the following set of functions: + * + * // Get/set an int32 from a upb_value. + * int32_t upb_value_getint32(upb_value val); + * void upb_value_setint32(upb_value *val, int32_t cval); + * + * // Construct a new upb_value from an int32. + * upb_value upb_value_int32(int32_t val); */ +#define FUNCS(name, membername, type_t, converter, proto_type) \ + UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \ + val->val = (converter)cval; \ + } \ + UPB_INLINE upb_value upb_value_ ## name(type_t val) { \ + upb_value ret; \ + upb_value_set ## name(&ret, val); \ + return ret; \ + } \ + UPB_INLINE type_t upb_value_get ## name(upb_value val) { \ + return (type_t)(converter)val.val; \ + } + +FUNCS(int32, int32, int32_t, int32_t, UPB_CTYPE_INT32) +FUNCS(int64, int64, int64_t, int64_t, UPB_CTYPE_INT64) +FUNCS(uint32, uint32, uint32_t, uint32_t, UPB_CTYPE_UINT32) +FUNCS(uint64, uint64, uint64_t, uint64_t, UPB_CTYPE_UINT64) +FUNCS(bool, _bool, bool, bool, UPB_CTYPE_BOOL) +FUNCS(cstr, cstr, char*, uintptr_t, UPB_CTYPE_CSTR) +FUNCS(ptr, ptr, void*, uintptr_t, UPB_CTYPE_PTR) +FUNCS(constptr, constptr, const void*, uintptr_t, UPB_CTYPE_CONSTPTR) +FUNCS(fptr, fptr, upb_func*, uintptr_t, UPB_CTYPE_FPTR) + +#undef FUNCS + +UPB_INLINE void upb_value_setfloat(upb_value *val, float cval) { + memcpy(&val->val, &cval, sizeof(cval)); +} + +UPB_INLINE void upb_value_setdouble(upb_value *val, double cval) { + memcpy(&val->val, &cval, sizeof(cval)); +} + +UPB_INLINE upb_value upb_value_float(float cval) { + upb_value ret; + upb_value_setfloat(&ret, cval); + return ret; +} + +UPB_INLINE upb_value upb_value_double(double cval) { + upb_value ret; + upb_value_setdouble(&ret, cval); + return ret; +} + +#undef SET_TYPE + + +/* upb_tabkey *****************************************************************/ + +/* Either: + * 1. an actual integer key, or + * 2. a pointer to a string prefixed by its uint32_t length, owned by us. + * + * ...depending on whether this is a string table or an int table. We would + * make this a union of those two types, but C89 doesn't support statically + * initializing a non-first union member. */ +typedef uintptr_t upb_tabkey; + +UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) { + char* mem = (char*)key; + if (len) memcpy(len, mem, sizeof(*len)); + return mem + sizeof(*len); +} + +UPB_INLINE upb_strview upb_tabstrview(upb_tabkey key) { + upb_strview ret; + uint32_t len; + ret.data = upb_tabstr(key, &len); + ret.size = len; + return ret; +} + +/* upb_tabval *****************************************************************/ + +typedef struct upb_tabval { + uint64_t val; +} upb_tabval; + +#define UPB_TABVALUE_EMPTY_INIT {-1} + +/* upb_table ******************************************************************/ + +typedef struct _upb_tabent { + upb_tabkey key; + upb_tabval val; + + /* Internal chaining. This is const so we can create static initializers for + * tables. We cast away const sometimes, but *only* when the containing + * upb_table is known to be non-const. This requires a bit of care, but + * the subtlety is confined to table.c. */ + const struct _upb_tabent *next; +} upb_tabent; + +typedef struct { + size_t count; /* Number of entries in the hash part. */ + uint32_t mask; /* Mask to turn hash value -> bucket. */ + uint32_t max_count; /* Max count before we hit our load limit. */ + uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ + + /* Hash table entries. + * Making this const isn't entirely accurate; what we really want is for it to + * have the same const-ness as the table it's inside. But there's no way to + * declare that in C. So we have to make it const so that we can statically + * initialize const hash tables. Then we cast away const when we have to. + */ + const upb_tabent *entries; +} upb_table; + +typedef struct { + upb_table t; +} upb_strtable; + +typedef struct { + upb_table t; /* For entries that don't fit in the array part. */ + const upb_tabval *array; /* Array part of the table. See const note above. */ + size_t array_size; /* Array part size. */ + size_t array_count; /* Array part number of elements. */ +} upb_inttable; + +#define UPB_ARRAY_EMPTYENT -1 + +UPB_INLINE size_t upb_table_size(const upb_table *t) { + if (t->size_lg2 == 0) + return 0; + else + return 1 << t->size_lg2; +} + +/* Internal-only functions, in .h file only out of necessity. */ +UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) { + return e->key == 0; +} + +/* Used by some of the unit tests for generic hashing functionality. */ +uint32_t upb_murmur_hash2(const void * key, size_t len, uint32_t seed); + +UPB_INLINE uintptr_t upb_intkey(uintptr_t key) { + return key; +} + +UPB_INLINE uint32_t upb_inthash(uintptr_t key) { + return (uint32_t)key; +} + +static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) { + return t->entries + (hash & t->mask); +} + +UPB_INLINE bool upb_arrhas(upb_tabval key) { + return key.val != (uint64_t)-1; +} + +/* Initialize and uninitialize a table, respectively. If memory allocation + * failed, false is returned that the table is uninitialized. */ +bool upb_inttable_init2(upb_inttable *table, upb_ctype_t ctype, upb_alloc *a); +bool upb_strtable_init2(upb_strtable *table, upb_ctype_t ctype, + size_t expected_size, upb_alloc *a); +void upb_inttable_uninit2(upb_inttable *table, upb_alloc *a); +void upb_strtable_uninit2(upb_strtable *table, upb_alloc *a); + +UPB_INLINE bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype) { + return upb_inttable_init2(table, ctype, &upb_alloc_global); +} + +UPB_INLINE bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype) { + return upb_strtable_init2(table, ctype, 4, &upb_alloc_global); +} + +UPB_INLINE void upb_inttable_uninit(upb_inttable *table) { + upb_inttable_uninit2(table, &upb_alloc_global); +} + +UPB_INLINE void upb_strtable_uninit(upb_strtable *table) { + upb_strtable_uninit2(table, &upb_alloc_global); +} + +/* Returns the number of values in the table. */ +size_t upb_inttable_count(const upb_inttable *t); +UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) { + return t->t.count; +} + +void upb_inttable_packedsize(const upb_inttable *t, size_t *size); +void upb_strtable_packedsize(const upb_strtable *t, size_t *size); +upb_inttable *upb_inttable_pack(const upb_inttable *t, void *p, size_t *ofs, + size_t size); +upb_strtable *upb_strtable_pack(const upb_strtable *t, void *p, size_t *ofs, + size_t size); +void upb_strtable_clear(upb_strtable *t); + +/* Inserts the given key into the hashtable with the given value. The key must + * not already exist in the hash table. For string tables, the key must be + * NULL-terminated, and the table will make an internal copy of the key. + * Inttables must not insert a value of UINTPTR_MAX. + * + * If a table resize was required but memory allocation failed, false is + * returned and the table is unchanged. */ +bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, + upb_alloc *a); +bool upb_strtable_insert3(upb_strtable *t, const char *key, size_t len, + upb_value val, upb_alloc *a); + +UPB_INLINE bool upb_inttable_insert(upb_inttable *t, uintptr_t key, + upb_value val) { + return upb_inttable_insert2(t, key, val, &upb_alloc_global); +} + +UPB_INLINE bool upb_strtable_insert2(upb_strtable *t, const char *key, + size_t len, upb_value val) { + return upb_strtable_insert3(t, key, len, val, &upb_alloc_global); +} + +/* For NULL-terminated strings. */ +UPB_INLINE bool upb_strtable_insert(upb_strtable *t, const char *key, + upb_value val) { + return upb_strtable_insert2(t, key, strlen(key), val); +} + +/* Looks up key in this table, returning "true" if the key was found. + * If v is non-NULL, copies the value for this key into *v. */ +bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v); +bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len, + upb_value *v); + +/* For NULL-terminated strings. */ +UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key, + upb_value *v) { + return upb_strtable_lookup2(t, key, strlen(key), v); +} + +/* Removes an item from the table. Returns true if the remove was successful, + * and stores the removed item in *val if non-NULL. */ +bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val); +bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len, + upb_value *val, upb_alloc *alloc); + +UPB_INLINE bool upb_strtable_remove2(upb_strtable *t, const char *key, + size_t len, upb_value *val) { + return upb_strtable_remove3(t, key, len, val, &upb_alloc_global); +} + +/* For NULL-terminated strings. */ +UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key, + upb_value *v) { + return upb_strtable_remove2(t, key, strlen(key), v); +} + +/* Updates an existing entry in an inttable. If the entry does not exist, + * returns false and does nothing. Unlike insert/remove, this does not + * invalidate iterators. */ +bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val); + +/* Convenience routines for inttables with pointer keys. */ +bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val, + upb_alloc *a); +bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val); +bool upb_inttable_lookupptr( + const upb_inttable *t, const void *key, upb_value *val); + +UPB_INLINE bool upb_inttable_insertptr(upb_inttable *t, const void *key, + upb_value val) { + return upb_inttable_insertptr2(t, key, val, &upb_alloc_global); +} + +/* Optimizes the table for the current set of entries, for both memory use and + * lookup time. Client should call this after all entries have been inserted; + * inserting more entries is legal, but will likely require a table resize. */ +void upb_inttable_compact2(upb_inttable *t, upb_alloc *a); + +UPB_INLINE void upb_inttable_compact(upb_inttable *t) { + upb_inttable_compact2(t, &upb_alloc_global); +} + +/* A special-case inlinable version of the lookup routine for 32-bit + * integers. */ +UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, + upb_value *v) { + *v = upb_value_int32(0); /* Silence compiler warnings. */ + if (key < t->array_size) { + upb_tabval arrval = t->array[key]; + if (upb_arrhas(arrval)) { + _upb_value_setval(v, arrval.val); + return true; + } else { + return false; + } + } else { + const upb_tabent *e; + if (t->t.entries == NULL) return false; + for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) { + if ((uint32_t)e->key == key) { + _upb_value_setval(v, e->val.val); + return true; + } + if (e->next == NULL) return false; + } + } +} + +/* Exposed for testing only. */ +bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a); + +/* Iterators ******************************************************************/ + +/* Iterators for int and string tables. We are subject to some kind of unusual + * design constraints: + * + * For high-level languages: + * - we must be able to guarantee that we don't crash or corrupt memory even if + * the program accesses an invalidated iterator. + * + * For C++11 range-based for: + * - iterators must be copyable + * - iterators must be comparable + * - it must be possible to construct an "end" value. + * + * Iteration order is undefined. + * + * Modifying the table invalidates iterators. upb_{str,int}table_done() is + * guaranteed to work even on an invalidated iterator, as long as the table it + * is iterating over has not been freed. Calling next() or accessing data from + * an invalidated iterator yields unspecified elements from the table, but it is + * guaranteed not to crash and to return real table elements (except when done() + * is true). */ + + +/* upb_strtable_iter **********************************************************/ + +/* upb_strtable_iter i; + * upb_strtable_begin(&i, t); + * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { + * const char *key = upb_strtable_iter_key(&i); + * const upb_value val = upb_strtable_iter_value(&i); + * // ... + * } + */ + +typedef struct { + const upb_strtable *t; + size_t index; +} upb_strtable_iter; + +void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t); +void upb_strtable_next(upb_strtable_iter *i); +bool upb_strtable_done(const upb_strtable_iter *i); +upb_strview upb_strtable_iter_key(const upb_strtable_iter *i); +upb_value upb_strtable_iter_value(const upb_strtable_iter *i); +void upb_strtable_iter_setdone(upb_strtable_iter *i); +bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, + const upb_strtable_iter *i2); + + +/* upb_inttable_iter **********************************************************/ + +/* upb_inttable_iter i; + * upb_inttable_begin(&i, t); + * for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { + * uintptr_t key = upb_inttable_iter_key(&i); + * upb_value val = upb_inttable_iter_value(&i); + * // ... + * } + */ + +typedef struct { + const upb_inttable *t; + size_t index; + bool array_part; +} upb_inttable_iter; + +UPB_INLINE const upb_tabent *str_tabent(const upb_strtable_iter *i) { + return &i->t->t.entries[i->index]; +} + +void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t); +void upb_inttable_next(upb_inttable_iter *i); +bool upb_inttable_done(const upb_inttable_iter *i); +uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i); +upb_value upb_inttable_iter_value(const upb_inttable_iter *i); +void upb_inttable_iter_setdone(upb_inttable_iter *i); +bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, + const upb_inttable_iter *i2); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_TABLE_H_ */ + +/* Must be last. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs) + +typedef void upb_msg; + +/** upb_msglayout *************************************************************/ + +/* upb_msglayout represents the memory layout of a given upb_msgdef. The + * members are public so generated code can initialize them, but users MUST NOT + * read or write any of its members. */ + +/* These aren't real labels according to descriptor.proto, but in the table we + * use these for map/packed fields instead of UPB_LABEL_REPEATED. */ +enum { + _UPB_LABEL_MAP = 4, + _UPB_LABEL_PACKED = 7 /* Low 3 bits are common with UPB_LABEL_REPEATED. */ +}; + +typedef struct { + uint32_t number; + uint16_t offset; + int16_t presence; /* If >0, hasbit_index. If <0, ~oneof_index. */ + uint16_t submsg_index; /* undefined if descriptortype != MESSAGE or GROUP. */ + uint8_t descriptortype; + uint8_t label; /* google.protobuf.Label or _UPB_LABEL_* above. */ +} upb_msglayout_field; + +struct upb_decstate; +struct upb_msglayout; + +typedef const char *_upb_field_parser(struct upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits, uint64_t data); + +typedef struct { + uint64_t field_data; + _upb_field_parser *field_parser; +} _upb_fasttable_entry; + +typedef struct upb_msglayout { + const struct upb_msglayout *const* submsgs; + const upb_msglayout_field *fields; + /* Must be aligned to sizeof(void*). Doesn't include internal members like + * unknown fields, extension dict, pointer to msglayout, etc. */ + uint16_t size; + uint16_t field_count; + bool extendable; + uint8_t table_mask; + /* To constant-initialize the tables of variable length, we need a flexible + * array member, and we need to compile in C99 mode. */ + _upb_fasttable_entry fasttable[]; +} upb_msglayout; + +/** upb_msg *******************************************************************/ + +/* Internal members of a upb_msg. We can change this without breaking binary + * compatibility. We put these before the user's data. The user's upb_msg* + * points after the upb_msg_internal. */ + +typedef struct { + uint32_t len; + uint32_t size; + /* Data follows. */ +} upb_msg_unknowndata; + +/* Used when a message is not extendable. */ +typedef struct { + upb_msg_unknowndata *unknown; +} upb_msg_internal; + +/* Maps upb_fieldtype_t -> memory size. */ +extern char _upb_fieldtype_to_size[12]; + +UPB_INLINE size_t upb_msg_sizeof(const upb_msglayout *l) { + return l->size + sizeof(upb_msg_internal); +} + +UPB_INLINE upb_msg *_upb_msg_new_inl(const upb_msglayout *l, upb_arena *a) { + size_t size = upb_msg_sizeof(l); + void *mem = upb_arena_malloc(a, size); + upb_msg *msg; + if (UPB_UNLIKELY(!mem)) return NULL; + msg = UPB_PTR_AT(mem, sizeof(upb_msg_internal), upb_msg); + memset(mem, 0, size); + return msg; +} + +/* Creates a new messages with the given layout on the given arena. */ +upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a); + +UPB_INLINE upb_msg_internal *upb_msg_getinternal(upb_msg *msg) { + ptrdiff_t size = sizeof(upb_msg_internal); + return (upb_msg_internal*)((char*)msg - size); +} + +/* Clears the given message. */ +void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l); + +/* Discards the unknown fields for this message only. */ +void _upb_msg_discardunknown_shallow(upb_msg *msg); + +/* Adds unknown data (serialized protobuf data) to the given message. The data + * is copied into the message instance. */ +bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, + upb_arena *arena); + +/* Returns a reference to the message's unknown data. */ +const char *upb_msg_getunknown(const upb_msg *msg, size_t *len); + +/** Hasbit access *************************************************************/ + +UPB_INLINE bool _upb_hasbit(const upb_msg *msg, size_t idx) { + return (*PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0; +} + +UPB_INLINE void _upb_sethas(const upb_msg *msg, size_t idx) { + (*PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8)); +} + +UPB_INLINE void _upb_clearhas(const upb_msg *msg, size_t idx) { + (*PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8))); +} + +UPB_INLINE size_t _upb_msg_hasidx(const upb_msglayout_field *f) { + UPB_ASSERT(f->presence > 0); + return f->presence; +} + +UPB_INLINE bool _upb_hasbit_field(const upb_msg *msg, + const upb_msglayout_field *f) { + return _upb_hasbit(msg, _upb_msg_hasidx(f)); +} + +UPB_INLINE void _upb_sethas_field(const upb_msg *msg, + const upb_msglayout_field *f) { + _upb_sethas(msg, _upb_msg_hasidx(f)); +} + +UPB_INLINE void _upb_clearhas_field(const upb_msg *msg, + const upb_msglayout_field *f) { + _upb_clearhas(msg, _upb_msg_hasidx(f)); +} + +/** Oneof case access *********************************************************/ + +UPB_INLINE uint32_t *_upb_oneofcase(upb_msg *msg, size_t case_ofs) { + return PTR_AT(msg, case_ofs, uint32_t); +} + +UPB_INLINE uint32_t _upb_getoneofcase(const void *msg, size_t case_ofs) { + return *PTR_AT(msg, case_ofs, uint32_t); +} + +UPB_INLINE size_t _upb_oneofcase_ofs(const upb_msglayout_field *f) { + UPB_ASSERT(f->presence < 0); + return ~(ptrdiff_t)f->presence; +} + +UPB_INLINE uint32_t *_upb_oneofcase_field(upb_msg *msg, + const upb_msglayout_field *f) { + return _upb_oneofcase(msg, _upb_oneofcase_ofs(f)); +} + +UPB_INLINE uint32_t _upb_getoneofcase_field(const upb_msg *msg, + const upb_msglayout_field *f) { + return _upb_getoneofcase(msg, _upb_oneofcase_ofs(f)); +} + +UPB_INLINE bool _upb_has_submsg_nohasbit(const upb_msg *msg, size_t ofs) { + return *PTR_AT(msg, ofs, const upb_msg*) != NULL; +} + +UPB_INLINE bool _upb_isrepeated(const upb_msglayout_field *field) { + return (field->label & 3) == UPB_LABEL_REPEATED; +} + +UPB_INLINE bool _upb_repeated_or_map(const upb_msglayout_field *field) { + return field->label >= UPB_LABEL_REPEATED; +} + +/** upb_array *****************************************************************/ + +/* Our internal representation for repeated fields. */ +typedef struct { + uintptr_t data; /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */ + size_t len; /* Measured in elements. */ + size_t size; /* Measured in elements. */ + uint64_t junk; +} upb_array; + +UPB_INLINE const void *_upb_array_constptr(const upb_array *arr) { + UPB_ASSERT((arr->data & 7) <= 4); + return (void*)(arr->data & ~(uintptr_t)7); +} + +UPB_INLINE uintptr_t _upb_array_tagptr(void* ptr, int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 <= 4); + return (uintptr_t)ptr | elem_size_lg2; +} + +UPB_INLINE void *_upb_array_ptr(upb_array *arr) { + return (void*)_upb_array_constptr(arr); +} + +UPB_INLINE uintptr_t _upb_tag_arrptr(void* ptr, int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 <= 4); + UPB_ASSERT(((uintptr_t)ptr & 7) == 0); + return (uintptr_t)ptr | (unsigned)elem_size_lg2; +} + +UPB_INLINE upb_array *_upb_array_new(upb_arena *a, size_t init_size, + int elem_size_lg2) { + const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_array), 8); + const size_t bytes = sizeof(upb_array) + (init_size << elem_size_lg2); + upb_array *arr = (upb_array*)upb_arena_malloc(a, bytes); + if (!arr) return NULL; + arr->data = _upb_tag_arrptr(UPB_PTR_AT(arr, arr_size, void), elem_size_lg2); + arr->len = 0; + arr->size = init_size; + return arr; +} + +/* Resizes the capacity of the array to be at least min_size. */ +bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena); + +/* Fallback functions for when the accessors require a resize. */ +void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size, + int elem_size_lg2, upb_arena *arena); +bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value, + int elem_size_lg2, upb_arena *arena); + +UPB_INLINE bool _upb_array_reserve(upb_array *arr, size_t size, + upb_arena *arena) { + if (arr->size < size) return _upb_array_realloc(arr, size, arena); + return true; +} + +UPB_INLINE bool _upb_array_resize(upb_array *arr, size_t size, + upb_arena *arena) { + if (!_upb_array_reserve(arr, size, arena)) return false; + arr->len = size; + return true; +} + +UPB_INLINE const void *_upb_array_accessor(const void *msg, size_t ofs, + size_t *size) { + const upb_array *arr = *PTR_AT(msg, ofs, const upb_array*); + if (arr) { + if (size) *size = arr->len; + return _upb_array_constptr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} + +UPB_INLINE void *_upb_array_mutable_accessor(void *msg, size_t ofs, + size_t *size) { + upb_array *arr = *PTR_AT(msg, ofs, upb_array*); + if (arr) { + if (size) *size = arr->len; + return _upb_array_ptr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} + +UPB_INLINE void *_upb_array_resize_accessor2(void *msg, size_t ofs, size_t size, + int elem_size_lg2, + upb_arena *arena) { + upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array *); + upb_array *arr = *arr_ptr; + if (!arr || arr->size < size) { + return _upb_array_resize_fallback(arr_ptr, size, elem_size_lg2, arena); + } + arr->len = size; + return _upb_array_ptr(arr); +} + +UPB_INLINE bool _upb_array_append_accessor2(void *msg, size_t ofs, + int elem_size_lg2, + const void *value, + upb_arena *arena) { + upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array *); + size_t elem_size = 1 << elem_size_lg2; + upb_array *arr = *arr_ptr; + void *ptr; + if (!arr || arr->len == arr->size) { + return _upb_array_append_fallback(arr_ptr, value, elem_size_lg2, arena); + } + ptr = _upb_array_ptr(arr); + memcpy(PTR_AT(ptr, arr->len * elem_size, char), value, elem_size); + arr->len++; + return true; +} + +/* Used by old generated code, remove once all code has been regenerated. */ +UPB_INLINE int _upb_sizelg2(upb_fieldtype_t type) { + switch (type) { + case UPB_TYPE_BOOL: + return 0; + case UPB_TYPE_FLOAT: + case UPB_TYPE_INT32: + case UPB_TYPE_UINT32: + case UPB_TYPE_ENUM: + return 2; + case UPB_TYPE_MESSAGE: + return UPB_SIZE(2, 3); + case UPB_TYPE_DOUBLE: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT64: + return 3; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + return UPB_SIZE(3, 4); + } + UPB_UNREACHABLE(); +} +UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size, + upb_fieldtype_t type, + upb_arena *arena) { + return _upb_array_resize_accessor2(msg, ofs, size, _upb_sizelg2(type), arena); +} +UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs, + size_t elem_size, upb_fieldtype_t type, + const void *value, + upb_arena *arena) { + (void)elem_size; + return _upb_array_append_accessor2(msg, ofs, _upb_sizelg2(type), value, + arena); +} + +/** upb_map *******************************************************************/ + +/* Right now we use strmaps for everything. We'll likely want to use + * integer-specific maps for integer-keyed maps.*/ +typedef struct { + /* Size of key and val, based on the map type. Strings are represented as '0' + * because they must be handled specially. */ + char key_size; + char val_size; + + upb_strtable table; +} upb_map; + +/* Map entries aren't actually stored, they are only used during parsing. For + * parsing, it helps a lot if all map entry messages have the same layout. + * The compiler and def.c must ensure that all map entries have this layout. */ +typedef struct { + upb_msg_internal internal; + union { + upb_strview str; /* For str/bytes. */ + upb_value val; /* For all other types. */ + } k; + union { + upb_strview str; /* For str/bytes. */ + upb_value val; /* For all other types. */ + } v; +} upb_map_entry; + +/* Creates a new map on the given arena with this key/value type. */ +upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size); + +/* Converting between internal table representation and user values. + * + * _upb_map_tokey() and _upb_map_fromkey() are inverses. + * _upb_map_tovalue() and _upb_map_fromvalue() are inverses. + * + * These functions account for the fact that strings are treated differently + * from other types when stored in a map. + */ + +UPB_INLINE upb_strview _upb_map_tokey(const void *key, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + return *(upb_strview*)key; + } else { + return upb_strview_make((const char*)key, size); + } +} + +UPB_INLINE void _upb_map_fromkey(upb_strview key, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + memcpy(out, &key, sizeof(key)); + } else { + memcpy(out, key.data, size); + } +} + +UPB_INLINE bool _upb_map_tovalue(const void *val, size_t size, upb_value *msgval, + upb_arena *a) { + if (size == UPB_MAPTYPE_STRING) { + upb_strview *strp = (upb_strview*)upb_arena_malloc(a, sizeof(*strp)); + if (!strp) return false; + *strp = *(upb_strview*)val; + *msgval = upb_value_ptr(strp); + } else { + memcpy(msgval, val, size); + } + return true; +} + +UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + const upb_strview *strp = (const upb_strview*)upb_value_getptr(val); + memcpy(out, strp, sizeof(upb_strview)); + } else { + memcpy(out, &val, size); + } +} + +/* Map operations, shared by reflection and generated code. */ + +UPB_INLINE size_t _upb_map_size(const upb_map *map) { + return map->table.t.count; +} + +UPB_INLINE bool _upb_map_get(const upb_map *map, const void *key, + size_t key_size, void *val, size_t val_size) { + upb_value tabval; + upb_strview k = _upb_map_tokey(key, key_size); + bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval); + if (ret && val) { + _upb_map_fromvalue(tabval, val, val_size); + } + return ret; +} + +UPB_INLINE void* _upb_map_next(const upb_map *map, size_t *iter) { + upb_strtable_iter it; + it.t = &map->table; + it.index = *iter; + upb_strtable_next(&it); + *iter = it.index; + if (upb_strtable_done(&it)) return NULL; + return (void*)str_tabent(&it); +} + +UPB_INLINE bool _upb_map_set(upb_map *map, const void *key, size_t key_size, + void *val, size_t val_size, upb_arena *arena) { + upb_strview strkey = _upb_map_tokey(key, key_size); + upb_value tabval = {0}; + if (!_upb_map_tovalue(val, val_size, &tabval, arena)) return false; + upb_alloc *a = upb_arena_alloc(arena); + + /* TODO(haberman): add overwrite operation to minimize number of lookups. */ + upb_strtable_remove3(&map->table, strkey.data, strkey.size, NULL, a); + return upb_strtable_insert3(&map->table, strkey.data, strkey.size, tabval, a); +} + +UPB_INLINE bool _upb_map_delete(upb_map *map, const void *key, size_t key_size) { + upb_strview k = _upb_map_tokey(key, key_size); + return upb_strtable_remove3(&map->table, k.data, k.size, NULL, NULL); +} + +UPB_INLINE void _upb_map_clear(upb_map *map) { + upb_strtable_clear(&map->table); +} + +/* Message map operations, these get the map from the message first. */ + +UPB_INLINE size_t _upb_msg_map_size(const upb_msg *msg, size_t ofs) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + return map ? _upb_map_size(map) : 0; +} + +UPB_INLINE bool _upb_msg_map_get(const upb_msg *msg, size_t ofs, + const void *key, size_t key_size, void *val, + size_t val_size) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + if (!map) return false; + return _upb_map_get(map, key, key_size, val, val_size); +} + +UPB_INLINE void *_upb_msg_map_next(const upb_msg *msg, size_t ofs, + size_t *iter) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + if (!map) return NULL; + return _upb_map_next(map, iter); +} + +UPB_INLINE bool _upb_msg_map_set(upb_msg *msg, size_t ofs, const void *key, + size_t key_size, void *val, size_t val_size, + upb_arena *arena) { + upb_map **map = PTR_AT(msg, ofs, upb_map *); + if (!*map) { + *map = _upb_map_new(arena, key_size, val_size); + } + return _upb_map_set(*map, key, key_size, val, val_size, arena); +} + +UPB_INLINE bool _upb_msg_map_delete(upb_msg *msg, size_t ofs, const void *key, + size_t key_size) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + if (!map) return false; + return _upb_map_delete(map, key, key_size); +} + +UPB_INLINE void _upb_msg_map_clear(upb_msg *msg, size_t ofs) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + if (!map) return; + _upb_map_clear(map); +} + +/* Accessing map key/value from a pointer, used by generated code only. */ + +UPB_INLINE void _upb_msg_map_key(const void* msg, void* key, size_t size) { + const upb_tabent *ent = (const upb_tabent*)msg; + uint32_t u32len; + upb_strview k; + k.data = upb_tabstr(ent->key, &u32len); + k.size = u32len; + _upb_map_fromkey(k, key, size); +} + +UPB_INLINE void _upb_msg_map_value(const void* msg, void* val, size_t size) { + const upb_tabent *ent = (const upb_tabent*)msg; + upb_value v; + _upb_value_setval(&v, ent->val.val); + _upb_map_fromvalue(v, val, size); +} + +UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, size_t size) { + upb_tabent *ent = (upb_tabent*)msg; + /* This is like _upb_map_tovalue() except the entry already exists so we can + * reuse the allocated upb_strview for string fields. */ + if (size == UPB_MAPTYPE_STRING) { + upb_strview *strp = (upb_strview*)(uintptr_t)ent->val.val; + memcpy(strp, val, sizeof(*strp)); + } else { + memcpy(&ent->val.val, val, size); + } +} + +/** _upb_mapsorter *************************************************************/ + +/* _upb_mapsorter sorts maps and provides ordered iteration over the entries. + * Since maps can be recursive (map values can be messages which contain other maps). + * _upb_mapsorter can contain a stack of maps. */ + +typedef struct { + upb_tabent const**entries; + int size; + int cap; +} _upb_mapsorter; + +typedef struct { + int start; + int pos; + int end; +} _upb_sortedmap; + +UPB_INLINE void _upb_mapsorter_init(_upb_mapsorter *s) { + s->entries = NULL; + s->size = 0; + s->cap = 0; +} + +UPB_INLINE void _upb_mapsorter_destroy(_upb_mapsorter *s) { + if (s->entries) free(s->entries); +} + +bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type, + const upb_map *map, _upb_sortedmap *sorted); + +UPB_INLINE void _upb_mapsorter_popmap(_upb_mapsorter *s, _upb_sortedmap *sorted) { + s->size = sorted->start; +} + +UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter *s, const upb_map *map, + _upb_sortedmap *sorted, + upb_map_entry *ent) { + if (sorted->pos == sorted->end) return false; + const upb_tabent *tabent = s->entries[sorted->pos++]; + upb_strview key = upb_tabstrview(tabent->key); + _upb_map_fromkey(key, &ent->k, map->key_size); + upb_value val = {tabent->val.val}; + _upb_map_fromvalue(val, &ent->v, map->val_size); + return true; +} + +#undef PTR_AT + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MSG_H_ */ + +/* Must be last. */ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /* If set, strings will alias the input buffer instead of copying into the + * arena. */ + UPB_DECODE_ALIAS = 1, +}; + +#define UPB_DECODE_MAXDEPTH(depth) ((depth) << 16) + +bool _upb_decode(const char *buf, size_t size, upb_msg *msg, + const upb_msglayout *l, upb_arena *arena, int options); + +UPB_INLINE +bool upb_decode(const char *buf, size_t size, upb_msg *msg, + const upb_msglayout *l, upb_arena *arena) { + return _upb_decode(buf, size, msg, l, arena, 0); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_DECODE_H_ */ +/* +** Internal implementation details of the decoder that are shared between +** decode.c and decode_fast.c. +*/ + +#ifndef UPB_DECODE_INT_H_ +#define UPB_DECODE_INT_H_ + +#include + + +#ifndef UPB_INT_H_ +#define UPB_INT_H_ + + +struct mem_block; +typedef struct mem_block mem_block; + +struct upb_arena { + _upb_arena_head head; + uint32_t *cleanups; + + /* Allocator to allocate arena blocks. We are responsible for freeing these + * when we are destroyed. */ + upb_alloc *block_alloc; + uint32_t last_size; + + /* When multiple arenas are fused together, each arena points to a parent + * arena (root points to itself). The root tracks how many live arenas + * reference it. */ + uint32_t refcount; /* Only used when a->parent == a */ + struct upb_arena *parent; + + /* Linked list of blocks to free/cleanup. */ + mem_block *freelist, *freelist_tail; +}; + +#endif /* UPB_INT_H_ */ + +/* Must be last. */ + +#define DECODE_NOGROUP (uint32_t)-1 + +typedef struct upb_decstate { + const char *end; /* Can read up to 16 bytes slop beyond this. */ + const char *limit_ptr; /* = end + UPB_MIN(limit, 0) */ + upb_msg *unknown_msg; /* If non-NULL, add unknown data at buffer flip. */ + const char *unknown; /* Start of unknown data. */ + int limit; /* Submessage limit relative to end. */ + int depth; + uint32_t end_group; /* field number of END_GROUP tag, else DECODE_NOGROUP */ + bool alias; + char patch[32]; + upb_arena arena; + jmp_buf err; +} upb_decstate; + +/* Error function that will abort decoding with longjmp(). We can't declare this + * UPB_NORETURN, even though it is appropriate, because if we do then compilers + * will "helpfully" refuse to tailcall to it + * (see: https://stackoverflow.com/a/55657013), which will defeat a major goal + * of our optimizations. That is also why we must declare it in a separate file, + * otherwise the compiler will see that it calls longjmp() and deduce that it is + * noreturn. */ +const char *fastdecode_err(upb_decstate *d); + +extern const uint8_t upb_utf8_offsets[]; + +UPB_INLINE +bool decode_verifyutf8_inl(const char *buf, int len) { + int i, j; + uint8_t offset; + + i = 0; + while (i < len) { + offset = upb_utf8_offsets[(uint8_t)buf[i]]; + if (offset == 0 || i + offset > len) { + return false; + } + for (j = i + 1; j < i + offset; j++) { + if ((buf[j] & 0xc0) != 0x80) { + return false; + } + } + i += offset; + } + return i == len; +} + +/* x86-64 pointers always have the high 16 bits matching. So we can shift + * left 8 and right 8 without loss of information. */ +UPB_INLINE intptr_t decode_totable(const upb_msglayout *tablep) { + return ((intptr_t)tablep << 8) | tablep->table_mask; +} + +UPB_INLINE const upb_msglayout *decode_totablep(intptr_t table) { + return (const upb_msglayout*)(table >> 8); +} + +UPB_INLINE +const char *decode_isdonefallback_inl(upb_decstate *d, const char *ptr, + int overrun) { + if (overrun < d->limit) { + /* Need to copy remaining data into patch buffer. */ + UPB_ASSERT(overrun < 16); + if (d->unknown_msg) { + if (!_upb_msg_addunknown(d->unknown_msg, d->unknown, ptr - d->unknown, + &d->arena)) { + return NULL; + } + d->unknown = &d->patch[0] + overrun; + } + memset(d->patch + 16, 0, 16); + memcpy(d->patch, d->end, 16); + ptr = &d->patch[0] + overrun; + d->end = &d->patch[16]; + d->limit -= 16; + d->limit_ptr = d->end + d->limit; + d->alias = false; + UPB_ASSERT(ptr < d->limit_ptr); + return ptr; + } else { + return NULL; + } +} + +const char *decode_isdonefallback(upb_decstate *d, const char *ptr, + int overrun); + +UPB_INLINE +bool decode_isdone(upb_decstate *d, const char **ptr) { + int overrun = *ptr - d->end; + if (UPB_LIKELY(*ptr < d->limit_ptr)) { + return false; + } else if (UPB_LIKELY(overrun == d->limit)) { + return true; + } else { + *ptr = decode_isdonefallback(d, *ptr, overrun); + return false; + } +} + +UPB_INLINE +const char *fastdecode_tagdispatch(upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, + uint64_t hasbits, uint32_t tag) { + const upb_msglayout *table_p = decode_totablep(table); + uint8_t mask = table; + uint64_t data; + size_t idx = tag & mask; + UPB_ASSUME((idx & 7) == 0); + idx >>= 3; + data = table_p->fasttable[idx].field_data ^ tag; + return table_p->fasttable[idx].field_parser(d, ptr, msg, table, hasbits, data); +} + +UPB_INLINE uint32_t fastdecode_loadtag(const char* ptr) { + uint16_t tag; + memcpy(&tag, ptr, 2); + return tag; +} + +UPB_INLINE void decode_checklimit(upb_decstate *d) { + UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit)); +} + +UPB_INLINE int decode_pushlimit(upb_decstate *d, const char *ptr, int size) { + int limit = size + (int)(ptr - d->end); + int delta = d->limit - limit; + decode_checklimit(d); + d->limit = limit; + d->limit_ptr = d->end + UPB_MIN(0, limit); + decode_checklimit(d); + return delta; +} + +UPB_INLINE void decode_poplimit(upb_decstate *d, const char *ptr, + int saved_delta) { + UPB_ASSERT(ptr - d->end == d->limit); + decode_checklimit(d); + d->limit += saved_delta; + d->limit_ptr = d->end + UPB_MIN(0, d->limit); + decode_checklimit(d); +} + + +#endif /* UPB_DECODE_INT_H_ */ +/* +** upb_encode: parsing into a upb_msg using a upb_msglayout. +*/ + +#ifndef UPB_ENCODE_H_ +#define UPB_ENCODE_H_ + + +/* Must be last. */ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /* If set, the results of serializing will be deterministic across all + * instances of this binary. There are no guarantees across different + * binary builds. + * + * If your proto contains maps, the encoder will need to malloc()/free() + * memory during encode. */ + UPB_ENCODE_DETERMINISTIC = 1, + + /* When set, unknown fields are not printed. */ + UPB_ENCODE_SKIPUNKNOWN = 2, +}; + +#define UPB_ENCODE_MAXDEPTH(depth) ((depth) << 16) + +char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options, + upb_arena *arena, size_t *size); + +UPB_INLINE char *upb_encode(const void *msg, const upb_msglayout *l, + upb_arena *arena, size_t *size) { + return upb_encode_ex(msg, l, 0, arena, size); +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* UPB_ENCODE_H_ */ +// These are the specialized field parser functions for the fast parser. +// Generated tables will refer to these by name. +// +// The function names are encoded with names like: +// +// // 123 4 +// upb_pss_1bt(); // Parse singular string, 1 byte tag. +// +// In position 1: +// - 'p' for parse, most function use this +// - 'c' for copy, for when we are copying strings instead of aliasing +// +// In position 2 (cardinality): +// - 's' for singular, with or without hasbit +// - 'o' for oneof +// - 'r' for non-packed repeated +// - 'p' for packed repeated +// +// In position 3 (type): +// - 'b1' for bool +// - 'v4' for 4-byte varint +// - 'v8' for 8-byte varint +// - 'z4' for zig-zag-encoded 4-byte varint +// - 'z8' for zig-zag-encoded 8-byte varint +// - 'f4' for 4-byte fixed +// - 'f8' for 8-byte fixed +// - 'm' for sub-message +// - 's' for string (validate UTF-8) +// - 'b' for bytes +// +// In position 4 (tag length): +// - '1' for one-byte tags (field numbers 1-15) +// - '2' for two-byte tags (field numbers 16-2048) + +#ifndef UPB_DECODE_FAST_H_ +#define UPB_DECODE_FAST_H_ + + +struct upb_decstate; + +// The fallback, generic parsing function that can handle any field type. +// This just uses the regular (non-fast) parser to parse a single field. +const char *fastdecode_generic(struct upb_decstate *d, const char *ptr, + upb_msg *msg, intptr_t table, uint64_t hasbits, + uint64_t data); + +#define UPB_PARSE_PARAMS \ + struct upb_decstate *d, const char *ptr, upb_msg *msg, intptr_t table, \ + uint64_t hasbits, uint64_t data + +/* primitive fields ***********************************************************/ + +#define F(card, type, valbytes, tagbytes) \ + const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS); + +#define TYPES(card, tagbytes) \ + F(card, b, 1, tagbytes) \ + F(card, v, 4, tagbytes) \ + F(card, v, 8, tagbytes) \ + F(card, z, 4, tagbytes) \ + F(card, z, 8, tagbytes) \ + F(card, f, 4, tagbytes) \ + F(card, f, 8, tagbytes) + +#define TAGBYTES(card) \ + TYPES(card, 1) \ + TYPES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) +TAGBYTES(p) + +#undef F +#undef TYPES +#undef TAGBYTES + +/* string fields **************************************************************/ + +#define F(card, tagbytes, type) \ + const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); \ + const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); + +#define UTF8(card, tagbytes) \ + F(card, tagbytes, s) \ + F(card, tagbytes, b) + +#define TAGBYTES(card) \ + UTF8(card, 1) \ + UTF8(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef F +#undef TAGBYTES + +/* sub-message fields *********************************************************/ + +#define F(card, tagbytes, size_ceil, ceil_arg) \ + const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b(UPB_PARSE_PARAMS); + +#define SIZES(card, tagbytes) \ + F(card, tagbytes, 64, 64) \ + F(card, tagbytes, 128, 128) \ + F(card, tagbytes, 192, 192) \ + F(card, tagbytes, 256, 256) \ + F(card, tagbytes, max, -1) + +#define TAGBYTES(card) \ + SIZES(card, 1) \ + SIZES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef TAGBYTES +#undef SIZES +#undef F + +#undef UPB_PARSE_PARAMS + +#endif /* UPB_DECODE_FAST_H_ */ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ + + + +#ifdef __cplusplus +extern "C" { +#endif + +struct google_protobuf_FileDescriptorSet; +struct google_protobuf_FileDescriptorProto; +struct google_protobuf_DescriptorProto; +struct google_protobuf_DescriptorProto_ExtensionRange; +struct google_protobuf_DescriptorProto_ReservedRange; +struct google_protobuf_ExtensionRangeOptions; +struct google_protobuf_FieldDescriptorProto; +struct google_protobuf_OneofDescriptorProto; +struct google_protobuf_EnumDescriptorProto; +struct google_protobuf_EnumDescriptorProto_EnumReservedRange; +struct google_protobuf_EnumValueDescriptorProto; +struct google_protobuf_ServiceDescriptorProto; +struct google_protobuf_MethodDescriptorProto; +struct google_protobuf_FileOptions; +struct google_protobuf_MessageOptions; +struct google_protobuf_FieldOptions; +struct google_protobuf_OneofOptions; +struct google_protobuf_EnumOptions; +struct google_protobuf_EnumValueOptions; +struct google_protobuf_ServiceOptions; +struct google_protobuf_MethodOptions; +struct google_protobuf_UninterpretedOption; +struct google_protobuf_UninterpretedOption_NamePart; +struct google_protobuf_SourceCodeInfo; +struct google_protobuf_SourceCodeInfo_Location; +struct google_protobuf_GeneratedCodeInfo; +struct google_protobuf_GeneratedCodeInfo_Annotation; +typedef struct google_protobuf_FileDescriptorSet google_protobuf_FileDescriptorSet; +typedef struct google_protobuf_FileDescriptorProto google_protobuf_FileDescriptorProto; +typedef struct google_protobuf_DescriptorProto google_protobuf_DescriptorProto; +typedef struct google_protobuf_DescriptorProto_ExtensionRange google_protobuf_DescriptorProto_ExtensionRange; +typedef struct google_protobuf_DescriptorProto_ReservedRange google_protobuf_DescriptorProto_ReservedRange; +typedef struct google_protobuf_ExtensionRangeOptions google_protobuf_ExtensionRangeOptions; +typedef struct google_protobuf_FieldDescriptorProto google_protobuf_FieldDescriptorProto; +typedef struct google_protobuf_OneofDescriptorProto google_protobuf_OneofDescriptorProto; +typedef struct google_protobuf_EnumDescriptorProto google_protobuf_EnumDescriptorProto; +typedef struct google_protobuf_EnumDescriptorProto_EnumReservedRange google_protobuf_EnumDescriptorProto_EnumReservedRange; +typedef struct google_protobuf_EnumValueDescriptorProto google_protobuf_EnumValueDescriptorProto; +typedef struct google_protobuf_ServiceDescriptorProto google_protobuf_ServiceDescriptorProto; +typedef struct google_protobuf_MethodDescriptorProto google_protobuf_MethodDescriptorProto; +typedef struct google_protobuf_FileOptions google_protobuf_FileOptions; +typedef struct google_protobuf_MessageOptions google_protobuf_MessageOptions; +typedef struct google_protobuf_FieldOptions google_protobuf_FieldOptions; +typedef struct google_protobuf_OneofOptions google_protobuf_OneofOptions; +typedef struct google_protobuf_EnumOptions google_protobuf_EnumOptions; +typedef struct google_protobuf_EnumValueOptions google_protobuf_EnumValueOptions; +typedef struct google_protobuf_ServiceOptions google_protobuf_ServiceOptions; +typedef struct google_protobuf_MethodOptions google_protobuf_MethodOptions; +typedef struct google_protobuf_UninterpretedOption google_protobuf_UninterpretedOption; +typedef struct google_protobuf_UninterpretedOption_NamePart google_protobuf_UninterpretedOption_NamePart; +typedef struct google_protobuf_SourceCodeInfo google_protobuf_SourceCodeInfo; +typedef struct google_protobuf_SourceCodeInfo_Location google_protobuf_SourceCodeInfo_Location; +typedef struct google_protobuf_GeneratedCodeInfo google_protobuf_GeneratedCodeInfo; +typedef struct google_protobuf_GeneratedCodeInfo_Annotation google_protobuf_GeneratedCodeInfo_Annotation; +extern const upb_msglayout google_protobuf_FileDescriptorSet_msginit; +extern const upb_msglayout google_protobuf_FileDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_DescriptorProto_msginit; +extern const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit; +extern const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit; +extern const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit; +extern const upb_msglayout google_protobuf_FieldDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_OneofDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_EnumDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit; +extern const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_MethodDescriptorProto_msginit; +extern const upb_msglayout google_protobuf_FileOptions_msginit; +extern const upb_msglayout google_protobuf_MessageOptions_msginit; +extern const upb_msglayout google_protobuf_FieldOptions_msginit; +extern const upb_msglayout google_protobuf_OneofOptions_msginit; +extern const upb_msglayout google_protobuf_EnumOptions_msginit; +extern const upb_msglayout google_protobuf_EnumValueOptions_msginit; +extern const upb_msglayout google_protobuf_ServiceOptions_msginit; +extern const upb_msglayout google_protobuf_MethodOptions_msginit; +extern const upb_msglayout google_protobuf_UninterpretedOption_msginit; +extern const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit; +extern const upb_msglayout google_protobuf_SourceCodeInfo_msginit; +extern const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit; +extern const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit; +extern const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit; + +typedef enum { + google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1, + google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2, + google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3 +} google_protobuf_FieldDescriptorProto_Label; + +typedef enum { + google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1, + google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2, + google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3, + google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4, + google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5, + google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6, + google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7, + google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8, + google_protobuf_FieldDescriptorProto_TYPE_STRING = 9, + google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10, + google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11, + google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12, + google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13, + google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14, + google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15, + google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16, + google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17, + google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18 +} google_protobuf_FieldDescriptorProto_Type; + +typedef enum { + google_protobuf_FieldOptions_STRING = 0, + google_protobuf_FieldOptions_CORD = 1, + google_protobuf_FieldOptions_STRING_PIECE = 2 +} google_protobuf_FieldOptions_CType; + +typedef enum { + google_protobuf_FieldOptions_JS_NORMAL = 0, + google_protobuf_FieldOptions_JS_STRING = 1, + google_protobuf_FieldOptions_JS_NUMBER = 2 +} google_protobuf_FieldOptions_JSType; + +typedef enum { + google_protobuf_FileOptions_SPEED = 1, + google_protobuf_FileOptions_CODE_SIZE = 2, + google_protobuf_FileOptions_LITE_RUNTIME = 3 +} google_protobuf_FileOptions_OptimizeMode; + +typedef enum { + google_protobuf_MethodOptions_IDEMPOTENCY_UNKNOWN = 0, + google_protobuf_MethodOptions_NO_SIDE_EFFECTS = 1, + google_protobuf_MethodOptions_IDEMPOTENT = 2 +} google_protobuf_MethodOptions_IdempotencyLevel; + + +/* google.protobuf.FileDescriptorSet */ + +UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_new(upb_arena *arena) { + return (google_protobuf_FileDescriptorSet *)_upb_msg_new(&google_protobuf_FileDescriptorSet_msginit, arena); +} +UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize(const google_protobuf_FileDescriptorSet *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_FileDescriptorSet_has_file(const google_protobuf_FileDescriptorSet *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet *msg, size_t *len) { return (const google_protobuf_FileDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } + +UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_mutable_file(google_protobuf_FileDescriptorSet *msg, size_t *len) { + return (google_protobuf_FileDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_resize_file(google_protobuf_FileDescriptorSet *msg, size_t len, upb_arena *arena) { + return (google_protobuf_FileDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorSet_add_file(google_protobuf_FileDescriptorSet *msg, upb_arena *arena) { + struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.FileDescriptorProto */ + +UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_new(upb_arena *arena) { + return (google_protobuf_FileDescriptorProto *)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize(const google_protobuf_FileDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FileDescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } +UPB_INLINE upb_strview const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_message_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); } +UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_enum_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(44, 88)); } +UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_service(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(48, 96)); } +UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_ServiceDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(48, 96), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_extension(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(52, 104)); } +UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(52, 104), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_FileOptions*); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 64), const google_protobuf_SourceCodeInfo*); } +UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(56, 112), len); } +UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(60, 120), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); } + +UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; +} +UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) { + return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len); +} +UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { + return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(36, 72), len, UPB_SIZE(3, 4), arena); +} +UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto *msg, upb_strview val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(36, 72), UPB_SIZE(3, 4), &val, + arena); +} +UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_mutable_message_type(google_protobuf_FileDescriptorProto *msg, size_t *len) { + return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len); +} +UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_resize_message_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(40, 80), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescriptorProto_add_message_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(40, 80), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_mutable_enum_type(google_protobuf_FileDescriptorProto *msg, size_t *len) { + return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len); +} +UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_resize_enum_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(44, 88), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescriptorProto_add_enum_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(44, 88), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_mutable_service(google_protobuf_FileDescriptorProto *msg, size_t *len) { + return (google_protobuf_ServiceDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 96), len); +} +UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_resize_service(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_ServiceDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(48, 96), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDescriptorProto_add_service(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(48, 96), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_mutable_extension(google_protobuf_FileDescriptorProto *msg, size_t *len) { + return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 104), len); +} +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_resize_extension(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(52, 104), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDescriptorProto_add_extension(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(52, 104), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_FileOptions*) = value; +} +UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_FileOptions* sub = (struct google_protobuf_FileOptions*)google_protobuf_FileDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FileOptions*)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_FileDescriptorProto_set_options(msg, sub); + } + return sub; +} +UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(32, 64), google_protobuf_SourceCodeInfo*) = value; +} +UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_SourceCodeInfo* sub = (struct google_protobuf_SourceCodeInfo*)google_protobuf_FileDescriptorProto_source_code_info(msg); + if (sub == NULL) { + sub = (struct google_protobuf_SourceCodeInfo*)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena); + if (!sub) return NULL; + google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub); + } + return sub; +} +UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) { + return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 112), len); +} +UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { + return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(56, 112), len, 2, arena); +} +UPB_INLINE bool google_protobuf_FileDescriptorProto_add_public_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(56, 112), 2, &val, + arena); +} +UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) { + return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(60, 120), len); +} +UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { + return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(60, 120), len, 2, arena); +} +UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(60, 120), 2, &val, + arena); +} +UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value; +} + +/* google.protobuf.DescriptorProto */ + +UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_new(upb_arena *arena) { + return (google_protobuf_DescriptorProto *)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_DescriptorProto_serialize(const google_protobuf_DescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_DescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_field(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } +UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_nested_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); } +UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_enum_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(24, 48)); } +UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_extension_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 56)); } +UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ExtensionRange* const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_extension(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(32, 64)); } +UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(32, 64), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_MessageOptions*); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_oneof_decl(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(36, 72)); } +UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_OneofDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_reserved_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); } +UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); } +UPB_INLINE upb_strview const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); } + +UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_field(google_protobuf_DescriptorProto *msg, size_t *len) { + return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); +} +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_field(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_field(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_mutable_nested_type(google_protobuf_DescriptorProto *msg, size_t *len) { + return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len); +} +UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_resize_nested_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_add_nested_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(20, 40), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_mutable_enum_type(google_protobuf_DescriptorProto *msg, size_t *len) { + return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len); +} +UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_resize_enum_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_DescriptorProto_add_enum_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(24, 48), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_mutable_extension_range(google_protobuf_DescriptorProto *msg, size_t *len) { + return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len); +} +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_resize_extension_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(28, 56), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_add_extension_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(28, 56), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_extension(google_protobuf_DescriptorProto *msg, size_t *len) { + return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 64), len); +} +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_extension(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(32, 64), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_extension(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(32, 64), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_MessageOptions*) = value; +} +UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProto_mutable_options(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_MessageOptions* sub = (struct google_protobuf_MessageOptions*)google_protobuf_DescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_MessageOptions*)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_DescriptorProto_set_options(msg, sub); + } + return sub; +} +UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_mutable_oneof_decl(google_protobuf_DescriptorProto *msg, size_t *len) { + return (google_protobuf_OneofDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len); +} +UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_resize_oneof_decl(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_OneofDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(36, 72), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_DescriptorProto_add_oneof_decl(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(36, 72), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_mutable_reserved_range(google_protobuf_DescriptorProto *msg, size_t *len) { + return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len); +} +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_resize_reserved_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(40, 80), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_add_reserved_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(40, 80), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE upb_strview* google_protobuf_DescriptorProto_mutable_reserved_name(google_protobuf_DescriptorProto *msg, size_t *len) { + return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len); +} +UPB_INLINE upb_strview* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { + return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(44, 88), len, UPB_SIZE(3, 4), arena); +} +UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto *msg, upb_strview val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(44, 88), UPB_SIZE(3, 4), &val, + arena); +} + +/* google.protobuf.DescriptorProto.ExtensionRange */ + +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_new(upb_arena *arena) { + return (google_protobuf_DescriptorProto_ExtensionRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena); +} +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize(const google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } +UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const google_protobuf_ExtensionRangeOptions*); } + +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_start(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; +} +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(12, 16), google_protobuf_ExtensionRangeOptions*) = value; +} +UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_mutable_options(google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena) { + struct google_protobuf_ExtensionRangeOptions* sub = (struct google_protobuf_ExtensionRangeOptions*)google_protobuf_DescriptorProto_ExtensionRange_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_ExtensionRangeOptions*)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub); + } + return sub; +} + +/* google.protobuf.DescriptorProto.ReservedRange */ + +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_new(upb_arena *arena) { + return (google_protobuf_DescriptorProto_ReservedRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena); +} +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize(const google_protobuf_DescriptorProto_ReservedRange *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } + +UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_start(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; +} + +/* google.protobuf.ExtensionRangeOptions */ + +UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_new(upb_arena *arena) { + return (google_protobuf_ExtensionRangeOptions *)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena); +} +UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize(const google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } + +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_resize_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ExtensionRangeOptions_add_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.FieldDescriptorProto */ + +UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_new(upb_arena *arena) { + return (google_protobuf_FieldDescriptorProto *)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_protobuf_FieldDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), int32_t); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 7); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 8); } +UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(64, 104), const google_protobuf_FieldOptions*); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 9); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 10); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 11); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool); } + +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(12, 12), int32_t) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 6); + *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 7); + *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) { + _upb_sethas(msg, 8); + *UPB_PTR_AT(msg, UPB_SIZE(64, 104), google_protobuf_FieldOptions*) = value; +} +UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FieldOptions*)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_FieldDescriptorProto_set_options(msg, sub); + } + return sub; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) { + _upb_sethas(msg, 9); + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 10); + *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) { + _upb_sethas(msg, 11); + *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool) = value; +} + +/* google.protobuf.OneofDescriptorProto */ + +UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_new(upb_arena *arena) { + return (google_protobuf_OneofDescriptorProto *)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize(const google_protobuf_OneofDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_OneofDescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_OneofOptions*); } + +UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_OneofOptions*) = value; +} +UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_mutable_options(google_protobuf_OneofDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_OneofOptions* sub = (struct google_protobuf_OneofOptions*)google_protobuf_OneofDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_OneofOptions*)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_OneofDescriptorProto_set_options(msg, sub); + } + return sub; +} + +/* google.protobuf.EnumDescriptorProto */ + +UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_new(upb_arena *arena) { + return (google_protobuf_EnumDescriptorProto *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize(const google_protobuf_EnumDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumDescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_value(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } +UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumValueDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } +UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_EnumOptions*); } +UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_reserved_range(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); } +UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto_EnumReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); } +UPB_INLINE upb_strview const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); } + +UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_mutable_value(google_protobuf_EnumDescriptorProto *msg, size_t *len) { + return (google_protobuf_EnumValueDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); +} +UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_resize_value(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_EnumValueDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumDescriptorProto_add_value(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_EnumOptions*) = value; +} +UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_mutable_options(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_EnumOptions* sub = (struct google_protobuf_EnumOptions*)google_protobuf_EnumDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_EnumOptions*)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_EnumDescriptorProto_set_options(msg, sub); + } + return sub; +} +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_mutable_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t *len) { + return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len); +} +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_resize_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_add_reserved_range(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(20, 40), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_mutable_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t *len) { + return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len); +} +UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) { + return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, UPB_SIZE(3, 4), arena); +} +UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto *msg, upb_strview val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(24, 48), UPB_SIZE(3, 4), &val, + arena); +} + +/* google.protobuf.EnumDescriptorProto.EnumReservedRange */ + +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_new(upb_arena *arena) { + return (google_protobuf_EnumDescriptorProto_EnumReservedRange *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena); +} +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } + +UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; +} + +/* google.protobuf.EnumValueDescriptorProto */ + +UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_new(upb_arena *arena) { + return (google_protobuf_EnumValueDescriptorProto *)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize(const google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); } +UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const google_protobuf_EnumValueOptions*); } + +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value; +} +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(16, 24), google_protobuf_EnumValueOptions*) = value; +} +UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_mutable_options(google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_EnumValueOptions* sub = (struct google_protobuf_EnumValueOptions*)google_protobuf_EnumValueDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_EnumValueOptions*)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_EnumValueDescriptorProto_set_options(msg, sub); + } + return sub; +} + +/* google.protobuf.ServiceDescriptorProto */ + +UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_new(upb_arena *arena) { + return (google_protobuf_ServiceDescriptorProto *)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize(const google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_method(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } +UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto *msg, size_t *len) { return (const google_protobuf_MethodDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } +UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_ServiceOptions*); } + +UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_mutable_method(google_protobuf_ServiceDescriptorProto *msg, size_t *len) { + return (google_protobuf_MethodDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); +} +UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_resize_method(google_protobuf_ServiceDescriptorProto *msg, size_t len, upb_arena *arena) { + return (google_protobuf_MethodDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_ServiceDescriptorProto_add_method(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_ServiceOptions*) = value; +} +UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_mutable_options(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_ServiceOptions* sub = (struct google_protobuf_ServiceOptions*)google_protobuf_ServiceDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_ServiceOptions*)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_ServiceDescriptorProto_set_options(msg, sub); + } + return sub; +} + +/* google.protobuf.MethodDescriptorProto */ + +UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_new(upb_arena *arena) { + return (google_protobuf_MethodDescriptorProto *)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize(const google_protobuf_MethodDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_MethodDescriptorProto_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_MethodOptions*); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); } + +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; +} +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value; +} +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_MethodOptions*) = value; +} +UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto *msg, upb_arena *arena) { + struct google_protobuf_MethodOptions* sub = (struct google_protobuf_MethodOptions*)google_protobuf_MethodDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_MethodOptions*)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena); + if (!sub) return NULL; + google_protobuf_MethodDescriptorProto_set_options(msg, sub); + } + return sub; +} +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; +} +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { + _upb_sethas(msg, 6); + *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value; +} + +/* google.protobuf.FileOptions */ + +UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_new(upb_arena *arena) { + return (google_protobuf_FileOptions *)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena); +} +UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FileOptions_serialize(const google_protobuf_FileOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FileOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE upb_strview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE upb_strview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(9, 9), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 7); } +UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(10, 10), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 8); } +UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(11, 11), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 9); } +UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 10); } +UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 11); } +UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 12); } +UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 13); } +UPB_INLINE upb_strview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 14); } +UPB_INLINE upb_strview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 15); } +UPB_INLINE upb_strview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 16); } +UPB_INLINE upb_strview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 17); } +UPB_INLINE upb_strview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 18); } +UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); } +UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 19); } +UPB_INLINE upb_strview google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 20); } +UPB_INLINE upb_strview google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(92, 168), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_uninterpreted_option(const google_protobuf_FileOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(100, 184)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(100, 184), len); } + +UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 6); + *UPB_PTR_AT(msg, UPB_SIZE(9, 9), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 7); + *UPB_PTR_AT(msg, UPB_SIZE(10, 10), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 8); + *UPB_PTR_AT(msg, UPB_SIZE(11, 11), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 9); + *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 10); + *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 11); + *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 12); + *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 13); + *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 14); + *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 15); + *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 16); + *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 17); + *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) { + _upb_sethas(msg, 18); + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 19); + *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_strview value) { + _upb_sethas(msg, 20); + *UPB_PTR_AT(msg, UPB_SIZE(92, 168), upb_strview) = value; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mutable_uninterpreted_option(google_protobuf_FileOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(100, 184), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_resize_uninterpreted_option(google_protobuf_FileOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(100, 184), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptions_add_uninterpreted_option(google_protobuf_FileOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(100, 184), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.MessageOptions */ + +UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_new(upb_arena *arena) { + return (google_protobuf_MessageOptions *)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena); +} +UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_MessageOptions_serialize(const google_protobuf_MessageOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_MessageOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } +UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_MessageOptions_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); } +UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool); } +UPB_INLINE bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool); } +UPB_INLINE bool google_protobuf_MessageOptions_has_uninterpreted_option(const google_protobuf_MessageOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 8)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(8, 8), len); } + +UPB_INLINE void google_protobuf_MessageOptions_set_message_set_wire_format(google_protobuf_MessageOptions *msg, bool value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; +} +UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value; +} +UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool) = value; +} +UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool) = value; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_mutable_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 8), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_resize_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 8), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOptions_add_uninterpreted_option(google_protobuf_MessageOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(8, 8), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.FieldOptions */ + +UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_new(upb_arena *arena) { + return (google_protobuf_FieldOptions *)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena); +} +UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FieldOptions_serialize(const google_protobuf_FieldOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FieldOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool); } +UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool); } +UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool); } +UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } +UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool); } +UPB_INLINE bool google_protobuf_FieldOptions_has_uninterpreted_option(const google_protobuf_FieldOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 16)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(16, 16), len); } + +UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOptions *msg, int32_t value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool) = value; +} +UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool) = value; +} +UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool) = value; +} +UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; +} +UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) { + _upb_sethas(msg, 6); + *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool) = value; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 16), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_resize_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOptions_add_uninterpreted_option(google_protobuf_FieldOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(16, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.OneofOptions */ + +UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_new(upb_arena *arena) { + return (google_protobuf_OneofOptions *)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena); +} +UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_OneofOptions_serialize(const google_protobuf_OneofOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_OneofOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_OneofOptions_has_uninterpreted_option(const google_protobuf_OneofOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } + +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mutable_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_resize_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOptions_add_uninterpreted_option(google_protobuf_OneofOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.EnumOptions */ + +UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_new(upb_arena *arena) { + return (google_protobuf_EnumOptions *)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena); +} +UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumOptions_serialize(const google_protobuf_EnumOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } +UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); } +UPB_INLINE bool google_protobuf_EnumOptions_has_uninterpreted_option(const google_protobuf_EnumOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } + +UPB_INLINE void google_protobuf_EnumOptions_set_allow_alias(google_protobuf_EnumOptions *msg, bool value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; +} +UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mutable_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_resize_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptions_add_uninterpreted_option(google_protobuf_EnumOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.EnumValueOptions */ + +UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_new(upb_arena *arena) { + return (google_protobuf_EnumValueOptions *)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena); +} +UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumValueOptions_serialize(const google_protobuf_EnumValueOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumValueOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } +UPB_INLINE bool google_protobuf_EnumValueOptions_has_uninterpreted_option(const google_protobuf_EnumValueOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } + +UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_EnumValueOptions *msg, bool value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_resize_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValueOptions_add_uninterpreted_option(google_protobuf_EnumValueOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.ServiceOptions */ + +UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_new(upb_arena *arena) { + return (google_protobuf_ServiceOptions *)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena); +} +UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_ServiceOptions_serialize(const google_protobuf_ServiceOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_ServiceOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } +UPB_INLINE bool google_protobuf_ServiceOptions_has_uninterpreted_option(const google_protobuf_ServiceOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } + +UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_ServiceOptions *msg, bool value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_mutable_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_resize_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOptions_add_uninterpreted_option(google_protobuf_ServiceOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.MethodOptions */ + +UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_new(upb_arena *arena) { + return (google_protobuf_MethodOptions *)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena); +} +UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_MethodOptions_serialize(const google_protobuf_MethodOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_MethodOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool); } +UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_MethodOptions_has_uninterpreted_option(const google_protobuf_MethodOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(12, 16)); } +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(12, 16), len); } + +UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value; +} +UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t *len) { + return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 16), len); +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_resize_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(12, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOptions_add_uninterpreted_option(google_protobuf_MethodOptions *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(12, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.UninterpretedOption */ + +UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_new(upb_arena *arena) { + return (google_protobuf_UninterpretedOption *)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); +} +UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_UninterpretedOption_serialize(const google_protobuf_UninterpretedOption *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_UninterpretedOption_has_name(const google_protobuf_UninterpretedOption *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(56, 80)); } +UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg, size_t *len) { return (const google_protobuf_UninterpretedOption_NamePart* const*)_upb_array_accessor(msg, UPB_SIZE(56, 80), len); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview); } + +UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_mutable_name(google_protobuf_UninterpretedOption *msg, size_t *len) { + return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 80), len); +} +UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_resize_name(google_protobuf_UninterpretedOption *msg, size_t len, upb_arena *arena) { + return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_resize_accessor2(msg, UPB_SIZE(56, 80), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_add_name(google_protobuf_UninterpretedOption *msg, upb_arena *arena) { + struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(56, 80), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview) = value; +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t) = value; +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t) = value; +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double) = value; +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_strview value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview) = value; +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_strview value) { + _upb_sethas(msg, 6); + *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview) = value; +} + +/* google.protobuf.UninterpretedOption.NamePart */ + +UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_new(upb_arena *arena) { + return (google_protobuf_UninterpretedOption_NamePart *)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena); +} +UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize(const google_protobuf_UninterpretedOption_NamePart *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } + +UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; +} + +/* google.protobuf.SourceCodeInfo */ + +UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_new(upb_arena *arena) { + return (google_protobuf_SourceCodeInfo *)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena); +} +UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize(const google_protobuf_SourceCodeInfo *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_SourceCodeInfo_has_location(const google_protobuf_SourceCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo *msg, size_t *len) { return (const google_protobuf_SourceCodeInfo_Location* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } + +UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_mutable_location(google_protobuf_SourceCodeInfo *msg, size_t *len) { + return (google_protobuf_SourceCodeInfo_Location**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_resize_location(google_protobuf_SourceCodeInfo *msg, size_t len, upb_arena *arena) { + return (google_protobuf_SourceCodeInfo_Location**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_add_location(google_protobuf_SourceCodeInfo *msg, upb_arena *arena) { + struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.SourceCodeInfo.Location */ + +UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_new(upb_arena *arena) { + return (google_protobuf_SourceCodeInfo_Location *)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena); +} +UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize(const google_protobuf_SourceCodeInfo_Location *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, arena, len); +} + +UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); } +UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); } +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } +UPB_INLINE upb_strview const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); } + +UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_path(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { + return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len); +} +UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_path(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) { + return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, 2, arena); +} +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_path(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(20, 40), 2, &val, + arena); +} +UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_span(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { + return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len); +} +UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_span(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) { + return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, 2, arena); +} +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_span(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(24, 48), 2, &val, + arena); +} +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; +} +UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { + return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len); +} +UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) { + return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(28, 56), len, UPB_SIZE(3, 4), arena); +} +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(28, 56), UPB_SIZE(3, 4), &val, + arena); +} + +/* google.protobuf.GeneratedCodeInfo */ + +UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_new(upb_arena *arena) { + return (google_protobuf_GeneratedCodeInfo *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_msginit, arena); +} +UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize(const google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_has_annotation(const google_protobuf_GeneratedCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo *msg, size_t *len) { return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } + +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_mutable_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t *len) { + return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_resize_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t len, upb_arena *arena) { + return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_add_annotation(google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena) { + struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* google.protobuf.GeneratedCodeInfo.Annotation */ + +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_new(upb_arena *arena) { + return (google_protobuf_GeneratedCodeInfo_Annotation *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena); +} +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse(const char *buf, size_t size, + upb_arena *arena) { + google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena); + return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena)) ? ret : NULL; +} +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena); + return (ret && _upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize(const google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, len); +} + +UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); } +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview); } +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } + +UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { + return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 32), len); +} +UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_resize_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t len, upb_arena *arena) { + return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 32), len, 2, arena); +} +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(20, 32), 2, &val, + arena); +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_strview value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview) = value; +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ */ +/* +** Defs are upb's internal representation of the constructs that can appear +** in a .proto file: +** +** - upb_msgdef: describes a "message" construct. +** - upb_fielddef: describes a message field. +** - upb_filedef: describes a .proto file and its defs. +** - upb_enumdef: describes an enum. +** - upb_oneofdef: describes a oneof. +** +** TODO: definitions of services. +*/ + +#ifndef UPB_DEF_H_ +#define UPB_DEF_H_ + + +/* Must be last. */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct upb_enumdef; +typedef struct upb_enumdef upb_enumdef; +struct upb_fielddef; +typedef struct upb_fielddef upb_fielddef; +struct upb_filedef; +typedef struct upb_filedef upb_filedef; +struct upb_msgdef; +typedef struct upb_msgdef upb_msgdef; +struct upb_oneofdef; +typedef struct upb_oneofdef upb_oneofdef; +struct upb_symtab; +typedef struct upb_symtab upb_symtab; + +typedef enum { + UPB_SYNTAX_PROTO2 = 2, + UPB_SYNTAX_PROTO3 = 3 +} upb_syntax_t; + +/* 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. + */ +typedef enum { + UPB_WELLKNOWN_UNSPECIFIED, + UPB_WELLKNOWN_ANY, + UPB_WELLKNOWN_FIELDMASK, + UPB_WELLKNOWN_DURATION, + UPB_WELLKNOWN_TIMESTAMP, + /* number wrappers */ + UPB_WELLKNOWN_DOUBLEVALUE, + UPB_WELLKNOWN_FLOATVALUE, + UPB_WELLKNOWN_INT64VALUE, + UPB_WELLKNOWN_UINT64VALUE, + UPB_WELLKNOWN_INT32VALUE, + UPB_WELLKNOWN_UINT32VALUE, + /* string wrappers */ + UPB_WELLKNOWN_STRINGVALUE, + UPB_WELLKNOWN_BYTESVALUE, + UPB_WELLKNOWN_BOOLVALUE, + UPB_WELLKNOWN_VALUE, + UPB_WELLKNOWN_LISTVALUE, + UPB_WELLKNOWN_STRUCT +} upb_wellknowntype_t; + +/* upb_fielddef ***************************************************************/ + +/* Maximum field number allowed for FieldDefs. This is an inherent limit of the + * protobuf wire format. */ +#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1) + +const char *upb_fielddef_fullname(const upb_fielddef *f); +upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f); +upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f); +upb_label_t upb_fielddef_label(const upb_fielddef *f); +uint32_t upb_fielddef_number(const upb_fielddef *f); +const char *upb_fielddef_name(const upb_fielddef *f); +const char *upb_fielddef_jsonname(const upb_fielddef *f); +bool upb_fielddef_isextension(const upb_fielddef *f); +bool upb_fielddef_lazy(const upb_fielddef *f); +bool upb_fielddef_packed(const upb_fielddef *f); +const upb_filedef *upb_fielddef_file(const upb_fielddef *f); +const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f); +const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f); +const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f); +uint32_t upb_fielddef_index(const upb_fielddef *f); +bool upb_fielddef_issubmsg(const upb_fielddef *f); +bool upb_fielddef_isstring(const upb_fielddef *f); +bool upb_fielddef_isseq(const upb_fielddef *f); +bool upb_fielddef_isprimitive(const upb_fielddef *f); +bool upb_fielddef_ismap(const upb_fielddef *f); +int64_t upb_fielddef_defaultint64(const upb_fielddef *f); +int32_t upb_fielddef_defaultint32(const upb_fielddef *f); +uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f); +uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f); +bool upb_fielddef_defaultbool(const upb_fielddef *f); +float upb_fielddef_defaultfloat(const upb_fielddef *f); +double upb_fielddef_defaultdouble(const upb_fielddef *f); +const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len); +bool upb_fielddef_hassubdef(const upb_fielddef *f); +bool upb_fielddef_haspresence(const upb_fielddef *f); +const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f); +const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f); +const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f); + +/* Internal only. */ +uint32_t upb_fielddef_selectorbase(const upb_fielddef *f); + +/* upb_oneofdef ***************************************************************/ + +typedef upb_inttable_iter upb_oneof_iter; + +const char *upb_oneofdef_name(const upb_oneofdef *o); +const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o); +uint32_t upb_oneofdef_index(const upb_oneofdef *o); +bool upb_oneofdef_issynthetic(const upb_oneofdef *o); +int upb_oneofdef_fieldcount(const upb_oneofdef *o); +const upb_fielddef *upb_oneofdef_field(const upb_oneofdef *o, int i); + +/* Oneof lookups: + * - ntof: look up a field by name. + * - ntofz: look up a field by name (as a null-terminated string). + * - itof: look up a field by number. */ +const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, + const char *name, size_t length); +UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o, + const char *name) { + return upb_oneofdef_ntof(o, name, strlen(name)); +} +const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num); + +/* DEPRECATED, slated for removal. */ +int upb_oneofdef_numfields(const upb_oneofdef *o); +void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o); +void upb_oneof_next(upb_oneof_iter *iter); +bool upb_oneof_done(upb_oneof_iter *iter); +upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter); +void upb_oneof_iter_setdone(upb_oneof_iter *iter); +bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1, + const upb_oneof_iter *iter2); +/* END DEPRECATED */ + +/* upb_msgdef *****************************************************************/ + +typedef upb_inttable_iter upb_msg_field_iter; +typedef upb_strtable_iter upb_msg_oneof_iter; + +/* Well-known field tag numbers for map-entry messages. */ +#define UPB_MAPENTRY_KEY 1 +#define UPB_MAPENTRY_VALUE 2 + +/* Well-known field tag numbers for Any messages. */ +#define UPB_ANY_TYPE 1 +#define UPB_ANY_VALUE 2 + +/* Well-known field tag numbers for timestamp messages. */ +#define UPB_DURATION_SECONDS 1 +#define UPB_DURATION_NANOS 2 + +/* Well-known field tag numbers for duration messages. */ +#define UPB_TIMESTAMP_SECONDS 1 +#define UPB_TIMESTAMP_NANOS 2 + +const char *upb_msgdef_fullname(const upb_msgdef *m); +const upb_filedef *upb_msgdef_file(const upb_msgdef *m); +const char *upb_msgdef_name(const upb_msgdef *m); +upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m); +bool upb_msgdef_mapentry(const upb_msgdef *m); +upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m); +bool upb_msgdef_iswrapper(const upb_msgdef *m); +bool upb_msgdef_isnumberwrapper(const upb_msgdef *m); +int upb_msgdef_fieldcount(const upb_msgdef *m); +int upb_msgdef_oneofcount(const upb_msgdef *m); +const upb_fielddef *upb_msgdef_field(const upb_msgdef *m, int i); +const upb_oneofdef *upb_msgdef_oneof(const upb_msgdef *m, int i); +const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i); +const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name, + size_t len); +const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, + size_t len); +const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m); + +UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m, + const char *name) { + return upb_msgdef_ntoo(m, name, strlen(name)); +} + +UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m, + const char *name) { + return upb_msgdef_ntof(m, name, strlen(name)); +} + +/* Internal-only. */ +size_t upb_msgdef_selectorcount(const upb_msgdef *m); +uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m); + +/* Lookup of either field or oneof by name. Returns whether either was found. + * If the return is true, then the found def will be set, and the non-found + * one set to NULL. */ +bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len, + const upb_fielddef **f, const upb_oneofdef **o); + +UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name, + const upb_fielddef **f, + const upb_oneofdef **o) { + return upb_msgdef_lookupname(m, name, strlen(name), f, o); +} + +/* Returns a field by either JSON name or regular proto name. */ +const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m, + const char *name, size_t len); + +/* DEPRECATED, slated for removal */ +int upb_msgdef_numfields(const upb_msgdef *m); +int upb_msgdef_numoneofs(const upb_msgdef *m); +int upb_msgdef_numrealoneofs(const upb_msgdef *m); +void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m); +void upb_msg_field_next(upb_msg_field_iter *iter); +bool upb_msg_field_done(const upb_msg_field_iter *iter); +upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter); +void upb_msg_field_iter_setdone(upb_msg_field_iter *iter); +bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1, + const upb_msg_field_iter * iter2); +void upb_msg_oneof_begin(upb_msg_oneof_iter * iter, const upb_msgdef *m); +void upb_msg_oneof_next(upb_msg_oneof_iter * iter); +bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter); +const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter); +void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter); +bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1, + const upb_msg_oneof_iter *iter2); +/* END DEPRECATED */ + +/* upb_enumdef ****************************************************************/ + +typedef upb_strtable_iter upb_enum_iter; + +const char *upb_enumdef_fullname(const upb_enumdef *e); +const char *upb_enumdef_name(const upb_enumdef *e); +const upb_filedef *upb_enumdef_file(const upb_enumdef *e); +int32_t upb_enumdef_default(const upb_enumdef *e); +int upb_enumdef_numvals(const upb_enumdef *e); + +/* Enum lookups: + * - ntoi: look up a name with specified length. + * - ntoiz: look up a name provided as a null-terminated string. + * - iton: look up an integer, returning the name as a null-terminated + * string. */ +bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len, + int32_t *num); +UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e, + const char *name, int32_t *num) { + return upb_enumdef_ntoi(e, name, strlen(name), num); +} +const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num); + +void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e); +void upb_enum_next(upb_enum_iter *iter); +bool upb_enum_done(upb_enum_iter *iter); +const char *upb_enum_iter_name(upb_enum_iter *iter); +int32_t upb_enum_iter_number(upb_enum_iter *iter); + +/* upb_filedef ****************************************************************/ + +const char *upb_filedef_name(const upb_filedef *f); +const char *upb_filedef_package(const upb_filedef *f); +const char *upb_filedef_phpprefix(const upb_filedef *f); +const char *upb_filedef_phpnamespace(const upb_filedef *f); +upb_syntax_t upb_filedef_syntax(const upb_filedef *f); +int upb_filedef_depcount(const upb_filedef *f); +int upb_filedef_msgcount(const upb_filedef *f); +int upb_filedef_enumcount(const upb_filedef *f); +const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i); +const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i); +const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i); +const upb_symtab *upb_filedef_symtab(const upb_filedef *f); + +/* upb_symtab *****************************************************************/ + +upb_symtab *upb_symtab_new(void); +void upb_symtab_free(upb_symtab* s); +const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym); +const upb_msgdef *upb_symtab_lookupmsg2( + const upb_symtab *s, const char *sym, size_t len); +const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym); +const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name); +const upb_filedef *upb_symtab_lookupfile2( + const upb_symtab *s, const char *name, size_t len); +int upb_symtab_filecount(const upb_symtab *s); +const upb_filedef *upb_symtab_addfile( + upb_symtab *s, const google_protobuf_FileDescriptorProto *file, + upb_status *status); +size_t _upb_symtab_bytesloaded(const upb_symtab *s); +upb_arena *_upb_symtab_arena(const upb_symtab *s); + +/* For generated code only: loads a generated descriptor. */ +typedef struct upb_def_init { + struct upb_def_init **deps; /* Dependencies of this file. */ + const upb_msglayout **layouts; /* Pre-order layouts of all messages. */ + const char *filename; + upb_strview descriptor; /* Serialized descriptor. */ +} upb_def_init; + +bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* UPB_DEF_H_ */ + +#ifndef UPB_REFLECTION_H_ +#define UPB_REFLECTION_H_ + + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef union { + bool bool_val; + float float_val; + double double_val; + int32_t int32_val; + int64_t int64_val; + uint32_t uint32_val; + uint64_t uint64_val; + const upb_map* map_val; + const upb_msg* msg_val; + const upb_array* array_val; + upb_strview str_val; +} upb_msgval; + +typedef union { + upb_map* map; + upb_msg* msg; + upb_array* array; +} upb_mutmsgval; + +upb_msgval upb_fielddef_default(const upb_fielddef *f); + +/** upb_msg *******************************************************************/ + +/* Creates a new message of the given type in the given arena. */ +upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a); + +/* Returns the value associated with this field. */ +upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f); + +/* Returns a mutable pointer to a map, array, or submessage value. If the given + * arena is non-NULL this will construct a new object if it was not previously + * present. May not be called for primitive fields. */ +upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, upb_arena *a); + +/* May only be called for fields where upb_fielddef_haspresence(f) == true. */ +bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f); + +/* Returns the field that is set in the oneof, or NULL if none are set. */ +const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg, + const upb_oneofdef *o); + +/* Sets the given field to the given value. For a msg/array/map/string, the + * value must be in the same arena. */ +void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val, + upb_arena *a); + +/* Clears any field presence and sets the value back to its default. */ +void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f); + +/* Clear all data and unknown fields. */ +void upb_msg_clear(upb_msg *msg, const upb_msgdef *m); + +/* Iterate over present fields. + * + * size_t iter = UPB_MSG_BEGIN; + * const upb_fielddef *f; + * upb_msgval val; + * while (upb_msg_next(msg, m, ext_pool, &f, &val, &iter)) { + * process_field(f, val); + * } + * + * If ext_pool is NULL, no extensions will be returned. If the given symtab + * returns extensions that don't match what is in this message, those extensions + * will be skipped. + */ + +#define UPB_MSG_BEGIN -1 +bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m, + const upb_symtab *ext_pool, const upb_fielddef **f, + upb_msgval *val, size_t *iter); + +/* Adds unknown data (serialized protobuf data) to the given message. The data + * is copied into the message instance. */ +void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, + upb_arena *arena); + +/* Clears all unknown field data from this message and all submessages. */ +bool upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int maxdepth); + +/* Returns a reference to the message's unknown data. */ +const char *upb_msg_getunknown(const upb_msg *msg, size_t *len); + +/** upb_array *****************************************************************/ + +/* Creates a new array on the given arena that holds elements of this type. */ +upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type); + +/* Returns the size of the array. */ +size_t upb_array_size(const upb_array *arr); + +/* Returns the given element, which must be within the array's current size. */ +upb_msgval upb_array_get(const upb_array *arr, size_t i); + +/* Sets the given element, which must be within the array's current size. */ +void upb_array_set(upb_array *arr, size_t i, upb_msgval val); + +/* Appends an element to the array. Returns false on allocation failure. */ +bool upb_array_append(upb_array *array, upb_msgval val, upb_arena *arena); + +/* Changes the size of a vector. New elements are initialized to empty/0. + * Returns false on allocation failure. */ +bool upb_array_resize(upb_array *array, size_t size, upb_arena *arena); + +/** upb_map *******************************************************************/ + +/* Creates a new map on the given arena with the given key/value size. */ +upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type, + upb_fieldtype_t value_type); + +/* Returns the number of entries in the map. */ +size_t upb_map_size(const upb_map *map); + +/* Stores a value for the given key into |*val| (or the zero value if the key is + * not present). Returns whether the key was present. The |val| pointer may be + * NULL, in which case the function tests whether the given key is present. */ +bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val); + +/* Removes all entries in the map. */ +void upb_map_clear(upb_map *map); + +/* Sets the given key to the given value. Returns true if this was a new key in + * the map, or false if an existing key was replaced. */ +bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, + upb_arena *arena); + +/* Deletes this key from the table. Returns true if the key was present. */ +bool upb_map_delete(upb_map *map, upb_msgval key); + +/* Map iteration: + * + * size_t iter = UPB_MAP_BEGIN; + * while (upb_mapiter_next(map, &iter)) { + * upb_msgval key = upb_mapiter_key(map, iter); + * upb_msgval val = upb_mapiter_value(map, iter); + * + * // If mutating is desired. + * upb_mapiter_setvalue(map, iter, value2); + * } + */ + +/* Advances to the next entry. Returns false if no more entries are present. */ +bool upb_mapiter_next(const upb_map *map, size_t *iter); + +/* Returns true if the iterator still points to a valid entry, or false if the + * iterator is past the last element. It is an error to call this function with + * UPB_MAP_BEGIN (you must call next() at least once first). */ +bool upb_mapiter_done(const upb_map *map, size_t iter); + +/* Returns the key and value for this entry of the map. */ +upb_msgval upb_mapiter_key(const upb_map *map, size_t iter); +upb_msgval upb_mapiter_value(const upb_map *map, size_t iter); + +/* Sets the value for this entry. The iterator must not be done, and the + * iterator must not have been initialized const. */ +void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_REFLECTION_H_ */ + +#ifndef UPB_JSONDECODE_H_ +#define UPB_JSONDECODE_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + UPB_JSONDEC_IGNOREUNKNOWN = 1 +}; + +bool upb_json_decode(const char *buf, size_t size, upb_msg *msg, + const upb_msgdef *m, const upb_symtab *any_pool, + int options, upb_arena *arena, upb_status *status); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* UPB_JSONDECODE_H_ */ + +#ifndef UPB_JSONENCODE_H_ +#define UPB_JSONENCODE_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /* When set, emits 0/default values. TODO(haberman): proto3 only? */ + UPB_JSONENC_EMITDEFAULTS = 1, + + /* When set, use normal (snake_caes) field names instead of JSON (camelCase) + names. */ + UPB_JSONENC_PROTONAMES = 2 +}; + +/* Encodes the given |msg| to JSON format. The message's reflection is given in + * |m|. The symtab in |symtab| is used to find extensions (if NULL, extensions + * will not be printed). + * + * Output is placed in the given buffer, and always NULL-terminated. The output + * size (excluding NULL) is returned. This means that a return value >= |size| + * implies that the output was truncated. (These are the same semantics as + * snprintf()). */ +size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m, + const upb_symtab *ext_pool, int options, char *buf, + size_t size, upb_status *status); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* UPB_JSONENCODE_H_ */ +/* See port_def.inc. This should #undef all macros #defined there. */ + +#undef UPB_MAPTYPE_STRING +#undef UPB_SIZE +#undef UPB_PTR_AT +#undef UPB_READ_ONEOF +#undef UPB_WRITE_ONEOF +#undef UPB_INLINE +#undef UPB_ALIGN_UP +#undef UPB_ALIGN_DOWN +#undef UPB_ALIGN_MALLOC +#undef UPB_ALIGN_OF +#undef UPB_FORCEINLINE +#undef UPB_NOINLINE +#undef UPB_NORETURN +#undef UPB_MAX +#undef UPB_MIN +#undef UPB_UNUSED +#undef UPB_ASSUME +#undef UPB_ASSERT +#undef UPB_UNREACHABLE +#undef UPB_POISON_MEMORY_REGION +#undef UPB_UNPOISON_MEMORY_REGION +#undef UPB_ASAN diff --git a/ruby/ext/google/protobuf_c/storage.c b/ruby/ext/google/protobuf_c/storage.c deleted file mode 100644 index 3ff2bda6bbc14..0000000000000 --- a/ruby/ext/google/protobuf_c/storage.c +++ /dev/null @@ -1,893 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2014 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "protobuf.h" - -#include - -#include - -// ----------------------------------------------------------------------------- -// Ruby <-> native slot management. -// ----------------------------------------------------------------------------- - -#define DEREF(memory, type) *(type*)(memory) - -size_t native_slot_size(upb_fieldtype_t type) { - switch (type) { - case UPB_TYPE_FLOAT: return 4; - case UPB_TYPE_DOUBLE: return 8; - case UPB_TYPE_BOOL: return 1; - case UPB_TYPE_STRING: return sizeof(VALUE); - case UPB_TYPE_BYTES: return sizeof(VALUE); - case UPB_TYPE_MESSAGE: return sizeof(VALUE); - case UPB_TYPE_ENUM: return 4; - case UPB_TYPE_INT32: return 4; - case UPB_TYPE_INT64: return 8; - case UPB_TYPE_UINT32: return 4; - case UPB_TYPE_UINT64: return 8; - default: return 0; - } -} - -static VALUE value_from_default(const upb_fielddef *field) { - switch (upb_fielddef_type(field)) { - case UPB_TYPE_FLOAT: return DBL2NUM(upb_fielddef_defaultfloat(field)); - case UPB_TYPE_DOUBLE: return DBL2NUM(upb_fielddef_defaultdouble(field)); - case UPB_TYPE_BOOL: - return upb_fielddef_defaultbool(field) ? Qtrue : Qfalse; - case UPB_TYPE_MESSAGE: return Qnil; - case UPB_TYPE_ENUM: { - const upb_enumdef *enumdef = upb_fielddef_enumsubdef(field); - int32_t num = upb_fielddef_defaultint32(field); - const char *label = upb_enumdef_iton(enumdef, num); - if (label) { - return ID2SYM(rb_intern(label)); - } else { - return INT2NUM(num); - } - } - case UPB_TYPE_INT32: return INT2NUM(upb_fielddef_defaultint32(field)); - case UPB_TYPE_INT64: return LL2NUM(upb_fielddef_defaultint64(field));; - case UPB_TYPE_UINT32: return UINT2NUM(upb_fielddef_defaultuint32(field)); - case UPB_TYPE_UINT64: return ULL2NUM(upb_fielddef_defaultuint64(field)); - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - size_t size; - const char *str = upb_fielddef_defaultstr(field, &size); - return rb_str_new(str, size); - } - default: return Qnil; - } -} - -static bool is_ruby_num(VALUE value) { - return (TYPE(value) == T_FLOAT || - TYPE(value) == T_FIXNUM || - TYPE(value) == T_BIGNUM); -} - -void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) { - if (!is_ruby_num(val)) { - rb_raise(rb_eTypeError, "Expected number type for integral field."); - } - - // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper - // bound; we just need to do precision checks (i.e., disallow rounding) and - // check for < 0 on unsigned types. - if (TYPE(val) == T_FLOAT) { - double dbl_val = NUM2DBL(val); - if (floor(dbl_val) != dbl_val) { - rb_raise(rb_eRangeError, - "Non-integral floating point value assigned to integer field."); - } - } - if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) { - if (NUM2DBL(val) < 0) { - rb_raise(rb_eRangeError, - "Assigning negative value to unsigned integer field."); - } - } -} - -VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value) { - rb_encoding* desired_encoding = (type == UPB_TYPE_STRING) ? - kRubyStringUtf8Encoding : kRubyString8bitEncoding; - VALUE desired_encoding_value = rb_enc_from_encoding(desired_encoding); - - // Note: this will not duplicate underlying string data unless necessary. - value = rb_str_encode(value, desired_encoding_value, 0, Qnil); - - if (type == UPB_TYPE_STRING && - rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) { - rb_raise(rb_eEncodingError, "String is invalid UTF-8"); - } - - // Ensure the data remains valid. Since we called #encode a moment ago, - // this does not freeze the string the user assigned. - rb_obj_freeze(value); - - return value; -} - -void native_slot_set(upb_fieldtype_t type, VALUE type_class, - void* memory, VALUE value) { - native_slot_set_value_and_case(type, type_class, memory, value, NULL, 0); -} - -void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class, - void* memory, VALUE value, - uint32_t* case_memory, - uint32_t case_number) { - // Note that in order to atomically change the value in memory and the case - // value (w.r.t. Ruby VM calls), we must set the value at |memory| only after - // all Ruby VM calls are complete. The case is then set at the bottom of this - // function. - switch (type) { - case UPB_TYPE_FLOAT: - if (!is_ruby_num(value)) { - rb_raise(rb_eTypeError, "Expected number type for float field."); - } - DEREF(memory, float) = NUM2DBL(value); - break; - case UPB_TYPE_DOUBLE: - if (!is_ruby_num(value)) { - rb_raise(rb_eTypeError, "Expected number type for double field."); - } - DEREF(memory, double) = NUM2DBL(value); - break; - case UPB_TYPE_BOOL: { - int8_t val = -1; - if (value == Qtrue) { - val = 1; - } else if (value == Qfalse) { - val = 0; - } else { - rb_raise(rb_eTypeError, "Invalid argument for boolean field."); - } - DEREF(memory, int8_t) = val; - break; - } - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - if (CLASS_OF(value) != rb_cString) { - rb_raise(rb_eTypeError, "Invalid argument for string field."); - } - - DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value); - break; - } - case UPB_TYPE_MESSAGE: { - if (CLASS_OF(value) == CLASS_OF(Qnil)) { - value = Qnil; - } else if (CLASS_OF(value) != type_class) { - rb_raise(rb_eTypeError, - "Invalid type %s to assign to submessage field.", - rb_class2name(CLASS_OF(value))); - } - DEREF(memory, VALUE) = value; - break; - } - case UPB_TYPE_ENUM: { - int32_t int_val = 0; - if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) { - rb_raise(rb_eTypeError, - "Expected number or symbol type for enum field."); - } - if (TYPE(value) == T_SYMBOL) { - // Ensure that the given symbol exists in the enum module. - VALUE lookup = rb_funcall(type_class, rb_intern("resolve"), 1, value); - if (lookup == Qnil) { - rb_raise(rb_eRangeError, "Unknown symbol value for enum field."); - } else { - int_val = NUM2INT(lookup); - } - } else { - native_slot_check_int_range_precision(UPB_TYPE_INT32, value); - int_val = NUM2INT(value); - } - DEREF(memory, int32_t) = int_val; - break; - } - case UPB_TYPE_INT32: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT32: - case UPB_TYPE_UINT64: - native_slot_check_int_range_precision(type, value); - switch (type) { - case UPB_TYPE_INT32: - DEREF(memory, int32_t) = NUM2INT(value); - break; - case UPB_TYPE_INT64: - DEREF(memory, int64_t) = NUM2LL(value); - break; - case UPB_TYPE_UINT32: - DEREF(memory, uint32_t) = NUM2UINT(value); - break; - case UPB_TYPE_UINT64: - DEREF(memory, uint64_t) = NUM2ULL(value); - break; - default: - break; - } - break; - default: - break; - } - - if (case_memory != NULL) { - *case_memory = case_number; - } -} - -VALUE native_slot_get(upb_fieldtype_t type, - VALUE type_class, - const void* memory) { - switch (type) { - case UPB_TYPE_FLOAT: - return DBL2NUM(DEREF(memory, float)); - case UPB_TYPE_DOUBLE: - return DBL2NUM(DEREF(memory, double)); - case UPB_TYPE_BOOL: - return DEREF(memory, int8_t) ? Qtrue : Qfalse; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - return DEREF(memory, VALUE); - case UPB_TYPE_ENUM: { - int32_t val = DEREF(memory, int32_t); - VALUE symbol = enum_lookup(type_class, INT2NUM(val)); - if (symbol == Qnil) { - return INT2NUM(val); - } else { - return symbol; - } - } - case UPB_TYPE_INT32: - return INT2NUM(DEREF(memory, int32_t)); - case UPB_TYPE_INT64: - return LL2NUM(DEREF(memory, int64_t)); - case UPB_TYPE_UINT32: - return UINT2NUM(DEREF(memory, uint32_t)); - case UPB_TYPE_UINT64: - return ULL2NUM(DEREF(memory, uint64_t)); - default: - return Qnil; - } -} - -void native_slot_init(upb_fieldtype_t type, void* memory) { - switch (type) { - case UPB_TYPE_FLOAT: - DEREF(memory, float) = 0.0; - break; - case UPB_TYPE_DOUBLE: - DEREF(memory, double) = 0.0; - break; - case UPB_TYPE_BOOL: - DEREF(memory, int8_t) = 0; - break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - DEREF(memory, VALUE) = rb_str_new2(""); - rb_enc_associate(DEREF(memory, VALUE), (type == UPB_TYPE_BYTES) ? - kRubyString8bitEncoding : kRubyStringUtf8Encoding); - break; - case UPB_TYPE_MESSAGE: - DEREF(memory, VALUE) = Qnil; - break; - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - DEREF(memory, int32_t) = 0; - break; - case UPB_TYPE_INT64: - DEREF(memory, int64_t) = 0; - break; - case UPB_TYPE_UINT32: - DEREF(memory, uint32_t) = 0; - break; - case UPB_TYPE_UINT64: - DEREF(memory, uint64_t) = 0; - break; - default: - break; - } -} - -void native_slot_mark(upb_fieldtype_t type, void* memory) { - switch (type) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - rb_gc_mark(DEREF(memory, VALUE)); - break; - default: - break; - } -} - -void native_slot_dup(upb_fieldtype_t type, void* to, void* from) { - memcpy(to, from, native_slot_size(type)); -} - -void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from) { - switch (type) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - VALUE from_val = DEREF(from, VALUE); - DEREF(to, VALUE) = (from_val != Qnil) ? - rb_funcall(from_val, rb_intern("dup"), 0) : Qnil; - break; - } - case UPB_TYPE_MESSAGE: { - VALUE from_val = DEREF(from, VALUE); - DEREF(to, VALUE) = (from_val != Qnil) ? - Message_deep_copy(from_val) : Qnil; - break; - } - default: - memcpy(to, from, native_slot_size(type)); - } -} - -bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2) { - switch (type) { - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: { - VALUE val1 = DEREF(mem1, VALUE); - VALUE val2 = DEREF(mem2, VALUE); - VALUE ret = rb_funcall(val1, rb_intern("=="), 1, val2); - return ret == Qtrue; - } - default: - return !memcmp(mem1, mem2, native_slot_size(type)); - } -} - -// ----------------------------------------------------------------------------- -// Map field utilities. -// ----------------------------------------------------------------------------- - -const upb_msgdef* tryget_map_entry_msgdef(const upb_fielddef* field) { - const upb_msgdef* subdef; - if (upb_fielddef_label(field) != UPB_LABEL_REPEATED || - upb_fielddef_type(field) != UPB_TYPE_MESSAGE) { - return NULL; - } - subdef = upb_fielddef_msgsubdef(field); - return upb_msgdef_mapentry(subdef) ? subdef : NULL; -} - -const upb_msgdef *map_entry_msgdef(const upb_fielddef* field) { - const upb_msgdef* subdef = tryget_map_entry_msgdef(field); - assert(subdef); - return subdef; -} - -bool is_map_field(const upb_fielddef *field) { - return tryget_map_entry_msgdef(field) != NULL; -} - -const upb_fielddef* map_field_key(const upb_fielddef* field) { - const upb_msgdef* subdef = map_entry_msgdef(field); - return map_entry_key(subdef); -} - -const upb_fielddef* map_field_value(const upb_fielddef* field) { - const upb_msgdef* subdef = map_entry_msgdef(field); - return map_entry_value(subdef); -} - -const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) { - const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD); - assert(key_field != NULL); - return key_field; -} - -const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) { - const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD); - assert(value_field != NULL); - return value_field; -} - -// ----------------------------------------------------------------------------- -// Memory layout management. -// ----------------------------------------------------------------------------- - -static size_t align_up_to(size_t offset, size_t granularity) { - // Granularity must be a power of two. - return (offset + granularity - 1) & ~(granularity - 1); -} - -MessageLayout* create_layout(const upb_msgdef* msgdef) { - MessageLayout* layout = ALLOC(MessageLayout); - int nfields = upb_msgdef_numfields(msgdef); - upb_msg_field_iter it; - upb_msg_oneof_iter oit; - size_t off = 0; - - layout->fields = ALLOC_N(MessageField, nfields); - - for (upb_msg_field_begin(&it, msgdef); - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* field = upb_msg_iter_field(&it); - size_t field_size; - - if (upb_fielddef_containingoneof(field)) { - // Oneofs are handled separately below. - continue; - } - - // Allocate |field_size| bytes for this field in the layout. - field_size = 0; - if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - field_size = sizeof(VALUE); - } else { - field_size = native_slot_size(upb_fielddef_type(field)); - } - // Align current offset up to |size| granularity. - off = align_up_to(off, field_size); - layout->fields[upb_fielddef_index(field)].offset = off; - layout->fields[upb_fielddef_index(field)].case_offset = - MESSAGE_FIELD_NO_CASE; - off += field_size; - } - - // Handle oneofs now -- we iterate over oneofs specifically and allocate only - // one slot per oneof. - // - // We assign all value slots first, then pack the 'case' fields at the end, - // since in the common case (modern 64-bit platform) these are 8 bytes and 4 - // bytes respectively and we want to avoid alignment overhead. - // - // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value - // space for oneof cases is conceptually as wide as field tag numbers. In - // practice, it's unlikely that a oneof would have more than e.g. 256 or 64K - // members (8 or 16 bits respectively), so conceivably we could assign - // consecutive case numbers and then pick a smaller oneof case slot size, but - // the complexity to implement this indirection is probably not worthwhile. - for (upb_msg_oneof_begin(&oit, msgdef); - !upb_msg_oneof_done(&oit); - upb_msg_oneof_next(&oit)) { - const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit); - upb_oneof_iter fit; - - // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between - // all fields. - size_t field_size = NATIVE_SLOT_MAX_SIZE; - // Align the offset. - off = align_up_to(off, field_size); - // Assign all fields in the oneof this same offset. - for (upb_oneof_begin(&fit, oneof); - !upb_oneof_done(&fit); - upb_oneof_next(&fit)) { - const upb_fielddef* field = upb_oneof_iter_field(&fit); - layout->fields[upb_fielddef_index(field)].offset = off; - } - off += field_size; - } - - // Now the case fields. - for (upb_msg_oneof_begin(&oit, msgdef); - !upb_msg_oneof_done(&oit); - upb_msg_oneof_next(&oit)) { - const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit); - upb_oneof_iter fit; - - size_t field_size = sizeof(uint32_t); - // Align the offset. - off = (off + field_size - 1) & ~(field_size - 1); - // Assign all fields in the oneof this same offset. - for (upb_oneof_begin(&fit, oneof); - !upb_oneof_done(&fit); - upb_oneof_next(&fit)) { - const upb_fielddef* field = upb_oneof_iter_field(&fit); - layout->fields[upb_fielddef_index(field)].case_offset = off; - } - off += field_size; - } - - layout->size = off; - - layout->msgdef = msgdef; - upb_msgdef_ref(layout->msgdef, &layout->msgdef); - - return layout; -} - -void free_layout(MessageLayout* layout) { - xfree(layout->fields); - upb_msgdef_unref(layout->msgdef, &layout->msgdef); - xfree(layout); -} - -VALUE field_type_class(const upb_fielddef* field) { - VALUE type_class = Qnil; - if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) { - VALUE submsgdesc = - get_def_obj(upb_fielddef_subdef(field)); - type_class = Descriptor_msgclass(submsgdesc); - } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) { - VALUE subenumdesc = - get_def_obj(upb_fielddef_subdef(field)); - type_class = EnumDescriptor_enummodule(subenumdesc); - } - return type_class; -} - -static void* slot_memory(MessageLayout* layout, - const void* storage, - const upb_fielddef* field) { - return ((uint8_t *)storage) + - layout->fields[upb_fielddef_index(field)].offset; -} - -static uint32_t* slot_oneof_case(MessageLayout* layout, - const void* storage, - const upb_fielddef* field) { - return (uint32_t *)(((uint8_t *)storage) + - layout->fields[upb_fielddef_index(field)].case_offset); -} - - -VALUE layout_get(MessageLayout* layout, - const void* storage, - const upb_fielddef* field) { - void* memory = slot_memory(layout, storage, field); - uint32_t* oneof_case = slot_oneof_case(layout, storage, field); - - if (upb_fielddef_containingoneof(field)) { - if (*oneof_case != upb_fielddef_number(field)) { - return value_from_default(field); - } - return native_slot_get(upb_fielddef_type(field), - field_type_class(field), - memory); - } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - return *((VALUE *)memory); - } else { - return native_slot_get(upb_fielddef_type(field), - field_type_class(field), - memory); - } -} - -static void check_repeated_field_type(VALUE val, const upb_fielddef* field) { - RepeatedField* self; - assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED); - - if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) || - RTYPEDDATA_TYPE(val) != &RepeatedField_type) { - rb_raise(rb_eTypeError, "Expected repeated field array"); - } - - self = ruby_to_RepeatedField(val); - if (self->field_type != upb_fielddef_type(field)) { - rb_raise(rb_eTypeError, "Repeated field array has wrong element type"); - } - - if (self->field_type == UPB_TYPE_MESSAGE || - self->field_type == UPB_TYPE_ENUM) { - if (self->field_type_class != - get_def_obj(upb_fielddef_subdef(field))) { - rb_raise(rb_eTypeError, - "Repeated field array has wrong message/enum class"); - } - } -} - -static void check_map_field_type(VALUE val, const upb_fielddef* field) { - const upb_fielddef* key_field = map_field_key(field); - const upb_fielddef* value_field = map_field_value(field); - Map* self; - - if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) || - RTYPEDDATA_TYPE(val) != &Map_type) { - rb_raise(rb_eTypeError, "Expected Map instance"); - } - - self = ruby_to_Map(val); - if (self->key_type != upb_fielddef_type(key_field)) { - rb_raise(rb_eTypeError, "Map key type does not match field's key type"); - } - if (self->value_type != upb_fielddef_type(value_field)) { - rb_raise(rb_eTypeError, "Map value type does not match field's value type"); - } - if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE || - upb_fielddef_type(value_field) == UPB_TYPE_ENUM) { - if (self->value_type_class != - get_def_obj(upb_fielddef_subdef(value_field))) { - rb_raise(rb_eTypeError, - "Map value type has wrong message/enum class"); - } - } -} - - -void layout_set(MessageLayout* layout, - void* storage, - const upb_fielddef* field, - VALUE val) { - void* memory = slot_memory(layout, storage, field); - uint32_t* oneof_case = slot_oneof_case(layout, storage, field); - - if (upb_fielddef_containingoneof(field)) { - if (val == Qnil) { - // Assigning nil to a oneof field clears the oneof completely. - *oneof_case = ONEOF_CASE_NONE; - memset(memory, 0, NATIVE_SLOT_MAX_SIZE); - } else { - // The transition between field types for a single oneof (union) slot is - // somewhat complex because we need to ensure that a GC triggered at any - // point by a call into the Ruby VM sees a valid state for this field and - // does not either go off into the weeds (following what it thinks is a - // VALUE but is actually a different field type) or miss an object (seeing - // what it thinks is a primitive field but is actually a VALUE for the new - // field type). - // - // In order for the transition to be safe, the oneof case slot must be in - // sync with the value slot whenever the Ruby VM has been called. Thus, we - // use native_slot_set_value_and_case(), which ensures that both the value - // and case number are altered atomically (w.r.t. the Ruby VM). - native_slot_set_value_and_case( - upb_fielddef_type(field), field_type_class(field), - memory, val, - oneof_case, upb_fielddef_number(field)); - } - } else if (is_map_field(field)) { - check_map_field_type(val, field); - DEREF(memory, VALUE) = val; - } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - check_repeated_field_type(val, field); - DEREF(memory, VALUE) = val; - } else { - native_slot_set(upb_fielddef_type(field), field_type_class(field), - memory, val); - } -} - -void layout_init(MessageLayout* layout, - void* storage) { - upb_msg_field_iter it; - for (upb_msg_field_begin(&it, layout->msgdef); - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* field = upb_msg_iter_field(&it); - void* memory = slot_memory(layout, storage, field); - uint32_t* oneof_case = slot_oneof_case(layout, storage, field); - - if (upb_fielddef_containingoneof(field)) { - memset(memory, 0, NATIVE_SLOT_MAX_SIZE); - *oneof_case = ONEOF_CASE_NONE; - } else if (is_map_field(field)) { - VALUE map = Qnil; - - const upb_fielddef* key_field = map_field_key(field); - const upb_fielddef* value_field = map_field_value(field); - VALUE type_class = field_type_class(value_field); - - if (type_class != Qnil) { - VALUE args[3] = { - fieldtype_to_ruby(upb_fielddef_type(key_field)), - fieldtype_to_ruby(upb_fielddef_type(value_field)), - type_class, - }; - map = rb_class_new_instance(3, args, cMap); - } else { - VALUE args[2] = { - fieldtype_to_ruby(upb_fielddef_type(key_field)), - fieldtype_to_ruby(upb_fielddef_type(value_field)), - }; - map = rb_class_new_instance(2, args, cMap); - } - - DEREF(memory, VALUE) = map; - } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - VALUE ary = Qnil; - - VALUE type_class = field_type_class(field); - - if (type_class != Qnil) { - VALUE args[2] = { - fieldtype_to_ruby(upb_fielddef_type(field)), - type_class, - }; - ary = rb_class_new_instance(2, args, cRepeatedField); - } else { - VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) }; - ary = rb_class_new_instance(1, args, cRepeatedField); - } - - DEREF(memory, VALUE) = ary; - } else { - native_slot_init(upb_fielddef_type(field), memory); - } - } -} - -void layout_mark(MessageLayout* layout, void* storage) { - upb_msg_field_iter it; - for (upb_msg_field_begin(&it, layout->msgdef); - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* field = upb_msg_iter_field(&it); - void* memory = slot_memory(layout, storage, field); - uint32_t* oneof_case = slot_oneof_case(layout, storage, field); - - if (upb_fielddef_containingoneof(field)) { - if (*oneof_case == upb_fielddef_number(field)) { - native_slot_mark(upb_fielddef_type(field), memory); - } - } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - rb_gc_mark(DEREF(memory, VALUE)); - } else { - native_slot_mark(upb_fielddef_type(field), memory); - } - } -} - -void layout_dup(MessageLayout* layout, void* to, void* from) { - upb_msg_field_iter it; - for (upb_msg_field_begin(&it, layout->msgdef); - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* field = upb_msg_iter_field(&it); - - void* to_memory = slot_memory(layout, to, field); - uint32_t* to_oneof_case = slot_oneof_case(layout, to, field); - void* from_memory = slot_memory(layout, from, field); - uint32_t* from_oneof_case = slot_oneof_case(layout, from, field); - - if (upb_fielddef_containingoneof(field)) { - if (*from_oneof_case == upb_fielddef_number(field)) { - *to_oneof_case = *from_oneof_case; - native_slot_dup(upb_fielddef_type(field), to_memory, from_memory); - } - } else if (is_map_field(field)) { - DEREF(to_memory, VALUE) = Map_dup(DEREF(from_memory, VALUE)); - } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE)); - } else { - native_slot_dup(upb_fielddef_type(field), to_memory, from_memory); - } - } -} - -void layout_deep_copy(MessageLayout* layout, void* to, void* from) { - upb_msg_field_iter it; - for (upb_msg_field_begin(&it, layout->msgdef); - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* field = upb_msg_iter_field(&it); - - void* to_memory = slot_memory(layout, to, field); - uint32_t* to_oneof_case = slot_oneof_case(layout, to, field); - void* from_memory = slot_memory(layout, from, field); - uint32_t* from_oneof_case = slot_oneof_case(layout, from, field); - - if (upb_fielddef_containingoneof(field)) { - if (*from_oneof_case == upb_fielddef_number(field)) { - *to_oneof_case = *from_oneof_case; - native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory); - } - } else if (is_map_field(field)) { - DEREF(to_memory, VALUE) = - Map_deep_copy(DEREF(from_memory, VALUE)); - } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - DEREF(to_memory, VALUE) = - RepeatedField_deep_copy(DEREF(from_memory, VALUE)); - } else { - native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory); - } - } -} - -VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) { - upb_msg_field_iter it; - for (upb_msg_field_begin(&it, layout->msgdef); - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* field = upb_msg_iter_field(&it); - - void* msg1_memory = slot_memory(layout, msg1, field); - uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field); - void* msg2_memory = slot_memory(layout, msg2, field); - uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field); - - if (upb_fielddef_containingoneof(field)) { - if (*msg1_oneof_case != *msg2_oneof_case || - (*msg1_oneof_case == upb_fielddef_number(field) && - !native_slot_eq(upb_fielddef_type(field), - msg1_memory, - msg2_memory))) { - return Qfalse; - } - } else if (is_map_field(field)) { - if (!Map_eq(DEREF(msg1_memory, VALUE), - DEREF(msg2_memory, VALUE))) { - return Qfalse; - } - } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - if (!RepeatedField_eq(DEREF(msg1_memory, VALUE), - DEREF(msg2_memory, VALUE))) { - return Qfalse; - } - } else { - if (!native_slot_eq(upb_fielddef_type(field), - msg1_memory, msg2_memory)) { - return Qfalse; - } - } - } - return Qtrue; -} - -VALUE layout_hash(MessageLayout* layout, void* storage) { - upb_msg_field_iter it; - st_index_t h = rb_hash_start(0); - VALUE hash_sym = rb_intern("hash"); - for (upb_msg_field_begin(&it, layout->msgdef); - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* field = upb_msg_iter_field(&it); - VALUE field_val = layout_get(layout, storage, field); - h = rb_hash_uint(h, NUM2LONG(rb_funcall(field_val, hash_sym, 0))); - } - h = rb_hash_end(h); - - return INT2FIX(h); -} - -VALUE layout_inspect(MessageLayout* layout, void* storage) { - VALUE str = rb_str_new2(""); - - upb_msg_field_iter it; - bool first = true; - for (upb_msg_field_begin(&it, layout->msgdef); - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* field = upb_msg_iter_field(&it); - VALUE field_val = layout_get(layout, storage, field); - - if (!first) { - str = rb_str_cat2(str, ", "); - } else { - first = false; - } - str = rb_str_cat2(str, upb_fielddef_name(field)); - str = rb_str_cat2(str, ": "); - - str = rb_str_append(str, rb_funcall(field_val, rb_intern("inspect"), 0)); - } - - return str; -} diff --git a/ruby/ext/google/protobuf_c/upb.c b/ruby/ext/google/protobuf_c/upb.c deleted file mode 100644 index 90d1f0cda8be2..0000000000000 --- a/ruby/ext/google/protobuf_c/upb.c +++ /dev/null @@ -1,13911 +0,0 @@ -// Amalgamated source file -#include "upb.h" - - -#include -#include -#include - -typedef struct { - size_t len; - char str[1]; /* Null-terminated string data follows. */ -} str_t; - -static str_t *newstr(const char *data, size_t len) { - str_t *ret = upb_gmalloc(sizeof(*ret) + len); - if (!ret) return NULL; - ret->len = len; - memcpy(ret->str, data, len); - ret->str[len] = '\0'; - return ret; -} - -static void freestr(str_t *s) { upb_gfree(s); } - -/* isalpha() etc. from are locale-dependent, which we don't want. */ -static bool upb_isbetween(char c, char low, char high) { - return c >= low && c <= high; -} - -static bool upb_isletter(char c) { - return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_'; -} - -static bool upb_isalphanum(char c) { - return upb_isletter(c) || upb_isbetween(c, '0', '9'); -} - -static bool upb_isident(const char *str, size_t len, bool full, upb_status *s) { - bool start = true; - size_t i; - for (i = 0; i < len; i++) { - char c = str[i]; - if (c == '.') { - if (start || !full) { - upb_status_seterrf(s, "invalid name: unexpected '.' (%s)", str); - return false; - } - start = true; - } else if (start) { - if (!upb_isletter(c)) { - upb_status_seterrf( - s, "invalid name: path components must start with a letter (%s)", - str); - return false; - } - start = false; - } else { - if (!upb_isalphanum(c)) { - upb_status_seterrf(s, "invalid name: non-alphanumeric character (%s)", - str); - return false; - } - } - } - return !start; -} - -static bool upb_isoneof(const upb_refcounted *def) { - return def->vtbl == &upb_oneofdef_vtbl; -} - -static bool upb_isfield(const upb_refcounted *def) { - return def->vtbl == &upb_fielddef_vtbl; -} - -static const upb_oneofdef *upb_trygetoneof(const upb_refcounted *def) { - return upb_isoneof(def) ? (const upb_oneofdef*)def : NULL; -} - -static const upb_fielddef *upb_trygetfield(const upb_refcounted *def) { - return upb_isfield(def) ? (const upb_fielddef*)def : NULL; -} - - -/* upb_def ********************************************************************/ - -upb_deftype_t upb_def_type(const upb_def *d) { return d->type; } - -const char *upb_def_fullname(const upb_def *d) { return d->fullname; } - -const char *upb_def_name(const upb_def *d) { - const char *p; - - if (d->fullname == NULL) { - return NULL; - } else if ((p = strrchr(d->fullname, '.')) == NULL) { - /* No '.' in the name, return the full string. */ - return d->fullname; - } else { - /* Return one past the last '.'. */ - return p + 1; - } -} - -bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s) { - UPB_ASSERT(!upb_def_isfrozen(def)); - if (!upb_isident(fullname, strlen(fullname), true, s)) { - return false; - } - - fullname = upb_gstrdup(fullname); - if (!fullname) { - upb_upberr_setoom(s); - return false; - } - - upb_gfree((void*)def->fullname); - def->fullname = fullname; - return true; -} - -const upb_filedef *upb_def_file(const upb_def *d) { return d->file; } - -static bool upb_def_init(upb_def *def, upb_deftype_t type, - const struct upb_refcounted_vtbl *vtbl, - const void *owner) { - if (!upb_refcounted_init(upb_def_upcast_mutable(def), vtbl, owner)) return false; - def->type = type; - def->fullname = NULL; - def->came_from_user = false; - def->file = NULL; - return true; -} - -static void upb_def_uninit(upb_def *def) { - upb_gfree((void*)def->fullname); -} - -static const char *msgdef_name(const upb_msgdef *m) { - const char *name = upb_def_fullname(upb_msgdef_upcast(m)); - return name ? name : "(anonymous)"; -} - -static bool upb_validate_field(upb_fielddef *f, upb_status *s) { - if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { - upb_status_seterrmsg(s, "fielddef must have name and number set"); - return false; - } - - if (!f->type_is_set_) { - upb_status_seterrmsg(s, "fielddef type was not initialized"); - return false; - } - - if (upb_fielddef_lazy(f) && - upb_fielddef_descriptortype(f) != UPB_DESCRIPTOR_TYPE_MESSAGE) { - upb_status_seterrmsg(s, - "only length-delimited submessage fields may be lazy"); - return false; - } - - if (upb_fielddef_hassubdef(f)) { - const upb_def *subdef; - - if (f->subdef_is_symbolic) { - upb_status_seterrf(s, "field '%s.%s' has not been resolved", - msgdef_name(f->msg.def), upb_fielddef_name(f)); - return false; - } - - subdef = upb_fielddef_subdef(f); - if (subdef == NULL) { - upb_status_seterrf(s, "field %s.%s is missing required subdef", - msgdef_name(f->msg.def), upb_fielddef_name(f)); - return false; - } - - if (!upb_def_isfrozen(subdef) && !subdef->came_from_user) { - upb_status_seterrf(s, - "subdef of field %s.%s is not frozen or being frozen", - msgdef_name(f->msg.def), upb_fielddef_name(f)); - return false; - } - } - - if (upb_fielddef_type(f) == UPB_TYPE_ENUM) { - bool has_default_name = upb_fielddef_enumhasdefaultstr(f); - bool has_default_number = upb_fielddef_enumhasdefaultint32(f); - - /* Previously verified by upb_validate_enumdef(). */ - UPB_ASSERT(upb_enumdef_numvals(upb_fielddef_enumsubdef(f)) > 0); - - /* We've already validated that we have an associated enumdef and that it - * has at least one member, so at least one of these should be true. - * Because if the user didn't set anything, we'll pick up the enum's - * default, but if the user *did* set something we should at least pick up - * the one they set (int32 or string). */ - UPB_ASSERT(has_default_name || has_default_number); - - if (!has_default_name) { - upb_status_seterrf(s, - "enum default for field %s.%s (%d) is not in the enum", - msgdef_name(f->msg.def), upb_fielddef_name(f), - upb_fielddef_defaultint32(f)); - return false; - } - - if (!has_default_number) { - upb_status_seterrf(s, - "enum default for field %s.%s (%s) is not in the enum", - msgdef_name(f->msg.def), upb_fielddef_name(f), - upb_fielddef_defaultstr(f, NULL)); - return false; - } - - /* Lift the effective numeric default into the field's default slot, in case - * we were only getting it "by reference" from the enumdef. */ - upb_fielddef_setdefaultint32(f, upb_fielddef_defaultint32(f)); - } - - /* Ensure that MapEntry submessages only appear as repeated fields, not - * optional/required (singular) fields. */ - if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE && - upb_fielddef_msgsubdef(f) != NULL) { - const upb_msgdef *subdef = upb_fielddef_msgsubdef(f); - if (upb_msgdef_mapentry(subdef) && !upb_fielddef_isseq(f)) { - upb_status_seterrf(s, - "Field %s refers to mapentry message but is not " - "a repeated field", - upb_fielddef_name(f) ? upb_fielddef_name(f) : - "(unnamed)"); - return false; - } - } - - return true; -} - -static bool upb_validate_enumdef(const upb_enumdef *e, upb_status *s) { - if (upb_enumdef_numvals(e) == 0) { - upb_status_seterrf(s, "enum %s has no members (must have at least one)", - upb_enumdef_fullname(e)); - return false; - } - - return true; -} - -/* All submessage fields are lower than all other fields. - * Secondly, fields are increasing in order. */ -uint32_t field_rank(const upb_fielddef *f) { - uint32_t ret = upb_fielddef_number(f); - const uint32_t high_bit = 1 << 30; - UPB_ASSERT(ret < high_bit); - if (!upb_fielddef_issubmsg(f)) - ret |= high_bit; - return ret; -} - -int cmp_fields(const void *p1, const void *p2) { - const upb_fielddef *f1 = *(upb_fielddef*const*)p1; - const upb_fielddef *f2 = *(upb_fielddef*const*)p2; - return field_rank(f1) - field_rank(f2); -} - -static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { - /* Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the - * lowest indexes, but we do not publicly guarantee this. */ - upb_msg_field_iter j; - upb_msg_oneof_iter k; - int i; - uint32_t selector; - int n = upb_msgdef_numfields(m); - upb_fielddef **fields; - - if (n == 0) { - m->selector_count = UPB_STATIC_SELECTOR_COUNT; - m->submsg_field_count = 0; - return true; - } - - fields = upb_gmalloc(n * sizeof(*fields)); - if (!fields) { - upb_upberr_setoom(s); - return false; - } - - m->submsg_field_count = 0; - for(i = 0, upb_msg_field_begin(&j, m); - !upb_msg_field_done(&j); - upb_msg_field_next(&j), i++) { - upb_fielddef *f = upb_msg_iter_field(&j); - UPB_ASSERT(f->msg.def == m); - if (!upb_validate_field(f, s)) { - upb_gfree(fields); - return false; - } - if (upb_fielddef_issubmsg(f)) { - m->submsg_field_count++; - } - fields[i] = f; - } - - qsort(fields, n, sizeof(*fields), cmp_fields); - - selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count; - for (i = 0; i < n; i++) { - upb_fielddef *f = fields[i]; - f->index_ = i; - f->selector_base = selector + upb_handlers_selectorbaseoffset(f); - selector += upb_handlers_selectorcount(f); - } - m->selector_count = selector; - -#ifndef NDEBUG - { - /* Verify that all selectors for the message are distinct. */ -#define TRY(type) \ - if (upb_handlers_getselector(f, type, &sel)) upb_inttable_insert(&t, sel, v); - - upb_inttable t; - upb_value v; - upb_selector_t sel; - - upb_inttable_init(&t, UPB_CTYPE_BOOL); - v = upb_value_bool(true); - upb_inttable_insert(&t, UPB_STARTMSG_SELECTOR, v); - upb_inttable_insert(&t, UPB_ENDMSG_SELECTOR, v); - for(upb_msg_field_begin(&j, m); - !upb_msg_field_done(&j); - upb_msg_field_next(&j)) { - upb_fielddef *f = upb_msg_iter_field(&j); - /* These calls will assert-fail in upb_table if the value already - * exists. */ - TRY(UPB_HANDLER_INT32); - TRY(UPB_HANDLER_INT64) - TRY(UPB_HANDLER_UINT32) - TRY(UPB_HANDLER_UINT64) - TRY(UPB_HANDLER_FLOAT) - TRY(UPB_HANDLER_DOUBLE) - TRY(UPB_HANDLER_BOOL) - TRY(UPB_HANDLER_STARTSTR) - TRY(UPB_HANDLER_STRING) - TRY(UPB_HANDLER_ENDSTR) - TRY(UPB_HANDLER_STARTSUBMSG) - TRY(UPB_HANDLER_ENDSUBMSG) - TRY(UPB_HANDLER_STARTSEQ) - TRY(UPB_HANDLER_ENDSEQ) - } - upb_inttable_uninit(&t); - } -#undef TRY -#endif - - for(upb_msg_oneof_begin(&k, m), i = 0; - !upb_msg_oneof_done(&k); - upb_msg_oneof_next(&k), i++) { - upb_oneofdef *o = upb_msg_iter_oneof(&k); - o->index = i; - } - - upb_gfree(fields); - return true; -} - -bool _upb_def_validate(upb_def *const*defs, size_t n, upb_status *s) { - size_t i; - - /* First perform validation, in two passes so we can check that we have a - * transitive closure without needing to search. */ - for (i = 0; i < n; i++) { - upb_def *def = defs[i]; - if (upb_def_isfrozen(def)) { - /* Could relax this requirement if it's annoying. */ - upb_status_seterrmsg(s, "def is already frozen"); - goto err; - } else if (def->type == UPB_DEF_FIELD) { - upb_status_seterrmsg(s, "standalone fielddefs can not be frozen"); - goto err; - } else { - /* Set now to detect transitive closure in the second pass. */ - def->came_from_user = true; - - if (def->type == UPB_DEF_ENUM && - !upb_validate_enumdef(upb_dyncast_enumdef(def), s)) { - goto err; - } - } - } - - /* Second pass of validation. Also assign selector bases and indexes, and - * compact tables. */ - for (i = 0; i < n; i++) { - upb_def *def = defs[i]; - upb_msgdef *m = upb_dyncast_msgdef_mutable(def); - upb_enumdef *e = upb_dyncast_enumdef_mutable(def); - if (m) { - upb_inttable_compact(&m->itof); - if (!assign_msg_indices(m, s)) { - goto err; - } - } else if (e) { - upb_inttable_compact(&e->iton); - } - } - - return true; - -err: - for (i = 0; i < n; i++) { - upb_def *def = defs[i]; - def->came_from_user = false; - } - UPB_ASSERT(!(s && upb_ok(s))); - return false; -} - -bool upb_def_freeze(upb_def *const* defs, size_t n, upb_status *s) { - /* Def graph contains FieldDefs between each MessageDef, so double the - * limit. */ - const size_t maxdepth = UPB_MAX_MESSAGE_DEPTH * 2; - - if (!_upb_def_validate(defs, n, s)) { - return false; - } - - - /* Validation all passed; freeze the objects. */ - return upb_refcounted_freeze((upb_refcounted *const*)defs, n, s, maxdepth); -} - - -/* upb_enumdef ****************************************************************/ - -static void visitenum(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_enumdef *e = (const upb_enumdef*)r; - const upb_def *def = upb_enumdef_upcast(e); - if (upb_def_file(def)) { - visit(r, upb_filedef_upcast(upb_def_file(def)), closure); - } -} - -static void freeenum(upb_refcounted *r) { - upb_enumdef *e = (upb_enumdef*)r; - upb_inttable_iter i; - upb_inttable_begin(&i, &e->iton); - for( ; !upb_inttable_done(&i); upb_inttable_next(&i)) { - /* To clean up the upb_gstrdup() from upb_enumdef_addval(). */ - upb_gfree(upb_value_getcstr(upb_inttable_iter_value(&i))); - } - upb_strtable_uninit(&e->ntoi); - upb_inttable_uninit(&e->iton); - upb_def_uninit(upb_enumdef_upcast_mutable(e)); - upb_gfree(e); -} - -const struct upb_refcounted_vtbl upb_enumdef_vtbl = {&visitenum, &freeenum}; - -upb_enumdef *upb_enumdef_new(const void *owner) { - upb_enumdef *e = upb_gmalloc(sizeof(*e)); - if (!e) return NULL; - - if (!upb_def_init(upb_enumdef_upcast_mutable(e), UPB_DEF_ENUM, - &upb_enumdef_vtbl, owner)) { - goto err2; - } - - if (!upb_strtable_init(&e->ntoi, UPB_CTYPE_INT32)) goto err2; - if (!upb_inttable_init(&e->iton, UPB_CTYPE_CSTR)) goto err1; - return e; - -err1: - upb_strtable_uninit(&e->ntoi); -err2: - upb_gfree(e); - return NULL; -} - -bool upb_enumdef_freeze(upb_enumdef *e, upb_status *status) { - upb_def *d = upb_enumdef_upcast_mutable(e); - return upb_def_freeze(&d, 1, status); -} - -const char *upb_enumdef_fullname(const upb_enumdef *e) { - return upb_def_fullname(upb_enumdef_upcast(e)); -} - -const char *upb_enumdef_name(const upb_enumdef *e) { - return upb_def_name(upb_enumdef_upcast(e)); -} - -bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname, - upb_status *s) { - return upb_def_setfullname(upb_enumdef_upcast_mutable(e), fullname, s); -} - -bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num, - upb_status *status) { - char *name2; - - if (!upb_isident(name, strlen(name), false, status)) { - return false; - } - - if (upb_enumdef_ntoiz(e, name, NULL)) { - upb_status_seterrf(status, "name '%s' is already defined", name); - return false; - } - - if (!upb_strtable_insert(&e->ntoi, name, upb_value_int32(num))) { - upb_status_seterrmsg(status, "out of memory"); - return false; - } - - if (!upb_inttable_lookup(&e->iton, num, NULL)) { - name2 = upb_gstrdup(name); - if (!name2 || !upb_inttable_insert(&e->iton, num, upb_value_cstr(name2))) { - upb_status_seterrmsg(status, "out of memory"); - upb_strtable_remove(&e->ntoi, name, NULL); - return false; - } - } - - if (upb_enumdef_numvals(e) == 1) { - bool ok = upb_enumdef_setdefault(e, num, NULL); - UPB_ASSERT(ok); - } - - return true; -} - -int32_t upb_enumdef_default(const upb_enumdef *e) { - UPB_ASSERT(upb_enumdef_iton(e, e->defaultval)); - return e->defaultval; -} - -bool upb_enumdef_setdefault(upb_enumdef *e, int32_t val, upb_status *s) { - UPB_ASSERT(!upb_enumdef_isfrozen(e)); - if (!upb_enumdef_iton(e, val)) { - upb_status_seterrf(s, "number '%d' is not in the enum.", val); - return false; - } - e->defaultval = val; - return true; -} - -int upb_enumdef_numvals(const upb_enumdef *e) { - return upb_strtable_count(&e->ntoi); -} - -void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) { - /* We iterate over the ntoi table, to account for duplicate numbers. */ - upb_strtable_begin(i, &e->ntoi); -} - -void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); } -bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); } - -bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name, - size_t len, int32_t *num) { - upb_value v; - if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) { - return false; - } - if (num) *num = upb_value_getint32(v); - return true; -} - -const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) { - upb_value v; - return upb_inttable_lookup32(&def->iton, num, &v) ? - upb_value_getcstr(v) : NULL; -} - -const char *upb_enum_iter_name(upb_enum_iter *iter) { - return upb_strtable_iter_key(iter); -} - -int32_t upb_enum_iter_number(upb_enum_iter *iter) { - return upb_value_getint32(upb_strtable_iter_value(iter)); -} - - -/* upb_fielddef ***************************************************************/ - -static void upb_fielddef_init_default(upb_fielddef *f); - -static void upb_fielddef_uninit_default(upb_fielddef *f) { - if (f->type_is_set_ && f->default_is_string && f->defaultval.bytes) - freestr(f->defaultval.bytes); -} - -const char *upb_fielddef_fullname(const upb_fielddef *e) { - return upb_def_fullname(upb_fielddef_upcast(e)); -} - -static void visitfield(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_fielddef *f = (const upb_fielddef*)r; - const upb_def *def = upb_fielddef_upcast(f); - if (upb_fielddef_containingtype(f)) { - visit(r, upb_msgdef_upcast2(upb_fielddef_containingtype(f)), closure); - } - if (upb_fielddef_containingoneof(f)) { - visit(r, upb_oneofdef_upcast(upb_fielddef_containingoneof(f)), closure); - } - if (upb_fielddef_subdef(f)) { - visit(r, upb_def_upcast(upb_fielddef_subdef(f)), closure); - } - if (upb_def_file(def)) { - visit(r, upb_filedef_upcast(upb_def_file(def)), closure); - } -} - -static void freefield(upb_refcounted *r) { - upb_fielddef *f = (upb_fielddef*)r; - upb_fielddef_uninit_default(f); - if (f->subdef_is_symbolic) - upb_gfree(f->sub.name); - upb_def_uninit(upb_fielddef_upcast_mutable(f)); - upb_gfree(f); -} - -static const char *enumdefaultstr(const upb_fielddef *f) { - const upb_enumdef *e; - UPB_ASSERT(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); - e = upb_fielddef_enumsubdef(f); - if (f->default_is_string && f->defaultval.bytes) { - /* Default was explicitly set as a string. */ - str_t *s = f->defaultval.bytes; - return s->str; - } else if (e) { - if (!f->default_is_string) { - /* Default was explicitly set as an integer; look it up in enumdef. */ - const char *name = upb_enumdef_iton(e, f->defaultval.sint); - if (name) { - return name; - } - } else { - /* Default is completely unset; pull enumdef default. */ - if (upb_enumdef_numvals(e) > 0) { - const char *name = upb_enumdef_iton(e, upb_enumdef_default(e)); - UPB_ASSERT(name); - return name; - } - } - } - return NULL; -} - -static bool enumdefaultint32(const upb_fielddef *f, int32_t *val) { - const upb_enumdef *e; - UPB_ASSERT(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); - e = upb_fielddef_enumsubdef(f); - if (!f->default_is_string) { - /* Default was explicitly set as an integer. */ - *val = f->defaultval.sint; - return true; - } else if (e) { - if (f->defaultval.bytes) { - /* Default was explicitly set as a str; try to lookup corresponding int. */ - str_t *s = f->defaultval.bytes; - if (upb_enumdef_ntoiz(e, s->str, val)) { - return true; - } - } else { - /* Default is unset; try to pull in enumdef default. */ - if (upb_enumdef_numvals(e) > 0) { - *val = upb_enumdef_default(e); - return true; - } - } - } - return false; -} - -const struct upb_refcounted_vtbl upb_fielddef_vtbl = {visitfield, freefield}; - -upb_fielddef *upb_fielddef_new(const void *o) { - upb_fielddef *f = upb_gmalloc(sizeof(*f)); - if (!f) return NULL; - if (!upb_def_init(upb_fielddef_upcast_mutable(f), UPB_DEF_FIELD, - &upb_fielddef_vtbl, o)) { - upb_gfree(f); - return NULL; - } - f->msg.def = NULL; - f->sub.def = NULL; - f->oneof = NULL; - f->subdef_is_symbolic = false; - f->msg_is_symbolic = false; - f->label_ = UPB_LABEL_OPTIONAL; - f->type_ = UPB_TYPE_INT32; - f->number_ = 0; - f->type_is_set_ = false; - f->tagdelim = false; - f->is_extension_ = false; - f->lazy_ = false; - f->packed_ = true; - - /* For the moment we default this to UPB_INTFMT_VARIABLE, since it will work - * with all integer types and is in some since more "default" since the most - * normal-looking proto2 types int32/int64/uint32/uint64 use variable. - * - * Other options to consider: - * - there is no default; users must set this manually (like type). - * - default signed integers to UPB_INTFMT_ZIGZAG, since it's more likely to - * be an optimal default for signed integers. */ - f->intfmt = UPB_INTFMT_VARIABLE; - return f; -} - -bool upb_fielddef_typeisset(const upb_fielddef *f) { - return f->type_is_set_; -} - -upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) { - UPB_ASSERT(f->type_is_set_); - return f->type_; -} - -uint32_t upb_fielddef_index(const upb_fielddef *f) { - return f->index_; -} - -upb_label_t upb_fielddef_label(const upb_fielddef *f) { - return f->label_; -} - -upb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f) { - return f->intfmt; -} - -bool upb_fielddef_istagdelim(const upb_fielddef *f) { - return f->tagdelim; -} - -uint32_t upb_fielddef_number(const upb_fielddef *f) { - return f->number_; -} - -bool upb_fielddef_isextension(const upb_fielddef *f) { - return f->is_extension_; -} - -bool upb_fielddef_lazy(const upb_fielddef *f) { - return f->lazy_; -} - -bool upb_fielddef_packed(const upb_fielddef *f) { - return f->packed_; -} - -const char *upb_fielddef_name(const upb_fielddef *f) { - return upb_def_fullname(upb_fielddef_upcast(f)); -} - -size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len) { - const char *name = upb_fielddef_name(f); - size_t src, dst = 0; - bool ucase_next = false; - -#define WRITE(byte) \ - ++dst; \ - if (dst < len) buf[dst - 1] = byte; \ - else if (dst == len) buf[dst - 1] = '\0' - - if (!name) { - WRITE('\0'); - return 0; - } - - /* Implement the transformation as described in the spec: - * 1. upper case all letters after an underscore. - * 2. remove all underscores. - */ - for (src = 0; name[src]; src++) { - if (name[src] == '_') { - ucase_next = true; - continue; - } - - if (ucase_next) { - WRITE(toupper(name[src])); - ucase_next = false; - } else { - WRITE(name[src]); - } - } - - WRITE('\0'); - return dst; - -#undef WRITE -} - -const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) { - return f->msg_is_symbolic ? NULL : f->msg.def; -} - -const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) { - return f->oneof; -} - -upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f) { - return (upb_msgdef*)upb_fielddef_containingtype(f); -} - -const char *upb_fielddef_containingtypename(upb_fielddef *f) { - return f->msg_is_symbolic ? f->msg.name : NULL; -} - -static void release_containingtype(upb_fielddef *f) { - if (f->msg_is_symbolic) upb_gfree(f->msg.name); -} - -bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name, - upb_status *s) { - char *name_copy; - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - if (upb_fielddef_containingtype(f)) { - upb_status_seterrmsg(s, "field has already been added to a message."); - return false; - } - /* TODO: validate name (upb_isident() doesn't quite work atm because this name - * may have a leading "."). */ - - name_copy = upb_gstrdup(name); - if (!name_copy) { - upb_upberr_setoom(s); - return false; - } - - release_containingtype(f); - f->msg.name = name_copy; - f->msg_is_symbolic = true; - return true; -} - -bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s) { - if (upb_fielddef_containingtype(f) || upb_fielddef_containingoneof(f)) { - upb_status_seterrmsg(s, "Already added to message or oneof"); - return false; - } - return upb_def_setfullname(upb_fielddef_upcast_mutable(f), name, s); -} - -static void chkdefaulttype(const upb_fielddef *f, upb_fieldtype_t type) { - UPB_UNUSED(f); - UPB_UNUSED(type); - UPB_ASSERT(f->type_is_set_ && upb_fielddef_type(f) == type); -} - -int64_t upb_fielddef_defaultint64(const upb_fielddef *f) { - chkdefaulttype(f, UPB_TYPE_INT64); - return f->defaultval.sint; -} - -int32_t upb_fielddef_defaultint32(const upb_fielddef *f) { - if (f->type_is_set_ && upb_fielddef_type(f) == UPB_TYPE_ENUM) { - int32_t val; - bool ok = enumdefaultint32(f, &val); - UPB_ASSERT(ok); - return val; - } else { - chkdefaulttype(f, UPB_TYPE_INT32); - return f->defaultval.sint; - } -} - -uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) { - chkdefaulttype(f, UPB_TYPE_UINT64); - return f->defaultval.uint; -} - -uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) { - chkdefaulttype(f, UPB_TYPE_UINT32); - return f->defaultval.uint; -} - -bool upb_fielddef_defaultbool(const upb_fielddef *f) { - chkdefaulttype(f, UPB_TYPE_BOOL); - return f->defaultval.uint; -} - -float upb_fielddef_defaultfloat(const upb_fielddef *f) { - chkdefaulttype(f, UPB_TYPE_FLOAT); - return f->defaultval.flt; -} - -double upb_fielddef_defaultdouble(const upb_fielddef *f) { - chkdefaulttype(f, UPB_TYPE_DOUBLE); - return f->defaultval.dbl; -} - -const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) { - UPB_ASSERT(f->type_is_set_); - UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_STRING || - upb_fielddef_type(f) == UPB_TYPE_BYTES || - upb_fielddef_type(f) == UPB_TYPE_ENUM); - - if (upb_fielddef_type(f) == UPB_TYPE_ENUM) { - const char *ret = enumdefaultstr(f); - UPB_ASSERT(ret); - /* Enum defaults can't have embedded NULLs. */ - if (len) *len = strlen(ret); - return ret; - } - - if (f->default_is_string) { - str_t *str = f->defaultval.bytes; - if (len) *len = str->len; - return str->str; - } - - return NULL; -} - -static void upb_fielddef_init_default(upb_fielddef *f) { - f->default_is_string = false; - switch (upb_fielddef_type(f)) { - case UPB_TYPE_DOUBLE: f->defaultval.dbl = 0; break; - case UPB_TYPE_FLOAT: f->defaultval.flt = 0; break; - case UPB_TYPE_INT32: - case UPB_TYPE_INT64: f->defaultval.sint = 0; break; - case UPB_TYPE_UINT64: - case UPB_TYPE_UINT32: - case UPB_TYPE_BOOL: f->defaultval.uint = 0; break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - f->defaultval.bytes = newstr("", 0); - f->default_is_string = true; - break; - case UPB_TYPE_MESSAGE: break; - case UPB_TYPE_ENUM: - /* This is our special sentinel that indicates "not set" for an enum. */ - f->default_is_string = true; - f->defaultval.bytes = NULL; - break; - } -} - -const upb_def *upb_fielddef_subdef(const upb_fielddef *f) { - return f->subdef_is_symbolic ? NULL : f->sub.def; -} - -const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) { - const upb_def *def = upb_fielddef_subdef(f); - return def ? upb_dyncast_msgdef(def) : NULL; -} - -const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) { - const upb_def *def = upb_fielddef_subdef(f); - return def ? upb_dyncast_enumdef(def) : NULL; -} - -upb_def *upb_fielddef_subdef_mutable(upb_fielddef *f) { - return (upb_def*)upb_fielddef_subdef(f); -} - -const char *upb_fielddef_subdefname(const upb_fielddef *f) { - if (f->subdef_is_symbolic) { - return f->sub.name; - } else if (f->sub.def) { - return upb_def_fullname(f->sub.def); - } else { - return NULL; - } -} - -bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s) { - if (upb_fielddef_containingtype(f)) { - upb_status_seterrmsg( - s, "cannot change field number after adding to a message"); - return false; - } - if (number == 0 || number > UPB_MAX_FIELDNUMBER) { - upb_status_seterrf(s, "invalid field number (%u)", number); - return false; - } - f->number_ = number; - return true; -} - -void upb_fielddef_settype(upb_fielddef *f, upb_fieldtype_t type) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - UPB_ASSERT(upb_fielddef_checktype(type)); - upb_fielddef_uninit_default(f); - f->type_ = type; - f->type_is_set_ = true; - upb_fielddef_init_default(f); -} - -void upb_fielddef_setdescriptortype(upb_fielddef *f, int type) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - switch (type) { - case UPB_DESCRIPTOR_TYPE_DOUBLE: - upb_fielddef_settype(f, UPB_TYPE_DOUBLE); - break; - case UPB_DESCRIPTOR_TYPE_FLOAT: - upb_fielddef_settype(f, UPB_TYPE_FLOAT); - break; - case UPB_DESCRIPTOR_TYPE_INT64: - case UPB_DESCRIPTOR_TYPE_SFIXED64: - case UPB_DESCRIPTOR_TYPE_SINT64: - upb_fielddef_settype(f, UPB_TYPE_INT64); - break; - case UPB_DESCRIPTOR_TYPE_UINT64: - case UPB_DESCRIPTOR_TYPE_FIXED64: - upb_fielddef_settype(f, UPB_TYPE_UINT64); - break; - case UPB_DESCRIPTOR_TYPE_INT32: - case UPB_DESCRIPTOR_TYPE_SFIXED32: - case UPB_DESCRIPTOR_TYPE_SINT32: - upb_fielddef_settype(f, UPB_TYPE_INT32); - break; - case UPB_DESCRIPTOR_TYPE_UINT32: - case UPB_DESCRIPTOR_TYPE_FIXED32: - upb_fielddef_settype(f, UPB_TYPE_UINT32); - break; - case UPB_DESCRIPTOR_TYPE_BOOL: - upb_fielddef_settype(f, UPB_TYPE_BOOL); - break; - case UPB_DESCRIPTOR_TYPE_STRING: - upb_fielddef_settype(f, UPB_TYPE_STRING); - break; - case UPB_DESCRIPTOR_TYPE_BYTES: - upb_fielddef_settype(f, UPB_TYPE_BYTES); - break; - case UPB_DESCRIPTOR_TYPE_GROUP: - case UPB_DESCRIPTOR_TYPE_MESSAGE: - upb_fielddef_settype(f, UPB_TYPE_MESSAGE); - break; - case UPB_DESCRIPTOR_TYPE_ENUM: - upb_fielddef_settype(f, UPB_TYPE_ENUM); - break; - default: UPB_ASSERT(false); - } - - if (type == UPB_DESCRIPTOR_TYPE_FIXED64 || - type == UPB_DESCRIPTOR_TYPE_FIXED32 || - type == UPB_DESCRIPTOR_TYPE_SFIXED64 || - type == UPB_DESCRIPTOR_TYPE_SFIXED32) { - upb_fielddef_setintfmt(f, UPB_INTFMT_FIXED); - } else if (type == UPB_DESCRIPTOR_TYPE_SINT64 || - type == UPB_DESCRIPTOR_TYPE_SINT32) { - upb_fielddef_setintfmt(f, UPB_INTFMT_ZIGZAG); - } else { - upb_fielddef_setintfmt(f, UPB_INTFMT_VARIABLE); - } - - upb_fielddef_settagdelim(f, type == UPB_DESCRIPTOR_TYPE_GROUP); -} - -upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) { - switch (upb_fielddef_type(f)) { - case UPB_TYPE_FLOAT: return UPB_DESCRIPTOR_TYPE_FLOAT; - case UPB_TYPE_DOUBLE: return UPB_DESCRIPTOR_TYPE_DOUBLE; - case UPB_TYPE_BOOL: return UPB_DESCRIPTOR_TYPE_BOOL; - case UPB_TYPE_STRING: return UPB_DESCRIPTOR_TYPE_STRING; - case UPB_TYPE_BYTES: return UPB_DESCRIPTOR_TYPE_BYTES; - case UPB_TYPE_ENUM: return UPB_DESCRIPTOR_TYPE_ENUM; - case UPB_TYPE_INT32: - switch (upb_fielddef_intfmt(f)) { - case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_INT32; - case UPB_INTFMT_FIXED: return UPB_DESCRIPTOR_TYPE_SFIXED32; - case UPB_INTFMT_ZIGZAG: return UPB_DESCRIPTOR_TYPE_SINT32; - } - case UPB_TYPE_INT64: - switch (upb_fielddef_intfmt(f)) { - case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_INT64; - case UPB_INTFMT_FIXED: return UPB_DESCRIPTOR_TYPE_SFIXED64; - case UPB_INTFMT_ZIGZAG: return UPB_DESCRIPTOR_TYPE_SINT64; - } - case UPB_TYPE_UINT32: - switch (upb_fielddef_intfmt(f)) { - case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_UINT32; - case UPB_INTFMT_FIXED: return UPB_DESCRIPTOR_TYPE_FIXED32; - case UPB_INTFMT_ZIGZAG: return -1; - } - case UPB_TYPE_UINT64: - switch (upb_fielddef_intfmt(f)) { - case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_UINT64; - case UPB_INTFMT_FIXED: return UPB_DESCRIPTOR_TYPE_FIXED64; - case UPB_INTFMT_ZIGZAG: return -1; - } - case UPB_TYPE_MESSAGE: - return upb_fielddef_istagdelim(f) ? - UPB_DESCRIPTOR_TYPE_GROUP : UPB_DESCRIPTOR_TYPE_MESSAGE; - } - return 0; -} - -void upb_fielddef_setisextension(upb_fielddef *f, bool is_extension) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - f->is_extension_ = is_extension; -} - -void upb_fielddef_setlazy(upb_fielddef *f, bool lazy) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - f->lazy_ = lazy; -} - -void upb_fielddef_setpacked(upb_fielddef *f, bool packed) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - f->packed_ = packed; -} - -void upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - UPB_ASSERT(upb_fielddef_checklabel(label)); - f->label_ = label; -} - -void upb_fielddef_setintfmt(upb_fielddef *f, upb_intfmt_t fmt) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - UPB_ASSERT(upb_fielddef_checkintfmt(fmt)); - f->intfmt = fmt; -} - -void upb_fielddef_settagdelim(upb_fielddef *f, bool tag_delim) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - f->tagdelim = tag_delim; - f->tagdelim = tag_delim; -} - -static bool checksetdefault(upb_fielddef *f, upb_fieldtype_t type) { - if (!f->type_is_set_ || upb_fielddef_isfrozen(f) || - upb_fielddef_type(f) != type) { - UPB_ASSERT(false); - return false; - } - if (f->default_is_string) { - str_t *s = f->defaultval.bytes; - UPB_ASSERT(s || type == UPB_TYPE_ENUM); - if (s) freestr(s); - } - f->default_is_string = false; - return true; -} - -void upb_fielddef_setdefaultint64(upb_fielddef *f, int64_t value) { - if (checksetdefault(f, UPB_TYPE_INT64)) - f->defaultval.sint = value; -} - -void upb_fielddef_setdefaultint32(upb_fielddef *f, int32_t value) { - if ((upb_fielddef_type(f) == UPB_TYPE_ENUM && - checksetdefault(f, UPB_TYPE_ENUM)) || - checksetdefault(f, UPB_TYPE_INT32)) { - f->defaultval.sint = value; - } -} - -void upb_fielddef_setdefaultuint64(upb_fielddef *f, uint64_t value) { - if (checksetdefault(f, UPB_TYPE_UINT64)) - f->defaultval.uint = value; -} - -void upb_fielddef_setdefaultuint32(upb_fielddef *f, uint32_t value) { - if (checksetdefault(f, UPB_TYPE_UINT32)) - f->defaultval.uint = value; -} - -void upb_fielddef_setdefaultbool(upb_fielddef *f, bool value) { - if (checksetdefault(f, UPB_TYPE_BOOL)) - f->defaultval.uint = value; -} - -void upb_fielddef_setdefaultfloat(upb_fielddef *f, float value) { - if (checksetdefault(f, UPB_TYPE_FLOAT)) - f->defaultval.flt = value; -} - -void upb_fielddef_setdefaultdouble(upb_fielddef *f, double value) { - if (checksetdefault(f, UPB_TYPE_DOUBLE)) - f->defaultval.dbl = value; -} - -bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len, - upb_status *s) { - str_t *str2; - UPB_ASSERT(upb_fielddef_isstring(f) || f->type_ == UPB_TYPE_ENUM); - if (f->type_ == UPB_TYPE_ENUM && !upb_isident(str, len, false, s)) - return false; - - if (f->default_is_string) { - str_t *s = f->defaultval.bytes; - UPB_ASSERT(s || f->type_ == UPB_TYPE_ENUM); - if (s) freestr(s); - } else { - UPB_ASSERT(f->type_ == UPB_TYPE_ENUM); - } - - str2 = newstr(str, len); - f->defaultval.bytes = str2; - f->default_is_string = true; - return true; -} - -void upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str, - upb_status *s) { - UPB_ASSERT(f->type_is_set_); - upb_fielddef_setdefaultstr(f, str, str ? strlen(str) : 0, s); -} - -bool upb_fielddef_enumhasdefaultint32(const upb_fielddef *f) { - int32_t val; - UPB_ASSERT(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); - return enumdefaultint32(f, &val); -} - -bool upb_fielddef_enumhasdefaultstr(const upb_fielddef *f) { - UPB_ASSERT(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); - return enumdefaultstr(f) != NULL; -} - -static bool upb_subdef_typecheck(upb_fielddef *f, const upb_def *subdef, - upb_status *s) { - if (f->type_ == UPB_TYPE_MESSAGE) { - if (upb_dyncast_msgdef(subdef)) return true; - upb_status_seterrmsg(s, "invalid subdef type for this submessage field"); - return false; - } else if (f->type_ == UPB_TYPE_ENUM) { - if (upb_dyncast_enumdef(subdef)) return true; - upb_status_seterrmsg(s, "invalid subdef type for this enum field"); - return false; - } else { - upb_status_seterrmsg(s, "only message and enum fields can have a subdef"); - return false; - } -} - -static void release_subdef(upb_fielddef *f) { - if (f->subdef_is_symbolic) { - upb_gfree(f->sub.name); - } else if (f->sub.def) { - upb_unref2(f->sub.def, f); - } -} - -bool upb_fielddef_setsubdef(upb_fielddef *f, const upb_def *subdef, - upb_status *s) { - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - UPB_ASSERT(upb_fielddef_hassubdef(f)); - if (subdef && !upb_subdef_typecheck(f, subdef, s)) return false; - release_subdef(f); - f->sub.def = subdef; - f->subdef_is_symbolic = false; - if (f->sub.def) upb_ref2(f->sub.def, f); - return true; -} - -bool upb_fielddef_setmsgsubdef(upb_fielddef *f, const upb_msgdef *subdef, - upb_status *s) { - return upb_fielddef_setsubdef(f, upb_msgdef_upcast(subdef), s); -} - -bool upb_fielddef_setenumsubdef(upb_fielddef *f, const upb_enumdef *subdef, - upb_status *s) { - return upb_fielddef_setsubdef(f, upb_enumdef_upcast(subdef), s); -} - -bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name, - upb_status *s) { - char *name_copy; - UPB_ASSERT(!upb_fielddef_isfrozen(f)); - if (!upb_fielddef_hassubdef(f)) { - upb_status_seterrmsg(s, "field type does not accept a subdef"); - return false; - } - - name_copy = upb_gstrdup(name); - if (!name_copy) { - upb_upberr_setoom(s); - return false; - } - - /* TODO: validate name (upb_isident() doesn't quite work atm because this name - * may have a leading "."). */ - release_subdef(f); - f->sub.name = name_copy; - f->subdef_is_symbolic = true; - return true; -} - -bool upb_fielddef_issubmsg(const upb_fielddef *f) { - return upb_fielddef_type(f) == UPB_TYPE_MESSAGE; -} - -bool upb_fielddef_isstring(const upb_fielddef *f) { - return upb_fielddef_type(f) == UPB_TYPE_STRING || - upb_fielddef_type(f) == UPB_TYPE_BYTES; -} - -bool upb_fielddef_isseq(const upb_fielddef *f) { - return upb_fielddef_label(f) == UPB_LABEL_REPEATED; -} - -bool upb_fielddef_isprimitive(const upb_fielddef *f) { - return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f); -} - -bool upb_fielddef_ismap(const upb_fielddef *f) { - return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) && - upb_msgdef_mapentry(upb_fielddef_msgsubdef(f)); -} - -bool upb_fielddef_haspresence(const upb_fielddef *f) { - if (upb_fielddef_isseq(f)) return false; - if (upb_fielddef_issubmsg(f)) return true; - - /* Primitive field: return true unless there is a message that specifies - * presence should not exist. */ - if (f->msg_is_symbolic || !f->msg.def) return true; - return f->msg.def->syntax == UPB_SYNTAX_PROTO2; -} - -bool upb_fielddef_hassubdef(const upb_fielddef *f) { - return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM; -} - -static bool between(int32_t x, int32_t low, int32_t high) { - return x >= low && x <= high; -} - -bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); } -bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); } -bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); } - -bool upb_fielddef_checkdescriptortype(int32_t type) { - return between(type, 1, 18); -} - -/* upb_msgdef *****************************************************************/ - -static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - upb_msg_oneof_iter o; - const upb_msgdef *m = (const upb_msgdef*)r; - const upb_def *def = upb_msgdef_upcast(m); - upb_msg_field_iter i; - for(upb_msg_field_begin(&i, m); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - visit(r, upb_fielddef_upcast2(f), closure); - } - for(upb_msg_oneof_begin(&o, m); - !upb_msg_oneof_done(&o); - upb_msg_oneof_next(&o)) { - upb_oneofdef *f = upb_msg_iter_oneof(&o); - visit(r, upb_oneofdef_upcast(f), closure); - } - if (upb_def_file(def)) { - visit(r, upb_filedef_upcast(upb_def_file(def)), closure); - } -} - -static void freemsg(upb_refcounted *r) { - upb_msgdef *m = (upb_msgdef*)r; - upb_strtable_uninit(&m->ntof); - upb_inttable_uninit(&m->itof); - upb_def_uninit(upb_msgdef_upcast_mutable(m)); - upb_gfree(m); -} - -const struct upb_refcounted_vtbl upb_msgdef_vtbl = {visitmsg, freemsg}; - -upb_msgdef *upb_msgdef_new(const void *owner) { - upb_msgdef *m = upb_gmalloc(sizeof(*m)); - if (!m) return NULL; - - if (!upb_def_init(upb_msgdef_upcast_mutable(m), UPB_DEF_MSG, &upb_msgdef_vtbl, - owner)) { - goto err2; - } - - if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err2; - if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err1; - m->map_entry = false; - m->syntax = UPB_SYNTAX_PROTO2; - return m; - -err1: - upb_inttable_uninit(&m->itof); -err2: - upb_gfree(m); - return NULL; -} - -bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status) { - upb_def *d = upb_msgdef_upcast_mutable(m); - return upb_def_freeze(&d, 1, status); -} - -const char *upb_msgdef_fullname(const upb_msgdef *m) { - return upb_def_fullname(upb_msgdef_upcast(m)); -} - -const char *upb_msgdef_name(const upb_msgdef *m) { - return upb_def_name(upb_msgdef_upcast(m)); -} - -bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, - upb_status *s) { - return upb_def_setfullname(upb_msgdef_upcast_mutable(m), fullname, s); -} - -bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax) { - if (syntax != UPB_SYNTAX_PROTO2 && syntax != UPB_SYNTAX_PROTO3) { - return false; - } - - m->syntax = syntax; - return true; -} - -upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) { - return m->syntax; -} - -/* Helper: check that the field |f| is safe to add to msgdef |m|. Set an error - * on status |s| and return false if not. */ -static bool check_field_add(const upb_msgdef *m, const upb_fielddef *f, - upb_status *s) { - if (upb_fielddef_containingtype(f) != NULL) { - upb_status_seterrmsg(s, "fielddef already belongs to a message"); - return false; - } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { - upb_status_seterrmsg(s, "field name or number were not set"); - return false; - } else if (upb_msgdef_itof(m, upb_fielddef_number(f))) { - upb_status_seterrmsg(s, "duplicate field number"); - return false; - } else if (upb_strtable_lookup(&m->ntof, upb_fielddef_name(f), NULL)) { - upb_status_seterrmsg(s, "name conflicts with existing field or oneof"); - return false; - } - return true; -} - -static void add_field(upb_msgdef *m, upb_fielddef *f, const void *ref_donor) { - release_containingtype(f); - f->msg.def = m; - f->msg_is_symbolic = false; - upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f)); - upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f)); - upb_ref2(f, m); - upb_ref2(m, f); - if (ref_donor) upb_fielddef_unref(f, ref_donor); -} - -bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor, - upb_status *s) { - /* TODO: extensions need to have a separate namespace, because proto2 allows a - * top-level extension (ie. one not in any package) to have the same name as a - * field from the message. - * - * This also implies that there needs to be a separate lookup-by-name method - * for extensions. It seems desirable for iteration to return both extensions - * and non-extensions though. - * - * We also need to validate that the field number is in an extension range iff - * it is an extension. - * - * This method is idempotent. Check if |f| is already part of this msgdef and - * return immediately if so. */ - if (upb_fielddef_containingtype(f) == m) { - if (ref_donor) upb_fielddef_unref(f, ref_donor); - return true; - } - - /* Check constraints for all fields before performing any action. */ - if (!check_field_add(m, f, s)) { - return false; - } else if (upb_fielddef_containingoneof(f) != NULL) { - /* Fields in a oneof can only be added by adding the oneof to the msgdef. */ - upb_status_seterrmsg(s, "fielddef is part of a oneof"); - return false; - } - - /* Constraint checks ok, perform the action. */ - add_field(m, f, ref_donor); - return true; -} - -bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, - upb_status *s) { - upb_oneof_iter it; - - /* Check various conditions that would prevent this oneof from being added. */ - if (upb_oneofdef_containingtype(o)) { - upb_status_seterrmsg(s, "oneofdef already belongs to a message"); - return false; - } else if (upb_oneofdef_name(o) == NULL) { - upb_status_seterrmsg(s, "oneofdef name was not set"); - return false; - } else if (upb_strtable_lookup(&m->ntof, upb_oneofdef_name(o), NULL)) { - upb_status_seterrmsg(s, "name conflicts with existing field or oneof"); - return false; - } - - /* Check that all of the oneof's fields do not conflict with names or numbers - * of fields already in the message. */ - for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) { - const upb_fielddef *f = upb_oneof_iter_field(&it); - if (!check_field_add(m, f, s)) { - return false; - } - } - - /* Everything checks out -- commit now. */ - - /* Add oneof itself first. */ - o->parent = m; - upb_strtable_insert(&m->ntof, upb_oneofdef_name(o), upb_value_ptr(o)); - upb_ref2(o, m); - upb_ref2(m, o); - - /* Add each field of the oneof directly to the msgdef. */ - for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) { - upb_fielddef *f = upb_oneof_iter_field(&it); - add_field(m, f, NULL); - } - - if (ref_donor) upb_oneofdef_unref(o, ref_donor); - - return true; -} - -const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) { - upb_value val; - return upb_inttable_lookup32(&m->itof, i, &val) ? - upb_value_getptr(val) : NULL; -} - -const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name, - size_t len) { - upb_value val; - - if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { - return NULL; - } - - return upb_trygetfield(upb_value_getptr(val)); -} - -const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, - size_t len) { - upb_value val; - - if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { - return NULL; - } - - return upb_trygetoneof(upb_value_getptr(val)); -} - -bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len, - const upb_fielddef **f, const upb_oneofdef **o) { - upb_value val; - - if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { - return false; - } - - *o = upb_trygetoneof(upb_value_getptr(val)); - *f = upb_trygetfield(upb_value_getptr(val)); - UPB_ASSERT((*o != NULL) ^ (*f != NULL)); /* Exactly one of the two should be set. */ - return true; -} - -int upb_msgdef_numfields(const upb_msgdef *m) { - /* The number table contains only fields. */ - return upb_inttable_count(&m->itof); -} - -int upb_msgdef_numoneofs(const upb_msgdef *m) { - /* The name table includes oneofs, and the number table does not. */ - return upb_strtable_count(&m->ntof) - upb_inttable_count(&m->itof); -} - -void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry) { - UPB_ASSERT(!upb_msgdef_isfrozen(m)); - m->map_entry = map_entry; -} - -bool upb_msgdef_mapentry(const upb_msgdef *m) { - return m->map_entry; -} - -void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) { - upb_inttable_begin(iter, &m->itof); -} - -void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); } - -bool upb_msg_field_done(const upb_msg_field_iter *iter) { - return upb_inttable_done(iter); -} - -upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) { - return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter)); -} - -void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) { - upb_inttable_iter_setdone(iter); -} - -void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) { - upb_strtable_begin(iter, &m->ntof); - /* We need to skip past any initial fields. */ - while (!upb_strtable_done(iter) && - !upb_isoneof(upb_value_getptr(upb_strtable_iter_value(iter)))) { - upb_strtable_next(iter); - } -} - -void upb_msg_oneof_next(upb_msg_oneof_iter *iter) { - /* We need to skip past fields to return only oneofs. */ - do { - upb_strtable_next(iter); - } while (!upb_strtable_done(iter) && - !upb_isoneof(upb_value_getptr(upb_strtable_iter_value(iter)))); -} - -bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) { - return upb_strtable_done(iter); -} - -upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) { - return (upb_oneofdef*)upb_value_getptr(upb_strtable_iter_value(iter)); -} - -void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) { - upb_strtable_iter_setdone(iter); -} - -/* upb_oneofdef ***************************************************************/ - -static void visitoneof(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_oneofdef *o = (const upb_oneofdef*)r; - upb_oneof_iter i; - for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) { - const upb_fielddef *f = upb_oneof_iter_field(&i); - visit(r, upb_fielddef_upcast2(f), closure); - } - if (o->parent) { - visit(r, upb_msgdef_upcast2(o->parent), closure); - } -} - -static void freeoneof(upb_refcounted *r) { - upb_oneofdef *o = (upb_oneofdef*)r; - upb_strtable_uninit(&o->ntof); - upb_inttable_uninit(&o->itof); - upb_gfree((void*)o->name); - upb_gfree(o); -} - -const struct upb_refcounted_vtbl upb_oneofdef_vtbl = {visitoneof, freeoneof}; - -upb_oneofdef *upb_oneofdef_new(const void *owner) { - upb_oneofdef *o = upb_gmalloc(sizeof(*o)); - - if (!o) { - return NULL; - } - - o->parent = NULL; - o->name = NULL; - - if (!upb_refcounted_init(upb_oneofdef_upcast_mutable(o), &upb_oneofdef_vtbl, - owner)) { - goto err2; - } - - if (!upb_inttable_init(&o->itof, UPB_CTYPE_PTR)) goto err2; - if (!upb_strtable_init(&o->ntof, UPB_CTYPE_PTR)) goto err1; - - return o; - -err1: - upb_inttable_uninit(&o->itof); -err2: - upb_gfree(o); - return NULL; -} - -const char *upb_oneofdef_name(const upb_oneofdef *o) { return o->name; } - -bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s) { - UPB_ASSERT(!upb_oneofdef_isfrozen(o)); - if (upb_oneofdef_containingtype(o)) { - upb_status_seterrmsg(s, "oneof already added to a message"); - return false; - } - - if (!upb_isident(name, strlen(name), true, s)) { - return false; - } - - name = upb_gstrdup(name); - if (!name) { - upb_status_seterrmsg(s, "One of memory"); - return false; - } - - upb_gfree((void*)o->name); - o->name = name; - return true; -} - -const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) { - return o->parent; -} - -int upb_oneofdef_numfields(const upb_oneofdef *o) { - return upb_strtable_count(&o->ntof); -} - -uint32_t upb_oneofdef_index(const upb_oneofdef *o) { - return o->index; -} - -bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f, - const void *ref_donor, - upb_status *s) { - UPB_ASSERT(!upb_oneofdef_isfrozen(o)); - UPB_ASSERT(!o->parent || !upb_msgdef_isfrozen(o->parent)); - - /* This method is idempotent. Check if |f| is already part of this oneofdef - * and return immediately if so. */ - if (upb_fielddef_containingoneof(f) == o) { - return true; - } - - /* The field must have an OPTIONAL label. */ - if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) { - upb_status_seterrmsg(s, "fields in oneof must have OPTIONAL label"); - return false; - } - - /* Check that no field with this name or number exists already in the oneof. - * Also check that the field is not already part of a oneof. */ - if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { - upb_status_seterrmsg(s, "field name or number were not set"); - return false; - } else if (upb_oneofdef_itof(o, upb_fielddef_number(f)) || - upb_oneofdef_ntofz(o, upb_fielddef_name(f))) { - upb_status_seterrmsg(s, "duplicate field name or number"); - return false; - } else if (upb_fielddef_containingoneof(f) != NULL) { - upb_status_seterrmsg(s, "fielddef already belongs to a oneof"); - return false; - } - - /* We allow adding a field to the oneof either if the field is not part of a - * msgdef, or if it is and we are also part of the same msgdef. */ - if (o->parent == NULL) { - /* If we're not in a msgdef, the field cannot be either. Otherwise we would - * need to magically add this oneof to a msgdef to remain consistent, which - * is surprising behavior. */ - if (upb_fielddef_containingtype(f) != NULL) { - upb_status_seterrmsg(s, "fielddef already belongs to a message, but " - "oneof does not"); - return false; - } - } else { - /* If we're in a msgdef, the user can add fields that either aren't in any - * msgdef (in which case they're added to our msgdef) or already a part of - * our msgdef. */ - if (upb_fielddef_containingtype(f) != NULL && - upb_fielddef_containingtype(f) != o->parent) { - upb_status_seterrmsg(s, "fielddef belongs to a different message " - "than oneof"); - return false; - } - } - - /* Commit phase. First add the field to our parent msgdef, if any, because - * that may fail; then add the field to our own tables. */ - - if (o->parent != NULL && upb_fielddef_containingtype(f) == NULL) { - if (!upb_msgdef_addfield((upb_msgdef*)o->parent, f, NULL, s)) { - return false; - } - } - - release_containingtype(f); - f->oneof = o; - upb_inttable_insert(&o->itof, upb_fielddef_number(f), upb_value_ptr(f)); - upb_strtable_insert(&o->ntof, upb_fielddef_name(f), upb_value_ptr(f)); - upb_ref2(f, o); - upb_ref2(o, f); - if (ref_donor) upb_fielddef_unref(f, ref_donor); - - return true; -} - -const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, - const char *name, size_t length) { - upb_value val; - return upb_strtable_lookup2(&o->ntof, name, length, &val) ? - upb_value_getptr(val) : NULL; -} - -const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) { - upb_value val; - return upb_inttable_lookup32(&o->itof, num, &val) ? - upb_value_getptr(val) : NULL; -} - -void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) { - upb_inttable_begin(iter, &o->itof); -} - -void upb_oneof_next(upb_oneof_iter *iter) { - upb_inttable_next(iter); -} - -bool upb_oneof_done(upb_oneof_iter *iter) { - return upb_inttable_done(iter); -} - -upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) { - return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter)); -} - -void upb_oneof_iter_setdone(upb_oneof_iter *iter) { - upb_inttable_iter_setdone(iter); -} - -/* upb_filedef ****************************************************************/ - -static void visitfiledef(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_filedef *f = (const upb_filedef*)r; - size_t i; - - for(i = 0; i < upb_filedef_defcount(f); i++) { - visit(r, upb_def_upcast(upb_filedef_def(f, i)), closure); - } -} - -static void freefiledef(upb_refcounted *r) { - upb_filedef *f = (upb_filedef*)r; - size_t i; - - for(i = 0; i < upb_filedef_depcount(f); i++) { - upb_filedef_unref(upb_filedef_dep(f, i), f); - } - - upb_inttable_uninit(&f->defs); - upb_inttable_uninit(&f->deps); - upb_gfree((void*)f->name); - upb_gfree((void*)f->package); - upb_gfree((void*)f->phpprefix); - upb_gfree((void*)f->phpnamespace); - upb_gfree(f); -} - -const struct upb_refcounted_vtbl upb_filedef_vtbl = {visitfiledef, freefiledef}; - -upb_filedef *upb_filedef_new(const void *owner) { - upb_filedef *f = upb_gmalloc(sizeof(*f)); - - if (!f) { - return NULL; - } - - f->package = NULL; - f->name = NULL; - f->phpprefix = NULL; - f->phpnamespace = NULL; - f->syntax = UPB_SYNTAX_PROTO2; - - if (!upb_refcounted_init(upb_filedef_upcast_mutable(f), &upb_filedef_vtbl, - owner)) { - goto err; - } - - if (!upb_inttable_init(&f->defs, UPB_CTYPE_CONSTPTR)) { - goto err; - } - - if (!upb_inttable_init(&f->deps, UPB_CTYPE_CONSTPTR)) { - goto err2; - } - - return f; - - -err2: - upb_inttable_uninit(&f->defs); - -err: - upb_gfree(f); - return NULL; -} - -const char *upb_filedef_name(const upb_filedef *f) { - return f->name; -} - -const char *upb_filedef_package(const upb_filedef *f) { - return f->package; -} - -const char *upb_filedef_phpprefix(const upb_filedef *f) { - return f->phpprefix; -} - -const char *upb_filedef_phpnamespace(const upb_filedef *f) { - return f->phpnamespace; -} - -upb_syntax_t upb_filedef_syntax(const upb_filedef *f) { - return f->syntax; -} - -size_t upb_filedef_defcount(const upb_filedef *f) { - return upb_inttable_count(&f->defs); -} - -size_t upb_filedef_depcount(const upb_filedef *f) { - return upb_inttable_count(&f->deps); -} - -const upb_def *upb_filedef_def(const upb_filedef *f, size_t i) { - upb_value v; - - if (upb_inttable_lookup32(&f->defs, i, &v)) { - return upb_value_getconstptr(v); - } else { - return NULL; - } -} - -const upb_filedef *upb_filedef_dep(const upb_filedef *f, size_t i) { - upb_value v; - - if (upb_inttable_lookup32(&f->deps, i, &v)) { - return upb_value_getconstptr(v); - } else { - return NULL; - } -} - -bool upb_filedef_setname(upb_filedef *f, const char *name, upb_status *s) { - name = upb_gstrdup(name); - if (!name) { - upb_upberr_setoom(s); - return false; - } - upb_gfree((void*)f->name); - f->name = name; - return true; -} - -bool upb_filedef_setpackage(upb_filedef *f, const char *package, - upb_status *s) { - if (!upb_isident(package, strlen(package), true, s)) return false; - package = upb_gstrdup(package); - if (!package) { - upb_upberr_setoom(s); - return false; - } - upb_gfree((void*)f->package); - f->package = package; - return true; -} - -bool upb_filedef_setphpprefix(upb_filedef *f, const char *phpprefix, - upb_status *s) { - phpprefix = upb_gstrdup(phpprefix); - if (!phpprefix) { - upb_upberr_setoom(s); - return false; - } - upb_gfree((void*)f->phpprefix); - f->phpprefix = phpprefix; - return true; -} - -bool upb_filedef_setphpnamespace(upb_filedef *f, const char *phpnamespace, - upb_status *s) { - phpnamespace = upb_gstrdup(phpnamespace); - if (!phpnamespace) { - upb_upberr_setoom(s); - return false; - } - upb_gfree((void*)f->phpnamespace); - f->phpnamespace = phpnamespace; - return true; -} - -bool upb_filedef_setsyntax(upb_filedef *f, upb_syntax_t syntax, - upb_status *s) { - UPB_UNUSED(s); - if (syntax != UPB_SYNTAX_PROTO2 && - syntax != UPB_SYNTAX_PROTO3) { - upb_status_seterrmsg(s, "Unknown syntax value."); - return false; - } - f->syntax = syntax; - - { - /* Set all messages in this file to match. */ - size_t i; - for (i = 0; i < upb_filedef_defcount(f); i++) { - /* Casting const away is safe since all defs in mutable filedef must - * also be mutable. */ - upb_def *def = (upb_def*)upb_filedef_def(f, i); - - upb_msgdef *m = upb_dyncast_msgdef_mutable(def); - if (m) { - m->syntax = syntax; - } - } - } - - return true; -} - -bool upb_filedef_adddef(upb_filedef *f, upb_def *def, const void *ref_donor, - upb_status *s) { - if (def->file) { - upb_status_seterrmsg(s, "Def is already part of another filedef."); - return false; - } - - if (upb_inttable_push(&f->defs, upb_value_constptr(def))) { - def->file = f; - upb_ref2(def, f); - upb_ref2(f, def); - if (ref_donor) upb_def_unref(def, ref_donor); - if (def->type == UPB_DEF_MSG) { - upb_downcast_msgdef_mutable(def)->syntax = f->syntax; - } - return true; - } else { - upb_upberr_setoom(s); - return false; - } -} - -bool upb_filedef_adddep(upb_filedef *f, const upb_filedef *dep) { - if (upb_inttable_push(&f->deps, upb_value_constptr(dep))) { - /* Regular ref instead of ref2 because files can't form cycles. */ - upb_filedef_ref(dep, f); - return true; - } else { - return false; - } -} - -void upb_symtab_free(upb_symtab *s) { - upb_strtable_iter i; - upb_strtable_begin(&i, &s->symtab); - for (; !upb_strtable_done(&i); upb_strtable_next(&i)) { - const upb_def *def = upb_value_getptr(upb_strtable_iter_value(&i)); - upb_def_unref(def, s); - } - upb_strtable_uninit(&s->symtab); - upb_gfree(s); -} - -upb_symtab *upb_symtab_new() { - upb_symtab *s = upb_gmalloc(sizeof(*s)); - if (!s) { - return NULL; - } - - upb_strtable_init(&s->symtab, UPB_CTYPE_PTR); - return s; -} - -const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym) { - upb_value v; - upb_def *ret = upb_strtable_lookup(&s->symtab, sym, &v) ? - upb_value_getptr(v) : NULL; - return ret; -} - -const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) { - upb_value v; - upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ? - upb_value_getptr(v) : NULL; - return def ? upb_dyncast_msgdef(def) : NULL; -} - -const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) { - upb_value v; - upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ? - upb_value_getptr(v) : NULL; - return def ? upb_dyncast_enumdef(def) : NULL; -} - -/* Given a symbol and the base symbol inside which it is defined, find the - * symbol's definition in t. */ -static upb_def *upb_resolvename(const upb_strtable *t, - const char *base, const char *sym) { - if(strlen(sym) == 0) return NULL; - if(sym[0] == '.') { - /* Symbols starting with '.' are absolute, so we do a single lookup. - * Slice to omit the leading '.' */ - upb_value v; - return upb_strtable_lookup(t, sym + 1, &v) ? upb_value_getptr(v) : NULL; - } else { - /* Remove components from base until we find an entry or run out. - * TODO: This branch is totally broken, but currently not used. */ - (void)base; - UPB_ASSERT(false); - return NULL; - } -} - -const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, - const char *sym) { - upb_def *ret = upb_resolvename(&s->symtab, base, sym); - return ret; -} - -/* TODO(haberman): we need a lot more testing of error conditions. */ -static bool symtab_add(upb_symtab *s, upb_def *const*defs, size_t n, - void *ref_donor, upb_refcounted *freeze_also, - upb_status *status) { - size_t i; - size_t add_n; - size_t freeze_n; - upb_strtable_iter iter; - upb_refcounted **add_objs = NULL; - upb_def **add_defs = NULL; - size_t add_objs_size; - upb_strtable addtab; - - if (n == 0 && !freeze_also) { - return true; - } - - if (!upb_strtable_init(&addtab, UPB_CTYPE_PTR)) { - upb_status_seterrmsg(status, "out of memory"); - return false; - } - - /* Add new defs to our "add" set. */ - for (i = 0; i < n; i++) { - upb_def *def = defs[i]; - const char *fullname; - upb_fielddef *f; - - if (upb_def_isfrozen(def)) { - upb_status_seterrmsg(status, "added defs must be mutable"); - goto err; - } - UPB_ASSERT(!upb_def_isfrozen(def)); - fullname = upb_def_fullname(def); - if (!fullname) { - upb_status_seterrmsg( - status, "Anonymous defs cannot be added to a symtab"); - goto err; - } - - f = upb_dyncast_fielddef_mutable(def); - - if (f) { - if (!upb_fielddef_containingtypename(f)) { - upb_status_seterrmsg(status, - "Standalone fielddefs must have a containing type " - "(extendee) name set"); - goto err; - } - } else { - if (upb_strtable_lookup(&addtab, fullname, NULL)) { - upb_status_seterrf(status, "Conflicting defs named '%s'", fullname); - goto err; - } - if (upb_strtable_lookup(&s->symtab, fullname, NULL)) { - upb_status_seterrf(status, "Symtab already has a def named '%s'", - fullname); - goto err; - } - if (!upb_strtable_insert(&addtab, fullname, upb_value_ptr(def))) - goto oom_err; - upb_def_donateref(def, ref_donor, s); - } - - if (upb_dyncast_fielddef_mutable(def)) { - /* TODO(haberman): allow adding extensions attached to files. */ - upb_status_seterrf(status, "Can't add extensions to symtab.\n"); - goto err; - } - } - - /* Now using the table, resolve symbolic references for subdefs. */ - upb_strtable_begin(&iter, &addtab); - for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { - const char *base; - upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter)); - upb_msgdef *m = upb_dyncast_msgdef_mutable(def); - upb_msg_field_iter j; - - if (!m) continue; - /* Type names are resolved relative to the message in which they appear. */ - base = upb_msgdef_fullname(m); - - for(upb_msg_field_begin(&j, m); - !upb_msg_field_done(&j); - upb_msg_field_next(&j)) { - upb_fielddef *f = upb_msg_iter_field(&j); - const char *name = upb_fielddef_subdefname(f); - if (name && !upb_fielddef_subdef(f)) { - /* Try the lookup in the current set of to-be-added defs first. If not - * there, try existing defs. */ - upb_def *subdef = upb_resolvename(&addtab, base, name); - if (subdef == NULL) { - subdef = upb_resolvename(&s->symtab, base, name); - } - if (subdef == NULL) { - upb_status_seterrf( - status, "couldn't resolve name '%s' in message '%s'", name, base); - goto err; - } else if (!upb_fielddef_setsubdef(f, subdef, status)) { - goto err; - } - } - } - } - - /* We need an array of the defs in addtab, for passing to - * upb_refcounted_freeze(). */ - add_objs_size = upb_strtable_count(&addtab); - if (freeze_also) { - add_objs_size++; - } - - add_defs = upb_gmalloc(sizeof(void*) * add_objs_size); - if (add_defs == NULL) goto oom_err; - upb_strtable_begin(&iter, &addtab); - for (add_n = 0; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { - add_defs[add_n++] = upb_value_getptr(upb_strtable_iter_value(&iter)); - } - - /* Validate defs. */ - if (!_upb_def_validate(add_defs, add_n, status)) { - goto err; - } - - /* Cheat a little and give the array a new type. - * This is probably undefined behavior, but this code will be deleted soon. */ - add_objs = (upb_refcounted**)add_defs; - - freeze_n = add_n; - if (freeze_also) { - add_objs[freeze_n++] = freeze_also; - } - - if (!upb_refcounted_freeze(add_objs, freeze_n, status, - UPB_MAX_MESSAGE_DEPTH * 2)) { - goto err; - } - - /* This must be delayed until all errors have been detected, since error - * recovery code uses this table to cleanup defs. */ - upb_strtable_uninit(&addtab); - - /* TODO(haberman) we don't properly handle errors after this point (like - * OOM in upb_strtable_insert() below). */ - for (i = 0; i < add_n; i++) { - upb_def *def = (upb_def*)add_objs[i]; - const char *name = upb_def_fullname(def); - bool success; - success = upb_strtable_insert(&s->symtab, name, upb_value_ptr(def)); - UPB_ASSERT(success); - } - upb_gfree(add_defs); - return true; - -oom_err: - upb_status_seterrmsg(status, "out of memory"); -err: { - /* We need to donate the refs back. */ - upb_strtable_begin(&iter, &addtab); - for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { - upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter)); - upb_def_donateref(def, s, ref_donor); - } - } - upb_strtable_uninit(&addtab); - upb_gfree(add_defs); - UPB_ASSERT(!upb_ok(status)); - return false; -} - -bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, size_t n, - void *ref_donor, upb_status *status) { - return symtab_add(s, defs, n, ref_donor, NULL, status); -} - -bool upb_symtab_addfile(upb_symtab *s, upb_filedef *file, upb_status *status) { - size_t n; - size_t i; - upb_def **defs; - bool ret; - - n = upb_filedef_defcount(file); - defs = upb_gmalloc(sizeof(*defs) * n); - - if (defs == NULL) { - upb_status_seterrmsg(status, "Out of memory"); - return false; - } - - for (i = 0; i < n; i++) { - defs[i] = upb_filedef_mutabledef(file, i); - } - - ret = symtab_add(s, defs, n, NULL, upb_filedef_upcast_mutable(file), status); - - upb_gfree(defs); - return ret; -} - -/* Iteration. */ - -static void advance_to_matching(upb_symtab_iter *iter) { - if (iter->type == UPB_DEF_ANY) - return; - - while (!upb_strtable_done(&iter->iter) && - iter->type != upb_symtab_iter_def(iter)->type) { - upb_strtable_next(&iter->iter); - } -} - -void upb_symtab_begin(upb_symtab_iter *iter, const upb_symtab *s, - upb_deftype_t type) { - upb_strtable_begin(&iter->iter, &s->symtab); - iter->type = type; - advance_to_matching(iter); -} - -void upb_symtab_next(upb_symtab_iter *iter) { - upb_strtable_next(&iter->iter); - advance_to_matching(iter); -} - -bool upb_symtab_done(const upb_symtab_iter *iter) { - return upb_strtable_done(&iter->iter); -} - -const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) { - return upb_value_getptr(upb_strtable_iter_value(&iter->iter)); -} -/* -** TODO(haberman): it's unclear whether a lot of the consistency checks should -** UPB_ASSERT() or return false. -*/ - - -#include - - -static void *upb_calloc(size_t size) { - void *mem = upb_gmalloc(size); - if (mem) { - memset(mem, 0, size); - } - return mem; -} - -/* Defined for the sole purpose of having a unique pointer value for - * UPB_NO_CLOSURE. */ -char _upb_noclosure; - -static void freehandlers(upb_refcounted *r) { - upb_handlers *h = (upb_handlers*)r; - - upb_inttable_iter i; - upb_inttable_begin(&i, &h->cleanup_); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - void *val = (void*)upb_inttable_iter_key(&i); - upb_value func_val = upb_inttable_iter_value(&i); - upb_handlerfree *func = upb_value_getfptr(func_val); - func(val); - } - - upb_inttable_uninit(&h->cleanup_); - upb_msgdef_unref(h->msg, h); - upb_gfree(h->sub); - upb_gfree(h); -} - -static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_handlers *h = (const upb_handlers*)r; - upb_msg_field_iter i; - for(upb_msg_field_begin(&i, h->msg); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - const upb_handlers *sub; - if (!upb_fielddef_issubmsg(f)) continue; - sub = upb_handlers_getsubhandlers(h, f); - if (sub) visit(r, upb_handlers_upcast(sub), closure); - } -} - -static const struct upb_refcounted_vtbl vtbl = {visithandlers, freehandlers}; - -typedef struct { - upb_inttable tab; /* maps upb_msgdef* -> upb_handlers*. */ - upb_handlers_callback *callback; - const void *closure; -} dfs_state; - -/* TODO(haberman): discard upb_handlers* objects that do not actually have any - * handlers set and cannot reach any upb_handlers* object that does. This is - * slightly tricky to do correctly. */ -static upb_handlers *newformsg(const upb_msgdef *m, const void *owner, - dfs_state *s) { - upb_msg_field_iter i; - upb_handlers *h = upb_handlers_new(m, owner); - if (!h) return NULL; - if (!upb_inttable_insertptr(&s->tab, m, upb_value_ptr(h))) goto oom; - - s->callback(s->closure, h); - - /* For each submessage field, get or create a handlers object and set it as - * the subhandlers. */ - for(upb_msg_field_begin(&i, m); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - const upb_msgdef *subdef; - upb_value subm_ent; - - if (!upb_fielddef_issubmsg(f)) continue; - - subdef = upb_downcast_msgdef(upb_fielddef_subdef(f)); - if (upb_inttable_lookupptr(&s->tab, subdef, &subm_ent)) { - upb_handlers_setsubhandlers(h, f, upb_value_getptr(subm_ent)); - } else { - upb_handlers *sub_mh = newformsg(subdef, &sub_mh, s); - if (!sub_mh) goto oom; - upb_handlers_setsubhandlers(h, f, sub_mh); - upb_handlers_unref(sub_mh, &sub_mh); - } - } - return h; - -oom: - upb_handlers_unref(h, owner); - return NULL; -} - -/* Given a selector for a STARTSUBMSG handler, resolves to a pointer to the - * subhandlers for this submessage field. */ -#define SUBH(h, selector) (h->sub[selector]) - -/* The selector for a submessage field is the field index. */ -#define SUBH_F(h, f) SUBH(h, f->index_) - -static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f, - upb_handlertype_t type) { - upb_selector_t sel; - UPB_ASSERT(!upb_handlers_isfrozen(h)); - if (upb_handlers_msgdef(h) != upb_fielddef_containingtype(f)) { - upb_status_seterrf( - &h->status_, "type mismatch: field %s does not belong to message %s", - upb_fielddef_name(f), upb_msgdef_fullname(upb_handlers_msgdef(h))); - return -1; - } - if (!upb_handlers_getselector(f, type, &sel)) { - upb_status_seterrf( - &h->status_, - "type mismatch: cannot register handler type %d for field %s", - type, upb_fielddef_name(f)); - return -1; - } - return sel; -} - -static upb_selector_t handlers_getsel(upb_handlers *h, const upb_fielddef *f, - upb_handlertype_t type) { - int32_t sel = trygetsel(h, f, type); - UPB_ASSERT(sel >= 0); - return sel; -} - -static const void **returntype(upb_handlers *h, const upb_fielddef *f, - upb_handlertype_t type) { - return &h->table[handlers_getsel(h, f, type)].attr.return_closure_type_; -} - -static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f, - upb_handlertype_t type, upb_func *func, - upb_handlerattr *attr) { - upb_handlerattr set_attr = UPB_HANDLERATTR_INITIALIZER; - const void *closure_type; - const void **context_closure_type; - - UPB_ASSERT(!upb_handlers_isfrozen(h)); - - if (sel < 0) { - upb_status_seterrmsg(&h->status_, - "incorrect handler type for this field."); - return false; - } - - if (h->table[sel].func) { - upb_status_seterrmsg(&h->status_, - "cannot change handler once it has been set."); - return false; - } - - if (attr) { - set_attr = *attr; - } - - /* Check that the given closure type matches the closure type that has been - * established for this context (if any). */ - closure_type = upb_handlerattr_closuretype(&set_attr); - - if (type == UPB_HANDLER_STRING) { - context_closure_type = returntype(h, f, UPB_HANDLER_STARTSTR); - } else if (f && upb_fielddef_isseq(f) && - type != UPB_HANDLER_STARTSEQ && - type != UPB_HANDLER_ENDSEQ) { - context_closure_type = returntype(h, f, UPB_HANDLER_STARTSEQ); - } else { - context_closure_type = &h->top_closure_type; - } - - if (closure_type && *context_closure_type && - closure_type != *context_closure_type) { - /* TODO(haberman): better message for debugging. */ - if (f) { - upb_status_seterrf(&h->status_, - "closure type does not match for field %s", - upb_fielddef_name(f)); - } else { - upb_status_seterrmsg( - &h->status_, "closure type does not match for message-level handler"); - } - return false; - } - - if (closure_type) - *context_closure_type = closure_type; - - /* If this is a STARTSEQ or STARTSTR handler, check that the returned pointer - * matches any pre-existing expectations about what type is expected. */ - if (type == UPB_HANDLER_STARTSEQ || type == UPB_HANDLER_STARTSTR) { - const void *return_type = upb_handlerattr_returnclosuretype(&set_attr); - const void *table_return_type = - upb_handlerattr_returnclosuretype(&h->table[sel].attr); - if (return_type && table_return_type && return_type != table_return_type) { - upb_status_seterrmsg(&h->status_, "closure return type does not match"); - return false; - } - - if (table_return_type && !return_type) - upb_handlerattr_setreturnclosuretype(&set_attr, table_return_type); - } - - h->table[sel].func = (upb_func*)func; - h->table[sel].attr = set_attr; - return true; -} - -/* Returns the effective closure type for this handler (which will propagate - * from outer frames if this frame has no START* handler). Not implemented for - * UPB_HANDLER_STRING at the moment since this is not needed. Returns NULL is - * the effective closure type is unspecified (either no handler was registered - * to specify it or the handler that was registered did not specify the closure - * type). */ -const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f, - upb_handlertype_t type) { - const void *ret; - upb_selector_t sel; - - UPB_ASSERT(type != UPB_HANDLER_STRING); - ret = h->top_closure_type; - - if (upb_fielddef_isseq(f) && - type != UPB_HANDLER_STARTSEQ && - type != UPB_HANDLER_ENDSEQ && - h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)].func) { - ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr); - } - - if (type == UPB_HANDLER_STRING && - h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSTR)].func) { - ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr); - } - - /* The effective type of the submessage; not used yet. - * if (type == SUBMESSAGE && - * h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) { - * ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr); - * } */ - - return ret; -} - -/* Checks whether the START* handler specified by f & type is missing even - * though it is required to convert the established type of an outer frame - * ("closure_type") into the established type of an inner frame (represented in - * the return closure type of this handler's attr. */ -bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type, - upb_status *status) { - const void *closure_type; - const upb_handlerattr *attr; - const void *return_closure_type; - - upb_selector_t sel = handlers_getsel(h, f, type); - if (h->table[sel].func) return true; - closure_type = effective_closure_type(h, f, type); - attr = &h->table[sel].attr; - return_closure_type = upb_handlerattr_returnclosuretype(attr); - if (closure_type && return_closure_type && - closure_type != return_closure_type) { - upb_status_seterrf(status, - "expected start handler to return sub type for field %f", - upb_fielddef_name(f)); - return false; - } - return true; -} - -/* Public interface ***********************************************************/ - -upb_handlers *upb_handlers_new(const upb_msgdef *md, const void *owner) { - int extra; - upb_handlers *h; - - UPB_ASSERT(upb_msgdef_isfrozen(md)); - - extra = sizeof(upb_handlers_tabent) * (md->selector_count - 1); - h = upb_calloc(sizeof(*h) + extra); - if (!h) return NULL; - - h->msg = md; - upb_msgdef_ref(h->msg, h); - upb_status_clear(&h->status_); - - if (md->submsg_field_count > 0) { - h->sub = upb_calloc(md->submsg_field_count * sizeof(*h->sub)); - if (!h->sub) goto oom; - } else { - h->sub = 0; - } - - if (!upb_refcounted_init(upb_handlers_upcast_mutable(h), &vtbl, owner)) - goto oom; - if (!upb_inttable_init(&h->cleanup_, UPB_CTYPE_FPTR)) goto oom; - - /* calloc() above initialized all handlers to NULL. */ - return h; - -oom: - freehandlers(upb_handlers_upcast_mutable(h)); - return NULL; -} - -const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m, - const void *owner, - upb_handlers_callback *callback, - const void *closure) { - dfs_state state; - upb_handlers *ret; - bool ok; - upb_refcounted *r; - - state.callback = callback; - state.closure = closure; - if (!upb_inttable_init(&state.tab, UPB_CTYPE_PTR)) return NULL; - - ret = newformsg(m, owner, &state); - - upb_inttable_uninit(&state.tab); - if (!ret) return NULL; - - r = upb_handlers_upcast_mutable(ret); - ok = upb_refcounted_freeze(&r, 1, NULL, UPB_MAX_HANDLER_DEPTH); - UPB_ASSERT(ok); - - return ret; -} - -const upb_status *upb_handlers_status(upb_handlers *h) { - UPB_ASSERT(!upb_handlers_isfrozen(h)); - return &h->status_; -} - -void upb_handlers_clearerr(upb_handlers *h) { - UPB_ASSERT(!upb_handlers_isfrozen(h)); - upb_status_clear(&h->status_); -} - -#define SETTER(name, handlerctype, handlertype) \ - bool upb_handlers_set ## name(upb_handlers *h, const upb_fielddef *f, \ - handlerctype func, upb_handlerattr *attr) { \ - int32_t sel = trygetsel(h, f, handlertype); \ - return doset(h, sel, f, handlertype, (upb_func*)func, attr); \ - } - -SETTER(int32, upb_int32_handlerfunc*, UPB_HANDLER_INT32) -SETTER(int64, upb_int64_handlerfunc*, UPB_HANDLER_INT64) -SETTER(uint32, upb_uint32_handlerfunc*, UPB_HANDLER_UINT32) -SETTER(uint64, upb_uint64_handlerfunc*, UPB_HANDLER_UINT64) -SETTER(float, upb_float_handlerfunc*, UPB_HANDLER_FLOAT) -SETTER(double, upb_double_handlerfunc*, UPB_HANDLER_DOUBLE) -SETTER(bool, upb_bool_handlerfunc*, UPB_HANDLER_BOOL) -SETTER(startstr, upb_startstr_handlerfunc*, UPB_HANDLER_STARTSTR) -SETTER(string, upb_string_handlerfunc*, UPB_HANDLER_STRING) -SETTER(endstr, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSTR) -SETTER(startseq, upb_startfield_handlerfunc*, UPB_HANDLER_STARTSEQ) -SETTER(startsubmsg, upb_startfield_handlerfunc*, UPB_HANDLER_STARTSUBMSG) -SETTER(endsubmsg, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSUBMSG) -SETTER(endseq, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSEQ) - -#undef SETTER - -bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func, - upb_handlerattr *attr) { - return doset(h, UPB_STARTMSG_SELECTOR, NULL, UPB_HANDLER_INT32, - (upb_func *)func, attr); -} - -bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func, - upb_handlerattr *attr) { - UPB_ASSERT(!upb_handlers_isfrozen(h)); - return doset(h, UPB_ENDMSG_SELECTOR, NULL, UPB_HANDLER_INT32, - (upb_func *)func, attr); -} - -bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f, - const upb_handlers *sub) { - UPB_ASSERT(sub); - UPB_ASSERT(!upb_handlers_isfrozen(h)); - UPB_ASSERT(upb_fielddef_issubmsg(f)); - if (SUBH_F(h, f)) return false; /* Can't reset. */ - if (upb_msgdef_upcast(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) { - return false; - } - SUBH_F(h, f) = sub; - upb_ref2(sub, h); - return true; -} - -const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h, - const upb_fielddef *f) { - UPB_ASSERT(upb_fielddef_issubmsg(f)); - return SUBH_F(h, f); -} - -bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t sel, - upb_handlerattr *attr) { - if (!upb_handlers_gethandler(h, sel)) - return false; - *attr = h->table[sel].attr; - return true; -} - -const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h, - upb_selector_t sel) { - /* STARTSUBMSG selector in sel is the field's selector base. */ - return SUBH(h, sel - UPB_STATIC_SELECTOR_COUNT); -} - -const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; } - -bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) { - bool ok; - if (upb_inttable_lookupptr(&h->cleanup_, p, NULL)) { - return false; - } - ok = upb_inttable_insertptr(&h->cleanup_, p, upb_value_fptr(func)); - UPB_ASSERT(ok); - return true; -} - - -/* "Static" methods ***********************************************************/ - -bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) { - /* TODO: verify we have a transitive closure. */ - int i; - for (i = 0; i < n; i++) { - upb_msg_field_iter j; - upb_handlers *h = handlers[i]; - - if (!upb_ok(&h->status_)) { - upb_status_seterrf(s, "handlers for message %s had error status: %s", - upb_msgdef_fullname(upb_handlers_msgdef(h)), - upb_status_errmsg(&h->status_)); - return false; - } - - /* Check that there are no closure mismatches due to missing Start* handlers - * or subhandlers with different type-level types. */ - for(upb_msg_field_begin(&j, h->msg); - !upb_msg_field_done(&j); - upb_msg_field_next(&j)) { - - const upb_fielddef *f = upb_msg_iter_field(&j); - if (upb_fielddef_isseq(f)) { - if (!checkstart(h, f, UPB_HANDLER_STARTSEQ, s)) - return false; - } - - if (upb_fielddef_isstring(f)) { - if (!checkstart(h, f, UPB_HANDLER_STARTSTR, s)) - return false; - } - - if (upb_fielddef_issubmsg(f)) { - bool hashandler = false; - if (upb_handlers_gethandler( - h, handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)) || - upb_handlers_gethandler( - h, handlers_getsel(h, f, UPB_HANDLER_ENDSUBMSG))) { - hashandler = true; - } - - if (upb_fielddef_isseq(f) && - (upb_handlers_gethandler( - h, handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)) || - upb_handlers_gethandler( - h, handlers_getsel(h, f, UPB_HANDLER_ENDSEQ)))) { - hashandler = true; - } - - if (hashandler && !upb_handlers_getsubhandlers(h, f)) { - /* For now we add an empty subhandlers in this case. It makes the - * decoder code generator simpler, because it only has to handle two - * cases (submessage has handlers or not) as opposed to three - * (submessage has handlers in enclosing message but no subhandlers). - * - * This makes parsing less efficient in the case that we want to - * notice a submessage but skip its contents (like if we're testing - * for submessage presence or counting the number of repeated - * submessages). In this case we will end up parsing the submessage - * field by field and throwing away the results for each, instead of - * skipping the whole delimited thing at once. If this is an issue we - * can revisit it, but do remember that this only arises when you have - * handlers (startseq/startsubmsg/endsubmsg/endseq) set for the - * submessage but no subhandlers. The uses cases for this are - * limited. */ - upb_handlers *sub = upb_handlers_new(upb_fielddef_msgsubdef(f), &sub); - upb_handlers_setsubhandlers(h, f, sub); - upb_handlers_unref(sub, &sub); - } - - /* TODO(haberman): check type of submessage. - * This is slightly tricky; also consider whether we should check that - * they match at setsubhandlers time. */ - } - } - } - - if (!upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s, - UPB_MAX_HANDLER_DEPTH)) { - return false; - } - - return true; -} - -upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) { - switch (upb_fielddef_type(f)) { - case UPB_TYPE_INT32: - case UPB_TYPE_ENUM: return UPB_HANDLER_INT32; - case UPB_TYPE_INT64: return UPB_HANDLER_INT64; - case UPB_TYPE_UINT32: return UPB_HANDLER_UINT32; - case UPB_TYPE_UINT64: return UPB_HANDLER_UINT64; - case UPB_TYPE_FLOAT: return UPB_HANDLER_FLOAT; - case UPB_TYPE_DOUBLE: return UPB_HANDLER_DOUBLE; - case UPB_TYPE_BOOL: return UPB_HANDLER_BOOL; - default: UPB_ASSERT(false); return -1; /* Invalid input. */ - } -} - -bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type, - upb_selector_t *s) { - switch (type) { - case UPB_HANDLER_INT32: - case UPB_HANDLER_INT64: - case UPB_HANDLER_UINT32: - case UPB_HANDLER_UINT64: - case UPB_HANDLER_FLOAT: - case UPB_HANDLER_DOUBLE: - case UPB_HANDLER_BOOL: - if (!upb_fielddef_isprimitive(f) || - upb_handlers_getprimitivehandlertype(f) != type) - return false; - *s = f->selector_base; - break; - case UPB_HANDLER_STRING: - if (upb_fielddef_isstring(f)) { - *s = f->selector_base; - } else if (upb_fielddef_lazy(f)) { - *s = f->selector_base + 3; - } else { - return false; - } - break; - case UPB_HANDLER_STARTSTR: - if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) { - *s = f->selector_base + 1; - } else { - return false; - } - break; - case UPB_HANDLER_ENDSTR: - if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) { - *s = f->selector_base + 2; - } else { - return false; - } - break; - case UPB_HANDLER_STARTSEQ: - if (!upb_fielddef_isseq(f)) return false; - *s = f->selector_base - 2; - break; - case UPB_HANDLER_ENDSEQ: - if (!upb_fielddef_isseq(f)) return false; - *s = f->selector_base - 1; - break; - case UPB_HANDLER_STARTSUBMSG: - if (!upb_fielddef_issubmsg(f)) return false; - /* Selectors for STARTSUBMSG are at the beginning of the table so that the - * selector can also be used as an index into the "sub" array of - * subhandlers. The indexes for the two into these two tables are the - * same, except that in the handler table the static selectors come first. */ - *s = f->index_ + UPB_STATIC_SELECTOR_COUNT; - break; - case UPB_HANDLER_ENDSUBMSG: - if (!upb_fielddef_issubmsg(f)) return false; - *s = f->selector_base; - break; - } - UPB_ASSERT((size_t)*s < upb_fielddef_containingtype(f)->selector_count); - return true; -} - -uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) { - return upb_fielddef_isseq(f) ? 2 : 0; -} - -uint32_t upb_handlers_selectorcount(const upb_fielddef *f) { - uint32_t ret = 1; - if (upb_fielddef_isseq(f)) ret += 2; /* STARTSEQ/ENDSEQ */ - if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */ - if (upb_fielddef_issubmsg(f)) { - /* ENDSUBMSG (STARTSUBMSG is at table beginning) */ - ret += 0; - if (upb_fielddef_lazy(f)) { - /* STARTSTR/ENDSTR/STRING (for lazy) */ - ret += 3; - } - } - return ret; -} - - -/* upb_handlerattr ************************************************************/ - -void upb_handlerattr_init(upb_handlerattr *attr) { - upb_handlerattr from = UPB_HANDLERATTR_INITIALIZER; - memcpy(attr, &from, sizeof(*attr)); -} - -void upb_handlerattr_uninit(upb_handlerattr *attr) { - UPB_UNUSED(attr); -} - -bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, const void *hd) { - attr->handler_data_ = hd; - return true; -} - -bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type) { - attr->closure_type_ = type; - return true; -} - -const void *upb_handlerattr_closuretype(const upb_handlerattr *attr) { - return attr->closure_type_; -} - -bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr, - const void *type) { - attr->return_closure_type_ = type; - return true; -} - -const void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr) { - return attr->return_closure_type_; -} - -bool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok) { - attr->alwaysok_ = alwaysok; - return true; -} - -bool upb_handlerattr_alwaysok(const upb_handlerattr *attr) { - return attr->alwaysok_; -} - -/* upb_bufhandle **************************************************************/ - -size_t upb_bufhandle_objofs(const upb_bufhandle *h) { - return h->objofs_; -} - -/* upb_byteshandler ***********************************************************/ - -void upb_byteshandler_init(upb_byteshandler* h) { - memset(h, 0, sizeof(*h)); -} - -/* For when we support handlerfree callbacks. */ -void upb_byteshandler_uninit(upb_byteshandler* h) { - UPB_UNUSED(h); -} - -bool upb_byteshandler_setstartstr(upb_byteshandler *h, - upb_startstr_handlerfunc *func, void *d) { - h->table[UPB_STARTSTR_SELECTOR].func = (upb_func*)func; - h->table[UPB_STARTSTR_SELECTOR].attr.handler_data_ = d; - return true; -} - -bool upb_byteshandler_setstring(upb_byteshandler *h, - upb_string_handlerfunc *func, void *d) { - h->table[UPB_STRING_SELECTOR].func = (upb_func*)func; - h->table[UPB_STRING_SELECTOR].attr.handler_data_ = d; - return true; -} - -bool upb_byteshandler_setendstr(upb_byteshandler *h, - upb_endfield_handlerfunc *func, void *d) { - h->table[UPB_ENDSTR_SELECTOR].func = (upb_func*)func; - h->table[UPB_ENDSTR_SELECTOR].attr.handler_data_ = d; - return true; -} - - -static bool is_power_of_two(size_t val) { - return (val & (val - 1)) == 0; -} - -/* Align up to the given power of 2. */ -static size_t align_up(size_t val, size_t align) { - UPB_ASSERT(is_power_of_two(align)); - return (val + align - 1) & ~(align - 1); -} - -static size_t div_round_up(size_t n, size_t d) { - return (n + d - 1) / d; -} - -bool upb_fieldtype_mapkeyok(upb_fieldtype_t type) { - return type == UPB_TYPE_BOOL || type == UPB_TYPE_INT32 || - type == UPB_TYPE_UINT32 || type == UPB_TYPE_INT64 || - type == UPB_TYPE_UINT64 || type == UPB_TYPE_STRING; -} - -void *upb_array_pack(const upb_array *arr, void *p, size_t *ofs, size_t size); -void *upb_map_pack(const upb_map *map, void *p, size_t *ofs, size_t size); - -#define CHARPTR_AT(msg, ofs) ((char*)msg + ofs) -#define ENCODE_MAX_NESTING 64 -#define CHECK_TRUE(x) if (!(x)) { return false; } - -/** upb_msgval ****************************************************************/ - -#define upb_alignof(t) offsetof(struct { char c; t x; }, x) - -/* These functions will generate real memcpy() calls on ARM sadly, because - * the compiler assumes they might not be aligned. */ - -static upb_msgval upb_msgval_read(const void *p, size_t ofs, - uint8_t size) { - upb_msgval val; - p = (char*)p + ofs; - memcpy(&val, p, size); - return val; -} - -static void upb_msgval_write(void *p, size_t ofs, upb_msgval val, - uint8_t size) { - p = (char*)p + ofs; - memcpy(p, &val, size); -} - -static size_t upb_msgval_sizeof(upb_fieldtype_t type) { - switch (type) { - case UPB_TYPE_DOUBLE: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT64: - return 8; - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - case UPB_TYPE_UINT32: - case UPB_TYPE_FLOAT: - return 4; - case UPB_TYPE_BOOL: - return 1; - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - return sizeof(void*); - case UPB_TYPE_STRING: - return sizeof(char*) + sizeof(size_t); - } - UPB_UNREACHABLE(); -} - -static uint8_t upb_msg_fieldsize(const upb_fielddef *f) { - if (upb_fielddef_isseq(f)) { - return sizeof(void*); - } else { - return upb_msgval_sizeof(upb_fielddef_type(f)); - } -} - -/* TODO(haberman): this is broken right now because upb_msgval can contain - * a char* / size_t pair, which is too big for a upb_value. To fix this - * we'll probably need to dynamically allocate a upb_msgval and store a - * pointer to that in the tables for extensions/maps. */ -static upb_value upb_toval(upb_msgval val) { - upb_value ret; - UPB_UNUSED(val); - memset(&ret, 0, sizeof(upb_value)); /* XXX */ - return ret; -} - -static upb_msgval upb_msgval_fromval(upb_value val) { - upb_msgval ret; - UPB_UNUSED(val); - memset(&ret, 0, sizeof(upb_msgval)); /* XXX */ - return ret; -} - -static upb_ctype_t upb_fieldtotabtype(upb_fieldtype_t type) { - switch (type) { - case UPB_TYPE_FLOAT: return UPB_CTYPE_FLOAT; - case UPB_TYPE_DOUBLE: return UPB_CTYPE_DOUBLE; - case UPB_TYPE_BOOL: return UPB_CTYPE_BOOL; - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - case UPB_TYPE_STRING: return UPB_CTYPE_CONSTPTR; - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: return UPB_CTYPE_INT32; - case UPB_TYPE_UINT32: return UPB_CTYPE_UINT32; - case UPB_TYPE_INT64: return UPB_CTYPE_INT64; - case UPB_TYPE_UINT64: return UPB_CTYPE_UINT64; - default: UPB_ASSERT(false); return 0; - } -} - -static upb_msgval upb_msgval_fromdefault(const upb_fielddef *f) { - /* TODO(haberman): improve/optimize this (maybe use upb_msgval in fielddef) */ - switch (upb_fielddef_type(f)) { - case UPB_TYPE_FLOAT: - return upb_msgval_float(upb_fielddef_defaultfloat(f)); - case UPB_TYPE_DOUBLE: - return upb_msgval_double(upb_fielddef_defaultdouble(f)); - case UPB_TYPE_BOOL: - return upb_msgval_bool(upb_fielddef_defaultbool(f)); - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - size_t len; - const char *ptr = upb_fielddef_defaultstr(f, &len); - return upb_msgval_str(ptr, len); - } - case UPB_TYPE_MESSAGE: - return upb_msgval_msg(NULL); - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - return upb_msgval_int32(upb_fielddef_defaultint32(f)); - case UPB_TYPE_UINT32: - return upb_msgval_uint32(upb_fielddef_defaultuint32(f)); - case UPB_TYPE_INT64: - return upb_msgval_int64(upb_fielddef_defaultint64(f)); - case UPB_TYPE_UINT64: - return upb_msgval_uint64(upb_fielddef_defaultuint64(f)); - default: - UPB_ASSERT(false); - return upb_msgval_msg(NULL); - } -} - - -/** upb_msglayout *************************************************************/ - -struct upb_msglayout { - upb_msgfactory *factory; - const upb_msgdef *msgdef; - size_t size; - size_t extdict_offset; - void *default_msg; - uint32_t *field_offsets; - uint32_t *case_offsets; - uint32_t *hasbits; - bool has_extdict; - uint8_t align; -}; - -static void upb_msg_checkfield(const upb_msglayout *l, const upb_fielddef *f) { - UPB_ASSERT(l->msgdef == upb_fielddef_containingtype(f)); -} - -static void upb_msglayout_free(upb_msglayout *l) { - upb_gfree(l->default_msg); - upb_gfree(l); -} - -const upb_msgdef *upb_msglayout_msgdef(const upb_msglayout *l) { - return l->msgdef; -} - -static size_t upb_msglayout_place(upb_msglayout *l, size_t size) { - size_t ret; - - l->size = align_up(l->size, size); - l->align = align_up(l->align, size); - ret = l->size; - l->size += size; - return ret; -} - -static uint32_t upb_msglayout_offset(const upb_msglayout *l, - const upb_fielddef *f) { - return l->field_offsets[upb_fielddef_index(f)]; -} - -static uint32_t upb_msglayout_hasbit(const upb_msglayout *l, - const upb_fielddef *f) { - return l->hasbits[upb_fielddef_index(f)]; -} - -static bool upb_msglayout_initdefault(upb_msglayout *l) { - const upb_msgdef *m = l->msgdef; - upb_msg_field_iter it; - - if (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2 && l->size) { - /* Allocate default message and set default values in it. */ - l->default_msg = upb_gmalloc(l->size); - if (!l->default_msg) { - return false; - } - - memset(l->default_msg, 0, l->size); - - for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* f = upb_msg_iter_field(&it); - - if (upb_fielddef_containingoneof(f)) { - continue; - } - - if (!upb_fielddef_isstring(f) && - !upb_fielddef_issubmsg(f) && - !upb_fielddef_isseq(f)) { - upb_msg_set(l->default_msg, f, upb_msgval_fromdefault(f), l); - } - } - } - - return true; -} - -static upb_msglayout *upb_msglayout_new(const upb_msgdef *m) { - upb_msg_field_iter it; - upb_msg_oneof_iter oit; - upb_msglayout *l; - size_t hasbit; - size_t array_size = upb_msgdef_numfields(m) + upb_msgdef_numoneofs(m); - - if (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2) { - array_size += upb_msgdef_numfields(m); /* hasbits. */ - } - - l = upb_gmalloc(sizeof(*l) + (sizeof(uint32_t) * array_size)); - if (!l) return NULL; - - memset(l, 0, sizeof(*l)); - - l->msgdef = m; - l->align = 1; - l->field_offsets = (uint32_t*)CHARPTR_AT(l, sizeof(*l)); - l->case_offsets = l->field_offsets + upb_msgdef_numfields(m); - l->hasbits = l->case_offsets + upb_msgdef_numoneofs(m); - - /* Allocate data offsets in three stages: - * - * 1. hasbits. - * 2. regular fields. - * 3. oneof fields. - * - * OPT: There is a lot of room for optimization here to minimize the size. - */ - - /* Allocate hasbits. Start at sizeof(void*) for upb_alloc*. */ - for (upb_msg_field_begin(&it, m), hasbit = sizeof(void*) * 8; - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* f = upb_msg_iter_field(&it); - - if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) { - l->hasbits[upb_fielddef_index(f)] = hasbit++; - } - } - - /* Account for space used by hasbits. */ - l->size = div_round_up(hasbit, 8); - - /* Allocate non-oneof fields. */ - for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* f = upb_msg_iter_field(&it); - size_t field_size = upb_msg_fieldsize(f); - size_t index = upb_fielddef_index(f); - - - if (upb_fielddef_containingoneof(f)) { - /* Oneofs are handled separately below. */ - continue; - } - - l->field_offsets[index] = upb_msglayout_place(l, field_size); - } - - /* Allocate oneof fields. Each oneof field consists of a uint32 for the case - * and space for the actual data. */ - for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit); - upb_msg_oneof_next(&oit)) { - const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit); - upb_oneof_iter fit; - size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */ - size_t field_size = 0; - size_t case_offset; - size_t val_offset; - - /* Calculate field size: the max of all field sizes. */ - for (upb_oneof_begin(&fit, oneof); - !upb_oneof_done(&fit); - upb_oneof_next(&fit)) { - const upb_fielddef* f = upb_oneof_iter_field(&fit); - field_size = UPB_MAX(field_size, upb_msg_fieldsize(f)); - } - - /* Align and allocate case offset. */ - case_offset = upb_msglayout_place(l, case_size); - val_offset = upb_msglayout_place(l, field_size); - - l->case_offsets[upb_oneofdef_index(oneof)] = case_offset; - - /* Assign all fields in the oneof this same offset. */ - for (upb_oneof_begin(&fit, oneof); !upb_oneof_done(&fit); - upb_oneof_next(&fit)) { - const upb_fielddef* f = upb_oneof_iter_field(&fit); - l->field_offsets[upb_fielddef_index(f)] = val_offset; - } - } - - /* Size of the entire structure should be a multiple of its greatest - * alignment. */ - l->size = align_up(l->size, l->align); - - if (upb_msglayout_initdefault(l)) { - return l; - } else { - upb_msglayout_free(l); - return NULL; - } -} - -upb_msgfactory *upb_msglayout_factory(const upb_msglayout *layout) { - return layout->factory; -} - - -/** upb_msgfactory ************************************************************/ - -struct upb_msgfactory { - const upb_symtab *symtab; /* We own a ref. */ - upb_inttable layouts; - upb_inttable mergehandlers; -}; - -upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab) { - upb_msgfactory *ret = upb_gmalloc(sizeof(*ret)); - - ret->symtab = symtab; - upb_inttable_init(&ret->layouts, UPB_CTYPE_PTR); - upb_inttable_init(&ret->mergehandlers, UPB_CTYPE_CONSTPTR); - - return ret; -} - -void upb_msgfactory_free(upb_msgfactory *f) { - upb_inttable_iter i; - upb_inttable_begin(&i, &f->layouts); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_msglayout *l = upb_value_getptr(upb_inttable_iter_value(&i)); - upb_msglayout_free(l); - } - - upb_inttable_begin(&i, &f->mergehandlers); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - const upb_handlers *h = upb_value_getconstptr(upb_inttable_iter_value(&i)); - upb_handlers_unref(h, f); - } - - upb_inttable_uninit(&f->layouts); - upb_inttable_uninit(&f->mergehandlers); - upb_gfree(f); -} - -const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f) { - return f->symtab; -} - -const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f, - const upb_msgdef *m) { - upb_value v; - UPB_ASSERT(upb_symtab_lookupmsg(f->symtab, upb_msgdef_fullname(m)) == m); - UPB_ASSERT(!upb_msgdef_mapentry(m)); - - if (upb_inttable_lookupptr(&f->layouts, m, &v)) { - UPB_ASSERT(upb_value_getptr(v)); - return upb_value_getptr(v); - } else { - upb_msgfactory *mutable_f = (void*)f; - upb_msglayout *l = upb_msglayout_new(m); - upb_inttable_insertptr(&mutable_f->layouts, m, upb_value_ptr(l)); - UPB_ASSERT(l); - l->factory = f; - return l; - } -} - -/* Our handlers that we don't expose externally. */ - -void *upb_msg_startstr(void *msg, const void *hd, size_t size_hint) { - uint32_t ofs = (uintptr_t)hd; - /* We pass NULL here because we know we can get away with it. */ - upb_alloc *alloc = upb_msg_alloc(msg, NULL); - upb_msgval val; - UPB_UNUSED(size_hint); - - val = upb_msgval_read(msg, ofs, upb_msgval_sizeof(UPB_TYPE_STRING)); - - upb_free(alloc, (void*)val.str.ptr); - val.str.ptr = NULL; - val.str.len = 0; - - upb_msgval_write(msg, ofs, val, upb_msgval_sizeof(UPB_TYPE_STRING)); - return msg; -} - -size_t upb_msg_str(void *msg, const void *hd, const char *ptr, size_t size, - const upb_bufhandle *handle) { - uint32_t ofs = (uintptr_t)hd; - /* We pass NULL here because we know we can get away with it. */ - upb_alloc *alloc = upb_msg_alloc(msg, NULL); - upb_msgval val; - size_t newsize; - UPB_UNUSED(handle); - - val = upb_msgval_read(msg, ofs, upb_msgval_sizeof(UPB_TYPE_STRING)); - - newsize = val.str.len + size; - val.str.ptr = upb_realloc(alloc, (void*)val.str.ptr, val.str.len, newsize); - - if (!val.str.ptr) { - return false; - } - - memcpy((char*)val.str.ptr + val.str.len, ptr, size); - val.str.len = newsize; - upb_msgval_write(msg, ofs, val, upb_msgval_sizeof(UPB_TYPE_STRING)); - return size; -} - -static void callback(const void *closure, upb_handlers *h) { - upb_msgfactory *factory = (upb_msgfactory*)closure; - const upb_msgdef *md = upb_handlers_msgdef(h); - const upb_msglayout* layout = upb_msgfactory_getlayout(factory, md); - upb_msg_field_iter i; - UPB_UNUSED(factory); - - for(upb_msg_field_begin(&i, md); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - size_t offset = upb_msglayout_offset(layout, f); - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, (void*)offset); - - if (upb_fielddef_isseq(f)) { - } else if (upb_fielddef_isstring(f)) { - upb_handlers_setstartstr(h, f, upb_msg_startstr, &attr); - upb_handlers_setstring(h, f, upb_msg_str, &attr); - } else { - upb_msg_setscalarhandler( - h, f, offset, upb_msglayout_hasbit(layout, f)); - } - } -} - -const upb_handlers *upb_msgfactory_getmergehandlers(upb_msgfactory *f, - const upb_msgdef *m) { - upb_msgfactory *mutable_f = (void*)f; - - /* TODO(haberman): properly cache these. */ - const upb_handlers *ret = upb_handlers_newfrozen(m, f, callback, f); - upb_inttable_push(&mutable_f->mergehandlers, upb_value_constptr(ret)); - - return ret; -} - -const upb_visitorplan *upb_msgfactory_getvisitorplan(upb_msgfactory *f, - const upb_handlers *h) { - const upb_msgdef *md = upb_handlers_msgdef(h); - return (const upb_visitorplan*)upb_msgfactory_getlayout(f, md); -} - - -/** upb_visitor ***************************************************************/ - -struct upb_visitor { - const upb_msglayout *layout; - upb_sink *sink; -}; - -static upb_selector_t getsel2(const upb_fielddef *f, upb_handlertype_t type) { - upb_selector_t ret; - bool ok = upb_handlers_getselector(f, type, &ret); - UPB_ASSERT(ok); - return ret; -} - -static bool upb_visitor_hasfield(const upb_msg *msg, const upb_fielddef *f, - const upb_msglayout *layout) { - if (upb_fielddef_isseq(f)) { - return upb_msgval_getarr(upb_msg_get(msg, f, layout)) != NULL; - } else if (upb_msgdef_syntax(upb_fielddef_containingtype(f)) == - UPB_SYNTAX_PROTO2) { - return upb_msg_has(msg, f, layout); - } else { - upb_msgval val = upb_msg_get(msg, f, layout); - switch (upb_fielddef_type(f)) { - case UPB_TYPE_FLOAT: - return upb_msgval_getfloat(val) != 0; - case UPB_TYPE_DOUBLE: - return upb_msgval_getdouble(val) != 0; - case UPB_TYPE_BOOL: - return upb_msgval_getbool(val); - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - return upb_msgval_getint32(val) != 0; - case UPB_TYPE_UINT32: - return upb_msgval_getuint32(val) != 0; - case UPB_TYPE_INT64: - return upb_msgval_getint64(val) != 0; - case UPB_TYPE_UINT64: - return upb_msgval_getuint64(val) != 0; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - return upb_msgval_getstr(val) && upb_msgval_getstrlen(val) > 0; - case UPB_TYPE_MESSAGE: - return upb_msgval_getmsg(val) != NULL; - } - UPB_UNREACHABLE(); - } -} - -static bool upb_visitor_visitmsg2(const upb_msg *msg, - const upb_msglayout *layout, upb_sink *sink, - int depth) { - const upb_msgdef *md = upb_msglayout_msgdef(layout); - upb_msg_field_iter i; - upb_status status; - - upb_sink_startmsg(sink); - - /* Protect against cycles (possible because users may freely reassign message - * and repeated fields) by imposing a maximum recursion depth. */ - if (depth > ENCODE_MAX_NESTING) { - return false; - } - - for (upb_msg_field_begin(&i, md); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - upb_msgval val; - - if (!upb_visitor_hasfield(msg, f, layout)) { - continue; - } - - val = upb_msg_get(msg, f, layout); - - if (upb_fielddef_isseq(f)) { - const upb_array *arr = upb_msgval_getarr(val); - UPB_ASSERT(arr); - /* TODO: putary(ary, f, sink, depth);*/ - } else if (upb_fielddef_issubmsg(f)) { - const upb_map *map = upb_msgval_getmap(val); - UPB_ASSERT(map); - /* TODO: putmap(map, f, sink, depth);*/ - } else if (upb_fielddef_isstring(f)) { - /* TODO putstr(); */ - } else { - upb_selector_t sel = getsel2(f, upb_handlers_getprimitivehandlertype(f)); - UPB_ASSERT(upb_fielddef_isprimitive(f)); - - switch (upb_fielddef_type(f)) { - case UPB_TYPE_FLOAT: - CHECK_TRUE(upb_sink_putfloat(sink, sel, upb_msgval_getfloat(val))); - break; - case UPB_TYPE_DOUBLE: - CHECK_TRUE(upb_sink_putdouble(sink, sel, upb_msgval_getdouble(val))); - break; - case UPB_TYPE_BOOL: - CHECK_TRUE(upb_sink_putbool(sink, sel, upb_msgval_getbool(val))); - break; - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - CHECK_TRUE(upb_sink_putint32(sink, sel, upb_msgval_getint32(val))); - break; - case UPB_TYPE_UINT32: - CHECK_TRUE(upb_sink_putuint32(sink, sel, upb_msgval_getuint32(val))); - break; - case UPB_TYPE_INT64: - CHECK_TRUE(upb_sink_putint64(sink, sel, upb_msgval_getint64(val))); - break; - case UPB_TYPE_UINT64: - CHECK_TRUE(upb_sink_putuint64(sink, sel, upb_msgval_getuint64(val))); - break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - UPB_UNREACHABLE(); - } - } - } - - upb_sink_endmsg(sink, &status); - return true; -} - -upb_visitor *upb_visitor_create(upb_env *e, const upb_visitorplan *vp, - upb_sink *output) { - upb_visitor *visitor = upb_env_malloc(e, sizeof(*visitor)); - visitor->layout = (const upb_msglayout*)vp; - visitor->sink = output; - return visitor; -} - -bool upb_visitor_visitmsg(upb_visitor *visitor, const upb_msg *msg) { - return upb_visitor_visitmsg2(msg, visitor->layout, visitor->sink, 0); -} - - -/** upb_msg *******************************************************************/ - -/* If we always read/write as a consistent type to each address, this shouldn't - * violate aliasing. - */ -#define DEREF(msg, ofs, type) *(type*)CHARPTR_AT(msg, ofs) - -static upb_inttable *upb_msg_trygetextdict(const upb_msg *msg, - const upb_msglayout *l) { - return l->has_extdict ? DEREF(msg, l->extdict_offset, upb_inttable*) : NULL; -} - -static upb_inttable *upb_msg_getextdict(upb_msg *msg, - const upb_msglayout *l, - upb_alloc *a) { - upb_inttable *ext_dict; - UPB_ASSERT(l->has_extdict); - - ext_dict = upb_msg_trygetextdict(msg, l); - - if (!ext_dict) { - ext_dict = upb_malloc(a, sizeof(upb_inttable)); - - if (!ext_dict) { - return NULL; - } - - /* Use an 8-byte type to ensure all bytes are copied. */ - if (!upb_inttable_init2(ext_dict, UPB_CTYPE_INT64, a)) { - upb_free(a, ext_dict); - return NULL; - } - - DEREF(msg, l->extdict_offset, upb_inttable*) = ext_dict; - } - - return ext_dict; -} - -static uint32_t upb_msg_getoneofint(const upb_msg *msg, - const upb_oneofdef *o, - const upb_msglayout *l) { - size_t oneof_ofs = l->case_offsets[upb_oneofdef_index(o)]; - return DEREF(msg, oneof_ofs, uint8_t); -} - -static void upb_msg_setoneofcase(const upb_msg *msg, - const upb_oneofdef *o, - const upb_msglayout *l, - uint32_t val) { - size_t oneof_ofs = l->case_offsets[upb_oneofdef_index(o)]; - DEREF(msg, oneof_ofs, uint8_t) = val; -} - - -static bool upb_msg_oneofis(const upb_msg *msg, const upb_msglayout *l, - const upb_oneofdef *o, const upb_fielddef *f) { - return upb_msg_getoneofint(msg, o, l) == upb_fielddef_number(f); -} - -size_t upb_msg_sizeof(const upb_msglayout *l) { return l->size; } - -void upb_msg_init(upb_msg *msg, const upb_msglayout *l, upb_alloc *a) { - if (l->default_msg) { - memcpy(msg, l->default_msg, l->size); - } else { - memset(msg, 0, l->size); - } - - /* Set arena pointer. */ - memcpy(msg, &a, sizeof(a)); -} - -void upb_msg_uninit(upb_msg *msg, const upb_msglayout *l) { - upb_inttable *ext_dict = upb_msg_trygetextdict(msg, l); - if (ext_dict) { - upb_inttable_uninit2(ext_dict, upb_msg_alloc(msg, l)); - } -} - -upb_msg *upb_msg_new(const upb_msglayout *l, upb_alloc *a) { - upb_msg *msg = upb_malloc(a, upb_msg_sizeof(l)); - - if (msg) { - upb_msg_init(msg, l, a); - } - - return msg; -} - -void upb_msg_free(upb_msg *msg, const upb_msglayout *l) { - upb_msg_uninit(msg, l); - upb_free(upb_msg_alloc(msg, l), msg); -} - -upb_alloc *upb_msg_alloc(const upb_msg *msg, const upb_msglayout *l) { - upb_alloc *alloc; - UPB_UNUSED(l); - memcpy(&alloc, msg, sizeof(alloc)); - return alloc; -} - -bool upb_msg_has(const upb_msg *msg, - const upb_fielddef *f, - const upb_msglayout *l) { - const upb_oneofdef *o; - upb_msg_checkfield(l, f); - UPB_ASSERT(upb_fielddef_haspresence(f)); - - if (upb_fielddef_isextension(f)) { - /* Extensions are set when they are present in the extension dict. */ - upb_inttable *ext_dict = upb_msg_trygetextdict(msg, l); - upb_value v; - return ext_dict != NULL && - upb_inttable_lookup32(ext_dict, upb_fielddef_number(f), &v); - } else if ((o = upb_fielddef_containingoneof(f)) != NULL) { - /* Oneofs are set when the oneof number is set to this field. */ - return upb_msg_getoneofint(msg, o, l) == upb_fielddef_number(f); - } else { - /* Other fields are set when their hasbit is set. */ - uint32_t hasbit = l->hasbits[upb_fielddef_index(f)]; - return DEREF(msg, hasbit / 8, char) | (1 << (hasbit % 8)); - } -} - -upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f, - const upb_msglayout *l) { - upb_msg_checkfield(l, f); - - if (upb_fielddef_isextension(f)) { - upb_inttable *ext_dict = upb_msg_trygetextdict(msg, l); - upb_value val; - if (upb_inttable_lookup32(ext_dict, upb_fielddef_number(f), &val)) { - return upb_msgval_fromval(val); - } else { - return upb_msgval_fromdefault(f); - } - } else { - size_t ofs = l->field_offsets[upb_fielddef_index(f)]; - const upb_oneofdef *o = upb_fielddef_containingoneof(f); - upb_msgval ret; - - if (o && !upb_msg_oneofis(msg, l, o, f)) { - /* Oneof defaults can't come from the message because the memory is reused - * by all types in the oneof. */ - return upb_msgval_fromdefault(f); - } - - ret = upb_msgval_read(msg, ofs, upb_msg_fieldsize(f)); - return ret; - } -} - -bool upb_msg_set(upb_msg *msg, - const upb_fielddef *f, - upb_msgval val, - const upb_msglayout *l) { - upb_alloc *a = upb_msg_alloc(msg, l); - upb_msg_checkfield(l, f); - - if (upb_fielddef_isextension(f)) { - /* TODO(haberman): introduce table API that can do this in one call. */ - upb_inttable *ext = upb_msg_getextdict(msg, l, a); - upb_value val2 = upb_toval(val); - if (!upb_inttable_replace(ext, upb_fielddef_number(f), val2) && - !upb_inttable_insert2(ext, upb_fielddef_number(f), val2, a)) { - return false; - } - } else { - size_t ofs = l->field_offsets[upb_fielddef_index(f)]; - const upb_oneofdef *o = upb_fielddef_containingoneof(f); - - if (o) { - upb_msg_setoneofcase(msg, o, l, upb_fielddef_number(f)); - } - - upb_msgval_write(msg, ofs, val, upb_msg_fieldsize(f)); - } - return true; -} - - -/** upb_array *****************************************************************/ - -struct upb_array { - upb_fieldtype_t type; - uint8_t element_size; - void *data; /* Each element is element_size. */ - size_t len; /* Measured in elements. */ - size_t size; /* Measured in elements. */ - upb_alloc *alloc; -}; - -#define DEREF_ARR(arr, i, type) ((type*)arr->data)[i] - -size_t upb_array_sizeof(upb_fieldtype_t type) { - UPB_UNUSED(type); - return sizeof(upb_array); -} - -void upb_array_init(upb_array *arr, upb_fieldtype_t type, upb_alloc *alloc) { - arr->type = type; - arr->data = NULL; - arr->len = 0; - arr->size = 0; - arr->element_size = upb_msgval_sizeof(type); - arr->alloc = alloc; -} - -void upb_array_uninit(upb_array *arr) { - upb_free(arr->alloc, arr->data); -} - -upb_array *upb_array_new(upb_fieldtype_t type, upb_alloc *a) { - upb_array *ret = upb_malloc(a, upb_array_sizeof(type)); - - if (ret) { - upb_array_init(ret, type, a); - } - - return ret; -} - -void upb_array_free(upb_array *arr) { - upb_array_uninit(arr); - upb_free(arr->alloc, arr); -} - -size_t upb_array_size(const upb_array *arr) { - return arr->len; -} - -upb_fieldtype_t upb_array_type(const upb_array *arr) { - return arr->type; -} - -upb_msgval upb_array_get(const upb_array *arr, size_t i) { - UPB_ASSERT(i < arr->len); - return upb_msgval_read(arr->data, i * arr->element_size, arr->element_size); -} - -bool upb_array_set(upb_array *arr, size_t i, upb_msgval val) { - UPB_ASSERT(i <= arr->len); - - if (i == arr->len) { - /* Extending the array. */ - - if (i == arr->size) { - /* Need to reallocate. */ - size_t new_size = UPB_MAX(arr->size * 2, 8); - size_t new_bytes = new_size * arr->element_size; - size_t old_bytes = arr->size * arr->element_size; - upb_msgval *new_data = - upb_realloc(arr->alloc, arr->data, old_bytes, new_bytes); - - if (!new_data) { - return false; - } - - arr->data = new_data; - arr->size = new_size; - } - - arr->len = i + 1; - } - - upb_msgval_write(arr->data, i * arr->element_size, val, arr->element_size); - return true; -} - - -/** upb_map *******************************************************************/ - -struct upb_map { - upb_fieldtype_t key_type; - upb_fieldtype_t val_type; - /* We may want to optimize this to use inttable where possible, for greater - * efficiency and lower memory footprint. */ - upb_strtable strtab; - upb_alloc *alloc; -}; - -static void upb_map_tokey(upb_fieldtype_t type, upb_msgval *key, - const char **out_key, size_t *out_len) { - switch (type) { - case UPB_TYPE_STRING: - /* Point to string data of the input key. */ - *out_key = key->str.ptr; - *out_len = key->str.len; - return; - case UPB_TYPE_BOOL: - case UPB_TYPE_INT32: - case UPB_TYPE_UINT32: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT64: - /* Point to the key itself. XXX: big-endian. */ - *out_key = (const char*)key; - *out_len = upb_msgval_sizeof(type); - return; - case UPB_TYPE_BYTES: - case UPB_TYPE_DOUBLE: - case UPB_TYPE_ENUM: - case UPB_TYPE_FLOAT: - case UPB_TYPE_MESSAGE: - break; /* Cannot be a map key. */ - } - UPB_UNREACHABLE(); -} - -static upb_msgval upb_map_fromkey(upb_fieldtype_t type, const char *key, - size_t len) { - switch (type) { - case UPB_TYPE_STRING: - return upb_msgval_str(key, len); - case UPB_TYPE_BOOL: - case UPB_TYPE_INT32: - case UPB_TYPE_UINT32: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT64: - return upb_msgval_read(key, 0, upb_msgval_sizeof(type)); - case UPB_TYPE_BYTES: - case UPB_TYPE_DOUBLE: - case UPB_TYPE_ENUM: - case UPB_TYPE_FLOAT: - case UPB_TYPE_MESSAGE: - break; /* Cannot be a map key. */ - } - UPB_UNREACHABLE(); -} - -size_t upb_map_sizeof(upb_fieldtype_t ktype, upb_fieldtype_t vtype) { - /* Size does not currently depend on key/value type. */ - UPB_UNUSED(ktype); - UPB_UNUSED(vtype); - return sizeof(upb_map); -} - -bool upb_map_init(upb_map *map, upb_fieldtype_t ktype, upb_fieldtype_t vtype, - upb_alloc *a) { - upb_ctype_t vtabtype = upb_fieldtotabtype(vtype); - UPB_ASSERT(upb_fieldtype_mapkeyok(ktype)); - map->key_type = ktype; - map->val_type = vtype; - map->alloc = a; - - if (!upb_strtable_init2(&map->strtab, vtabtype, a)) { - return false; - } - - return true; -} - -void upb_map_uninit(upb_map *map) { - upb_strtable_uninit2(&map->strtab, map->alloc); -} - -upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype, - upb_alloc *a) { - upb_map *map = upb_malloc(a, upb_map_sizeof(ktype, vtype)); - - if (!map) { - return NULL; - } - - if (!upb_map_init(map, ktype, vtype, a)) { - return NULL; - } - - return map; -} - -void upb_map_free(upb_map *map) { - upb_map_uninit(map); - upb_free(map->alloc, map); -} - -size_t upb_map_size(const upb_map *map) { - return upb_strtable_count(&map->strtab); -} - -upb_fieldtype_t upb_map_keytype(const upb_map *map) { - return map->key_type; -} - -upb_fieldtype_t upb_map_valuetype(const upb_map *map) { - return map->val_type; -} - -bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) { - upb_value tabval; - const char *key_str; - size_t key_len; - bool ret; - - upb_map_tokey(map->key_type, &key, &key_str, &key_len); - ret = upb_strtable_lookup2(&map->strtab, key_str, key_len, &tabval); - if (ret) { - memcpy(val, &tabval, sizeof(tabval)); - } - - return ret; -} - -bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, - upb_msgval *removed) { - const char *key_str; - size_t key_len; - upb_value tabval = upb_toval(val); - upb_value removedtabval; - upb_alloc *a = map->alloc; - - upb_map_tokey(map->key_type, &key, &key_str, &key_len); - - /* TODO(haberman): add overwrite operation to minimize number of lookups. */ - if (upb_strtable_lookup2(&map->strtab, key_str, key_len, NULL)) { - upb_strtable_remove3(&map->strtab, key_str, key_len, &removedtabval, a); - memcpy(&removed, &removedtabval, sizeof(removed)); - } - - return upb_strtable_insert3(&map->strtab, key_str, key_len, tabval, a); -} - -bool upb_map_del(upb_map *map, upb_msgval key) { - const char *key_str; - size_t key_len; - upb_alloc *a = map->alloc; - - upb_map_tokey(map->key_type, &key, &key_str, &key_len); - return upb_strtable_remove3(&map->strtab, key_str, key_len, NULL, a); -} - - -/** upb_mapiter ***************************************************************/ - -struct upb_mapiter { - upb_strtable_iter iter; - upb_fieldtype_t key_type; -}; - -size_t upb_mapiter_sizeof() { - return sizeof(upb_mapiter); -} - -void upb_mapiter_begin(upb_mapiter *i, const upb_map *map) { - upb_strtable_begin(&i->iter, &map->strtab); - i->key_type = map->key_type; -} - -upb_mapiter *upb_mapiter_new(const upb_map *t, upb_alloc *a) { - upb_mapiter *ret = upb_malloc(a, upb_mapiter_sizeof()); - - if (!ret) { - return NULL; - } - - upb_mapiter_begin(ret, t); - return ret; -} - -void upb_mapiter_free(upb_mapiter *i, upb_alloc *a) { - upb_free(a, i); -} - -void upb_mapiter_next(upb_mapiter *i) { - upb_strtable_next(&i->iter); -} - -bool upb_mapiter_done(const upb_mapiter *i) { - return upb_strtable_done(&i->iter); -} - -upb_msgval upb_mapiter_key(const upb_mapiter *i) { - return upb_map_fromkey(i->key_type, upb_strtable_iter_key(&i->iter), - upb_strtable_iter_keylength(&i->iter)); -} - -upb_msgval upb_mapiter_value(const upb_mapiter *i) { - return upb_msgval_fromval(upb_strtable_iter_value(&i->iter)); -} - -void upb_mapiter_setdone(upb_mapiter *i) { - upb_strtable_iter_setdone(&i->iter); -} - -bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2) { - return upb_strtable_iter_isequal(&i1->iter, &i2->iter); -} - - -/** Handlers for upb_msg ******************************************************/ - -typedef struct { - size_t offset; - int32_t hasbit; -} upb_msg_handlerdata; - -/* Fallback implementation if the handler is not specialized by the producer. */ -#define MSG_WRITER(type, ctype) \ - bool upb_msg_set ## type (void *c, const void *hd, ctype val) { \ - uint8_t *m = c; \ - const upb_msg_handlerdata *d = hd; \ - if (d->hasbit > 0) \ - *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8); \ - *(ctype*)&m[d->offset] = val; \ - return true; \ - } \ - -MSG_WRITER(double, double) -MSG_WRITER(float, float) -MSG_WRITER(int32, int32_t) -MSG_WRITER(int64, int64_t) -MSG_WRITER(uint32, uint32_t) -MSG_WRITER(uint64, uint64_t) -MSG_WRITER(bool, bool) - -bool upb_msg_setscalarhandler(upb_handlers *h, const upb_fielddef *f, - size_t offset, int32_t hasbit) { - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - bool ok; - - upb_msg_handlerdata *d = upb_gmalloc(sizeof(*d)); - if (!d) return false; - d->offset = offset; - d->hasbit = hasbit; - - upb_handlerattr_sethandlerdata(&attr, d); - upb_handlerattr_setalwaysok(&attr, true); - upb_handlers_addcleanup(h, d, upb_gfree); - -#define TYPE(u, l) \ - case UPB_TYPE_##u: \ - ok = upb_handlers_set##l(h, f, upb_msg_set##l, &attr); break; - - ok = false; - - switch (upb_fielddef_type(f)) { - TYPE(INT64, int64); - TYPE(INT32, int32); - TYPE(ENUM, int32); - TYPE(UINT64, uint64); - TYPE(UINT32, uint32); - TYPE(DOUBLE, double); - TYPE(FLOAT, float); - TYPE(BOOL, bool); - default: UPB_ASSERT(false); break; - } -#undef TYPE - - upb_handlerattr_uninit(&attr); - return ok; -} - -bool upb_msg_getscalarhandlerdata(const upb_handlers *h, - upb_selector_t s, - upb_fieldtype_t *type, - size_t *offset, - int32_t *hasbit) { - const upb_msg_handlerdata *d; - upb_func *f = upb_handlers_gethandler(h, s); - - if ((upb_int64_handlerfunc*)f == upb_msg_setint64) { - *type = UPB_TYPE_INT64; - } else if ((upb_int32_handlerfunc*)f == upb_msg_setint32) { - *type = UPB_TYPE_INT32; - } else if ((upb_uint64_handlerfunc*)f == upb_msg_setuint64) { - *type = UPB_TYPE_UINT64; - } else if ((upb_uint32_handlerfunc*)f == upb_msg_setuint32) { - *type = UPB_TYPE_UINT32; - } else if ((upb_double_handlerfunc*)f == upb_msg_setdouble) { - *type = UPB_TYPE_DOUBLE; - } else if ((upb_float_handlerfunc*)f == upb_msg_setfloat) { - *type = UPB_TYPE_FLOAT; - } else if ((upb_bool_handlerfunc*)f == upb_msg_setbool) { - *type = UPB_TYPE_BOOL; - } else { - return false; - } - - d = upb_handlers_gethandlerdata(h, s); - *offset = d->offset; - *hasbit = d->hasbit; - return true; -} -/* -** upb::RefCounted Implementation -** -** Our key invariants are: -** 1. reference cycles never span groups -** 2. for ref2(to, from), we increment to's count iff group(from) != group(to) -** -** The previous two are how we avoid leaking cycles. Other important -** invariants are: -** 3. for mutable objects "from" and "to", if there exists a ref2(to, from) -** this implies group(from) == group(to). (In practice, what we implement -** is even stronger; "from" and "to" will share a group if there has *ever* -** been a ref2(to, from), but all that is necessary for correctness is the -** weaker one). -** 4. mutable and immutable objects are never in the same group. -*/ - - -#include - -static void freeobj(upb_refcounted *o); - -const char untracked_val; -const void *UPB_UNTRACKED_REF = &untracked_val; - -/* arch-specific atomic primitives *******************************************/ - -#ifdef UPB_THREAD_UNSAFE /*---------------------------------------------------*/ - -static void atomic_inc(uint32_t *a) { (*a)++; } -static bool atomic_dec(uint32_t *a) { return --(*a) == 0; } - -#elif defined(__GNUC__) || defined(__clang__) /*------------------------------*/ - -static void atomic_inc(uint32_t *a) { __sync_fetch_and_add(a, 1); } -static bool atomic_dec(uint32_t *a) { return __sync_sub_and_fetch(a, 1) == 0; } - -#elif defined(WIN32) /*-------------------------------------------------------*/ - -#include - -static void atomic_inc(upb_atomic_t *a) { InterlockedIncrement(&a->val); } -static bool atomic_dec(upb_atomic_t *a) { - return InterlockedDecrement(&a->val) == 0; -} - -#else -#error Atomic primitives not defined for your platform/CPU. \ - Implement them or compile with UPB_THREAD_UNSAFE. -#endif - -/* All static objects point to this refcount. - * It is special-cased in ref/unref below. */ -uint32_t static_refcount = -1; - -/* We can avoid atomic ops for statically-declared objects. - * This is a minor optimization but nice since we can avoid degrading under - * contention in this case. */ - -static void refgroup(uint32_t *group) { - if (group != &static_refcount) - atomic_inc(group); -} - -static bool unrefgroup(uint32_t *group) { - if (group == &static_refcount) { - return false; - } else { - return atomic_dec(group); - } -} - - -/* Reference tracking (debug only) ********************************************/ - -#ifdef UPB_DEBUG_REFS - -#ifdef UPB_THREAD_UNSAFE - -static void upb_lock() {} -static void upb_unlock() {} - -#else - -/* User must define functions that lock/unlock a global mutex and link this - * file against them. */ -void upb_lock(); -void upb_unlock(); - -#endif - -/* UPB_DEBUG_REFS mode counts on being able to malloc() memory in some - * code-paths that can normally never fail, like upb_refcounted_ref(). Since - * we have no way to propagage out-of-memory errors back to the user, and since - * these errors can only occur in UPB_DEBUG_REFS mode, we use an allocator that - * immediately aborts on failure (avoiding the global allocator, which might - * inject failures). */ - -#include - -static void *upb_debugrefs_allocfunc(upb_alloc *alloc, void *ptr, - size_t oldsize, size_t size) { - UPB_UNUSED(alloc); - UPB_UNUSED(oldsize); - if (size == 0) { - free(ptr); - return NULL; - } else { - void *ret = realloc(ptr, size); - - if (!ret) { - abort(); - } - - return ret; - } -} - -upb_alloc upb_alloc_debugrefs = {&upb_debugrefs_allocfunc}; - -typedef struct { - int count; /* How many refs there are (duplicates only allowed for ref2). */ - bool is_ref2; -} trackedref; - -static trackedref *trackedref_new(bool is_ref2) { - trackedref *ret = upb_malloc(&upb_alloc_debugrefs, sizeof(*ret)); - ret->count = 1; - ret->is_ref2 = is_ref2; - return ret; -} - -static void track(const upb_refcounted *r, const void *owner, bool ref2) { - upb_value v; - - UPB_ASSERT(owner); - if (owner == UPB_UNTRACKED_REF) return; - - upb_lock(); - if (upb_inttable_lookupptr(r->refs, owner, &v)) { - trackedref *ref = upb_value_getptr(v); - /* Since we allow multiple ref2's for the same to/from pair without - * allocating separate memory for each one, we lose the fine-grained - * tracking behavior we get with regular refs. Since ref2s only happen - * inside upb, we'll accept this limitation until/unless there is a really - * difficult upb-internal bug that can't be figured out without it. */ - UPB_ASSERT(ref2); - UPB_ASSERT(ref->is_ref2); - ref->count++; - } else { - trackedref *ref = trackedref_new(ref2); - upb_inttable_insertptr2(r->refs, owner, upb_value_ptr(ref), - &upb_alloc_debugrefs); - if (ref2) { - /* We know this cast is safe when it is a ref2, because it's coming from - * another refcounted object. */ - const upb_refcounted *from = owner; - UPB_ASSERT(!upb_inttable_lookupptr(from->ref2s, r, NULL)); - upb_inttable_insertptr2(from->ref2s, r, upb_value_ptr(NULL), - &upb_alloc_debugrefs); - } - } - upb_unlock(); -} - -static void untrack(const upb_refcounted *r, const void *owner, bool ref2) { - upb_value v; - bool found; - trackedref *ref; - - UPB_ASSERT(owner); - if (owner == UPB_UNTRACKED_REF) return; - - upb_lock(); - found = upb_inttable_lookupptr(r->refs, owner, &v); - /* This assert will fail if an owner attempts to release a ref it didn't have. */ - UPB_ASSERT(found); - ref = upb_value_getptr(v); - UPB_ASSERT(ref->is_ref2 == ref2); - if (--ref->count == 0) { - free(ref); - upb_inttable_removeptr(r->refs, owner, NULL); - if (ref2) { - /* We know this cast is safe when it is a ref2, because it's coming from - * another refcounted object. */ - const upb_refcounted *from = owner; - bool removed = upb_inttable_removeptr(from->ref2s, r, NULL); - UPB_ASSERT(removed); - } - } - upb_unlock(); -} - -static void checkref(const upb_refcounted *r, const void *owner, bool ref2) { - upb_value v; - bool found; - trackedref *ref; - - upb_lock(); - found = upb_inttable_lookupptr(r->refs, owner, &v); - UPB_ASSERT(found); - ref = upb_value_getptr(v); - UPB_ASSERT(ref->is_ref2 == ref2); - upb_unlock(); -} - -/* Populates the given UPB_CTYPE_INT32 inttable with counts of ref2's that - * originate from the given owner. */ -static void getref2s(const upb_refcounted *owner, upb_inttable *tab) { - upb_inttable_iter i; - - upb_lock(); - upb_inttable_begin(&i, owner->ref2s); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_value v; - upb_value count; - trackedref *ref; - bool found; - - upb_refcounted *to = (upb_refcounted*)upb_inttable_iter_key(&i); - - /* To get the count we need to look in the target's table. */ - found = upb_inttable_lookupptr(to->refs, owner, &v); - UPB_ASSERT(found); - ref = upb_value_getptr(v); - count = upb_value_int32(ref->count); - - upb_inttable_insertptr2(tab, to, count, &upb_alloc_debugrefs); - } - upb_unlock(); -} - -typedef struct { - upb_inttable ref2; - const upb_refcounted *obj; -} check_state; - -static void visit_check(const upb_refcounted *obj, const upb_refcounted *subobj, - void *closure) { - check_state *s = closure; - upb_inttable *ref2 = &s->ref2; - upb_value v; - bool removed; - int32_t newcount; - - UPB_ASSERT(obj == s->obj); - UPB_ASSERT(subobj); - removed = upb_inttable_removeptr(ref2, subobj, &v); - /* The following assertion will fail if the visit() function visits a subobj - * that it did not have a ref2 on, or visits the same subobj too many times. */ - UPB_ASSERT(removed); - newcount = upb_value_getint32(v) - 1; - if (newcount > 0) { - upb_inttable_insert2(ref2, (uintptr_t)subobj, upb_value_int32(newcount), - &upb_alloc_debugrefs); - } -} - -static void visit(const upb_refcounted *r, upb_refcounted_visit *v, - void *closure) { - /* In DEBUG_REFS mode we know what existing ref2 refs there are, so we know - * exactly the set of nodes that visit() should visit. So we verify visit()'s - * correctness here. */ - check_state state; - state.obj = r; - upb_inttable_init2(&state.ref2, UPB_CTYPE_INT32, &upb_alloc_debugrefs); - getref2s(r, &state.ref2); - - /* This should visit any children in the ref2 table. */ - if (r->vtbl->visit) r->vtbl->visit(r, visit_check, &state); - - /* This assertion will fail if the visit() function missed any children. */ - UPB_ASSERT(upb_inttable_count(&state.ref2) == 0); - upb_inttable_uninit2(&state.ref2, &upb_alloc_debugrefs); - if (r->vtbl->visit) r->vtbl->visit(r, v, closure); -} - -static void trackinit(upb_refcounted *r) { - r->refs = upb_malloc(&upb_alloc_debugrefs, sizeof(*r->refs)); - r->ref2s = upb_malloc(&upb_alloc_debugrefs, sizeof(*r->ref2s)); - upb_inttable_init2(r->refs, UPB_CTYPE_PTR, &upb_alloc_debugrefs); - upb_inttable_init2(r->ref2s, UPB_CTYPE_PTR, &upb_alloc_debugrefs); -} - -static void trackfree(const upb_refcounted *r) { - upb_inttable_uninit2(r->refs, &upb_alloc_debugrefs); - upb_inttable_uninit2(r->ref2s, &upb_alloc_debugrefs); - upb_free(&upb_alloc_debugrefs, r->refs); - upb_free(&upb_alloc_debugrefs, r->ref2s); -} - -#else - -static void track(const upb_refcounted *r, const void *owner, bool ref2) { - UPB_UNUSED(r); - UPB_UNUSED(owner); - UPB_UNUSED(ref2); -} - -static void untrack(const upb_refcounted *r, const void *owner, bool ref2) { - UPB_UNUSED(r); - UPB_UNUSED(owner); - UPB_UNUSED(ref2); -} - -static void checkref(const upb_refcounted *r, const void *owner, bool ref2) { - UPB_UNUSED(r); - UPB_UNUSED(owner); - UPB_UNUSED(ref2); -} - -static void trackinit(upb_refcounted *r) { - UPB_UNUSED(r); -} - -static void trackfree(const upb_refcounted *r) { - UPB_UNUSED(r); -} - -static void visit(const upb_refcounted *r, upb_refcounted_visit *v, - void *closure) { - if (r->vtbl->visit) r->vtbl->visit(r, v, closure); -} - -#endif /* UPB_DEBUG_REFS */ - - -/* freeze() *******************************************************************/ - -/* The freeze() operation is by far the most complicated part of this scheme. - * We compute strongly-connected components and then mutate the graph such that - * we preserve the invariants documented at the top of this file. And we must - * handle out-of-memory errors gracefully (without leaving the graph - * inconsistent), which adds to the fun. */ - -/* The state used by the freeze operation (shared across many functions). */ -typedef struct { - int depth; - int maxdepth; - uint64_t index; - /* Maps upb_refcounted* -> attributes (color, etc). attr layout varies by - * color. */ - upb_inttable objattr; - upb_inttable stack; /* stack of upb_refcounted* for Tarjan's algorithm. */ - upb_inttable groups; /* array of uint32_t*, malloc'd refcounts for new groups */ - upb_status *status; - jmp_buf err; -} tarjan; - -static void release_ref2(const upb_refcounted *obj, - const upb_refcounted *subobj, - void *closure); - -/* Node attributes -----------------------------------------------------------*/ - -/* After our analysis phase all nodes will be either GRAY or WHITE. */ - -typedef enum { - BLACK = 0, /* Object has not been seen. */ - GRAY, /* Object has been found via a refgroup but may not be reachable. */ - GREEN, /* Object is reachable and is currently on the Tarjan stack. */ - WHITE /* Object is reachable and has been assigned a group (SCC). */ -} color_t; - -UPB_NORETURN static void err(tarjan *t) { longjmp(t->err, 1); } -UPB_NORETURN static void oom(tarjan *t) { - upb_status_seterrmsg(t->status, "out of memory"); - err(t); -} - -static uint64_t trygetattr(const tarjan *t, const upb_refcounted *r) { - upb_value v; - return upb_inttable_lookupptr(&t->objattr, r, &v) ? - upb_value_getuint64(v) : 0; -} - -static uint64_t getattr(const tarjan *t, const upb_refcounted *r) { - upb_value v; - bool found = upb_inttable_lookupptr(&t->objattr, r, &v); - UPB_ASSERT(found); - return upb_value_getuint64(v); -} - -static void setattr(tarjan *t, const upb_refcounted *r, uint64_t attr) { - upb_inttable_removeptr(&t->objattr, r, NULL); - upb_inttable_insertptr(&t->objattr, r, upb_value_uint64(attr)); -} - -static color_t color(tarjan *t, const upb_refcounted *r) { - return trygetattr(t, r) & 0x3; /* Color is always stored in the low 2 bits. */ -} - -static void set_gray(tarjan *t, const upb_refcounted *r) { - UPB_ASSERT(color(t, r) == BLACK); - setattr(t, r, GRAY); -} - -/* Pushes an obj onto the Tarjan stack and sets it to GREEN. */ -static void push(tarjan *t, const upb_refcounted *r) { - UPB_ASSERT(color(t, r) == BLACK || color(t, r) == GRAY); - /* This defines the attr layout for the GREEN state. "index" and "lowlink" - * get 31 bits, which is plenty (limit of 2B objects frozen at a time). */ - setattr(t, r, GREEN | (t->index << 2) | (t->index << 33)); - if (++t->index == 0x80000000) { - upb_status_seterrmsg(t->status, "too many objects to freeze"); - err(t); - } - upb_inttable_push(&t->stack, upb_value_ptr((void*)r)); -} - -/* Pops an obj from the Tarjan stack and sets it to WHITE, with a ptr to its - * SCC group. */ -static upb_refcounted *pop(tarjan *t) { - upb_refcounted *r = upb_value_getptr(upb_inttable_pop(&t->stack)); - UPB_ASSERT(color(t, r) == GREEN); - /* This defines the attr layout for nodes in the WHITE state. - * Top of group stack is [group, NULL]; we point at group. */ - setattr(t, r, WHITE | (upb_inttable_count(&t->groups) - 2) << 8); - return r; -} - -static void tarjan_newgroup(tarjan *t) { - uint32_t *group = upb_gmalloc(sizeof(*group)); - if (!group) oom(t); - /* Push group and empty group leader (we'll fill in leader later). */ - if (!upb_inttable_push(&t->groups, upb_value_ptr(group)) || - !upb_inttable_push(&t->groups, upb_value_ptr(NULL))) { - upb_gfree(group); - oom(t); - } - *group = 0; -} - -static uint32_t idx(tarjan *t, const upb_refcounted *r) { - UPB_ASSERT(color(t, r) == GREEN); - return (getattr(t, r) >> 2) & 0x7FFFFFFF; -} - -static uint32_t lowlink(tarjan *t, const upb_refcounted *r) { - if (color(t, r) == GREEN) { - return getattr(t, r) >> 33; - } else { - return UINT32_MAX; - } -} - -static void set_lowlink(tarjan *t, const upb_refcounted *r, uint32_t lowlink) { - UPB_ASSERT(color(t, r) == GREEN); - setattr(t, r, ((uint64_t)lowlink << 33) | (getattr(t, r) & 0x1FFFFFFFF)); -} - -static uint32_t *group(tarjan *t, upb_refcounted *r) { - uint64_t groupnum; - upb_value v; - bool found; - - UPB_ASSERT(color(t, r) == WHITE); - groupnum = getattr(t, r) >> 8; - found = upb_inttable_lookup(&t->groups, groupnum, &v); - UPB_ASSERT(found); - return upb_value_getptr(v); -} - -/* If the group leader for this object's group has not previously been set, - * the given object is assigned to be its leader. */ -static upb_refcounted *groupleader(tarjan *t, upb_refcounted *r) { - uint64_t leader_slot; - upb_value v; - bool found; - - UPB_ASSERT(color(t, r) == WHITE); - leader_slot = (getattr(t, r) >> 8) + 1; - found = upb_inttable_lookup(&t->groups, leader_slot, &v); - UPB_ASSERT(found); - if (upb_value_getptr(v)) { - return upb_value_getptr(v); - } else { - upb_inttable_remove(&t->groups, leader_slot, NULL); - upb_inttable_insert(&t->groups, leader_slot, upb_value_ptr(r)); - return r; - } -} - - -/* Tarjan's algorithm --------------------------------------------------------*/ - -/* See: - * http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm */ -static void do_tarjan(const upb_refcounted *obj, tarjan *t); - -static void tarjan_visit(const upb_refcounted *obj, - const upb_refcounted *subobj, - void *closure) { - tarjan *t = closure; - if (++t->depth > t->maxdepth) { - upb_status_seterrf(t->status, "graph too deep to freeze (%d)", t->maxdepth); - err(t); - } else if (subobj->is_frozen || color(t, subobj) == WHITE) { - /* Do nothing: we don't want to visit or color already-frozen nodes, - * and WHITE nodes have already been assigned a SCC. */ - } else if (color(t, subobj) < GREEN) { - /* Subdef has not yet been visited; recurse on it. */ - do_tarjan(subobj, t); - set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), lowlink(t, subobj))); - } else if (color(t, subobj) == GREEN) { - /* Subdef is in the stack and hence in the current SCC. */ - set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), idx(t, subobj))); - } - --t->depth; -} - -static void do_tarjan(const upb_refcounted *obj, tarjan *t) { - if (color(t, obj) == BLACK) { - /* We haven't seen this object's group; mark the whole group GRAY. */ - const upb_refcounted *o = obj; - do { set_gray(t, o); } while ((o = o->next) != obj); - } - - push(t, obj); - visit(obj, tarjan_visit, t); - if (lowlink(t, obj) == idx(t, obj)) { - tarjan_newgroup(t); - while (pop(t) != obj) - ; - } -} - - -/* freeze() ------------------------------------------------------------------*/ - -static void crossref(const upb_refcounted *r, const upb_refcounted *subobj, - void *_t) { - tarjan *t = _t; - UPB_ASSERT(color(t, r) > BLACK); - if (color(t, subobj) > BLACK && r->group != subobj->group) { - /* Previously this ref was not reflected in subobj->group because they - * were in the same group; now that they are split a ref must be taken. */ - refgroup(subobj->group); - } -} - -static bool freeze(upb_refcounted *const*roots, int n, upb_status *s, - int maxdepth) { - volatile bool ret = false; - int i; - upb_inttable_iter iter; - - /* We run in two passes so that we can allocate all memory before performing - * any mutation of the input -- this allows us to leave the input unchanged - * in the case of memory allocation failure. */ - tarjan t; - t.index = 0; - t.depth = 0; - t.maxdepth = maxdepth; - t.status = s; - if (!upb_inttable_init(&t.objattr, UPB_CTYPE_UINT64)) goto err1; - if (!upb_inttable_init(&t.stack, UPB_CTYPE_PTR)) goto err2; - if (!upb_inttable_init(&t.groups, UPB_CTYPE_PTR)) goto err3; - if (setjmp(t.err) != 0) goto err4; - - - for (i = 0; i < n; i++) { - if (color(&t, roots[i]) < GREEN) { - do_tarjan(roots[i], &t); - } - } - - /* If we've made it this far, no further errors are possible so it's safe to - * mutate the objects without risk of leaving them in an inconsistent state. */ - ret = true; - - /* The transformation that follows requires care. The preconditions are: - * - all objects in attr map are WHITE or GRAY, and are in mutable groups - * (groups of all mutable objs) - * - no ref2(to, from) refs have incremented count(to) if both "to" and - * "from" are in our attr map (this follows from invariants (2) and (3)) */ - - /* Pass 1: we remove WHITE objects from their mutable groups, and add them to - * new groups according to the SCC's we computed. These new groups will - * consist of only frozen objects. None will be immediately collectible, - * because WHITE objects are by definition reachable from one of "roots", - * which the caller must own refs on. */ - upb_inttable_begin(&iter, &t.objattr); - for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) { - upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter); - /* Since removal from a singly-linked list requires access to the object's - * predecessor, we consider obj->next instead of obj for moving. With the - * while() loop we guarantee that we will visit every node's predecessor. - * Proof: - * 1. every node's predecessor is in our attr map. - * 2. though the loop body may change a node's predecessor, it will only - * change it to be the node we are currently operating on, so with a - * while() loop we guarantee ourselves the chance to remove each node. */ - while (color(&t, obj->next) == WHITE && - group(&t, obj->next) != obj->next->group) { - upb_refcounted *leader; - - /* Remove from old group. */ - upb_refcounted *move = obj->next; - if (obj == move) { - /* Removing the last object from a group. */ - UPB_ASSERT(*obj->group == obj->individual_count); - upb_gfree(obj->group); - } else { - obj->next = move->next; - /* This may decrease to zero; we'll collect GRAY objects (if any) that - * remain in the group in the third pass. */ - UPB_ASSERT(*move->group >= move->individual_count); - *move->group -= move->individual_count; - } - - /* Add to new group. */ - leader = groupleader(&t, move); - if (move == leader) { - /* First object added to new group is its leader. */ - move->group = group(&t, move); - move->next = move; - *move->group = move->individual_count; - } else { - /* Group already has at least one object in it. */ - UPB_ASSERT(leader->group == group(&t, move)); - move->group = group(&t, move); - move->next = leader->next; - leader->next = move; - *move->group += move->individual_count; - } - - move->is_frozen = true; - } - } - - /* Pass 2: GRAY and WHITE objects "obj" with ref2(to, obj) references must - * increment count(to) if group(obj) != group(to) (which could now be the - * case if "to" was just frozen). */ - upb_inttable_begin(&iter, &t.objattr); - for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) { - upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter); - visit(obj, crossref, &t); - } - - /* Pass 3: GRAY objects are collected if their group's refcount dropped to - * zero when we removed its white nodes. This can happen if they had only - * been kept alive by virtue of sharing a group with an object that was just - * frozen. - * - * It is important that we do this last, since the GRAY object's free() - * function could call unref2() on just-frozen objects, which will decrement - * refs that were added in pass 2. */ - upb_inttable_begin(&iter, &t.objattr); - for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) { - upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter); - if (obj->group == NULL || *obj->group == 0) { - if (obj->group) { - upb_refcounted *o; - - /* We eagerly free() the group's count (since we can't easily determine - * the group's remaining size it's the easiest way to ensure it gets - * done). */ - upb_gfree(obj->group); - - /* Visit to release ref2's (done in a separate pass since release_ref2 - * depends on o->group being unmodified so it can test merged()). */ - o = obj; - do { visit(o, release_ref2, NULL); } while ((o = o->next) != obj); - - /* Mark "group" fields as NULL so we know to free the objects later in - * this loop, but also don't try to delete the group twice. */ - o = obj; - do { o->group = NULL; } while ((o = o->next) != obj); - } - freeobj(obj); - } - } - -err4: - if (!ret) { - upb_inttable_begin(&iter, &t.groups); - for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) - upb_gfree(upb_value_getptr(upb_inttable_iter_value(&iter))); - } - upb_inttable_uninit(&t.groups); -err3: - upb_inttable_uninit(&t.stack); -err2: - upb_inttable_uninit(&t.objattr); -err1: - return ret; -} - - -/* Misc internal functions ***************************************************/ - -static bool merged(const upb_refcounted *r, const upb_refcounted *r2) { - return r->group == r2->group; -} - -static void merge(upb_refcounted *r, upb_refcounted *from) { - upb_refcounted *base; - upb_refcounted *tmp; - - if (merged(r, from)) return; - *r->group += *from->group; - upb_gfree(from->group); - base = from; - - /* Set all refcount pointers in the "from" chain to the merged refcount. - * - * TODO(haberman): this linear algorithm can result in an overall O(n^2) bound - * if the user continuously extends a group by one object. Prevent this by - * using one of the techniques in this paper: - * http://bioinfo.ict.ac.cn/~dbu/AlgorithmCourses/Lectures/Union-Find-Tarjan.pdf */ - do { from->group = r->group; } while ((from = from->next) != base); - - /* Merge the two circularly linked lists by swapping their next pointers. */ - tmp = r->next; - r->next = base->next; - base->next = tmp; -} - -static void unref(const upb_refcounted *r); - -static void release_ref2(const upb_refcounted *obj, - const upb_refcounted *subobj, - void *closure) { - UPB_UNUSED(closure); - untrack(subobj, obj, true); - if (!merged(obj, subobj)) { - UPB_ASSERT(subobj->is_frozen); - unref(subobj); - } -} - -static void unref(const upb_refcounted *r) { - if (unrefgroup(r->group)) { - const upb_refcounted *o; - - upb_gfree(r->group); - - /* In two passes, since release_ref2 needs a guarantee that any subobjs - * are alive. */ - o = r; - do { visit(o, release_ref2, NULL); } while((o = o->next) != r); - - o = r; - do { - const upb_refcounted *next = o->next; - UPB_ASSERT(o->is_frozen || o->individual_count == 0); - freeobj((upb_refcounted*)o); - o = next; - } while(o != r); - } -} - -static void freeobj(upb_refcounted *o) { - trackfree(o); - o->vtbl->free((upb_refcounted*)o); -} - - -/* Public interface ***********************************************************/ - -bool upb_refcounted_init(upb_refcounted *r, - const struct upb_refcounted_vtbl *vtbl, - const void *owner) { -#ifndef NDEBUG - /* Endianness check. This is unrelated to upb_refcounted, it's just a - * convenient place to put the check that we can be assured will run for - * basically every program using upb. */ - const int x = 1; -#ifdef UPB_BIG_ENDIAN - UPB_ASSERT(*(char*)&x != 1); -#else - UPB_ASSERT(*(char*)&x == 1); -#endif -#endif - - r->next = r; - r->vtbl = vtbl; - r->individual_count = 0; - r->is_frozen = false; - r->group = upb_gmalloc(sizeof(*r->group)); - if (!r->group) return false; - *r->group = 0; - trackinit(r); - upb_refcounted_ref(r, owner); - return true; -} - -bool upb_refcounted_isfrozen(const upb_refcounted *r) { - return r->is_frozen; -} - -void upb_refcounted_ref(const upb_refcounted *r, const void *owner) { - track(r, owner, false); - if (!r->is_frozen) - ((upb_refcounted*)r)->individual_count++; - refgroup(r->group); -} - -void upb_refcounted_unref(const upb_refcounted *r, const void *owner) { - untrack(r, owner, false); - if (!r->is_frozen) - ((upb_refcounted*)r)->individual_count--; - unref(r); -} - -void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from) { - UPB_ASSERT(!from->is_frozen); /* Non-const pointer implies this. */ - track(r, from, true); - if (r->is_frozen) { - refgroup(r->group); - } else { - merge((upb_refcounted*)r, from); - } -} - -void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from) { - UPB_ASSERT(!from->is_frozen); /* Non-const pointer implies this. */ - untrack(r, from, true); - if (r->is_frozen) { - unref(r); - } else { - UPB_ASSERT(merged(r, from)); - } -} - -void upb_refcounted_donateref( - const upb_refcounted *r, const void *from, const void *to) { - UPB_ASSERT(from != to); - if (to != NULL) - upb_refcounted_ref(r, to); - if (from != NULL) - upb_refcounted_unref(r, from); -} - -void upb_refcounted_checkref(const upb_refcounted *r, const void *owner) { - checkref(r, owner, false); -} - -bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s, - int maxdepth) { - int i; - bool ret; - for (i = 0; i < n; i++) { - UPB_ASSERT(!roots[i]->is_frozen); - } - ret = freeze(roots, n, s, maxdepth); - UPB_ASSERT(!s || ret == upb_ok(s)); - return ret; -} - - -bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink *sink) { - void *subc; - bool ret; - upb_bufhandle handle; - upb_bufhandle_init(&handle); - upb_bufhandle_setbuf(&handle, buf, 0); - ret = upb_bytessink_start(sink, len, &subc); - if (ret && len != 0) { - ret = (upb_bytessink_putbuf(sink, subc, buf, len, &handle) >= len); - } - if (ret) { - ret = upb_bytessink_end(sink); - } - upb_bufhandle_uninit(&handle); - return ret; -} - -struct upb_bufsink { - upb_byteshandler handler; - upb_bytessink sink; - upb_env *env; - char *ptr; - size_t len, size; -}; - -static void *upb_bufsink_start(void *_sink, const void *hd, size_t size_hint) { - upb_bufsink *sink = _sink; - UPB_UNUSED(hd); - UPB_UNUSED(size_hint); - sink->len = 0; - return sink; -} - -static size_t upb_bufsink_string(void *_sink, const void *hd, const char *ptr, - size_t len, const upb_bufhandle *handle) { - upb_bufsink *sink = _sink; - size_t new_size = sink->size; - - UPB_ASSERT(new_size > 0); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - while (sink->len + len > new_size) { - new_size *= 2; - } - - if (new_size != sink->size) { - sink->ptr = upb_env_realloc(sink->env, sink->ptr, sink->size, new_size); - sink->size = new_size; - } - - memcpy(sink->ptr + sink->len, ptr, len); - sink->len += len; - - return len; -} - -upb_bufsink *upb_bufsink_new(upb_env *env) { - upb_bufsink *sink = upb_env_malloc(env, sizeof(upb_bufsink)); - upb_byteshandler_init(&sink->handler); - upb_byteshandler_setstartstr(&sink->handler, upb_bufsink_start, NULL); - upb_byteshandler_setstring(&sink->handler, upb_bufsink_string, NULL); - - upb_bytessink_reset(&sink->sink, &sink->handler, sink); - - sink->env = env; - sink->size = 32; - sink->ptr = upb_env_malloc(env, sink->size); - sink->len = 0; - - return sink; -} - -void upb_bufsink_free(upb_bufsink *sink) { - upb_env_free(sink->env, sink->ptr); - upb_env_free(sink->env, sink); -} - -upb_bytessink *upb_bufsink_sink(upb_bufsink *sink) { - return &sink->sink; -} - -const char *upb_bufsink_getdata(const upb_bufsink *sink, size_t *len) { - *len = sink->len; - return sink->ptr; -} -/* -** upb_table Implementation -** -** Implementation is heavily inspired by Lua's ltable.c. -*/ - - -#include - -#define UPB_MAXARRSIZE 16 /* 64k. */ - -/* From Chromium. */ -#define ARRAY_SIZE(x) \ - ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) - -static void upb_check_alloc(upb_table *t, upb_alloc *a) { - UPB_UNUSED(t); - UPB_UNUSED(a); - UPB_ASSERT_DEBUGVAR(t->alloc == a); -} - -static const double MAX_LOAD = 0.85; - -/* The minimum utilization of the array part of a mixed hash/array table. This - * is a speed/memory-usage tradeoff (though it's not straightforward because of - * cache effects). The lower this is, the more memory we'll use. */ -static const double MIN_DENSITY = 0.1; - -bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; } - -int log2ceil(uint64_t v) { - int ret = 0; - bool pow2 = is_pow2(v); - while (v >>= 1) ret++; - ret = pow2 ? ret : ret + 1; /* Ceiling. */ - return UPB_MIN(UPB_MAXARRSIZE, ret); -} - -char *upb_strdup(const char *s, upb_alloc *a) { - return upb_strdup2(s, strlen(s), a); -} - -char *upb_strdup2(const char *s, size_t len, upb_alloc *a) { - size_t n; - char *p; - - /* Prevent overflow errors. */ - if (len == SIZE_MAX) return NULL; - /* Always null-terminate, even if binary data; but don't rely on the input to - * have a null-terminating byte since it may be a raw binary buffer. */ - n = len + 1; - p = upb_malloc(a, n); - if (p) { - memcpy(p, s, len); - p[len] = 0; - } - return p; -} - -/* A type to represent the lookup key of either a strtable or an inttable. */ -typedef union { - uintptr_t num; - struct { - const char *str; - size_t len; - } str; -} lookupkey_t; - -static lookupkey_t strkey2(const char *str, size_t len) { - lookupkey_t k; - k.str.str = str; - k.str.len = len; - return k; -} - -static lookupkey_t intkey(uintptr_t key) { - lookupkey_t k; - k.num = key; - return k; -} - -typedef uint32_t hashfunc_t(upb_tabkey key); -typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2); - -/* Base table (shared code) ***************************************************/ - -/* For when we need to cast away const. */ -static upb_tabent *mutable_entries(upb_table *t) { - return (upb_tabent*)t->entries; -} - -static bool isfull(upb_table *t) { - if (upb_table_size(t) == 0) { - return true; - } else { - return ((double)(t->count + 1) / upb_table_size(t)) > MAX_LOAD; - } -} - -static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2, - upb_alloc *a) { - size_t bytes; - - t->count = 0; - t->ctype = ctype; - t->size_lg2 = size_lg2; - t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0; -#ifndef NDEBUG - t->alloc = a; -#endif - bytes = upb_table_size(t) * sizeof(upb_tabent); - if (bytes > 0) { - t->entries = upb_malloc(a, bytes); - if (!t->entries) return false; - memset(mutable_entries(t), 0, bytes); - } else { - t->entries = NULL; - } - return true; -} - -static void uninit(upb_table *t, upb_alloc *a) { - upb_check_alloc(t, a); - upb_free(a, mutable_entries(t)); -} - -static upb_tabent *emptyent(upb_table *t) { - upb_tabent *e = mutable_entries(t) + upb_table_size(t); - while (1) { if (upb_tabent_isempty(--e)) return e; UPB_ASSERT(e > t->entries); } -} - -static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) { - return (upb_tabent*)upb_getentry(t, hash); -} - -static const upb_tabent *findentry(const upb_table *t, lookupkey_t key, - uint32_t hash, eqlfunc_t *eql) { - const upb_tabent *e; - - if (t->size_lg2 == 0) return NULL; - e = upb_getentry(t, hash); - if (upb_tabent_isempty(e)) return NULL; - while (1) { - if (eql(e->key, key)) return e; - if ((e = e->next) == NULL) return NULL; - } -} - -static upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key, - uint32_t hash, eqlfunc_t *eql) { - return (upb_tabent*)findentry(t, key, hash, eql); -} - -static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v, - uint32_t hash, eqlfunc_t *eql) { - const upb_tabent *e = findentry(t, key, hash, eql); - if (e) { - if (v) { - _upb_value_setval(v, e->val.val, t->ctype); - } - return true; - } else { - return false; - } -} - -/* The given key must not already exist in the table. */ -static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey, - upb_value val, uint32_t hash, - hashfunc_t *hashfunc, eqlfunc_t *eql) { - upb_tabent *mainpos_e; - upb_tabent *our_e; - - UPB_ASSERT(findentry(t, key, hash, eql) == NULL); - UPB_ASSERT_DEBUGVAR(val.ctype == t->ctype); - - t->count++; - mainpos_e = getentry_mutable(t, hash); - our_e = mainpos_e; - - if (upb_tabent_isempty(mainpos_e)) { - /* Our main position is empty; use it. */ - our_e->next = NULL; - } else { - /* Collision. */ - upb_tabent *new_e = emptyent(t); - /* Head of collider's chain. */ - upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key)); - if (chain == mainpos_e) { - /* Existing ent is in its main posisiton (it has the same hash as us, and - * is the head of our chain). Insert to new ent and append to this chain. */ - new_e->next = mainpos_e->next; - mainpos_e->next = new_e; - our_e = new_e; - } else { - /* Existing ent is not in its main position (it is a node in some other - * chain). This implies that no existing ent in the table has our hash. - * Evict it (updating its chain) and use its ent for head of our chain. */ - *new_e = *mainpos_e; /* copies next. */ - while (chain->next != mainpos_e) { - chain = (upb_tabent*)chain->next; - UPB_ASSERT(chain); - } - chain->next = new_e; - our_e = mainpos_e; - our_e->next = NULL; - } - } - our_e->key = tabkey; - our_e->val.val = val.val; - UPB_ASSERT(findentry(t, key, hash, eql) == our_e); -} - -static bool rm(upb_table *t, lookupkey_t key, upb_value *val, - upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) { - upb_tabent *chain = getentry_mutable(t, hash); - if (upb_tabent_isempty(chain)) return false; - if (eql(chain->key, key)) { - /* Element to remove is at the head of its chain. */ - t->count--; - if (val) _upb_value_setval(val, chain->val.val, t->ctype); - if (removed) *removed = chain->key; - if (chain->next) { - upb_tabent *move = (upb_tabent*)chain->next; - *chain = *move; - move->key = 0; /* Make the slot empty. */ - } else { - chain->key = 0; /* Make the slot empty. */ - } - return true; - } else { - /* Element to remove is either in a non-head position or not in the - * table. */ - while (chain->next && !eql(chain->next->key, key)) { - chain = (upb_tabent*)chain->next; - } - if (chain->next) { - /* Found element to remove. */ - upb_tabent *rm = (upb_tabent*)chain->next; - t->count--; - if (val) _upb_value_setval(val, chain->next->val.val, t->ctype); - if (removed) *removed = rm->key; - rm->key = 0; /* Make the slot empty. */ - chain->next = rm->next; - return true; - } else { - /* Element to remove is not in the table. */ - return false; - } - } -} - -static size_t next(const upb_table *t, size_t i) { - do { - if (++i >= upb_table_size(t)) - return SIZE_MAX; - } while(upb_tabent_isempty(&t->entries[i])); - - return i; -} - -static size_t begin(const upb_table *t) { - return next(t, -1); -} - - -/* upb_strtable ***************************************************************/ - -/* A simple "subclass" of upb_table that only adds a hash function for strings. */ - -static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) { - char *str = upb_malloc(a, k2.str.len + sizeof(uint32_t) + 1); - if (str == NULL) return 0; - memcpy(str, &k2.str.len, sizeof(uint32_t)); - memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len + 1); - return (uintptr_t)str; -} - -static uint32_t strhash(upb_tabkey key) { - uint32_t len; - char *str = upb_tabstr(key, &len); - return MurmurHash2(str, len, 0); -} - -static bool streql(upb_tabkey k1, lookupkey_t k2) { - uint32_t len; - char *str = upb_tabstr(k1, &len); - return len == k2.str.len && memcmp(str, k2.str.str, len) == 0; -} - -bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) { - return init(&t->t, ctype, 2, a); -} - -void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) { - size_t i; - for (i = 0; i < upb_table_size(&t->t); i++) - upb_free(a, (void*)t->t.entries[i].key); - uninit(&t->t, a); -} - -bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) { - upb_strtable new_table; - upb_strtable_iter i; - - upb_check_alloc(&t->t, a); - - if (!init(&new_table.t, t->t.ctype, size_lg2, a)) - return false; - upb_strtable_begin(&i, t); - for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) { - upb_strtable_insert3( - &new_table, - upb_strtable_iter_key(&i), - upb_strtable_iter_keylength(&i), - upb_strtable_iter_value(&i), - a); - } - upb_strtable_uninit2(t, a); - *t = new_table; - return true; -} - -bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len, - upb_value v, upb_alloc *a) { - lookupkey_t key; - upb_tabkey tabkey; - uint32_t hash; - - upb_check_alloc(&t->t, a); - - if (isfull(&t->t)) { - /* Need to resize. New table of double the size, add old elements to it. */ - if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) { - return false; - } - } - - key = strkey2(k, len); - tabkey = strcopy(key, a); - if (tabkey == 0) return false; - - hash = MurmurHash2(key.str.str, key.str.len, 0); - insert(&t->t, key, tabkey, v, hash, &strhash, &streql); - return true; -} - -bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len, - upb_value *v) { - uint32_t hash = MurmurHash2(key, len, 0); - return lookup(&t->t, strkey2(key, len), v, hash, &streql); -} - -bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len, - upb_value *val, upb_alloc *alloc) { - uint32_t hash = MurmurHash2(key, len, 0); - upb_tabkey tabkey; - if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) { - upb_free(alloc, (void*)tabkey); - return true; - } else { - return false; - } -} - -/* Iteration */ - -static const upb_tabent *str_tabent(const upb_strtable_iter *i) { - return &i->t->t.entries[i->index]; -} - -void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) { - i->t = t; - i->index = begin(&t->t); -} - -void upb_strtable_next(upb_strtable_iter *i) { - i->index = next(&i->t->t, i->index); -} - -bool upb_strtable_done(const upb_strtable_iter *i) { - return i->index >= upb_table_size(&i->t->t) || - upb_tabent_isempty(str_tabent(i)); -} - -const char *upb_strtable_iter_key(const upb_strtable_iter *i) { - UPB_ASSERT(!upb_strtable_done(i)); - return upb_tabstr(str_tabent(i)->key, NULL); -} - -size_t upb_strtable_iter_keylength(const upb_strtable_iter *i) { - uint32_t len; - UPB_ASSERT(!upb_strtable_done(i)); - upb_tabstr(str_tabent(i)->key, &len); - return len; -} - -upb_value upb_strtable_iter_value(const upb_strtable_iter *i) { - UPB_ASSERT(!upb_strtable_done(i)); - return _upb_value_val(str_tabent(i)->val.val, i->t->t.ctype); -} - -void upb_strtable_iter_setdone(upb_strtable_iter *i) { - i->index = SIZE_MAX; -} - -bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, - const upb_strtable_iter *i2) { - if (upb_strtable_done(i1) && upb_strtable_done(i2)) - return true; - return i1->t == i2->t && i1->index == i2->index; -} - - -/* upb_inttable ***************************************************************/ - -/* For inttables we use a hybrid structure where small keys are kept in an - * array and large keys are put in the hash table. */ - -static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); } - -static bool inteql(upb_tabkey k1, lookupkey_t k2) { - return k1 == k2.num; -} - -static upb_tabval *mutable_array(upb_inttable *t) { - return (upb_tabval*)t->array; -} - -static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) { - if (key < t->array_size) { - return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL; - } else { - upb_tabent *e = - findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql); - return e ? &e->val : NULL; - } -} - -static const upb_tabval *inttable_val_const(const upb_inttable *t, - uintptr_t key) { - return inttable_val((upb_inttable*)t, key); -} - -size_t upb_inttable_count(const upb_inttable *t) { - return t->t.count + t->array_count; -} - -static void check(upb_inttable *t) { - UPB_UNUSED(t); -#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG) - { - /* This check is very expensive (makes inserts/deletes O(N)). */ - size_t count = 0; - upb_inttable_iter i; - upb_inttable_begin(&i, t); - for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) { - UPB_ASSERT(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL)); - } - UPB_ASSERT(count == upb_inttable_count(t)); - } -#endif -} - -bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype, - size_t asize, int hsize_lg2, upb_alloc *a) { - size_t array_bytes; - - if (!init(&t->t, ctype, hsize_lg2, a)) return false; - /* Always make the array part at least 1 long, so that we know key 0 - * won't be in the hash part, which simplifies things. */ - t->array_size = UPB_MAX(1, asize); - t->array_count = 0; - array_bytes = t->array_size * sizeof(upb_value); - t->array = upb_malloc(a, array_bytes); - if (!t->array) { - uninit(&t->t, a); - return false; - } - memset(mutable_array(t), 0xff, array_bytes); - check(t); - return true; -} - -bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) { - return upb_inttable_sizedinit(t, ctype, 0, 4, a); -} - -void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) { - uninit(&t->t, a); - upb_free(a, mutable_array(t)); -} - -bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, - upb_alloc *a) { - upb_tabval tabval; - tabval.val = val.val; - UPB_ASSERT(upb_arrhas(tabval)); /* This will reject (uint64_t)-1. Fix this. */ - - upb_check_alloc(&t->t, a); - - if (key < t->array_size) { - UPB_ASSERT(!upb_arrhas(t->array[key])); - t->array_count++; - mutable_array(t)[key].val = val.val; - } else { - if (isfull(&t->t)) { - /* Need to resize the hash part, but we re-use the array part. */ - size_t i; - upb_table new_table; - - if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1, a)) { - return false; - } - - for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) { - const upb_tabent *e = &t->t.entries[i]; - uint32_t hash; - upb_value v; - - _upb_value_setval(&v, e->val.val, t->t.ctype); - hash = upb_inthash(e->key); - insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql); - } - - UPB_ASSERT(t->t.count == new_table.count); - - uninit(&t->t, a); - t->t = new_table; - } - insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql); - } - check(t); - return true; -} - -bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) { - const upb_tabval *table_v = inttable_val_const(t, key); - if (!table_v) return false; - if (v) _upb_value_setval(v, table_v->val, t->t.ctype); - return true; -} - -bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) { - upb_tabval *table_v = inttable_val(t, key); - if (!table_v) return false; - table_v->val = val.val; - return true; -} - -bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) { - bool success; - if (key < t->array_size) { - if (upb_arrhas(t->array[key])) { - upb_tabval empty = UPB_TABVALUE_EMPTY_INIT; - t->array_count--; - if (val) { - _upb_value_setval(val, t->array[key].val, t->t.ctype); - } - mutable_array(t)[key] = empty; - success = true; - } else { - success = false; - } - } else { - success = rm(&t->t, intkey(key), val, NULL, upb_inthash(key), &inteql); - } - check(t); - return success; -} - -bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a) { - upb_check_alloc(&t->t, a); - return upb_inttable_insert2(t, upb_inttable_count(t), val, a); -} - -upb_value upb_inttable_pop(upb_inttable *t) { - upb_value val; - bool ok = upb_inttable_remove(t, upb_inttable_count(t) - 1, &val); - UPB_ASSERT(ok); - return val; -} - -bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val, - upb_alloc *a) { - upb_check_alloc(&t->t, a); - return upb_inttable_insert2(t, (uintptr_t)key, val, a); -} - -bool upb_inttable_lookupptr(const upb_inttable *t, const void *key, - upb_value *v) { - return upb_inttable_lookup(t, (uintptr_t)key, v); -} - -bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) { - return upb_inttable_remove(t, (uintptr_t)key, val); -} - -void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) { - /* A power-of-two histogram of the table keys. */ - size_t counts[UPB_MAXARRSIZE + 1] = {0}; - - /* The max key in each bucket. */ - uintptr_t max[UPB_MAXARRSIZE + 1] = {0}; - - upb_inttable_iter i; - size_t arr_count; - int size_lg2; - upb_inttable new_t; - - upb_check_alloc(&t->t, a); - - upb_inttable_begin(&i, t); - for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { - uintptr_t key = upb_inttable_iter_key(&i); - int bucket = log2ceil(key); - max[bucket] = UPB_MAX(max[bucket], key); - counts[bucket]++; - } - - /* Find the largest power of two that satisfies the MIN_DENSITY - * definition (while actually having some keys). */ - arr_count = upb_inttable_count(t); - - for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) { - if (counts[size_lg2] == 0) { - /* We can halve again without losing any entries. */ - continue; - } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) { - break; - } - - arr_count -= counts[size_lg2]; - } - - UPB_ASSERT(arr_count <= upb_inttable_count(t)); - - { - /* Insert all elements into new, perfectly-sized table. */ - size_t arr_size = max[size_lg2] + 1; /* +1 so arr[max] will fit. */ - size_t hash_count = upb_inttable_count(t) - arr_count; - size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0; - size_t hashsize_lg2 = log2ceil(hash_size); - - upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2, a); - upb_inttable_begin(&i, t); - for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { - uintptr_t k = upb_inttable_iter_key(&i); - upb_inttable_insert2(&new_t, k, upb_inttable_iter_value(&i), a); - } - UPB_ASSERT(new_t.array_size == arr_size); - UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2); - } - upb_inttable_uninit2(t, a); - *t = new_t; -} - -/* Iteration. */ - -static const upb_tabent *int_tabent(const upb_inttable_iter *i) { - UPB_ASSERT(!i->array_part); - return &i->t->t.entries[i->index]; -} - -static upb_tabval int_arrent(const upb_inttable_iter *i) { - UPB_ASSERT(i->array_part); - return i->t->array[i->index]; -} - -void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) { - i->t = t; - i->index = -1; - i->array_part = true; - upb_inttable_next(i); -} - -void upb_inttable_next(upb_inttable_iter *iter) { - const upb_inttable *t = iter->t; - if (iter->array_part) { - while (++iter->index < t->array_size) { - if (upb_arrhas(int_arrent(iter))) { - return; - } - } - iter->array_part = false; - iter->index = begin(&t->t); - } else { - iter->index = next(&t->t, iter->index); - } -} - -bool upb_inttable_done(const upb_inttable_iter *i) { - if (i->array_part) { - return i->index >= i->t->array_size || - !upb_arrhas(int_arrent(i)); - } else { - return i->index >= upb_table_size(&i->t->t) || - upb_tabent_isempty(int_tabent(i)); - } -} - -uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) { - UPB_ASSERT(!upb_inttable_done(i)); - return i->array_part ? i->index : int_tabent(i)->key; -} - -upb_value upb_inttable_iter_value(const upb_inttable_iter *i) { - UPB_ASSERT(!upb_inttable_done(i)); - return _upb_value_val( - i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val, - i->t->t.ctype); -} - -void upb_inttable_iter_setdone(upb_inttable_iter *i) { - i->index = SIZE_MAX; - i->array_part = false; -} - -bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, - const upb_inttable_iter *i2) { - if (upb_inttable_done(i1) && upb_inttable_done(i2)) - return true; - return i1->t == i2->t && i1->index == i2->index && - i1->array_part == i2->array_part; -} - -#ifdef UPB_UNALIGNED_READS_OK -/* ----------------------------------------------------------------------------- - * MurmurHash2, by Austin Appleby (released as public domain). - * Reformatted and C99-ified by Joshua Haberman. - * Note - This code makes a few assumptions about how your machine behaves - - * 1. We can read a 4-byte value from any address without crashing - * 2. sizeof(int) == 4 (in upb this limitation is removed by using uint32_t - * And it has a few limitations - - * 1. It will not work incrementally. - * 2. It will not produce the same results on little-endian and big-endian - * machines. */ -uint32_t MurmurHash2(const void *key, size_t len, uint32_t seed) { - /* 'm' and 'r' are mixing constants generated offline. - * They're not really 'magic', they just happen to work well. */ - const uint32_t m = 0x5bd1e995; - const int32_t r = 24; - - /* Initialize the hash to a 'random' value */ - uint32_t h = seed ^ len; - - /* Mix 4 bytes at a time into the hash */ - const uint8_t * data = (const uint8_t *)key; - while(len >= 4) { - uint32_t k = *(uint32_t *)data; - - k *= m; - k ^= k >> r; - k *= m; - - h *= m; - h ^= k; - - data += 4; - len -= 4; - } - - /* Handle the last few bytes of the input array */ - switch(len) { - case 3: h ^= data[2] << 16; - case 2: h ^= data[1] << 8; - case 1: h ^= data[0]; h *= m; - }; - - /* Do a few final mixes of the hash to ensure the last few - * bytes are well-incorporated. */ - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return h; -} - -#else /* !UPB_UNALIGNED_READS_OK */ - -/* ----------------------------------------------------------------------------- - * MurmurHashAligned2, by Austin Appleby - * Same algorithm as MurmurHash2, but only does aligned reads - should be safer - * on certain platforms. - * Performance will be lower than MurmurHash2 */ - -#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; } - -uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed) { - const uint32_t m = 0x5bd1e995; - const int32_t r = 24; - const uint8_t * data = (const uint8_t *)key; - uint32_t h = seed ^ len; - uint8_t align = (uintptr_t)data & 3; - - if(align && (len >= 4)) { - /* Pre-load the temp registers */ - uint32_t t = 0, d = 0; - int32_t sl; - int32_t sr; - - switch(align) { - case 1: t |= data[2] << 16; - case 2: t |= data[1] << 8; - case 3: t |= data[0]; - } - - t <<= (8 * align); - - data += 4-align; - len -= 4-align; - - sl = 8 * (4-align); - sr = 8 * align; - - /* Mix */ - - while(len >= 4) { - uint32_t k; - - d = *(uint32_t *)data; - t = (t >> sr) | (d << sl); - - k = t; - - MIX(h,k,m); - - t = d; - - data += 4; - len -= 4; - } - - /* Handle leftover data in temp registers */ - - d = 0; - - if(len >= align) { - uint32_t k; - - switch(align) { - case 3: d |= data[2] << 16; - case 2: d |= data[1] << 8; - case 1: d |= data[0]; - } - - k = (t >> sr) | (d << sl); - MIX(h,k,m); - - data += align; - len -= align; - - /* ---------- - * Handle tail bytes */ - - switch(len) { - case 3: h ^= data[2] << 16; - case 2: h ^= data[1] << 8; - case 1: h ^= data[0]; h *= m; - }; - } else { - switch(len) { - case 3: d |= data[2] << 16; - case 2: d |= data[1] << 8; - case 1: d |= data[0]; - case 0: h ^= (t >> sr) | (d << sl); h *= m; - } - } - - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return h; - } else { - while(len >= 4) { - uint32_t k = *(uint32_t *)data; - - MIX(h,k,m); - - data += 4; - len -= 4; - } - - /* ---------- - * Handle tail bytes */ - - switch(len) { - case 3: h ^= data[2] << 16; - case 2: h ^= data[1] << 8; - case 1: h ^= data[0]; h *= m; - }; - - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return h; - } -} -#undef MIX - -#endif /* UPB_UNALIGNED_READS_OK */ - -#include -#include -#include -#include -#include -#include -#include - -bool upb_dumptostderr(void *closure, const upb_status* status) { - UPB_UNUSED(closure); - fprintf(stderr, "%s\n", upb_status_errmsg(status)); - return false; -} - -/* Guarantee null-termination and provide ellipsis truncation. - * It may be tempting to "optimize" this by initializing these final - * four bytes up-front and then being careful never to overwrite them, - * this is safer and simpler. */ -static void nullz(upb_status *status) { - const char *ellipsis = "..."; - size_t len = strlen(ellipsis); - UPB_ASSERT(sizeof(status->msg) > len); - memcpy(status->msg + sizeof(status->msg) - len, ellipsis, len); -} - - -/* upb_upberr *****************************************************************/ - -upb_errorspace upb_upberr = {"upb error"}; - -void upb_upberr_setoom(upb_status *status) { - status->error_space_ = &upb_upberr; - upb_status_seterrmsg(status, "Out of memory"); -} - - -/* upb_status *****************************************************************/ - -void upb_status_clear(upb_status *status) { - if (!status) return; - status->ok_ = true; - status->code_ = 0; - status->msg[0] = '\0'; -} - -bool upb_ok(const upb_status *status) { return status->ok_; } - -upb_errorspace *upb_status_errspace(const upb_status *status) { - return status->error_space_; -} - -int upb_status_errcode(const upb_status *status) { return status->code_; } - -const char *upb_status_errmsg(const upb_status *status) { return status->msg; } - -void upb_status_seterrmsg(upb_status *status, const char *msg) { - if (!status) return; - status->ok_ = false; - strncpy(status->msg, msg, sizeof(status->msg)); - nullz(status); -} - -void upb_status_seterrf(upb_status *status, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - upb_status_vseterrf(status, fmt, args); - va_end(args); -} - -void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) { - if (!status) return; - status->ok_ = false; - _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args); - nullz(status); -} - -void upb_status_copy(upb_status *to, const upb_status *from) { - if (!to) return; - *to = *from; -} - - -/* upb_alloc ******************************************************************/ - -static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize, - size_t size) { - UPB_UNUSED(alloc); - UPB_UNUSED(oldsize); - if (size == 0) { - free(ptr); - return NULL; - } else { - return realloc(ptr, size); - } -} - -upb_alloc upb_alloc_global = {&upb_global_allocfunc}; - - -/* upb_arena ******************************************************************/ - -/* Be conservative and choose 16 in case anyone is using SSE. */ -static const size_t maxalign = 16; - -static size_t align_up_max(size_t size) { - return ((size + maxalign - 1) / maxalign) * maxalign; -} - -typedef struct mem_block { - struct mem_block *next; - size_t size; - size_t used; - bool owned; - /* Data follows. */ -} mem_block; - -typedef struct cleanup_ent { - struct cleanup_ent *next; - upb_cleanup_func *cleanup; - void *ud; -} cleanup_ent; - -static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size, - bool owned) { - mem_block *block = ptr; - - block->next = a->block_head; - block->size = size; - block->used = align_up_max(sizeof(mem_block)); - block->owned = owned; - - a->block_head = block; - - /* TODO(haberman): ASAN poison. */ -} - - -static mem_block *upb_arena_allocblock(upb_arena *a, size_t size) { - size_t block_size = UPB_MAX(size, a->next_block_size) + sizeof(mem_block); - mem_block *block = upb_malloc(a->block_alloc, block_size); - - if (!block) { - return NULL; - } - - upb_arena_addblock(a, block, block_size, true); - a->next_block_size = UPB_MIN(block_size * 2, a->max_block_size); - - return block; -} - -static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize, - size_t size) { - upb_arena *a = (upb_arena*)alloc; /* upb_alloc is initial member. */ - mem_block *block = a->block_head; - void *ret; - - if (size == 0) { - return NULL; /* We are an arena, don't need individual frees. */ - } - - size = align_up_max(size); - - /* TODO(haberman): special-case if this is a realloc of the last alloc? */ - - if (!block || block->size - block->used < size) { - /* Slow path: have to allocate a new block. */ - block = upb_arena_allocblock(a, size); - - if (!block) { - return NULL; /* Out of memory. */ - } - } - - ret = (char*)block + block->used; - block->used += size; - - if (oldsize > 0) { - memcpy(ret, ptr, oldsize); /* Preserve existing data. */ - } - - /* TODO(haberman): ASAN unpoison. */ - - a->bytes_allocated += size; - return ret; -} - -/* Public Arena API ***********************************************************/ - -void upb_arena_init(upb_arena *a) { - a->alloc.func = &upb_arena_doalloc; - a->block_alloc = &upb_alloc_global; - a->bytes_allocated = 0; - a->next_block_size = 256; - a->max_block_size = 16384; - a->cleanup_head = NULL; - a->block_head = NULL; -} - -void upb_arena_init2(upb_arena *a, void *mem, size_t size, upb_alloc *alloc) { - upb_arena_init(a); - - if (size > sizeof(mem_block)) { - upb_arena_addblock(a, mem, size, false); - } - - if (alloc) { - a->block_alloc = alloc; - } -} - -void upb_arena_uninit(upb_arena *a) { - cleanup_ent *ent = a->cleanup_head; - mem_block *block = a->block_head; - - while (ent) { - ent->cleanup(ent->ud); - ent = ent->next; - } - - /* Must do this after running cleanup functions, because this will delete - * the memory we store our cleanup entries in! */ - while (block) { - mem_block *next = block->next; - - if (block->owned) { - upb_free(a->block_alloc, block); - } - - block = next; - } - - /* Protect against multiple-uninit. */ - a->cleanup_head = NULL; - a->block_head = NULL; -} - -bool upb_arena_addcleanup(upb_arena *a, upb_cleanup_func *func, void *ud) { - cleanup_ent *ent = upb_malloc(&a->alloc, sizeof(cleanup_ent)); - if (!ent) { - return false; /* Out of memory. */ - } - - ent->cleanup = func; - ent->ud = ud; - ent->next = a->cleanup_head; - a->cleanup_head = ent; - - return true; -} - -size_t upb_arena_bytesallocated(const upb_arena *a) { - return a->bytes_allocated; -} - - -/* Standard error functions ***************************************************/ - -static bool default_err(void *ud, const upb_status *status) { - UPB_UNUSED(ud); - UPB_UNUSED(status); - return false; -} - -static bool write_err_to(void *ud, const upb_status *status) { - upb_status *copy_to = ud; - upb_status_copy(copy_to, status); - return false; -} - - -/* upb_env ********************************************************************/ - -void upb_env_initonly(upb_env *e) { - e->ok_ = true; - e->error_func_ = &default_err; - e->error_ud_ = NULL; -} - -void upb_env_init(upb_env *e) { - upb_arena_init(&e->arena_); - upb_env_initonly(e); -} - -void upb_env_init2(upb_env *e, void *mem, size_t n, upb_alloc *alloc) { - upb_arena_init2(&e->arena_, mem, n, alloc); - upb_env_initonly(e); -} - -void upb_env_uninit(upb_env *e) { - upb_arena_uninit(&e->arena_); -} - -void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud) { - e->error_func_ = func; - e->error_ud_ = ud; -} - -void upb_env_reporterrorsto(upb_env *e, upb_status *s) { - e->error_func_ = &write_err_to; - e->error_ud_ = s; -} - -bool upb_env_reporterror(upb_env *e, const upb_status *status) { - e->ok_ = false; - return e->error_func_(e->error_ud_, status); -} - -void *upb_env_malloc(upb_env *e, size_t size) { - return upb_malloc(&e->arena_.alloc, size); -} - -void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size) { - return upb_realloc(&e->arena_.alloc, ptr, oldsize, size); -} - -void upb_env_free(upb_env *e, void *ptr) { - upb_free(&e->arena_.alloc, ptr); -} - -bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud) { - return upb_arena_addcleanup(&e->arena_, func, ud); -} - -size_t upb_env_bytesallocated(const upb_env *e) { - return upb_arena_bytesallocated(&e->arena_); -} -/* This file was generated by upbc (the upb compiler) from the input - * file: - * - * upb/descriptor/descriptor.proto - * - * Do not edit -- your changes will be discarded when the file is - * regenerated. */ - - -static const upb_msgdef msgs[22]; -static const upb_fielddef fields[107]; -static const upb_enumdef enums[5]; -static const upb_tabent strentries[236]; -static const upb_tabent intentries[18]; -static const upb_tabval arrays[187]; - -#ifdef UPB_DEBUG_REFS -static upb_inttable reftables[268]; -#endif - -static const upb_msgdef msgs[22] = { - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", 40, 8, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[0], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[0]), false, UPB_SYNTAX_PROTO2, &reftables[0], &reftables[1]), - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", 4, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[11], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[16]), false, UPB_SYNTAX_PROTO2, &reftables[2], &reftables[3]), - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ReservedRange", 4, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[14], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[20]), false, UPB_SYNTAX_PROTO2, &reftables[4], &reftables[5]), - UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[17], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[24]), false, UPB_SYNTAX_PROTO2, &reftables[6], &reftables[7]), - UPB_MSGDEF_INIT("google.protobuf.EnumOptions", 8, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[0], &arrays[21], 4, 2), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[28]), false, UPB_SYNTAX_PROTO2, &reftables[8], &reftables[9]), - UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", 8, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[25], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[32]), false, UPB_SYNTAX_PROTO2, &reftables[10], &reftables[11]), - UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", 7, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[2], &arrays[29], 2, 1), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[36]), false, UPB_SYNTAX_PROTO2, &reftables[12], &reftables[13]), - UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", 23, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[31], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[40]), false, UPB_SYNTAX_PROTO2, &reftables[14], &reftables[15]), - UPB_MSGDEF_INIT("google.protobuf.FieldOptions", 12, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[4], &arrays[42], 11, 6), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[56]), false, UPB_SYNTAX_PROTO2, &reftables[16], &reftables[17]), - UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", 42, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[53], 13, 12), UPB_STRTABLE_INIT(12, 15, UPB_CTYPE_PTR, 4, &strentries[72]), false, UPB_SYNTAX_PROTO2, &reftables[18], &reftables[19]), - UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[66], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[88]), false, UPB_SYNTAX_PROTO2, &reftables[20], &reftables[21]), - UPB_MSGDEF_INIT("google.protobuf.FileOptions", 37, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 42, 17), UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_PTR, 5, &strentries[92]), false, UPB_SYNTAX_PROTO2, &reftables[22], &reftables[23]), - UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 10, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[110], 8, 4), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[124]), false, UPB_SYNTAX_PROTO2, &reftables[24], &reftables[25]), - UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 15, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[118], 7, 6), UPB_STRTABLE_INIT(6, 7, UPB_CTYPE_PTR, 3, &strentries[132]), false, UPB_SYNTAX_PROTO2, &reftables[26], &reftables[27]), - UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[10], &arrays[125], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[140]), false, UPB_SYNTAX_PROTO2, &reftables[28], &reftables[29]), - UPB_MSGDEF_INIT("google.protobuf.OneofDescriptorProto", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[126], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[144]), false, UPB_SYNTAX_PROTO2, &reftables[30], &reftables[31]), - UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[128], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[148]), false, UPB_SYNTAX_PROTO2, &reftables[32], &reftables[33]), - UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[14], &arrays[132], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[152]), false, UPB_SYNTAX_PROTO2, &reftables[34], &reftables[35]), - UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[133], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[156]), false, UPB_SYNTAX_PROTO2, &reftables[36], &reftables[37]), - UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 19, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[135], 7, 5), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[160]), false, UPB_SYNTAX_PROTO2, &reftables[38], &reftables[39]), - UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 18, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[142], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[168]), false, UPB_SYNTAX_PROTO2, &reftables[40], &reftables[41]), - UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[151], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[184]), false, UPB_SYNTAX_PROTO2, &reftables[42], &reftables[43]), -}; - -static const upb_fielddef fields[107] = { - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "aggregate_value", 8, &msgs[20], NULL, 15, 6, {0},&reftables[44], &reftables[45]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "allow_alias", 2, &msgs[4], NULL, 6, 1, {0},&reftables[46], &reftables[47]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_enable_arenas", 31, &msgs[11], NULL, 23, 12, {0},&reftables[48], &reftables[49]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_generic_services", 16, &msgs[11], NULL, 17, 6, {0},&reftables[50], &reftables[51]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "client_streaming", 5, &msgs[13], NULL, 13, 4, {0},&reftables[52], &reftables[53]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "csharp_namespace", 37, &msgs[11], NULL, 27, 14, {0},&reftables[54], &reftables[55]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "ctype", 1, &msgs[8], (const upb_def*)(&enums[2]), 6, 1, {0},&reftables[56], &reftables[57]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "default_value", 7, &msgs[7], NULL, 16, 7, {0},&reftables[58], &reftables[59]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "dependency", 3, &msgs[9], NULL, 30, 8, {0},&reftables[60], &reftables[61]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[8], NULL, 8, 3, {0},&reftables[62], &reftables[63]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[14], NULL, 6, 1, {0},&reftables[64], &reftables[65]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[12], NULL, 8, 3, {0},&reftables[66], &reftables[67]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 23, &msgs[11], NULL, 21, 10, {0},&reftables[68], &reftables[69]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 1, &msgs[6], NULL, 6, 1, {0},&reftables[70], &reftables[71]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[4], NULL, 7, 2, {0},&reftables[72], &reftables[73]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[17], NULL, 6, 1, {0},&reftables[74], &reftables[75]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, false, false, false, "double_value", 6, &msgs[20], NULL, 11, 4, {0},&reftables[76], &reftables[77]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[2], NULL, 3, 1, {0},&reftables[78], &reftables[79]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[1], NULL, 3, 1, {0},&reftables[80], &reftables[81]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 5, &msgs[9], (const upb_def*)(&msgs[3]), 13, 1, {0},&reftables[82], &reftables[83]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 4, &msgs[0], (const upb_def*)(&msgs[3]), 18, 2, {0},&reftables[84], &reftables[85]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "extendee", 2, &msgs[7], NULL, 7, 2, {0},&reftables[86], &reftables[87]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 6, &msgs[0], (const upb_def*)(&msgs[7]), 24, 4, {0},&reftables[88], &reftables[89]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 7, &msgs[9], (const upb_def*)(&msgs[7]), 19, 3, {0},&reftables[90], &reftables[91]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension_range", 5, &msgs[0], (const upb_def*)(&msgs[1]), 21, 3, {0},&reftables[92], &reftables[93]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "field", 2, &msgs[0], (const upb_def*)(&msgs[7]), 12, 0, {0},&reftables[94], &reftables[95]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "file", 1, &msgs[10], (const upb_def*)(&msgs[9]), 5, 0, {0},&reftables[96], &reftables[97]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "go_package", 11, &msgs[11], NULL, 14, 5, {0},&reftables[98], &reftables[99]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "identifier_value", 3, &msgs[20], NULL, 6, 1, {0},&reftables[100], &reftables[101]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "input_type", 2, &msgs[13], NULL, 7, 2, {0},&reftables[102], &reftables[103]), - UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, false, false, false, "is_extension", 2, &msgs[21], NULL, 5, 1, {0},&reftables[104], &reftables[105]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generate_equals_and_hash", 20, &msgs[11], NULL, 20, 9, {0},&reftables[106], &reftables[107]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generic_services", 17, &msgs[11], NULL, 18, 7, {0},&reftables[108], &reftables[109]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_multiple_files", 10, &msgs[11], NULL, 13, 4, {0},&reftables[110], &reftables[111]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_outer_classname", 8, &msgs[11], NULL, 9, 2, {0},&reftables[112], &reftables[113]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_package", 1, &msgs[11], NULL, 6, 1, {0},&reftables[114], &reftables[115]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_string_check_utf8", 27, &msgs[11], NULL, 22, 11, {0},&reftables[116], &reftables[117]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "javanano_use_deprecated_package", 38, &msgs[11], NULL, 30, 15, {0},&reftables[118], &reftables[119]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "json_name", 10, &msgs[7], NULL, 20, 9, {0},&reftables[120], &reftables[121]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "jstype", 6, &msgs[8], (const upb_def*)(&enums[3]), 10, 5, {0},&reftables[122], &reftables[123]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "label", 4, &msgs[7], (const upb_def*)(&enums[0]), 11, 4, {0},&reftables[124], &reftables[125]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "lazy", 5, &msgs[8], NULL, 9, 4, {0},&reftables[126], &reftables[127]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "leading_comments", 3, &msgs[19], NULL, 8, 2, {0},&reftables[128], &reftables[129]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "leading_detached_comments", 6, &msgs[19], NULL, 16, 4, {0},&reftables[130], &reftables[131]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "location", 1, &msgs[18], (const upb_def*)(&msgs[19]), 5, 0, {0},&reftables[132], &reftables[133]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "map_entry", 7, &msgs[12], NULL, 9, 4, {0},&reftables[134], &reftables[135]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "message_set_wire_format", 1, &msgs[12], NULL, 6, 1, {0},&reftables[136], &reftables[137]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "message_type", 4, &msgs[9], (const upb_def*)(&msgs[0]), 10, 0, {0},&reftables[138], &reftables[139]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "method", 2, &msgs[16], (const upb_def*)(&msgs[13]), 6, 0, {0},&reftables[140], &reftables[141]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "name", 2, &msgs[20], (const upb_def*)(&msgs[21]), 5, 0, {0},&reftables[142], &reftables[143]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[5], NULL, 4, 1, {0},&reftables[144], &reftables[145]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[9], NULL, 22, 6, {0},&reftables[146], &reftables[147]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[3], NULL, 8, 2, {0},&reftables[148], &reftables[149]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[16], NULL, 8, 2, {0},&reftables[150], &reftables[151]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[15], NULL, 2, 0, {0},&reftables[152], &reftables[153]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[13], NULL, 4, 1, {0},&reftables[154], &reftables[155]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[7], NULL, 4, 1, {0},&reftables[156], &reftables[157]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 32, 8, {0},&reftables[158], &reftables[159]), - UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, false, false, false, "name_part", 1, &msgs[21], NULL, 2, 0, {0},&reftables[160], &reftables[161]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, false, false, false, "negative_int_value", 5, &msgs[20], NULL, 10, 3, {0},&reftables[162], &reftables[163]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "nested_type", 3, &msgs[0], (const upb_def*)(&msgs[0]), 15, 1, {0},&reftables[164], &reftables[165]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "no_standard_descriptor_accessor", 2, &msgs[12], NULL, 7, 2, {0},&reftables[166], &reftables[167]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 3, &msgs[7], NULL, 10, 3, {0},&reftables[168], &reftables[169]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 2, &msgs[5], NULL, 7, 2, {0},&reftables[170], &reftables[171]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "objc_class_prefix", 36, &msgs[11], NULL, 24, 13, {0},&reftables[172], &reftables[173]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "oneof_decl", 8, &msgs[0], (const upb_def*)(&msgs[15]), 28, 6, {0},&reftables[174], &reftables[175]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "oneof_index", 9, &msgs[7], NULL, 19, 8, {0},&reftables[176], &reftables[177]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "optimize_for", 9, &msgs[11], (const upb_def*)(&enums[4]), 12, 3, {0},&reftables[178], &reftables[179]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 7, &msgs[0], (const upb_def*)(&msgs[12]), 25, 5, {0},&reftables[180], &reftables[181]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[9], (const upb_def*)(&msgs[11]), 20, 4, {0},&reftables[182], &reftables[183]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[7], (const upb_def*)(&msgs[8]), 3, 0, {0},&reftables[184], &reftables[185]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 4, &msgs[13], (const upb_def*)(&msgs[14]), 3, 0, {0},&reftables[186], &reftables[187]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[16], (const upb_def*)(&msgs[17]), 7, 1, {0},&reftables[188], &reftables[189]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[3], (const upb_def*)(&msgs[4]), 7, 1, {0},&reftables[190], &reftables[191]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[5], (const upb_def*)(&msgs[6]), 3, 0, {0},&reftables[192], &reftables[193]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "output_type", 3, &msgs[13], NULL, 10, 3, {0},&reftables[194], &reftables[195]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "package", 2, &msgs[9], NULL, 25, 7, {0},&reftables[196], &reftables[197]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "packed", 2, &msgs[8], NULL, 7, 2, {0},&reftables[198], &reftables[199]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "path", 1, &msgs[19], NULL, 4, 0, {0},&reftables[200], &reftables[201]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "php_class_prefix", 40, &msgs[11], NULL, 31, 16, {0},&reftables[202], &reftables[203]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "php_namespace", 41, &msgs[11], NULL, 34, 17, {0},&reftables[204], &reftables[205]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, false, "positive_int_value", 4, &msgs[20], NULL, 9, 2, {0},&reftables[206], &reftables[207]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "public_dependency", 10, &msgs[9], NULL, 35, 9, {0},&reftables[208], &reftables[209]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "py_generic_services", 18, &msgs[11], NULL, 19, 8, {0},&reftables[210], &reftables[211]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "reserved_name", 10, &msgs[0], NULL, 37, 9, {0},&reftables[212], &reftables[213]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "reserved_range", 9, &msgs[0], (const upb_def*)(&msgs[2]), 31, 7, {0},&reftables[214], &reftables[215]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "server_streaming", 6, &msgs[13], NULL, 14, 5, {0},&reftables[216], &reftables[217]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "service", 6, &msgs[9], (const upb_def*)(&msgs[16]), 16, 2, {0},&reftables[218], &reftables[219]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "source_code_info", 9, &msgs[9], (const upb_def*)(&msgs[18]), 21, 5, {0},&reftables[220], &reftables[221]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "span", 2, &msgs[19], NULL, 7, 1, {0},&reftables[222], &reftables[223]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[2], NULL, 2, 0, {0},&reftables[224], &reftables[225]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[1], NULL, 2, 0, {0},&reftables[226], &reftables[227]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[20], NULL, 12, 5, {0},&reftables[228], &reftables[229]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "syntax", 12, &msgs[9], NULL, 39, 11, {0},&reftables[230], &reftables[231]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[19], NULL, 11, 3, {0},&reftables[232], &reftables[233]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "type", 5, &msgs[7], (const upb_def*)(&enums[1]), 12, 5, {0},&reftables[234], &reftables[235]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[7], NULL, 13, 6, {0},&reftables[236], &reftables[237]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[12], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[238], &reftables[239]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[17], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[240], &reftables[241]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[11], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[242], &reftables[243]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[14], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[244], &reftables[245]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[8], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[246], &reftables[247]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[6], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[248], &reftables[249]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[4], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[250], &reftables[251]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "value", 2, &msgs[3], (const upb_def*)(&msgs[5]), 6, 0, {0},&reftables[252], &reftables[253]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[8], NULL, 11, 6, {0},&reftables[254], &reftables[255]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "weak_dependency", 11, &msgs[9], NULL, 38, 10, {0},&reftables[256], &reftables[257]), -}; - -static const upb_enumdef enums[5] = { - UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[188]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[154], 4, 3), 0, &reftables[258], &reftables[259]), - UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_INT32, 5, &strentries[192]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[158], 19, 18), 0, &reftables[260], &reftables[261]), - UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[224]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[177], 3, 3), 0, &reftables[262], &reftables[263]), - UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.JSType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[228]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[180], 3, 3), 0, &reftables[264], &reftables[265]), - UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[232]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[183], 4, 3), 0, &reftables[266], &reftables[267]), -}; - -static const upb_tabent strentries[236] = { - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[22]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "reserved_name"), UPB_TABVALUE_PTR_INIT(&fields[84]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[57]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "field"), UPB_TABVALUE_PTR_INIT(&fields[25]), &strentries[12]}, - {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "extension_range"), UPB_TABVALUE_PTR_INIT(&fields[24]), &strentries[14]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "nested_type"), UPB_TABVALUE_PTR_INIT(&fields[60]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "reserved_range"), UPB_TABVALUE_PTR_INIT(&fields[85]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[68]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "oneof_decl"), UPB_TABVALUE_PTR_INIT(&fields[65]), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[20]), &strentries[13]}, - {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[91]), NULL}, - {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[18]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[90]), NULL}, - {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[17]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "value"), UPB_TABVALUE_PTR_INIT(&fields[104]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[52]), &strentries[26]}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "allow_alias"), UPB_TABVALUE_PTR_INIT(&fields[1]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[63]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[50]), &strentries[34]}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[102]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[13]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "oneof_index"), UPB_TABVALUE_PTR_INIT(&fields[66]), NULL}, - {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "label"), UPB_TABVALUE_PTR_INIT(&fields[40]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[56]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[62]), &strentries[53]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "extendee"), UPB_TABVALUE_PTR_INIT(&fields[21]), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "type_name"), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "json_name"), UPB_TABVALUE_PTR_INIT(&fields[38]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "type"), UPB_TABVALUE_PTR_INIT(&fields[95]), &strentries[50]}, - {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "default_value"), UPB_TABVALUE_PTR_INIT(&fields[7]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[70]), NULL}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "weak"), UPB_TABVALUE_PTR_INIT(&fields[105]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "packed"), UPB_TABVALUE_PTR_INIT(&fields[77]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "lazy"), UPB_TABVALUE_PTR_INIT(&fields[41]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "ctype"), UPB_TABVALUE_PTR_INIT(&fields[6]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "jstype"), UPB_TABVALUE_PTR_INIT(&fields[39]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[9]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[23]), NULL}, - {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "weak_dependency"), UPB_TABVALUE_PTR_INIT(&fields[106]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[51]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "service"), UPB_TABVALUE_PTR_INIT(&fields[87]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "source_code_info"), UPB_TABVALUE_PTR_INIT(&fields[88]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "syntax"), UPB_TABVALUE_PTR_INIT(&fields[93]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "dependency"), UPB_TABVALUE_PTR_INIT(&fields[8]), NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "message_type"), UPB_TABVALUE_PTR_INIT(&fields[47]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "package"), UPB_TABVALUE_PTR_INIT(&fields[76]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[69]), &strentries[86]}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[19]), NULL}, - {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "public_dependency"), UPB_TABVALUE_PTR_INIT(&fields[82]), &strentries[85]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "file"), UPB_TABVALUE_PTR_INIT(&fields[26]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "cc_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[3]), NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "csharp_namespace"), UPB_TABVALUE_PTR_INIT(&fields[5]), &strentries[116]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "go_package"), UPB_TABVALUE_PTR_INIT(&fields[27]), NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "java_package"), UPB_TABVALUE_PTR_INIT(&fields[35]), &strentries[120]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "java_outer_classname"), UPB_TABVALUE_PTR_INIT(&fields[34]), NULL}, - {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "php_namespace"), UPB_TABVALUE_PTR_INIT(&fields[80]), &strentries[113]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "java_multiple_files"), UPB_TABVALUE_PTR_INIT(&fields[33]), &strentries[117]}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL}, - {UPB_TABKEY_STR("\025", "\000", "\000", "\000", "java_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[32]), &strentries[118]}, - {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "java_generate_equals_and_hash"), UPB_TABVALUE_PTR_INIT(&fields[31]), NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "php_class_prefix"), UPB_TABVALUE_PTR_INIT(&fields[79]), NULL}, - {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "javanano_use_deprecated_package"), UPB_TABVALUE_PTR_INIT(&fields[37]), &strentries[123]}, - {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "py_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[83]), NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "optimize_for"), UPB_TABVALUE_PTR_INIT(&fields[67]), NULL}, - {UPB_TABKEY_STR("\026", "\000", "\000", "\000", "java_string_check_utf8"), UPB_TABVALUE_PTR_INIT(&fields[36]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[12]), &strentries[119]}, - {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "objc_class_prefix"), UPB_TABVALUE_PTR_INIT(&fields[64]), NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "cc_enable_arenas"), UPB_TABVALUE_PTR_INIT(&fields[2]), NULL}, - {UPB_TABKEY_STR("\027", "\000", "\000", "\000", "message_set_wire_format"), UPB_TABVALUE_PTR_INIT(&fields[46]), &strentries[128]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "map_entry"), UPB_TABVALUE_PTR_INIT(&fields[45]), NULL}, - {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "no_standard_descriptor_accessor"), UPB_TABVALUE_PTR_INIT(&fields[61]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "client_streaming"), UPB_TABVALUE_PTR_INIT(&fields[4]), NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "server_streaming"), UPB_TABVALUE_PTR_INIT(&fields[86]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[55]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "input_type"), UPB_TABVALUE_PTR_INIT(&fields[29]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "output_type"), UPB_TABVALUE_PTR_INIT(&fields[75]), NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[54]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[72]), &strentries[150]}, - {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "method"), UPB_TABVALUE_PTR_INIT(&fields[48]), NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[53]), &strentries[149]}, - {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "location"), UPB_TABVALUE_PTR_INIT(&fields[44]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "span"), UPB_TABVALUE_PTR_INIT(&fields[89]), &strentries[167]}, - {UPB_TABKEY_STR("\031", "\000", "\000", "\000", "leading_detached_comments"), UPB_TABVALUE_PTR_INIT(&fields[43]), &strentries[165]}, - {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "trailing_comments"), UPB_TABVALUE_PTR_INIT(&fields[94]), NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "leading_comments"), UPB_TABVALUE_PTR_INIT(&fields[42]), &strentries[164]}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "path"), UPB_TABVALUE_PTR_INIT(&fields[78]), NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "double_value"), UPB_TABVALUE_PTR_INIT(&fields[16]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[49]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "negative_int_value"), UPB_TABVALUE_PTR_INIT(&fields[59]), NULL}, - {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "aggregate_value"), UPB_TABVALUE_PTR_INIT(&fields[0]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "positive_int_value"), UPB_TABVALUE_PTR_INIT(&fields[81]), NULL}, - {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "identifier_value"), UPB_TABVALUE_PTR_INIT(&fields[28]), NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "string_value"), UPB_TABVALUE_PTR_INIT(&fields[92]), &strentries[182]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "is_extension"), UPB_TABVALUE_PTR_INIT(&fields[30]), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "name_part"), UPB_TABVALUE_PTR_INIT(&fields[58]), NULL}, - {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REQUIRED"), UPB_TABVALUE_INT_INIT(2), &strentries[190]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REPEATED"), UPB_TABVALUE_INT_INIT(3), NULL}, - {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_OPTIONAL"), UPB_TABVALUE_INT_INIT(1), NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED64"), UPB_TABVALUE_INT_INIT(6), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_STRING"), UPB_TABVALUE_INT_INIT(9), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_FLOAT"), UPB_TABVALUE_INT_INIT(2), &strentries[221]}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_DOUBLE"), UPB_TABVALUE_INT_INIT(1), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT32"), UPB_TABVALUE_INT_INIT(5), NULL}, - {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED32"), UPB_TABVALUE_INT_INIT(15), NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED32"), UPB_TABVALUE_INT_INIT(7), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_MESSAGE"), UPB_TABVALUE_INT_INIT(11), &strentries[222]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT64"), UPB_TABVALUE_INT_INIT(3), &strentries[219]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_ENUM"), UPB_TABVALUE_INT_INIT(14), NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT32"), UPB_TABVALUE_INT_INIT(13), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT64"), UPB_TABVALUE_INT_INIT(4), &strentries[218]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED64"), UPB_TABVALUE_INT_INIT(16), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_BYTES"), UPB_TABVALUE_INT_INIT(12), NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT64"), UPB_TABVALUE_INT_INIT(18), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_BOOL"), UPB_TABVALUE_INT_INIT(8), NULL}, - {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_GROUP"), UPB_TABVALUE_INT_INIT(10), NULL}, - {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT32"), UPB_TABVALUE_INT_INIT(17), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "CORD"), UPB_TABVALUE_INT_INIT(1), NULL}, - {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "STRING"), UPB_TABVALUE_INT_INIT(0), &strentries[225]}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "STRING_PIECE"), UPB_TABVALUE_INT_INIT(2), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_NORMAL"), UPB_TABVALUE_INT_INIT(0), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_NUMBER"), UPB_TABVALUE_INT_INIT(2), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_STRING"), UPB_TABVALUE_INT_INIT(1), NULL}, - {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "CODE_SIZE"), UPB_TABVALUE_INT_INIT(2), NULL}, - {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "SPEED"), UPB_TABVALUE_INT_INIT(1), &strentries[235]}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "LITE_RUNTIME"), UPB_TABVALUE_INT_INIT(3), NULL}, -}; - -static const upb_tabent intentries[18] = { - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[102]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL}, - {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL}, - {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL}, -}; - -static const upb_tabval arrays[187] = { - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[57]), - UPB_TABVALUE_PTR_INIT(&fields[25]), - UPB_TABVALUE_PTR_INIT(&fields[60]), - UPB_TABVALUE_PTR_INIT(&fields[20]), - UPB_TABVALUE_PTR_INIT(&fields[24]), - UPB_TABVALUE_PTR_INIT(&fields[22]), - UPB_TABVALUE_PTR_INIT(&fields[68]), - UPB_TABVALUE_PTR_INIT(&fields[65]), - UPB_TABVALUE_PTR_INIT(&fields[85]), - UPB_TABVALUE_PTR_INIT(&fields[84]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[91]), - UPB_TABVALUE_PTR_INIT(&fields[18]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[90]), - UPB_TABVALUE_PTR_INIT(&fields[17]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[52]), - UPB_TABVALUE_PTR_INIT(&fields[104]), - UPB_TABVALUE_PTR_INIT(&fields[73]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[1]), - UPB_TABVALUE_PTR_INIT(&fields[14]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[50]), - UPB_TABVALUE_PTR_INIT(&fields[63]), - UPB_TABVALUE_PTR_INIT(&fields[74]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[13]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[56]), - UPB_TABVALUE_PTR_INIT(&fields[21]), - UPB_TABVALUE_PTR_INIT(&fields[62]), - UPB_TABVALUE_PTR_INIT(&fields[40]), - UPB_TABVALUE_PTR_INIT(&fields[95]), - UPB_TABVALUE_PTR_INIT(&fields[96]), - UPB_TABVALUE_PTR_INIT(&fields[7]), - UPB_TABVALUE_PTR_INIT(&fields[70]), - UPB_TABVALUE_PTR_INIT(&fields[66]), - UPB_TABVALUE_PTR_INIT(&fields[38]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[6]), - UPB_TABVALUE_PTR_INIT(&fields[77]), - UPB_TABVALUE_PTR_INIT(&fields[9]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[41]), - UPB_TABVALUE_PTR_INIT(&fields[39]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[105]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[51]), - UPB_TABVALUE_PTR_INIT(&fields[76]), - UPB_TABVALUE_PTR_INIT(&fields[8]), - UPB_TABVALUE_PTR_INIT(&fields[47]), - UPB_TABVALUE_PTR_INIT(&fields[19]), - UPB_TABVALUE_PTR_INIT(&fields[87]), - UPB_TABVALUE_PTR_INIT(&fields[23]), - UPB_TABVALUE_PTR_INIT(&fields[69]), - UPB_TABVALUE_PTR_INIT(&fields[88]), - UPB_TABVALUE_PTR_INIT(&fields[82]), - UPB_TABVALUE_PTR_INIT(&fields[106]), - UPB_TABVALUE_PTR_INIT(&fields[93]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[26]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[35]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[34]), - UPB_TABVALUE_PTR_INIT(&fields[67]), - UPB_TABVALUE_PTR_INIT(&fields[33]), - UPB_TABVALUE_PTR_INIT(&fields[27]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[3]), - UPB_TABVALUE_PTR_INIT(&fields[32]), - UPB_TABVALUE_PTR_INIT(&fields[83]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[31]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[12]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[36]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[2]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[64]), - UPB_TABVALUE_PTR_INIT(&fields[5]), - UPB_TABVALUE_PTR_INIT(&fields[37]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[79]), - UPB_TABVALUE_PTR_INIT(&fields[80]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[46]), - UPB_TABVALUE_PTR_INIT(&fields[61]), - UPB_TABVALUE_PTR_INIT(&fields[11]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[45]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[55]), - UPB_TABVALUE_PTR_INIT(&fields[29]), - UPB_TABVALUE_PTR_INIT(&fields[75]), - UPB_TABVALUE_PTR_INIT(&fields[71]), - UPB_TABVALUE_PTR_INIT(&fields[4]), - UPB_TABVALUE_PTR_INIT(&fields[86]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[54]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[53]), - UPB_TABVALUE_PTR_INIT(&fields[48]), - UPB_TABVALUE_PTR_INIT(&fields[72]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[44]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[78]), - UPB_TABVALUE_PTR_INIT(&fields[89]), - UPB_TABVALUE_PTR_INIT(&fields[42]), - UPB_TABVALUE_PTR_INIT(&fields[94]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[43]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[49]), - UPB_TABVALUE_PTR_INIT(&fields[28]), - UPB_TABVALUE_PTR_INIT(&fields[81]), - UPB_TABVALUE_PTR_INIT(&fields[59]), - UPB_TABVALUE_PTR_INIT(&fields[16]), - UPB_TABVALUE_PTR_INIT(&fields[92]), - UPB_TABVALUE_PTR_INIT(&fields[0]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT(&fields[58]), - UPB_TABVALUE_PTR_INIT(&fields[30]), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT("LABEL_OPTIONAL"), - UPB_TABVALUE_PTR_INIT("LABEL_REQUIRED"), - UPB_TABVALUE_PTR_INIT("LABEL_REPEATED"), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT("TYPE_DOUBLE"), - UPB_TABVALUE_PTR_INIT("TYPE_FLOAT"), - UPB_TABVALUE_PTR_INIT("TYPE_INT64"), - UPB_TABVALUE_PTR_INIT("TYPE_UINT64"), - UPB_TABVALUE_PTR_INIT("TYPE_INT32"), - UPB_TABVALUE_PTR_INIT("TYPE_FIXED64"), - UPB_TABVALUE_PTR_INIT("TYPE_FIXED32"), - UPB_TABVALUE_PTR_INIT("TYPE_BOOL"), - UPB_TABVALUE_PTR_INIT("TYPE_STRING"), - UPB_TABVALUE_PTR_INIT("TYPE_GROUP"), - UPB_TABVALUE_PTR_INIT("TYPE_MESSAGE"), - UPB_TABVALUE_PTR_INIT("TYPE_BYTES"), - UPB_TABVALUE_PTR_INIT("TYPE_UINT32"), - UPB_TABVALUE_PTR_INIT("TYPE_ENUM"), - UPB_TABVALUE_PTR_INIT("TYPE_SFIXED32"), - UPB_TABVALUE_PTR_INIT("TYPE_SFIXED64"), - UPB_TABVALUE_PTR_INIT("TYPE_SINT32"), - UPB_TABVALUE_PTR_INIT("TYPE_SINT64"), - UPB_TABVALUE_PTR_INIT("STRING"), - UPB_TABVALUE_PTR_INIT("CORD"), - UPB_TABVALUE_PTR_INIT("STRING_PIECE"), - UPB_TABVALUE_PTR_INIT("JS_NORMAL"), - UPB_TABVALUE_PTR_INIT("JS_STRING"), - UPB_TABVALUE_PTR_INIT("JS_NUMBER"), - UPB_TABVALUE_EMPTY_INIT, - UPB_TABVALUE_PTR_INIT("SPEED"), - UPB_TABVALUE_PTR_INIT("CODE_SIZE"), - UPB_TABVALUE_PTR_INIT("LITE_RUNTIME"), -}; - -#ifdef UPB_DEBUG_REFS -static upb_inttable reftables[268] = { - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), - UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), -}; -#endif - -static const upb_msgdef *refm(const upb_msgdef *m, const void *owner) { - upb_msgdef_ref(m, owner); - return m; -} - -static const upb_enumdef *refe(const upb_enumdef *e, const void *owner) { - upb_enumdef_ref(e, owner); - return e; -} - -/* Public API. */ -const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_get(const void *owner) { return refm(&msgs[0], owner); } -const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(const void *owner) { return refm(&msgs[1], owner); } -const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(const void *owner) { return refm(&msgs[2], owner); } -const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto_get(const void *owner) { return refm(&msgs[3], owner); } -const upb_msgdef *upbdefs_google_protobuf_EnumOptions_get(const void *owner) { return refm(&msgs[4], owner); } -const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto_get(const void *owner) { return refm(&msgs[5], owner); } -const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions_get(const void *owner) { return refm(&msgs[6], owner); } -const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto_get(const void *owner) { return refm(&msgs[7], owner); } -const upb_msgdef *upbdefs_google_protobuf_FieldOptions_get(const void *owner) { return refm(&msgs[8], owner); } -const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto_get(const void *owner) { return refm(&msgs[9], owner); } -const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet_get(const void *owner) { return refm(&msgs[10], owner); } -const upb_msgdef *upbdefs_google_protobuf_FileOptions_get(const void *owner) { return refm(&msgs[11], owner); } -const upb_msgdef *upbdefs_google_protobuf_MessageOptions_get(const void *owner) { return refm(&msgs[12], owner); } -const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto_get(const void *owner) { return refm(&msgs[13], owner); } -const upb_msgdef *upbdefs_google_protobuf_MethodOptions_get(const void *owner) { return refm(&msgs[14], owner); } -const upb_msgdef *upbdefs_google_protobuf_OneofDescriptorProto_get(const void *owner) { return refm(&msgs[15], owner); } -const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto_get(const void *owner) { return refm(&msgs[16], owner); } -const upb_msgdef *upbdefs_google_protobuf_ServiceOptions_get(const void *owner) { return refm(&msgs[17], owner); } -const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_get(const void *owner) { return refm(&msgs[18], owner); } -const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location_get(const void *owner) { return refm(&msgs[19], owner); } -const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_get(const void *owner) { return refm(&msgs[20], owner); } -const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart_get(const void *owner) { return refm(&msgs[21], owner); } - -const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label_get(const void *owner) { return refe(&enums[0], owner); } -const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type_get(const void *owner) { return refe(&enums[1], owner); } -const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType_get(const void *owner) { return refe(&enums[2], owner); } -const upb_enumdef *upbdefs_google_protobuf_FieldOptions_JSType_get(const void *owner) { return refe(&enums[3], owner); } -const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode_get(const void *owner) { return refe(&enums[4], owner); } -/* -** XXX: The routines in this file that consume a string do not currently -** support having the string span buffers. In the future, as upb_sink and -** its buffering/sharing functionality evolve there should be an easy and -** idiomatic way of correctly handling this case. For now, we accept this -** limitation since we currently only parse descriptors from single strings. -*/ - - -#include -#include -#include - -/* Compares a NULL-terminated string with a non-NULL-terminated string. */ -static bool upb_streq(const char *str, const char *buf, size_t n) { - return strlen(str) == n && memcmp(str, buf, n) == 0; -} - -/* We keep a stack of all the messages scopes we are currently in, as well as - * the top-level file scope. This is necessary to correctly qualify the - * definitions that are contained inside. "name" tracks the name of the - * message or package (a bare name -- not qualified by any enclosing scopes). */ -typedef struct { - char *name; - /* Index of the first def that is under this scope. For msgdefs, the - * msgdef itself is at start-1. */ - int start; - uint32_t oneof_start; - uint32_t oneof_index; -} upb_descreader_frame; - -/* The maximum number of nested declarations that are allowed, ie. - * message Foo { - * message Bar { - * message Baz { - * } - * } - * } - * - * This is a resource limit that affects how big our runtime stack can grow. - * TODO: make this a runtime-settable property of the Reader instance. */ -#define UPB_MAX_MESSAGE_NESTING 64 - -struct upb_descreader { - upb_sink sink; - upb_inttable files; - upb_filedef *file; /* The last file in files. */ - upb_descreader_frame stack[UPB_MAX_MESSAGE_NESTING]; - int stack_len; - upb_inttable oneofs; - - uint32_t number; - char *name; - bool saw_number; - bool saw_name; - - char *default_string; - - upb_fielddef *f; -}; - -static char *upb_gstrndup(const char *buf, size_t n) { - char *ret = upb_gmalloc(n + 1); - if (!ret) return NULL; - memcpy(ret, buf, n); - ret[n] = '\0'; - return ret; -} - -/* Returns a newly allocated string that joins input strings together, for - * example: - * join("Foo.Bar", "Baz") -> "Foo.Bar.Baz" - * join("", "Baz") -> "Baz" - * Caller owns a ref on the returned string. */ -static char *upb_join(const char *base, const char *name) { - if (!base || strlen(base) == 0) { - return upb_gstrdup(name); - } else { - char *ret = upb_gmalloc(strlen(base) + strlen(name) + 2); - if (!ret) { - return NULL; - } - ret[0] = '\0'; - strcat(ret, base); - strcat(ret, "."); - strcat(ret, name); - return ret; - } -} - -/* Qualify the defname for all defs starting with offset "start" with "str". */ -static bool upb_descreader_qualify(upb_filedef *f, char *str, int32_t start) { - size_t i; - for (i = start; i < upb_filedef_defcount(f); i++) { - upb_def *def = upb_filedef_mutabledef(f, i); - char *name = upb_join(str, upb_def_fullname(def)); - if (!name) { - /* Need better logic here; at this point we've qualified some names but - * not others. */ - return false; - } - upb_def_setfullname(def, name, NULL); - upb_gfree(name); - } - return true; -} - - -/* upb_descreader ************************************************************/ - -static upb_msgdef *upb_descreader_top(upb_descreader *r) { - int index; - UPB_ASSERT(r->stack_len > 1); - index = r->stack[r->stack_len-1].start - 1; - UPB_ASSERT(index >= 0); - return upb_downcast_msgdef_mutable(upb_filedef_mutabledef(r->file, index)); -} - -static upb_def *upb_descreader_last(upb_descreader *r) { - return upb_filedef_mutabledef(r->file, upb_filedef_defcount(r->file) - 1); -} - -/* Start/end handlers for FileDescriptorProto and DescriptorProto (the two - * entities that have names and can contain sub-definitions. */ -void upb_descreader_startcontainer(upb_descreader *r) { - upb_descreader_frame *f = &r->stack[r->stack_len++]; - f->start = upb_filedef_defcount(r->file); - f->oneof_start = upb_inttable_count(&r->oneofs); - f->oneof_index = 0; - f->name = NULL; -} - -bool upb_descreader_endcontainer(upb_descreader *r) { - upb_descreader_frame *f = &r->stack[r->stack_len - 1]; - - while (upb_inttable_count(&r->oneofs) > f->oneof_start) { - upb_oneofdef *o = upb_value_getptr(upb_inttable_pop(&r->oneofs)); - bool ok = upb_msgdef_addoneof(upb_descreader_top(r), o, &r->oneofs, NULL); - UPB_ASSERT(ok); - } - - if (!upb_descreader_qualify(r->file, f->name, f->start)) { - return false; - } - upb_gfree(f->name); - f->name = NULL; - - r->stack_len--; - return true; -} - -void upb_descreader_setscopename(upb_descreader *r, char *str) { - upb_descreader_frame *f = &r->stack[r->stack_len-1]; - upb_gfree(f->name); - f->name = str; -} - -static upb_oneofdef *upb_descreader_getoneof(upb_descreader *r, - uint32_t index) { - bool found; - upb_value val; - upb_descreader_frame *f = &r->stack[r->stack_len-1]; - - /* DescriptorProto messages can be nested, so we will see the nested messages - * between when we see the FieldDescriptorProto and the OneofDescriptorProto. - * We need to preserve the oneofs in between these two things. */ - index += f->oneof_start; - - while (upb_inttable_count(&r->oneofs) <= index) { - upb_inttable_push(&r->oneofs, upb_value_ptr(upb_oneofdef_new(&r->oneofs))); - } - - found = upb_inttable_lookup(&r->oneofs, index, &val); - UPB_ASSERT(found); - return upb_value_getptr(val); -} - -/** Handlers for google.protobuf.FileDescriptorSet. ***************************/ - -static void *fileset_startfile(void *closure, const void *hd) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - r->file = upb_filedef_new(&r->files); - upb_inttable_push(&r->files, upb_value_ptr(r->file)); - return r; -} - -/** Handlers for google.protobuf.FileDescriptorProto. *************************/ - -static bool file_start(void *closure, const void *hd) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - upb_descreader_startcontainer(r); - return true; -} - -static bool file_end(void *closure, const void *hd, upb_status *status) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - UPB_UNUSED(status); - return upb_descreader_endcontainer(r); -} - -static size_t file_onname(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *name; - bool ok; - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - name = upb_gstrndup(buf, n); - /* XXX: see comment at the top of the file. */ - ok = upb_filedef_setname(r->file, name, NULL); - upb_gfree(name); - UPB_ASSERT(ok); - return n; -} - -static size_t file_onpackage(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *package; - bool ok; - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - package = upb_gstrndup(buf, n); - /* XXX: see comment at the top of the file. */ - upb_descreader_setscopename(r, package); - ok = upb_filedef_setpackage(r->file, package, NULL); - UPB_ASSERT(ok); - return n; -} - -static size_t file_onphpnamespace(void *closure, const void *hd, - const char *buf, size_t n, - const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *php_namespace; - bool ok; - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - php_namespace = upb_gstrndup(buf, n); - ok = upb_filedef_setphpnamespace(r->file, php_namespace, NULL); - upb_gfree(php_namespace); - UPB_ASSERT(ok); - return n; -} - -static size_t file_onphpprefix(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *prefix; - bool ok; - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - prefix = upb_gstrndup(buf, n); - ok = upb_filedef_setphpprefix(r->file, prefix, NULL); - upb_gfree(prefix); - UPB_ASSERT(ok); - return n; -} - -static size_t file_onsyntax(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - bool ok; - UPB_UNUSED(hd); - UPB_UNUSED(handle); - /* XXX: see comment at the top of the file. */ - if (upb_streq("proto2", buf, n)) { - ok = upb_filedef_setsyntax(r->file, UPB_SYNTAX_PROTO2, NULL); - } else if (upb_streq("proto3", buf, n)) { - ok = upb_filedef_setsyntax(r->file, UPB_SYNTAX_PROTO3, NULL); - } else { - ok = false; - } - - UPB_ASSERT(ok); - return n; -} - -static void *file_startmsg(void *closure, const void *hd) { - upb_descreader *r = closure; - upb_msgdef *m = upb_msgdef_new(&m); - bool ok = upb_filedef_addmsg(r->file, m, &m, NULL); - UPB_UNUSED(hd); - UPB_ASSERT(ok); - return r; -} - -static void *file_startenum(void *closure, const void *hd) { - upb_descreader *r = closure; - upb_enumdef *e = upb_enumdef_new(&e); - bool ok = upb_filedef_addenum(r->file, e, &e, NULL); - UPB_UNUSED(hd); - UPB_ASSERT(ok); - return r; -} - -static void *file_startext(void *closure, const void *hd) { - upb_descreader *r = closure; - bool ok; - r->f = upb_fielddef_new(r); - ok = upb_filedef_addext(r->file, r->f, r, NULL); - UPB_UNUSED(hd); - UPB_ASSERT(ok); - return r; -} - -/** Handlers for google.protobuf.EnumValueDescriptorProto. *********************/ - -static bool enumval_startmsg(void *closure, const void *hd) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - r->saw_number = false; - r->saw_name = false; - return true; -} - -static size_t enumval_onname(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - UPB_UNUSED(handle); - /* XXX: see comment at the top of the file. */ - upb_gfree(r->name); - r->name = upb_gstrndup(buf, n); - r->saw_name = true; - return n; -} - -static bool enumval_onnumber(void *closure, const void *hd, int32_t val) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - r->number = val; - r->saw_number = true; - return true; -} - -static bool enumval_endmsg(void *closure, const void *hd, upb_status *status) { - upb_descreader *r = closure; - upb_enumdef *e; - UPB_UNUSED(hd); - - if(!r->saw_number || !r->saw_name) { - upb_status_seterrmsg(status, "Enum value missing name or number."); - return false; - } - e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); - upb_enumdef_addval(e, r->name, r->number, status); - upb_gfree(r->name); - r->name = NULL; - return true; -} - -/** Handlers for google.protobuf.EnumDescriptorProto. *************************/ - -static bool enum_endmsg(void *closure, const void *hd, upb_status *status) { - upb_descreader *r = closure; - upb_enumdef *e; - UPB_UNUSED(hd); - - e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); - if (upb_def_fullname(upb_descreader_last(r)) == NULL) { - upb_status_seterrmsg(status, "Enum had no name."); - return false; - } - if (upb_enumdef_numvals(e) == 0) { - upb_status_seterrmsg(status, "Enum had no values."); - return false; - } - return true; -} - -static size_t enum_onname(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *fullname = upb_gstrndup(buf, n); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - /* XXX: see comment at the top of the file. */ - upb_def_setfullname(upb_descreader_last(r), fullname, NULL); - upb_gfree(fullname); - return n; -} - -/** Handlers for google.protobuf.FieldDescriptorProto *************************/ - -static bool field_startmsg(void *closure, const void *hd) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - UPB_ASSERT(r->f); - upb_gfree(r->default_string); - r->default_string = NULL; - - /* fielddefs default to packed, but descriptors default to non-packed. */ - upb_fielddef_setpacked(r->f, false); - return true; -} - -/* Converts the default value in string "str" into "d". Passes a ref on str. - * Returns true on success. */ -static bool parse_default(char *str, upb_fielddef *f) { - bool success = true; - char *end; - switch (upb_fielddef_type(f)) { - case UPB_TYPE_INT32: { - long val = strtol(str, &end, 0); - if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end) - success = false; - else - upb_fielddef_setdefaultint32(f, val); - break; - } - case UPB_TYPE_INT64: { - /* XXX: Need to write our own strtoll, since it's not available in c89. */ - long long val = strtol(str, &end, 0); - if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end) - success = false; - else - upb_fielddef_setdefaultint64(f, val); - break; - } - case UPB_TYPE_UINT32: { - unsigned long val = strtoul(str, &end, 0); - if (val > UINT32_MAX || errno == ERANGE || *end) - success = false; - else - upb_fielddef_setdefaultuint32(f, val); - break; - } - case UPB_TYPE_UINT64: { - /* XXX: Need to write our own strtoull, since it's not available in c89. */ - unsigned long long val = strtoul(str, &end, 0); - if (val > UINT64_MAX || errno == ERANGE || *end) - success = false; - else - upb_fielddef_setdefaultuint64(f, val); - break; - } - case UPB_TYPE_DOUBLE: { - double val = strtod(str, &end); - if (errno == ERANGE || *end) - success = false; - else - upb_fielddef_setdefaultdouble(f, val); - break; - } - case UPB_TYPE_FLOAT: { - /* XXX: Need to write our own strtof, since it's not available in c89. */ - float val = strtod(str, &end); - if (errno == ERANGE || *end) - success = false; - else - upb_fielddef_setdefaultfloat(f, val); - break; - } - case UPB_TYPE_BOOL: { - if (strcmp(str, "false") == 0) - upb_fielddef_setdefaultbool(f, false); - else if (strcmp(str, "true") == 0) - upb_fielddef_setdefaultbool(f, true); - else - success = false; - break; - } - default: abort(); - } - return success; -} - -static bool field_endmsg(void *closure, const void *hd, upb_status *status) { - upb_descreader *r = closure; - upb_fielddef *f = r->f; - UPB_UNUSED(hd); - - /* TODO: verify that all required fields were present. */ - UPB_ASSERT(upb_fielddef_number(f) != 0); - UPB_ASSERT(upb_fielddef_name(f) != NULL); - UPB_ASSERT((upb_fielddef_subdefname(f) != NULL) == upb_fielddef_hassubdef(f)); - - if (r->default_string) { - if (upb_fielddef_issubmsg(f)) { - upb_status_seterrmsg(status, "Submessages cannot have defaults."); - return false; - } - if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM) { - upb_fielddef_setdefaultcstr(f, r->default_string, NULL); - } else { - if (r->default_string && !parse_default(r->default_string, f)) { - /* We don't worry too much about giving a great error message since the - * compiler should have ensured this was correct. */ - upb_status_seterrmsg(status, "Error converting default value."); - return false; - } - } - } - return true; -} - -static bool field_onlazy(void *closure, const void *hd, bool val) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - - upb_fielddef_setlazy(r->f, val); - return true; -} - -static bool field_onpacked(void *closure, const void *hd, bool val) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - - upb_fielddef_setpacked(r->f, val); - return true; -} - -static bool field_ontype(void *closure, const void *hd, int32_t val) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - - upb_fielddef_setdescriptortype(r->f, val); - return true; -} - -static bool field_onlabel(void *closure, const void *hd, int32_t val) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - - upb_fielddef_setlabel(r->f, val); - return true; -} - -static bool field_onnumber(void *closure, const void *hd, int32_t val) { - upb_descreader *r = closure; - bool ok; - UPB_UNUSED(hd); - - ok = upb_fielddef_setnumber(r->f, val, NULL); - UPB_ASSERT(ok); - return true; -} - -static size_t field_onname(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *name = upb_gstrndup(buf, n); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - /* XXX: see comment at the top of the file. */ - upb_fielddef_setname(r->f, name, NULL); - upb_gfree(name); - return n; -} - -static size_t field_ontypename(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *name = upb_gstrndup(buf, n); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - /* XXX: see comment at the top of the file. */ - upb_fielddef_setsubdefname(r->f, name, NULL); - upb_gfree(name); - return n; -} - -static size_t field_onextendee(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - char *name = upb_gstrndup(buf, n); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - /* XXX: see comment at the top of the file. */ - upb_fielddef_setcontainingtypename(r->f, name, NULL); - upb_gfree(name); - return n; -} - -static size_t field_ondefaultval(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - /* Have to convert from string to the correct type, but we might not know the - * type yet, so we save it as a string until the end of the field. - * XXX: see comment at the top of the file. */ - upb_gfree(r->default_string); - r->default_string = upb_gstrndup(buf, n); - return n; -} - -static bool field_ononeofindex(void *closure, const void *hd, int32_t index) { - upb_descreader *r = closure; - upb_oneofdef *o = upb_descreader_getoneof(r, index); - bool ok = upb_oneofdef_addfield(o, r->f, &r->f, NULL); - UPB_UNUSED(hd); - - UPB_ASSERT(ok); - return true; -} - -/** Handlers for google.protobuf.OneofDescriptorProto. ************************/ - -static size_t oneof_name(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - upb_descreader_frame *f = &r->stack[r->stack_len-1]; - upb_oneofdef *o = upb_descreader_getoneof(r, f->oneof_index++); - char *name_null_terminated = upb_gstrndup(buf, n); - bool ok = upb_oneofdef_setname(o, name_null_terminated, NULL); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - UPB_ASSERT(ok); - free(name_null_terminated); - return n; -} - -/** Handlers for google.protobuf.DescriptorProto ******************************/ - -static bool msg_start(void *closure, const void *hd) { - upb_descreader *r = closure; - UPB_UNUSED(hd); - - upb_descreader_startcontainer(r); - return true; -} - -static bool msg_end(void *closure, const void *hd, upb_status *status) { - upb_descreader *r = closure; - upb_msgdef *m = upb_descreader_top(r); - UPB_UNUSED(hd); - - if(!upb_def_fullname(upb_msgdef_upcast_mutable(m))) { - upb_status_seterrmsg(status, "Encountered message with no name."); - return false; - } - return upb_descreader_endcontainer(r); -} - -static size_t msg_name(void *closure, const void *hd, const char *buf, - size_t n, const upb_bufhandle *handle) { - upb_descreader *r = closure; - upb_msgdef *m = upb_descreader_top(r); - /* XXX: see comment at the top of the file. */ - char *name = upb_gstrndup(buf, n); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - upb_def_setfullname(upb_msgdef_upcast_mutable(m), name, NULL); - upb_descreader_setscopename(r, name); /* Passes ownership of name. */ - return n; -} - -static void *msg_startmsg(void *closure, const void *hd) { - upb_descreader *r = closure; - upb_msgdef *m = upb_msgdef_new(&m); - bool ok = upb_filedef_addmsg(r->file, m, &m, NULL); - UPB_UNUSED(hd); - UPB_ASSERT(ok); - return r; -} - -static void *msg_startext(void *closure, const void *hd) { - upb_descreader *r = closure; - upb_fielddef *f = upb_fielddef_new(&f); - bool ok = upb_filedef_addext(r->file, f, &f, NULL); - UPB_UNUSED(hd); - UPB_ASSERT(ok); - return r; -} - -static void *msg_startfield(void *closure, const void *hd) { - upb_descreader *r = closure; - r->f = upb_fielddef_new(&r->f); - /* We can't add the new field to the message until its name/number are - * filled in. */ - UPB_UNUSED(hd); - return r; -} - -static bool msg_endfield(void *closure, const void *hd) { - upb_descreader *r = closure; - upb_msgdef *m = upb_descreader_top(r); - bool ok; - UPB_UNUSED(hd); - - /* Oneof fields are added to the msgdef through their oneof, so don't need to - * be added here. */ - if (upb_fielddef_containingoneof(r->f) == NULL) { - ok = upb_msgdef_addfield(m, r->f, &r->f, NULL); - UPB_ASSERT(ok); - } - r->f = NULL; - return true; -} - -static bool msg_onmapentry(void *closure, const void *hd, bool mapentry) { - upb_descreader *r = closure; - upb_msgdef *m = upb_descreader_top(r); - UPB_UNUSED(hd); - - upb_msgdef_setmapentry(m, mapentry); - r->f = NULL; - return true; -} - - - -/** Code to register handlers *************************************************/ - -#define F(msg, field) upbdefs_google_protobuf_ ## msg ## _f_ ## field(m) - -static void reghandlers(const void *closure, upb_handlers *h) { - const upb_msgdef *m = upb_handlers_msgdef(h); - UPB_UNUSED(closure); - - if (upbdefs_google_protobuf_FileDescriptorSet_is(m)) { - upb_handlers_setstartsubmsg(h, F(FileDescriptorSet, file), - &fileset_startfile, NULL); - } else if (upbdefs_google_protobuf_DescriptorProto_is(m)) { - upb_handlers_setstartmsg(h, &msg_start, NULL); - upb_handlers_setendmsg(h, &msg_end, NULL); - upb_handlers_setstring(h, F(DescriptorProto, name), &msg_name, NULL); - upb_handlers_setstartsubmsg(h, F(DescriptorProto, extension), &msg_startext, - NULL); - upb_handlers_setstartsubmsg(h, F(DescriptorProto, nested_type), - &msg_startmsg, NULL); - upb_handlers_setstartsubmsg(h, F(DescriptorProto, field), - &msg_startfield, NULL); - upb_handlers_setendsubmsg(h, F(DescriptorProto, field), - &msg_endfield, NULL); - upb_handlers_setstartsubmsg(h, F(DescriptorProto, enum_type), - &file_startenum, NULL); - } else if (upbdefs_google_protobuf_FileDescriptorProto_is(m)) { - upb_handlers_setstartmsg(h, &file_start, NULL); - upb_handlers_setendmsg(h, &file_end, NULL); - upb_handlers_setstring(h, F(FileDescriptorProto, name), &file_onname, - NULL); - upb_handlers_setstring(h, F(FileDescriptorProto, package), &file_onpackage, - NULL); - upb_handlers_setstring(h, F(FileDescriptorProto, syntax), &file_onsyntax, - NULL); - upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, message_type), - &file_startmsg, NULL); - upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, enum_type), - &file_startenum, NULL); - upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, extension), - &file_startext, NULL); - } else if (upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)) { - upb_handlers_setstartmsg(h, &enumval_startmsg, NULL); - upb_handlers_setendmsg(h, &enumval_endmsg, NULL); - upb_handlers_setstring(h, F(EnumValueDescriptorProto, name), &enumval_onname, NULL); - upb_handlers_setint32(h, F(EnumValueDescriptorProto, number), &enumval_onnumber, - NULL); - } else if (upbdefs_google_protobuf_EnumDescriptorProto_is(m)) { - upb_handlers_setendmsg(h, &enum_endmsg, NULL); - upb_handlers_setstring(h, F(EnumDescriptorProto, name), &enum_onname, NULL); - } else if (upbdefs_google_protobuf_FieldDescriptorProto_is(m)) { - upb_handlers_setstartmsg(h, &field_startmsg, NULL); - upb_handlers_setendmsg(h, &field_endmsg, NULL); - upb_handlers_setint32(h, F(FieldDescriptorProto, type), &field_ontype, - NULL); - upb_handlers_setint32(h, F(FieldDescriptorProto, label), &field_onlabel, - NULL); - upb_handlers_setint32(h, F(FieldDescriptorProto, number), &field_onnumber, - NULL); - upb_handlers_setstring(h, F(FieldDescriptorProto, name), &field_onname, - NULL); - upb_handlers_setstring(h, F(FieldDescriptorProto, type_name), - &field_ontypename, NULL); - upb_handlers_setstring(h, F(FieldDescriptorProto, extendee), - &field_onextendee, NULL); - upb_handlers_setstring(h, F(FieldDescriptorProto, default_value), - &field_ondefaultval, NULL); - upb_handlers_setint32(h, F(FieldDescriptorProto, oneof_index), - &field_ononeofindex, NULL); - } else if (upbdefs_google_protobuf_OneofDescriptorProto_is(m)) { - upb_handlers_setstring(h, F(OneofDescriptorProto, name), &oneof_name, NULL); - } else if (upbdefs_google_protobuf_FieldOptions_is(m)) { - upb_handlers_setbool(h, F(FieldOptions, lazy), &field_onlazy, NULL); - upb_handlers_setbool(h, F(FieldOptions, packed), &field_onpacked, NULL); - } else if (upbdefs_google_protobuf_MessageOptions_is(m)) { - upb_handlers_setbool(h, F(MessageOptions, map_entry), &msg_onmapentry, NULL); - } else if (upbdefs_google_protobuf_FileOptions_is(m)) { - upb_handlers_setstring(h, F(FileOptions, php_class_prefix), - &file_onphpprefix, NULL); - upb_handlers_setstring(h, F(FileOptions, php_namespace), - &file_onphpnamespace, NULL); - } - - UPB_ASSERT(upb_ok(upb_handlers_status(h))); -} - -#undef F - -void descreader_cleanup(void *_r) { - upb_descreader *r = _r; - size_t i; - - for (i = 0; i < upb_descreader_filecount(r); i++) { - upb_filedef_unref(upb_descreader_file(r, i), &r->files); - } - - upb_gfree(r->name); - upb_inttable_uninit(&r->files); - upb_inttable_uninit(&r->oneofs); - upb_gfree(r->default_string); - while (r->stack_len > 0) { - upb_descreader_frame *f = &r->stack[--r->stack_len]; - upb_gfree(f->name); - } -} - - -/* Public API ****************************************************************/ - -upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h) { - upb_descreader *r = upb_env_malloc(e, sizeof(upb_descreader)); - if (!r || !upb_env_addcleanup(e, descreader_cleanup, r)) { - return NULL; - } - - upb_inttable_init(&r->files, UPB_CTYPE_PTR); - upb_inttable_init(&r->oneofs, UPB_CTYPE_PTR); - upb_sink_reset(upb_descreader_input(r), h, r); - r->stack_len = 0; - r->name = NULL; - r->default_string = NULL; - - return r; -} - -size_t upb_descreader_filecount(const upb_descreader *r) { - return upb_inttable_count(&r->files); -} - -upb_filedef *upb_descreader_file(const upb_descreader *r, size_t i) { - upb_value v; - if (upb_inttable_lookup(&r->files, i, &v)) { - return upb_value_getptr(v); - } else { - return NULL; - } -} - -upb_sink *upb_descreader_input(upb_descreader *r) { - return &r->sink; -} - -const upb_handlers *upb_descreader_newhandlers(const void *owner) { - const upb_msgdef *m = upbdefs_google_protobuf_FileDescriptorSet_get(&m); - const upb_handlers *h = upb_handlers_newfrozen(m, owner, reghandlers, NULL); - upb_msgdef_unref(m, &m); - return h; -} -/* -** protobuf decoder bytecode compiler -** -** Code to compile a upb::Handlers into bytecode for decoding a protobuf -** according to that specific schema and destination handlers. -** -** Compiling to bytecode is always the first step. If we are using the -** interpreted decoder we leave it as bytecode and interpret that. If we are -** using a JIT decoder we use a code generator to turn the bytecode into native -** code, LLVM IR, etc. -** -** Bytecode definition is in decoder.int.h. -*/ - -#include - -#ifdef UPB_DUMP_BYTECODE -#include -#endif - -#define MAXLABEL 5 -#define EMPTYLABEL -1 - -/* mgroup *********************************************************************/ - -static void freegroup(upb_refcounted *r) { - mgroup *g = (mgroup*)r; - upb_inttable_uninit(&g->methods); -#ifdef UPB_USE_JIT_X64 - upb_pbdecoder_freejit(g); -#endif - upb_gfree(g->bytecode); - upb_gfree(g); -} - -static void visitgroup(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const mgroup *g = (const mgroup*)r; - upb_inttable_iter i; - upb_inttable_begin(&i, &g->methods); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i)); - visit(r, upb_pbdecodermethod_upcast(method), closure); - } -} - -mgroup *newgroup(const void *owner) { - mgroup *g = upb_gmalloc(sizeof(*g)); - static const struct upb_refcounted_vtbl vtbl = {visitgroup, freegroup}; - upb_refcounted_init(mgroup_upcast_mutable(g), &vtbl, owner); - upb_inttable_init(&g->methods, UPB_CTYPE_PTR); - g->bytecode = NULL; - g->bytecode_end = NULL; - return g; -} - - -/* upb_pbdecodermethod ********************************************************/ - -static void freemethod(upb_refcounted *r) { - upb_pbdecodermethod *method = (upb_pbdecodermethod*)r; - - if (method->dest_handlers_) { - upb_handlers_unref(method->dest_handlers_, method); - } - - upb_inttable_uninit(&method->dispatch); - upb_gfree(method); -} - -static void visitmethod(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_pbdecodermethod *m = (const upb_pbdecodermethod*)r; - visit(r, m->group, closure); -} - -static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers, - mgroup *group) { - static const struct upb_refcounted_vtbl vtbl = {visitmethod, freemethod}; - upb_pbdecodermethod *ret = upb_gmalloc(sizeof(*ret)); - upb_refcounted_init(upb_pbdecodermethod_upcast_mutable(ret), &vtbl, &ret); - upb_byteshandler_init(&ret->input_handler_); - - /* The method references the group and vice-versa, in a circular reference. */ - upb_ref2(ret, group); - upb_ref2(group, ret); - upb_inttable_insertptr(&group->methods, dest_handlers, upb_value_ptr(ret)); - upb_pbdecodermethod_unref(ret, &ret); - - ret->group = mgroup_upcast_mutable(group); - ret->dest_handlers_ = dest_handlers; - ret->is_native_ = false; /* If we JIT, it will update this later. */ - upb_inttable_init(&ret->dispatch, UPB_CTYPE_UINT64); - - if (ret->dest_handlers_) { - upb_handlers_ref(ret->dest_handlers_, ret); - } - return ret; -} - -const upb_handlers *upb_pbdecodermethod_desthandlers( - const upb_pbdecodermethod *m) { - return m->dest_handlers_; -} - -const upb_byteshandler *upb_pbdecodermethod_inputhandler( - const upb_pbdecodermethod *m) { - return &m->input_handler_; -} - -bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m) { - return m->is_native_; -} - -const upb_pbdecodermethod *upb_pbdecodermethod_new( - const upb_pbdecodermethodopts *opts, const void *owner) { - const upb_pbdecodermethod *ret; - upb_pbcodecache cache; - - upb_pbcodecache_init(&cache); - ret = upb_pbcodecache_getdecodermethod(&cache, opts); - upb_pbdecodermethod_ref(ret, owner); - upb_pbcodecache_uninit(&cache); - return ret; -} - - -/* bytecode compiler **********************************************************/ - -/* Data used only at compilation time. */ -typedef struct { - mgroup *group; - - uint32_t *pc; - int fwd_labels[MAXLABEL]; - int back_labels[MAXLABEL]; - - /* For fields marked "lazy", parse them lazily or eagerly? */ - bool lazy; -} compiler; - -static compiler *newcompiler(mgroup *group, bool lazy) { - compiler *ret = upb_gmalloc(sizeof(*ret)); - int i; - - ret->group = group; - ret->lazy = lazy; - for (i = 0; i < MAXLABEL; i++) { - ret->fwd_labels[i] = EMPTYLABEL; - ret->back_labels[i] = EMPTYLABEL; - } - return ret; -} - -static void freecompiler(compiler *c) { - upb_gfree(c); -} - -const size_t ptr_words = sizeof(void*) / sizeof(uint32_t); - -/* How many words an instruction is. */ -static int instruction_len(uint32_t instr) { - switch (getop(instr)) { - case OP_SETDISPATCH: return 1 + ptr_words; - case OP_TAGN: return 3; - case OP_SETBIGGROUPNUM: return 2; - default: return 1; - } -} - -bool op_has_longofs(int32_t instruction) { - switch (getop(instruction)) { - case OP_CALL: - case OP_BRANCH: - case OP_CHECKDELIM: - return true; - /* The "tag" instructions only have 8 bytes available for the jump target, - * but that is ok because these opcodes only require short jumps. */ - case OP_TAG1: - case OP_TAG2: - case OP_TAGN: - return false; - default: - UPB_ASSERT(false); - return false; - } -} - -static int32_t getofs(uint32_t instruction) { - if (op_has_longofs(instruction)) { - return (int32_t)instruction >> 8; - } else { - return (int8_t)(instruction >> 8); - } -} - -static void setofs(uint32_t *instruction, int32_t ofs) { - if (op_has_longofs(*instruction)) { - *instruction = getop(*instruction) | ofs << 8; - } else { - *instruction = (*instruction & ~0xff00) | ((ofs & 0xff) << 8); - } - UPB_ASSERT(getofs(*instruction) == ofs); /* Would fail in cases of overflow. */ -} - -static uint32_t pcofs(compiler *c) { return c->pc - c->group->bytecode; } - -/* Defines a local label at the current PC location. All previous forward - * references are updated to point to this location. The location is noted - * for any future backward references. */ -static void label(compiler *c, unsigned int label) { - int val; - uint32_t *codep; - - UPB_ASSERT(label < MAXLABEL); - val = c->fwd_labels[label]; - codep = (val == EMPTYLABEL) ? NULL : c->group->bytecode + val; - while (codep) { - int ofs = getofs(*codep); - setofs(codep, c->pc - codep - instruction_len(*codep)); - codep = ofs ? codep + ofs : NULL; - } - c->fwd_labels[label] = EMPTYLABEL; - c->back_labels[label] = pcofs(c); -} - -/* Creates a reference to a numbered label; either a forward reference - * (positive arg) or backward reference (negative arg). For forward references - * the value returned now is actually a "next" pointer into a linked list of all - * instructions that use this label and will be patched later when the label is - * defined with label(). - * - * The returned value is the offset that should be written into the instruction. - */ -static int32_t labelref(compiler *c, int label) { - UPB_ASSERT(label < MAXLABEL); - if (label == LABEL_DISPATCH) { - /* No resolving required. */ - return 0; - } else if (label < 0) { - /* Backward local label. Relative to the next instruction. */ - uint32_t from = (c->pc + 1) - c->group->bytecode; - return c->back_labels[-label] - from; - } else { - /* Forward local label: prepend to (possibly-empty) linked list. */ - int *lptr = &c->fwd_labels[label]; - int32_t ret = (*lptr == EMPTYLABEL) ? 0 : *lptr - pcofs(c); - *lptr = pcofs(c); - return ret; - } -} - -static void put32(compiler *c, uint32_t v) { - mgroup *g = c->group; - if (c->pc == g->bytecode_end) { - int ofs = pcofs(c); - size_t oldsize = g->bytecode_end - g->bytecode; - size_t newsize = UPB_MAX(oldsize * 2, 64); - /* TODO(haberman): handle OOM. */ - g->bytecode = upb_grealloc(g->bytecode, oldsize * sizeof(uint32_t), - newsize * sizeof(uint32_t)); - g->bytecode_end = g->bytecode + newsize; - c->pc = g->bytecode + ofs; - } - *c->pc++ = v; -} - -static void putop(compiler *c, opcode op, ...) { - va_list ap; - va_start(ap, op); - - switch (op) { - case OP_SETDISPATCH: { - uintptr_t ptr = (uintptr_t)va_arg(ap, void*); - put32(c, OP_SETDISPATCH); - put32(c, ptr); - if (sizeof(uintptr_t) > sizeof(uint32_t)) - put32(c, (uint64_t)ptr >> 32); - break; - } - case OP_STARTMSG: - case OP_ENDMSG: - case OP_PUSHLENDELIM: - case OP_POP: - case OP_SETDELIM: - case OP_HALT: - case OP_RET: - case OP_DISPATCH: - put32(c, op); - break; - case OP_PARSE_DOUBLE: - case OP_PARSE_FLOAT: - case OP_PARSE_INT64: - case OP_PARSE_UINT64: - case OP_PARSE_INT32: - case OP_PARSE_FIXED64: - case OP_PARSE_FIXED32: - case OP_PARSE_BOOL: - case OP_PARSE_UINT32: - case OP_PARSE_SFIXED32: - case OP_PARSE_SFIXED64: - case OP_PARSE_SINT32: - case OP_PARSE_SINT64: - case OP_STARTSEQ: - case OP_ENDSEQ: - case OP_STARTSUBMSG: - case OP_ENDSUBMSG: - case OP_STARTSTR: - case OP_STRING: - case OP_ENDSTR: - case OP_PUSHTAGDELIM: - put32(c, op | va_arg(ap, upb_selector_t) << 8); - break; - case OP_SETBIGGROUPNUM: - put32(c, op); - put32(c, va_arg(ap, int)); - break; - case OP_CALL: { - const upb_pbdecodermethod *method = va_arg(ap, upb_pbdecodermethod *); - put32(c, op | (method->code_base.ofs - (pcofs(c) + 1)) << 8); - break; - } - case OP_CHECKDELIM: - case OP_BRANCH: { - uint32_t instruction = op; - int label = va_arg(ap, int); - setofs(&instruction, labelref(c, label)); - put32(c, instruction); - break; - } - case OP_TAG1: - case OP_TAG2: { - int label = va_arg(ap, int); - uint64_t tag = va_arg(ap, uint64_t); - uint32_t instruction = op | (tag << 16); - UPB_ASSERT(tag <= 0xffff); - setofs(&instruction, labelref(c, label)); - put32(c, instruction); - break; - } - case OP_TAGN: { - int label = va_arg(ap, int); - uint64_t tag = va_arg(ap, uint64_t); - uint32_t instruction = op | (upb_value_size(tag) << 16); - setofs(&instruction, labelref(c, label)); - put32(c, instruction); - put32(c, tag); - put32(c, tag >> 32); - break; - } - } - - va_end(ap); -} - -#if defined(UPB_USE_JIT_X64) || defined(UPB_DUMP_BYTECODE) - -const char *upb_pbdecoder_getopname(unsigned int op) { -#define QUOTE(x) #x -#define EXPAND_AND_QUOTE(x) QUOTE(x) -#define OPNAME(x) OP_##x -#define OP(x) case OPNAME(x): return EXPAND_AND_QUOTE(OPNAME(x)); -#define T(x) OP(PARSE_##x) - /* Keep in sync with list in decoder.int.h. */ - switch ((opcode)op) { - T(DOUBLE) T(FLOAT) T(INT64) T(UINT64) T(INT32) T(FIXED64) T(FIXED32) - T(BOOL) T(UINT32) T(SFIXED32) T(SFIXED64) T(SINT32) T(SINT64) - OP(STARTMSG) OP(ENDMSG) OP(STARTSEQ) OP(ENDSEQ) OP(STARTSUBMSG) - OP(ENDSUBMSG) OP(STARTSTR) OP(STRING) OP(ENDSTR) OP(CALL) OP(RET) - OP(PUSHLENDELIM) OP(PUSHTAGDELIM) OP(SETDELIM) OP(CHECKDELIM) - OP(BRANCH) OP(TAG1) OP(TAG2) OP(TAGN) OP(SETDISPATCH) OP(POP) - OP(SETBIGGROUPNUM) OP(DISPATCH) OP(HALT) - } - return ""; -#undef OP -#undef T -} - -#endif - -#ifdef UPB_DUMP_BYTECODE - -static void dumpbc(uint32_t *p, uint32_t *end, FILE *f) { - - uint32_t *begin = p; - - while (p < end) { - fprintf(f, "%p %8tx", p, p - begin); - uint32_t instr = *p++; - uint8_t op = getop(instr); - fprintf(f, " %s", upb_pbdecoder_getopname(op)); - switch ((opcode)op) { - case OP_SETDISPATCH: { - const upb_inttable *dispatch; - memcpy(&dispatch, p, sizeof(void*)); - p += ptr_words; - const upb_pbdecodermethod *method = - (void *)((char *)dispatch - - offsetof(upb_pbdecodermethod, dispatch)); - fprintf(f, " %s", upb_msgdef_fullname( - upb_handlers_msgdef(method->dest_handlers_))); - break; - } - case OP_DISPATCH: - case OP_STARTMSG: - case OP_ENDMSG: - case OP_PUSHLENDELIM: - case OP_POP: - case OP_SETDELIM: - case OP_HALT: - case OP_RET: - break; - case OP_PARSE_DOUBLE: - case OP_PARSE_FLOAT: - case OP_PARSE_INT64: - case OP_PARSE_UINT64: - case OP_PARSE_INT32: - case OP_PARSE_FIXED64: - case OP_PARSE_FIXED32: - case OP_PARSE_BOOL: - case OP_PARSE_UINT32: - case OP_PARSE_SFIXED32: - case OP_PARSE_SFIXED64: - case OP_PARSE_SINT32: - case OP_PARSE_SINT64: - case OP_STARTSEQ: - case OP_ENDSEQ: - case OP_STARTSUBMSG: - case OP_ENDSUBMSG: - case OP_STARTSTR: - case OP_STRING: - case OP_ENDSTR: - case OP_PUSHTAGDELIM: - fprintf(f, " %d", instr >> 8); - break; - case OP_SETBIGGROUPNUM: - fprintf(f, " %d", *p++); - break; - case OP_CHECKDELIM: - case OP_CALL: - case OP_BRANCH: - fprintf(f, " =>0x%tx", p + getofs(instr) - begin); - break; - case OP_TAG1: - case OP_TAG2: { - fprintf(f, " tag:0x%x", instr >> 16); - if (getofs(instr)) { - fprintf(f, " =>0x%tx", p + getofs(instr) - begin); - } - break; - } - case OP_TAGN: { - uint64_t tag = *p++; - tag |= (uint64_t)*p++ << 32; - fprintf(f, " tag:0x%llx", (long long)tag); - fprintf(f, " n:%d", instr >> 16); - if (getofs(instr)) { - fprintf(f, " =>0x%tx", p + getofs(instr) - begin); - } - break; - } - } - fputs("\n", f); - } -} - -#endif - -static uint64_t get_encoded_tag(const upb_fielddef *f, int wire_type) { - uint32_t tag = (upb_fielddef_number(f) << 3) | wire_type; - uint64_t encoded_tag = upb_vencode32(tag); - /* No tag should be greater than 5 bytes. */ - UPB_ASSERT(encoded_tag <= 0xffffffffff); - return encoded_tag; -} - -static void putchecktag(compiler *c, const upb_fielddef *f, - int wire_type, int dest) { - uint64_t tag = get_encoded_tag(f, wire_type); - switch (upb_value_size(tag)) { - case 1: - putop(c, OP_TAG1, dest, tag); - break; - case 2: - putop(c, OP_TAG2, dest, tag); - break; - default: - putop(c, OP_TAGN, dest, tag); - break; - } -} - -static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) { - upb_selector_t selector; - bool ok = upb_handlers_getselector(f, type, &selector); - UPB_ASSERT(ok); - return selector; -} - -/* Takes an existing, primary dispatch table entry and repacks it with a - * different alternate wire type. Called when we are inserting a secondary - * dispatch table entry for an alternate wire type. */ -static uint64_t repack(uint64_t dispatch, int new_wt2) { - uint64_t ofs; - uint8_t wt1; - uint8_t old_wt2; - upb_pbdecoder_unpackdispatch(dispatch, &ofs, &wt1, &old_wt2); - UPB_ASSERT(old_wt2 == NO_WIRE_TYPE); /* wt2 should not be set yet. */ - return upb_pbdecoder_packdispatch(ofs, wt1, new_wt2); -} - -/* Marks the current bytecode position as the dispatch target for this message, - * field, and wire type. */ -static void dispatchtarget(compiler *c, upb_pbdecodermethod *method, - const upb_fielddef *f, int wire_type) { - /* Offset is relative to msg base. */ - uint64_t ofs = pcofs(c) - method->code_base.ofs; - uint32_t fn = upb_fielddef_number(f); - upb_inttable *d = &method->dispatch; - upb_value v; - if (upb_inttable_remove(d, fn, &v)) { - /* TODO: prioritize based on packed setting in .proto file. */ - uint64_t repacked = repack(upb_value_getuint64(v), wire_type); - upb_inttable_insert(d, fn, upb_value_uint64(repacked)); - upb_inttable_insert(d, fn + UPB_MAX_FIELDNUMBER, upb_value_uint64(ofs)); - } else { - uint64_t val = upb_pbdecoder_packdispatch(ofs, wire_type, NO_WIRE_TYPE); - upb_inttable_insert(d, fn, upb_value_uint64(val)); - } -} - -static void putpush(compiler *c, const upb_fielddef *f) { - if (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) { - putop(c, OP_PUSHLENDELIM); - } else { - uint32_t fn = upb_fielddef_number(f); - if (fn >= 1 << 24) { - putop(c, OP_PUSHTAGDELIM, 0); - putop(c, OP_SETBIGGROUPNUM, fn); - } else { - putop(c, OP_PUSHTAGDELIM, fn); - } - } -} - -static upb_pbdecodermethod *find_submethod(const compiler *c, - const upb_pbdecodermethod *method, - const upb_fielddef *f) { - const upb_handlers *sub = - upb_handlers_getsubhandlers(method->dest_handlers_, f); - upb_value v; - return upb_inttable_lookupptr(&c->group->methods, sub, &v) - ? upb_value_getptr(v) - : NULL; -} - -static void putsel(compiler *c, opcode op, upb_selector_t sel, - const upb_handlers *h) { - if (upb_handlers_gethandler(h, sel)) { - putop(c, op, sel); - } -} - -/* Puts an opcode to call a callback, but only if a callback actually exists for - * this field and handler type. */ -static void maybeput(compiler *c, opcode op, const upb_handlers *h, - const upb_fielddef *f, upb_handlertype_t type) { - putsel(c, op, getsel(f, type), h); -} - -static bool haslazyhandlers(const upb_handlers *h, const upb_fielddef *f) { - if (!upb_fielddef_lazy(f)) - return false; - - return upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STARTSTR)) || - upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STRING)) || - upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_ENDSTR)); -} - - -/* bytecode compiler code generation ******************************************/ - -/* Symbolic names for our local labels. */ -#define LABEL_LOOPSTART 1 /* Top of a repeated field loop. */ -#define LABEL_LOOPBREAK 2 /* To jump out of a repeated loop */ -#define LABEL_FIELD 3 /* Jump backward to find the most recent field. */ -#define LABEL_ENDMSG 4 /* To reach the OP_ENDMSG instr for this msg. */ - -/* Generates bytecode to parse a single non-lazy message field. */ -static void generate_msgfield(compiler *c, const upb_fielddef *f, - upb_pbdecodermethod *method) { - const upb_handlers *h = upb_pbdecodermethod_desthandlers(method); - const upb_pbdecodermethod *sub_m = find_submethod(c, method, f); - int wire_type; - - if (!sub_m) { - /* Don't emit any code for this field at all; it will be parsed as an - * unknown field. - * - * TODO(haberman): we should change this to parse it as a string field - * instead. It will probably be faster, but more importantly, once we - * start vending unknown fields, a field shouldn't be treated as unknown - * just because it doesn't have subhandlers registered. */ - return; - } - - label(c, LABEL_FIELD); - - wire_type = - (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) - ? UPB_WIRE_TYPE_DELIMITED - : UPB_WIRE_TYPE_START_GROUP; - - if (upb_fielddef_isseq(f)) { - putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - putchecktag(c, f, wire_type, LABEL_DISPATCH); - dispatchtarget(c, method, f, wire_type); - putop(c, OP_PUSHTAGDELIM, 0); - putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); - label(c, LABEL_LOOPSTART); - putpush(c, f); - putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG)); - putop(c, OP_CALL, sub_m); - putop(c, OP_POP); - maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG); - if (wire_type == UPB_WIRE_TYPE_DELIMITED) { - putop(c, OP_SETDELIM); - } - putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK); - putchecktag(c, f, wire_type, LABEL_LOOPBREAK); - putop(c, OP_BRANCH, -LABEL_LOOPSTART); - label(c, LABEL_LOOPBREAK); - putop(c, OP_POP); - maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ); - } else { - putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - putchecktag(c, f, wire_type, LABEL_DISPATCH); - dispatchtarget(c, method, f, wire_type); - putpush(c, f); - putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG)); - putop(c, OP_CALL, sub_m); - putop(c, OP_POP); - maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG); - if (wire_type == UPB_WIRE_TYPE_DELIMITED) { - putop(c, OP_SETDELIM); - } - } -} - -/* Generates bytecode to parse a single string or lazy submessage field. */ -static void generate_delimfield(compiler *c, const upb_fielddef *f, - upb_pbdecodermethod *method) { - const upb_handlers *h = upb_pbdecodermethod_desthandlers(method); - - label(c, LABEL_FIELD); - if (upb_fielddef_isseq(f)) { - putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH); - dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED); - putop(c, OP_PUSHTAGDELIM, 0); - putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); - label(c, LABEL_LOOPSTART); - putop(c, OP_PUSHLENDELIM); - putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR)); - /* Need to emit even if no handler to skip past the string. */ - putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING)); - putop(c, OP_POP); - maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR); - putop(c, OP_SETDELIM); - putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK); - putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_LOOPBREAK); - putop(c, OP_BRANCH, -LABEL_LOOPSTART); - label(c, LABEL_LOOPBREAK); - putop(c, OP_POP); - maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ); - } else { - putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH); - dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED); - putop(c, OP_PUSHLENDELIM); - putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR)); - putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING)); - putop(c, OP_POP); - maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR); - putop(c, OP_SETDELIM); - } -} - -/* Generates bytecode to parse a single primitive field. */ -static void generate_primitivefield(compiler *c, const upb_fielddef *f, - upb_pbdecodermethod *method) { - const upb_handlers *h = upb_pbdecodermethod_desthandlers(method); - upb_descriptortype_t descriptor_type = upb_fielddef_descriptortype(f); - opcode parse_type; - upb_selector_t sel; - int wire_type; - - label(c, LABEL_FIELD); - - /* From a decoding perspective, ENUM is the same as INT32. */ - if (descriptor_type == UPB_DESCRIPTOR_TYPE_ENUM) - descriptor_type = UPB_DESCRIPTOR_TYPE_INT32; - - parse_type = (opcode)descriptor_type; - - /* TODO(haberman): generate packed or non-packed first depending on "packed" - * setting in the fielddef. This will favor (in speed) whichever was - * specified. */ - - UPB_ASSERT((int)parse_type >= 0 && parse_type <= OP_MAX); - sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); - wire_type = upb_pb_native_wire_types[upb_fielddef_descriptortype(f)]; - if (upb_fielddef_isseq(f)) { - putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH); - dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED); - putop(c, OP_PUSHLENDELIM); - putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); /* Packed */ - label(c, LABEL_LOOPSTART); - putop(c, parse_type, sel); - putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK); - putop(c, OP_BRANCH, -LABEL_LOOPSTART); - dispatchtarget(c, method, f, wire_type); - putop(c, OP_PUSHTAGDELIM, 0); - putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); /* Non-packed */ - label(c, LABEL_LOOPSTART); - putop(c, parse_type, sel); - putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK); - putchecktag(c, f, wire_type, LABEL_LOOPBREAK); - putop(c, OP_BRANCH, -LABEL_LOOPSTART); - label(c, LABEL_LOOPBREAK); - putop(c, OP_POP); /* Packed and non-packed join. */ - maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ); - putop(c, OP_SETDELIM); /* Could remove for non-packed by dup ENDSEQ. */ - } else { - putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - putchecktag(c, f, wire_type, LABEL_DISPATCH); - dispatchtarget(c, method, f, wire_type); - putop(c, parse_type, sel); - } -} - -/* Adds bytecode for parsing the given message to the given decoderplan, - * while adding all dispatch targets to this message's dispatch table. */ -static void compile_method(compiler *c, upb_pbdecodermethod *method) { - const upb_handlers *h; - const upb_msgdef *md; - uint32_t* start_pc; - upb_msg_field_iter i; - upb_value val; - - UPB_ASSERT(method); - - /* Clear all entries in the dispatch table. */ - upb_inttable_uninit(&method->dispatch); - upb_inttable_init(&method->dispatch, UPB_CTYPE_UINT64); - - h = upb_pbdecodermethod_desthandlers(method); - md = upb_handlers_msgdef(h); - - method->code_base.ofs = pcofs(c); - putop(c, OP_SETDISPATCH, &method->dispatch); - putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h); - label(c, LABEL_FIELD); - start_pc = c->pc; - for(upb_msg_field_begin(&i, md); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - upb_fieldtype_t type = upb_fielddef_type(f); - - if (type == UPB_TYPE_MESSAGE && !(haslazyhandlers(h, f) && c->lazy)) { - generate_msgfield(c, f, method); - } else if (type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES || - type == UPB_TYPE_MESSAGE) { - generate_delimfield(c, f, method); - } else { - generate_primitivefield(c, f, method); - } - } - - /* If there were no fields, or if no handlers were defined, we need to - * generate a non-empty loop body so that we can at least dispatch for unknown - * fields and check for the end of the message. */ - if (c->pc == start_pc) { - /* Check for end-of-message. */ - putop(c, OP_CHECKDELIM, LABEL_ENDMSG); - /* Unconditionally dispatch. */ - putop(c, OP_DISPATCH, 0); - } - - /* For now we just loop back to the last field of the message (or if none, - * the DISPATCH opcode for the message). */ - putop(c, OP_BRANCH, -LABEL_FIELD); - - /* Insert both a label and a dispatch table entry for this end-of-msg. */ - label(c, LABEL_ENDMSG); - val = upb_value_uint64(pcofs(c) - method->code_base.ofs); - upb_inttable_insert(&method->dispatch, DISPATCH_ENDMSG, val); - - putsel(c, OP_ENDMSG, UPB_ENDMSG_SELECTOR, h); - putop(c, OP_RET); - - upb_inttable_compact(&method->dispatch); -} - -/* Populate "methods" with new upb_pbdecodermethod objects reachable from "h". - * Returns the method for these handlers. - * - * Generates a new method for every destination handlers reachable from "h". */ -static void find_methods(compiler *c, const upb_handlers *h) { - upb_value v; - upb_msg_field_iter i; - const upb_msgdef *md; - - if (upb_inttable_lookupptr(&c->group->methods, h, &v)) - return; - newmethod(h, c->group); - - /* Find submethods. */ - md = upb_handlers_msgdef(h); - for(upb_msg_field_begin(&i, md); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - const upb_handlers *sub_h; - if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE && - (sub_h = upb_handlers_getsubhandlers(h, f)) != NULL) { - /* We only generate a decoder method for submessages with handlers. - * Others will be parsed as unknown fields. */ - find_methods(c, sub_h); - } - } -} - -/* (Re-)compile bytecode for all messages in "msgs." - * Overwrites any existing bytecode in "c". */ -static void compile_methods(compiler *c) { - upb_inttable_iter i; - - /* Start over at the beginning of the bytecode. */ - c->pc = c->group->bytecode; - - upb_inttable_begin(&i, &c->group->methods); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i)); - compile_method(c, method); - } -} - -static void set_bytecode_handlers(mgroup *g) { - upb_inttable_iter i; - upb_inttable_begin(&i, &g->methods); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_pbdecodermethod *m = upb_value_getptr(upb_inttable_iter_value(&i)); - upb_byteshandler *h = &m->input_handler_; - - m->code_base.ptr = g->bytecode + m->code_base.ofs; - - upb_byteshandler_setstartstr(h, upb_pbdecoder_startbc, m->code_base.ptr); - upb_byteshandler_setstring(h, upb_pbdecoder_decode, g); - upb_byteshandler_setendstr(h, upb_pbdecoder_end, m); - } -} - - -/* JIT setup. *****************************************************************/ - -#ifdef UPB_USE_JIT_X64 - -static void sethandlers(mgroup *g, bool allowjit) { - g->jit_code = NULL; - if (allowjit) { - /* Compile byte-code into machine code, create handlers. */ - upb_pbdecoder_jit(g); - } else { - set_bytecode_handlers(g); - } -} - -#else /* UPB_USE_JIT_X64 */ - -static void sethandlers(mgroup *g, bool allowjit) { - /* No JIT compiled in; use bytecode handlers unconditionally. */ - UPB_UNUSED(allowjit); - set_bytecode_handlers(g); -} - -#endif /* UPB_USE_JIT_X64 */ - - -/* TODO(haberman): allow this to be constructed for an arbitrary set of dest - * handlers and other mgroups (but verify we have a transitive closure). */ -const mgroup *mgroup_new(const upb_handlers *dest, bool allowjit, bool lazy, - const void *owner) { - mgroup *g; - compiler *c; - - UPB_UNUSED(allowjit); - UPB_ASSERT(upb_handlers_isfrozen(dest)); - - g = newgroup(owner); - c = newcompiler(g, lazy); - find_methods(c, dest); - - /* We compile in two passes: - * 1. all messages are assigned relative offsets from the beginning of the - * bytecode (saved in method->code_base). - * 2. forwards OP_CALL instructions can be correctly linked since message - * offsets have been previously assigned. - * - * Could avoid the second pass by linking OP_CALL instructions somehow. */ - compile_methods(c); - compile_methods(c); - g->bytecode_end = c->pc; - freecompiler(c); - -#ifdef UPB_DUMP_BYTECODE - { - FILE *f = fopen("/tmp/upb-bytecode", "w"); - UPB_ASSERT(f); - dumpbc(g->bytecode, g->bytecode_end, stderr); - dumpbc(g->bytecode, g->bytecode_end, f); - fclose(f); - - f = fopen("/tmp/upb-bytecode.bin", "wb"); - UPB_ASSERT(f); - fwrite(g->bytecode, 1, g->bytecode_end - g->bytecode, f); - fclose(f); - } -#endif - - sethandlers(g, allowjit); - return g; -} - - -/* upb_pbcodecache ************************************************************/ - -void upb_pbcodecache_init(upb_pbcodecache *c) { - upb_inttable_init(&c->groups, UPB_CTYPE_CONSTPTR); - c->allow_jit_ = true; -} - -void upb_pbcodecache_uninit(upb_pbcodecache *c) { - upb_inttable_iter i; - upb_inttable_begin(&i, &c->groups); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - const mgroup *group = upb_value_getconstptr(upb_inttable_iter_value(&i)); - mgroup_unref(group, c); - } - upb_inttable_uninit(&c->groups); -} - -bool upb_pbcodecache_allowjit(const upb_pbcodecache *c) { - return c->allow_jit_; -} - -bool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow) { - if (upb_inttable_count(&c->groups) > 0) - return false; - c->allow_jit_ = allow; - return true; -} - -const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod( - upb_pbcodecache *c, const upb_pbdecodermethodopts *opts) { - upb_value v; - bool ok; - - /* Right now we build a new DecoderMethod every time. - * TODO(haberman): properly cache methods by their true key. */ - const mgroup *g = mgroup_new(opts->handlers, c->allow_jit_, opts->lazy, c); - upb_inttable_push(&c->groups, upb_value_constptr(g)); - - ok = upb_inttable_lookupptr(&g->methods, opts->handlers, &v); - UPB_ASSERT(ok); - return upb_value_getptr(v); -} - - -/* upb_pbdecodermethodopts ****************************************************/ - -void upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts, - const upb_handlers *h) { - opts->handlers = h; - opts->lazy = false; -} - -void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy) { - opts->lazy = lazy; -} -/* -** upb::Decoder (Bytecode Decoder VM) -** -** Bytecode must previously have been generated using the bytecode compiler in -** compile_decoder.c. This decoder then walks through the bytecode op-by-op to -** parse the input. -** -** Decoding is fully resumable; we just keep a pointer to the current bytecode -** instruction and resume from there. A fair amount of the logic here is to -** handle the fact that values can span buffer seams and we have to be able to -** be capable of suspending/resuming from any byte in the stream. This -** sometimes requires keeping a few trailing bytes from the last buffer around -** in the "residual" buffer. -*/ - -#include -#include - -#ifdef UPB_DUMP_BYTECODE -#include -#endif - -#define CHECK_SUSPEND(x) if (!(x)) return upb_pbdecoder_suspend(d); - -/* Error messages that are shared between the bytecode and JIT decoders. */ -const char *kPbDecoderStackOverflow = "Nesting too deep."; -const char *kPbDecoderSubmessageTooLong = - "Submessage end extends past enclosing submessage."; - -/* Error messages shared within this file. */ -static const char *kUnterminatedVarint = "Unterminated varint."; - -/* upb_pbdecoder **************************************************************/ - -static opcode halt = OP_HALT; - -/* A dummy character we can point to when the user passes us a NULL buffer. - * We need this because in C (NULL + 0) and (NULL - NULL) are undefined - * behavior, which would invalidate functions like curbufleft(). */ -static const char dummy_char; - -/* Whether an op consumes any of the input buffer. */ -static bool consumes_input(opcode op) { - switch (op) { - case OP_SETDISPATCH: - case OP_STARTMSG: - case OP_ENDMSG: - case OP_STARTSEQ: - case OP_ENDSEQ: - case OP_STARTSUBMSG: - case OP_ENDSUBMSG: - case OP_STARTSTR: - case OP_ENDSTR: - case OP_PUSHTAGDELIM: - case OP_POP: - case OP_SETDELIM: - case OP_SETBIGGROUPNUM: - case OP_CHECKDELIM: - case OP_CALL: - case OP_RET: - case OP_BRANCH: - return false; - default: - return true; - } -} - -static size_t stacksize(upb_pbdecoder *d, size_t entries) { - UPB_UNUSED(d); - return entries * sizeof(upb_pbdecoder_frame); -} - -static size_t callstacksize(upb_pbdecoder *d, size_t entries) { - UPB_UNUSED(d); - -#ifdef UPB_USE_JIT_X64 - if (d->method_->is_native_) { - /* Each native stack frame needs two pointers, plus we need a few frames for - * the enter/exit trampolines. */ - size_t ret = entries * sizeof(void*) * 2; - ret += sizeof(void*) * 10; - return ret; - } -#endif - - return entries * sizeof(uint32_t*); -} - - -static bool in_residual_buf(const upb_pbdecoder *d, const char *p); - -/* It's unfortunate that we have to micro-manage the compiler with - * UPB_FORCEINLINE and UPB_NOINLINE, especially since this tuning is necessarily - * specific to one hardware configuration. But empirically on a Core i7, - * performance increases 30-50% with these annotations. Every instance where - * these appear, gcc 4.2.1 made the wrong decision and degraded performance in - * benchmarks. */ - -static void seterr(upb_pbdecoder *d, const char *msg) { - upb_status status = UPB_STATUS_INIT; - upb_status_seterrmsg(&status, msg); - upb_env_reporterror(d->env, &status); -} - -void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) { - seterr(d, msg); -} - - -/* Buffering ******************************************************************/ - -/* We operate on one buffer at a time, which is either the user's buffer passed - * to our "decode" callback or some residual bytes from the previous buffer. */ - -/* How many bytes can be safely read from d->ptr without reading past end-of-buf - * or past the current delimited end. */ -static size_t curbufleft(const upb_pbdecoder *d) { - UPB_ASSERT(d->data_end >= d->ptr); - return d->data_end - d->ptr; -} - -/* How many bytes are available before end-of-buffer. */ -static size_t bufleft(const upb_pbdecoder *d) { - return d->end - d->ptr; -} - -/* Overall stream offset of d->ptr. */ -uint64_t offset(const upb_pbdecoder *d) { - return d->bufstart_ofs + (d->ptr - d->buf); -} - -/* How many bytes are available before the end of this delimited region. */ -size_t delim_remaining(const upb_pbdecoder *d) { - return d->top->end_ofs - offset(d); -} - -/* Advances d->ptr. */ -static void advance(upb_pbdecoder *d, size_t len) { - UPB_ASSERT(curbufleft(d) >= len); - d->ptr += len; -} - -static bool in_buf(const char *p, const char *buf, const char *end) { - return p >= buf && p <= end; -} - -static bool in_residual_buf(const upb_pbdecoder *d, const char *p) { - return in_buf(p, d->residual, d->residual_end); -} - -/* Calculates the delim_end value, which is affected by both the current buffer - * and the parsing stack, so must be called whenever either is updated. */ -static void set_delim_end(upb_pbdecoder *d) { - size_t delim_ofs = d->top->end_ofs - d->bufstart_ofs; - if (delim_ofs <= (size_t)(d->end - d->buf)) { - d->delim_end = d->buf + delim_ofs; - d->data_end = d->delim_end; - } else { - d->data_end = d->end; - d->delim_end = NULL; - } -} - -static void switchtobuf(upb_pbdecoder *d, const char *buf, const char *end) { - d->ptr = buf; - d->buf = buf; - d->end = end; - set_delim_end(d); -} - -static void advancetobuf(upb_pbdecoder *d, const char *buf, size_t len) { - UPB_ASSERT(curbufleft(d) == 0); - d->bufstart_ofs += (d->end - d->buf); - switchtobuf(d, buf, buf + len); -} - -static void checkpoint(upb_pbdecoder *d) { - /* The assertion here is in the interests of efficiency, not correctness. - * We are trying to ensure that we don't checkpoint() more often than - * necessary. */ - UPB_ASSERT(d->checkpoint != d->ptr); - d->checkpoint = d->ptr; -} - -/* Skips "bytes" bytes in the stream, which may be more than available. If we - * skip more bytes than are available, we return a long read count to the caller - * indicating how many bytes can be skipped over before passing actual data - * again. Skipped bytes can pass a NULL buffer and the decoder guarantees they - * won't actually be read. - */ -static int32_t skip(upb_pbdecoder *d, size_t bytes) { - UPB_ASSERT(!in_residual_buf(d, d->ptr) || d->size_param == 0); - UPB_ASSERT(d->skip == 0); - if (bytes > delim_remaining(d)) { - seterr(d, "Skipped value extended beyond enclosing submessage."); - return upb_pbdecoder_suspend(d); - } else if (bufleft(d) >= bytes) { - /* Skipped data is all in current buffer, and more is still available. */ - advance(d, bytes); - d->skip = 0; - return DECODE_OK; - } else { - /* Skipped data extends beyond currently available buffers. */ - d->pc = d->last; - d->skip = bytes - curbufleft(d); - d->bufstart_ofs += (d->end - d->buf); - d->residual_end = d->residual; - switchtobuf(d, d->residual, d->residual_end); - return d->size_param + d->skip; - } -} - - -/* Resumes the decoder from an initial state or from a previous suspend. */ -int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf, - size_t size, const upb_bufhandle *handle) { - UPB_UNUSED(p); /* Useless; just for the benefit of the JIT. */ - - /* d->skip and d->residual_end could probably elegantly be represented - * as a single variable, to more easily represent this invariant. */ - UPB_ASSERT(!(d->skip && d->residual_end > d->residual)); - - /* We need to remember the original size_param, so that the value we return - * is relative to it, even if we do some skipping first. */ - d->size_param = size; - d->handle = handle; - - /* Have to handle this case specially (ie. not with skip()) because the user - * is allowed to pass a NULL buffer here, which won't allow us to safely - * calculate a d->end or use our normal functions like curbufleft(). */ - if (d->skip && d->skip >= size) { - d->skip -= size; - d->bufstart_ofs += size; - buf = &dummy_char; - size = 0; - - /* We can't just return now, because we might need to execute some ops - * like CHECKDELIM, which could call some callbacks and pop the stack. */ - } - - /* We need to pretend that this was the actual buffer param, since some of the - * calculations assume that d->ptr/d->buf is relative to this. */ - d->buf_param = buf; - - if (!buf) { - /* NULL buf is ok if its entire span is covered by the "skip" above, but - * by this point we know that "skip" doesn't cover the buffer. */ - seterr(d, "Passed NULL buffer over non-skippable region."); - return upb_pbdecoder_suspend(d); - } - - if (d->residual_end > d->residual) { - /* We have residual bytes from the last buffer. */ - UPB_ASSERT(d->ptr == d->residual); - } else { - switchtobuf(d, buf, buf + size); - } - - d->checkpoint = d->ptr; - - /* Handle skips that don't cover the whole buffer (as above). */ - if (d->skip) { - size_t skip_bytes = d->skip; - d->skip = 0; - CHECK_RETURN(skip(d, skip_bytes)); - checkpoint(d); - } - - /* If we're inside an unknown group, continue to parse unknown values. */ - if (d->top->groupnum < 0) { - CHECK_RETURN(upb_pbdecoder_skipunknown(d, -1, 0)); - checkpoint(d); - } - - return DECODE_OK; -} - -/* Suspends the decoder at the last checkpoint, without saving any residual - * bytes. If there are any unconsumed bytes, returns a short byte count. */ -size_t upb_pbdecoder_suspend(upb_pbdecoder *d) { - d->pc = d->last; - if (d->checkpoint == d->residual) { - /* Checkpoint was in residual buf; no user bytes were consumed. */ - d->ptr = d->residual; - return 0; - } else { - size_t ret = d->size_param - (d->end - d->checkpoint); - UPB_ASSERT(!in_residual_buf(d, d->checkpoint)); - UPB_ASSERT(d->buf == d->buf_param || d->buf == &dummy_char); - - d->bufstart_ofs += (d->checkpoint - d->buf); - d->residual_end = d->residual; - switchtobuf(d, d->residual, d->residual_end); - return ret; - } -} - -/* Suspends the decoder at the last checkpoint, and saves any unconsumed - * bytes in our residual buffer. This is necessary if we need more user - * bytes to form a complete value, which might not be contiguous in the - * user's buffers. Always consumes all user bytes. */ -static size_t suspend_save(upb_pbdecoder *d) { - /* We hit end-of-buffer before we could parse a full value. - * Save any unconsumed bytes (if any) to the residual buffer. */ - d->pc = d->last; - - if (d->checkpoint == d->residual) { - /* Checkpoint was in residual buf; append user byte(s) to residual buf. */ - UPB_ASSERT((d->residual_end - d->residual) + d->size_param <= - sizeof(d->residual)); - if (!in_residual_buf(d, d->ptr)) { - d->bufstart_ofs -= (d->residual_end - d->residual); - } - memcpy(d->residual_end, d->buf_param, d->size_param); - d->residual_end += d->size_param; - } else { - /* Checkpoint was in user buf; old residual bytes not needed. */ - size_t save; - UPB_ASSERT(!in_residual_buf(d, d->checkpoint)); - - d->ptr = d->checkpoint; - save = curbufleft(d); - UPB_ASSERT(save <= sizeof(d->residual)); - memcpy(d->residual, d->ptr, save); - d->residual_end = d->residual + save; - d->bufstart_ofs = offset(d); - } - - switchtobuf(d, d->residual, d->residual_end); - return d->size_param; -} - -/* Copies the next "bytes" bytes into "buf" and advances the stream. - * Requires that this many bytes are available in the current buffer. */ -UPB_FORCEINLINE static void consumebytes(upb_pbdecoder *d, void *buf, - size_t bytes) { - UPB_ASSERT(bytes <= curbufleft(d)); - memcpy(buf, d->ptr, bytes); - advance(d, bytes); -} - -/* Slow path for getting the next "bytes" bytes, regardless of whether they are - * available in the current buffer or not. Returns a status code as described - * in decoder.int.h. */ -UPB_NOINLINE static int32_t getbytes_slow(upb_pbdecoder *d, void *buf, - size_t bytes) { - const size_t avail = curbufleft(d); - consumebytes(d, buf, avail); - bytes -= avail; - UPB_ASSERT(bytes > 0); - if (in_residual_buf(d, d->ptr)) { - advancetobuf(d, d->buf_param, d->size_param); - } - if (curbufleft(d) >= bytes) { - consumebytes(d, (char *)buf + avail, bytes); - return DECODE_OK; - } else if (d->data_end == d->delim_end) { - seterr(d, "Submessage ended in the middle of a value or group"); - return upb_pbdecoder_suspend(d); - } else { - return suspend_save(d); - } -} - -/* Gets the next "bytes" bytes, regardless of whether they are available in the - * current buffer or not. Returns a status code as described in decoder.int.h. - */ -UPB_FORCEINLINE static int32_t getbytes(upb_pbdecoder *d, void *buf, - size_t bytes) { - if (curbufleft(d) >= bytes) { - /* Buffer has enough data to satisfy. */ - consumebytes(d, buf, bytes); - return DECODE_OK; - } else { - return getbytes_slow(d, buf, bytes); - } -} - -UPB_NOINLINE static size_t peekbytes_slow(upb_pbdecoder *d, void *buf, - size_t bytes) { - size_t ret = curbufleft(d); - memcpy(buf, d->ptr, ret); - if (in_residual_buf(d, d->ptr)) { - size_t copy = UPB_MIN(bytes - ret, d->size_param); - memcpy((char *)buf + ret, d->buf_param, copy); - ret += copy; - } - return ret; -} - -UPB_FORCEINLINE static size_t peekbytes(upb_pbdecoder *d, void *buf, - size_t bytes) { - if (curbufleft(d) >= bytes) { - memcpy(buf, d->ptr, bytes); - return bytes; - } else { - return peekbytes_slow(d, buf, bytes); - } -} - - -/* Decoding of wire types *****************************************************/ - -/* Slow path for decoding a varint from the current buffer position. - * Returns a status code as described in decoder.int.h. */ -UPB_NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, - uint64_t *u64) { - uint8_t byte = 0x80; - int bitpos; - *u64 = 0; - for(bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) { - CHECK_RETURN(getbytes(d, &byte, 1)); - *u64 |= (uint64_t)(byte & 0x7F) << bitpos; - } - if(bitpos == 70 && (byte & 0x80)) { - seterr(d, kUnterminatedVarint); - return upb_pbdecoder_suspend(d); - } - return DECODE_OK; -} - -/* Decodes a varint from the current buffer position. - * Returns a status code as described in decoder.int.h. */ -UPB_FORCEINLINE static int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) { - if (curbufleft(d) > 0 && !(*d->ptr & 0x80)) { - *u64 = *d->ptr; - advance(d, 1); - return DECODE_OK; - } else if (curbufleft(d) >= 10) { - /* Fast case. */ - upb_decoderet r = upb_vdecode_fast(d->ptr); - if (r.p == NULL) { - seterr(d, kUnterminatedVarint); - return upb_pbdecoder_suspend(d); - } - advance(d, r.p - d->ptr); - *u64 = r.val; - return DECODE_OK; - } else { - /* Slow case -- varint spans buffer seam. */ - return upb_pbdecoder_decode_varint_slow(d, u64); - } -} - -/* Decodes a 32-bit varint from the current buffer position. - * Returns a status code as described in decoder.int.h. */ -UPB_FORCEINLINE static int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) { - uint64_t u64; - int32_t ret = decode_varint(d, &u64); - if (ret >= 0) return ret; - if (u64 > UINT32_MAX) { - seterr(d, "Unterminated 32-bit varint"); - /* TODO(haberman) guarantee that this function return is >= 0 somehow, - * so we know this path will always be treated as error by our caller. - * Right now the size_t -> int32_t can overflow and produce negative values. - */ - *u32 = 0; - return upb_pbdecoder_suspend(d); - } - *u32 = u64; - return DECODE_OK; -} - -/* Decodes a fixed32 from the current buffer position. - * Returns a status code as described in decoder.int.h. - * TODO: proper byte swapping for big-endian machines. */ -UPB_FORCEINLINE static int32_t decode_fixed32(upb_pbdecoder *d, uint32_t *u32) { - return getbytes(d, u32, 4); -} - -/* Decodes a fixed64 from the current buffer position. - * Returns a status code as described in decoder.int.h. - * TODO: proper byte swapping for big-endian machines. */ -UPB_FORCEINLINE static int32_t decode_fixed64(upb_pbdecoder *d, uint64_t *u64) { - return getbytes(d, u64, 8); -} - -/* Non-static versions of the above functions. - * These are called by the JIT for fallback paths. */ -int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32) { - return decode_fixed32(d, u32); -} - -int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64) { - return decode_fixed64(d, u64); -} - -static double as_double(uint64_t n) { double d; memcpy(&d, &n, 8); return d; } -static float as_float(uint32_t n) { float f; memcpy(&f, &n, 4); return f; } - -/* Pushes a frame onto the decoder stack. */ -static bool decoder_push(upb_pbdecoder *d, uint64_t end) { - upb_pbdecoder_frame *fr = d->top; - - if (end > fr->end_ofs) { - seterr(d, kPbDecoderSubmessageTooLong); - return false; - } else if (fr == d->limit) { - seterr(d, kPbDecoderStackOverflow); - return false; - } - - fr++; - fr->end_ofs = end; - fr->dispatch = NULL; - fr->groupnum = 0; - d->top = fr; - return true; -} - -static bool pushtagdelim(upb_pbdecoder *d, uint32_t arg) { - /* While we expect to see an "end" tag (either ENDGROUP or a non-sequence - * field number) prior to hitting any enclosing submessage end, pushing our - * existing delim end prevents us from continuing to parse values from a - * corrupt proto that doesn't give us an END tag in time. */ - if (!decoder_push(d, d->top->end_ofs)) - return false; - d->top->groupnum = arg; - return true; -} - -/* Pops a frame from the decoder stack. */ -static void decoder_pop(upb_pbdecoder *d) { d->top--; } - -UPB_NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d, - uint64_t expected) { - uint64_t data = 0; - size_t bytes = upb_value_size(expected); - size_t read = peekbytes(d, &data, bytes); - if (read == bytes && data == expected) { - /* Advance past matched bytes. */ - int32_t ok = getbytes(d, &data, read); - UPB_ASSERT(ok < 0); - return DECODE_OK; - } else if (read < bytes && memcmp(&data, &expected, read) == 0) { - return suspend_save(d); - } else { - return DECODE_MISMATCH; - } -} - -int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum, - uint8_t wire_type) { - if (fieldnum >= 0) - goto have_tag; - - while (true) { - uint32_t tag; - CHECK_RETURN(decode_v32(d, &tag)); - wire_type = tag & 0x7; - fieldnum = tag >> 3; - -have_tag: - if (fieldnum == 0) { - seterr(d, "Saw invalid field number (0)"); - return upb_pbdecoder_suspend(d); - } - - /* TODO: deliver to unknown field callback. */ - switch (wire_type) { - case UPB_WIRE_TYPE_32BIT: - CHECK_RETURN(skip(d, 4)); - break; - case UPB_WIRE_TYPE_64BIT: - CHECK_RETURN(skip(d, 8)); - break; - case UPB_WIRE_TYPE_VARINT: { - uint64_t u64; - CHECK_RETURN(decode_varint(d, &u64)); - break; - } - case UPB_WIRE_TYPE_DELIMITED: { - uint32_t len; - CHECK_RETURN(decode_v32(d, &len)); - CHECK_RETURN(skip(d, len)); - break; - } - case UPB_WIRE_TYPE_START_GROUP: - CHECK_SUSPEND(pushtagdelim(d, -fieldnum)); - break; - case UPB_WIRE_TYPE_END_GROUP: - if (fieldnum == -d->top->groupnum) { - decoder_pop(d); - } else if (fieldnum == d->top->groupnum) { - return DECODE_ENDGROUP; - } else { - seterr(d, "Unmatched ENDGROUP tag."); - return upb_pbdecoder_suspend(d); - } - break; - default: - seterr(d, "Invalid wire type"); - return upb_pbdecoder_suspend(d); - } - - if (d->top->groupnum >= 0) { - return DECODE_OK; - } - - /* Unknown group -- continue looping over unknown fields. */ - checkpoint(d); - } -} - -static void goto_endmsg(upb_pbdecoder *d) { - upb_value v; - bool found = upb_inttable_lookup32(d->top->dispatch, DISPATCH_ENDMSG, &v); - UPB_ASSERT(found); - d->pc = d->top->base + upb_value_getuint64(v); -} - -/* Parses a tag and jumps to the corresponding bytecode instruction for this - * field. - * - * If the tag is unknown (or the wire type doesn't match), parses the field as - * unknown. If the tag is a valid ENDGROUP tag, jumps to the bytecode - * instruction for the end of message. */ -static int32_t dispatch(upb_pbdecoder *d) { - upb_inttable *dispatch = d->top->dispatch; - uint32_t tag; - uint8_t wire_type; - uint32_t fieldnum; - upb_value val; - int32_t retval; - - /* Decode tag. */ - CHECK_RETURN(decode_v32(d, &tag)); - wire_type = tag & 0x7; - fieldnum = tag >> 3; - - /* Lookup tag. Because of packed/non-packed compatibility, we have to - * check the wire type against two possibilities. */ - if (fieldnum != DISPATCH_ENDMSG && - upb_inttable_lookup32(dispatch, fieldnum, &val)) { - uint64_t v = upb_value_getuint64(val); - if (wire_type == (v & 0xff)) { - d->pc = d->top->base + (v >> 16); - return DECODE_OK; - } else if (wire_type == ((v >> 8) & 0xff)) { - bool found = - upb_inttable_lookup(dispatch, fieldnum + UPB_MAX_FIELDNUMBER, &val); - UPB_ASSERT(found); - d->pc = d->top->base + upb_value_getuint64(val); - return DECODE_OK; - } - } - - /* We have some unknown fields (or ENDGROUP) to parse. The DISPATCH or TAG - * bytecode that triggered this is preceded by a CHECKDELIM bytecode which - * we need to back up to, so that when we're done skipping unknown data we - * can re-check the delimited end. */ - d->last--; /* Necessary if we get suspended */ - d->pc = d->last; - UPB_ASSERT(getop(*d->last) == OP_CHECKDELIM); - - /* Unknown field or ENDGROUP. */ - retval = upb_pbdecoder_skipunknown(d, fieldnum, wire_type); - - CHECK_RETURN(retval); - - if (retval == DECODE_ENDGROUP) { - goto_endmsg(d); - return DECODE_OK; - } - - return DECODE_OK; -} - -/* Callers know that the stack is more than one deep because the opcodes that - * call this only occur after PUSH operations. */ -upb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) { - UPB_ASSERT(d->top != d->stack); - return d->top - 1; -} - - -/* The main decoding loop *****************************************************/ - -/* The main decoder VM function. Uses traditional bytecode dispatch loop with a - * switch() statement. */ -size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group, - const upb_bufhandle* handle) { - -#define VMCASE(op, code) \ - case op: { code; if (consumes_input(op)) checkpoint(d); break; } -#define PRIMITIVE_OP(type, wt, name, convfunc, ctype) \ - VMCASE(OP_PARSE_ ## type, { \ - ctype val; \ - CHECK_RETURN(decode_ ## wt(d, &val)); \ - upb_sink_put ## name(&d->top->sink, arg, (convfunc)(val)); \ - }) - - while(1) { - int32_t instruction; - opcode op; - uint32_t arg; - int32_t longofs; - - d->last = d->pc; - instruction = *d->pc++; - op = getop(instruction); - arg = instruction >> 8; - longofs = arg; - UPB_ASSERT(d->ptr != d->residual_end); - UPB_UNUSED(group); -#ifdef UPB_DUMP_BYTECODE - fprintf(stderr, "s_ofs=%d buf_ofs=%d data_rem=%d buf_rem=%d delim_rem=%d " - "%x %s (%d)\n", - (int)offset(d), - (int)(d->ptr - d->buf), - (int)(d->data_end - d->ptr), - (int)(d->end - d->ptr), - (int)((d->top->end_ofs - d->bufstart_ofs) - (d->ptr - d->buf)), - (int)(d->pc - 1 - group->bytecode), - upb_pbdecoder_getopname(op), - arg); -#endif - switch (op) { - /* Technically, we are losing data if we see a 32-bit varint that is not - * properly sign-extended. We could detect this and error about the data - * loss, but proto2 does not do this, so we pass. */ - PRIMITIVE_OP(INT32, varint, int32, int32_t, uint64_t) - PRIMITIVE_OP(INT64, varint, int64, int64_t, uint64_t) - PRIMITIVE_OP(UINT32, varint, uint32, uint32_t, uint64_t) - PRIMITIVE_OP(UINT64, varint, uint64, uint64_t, uint64_t) - PRIMITIVE_OP(FIXED32, fixed32, uint32, uint32_t, uint32_t) - PRIMITIVE_OP(FIXED64, fixed64, uint64, uint64_t, uint64_t) - PRIMITIVE_OP(SFIXED32, fixed32, int32, int32_t, uint32_t) - PRIMITIVE_OP(SFIXED64, fixed64, int64, int64_t, uint64_t) - PRIMITIVE_OP(BOOL, varint, bool, bool, uint64_t) - PRIMITIVE_OP(DOUBLE, fixed64, double, as_double, uint64_t) - PRIMITIVE_OP(FLOAT, fixed32, float, as_float, uint32_t) - PRIMITIVE_OP(SINT32, varint, int32, upb_zzdec_32, uint64_t) - PRIMITIVE_OP(SINT64, varint, int64, upb_zzdec_64, uint64_t) - - VMCASE(OP_SETDISPATCH, - d->top->base = d->pc - 1; - memcpy(&d->top->dispatch, d->pc, sizeof(void*)); - d->pc += sizeof(void*) / sizeof(uint32_t); - ) - VMCASE(OP_STARTMSG, - CHECK_SUSPEND(upb_sink_startmsg(&d->top->sink)); - ) - VMCASE(OP_ENDMSG, - CHECK_SUSPEND(upb_sink_endmsg(&d->top->sink, d->status)); - ) - VMCASE(OP_STARTSEQ, - upb_pbdecoder_frame *outer = outer_frame(d); - CHECK_SUSPEND(upb_sink_startseq(&outer->sink, arg, &d->top->sink)); - ) - VMCASE(OP_ENDSEQ, - CHECK_SUSPEND(upb_sink_endseq(&d->top->sink, arg)); - ) - VMCASE(OP_STARTSUBMSG, - upb_pbdecoder_frame *outer = outer_frame(d); - CHECK_SUSPEND(upb_sink_startsubmsg(&outer->sink, arg, &d->top->sink)); - ) - VMCASE(OP_ENDSUBMSG, - CHECK_SUSPEND(upb_sink_endsubmsg(&d->top->sink, arg)); - ) - VMCASE(OP_STARTSTR, - uint32_t len = delim_remaining(d); - upb_pbdecoder_frame *outer = outer_frame(d); - CHECK_SUSPEND(upb_sink_startstr(&outer->sink, arg, len, &d->top->sink)); - if (len == 0) { - d->pc++; /* Skip OP_STRING. */ - } - ) - VMCASE(OP_STRING, - uint32_t len = curbufleft(d); - size_t n = upb_sink_putstring(&d->top->sink, arg, d->ptr, len, handle); - if (n > len) { - if (n > delim_remaining(d)) { - seterr(d, "Tried to skip past end of string."); - return upb_pbdecoder_suspend(d); - } else { - int32_t ret = skip(d, n); - /* This shouldn't return DECODE_OK, because n > len. */ - UPB_ASSERT(ret >= 0); - return ret; - } - } - advance(d, n); - if (n < len || d->delim_end == NULL) { - /* We aren't finished with this string yet. */ - d->pc--; /* Repeat OP_STRING. */ - if (n > 0) checkpoint(d); - return upb_pbdecoder_suspend(d); - } - ) - VMCASE(OP_ENDSTR, - CHECK_SUSPEND(upb_sink_endstr(&d->top->sink, arg)); - ) - VMCASE(OP_PUSHTAGDELIM, - CHECK_SUSPEND(pushtagdelim(d, arg)); - ) - VMCASE(OP_SETBIGGROUPNUM, - d->top->groupnum = *d->pc++; - ) - VMCASE(OP_POP, - UPB_ASSERT(d->top > d->stack); - decoder_pop(d); - ) - VMCASE(OP_PUSHLENDELIM, - uint32_t len; - CHECK_RETURN(decode_v32(d, &len)); - CHECK_SUSPEND(decoder_push(d, offset(d) + len)); - set_delim_end(d); - ) - VMCASE(OP_SETDELIM, - set_delim_end(d); - ) - VMCASE(OP_CHECKDELIM, - /* We are guaranteed of this assert because we never allow ourselves to - * consume bytes beyond data_end, which covers delim_end when non-NULL. - */ - UPB_ASSERT(!(d->delim_end && d->ptr > d->delim_end)); - if (d->ptr == d->delim_end) - d->pc += longofs; - ) - VMCASE(OP_CALL, - d->callstack[d->call_len++] = d->pc; - d->pc += longofs; - ) - VMCASE(OP_RET, - UPB_ASSERT(d->call_len > 0); - d->pc = d->callstack[--d->call_len]; - ) - VMCASE(OP_BRANCH, - d->pc += longofs; - ) - VMCASE(OP_TAG1, - uint8_t expected; - CHECK_SUSPEND(curbufleft(d) > 0); - expected = (arg >> 8) & 0xff; - if (*d->ptr == expected) { - advance(d, 1); - } else { - int8_t shortofs; - badtag: - shortofs = arg; - if (shortofs == LABEL_DISPATCH) { - CHECK_RETURN(dispatch(d)); - } else { - d->pc += shortofs; - break; /* Avoid checkpoint(). */ - } - } - ) - VMCASE(OP_TAG2, - uint16_t expected; - CHECK_SUSPEND(curbufleft(d) > 0); - expected = (arg >> 8) & 0xffff; - if (curbufleft(d) >= 2) { - uint16_t actual; - memcpy(&actual, d->ptr, 2); - if (expected == actual) { - advance(d, 2); - } else { - goto badtag; - } - } else { - int32_t result = upb_pbdecoder_checktag_slow(d, expected); - if (result == DECODE_MISMATCH) goto badtag; - if (result >= 0) return result; - } - ) - VMCASE(OP_TAGN, { - uint64_t expected; - int32_t result; - memcpy(&expected, d->pc, 8); - d->pc += 2; - result = upb_pbdecoder_checktag_slow(d, expected); - if (result == DECODE_MISMATCH) goto badtag; - if (result >= 0) return result; - }) - VMCASE(OP_DISPATCH, { - CHECK_RETURN(dispatch(d)); - }) - VMCASE(OP_HALT, { - return d->size_param; - }) - } - } -} - - -/* BytesHandler handlers ******************************************************/ - -void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint) { - upb_pbdecoder *d = closure; - UPB_UNUSED(size_hint); - d->top->end_ofs = UINT64_MAX; - d->bufstart_ofs = 0; - d->call_len = 1; - d->callstack[0] = &halt; - d->pc = pc; - d->skip = 0; - return d; -} - -void *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint) { - upb_pbdecoder *d = closure; - UPB_UNUSED(hd); - UPB_UNUSED(size_hint); - d->top->end_ofs = UINT64_MAX; - d->bufstart_ofs = 0; - d->call_len = 0; - d->skip = 0; - return d; -} - -bool upb_pbdecoder_end(void *closure, const void *handler_data) { - upb_pbdecoder *d = closure; - const upb_pbdecodermethod *method = handler_data; - uint64_t end; - char dummy; - - if (d->residual_end > d->residual) { - seterr(d, "Unexpected EOF: decoder still has buffered unparsed data"); - return false; - } - - if (d->skip) { - seterr(d, "Unexpected EOF inside skipped data"); - return false; - } - - if (d->top->end_ofs != UINT64_MAX) { - seterr(d, "Unexpected EOF inside delimited string"); - return false; - } - - /* The user's end() call indicates that the message ends here. */ - end = offset(d); - d->top->end_ofs = end; - -#ifdef UPB_USE_JIT_X64 - if (method->is_native_) { - const mgroup *group = (const mgroup*)method->group; - if (d->top != d->stack) - d->stack->end_ofs = 0; - group->jit_code(closure, method->code_base.ptr, &dummy, 0, NULL); - } else -#endif - { - const uint32_t *p = d->pc; - d->stack->end_ofs = end; - /* Check the previous bytecode, but guard against beginning. */ - if (p != method->code_base.ptr) p--; - if (getop(*p) == OP_CHECKDELIM) { - /* Rewind from OP_TAG* to OP_CHECKDELIM. */ - UPB_ASSERT(getop(*d->pc) == OP_TAG1 || - getop(*d->pc) == OP_TAG2 || - getop(*d->pc) == OP_TAGN || - getop(*d->pc) == OP_DISPATCH); - d->pc = p; - } - upb_pbdecoder_decode(closure, handler_data, &dummy, 0, NULL); - } - - if (d->call_len != 0) { - seterr(d, "Unexpected EOF inside submessage or group"); - return false; - } - - return true; -} - -size_t upb_pbdecoder_decode(void *decoder, const void *group, const char *buf, - size_t size, const upb_bufhandle *handle) { - int32_t result = upb_pbdecoder_resume(decoder, NULL, buf, size, handle); - - if (result == DECODE_ENDGROUP) goto_endmsg(decoder); - CHECK_RETURN(result); - - return run_decoder_vm(decoder, group, handle); -} - - -/* Public API *****************************************************************/ - -void upb_pbdecoder_reset(upb_pbdecoder *d) { - d->top = d->stack; - d->top->groupnum = 0; - d->ptr = d->residual; - d->buf = d->residual; - d->end = d->residual; - d->residual_end = d->residual; -} - -upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m, - upb_sink *sink) { - const size_t default_max_nesting = 64; -#ifndef NDEBUG - size_t size_before = upb_env_bytesallocated(e); -#endif - - upb_pbdecoder *d = upb_env_malloc(e, sizeof(upb_pbdecoder)); - if (!d) return NULL; - - d->method_ = m; - d->callstack = upb_env_malloc(e, callstacksize(d, default_max_nesting)); - d->stack = upb_env_malloc(e, stacksize(d, default_max_nesting)); - if (!d->stack || !d->callstack) { - return NULL; - } - - d->env = e; - d->limit = d->stack + default_max_nesting - 1; - d->stack_size = default_max_nesting; - d->status = NULL; - - upb_pbdecoder_reset(d); - upb_bytessink_reset(&d->input_, &m->input_handler_, d); - - UPB_ASSERT(sink); - if (d->method_->dest_handlers_) { - if (sink->handlers != d->method_->dest_handlers_) - return NULL; - } - upb_sink_reset(&d->top->sink, sink->handlers, sink->closure); - - /* If this fails, increase the value in decoder.h. */ - UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(e) - size_before <= - UPB_PB_DECODER_SIZE); - return d; -} - -uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d) { - return offset(d); -} - -const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d) { - return d->method_; -} - -upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d) { - return &d->input_; -} - -size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d) { - return d->stack_size; -} - -bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) { - UPB_ASSERT(d->top >= d->stack); - - if (max < (size_t)(d->top - d->stack)) { - /* Can't set a limit smaller than what we are currently at. */ - return false; - } - - if (max > d->stack_size) { - /* Need to reallocate stack and callstack to accommodate. */ - size_t old_size = stacksize(d, d->stack_size); - size_t new_size = stacksize(d, max); - void *p = upb_env_realloc(d->env, d->stack, old_size, new_size); - if (!p) { - return false; - } - d->stack = p; - - old_size = callstacksize(d, d->stack_size); - new_size = callstacksize(d, max); - p = upb_env_realloc(d->env, d->callstack, old_size, new_size); - if (!p) { - return false; - } - d->callstack = p; - - d->stack_size = max; - } - - d->limit = d->stack + max - 1; - return true; -} -/* -** upb::Encoder -** -** Since we are implementing pure handlers (ie. without any out-of-band access -** to pre-computed lengths), we have to buffer all submessages before we can -** emit even their first byte. -** -** Not knowing the size of submessages also means we can't write a perfect -** zero-copy implementation, even with buffering. Lengths are stored as -** varints, which means that we don't know how many bytes to reserve for the -** length until we know what the length is. -** -** This leaves us with three main choices: -** -** 1. buffer all submessage data in a temporary buffer, then copy it exactly -** once into the output buffer. -** -** 2. attempt to buffer data directly into the output buffer, estimating how -** many bytes each length will take. When our guesses are wrong, use -** memmove() to grow or shrink the allotted space. -** -** 3. buffer directly into the output buffer, allocating a max length -** ahead-of-time for each submessage length. If we overallocated, we waste -** space, but no memcpy() or memmove() is required. This approach requires -** defining a maximum size for submessages and rejecting submessages that -** exceed that size. -** -** (2) and (3) have the potential to have better performance, but they are more -** complicated and subtle to implement: -** -** (3) requires making an arbitrary choice of the maximum message size; it -** wastes space when submessages are shorter than this and fails -** completely when they are longer. This makes it more finicky and -** requires configuration based on the input. It also makes it impossible -** to perfectly match the output of reference encoders that always use the -** optimal amount of space for each length. -** -** (2) requires guessing the the size upfront, and if multiple lengths are -** guessed wrong the minimum required number of memmove() operations may -** be complicated to compute correctly. Implemented properly, it may have -** a useful amortized or average cost, but more investigation is required -** to determine this and what the optimal algorithm is to achieve it. -** -** (1) makes you always pay for exactly one copy, but its implementation is -** the simplest and its performance is predictable. -** -** So for now, we implement (1) only. If we wish to optimize later, we should -** be able to do it without affecting users. -** -** The strategy is to buffer the segments of data that do *not* depend on -** unknown lengths in one buffer, and keep a separate buffer of segment pointers -** and lengths. When the top-level submessage ends, we can go beginning to end, -** alternating the writing of lengths with memcpy() of the rest of the data. -** At the top level though, no buffering is required. -*/ - - - -/* The output buffer is divided into segments; a segment is a string of data - * that is "ready to go" -- it does not need any varint lengths inserted into - * the middle. The seams between segments are where varints will be inserted - * once they are known. - * - * We also use the concept of a "run", which is a range of encoded bytes that - * occur at a single submessage level. Every segment contains one or more runs. - * - * A segment can span messages. Consider: - * - * .--Submessage lengths---------. - * | | | - * | V V - * V | |--------------- | |----------------- - * Submessages: | |----------------------------------------------- - * Top-level msg: ------------------------------------------------------------ - * - * Segments: ----- ------------------- ----------------- - * Runs: *---- *--------------*--- *---------------- - * (* marks the start) - * - * Note that the top-level menssage is not in any segment because it does not - * have any length preceding it. - * - * A segment is only interrupted when another length needs to be inserted. So - * observe how the second segment spans both the inner submessage and part of - * the next enclosing message. */ -typedef struct { - uint32_t msglen; /* The length to varint-encode before this segment. */ - uint32_t seglen; /* Length of the segment. */ -} upb_pb_encoder_segment; - -struct upb_pb_encoder { - upb_env *env; - - /* Our input and output. */ - upb_sink input_; - upb_bytessink *output_; - - /* The "subclosure" -- used as the inner closure as part of the bytessink - * protocol. */ - void *subc; - - /* The output buffer and limit, and our current write position. "buf" - * initially points to "initbuf", but is dynamically allocated if we need to - * grow beyond the initial size. */ - char *buf, *ptr, *limit; - - /* The beginning of the current run, or undefined if we are at the top - * level. */ - char *runbegin; - - /* The list of segments we are accumulating. */ - upb_pb_encoder_segment *segbuf, *segptr, *seglimit; - - /* The stack of enclosing submessages. Each entry in the stack points to the - * segment where this submessage's length is being accumulated. */ - int *stack, *top, *stacklimit; - - /* Depth of startmsg/endmsg calls. */ - int depth; -}; - -/* low-level buffering ********************************************************/ - -/* Low-level functions for interacting with the output buffer. */ - -/* TODO(haberman): handle pushback */ -static void putbuf(upb_pb_encoder *e, const char *buf, size_t len) { - size_t n = upb_bytessink_putbuf(e->output_, e->subc, buf, len, NULL); - UPB_ASSERT(n == len); -} - -static upb_pb_encoder_segment *top(upb_pb_encoder *e) { - return &e->segbuf[*e->top]; -} - -/* Call to ensure that at least "bytes" bytes are available for writing at - * e->ptr. Returns false if the bytes could not be allocated. */ -static bool reserve(upb_pb_encoder *e, size_t bytes) { - if ((size_t)(e->limit - e->ptr) < bytes) { - /* Grow buffer. */ - char *new_buf; - size_t needed = bytes + (e->ptr - e->buf); - size_t old_size = e->limit - e->buf; - - size_t new_size = old_size; - - while (new_size < needed) { - new_size *= 2; - } - - new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size); - - if (new_buf == NULL) { - return false; - } - - e->ptr = new_buf + (e->ptr - e->buf); - e->runbegin = new_buf + (e->runbegin - e->buf); - e->limit = new_buf + new_size; - e->buf = new_buf; - } - - return true; -} - -/* Call when "bytes" bytes have been writte at e->ptr. The caller *must* have - * previously called reserve() with at least this many bytes. */ -static void encoder_advance(upb_pb_encoder *e, size_t bytes) { - UPB_ASSERT((size_t)(e->limit - e->ptr) >= bytes); - e->ptr += bytes; -} - -/* Call when all of the bytes for a handler have been written. Flushes the - * bytes if possible and necessary, returning false if this failed. */ -static bool commit(upb_pb_encoder *e) { - if (!e->top) { - /* We aren't inside a delimited region. Flush our accumulated bytes to - * the output. - * - * TODO(haberman): in the future we may want to delay flushing for - * efficiency reasons. */ - putbuf(e, e->buf, e->ptr - e->buf); - e->ptr = e->buf; - } - - return true; -} - -/* Writes the given bytes to the buffer, handling reserve/advance. */ -static bool encode_bytes(upb_pb_encoder *e, const void *data, size_t len) { - if (!reserve(e, len)) { - return false; - } - - memcpy(e->ptr, data, len); - encoder_advance(e, len); - return true; -} - -/* Finish the current run by adding the run totals to the segment and message - * length. */ -static void accumulate(upb_pb_encoder *e) { - size_t run_len; - UPB_ASSERT(e->ptr >= e->runbegin); - run_len = e->ptr - e->runbegin; - e->segptr->seglen += run_len; - top(e)->msglen += run_len; - e->runbegin = e->ptr; -} - -/* Call to indicate the start of delimited region for which the full length is - * not yet known. All data will be buffered until the length is known. - * Delimited regions may be nested; their lengths will all be tracked properly. */ -static bool start_delim(upb_pb_encoder *e) { - if (e->top) { - /* We are already buffering, advance to the next segment and push it on the - * stack. */ - accumulate(e); - - if (++e->top == e->stacklimit) { - /* TODO(haberman): grow stack? */ - return false; - } - - if (++e->segptr == e->seglimit) { - /* Grow segment buffer. */ - size_t old_size = - (e->seglimit - e->segbuf) * sizeof(upb_pb_encoder_segment); - size_t new_size = old_size * 2; - upb_pb_encoder_segment *new_buf = - upb_env_realloc(e->env, e->segbuf, old_size, new_size); - - if (new_buf == NULL) { - return false; - } - - e->segptr = new_buf + (e->segptr - e->segbuf); - e->seglimit = new_buf + (new_size / sizeof(upb_pb_encoder_segment)); - e->segbuf = new_buf; - } - } else { - /* We were previously at the top level, start buffering. */ - e->segptr = e->segbuf; - e->top = e->stack; - e->runbegin = e->ptr; - } - - *e->top = e->segptr - e->segbuf; - e->segptr->seglen = 0; - e->segptr->msglen = 0; - - return true; -} - -/* Call to indicate the end of a delimited region. We now know the length of - * the delimited region. If we are not nested inside any other delimited - * regions, we can now emit all of the buffered data we accumulated. */ -static bool end_delim(upb_pb_encoder *e) { - size_t msglen; - accumulate(e); - msglen = top(e)->msglen; - - if (e->top == e->stack) { - /* All lengths are now available, emit all buffered data. */ - char buf[UPB_PB_VARINT_MAX_LEN]; - upb_pb_encoder_segment *s; - const char *ptr = e->buf; - for (s = e->segbuf; s <= e->segptr; s++) { - size_t lenbytes = upb_vencode64(s->msglen, buf); - putbuf(e, buf, lenbytes); - putbuf(e, ptr, s->seglen); - ptr += s->seglen; - } - - e->ptr = e->buf; - e->top = NULL; - } else { - /* Need to keep buffering; propagate length info into enclosing - * submessages. */ - --e->top; - top(e)->msglen += msglen + upb_varint_size(msglen); - } - - return true; -} - - -/* tag_t **********************************************************************/ - -/* A precomputed (pre-encoded) tag and length. */ - -typedef struct { - uint8_t bytes; - char tag[7]; -} tag_t; - -/* Allocates a new tag for this field, and sets it in these handlerattr. */ -static void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt, - upb_handlerattr *attr) { - uint32_t n = upb_fielddef_number(f); - - tag_t *tag = upb_gmalloc(sizeof(tag_t)); - tag->bytes = upb_vencode64((n << 3) | wt, tag->tag); - - upb_handlerattr_init(attr); - upb_handlerattr_sethandlerdata(attr, tag); - upb_handlers_addcleanup(h, tag, upb_gfree); -} - -static bool encode_tag(upb_pb_encoder *e, const tag_t *tag) { - return encode_bytes(e, tag->tag, tag->bytes); -} - - -/* encoding of wire types *****************************************************/ - -static bool encode_fixed64(upb_pb_encoder *e, uint64_t val) { - /* TODO(haberman): byte-swap for big endian. */ - return encode_bytes(e, &val, sizeof(uint64_t)); -} - -static bool encode_fixed32(upb_pb_encoder *e, uint32_t val) { - /* TODO(haberman): byte-swap for big endian. */ - return encode_bytes(e, &val, sizeof(uint32_t)); -} - -static bool encode_varint(upb_pb_encoder *e, uint64_t val) { - if (!reserve(e, UPB_PB_VARINT_MAX_LEN)) { - return false; - } - - encoder_advance(e, upb_vencode64(val, e->ptr)); - return true; -} - -static uint64_t dbl2uint64(double d) { - uint64_t ret; - memcpy(&ret, &d, sizeof(uint64_t)); - return ret; -} - -static uint32_t flt2uint32(float d) { - uint32_t ret; - memcpy(&ret, &d, sizeof(uint32_t)); - return ret; -} - - -/* encoding of proto types ****************************************************/ - -static bool startmsg(void *c, const void *hd) { - upb_pb_encoder *e = c; - UPB_UNUSED(hd); - if (e->depth++ == 0) { - upb_bytessink_start(e->output_, 0, &e->subc); - } - return true; -} - -static bool endmsg(void *c, const void *hd, upb_status *status) { - upb_pb_encoder *e = c; - UPB_UNUSED(hd); - UPB_UNUSED(status); - if (--e->depth == 0) { - upb_bytessink_end(e->output_); - } - return true; -} - -static void *encode_startdelimfield(void *c, const void *hd) { - bool ok = encode_tag(c, hd) && commit(c) && start_delim(c); - return ok ? c : UPB_BREAK; -} - -static bool encode_enddelimfield(void *c, const void *hd) { - UPB_UNUSED(hd); - return end_delim(c); -} - -static void *encode_startgroup(void *c, const void *hd) { - return (encode_tag(c, hd) && commit(c)) ? c : UPB_BREAK; -} - -static bool encode_endgroup(void *c, const void *hd) { - return encode_tag(c, hd) && commit(c); -} - -static void *encode_startstr(void *c, const void *hd, size_t size_hint) { - UPB_UNUSED(size_hint); - return encode_startdelimfield(c, hd); -} - -static size_t encode_strbuf(void *c, const void *hd, const char *buf, - size_t len, const upb_bufhandle *h) { - UPB_UNUSED(hd); - UPB_UNUSED(h); - return encode_bytes(c, buf, len) ? len : 0; -} - -#define T(type, ctype, convert, encode) \ - static bool encode_scalar_##type(void *e, const void *hd, ctype val) { \ - return encode_tag(e, hd) && encode(e, (convert)(val)) && commit(e); \ - } \ - static bool encode_packed_##type(void *e, const void *hd, ctype val) { \ - UPB_UNUSED(hd); \ - return encode(e, (convert)(val)); \ - } - -T(double, double, dbl2uint64, encode_fixed64) -T(float, float, flt2uint32, encode_fixed32) -T(int64, int64_t, uint64_t, encode_varint) -T(int32, int32_t, int64_t, encode_varint) -T(fixed64, uint64_t, uint64_t, encode_fixed64) -T(fixed32, uint32_t, uint32_t, encode_fixed32) -T(bool, bool, bool, encode_varint) -T(uint32, uint32_t, uint32_t, encode_varint) -T(uint64, uint64_t, uint64_t, encode_varint) -T(enum, int32_t, uint32_t, encode_varint) -T(sfixed32, int32_t, uint32_t, encode_fixed32) -T(sfixed64, int64_t, uint64_t, encode_fixed64) -T(sint32, int32_t, upb_zzenc_32, encode_varint) -T(sint64, int64_t, upb_zzenc_64, encode_varint) - -#undef T - - -/* code to build the handlers *************************************************/ - -static void newhandlers_callback(const void *closure, upb_handlers *h) { - const upb_msgdef *m; - upb_msg_field_iter i; - - UPB_UNUSED(closure); - - upb_handlers_setstartmsg(h, startmsg, NULL); - upb_handlers_setendmsg(h, endmsg, NULL); - - m = upb_handlers_msgdef(h); - for(upb_msg_field_begin(&i, m); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) && - upb_fielddef_packed(f); - upb_handlerattr attr; - upb_wiretype_t wt = - packed ? UPB_WIRE_TYPE_DELIMITED - : upb_pb_native_wire_types[upb_fielddef_descriptortype(f)]; - - /* Pre-encode the tag for this field. */ - new_tag(h, f, wt, &attr); - - if (packed) { - upb_handlers_setstartseq(h, f, encode_startdelimfield, &attr); - upb_handlers_setendseq(h, f, encode_enddelimfield, &attr); - } - -#define T(upper, lower, upbtype) \ - case UPB_DESCRIPTOR_TYPE_##upper: \ - if (packed) { \ - upb_handlers_set##upbtype(h, f, encode_packed_##lower, &attr); \ - } else { \ - upb_handlers_set##upbtype(h, f, encode_scalar_##lower, &attr); \ - } \ - break; - - switch (upb_fielddef_descriptortype(f)) { - T(DOUBLE, double, double); - T(FLOAT, float, float); - T(INT64, int64, int64); - T(INT32, int32, int32); - T(FIXED64, fixed64, uint64); - T(FIXED32, fixed32, uint32); - T(BOOL, bool, bool); - T(UINT32, uint32, uint32); - T(UINT64, uint64, uint64); - T(ENUM, enum, int32); - T(SFIXED32, sfixed32, int32); - T(SFIXED64, sfixed64, int64); - T(SINT32, sint32, int32); - T(SINT64, sint64, int64); - case UPB_DESCRIPTOR_TYPE_STRING: - case UPB_DESCRIPTOR_TYPE_BYTES: - upb_handlers_setstartstr(h, f, encode_startstr, &attr); - upb_handlers_setendstr(h, f, encode_enddelimfield, &attr); - upb_handlers_setstring(h, f, encode_strbuf, &attr); - break; - case UPB_DESCRIPTOR_TYPE_MESSAGE: - upb_handlers_setstartsubmsg(h, f, encode_startdelimfield, &attr); - upb_handlers_setendsubmsg(h, f, encode_enddelimfield, &attr); - break; - case UPB_DESCRIPTOR_TYPE_GROUP: { - /* Endgroup takes a different tag (wire_type = END_GROUP). */ - upb_handlerattr attr2; - new_tag(h, f, UPB_WIRE_TYPE_END_GROUP, &attr2); - - upb_handlers_setstartsubmsg(h, f, encode_startgroup, &attr); - upb_handlers_setendsubmsg(h, f, encode_endgroup, &attr2); - - upb_handlerattr_uninit(&attr2); - break; - } - } - -#undef T - - upb_handlerattr_uninit(&attr); - } -} - -void upb_pb_encoder_reset(upb_pb_encoder *e) { - e->segptr = NULL; - e->top = NULL; - e->depth = 0; -} - - -/* public API *****************************************************************/ - -const upb_handlers *upb_pb_encoder_newhandlers(const upb_msgdef *m, - const void *owner) { - return upb_handlers_newfrozen(m, owner, newhandlers_callback, NULL); -} - -upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h, - upb_bytessink *output) { - const size_t initial_bufsize = 256; - const size_t initial_segbufsize = 16; - /* TODO(haberman): make this configurable. */ - const size_t stack_size = 64; -#ifndef NDEBUG - const size_t size_before = upb_env_bytesallocated(env); -#endif - - upb_pb_encoder *e = upb_env_malloc(env, sizeof(upb_pb_encoder)); - if (!e) return NULL; - - e->buf = upb_env_malloc(env, initial_bufsize); - e->segbuf = upb_env_malloc(env, initial_segbufsize * sizeof(*e->segbuf)); - e->stack = upb_env_malloc(env, stack_size * sizeof(*e->stack)); - - if (!e->buf || !e->segbuf || !e->stack) { - return NULL; - } - - e->limit = e->buf + initial_bufsize; - e->seglimit = e->segbuf + initial_segbufsize; - e->stacklimit = e->stack + stack_size; - - upb_pb_encoder_reset(e); - upb_sink_reset(&e->input_, h, e); - - e->env = env; - e->output_ = output; - e->subc = output->closure; - e->ptr = e->buf; - - /* If this fails, increase the value in encoder.h. */ - UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <= - UPB_PB_ENCODER_SIZE); - return e; -} - -upb_sink *upb_pb_encoder_input(upb_pb_encoder *e) { return &e->input_; } - - - -upb_filedef **upb_loaddescriptor(const char *buf, size_t n, const void *owner, - upb_status *status) { - /* Create handlers. */ - const upb_pbdecodermethod *decoder_m; - const upb_handlers *reader_h = upb_descreader_newhandlers(&reader_h); - upb_env env; - upb_pbdecodermethodopts opts; - upb_pbdecoder *decoder; - upb_descreader *reader; - bool ok; - size_t i; - upb_filedef **ret = NULL; - - upb_pbdecodermethodopts_init(&opts, reader_h); - decoder_m = upb_pbdecodermethod_new(&opts, &decoder_m); - - upb_env_init(&env); - upb_env_reporterrorsto(&env, status); - - reader = upb_descreader_create(&env, reader_h); - decoder = upb_pbdecoder_create(&env, decoder_m, upb_descreader_input(reader)); - - /* Push input data. */ - ok = upb_bufsrc_putbuf(buf, n, upb_pbdecoder_input(decoder)); - - if (!ok) { - goto cleanup; - } - - ret = upb_gmalloc(sizeof (*ret) * (upb_descreader_filecount(reader) + 1)); - - if (!ret) { - goto cleanup; - } - - for (i = 0; i < upb_descreader_filecount(reader); i++) { - ret[i] = upb_descreader_file(reader, i); - upb_filedef_ref(ret[i], owner); - } - - ret[i] = NULL; - -cleanup: - upb_env_uninit(&env); - upb_handlers_unref(reader_h, &reader_h); - upb_pbdecodermethod_unref(decoder_m, &decoder_m); - return ret; -} -/* - * upb::pb::TextPrinter - * - * OPT: This is not optimized at all. It uses printf() which parses the format - * string every time, and it allocates memory for every put. - */ - - -#include -#include -#include -#include -#include -#include - - -struct upb_textprinter { - upb_sink input_; - upb_bytessink *output_; - int indent_depth_; - bool single_line_; - void *subc; -}; - -#define CHECK(x) if ((x) < 0) goto err; - -static const char *shortname(const char *longname) { - const char *last = strrchr(longname, '.'); - return last ? last + 1 : longname; -} - -static int indent(upb_textprinter *p) { - int i; - if (!p->single_line_) - for (i = 0; i < p->indent_depth_; i++) - upb_bytessink_putbuf(p->output_, p->subc, " ", 2, NULL); - return 0; -} - -static int endfield(upb_textprinter *p) { - const char ch = (p->single_line_ ? ' ' : '\n'); - upb_bytessink_putbuf(p->output_, p->subc, &ch, 1, NULL); - return 0; -} - -static int putescaped(upb_textprinter *p, const char *buf, size_t len, - bool preserve_utf8) { - /* Based on CEscapeInternal() from Google's protobuf release. */ - char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf); - const char *end = buf + len; - - /* I think hex is prettier and more useful, but proto2 uses octal; should - * investigate whether it can parse hex also. */ - const bool use_hex = false; - bool last_hex_escape = false; /* true if last output char was \xNN */ - - for (; buf < end; buf++) { - bool is_hex_escape; - - if (dstend - dst < 4) { - upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL); - dst = dstbuf; - } - - is_hex_escape = false; - switch (*buf) { - case '\n': *(dst++) = '\\'; *(dst++) = 'n'; break; - case '\r': *(dst++) = '\\'; *(dst++) = 'r'; break; - case '\t': *(dst++) = '\\'; *(dst++) = 't'; break; - case '\"': *(dst++) = '\\'; *(dst++) = '\"'; break; - case '\'': *(dst++) = '\\'; *(dst++) = '\''; break; - case '\\': *(dst++) = '\\'; *(dst++) = '\\'; break; - default: - /* Note that if we emit \xNN and the buf character after that is a hex - * digit then that digit must be escaped too to prevent it being - * interpreted as part of the character code by C. */ - if ((!preserve_utf8 || (uint8_t)*buf < 0x80) && - (!isprint(*buf) || (last_hex_escape && isxdigit(*buf)))) { - sprintf(dst, (use_hex ? "\\x%02x" : "\\%03o"), (uint8_t)*buf); - is_hex_escape = use_hex; - dst += 4; - } else { - *(dst++) = *buf; break; - } - } - last_hex_escape = is_hex_escape; - } - /* Flush remaining data. */ - upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL); - return 0; -} - -bool putf(upb_textprinter *p, const char *fmt, ...) { - va_list args; - va_list args_copy; - char *str; - int written; - int len; - bool ok; - - va_start(args, fmt); - - /* Run once to get the length of the string. */ - _upb_va_copy(args_copy, args); - len = _upb_vsnprintf(NULL, 0, fmt, args_copy); - va_end(args_copy); - - /* + 1 for NULL terminator (vsprintf() requires it even if we don't). */ - str = upb_gmalloc(len + 1); - if (!str) return false; - written = vsprintf(str, fmt, args); - va_end(args); - UPB_ASSERT(written == len); - - ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL); - upb_gfree(str); - return ok; -} - - -/* handlers *******************************************************************/ - -static bool textprinter_startmsg(void *c, const void *hd) { - upb_textprinter *p = c; - UPB_UNUSED(hd); - if (p->indent_depth_ == 0) { - upb_bytessink_start(p->output_, 0, &p->subc); - } - return true; -} - -static bool textprinter_endmsg(void *c, const void *hd, upb_status *s) { - upb_textprinter *p = c; - UPB_UNUSED(hd); - UPB_UNUSED(s); - if (p->indent_depth_ == 0) { - upb_bytessink_end(p->output_); - } - return true; -} - -#define TYPE(name, ctype, fmt) \ - static bool textprinter_put ## name(void *closure, const void *handler_data, \ - ctype val) { \ - upb_textprinter *p = closure; \ - const upb_fielddef *f = handler_data; \ - CHECK(indent(p)); \ - putf(p, "%s: " fmt, upb_fielddef_name(f), val); \ - CHECK(endfield(p)); \ - return true; \ - err: \ - return false; \ -} - -static bool textprinter_putbool(void *closure, const void *handler_data, - bool val) { - upb_textprinter *p = closure; - const upb_fielddef *f = handler_data; - CHECK(indent(p)); - putf(p, "%s: %s", upb_fielddef_name(f), val ? "true" : "false"); - CHECK(endfield(p)); - return true; -err: - return false; -} - -#define STRINGIFY_HELPER(x) #x -#define STRINGIFY_MACROVAL(x) STRINGIFY_HELPER(x) - -TYPE(int32, int32_t, "%" PRId32) -TYPE(int64, int64_t, "%" PRId64) -TYPE(uint32, uint32_t, "%" PRIu32) -TYPE(uint64, uint64_t, "%" PRIu64) -TYPE(float, float, "%." STRINGIFY_MACROVAL(FLT_DIG) "g") -TYPE(double, double, "%." STRINGIFY_MACROVAL(DBL_DIG) "g") - -#undef TYPE - -/* Output a symbolic value from the enum if found, else just print as int32. */ -static bool textprinter_putenum(void *closure, const void *handler_data, - int32_t val) { - upb_textprinter *p = closure; - const upb_fielddef *f = handler_data; - const upb_enumdef *enum_def = upb_downcast_enumdef(upb_fielddef_subdef(f)); - const char *label = upb_enumdef_iton(enum_def, val); - if (label) { - indent(p); - putf(p, "%s: %s", upb_fielddef_name(f), label); - endfield(p); - } else { - if (!textprinter_putint32(closure, handler_data, val)) - return false; - } - return true; -} - -static void *textprinter_startstr(void *closure, const void *handler_data, - size_t size_hint) { - upb_textprinter *p = closure; - const upb_fielddef *f = handler_data; - UPB_UNUSED(size_hint); - indent(p); - putf(p, "%s: \"", upb_fielddef_name(f)); - return p; -} - -static bool textprinter_endstr(void *closure, const void *handler_data) { - upb_textprinter *p = closure; - UPB_UNUSED(handler_data); - putf(p, "\""); - endfield(p); - return true; -} - -static size_t textprinter_putstr(void *closure, const void *hd, const char *buf, - size_t len, const upb_bufhandle *handle) { - upb_textprinter *p = closure; - const upb_fielddef *f = hd; - UPB_UNUSED(handle); - CHECK(putescaped(p, buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING)); - return len; -err: - return 0; -} - -static void *textprinter_startsubmsg(void *closure, const void *handler_data) { - upb_textprinter *p = closure; - const char *name = handler_data; - CHECK(indent(p)); - putf(p, "%s {%c", name, p->single_line_ ? ' ' : '\n'); - p->indent_depth_++; - return p; -err: - return UPB_BREAK; -} - -static bool textprinter_endsubmsg(void *closure, const void *handler_data) { - upb_textprinter *p = closure; - UPB_UNUSED(handler_data); - p->indent_depth_--; - CHECK(indent(p)); - upb_bytessink_putbuf(p->output_, p->subc, "}", 1, NULL); - CHECK(endfield(p)); - return true; -err: - return false; -} - -static void onmreg(const void *c, upb_handlers *h) { - const upb_msgdef *m = upb_handlers_msgdef(h); - upb_msg_field_iter i; - UPB_UNUSED(c); - - upb_handlers_setstartmsg(h, textprinter_startmsg, NULL); - upb_handlers_setendmsg(h, textprinter_endmsg, NULL); - - for(upb_msg_field_begin(&i, m); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, f); - switch (upb_fielddef_type(f)) { - case UPB_TYPE_INT32: - upb_handlers_setint32(h, f, textprinter_putint32, &attr); - break; - case UPB_TYPE_INT64: - upb_handlers_setint64(h, f, textprinter_putint64, &attr); - break; - case UPB_TYPE_UINT32: - upb_handlers_setuint32(h, f, textprinter_putuint32, &attr); - break; - case UPB_TYPE_UINT64: - upb_handlers_setuint64(h, f, textprinter_putuint64, &attr); - break; - case UPB_TYPE_FLOAT: - upb_handlers_setfloat(h, f, textprinter_putfloat, &attr); - break; - case UPB_TYPE_DOUBLE: - upb_handlers_setdouble(h, f, textprinter_putdouble, &attr); - break; - case UPB_TYPE_BOOL: - upb_handlers_setbool(h, f, textprinter_putbool, &attr); - break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - upb_handlers_setstartstr(h, f, textprinter_startstr, &attr); - upb_handlers_setstring(h, f, textprinter_putstr, &attr); - upb_handlers_setendstr(h, f, textprinter_endstr, &attr); - break; - case UPB_TYPE_MESSAGE: { - const char *name = - upb_fielddef_istagdelim(f) - ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f))) - : upb_fielddef_name(f); - upb_handlerattr_sethandlerdata(&attr, name); - upb_handlers_setstartsubmsg(h, f, textprinter_startsubmsg, &attr); - upb_handlers_setendsubmsg(h, f, textprinter_endsubmsg, &attr); - break; - } - case UPB_TYPE_ENUM: - upb_handlers_setint32(h, f, textprinter_putenum, &attr); - break; - } - } -} - -static void textprinter_reset(upb_textprinter *p, bool single_line) { - p->single_line_ = single_line; - p->indent_depth_ = 0; -} - - -/* Public API *****************************************************************/ - -upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h, - upb_bytessink *output) { - upb_textprinter *p = upb_env_malloc(env, sizeof(upb_textprinter)); - if (!p) return NULL; - - p->output_ = output; - upb_sink_reset(&p->input_, h, p); - textprinter_reset(p, false); - - return p; -} - -const upb_handlers *upb_textprinter_newhandlers(const upb_msgdef *m, - const void *owner) { - return upb_handlers_newfrozen(m, owner, &onmreg, NULL); -} - -upb_sink *upb_textprinter_input(upb_textprinter *p) { return &p->input_; } - -void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) { - p->single_line_ = single_line; -} - - -/* Index is descriptor type. */ -const uint8_t upb_pb_native_wire_types[] = { - UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */ - UPB_WIRE_TYPE_64BIT, /* DOUBLE */ - UPB_WIRE_TYPE_32BIT, /* FLOAT */ - UPB_WIRE_TYPE_VARINT, /* INT64 */ - UPB_WIRE_TYPE_VARINT, /* UINT64 */ - UPB_WIRE_TYPE_VARINT, /* INT32 */ - UPB_WIRE_TYPE_64BIT, /* FIXED64 */ - UPB_WIRE_TYPE_32BIT, /* FIXED32 */ - UPB_WIRE_TYPE_VARINT, /* BOOL */ - UPB_WIRE_TYPE_DELIMITED, /* STRING */ - UPB_WIRE_TYPE_START_GROUP, /* GROUP */ - UPB_WIRE_TYPE_DELIMITED, /* MESSAGE */ - UPB_WIRE_TYPE_DELIMITED, /* BYTES */ - UPB_WIRE_TYPE_VARINT, /* UINT32 */ - UPB_WIRE_TYPE_VARINT, /* ENUM */ - UPB_WIRE_TYPE_32BIT, /* SFIXED32 */ - UPB_WIRE_TYPE_64BIT, /* SFIXED64 */ - UPB_WIRE_TYPE_VARINT, /* SINT32 */ - UPB_WIRE_TYPE_VARINT, /* SINT64 */ -}; - -/* A basic branch-based decoder, uses 32-bit values to get good performance - * on 32-bit architectures (but performs well on 64-bits also). - * This scheme comes from the original Google Protobuf implementation - * (proto2). */ -upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r) { - upb_decoderet err = {NULL, 0}; - const char *p = r.p; - uint32_t low = (uint32_t)r.val; - uint32_t high = 0; - uint32_t b; - b = *(p++); low |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done; - b = *(p++); low |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done; - b = *(p++); low |= (b & 0x7fU) << 28; - high = (b & 0x7fU) >> 4; if (!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7fU) << 3; if (!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7fU) << 10; if (!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7fU) << 17; if (!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7fU) << 24; if (!(b & 0x80)) goto done; - b = *(p++); high |= (b & 0x7fU) << 31; if (!(b & 0x80)) goto done; - return err; - -done: - r.val = ((uint64_t)high << 32) | low; - r.p = p; - return r; -} - -/* Like the previous, but uses 64-bit values. */ -upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r) { - const char *p = r.p; - uint64_t val = r.val; - uint64_t b; - upb_decoderet err = {NULL, 0}; - b = *(p++); val |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7fU) << 28; if (!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7fU) << 35; if (!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7fU) << 42; if (!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7fU) << 49; if (!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7fU) << 56; if (!(b & 0x80)) goto done; - b = *(p++); val |= (b & 0x7fU) << 63; if (!(b & 0x80)) goto done; - return err; - -done: - r.val = val; - r.p = p; - return r; -} - -#line 1 "upb/json/parser.rl" -/* -** upb::json::Parser (upb_json_parser) -** -** A parser that uses the Ragel State Machine Compiler to generate -** the finite automata. -** -** Ragel only natively handles regular languages, but we can manually -** program it a bit to handle context-free languages like JSON, by using -** the "fcall" and "fret" constructs. -** -** This parser can handle the basics, but needs several things to be fleshed -** out: -** -** - handling of unicode escape sequences (including high surrogate pairs). -** - properly check and report errors for unknown fields, stack overflow, -** improper array nesting (or lack of nesting). -** - handling of base64 sequences with padding characters. -** - handling of push-back (non-success returns from sink functions). -** - handling of keys/escape-sequences/etc that span input buffers. -*/ - -#include -#include -#include -#include -#include -#include - - -#define UPB_JSON_MAX_DEPTH 64 - -typedef struct { - upb_sink sink; - - /* The current message in which we're parsing, and the field whose value we're - * expecting next. */ - const upb_msgdef *m; - const upb_fielddef *f; - - /* The table mapping json name to fielddef for this message. */ - upb_strtable *name_table; - - /* We are in a repeated-field context, ready to emit mapentries as - * submessages. This flag alters the start-of-object (open-brace) behavior to - * begin a sequence of mapentry messages rather than a single submessage. */ - bool is_map; - - /* We are in a map-entry message context. This flag is set when parsing the - * value field of a single map entry and indicates to all value-field parsers - * (subobjects, strings, numbers, and bools) that the map-entry submessage - * should end as soon as the value is parsed. */ - bool is_mapentry; - - /* If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent - * message's map field that we're currently parsing. This differs from |f| - * because |f| is the field in the *current* message (i.e., the map-entry - * message itself), not the parent's field that leads to this map. */ - const upb_fielddef *mapfield; -} upb_jsonparser_frame; - -struct upb_json_parser { - upb_env *env; - const upb_json_parsermethod *method; - upb_bytessink input_; - - /* Stack to track the JSON scopes we are in. */ - upb_jsonparser_frame stack[UPB_JSON_MAX_DEPTH]; - upb_jsonparser_frame *top; - upb_jsonparser_frame *limit; - - upb_status status; - - /* Ragel's internal parsing stack for the parsing state machine. */ - int current_state; - int parser_stack[UPB_JSON_MAX_DEPTH]; - int parser_top; - - /* The handle for the current buffer. */ - const upb_bufhandle *handle; - - /* Accumulate buffer. See details in parser.rl. */ - const char *accumulated; - size_t accumulated_len; - char *accumulate_buf; - size_t accumulate_buf_size; - - /* Multi-part text data. See details in parser.rl. */ - int multipart_state; - upb_selector_t string_selector; - - /* Input capture. See details in parser.rl. */ - const char *capture; - - /* Intermediate result of parsing a unicode escape sequence. */ - uint32_t digit; -}; - -struct upb_json_parsermethod { - upb_refcounted base; - - upb_byteshandler input_handler_; - - /* Mainly for the purposes of refcounting, so all the fielddefs we point - * to stay alive. */ - const upb_msgdef *msg; - - /* Keys are upb_msgdef*, values are upb_strtable (json_name -> fielddef) */ - upb_inttable name_tables; -}; - -#define PARSER_CHECK_RETURN(x) if (!(x)) return false - -/* Used to signal that a capture has been suspended. */ -static char suspend_capture; - -static upb_selector_t getsel_for_handlertype(upb_json_parser *p, - upb_handlertype_t type) { - upb_selector_t sel; - bool ok = upb_handlers_getselector(p->top->f, type, &sel); - UPB_ASSERT(ok); - return sel; -} - -static upb_selector_t parser_getsel(upb_json_parser *p) { - return getsel_for_handlertype( - p, upb_handlers_getprimitivehandlertype(p->top->f)); -} - -static bool check_stack(upb_json_parser *p) { - if ((p->top + 1) == p->limit) { - upb_status_seterrmsg(&p->status, "Nesting too deep"); - upb_env_reporterror(p->env, &p->status); - return false; - } - - return true; -} - -static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) { - upb_value v; - bool ok = upb_inttable_lookupptr(&p->method->name_tables, frame->m, &v); - UPB_ASSERT(ok); - frame->name_table = upb_value_getptr(v); -} - -/* There are GCC/Clang built-ins for overflow checking which we could start - * using if there was any performance benefit to it. */ - -static bool checked_add(size_t a, size_t b, size_t *c) { - if (SIZE_MAX - a < b) return false; - *c = a + b; - return true; -} - -static size_t saturating_multiply(size_t a, size_t b) { - /* size_t is unsigned, so this is defined behavior even on overflow. */ - size_t ret = a * b; - if (b != 0 && ret / b != a) { - ret = SIZE_MAX; - } - return ret; -} - - -/* Base64 decoding ************************************************************/ - -/* TODO(haberman): make this streaming. */ - -static const signed char b64table[] = { - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */, - 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, - 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1, - -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, - 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, - 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, - 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1, - -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, - 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, - 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, - 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 -}; - -/* Returns the table value sign-extended to 32 bits. Knowing that the upper - * bits will be 1 for unrecognized characters makes it easier to check for - * this error condition later (see below). */ -int32_t b64lookup(unsigned char ch) { return b64table[ch]; } - -/* Returns true if the given character is not a valid base64 character or - * padding. */ -bool nonbase64(unsigned char ch) { return b64lookup(ch) == -1 && ch != '='; } - -static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr, - size_t len) { - const char *limit = ptr + len; - for (; ptr < limit; ptr += 4) { - uint32_t val; - char output[3]; - - if (limit - ptr < 4) { - upb_status_seterrf(&p->status, - "Base64 input for bytes field not a multiple of 4: %s", - upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); - return false; - } - - val = b64lookup(ptr[0]) << 18 | - b64lookup(ptr[1]) << 12 | - b64lookup(ptr[2]) << 6 | - b64lookup(ptr[3]); - - /* Test the upper bit; returns true if any of the characters returned -1. */ - if (val & 0x80000000) { - goto otherchar; - } - - output[0] = val >> 16; - output[1] = (val >> 8) & 0xff; - output[2] = val & 0xff; - upb_sink_putstring(&p->top->sink, sel, output, 3, NULL); - } - return true; - -otherchar: - if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) || - nonbase64(ptr[3]) ) { - upb_status_seterrf(&p->status, - "Non-base64 characters in bytes field: %s", - upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); - return false; - } if (ptr[2] == '=') { - uint32_t val; - char output; - - /* Last group contains only two input bytes, one output byte. */ - if (ptr[0] == '=' || ptr[1] == '=' || ptr[3] != '=') { - goto badpadding; - } - - val = b64lookup(ptr[0]) << 18 | - b64lookup(ptr[1]) << 12; - - UPB_ASSERT(!(val & 0x80000000)); - output = val >> 16; - upb_sink_putstring(&p->top->sink, sel, &output, 1, NULL); - return true; - } else { - uint32_t val; - char output[2]; - - /* Last group contains only three input bytes, two output bytes. */ - if (ptr[0] == '=' || ptr[1] == '=' || ptr[2] == '=') { - goto badpadding; - } - - val = b64lookup(ptr[0]) << 18 | - b64lookup(ptr[1]) << 12 | - b64lookup(ptr[2]) << 6; - - output[0] = val >> 16; - output[1] = (val >> 8) & 0xff; - upb_sink_putstring(&p->top->sink, sel, output, 2, NULL); - return true; - } - -badpadding: - upb_status_seterrf(&p->status, - "Incorrect base64 padding for field: %s (%.*s)", - upb_fielddef_name(p->top->f), - 4, ptr); - upb_env_reporterror(p->env, &p->status); - return false; -} - - -/* Accumulate buffer **********************************************************/ - -/* Functionality for accumulating a buffer. - * - * Some parts of the parser need an entire value as a contiguous string. For - * example, to look up a member name in a hash table, or to turn a string into - * a number, the relevant library routines need the input string to be in - * contiguous memory, even if the value spanned two or more buffers in the - * input. These routines handle that. - * - * In the common case we can just point to the input buffer to get this - * contiguous string and avoid any actual copy. So we optimistically begin - * this way. But there are a few cases where we must instead copy into a - * separate buffer: - * - * 1. The string was not contiguous in the input (it spanned buffers). - * - * 2. The string included escape sequences that need to be interpreted to get - * the true value in a contiguous buffer. */ - -static void assert_accumulate_empty(upb_json_parser *p) { - UPB_ASSERT(p->accumulated == NULL); - UPB_ASSERT(p->accumulated_len == 0); -} - -static void accumulate_clear(upb_json_parser *p) { - p->accumulated = NULL; - p->accumulated_len = 0; -} - -/* Used internally by accumulate_append(). */ -static bool accumulate_realloc(upb_json_parser *p, size_t need) { - void *mem; - size_t old_size = p->accumulate_buf_size; - size_t new_size = UPB_MAX(old_size, 128); - while (new_size < need) { - new_size = saturating_multiply(new_size, 2); - } - - mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size); - if (!mem) { - upb_status_seterrmsg(&p->status, "Out of memory allocating buffer."); - upb_env_reporterror(p->env, &p->status); - return false; - } - - p->accumulate_buf = mem; - p->accumulate_buf_size = new_size; - return true; -} - -/* Logically appends the given data to the append buffer. - * If "can_alias" is true, we will try to avoid actually copying, but the buffer - * must be valid until the next accumulate_append() call (if any). */ -static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len, - bool can_alias) { - size_t need; - - if (!p->accumulated && can_alias) { - p->accumulated = buf; - p->accumulated_len = len; - return true; - } - - if (!checked_add(p->accumulated_len, len, &need)) { - upb_status_seterrmsg(&p->status, "Integer overflow."); - upb_env_reporterror(p->env, &p->status); - return false; - } - - if (need > p->accumulate_buf_size && !accumulate_realloc(p, need)) { - return false; - } - - if (p->accumulated != p->accumulate_buf) { - memcpy(p->accumulate_buf, p->accumulated, p->accumulated_len); - p->accumulated = p->accumulate_buf; - } - - memcpy(p->accumulate_buf + p->accumulated_len, buf, len); - p->accumulated_len += len; - return true; -} - -/* Returns a pointer to the data accumulated since the last accumulate_clear() - * call, and writes the length to *len. This with point either to the input - * buffer or a temporary accumulate buffer. */ -static const char *accumulate_getptr(upb_json_parser *p, size_t *len) { - UPB_ASSERT(p->accumulated); - *len = p->accumulated_len; - return p->accumulated; -} - - -/* Mult-part text data ********************************************************/ - -/* When we have text data in the input, it can often come in multiple segments. - * For example, there may be some raw string data followed by an escape - * sequence. The two segments are processed with different logic. Also buffer - * seams in the input can cause multiple segments. - * - * As we see segments, there are two main cases for how we want to process them: - * - * 1. we want to push the captured input directly to string handlers. - * - * 2. we need to accumulate all the parts into a contiguous buffer for further - * processing (field name lookup, string->number conversion, etc). */ - -/* This is the set of states for p->multipart_state. */ -enum { - /* We are not currently processing multipart data. */ - MULTIPART_INACTIVE = 0, - - /* We are processing multipart data by accumulating it into a contiguous - * buffer. */ - MULTIPART_ACCUMULATE = 1, - - /* We are processing multipart data by pushing each part directly to the - * current string handlers. */ - MULTIPART_PUSHEAGERLY = 2 -}; - -/* Start a multi-part text value where we accumulate the data for processing at - * the end. */ -static void multipart_startaccum(upb_json_parser *p) { - assert_accumulate_empty(p); - UPB_ASSERT(p->multipart_state == MULTIPART_INACTIVE); - p->multipart_state = MULTIPART_ACCUMULATE; -} - -/* Start a multi-part text value where we immediately push text data to a string - * value with the given selector. */ -static void multipart_start(upb_json_parser *p, upb_selector_t sel) { - assert_accumulate_empty(p); - UPB_ASSERT(p->multipart_state == MULTIPART_INACTIVE); - p->multipart_state = MULTIPART_PUSHEAGERLY; - p->string_selector = sel; -} - -static bool multipart_text(upb_json_parser *p, const char *buf, size_t len, - bool can_alias) { - switch (p->multipart_state) { - case MULTIPART_INACTIVE: - upb_status_seterrmsg( - &p->status, "Internal error: unexpected state MULTIPART_INACTIVE"); - upb_env_reporterror(p->env, &p->status); - return false; - - case MULTIPART_ACCUMULATE: - if (!accumulate_append(p, buf, len, can_alias)) { - return false; - } - break; - - case MULTIPART_PUSHEAGERLY: { - const upb_bufhandle *handle = can_alias ? p->handle : NULL; - upb_sink_putstring(&p->top->sink, p->string_selector, buf, len, handle); - break; - } - } - - return true; -} - -/* Note: this invalidates the accumulate buffer! Call only after reading its - * contents. */ -static void multipart_end(upb_json_parser *p) { - UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE); - p->multipart_state = MULTIPART_INACTIVE; - accumulate_clear(p); -} - - -/* Input capture **************************************************************/ - -/* Functionality for capturing a region of the input as text. Gracefully - * handles the case where a buffer seam occurs in the middle of the captured - * region. */ - -static void capture_begin(upb_json_parser *p, const char *ptr) { - UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE); - UPB_ASSERT(p->capture == NULL); - p->capture = ptr; -} - -static bool capture_end(upb_json_parser *p, const char *ptr) { - UPB_ASSERT(p->capture); - if (multipart_text(p, p->capture, ptr - p->capture, true)) { - p->capture = NULL; - return true; - } else { - return false; - } -} - -/* This is called at the end of each input buffer (ie. when we have hit a - * buffer seam). If we are in the middle of capturing the input, this - * processes the unprocessed capture region. */ -static void capture_suspend(upb_json_parser *p, const char **ptr) { - if (!p->capture) return; - - if (multipart_text(p, p->capture, *ptr - p->capture, false)) { - /* We use this as a signal that we were in the middle of capturing, and - * that capturing should resume at the beginning of the next buffer. - * - * We can't use *ptr here, because we have no guarantee that this pointer - * will be valid when we resume (if the underlying memory is freed, then - * using the pointer at all, even to compare to NULL, is likely undefined - * behavior). */ - p->capture = &suspend_capture; - } else { - /* Need to back up the pointer to the beginning of the capture, since - * we were not able to actually preserve it. */ - *ptr = p->capture; - } -} - -static void capture_resume(upb_json_parser *p, const char *ptr) { - if (p->capture) { - UPB_ASSERT(p->capture == &suspend_capture); - p->capture = ptr; - } -} - - -/* Callbacks from the parser **************************************************/ - -/* These are the functions called directly from the parser itself. - * We define these in the same order as their declarations in the parser. */ - -static char escape_char(char in) { - switch (in) { - case 'r': return '\r'; - case 't': return '\t'; - case 'n': return '\n'; - case 'f': return '\f'; - case 'b': return '\b'; - case '/': return '/'; - case '"': return '"'; - case '\\': return '\\'; - default: - UPB_ASSERT(0); - return 'x'; - } -} - -static bool escape(upb_json_parser *p, const char *ptr) { - char ch = escape_char(*ptr); - return multipart_text(p, &ch, 1, false); -} - -static void start_hex(upb_json_parser *p) { - p->digit = 0; -} - -static void hexdigit(upb_json_parser *p, const char *ptr) { - char ch = *ptr; - - p->digit <<= 4; - - if (ch >= '0' && ch <= '9') { - p->digit += (ch - '0'); - } else if (ch >= 'a' && ch <= 'f') { - p->digit += ((ch - 'a') + 10); - } else { - UPB_ASSERT(ch >= 'A' && ch <= 'F'); - p->digit += ((ch - 'A') + 10); - } -} - -static bool end_hex(upb_json_parser *p) { - uint32_t codepoint = p->digit; - - /* emit the codepoint as UTF-8. */ - char utf8[3]; /* support \u0000 -- \uFFFF -- need only three bytes. */ - int length = 0; - if (codepoint <= 0x7F) { - utf8[0] = codepoint; - length = 1; - } else if (codepoint <= 0x07FF) { - utf8[1] = (codepoint & 0x3F) | 0x80; - codepoint >>= 6; - utf8[0] = (codepoint & 0x1F) | 0xC0; - length = 2; - } else /* codepoint <= 0xFFFF */ { - utf8[2] = (codepoint & 0x3F) | 0x80; - codepoint >>= 6; - utf8[1] = (codepoint & 0x3F) | 0x80; - codepoint >>= 6; - utf8[0] = (codepoint & 0x0F) | 0xE0; - length = 3; - } - /* TODO(haberman): Handle high surrogates: if codepoint is a high surrogate - * we have to wait for the next escape to get the full code point). */ - - return multipart_text(p, utf8, length, false); -} - -static void start_text(upb_json_parser *p, const char *ptr) { - capture_begin(p, ptr); -} - -static bool end_text(upb_json_parser *p, const char *ptr) { - return capture_end(p, ptr); -} - -static void start_number(upb_json_parser *p, const char *ptr) { - multipart_startaccum(p); - capture_begin(p, ptr); -} - -static bool parse_number(upb_json_parser *p, bool is_quoted); - -static bool end_number(upb_json_parser *p, const char *ptr) { - if (!capture_end(p, ptr)) { - return false; - } - - return parse_number(p, false); -} - -static bool parse_number_from_buffer(upb_json_parser *p, const char *buf, - const char *bufend, bool is_quoted) { - size_t len = bufend - buf; - char *end; - upb_fieldtype_t type = upb_fielddef_type(p->top->f); - double val; - double dummy; - - if (buf[0] == ' ') { - return false; - } - - /* For integer types, first try parsing with integer-specific routines. - * If these succeed, they will be more accurate for int64/uint64 than - * strtod(). - */ - switch (type) { - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: { - long val = strtol(buf, &end, 0); - if (errno == ERANGE || end != bufend) { - break; - } else if (val > INT32_MAX || val < INT32_MIN) { - return false; - } else { - upb_sink_putint32(&p->top->sink, parser_getsel(p), val); - return true; - } - } - case UPB_TYPE_UINT32: { - unsigned long val = strtoul(buf, &end, 0); - if (end != bufend) { - break; - } else if (val > UINT32_MAX || errno == ERANGE) { - return false; - } else { - upb_sink_putuint32(&p->top->sink, parser_getsel(p), val); - return true; - } - } - /* XXX: We can't handle [u]int64 properly on 32-bit machines because - * strto[u]ll isn't in C89. */ - case UPB_TYPE_INT64: { - long val = strtol(buf, &end, 0); - if (errno == ERANGE || end != bufend) { - break; - } else { - upb_sink_putint64(&p->top->sink, parser_getsel(p), val); - return true; - } - } - case UPB_TYPE_UINT64: { - unsigned long val = strtoul(p->accumulated, &end, 0); - if (end != bufend) { - break; - } else if (errno == ERANGE) { - return false; - } else { - upb_sink_putuint64(&p->top->sink, parser_getsel(p), val); - return true; - } - } - default: - break; - } - - if (type != UPB_TYPE_DOUBLE && type != UPB_TYPE_FLOAT && is_quoted) { - /* Quoted numbers shouldn't support double forms for integer types. */ - return false; - } - - if (len == strlen("Infinity") && strcmp(buf, "Infinity") == 0) { - /* C89 does not have an INFINITY macro. */ - val = 1.0 / 0.0; - } else if (len == strlen("-Infinity") && strcmp(buf, "-Infinity") == 0) { - val = -1.0 / 0.0; - } else { - val = strtod(buf, &end); - if (errno == ERANGE || end != bufend) { - return false; - } - } - - switch (type) { -#define CASE(capitaltype, smalltype, min, max) \ - case UPB_TYPE_ ## capitaltype: { \ - if (modf(val, &dummy) != 0 || val > max || val < min) { \ - return false; \ - } else { \ - upb_sink_put ## smalltype(&p->top->sink, parser_getsel(p), val); \ - return true; \ - } \ - break; \ - } - case UPB_TYPE_ENUM: - CASE(INT32, int32, INT32_MIN, INT32_MAX); - CASE(INT64, int64, INT64_MIN, INT64_MAX); - CASE(UINT32, uint32, 0, UINT32_MAX); - CASE(UINT64, uint64, 0, UINT64_MAX); -#undef CASE - - case UPB_TYPE_DOUBLE: - upb_sink_putdouble(&p->top->sink, parser_getsel(p), val); - return true; - case UPB_TYPE_FLOAT: - if (false /*val > FLT_MAX || val < -FLT_MAX*/) { - return false; - } else { - upb_sink_putfloat(&p->top->sink, parser_getsel(p), val); - return true; - } - default: - return false; - } -} - -static bool parse_number(upb_json_parser *p, bool is_quoted) { - size_t len; - const char *buf; - const char *bufend; - - /* strtol() and friends unfortunately do not support specifying the length of - * the input string, so we need to force a copy into a NULL-terminated buffer. */ - if (!multipart_text(p, "\0", 1, false)) { - return false; - } - - buf = accumulate_getptr(p, &len); - bufend = buf + len - 1; /* One for NULL. */ - errno = 0; - - if (parse_number_from_buffer(p, buf, bufend, is_quoted)) { - multipart_end(p); - return true; - } else { - upb_status_seterrf(&p->status, "error parsing number: %s", buf); - upb_env_reporterror(p->env, &p->status); - multipart_end(p); - return false; - } -} - -static bool parser_putbool(upb_json_parser *p, bool val) { - bool ok; - - if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) { - upb_status_seterrf(&p->status, - "Boolean value specified for non-bool field: %s", - upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); - return false; - } - - ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val); - UPB_ASSERT(ok); - - return true; -} - -static bool start_stringval(upb_json_parser *p) { - UPB_ASSERT(p->top->f); - - if (upb_fielddef_isstring(p->top->f)) { - upb_jsonparser_frame *inner; - upb_selector_t sel; - - if (!check_stack(p)) return false; - - /* Start a new parser frame: parser frames correspond one-to-one with - * handler frames, and string events occur in a sub-frame. */ - inner = p->top + 1; - sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR); - upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink); - inner->m = p->top->m; - inner->f = p->top->f; - inner->name_table = NULL; - inner->is_map = false; - inner->is_mapentry = false; - p->top = inner; - - if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) { - /* For STRING fields we push data directly to the handlers as it is - * parsed. We don't do this yet for BYTES fields, because our base64 - * decoder is not streaming. - * - * TODO(haberman): make base64 decoding streaming also. */ - multipart_start(p, getsel_for_handlertype(p, UPB_HANDLER_STRING)); - return true; - } else { - multipart_startaccum(p); - return true; - } - } else if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL && - upb_fielddef_type(p->top->f) != UPB_TYPE_MESSAGE) { - /* No need to push a frame -- numeric values in quotes remain in the - * current parser frame. These values must accmulate so we can convert - * them all at once at the end. */ - multipart_startaccum(p); - return true; - } else { - upb_status_seterrf(&p->status, - "String specified for bool or submessage field: %s", - upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); - return false; - } -} - -static bool end_stringval(upb_json_parser *p) { - bool ok = true; - - switch (upb_fielddef_type(p->top->f)) { - case UPB_TYPE_BYTES: - if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING), - p->accumulated, p->accumulated_len)) { - return false; - } - /* Fall through. */ - - case UPB_TYPE_STRING: { - upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR); - p->top--; - upb_sink_endstr(&p->top->sink, sel); - break; - } - - case UPB_TYPE_ENUM: { - /* Resolve enum symbolic name to integer value. */ - const upb_enumdef *enumdef = - (const upb_enumdef*)upb_fielddef_subdef(p->top->f); - - size_t len; - const char *buf = accumulate_getptr(p, &len); - - int32_t int_val = 0; - ok = upb_enumdef_ntoi(enumdef, buf, len, &int_val); - - if (ok) { - upb_selector_t sel = parser_getsel(p); - upb_sink_putint32(&p->top->sink, sel, int_val); - } else { - upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf); - upb_env_reporterror(p->env, &p->status); - } - - break; - } - - case UPB_TYPE_INT32: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT32: - case UPB_TYPE_UINT64: - case UPB_TYPE_DOUBLE: - case UPB_TYPE_FLOAT: - ok = parse_number(p, true); - break; - - default: - UPB_ASSERT(false); - upb_status_seterrmsg(&p->status, "Internal error in JSON decoder"); - upb_env_reporterror(p->env, &p->status); - ok = false; - break; - } - - multipart_end(p); - - return ok; -} - -static void start_member(upb_json_parser *p) { - UPB_ASSERT(!p->top->f); - multipart_startaccum(p); -} - -/* Helper: invoked during parse_mapentry() to emit the mapentry message's key - * field based on the current contents of the accumulate buffer. */ -static bool parse_mapentry_key(upb_json_parser *p) { - - size_t len; - const char *buf = accumulate_getptr(p, &len); - - /* Emit the key field. We do a bit of ad-hoc parsing here because the - * parser state machine has already decided that this is a string field - * name, and we are reinterpreting it as some arbitrary key type. In - * particular, integer and bool keys are quoted, so we need to parse the - * quoted string contents here. */ - - p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY); - if (p->top->f == NULL) { - upb_status_seterrmsg(&p->status, "mapentry message has no key"); - upb_env_reporterror(p->env, &p->status); - return false; - } - switch (upb_fielddef_type(p->top->f)) { - case UPB_TYPE_INT32: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT32: - case UPB_TYPE_UINT64: - /* Invoke end_number. The accum buffer has the number's text already. */ - if (!parse_number(p, true)) { - return false; - } - break; - case UPB_TYPE_BOOL: - if (len == 4 && !strncmp(buf, "true", 4)) { - if (!parser_putbool(p, true)) { - return false; - } - } else if (len == 5 && !strncmp(buf, "false", 5)) { - if (!parser_putbool(p, false)) { - return false; - } - } else { - upb_status_seterrmsg(&p->status, - "Map bool key not 'true' or 'false'"); - upb_env_reporterror(p->env, &p->status); - return false; - } - multipart_end(p); - break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - upb_sink subsink; - upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR); - upb_sink_startstr(&p->top->sink, sel, len, &subsink); - sel = getsel_for_handlertype(p, UPB_HANDLER_STRING); - upb_sink_putstring(&subsink, sel, buf, len, NULL); - sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR); - upb_sink_endstr(&p->top->sink, sel); - multipart_end(p); - break; - } - default: - upb_status_seterrmsg(&p->status, "Invalid field type for map key"); - upb_env_reporterror(p->env, &p->status); - return false; - } - - return true; -} - -/* Helper: emit one map entry (as a submessage in the map field sequence). This - * is invoked from end_membername(), at the end of the map entry's key string, - * with the map key in the accumulate buffer. It parses the key from that - * buffer, emits the handler calls to start the mapentry submessage (setting up - * its subframe in the process), and sets up state in the subframe so that the - * value parser (invoked next) will emit the mapentry's value field and then - * end the mapentry message. */ - -static bool handle_mapentry(upb_json_parser *p) { - const upb_fielddef *mapfield; - const upb_msgdef *mapentrymsg; - upb_jsonparser_frame *inner; - upb_selector_t sel; - - /* Map entry: p->top->sink is the seq frame, so we need to start a frame - * for the mapentry itself, and then set |f| in that frame so that the map - * value field is parsed, and also set a flag to end the frame after the - * map-entry value is parsed. */ - if (!check_stack(p)) return false; - - mapfield = p->top->mapfield; - mapentrymsg = upb_fielddef_msgsubdef(mapfield); - - inner = p->top + 1; - p->top->f = mapfield; - sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG); - upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink); - inner->m = mapentrymsg; - inner->name_table = NULL; - inner->mapfield = mapfield; - inner->is_map = false; - - /* Don't set this to true *yet* -- we reuse parsing handlers below to push - * the key field value to the sink, and these handlers will pop the frame - * if they see is_mapentry (when invoked by the parser state machine, they - * would have just seen the map-entry value, not key). */ - inner->is_mapentry = false; - p->top = inner; - - /* send STARTMSG in submsg frame. */ - upb_sink_startmsg(&p->top->sink); - - parse_mapentry_key(p); - - /* Set up the value field to receive the map-entry value. */ - p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_VALUE); - p->top->is_mapentry = true; /* set up to pop frame after value is parsed. */ - p->top->mapfield = mapfield; - if (p->top->f == NULL) { - upb_status_seterrmsg(&p->status, "mapentry message has no value"); - upb_env_reporterror(p->env, &p->status); - return false; - } - - return true; -} - -static bool end_membername(upb_json_parser *p) { - UPB_ASSERT(!p->top->f); - - if (p->top->is_map) { - return handle_mapentry(p); - } else { - size_t len; - const char *buf = accumulate_getptr(p, &len); - upb_value v; - - if (upb_strtable_lookup2(p->top->name_table, buf, len, &v)) { - p->top->f = upb_value_getconstptr(v); - multipart_end(p); - - return true; - } else { - /* TODO(haberman): Ignore unknown fields if requested/configured to do - * so. */ - upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf); - upb_env_reporterror(p->env, &p->status); - return false; - } - } -} - -static void end_member(upb_json_parser *p) { - /* If we just parsed a map-entry value, end that frame too. */ - if (p->top->is_mapentry) { - upb_status s = UPB_STATUS_INIT; - upb_selector_t sel; - bool ok; - const upb_fielddef *mapfield; - - UPB_ASSERT(p->top > p->stack); - /* send ENDMSG on submsg. */ - upb_sink_endmsg(&p->top->sink, &s); - mapfield = p->top->mapfield; - - /* send ENDSUBMSG in repeated-field-of-mapentries frame. */ - p->top--; - ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel); - UPB_ASSERT(ok); - upb_sink_endsubmsg(&p->top->sink, sel); - } - - p->top->f = NULL; -} - -static bool start_subobject(upb_json_parser *p) { - UPB_ASSERT(p->top->f); - - if (upb_fielddef_ismap(p->top->f)) { - upb_jsonparser_frame *inner; - upb_selector_t sel; - - /* Beginning of a map. Start a new parser frame in a repeated-field - * context. */ - if (!check_stack(p)) return false; - - inner = p->top + 1; - sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ); - upb_sink_startseq(&p->top->sink, sel, &inner->sink); - inner->m = upb_fielddef_msgsubdef(p->top->f); - inner->name_table = NULL; - inner->mapfield = p->top->f; - inner->f = NULL; - inner->is_map = true; - inner->is_mapentry = false; - p->top = inner; - - return true; - } else if (upb_fielddef_issubmsg(p->top->f)) { - upb_jsonparser_frame *inner; - upb_selector_t sel; - - /* Beginning of a subobject. Start a new parser frame in the submsg - * context. */ - if (!check_stack(p)) return false; - - inner = p->top + 1; - - sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG); - upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink); - inner->m = upb_fielddef_msgsubdef(p->top->f); - set_name_table(p, inner); - inner->f = NULL; - inner->is_map = false; - inner->is_mapentry = false; - p->top = inner; - - return true; - } else { - upb_status_seterrf(&p->status, - "Object specified for non-message/group field: %s", - upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); - return false; - } -} - -static void end_subobject(upb_json_parser *p) { - if (p->top->is_map) { - upb_selector_t sel; - p->top--; - sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ); - upb_sink_endseq(&p->top->sink, sel); - } else { - upb_selector_t sel; - p->top--; - sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG); - upb_sink_endsubmsg(&p->top->sink, sel); - } -} - -static bool start_array(upb_json_parser *p) { - upb_jsonparser_frame *inner; - upb_selector_t sel; - - UPB_ASSERT(p->top->f); - - if (!upb_fielddef_isseq(p->top->f)) { - upb_status_seterrf(&p->status, - "Array specified for non-repeated field: %s", - upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); - return false; - } - - if (!check_stack(p)) return false; - - inner = p->top + 1; - sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ); - upb_sink_startseq(&p->top->sink, sel, &inner->sink); - inner->m = p->top->m; - inner->name_table = NULL; - inner->f = p->top->f; - inner->is_map = false; - inner->is_mapentry = false; - p->top = inner; - - return true; -} - -static void end_array(upb_json_parser *p) { - upb_selector_t sel; - - UPB_ASSERT(p->top > p->stack); - - p->top--; - sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ); - upb_sink_endseq(&p->top->sink, sel); -} - -static void start_object(upb_json_parser *p) { - if (!p->top->is_map) { - upb_sink_startmsg(&p->top->sink); - } -} - -static void end_object(upb_json_parser *p) { - if (!p->top->is_map) { - upb_status status; - upb_status_clear(&status); - upb_sink_endmsg(&p->top->sink, &status); - if (!upb_ok(&status)) { - upb_env_reporterror(p->env, &status); - } - } -} - - -#define CHECK_RETURN_TOP(x) if (!(x)) goto error - - -/* The actual parser **********************************************************/ - -/* What follows is the Ragel parser itself. The language is specified in Ragel - * and the actions call our C functions above. - * - * Ragel has an extensive set of functionality, and we use only a small part of - * it. There are many action types but we only use a few: - * - * ">" -- transition into a machine - * "%" -- transition out of a machine - * "@" -- transition into a final state of a machine. - * - * "@" transitions are tricky because a machine can transition into a final - * state repeatedly. But in some cases we know this can't happen, for example - * a string which is delimited by a final '"' can only transition into its - * final state once, when the closing '"' is seen. */ - - -#line 1306 "upb/json/parser.rl" - - - -#line 1218 "upb/json/parser.c" -static const char _json_actions[] = { - 0, 1, 0, 1, 2, 1, 3, 1, - 5, 1, 6, 1, 7, 1, 8, 1, - 10, 1, 12, 1, 13, 1, 14, 1, - 15, 1, 16, 1, 17, 1, 21, 1, - 25, 1, 27, 2, 3, 8, 2, 4, - 5, 2, 6, 2, 2, 6, 8, 2, - 11, 9, 2, 13, 15, 2, 14, 15, - 2, 18, 1, 2, 19, 27, 2, 20, - 9, 2, 22, 27, 2, 23, 27, 2, - 24, 27, 2, 26, 27, 3, 14, 11, - 9 -}; - -static const unsigned char _json_key_offsets[] = { - 0, 0, 4, 9, 14, 15, 19, 24, - 29, 34, 38, 42, 45, 48, 50, 54, - 58, 60, 62, 67, 69, 71, 80, 86, - 92, 98, 104, 106, 115, 116, 116, 116, - 121, 126, 131, 132, 133, 134, 135, 135, - 136, 137, 138, 138, 139, 140, 141, 141, - 146, 151, 152, 156, 161, 166, 171, 175, - 175, 178, 178, 178 -}; - -static const char _json_trans_keys[] = { - 32, 123, 9, 13, 32, 34, 125, 9, - 13, 32, 34, 125, 9, 13, 34, 32, - 58, 9, 13, 32, 93, 125, 9, 13, - 32, 44, 125, 9, 13, 32, 44, 125, - 9, 13, 32, 34, 9, 13, 45, 48, - 49, 57, 48, 49, 57, 46, 69, 101, - 48, 57, 69, 101, 48, 57, 43, 45, - 48, 57, 48, 57, 48, 57, 46, 69, - 101, 48, 57, 34, 92, 34, 92, 34, - 47, 92, 98, 102, 110, 114, 116, 117, - 48, 57, 65, 70, 97, 102, 48, 57, - 65, 70, 97, 102, 48, 57, 65, 70, - 97, 102, 48, 57, 65, 70, 97, 102, - 34, 92, 34, 45, 91, 102, 110, 116, - 123, 48, 57, 34, 32, 93, 125, 9, - 13, 32, 44, 93, 9, 13, 32, 93, - 125, 9, 13, 97, 108, 115, 101, 117, - 108, 108, 114, 117, 101, 32, 34, 125, - 9, 13, 32, 34, 125, 9, 13, 34, - 32, 58, 9, 13, 32, 93, 125, 9, - 13, 32, 44, 125, 9, 13, 32, 44, - 125, 9, 13, 32, 34, 9, 13, 32, - 9, 13, 0 -}; - -static const char _json_single_lengths[] = { - 0, 2, 3, 3, 1, 2, 3, 3, - 3, 2, 2, 1, 3, 0, 2, 2, - 0, 0, 3, 2, 2, 9, 0, 0, - 0, 0, 2, 7, 1, 0, 0, 3, - 3, 3, 1, 1, 1, 1, 0, 1, - 1, 1, 0, 1, 1, 1, 0, 3, - 3, 1, 2, 3, 3, 3, 2, 0, - 1, 0, 0, 0 -}; - -static const char _json_range_lengths[] = { - 0, 1, 1, 1, 0, 1, 1, 1, - 1, 1, 1, 1, 0, 1, 1, 1, - 1, 1, 1, 0, 0, 0, 3, 3, - 3, 3, 0, 1, 0, 0, 0, 1, - 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, - 1, 0, 1, 1, 1, 1, 1, 0, - 1, 0, 0, 0 -}; - -static const short _json_index_offsets[] = { - 0, 0, 4, 9, 14, 16, 20, 25, - 30, 35, 39, 43, 46, 50, 52, 56, - 60, 62, 64, 69, 72, 75, 85, 89, - 93, 97, 101, 104, 113, 115, 116, 117, - 122, 127, 132, 134, 136, 138, 140, 141, - 143, 145, 147, 148, 150, 152, 154, 155, - 160, 165, 167, 171, 176, 181, 186, 190, - 191, 194, 195, 196 -}; - -static const char _json_indicies[] = { - 0, 2, 0, 1, 3, 4, 5, 3, - 1, 6, 7, 8, 6, 1, 9, 1, - 10, 11, 10, 1, 11, 1, 1, 11, - 12, 13, 14, 15, 13, 1, 16, 17, - 8, 16, 1, 17, 7, 17, 1, 18, - 19, 20, 1, 19, 20, 1, 22, 23, - 23, 21, 24, 1, 23, 23, 24, 21, - 25, 25, 26, 1, 26, 1, 26, 21, - 22, 23, 23, 20, 21, 28, 29, 27, - 31, 32, 30, 33, 33, 33, 33, 33, - 33, 33, 33, 34, 1, 35, 35, 35, - 1, 36, 36, 36, 1, 37, 37, 37, - 1, 38, 38, 38, 1, 40, 41, 39, - 42, 43, 44, 45, 46, 47, 48, 43, - 1, 49, 1, 50, 51, 53, 54, 1, - 53, 52, 55, 56, 54, 55, 1, 56, - 1, 1, 56, 52, 57, 1, 58, 1, - 59, 1, 60, 1, 61, 62, 1, 63, - 1, 64, 1, 65, 66, 1, 67, 1, - 68, 1, 69, 70, 71, 72, 70, 1, - 73, 74, 75, 73, 1, 76, 1, 77, - 78, 77, 1, 78, 1, 1, 78, 79, - 80, 81, 82, 80, 1, 83, 84, 75, - 83, 1, 84, 74, 84, 1, 85, 86, - 86, 1, 1, 1, 1, 0 -}; - -static const char _json_trans_targs[] = { - 1, 0, 2, 3, 4, 56, 3, 4, - 56, 5, 5, 6, 7, 8, 9, 56, - 8, 9, 11, 12, 18, 57, 13, 15, - 14, 16, 17, 20, 58, 21, 20, 58, - 21, 19, 22, 23, 24, 25, 26, 20, - 58, 21, 28, 30, 31, 34, 39, 43, - 47, 29, 59, 59, 32, 31, 29, 32, - 33, 35, 36, 37, 38, 59, 40, 41, - 42, 59, 44, 45, 46, 59, 48, 49, - 55, 48, 49, 55, 50, 50, 51, 52, - 53, 54, 55, 53, 54, 59, 56 -}; - -static const char _json_trans_actions[] = { - 0, 0, 0, 21, 77, 53, 0, 47, - 23, 17, 0, 0, 15, 19, 19, 50, - 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 3, 13, 0, 0, 35, - 5, 11, 0, 38, 7, 7, 7, 41, - 44, 9, 62, 56, 25, 0, 0, 0, - 31, 29, 33, 59, 15, 0, 27, 0, - 0, 0, 0, 0, 0, 68, 0, 0, - 0, 71, 0, 0, 0, 65, 21, 77, - 53, 0, 47, 23, 17, 0, 0, 15, - 19, 19, 50, 0, 0, 74, 0 -}; - -static const int json_start = 1; - -static const int json_en_number_machine = 10; -static const int json_en_string_machine = 19; -static const int json_en_value_machine = 27; -static const int json_en_main = 1; - - -#line 1309 "upb/json/parser.rl" - -size_t parse(void *closure, const void *hd, const char *buf, size_t size, - const upb_bufhandle *handle) { - upb_json_parser *parser = closure; - - /* Variables used by Ragel's generated code. */ - int cs = parser->current_state; - int *stack = parser->parser_stack; - int top = parser->parser_top; - - const char *p = buf; - const char *pe = buf + size; - - parser->handle = handle; - - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - capture_resume(parser, buf); - - -#line 1389 "upb/json/parser.c" - { - int _klen; - unsigned int _trans; - const char *_acts; - unsigned int _nacts; - const char *_keys; - - if ( p == pe ) - goto _test_eof; - if ( cs == 0 ) - goto _out; -_resume: - _keys = _json_trans_keys + _json_key_offsets[cs]; - _trans = _json_index_offsets[cs]; - - _klen = _json_single_lengths[cs]; - if ( _klen > 0 ) { - const char *_lower = _keys; - const char *_mid; - const char *_upper = _keys + _klen - 1; - while (1) { - if ( _upper < _lower ) - break; - - _mid = _lower + ((_upper-_lower) >> 1); - if ( (*p) < *_mid ) - _upper = _mid - 1; - else if ( (*p) > *_mid ) - _lower = _mid + 1; - else { - _trans += (unsigned int)(_mid - _keys); - goto _match; - } - } - _keys += _klen; - _trans += _klen; - } - - _klen = _json_range_lengths[cs]; - if ( _klen > 0 ) { - const char *_lower = _keys; - const char *_mid; - const char *_upper = _keys + (_klen<<1) - 2; - while (1) { - if ( _upper < _lower ) - break; - - _mid = _lower + (((_upper-_lower) >> 1) & ~1); - if ( (*p) < _mid[0] ) - _upper = _mid - 2; - else if ( (*p) > _mid[1] ) - _lower = _mid + 2; - else { - _trans += (unsigned int)((_mid - _keys)>>1); - goto _match; - } - } - _trans += _klen; - } - -_match: - _trans = _json_indicies[_trans]; - cs = _json_trans_targs[_trans]; - - if ( _json_trans_actions[_trans] == 0 ) - goto _again; - - _acts = _json_actions + _json_trans_actions[_trans]; - _nacts = (unsigned int) *_acts++; - while ( _nacts-- > 0 ) - { - switch ( *_acts++ ) - { - case 0: -#line 1221 "upb/json/parser.rl" - { p--; {cs = stack[--top]; goto _again;} } - break; - case 1: -#line 1222 "upb/json/parser.rl" - { p--; {stack[top++] = cs; cs = 10; goto _again;} } - break; - case 2: -#line 1226 "upb/json/parser.rl" - { start_text(parser, p); } - break; - case 3: -#line 1227 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_text(parser, p)); } - break; - case 4: -#line 1233 "upb/json/parser.rl" - { start_hex(parser); } - break; - case 5: -#line 1234 "upb/json/parser.rl" - { hexdigit(parser, p); } - break; - case 6: -#line 1235 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_hex(parser)); } - break; - case 7: -#line 1241 "upb/json/parser.rl" - { CHECK_RETURN_TOP(escape(parser, p)); } - break; - case 8: -#line 1247 "upb/json/parser.rl" - { p--; {cs = stack[--top]; goto _again;} } - break; - case 9: -#line 1250 "upb/json/parser.rl" - { {stack[top++] = cs; cs = 19; goto _again;} } - break; - case 10: -#line 1252 "upb/json/parser.rl" - { p--; {stack[top++] = cs; cs = 27; goto _again;} } - break; - case 11: -#line 1257 "upb/json/parser.rl" - { start_member(parser); } - break; - case 12: -#line 1258 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_membername(parser)); } - break; - case 13: -#line 1261 "upb/json/parser.rl" - { end_member(parser); } - break; - case 14: -#line 1267 "upb/json/parser.rl" - { start_object(parser); } - break; - case 15: -#line 1270 "upb/json/parser.rl" - { end_object(parser); } - break; - case 16: -#line 1276 "upb/json/parser.rl" - { CHECK_RETURN_TOP(start_array(parser)); } - break; - case 17: -#line 1280 "upb/json/parser.rl" - { end_array(parser); } - break; - case 18: -#line 1285 "upb/json/parser.rl" - { start_number(parser, p); } - break; - case 19: -#line 1286 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_number(parser, p)); } - break; - case 20: -#line 1288 "upb/json/parser.rl" - { CHECK_RETURN_TOP(start_stringval(parser)); } - break; - case 21: -#line 1289 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_stringval(parser)); } - break; - case 22: -#line 1291 "upb/json/parser.rl" - { CHECK_RETURN_TOP(parser_putbool(parser, true)); } - break; - case 23: -#line 1293 "upb/json/parser.rl" - { CHECK_RETURN_TOP(parser_putbool(parser, false)); } - break; - case 24: -#line 1295 "upb/json/parser.rl" - { /* null value */ } - break; - case 25: -#line 1297 "upb/json/parser.rl" - { CHECK_RETURN_TOP(start_subobject(parser)); } - break; - case 26: -#line 1298 "upb/json/parser.rl" - { end_subobject(parser); } - break; - case 27: -#line 1303 "upb/json/parser.rl" - { p--; {cs = stack[--top]; goto _again;} } - break; -#line 1575 "upb/json/parser.c" - } - } - -_again: - if ( cs == 0 ) - goto _out; - if ( ++p != pe ) - goto _resume; - _test_eof: {} - _out: {} - } - -#line 1330 "upb/json/parser.rl" - - if (p != pe) { - upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p); - upb_env_reporterror(parser->env, &parser->status); - } else { - capture_suspend(parser, &p); - } - -error: - /* Save parsing state back to parser. */ - parser->current_state = cs; - parser->parser_top = top; - - return p - buf; -} - -bool end(void *closure, const void *hd) { - UPB_UNUSED(closure); - UPB_UNUSED(hd); - - /* Prevent compile warning on unused static constants. */ - UPB_UNUSED(json_start); - UPB_UNUSED(json_en_number_machine); - UPB_UNUSED(json_en_string_machine); - UPB_UNUSED(json_en_value_machine); - UPB_UNUSED(json_en_main); - return true; -} - -static void json_parser_reset(upb_json_parser *p) { - int cs; - int top; - - p->top = p->stack; - p->top->f = NULL; - p->top->is_map = false; - p->top->is_mapentry = false; - - /* Emit Ragel initialization of the parser. */ - -#line 1629 "upb/json/parser.c" - { - cs = json_start; - top = 0; - } - -#line 1370 "upb/json/parser.rl" - p->current_state = cs; - p->parser_top = top; - accumulate_clear(p); - p->multipart_state = MULTIPART_INACTIVE; - p->capture = NULL; - p->accumulated = NULL; - upb_status_clear(&p->status); -} - -static void visit_json_parsermethod(const upb_refcounted *r, - upb_refcounted_visit *visit, - void *closure) { - const upb_json_parsermethod *method = (upb_json_parsermethod*)r; - visit(r, upb_msgdef_upcast2(method->msg), closure); -} - -static void free_json_parsermethod(upb_refcounted *r) { - upb_json_parsermethod *method = (upb_json_parsermethod*)r; - - upb_inttable_iter i; - upb_inttable_begin(&i, &method->name_tables); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_value val = upb_inttable_iter_value(&i); - upb_strtable *t = upb_value_getptr(val); - upb_strtable_uninit(t); - upb_gfree(t); - } - - upb_inttable_uninit(&method->name_tables); - - upb_gfree(r); -} - -static void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* md) { - upb_msg_field_iter i; - upb_strtable *t; - - /* It would be nice to stack-allocate this, but protobufs do not limit the - * length of fields to any reasonable limit. */ - char *buf = NULL; - size_t len = 0; - - if (upb_inttable_lookupptr(&m->name_tables, md, NULL)) { - return; - } - - /* TODO(haberman): handle malloc failure. */ - t = upb_gmalloc(sizeof(*t)); - upb_strtable_init(t, UPB_CTYPE_CONSTPTR); - upb_inttable_insertptr(&m->name_tables, md, upb_value_ptr(t)); - - for(upb_msg_field_begin(&i, md); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - - /* Add an entry for the JSON name. */ - size_t field_len = upb_fielddef_getjsonname(f, buf, len); - if (field_len > len) { - size_t len2; - buf = upb_grealloc(buf, 0, field_len); - len = field_len; - len2 = upb_fielddef_getjsonname(f, buf, len); - UPB_ASSERT(len == len2); - } - upb_strtable_insert(t, buf, upb_value_constptr(f)); - - if (strcmp(buf, upb_fielddef_name(f)) != 0) { - /* Since the JSON name is different from the regular field name, add an - * entry for the raw name (compliant proto3 JSON parsers must accept - * both). */ - upb_strtable_insert(t, upb_fielddef_name(f), upb_value_constptr(f)); - } - - if (upb_fielddef_issubmsg(f)) { - add_jsonname_table(m, upb_fielddef_msgsubdef(f)); - } - } - - upb_gfree(buf); -} - -/* Public API *****************************************************************/ - -upb_json_parser *upb_json_parser_create(upb_env *env, - const upb_json_parsermethod *method, - upb_sink *output) { -#ifndef NDEBUG - const size_t size_before = upb_env_bytesallocated(env); -#endif - upb_json_parser *p = upb_env_malloc(env, sizeof(upb_json_parser)); - if (!p) return false; - - p->env = env; - p->method = method; - p->limit = p->stack + UPB_JSON_MAX_DEPTH; - p->accumulate_buf = NULL; - p->accumulate_buf_size = 0; - upb_bytessink_reset(&p->input_, &method->input_handler_, p); - - json_parser_reset(p); - upb_sink_reset(&p->top->sink, output->handlers, output->closure); - p->top->m = upb_handlers_msgdef(output->handlers); - set_name_table(p, p->top); - - /* If this fails, uncomment and increase the value in parser.h. */ - /* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */ - UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <= - UPB_JSON_PARSER_SIZE); - return p; -} - -upb_bytessink *upb_json_parser_input(upb_json_parser *p) { - return &p->input_; -} - -upb_json_parsermethod *upb_json_parsermethod_new(const upb_msgdef* md, - const void* owner) { - static const struct upb_refcounted_vtbl vtbl = {visit_json_parsermethod, - free_json_parsermethod}; - upb_json_parsermethod *ret = upb_gmalloc(sizeof(*ret)); - upb_refcounted_init(upb_json_parsermethod_upcast_mutable(ret), &vtbl, owner); - - ret->msg = md; - upb_ref2(md, ret); - - upb_byteshandler_init(&ret->input_handler_); - upb_byteshandler_setstring(&ret->input_handler_, parse, ret); - upb_byteshandler_setendstr(&ret->input_handler_, end, ret); - - upb_inttable_init(&ret->name_tables, UPB_CTYPE_PTR); - - add_jsonname_table(ret, md); - - return ret; -} - -const upb_byteshandler *upb_json_parsermethod_inputhandler( - const upb_json_parsermethod *m) { - return &m->input_handler_; -} -/* -** This currently uses snprintf() to format primitives, and could be optimized -** further. -*/ - - -#include -#include - -struct upb_json_printer { - upb_sink input_; - /* BytesSink closure. */ - void *subc_; - upb_bytessink *output_; - - /* We track the depth so that we know when to emit startstr/endstr on the - * output. */ - int depth_; - - /* Have we emitted the first element? This state is necessary to emit commas - * without leaving a trailing comma in arrays/maps. We keep this state per - * frame depth. - * - * Why max_depth * 2? UPB_MAX_HANDLER_DEPTH counts depth as nested messages. - * We count frames (contexts in which we separate elements by commas) as both - * repeated fields and messages (maps), and the worst case is a - * message->repeated field->submessage->repeated field->... nesting. */ - bool first_elem_[UPB_MAX_HANDLER_DEPTH * 2]; -}; - -/* StringPiece; a pointer plus a length. */ -typedef struct { - char *ptr; - size_t len; -} strpc; - -void freestrpc(void *ptr) { - strpc *pc = ptr; - upb_gfree(pc->ptr); - upb_gfree(pc); -} - -/* Convert fielddef name to JSON name and return as a string piece. */ -strpc *newstrpc(upb_handlers *h, const upb_fielddef *f, - bool preserve_fieldnames) { - /* TODO(haberman): handle malloc failure. */ - strpc *ret = upb_gmalloc(sizeof(*ret)); - if (preserve_fieldnames) { - ret->ptr = upb_gstrdup(upb_fielddef_name(f)); - ret->len = strlen(ret->ptr); - } else { - size_t len; - ret->len = upb_fielddef_getjsonname(f, NULL, 0); - ret->ptr = upb_gmalloc(ret->len); - len = upb_fielddef_getjsonname(f, ret->ptr, ret->len); - UPB_ASSERT(len == ret->len); - ret->len--; /* NULL */ - } - - upb_handlers_addcleanup(h, ret, freestrpc); - return ret; -} - -/* ------------ JSON string printing: values, maps, arrays ------------------ */ - -static void print_data( - upb_json_printer *p, const char *buf, unsigned int len) { - /* TODO: Will need to change if we support pushback from the sink. */ - size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL); - UPB_ASSERT(n == len); -} - -static void print_comma(upb_json_printer *p) { - if (!p->first_elem_[p->depth_]) { - print_data(p, ",", 1); - } - p->first_elem_[p->depth_] = false; -} - -/* Helpers that print properly formatted elements to the JSON output stream. */ - -/* Used for escaping control chars in strings. */ -static const char kControlCharLimit = 0x20; - -UPB_INLINE bool is_json_escaped(char c) { - /* See RFC 4627. */ - unsigned char uc = (unsigned char)c; - return uc < kControlCharLimit || uc == '"' || uc == '\\'; -} - -UPB_INLINE const char* json_nice_escape(char c) { - switch (c) { - case '"': return "\\\""; - case '\\': return "\\\\"; - case '\b': return "\\b"; - case '\f': return "\\f"; - case '\n': return "\\n"; - case '\r': return "\\r"; - case '\t': return "\\t"; - default: return NULL; - } -} - -/* Write a properly escaped string chunk. The surrounding quotes are *not* - * printed; this is so that the caller has the option of emitting the string - * content in chunks. */ -static void putstring(upb_json_printer *p, const char *buf, unsigned int len) { - const char* unescaped_run = NULL; - unsigned int i; - for (i = 0; i < len; i++) { - char c = buf[i]; - /* Handle escaping. */ - if (is_json_escaped(c)) { - /* Use a "nice" escape, like \n, if one exists for this character. */ - const char* escape = json_nice_escape(c); - /* If we don't have a specific 'nice' escape code, use a \uXXXX-style - * escape. */ - char escape_buf[8]; - if (!escape) { - unsigned char byte = (unsigned char)c; - _upb_snprintf(escape_buf, sizeof(escape_buf), "\\u%04x", (int)byte); - escape = escape_buf; - } - - /* N.B. that we assume that the input encoding is equal to the output - * encoding (both UTF-8 for now), so for chars >= 0x20 and != \, ", we - * can simply pass the bytes through. */ - - /* If there's a current run of unescaped chars, print that run first. */ - if (unescaped_run) { - print_data(p, unescaped_run, &buf[i] - unescaped_run); - unescaped_run = NULL; - } - /* Then print the escape code. */ - print_data(p, escape, strlen(escape)); - } else { - /* Add to the current unescaped run of characters. */ - if (unescaped_run == NULL) { - unescaped_run = &buf[i]; - } - } - } - - /* If the string ended in a run of unescaped characters, print that last run. */ - if (unescaped_run) { - print_data(p, unescaped_run, &buf[len] - unescaped_run); - } -} - -#define CHKLENGTH(x) if (!(x)) return -1; - -/* Helpers that format floating point values according to our custom formats. - * Right now we use %.8g and %.17g for float/double, respectively, to match - * proto2::util::JsonFormat's defaults. May want to change this later. */ - -const char neginf[] = "\"-Infinity\""; -const char inf[] = "\"Infinity\""; - -static size_t fmt_double(double val, char* buf, size_t length) { - if (val == (1.0 / 0.0)) { - CHKLENGTH(length >= strlen(inf)); - strcpy(buf, inf); - return strlen(inf); - } else if (val == (-1.0 / 0.0)) { - CHKLENGTH(length >= strlen(neginf)); - strcpy(buf, neginf); - return strlen(neginf); - } else { - size_t n = _upb_snprintf(buf, length, "%.17g", val); - CHKLENGTH(n > 0 && n < length); - return n; - } -} - -static size_t fmt_float(float val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "%.8g", val); - CHKLENGTH(n > 0 && n < length); - return n; -} - -static size_t fmt_bool(bool val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "%s", (val ? "true" : "false")); - CHKLENGTH(n > 0 && n < length); - return n; -} - -static size_t fmt_int64(long val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "%ld", val); - CHKLENGTH(n > 0 && n < length); - return n; -} - -static size_t fmt_uint64(unsigned long long val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "%llu", val); - CHKLENGTH(n > 0 && n < length); - return n; -} - -/* Print a map key given a field name. Called by scalar field handlers and by - * startseq for repeated fields. */ -static bool putkey(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - const strpc *key = handler_data; - print_comma(p); - print_data(p, "\"", 1); - putstring(p, key->ptr, key->len); - print_data(p, "\":", 2); - return true; -} - -#define CHKFMT(val) if ((val) == (size_t)-1) return false; -#define CHK(val) if (!(val)) return false; - -#define TYPE_HANDLERS(type, fmt_func) \ - static bool put##type(void *closure, const void *handler_data, type val) { \ - upb_json_printer *p = closure; \ - char data[64]; \ - size_t length = fmt_func(val, data, sizeof(data)); \ - UPB_UNUSED(handler_data); \ - CHKFMT(length); \ - print_data(p, data, length); \ - return true; \ - } \ - static bool scalar_##type(void *closure, const void *handler_data, \ - type val) { \ - CHK(putkey(closure, handler_data)); \ - CHK(put##type(closure, handler_data, val)); \ - return true; \ - } \ - static bool repeated_##type(void *closure, const void *handler_data, \ - type val) { \ - upb_json_printer *p = closure; \ - print_comma(p); \ - CHK(put##type(closure, handler_data, val)); \ - return true; \ - } - -#define TYPE_HANDLERS_MAPKEY(type, fmt_func) \ - static bool putmapkey_##type(void *closure, const void *handler_data, \ - type val) { \ - upb_json_printer *p = closure; \ - print_data(p, "\"", 1); \ - CHK(put##type(closure, handler_data, val)); \ - print_data(p, "\":", 2); \ - return true; \ - } - -TYPE_HANDLERS(double, fmt_double) -TYPE_HANDLERS(float, fmt_float) -TYPE_HANDLERS(bool, fmt_bool) -TYPE_HANDLERS(int32_t, fmt_int64) -TYPE_HANDLERS(uint32_t, fmt_int64) -TYPE_HANDLERS(int64_t, fmt_int64) -TYPE_HANDLERS(uint64_t, fmt_uint64) - -/* double and float are not allowed to be map keys. */ -TYPE_HANDLERS_MAPKEY(bool, fmt_bool) -TYPE_HANDLERS_MAPKEY(int32_t, fmt_int64) -TYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64) -TYPE_HANDLERS_MAPKEY(int64_t, fmt_int64) -TYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64) - -#undef TYPE_HANDLERS -#undef TYPE_HANDLERS_MAPKEY - -typedef struct { - void *keyname; - const upb_enumdef *enumdef; -} EnumHandlerData; - -static bool scalar_enum(void *closure, const void *handler_data, - int32_t val) { - const EnumHandlerData *hd = handler_data; - upb_json_printer *p = closure; - const char *symbolic_name; - - CHK(putkey(closure, hd->keyname)); - - symbolic_name = upb_enumdef_iton(hd->enumdef, val); - if (symbolic_name) { - print_data(p, "\"", 1); - putstring(p, symbolic_name, strlen(symbolic_name)); - print_data(p, "\"", 1); - } else { - putint32_t(closure, NULL, val); - } - - return true; -} - -static void print_enum_symbolic_name(upb_json_printer *p, - const upb_enumdef *def, - int32_t val) { - const char *symbolic_name = upb_enumdef_iton(def, val); - if (symbolic_name) { - print_data(p, "\"", 1); - putstring(p, symbolic_name, strlen(symbolic_name)); - print_data(p, "\"", 1); - } else { - putint32_t(p, NULL, val); - } -} - -static bool repeated_enum(void *closure, const void *handler_data, - int32_t val) { - const EnumHandlerData *hd = handler_data; - upb_json_printer *p = closure; - print_comma(p); - - print_enum_symbolic_name(p, hd->enumdef, val); - - return true; -} - -static bool mapvalue_enum(void *closure, const void *handler_data, - int32_t val) { - const EnumHandlerData *hd = handler_data; - upb_json_printer *p = closure; - - print_enum_symbolic_name(p, hd->enumdef, val); - - return true; -} - -static void *scalar_startsubmsg(void *closure, const void *handler_data) { - return putkey(closure, handler_data) ? closure : UPB_BREAK; -} - -static void *repeated_startsubmsg(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - print_comma(p); - return closure; -} - -static void start_frame(upb_json_printer *p) { - p->depth_++; - p->first_elem_[p->depth_] = true; - print_data(p, "{", 1); -} - -static void end_frame(upb_json_printer *p) { - print_data(p, "}", 1); - p->depth_--; -} - -static bool printer_startmsg(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - if (p->depth_ == 0) { - upb_bytessink_start(p->output_, 0, &p->subc_); - } - start_frame(p); - return true; -} - -static bool printer_endmsg(void *closure, const void *handler_data, upb_status *s) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - UPB_UNUSED(s); - end_frame(p); - if (p->depth_ == 0) { - upb_bytessink_end(p->output_); - } - return true; -} - -static void *startseq(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - CHK(putkey(closure, handler_data)); - p->depth_++; - p->first_elem_[p->depth_] = true; - print_data(p, "[", 1); - return closure; -} - -static bool endseq(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - print_data(p, "]", 1); - p->depth_--; - return true; -} - -static void *startmap(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - CHK(putkey(closure, handler_data)); - p->depth_++; - p->first_elem_[p->depth_] = true; - print_data(p, "{", 1); - return closure; -} - -static bool endmap(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - print_data(p, "}", 1); - p->depth_--; - return true; -} - -static size_t putstr(void *closure, const void *handler_data, const char *str, - size_t len, const upb_bufhandle *handle) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - UPB_UNUSED(handle); - putstring(p, str, len); - return len; -} - -/* This has to Base64 encode the bytes, because JSON has no "bytes" type. */ -static size_t putbytes(void *closure, const void *handler_data, const char *str, - size_t len, const upb_bufhandle *handle) { - upb_json_printer *p = closure; - - /* This is the regular base64, not the "web-safe" version. */ - static const char base64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - /* Base64-encode. */ - char data[16000]; - const char *limit = data + sizeof(data); - const unsigned char *from = (const unsigned char*)str; - char *to = data; - size_t remaining = len; - size_t bytes; - - UPB_UNUSED(handler_data); - UPB_UNUSED(handle); - - while (remaining > 2) { - /* TODO(haberman): handle encoded lengths > sizeof(data) */ - UPB_ASSERT((limit - to) >= 4); - - to[0] = base64[from[0] >> 2]; - to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)]; - to[2] = base64[((from[1] & 0xf) << 2) | (from[2] >> 6)]; - to[3] = base64[from[2] & 0x3f]; - - remaining -= 3; - to += 4; - from += 3; - } - - switch (remaining) { - case 2: - to[0] = base64[from[0] >> 2]; - to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)]; - to[2] = base64[(from[1] & 0xf) << 2]; - to[3] = '='; - to += 4; - from += 2; - break; - case 1: - to[0] = base64[from[0] >> 2]; - to[1] = base64[((from[0] & 0x3) << 4)]; - to[2] = '='; - to[3] = '='; - to += 4; - from += 1; - break; - } - - bytes = to - data; - print_data(p, "\"", 1); - putstring(p, data, bytes); - print_data(p, "\"", 1); - return len; -} - -static void *scalar_startstr(void *closure, const void *handler_data, - size_t size_hint) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - UPB_UNUSED(size_hint); - CHK(putkey(closure, handler_data)); - print_data(p, "\"", 1); - return p; -} - -static size_t scalar_str(void *closure, const void *handler_data, - const char *str, size_t len, - const upb_bufhandle *handle) { - CHK(putstr(closure, handler_data, str, len, handle)); - return len; -} - -static bool scalar_endstr(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - print_data(p, "\"", 1); - return true; -} - -static void *repeated_startstr(void *closure, const void *handler_data, - size_t size_hint) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - UPB_UNUSED(size_hint); - print_comma(p); - print_data(p, "\"", 1); - return p; -} - -static size_t repeated_str(void *closure, const void *handler_data, - const char *str, size_t len, - const upb_bufhandle *handle) { - CHK(putstr(closure, handler_data, str, len, handle)); - return len; -} - -static bool repeated_endstr(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - print_data(p, "\"", 1); - return true; -} - -static void *mapkeyval_startstr(void *closure, const void *handler_data, - size_t size_hint) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - UPB_UNUSED(size_hint); - print_data(p, "\"", 1); - return p; -} - -static size_t mapkey_str(void *closure, const void *handler_data, - const char *str, size_t len, - const upb_bufhandle *handle) { - CHK(putstr(closure, handler_data, str, len, handle)); - return len; -} - -static bool mapkey_endstr(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - print_data(p, "\":", 2); - return true; -} - -static bool mapvalue_endstr(void *closure, const void *handler_data) { - upb_json_printer *p = closure; - UPB_UNUSED(handler_data); - print_data(p, "\"", 1); - return true; -} - -static size_t scalar_bytes(void *closure, const void *handler_data, - const char *str, size_t len, - const upb_bufhandle *handle) { - CHK(putkey(closure, handler_data)); - CHK(putbytes(closure, handler_data, str, len, handle)); - return len; -} - -static size_t repeated_bytes(void *closure, const void *handler_data, - const char *str, size_t len, - const upb_bufhandle *handle) { - upb_json_printer *p = closure; - print_comma(p); - CHK(putbytes(closure, handler_data, str, len, handle)); - return len; -} - -static size_t mapkey_bytes(void *closure, const void *handler_data, - const char *str, size_t len, - const upb_bufhandle *handle) { - upb_json_printer *p = closure; - CHK(putbytes(closure, handler_data, str, len, handle)); - print_data(p, ":", 1); - return len; -} - -static void set_enum_hd(upb_handlers *h, - const upb_fielddef *f, - bool preserve_fieldnames, - upb_handlerattr *attr) { - EnumHandlerData *hd = upb_gmalloc(sizeof(EnumHandlerData)); - hd->enumdef = (const upb_enumdef *)upb_fielddef_subdef(f); - hd->keyname = newstrpc(h, f, preserve_fieldnames); - upb_handlers_addcleanup(h, hd, upb_gfree); - upb_handlerattr_sethandlerdata(attr, hd); -} - -/* Set up handlers for a mapentry submessage (i.e., an individual key/value pair - * in a map). - * - * TODO: Handle missing key, missing value, out-of-order key/value, or repeated - * key or value cases properly. The right way to do this is to allocate a - * temporary structure at the start of a mapentry submessage, store key and - * value data in it as key and value handlers are called, and then print the - * key/value pair once at the end of the submessage. If we don't do this, we - * should at least detect the case and throw an error. However, so far all of - * our sources that emit mapentry messages do so canonically (with one key - * field, and then one value field), so this is not a pressing concern at the - * moment. */ -void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames, - upb_handlers *h) { - const upb_msgdef *md = upb_handlers_msgdef(h); - - /* A mapentry message is printed simply as '"key": value'. Rather than - * special-case key and value for every type below, we just handle both - * fields explicitly here. */ - const upb_fielddef* key_field = upb_msgdef_itof(md, UPB_MAPENTRY_KEY); - const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_MAPENTRY_VALUE); - - upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; - - UPB_UNUSED(closure); - - switch (upb_fielddef_type(key_field)) { - case UPB_TYPE_INT32: - upb_handlers_setint32(h, key_field, putmapkey_int32_t, &empty_attr); - break; - case UPB_TYPE_INT64: - upb_handlers_setint64(h, key_field, putmapkey_int64_t, &empty_attr); - break; - case UPB_TYPE_UINT32: - upb_handlers_setuint32(h, key_field, putmapkey_uint32_t, &empty_attr); - break; - case UPB_TYPE_UINT64: - upb_handlers_setuint64(h, key_field, putmapkey_uint64_t, &empty_attr); - break; - case UPB_TYPE_BOOL: - upb_handlers_setbool(h, key_field, putmapkey_bool, &empty_attr); - break; - case UPB_TYPE_STRING: - upb_handlers_setstartstr(h, key_field, mapkeyval_startstr, &empty_attr); - upb_handlers_setstring(h, key_field, mapkey_str, &empty_attr); - upb_handlers_setendstr(h, key_field, mapkey_endstr, &empty_attr); - break; - case UPB_TYPE_BYTES: - upb_handlers_setstring(h, key_field, mapkey_bytes, &empty_attr); - break; - default: - UPB_ASSERT(false); - break; - } - - switch (upb_fielddef_type(value_field)) { - case UPB_TYPE_INT32: - upb_handlers_setint32(h, value_field, putint32_t, &empty_attr); - break; - case UPB_TYPE_INT64: - upb_handlers_setint64(h, value_field, putint64_t, &empty_attr); - break; - case UPB_TYPE_UINT32: - upb_handlers_setuint32(h, value_field, putuint32_t, &empty_attr); - break; - case UPB_TYPE_UINT64: - upb_handlers_setuint64(h, value_field, putuint64_t, &empty_attr); - break; - case UPB_TYPE_BOOL: - upb_handlers_setbool(h, value_field, putbool, &empty_attr); - break; - case UPB_TYPE_FLOAT: - upb_handlers_setfloat(h, value_field, putfloat, &empty_attr); - break; - case UPB_TYPE_DOUBLE: - upb_handlers_setdouble(h, value_field, putdouble, &empty_attr); - break; - case UPB_TYPE_STRING: - upb_handlers_setstartstr(h, value_field, mapkeyval_startstr, &empty_attr); - upb_handlers_setstring(h, value_field, putstr, &empty_attr); - upb_handlers_setendstr(h, value_field, mapvalue_endstr, &empty_attr); - break; - case UPB_TYPE_BYTES: - upb_handlers_setstring(h, value_field, putbytes, &empty_attr); - break; - case UPB_TYPE_ENUM: { - upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER; - set_enum_hd(h, value_field, preserve_fieldnames, &enum_attr); - upb_handlers_setint32(h, value_field, mapvalue_enum, &enum_attr); - upb_handlerattr_uninit(&enum_attr); - break; - } - case UPB_TYPE_MESSAGE: - /* No handler necessary -- the submsg handlers will print the message - * as appropriate. */ - break; - } - - upb_handlerattr_uninit(&empty_attr); -} - -void printer_sethandlers(const void *closure, upb_handlers *h) { - const upb_msgdef *md = upb_handlers_msgdef(h); - bool is_mapentry = upb_msgdef_mapentry(md); - upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; - upb_msg_field_iter i; - const bool *preserve_fieldnames_ptr = closure; - const bool preserve_fieldnames = *preserve_fieldnames_ptr; - - if (is_mapentry) { - /* mapentry messages are sufficiently different that we handle them - * separately. */ - printer_sethandlers_mapentry(closure, preserve_fieldnames, h); - return; - } - - upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr); - upb_handlers_setendmsg(h, printer_endmsg, &empty_attr); - -#define TYPE(type, name, ctype) \ - case type: \ - if (upb_fielddef_isseq(f)) { \ - upb_handlers_set##name(h, f, repeated_##ctype, &empty_attr); \ - } else { \ - upb_handlers_set##name(h, f, scalar_##ctype, &name_attr); \ - } \ - break; - - upb_msg_field_begin(&i, md); - for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - - upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&name_attr, - newstrpc(h, f, preserve_fieldnames)); - - if (upb_fielddef_ismap(f)) { - upb_handlers_setstartseq(h, f, startmap, &name_attr); - upb_handlers_setendseq(h, f, endmap, &name_attr); - } else if (upb_fielddef_isseq(f)) { - upb_handlers_setstartseq(h, f, startseq, &name_attr); - upb_handlers_setendseq(h, f, endseq, &empty_attr); - } - - switch (upb_fielddef_type(f)) { - TYPE(UPB_TYPE_FLOAT, float, float); - TYPE(UPB_TYPE_DOUBLE, double, double); - TYPE(UPB_TYPE_BOOL, bool, bool); - TYPE(UPB_TYPE_INT32, int32, int32_t); - TYPE(UPB_TYPE_UINT32, uint32, uint32_t); - TYPE(UPB_TYPE_INT64, int64, int64_t); - TYPE(UPB_TYPE_UINT64, uint64, uint64_t); - case UPB_TYPE_ENUM: { - /* For now, we always emit symbolic names for enums. We may want an - * option later to control this behavior, but we will wait for a real - * need first. */ - upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER; - set_enum_hd(h, f, preserve_fieldnames, &enum_attr); - - if (upb_fielddef_isseq(f)) { - upb_handlers_setint32(h, f, repeated_enum, &enum_attr); - } else { - upb_handlers_setint32(h, f, scalar_enum, &enum_attr); - } - - upb_handlerattr_uninit(&enum_attr); - break; - } - case UPB_TYPE_STRING: - if (upb_fielddef_isseq(f)) { - upb_handlers_setstartstr(h, f, repeated_startstr, &empty_attr); - upb_handlers_setstring(h, f, repeated_str, &empty_attr); - upb_handlers_setendstr(h, f, repeated_endstr, &empty_attr); - } else { - upb_handlers_setstartstr(h, f, scalar_startstr, &name_attr); - upb_handlers_setstring(h, f, scalar_str, &empty_attr); - upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr); - } - break; - case UPB_TYPE_BYTES: - /* XXX: this doesn't support strings that span buffers yet. The base64 - * encoder will need to be made resumable for this to work properly. */ - if (upb_fielddef_isseq(f)) { - upb_handlers_setstring(h, f, repeated_bytes, &empty_attr); - } else { - upb_handlers_setstring(h, f, scalar_bytes, &name_attr); - } - break; - case UPB_TYPE_MESSAGE: - if (upb_fielddef_isseq(f)) { - upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &name_attr); - } else { - upb_handlers_setstartsubmsg(h, f, scalar_startsubmsg, &name_attr); - } - break; - } - - upb_handlerattr_uninit(&name_attr); - } - - upb_handlerattr_uninit(&empty_attr); -#undef TYPE -} - -static void json_printer_reset(upb_json_printer *p) { - p->depth_ = 0; -} - - -/* Public API *****************************************************************/ - -upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h, - upb_bytessink *output) { -#ifndef NDEBUG - size_t size_before = upb_env_bytesallocated(e); -#endif - - upb_json_printer *p = upb_env_malloc(e, sizeof(upb_json_printer)); - if (!p) return NULL; - - p->output_ = output; - json_printer_reset(p); - upb_sink_reset(&p->input_, h, p); - - /* If this fails, increase the value in printer.h. */ - UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(e) - size_before <= - UPB_JSON_PRINTER_SIZE); - return p; -} - -upb_sink *upb_json_printer_input(upb_json_printer *p) { - return &p->input_; -} - -const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md, - bool preserve_fieldnames, - const void *owner) { - return upb_handlers_newfrozen( - md, owner, printer_sethandlers, &preserve_fieldnames); -} diff --git a/ruby/ext/google/protobuf_c/upb.h b/ruby/ext/google/protobuf_c/upb.h deleted file mode 100644 index 3edee0d18f576..0000000000000 --- a/ruby/ext/google/protobuf_c/upb.h +++ /dev/null @@ -1,8872 +0,0 @@ -// Amalgamated source file -/* -** Defs are upb's internal representation of the constructs that can appear -** in a .proto file: -** -** - upb::MessageDef (upb_msgdef): describes a "message" construct. -** - upb::FieldDef (upb_fielddef): describes a message field. -** - upb::FileDef (upb_filedef): describes a .proto file and its defs. -** - upb::EnumDef (upb_enumdef): describes an enum. -** - upb::OneofDef (upb_oneofdef): describes a oneof. -** - upb::Def (upb_def): base class of all the others. -** -** TODO: definitions of services. -** -** Like upb_refcounted objects, defs are mutable only until frozen, and are -** only thread-safe once frozen. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. -*/ - -#ifndef UPB_DEF_H_ -#define UPB_DEF_H_ - -/* -** upb::RefCounted (upb_refcounted) -** -** A refcounting scheme that supports circular refs. It accomplishes this by -** partitioning the set of objects into groups such that no cycle spans groups; -** we can then reference-count the group as a whole and ignore refs within the -** group. When objects are mutable, these groups are computed very -** conservatively; we group any objects that have ever had a link between them. -** When objects are frozen, we compute strongly-connected components which -** allows us to be precise and only group objects that are actually cyclic. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. -*/ - -#ifndef UPB_REFCOUNTED_H_ -#define UPB_REFCOUNTED_H_ - -/* -** upb_table -** -** This header is INTERNAL-ONLY! Its interfaces are not public or stable! -** This file defines very fast int->upb_value (inttable) and string->upb_value -** (strtable) hash tables. -** -** The table uses chained scatter with Brent's variation (inspired by the Lua -** implementation of hash tables). The hash function for strings is Austin -** Appleby's "MurmurHash." -** -** The inttable uses uintptr_t as its key, which guarantees it can be used to -** store pointers or integers of at least 32 bits (upb isn't really useful on -** systems where sizeof(void*) < 4). -** -** The table must be homogenous (all values of the same type). In debug -** mode, we check this on insert and lookup. -*/ - -#ifndef UPB_TABLE_H_ -#define UPB_TABLE_H_ - -#include -#include -/* -** This file contains shared definitions that are widely used across upb. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. -*/ - -#ifndef UPB_H_ -#define UPB_H_ - -#include -#include -#include -#include - -#ifdef __cplusplus -namespace upb { -class Allocator; -class Arena; -class Environment; -class ErrorSpace; -class Status; -template class InlinedArena; -template class InlinedEnvironment; -} -#endif - -/* UPB_INLINE: inline if possible, emit standalone code if required. */ -#ifdef __cplusplus -#define UPB_INLINE inline -#elif defined (__GNUC__) -#define UPB_INLINE static __inline__ -#else -#define UPB_INLINE static -#endif - -/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler - * doesn't provide these preprocessor symbols. */ -#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) -#define UPB_BIG_ENDIAN -#endif - -/* Macros for function attributes on compilers that support them. */ -#ifdef __GNUC__ -#define UPB_FORCEINLINE __inline__ __attribute__((always_inline)) -#define UPB_NOINLINE __attribute__((noinline)) -#define UPB_NORETURN __attribute__((__noreturn__)) -#else /* !defined(__GNUC__) */ -#define UPB_FORCEINLINE -#define UPB_NOINLINE -#define UPB_NORETURN -#endif - -#if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L -/* C99/C++11 versions. */ -#include -#define _upb_snprintf snprintf -#define _upb_vsnprintf vsnprintf -#define _upb_va_copy(a, b) va_copy(a, b) -#elif defined __GNUC__ -/* A few hacky workarounds for functions not in C89. - * For internal use only! - * TODO(haberman): fix these by including our own implementations, or finding - * another workaround. - */ -#define _upb_snprintf __builtin_snprintf -#define _upb_vsnprintf __builtin_vsnprintf -#define _upb_va_copy(a, b) __va_copy(a, b) -#else -#error Need implementations of [v]snprintf and va_copy -#endif - - -#if ((defined(__cplusplus) && __cplusplus >= 201103L) || \ - defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(UPB_NO_CXX11) -#define UPB_CXX11 -#endif - -/* UPB_DISALLOW_COPY_AND_ASSIGN() - * UPB_DISALLOW_POD_OPS() - * - * Declare these in the "private" section of a C++ class to forbid copy/assign - * or all POD ops (construct, destruct, copy, assign) on that class. */ -#ifdef UPB_CXX11 -#include -#define UPB_DISALLOW_COPY_AND_ASSIGN(class_name) \ - class_name(const class_name&) = delete; \ - void operator=(const class_name&) = delete; -#define UPB_DISALLOW_POD_OPS(class_name, full_class_name) \ - class_name() = delete; \ - ~class_name() = delete; \ - UPB_DISALLOW_COPY_AND_ASSIGN(class_name) -#define UPB_ASSERT_STDLAYOUT(type) \ - static_assert(std::is_standard_layout::value, \ - #type " must be standard layout"); -#define UPB_FINAL final -#else /* !defined(UPB_CXX11) */ -#define UPB_DISALLOW_COPY_AND_ASSIGN(class_name) \ - class_name(const class_name&); \ - void operator=(const class_name&); -#define UPB_DISALLOW_POD_OPS(class_name, full_class_name) \ - class_name(); \ - ~class_name(); \ - UPB_DISALLOW_COPY_AND_ASSIGN(class_name) -#define UPB_ASSERT_STDLAYOUT(type) -#define UPB_FINAL -#endif - -/* UPB_DECLARE_TYPE() - * UPB_DECLARE_DERIVED_TYPE() - * UPB_DECLARE_DERIVED_TYPE2() - * - * Macros for declaring C and C++ types both, including inheritance. - * The inheritance doesn't use real C++ inheritance, to stay compatible with C. - * - * These macros also provide upcasts: - * - in C: types-specific functions (ie. upb_foo_upcast(foo)) - * - in C++: upb::upcast(foo) along with implicit conversions - * - * Downcasts are not provided, but upb/def.h defines downcasts for upb::Def. */ - -#define UPB_C_UPCASTS(ty, base) \ - UPB_INLINE base *ty ## _upcast_mutable(ty *p) { return (base*)p; } \ - UPB_INLINE const base *ty ## _upcast(const ty *p) { return (const base*)p; } - -#define UPB_C_UPCASTS2(ty, base, base2) \ - UPB_C_UPCASTS(ty, base) \ - UPB_INLINE base2 *ty ## _upcast2_mutable(ty *p) { return (base2*)p; } \ - UPB_INLINE const base2 *ty ## _upcast2(const ty *p) { return (const base2*)p; } - -#ifdef __cplusplus - -#define UPB_BEGIN_EXTERN_C extern "C" { -#define UPB_END_EXTERN_C } -#define UPB_PRIVATE_FOR_CPP private: -#define UPB_DECLARE_TYPE(cppname, cname) typedef cppname cname; - -#define UPB_DECLARE_DERIVED_TYPE(cppname, cppbase, cname, cbase) \ - UPB_DECLARE_TYPE(cppname, cname) \ - UPB_C_UPCASTS(cname, cbase) \ - namespace upb { \ - template <> \ - class Pointer : public PointerBase { \ - public: \ - explicit Pointer(cppname* ptr) \ - : PointerBase(ptr) {} \ - }; \ - template <> \ - class Pointer \ - : public PointerBase { \ - public: \ - explicit Pointer(const cppname* ptr) \ - : PointerBase(ptr) {} \ - }; \ - } - -#define UPB_DECLARE_DERIVED_TYPE2(cppname, cppbase, cppbase2, cname, cbase, \ - cbase2) \ - UPB_DECLARE_TYPE(cppname, cname) \ - UPB_C_UPCASTS2(cname, cbase, cbase2) \ - namespace upb { \ - template <> \ - class Pointer : public PointerBase2 { \ - public: \ - explicit Pointer(cppname* ptr) \ - : PointerBase2(ptr) {} \ - }; \ - template <> \ - class Pointer \ - : public PointerBase2 { \ - public: \ - explicit Pointer(const cppname* ptr) \ - : PointerBase2(ptr) {} \ - }; \ - } - -#else /* !defined(__cplusplus) */ - -#define UPB_BEGIN_EXTERN_C -#define UPB_END_EXTERN_C -#define UPB_PRIVATE_FOR_CPP -#define UPB_DECLARE_TYPE(cppname, cname) \ - struct cname; \ - typedef struct cname cname; -#define UPB_DECLARE_DERIVED_TYPE(cppname, cppbase, cname, cbase) \ - UPB_DECLARE_TYPE(cppname, cname) \ - UPB_C_UPCASTS(cname, cbase) -#define UPB_DECLARE_DERIVED_TYPE2(cppname, cppbase, cppbase2, \ - cname, cbase, cbase2) \ - UPB_DECLARE_TYPE(cppname, cname) \ - UPB_C_UPCASTS2(cname, cbase, cbase2) - -#endif /* defined(__cplusplus) */ - -#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) -#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y)) - -#define UPB_UNUSED(var) (void)var - -/* UPB_ASSERT(): in release mode, we use the expression without letting it be - * evaluated. This prevents "unused variable" warnings. */ -#ifdef NDEBUG -#define UPB_ASSERT(expr) do {} while (false && (expr)) -#else -#define UPB_ASSERT(expr) assert(expr) -#endif - -/* UPB_ASSERT_DEBUGVAR(): assert that uses functions or variables that only - * exist in debug mode. This turns into regular assert. */ -#define UPB_ASSERT_DEBUGVAR(expr) assert(expr) - -#ifdef __GNUC__ -#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0) -#else -#define UPB_UNREACHABLE() do { assert(0); } while(0) -#endif - -/* Generic function type. */ -typedef void upb_func(); - - -/* C++ Casts ******************************************************************/ - -#ifdef __cplusplus - -namespace upb { - -template class Pointer; - -/* Casts to a subclass. The caller must know that cast is correct; an - * incorrect cast will throw an assertion failure in debug mode. - * - * Example: - * upb::Def* def = GetDef(); - * // Assert-fails if this was not actually a MessageDef. - * upb::MessgeDef* md = upb::down_cast(def); - * - * Note that downcasts are only defined for some types (at the moment you can - * only downcast from a upb::Def to a specific Def type). */ -template To down_cast(From* f); - -/* Casts to a subclass. If the class does not actually match the given To type, - * returns NULL. - * - * Example: - * upb::Def* def = GetDef(); - * // md will be NULL if this was not actually a MessageDef. - * upb::MessgeDef* md = upb::down_cast(def); - * - * Note that dynamic casts are only defined for some types (at the moment you - * can only downcast from a upb::Def to a specific Def type).. */ -template To dyn_cast(From* f); - -/* Casts to any base class, or the type itself (ie. can be a no-op). - * - * Example: - * upb::MessageDef* md = GetDef(); - * // This will fail to compile if this wasn't actually a base class. - * upb::Def* def = upb::upcast(md); - */ -template inline Pointer upcast(T *f) { return Pointer(f); } - -/* Attempt upcast to specific base class. - * - * Example: - * upb::MessageDef* md = GetDef(); - * upb::upcast_to(md)->MethodOnDef(); - */ -template inline T* upcast_to(F *f) { - return static_cast(upcast(f)); -} - -/* PointerBase: implementation detail of upb::upcast(). - * It is implicitly convertable to pointers to the Base class(es). - */ -template -class PointerBase { - public: - explicit PointerBase(T* ptr) : ptr_(ptr) {} - operator T*() { return ptr_; } - operator Base*() { return (Base*)ptr_; } - - private: - T* ptr_; -}; - -template -class PointerBase2 : public PointerBase { - public: - explicit PointerBase2(T* ptr) : PointerBase(ptr) {} - operator Base2*() { return Pointer(*this); } -}; - -} - -#endif - - -/* upb::ErrorSpace ************************************************************/ - -/* A upb::ErrorSpace represents some domain of possible error values. This lets - * upb::Status attach specific error codes to operations, like POSIX/C errno, - * Win32 error codes, etc. Clients who want to know the very specific error - * code can check the error space and then know the type of the integer code. - * - * NOTE: upb::ErrorSpace is currently not used and should be considered - * experimental. It is important primarily in cases where upb is performing - * I/O, but upb doesn't currently have any components that do this. */ - -UPB_DECLARE_TYPE(upb::ErrorSpace, upb_errorspace) - -#ifdef __cplusplus -class upb::ErrorSpace { -#else -struct upb_errorspace { -#endif - const char *name; -}; - - -/* upb::Status ****************************************************************/ - -/* upb::Status represents a success or failure status and error message. - * It owns no resources and allocates no memory, so it should work - * even in OOM situations. */ -UPB_DECLARE_TYPE(upb::Status, upb_status) - -/* The maximum length of an error message before it will get truncated. */ -#define UPB_STATUS_MAX_MESSAGE 128 - -UPB_BEGIN_EXTERN_C - -const char *upb_status_errmsg(const upb_status *status); -bool upb_ok(const upb_status *status); -upb_errorspace *upb_status_errspace(const upb_status *status); -int upb_status_errcode(const upb_status *status); - -/* Any of the functions that write to a status object allow status to be NULL, - * to support use cases where the function's caller does not care about the - * status message. */ -void upb_status_clear(upb_status *status); -void upb_status_seterrmsg(upb_status *status, const char *msg); -void upb_status_seterrf(upb_status *status, const char *fmt, ...); -void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args); -void upb_status_copy(upb_status *to, const upb_status *from); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -class upb::Status { - public: - Status() { upb_status_clear(this); } - - /* Returns true if there is no error. */ - bool ok() const { return upb_ok(this); } - - /* Optional error space and code, useful if the caller wants to - * programmatically check the specific kind of error. */ - ErrorSpace* error_space() { return upb_status_errspace(this); } - int error_code() const { return upb_status_errcode(this); } - - /* The returned string is invalidated by any other call into the status. */ - const char *error_message() const { return upb_status_errmsg(this); } - - /* The error message will be truncated if it is longer than - * UPB_STATUS_MAX_MESSAGE-4. */ - void SetErrorMessage(const char* msg) { upb_status_seterrmsg(this, msg); } - void SetFormattedErrorMessage(const char* fmt, ...) { - va_list args; - va_start(args, fmt); - upb_status_vseterrf(this, fmt, args); - va_end(args); - } - - /* Resets the status to a successful state with no message. */ - void Clear() { upb_status_clear(this); } - - void CopyFrom(const Status& other) { upb_status_copy(this, &other); } - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(Status) -#else -struct upb_status { -#endif - bool ok_; - - /* Specific status code defined by some error space (optional). */ - int code_; - upb_errorspace *error_space_; - - /* TODO(haberman): add file/line of error? */ - - /* Error message; NULL-terminated. */ - char msg[UPB_STATUS_MAX_MESSAGE]; -}; - -#define UPB_STATUS_INIT {true, 0, NULL, {0}} - - -/** Built-in error spaces. ****************************************************/ - -/* Errors raised by upb that we want to be able to detect programmatically. */ -typedef enum { - UPB_NOMEM /* Can't reuse ENOMEM because it is POSIX, not ISO C. */ -} upb_errcode_t; - -extern upb_errorspace upb_upberr; - -void upb_upberr_setoom(upb_status *s); - -/* Since errno is defined by standard C, we define an error space for it in - * core upb. Other error spaces should be defined in other, platform-specific - * modules. */ - -extern upb_errorspace upb_errnoerr; - - -/** upb::Allocator ************************************************************/ - -/* A upb::Allocator is a possibly-stateful allocator object. - * - * It could either be an arena allocator (which doesn't require individual - * free() calls) or a regular malloc() (which does). The client must therefore - * free memory unless it knows that the allocator is an arena allocator. */ -UPB_DECLARE_TYPE(upb::Allocator, upb_alloc) - -/* A malloc()/free() function. - * If "size" is 0 then the function acts like free(), otherwise it acts like - * realloc(). Only "oldsize" bytes from a previous allocation are preserved. */ -typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize, - size_t size); - -#ifdef __cplusplus - -class upb::Allocator UPB_FINAL { - public: - Allocator() {} - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(Allocator) - - public: -#else -struct upb_alloc { -#endif /* __cplusplus */ - upb_alloc_func *func; -}; - -UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) { - UPB_ASSERT(alloc); - return alloc->func(alloc, NULL, 0, size); -} - -UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize, - size_t size) { - UPB_ASSERT(alloc); - return alloc->func(alloc, ptr, oldsize, size); -} - -UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) { - assert(alloc); - alloc->func(alloc, ptr, 0, 0); -} - -/* The global allocator used by upb. Uses the standard malloc()/free(). */ - -extern upb_alloc upb_alloc_global; - -/* Functions that hard-code the global malloc. - * - * We still get benefit because we can put custom logic into our global - * allocator, like injecting out-of-memory faults in debug/testing builds. */ - -UPB_INLINE void *upb_gmalloc(size_t size) { - return upb_malloc(&upb_alloc_global, size); -} - -UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) { - return upb_realloc(&upb_alloc_global, ptr, oldsize, size); -} - -UPB_INLINE void upb_gfree(void *ptr) { - upb_free(&upb_alloc_global, ptr); -} - -/* upb::Arena *****************************************************************/ - -/* upb::Arena is a specific allocator implementation that uses arena allocation. - * The user provides an allocator that will be used to allocate the underlying - * arena blocks. Arenas by nature do not require the individual allocations - * to be freed. However the Arena does allow users to register cleanup - * functions that will run when the arena is destroyed. - * - * A upb::Arena is *not* thread-safe. - * - * You could write a thread-safe arena allocator that satisfies the - * upb::Allocator interface, but it would not be as efficient for the - * single-threaded case. */ -UPB_DECLARE_TYPE(upb::Arena, upb_arena) - -typedef void upb_cleanup_func(void *ud); - -#define UPB_ARENA_BLOCK_OVERHEAD (sizeof(size_t)*4) - -UPB_BEGIN_EXTERN_C - -void upb_arena_init(upb_arena *a); -void upb_arena_init2(upb_arena *a, void *mem, size_t n, upb_alloc *alloc); -void upb_arena_uninit(upb_arena *a); -bool upb_arena_addcleanup(upb_arena *a, upb_cleanup_func *func, void *ud); -size_t upb_arena_bytesallocated(const upb_arena *a); -void upb_arena_setnextblocksize(upb_arena *a, size_t size); -void upb_arena_setmaxblocksize(upb_arena *a, size_t size); -UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; } - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -class upb::Arena { - public: - /* A simple arena with no initial memory block and the default allocator. */ - Arena() { upb_arena_init(this); } - - /* Constructs an arena with the given initial block which allocates blocks - * with the given allocator. The given allocator must outlive the Arena. - * - * If you pass NULL for the allocator it will default to the global allocator - * upb_alloc_global, and NULL/0 for the initial block will cause there to be - * no initial block. */ - Arena(void *mem, size_t len, Allocator* a) { - upb_arena_init2(this, mem, len, a); - } - - ~Arena() { upb_arena_uninit(this); } - - /* Sets the size of the next block the Arena will request (unless the - * requested allocation is larger). Each block will double in size until the - * max limit is reached. */ - void SetNextBlockSize(size_t size) { upb_arena_setnextblocksize(this, size); } - - /* Sets the maximum block size. No blocks larger than this will be requested - * from the underlying allocator unless individual arena allocations are - * larger. */ - void SetMaxBlockSize(size_t size) { upb_arena_setmaxblocksize(this, size); } - - /* Allows this arena to be used as a generic allocator. - * - * The arena does not need free() calls so when using Arena as an allocator - * it is safe to skip them. However they are no-ops so there is no harm in - * calling free() either. */ - Allocator* allocator() { return upb_arena_alloc(this); } - - /* Add a cleanup function to run when the arena is destroyed. - * Returns false on out-of-memory. */ - bool AddCleanup(upb_cleanup_func* func, void* ud) { - return upb_arena_addcleanup(this, func, ud); - } - - /* Total number of bytes that have been allocated. It is undefined what - * Realloc() does to this counter. */ - size_t BytesAllocated() const { - return upb_arena_bytesallocated(this); - } - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(Arena) - -#else -struct upb_arena { -#endif /* __cplusplus */ - /* We implement the allocator interface. - * This must be the first member of upb_arena! */ - upb_alloc alloc; - - /* Allocator to allocate arena blocks. We are responsible for freeing these - * when we are destroyed. */ - upb_alloc *block_alloc; - - size_t bytes_allocated; - size_t next_block_size; - size_t max_block_size; - - /* Linked list of blocks. Points to an arena_block, defined in env.c */ - void *block_head; - - /* Cleanup entries. Pointer to a cleanup_ent, defined in env.c */ - void *cleanup_head; - - /* For future expansion, since the size of this struct is exposed to users. */ - void *future1; - void *future2; -}; - - -/* upb::Environment ***********************************************************/ - -/* A upb::Environment provides a means for injecting malloc and an - * error-reporting callback into encoders/decoders. This allows them to be - * independent of nearly all assumptions about their actual environment. - * - * It is also a container for allocating the encoders/decoders themselves that - * insulates clients from knowing their actual size. This provides ABI - * compatibility even if the size of the objects change. And this allows the - * structure definitions to be in the .c files instead of the .h files, making - * the .h files smaller and more readable. - * - * We might want to consider renaming this to "Pipeline" if/when the concept of - * a pipeline element becomes more formalized. */ -UPB_DECLARE_TYPE(upb::Environment, upb_env) - -/* A function that receives an error report from an encoder or decoder. The - * callback can return true to request that the error should be recovered, but - * if the error is not recoverable this has no effect. */ -typedef bool upb_error_func(void *ud, const upb_status *status); - -UPB_BEGIN_EXTERN_C - -void upb_env_init(upb_env *e); -void upb_env_init2(upb_env *e, void *mem, size_t n, upb_alloc *alloc); -void upb_env_uninit(upb_env *e); - -void upb_env_initonly(upb_env *e); - -upb_arena *upb_env_arena(upb_env *e); -bool upb_env_ok(const upb_env *e); -void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud); - -/* Convenience wrappers around the methods of the contained arena. */ -void upb_env_reporterrorsto(upb_env *e, upb_status *s); -bool upb_env_reporterror(upb_env *e, const upb_status *s); -void *upb_env_malloc(upb_env *e, size_t size); -void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size); -void upb_env_free(upb_env *e, void *ptr); -bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud); -size_t upb_env_bytesallocated(const upb_env *e); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -class upb::Environment { - public: - /* The given Arena must outlive this environment. */ - Environment() { upb_env_initonly(this); } - - Environment(void *mem, size_t len, Allocator *a) : arena_(mem, len, a) { - upb_env_initonly(this); - } - - Arena* arena() { return upb_env_arena(this); } - - /* Set a custom error reporting function. */ - void SetErrorFunction(upb_error_func* func, void* ud) { - upb_env_seterrorfunc(this, func, ud); - } - - /* Set the error reporting function to simply copy the status to the given - * status and abort. */ - void ReportErrorsTo(Status* status) { upb_env_reporterrorsto(this, status); } - - /* Returns true if all allocations and AddCleanup() calls have succeeded, - * and no errors were reported with ReportError() (except ones that recovered - * successfully). */ - bool ok() const { return upb_env_ok(this); } - - /* Reports an error to this environment's callback, returning true if - * the caller should try to recover. */ - bool ReportError(const Status* status) { - return upb_env_reporterror(this, status); - } - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(Environment) - -#else -struct upb_env { -#endif /* __cplusplus */ - upb_arena arena_; - upb_error_func *error_func_; - void *error_ud_; - bool ok_; -}; - - -/* upb::InlinedArena **********************************************************/ -/* upb::InlinedEnvironment ****************************************************/ - -/* upb::InlinedArena and upb::InlinedEnvironment seed their arenas with a - * predefined amount of memory. No heap memory will be allocated until the - * initial block is exceeded. - * - * These types only exist in C++ */ - -#ifdef __cplusplus - -template class upb::InlinedArena : public upb::Arena { - public: - InlinedArena() : Arena(initial_block_, N, NULL) {} - explicit InlinedArena(Allocator* a) : Arena(initial_block_, N, a) {} - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(InlinedArena) - - char initial_block_[N + UPB_ARENA_BLOCK_OVERHEAD]; -}; - -template class upb::InlinedEnvironment : public upb::Environment { - public: - InlinedEnvironment() : Environment(initial_block_, N, NULL) {} - explicit InlinedEnvironment(Allocator *a) - : Environment(initial_block_, N, a) {} - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(InlinedEnvironment) - - char initial_block_[N + UPB_ARENA_BLOCK_OVERHEAD]; -}; - -#endif /* __cplusplus */ - - - -#endif /* UPB_H_ */ - -#ifdef __cplusplus -extern "C" { -#endif - - -/* upb_value ******************************************************************/ - -/* A tagged union (stored untagged inside the table) so that we can check that - * clients calling table accessors are correctly typed without having to have - * an explosion of accessors. */ -typedef enum { - UPB_CTYPE_INT32 = 1, - UPB_CTYPE_INT64 = 2, - UPB_CTYPE_UINT32 = 3, - UPB_CTYPE_UINT64 = 4, - UPB_CTYPE_BOOL = 5, - UPB_CTYPE_CSTR = 6, - UPB_CTYPE_PTR = 7, - UPB_CTYPE_CONSTPTR = 8, - UPB_CTYPE_FPTR = 9, - UPB_CTYPE_FLOAT = 10, - UPB_CTYPE_DOUBLE = 11 -} upb_ctype_t; - -typedef struct { - uint64_t val; -#ifndef NDEBUG - /* In debug mode we carry the value type around also so we can check accesses - * to be sure the right member is being read. */ - upb_ctype_t ctype; -#endif -} upb_value; - -#ifdef NDEBUG -#define SET_TYPE(dest, val) UPB_UNUSED(val) -#else -#define SET_TYPE(dest, val) dest = val -#endif - -/* Like strdup(), which isn't always available since it's not ANSI C. */ -char *upb_strdup(const char *s, upb_alloc *a); -/* Variant that works with a length-delimited rather than NULL-delimited string, - * as supported by strtable. */ -char *upb_strdup2(const char *s, size_t len, upb_alloc *a); - -UPB_INLINE char *upb_gstrdup(const char *s) { - return upb_strdup(s, &upb_alloc_global); -} - -UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val, - upb_ctype_t ctype) { - v->val = val; - SET_TYPE(v->ctype, ctype); -} - -UPB_INLINE upb_value _upb_value_val(uint64_t val, upb_ctype_t ctype) { - upb_value ret; - _upb_value_setval(&ret, val, ctype); - return ret; -} - -/* For each value ctype, define the following set of functions: - * - * // Get/set an int32 from a upb_value. - * int32_t upb_value_getint32(upb_value val); - * void upb_value_setint32(upb_value *val, int32_t cval); - * - * // Construct a new upb_value from an int32. - * upb_value upb_value_int32(int32_t val); */ -#define FUNCS(name, membername, type_t, converter, proto_type) \ - UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \ - val->val = (converter)cval; \ - SET_TYPE(val->ctype, proto_type); \ - } \ - UPB_INLINE upb_value upb_value_ ## name(type_t val) { \ - upb_value ret; \ - upb_value_set ## name(&ret, val); \ - return ret; \ - } \ - UPB_INLINE type_t upb_value_get ## name(upb_value val) { \ - UPB_ASSERT_DEBUGVAR(val.ctype == proto_type); \ - return (type_t)(converter)val.val; \ - } - -FUNCS(int32, int32, int32_t, int32_t, UPB_CTYPE_INT32) -FUNCS(int64, int64, int64_t, int64_t, UPB_CTYPE_INT64) -FUNCS(uint32, uint32, uint32_t, uint32_t, UPB_CTYPE_UINT32) -FUNCS(uint64, uint64, uint64_t, uint64_t, UPB_CTYPE_UINT64) -FUNCS(bool, _bool, bool, bool, UPB_CTYPE_BOOL) -FUNCS(cstr, cstr, char*, uintptr_t, UPB_CTYPE_CSTR) -FUNCS(ptr, ptr, void*, uintptr_t, UPB_CTYPE_PTR) -FUNCS(constptr, constptr, const void*, uintptr_t, UPB_CTYPE_CONSTPTR) -FUNCS(fptr, fptr, upb_func*, uintptr_t, UPB_CTYPE_FPTR) - -#undef FUNCS - -UPB_INLINE void upb_value_setfloat(upb_value *val, float cval) { - memcpy(&val->val, &cval, sizeof(cval)); - SET_TYPE(val->ctype, UPB_CTYPE_FLOAT); -} - -UPB_INLINE void upb_value_setdouble(upb_value *val, double cval) { - memcpy(&val->val, &cval, sizeof(cval)); - SET_TYPE(val->ctype, UPB_CTYPE_DOUBLE); -} - -UPB_INLINE upb_value upb_value_float(float cval) { - upb_value ret; - upb_value_setfloat(&ret, cval); - return ret; -} - -UPB_INLINE upb_value upb_value_double(double cval) { - upb_value ret; - upb_value_setdouble(&ret, cval); - return ret; -} - -#undef SET_TYPE - - -/* upb_tabkey *****************************************************************/ - -/* Either: - * 1. an actual integer key, or - * 2. a pointer to a string prefixed by its uint32_t length, owned by us. - * - * ...depending on whether this is a string table or an int table. We would - * make this a union of those two types, but C89 doesn't support statically - * initializing a non-first union member. */ -typedef uintptr_t upb_tabkey; - -#define UPB_TABKEY_NUM(n) n -#define UPB_TABKEY_NONE 0 -/* The preprocessor isn't quite powerful enough to turn the compile-time string - * length into a byte-wise string representation, so code generation needs to - * help it along. - * - * "len1" is the low byte and len4 is the high byte. */ -#ifdef UPB_BIG_ENDIAN -#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \ - (uintptr_t)(len4 len3 len2 len1 strval) -#else -#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \ - (uintptr_t)(len1 len2 len3 len4 strval) -#endif - -UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) { - char* mem = (char*)key; - if (len) memcpy(len, mem, sizeof(*len)); - return mem + sizeof(*len); -} - - -/* upb_tabval *****************************************************************/ - -#ifdef __cplusplus - -/* Status initialization not supported. - * - * This separate definition is necessary because in C++, UINTPTR_MAX isn't - * reliably available. */ -typedef struct { - uint64_t val; -} upb_tabval; - -#else - -/* C -- supports static initialization, but to support static initialization of - * both integers and points for both 32 and 64 bit targets, it takes a little - * bit of doing. */ - -#if UINTPTR_MAX == 0xffffffffffffffffULL -#define UPB_PTR_IS_64BITS -#elif UINTPTR_MAX != 0xffffffff -#error Could not determine how many bits pointers are. -#endif - -typedef union { - /* For static initialization. - * - * Unfortunately this ugliness is necessary -- it is the only way that we can, - * with -std=c89 -pedantic, statically initialize this to either a pointer or - * an integer on 32-bit platforms. */ - struct { -#ifdef UPB_PTR_IS_64BITS - uintptr_t val; -#else - uintptr_t val1; - uintptr_t val2; -#endif - } staticinit; - - /* The normal accessor that we use for everything at runtime. */ - uint64_t val; -} upb_tabval; - -#ifdef UPB_PTR_IS_64BITS -#define UPB_TABVALUE_INT_INIT(v) {{v}} -#define UPB_TABVALUE_EMPTY_INIT {{-1}} -#else - -/* 32-bit pointers */ - -#ifdef UPB_BIG_ENDIAN -#define UPB_TABVALUE_INT_INIT(v) {{0, v}} -#define UPB_TABVALUE_EMPTY_INIT {{-1, -1}} -#else -#define UPB_TABVALUE_INT_INIT(v) {{v, 0}} -#define UPB_TABVALUE_EMPTY_INIT {{-1, -1}} -#endif - -#endif - -#define UPB_TABVALUE_PTR_INIT(v) UPB_TABVALUE_INT_INIT((uintptr_t)v) - -#undef UPB_PTR_IS_64BITS - -#endif /* __cplusplus */ - - -/* upb_table ******************************************************************/ - -typedef struct _upb_tabent { - upb_tabkey key; - upb_tabval val; - - /* Internal chaining. This is const so we can create static initializers for - * tables. We cast away const sometimes, but *only* when the containing - * upb_table is known to be non-const. This requires a bit of care, but - * the subtlety is confined to table.c. */ - const struct _upb_tabent *next; -} upb_tabent; - -typedef struct { - size_t count; /* Number of entries in the hash part. */ - size_t mask; /* Mask to turn hash value -> bucket. */ - upb_ctype_t ctype; /* Type of all values. */ - uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ - - /* Hash table entries. - * Making this const isn't entirely accurate; what we really want is for it to - * have the same const-ness as the table it's inside. But there's no way to - * declare that in C. So we have to make it const so that we can statically - * initialize const hash tables. Then we cast away const when we have to. - */ - const upb_tabent *entries; - -#ifndef NDEBUG - /* This table's allocator. We make the user pass it in to every relevant - * function and only use this to check it in debug mode. We do this solely - * to keep upb_table as small as possible. This might seem slightly paranoid - * but the plan is to use upb_table for all map fields and extension sets in - * a forthcoming message representation, so there could be a lot of these. - * If this turns out to be too annoying later, we can change it (since this - * is an internal-only header file). */ - upb_alloc *alloc; -#endif -} upb_table; - -#ifdef NDEBUG -# define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \ - {count, mask, ctype, size_lg2, entries} -#else -# ifdef UPB_DEBUG_REFS -/* At the moment the only mutable tables we statically initialize are debug - * ref tables. */ -# define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \ - {count, mask, ctype, size_lg2, entries, &upb_alloc_debugrefs} -# else -# define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \ - {count, mask, ctype, size_lg2, entries, NULL} -# endif -#endif - -typedef struct { - upb_table t; -} upb_strtable; - -#define UPB_STRTABLE_INIT(count, mask, ctype, size_lg2, entries) \ - {UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries)} - -#define UPB_EMPTY_STRTABLE_INIT(ctype) \ - UPB_STRTABLE_INIT(0, 0, ctype, 0, NULL) - -typedef struct { - upb_table t; /* For entries that don't fit in the array part. */ - const upb_tabval *array; /* Array part of the table. See const note above. */ - size_t array_size; /* Array part size. */ - size_t array_count; /* Array part number of elements. */ -} upb_inttable; - -#define UPB_INTTABLE_INIT(count, mask, ctype, size_lg2, ent, a, asize, acount) \ - {UPB_TABLE_INIT(count, mask, ctype, size_lg2, ent), a, asize, acount} - -#define UPB_EMPTY_INTTABLE_INIT(ctype) \ - UPB_INTTABLE_INIT(0, 0, ctype, 0, NULL, NULL, 0, 0) - -#define UPB_ARRAY_EMPTYENT -1 - -UPB_INLINE size_t upb_table_size(const upb_table *t) { - if (t->size_lg2 == 0) - return 0; - else - return 1 << t->size_lg2; -} - -/* Internal-only functions, in .h file only out of necessity. */ -UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) { - return e->key == 0; -} - -/* Used by some of the unit tests for generic hashing functionality. */ -uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed); - -UPB_INLINE uintptr_t upb_intkey(uintptr_t key) { - return key; -} - -UPB_INLINE uint32_t upb_inthash(uintptr_t key) { - return (uint32_t)key; -} - -static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) { - return t->entries + (hash & t->mask); -} - -UPB_INLINE bool upb_arrhas(upb_tabval key) { - return key.val != (uint64_t)-1; -} - -/* Initialize and uninitialize a table, respectively. If memory allocation - * failed, false is returned that the table is uninitialized. */ -bool upb_inttable_init2(upb_inttable *table, upb_ctype_t ctype, upb_alloc *a); -bool upb_strtable_init2(upb_strtable *table, upb_ctype_t ctype, upb_alloc *a); -void upb_inttable_uninit2(upb_inttable *table, upb_alloc *a); -void upb_strtable_uninit2(upb_strtable *table, upb_alloc *a); - -UPB_INLINE bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype) { - return upb_inttable_init2(table, ctype, &upb_alloc_global); -} - -UPB_INLINE bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype) { - return upb_strtable_init2(table, ctype, &upb_alloc_global); -} - -UPB_INLINE void upb_inttable_uninit(upb_inttable *table) { - upb_inttable_uninit2(table, &upb_alloc_global); -} - -UPB_INLINE void upb_strtable_uninit(upb_strtable *table) { - upb_strtable_uninit2(table, &upb_alloc_global); -} - -/* Returns the number of values in the table. */ -size_t upb_inttable_count(const upb_inttable *t); -UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) { - return t->t.count; -} - -void upb_inttable_packedsize(const upb_inttable *t, size_t *size); -void upb_strtable_packedsize(const upb_strtable *t, size_t *size); -upb_inttable *upb_inttable_pack(const upb_inttable *t, void *p, size_t *ofs, - size_t size); -upb_strtable *upb_strtable_pack(const upb_strtable *t, void *p, size_t *ofs, - size_t size); - -/* Inserts the given key into the hashtable with the given value. The key must - * not already exist in the hash table. For string tables, the key must be - * NULL-terminated, and the table will make an internal copy of the key. - * Inttables must not insert a value of UINTPTR_MAX. - * - * If a table resize was required but memory allocation failed, false is - * returned and the table is unchanged. */ -bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, - upb_alloc *a); -bool upb_strtable_insert3(upb_strtable *t, const char *key, size_t len, - upb_value val, upb_alloc *a); - -UPB_INLINE bool upb_inttable_insert(upb_inttable *t, uintptr_t key, - upb_value val) { - return upb_inttable_insert2(t, key, val, &upb_alloc_global); -} - -UPB_INLINE bool upb_strtable_insert2(upb_strtable *t, const char *key, - size_t len, upb_value val) { - return upb_strtable_insert3(t, key, len, val, &upb_alloc_global); -} - -/* For NULL-terminated strings. */ -UPB_INLINE bool upb_strtable_insert(upb_strtable *t, const char *key, - upb_value val) { - return upb_strtable_insert2(t, key, strlen(key), val); -} - -/* Looks up key in this table, returning "true" if the key was found. - * If v is non-NULL, copies the value for this key into *v. */ -bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v); -bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len, - upb_value *v); - -/* For NULL-terminated strings. */ -UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key, - upb_value *v) { - return upb_strtable_lookup2(t, key, strlen(key), v); -} - -/* Removes an item from the table. Returns true if the remove was successful, - * and stores the removed item in *val if non-NULL. */ -bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val); -bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len, - upb_value *val, upb_alloc *alloc); - -UPB_INLINE bool upb_strtable_remove2(upb_strtable *t, const char *key, - size_t len, upb_value *val) { - return upb_strtable_remove3(t, key, len, val, &upb_alloc_global); -} - -/* For NULL-terminated strings. */ -UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key, - upb_value *v) { - return upb_strtable_remove2(t, key, strlen(key), v); -} - -/* Updates an existing entry in an inttable. If the entry does not exist, - * returns false and does nothing. Unlike insert/remove, this does not - * invalidate iterators. */ -bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val); - -/* Handy routines for treating an inttable like a stack. May not be mixed with - * other insert/remove calls. */ -bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a); -upb_value upb_inttable_pop(upb_inttable *t); - -UPB_INLINE bool upb_inttable_push(upb_inttable *t, upb_value val) { - return upb_inttable_push2(t, val, &upb_alloc_global); -} - -/* Convenience routines for inttables with pointer keys. */ -bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val, - upb_alloc *a); -bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val); -bool upb_inttable_lookupptr( - const upb_inttable *t, const void *key, upb_value *val); - -UPB_INLINE bool upb_inttable_insertptr(upb_inttable *t, const void *key, - upb_value val) { - return upb_inttable_insertptr2(t, key, val, &upb_alloc_global); -} - -/* Optimizes the table for the current set of entries, for both memory use and - * lookup time. Client should call this after all entries have been inserted; - * inserting more entries is legal, but will likely require a table resize. */ -void upb_inttable_compact2(upb_inttable *t, upb_alloc *a); - -UPB_INLINE void upb_inttable_compact(upb_inttable *t) { - upb_inttable_compact2(t, &upb_alloc_global); -} - -/* A special-case inlinable version of the lookup routine for 32-bit - * integers. */ -UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, - upb_value *v) { - *v = upb_value_int32(0); /* Silence compiler warnings. */ - if (key < t->array_size) { - upb_tabval arrval = t->array[key]; - if (upb_arrhas(arrval)) { - _upb_value_setval(v, arrval.val, t->t.ctype); - return true; - } else { - return false; - } - } else { - const upb_tabent *e; - if (t->t.entries == NULL) return false; - for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) { - if ((uint32_t)e->key == key) { - _upb_value_setval(v, e->val.val, t->t.ctype); - return true; - } - if (e->next == NULL) return false; - } - } -} - -/* Exposed for testing only. */ -bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a); - -/* Iterators ******************************************************************/ - -/* Iterators for int and string tables. We are subject to some kind of unusual - * design constraints: - * - * For high-level languages: - * - we must be able to guarantee that we don't crash or corrupt memory even if - * the program accesses an invalidated iterator. - * - * For C++11 range-based for: - * - iterators must be copyable - * - iterators must be comparable - * - it must be possible to construct an "end" value. - * - * Iteration order is undefined. - * - * Modifying the table invalidates iterators. upb_{str,int}table_done() is - * guaranteed to work even on an invalidated iterator, as long as the table it - * is iterating over has not been freed. Calling next() or accessing data from - * an invalidated iterator yields unspecified elements from the table, but it is - * guaranteed not to crash and to return real table elements (except when done() - * is true). */ - - -/* upb_strtable_iter **********************************************************/ - -/* upb_strtable_iter i; - * upb_strtable_begin(&i, t); - * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { - * const char *key = upb_strtable_iter_key(&i); - * const upb_value val = upb_strtable_iter_value(&i); - * // ... - * } - */ - -typedef struct { - const upb_strtable *t; - size_t index; -} upb_strtable_iter; - -void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t); -void upb_strtable_next(upb_strtable_iter *i); -bool upb_strtable_done(const upb_strtable_iter *i); -const char *upb_strtable_iter_key(const upb_strtable_iter *i); -size_t upb_strtable_iter_keylength(const upb_strtable_iter *i); -upb_value upb_strtable_iter_value(const upb_strtable_iter *i); -void upb_strtable_iter_setdone(upb_strtable_iter *i); -bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, - const upb_strtable_iter *i2); - - -/* upb_inttable_iter **********************************************************/ - -/* upb_inttable_iter i; - * upb_inttable_begin(&i, t); - * for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - * uintptr_t key = upb_inttable_iter_key(&i); - * upb_value val = upb_inttable_iter_value(&i); - * // ... - * } - */ - -typedef struct { - const upb_inttable *t; - size_t index; - bool array_part; -} upb_inttable_iter; - -void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t); -void upb_inttable_next(upb_inttable_iter *i); -bool upb_inttable_done(const upb_inttable_iter *i); -uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i); -upb_value upb_inttable_iter_value(const upb_inttable_iter *i); -void upb_inttable_iter_setdone(upb_inttable_iter *i); -bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, - const upb_inttable_iter *i2); - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_TABLE_H_ */ - -/* Reference tracking will check ref()/unref() operations to make sure the - * ref ownership is correct. Where possible it will also make tools like - * Valgrind attribute ref leaks to the code that took the leaked ref, not - * the code that originally created the object. - * - * Enabling this requires the application to define upb_lock()/upb_unlock() - * functions that acquire/release a global mutex (or #define UPB_THREAD_UNSAFE). - * For this reason we don't enable it by default, even in debug builds. - */ - -/* #define UPB_DEBUG_REFS */ - -#ifdef __cplusplus -namespace upb { -class RefCounted; -template class reffed_ptr; -} -#endif - -UPB_DECLARE_TYPE(upb::RefCounted, upb_refcounted) - -struct upb_refcounted_vtbl; - -#ifdef __cplusplus - -class upb::RefCounted { - public: - /* Returns true if the given object is frozen. */ - bool IsFrozen() const; - - /* Increases the ref count, the new ref is owned by "owner" which must not - * already own a ref (and should not itself be a refcounted object if the ref - * could possibly be circular; see below). - * Thread-safe iff "this" is frozen. */ - void Ref(const void *owner) const; - - /* Release a ref that was acquired from upb_refcounted_ref() and collects any - * objects it can. */ - void Unref(const void *owner) const; - - /* Moves an existing ref from "from" to "to", without changing the overall - * ref count. DonateRef(foo, NULL, owner) is the same as Ref(foo, owner), - * but "to" may not be NULL. */ - void DonateRef(const void *from, const void *to) const; - - /* Verifies that a ref to the given object is currently held by the given - * owner. Only effective in UPB_DEBUG_REFS builds. */ - void CheckRef(const void *owner) const; - - private: - UPB_DISALLOW_POD_OPS(RefCounted, upb::RefCounted) -#else -struct upb_refcounted { -#endif - /* TODO(haberman): move the actual structure definition to structdefs.int.h. - * The only reason they are here is because inline functions need to see the - * definition of upb_handlers, which needs to see this definition. But we - * can change the upb_handlers inline functions to deal in raw offsets - * instead. - */ - - /* A single reference count shared by all objects in the group. */ - uint32_t *group; - - /* A singly-linked list of all objects in the group. */ - upb_refcounted *next; - - /* Table of function pointers for this type. */ - const struct upb_refcounted_vtbl *vtbl; - - /* Maintained only when mutable, this tracks the number of refs (but not - * ref2's) to this object. *group should be the sum of all individual_count - * in the group. */ - uint32_t individual_count; - - bool is_frozen; - -#ifdef UPB_DEBUG_REFS - upb_inttable *refs; /* Maps owner -> trackedref for incoming refs. */ - upb_inttable *ref2s; /* Set of targets for outgoing ref2s. */ -#endif -}; - -#ifdef UPB_DEBUG_REFS -extern upb_alloc upb_alloc_debugrefs; -#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \ - {&static_refcount, NULL, vtbl, 0, true, refs, ref2s} -#else -#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \ - {&static_refcount, NULL, vtbl, 0, true} -#endif - -UPB_BEGIN_EXTERN_C - -/* It is better to use tracked refs when possible, for the extra debugging - * capability. But if this is not possible (because you don't have easy access - * to a stable pointer value that is associated with the ref), you can pass - * UPB_UNTRACKED_REF instead. */ -extern const void *UPB_UNTRACKED_REF; - -/* Native C API. */ -bool upb_refcounted_isfrozen(const upb_refcounted *r); -void upb_refcounted_ref(const upb_refcounted *r, const void *owner); -void upb_refcounted_unref(const upb_refcounted *r, const void *owner); -void upb_refcounted_donateref( - const upb_refcounted *r, const void *from, const void *to); -void upb_refcounted_checkref(const upb_refcounted *r, const void *owner); - -#define UPB_REFCOUNTED_CMETHODS(type, upcastfunc) \ - UPB_INLINE bool type ## _isfrozen(const type *v) { \ - return upb_refcounted_isfrozen(upcastfunc(v)); \ - } \ - UPB_INLINE void type ## _ref(const type *v, const void *owner) { \ - upb_refcounted_ref(upcastfunc(v), owner); \ - } \ - UPB_INLINE void type ## _unref(const type *v, const void *owner) { \ - upb_refcounted_unref(upcastfunc(v), owner); \ - } \ - UPB_INLINE void type ## _donateref(const type *v, const void *from, const void *to) { \ - upb_refcounted_donateref(upcastfunc(v), from, to); \ - } \ - UPB_INLINE void type ## _checkref(const type *v, const void *owner) { \ - upb_refcounted_checkref(upcastfunc(v), owner); \ - } - -#define UPB_REFCOUNTED_CPPMETHODS \ - bool IsFrozen() const { \ - return upb::upcast_to(this)->IsFrozen(); \ - } \ - void Ref(const void *owner) const { \ - return upb::upcast_to(this)->Ref(owner); \ - } \ - void Unref(const void *owner) const { \ - return upb::upcast_to(this)->Unref(owner); \ - } \ - void DonateRef(const void *from, const void *to) const { \ - return upb::upcast_to(this)->DonateRef(from, to); \ - } \ - void CheckRef(const void *owner) const { \ - return upb::upcast_to(this)->CheckRef(owner); \ - } - -/* Internal-to-upb Interface **************************************************/ - -typedef void upb_refcounted_visit(const upb_refcounted *r, - const upb_refcounted *subobj, - void *closure); - -struct upb_refcounted_vtbl { - /* Must visit all subobjects that are currently ref'd via upb_refcounted_ref2. - * Must be longjmp()-safe. */ - void (*visit)(const upb_refcounted *r, upb_refcounted_visit *visit, void *c); - - /* Must free the object and release all references to other objects. */ - void (*free)(upb_refcounted *r); -}; - -/* Initializes the refcounted with a single ref for the given owner. Returns - * false if memory could not be allocated. */ -bool upb_refcounted_init(upb_refcounted *r, - const struct upb_refcounted_vtbl *vtbl, - const void *owner); - -/* Adds a ref from one refcounted object to another ("from" must not already - * own a ref). These refs may be circular; cycles will be collected correctly - * (if conservatively). These refs do not need to be freed in from's free() - * function. */ -void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from); - -/* Removes a ref that was acquired from upb_refcounted_ref2(), and collects any - * object it can. This is only necessary when "from" no longer points to "r", - * and not from from's "free" function. */ -void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from); - -#define upb_ref2(r, from) \ - upb_refcounted_ref2((const upb_refcounted*)r, (upb_refcounted*)from) -#define upb_unref2(r, from) \ - upb_refcounted_unref2((const upb_refcounted*)r, (upb_refcounted*)from) - -/* Freezes all mutable object reachable by ref2() refs from the given roots. - * This will split refcounting groups into precise SCC groups, so that - * refcounting of frozen objects can be more aggressive. If memory allocation - * fails, or if more than 2**31 mutable objects are reachable from "roots", or - * if the maximum depth of the graph exceeds "maxdepth", false is returned and - * the objects are unchanged. - * - * After this operation succeeds, the objects are frozen/const, and may not be - * used through non-const pointers. In particular, they may not be passed as - * the second parameter of upb_refcounted_{ref,unref}2(). On the upside, all - * operations on frozen refcounteds are threadsafe, and objects will be freed - * at the precise moment that they become unreachable. - * - * Caller must own refs on each object in the "roots" list. */ -bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s, - int maxdepth); - -/* Shared by all compiled-in refcounted objects. */ -extern uint32_t static_refcount; - -UPB_END_EXTERN_C - -#ifdef __cplusplus -/* C++ Wrappers. */ -namespace upb { -inline bool RefCounted::IsFrozen() const { - return upb_refcounted_isfrozen(this); -} -inline void RefCounted::Ref(const void *owner) const { - upb_refcounted_ref(this, owner); -} -inline void RefCounted::Unref(const void *owner) const { - upb_refcounted_unref(this, owner); -} -inline void RefCounted::DonateRef(const void *from, const void *to) const { - upb_refcounted_donateref(this, from, to); -} -inline void RefCounted::CheckRef(const void *owner) const { - upb_refcounted_checkref(this, owner); -} -} /* namespace upb */ -#endif - - -/* upb::reffed_ptr ************************************************************/ - -#ifdef __cplusplus - -#include /* For std::swap(). */ - -/* Provides RAII semantics for upb refcounted objects. Each reffed_ptr owns a - * ref on whatever object it points to (if any). */ -template class upb::reffed_ptr { - public: - reffed_ptr() : ptr_(NULL) {} - - /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */ - template - reffed_ptr(U* val, const void* ref_donor = NULL) - : ptr_(upb::upcast(val)) { - if (ref_donor) { - UPB_ASSERT(ptr_); - ptr_->DonateRef(ref_donor, this); - } else if (ptr_) { - ptr_->Ref(this); - } - } - - template - reffed_ptr(const reffed_ptr& other) - : ptr_(upb::upcast(other.get())) { - if (ptr_) ptr_->Ref(this); - } - - reffed_ptr(const reffed_ptr& other) - : ptr_(upb::upcast(other.get())) { - if (ptr_) ptr_->Ref(this); - } - - ~reffed_ptr() { if (ptr_) ptr_->Unref(this); } - - template - reffed_ptr& operator=(const reffed_ptr& other) { - reset(other.get()); - return *this; - } - - reffed_ptr& operator=(const reffed_ptr& other) { - reset(other.get()); - return *this; - } - - /* TODO(haberman): add C++11 move construction/assignment for greater - * efficiency. */ - - void swap(reffed_ptr& other) { - if (ptr_ == other.ptr_) { - return; - } - - if (ptr_) ptr_->DonateRef(this, &other); - if (other.ptr_) other.ptr_->DonateRef(&other, this); - std::swap(ptr_, other.ptr_); - } - - T& operator*() const { - UPB_ASSERT(ptr_); - return *ptr_; - } - - T* operator->() const { - UPB_ASSERT(ptr_); - return ptr_; - } - - T* get() const { return ptr_; } - - /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */ - template - void reset(U* ptr = NULL, const void* ref_donor = NULL) { - reffed_ptr(ptr, ref_donor).swap(*this); - } - - template - reffed_ptr down_cast() { - return reffed_ptr(upb::down_cast(get())); - } - - template - reffed_ptr dyn_cast() { - return reffed_ptr(upb::dyn_cast(get())); - } - - /* Plain release() is unsafe; if we were the only owner, it would leak the - * object. Instead we provide this: */ - T* ReleaseTo(const void* new_owner) { - T* ret = NULL; - ptr_->DonateRef(this, new_owner); - std::swap(ret, ptr_); - return ret; - } - - private: - T* ptr_; -}; - -#endif /* __cplusplus */ - -#endif /* UPB_REFCOUNT_H_ */ - -#ifdef __cplusplus -#include -#include -#include - -namespace upb { -class Def; -class EnumDef; -class FieldDef; -class FileDef; -class MessageDef; -class OneofDef; -class SymbolTable; -} -#endif - -UPB_DECLARE_DERIVED_TYPE(upb::Def, upb::RefCounted, upb_def, upb_refcounted) -UPB_DECLARE_DERIVED_TYPE(upb::OneofDef, upb::RefCounted, upb_oneofdef, - upb_refcounted) -UPB_DECLARE_DERIVED_TYPE(upb::FileDef, upb::RefCounted, upb_filedef, - upb_refcounted) -UPB_DECLARE_TYPE(upb::SymbolTable, upb_symtab) - - -/* The maximum message depth that the type graph can have. This is a resource - * limit for the C stack since we sometimes need to recursively traverse the - * graph. Cycles are ok; the traversal will stop when it detects a cycle, but - * we must hit the cycle before the maximum depth is reached. - * - * If having a single static limit is too inflexible, we can add another variant - * of Def::Freeze that allows specifying this as a parameter. */ -#define UPB_MAX_MESSAGE_DEPTH 64 - - -/* upb::Def: base class for top-level defs ***********************************/ - -/* All the different kind of defs that can be defined at the top-level and put - * in a SymbolTable or appear in a FileDef::defs() list. This excludes some - * defs (like oneofs and files). It only includes fields because they can be - * defined as extensions. */ -typedef enum { - UPB_DEF_MSG, - UPB_DEF_FIELD, - UPB_DEF_ENUM, - UPB_DEF_SERVICE, /* Not yet implemented. */ - UPB_DEF_ANY = -1 /* Wildcard for upb_symtab_get*() */ -} upb_deftype_t; - -#ifdef __cplusplus - -/* The base class of all defs. Its base is upb::RefCounted (use upb::upcast() - * to convert). */ -class upb::Def { - public: - typedef upb_deftype_t Type; - - /* upb::RefCounted methods like Ref()/Unref(). */ - UPB_REFCOUNTED_CPPMETHODS - - Type def_type() const; - - /* "fullname" is the def's fully-qualified name (eg. foo.bar.Message). */ - const char *full_name() const; - - /* The final part of a def's name (eg. Message). */ - const char *name() const; - - /* The def must be mutable. Caller retains ownership of fullname. Defs are - * not required to have a name; if a def has no name when it is frozen, it - * will remain an anonymous def. On failure, returns false and details in "s" - * if non-NULL. */ - bool set_full_name(const char* fullname, upb::Status* s); - bool set_full_name(const std::string &fullname, upb::Status* s); - - /* The file in which this def appears. It is not necessary to add a def to a - * file (and consequently the accessor may return NULL). Set this by calling - * file->Add(def). */ - FileDef* file() const; - - /* Freezes the given defs; this validates all constraints and marks the defs - * as frozen (read-only). "defs" may not contain any fielddefs, but fields - * of any msgdefs will be frozen. - * - * Symbolic references to sub-types and enum defaults must have already been - * resolved. Any mutable defs reachable from any of "defs" must also be in - * the list; more formally, "defs" must be a transitive closure of mutable - * defs. - * - * After this operation succeeds, the finalized defs must only be accessed - * through a const pointer! */ - static bool Freeze(Def* const* defs, size_t n, Status* status); - static bool Freeze(const std::vector& defs, Status* status); - - private: - UPB_DISALLOW_POD_OPS(Def, upb::Def) -}; - -#endif /* __cplusplus */ - -UPB_BEGIN_EXTERN_C - -/* Include upb_refcounted methods like upb_def_ref()/upb_def_unref(). */ -UPB_REFCOUNTED_CMETHODS(upb_def, upb_def_upcast) - -upb_deftype_t upb_def_type(const upb_def *d); -const char *upb_def_fullname(const upb_def *d); -const char *upb_def_name(const upb_def *d); -const upb_filedef *upb_def_file(const upb_def *d); -bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s); -bool upb_def_freeze(upb_def *const *defs, size_t n, upb_status *s); - -/* Temporary API: for internal use only. */ -bool _upb_def_validate(upb_def *const*defs, size_t n, upb_status *s); - -UPB_END_EXTERN_C - - -/* upb::Def casts *************************************************************/ - -#ifdef __cplusplus -#define UPB_CPP_CASTS(cname, cpptype) \ - namespace upb { \ - template <> \ - inline cpptype *down_cast(Def * def) { \ - return upb_downcast_##cname##_mutable(def); \ - } \ - template <> \ - inline cpptype *dyn_cast(Def * def) { \ - return upb_dyncast_##cname##_mutable(def); \ - } \ - template <> \ - inline const cpptype *down_cast( \ - const Def *def) { \ - return upb_downcast_##cname(def); \ - } \ - template <> \ - inline const cpptype *dyn_cast(const Def *def) { \ - return upb_dyncast_##cname(def); \ - } \ - template <> \ - inline const cpptype *down_cast(Def * def) { \ - return upb_downcast_##cname(def); \ - } \ - template <> \ - inline const cpptype *dyn_cast(Def * def) { \ - return upb_dyncast_##cname(def); \ - } \ - } /* namespace upb */ -#else -#define UPB_CPP_CASTS(cname, cpptype) -#endif /* __cplusplus */ - -/* Dynamic casts, for determining if a def is of a particular type at runtime. - * Downcasts, for when some wants to assert that a def is of a particular type. - * These are only checked if we are building debug. */ -#define UPB_DEF_CASTS(lower, upper, cpptype) \ - UPB_INLINE const upb_##lower *upb_dyncast_##lower(const upb_def *def) { \ - if (upb_def_type(def) != UPB_DEF_##upper) return NULL; \ - return (upb_##lower *)def; \ - } \ - UPB_INLINE const upb_##lower *upb_downcast_##lower(const upb_def *def) { \ - UPB_ASSERT(upb_def_type(def) == UPB_DEF_##upper); \ - return (const upb_##lower *)def; \ - } \ - UPB_INLINE upb_##lower *upb_dyncast_##lower##_mutable(upb_def *def) { \ - return (upb_##lower *)upb_dyncast_##lower(def); \ - } \ - UPB_INLINE upb_##lower *upb_downcast_##lower##_mutable(upb_def *def) { \ - return (upb_##lower *)upb_downcast_##lower(def); \ - } \ - UPB_CPP_CASTS(lower, cpptype) - -#define UPB_DEFINE_DEF(cppname, lower, upper, cppmethods, members) \ - UPB_DEFINE_CLASS2(cppname, upb::Def, upb::RefCounted, cppmethods, \ - members) \ - UPB_DEF_CASTS(lower, upper, cppname) - -#define UPB_DECLARE_DEF_TYPE(cppname, lower, upper) \ - UPB_DECLARE_DERIVED_TYPE2(cppname, upb::Def, upb::RefCounted, \ - upb_ ## lower, upb_def, upb_refcounted) \ - UPB_DEF_CASTS(lower, upper, cppname) - -UPB_DECLARE_DEF_TYPE(upb::FieldDef, fielddef, FIELD) -UPB_DECLARE_DEF_TYPE(upb::MessageDef, msgdef, MSG) -UPB_DECLARE_DEF_TYPE(upb::EnumDef, enumdef, ENUM) - -#undef UPB_DECLARE_DEF_TYPE -#undef UPB_DEF_CASTS -#undef UPB_CPP_CASTS - - -/* upb::FieldDef **************************************************************/ - -/* The types a field can have. Note that this list is not identical to the - * types defined in descriptor.proto, which gives INT32 and SINT32 separate - * types (we distinguish the two with the "integer encoding" enum below). */ -typedef enum { - /* Types stored in 1 byte. */ - UPB_TYPE_BOOL = 1, - /* Types stored in 4 bytes. */ - UPB_TYPE_FLOAT = 2, - UPB_TYPE_INT32 = 3, - UPB_TYPE_UINT32 = 4, - UPB_TYPE_ENUM = 5, /* Enum values are int32. */ - /* Types stored as pointers (probably 4 or 8 bytes). */ - UPB_TYPE_STRING = 6, - UPB_TYPE_BYTES = 7, - UPB_TYPE_MESSAGE = 8, - /* Types stored as 8 bytes. */ - UPB_TYPE_DOUBLE = 9, - UPB_TYPE_INT64 = 10, - UPB_TYPE_UINT64 = 11 -} upb_fieldtype_t; - -/* The repeated-ness of each field; this matches descriptor.proto. */ -typedef enum { - UPB_LABEL_OPTIONAL = 1, - UPB_LABEL_REQUIRED = 2, - UPB_LABEL_REPEATED = 3 -} upb_label_t; - -/* How integers should be encoded in serializations that offer multiple - * integer encoding methods. */ -typedef enum { - UPB_INTFMT_VARIABLE = 1, - UPB_INTFMT_FIXED = 2, - UPB_INTFMT_ZIGZAG = 3 /* Only for signed types (INT32/INT64). */ -} upb_intfmt_t; - -/* Descriptor types, as defined in descriptor.proto. */ -typedef enum { - UPB_DESCRIPTOR_TYPE_DOUBLE = 1, - UPB_DESCRIPTOR_TYPE_FLOAT = 2, - UPB_DESCRIPTOR_TYPE_INT64 = 3, - UPB_DESCRIPTOR_TYPE_UINT64 = 4, - UPB_DESCRIPTOR_TYPE_INT32 = 5, - UPB_DESCRIPTOR_TYPE_FIXED64 = 6, - UPB_DESCRIPTOR_TYPE_FIXED32 = 7, - UPB_DESCRIPTOR_TYPE_BOOL = 8, - UPB_DESCRIPTOR_TYPE_STRING = 9, - UPB_DESCRIPTOR_TYPE_GROUP = 10, - UPB_DESCRIPTOR_TYPE_MESSAGE = 11, - UPB_DESCRIPTOR_TYPE_BYTES = 12, - UPB_DESCRIPTOR_TYPE_UINT32 = 13, - UPB_DESCRIPTOR_TYPE_ENUM = 14, - UPB_DESCRIPTOR_TYPE_SFIXED32 = 15, - UPB_DESCRIPTOR_TYPE_SFIXED64 = 16, - UPB_DESCRIPTOR_TYPE_SINT32 = 17, - UPB_DESCRIPTOR_TYPE_SINT64 = 18 -} upb_descriptortype_t; - -typedef enum { - UPB_SYNTAX_PROTO2 = 2, - UPB_SYNTAX_PROTO3 = 3 -} upb_syntax_t; - -/* Maximum field number allowed for FieldDefs. This is an inherent limit of the - * protobuf wire format. */ -#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1) - -#ifdef __cplusplus - -/* A upb_fielddef describes a single field in a message. It is most often - * found as a part of a upb_msgdef, but can also stand alone to represent - * an extension. - * - * Its base class is upb::Def (use upb::upcast() to convert). */ -class upb::FieldDef { - public: - typedef upb_fieldtype_t Type; - typedef upb_label_t Label; - typedef upb_intfmt_t IntegerFormat; - typedef upb_descriptortype_t DescriptorType; - - /* These return true if the given value is a valid member of the enumeration. */ - static bool CheckType(int32_t val); - static bool CheckLabel(int32_t val); - static bool CheckDescriptorType(int32_t val); - static bool CheckIntegerFormat(int32_t val); - - /* These convert to the given enumeration; they require that the value is - * valid. */ - static Type ConvertType(int32_t val); - static Label ConvertLabel(int32_t val); - static DescriptorType ConvertDescriptorType(int32_t val); - static IntegerFormat ConvertIntegerFormat(int32_t val); - - /* Returns NULL if memory allocation failed. */ - static reffed_ptr New(); - - /* upb::RefCounted methods like Ref()/Unref(). */ - UPB_REFCOUNTED_CPPMETHODS - - /* Functionality from upb::Def. */ - const char* full_name() const; - - bool type_is_set() const; /* set_[descriptor_]type() has been called? */ - Type type() const; /* Requires that type_is_set() == true. */ - Label label() const; /* Defaults to UPB_LABEL_OPTIONAL. */ - const char* name() const; /* NULL if uninitialized. */ - uint32_t number() const; /* Returns 0 if uninitialized. */ - bool is_extension() const; - - /* Copies the JSON name for this field into the given buffer. Returns the - * actual size of the JSON name, including the NULL terminator. If the - * return value is 0, the JSON name is unset. If the return value is - * greater than len, the JSON name was truncated. The buffer is always - * NULL-terminated if len > 0. - * - * The JSON name always defaults to a camelCased version of the regular - * name. However if the regular name is unset, the JSON name will be unset - * also. - */ - size_t GetJsonName(char* buf, size_t len) const; - - /* Convenience version of the above function which copies the JSON name - * into the given string, returning false if the name is not set. */ - template - bool GetJsonName(T* str) { - str->resize(GetJsonName(NULL, 0)); - GetJsonName(&(*str)[0], str->size()); - return str->size() > 0; - } - - /* For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false, - * indicates whether this field should have lazy parsing handlers that yield - * the unparsed string for the submessage. - * - * TODO(haberman): I think we want to move this into a FieldOptions container - * when we add support for custom options (the FieldOptions struct will - * contain both regular FieldOptions like "lazy" *and* custom options). */ - bool lazy() const; - - /* For non-string, non-submessage fields, this indicates whether binary - * protobufs are encoded in packed or non-packed format. - * - * TODO(haberman): see note above about putting options like this into a - * FieldOptions container. */ - bool packed() const; - - /* An integer that can be used as an index into an array of fields for - * whatever message this field belongs to. Guaranteed to be less than - * f->containing_type()->field_count(). May only be accessed once the def has - * been finalized. */ - uint32_t index() const; - - /* The MessageDef to which this field belongs. - * - * If this field has been added to a MessageDef, that message can be retrieved - * directly (this is always the case for frozen FieldDefs). - * - * If the field has not yet been added to a MessageDef, you can set the name - * of the containing type symbolically instead. This is mostly useful for - * extensions, where the extension is declared separately from the message. */ - const MessageDef* containing_type() const; - const char* containing_type_name(); - - /* The OneofDef to which this field belongs, or NULL if this field is not part - * of a oneof. */ - const OneofDef* containing_oneof() const; - - /* The field's type according to the enum in descriptor.proto. This is not - * the same as UPB_TYPE_*, because it distinguishes between (for example) - * INT32 and SINT32, whereas our "type" enum does not. This return of - * descriptor_type() is a function of type(), integer_format(), and - * is_tag_delimited(). Likewise set_descriptor_type() sets all three - * appropriately. */ - DescriptorType descriptor_type() const; - - /* Convenient field type tests. */ - bool IsSubMessage() const; - bool IsString() const; - bool IsSequence() const; - bool IsPrimitive() const; - bool IsMap() const; - - /* Returns whether this field explicitly represents presence. - * - * For proto2 messages: Returns true for any scalar (non-repeated) field. - * For proto3 messages: Returns true for scalar submessage or oneof fields. */ - bool HasPresence() const; - - /* How integers are encoded. Only meaningful for integer types. - * Defaults to UPB_INTFMT_VARIABLE, and is reset when "type" changes. */ - IntegerFormat integer_format() const; - - /* Whether a submessage field is tag-delimited or not (if false, then - * length-delimited). May only be set when type() == UPB_TYPE_MESSAGE. */ - bool is_tag_delimited() const; - - /* Returns the non-string default value for this fielddef, which may either - * be something the client set explicitly or the "default default" (0 for - * numbers, empty for strings). The field's type indicates the type of the - * returned value, except for enum fields that are still mutable. - * - * Requires that the given function matches the field's current type. */ - int64_t default_int64() const; - int32_t default_int32() const; - uint64_t default_uint64() const; - uint32_t default_uint32() const; - bool default_bool() const; - float default_float() const; - double default_double() const; - - /* The resulting string is always NULL-terminated. If non-NULL, the length - * will be stored in *len. */ - const char *default_string(size_t* len) const; - - /* For frozen UPB_TYPE_ENUM fields, enum defaults can always be read as either - * string or int32, and both of these methods will always return true. - * - * For mutable UPB_TYPE_ENUM fields, the story is a bit more complicated. - * Enum defaults are unusual. They can be specified either as string or int32, - * but to be valid the enum must have that value as a member. And if no - * default is specified, the "default default" comes from the EnumDef. - * - * We allow reading the default as either an int32 or a string, but only if - * we have a meaningful value to report. We have a meaningful value if it was - * set explicitly, or if we could get the "default default" from the EnumDef. - * Also if you explicitly set the name and we find the number in the EnumDef */ - bool EnumHasStringDefault() const; - bool EnumHasInt32Default() const; - - /* Submessage and enum fields must reference a "subdef", which is the - * upb::MessageDef or upb::EnumDef that defines their type. Note that when - * the FieldDef is mutable it may not have a subdef *yet*, but this function - * still returns true to indicate that the field's type requires a subdef. */ - bool HasSubDef() const; - - /* Returns the enum or submessage def for this field, if any. The field's - * type must match (ie. you may only call enum_subdef() for fields where - * type() == UPB_TYPE_ENUM). Returns NULL if the subdef has not been set or - * is currently set symbolically. */ - const EnumDef* enum_subdef() const; - const MessageDef* message_subdef() const; - - /* Returns the generic subdef for this field. Requires that HasSubDef() (ie. - * only works for UPB_TYPE_ENUM and UPB_TYPE_MESSAGE fields). */ - const Def* subdef() const; - - /* Returns the symbolic name of the subdef. If the subdef is currently set - * unresolved (ie. set symbolically) returns the symbolic name. If it has - * been resolved to a specific subdef, returns the name from that subdef. */ - const char* subdef_name() const; - - /* Setters (non-const methods), only valid for mutable FieldDefs! ***********/ - - bool set_full_name(const char* fullname, upb::Status* s); - bool set_full_name(const std::string& fullname, upb::Status* s); - - /* This may only be called if containing_type() == NULL (ie. the field has not - * been added to a message yet). */ - bool set_containing_type_name(const char *name, Status* status); - bool set_containing_type_name(const std::string& name, Status* status); - - /* Defaults to false. When we freeze, we ensure that this can only be true - * for length-delimited message fields. Prior to freezing this can be true or - * false with no restrictions. */ - void set_lazy(bool lazy); - - /* Defaults to true. Sets whether this field is encoded in packed format. */ - void set_packed(bool packed); - - /* "type" or "descriptor_type" MUST be set explicitly before the fielddef is - * finalized. These setters require that the enum value is valid; if the - * value did not come directly from an enum constant, the caller should - * validate it first with the functions above (CheckFieldType(), etc). */ - void set_type(Type type); - void set_label(Label label); - void set_descriptor_type(DescriptorType type); - void set_is_extension(bool is_extension); - - /* "number" and "name" must be set before the FieldDef is added to a - * MessageDef, and may not be set after that. - * - * "name" is the same as full_name()/set_full_name(), but since fielddefs - * most often use simple, non-qualified names, we provide this accessor - * also. Generally only extensions will want to think of this name as - * fully-qualified. */ - bool set_number(uint32_t number, upb::Status* s); - bool set_name(const char* name, upb::Status* s); - bool set_name(const std::string& name, upb::Status* s); - - /* Sets the JSON name to the given string. */ - /* TODO(haberman): implement. Right now only default json_name (camelCase) - * is supported. */ - bool set_json_name(const char* json_name, upb::Status* s); - bool set_json_name(const std::string& name, upb::Status* s); - - /* Clears the JSON name. This will make it revert to its default, which is - * a camelCased version of the regular field name. */ - void clear_json_name(); - - void set_integer_format(IntegerFormat format); - bool set_tag_delimited(bool tag_delimited, upb::Status* s); - - /* Sets default value for the field. The call must exactly match the type - * of the field. Enum fields may use either setint32 or setstring to set - * the default numerically or symbolically, respectively, but symbolic - * defaults must be resolved before finalizing (see ResolveEnumDefault()). - * - * Changing the type of a field will reset its default. */ - void set_default_int64(int64_t val); - void set_default_int32(int32_t val); - void set_default_uint64(uint64_t val); - void set_default_uint32(uint32_t val); - void set_default_bool(bool val); - void set_default_float(float val); - void set_default_double(double val); - bool set_default_string(const void *str, size_t len, Status *s); - bool set_default_string(const std::string &str, Status *s); - void set_default_cstr(const char *str, Status *s); - - /* Before a fielddef is frozen, its subdef may be set either directly (with a - * upb::Def*) or symbolically. Symbolic refs must be resolved before the - * containing msgdef can be frozen (see upb_resolve() above). upb always - * guarantees that any def reachable from a live def will also be kept alive. - * - * Both methods require that upb_hassubdef(f) (so the type must be set prior - * to calling these methods). Returns false if this is not the case, or if - * the given subdef is not of the correct type. The subdef is reset if the - * field's type is changed. The subdef can be set to NULL to clear it. */ - bool set_subdef(const Def* subdef, Status* s); - bool set_enum_subdef(const EnumDef* subdef, Status* s); - bool set_message_subdef(const MessageDef* subdef, Status* s); - bool set_subdef_name(const char* name, Status* s); - bool set_subdef_name(const std::string &name, Status* s); - - private: - UPB_DISALLOW_POD_OPS(FieldDef, upb::FieldDef) -}; - -# endif /* defined(__cplusplus) */ - -UPB_BEGIN_EXTERN_C - -/* Native C API. */ -upb_fielddef *upb_fielddef_new(const void *owner); - -/* Include upb_refcounted methods like upb_fielddef_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_fielddef, upb_fielddef_upcast2) - -/* Methods from upb_def. */ -const char *upb_fielddef_fullname(const upb_fielddef *f); -bool upb_fielddef_setfullname(upb_fielddef *f, const char *fullname, - upb_status *s); - -bool upb_fielddef_typeisset(const upb_fielddef *f); -upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f); -upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f); -upb_label_t upb_fielddef_label(const upb_fielddef *f); -uint32_t upb_fielddef_number(const upb_fielddef *f); -const char *upb_fielddef_name(const upb_fielddef *f); -bool upb_fielddef_isextension(const upb_fielddef *f); -bool upb_fielddef_lazy(const upb_fielddef *f); -bool upb_fielddef_packed(const upb_fielddef *f); -size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len); -const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f); -const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f); -upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f); -const char *upb_fielddef_containingtypename(upb_fielddef *f); -upb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f); -uint32_t upb_fielddef_index(const upb_fielddef *f); -bool upb_fielddef_istagdelim(const upb_fielddef *f); -bool upb_fielddef_issubmsg(const upb_fielddef *f); -bool upb_fielddef_isstring(const upb_fielddef *f); -bool upb_fielddef_isseq(const upb_fielddef *f); -bool upb_fielddef_isprimitive(const upb_fielddef *f); -bool upb_fielddef_ismap(const upb_fielddef *f); -bool upb_fielddef_haspresence(const upb_fielddef *f); -int64_t upb_fielddef_defaultint64(const upb_fielddef *f); -int32_t upb_fielddef_defaultint32(const upb_fielddef *f); -uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f); -uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f); -bool upb_fielddef_defaultbool(const upb_fielddef *f); -float upb_fielddef_defaultfloat(const upb_fielddef *f); -double upb_fielddef_defaultdouble(const upb_fielddef *f); -const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len); -bool upb_fielddef_enumhasdefaultint32(const upb_fielddef *f); -bool upb_fielddef_enumhasdefaultstr(const upb_fielddef *f); -bool upb_fielddef_hassubdef(const upb_fielddef *f); -const upb_def *upb_fielddef_subdef(const upb_fielddef *f); -const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f); -const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f); -const char *upb_fielddef_subdefname(const upb_fielddef *f); - -void upb_fielddef_settype(upb_fielddef *f, upb_fieldtype_t type); -void upb_fielddef_setdescriptortype(upb_fielddef *f, int type); -void upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label); -bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s); -bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s); -bool upb_fielddef_setjsonname(upb_fielddef *f, const char *name, upb_status *s); -bool upb_fielddef_clearjsonname(upb_fielddef *f); -bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name, - upb_status *s); -void upb_fielddef_setisextension(upb_fielddef *f, bool is_extension); -void upb_fielddef_setlazy(upb_fielddef *f, bool lazy); -void upb_fielddef_setpacked(upb_fielddef *f, bool packed); -void upb_fielddef_setintfmt(upb_fielddef *f, upb_intfmt_t fmt); -void upb_fielddef_settagdelim(upb_fielddef *f, bool tag_delim); -void upb_fielddef_setdefaultint64(upb_fielddef *f, int64_t val); -void upb_fielddef_setdefaultint32(upb_fielddef *f, int32_t val); -void upb_fielddef_setdefaultuint64(upb_fielddef *f, uint64_t val); -void upb_fielddef_setdefaultuint32(upb_fielddef *f, uint32_t val); -void upb_fielddef_setdefaultbool(upb_fielddef *f, bool val); -void upb_fielddef_setdefaultfloat(upb_fielddef *f, float val); -void upb_fielddef_setdefaultdouble(upb_fielddef *f, double val); -bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len, - upb_status *s); -void upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str, - upb_status *s); -bool upb_fielddef_setsubdef(upb_fielddef *f, const upb_def *subdef, - upb_status *s); -bool upb_fielddef_setmsgsubdef(upb_fielddef *f, const upb_msgdef *subdef, - upb_status *s); -bool upb_fielddef_setenumsubdef(upb_fielddef *f, const upb_enumdef *subdef, - upb_status *s); -bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name, - upb_status *s); - -bool upb_fielddef_checklabel(int32_t label); -bool upb_fielddef_checktype(int32_t type); -bool upb_fielddef_checkdescriptortype(int32_t type); -bool upb_fielddef_checkintfmt(int32_t fmt); - -UPB_END_EXTERN_C - - -/* upb::MessageDef ************************************************************/ - -typedef upb_inttable_iter upb_msg_field_iter; -typedef upb_strtable_iter upb_msg_oneof_iter; - -/* Well-known field tag numbers for map-entry messages. */ -#define UPB_MAPENTRY_KEY 1 -#define UPB_MAPENTRY_VALUE 2 - -#ifdef __cplusplus - -/* Structure that describes a single .proto message type. - * - * Its base class is upb::Def (use upb::upcast() to convert). */ -class upb::MessageDef { - public: - /* Returns NULL if memory allocation failed. */ - static reffed_ptr New(); - - /* upb::RefCounted methods like Ref()/Unref(). */ - UPB_REFCOUNTED_CPPMETHODS - - /* Functionality from upb::Def. */ - const char* full_name() const; - const char* name() const; - bool set_full_name(const char* fullname, Status* s); - bool set_full_name(const std::string& fullname, Status* s); - - /* Call to freeze this MessageDef. - * WARNING: this will fail if this message has any unfrozen submessages! - * Messages with cycles must be frozen as a batch using upb::Def::Freeze(). */ - bool Freeze(Status* s); - - /* The number of fields that belong to the MessageDef. */ - int field_count() const; - - /* The number of oneofs that belong to the MessageDef. */ - int oneof_count() const; - - /* Adds a field (upb_fielddef object) to a msgdef. Requires that the msgdef - * and the fielddefs are mutable. The fielddef's name and number must be - * set, and the message may not already contain any field with this name or - * number, and this fielddef may not be part of another message. In error - * cases false is returned and the msgdef is unchanged. - * - * If the given field is part of a oneof, this call succeeds if and only if - * that oneof is already part of this msgdef. (Note that adding a oneof to a - * msgdef automatically adds all of its fields to the msgdef at the time that - * the oneof is added, so it is usually more idiomatic to add the oneof's - * fields first then add the oneof to the msgdef. This case is supported for - * convenience.) - * - * If |f| is already part of this MessageDef, this method performs no action - * and returns true (success). Thus, this method is idempotent. */ - bool AddField(FieldDef* f, Status* s); - bool AddField(const reffed_ptr& f, Status* s); - - /* Adds a oneof (upb_oneofdef object) to a msgdef. Requires that the msgdef, - * oneof, and any fielddefs are mutable, that the fielddefs contained in the - * oneof do not have any name or number conflicts with existing fields in the - * msgdef, and that the oneof's name is unique among all oneofs in the msgdef. - * If the oneof is added successfully, all of its fields will be added - * directly to the msgdef as well. In error cases, false is returned and the - * msgdef is unchanged. */ - bool AddOneof(OneofDef* o, Status* s); - bool AddOneof(const reffed_ptr& o, Status* s); - - upb_syntax_t syntax() const; - - /* Returns false if we don't support this syntax value. */ - bool set_syntax(upb_syntax_t syntax); - - /* Set this to false to indicate that primitive fields should not have - * explicit presence information associated with them. This will affect all - * fields added to this message. Defaults to true. */ - void SetPrimitivesHavePresence(bool have_presence); - - /* These return NULL if the field is not found. */ - FieldDef* FindFieldByNumber(uint32_t number); - FieldDef* FindFieldByName(const char *name, size_t len); - const FieldDef* FindFieldByNumber(uint32_t number) const; - const FieldDef* FindFieldByName(const char* name, size_t len) const; - - - FieldDef* FindFieldByName(const char *name) { - return FindFieldByName(name, strlen(name)); - } - const FieldDef* FindFieldByName(const char *name) const { - return FindFieldByName(name, strlen(name)); - } - - template - FieldDef* FindFieldByName(const T& str) { - return FindFieldByName(str.c_str(), str.size()); - } - template - const FieldDef* FindFieldByName(const T& str) const { - return FindFieldByName(str.c_str(), str.size()); - } - - OneofDef* FindOneofByName(const char* name, size_t len); - const OneofDef* FindOneofByName(const char* name, size_t len) const; - - OneofDef* FindOneofByName(const char* name) { - return FindOneofByName(name, strlen(name)); - } - const OneofDef* FindOneofByName(const char* name) const { - return FindOneofByName(name, strlen(name)); - } - - template - OneofDef* FindOneofByName(const T& str) { - return FindOneofByName(str.c_str(), str.size()); - } - template - const OneofDef* FindOneofByName(const T& str) const { - return FindOneofByName(str.c_str(), str.size()); - } - - /* Is this message a map entry? */ - void setmapentry(bool map_entry); - bool mapentry() const; - - /* Iteration over fields. The order is undefined. */ - class field_iterator - : public std::iterator { - public: - explicit field_iterator(MessageDef* md); - static field_iterator end(MessageDef* md); - - void operator++(); - FieldDef* operator*() const; - bool operator!=(const field_iterator& other) const; - bool operator==(const field_iterator& other) const; - - private: - upb_msg_field_iter iter_; - }; - - class const_field_iterator - : public std::iterator { - public: - explicit const_field_iterator(const MessageDef* md); - static const_field_iterator end(const MessageDef* md); - - void operator++(); - const FieldDef* operator*() const; - bool operator!=(const const_field_iterator& other) const; - bool operator==(const const_field_iterator& other) const; - - private: - upb_msg_field_iter iter_; - }; - - /* Iteration over oneofs. The order is undefined. */ - class oneof_iterator - : public std::iterator { - public: - explicit oneof_iterator(MessageDef* md); - static oneof_iterator end(MessageDef* md); - - void operator++(); - OneofDef* operator*() const; - bool operator!=(const oneof_iterator& other) const; - bool operator==(const oneof_iterator& other) const; - - private: - upb_msg_oneof_iter iter_; - }; - - class const_oneof_iterator - : public std::iterator { - public: - explicit const_oneof_iterator(const MessageDef* md); - static const_oneof_iterator end(const MessageDef* md); - - void operator++(); - const OneofDef* operator*() const; - bool operator!=(const const_oneof_iterator& other) const; - bool operator==(const const_oneof_iterator& other) const; - - private: - upb_msg_oneof_iter iter_; - }; - - class FieldAccessor { - public: - explicit FieldAccessor(MessageDef* msg) : msg_(msg) {} - field_iterator begin() { return msg_->field_begin(); } - field_iterator end() { return msg_->field_end(); } - private: - MessageDef* msg_; - }; - - class ConstFieldAccessor { - public: - explicit ConstFieldAccessor(const MessageDef* msg) : msg_(msg) {} - const_field_iterator begin() { return msg_->field_begin(); } - const_field_iterator end() { return msg_->field_end(); } - private: - const MessageDef* msg_; - }; - - class OneofAccessor { - public: - explicit OneofAccessor(MessageDef* msg) : msg_(msg) {} - oneof_iterator begin() { return msg_->oneof_begin(); } - oneof_iterator end() { return msg_->oneof_end(); } - private: - MessageDef* msg_; - }; - - class ConstOneofAccessor { - public: - explicit ConstOneofAccessor(const MessageDef* msg) : msg_(msg) {} - const_oneof_iterator begin() { return msg_->oneof_begin(); } - const_oneof_iterator end() { return msg_->oneof_end(); } - private: - const MessageDef* msg_; - }; - - field_iterator field_begin(); - field_iterator field_end(); - const_field_iterator field_begin() const; - const_field_iterator field_end() const; - - oneof_iterator oneof_begin(); - oneof_iterator oneof_end(); - const_oneof_iterator oneof_begin() const; - const_oneof_iterator oneof_end() const; - - FieldAccessor fields() { return FieldAccessor(this); } - ConstFieldAccessor fields() const { return ConstFieldAccessor(this); } - OneofAccessor oneofs() { return OneofAccessor(this); } - ConstOneofAccessor oneofs() const { return ConstOneofAccessor(this); } - - private: - UPB_DISALLOW_POD_OPS(MessageDef, upb::MessageDef) -}; - -#endif /* __cplusplus */ - -UPB_BEGIN_EXTERN_C - -/* Returns NULL if memory allocation failed. */ -upb_msgdef *upb_msgdef_new(const void *owner); - -/* Include upb_refcounted methods like upb_msgdef_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_msgdef, upb_msgdef_upcast2) - -bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status); - -const char *upb_msgdef_fullname(const upb_msgdef *m); -const char *upb_msgdef_name(const upb_msgdef *m); -int upb_msgdef_numoneofs(const upb_msgdef *m); -upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m); - -bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor, - upb_status *s); -bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, - upb_status *s); -bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, upb_status *s); -void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry); -bool upb_msgdef_mapentry(const upb_msgdef *m); -bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax); - -/* Field lookup in a couple of different variations: - * - itof = int to field - * - ntof = name to field - * - ntofz = name to field, null-terminated string. */ -const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i); -const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name, - size_t len); -int upb_msgdef_numfields(const upb_msgdef *m); - -UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m, - const char *name) { - return upb_msgdef_ntof(m, name, strlen(name)); -} - -UPB_INLINE upb_fielddef *upb_msgdef_itof_mutable(upb_msgdef *m, uint32_t i) { - return (upb_fielddef*)upb_msgdef_itof(m, i); -} - -UPB_INLINE upb_fielddef *upb_msgdef_ntof_mutable(upb_msgdef *m, - const char *name, size_t len) { - return (upb_fielddef *)upb_msgdef_ntof(m, name, len); -} - -/* Oneof lookup: - * - ntoo = name to oneof - * - ntooz = name to oneof, null-terminated string. */ -const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, - size_t len); -int upb_msgdef_numoneofs(const upb_msgdef *m); - -UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m, - const char *name) { - return upb_msgdef_ntoo(m, name, strlen(name)); -} - -UPB_INLINE upb_oneofdef *upb_msgdef_ntoo_mutable(upb_msgdef *m, - const char *name, size_t len) { - return (upb_oneofdef *)upb_msgdef_ntoo(m, name, len); -} - -/* Lookup of either field or oneof by name. Returns whether either was found. - * If the return is true, then the found def will be set, and the non-found - * one set to NULL. */ -bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len, - const upb_fielddef **f, const upb_oneofdef **o); - -UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name, - const upb_fielddef **f, - const upb_oneofdef **o) { - return upb_msgdef_lookupname(m, name, strlen(name), f, o); -} - -/* Iteration over fields and oneofs. For example: - * - * upb_msg_field_iter i; - * for(upb_msg_field_begin(&i, m); - * !upb_msg_field_done(&i); - * upb_msg_field_next(&i)) { - * upb_fielddef *f = upb_msg_iter_field(&i); - * // ... - * } - * - * For C we don't have separate iterators for const and non-const. - * It is the caller's responsibility to cast the upb_fielddef* to - * const if the upb_msgdef* is const. */ -void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m); -void upb_msg_field_next(upb_msg_field_iter *iter); -bool upb_msg_field_done(const upb_msg_field_iter *iter); -upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter); -void upb_msg_field_iter_setdone(upb_msg_field_iter *iter); - -/* Similar to above, we also support iterating through the oneofs in a - * msgdef. */ -void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m); -void upb_msg_oneof_next(upb_msg_oneof_iter *iter); -bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter); -upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter); -void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter); - -UPB_END_EXTERN_C - - -/* upb::EnumDef ***************************************************************/ - -typedef upb_strtable_iter upb_enum_iter; - -#ifdef __cplusplus - -/* Class that represents an enum. Its base class is upb::Def (convert with - * upb::upcast()). */ -class upb::EnumDef { - public: - /* Returns NULL if memory allocation failed. */ - static reffed_ptr New(); - - /* upb::RefCounted methods like Ref()/Unref(). */ - UPB_REFCOUNTED_CPPMETHODS - - /* Functionality from upb::Def. */ - const char* full_name() const; - const char* name() const; - bool set_full_name(const char* fullname, Status* s); - bool set_full_name(const std::string& fullname, Status* s); - - /* Call to freeze this EnumDef. */ - bool Freeze(Status* s); - - /* 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. - * Requires that value_count() > 0. */ - int32_t default_value() const; - - /* Sets the default value. If this value is not valid, returns false and an - * error message in status. */ - bool set_default_value(int32_t val, Status* status); - - /* Returns the number of values currently defined in the enum. Note that - * multiple names can refer to the same number, so this may be greater than - * the total number of unique numbers. */ - int value_count() const; - - /* Adds a single name/number pair to the enum. Fails if this name has - * already been used by another value. */ - bool AddValue(const char* name, int32_t num, Status* status); - bool AddValue(const std::string& name, int32_t num, Status* status); - - /* Lookups from name to integer, returning true if found. */ - bool FindValueByName(const char* name, int32_t* num) const; - - /* Finds the name corresponding to the given number, or NULL if none was - * found. If more than one name corresponds to this number, returns the - * first one that was added. */ - const char* FindValueByNumber(int32_t num) const; - - /* Iteration over name/value pairs. The order is undefined. - * Adding an enum val invalidates any iterators. - * - * TODO: make compatible with range-for, with elements as pairs? */ - class Iterator { - public: - explicit Iterator(const EnumDef*); - - int32_t number(); - const char *name(); - bool Done(); - void Next(); - - private: - upb_enum_iter iter_; - }; - - private: - UPB_DISALLOW_POD_OPS(EnumDef, upb::EnumDef) -}; - -#endif /* __cplusplus */ - -UPB_BEGIN_EXTERN_C - -/* Native C API. */ -upb_enumdef *upb_enumdef_new(const void *owner); - -/* Include upb_refcounted methods like upb_enumdef_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_enumdef, upb_enumdef_upcast2) - -bool upb_enumdef_freeze(upb_enumdef *e, upb_status *status); - -/* From upb_def. */ -const char *upb_enumdef_fullname(const upb_enumdef *e); -const char *upb_enumdef_name(const upb_enumdef *e); -bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname, - upb_status *s); - -int32_t upb_enumdef_default(const upb_enumdef *e); -bool upb_enumdef_setdefault(upb_enumdef *e, int32_t val, upb_status *s); -int upb_enumdef_numvals(const upb_enumdef *e); -bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num, - upb_status *status); - -/* Enum lookups: - * - ntoi: look up a name with specified length. - * - ntoiz: look up a name provided as a null-terminated string. - * - iton: look up an integer, returning the name as a null-terminated - * string. */ -bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len, - int32_t *num); -UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e, - const char *name, int32_t *num) { - return upb_enumdef_ntoi(e, name, strlen(name), num); -} -const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num); - -/* upb_enum_iter i; - * for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) { - * // ... - * } - */ -void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e); -void upb_enum_next(upb_enum_iter *iter); -bool upb_enum_done(upb_enum_iter *iter); -const char *upb_enum_iter_name(upb_enum_iter *iter); -int32_t upb_enum_iter_number(upb_enum_iter *iter); - -UPB_END_EXTERN_C - - -/* upb::OneofDef **************************************************************/ - -typedef upb_inttable_iter upb_oneof_iter; - -#ifdef __cplusplus - -/* Class that represents a oneof. */ -class upb::OneofDef { - public: - /* Returns NULL if memory allocation failed. */ - static reffed_ptr New(); - - /* upb::RefCounted methods like Ref()/Unref(). */ - UPB_REFCOUNTED_CPPMETHODS - - /* Returns the MessageDef that owns this OneofDef. */ - const MessageDef* containing_type() const; - - /* Returns the name of this oneof. This is the name used to look up the oneof - * by name once added to a message def. */ - const char* name() const; - bool set_name(const char* name, Status* s); - bool set_name(const std::string& name, Status* s); - - /* Returns the number of fields currently defined in the oneof. */ - int field_count() const; - - /* Adds a field to the oneof. The field must not have been added to any other - * oneof or msgdef. If the oneof is not yet part of a msgdef, then when the - * oneof is eventually added to a msgdef, all fields added to the oneof will - * also be added to the msgdef at that time. If the oneof is already part of a - * msgdef, the field must either be a part of that msgdef already, or must not - * be a part of any msgdef; in the latter case, the field is added to the - * msgdef as a part of this operation. - * - * The field may only have an OPTIONAL label, never REQUIRED or REPEATED. - * - * If |f| is already part of this MessageDef, this method performs no action - * and returns true (success). Thus, this method is idempotent. */ - bool AddField(FieldDef* field, Status* s); - bool AddField(const reffed_ptr& field, Status* s); - - /* Looks up by name. */ - const FieldDef* FindFieldByName(const char* name, size_t len) const; - FieldDef* FindFieldByName(const char* name, size_t len); - const FieldDef* FindFieldByName(const char* name) const { - return FindFieldByName(name, strlen(name)); - } - FieldDef* FindFieldByName(const char* name) { - return FindFieldByName(name, strlen(name)); - } - - template - FieldDef* FindFieldByName(const T& str) { - return FindFieldByName(str.c_str(), str.size()); - } - template - const FieldDef* FindFieldByName(const T& str) const { - return FindFieldByName(str.c_str(), str.size()); - } - - /* Looks up by tag number. */ - const FieldDef* FindFieldByNumber(uint32_t num) const; - - /* Iteration over fields. The order is undefined. */ - class iterator : public std::iterator { - public: - explicit iterator(OneofDef* md); - static iterator end(OneofDef* md); - - void operator++(); - FieldDef* operator*() const; - bool operator!=(const iterator& other) const; - bool operator==(const iterator& other) const; - - private: - upb_oneof_iter iter_; - }; - - class const_iterator - : public std::iterator { - public: - explicit const_iterator(const OneofDef* md); - static const_iterator end(const OneofDef* md); - - void operator++(); - const FieldDef* operator*() const; - bool operator!=(const const_iterator& other) const; - bool operator==(const const_iterator& other) const; - - private: - upb_oneof_iter iter_; - }; - - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; - - private: - UPB_DISALLOW_POD_OPS(OneofDef, upb::OneofDef) -}; - -#endif /* __cplusplus */ - -UPB_BEGIN_EXTERN_C - -/* Native C API. */ -upb_oneofdef *upb_oneofdef_new(const void *owner); - -/* Include upb_refcounted methods like upb_oneofdef_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_oneofdef, upb_oneofdef_upcast) - -const char *upb_oneofdef_name(const upb_oneofdef *o); -const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o); -int upb_oneofdef_numfields(const upb_oneofdef *o); -uint32_t upb_oneofdef_index(const upb_oneofdef *o); - -bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s); -bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f, - const void *ref_donor, - upb_status *s); - -/* Oneof lookups: - * - ntof: look up a field by name. - * - ntofz: look up a field by name (as a null-terminated string). - * - itof: look up a field by number. */ -const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, - const char *name, size_t length); -UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o, - const char *name) { - return upb_oneofdef_ntof(o, name, strlen(name)); -} -const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num); - -/* upb_oneof_iter i; - * for(upb_oneof_begin(&i, e); !upb_oneof_done(&i); upb_oneof_next(&i)) { - * // ... - * } - */ -void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o); -void upb_oneof_next(upb_oneof_iter *iter); -bool upb_oneof_done(upb_oneof_iter *iter); -upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter); -void upb_oneof_iter_setdone(upb_oneof_iter *iter); - -UPB_END_EXTERN_C - - -/* upb::FileDef ***************************************************************/ - -#ifdef __cplusplus - -/* Class that represents a .proto file with some things defined in it. - * - * Many users won't care about FileDefs, but they are necessary if you want to - * read the values of file-level options. */ -class upb::FileDef { - public: - /* Returns NULL if memory allocation failed. */ - static reffed_ptr New(); - - /* upb::RefCounted methods like Ref()/Unref(). */ - UPB_REFCOUNTED_CPPMETHODS - - /* Get/set name of the file (eg. "foo/bar.proto"). */ - const char* name() const; - bool set_name(const char* name, Status* s); - bool set_name(const std::string& name, Status* s); - - /* Package name for definitions inside the file (eg. "foo.bar"). */ - const char* package() const; - bool set_package(const char* package, Status* s); - - /* Sets the php class prefix which is prepended to all php generated classes - * from this .proto. Default is empty. */ - const char* phpprefix() const; - bool set_phpprefix(const char* phpprefix, Status* s); - - /* Use this option to change the namespace of php generated classes. Default - * is empty. When this option is empty, the package name will be used for - * determining the namespace. */ - const char* phpnamespace() const; - bool set_phpnamespace(const char* phpnamespace, Status* s); - - /* Syntax for the file. Defaults to proto2. */ - upb_syntax_t syntax() const; - void set_syntax(upb_syntax_t syntax); - - /* Get the list of defs from the file. These are returned in the order that - * they were added to the FileDef. */ - int def_count() const; - const Def* def(int index) const; - Def* def(int index); - - /* Get the list of dependencies from the file. These are returned in the - * order that they were added to the FileDef. */ - int dependency_count() const; - const FileDef* dependency(int index) const; - - /* Adds defs to this file. The def must not already belong to another - * file. - * - * Note: this does *not* ensure that this def's name is unique in this file! - * Use a SymbolTable if you want to check this property. Especially since - * properly checking uniqueness would require a check across *all* files - * (including dependencies). */ - bool AddDef(Def* def, Status* s); - bool AddMessage(MessageDef* m, Status* s); - bool AddEnum(EnumDef* e, Status* s); - bool AddExtension(FieldDef* f, Status* s); - - /* Adds a dependency of this file. */ - bool AddDependency(const FileDef* file); - - /* Freezes this FileDef and all messages/enums under it. All subdefs must be - * resolved and all messages/enums must validate. Returns true if this - * succeeded. - * - * TODO(haberman): should we care whether the file's dependencies are frozen - * already? */ - bool Freeze(Status* s); - - private: - UPB_DISALLOW_POD_OPS(FileDef, upb::FileDef) -}; - -#endif - -UPB_BEGIN_EXTERN_C - -upb_filedef *upb_filedef_new(const void *owner); - -/* Include upb_refcounted methods like upb_msgdef_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_filedef, upb_filedef_upcast) - -const char *upb_filedef_name(const upb_filedef *f); -const char *upb_filedef_package(const upb_filedef *f); -const char *upb_filedef_phpprefix(const upb_filedef *f); -const char *upb_filedef_phpnamespace(const upb_filedef *f); -upb_syntax_t upb_filedef_syntax(const upb_filedef *f); -size_t upb_filedef_defcount(const upb_filedef *f); -size_t upb_filedef_depcount(const upb_filedef *f); -const upb_def *upb_filedef_def(const upb_filedef *f, size_t i); -const upb_filedef *upb_filedef_dep(const upb_filedef *f, size_t i); - -bool upb_filedef_freeze(upb_filedef *f, upb_status *s); -bool upb_filedef_setname(upb_filedef *f, const char *name, upb_status *s); -bool upb_filedef_setpackage(upb_filedef *f, const char *package, upb_status *s); -bool upb_filedef_setphpprefix(upb_filedef *f, const char *phpprefix, - upb_status *s); -bool upb_filedef_setphpnamespace(upb_filedef *f, const char *phpnamespace, - upb_status *s); -bool upb_filedef_setsyntax(upb_filedef *f, upb_syntax_t syntax, upb_status *s); - -bool upb_filedef_adddef(upb_filedef *f, upb_def *def, const void *ref_donor, - upb_status *s); -bool upb_filedef_adddep(upb_filedef *f, const upb_filedef *dep); - -UPB_INLINE bool upb_filedef_addmsg(upb_filedef *f, upb_msgdef *m, - const void *ref_donor, upb_status *s) { - return upb_filedef_adddef(f, upb_msgdef_upcast_mutable(m), ref_donor, s); -} - -UPB_INLINE bool upb_filedef_addenum(upb_filedef *f, upb_enumdef *e, - const void *ref_donor, upb_status *s) { - return upb_filedef_adddef(f, upb_enumdef_upcast_mutable(e), ref_donor, s); -} - -UPB_INLINE bool upb_filedef_addext(upb_filedef *file, upb_fielddef *f, - const void *ref_donor, upb_status *s) { - return upb_filedef_adddef(file, upb_fielddef_upcast_mutable(f), ref_donor, s); -} -UPB_INLINE upb_def *upb_filedef_mutabledef(upb_filedef *f, int i) { - return (upb_def*)upb_filedef_def(f, i); -} - -UPB_END_EXTERN_C - -typedef struct { - UPB_PRIVATE_FOR_CPP - upb_strtable_iter iter; - upb_deftype_t type; -} upb_symtab_iter; - -#ifdef __cplusplus - -/* Non-const methods in upb::SymbolTable are NOT thread-safe. */ -class upb::SymbolTable { - public: - /* Returns a new symbol table with a single ref owned by "owner." - * Returns NULL if memory allocation failed. */ - static SymbolTable* New(); - static void Free(upb::SymbolTable* table); - - /* For all lookup functions, the returned pointer is not owned by the - * caller; it may be invalidated by any non-const call or unref of the - * SymbolTable! To protect against this, take a ref if desired. */ - - /* Freezes the symbol table: prevents further modification of it. - * After the Freeze() operation is successful, the SymbolTable must only be - * accessed via a const pointer. - * - * Unlike with upb::MessageDef/upb::EnumDef/etc, freezing a SymbolTable is not - * a necessary step in using a SymbolTable. If you have no need for it to be - * immutable, there is no need to freeze it ever. However sometimes it is - * useful, and SymbolTables that are statically compiled into the binary are - * always frozen by nature. */ - void Freeze(); - - /* Resolves the given symbol using the rules described in descriptor.proto, - * namely: - * - * If the name starts with a '.', it is fully-qualified. Otherwise, - * C++-like scoping rules are used to find the type (i.e. first the nested - * types within this message are searched, then within the parent, on up - * to the root namespace). - * - * If not found, returns NULL. */ - const Def* Resolve(const char* base, const char* sym) const; - - /* Finds an entry in the symbol table with this exact name. If not found, - * returns NULL. */ - const Def* Lookup(const char *sym) const; - const MessageDef* LookupMessage(const char *sym) const; - const EnumDef* LookupEnum(const char *sym) const; - - /* TODO: introduce a C++ iterator, but make it nice and templated so that if - * you ask for an iterator of MessageDef the iterated elements are strongly - * typed as MessageDef*. */ - - /* Adds the given mutable defs to the symtab, resolving all symbols (including - * enum default values) and finalizing the defs. Only one def per name may be - * in the list, and the defs may not duplicate any name already in the symtab. - * All defs must have a name -- anonymous defs are not allowed. Anonymous - * defs can still be frozen by calling upb_def_freeze() directly. - * - * The entire operation either succeeds or fails. If the operation fails, - * the symtab is unchanged, false is returned, and status indicates the - * error. The caller passes a ref on all defs to the symtab (even if the - * operation fails). - * - * TODO(haberman): currently failure will leave the symtab unchanged, but may - * leave the defs themselves partially resolved. Does this matter? If so we - * could do a prepass that ensures that all symbols are resolvable and bail - * if not, so we don't mutate anything until we know the operation will - * succeed. */ - bool Add(Def*const* defs, size_t n, void* ref_donor, Status* status); - - bool Add(const std::vector& defs, void *owner, Status* status) { - return Add((Def*const*)&defs[0], defs.size(), owner, status); - } - - /* Resolves all subdefs for messages in this file and attempts to freeze the - * file. If this succeeds, adds all the symbols to this SymbolTable - * (replacing any existing ones with the same names). */ - bool AddFile(FileDef* file, Status* s); - - private: - UPB_DISALLOW_POD_OPS(SymbolTable, upb::SymbolTable) -}; - -#endif /* __cplusplus */ - -UPB_BEGIN_EXTERN_C - -/* Native C API. */ - -upb_symtab *upb_symtab_new(); -void upb_symtab_free(upb_symtab* s); -const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, - const char *sym); -const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym); -const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym); -const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym); -bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, size_t n, - void *ref_donor, upb_status *status); -bool upb_symtab_addfile(upb_symtab *s, upb_filedef *file, upb_status* status); - -/* upb_symtab_iter i; - * for(upb_symtab_begin(&i, s, type); !upb_symtab_done(&i); - * upb_symtab_next(&i)) { - * const upb_def *def = upb_symtab_iter_def(&i); - * // ... - * } - * - * For C we don't have separate iterators for const and non-const. - * It is the caller's responsibility to cast the upb_fielddef* to - * const if the upb_msgdef* is const. */ -void upb_symtab_begin(upb_symtab_iter *iter, const upb_symtab *s, - upb_deftype_t type); -void upb_symtab_next(upb_symtab_iter *iter); -bool upb_symtab_done(const upb_symtab_iter *iter); -const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter); - -UPB_END_EXTERN_C - -#ifdef __cplusplus -/* C++ inline wrappers. */ -namespace upb { -inline SymbolTable* SymbolTable::New() { - return upb_symtab_new(); -} -inline void SymbolTable::Free(SymbolTable* s) { - upb_symtab_free(s); -} -inline const Def *SymbolTable::Resolve(const char *base, - const char *sym) const { - return upb_symtab_resolve(this, base, sym); -} -inline const Def* SymbolTable::Lookup(const char *sym) const { - return upb_symtab_lookup(this, sym); -} -inline const MessageDef *SymbolTable::LookupMessage(const char *sym) const { - return upb_symtab_lookupmsg(this, sym); -} -inline bool SymbolTable::Add( - Def*const* defs, size_t n, void* ref_donor, Status* status) { - return upb_symtab_add(this, (upb_def*const*)defs, n, ref_donor, status); -} -inline bool SymbolTable::AddFile(FileDef* file, Status* s) { - return upb_symtab_addfile(this, file, s); -} -} /* namespace upb */ -#endif - -#ifdef __cplusplus - -UPB_INLINE const char* upb_safecstr(const std::string& str) { - UPB_ASSERT(str.size() == std::strlen(str.c_str())); - return str.c_str(); -} - -/* Inline C++ wrappers. */ -namespace upb { - -inline Def::Type Def::def_type() const { return upb_def_type(this); } -inline const char* Def::full_name() const { return upb_def_fullname(this); } -inline const char* Def::name() const { return upb_def_name(this); } -inline bool Def::set_full_name(const char* fullname, Status* s) { - return upb_def_setfullname(this, fullname, s); -} -inline bool Def::set_full_name(const std::string& fullname, Status* s) { - return upb_def_setfullname(this, upb_safecstr(fullname), s); -} -inline bool Def::Freeze(Def* const* defs, size_t n, Status* status) { - return upb_def_freeze(defs, n, status); -} -inline bool Def::Freeze(const std::vector& defs, Status* status) { - return upb_def_freeze((Def* const*)&defs[0], defs.size(), status); -} - -inline bool FieldDef::CheckType(int32_t val) { - return upb_fielddef_checktype(val); -} -inline bool FieldDef::CheckLabel(int32_t val) { - return upb_fielddef_checklabel(val); -} -inline bool FieldDef::CheckDescriptorType(int32_t val) { - return upb_fielddef_checkdescriptortype(val); -} -inline bool FieldDef::CheckIntegerFormat(int32_t val) { - return upb_fielddef_checkintfmt(val); -} -inline FieldDef::Type FieldDef::ConvertType(int32_t val) { - UPB_ASSERT(CheckType(val)); - return static_cast(val); -} -inline FieldDef::Label FieldDef::ConvertLabel(int32_t val) { - UPB_ASSERT(CheckLabel(val)); - return static_cast(val); -} -inline FieldDef::DescriptorType FieldDef::ConvertDescriptorType(int32_t val) { - UPB_ASSERT(CheckDescriptorType(val)); - return static_cast(val); -} -inline FieldDef::IntegerFormat FieldDef::ConvertIntegerFormat(int32_t val) { - UPB_ASSERT(CheckIntegerFormat(val)); - return static_cast(val); -} - -inline reffed_ptr FieldDef::New() { - upb_fielddef *f = upb_fielddef_new(&f); - return reffed_ptr(f, &f); -} -inline const char* FieldDef::full_name() const { - return upb_fielddef_fullname(this); -} -inline bool FieldDef::set_full_name(const char* fullname, Status* s) { - return upb_fielddef_setfullname(this, fullname, s); -} -inline bool FieldDef::set_full_name(const std::string& fullname, Status* s) { - return upb_fielddef_setfullname(this, upb_safecstr(fullname), s); -} -inline bool FieldDef::type_is_set() const { - return upb_fielddef_typeisset(this); -} -inline FieldDef::Type FieldDef::type() const { return upb_fielddef_type(this); } -inline FieldDef::DescriptorType FieldDef::descriptor_type() const { - return upb_fielddef_descriptortype(this); -} -inline FieldDef::Label FieldDef::label() const { - return upb_fielddef_label(this); -} -inline uint32_t FieldDef::number() const { return upb_fielddef_number(this); } -inline const char* FieldDef::name() const { return upb_fielddef_name(this); } -inline bool FieldDef::is_extension() const { - return upb_fielddef_isextension(this); -} -inline size_t FieldDef::GetJsonName(char* buf, size_t len) const { - return upb_fielddef_getjsonname(this, buf, len); -} -inline bool FieldDef::lazy() const { - return upb_fielddef_lazy(this); -} -inline void FieldDef::set_lazy(bool lazy) { - upb_fielddef_setlazy(this, lazy); -} -inline bool FieldDef::packed() const { - return upb_fielddef_packed(this); -} -inline uint32_t FieldDef::index() const { - return upb_fielddef_index(this); -} -inline void FieldDef::set_packed(bool packed) { - upb_fielddef_setpacked(this, packed); -} -inline const MessageDef* FieldDef::containing_type() const { - return upb_fielddef_containingtype(this); -} -inline const OneofDef* FieldDef::containing_oneof() const { - return upb_fielddef_containingoneof(this); -} -inline const char* FieldDef::containing_type_name() { - return upb_fielddef_containingtypename(this); -} -inline bool FieldDef::set_number(uint32_t number, Status* s) { - return upb_fielddef_setnumber(this, number, s); -} -inline bool FieldDef::set_name(const char *name, Status* s) { - return upb_fielddef_setname(this, name, s); -} -inline bool FieldDef::set_name(const std::string& name, Status* s) { - return upb_fielddef_setname(this, upb_safecstr(name), s); -} -inline bool FieldDef::set_json_name(const char *name, Status* s) { - return upb_fielddef_setjsonname(this, name, s); -} -inline bool FieldDef::set_json_name(const std::string& name, Status* s) { - return upb_fielddef_setjsonname(this, upb_safecstr(name), s); -} -inline void FieldDef::clear_json_name() { - upb_fielddef_clearjsonname(this); -} -inline bool FieldDef::set_containing_type_name(const char *name, Status* s) { - return upb_fielddef_setcontainingtypename(this, name, s); -} -inline bool FieldDef::set_containing_type_name(const std::string &name, - Status *s) { - return upb_fielddef_setcontainingtypename(this, upb_safecstr(name), s); -} -inline void FieldDef::set_type(upb_fieldtype_t type) { - upb_fielddef_settype(this, type); -} -inline void FieldDef::set_is_extension(bool is_extension) { - upb_fielddef_setisextension(this, is_extension); -} -inline void FieldDef::set_descriptor_type(FieldDef::DescriptorType type) { - upb_fielddef_setdescriptortype(this, type); -} -inline void FieldDef::set_label(upb_label_t label) { - upb_fielddef_setlabel(this, label); -} -inline bool FieldDef::IsSubMessage() const { - return upb_fielddef_issubmsg(this); -} -inline bool FieldDef::IsString() const { return upb_fielddef_isstring(this); } -inline bool FieldDef::IsSequence() const { return upb_fielddef_isseq(this); } -inline bool FieldDef::IsMap() const { return upb_fielddef_ismap(this); } -inline int64_t FieldDef::default_int64() const { - return upb_fielddef_defaultint64(this); -} -inline int32_t FieldDef::default_int32() const { - return upb_fielddef_defaultint32(this); -} -inline uint64_t FieldDef::default_uint64() const { - return upb_fielddef_defaultuint64(this); -} -inline uint32_t FieldDef::default_uint32() const { - return upb_fielddef_defaultuint32(this); -} -inline bool FieldDef::default_bool() const { - return upb_fielddef_defaultbool(this); -} -inline float FieldDef::default_float() const { - return upb_fielddef_defaultfloat(this); -} -inline double FieldDef::default_double() const { - return upb_fielddef_defaultdouble(this); -} -inline const char* FieldDef::default_string(size_t* len) const { - return upb_fielddef_defaultstr(this, len); -} -inline void FieldDef::set_default_int64(int64_t value) { - upb_fielddef_setdefaultint64(this, value); -} -inline void FieldDef::set_default_int32(int32_t value) { - upb_fielddef_setdefaultint32(this, value); -} -inline void FieldDef::set_default_uint64(uint64_t value) { - upb_fielddef_setdefaultuint64(this, value); -} -inline void FieldDef::set_default_uint32(uint32_t value) { - upb_fielddef_setdefaultuint32(this, value); -} -inline void FieldDef::set_default_bool(bool value) { - upb_fielddef_setdefaultbool(this, value); -} -inline void FieldDef::set_default_float(float value) { - upb_fielddef_setdefaultfloat(this, value); -} -inline void FieldDef::set_default_double(double value) { - upb_fielddef_setdefaultdouble(this, value); -} -inline bool FieldDef::set_default_string(const void *str, size_t len, - Status *s) { - return upb_fielddef_setdefaultstr(this, str, len, s); -} -inline bool FieldDef::set_default_string(const std::string& str, Status* s) { - return upb_fielddef_setdefaultstr(this, str.c_str(), str.size(), s); -} -inline void FieldDef::set_default_cstr(const char* str, Status* s) { - return upb_fielddef_setdefaultcstr(this, str, s); -} -inline bool FieldDef::HasSubDef() const { return upb_fielddef_hassubdef(this); } -inline const Def* FieldDef::subdef() const { return upb_fielddef_subdef(this); } -inline const MessageDef *FieldDef::message_subdef() const { - return upb_fielddef_msgsubdef(this); -} -inline const EnumDef *FieldDef::enum_subdef() const { - return upb_fielddef_enumsubdef(this); -} -inline const char* FieldDef::subdef_name() const { - return upb_fielddef_subdefname(this); -} -inline bool FieldDef::set_subdef(const Def* subdef, Status* s) { - return upb_fielddef_setsubdef(this, subdef, s); -} -inline bool FieldDef::set_enum_subdef(const EnumDef* subdef, Status* s) { - return upb_fielddef_setenumsubdef(this, subdef, s); -} -inline bool FieldDef::set_message_subdef(const MessageDef* subdef, Status* s) { - return upb_fielddef_setmsgsubdef(this, subdef, s); -} -inline bool FieldDef::set_subdef_name(const char* name, Status* s) { - return upb_fielddef_setsubdefname(this, name, s); -} -inline bool FieldDef::set_subdef_name(const std::string& name, Status* s) { - return upb_fielddef_setsubdefname(this, upb_safecstr(name), s); -} - -inline reffed_ptr MessageDef::New() { - upb_msgdef *m = upb_msgdef_new(&m); - return reffed_ptr(m, &m); -} -inline const char *MessageDef::full_name() const { - return upb_msgdef_fullname(this); -} -inline const char *MessageDef::name() const { - return upb_msgdef_name(this); -} -inline upb_syntax_t MessageDef::syntax() const { - return upb_msgdef_syntax(this); -} -inline bool MessageDef::set_full_name(const char* fullname, Status* s) { - return upb_msgdef_setfullname(this, fullname, s); -} -inline bool MessageDef::set_full_name(const std::string& fullname, Status* s) { - return upb_msgdef_setfullname(this, upb_safecstr(fullname), s); -} -inline bool MessageDef::set_syntax(upb_syntax_t syntax) { - return upb_msgdef_setsyntax(this, syntax); -} -inline bool MessageDef::Freeze(Status* status) { - return upb_msgdef_freeze(this, status); -} -inline int MessageDef::field_count() const { - return upb_msgdef_numfields(this); -} -inline int MessageDef::oneof_count() const { - return upb_msgdef_numoneofs(this); -} -inline bool MessageDef::AddField(upb_fielddef* f, Status* s) { - return upb_msgdef_addfield(this, f, NULL, s); -} -inline bool MessageDef::AddField(const reffed_ptr& f, Status* s) { - return upb_msgdef_addfield(this, f.get(), NULL, s); -} -inline bool MessageDef::AddOneof(upb_oneofdef* o, Status* s) { - return upb_msgdef_addoneof(this, o, NULL, s); -} -inline bool MessageDef::AddOneof(const reffed_ptr& o, Status* s) { - return upb_msgdef_addoneof(this, o.get(), NULL, s); -} -inline FieldDef* MessageDef::FindFieldByNumber(uint32_t number) { - return upb_msgdef_itof_mutable(this, number); -} -inline FieldDef* MessageDef::FindFieldByName(const char* name, size_t len) { - return upb_msgdef_ntof_mutable(this, name, len); -} -inline const FieldDef* MessageDef::FindFieldByNumber(uint32_t number) const { - return upb_msgdef_itof(this, number); -} -inline const FieldDef *MessageDef::FindFieldByName(const char *name, - size_t len) const { - return upb_msgdef_ntof(this, name, len); -} -inline OneofDef* MessageDef::FindOneofByName(const char* name, size_t len) { - return upb_msgdef_ntoo_mutable(this, name, len); -} -inline const OneofDef* MessageDef::FindOneofByName(const char* name, - size_t len) const { - return upb_msgdef_ntoo(this, name, len); -} -inline void MessageDef::setmapentry(bool map_entry) { - upb_msgdef_setmapentry(this, map_entry); -} -inline bool MessageDef::mapentry() const { - return upb_msgdef_mapentry(this); -} -inline MessageDef::field_iterator MessageDef::field_begin() { - return field_iterator(this); -} -inline MessageDef::field_iterator MessageDef::field_end() { - return field_iterator::end(this); -} -inline MessageDef::const_field_iterator MessageDef::field_begin() const { - return const_field_iterator(this); -} -inline MessageDef::const_field_iterator MessageDef::field_end() const { - return const_field_iterator::end(this); -} - -inline MessageDef::oneof_iterator MessageDef::oneof_begin() { - return oneof_iterator(this); -} -inline MessageDef::oneof_iterator MessageDef::oneof_end() { - return oneof_iterator::end(this); -} -inline MessageDef::const_oneof_iterator MessageDef::oneof_begin() const { - return const_oneof_iterator(this); -} -inline MessageDef::const_oneof_iterator MessageDef::oneof_end() const { - return const_oneof_iterator::end(this); -} - -inline MessageDef::field_iterator::field_iterator(MessageDef* md) { - upb_msg_field_begin(&iter_, md); -} -inline MessageDef::field_iterator MessageDef::field_iterator::end( - MessageDef* md) { - MessageDef::field_iterator iter(md); - upb_msg_field_iter_setdone(&iter.iter_); - return iter; -} -inline FieldDef* MessageDef::field_iterator::operator*() const { - return upb_msg_iter_field(&iter_); -} -inline void MessageDef::field_iterator::operator++() { - return upb_msg_field_next(&iter_); -} -inline bool MessageDef::field_iterator::operator==( - const field_iterator &other) const { - return upb_inttable_iter_isequal(&iter_, &other.iter_); -} -inline bool MessageDef::field_iterator::operator!=( - const field_iterator &other) const { - return !(*this == other); -} - -inline MessageDef::const_field_iterator::const_field_iterator( - const MessageDef* md) { - upb_msg_field_begin(&iter_, md); -} -inline MessageDef::const_field_iterator MessageDef::const_field_iterator::end( - const MessageDef *md) { - MessageDef::const_field_iterator iter(md); - upb_msg_field_iter_setdone(&iter.iter_); - return iter; -} -inline const FieldDef* MessageDef::const_field_iterator::operator*() const { - return upb_msg_iter_field(&iter_); -} -inline void MessageDef::const_field_iterator::operator++() { - return upb_msg_field_next(&iter_); -} -inline bool MessageDef::const_field_iterator::operator==( - const const_field_iterator &other) const { - return upb_inttable_iter_isequal(&iter_, &other.iter_); -} -inline bool MessageDef::const_field_iterator::operator!=( - const const_field_iterator &other) const { - return !(*this == other); -} - -inline MessageDef::oneof_iterator::oneof_iterator(MessageDef* md) { - upb_msg_oneof_begin(&iter_, md); -} -inline MessageDef::oneof_iterator MessageDef::oneof_iterator::end( - MessageDef* md) { - MessageDef::oneof_iterator iter(md); - upb_msg_oneof_iter_setdone(&iter.iter_); - return iter; -} -inline OneofDef* MessageDef::oneof_iterator::operator*() const { - return upb_msg_iter_oneof(&iter_); -} -inline void MessageDef::oneof_iterator::operator++() { - return upb_msg_oneof_next(&iter_); -} -inline bool MessageDef::oneof_iterator::operator==( - const oneof_iterator &other) const { - return upb_strtable_iter_isequal(&iter_, &other.iter_); -} -inline bool MessageDef::oneof_iterator::operator!=( - const oneof_iterator &other) const { - return !(*this == other); -} - -inline MessageDef::const_oneof_iterator::const_oneof_iterator( - const MessageDef* md) { - upb_msg_oneof_begin(&iter_, md); -} -inline MessageDef::const_oneof_iterator MessageDef::const_oneof_iterator::end( - const MessageDef *md) { - MessageDef::const_oneof_iterator iter(md); - upb_msg_oneof_iter_setdone(&iter.iter_); - return iter; -} -inline const OneofDef* MessageDef::const_oneof_iterator::operator*() const { - return upb_msg_iter_oneof(&iter_); -} -inline void MessageDef::const_oneof_iterator::operator++() { - return upb_msg_oneof_next(&iter_); -} -inline bool MessageDef::const_oneof_iterator::operator==( - const const_oneof_iterator &other) const { - return upb_strtable_iter_isequal(&iter_, &other.iter_); -} -inline bool MessageDef::const_oneof_iterator::operator!=( - const const_oneof_iterator &other) const { - return !(*this == other); -} - -inline reffed_ptr EnumDef::New() { - upb_enumdef *e = upb_enumdef_new(&e); - return reffed_ptr(e, &e); -} -inline const char* EnumDef::full_name() const { - return upb_enumdef_fullname(this); -} -inline const char* EnumDef::name() const { - return upb_enumdef_name(this); -} -inline bool EnumDef::set_full_name(const char* fullname, Status* s) { - return upb_enumdef_setfullname(this, fullname, s); -} -inline bool EnumDef::set_full_name(const std::string& fullname, Status* s) { - return upb_enumdef_setfullname(this, upb_safecstr(fullname), s); -} -inline bool EnumDef::Freeze(Status* status) { - return upb_enumdef_freeze(this, status); -} -inline int32_t EnumDef::default_value() const { - return upb_enumdef_default(this); -} -inline bool EnumDef::set_default_value(int32_t val, Status* status) { - return upb_enumdef_setdefault(this, val, status); -} -inline int EnumDef::value_count() const { return upb_enumdef_numvals(this); } -inline bool EnumDef::AddValue(const char* name, int32_t num, Status* status) { - return upb_enumdef_addval(this, name, num, status); -} -inline bool EnumDef::AddValue(const std::string& name, int32_t num, - Status* status) { - return upb_enumdef_addval(this, upb_safecstr(name), num, status); -} -inline bool EnumDef::FindValueByName(const char* name, int32_t *num) const { - return upb_enumdef_ntoiz(this, name, num); -} -inline const char* EnumDef::FindValueByNumber(int32_t num) const { - return upb_enumdef_iton(this, num); -} - -inline EnumDef::Iterator::Iterator(const EnumDef* e) { - upb_enum_begin(&iter_, e); -} -inline int32_t EnumDef::Iterator::number() { - return upb_enum_iter_number(&iter_); -} -inline const char* EnumDef::Iterator::name() { - return upb_enum_iter_name(&iter_); -} -inline bool EnumDef::Iterator::Done() { return upb_enum_done(&iter_); } -inline void EnumDef::Iterator::Next() { return upb_enum_next(&iter_); } - -inline reffed_ptr OneofDef::New() { - upb_oneofdef *o = upb_oneofdef_new(&o); - return reffed_ptr(o, &o); -} - -inline const MessageDef* OneofDef::containing_type() const { - return upb_oneofdef_containingtype(this); -} -inline const char* OneofDef::name() const { - return upb_oneofdef_name(this); -} -inline bool OneofDef::set_name(const char* name, Status* s) { - return upb_oneofdef_setname(this, name, s); -} -inline bool OneofDef::set_name(const std::string& name, Status* s) { - return upb_oneofdef_setname(this, upb_safecstr(name), s); -} -inline int OneofDef::field_count() const { - return upb_oneofdef_numfields(this); -} -inline bool OneofDef::AddField(FieldDef* field, Status* s) { - return upb_oneofdef_addfield(this, field, NULL, s); -} -inline bool OneofDef::AddField(const reffed_ptr& field, Status* s) { - return upb_oneofdef_addfield(this, field.get(), NULL, s); -} -inline const FieldDef* OneofDef::FindFieldByName(const char* name, - size_t len) const { - return upb_oneofdef_ntof(this, name, len); -} -inline const FieldDef* OneofDef::FindFieldByNumber(uint32_t num) const { - return upb_oneofdef_itof(this, num); -} -inline OneofDef::iterator OneofDef::begin() { return iterator(this); } -inline OneofDef::iterator OneofDef::end() { return iterator::end(this); } -inline OneofDef::const_iterator OneofDef::begin() const { - return const_iterator(this); -} -inline OneofDef::const_iterator OneofDef::end() const { - return const_iterator::end(this); -} - -inline OneofDef::iterator::iterator(OneofDef* o) { - upb_oneof_begin(&iter_, o); -} -inline OneofDef::iterator OneofDef::iterator::end(OneofDef* o) { - OneofDef::iterator iter(o); - upb_oneof_iter_setdone(&iter.iter_); - return iter; -} -inline FieldDef* OneofDef::iterator::operator*() const { - return upb_oneof_iter_field(&iter_); -} -inline void OneofDef::iterator::operator++() { return upb_oneof_next(&iter_); } -inline bool OneofDef::iterator::operator==(const iterator &other) const { - return upb_inttable_iter_isequal(&iter_, &other.iter_); -} -inline bool OneofDef::iterator::operator!=(const iterator &other) const { - return !(*this == other); -} - -inline OneofDef::const_iterator::const_iterator(const OneofDef* md) { - upb_oneof_begin(&iter_, md); -} -inline OneofDef::const_iterator OneofDef::const_iterator::end( - const OneofDef *md) { - OneofDef::const_iterator iter(md); - upb_oneof_iter_setdone(&iter.iter_); - return iter; -} -inline const FieldDef* OneofDef::const_iterator::operator*() const { - return upb_msg_iter_field(&iter_); -} -inline void OneofDef::const_iterator::operator++() { - return upb_oneof_next(&iter_); -} -inline bool OneofDef::const_iterator::operator==( - const const_iterator &other) const { - return upb_inttable_iter_isequal(&iter_, &other.iter_); -} -inline bool OneofDef::const_iterator::operator!=( - const const_iterator &other) const { - return !(*this == other); -} - -inline reffed_ptr FileDef::New() { - upb_filedef *f = upb_filedef_new(&f); - return reffed_ptr(f, &f); -} - -inline const char* FileDef::name() const { - return upb_filedef_name(this); -} -inline bool FileDef::set_name(const char* name, Status* s) { - return upb_filedef_setname(this, name, s); -} -inline bool FileDef::set_name(const std::string& name, Status* s) { - return upb_filedef_setname(this, upb_safecstr(name), s); -} -inline const char* FileDef::package() const { - return upb_filedef_package(this); -} -inline bool FileDef::set_package(const char* package, Status* s) { - return upb_filedef_setpackage(this, package, s); -} -inline const char* FileDef::phpprefix() const { - return upb_filedef_phpprefix(this); -} -inline bool FileDef::set_phpprefix(const char* phpprefix, Status* s) { - return upb_filedef_setphpprefix(this, phpprefix, s); -} -inline const char* FileDef::phpnamespace() const { - return upb_filedef_phpnamespace(this); -} -inline bool FileDef::set_phpnamespace(const char* phpnamespace, Status* s) { - return upb_filedef_setphpnamespace(this, phpnamespace, s); -} -inline int FileDef::def_count() const { - return upb_filedef_defcount(this); -} -inline const Def* FileDef::def(int index) const { - return upb_filedef_def(this, index); -} -inline Def* FileDef::def(int index) { - return const_cast(upb_filedef_def(this, index)); -} -inline int FileDef::dependency_count() const { - return upb_filedef_depcount(this); -} -inline const FileDef* FileDef::dependency(int index) const { - return upb_filedef_dep(this, index); -} -inline bool FileDef::AddDef(Def* def, Status* s) { - return upb_filedef_adddef(this, def, NULL, s); -} -inline bool FileDef::AddMessage(MessageDef* m, Status* s) { - return upb_filedef_addmsg(this, m, NULL, s); -} -inline bool FileDef::AddEnum(EnumDef* e, Status* s) { - return upb_filedef_addenum(this, e, NULL, s); -} -inline bool FileDef::AddExtension(FieldDef* f, Status* s) { - return upb_filedef_addext(this, f, NULL, s); -} -inline bool FileDef::AddDependency(const FileDef* file) { - return upb_filedef_adddep(this, file); -} - -} /* namespace upb */ -#endif - -#endif /* UPB_DEF_H_ */ -/* -** This file contains definitions of structs that should be considered private -** and NOT stable across versions of upb. -** -** The only reason they are declared here and not in .c files is to allow upb -** and the application (if desired) to embed statically-initialized instances -** of structures like defs. -** -** If you include this file, all guarantees of ABI compatibility go out the -** window! Any code that includes this file needs to recompile against the -** exact same version of upb that they are linking against. -** -** You also need to recompile if you change the value of the UPB_DEBUG_REFS -** flag. -*/ - - -#ifndef UPB_STATICINIT_H_ -#define UPB_STATICINIT_H_ - -#ifdef __cplusplus -/* Because of how we do our typedefs, this header can't be included from C++. */ -#error This file cannot be included from C++ -#endif - -/* upb_refcounted *************************************************************/ - - -/* upb_def ********************************************************************/ - -struct upb_def { - upb_refcounted base; - - const char *fullname; - const upb_filedef* file; - char type; /* A upb_deftype_t (char to save space) */ - - /* Used as a flag during the def's mutable stage. Must be false unless - * it is currently being used by a function on the stack. This allows - * us to easily determine which defs were passed into the function's - * current invocation. */ - bool came_from_user; -}; - -#define UPB_DEF_INIT(name, type, vtbl, refs, ref2s) \ - { UPB_REFCOUNT_INIT(vtbl, refs, ref2s), name, NULL, type, false } - - -/* upb_fielddef ***************************************************************/ - -struct upb_fielddef { - upb_def base; - - union { - int64_t sint; - uint64_t uint; - double dbl; - float flt; - void *bytes; - } defaultval; - union { - const upb_msgdef *def; /* If !msg_is_symbolic. */ - char *name; /* If msg_is_symbolic. */ - } msg; - union { - const upb_def *def; /* If !subdef_is_symbolic. */ - char *name; /* If subdef_is_symbolic. */ - } sub; /* The msgdef or enumdef for this field, if upb_hassubdef(f). */ - bool subdef_is_symbolic; - bool msg_is_symbolic; - const upb_oneofdef *oneof; - bool default_is_string; - bool type_is_set_; /* False until type is explicitly set. */ - bool is_extension_; - bool lazy_; - bool packed_; - upb_intfmt_t intfmt; - bool tagdelim; - upb_fieldtype_t type_; - upb_label_t label_; - uint32_t number_; - uint32_t selector_base; /* Used to index into a upb::Handlers table. */ - uint32_t index_; -}; - -extern const struct upb_refcounted_vtbl upb_fielddef_vtbl; - -#define UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, lazy, \ - packed, name, num, msgdef, subdef, selector_base, \ - index, defaultval, refs, ref2s) \ - { \ - UPB_DEF_INIT(name, UPB_DEF_FIELD, &upb_fielddef_vtbl, refs, ref2s), \ - defaultval, {msgdef}, {subdef}, NULL, false, false, \ - type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES, true, is_extension, \ - lazy, packed, intfmt, tagdelim, type, label, num, selector_base, index \ - } - - -/* upb_msgdef *****************************************************************/ - -struct upb_msgdef { - upb_def base; - - size_t selector_count; - uint32_t submsg_field_count; - - /* Tables for looking up fields by number and name. */ - upb_inttable itof; /* int to field */ - upb_strtable ntof; /* name to field/oneof */ - - /* Is this a map-entry message? */ - bool map_entry; - - /* Whether this message has proto2 or proto3 semantics. */ - upb_syntax_t syntax; - - /* TODO(haberman): proper extension ranges (there can be multiple). */ -}; - -extern const struct upb_refcounted_vtbl upb_msgdef_vtbl; - -/* TODO: also support static initialization of the oneofs table. This will be - * needed if we compile in descriptors that contain oneofs. */ -#define UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof, \ - map_entry, syntax, refs, ref2s) \ - { \ - UPB_DEF_INIT(name, UPB_DEF_MSG, &upb_fielddef_vtbl, refs, ref2s), \ - selector_count, submsg_field_count, itof, ntof, map_entry, syntax \ - } - - -/* upb_enumdef ****************************************************************/ - -struct upb_enumdef { - upb_def base; - - upb_strtable ntoi; - upb_inttable iton; - int32_t defaultval; -}; - -extern const struct upb_refcounted_vtbl upb_enumdef_vtbl; - -#define UPB_ENUMDEF_INIT(name, ntoi, iton, defaultval, refs, ref2s) \ - { UPB_DEF_INIT(name, UPB_DEF_ENUM, &upb_enumdef_vtbl, refs, ref2s), ntoi, \ - iton, defaultval } - - -/* upb_oneofdef ***************************************************************/ - -struct upb_oneofdef { - upb_refcounted base; - - uint32_t index; /* Index within oneofs. */ - const char *name; - upb_strtable ntof; - upb_inttable itof; - const upb_msgdef *parent; -}; - -extern const struct upb_refcounted_vtbl upb_oneofdef_vtbl; - -#define UPB_ONEOFDEF_INIT(name, ntof, itof, refs, ref2s) \ - { UPB_REFCOUNT_INIT(&upb_oneofdef_vtbl, refs, ref2s), 0, name, ntof, itof } - - -/* upb_symtab *****************************************************************/ - -struct upb_symtab { - upb_refcounted base; - - upb_strtable symtab; -}; - -struct upb_filedef { - upb_refcounted base; - - const char *name; - const char *package; - const char *phpprefix; - const char *phpnamespace; - upb_syntax_t syntax; - - upb_inttable defs; - upb_inttable deps; -}; - -extern const struct upb_refcounted_vtbl upb_filedef_vtbl; - -#endif /* UPB_STATICINIT_H_ */ -/* -** upb::Handlers (upb_handlers) -** -** A upb_handlers is like a virtual table for a upb_msgdef. Each field of the -** message can have associated functions that will be called when we are -** parsing or visiting a stream of data. This is similar to how handlers work -** in SAX (the Simple API for XML). -** -** The handlers have no idea where the data is coming from, so a single set of -** handlers could be used with two completely different data sources (for -** example, a parser and a visitor over in-memory objects). This decoupling is -** the most important feature of upb, because it allows parsers and serializers -** to be highly reusable. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. -*/ - -#ifndef UPB_HANDLERS_H -#define UPB_HANDLERS_H - - -#ifdef __cplusplus -namespace upb { -class BufferHandle; -class BytesHandler; -class HandlerAttributes; -class Handlers; -template class Handler; -template struct CanonicalType; -} /* namespace upb */ -#endif - -UPB_DECLARE_TYPE(upb::BufferHandle, upb_bufhandle) -UPB_DECLARE_TYPE(upb::BytesHandler, upb_byteshandler) -UPB_DECLARE_TYPE(upb::HandlerAttributes, upb_handlerattr) -UPB_DECLARE_DERIVED_TYPE(upb::Handlers, upb::RefCounted, - upb_handlers, upb_refcounted) - -/* The maximum depth that the handler graph can have. This is a resource limit - * for the C stack since we sometimes need to recursively traverse the graph. - * Cycles are ok; the traversal will stop when it detects a cycle, but we must - * hit the cycle before the maximum depth is reached. - * - * If having a single static limit is too inflexible, we can add another variant - * of Handlers::Freeze that allows specifying this as a parameter. */ -#define UPB_MAX_HANDLER_DEPTH 64 - -/* All the different types of handlers that can be registered. - * Only needed for the advanced functions in upb::Handlers. */ -typedef enum { - UPB_HANDLER_INT32, - UPB_HANDLER_INT64, - UPB_HANDLER_UINT32, - UPB_HANDLER_UINT64, - UPB_HANDLER_FLOAT, - UPB_HANDLER_DOUBLE, - UPB_HANDLER_BOOL, - UPB_HANDLER_STARTSTR, - UPB_HANDLER_STRING, - UPB_HANDLER_ENDSTR, - UPB_HANDLER_STARTSUBMSG, - UPB_HANDLER_ENDSUBMSG, - UPB_HANDLER_STARTSEQ, - UPB_HANDLER_ENDSEQ -} upb_handlertype_t; - -#define UPB_HANDLER_MAX (UPB_HANDLER_ENDSEQ+1) - -#define UPB_BREAK NULL - -/* A convenient definition for when no closure is needed. */ -extern char _upb_noclosure; -#define UPB_NO_CLOSURE &_upb_noclosure - -/* A selector refers to a specific field handler in the Handlers object - * (for example: the STARTSUBMSG handler for field "field15"). */ -typedef int32_t upb_selector_t; - -UPB_BEGIN_EXTERN_C - -/* Forward-declares for C inline accessors. We need to declare these here - * so we can "friend" them in the class declarations in C++. */ -UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h, - upb_selector_t s); -UPB_INLINE const void *upb_handlerattr_handlerdata(const upb_handlerattr *attr); -UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h, - upb_selector_t s); - -UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h); -UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj, - const void *type); -UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf, - size_t ofs); -UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h); -UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h); -UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h); - -UPB_END_EXTERN_C - - -/* Static selectors for upb::Handlers. */ -#define UPB_STARTMSG_SELECTOR 0 -#define UPB_ENDMSG_SELECTOR 1 -#define UPB_STATIC_SELECTOR_COUNT 2 - -/* Static selectors for upb::BytesHandler. */ -#define UPB_STARTSTR_SELECTOR 0 -#define UPB_STRING_SELECTOR 1 -#define UPB_ENDSTR_SELECTOR 2 - -typedef void upb_handlerfree(void *d); - -#ifdef __cplusplus - -/* A set of attributes that accompanies a handler's function pointer. */ -class upb::HandlerAttributes { - public: - HandlerAttributes(); - ~HandlerAttributes(); - - /* Sets the handler data that will be passed as the second parameter of the - * handler. To free this pointer when the handlers are freed, call - * Handlers::AddCleanup(). */ - bool SetHandlerData(const void *handler_data); - const void* handler_data() const; - - /* Use this to specify the type of the closure. This will be checked against - * all other closure types for handler that use the same closure. - * Registration will fail if this does not match all other non-NULL closure - * types. */ - bool SetClosureType(const void *closure_type); - const void* closure_type() const; - - /* Use this to specify the type of the returned closure. Only used for - * Start*{String,SubMessage,Sequence} handlers. This must match the closure - * type of any handlers that use it (for example, the StringBuf handler must - * match the closure returned from StartString). */ - bool SetReturnClosureType(const void *return_closure_type); - const void* return_closure_type() const; - - /* Set to indicate that the handler always returns "ok" (either "true" or a - * non-NULL closure). This is a hint that can allow code generators to - * generate more efficient code. */ - bool SetAlwaysOk(bool always_ok); - bool always_ok() const; - - private: - friend UPB_INLINE const void * ::upb_handlerattr_handlerdata( - const upb_handlerattr *attr); -#else -struct upb_handlerattr { -#endif - const void *handler_data_; - const void *closure_type_; - const void *return_closure_type_; - bool alwaysok_; -}; - -#define UPB_HANDLERATTR_INITIALIZER {NULL, NULL, NULL, false} - -typedef struct { - upb_func *func; - - /* It is wasteful to include the entire attributes here: - * - * * Some of the information is redundant (like storing the closure type - * separately for each handler that must match). - * * Some of the info is only needed prior to freeze() (like closure types). - * * alignment padding wastes a lot of space for alwaysok_. - * - * If/when the size and locality of handlers is an issue, we can optimize this - * not to store the entire attr like this. We do not expose the table's - * layout to allow this optimization in the future. */ - upb_handlerattr attr; -} upb_handlers_tabent; - -#ifdef __cplusplus - -/* Extra information about a buffer that is passed to a StringBuf handler. - * TODO(haberman): allow the handle to be pinned so that it will outlive - * the handler invocation. */ -class upb::BufferHandle { - public: - BufferHandle(); - ~BufferHandle(); - - /* The beginning of the buffer. This may be different than the pointer - * passed to a StringBuf handler because the handler may receive data - * that is from the middle or end of a larger buffer. */ - const char* buffer() const; - - /* The offset within the attached object where this buffer begins. Only - * meaningful if there is an attached object. */ - size_t object_offset() const; - - /* Note that object_offset is the offset of "buf" within the attached - * object. */ - void SetBuffer(const char* buf, size_t object_offset); - - /* The BufferHandle can have an "attached object", which can be used to - * tunnel through a pointer to the buffer's underlying representation. */ - template - void SetAttachedObject(const T* obj); - - /* Returns NULL if the attached object is not of this type. */ - template - const T* GetAttachedObject() const; - - private: - friend UPB_INLINE void ::upb_bufhandle_init(upb_bufhandle *h); - friend UPB_INLINE void ::upb_bufhandle_setobj(upb_bufhandle *h, - const void *obj, - const void *type); - friend UPB_INLINE void ::upb_bufhandle_setbuf(upb_bufhandle *h, - const char *buf, size_t ofs); - friend UPB_INLINE const void* ::upb_bufhandle_obj(const upb_bufhandle *h); - friend UPB_INLINE const void* ::upb_bufhandle_objtype( - const upb_bufhandle *h); - friend UPB_INLINE const char* ::upb_bufhandle_buf(const upb_bufhandle *h); -#else -struct upb_bufhandle { -#endif - const char *buf_; - const void *obj_; - const void *objtype_; - size_t objofs_; -}; - -#ifdef __cplusplus - -/* A upb::Handlers object represents the set of handlers associated with a - * message in the graph of messages. You can think of it as a big virtual - * table with functions corresponding to all the events that can fire while - * parsing or visiting a message of a specific type. - * - * Any handlers that are not set behave as if they had successfully consumed - * the value. Any unset Start* handlers will propagate their closure to the - * inner frame. - * - * The easiest way to create the *Handler objects needed by the Set* methods is - * with the UpbBind() and UpbMakeHandler() macros; see below. */ -class upb::Handlers { - public: - typedef upb_selector_t Selector; - typedef upb_handlertype_t Type; - - typedef Handler StartFieldHandler; - typedef Handler EndFieldHandler; - typedef Handler StartMessageHandler; - typedef Handler EndMessageHandler; - typedef Handler StartStringHandler; - typedef Handler StringHandler; - - template struct ValueHandler { - typedef Handler H; - }; - - typedef ValueHandler::H Int32Handler; - typedef ValueHandler::H Int64Handler; - typedef ValueHandler::H UInt32Handler; - typedef ValueHandler::H UInt64Handler; - typedef ValueHandler::H FloatHandler; - typedef ValueHandler::H DoubleHandler; - typedef ValueHandler::H BoolHandler; - - /* Any function pointer can be converted to this and converted back to its - * correct type. */ - typedef void GenericFunction(); - - typedef void HandlersCallback(const void *closure, upb_handlers *h); - - /* Returns a new handlers object for the given frozen msgdef. - * Returns NULL if memory allocation failed. */ - static reffed_ptr New(const MessageDef *m); - - /* Convenience function for registering a graph of handlers that mirrors the - * graph of msgdefs for some message. For "m" and all its children a new set - * of handlers will be created and the given callback will be invoked, - * allowing the client to register handlers for this message. Note that any - * subhandlers set by the callback will be overwritten. */ - static reffed_ptr NewFrozen(const MessageDef *m, - HandlersCallback *callback, - const void *closure); - - /* Functionality from upb::RefCounted. */ - UPB_REFCOUNTED_CPPMETHODS - - /* All handler registration functions return bool to indicate success or - * failure; details about failures are stored in this status object. If a - * failure does occur, it must be cleared before the Handlers are frozen, - * otherwise the freeze() operation will fail. The functions may *only* be - * used while the Handlers are mutable. */ - const Status* status(); - void ClearError(); - - /* Call to freeze these Handlers. Requires that any SubHandlers are already - * frozen. For cycles, you must use the static version below and freeze the - * whole graph at once. */ - bool Freeze(Status* s); - - /* Freezes the given set of handlers. You may not freeze a handler without - * also freezing any handlers they point to. */ - static bool Freeze(Handlers*const* handlers, int n, Status* s); - static bool Freeze(const std::vector& handlers, Status* s); - - /* Returns the msgdef associated with this handlers object. */ - const MessageDef* message_def() const; - - /* Adds the given pointer and function to the list of cleanup functions that - * will be run when these handlers are freed. If this pointer has previously - * been registered, the function returns false and does nothing. */ - bool AddCleanup(void *ptr, upb_handlerfree *cleanup); - - /* Sets the startmsg handler for the message, which is defined as follows: - * - * bool startmsg(MyType* closure) { - * // Called when the message begins. Returns true if processing should - * // continue. - * return true; - * } - */ - bool SetStartMessageHandler(const StartMessageHandler& handler); - - /* Sets the endmsg handler for the message, which is defined as follows: - * - * bool endmsg(MyType* closure, upb_status *status) { - * // Called when processing of this message ends, whether in success or - * // failure. "status" indicates the final status of processing, and - * // can also be modified in-place to update the final status. - * } - */ - bool SetEndMessageHandler(const EndMessageHandler& handler); - - /* Sets the value handler for the given field, which is defined as follows - * (this is for an int32 field; other field types will pass their native - * C/C++ type for "val"): - * - * bool OnValue(MyClosure* c, const MyHandlerData* d, int32_t val) { - * // Called when the field's value is encountered. "d" contains - * // whatever data was bound to this field when it was registered. - * // Returns true if processing should continue. - * return true; - * } - * - * handers->SetInt32Handler(f, UpbBind(OnValue, new MyHandlerData(...))); - * - * The value type must exactly match f->type(). - * For example, a handler that takes an int32_t parameter may only be used for - * fields of type UPB_TYPE_INT32 and UPB_TYPE_ENUM. - * - * Returns false if the handler failed to register; in this case the cleanup - * handler (if any) will be called immediately. - */ - bool SetInt32Handler (const FieldDef* f, const Int32Handler& h); - bool SetInt64Handler (const FieldDef* f, const Int64Handler& h); - bool SetUInt32Handler(const FieldDef* f, const UInt32Handler& h); - bool SetUInt64Handler(const FieldDef* f, const UInt64Handler& h); - bool SetFloatHandler (const FieldDef* f, const FloatHandler& h); - bool SetDoubleHandler(const FieldDef* f, const DoubleHandler& h); - bool SetBoolHandler (const FieldDef* f, const BoolHandler& h); - - /* Like the previous, but templated on the type on the value (ie. int32). - * This is mostly useful to call from other templates. To call this you must - * specify the template parameter explicitly, ie: - * h->SetValueHandler(f, UpbBind(MyHandler, MyData)); */ - template - bool SetValueHandler( - const FieldDef *f, - const typename ValueHandler::Type>::H& handler); - - /* Sets handlers for a string field, which are defined as follows: - * - * MySubClosure* startstr(MyClosure* c, const MyHandlerData* d, - * size_t size_hint) { - * // Called when a string value begins. The return value indicates the - * // closure for the string. "size_hint" indicates the size of the - * // string if it is known, however if the string is length-delimited - * // and the end-of-string is not available size_hint will be zero. - * // This case is indistinguishable from the case where the size is - * // known to be zero. - * // - * // TODO(haberman): is it important to distinguish these cases? - * // If we had ssize_t as a type we could make -1 "unknown", but - * // ssize_t is POSIX (not ANSI) and therefore less portable. - * // In practice I suspect it won't be important to distinguish. - * return closure; - * } - * - * size_t str(MyClosure* closure, const MyHandlerData* d, - * const char *str, size_t len) { - * // Called for each buffer of string data; the multiple physical buffers - * // are all part of the same logical string. The return value indicates - * // how many bytes were consumed. If this number is less than "len", - * // this will also indicate that processing should be halted for now, - * // like returning false or UPB_BREAK from any other callback. If - * // number is greater than "len", the excess bytes will be skipped over - * // and not passed to the callback. - * return len; - * } - * - * bool endstr(MyClosure* c, const MyHandlerData* d) { - * // Called when a string value ends. Return value indicates whether - * // processing should continue. - * return true; - * } - */ - bool SetStartStringHandler(const FieldDef* f, const StartStringHandler& h); - bool SetStringHandler(const FieldDef* f, const StringHandler& h); - bool SetEndStringHandler(const FieldDef* f, const EndFieldHandler& h); - - /* Sets the startseq handler, which is defined as follows: - * - * MySubClosure *startseq(MyClosure* c, const MyHandlerData* d) { - * // Called when a sequence (repeated field) begins. The returned - * // pointer indicates the closure for the sequence (or UPB_BREAK - * // to interrupt processing). - * return closure; - * } - * - * h->SetStartSequenceHandler(f, UpbBind(startseq, new MyHandlerData(...))); - * - * Returns "false" if "f" does not belong to this message or is not a - * repeated field. - */ - bool SetStartSequenceHandler(const FieldDef* f, const StartFieldHandler& h); - - /* Sets the startsubmsg handler for the given field, which is defined as - * follows: - * - * MySubClosure* startsubmsg(MyClosure* c, const MyHandlerData* d) { - * // Called when a submessage begins. The returned pointer indicates the - * // closure for the sequence (or UPB_BREAK to interrupt processing). - * return closure; - * } - * - * h->SetStartSubMessageHandler(f, UpbBind(startsubmsg, - * new MyHandlerData(...))); - * - * Returns "false" if "f" does not belong to this message or is not a - * submessage/group field. - */ - bool SetStartSubMessageHandler(const FieldDef* f, const StartFieldHandler& h); - - /* Sets the endsubmsg handler for the given field, which is defined as - * follows: - * - * bool endsubmsg(MyClosure* c, const MyHandlerData* d) { - * // Called when a submessage ends. Returns true to continue processing. - * return true; - * } - * - * Returns "false" if "f" does not belong to this message or is not a - * submessage/group field. - */ - bool SetEndSubMessageHandler(const FieldDef *f, const EndFieldHandler &h); - - /* Starts the endsubseq handler for the given field, which is defined as - * follows: - * - * bool endseq(MyClosure* c, const MyHandlerData* d) { - * // Called when a sequence ends. Returns true continue processing. - * return true; - * } - * - * Returns "false" if "f" does not belong to this message or is not a - * repeated field. - */ - bool SetEndSequenceHandler(const FieldDef* f, const EndFieldHandler& h); - - /* Sets or gets the object that specifies handlers for the given field, which - * must be a submessage or group. Returns NULL if no handlers are set. */ - bool SetSubHandlers(const FieldDef* f, const Handlers* sub); - const Handlers* GetSubHandlers(const FieldDef* f) const; - - /* Equivalent to GetSubHandlers, but takes the STARTSUBMSG selector for the - * field. */ - const Handlers* GetSubHandlers(Selector startsubmsg) const; - - /* A selector refers to a specific field handler in the Handlers object - * (for example: the STARTSUBMSG handler for field "field15"). - * On success, returns true and stores the selector in "s". - * If the FieldDef or Type are invalid, returns false. - * The returned selector is ONLY valid for Handlers whose MessageDef - * contains this FieldDef. */ - static bool GetSelector(const FieldDef* f, Type type, Selector* s); - - /* Given a START selector of any kind, returns the corresponding END selector. */ - static Selector GetEndSelector(Selector start_selector); - - /* Returns the function pointer for this handler. It is the client's - * responsibility to cast to the correct function type before calling it. */ - GenericFunction* GetHandler(Selector selector); - - /* Sets the given attributes to the attributes for this selector. */ - bool GetAttributes(Selector selector, HandlerAttributes* attr); - - /* Returns the handler data that was registered with this handler. */ - const void* GetHandlerData(Selector selector); - - /* Could add any of the following functions as-needed, with some minor - * implementation changes: - * - * const FieldDef* GetFieldDef(Selector selector); - * static bool IsSequence(Selector selector); */ - - private: - UPB_DISALLOW_POD_OPS(Handlers, upb::Handlers) - - friend UPB_INLINE GenericFunction *::upb_handlers_gethandler( - const upb_handlers *h, upb_selector_t s); - friend UPB_INLINE const void *::upb_handlers_gethandlerdata( - const upb_handlers *h, upb_selector_t s); -#else -struct upb_handlers { -#endif - upb_refcounted base; - - const upb_msgdef *msg; - const upb_handlers **sub; - const void *top_closure_type; - upb_inttable cleanup_; - upb_status status_; /* Used only when mutable. */ - upb_handlers_tabent table[1]; /* Dynamically-sized field handler array. */ -}; - -#ifdef __cplusplus - -namespace upb { - -/* Convenience macros for creating a Handler object that is wrapped with a - * type-safe wrapper function that converts the "void*" parameters/returns - * of the underlying C API into nice C++ function. - * - * Sample usage: - * void OnValue1(MyClosure* c, const MyHandlerData* d, int32_t val) { - * // do stuff ... - * } - * - * // Handler that doesn't need any data bound to it. - * void OnValue2(MyClosure* c, int32_t val) { - * // do stuff ... - * } - * - * // Handler that returns bool so it can return failure if necessary. - * bool OnValue3(MyClosure* c, int32_t val) { - * // do stuff ... - * return ok; - * } - * - * // Member function handler. - * class MyClosure { - * public: - * void OnValue(int32_t val) { - * // do stuff ... - * } - * }; - * - * // Takes ownership of the MyHandlerData. - * handlers->SetInt32Handler(f1, UpbBind(OnValue1, new MyHandlerData(...))); - * handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue2)); - * handlers->SetInt32Handler(f1, UpbMakeHandler(OnValue3)); - * handlers->SetInt32Handler(f2, UpbMakeHandler(&MyClosure::OnValue)); - */ - -#ifdef UPB_CXX11 - -/* In C++11, the "template" disambiguator can appear even outside templates, - * so all calls can safely use this pair of macros. */ - -#define UpbMakeHandler(f) upb::MatchFunc(f).template GetFunc() - -/* We have to be careful to only evaluate "d" once. */ -#define UpbBind(f, d) upb::MatchFunc(f).template GetFunc((d)) - -#else - -/* Prior to C++11, the "template" disambiguator may only appear inside a - * template, so the regular macro must not use "template" */ - -#define UpbMakeHandler(f) upb::MatchFunc(f).GetFunc() - -#define UpbBind(f, d) upb::MatchFunc(f).GetFunc((d)) - -#endif /* UPB_CXX11 */ - -/* This macro must be used in C++98 for calls from inside a template. But we - * define this variant in all cases; code that wants to be compatible with both - * C++98 and C++11 should always use this macro when calling from a template. */ -#define UpbMakeHandlerT(f) upb::MatchFunc(f).template GetFunc() - -/* We have to be careful to only evaluate "d" once. */ -#define UpbBindT(f, d) upb::MatchFunc(f).template GetFunc((d)) - -/* Handler: a struct that contains the (handler, data, deleter) tuple that is - * used to register all handlers. Users can Make() these directly but it's - * more convenient to use the UpbMakeHandler/UpbBind macros above. */ -template class Handler { - public: - /* The underlying, handler function signature that upb uses internally. */ - typedef T FuncPtr; - - /* Intentionally implicit. */ - template Handler(F func); - ~Handler(); - - private: - void AddCleanup(Handlers* h) const { - if (cleanup_func_) { - bool ok = h->AddCleanup(cleanup_data_, cleanup_func_); - UPB_ASSERT(ok); - } - } - - UPB_DISALLOW_COPY_AND_ASSIGN(Handler) - friend class Handlers; - FuncPtr handler_; - mutable HandlerAttributes attr_; - mutable bool registered_; - void *cleanup_data_; - upb_handlerfree *cleanup_func_; -}; - -} /* namespace upb */ - -#endif /* __cplusplus */ - -UPB_BEGIN_EXTERN_C - -/* Native C API. */ - -/* Handler function typedefs. */ -typedef bool upb_startmsg_handlerfunc(void *c, const void*); -typedef bool upb_endmsg_handlerfunc(void *c, const void *, upb_status *status); -typedef void* upb_startfield_handlerfunc(void *c, const void *hd); -typedef bool upb_endfield_handlerfunc(void *c, const void *hd); -typedef bool upb_int32_handlerfunc(void *c, const void *hd, int32_t val); -typedef bool upb_int64_handlerfunc(void *c, const void *hd, int64_t val); -typedef bool upb_uint32_handlerfunc(void *c, const void *hd, uint32_t val); -typedef bool upb_uint64_handlerfunc(void *c, const void *hd, uint64_t val); -typedef bool upb_float_handlerfunc(void *c, const void *hd, float val); -typedef bool upb_double_handlerfunc(void *c, const void *hd, double val); -typedef bool upb_bool_handlerfunc(void *c, const void *hd, bool val); -typedef void *upb_startstr_handlerfunc(void *c, const void *hd, - size_t size_hint); -typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf, - size_t n, const upb_bufhandle* handle); - -/* upb_bufhandle */ -size_t upb_bufhandle_objofs(const upb_bufhandle *h); - -/* upb_handlerattr */ -void upb_handlerattr_init(upb_handlerattr *attr); -void upb_handlerattr_uninit(upb_handlerattr *attr); - -bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, const void *hd); -bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type); -const void *upb_handlerattr_closuretype(const upb_handlerattr *attr); -bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr, - const void *type); -const void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr); -bool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok); -bool upb_handlerattr_alwaysok(const upb_handlerattr *attr); - -UPB_INLINE const void *upb_handlerattr_handlerdata( - const upb_handlerattr *attr) { - return attr->handler_data_; -} - -/* upb_handlers */ -typedef void upb_handlers_callback(const void *closure, upb_handlers *h); -upb_handlers *upb_handlers_new(const upb_msgdef *m, - const void *owner); -const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m, - const void *owner, - upb_handlers_callback *callback, - const void *closure); - -/* Include refcounted methods like upb_handlers_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_handlers, upb_handlers_upcast) - -const upb_status *upb_handlers_status(upb_handlers *h); -void upb_handlers_clearerr(upb_handlers *h); -const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h); -bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *hfree); - -bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setint32(upb_handlers *h, const upb_fielddef *f, - upb_int32_handlerfunc *func, upb_handlerattr *attr); -bool upb_handlers_setint64(upb_handlers *h, const upb_fielddef *f, - upb_int64_handlerfunc *func, upb_handlerattr *attr); -bool upb_handlers_setuint32(upb_handlers *h, const upb_fielddef *f, - upb_uint32_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setuint64(upb_handlers *h, const upb_fielddef *f, - upb_uint64_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setfloat(upb_handlers *h, const upb_fielddef *f, - upb_float_handlerfunc *func, upb_handlerattr *attr); -bool upb_handlers_setdouble(upb_handlers *h, const upb_fielddef *f, - upb_double_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setbool(upb_handlers *h, const upb_fielddef *f, - upb_bool_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setstartstr(upb_handlers *h, const upb_fielddef *f, - upb_startstr_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setstring(upb_handlers *h, const upb_fielddef *f, - upb_string_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setendstr(upb_handlers *h, const upb_fielddef *f, - upb_endfield_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setstartseq(upb_handlers *h, const upb_fielddef *f, - upb_startfield_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setstartsubmsg(upb_handlers *h, const upb_fielddef *f, - upb_startfield_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setendsubmsg(upb_handlers *h, const upb_fielddef *f, - upb_endfield_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f, - upb_endfield_handlerfunc *func, - upb_handlerattr *attr); - -bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f, - const upb_handlers *sub); -const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h, - const upb_fielddef *f); -const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h, - upb_selector_t sel); - -UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h, - upb_selector_t s) { - return (upb_func *)h->table[s].func; -} - -bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t s, - upb_handlerattr *attr); - -UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h, - upb_selector_t s) { - return upb_handlerattr_handlerdata(&h->table[s].attr); -} - -#ifdef __cplusplus - -/* Handler types for single fields. - * Right now we only have one for TYPE_BYTES but ones for other types - * should follow. - * - * These follow the same handlers protocol for fields of a message. */ -class upb::BytesHandler { - public: - BytesHandler(); - ~BytesHandler(); -#else -struct upb_byteshandler { -#endif - upb_handlers_tabent table[3]; -}; - -void upb_byteshandler_init(upb_byteshandler *h); - -/* Caller must ensure that "d" outlives the handlers. - * TODO(haberman): should this have a "freeze" operation? It's not necessary - * for memory management, but could be useful to force immutability and provide - * a convenient moment to verify that all registration succeeded. */ -bool upb_byteshandler_setstartstr(upb_byteshandler *h, - upb_startstr_handlerfunc *func, void *d); -bool upb_byteshandler_setstring(upb_byteshandler *h, - upb_string_handlerfunc *func, void *d); -bool upb_byteshandler_setendstr(upb_byteshandler *h, - upb_endfield_handlerfunc *func, void *d); - -/* "Static" methods */ -bool upb_handlers_freeze(upb_handlers *const *handlers, int n, upb_status *s); -upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f); -bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type, - upb_selector_t *s); -UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) { - return start + 1; -} - -/* Internal-only. */ -uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f); -uint32_t upb_handlers_selectorcount(const upb_fielddef *f); - -UPB_END_EXTERN_C - -/* -** Inline definitions for handlers.h, which are particularly long and a bit -** tricky. -*/ - -#ifndef UPB_HANDLERS_INL_H_ -#define UPB_HANDLERS_INL_H_ - -#include - -/* C inline methods. */ - -/* upb_bufhandle */ -UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h) { - h->obj_ = NULL; - h->objtype_ = NULL; - h->buf_ = NULL; - h->objofs_ = 0; -} -UPB_INLINE void upb_bufhandle_uninit(upb_bufhandle *h) { - UPB_UNUSED(h); -} -UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj, - const void *type) { - h->obj_ = obj; - h->objtype_ = type; -} -UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf, - size_t ofs) { - h->buf_ = buf; - h->objofs_ = ofs; -} -UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h) { - return h->obj_; -} -UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h) { - return h->objtype_; -} -UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h) { - return h->buf_; -} - - -#ifdef __cplusplus - -/* Type detection and typedefs for integer types. - * For platforms where there are multiple 32-bit or 64-bit types, we need to be - * able to enumerate them so we can properly create overloads for all variants. - * - * If any platform existed where there were three integer types with the same - * size, this would have to become more complicated. For example, short, int, - * and long could all be 32-bits. Even more diabolically, short, int, long, - * and long long could all be 64 bits and still be standard-compliant. - * However, few platforms are this strange, and it's unlikely that upb will be - * used on the strangest ones. */ - -/* Can't count on stdint.h limits like INT32_MAX, because in C++ these are - * only defined when __STDC_LIMIT_MACROS are defined before the *first* include - * of stdint.h. We can't guarantee that someone else didn't include these first - * without defining __STDC_LIMIT_MACROS. */ -#define UPB_INT32_MAX 0x7fffffffLL -#define UPB_INT32_MIN (-UPB_INT32_MAX - 1) -#define UPB_INT64_MAX 0x7fffffffffffffffLL -#define UPB_INT64_MIN (-UPB_INT64_MAX - 1) - -#if INT_MAX == UPB_INT32_MAX && INT_MIN == UPB_INT32_MIN -#define UPB_INT_IS_32BITS 1 -#endif - -#if LONG_MAX == UPB_INT32_MAX && LONG_MIN == UPB_INT32_MIN -#define UPB_LONG_IS_32BITS 1 -#endif - -#if LONG_MAX == UPB_INT64_MAX && LONG_MIN == UPB_INT64_MIN -#define UPB_LONG_IS_64BITS 1 -#endif - -#if LLONG_MAX == UPB_INT64_MAX && LLONG_MIN == UPB_INT64_MIN -#define UPB_LLONG_IS_64BITS 1 -#endif - -/* We use macros instead of typedefs so we can undefine them later and avoid - * leaking them outside this header file. */ -#if UPB_INT_IS_32BITS -#define UPB_INT32_T int -#define UPB_UINT32_T unsigned int - -#if UPB_LONG_IS_32BITS -#define UPB_TWO_32BIT_TYPES 1 -#define UPB_INT32ALT_T long -#define UPB_UINT32ALT_T unsigned long -#endif /* UPB_LONG_IS_32BITS */ - -#elif UPB_LONG_IS_32BITS /* && !UPB_INT_IS_32BITS */ -#define UPB_INT32_T long -#define UPB_UINT32_T unsigned long -#endif /* UPB_INT_IS_32BITS */ - - -#if UPB_LONG_IS_64BITS -#define UPB_INT64_T long -#define UPB_UINT64_T unsigned long - -#if UPB_LLONG_IS_64BITS -#define UPB_TWO_64BIT_TYPES 1 -#define UPB_INT64ALT_T long long -#define UPB_UINT64ALT_T unsigned long long -#endif /* UPB_LLONG_IS_64BITS */ - -#elif UPB_LLONG_IS_64BITS /* && !UPB_LONG_IS_64BITS */ -#define UPB_INT64_T long long -#define UPB_UINT64_T unsigned long long -#endif /* UPB_LONG_IS_64BITS */ - -#undef UPB_INT32_MAX -#undef UPB_INT32_MIN -#undef UPB_INT64_MAX -#undef UPB_INT64_MIN -#undef UPB_INT_IS_32BITS -#undef UPB_LONG_IS_32BITS -#undef UPB_LONG_IS_64BITS -#undef UPB_LLONG_IS_64BITS - - -namespace upb { - -typedef void CleanupFunc(void *ptr); - -/* Template to remove "const" from "const T*" and just return "T*". - * - * We define a nonsense default because otherwise it will fail to instantiate as - * a function parameter type even in cases where we don't expect any caller to - * actually match the overload. */ -class CouldntRemoveConst {}; -template struct remove_constptr { typedef CouldntRemoveConst type; }; -template struct remove_constptr { typedef T *type; }; - -/* Template that we use below to remove a template specialization from - * consideration if it matches a specific type. */ -template struct disable_if_same { typedef void Type; }; -template struct disable_if_same {}; - -template void DeletePointer(void *p) { delete static_cast(p); } - -template -struct FirstUnlessVoidOrBool { - typedef T1 value; -}; - -template -struct FirstUnlessVoidOrBool { - typedef T2 value; -}; - -template -struct FirstUnlessVoidOrBool { - typedef T2 value; -}; - -template -struct is_same { - static bool value; -}; - -template -struct is_same { - static bool value; -}; - -template -bool is_same::value = false; - -template -bool is_same::value = true; - -/* FuncInfo *******************************************************************/ - -/* Info about the user's original, pre-wrapped function. */ -template -struct FuncInfo { - /* The type of the closure that the function takes (its first param). */ - typedef C Closure; - - /* The return type. */ - typedef R Return; -}; - -/* Func ***********************************************************************/ - -/* Func1, Func2, Func3: Template classes representing a function and its - * signature. - * - * Since the function is a template parameter, calling the function can be - * inlined at compile-time and does not require a function pointer at runtime. - * These functions are not bound to a handler data so have no data or cleanup - * handler. */ -struct UnboundFunc { - CleanupFunc *GetCleanup() { return NULL; } - void *GetData() { return NULL; } -}; - -template -struct Func1 : public UnboundFunc { - typedef R Return; - typedef I FuncInfo; - static R Call(P1 p1) { return F(p1); } -}; - -template -struct Func2 : public UnboundFunc { - typedef R Return; - typedef I FuncInfo; - static R Call(P1 p1, P2 p2) { return F(p1, p2); } -}; - -template -struct Func3 : public UnboundFunc { - typedef R Return; - typedef I FuncInfo; - static R Call(P1 p1, P2 p2, P3 p3) { return F(p1, p2, p3); } -}; - -template -struct Func4 : public UnboundFunc { - typedef R Return; - typedef I FuncInfo; - static R Call(P1 p1, P2 p2, P3 p3, P4 p4) { return F(p1, p2, p3, p4); } -}; - -template -struct Func5 : public UnboundFunc { - typedef R Return; - typedef I FuncInfo; - static R Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { - return F(p1, p2, p3, p4, p5); - } -}; - -/* BoundFunc ******************************************************************/ - -/* BoundFunc2, BoundFunc3: Like Func2/Func3 except also contains a value that - * shall be bound to the function's second parameter. - * - * Note that the second parameter is a const pointer, but our stored bound value - * is non-const so we can free it when the handlers are destroyed. */ -template -struct BoundFunc { - typedef typename remove_constptr::type MutableP2; - explicit BoundFunc(MutableP2 data_) : data(data_) {} - CleanupFunc *GetCleanup() { return &DeletePointer; } - MutableP2 GetData() { return data; } - MutableP2 data; -}; - -template -struct BoundFunc2 : public BoundFunc { - typedef BoundFunc Base; - typedef I FuncInfo; - explicit BoundFunc2(typename Base::MutableP2 arg) : Base(arg) {} -}; - -template -struct BoundFunc3 : public BoundFunc { - typedef BoundFunc Base; - typedef I FuncInfo; - explicit BoundFunc3(typename Base::MutableP2 arg) : Base(arg) {} -}; - -template -struct BoundFunc4 : public BoundFunc { - typedef BoundFunc Base; - typedef I FuncInfo; - explicit BoundFunc4(typename Base::MutableP2 arg) : Base(arg) {} -}; - -template -struct BoundFunc5 : public BoundFunc { - typedef BoundFunc Base; - typedef I FuncInfo; - explicit BoundFunc5(typename Base::MutableP2 arg) : Base(arg) {} -}; - -/* FuncSig ********************************************************************/ - -/* FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function - * *signature*, but without a specific function attached. - * - * These classes contain member functions that can be invoked with a - * specific function to return a Func/BoundFunc class. */ -template -struct FuncSig1 { - template - Func1 > GetFunc() { - return Func1 >(); - } -}; - -template -struct FuncSig2 { - template - Func2 > GetFunc() { - return Func2 >(); - } - - template - BoundFunc2 > GetFunc( - typename remove_constptr::type param2) { - return BoundFunc2 >(param2); - } -}; - -template -struct FuncSig3 { - template - Func3 > GetFunc() { - return Func3 >(); - } - - template - BoundFunc3 > GetFunc( - typename remove_constptr::type param2) { - return BoundFunc3 >(param2); - } -}; - -template -struct FuncSig4 { - template - Func4 > GetFunc() { - return Func4 >(); - } - - template - BoundFunc4 > GetFunc( - typename remove_constptr::type param2) { - return BoundFunc4 >(param2); - } -}; - -template -struct FuncSig5 { - template - Func5 > GetFunc() { - return Func5 >(); - } - - template - BoundFunc5 > GetFunc( - typename remove_constptr::type param2) { - return BoundFunc5 >(param2); - } -}; - -/* Overloaded template function that can construct the appropriate FuncSig* - * class given a function pointer by deducing the template parameters. */ -template -inline FuncSig1 MatchFunc(R (*f)(P1)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return FuncSig1(); -} - -template -inline FuncSig2 MatchFunc(R (*f)(P1, P2)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return FuncSig2(); -} - -template -inline FuncSig3 MatchFunc(R (*f)(P1, P2, P3)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return FuncSig3(); -} - -template -inline FuncSig4 MatchFunc(R (*f)(P1, P2, P3, P4)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return FuncSig4(); -} - -template -inline FuncSig5 MatchFunc(R (*f)(P1, P2, P3, P4, P5)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return FuncSig5(); -} - -/* MethodSig ******************************************************************/ - -/* CallMethod*: a function template that calls a given method. */ -template -R CallMethod0(C *obj) { - return ((*obj).*F)(); -} - -template -R CallMethod1(C *obj, P1 arg1) { - return ((*obj).*F)(arg1); -} - -template -R CallMethod2(C *obj, P1 arg1, P2 arg2) { - return ((*obj).*F)(arg1, arg2); -} - -template -R CallMethod3(C *obj, P1 arg1, P2 arg2, P3 arg3) { - return ((*obj).*F)(arg1, arg2, arg3); -} - -template -R CallMethod4(C *obj, P1 arg1, P2 arg2, P3 arg3, P4 arg4) { - return ((*obj).*F)(arg1, arg2, arg3, arg4); -} - -/* MethodSig: like FuncSig, but for member functions. - * - * GetFunc() returns a normal FuncN object, so after calling GetFunc() no - * more logic is required to special-case methods. */ -template -struct MethodSig0 { - template - Func1, FuncInfo > GetFunc() { - return Func1, FuncInfo >(); - } -}; - -template -struct MethodSig1 { - template - Func2, FuncInfo > GetFunc() { - return Func2, FuncInfo >(); - } - - template - BoundFunc2, FuncInfo > GetFunc( - typename remove_constptr::type param1) { - return BoundFunc2, FuncInfo >( - param1); - } -}; - -template -struct MethodSig2 { - template - Func3, FuncInfo > - GetFunc() { - return Func3, - FuncInfo >(); - } - - template - BoundFunc3, FuncInfo > - GetFunc(typename remove_constptr::type param1) { - return BoundFunc3, - FuncInfo >(param1); - } -}; - -template -struct MethodSig3 { - template - Func4, FuncInfo > - GetFunc() { - return Func4, - FuncInfo >(); - } - - template - BoundFunc4, - FuncInfo > - GetFunc(typename remove_constptr::type param1) { - return BoundFunc4, - FuncInfo >(param1); - } -}; - -template -struct MethodSig4 { - template - Func5, - FuncInfo > - GetFunc() { - return Func5, - FuncInfo >(); - } - - template - BoundFunc5, - FuncInfo > - GetFunc(typename remove_constptr::type param1) { - return BoundFunc5, FuncInfo >( - param1); - } -}; - -template -inline MethodSig0 MatchFunc(R (C::*f)()) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return MethodSig0(); -} - -template -inline MethodSig1 MatchFunc(R (C::*f)(P1)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return MethodSig1(); -} - -template -inline MethodSig2 MatchFunc(R (C::*f)(P1, P2)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return MethodSig2(); -} - -template -inline MethodSig3 MatchFunc(R (C::*f)(P1, P2, P3)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return MethodSig3(); -} - -template -inline MethodSig4 MatchFunc(R (C::*f)(P1, P2, P3, P4)) { - UPB_UNUSED(f); /* Only used for template parameter deduction. */ - return MethodSig4(); -} - -/* MaybeWrapReturn ************************************************************/ - -/* Template class that attempts to wrap the return value of the function so it - * matches the expected type. There are two main adjustments it may make: - * - * 1. If the function returns void, make it return the expected type and with - * a value that always indicates success. - * 2. If the function returns bool, make it return the expected type with a - * value that indicates success or failure. - * - * The "expected type" for return is: - * 1. void* for start handlers. If the closure parameter has a different type - * we will cast it to void* for the return in the success case. - * 2. size_t for string buffer handlers. - * 3. bool for everything else. */ - -/* Template parameters are FuncN type and desired return type. */ -template -struct MaybeWrapReturn; - -/* If the return type matches, return the given function unwrapped. */ -template -struct MaybeWrapReturn { - typedef F Func; -}; - -/* Function wrapper that munges the return value from void to (bool)true. */ -template -bool ReturnTrue2(P1 p1, P2 p2) { - F(p1, p2); - return true; -} - -template -bool ReturnTrue3(P1 p1, P2 p2, P3 p3) { - F(p1, p2, p3); - return true; -} - -/* Function wrapper that munges the return value from void to (void*)arg1 */ -template -void *ReturnClosure2(P1 p1, P2 p2) { - F(p1, p2); - return p1; -} - -template -void *ReturnClosure3(P1 p1, P2 p2, P3 p3) { - F(p1, p2, p3); - return p1; -} - -/* Function wrapper that munges the return value from R to void*. */ -template -void *CastReturnToVoidPtr2(P1 p1, P2 p2) { - return F(p1, p2); -} - -template -void *CastReturnToVoidPtr3(P1 p1, P2 p2, P3 p3) { - return F(p1, p2, p3); -} - -/* Function wrapper that munges the return value from bool to void*. */ -template -void *ReturnClosureOrBreak2(P1 p1, P2 p2) { - return F(p1, p2) ? p1 : UPB_BREAK; -} - -template -void *ReturnClosureOrBreak3(P1 p1, P2 p2, P3 p3) { - return F(p1, p2, p3) ? p1 : UPB_BREAK; -} - -/* For the string callback, which takes five params, returns the size param. */ -template -size_t ReturnStringLen(P1 p1, P2 p2, const char *p3, size_t p4, - const BufferHandle *p5) { - F(p1, p2, p3, p4, p5); - return p4; -} - -/* For the string callback, which takes five params, returns the size param or - * zero. */ -template -size_t ReturnNOr0(P1 p1, P2 p2, const char *p3, size_t p4, - const BufferHandle *p5) { - return F(p1, p2, p3, p4, p5) ? p4 : 0; -} - -/* If we have a function returning void but want a function returning bool, wrap - * it in a function that returns true. */ -template -struct MaybeWrapReturn, bool> { - typedef Func2, I> Func; -}; - -template -struct MaybeWrapReturn, bool> { - typedef Func3, I> Func; -}; - -/* If our function returns void but we want one returning void*, wrap it in a - * function that returns the first argument. */ -template -struct MaybeWrapReturn, void *> { - typedef Func2, I> Func; -}; - -template -struct MaybeWrapReturn, void *> { - typedef Func3, I> Func; -}; - -/* If our function returns R* but we want one returning void*, wrap it in a - * function that casts to void*. */ -template -struct MaybeWrapReturn, void *, - typename disable_if_same::Type> { - typedef Func2, I> Func; -}; - -template -struct MaybeWrapReturn, void *, - typename disable_if_same::Type> { - typedef Func3, I> - Func; -}; - -/* If our function returns bool but we want one returning void*, wrap it in a - * function that returns either the first param or UPB_BREAK. */ -template -struct MaybeWrapReturn, void *> { - typedef Func2, I> Func; -}; - -template -struct MaybeWrapReturn, void *> { - typedef Func3, I> - Func; -}; - -/* If our function returns void but we want one returning size_t, wrap it in a - * function that returns the size argument. */ -template -struct MaybeWrapReturn< - Func5, - size_t> { - typedef Func5, I> Func; -}; - -/* If our function returns bool but we want one returning size_t, wrap it in a - * function that returns either 0 or the buf size. */ -template -struct MaybeWrapReturn< - Func5, - size_t> { - typedef Func5, I> Func; -}; - -/* ConvertParams **************************************************************/ - -/* Template class that converts the function parameters if necessary, and - * ignores the HandlerData parameter if appropriate. - * - * Template parameter is the are FuncN function type. */ -template -struct ConvertParams; - -/* Function that discards the handler data parameter. */ -template -R IgnoreHandlerData2(void *p1, const void *hd) { - UPB_UNUSED(hd); - return F(static_cast(p1)); -} - -template -R IgnoreHandlerData3(void *p1, const void *hd, P2Wrapper p2) { - UPB_UNUSED(hd); - return F(static_cast(p1), p2); -} - -template -R IgnoreHandlerData4(void *p1, const void *hd, P2 p2, P3 p3) { - UPB_UNUSED(hd); - return F(static_cast(p1), p2, p3); -} - -template -R IgnoreHandlerData5(void *p1, const void *hd, P2 p2, P3 p3, P4 p4) { - UPB_UNUSED(hd); - return F(static_cast(p1), p2, p3, p4); -} - -template -R IgnoreHandlerDataIgnoreHandle(void *p1, const void *hd, const char *p2, - size_t p3, const BufferHandle *handle) { - UPB_UNUSED(hd); - UPB_UNUSED(handle); - return F(static_cast(p1), p2, p3); -} - -/* Function that casts the handler data parameter. */ -template -R CastHandlerData2(void *c, const void *hd) { - return F(static_cast(c), static_cast(hd)); -} - -template -R CastHandlerData3(void *c, const void *hd, P3Wrapper p3) { - return F(static_cast(c), static_cast(hd), p3); -} - -template -R CastHandlerData5(void *c, const void *hd, P3 p3, P4 p4, P5 p5) { - return F(static_cast(c), static_cast(hd), p3, p4, p5); -} - -template -R CastHandlerDataIgnoreHandle(void *c, const void *hd, const char *p3, - size_t p4, const BufferHandle *handle) { - UPB_UNUSED(handle); - return F(static_cast(c), static_cast(hd), p3, p4); -} - -/* For unbound functions, ignore the handler data. */ -template -struct ConvertParams, T> { - typedef Func2, I> Func; -}; - -template -struct ConvertParams, - R2 (*)(P1_2, P2_2, P3_2)> { - typedef Func3, I> Func; -}; - -/* For StringBuffer only; this ignores both the handler data and the - * BufferHandle. */ -template -struct ConvertParams, T> { - typedef Func5, - I> Func; -}; - -template -struct ConvertParams, T> { - typedef Func5, I> Func; -}; - -/* For bound functions, cast the handler data. */ -template -struct ConvertParams, T> { - typedef Func2, I> - Func; -}; - -template -struct ConvertParams, - R2 (*)(P1_2, P2_2, P3_2)> { - typedef Func3, I> Func; -}; - -/* For StringBuffer only; this ignores the BufferHandle. */ -template -struct ConvertParams, T> { - typedef Func5, - I> Func; -}; - -template -struct ConvertParams, T> { - typedef Func5, I> Func; -}; - -/* utype/ltype are upper/lower-case, ctype is canonical C type, vtype is - * variant C type. */ -#define TYPE_METHODS(utype, ltype, ctype, vtype) \ - template <> struct CanonicalType { \ - typedef ctype Type; \ - }; \ - template <> \ - inline bool Handlers::SetValueHandler( \ - const FieldDef *f, \ - const Handlers::utype ## Handler& handler) { \ - UPB_ASSERT(!handler.registered_); \ - handler.AddCleanup(this); \ - handler.registered_ = true; \ - return upb_handlers_set##ltype(this, f, handler.handler_, &handler.attr_); \ - } \ - -TYPE_METHODS(Double, double, double, double) -TYPE_METHODS(Float, float, float, float) -TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64_T) -TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32_T) -TYPE_METHODS(Int64, int64, int64_t, UPB_INT64_T) -TYPE_METHODS(Int32, int32, int32_t, UPB_INT32_T) -TYPE_METHODS(Bool, bool, bool, bool) - -#ifdef UPB_TWO_32BIT_TYPES -TYPE_METHODS(Int32, int32, int32_t, UPB_INT32ALT_T) -TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32ALT_T) -#endif - -#ifdef UPB_TWO_64BIT_TYPES -TYPE_METHODS(Int64, int64, int64_t, UPB_INT64ALT_T) -TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64ALT_T) -#endif -#undef TYPE_METHODS - -template <> struct CanonicalType { - typedef Status* Type; -}; - -/* Type methods that are only one-per-canonical-type and not - * one-per-cvariant. */ - -#define TYPE_METHODS(utype, ctype) \ - inline bool Handlers::Set##utype##Handler(const FieldDef *f, \ - const utype##Handler &h) { \ - return SetValueHandler(f, h); \ - } \ - -TYPE_METHODS(Double, double) -TYPE_METHODS(Float, float) -TYPE_METHODS(UInt64, uint64_t) -TYPE_METHODS(UInt32, uint32_t) -TYPE_METHODS(Int64, int64_t) -TYPE_METHODS(Int32, int32_t) -TYPE_METHODS(Bool, bool) -#undef TYPE_METHODS - -template struct ReturnOf; - -template -struct ReturnOf { - typedef R Return; -}; - -template -struct ReturnOf { - typedef R Return; -}; - -template -struct ReturnOf { - typedef R Return; -}; - -template -struct ReturnOf { - typedef R Return; -}; - -template const void *UniquePtrForType() { - static const char ch = 0; - return &ch; -} - -template -template -inline Handler::Handler(F func) - : registered_(false), - cleanup_data_(func.GetData()), - cleanup_func_(func.GetCleanup()) { - upb_handlerattr_sethandlerdata(&attr_, func.GetData()); - typedef typename ReturnOf::Return Return; - typedef typename ConvertParams::Func ConvertedParamsFunc; - typedef typename MaybeWrapReturn::Func - ReturnWrappedFunc; - handler_ = ReturnWrappedFunc().Call; - - /* Set attributes based on what templates can statically tell us about the - * user's function. */ - - /* If the original function returns void, then we know that we wrapped it to - * always return ok. */ - bool always_ok = is_same::value; - attr_.SetAlwaysOk(always_ok); - - /* Closure parameter and return type. */ - attr_.SetClosureType(UniquePtrForType()); - - /* We use the closure type (from the first parameter) if the return type is - * void or bool, since these are the two cases we wrap to return the closure's - * type anyway. - * - * This is all nonsense for non START* handlers, but it doesn't matter because - * in that case the value will be ignored. */ - typedef typename FirstUnlessVoidOrBool::value - EffectiveReturn; - attr_.SetReturnClosureType(UniquePtrForType()); -} - -template -inline Handler::~Handler() { - UPB_ASSERT(registered_); -} - -inline HandlerAttributes::HandlerAttributes() { upb_handlerattr_init(this); } -inline HandlerAttributes::~HandlerAttributes() { upb_handlerattr_uninit(this); } -inline bool HandlerAttributes::SetHandlerData(const void *hd) { - return upb_handlerattr_sethandlerdata(this, hd); -} -inline const void* HandlerAttributes::handler_data() const { - return upb_handlerattr_handlerdata(this); -} -inline bool HandlerAttributes::SetClosureType(const void *type) { - return upb_handlerattr_setclosuretype(this, type); -} -inline const void* HandlerAttributes::closure_type() const { - return upb_handlerattr_closuretype(this); -} -inline bool HandlerAttributes::SetReturnClosureType(const void *type) { - return upb_handlerattr_setreturnclosuretype(this, type); -} -inline const void* HandlerAttributes::return_closure_type() const { - return upb_handlerattr_returnclosuretype(this); -} -inline bool HandlerAttributes::SetAlwaysOk(bool always_ok) { - return upb_handlerattr_setalwaysok(this, always_ok); -} -inline bool HandlerAttributes::always_ok() const { - return upb_handlerattr_alwaysok(this); -} - -inline BufferHandle::BufferHandle() { upb_bufhandle_init(this); } -inline BufferHandle::~BufferHandle() { upb_bufhandle_uninit(this); } -inline const char* BufferHandle::buffer() const { - return upb_bufhandle_buf(this); -} -inline size_t BufferHandle::object_offset() const { - return upb_bufhandle_objofs(this); -} -inline void BufferHandle::SetBuffer(const char* buf, size_t ofs) { - upb_bufhandle_setbuf(this, buf, ofs); -} -template -void BufferHandle::SetAttachedObject(const T* obj) { - upb_bufhandle_setobj(this, obj, UniquePtrForType()); -} -template -const T* BufferHandle::GetAttachedObject() const { - return upb_bufhandle_objtype(this) == UniquePtrForType() - ? static_cast(upb_bufhandle_obj(this)) - : NULL; -} - -inline reffed_ptr Handlers::New(const MessageDef *m) { - upb_handlers *h = upb_handlers_new(m, &h); - return reffed_ptr(h, &h); -} -inline reffed_ptr Handlers::NewFrozen( - const MessageDef *m, upb_handlers_callback *callback, - const void *closure) { - const upb_handlers *h = upb_handlers_newfrozen(m, &h, callback, closure); - return reffed_ptr(h, &h); -} -inline const Status* Handlers::status() { - return upb_handlers_status(this); -} -inline void Handlers::ClearError() { - return upb_handlers_clearerr(this); -} -inline bool Handlers::Freeze(Status *s) { - upb::Handlers* h = this; - return upb_handlers_freeze(&h, 1, s); -} -inline bool Handlers::Freeze(Handlers *const *handlers, int n, Status *s) { - return upb_handlers_freeze(handlers, n, s); -} -inline bool Handlers::Freeze(const std::vector& h, Status* status) { - return upb_handlers_freeze((Handlers* const*)&h[0], h.size(), status); -} -inline const MessageDef *Handlers::message_def() const { - return upb_handlers_msgdef(this); -} -inline bool Handlers::AddCleanup(void *p, upb_handlerfree *func) { - return upb_handlers_addcleanup(this, p, func); -} -inline bool Handlers::SetStartMessageHandler( - const Handlers::StartMessageHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstartmsg(this, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetEndMessageHandler( - const Handlers::EndMessageHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setendmsg(this, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetStartStringHandler(const FieldDef *f, - const StartStringHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstartstr(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetEndStringHandler(const FieldDef *f, - const EndFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setendstr(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetStringHandler(const FieldDef *f, - const StringHandler& handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstring(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetStartSequenceHandler( - const FieldDef *f, const StartFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstartseq(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetStartSubMessageHandler( - const FieldDef *f, const StartFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstartsubmsg(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetEndSubMessageHandler(const FieldDef *f, - const EndFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setendsubmsg(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetEndSequenceHandler(const FieldDef *f, - const EndFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setendseq(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetSubHandlers(const FieldDef *f, const Handlers *sub) { - return upb_handlers_setsubhandlers(this, f, sub); -} -inline const Handlers *Handlers::GetSubHandlers(const FieldDef *f) const { - return upb_handlers_getsubhandlers(this, f); -} -inline const Handlers *Handlers::GetSubHandlers(Handlers::Selector sel) const { - return upb_handlers_getsubhandlers_sel(this, sel); -} -inline bool Handlers::GetSelector(const FieldDef *f, Handlers::Type type, - Handlers::Selector *s) { - return upb_handlers_getselector(f, type, s); -} -inline Handlers::Selector Handlers::GetEndSelector(Handlers::Selector start) { - return upb_handlers_getendselector(start); -} -inline Handlers::GenericFunction *Handlers::GetHandler( - Handlers::Selector selector) { - return upb_handlers_gethandler(this, selector); -} -inline const void *Handlers::GetHandlerData(Handlers::Selector selector) { - return upb_handlers_gethandlerdata(this, selector); -} - -inline BytesHandler::BytesHandler() { - upb_byteshandler_init(this); -} - -inline BytesHandler::~BytesHandler() {} - -} /* namespace upb */ - -#endif /* __cplusplus */ - - -#undef UPB_TWO_32BIT_TYPES -#undef UPB_TWO_64BIT_TYPES -#undef UPB_INT32_T -#undef UPB_UINT32_T -#undef UPB_INT32ALT_T -#undef UPB_UINT32ALT_T -#undef UPB_INT64_T -#undef UPB_UINT64_T -#undef UPB_INT64ALT_T -#undef UPB_UINT64ALT_T - -#endif /* UPB_HANDLERS_INL_H_ */ - -#endif /* UPB_HANDLERS_H */ -/* -** upb::Sink (upb_sink) -** upb::BytesSink (upb_bytessink) -** -** A upb_sink is an object that binds a upb_handlers object to some runtime -** state. It is the object that can actually receive data via the upb_handlers -** interface. -** -** Unlike upb_def and upb_handlers, upb_sink is never frozen, immutable, or -** thread-safe. You can create as many of them as you want, but each one may -** only be used in a single thread at a time. -** -** If we compare with class-based OOP, a you can think of a upb_def as an -** abstract base class, a upb_handlers as a concrete derived class, and a -** upb_sink as an object (class instance). -*/ - -#ifndef UPB_SINK_H -#define UPB_SINK_H - - -#ifdef __cplusplus -namespace upb { -class BufferSink; -class BufferSource; -class BytesSink; -class Sink; -} -#endif - -UPB_DECLARE_TYPE(upb::BufferSink, upb_bufsink) -UPB_DECLARE_TYPE(upb::BufferSource, upb_bufsrc) -UPB_DECLARE_TYPE(upb::BytesSink, upb_bytessink) -UPB_DECLARE_TYPE(upb::Sink, upb_sink) - -#ifdef __cplusplus - -/* A upb::Sink is an object that binds a upb::Handlers object to some runtime - * state. It represents an endpoint to which data can be sent. - * - * TODO(haberman): right now all of these functions take selectors. Should they - * take selectorbase instead? - * - * ie. instead of calling: - * sink->StartString(FOO_FIELD_START_STRING, ...) - * a selector base would let you say: - * sink->StartString(FOO_FIELD, ...) - * - * This would make call sites a little nicer and require emitting fewer selector - * definitions in .h files. - * - * But the current scheme has the benefit that you can retrieve a function - * pointer for any handler with handlers->GetHandler(selector), without having - * to have a separate GetHandler() function for each handler type. The JIT - * compiler uses this. To accommodate we'd have to expose a separate - * GetHandler() for every handler type. - * - * Also to ponder: selectors right now are independent of a specific Handlers - * instance. In other words, they allocate a number to every possible handler - * that *could* be registered, without knowing anything about what handlers - * *are* registered. That means that using selectors as table offsets prohibits - * us from compacting the handler table at Freeze() time. If the table is very - * sparse, this could be wasteful. - * - * Having another selector-like thing that is specific to a Handlers instance - * would allow this compacting, but then it would be impossible to write code - * ahead-of-time that can be bound to any Handlers instance at runtime. For - * example, a .proto file parser written as straight C will not know what - * Handlers it will be bound to, so when it calls sink->StartString() what - * selector will it pass? It needs a selector like we have today, that is - * independent of any particular upb::Handlers. - * - * Is there a way then to allow Handlers table compaction? */ -class upb::Sink { - public: - /* Constructor with no initialization; must be Reset() before use. */ - Sink() {} - - /* Constructs a new sink for the given frozen handlers and closure. - * - * TODO: once the Handlers know the expected closure type, verify that T - * matches it. */ - template Sink(const Handlers* handlers, T* closure); - - /* Resets the value of the sink. */ - template void Reset(const Handlers* handlers, T* closure); - - /* Returns the top-level object that is bound to this sink. - * - * TODO: once the Handlers know the expected closure type, verify that T - * matches it. */ - template T* GetObject() const; - - /* Functions for pushing data into the sink. - * - * These return false if processing should stop (either due to error or just - * to suspend). - * - * These may not be called from within one of the same sink's handlers (in - * other words, handlers are not re-entrant). */ - - /* Should be called at the start and end of every message; both the top-level - * message and submessages. This means that submessages should use the - * following sequence: - * sink->StartSubMessage(startsubmsg_selector); - * sink->StartMessage(); - * // ... - * sink->EndMessage(&status); - * sink->EndSubMessage(endsubmsg_selector); */ - bool StartMessage(); - bool EndMessage(Status* status); - - /* Putting of individual values. These work for both repeated and - * non-repeated fields, but for repeated fields you must wrap them in - * calls to StartSequence()/EndSequence(). */ - bool PutInt32(Handlers::Selector s, int32_t val); - bool PutInt64(Handlers::Selector s, int64_t val); - bool PutUInt32(Handlers::Selector s, uint32_t val); - bool PutUInt64(Handlers::Selector s, uint64_t val); - bool PutFloat(Handlers::Selector s, float val); - bool PutDouble(Handlers::Selector s, double val); - bool PutBool(Handlers::Selector s, bool val); - - /* Putting of string/bytes values. Each string can consist of zero or more - * non-contiguous buffers of data. - * - * For StartString(), the function will write a sink for the string to "sub." - * The sub-sink must be used for any/all PutStringBuffer() calls. */ - bool StartString(Handlers::Selector s, size_t size_hint, Sink* sub); - size_t PutStringBuffer(Handlers::Selector s, const char *buf, size_t len, - const BufferHandle *handle); - bool EndString(Handlers::Selector s); - - /* For submessage fields. - * - * For StartSubMessage(), the function will write a sink for the string to - * "sub." The sub-sink must be used for any/all handlers called within the - * submessage. */ - bool StartSubMessage(Handlers::Selector s, Sink* sub); - bool EndSubMessage(Handlers::Selector s); - - /* For repeated fields of any type, the sequence of values must be wrapped in - * these calls. - * - * For StartSequence(), the function will write a sink for the string to - * "sub." The sub-sink must be used for any/all handlers called within the - * sequence. */ - bool StartSequence(Handlers::Selector s, Sink* sub); - bool EndSequence(Handlers::Selector s); - - /* Copy and assign specifically allowed. - * We don't even bother making these members private because so many - * functions need them and this is mainly just a dumb data container anyway. - */ -#else -struct upb_sink { -#endif - const upb_handlers *handlers; - void *closure; -}; - -#ifdef __cplusplus -class upb::BytesSink { - public: - BytesSink() {} - - /* Constructs a new sink for the given frozen handlers and closure. - * - * TODO(haberman): once the Handlers know the expected closure type, verify - * that T matches it. */ - template BytesSink(const BytesHandler* handler, T* closure); - - /* Resets the value of the sink. */ - template void Reset(const BytesHandler* handler, T* closure); - - bool Start(size_t size_hint, void **subc); - size_t PutBuffer(void *subc, const char *buf, size_t len, - const BufferHandle *handle); - bool End(); -#else -struct upb_bytessink { -#endif - const upb_byteshandler *handler; - void *closure; -}; - -#ifdef __cplusplus - -/* A class for pushing a flat buffer of data to a BytesSink. - * You can construct an instance of this to get a resumable source, - * or just call the static PutBuffer() to do a non-resumable push all in one - * go. */ -class upb::BufferSource { - public: - BufferSource(); - BufferSource(const char* buf, size_t len, BytesSink* sink); - - /* Returns true if the entire buffer was pushed successfully. Otherwise the - * next call to PutNext() will resume where the previous one left off. - * TODO(haberman): implement this. */ - bool PutNext(); - - /* A static version; with this version is it not possible to resume in the - * case of failure or a partially-consumed buffer. */ - static bool PutBuffer(const char* buf, size_t len, BytesSink* sink); - - template static bool PutBuffer(const T& str, BytesSink* sink) { - return PutBuffer(str.c_str(), str.size(), sink); - } -#else -struct upb_bufsrc { - char dummy; -#endif -}; - -UPB_BEGIN_EXTERN_C - -/* A class for accumulating output string data in a flat buffer. */ - -upb_bufsink *upb_bufsink_new(upb_env *env); -void upb_bufsink_free(upb_bufsink *sink); -upb_bytessink *upb_bufsink_sink(upb_bufsink *sink); -const char *upb_bufsink_getdata(const upb_bufsink *sink, size_t *len); - -/* Inline definitions. */ - -UPB_INLINE void upb_bytessink_reset(upb_bytessink *s, const upb_byteshandler *h, - void *closure) { - s->handler = h; - s->closure = closure; -} - -UPB_INLINE bool upb_bytessink_start(upb_bytessink *s, size_t size_hint, - void **subc) { - typedef upb_startstr_handlerfunc func; - func *start; - *subc = s->closure; - if (!s->handler) return true; - start = (func *)s->handler->table[UPB_STARTSTR_SELECTOR].func; - - if (!start) return true; - *subc = start(s->closure, upb_handlerattr_handlerdata( - &s->handler->table[UPB_STARTSTR_SELECTOR].attr), - size_hint); - return *subc != NULL; -} - -UPB_INLINE size_t upb_bytessink_putbuf(upb_bytessink *s, void *subc, - const char *buf, size_t size, - const upb_bufhandle* handle) { - typedef upb_string_handlerfunc func; - func *putbuf; - if (!s->handler) return true; - putbuf = (func *)s->handler->table[UPB_STRING_SELECTOR].func; - - if (!putbuf) return true; - return putbuf(subc, upb_handlerattr_handlerdata( - &s->handler->table[UPB_STRING_SELECTOR].attr), - buf, size, handle); -} - -UPB_INLINE bool upb_bytessink_end(upb_bytessink *s) { - typedef upb_endfield_handlerfunc func; - func *end; - if (!s->handler) return true; - end = (func *)s->handler->table[UPB_ENDSTR_SELECTOR].func; - - if (!end) return true; - return end(s->closure, - upb_handlerattr_handlerdata( - &s->handler->table[UPB_ENDSTR_SELECTOR].attr)); -} - -bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink *sink); - -#define PUTVAL(type, ctype) \ - UPB_INLINE bool upb_sink_put##type(upb_sink *s, upb_selector_t sel, \ - ctype val) { \ - typedef upb_##type##_handlerfunc functype; \ - functype *func; \ - const void *hd; \ - if (!s->handlers) return true; \ - func = (functype *)upb_handlers_gethandler(s->handlers, sel); \ - if (!func) return true; \ - hd = upb_handlers_gethandlerdata(s->handlers, sel); \ - return func(s->closure, hd, val); \ - } - -PUTVAL(int32, int32_t) -PUTVAL(int64, int64_t) -PUTVAL(uint32, uint32_t) -PUTVAL(uint64, uint64_t) -PUTVAL(float, float) -PUTVAL(double, double) -PUTVAL(bool, bool) -#undef PUTVAL - -UPB_INLINE void upb_sink_reset(upb_sink *s, const upb_handlers *h, void *c) { - s->handlers = h; - s->closure = c; -} - -UPB_INLINE size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel, - const char *buf, size_t n, - const upb_bufhandle *handle) { - typedef upb_string_handlerfunc func; - func *handler; - const void *hd; - if (!s->handlers) return n; - handler = (func *)upb_handlers_gethandler(s->handlers, sel); - - if (!handler) return n; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - return handler(s->closure, hd, buf, n, handle); -} - -UPB_INLINE bool upb_sink_startmsg(upb_sink *s) { - typedef upb_startmsg_handlerfunc func; - func *startmsg; - const void *hd; - if (!s->handlers) return true; - startmsg = (func*)upb_handlers_gethandler(s->handlers, UPB_STARTMSG_SELECTOR); - - if (!startmsg) return true; - hd = upb_handlers_gethandlerdata(s->handlers, UPB_STARTMSG_SELECTOR); - return startmsg(s->closure, hd); -} - -UPB_INLINE bool upb_sink_endmsg(upb_sink *s, upb_status *status) { - typedef upb_endmsg_handlerfunc func; - func *endmsg; - const void *hd; - if (!s->handlers) return true; - endmsg = (func *)upb_handlers_gethandler(s->handlers, UPB_ENDMSG_SELECTOR); - - if (!endmsg) return true; - hd = upb_handlers_gethandlerdata(s->handlers, UPB_ENDMSG_SELECTOR); - return endmsg(s->closure, hd, status); -} - -UPB_INLINE bool upb_sink_startseq(upb_sink *s, upb_selector_t sel, - upb_sink *sub) { - typedef upb_startfield_handlerfunc func; - func *startseq; - const void *hd; - sub->closure = s->closure; - sub->handlers = s->handlers; - if (!s->handlers) return true; - startseq = (func*)upb_handlers_gethandler(s->handlers, sel); - - if (!startseq) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - sub->closure = startseq(s->closure, hd); - return sub->closure ? true : false; -} - -UPB_INLINE bool upb_sink_endseq(upb_sink *s, upb_selector_t sel) { - typedef upb_endfield_handlerfunc func; - func *endseq; - const void *hd; - if (!s->handlers) return true; - endseq = (func*)upb_handlers_gethandler(s->handlers, sel); - - if (!endseq) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - return endseq(s->closure, hd); -} - -UPB_INLINE bool upb_sink_startstr(upb_sink *s, upb_selector_t sel, - size_t size_hint, upb_sink *sub) { - typedef upb_startstr_handlerfunc func; - func *startstr; - const void *hd; - sub->closure = s->closure; - sub->handlers = s->handlers; - if (!s->handlers) return true; - startstr = (func*)upb_handlers_gethandler(s->handlers, sel); - - if (!startstr) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - sub->closure = startstr(s->closure, hd, size_hint); - return sub->closure ? true : false; -} - -UPB_INLINE bool upb_sink_endstr(upb_sink *s, upb_selector_t sel) { - typedef upb_endfield_handlerfunc func; - func *endstr; - const void *hd; - if (!s->handlers) return true; - endstr = (func*)upb_handlers_gethandler(s->handlers, sel); - - if (!endstr) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - return endstr(s->closure, hd); -} - -UPB_INLINE bool upb_sink_startsubmsg(upb_sink *s, upb_selector_t sel, - upb_sink *sub) { - typedef upb_startfield_handlerfunc func; - func *startsubmsg; - const void *hd; - sub->closure = s->closure; - if (!s->handlers) { - sub->handlers = NULL; - return true; - } - sub->handlers = upb_handlers_getsubhandlers_sel(s->handlers, sel); - startsubmsg = (func*)upb_handlers_gethandler(s->handlers, sel); - - if (!startsubmsg) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - sub->closure = startsubmsg(s->closure, hd); - return sub->closure ? true : false; -} - -UPB_INLINE bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) { - typedef upb_endfield_handlerfunc func; - func *endsubmsg; - const void *hd; - if (!s->handlers) return true; - endsubmsg = (func*)upb_handlers_gethandler(s->handlers, sel); - - if (!endsubmsg) return s->closure; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - return endsubmsg(s->closure, hd); -} - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { - -template Sink::Sink(const Handlers* handlers, T* closure) { - upb_sink_reset(this, handlers, closure); -} -template -inline void Sink::Reset(const Handlers* handlers, T* closure) { - upb_sink_reset(this, handlers, closure); -} -inline bool Sink::StartMessage() { - return upb_sink_startmsg(this); -} -inline bool Sink::EndMessage(Status* status) { - return upb_sink_endmsg(this, status); -} -inline bool Sink::PutInt32(Handlers::Selector sel, int32_t val) { - return upb_sink_putint32(this, sel, val); -} -inline bool Sink::PutInt64(Handlers::Selector sel, int64_t val) { - return upb_sink_putint64(this, sel, val); -} -inline bool Sink::PutUInt32(Handlers::Selector sel, uint32_t val) { - return upb_sink_putuint32(this, sel, val); -} -inline bool Sink::PutUInt64(Handlers::Selector sel, uint64_t val) { - return upb_sink_putuint64(this, sel, val); -} -inline bool Sink::PutFloat(Handlers::Selector sel, float val) { - return upb_sink_putfloat(this, sel, val); -} -inline bool Sink::PutDouble(Handlers::Selector sel, double val) { - return upb_sink_putdouble(this, sel, val); -} -inline bool Sink::PutBool(Handlers::Selector sel, bool val) { - return upb_sink_putbool(this, sel, val); -} -inline bool Sink::StartString(Handlers::Selector sel, size_t size_hint, - Sink *sub) { - return upb_sink_startstr(this, sel, size_hint, sub); -} -inline size_t Sink::PutStringBuffer(Handlers::Selector sel, const char *buf, - size_t len, const BufferHandle* handle) { - return upb_sink_putstring(this, sel, buf, len, handle); -} -inline bool Sink::EndString(Handlers::Selector sel) { - return upb_sink_endstr(this, sel); -} -inline bool Sink::StartSubMessage(Handlers::Selector sel, Sink* sub) { - return upb_sink_startsubmsg(this, sel, sub); -} -inline bool Sink::EndSubMessage(Handlers::Selector sel) { - return upb_sink_endsubmsg(this, sel); -} -inline bool Sink::StartSequence(Handlers::Selector sel, Sink* sub) { - return upb_sink_startseq(this, sel, sub); -} -inline bool Sink::EndSequence(Handlers::Selector sel) { - return upb_sink_endseq(this, sel); -} - -template -BytesSink::BytesSink(const BytesHandler* handler, T* closure) { - Reset(handler, closure); -} - -template -void BytesSink::Reset(const BytesHandler *handler, T *closure) { - upb_bytessink_reset(this, handler, closure); -} -inline bool BytesSink::Start(size_t size_hint, void **subc) { - return upb_bytessink_start(this, size_hint, subc); -} -inline size_t BytesSink::PutBuffer(void *subc, const char *buf, size_t len, - const BufferHandle *handle) { - return upb_bytessink_putbuf(this, subc, buf, len, handle); -} -inline bool BytesSink::End() { - return upb_bytessink_end(this); -} - -inline bool BufferSource::PutBuffer(const char *buf, size_t len, - BytesSink *sink) { - return upb_bufsrc_putbuf(buf, len, sink); -} - -} /* namespace upb */ -#endif - -#endif -/* -** upb::Message is a representation for protobuf messages. -** -** However it differs from other common representations like -** google::protobuf::Message in one key way: it does not prescribe any -** ownership between messages and submessages, and it relies on the -** client to delete each message/submessage/array/map at the appropriate -** time. -** -** A client can access a upb::Message without knowing anything about -** ownership semantics, but to create or mutate a message a user needs -** to implement the memory management themselves. -** -** Currently all messages, arrays, and maps store a upb_alloc* internally. -** Mutating operations use this when they require dynamically-allocated -** memory. We could potentially eliminate this size overhead later by -** letting the user flip a bit on the factory that prevents this from -** being stored. The user would then need to use separate functions where -** the upb_alloc* is passed explicitly. However for handlers to populate -** such structures, they would need a place to store this upb_alloc* during -** parsing; upb_handlers don't currently have a good way to accommodate this. -** -** TODO: UTF-8 checking? -**/ - -#ifndef UPB_MSG_H_ -#define UPB_MSG_H_ - - -#ifdef __cplusplus - -namespace upb { -class Array; -class Map; -class MapIterator; -class MessageFactory; -class MessageLayout; -class Visitor; -class VisitorPlan; -} - -#endif - -UPB_DECLARE_TYPE(upb::MessageFactory, upb_msgfactory) -UPB_DECLARE_TYPE(upb::MessageLayout, upb_msglayout) -UPB_DECLARE_TYPE(upb::Array, upb_array) -UPB_DECLARE_TYPE(upb::Map, upb_map) -UPB_DECLARE_TYPE(upb::MapIterator, upb_mapiter) -UPB_DECLARE_TYPE(upb::Visitor, upb_visitor) -UPB_DECLARE_TYPE(upb::VisitorPlan, upb_visitorplan) - -/* TODO(haberman): C++ accessors */ - -UPB_BEGIN_EXTERN_C - -typedef void upb_msg; - - -/** upb_msglayout *************************************************************/ - -/* upb_msglayout represents the memory layout of a given upb_msgdef. You get - * instances of this from a upb_msgfactory, and the factory always owns the - * msglayout. */ - -/* Gets the factory for this layout */ -upb_msgfactory *upb_msglayout_factory(const upb_msglayout *l); - -/* Get the msglayout for a submessage. This requires that this field is a - * submessage, ie. upb_fielddef_issubmsg(upb_msglayout_msgdef(l)) == true. - * - * Since map entry messages don't have layouts, if upb_fielddef_ismap(f) == true - * then this function will return the layout for the map's value. It requires - * that the value type of the map field is a submessage. */ -const upb_msglayout *upb_msglayout_sublayout(const upb_msglayout *l, - const upb_fielddef *f); - -/* Returns the msgdef for this msglayout. */ -const upb_msgdef *upb_msglayout_msgdef(const upb_msglayout *l); - - -/** upb_visitor ***************************************************************/ - -/* upb_visitor will visit all the fields of a message and its submessages. It - * uses a upb_visitorplan which you can obtain from a upb_msgfactory. */ - -upb_visitor *upb_visitor_create(upb_env *e, const upb_visitorplan *vp, - upb_sink *output); -bool upb_visitor_visitmsg(upb_visitor *v, const upb_msg *msg); - - -/** upb_msgfactory ************************************************************/ - -/* A upb_msgfactory contains a cache of upb_msglayout, upb_handlers, and - * upb_visitorplan objects. These are the objects necessary to represent, - * populate, and and visit upb_msg objects. - * - * These caches are all populated by upb_msgdef, and lazily created on demand. - */ - -/* Creates and destroys a msgfactory, respectively. The messages for this - * msgfactory must come from |symtab| (which should outlive the msgfactory). */ -upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab); -void upb_msgfactory_free(upb_msgfactory *f); - -const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f); - -/* The functions to get cached objects, lazily creating them on demand. These - * all require: - * - * - m is in upb_msgfactory_symtab(f) - * - upb_msgdef_mapentry(m) == false (since map messages can't have layouts). - * - * The returned objects will live for as long as the msgfactory does. - * - * TODO(haberman): consider making this thread-safe and take a const - * upb_msgfactory. */ -const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f, - const upb_msgdef *m); -const upb_handlers *upb_msgfactory_getmergehandlers(upb_msgfactory *f, - const upb_msgdef *m); -const upb_visitorplan *upb_msgfactory_getvisitorplan(upb_msgfactory *f, - const upb_handlers *h); - - -/** upb_msgval ****************************************************************/ - -/* A union representing all possible protobuf values. Used for generic get/set - * operations. */ - -typedef union { - bool b; - float flt; - double dbl; - int32_t i32; - int64_t i64; - uint32_t u32; - uint64_t u64; - const upb_map* map; - const upb_msg* msg; - const upb_array* arr; - const void* ptr; - struct { - const char *ptr; - size_t len; - } str; -} upb_msgval; - -#define ACCESSORS(name, membername, ctype) \ - UPB_INLINE ctype upb_msgval_get ## name(upb_msgval v) { \ - return v.membername; \ - } \ - UPB_INLINE void upb_msgval_set ## name(upb_msgval *v, ctype cval) { \ - v->membername = cval; \ - } \ - UPB_INLINE upb_msgval upb_msgval_ ## name(ctype v) { \ - upb_msgval ret; \ - ret.membername = v; \ - return ret; \ - } - -ACCESSORS(bool, b, bool) -ACCESSORS(float, flt, float) -ACCESSORS(double, dbl, double) -ACCESSORS(int32, i32, int32_t) -ACCESSORS(int64, i64, int64_t) -ACCESSORS(uint32, u32, uint32_t) -ACCESSORS(uint64, u64, uint64_t) -ACCESSORS(map, map, const upb_map*) -ACCESSORS(msg, msg, const upb_msg*) -ACCESSORS(ptr, ptr, const void*) -ACCESSORS(arr, arr, const upb_array*) - -#undef ACCESSORS - -UPB_INLINE upb_msgval upb_msgval_str(const char *ptr, size_t len) { - upb_msgval ret; - ret.str.ptr = ptr; - ret.str.len = len; - return ret; -} - -UPB_INLINE const char* upb_msgval_getstr(upb_msgval val) { - return val.str.ptr; -} - -UPB_INLINE size_t upb_msgval_getstrlen(upb_msgval val) { - return val.str.len; -} - - -/** upb_msg *******************************************************************/ - -/* A upb_msg represents a protobuf message. It always corresponds to a specific - * upb_msglayout, which describes how it is laid out in memory. - * - * The message will have a fixed size, as returned by upb_msg_sizeof(), which - * will be used to store fixed-length fields. The upb_msg may also allocate - * dynamic memory internally to store data such as: - * - * - extensions - * - unknown fields - */ - -/* Returns the size of a message given this layout. */ -size_t upb_msg_sizeof(const upb_msglayout *l); - -/* upb_msg_init() / upb_msg_uninit() allow the user to use a pre-allocated - * block of memory as a message. The block's size should be upb_msg_sizeof(). - * upb_msg_uninit() must be called to release internally-allocated memory - * unless the allocator is an arena that does not require freeing. - * - * Please note that upb_msg_uninit() does *not* free any submessages, maps, - * or arrays referred to by this message's fields. You must free them manually - * yourself. */ -void upb_msg_init(upb_msg *msg, const upb_msglayout *l, upb_alloc *a); -void upb_msg_uninit(upb_msg *msg, const upb_msglayout *l); - -/* Like upb_msg_init() / upb_msg_uninit(), except the message's memory is - * allocated / freed from the given upb_alloc. */ -upb_msg *upb_msg_new(const upb_msglayout *l, upb_alloc *a); -void upb_msg_free(upb_msg *msg, const upb_msglayout *l); - -/* Returns the upb_alloc for the given message. */ -upb_alloc *upb_msg_alloc(const upb_msg *msg, const upb_msglayout *l); - -/* Packs the tree of messages rooted at "msg" into a single hunk of memory, - * allocated from the given allocator. */ -void *upb_msg_pack(const upb_msg *msg, const upb_msglayout *l, - void *p, size_t *ofs, size_t size); - -/* Read-only message API. Can be safely called by anyone. */ - -/* Returns the value associated with this field: - * - for scalar fields (including strings), the value directly. - * - return upb_msg*, or upb_map* for msg/map. - * If the field is unset for these field types, returns NULL. - * - * TODO(haberman): should we let users store cached array/map/msg - * pointers here for fields that are unset? Could be useful for the - * strongly-owned submessage model (ie. generated C API that doesn't use - * arenas). - */ -upb_msgval upb_msg_get(const upb_msg *msg, - const upb_fielddef *f, - const upb_msglayout *l); - -/* May only be called for fields where upb_fielddef_haspresence(f) == true. */ -bool upb_msg_has(const upb_msg *msg, - const upb_fielddef *f, - const upb_msglayout *l); - -/* Returns NULL if no field in the oneof is set. */ -const upb_fielddef *upb_msg_getoneofcase(const upb_msg *msg, - const upb_oneofdef *o, - const upb_msglayout *l); - -/* Returns true if any field in the oneof is set. */ -bool upb_msg_hasoneof(const upb_msg *msg, - const upb_oneofdef *o, - const upb_msglayout *l); - - -/* Mutable message API. May only be called by the owner of the message who - * knows its ownership scheme and how to keep it consistent. */ - -/* Sets the given field to the given value. Does not perform any memory - * management: if you overwrite a pointer to a msg/array/map/string without - * cleaning it up (or using an arena) it will leak. - */ -bool upb_msg_set(upb_msg *msg, - const upb_fielddef *f, - upb_msgval val, - const upb_msglayout *l); - -/* For a primitive field, set it back to its default. For repeated, string, and - * submessage fields set it back to NULL. This could involve releasing some - * internal memory (for example, from an extension dictionary), but it is not - * recursive in any way and will not recover any memory that may be used by - * arrays/maps/strings/msgs that this field may have pointed to. - */ -bool upb_msg_clearfield(upb_msg *msg, - const upb_fielddef *f, - const upb_msglayout *l); - -/* Clears all fields in the oneof such that none of them are set. */ -bool upb_msg_clearoneof(upb_msg *msg, - const upb_oneofdef *o, - const upb_msglayout *l); - -/* TODO(haberman): copyfrom()/mergefrom()? */ - - -/** upb_array *****************************************************************/ - -/* A upb_array stores data for a repeated field. The memory management - * semantics are the same as upb_msg. A upb_array allocates dynamic - * memory internally for the array elements. */ - -size_t upb_array_sizeof(upb_fieldtype_t type); -void upb_array_init(upb_array *arr, upb_fieldtype_t type, upb_alloc *a); -void upb_array_uninit(upb_array *arr); -upb_array *upb_array_new(upb_fieldtype_t type, upb_alloc *a); -void upb_array_free(upb_array *arr); - -/* Read-only interface. Safe for anyone to call. */ - -size_t upb_array_size(const upb_array *arr); -upb_fieldtype_t upb_array_type(const upb_array *arr); -upb_msgval upb_array_get(const upb_array *arr, size_t i); - -/* Write interface. May only be called by the message's owner who can enforce - * its memory management invariants. */ - -bool upb_array_set(upb_array *arr, size_t i, upb_msgval val); - - -/** upb_map *******************************************************************/ - -/* A upb_map stores data for a map field. The memory management semantics are - * the same as upb_msg, with one notable exception. upb_map will internally - * store a copy of all string keys, but *not* any string values or submessages. - * So you must ensure that any string or message values outlive the map, and you - * must delete them manually when they are no longer required. */ - -size_t upb_map_sizeof(upb_fieldtype_t ktype, upb_fieldtype_t vtype); -bool upb_map_init(upb_map *map, upb_fieldtype_t ktype, upb_fieldtype_t vtype, - upb_alloc *a); -void upb_map_uninit(upb_map *map); -upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype, upb_alloc *a); -void upb_map_free(upb_map *map); - -/* Read-only interface. Safe for anyone to call. */ - -size_t upb_map_size(const upb_map *map); -upb_fieldtype_t upb_map_keytype(const upb_map *map); -upb_fieldtype_t upb_map_valuetype(const upb_map *map); -bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val); - -/* Write interface. May only be called by the message's owner who can enforce - * its memory management invariants. */ - -/* Sets or overwrites an entry in the map. Return value indicates whether - * the operation succeeded or failed with OOM, and also whether an existing - * key was replaced or not. */ -bool upb_map_set(upb_map *map, - upb_msgval key, upb_msgval val, - upb_msgval *valremoved); - -/* Deletes an entry in the map. Returns true if the key was present. */ -bool upb_map_del(upb_map *map, upb_msgval key); - - -/** upb_mapiter ***************************************************************/ - -/* For iterating over a map. Map iterators are invalidated by mutations to the - * map, but an invalidated iterator will never return junk or crash the process. - * An invalidated iterator may return entries that were already returned though, - * and if you keep invalidating the iterator during iteration, the program may - * enter an infinite loop. */ - -size_t upb_mapiter_sizeof(); - -void upb_mapiter_begin(upb_mapiter *i, const upb_map *t); -upb_mapiter *upb_mapiter_new(const upb_map *t, upb_alloc *a); -void upb_mapiter_free(upb_mapiter *i, upb_alloc *a); -void upb_mapiter_next(upb_mapiter *i); -bool upb_mapiter_done(const upb_mapiter *i); - -upb_msgval upb_mapiter_key(const upb_mapiter *i); -upb_msgval upb_mapiter_value(const upb_mapiter *i); -void upb_mapiter_setdone(upb_mapiter *i); -bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2); - - -/** Handlers ******************************************************************/ - -/* These are the handlers used internally by upb_msgfactory_getmergehandlers(). - * They write scalar data to a known offset from the message pointer. - * - * These would be trivial for anyone to implement themselves, but it's better - * to use these because some JITs will recognize and specialize these instead - * of actually calling the function. */ - -/* Sets a handler for the given primitive field that will write the data at the - * given offset. If hasbit > 0, also sets a hasbit at the given bit offset - * (addressing each byte low to high). */ -bool upb_msg_setscalarhandler(upb_handlers *h, - const upb_fielddef *f, - size_t offset, - int32_t hasbit); - -/* If the given handler is a msghandlers_primitive field, returns true and sets - * *type, *offset and *hasbit. Otherwise returns false. */ -bool upb_msg_getscalarhandlerdata(const upb_handlers *h, - upb_selector_t s, - upb_fieldtype_t *type, - size_t *offset, - int32_t *hasbit); - -UPB_END_EXTERN_C - -#endif /* UPB_MSG_H_ */ -/* -** upb::descriptor::Reader (upb_descreader) -** -** Provides a way of building upb::Defs from data in descriptor.proto format. -*/ - -#ifndef UPB_DESCRIPTOR_H -#define UPB_DESCRIPTOR_H - - -#ifdef __cplusplus -namespace upb { -namespace descriptor { -class Reader; -} /* namespace descriptor */ -} /* namespace upb */ -#endif - -UPB_DECLARE_TYPE(upb::descriptor::Reader, upb_descreader) - -#ifdef __cplusplus - -/* Class that receives descriptor data according to the descriptor.proto schema - * and use it to build upb::Defs corresponding to that schema. */ -class upb::descriptor::Reader { - public: - /* These handlers must have come from NewHandlers() and must outlive the - * Reader. - * - * TODO: generate the handlers statically (like we do with the - * descriptor.proto defs) so that there is no need to pass this parameter (or - * to build/memory-manage the handlers at runtime at all). Unfortunately this - * is a bit tricky to implement for Handlers, but necessary to simplify this - * interface. */ - static Reader* Create(Environment* env, const Handlers* handlers); - - /* The reader's input; this is where descriptor.proto data should be sent. */ - Sink* input(); - - /* Use to get the FileDefs that have been parsed. */ - size_t file_count() const; - FileDef* file(size_t i) const; - - /* Builds and returns handlers for the reader, owned by "owner." */ - static Handlers* NewHandlers(const void* owner); - - private: - UPB_DISALLOW_POD_OPS(Reader, upb::descriptor::Reader) -}; - -#endif - -UPB_BEGIN_EXTERN_C - -/* C API. */ -upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h); -upb_sink *upb_descreader_input(upb_descreader *r); -size_t upb_descreader_filecount(const upb_descreader *r); -upb_filedef *upb_descreader_file(const upb_descreader *r, size_t i); -const upb_handlers *upb_descreader_newhandlers(const void *owner); - -UPB_END_EXTERN_C - -#ifdef __cplusplus -/* C++ implementation details. ************************************************/ -namespace upb { -namespace descriptor { -inline Reader* Reader::Create(Environment* e, const Handlers *h) { - return upb_descreader_create(e, h); -} -inline Sink* Reader::input() { return upb_descreader_input(this); } -inline size_t Reader::file_count() const { - return upb_descreader_filecount(this); -} -inline FileDef* Reader::file(size_t i) const { - return upb_descreader_file(this, i); -} -} /* namespace descriptor */ -} /* namespace upb */ -#endif - -#endif /* UPB_DESCRIPTOR_H */ -/* This file contains accessors for a set of compiled-in defs. - * Note that unlike Google's protobuf, it does *not* define - * generated classes or any other kind of data structure for - * actually storing protobufs. It only contains *defs* which - * let you reflect over a protobuf *schema*. - */ -/* This file was generated by upbc (the upb compiler) from the input - * file: - * - * upb/descriptor/descriptor.proto - * - * Do not edit -- your changes will be discarded when the file is - * regenerated. */ - -#ifndef UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_ -#define UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_ - - -UPB_BEGIN_EXTERN_C - -/* Enums */ - -typedef enum { - google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1, - google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2, - google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3 -} google_protobuf_FieldDescriptorProto_Label; - -typedef enum { - google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1, - google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2, - google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3, - google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4, - google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5, - google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6, - google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7, - google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8, - google_protobuf_FieldDescriptorProto_TYPE_STRING = 9, - google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10, - google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11, - google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12, - google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13, - google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14, - google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15, - google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16, - google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17, - google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18 -} google_protobuf_FieldDescriptorProto_Type; - -typedef enum { - google_protobuf_FieldOptions_STRING = 0, - google_protobuf_FieldOptions_CORD = 1, - google_protobuf_FieldOptions_STRING_PIECE = 2 -} google_protobuf_FieldOptions_CType; - -typedef enum { - google_protobuf_FieldOptions_JS_NORMAL = 0, - google_protobuf_FieldOptions_JS_STRING = 1, - google_protobuf_FieldOptions_JS_NUMBER = 2 -} google_protobuf_FieldOptions_JSType; - -typedef enum { - google_protobuf_FileOptions_SPEED = 1, - google_protobuf_FileOptions_CODE_SIZE = 2, - google_protobuf_FileOptions_LITE_RUNTIME = 3 -} google_protobuf_FileOptions_OptimizeMode; - -/* MessageDefs: call these functions to get a ref to a msgdef. */ -const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_EnumOptions_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_FieldOptions_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_FileOptions_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_MessageOptions_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_MethodOptions_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_OneofDescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_ServiceOptions_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_get(const void *owner); -const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart_get(const void *owner); - -/* EnumDefs: call these functions to get a ref to an enumdef. */ -const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label_get(const void *owner); -const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type_get(const void *owner); -const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType_get(const void *owner); -const upb_enumdef *upbdefs_google_protobuf_FieldOptions_JSType_get(const void *owner); -const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode_get(const void *owner); - -/* Functions to test whether this message is of a certain type. */ -UPB_INLINE bool upbdefs_google_protobuf_DescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.DescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.DescriptorProto.ExtensionRange") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.DescriptorProto.ReservedRange") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_EnumDescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumDescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_EnumOptions_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumOptions") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_EnumValueDescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumValueDescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_EnumValueOptions_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumValueOptions") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FieldDescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.FieldDescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FieldOptions_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.FieldOptions") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FileDescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.FileDescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FileDescriptorSet_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.FileDescriptorSet") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FileOptions_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.FileOptions") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_MessageOptions_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.MessageOptions") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_MethodDescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.MethodDescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_MethodOptions_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.MethodOptions") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_OneofDescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.OneofDescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_ServiceDescriptorProto_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.ServiceDescriptorProto") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_ServiceOptions_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.ServiceOptions") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_SourceCodeInfo_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.SourceCodeInfo") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_SourceCodeInfo_Location_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.SourceCodeInfo.Location") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_UninterpretedOption_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.UninterpretedOption") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_UninterpretedOption_NamePart_is(const upb_msgdef *m) { - return strcmp(upb_msgdef_fullname(m), "google.protobuf.UninterpretedOption.NamePart") == 0; -} - -/* Functions to test whether this enum is of a certain type. */ -UPB_INLINE bool upbdefs_google_protobuf_FieldDescriptorProto_Label_is(const upb_enumdef *e) { - return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldDescriptorProto.Label") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FieldDescriptorProto_Type_is(const upb_enumdef *e) { - return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldDescriptorProto.Type") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FieldOptions_CType_is(const upb_enumdef *e) { - return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldOptions.CType") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FieldOptions_JSType_is(const upb_enumdef *e) { - return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldOptions.JSType") == 0; -} -UPB_INLINE bool upbdefs_google_protobuf_FileOptions_OptimizeMode_is(const upb_enumdef *e) { - return strcmp(upb_enumdef_fullname(e), "google.protobuf.FileOptions.OptimizeMode") == 0; -} - - -/* Functions to get a fielddef from a msgdef reference. */ -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_f_end(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_f_start(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_f_end(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_f_start(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_enum_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_extension(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_extension_range(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_field(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_nested_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_oneof_decl(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_reserved_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_reserved_range(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_f_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_f_allow_alias(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumOptions_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumOptions_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumOptions_is(m)); return upb_msgdef_itof(m, 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_f_number(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueOptions_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueOptions_is(m)); return upb_msgdef_itof(m, 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_default_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_extendee(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_json_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_label(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_number(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_oneof_index(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_type_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_ctype(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_jstype(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_lazy(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_packed(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_weak(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_dependency(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_enum_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_extension(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_message_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_package(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_public_dependency(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_service(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_source_code_info(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_syntax(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 12); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_weak_dependency(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 11); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorSet_f_file(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorSet_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_cc_enable_arenas(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 31); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_cc_generic_services(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 16); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_csharp_namespace(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 37); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 23); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_go_package(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 11); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_generate_equals_and_hash(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 20); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_generic_services(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 17); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_multiple_files(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 10); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_outer_classname(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_package(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_string_check_utf8(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 27); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_javanano_use_deprecated_package(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 38); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_objc_class_prefix(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 36); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_optimize_for(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 9); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_php_class_prefix(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 40); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_php_namespace(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 41); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_py_generic_services(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 18); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_map_entry(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 7); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_message_set_wire_format(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_no_standard_descriptor_accessor(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_client_streaming(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_input_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_output_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_server_streaming(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodOptions_is(m)); return upb_msgdef_itof(m, 33); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodOptions_is(m)); return upb_msgdef_itof(m, 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_OneofDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_OneofDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_f_method(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceOptions_is(m)); return upb_msgdef_itof(m, 33); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceOptions_is(m)); return upb_msgdef_itof(m, 999); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_leading_comments(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_leading_detached_comments(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_path(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_span(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_trailing_comments(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_f_location(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_f_is_extension(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_NamePart_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_f_name_part(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_NamePart_is(m)); return upb_msgdef_itof(m, 1); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_aggregate_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 8); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_double_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 6); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_identifier_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 3); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 2); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_negative_int_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 5); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_positive_int_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 4); } -UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_string_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 7); } - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upbdefs { -namespace google { -namespace protobuf { - -class DescriptorProto : public ::upb::reffed_ptr { - public: - DescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); - } - - static DescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_get(&m); - return DescriptorProto(m, &m); - } - - class ExtensionRange : public ::upb::reffed_ptr { - public: - ExtensionRange(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(m)); - } - - static ExtensionRange get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(&m); - return ExtensionRange(m, &m); - } - }; - - class ReservedRange : public ::upb::reffed_ptr { - public: - ReservedRange(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(m)); - } - - static ReservedRange get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(&m); - return ReservedRange(m, &m); - } - }; -}; - -class EnumDescriptorProto : public ::upb::reffed_ptr { - public: - EnumDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); - } - - static EnumDescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumDescriptorProto_get(&m); - return EnumDescriptorProto(m, &m); - } -}; - -class EnumOptions : public ::upb::reffed_ptr { - public: - EnumOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_EnumOptions_is(m)); - } - - static EnumOptions get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumOptions_get(&m); - return EnumOptions(m, &m); - } -}; - -class EnumValueDescriptorProto : public ::upb::reffed_ptr { - public: - EnumValueDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); - } - - static EnumValueDescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumValueDescriptorProto_get(&m); - return EnumValueDescriptorProto(m, &m); - } -}; - -class EnumValueOptions : public ::upb::reffed_ptr { - public: - EnumValueOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_EnumValueOptions_is(m)); - } - - static EnumValueOptions get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumValueOptions_get(&m); - return EnumValueOptions(m, &m); - } -}; - -class FieldDescriptorProto : public ::upb::reffed_ptr { - public: - FieldDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); - } - - static FieldDescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_FieldDescriptorProto_get(&m); - return FieldDescriptorProto(m, &m); - } - - class Label : public ::upb::reffed_ptr { - public: - Label(const ::upb::EnumDef* e, const void *ref_donor = NULL) - : reffed_ptr(e, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_Label_is(e)); - } - static Label get() { - const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldDescriptorProto_Label_get(&e); - return Label(e, &e); - } - }; - - class Type : public ::upb::reffed_ptr { - public: - Type(const ::upb::EnumDef* e, const void *ref_donor = NULL) - : reffed_ptr(e, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_Type_is(e)); - } - static Type get() { - const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldDescriptorProto_Type_get(&e); - return Type(e, &e); - } - }; -}; - -class FieldOptions : public ::upb::reffed_ptr { - public: - FieldOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); - } - - static FieldOptions get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_FieldOptions_get(&m); - return FieldOptions(m, &m); - } - - class CType : public ::upb::reffed_ptr { - public: - CType(const ::upb::EnumDef* e, const void *ref_donor = NULL) - : reffed_ptr(e, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_CType_is(e)); - } - static CType get() { - const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldOptions_CType_get(&e); - return CType(e, &e); - } - }; - - class JSType : public ::upb::reffed_ptr { - public: - JSType(const ::upb::EnumDef* e, const void *ref_donor = NULL) - : reffed_ptr(e, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_JSType_is(e)); - } - static JSType get() { - const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldOptions_JSType_get(&e); - return JSType(e, &e); - } - }; -}; - -class FileDescriptorProto : public ::upb::reffed_ptr { - public: - FileDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); - } - - static FileDescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_FileDescriptorProto_get(&m); - return FileDescriptorProto(m, &m); - } -}; - -class FileDescriptorSet : public ::upb::reffed_ptr { - public: - FileDescriptorSet(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorSet_is(m)); - } - - static FileDescriptorSet get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_FileDescriptorSet_get(&m); - return FileDescriptorSet(m, &m); - } -}; - -class FileOptions : public ::upb::reffed_ptr { - public: - FileOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); - } - - static FileOptions get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_FileOptions_get(&m); - return FileOptions(m, &m); - } - - class OptimizeMode : public ::upb::reffed_ptr { - public: - OptimizeMode(const ::upb::EnumDef* e, const void *ref_donor = NULL) - : reffed_ptr(e, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_FileOptions_OptimizeMode_is(e)); - } - static OptimizeMode get() { - const ::upb::EnumDef* e = upbdefs_google_protobuf_FileOptions_OptimizeMode_get(&e); - return OptimizeMode(e, &e); - } - }; -}; - -class MessageOptions : public ::upb::reffed_ptr { - public: - MessageOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); - } - - static MessageOptions get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_MessageOptions_get(&m); - return MessageOptions(m, &m); - } -}; - -class MethodDescriptorProto : public ::upb::reffed_ptr { - public: - MethodDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); - } - - static MethodDescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_MethodDescriptorProto_get(&m); - return MethodDescriptorProto(m, &m); - } -}; - -class MethodOptions : public ::upb::reffed_ptr { - public: - MethodOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_MethodOptions_is(m)); - } - - static MethodOptions get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_MethodOptions_get(&m); - return MethodOptions(m, &m); - } -}; - -class OneofDescriptorProto : public ::upb::reffed_ptr { - public: - OneofDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_OneofDescriptorProto_is(m)); - } - - static OneofDescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_OneofDescriptorProto_get(&m); - return OneofDescriptorProto(m, &m); - } -}; - -class ServiceDescriptorProto : public ::upb::reffed_ptr { - public: - ServiceDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_ServiceDescriptorProto_is(m)); - } - - static ServiceDescriptorProto get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_ServiceDescriptorProto_get(&m); - return ServiceDescriptorProto(m, &m); - } -}; - -class ServiceOptions : public ::upb::reffed_ptr { - public: - ServiceOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_ServiceOptions_is(m)); - } - - static ServiceOptions get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_ServiceOptions_get(&m); - return ServiceOptions(m, &m); - } -}; - -class SourceCodeInfo : public ::upb::reffed_ptr { - public: - SourceCodeInfo(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_is(m)); - } - - static SourceCodeInfo get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_SourceCodeInfo_get(&m); - return SourceCodeInfo(m, &m); - } - - class Location : public ::upb::reffed_ptr { - public: - Location(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); - } - - static Location get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_SourceCodeInfo_Location_get(&m); - return Location(m, &m); - } - }; -}; - -class UninterpretedOption : public ::upb::reffed_ptr { - public: - UninterpretedOption(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); - } - - static UninterpretedOption get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_UninterpretedOption_get(&m); - return UninterpretedOption(m, &m); - } - - class NamePart : public ::upb::reffed_ptr { - public: - NamePart(const ::upb::MessageDef* m, const void *ref_donor = NULL) - : reffed_ptr(m, ref_donor) { - UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_NamePart_is(m)); - } - - static NamePart get() { - const ::upb::MessageDef* m = upbdefs_google_protobuf_UninterpretedOption_NamePart_get(&m); - return NamePart(m, &m); - } - }; -}; - -} /* namespace protobuf */ -} /* namespace google */ -} /* namespace upbdefs */ - -#endif /* __cplusplus */ - -#endif /* UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_ */ -/* -** Internal-only definitions for the decoder. -*/ - -#ifndef UPB_DECODER_INT_H_ -#define UPB_DECODER_INT_H_ - -/* -** upb::pb::Decoder -** -** A high performance, streaming, resumable decoder for the binary protobuf -** format. -** -** This interface works the same regardless of what decoder backend is being -** used. A client of this class does not need to know whether decoding is using -** a JITted decoder (DynASM, LLVM, etc) or an interpreted decoder. By default, -** it will always use the fastest available decoder. However, you can call -** set_allow_jit(false) to disable any JIT decoder that might be available. -** This is primarily useful for testing purposes. -*/ - -#ifndef UPB_DECODER_H_ -#define UPB_DECODER_H_ - - -#ifdef __cplusplus -namespace upb { -namespace pb { -class CodeCache; -class Decoder; -class DecoderMethod; -class DecoderMethodOptions; -} /* namespace pb */ -} /* namespace upb */ -#endif - -UPB_DECLARE_TYPE(upb::pb::CodeCache, upb_pbcodecache) -UPB_DECLARE_TYPE(upb::pb::Decoder, upb_pbdecoder) -UPB_DECLARE_TYPE(upb::pb::DecoderMethodOptions, upb_pbdecodermethodopts) - -UPB_DECLARE_DERIVED_TYPE(upb::pb::DecoderMethod, upb::RefCounted, - upb_pbdecodermethod, upb_refcounted) - -/* The maximum number of bytes we are required to buffer internally between - * calls to the decoder. The value is 14: a 5 byte unknown tag plus ten-byte - * varint, less one because we are buffering an incomplete value. - * - * Should only be used by unit tests. */ -#define UPB_DECODER_MAX_RESIDUAL_BYTES 14 - -#ifdef __cplusplus - -/* The parameters one uses to construct a DecoderMethod. - * TODO(haberman): move allowjit here? Seems more convenient for users. - * TODO(haberman): move this to be heap allocated for ABI stability. */ -class upb::pb::DecoderMethodOptions { - public: - /* Parameter represents the destination handlers that this method will push - * to. */ - explicit DecoderMethodOptions(const Handlers* dest_handlers); - - /* Should the decoder push submessages to lazy handlers for fields that have - * them? The caller should set this iff the lazy handlers expect data that is - * in protobuf binary format and the caller wishes to lazy parse it. */ - void set_lazy(bool lazy); -#else -struct upb_pbdecodermethodopts { -#endif - const upb_handlers *handlers; - bool lazy; -}; - -#ifdef __cplusplus - -/* Represents the code to parse a protobuf according to a destination - * Handlers. */ -class upb::pb::DecoderMethod { - public: - /* Include base methods from upb::ReferenceCounted. */ - UPB_REFCOUNTED_CPPMETHODS - - /* The destination handlers that are statically bound to this method. - * This method is only capable of outputting to a sink that uses these - * handlers. */ - const Handlers* dest_handlers() const; - - /* The input handlers for this decoder method. */ - const BytesHandler* input_handler() const; - - /* Whether this method is native. */ - bool is_native() const; - - /* Convenience method for generating a DecoderMethod without explicitly - * creating a CodeCache. */ - static reffed_ptr New(const DecoderMethodOptions& opts); - - private: - UPB_DISALLOW_POD_OPS(DecoderMethod, upb::pb::DecoderMethod) -}; - -#endif - -/* Preallocation hint: decoder won't allocate more bytes than this when first - * constructed. This hint may be an overestimate for some build configurations. - * But if the decoder library is upgraded without recompiling the application, - * it may be an underestimate. */ -#define UPB_PB_DECODER_SIZE 4416 - -#ifdef __cplusplus - -/* A Decoder receives binary protobuf data on its input sink and pushes the - * decoded data to its output sink. */ -class upb::pb::Decoder { - public: - /* Constructs a decoder instance for the given method, which must outlive this - * decoder. Any errors during parsing will be set on the given status, which - * must also outlive this decoder. - * - * The sink must match the given method. */ - static Decoder* Create(Environment* env, const DecoderMethod* method, - Sink* output); - - /* Returns the DecoderMethod this decoder is parsing from. */ - const DecoderMethod* method() const; - - /* The sink on which this decoder receives input. */ - BytesSink* input(); - - /* Returns number of bytes successfully parsed. - * - * This can be useful for determining the stream position where an error - * occurred. - * - * This value may not be up-to-date when called from inside a parsing - * callback. */ - uint64_t BytesParsed() const; - - /* Gets/sets the parsing nexting limit. If the total number of nested - * submessages and repeated fields hits this limit, parsing will fail. This - * is a resource limit that controls the amount of memory used by the parsing - * stack. - * - * Setting the limit will fail if the parser is currently suspended at a depth - * greater than this, or if memory allocation of the stack fails. */ - size_t max_nesting() const; - bool set_max_nesting(size_t max); - - void Reset(); - - static const size_t kSize = UPB_PB_DECODER_SIZE; - - private: - UPB_DISALLOW_POD_OPS(Decoder, upb::pb::Decoder) -}; - -#endif /* __cplusplus */ - -#ifdef __cplusplus - -/* A class for caching protobuf processing code, whether bytecode for the - * interpreted decoder or machine code for the JIT. - * - * This class is not thread-safe. - * - * TODO(haberman): move this to be heap allocated for ABI stability. */ -class upb::pb::CodeCache { - public: - CodeCache(); - ~CodeCache(); - - /* Whether the cache is allowed to generate machine code. Defaults to true. - * There is no real reason to turn it off except for testing or if you are - * having a specific problem with the JIT. - * - * Note that allow_jit = true does not *guarantee* that the code will be JIT - * compiled. If this platform is not supported or the JIT was not compiled - * in, the code may still be interpreted. */ - bool allow_jit() const; - - /* This may only be called when the object is first constructed, and prior to - * any code generation, otherwise returns false and does nothing. */ - bool set_allow_jit(bool allow); - - /* Returns a DecoderMethod that can push data to the given handlers. - * If a suitable method already exists, it will be returned from the cache. - * - * Specifying the destination handlers here allows the DecoderMethod to be - * statically bound to the destination handlers if possible, which can allow - * more efficient decoding. However the returned method may or may not - * actually be statically bound. But in all cases, the returned method can - * push data to the given handlers. */ - const DecoderMethod *GetDecoderMethod(const DecoderMethodOptions& opts); - - /* If/when someone needs to explicitly create a dynamically-bound - * DecoderMethod*, we can add a method to get it here. */ - - private: - UPB_DISALLOW_COPY_AND_ASSIGN(CodeCache) -#else -struct upb_pbcodecache { -#endif - bool allow_jit_; - - /* Array of mgroups. */ - upb_inttable groups; -}; - -UPB_BEGIN_EXTERN_C - -upb_pbdecoder *upb_pbdecoder_create(upb_env *e, - const upb_pbdecodermethod *method, - upb_sink *output); -const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d); -upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d); -uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d); -size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d); -bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max); -void upb_pbdecoder_reset(upb_pbdecoder *d); - -void upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts, - const upb_handlers *h); -void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy); - - -/* Include refcounted methods like upb_pbdecodermethod_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_pbdecodermethod, upb_pbdecodermethod_upcast) - -const upb_handlers *upb_pbdecodermethod_desthandlers( - const upb_pbdecodermethod *m); -const upb_byteshandler *upb_pbdecodermethod_inputhandler( - const upb_pbdecodermethod *m); -bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m); -const upb_pbdecodermethod *upb_pbdecodermethod_new( - const upb_pbdecodermethodopts *opts, const void *owner); - -void upb_pbcodecache_init(upb_pbcodecache *c); -void upb_pbcodecache_uninit(upb_pbcodecache *c); -bool upb_pbcodecache_allowjit(const upb_pbcodecache *c); -bool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow); -const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod( - upb_pbcodecache *c, const upb_pbdecodermethodopts *opts); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { - -namespace pb { - -/* static */ -inline Decoder* Decoder::Create(Environment* env, const DecoderMethod* m, - Sink* sink) { - return upb_pbdecoder_create(env, m, sink); -} -inline const DecoderMethod* Decoder::method() const { - return upb_pbdecoder_method(this); -} -inline BytesSink* Decoder::input() { - return upb_pbdecoder_input(this); -} -inline uint64_t Decoder::BytesParsed() const { - return upb_pbdecoder_bytesparsed(this); -} -inline size_t Decoder::max_nesting() const { - return upb_pbdecoder_maxnesting(this); -} -inline bool Decoder::set_max_nesting(size_t max) { - return upb_pbdecoder_setmaxnesting(this, max); -} -inline void Decoder::Reset() { upb_pbdecoder_reset(this); } - -inline DecoderMethodOptions::DecoderMethodOptions(const Handlers* h) { - upb_pbdecodermethodopts_init(this, h); -} -inline void DecoderMethodOptions::set_lazy(bool lazy) { - upb_pbdecodermethodopts_setlazy(this, lazy); -} - -inline const Handlers* DecoderMethod::dest_handlers() const { - return upb_pbdecodermethod_desthandlers(this); -} -inline const BytesHandler* DecoderMethod::input_handler() const { - return upb_pbdecodermethod_inputhandler(this); -} -inline bool DecoderMethod::is_native() const { - return upb_pbdecodermethod_isnative(this); -} -/* static */ -inline reffed_ptr DecoderMethod::New( - const DecoderMethodOptions &opts) { - const upb_pbdecodermethod *m = upb_pbdecodermethod_new(&opts, &m); - return reffed_ptr(m, &m); -} - -inline CodeCache::CodeCache() { - upb_pbcodecache_init(this); -} -inline CodeCache::~CodeCache() { - upb_pbcodecache_uninit(this); -} -inline bool CodeCache::allow_jit() const { - return upb_pbcodecache_allowjit(this); -} -inline bool CodeCache::set_allow_jit(bool allow) { - return upb_pbcodecache_setallowjit(this, allow); -} -inline const DecoderMethod *CodeCache::GetDecoderMethod( - const DecoderMethodOptions& opts) { - return upb_pbcodecache_getdecodermethod(this, &opts); -} - -} /* namespace pb */ -} /* namespace upb */ - -#endif /* __cplusplus */ - -#endif /* UPB_DECODER_H_ */ - -/* C++ names are not actually used since this type isn't exposed to users. */ -#ifdef __cplusplus -namespace upb { -namespace pb { -class MessageGroup; -} /* namespace pb */ -} /* namespace upb */ -#endif -UPB_DECLARE_DERIVED_TYPE(upb::pb::MessageGroup, upb::RefCounted, - mgroup, upb_refcounted) - -/* Opcode definitions. The canonical meaning of each opcode is its - * implementation in the interpreter (the JIT is written to match this). - * - * All instructions have the opcode in the low byte. - * Instruction format for most instructions is: - * - * +-------------------+--------+ - * | arg (24) | op (8) | - * +-------------------+--------+ - * - * Exceptions are indicated below. A few opcodes are multi-word. */ -typedef enum { - /* Opcodes 1-8, 13, 15-18 parse their respective descriptor types. - * Arg for all of these is the upb selector for this field. */ -#define T(type) OP_PARSE_ ## type = UPB_DESCRIPTOR_TYPE_ ## type - T(DOUBLE), T(FLOAT), T(INT64), T(UINT64), T(INT32), T(FIXED64), T(FIXED32), - T(BOOL), T(UINT32), T(SFIXED32), T(SFIXED64), T(SINT32), T(SINT64), -#undef T - OP_STARTMSG = 9, /* No arg. */ - OP_ENDMSG = 10, /* No arg. */ - OP_STARTSEQ = 11, - OP_ENDSEQ = 12, - OP_STARTSUBMSG = 14, - OP_ENDSUBMSG = 19, - OP_STARTSTR = 20, - OP_STRING = 21, - OP_ENDSTR = 22, - - OP_PUSHTAGDELIM = 23, /* No arg. */ - OP_PUSHLENDELIM = 24, /* No arg. */ - OP_POP = 25, /* No arg. */ - OP_SETDELIM = 26, /* No arg. */ - OP_SETBIGGROUPNUM = 27, /* two words: - * | unused (24) | opc (8) | - * | groupnum (32) | */ - OP_CHECKDELIM = 28, - OP_CALL = 29, - OP_RET = 30, - OP_BRANCH = 31, - - /* Different opcodes depending on how many bytes expected. */ - OP_TAG1 = 32, /* | match tag (16) | jump target (8) | opc (8) | */ - OP_TAG2 = 33, /* | match tag (16) | jump target (8) | opc (8) | */ - OP_TAGN = 34, /* three words: */ - /* | unused (16) | jump target(8) | opc (8) | */ - /* | match tag 1 (32) | */ - /* | match tag 2 (32) | */ - - OP_SETDISPATCH = 35, /* N words: */ - /* | unused (24) | opc | */ - /* | upb_inttable* (32 or 64) | */ - - OP_DISPATCH = 36, /* No arg. */ - - OP_HALT = 37 /* No arg. */ -} opcode; - -#define OP_MAX OP_HALT - -UPB_INLINE opcode getop(uint32_t instr) { return instr & 0xff; } - -/* Method group; represents a set of decoder methods that had their code - * emitted together, and must therefore be freed together. Immutable once - * created. It is possible we may want to expose this to users at some point. - * - * Overall ownership of Decoder objects looks like this: - * - * +----------+ - * | | <---> DecoderMethod - * | method | - * CodeCache ---> | group | <---> DecoderMethod - * | | - * | (mgroup) | <---> DecoderMethod - * +----------+ - */ -struct mgroup { - upb_refcounted base; - - /* Maps upb_msgdef/upb_handlers -> upb_pbdecodermethod. We own refs on the - * methods. */ - upb_inttable methods; - - /* When we add the ability to link to previously existing mgroups, we'll - * need an array of mgroups we reference here, and own refs on them. */ - - /* The bytecode for our methods, if any exists. Owned by us. */ - uint32_t *bytecode; - uint32_t *bytecode_end; - -#ifdef UPB_USE_JIT_X64 - /* JIT-generated machine code, if any. */ - upb_string_handlerfunc *jit_code; - /* The size of the jit_code (required to munmap()). */ - size_t jit_size; - char *debug_info; - void *dl; -#endif -}; - -/* The maximum that any submessages can be nested. Matches proto2's limit. - * This specifies the size of the decoder's statically-sized array and therefore - * setting it high will cause the upb::pb::Decoder object to be larger. - * - * If necessary we can add a runtime-settable property to Decoder that allow - * this to be larger than the compile-time setting, but this would add - * complexity, particularly since we would have to decide how/if to give users - * the ability to set a custom memory allocation function. */ -#define UPB_DECODER_MAX_NESTING 64 - -/* Internal-only struct used by the decoder. */ -typedef struct { - /* Space optimization note: we store two pointers here that the JIT - * doesn't need at all; the upb_handlers* inside the sink and - * the dispatch table pointer. We can optimze so that the JIT uses - * smaller stack frames than the interpreter. The only thing we need - * to guarantee is that the fallback routines can find end_ofs. */ - upb_sink sink; - - /* The absolute stream offset of the end-of-frame delimiter. - * Non-delimited frames (groups and non-packed repeated fields) reuse the - * delimiter of their parent, even though the frame may not end there. - * - * NOTE: the JIT stores a slightly different value here for non-top frames. - * It stores the value relative to the end of the enclosed message. But the - * top frame is still stored the same way, which is important for ensuring - * that calls from the JIT into C work correctly. */ - uint64_t end_ofs; - const uint32_t *base; - - /* 0 indicates a length-delimited field. - * A positive number indicates a known group. - * A negative number indicates an unknown group. */ - int32_t groupnum; - upb_inttable *dispatch; /* Not used by the JIT. */ -} upb_pbdecoder_frame; - -struct upb_pbdecodermethod { - upb_refcounted base; - - /* While compiling, the base is relative in "ofs", after compiling it is - * absolute in "ptr". */ - union { - uint32_t ofs; /* PC offset of method. */ - void *ptr; /* Pointer to bytecode or machine code for this method. */ - } code_base; - - /* The decoder method group to which this method belongs. We own a ref. - * Owning a ref on the entire group is more coarse-grained than is strictly - * necessary; all we truly require is that methods we directly reference - * outlive us, while the group could contain many other messages we don't - * require. But the group represents the messages that were - * allocated+compiled together, so it makes the most sense to free them - * together also. */ - const upb_refcounted *group; - - /* Whether this method is native code or bytecode. */ - bool is_native_; - - /* The handler one calls to invoke this method. */ - upb_byteshandler input_handler_; - - /* The destination handlers this method is bound to. We own a ref. */ - const upb_handlers *dest_handlers_; - - /* Dispatch table -- used by both bytecode decoder and JIT when encountering a - * field number that wasn't the one we were expecting to see. See - * decoder.int.h for the layout of this table. */ - upb_inttable dispatch; -}; - -struct upb_pbdecoder { - upb_env *env; - - /* Our input sink. */ - upb_bytessink input_; - - /* The decoder method we are parsing with (owned). */ - const upb_pbdecodermethod *method_; - - size_t call_len; - const uint32_t *pc, *last; - - /* Current input buffer and its stream offset. */ - const char *buf, *ptr, *end, *checkpoint; - - /* End of the delimited region, relative to ptr, NULL if not in this buf. */ - const char *delim_end; - - /* End of the delimited region, relative to ptr, end if not in this buf. */ - const char *data_end; - - /* Overall stream offset of "buf." */ - uint64_t bufstart_ofs; - - /* Buffer for residual bytes not parsed from the previous buffer. */ - char residual[UPB_DECODER_MAX_RESIDUAL_BYTES]; - char *residual_end; - - /* Bytes of data that should be discarded from the input beore we start - * parsing again. We set this when we internally determine that we can - * safely skip the next N bytes, but this region extends past the current - * user buffer. */ - size_t skip; - - /* Stores the user buffer passed to our decode function. */ - const char *buf_param; - size_t size_param; - const upb_bufhandle *handle; - - /* Our internal stack. */ - upb_pbdecoder_frame *stack, *top, *limit; - const uint32_t **callstack; - size_t stack_size; - - upb_status *status; - -#ifdef UPB_USE_JIT_X64 - /* Used momentarily by the generated code to store a value while a user - * function is called. */ - uint32_t tmp_len; - - const void *saved_rsp; -#endif -}; - -/* Decoder entry points; used as handlers. */ -void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint); -void *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint); -size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, - size_t size, const upb_bufhandle *handle); -bool upb_pbdecoder_end(void *closure, const void *handler_data); - -/* Decoder-internal functions that the JIT calls to handle fallback paths. */ -int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf, - size_t size, const upb_bufhandle *handle); -size_t upb_pbdecoder_suspend(upb_pbdecoder *d); -int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum, - uint8_t wire_type); -int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d, uint64_t expected); -int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, uint64_t *u64); -int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32); -int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64); -void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg); - -/* Error messages that are shared between the bytecode and JIT decoders. */ -extern const char *kPbDecoderStackOverflow; -extern const char *kPbDecoderSubmessageTooLong; - -/* Access to decoderplan members needed by the decoder. */ -const char *upb_pbdecoder_getopname(unsigned int op); - -/* JIT codegen entry point. */ -void upb_pbdecoder_jit(mgroup *group); -void upb_pbdecoder_freejit(mgroup *group); -UPB_REFCOUNTED_CMETHODS(mgroup, mgroup_upcast) - -/* A special label that means "do field dispatch for this message and branch to - * wherever that takes you." */ -#define LABEL_DISPATCH 0 - -/* A special slot in the dispatch table that stores the epilogue (ENDMSG and/or - * RET) for branching to when we find an appropriate ENDGROUP tag. */ -#define DISPATCH_ENDMSG 0 - -/* It's important to use this invalid wire type instead of 0 (which is a valid - * wire type). */ -#define NO_WIRE_TYPE 0xff - -/* The dispatch table layout is: - * [field number] -> [ 48-bit offset ][ 8-bit wt2 ][ 8-bit wt1 ] - * - * If wt1 matches, jump to the 48-bit offset. If wt2 matches, lookup - * (UPB_MAX_FIELDNUMBER + fieldnum) and jump there. - * - * We need two wire types because of packed/non-packed compatibility. A - * primitive repeated field can use either wire type and be valid. While we - * could key the table on fieldnum+wiretype, the table would be 8x sparser. - * - * Storing two wire types in the primary value allows us to quickly rule out - * the second wire type without needing to do a separate lookup (this case is - * less common than an unknown field). */ -UPB_INLINE uint64_t upb_pbdecoder_packdispatch(uint64_t ofs, uint8_t wt1, - uint8_t wt2) { - return (ofs << 16) | (wt2 << 8) | wt1; -} - -UPB_INLINE void upb_pbdecoder_unpackdispatch(uint64_t dispatch, uint64_t *ofs, - uint8_t *wt1, uint8_t *wt2) { - *wt1 = (uint8_t)dispatch; - *wt2 = (uint8_t)(dispatch >> 8); - *ofs = dispatch >> 16; -} - -/* All of the functions in decoder.c that return int32_t return values according - * to the following scheme: - * 1. negative values indicate a return code from the following list. - * 2. positive values indicate that error or end of buffer was hit, and - * that the decode function should immediately return the given value - * (the decoder state has already been suspended and is ready to be - * resumed). */ -#define DECODE_OK -1 -#define DECODE_MISMATCH -2 /* Used only from checktag_slow(). */ -#define DECODE_ENDGROUP -3 /* Used only from checkunknown(). */ - -#define CHECK_RETURN(x) { int32_t ret = x; if (ret >= 0) return ret; } - -#endif /* UPB_DECODER_INT_H_ */ -/* -** A number of routines for varint manipulation (we keep them all around to -** have multiple approaches available for benchmarking). -*/ - -#ifndef UPB_VARINT_DECODER_H_ -#define UPB_VARINT_DECODER_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* A list of types as they are encoded on-the-wire. */ -typedef enum { - UPB_WIRE_TYPE_VARINT = 0, - UPB_WIRE_TYPE_64BIT = 1, - UPB_WIRE_TYPE_DELIMITED = 2, - UPB_WIRE_TYPE_START_GROUP = 3, - UPB_WIRE_TYPE_END_GROUP = 4, - UPB_WIRE_TYPE_32BIT = 5 -} upb_wiretype_t; - -#define UPB_MAX_WIRE_TYPE 5 - -/* The maximum number of bytes that it takes to encode a 64-bit varint. - * Note that with a better encoding this could be 9 (TODO: write up a - * wiki document about this). */ -#define UPB_PB_VARINT_MAX_LEN 10 - -/* Array of the "native" (ie. non-packed-repeated) wire type for the given a - * descriptor type (upb_descriptortype_t). */ -extern const uint8_t upb_pb_native_wire_types[]; - -/* Zig-zag encoding/decoding **************************************************/ - -UPB_INLINE int32_t upb_zzdec_32(uint32_t n) { - return (n >> 1) ^ -(int32_t)(n & 1); -} -UPB_INLINE int64_t upb_zzdec_64(uint64_t n) { - return (n >> 1) ^ -(int64_t)(n & 1); -} -UPB_INLINE uint32_t upb_zzenc_32(int32_t n) { return (n << 1) ^ (n >> 31); } -UPB_INLINE uint64_t upb_zzenc_64(int64_t n) { return (n << 1) ^ (n >> 63); } - -/* Decoding *******************************************************************/ - -/* All decoding functions return this struct by value. */ -typedef struct { - const char *p; /* NULL if the varint was unterminated. */ - uint64_t val; -} upb_decoderet; - -UPB_INLINE upb_decoderet upb_decoderet_make(const char *p, uint64_t val) { - upb_decoderet ret; - ret.p = p; - ret.val = val; - return ret; -} - -upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r); -upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r); - -/* Template for a function that checks the first two bytes with branching - * and dispatches 2-10 bytes with a separate function. Note that this may read - * up to 10 bytes, so it must not be used unless there are at least ten bytes - * left in the buffer! */ -#define UPB_VARINT_DECODER_CHECK2(name, decode_max8_function) \ -UPB_INLINE upb_decoderet upb_vdecode_check2_ ## name(const char *_p) { \ - uint8_t *p = (uint8_t*)_p; \ - upb_decoderet r; \ - if ((*p & 0x80) == 0) { \ - /* Common case: one-byte varint. */ \ - return upb_decoderet_make(_p + 1, *p & 0x7fU); \ - } \ - r = upb_decoderet_make(_p + 2, (*p & 0x7fU) | ((*(p + 1) & 0x7fU) << 7)); \ - if ((*(p + 1) & 0x80) == 0) { \ - /* Two-byte varint. */ \ - return r; \ - } \ - /* Longer varint, fallback to out-of-line function. */ \ - return decode_max8_function(r); \ -} - -UPB_VARINT_DECODER_CHECK2(branch32, upb_vdecode_max8_branch32) -UPB_VARINT_DECODER_CHECK2(branch64, upb_vdecode_max8_branch64) -#undef UPB_VARINT_DECODER_CHECK2 - -/* Our canonical functions for decoding varints, based on the currently - * favored best-performing implementations. */ -UPB_INLINE upb_decoderet upb_vdecode_fast(const char *p) { - if (sizeof(long) == 8) - return upb_vdecode_check2_branch64(p); - else - return upb_vdecode_check2_branch32(p); -} - - -/* Encoding *******************************************************************/ - -UPB_INLINE int upb_value_size(uint64_t val) { -#ifdef __GNUC__ - int high_bit = 63 - __builtin_clzll(val); /* 0-based, undef if val == 0. */ -#else - int high_bit = 0; - uint64_t tmp = val; - while(tmp >>= 1) high_bit++; -#endif - return val == 0 ? 1 : high_bit / 8 + 1; -} - -/* Encodes a 64-bit varint into buf (which must be >=UPB_PB_VARINT_MAX_LEN - * bytes long), returning how many bytes were used. - * - * TODO: benchmark and optimize if necessary. */ -UPB_INLINE size_t upb_vencode64(uint64_t val, char *buf) { - size_t i; - if (val == 0) { buf[0] = 0; return 1; } - i = 0; - while (val) { - uint8_t byte = val & 0x7fU; - val >>= 7; - if (val) byte |= 0x80U; - buf[i++] = byte; - } - return i; -} - -UPB_INLINE size_t upb_varint_size(uint64_t val) { - char buf[UPB_PB_VARINT_MAX_LEN]; - return upb_vencode64(val, buf); -} - -/* Encodes a 32-bit varint, *not* sign-extended. */ -UPB_INLINE uint64_t upb_vencode32(uint32_t val) { - char buf[UPB_PB_VARINT_MAX_LEN]; - size_t bytes = upb_vencode64(val, buf); - uint64_t ret = 0; - UPB_ASSERT(bytes <= 5); - memcpy(&ret, buf, bytes); - UPB_ASSERT(ret <= 0xffffffffffU); - return ret; -} - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_VARINT_DECODER_H_ */ -/* -** upb::pb::Encoder (upb_pb_encoder) -** -** Implements a set of upb_handlers that write protobuf data to the binary wire -** format. -** -** This encoder implementation does not have any access to any out-of-band or -** precomputed lengths for submessages, so it must buffer submessages internally -** before it can emit the first byte. -*/ - -#ifndef UPB_ENCODER_H_ -#define UPB_ENCODER_H_ - - -#ifdef __cplusplus -namespace upb { -namespace pb { -class Encoder; -} /* namespace pb */ -} /* namespace upb */ -#endif - -UPB_DECLARE_TYPE(upb::pb::Encoder, upb_pb_encoder) - -#define UPB_PBENCODER_MAX_NESTING 100 - -/* upb::pb::Encoder ***********************************************************/ - -/* Preallocation hint: decoder won't allocate more bytes than this when first - * constructed. This hint may be an overestimate for some build configurations. - * But if the decoder library is upgraded without recompiling the application, - * it may be an underestimate. */ -#define UPB_PB_ENCODER_SIZE 768 - -#ifdef __cplusplus - -class upb::pb::Encoder { - public: - /* Creates a new encoder in the given environment. The Handlers must have - * come from NewHandlers() below. */ - static Encoder* Create(Environment* env, const Handlers* handlers, - BytesSink* output); - - /* The input to the encoder. */ - Sink* input(); - - /* Creates a new set of handlers for this MessageDef. */ - static reffed_ptr NewHandlers(const MessageDef* msg); - - static const size_t kSize = UPB_PB_ENCODER_SIZE; - - private: - UPB_DISALLOW_POD_OPS(Encoder, upb::pb::Encoder) -}; - -#endif - -UPB_BEGIN_EXTERN_C - -const upb_handlers *upb_pb_encoder_newhandlers(const upb_msgdef *m, - const void *owner); -upb_sink *upb_pb_encoder_input(upb_pb_encoder *p); -upb_pb_encoder* upb_pb_encoder_create(upb_env* e, const upb_handlers* h, - upb_bytessink* output); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { -namespace pb { -inline Encoder* Encoder::Create(Environment* env, const Handlers* handlers, - BytesSink* output) { - return upb_pb_encoder_create(env, handlers, output); -} -inline Sink* Encoder::input() { - return upb_pb_encoder_input(this); -} -inline reffed_ptr Encoder::NewHandlers( - const upb::MessageDef *md) { - const Handlers* h = upb_pb_encoder_newhandlers(md, &h); - return reffed_ptr(h, &h); -} -} /* namespace pb */ -} /* namespace upb */ - -#endif - -#endif /* UPB_ENCODER_H_ */ -/* -** upb's core components like upb_decoder and upb_msg are carefully designed to -** avoid depending on each other for maximum orthogonality. In other words, -** you can use a upb_decoder to decode into *any* kind of structure; upb_msg is -** just one such structure. A upb_msg can be serialized/deserialized into any -** format, protobuf binary format is just one such format. -** -** However, for convenience we provide functions here for doing common -** operations like deserializing protobuf binary format into a upb_msg. The -** compromise is that this file drags in almost all of upb as a dependency, -** which could be undesirable if you're trying to use a trimmed-down build of -** upb. -** -** While these routines are convenient, they do not reuse any encoding/decoding -** state. For example, if a decoder is JIT-based, it will be re-JITted every -** time these functions are called. For this reason, if you are parsing lots -** of data and efficiency is an issue, these may not be the best functions to -** use (though they are useful for prototyping, before optimizing). -*/ - -#ifndef UPB_GLUE_H -#define UPB_GLUE_H - -#include - -#ifdef __cplusplus -#include - -extern "C" { -#endif - -/* Loads a binary descriptor and returns a NULL-terminated array of unfrozen - * filedefs. The caller owns the returned array, which must be freed with - * upb_gfree(). */ -upb_filedef **upb_loaddescriptor(const char *buf, size_t n, const void *owner, - upb_status *status); - -#ifdef __cplusplus -} /* extern "C" */ - -namespace upb { - -inline bool LoadDescriptor(const char* buf, size_t n, Status* status, - std::vector >* files) { - FileDef** parsed_files = upb_loaddescriptor(buf, n, &parsed_files, status); - - if (parsed_files) { - FileDef** p = parsed_files; - while (*p) { - files->push_back(reffed_ptr(*p, &parsed_files)); - ++p; - } - free(parsed_files); - return true; - } else { - return false; - } -} - -/* Templated so it can accept both string and std::string. */ -template -bool LoadDescriptor(const T& desc, Status* status, - std::vector >* files) { - return LoadDescriptor(desc.c_str(), desc.size(), status, files); -} - -} /* namespace upb */ - -#endif - -#endif /* UPB_GLUE_H */ -/* -** upb::pb::TextPrinter (upb_textprinter) -** -** Handlers for writing to protobuf text format. -*/ - -#ifndef UPB_TEXT_H_ -#define UPB_TEXT_H_ - - -#ifdef __cplusplus -namespace upb { -namespace pb { -class TextPrinter; -} /* namespace pb */ -} /* namespace upb */ -#endif - -UPB_DECLARE_TYPE(upb::pb::TextPrinter, upb_textprinter) - -#ifdef __cplusplus - -class upb::pb::TextPrinter { - public: - /* The given handlers must have come from NewHandlers(). It must outlive the - * TextPrinter. */ - static TextPrinter *Create(Environment *env, const upb::Handlers *handlers, - BytesSink *output); - - void SetSingleLineMode(bool single_line); - - Sink* input(); - - /* If handler caching becomes a requirement we can add a code cache as in - * decoder.h */ - static reffed_ptr NewHandlers(const MessageDef* md); -}; - -#endif - -UPB_BEGIN_EXTERN_C - -/* C API. */ -upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h, - upb_bytessink *output); -void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line); -upb_sink *upb_textprinter_input(upb_textprinter *p); - -const upb_handlers *upb_textprinter_newhandlers(const upb_msgdef *m, - const void *owner); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { -namespace pb { -inline TextPrinter *TextPrinter::Create(Environment *env, - const upb::Handlers *handlers, - BytesSink *output) { - return upb_textprinter_create(env, handlers, output); -} -inline void TextPrinter::SetSingleLineMode(bool single_line) { - upb_textprinter_setsingleline(this, single_line); -} -inline Sink* TextPrinter::input() { - return upb_textprinter_input(this); -} -inline reffed_ptr TextPrinter::NewHandlers( - const MessageDef *md) { - const Handlers* h = upb_textprinter_newhandlers(md, &h); - return reffed_ptr(h, &h); -} -} /* namespace pb */ -} /* namespace upb */ - -#endif - -#endif /* UPB_TEXT_H_ */ -/* -** upb::json::Parser (upb_json_parser) -** -** Parses JSON according to a specific schema. -** Support for parsing arbitrary JSON (schema-less) will be added later. -*/ - -#ifndef UPB_JSON_PARSER_H_ -#define UPB_JSON_PARSER_H_ - - -#ifdef __cplusplus -namespace upb { -namespace json { -class Parser; -class ParserMethod; -} /* namespace json */ -} /* namespace upb */ -#endif - -UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser) -UPB_DECLARE_DERIVED_TYPE(upb::json::ParserMethod, upb::RefCounted, - upb_json_parsermethod, upb_refcounted) - -/* upb::json::Parser **********************************************************/ - -/* Preallocation hint: parser won't allocate more bytes than this when first - * constructed. This hint may be an overestimate for some build configurations. - * But if the parser library is upgraded without recompiling the application, - * it may be an underestimate. */ -#define UPB_JSON_PARSER_SIZE 4112 - -#ifdef __cplusplus - -/* Parses an incoming BytesStream, pushing the results to the destination - * sink. */ -class upb::json::Parser { - public: - static Parser* Create(Environment* env, const ParserMethod* method, - Sink* output); - - BytesSink* input(); - - private: - UPB_DISALLOW_POD_OPS(Parser, upb::json::Parser) -}; - -class upb::json::ParserMethod { - public: - /* Include base methods from upb::ReferenceCounted. */ - UPB_REFCOUNTED_CPPMETHODS - - /* Returns handlers for parsing according to the specified schema. */ - static reffed_ptr New(const upb::MessageDef* md); - - /* The destination handlers that are statically bound to this method. - * This method is only capable of outputting to a sink that uses these - * handlers. */ - const Handlers* dest_handlers() const; - - /* The input handlers for this decoder method. */ - const BytesHandler* input_handler() const; - - private: - UPB_DISALLOW_POD_OPS(ParserMethod, upb::json::ParserMethod) -}; - -#endif - -UPB_BEGIN_EXTERN_C - -upb_json_parser* upb_json_parser_create(upb_env* e, - const upb_json_parsermethod* m, - upb_sink* output); -upb_bytessink *upb_json_parser_input(upb_json_parser *p); - -upb_json_parsermethod* upb_json_parsermethod_new(const upb_msgdef* md, - const void* owner); -const upb_handlers *upb_json_parsermethod_desthandlers( - const upb_json_parsermethod *m); -const upb_byteshandler *upb_json_parsermethod_inputhandler( - const upb_json_parsermethod *m); - -/* Include refcounted methods like upb_json_parsermethod_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_json_parsermethod, upb_json_parsermethod_upcast) - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { -namespace json { -inline Parser* Parser::Create(Environment* env, const ParserMethod* method, - Sink* output) { - return upb_json_parser_create(env, method, output); -} -inline BytesSink* Parser::input() { - return upb_json_parser_input(this); -} - -inline const Handlers* ParserMethod::dest_handlers() const { - return upb_json_parsermethod_desthandlers(this); -} -inline const BytesHandler* ParserMethod::input_handler() const { - return upb_json_parsermethod_inputhandler(this); -} -/* static */ -inline reffed_ptr ParserMethod::New( - const MessageDef* md) { - const upb_json_parsermethod *m = upb_json_parsermethod_new(md, &m); - return reffed_ptr(m, &m); -} - -} /* namespace json */ -} /* namespace upb */ - -#endif - - -#endif /* UPB_JSON_PARSER_H_ */ -/* -** upb::json::Printer -** -** Handlers that emit JSON according to a specific protobuf schema. -*/ - -#ifndef UPB_JSON_TYPED_PRINTER_H_ -#define UPB_JSON_TYPED_PRINTER_H_ - - -#ifdef __cplusplus -namespace upb { -namespace json { -class Printer; -} /* namespace json */ -} /* namespace upb */ -#endif - -UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer) - - -/* upb::json::Printer *********************************************************/ - -#define UPB_JSON_PRINTER_SIZE 176 - -#ifdef __cplusplus - -/* Prints an incoming stream of data to a BytesSink in JSON format. */ -class upb::json::Printer { - public: - static Printer* Create(Environment* env, const upb::Handlers* handlers, - BytesSink* output); - - /* The input to the printer. */ - Sink* input(); - - /* Returns handlers for printing according to the specified schema. - * If preserve_proto_fieldnames is true, the output JSON will use the - * original .proto field names (ie. {"my_field":3}) instead of using - * camelCased names, which is the default: (eg. {"myField":3}). */ - static reffed_ptr NewHandlers(const upb::MessageDef* md, - bool preserve_proto_fieldnames); - - static const size_t kSize = UPB_JSON_PRINTER_SIZE; - - private: - UPB_DISALLOW_POD_OPS(Printer, upb::json::Printer) -}; - -#endif - -UPB_BEGIN_EXTERN_C - -/* Native C API. */ -upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h, - upb_bytessink *output); -upb_sink *upb_json_printer_input(upb_json_printer *p); -const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md, - bool preserve_fieldnames, - const void *owner); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { -namespace json { -inline Printer* Printer::Create(Environment* env, const upb::Handlers* handlers, - BytesSink* output) { - return upb_json_printer_create(env, handlers, output); -} -inline Sink* Printer::input() { return upb_json_printer_input(this); } -inline reffed_ptr Printer::NewHandlers( - const upb::MessageDef *md, bool preserve_proto_fieldnames) { - const Handlers* h = upb_json_printer_newhandlers( - md, preserve_proto_fieldnames, &h); - return reffed_ptr(h, &h); -} -} /* namespace json */ -} /* namespace upb */ - -#endif - -#endif /* UPB_JSON_TYPED_PRINTER_H_ */ diff --git a/ruby/ext/google/protobuf_c/wrap_memcpy.c b/ruby/ext/google/protobuf_c/wrap_memcpy.c index 394a52f9f639c..18c036780cdd5 100644 --- a/ruby/ext/google/protobuf_c/wrap_memcpy.c +++ b/ruby/ext/google/protobuf_c/wrap_memcpy.c @@ -33,7 +33,7 @@ // On x86-64 Linux with glibc, we link against the 2.2.5 version of memcpy so // that we avoid depending on the 2.14 version of the symbol. This way, // distributions that are using pre-2.14 versions of glibc can successfully use -// the gem we distribute (https://github.com/google/protobuf/issues/2783). +// the gem we distribute (https://github.com/protocolbuffers/protobuf/issues/2783). // // This wrapper is enabled by passing the linker flags -Wl,-wrap,memcpy in // extconf.rb. diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec index 12338c04df84e..6420dfc0511f1 100644 --- a/ruby/google-protobuf.gemspec +++ b/ruby/google-protobuf.gemspec @@ -1,12 +1,14 @@ Gem::Specification.new do |s| s.name = "google-protobuf" - s.version = "3.4.0" + s.version = "3.15.0" + git_tag = "v#{s.version.to_s.sub('.rc.', '-rc')}" # Converts X.Y.Z.rc.N to vX.Y.Z-rcN, used for the git tag s.licenses = ["BSD-3-Clause"] s.summary = "Protocol Buffers" s.description = "Protocol Buffers are Google's data interchange format." s.homepage = "https://developers.google.com/protocol-buffers" s.authors = ["Protobuf Authors"] s.email = "protobuf@googlegroups.com" + s.metadata = { "source_code_uri" => "https://github.com/protocolbuffers/protobuf/tree/#{git_tag}/ruby" } s.require_paths = ["lib"] s.files = Dir.glob('lib/**/*.rb') if RUBY_PLATFORM == "java" @@ -15,12 +17,13 @@ Gem::Specification.new do |s| else s.files += Dir.glob('ext/**/*') s.extensions= ["ext/google/protobuf_c/extconf.rb"] - s.add_development_dependency "rake-compiler-dock", "~> 0.6.0" + s.add_development_dependency "rake-compiler-dock", ">= 1.1.0", "< 2.0" end s.test_files = ["tests/basic.rb", "tests/stress.rb", "tests/generated_code_test.rb"] - s.add_development_dependency "rake-compiler", "~> 0.9.5" + s.required_ruby_version = '>= 2.3' + s.add_development_dependency "rake-compiler", "~> 1.1.0" s.add_development_dependency "test-unit", '~> 3.0', '>= 3.0.9' s.add_development_dependency "rubygems-tasks", "~> 0.2.4" end diff --git a/ruby/lib/google/protobuf.rb b/ruby/lib/google/protobuf.rb index 9b8d8231e2faf..83ece4cfa17a0 100644 --- a/ruby/lib/google/protobuf.rb +++ b/ruby/lib/google/protobuf.rb @@ -37,6 +37,7 @@ module Google module Protobuf class Error < StandardError; end class ParseError < Error; end + class TypeError < ::TypeError; end end end @@ -49,6 +50,76 @@ class ParseError < Error; end rescue LoadError require 'google/protobuf_c' end + + module Google + module Protobuf + module Internal + def self.infer_package(names) + # Package is longest common prefix ending in '.', if any. + if not names.empty? + min, max = names.minmax + last_common_dot = nil + min.size.times { |i| + if min[i] != max[i] then break end + if min[i] == ?. then last_common_dot = i end + } + if last_common_dot + return min.slice(0, last_common_dot) + end + end + + nil + end + + class NestingBuilder + def initialize(msg_names, enum_names) + @to_pos = {nil=>nil} + @msg_children = Hash.new { |hash, key| hash[key] = [] } + @enum_children = Hash.new { |hash, key| hash[key] = [] } + + msg_names.each_with_index { |name, idx| @to_pos[name] = idx } + enum_names.each_with_index { |name, idx| @to_pos[name] = idx } + + msg_names.each { |name| @msg_children[parent(name)] << name } + enum_names.each { |name| @enum_children[parent(name)] << name } + end + + def build(package) + return build_msg(package) + end + + private + def build_msg(msg) + return { + :pos => @to_pos[msg], + :msgs => @msg_children[msg].map { |child| build_msg(child) }, + :enums => @enum_children[msg].map { |child| @to_pos[child] }, + } + end + + private + def parent(name) + idx = name.rindex(?.) + if idx + return name.slice(0, idx) + else + return nil + end + end + end + + def self.fixup_descriptor(package, msg_names, enum_names) + if package.nil? + package = self.infer_package(msg_names + enum_names) + end + + nesting = NestingBuilder.new(msg_names, enum_names).build(package) + + return package, nesting + end + end + end + end end require 'google/protobuf/repeated_field' @@ -60,16 +131,16 @@ def self.encode(msg) msg.to_proto end - def self.encode_json(msg) - msg.to_json + def self.encode_json(msg, options = {}) + msg.to_json(options) end def self.decode(klass, proto) klass.decode(proto) end - def self.decode_json(klass, json) - klass.decode_json(json) + def self.decode_json(klass, json, options = {}) + klass.decode_json(json, options) end end diff --git a/ruby/lib/google/protobuf/message_exts.rb b/ruby/lib/google/protobuf/message_exts.rb index e10266ba2f363..f432f89fed0c6 100644 --- a/ruby/lib/google/protobuf/message_exts.rb +++ b/ruby/lib/google/protobuf/message_exts.rb @@ -40,8 +40,8 @@ def self.included(klass) module ClassMethods end - def to_json - self.class.encode_json(self) + def to_json(options = {}) + self.class.encode_json(self, options) end def to_proto diff --git a/ruby/lib/google/protobuf/repeated_field.rb b/ruby/lib/google/protobuf/repeated_field.rb index 11d6c2eb8cba3..bc9699fdfd3b5 100644 --- a/ruby/lib/google/protobuf/repeated_field.rb +++ b/ruby/lib/google/protobuf/repeated_field.rb @@ -79,7 +79,7 @@ class RepeatedField def first(n=nil) - n ? self[0..n] : self[0] + n ? self[0...n] : self[0] end @@ -150,12 +150,12 @@ def define_array_wrapper_with_result_method(method_name) end - %w(delete delete_at delete_if shift slice! unshift).each do |method_name| + %w(delete delete_at shift slice! unshift).each do |method_name| define_array_wrapper_method(method_name) end - %w(collect! compact! fill flatten! insert reverse! + %w(collect! compact! delete_if fill flatten! insert reverse! rotate! select! shuffle! sort! sort_by! uniq!).each do |method_name| define_array_wrapper_with_result_method(method_name) end diff --git a/ruby/lib/google/protobuf/well_known_types.rb b/ruby/lib/google/protobuf/well_known_types.rb old mode 100644 new mode 100755 index 921ddbc06fbe3..37f8d5b675cd6 --- a/ruby/lib/google/protobuf/well_known_types.rb +++ b/ruby/lib/google/protobuf/well_known_types.rb @@ -39,6 +39,12 @@ module Google module Protobuf Any.class_eval do + def self.pack(msg, type_url_prefix='type.googleapis.com/') + any = self.new + any.pack(msg, type_url_prefix) + any + end + def pack(msg, type_url_prefix='type.googleapis.com/') if type_url_prefix.empty? or type_url_prefix[-1] != '/' then self.type_url = "#{type_url_prefix}/#{msg.class.descriptor.name}" @@ -66,8 +72,14 @@ def is(klass) end Timestamp.class_eval do - def to_time - Time.at(self.to_f) + if RUBY_VERSION < "2.5" + def to_time + Time.at(self.to_f) + end + else + def to_time + Time.at(seconds, nanos, :nanosecond) + end end def from_time(time) @@ -149,6 +161,8 @@ def from_ruby(value) Struct.class_eval do def [](key) self.fields[key].to_ruby + rescue NoMethodError + nil end def []=(key, value) @@ -170,6 +184,10 @@ def self.from_hash(hash) hash.each { |key, val| ret[key] = val } ret end + + def has_key?(key) + self.fields.has_key?(key) + end end ListValue.class_eval do diff --git a/ruby/pom.xml b/ruby/pom.xml index adf6ff207da9d..6c96bf42a3188 100644 --- a/ruby/pom.xml +++ b/ruby/pom.xml @@ -27,9 +27,9 @@ - https://github.com/google/protobuf + https://github.com/protocolbuffers/protobuf - scm:git:https://github.com/google/protobuf.git + scm:git:https://github.com/protocolbuffers/protobuf.git @@ -43,6 +43,7 @@ org.apache.maven.plugins maven-assembly-plugin + 3.3.0 ${jar.finalName} ${ruby.sources} @@ -64,9 +65,10 @@ org.apache.maven.plugins maven-compiler-plugin + 3.8.1 - 1.6 - 1.6 + 1.8 + 1.8 @@ -80,13 +82,13 @@ org.jruby jruby-complete - 1.7.13 + 9.2.11.1 provided com.google.protobuf - protobuf-java - 3.0.0 + protobuf-java-util + 3.13.0 diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java index 5addae58dad7f..b19ea6473e888 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java @@ -41,8 +41,8 @@ @JRubyClass(name = "Builder") public class RubyBuilder extends RubyObject { public static void createRubyBuilder(Ruby runtime) { - RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf"); - RubyClass cBuilder = protobuf.defineClassUnder("Builder", runtime.getObject(), new ObjectAllocator() { + RubyModule internal = runtime.getClassFromPath("Google::Protobuf::Internal"); + RubyClass cBuilder = internal.defineClassUnder("Builder", runtime.getObject(), new ObjectAllocator() { @Override public IRubyObject allocate(Ruby runtime, RubyClass klazz) { return new RubyBuilder(runtime, klazz); @@ -53,10 +53,7 @@ public IRubyObject allocate(Ruby runtime, RubyClass klazz) { public RubyBuilder(Ruby runtime, RubyClass metaClass) { super(runtime, metaClass); - this.cDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Descriptor"); - this.cEnumDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumDescriptor"); - this.cMessageBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::MessageBuilderContext"); - this.cEnumBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumBuilderContext"); + this.cFileBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Internal::FileBuilderContext"); } /* @@ -68,9 +65,8 @@ public RubyBuilder(Ruby runtime, RubyClass metaClass) { * (co)recursive type references. */ @JRubyMethod - public IRubyObject initialize(ThreadContext context) { - Ruby runtime = context.runtime; - this.pendingList = runtime.newArray(); + public IRubyObject initialize(ThreadContext context, IRubyObject descriptorPool) { + this.descriptorPool = (RubyDescriptorPool) descriptorPool; return this; } @@ -78,90 +74,74 @@ public IRubyObject initialize(ThreadContext context) { * call-seq: * Builder.add_message(name, &block) * - * Creates a new, empty descriptor with the given name, and invokes the block in - * the context of a MessageBuilderContext on that descriptor. The block can then - * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated - * methods to define the message fields. + * Old and deprecated way to create a new descriptor. + * See FileBuilderContext.add_message for the recommended way. * - * This is the recommended, idiomatic way to build message definitions. + * Exists for backwards compatibility to allow building descriptor pool for + * files generated by protoc which don't add messages within "add_file" block. + * Descriptors created this way get assigned to a default empty FileDescriptor. */ @JRubyMethod(name = "add_message") public IRubyObject addMessage(ThreadContext context, IRubyObject name, Block block) { - RubyDescriptor msgdef = (RubyDescriptor) cDescriptor.newInstance(context, Block.NULL_BLOCK); - IRubyObject ctx = cMessageBuilderContext.newInstance(context, msgdef, this, Block.NULL_BLOCK); - msgdef.setName(context, name); - if (block.isGiven()) { - if (block.arity() == Arity.ONE_ARGUMENT) { - block.yield(context, ctx); - } else { - Binding binding = block.getBinding(); - binding.setSelf(ctx); - block.yieldSpecific(context); - } - } - this.pendingList.add(msgdef); - return context.runtime.getNil(); + ensureDefaultFileBuilder(context); + defaultFileBuilder.addMessage(context, name, block); + return context.nil; } /* * call-seq: * Builder.add_enum(name, &block) * - * Creates a new, empty enum descriptor with the given name, and invokes the block in - * the context of an EnumBuilderContext on that descriptor. The block can then - * call EnumBuilderContext#add_value to define the enum values. + * Old and deprecated way to create a new enum descriptor. + * See FileBuilderContext.add_enum for the recommended way. * - * This is the recommended, idiomatic way to build enum definitions. + * Exists for backwards compatibility to allow building descriptor pool for + * files generated by protoc which don't add enums within "add_file" block. + * Enum descriptors created this way get assigned to a default empty + * FileDescriptor. */ @JRubyMethod(name = "add_enum") public IRubyObject addEnum(ThreadContext context, IRubyObject name, Block block) { - RubyEnumDescriptor enumDef = (RubyEnumDescriptor) cEnumDescriptor.newInstance(context, Block.NULL_BLOCK); - IRubyObject ctx = cEnumBuilderContext.newInstance(context, enumDef, Block.NULL_BLOCK); - enumDef.setName(context, name); - - if (block.isGiven()) { - if (block.arity() == Arity.ONE_ARGUMENT) { - block.yield(context, ctx); - } else { - Binding binding = block.getBinding(); - binding.setSelf(ctx); - block.yieldSpecific(context); - } - } - - this.pendingList.add(enumDef); - return context.runtime.getNil(); + ensureDefaultFileBuilder(context); + defaultFileBuilder.addEnum(context, name, block); + return context.nil; } /* * call-seq: - * Builder.finalize_to_pool(pool) + * Builder.add_file(name, options = nil, &block) * - * Adds all accumulated message and enum descriptors created in this builder - * context to the given pool. The operation occurs atomically, and all - * descriptors can refer to each other (including in cycles). This is the only - * way to build (co)recursive message definitions. + * Creates a new, file descriptor with the given name and options and invokes + * the block in the context of a FileBuilderContext on that descriptor. The + * block can then call FileBuilderContext#add_message or + * FileBuilderContext#add_enum to define new messages or enums, respectively. * - * This method is usually called automatically by DescriptorPool#build after it - * invokes the given user block in the context of the builder. The user should - * not normally need to call this manually because a Builder is not normally - * created manually. + * This is the recommended, idiomatic way to build file descriptors. */ - @JRubyMethod(name = "finalize_to_pool") - public IRubyObject finalizeToPool(ThreadContext context, IRubyObject rbPool) { - RubyDescriptorPool pool = (RubyDescriptorPool) rbPool; - for (int i = 0; i < this.pendingList.size(); i++) { - IRubyObject defRb = this.pendingList.entry(i); - if (defRb instanceof RubyDescriptor) { - pool.addToSymtab(context, (RubyDescriptor) defRb); - } else { - pool.addToSymtab(context, (RubyEnumDescriptor) defRb); - } + @JRubyMethod(name = "add_file") + public IRubyObject addFile(ThreadContext context, IRubyObject name, IRubyObject options, Block block) { + RubyFileBuilderContext ctx = (RubyFileBuilderContext) cFileBuilderContext.newInstance(context, descriptorPool, name, options, Block.NULL_BLOCK); + ctx.instance_eval(context, block); + ctx.build(context); + return context.nil; + } + + /* + * Used to trigger the build when using the deprecated syntax + */ + protected void build(ThreadContext context) { + if (defaultFileBuilder != null) { + defaultFileBuilder.build(context); + } + } + + private void ensureDefaultFileBuilder(ThreadContext context) { + if (defaultFileBuilder == null) { + this.defaultFileBuilder = (RubyFileBuilderContext) cFileBuilderContext.newInstance(context, descriptorPool, context.runtime.newString("ruby_default_file.proto"), Block.NULL_BLOCK); } - this.pendingList = context.runtime.newArray(); - return context.runtime.getNil(); } - protected RubyArray pendingList; - private RubyClass cDescriptor, cEnumDescriptor, cMessageBuilderContext, cEnumBuilderContext; + private RubyClass cFileBuilderContext; + private RubyDescriptorPool descriptorPool; + private RubyFileBuilderContext defaultFileBuilder; } diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java index dd9179b0300c9..a59596a5b6b45 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java @@ -32,12 +32,14 @@ package com.google.protobuf.jruby; -import com.google.protobuf.DescriptorProtos; -import com.google.protobuf.Descriptors; +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Descriptors.OneofDescriptor; import org.jruby.*; import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyMethod; import org.jruby.runtime.Block; +import org.jruby.runtime.Helpers; import org.jruby.runtime.ObjectAllocator; import org.jruby.runtime.ThreadContext; import org.jruby.runtime.builtin.IRubyObject; @@ -58,70 +60,24 @@ public IRubyObject allocate(Ruby runtime, RubyClass klazz) { }); cDescriptor.includeModule(runtime.getEnumerable()); cDescriptor.defineAnnotatedMethods(RubyDescriptor.class); + cFieldDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::FieldDescriptor"); + cOneofDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::OneofDescriptor"); } public RubyDescriptor(Ruby runtime, RubyClass klazz) { super(runtime, klazz); } - /* - * call-seq: - * Descriptor.new => descriptor - * - * Creates a new, empty, message type descriptor. At a minimum, its name must be - * set before it is added to a pool. It cannot be used to create messages until - * it is added to a pool, after which it becomes immutable (as part of a - * finalization process). - */ - @JRubyMethod - public IRubyObject initialize(ThreadContext context) { - this.builder = DescriptorProtos.DescriptorProto.newBuilder(); - this.fieldDefMap = new HashMap(); - this.oneofDefs = new HashMap(); - return this; - } - /* * call-seq: * Descriptor.name => name * - * Returns the name of this message type as a fully-qualfied string (e.g., + * Returns the name of this message type as a fully-qualified string (e.g., * My.Package.MessageType). */ @JRubyMethod(name = "name") public IRubyObject getName(ThreadContext context) { - return this.name; - } - - /* - * call-seq: - * Descriptor.name = name - * - * Assigns a name to this message type. The descriptor must not have been added - * to a pool yet. - */ - @JRubyMethod(name = "name=") - public IRubyObject setName(ThreadContext context, IRubyObject name) { - this.name = name; - this.builder.setName(Utils.escapeIdentifier(this.name.asJavaString())); - return context.runtime.getNil(); - } - - /* - * call-seq: - * Descriptor.add_field(field) => nil - * - * Adds the given FieldDescriptor to this message type. The descriptor must not - * have been added to a pool yet. Raises an exception if a field with the same - * name or number already exists. Sub-type references (e.g. for fields of type - * message) are not resolved at this point. - */ - @JRubyMethod(name = "add_field") - public IRubyObject addField(ThreadContext context, IRubyObject obj) { - RubyFieldDescriptor fieldDef = (RubyFieldDescriptor) obj; - this.fieldDefMap.put(fieldDef.getName(context).asJavaString(), fieldDef); - this.builder.addField(fieldDef.build()); - return context.runtime.getNil(); + return name; } /* @@ -133,7 +89,7 @@ public IRubyObject addField(ThreadContext context, IRubyObject obj) { */ @JRubyMethod public IRubyObject lookup(ThreadContext context, IRubyObject fieldName) { - return this.fieldDefMap.get(fieldName.asJavaString()); + return Helpers.nullToNil(fieldDescriptors.get(fieldName), context.nil); } /* @@ -145,10 +101,7 @@ public IRubyObject lookup(ThreadContext context, IRubyObject fieldName) { */ @JRubyMethod public IRubyObject msgclass(ThreadContext context) { - if (this.klazz == null) { - this.klazz = buildClassFromDescriptor(context); - } - return this.klazz; + return klazz; } /* @@ -159,33 +112,22 @@ public IRubyObject msgclass(ThreadContext context) { */ @JRubyMethod public IRubyObject each(ThreadContext context, Block block) { - for (Map.Entry entry : fieldDefMap.entrySet()) { + for (Map.Entry entry : fieldDescriptors.entrySet()) { block.yield(context, entry.getValue()); } - return context.runtime.getNil(); + return context.nil; } /* * call-seq: - * Descriptor.add_oneof(oneof) => nil + * Descriptor.file_descriptor * - * Adds the given OneofDescriptor to this message type. This descriptor must not - * have been added to a pool yet. Raises an exception if a oneof with the same - * name already exists, or if any of the oneof's fields' names or numbers - * conflict with an existing field in this message type. All fields in the oneof - * are added to the message descriptor. Sub-type references (e.g. for fields of - * type message) are not resolved at this point. + * Returns the FileDescriptor object this message belongs to. */ - @JRubyMethod(name = "add_oneof") - public IRubyObject addOneof(ThreadContext context, IRubyObject obj) { - RubyOneofDescriptor def = (RubyOneofDescriptor) obj; - builder.addOneofDecl(def.build(builder.getOneofDeclCount())); - for (RubyFieldDescriptor fieldDescriptor : def.getFields()) { - addField(context, fieldDescriptor); - } - oneofDefs.put(def.getName(context), def); - return context.runtime.getNil(); - } + @JRubyMethod(name = "file_descriptor") + public IRubyObject getFileDescriptor(ThreadContext context) { + return RubyFileDescriptor.getRubyFileDescriptor(context, descriptor); + } /* * call-seq: @@ -196,10 +138,10 @@ public IRubyObject addOneof(ThreadContext context, IRubyObject obj) { */ @JRubyMethod(name = "each_oneof") public IRubyObject eachOneof(ThreadContext context, Block block) { - for (RubyOneofDescriptor oneofDescriptor : oneofDefs.values()) { + for (RubyOneofDescriptor oneofDescriptor : oneofDescriptors.values()) { block.yieldSpecific(context, oneofDescriptor); } - return context.runtime.getNil(); + return context.nil; } /* @@ -211,29 +153,44 @@ public IRubyObject eachOneof(ThreadContext context, Block block) { */ @JRubyMethod(name = "lookup_oneof") public IRubyObject lookupOneof(ThreadContext context, IRubyObject name) { - if (name instanceof RubySymbol) { - name = ((RubySymbol) name).id2name(); - } - return oneofDefs.containsKey(name) ? oneofDefs.get(name) : context.runtime.getNil(); + return Helpers.nullToNil(oneofDescriptors.get(Utils.symToString(name)), context.nil); } - public void setDescriptor(Descriptors.Descriptor descriptor) { - this.descriptor = descriptor; + protected FieldDescriptor getField(String name) { + return descriptor.findFieldByName(name); } - public Descriptors.Descriptor getDescriptor() { - return this.descriptor; - } + protected void setDescriptor(ThreadContext context, Descriptor descriptor, RubyDescriptorPool pool) { + Ruby runtime = context.runtime; + Map cache = new HashMap(); + this.descriptor = descriptor; + + // Populate the field caches + fieldDescriptors = new HashMap(); + oneofDescriptors = new HashMap(); - public DescriptorProtos.DescriptorProto.Builder getBuilder() { - return builder; + for (FieldDescriptor fieldDescriptor : descriptor.getFields()) { + RubyFieldDescriptor fd = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK); + fd.setDescriptor(context, fieldDescriptor, pool); + fieldDescriptors.put(runtime.newString(fieldDescriptor.getName()), fd); + cache.put(fieldDescriptor, fd); + } + + for (OneofDescriptor oneofDescriptor : descriptor.getRealOneofs()) { + RubyOneofDescriptor ood = (RubyOneofDescriptor) cOneofDescriptor.newInstance(context, Block.NULL_BLOCK); + ood.setDescriptor(context, oneofDescriptor, cache); + oneofDescriptors.put(runtime.newString(oneofDescriptor.getName()), ood); + } + + // Make sure our class is built + this.klazz = buildClassFromDescriptor(context); } - public void setMapEntry(boolean isMapEntry) { - this.builder.setOptions(DescriptorProtos.MessageOptions.newBuilder().setMapEntry(isMapEntry)); + protected void setName(IRubyObject name) { + this.name = name; } - private RubyModule buildClassFromDescriptor(ThreadContext context) { + private RubyClass buildClassFromDescriptor(ThreadContext context) { Ruby runtime = context.runtime; ObjectAllocator allocator = new ObjectAllocator() { @@ -255,15 +212,12 @@ public IRubyObject allocate(Ruby runtime, RubyClass klazz) { return klass; } - protected RubyFieldDescriptor lookup(String fieldName) { - return fieldDefMap.get(Utils.unescapeIdentifier(fieldName)); - } + private static RubyClass cFieldDescriptor; + private static RubyClass cOneofDescriptor; + private Descriptor descriptor; private IRubyObject name; - private RubyModule klazz; - - private DescriptorProtos.DescriptorProto.Builder builder; - private Descriptors.Descriptor descriptor; - private Map fieldDefMap; - private Map oneofDefs; + private Map fieldDescriptors; + private Map oneofDescriptors; + private RubyClass klazz; } 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 0345cb991b1a1..99a7f02d1d702 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java @@ -32,15 +32,20 @@ package com.google.protobuf.jruby; -import com.google.protobuf.DescriptorProtos; -import com.google.protobuf.Descriptors; +import com.google.protobuf.DescriptorProtos.FileDescriptorProto; +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.DescriptorValidationException; +import com.google.protobuf.Descriptors.EnumDescriptor; +import com.google.protobuf.Descriptors.FileDescriptor; import org.jruby.*; import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyMethod; import org.jruby.runtime.*; import org.jruby.runtime.builtin.IRubyObject; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; @JRubyClass(name = "DescriptorPool") @@ -56,42 +61,38 @@ public IRubyObject allocate(Ruby runtime, RubyClass klazz) { cDescriptorPool.defineAnnotatedMethods(RubyDescriptorPool.class); descriptorPool = (RubyDescriptorPool) cDescriptorPool.newInstance(runtime.getCurrentContext(), Block.NULL_BLOCK); + cBuilder = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Internal::Builder"); + cDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Descriptor"); + cEnumDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumDescriptor"); } - public RubyDescriptorPool(Ruby ruby, RubyClass klazz) { - super(ruby, klazz); - } - - @JRubyMethod - public IRubyObject initialize(ThreadContext context) { + public RubyDescriptorPool(Ruby runtime, RubyClass klazz) { + super(runtime, klazz); + this.fileDescriptors = new ArrayList<>(); this.symtab = new HashMap(); - this.cBuilder = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::Builder"); - this.builder = DescriptorProtos.FileDescriptorProto.newBuilder(); - return this; } @JRubyMethod public IRubyObject build(ThreadContext context, Block block) { - RubyBuilder ctx = (RubyBuilder) cBuilder.newInstance(context, Block.NULL_BLOCK); - if (block.arity() == Arity.ONE_ARGUMENT) { - block.yield(context, ctx); - } else { - Binding binding = block.getBinding(); - binding.setSelf(ctx); - block.yieldSpecific(context); - } - ctx.finalizeToPool(context, this); - buildFileDescriptor(context); - return context.runtime.getNil(); + RubyBuilder ctx = (RubyBuilder) cBuilder.newInstance(context, this, Block.NULL_BLOCK); + ctx.instance_eval(context, block); + ctx.build(context); // Needs to be called to support the deprecated syntax + return context.nil; } + /* + * call-seq: + * DescriptorPool.lookup(name) => descriptor + * + * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none + * exists with the given name. + * + * This currently lazy loads the ruby descriptor objects as they are requested. + * This allows us to leave the heavy lifting to the java library + */ @JRubyMethod public IRubyObject lookup(ThreadContext context, IRubyObject name) { - IRubyObject descriptor = this.symtab.get(name); - if (descriptor == null) { - return context.runtime.getNil(); - } - return descriptor; + return Helpers.nullToNil(symtab.get(name), context.nil); } /* @@ -108,62 +109,59 @@ public static IRubyObject generatedPool(ThreadContext context, IRubyObject recv) return descriptorPool; } - protected void addToSymtab(ThreadContext context, RubyDescriptor def) { - symtab.put(def.getName(context), def); - this.builder.addMessageType(def.getBuilder()); + protected void registerFileDescriptor(ThreadContext context, FileDescriptorProto.Builder builder) { + final FileDescriptor fd; + try { + fd = FileDescriptor.buildFrom(builder.build(), existingFileDescriptors()); + } catch (DescriptorValidationException e) { + throw context.runtime.newRuntimeError(e.getMessage()); + } + + String packageName = fd.getPackage(); + if (!packageName.isEmpty()) { + packageName = packageName + "."; + } + + // Need to make sure enums are registered first in case anything references them + for (EnumDescriptor ed : fd.getEnumTypes()) registerEnumDescriptor(context, ed, packageName); + for (Descriptor message : fd.getMessageTypes()) registerDescriptor(context, message, packageName); + + // Mark this as a loaded file + fileDescriptors.add(fd); + } + + private void registerDescriptor(ThreadContext context, Descriptor descriptor, String parentPath) { + String fullName = parentPath + descriptor.getName(); + String fullPath = fullName + "."; + RubyString name = context.runtime.newString(fullName); + + RubyDescriptor des = (RubyDescriptor) cDescriptor.newInstance(context, Block.NULL_BLOCK); + des.setName(name); + des.setDescriptor(context, descriptor, this); + symtab.put(name, des); + + // Need to make sure enums are registered first in case anything references them + for (EnumDescriptor ed : descriptor.getEnumTypes()) registerEnumDescriptor(context, ed, fullPath); + for (Descriptor message : descriptor.getNestedTypes()) registerDescriptor(context, message, fullPath); } - protected void addToSymtab(ThreadContext context, RubyEnumDescriptor def) { - symtab.put(def.getName(context), def); - this.builder.addEnumType(def.getBuilder()); + private void registerEnumDescriptor(ThreadContext context, EnumDescriptor descriptor, String parentPath) { + RubyString name = context.runtime.newString(parentPath + descriptor.getName()); + RubyEnumDescriptor des = (RubyEnumDescriptor) cEnumDescriptor.newInstance(context, Block.NULL_BLOCK); + des.setName(name); + des.setDescriptor(context, descriptor); + symtab.put(name, des); } - private void buildFileDescriptor(ThreadContext context) { - Ruby runtime = context.runtime; - try { - this.builder.setSyntax("proto3"); - final Descriptors.FileDescriptor fileDescriptor = Descriptors.FileDescriptor.buildFrom( - this.builder.build(), new Descriptors.FileDescriptor[]{}); - - for (Descriptors.EnumDescriptor enumDescriptor : fileDescriptor.getEnumTypes()) { - String enumName = Utils.unescapeIdentifier(enumDescriptor.getName()); - if (enumDescriptor.findValueByNumber(0) == null) { - throw runtime.newTypeError("Enum definition " + enumName - + " does not contain a value for '0'"); - } - ((RubyEnumDescriptor) symtab.get(runtime.newString(enumName))) - .setDescriptor(enumDescriptor); - } - for (Descriptors.Descriptor descriptor : fileDescriptor.getMessageTypes()) { - RubyDescriptor rubyDescriptor = ((RubyDescriptor) - symtab.get(runtime.newString(Utils.unescapeIdentifier(descriptor.getName())))); - for (Descriptors.FieldDescriptor fieldDescriptor : descriptor.getFields()) { - if (fieldDescriptor.isRequired()) { - throw runtime.newTypeError("Required fields are unsupported in proto3"); - } - RubyFieldDescriptor rubyFieldDescriptor = rubyDescriptor.lookup(fieldDescriptor.getName()); - rubyFieldDescriptor.setFieldDef(fieldDescriptor); - if (fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.MESSAGE) { - RubyDescriptor subType = (RubyDescriptor) lookup(context, - runtime.newString(Utils.unescapeIdentifier(fieldDescriptor.getMessageType().getName()))); - rubyFieldDescriptor.setSubType(subType); - } - if (fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.ENUM) { - RubyEnumDescriptor subType = (RubyEnumDescriptor) lookup(context, - runtime.newString(Utils.unescapeIdentifier(fieldDescriptor.getEnumType().getName()))); - rubyFieldDescriptor.setSubType(subType); - } - } - rubyDescriptor.setDescriptor(descriptor); - } - } catch (Descriptors.DescriptorValidationException e) { - throw runtime.newRuntimeError(e.getMessage()); - } + private FileDescriptor[] existingFileDescriptors() { + return fileDescriptors.toArray(new FileDescriptor[fileDescriptors.size()]); } + private static RubyClass cBuilder; + private static RubyClass cDescriptor; + private static RubyClass cEnumDescriptor; private static RubyDescriptorPool descriptorPool; - private RubyClass cBuilder; + private List fileDescriptors; private Map symtab; - private DescriptorProtos.FileDescriptorProto.Builder builder; } diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java index 929d869990153..17525dfe44956 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java @@ -32,9 +32,7 @@ package com.google.protobuf.jruby; -import com.google.protobuf.Descriptors; import org.jruby.RubyModule; -import org.jruby.RubyNumeric; import org.jruby.anno.JRubyMethod; import org.jruby.runtime.ThreadContext; import org.jruby.runtime.builtin.IRubyObject; @@ -49,11 +47,8 @@ public class RubyEnum { */ @JRubyMethod(meta = true) public static IRubyObject lookup(ThreadContext context, IRubyObject recv, IRubyObject number) { - RubyEnumDescriptor rubyEnumDescriptorescriptor = (RubyEnumDescriptor) getDescriptor(context, recv); - Descriptors.EnumDescriptor descriptor = rubyEnumDescriptorescriptor.getDescriptor(); - Descriptors.EnumValueDescriptor value = descriptor.findValueByNumber(RubyNumeric.num2int(number)); - if (value == null) return context.runtime.getNil(); - return context.runtime.newSymbol(value.getName()); + RubyEnumDescriptor rubyEnumDescriptor = (RubyEnumDescriptor) getDescriptor(context, recv); + return rubyEnumDescriptor.numberToName(context, number); } /* @@ -65,11 +60,8 @@ public static IRubyObject lookup(ThreadContext context, IRubyObject recv, IRubyO */ @JRubyMethod(meta = true) public static IRubyObject resolve(ThreadContext context, IRubyObject recv, IRubyObject name) { - RubyEnumDescriptor rubyEnumDescriptorescriptor = (RubyEnumDescriptor) getDescriptor(context, recv); - Descriptors.EnumDescriptor descriptor = rubyEnumDescriptorescriptor.getDescriptor(); - Descriptors.EnumValueDescriptor value = descriptor.findValueByName(name.asJavaString()); - if (value == null) return context.runtime.getNil(); - return context.runtime.newFixnum(value.getNumber()); + RubyEnumDescriptor rubyEnumDescriptor = (RubyEnumDescriptor) getDescriptor(context, recv); + return rubyEnumDescriptor.nameToNumber(context, name); } /* diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java index e4cac345812b0..38d31ad7fe82a 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java @@ -32,9 +32,11 @@ package com.google.protobuf.jruby; +import com.google.protobuf.DescriptorProtos.EnumDescriptorProto; import org.jruby.Ruby; import org.jruby.RubyClass; import org.jruby.RubyModule; +import org.jruby.RubyNumeric; import org.jruby.RubyObject; import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyMethod; @@ -45,14 +47,14 @@ @JRubyClass(name = "EnumBuilderContext") public class RubyEnumBuilderContext extends RubyObject { public static void createRubyEnumBuilderContext(Ruby runtime) { - RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf"); - RubyClass cMessageBuilderContext = protobuf.defineClassUnder("EnumBuilderContext", runtime.getObject(), new ObjectAllocator() { + RubyModule internal = runtime.getClassFromPath("Google::Protobuf::Internal"); + RubyClass cEnumBuilderContext = internal.defineClassUnder("EnumBuilderContext", runtime.getObject(), new ObjectAllocator() { @Override public IRubyObject allocate(Ruby runtime, RubyClass klazz) { return new RubyEnumBuilderContext(runtime, klazz); } }); - cMessageBuilderContext.defineAnnotatedMethods(RubyEnumBuilderContext.class); + cEnumBuilderContext.defineAnnotatedMethods(RubyEnumBuilderContext.class); } public RubyEnumBuilderContext(Ruby ruby, RubyClass klazz) { @@ -60,8 +62,12 @@ public RubyEnumBuilderContext(Ruby ruby, RubyClass klazz) { } @JRubyMethod - public IRubyObject initialize(ThreadContext context, IRubyObject enumDescriptor) { - this.enumDescriptor = (RubyEnumDescriptor) enumDescriptor; + public IRubyObject initialize(ThreadContext context, IRubyObject fileBuilderContext, IRubyObject name) { + this.fileBuilderContext = (RubyFileBuilderContext) fileBuilderContext; + this.builder = this.fileBuilderContext.getNewEnumBuilder(); + this.builder.setName(name.asJavaString()); + this.builder.getOptionsBuilder().setAllowAlias(true); + return this; } @@ -74,9 +80,12 @@ public IRubyObject initialize(ThreadContext context, IRubyObject enumDescriptor) */ @JRubyMethod public IRubyObject value(ThreadContext context, IRubyObject name, IRubyObject number) { - this.enumDescriptor.addValue(context, name, number); - return context.runtime.getNil(); + this.builder.addValueBuilder() + .setName(name.asJavaString()) + .setNumber(RubyNumeric.num2int(number)); + return context.nil; } - private RubyEnumDescriptor enumDescriptor; + private EnumDescriptorProto.Builder builder; + private RubyFileBuilderContext fileBuilderContext; } diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java index 4df832d0cfc95..e9c1f10abe05d 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java @@ -32,8 +32,9 @@ package com.google.protobuf.jruby; -import com.google.protobuf.DescriptorProtos; -import com.google.protobuf.Descriptors; +import com.google.protobuf.DescriptorProtos.EnumDescriptorProto; +import com.google.protobuf.Descriptors.EnumDescriptor; +import com.google.protobuf.Descriptors.EnumValueDescriptor; import org.jruby.Ruby; import org.jruby.RubyClass; import org.jruby.RubyModule; @@ -64,20 +65,6 @@ public RubyEnumDescriptor(Ruby runtime, RubyClass klazz) { super(runtime, klazz); } - /* - * call-seq: - * EnumDescriptor.new => enum_descriptor - * - * Creates a new, empty, enum descriptor. Must be added to a pool before the - * enum type can be used. The enum type may only be modified prior to adding to - * a pool. - */ - @JRubyMethod - public IRubyObject initialize(ThreadContext context) { - this.builder = DescriptorProtos.EnumDescriptorProto.newBuilder(); - return this; - } - /* * call-seq: * EnumDescriptor.name => name @@ -89,37 +76,6 @@ public IRubyObject getName(ThreadContext context) { return this.name; } - /* - * call-seq: - * EnumDescriptor.name = name - * - * Sets the name of this enum type. Cannot be called if the enum type has - * already been added to a pool. - */ - @JRubyMethod(name = "name=") - public IRubyObject setName(ThreadContext context, IRubyObject name) { - this.name = name; - this.builder.setName(Utils.escapeIdentifier(name.asJavaString())); - return context.runtime.getNil(); - } - - /* - * call-seq: - * EnumDescriptor.add_value(key, value) - * - * Adds a new key => value mapping to this enum type. Key must be given as a - * Ruby symbol. Cannot be called if the enum type has already been added to a - * pool. Will raise an exception if the key or value is already in use. - */ - @JRubyMethod(name = "add_value") - public IRubyObject addValue(ThreadContext context, IRubyObject name, IRubyObject number) { - DescriptorProtos.EnumValueDescriptorProto.Builder valueBuilder = DescriptorProtos.EnumValueDescriptorProto.newBuilder(); - valueBuilder.setName(name.asJavaString()); - valueBuilder.setNumber(RubyNumeric.num2int(number)); - this.builder.addValue(valueBuilder); - return context.runtime.getNil(); - } - /* * call-seq: * EnumDescriptor.each(&block) @@ -130,11 +86,11 @@ public IRubyObject addValue(ThreadContext context, IRubyObject name, IRubyObject @JRubyMethod public IRubyObject each(ThreadContext context, Block block) { Ruby runtime = context.runtime; - for (Descriptors.EnumValueDescriptor enumValueDescriptor : descriptor.getValues()) { + for (EnumValueDescriptor enumValueDescriptor : descriptor.getValues()) { block.yield(context, runtime.newArray(runtime.newSymbol(enumValueDescriptor.getName()), runtime.newFixnum(enumValueDescriptor.getNumber()))); } - return runtime.getNil(); + return context.nil; } /* @@ -146,31 +102,63 @@ public IRubyObject each(ThreadContext context, Block block) { */ @JRubyMethod public IRubyObject enummodule(ThreadContext context) { - if (this.klazz == null) { - this.klazz = buildModuleFromDescriptor(context); + return module; + } + + /* + * call-seq: + * EnumDescriptor.file_descriptor + * + * Returns the FileDescriptor object this enum belongs to. + */ + @JRubyMethod(name = "file_descriptor") + public IRubyObject getFileDescriptor(ThreadContext context) { + return RubyFileDescriptor.getRubyFileDescriptor(context, descriptor); + } + + public boolean isValidValue(ThreadContext context, IRubyObject value) { + EnumValueDescriptor enumValue; + + if (Utils.isRubyNum(value)) { + enumValue = descriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value)); + } else { + enumValue = descriptor.findValueByName(value.asJavaString()); } - return this.klazz; + + return enumValue != null; } - public void setDescriptor(Descriptors.EnumDescriptor descriptor) { - this.descriptor = descriptor; + protected IRubyObject nameToNumber(ThreadContext context, IRubyObject name) { + EnumValueDescriptor value = descriptor.findValueByName(name.asJavaString()); + return value == null ? context.nil : context.runtime.newFixnum(value.getNumber()); } - public Descriptors.EnumDescriptor getDescriptor() { - return this.descriptor; + protected IRubyObject numberToName(ThreadContext context, IRubyObject number) { + EnumValueDescriptor value = descriptor.findValueByNumber(RubyNumeric.num2int(number)); + return value == null ? context.nil : context.runtime.newSymbol(value.getName()); } - public DescriptorProtos.EnumDescriptorProto.Builder getBuilder() { - return this.builder; + protected void setDescriptor(ThreadContext context, EnumDescriptor descriptor) { + this.descriptor = descriptor; + this.module = buildModuleFromDescriptor(context); + } + + protected void setName(IRubyObject name) { + this.name = name; } private RubyModule buildModuleFromDescriptor(ThreadContext context) { Ruby runtime = context.runtime; - Utils.checkNameAvailability(context, name.asJavaString()); RubyModule enumModule = RubyModule.newModule(runtime); - for (Descriptors.EnumValueDescriptor value : descriptor.getValues()) { - enumModule.defineConstant(value.getName(), runtime.newFixnum(value.getNumber())); + for (EnumValueDescriptor value : descriptor.getValues()) { + String name = value.getName(); + // Make sure its a valid constant name before trying to create it + if (Character.isUpperCase(name.codePointAt(0))) { + enumModule.defineConstant(name, runtime.newFixnum(value.getNumber())); + } else { + runtime.getWarnings().warn("Enum value " + name + " does not start with an uppercase letter as is required for Ruby constants."); + } } enumModule.instance_variable_set(runtime.newString(Utils.DESCRIPTOR_INSTANCE_VAR), this); @@ -178,8 +166,8 @@ private RubyModule buildModuleFromDescriptor(ThreadContext context) { return enumModule; } + private EnumDescriptor descriptor; + private EnumDescriptorProto.Builder builder; private IRubyObject name; - private RubyModule klazz; - private Descriptors.EnumDescriptor descriptor; - private DescriptorProtos.EnumDescriptorProto.Builder builder; + private RubyModule module; } 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 f3c488bc98666..8ac5e4c4d7f44 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java @@ -32,8 +32,8 @@ package com.google.protobuf.jruby; -import com.google.protobuf.DescriptorProtos; -import com.google.protobuf.Descriptors; +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.FieldDescriptor; import org.jruby.*; import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyMethod; @@ -43,7 +43,7 @@ @JRubyClass(name = "FieldDescriptor") public class RubyFieldDescriptor extends RubyObject { - public static void createRubyFileDescriptor(Ruby runtime) { + public static void createRubyFieldDescriptor(Ruby runtime) { RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf"); RubyClass cFieldDescriptor = mProtobuf.defineClassUnder("FieldDescriptor", runtime.getObject(), new ObjectAllocator() { @Override @@ -60,42 +60,30 @@ public RubyFieldDescriptor(Ruby runtime, RubyClass klazz) { /* * call-seq: - * FieldDescriptor.new => field + * FieldDescriptor.default => default * - * Returns a new field descriptor. Its name, type, etc. must be set before it is - * added to a message type. + * Returns this field's default, as a Ruby object, or nil if not yet set. */ - @JRubyMethod - public IRubyObject initialize(ThreadContext context) { - builder = DescriptorProtos.FieldDescriptorProto.newBuilder(); - return this; - } + // VALUE FieldDescriptor_default(VALUE _self) { + // DEFINE_SELF(FieldDescriptor, self, _self); + // return layout_get_default(self->fielddef); + // } /* * call-seq: - * FieldDescriptor.label + * FieldDescriptor.label => label + * + * Returns this field's label (i.e., plurality), as a Ruby symbol. * - * Return the label of this field. + * Valid field labels are: + * :optional, :repeated */ @JRubyMethod(name = "label") public IRubyObject getLabel(ThreadContext context) { - return this.label; - } - - /* - * call-seq: - * FieldDescriptor.label = label - * - * Sets the label on this field. Cannot be called if field is part of a message - * type already in a pool. - */ - @JRubyMethod(name = "label=") - public IRubyObject setLabel(ThreadContext context, IRubyObject value) { - String labelName = value.asJavaString(); - this.label = context.runtime.newSymbol(labelName.toLowerCase()); - this.builder.setLabel( - DescriptorProtos.FieldDescriptorProto.Label.valueOf("LABEL_" + labelName.toUpperCase())); - return context.runtime.getNil(); + if (label == null) { + calculateLabel(context); + } + return label; } /* @@ -111,23 +99,19 @@ public IRubyObject getName(ThreadContext context) { /* * call-seq: - * FieldDescriptor.name = name + * FieldDescriptor.subtype => message_or_enum_descriptor * - * Sets the name of this field. Cannot be called once the containing message - * type, if any, is added to a pool. + * Returns the message or enum descriptor corresponding to this field's type if + * it is a message or enum field, respectively, or nil otherwise. Cannot be + * called *until* the containing message type is added to a pool (and thus + * resolved). */ - @JRubyMethod(name = "name=") - public IRubyObject setName(ThreadContext context, IRubyObject value) { - String nameStr = value.asJavaString(); - this.name = context.runtime.newString(nameStr); - this.builder.setName(Utils.escapeIdentifier(nameStr)); - return context.runtime.getNil(); - } - - @JRubyMethod(name = "subtype") - public IRubyObject getSubType(ThreadContext context) { - return subType; + public IRubyObject getSubtype(ThreadContext context) { + if (subtype == null) { + calculateSubtype(context); + } + return subtype; } /* @@ -142,48 +126,42 @@ public IRubyObject getSubType(ThreadContext context) { */ @JRubyMethod(name = "type") public IRubyObject getType(ThreadContext context) { - return Utils.fieldTypeToRuby(context, this.builder.getType()); - } - - /* - * call-seq: - * FieldDescriptor.type = type - * - * Sets this field's type. Cannot be called if field is part of a message type - * already in a pool. - */ - @JRubyMethod(name = "type=") - public IRubyObject setType(ThreadContext context, IRubyObject value) { - this.builder.setType(DescriptorProtos.FieldDescriptorProto.Type.valueOf("TYPE_" + value.asJavaString().toUpperCase())); - return context.runtime.getNil(); + return Utils.fieldTypeToRuby(context, descriptor.getType()); } /* * call-seq: * FieldDescriptor.number => number * - * Returns this field's number, as a Ruby Integer, or nil if not yet set. - * + * Returns the tag number for this field. */ @JRubyMethod(name = "number") - public IRubyObject getnumber(ThreadContext context) { + public IRubyObject getNumber(ThreadContext context) { return this.number; } /* * call-seq: - * FieldDescriptor.number = number + * FieldDescriptor.submsg_name => submsg_name * - * Sets the tag number for this field. Cannot be called if field is part of a - * message type already in a pool. + * Returns the name of the message or enum type corresponding to this field, if + * it is a message or enum field (respectively), or nil otherwise. This type + * name will be resolved within the context of the pool to which the containing + * message type is added. */ - @JRubyMethod(name = "number=") - public IRubyObject setNumber(ThreadContext context, IRubyObject value) { - this.number = value; - this.builder.setNumber(RubyNumeric.num2int(value)); - return context.runtime.getNil(); - } - + // VALUE FieldDescriptor_submsg_name(VALUE _self) { + // DEFINE_SELF(FieldDescriptor, self, _self); + // switch (upb_fielddef_type(self->fielddef)) { + // case UPB_TYPE_ENUM: + // return rb_str_new2( + // upb_enumdef_fullname(upb_fielddef_enumsubdef(self->fielddef))); + // case UPB_TYPE_MESSAGE: + // return rb_str_new2( + // upb_msgdef_fullname(upb_fielddef_msgsubdef(self->fielddef))); + // default: + // return Qnil; + // } + // } /* * call-seq: * FieldDescriptor.submsg_name = submsg_name @@ -194,10 +172,21 @@ public IRubyObject setNumber(ThreadContext context, IRubyObject value) { * Cannot be called on field that are not of message or enum type, or on fields * that are part of a message type already added to a pool. */ - @JRubyMethod(name = "submsg_name=") - public IRubyObject setSubmsgName(ThreadContext context, IRubyObject name) { - this.builder.setTypeName("." + Utils.escapeIdentifier(name.asJavaString())); - return context.runtime.getNil(); + // @JRubyMethod(name = "submsg_name=") + // public IRubyObject setSubmsgName(ThreadContext context, IRubyObject name) { + // this.builder.setTypeName("." + Utils.escapeIdentifier(name.asJavaString())); + // return context.runtime.getNil(); + // } + + /* + * call-seq: + * FieldDescriptor.clear(message) + * + * Clears the field from the message if it's set. + */ + @JRubyMethod(name = "clear") + public IRubyObject clearValue(ThreadContext context, IRubyObject message) { + return ((RubyMessage) message).clearField(context, descriptor); } /* @@ -208,14 +197,22 @@ public IRubyObject setSubmsgName(ThreadContext context, IRubyObject name) { * exception if message is of the wrong type. */ @JRubyMethod(name = "get") - public IRubyObject getValue(ThreadContext context, IRubyObject msgRb) { - RubyMessage message = (RubyMessage) msgRb; - if (message.getDescriptor() != fieldDef.getContainingType()) { - throw context.runtime.newTypeError("set method called on wrong message type"); - } - return message.getField(context, fieldDef); + public IRubyObject getValue(ThreadContext context, IRubyObject message) { + return ((RubyMessage) message).getField(context, descriptor); } + /* + * call-seq: + * FieldDescriptor.has?(message) => boolean + * + * Returns whether the value is set on the given message. Raises an + * exception when calling for fields that do not have presence. + */ + @JRubyMethod(name = "has?") + public IRubyObject has(ThreadContext context, IRubyObject message) { + return ((RubyMessage) message).hasField(context, descriptor); + } + /* * call-seq: * FieldDescriptor.set(message, value) @@ -225,53 +222,46 @@ public IRubyObject getValue(ThreadContext context, IRubyObject msgRb) { * ordinary type-checks for field setting. */ @JRubyMethod(name = "set") - public IRubyObject setValue(ThreadContext context, IRubyObject msgRb, IRubyObject value) { - RubyMessage message = (RubyMessage) msgRb; - if (message.getDescriptor() != fieldDef.getContainingType()) { - throw context.runtime.newTypeError("set method called on wrong message type"); - } - message.setField(context, fieldDef, value); - return context.runtime.getNil(); - } - - protected void setSubType(IRubyObject rubyDescriptor) { - this.subType = rubyDescriptor; - } - - protected void setFieldDef(Descriptors.FieldDescriptor fieldDescriptor) { - this.fieldDef = fieldDescriptor; + public IRubyObject setValue(ThreadContext context, IRubyObject message, IRubyObject value) { + ((RubyMessage) message).setField(context, descriptor, value); + return context.nil; } - protected void setOneofName(IRubyObject name) { - oneofName = name; + protected void setDescriptor(ThreadContext context, FieldDescriptor descriptor, RubyDescriptorPool pool) { + this.descriptor = descriptor; + this.name = context.runtime.newString(descriptor.getName()); + this.pool = pool; } - protected void setOneofIndex(int index) { - hasOneofIndex = true; - oneofIndex = index; - } - - protected IRubyObject getOneofName() { - return oneofName; + private void calculateLabel(ThreadContext context) { + if (descriptor.isRepeated()) { + this.label = context.runtime.newSymbol("repeated"); + } else if (descriptor.isOptional()) { + this.label = context.runtime.newSymbol("optional"); + } else { + this.label = context.nil; + } } - protected Descriptors.FieldDescriptor getFieldDef() { - return fieldDef; + private void calculateSubtype(ThreadContext context) { + FieldDescriptor.Type fdType = descriptor.getType(); + if (fdType == FieldDescriptor.Type.MESSAGE) { + RubyString messageName = context.runtime.newString(descriptor.getMessageType().getFullName()); + this.subtype = pool.lookup(context, messageName); + } else if (fdType == FieldDescriptor.Type.ENUM) { + RubyString enumName = context.runtime.newString(descriptor.getEnumType().getFullName()); + this.subtype = pool.lookup(context, enumName); + } else { + this.subtype = context.nil; + } } - protected DescriptorProtos.FieldDescriptorProto build() { - if (hasOneofIndex) - builder.setOneofIndex(oneofIndex); - return this.builder.build(); - } + private static final String DOT = "."; - private DescriptorProtos.FieldDescriptorProto.Builder builder; + private FieldDescriptor descriptor; private IRubyObject name; private IRubyObject label; private IRubyObject number; - private IRubyObject subType; - private IRubyObject oneofName; - private Descriptors.FieldDescriptor fieldDef; - private int oneofIndex; - private boolean hasOneofIndex = false; + private IRubyObject subtype; + private RubyDescriptorPool pool; } diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyFileBuilderContext.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyFileBuilderContext.java new file mode 100644 index 0000000000000..00ce3f2158294 --- /dev/null +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyFileBuilderContext.java @@ -0,0 +1,348 @@ +/* + * Protocol Buffers - Google's data interchange format + * Copyright 2014 Google Inc. All rights reserved. + * https://developers.google.com/protocol-buffers/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.google.protobuf.jruby; + +import com.google.protobuf.DescriptorProtos.DescriptorProto; +import com.google.protobuf.DescriptorProtos.EnumDescriptorProto; +import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProtoOrBuilder; +import com.google.protobuf.DescriptorProtos.FieldDescriptorProto; +import com.google.protobuf.DescriptorProtos.FileDescriptorProto; +import com.google.protobuf.Descriptors.FieldDescriptor; +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyHash; +import org.jruby.RubyModule; +import org.jruby.RubyObject; +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 java.util.HashMap; +import java.util.List; +import java.util.TreeMap; + +@JRubyClass(name = "FileBuilderContext") +public class RubyFileBuilderContext extends RubyObject { + public static void createRubyFileBuilderContext(Ruby runtime) { + RubyModule internal = runtime.getClassFromPath("Google::Protobuf::Internal"); + RubyClass cFileBuilderContext = internal.defineClassUnder("FileBuilderContext", runtime.getObject(), new ObjectAllocator() { + @Override + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + return new RubyFileBuilderContext(runtime, klazz); + } + }); + cFileBuilderContext.defineAnnotatedMethods(RubyFileBuilderContext.class); + + cDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Descriptor"); + cEnumBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Internal::EnumBuilderContext"); + cEnumDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumDescriptor"); + cMessageBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Internal::MessageBuilderContext"); + } + + public RubyFileBuilderContext(Ruby runtime, RubyClass klazz) { + super(runtime, klazz); + } + + /* + * call-seq: + * FileBuilderContext.new(descriptor_pool, name, options = nil) => context + * + * Create a new file builder context for the given file descriptor and + * builder context. This class is intended to serve as a DSL context to be used + * with #instance_eval. + */ + @JRubyMethod(required = 2, optional = 1) + public IRubyObject initialize(ThreadContext context, IRubyObject[] args) { + this.descriptorPool = (RubyDescriptorPool) args[0]; + this.builder = FileDescriptorProto.newBuilder(); + this.builder.setName(args[1].asJavaString()); + this.builder.setSyntax("proto3"); + + if (args.length > 2) { + RubyHash options = (RubyHash) args[2]; + IRubyObject syntax = options.fastARef(context.runtime.newSymbol("syntax")); + + if (syntax != null) { + String syntaxStr = syntax.asJavaString(); + this.builder.setSyntax(syntaxStr); + this.proto3 = syntaxStr.equals("proto3"); + } + } + + return this; + } + + /* + * call-seq: + * FileBuilderContext.add_enum(name, &block) + * + * Creates a new, empty enum descriptor with the given name, and invokes the + * block in the context of an EnumBuilderContext on that descriptor. The block + * can then call EnumBuilderContext#add_value to define the enum values. + * + * This is the recommended, idiomatic way to build enum definitions. + */ + @JRubyMethod(name = "add_enum") + public IRubyObject addEnum(ThreadContext context, IRubyObject name, Block block) { + RubyObject ctx = (RubyObject) cEnumBuilderContext.newInstance(context, this, name, Block.NULL_BLOCK); + ctx.instance_eval(context, block); + + return context.nil; + } + + /* + * call-seq: + * FileBuilderContext.add_message(name, &block) + * + * Creates a new, empty descriptor with the given name, and invokes the block in + * the context of a MessageBuilderContext on that descriptor. The block can then + * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated + * methods to define the message fields. + * + * This is the recommended, idiomatic way to build message definitions. + */ + @JRubyMethod(name = "add_message") + public IRubyObject addMessage(ThreadContext context, IRubyObject name, Block block) { + RubyObject ctx = (RubyObject) cMessageBuilderContext.newInstance(context, this, name, Block.NULL_BLOCK); + ctx.instance_eval(context, block); + + return context.nil; + } + + protected void build(ThreadContext context) { + Ruby runtime = context.runtime; + List messageBuilderList = builder.getMessageTypeBuilderList(); + List enumBuilderList = builder.getEnumTypeBuilderList(); + + // Get the package name from defined names + String packageName = getPackageName(messageBuilderList, enumBuilderList); + + if (!packageName.isEmpty()) { + builder.setPackage(packageName); + } + + // Make an index of the message builders so we can easily nest them + TreeMap messageBuilderMap = new TreeMap(); + for (DescriptorProto.Builder messageBuilder : messageBuilderList) { + messageBuilderMap.put(messageBuilder.getName(), messageBuilder); + } + + // Make an index of the enum builders so we can easily nest them + HashMap enumBuilderMap = new HashMap(); + for (EnumDescriptorProto.Builder enumBuilder : enumBuilderList) { + enumBuilderMap.put("." + enumBuilder.getName(), enumBuilder); + } + + // Rename and properly nest messages and create associated ruby objects + int packageNameLength = packageName.length(); + int currentMessageIndex = 0; + int currentEnumIndex = 0; + + // Need to get a static list because we are potentially deleting some of them from the collection + DescriptorProto.Builder[] messageBuilders = new DescriptorProto.Builder[messageBuilderList.size()]; + messageBuilderList.toArray(messageBuilders); + EnumDescriptorProto.Builder[] enumBuilders = new EnumDescriptorProto.Builder[enumBuilderList.size()]; + enumBuilderList.toArray(enumBuilders); + + for (EnumDescriptorProto.Builder enumBuilder : enumBuilders) { + String name = enumBuilder.getName(); + int lastDot = name.lastIndexOf('.'); + + if (lastDot > packageNameLength) { + String parentName = name.substring(0, lastDot); + String shortName = name.substring(lastDot + 1); + + enumBuilder.setName(shortName); + messageBuilderMap.get(parentName).addEnumType(enumBuilder); + + builder.removeEnumType(currentEnumIndex); + + } else { + if (packageNameLength > 0) { + // Remove the package name + String shortName = name.substring(packageNameLength + 1); + enumBuilder.setName(shortName); + } + + currentEnumIndex++; + } + + // Ensure we have a default value if using proto3 syntax + if (proto3) { + boolean foundDefault = false; + for (EnumValueDescriptorProtoOrBuilder enumValue : enumBuilder.getValueOrBuilderList()) { + if (enumValue.getNumber() == 0) { + foundDefault = true; + break; + } + } + + if (!foundDefault) { + throw Utils.createTypeError(context, "Enum definition " + enumBuilder.getName() + " does not contain a value for '0'"); + } + } + } + + // Wipe out top level message builders so we can insert only the ones that should be there + builder.clearMessageType(); + + /* + * This block is done in this order because calling + * `addNestedType` and `addMessageType` makes a copy of the builder + * so the objects that our maps point to are no longer the objects + * that are being used to build the descriptions. + */ + for (HashMap.Entry entry : messageBuilderMap.descendingMap().entrySet()) { + DescriptorProto.Builder messageBuilder = entry.getValue(); + + // Rewrite any enum defaults needed + for(FieldDescriptorProto.Builder field : messageBuilder.getFieldBuilderList()) { + String typeName = field.getTypeName(); + + if (typeName == null || !field.hasDefaultValue()) continue; + + EnumDescriptorProto.Builder enumBuilder = enumBuilderMap.get(typeName); + + if (enumBuilder == null) continue; + + int defaultValue = Integer.parseInt(field.getDefaultValue()); + + for (EnumValueDescriptorProtoOrBuilder enumValue : enumBuilder.getValueOrBuilderList()) { + if (enumValue.getNumber() == defaultValue) { + field.setDefaultValue(enumValue.getName()); + break; + } + } + } + + // Turn Foo.Bar.Baz into a correctly nested structure with the correct name + String name = messageBuilder.getName(); + int lastDot = name.lastIndexOf('.'); + + if (lastDot > packageNameLength) { + String parentName = name.substring(0, lastDot); + String shortName = name.substring(lastDot + 1); + messageBuilder.setName(shortName); + messageBuilderMap.get(parentName).addNestedType(messageBuilder); + + } else { + if (packageNameLength > 0) { + // Remove the package name + messageBuilder.setName(name.substring(packageNameLength + 1)); + } + + // Add back in top level message definitions + builder.addMessageType(messageBuilder); + + currentMessageIndex++; + } + } + + descriptorPool.registerFileDescriptor(context, builder); + } + + protected EnumDescriptorProto.Builder getNewEnumBuilder() { + return builder.addEnumTypeBuilder(); + } + + protected DescriptorProto.Builder getNewMessageBuilder() { + return builder.addMessageTypeBuilder(); + } + + protected boolean isProto3() { + return proto3; + } + + private String getPackageName(List messages, List enums) { + String shortest = null; + String longest = null; + + /* + * The >= in the longest string comparisons below makes it so we replace + * the name in case all the names are the same length. This makes it so + * that the shortest and longest aren't the same name to prevent + * finding a "package" that isn't correct + */ + + for (DescriptorProto.Builder message : messages) { + String name = message.getName(); + int nameLength = name.length(); + if (shortest == null) { + shortest = name; + longest = name; + } else if (nameLength < shortest.length()) { + shortest = name; + } else if (nameLength >= longest.length()) { + longest = name; + } + } + + for (EnumDescriptorProto.Builder item : enums) { + String name = item.getName(); + int nameLength = name.length(); + if (shortest == null) { + shortest = name; + longest = name; + } else if (nameLength < shortest.length()) { + shortest = name; + } else if (nameLength >= longest.length()) { + longest = name; + } + } + + if (shortest == null) { + return ""; + } + + int lastCommonDot = 0; + for (int i = 0; i < shortest.length(); i++) { + char nextChar = shortest.charAt(i); + if (nextChar != longest.charAt(i)) break; + if (nextChar == '.') lastCommonDot = i; + } + + return shortest.substring(0, lastCommonDot); + } + + private static RubyClass cDescriptor; + private static RubyClass cEnumBuilderContext; + private static RubyClass cEnumDescriptor; + private static RubyClass cMessageBuilderContext; + + private FileDescriptorProto.Builder builder; + private RubyDescriptorPool descriptorPool; + private boolean proto3 = true; +} diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyFileDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyFileDescriptor.java new file mode 100644 index 0000000000000..b3e1816c76a24 --- /dev/null +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyFileDescriptor.java @@ -0,0 +1,106 @@ +/* + * Protocol Buffers - Google's data interchange format + * Copyright 2014 Google Inc. All rights reserved. + * https://developers.google.com/protocol-buffers/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.google.protobuf.jruby; + +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.FileDescriptor; +import com.google.protobuf.Descriptors.FileDescriptor.Syntax.*; +import com.google.protobuf.Descriptors.GenericDescriptor; +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; + +@JRubyClass(name = "FileDescriptor") +public class RubyFileDescriptor extends RubyObject { + public static void createRubyFileDescriptor(Ruby runtime) { + RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf"); + cFileDescriptor = mProtobuf.defineClassUnder("FileDescriptor", runtime.getObject(), new ObjectAllocator() { + @Override + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + return new RubyFileDescriptor(runtime, klazz); + } + }); + cFileDescriptor.defineAnnotatedMethods(RubyFileDescriptor.class); + } + + public static RubyFileDescriptor getRubyFileDescriptor(ThreadContext context, GenericDescriptor descriptor) { + RubyFileDescriptor rfd = (RubyFileDescriptor) cFileDescriptor.newInstance(context, Block.NULL_BLOCK); + rfd.fileDescriptor = descriptor.getFile(); + return rfd; + } + + public RubyFileDescriptor(Ruby runtime, RubyClass klazz) { + super(runtime, klazz); + } + + /* + * call-seq: + * FileDescriptor.name => name + * + * Returns the name of the file. + */ + @JRubyMethod(name = "name") + public IRubyObject getName(ThreadContext context) { + String name = fileDescriptor.getName(); + return name == null ? context.nil : context.runtime.newString(name); + } + + /* + * call-seq: + * FileDescriptor.syntax => syntax + * + * Returns this file descriptors syntax. + * + * Valid syntax versions are: + * :proto2 or :proto3. + */ + @JRubyMethod(name = "syntax") + public IRubyObject getSyntax(ThreadContext context) { + switch (fileDescriptor.getSyntax()) { + case PROTO2: + return context.runtime.newSymbol("proto2"); + case PROTO3: + return context.runtime.newSymbol("proto3"); + default: + return context.nil; + } + } + + private static RubyClass cFileDescriptor; + + private FileDescriptor fileDescriptor; +} diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java index 3adaa2a8bdc1c..087f1cb4c133a 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java @@ -32,19 +32,19 @@ package com.google.protobuf.jruby; -import com.google.protobuf.Descriptors; +import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.DynamicMessage; -import com.google.protobuf.MapEntry; import org.jruby.*; import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyMethod; import org.jruby.internal.runtime.methods.DynamicMethod; import org.jruby.runtime.Block; +import org.jruby.runtime.Helpers; import org.jruby.runtime.ObjectAllocator; import org.jruby.runtime.ThreadContext; import org.jruby.runtime.builtin.IRubyObject; -import org.jruby.util.ByteList; +import java.nio.ByteBuffer; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; @@ -100,7 +100,6 @@ public RubyMap(Ruby ruby, RubyClass rubyClass) { * references to underlying objects will be shared if the value type is a * message type. */ - @JRubyMethod(required = 2, optional = 2) public IRubyObject initialize(ThreadContext context, IRubyObject[] args) { this.table = new HashMap(); @@ -108,13 +107,15 @@ public IRubyObject initialize(ThreadContext context, IRubyObject[] args) { this.valueType = Utils.rubyToFieldType(args[1]); switch(keyType) { + case STRING: + case BYTES: + this.keyTypeIsString = true; + break; case INT32: case INT64: case UINT32: case UINT64: case BOOL: - case STRING: - case BYTES: // These are OK. break; default: @@ -130,8 +131,6 @@ public IRubyObject initialize(ThreadContext context, IRubyObject[] args) { this.valueTypeClass = context.runtime.getNilClass(); } - // Table value type is always UINT64: this ensures enough space to store the - // native_slot value. if (args.length > initValueArg) { mergeIntoSelf(context, args[initValueArg]); } @@ -148,10 +147,19 @@ public IRubyObject initialize(ThreadContext context, IRubyObject[] args) { */ @JRubyMethod(name = "[]=") public IRubyObject indexSet(ThreadContext context, IRubyObject key, IRubyObject value) { - key = Utils.checkType(context, keyType, key, (RubyModule) valueTypeClass); - value = Utils.checkType(context, valueType, value, (RubyModule) valueTypeClass); + checkFrozen(); + + /* + * String types for keys return a different error than + * other types for keys, so deal with them specifically first + */ + if (keyTypeIsString && !(key instanceof RubySymbol || key instanceof RubyString)) { + throw context.runtime.newTypeError("Expected string for map key"); + } + key = Utils.checkType(context, keyType, "key", key, (RubyModule) valueTypeClass); + value = Utils.checkType(context, valueType, "value", value, (RubyModule) valueTypeClass); IRubyObject symbol; - if (valueType == Descriptors.FieldDescriptor.Type.ENUM && + if (valueType == FieldDescriptor.Type.ENUM && Utils.isRubyNum(value) && ! (symbol = RubyEnum.lookup(context, valueTypeClass, value)).isNil()) { value = symbol; @@ -169,9 +177,8 @@ public IRubyObject indexSet(ThreadContext context, IRubyObject key, IRubyObject */ @JRubyMethod(name = "[]") public IRubyObject index(ThreadContext context, IRubyObject key) { - if (table.containsKey(key)) - return this.table.get(key); - return context.runtime.getNil(); + key = Utils.symToString(key); + return Helpers.nullToNil(table.get(key), context.nil); } /* @@ -190,7 +197,7 @@ public IRubyObject index(ThreadContext context, IRubyObject key) { @JRubyMethod(name = "==") public IRubyObject eq(ThreadContext context, IRubyObject _other) { if (_other instanceof RubyHash) - return toHash(context).op_equal(context, _other); + return singleLevelHash(context).op_equal(context, _other); RubyMap other = (RubyMap) _other; if (this == other) return context.runtime.getTrue(); if (!typeCompatible(other) || this.table.size() != other.table.size()) @@ -214,7 +221,7 @@ public IRubyObject eq(ThreadContext context, IRubyObject _other) { */ @JRubyMethod public IRubyObject inspect() { - return toHash(getRuntime().getCurrentContext()).inspect(); + return singleLevelHash(getRuntime().getCurrentContext()).inspect(); } /* @@ -231,7 +238,7 @@ public IRubyObject hash(ThreadContext context) { digest.update((byte) key.hashCode()); digest.update((byte) table.get(key).hashCode()); } - return context.runtime.newString(new ByteList(digest.digest())); + return context.runtime.newFixnum(ByteBuffer.wrap(digest.digest()).getLong()); } catch (NoSuchAlgorithmException ignore) { return context.runtime.newFixnum(System.identityHashCode(table)); } @@ -267,8 +274,9 @@ public IRubyObject values(ThreadContext context) { */ @JRubyMethod public IRubyObject clear(ThreadContext context) { + checkFrozen(); table.clear(); - return context.runtime.getNil(); + return context.nil; } /* @@ -284,7 +292,7 @@ public IRubyObject each(ThreadContext context, Block block) { for (IRubyObject key : table.keySet()) { block.yieldSpecific(context, key, table.get(key)); } - return context.runtime.getNil(); + return context.nil; } /* @@ -296,6 +304,7 @@ public IRubyObject each(ThreadContext context, Block block) { */ @JRubyMethod public IRubyObject delete(ThreadContext context, IRubyObject key) { + checkFrozen(); return table.remove(key); } @@ -338,9 +347,22 @@ public IRubyObject dup(ThreadContext context) { return newMap; } - @JRubyMethod(name = {"to_h", "to_hash"}) + @JRubyMethod(name = "to_h") public RubyHash toHash(ThreadContext context) { - return RubyHash.newHash(context.runtime, table, context.runtime.getNil()); + Map mapForHash = new HashMap(); + + table.forEach((key, value) -> { + if (!value.isNil()) { + if (value.respondsTo("to_h")) { + value = Helpers.invoke(context, value, "to_h"); + } else if (value.respondsTo("to_a")) { + value = Helpers.invoke(context, value, "to_a"); + } + mapForHash.put(key, value); + } + }); + + return RubyHash.newHash(context.runtime, mapForHash, context.nil); } // Used by Google::Protobuf.deep_copy but not exposed directly. @@ -361,16 +383,16 @@ protected IRubyObject deepCopy(ThreadContext context) { return newMap; } - protected List build(ThreadContext context, RubyDescriptor descriptor) { + protected List build(ThreadContext context, RubyDescriptor descriptor, int depth) { List list = new ArrayList(); RubyClass rubyClass = (RubyClass) descriptor.msgclass(context); - Descriptors.FieldDescriptor keyField = descriptor.lookup("key").getFieldDef(); - Descriptors.FieldDescriptor valueField = descriptor.lookup("value").getFieldDef(); + FieldDescriptor keyField = descriptor.getField("key"); + FieldDescriptor valueField = descriptor.getField("value"); for (IRubyObject key : table.keySet()) { RubyMessage mapMessage = (RubyMessage) rubyClass.newInstance(context, Block.NULL_BLOCK); mapMessage.setField(context, keyField, key); mapMessage.setField(context, valueField, table.get(key)); - list.add(mapMessage.build(context)); + list.add(mapMessage.build(context, depth + 1)); } return list; } @@ -380,13 +402,16 @@ protected RubyMap mergeIntoSelf(final ThreadContext context, IRubyObject hashmap ((RubyHash) hashmap).visitAll(new RubyHash.Visitor() { @Override public void visit(IRubyObject key, IRubyObject val) { + if (val instanceof RubyHash && !valueTypeClass.isNil()) { + val = ((RubyClass) valueTypeClass).newInstance(context, val, Block.NULL_BLOCK); + } indexSet(context, key, val); } }); } else if (hashmap instanceof RubyMap) { RubyMap other = (RubyMap) hashmap; if (!typeCompatible(other)) { - throw context.runtime.newTypeError("Attempt to merge Map with mismatching types"); + throw Utils.createTypeError(context, "Attempt to merge Map with mismatching types"); } } else { throw context.runtime.newTypeError("Unknown type merging into Map"); @@ -417,7 +442,15 @@ private RubyMap newThisType(ThreadContext context) { return newMap; } - private boolean needTypeclass(Descriptors.FieldDescriptor.Type type) { + /* + * toHash calls toHash on values, for some camparisons we only need + * a hash with the original objects still as values + */ + private RubyHash singleLevelHash(ThreadContext context) { + return RubyHash.newHash(context.runtime, table, context.nil); + } + + private boolean needTypeclass(FieldDescriptor.Type type) { switch(type) { case MESSAGE: case ENUM: @@ -427,8 +460,9 @@ private boolean needTypeclass(Descriptors.FieldDescriptor.Type type) { } } - private Descriptors.FieldDescriptor.Type keyType; - private Descriptors.FieldDescriptor.Type valueType; + private FieldDescriptor.Type keyType; + private FieldDescriptor.Type valueType; private IRubyObject valueTypeClass; private Map table; + private boolean keyTypeIsString = false; } diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java index 733ccfbc7dbc2..a905c9a260600 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java @@ -32,24 +32,45 @@ package com.google.protobuf.jruby; -import com.google.protobuf.*; +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.EnumDescriptor; +import com.google.protobuf.Descriptors.EnumValueDescriptor; +import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Descriptors.FileDescriptor; +import com.google.protobuf.Descriptors.OneofDescriptor; +import com.google.protobuf.ByteString; +import com.google.protobuf.DynamicMessage; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Message; +import com.google.protobuf.UnknownFieldSet; +import com.google.protobuf.util.JsonFormat; import org.jruby.*; import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; import org.jruby.runtime.Block; import org.jruby.runtime.Helpers; import org.jruby.runtime.ThreadContext; import org.jruby.runtime.builtin.IRubyObject; import org.jruby.util.ByteList; +import java.nio.ByteBuffer; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; +import java.util.List; import java.util.Map; public class RubyMessage extends RubyObject { - public RubyMessage(Ruby ruby, RubyClass klazz, Descriptors.Descriptor descriptor) { - super(ruby, klazz); + public RubyMessage(Ruby runtime, RubyClass klazz, Descriptor descriptor) { + super(runtime, klazz); + this.descriptor = descriptor; + this.cRepeatedField = (RubyClass) runtime.getClassFromPath("Google::Protobuf::RepeatedField"); + this.cMap = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Map"); + this.builder = DynamicMessage.newBuilder(descriptor); + this.fields = new HashMap(); + this.oneofCases = new HashMap(); + this.proto3 = descriptor.getFile().getSyntax() == FileDescriptor.Syntax.PROTO3; } /* @@ -67,13 +88,6 @@ public RubyMessage(Ruby ruby, RubyClass klazz, Descriptors.Descriptor descriptor @JRubyMethod(optional = 1) public IRubyObject initialize(final ThreadContext context, IRubyObject[] args) { final Ruby runtime = context.runtime; - this.cRepeatedField = (RubyClass) runtime.getClassFromPath("Google::Protobuf::RepeatedField"); - this.cMap = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Map"); - this.builder = DynamicMessage.newBuilder(this.descriptor); - this.repeatedFields = new HashMap(); - this.maps = new HashMap(); - this.fields = new HashMap(); - this.oneofCases = new HashMap(); if (args.length == 1) { if (!(args[0] instanceof RubyHash)) { throw runtime.newArgumentError("expected Hash arguments."); @@ -82,30 +96,39 @@ public IRubyObject initialize(final ThreadContext context, IRubyObject[] args) { hash.visitAll(new RubyHash.Visitor() { @Override public void visit(IRubyObject key, IRubyObject value) { - if (!(key instanceof RubySymbol)) - throw runtime.newTypeError("Expected symbols as hash keys in initialization map."); - final Descriptors.FieldDescriptor fieldDescriptor = findField(context, key); + if (!(key instanceof RubySymbol) && !(key instanceof RubyString)) + throw runtime.newTypeError("Expected string or symbols as hash keys in initialization map."); + final FieldDescriptor fieldDescriptor = findField(context, key, ignoreUnknownFieldsOnInit); + + if (value == null || value.isNil()) return; if (Utils.isMapEntry(fieldDescriptor)) { if (!(value instanceof RubyHash)) - throw runtime.newArgumentError("Expected Hash object as initializer value for map field '" + key.asJavaString() + "'."); + throw runtime.newArgumentError("Expected Hash object as initializer value for map field '" + key.asJavaString() + "' (given " + value.getMetaClass() + ")."); final RubyMap map = newMapForField(context, fieldDescriptor); map.mergeIntoSelf(context, value); - maps.put(fieldDescriptor, map); + fields.put(fieldDescriptor, map); } else if (fieldDescriptor.isRepeated()) { if (!(value instanceof RubyArray)) - throw runtime.newArgumentError("Expected array as initializer value for repeated field '" + key.asJavaString() + "'."); - RubyRepeatedField repeatedField = rubyToRepeatedField(context, fieldDescriptor, value); - addRepeatedField(fieldDescriptor, repeatedField); + throw runtime.newArgumentError("Expected array as initializer value for repeated field '" + key.asJavaString() + "' (given " + value.getMetaClass() + ")."); + fields.put(fieldDescriptor, rubyToRepeatedField(context, fieldDescriptor, value)); } else { - Descriptors.OneofDescriptor oneof = fieldDescriptor.getContainingOneof(); + OneofDescriptor oneof = fieldDescriptor.getContainingOneof(); if (oneof != null) { oneofCases.put(oneof, fieldDescriptor); } - fields.put(fieldDescriptor, value); - } + if (value instanceof RubyHash && fieldDescriptor.getType() == FieldDescriptor.Type.MESSAGE) { + RubyDescriptor descriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor); + RubyClass typeClass = (RubyClass) descriptor.msgclass(context); + value = (IRubyObject) typeClass.newInstance(context, value, Block.NULL_BLOCK); + fields.put(fieldDescriptor, value); + } else { + indexSet(context, key, value); + } + + } } }); } @@ -121,8 +144,8 @@ public void visit(IRubyObject key, IRubyObject value) { */ @JRubyMethod(name = "[]=") public IRubyObject indexSet(ThreadContext context, IRubyObject fieldName, IRubyObject value) { - Descriptors.FieldDescriptor fieldDescriptor = findField(context, fieldName); - return setField(context, fieldDescriptor, value); + FieldDescriptor fieldDescriptor = findField(context, fieldName); + return setFieldInternal(context, fieldDescriptor, value); } /* @@ -134,8 +157,8 @@ public IRubyObject indexSet(ThreadContext context, IRubyObject fieldName, IRubyO */ @JRubyMethod(name = "[]") public IRubyObject index(ThreadContext context, IRubyObject fieldName) { - Descriptors.FieldDescriptor fieldDescriptor = findField(context, fieldName); - return getField(context, fieldDescriptor); + FieldDescriptor fieldDescriptor = findField(context, fieldName); + return getFieldInternal(context, fieldDescriptor); } /* @@ -146,16 +169,37 @@ public IRubyObject index(ThreadContext context, IRubyObject fieldName) { * formatted as "". Each * field's value is represented according to its own #inspect method. */ - @JRubyMethod + @JRubyMethod(name = {"inspect", "to_s"}) public IRubyObject inspect() { + ThreadContext context = getRuntime().getCurrentContext(); String cname = metaClass.getName(); + String colon = ": "; + String comma = ", "; StringBuilder sb = new StringBuilder("<"); - sb.append(cname); - sb.append(": "); - sb.append(this.layoutInspect()); + boolean addComma = false; + + sb.append(cname).append(colon); + + for (FieldDescriptor fd : descriptor.getFields()) { + if (addComma) { + sb.append(comma); + } else { + addComma = true; + } + + sb.append(fd.getName()).append(colon); + + IRubyObject value = getFieldInternal(context, fd); + if (value instanceof RubyBoolean) { + // Booleans don't implement internal "inspect" methods so have to call handle them manually + sb.append(value.isTrue() ? "true" : "false"); + } else { + sb.append(value.inspect()); + } + } sb.append(">"); - return getRuntime().newString(sb.toString()); + return context.runtime.newString(sb.toString()); } /* @@ -168,16 +212,10 @@ public IRubyObject inspect() { public IRubyObject hash(ThreadContext context) { try { MessageDigest digest = MessageDigest.getInstance("SHA-256"); - for (RubyMap map : maps.values()) { - digest.update((byte) map.hashCode()); - } - for (RubyRepeatedField repeatedField : repeatedFields.values()) { - digest.update((byte) repeatedFields.hashCode()); - } - for (IRubyObject field : fields.values()) { - digest.update((byte) field.hashCode()); + for (FieldDescriptor fd : descriptor.getFields()) { + digest.update((byte) getFieldInternal(context, fd).hashCode()); } - return context.runtime.newString(new ByteList(digest.digest())); + return context.runtime.newFixnum(ByteBuffer.wrap(digest.digest()).getLong()); } catch (NoSuchAlgorithmException ignore) { return context.runtime.newFixnum(System.identityHashCode(this)); } @@ -192,7 +230,7 @@ public IRubyObject hash(ThreadContext context) { * method's semantics (a more efficient comparison may actually be done if the * field is of a primitive type). */ - @JRubyMethod(name = "==") + @JRubyMethod(name = {"==", "eql?"}) public IRubyObject eq(ThreadContext context, IRubyObject other) { Ruby runtime = context.runtime; if (!(other instanceof RubyMessage)) @@ -202,9 +240,9 @@ public IRubyObject eq(ThreadContext context, IRubyObject other) { return runtime.getFalse(); } - for (Descriptors.FieldDescriptor fdef : descriptor.getFields()) { - IRubyObject thisVal = getField(context, fdef); - IRubyObject thatVal = message.getField(context, fdef); + for (FieldDescriptor fdef : descriptor.getFields()) { + IRubyObject thisVal = getFieldInternal(context, fdef); + IRubyObject thatVal = message.getFieldInternal(context, fdef); IRubyObject ret = thisVal.callMethod(context, "==", thatVal); if (!ret.isTrue()) { return runtime.getFalse(); @@ -217,46 +255,169 @@ public IRubyObject eq(ThreadContext context, IRubyObject other) { * call-seq: * Message.method_missing(*args) * - * Provides accessors and setters for message fields according to their field - * names. For any field whose name does not conflict with a built-in method, an + * Provides accessors and setters and methods to clear and check for presence of + * message fields according to their field names. + * + * For any field whose name does not conflict with a built-in method, an * accessor is provided with the same name as the field, and a setter is * provided with the name of the field plus the '=' suffix. Thus, given a * message instance 'msg' with field 'foo', the following code is valid: * * msg.foo = 42 * puts msg.foo + * + * This method also provides read-only accessors for oneofs. If a oneof exists + * with name 'my_oneof', then msg.my_oneof will return a Ruby symbol equal to + * the name of the field in that oneof that is currently set, or nil if none. + * + * It also provides methods of the form 'clear_fieldname' to clear the value + * of the field 'fieldname'. For basic data types, this will set the default + * value of the field. + * + * Additionally, it provides methods of the form 'has_fieldname?', which returns + * true if the field 'fieldname' is set in the message object, else false. For + * 'proto3' syntax, calling this for a basic type field will result in an error. */ @JRubyMethod(name = "method_missing", rest = true) public IRubyObject methodMissing(ThreadContext context, IRubyObject[] args) { + Ruby runtime = context.runtime; + String methodName = args[0].asJavaString(); + if (args.length == 1) { RubyDescriptor rubyDescriptor = (RubyDescriptor) getDescriptor(context, metaClass); + + // If we find a Oneof return it's name (use lookupOneof because it has an index) IRubyObject oneofDescriptor = rubyDescriptor.lookupOneof(context, args[0]); - if (oneofDescriptor.isNil()) { - if (!hasField(args[0])) { - return Helpers.invokeSuper(context, this, metaClass, "method_missing", args, Block.NULL_BLOCK); + + if (!oneofDescriptor.isNil()) { + RubyOneofDescriptor rubyOneofDescriptor = (RubyOneofDescriptor) oneofDescriptor; + OneofDescriptor ood = rubyOneofDescriptor.getDescriptor(); + + // Check to see if we set this through ruby + FieldDescriptor fieldDescriptor = oneofCases.get(ood); + + if (fieldDescriptor == null) { + // See if we set this from decoding a message + fieldDescriptor = builder.getOneofFieldDescriptor(ood); + + if (fieldDescriptor == null) { + return context.nil; + } else { + // Cache it so we don't need to do multiple checks next time + oneofCases.put(ood, fieldDescriptor); + return runtime.newSymbol(fieldDescriptor.getName()); + } + } else { + return runtime.newSymbol(fieldDescriptor.getName()); } - return index(context, args[0]); } - RubyOneofDescriptor rubyOneofDescriptor = (RubyOneofDescriptor) oneofDescriptor; - Descriptors.FieldDescriptor fieldDescriptor = - oneofCases.get(rubyOneofDescriptor.getOneofDescriptor()); - if (fieldDescriptor == null) - return context.runtime.getNil(); - return context.runtime.newSymbol(fieldDescriptor.getName()); - } else { - // fieldName is RubySymbol - RubyString field = args[0].asString(); - RubyString equalSign = context.runtime.newString(Utils.EQUAL_SIGN); - if (field.end_with_p(context, equalSign).isTrue()) { - field.chomp_bang(context, equalSign); + // If we find a field return its value + FieldDescriptor fieldDescriptor = descriptor.findFieldByName(methodName); + + if (fieldDescriptor != null) { + return getFieldInternal(context, fieldDescriptor); } - if (!hasField(field)) { - return Helpers.invokeSuper(context, this, metaClass, "method_missing", args, Block.NULL_BLOCK); + if (methodName.startsWith(CLEAR_PREFIX)) { + methodName = methodName.substring(6); + oneofDescriptor = rubyDescriptor.lookupOneof(context, runtime.newSymbol(methodName)); + + if (!oneofDescriptor.isNil()) { + fieldDescriptor = oneofCases.get(((RubyOneofDescriptor) oneofDescriptor).getDescriptor()); + } + + if (fieldDescriptor == null) { + fieldDescriptor = descriptor.findFieldByName(methodName); + } + + if (fieldDescriptor != null) { + return clearFieldInternal(context, fieldDescriptor); + } + + } else if (methodName.startsWith(HAS_PREFIX) && methodName.endsWith(QUESTION_MARK)) { + methodName = methodName.substring(4, methodName.length() - 1); // Trim "has_" and "?" off the field name + oneofDescriptor = rubyDescriptor.lookupOneof(context, runtime.newSymbol(methodName)); + if (!oneofDescriptor.isNil()) { + RubyOneofDescriptor rubyOneofDescriptor = (RubyOneofDescriptor) oneofDescriptor; + return oneofCases.containsKey(rubyOneofDescriptor.getDescriptor()) ? runtime.getTrue() : runtime.getFalse(); + } + + fieldDescriptor = descriptor.findFieldByName(methodName); + + if (fieldDescriptor != null && + (!proto3 || fieldDescriptor.getContainingOneof() == null) && // This seems like a bug but its needed to pass the tests... + fieldHasPresence(fieldDescriptor)) { + return fields.containsKey(fieldDescriptor) ? runtime.getTrue() : runtime.getFalse(); + } + + } else if (methodName.endsWith(AS_VALUE_SUFFIX)) { + methodName = methodName.substring(0, methodName.length() - 9); + fieldDescriptor = descriptor.findFieldByName(methodName); + + if (fieldDescriptor != null && isWrappable(fieldDescriptor)) { + IRubyObject value = getFieldInternal(context, fieldDescriptor); + + if (!value.isNil() && value instanceof RubyMessage) { + return ((RubyMessage) value).index(context, runtime.newString("value")); + } + + return value; + } + + } else if (methodName.endsWith(CONST_SUFFIX)) { + methodName = methodName.substring(0, methodName.length() - 6); + fieldDescriptor = descriptor.findFieldByName(methodName); + + if (fieldDescriptor.getType() == FieldDescriptor.Type.ENUM) { + IRubyObject enumValue = getFieldInternal(context, fieldDescriptor); + + if (!enumValue.isNil()) { + EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType(); + if (enumValue instanceof RubyRepeatedField) { + RubyArray values = (RubyArray) ((RubyRepeatedField) enumValue).toArray(context); + RubyArray retValues = runtime.newArray(values.getLength()); + for (int i = 0; i < values.getLength(); i++) { + String val = values.eltInternal(i).toString(); + retValues.store((long) i, runtime.newFixnum(enumDescriptor.findValueByName(val).getNumber())); + } + return retValues; + } + + return runtime.newFixnum(enumDescriptor.findValueByName(enumValue.asJavaString()).getNumber()); + } + } + } + + } else if (args.length == 2 && methodName.endsWith(Utils.EQUAL_SIGN)) { + + methodName = methodName.substring(0, methodName.length() - 1); // Trim equals sign + FieldDescriptor fieldDescriptor = descriptor.findFieldByName(methodName); + + if (fieldDescriptor != null) { + return setFieldInternal(context, fieldDescriptor, args[1]); } - return indexSet(context, field, args[1]); + + if (methodName.endsWith(AS_VALUE_SUFFIX)) { + methodName = methodName.substring(0, methodName.length() - 9); + + fieldDescriptor = descriptor.findFieldByName(methodName); + + if (fieldDescriptor != null) { + if (args[1].isNil()) { + return setFieldInternal(context, fieldDescriptor, args[1]); + } + + RubyClass typeClass = (RubyClass) ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context); + RubyMessage msg = (RubyMessage) typeClass.newInstance(context, Block.NULL_BLOCK); + msg.indexSet(context, runtime.newString("value"), args[1]); + return setFieldInternal(context, fieldDescriptor, msg); + } + } + } + + return Helpers.invokeSuper(context, this, metaClass, "method_missing", args, Block.NULL_BLOCK); } /** @@ -268,18 +429,15 @@ public IRubyObject methodMissing(ThreadContext context, IRubyObject[] args) { public IRubyObject dup(ThreadContext context) { RubyMessage dup = (RubyMessage) metaClass.newInstance(context, Block.NULL_BLOCK); IRubyObject value; - for (Descriptors.FieldDescriptor fieldDescriptor : this.descriptor.getFields()) { + for (FieldDescriptor fieldDescriptor : this.descriptor.getFields()) { if (fieldDescriptor.isRepeated()) { - dup.addRepeatedField(fieldDescriptor, this.getRepeatedField(context, fieldDescriptor)); + dup.fields.put(fieldDescriptor, this.getRepeatedField(context, fieldDescriptor)); } else if (fields.containsKey(fieldDescriptor)) { dup.fields.put(fieldDescriptor, fields.get(fieldDescriptor)); } else if (this.builder.hasField(fieldDescriptor)) { dup.fields.put(fieldDescriptor, wrapField(context, fieldDescriptor, this.builder.getField(fieldDescriptor))); } } - for (Descriptors.FieldDescriptor fieldDescriptor : maps.keySet()) { - dup.maps.put(fieldDescriptor, maps.get(fieldDescriptor)); - } return dup; } @@ -304,6 +462,9 @@ public static IRubyObject getDescriptor(ThreadContext context, IRubyObject recv) */ @JRubyMethod(meta = true) public static IRubyObject encode(ThreadContext context, IRubyObject recv, IRubyObject value) { + if (recv != value.getMetaClass()) { + throw context.runtime.newArgumentError("Tried to encode a " + value.getMetaClass() + " message with " + recv); + } RubyMessage message = (RubyMessage) value; return context.runtime.newString(new ByteList(message.build(context).toByteArray())); } @@ -323,57 +484,143 @@ public static IRubyObject decode(ThreadContext context, IRubyObject recv, IRubyO try { ret.builder.mergeFrom(bin); } catch (InvalidProtocolBufferException e) { - throw context.runtime.newRuntimeError(e.getMessage()); + throw RaiseException.from(context.runtime, (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::ParseError"), e.getMessage()); + } + + if (!ret.proto3) { + // Need to reset unknown values in repeated enum fields + ret.builder.getUnknownFields().asMap().forEach((i, values) -> { + FieldDescriptor fd = ret.builder.getDescriptorForType().findFieldByNumber(i); + if (fd != null && fd.isRepeated() && fd.getType() == FieldDescriptor.Type.ENUM) { + EnumDescriptor ed = fd.getEnumType(); + values.getVarintList().forEach(value -> { + ret.builder.addRepeatedField(fd, ed.findValueByNumberCreatingIfUnknown(value.intValue())); + }); + } + }); } + return ret; } /* * call-seq: - * MessageClass.encode_json(msg) => json_string + * MessageClass.encode_json(msg, options = {}) => json_string * * Encodes the given message object into its serialized JSON representation. + * @param options [Hash] options for the decoder + * preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase) + * emit_defaults: set true to emit 0/false values (default is to omit them) */ - @JRubyMethod(name = "encode_json", meta = true) - public static IRubyObject encodeJson(ThreadContext context, IRubyObject recv, IRubyObject msgRb) { - RubyMessage message = (RubyMessage) msgRb; - return Helpers.invoke(context, message.toHash(context), "to_json"); + @JRubyMethod(name = "encode_json", required = 1, optional = 1, meta = true) + public static IRubyObject encodeJson(ThreadContext context, IRubyObject recv, IRubyObject[] args) { + Ruby runtime = context.runtime; + RubyMessage message = (RubyMessage) args[0]; + JsonFormat.Printer printer = JsonFormat.printer().omittingInsignificantWhitespace(); + String result; + + if (args.length > 1) { + RubyHash options = (RubyHash) args[1]; + IRubyObject emitDefaults = options.fastARef(runtime.newSymbol("emit_defaults")); + IRubyObject preserveNames = options.fastARef(runtime.newSymbol("preserve_proto_fieldnames")); + + if (emitDefaults != null && emitDefaults.isTrue()) { + printer = printer.includingDefaultValueFields(); + } + + if (preserveNames != null && preserveNames.isTrue()) { + printer = printer.preservingProtoFieldNames(); + } + } + + try { + result = printer.print(message.build(context)); + } catch(InvalidProtocolBufferException e) { + throw runtime.newRuntimeError(e.getMessage()); + } + + return runtime.newString(result); } /* * call-seq: - * MessageClass.decode_json(data) => message + * MessageClass.decode_json(data, options = {}) => message * * Decodes the given data (as a string containing bytes in protocol buffers wire * format) under the interpretration given by this message class's definition * and returns a message object with the corresponding field values. + * + * @param options [Hash] options for the decoder + * ignore_unknown_fields: set true to ignore unknown fields (default is to + * raise an error) */ - @JRubyMethod(name = "decode_json", meta = true) - public static IRubyObject decodeJson(ThreadContext context, IRubyObject recv, IRubyObject json) { + @JRubyMethod(name = "decode_json", required = 1, optional = 1, meta = true) + public static IRubyObject decodeJson(ThreadContext context, IRubyObject recv, IRubyObject[] args) { Ruby runtime = context.runtime; + boolean ignoreUnknownFields = false; + IRubyObject data = args[0]; + JsonFormat.Parser parser = JsonFormat.parser(); + + if (args.length == 2) { + if (!(args[1] instanceof RubyHash)) { + throw runtime.newArgumentError("Expected hash arguments."); + } + + IRubyObject ignoreSetting = ((RubyHash) args[1]).fastARef(runtime.newSymbol("ignore_unknown_fields")); + if (ignoreSetting != null && ignoreSetting.isTrue()) { + parser = parser.ignoringUnknownFields(); + } + } + + if (!(data instanceof RubyString)) { + throw runtime.newArgumentError("Expected string for JSON data."); + } + RubyMessage ret = (RubyMessage) ((RubyClass) recv).newInstance(context, Block.NULL_BLOCK); - RubyModule jsonModule = runtime.getClassFromPath("JSON"); - RubyHash opts = RubyHash.newHash(runtime); - opts.fastASet(runtime.newSymbol("symbolize_names"), runtime.getTrue()); - IRubyObject[] args = new IRubyObject[] { Helpers.invoke(context, jsonModule, "parse", json, opts) }; - ret.initialize(context, args); + + try { + parser.merge(data.asJavaString(), ret.builder); + } catch(InvalidProtocolBufferException e) { + throw createParseError(context, e.getMessage().replace("Cannot find", "No such")); + } + + if (isWrapper(ret.descriptor)) { + throw runtime.newRuntimeError("Parsing a wrapper type from JSON at the top level does not work."); + } + return ret; } - @JRubyMethod(name = {"to_h", "to_hash"}) + @JRubyMethod(name = "to_h") public IRubyObject toHash(ThreadContext context) { Ruby runtime = context.runtime; RubyHash ret = RubyHash.newHash(runtime); - for (Descriptors.FieldDescriptor fdef : this.descriptor.getFields()) { - IRubyObject value = getField(context, fdef); + for (FieldDescriptor fdef : this.descriptor.getFields()) { + IRubyObject value = getFieldInternal(context, fdef, proto3); + if (!value.isNil()) { - if (value.respondsTo("to_h")) { + if (fdef.isRepeated() && !fdef.isMapField()) { + if (!proto3 && ((RubyRepeatedField) value).size() == 0) continue; // Don't output empty repeated fields for proto2 + if (fdef.getType() != FieldDescriptor.Type.MESSAGE) { + value = Helpers.invoke(context, value, "to_a"); + } else { + RubyArray ary = value.convertToArray(); + for (int i = 0; i < ary.size(); i++) { + IRubyObject submsg = Helpers.invoke(context, ary.eltInternal(i), "to_h"); + ary.eltInternalSet(i, submsg); + } + + value = ary.to_ary(); + } + } else if (value.respondsTo("to_h")) { value = Helpers.invoke(context, value, "to_h"); } else if (value.respondsTo("to_a")) { value = Helpers.invoke(context, value, "to_a"); } } - ret.fastASet(runtime.newSymbol(fdef.getName()), value); + if (proto3 || !value.isNil()) { + ret.fastASet(runtime.newSymbol(fdef.getName()), value); + } } return ret; } @@ -386,183 +633,197 @@ protected DynamicMessage build(ThreadContext context, int depth) { if (depth > SINK_MAXIMUM_NESTING) { throw context.runtime.newRuntimeError("Maximum recursion depth exceeded during encoding."); } - for (Descriptors.FieldDescriptor fieldDescriptor : maps.keySet()) { - this.builder.clearField(fieldDescriptor); - RubyDescriptor mapDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor); - for (DynamicMessage kv : maps.get(fieldDescriptor).build(context, mapDescriptor)) { - this.builder.addRepeatedField(fieldDescriptor, kv); - } - } - for (Descriptors.FieldDescriptor fieldDescriptor : repeatedFields.keySet()) { - RubyRepeatedField repeatedField = repeatedFields.get(fieldDescriptor); - this.builder.clearField(fieldDescriptor); - for (int i = 0; i < repeatedField.size(); i++) { - Object item = convert(context, fieldDescriptor, repeatedField.get(i), depth); - this.builder.addRepeatedField(fieldDescriptor, item); - } - } - for (Descriptors.FieldDescriptor fieldDescriptor : fields.keySet()) { + for (FieldDescriptor fieldDescriptor : fields.keySet()) { IRubyObject value = fields.get(fieldDescriptor); - this.builder.setField(fieldDescriptor, convert(context, fieldDescriptor, value, depth)); + + if (value instanceof RubyMap) { + builder.clearField(fieldDescriptor); + RubyDescriptor mapDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor); + for (DynamicMessage kv : ((RubyMap) value).build(context, mapDescriptor, depth)) { + builder.addRepeatedField(fieldDescriptor, kv); + } + + } else if (value instanceof RubyRepeatedField) { + RubyRepeatedField repeatedField = (RubyRepeatedField) value; + + builder.clearField(fieldDescriptor); + for (int i = 0; i < repeatedField.size(); i++) { + Object item = convert(context, fieldDescriptor, repeatedField.get(i), depth); + builder.addRepeatedField(fieldDescriptor, item); + } + + } else { + builder.setField(fieldDescriptor, convert(context, fieldDescriptor, value, depth)); + } } - return this.builder.build(); - } - protected Descriptors.Descriptor getDescriptor() { - return this.descriptor; + return builder.build(); } // Internal use only, called by Google::Protobuf.deep_copy protected IRubyObject deepCopy(ThreadContext context) { RubyMessage copy = (RubyMessage) metaClass.newInstance(context, Block.NULL_BLOCK); - for (Descriptors.FieldDescriptor fdef : this.descriptor.getFields()) { + for (FieldDescriptor fdef : descriptor.getFields()) { if (fdef.isRepeated()) { - copy.addRepeatedField(fdef, this.getRepeatedField(context, fdef).deepCopy(context)); + copy.fields.put(fdef, this.getRepeatedField(context, fdef).deepCopy(context)); } else if (fields.containsKey(fdef)) { copy.fields.put(fdef, fields.get(fdef)); - } else if (this.builder.hasField(fdef)) { - copy.fields.put(fdef, wrapField(context, fdef, this.builder.getField(fdef))); + } else if (builder.hasField(fdef)) { + copy.fields.put(fdef, wrapField(context, fdef, builder.getField(fdef))); } } return copy; } - private RubyRepeatedField getRepeatedField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) { - if (this.repeatedFields.containsKey(fieldDescriptor)) { - return this.repeatedFields.get(fieldDescriptor); + protected IRubyObject clearField(ThreadContext context, FieldDescriptor fieldDescriptor) { + validateMessageType(context, fieldDescriptor, "clear"); + return clearFieldInternal(context, fieldDescriptor); + } + + protected void discardUnknownFields(ThreadContext context) { + discardUnknownFields(context, builder); + } + + protected IRubyObject getField(ThreadContext context, FieldDescriptor fieldDescriptor) { + validateMessageType(context, fieldDescriptor, "get"); + return getFieldInternal(context, fieldDescriptor); + } + + protected IRubyObject hasField(ThreadContext context, FieldDescriptor fieldDescriptor) { + validateMessageType(context, fieldDescriptor, "has?"); + if (!fieldHasPresence(fieldDescriptor)) throw context.runtime.newArgumentError("does not track presence"); + return fields.containsKey(fieldDescriptor) ? context.runtime.getTrue() : context.runtime.getFalse(); + } + + protected IRubyObject setField(ThreadContext context, FieldDescriptor fieldDescriptor, IRubyObject value) { + validateMessageType(context, fieldDescriptor, "set"); + return setFieldInternal(context, fieldDescriptor, value); + } + + private RubyRepeatedField getRepeatedField(ThreadContext context, FieldDescriptor fieldDescriptor) { + if (fields.containsKey(fieldDescriptor)) { + return (RubyRepeatedField) fields.get(fieldDescriptor); } int count = this.builder.getRepeatedFieldCount(fieldDescriptor); RubyRepeatedField ret = repeatedFieldForFieldDescriptor(context, fieldDescriptor); for (int i = 0; i < count; i++) { - ret.push(context, wrapField(context, fieldDescriptor, this.builder.getRepeatedField(fieldDescriptor, i))); + ret.push(context, new IRubyObject[] {wrapField(context, fieldDescriptor, this.builder.getRepeatedField(fieldDescriptor, i))}); } - addRepeatedField(fieldDescriptor, ret); + fields.put(fieldDescriptor, ret); return ret; } - private void addRepeatedField(Descriptors.FieldDescriptor fieldDescriptor, RubyRepeatedField repeatedField) { - this.repeatedFields.put(fieldDescriptor, repeatedField); - } - private IRubyObject buildFrom(ThreadContext context, DynamicMessage dynamicMessage) { this.builder.mergeFrom(dynamicMessage); return this; } - private Descriptors.FieldDescriptor findField(ThreadContext context, IRubyObject fieldName) { - String nameStr = fieldName.asJavaString(); - Descriptors.FieldDescriptor ret = this.descriptor.findFieldByName(Utils.escapeIdentifier(nameStr)); - if (ret == null) - throw context.runtime.newArgumentError("field " + fieldName.asJavaString() + " is not found"); - return ret; + private IRubyObject clearFieldInternal(ThreadContext context, FieldDescriptor fieldDescriptor) { + OneofDescriptor ood = fieldDescriptor.getContainingOneof(); + if (ood != null) oneofCases.remove(ood); + fields.remove(fieldDescriptor); + builder.clearField(fieldDescriptor); + return context.nil; } - private boolean hasField(IRubyObject fieldName) { - String nameStr = fieldName.asJavaString(); - return this.descriptor.findFieldByName(Utils.escapeIdentifier(nameStr)) != null; + private void discardUnknownFields(ThreadContext context, Message.Builder messageBuilder) { + messageBuilder.setUnknownFields(UnknownFieldSet.getDefaultInstance()); + messageBuilder.getAllFields().forEach((fd, value) -> { + if (fd.getType() == FieldDescriptor.Type.MESSAGE) { + if (fd.isRepeated()) { + messageBuilder.clearField(fd); + ((List) value).forEach((val) -> { + Message.Builder submessageBuilder = ((DynamicMessage) val).toBuilder(); + discardUnknownFields(context, submessageBuilder); + messageBuilder.addRepeatedField(fd, submessageBuilder.build()); + }); + } else { + Message.Builder submessageBuilder = ((DynamicMessage) value).toBuilder(); + discardUnknownFields(context, submessageBuilder); + messageBuilder.setField(fd, submessageBuilder.build()); + } + } + }); } - private void checkRepeatedFieldType(ThreadContext context, IRubyObject value, - Descriptors.FieldDescriptor fieldDescriptor) { - Ruby runtime = context.runtime; - if (!(value instanceof RubyRepeatedField)) { - throw runtime.newTypeError("Expected repeated field array"); + private FieldDescriptor findField(ThreadContext context, IRubyObject fieldName) { + return findField(context, fieldName, false); + } + + private FieldDescriptor findField(ThreadContext context, IRubyObject fieldName, boolean ignoreUnknownField) { + String nameStr = fieldName.asJavaString(); + FieldDescriptor ret = this.descriptor.findFieldByName(nameStr); + if (ret == null && !ignoreUnknownField) { + throw context.runtime.newArgumentError("field " + fieldName.asJavaString() + " is not found"); } + return ret; } - // convert a ruby object to protobuf type, with type check + // convert a ruby object to protobuf type, skip type check since it is checked on the way in private Object convert(ThreadContext context, - Descriptors.FieldDescriptor fieldDescriptor, + FieldDescriptor fieldDescriptor, IRubyObject value, int depth) { Ruby runtime = context.runtime; Object val = null; switch (fieldDescriptor.getType()) { case INT32: + val = RubyNumeric.num2int(value); + break; case INT64: + val = RubyNumeric.num2long(value); + break; case UINT32: + val = Utils.num2uint(value); + break; case UINT64: - if (!Utils.isRubyNum(value)) { - throw runtime.newTypeError("Expected number type for integral field."); - } - Utils.checkIntTypePrecision(context, fieldDescriptor.getType(), value); - switch (fieldDescriptor.getType()) { - case INT32: - val = RubyNumeric.num2int(value); - break; - case INT64: - val = RubyNumeric.num2long(value); - break; - case UINT32: - val = Utils.num2uint(value); - break; - case UINT64: - val = Utils.num2ulong(context.runtime, value); - break; - default: - break; - } + val = Utils.num2ulong(context.runtime, value); break; case FLOAT: - if (!Utils.isRubyNum(value)) - throw runtime.newTypeError("Expected number type for float field."); val = (float) RubyNumeric.num2dbl(value); break; case DOUBLE: - if (!Utils.isRubyNum(value)) - throw runtime.newTypeError("Expected number type for double field."); - val = RubyNumeric.num2dbl(value); + val = (double) RubyNumeric.num2dbl(value); break; case BOOL: - if (!(value instanceof RubyBoolean)) - throw runtime.newTypeError("Invalid argument for boolean field."); val = value.isTrue(); break; case BYTES: + val = ByteString.copyFrom(((RubyString) value).getBytes()); + break; case STRING: - Utils.validateStringEncoding(context, fieldDescriptor.getType(), value); - RubyString str = (RubyString) value; - switch (fieldDescriptor.getType()) { - case BYTES: - val = ByteString.copyFrom(str.getBytes()); - break; - case STRING: - val = str.asJavaString(); - break; - default: - break; - } + val = ((RubyString) value).asJavaString(); break; case MESSAGE: - RubyClass typeClass = (RubyClass) ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context); - if (!value.getMetaClass().equals(typeClass)) - throw runtime.newTypeError(value, "Invalid type to assign to submessage field."); val = ((RubyMessage) value).build(context, depth + 1); break; case ENUM: - Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType(); - + EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType(); if (Utils.isRubyNum(value)) { val = enumDescriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value)); - } else if (value instanceof RubySymbol) { - val = enumDescriptor.findValueByName(value.asJavaString()); } else { - throw runtime.newTypeError("Expected number or symbol type for enum field."); - } - if (val == null) { - throw runtime.newRangeError("Enum value " + value + " is not found."); + val = enumDescriptor.findValueByName(value.asJavaString()); } break; default: break; } + return val; } - private IRubyObject wrapField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor, Object value) { + private static RaiseException createParseError(ThreadContext context, String message) { + if (parseErrorClass == null) { + parseErrorClass = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::ParseError"); + } + return RaiseException.from(context.runtime, parseErrorClass, message); + } + + private IRubyObject wrapField(ThreadContext context, FieldDescriptor fieldDescriptor, Object value) { if (value == null) { return context.runtime.getNil(); } Ruby runtime = context.runtime; + switch (fieldDescriptor.getType()) { case INT32: case INT64: @@ -579,7 +840,7 @@ private IRubyObject wrapField(ThreadContext context, Descriptors.FieldDescriptor RubyMessage msg = (RubyMessage) typeClass.newInstance(context, Block.NULL_BLOCK); return msg.buildFrom(context, (DynamicMessage) value); case ENUM: - Descriptors.EnumValueDescriptor enumValueDescriptor = (Descriptors.EnumValueDescriptor) value; + EnumValueDescriptor enumValueDescriptor = (EnumValueDescriptor) value; if (enumValueDescriptor.getIndex() == -1) { // UNKNOWN ENUM VALUE return runtime.newFixnum(enumValueDescriptor.getNumber()); } @@ -589,48 +850,59 @@ private IRubyObject wrapField(ThreadContext context, Descriptors.FieldDescriptor } } - private RubyRepeatedField repeatedFieldForFieldDescriptor(ThreadContext context, - Descriptors.FieldDescriptor fieldDescriptor) { + private RubyRepeatedField repeatedFieldForFieldDescriptor(ThreadContext context, FieldDescriptor fieldDescriptor) { IRubyObject typeClass = context.runtime.getNilClass(); - IRubyObject descriptor = getDescriptorForField(context, fieldDescriptor); - Descriptors.FieldDescriptor.Type type = fieldDescriptor.getType(); - if (type == Descriptors.FieldDescriptor.Type.MESSAGE) { + FieldDescriptor.Type type = fieldDescriptor.getType(); + + if (type == FieldDescriptor.Type.MESSAGE) { typeClass = ((RubyDescriptor) descriptor).msgclass(context); - } else if (type == Descriptors.FieldDescriptor.Type.ENUM) { + } else if (type == FieldDescriptor.Type.ENUM) { typeClass = ((RubyEnumDescriptor) descriptor).enummodule(context); } - return new RubyRepeatedField(context.runtime, cRepeatedField, type, typeClass); + + RubyRepeatedField field = new RubyRepeatedField(context.runtime, cRepeatedField, type, typeClass); + field.setName(fieldDescriptor.getName()); + + return field; } - protected IRubyObject getField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) { - Descriptors.OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof(); + private IRubyObject getFieldInternal(ThreadContext context, FieldDescriptor fieldDescriptor) { + return getFieldInternal(context, fieldDescriptor, true); + } + + private IRubyObject getFieldInternal(ThreadContext context, FieldDescriptor fieldDescriptor, boolean returnDefaults) { + OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof(); if (oneofDescriptor != null) { if (oneofCases.get(oneofDescriptor) == fieldDescriptor) { return fields.get(fieldDescriptor); } else { - Descriptors.FieldDescriptor oneofCase = builder.getOneofFieldDescriptor(oneofDescriptor); + FieldDescriptor oneofCase = builder.getOneofFieldDescriptor(oneofDescriptor); if (oneofCase != fieldDescriptor) { - if (fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.MESSAGE) { - return context.runtime.getNil(); + if (fieldDescriptor.getType() == FieldDescriptor.Type.MESSAGE || !returnDefaults) { + return context.nil; } else { return wrapField(context, fieldDescriptor, fieldDescriptor.getDefaultValue()); } } - IRubyObject value = wrapField(context, oneofCase, builder.getField(oneofCase)); - fields.put(fieldDescriptor, value); - return value; + if (returnDefaults || builder.hasField(fieldDescriptor)) { + IRubyObject value = wrapField(context, oneofCase, builder.getField(oneofCase)); + fields.put(fieldDescriptor, value); + return value; + } else { + return context.nil; + } } } if (Utils.isMapEntry(fieldDescriptor)) { - RubyMap map = maps.get(fieldDescriptor); + RubyMap map = (RubyMap) fields.get(fieldDescriptor); if (map == null) { map = newMapForField(context, fieldDescriptor); int mapSize = this.builder.getRepeatedFieldCount(fieldDescriptor); - Descriptors.FieldDescriptor keyField = fieldDescriptor.getMessageType().findFieldByNumber(1); - Descriptors.FieldDescriptor valueField = fieldDescriptor.getMessageType().findFieldByNumber(2); + FieldDescriptor keyField = fieldDescriptor.getMessageType().findFieldByNumber(1); + FieldDescriptor valueField = fieldDescriptor.getMessageType().findFieldByNumber(2); RubyDescriptor kvDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor); RubyClass kvClass = (RubyClass) kvDescriptor.msgclass(context); for (int i = 0; i < mapSize; i++) { @@ -639,146 +911,234 @@ protected IRubyObject getField(ThreadContext context, Descriptors.FieldDescripto kvMessage.buildFrom(context, message); map.indexSet(context, kvMessage.getField(context, keyField), kvMessage.getField(context, valueField)); } - maps.put(fieldDescriptor, map); + fields.put(fieldDescriptor, map); } return map; } + if (fieldDescriptor.isRepeated()) { return getRepeatedField(context, fieldDescriptor); } - if (fieldDescriptor.getType() != Descriptors.FieldDescriptor.Type.MESSAGE || - this.builder.hasField(fieldDescriptor) || fields.containsKey(fieldDescriptor)) { + + if (fieldDescriptor.getType() != FieldDescriptor.Type.MESSAGE || + builder.hasField(fieldDescriptor) || fields.containsKey(fieldDescriptor)) { if (fields.containsKey(fieldDescriptor)) { return fields.get(fieldDescriptor); - } else { - IRubyObject value = wrapField(context, fieldDescriptor, this.builder.getField(fieldDescriptor)); - if (this.builder.hasField(fieldDescriptor)) { + } else if (returnDefaults || builder.hasField(fieldDescriptor)) { + IRubyObject value = wrapField(context, fieldDescriptor, builder.getField(fieldDescriptor)); + if (builder.hasField(fieldDescriptor)) { fields.put(fieldDescriptor, value); } return value; } } - return context.runtime.getNil(); + return context.nil; } - protected IRubyObject setField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor, IRubyObject value) { + private IRubyObject setFieldInternal(ThreadContext context, FieldDescriptor fieldDescriptor, IRubyObject value) { + testFrozen("can't modify frozen " + getMetaClass()); + if (Utils.isMapEntry(fieldDescriptor)) { if (!(value instanceof RubyMap)) { - throw context.runtime.newTypeError("Expected Map instance"); + throw Utils.createTypeError(context, "Expected Map instance"); } - RubyMap thisMap = (RubyMap) getField(context, fieldDescriptor); + RubyMap thisMap = (RubyMap) getFieldInternal(context, fieldDescriptor); thisMap.mergeIntoSelf(context, value); + } else if (fieldDescriptor.isRepeated()) { - checkRepeatedFieldType(context, value, fieldDescriptor); if (value instanceof RubyRepeatedField) { - addRepeatedField(fieldDescriptor, (RubyRepeatedField) value); + fields.put(fieldDescriptor, value); } else { - RubyArray ary = value.convertToArray(); - RubyRepeatedField repeatedField = rubyToRepeatedField(context, fieldDescriptor, ary); - addRepeatedField(fieldDescriptor, repeatedField); + throw Utils.createTypeError(context, "Expected repeated field array"); } + } else { - Descriptors.OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof(); + boolean addValue = true; + FieldDescriptor.Type fieldType = fieldDescriptor.getType(); + OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof(); + + // Determine the typeclass, if any + IRubyObject typeClass = context.runtime.getObject(); + if (fieldType == FieldDescriptor.Type.MESSAGE) { + typeClass = ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context); + if (value.isNil()){ + addValue = false; + } + } else if (fieldType == FieldDescriptor.Type.ENUM) { + typeClass = ((RubyEnumDescriptor) getDescriptorForField(context, fieldDescriptor)).enummodule(context); + value = enumToSymbol(context, fieldDescriptor.getEnumType(), value); + } + if (oneofDescriptor != null) { - Descriptors.FieldDescriptor oneofCase = oneofCases.get(oneofDescriptor); + FieldDescriptor oneofCase = oneofCases.get(oneofDescriptor); + + // Remove the existing field if we are setting a different field in the Oneof if (oneofCase != null && oneofCase != fieldDescriptor) { fields.remove(oneofCase); } + + // Keep track of what Oneofs are set if (value.isNil()) { oneofCases.remove(oneofDescriptor); - fields.remove(fieldDescriptor); + addValue = false; } else { oneofCases.put(oneofDescriptor, fieldDescriptor); - fields.put(fieldDescriptor, value); } + } + + if (addValue) { + value = Utils.checkType(context, fieldType, fieldDescriptor.getName(), value, (RubyModule) typeClass); + fields.put(fieldDescriptor, value); } else { - Descriptors.FieldDescriptor.Type fieldType = fieldDescriptor.getType(); - IRubyObject typeClass = context.runtime.getObject(); - boolean addValue = true; - if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE) { - typeClass = ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context); - if (value.isNil()){ - addValue = false; - } - } else if (fieldType == Descriptors.FieldDescriptor.Type.ENUM) { - typeClass = ((RubyEnumDescriptor) getDescriptorForField(context, fieldDescriptor)).enummodule(context); - Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType(); - if (Utils.isRubyNum(value)) { - Descriptors.EnumValueDescriptor val = - enumDescriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value)); - if (val.getIndex() != -1) value = context.runtime.newSymbol(val.getName()); - } - } - if (addValue) { - value = Utils.checkType(context, fieldType, value, (RubyModule) typeClass); - this.fields.put(fieldDescriptor, value); - } else { - this.fields.remove(fieldDescriptor); - } + fields.remove(fieldDescriptor); } } - return context.runtime.getNil(); + return context.nil; } - private String layoutInspect() { - ThreadContext context = getRuntime().getCurrentContext(); - StringBuilder sb = new StringBuilder(); - for (Descriptors.FieldDescriptor fdef : descriptor.getFields()) { - sb.append(Utils.unescapeIdentifier(fdef.getName())); - sb.append(": "); - sb.append(getField(context, fdef).inspect()); - sb.append(", "); + private IRubyObject getDescriptorForField(ThreadContext context, FieldDescriptor fieldDescriptor) { + RubyDescriptor thisRbDescriptor = (RubyDescriptor) getDescriptor(context, metaClass); + RubyFieldDescriptor fd = (RubyFieldDescriptor) thisRbDescriptor.lookup(context, context.runtime.newString(fieldDescriptor.getName())); + return fd.getSubtype(context); + } + + private IRubyObject enumToSymbol(ThreadContext context, EnumDescriptor enumDescriptor, IRubyObject value) { + if (value instanceof RubySymbol) { + return (RubySymbol) value; + } else if (Utils.isRubyNum(value)) { + EnumValueDescriptor enumValue = enumDescriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value)); + if (enumValue.getIndex() != -1) { + return context.runtime.newSymbol(enumValue.getName()); + } else { + return value; + } + } else if (value instanceof RubyString) { + return ((RubyString) value).intern(); } - return sb.substring(0, sb.length() - 2); + + return context.runtime.newSymbol("UNKNOWN"); } - private IRubyObject getDescriptorForField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) { - RubyDescriptor thisRbDescriptor = (RubyDescriptor) getDescriptor(context, metaClass); - return thisRbDescriptor.lookup(fieldDescriptor.getName()).getSubType(context); + private boolean fieldHasPresence(FieldDescriptor fieldDescriptor) { + return !fieldDescriptor.isRepeated() && + (fieldDescriptor.getType() == FieldDescriptor.Type.MESSAGE || + fieldDescriptor.getContainingOneof() != null || + !proto3); } private RubyRepeatedField rubyToRepeatedField(ThreadContext context, - Descriptors.FieldDescriptor fieldDescriptor, IRubyObject value) { + FieldDescriptor fieldDescriptor, IRubyObject value) { RubyArray arr = value.convertToArray(); RubyRepeatedField repeatedField = repeatedFieldForFieldDescriptor(context, fieldDescriptor); + IRubyObject[] values = new IRubyObject[arr.size()]; + FieldDescriptor.Type fieldType = fieldDescriptor.getType(); + String fieldName = fieldDescriptor.getName(); + + RubyModule typeClass = null; + if (fieldType == FieldDescriptor.Type.MESSAGE) { + RubyDescriptor descriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor); + typeClass = (RubyModule) descriptor.msgclass(context); + } else if (fieldType == FieldDescriptor.Type.ENUM) { + RubyEnumDescriptor enumDescriptor = (RubyEnumDescriptor) getDescriptorForField(context, fieldDescriptor); + typeClass = (RubyModule) enumDescriptor.enummodule(context); + } + for (int i = 0; i < arr.size(); i++) { - repeatedField.push(context, arr.eltInternal(i)); + IRubyObject item = arr.eltInternal(i); + if (item instanceof RubyHash && typeClass != null) { + values[i] = (IRubyObject) ((RubyClass) typeClass).newInstance(context, item, Block.NULL_BLOCK); + } else { + if (fieldType == FieldDescriptor.Type.ENUM) { + item = enumToSymbol(context, fieldDescriptor.getEnumType(), item); + } + + values[i] = item; + } } + repeatedField.push(context, values); + return repeatedField; } - private RubyMap newMapForField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) { + private RubyMap newMapForField(ThreadContext context, FieldDescriptor fieldDescriptor) { RubyDescriptor mapDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor); - Descriptors.FieldDescriptor keyField = fieldDescriptor.getMessageType().findFieldByNumber(1); - Descriptors.FieldDescriptor valueField = fieldDescriptor.getMessageType().findFieldByNumber(2); + FieldDescriptor keyField = fieldDescriptor.getMessageType().findFieldByNumber(1); + FieldDescriptor valueField = fieldDescriptor.getMessageType().findFieldByNumber(2); IRubyObject keyType = RubySymbol.newSymbol(context.runtime, keyField.getType().name()); IRubyObject valueType = RubySymbol.newSymbol(context.runtime, valueField.getType().name()); - if (valueField.getType() == Descriptors.FieldDescriptor.Type.MESSAGE) { + + if (valueField.getType() == FieldDescriptor.Type.MESSAGE) { RubyFieldDescriptor rubyFieldDescriptor = (RubyFieldDescriptor) mapDescriptor.lookup(context, context.runtime.newString("value")); - RubyDescriptor rubyDescriptor = (RubyDescriptor) rubyFieldDescriptor.getSubType(context); + RubyDescriptor rubyDescriptor = (RubyDescriptor) rubyFieldDescriptor.getSubtype(context); return (RubyMap) cMap.newInstance(context, keyType, valueType, rubyDescriptor.msgclass(context), Block.NULL_BLOCK); + + } else if (valueField.getType() == FieldDescriptor.Type.ENUM) { + RubyFieldDescriptor rubyFieldDescriptor = (RubyFieldDescriptor) mapDescriptor.lookup(context, + context.runtime.newString("value")); + RubyEnumDescriptor rubyEnumDescriptor = (RubyEnumDescriptor) rubyFieldDescriptor.getSubtype(context); + return (RubyMap) cMap.newInstance(context, keyType, valueType, + rubyEnumDescriptor.enummodule(context), Block.NULL_BLOCK); + } else { return (RubyMap) cMap.newInstance(context, keyType, valueType, Block.NULL_BLOCK); } } - private Descriptors.FieldDescriptor getOneofCase(Descriptors.OneofDescriptor oneof) { + private FieldDescriptor getOneofCase(OneofDescriptor oneof) { if (oneofCases.containsKey(oneof)) { return oneofCases.get(oneof); } return builder.getOneofFieldDescriptor(oneof); } - private Descriptors.Descriptor descriptor; + private boolean isWrappable(FieldDescriptor fieldDescriptor) { + if (fieldDescriptor.getType() != FieldDescriptor.Type.MESSAGE) return false; + + return isWrapper(fieldDescriptor.getMessageType()); + } + + private static boolean isWrapper(Descriptor messageDescriptor) { + switch(messageDescriptor.getFullName()) { + case "google.protobuf.DoubleValue": + case "google.protobuf.FloatValue": + case "google.protobuf.Int64Value": + case "google.protobuf.UInt64Value": + case "google.protobuf.Int32Value": + case "google.protobuf.UInt32Value": + case "google.protobuf.BoolValue": + case "google.protobuf.StringValue": + case "google.protobuf.BytesValue": + return true; + default: + return false; + } + } + + private void validateMessageType(ThreadContext context, FieldDescriptor fieldDescriptor, String methodName) { + if (descriptor != fieldDescriptor.getContainingType()) { + throw context.runtime.newTypeError(methodName + " method called on wrong message type"); + } + } + + private static RubyClass parseErrorClass; + + private static final String AS_VALUE_SUFFIX = "_as_value"; + private static final String CLEAR_PREFIX = "clear_"; + private static final String CONST_SUFFIX = "_const"; + private static final String HAS_PREFIX = "has_"; + private static final String QUESTION_MARK = "?"; + private static final int SINK_MAXIMUM_NESTING = 63; + + private Descriptor descriptor; private DynamicMessage.Builder builder; + private Map fields; + private Map oneofCases; private RubyClass cRepeatedField; private RubyClass cMap; - private Map repeatedFields; - private Map maps; - private Map fields; - private Map oneofCases; + private boolean ignoreUnknownFieldsOnInit = false; + private boolean proto3; + - private static final int SINK_MAXIMUM_NESTING = 64; } diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java index a619b803cc664..211236c48a44f 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java @@ -32,7 +32,9 @@ package com.google.protobuf.jruby; -import com.google.protobuf.Descriptors; +import com.google.protobuf.DescriptorProtos.DescriptorProto; +import com.google.protobuf.DescriptorProtos.FieldDescriptorProto; +import com.google.protobuf.DescriptorProtos.OneofDescriptorProto; import org.jruby.*; import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyMethod; @@ -45,52 +47,58 @@ @JRubyClass(name = "MessageBuilderContext") public class RubyMessageBuilderContext extends RubyObject { public static void createRubyMessageBuilderContext(Ruby runtime) { - RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf"); - RubyClass cMessageBuilderContext = protobuf.defineClassUnder("MessageBuilderContext", runtime.getObject(), new ObjectAllocator() { + RubyModule internal = runtime.getClassFromPath("Google::Protobuf::Internal"); + RubyClass cMessageBuilderContext = internal.defineClassUnder("MessageBuilderContext", runtime.getObject(), new ObjectAllocator() { @Override public IRubyObject allocate(Ruby runtime, RubyClass klazz) { return new RubyMessageBuilderContext(runtime, klazz); } }); cMessageBuilderContext.defineAnnotatedMethods(RubyMessageBuilderContext.class); + + cFieldDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::FieldDescriptor"); + cOneofBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Internal::OneofBuilderContext"); } - public RubyMessageBuilderContext(Ruby ruby, RubyClass klazz) { - super(ruby, klazz); + public RubyMessageBuilderContext(Ruby runtime, RubyClass klazz) { + super(runtime, klazz); } @JRubyMethod - public IRubyObject initialize(ThreadContext context, IRubyObject descriptor, IRubyObject rubyBuilder) { - this.cFieldDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::FieldDescriptor"); - this.cDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::Descriptor"); - this.cOneofDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::OneofDescriptor"); - this.cOneofBuilderContext = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::Internal::OneofBuilderContext"); - this.descriptor = (RubyDescriptor) descriptor; - this.builder = (RubyBuilder) rubyBuilder; + public IRubyObject initialize(ThreadContext context, IRubyObject fileBuilderContext, IRubyObject name) { + this.fileBuilderContext = (RubyFileBuilderContext) fileBuilderContext; + this.builder = this.fileBuilderContext.getNewMessageBuilder(); + this.builder.setName(name.asJavaString()); + return this; } /* * call-seq: - * MessageBuilderContext.optional(name, type, number, type_class = nil) + * MessageBuilderContext.optional(name, type, number, type_class = nil, + * options = nil) * * Defines a new optional field on this message type with the given type, tag * number, and type class (for message and enum fields). The type must be a Ruby * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a * string, if present (as accepted by FieldDescriptor#submsg_name=). */ - @JRubyMethod(required = 3, optional = 1) + @JRubyMethod(required = 3, optional = 2) public IRubyObject optional(ThreadContext context, IRubyObject[] args) { - Ruby runtime = context.runtime; - IRubyObject typeClass = runtime.getNil(); - if (args.length > 3) typeClass = args[3]; - msgdefAddField(context, "optional", args[0], args[1], args[2], typeClass); - return context.runtime.getNil(); + addField(context, OPTIONAL, args, false); + return context.nil; + } + + @JRubyMethod(required = 3, optional = 2) + public IRubyObject proto3_optional(ThreadContext context, IRubyObject[] args) { + addField(context, OPTIONAL, args, true); + return context.nil; } /* * call-seq: - * MessageBuilderContext.required(name, type, number, type_class = nil) + * MessageBuilderContext.required(name, type, number, type_class = nil, + * options = nil) * * Defines a new required field on this message type with the given type, tag * number, and type class (for message and enum fields). The type must be a Ruby @@ -101,12 +109,11 @@ public IRubyObject optional(ThreadContext context, IRubyObject[] args) { * completeness. Any attempt to add a message type with required fields to a * pool will currently result in an error. */ - @JRubyMethod(required = 3, optional = 1) + @JRubyMethod(required = 3, optional = 2) public IRubyObject required(ThreadContext context, IRubyObject[] args) { - IRubyObject typeClass = context.runtime.getNil(); - if (args.length > 3) typeClass = args[3]; - msgdefAddField(context, "required", args[0], args[1], args[2], typeClass); - return context.runtime.getNil(); + if (fileBuilderContext.isProto3()) throw Utils.createTypeError(context, "Required fields are unsupported in proto3"); + addField(context, "required", args, false); + return context.nil; } /* @@ -120,10 +127,8 @@ public IRubyObject required(ThreadContext context, IRubyObject[] args) { */ @JRubyMethod(required = 3, optional = 1) public IRubyObject repeated(ThreadContext context, IRubyObject[] args) { - IRubyObject typeClass = context.runtime.getNil(); - if (args.length > 3) typeClass = args[3]; - msgdefAddField(context, "repeated", args[0], args[1], args[2], typeClass); - return context.runtime.getNil(); + addField(context, "repeated", args, false); + return context.nil; } /* @@ -141,77 +146,110 @@ public IRubyObject repeated(ThreadContext context, IRubyObject[] args) { @JRubyMethod(required = 4, optional = 1) public IRubyObject map(ThreadContext context, IRubyObject[] args) { Ruby runtime = context.runtime; + if (!fileBuilderContext.isProto3()) throw runtime.newArgumentError("Cannot add a native map field using proto2 syntax."); + + RubySymbol messageSym = runtime.newSymbol("message"); + IRubyObject name = args[0]; IRubyObject keyType = args[1]; IRubyObject valueType = args[2]; IRubyObject number = args[3]; - IRubyObject typeClass = args.length > 4 ? args[4] : context.runtime.getNil(); + IRubyObject typeClass = args.length > 4 ? args[4] : context.nil; // Validate the key type. We can't accept enums, messages, or floats/doubles // as map keys. (We exclude these explicitly, and the field-descriptor setter // below then ensures that the type is one of the remaining valid options.) - if (keyType.equals(RubySymbol.newSymbol(runtime, "float")) || - keyType.equals(RubySymbol.newSymbol(runtime, "double")) || - keyType.equals(RubySymbol.newSymbol(runtime, "enum")) || - keyType.equals(RubySymbol.newSymbol(runtime, "message"))) + if (keyType.equals(runtime.newSymbol("float")) || + keyType.equals(runtime.newSymbol("double")) || + keyType.equals(runtime.newSymbol("enum")) || + keyType.equals(messageSym)) throw runtime.newArgumentError("Cannot add a map field with a float, double, enum, or message type."); - // Create a new message descriptor for the map entry message, and create a - // repeated submessage field here with that type. - RubyDescriptor mapentryDesc = (RubyDescriptor) cDescriptor.newInstance(context, Block.NULL_BLOCK); - IRubyObject mapentryDescName = RubySymbol.newSymbol(runtime, name).id2name(context); - mapentryDesc.setName(context, mapentryDescName); - mapentryDesc.setMapEntry(true); - - //optional key = 1; - RubyFieldDescriptor keyField = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK); - keyField.setName(context, runtime.newString("key")); - keyField.setLabel(context, RubySymbol.newSymbol(runtime, "optional")); - keyField.setNumber(context, runtime.newFixnum(1)); - keyField.setType(context, keyType); - mapentryDesc.addField(context, keyField); - - //optional value = 2; - RubyFieldDescriptor valueField = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK); - valueField.setName(context, runtime.newString("value")); - valueField.setLabel(context, RubySymbol.newSymbol(runtime, "optional")); - valueField.setNumber(context, runtime.newFixnum(2)); - valueField.setType(context, valueType); - if (! typeClass.isNil()) valueField.setSubmsgName(context, typeClass); - mapentryDesc.addField(context, valueField); - - // Add the map-entry message type to the current builder, and use the type to - // create the map field itself. - this.builder.pendingList.add(mapentryDesc); - - msgdefAddField(context, "repeated", name, runtime.newSymbol("message"), number, mapentryDescName); - return runtime.getNil(); + DescriptorProto.Builder mapEntryBuilder = fileBuilderContext.getNewMessageBuilder(); + mapEntryBuilder.setName(builder.getName() + "_MapEntry_" + name.asJavaString()); + mapEntryBuilder.getOptionsBuilder().setMapEntry(true); + + mapEntryBuilder.addField( + Utils.createFieldBuilder( + context, + OPTIONAL, + new IRubyObject[] { + runtime.newString("key"), + keyType, + runtime.newFixnum(1) + } + ) + ); + + mapEntryBuilder.addField( + Utils.createFieldBuilder( + context, + OPTIONAL, + new IRubyObject[] { + runtime.newString("value"), + valueType, + runtime.newFixnum(2), + typeClass + } + ) + ); + + IRubyObject[] addFieldArgs = { + name, messageSym, number, runtime.newString(mapEntryBuilder.getName()) + }; + + repeated(context, addFieldArgs); + + return context.nil; } + /* + * call-seq: + * MessageBuilderContext.oneof(name, &block) => nil + * + * Creates a new OneofDescriptor with the given name, creates a + * OneofBuilderContext attached to that OneofDescriptor, evaluates the given + * block in the context of that OneofBuilderContext with #instance_eval, and + * then adds the oneof to the message. + * + * This is the recommended, idiomatic way to build oneof definitions. + */ @JRubyMethod public IRubyObject oneof(ThreadContext context, IRubyObject name, Block block) { - RubyOneofDescriptor oneofdef = (RubyOneofDescriptor) - cOneofDescriptor.newInstance(context, Block.NULL_BLOCK); RubyOneofBuilderContext ctx = (RubyOneofBuilderContext) - cOneofBuilderContext.newInstance(context, oneofdef, Block.NULL_BLOCK); - oneofdef.setName(context, name); - Binding binding = block.getBinding(); - binding.setSelf(ctx); - block.yieldSpecific(context); - descriptor.addOneof(context, oneofdef); - return context.runtime.getNil(); + cOneofBuilderContext.newInstance( + context, + context.runtime.newFixnum(builder.getOneofDeclCount()), + this, + Block.NULL_BLOCK + ); + + builder.addOneofDeclBuilder().setName(name.asJavaString()); + ctx.instance_eval(context, block); + + return context.nil; } - private void msgdefAddField(ThreadContext context, String label, IRubyObject name, - IRubyObject type, IRubyObject number, IRubyObject typeClass) { - descriptor.addField(context, - Utils.msgdefCreateField(context, label, name, type, number, typeClass, cFieldDescriptor)); + protected void addFieldBuilder(FieldDescriptorProto.Builder fieldBuilder) { + builder.addField(fieldBuilder); } - private RubyDescriptor descriptor; - private RubyBuilder builder; - private RubyClass cFieldDescriptor; - private RubyClass cOneofDescriptor; - private RubyClass cOneofBuilderContext; + private FieldDescriptorProto.Builder addField(ThreadContext context, String label, IRubyObject[] args, boolean proto3Optional) { + FieldDescriptorProto.Builder fieldBuilder = + Utils.createFieldBuilder(context, label, args); + + fieldBuilder.setProto3Optional(proto3Optional); + builder.addField(fieldBuilder); + + return fieldBuilder; + } + + private static RubyClass cFieldDescriptor; + private static RubyClass cOneofBuilderContext; + + private static final String OPTIONAL = "optional"; + + private DescriptorProto.Builder builder; private RubyClass cDescriptor; + private RubyFileBuilderContext fileBuilderContext; } diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java index c9b99e0489d83..1ce500e3aab3a 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java @@ -32,9 +32,12 @@ package com.google.protobuf.jruby; +import com.google.protobuf.DescriptorProtos.FieldDescriptorProto; import org.jruby.Ruby; import org.jruby.RubyClass; +import org.jruby.RubyHash; import org.jruby.RubyModule; +import org.jruby.RubyNumeric; import org.jruby.RubyObject; import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyMethod; @@ -45,8 +48,7 @@ @JRubyClass(name = "OneofBuilderContext") public class RubyOneofBuilderContext extends RubyObject { public static void createRubyOneofBuilderContext(Ruby runtime) { - RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf"); - RubyModule internal = protobuf.defineModuleUnder("Internal"); + RubyModule internal = runtime.getClassFromPath("Google::Protobuf::Internal"); RubyClass cRubyOneofBuidlerContext = internal.defineClassUnder("OneofBuilderContext", runtime.getObject(), new ObjectAllocator() { @Override public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) { @@ -60,25 +62,42 @@ public RubyOneofBuilderContext(Ruby ruby, RubyClass rubyClass) { super(ruby, rubyClass); } + /* + * call-seq: + * OneofBuilderContext.new(oneof_index, message_builder) => context + * + * Create a new oneof builder context around the given oneof descriptor and + * builder context. This class is intended to serve as a DSL context to be used + * with #instance_eval. + */ @JRubyMethod - public IRubyObject initialize(ThreadContext context, IRubyObject oneofdef) { - this.descriptor = (RubyOneofDescriptor) oneofdef; - this.cFieldDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::FieldDescriptor"); + public IRubyObject initialize(ThreadContext context, IRubyObject index, IRubyObject messageBuilder) { + this.builder = (RubyMessageBuilderContext) messageBuilder; + this.index = RubyNumeric.num2int(index); + return this; } - @JRubyMethod(required = 3, optional = 1) + /* + * call-seq: + * OneofBuilderContext.optional(name, type, number, type_class = nil, + * options = nil) + * + * Defines a new optional field in this oneof with the given type, tag number, + * and type class (for message and enum fields). The type must be a Ruby symbol + * (as accepted by FieldDescriptor#type=) and the type_class must be a string, + * if present (as accepted by FieldDescriptor#submsg_name=). + */ + @JRubyMethod(required = 3, optional = 2) public IRubyObject optional(ThreadContext context, IRubyObject[] args) { - IRubyObject name = args[0]; - IRubyObject type = args[1]; - IRubyObject number = args[2]; - IRubyObject typeClass = args.length > 3 ? args[3] : context.runtime.getNil(); - RubyFieldDescriptor fieldDescriptor = Utils.msgdefCreateField(context, "optional", - name, type, number, typeClass, cFieldDescriptor); - descriptor.addField(context, fieldDescriptor); - return this; + FieldDescriptorProto.Builder fieldBuilder = + Utils.createFieldBuilder(context, "optional", args); + fieldBuilder.setOneofIndex(index); + builder.addFieldBuilder(fieldBuilder); + + return context.nil; } - private RubyOneofDescriptor descriptor; - private RubyClass cFieldDescriptor; + private RubyMessageBuilderContext builder; + private int index; } diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java index cc4ab662846c4..6f2ebdb45f27c 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java @@ -1,7 +1,7 @@ package com.google.protobuf.jruby; -import com.google.protobuf.DescriptorProtos; -import com.google.protobuf.Descriptors; +import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Descriptors.OneofDescriptor; import org.jruby.Ruby; import org.jruby.RubyClass; import org.jruby.RubyModule; @@ -13,7 +13,10 @@ import org.jruby.runtime.ThreadContext; import org.jruby.runtime.builtin.IRubyObject; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; @JRubyClass(name = "OneofDescriptor", include = "Enumerable") public class RubyOneofDescriptor extends RubyObject { @@ -32,13 +35,7 @@ public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) { public RubyOneofDescriptor(Ruby ruby, RubyClass rubyClass) { super(ruby, rubyClass); - } - - @JRubyMethod - public IRubyObject initialize(ThreadContext context) { - builder = DescriptorProtos.OneofDescriptorProto.newBuilder(); fields = new ArrayList(); - return this; } /* @@ -52,42 +49,6 @@ public IRubyObject getName(ThreadContext context) { return name; } - /* - * call-seq: - * OneofDescriptor.name = name - * - * Sets a new name for this oneof. The oneof must not have been added to a - * message descriptor yet. - */ - @JRubyMethod(name = "name=") - public IRubyObject setName(ThreadContext context, IRubyObject name) { - this.name = context.runtime.newString(name.asJavaString()); - this.builder.setName(name.asJavaString()); - return context.runtime.getNil(); - } - - /* - * call-seq: - * OneofDescriptor.add_field(field) => nil - * - * Adds a field to this oneof. The field may have been added to this oneof in - * the past, or the message to which this oneof belongs (if any), but may not - * have already been added to any other oneof or message. Otherwise, an - * exception is raised. - * - * All fields added to the oneof via this method will be automatically added to - * the message to which this oneof belongs, if it belongs to one currently, or - * else will be added to any message to which the oneof is later added at the - * time that it is added. - */ - @JRubyMethod(name = "add_field") - public IRubyObject addField(ThreadContext context, IRubyObject obj) { - RubyFieldDescriptor fieldDescriptor = (RubyFieldDescriptor) obj; - fieldDescriptor.setOneofName(this.name); - fields.add(fieldDescriptor); - return context.runtime.getNil(); - } - /* * call-seq: * OneofDescriptor.each(&block) => nil @@ -99,26 +60,27 @@ public IRubyObject each(ThreadContext context, Block block) { for (RubyFieldDescriptor field : fields) { block.yieldSpecific(context, field); } - return context.runtime.getNil(); - } - - public DescriptorProtos.OneofDescriptorProto build(int index) { - for (RubyFieldDescriptor field: fields) { - field.setOneofIndex(index); - } - return this.builder.build(); + return context.nil; } protected Collection getFields() { return fields; } - protected Descriptors.OneofDescriptor getOneofDescriptor() { - RubyFieldDescriptor fieldDescriptor = fields.get(0); - return fieldDescriptor.getFieldDef().getContainingOneof(); + protected OneofDescriptor getDescriptor() { + return descriptor; + } + + protected void setDescriptor(ThreadContext context, OneofDescriptor descriptor, Map fieldCache) { + this.descriptor = descriptor; + this.name = context.runtime.newString(descriptor.getName()); + + for (FieldDescriptor fd : descriptor.getFields()) { + fields.add(fieldCache.get(fd)); + } } private IRubyObject name; - private DescriptorProtos.OneofDescriptorProto.Builder builder; private List fields; + private OneofDescriptor descriptor; } diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java index 2cf210d26f585..582c675b2b2ee 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java @@ -46,6 +46,7 @@ public static void createProtobuf(Ruby runtime) { RubyModule mGoogle = runtime.getModule("Google"); RubyModule mProtobuf = mGoogle.defineModuleUnder("Protobuf"); mProtobuf.defineAnnotatedMethods(RubyProtobuf.class); + RubyModule mInternal = mProtobuf.defineModuleUnder("Internal"); } /* @@ -65,4 +66,17 @@ public static IRubyObject deepCopy(ThreadContext context, IRubyObject self, IRub return ((RubyMap) message).deepCopy(context); } } + + /* + * call-seq: + * Google::Protobuf.discard_unknown(msg) + * + * Discard unknown fields in the given message object and recursively discard + * unknown fields in submessages. + */ + @JRubyMethod(name = "discard_unknown", meta = true) + public static IRubyObject discardUnknown(ThreadContext context, IRubyObject self, IRubyObject message) { + ((RubyMessage) message).discardUnknownFields(context); + return context.nil; + } } diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java index ae2907a98501c..995171fc7b2e4 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java @@ -32,7 +32,7 @@ package com.google.protobuf.jruby; -import com.google.protobuf.Descriptors; +import com.google.protobuf.Descriptors.FieldDescriptor; import org.jruby.*; import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyMethod; @@ -61,7 +61,7 @@ public RubyRepeatedField(Ruby runtime, RubyClass klazz) { super(runtime, klazz); } - public RubyRepeatedField(Ruby runtime, RubyClass klazz, Descriptors.FieldDescriptor.Type fieldType, IRubyObject typeClass) { + public RubyRepeatedField(Ruby runtime, RubyClass klazz, FieldDescriptor.Type fieldType, IRubyObject typeClass) { this(runtime, klazz); this.fieldType = fieldType; this.storage = runtime.newArray(); @@ -77,8 +77,8 @@ public IRubyObject initialize(ThreadContext context, IRubyObject[] args) { throw runtime.newArgumentError("Expected Symbol for type name"); } this.fieldType = Utils.rubyToFieldType(args[0]); - if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE - || fieldType == Descriptors.FieldDescriptor.Type.ENUM) { + if (fieldType == FieldDescriptor.Type.MESSAGE + || fieldType == FieldDescriptor.Type.ENUM) { if (args.length < 2) throw runtime.newArgumentError("Expected at least 2 arguments for message/enum"); typeClass = args[1]; @@ -110,7 +110,7 @@ public IRubyObject initialize(ThreadContext context, IRubyObject[] args) { @JRubyMethod(name = "[]=") public IRubyObject indexSet(ThreadContext context, IRubyObject index, IRubyObject value) { int arrIndex = normalizeArrayIndex(index); - value = Utils.checkType(context, fieldType, value, (RubyModule) typeClass); + value = Utils.checkType(context, fieldType, name, value, (RubyModule) typeClass); IRubyObject defaultValue = defaultValue(context); for (int i = this.storage.size(); i < arrIndex; i++) { this.storage.set(i, defaultValue); @@ -138,9 +138,12 @@ public IRubyObject index(ThreadContext context, IRubyObject[] args) { return this.storage.eltInternal(arrIndex); } else if (arg instanceof RubyRange) { RubyRange range = ((RubyRange) arg); + int beg = RubyNumeric.num2int(range.first(context)); - int to = RubyNumeric.num2int(range.last(context)); - int len = to - beg + 1; + int len = RubyNumeric.num2int(range.size(context)); + + if (len == 0) return context.runtime.newEmptyArray(); + return this.storage.subseq(beg, len); } } @@ -162,14 +165,17 @@ public IRubyObject index(ThreadContext context, IRubyObject[] args) { * * Adds a new element to the repeated field. */ - @JRubyMethod(name = {"push", "<<"}) - public IRubyObject push(ThreadContext context, IRubyObject value) { - if (!(fieldType == Descriptors.FieldDescriptor.Type.MESSAGE && - value == context.runtime.getNil())) { - value = Utils.checkType(context, fieldType, value, (RubyModule) typeClass); + @JRubyMethod(name = {"push", "<<"}, required = 1, rest = true) + public IRubyObject push(ThreadContext context, IRubyObject[] args) { + for (int i = 0; i < args.length; i++) { + IRubyObject val = args[i]; + if (fieldType != FieldDescriptor.Type.MESSAGE || !val.isNil()) { + val = Utils.checkType(context, fieldType, name, val, (RubyModule) typeClass); + } + storage.add(val); } - this.storage.add(value); - return this.storage; + + return this; } /* @@ -193,7 +199,7 @@ public IRubyObject replace(ThreadContext context, IRubyObject list) { RubyArray arr = (RubyArray) list; checkArrayElementType(context, arr); this.storage = arr; - return this.storage; + return this; } /* @@ -205,7 +211,7 @@ public IRubyObject replace(ThreadContext context, IRubyObject list) { @JRubyMethod public IRubyObject clear(ThreadContext context) { this.storage.clear(); - return this.storage; + return this; } /* @@ -261,7 +267,7 @@ public IRubyObject concat(ThreadContext context, IRubyObject list) { throw context.runtime.newArgumentError("Attempt to append RepeatedField with different element type."); this.storage.addAll((RubyArray) repeatedField.toArray(context)); } - return this.storage; + return this; } /* @@ -301,7 +307,7 @@ public IRubyObject eq(ThreadContext context, IRubyObject other) { @JRubyMethod public IRubyObject each(ThreadContext context, Block block) { this.storage.each(context, block); - return this.storage; + return this; } @@ -320,12 +326,15 @@ public IRubyObject toArray(ThreadContext context) { @JRubyMethod public IRubyObject dup(ThreadContext context) { RubyRepeatedField dup = new RubyRepeatedField(context.runtime, metaClass, fieldType, typeClass); - for (int i = 0; i < this.storage.size(); i++) { - dup.push(context, this.storage.eltInternal(i)); - } + dup.push(context, storage.toJavaArray()); return dup; } + @JRubyMethod + public IRubyObject inspect() { + return storage.inspect(); + } + // Java API protected IRubyObject get(int index) { return this.storage.eltInternal(index); @@ -335,7 +344,7 @@ protected RubyRepeatedField deepCopy(ThreadContext context) { RubyRepeatedField copy = new RubyRepeatedField(context.runtime, metaClass, fieldType, typeClass); for (int i = 0; i < size(); i++) { IRubyObject value = storage.eltInternal(i); - if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE) { + if (fieldType == FieldDescriptor.Type.MESSAGE) { copy.storage.add(((RubyMessage) value).deepCopy(context)); } else { copy.storage.add(value); @@ -344,6 +353,10 @@ protected RubyRepeatedField deepCopy(ThreadContext context) { return copy; } + protected void setName(String name) { + this.name = name; + } + protected int size() { return this.storage.size(); } @@ -390,7 +403,7 @@ private IRubyObject defaultValue(ThreadContext context) { private void checkArrayElementType(ThreadContext context, RubyArray arr) { for (int i = 0; i < arr.getLength(); i++) { - Utils.checkType(context, fieldType, arr.eltInternal(i), (RubyModule) typeClass); + Utils.checkType(context, fieldType, name, arr.eltInternal(i), (RubyModule) typeClass); } } @@ -403,7 +416,8 @@ private int normalizeArrayIndex(IRubyObject index) { return arrIndex; } - private RubyArray storage; - private Descriptors.FieldDescriptor.Type fieldType; + private FieldDescriptor.Type fieldType; private IRubyObject typeClass; + private RubyArray storage; + private String name; } diff --git a/ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java b/ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java index 54f2c729a2695..b3f23c5d35881 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java @@ -204,7 +204,7 @@ public java.lang.String getDefaultString() { if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { - com.google.protobuf.ByteString bs = + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { @@ -220,7 +220,7 @@ public java.lang.String getDefaultString() { getDefaultStringBytes() { java.lang.Object ref = defaultString_; if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = + com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); defaultString_ = b; @@ -432,7 +432,7 @@ public int getDefaultInt32() { * optional int32 default_int32 = 1; */ public Builder setDefaultInt32(int value) { - + defaultInt32_ = value; onChanged(); return this; @@ -441,7 +441,7 @@ public Builder setDefaultInt32(int value) { * optional int32 default_int32 = 1; */ public Builder clearDefaultInt32() { - + defaultInt32_ = 0; onChanged(); return this; @@ -458,7 +458,7 @@ public long getDefaultInt64() { * optional int64 default_int64 = 2; */ public Builder setDefaultInt64(long value) { - + defaultInt64_ = value; onChanged(); return this; @@ -467,7 +467,7 @@ public Builder setDefaultInt64(long value) { * optional int64 default_int64 = 2; */ public Builder clearDefaultInt64() { - + defaultInt64_ = 0L; onChanged(); return this; @@ -484,7 +484,7 @@ public int getDefaultUnit32() { * optional uint32 default_unit32 = 3; */ public Builder setDefaultUnit32(int value) { - + defaultUnit32_ = value; onChanged(); return this; @@ -493,7 +493,7 @@ public Builder setDefaultUnit32(int value) { * optional uint32 default_unit32 = 3; */ public Builder clearDefaultUnit32() { - + defaultUnit32_ = 0; onChanged(); return this; @@ -510,7 +510,7 @@ public long getDefaultUint64() { * optional uint64 default_uint64 = 4; */ public Builder setDefaultUint64(long value) { - + defaultUint64_ = value; onChanged(); return this; @@ -519,7 +519,7 @@ public Builder setDefaultUint64(long value) { * optional uint64 default_uint64 = 4; */ public Builder clearDefaultUint64() { - + defaultUint64_ = 0L; onChanged(); return this; @@ -550,7 +550,7 @@ public java.lang.String getDefaultString() { getDefaultStringBytes() { java.lang.Object ref = defaultString_; if (ref instanceof String) { - com.google.protobuf.ByteString b = + com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (java.lang.String) ref); defaultString_ = b; @@ -567,7 +567,7 @@ public Builder setDefaultString( if (value == null) { throw new NullPointerException(); } - + defaultString_ = value; onChanged(); return this; @@ -576,7 +576,7 @@ public Builder setDefaultString( * optional string default_string = 5; */ public Builder clearDefaultString() { - + defaultString_ = getDefaultInstance().getDefaultString(); onChanged(); return this; @@ -589,7 +589,7 @@ public Builder setDefaultStringBytes( if (value == null) { throw new NullPointerException(); } - + defaultString_ = value; onChanged(); return this; @@ -606,7 +606,7 @@ public boolean getDefaultBool() { * optional bool default_bool = 6; */ public Builder setDefaultBool(boolean value) { - + defaultBool_ = value; onChanged(); return this; @@ -615,7 +615,7 @@ public Builder setDefaultBool(boolean value) { * optional bool default_bool = 6; */ public Builder clearDefaultBool() { - + defaultBool_ = false; onChanged(); return this; @@ -632,7 +632,7 @@ public float getDefaultFloat() { * optional float default_float = 7; */ public Builder setDefaultFloat(float value) { - + defaultFloat_ = value; onChanged(); return this; @@ -641,7 +641,7 @@ public Builder setDefaultFloat(float value) { * optional float default_float = 7; */ public Builder clearDefaultFloat() { - + defaultFloat_ = 0F; onChanged(); return this; @@ -658,7 +658,7 @@ public double getDefaultDouble() { * optional double default_double = 8; */ public Builder setDefaultDouble(double value) { - + defaultDouble_ = value; onChanged(); return this; @@ -667,7 +667,7 @@ public Builder setDefaultDouble(double value) { * optional double default_double = 8; */ public Builder clearDefaultDouble() { - + defaultDouble_ = 0D; onChanged(); return this; @@ -687,7 +687,7 @@ public Builder setDefaultBytes(com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } - + defaultBytes_ = value; onChanged(); return this; @@ -696,7 +696,7 @@ public Builder setDefaultBytes(com.google.protobuf.ByteString value) { * optional bytes default_bytes = 9; */ public Builder clearDefaultBytes() { - + defaultBytes_ = getDefaultInstance().getDefaultBytes(); onChanged(); return this; diff --git a/ruby/src/main/java/com/google/protobuf/jruby/Utils.java b/ruby/src/main/java/com/google/protobuf/jruby/Utils.java index f199feb962ec8..17c1c8d7bc869 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/Utils.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/Utils.java @@ -33,29 +33,30 @@ package com.google.protobuf.jruby; import com.google.protobuf.ByteString; -import com.google.protobuf.DescriptorProtos; -import com.google.protobuf.Descriptors; +import com.google.protobuf.DescriptorProtos.FieldDescriptorProto; +import com.google.protobuf.Descriptors.FieldDescriptor; import org.jcodings.Encoding; import org.jcodings.specific.ASCIIEncoding; -import org.jcodings.specific.USASCIIEncoding; -import org.jcodings.specific.UTF8Encoding; import org.jruby.*; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.bigdecimal.RubyBigDecimal; import org.jruby.runtime.Block; +import org.jruby.runtime.Helpers; import org.jruby.runtime.ThreadContext; import org.jruby.runtime.builtin.IRubyObject; import java.math.BigInteger; public class Utils { - public static Descriptors.FieldDescriptor.Type rubyToFieldType(IRubyObject typeClass) { - return Descriptors.FieldDescriptor.Type.valueOf(typeClass.asJavaString().toUpperCase()); + public static FieldDescriptor.Type rubyToFieldType(IRubyObject typeClass) { + return FieldDescriptor.Type.valueOf(typeClass.asJavaString().toUpperCase()); } - public static IRubyObject fieldTypeToRuby(ThreadContext context, Descriptors.FieldDescriptor.Type type) { + public static IRubyObject fieldTypeToRuby(ThreadContext context, FieldDescriptor.Type type) { return fieldTypeToRuby(context, type.name()); } - public static IRubyObject fieldTypeToRuby(ThreadContext context, DescriptorProtos.FieldDescriptorProto.Type type) { + public static IRubyObject fieldTypeToRuby(ThreadContext context, FieldDescriptorProto.Type type) { return fieldTypeToRuby(context, type.name()); } @@ -64,64 +65,115 @@ private static IRubyObject fieldTypeToRuby(ThreadContext context, String typeNam return context.runtime.newSymbol(typeName.replace("TYPE_", "").toLowerCase()); } - public static IRubyObject checkType(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType, - IRubyObject value, RubyModule typeClass) { + public static IRubyObject checkType(ThreadContext context, FieldDescriptor.Type fieldType, + String fieldName, IRubyObject value, RubyModule typeClass) { Ruby runtime = context.runtime; - Object val; + switch(fieldType) { case INT32: case INT64: case UINT32: case UINT64: - if (!isRubyNum(value)) { - throw runtime.newTypeError("Expected number type for integral field."); + if (!isRubyNum(value)) + throw createExpectedTypeError(context, "number", "integral", fieldName, value); + + if (value instanceof RubyFloat) { + double doubleVal = RubyNumeric.num2dbl(value); + if (Math.floor(doubleVal) != doubleVal) { + throw runtime.newRangeError("Non-integral floating point value assigned to integer field '" + fieldName + "' (given " + value.getMetaClass() + ")."); + } + } + if (fieldType == FieldDescriptor.Type.UINT32 || fieldType == FieldDescriptor.Type.UINT64) { + if (((RubyNumeric) value).isNegative()) { + throw runtime.newRangeError("Assigning negative value to unsigned integer field '" + fieldName + "' (given " + value.getMetaClass() + ")."); + } } + switch(fieldType) { case INT32: RubyNumeric.num2int(value); break; - case INT64: - RubyNumeric.num2long(value); - break; case UINT32: num2uint(value); break; - default: + case UINT64: num2ulong(context.runtime, value); break; + default: + RubyNumeric.num2long(value); + break; } - checkIntTypePrecision(context, fieldType, value); break; case FLOAT: if (!isRubyNum(value)) - throw runtime.newTypeError("Expected number type for float field."); + throw createExpectedTypeError(context, "number", "float", fieldName, value); break; case DOUBLE: if (!isRubyNum(value)) - throw runtime.newTypeError("Expected number type for double field."); + throw createExpectedTypeError(context, "number", "double", fieldName, value); break; case BOOL: if (!(value instanceof RubyBoolean)) - throw runtime.newTypeError("Invalid argument for boolean field."); + throw createInvalidTypeError(context, "boolean", fieldName, value); break; case BYTES: + value = validateAndEncodeString(context, "bytes", fieldName, value, "Encoding::ASCII_8BIT"); + break; case STRING: - value = validateStringEncoding(context, fieldType, value); + value = validateAndEncodeString(context, "string", fieldName, symToString(value), "Encoding::UTF_8"); break; case MESSAGE: if (value.getMetaClass() != typeClass) { - throw runtime.newTypeError(value, typeClass); + // See if we can convert the value before flagging it as invalid + String className = typeClass.getName(); + + if (className.equals("Google::Protobuf::Timestamp") && value instanceof RubyTime) { + RubyTime rt = (RubyTime) value; + RubyHash timestampArgs = + Helpers.constructHash(runtime, + runtime.newString("nanos"), rt.nsec(), false, + runtime.newString("seconds"), rt.to_i(), false); + return ((RubyClass) typeClass).newInstance(context, timestampArgs, Block.NULL_BLOCK); + + } else if (className.equals("Google::Protobuf::Duration") && value instanceof RubyNumeric) { + IRubyObject seconds; + if (value instanceof RubyFloat) { + seconds = ((RubyFloat) value).truncate(context); + } else if (value instanceof RubyRational) { + seconds = ((RubyRational) value).to_i(context); + } else if (value instanceof RubyBigDecimal) { + seconds = ((RubyBigDecimal) value).to_int(context); + } else { + seconds = ((RubyInteger) value).to_i(); + } + + IRubyObject nanos = ((RubyNumeric) value).remainder(context, RubyFixnum.one(runtime)); + if (nanos instanceof RubyFloat) { + nanos = ((RubyFloat) nanos).op_mul(context, 1000000000); + } else if (nanos instanceof RubyRational) { + nanos = ((RubyRational) nanos).op_mul(context, runtime.newFixnum(1000000000)); + } else if (nanos instanceof RubyBigDecimal) { + nanos = ((RubyBigDecimal) nanos).op_mul(context, runtime.newFixnum(1000000000)); + } else { + nanos = ((RubyInteger) nanos).op_mul(context, 1000000000); + } + + RubyHash durationArgs = + Helpers.constructHash(runtime, + runtime.newString("nanos"), ((RubyNumeric) nanos).round(context), false, + runtime.newString("seconds"), seconds, false); + return ((RubyClass) typeClass).newInstance(context, durationArgs, Block.NULL_BLOCK); + } + + // Not able to convert so flag as invalid + throw createTypeError(context, "Invalid type " + value.getMetaClass() + " to assign to submessage field '" + fieldName + "'."); } + break; case ENUM: - if (value instanceof RubySymbol) { - Descriptors.EnumDescriptor enumDescriptor = - ((RubyEnumDescriptor) typeClass.getInstanceVariable(DESCRIPTOR_INSTANCE_VAR)).getDescriptor(); - val = enumDescriptor.findValueByName(value.asJavaString()); - if (val == null) - throw runtime.newRangeError("Enum value " + value + " is not found."); - } else if(!isRubyNum(value)) { - throw runtime.newTypeError("Expected number or symbol type for enum field."); + boolean isValid = ((RubyEnumDescriptor) typeClass.getInstanceVariable(DESCRIPTOR_INSTANCE_VAR)).isValidValue(context, value); + if (!isValid) { + throw runtime.newRangeError("Unknown symbol value for enum field '" + fieldName + "'."); } break; default: @@ -130,7 +182,7 @@ public static IRubyObject checkType(ThreadContext context, Descriptors.FieldDesc return value; } - public static IRubyObject wrapPrimaryValue(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType, Object value) { + public static IRubyObject wrapPrimaryValue(ThreadContext context, FieldDescriptor.Type fieldType, Object value) { Ruby runtime = context.runtime; switch (fieldType) { case INT32: @@ -150,7 +202,7 @@ public static IRubyObject wrapPrimaryValue(ThreadContext context, Descriptors.Fi case BOOL: return (Boolean) value ? runtime.getTrue() : runtime.getFalse(); case BYTES: { - IRubyObject wrapped = runtime.newString(((ByteString) value).toStringUtf8()); + IRubyObject wrapped = RubyString.newString(runtime, ((ByteString) value).toStringUtf8(), ASCIIEncoding.INSTANCE); wrapped.setFrozen(true); return wrapped; } @@ -187,21 +239,14 @@ public static long num2ulong(Ruby runtime, IRubyObject value) { } } - public static IRubyObject validateStringEncoding(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value) { - if (!(value instanceof RubyString)) - throw context.runtime.newTypeError("Invalid argument for string field."); - switch(type) { - case BYTES: - value = ((RubyString)value).encode(context, context.runtime.evalScriptlet("Encoding::ASCII_8BIT")); - break; - case STRING: - value = ((RubyString)value).encode(context, context.runtime.evalScriptlet("Encoding::UTF_8")); - break; - default: - break; + /* + * Helper to make it easier to support symbols being passed instead of strings + */ + public static IRubyObject symToString(IRubyObject sym) { + if (sym instanceof RubySymbol) { + return ((RubySymbol) sym).id2name(); } - value.setFrozen(true); - return value; + return sym; } public static void checkNameAvailability(ThreadContext context, String name) { @@ -209,67 +254,84 @@ public static void checkNameAvailability(ThreadContext context, String name) { throw context.runtime.newNameError(name + " is already defined", name); } - /** - * Replace invalid "." in descriptor with __DOT__ - * @param name - * @return - */ - public static String escapeIdentifier(String name) { - return name.replace(".", BADNAME_REPLACEMENT); - } - - /** - * Replace __DOT__ in descriptor name with "." - * @param name - * @return - */ - public static String unescapeIdentifier(String name) { - return name.replace(BADNAME_REPLACEMENT, "."); - } - - public static boolean isMapEntry(Descriptors.FieldDescriptor fieldDescriptor) { - return fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.MESSAGE && + public static boolean isMapEntry(FieldDescriptor fieldDescriptor) { + return fieldDescriptor.getType() == FieldDescriptor.Type.MESSAGE && fieldDescriptor.isRepeated() && fieldDescriptor.getMessageType().getOptions().getMapEntry(); } - public static RubyFieldDescriptor msgdefCreateField(ThreadContext context, String label, IRubyObject name, - IRubyObject type, IRubyObject number, IRubyObject typeClass, RubyClass cFieldDescriptor) { + /* + * call-seq: + * Utils.createFieldBuilder(context, label, name, type, number, typeClass = nil, options = nil) + * + * Most places calling this are already dealing with an optional number of + * arguments so dealing with them here. This helper is a standard way to + * create a FieldDescriptor builder that handles some of the options that + * are used in different places. + */ + public static FieldDescriptorProto.Builder createFieldBuilder(ThreadContext context, + String label, IRubyObject[] args) { + Ruby runtime = context.runtime; - RubyFieldDescriptor fieldDef = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK); - fieldDef.setLabel(context, runtime.newString(label)); - fieldDef.setName(context, name); - fieldDef.setType(context, type); - fieldDef.setNumber(context, number); + IRubyObject options = context.nil; + IRubyObject typeClass = context.nil; + + if (args.length > 4) { + options = args[4]; + typeClass = args[3]; + } else if (args.length > 3) { + if (args[3] instanceof RubyHash) { + options = args[3]; + } else { + typeClass = args[3]; + } + } + + FieldDescriptorProto.Builder builder = FieldDescriptorProto.newBuilder(); + + builder.setLabel(FieldDescriptorProto.Label.valueOf("LABEL_" + label.toUpperCase())) + .setName(args[0].asJavaString()) + .setNumber(RubyNumeric.num2int(args[2])) + .setType(FieldDescriptorProto.Type.valueOf("TYPE_" + args[1].asJavaString().toUpperCase())); if (!typeClass.isNil()) { if (!(typeClass instanceof RubyString)) { throw runtime.newArgumentError("expected string for type class"); } - fieldDef.setSubmsgName(context, typeClass); + builder.setTypeName("." + typeClass.asJavaString()); } - return fieldDef; - } - protected static void checkIntTypePrecision(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value) { - if (value instanceof RubyFloat) { - double doubleVal = RubyNumeric.num2dbl(value); - if (Math.floor(doubleVal) != doubleVal) { - throw context.runtime.newRangeError("Non-integral floating point value assigned to integer field."); + if (options instanceof RubyHash) { + IRubyObject defaultValue = ((RubyHash) options).fastARef(runtime.newSymbol("default")); + if (defaultValue != null) { + builder.setDefaultValue(defaultValue.toString()); } } - if (type == Descriptors.FieldDescriptor.Type.UINT32 || type == Descriptors.FieldDescriptor.Type.UINT64) { - if (RubyNumeric.num2dbl(value) < 0) { - throw context.runtime.newRangeError("Assigning negative value to unsigned integer field."); - } + + return builder; + } + + + public static RaiseException createTypeError(ThreadContext context, String message) { + if (cTypeError == null) { + cTypeError = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::TypeError"); } + return RaiseException.from(context.runtime, cTypeError, message); + } + + public static RaiseException createExpectedTypeError(ThreadContext context, String type, String fieldType, String fieldName, IRubyObject value) { + return createTypeError(context, String.format(EXPECTED_TYPE_ERROR_FORMAT, type, fieldType, fieldName, value.getMetaClass())); + } + + public static RaiseException createInvalidTypeError(ThreadContext context, String fieldType, String fieldName, IRubyObject value) { + return createTypeError(context, String.format(INVALID_TYPE_ERROR_FORMAT, fieldType, fieldName, value.getMetaClass())); } protected static boolean isRubyNum(Object value) { return value instanceof RubyFixnum || value instanceof RubyFloat || value instanceof RubyBignum; } - protected static void validateTypeClass(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value) { + protected static void validateTypeClass(ThreadContext context, FieldDescriptor.Type type, IRubyObject value) { Ruby runtime = context.runtime; if (!(value instanceof RubyModule)) { throw runtime.newArgumentError("TypeClass has incorrect type"); @@ -280,24 +342,36 @@ protected static void validateTypeClass(ThreadContext context, Descriptors.Field throw runtime.newArgumentError("Type class has no descriptor. Please pass a " + "class or enum as returned by the DescriptorPool."); } - if (type == Descriptors.FieldDescriptor.Type.MESSAGE) { + if (type == FieldDescriptor.Type.MESSAGE) { if (! (descriptor instanceof RubyDescriptor)) { throw runtime.newArgumentError("Descriptor has an incorrect type"); } - } else if (type == Descriptors.FieldDescriptor.Type.ENUM) { + } else if (type == FieldDescriptor.Type.ENUM) { if (! (descriptor instanceof RubyEnumDescriptor)) { throw runtime.newArgumentError("Descriptor has an incorrect type"); } } } - public static String BADNAME_REPLACEMENT = "__DOT__"; + private static IRubyObject validateAndEncodeString(ThreadContext context, String fieldType, String fieldName, IRubyObject value, String encoding) { + if (!(value instanceof RubyString)) + throw createInvalidTypeError(context, fieldType, fieldName, value); + + value = ((RubyString) value).encode(context, context.runtime.evalScriptlet(encoding)); + value.setFrozen(true); + return value; + } + + public static final String DESCRIPTOR_INSTANCE_VAR = "@descriptor"; + + public static final String EQUAL_SIGN = "="; - public static String DESCRIPTOR_INSTANCE_VAR = "@descriptor"; + private static final BigInteger UINT64_COMPLEMENTARY = new BigInteger("18446744073709551616"); //Math.pow(2, 64) - public static String EQUAL_SIGN = "="; + private static final String EXPECTED_TYPE_ERROR_FORMAT = "Expected %s type for %s field '%s' (given %s)."; + private static final String INVALID_TYPE_ERROR_FORMAT = "Invalid argument for %s field '%s' (given %s)."; - private static BigInteger UINT64_COMPLEMENTARY = new BigInteger("18446744073709551616"); //Math.pow(2, 64) + private static final long UINT_MAX = 0xffffffffl; - private static long UINT_MAX = 0xffffffffl; + private static RubyClass cTypeError; } diff --git a/ruby/src/main/java/google/ProtobufJavaService.java b/ruby/src/main/java/google/ProtobufJavaService.java index bffb492a9e270..a364719400019 100644 --- a/ruby/src/main/java/google/ProtobufJavaService.java +++ b/ruby/src/main/java/google/ProtobufJavaService.java @@ -42,19 +42,26 @@ public class ProtobufJavaService implements BasicLibraryService { @Override public boolean basicLoad(Ruby ruby) throws IOException { ruby.defineModule("Google"); + + /* + * The order these happen in is important because we + * save a static reference to some classes and they + * need to exist before we try to save a reference to them + */ RubyProtobuf.createProtobuf(ruby); - RubyDescriptor.createRubyDescriptor(ruby); RubyBuilder.createRubyBuilder(ruby); - RubyFieldDescriptor.createRubyFileDescriptor(ruby); - RubyMessageBuilderContext.createRubyMessageBuilderContext(ruby); + RubyFileDescriptor.createRubyFileDescriptor(ruby); RubyEnumDescriptor.createRubyEnumDescriptor(ruby); RubyEnumBuilderContext.createRubyEnumBuilderContext(ruby); - RubyDescriptorPool.createRubyDescriptorPool(ruby); RubyRepeatedField.createRubyRepeatedField(ruby); - RubyFieldDescriptor.createRubyFileDescriptor(ruby); + RubyFieldDescriptor.createRubyFieldDescriptor(ruby); RubyMap.createRubyMap(ruby); RubyOneofDescriptor.createRubyOneofDescriptor(ruby); RubyOneofBuilderContext.createRubyOneofBuilderContext(ruby); + RubyMessageBuilderContext.createRubyMessageBuilderContext(ruby); + RubyDescriptor.createRubyDescriptor(ruby); + RubyFileBuilderContext.createRubyFileBuilderContext(ruby); + RubyDescriptorPool.createRubyDescriptorPool(ruby); return true; } } diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb old mode 100644 new mode 100755 index 020effb05677a..098ac41e7e9c3 --- a/ruby/tests/basic.rb +++ b/ruby/tests/basic.rb @@ -1,5 +1,10 @@ #!/usr/bin/ruby +# basic_test_pb.rb is in the same directory as this test. +$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) + +require 'basic_test_pb' +require 'common_tests' require 'google/protobuf' require 'json' require 'test/unit' @@ -9,623 +14,169 @@ module BasicTest pool = Google::Protobuf::DescriptorPool.new pool.build do - add_message "Foo" do - optional :bar, :message, 1, "Bar" - repeated :baz, :message, 2, "Baz" - end - - add_message "Bar" do - optional :msg, :string, 1 - end - - add_message "Baz" do - optional :msg, :string, 1 - end - - add_message "TestMessage" do - optional :optional_int32, :int32, 1 - optional :optional_int64, :int64, 2 - optional :optional_uint32, :uint32, 3 - optional :optional_uint64, :uint64, 4 - optional :optional_bool, :bool, 5 - optional :optional_float, :float, 6 - optional :optional_double, :double, 7 - optional :optional_string, :string, 8 - optional :optional_bytes, :bytes, 9 - optional :optional_msg, :message, 10, "TestMessage2" - optional :optional_enum, :enum, 11, "TestEnum" - - repeated :repeated_int32, :int32, 12 - repeated :repeated_int64, :int64, 13 - repeated :repeated_uint32, :uint32, 14 - repeated :repeated_uint64, :uint64, 15 - repeated :repeated_bool, :bool, 16 - repeated :repeated_float, :float, 17 - repeated :repeated_double, :double, 18 - repeated :repeated_string, :string, 19 - repeated :repeated_bytes, :bytes, 20 - repeated :repeated_msg, :message, 21, "TestMessage2" - repeated :repeated_enum, :enum, 22, "TestEnum" - end - add_message "TestMessage2" do - optional :foo, :int32, 1 - end - - add_message "Recursive1" do - optional :foo, :message, 1, "Recursive2" - end - add_message "Recursive2" do - optional :foo, :message, 1, "Recursive1" - end - - add_enum "TestEnum" do - value :Default, 0 - value :A, 1 - value :B, 2 - value :C, 3 - end - add_message "BadFieldNames" do optional :dup, :int32, 1 optional :class, :int32, 2 - optional :"a.b", :int32, 3 - end - - add_message "MapMessage" do - map :map_string_int32, :string, :int32, 1 - map :map_string_msg, :string, :message, 2, "TestMessage2" - end - add_message "MapMessageWireEquiv" do - repeated :map_string_int32, :message, 1, "MapMessageWireEquiv_entry1" - repeated :map_string_msg, :message, 2, "MapMessageWireEquiv_entry2" - end - add_message "MapMessageWireEquiv_entry1" do - optional :key, :string, 1 - optional :value, :int32, 2 - end - add_message "MapMessageWireEquiv_entry2" do - optional :key, :string, 1 - optional :value, :message, 2, "TestMessage2" - end - - add_message "OneofMessage" do - oneof :my_oneof do - optional :a, :string, 1 - optional :b, :int32, 2 - optional :c, :message, 3, "TestMessage2" - optional :d, :enum, 4, "TestEnum" - end end end - Foo = pool.lookup("Foo").msgclass - Bar = pool.lookup("Bar").msgclass - Baz = pool.lookup("Baz").msgclass - TestMessage = pool.lookup("TestMessage").msgclass - TestMessage2 = pool.lookup("TestMessage2").msgclass - Recursive1 = pool.lookup("Recursive1").msgclass - Recursive2 = pool.lookup("Recursive2").msgclass - TestEnum = pool.lookup("TestEnum").enummodule BadFieldNames = pool.lookup("BadFieldNames").msgclass - MapMessage = pool.lookup("MapMessage").msgclass - MapMessageWireEquiv = pool.lookup("MapMessageWireEquiv").msgclass - MapMessageWireEquiv_entry1 = - pool.lookup("MapMessageWireEquiv_entry1").msgclass - MapMessageWireEquiv_entry2 = - pool.lookup("MapMessageWireEquiv_entry2").msgclass - OneofMessage = pool.lookup("OneofMessage").msgclass # ------------ test cases --------------- class MessageContainerTest < Test::Unit::TestCase - - def test_defaults - m = TestMessage.new - assert m.optional_int32 == 0 - assert m.optional_int64 == 0 - assert m.optional_uint32 == 0 - assert m.optional_uint64 == 0 - assert m.optional_bool == false - assert m.optional_float == 0.0 - assert m.optional_double == 0.0 - assert m.optional_string == "" - assert m.optional_bytes == "" - assert m.optional_msg == nil - assert m.optional_enum == :Default - end - - def test_setters - m = TestMessage.new - m.optional_int32 = -42 - assert m.optional_int32 == -42 - m.optional_int64 = -0x1_0000_0000 - assert m.optional_int64 == -0x1_0000_0000 - m.optional_uint32 = 0x9000_0000 - assert m.optional_uint32 == 0x9000_0000 - m.optional_uint64 = 0x9000_0000_0000_0000 - assert m.optional_uint64 == 0x9000_0000_0000_0000 - m.optional_bool = true - assert m.optional_bool == true - m.optional_float = 0.5 - assert m.optional_float == 0.5 - m.optional_double = 0.5 - m.optional_string = "hello" - assert m.optional_string == "hello" - m.optional_bytes = "world".encode!('ASCII-8BIT') - assert m.optional_bytes == "world" - m.optional_msg = TestMessage2.new(:foo => 42) - assert m.optional_msg == TestMessage2.new(:foo => 42) - m.optional_msg = nil - assert m.optional_msg == nil + # Required by CommonTests module to resolve proto3 proto classes used in tests. + def proto_module + ::BasicTest end + include CommonTests - def test_ctor_args - m = TestMessage.new(:optional_int32 => -42, - :optional_msg => TestMessage2.new, - :optional_enum => :C, - :repeated_string => ["hello", "there", "world"]) - assert m.optional_int32 == -42 - assert m.optional_msg.class == TestMessage2 - assert m.repeated_string.length == 3 - assert m.optional_enum == :C - assert m.repeated_string[0] == "hello" - assert m.repeated_string[1] == "there" - assert m.repeated_string[2] == "world" - end - - def test_inspect - m = TestMessage.new(:optional_int32 => -42, - :optional_enum => :A, - :optional_msg => TestMessage2.new, - :repeated_string => ["hello", "there", "world"]) - expected = ', optional_enum: :A, repeated_int32: [], repeated_int64: [], repeated_uint32: [], repeated_uint64: [], repeated_bool: [], repeated_float: [], repeated_double: [], repeated_string: ["hello", "there", "world"], repeated_bytes: [], repeated_msg: [], repeated_enum: []>' - assert_equal expected, m.inspect - end - - def test_hash - m1 = TestMessage.new(:optional_int32 => 42) - m2 = TestMessage.new(:optional_int32 => 102, repeated_string: ['please', 'work', 'ok?']) - m3 = TestMessage.new(:optional_int32 => 102, repeated_string: ['please', 'work', 'ok?']) - assert m1.hash != 0 - assert m2.hash != 0 - assert m3.hash != 0 - # relying on the randomness here -- if hash function changes and we are - # unlucky enough to get a collision, then change the values above. - assert m1.hash != m2.hash - assert_equal m2.hash, m3.hash - end + def test_has_field + m = TestSingularFields.new + assert !m.has_singular_msg? + m.singular_msg = TestMessage2.new + assert m.has_singular_msg? + assert TestSingularFields.descriptor.lookup('singular_msg').has?(m) - def test_unknown_field_errors - e = assert_raise NoMethodError do - TestMessage.new.hello + m = OneofMessage.new + assert !m.has_my_oneof? + m.a = "foo" + assert m.has_my_oneof? + assert_raise NoMethodError do + m.has_a? end - assert_match(/hello/, e.message) + assert_true OneofMessage.descriptor.lookup('a').has?(m) - e = assert_raise NoMethodError do - TestMessage.new.hello = "world" + m = TestSingularFields.new + assert_raise NoMethodError do + m.has_singular_int32? end - assert_match(/hello/, e.message) - end - - def test_initialization_map_errors - e = assert_raise ArgumentError do - TestMessage.new(:hello => "world") - end - assert_match(/hello/, e.message) - - e = assert_raise ArgumentError do - MapMessage.new(:map_string_int32 => "hello") - end - assert_equal e.message, "Expected Hash object as initializer value for map field 'map_string_int32'." - - e = assert_raise ArgumentError do - TestMessage.new(:repeated_uint32 => "hello") + assert_raise ArgumentError do + TestSingularFields.descriptor.lookup('singular_int32').has?(m) end - assert_equal e.message, "Expected array as initializer value for repeated field 'repeated_uint32'." - end - def test_type_errors - m = TestMessage.new - assert_raise TypeError do - m.optional_int32 = "hello" - end - assert_raise TypeError do - m.optional_string = 42 - end - assert_raise TypeError do - m.optional_string = nil - end - assert_raise TypeError do - m.optional_bool = 42 + assert_raise NoMethodError do + m.has_singular_string? end - assert_raise TypeError do - m.optional_msg = TestMessage.new # expects TestMessage2 + assert_raise ArgumentError do + TestSingularFields.descriptor.lookup('singular_string').has?(m) end - assert_raise TypeError do - m.repeated_int32 = [] # needs RepeatedField + assert_raise NoMethodError do + m.has_singular_bool? end - - assert_raise TypeError do - m.repeated_int32.push "hello" + assert_raise ArgumentError do + TestSingularFields.descriptor.lookup('singular_bool').has?(m) end - assert_raise TypeError do - m.repeated_msg.push TestMessage.new - end - end - - def test_string_encoding m = TestMessage.new - - # Assigning a normal (ASCII or UTF8) string to a bytes field, or - # ASCII-8BIT to a string field will convert to the proper encoding. - m.optional_bytes = "Test string ASCII".encode!('ASCII') - assert m.optional_bytes.frozen? - assert_equal Encoding::ASCII_8BIT, m.optional_bytes.encoding - assert_equal "Test string ASCII", m.optional_bytes - - assert_raise Encoding::UndefinedConversionError do - m.optional_bytes = "Test string UTF-8 \u0100".encode!('UTF-8') - end - - assert_raise Encoding::UndefinedConversionError do - m.optional_string = ["FFFF"].pack('H*') + assert_raise NoMethodError do + m.has_repeated_msg? end - - # "Ordinary" use case. - m.optional_bytes = ["FFFF"].pack('H*') - m.optional_string = "\u0100" - - # strings are immutable so we can't do this, but serialize should catch it. - m.optional_string = "asdf".encode!('UTF-8') - assert_raise RuntimeError do - m.optional_string.encode!('ASCII-8BIT') + assert_raise ArgumentError do + TestMessage.descriptor.lookup('repeated_msg').has?(m) end end - def test_rptfield_int32 - l = Google::Protobuf::RepeatedField.new(:int32) - assert l.count == 0 - l = Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3]) - assert l.count == 3 - assert_equal [1, 2, 3], l - assert_equal l, [1, 2, 3] - l.push 4 - assert l == [1, 2, 3, 4] - dst_list = [] - l.each { |val| dst_list.push val } - assert dst_list == [1, 2, 3, 4] - assert l.to_a == [1, 2, 3, 4] - assert l[0] == 1 - assert l[3] == 4 - l[0] = 5 - assert l == [5, 2, 3, 4] - - l2 = l.dup - assert l == l2 - assert l.object_id != l2.object_id - l2.push 6 - assert l.count == 4 - assert l2.count == 5 - - assert l.inspect == '[5, 2, 3, 4]' - - l.concat([7, 8, 9]) - assert l == [5, 2, 3, 4, 7, 8, 9] - assert l.pop == 9 - assert l == [5, 2, 3, 4, 7, 8] - - assert_raise TypeError do - m = TestMessage.new - l.push m - end + def test_no_presence + m = TestSingularFields.new - m = TestMessage.new - m.repeated_int32 = l - assert m.repeated_int32 == [5, 2, 3, 4, 7, 8] - assert m.repeated_int32.object_id == l.object_id - l.push 42 - assert m.repeated_int32.pop == 42 - - l3 = l + l.dup - assert l3.count == l.count * 2 - l.count.times do |i| - assert l3[i] == l[i] - assert l3[l.count + i] == l[i] - end + # Explicitly setting to zero does not cause anything to be serialized. + m.singular_int32 = 0 + assert_equal "", TestSingularFields.encode(m) - l.clear - assert l.count == 0 - l += [1, 2, 3, 4] - l.replace([5, 6, 7, 8]) - assert l == [5, 6, 7, 8] + # Explicitly setting to a non-zero value *does* cause serialization. + m.singular_int32 = 1 + assert_not_equal "", TestSingularFields.encode(m) - l4 = Google::Protobuf::RepeatedField.new(:int32) - l4[5] = 42 - assert l4 == [0, 0, 0, 0, 0, 42] - - l4 << 100 - assert l4 == [0, 0, 0, 0, 0, 42, 100] - l4 << 101 << 102 - assert l4 == [0, 0, 0, 0, 0, 42, 100, 101, 102] + m.singular_int32 = 0 + assert_equal "", TestSingularFields.encode(m) end - def test_parent_rptfield - #make sure we set the RepeatedField and can add to it - m = TestMessage.new - assert m.repeated_string == [] - m.repeated_string << 'ok' - m.repeated_string.push('ok2') - assert m.repeated_string == ['ok', 'ok2'] - m.repeated_string += ['ok3'] - assert m.repeated_string == ['ok', 'ok2', 'ok3'] - end + def test_set_clear_defaults + m = TestSingularFields.new - def test_rptfield_msg - l = Google::Protobuf::RepeatedField.new(:message, TestMessage) - l.push TestMessage.new - assert l.count == 1 - assert_raise TypeError do - l.push TestMessage2.new - end - assert_raise TypeError do - l.push 42 - end + m.singular_int32 = -42 + assert_equal -42, m.singular_int32 + m.clear_singular_int32 + assert_equal 0, m.singular_int32 - l2 = l.dup - assert l2[0] == l[0] - assert l2[0].object_id == l[0].object_id - - l2 = Google::Protobuf.deep_copy(l) - assert l2[0] == l[0] - assert l2[0].object_id != l[0].object_id - - l3 = l + l2 - assert l3.count == 2 - assert l3[0] == l[0] - assert l3[1] == l2[0] - l3[0].optional_int32 = 1000 - assert l[0].optional_int32 == 1000 - - new_msg = TestMessage.new(:optional_int32 => 200) - l4 = l + [new_msg] - assert l4.count == 2 - new_msg.optional_int32 = 1000 - assert l4[1].optional_int32 == 1000 - end + m.singular_int32 = 50 + assert_equal 50, m.singular_int32 + TestSingularFields.descriptor.lookup('singular_int32').clear(m) + assert_equal 0, m.singular_int32 - def test_rptfield_enum - l = Google::Protobuf::RepeatedField.new(:enum, TestEnum) - l.push :A - l.push :B - l.push :C - assert l.count == 3 - assert_raise RangeError do - l.push :D - end - assert l[0] == :A + m.singular_string = "foo bar" + assert_equal "foo bar", m.singular_string + m.clear_singular_string + assert_equal "", m.singular_string - l.push 4 - assert l[3] == 4 - end + m.singular_string = "foo" + assert_equal "foo", m.singular_string + TestSingularFields.descriptor.lookup('singular_string').clear(m) + assert_equal "", m.singular_string - def test_rptfield_initialize - assert_raise ArgumentError do - l = Google::Protobuf::RepeatedField.new - end - assert_raise ArgumentError do - l = Google::Protobuf::RepeatedField.new(:message) - end - assert_raise ArgumentError do - l = Google::Protobuf::RepeatedField.new([1, 2, 3]) - end - assert_raise ArgumentError do - l = Google::Protobuf::RepeatedField.new(:message, [TestMessage2.new]) - end - end + m.singular_msg = TestMessage2.new(:foo => 42) + assert_equal TestMessage2.new(:foo => 42), m.singular_msg + assert m.has_singular_msg? + m.clear_singular_msg + assert_equal nil, m.singular_msg + assert !m.has_singular_msg? - def test_rptfield_array_ducktyping - l = Google::Protobuf::RepeatedField.new(:int32) - length_methods = %w(count length size) - length_methods.each do |lm| - assert l.send(lm) == 0 - end - # out of bounds returns a nil - assert l[0] == nil - assert l[1] == nil - assert l[-1] == nil - l.push 4 - length_methods.each do |lm| - assert l.send(lm) == 1 - end - assert l[0] == 4 - assert l[1] == nil - assert l[-1] == 4 - assert l[-2] == nil - - l.push 2 - length_methods.each do |lm| - assert l.send(lm) == 2 - end - assert l[0] == 4 - assert l[1] == 2 - assert l[2] == nil - assert l[-1] == 2 - assert l[-2] == 4 - assert l[-3] == nil - - #adding out of scope will backfill with empty objects + m.singular_msg = TestMessage2.new(:foo => 42) + assert_equal TestMessage2.new(:foo => 42), m.singular_msg + TestSingularFields.descriptor.lookup('singular_msg').clear(m) + assert_equal nil, m.singular_msg end - def test_map_basic - # allowed key types: - # :int32, :int64, :uint32, :uint64, :bool, :string, :bytes. - - m = Google::Protobuf::Map.new(:string, :int32) - m["asdf"] = 1 - assert m["asdf"] == 1 - m["jkl;"] = 42 - assert m == { "jkl;" => 42, "asdf" => 1 } - assert m.has_key?("asdf") - assert !m.has_key?("qwerty") - assert m.length == 2 - - m2 = m.dup - assert_equal m, m2 - assert m.hash != 0 - assert_equal m.hash, m2.hash - - collected = {} - m.each { |k,v| collected[v] = k } - assert collected == { 42 => "jkl;", 1 => "asdf" } - - assert m.delete("asdf") == 1 - assert !m.has_key?("asdf") - assert m["asdf"] == nil - assert !m.has_key?("asdf") + def test_clear_repeated_fields + m = TestMessage.new - # We only assert on inspect value when there is one map entry because the - # order in which elements appear is unspecified (depends on the internal - # hash function). We don't want a brittle test. - assert m.inspect == "{\"jkl;\"=>42}" + m.repeated_int32.push(1) + assert_equal [1], m.repeated_int32 + m.clear_repeated_int32 + assert_equal [], m.repeated_int32 - assert m.keys == ["jkl;"] - assert m.values == [42] + m.repeated_int32.push(1) + assert_equal [1], m.repeated_int32 + TestMessage.descriptor.lookup('repeated_int32').clear(m) + assert_equal [], m.repeated_int32 - m.clear - assert m.length == 0 - assert m == {} + m = OneofMessage.new + m.a = "foo" + assert_equal "foo", m.a + assert m.has_my_oneof? + assert_equal :a, m.my_oneof + m.clear_a + assert !m.has_my_oneof? - assert_raise TypeError do - m[1] = 1 - end - assert_raise RangeError do - m["asdf"] = 0x1_0000_0000 - end - end + m.a = "foobar" + assert m.has_my_oneof? + m.clear_my_oneof + assert !m.has_my_oneof? - def test_map_ctor - m = Google::Protobuf::Map.new(:string, :int32, - {"a" => 1, "b" => 2, "c" => 3}) - assert m == {"a" => 1, "c" => 3, "b" => 2} + m.a = "bar" + assert_equal "bar", m.a + assert m.has_my_oneof? + OneofMessage.descriptor.lookup('a').clear(m) + assert !m.has_my_oneof? end - def test_map_keytypes - m = Google::Protobuf::Map.new(:int32, :int32) - m[1] = 42 - m[-1] = 42 - assert_raise RangeError do - m[0x8000_0000] = 1 - end - assert_raise TypeError do - m["asdf"] = 1 - end - - m = Google::Protobuf::Map.new(:int64, :int32) - m[0x1000_0000_0000_0000] = 1 - assert_raise RangeError do - m[0x1_0000_0000_0000_0000] = 1 - end - assert_raise TypeError do - m["asdf"] = 1 - end - - m = Google::Protobuf::Map.new(:uint32, :int32) - m[0x8000_0000] = 1 - assert_raise RangeError do - m[0x1_0000_0000] = 1 - end - assert_raise RangeError do - m[-1] = 1 - end - - m = Google::Protobuf::Map.new(:uint64, :int32) - m[0x8000_0000_0000_0000] = 1 - assert_raise RangeError do - m[0x1_0000_0000_0000_0000] = 1 - end - assert_raise RangeError do - m[-1] = 1 - end - - m = Google::Protobuf::Map.new(:bool, :int32) - m[true] = 1 - m[false] = 2 - assert_raise TypeError do - m[1] = 1 - end - assert_raise TypeError do - m["asdf"] = 1 - end - - m = Google::Protobuf::Map.new(:string, :int32) - m["asdf"] = 1 - assert_raise TypeError do - m[1] = 1 - end - assert_raise Encoding::UndefinedConversionError do - bytestring = ["FFFF"].pack("H*") - m[bytestring] = 1 - end - - m = Google::Protobuf::Map.new(:bytes, :int32) - bytestring = ["FFFF"].pack("H*") - m[bytestring] = 1 - # Allowed -- we will automatically convert to ASCII-8BIT. - m["asdf"] = 1 - assert_raise TypeError do - m[1] = 1 + def test_initialization_map_errors + e = assert_raise ArgumentError do + TestMessage.new(:hello => "world") end - end + assert_match(/hello/, e.message) - def test_map_msg_enum_valuetypes - m = Google::Protobuf::Map.new(:string, :message, TestMessage) - m["asdf"] = TestMessage.new - assert_raise TypeError do - m["jkl;"] = TestMessage2.new + e = assert_raise ArgumentError do + MapMessage.new(:map_string_int32 => "hello") end + assert_equal e.message, "Expected Hash object as initializer value for map field 'map_string_int32' (given String)." - m = Google::Protobuf::Map.new( - :string, :message, TestMessage, - { "a" => TestMessage.new(:optional_int32 => 42), - "b" => TestMessage.new(:optional_int32 => 84) }) - assert m.length == 2 - assert m.values.map{|msg| msg.optional_int32}.sort == [42, 84] - - m = Google::Protobuf::Map.new(:string, :enum, TestEnum, - { "x" => :A, "y" => :B, "z" => :C }) - assert m.length == 3 - assert m["z"] == :C - m["z"] = 2 - assert m["z"] == :B - m["z"] = 4 - assert m["z"] == 4 - assert_raise RangeError do - m["z"] = :Z - end - assert_raise TypeError do - m["z"] = "z" + e = assert_raise ArgumentError do + TestMessage.new(:repeated_uint32 => "hello") end - end - - def test_map_dup_deep_copy - m = Google::Protobuf::Map.new( - :string, :message, TestMessage, - { "a" => TestMessage.new(:optional_int32 => 42), - "b" => TestMessage.new(:optional_int32 => 84) }) - - m2 = m.dup - assert m == m2 - assert m.object_id != m2.object_id - assert m["a"].object_id == m2["a"].object_id - assert m["b"].object_id == m2["b"].object_id - - m2 = Google::Protobuf.deep_copy(m) - assert m == m2 - assert m.object_id != m2.object_id - assert m["a"].object_id != m2["a"].object_id - assert m["b"].object_id != m2["b"].object_id + assert_equal e.message, "Expected array as initializer value for repeated field 'repeated_uint32' (given String)." end def test_map_field @@ -636,10 +187,12 @@ def test_map_field m = MapMessage.new( :map_string_int32 => {"a" => 1, "b" => 2}, :map_string_msg => {"a" => TestMessage2.new(:foo => 1), - "b" => TestMessage2.new(:foo => 2)}) + "b" => TestMessage2.new(:foo => 2)}, + :map_string_enum => {"a" => :A, "b" => :B}) assert m.map_string_int32.keys.sort == ["a", "b"] assert m.map_string_int32["a"] == 1 assert m.map_string_msg["b"].foo == 2 + assert m.map_string_enum["a"] == :A m.map_string_int32["c"] = 3 assert m.map_string_int32["c"] == 3 @@ -649,25 +202,53 @@ def test_map_field m.map_string_msg.delete("c") assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) } - assert_raise TypeError do + assert_raise Google::Protobuf::TypeError do m.map_string_msg["e"] = TestMessage.new # wrong value type end # ensure nothing was added by the above assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) } m.map_string_int32 = Google::Protobuf::Map.new(:string, :int32) - assert_raise TypeError do + assert_raise Google::Protobuf::TypeError do m.map_string_int32 = Google::Protobuf::Map.new(:string, :int64) end - assert_raise TypeError do + assert_raise Google::Protobuf::TypeError do m.map_string_int32 = {} end - assert_raise TypeError do + assert_raise Google::Protobuf::TypeError do m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" }) end end + def test_map_field_with_symbol + m = MapMessage.new + assert m.map_string_int32 == {} + assert m.map_string_msg == {} + + m = MapMessage.new( + :map_string_int32 => {a: 1, "b" => 2}, + :map_string_msg => {a: TestMessage2.new(:foo => 1), + b: TestMessage2.new(:foo => 10)}) + assert_equal 1, m.map_string_int32[:a] + assert_equal 2, m.map_string_int32[:b] + assert_equal 10, m.map_string_msg[:b].foo + end + + def test_map_inspect + m = MapMessage.new( + :map_string_int32 => {"a" => 1, "b" => 2}, + :map_string_msg => {"a" => TestMessage2.new(:foo => 1), + "b" => TestMessage2.new(:foo => 2)}, + :map_string_enum => {"a" => :A, "b" => :B}) + + # JRuby doesn't keep consistent ordering so check for either version + expected_a = "2, \"a\"=>1}, map_string_msg: {\"b\"=>, \"a\"=>}, map_string_enum: {\"b\"=>:B, \"a\"=>:A}>" + expected_b = "1, \"b\"=>2}, map_string_msg: {\"a\"=>, \"b\"=>}, map_string_enum: {\"a\"=>:A, \"b\"=>:B}>" + inspect_result = m.inspect + assert expected_a == inspect_result || expected_b == inspect_result, "Incorrect inspect result: #{inspect_result}" + end + def test_map_corruption # This pattern led to a crash in a previous version of upb/protobuf. m = MapMessage.new(map_string_int32: { "aaa" => 1 }) @@ -675,11 +256,149 @@ def test_map_corruption m.map_string_int32['aaa'] = 3 end + def test_map_wrappers + run_asserts = ->(m) { + assert_equal 2.0, m.map_double[0].value + assert_equal 4.0, m.map_float[0].value + assert_equal 3, m.map_int32[0].value + assert_equal 4, m.map_int64[0].value + assert_equal 5, m.map_uint32[0].value + assert_equal 6, m.map_uint64[0].value + assert_equal true, m.map_bool[0].value + assert_equal 'str', m.map_string[0].value + assert_equal 'fun', m.map_bytes[0].value + } + + m = proto_module::Wrapper.new( + map_double: {0 => Google::Protobuf::DoubleValue.new(value: 2.0)}, + map_float: {0 => Google::Protobuf::FloatValue.new(value: 4.0)}, + map_int32: {0 => Google::Protobuf::Int32Value.new(value: 3)}, + map_int64: {0 => Google::Protobuf::Int64Value.new(value: 4)}, + map_uint32: {0 => Google::Protobuf::UInt32Value.new(value: 5)}, + map_uint64: {0 => Google::Protobuf::UInt64Value.new(value: 6)}, + map_bool: {0 => Google::Protobuf::BoolValue.new(value: true)}, + map_string: {0 => Google::Protobuf::StringValue.new(value: 'str')}, + map_bytes: {0 => Google::Protobuf::BytesValue.new(value: 'fun')}, + ) + + run_asserts.call(m) + serialized = proto_module::Wrapper::encode(m) + m2 = proto_module::Wrapper::decode(serialized) + run_asserts.call(m2) + + # Test the case where we are serializing directly from the parsed form + # (before anything lazy is materialized). + m3 = proto_module::Wrapper::decode(serialized) + serialized2 = proto_module::Wrapper::encode(m3) + m4 = proto_module::Wrapper::decode(serialized2) + run_asserts.call(m4) + + # Test that the lazy form compares equal to the expanded form. + m5 = proto_module::Wrapper::decode(serialized2) + assert_equal m5, m + end + + def test_map_wrappers_with_default_values + run_asserts = ->(m) { + assert_equal 0.0, m.map_double[0].value + assert_equal 0.0, m.map_float[0].value + assert_equal 0, m.map_int32[0].value + assert_equal 0, m.map_int64[0].value + assert_equal 0, m.map_uint32[0].value + assert_equal 0, m.map_uint64[0].value + assert_equal false, m.map_bool[0].value + assert_equal '', m.map_string[0].value + assert_equal '', m.map_bytes[0].value + } + + m = proto_module::Wrapper.new( + map_double: {0 => Google::Protobuf::DoubleValue.new(value: 0.0)}, + map_float: {0 => Google::Protobuf::FloatValue.new(value: 0.0)}, + map_int32: {0 => Google::Protobuf::Int32Value.new(value: 0)}, + map_int64: {0 => Google::Protobuf::Int64Value.new(value: 0)}, + map_uint32: {0 => Google::Protobuf::UInt32Value.new(value: 0)}, + map_uint64: {0 => Google::Protobuf::UInt64Value.new(value: 0)}, + map_bool: {0 => Google::Protobuf::BoolValue.new(value: false)}, + map_string: {0 => Google::Protobuf::StringValue.new(value: '')}, + map_bytes: {0 => Google::Protobuf::BytesValue.new(value: '')}, + ) + + run_asserts.call(m) + serialized = proto_module::Wrapper::encode(m) + m2 = proto_module::Wrapper::decode(serialized) + run_asserts.call(m2) + + # Test the case where we are serializing directly from the parsed form + # (before anything lazy is materialized). + m3 = proto_module::Wrapper::decode(serialized) + serialized2 = proto_module::Wrapper::encode(m3) + m4 = proto_module::Wrapper::decode(serialized2) + run_asserts.call(m4) + + # Test that the lazy form compares equal to the expanded form. + m5 = proto_module::Wrapper::decode(serialized2) + assert_equal m5, m + end + + def test_map_wrappers_with_no_value + run_asserts = ->(m) { + assert_equal 0.0, m.map_double[0].value + assert_equal 0.0, m.map_float[0].value + assert_equal 0, m.map_int32[0].value + assert_equal 0, m.map_int64[0].value + assert_equal 0, m.map_uint32[0].value + assert_equal 0, m.map_uint64[0].value + assert_equal false, m.map_bool[0].value + assert_equal '', m.map_string[0].value + assert_equal '', m.map_bytes[0].value + } + + m = proto_module::Wrapper.new( + map_double: {0 => Google::Protobuf::DoubleValue.new()}, + map_float: {0 => Google::Protobuf::FloatValue.new()}, + map_int32: {0 => Google::Protobuf::Int32Value.new()}, + map_int64: {0 => Google::Protobuf::Int64Value.new()}, + map_uint32: {0 => Google::Protobuf::UInt32Value.new()}, + map_uint64: {0 => Google::Protobuf::UInt64Value.new()}, + map_bool: {0 => Google::Protobuf::BoolValue.new()}, + map_string: {0 => Google::Protobuf::StringValue.new()}, + map_bytes: {0 => Google::Protobuf::BytesValue.new()}, + ) + run_asserts.call(m) + + serialized = proto_module::Wrapper::encode(m) + m2 = proto_module::Wrapper::decode(serialized) + run_asserts.call(m2) + + # Test the case where we are serializing directly from the parsed form + # (before anything lazy is materialized). + m3 = proto_module::Wrapper::decode(serialized) + serialized2 = proto_module::Wrapper::encode(m3) + m4 = proto_module::Wrapper::decode(serialized2) + run_asserts.call(m4) + end + + def test_concurrent_decoding + o = Outer.new + o.items[0] = Inner.new + raw = Outer.encode(o) + + thds = 2.times.map do + Thread.new do + 100000.times do + assert_equal o, Outer.decode(raw) + end + end + end + thds.map(&:join) + end + def test_map_encode_decode m = MapMessage.new( :map_string_int32 => {"a" => 1, "b" => 2}, :map_string_msg => {"a" => TestMessage2.new(:foo => 1), - "b" => TestMessage2.new(:foo => 2)}) + "b" => TestMessage2.new(:foo => 2)}, + :map_string_enum => {"a" => :A, "b" => :B}) m2 = MapMessage.decode(MapMessage.encode(m)) assert m == m2 @@ -696,213 +415,29 @@ def test_map_encode_decode "b" => TestMessage2.new(:foo => 2)} end - def test_oneof_descriptors - d = OneofMessage.descriptor - o = d.lookup_oneof("my_oneof") - assert o != nil - assert o.class == Google::Protobuf::OneofDescriptor - assert o.name == "my_oneof" - oneof_count = 0 - d.each_oneof{ |oneof| - oneof_count += 1 - assert oneof == o - } - assert oneof_count == 1 - assert o.count == 4 - field_names = o.map{|f| f.name}.sort - assert field_names == ["a", "b", "c", "d"] - end - - def test_oneof - d = OneofMessage.new - assert d.a == "" - assert d.b == 0 - assert d.c == nil - assert d.d == :Default - assert d.my_oneof == nil - - d.a = "hi" - assert d.a == "hi" - assert d.b == 0 - assert d.c == nil - assert d.d == :Default - assert d.my_oneof == :a - - d.b = 42 - assert d.a == "" - assert d.b == 42 - assert d.c == nil - assert d.d == :Default - assert d.my_oneof == :b - - d.c = TestMessage2.new(:foo => 100) - assert d.a == "" - assert d.b == 0 - assert d.c.foo == 100 - assert d.d == :Default - assert d.my_oneof == :c - - d.d = :C - assert d.a == "" - assert d.b == 0 - assert d.c == nil - assert d.d == :C - assert d.my_oneof == :d - - d2 = OneofMessage.decode(OneofMessage.encode(d)) - assert d2 == d - - encoded_field_a = OneofMessage.encode(OneofMessage.new(:a => "string")) - encoded_field_b = OneofMessage.encode(OneofMessage.new(:b => 1000)) - encoded_field_c = OneofMessage.encode( - OneofMessage.new(:c => TestMessage2.new(:foo => 1))) - encoded_field_d = OneofMessage.encode(OneofMessage.new(:d => :B)) - - d3 = OneofMessage.decode( - encoded_field_c + encoded_field_a + encoded_field_d) - assert d3.a == "" - assert d3.b == 0 - assert d3.c == nil - assert d3.d == :B - - d4 = OneofMessage.decode( - encoded_field_c + encoded_field_a + encoded_field_d + - encoded_field_c) - assert d4.a == "" - assert d4.b == 0 - assert d4.c.foo == 1 - assert d4.d == :Default - - d5 = OneofMessage.new(:a => "hello") - assert d5.a == "hello" - d5.a = nil - assert d5.a == "" - assert OneofMessage.encode(d5) == '' - assert d5.my_oneof == nil - end - - def test_enum_field - m = TestMessage.new - assert m.optional_enum == :Default - m.optional_enum = :A - assert m.optional_enum == :A - assert_raise RangeError do - m.optional_enum = :ASDF - end - m.optional_enum = 1 - assert m.optional_enum == :A - m.optional_enum = 100 - assert m.optional_enum == 100 - end - - def test_dup - m = TestMessage.new - m.optional_string = "hello" - m.optional_int32 = 42 - tm1 = TestMessage2.new(:foo => 100) - tm2 = TestMessage2.new(:foo => 200) - m.repeated_msg.push tm1 - assert m.repeated_msg[-1] == tm1 - m.repeated_msg.push tm2 - assert m.repeated_msg[-1] == tm2 - m2 = m.dup - assert m == m2 - m.optional_int32 += 1 - assert m != m2 - assert m.repeated_msg[0] == m2.repeated_msg[0] - assert m.repeated_msg[0].object_id == m2.repeated_msg[0].object_id - end - - def test_deep_copy - m = TestMessage.new(:optional_int32 => 42, - :repeated_msg => [TestMessage2.new(:foo => 100)]) - m2 = Google::Protobuf.deep_copy(m) - assert m == m2 - assert m.repeated_msg == m2.repeated_msg - assert m.repeated_msg.object_id != m2.repeated_msg.object_id - assert m.repeated_msg[0].object_id != m2.repeated_msg[0].object_id - end - - def test_eq - m = TestMessage.new(:optional_int32 => 42, - :repeated_int32 => [1, 2, 3]) - m2 = TestMessage.new(:optional_int32 => 43, - :repeated_int32 => [1, 2, 3]) - assert m != m2 - end - - def test_enum_lookup - assert TestEnum::A == 1 - assert TestEnum::B == 2 - assert TestEnum::C == 3 - - assert TestEnum::lookup(1) == :A - assert TestEnum::lookup(2) == :B - assert TestEnum::lookup(3) == :C - - assert TestEnum::resolve(:A) == 1 - assert TestEnum::resolve(:B) == 2 - assert TestEnum::resolve(:C) == 3 - end - - def test_parse_serialize - m = TestMessage.new(:optional_int32 => 42, - :optional_string => "hello world", - :optional_enum => :B, - :repeated_string => ["a", "b", "c"], - :repeated_int32 => [42, 43, 44], - :repeated_enum => [:A, :B, :C, 100], - :repeated_msg => [TestMessage2.new(:foo => 1), - TestMessage2.new(:foo => 2)]) - data = TestMessage.encode m - m2 = TestMessage.decode data - assert m == m2 - - data = Google::Protobuf.encode m - m2 = Google::Protobuf.decode(TestMessage, data) - assert m == m2 - end + def test_protobuf_decode_json_ignore_unknown_fields + m = TestMessage.decode_json({ + optional_string: "foo", + not_in_message: "some_value" + }.to_json, { ignore_unknown_fields: true }) - def test_encode_decode_helpers - m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2']) - assert_equal 'foo', m.optional_string - assert_equal ['bar1', 'bar2'], m.repeated_string - - json = m.to_json - m2 = TestMessage.decode_json(json) - assert_equal 'foo', m2.optional_string - assert_equal ['bar1', 'bar2'], m2.repeated_string - if RUBY_PLATFORM != "java" - assert m2.optional_string.frozen? - assert m2.repeated_string[0].frozen? + assert_equal m.optional_string, "foo" + e = assert_raise Google::Protobuf::ParseError do + TestMessage.decode_json({ not_in_message: "some_value" }.to_json) end - - proto = m.to_proto - m2 = TestMessage.decode(proto) - assert_equal 'foo', m2.optional_string - assert_equal ['bar1', 'bar2'], m2.repeated_string + assert_match(/No such field: not_in_message/, e.message) end - def test_protobuf_encode_decode_helpers - m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2']) - encoded_msg = Google::Protobuf.encode(m) - assert_equal m.to_proto, encoded_msg - - decoded_msg = Google::Protobuf.decode(TestMessage, encoded_msg) - assert_equal TestMessage.decode(m.to_proto), decoded_msg - end - - def test_protobuf_encode_decode_json_helpers - m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2']) - encoded_msg = Google::Protobuf.encode_json(m) - assert_equal m.to_json, encoded_msg - - decoded_msg = Google::Protobuf.decode_json(TestMessage, encoded_msg) - assert_equal TestMessage.decode_json(m.to_json), decoded_msg - end + #def test_json_quoted_string + # m = TestMessage.decode_json(%q( + # "optionalInt64": "1",, + # })) + # puts(m) + # assert_equal 1, m.optional_int32 + #end def test_to_h - m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2']) + m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'], :repeated_msg => [TestMessage2.new(:foo => 100)]) expected_result = { :optional_bool=>true, :optional_bytes=>"", @@ -912,6 +447,7 @@ def test_to_h :optional_int32=>0, :optional_int64=>0, :optional_msg=>nil, + :optional_msg2=>nil, :optional_string=>"foo", :optional_uint32=>0, :optional_uint64=>0, @@ -922,7 +458,7 @@ def test_to_h :repeated_float=>[], :repeated_int32=>[], :repeated_int64=>[], - :repeated_msg=>[], + :repeated_msg=>[{:foo => 100}], :repeated_string=>["bar1", "bar2"], :repeated_uint32=>[], :repeated_uint64=>[] @@ -932,400 +468,105 @@ def test_to_h m = MapMessage.new( :map_string_int32 => {"a" => 1, "b" => 2}, :map_string_msg => {"a" => TestMessage2.new(:foo => 1), - "b" => TestMessage2.new(:foo => 2)}) + "b" => TestMessage2.new(:foo => 2)}, + :map_string_enum => {"a" => :A, "b" => :B}) expected_result = { :map_string_int32 => {"a" => 1, "b" => 2}, - :map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}} + :map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}}, + :map_string_enum => {"a" => :A, "b" => :B} } assert_equal expected_result, m.to_h end - def test_def_errors - s = Google::Protobuf::DescriptorPool.new - assert_raise TypeError do - s.build do - # enum with no default (integer value 0) - add_enum "MyEnum" do - value :A, 1 - end - end - end - assert_raise TypeError do - s.build do - # message with required field (unsupported in proto3) - add_message "MyMessage" do - required :foo, :int32, 1 - end - end - end - end - - def test_corecursive - # just be sure that we can instantiate types with corecursive field-type - # references. - m = Recursive1.new(:foo => Recursive2.new(:foo => Recursive1.new)) - assert Recursive1.descriptor.lookup("foo").subtype == - Recursive2.descriptor - assert Recursive2.descriptor.lookup("foo").subtype == - Recursive1.descriptor - - serialized = Recursive1.encode(m) - m2 = Recursive1.decode(serialized) - assert m == m2 - end - - def test_serialize_cycle - m = Recursive1.new(:foo => Recursive2.new) - m.foo.foo = m - assert_raise RuntimeError do - serialized = Recursive1.encode(m) - end - end - - def test_bad_field_names - m = BadFieldNames.new(:dup => 1, :class => 2) - m2 = m.dup - assert m == m2 - assert m['dup'] == 1 - assert m['class'] == 2 - m['dup'] = 3 - assert m['dup'] == 3 - m['a.b'] = 4 - assert m['a.b'] == 4 - end - - def test_int_ranges - m = TestMessage.new - - m.optional_int32 = 0 - m.optional_int32 = -0x8000_0000 - m.optional_int32 = +0x7fff_ffff - m.optional_int32 = 1.0 - m.optional_int32 = -1.0 - m.optional_int32 = 2e9 - assert_raise RangeError do - m.optional_int32 = -0x8000_0001 - end - assert_raise RangeError do - m.optional_int32 = +0x8000_0000 - end - assert_raise RangeError do - m.optional_int32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum - end - assert_raise RangeError do - m.optional_int32 = 1e12 - end - assert_raise RangeError do - m.optional_int32 = 1.5 - end - - m.optional_uint32 = 0 - m.optional_uint32 = +0xffff_ffff - m.optional_uint32 = 1.0 - m.optional_uint32 = 4e9 - assert_raise RangeError do - m.optional_uint32 = -1 - end - assert_raise RangeError do - m.optional_uint32 = -1.5 - end - assert_raise RangeError do - m.optional_uint32 = -1.5e12 - end - assert_raise RangeError do - m.optional_uint32 = -0x1000_0000_0000_0000 - end - assert_raise RangeError do - m.optional_uint32 = +0x1_0000_0000 - end - assert_raise RangeError do - m.optional_uint32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum - end - assert_raise RangeError do - m.optional_uint32 = 1e12 - end - assert_raise RangeError do - m.optional_uint32 = 1.5 - end - - m.optional_int64 = 0 - m.optional_int64 = -0x8000_0000_0000_0000 - m.optional_int64 = +0x7fff_ffff_ffff_ffff - m.optional_int64 = 1.0 - m.optional_int64 = -1.0 - m.optional_int64 = 8e18 - m.optional_int64 = -8e18 - assert_raise RangeError do - m.optional_int64 = -0x8000_0000_0000_0001 - end - assert_raise RangeError do - m.optional_int64 = +0x8000_0000_0000_0000 - end - assert_raise RangeError do - m.optional_int64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum - end - assert_raise RangeError do - m.optional_int64 = 1e50 - end - assert_raise RangeError do - m.optional_int64 = 1.5 - end - - m.optional_uint64 = 0 - m.optional_uint64 = +0xffff_ffff_ffff_ffff - m.optional_uint64 = 1.0 - m.optional_uint64 = 16e18 - assert_raise RangeError do - m.optional_uint64 = -1 - end - assert_raise RangeError do - m.optional_uint64 = -1.5 - end - assert_raise RangeError do - m.optional_uint64 = -1.5e12 - end - assert_raise RangeError do - m.optional_uint64 = -0x1_0000_0000_0000_0000 - end - assert_raise RangeError do - m.optional_uint64 = +0x1_0000_0000_0000_0000 - end - assert_raise RangeError do - m.optional_uint64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum - end - assert_raise RangeError do - m.optional_uint64 = 1e50 - end - assert_raise RangeError do - m.optional_uint64 = 1.5 - end - end - - def test_stress_test - m = TestMessage.new - m.optional_int32 = 42 - m.optional_int64 = 0x100000000 - m.optional_string = "hello world" - 10.times do m.repeated_msg.push TestMessage2.new(:foo => 42) end - 10.times do m.repeated_string.push "hello world" end - - data = TestMessage.encode(m) - - l = 0 - 10_000.times do - m = TestMessage.decode(data) - data_new = TestMessage.encode(m) - assert data_new == data - data = data_new - end - end - - def test_reflection - m = TestMessage.new(:optional_int32 => 1234) - msgdef = m.class.descriptor - assert msgdef.class == Google::Protobuf::Descriptor - assert msgdef.any? {|field| field.name == "optional_int32"} - optional_int32 = msgdef.lookup "optional_int32" - assert optional_int32.class == Google::Protobuf::FieldDescriptor - assert optional_int32 != nil - assert optional_int32.name == "optional_int32" - assert optional_int32.type == :int32 - optional_int32.set(m, 5678) - assert m.optional_int32 == 5678 - m.optional_int32 = 1000 - assert optional_int32.get(m) == 1000 - - optional_msg = msgdef.lookup "optional_msg" - assert optional_msg.subtype == TestMessage2.descriptor - - optional_msg.set(m, optional_msg.subtype.msgclass.new) - - assert msgdef.msgclass == TestMessage - - optional_enum = msgdef.lookup "optional_enum" - assert optional_enum.subtype == TestEnum.descriptor - assert optional_enum.subtype.class == Google::Protobuf::EnumDescriptor - optional_enum.subtype.each do |k, v| - # set with integer, check resolution to symbolic name - optional_enum.set(m, v) - assert optional_enum.get(m) == k - end - end - - def test_json + def test_json_maps # TODO: Fix JSON in JRuby version. return if RUBY_PLATFORM == "java" - m = TestMessage.new(:optional_int32 => 1234, - :optional_int64 => -0x1_0000_0000, - :optional_uint32 => 0x8000_0000, - :optional_uint64 => 0xffff_ffff_ffff_ffff, - :optional_bool => true, - :optional_float => 1.0, - :optional_double => -1e100, - :optional_string => "Test string", - :optional_bytes => ["FFFFFFFF"].pack('H*'), - :optional_msg => TestMessage2.new(:foo => 42), - :repeated_int32 => [1, 2, 3, 4], - :repeated_string => ["a", "b", "c"], - :repeated_bool => [true, false, true, false], - :repeated_msg => [TestMessage2.new(:foo => 1), - TestMessage2.new(:foo => 2)]) - - json_text = TestMessage.encode_json(m) - m2 = TestMessage.decode_json(json_text) - puts m.inspect - puts m2.inspect - assert m == m2 + m = MapMessage.new(:map_string_int32 => {"a" => 1}) + expected = {mapStringInt32: {a: 1}, mapStringMsg: {}, mapStringEnum: {}} + expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}, map_string_enum: {}} + assert_equal JSON.parse(MapMessage.encode_json(m, :emit_defaults=>true), :symbolize_names => true), expected + + json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true, :emit_defaults=>true) + assert_equal JSON.parse(json, :symbolize_names => true), expected_preserve - # Crash case from GitHub issue 283. - bar = Bar.new(msg: "bar") - baz1 = Baz.new(msg: "baz") - baz2 = Baz.new(msg: "quux") - Foo.encode_json(Foo.new) - Foo.encode_json(Foo.new(bar: bar)) - Foo.encode_json(Foo.new(bar: bar, baz: [baz1, baz2])) + m2 = MapMessage.decode_json(MapMessage.encode_json(m)) + assert_equal m, m2 end - def test_json_emit_defaults + def test_json_maps_emit_defaults_submsg # TODO: Fix JSON in JRuby version. return if RUBY_PLATFORM == "java" - m = TestMessage.new - - expected = { - optionalInt32: 0, - optionalInt64: 0, - optionalUint32: 0, - optionalUint64: 0, - optionalBool: false, - optionalFloat: 0, - optionalDouble: 0, - optionalString: "", - optionalBytes: "", - optionalEnum: "Default", - repeatedInt32: [], - repeatedInt64: [], - repeatedUint32: [], - repeatedUint64: [], - repeatedBool: [], - repeatedFloat: [], - repeatedDouble: [], - repeatedString: [], - repeatedBytes: [], - repeatedMsg: [], - repeatedEnum: [] - } + m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new(foo: 0)}) + expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}, mapStringEnum: {}} - actual = TestMessage.encode_json(m, :emit_defaults => true) + actual = MapMessage.encode_json(m, :emit_defaults => true) - assert JSON.parse(actual, :symbolize_names => true) == expected + assert_equal JSON.parse(actual, :symbolize_names => true), expected end def test_json_emit_defaults_submsg # TODO: Fix JSON in JRuby version. return if RUBY_PLATFORM == "java" - m = TestMessage.new(optional_msg: TestMessage2.new) + m = TestSingularFields.new(singular_msg: proto_module::TestMessage2.new) expected = { - optionalInt32: 0, - optionalInt64: 0, - optionalUint32: 0, - optionalUint64: 0, - optionalBool: false, - optionalFloat: 0, - optionalDouble: 0, - optionalString: "", - optionalBytes: "", - optionalMsg: {foo: 0}, - optionalEnum: "Default", - repeatedInt32: [], - repeatedInt64: [], - repeatedUint32: [], - repeatedUint64: [], - repeatedBool: [], - repeatedFloat: [], - repeatedDouble: [], - repeatedString: [], - repeatedBytes: [], - repeatedMsg: [], - repeatedEnum: [] + singularInt32: 0, + singularInt64: "0", + singularUint32: 0, + singularUint64: "0", + singularBool: false, + singularFloat: 0, + singularDouble: 0, + singularString: "", + singularBytes: "", + singularMsg: {}, + singularEnum: "Default", } - actual = TestMessage.encode_json(m, :emit_defaults => true) + actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true) - assert JSON.parse(actual, :symbolize_names => true) == expected + assert_equal expected, JSON.parse(actual, :symbolize_names => true) end - def test_json_emit_defaults_repeated_submsg - # TODO: Fix JSON in JRuby version. + def test_respond_to + # This test fails with JRuby 1.7.23, likely because of an old JRuby bug. return if RUBY_PLATFORM == "java" - m = TestMessage.new(repeated_msg: [TestMessage2.new]) - - expected = { - optionalInt32: 0, - optionalInt64: 0, - optionalUint32: 0, - optionalUint64: 0, - optionalBool: false, - optionalFloat: 0, - optionalDouble: 0, - optionalString: "", - optionalBytes: "", - optionalEnum: "Default", - repeatedInt32: [], - repeatedInt64: [], - repeatedUint32: [], - repeatedUint64: [], - repeatedBool: [], - repeatedFloat: [], - repeatedDouble: [], - repeatedString: [], - repeatedBytes: [], - repeatedMsg: [{foo: 0}], - repeatedEnum: [] - } - - actual = TestMessage.encode_json(m, :emit_defaults => true) - - assert JSON.parse(actual, :symbolize_names => true) == expected + msg = MapMessage.new + assert msg.respond_to?(:map_string_int32) + assert !msg.respond_to?(:bacon) end - def test_json_maps - # TODO: Fix JSON in JRuby version. - return if RUBY_PLATFORM == "java" - m = MapMessage.new(:map_string_int32 => {"a" => 1}) - expected = {mapStringInt32: {a: 1}, mapStringMsg: {}} - expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}} - assert JSON.parse(MapMessage.encode_json(m), :symbolize_names => true) == expected - - json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true) - assert JSON.parse(json, :symbolize_names => true) == expected_preserve + def test_file_descriptor + file_descriptor = TestMessage.descriptor.file_descriptor + assert nil != file_descriptor + assert_equal "tests/basic_test.proto", file_descriptor.name + assert_equal :proto3, file_descriptor.syntax - m2 = MapMessage.decode_json(MapMessage.encode_json(m)) - assert m == m2 + file_descriptor = TestEnum.descriptor.file_descriptor + assert nil != file_descriptor + assert_equal "tests/basic_test.proto", file_descriptor.name + assert_equal :proto3, file_descriptor.syntax end - def test_json_maps_emit_defaults_submsg - # TODO: Fix JSON in JRuby version. - return if RUBY_PLATFORM == "java" - m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new}) - expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}} + # Ruby 2.5 changed to raise FrozenError instead of RuntimeError + FrozenErrorType = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5') ? RuntimeError : FrozenError - actual = MapMessage.encode_json(m, :emit_defaults => true) + def test_map_freeze + m = proto_module::MapMessage.new + m.map_string_int32['a'] = 5 + m.map_string_msg['b'] = proto_module::TestMessage2.new - assert JSON.parse(actual, :symbolize_names => true) == expected - end + m.map_string_int32.freeze + m.map_string_msg.freeze - def test_comparison_with_arbitrary_object - assert MapMessage.new != nil - end + assert m.map_string_int32.frozen? + assert m.map_string_msg.frozen? - def test_respond_to - # This test fails with JRuby 1.7.23, likely because of an old JRuby bug. - return if RUBY_PLATFORM == "java" - msg = MapMessage.new - assert msg.respond_to?(:map_string_int32) - assert !msg.respond_to?(:bacon) + assert_raise(FrozenErrorType) { m.map_string_int32['foo'] = 1 } + assert_raise(FrozenErrorType) { m.map_string_msg['bar'] = proto_module::TestMessage2.new } + assert_raise(FrozenErrorType) { m.map_string_int32.delete('a') } + assert_raise(FrozenErrorType) { m.map_string_int32.clear } end end end diff --git a/ruby/tests/basic_proto2.rb b/ruby/tests/basic_proto2.rb new file mode 100755 index 0000000000000..a7114ea6edf53 --- /dev/null +++ b/ruby/tests/basic_proto2.rb @@ -0,0 +1,259 @@ +#!/usr/bin/ruby + +# basic_test_pb.rb is in the same directory as this test. +$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) + +require 'basic_test_proto2_pb' +require 'common_tests' +require 'google/protobuf' +require 'json' +require 'test/unit' + +# ------------- generated code -------------- + +module BasicTestProto2 + pool = Google::Protobuf::DescriptorPool.new + pool.build do + add_file "test_proto2.proto", syntax: :proto2 do + add_message "BadFieldNames" do + optional :dup, :int32, 1 + optional :class, :int32, 2 + end + end + end + + BadFieldNames = pool.lookup("BadFieldNames").msgclass + +# ------------ test cases --------------- + + class MessageContainerTest < Test::Unit::TestCase + # Required by CommonTests module to resolve proto2 proto classes used in tests. + def proto_module + ::BasicTestProto2 + end + include CommonTests + + def test_has_field + m = TestMessage.new + assert !m.has_optional_int32? + assert !TestMessage.descriptor.lookup('optional_int32').has?(m) + assert !m.has_optional_int64? + assert !TestMessage.descriptor.lookup('optional_int64').has?(m) + assert !m.has_optional_uint32? + assert !TestMessage.descriptor.lookup('optional_uint32').has?(m) + assert !m.has_optional_uint64? + assert !TestMessage.descriptor.lookup('optional_uint64').has?(m) + assert !m.has_optional_bool? + assert !TestMessage.descriptor.lookup('optional_bool').has?(m) + assert !m.has_optional_float? + assert !TestMessage.descriptor.lookup('optional_float').has?(m) + assert !m.has_optional_double? + assert !TestMessage.descriptor.lookup('optional_double').has?(m) + assert !m.has_optional_string? + assert !TestMessage.descriptor.lookup('optional_string').has?(m) + assert !m.has_optional_bytes? + assert !TestMessage.descriptor.lookup('optional_bytes').has?(m) + assert !m.has_optional_enum? + assert !TestMessage.descriptor.lookup('optional_enum').has?(m) + + m = TestMessage.new(:optional_int32 => nil) + assert !m.has_optional_int32? + + assert_raise NoMethodError do + m.has_repeated_msg? + end + assert_raise ArgumentError do + TestMessage.descriptor.lookup('repeated_msg').has?(m) + end + + m.optional_msg = TestMessage2.new + assert m.has_optional_msg? + assert TestMessage.descriptor.lookup('optional_msg').has?(m) + + m = OneofMessage.new + assert !m.has_my_oneof? + m.a = "foo" + assert m.has_my_oneof? + assert_equal :a, m.my_oneof + assert m.has_a? + assert OneofMessage.descriptor.lookup('a').has?(m) + assert_equal "foo", m.a + assert !m.has_b? + assert !OneofMessage.descriptor.lookup('b').has?(m) + assert !m.has_c? + assert !OneofMessage.descriptor.lookup('c').has?(m) + assert !m.has_d? + assert !OneofMessage.descriptor.lookup('d').has?(m) + + m = OneofMessage.new + m.b = 100 + assert m.has_b? + assert_equal 100, m.b + assert m.has_my_oneof? + assert !m.has_a? + assert !m.has_c? + assert !m.has_d? + + m = OneofMessage.new + m.c = TestMessage2.new + assert m.has_c? + assert_equal TestMessage2.new, m.c + assert m.has_my_oneof? + assert !m.has_a? + assert !m.has_b? + assert !m.has_d? + + m = OneofMessage.new + m.d = :A + assert m.has_d? + assert_equal :A, m.d + assert m.has_my_oneof? + assert !m.has_a? + assert !m.has_b? + assert !m.has_c? + end + + def test_defined_defaults + m = TestMessageDefaults.new + assert_equal 1, m.optional_int32 + assert_equal 2, m.optional_int64 + assert_equal 3, m.optional_uint32 + assert_equal 4, m.optional_uint64 + assert_equal true, m.optional_bool + assert_equal 6.0, m.optional_float + assert_equal 7.0, m.optional_double + assert_equal "Default Str", m.optional_string + assert_equal "\xCF\xA5s\xBD\xBA\xE6fubar".force_encoding("ASCII-8BIT"), m.optional_bytes + assert_equal :B2, m.optional_enum + + assert !m.has_optional_int32? + assert !m.has_optional_int64? + assert !m.has_optional_uint32? + assert !m.has_optional_uint64? + assert !m.has_optional_bool? + assert !m.has_optional_float? + assert !m.has_optional_double? + assert !m.has_optional_string? + assert !m.has_optional_bytes? + assert !m.has_optional_enum? + end + + def test_set_clear_defaults + m = TestMessageDefaults.new + + m.optional_int32 = -42 + assert_equal -42, m.optional_int32 + assert m.has_optional_int32? + m.clear_optional_int32 + assert_equal 1, m.optional_int32 + assert !m.has_optional_int32? + + m.optional_string = "foo bar" + assert_equal "foo bar", m.optional_string + assert m.has_optional_string? + m.clear_optional_string + assert_equal "Default Str", m.optional_string + assert !m.has_optional_string? + + m.optional_msg = TestMessage2.new(:foo => 42) + assert_equal TestMessage2.new(:foo => 42), m.optional_msg + assert m.has_optional_msg? + + m.clear_optional_msg + assert_equal nil, m.optional_msg + assert !m.has_optional_msg? + + m.optional_msg = TestMessage2.new(:foo => 42) + assert_equal TestMessage2.new(:foo => 42), m.optional_msg + assert TestMessageDefaults.descriptor.lookup('optional_msg').has?(m) + + TestMessageDefaults.descriptor.lookup('optional_msg').clear(m) + assert_equal nil, m.optional_msg + assert !TestMessageDefaults.descriptor.lookup('optional_msg').has?(m) + + m = TestMessage.new + m.repeated_int32.push(1) + assert_equal [1], m.repeated_int32 + m.clear_repeated_int32 + assert_equal [], m.repeated_int32 + + m = OneofMessage.new + m.a = "foo" + assert_equal "foo", m.a + assert m.has_a? + m.clear_a + assert !m.has_a? + + m = OneofMessage.new + m.a = "foobar" + assert m.has_my_oneof? + m.clear_my_oneof + assert !m.has_my_oneof? + + m = OneofMessage.new + m.a = "bar" + assert_equal "bar", m.a + assert m.has_my_oneof? + OneofMessage.descriptor.lookup('a').clear(m) + assert !m.has_my_oneof? + end + + def test_assign_nil + m = TestMessageDefaults.new + m.optional_msg = TestMessage2.new(:foo => 42) + + assert_equal TestMessage2.new(:foo => 42), m.optional_msg + assert m.has_optional_msg? + m.optional_msg = nil + assert_equal nil, m.optional_msg + assert !m.has_optional_msg? + end + + def test_initialization_map_errors + e = assert_raise ArgumentError do + TestMessage.new(:hello => "world") + end + assert_match(/hello/, e.message) + + e = assert_raise ArgumentError do + TestMessage.new(:repeated_uint32 => "hello") + end + assert_equal e.message, "Expected array as initializer value for repeated field 'repeated_uint32' (given String)." + end + + + def test_to_h + m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2']) + expected_result = { + :optional_bool=>true, + :optional_double=>-10.100001, + :optional_string=>"foo", + :repeated_string=>["bar1", "bar2"], + } + assert_equal expected_result, m.to_h + + m = OneofMessage.new(:a => "foo") + expected_result = {:a => "foo"} + assert_equal expected_result, m.to_h + end + + def test_respond_to + # This test fails with JRuby 1.7.23, likely because of an old JRuby bug. + return if RUBY_PLATFORM == "java" + msg = TestMessage.new + assert !msg.respond_to?(:bacon) + end + + def test_file_descriptor + file_descriptor = TestMessage.descriptor.file_descriptor + assert nil != file_descriptor + assert_equal "tests/basic_test_proto2.proto", file_descriptor.name + assert_equal :proto2, file_descriptor.syntax + + file_descriptor = TestEnum.descriptor.file_descriptor + assert nil != file_descriptor + assert_equal "tests/basic_test_proto2.proto", file_descriptor.name + assert_equal :proto2, file_descriptor.syntax + end + end +end diff --git a/ruby/tests/basic_test.proto b/ruby/tests/basic_test.proto new file mode 100644 index 0000000000000..5b4ed6311c78f --- /dev/null +++ b/ruby/tests/basic_test.proto @@ -0,0 +1,210 @@ +syntax = "proto3"; + +package basic_test; + +import "google/protobuf/wrappers.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; + +message Foo { + Bar bar = 1; + repeated Baz baz = 2; +} + +message Bar { + string msg = 1; +} + +message Baz { + string msg = 1; +} + +message TestMessage { + optional int32 optional_int32 = 1; + optional int64 optional_int64 = 2; + optional uint32 optional_uint32 = 3; + optional uint64 optional_uint64 = 4; + optional bool optional_bool = 5; + optional float optional_float = 6; + optional double optional_double = 7; + optional string optional_string = 8; + optional bytes optional_bytes = 9; + optional TestMessage2 optional_msg = 10; + optional TestEnum optional_enum = 11; + + repeated int32 repeated_int32 = 12; + repeated int64 repeated_int64 = 13; + repeated uint32 repeated_uint32 = 14; + repeated uint64 repeated_uint64 = 15; + repeated bool repeated_bool = 16; + repeated float repeated_float = 17; + repeated double repeated_double = 18; + repeated string repeated_string = 19; + repeated bytes repeated_bytes = 20; + repeated TestMessage2 repeated_msg = 21; + repeated TestEnum repeated_enum = 22; + + optional TestSingularFields optional_msg2 = 23; +} + +message TestSingularFields { + int32 singular_int32 = 1; + int64 singular_int64 = 2; + uint32 singular_uint32 = 3; + uint64 singular_uint64 = 4; + bool singular_bool = 5; + float singular_float = 6; + double singular_double = 7; + string singular_string = 8; + bytes singular_bytes = 9; + TestMessage2 singular_msg = 10; + TestEnum singular_enum = 11; +} + +message TestMessage2 { + optional int32 foo = 1; +} + +enum TestEnum { + Default = 0; + A = 1; + B = 2; + C = 3; +} + +message TestEmbeddedMessageParent { + TestEmbeddedMessageChild child_msg = 1; + int32 number = 2; + + repeated TestEmbeddedMessageChild repeated_msg = 3; + repeated int32 repeated_number = 4; +} + +message TestEmbeddedMessageChild { + TestMessage sub_child = 1; +} + +message Recursive1 { + Recursive2 foo = 1; +} + +message Recursive2 { + Recursive1 foo = 1; +} + +message MapMessage { + map map_string_int32 = 1; + map map_string_msg = 2; + map map_string_enum = 3; +} + +message MapMessageWireEquiv { + repeated MapMessageWireEquiv_entry1 map_string_int32 = 1; + repeated MapMessageWireEquiv_entry2 map_string_msg = 2; +} + +message MapMessageWireEquiv_entry1 { + string key = 1; + int32 value = 2; +} + +message MapMessageWireEquiv_entry2 { + string key = 1; + TestMessage2 value = 2; +} + +message OneofMessage { + oneof my_oneof { + string a = 1; + int32 b = 2; + TestMessage2 c = 3; + TestEnum d = 4; + } +} + +message Outer { + map items = 1; +} + +message Inner { +} + +message Wrapper { + google.protobuf.DoubleValue double = 1; + google.protobuf.FloatValue float = 2; + google.protobuf.Int32Value int32 = 3; + google.protobuf.Int64Value int64 = 4; + google.protobuf.UInt32Value uint32 = 5; + google.protobuf.UInt64Value uint64 = 6; + google.protobuf.BoolValue bool = 7; + google.protobuf.StringValue string = 8; + google.protobuf.BytesValue bytes = 9; + string real_string = 100; + oneof a_oneof { + string string_in_oneof = 10; + } + + // Repeated wrappers don't make sense, but we still need to make sure they + // work and don't crash. + repeated google.protobuf.DoubleValue repeated_double = 11; + repeated google.protobuf.FloatValue repeated_float = 12; + repeated google.protobuf.Int32Value repeated_int32 = 13; + repeated google.protobuf.Int64Value repeated_int64 = 14; + repeated google.protobuf.UInt32Value repeated_uint32 = 15; + repeated google.protobuf.UInt64Value repeated_uint64 = 16; + repeated google.protobuf.BoolValue repeated_bool = 17; + repeated google.protobuf.StringValue repeated_string = 18; + repeated google.protobuf.BytesValue repeated_bytes = 19; + + // Wrappers as map keys don't make sense, but we still need to make sure they + // work and don't crash. + map map_double = 21; + map map_float = 22; + map map_int32 = 23; + map map_int64 = 24; + map map_uint32 = 25; + map map_uint64 = 26; + map map_bool = 27; + map map_string = 28; + map map_bytes = 29; + + // Wrappers in oneofs don't make sense, but we still need to make sure they + // work and don't crash. + oneof wrapper_oneof { + google.protobuf.DoubleValue oneof_double = 31; + google.protobuf.FloatValue oneof_float = 32; + google.protobuf.Int32Value oneof_int32 = 33; + google.protobuf.Int64Value oneof_int64 = 34; + google.protobuf.UInt32Value oneof_uint32 = 35; + google.protobuf.UInt64Value oneof_uint64 = 36; + google.protobuf.BoolValue oneof_bool = 37; + google.protobuf.StringValue oneof_string = 38; + google.protobuf.BytesValue oneof_bytes = 39; + string oneof_plain_string = 101; + } +} + +message TimeMessage { + google.protobuf.Timestamp timestamp = 1; + google.protobuf.Duration duration = 2; +} + +message Enumer { + TestEnum optional_enum = 1; + repeated TestEnum repeated_enum = 2; + string a_const = 3; + oneof a_oneof { + string str = 10; + TestEnum const = 11; + } +} + +message MyRepeatedStruct { + repeated MyStruct structs = 1; +} + +message MyStruct { + string string = 1; + google.protobuf.Struct struct = 2; +} diff --git a/ruby/tests/basic_test_proto2.proto b/ruby/tests/basic_test_proto2.proto new file mode 100644 index 0000000000000..0c1a2b98363f0 --- /dev/null +++ b/ruby/tests/basic_test_proto2.proto @@ -0,0 +1,189 @@ +syntax = "proto2"; + +package basic_test_proto2; + +import "google/protobuf/wrappers.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; + +message Foo { + optional Bar bar = 1; + repeated Baz baz = 2; +} + +message Bar { + optional string msg = 1; +} + +message Baz { + optional string msg = 1; +} + +message TestMessage { + optional int32 optional_int32 = 1; + optional int64 optional_int64 = 2; + optional uint32 optional_uint32 = 3; + optional uint64 optional_uint64 = 4; + optional bool optional_bool = 5; + optional float optional_float = 6; + optional double optional_double = 7; + optional string optional_string = 8; + optional bytes optional_bytes = 9; + optional TestMessage2 optional_msg = 10; + optional TestEnum optional_enum = 11; + + repeated int32 repeated_int32 = 12; + repeated int64 repeated_int64 = 13; + repeated uint32 repeated_uint32 = 14; + repeated uint64 repeated_uint64 = 15; + repeated bool repeated_bool = 16; + repeated float repeated_float = 17; + repeated double repeated_double = 18; + repeated string repeated_string = 19; + repeated bytes repeated_bytes = 20; + repeated TestMessage2 repeated_msg = 21; + repeated TestEnum repeated_enum = 22; +} + +message TestMessage2 { + optional int32 foo = 1; +} + +message TestMessageDefaults { + optional int32 optional_int32 = 1 [default = 1]; + optional int64 optional_int64 = 2 [default = 2]; + optional uint32 optional_uint32 = 3 [default = 3]; + optional uint64 optional_uint64 = 4 [default = 4]; + optional bool optional_bool = 5 [default = true]; + optional float optional_float = 6 [default = 6]; + optional double optional_double = 7 [default = 7]; + optional string optional_string = 8 [default = "Default Str"]; + optional bytes optional_bytes = 9 [default = "\xCF\xA5s\xBD\xBA\xE6fubar"]; + optional TestMessage2 optional_msg = 10; + optional TestNonZeroEnum optional_enum = 11 [default = B2]; +} + +enum TestEnum { + Default = 0; + A = 1; + B = 2; + C = 3; +} + +enum TestNonZeroEnum { + A2 = 1; + B2 = 2; + C2 = 3; +} + +message TestEmbeddedMessageParent { + optional TestEmbeddedMessageChild child_msg = 1; + optional int32 number = 2; + + repeated TestEmbeddedMessageChild repeated_msg = 3; + repeated int32 repeated_number = 4; +} + +message TestEmbeddedMessageChild { + optional TestMessage sub_child = 1; +} + +message Recursive1 { + optional Recursive2 foo = 1; +} + +message Recursive2 { + optional Recursive1 foo = 1; +} + +message MapMessageWireEquiv { + repeated MapMessageWireEquiv_entry1 map_string_int32 = 1; + repeated MapMessageWireEquiv_entry2 map_string_msg = 2; +} + +message MapMessageWireEquiv_entry1 { + optional string key = 1; + optional int32 value = 2; +} + +message MapMessageWireEquiv_entry2 { + optional string key = 1; + optional TestMessage2 value = 2; +} + +message OneofMessage { + oneof my_oneof { + string a = 1; + int32 b = 2; + TestMessage2 c = 3; + TestEnum d = 4; + } +} + +message Wrapper { + optional google.protobuf.DoubleValue double = 1; + optional google.protobuf.FloatValue float = 2; + optional google.protobuf.Int32Value int32 = 3; + optional google.protobuf.Int64Value int64 = 4; + optional google.protobuf.UInt32Value uint32 = 5; + optional google.protobuf.UInt64Value uint64 = 6; + optional google.protobuf.BoolValue bool = 7; + optional google.protobuf.StringValue string = 8; + optional google.protobuf.BytesValue bytes = 9; + optional string real_string = 100; + oneof a_oneof { + string string_in_oneof = 10; + } + + // Repeated wrappers don't really make sense, but we still need to make sure + // they work and don't crash. + repeated google.protobuf.DoubleValue repeated_double = 11; + repeated google.protobuf.FloatValue repeated_float = 12; + repeated google.protobuf.Int32Value repeated_int32 = 13; + repeated google.protobuf.Int64Value repeated_int64 = 14; + repeated google.protobuf.UInt32Value repeated_uint32 = 15; + repeated google.protobuf.UInt64Value repeated_uint64 = 16; + repeated google.protobuf.BoolValue repeated_bool = 17; + repeated google.protobuf.StringValue repeated_string = 18; + repeated google.protobuf.BytesValue repeated_bytes = 19; + + // Wrappers in oneofs don't make sense, but we still need to make sure they + // work and don't crash. + oneof wrapper_oneof { + google.protobuf.DoubleValue oneof_double = 31; + google.protobuf.FloatValue oneof_float = 32; + google.protobuf.Int32Value oneof_int32 = 33; + google.protobuf.Int64Value oneof_int64 = 34; + google.protobuf.UInt32Value oneof_uint32 = 35; + google.protobuf.UInt64Value oneof_uint64 = 36; + google.protobuf.BoolValue oneof_bool = 37; + google.protobuf.StringValue oneof_string = 38; + google.protobuf.BytesValue oneof_bytes = 39; + string oneof_plain_string = 101; + } +} + +message TimeMessage { + optional google.protobuf.Timestamp timestamp = 1; + optional google.protobuf.Duration duration = 2; +} + +message Enumer { + optional TestEnum optional_enum = 11; + repeated TestEnum repeated_enum = 22; + optional string a_const = 3; + oneof a_oneof { + string str = 100; + TestEnum const = 101; + } +} + +message MyRepeatedStruct { + repeated MyStruct structs = 1; +} + +message MyStruct { + optional string string = 1; + optional google.protobuf.Struct struct = 2; +} diff --git a/ruby/tests/common_tests.rb b/ruby/tests/common_tests.rb new file mode 100644 index 0000000000000..589934b0e92f6 --- /dev/null +++ b/ruby/tests/common_tests.rb @@ -0,0 +1,1782 @@ +require 'google/protobuf/wrappers_pb.rb' + +# Defines tests which are common between proto2 and proto3 syntax. +# +# Requires that the proto messages are exactly the same in proto2 and proto3 syntax +# and that the including class should define a 'proto_module' method which returns +# the enclosing module of the proto message classes. + +require 'bigdecimal' + +module CommonTests + # Ruby 2.5 changed to raise FrozenError instead of RuntimeError + FrozenErrorType = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5') ? RuntimeError : FrozenError + + def test_defaults + m = proto_module::TestMessage.new + assert m.optional_int32 == 0 + assert m.optional_int64 == 0 + assert m.optional_uint32 == 0 + assert m.optional_uint64 == 0 + assert m.optional_bool == false + assert m.optional_float == 0.0 + assert m.optional_double == 0.0 + assert m.optional_string == "" + assert m.optional_bytes == "" + assert m.optional_msg == nil + assert m.optional_enum == :Default + end + + def test_setters + m = proto_module::TestMessage.new + m.optional_int32 = -42 + assert m.optional_int32 == -42 + m.optional_int64 = -0x1_0000_0000 + assert m.optional_int64 == -0x1_0000_0000 + m.optional_uint32 = 0x9000_0000 + assert m.optional_uint32 == 0x9000_0000 + m.optional_uint64 = 0x9000_0000_0000_0000 + assert m.optional_uint64 == 0x9000_0000_0000_0000 + m.optional_bool = true + assert m.optional_bool == true + m.optional_float = 0.5 + assert m.optional_float == 0.5 + m.optional_double = 0.5 + assert m.optional_double == 0.5 + m.optional_string = "hello" + assert m.optional_string == "hello" + m.optional_string = :hello + assert m.optional_string == "hello" + m.optional_bytes = "world".encode!('ASCII-8BIT') + assert m.optional_bytes == "world" + m.optional_msg = proto_module::TestMessage2.new(:foo => 42) + assert m.optional_msg == proto_module::TestMessage2.new(:foo => 42) + m.optional_msg = nil + assert m.optional_msg == nil + m.optional_enum = :C + assert m.optional_enum == :C + m.optional_enum = 'C' + assert m.optional_enum == :C + end + + def test_ctor_args + m = proto_module::TestMessage.new(:optional_int32 => -42, + :optional_msg => proto_module::TestMessage2.new, + :optional_enum => :C, + :repeated_string => ["hello", "there", "world"]) + assert m.optional_int32 == -42 + assert m.optional_msg.class == proto_module::TestMessage2 + assert m.repeated_string.length == 3 + assert m.optional_enum == :C + assert m.repeated_string[0] == "hello" + assert m.repeated_string[1] == "there" + assert m.repeated_string[2] == "world" + end + + def test_ctor_string_symbol_args + m = proto_module::TestMessage.new(:optional_enum => 'C', :repeated_enum => ['A', 'B']) + assert_equal :C, m.optional_enum + assert_equal [:A, :B], m.repeated_enum + + m = proto_module::TestMessage.new(:optional_string => :foo, :repeated_string => [:foo, :bar]) + assert_equal 'foo', m.optional_string + assert_equal ['foo', 'bar'], m.repeated_string + end + + def test_ctor_nil_args + m = proto_module::TestMessage.new(:optional_enum => nil, :optional_int32 => nil, :optional_string => nil, :optional_msg => nil) + + assert_equal :Default, m.optional_enum + assert_equal 0, m.optional_int32 + assert_equal "", m.optional_string + assert_nil m.optional_msg + end + + def test_embeddedmsg_hash_init + m = proto_module::TestEmbeddedMessageParent.new( + :child_msg => {sub_child: {optional_int32: 1}}, + :number => 2, + :repeated_msg => [{sub_child: {optional_int32: 3}}], + :repeated_number => [10, 20, 30]) + + assert_equal 2, m.number + assert_equal [10, 20, 30], m.repeated_number + + assert_not_nil m.child_msg + assert_not_nil m.child_msg.sub_child + assert_equal m.child_msg.sub_child.optional_int32, 1 + + assert_not_nil m.repeated_msg + assert_equal 1, m.repeated_msg.length + assert_equal 3, m.repeated_msg.first.sub_child.optional_int32 + end + + def test_inspect_eq_to_s + m = proto_module::TestMessage.new( + :optional_int32 => -42, + :optional_enum => :A, + :optional_msg => proto_module::TestMessage2.new(foo: 0), + :repeated_string => ["hello", "there", "world"]) + expected = "<#{proto_module}::TestMessage: optional_int32: -42, optional_msg: <#{proto_module}::TestMessage2: foo: 0>, optional_enum: :A, repeated_int32: [], repeated_int64: [], repeated_uint32: [], repeated_uint64: [], repeated_bool: [], repeated_float: [], repeated_double: [], repeated_string: [\"hello\", \"there\", \"world\"], repeated_bytes: [], repeated_msg: [], repeated_enum: []>" + assert_equal expected, m.inspect + assert_equal expected, m.to_s + + m = proto_module::OneofMessage.new(:b => -42) + expected = "<#{proto_module}::OneofMessage: b: -42>" + assert_equal expected, m.inspect + assert_equal expected, m.to_s + end + + def test_hash + m1 = proto_module::TestMessage.new(:optional_int32 => 42) + m2 = proto_module::TestMessage.new(:optional_int32 => 102, repeated_string: ['please', 'work', 'ok?']) + m3 = proto_module::TestMessage.new(:optional_int32 => 102, repeated_string: ['please', 'work', 'ok?']) + assert m1.hash != 0 + assert m2.hash != 0 + assert m3.hash != 0 + # relying on the randomness here -- if hash function changes and we are + # unlucky enough to get a collision, then change the values above. + assert m1.hash != m2.hash + assert_equal m2.hash, m3.hash + end + + def test_unknown_field_errors + e = assert_raise NoMethodError do + proto_module::TestMessage.new.hello + end + assert_match(/hello/, e.message) + + e = assert_raise NoMethodError do + proto_module::TestMessage.new.hello = "world" + end + assert_match(/hello/, e.message) + end + + def test_type_errors + m = proto_module::TestMessage.new + e = assert_raise Google::Protobuf::TypeError do + m.optional_int32 = "hello" + end + + # Google::Protobuf::TypeError should inherit from TypeError for backwards compatibility + # TODO: This can be removed when we can safely migrate to Google::Protobuf::TypeError + assert e.is_a?(::TypeError) + + assert_raise Google::Protobuf::TypeError do + m.optional_string = 42 + end + assert_raise Google::Protobuf::TypeError do + m.optional_string = nil + end + assert_raise Google::Protobuf::TypeError do + m.optional_bool = 42 + end + assert_raise Google::Protobuf::TypeError do + m.optional_msg = proto_module::TestMessage.new # expects TestMessage2 + end + + assert_raise Google::Protobuf::TypeError do + m.repeated_int32 = [] # needs RepeatedField + end + + assert_raise Google::Protobuf::TypeError do + m.repeated_int32.push "hello" + end + + assert_raise Google::Protobuf::TypeError do + m.repeated_msg.push proto_module::TestMessage.new + end + end + + def test_string_encoding + m = proto_module::TestMessage.new + + # Assigning a normal (ASCII or UTF8) string to a bytes field, or + # ASCII-8BIT to a string field will convert to the proper encoding. + m.optional_bytes = "Test string ASCII".encode!('ASCII') + assert m.optional_bytes.frozen? + assert_equal Encoding::ASCII_8BIT, m.optional_bytes.encoding + assert_equal "Test string ASCII", m.optional_bytes + + assert_raise Encoding::UndefinedConversionError do + m.optional_bytes = "Test string UTF-8 \u0100".encode!('UTF-8') + end + + assert_raise Encoding::UndefinedConversionError do + m.optional_string = ["FFFF"].pack('H*') + end + + # "Ordinary" use case. + m.optional_bytes = ["FFFF"].pack('H*') + m.optional_string = "\u0100" + + # strings are immutable so we can't do this, but serialize should catch it. + m.optional_string = "asdf".encode!('UTF-8') + assert_raise(FrozenErrorType) { m.optional_string.encode!('ASCII-8BIT') } + end + + def test_rptfield_int32 + l = Google::Protobuf::RepeatedField.new(:int32) + assert l.count == 0 + l = Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3]) + assert l.count == 3 + assert_equal [1, 2, 3], l + assert_equal l, [1, 2, 3] + l.push 4 + assert l == [1, 2, 3, 4] + dst_list = [] + l.each { |val| dst_list.push val } + assert dst_list == [1, 2, 3, 4] + assert l.to_a == [1, 2, 3, 4] + assert l[0] == 1 + assert l[3] == 4 + l[0] = 5 + assert l == [5, 2, 3, 4] + + l2 = l.dup + assert l == l2 + assert l.object_id != l2.object_id + l2.push 6 + assert l.count == 4 + assert l2.count == 5 + + assert l.inspect == '[5, 2, 3, 4]' + + l.concat([7, 8, 9]) + assert l == [5, 2, 3, 4, 7, 8, 9] + assert l.pop == 9 + assert l == [5, 2, 3, 4, 7, 8] + + assert_raise Google::Protobuf::TypeError do + m = proto_module::TestMessage.new + l.push m + end + + m = proto_module::TestMessage.new + m.repeated_int32 = l + assert m.repeated_int32 == [5, 2, 3, 4, 7, 8] + assert m.repeated_int32.object_id == l.object_id + l.push 42 + assert m.repeated_int32.pop == 42 + + l3 = l + l.dup + assert l3.count == l.count * 2 + l.count.times do |i| + assert l3[i] == l[i] + assert l3[l.count + i] == l[i] + end + + l.clear + assert l.count == 0 + l += [1, 2, 3, 4] + l.replace([5, 6, 7, 8]) + assert l == [5, 6, 7, 8] + + l4 = Google::Protobuf::RepeatedField.new(:int32) + l4[5] = 42 + assert l4 == [0, 0, 0, 0, 0, 42] + + l4 << 100 + assert l4 == [0, 0, 0, 0, 0, 42, 100] + l4 << 101 << 102 + assert l4 == [0, 0, 0, 0, 0, 42, 100, 101, 102] + end + + def test_parent_rptfield + #make sure we set the RepeatedField and can add to it + m = proto_module::TestMessage.new + assert m.repeated_string == [] + m.repeated_string << 'ok' + m.repeated_string.push('ok2') + assert m.repeated_string == ['ok', 'ok2'] + m.repeated_string += ['ok3'] + assert m.repeated_string == ['ok', 'ok2', 'ok3'] + end + + def test_rptfield_msg + l = Google::Protobuf::RepeatedField.new(:message, proto_module::TestMessage) + l.push proto_module::TestMessage.new + assert l.count == 1 + assert_raise Google::Protobuf::TypeError do + l.push proto_module::TestMessage2.new + end + assert_raise Google::Protobuf::TypeError do + l.push 42 + end + + l2 = l.dup + assert l2[0] == l[0] + assert l2[0].object_id == l[0].object_id + + l2 = Google::Protobuf.deep_copy(l) + assert l2[0] == l[0] + assert l2[0].object_id != l[0].object_id + + l3 = l + l2 + assert l3.count == 2 + assert l3[0] == l[0] + assert l3[1] == l2[0] + l3[0].optional_int32 = 1000 + assert l[0].optional_int32 == 1000 + + new_msg = proto_module::TestMessage.new(:optional_int32 => 200) + l4 = l + [new_msg] + assert l4.count == 2 + new_msg.optional_int32 = 1000 + assert l4[1].optional_int32 == 1000 + end + + def test_rptfield_enum + l = Google::Protobuf::RepeatedField.new(:enum, proto_module::TestEnum) + l.push :A + l.push :B + l.push :C + assert l.count == 3 + assert_raise RangeError do + l.push :D + end + assert l[0] == :A + + l.push 4 + assert l[3] == 4 + end + + def test_rptfield_initialize + assert_raise ArgumentError do + Google::Protobuf::RepeatedField.new + end + assert_raise ArgumentError do + Google::Protobuf::RepeatedField.new(:message) + end + assert_raise ArgumentError do + Google::Protobuf::RepeatedField.new([1, 2, 3]) + end + assert_raise ArgumentError do + Google::Protobuf::RepeatedField.new(:message, [proto_module::TestMessage2.new]) + end + end + + def test_rptfield_array_ducktyping + l = Google::Protobuf::RepeatedField.new(:int32) + length_methods = %w(count length size) + length_methods.each do |lm| + assert l.send(lm) == 0 + end + # out of bounds returns a nil + assert l[0] == nil + assert l[1] == nil + assert l[-1] == nil + l.push 4 + length_methods.each do |lm| + assert l.send(lm) == 1 + end + assert l[0] == 4 + assert l[1] == nil + assert l[-1] == 4 + assert l[-2] == nil + + l.push 2 + length_methods.each do |lm| + assert l.send(lm) == 2 + end + assert l[0] == 4 + assert l[1] == 2 + assert l[2] == nil + assert l[-1] == 2 + assert l[-2] == 4 + assert l[-3] == nil + + #adding out of scope will backfill with empty objects + end + + def test_map_basic + # allowed key types: + # :int32, :int64, :uint32, :uint64, :bool, :string, :bytes. + + m = Google::Protobuf::Map.new(:string, :int32) + m["asdf"] = 1 + assert m["asdf"] == 1 + m["jkl;"] = 42 + assert m == { "jkl;" => 42, "asdf" => 1 } + assert m.has_key?("asdf") + assert !m.has_key?("qwerty") + assert m.length == 2 + + m2 = m.dup + assert_equal m, m2 + assert m.hash != 0 + assert_equal m.hash, m2.hash + + collected = {} + m.each { |k,v| collected[v] = k } + assert collected == { 42 => "jkl;", 1 => "asdf" } + + assert m.delete("asdf") == 1 + assert !m.has_key?("asdf") + assert m["asdf"] == nil + assert !m.has_key?("asdf") + + # We only assert on inspect value when there is one map entry because the + # order in which elements appear is unspecified (depends on the internal + # hash function). We don't want a brittle test. + assert m.inspect == "{\"jkl;\"=>42}" + + assert m.keys == ["jkl;"] + assert m.values == [42] + + m.clear + assert m.length == 0 + assert m == {} + + assert_raise Google::Protobuf::TypeError do + m[1] = 1 + end + assert_raise RangeError do + m["asdf"] = 0x1_0000_0000 + end + end + + def test_map_ctor + m = Google::Protobuf::Map.new(:string, :int32, + {"a" => 1, "b" => 2, "c" => 3}) + assert m == {"a" => 1, "c" => 3, "b" => 2} + end + + def test_map_keytypes + m = Google::Protobuf::Map.new(:int32, :int32) + m[1] = 42 + m[-1] = 42 + assert_raise RangeError do + m[0x8000_0000] = 1 + end + assert_raise Google::Protobuf::TypeError do + m["asdf"] = 1 + end + + m = Google::Protobuf::Map.new(:int64, :int32) + m[0x1000_0000_0000_0000] = 1 + assert_raise RangeError do + m[0x1_0000_0000_0000_0000] = 1 + end + assert_raise Google::Protobuf::TypeError do + m["asdf"] = 1 + end + + m = Google::Protobuf::Map.new(:uint32, :int32) + m[0x8000_0000] = 1 + assert_raise RangeError do + m[0x1_0000_0000] = 1 + end + assert_raise RangeError do + m[-1] = 1 + end + + m = Google::Protobuf::Map.new(:uint64, :int32) + m[0x8000_0000_0000_0000] = 1 + assert_raise RangeError do + m[0x1_0000_0000_0000_0000] = 1 + end + assert_raise RangeError do + m[-1] = 1 + end + + m = Google::Protobuf::Map.new(:bool, :int32) + m[true] = 1 + m[false] = 2 + assert_raise Google::Protobuf::TypeError do + m[1] = 1 + end + assert_raise Google::Protobuf::TypeError do + m["asdf"] = 1 + end + + m = Google::Protobuf::Map.new(:string, :int32) + m["asdf"] = 1 + assert_raise Google::Protobuf::TypeError do + m[1] = 1 + end + assert_raise Encoding::UndefinedConversionError do + bytestring = ["FFFF"].pack("H*") + m[bytestring] = 1 + end + + m = Google::Protobuf::Map.new(:bytes, :int32) + bytestring = ["FFFF"].pack("H*") + m[bytestring] = 1 + # Allowed -- we will automatically convert to ASCII-8BIT. + m["asdf"] = 1 + assert_raise Google::Protobuf::TypeError do + m[1] = 1 + end + end + + def test_map_msg_enum_valuetypes + m = Google::Protobuf::Map.new(:string, :message, proto_module::TestMessage) + m["asdf"] = proto_module::TestMessage.new + assert_raise Google::Protobuf::TypeError do + m["jkl;"] = proto_module::TestMessage2.new + end + + m = Google::Protobuf::Map.new( + :string, :message, proto_module::TestMessage, + { "a" => proto_module::TestMessage.new(:optional_int32 => 42), + "b" => proto_module::TestMessage.new(:optional_int32 => 84) }) + assert m.length == 2 + assert m.values.map{|msg| msg.optional_int32}.sort == [42, 84] + + m = Google::Protobuf::Map.new(:string, :enum, proto_module::TestEnum, + { "x" => :A, "y" => :B, "z" => :C }) + assert m.length == 3 + assert m["z"] == :C + m["z"] = 2 + assert m["z"] == :B + m["z"] = 4 + assert m["z"] == 4 + assert_raise RangeError do + m["z"] = :Z + end + assert_raise RangeError do + m["z"] = "z" + end + end + + def test_map_dup_deep_copy + m = Google::Protobuf::Map.new( + :string, :message, proto_module::TestMessage, + { "a" => proto_module::TestMessage.new(:optional_int32 => 42), + "b" => proto_module::TestMessage.new(:optional_int32 => 84) }) + + m2 = m.dup + assert m.to_h == m2.to_h + assert m == m2 + assert m.object_id != m2.object_id + assert m["a"].object_id == m2["a"].object_id + assert m["b"].object_id == m2["b"].object_id + + m2 = Google::Protobuf.deep_copy(m) + assert m == m2 + assert m.object_id != m2.object_id + assert m["a"].object_id != m2["a"].object_id + assert m["b"].object_id != m2["b"].object_id + end + + def test_oneof_descriptors + d = proto_module::OneofMessage.descriptor + o = d.lookup_oneof("my_oneof") + assert o != nil + assert o.class == Google::Protobuf::OneofDescriptor + assert o.name == "my_oneof" + oneof_count = 0 + d.each_oneof{ |oneof| + oneof_count += 1 + assert oneof == o + } + assert oneof_count == 1 + assert o.count == 4 + field_names = o.map{|f| f.name}.sort + assert field_names == ["a", "b", "c", "d"] + end + + def test_oneof + d = proto_module::OneofMessage.new + assert d.a == "" + assert d.b == 0 + assert d.c == nil + assert d.d == :Default + assert d.my_oneof == nil + + d.a = "hi" + assert d.a == "hi" + assert d.b == 0 + assert d.c == nil + assert d.d == :Default + assert d.my_oneof == :a + + d.b = 42 + assert d.a == "" + assert d.b == 42 + assert d.c == nil + assert d.d == :Default + assert d.my_oneof == :b + + d.c = proto_module::TestMessage2.new(:foo => 100) + assert d.a == "" + assert d.b == 0 + assert d.c.foo == 100 + assert d.d == :Default + assert d.my_oneof == :c + + d.d = :C + assert d.a == "" + assert d.b == 0 + assert d.c == nil + assert d.d == :C + assert d.my_oneof == :d + + d2 = proto_module::OneofMessage.decode(proto_module::OneofMessage.encode(d)) + assert d2 == d + + encoded_field_a = proto_module::OneofMessage.encode(proto_module::OneofMessage.new(:a => "string")) + encoded_field_b = proto_module::OneofMessage.encode(proto_module::OneofMessage.new(:b => 1000)) + encoded_field_c = proto_module::OneofMessage.encode( + proto_module::OneofMessage.new(:c => proto_module::TestMessage2.new(:foo => 1))) + encoded_field_d = proto_module::OneofMessage.encode(proto_module::OneofMessage.new(:d => :B)) + + d3 = proto_module::OneofMessage.decode( + encoded_field_c + encoded_field_a + encoded_field_b + encoded_field_d) + assert d3.a == "" + assert d3.b == 0 + assert d3.c == nil + assert d3.d == :B + + d4 = proto_module::OneofMessage.decode( + encoded_field_c + encoded_field_a + encoded_field_b + encoded_field_d + + encoded_field_c) + assert d4.a == "" + assert d4.b == 0 + assert d4.c.foo == 1 + assert d4.d == :Default + + d5 = proto_module::OneofMessage.new(:a => "hello") + assert d5.a == "hello" + d5.a = nil + assert d5.a == "" + assert proto_module::OneofMessage.encode(d5) == '' + assert d5.my_oneof == nil + end + + def test_enum_field + m = proto_module::TestMessage.new + assert m.optional_enum == :Default + m.optional_enum = :A + assert m.optional_enum == :A + assert_raise RangeError do + m.optional_enum = :ASDF + end + m.optional_enum = 1 + assert m.optional_enum == :A + m.optional_enum = 100 + assert m.optional_enum == 100 + end + + def test_dup + m = proto_module::TestMessage.new + m.optional_string = "hello" + m.optional_int32 = 42 + tm1 = proto_module::TestMessage2.new(:foo => 100) + tm2 = proto_module::TestMessage2.new(:foo => 200) + m.repeated_msg.push tm1 + assert m.repeated_msg[-1] == tm1 + m.repeated_msg.push tm2 + assert m.repeated_msg[-1] == tm2 + m2 = m.dup + assert m == m2 + m.optional_int32 += 1 + assert m != m2 + assert m.repeated_msg[0] == m2.repeated_msg[0] + assert m.repeated_msg[0].object_id == m2.repeated_msg[0].object_id + end + + def test_deep_copy + m = proto_module::TestMessage.new(:optional_int32 => 42, + :repeated_msg => [proto_module::TestMessage2.new(:foo => 100)]) + m2 = Google::Protobuf.deep_copy(m) + assert m == m2 + assert m.repeated_msg == m2.repeated_msg + assert m.repeated_msg.object_id != m2.repeated_msg.object_id + assert m.repeated_msg[0].object_id != m2.repeated_msg[0].object_id + end + + def test_eq + m = proto_module::TestMessage.new(:optional_int32 => 42, + :repeated_int32 => [1, 2, 3]) + m2 = proto_module::TestMessage.new(:optional_int32 => 43, + :repeated_int32 => [1, 2, 3]) + assert m != m2 + end + + def test_enum_lookup + assert proto_module::TestEnum::A == 1 + assert proto_module::TestEnum::B == 2 + assert proto_module::TestEnum::C == 3 + + assert proto_module::TestEnum::lookup(1) == :A + assert proto_module::TestEnum::lookup(2) == :B + assert proto_module::TestEnum::lookup(3) == :C + + assert proto_module::TestEnum::resolve(:A) == 1 + assert proto_module::TestEnum::resolve(:B) == 2 + assert proto_module::TestEnum::resolve(:C) == 3 + end + + def test_enum_const_get_helpers + m = proto_module::TestMessage.new + assert_equal proto_module::TestEnum::Default, m.optional_enum_const + assert_equal proto_module::TestEnum.const_get(:Default), m.optional_enum_const + + m = proto_module::TestMessage.new({optional_enum: proto_module::TestEnum::A}) + assert_equal proto_module::TestEnum::A, m.optional_enum_const + assert_equal proto_module::TestEnum.const_get(:A), m.optional_enum_const + + m = proto_module::TestMessage.new({optional_enum: proto_module::TestEnum::B}) + assert_equal proto_module::TestEnum::B, m.optional_enum_const + assert_equal proto_module::TestEnum.const_get(:B), m.optional_enum_const + + m = proto_module::TestMessage.new({optional_enum: proto_module::TestEnum::C}) + assert_equal proto_module::TestEnum::C, m.optional_enum_const + assert_equal proto_module::TestEnum.const_get(:C), m.optional_enum_const + + m = proto_module::TestMessage2.new({foo: 2}) + assert_equal 2, m.foo + assert_raise(NoMethodError) { m.foo_ } + assert_raise(NoMethodError) { m.foo_X } + assert_raise(NoMethodError) { m.foo_XX } + assert_raise(NoMethodError) { m.foo_XXX } + assert_raise(NoMethodError) { m.foo_XXXX } + assert_raise(NoMethodError) { m.foo_XXXXX } + assert_raise(NoMethodError) { m.foo_XXXXXX } + + m = proto_module::Enumer.new({optional_enum: :B}) + assert_equal :B, m.optional_enum + assert_raise(NoMethodError) { m.optional_enum_ } + assert_raise(NoMethodError) { m.optional_enum_X } + assert_raise(NoMethodError) { m.optional_enum_XX } + assert_raise(NoMethodError) { m.optional_enum_XXX } + assert_raise(NoMethodError) { m.optional_enum_XXXX } + assert_raise(NoMethodError) { m.optional_enum_XXXXX } + assert_raise(NoMethodError) { m.optional_enum_XXXXXX } + end + + def test_enum_getter + m = proto_module::Enumer.new(:optional_enum => :B, :repeated_enum => [:A, :C]) + + assert_equal :B, m.optional_enum + assert_equal 2, m.optional_enum_const + assert_equal proto_module::TestEnum::B, m.optional_enum_const + assert_equal [:A, :C], m.repeated_enum + assert_equal [1, 3], m.repeated_enum_const + assert_equal [proto_module::TestEnum::A, proto_module::TestEnum::C], m.repeated_enum_const + end + + def test_enum_getter_oneof + m = proto_module::Enumer.new(:const => :C) + + assert_equal :C, m.const + assert_equal 3, m.const_const + assert_equal proto_module::TestEnum::C, m.const_const + end + + def test_enum_getter_only_enums + m = proto_module::Enumer.new(:optional_enum => :B, :a_const => 'thing') + + assert_equal 'thing', m.a_const + assert_equal :B, m.optional_enum + + assert_raise(NoMethodError) { m.a } + assert_raise(NoMethodError) { m.a_const_const } + end + + def test_repeated_push + m = proto_module::TestMessage.new + + m.repeated_string += ['one'] + m.repeated_string += %w[two three] + assert_equal %w[one two three], m.repeated_string + + m.repeated_string.push *['four', 'five'] + assert_equal %w[one two three four five], m.repeated_string + + m.repeated_string.push 'six', 'seven' + assert_equal %w[one two three four five six seven], m.repeated_string + + m = proto_module::TestMessage.new + + m.repeated_msg += [proto_module::TestMessage2.new(:foo => 1), proto_module::TestMessage2.new(:foo => 2)] + m.repeated_msg += [proto_module::TestMessage2.new(:foo => 3)] + m.repeated_msg.push proto_module::TestMessage2.new(:foo => 4), proto_module::TestMessage2.new(:foo => 5) + assert_equal [1, 2, 3, 4, 5], m.repeated_msg.map {|x| x.foo} + end + + def test_parse_serialize + m = proto_module::TestMessage.new(:optional_int32 => 42, + :optional_string => "hello world", + :optional_enum => :B, + :repeated_string => ["a", "b", "c"], + :repeated_int32 => [42, 43, 44], + :repeated_enum => [:A, :B, :C, 100], + :repeated_msg => [proto_module::TestMessage2.new(:foo => 1), + proto_module::TestMessage2.new(:foo => 2)]) + data = proto_module::TestMessage.encode m + m2 = proto_module::TestMessage.decode data + assert_equal m, m2 + + data = Google::Protobuf.encode m + m2 = Google::Protobuf.decode(proto_module::TestMessage, data) + assert m == m2 + end + + def test_encode_decode_helpers + m = proto_module::TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2']) + assert_equal 'foo', m.optional_string + assert_equal ['bar1', 'bar2'], m.repeated_string + + json = m.to_json + m2 = proto_module::TestMessage.decode_json(json) + assert_equal 'foo', m2.optional_string + assert_equal ['bar1', 'bar2'], m2.repeated_string + if RUBY_PLATFORM != "java" + assert m2.optional_string.frozen? + assert m2.repeated_string[0].frozen? + end + + proto = m.to_proto + m2 = proto_module::TestMessage.decode(proto) + assert_equal 'foo', m2.optional_string + assert_equal ['bar1', 'bar2'], m2.repeated_string + end + + def test_protobuf_encode_decode_helpers + m = proto_module::TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2']) + encoded_msg = Google::Protobuf.encode(m) + assert_equal m.to_proto, encoded_msg + + decoded_msg = Google::Protobuf.decode(proto_module::TestMessage, encoded_msg) + assert_equal proto_module::TestMessage.decode(m.to_proto), decoded_msg + end + + def test_protobuf_encode_decode_json_helpers + m = proto_module::TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2']) + encoded_msg = Google::Protobuf.encode_json(m) + assert_equal m.to_json, encoded_msg + + decoded_msg = Google::Protobuf.decode_json(proto_module::TestMessage, encoded_msg) + assert_equal proto_module::TestMessage.decode_json(m.to_json), decoded_msg + end + + def test_def_errors + s = Google::Protobuf::DescriptorPool.new + assert_raise Google::Protobuf::TypeError do + s.build do + # enum with no default (integer value 0) + add_enum "MyEnum" do + value :A, 1 + end + end + end + assert_raise Google::Protobuf::TypeError do + s.build do + # message with required field (unsupported in proto3) + add_message "MyMessage" do + required :foo, :int32, 1 + end + end + end + end + + def test_corecursive + # just be sure that we can instantiate types with corecursive field-type + # references. + m = proto_module::Recursive1.new(:foo => proto_module::Recursive2.new(:foo => proto_module::Recursive1.new)) + assert proto_module::Recursive1.descriptor.lookup("foo").subtype == + proto_module::Recursive2.descriptor + assert proto_module::Recursive2.descriptor.lookup("foo").subtype == + proto_module::Recursive1.descriptor + + serialized = proto_module::Recursive1.encode(m) + m2 = proto_module::Recursive1.decode(serialized) + assert m == m2 + end + + def test_serialize_cycle + m = proto_module::Recursive1.new(:foo => proto_module::Recursive2.new) + m.foo.foo = m + assert_raise RuntimeError do + proto_module::Recursive1.encode(m) + end + end + + def test_bad_field_names + m = proto_module::BadFieldNames.new(:dup => 1, :class => 2) + m2 = m.dup + assert m == m2 + assert m['dup'] == 1 + assert m['class'] == 2 + m['dup'] = 3 + assert m['dup'] == 3 + end + + def test_int_ranges + m = proto_module::TestMessage.new + + m.optional_int32 = 0 + m.optional_int32 = -0x8000_0000 + m.optional_int32 = +0x7fff_ffff + m.optional_int32 = 1.0 + m.optional_int32 = -1.0 + m.optional_int32 = 2e9 + assert_raise RangeError do + m.optional_int32 = -0x8000_0001 + end + assert_raise RangeError do + m.optional_int32 = +0x8000_0000 + end + assert_raise RangeError do + m.optional_int32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum + end + assert_raise RangeError do + m.optional_int32 = 1e12 + end + assert_raise RangeError do + m.optional_int32 = 1.5 + end + + m.optional_uint32 = 0 + m.optional_uint32 = +0xffff_ffff + m.optional_uint32 = 1.0 + m.optional_uint32 = 4e9 + assert_raise RangeError do + m.optional_uint32 = -1 + end + assert_raise RangeError do + m.optional_uint32 = -1.5 + end + assert_raise RangeError do + m.optional_uint32 = -1.5e12 + end + assert_raise RangeError do + m.optional_uint32 = -0x1000_0000_0000_0000 + end + assert_raise RangeError do + m.optional_uint32 = +0x1_0000_0000 + end + assert_raise RangeError do + m.optional_uint32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum + end + assert_raise RangeError do + m.optional_uint32 = 1e12 + end + assert_raise RangeError do + m.optional_uint32 = 1.5 + end + + m.optional_int64 = 0 + m.optional_int64 = -0x8000_0000_0000_0000 + m.optional_int64 = +0x7fff_ffff_ffff_ffff + m.optional_int64 = 1.0 + m.optional_int64 = -1.0 + m.optional_int64 = 8e18 + m.optional_int64 = -8e18 + assert_raise RangeError do + m.optional_int64 = -0x8000_0000_0000_0001 + end + assert_raise RangeError do + m.optional_int64 = +0x8000_0000_0000_0000 + end + assert_raise RangeError do + m.optional_int64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum + end + assert_raise RangeError do + m.optional_int64 = 1e50 + end + assert_raise RangeError do + m.optional_int64 = 1.5 + end + + m.optional_uint64 = 0 + m.optional_uint64 = +0xffff_ffff_ffff_ffff + m.optional_uint64 = 1.0 + m.optional_uint64 = 16e18 + assert_raise RangeError do + m.optional_uint64 = -1 + end + assert_raise RangeError do + m.optional_uint64 = -1.5 + end + assert_raise RangeError do + m.optional_uint64 = -1.5e12 + end + assert_raise RangeError do + m.optional_uint64 = -0x1_0000_0000_0000_0000 + end + assert_raise RangeError do + m.optional_uint64 = +0x1_0000_0000_0000_0000 + end + assert_raise RangeError do + m.optional_uint64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum + end + assert_raise RangeError do + m.optional_uint64 = 1e50 + end + assert_raise RangeError do + m.optional_uint64 = 1.5 + end + end + + def test_stress_test + m = proto_module::TestMessage.new + m.optional_int32 = 42 + m.optional_int64 = 0x100000000 + m.optional_string = "hello world" + 10.times do m.repeated_msg.push proto_module::TestMessage2.new(:foo => 42) end + 10.times do m.repeated_string.push "hello world" end + + data = proto_module::TestMessage.encode(m) + + 10_000.times do + m = proto_module::TestMessage.decode(data) + data_new = proto_module::TestMessage.encode(m) + assert data_new == data + data = data_new + end + end + + def test_reflection + m = proto_module::TestMessage.new(:optional_int32 => 1234) + msgdef = m.class.descriptor + assert msgdef.class == Google::Protobuf::Descriptor + assert msgdef.any? {|field| field.name == "optional_int32"} + optional_int32 = msgdef.lookup "optional_int32" + assert optional_int32.class == Google::Protobuf::FieldDescriptor + assert optional_int32 != nil + assert optional_int32.name == "optional_int32" + assert optional_int32.type == :int32 + optional_int32.set(m, 5678) + assert m.optional_int32 == 5678 + m.optional_int32 = 1000 + assert optional_int32.get(m) == 1000 + + optional_msg = msgdef.lookup "optional_msg" + assert optional_msg.subtype == proto_module::TestMessage2.descriptor + + optional_msg.set(m, optional_msg.subtype.msgclass.new) + + assert msgdef.msgclass == proto_module::TestMessage + + optional_enum = msgdef.lookup "optional_enum" + assert optional_enum.subtype == proto_module::TestEnum.descriptor + assert optional_enum.subtype.class == Google::Protobuf::EnumDescriptor + optional_enum.subtype.each do |k, v| + # set with integer, check resolution to symbolic name + optional_enum.set(m, v) + assert optional_enum.get(m) == k + end + end + + def test_json + # TODO: Fix JSON in JRuby version. + return if RUBY_PLATFORM == "java" + m = proto_module::TestMessage.new(:optional_int32 => 1234, + :optional_int64 => -0x1_0000_0000, + :optional_uint32 => 0x8000_0000, + :optional_uint64 => 0xffff_ffff_ffff_ffff, + :optional_bool => true, + :optional_float => 1.0, + :optional_double => -1e100, + :optional_string => "Test string", + :optional_bytes => ["FFFFFFFF"].pack('H*'), + :optional_msg => proto_module::TestMessage2.new(:foo => 42), + :repeated_int32 => [1, 2, 3, 4], + :repeated_string => ["a", "b", "c"], + :repeated_bool => [true, false, true, false], + :repeated_msg => [proto_module::TestMessage2.new(:foo => 1), + proto_module::TestMessage2.new(:foo => 2)]) + + json_text = proto_module::TestMessage.encode_json(m) + m2 = proto_module::TestMessage.decode_json(json_text) + assert_equal m, m2 + + # Crash case from GitHub issue 283. + bar = proto_module::Bar.new(msg: "bar") + baz1 = proto_module::Baz.new(msg: "baz") + baz2 = proto_module::Baz.new(msg: "quux") + proto_module::Foo.encode_json(proto_module::Foo.new) + proto_module::Foo.encode_json(proto_module::Foo.new(bar: bar)) + proto_module::Foo.encode_json(proto_module::Foo.new(bar: bar, baz: [baz1, baz2])) + end + + def test_json_empty + assert proto_module::TestMessage.encode_json(proto_module::TestMessage.new) == '{}' + end + + def test_json_emit_defaults + # TODO: Fix JSON in JRuby version. + return if RUBY_PLATFORM == "java" + m = proto_module::TestMessage.new + + expected = { + repeatedInt32: [], + repeatedInt64: [], + repeatedUint32: [], + repeatedUint64: [], + repeatedBool: [], + repeatedFloat: [], + repeatedDouble: [], + repeatedString: [], + repeatedBytes: [], + repeatedMsg: [], + repeatedEnum: [] + } + + actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true) + + assert_equal expected, JSON.parse(actual, :symbolize_names => true) + end + + def test_json_emit_defaults_submsg + # TODO: Fix JSON in JRuby version. + return if RUBY_PLATFORM == "java" + m = proto_module::TestMessage.new(optional_msg: proto_module::TestMessage2.new) + + expected = { + optionalMsg: {}, + repeatedInt32: [], + repeatedInt64: [], + repeatedUint32: [], + repeatedUint64: [], + repeatedBool: [], + repeatedFloat: [], + repeatedDouble: [], + repeatedString: [], + repeatedBytes: [], + repeatedMsg: [], + repeatedEnum: [] + } + + actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true) + + assert_equal expected, JSON.parse(actual, :symbolize_names => true) + end + + def test_json_emit_defaults_repeated_submsg + # TODO: Fix JSON in JRuby version. + return if RUBY_PLATFORM == "java" + m = proto_module::TestMessage.new(repeated_msg: [proto_module::TestMessage2.new]) + + expected = { + repeatedInt32: [], + repeatedInt64: [], + repeatedUint32: [], + repeatedUint64: [], + repeatedBool: [], + repeatedFloat: [], + repeatedDouble: [], + repeatedString: [], + repeatedBytes: [], + repeatedMsg: [{}], + repeatedEnum: [] + } + + actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true) + + assert_equal expected, JSON.parse(actual, :symbolize_names => true) + end + + def value_from_ruby(value) + ret = Google::Protobuf::Value.new + case value + when String + ret.string_value = value + when Google::Protobuf::Struct + ret.struct_value = value + when Hash + ret.struct_value = struct_from_ruby(value) + when Google::Protobuf::ListValue + ret.list_value = value + when Array + ret.list_value = list_from_ruby(value) + else + @log.error "Unknown type: #{value.class}" + raise Google::Protobuf::Error, "Unknown type: #{value.class}" + end + ret + end + + def list_from_ruby(arr) + ret = Google::Protobuf::ListValue.new + arr.each do |v| + ret.values << value_from_ruby(v) + end + ret + end + + def struct_from_ruby(hash) + ret = Google::Protobuf::Struct.new + hash.each do |k, v| + ret.fields[k] ||= value_from_ruby(v) + end + ret + end + + def test_deep_json + # will not overflow + json = '{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":'\ + '{"a":{"a":{"a":{"a":{}}}}}}}}}}}}}}}}' + + struct = struct_from_ruby(JSON.parse(json)) + assert_equal json, struct.to_json + + encoded = proto_module::MyRepeatedStruct.encode( + proto_module::MyRepeatedStruct.new(structs: [proto_module::MyStruct.new(struct: struct)])) + assert_equal json, proto_module::MyRepeatedStruct.decode(encoded).structs[0].struct.to_json + + # will overflow + json = '{"a":{"a":{"a":[{"a":{"a":[{"a":[{"a":{"a":[{"a":[{"a":'\ + '{"a":[{"a":[{"a":{"a":{"a":[{"a":"a"}]}}}]}]}}]}]}}]}]}}]}}}' + + struct = struct_from_ruby(JSON.parse(json)) + assert_equal json, struct.to_json + + assert_raise(RuntimeError, "Maximum recursion depth exceeded during encoding") do + struct = Google::Protobuf::Struct.new + struct.fields["foobar"] = Google::Protobuf::Value.new(struct_value: struct) + Google::Protobuf::Struct.encode(struct) + end + end + + def test_comparison_with_arbitrary_object + assert proto_module::TestMessage.new != nil + end + + def test_wrappers_set_to_default + run_asserts = ->(m) { + assert_equal 0.0, m.double.value + assert_equal 0.0, m.float.value + assert_equal 0, m.int32.value + assert_equal 0, m.int64.value + assert_equal 0, m.uint32.value + assert_equal 0, m.uint64.value + assert_equal false, m.bool.value + assert_equal '', m.string.value + assert_equal '', m.bytes.value + } + + m = proto_module::Wrapper.new( + double: Google::Protobuf::DoubleValue.new(value: 0.0), + float: Google::Protobuf::FloatValue.new(value: 0.0), + int32: Google::Protobuf::Int32Value.new(value: 0), + int64: Google::Protobuf::Int64Value.new(value: 0), + uint32: Google::Protobuf::UInt32Value.new(value: 0), + uint64: Google::Protobuf::UInt64Value.new(value: 0), + bool: Google::Protobuf::BoolValue.new(value: false), + string: Google::Protobuf::StringValue.new(value: ""), + bytes: Google::Protobuf::BytesValue.new(value: ''), + ) + + run_asserts.call(m) + m2 = proto_module::Wrapper.decode(m.to_proto) + run_asserts.call(m2) + m3 = proto_module::Wrapper.decode_json(m.to_json) + end + + def test_wrapper_getters + run_asserts = ->(m) { + assert_equal 2.0, m.double_as_value + assert_equal 2.0, m.double.value + assert_equal 2.0, m.double_as_value + + assert_equal 4.0, m.float_as_value + assert_equal 4.0, m.float.value + assert_equal 4.0, m.float_as_value + + assert_equal 3, m.int32_as_value + assert_equal 3, m.int32.value + assert_equal 3, m.int32_as_value + + assert_equal 4, m.int64_as_value + assert_equal 4, m.int64.value + assert_equal 4, m.int64_as_value + + assert_equal 5, m.uint32_as_value + assert_equal 5, m.uint32.value + assert_equal 5, m.uint32_as_value + + assert_equal 6, m.uint64_as_value + assert_equal 6, m.uint64.value + assert_equal 6, m.uint64_as_value + + assert_equal true, m.bool_as_value + assert_equal true, m.bool.value + assert_equal true, m.bool_as_value + + assert_equal "st\nr", m.string_as_value + assert_equal "st\nr", m.string.value + assert_equal "st\nr", m.string_as_value + + assert_equal 'fun', m.bytes_as_value + assert_equal 'fun', m.bytes.value + assert_equal 'fun', m.bytes_as_value + } + + m = proto_module::Wrapper.new( + double: Google::Protobuf::DoubleValue.new(value: 2.0), + float: Google::Protobuf::FloatValue.new(value: 4.0), + int32: Google::Protobuf::Int32Value.new(value: 3), + int64: Google::Protobuf::Int64Value.new(value: 4), + uint32: Google::Protobuf::UInt32Value.new(value: 5), + uint64: Google::Protobuf::UInt64Value.new(value: 6), + bool: Google::Protobuf::BoolValue.new(value: true), + string: Google::Protobuf::StringValue.new(value: "st\nr"), + bytes: Google::Protobuf::BytesValue.new(value: 'fun'), + real_string: '100' + ) + + run_asserts.call(m) + serialized = proto_module::Wrapper::encode(m) + m2 = proto_module::Wrapper::decode(serialized) + run_asserts.call(m2) + + # Test the case where we are serializing directly from the parsed form + # (before anything lazy is materialized). + m3 = proto_module::Wrapper::decode(serialized) + serialized2 = proto_module::Wrapper::encode(m3) + m4 = proto_module::Wrapper::decode(serialized2) + run_asserts.call(m4) + + # Test that the lazy form compares equal to the expanded form. + m5 = proto_module::Wrapper::decode(serialized2) + assert_equal m5, m + + serialized_json = proto_module::Wrapper::encode_json(m) + m6 = proto_module::Wrapper::decode_json(serialized_json) + assert_equal m6, m + end + + def test_repeated_wrappers + run_asserts = ->(m) { + assert_equal 2.0, m.repeated_double[0].value + assert_equal 4.0, m.repeated_float[0].value + assert_equal 3, m.repeated_int32[0].value + assert_equal 4, m.repeated_int64[0].value + assert_equal 5, m.repeated_uint32[0].value + assert_equal 6, m.repeated_uint64[0].value + assert_equal true, m.repeated_bool[0].value + assert_equal 'str', m.repeated_string[0].value + assert_equal 'fun', m.repeated_bytes[0].value + } + + m = proto_module::Wrapper.new( + repeated_double: [Google::Protobuf::DoubleValue.new(value: 2.0)], + repeated_float: [Google::Protobuf::FloatValue.new(value: 4.0)], + repeated_int32: [Google::Protobuf::Int32Value.new(value: 3)], + repeated_int64: [Google::Protobuf::Int64Value.new(value: 4)], + repeated_uint32: [Google::Protobuf::UInt32Value.new(value: 5)], + repeated_uint64: [Google::Protobuf::UInt64Value.new(value: 6)], + repeated_bool: [Google::Protobuf::BoolValue.new(value: true)], + repeated_string: [Google::Protobuf::StringValue.new(value: 'str')], + repeated_bytes: [Google::Protobuf::BytesValue.new(value: 'fun')], + ) + + run_asserts.call(m) + serialized = proto_module::Wrapper::encode(m) + m2 = proto_module::Wrapper::decode(serialized) + run_asserts.call(m2) + + # Test the case where we are serializing directly from the parsed form + # (before anything lazy is materialized). + m3 = proto_module::Wrapper::decode(serialized) + serialized2 = proto_module::Wrapper::encode(m3) + m4 = proto_module::Wrapper::decode(serialized2) + run_asserts.call(m4) + + # Test that the lazy form compares equal to the expanded form. + m5 = proto_module::Wrapper::decode(serialized2) + assert_equal m5, m + + # Test JSON. + serialized_json = proto_module::Wrapper::encode_json(m5) + m6 = proto_module::Wrapper::decode_json(serialized_json) + run_asserts.call(m6) + assert_equal m6, m + end + + def test_oneof_wrappers + run_test = ->(m) { + serialized = proto_module::Wrapper::encode(m) + m2 = proto_module::Wrapper::decode(serialized) + + # Encode directly from lazy form. + serialized2 = proto_module::Wrapper::encode(m2) + + assert_equal m, m2 + assert_equal serialized, serialized2 + + serialized_json = proto_module::Wrapper::encode_json(m) + m3 = proto_module::Wrapper::decode_json(serialized_json) + assert_equal m, m3 + } + + m = proto_module::Wrapper.new() + + run_test.call(m) + m.oneof_double_as_value = 2.0 + run_test.call(m) + m.oneof_float_as_value = 4.0 + run_test.call(m) + m.oneof_int32_as_value = 3 + run_test.call(m) + m.oneof_int64_as_value = 5 + run_test.call(m) + m.oneof_uint32_as_value = 6 + run_test.call(m) + m.oneof_uint64_as_value = 7 + run_test.call(m) + m.oneof_string_as_value = 'str' + run_test.call(m) + m.oneof_bytes_as_value = 'fun' + run_test.call(m) + end + + def test_top_level_wrappers + # We don't expect anyone to do this, but we should also make sure it does + # the right thing. + run_test = ->(klass, val) { + m = klass.new(value: val) + serialized = klass::encode(m) + m2 = klass::decode(serialized) + + # Encode directly from lazy form. + serialized2 = klass::encode(m2) + + assert_equal m, m2 + assert_equal serialized, serialized2 + + serialized_json = klass::encode_json(m) + + # This is nonsensical to do and does not work. There is no good reason + # to parse a wrapper type directly. + assert_raise(RuntimeError) { klass::decode_json(serialized_json) } + } + + run_test.call(Google::Protobuf::DoubleValue, 2.0) + run_test.call(Google::Protobuf::FloatValue, 4.0) + run_test.call(Google::Protobuf::Int32Value, 3) + run_test.call(Google::Protobuf::Int64Value, 4) + run_test.call(Google::Protobuf::UInt32Value, 5) + run_test.call(Google::Protobuf::UInt64Value, 6) + run_test.call(Google::Protobuf::BoolValue, true) + run_test.call(Google::Protobuf::StringValue, 'str') + run_test.call(Google::Protobuf::BytesValue, 'fun') + end + + def test_wrapper_setters_as_value + run_asserts = ->(m) { + m.double_as_value = 4.8 + assert_equal 4.8, m.double_as_value + assert_equal Google::Protobuf::DoubleValue.new(value: 4.8), m.double + m.float_as_value = 2.4 + assert_in_delta 2.4, m.float_as_value + assert_in_delta Google::Protobuf::FloatValue.new(value: 2.4).value, m.float.value + m.int32_as_value = 5 + assert_equal 5, m.int32_as_value + assert_equal Google::Protobuf::Int32Value.new(value: 5), m.int32 + m.int64_as_value = 15 + assert_equal 15, m.int64_as_value + assert_equal Google::Protobuf::Int64Value.new(value: 15), m.int64 + m.uint32_as_value = 50 + assert_equal 50, m.uint32_as_value + assert_equal Google::Protobuf::UInt32Value.new(value: 50), m.uint32 + m.uint64_as_value = 500 + assert_equal 500, m.uint64_as_value + assert_equal Google::Protobuf::UInt64Value.new(value: 500), m.uint64 + m.bool_as_value = false + assert_equal false, m.bool_as_value + assert_equal Google::Protobuf::BoolValue.new(value: false), m.bool + m.string_as_value = 'xy' + assert_equal 'xy', m.string_as_value + assert_equal Google::Protobuf::StringValue.new(value: 'xy'), m.string + m.bytes_as_value = '123' + assert_equal '123', m.bytes_as_value + assert_equal Google::Protobuf::BytesValue.new(value: '123'), m.bytes + + m.double_as_value = nil + assert_nil m.double + assert_nil m.double_as_value + m.float_as_value = nil + assert_nil m.float + assert_nil m.float_as_value + m.int32_as_value = nil + assert_nil m.int32 + assert_nil m.int32_as_value + m.int64_as_value = nil + assert_nil m.int64 + assert_nil m.int64_as_value + m.uint32_as_value = nil + assert_nil m.uint32 + assert_nil m.uint32_as_value + m.uint64_as_value = nil + assert_nil m.uint64 + assert_nil m.uint64_as_value + m.bool_as_value = nil + assert_nil m.bool + assert_nil m.bool_as_value + m.string_as_value = nil + assert_nil m.string + assert_nil m.string_as_value + m.bytes_as_value = nil + assert_nil m.bytes + assert_nil m.bytes_as_value + } + + m = proto_module::Wrapper.new + + m2 = proto_module::Wrapper.new( + double: Google::Protobuf::DoubleValue.new(value: 2.0), + float: Google::Protobuf::FloatValue.new(value: 4.0), + int32: Google::Protobuf::Int32Value.new(value: 3), + int64: Google::Protobuf::Int64Value.new(value: 4), + uint32: Google::Protobuf::UInt32Value.new(value: 5), + uint64: Google::Protobuf::UInt64Value.new(value: 6), + bool: Google::Protobuf::BoolValue.new(value: true), + string: Google::Protobuf::StringValue.new(value: 'str'), + bytes: Google::Protobuf::BytesValue.new(value: 'fun'), + real_string: '100' + ) + + run_asserts.call(m2) + + serialized = proto_module::Wrapper::encode(m2) + m3 = proto_module::Wrapper::decode(serialized) + run_asserts.call(m3) + end + + def test_wrapper_setters + run_asserts = ->(m) { + m.double = Google::Protobuf::DoubleValue.new(value: 4.8) + assert_equal 4.8, m.double_as_value + assert_equal Google::Protobuf::DoubleValue.new(value: 4.8), m.double + m.float = Google::Protobuf::FloatValue.new(value: 2.4) + assert_in_delta 2.4, m.float_as_value + assert_in_delta Google::Protobuf::FloatValue.new(value: 2.4).value, m.float.value + m.int32 = Google::Protobuf::Int32Value.new(value: 5) + assert_equal 5, m.int32_as_value + assert_equal Google::Protobuf::Int32Value.new(value: 5), m.int32 + m.int64 = Google::Protobuf::Int64Value.new(value: 15) + assert_equal 15, m.int64_as_value + assert_equal Google::Protobuf::Int64Value.new(value: 15), m.int64 + m.uint32 = Google::Protobuf::UInt32Value.new(value: 50) + assert_equal 50, m.uint32_as_value + assert_equal Google::Protobuf::UInt32Value.new(value: 50), m.uint32 + m.uint64 = Google::Protobuf::UInt64Value.new(value: 500) + assert_equal 500, m.uint64_as_value + assert_equal Google::Protobuf::UInt64Value.new(value: 500), m.uint64 + m.bool = Google::Protobuf::BoolValue.new(value: false) + assert_equal false, m.bool_as_value + assert_equal Google::Protobuf::BoolValue.new(value: false), m.bool + m.string = Google::Protobuf::StringValue.new(value: 'xy') + assert_equal 'xy', m.string_as_value + assert_equal Google::Protobuf::StringValue.new(value: 'xy'), m.string + m.bytes = Google::Protobuf::BytesValue.new(value: '123') + assert_equal '123', m.bytes_as_value + assert_equal Google::Protobuf::BytesValue.new(value: '123'), m.bytes + + m.double = nil + assert_nil m.double + assert_nil m.double_as_value + m.float = nil + assert_nil m.float + assert_nil m.float_as_value + m.int32 = nil + assert_nil m.int32 + assert_nil m.int32_as_value + m.int64 = nil + assert_nil m.int64 + assert_nil m.int64_as_value + m.uint32 = nil + assert_nil m.uint32 + assert_nil m.uint32_as_value + m.uint64 = nil + assert_nil m.uint64 + assert_nil m.uint64_as_value + m.bool = nil + assert_nil m.bool + assert_nil m.bool_as_value + m.string = nil + assert_nil m.string + assert_nil m.string_as_value + m.bytes = nil + assert_nil m.bytes + assert_nil m.bytes_as_value + } + + m = proto_module::Wrapper.new + run_asserts.call(m) + + m2 = proto_module::Wrapper.new( + double: Google::Protobuf::DoubleValue.new(value: 2.0), + float: Google::Protobuf::FloatValue.new(value: 4.0), + int32: Google::Protobuf::Int32Value.new(value: 3), + int64: Google::Protobuf::Int64Value.new(value: 4), + uint32: Google::Protobuf::UInt32Value.new(value: 5), + uint64: Google::Protobuf::UInt64Value.new(value: 6), + bool: Google::Protobuf::BoolValue.new(value: true), + string: Google::Protobuf::StringValue.new(value: 'str'), + bytes: Google::Protobuf::BytesValue.new(value: 'fun'), + real_string: '100' + ) + + run_asserts.call(m2) + + serialized = proto_module::Wrapper::encode(m2) + m3 = proto_module::Wrapper::decode(serialized) + run_asserts.call(m3) + end + + def test_wrappers_only + m = proto_module::Wrapper.new(real_string: 'hi', string_in_oneof: 'there') + + assert_raise(NoMethodError) { m.real_string_as_value } + assert_raise(NoMethodError) { m.as_value } + assert_raise(NoMethodError) { m._as_value } + assert_raise(NoMethodError) { m.string_in_oneof_as_value } + + m = proto_module::Wrapper.new + m.string_as_value = 'you' + assert_equal 'you', m.string.value + assert_equal 'you', m.string_as_value + assert_raise(NoMethodError) { m.string_ } + assert_raise(NoMethodError) { m.string_X } + assert_raise(NoMethodError) { m.string_XX } + assert_raise(NoMethodError) { m.string_XXX } + assert_raise(NoMethodError) { m.string_XXXX } + assert_raise(NoMethodError) { m.string_XXXXX } + assert_raise(NoMethodError) { m.string_XXXXXX } + assert_raise(NoMethodError) { m.string_XXXXXXX } + assert_raise(NoMethodError) { m.string_XXXXXXXX } + assert_raise(NoMethodError) { m.string_XXXXXXXXX } + assert_raise(NoMethodError) { m.string_XXXXXXXXXX } + end + + def test_converts_time + m = proto_module::TimeMessage.new + + m.timestamp = Google::Protobuf::Timestamp.new(seconds: 5, nanos: 6) + assert_kind_of Google::Protobuf::Timestamp, m.timestamp + assert_equal 5, m.timestamp.seconds + assert_equal 6, m.timestamp.nanos + + m.timestamp = Time.at(9466, 123456.789) + assert_equal Google::Protobuf::Timestamp.new(seconds: 9466, nanos: 123456789), m.timestamp + + m = proto_module::TimeMessage.new(timestamp: Time.at(1)) + assert_equal Google::Protobuf::Timestamp.new(seconds: 1, nanos: 0), m.timestamp + + assert_raise(Google::Protobuf::TypeError) { m.timestamp = 2 } + assert_raise(Google::Protobuf::TypeError) { m.timestamp = 2.4 } + assert_raise(Google::Protobuf::TypeError) { m.timestamp = '4' } + assert_raise(Google::Protobuf::TypeError) { m.timestamp = proto_module::TimeMessage.new } + + def test_time(year, month, day) + str = ("\"%04d-%02d-%02dT00:00:00.000+00:00\"" % [year, month, day]) + t = Google::Protobuf::Timestamp.decode_json(str) + time = Time.new(year, month, day, 0, 0, 0, "+00:00") + assert_equal t.seconds, time.to_i + end + + (1970..2010).each do |year| + test_time(year, 2, 28) + test_time(year, 3, 01) + end + end + + def test_converts_duration + m = proto_module::TimeMessage.new + + m.duration = Google::Protobuf::Duration.new(seconds: 2, nanos: 22) + assert_kind_of Google::Protobuf::Duration, m.duration + assert_equal 2, m.duration.seconds + assert_equal 22, m.duration.nanos + + m.duration = 10.5 + assert_equal Google::Protobuf::Duration.new(seconds: 10, nanos: 500_000_000), m.duration + + m.duration = 200 + assert_equal Google::Protobuf::Duration.new(seconds: 200, nanos: 0), m.duration + + m.duration = Rational(3, 2) + assert_equal Google::Protobuf::Duration.new(seconds: 1, nanos: 500_000_000), m.duration + + m.duration = BigDecimal("5") + assert_equal Google::Protobuf::Duration.new(seconds: 5, nanos: 0), m.duration + + m = proto_module::TimeMessage.new(duration: 1.1) + assert_equal Google::Protobuf::Duration.new(seconds: 1, nanos: 100_000_000), m.duration + + assert_raise(Google::Protobuf::TypeError) { m.duration = '2' } + assert_raise(Google::Protobuf::TypeError) { m.duration = proto_module::TimeMessage.new } + end + + def test_freeze + m = proto_module::TestMessage.new + m.optional_int32 = 10 + m.freeze + + frozen_error = assert_raise(FrozenErrorType) { m.optional_int32 = 20 } + assert_match "can't modify frozen #{proto_module}::TestMessage", frozen_error.message + assert_equal 10, m.optional_int32 + assert_equal true, m.frozen? + + assert_raise(FrozenErrorType) { m.optional_int64 = 2 } + assert_raise(FrozenErrorType) { m.optional_uint32 = 3 } + assert_raise(FrozenErrorType) { m.optional_uint64 = 4 } + assert_raise(FrozenErrorType) { m.optional_bool = true } + assert_raise(FrozenErrorType) { m.optional_float = 6.0 } + assert_raise(FrozenErrorType) { m.optional_double = 7.0 } + assert_raise(FrozenErrorType) { m.optional_string = '8' } + assert_raise(FrozenErrorType) { m.optional_bytes = nil } + assert_raise(FrozenErrorType) { m.optional_msg = proto_module::TestMessage2.new } + assert_raise(FrozenErrorType) { m.optional_enum = :A } + assert_raise(FrozenErrorType) { m.repeated_int32 = 1 } + assert_raise(FrozenErrorType) { m.repeated_int64 = 2 } + assert_raise(FrozenErrorType) { m.repeated_uint32 = 3 } + assert_raise(FrozenErrorType) { m.repeated_uint64 = 4 } + assert_raise(FrozenErrorType) { m.repeated_bool = true } + assert_raise(FrozenErrorType) { m.repeated_float = 6.0 } + assert_raise(FrozenErrorType) { m.repeated_double = 7.0 } + assert_raise(FrozenErrorType) { m.repeated_string = '8' } + assert_raise(FrozenErrorType) { m.repeated_bytes = nil } + assert_raise(FrozenErrorType) { m.repeated_msg = proto_module::TestMessage2.new } + assert_raise(FrozenErrorType) { m.repeated_enum = :A } + end + + def test_eq + m1 = proto_module::TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2']) + m2 = proto_module::TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2']) + + h = {} + h[m1] = :yes + + assert m1 == m2 + assert m1.eql?(m2) + assert m1.hash == m2.hash + assert h[m1] == :yes + assert h[m2] == :yes + + m1.optional_int32 = 2 + + assert m1 != m2 + assert !m1.eql?(m2) + assert m1.hash != m2.hash + assert_nil h[m2] + end + + def test_object_gc + m = proto_module::TestMessage.new(optional_msg: proto_module::TestMessage2.new) + m.optional_msg + GC.start(full_mark: true, immediate_sweep: true) + m.optional_msg.inspect + end + + def test_object_gc_freeze + m = proto_module::TestMessage.new + m.repeated_float.freeze + GC.start(full_mark: true) + + # Make sure we remember that the object is frozen. + # The wrapper object contains this information, so we need to ensure that + # the previous GC did not collect it. + assert m.repeated_float.frozen? + + GC.start(full_mark: true, immediate_sweep: true) + assert m.repeated_float.frozen? + end +end diff --git a/ruby/tests/encode_decode_test.rb b/ruby/tests/encode_decode_test.rb new file mode 100755 index 0000000000000..cce364d0d8161 --- /dev/null +++ b/ruby/tests/encode_decode_test.rb @@ -0,0 +1,98 @@ +#!/usr/bin/ruby + +# generated_code.rb is in the same directory as this test. +$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) + +require 'generated_code_pb' +require 'google/protobuf/well_known_types' +require 'test/unit' + +def hex2bin(s) + s.scan(/../).map { |x| x.hex.chr }.join +end + +class EncodeDecodeTest < Test::Unit::TestCase + def test_discard_unknown + # Test discard unknown in message. + unknown_msg = A::B::C::TestUnknown.new(:unknown_field => 1) + from = A::B::C::TestUnknown.encode(unknown_msg) + m = A::B::C::TestMessage.decode(from) + Google::Protobuf.discard_unknown(m) + to = A::B::C::TestMessage.encode(m) + assert_equal '', to + + # Test discard unknown for singular message field. + unknown_msg = A::B::C::TestUnknown.new( + :optional_unknown => + A::B::C::TestUnknown.new(:unknown_field => 1)) + from = A::B::C::TestUnknown.encode(unknown_msg) + m = A::B::C::TestMessage.decode(from) + Google::Protobuf.discard_unknown(m) + to = A::B::C::TestMessage.encode(m.optional_msg) + assert_equal '', to + + # Test discard unknown for repeated message field. + unknown_msg = A::B::C::TestUnknown.new( + :repeated_unknown => + [A::B::C::TestUnknown.new(:unknown_field => 1)]) + from = A::B::C::TestUnknown.encode(unknown_msg) + m = A::B::C::TestMessage.decode(from) + Google::Protobuf.discard_unknown(m) + to = A::B::C::TestMessage.encode(m.repeated_msg[0]) + assert_equal '', to + + # Test discard unknown for map value message field. + unknown_msg = A::B::C::TestUnknown.new( + :map_unknown => + {"" => A::B::C::TestUnknown.new(:unknown_field => 1)}) + from = A::B::C::TestUnknown.encode(unknown_msg) + m = A::B::C::TestMessage.decode(from) + Google::Protobuf.discard_unknown(m) + to = A::B::C::TestMessage.encode(m.map_string_msg['']) + assert_equal '', to + + # Test discard unknown for oneof message field. + unknown_msg = A::B::C::TestUnknown.new( + :oneof_unknown => + A::B::C::TestUnknown.new(:unknown_field => 1)) + from = A::B::C::TestUnknown.encode(unknown_msg) + m = A::B::C::TestMessage.decode(from) + Google::Protobuf.discard_unknown(m) + to = A::B::C::TestMessage.encode(m.oneof_msg) + assert_equal '', to + end + + def test_encode_json + msg = A::B::C::TestMessage.new({ optional_int32: 22 }) + json = msg.to_json + + to = A::B::C::TestMessage.decode_json(json) + assert_equal to.optional_int32, 22 + + msg = A::B::C::TestMessage.new({ optional_int32: 22 }) + json = msg.to_json({ preserve_proto_fieldnames: true }) + + assert_match 'optional_int32', json + + to = A::B::C::TestMessage.decode_json(json) + assert_equal 22, to.optional_int32 + + msg = A::B::C::TestMessage.new({ optional_int32: 22 }) + json = A::B::C::TestMessage.encode_json( + msg, + { preserve_proto_fieldnames: true, emit_defaults: true } + ) + + assert_match 'optional_int32', json + end + + def test_encode_wrong_msg + assert_raise ::ArgumentError do + m = A::B::C::TestMessage.new( + :optional_int32 => 1, + ) + Google::Protobuf::Any.encode(m) + end + end + +end diff --git a/ruby/tests/gc_test.rb b/ruby/tests/gc_test.rb new file mode 100755 index 0000000000000..d7fecaeea1083 --- /dev/null +++ b/ruby/tests/gc_test.rb @@ -0,0 +1,110 @@ +#!/usr/bin/ruby +# +# generated_code.rb is in the same directory as this test. +$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) + +old_gc = GC.stress +# Ruby 2.7.0 - 2.7.1 has a GC bug in its parser, so turn off stress for now +# See https://bugs.ruby-lang.org/issues/16807 +GC.stress = 0x01 | 0x04 unless RUBY_VERSION.match?(/^2\.7\./) +require 'generated_code_pb' +require 'generated_code_proto2_pb' +GC.stress = old_gc + +require 'test/unit' + +class GCTest < Test::Unit::TestCase + def get_msg_proto3 + A::B::C::TestMessage.new( + :optional_int32 => 1, + :optional_int64 => 1, + :optional_uint32 => 1, + :optional_uint64 => 1, + :optional_bool => true, + :optional_double => 1.0, + :optional_float => 1.0, + :optional_string => "a", + :optional_bytes => "b", + :optional_enum => A::B::C::TestEnum::A, + :optional_msg => A::B::C::TestMessage.new(), + :repeated_int32 => [1], + :repeated_int64 => [1], + :repeated_uint32 => [1], + :repeated_uint64 => [1], + :repeated_bool => [true], + :repeated_double => [1.0], + :repeated_float => [1.0], + :repeated_string => ["a"], + :repeated_bytes => ["b"], + :repeated_enum => [A::B::C::TestEnum::A], + :repeated_msg => [A::B::C::TestMessage.new()], + :map_int32_string => {1 => "a"}, + :map_int64_string => {1 => "a"}, + :map_uint32_string => {1 => "a"}, + :map_uint64_string => {1 => "a"}, + :map_bool_string => {true => "a"}, + :map_string_string => {"a" => "a"}, + :map_string_msg => {"a" => A::B::C::TestMessage.new()}, + :map_string_int32 => {"a" => 1}, + :map_string_bool => {"a" => true}, + ) + end + + def get_msg_proto2 + A::B::Proto2::TestMessage.new( + :optional_int32 => 1, + :optional_int64 => 1, + :optional_uint32 => 1, + :optional_uint64 => 1, + :optional_bool => true, + :optional_double => 1.0, + :optional_float => 1.0, + :optional_string => "a", + :optional_bytes => "b", + :optional_enum => A::B::Proto2::TestEnum::A, + :optional_msg => A::B::Proto2::TestMessage.new(), + :repeated_int32 => [1], + :repeated_int64 => [1], + :repeated_uint32 => [1], + :repeated_uint64 => [1], + :repeated_bool => [true], + :repeated_double => [1.0], + :repeated_float => [1.0], + :repeated_string => ["a"], + :repeated_bytes => ["b"], + :repeated_enum => [A::B::Proto2::TestEnum::A], + :repeated_msg => [A::B::Proto2::TestMessage.new()], + :required_int32 => 1, + :required_int64 => 1, + :required_uint32 => 1, + :required_uint64 => 1, + :required_bool => true, + :required_double => 1.0, + :required_float => 1.0, + :required_string => "a", + :required_bytes => "b", + :required_enum => A::B::Proto2::TestEnum::A, + :required_msg => A::B::Proto2::TestMessage.new(), + ) + end + + def test_generated_msg + old_gc = GC.stress + GC.stress = 0x01 | 0x04 + from = get_msg_proto3 + data = A::B::C::TestMessage.encode(from) + to = A::B::C::TestMessage.decode(data) + + # This doesn't work for proto2 on JRuby because there is a nested required message. + # A::B::Proto2::TestMessage has :required_msg which is of type: + # A::B::Proto2::TestMessage so there is no way to generate a valid + # message that doesn't exceed the depth limit + if !defined? JRUBY_VERSION + from = get_msg_proto2 + data = A::B::Proto2::TestMessage.encode(from) + to = A::B::Proto2::TestMessage.decode(data) + end + GC.stress = old_gc + puts "passed" + end +end diff --git a/ruby/tests/generated_code.proto b/ruby/tests/generated_code.proto index 62fd83ed896be..e8116697d7a3d 100644 --- a/ruby/tests/generated_code.proto +++ b/ruby/tests/generated_code.proto @@ -57,6 +57,9 @@ message TestMessage { } NestedMessage nested_message = 80; + + // Reserved for non-existing field test. + // int32 non_exist = 89; } enum TestEnum { @@ -65,3 +68,18 @@ enum TestEnum { B = 2; C = 3; } + +message testLowercaseNested { + message lowercase{} +} + + +message TestUnknown { + TestUnknown optional_unknown = 11; + repeated TestUnknown repeated_unknown = 31; + oneof my_oneof { + TestUnknown oneof_unknown = 51; + } + map map_unknown = 67; + int32 unknown_field = 89; +} diff --git a/ruby/tests/generated_code_proto2.proto b/ruby/tests/generated_code_proto2.proto new file mode 100644 index 0000000000000..1e957219fac68 --- /dev/null +++ b/ruby/tests/generated_code_proto2.proto @@ -0,0 +1,80 @@ +syntax = "proto2"; + +package a.b.proto2; + +message TestMessage { + optional int32 optional_int32 = 1; + optional int64 optional_int64 = 2; + optional uint32 optional_uint32 = 3; + optional uint64 optional_uint64 = 4; + optional bool optional_bool = 5; + optional double optional_double = 6; + optional float optional_float = 7; + optional string optional_string = 8; + optional bytes optional_bytes = 9; + optional TestEnum optional_enum = 10; + optional 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; + + required int32 required_int32 = 41; + required int64 required_int64 = 42; + required uint32 required_uint32 = 43; + required uint64 required_uint64 = 44; + required bool required_bool = 45; + required double required_double = 46; + required float required_float = 47; + required string required_string = 48; + required bytes required_bytes = 49; + required TestEnum required_enum = 50; + required TestMessage required_msg = 51; + + 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 { + optional int32 foo = 1; + } + + optional NestedMessage nested_message = 80; + + // Reserved for non-existing field test. + // int32 non_exist = 89; +} + +enum TestEnum { + Default = 0; + A = 1; + B = 2; + C = 3; +} + +message TestUnknown { + optional TestUnknown optional_unknown = 11; + repeated TestUnknown repeated_unknown = 31; + oneof my_oneof { + TestUnknown oneof_unknown = 51; + } + optional int32 unknown_field = 89; +} diff --git a/ruby/tests/generated_code_proto2_test.rb b/ruby/tests/generated_code_proto2_test.rb new file mode 100755 index 0000000000000..302f9451555a1 --- /dev/null +++ b/ruby/tests/generated_code_proto2_test.rb @@ -0,0 +1,21 @@ +#!/usr/bin/ruby + +# generated_code.rb is in the same directory as this test. +$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) + +require 'generated_code_proto2_pb' +require 'test_import_proto2_pb' +require 'test_ruby_package_proto2_pb' +require 'test/unit' + +class GeneratedCodeProto2Test < Test::Unit::TestCase + def test_generated_msg + # just test that we can instantiate the message. The purpose of this test + # is to ensure that the output of the code generator is valid Ruby and + # successfully creates message definitions and classes, not to test every + # aspect of the extension (basic.rb is for that). + A::B::Proto2::TestMessage.new + FooBar::Proto2::TestImportedMessage.new + A::B::Proto2::TestRubyPackageMessage.new + end +end diff --git a/ruby/tests/generated_code_test.rb b/ruby/tests/generated_code_test.rb old mode 100644 new mode 100755 index b92b0462d1556..aed1cf8ebc379 --- a/ruby/tests/generated_code_test.rb +++ b/ruby/tests/generated_code_test.rb @@ -5,6 +5,7 @@ require 'generated_code_pb' require 'test_import_pb' +require 'test_ruby_package_pb' require 'test/unit' class GeneratedCodeTest < Test::Unit::TestCase @@ -13,7 +14,10 @@ def test_generated_msg # is to ensure that the output of the code generator is valid Ruby and # successfully creates message definitions and classes, not to test every # aspect of the extension (basic.rb is for that). - m = A::B::C::TestMessage.new() - m2 = FooBar::TestImportedMessage.new() + A::B::C::TestMessage.new + A::B::C::TestMessage::NestedMessage.new + A::B::C::TestLowercaseNested::Lowercase.new + FooBar::TestImportedMessage.new + A::B::TestRubyPackageMessage.new end end diff --git a/ruby/tests/multi_level_nesting_test.proto b/ruby/tests/multi_level_nesting_test.proto new file mode 100644 index 0000000000000..84c3fa4c07f88 --- /dev/null +++ b/ruby/tests/multi_level_nesting_test.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +message Function { + string name = 1; + repeated Function.Parameter parameters = 2; + string return_type = 3; + + message Parameter { + string name = 1; + Function.Parameter.Value value = 2; + + message Value { + oneof type { + string string = 1; + int64 integer = 2; + } + } + } +} diff --git a/ruby/tests/multi_level_nesting_test.rb b/ruby/tests/multi_level_nesting_test.rb new file mode 100644 index 0000000000000..7e5d0ec6b727d --- /dev/null +++ b/ruby/tests/multi_level_nesting_test.rb @@ -0,0 +1,20 @@ +#!/usr/bin/ruby + +# multi_level_nesting_test_pb.rb is in the same directory as this test. +$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) + +require 'test/unit' +require 'multi_level_nesting_test_pb' + +# +# Provide tests for having messages nested 3 levels deep +# +class MultiLevelNestingTest < Test::Unit::TestCase + + def test_levels_exist + assert ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Function").msgclass + assert ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Function.Parameter").msgclass + assert ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Function.Parameter.Value").msgclass + end + +end diff --git a/ruby/tests/repeated_field_test.rb b/ruby/tests/repeated_field_test.rb old mode 100644 new mode 100755 index 25727b7b282c9..6307447bc3f3a --- a/ruby/tests/repeated_field_test.rb +++ b/ruby/tests/repeated_field_test.rb @@ -18,7 +18,9 @@ def test_acts_like_an_array # jRuby additions to the Array class that we can ignore arr_methods -= [ :indices, :iter_for_each, :iter_for_each_index, :iter_for_each_with_index, :dimensions, :copy_data, :copy_data_simple, - :nitems, :iter_for_reverse_each, :indexes] + :nitems, :iter_for_reverse_each, :indexes, :append, :prepend] + arr_methods -= [:union, :difference, :filter!] + arr_methods -= [:intersection, :deconstruct] # ruby 2.7 methods we can ignore arr_methods.each do |method_name| assert m.repeated_string.respond_to?(method_name) == true, "does not respond to #{method_name}" end @@ -28,7 +30,10 @@ def test_first m = TestMessage.new repeated_field_names(TestMessage).each do |field_name| assert_nil m.send(field_name).first + assert_equal [], m.send(field_name).first(0) + assert_equal [], m.send(field_name).first(1) end + fill_test_msg(m) assert_equal -10, m.repeated_int32.first assert_equal -1_000_000, m.repeated_int64.first @@ -41,6 +46,11 @@ def test_first assert_equal "bar".encode!('ASCII-8BIT'), m.repeated_bytes.first assert_equal TestMessage2.new(:foo => 1), m.repeated_msg.first assert_equal :A, m.repeated_enum.first + + assert_equal [], m.repeated_int32.first(0) + assert_equal [-10], m.repeated_int32.first(1) + assert_equal [-10, -11], m.repeated_int32.first(2) + assert_equal [-10, -11], m.repeated_int32.first(3) end @@ -126,6 +136,12 @@ def test_empty? assert_equal false, m.repeated_string.empty? end + def test_reassign + m = TestMessage.new + m.repeated_msg = Google::Protobuf::RepeatedField.new(:message, TestMessage2, [TestMessage2.new(:foo => 1)]) + assert_equal m.repeated_msg.first, TestMessage2.new(:foo => 1) + end + def test_array_accessor m = TestMessage.new reference_arr = %w(foo bar baz) @@ -206,7 +222,7 @@ def test_array_settor def test_push m = TestMessage.new - reference_arr = %w(foo bar baz) + reference_arr = %w[foo bar baz] m.repeated_string += reference_arr.clone check_self_modifying_method(m.repeated_string, reference_arr) do |arr| @@ -215,10 +231,9 @@ def test_push check_self_modifying_method(m.repeated_string, reference_arr) do |arr| arr << 'fizz' end - #TODO: push should support multiple - # check_self_modifying_method(m.repeated_string, reference_arr) do |arr| - # arr.push('fizz', 'buzz') - # end + check_self_modifying_method(m.repeated_string, reference_arr) do |arr| + arr.push('fizz', 'buzz') + end end def test_clear @@ -363,6 +378,15 @@ def test_delete_at end end + def test_delete_if + m = TestMessage.new + reference_arr = %w(foo bar baz) + m.repeated_string += reference_arr.clone + check_self_modifying_method(m.repeated_string, reference_arr) do |arr| + arr.delete_if { |v| v == "bar" } + end + end + def test_fill m = TestMessage.new reference_arr = %w(foo bar baz) diff --git a/ruby/tests/stress.rb b/ruby/tests/stress.rb old mode 100644 new mode 100755 diff --git a/ruby/tests/test_import_proto2.proto b/ruby/tests/test_import_proto2.proto new file mode 100644 index 0000000000000..8d2ef375ef156 --- /dev/null +++ b/ruby/tests/test_import_proto2.proto @@ -0,0 +1,5 @@ +syntax = "proto2"; + +package foo_bar.proto2; + +message TestImportedMessage {} diff --git a/ruby/tests/test_ruby_package.proto b/ruby/tests/test_ruby_package.proto new file mode 100644 index 0000000000000..54b7aca50a38d --- /dev/null +++ b/ruby/tests/test_ruby_package.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +package foo_bar; + +option ruby_package = "A::B"; + +message TestRubyPackageMessage {} diff --git a/ruby/tests/test_ruby_package_proto2.proto b/ruby/tests/test_ruby_package_proto2.proto new file mode 100644 index 0000000000000..c55bde435b7e4 --- /dev/null +++ b/ruby/tests/test_ruby_package_proto2.proto @@ -0,0 +1,7 @@ +syntax = "proto2"; + +package foo_bar_proto2; + +option ruby_package = "A::B::Proto2"; + +message TestRubyPackageMessage {} diff --git a/ruby/tests/type_errors.rb b/ruby/tests/type_errors.rb new file mode 100755 index 0000000000000..6f6eb06178bb8 --- /dev/null +++ b/ruby/tests/type_errors.rb @@ -0,0 +1,176 @@ +#!/usr/bin/ruby + +# generated_code.rb is in the same directory as this test. +$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) + +require 'test/unit' +require 'google/protobuf/well_known_types' +require 'generated_code_pb' + +class TestTypeErrors < Test::Unit::TestCase + # Ruby 2.4 unified Fixnum with Integer + IntegerType = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.4') ? Fixnum : Integer + + def test_bad_string + check_error Google::Protobuf::TypeError, + "Invalid argument for string field 'optional_string' (given #{IntegerType.name})." do + A::B::C::TestMessage.new(optional_string: 4) + end + check_error Google::Protobuf::TypeError, + "Invalid argument for string field 'oneof_string' (given #{IntegerType.name})." do + A::B::C::TestMessage.new(oneof_string: 4) + end + check_error ArgumentError, + "Expected array as initializer value for repeated field 'repeated_string' (given String)." do + A::B::C::TestMessage.new(repeated_string: '4') + end + end + + def test_bad_float + check_error Google::Protobuf::TypeError, + "Expected number type for float field 'optional_float' (given TrueClass)." do + A::B::C::TestMessage.new(optional_float: true) + end + check_error Google::Protobuf::TypeError, + "Expected number type for float field 'oneof_float' (given TrueClass)." do + A::B::C::TestMessage.new(oneof_float: true) + end + check_error ArgumentError, + "Expected array as initializer value for repeated field 'repeated_float' (given String)." do + A::B::C::TestMessage.new(repeated_float: 'true') + end + end + + def test_bad_double + check_error Google::Protobuf::TypeError, + "Expected number type for double field 'optional_double' (given Symbol)." do + A::B::C::TestMessage.new(optional_double: :double) + end + check_error Google::Protobuf::TypeError, + "Expected number type for double field 'oneof_double' (given Symbol)." do + A::B::C::TestMessage.new(oneof_double: :double) + end + check_error ArgumentError, + "Expected array as initializer value for repeated field 'repeated_double' (given FalseClass)." do + A::B::C::TestMessage.new(repeated_double: false) + end + end + + def test_bad_bool + check_error Google::Protobuf::TypeError, + "Invalid argument for boolean field 'optional_bool' (given Float)." do + A::B::C::TestMessage.new(optional_bool: 4.4) + end + check_error Google::Protobuf::TypeError, + "Invalid argument for boolean field 'oneof_bool' (given Float)." do + A::B::C::TestMessage.new(oneof_bool: 4.4) + end + check_error ArgumentError, + "Expected array as initializer value for repeated field 'repeated_bool' (given String)." do + A::B::C::TestMessage.new(repeated_bool: 'hi') + end + end + + def test_bad_int + check_error Google::Protobuf::TypeError, + "Expected number type for integral field 'optional_int32' (given String)." do + A::B::C::TestMessage.new(optional_int32: 'hi') + end + check_error RangeError, + "Non-integral floating point value assigned to integer field 'optional_int64' (given Float)." do + A::B::C::TestMessage.new(optional_int64: 2.4) + end + check_error Google::Protobuf::TypeError, + "Expected number type for integral field 'optional_uint32' (given Symbol)." do + A::B::C::TestMessage.new(optional_uint32: :thing) + end + check_error Google::Protobuf::TypeError, + "Expected number type for integral field 'optional_uint64' (given FalseClass)." do + A::B::C::TestMessage.new(optional_uint64: false) + end + check_error Google::Protobuf::TypeError, + "Expected number type for integral field 'oneof_int32' (given Symbol)." do + A::B::C::TestMessage.new(oneof_int32: :hi) + end + check_error RangeError, + "Non-integral floating point value assigned to integer field 'oneof_int64' (given Float)." do + A::B::C::TestMessage.new(oneof_int64: 2.4) + end + check_error Google::Protobuf::TypeError, + "Expected number type for integral field 'oneof_uint32' (given String)." do + A::B::C::TestMessage.new(oneof_uint32: 'x') + end + check_error RangeError, + "Non-integral floating point value assigned to integer field 'oneof_uint64' (given Float)." do + A::B::C::TestMessage.new(oneof_uint64: 1.1) + end + check_error ArgumentError, + "Expected array as initializer value for repeated field 'repeated_int32' (given Symbol)." do + A::B::C::TestMessage.new(repeated_int32: :hi) + end + check_error ArgumentError, + "Expected array as initializer value for repeated field 'repeated_int64' (given Float)." do + A::B::C::TestMessage.new(repeated_int64: 2.4) + end + check_error ArgumentError, + "Expected array as initializer value for repeated field 'repeated_uint32' (given String)." do + A::B::C::TestMessage.new(repeated_uint32: 'x') + end + check_error ArgumentError, + "Expected array as initializer value for repeated field 'repeated_uint64' (given Float)." do + A::B::C::TestMessage.new(repeated_uint64: 1.1) + end + end + + def test_bad_enum + check_error RangeError, + "Unknown symbol value for enum field 'optional_enum'." do + A::B::C::TestMessage.new(optional_enum: 'enum') + end + check_error RangeError, + "Unknown symbol value for enum field 'oneof_enum'." do + A::B::C::TestMessage.new(oneof_enum: '') + end + check_error ArgumentError, + "Expected array as initializer value for repeated field 'repeated_enum' (given String)." do + A::B::C::TestMessage.new(repeated_enum: '') + end + end + + def test_bad_bytes + check_error Google::Protobuf::TypeError, + "Invalid argument for bytes field 'optional_bytes' (given Float)." do + A::B::C::TestMessage.new(optional_bytes: 22.22) + end + check_error Google::Protobuf::TypeError, + "Invalid argument for bytes field 'oneof_bytes' (given Symbol)." do + A::B::C::TestMessage.new(oneof_bytes: :T22) + end + check_error ArgumentError, + "Expected array as initializer value for repeated field 'repeated_bytes' (given Symbol)." do + A::B::C::TestMessage.new(repeated_bytes: :T22) + end + end + + def test_bad_msg + check_error Google::Protobuf::TypeError, + "Invalid type #{IntegerType.name} to assign to submessage field 'optional_msg'." do + A::B::C::TestMessage.new(optional_msg: 2) + end + check_error Google::Protobuf::TypeError, + "Invalid type String to assign to submessage field 'oneof_msg'." do + A::B::C::TestMessage.new(oneof_msg: '2') + end + check_error ArgumentError, + "Expected array as initializer value for repeated field 'repeated_msg' (given String)." do + A::B::C::TestMessage.new(repeated_msg: '2') + end + end + + def check_error(type, message) + err = assert_raises type do + yield + end + assert_equal message, err.message + end +end diff --git a/ruby/tests/well_known_types_test.rb b/ruby/tests/well_known_types_test.rb old mode 100644 new mode 100755 index bd24c32884ae3..3eafe095ad0f5 --- a/ruby/tests/well_known_types_test.rb +++ b/ruby/tests/well_known_types_test.rb @@ -60,6 +60,9 @@ def test_struct assert_equal(Google::Protobuf::ListValue.from_a(sublist), struct["sublist"]) + assert_equal true, struct.has_key?("null") + assert_equal false, struct.has_key?("missing_key") + should_equal = { "number" => 12345, "boolean-true" => true, @@ -82,6 +85,9 @@ def test_struct # to_h returns a fully-flattened Ruby structure (Hash and Array). assert_equal(should_equal, struct.to_h) + # Test that we can safely access a missing key + assert_equal(nil, struct["missing_key"]) + # Test that we can assign Struct and ListValue directly. struct["substruct"] = Google::Protobuf::Struct.from_hash(substruct) struct["sublist"] = Google::Protobuf::ListValue.from_a(sublist) @@ -120,11 +126,71 @@ def test_struct end def test_any - any = Google::Protobuf::Any.new ts = Google::Protobuf::Timestamp.new(seconds: 12345, nanos: 6789) + + any = Google::Protobuf::Any.new any.pack(ts) assert any.is(Google::Protobuf::Timestamp) assert_equal ts, any.unpack(Google::Protobuf::Timestamp) + + any = Google::Protobuf::Any.pack(ts) + + assert any.is(Google::Protobuf::Timestamp) + assert_equal ts, any.unpack(Google::Protobuf::Timestamp) + end + + def test_struct_init + s = Google::Protobuf::Struct.new(fields: {'a' => Google::Protobuf::Value.new({number_value: 4.4})}) + assert_equal 4.4, s['a'] + + s = Google::Protobuf::Struct.new(fields: {'a' => {number_value: 2.2}}) + assert_equal 2.2, s['a'] + + s = Google::Protobuf::Struct.new(fields: {a: {number_value: 1.1}}) + assert_equal 1.1, s[:a] + end + + def test_struct_nested_init + s = Google::Protobuf::Struct.new( + fields: { + 'a' => {string_value: 'A'}, + 'b' => {struct_value: { + fields: { + 'x' => {list_value: {values: [{number_value: 1.0}, {string_value: "ok"}]}}, + 'y' => {bool_value: true}}} + }, + 'c' => {struct_value: {}} + } + ) + assert_equal 'A', s['a'] + assert_equal 'A', s[:a] + expected_b_x = [Google::Protobuf::Value.new(number_value: 1.0), Google::Protobuf::Value.new(string_value: "ok")] + assert_equal expected_b_x, s['b']['x'].values + assert_equal expected_b_x, s[:b][:x].values + assert_equal expected_b_x, s['b'][:x].values + assert_equal expected_b_x, s[:b]['x'].values + assert_equal true, s['b']['y'] + assert_equal true, s[:b][:y] + assert_equal true, s[:b]['y'] + assert_equal true, s['b'][:y] + assert_equal Google::Protobuf::Struct.new, s['c'] + assert_equal Google::Protobuf::Struct.new, s[:c] + + s = Google::Protobuf::Struct.new( + fields: { + a: {string_value: 'Eh'}, + b: {struct_value: { + fields: { + y: {bool_value: false}}} + } + } + ) + assert_equal 'Eh', s['a'] + assert_equal 'Eh', s[:a] + assert_equal false, s['b']['y'] + assert_equal false, s[:b][:y] + assert_equal false, s['b'][:y] + assert_equal false, s[:b]['y'] end end diff --git a/ruby/travis-test.sh b/ruby/travis-test.sh index 52ea81b6160c9..faf0f9d0c7331 100755 --- a/ruby/travis-test.sh +++ b/ruby/travis-test.sh @@ -5,22 +5,42 @@ set -e test_version() { version=$1 - if [ "$version" == "jruby-1.7" ] ; then - # No conformance tests yet -- JRuby is too broken to run them. + + RUBY_CONFORMANCE=test_ruby + + if [ "$version" == "jruby-9.2.11.1" ] ; then bash --login -c \ "rvm install $version && rvm use $version && rvm get head && \ which ruby && \ git clean -f && \ gem install bundler && bundle && \ - rake test" - else + rake test && + rake gc_test && + cd ../conformance && make test_jruby && + cd ../ruby/compatibility_tests/v3.0.0 && ./test.sh" + elif [ "$version" == "ruby-2.6.0" -o "$version" == "ruby-2.7.0" -o "$version" == "ruby-3.0.0" ] ; then bash --login -c \ "rvm install $version && rvm use $version && \ which ruby && \ git clean -f && \ - gem install bundler && bundle && \ + gem install bundler -v 1.17.3 && bundle && \ + rake test && + rake gc_test && + cd ../conformance && make ${RUBY_CONFORMANCE} && + cd ../ruby/compatibility_tests/v3.0.0 && + cp -R ../../lib lib && ./test.sh" + else + # Recent versions of OSX have deprecated OpenSSL, so we have to explicitly + # provide a path to the OpenSSL directory installed via Homebrew. + bash --login -c \ + "rvm install $version --with-openssl-dir=`brew --prefix openssl` && \ + rvm use $version && \ + which ruby && \ + git clean -f && \ + gem install bundler -v 1.17.3 && bundle && \ rake test && - cd ../conformance && make test_ruby && + rake gc_test && + cd ../conformance && make ${RUBY_CONFORMANCE} && cd ../ruby/compatibility_tests/v3.0.0 && ./test.sh" fi } diff --git a/six.BUILD b/six.BUILD deleted file mode 100644 index fb0b3604cdf44..0000000000000 --- a/six.BUILD +++ /dev/null @@ -1,13 +0,0 @@ -genrule( - name = "copy_six", - srcs = ["six-1.10.0/six.py"], - outs = ["six.py"], - cmd = "cp $< $(@)", -) - -py_library( - name = "six", - srcs = ["six.py"], - srcs_version = "PY2AND3", - visibility = ["//visibility:public"], -) diff --git a/src/Makefile.am b/src/Makefile.am index 1999213c78095..2f0f92ab98a9c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,6 +18,8 @@ else PTHREAD_DEF = endif +PROTOBUF_VERSION = 26:0:0 + if GCC # Turn on all warnings except for sign comparison (we ignore sign comparison # in Google so our code base have tons of such warnings). @@ -56,49 +58,29 @@ clean-local: CLEANFILES = $(protoc_outputs) unittest_proto_middleman \ testzip.jar testzip.list testzip.proto testzip.zip \ - no_warning_test.cc \ - google/protobuf/compiler/js/well_known_types_embed.cc \ - js_embed$(EXEEXT) + no_warning_test.cc MAINTAINERCLEANFILES = \ Makefile.in nobase_include_HEADERS = \ - google/protobuf/stubs/atomic_sequence_num.h \ - google/protobuf/stubs/atomicops.h \ - google/protobuf/stubs/atomicops_internals_power.h \ - google/protobuf/stubs/atomicops_internals_ppc_gcc.h \ - google/protobuf/stubs/atomicops_internals_arm64_gcc.h \ - google/protobuf/stubs/atomicops_internals_arm_gcc.h \ - google/protobuf/stubs/atomicops_internals_arm_qnx.h \ - google/protobuf/stubs/atomicops_internals_atomicword_compat.h \ - google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h \ - google/protobuf/stubs/atomicops_internals_generic_gcc.h \ - google/protobuf/stubs/atomicops_internals_mips_gcc.h \ - google/protobuf/stubs/atomicops_internals_solaris.h \ - google/protobuf/stubs/atomicops_internals_tsan.h \ - google/protobuf/stubs/atomicops_internals_x86_gcc.h \ - google/protobuf/stubs/atomicops_internals_x86_msvc.h \ google/protobuf/stubs/callback.h \ google/protobuf/stubs/bytestream.h \ google/protobuf/stubs/casts.h \ google/protobuf/stubs/common.h \ - google/protobuf/stubs/fastmem.h \ google/protobuf/stubs/hash.h \ google/protobuf/stubs/logging.h \ google/protobuf/stubs/macros.h \ + google/protobuf/stubs/map_util.h \ google/protobuf/stubs/mutex.h \ google/protobuf/stubs/once.h \ google/protobuf/stubs/platform_macros.h \ google/protobuf/stubs/port.h \ - google/protobuf/stubs/scoped_ptr.h \ - google/protobuf/stubs/shared_ptr.h \ - google/protobuf/stubs/singleton.h \ google/protobuf/stubs/status.h \ google/protobuf/stubs/stl_util.h \ google/protobuf/stubs/stringpiece.h \ + google/protobuf/stubs/strutil.h \ google/protobuf/stubs/template_util.h \ - google/protobuf/stubs/type_traits.h \ google/protobuf/any.pb.h \ google/protobuf/api.pb.h \ google/protobuf/any.h \ @@ -112,6 +94,7 @@ nobase_include_HEADERS = \ google/protobuf/dynamic_message.h \ google/protobuf/empty.pb.h \ google/protobuf/extension_set.h \ + google/protobuf/extension_set_inl.h \ google/protobuf/field_mask.pb.h \ google/protobuf/generated_enum_reflection.h \ google/protobuf/generated_enum_util.h \ @@ -119,6 +102,8 @@ nobase_include_HEADERS = \ google/protobuf/generated_message_table_driven.h \ google/protobuf/generated_message_util.h \ google/protobuf/has_bits.h \ + google/protobuf/implicit_weak_message.h \ + google/protobuf/io/io_win32.h \ google/protobuf/map_entry.h \ google/protobuf/map_entry_lite.h \ google/protobuf/map_field.h \ @@ -130,6 +115,10 @@ nobase_include_HEADERS = \ google/protobuf/message_lite.h \ google/protobuf/metadata.h \ google/protobuf/metadata_lite.h \ + google/protobuf/parse_context.h \ + google/protobuf/port.h \ + google/protobuf/port_def.inc \ + google/protobuf/port_undef.inc \ google/protobuf/reflection.h \ google/protobuf/reflection_ops.h \ google/protobuf/repeated_field.h \ @@ -142,7 +131,6 @@ nobase_include_HEADERS = \ google/protobuf/unknown_field_set.h \ google/protobuf/wire_format.h \ google/protobuf/wire_format_lite.h \ - google/protobuf/wire_format_lite_inl.h \ google/protobuf/wrappers.pb.h \ google/protobuf/io/coded_stream.h \ $(GZHEADERS) \ @@ -163,7 +151,6 @@ nobase_include_HEADERS = \ google/protobuf/compiler/csharp/csharp_names.h \ google/protobuf/compiler/java/java_generator.h \ google/protobuf/compiler/java/java_names.h \ - google/protobuf/compiler/javanano/javanano_generator.h \ google/protobuf/compiler/js/js_generator.h \ google/protobuf/compiler/js/well_known_types_embed.h \ google/protobuf/compiler/objectivec/objectivec_generator.h \ @@ -182,27 +169,22 @@ nobase_include_HEADERS = \ lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la -libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS) -libprotobuf_lite_la_LDFLAGS = -version-info 14:0:0 -export-dynamic -no-undefined +libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS) $(LIBATOMIC_LIBS) +libprotobuf_lite_la_LDFLAGS = -version-info $(PROTOBUF_VERSION) -export-dynamic -no-undefined if HAVE_LD_VERSION_SCRIPT libprotobuf_lite_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libprotobuf-lite.map EXTRA_libprotobuf_lite_la_DEPENDENCIES = libprotobuf-lite.map endif libprotobuf_lite_la_SOURCES = \ - google/protobuf/stubs/atomicops_internals_x86_gcc.cc \ - google/protobuf/stubs/atomicops_internals_x86_msvc.cc \ google/protobuf/stubs/bytestream.cc \ google/protobuf/stubs/bytestream.h \ google/protobuf/stubs/common.cc \ google/protobuf/stubs/hash.h \ google/protobuf/stubs/int128.cc \ google/protobuf/stubs/int128.h \ - google/protobuf/stubs/io_win32.cc \ - google/protobuf/stubs/io_win32.h \ + google/protobuf/io/io_win32.cc \ google/protobuf/stubs/map_util.h \ google/protobuf/stubs/mathutil.h \ - google/protobuf/stubs/once.cc \ - google/protobuf/stubs/shared_ptr.h \ google/protobuf/stubs/status.cc \ google/protobuf/stubs/status.h \ google/protobuf/stubs/status_macros.h \ @@ -214,25 +196,30 @@ libprotobuf_lite_la_SOURCES = \ google/protobuf/stubs/stringprintf.h \ google/protobuf/stubs/structurally_valid.cc \ google/protobuf/stubs/strutil.cc \ - google/protobuf/stubs/strutil.h \ google/protobuf/stubs/time.cc \ google/protobuf/stubs/time.h \ + google/protobuf/any_lite.cc \ google/protobuf/arena.cc \ google/protobuf/arenastring.cc \ google/protobuf/extension_set.cc \ + google/protobuf/generated_enum_util.cc \ google/protobuf/generated_message_util.cc \ google/protobuf/generated_message_table_driven_lite.h \ google/protobuf/generated_message_table_driven_lite.cc \ + google/protobuf/implicit_weak_message.cc \ + google/protobuf/map.cc \ google/protobuf/message_lite.cc \ + google/protobuf/parse_context.cc \ google/protobuf/repeated_field.cc \ google/protobuf/wire_format_lite.cc \ google/protobuf/io/coded_stream.cc \ - google/protobuf/io/coded_stream_inl.h \ + google/protobuf/io/strtod.cc \ google/protobuf/io/zero_copy_stream.cc \ + google/protobuf/io/zero_copy_stream_impl.cc \ google/protobuf/io/zero_copy_stream_impl_lite.cc -libprotobuf_la_LIBADD = $(PTHREAD_LIBS) -libprotobuf_la_LDFLAGS = -version-info 14:0:0 -export-dynamic -no-undefined +libprotobuf_la_LIBADD = $(PTHREAD_LIBS) $(LIBATOMIC_LIBS) +libprotobuf_la_LDFLAGS = -version-info $(PROTOBUF_VERSION) -export-dynamic -no-undefined if HAVE_LD_VERSION_SCRIPT libprotobuf_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libprotobuf.map EXTRA_libprotobuf_la_DEPENDENCIES = libprotobuf.map @@ -241,8 +228,6 @@ libprotobuf_la_SOURCES = \ $(libprotobuf_lite_la_SOURCES) \ google/protobuf/any.pb.cc \ google/protobuf/api.pb.cc \ - google/protobuf/stubs/mathlimits.cc \ - google/protobuf/stubs/mathlimits.h \ google/protobuf/any.cc \ google/protobuf/descriptor.cc \ google/protobuf/descriptor_database.cc \ @@ -272,9 +257,7 @@ libprotobuf_la_SOURCES = \ google/protobuf/wrappers.pb.cc \ google/protobuf/io/gzip_stream.cc \ google/protobuf/io/printer.cc \ - google/protobuf/io/strtod.cc \ google/protobuf/io/tokenizer.cc \ - google/protobuf/io/zero_copy_stream_impl.cc \ google/protobuf/compiler/importer.cc \ google/protobuf/compiler/parser.cc \ google/protobuf/util/delimited_message_util.cc \ @@ -323,7 +306,7 @@ libprotobuf_la_SOURCES = \ nodist_libprotobuf_la_SOURCES = $(nodist_libprotobuf_lite_la_SOURCES) libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la -libprotoc_la_LDFLAGS = -version-info 14:0:0 -export-dynamic -no-undefined +libprotoc_la_LDFLAGS = -version-info $(PROTOBUF_VERSION) -export-dynamic -no-undefined if HAVE_LD_VERSION_SCRIPT libprotoc_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libprotoc.map EXTRA_libprotoc_la_DEPENDENCIES = libprotoc.map @@ -333,6 +316,7 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/command_line_interface.cc \ google/protobuf/compiler/plugin.cc \ google/protobuf/compiler/plugin.pb.cc \ + google/protobuf/compiler/scc.h \ google/protobuf/compiler/subprocess.cc \ google/protobuf/compiler/subprocess.h \ google/protobuf/compiler/zip_writer.cc \ @@ -356,7 +340,11 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/cpp/cpp_message.h \ google/protobuf/compiler/cpp/cpp_message_field.cc \ google/protobuf/compiler/cpp/cpp_message_field.h \ + google/protobuf/compiler/cpp/cpp_message_layout_helper.h \ + google/protobuf/compiler/cpp/cpp_names.h \ google/protobuf/compiler/cpp/cpp_options.h \ + google/protobuf/compiler/cpp/cpp_padding_optimizer.cc \ + google/protobuf/compiler/cpp/cpp_padding_optimizer.h \ google/protobuf/compiler/cpp/cpp_primitive_field.cc \ google/protobuf/compiler/cpp/cpp_primitive_field.h \ google/protobuf/compiler/cpp/cpp_service.cc \ @@ -386,10 +374,6 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/java/java_generator_factory.h \ google/protobuf/compiler/java/java_helpers.cc \ google/protobuf/compiler/java/java_helpers.h \ - google/protobuf/compiler/java/java_lazy_message_field.cc \ - google/protobuf/compiler/java/java_lazy_message_field.h \ - google/protobuf/compiler/java/java_lazy_message_field_lite.cc\ - google/protobuf/compiler/java/java_lazy_message_field_lite.h \ google/protobuf/compiler/java/java_map_field.cc \ google/protobuf/compiler/java/java_map_field.h \ google/protobuf/compiler/java/java_map_field_lite.cc \ @@ -425,29 +409,6 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/java/java_doc_comment.h \ google/protobuf/compiler/js/js_generator.cc \ google/protobuf/compiler/js/well_known_types_embed.cc \ - google/protobuf/compiler/javanano/javanano_enum.cc \ - google/protobuf/compiler/javanano/javanano_enum.h \ - google/protobuf/compiler/javanano/javanano_enum_field.cc \ - google/protobuf/compiler/javanano/javanano_enum_field.h \ - google/protobuf/compiler/javanano/javanano_extension.cc \ - google/protobuf/compiler/javanano/javanano_extension.h \ - google/protobuf/compiler/javanano/javanano_field.cc \ - google/protobuf/compiler/javanano/javanano_field.h \ - google/protobuf/compiler/javanano/javanano_file.cc \ - google/protobuf/compiler/javanano/javanano_file.h \ - google/protobuf/compiler/javanano/javanano_generator.cc \ - google/protobuf/compiler/javanano/javanano_generator.h \ - google/protobuf/compiler/javanano/javanano_helpers.cc \ - google/protobuf/compiler/javanano/javanano_helpers.h \ - google/protobuf/compiler/javanano/javanano_map_field.cc \ - google/protobuf/compiler/javanano/javanano_map_field.h \ - google/protobuf/compiler/javanano/javanano_message.cc \ - google/protobuf/compiler/javanano/javanano_message.h \ - google/protobuf/compiler/javanano/javanano_message_field.cc \ - google/protobuf/compiler/javanano/javanano_message_field.h \ - google/protobuf/compiler/javanano/javanano_params.h \ - google/protobuf/compiler/javanano/javanano_primitive_field.cc \ - google/protobuf/compiler/javanano/javanano_primitive_field.h \ google/protobuf/compiler/objectivec/objectivec_enum.cc \ google/protobuf/compiler/objectivec/objectivec_enum.h \ google/protobuf/compiler/objectivec/objectivec_enum_field.cc \ @@ -467,6 +428,7 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/objectivec/objectivec_message.h \ google/protobuf/compiler/objectivec/objectivec_message_field.cc \ google/protobuf/compiler/objectivec/objectivec_message_field.h \ + google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h \ google/protobuf/compiler/objectivec/objectivec_oneof.cc \ google/protobuf/compiler/objectivec/objectivec_oneof.h \ google/protobuf/compiler/objectivec/objectivec_primitive_field.cc \ @@ -511,21 +473,6 @@ bin_PROGRAMS = protoc protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la protoc_SOURCES = google/protobuf/compiler/main.cc -# The special JS code for the well-known types is linked into the compiler via -# well_known_types_embed.cc, which is generated from .js source files. We have -# to build the js_embed binary using $(CXX_FOR_BUILD) so that it is executable -# on the build machine in a cross-compilation setup. -js_embed$(EXEEXT): $(srcdir)/google/protobuf/compiler/js/embed.cc - $(CXX_FOR_BUILD) -o $@ $< -js_well_known_types_sources = \ - google/protobuf/compiler/js/well_known_types/any.js \ - google/protobuf/compiler/js/well_known_types/struct.js \ - google/protobuf/compiler/js/well_known_types/timestamp.js -# We have to cd to $(srcdir) so that out-of-tree builds work properly. -google/protobuf/compiler/js/well_known_types_embed.cc: js_embed$(EXEEXT) $(js_well_known_types_sources) - oldpwd=`pwd` && cd $(srcdir) && \ - $$oldpwd/js_embed$(EXEEXT) $(js_well_known_types_sources) > $$oldpwd/$@ - # Tests ============================================================== protoc_inputs = \ @@ -551,18 +498,17 @@ protoc_inputs = \ google/protobuf/unittest_lite.proto \ google/protobuf/unittest_mset.proto \ google/protobuf/unittest_mset_wire_format.proto \ - google/protobuf/unittest_no_arena_lite.proto \ - google/protobuf/unittest_no_arena_import.proto \ - google/protobuf/unittest_no_arena.proto \ google/protobuf/unittest_no_field_presence.proto \ google/protobuf/unittest_no_generic_services.proto \ google/protobuf/unittest_optimize_for.proto \ google/protobuf/unittest_preserve_unknown_enum2.proto \ google/protobuf/unittest_preserve_unknown_enum.proto \ google/protobuf/unittest.proto \ + google/protobuf/unittest_proto3.proto \ google/protobuf/unittest_proto3_arena.proto \ - google/protobuf/unittest_proto3_arena_lite.proto \ - google/protobuf/unittest_proto3_lite.proto \ + google/protobuf/unittest_proto3_arena_lite.proto \ + google/protobuf/unittest_proto3_lite.proto \ + google/protobuf/unittest_proto3_optional.proto \ google/protobuf/unittest_well_known_types.proto \ google/protobuf/util/internal/testdata/anys.proto \ google/protobuf/util/internal/testdata/books.proto \ @@ -575,14 +521,16 @@ protoc_inputs = \ google/protobuf/util/internal/testdata/struct.proto \ google/protobuf/util/internal/testdata/timestamp_duration.proto \ google/protobuf/util/internal/testdata/wrappers.proto \ + google/protobuf/util/json_format.proto \ google/protobuf/util/json_format_proto3.proto \ google/protobuf/util/message_differencer_unittest.proto \ google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto EXTRA_DIST = \ $(protoc_inputs) \ - $(js_well_known_types_sources) \ solaris/libstdc++.la \ + google/protobuf/test_messages_proto3.proto \ + google/protobuf/test_messages_proto2.proto \ google/protobuf/io/gzip_stream.h \ google/protobuf/io/gzip_stream_unittest.sh \ google/protobuf/testdata/golden_message \ @@ -601,9 +549,16 @@ EXTRA_DIST = \ google/protobuf/package_info.h \ google/protobuf/io/package_info.h \ google/protobuf/util/package_info.h \ - google/protobuf/compiler/js/embed.cc \ google/protobuf/compiler/ruby/ruby_generated_code.proto \ google/protobuf/compiler/ruby/ruby_generated_code_pb.rb \ + google/protobuf/compiler/ruby/ruby_generated_code_proto2.proto \ + google/protobuf/compiler/ruby/ruby_generated_code_proto2_pb.rb \ + google/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto \ + google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto \ + google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy_pb.rb \ + google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_pb.rb \ + google/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto \ + google/protobuf/compiler/ruby/ruby_generated_pkg_implicit_pb.rb \ google/protobuf/compiler/package_info.h \ google/protobuf/compiler/zip_output_unittest.sh \ libprotobuf-lite.map \ @@ -616,8 +571,6 @@ protoc_lite_outputs = \ google/protobuf/map_lite_unittest.pb.h \ google/protobuf/unittest_lite.pb.cc \ google/protobuf/unittest_lite.pb.h \ - google/protobuf/unittest_no_arena_lite.pb.cc \ - google/protobuf/unittest_no_arena_lite.pb.h \ google/protobuf/unittest_import_lite.pb.cc \ google/protobuf/unittest_import_lite.pb.h \ google/protobuf/unittest_import_public_lite.pb.cc \ @@ -663,10 +616,6 @@ protoc_outputs = \ google/protobuf/unittest_mset.pb.h \ google/protobuf/unittest_mset_wire_format.pb.cc \ google/protobuf/unittest_mset_wire_format.pb.h \ - google/protobuf/unittest_no_arena_import.pb.cc \ - google/protobuf/unittest_no_arena_import.pb.h \ - google/protobuf/unittest_no_arena.pb.cc \ - google/protobuf/unittest_no_arena.pb.h \ google/protobuf/unittest_no_field_presence.pb.cc \ google/protobuf/unittest_no_field_presence.pb.h \ google/protobuf/unittest_no_generic_services.pb.cc \ @@ -679,12 +628,16 @@ protoc_outputs = \ google/protobuf/unittest_preserve_unknown_enum2.pb.h \ google/protobuf/unittest_preserve_unknown_enum.pb.cc \ google/protobuf/unittest_preserve_unknown_enum.pb.h \ + google/protobuf/unittest_proto3.pb.cc \ + google/protobuf/unittest_proto3.pb.h \ google/protobuf/unittest_proto3_arena.pb.cc \ google/protobuf/unittest_proto3_arena.pb.h \ google/protobuf/unittest_proto3_arena_lite.pb.cc \ google/protobuf/unittest_proto3_arena_lite.pb.h \ google/protobuf/unittest_proto3_lite.pb.cc \ google/protobuf/unittest_proto3_lite.pb.h \ + google/protobuf/unittest_proto3_optional.pb.cc \ + google/protobuf/unittest_proto3_optional.pb.h \ google/protobuf/unittest_well_known_types.pb.cc \ google/protobuf/unittest_well_known_types.pb.h \ google/protobuf/util/internal/testdata/anys.pb.cc \ @@ -709,13 +662,13 @@ protoc_outputs = \ google/protobuf/util/internal/testdata/timestamp_duration.pb.h \ google/protobuf/util/internal/testdata/wrappers.pb.cc \ google/protobuf/util/internal/testdata/wrappers.pb.h \ + google/protobuf/util/json_format.pb.cc \ + google/protobuf/util/json_format.pb.h \ google/protobuf/util/json_format_proto3.pb.cc \ google/protobuf/util/json_format_proto3.pb.h \ google/protobuf/util/message_differencer_unittest.pb.cc \ google/protobuf/util/message_differencer_unittest.pb.h -BUILT_SOURCES = $(protoc_outputs) google/protobuf/compiler/js/well_known_types_embed.cc - if USE_EXTERNAL_PROTOC unittest_proto_middleman: $(protoc_inputs) @@ -728,7 +681,7 @@ else # relative to srcdir, which may not be the same as the current directory when # building out-of-tree. unittest_proto_middleman: protoc$(EXEEXT) $(protoc_inputs) - oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd $(protoc_inputs) ) + oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd $(protoc_inputs) --experimental_allow_proto3_optional ) touch unittest_proto_middleman endif @@ -738,35 +691,43 @@ $(protoc_outputs): unittest_proto_middleman COMMON_TEST_SOURCES = \ google/protobuf/arena_test_util.cc \ google/protobuf/arena_test_util.h \ - google/protobuf/map_test_util.cc \ + google/protobuf/map_test_util.inc \ google/protobuf/map_test_util.h \ google/protobuf/map_test_util_impl.h \ google/protobuf/test_util.cc \ google/protobuf/test_util.h \ + google/protobuf/test_util.inc \ + google/protobuf/test_util2.h \ google/protobuf/testing/googletest.cc \ google/protobuf/testing/googletest.h \ google/protobuf/testing/file.cc \ google/protobuf/testing/file.h +GOOGLETEST_BUILD_DIR=../third_party/googletest/googletest +GOOGLEMOCK_BUILD_DIR=../third_party/googletest/googlemock +GOOGLETEST_SRC_DIR=$(srcdir)/../third_party/googletest/googletest +GOOGLEMOCK_SRC_DIR=$(srcdir)/../third_party/googletest/googlemock check_PROGRAMS = protoc protobuf-test protobuf-lazy-descriptor-test \ protobuf-lite-test test_plugin protobuf-lite-arena-test \ no-warning-test $(GZCHECKPROGRAMS) protobuf_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \ - ../gmock/gtest/lib/libgtest.la \ - ../gmock/lib/libgmock.la \ - ../gmock/lib/libgmock_main.la -protobuf_test_CPPFLAGS = -I$(srcdir)/../gmock/gtest/include \ - -I$(srcdir)/../gmock/include + $(GOOGLETEST_BUILD_DIR)/lib/libgtest.la \ + $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock.la \ + $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock_main.la +protobuf_test_CPPFLAGS = -I$(GOOGLETEST_SRC_DIR)/include \ + -I$(GOOGLEMOCK_SRC_DIR)/include # Disable optimization for tests unless the user explicitly asked for it, # since test_util.cc takes forever to compile with optimization (with GCC). # See configure.ac for more info. protobuf_test_CXXFLAGS = $(NO_OPT_CXXFLAGS) +# Doesn't pass on Windows with MSVC +NON_MSVC_TEST_SOURCES = \ + google/protobuf/compiler/command_line_interface_unittest.cc protobuf_test_SOURCES = \ google/protobuf/stubs/bytestream_unittest.cc \ google/protobuf/stubs/common_unittest.cc \ google/protobuf/stubs/int128_unittest.cc \ - google/protobuf/stubs/io_win32_unittest.cc \ - google/protobuf/stubs/once_unittest.cc \ + google/protobuf/io/io_win32_unittest.cc \ google/protobuf/stubs/statusor_test.cc \ google/protobuf/stubs/status_test.cc \ google/protobuf/stubs/stringpiece_unittest.cc \ @@ -775,7 +736,6 @@ protobuf_test_SOURCES = \ google/protobuf/stubs/strutil_unittest.cc \ google/protobuf/stubs/template_util_unittest.cc \ google/protobuf/stubs/time_test.cc \ - google/protobuf/stubs/type_traits_unittest.cc \ google/protobuf/any_test.cc \ google/protobuf/arenastring_unittest.cc \ google/protobuf/arena_unittest.cc \ @@ -788,11 +748,13 @@ protobuf_test_SOURCES = \ google/protobuf/map_field_test.cc \ google/protobuf/map_test.cc \ google/protobuf/message_unittest.cc \ + google/protobuf/message_unittest.inc \ google/protobuf/no_field_presence_test.cc \ google/protobuf/preserve_unknown_enum_test.cc \ - google/protobuf/proto3_arena_unittest.cc \ google/protobuf/proto3_arena_lite_unittest.cc \ + google/protobuf/proto3_arena_unittest.cc \ google/protobuf/proto3_lite_unittest.cc \ + google/protobuf/proto3_lite_unittest.inc \ google/protobuf/reflection_ops_unittest.cc \ google/protobuf/repeated_field_reflection_unittest.cc \ google/protobuf/repeated_field_unittest.cc \ @@ -804,7 +766,8 @@ protobuf_test_SOURCES = \ google/protobuf/io/printer_unittest.cc \ google/protobuf/io/tokenizer_unittest.cc \ google/protobuf/io/zero_copy_stream_unittest.cc \ - google/protobuf/compiler/command_line_interface_unittest.cc \ + google/protobuf/compiler/annotation_test_util.h \ + google/protobuf/compiler/annotation_test_util.cc \ google/protobuf/compiler/importer_unittest.cc \ google/protobuf/compiler/mock_code_generator.cc \ google/protobuf/compiler/mock_code_generator.h \ @@ -813,6 +776,7 @@ protobuf_test_SOURCES = \ google/protobuf/compiler/cpp/cpp_move_unittest.cc \ google/protobuf/compiler/cpp/cpp_unittest.h \ google/protobuf/compiler/cpp/cpp_unittest.cc \ + google/protobuf/compiler/cpp/cpp_unittest.inc \ google/protobuf/compiler/cpp/cpp_plugin_unittest.cc \ google/protobuf/compiler/cpp/metadata_test.cc \ google/protobuf/compiler/java/java_plugin_unittest.cc \ @@ -835,25 +799,26 @@ protobuf_test_SOURCES = \ google/protobuf/util/message_differencer_unittest.cc \ google/protobuf/util/time_util_test.cc \ google/protobuf/util/type_resolver_util_test.cc \ + $(NON_MSVC_TEST_SOURCES) \ $(COMMON_TEST_SOURCES) - - nodist_protobuf_test_SOURCES = $(protoc_outputs) +$(am_protobuf_test_OBJECTS): unittest_proto_middleman # Run cpp_unittest again with PROTOBUF_TEST_NO_DESCRIPTORS defined. protobuf_lazy_descriptor_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la \ libprotoc.la \ - ../gmock/gtest/lib/libgtest.la \ - ../gmock/lib/libgmock.la \ - ../gmock/lib/libgmock_main.la -protobuf_lazy_descriptor_test_CPPFLAGS = -I$(srcdir)/../gmock/include \ - -I$(srcdir)/../gmock/gtest/include \ + $(GOOGLETEST_BUILD_DIR)/lib/libgtest.la \ + $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock.la \ + $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock_main.la +protobuf_lazy_descriptor_test_CPPFLAGS = -I$(GOOGLEMOCK_SRC_DIR)/include \ + -I$(GOOGLETEST_SRC_DIR)/include \ -DPROTOBUF_TEST_NO_DESCRIPTORS protobuf_lazy_descriptor_test_CXXFLAGS = $(NO_OPT_CXXFLAGS) protobuf_lazy_descriptor_test_SOURCES = \ google/protobuf/compiler/cpp/cpp_unittest.cc \ $(COMMON_TEST_SOURCES) nodist_protobuf_lazy_descriptor_test_SOURCES = $(protoc_outputs) +$(am_protobuf_lazy_descriptor_test_OBJECTS): unittest_proto_middleman COMMON_LITE_TEST_SOURCES = \ google/protobuf/arena_test_util.cc \ @@ -867,37 +832,39 @@ COMMON_LITE_TEST_SOURCES = \ # depend on gtest because our internal version of gtest depend on proto # full runtime and we want to make sure this test builds without full # runtime. -protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la \ - ../gmock/gtest/lib/libgtest.la \ - ../gmock/lib/libgmock.la \ - ../gmock/lib/libgmock_main.la -protobuf_lite_test_CPPFLAGS= -I$(srcdir)/../gmock/include \ - -I$(srcdir)/../gmock/gtest/include +protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la \ + $(GOOGLETEST_BUILD_DIR)/lib/libgtest.la \ + $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock.la \ + $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock_main.la +protobuf_lite_test_CPPFLAGS= -I$(GOOGLEMOCK_SRC_DIR)/include \ + -I$(GOOGLETEST_SRC_DIR)/include protobuf_lite_test_CXXFLAGS = $(NO_OPT_CXXFLAGS) protobuf_lite_test_SOURCES = \ google/protobuf/lite_unittest.cc \ $(COMMON_LITE_TEST_SOURCES) nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs) +$(am_protobuf_lite_test_OBJECTS): unittest_proto_middleman # lite_arena_unittest depends on gtest because teboring@ found that without # gtest when building the test internally our memory sanitizer doesn't detect # memory leaks (don't know why). protobuf_lite_arena_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la \ - ../gmock/gtest/lib/libgtest.la \ - ../gmock/lib/libgmock.la \ - ../gmock/lib/libgmock_main.la -protobuf_lite_arena_test_CPPFLAGS = -I$(srcdir)/../gmock/include \ - -I$(srcdir)/../gmock/gtest/include + $(GOOGLETEST_BUILD_DIR)/lib/libgtest.la \ + $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock.la \ + $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock_main.la +protobuf_lite_arena_test_CPPFLAGS = -I$(GOOGLEMOCK_SRC_DIR)/include \ + -I$(GOOGLETEST_SRC_DIR)/include protobuf_lite_arena_test_CXXFLAGS = $(NO_OPT_CXXFLAGS) protobuf_lite_arena_test_SOURCES = \ google/protobuf/lite_arena_unittest.cc \ $(COMMON_LITE_TEST_SOURCES) nodist_protobuf_lite_arena_test_SOURCES = $(protoc_lite_outputs) +$(am_protobuf_lite_arena_test_OBJECTS): unittest_proto_middleman # Test plugin binary. test_plugin_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \ - ../gmock/gtest/lib/libgtest.la -test_plugin_CPPFLAGS = -I$(srcdir)/../gmock/gtest/include + $(GOOGLETEST_BUILD_DIR)/lib/libgtest.la +test_plugin_CPPFLAGS = -I$(GOOGLETEST_SRC_DIR)/include test_plugin_SOURCES = \ google/protobuf/compiler/mock_code_generator.cc \ google/protobuf/testing/file.cc \ @@ -918,9 +885,7 @@ endif no_warning_test.cc: echo "// Generated from Makefile.am" > no_warning_test.cc for FILE in $(nobase_include_HEADERS); do \ - if ! echo $${FILE} | grep "atomicops"; then \ - echo "#include <$${FILE}>" >> no_warning_test.cc; \ - fi \ + echo "#include <$${FILE}>" >> no_warning_test.cc; \ done echo "int main(int, char**) { return 0; }" >> no_warning_test.cc diff --git a/src/README.md b/src/README.md index c9362ee2288a4..78d6bb5ec72c7 100644 --- a/src/README.md +++ b/src/README.md @@ -1,7 +1,7 @@ Protocol Buffers - Google's data interchange format =================================================== -[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) +[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-cpp_distcheck.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fcpp_distcheck%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-bazel.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fbazel%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fcpp%2Fcontinuous) [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-cpp_distcheck.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fcpp_distcheck%2Fcontinuous) [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) Copyright 2008 Google Inc. @@ -15,38 +15,45 @@ To build protobuf from source, the following tools are needed: * autoconf * automake * libtool - * curl (used to download gmock) * make * g++ * unzip -On Ubuntu, you can install them with: +On Ubuntu/Debian, you can install them with: $ sudo apt-get install autoconf automake libtool curl make g++ unzip On other platforms, please use the corresponding package managing tool to install them before proceeding. -If you get the source from github, you need to generate the configure script -first: +To get the source, download one of the release .tar.gz or .zip packages in the +release page: - $ ./autogen.sh + https://github.com/protocolbuffers/protobuf/releases/latest -This will download gmock source (which is used for C++ Protocol Buffer -unit-tests) to the current directory and run automake, autoconf, etc. -to generate the configure script and various template makefiles. +For example: if you only need C++, download `protobuf-cpp-[VERSION].tar.gz`; if +you need C++ and Java, download `protobuf-java-[VERSION].tar.gz` (every package +contains C++ source already); if you need C++ and multiple other languages, +download `protobuf-all-[VERSION].tar.gz`. -You can skip this step if you are using a release package (which already -contains gmock and the configure script). +You can also get the source by "git clone" our git repository. Make sure you +have also cloned the submodules and generated the configure script (skip this +if you are using a release .tar.gz or .zip package): + + git clone https://github.com/protocolbuffers/protobuf.git + cd protobuf + git submodule update --init --recursive + ./autogen.sh To build and install the C++ Protocol Buffer runtime and the Protocol Buffer compiler (protoc) execute the following: - $ ./configure - $ make - $ make check - $ sudo make install - $ sudo ldconfig # refresh shared library cache. + + ./configure + make + make check + sudo make install + sudo ldconfig # refresh shared library cache. If "make check" fails, you can still install, but it is likely that some features of this library will not work correctly on your system. @@ -55,122 +62,125 @@ Proceed at your own risk. For advanced usage information on configure and make, please refer to the autoconf documentation: - http://www.gnu.org/software/autoconf/manual/autoconf.html#Running-configure-Scripts + http://www.gnu.org/software/autoconf/manual/autoconf.html#Running-configure-Scripts **Hint on install location** - By default, the package will be installed to /usr/local. However, - on many platforms, /usr/local/lib is not part of LD_LIBRARY_PATH. - You can add it, but it may be easier to just install to /usr - instead. To do this, invoke configure as follows: +By default, the package will be installed to /usr/local. However, +on many platforms, /usr/local/lib is not part of LD_LIBRARY_PATH. +You can add it, but it may be easier to just install to /usr +instead. To do this, invoke configure as follows: ./configure --prefix=/usr - If you already built the package with a different prefix, make sure - to run "make clean" before building again. +If you already built the package with a different prefix, make sure +to run "make clean" before building again. **Compiling dependent packages** - To compile a package that uses Protocol Buffers, you need to pass - various flags to your compiler and linker. As of version 2.2.0, - Protocol Buffers integrates with pkg-config to manage this. If you - have pkg-config installed, then you can invoke it to get a list of - flags like so: +To compile a package that uses Protocol Buffers, you need to pass +various flags to your compiler and linker. As of version 2.2.0, +Protocol Buffers integrates with pkg-config to manage this. If you +have pkg-config installed, then you can invoke it to get a list of +flags like so: + pkg-config --cflags protobuf # print compiler flags pkg-config --libs protobuf # print linker flags pkg-config --cflags --libs protobuf # print both - For example: + +For example: c++ my_program.cc my_proto.pb.cc `pkg-config --cflags --libs protobuf` - Note that packages written prior to the 2.2.0 release of Protocol - Buffers may not yet integrate with pkg-config to get flags, and may - not pass the correct set of flags to correctly link against - libprotobuf. If the package in question uses autoconf, you can - often fix the problem by invoking its configure script like: +Note that packages written prior to the 2.2.0 release of Protocol +Buffers may not yet integrate with pkg-config to get flags, and may +not pass the correct set of flags to correctly link against +libprotobuf. If the package in question uses autoconf, you can +often fix the problem by invoking its configure script like: + configure CXXFLAGS="$(pkg-config --cflags protobuf)" \ LIBS="$(pkg-config --libs protobuf)" - This will force it to use the correct flags. +This will force it to use the correct flags. - If you are writing an autoconf-based package that uses Protocol - Buffers, you should probably use the PKG_CHECK_MODULES macro in your - configure script like: +If you are writing an autoconf-based package that uses Protocol +Buffers, you should probably use the PKG_CHECK_MODULES macro in your +configure script like: PKG_CHECK_MODULES([protobuf], [protobuf]) - See the pkg-config man page for more info. +See the pkg-config man page for more info. - If you only want protobuf-lite, substitute "protobuf-lite" in place - of "protobuf" in these examples. +If you only want protobuf-lite, substitute "protobuf-lite" in place +of "protobuf" in these examples. **Note for Mac users** - For a Mac system, Unix tools are not available by default. You will first need - to install Xcode from the Mac AppStore and then run the following command from - a terminal: +For a Mac system, Unix tools are not available by default. You will first need +to install Xcode from the Mac AppStore and then run the following command from +a terminal: - $ sudo xcode-select --install + sudo xcode-select --install - To install Unix tools, you can install "port" following the instructions at - https://www.macports.org . This will reside in /opt/local/bin/port for most - Mac installations. +To install Unix tools, you can install "port" following the instructions at +https://www.macports.org . This will reside in /opt/local/bin/port for most +Mac installations. - $ sudo /opt/local/bin/port install autoconf automake libtool + sudo /opt/local/bin/port install autoconf automake libtool - Then follow the Unix instructions above. +Then follow the Unix instructions above. **Note for cross-compiling** - The makefiles normally invoke the protoc executable that they just - built in order to build tests. When cross-compiling, the protoc - executable may not be executable on the host machine. In this case, - you must build a copy of protoc for the host machine first, then use - the --with-protoc option to tell configure to use it instead. For - example: +The makefiles normally invoke the protoc executable that they just +built in order to build tests. When cross-compiling, the protoc +executable may not be executable on the host machine. In this case, +you must build a copy of protoc for the host machine first, then use +the --with-protoc option to tell configure to use it instead. For +example: ./configure --with-protoc=protoc - This will use the installed protoc (found in your $PATH) instead of - trying to execute the one built during the build process. You can - also use an executable that hasn't been installed. For example, if - you built the protobuf package for your host machine in ../host, - you might do: +This will use the installed protoc (found in your $PATH) instead of +trying to execute the one built during the build process. You can +also use an executable that hasn't been installed. For example, if +you built the protobuf package for your host machine in ../host, +you might do: ./configure --with-protoc=../host/src/protoc - Either way, you must make sure that the protoc executable you use - has the same version as the protobuf source code you are trying to - use it with. +Either way, you must make sure that the protoc executable you use +has the same version as the protobuf source code you are trying to +use it with. **Note for Solaris users** - Solaris 10 x86 has a bug that will make linking fail, complaining - about libstdc++.la being invalid. We have included a work-around - in this package. To use the work-around, run configure as follows: +Solaris 10 x86 has a bug that will make linking fail, complaining +about libstdc++.la being invalid. We have included a work-around +in this package. To use the work-around, run configure as follows: ./configure LDFLAGS=-L$PWD/src/solaris - See src/solaris/libstdc++.la for more info on this bug. +See src/solaris/libstdc++.la for more info on this bug. **Note for HP C++ Tru64 users** - To compile invoke configure as follows: +To compile invoke configure as follows: ./configure CXXFLAGS="-O -std ansi -ieee -D__USE_STD_IOSTREAM" - Also, you will need to use gmake instead of make. +Also, you will need to use gmake instead of make. **Note for AIX users** - Compile using the IBM xlC C++ compiler as follows: +Compile using the IBM xlC C++ compiler as follows: ./configure CXX=xlC - Also, you will need to use GNU `make` (`gmake`) instead of AIX `make`. +Also, you will need to use GNU `make` (`gmake`) instead of AIX `make`. C++ Installation - Windows -------------------------- @@ -178,12 +188,22 @@ C++ Installation - Windows If you only need the protoc binary, you can download it from the release page: - https://github.com/google/protobuf/releases + https://github.com/protocolbuffers/protobuf/releases/latest In the downloads section, download the zip file protoc-$VERSION-win32.zip. It contains the protoc binary as well as public proto files of protobuf library. +Protobuf and its dependencies can be installed directly by using `vcpkg`: + + >vcpkg install protobuf protobuf:x64-windows + +If zlib support is desired, you'll also need to install the zlib feature: + + >vcpkg install protobuf[zlib] protobuf[zlib]:x64-windows + +See https://github.com/Microsoft/vcpkg for more information. + To build from source using Microsoft Visual C++, see [cmake/README.md](../cmake/README.md). To build from source using Cygwin or MinGW, follow the Unix installation diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc index 83edba5788ad7..029ba0d9299d2 100644 --- a/src/google/protobuf/any.cc +++ b/src/google/protobuf/any.cc @@ -30,85 +30,55 @@ #include +#include +#include #include +#include + +#include namespace google { namespace protobuf { namespace internal { -namespace { -string GetTypeUrl(const Descriptor* message, - const string& type_url_prefix) { - if (!type_url_prefix.empty() && - type_url_prefix[type_url_prefix.size() - 1] == '/') { - return type_url_prefix + message->full_name(); - } else { - return type_url_prefix + "/" + message->full_name(); - } -} -} // namespace - -const char kAnyFullTypeName[] = "google.protobuf.Any"; -const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/"; -const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/"; - -AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value) - : type_url_(type_url), value_(value) { +bool AnyMetadata::PackFrom(const Message& message) { + return PackFrom(message, kTypeGoogleApisComPrefix); } -void AnyMetadata::PackFrom(const Message& message) { - PackFrom(message, kTypeGoogleApisComPrefix); -} - -void AnyMetadata::PackFrom(const Message& message, - const string& type_url_prefix) { - type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(), - GetTypeUrl(message.GetDescriptor(), type_url_prefix)); - message.SerializeToString(value_->MutableNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited())); +bool AnyMetadata::PackFrom(const Message& message, + StringPiece type_url_prefix) { + type_url_->Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString(), + GetTypeUrl(message.GetDescriptor()->full_name(), type_url_prefix), + nullptr); + return message.SerializeToString( + value_->Mutable(ArenaStringPtr::EmptyDefault{}, nullptr)); } bool AnyMetadata::UnpackTo(Message* message) const { - if (!InternalIs(message->GetDescriptor())) { + if (!InternalIs(message->GetDescriptor()->full_name())) { return false; } - return message->ParseFromString(value_->GetNoArena()); + return message->ParseFromString(value_->Get()); } -bool AnyMetadata::InternalIs(const Descriptor* descriptor) const { - const string type_url = type_url_->GetNoArena(); - string full_name; - if (!ParseAnyTypeUrl(type_url, &full_name)) { - return false; - } - return full_name == descriptor->full_name(); -} - -bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) { - size_t pos = type_url.find_last_of("/"); - if (pos == string::npos || pos + 1 == type_url.size()) { - return false; - } - *full_type_name = type_url.substr(pos + 1); - return true; -} - - bool GetAnyFieldDescriptors(const Message& message, const FieldDescriptor** type_url_field, const FieldDescriptor** value_field) { - const Descriptor* descriptor = message.GetDescriptor(); - if (descriptor->full_name() != kAnyFullTypeName) { - return false; - } - *type_url_field = descriptor->FindFieldByNumber(1); - *value_field = descriptor->FindFieldByNumber(2); - return (*type_url_field != NULL && - (*type_url_field)->type() == FieldDescriptor::TYPE_STRING && - *value_field != NULL && - (*value_field)->type() == FieldDescriptor::TYPE_BYTES); + const Descriptor* descriptor = message.GetDescriptor(); + if (descriptor->full_name() != kAnyFullTypeName) { + return false; + } + *type_url_field = descriptor->FindFieldByNumber(1); + *value_field = descriptor->FindFieldByNumber(2); + return (*type_url_field != NULL && + (*type_url_field)->type() == FieldDescriptor::TYPE_STRING && + *value_field != NULL && + (*value_field)->type() == FieldDescriptor::TYPE_BYTES); } } // namespace internal } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h index c2c27ec33381a..684fbf1584315 100644 --- a/src/google/protobuf/any.h +++ b/src/google/protobuf/any.h @@ -34,49 +34,86 @@ #include #include -#include -#include #include +#include + +#include namespace google { namespace protobuf { + +class FieldDescriptor; +class Message; + namespace internal { +extern const char kAnyFullTypeName[]; // "google.protobuf.Any". +extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/". +extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/". + +std::string GetTypeUrl(StringPiece message_name, + StringPiece type_url_prefix); + // Helper class used to implement google::protobuf::Any. -class LIBPROTOBUF_EXPORT AnyMetadata { +class PROTOBUF_EXPORT AnyMetadata { typedef ArenaStringPtr UrlType; typedef ArenaStringPtr ValueType; public: // AnyMetadata does not take ownership of "type_url" and "value". - AnyMetadata(UrlType* type_url, ValueType* value); + constexpr AnyMetadata(UrlType* type_url, ValueType* value) + : type_url_(type_url), value_(value) {} // Packs a message using the default type URL prefix: "type.googleapis.com". // The resulted type URL will be "type.googleapis.com/". - void PackFrom(const Message& message); + // Returns false if serializing the message failed. + template + bool PackFrom(const T& message) { + return InternalPackFrom(message, kTypeGoogleApisComPrefix, + T::FullMessageName()); + } + + bool PackFrom(const Message& message); + // Packs a message using the given type URL prefix. The type URL will be // constructed by concatenating the message type's full name to the prefix - // with an optional "/" separator if the prefix doesn't already end up "/". + // with an optional "/" separator if the prefix doesn't already end with "/". // For example, both PackFrom(message, "type.googleapis.com") and // PackFrom(message, "type.googleapis.com/") yield the same result type // URL: "type.googleapis.com/". - void PackFrom(const Message& message, const string& type_url_prefix); + // Returns false if serializing the message failed. + template + bool PackFrom(const T& message, StringPiece type_url_prefix) { + return InternalPackFrom(message, type_url_prefix, T::FullMessageName()); + } + + bool PackFrom(const Message& message, StringPiece type_url_prefix); // Unpacks the payload into the given message. Returns false if the message's // type doesn't match the type specified in the type URL (i.e., the full // name after the last "/" of the type URL doesn't match the message's actual // full name) or parsing the payload has failed. + template + bool UnpackTo(T* message) const { + return InternalUnpackTo(T::FullMessageName(), message); + } + bool UnpackTo(Message* message) const; // Checks whether the type specified in the type URL matches the given type. - // A type is consdiered matching if its full name matches the full name after + // A type is considered matching if its full name matches the full name after // the last "/" in the type URL. - template + template bool Is() const { - return InternalIs(T::default_instance().GetDescriptor()); + return InternalIs(T::FullMessageName()); } private: - bool InternalIs(const Descriptor* message) const; + bool InternalPackFrom(const MessageLite& message, + StringPiece type_url_prefix, + StringPiece type_name); + bool InternalUnpackTo(StringPiece type_name, + MessageLite* message) const; + bool InternalIs(StringPiece type_name) const; UrlType* type_url_; ValueType* value_; @@ -84,15 +121,22 @@ class LIBPROTOBUF_EXPORT AnyMetadata { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata); }; -extern const char kAnyFullTypeName[]; // "google.protobuf.Any". -extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/". -extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/". - // Get the proto type name from Any::type_url value. For example, passing // "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in // *full_type_name. Returns false if the type_url does not have a "/" // in the type url separating the full type name. -bool ParseAnyTypeUrl(const string& type_url, string* full_type_name); +// +// NOTE: this function is available publicly as: +// google::protobuf::Any() // static method on the generated message type. +bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name); + +// Get the proto type name and prefix from Any::type_url value. For example, +// passing "type.googleapis.com/rpc.QueryOrigin" will return +// "type.googleapis.com/" in *url_prefix and "rpc.QueryOrigin" in +// *full_type_name. Returns false if the type_url does not have a "/" in the +// type url separating the full type name. +bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix, + std::string* full_type_name); // See if message is of type google.protobuf.Any, if so, return the descriptors // for "type_url" and "value" fields. @@ -102,6 +146,8 @@ bool GetAnyFieldDescriptors(const Message& message, } // namespace internal } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_ANY_H__ diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index 7d538212567ec..aea98c08f6dc3 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -1,346 +1,236 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/any.proto -#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include #include -#include -#include -#include #include -#include +#include +#include #include #include #include #include // @@protoc_insertion_point(includes) - -namespace google { -namespace protobuf { -class AnyDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _Any_default_instance_; - -namespace protobuf_google_2fprotobuf_2fany_2eproto { - - -namespace { - -::google::protobuf::Metadata file_level_metadata[1]; - -} // namespace - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField - const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0}, -}; - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField - const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - ::google::protobuf::internal::AuxillaryParseTableField(), -}; -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const - TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, +#include + +PROTOBUF_PRAGMA_INIT_SEG +PROTOBUF_NAMESPACE_OPEN +constexpr Any::Any( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , _any_metadata_(&type_url_, &value_){} +struct AnyDefaultTypeInternal { + constexpr AnyDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~AnyDefaultTypeInternal() {} + union { + Any _instance; + }; }; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT AnyDefaultTypeInternal _Any_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fany_2eproto[1]; +static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fany_2eproto = nullptr; -const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { +const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fany_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { ~0u, // no _has_bits_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Any, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, type_url_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, value_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Any, type_url_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Any, value_), }; -static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { 0, -1, sizeof(Any)}, +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, sizeof(PROTOBUF_NAMESPACE_ID::Any)}, }; -static ::google::protobuf::Message const * const file_default_instances[] = { - reinterpret_cast(&_Any_default_instance_), +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_Any_default_instance_), }; -namespace { - -void protobuf_AssignDescriptors() { - AddDescriptors(); - ::google::protobuf::MessageFactory* factory = NULL; - AssignDescriptors( - "google/protobuf/any.proto", schemas, file_default_instances, TableStruct::offsets, factory, - file_level_metadata, NULL, NULL); -} - -void protobuf_AssignDescriptorsOnce() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors); -} - -void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; -void protobuf_RegisterTypes(const ::std::string&) { - protobuf_AssignDescriptorsOnce(); - ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1); -} - -} // namespace -void TableStruct::InitDefaultsImpl() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - ::google::protobuf::internal::InitProtobufDefaults(); - _Any_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_Any_default_instance_);} - -void InitDefaults() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl); -} -namespace { -void AddDescriptorsImpl() { - InitDefaults(); - static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - "\n\031google/protobuf/any.proto\022\017google.prot" - "obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002" - " \001(\014Bo\n\023com.google.protobufB\010AnyProtoP\001Z" - "%github.com/golang/protobuf/ptypes/any\242\002" - "\003GPB\252\002\036Google.Protobuf.WellKnownTypesb\006p" - "roto3" - }; - ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( - descriptor, 205); - ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( - "google/protobuf/any.proto", &protobuf_RegisterTypes); +const char descriptor_table_protodef_google_2fprotobuf_2fany_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\031google/protobuf/any.proto\022\017google.prot" + "obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002" + " \001(\014Bv\n\023com.google.protobufB\010AnyProtoP\001Z" + ",google.golang.org/protobuf/types/known/" + "anypb\242\002\003GPB\252\002\036Google.Protobuf.WellKnownT" + "ypesb\006proto3" + ; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fany_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto = { + false, false, 212, descriptor_table_protodef_google_2fprotobuf_2fany_2eproto, "google/protobuf/any.proto", + &descriptor_table_google_2fprotobuf_2fany_2eproto_once, nullptr, 0, 1, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fany_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fany_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto, file_level_service_descriptors_google_2fprotobuf_2fany_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata +descriptor_table_google_2fprotobuf_2fany_2eproto_metadata_getter(int index) { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fany_2eproto); + return descriptor_table_google_2fprotobuf_2fany_2eproto.file_level_metadata[index]; } -} // anonymous namespace - -void AddDescriptors() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl); -} -// Force AddDescriptors() to be called at dynamic initialization time. -struct StaticDescriptorInitializer { - StaticDescriptorInitializer() { - AddDescriptors(); - } -} static_descriptor_initializer; - -} // namespace protobuf_google_2fprotobuf_2fany_2eproto +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fany_2eproto(&descriptor_table_google_2fprotobuf_2fany_2eproto); +PROTOBUF_NAMESPACE_OPEN // =================================================================== -void Any::PackFrom(const ::google::protobuf::Message& message) { - _any_metadata_.PackFrom(message); -} - -void Any::PackFrom(const ::google::protobuf::Message& message, - const ::std::string& type_url_prefix) { - _any_metadata_.PackFrom(message, type_url_prefix); +bool Any::GetAnyFieldDescriptors( + const ::PROTOBUF_NAMESPACE_ID::Message& message, + const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field, + const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** value_field) { + return ::PROTOBUF_NAMESPACE_ID::internal::GetAnyFieldDescriptors( + message, type_url_field, value_field); } - -bool Any::UnpackTo(::google::protobuf::Message* message) const { - return _any_metadata_.UnpackTo(message); +bool Any::ParseAnyTypeUrl( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url, + std::string* full_type_name) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseAnyTypeUrl(type_url, + full_type_name); } -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int Any::kTypeUrlFieldNumber; -const int Any::kValueFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +class Any::_Internal { + public: +}; -Any::Any() - : ::google::protobuf::Message(), _internal_metadata_(NULL), _any_metadata_(&type_url_, &value_) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fany_2eproto::InitDefaults(); - } +Any::Any(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + _any_metadata_(&type_url_, &value_) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.Any) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Any) } Any::Any(const Any& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _cached_size_(0), + : ::PROTOBUF_NAMESPACE_ID::Message(), _any_metadata_(&type_url_, &value_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.type_url().size() > 0) { - type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_type_url().empty()) { + type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_type_url(), + GetArena()); } - value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.value().size() > 0) { - value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_); + value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_value().empty()) { + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_value(), + GetArena()); } // @@protoc_insertion_point(copy_constructor:google.protobuf.Any) } void Any::SharedCtor() { - type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - _cached_size_ = 0; +type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } Any::~Any() { // @@protoc_insertion_point(destructor:google.protobuf.Any) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void Any::SharedDtor() { - type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + type_url_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + value_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } -void Any::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* Any::descriptor() { - protobuf_google_2fprotobuf_2fany_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fany_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void Any::ArenaDtor(void* object) { + Any* _this = reinterpret_cast< Any* >(object); + (void)_this; } - -const Any& Any::default_instance() { - protobuf_google_2fprotobuf_2fany_2eproto::InitDefaults(); - return *internal_default_instance(); +void Any::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -Any* Any::New(::google::protobuf::Arena* arena) const { - Any* n = new Any; - if (arena != NULL) { - arena->Own(n); - } - return n; +void Any::SetCachedSize(int size) const { + _cached_size_.Set(size); } void Any::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Any) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - _internal_metadata_.Clear(); + type_url_.ClearToEmpty(); + value_.ClearToEmpty(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } -bool Any::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.Any) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { +const char* Any::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { // string type_url = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_type_url())); - DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->type_url().data(), static_cast(this->type_url().length()), - ::google::protobuf::internal::WireFormatLite::PARSE, - "google.protobuf.Any.type_url")); - } else { - goto handle_unusual; - } - break; - } - + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_type_url(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.Any.type_url")); + CHK_(ptr); + } else goto handle_unusual; + continue; // bytes value = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadBytes( - input, this->mutable_value())); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + auto str = _internal_mutable_value(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.Any) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.Any) - return false; -#undef DO_ + ptr = nullptr; + goto success; +#undef CHK_ } -void Any::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.Any) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // string type_url = 1; - if (this->type_url().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->type_url().data(), static_cast(this->type_url().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, - "google.protobuf.Any.type_url"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->type_url(), output); - } - - // bytes value = 2; - if (this->value().size() > 0) { - ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased( - 2, this->value(), output); - } - - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.Any) -} - -::google::protobuf::uint8* Any::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* Any::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // string type_url = 1; if (this->type_url().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->type_url().data(), static_cast(this->type_url().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_type_url().data(), static_cast(this->_internal_type_url().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "google.protobuf.Any.type_url"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->type_url(), target); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_type_url(), target); } // bytes value = 2; if (this->value().size() > 0) { - target = - ::google::protobuf::internal::WireFormatLite::WriteBytesToArray( - 2, this->value(), target); + target = stream->WriteBytesMaybeAliased( + 2, this->_internal_value(), target); } - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Any) return target; @@ -350,41 +240,42 @@ size_t Any::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any) size_t total_size = 0; - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // string type_url = 1; if (this->type_url().size() > 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->type_url()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_type_url()); } // bytes value = 2; if (this->value().size() > 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::BytesSize( - this->value()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize( + this->_internal_value()); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void Any::MergeFrom(const ::google::protobuf::Message& from) { +void Any::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Any) GOOGLE_DCHECK_NE(&from, this); const Any* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Any) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Any) MergeFrom(*source); @@ -394,21 +285,19 @@ void Any::MergeFrom(const ::google::protobuf::Message& from) { void Any::MergeFrom(const Any& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; if (from.type_url().size() > 0) { - - type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_); + _internal_set_type_url(from._internal_type_url()); } if (from.value().size() > 0) { - - value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_); + _internal_set_value(from._internal_value()); } } -void Any::CopyFrom(const ::google::protobuf::Message& from) { +void Any::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Any) if (&from == this) return; Clear(); @@ -426,137 +315,25 @@ bool Any::IsInitialized() const { return true; } -void Any::Swap(Any* other) { - if (other == this) return; - InternalSwap(other); -} void Any::InternalSwap(Any* other) { using std::swap; - type_url_.Swap(&other->type_url_); - value_.Swap(&other->value_); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata Any::GetMetadata() const { - protobuf_google_2fprotobuf_2fany_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fany_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// Any - -// string type_url = 1; -void Any::clear_type_url() { - type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -const ::std::string& Any::type_url() const { - // @@protoc_insertion_point(field_get:google.protobuf.Any.type_url) - return type_url_.GetNoArena(); -} -void Any::set_type_url(const ::std::string& value) { - - type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.Any.type_url) -} -#if LANG_CXX11 -void Any::set_type_url(::std::string&& value) { - - type_url_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.type_url) -} -#endif -void Any::set_type_url(const char* value) { - GOOGLE_DCHECK(value != NULL); - - type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.Any.type_url) -} -void Any::set_type_url(const char* value, size_t size) { - - type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url) -} -::std::string* Any::mutable_type_url() { - - // @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url) - return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* Any::release_type_url() { - // @@protoc_insertion_point(field_release:google.protobuf.Any.type_url) - - return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void Any::set_allocated_type_url(::std::string* type_url) { - if (type_url != NULL) { - - } else { - - } - type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url) + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + type_url_.Swap(&other->type_url_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + value_.Swap(&other->value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -// bytes value = 2; -void Any::clear_value() { - value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -const ::std::string& Any::value() const { - // @@protoc_insertion_point(field_get:google.protobuf.Any.value) - return value_.GetNoArena(); -} -void Any::set_value(const ::std::string& value) { - - value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.Any.value) -} -#if LANG_CXX11 -void Any::set_value(::std::string&& value) { - - value_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.value) -} -#endif -void Any::set_value(const char* value) { - GOOGLE_DCHECK(value != NULL); - - value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.Any.value) -} -void Any::set_value(const void* value, size_t size) { - - value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value) -} -::std::string* Any::mutable_value() { - - // @@protoc_insertion_point(field_mutable:google.protobuf.Any.value) - return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* Any::release_value() { - // @@protoc_insertion_point(field_release:google.protobuf.Any.value) - - return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void Any::set_allocated_value(::std::string* value) { - if (value != NULL) { - - } else { - - } - value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value) +::PROTOBUF_NAMESPACE_ID::Metadata Any::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::Any* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::Any >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::Any >(arena); +} +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) +#include diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h index 5ffda74117fb4..98d48904397f3 100644 --- a/src/google/protobuf/any.pb.h +++ b/src/google/protobuf/any.pb.h @@ -1,184 +1,270 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/any.proto -#ifndef PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED -#define PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto +#include #include -#include - -#if GOOGLE_PROTOBUF_VERSION < 3004000 +#include +#if PROTOBUF_VERSION < 3015000 #error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update +#error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 3015000 < PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please +#error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif +#include #include #include #include #include #include -#include +#include +#include #include #include // IWYU pragma: export #include // IWYU pragma: export #include -#include // @@protoc_insertion_point(includes) -namespace google { -namespace protobuf { -class Any; -class AnyDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_; -} // namespace protobuf -} // namespace google - -namespace google { -namespace protobuf { - -namespace protobuf_google_2fprotobuf_2fany_2eproto { -// Internal implementation detail -- do not call these. -struct LIBPROTOBUF_EXPORT TableStruct { - static const ::google::protobuf::internal::ParseTableField entries[]; - static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; - static const ::google::protobuf::internal::ParseTable schema[]; - static const ::google::protobuf::uint32 offsets[]; - static const ::google::protobuf::internal::FieldMetadata field_metadata[]; - static const ::google::protobuf::internal::SerializationTable serialization_table[]; - static void InitDefaultsImpl(); +#include +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fany_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fany_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; }; -void LIBPROTOBUF_EXPORT AddDescriptors(); -void LIBPROTOBUF_EXPORT InitDefaults(); -} // namespace protobuf_google_2fprotobuf_2fany_2eproto +extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto; +PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fany_2eproto_metadata_getter(int index); +PROTOBUF_NAMESPACE_OPEN +class Any; +struct AnyDefaultTypeInternal; +PROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::Any* Arena::CreateMaybeMessage(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN // =================================================================== -class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ { +class PROTOBUF_EXPORT Any PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ { public: - Any(); + inline Any() : Any(nullptr) {} virtual ~Any(); + explicit constexpr Any(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); Any(const Any& from); + Any(Any&& from) noexcept + : Any() { + *this = ::std::move(from); + } inline Any& operator=(const Any& from) { CopyFrom(from); return *this; } - static const ::google::protobuf::Descriptor* descriptor(); - static const Any& default_instance(); + inline Any& operator=(Any&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const Any& default_instance() { + return *internal_default_instance(); + } static inline const Any* internal_default_instance() { return reinterpret_cast( &_Any_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 0; // implements Any ----------------------------------------------- - void PackFrom(const ::google::protobuf::Message& message); - void PackFrom(const ::google::protobuf::Message& message, - const ::std::string& type_url_prefix); - bool UnpackTo(::google::protobuf::Message* message) const; + bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message) { + return _any_metadata_.PackFrom(message); + } + bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message, + ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) { + return _any_metadata_.PackFrom(message, type_url_prefix); + } + bool UnpackTo(::PROTOBUF_NAMESPACE_ID::Message* message) const { + return _any_metadata_.UnpackTo(message); + } + static bool GetAnyFieldDescriptors( + const ::PROTOBUF_NAMESPACE_ID::Message& message, + const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field, + const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** value_field); + template ::value>::type> + bool PackFrom(const T& message) { + return _any_metadata_.PackFrom(message); + } + template ::value>::type> + bool PackFrom(const T& message, + ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) { + return _any_metadata_.PackFrom(message, type_url_prefix);} + template ::value>::type> + bool UnpackTo(T* message) const { + return _any_metadata_.UnpackTo(message); + } template bool Is() const { return _any_metadata_.Is(); } - - void Swap(Any* other); + static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url, + std::string* full_type_name); friend void swap(Any& a, Any& b) { a.Swap(&b); } + inline void Swap(Any* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Any* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline Any* New() const PROTOBUF_FINAL { return New(NULL); } + inline Any* New() const final { + return CreateMaybeMessage(nullptr); + } - Any* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + Any* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const Any& from); void MergeFrom(const Any& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(Any* other); - private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Any"; } + protected: + explicit Any(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fany_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kTypeUrlFieldNumber = 1, + kValueFieldNumber = 2, + }; // string type_url = 1; void clear_type_url(); - static const int kTypeUrlFieldNumber = 1; - const ::std::string& type_url() const; - void set_type_url(const ::std::string& value); - #if LANG_CXX11 - void set_type_url(::std::string&& value); - #endif + const std::string& type_url() const; + void set_type_url(const std::string& value); + void set_type_url(std::string&& value); void set_type_url(const char* value); void set_type_url(const char* value, size_t size); - ::std::string* mutable_type_url(); - ::std::string* release_type_url(); - void set_allocated_type_url(::std::string* type_url); + std::string* mutable_type_url(); + std::string* release_type_url(); + void set_allocated_type_url(std::string* type_url); + private: + const std::string& _internal_type_url() const; + void _internal_set_type_url(const std::string& value); + std::string* _internal_mutable_type_url(); + public: // bytes value = 2; void clear_value(); - static const int kValueFieldNumber = 2; - const ::std::string& value() const; - void set_value(const ::std::string& value); - #if LANG_CXX11 - void set_value(::std::string&& value); - #endif + const std::string& value() const; + void set_value(const std::string& value); + void set_value(std::string&& value); void set_value(const char* value); void set_value(const void* value, size_t size); - ::std::string* mutable_value(); - ::std::string* release_value(); - void set_allocated_value(::std::string* value); + std::string* mutable_value(); + std::string* release_value(); + void set_allocated_value(std::string* value); + private: + const std::string& _internal_value() const; + void _internal_set_value(const std::string& value); + std::string* _internal_mutable_value(); + public: // @@protoc_insertion_point(class_scope:google.protobuf.Any) private: - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::ArenaStringPtr type_url_; - ::google::protobuf::internal::ArenaStringPtr value_; - mutable int _cached_size_; - ::google::protobuf::internal::AnyMetadata _any_metadata_; - friend struct protobuf_google_2fprotobuf_2fany_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr type_url_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr value_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata _any_metadata_; + friend struct ::TableStruct_google_2fprotobuf_2fany_2eproto; }; // =================================================================== // =================================================================== -#if !PROTOBUF_INLINE_NOT_IN_HEADERS #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" @@ -187,121 +273,135 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_in // string type_url = 1; inline void Any::clear_type_url() { - type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + type_url_.ClearToEmpty(); } -inline const ::std::string& Any::type_url() const { +inline const std::string& Any::type_url() const { // @@protoc_insertion_point(field_get:google.protobuf.Any.type_url) - return type_url_.GetNoArena(); + return _internal_type_url(); } -inline void Any::set_type_url(const ::std::string& value) { - - type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void Any::set_type_url(const std::string& value) { + _internal_set_type_url(value); // @@protoc_insertion_point(field_set:google.protobuf.Any.type_url) } -#if LANG_CXX11 -inline void Any::set_type_url(::std::string&& value) { +inline std::string* Any::mutable_type_url() { + // @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url) + return _internal_mutable_type_url(); +} +inline const std::string& Any::_internal_type_url() const { + return type_url_.Get(); +} +inline void Any::_internal_set_type_url(const std::string& value) { + + type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void Any::set_type_url(std::string&& value) { - type_url_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + type_url_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.type_url) } -#endif inline void Any::set_type_url(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); - type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Any.type_url) } -inline void Any::set_type_url(const char* value, size_t size) { +inline void Any::set_type_url(const char* value, + size_t size) { - type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); + type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url) } -inline ::std::string* Any::mutable_type_url() { +inline std::string* Any::_internal_mutable_type_url() { - // @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url) - return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* Any::release_type_url() { +inline std::string* Any::release_type_url() { // @@protoc_insertion_point(field_release:google.protobuf.Any.type_url) - - return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return type_url_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void Any::set_allocated_type_url(::std::string* type_url) { - if (type_url != NULL) { +inline void Any::set_allocated_type_url(std::string* type_url) { + if (type_url != nullptr) { } else { } - type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url); + type_url_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), type_url, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url) } // bytes value = 2; inline void Any::clear_value() { - value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + value_.ClearToEmpty(); } -inline const ::std::string& Any::value() const { +inline const std::string& Any::value() const { // @@protoc_insertion_point(field_get:google.protobuf.Any.value) - return value_.GetNoArena(); + return _internal_value(); } -inline void Any::set_value(const ::std::string& value) { - - value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void Any::set_value(const std::string& value) { + _internal_set_value(value); // @@protoc_insertion_point(field_set:google.protobuf.Any.value) } -#if LANG_CXX11 -inline void Any::set_value(::std::string&& value) { +inline std::string* Any::mutable_value() { + // @@protoc_insertion_point(field_mutable:google.protobuf.Any.value) + return _internal_mutable_value(); +} +inline const std::string& Any::_internal_value() const { + return value_.Get(); +} +inline void Any::_internal_set_value(const std::string& value) { - value_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void Any::set_value(std::string&& value) { + + value_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.value) } -#endif inline void Any::set_value(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); - value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Any.value) } -inline void Any::set_value(const void* value, size_t size) { +inline void Any::set_value(const void* value, + size_t size) { - value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value) } -inline ::std::string* Any::mutable_value() { +inline std::string* Any::_internal_mutable_value() { - // @@protoc_insertion_point(field_mutable:google.protobuf.Any.value) - return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* Any::release_value() { +inline std::string* Any::release_value() { // @@protoc_insertion_point(field_release:google.protobuf.Any.value) - - return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return value_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void Any::set_allocated_value(::std::string* value) { - if (value != NULL) { +inline void Any::set_allocated_value(std::string* value) { + if (value != nullptr) { } else { } - value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value) } #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ -#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) -#endif // PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto index c74866762315f..6ed8a23cf5a30 100644 --- a/src/google/protobuf/any.proto +++ b/src/google/protobuf/any.proto @@ -33,7 +33,7 @@ syntax = "proto3"; package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option go_package = "github.com/golang/protobuf/ptypes/any"; +option go_package = "google.golang.org/protobuf/types/known/anypb"; option java_package = "com.google.protobuf"; option java_outer_classname = "AnyProto"; option java_multiple_files = true; @@ -77,10 +77,13 @@ option objc_class_prefix = "GPB"; // Example 4: Pack and unpack a message in Go // // foo := &pb.Foo{...} -// any, err := ptypes.MarshalAny(foo) +// any, err := anypb.New(foo) +// if err != nil { +// ... +// } // ... // foo := &pb.Foo{} -// if err := ptypes.UnmarshalAny(any, foo); err != nil { +// if err := any.UnmarshalTo(foo); err != nil { // ... // } // @@ -120,17 +123,19 @@ option objc_class_prefix = "GPB"; // } // message Any { - // A URL/resource name whose content describes the type of the - // serialized protocol buffer message. + // A URL/resource name that uniquely identifies the type of the serialized + // protocol buffer message. This string must contain at least + // one "/" character. The last segment of the URL's path must represent + // the fully qualified name of the type (as in + // `path/google.protobuf.Duration`). The name should be in a canonical form + // (e.g., leading "." is not accepted). // - // For URLs which use the scheme `http`, `https`, or no scheme, the - // following restrictions and interpretations apply: + // In practice, teams usually precompile into the binary all types that they + // expect it to use in the context of Any. However, for URLs which use the + // scheme `http`, `https`, or no scheme, one can optionally set up a type + // server that maps type URLs to message definitions as follows: // // * If no scheme is provided, `https` is assumed. - // * The last segment of the URL's path must represent the fully - // qualified name of the type (as in `path/google.protobuf.Duration`). - // The name should be in a canonical form (e.g., leading "." is - // not accepted). // * An HTTP GET on the URL must yield a [google.protobuf.Type][] // value in binary format, or produce an error. // * Applications are allowed to cache lookup results based on the @@ -139,6 +144,10 @@ message Any { // on changes to types. (Use versioned type names to manage // breaking changes.) // + // Note: this functionality is not currently available in the official + // protobuf release, and it is not used for type URLs beginning with + // type.googleapis.com. + // // Schemes other than `http`, `https` (or the empty scheme) might be // used with implementation specific semantics. // diff --git a/src/google/protobuf/any_lite.cc b/src/google/protobuf/any_lite.cc new file mode 100644 index 0000000000000..48e0faccf7f59 --- /dev/null +++ b/src/google/protobuf/any_lite.cc @@ -0,0 +1,99 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +std::string GetTypeUrl(StringPiece message_name, + StringPiece type_url_prefix) { + if (!type_url_prefix.empty() && + type_url_prefix[type_url_prefix.size() - 1] == '/') { + return StrCat(type_url_prefix, message_name); + } else { + return StrCat(type_url_prefix, "/", message_name); + } +} + +const char kAnyFullTypeName[] = "google.protobuf.Any"; +const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/"; +const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/"; + +bool AnyMetadata::InternalPackFrom(const MessageLite& message, + StringPiece type_url_prefix, + StringPiece type_name) { + type_url_->Set(&::google::protobuf::internal::GetEmptyString(), + GetTypeUrl(type_name, type_url_prefix), nullptr); + return message.SerializeToString( + value_->Mutable(ArenaStringPtr::EmptyDefault{}, nullptr)); +} + +bool AnyMetadata::InternalUnpackTo(StringPiece type_name, + MessageLite* message) const { + if (!InternalIs(type_name)) { + return false; + } + return message->ParseFromString(value_->Get()); +} + +bool AnyMetadata::InternalIs(StringPiece type_name) const { + StringPiece type_url = type_url_->Get(); + return type_url.size() >= type_name.size() + 1 && + type_url[type_url.size() - type_name.size() - 1] == '/' && + HasSuffixString(type_url, type_name); +} + +bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix, + std::string* full_type_name) { + size_t pos = type_url.find_last_of('/'); + if (pos == std::string::npos || pos + 1 == type_url.size()) { + return false; + } + if (url_prefix) { + *url_prefix = std::string(type_url.substr(0, pos + 1)); + } + *full_type_name = std::string(type_url.substr(pos + 1)); + return true; +} + +bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name) { + return ParseAnyTypeUrl(type_url, nullptr, full_type_name); +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/any_test.cc b/src/google/protobuf/any_test.cc index 1bfaa63d879e9..1d136aa5575a3 100644 --- a/src/google/protobuf/any_test.cc +++ b/src/google/protobuf/any_test.cc @@ -29,26 +29,55 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include #include + +// Must be included last. +#include + namespace google { namespace protobuf { namespace { +TEST(AnyMetadataTest, ConstInit) { + PROTOBUF_CONSTINIT static internal::AnyMetadata metadata(nullptr, nullptr); + (void)metadata; +} + TEST(AnyTest, TestPackAndUnpack) { protobuf_unittest::TestAny submessage; submessage.set_int32_value(12345); protobuf_unittest::TestAny message; - message.mutable_any_value()->PackFrom(submessage); + ASSERT_TRUE(message.mutable_any_value()->PackFrom(submessage)); - string data = message.SerializeAsString(); + std::string data = message.SerializeAsString(); ASSERT_TRUE(message.ParseFromString(data)); EXPECT_TRUE(message.has_any_value()); + submessage.Clear(); ASSERT_TRUE(message.any_value().UnpackTo(&submessage)); EXPECT_EQ(12345, submessage.int32_value()); } +TEST(AnyTest, TestPackFromSerializationExceedsSizeLimit) { + protobuf_unittest::TestAny submessage; + submessage.mutable_text()->resize(INT_MAX, 'a'); + protobuf_unittest::TestAny message; + EXPECT_FALSE(message.mutable_any_value()->PackFrom(submessage)); +} + +TEST(AnyTest, TestUnpackWithTypeMismatch) { + protobuf_unittest::TestAny payload; + payload.set_int32_value(13); + google::protobuf::Any any; + any.PackFrom(payload); + + // Attempt to unpack into the wrong type. + protobuf_unittest::TestAllTypes dest; + EXPECT_FALSE(any.UnpackTo(&dest)); +} + TEST(AnyTest, TestPackAndUnpackAny) { // We can pack a Any message inside another Any message. protobuf_unittest::TestAny submessage; @@ -58,15 +87,37 @@ TEST(AnyTest, TestPackAndUnpackAny) { protobuf_unittest::TestAny message; message.mutable_any_value()->PackFrom(any); - string data = message.SerializeAsString(); + std::string data = message.SerializeAsString(); ASSERT_TRUE(message.ParseFromString(data)); EXPECT_TRUE(message.has_any_value()); + any.Clear(); + submessage.Clear(); ASSERT_TRUE(message.any_value().UnpackTo(&any)); ASSERT_TRUE(any.UnpackTo(&submessage)); EXPECT_EQ(12345, submessage.int32_value()); } +TEST(AnyTest, TestPackWithCustomTypeUrl) { + protobuf_unittest::TestAny submessage; + submessage.set_int32_value(12345); + google::protobuf::Any any; + // Pack with a custom type URL prefix. + any.PackFrom(submessage, "type.myservice.com"); + EXPECT_EQ("type.myservice.com/protobuf_unittest.TestAny", any.type_url()); + // Pack with a custom type URL prefix ending with '/'. + any.PackFrom(submessage, "type.myservice.com/"); + EXPECT_EQ("type.myservice.com/protobuf_unittest.TestAny", any.type_url()); + // Pack with an empty type URL prefix. + any.PackFrom(submessage, ""); + EXPECT_EQ("/protobuf_unittest.TestAny", any.type_url()); + + // Test unpacking the type. + submessage.Clear(); + EXPECT_TRUE(any.UnpackTo(&submessage)); + EXPECT_EQ(12345, submessage.int32_value()); +} + TEST(AnyTest, TestIs) { protobuf_unittest::TestAny submessage; submessage.set_int32_value(12345); @@ -81,9 +132,53 @@ TEST(AnyTest, TestIs) { ASSERT_TRUE(message.ParseFromString(message.SerializeAsString())); EXPECT_FALSE(message.any_value().Is()); EXPECT_TRUE(message.any_value().Is()); + + any.set_type_url("/protobuf_unittest.TestAny"); + EXPECT_TRUE(any.Is()); + // The type URL must contain at least one "/". + any.set_type_url("protobuf_unittest.TestAny"); + EXPECT_FALSE(any.Is()); + // The type name after the slash must be fully qualified. + any.set_type_url("/TestAny"); + EXPECT_FALSE(any.Is()); +} + +TEST(AnyTest, MoveConstructor) { + protobuf_unittest::TestAny payload; + payload.set_int32_value(12345); + + google::protobuf::Any src; + src.PackFrom(payload); + + const char* type_url = src.type_url().data(); + + google::protobuf::Any dst(std::move(src)); + EXPECT_EQ(type_url, dst.type_url().data()); + payload.Clear(); + ASSERT_TRUE(dst.UnpackTo(&payload)); + EXPECT_EQ(12345, payload.int32_value()); } +TEST(AnyTest, MoveAssignment) { + protobuf_unittest::TestAny payload; + payload.set_int32_value(12345); + + google::protobuf::Any src; + src.PackFrom(payload); + + const char* type_url = src.type_url().data(); + + google::protobuf::Any dst; + dst = std::move(src); + EXPECT_EQ(type_url, dst.type_url().data()); + payload.Clear(); + ASSERT_TRUE(dst.UnpackTo(&payload)); + EXPECT_EQ(12345, payload.int32_value()); +} + + } // namespace } // namespace protobuf - } // namespace google + +#include diff --git a/src/google/protobuf/any_test.proto b/src/google/protobuf/any_test.proto index 0c5b30ba3e4a8..256035b4467de 100644 --- a/src/google/protobuf/any_test.proto +++ b/src/google/protobuf/any_test.proto @@ -34,8 +34,11 @@ package protobuf_unittest; import "google/protobuf/any.proto"; +option java_outer_classname = "TestAnyProto"; + message TestAny { int32 int32_value = 1; google.protobuf.Any any_value = 2; repeated google.protobuf.Any repeated_any_value = 3; + string text = 4; } diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index 96a5074dcfd4f..c26b2130ec34b 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -1,566 +1,436 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/api.proto -#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include #include -#include -#include -#include #include -#include +#include +#include #include #include #include #include // @@protoc_insertion_point(includes) - -namespace google { -namespace protobuf { -class ApiDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _Api_default_instance_; -class MethodDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _Method_default_instance_; -class MixinDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _Mixin_default_instance_; - -namespace protobuf_google_2fprotobuf_2fapi_2eproto { - - -namespace { - -::google::protobuf::Metadata file_level_metadata[3]; - -} // namespace - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField - const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0}, +#include + +PROTOBUF_PRAGMA_INIT_SEG +PROTOBUF_NAMESPACE_OPEN +constexpr Api::Api( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : methods_() + , options_() + , mixins_() + , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , version_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , source_context_(nullptr) + , syntax_(0) +{} +struct ApiDefaultTypeInternal { + constexpr ApiDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~ApiDefaultTypeInternal() {} + union { + Api _instance; + }; }; - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField - const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - ::google::protobuf::internal::AuxillaryParseTableField(), +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT ApiDefaultTypeInternal _Api_default_instance_; +constexpr Method::Method( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : options_() + , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , request_type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , response_type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , request_streaming_(false) + , response_streaming_(false) + , syntax_(0) +{} +struct MethodDefaultTypeInternal { + constexpr MethodDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~MethodDefaultTypeInternal() {} + union { + Method _instance; + }; }; -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const - TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT MethodDefaultTypeInternal _Method_default_instance_; +constexpr Mixin::Mixin( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , root_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){} +struct MixinDefaultTypeInternal { + constexpr MixinDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~MixinDefaultTypeInternal() {} + union { + Mixin _instance; + }; }; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT MixinDefaultTypeInternal _Mixin_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fapi_2eproto[3]; +static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr; -const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { +const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fapi_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { ~0u, // no _has_bits_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Api, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, methods_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, options_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, version_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, source_context_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, mixins_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, syntax_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Api, name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Api, methods_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Api, options_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Api, version_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Api, source_context_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Api, mixins_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Api, syntax_), ~0u, // no _has_bits_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Method, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, request_type_url_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, request_streaming_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, response_type_url_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, response_streaming_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, options_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Method, syntax_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Method, name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Method, request_type_url_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Method, request_streaming_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Method, response_type_url_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Method, response_streaming_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Method, options_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Method, syntax_), ~0u, // no _has_bits_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Mixin, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Mixin, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Mixin, name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Mixin, root_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Mixin, name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Mixin, root_), }; -static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { 0, -1, sizeof(Api)}, - { 12, -1, sizeof(Method)}, - { 24, -1, sizeof(Mixin)}, +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, sizeof(PROTOBUF_NAMESPACE_ID::Api)}, + { 12, -1, sizeof(PROTOBUF_NAMESPACE_ID::Method)}, + { 24, -1, sizeof(PROTOBUF_NAMESPACE_ID::Mixin)}, }; -static ::google::protobuf::Message const * const file_default_instances[] = { - reinterpret_cast(&_Api_default_instance_), - reinterpret_cast(&_Method_default_instance_), - reinterpret_cast(&_Mixin_default_instance_), +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_Api_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_Method_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_Mixin_default_instance_), }; -namespace { - -void protobuf_AssignDescriptors() { - AddDescriptors(); - ::google::protobuf::MessageFactory* factory = NULL; - AssignDescriptors( - "google/protobuf/api.proto", schemas, file_default_instances, TableStruct::offsets, factory, - file_level_metadata, NULL, NULL); -} - -void protobuf_AssignDescriptorsOnce() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors); -} - -void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; -void protobuf_RegisterTypes(const ::std::string&) { - protobuf_AssignDescriptorsOnce(); - ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 3); -} - -} // namespace -void TableStruct::InitDefaultsImpl() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - ::google::protobuf::internal::InitProtobufDefaults(); - ::google::protobuf::protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::InitDefaults(); - ::google::protobuf::protobuf_google_2fprotobuf_2ftype_2eproto::InitDefaults(); - _Api_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_Api_default_instance_);_Method_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_Method_default_instance_);_Mixin_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_Mixin_default_instance_);_Api_default_instance_._instance.get_mutable()->source_context_ = const_cast< ::google::protobuf::SourceContext*>( - ::google::protobuf::SourceContext::internal_default_instance()); -} - -void InitDefaults() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl); -} -namespace { -void AddDescriptorsImpl() { - InitDefaults(); - static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - "\n\031google/protobuf/api.proto\022\017google.prot" - "obuf\032$google/protobuf/source_context.pro" - "to\032\032google/protobuf/type.proto\"\201\002\n\003Api\022\014" - "\n\004name\030\001 \001(\t\022(\n\007methods\030\002 \003(\0132\027.google.p" - "rotobuf.Method\022(\n\007options\030\003 \003(\0132\027.google" - ".protobuf.Option\022\017\n\007version\030\004 \001(\t\0226\n\016sou" - "rce_context\030\005 \001(\0132\036.google.protobuf.Sour" - "ceContext\022&\n\006mixins\030\006 \003(\0132\026.google.proto" - "buf.Mixin\022\'\n\006syntax\030\007 \001(\0162\027.google.proto" - "buf.Syntax\"\325\001\n\006Method\022\014\n\004name\030\001 \001(\t\022\030\n\020r" - "equest_type_url\030\002 \001(\t\022\031\n\021request_streami" - "ng\030\003 \001(\010\022\031\n\021response_type_url\030\004 \001(\t\022\032\n\022r" - "esponse_streaming\030\005 \001(\010\022(\n\007options\030\006 \003(\013" - "2\027.google.protobuf.Option\022\'\n\006syntax\030\007 \001(" - "\0162\027.google.protobuf.Syntax\"#\n\005Mixin\022\014\n\004n" - "ame\030\001 \001(\t\022\014\n\004root\030\002 \001(\tBu\n\023com.google.pr" - "otobufB\010ApiProtoP\001Z+google.golang.org/ge" - "nproto/protobuf/api;api\242\002\003GPB\252\002\036Google.P" - "rotobuf.WellKnownTypesb\006proto3" - }; - ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( - descriptor, 750); - ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( - "google/protobuf/api.proto", &protobuf_RegisterTypes); - ::google::protobuf::protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::AddDescriptors(); - ::google::protobuf::protobuf_google_2fprotobuf_2ftype_2eproto::AddDescriptors(); -} -} // anonymous namespace - -void AddDescriptors() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl); -} -// Force AddDescriptors() to be called at dynamic initialization time. -struct StaticDescriptorInitializer { - StaticDescriptorInitializer() { - AddDescriptors(); - } -} static_descriptor_initializer; - -} // namespace protobuf_google_2fprotobuf_2fapi_2eproto +const char descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\031google/protobuf/api.proto\022\017google.prot" + "obuf\032$google/protobuf/source_context.pro" + "to\032\032google/protobuf/type.proto\"\201\002\n\003Api\022\014" + "\n\004name\030\001 \001(\t\022(\n\007methods\030\002 \003(\0132\027.google.p" + "rotobuf.Method\022(\n\007options\030\003 \003(\0132\027.google" + ".protobuf.Option\022\017\n\007version\030\004 \001(\t\0226\n\016sou" + "rce_context\030\005 \001(\0132\036.google.protobuf.Sour" + "ceContext\022&\n\006mixins\030\006 \003(\0132\026.google.proto" + "buf.Mixin\022\'\n\006syntax\030\007 \001(\0162\027.google.proto" + "buf.Syntax\"\325\001\n\006Method\022\014\n\004name\030\001 \001(\t\022\030\n\020r" + "equest_type_url\030\002 \001(\t\022\031\n\021request_streami" + "ng\030\003 \001(\010\022\031\n\021response_type_url\030\004 \001(\t\022\032\n\022r" + "esponse_streaming\030\005 \001(\010\022(\n\007options\030\006 \003(\013" + "2\027.google.protobuf.Option\022\'\n\006syntax\030\007 \001(" + "\0162\027.google.protobuf.Syntax\"#\n\005Mixin\022\014\n\004n" + "ame\030\001 \001(\t\022\014\n\004root\030\002 \001(\tBv\n\023com.google.pr" + "otobufB\010ApiProtoP\001Z,google.golang.org/pr" + "otobuf/types/known/apipb\242\002\003GPB\252\002\036Google." + "Protobuf.WellKnownTypesb\006proto3" + ; +static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fapi_2eproto_deps[2] = { + &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto, + &::descriptor_table_google_2fprotobuf_2ftype_2eproto, +}; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fapi_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto = { + false, false, 751, descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto, "google/protobuf/api.proto", + &descriptor_table_google_2fprotobuf_2fapi_2eproto_once, descriptor_table_google_2fprotobuf_2fapi_2eproto_deps, 2, 3, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fapi_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fapi_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto, file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata +descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(int index) { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fapi_2eproto); + return descriptor_table_google_2fprotobuf_2fapi_2eproto.file_level_metadata[index]; +} +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fapi_2eproto(&descriptor_table_google_2fprotobuf_2fapi_2eproto); +PROTOBUF_NAMESPACE_OPEN // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int Api::kNameFieldNumber; -const int Api::kMethodsFieldNumber; -const int Api::kOptionsFieldNumber; -const int Api::kVersionFieldNumber; -const int Api::kSourceContextFieldNumber; -const int Api::kMixinsFieldNumber; -const int Api::kSyntaxFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -Api::Api() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaults(); +class Api::_Internal { + public: + static const PROTOBUF_NAMESPACE_ID::SourceContext& source_context(const Api* msg); +}; + +const PROTOBUF_NAMESPACE_ID::SourceContext& +Api::_Internal::source_context(const Api* msg) { + return *msg->source_context_; +} +void Api::clear_options() { + options_.Clear(); +} +void Api::clear_source_context() { + if (GetArena() == nullptr && source_context_ != nullptr) { + delete source_context_; } + source_context_ = nullptr; +} +Api::Api(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + methods_(arena), + options_(arena), + mixins_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.Api) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Api) } Api::Api(const Api& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), methods_(from.methods_), options_(from.options_), - mixins_(from.mixins_), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.name().size() > 0) { - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); - } - version_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.version().size() > 0) { - version_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.version_); - } - if (from.has_source_context()) { - source_context_ = new ::google::protobuf::SourceContext(*from.source_context_); + mixins_(from.mixins_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_name().empty()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArena()); + } + version_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_version().empty()) { + version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_version(), + GetArena()); + } + if (from._internal_has_source_context()) { + source_context_ = new PROTOBUF_NAMESPACE_ID::SourceContext(*from.source_context_); } else { - source_context_ = NULL; + source_context_ = nullptr; } syntax_ = from.syntax_; // @@protoc_insertion_point(copy_constructor:google.protobuf.Api) } void Api::SharedCtor() { - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - version_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - ::memset(&source_context_, 0, static_cast( - reinterpret_cast(&syntax_) - - reinterpret_cast(&source_context_)) + sizeof(syntax_)); - _cached_size_ = 0; +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +version_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&source_context_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&syntax_) - + reinterpret_cast(&source_context_)) + sizeof(syntax_)); } Api::~Api() { // @@protoc_insertion_point(destructor:google.protobuf.Api) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void Api::SharedDtor() { - name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - version_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + version_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (this != internal_default_instance()) delete source_context_; } -void Api::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void Api::ArenaDtor(void* object) { + Api* _this = reinterpret_cast< Api* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* Api::descriptor() { - protobuf_google_2fprotobuf_2fapi_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fapi_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const Api& Api::default_instance() { - protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaults(); - return *internal_default_instance(); +void Api::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -Api* Api::New(::google::protobuf::Arena* arena) const { - Api* n = new Api; - if (arena != NULL) { - arena->Own(n); - } - return n; +void Api::SetCachedSize(int size) const { + _cached_size_.Set(size); } void Api::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Api) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; methods_.Clear(); options_.Clear(); mixins_.Clear(); - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (GetArenaNoVirtual() == NULL && source_context_ != NULL) { + name_.ClearToEmpty(); + version_.ClearToEmpty(); + if (GetArena() == nullptr && source_context_ != nullptr) { delete source_context_; } - source_context_ = NULL; + source_context_ = nullptr; syntax_ = 0; - _internal_metadata_.Clear(); -} - -bool Api::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.Api) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // string name = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_name())); - DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormatLite::PARSE, - "google.protobuf.Api.name")); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* Api::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.Api.name")); + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated .google.protobuf.Method methods = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_methods())); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_methods(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr)); + } else goto handle_unusual; + continue; // repeated .google.protobuf.Option options = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_options())); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_options(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr)); + } else goto handle_unusual; + continue; // string version = 4; - case 4: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_version())); - DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->version().data(), static_cast(this->version().length()), - ::google::protobuf::internal::WireFormatLite::PARSE, - "google.protobuf.Api.version")); - } else { - goto handle_unusual; - } - break; - } - + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + auto str = _internal_mutable_version(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.Api.version")); + CHK_(ptr); + } else goto handle_unusual; + continue; // .google.protobuf.SourceContext source_context = 5; - case 5: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(42u /* 42 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, mutable_source_context())); - } else { - goto handle_unusual; - } - break; - } - + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 42)) { + ptr = ctx->ParseMessage(_internal_mutable_source_context(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated .google.protobuf.Mixin mixins = 6; - case 6: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_mixins())); - } else { - goto handle_unusual; - } - break; - } - + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 50)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_mixins(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr)); + } else goto handle_unusual; + continue; // .google.protobuf.Syntax syntax = 7; - case 7: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(56u /* 56 & 0xFF */)) { - int value; - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( - input, &value))); - set_syntax(static_cast< ::google::protobuf::Syntax >(value)); - } else { - goto handle_unusual; - } - break; - } - + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 56)) { + ::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + _internal_set_syntax(static_cast(val)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.Api) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.Api) - return false; -#undef DO_ + ptr = nullptr; + goto success; +#undef CHK_ } -void Api::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.Api) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // string name = 1; - if (this->name().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, - "google.protobuf.Api.name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->name(), output); - } - - // repeated .google.protobuf.Method methods = 2; - for (unsigned int i = 0, - n = static_cast(this->methods_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 2, this->methods(static_cast(i)), output); - } - - // repeated .google.protobuf.Option options = 3; - for (unsigned int i = 0, - n = static_cast(this->options_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 3, this->options(static_cast(i)), output); - } - - // string version = 4; - if (this->version().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->version().data(), static_cast(this->version().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, - "google.protobuf.Api.version"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 4, this->version(), output); - } - - // .google.protobuf.SourceContext source_context = 5; - if (this->has_source_context()) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 5, *this->source_context_, output); - } - - // repeated .google.protobuf.Mixin mixins = 6; - for (unsigned int i = 0, - n = static_cast(this->mixins_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 6, this->mixins(static_cast(i)), output); - } - - // .google.protobuf.Syntax syntax = 7; - if (this->syntax() != 0) { - ::google::protobuf::internal::WireFormatLite::WriteEnum( - 7, this->syntax(), output); - } - - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.Api) -} - -::google::protobuf::uint8* Api::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* Api::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Api) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // string name = 1; if (this->name().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "google.protobuf.Api.name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->name(), target); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); } // repeated .google.protobuf.Method methods = 2; for (unsigned int i = 0, - n = static_cast(this->methods_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 2, this->methods(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_methods_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(2, this->_internal_methods(i), target, stream); } // repeated .google.protobuf.Option options = 3; for (unsigned int i = 0, - n = static_cast(this->options_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 3, this->options(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_options_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(3, this->_internal_options(i), target, stream); } // string version = 4; if (this->version().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->version().data(), static_cast(this->version().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_version().data(), static_cast(this->_internal_version().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "google.protobuf.Api.version"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 4, this->version(), target); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_version(), target); } // .google.protobuf.SourceContext source_context = 5; if (this->has_source_context()) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 5, *this->source_context_, deterministic, target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 5, _Internal::source_context(this), target, stream); } // repeated .google.protobuf.Mixin mixins = 6; for (unsigned int i = 0, - n = static_cast(this->mixins_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 6, this->mixins(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_mixins_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(6, this->_internal_mixins(i), target, stream); } // .google.protobuf.Syntax syntax = 7; if (this->syntax() != 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( - 7, this->syntax(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray( + 7, this->_internal_syntax(), target); } - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Api) return target; @@ -570,87 +440,76 @@ size_t Api::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Api) size_t total_size = 0; - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.Method methods = 2; - { - unsigned int count = static_cast(this->methods_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->methods(static_cast(i))); - } + total_size += 1UL * this->_internal_methods_size(); + for (const auto& msg : this->methods_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // repeated .google.protobuf.Option options = 3; - { - unsigned int count = static_cast(this->options_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->options(static_cast(i))); - } + total_size += 1UL * this->_internal_options_size(); + for (const auto& msg : this->options_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // repeated .google.protobuf.Mixin mixins = 6; - { - unsigned int count = static_cast(this->mixins_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->mixins(static_cast(i))); - } + total_size += 1UL * this->_internal_mixins_size(); + for (const auto& msg : this->mixins_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // string name = 1; if (this->name().size() > 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->name()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); } // string version = 4; if (this->version().size() > 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->version()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_version()); } // .google.protobuf.SourceContext source_context = 5; if (this->has_source_context()) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - *this->source_context_); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *source_context_); } // .google.protobuf.Syntax syntax = 7; if (this->syntax() != 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::EnumSize(this->syntax()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_syntax()); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void Api::MergeFrom(const ::google::protobuf::Message& from) { +void Api::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Api) GOOGLE_DCHECK_NE(&from, this); const Api* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Api) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Api) MergeFrom(*source); @@ -660,30 +519,28 @@ void Api::MergeFrom(const ::google::protobuf::Message& from) { void Api::MergeFrom(const Api& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Api) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; methods_.MergeFrom(from.methods_); options_.MergeFrom(from.options_); mixins_.MergeFrom(from.mixins_); if (from.name().size() > 0) { - - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); + _internal_set_name(from._internal_name()); } if (from.version().size() > 0) { - - version_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.version_); + _internal_set_version(from._internal_version()); } if (from.has_source_context()) { - mutable_source_context()->::google::protobuf::SourceContext::MergeFrom(from.source_context()); + _internal_mutable_source_context()->PROTOBUF_NAMESPACE_ID::SourceContext::MergeFrom(from._internal_source_context()); } if (from.syntax() != 0) { - set_syntax(from.syntax()); + _internal_set_syntax(from._internal_syntax()); } } -void Api::CopyFrom(const ::google::protobuf::Message& from) { +void Api::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Api) if (&from == this) return; Clear(); @@ -701,320 +558,61 @@ bool Api::IsInitialized() const { return true; } -void Api::Swap(Api* other) { - if (other == this) return; - InternalSwap(other); -} void Api::InternalSwap(Api* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); methods_.InternalSwap(&other->methods_); options_.InternalSwap(&other->options_); mixins_.InternalSwap(&other->mixins_); - name_.Swap(&other->name_); - version_.Swap(&other->version_); - swap(source_context_, other->source_context_); - swap(syntax_, other->syntax_); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata Api::GetMetadata() const { - protobuf_google_2fprotobuf_2fapi_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fapi_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// Api - -// string name = 1; -void Api::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -const ::std::string& Api::name() const { - // @@protoc_insertion_point(field_get:google.protobuf.Api.name) - return name_.GetNoArena(); -} -void Api::set_name(const ::std::string& value) { - - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.Api.name) -} -#if LANG_CXX11 -void Api::set_name(::std::string&& value) { - - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Api.name) -} -#endif -void Api::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.Api.name) -} -void Api::set_name(const char* value, size_t size) { - - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.name) -} -::std::string* Api::mutable_name() { - - // @@protoc_insertion_point(field_mutable:google.protobuf.Api.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* Api::release_name() { - // @@protoc_insertion_point(field_release:google.protobuf.Api.name) - - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void Api::set_allocated_name(::std::string* name) { - if (name != NULL) { - - } else { - - } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.name) + name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + version_.Swap(&other->version_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(Api, syntax_) + + sizeof(Api::syntax_) + - PROTOBUF_FIELD_OFFSET(Api, source_context_)>( + reinterpret_cast(&source_context_), + reinterpret_cast(&other->source_context_)); } -// repeated .google.protobuf.Method methods = 2; -int Api::methods_size() const { - return methods_.size(); -} -void Api::clear_methods() { - methods_.Clear(); -} -const ::google::protobuf::Method& Api::methods(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.Api.methods) - return methods_.Get(index); -} -::google::protobuf::Method* Api::mutable_methods(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.Api.methods) - return methods_.Mutable(index); -} -::google::protobuf::Method* Api::add_methods() { - // @@protoc_insertion_point(field_add:google.protobuf.Api.methods) - return methods_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >* -Api::mutable_methods() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.methods) - return &methods_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >& -Api::methods() const { - // @@protoc_insertion_point(field_list:google.protobuf.Api.methods) - return methods_; +::PROTOBUF_NAMESPACE_ID::Metadata Api::GetMetadata() const { + return GetMetadataStatic(); } -// repeated .google.protobuf.Option options = 3; -int Api::options_size() const { - return options_.size(); -} -void Api::clear_options() { - options_.Clear(); -} -const ::google::protobuf::Option& Api::options(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.Api.options) - return options_.Get(index); -} -::google::protobuf::Option* Api::mutable_options(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.Api.options) - return options_.Mutable(index); -} -::google::protobuf::Option* Api::add_options() { - // @@protoc_insertion_point(field_add:google.protobuf.Api.options) - return options_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >* -Api::mutable_options() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.options) - return &options_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >& -Api::options() const { - // @@protoc_insertion_point(field_list:google.protobuf.Api.options) - return options_; -} - -// string version = 4; -void Api::clear_version() { - version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -const ::std::string& Api::version() const { - // @@protoc_insertion_point(field_get:google.protobuf.Api.version) - return version_.GetNoArena(); -} -void Api::set_version(const ::std::string& value) { - - version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.Api.version) -} -#if LANG_CXX11 -void Api::set_version(::std::string&& value) { - - version_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Api.version) -} -#endif -void Api::set_version(const char* value) { - GOOGLE_DCHECK(value != NULL); - - version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.Api.version) -} -void Api::set_version(const char* value, size_t size) { - - version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.version) -} -::std::string* Api::mutable_version() { - - // @@protoc_insertion_point(field_mutable:google.protobuf.Api.version) - return version_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* Api::release_version() { - // @@protoc_insertion_point(field_release:google.protobuf.Api.version) - - return version_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void Api::set_allocated_version(::std::string* version) { - if (version != NULL) { - - } else { - - } - version_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), version); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.version) -} -// .google.protobuf.SourceContext source_context = 5; -bool Api::has_source_context() const { - return this != internal_default_instance() && source_context_ != NULL; -} -void Api::clear_source_context() { - if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_; - source_context_ = NULL; -} -const ::google::protobuf::SourceContext& Api::source_context() const { - const ::google::protobuf::SourceContext* p = source_context_; - // @@protoc_insertion_point(field_get:google.protobuf.Api.source_context) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_SourceContext_default_instance_); -} -::google::protobuf::SourceContext* Api::mutable_source_context() { - - if (source_context_ == NULL) { - source_context_ = new ::google::protobuf::SourceContext; - } - // @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context) - return source_context_; -} -::google::protobuf::SourceContext* Api::release_source_context() { - // @@protoc_insertion_point(field_release:google.protobuf.Api.source_context) - - ::google::protobuf::SourceContext* temp = source_context_; - source_context_ = NULL; - return temp; -} -void Api::set_allocated_source_context(::google::protobuf::SourceContext* source_context) { - delete source_context_; - source_context_ = source_context; - if (source_context) { - - } else { - - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.source_context) -} +// =================================================================== -// repeated .google.protobuf.Mixin mixins = 6; -int Api::mixins_size() const { - return mixins_.size(); -} -void Api::clear_mixins() { - mixins_.Clear(); -} -const ::google::protobuf::Mixin& Api::mixins(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.Api.mixins) - return mixins_.Get(index); -} -::google::protobuf::Mixin* Api::mutable_mixins(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.Api.mixins) - return mixins_.Mutable(index); -} -::google::protobuf::Mixin* Api::add_mixins() { - // @@protoc_insertion_point(field_add:google.protobuf.Api.mixins) - return mixins_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >* -Api::mutable_mixins() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.mixins) - return &mixins_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >& -Api::mixins() const { - // @@protoc_insertion_point(field_list:google.protobuf.Api.mixins) - return mixins_; -} +class Method::_Internal { + public: +}; -// .google.protobuf.Syntax syntax = 7; -void Api::clear_syntax() { - syntax_ = 0; -} -::google::protobuf::Syntax Api::syntax() const { - // @@protoc_insertion_point(field_get:google.protobuf.Api.syntax) - return static_cast< ::google::protobuf::Syntax >(syntax_); -} -void Api::set_syntax(::google::protobuf::Syntax value) { - - syntax_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.Api.syntax) +void Method::clear_options() { + options_.Clear(); } - -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS - -// =================================================================== - -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int Method::kNameFieldNumber; -const int Method::kRequestTypeUrlFieldNumber; -const int Method::kRequestStreamingFieldNumber; -const int Method::kResponseTypeUrlFieldNumber; -const int Method::kResponseStreamingFieldNumber; -const int Method::kOptionsFieldNumber; -const int Method::kSyntaxFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -Method::Method() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaults(); - } +Method::Method(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + options_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.Method) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Method) } Method::Method(const Method& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - options_(from.options_), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.name().size() > 0) { - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); - } - request_type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.request_type_url().size() > 0) { - request_type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.request_type_url_); - } - response_type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.response_type_url().size() > 0) { - response_type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.response_type_url_); + : ::PROTOBUF_NAMESPACE_ID::Message(), + options_(from.options_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_name().empty()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArena()); + } + request_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_request_type_url().empty()) { + request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_request_type_url(), + GetArena()); + } + response_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_response_type_url().empty()) { + response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_response_type_url(), + GetArena()); } ::memcpy(&request_streaming_, &from.request_streaming_, static_cast(reinterpret_cast(&syntax_) - @@ -1023,331 +621,210 @@ Method::Method(const Method& from) } void Method::SharedCtor() { - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - request_type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - response_type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - ::memset(&request_streaming_, 0, static_cast( - reinterpret_cast(&syntax_) - - reinterpret_cast(&request_streaming_)) + sizeof(syntax_)); - _cached_size_ = 0; +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +request_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +response_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&request_streaming_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&syntax_) - + reinterpret_cast(&request_streaming_)) + sizeof(syntax_)); } Method::~Method() { // @@protoc_insertion_point(destructor:google.protobuf.Method) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void Method::SharedDtor() { - name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - request_type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - response_type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + request_type_url_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + response_type_url_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } -void Method::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* Method::descriptor() { - protobuf_google_2fprotobuf_2fapi_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fapi_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void Method::ArenaDtor(void* object) { + Method* _this = reinterpret_cast< Method* >(object); + (void)_this; } - -const Method& Method::default_instance() { - protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaults(); - return *internal_default_instance(); +void Method::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -Method* Method::New(::google::protobuf::Arena* arena) const { - Method* n = new Method; - if (arena != NULL) { - arena->Own(n); - } - return n; +void Method::SetCachedSize(int size) const { + _cached_size_.Set(size); } void Method::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Method) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; options_.Clear(); - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - request_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - response_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + name_.ClearToEmpty(); + request_type_url_.ClearToEmpty(); + response_type_url_.ClearToEmpty(); ::memset(&request_streaming_, 0, static_cast( reinterpret_cast(&syntax_) - reinterpret_cast(&request_streaming_)) + sizeof(syntax_)); - _internal_metadata_.Clear(); -} - -bool Method::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.Method) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // string name = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_name())); - DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormatLite::PARSE, - "google.protobuf.Method.name")); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* Method::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.Method.name")); + CHK_(ptr); + } else goto handle_unusual; + continue; // string request_type_url = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_request_type_url())); - DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->request_type_url().data(), static_cast(this->request_type_url().length()), - ::google::protobuf::internal::WireFormatLite::PARSE, - "google.protobuf.Method.request_type_url")); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + auto str = _internal_mutable_request_type_url(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.Method.request_type_url")); + CHK_(ptr); + } else goto handle_unusual; + continue; // bool request_streaming = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) { - - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &request_streaming_))); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + request_streaming_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // string response_type_url = 4; - case 4: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_response_type_url())); - DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->response_type_url().data(), static_cast(this->response_type_url().length()), - ::google::protobuf::internal::WireFormatLite::PARSE, - "google.protobuf.Method.response_type_url")); - } else { - goto handle_unusual; - } - break; - } - + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + auto str = _internal_mutable_response_type_url(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.Method.response_type_url")); + CHK_(ptr); + } else goto handle_unusual; + continue; // bool response_streaming = 5; - case 5: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(40u /* 40 & 0xFF */)) { - - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &response_streaming_))); - } else { - goto handle_unusual; - } - break; - } - + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 40)) { + response_streaming_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated .google.protobuf.Option options = 6; - case 6: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_options())); - } else { - goto handle_unusual; - } - break; - } - + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 50)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_options(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr)); + } else goto handle_unusual; + continue; // .google.protobuf.Syntax syntax = 7; - case 7: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(56u /* 56 & 0xFF */)) { - int value; - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( - input, &value))); - set_syntax(static_cast< ::google::protobuf::Syntax >(value)); - } else { - goto handle_unusual; - } - break; - } - + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 56)) { + ::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + _internal_set_syntax(static_cast(val)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.Method) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.Method) - return false; -#undef DO_ -} - -void Method::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.Method) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // string name = 1; - if (this->name().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, - "google.protobuf.Method.name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->name(), output); - } - - // string request_type_url = 2; - if (this->request_type_url().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->request_type_url().data(), static_cast(this->request_type_url().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, - "google.protobuf.Method.request_type_url"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 2, this->request_type_url(), output); - } - - // bool request_streaming = 3; - if (this->request_streaming() != 0) { - ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->request_streaming(), output); - } - - // string response_type_url = 4; - if (this->response_type_url().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->response_type_url().data(), static_cast(this->response_type_url().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, - "google.protobuf.Method.response_type_url"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 4, this->response_type_url(), output); - } - - // bool response_streaming = 5; - if (this->response_streaming() != 0) { - ::google::protobuf::internal::WireFormatLite::WriteBool(5, this->response_streaming(), output); - } - - // repeated .google.protobuf.Option options = 6; - for (unsigned int i = 0, - n = static_cast(this->options_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 6, this->options(static_cast(i)), output); - } - - // .google.protobuf.Syntax syntax = 7; - if (this->syntax() != 0) { - ::google::protobuf::internal::WireFormatLite::WriteEnum( - 7, this->syntax(), output); - } - - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.Method) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* Method::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* Method::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Method) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // string name = 1; if (this->name().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "google.protobuf.Method.name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->name(), target); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); } // string request_type_url = 2; if (this->request_type_url().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->request_type_url().data(), static_cast(this->request_type_url().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_request_type_url().data(), static_cast(this->_internal_request_type_url().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "google.protobuf.Method.request_type_url"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 2, this->request_type_url(), target); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_request_type_url(), target); } // bool request_streaming = 3; if (this->request_streaming() != 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->request_streaming(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(3, this->_internal_request_streaming(), target); } // string response_type_url = 4; if (this->response_type_url().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->response_type_url().data(), static_cast(this->response_type_url().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_response_type_url().data(), static_cast(this->_internal_response_type_url().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "google.protobuf.Method.response_type_url"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 4, this->response_type_url(), target); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_response_type_url(), target); } // bool response_streaming = 5; if (this->response_streaming() != 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->response_streaming(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(5, this->_internal_response_streaming(), target); } // repeated .google.protobuf.Option options = 6; for (unsigned int i = 0, - n = static_cast(this->options_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 6, this->options(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_options_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(6, this->_internal_options(i), target, stream); } // .google.protobuf.Syntax syntax = 7; if (this->syntax() != 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( - 7, this->syntax(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray( + 7, this->_internal_syntax(), target); } - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Method) return target; @@ -1357,41 +834,36 @@ size_t Method::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Method) size_t total_size = 0; - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.Option options = 6; - { - unsigned int count = static_cast(this->options_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->options(static_cast(i))); - } + total_size += 1UL * this->_internal_options_size(); + for (const auto& msg : this->options_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // string name = 1; if (this->name().size() > 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->name()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); } // string request_type_url = 2; if (this->request_type_url().size() > 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->request_type_url()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_request_type_url()); } // string response_type_url = 4; if (this->response_type_url().size() > 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->response_type_url()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_response_type_url()); } // bool request_streaming = 3; @@ -1407,25 +879,27 @@ size_t Method::ByteSizeLong() const { // .google.protobuf.Syntax syntax = 7; if (this->syntax() != 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::EnumSize(this->syntax()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_syntax()); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void Method::MergeFrom(const ::google::protobuf::Message& from) { +void Method::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Method) GOOGLE_DCHECK_NE(&from, this); const Method* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Method) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Method) MergeFrom(*source); @@ -1435,35 +909,32 @@ void Method::MergeFrom(const ::google::protobuf::Message& from) { void Method::MergeFrom(const Method& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Method) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; options_.MergeFrom(from.options_); if (from.name().size() > 0) { - - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); + _internal_set_name(from._internal_name()); } if (from.request_type_url().size() > 0) { - - request_type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.request_type_url_); + _internal_set_request_type_url(from._internal_request_type_url()); } if (from.response_type_url().size() > 0) { - - response_type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.response_type_url_); + _internal_set_response_type_url(from._internal_response_type_url()); } if (from.request_streaming() != 0) { - set_request_streaming(from.request_streaming()); + _internal_set_request_streaming(from._internal_request_streaming()); } if (from.response_streaming() != 0) { - set_response_streaming(from.response_streaming()); + _internal_set_response_streaming(from._internal_response_streaming()); } if (from.syntax() != 0) { - set_syntax(from.syntax()); + _internal_set_syntax(from._internal_syntax()); } } -void Method::CopyFrom(const ::google::protobuf::Message& from) { +void Method::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Method) if (&from == this) return; Clear(); @@ -1481,472 +952,168 @@ bool Method::IsInitialized() const { return true; } -void Method::Swap(Method* other) { - if (other == this) return; - InternalSwap(other); -} void Method::InternalSwap(Method* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); options_.InternalSwap(&other->options_); - name_.Swap(&other->name_); - request_type_url_.Swap(&other->request_type_url_); - response_type_url_.Swap(&other->response_type_url_); - swap(request_streaming_, other->request_streaming_); - swap(response_streaming_, other->response_streaming_); - swap(syntax_, other->syntax_); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata Method::GetMetadata() const { - protobuf_google_2fprotobuf_2fapi_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fapi_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// Method - -// string name = 1; -void Method::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -const ::std::string& Method::name() const { - // @@protoc_insertion_point(field_get:google.protobuf.Method.name) - return name_.GetNoArena(); -} -void Method::set_name(const ::std::string& value) { - - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.Method.name) -} -#if LANG_CXX11 -void Method::set_name(::std::string&& value) { - - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.name) -} -#endif -void Method::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.Method.name) -} -void Method::set_name(const char* value, size_t size) { - - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.name) -} -::std::string* Method::mutable_name() { - - // @@protoc_insertion_point(field_mutable:google.protobuf.Method.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* Method::release_name() { - // @@protoc_insertion_point(field_release:google.protobuf.Method.name) - - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void Method::set_allocated_name(::std::string* name) { - if (name != NULL) { - - } else { - - } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.name) -} - -// string request_type_url = 2; -void Method::clear_request_type_url() { - request_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -const ::std::string& Method::request_type_url() const { - // @@protoc_insertion_point(field_get:google.protobuf.Method.request_type_url) - return request_type_url_.GetNoArena(); -} -void Method::set_request_type_url(const ::std::string& value) { - - request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.Method.request_type_url) -} -#if LANG_CXX11 -void Method::set_request_type_url(::std::string&& value) { - - request_type_url_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.request_type_url) -} -#endif -void Method::set_request_type_url(const char* value) { - GOOGLE_DCHECK(value != NULL); - - request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.Method.request_type_url) -} -void Method::set_request_type_url(const char* value, size_t size) { - - request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.request_type_url) -} -::std::string* Method::mutable_request_type_url() { - - // @@protoc_insertion_point(field_mutable:google.protobuf.Method.request_type_url) - return request_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* Method::release_request_type_url() { - // @@protoc_insertion_point(field_release:google.protobuf.Method.request_type_url) - - return request_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void Method::set_allocated_request_type_url(::std::string* request_type_url) { - if (request_type_url != NULL) { - - } else { - - } - request_type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), request_type_url); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.request_type_url) -} - -// bool request_streaming = 3; -void Method::clear_request_streaming() { - request_streaming_ = false; -} -bool Method::request_streaming() const { - // @@protoc_insertion_point(field_get:google.protobuf.Method.request_streaming) - return request_streaming_; -} -void Method::set_request_streaming(bool value) { - - request_streaming_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.Method.request_streaming) -} - -// string response_type_url = 4; -void Method::clear_response_type_url() { - response_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -const ::std::string& Method::response_type_url() const { - // @@protoc_insertion_point(field_get:google.protobuf.Method.response_type_url) - return response_type_url_.GetNoArena(); -} -void Method::set_response_type_url(const ::std::string& value) { - - response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.Method.response_type_url) -} -#if LANG_CXX11 -void Method::set_response_type_url(::std::string&& value) { - - response_type_url_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.response_type_url) -} -#endif -void Method::set_response_type_url(const char* value) { - GOOGLE_DCHECK(value != NULL); - - response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.Method.response_type_url) -} -void Method::set_response_type_url(const char* value, size_t size) { - - response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.response_type_url) -} -::std::string* Method::mutable_response_type_url() { - - // @@protoc_insertion_point(field_mutable:google.protobuf.Method.response_type_url) - return response_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* Method::release_response_type_url() { - // @@protoc_insertion_point(field_release:google.protobuf.Method.response_type_url) - - return response_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void Method::set_allocated_response_type_url(::std::string* response_type_url) { - if (response_type_url != NULL) { - - } else { - - } - response_type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), response_type_url); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.response_type_url) -} - -// bool response_streaming = 5; -void Method::clear_response_streaming() { - response_streaming_ = false; -} -bool Method::response_streaming() const { - // @@protoc_insertion_point(field_get:google.protobuf.Method.response_streaming) - return response_streaming_; -} -void Method::set_response_streaming(bool value) { - - response_streaming_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.Method.response_streaming) -} - -// repeated .google.protobuf.Option options = 6; -int Method::options_size() const { - return options_.size(); -} -void Method::clear_options() { - options_.Clear(); -} -const ::google::protobuf::Option& Method::options(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.Method.options) - return options_.Get(index); -} -::google::protobuf::Option* Method::mutable_options(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.Method.options) - return options_.Mutable(index); -} -::google::protobuf::Option* Method::add_options() { - // @@protoc_insertion_point(field_add:google.protobuf.Method.options) - return options_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >* -Method::mutable_options() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.Method.options) - return &options_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >& -Method::options() const { - // @@protoc_insertion_point(field_list:google.protobuf.Method.options) - return options_; + name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + request_type_url_.Swap(&other->request_type_url_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + response_type_url_.Swap(&other->response_type_url_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(Method, syntax_) + + sizeof(Method::syntax_) + - PROTOBUF_FIELD_OFFSET(Method, request_streaming_)>( + reinterpret_cast(&request_streaming_), + reinterpret_cast(&other->request_streaming_)); } -// .google.protobuf.Syntax syntax = 7; -void Method::clear_syntax() { - syntax_ = 0; -} -::google::protobuf::Syntax Method::syntax() const { - // @@protoc_insertion_point(field_get:google.protobuf.Method.syntax) - return static_cast< ::google::protobuf::Syntax >(syntax_); -} -void Method::set_syntax(::google::protobuf::Syntax value) { - - syntax_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.Method.syntax) +::PROTOBUF_NAMESPACE_ID::Metadata Method::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int Mixin::kNameFieldNumber; -const int Mixin::kRootFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +class Mixin::_Internal { + public: +}; -Mixin::Mixin() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaults(); - } +Mixin::Mixin(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.Mixin) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Mixin) } Mixin::Mixin(const Mixin& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.name().size() > 0) { - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); - } - root_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.root().size() > 0) { - root_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.root_); + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_name().empty()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArena()); + } + root_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_root().empty()) { + root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_root(), + GetArena()); } // @@protoc_insertion_point(copy_constructor:google.protobuf.Mixin) } void Mixin::SharedCtor() { - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - root_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - _cached_size_ = 0; +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +root_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } Mixin::~Mixin() { // @@protoc_insertion_point(destructor:google.protobuf.Mixin) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void Mixin::SharedDtor() { - name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - root_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + root_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } -void Mixin::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void Mixin::ArenaDtor(void* object) { + Mixin* _this = reinterpret_cast< Mixin* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* Mixin::descriptor() { - protobuf_google_2fprotobuf_2fapi_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fapi_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void Mixin::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -const Mixin& Mixin::default_instance() { - protobuf_google_2fprotobuf_2fapi_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -Mixin* Mixin::New(::google::protobuf::Arena* arena) const { - Mixin* n = new Mixin; - if (arena != NULL) { - arena->Own(n); - } - return n; +void Mixin::SetCachedSize(int size) const { + _cached_size_.Set(size); } void Mixin::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Mixin) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - root_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - _internal_metadata_.Clear(); -} - -bool Mixin::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.Mixin) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // string name = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_name())); - DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormatLite::PARSE, - "google.protobuf.Mixin.name")); - } else { - goto handle_unusual; - } - break; - } + name_.ClearToEmpty(); + root_.ClearToEmpty(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* Mixin::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.Mixin.name")); + CHK_(ptr); + } else goto handle_unusual; + continue; // string root = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_root())); - DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->root().data(), static_cast(this->root().length()), - ::google::protobuf::internal::WireFormatLite::PARSE, - "google.protobuf.Mixin.root")); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + auto str = _internal_mutable_root(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.Mixin.root")); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.Mixin) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.Mixin) - return false; -#undef DO_ -} - -void Mixin::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.Mixin) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // string name = 1; - if (this->name().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, - "google.protobuf.Mixin.name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->name(), output); - } - - // string root = 2; - if (this->root().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->root().data(), static_cast(this->root().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, - "google.protobuf.Mixin.root"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 2, this->root(), output); - } - - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.Mixin) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* Mixin::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* Mixin::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Mixin) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // string name = 1; if (this->name().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "google.protobuf.Mixin.name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->name(), target); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); } // string root = 2; if (this->root().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->root().data(), static_cast(this->root().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_root().data(), static_cast(this->_internal_root().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "google.protobuf.Mixin.root"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 2, this->root(), target); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_root(), target); } - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Mixin) return target; @@ -1956,41 +1123,42 @@ size_t Mixin::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Mixin) size_t total_size = 0; - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // string name = 1; if (this->name().size() > 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->name()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); } // string root = 2; if (this->root().size() > 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->root()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_root()); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void Mixin::MergeFrom(const ::google::protobuf::Message& from) { +void Mixin::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Mixin) GOOGLE_DCHECK_NE(&from, this); const Mixin* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Mixin) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Mixin) MergeFrom(*source); @@ -2000,21 +1168,19 @@ void Mixin::MergeFrom(const ::google::protobuf::Message& from) { void Mixin::MergeFrom(const Mixin& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Mixin) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; if (from.name().size() > 0) { - - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); + _internal_set_name(from._internal_name()); } if (from.root().size() > 0) { - - root_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.root_); + _internal_set_root(from._internal_root()); } } -void Mixin::CopyFrom(const ::google::protobuf::Message& from) { +void Mixin::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Mixin) if (&from == this) return; Clear(); @@ -2032,137 +1198,31 @@ bool Mixin::IsInitialized() const { return true; } -void Mixin::Swap(Mixin* other) { - if (other == this) return; - InternalSwap(other); -} void Mixin::InternalSwap(Mixin* other) { using std::swap; - name_.Swap(&other->name_); - root_.Swap(&other->root_); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata Mixin::GetMetadata() const { - protobuf_google_2fprotobuf_2fapi_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fapi_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// Mixin - -// string name = 1; -void Mixin::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -const ::std::string& Mixin::name() const { - // @@protoc_insertion_point(field_get:google.protobuf.Mixin.name) - return name_.GetNoArena(); -} -void Mixin::set_name(const ::std::string& value) { - - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.Mixin.name) -} -#if LANG_CXX11 -void Mixin::set_name(::std::string&& value) { - - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Mixin.name) -} -#endif -void Mixin::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.name) -} -void Mixin::set_name(const char* value, size_t size) { - - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.name) -} -::std::string* Mixin::mutable_name() { - - // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* Mixin::release_name() { - // @@protoc_insertion_point(field_release:google.protobuf.Mixin.name) - - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void Mixin::set_allocated_name(::std::string* name) { - if (name != NULL) { - - } else { - - } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.name) -} - -// string root = 2; -void Mixin::clear_root() { - root_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -const ::std::string& Mixin::root() const { - // @@protoc_insertion_point(field_get:google.protobuf.Mixin.root) - return root_.GetNoArena(); -} -void Mixin::set_root(const ::std::string& value) { - - root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.Mixin.root) -} -#if LANG_CXX11 -void Mixin::set_root(::std::string&& value) { - - root_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Mixin.root) -} -#endif -void Mixin::set_root(const char* value) { - GOOGLE_DCHECK(value != NULL); - - root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.root) -} -void Mixin::set_root(const char* value, size_t size) { - - root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.root) -} -::std::string* Mixin::mutable_root() { - - // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.root) - return root_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* Mixin::release_root() { - // @@protoc_insertion_point(field_release:google.protobuf.Mixin.root) - - return root_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void Mixin::set_allocated_root(::std::string* root) { - if (root != NULL) { - - } else { - - } - root_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), root); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.root) + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + root_.Swap(&other->root_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS +::PROTOBUF_NAMESPACE_ID::Metadata Mixin::GetMetadata() const { + return GetMetadataStatic(); +} -// @@protoc_insertion_point(namespace_scope) -} // namespace protobuf -} // namespace google +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::Api* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::Api >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::Api >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::Method* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::Method >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::Method >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::Mixin* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::Mixin >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::Mixin >(arena); +} +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) +#include diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h index bed136dbf0f45..863b9da67d10c 100644 --- a/src/google/protobuf/api.pb.h +++ b/src/google/protobuf/api.pb.h @@ -1,30 +1,32 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/api.proto -#ifndef PROTOBUF_google_2fprotobuf_2fapi_2eproto__INCLUDED -#define PROTOBUF_google_2fprotobuf_2fapi_2eproto__INCLUDED +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto +#include #include -#include - -#if GOOGLE_PROTOBUF_VERSION < 3004000 +#include +#if PROTOBUF_VERSION < 3015000 #error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update +#error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 3015000 < PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please +#error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif +#include #include #include #include #include #include -#include +#include +#include #include #include // IWYU pragma: export #include // IWYU pragma: export @@ -32,509 +34,699 @@ #include #include // @@protoc_insertion_point(includes) -namespace google { -namespace protobuf { +#include +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fapi_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fapi_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[3] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; +}; +extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto; +PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(int index); +PROTOBUF_NAMESPACE_OPEN class Api; -class ApiDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern ApiDefaultTypeInternal _Api_default_instance_; +struct ApiDefaultTypeInternal; +PROTOBUF_EXPORT extern ApiDefaultTypeInternal _Api_default_instance_; class Method; -class MethodDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern MethodDefaultTypeInternal _Method_default_instance_; +struct MethodDefaultTypeInternal; +PROTOBUF_EXPORT extern MethodDefaultTypeInternal _Method_default_instance_; class Mixin; -class MixinDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern MixinDefaultTypeInternal _Mixin_default_instance_; -} // namespace protobuf -} // namespace google - -namespace google { -namespace protobuf { - -namespace protobuf_google_2fprotobuf_2fapi_2eproto { -// Internal implementation detail -- do not call these. -struct LIBPROTOBUF_EXPORT TableStruct { - static const ::google::protobuf::internal::ParseTableField entries[]; - static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; - static const ::google::protobuf::internal::ParseTable schema[]; - static const ::google::protobuf::uint32 offsets[]; - static const ::google::protobuf::internal::FieldMetadata field_metadata[]; - static const ::google::protobuf::internal::SerializationTable serialization_table[]; - static void InitDefaultsImpl(); -}; -void LIBPROTOBUF_EXPORT AddDescriptors(); -void LIBPROTOBUF_EXPORT InitDefaults(); -} // namespace protobuf_google_2fprotobuf_2fapi_2eproto +struct MixinDefaultTypeInternal; +PROTOBUF_EXPORT extern MixinDefaultTypeInternal _Mixin_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::Api* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::Method* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::Mixin* Arena::CreateMaybeMessage(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN // =================================================================== -class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Api) */ { +class PROTOBUF_EXPORT Api PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Api) */ { public: - Api(); + inline Api() : Api(nullptr) {} virtual ~Api(); + explicit constexpr Api(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); Api(const Api& from); - - inline Api& operator=(const Api& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 Api(Api&& from) noexcept : Api() { *this = ::std::move(from); } + inline Api& operator=(const Api& from) { + CopyFrom(from); + return *this; + } inline Api& operator=(Api&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - static const ::google::protobuf::Descriptor* descriptor(); - static const Api& default_instance(); + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const Api& default_instance() { + return *internal_default_instance(); + } static inline const Api* internal_default_instance() { return reinterpret_cast( &_Api_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 0; - void Swap(Api* other); friend void swap(Api& a, Api& b) { a.Swap(&b); } + inline void Swap(Api* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Api* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline Api* New() const PROTOBUF_FINAL { return New(NULL); } + inline Api* New() const final { + return CreateMaybeMessage(nullptr); + } - Api* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + Api* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const Api& from); void MergeFrom(const Api& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(Api* other); - private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Api"; } + protected: + explicit Api(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kMethodsFieldNumber = 2, + kOptionsFieldNumber = 3, + kMixinsFieldNumber = 6, + kNameFieldNumber = 1, + kVersionFieldNumber = 4, + kSourceContextFieldNumber = 5, + kSyntaxFieldNumber = 7, + }; // repeated .google.protobuf.Method methods = 2; int methods_size() const; + private: + int _internal_methods_size() const; + public: void clear_methods(); - static const int kMethodsFieldNumber = 2; - const ::google::protobuf::Method& methods(int index) const; - ::google::protobuf::Method* mutable_methods(int index); - ::google::protobuf::Method* add_methods(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >* + PROTOBUF_NAMESPACE_ID::Method* mutable_methods(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Method >* mutable_methods(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >& + private: + const PROTOBUF_NAMESPACE_ID::Method& _internal_methods(int index) const; + PROTOBUF_NAMESPACE_ID::Method* _internal_add_methods(); + public: + const PROTOBUF_NAMESPACE_ID::Method& methods(int index) const; + PROTOBUF_NAMESPACE_ID::Method* add_methods(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Method >& methods() const; // repeated .google.protobuf.Option options = 3; int options_size() const; + private: + int _internal_options_size() const; + public: void clear_options(); - static const int kOptionsFieldNumber = 3; - const ::google::protobuf::Option& options(int index) const; - ::google::protobuf::Option* mutable_options(int index); - ::google::protobuf::Option* add_options(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >* + PROTOBUF_NAMESPACE_ID::Option* mutable_options(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >* mutable_options(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >& + private: + const PROTOBUF_NAMESPACE_ID::Option& _internal_options(int index) const; + PROTOBUF_NAMESPACE_ID::Option* _internal_add_options(); + public: + const PROTOBUF_NAMESPACE_ID::Option& options(int index) const; + PROTOBUF_NAMESPACE_ID::Option* add_options(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >& options() const; // repeated .google.protobuf.Mixin mixins = 6; int mixins_size() const; + private: + int _internal_mixins_size() const; + public: void clear_mixins(); - static const int kMixinsFieldNumber = 6; - const ::google::protobuf::Mixin& mixins(int index) const; - ::google::protobuf::Mixin* mutable_mixins(int index); - ::google::protobuf::Mixin* add_mixins(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >* + PROTOBUF_NAMESPACE_ID::Mixin* mutable_mixins(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Mixin >* mutable_mixins(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >& + private: + const PROTOBUF_NAMESPACE_ID::Mixin& _internal_mixins(int index) const; + PROTOBUF_NAMESPACE_ID::Mixin* _internal_add_mixins(); + public: + const PROTOBUF_NAMESPACE_ID::Mixin& mixins(int index) const; + PROTOBUF_NAMESPACE_ID::Mixin* add_mixins(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Mixin >& mixins() const; // string name = 1; void clear_name(); - static const int kNameFieldNumber = 1; - const ::std::string& name() const; - void set_name(const ::std::string& value); - #if LANG_CXX11 - void set_name(::std::string&& value); - #endif + const std::string& name() const; + void set_name(const std::string& value); + void set_name(std::string&& value); void set_name(const char* value); void set_name(const char* value, size_t size); - ::std::string* mutable_name(); - ::std::string* release_name(); - void set_allocated_name(::std::string* name); + std::string* mutable_name(); + std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: // string version = 4; void clear_version(); - static const int kVersionFieldNumber = 4; - const ::std::string& version() const; - void set_version(const ::std::string& value); - #if LANG_CXX11 - void set_version(::std::string&& value); - #endif + const std::string& version() const; + void set_version(const std::string& value); + void set_version(std::string&& value); void set_version(const char* value); void set_version(const char* value, size_t size); - ::std::string* mutable_version(); - ::std::string* release_version(); - void set_allocated_version(::std::string* version); + std::string* mutable_version(); + std::string* release_version(); + void set_allocated_version(std::string* version); + private: + const std::string& _internal_version() const; + void _internal_set_version(const std::string& value); + std::string* _internal_mutable_version(); + public: // .google.protobuf.SourceContext source_context = 5; bool has_source_context() const; + private: + bool _internal_has_source_context() const; + public: void clear_source_context(); - static const int kSourceContextFieldNumber = 5; - const ::google::protobuf::SourceContext& source_context() const; - ::google::protobuf::SourceContext* mutable_source_context(); - ::google::protobuf::SourceContext* release_source_context(); - void set_allocated_source_context(::google::protobuf::SourceContext* source_context); + const PROTOBUF_NAMESPACE_ID::SourceContext& source_context() const; + PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context(); + PROTOBUF_NAMESPACE_ID::SourceContext* mutable_source_context(); + void set_allocated_source_context(PROTOBUF_NAMESPACE_ID::SourceContext* source_context); + private: + const PROTOBUF_NAMESPACE_ID::SourceContext& _internal_source_context() const; + PROTOBUF_NAMESPACE_ID::SourceContext* _internal_mutable_source_context(); + public: + void unsafe_arena_set_allocated_source_context( + PROTOBUF_NAMESPACE_ID::SourceContext* source_context); + PROTOBUF_NAMESPACE_ID::SourceContext* unsafe_arena_release_source_context(); // .google.protobuf.Syntax syntax = 7; void clear_syntax(); - static const int kSyntaxFieldNumber = 7; - ::google::protobuf::Syntax syntax() const; - void set_syntax(::google::protobuf::Syntax value); + PROTOBUF_NAMESPACE_ID::Syntax syntax() const; + void set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value); + private: + PROTOBUF_NAMESPACE_ID::Syntax _internal_syntax() const; + void _internal_set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.Api) private: - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method > methods_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin > mixins_; - ::google::protobuf::internal::ArenaStringPtr name_; - ::google::protobuf::internal::ArenaStringPtr version_; - ::google::protobuf::SourceContext* source_context_; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Method > methods_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option > options_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Mixin > mixins_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr version_; + PROTOBUF_NAMESPACE_ID::SourceContext* source_context_; int syntax_; - mutable int _cached_size_; - friend struct protobuf_google_2fprotobuf_2fapi_2eproto::TableStruct; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2fapi_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Method) */ { +class PROTOBUF_EXPORT Method PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Method) */ { public: - Method(); + inline Method() : Method(nullptr) {} virtual ~Method(); + explicit constexpr Method(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); Method(const Method& from); - - inline Method& operator=(const Method& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 Method(Method&& from) noexcept : Method() { *this = ::std::move(from); } + inline Method& operator=(const Method& from) { + CopyFrom(from); + return *this; + } inline Method& operator=(Method&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - static const ::google::protobuf::Descriptor* descriptor(); - static const Method& default_instance(); + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const Method& default_instance() { + return *internal_default_instance(); + } static inline const Method* internal_default_instance() { return reinterpret_cast( &_Method_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 1; - void Swap(Method* other); friend void swap(Method& a, Method& b) { a.Swap(&b); } + inline void Swap(Method* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Method* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline Method* New() const PROTOBUF_FINAL { return New(NULL); } + inline Method* New() const final { + return CreateMaybeMessage(nullptr); + } - Method* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + Method* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const Method& from); void MergeFrom(const Method& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(Method* other); - private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Method"; } + protected: + explicit Method(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kOptionsFieldNumber = 6, + kNameFieldNumber = 1, + kRequestTypeUrlFieldNumber = 2, + kResponseTypeUrlFieldNumber = 4, + kRequestStreamingFieldNumber = 3, + kResponseStreamingFieldNumber = 5, + kSyntaxFieldNumber = 7, + }; // repeated .google.protobuf.Option options = 6; int options_size() const; + private: + int _internal_options_size() const; + public: void clear_options(); - static const int kOptionsFieldNumber = 6; - const ::google::protobuf::Option& options(int index) const; - ::google::protobuf::Option* mutable_options(int index); - ::google::protobuf::Option* add_options(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >* + PROTOBUF_NAMESPACE_ID::Option* mutable_options(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >* mutable_options(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >& + private: + const PROTOBUF_NAMESPACE_ID::Option& _internal_options(int index) const; + PROTOBUF_NAMESPACE_ID::Option* _internal_add_options(); + public: + const PROTOBUF_NAMESPACE_ID::Option& options(int index) const; + PROTOBUF_NAMESPACE_ID::Option* add_options(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >& options() const; // string name = 1; void clear_name(); - static const int kNameFieldNumber = 1; - const ::std::string& name() const; - void set_name(const ::std::string& value); - #if LANG_CXX11 - void set_name(::std::string&& value); - #endif + const std::string& name() const; + void set_name(const std::string& value); + void set_name(std::string&& value); void set_name(const char* value); void set_name(const char* value, size_t size); - ::std::string* mutable_name(); - ::std::string* release_name(); - void set_allocated_name(::std::string* name); + std::string* mutable_name(); + std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: // string request_type_url = 2; void clear_request_type_url(); - static const int kRequestTypeUrlFieldNumber = 2; - const ::std::string& request_type_url() const; - void set_request_type_url(const ::std::string& value); - #if LANG_CXX11 - void set_request_type_url(::std::string&& value); - #endif + const std::string& request_type_url() const; + void set_request_type_url(const std::string& value); + void set_request_type_url(std::string&& value); void set_request_type_url(const char* value); void set_request_type_url(const char* value, size_t size); - ::std::string* mutable_request_type_url(); - ::std::string* release_request_type_url(); - void set_allocated_request_type_url(::std::string* request_type_url); + std::string* mutable_request_type_url(); + std::string* release_request_type_url(); + void set_allocated_request_type_url(std::string* request_type_url); + private: + const std::string& _internal_request_type_url() const; + void _internal_set_request_type_url(const std::string& value); + std::string* _internal_mutable_request_type_url(); + public: // string response_type_url = 4; void clear_response_type_url(); - static const int kResponseTypeUrlFieldNumber = 4; - const ::std::string& response_type_url() const; - void set_response_type_url(const ::std::string& value); - #if LANG_CXX11 - void set_response_type_url(::std::string&& value); - #endif + const std::string& response_type_url() const; + void set_response_type_url(const std::string& value); + void set_response_type_url(std::string&& value); void set_response_type_url(const char* value); void set_response_type_url(const char* value, size_t size); - ::std::string* mutable_response_type_url(); - ::std::string* release_response_type_url(); - void set_allocated_response_type_url(::std::string* response_type_url); + std::string* mutable_response_type_url(); + std::string* release_response_type_url(); + void set_allocated_response_type_url(std::string* response_type_url); + private: + const std::string& _internal_response_type_url() const; + void _internal_set_response_type_url(const std::string& value); + std::string* _internal_mutable_response_type_url(); + public: // bool request_streaming = 3; void clear_request_streaming(); - static const int kRequestStreamingFieldNumber = 3; bool request_streaming() const; void set_request_streaming(bool value); + private: + bool _internal_request_streaming() const; + void _internal_set_request_streaming(bool value); + public: // bool response_streaming = 5; void clear_response_streaming(); - static const int kResponseStreamingFieldNumber = 5; bool response_streaming() const; void set_response_streaming(bool value); + private: + bool _internal_response_streaming() const; + void _internal_set_response_streaming(bool value); + public: // .google.protobuf.Syntax syntax = 7; void clear_syntax(); - static const int kSyntaxFieldNumber = 7; - ::google::protobuf::Syntax syntax() const; - void set_syntax(::google::protobuf::Syntax value); + PROTOBUF_NAMESPACE_ID::Syntax syntax() const; + void set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value); + private: + PROTOBUF_NAMESPACE_ID::Syntax _internal_syntax() const; + void _internal_set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.Method) private: - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_; - ::google::protobuf::internal::ArenaStringPtr name_; - ::google::protobuf::internal::ArenaStringPtr request_type_url_; - ::google::protobuf::internal::ArenaStringPtr response_type_url_; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option > options_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr request_type_url_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr response_type_url_; bool request_streaming_; bool response_streaming_; int syntax_; - mutable int _cached_size_; - friend struct protobuf_google_2fprotobuf_2fapi_2eproto::TableStruct; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2fapi_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT Mixin : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Mixin) */ { +class PROTOBUF_EXPORT Mixin PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Mixin) */ { public: - Mixin(); + inline Mixin() : Mixin(nullptr) {} virtual ~Mixin(); + explicit constexpr Mixin(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); Mixin(const Mixin& from); - - inline Mixin& operator=(const Mixin& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 Mixin(Mixin&& from) noexcept : Mixin() { *this = ::std::move(from); } + inline Mixin& operator=(const Mixin& from) { + CopyFrom(from); + return *this; + } inline Mixin& operator=(Mixin&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - static const ::google::protobuf::Descriptor* descriptor(); - static const Mixin& default_instance(); + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const Mixin& default_instance() { + return *internal_default_instance(); + } static inline const Mixin* internal_default_instance() { return reinterpret_cast( &_Mixin_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 2; - void Swap(Mixin* other); friend void swap(Mixin& a, Mixin& b) { a.Swap(&b); } + inline void Swap(Mixin* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Mixin* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline Mixin* New() const PROTOBUF_FINAL { return New(NULL); } + inline Mixin* New() const final { + return CreateMaybeMessage(nullptr); + } - Mixin* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + Mixin* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const Mixin& from); void MergeFrom(const Mixin& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(Mixin* other); - private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Mixin"; } + protected: + explicit Mixin(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kNameFieldNumber = 1, + kRootFieldNumber = 2, + }; // string name = 1; void clear_name(); - static const int kNameFieldNumber = 1; - const ::std::string& name() const; - void set_name(const ::std::string& value); - #if LANG_CXX11 - void set_name(::std::string&& value); - #endif + const std::string& name() const; + void set_name(const std::string& value); + void set_name(std::string&& value); void set_name(const char* value); void set_name(const char* value, size_t size); - ::std::string* mutable_name(); - ::std::string* release_name(); - void set_allocated_name(::std::string* name); + std::string* mutable_name(); + std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: // string root = 2; void clear_root(); - static const int kRootFieldNumber = 2; - const ::std::string& root() const; - void set_root(const ::std::string& value); - #if LANG_CXX11 - void set_root(::std::string&& value); - #endif + const std::string& root() const; + void set_root(const std::string& value); + void set_root(std::string&& value); void set_root(const char* value); void set_root(const char* value, size_t size); - ::std::string* mutable_root(); - ::std::string* release_root(); - void set_allocated_root(::std::string* root); + std::string* mutable_root(); + std::string* release_root(); + void set_allocated_root(std::string* root); + private: + const std::string& _internal_root() const; + void _internal_set_root(const std::string& value); + std::string* _internal_mutable_root(); + public: // @@protoc_insertion_point(class_scope:google.protobuf.Mixin) private: - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::ArenaStringPtr name_; - ::google::protobuf::internal::ArenaStringPtr root_; - mutable int _cached_size_; - friend struct protobuf_google_2fprotobuf_2fapi_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr root_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2fapi_2eproto; }; // =================================================================== // =================================================================== -#if !PROTOBUF_INLINE_NOT_IN_HEADERS #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" @@ -543,112 +735,135 @@ class LIBPROTOBUF_EXPORT Mixin : public ::google::protobuf::Message /* @@protoc_ // string name = 1; inline void Api::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + name_.ClearToEmpty(); } -inline const ::std::string& Api::name() const { +inline const std::string& Api::name() const { // @@protoc_insertion_point(field_get:google.protobuf.Api.name) - return name_.GetNoArena(); + return _internal_name(); } -inline void Api::set_name(const ::std::string& value) { - - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void Api::set_name(const std::string& value) { + _internal_set_name(value); // @@protoc_insertion_point(field_set:google.protobuf.Api.name) } -#if LANG_CXX11 -inline void Api::set_name(::std::string&& value) { +inline std::string* Api::mutable_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.Api.name) + return _internal_mutable_name(); +} +inline const std::string& Api::_internal_name() const { + return name_.Get(); +} +inline void Api::_internal_set_name(const std::string& value) { - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void Api::set_name(std::string&& value) { + + name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Api.name) } -#endif inline void Api::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Api.name) } -inline void Api::set_name(const char* value, size_t size) { +inline void Api::set_name(const char* value, + size_t size) { - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.name) } -inline ::std::string* Api::mutable_name() { +inline std::string* Api::_internal_mutable_name() { - // @@protoc_insertion_point(field_mutable:google.protobuf.Api.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* Api::release_name() { +inline std::string* Api::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.Api.name) - - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void Api::set_allocated_name(::std::string* name) { - if (name != NULL) { +inline void Api::set_allocated_name(std::string* name) { + if (name != nullptr) { } else { } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.name) } // repeated .google.protobuf.Method methods = 2; -inline int Api::methods_size() const { +inline int Api::_internal_methods_size() const { return methods_.size(); } +inline int Api::methods_size() const { + return _internal_methods_size(); +} inline void Api::clear_methods() { methods_.Clear(); } -inline const ::google::protobuf::Method& Api::methods(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.Api.methods) - return methods_.Get(index); -} -inline ::google::protobuf::Method* Api::mutable_methods(int index) { +inline PROTOBUF_NAMESPACE_ID::Method* Api::mutable_methods(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.Api.methods) return methods_.Mutable(index); } -inline ::google::protobuf::Method* Api::add_methods() { - // @@protoc_insertion_point(field_add:google.protobuf.Api.methods) - return methods_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Method >* Api::mutable_methods() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.methods) return &methods_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >& +inline const PROTOBUF_NAMESPACE_ID::Method& Api::_internal_methods(int index) const { + return methods_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::Method& Api::methods(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.Api.methods) + return _internal_methods(index); +} +inline PROTOBUF_NAMESPACE_ID::Method* Api::_internal_add_methods() { + return methods_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::Method* Api::add_methods() { + // @@protoc_insertion_point(field_add:google.protobuf.Api.methods) + return _internal_add_methods(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Method >& Api::methods() const { // @@protoc_insertion_point(field_list:google.protobuf.Api.methods) return methods_; } // repeated .google.protobuf.Option options = 3; -inline int Api::options_size() const { +inline int Api::_internal_options_size() const { return options_.size(); } -inline void Api::clear_options() { - options_.Clear(); -} -inline const ::google::protobuf::Option& Api::options(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.Api.options) - return options_.Get(index); +inline int Api::options_size() const { + return _internal_options_size(); } -inline ::google::protobuf::Option* Api::mutable_options(int index) { +inline PROTOBUF_NAMESPACE_ID::Option* Api::mutable_options(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.Api.options) return options_.Mutable(index); } -inline ::google::protobuf::Option* Api::add_options() { - // @@protoc_insertion_point(field_add:google.protobuf.Api.options) - return options_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >* Api::mutable_options() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.options) return &options_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >& +inline const PROTOBUF_NAMESPACE_ID::Option& Api::_internal_options(int index) const { + return options_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::Option& Api::options(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.Api.options) + return _internal_options(index); +} +inline PROTOBUF_NAMESPACE_ID::Option* Api::_internal_add_options() { + return options_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::Option* Api::add_options() { + // @@protoc_insertion_point(field_add:google.protobuf.Api.options) + return _internal_add_options(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >& Api::options() const { // @@protoc_insertion_point(field_list:google.protobuf.Api.options) return options_; @@ -656,122 +871,176 @@ Api::options() const { // string version = 4; inline void Api::clear_version() { - version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + version_.ClearToEmpty(); } -inline const ::std::string& Api::version() const { +inline const std::string& Api::version() const { // @@protoc_insertion_point(field_get:google.protobuf.Api.version) - return version_.GetNoArena(); + return _internal_version(); } -inline void Api::set_version(const ::std::string& value) { - - version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void Api::set_version(const std::string& value) { + _internal_set_version(value); // @@protoc_insertion_point(field_set:google.protobuf.Api.version) } -#if LANG_CXX11 -inline void Api::set_version(::std::string&& value) { +inline std::string* Api::mutable_version() { + // @@protoc_insertion_point(field_mutable:google.protobuf.Api.version) + return _internal_mutable_version(); +} +inline const std::string& Api::_internal_version() const { + return version_.Get(); +} +inline void Api::_internal_set_version(const std::string& value) { - version_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void Api::set_version(std::string&& value) { + + version_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Api.version) } -#endif inline void Api::set_version(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); - version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Api.version) } -inline void Api::set_version(const char* value, size_t size) { +inline void Api::set_version(const char* value, + size_t size) { - version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); + version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.version) } -inline ::std::string* Api::mutable_version() { +inline std::string* Api::_internal_mutable_version() { - // @@protoc_insertion_point(field_mutable:google.protobuf.Api.version) - return version_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return version_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* Api::release_version() { +inline std::string* Api::release_version() { // @@protoc_insertion_point(field_release:google.protobuf.Api.version) - - return version_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return version_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void Api::set_allocated_version(::std::string* version) { - if (version != NULL) { +inline void Api::set_allocated_version(std::string* version) { + if (version != nullptr) { } else { } - version_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), version); + version_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), version, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.version) } // .google.protobuf.SourceContext source_context = 5; +inline bool Api::_internal_has_source_context() const { + return this != internal_default_instance() && source_context_ != nullptr; +} inline bool Api::has_source_context() const { - return this != internal_default_instance() && source_context_ != NULL; + return _internal_has_source_context(); } -inline void Api::clear_source_context() { - if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_; - source_context_ = NULL; +inline const PROTOBUF_NAMESPACE_ID::SourceContext& Api::_internal_source_context() const { + const PROTOBUF_NAMESPACE_ID::SourceContext* p = source_context_; + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_); } -inline const ::google::protobuf::SourceContext& Api::source_context() const { - const ::google::protobuf::SourceContext* p = source_context_; +inline const PROTOBUF_NAMESPACE_ID::SourceContext& Api::source_context() const { // @@protoc_insertion_point(field_get:google.protobuf.Api.source_context) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_SourceContext_default_instance_); + return _internal_source_context(); } -inline ::google::protobuf::SourceContext* Api::mutable_source_context() { +inline void Api::unsafe_arena_set_allocated_source_context( + PROTOBUF_NAMESPACE_ID::SourceContext* source_context) { + if (GetArena() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context_); + } + source_context_ = source_context; + if (source_context) { + + } else { + + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Api.source_context) +} +inline PROTOBUF_NAMESPACE_ID::SourceContext* Api::release_source_context() { - if (source_context_ == NULL) { - source_context_ = new ::google::protobuf::SourceContext; + PROTOBUF_NAMESPACE_ID::SourceContext* temp = source_context_; + source_context_ = nullptr; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); } - // @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context) - return source_context_; + return temp; } -inline ::google::protobuf::SourceContext* Api::release_source_context() { +inline PROTOBUF_NAMESPACE_ID::SourceContext* Api::unsafe_arena_release_source_context() { // @@protoc_insertion_point(field_release:google.protobuf.Api.source_context) - ::google::protobuf::SourceContext* temp = source_context_; - source_context_ = NULL; + PROTOBUF_NAMESPACE_ID::SourceContext* temp = source_context_; + source_context_ = nullptr; return temp; } -inline void Api::set_allocated_source_context(::google::protobuf::SourceContext* source_context) { - delete source_context_; - source_context_ = source_context; +inline PROTOBUF_NAMESPACE_ID::SourceContext* Api::_internal_mutable_source_context() { + + if (source_context_ == nullptr) { + auto* p = CreateMaybeMessage(GetArena()); + source_context_ = p; + } + return source_context_; +} +inline PROTOBUF_NAMESPACE_ID::SourceContext* Api::mutable_source_context() { + // @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context) + return _internal_mutable_source_context(); +} +inline void Api::set_allocated_source_context(PROTOBUF_NAMESPACE_ID::SourceContext* source_context) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + if (message_arena == nullptr) { + delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context_); + } if (source_context) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context)->GetArena(); + if (message_arena != submessage_arena) { + source_context = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, source_context, submessage_arena); + } } else { } + source_context_ = source_context; // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.source_context) } // repeated .google.protobuf.Mixin mixins = 6; -inline int Api::mixins_size() const { +inline int Api::_internal_mixins_size() const { return mixins_.size(); } +inline int Api::mixins_size() const { + return _internal_mixins_size(); +} inline void Api::clear_mixins() { mixins_.Clear(); } -inline const ::google::protobuf::Mixin& Api::mixins(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.Api.mixins) - return mixins_.Get(index); -} -inline ::google::protobuf::Mixin* Api::mutable_mixins(int index) { +inline PROTOBUF_NAMESPACE_ID::Mixin* Api::mutable_mixins(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.Api.mixins) return mixins_.Mutable(index); } -inline ::google::protobuf::Mixin* Api::add_mixins() { - // @@protoc_insertion_point(field_add:google.protobuf.Api.mixins) - return mixins_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Mixin >* Api::mutable_mixins() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.mixins) return &mixins_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >& +inline const PROTOBUF_NAMESPACE_ID::Mixin& Api::_internal_mixins(int index) const { + return mixins_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::Mixin& Api::mixins(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.Api.mixins) + return _internal_mixins(index); +} +inline PROTOBUF_NAMESPACE_ID::Mixin* Api::_internal_add_mixins() { + return mixins_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::Mixin* Api::add_mixins() { + // @@protoc_insertion_point(field_add:google.protobuf.Api.mixins) + return _internal_add_mixins(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Mixin >& Api::mixins() const { // @@protoc_insertion_point(field_list:google.protobuf.Api.mixins) return mixins_; @@ -781,13 +1050,19 @@ Api::mixins() const { inline void Api::clear_syntax() { syntax_ = 0; } -inline ::google::protobuf::Syntax Api::syntax() const { +inline PROTOBUF_NAMESPACE_ID::Syntax Api::_internal_syntax() const { + return static_cast< PROTOBUF_NAMESPACE_ID::Syntax >(syntax_); +} +inline PROTOBUF_NAMESPACE_ID::Syntax Api::syntax() const { // @@protoc_insertion_point(field_get:google.protobuf.Api.syntax) - return static_cast< ::google::protobuf::Syntax >(syntax_); + return _internal_syntax(); } -inline void Api::set_syntax(::google::protobuf::Syntax value) { +inline void Api::_internal_set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value) { syntax_ = value; +} +inline void Api::set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value) { + _internal_set_syntax(value); // @@protoc_insertion_point(field_set:google.protobuf.Api.syntax) } @@ -797,107 +1072,123 @@ inline void Api::set_syntax(::google::protobuf::Syntax value) { // string name = 1; inline void Method::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + name_.ClearToEmpty(); } -inline const ::std::string& Method::name() const { +inline const std::string& Method::name() const { // @@protoc_insertion_point(field_get:google.protobuf.Method.name) - return name_.GetNoArena(); + return _internal_name(); } -inline void Method::set_name(const ::std::string& value) { - - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void Method::set_name(const std::string& value) { + _internal_set_name(value); // @@protoc_insertion_point(field_set:google.protobuf.Method.name) } -#if LANG_CXX11 -inline void Method::set_name(::std::string&& value) { +inline std::string* Method::mutable_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.Method.name) + return _internal_mutable_name(); +} +inline const std::string& Method::_internal_name() const { + return name_.Get(); +} +inline void Method::_internal_set_name(const std::string& value) { + + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void Method::set_name(std::string&& value) { - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.name) } -#endif inline void Method::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Method.name) } -inline void Method::set_name(const char* value, size_t size) { +inline void Method::set_name(const char* value, + size_t size) { - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.name) } -inline ::std::string* Method::mutable_name() { +inline std::string* Method::_internal_mutable_name() { - // @@protoc_insertion_point(field_mutable:google.protobuf.Method.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* Method::release_name() { +inline std::string* Method::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.Method.name) - - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void Method::set_allocated_name(::std::string* name) { - if (name != NULL) { +inline void Method::set_allocated_name(std::string* name) { + if (name != nullptr) { } else { } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.name) } // string request_type_url = 2; inline void Method::clear_request_type_url() { - request_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + request_type_url_.ClearToEmpty(); } -inline const ::std::string& Method::request_type_url() const { +inline const std::string& Method::request_type_url() const { // @@protoc_insertion_point(field_get:google.protobuf.Method.request_type_url) - return request_type_url_.GetNoArena(); + return _internal_request_type_url(); } -inline void Method::set_request_type_url(const ::std::string& value) { - - request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void Method::set_request_type_url(const std::string& value) { + _internal_set_request_type_url(value); // @@protoc_insertion_point(field_set:google.protobuf.Method.request_type_url) } -#if LANG_CXX11 -inline void Method::set_request_type_url(::std::string&& value) { +inline std::string* Method::mutable_request_type_url() { + // @@protoc_insertion_point(field_mutable:google.protobuf.Method.request_type_url) + return _internal_mutable_request_type_url(); +} +inline const std::string& Method::_internal_request_type_url() const { + return request_type_url_.Get(); +} +inline void Method::_internal_set_request_type_url(const std::string& value) { - request_type_url_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void Method::set_request_type_url(std::string&& value) { + + request_type_url_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.request_type_url) } -#endif inline void Method::set_request_type_url(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); - request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Method.request_type_url) } -inline void Method::set_request_type_url(const char* value, size_t size) { +inline void Method::set_request_type_url(const char* value, + size_t size) { - request_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); + request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.request_type_url) } -inline ::std::string* Method::mutable_request_type_url() { +inline std::string* Method::_internal_mutable_request_type_url() { - // @@protoc_insertion_point(field_mutable:google.protobuf.Method.request_type_url) - return request_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return request_type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* Method::release_request_type_url() { +inline std::string* Method::release_request_type_url() { // @@protoc_insertion_point(field_release:google.protobuf.Method.request_type_url) - - return request_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return request_type_url_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void Method::set_allocated_request_type_url(::std::string* request_type_url) { - if (request_type_url != NULL) { +inline void Method::set_allocated_request_type_url(std::string* request_type_url) { + if (request_type_url != nullptr) { } else { } - request_type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), request_type_url); + request_type_url_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), request_type_url, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.request_type_url) } @@ -905,66 +1196,80 @@ inline void Method::set_allocated_request_type_url(::std::string* request_type_u inline void Method::clear_request_streaming() { request_streaming_ = false; } +inline bool Method::_internal_request_streaming() const { + return request_streaming_; +} inline bool Method::request_streaming() const { // @@protoc_insertion_point(field_get:google.protobuf.Method.request_streaming) - return request_streaming_; + return _internal_request_streaming(); } -inline void Method::set_request_streaming(bool value) { +inline void Method::_internal_set_request_streaming(bool value) { request_streaming_ = value; +} +inline void Method::set_request_streaming(bool value) { + _internal_set_request_streaming(value); // @@protoc_insertion_point(field_set:google.protobuf.Method.request_streaming) } // string response_type_url = 4; inline void Method::clear_response_type_url() { - response_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + response_type_url_.ClearToEmpty(); } -inline const ::std::string& Method::response_type_url() const { +inline const std::string& Method::response_type_url() const { // @@protoc_insertion_point(field_get:google.protobuf.Method.response_type_url) - return response_type_url_.GetNoArena(); + return _internal_response_type_url(); } -inline void Method::set_response_type_url(const ::std::string& value) { - - response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void Method::set_response_type_url(const std::string& value) { + _internal_set_response_type_url(value); // @@protoc_insertion_point(field_set:google.protobuf.Method.response_type_url) } -#if LANG_CXX11 -inline void Method::set_response_type_url(::std::string&& value) { +inline std::string* Method::mutable_response_type_url() { + // @@protoc_insertion_point(field_mutable:google.protobuf.Method.response_type_url) + return _internal_mutable_response_type_url(); +} +inline const std::string& Method::_internal_response_type_url() const { + return response_type_url_.Get(); +} +inline void Method::_internal_set_response_type_url(const std::string& value) { + + response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void Method::set_response_type_url(std::string&& value) { - response_type_url_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + response_type_url_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.response_type_url) } -#endif inline void Method::set_response_type_url(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); - response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Method.response_type_url) } -inline void Method::set_response_type_url(const char* value, size_t size) { +inline void Method::set_response_type_url(const char* value, + size_t size) { - response_type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); + response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.response_type_url) } -inline ::std::string* Method::mutable_response_type_url() { +inline std::string* Method::_internal_mutable_response_type_url() { - // @@protoc_insertion_point(field_mutable:google.protobuf.Method.response_type_url) - return response_type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return response_type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* Method::release_response_type_url() { +inline std::string* Method::release_response_type_url() { // @@protoc_insertion_point(field_release:google.protobuf.Method.response_type_url) - - return response_type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return response_type_url_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void Method::set_allocated_response_type_url(::std::string* response_type_url) { - if (response_type_url != NULL) { +inline void Method::set_allocated_response_type_url(std::string* response_type_url) { + if (response_type_url != nullptr) { } else { } - response_type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), response_type_url); + response_type_url_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), response_type_url, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.response_type_url) } @@ -972,41 +1277,53 @@ inline void Method::set_allocated_response_type_url(::std::string* response_type inline void Method::clear_response_streaming() { response_streaming_ = false; } +inline bool Method::_internal_response_streaming() const { + return response_streaming_; +} inline bool Method::response_streaming() const { // @@protoc_insertion_point(field_get:google.protobuf.Method.response_streaming) - return response_streaming_; + return _internal_response_streaming(); } -inline void Method::set_response_streaming(bool value) { +inline void Method::_internal_set_response_streaming(bool value) { response_streaming_ = value; +} +inline void Method::set_response_streaming(bool value) { + _internal_set_response_streaming(value); // @@protoc_insertion_point(field_set:google.protobuf.Method.response_streaming) } // repeated .google.protobuf.Option options = 6; -inline int Method::options_size() const { +inline int Method::_internal_options_size() const { return options_.size(); } -inline void Method::clear_options() { - options_.Clear(); -} -inline const ::google::protobuf::Option& Method::options(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.Method.options) - return options_.Get(index); +inline int Method::options_size() const { + return _internal_options_size(); } -inline ::google::protobuf::Option* Method::mutable_options(int index) { +inline PROTOBUF_NAMESPACE_ID::Option* Method::mutable_options(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.Method.options) return options_.Mutable(index); } -inline ::google::protobuf::Option* Method::add_options() { - // @@protoc_insertion_point(field_add:google.protobuf.Method.options) - return options_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >* Method::mutable_options() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.Method.options) return &options_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >& +inline const PROTOBUF_NAMESPACE_ID::Option& Method::_internal_options(int index) const { + return options_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::Option& Method::options(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.Method.options) + return _internal_options(index); +} +inline PROTOBUF_NAMESPACE_ID::Option* Method::_internal_add_options() { + return options_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::Option* Method::add_options() { + // @@protoc_insertion_point(field_add:google.protobuf.Method.options) + return _internal_add_options(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Option >& Method::options() const { // @@protoc_insertion_point(field_list:google.protobuf.Method.options) return options_; @@ -1016,13 +1333,19 @@ Method::options() const { inline void Method::clear_syntax() { syntax_ = 0; } -inline ::google::protobuf::Syntax Method::syntax() const { +inline PROTOBUF_NAMESPACE_ID::Syntax Method::_internal_syntax() const { + return static_cast< PROTOBUF_NAMESPACE_ID::Syntax >(syntax_); +} +inline PROTOBUF_NAMESPACE_ID::Syntax Method::syntax() const { // @@protoc_insertion_point(field_get:google.protobuf.Method.syntax) - return static_cast< ::google::protobuf::Syntax >(syntax_); + return _internal_syntax(); } -inline void Method::set_syntax(::google::protobuf::Syntax value) { +inline void Method::_internal_set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value) { syntax_ = value; +} +inline void Method::set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value) { + _internal_set_syntax(value); // @@protoc_insertion_point(field_set:google.protobuf.Method.syntax) } @@ -1032,114 +1355,129 @@ inline void Method::set_syntax(::google::protobuf::Syntax value) { // string name = 1; inline void Mixin::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + name_.ClearToEmpty(); } -inline const ::std::string& Mixin::name() const { +inline const std::string& Mixin::name() const { // @@protoc_insertion_point(field_get:google.protobuf.Mixin.name) - return name_.GetNoArena(); + return _internal_name(); } -inline void Mixin::set_name(const ::std::string& value) { - - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void Mixin::set_name(const std::string& value) { + _internal_set_name(value); // @@protoc_insertion_point(field_set:google.protobuf.Mixin.name) } -#if LANG_CXX11 -inline void Mixin::set_name(::std::string&& value) { +inline std::string* Mixin::mutable_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.name) + return _internal_mutable_name(); +} +inline const std::string& Mixin::_internal_name() const { + return name_.Get(); +} +inline void Mixin::_internal_set_name(const std::string& value) { + + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void Mixin::set_name(std::string&& value) { - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Mixin.name) } -#endif inline void Mixin::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.name) } -inline void Mixin::set_name(const char* value, size_t size) { +inline void Mixin::set_name(const char* value, + size_t size) { - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.name) } -inline ::std::string* Mixin::mutable_name() { +inline std::string* Mixin::_internal_mutable_name() { - // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* Mixin::release_name() { +inline std::string* Mixin::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.Mixin.name) - - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void Mixin::set_allocated_name(::std::string* name) { - if (name != NULL) { +inline void Mixin::set_allocated_name(std::string* name) { + if (name != nullptr) { } else { } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.name) } // string root = 2; inline void Mixin::clear_root() { - root_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + root_.ClearToEmpty(); } -inline const ::std::string& Mixin::root() const { +inline const std::string& Mixin::root() const { // @@protoc_insertion_point(field_get:google.protobuf.Mixin.root) - return root_.GetNoArena(); + return _internal_root(); } -inline void Mixin::set_root(const ::std::string& value) { - - root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void Mixin::set_root(const std::string& value) { + _internal_set_root(value); // @@protoc_insertion_point(field_set:google.protobuf.Mixin.root) } -#if LANG_CXX11 -inline void Mixin::set_root(::std::string&& value) { +inline std::string* Mixin::mutable_root() { + // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.root) + return _internal_mutable_root(); +} +inline const std::string& Mixin::_internal_root() const { + return root_.Get(); +} +inline void Mixin::_internal_set_root(const std::string& value) { + + root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void Mixin::set_root(std::string&& value) { - root_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + root_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Mixin.root) } -#endif inline void Mixin::set_root(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); - root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.root) } -inline void Mixin::set_root(const char* value, size_t size) { +inline void Mixin::set_root(const char* value, + size_t size) { - root_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); + root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.root) } -inline ::std::string* Mixin::mutable_root() { +inline std::string* Mixin::_internal_mutable_root() { - // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.root) - return root_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return root_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* Mixin::release_root() { +inline std::string* Mixin::release_root() { // @@protoc_insertion_point(field_release:google.protobuf.Mixin.root) - - return root_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return root_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void Mixin::set_allocated_root(::std::string* root) { - if (root != NULL) { +inline void Mixin::set_allocated_root(std::string* root) { + if (root != nullptr) { } else { } - root_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), root); + root_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), root, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.root) } #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ -#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // ------------------------------------------------------------------- // ------------------------------------------------------------------- @@ -1147,10 +1485,9 @@ inline void Mixin::set_allocated_root(::std::string* root) { // @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) -#endif // PROTOBUF_google_2fprotobuf_2fapi_2eproto__INCLUDED +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto diff --git a/src/google/protobuf/api.proto b/src/google/protobuf/api.proto index f37ee2fa46baa..3d598fc8590e7 100644 --- a/src/google/protobuf/api.proto +++ b/src/google/protobuf/api.proto @@ -40,7 +40,7 @@ option java_package = "com.google.protobuf"; option java_outer_classname = "ApiProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; -option go_package = "google.golang.org/genproto/protobuf/api;api"; +option go_package = "google.golang.org/protobuf/types/known/apipb"; // Api is a light-weight descriptor for an API Interface. // @@ -52,7 +52,6 @@ option go_package = "google.golang.org/genproto/protobuf/api;api"; // this message itself. See https://cloud.google.com/apis/design/glossary for // detailed terminology. message Api { - // The fully qualified name of this interface, including package name // followed by the interface's simple name. string name = 1; @@ -99,7 +98,6 @@ message Api { // Method represents a method of an API interface. message Method { - // The simple name of this method. string name = 1; @@ -169,7 +167,7 @@ message Method { // The mixin construct implies that all methods in `AccessControl` are // also declared with same name and request/response types in // `Storage`. A documentation generator or annotation processor will -// see the effective `Storage.GetAcl` method after inherting +// see the effective `Storage.GetAcl` method after inheriting // documentation and annotations as follows: // // service Storage { diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc old mode 100755 new mode 100644 index fe38f5ddd7038..bd9516b600d31 --- a/src/google/protobuf/arena.cc +++ b/src/google/protobuf/arena.cc @@ -31,327 +31,449 @@ #include #include +#include +#include +#include #include +#include +#include +#include #ifdef ADDRESS_SANITIZER #include #endif // ADDRESS_SANITIZER -namespace google { -static const size_t kMinCleanupListElements = 8; -static const size_t kMaxCleanupListElements = 64; // 1kB on 64-bit. +#include +namespace google { namespace protobuf { namespace internal { +static SerialArena::Memory AllocateMemory(const AllocationPolicy* policy_ptr, + size_t last_size, size_t min_bytes) { + AllocationPolicy policy; // default policy + if (policy_ptr) policy = *policy_ptr; + size_t size; + if (last_size != 0) { + // Double the current block size, up to a limit. + auto max_size = policy.max_block_size; + size = std::min(2 * last_size, max_size); + } else { + size = policy.start_block_size; + } + // Verify that min_bytes + kBlockHeaderSize won't overflow. + GOOGLE_CHECK_LE(min_bytes, + std::numeric_limits::max() - SerialArena::kBlockHeaderSize); + size = std::max(size, SerialArena::kBlockHeaderSize + min_bytes); + + void* mem; + if (policy.block_alloc == nullptr) { + mem = ::operator new(size); + } else { + mem = policy.block_alloc(size); + } + return {mem, size}; +} + +class GetDeallocator { + public: + GetDeallocator(const AllocationPolicy* policy, size_t* space_allocated) + : dealloc_(policy ? policy->block_dealloc : nullptr), + space_allocated_(space_allocated) {} + + void operator()(SerialArena::Memory mem) const { +#ifdef ADDRESS_SANITIZER + // This memory was provided by the underlying allocator as unpoisoned, + // so return it in an unpoisoned state. + ASAN_UNPOISON_MEMORY_REGION(mem.ptr, mem.size); +#endif // ADDRESS_SANITIZER + if (dealloc_) { + dealloc_(mem.ptr, mem.size); + } else { +#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) + ::operator delete(mem.ptr, mem.size); +#else + ::operator delete(mem.ptr); +#endif + } + *space_allocated_ += mem.size; + } + + private: + void (*dealloc_)(void*, size_t); + size_t* space_allocated_; +}; + +SerialArena::SerialArena(Block* b, void* owner) : space_allocated_(b->size) { + owner_ = owner; + head_ = b; + ptr_ = b->Pointer(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize); + limit_ = b->Pointer(b->size & static_cast(-8)); +} + +SerialArena* SerialArena::New(Memory mem, void* owner) { + GOOGLE_DCHECK_LE(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize, mem.size); + + auto b = new (mem.ptr) Block{nullptr, mem.size}; + return new (b->Pointer(kBlockHeaderSize)) SerialArena(b, owner); +} + +template +SerialArena::Memory SerialArena::Free(Deallocator deallocator) { + Block* b = head_; + Memory mem = {b, b->size}; + while (b->next) { + b = b->next; // We must first advance before deleting this block + deallocator(mem); + mem = {b, b->size}; + } + return mem; +} + +PROTOBUF_NOINLINE +std::pair +SerialArena::AllocateAlignedWithCleanupFallback( + size_t n, const AllocationPolicy* policy) { + AllocateNewBlock(n + kCleanupSize, policy); + return AllocateAlignedWithCleanup(n, policy); +} -google::protobuf::internal::SequenceNumber ArenaImpl::lifecycle_id_generator_; +PROTOBUF_NOINLINE +void* SerialArena::AllocateAlignedFallback(size_t n, + const AllocationPolicy* policy) { + AllocateNewBlock(n, policy); + return AllocateAligned(n, policy); +} + +void SerialArena::AllocateNewBlock(size_t n, const AllocationPolicy* policy) { + // Sync limit to block + head_->start = reinterpret_cast(limit_); + + // Record how much used in this block. + space_used_ += ptr_ - head_->Pointer(kBlockHeaderSize); + + auto mem = AllocateMemory(policy, head_->size, n); + // We don't want to emit an expensive RMW instruction that requires + // exclusive access to a cacheline. Hence we write it in terms of a + // regular add. + auto relaxed = std::memory_order_relaxed; + space_allocated_.store(space_allocated_.load(relaxed) + mem.size, relaxed); + head_ = new (mem.ptr) Block{head_, mem.size}; + ptr_ = head_->Pointer(kBlockHeaderSize); + limit_ = head_->Pointer(head_->size); + +#ifdef ADDRESS_SANITIZER + ASAN_POISON_MEMORY_REGION(ptr_, limit_ - ptr_); +#endif // ADDRESS_SANITIZER +} + +uint64 SerialArena::SpaceUsed() const { + uint64 space_used = ptr_ - head_->Pointer(kBlockHeaderSize); + space_used += space_used_; + // Remove the overhead of the SerialArena itself. + space_used -= ThreadSafeArena::kSerialArenaSize; + return space_used; +} + +void SerialArena::CleanupList() { + Block* b = head_; + b->start = reinterpret_cast(limit_); + do { + auto* limit = reinterpret_cast( + b->Pointer(b->size & static_cast(-8))); + auto it = b->start; + auto num = limit - it; + if (num > 0) { + for (; it < limit; it++) { + it->cleanup(it->elem); + } + } + b = b->next; + } while (b); +} + + +ThreadSafeArena::CacheAlignedLifecycleIdGenerator + ThreadSafeArena::lifecycle_id_generator_; #if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) -ArenaImpl::ThreadCache& ArenaImpl::thread_cache() { +ThreadSafeArena::ThreadCache& ThreadSafeArena::thread_cache() { static internal::ThreadLocalStorage* thread_cache_ = new internal::ThreadLocalStorage(); return *thread_cache_->Get(); } #elif defined(PROTOBUF_USE_DLLS) -ArenaImpl::ThreadCache& ArenaImpl::thread_cache() { - static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL }; +ThreadSafeArena::ThreadCache& ThreadSafeArena::thread_cache() { + static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_ = { + 0, static_cast(-1), nullptr}; return thread_cache_; } #else -GOOGLE_THREAD_LOCAL ArenaImpl::ThreadCache ArenaImpl::thread_cache_ = {-1, NULL}; +PROTOBUF_THREAD_LOCAL ThreadSafeArena::ThreadCache + ThreadSafeArena::thread_cache_ = {0, static_cast(-1), + nullptr}; #endif -void ArenaImpl::Init() { - lifecycle_id_ = lifecycle_id_generator_.GetNext(); - blocks_ = 0; - hint_ = 0; - space_allocated_ = 0; - owns_first_block_ = true; - - if (options_.initial_block != NULL && options_.initial_block_size > 0) { - GOOGLE_CHECK_GE(options_.initial_block_size, sizeof(Block)) - << ": Initial block size too small for header."; - - // Add first unowned block to list. - Block* first_block = reinterpret_cast(options_.initial_block); - first_block->size = options_.initial_block_size; - first_block->pos = kHeaderSize; - first_block->next = NULL; - first_block->cleanup = NULL; - // Thread which calls Init() owns the first block. This allows the - // single-threaded case to allocate on the first block without taking any - // locks. - first_block->owner = &thread_cache(); - AddBlockInternal(first_block); - CacheBlock(first_block); - owns_first_block_ = false; - } -} - -ArenaImpl::~ArenaImpl() { ResetInternal(); } +void ThreadSafeArena::InitializeFrom(void* mem, size_t size) { + GOOGLE_DCHECK_EQ(reinterpret_cast(mem) & 7, 0u); + Init(false); -uint64 ArenaImpl::Reset() { - // Invalidate any ThreadCaches pointing to any blocks we just destroyed. - lifecycle_id_ = lifecycle_id_generator_.GetNext(); - return ResetInternal(); + // Ignore initial block if it is too small. + if (mem != nullptr && size >= kBlockHeaderSize + kSerialArenaSize) { + alloc_policy_ |= kUserOwnedInitialBlock; + SetInitialBlock(mem, size); + } } -uint64 ArenaImpl::ResetInternal() { - Block* head = - reinterpret_cast(google::protobuf::internal::NoBarrier_Load(&blocks_)); - CleanupList(head); - uint64 space_allocated = FreeBlocks(head); +void ThreadSafeArena::InitializeWithPolicy(void* mem, size_t size, + bool record_allocs, + AllocationPolicy policy) { + GOOGLE_DCHECK_EQ(reinterpret_cast(mem) & 7, 0u); - return space_allocated; -} + Init(record_allocs); -ArenaImpl::Block* ArenaImpl::NewBlock(void* me, Block* my_last_block, - size_t min_bytes, size_t start_block_size, - size_t max_block_size) { - size_t size; - if (my_last_block != NULL) { - // Double the current block size, up to a limit. - size = std::min(2 * my_last_block->size, max_block_size); + // Ignore initial block if it is too small. We include an optional + // AllocationPolicy in this check, so that this can be allocated on the + // first block. + constexpr size_t kAPSize = internal::AlignUpTo8(sizeof(AllocationPolicy)); + constexpr size_t kMinimumSize = kBlockHeaderSize + kSerialArenaSize + kAPSize; + if (mem != nullptr && size >= kMinimumSize) { + alloc_policy_ = kUserOwnedInitialBlock; } else { - size = start_block_size; + alloc_policy_ = 0; + auto tmp = AllocateMemory(&policy, 0, kMinimumSize); + mem = tmp.ptr; + size = tmp.size; } - // Verify that min_bytes + kHeaderSize won't overflow. - GOOGLE_CHECK_LE(min_bytes, std::numeric_limits::max() - kHeaderSize); - size = std::max(size, kHeaderSize + min_bytes); - - Block* b = reinterpret_cast(options_.block_alloc(size)); - b->pos = kHeaderSize; - b->size = size; - b->owner = me; - b->cleanup = NULL; -#ifdef ADDRESS_SANITIZER - // Poison the rest of the block for ASAN. It was unpoisoned by the underlying - // malloc but it's not yet usable until we return it as part of an allocation. - ASAN_POISON_MEMORY_REGION( - reinterpret_cast(b) + b->pos, b->size - b->pos); -#endif // ADDRESS_SANITIZER - AddBlock(b); - return b; + SetInitialBlock(mem, size); + + auto sa = threads_.load(std::memory_order_relaxed); + // We ensured enough space so this cannot fail. + void* p; + if (!sa || !sa->MaybeAllocateAligned(kAPSize, &p)) { + GOOGLE_LOG(FATAL) << "MaybeAllocateAligned cannot fail here."; + return; + } + new (p) AllocationPolicy{policy}; + alloc_policy_ |= reinterpret_cast(p); } -void ArenaImpl::AddBlock(Block* b) { - MutexLock l(&blocks_lock_); - AddBlockInternal(b); +void ThreadSafeArena::Init(bool record_allocs) { + ThreadCache& tc = thread_cache(); + auto id = tc.next_lifecycle_id; + // We increment lifecycle_id's by multiples of two so we can use bit 0 as + // a tag. + constexpr uint64 kDelta = 2; + constexpr uint64 kInc = ThreadCache::kPerThreadIds * kDelta; + if (PROTOBUF_PREDICT_FALSE((id & (kInc - 1)) == 0)) { + constexpr auto relaxed = std::memory_order_relaxed; + // On platforms that don't support uint64 atomics we can certainly not + // afford to increment by large intervals and expect uniqueness due to + // wrapping, hence we only add by 1. + id = lifecycle_id_generator_.id.fetch_add(1, relaxed) * kInc; + } + tc.next_lifecycle_id = id + kDelta; + tag_and_id_ = id | (record_allocs ? kRecordAllocs : 0); + hint_.store(nullptr, std::memory_order_relaxed); + threads_.store(nullptr, std::memory_order_relaxed); } -void ArenaImpl::AddBlockInternal(Block* b) { - b->next = reinterpret_cast(google::protobuf::internal::NoBarrier_Load(&blocks_)); - google::protobuf::internal::Release_Store(&blocks_, reinterpret_cast(b)); - space_allocated_ += b->size; +void ThreadSafeArena::SetInitialBlock(void* mem, size_t size) { + SerialArena* serial = SerialArena::New({mem, size}, &thread_cache()); + serial->set_next(NULL); + threads_.store(serial, std::memory_order_relaxed); + CacheSerialArena(serial); } -ArenaImpl::Block* ArenaImpl::ExpandCleanupList(Block* b) { - size_t size = b->cleanup ? b->cleanup->size * 2 : kMinCleanupListElements; - size = std::min(size, kMaxCleanupListElements); - size_t bytes = internal::AlignUpTo8(CleanupChunk::SizeOf(size)); - if (b->avail() < bytes) { - b = GetBlock(bytes); - } - CleanupChunk* list = - reinterpret_cast(AllocFromBlock(b, bytes)); - list->next = b->cleanup; - list->size = size; - list->len = 0; - b->cleanup = list; - return b; -} +ThreadSafeArena::~ThreadSafeArena() { + // Have to do this in a first pass, because some of the destructors might + // refer to memory in other blocks. + CleanupList(); -inline GOOGLE_ATTRIBUTE_ALWAYS_INLINE void ArenaImpl::AddCleanupInBlock( - Block* b, void* elem, void (*cleanup)(void*)) { - if (b->cleanup == NULL || b->cleanup->len == b->cleanup->size) { - b = ExpandCleanupList(b); - } + size_t space_allocated = 0; + auto mem = Free(&space_allocated); - CleanupNode* node = &b->cleanup->nodes[b->cleanup->len++]; + // Policy is about to get deleted. + auto p = AllocPolicy(); + ArenaMetricsCollector* collector = p ? p->metrics_collector : nullptr; - node->elem = elem; - node->cleanup = cleanup; + if (alloc_policy_ & kUserOwnedInitialBlock) { + space_allocated += mem.size; + } else { + GetDeallocator(AllocPolicy(), &space_allocated)(mem); + } + + if (collector) collector->OnDestroy(space_allocated); } -void ArenaImpl::AddCleanup(void* elem, void (*cleanup)(void*)) { - return AddCleanupInBlock(GetBlock(0), elem, cleanup); +SerialArena::Memory ThreadSafeArena::Free(size_t* space_allocated) { + SerialArena::Memory mem = {nullptr, 0}; + auto deallocator = GetDeallocator(AllocPolicy(), space_allocated); + PerSerialArena([deallocator, &mem](SerialArena* a) { + if (mem.ptr) deallocator(mem); + mem = a->Free(deallocator); + }); + return mem; } -void* ArenaImpl::AllocateAligned(size_t n) { - GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. +uint64 ThreadSafeArena::Reset() { + // Have to do this in a first pass, because some of the destructors might + // refer to memory in other blocks. + CleanupList(); - return AllocFromBlock(GetBlock(n), n); -} + // Discard all blocks except the special block (if present). + size_t space_allocated = 0; + auto mem = Free(&space_allocated); -void* ArenaImpl::AllocateAlignedAndAddCleanup(size_t n, - void (*cleanup)(void*)) { - GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. + if (AllocPolicy()) { + auto saved_policy = *AllocPolicy(); + if (alloc_policy_ & kUserOwnedInitialBlock) { + space_allocated += mem.size; + } else { + GetDeallocator(AllocPolicy(), &space_allocated)(mem); + mem.ptr = nullptr; + mem.size = 0; + } + ArenaMetricsCollector* collector = saved_policy.metrics_collector; + if (collector) collector->OnReset(space_allocated); + InitializeWithPolicy(mem.ptr, mem.size, ShouldRecordAlloc(), saved_policy); + } else { + // Nullptr policy + if (alloc_policy_ & kUserOwnedInitialBlock) { + space_allocated += mem.size; + InitializeFrom(mem.ptr, mem.size); + } else { + GetDeallocator(AllocPolicy(), &space_allocated)(mem); + Init(false); + } + } - Block* b = GetBlock(n); - void* mem = AllocFromBlock(b, n); - AddCleanupInBlock(b, mem, cleanup); - return mem; + return space_allocated; } -inline GOOGLE_ATTRIBUTE_ALWAYS_INLINE ArenaImpl::Block* ArenaImpl::GetBlock(size_t n) { - Block* my_block = NULL; - - // If this thread already owns a block in this arena then try to use that. - // This fast path optimizes the case where multiple threads allocate from the - // same arena. - ThreadCache* tc = &thread_cache(); - if (tc->last_lifecycle_id_seen == lifecycle_id_) { - my_block = tc->last_block_used_; - if (my_block->avail() >= n) { - return my_block; - } +std::pair +ThreadSafeArena::AllocateAlignedWithCleanup(size_t n, + const std::type_info* type) { + SerialArena* arena; + if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(tag_and_id_, &arena))) { + return arena->AllocateAlignedWithCleanup(n, AllocPolicy()); + } else { + return AllocateAlignedWithCleanupFallback(n, type); } +} - // Check whether we own the last accessed block on this arena. - // This fast path optimizes the case where a single thread uses multiple - // arenas. - Block* b = reinterpret_cast(google::protobuf::internal::Acquire_Load(&hint_)); - if (b != NULL && b->owner == tc) { - my_block = b; - if (my_block->avail() >= n) { - return my_block; - } +void ThreadSafeArena::AddCleanup(void* elem, void (*cleanup)(void*)) { + SerialArena* arena; + if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(LifeCycleId(), &arena))) { + arena->AddCleanup(elem, cleanup, AllocPolicy()); + } else { + return AddCleanupFallback(elem, cleanup); } - return GetBlockSlow(tc, my_block, n); } -inline GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* ArenaImpl::AllocFromBlock(Block* b, - size_t n) { - GOOGLE_DCHECK_EQ(internal::AlignUpTo8(b->pos), b->pos); // Must be already aligned. - GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. - GOOGLE_DCHECK_GE(b->avail(), n); - size_t p = b->pos; - b->pos = p + n; -#ifdef ADDRESS_SANITIZER - ASAN_UNPOISON_MEMORY_REGION(reinterpret_cast(b) + p, n); -#endif // ADDRESS_SANITIZER - return reinterpret_cast(b) + p; +PROTOBUF_NOINLINE +void* ThreadSafeArena::AllocateAlignedFallback(size_t n, + const std::type_info* type) { + if (ShouldRecordAlloc()) { + RecordAlloc(type, n); + SerialArena* arena; + if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(LifeCycleId(), &arena))) { + return arena->AllocateAligned(n, AllocPolicy()); + } + } + return GetSerialArenaFallback(&thread_cache()) + ->AllocateAligned(n, AllocPolicy()); } -ArenaImpl::Block* ArenaImpl::GetBlockSlow(void* me, Block* my_full_block, - size_t n) { - Block* b = FindBlock(me); // Find block owned by me. - if (b == NULL || b->avail() < n) { - b = NewBlock(me, b, n, options_.start_block_size, options_.max_block_size); - - // Try to steal the cleanup list from my_full_block. It's too full for this - // allocation, but it might have space left in its cleanup list and there's - // no reason to waste that memory. - if (my_full_block) { - GOOGLE_DCHECK_EQ(my_full_block->owner, me); - GOOGLE_DCHECK(b->cleanup == NULL); - b->cleanup = my_full_block->cleanup; - my_full_block->cleanup = NULL; +PROTOBUF_NOINLINE +std::pair +ThreadSafeArena::AllocateAlignedWithCleanupFallback( + size_t n, const std::type_info* type) { + if (ShouldRecordAlloc()) { + RecordAlloc(type, n); + SerialArena* arena; + if (GetSerialArenaFast(LifeCycleId(), &arena)) { + return arena->AllocateAlignedWithCleanup(n, AllocPolicy()); } } - CacheBlock(b); - return b; + return GetSerialArenaFallback(&thread_cache()) + ->AllocateAlignedWithCleanup(n, AllocPolicy()); } -uint64 ArenaImpl::SpaceAllocated() const { - MutexLock l(&blocks_lock_); - return space_allocated_; +PROTOBUF_NOINLINE +void ThreadSafeArena::AddCleanupFallback(void* elem, void (*cleanup)(void*)) { + GetSerialArenaFallback(&thread_cache()) + ->AddCleanup(elem, cleanup, AllocPolicy()); } -uint64 ArenaImpl::SpaceUsed() const { - uint64 space_used = 0; - Block* b = reinterpret_cast(google::protobuf::internal::NoBarrier_Load(&blocks_)); - while (b != NULL) { - space_used += (b->pos - kHeaderSize); - b = b->next; +uint64 ThreadSafeArena::SpaceAllocated() const { + SerialArena* serial = threads_.load(std::memory_order_acquire); + uint64 res = 0; + for (; serial; serial = serial->next()) { + res += serial->SpaceAllocated(); } - return space_used; + return res; } -uint64 ArenaImpl::FreeBlocks(Block* head) { - uint64 space_allocated = 0; - Block* first_block = NULL; - Block* b = head; - - while (b != NULL) { - space_allocated += (b->size); - Block* next = b->next; - if (next != NULL) { -#ifdef ADDRESS_SANITIZER - // This memory was provided by the underlying allocator as unpoisoned, so - // return it in an unpoisoned state. - ASAN_UNPOISON_MEMORY_REGION(reinterpret_cast(b), b->size); -#endif // ADDRESS_SANITIZER - options_.block_dealloc(b, b->size); - } else { - if (owns_first_block_) { -#ifdef ADDRESS_SANITIZER - // This memory was provided by the underlying allocator as unpoisoned, - // so return it in an unpoisoned state. - ASAN_UNPOISON_MEMORY_REGION(reinterpret_cast(b), b->size); -#endif // ADDRESS_SANITIZER - options_.block_dealloc(b, b->size); - } else { - // User passed in the first block, skip free'ing the memory. - first_block = b; - } - } - b = next; - } - blocks_ = 0; - hint_ = 0; - space_allocated_ = 0; - if (!owns_first_block_) { - // Make the first block that was passed in through ArenaOptions - // available for reuse. - first_block->pos = kHeaderSize; - first_block->cleanup = NULL; - // Thread which calls Reset() owns the first block. This allows the - // single-threaded case to allocate on the first block without taking any - // locks. - first_block->owner = &thread_cache(); - AddBlockInternal(first_block); - CacheBlock(first_block); +uint64 ThreadSafeArena::SpaceUsed() const { + SerialArena* serial = threads_.load(std::memory_order_acquire); + uint64 space_used = 0; + for (; serial; serial = serial->next()) { + space_used += serial->SpaceUsed(); } - return space_allocated; + return space_used - (AllocPolicy() ? sizeof(AllocationPolicy) : 0); } -void ArenaImpl::CleanupList(Block* head) { - // Have to do this in a first pass, because some of the destructors might - // refer to memory in other blocks. - for (Block* b = head; b; b = b->next) { - CleanupChunk* list = b->cleanup; - while (list) { - size_t n = list->len; - CleanupNode* node = &list->nodes[list->len - 1]; - for (size_t i = 0; i < n; i++, node--) { - node->cleanup(node->elem); - } - list = list->next; +void ThreadSafeArena::CleanupList() { + PerSerialArena([](SerialArena* a) { a->CleanupList(); }); +} + +PROTOBUF_NOINLINE +SerialArena* ThreadSafeArena::GetSerialArenaFallback(void* me) { + // Look for this SerialArena in our linked list. + SerialArena* serial = threads_.load(std::memory_order_acquire); + for (; serial; serial = serial->next()) { + if (serial->owner() == me) { + break; } - b->cleanup = NULL; } -} -ArenaImpl::Block* ArenaImpl::FindBlock(void* me) { - // TODO(sanjay): We might want to keep a separate list with one - // entry per thread. - Block* b = reinterpret_cast(google::protobuf::internal::Acquire_Load(&blocks_)); - while (b != NULL && b->owner != me) { - b = b->next; + if (!serial) { + // This thread doesn't have any SerialArena, which also means it doesn't + // have any blocks yet. So we'll allocate its first block now. + serial = SerialArena::New( + AllocateMemory(AllocPolicy(), 0, kSerialArenaSize), me); + + SerialArena* head = threads_.load(std::memory_order_relaxed); + do { + serial->set_next(head); + } while (!threads_.compare_exchange_weak( + head, serial, std::memory_order_release, std::memory_order_relaxed)); } - return b; + + CacheSerialArena(serial); + return serial; } } // namespace internal -void Arena::OnArenaAllocation(const std::type_info* allocated_type, - size_t n) const { - if (on_arena_allocation_ != NULL) { - on_arena_allocation_(allocated_type, n, hooks_cookie_); - } +PROTOBUF_FUNC_ALIGN(32) +void* Arena::AllocateAlignedNoHook(size_t n) { + return impl_.AllocateAligned(n, nullptr); +} + +PROTOBUF_FUNC_ALIGN(32) +void* Arena::AllocateAlignedWithHook(size_t n, const std::type_info* type) { + return impl_.AllocateAligned(n, type); +} + +PROTOBUF_FUNC_ALIGN(32) +std::pair +Arena::AllocateAlignedWithCleanup(size_t n, const std::type_info* type) { + return impl_.AllocateAlignedWithCleanup(n, type); } } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index f8a947059f565..8b5c7f1826f6c 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -33,14 +33,14 @@ #ifndef GOOGLE_PROTOBUF_ARENA_H__ #define GOOGLE_PROTOBUF_ARENA_H__ + #include +#include +#include #ifdef max #undef max // Visual Studio defines this macro #endif -#if LANG_CXX11 -#include -#endif -#if defined(_MSC_VER) && !_HAS_EXCEPTIONS +#if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER) && !_HAS_EXCEPTIONS // Work around bugs in MSVC header when _HAS_EXCEPTIONS=0. #include #include @@ -51,37 +51,74 @@ using type_info = ::type_info; #include #endif +#include #include +#include + +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { + +struct ArenaOptions; // defined below + +} // namespace protobuf +} // namespace google namespace google { namespace protobuf { -class Arena; // defined below -class Message; // message.h +class Arena; // defined below +class Message; // defined in message.h +class MessageLite; +template +class Map; + +namespace arena_metrics { + +void EnableArenaMetrics(ArenaOptions* options); + +} // namespace arena_metrics namespace internal { -class ArenaString; // arenastring.h -class LazyField; // lazy_field.h -template -class GenericTypeHandler; // repeated_field.h +struct ArenaStringPtr; // defined in arenastring.h +class LazyField; // defined in lazy_field.h +class EpsCopyInputStream; // defined in parse_context.h + +template +class GenericTypeHandler; // defined in repeated_field.h + +PROTOBUF_ALWAYS_INLINE +inline void* AlignTo(void* ptr, size_t align) { + return reinterpret_cast( + (reinterpret_cast(ptr) + align - 1) & (~align + 1)); +} // Templated cleanup methods. -template void arena_destruct_object(void* object) { +template +void arena_destruct_object(void* object) { reinterpret_cast(object)->~T(); } -template void arena_delete_object(void* object) { + +template +struct ObjectDestructor { + constexpr static void (*destructor)(void*) = &arena_destruct_object; +}; + +template +struct ObjectDestructor { + constexpr static void (*destructor)(void*) = nullptr; +}; + +template +void arena_delete_object(void* object) { delete reinterpret_cast(object); } -inline void arena_free(void* object, size_t size) { -#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) - ::operator delete(object, size); -#else - (void)size; - ::operator delete(object); -#endif -} - } // namespace internal // ArenaOptions provides optional additional parameters to arena construction @@ -116,49 +153,45 @@ struct ArenaOptions { // from the arena. By default, it contains a ptr to a wrapper function that // calls free. void (*block_dealloc)(void*, size_t); - // Hooks for adding external functionality such as user-specific metrics - // collection, specific debugging abilities, etc. - // Init hook may return a pointer to a cookie to be stored in the arena. - // reset and destruction hooks will then be called with the same cookie - // pointer. This allows us to save an external object per arena instance and - // use it on the other hooks (Note: It is just as legal for init to return - // NULL and not use the cookie feature). - // on_arena_reset and on_arena_destruction also receive the space used in - // the arena just before the reset. - void* (*on_arena_init)(Arena* arena); - void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used); - void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used); - - // type_info is promised to be static - its lifetime extends to - // match program's lifetime (It is given by typeid operator). - // Note: typeid(void) will be passed as allocated_type every time we - // intentionally want to avoid monitoring an allocation. (i.e. internal - // allocations for managing the arena) - void (*on_arena_allocation)(const std::type_info* allocated_type, - uint64 alloc_size, void* cookie); ArenaOptions() - : start_block_size(kDefaultStartBlockSize), - max_block_size(kDefaultMaxBlockSize), + : start_block_size(internal::AllocationPolicy::kDefaultStartBlockSize), + max_block_size(internal::AllocationPolicy::kDefaultMaxBlockSize), initial_block(NULL), initial_block_size(0), - block_alloc(&::operator new), - block_dealloc(&internal::arena_free), - on_arena_init(NULL), - on_arena_reset(NULL), - on_arena_destruction(NULL), - on_arena_allocation(NULL) {} + block_alloc(nullptr), + block_dealloc(nullptr), + make_metrics_collector(nullptr) {} private: - // Constants define default starting block size and max block size for - // arena allocator behavior -- see descriptions above. - static const size_t kDefaultStartBlockSize = 256; - static const size_t kDefaultMaxBlockSize = 8192; + // If make_metrics_collector is not nullptr, it will be called at Arena init + // time. It may return a pointer to a collector instance that will be notified + // of interesting events related to the arena. + internal::ArenaMetricsCollector* (*make_metrics_collector)(); + + internal::ArenaMetricsCollector* MetricsCollector() const { + return make_metrics_collector ? (*make_metrics_collector)() : nullptr; + } + + internal::AllocationPolicy AllocationPolicy() const { + internal::AllocationPolicy res; + res.start_block_size = start_block_size; + res.max_block_size = max_block_size; + res.block_alloc = block_alloc; + res.block_dealloc = block_dealloc; + res.metrics_collector = MetricsCollector(); + return res; + } + + friend void arena_metrics::EnableArenaMetrics(ArenaOptions*); + + friend class Arena; + friend class ArenaOptionsTestFriend; }; // Support for non-RTTI environments. (The metrics hooks API uses type // information.) -#ifndef GOOGLE_PROTOBUF_NO_RTTI +#if PROTOBUF_RTTI #define RTTI_TYPE_ID(type) (&typeid(type)) #else #define RTTI_TYPE_ID(type) (NULL) @@ -184,14 +217,15 @@ struct ArenaOptions { // any special requirements on the type T, and will invoke the object's // destructor when the arena is destroyed. // -// The arena message allocation protocol, required by CreateMessage, is as -// follows: +// The arena message allocation protocol, required by +// CreateMessage(Arena* arena, Args&&... args), is as follows: // -// - The type T must have (at least) two constructors: a constructor with no -// arguments, called when a T is allocated on the heap; and a constructor with -// a google::protobuf::Arena* argument, called when a T is allocated on an arena. If the -// second constructor is called with a NULL arena pointer, it must be -// equivalent to invoking the first (no-argument) constructor. +// - The type T must have (at least) two constructors: a constructor callable +// with `args` (without `arena`), called when a T is allocated on the heap; +// and a constructor callable with `Arena* arena, Args&&... args`, called when +// a T is allocated on an arena. If the second constructor is called with a +// NULL arena pointer, it must be equivalent to invoking the first +// (`args`-only) constructor. // // - The type T must have a particular type trait: a nested type // |InternalArenaConstructable_|. This is usually a typedef to |void|. If no @@ -204,52 +238,43 @@ struct ArenaOptions { // present on the type, then its destructor is always called when the // containing arena is destroyed. // -// - One- and two-user-argument forms of CreateMessage() also exist that -// forward these constructor arguments to T's constructor: for example, -// CreateMessage(Arena*, arg1, arg2) forwards to a constructor T(Arena*, -// arg1, arg2). -// // This protocol is implemented by all arena-enabled proto2 message classes as -// well as RepeatedPtrField. -// -// Do NOT subclass Arena. This class will be marked as final when C++11 is -// enabled. -class LIBPROTOBUF_EXPORT Arena { +// well as protobuf container types like RepeatedPtrField and Map. The protocol +// is internal to protobuf and is not guaranteed to be stable. Non-proto types +// should not rely on this protocol. +class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { public: - // Arena constructor taking custom options. See ArenaOptions below for - // descriptions of the options available. - explicit Arena(const ArenaOptions& options) : impl_(options) { - Init(options); - } - // Default constructor with sensible default options, tuned for average // use-cases. - Arena() : impl_(ArenaOptions()) { Init(ArenaOptions()); } + inline Arena() : impl_() {} - ~Arena() { - uint64 space_allocated = SpaceAllocated(); - // Call the reset hook - if (on_arena_reset_ != NULL) { - on_arena_reset_(this, hooks_cookie_, space_allocated); - } + // Construct an arena with default options, except for the supplied + // initial block. It is more efficient to use this constructor + // instead of passing ArenaOptions if the only configuration needed + // by the caller is supplying an initial block. + inline Arena(char* initial_block, size_t initial_block_size) + : impl_(initial_block, initial_block_size) {} - // Call the destruction hook - if (on_arena_destruction_ != NULL) { - on_arena_destruction_(this, hooks_cookie_, space_allocated); - } - } + // Arena constructor taking custom options. See ArenaOptions above for + // descriptions of the options available. + explicit Arena(const ArenaOptions& options) + : impl_(options.initial_block, options.initial_block_size, + options.AllocationPolicy()) {} - void Init(const ArenaOptions& options) { - on_arena_allocation_ = options.on_arena_allocation; - on_arena_reset_ = options.on_arena_reset; - on_arena_destruction_ = options.on_arena_destruction; - // Call the initialization hook - if (options.on_arena_init != NULL) { - hooks_cookie_ = options.on_arena_init(this); - } else { - hooks_cookie_ = NULL; - } - } + // Block overhead. Use this as a guide for how much to over-allocate the + // initial block if you want an allocation of size N to fit inside it. + // + // WARNING: if you allocate multiple objects, it is difficult to guarantee + // that a series of allocations will fit in the initial block, especially if + // Arena changes its alignment guarantees in the future! + static const size_t kBlockOverhead = + internal::ThreadSafeArena::kBlockHeaderSize + + internal::ThreadSafeArena::kSerialArenaSize; + + inline ~Arena() {} + + // TODO(protobuf-team): Fix callers to use constructor and delete this method. + void Init(const ArenaOptions&) {} // API to create proto2 message objects on the arena. If the arena passed in // is NULL, then a heap allocated object is returned. Type T must be a message @@ -261,54 +286,15 @@ class LIBPROTOBUF_EXPORT Arena { // // This function also accepts any type T that satisfies the arena message // allocation protocol, documented above. - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static T* CreateMessage(::google::protobuf::Arena* arena) { -#if LANG_CXX11 + template + PROTOBUF_ALWAYS_INLINE static T* CreateMessage(Arena* arena, Args&&... args) { static_assert( InternalHelper::is_arena_constructable::value, "CreateMessage can only construct types that are ArenaConstructable"); -#endif - if (arena == NULL) { - return new T; - } else { - return arena->CreateMessageInternal(); - } - } - - // One-argument form of CreateMessage. This is useful for constructing objects - // that implement the arena message construction protocol described above but - // take additional constructor arguments. - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static T* CreateMessage(::google::protobuf::Arena* arena, const Arg& arg) { -#if LANG_CXX11 - static_assert( - InternalHelper::is_arena_constructable::value, - "CreateMessage can only construct types that are ArenaConstructable"); -#endif - if (arena == NULL) { - return new T(NULL, arg); - } else { - return arena->CreateMessageInternal(arg); - } - } - - // Two-argument form of CreateMessage. This is useful for constructing objects - // that implement the arena message construction protocol described above but - // take additional constructor arguments. - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static T* CreateMessage(::google::protobuf::Arena* arena, - const Arg1& arg1, - const Arg2& arg2) { -#if LANG_CXX11 - static_assert( - InternalHelper::is_arena_constructable::value, - "CreateMessage can only construct types that are ArenaConstructable"); -#endif - if (arena == NULL) { - return new T(NULL, arg1, arg2); - } else { - return arena->CreateMessageInternal(arg1, arg2); - } + // We must delegate to CreateMaybeMessage() and NOT CreateMessageInternal() + // because protobuf generated classes specialize CreateMaybeMessage() and we + // need to use that specialization for code size reasons. + return Arena::CreateMaybeMessage(arena, std::forward(args)...); } // API to create any objects on the arena. Note that only the object will @@ -326,143 +312,10 @@ class LIBPROTOBUF_EXPORT Arena { // (unless the destructor is trivial). Hence, from T's point of view, it is as // if the object were allocated on the heap (except that the underlying memory // is obtained from the arena). -#if LANG_CXX11 - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static T* Create(::google::protobuf::Arena* arena, Args&&... args) { - if (arena == NULL) { - return new T(std::forward(args)...); - } else { - return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, - std::forward(args)...); - } - } -#endif - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static T* Create(::google::protobuf::Arena* arena) { - if (arena == NULL) { - return new T(); - } else { - return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value); - } - } - - // Version of the above with one constructor argument for the created object. - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static T* Create(::google::protobuf::Arena* arena, const Arg& arg) { - if (arena == NULL) { - return new T(arg); - } else { - return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, - arg); - } - } - - // Version of the above with two constructor arguments for the created object. - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static T* Create(::google::protobuf::Arena* arena, const Arg1& arg1, const Arg2& arg2) { - if (arena == NULL) { - return new T(arg1, arg2); - } else { - return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, - arg1, arg2); - } - } - - // Version of the above with three constructor arguments for the created - // object. - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena, - const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3) { - if (arena == NULL) { - return new T(arg1, arg2, arg3); - } else { - return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, - arg1, arg2, arg3); - } - } - - // Version of the above with four constructor arguments for the created - // object. - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena, - const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3, const Arg4& arg4) { - if (arena == NULL) { - return new T(arg1, arg2, arg3, arg4); - } else { - return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, - arg1, arg2, arg3, arg4); - } - } - - // Version of the above with five constructor arguments for the created - // object. - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena, - const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3, const Arg4& arg4, - const Arg5& arg5) { - if (arena == NULL) { - return new T(arg1, arg2, arg3, arg4, arg5); - } else { - return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, - arg1, arg2, arg3, arg4, arg5); - } - } - - // Version of the above with six constructor arguments for the created - // object. - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena, - const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3, const Arg4& arg4, - const Arg5& arg5, const Arg6& arg6) { - if (arena == NULL) { - return new T(arg1, arg2, arg3, arg4, arg5, arg6); - } else { - return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, - arg1, arg2, arg3, arg4, arg5, arg6); - } - } - - // Version of the above with seven constructor arguments for the created - // object. - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena, - const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3, const Arg4& arg4, - const Arg5& arg5, const Arg6& arg6, - const Arg7& arg7) { - if (arena == NULL) { - return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7); - } else { - return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, - arg1, arg2, arg3, arg4, arg5, arg6, arg7); - } - } - - // Version of the above with eight constructor arguments for the created - // object. - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena, - const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3, const Arg4& arg4, - const Arg5& arg5, const Arg6& arg6, - const Arg7& arg7, const Arg8& arg8) { - if (arena == NULL) { - return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); - } else { - return arena->CreateInternal( - google::protobuf::internal::has_trivial_destructor::value, - arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); - } + template + PROTOBUF_NDEBUG_INLINE static T* Create(Arena* arena, Args&&... args) { + return CreateInternal(arena, std::is_convertible(), + std::forward(args)...); } // Create an array of object type T on the arena *without* invoking the @@ -471,10 +324,14 @@ class LIBPROTOBUF_EXPORT Arena { // To ensure safe uses, this function checks at compile time // (when compiled as C++11) that T is trivially default-constructible and // trivially destructible. - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static T* CreateArray(::google::protobuf::Arena* arena, size_t num_elements) { - GOOGLE_CHECK_LE(num_elements, - std::numeric_limits::max() / sizeof(T)) + template + PROTOBUF_NDEBUG_INLINE static T* CreateArray(Arena* arena, + size_t num_elements) { + static_assert(std::is_trivial::value, + "CreateArray requires a trivially constructible type"); + static_assert(std::is_trivially_destructible::value, + "CreateArray requires a trivially destructible type"); + GOOGLE_CHECK_LE(num_elements, std::numeric_limits::max() / sizeof(T)) << "Requested size is too large to fit into size_t."; if (arena == NULL) { return static_cast(::operator new[](num_elements * sizeof(T))); @@ -483,42 +340,31 @@ class LIBPROTOBUF_EXPORT Arena { } } + // The following are routines are for monitoring. They will approximate the + // total sum allocated and used memory, but the exact value is an + // implementation deal. For instance allocated space depends on growth + // policies. Do not use these in unit tests. // Returns the total space allocated by the arena, which is the sum of the - // sizes of the underlying blocks. This method is relatively fast; a counter - // is kept as blocks are allocated. + // sizes of the underlying blocks. uint64 SpaceAllocated() const { return impl_.SpaceAllocated(); } // Returns the total space used by the arena. Similar to SpaceAllocated but // does not include free space and block overhead. The total space returned // may not include space used by other threads executing concurrently with // the call to this method. uint64 SpaceUsed() const { return impl_.SpaceUsed(); } - // DEPRECATED. Please use SpaceAllocated() and SpaceUsed(). - // - // Combines SpaceAllocated and SpaceUsed. Returns a pair of - // . - std::pair SpaceAllocatedAndUsed() const { - return std::make_pair(SpaceAllocated(), SpaceUsed()); - } // Frees all storage allocated by this arena after calling destructors // registered with OwnDestructor() and freeing objects registered with Own(). // Any objects allocated on this arena are unusable after this call. It also // returns the total space used by the arena which is the sums of the sizes // of the allocated blocks. This method is not thread-safe. - GOOGLE_ATTRIBUTE_NOINLINE uint64 Reset() { - uint64 space_allocated = SpaceAllocated(); - // Call the reset hook - if (on_arena_reset_ != NULL) { - on_arena_reset_(this, hooks_cookie_, space_allocated); - } - return impl_.Reset(); - } + uint64 Reset() { return impl_.Reset(); } // Adds |object| to a list of heap-allocated objects to be freed with |delete| // when the arena is destroyed or reset. - template GOOGLE_ATTRIBUTE_NOINLINE - void Own(T* object) { - OwnInternal(object, google::protobuf::internal::is_convertible()); + template + PROTOBUF_ALWAYS_INLINE void Own(T* object) { + OwnInternal(object, std::is_convertible()); } // Adds |object| to a list of objects whose destructors will be manually @@ -526,8 +372,8 @@ class LIBPROTOBUF_EXPORT Arena { // that it does not free the underlying memory with |delete|; hence, it is // normally only used for objects that are placement-newed into // arena-allocated memory. - template GOOGLE_ATTRIBUTE_NOINLINE - void OwnDestructor(T* object) { + template + PROTOBUF_ALWAYS_INLINE void OwnDestructor(T* object) { if (object != NULL) { impl_.AddCleanup(object, &internal::arena_destruct_object); } @@ -537,18 +383,18 @@ class LIBPROTOBUF_EXPORT Arena { // will be manually called when the arena is destroyed or reset. This differs // from OwnDestructor() in that any member function may be specified, not only // the class destructor. - GOOGLE_ATTRIBUTE_NOINLINE void OwnCustomDestructor(void* object, - void (*destruct)(void*)) { + PROTOBUF_ALWAYS_INLINE void OwnCustomDestructor(void* object, + void (*destruct)(void*)) { impl_.AddCleanup(object, destruct); } // Retrieves the arena associated with |value| if |value| is an arena-capable - // message, or NULL otherwise. This differs from value->GetArena() in that the - // latter is a virtual call, while this method is a templated call that - // resolves at compile-time. - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static ::google::protobuf::Arena* GetArena(const T* value) { - return GetArenaInternal(value, is_arena_constructable()); + // message, or NULL otherwise. If possible, the call resolves at compile time. + // Note that we can often devirtualize calls to `value->GetArena()` so usually + // calling this method is unnecessary. + template + PROTOBUF_ALWAYS_INLINE static Arena* GetArena(const T* value) { + return GetArenaInternal(value); } template @@ -558,80 +404,119 @@ class LIBPROTOBUF_EXPORT Arena { template static double DestructorSkippable(...); - typedef google::protobuf::internal::integral_constant< + typedef std::integral_constant< bool, sizeof(DestructorSkippable(static_cast(0))) == sizeof(char) || - google::protobuf::internal::has_trivial_destructor::value> + std::is_trivially_destructible::value> is_destructor_skippable; - template + template static char ArenaConstructable( const typename U::InternalArenaConstructable_*); - template + template static double ArenaConstructable(...); - typedef google::protobuf::internal::integral_constant( - static_cast(0))) == - sizeof(char)> + typedef std::integral_constant( + static_cast(0))) == + sizeof(char)> is_arena_constructable; -#if LANG_CXX11 + template () + .GetArena())>::value, + int>::type = 0> + static char HasGetArena(decltype(&U::GetArena)); + template + static double HasGetArena(...); + + typedef std::integral_constant(nullptr)) == + sizeof(char)> + has_get_arena; + template static T* Construct(void* ptr, Args&&... args) { return new (ptr) T(std::forward(args)...); } -#else - template - static T* Construct(void* ptr, const Arg1& arg1) { - return new (ptr) T(arg1); - } - template - static T* Construct(void* ptr, const Arg1& arg1, const Arg2& arg2) { - return new (ptr) T(arg1, arg2); - } - template - static T* Construct(void* ptr, const Arg1& arg1, - const Arg2& arg2, const Arg3& arg3) { - return new (ptr) T(arg1, arg2, arg3); - } -#endif // LANG_CXX11 - static Arena* GetArena(const T* p) { return p->GetArenaNoVirtual(); } + static Arena* GetArena(const T* p) { return p->GetArena(); } friend class Arena; }; - // Helper typetrait that indicates support for arenas in a type T at compile + // Helper typetraits that indicates support for arenas in a type T at compile // time. This is public only to allow construction of higher-level templated - // utilities. is_arena_constructable::value is true if the message type T - // has arena support enabled, and false otherwise. + // utilities. + // + // is_arena_constructable::value is true if the message type T has arena + // support enabled, and false otherwise. + // + // is_destructor_skippable::value is true if the message type T has told + // the arena that it is safe to skip the destructor, and false otherwise. // // This is inside Arena because only Arena has the friend relationships // necessary to see the underlying generated code traits. template struct is_arena_constructable : InternalHelper::is_arena_constructable {}; + template + struct is_destructor_skippable : InternalHelper::is_destructor_skippable { + }; private: - void OnArenaAllocation(const std::type_info* allocated_type, size_t n) const; - inline void AllocHook(const std::type_info* allocated_type, size_t n) const { - if (GOOGLE_PREDICT_FALSE(hooks_cookie_ != NULL)) { - OnArenaAllocation(allocated_type, n); + internal::ThreadSafeArena impl_; + + template + struct has_get_arena : InternalHelper::has_get_arena {}; + + template + PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena, + Args&&... args) { + static_assert( + InternalHelper::is_arena_constructable::value, + "CreateMessage can only construct types that are ArenaConstructable"); + if (arena == NULL) { + return new T(nullptr, std::forward(args)...); + } else { + return arena->DoCreateMessage(std::forward(args)...); } } - // Allocate and also optionally call on_arena_allocation callback with the - // allocated type info when the hooks are in place in ArenaOptions and - // the cookie is not null. - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - void* AllocateInternal(bool skip_explicit_ownership) { - const size_t n = internal::AlignUpTo8(sizeof(T)); - AllocHook(RTTI_TYPE_ID(T), n); + // This specialization for no arguments is necessary, because its behavior is + // slightly different. When the arena pointer is nullptr, it calls T() + // instead of T(nullptr). + template + PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena) { + static_assert( + InternalHelper::is_arena_constructable::value, + "CreateMessage can only construct types that are ArenaConstructable"); + if (arena == NULL) { + return new T(); + } else { + return arena->DoCreateMessage(); + } + } + + // Allocate and also optionally call collector with the allocated type info + // when allocation recording is enabled. + PROTOBUF_NDEBUG_INLINE void* AllocateInternal(size_t size, size_t align, + void (*destructor)(void*), + const std::type_info* type) { // Monitor allocation if needed. - if (skip_explicit_ownership) { - return impl_.AllocateAligned(n); + if (destructor == nullptr) { + return AllocateAlignedWithHook(size, align, type); } else { - return impl_.AllocateAlignedAndAddCleanup( - n, &internal::arena_destruct_object); + if (align <= 8) { + auto res = AllocateAlignedWithCleanup(internal::AlignUpTo8(size), type); + res.second->elem = res.first; + res.second->cleanup = destructor; + return res.first; + } else { + auto res = AllocateAlignedWithCleanup(size + align - 8, type); + auto ptr = internal::AlignTo(res.first, align); + res.second->elem = ptr; + res.second->cleanup = destructor; + return ptr; + } } } @@ -640,203 +525,132 @@ class LIBPROTOBUF_EXPORT Arena { // as it can cause confusing API usages, and end up having double free in // user code. These are used only internally from LazyField and Repeated // fields, since they are designed to work in all mode combinations. - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE static Msg* CreateMaybeMessage(Arena* arena, - google::protobuf::internal::true_type) { - return CreateMessage(arena); + template + PROTOBUF_ALWAYS_INLINE static Msg* DoCreateMaybeMessage(Arena* arena, + std::true_type, + Args&&... args) { + return CreateMessageInternal(arena, std::forward(args)...); } - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* CreateMaybeMessage(Arena* arena, - google::protobuf::internal::false_type) { - return Create(arena); + template + PROTOBUF_ALWAYS_INLINE static T* DoCreateMaybeMessage(Arena* arena, + std::false_type, + Args&&... args) { + return Create(arena, std::forward(args)...); } - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* CreateMaybeMessage(Arena* arena) { - return CreateMaybeMessage(arena, is_arena_constructable()); + template + PROTOBUF_ALWAYS_INLINE static T* CreateMaybeMessage(Arena* arena, + Args&&... args) { + return DoCreateMaybeMessage(arena, is_arena_constructable(), + std::forward(args)...); } // Just allocate the required size for the given type assuming the // type has a trivial constructor. - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - T* CreateInternalRawArray(size_t num_elements) { - GOOGLE_CHECK_LE(num_elements, - std::numeric_limits::max() / sizeof(T)) - << "Requested size is too large to fit into size_t."; - const size_t n = internal::AlignUpTo8(sizeof(T) * num_elements); - // Monitor allocation if needed. - AllocHook(RTTI_TYPE_ID(T), n); - return static_cast(impl_.AllocateAligned(n)); - } - -#if LANG_CXX11 - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - T* CreateInternal(bool skip_explicit_ownership, Args&&... args) { - return new (AllocateInternal(skip_explicit_ownership)) - T(std::forward(args)...); - } -#else - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - T* CreateInternal(bool skip_explicit_ownership) { - return new (AllocateInternal(skip_explicit_ownership)) T(); - } - - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - T* CreateInternal(bool skip_explicit_ownership, const Arg& arg) { - return new (AllocateInternal(skip_explicit_ownership)) T(arg); - } - - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership, - const Arg1& arg1, - const Arg2& arg2) { - return new (AllocateInternal(skip_explicit_ownership)) T(arg1, arg2); - } - - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership, - const Arg1& arg1, - const Arg2& arg2, - const Arg3& arg3) { - return new (AllocateInternal(skip_explicit_ownership)) - T(arg1, arg2, arg3); - } - - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership, - const Arg1& arg1, - const Arg2& arg2, - const Arg3& arg3, - const Arg4& arg4) { - return new (AllocateInternal(skip_explicit_ownership)) - T(arg1, arg2, arg3, arg4); - } - - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership, - const Arg1& arg1, - const Arg2& arg2, - const Arg3& arg3, - const Arg4& arg4, - const Arg5& arg5) { - return new (AllocateInternal(skip_explicit_ownership)) - T(arg1, arg2, arg3, arg4, arg5); - } - - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership, - const Arg1& arg1, - const Arg2& arg2, - const Arg3& arg3, - const Arg4& arg4, - const Arg5& arg5, - const Arg6& arg6) { - return new (AllocateInternal(skip_explicit_ownership)) - T(arg1, arg2, arg3, arg4, arg5, arg6); - } - - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership, - const Arg1& arg1, - const Arg2& arg2, - const Arg3& arg3, - const Arg4& arg4, - const Arg5& arg5, - const Arg6& arg6, - const Arg7& arg7) { - return new (AllocateInternal(skip_explicit_ownership)) - T(arg1, arg2, arg3, arg4, arg5, arg6, arg7); - } - - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership, - const Arg1& arg1, - const Arg2& arg2, - const Arg3& arg3, - const Arg4& arg4, - const Arg5& arg5, - const Arg6& arg6, - const Arg7& arg7, - const Arg8& arg8) { - return new (AllocateInternal(skip_explicit_ownership)) - T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); - } -#endif template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateMessageInternal() { - return InternalHelper::Construct( - AllocateInternal(InternalHelper::is_destructor_skippable::value), - this); - } - - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateMessageInternal(const Arg& arg) { - return InternalHelper::Construct( - AllocateInternal(InternalHelper::is_destructor_skippable::value), - this, arg); + PROTOBUF_NDEBUG_INLINE T* CreateInternalRawArray(size_t num_elements) { + GOOGLE_CHECK_LE(num_elements, std::numeric_limits::max() / sizeof(T)) + << "Requested size is too large to fit into size_t."; + // We count on compiler to realize that if sizeof(T) is a multiple of + // 8 AlignUpTo can be elided. + const size_t n = sizeof(T) * num_elements; + return static_cast( + AllocateAlignedWithHook(n, alignof(T), RTTI_TYPE_ID(T))); } - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateMessageInternal(const Arg1& arg1, - const Arg2& arg2) { + template + PROTOBUF_NDEBUG_INLINE T* DoCreateMessage(Args&&... args) { return InternalHelper::Construct( - AllocateInternal(InternalHelper::is_destructor_skippable::value), - this, arg1, arg2); + AllocateInternal(sizeof(T), alignof(T), + internal::ObjectDestructor< + InternalHelper::is_destructor_skippable::value, + T>::destructor, + RTTI_TYPE_ID(T)), + this, std::forward(args)...); } // CreateInArenaStorage is used to implement map field. Without it, - // google::protobuf::Map need to call generated message's protected arena constructor, - // which needs to declare google::protobuf::Map as friend of generated message. - template - static void CreateInArenaStorage(T* ptr, Arena* arena) { + // Map need to call generated message's protected arena constructor, + // which needs to declare Map as friend of generated message. + template + static void CreateInArenaStorage(T* ptr, Arena* arena, Args&&... args) { CreateInArenaStorageInternal(ptr, arena, - typename is_arena_constructable::type()); + typename is_arena_constructable::type(), + std::forward(args)...); RegisterDestructorInternal( ptr, arena, typename InternalHelper::is_destructor_skippable::type()); } - template - static void CreateInArenaStorageInternal( - T* ptr, Arena* arena, google::protobuf::internal::true_type) { - InternalHelper::Construct(ptr, arena); + template + static void CreateInArenaStorageInternal(T* ptr, Arena* arena, + std::true_type, Args&&... args) { + InternalHelper::Construct(ptr, arena, std::forward(args)...); } - template - static void CreateInArenaStorageInternal( - T* ptr, Arena* /* arena */, google::protobuf::internal::false_type) { - new (ptr) T(); + template + static void CreateInArenaStorageInternal(T* ptr, Arena* /* arena */, + std::false_type, Args&&... args) { + new (ptr) T(std::forward(args)...); } template - static void RegisterDestructorInternal( - T* /* ptr */, Arena* /* arena */, google::protobuf::internal::true_type) {} + static void RegisterDestructorInternal(T* /* ptr */, Arena* /* arena */, + std::true_type) {} template - static void RegisterDestructorInternal( - T* ptr, Arena* arena, google::protobuf::internal::false_type) { + static void RegisterDestructorInternal(T* ptr, Arena* arena, + std::false_type) { arena->OwnDestructor(ptr); } + // These implement Create(). The second parameter has type 'true_type' if T is + // a subtype of Message and 'false_type' otherwise. + template + PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::true_type, + Args&&... args) { + if (arena == nullptr) { + return new T(std::forward(args)...); + } else { + auto destructor = + internal::ObjectDestructor::value, + T>::destructor; + T* result = + new (arena->AllocateInternal(sizeof(T), alignof(T), destructor, + RTTI_TYPE_ID(T))) + T(std::forward(args)...); + result->SetOwningArena(arena); + return result; + } + } + template + PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::false_type, + Args&&... args) { + if (arena == nullptr) { + return new T(std::forward(args)...); + } else { + auto destructor = + internal::ObjectDestructor::value, + T>::destructor; + return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor, + RTTI_TYPE_ID(T))) + T(std::forward(args)...); + } + } + // These implement Own(), which registers an object for deletion (destructor // call and operator delete()). The second parameter has type 'true_type' if T - // is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing + // is a subtype of Message and 'false_type' otherwise. Collapsing // all template instantiations to one for generic Message reduces code size, // using the virtual destructor instead. - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - void OwnInternal(T* object, google::protobuf::internal::true_type) { + template + PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) { if (object != NULL) { - impl_.AddCleanup(object, - &internal::arena_delete_object< ::google::protobuf::Message>); + impl_.AddCleanup(object, &internal::arena_delete_object); + object->SetOwningArena(this); } } - template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - void OwnInternal(T* object, google::protobuf::internal::false_type) { + template + PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::false_type) { if (object != NULL) { impl_.AddCleanup(object, &internal::arena_delete_object); } @@ -844,41 +658,68 @@ class LIBPROTOBUF_EXPORT Arena { // Implementation for GetArena(). Only message objects with // InternalArenaConstructable_ tags can be associated with an arena, and such - // objects must implement a GetArenaNoVirtual() method. - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE static ::google::protobuf::Arena* GetArenaInternal( - const T* value, google::protobuf::internal::true_type) { + // objects must implement a GetArena() method. + template ::value, int>::type = 0> + PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) { return InternalHelper::GetArena(value); } - - template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE static ::google::protobuf::Arena* GetArenaInternal( - const T* value, google::protobuf::internal::false_type) { - return NULL; + template ::value && + has_get_arena::value, + int>::type = 0> + PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) { + return value->GetArena(); + } + template ::value && + !has_get_arena::value, + int>::type = 0> + PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) { + (void)value; + return nullptr; } // For friends of arena. - void* AllocateAligned(size_t n) { - AllocHook(NULL, n); - return impl_.AllocateAligned(internal::AlignUpTo8(n)); + void* AllocateAligned(size_t n, size_t align = 8) { + if (align <= 8) { + return AllocateAlignedNoHook(internal::AlignUpTo8(n)); + } else { + // We are wasting space by over allocating align - 8 bytes. Compared + // to a dedicated function that takes current alignment in consideration. + // Such a scheme would only waste (align - 8)/2 bytes on average, but + // requires a dedicated function in the outline arena allocation + // functions. Possibly re-evaluate tradeoffs later. + return internal::AlignTo(AllocateAlignedNoHook(n + align - 8), align); + } } - internal::ArenaImpl impl_; - - void* (*on_arena_init_)(Arena* arena); - void (*on_arena_allocation_)(const std::type_info* allocated_type, - uint64 alloc_size, void* cookie); - void (*on_arena_reset_)(Arena* arena, void* cookie, uint64 space_used); - void (*on_arena_destruction_)(Arena* arena, void* cookie, uint64 space_used); + void* AllocateAlignedWithHook(size_t n, size_t align, + const std::type_info* type) { + if (align <= 8) { + return AllocateAlignedWithHook(internal::AlignUpTo8(n), type); + } else { + // We are wasting space by over allocating align - 8 bytes. Compared + // to a dedicated function that takes current alignment in consideration. + // Such a schemee would only waste (align - 8)/2 bytes on average, but + // requires a dedicated function in the outline arena allocation + // functions. Possibly re-evaluate tradeoffs later. + return internal::AlignTo(AllocateAlignedWithHook(n + align - 8, type), + align); + } + } - // The arena may save a cookie it receives from the external on_init hook - // and then use it when calling the on_reset and on_destruction hooks. - void* hooks_cookie_; + void* AllocateAlignedNoHook(size_t n); + void* AllocateAlignedWithHook(size_t n, const std::type_info* type); + std::pair + AllocateAlignedWithCleanup(size_t n, const std::type_info* type); template - friend class ::google::protobuf::internal::GenericTypeHandler; - friend class internal::ArenaString; // For AllocateAligned. - friend class internal::LazyField; // For CreateMaybeMessage. + friend class internal::GenericTypeHandler; + friend struct internal::ArenaStringPtr; // For AllocateAligned. + friend class internal::LazyField; // For CreateMaybeMessage. + friend class internal::EpsCopyInputStream; // For parser performance + friend class MessageLite; template friend class Map; }; @@ -887,6 +728,8 @@ class LIBPROTOBUF_EXPORT Arena { #undef RTTI_TYPE_ID } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_ARENA_H__ diff --git a/src/google/protobuf/arena_impl.h b/src/google/protobuf/arena_impl.h index b7f0c7b6ad1f5..40608dfe0d30a 100644 --- a/src/google/protobuf/arena_impl.h +++ b/src/google/protobuf/arena_impl.h @@ -33,182 +33,453 @@ #ifndef GOOGLE_PROTOBUF_ARENA_IMPL_H__ #define GOOGLE_PROTOBUF_ARENA_IMPL_H__ +#include #include +#include -#include -#include #include #include -#include -#include -namespace google { +#ifdef ADDRESS_SANITIZER +#include +#endif // ADDRESS_SANITIZER + +#include + +namespace google { namespace protobuf { namespace internal { -inline size_t AlignUpTo8(size_t n) { +inline constexpr size_t AlignUpTo8(size_t n) { // Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.) - return (n + 7) & -8; + return (n + 7) & static_cast(-8); } +using LifecycleIdAtomic = uint64_t; + +// MetricsCollector collects stats for a particular arena. +class PROTOBUF_EXPORT ArenaMetricsCollector { + public: + ArenaMetricsCollector(bool record_allocs) : record_allocs_(record_allocs) {} + + // Invoked when the arena is about to be destroyed. This method will + // typically finalize any metric collection and delete the collector. + // space_allocated is the space used by the arena. + virtual void OnDestroy(uint64 space_allocated) = 0; + + // OnReset() is called when the associated arena is reset. + // space_allocated is the space used by the arena just before the reset. + virtual void OnReset(uint64 space_allocated) = 0; + + // OnAlloc is called when an allocation happens. + // type_info is promised to be static - its lifetime extends to + // match program's lifetime (It is given by typeid operator). + // Note: typeid(void) will be passed as allocated_type every time we + // intentionally want to avoid monitoring an allocation. (i.e. internal + // allocations for managing the arena) + virtual void OnAlloc(const std::type_info* allocated_type, + uint64 alloc_size) = 0; + + // Does OnAlloc() need to be called? If false, metric collection overhead + // will be reduced since we will not do extra work per allocation. + bool RecordAllocs() { return record_allocs_; } + + protected: + // This class is destructed by the call to OnDestroy(). + ~ArenaMetricsCollector() = default; + const bool record_allocs_; +}; + +struct AllocationPolicy { + static constexpr size_t kDefaultStartBlockSize = 256; + static constexpr size_t kDefaultMaxBlockSize = 8192; + + size_t start_block_size = kDefaultStartBlockSize; + size_t max_block_size = kDefaultMaxBlockSize; + void* (*block_alloc)(size_t) = nullptr; + void (*block_dealloc)(void*, size_t) = nullptr; + ArenaMetricsCollector* metrics_collector = nullptr; + + bool IsDefault() const { + return start_block_size == kDefaultMaxBlockSize && + max_block_size == kDefaultMaxBlockSize && block_alloc == nullptr && + block_dealloc == nullptr && metrics_collector == nullptr; + } +}; + +// A simple arena allocator. Calls to allocate functions must be properly +// serialized by the caller, hence this class cannot be used as a general +// purpose allocator in a multi-threaded program. It serves as a building block +// for ThreadSafeArena, which provides a thread-safe arena allocator. +// +// This class manages +// 1) Arena bump allocation + owning memory blocks. +// 2) Maintaining a cleanup list. +// It delagetes the actual memory allocation back to ThreadSafeArena, which +// contains the information on block growth policy and backing memory allocation +// used. +class PROTOBUF_EXPORT SerialArena { + public: + struct Memory { + void* ptr; + size_t size; + }; + + // Node contains the ptr of the object to be cleaned up and the associated + // cleanup function ptr. + struct CleanupNode { + void* elem; // Pointer to the object to be cleaned up. + void (*cleanup)(void*); // Function pointer to the destructor or deleter. + }; + + // Creates a new SerialArena inside mem using the remaining memory as for + // future allocations. + static SerialArena* New(SerialArena::Memory mem, void* owner); + // Free SerialArena returning the memory passed in to New + template + Memory Free(Deallocator deallocator); + + void CleanupList(); + uint64 SpaceAllocated() const { + return space_allocated_.load(std::memory_order_relaxed); + } + uint64 SpaceUsed() const; + + bool HasSpace(size_t n) { return n <= static_cast(limit_ - ptr_); } + + void* AllocateAligned(size_t n, const AllocationPolicy* policy) { + GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. + GOOGLE_DCHECK_GE(limit_, ptr_); + if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) { + return AllocateAlignedFallback(n, policy); + } + void* ret = ptr_; + ptr_ += n; +#ifdef ADDRESS_SANITIZER + ASAN_UNPOISON_MEMORY_REGION(ret, n); +#endif // ADDRESS_SANITIZER + return ret; + } + + // Allocate space if the current region provides enough space. + bool MaybeAllocateAligned(size_t n, void** out) { + GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. + GOOGLE_DCHECK_GE(limit_, ptr_); + if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) return false; + void* ret = ptr_; + ptr_ += n; +#ifdef ADDRESS_SANITIZER + ASAN_UNPOISON_MEMORY_REGION(ret, n); +#endif // ADDRESS_SANITIZER + *out = ret; + return true; + } + + std::pair AllocateAlignedWithCleanup( + size_t n, const AllocationPolicy* policy) { + if (PROTOBUF_PREDICT_FALSE(!HasSpace(n + kCleanupSize))) { + return AllocateAlignedWithCleanupFallback(n, policy); + } + void* ret = ptr_; + ptr_ += n; + limit_ -= kCleanupSize; +#ifdef ADDRESS_SANITIZER + ASAN_UNPOISON_MEMORY_REGION(ret, n); + ASAN_UNPOISON_MEMORY_REGION(limit_, kCleanupSize); +#endif // ADDRESS_SANITIZER + return CreatePair(ret, reinterpret_cast(limit_)); + } + + void AddCleanup(void* elem, void (*cleanup)(void*), + const AllocationPolicy* policy) { + auto res = AllocateAlignedWithCleanup(0, policy); + res.second->elem = elem; + res.second->cleanup = cleanup; + } + + void* owner() const { return owner_; } + SerialArena* next() const { return next_; } + void set_next(SerialArena* next) { next_ = next; } + + private: + // Blocks are variable length malloc-ed objects. The following structure + // describes the common header for all blocks. + struct Block { + char* Pointer(size_t n) { + GOOGLE_DCHECK(n <= size); + return reinterpret_cast(this) + n; + } + + Block* next; + size_t size; + CleanupNode* start; + // data follows + }; + + void* owner_; // &ThreadCache of this thread; + Block* head_; // Head of linked list of blocks. + SerialArena* next_; // Next SerialArena in this linked list. + size_t space_used_ = 0; // Necessary for metrics. + std::atomic space_allocated_; + + // Next pointer to allocate from. Always 8-byte aligned. Points inside + // head_ (and head_->pos will always be non-canonical). We keep these + // here to reduce indirection. + char* ptr_; + char* limit_; + + // Constructor is private as only New() should be used. + inline SerialArena(Block* b, void* owner); + void* AllocateAlignedFallback(size_t n, const AllocationPolicy* policy); + std::pair AllocateAlignedWithCleanupFallback( + size_t n, const AllocationPolicy* policy); + void AllocateNewBlock(size_t n, const AllocationPolicy* policy); + + std::pair CreatePair(void* ptr, CleanupNode* node) { + return {ptr, node}; + } + + public: + static constexpr size_t kBlockHeaderSize = AlignUpTo8(sizeof(Block)); + static constexpr size_t kCleanupSize = AlignUpTo8(sizeof(CleanupNode)); +}; + // This class provides the core Arena memory allocation library. Different // implementations only need to implement the public interface below. // Arena is not a template type as that would only be useful if all protos // in turn would be templates, which will/cannot happen. However separating // the memory allocation part from the cruft of the API users expect we can // use #ifdef the select the best implementation based on hardware / OS. -class LIBPROTOBUF_EXPORT ArenaImpl { +class PROTOBUF_EXPORT ThreadSafeArena { public: - struct Options { - size_t start_block_size; - size_t max_block_size; - char* initial_block; - size_t initial_block_size; - void* (*block_alloc)(size_t); - void (*block_dealloc)(void*, size_t); - - template - explicit Options(const O& options) - : start_block_size(options.start_block_size), - max_block_size(options.max_block_size), - initial_block(options.initial_block), - initial_block_size(options.initial_block_size), - block_alloc(options.block_alloc), - block_dealloc(options.block_dealloc) {} - }; - - template - explicit ArenaImpl(const O& options) : options_(options) { - Init(); + ThreadSafeArena() { Init(false); } + + ThreadSafeArena(char* mem, size_t size) { InitializeFrom(mem, size); } + + explicit ThreadSafeArena(void* mem, size_t size, + const AllocationPolicy& policy) { + if (policy.IsDefault()) { + // Legacy code doesn't use the API above, but provides the initial block + // through ArenaOptions. I suspect most do not touch the allocation + // policy parameters. + InitializeFrom(mem, size); + } else { + auto collector = policy.metrics_collector; + bool record_allocs = collector && collector->RecordAllocs(); + InitializeWithPolicy(mem, size, record_allocs, policy); + } } // Destructor deletes all owned heap allocated objects, and destructs objects // that have non-trivial destructors, except for proto2 message objects whose // destructors can be skipped. Also, frees all blocks except the initial block // if it was passed in. - ~ArenaImpl(); + ~ThreadSafeArena(); uint64 Reset(); uint64 SpaceAllocated() const; uint64 SpaceUsed() const; - void* AllocateAligned(size_t n); + void* AllocateAligned(size_t n, const std::type_info* type) { + SerialArena* arena; + if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(tag_and_id_, &arena))) { + return arena->AllocateAligned(n, AllocPolicy()); + } else { + return AllocateAlignedFallback(n, type); + } + } + + // This function allocates n bytes if the common happy case is true and + // returns true. Otherwise does nothing and returns false. This strange + // semantics is necessary to allow callers to program functions that only + // have fallback function calls in tail position. This substantially improves + // code for the happy path. + PROTOBUF_NDEBUG_INLINE bool MaybeAllocateAligned(size_t n, void** out) { + SerialArena* a; + if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFromThreadCache(tag_and_id_, &a))) { + return a->MaybeAllocateAligned(n, out); + } + return false; + } - void* AllocateAlignedAndAddCleanup(size_t n, void (*cleanup)(void*)); + std::pair AllocateAlignedWithCleanup( + size_t n, const std::type_info* type); // Add object pointer and cleanup function pointer to the list. void AddCleanup(void* elem, void (*cleanup)(void*)); private: - // Node contains the ptr of the object to be cleaned up and the associated - // cleanup function ptr. - struct CleanupNode { - void* elem; // Pointer to the object to be cleaned up. - void (*cleanup)(void*); // Function pointer to the destructor or deleter. - }; + // Unique for each arena. Changes on Reset(). + uint64 tag_and_id_; + // The LSB of tag_and_id_ indicates if allocs in this arena are recorded. + enum { kRecordAllocs = 1 }; + + intptr_t alloc_policy_ = 0; // Tagged pointer to AllocPolicy. + // The LSB of alloc_policy_ indicates if the user owns the initial block. + enum { kUserOwnedInitialBlock = 1 }; + + // Pointer to a linked list of SerialArena. + std::atomic threads_; + std::atomic hint_; // Fast thread-local block access + + const AllocationPolicy* AllocPolicy() const { + return reinterpret_cast(alloc_policy_ & -8); + } + void InitializeFrom(void* mem, size_t size); + void InitializeWithPolicy(void* mem, size_t size, bool record_allocs, + AllocationPolicy policy); + void* AllocateAlignedFallback(size_t n, const std::type_info* type); + std::pair + AllocateAlignedWithCleanupFallback(size_t n, const std::type_info* type); + void AddCleanupFallback(void* elem, void (*cleanup)(void*)); + + void Init(bool record_allocs); + void SetInitialBlock(void* mem, size_t size); - // Cleanup uses a chunked linked list, to reduce pointer chasing. - struct CleanupChunk { - static size_t SizeOf(size_t i) { - return sizeof(CleanupChunk) + (sizeof(CleanupNode) * (i - 1)); + // Delete or Destruct all objects owned by the arena. + void CleanupList(); + + inline bool ShouldRecordAlloc() const { return tag_and_id_ & kRecordAllocs; } + + inline uint64 LifeCycleId() const { + return tag_and_id_ & (-kRecordAllocs - 1); + } + + inline void RecordAlloc(const std::type_info* allocated_type, + size_t n) const { + AllocPolicy()->metrics_collector->OnAlloc(allocated_type, n); + } + + inline void CacheSerialArena(SerialArena* serial) { + thread_cache().last_serial_arena = serial; + thread_cache().last_lifecycle_id_seen = LifeCycleId(); + // TODO(haberman): evaluate whether we would gain efficiency by getting rid + // of hint_. It's the only write we do to ThreadSafeArena in the allocation + // path, which will dirty the cache line. + + hint_.store(serial, std::memory_order_release); + } + + PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFast(uint64 lifecycle_id, + SerialArena** arena) { + if (GetSerialArenaFromThreadCache(lifecycle_id, arena)) return true; + if (lifecycle_id & kRecordAllocs) return false; + + // Check whether we own the last accessed SerialArena on this arena. This + // fast path optimizes the case where a single thread uses multiple arenas. + ThreadCache* tc = &thread_cache(); + SerialArena* serial = hint_.load(std::memory_order_acquire); + if (PROTOBUF_PREDICT_TRUE(serial != NULL && serial->owner() == tc)) { + *arena = serial; + return true; } - size_t len; // Number of elements currently present. - size_t size; // Total elements in the list. - CleanupChunk* next; // Next node in the list. - CleanupNode nodes[1]; // True length is |size|. - }; + return false; + } - // Blocks are variable length malloc-ed objects. The following structure - // describes the common header for all blocks. - struct Block { - void* owner; // &ThreadCache of thread that owns this block. - Block* next; // Next block in arena (may have different owner) - CleanupChunk* cleanup; // Head of cleanup list (may point to another block, - // but it must have the same owner). - // ((char*) &block) + pos is next available byte. It is always - // aligned at a multiple of 8 bytes. - size_t pos; - size_t size; // total size of the block. - GOOGLE_ATTRIBUTE_ALWAYS_INLINE size_t avail() const { return size - pos; } - // data follows - }; + PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFromThreadCache( + uint64 lifecycle_id, SerialArena** arena) { + // If this thread already owns a block in this arena then try to use that. + // This fast path optimizes the case where multiple threads allocate from + // the same arena. + ThreadCache* tc = &thread_cache(); + if (PROTOBUF_PREDICT_TRUE(tc->last_lifecycle_id_seen == lifecycle_id)) { + *arena = tc->last_serial_arena; + return true; + } + return false; + } + SerialArena* GetSerialArenaFallback(void* me); + + template + void PerSerialArena(Functor fn) { + // By omitting an Acquire barrier we ensure that any user code that doesn't + // properly synchronize Reset() or the destructor will throw a TSAN warning. + SerialArena* serial = threads_.load(std::memory_order_relaxed); + + for (; serial; serial = serial->next()) fn(serial); + } + + // Releases all memory except the first block which it returns. The first + // block might be owned by the user and thus need some extra checks before + // deleting. + SerialArena::Memory Free(size_t* space_allocated); - struct ThreadCache { +#ifdef _MSC_VER +#pragma warning(disable : 4324) +#endif + struct alignas(64) ThreadCache { +#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) + // If we are using the ThreadLocalStorage class to store the ThreadCache, + // then the ThreadCache's default constructor has to be responsible for + // initializing it. + ThreadCache() + : next_lifecycle_id(0), + last_lifecycle_id_seen(-1), + last_serial_arena(NULL) {} +#endif + + // Number of per-thread lifecycle IDs to reserve. Must be power of two. + // To reduce contention on a global atomic, each thread reserves a batch of + // IDs. The following number is calculated based on a stress test with + // ~6500 threads all frequently allocating a new arena. + static constexpr size_t kPerThreadIds = 256; + // Next lifecycle ID available to this thread. We need to reserve a new + // batch, if `next_lifecycle_id & (kPerThreadIds - 1) == 0`. + uint64 next_lifecycle_id; // The ThreadCache is considered valid as long as this matches the // lifecycle_id of the arena being used. - int64 last_lifecycle_id_seen; - Block* last_block_used_; + uint64 last_lifecycle_id_seen; + SerialArena* last_serial_arena; }; - // kHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8 to - // protect the invariant that pos is always at a multiple of 8. - static const size_t kHeaderSize = (sizeof(Block) + 7) & -8; -#if LANG_CXX11 - static_assert(kHeaderSize % 8 == 0, "kHeaderSize must be a multiple of 8."); + // Lifecycle_id can be highly contended variable in a situation of lots of + // arena creation. Make sure that other global variables are not sharing the + // cacheline. +#ifdef _MSC_VER +#pragma warning(disable : 4324) #endif - static google::protobuf::internal::SequenceNumber lifecycle_id_generator_; + struct alignas(64) CacheAlignedLifecycleIdGenerator { + std::atomic id; + }; + static CacheAlignedLifecycleIdGenerator lifecycle_id_generator_; #if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) - // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread + // Android ndk does not support __thread keyword so we use a custom thread // local storage class we implemented. - // iOS also does not support the GOOGLE_THREAD_LOCAL keyword. + // iOS also does not support the __thread keyword. static ThreadCache& thread_cache(); #elif defined(PROTOBUF_USE_DLLS) // Thread local variables cannot be exposed through DLL interface but we can // wrap them in static functions. static ThreadCache& thread_cache(); #else - static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_; + static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_; static ThreadCache& thread_cache() { return thread_cache_; } #endif - void Init(); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadSafeArena); + // All protos have pointers back to the arena hence Arena must have + // pointer stability. + ThreadSafeArena(ThreadSafeArena&&) = delete; + ThreadSafeArena& operator=(ThreadSafeArena&&) = delete; - // Free all blocks and return the total space used which is the sums of sizes - // of the all the allocated blocks. - uint64 FreeBlocks(Block* head); - - void AddCleanupInBlock(Block* b, void* elem, void (*cleanup)(void*)); - Block* ExpandCleanupList(Block* b); - // Delete or Destruct all objects owned by the arena. - void CleanupList(Block* head); - uint64 ResetInternal(); - - inline void CacheBlock(Block* block) { - thread_cache().last_block_used_ = block; - thread_cache().last_lifecycle_id_seen = lifecycle_id_; - google::protobuf::internal::Release_Store(&hint_, reinterpret_cast(block)); - } - - google::protobuf::internal::AtomicWord blocks_; // Head of linked list of all allocated blocks - google::protobuf::internal::AtomicWord hint_; // Fast thread-local block access - uint64 space_allocated_; // Sum of sizes of all allocated blocks. - - bool owns_first_block_; // Indicates that arena owns the first block - mutable Mutex blocks_lock_; - - void AddBlock(Block* b); - // Access must be synchronized, either by blocks_lock_ or by being called from - // Init()/Reset(). - void AddBlockInternal(Block* b); - // Returns a block owned by this thread. - Block* GetBlock(size_t n); - Block* GetBlockSlow(void* me, Block* my_full_block, size_t n); - Block* FindBlock(void* me); - Block* NewBlock(void* me, Block* my_last_block, size_t min_bytes, - size_t start_block_size, size_t max_block_size); - static void* AllocFromBlock(Block* b, size_t n); - - int64 lifecycle_id_; // Unique for each arena. Changes on Reset(). - - Options options_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArenaImpl); + public: + // kBlockHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8 + // to protect the invariant that pos is always at a multiple of 8. + static constexpr size_t kBlockHeaderSize = SerialArena::kBlockHeaderSize; + static constexpr size_t kSerialArenaSize = + (sizeof(SerialArena) + 7) & static_cast(-8); + static_assert(kBlockHeaderSize % 8 == 0, + "kBlockHeaderSize must be a multiple of 8."); + static_assert(kSerialArenaSize % 8 == 0, + "kSerialArenaSize must be a multiple of 8."); }; } // namespace internal } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_ARENA_IMPL_H__ diff --git a/src/google/protobuf/arena_test_util.cc b/src/google/protobuf/arena_test_util.cc index df9c5bd6b488c..da32960ce131a 100644 --- a/src/google/protobuf/arena_test_util.cc +++ b/src/google/protobuf/arena_test_util.cc @@ -28,9 +28,9 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include #include #include -#include #define EXPECT_EQ GOOGLE_CHECK_EQ diff --git a/src/google/protobuf/arena_test_util.h b/src/google/protobuf/arena_test_util.h index 8c9f7698c5da6..8ceab91aabc74 100644 --- a/src/google/protobuf/arena_test_util.h +++ b/src/google/protobuf/arena_test_util.h @@ -33,6 +33,8 @@ #include #include +#include +#include #include namespace google { @@ -41,16 +43,23 @@ namespace protobuf { template void TestParseCorruptedString(const T& message) { int success_count = 0; - string s = message.SerializeAsString(); + std::string s; + { + // Map order is not deterministic. To make the test deterministic we want + // to serialize the proto deterministically. + io::StringOutputStream output(&s); + io::CodedOutputStream out(&output); + out.SetSerializationDeterministic(true); + message.SerializePartialToCodedStream(&out); + } const int kMaxIters = 900; const int stride = s.size() <= kMaxIters ? 1 : s.size() / kMaxIters; const int start = stride == 1 || use_arena ? 0 : (stride + 1) / 2; for (int i = start; i < s.size(); i += stride) { for (int c = 1 + (i % 17); c < 256; c += 2 * c + (i & 3)) { s[i] ^= c; - google::protobuf::Arena arena; - T* message = - google::protobuf::Arena::CreateMessage(use_arena ? &arena : NULL); + Arena arena; + T* message = Arena::CreateMessage(use_arena ? &arena : nullptr); if (message->ParseFromString(s)) { ++success_count; } @@ -69,14 +78,13 @@ namespace internal { class NoHeapChecker { public: - NoHeapChecker() { - capture_alloc.Hook(); - } + NoHeapChecker() { capture_alloc.Hook(); } ~NoHeapChecker(); + private: class NewDeleteCapture { public: - // TOOD(xiaofeng): Implement this for opensource protobuf. + // TODO(xiaofeng): Implement this for opensource protobuf. void Hook() {} void Unhook() {} int alloc_count() { return 0; } @@ -86,6 +94,6 @@ class NoHeapChecker { } // namespace internal } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__ diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index 6172cade09df3..7e9016429f646 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -31,12 +31,11 @@ #include #include +#include #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include +#include #include #include @@ -46,7 +45,6 @@ #include #include #include -#include #include #include #include @@ -54,30 +52,29 @@ #include #include #include -#include #include +#include #include +#include -namespace google { +// Must be included last +#include + using proto2_arena_unittest::ArenaMessage; -using protobuf_unittest::TestAllTypes; using protobuf_unittest::TestAllExtensions; -using protobuf_unittest::TestOneof2; +using protobuf_unittest::TestAllTypes; using protobuf_unittest::TestEmptyMessage; +using protobuf_unittest::TestOneof2; +namespace google { namespace protobuf { -namespace { class Notifier { public: Notifier() : count_(0) {} - void Notify() { - count_++; - } - int GetCount() { - return count_; - } + void Notify() { count_++; } + int GetCount() { return count_; } private: int count_; @@ -86,14 +83,13 @@ class Notifier { class SimpleDataType { public: SimpleDataType() : notifier_(NULL) {} - void SetNotifier(Notifier* notifier) { - notifier_ = notifier; - } + void SetNotifier(Notifier* notifier) { notifier_ = notifier; } virtual ~SimpleDataType() { if (notifier_ != NULL) { notifier_->Notify(); } }; + private: Notifier* notifier_; }; @@ -114,14 +110,14 @@ class PleaseDontCopyMe { // A class that takes four different types as constructor arguments. class MustBeConstructedWithOneThroughFour { public: - MustBeConstructedWithOneThroughFour( - int one, const char* two, const string& three, - const PleaseDontCopyMe* four) + MustBeConstructedWithOneThroughFour(int one, const char* two, + const std::string& three, + const PleaseDontCopyMe* four) : one_(one), two_(two), three_(three), four_(four) {} int one_; const char* const two_; - string three_; + std::string three_; const PleaseDontCopyMe* four_; private: @@ -131,21 +127,29 @@ class MustBeConstructedWithOneThroughFour { // A class that takes eight different types as constructor arguments. class MustBeConstructedWithOneThroughEight { public: - MustBeConstructedWithOneThroughEight( - int one, const char* two, const string& three, - const PleaseDontCopyMe* four, int five, const char* six, - const string& seven, const string& eight) - : one_(one), two_(two), three_(three), four_(four), five_(five), - six_(six), seven_(seven), eight_(eight) {} + MustBeConstructedWithOneThroughEight(int one, const char* two, + const std::string& three, + const PleaseDontCopyMe* four, int five, + const char* six, + const std::string& seven, + const std::string& eight) + : one_(one), + two_(two), + three_(three), + four_(four), + five_(five), + six_(six), + seven_(seven), + eight_(eight) {} int one_; const char* const two_; - string three_; + std::string three_; const PleaseDontCopyMe* four_; int five_; const char* const six_; - string seven_; - string eight_; + std::string seven_; + std::string eight_; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughEight); @@ -157,18 +161,24 @@ TEST(ArenaTest, ArenaConstructable) { EXPECT_FALSE(Arena::is_arena_constructable::type::value); } +TEST(ArenaTest, DestructorSkippable) { + EXPECT_TRUE(Arena::is_destructor_skippable::type::value); + EXPECT_TRUE(Arena::is_destructor_skippable::type::value); + EXPECT_FALSE(Arena::is_destructor_skippable::type::value); +} + TEST(ArenaTest, BasicCreate) { Arena arena; EXPECT_TRUE(Arena::Create(&arena) != NULL); EXPECT_TRUE(Arena::Create(&arena) != NULL); EXPECT_TRUE(Arena::Create(&arena) != NULL); EXPECT_TRUE(Arena::Create(&arena) != NULL); - EXPECT_TRUE(Arena::Create(&arena) != NULL); + EXPECT_TRUE(Arena::Create(&arena) != NULL); arena.Own(new int32); arena.Own(new int64); arena.Own(new float); arena.Own(new double); - arena.Own(new string); + arena.Own(new std::string); arena.Own(NULL); Notifier notifier; SimpleDataType* data = Arena::Create(&arena); @@ -182,8 +192,8 @@ TEST(ArenaTest, BasicCreate) { TEST(ArenaTest, CreateAndConstCopy) { Arena arena; - const string s("foo"); - const string* s_copy = Arena::Create(&arena, s); + const std::string s("foo"); + const std::string* s_copy = Arena::Create(&arena, s); EXPECT_TRUE(s_copy != NULL); EXPECT_EQ("foo", s); EXPECT_EQ("foo", *s_copy); @@ -191,31 +201,29 @@ TEST(ArenaTest, CreateAndConstCopy) { TEST(ArenaTest, CreateAndNonConstCopy) { Arena arena; - string s("foo"); - const string* s_copy = Arena::Create(&arena, s); + std::string s("foo"); + const std::string* s_copy = Arena::Create(&arena, s); EXPECT_TRUE(s_copy != NULL); EXPECT_EQ("foo", s); EXPECT_EQ("foo", *s_copy); } -#if LANG_CXX11 TEST(ArenaTest, CreateAndMove) { Arena arena; - string s("foo"); - const string* s_move = Arena::Create(&arena, std::move(s)); + std::string s("foo"); + const std::string* s_move = Arena::Create(&arena, std::move(s)); EXPECT_TRUE(s_move != NULL); EXPECT_TRUE(s.empty()); // NOLINT EXPECT_EQ("foo", *s_move); } -#endif TEST(ArenaTest, CreateWithFourConstructorArguments) { Arena arena; - const string three("3"); + const std::string three("3"); const PleaseDontCopyMe four(4); const MustBeConstructedWithOneThroughFour* new_object = - Arena::Create( - &arena, 1, "2", three, &four); + Arena::Create(&arena, 1, "2", three, + &four); EXPECT_TRUE(new_object != NULL); ASSERT_EQ(1, new_object->one_); ASSERT_STREQ("2", new_object->two_); @@ -225,10 +233,10 @@ TEST(ArenaTest, CreateWithFourConstructorArguments) { TEST(ArenaTest, CreateWithEightConstructorArguments) { Arena arena; - const string three("3"); + const std::string three("3"); const PleaseDontCopyMe four(4); - const string seven("7"); - const string eight("8"); + const std::string seven("7"); + const std::string eight("8"); const MustBeConstructedWithOneThroughEight* new_object = Arena::Create( &arena, 1, "2", three, &four, 5, "6", seven, eight); @@ -243,17 +251,16 @@ TEST(ArenaTest, CreateWithEightConstructorArguments) { ASSERT_EQ("8", new_object->eight_); } -#if LANG_CXX11 class PleaseMoveMe { public: - explicit PleaseMoveMe(const string& value) : value_(value) {} + explicit PleaseMoveMe(const std::string& value) : value_(value) {} PleaseMoveMe(PleaseMoveMe&&) = default; PleaseMoveMe(const PleaseMoveMe&) = delete; - const string& value() const { return value_; } + const std::string& value() const { return value_; } private: - string value_; + std::string value_; }; TEST(ArenaTest, CreateWithMoveArguments) { @@ -264,31 +271,38 @@ TEST(ArenaTest, CreateWithMoveArguments) { EXPECT_TRUE(new_object); ASSERT_EQ("1", new_object->value()); } -#endif TEST(ArenaTest, InitialBlockTooSmall) { - // Construct a small (64 byte) initial block of memory to be used by the - // arena allocator; then, allocate an object which will not fit in the - // initial block. - std::vector arena_block(64); - ArenaOptions options; - options.initial_block = &arena_block[0]; - options.initial_block_size = arena_block.size(); - Arena arena(options); + // Construct a small blocks of memory to be used by the arena allocator; then, + // allocate an object which will not fit in the initial block. + for (int size = 0; size <= Arena::kBlockOverhead + 32; size++) { + std::vector arena_block(size); + ArenaOptions options; + options.initial_block = arena_block.data(); + options.initial_block_size = arena_block.size(); + + // Try sometimes with non-default block sizes so that we exercise paths + // with and without ArenaImpl::Options. + if ((size % 2) != 0) { + options.start_block_size += 8; + } + + Arena arena(options); - char* p = ::google::protobuf::Arena::CreateArray(&arena, 96); - uintptr_t allocation = reinterpret_cast(p); + char* p = Arena::CreateArray(&arena, 96); + uintptr_t allocation = reinterpret_cast(p); - // Ensure that the arena allocator did not return memory pointing into the - // initial block of memory. - uintptr_t arena_start = reinterpret_cast(&arena_block[0]); - uintptr_t arena_end = arena_start + arena_block.size(); - EXPECT_FALSE(allocation >= arena_start && allocation < arena_end); + // Ensure that the arena allocator did not return memory pointing into the + // initial block of memory. + uintptr_t arena_start = reinterpret_cast(arena_block.data()); + uintptr_t arena_end = arena_start + arena_block.size(); + EXPECT_FALSE(allocation >= arena_start && allocation < arena_end); - // Write to the memory we allocated; this should (but is not guaranteed to) - // trigger a check for heap corruption if the object was allocated from the - // initially-provided block. - memset(p, '\0', 96); + // Write to the memory we allocated; this should (but is not guaranteed to) + // trigger a check for heap corruption if the object was allocated from the + // initially-provided block. + memset(p, '\0', 96); + } } TEST(ArenaTest, Parsing) { @@ -407,7 +421,7 @@ TEST(ArenaTest, ReflectionSwapFields) { reflection->SwapFields(arena1_message, arena2_message, fields); EXPECT_EQ(&arena1, arena1_message->GetArena()); EXPECT_EQ(&arena2, arena2_message->GetArena()); - string output; + std::string output; arena1_message->SerializeToString(&output); EXPECT_EQ(0, output.size()); TestUtil::ExpectAllFieldsSet(*arena2_message); @@ -443,7 +457,7 @@ TEST(ArenaTest, ReflectionSwapFields) { TestUtil::SetAllFields(arena1_message); reflection->SwapFields(arena1_message, &message, fields); EXPECT_EQ(&arena1, arena1_message->GetArena()); - EXPECT_EQ(NULL, message.GetArena()); + EXPECT_EQ(nullptr, message.GetArena()); arena1_message->SerializeToString(&output); EXPECT_EQ(0, output.size()); TestUtil::ExpectAllFieldsSet(message); @@ -451,25 +465,18 @@ TEST(ArenaTest, ReflectionSwapFields) { TEST(ArenaTest, SetAllocatedMessage) { Arena arena; - TestAllTypes *arena_message = Arena::CreateMessage(&arena); + TestAllTypes* arena_message = Arena::CreateMessage(&arena); TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage; nested->set_bb(118); arena_message->set_allocated_optional_nested_message(nested); EXPECT_EQ(118, arena_message->optional_nested_message().bb()); - - protobuf_unittest_no_arena::TestNoArenaMessage no_arena_message; - EXPECT_FALSE(no_arena_message.has_arena_message()); - no_arena_message.set_allocated_arena_message(NULL); - EXPECT_FALSE(no_arena_message.has_arena_message()); - no_arena_message.set_allocated_arena_message(new ArenaMessage); - EXPECT_TRUE(no_arena_message.has_arena_message()); } TEST(ArenaTest, ReleaseMessage) { Arena arena; TestAllTypes* arena_message = Arena::CreateMessage(&arena); arena_message->mutable_optional_nested_message()->set_bb(118); - google::protobuf::scoped_ptr nested( + std::unique_ptr nested( arena_message->release_optional_nested_message()); EXPECT_EQ(118, nested->bb()); @@ -481,7 +488,7 @@ TEST(ArenaTest, ReleaseMessage) { TEST(ArenaTest, SetAllocatedString) { Arena arena; TestAllTypes* arena_message = Arena::CreateMessage(&arena); - string* allocated_str = new string("hello"); + std::string* allocated_str = new std::string("hello"); arena_message->set_allocated_optional_string(allocated_str); EXPECT_EQ("hello", arena_message->optional_string()); } @@ -490,7 +497,7 @@ TEST(ArenaTest, ReleaseString) { Arena arena; TestAllTypes* arena_message = Arena::CreateMessage(&arena); arena_message->set_optional_string("hello"); - google::protobuf::scoped_ptr released_str( + std::unique_ptr released_str( arena_message->release_optional_string()); EXPECT_EQ("hello", *released_str); @@ -506,7 +513,7 @@ TEST(ArenaTest, SwapBetweenArenasWithAllFieldsSet) { TestAllTypes* arena2_message = Arena::CreateMessage(&arena2); TestUtil::SetAllFields(arena2_message); arena2_message->Swap(arena1_message); - string output; + std::string output; arena2_message->SerializeToString(&output); EXPECT_EQ(0, output.size()); } @@ -544,7 +551,7 @@ TEST(ArenaTest, SwapBetweenArenasUsingReflection) { TestUtil::SetAllFields(arena2_message); const Reflection* r = arena2_message->GetReflection(); r->Swap(arena1_message, arena2_message); - string output; + std::string output; arena2_message->SerializeToString(&output); EXPECT_EQ(0, output.size()); } @@ -567,7 +574,7 @@ TEST(ArenaTest, SwapBetweenArenaAndNonArenaUsingReflection) { TEST(ArenaTest, ReleaseFromArenaMessageMakesCopy) { TestAllTypes::NestedMessage* nested_msg = NULL; - string* nested_string = NULL; + std::string* nested_string = NULL; { Arena arena; TestAllTypes* arena_message = Arena::CreateMessage(&arena); @@ -582,7 +589,7 @@ TEST(ArenaTest, ReleaseFromArenaMessageMakesCopy) { delete nested_string; } -#ifndef GOOGLE_PROTOBUF_NO_RTTI +#if PROTOBUF_RTTI TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) { TestAllTypes::NestedMessage* nested_msg = NULL; // Note: no string: reflection API only supports releasing submessages. @@ -599,26 +606,7 @@ TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) { EXPECT_EQ(42, nested_msg->bb()); delete nested_msg; } -#endif // !GOOGLE_PROTOBUF_NO_RTTI - -TEST(ArenaTest, UnsafeArenaReleaseDoesNotMakeCopy) { - Arena arena; - TestAllTypes* arena_message = Arena::CreateMessage(&arena); - TestAllTypes::NestedMessage* nested_msg = NULL; - TestAllTypes::NestedMessage* orig_nested_msg = NULL; - string* nested_string = NULL; - string* orig_nested_string = NULL; - arena_message->mutable_optional_nested_message()->set_bb(42); - *arena_message->mutable_optional_string() = "Hello"; - orig_nested_msg = arena_message->mutable_optional_nested_message(); - orig_nested_string = arena_message->mutable_optional_string(); - nested_msg = arena_message->unsafe_arena_release_optional_nested_message(); - nested_string = arena_message->unsafe_arena_release_optional_string(); - - EXPECT_EQ(orig_nested_msg, nested_msg); - EXPECT_EQ(orig_nested_string, nested_string); - // Released pointers still on arena; no 'delete' calls needed here. -} +#endif // PROTOBUF_RTTI TEST(ArenaTest, SetAllocatedAcrossArenas) { Arena arena1; @@ -628,8 +616,7 @@ TEST(ArenaTest, SetAllocatedAcrossArenas) { heap_submessage->set_bb(42); arena1_message->set_allocated_optional_nested_message(heap_submessage); // Should keep same object and add to arena's Own()-list. - EXPECT_EQ(heap_submessage, - arena1_message->mutable_optional_nested_message()); + EXPECT_EQ(heap_submessage, arena1_message->mutable_optional_nested_message()); { Arena arena2; TestAllTypes::NestedMessage* arena2_submessage = @@ -645,8 +632,7 @@ TEST(ArenaTest, SetAllocatedAcrossArenas) { arena1_submessage->set_bb(42); TestAllTypes* heap_message = new TestAllTypes; heap_message->set_allocated_optional_nested_message(arena1_submessage); - EXPECT_NE(arena1_submessage, - heap_message->mutable_optional_nested_message()); + EXPECT_NE(arena1_submessage, heap_message->mutable_optional_nested_message()); delete heap_message; } @@ -656,15 +642,14 @@ TEST(ArenaTest, SetAllocatedAcrossArenasWithReflection) { TestAllTypes* arena1_message = Arena::CreateMessage(&arena1); const Reflection* r = arena1_message->GetReflection(); const Descriptor* d = arena1_message->GetDescriptor(); - const FieldDescriptor* msg_field = d->FindFieldByName( - "optional_nested_message"); + const FieldDescriptor* msg_field = + d->FindFieldByName("optional_nested_message"); TestAllTypes::NestedMessage* heap_submessage = new TestAllTypes::NestedMessage(); heap_submessage->set_bb(42); r->SetAllocatedMessage(arena1_message, heap_submessage, msg_field); // Should keep same object and add to arena's Own()-list. - EXPECT_EQ(heap_submessage, - arena1_message->mutable_optional_nested_message()); + EXPECT_EQ(heap_submessage, arena1_message->mutable_optional_nested_message()); { Arena arena2; TestAllTypes::NestedMessage* arena2_submessage = @@ -680,8 +665,7 @@ TEST(ArenaTest, SetAllocatedAcrossArenasWithReflection) { arena1_submessage->set_bb(42); TestAllTypes* heap_message = new TestAllTypes; r->SetAllocatedMessage(heap_message, arena1_submessage, msg_field); - EXPECT_NE(arena1_submessage, - heap_message->mutable_optional_nested_message()); + EXPECT_NE(arena1_submessage, heap_message->mutable_optional_nested_message()); delete heap_message; } @@ -690,15 +674,8 @@ TEST(ArenaTest, AddAllocatedWithReflection) { ArenaMessage* arena1_message = Arena::CreateMessage(&arena1); const Reflection* r = arena1_message->GetReflection(); const Descriptor* d = arena1_message->GetDescriptor(); - const FieldDescriptor* fd = - d->FindFieldByName("repeated_import_no_arena_message"); - // Message with cc_enable_arenas = false; - r->AddMessage(arena1_message, fd); - r->AddMessage(arena1_message, fd); - r->AddMessage(arena1_message, fd); - EXPECT_EQ(3, r->FieldSize(*arena1_message, fd)); // Message with cc_enable_arenas = true; - fd = d->FindFieldByName("repeated_nested_message"); + const FieldDescriptor* fd = d->FindFieldByName("repeated_nested_message"); r->AddMessage(arena1_message, fd); r->AddMessage(arena1_message, fd); r->AddMessage(arena1_message, fd); @@ -736,11 +713,10 @@ TEST(ArenaTest, AddAllocatedToRepeatedField) { TestAllTypes::NestedMessage* heap_submessage = new TestAllTypes::NestedMessage(); heap_submessage->set_bb(42); - arena1_message->mutable_repeated_nested_message()-> - AddAllocated(heap_submessage); + arena1_message->mutable_repeated_nested_message()->AddAllocated( + heap_submessage); // Should not copy object -- will use arena_->Own(). - EXPECT_EQ(heap_submessage, - &arena1_message->repeated_nested_message(i)); + EXPECT_EQ(heap_submessage, &arena1_message->repeated_nested_message(i)); EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb()); } @@ -751,11 +727,10 @@ TEST(ArenaTest, AddAllocatedToRepeatedField) { TestAllTypes::NestedMessage* arena2_submessage = Arena::CreateMessage(&arena2); arena2_submessage->set_bb(42); - arena1_message->mutable_repeated_nested_message()-> - AddAllocated(arena2_submessage); + arena1_message->mutable_repeated_nested_message()->AddAllocated( + arena2_submessage); // Should copy object. - EXPECT_NE(arena2_submessage, - &arena1_message->repeated_nested_message(i)); + EXPECT_NE(arena2_submessage, &arena1_message->repeated_nested_message(i)); EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb()); } @@ -766,11 +741,10 @@ TEST(ArenaTest, AddAllocatedToRepeatedField) { TestAllTypes::NestedMessage* arena2_submessage = Arena::CreateMessage(&arena2); arena2_submessage->set_bb(42); - heap_message->mutable_repeated_nested_message()-> - AddAllocated(arena2_submessage); + heap_message->mutable_repeated_nested_message()->AddAllocated( + arena2_submessage); // Should copy object. - EXPECT_NE(arena2_submessage, - &heap_message->repeated_nested_message(i)); + EXPECT_NE(arena2_submessage, &heap_message->repeated_nested_message(i)); EXPECT_EQ(42, heap_message->repeated_nested_message(i).bb()); } delete heap_message; @@ -778,9 +752,8 @@ TEST(ArenaTest, AddAllocatedToRepeatedField) { // Heap-arena case for strings (which are not arena-allocated). arena1_message->Clear(); for (int i = 0; i < 10; i++) { - string* s = new string("Test"); - arena1_message->mutable_repeated_string()-> - AddAllocated(s); + std::string* s = new std::string("Test"); + arena1_message->mutable_repeated_string()->AddAllocated(s); // Should not copy. EXPECT_EQ(s, &arena1_message->repeated_string(i)); EXPECT_EQ("Test", arena1_message->repeated_string(i)); @@ -793,16 +766,14 @@ TEST(ArenaTest, AddAllocatedToRepeatedFieldViaReflection) { TestAllTypes* arena1_message = Arena::CreateMessage(&arena1); const Reflection* r = arena1_message->GetReflection(); const Descriptor* d = arena1_message->GetDescriptor(); - const FieldDescriptor* fd = - d->FindFieldByName("repeated_nested_message"); + const FieldDescriptor* fd = d->FindFieldByName("repeated_nested_message"); for (int i = 0; i < 10; i++) { TestAllTypes::NestedMessage* heap_submessage = new TestAllTypes::NestedMessage; heap_submessage->set_bb(42); r->AddAllocatedMessage(arena1_message, fd, heap_submessage); // Should not copy object -- will use arena_->Own(). - EXPECT_EQ(heap_submessage, - &arena1_message->repeated_nested_message(i)); + EXPECT_EQ(heap_submessage, &arena1_message->repeated_nested_message(i)); EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb()); } @@ -815,8 +786,7 @@ TEST(ArenaTest, AddAllocatedToRepeatedFieldViaReflection) { arena2_submessage->set_bb(42); r->AddAllocatedMessage(arena1_message, fd, arena2_submessage); // Should copy object. - EXPECT_NE(arena2_submessage, - &arena1_message->repeated_nested_message(i)); + EXPECT_NE(arena2_submessage, &arena1_message->repeated_nested_message(i)); EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb()); } @@ -829,8 +799,7 @@ TEST(ArenaTest, AddAllocatedToRepeatedFieldViaReflection) { arena2_submessage->set_bb(42); r->AddAllocatedMessage(heap_message, fd, arena2_submessage); // Should copy object. - EXPECT_NE(arena2_submessage, - &heap_message->repeated_nested_message(i)); + EXPECT_NE(arena2_submessage, &heap_message->repeated_nested_message(i)); EXPECT_EQ(42, heap_message->repeated_nested_message(i).bb()); } delete heap_message; @@ -849,9 +818,9 @@ TEST(ArenaTest, ReleaseLastRepeatedField) { } for (int i = 0; i < 10; i++) { - const TestAllTypes::NestedMessage *orig_submessage = + const TestAllTypes::NestedMessage* orig_submessage = &arena_message->repeated_nested_message(10 - 1 - i); // last element - TestAllTypes::NestedMessage *released = + TestAllTypes::NestedMessage* released = arena_message->mutable_repeated_nested_message()->ReleaseLast(); EXPECT_NE(released, orig_submessage); EXPECT_EQ(42, released->bb()); @@ -867,98 +836,61 @@ TEST(ArenaTest, ReleaseLastRepeatedField) { } for (int i = 0; i < 10; i++) { - const TestAllTypes::NestedMessage *orig_submessage = + const TestAllTypes::NestedMessage* orig_submessage = &arena_message->repeated_nested_message(10 - 1 - i); // last element - TestAllTypes::NestedMessage *released = - arena_message->mutable_repeated_nested_message()-> - UnsafeArenaReleaseLast(); + TestAllTypes::NestedMessage* released = + arena_message->mutable_repeated_nested_message() + ->UnsafeArenaReleaseLast(); EXPECT_EQ(released, orig_submessage); EXPECT_EQ(42, released->bb()); // no delete -- |released| is on the arena. } - // Test string case as well. ReleaseLast() in this case must copy the string, - // even though it was originally heap-allocated and its pointer was simply - // appended to the repeated field's internal vector, because the string was - // placed on the arena's destructor list and cannot be removed from that list - // (so the arena permanently owns the original instance). + // Test string case as well. ReleaseLast() in this case must copy the + // string, even though it was originally heap-allocated and its pointer + // was simply appended to the repeated field's internal vector, because the + // string was placed on the arena's destructor list and cannot be removed + // from that list (so the arena permanently owns the original instance). arena_message->Clear(); for (int i = 0; i < 10; i++) { - string* s = new string("Test"); + std::string* s = new std::string("Test"); arena_message->mutable_repeated_string()->AddAllocated(s); } for (int i = 0; i < 10; i++) { - const string* orig_element = &arena_message->repeated_string(10 - 1 - i); - string* released = arena_message->mutable_repeated_string()->ReleaseLast(); + const std::string* orig_element = + &arena_message->repeated_string(10 - 1 - i); + std::string* released = + arena_message->mutable_repeated_string()->ReleaseLast(); EXPECT_NE(released, orig_element); EXPECT_EQ("Test", *released); delete released; } } -TEST(ArenaTest, UnsafeArenaReleaseAdd) { - // Use unsafe_arena_release() and unsafe_arena_set_allocated() to transfer an - // arena-allocated string from one message to another. - Arena arena; - TestAllTypes* message1 = Arena::CreateMessage(&arena); - TestAllTypes* message2 = Arena::CreateMessage(&arena); - string* arena_string = Arena::Create(&arena); - *arena_string = "Test content"; - - message1->unsafe_arena_set_allocated_optional_string(arena_string); - EXPECT_EQ(arena_string, message1->mutable_optional_string()); - message2->unsafe_arena_set_allocated_optional_string( - message1->unsafe_arena_release_optional_string()); - EXPECT_EQ(arena_string, message2->mutable_optional_string()); -} - TEST(ArenaTest, UnsafeArenaAddAllocated) { Arena arena; TestAllTypes* message = Arena::CreateMessage(&arena); for (int i = 0; i < 10; i++) { - string* arena_string = Arena::Create(&arena); + std::string* arena_string = Arena::Create(&arena); message->mutable_repeated_string()->UnsafeArenaAddAllocated(arena_string); EXPECT_EQ(arena_string, message->mutable_repeated_string(i)); } } -TEST(ArenaTest, UnsafeArenaRelease) { - Arena arena; - TestAllTypes* message = Arena::CreateMessage(&arena); - - string* s = new string("test string"); - message->unsafe_arena_set_allocated_optional_string(s); - EXPECT_TRUE(message->has_optional_string()); - EXPECT_EQ("test string", message->optional_string()); - s = message->unsafe_arena_release_optional_string(); - EXPECT_FALSE(message->has_optional_string()); - delete s; - - s = new string("test string"); - message->unsafe_arena_set_allocated_oneof_string(s); - EXPECT_TRUE(message->has_oneof_string()); - EXPECT_EQ("test string", message->oneof_string()); - s = message->unsafe_arena_release_oneof_string(); - EXPECT_FALSE(message->has_oneof_string()); - delete s; -} - TEST(ArenaTest, OneofMerge) { Arena arena; TestAllTypes* message0 = Arena::CreateMessage(&arena); TestAllTypes* message1 = Arena::CreateMessage(&arena); - message0->unsafe_arena_set_allocated_oneof_string(new string("x")); + message0->set_oneof_string("x"); ASSERT_TRUE(message0->has_oneof_string()); - message1->unsafe_arena_set_allocated_oneof_string(new string("y")); + message1->set_oneof_string("y"); ASSERT_TRUE(message1->has_oneof_string()); EXPECT_EQ("x", message0->oneof_string()); EXPECT_EQ("y", message1->oneof_string()); message0->MergeFrom(*message1); EXPECT_EQ("y", message0->oneof_string()); EXPECT_EQ("y", message1->oneof_string()); - delete message0->unsafe_arena_release_oneof_string(); - delete message1->unsafe_arena_release_oneof_string(); } TEST(ArenaTest, ArenaOneofReflection) { @@ -967,12 +899,10 @@ TEST(ArenaTest, ArenaOneofReflection) { const Descriptor* desc = message->GetDescriptor(); const Reflection* refl = message->GetReflection(); - const FieldDescriptor* string_field = desc->FindFieldByName( - "oneof_string"); - const FieldDescriptor* msg_field = desc->FindFieldByName( - "oneof_nested_message"); - const OneofDescriptor* oneof = desc->FindOneofByName( - "oneof_field"); + const FieldDescriptor* string_field = desc->FindFieldByName("oneof_string"); + const FieldDescriptor* msg_field = + desc->FindFieldByName("oneof_nested_message"); + const OneofDescriptor* oneof = desc->FindOneofByName("oneof_field"); refl->SetString(message, string_field, "Test value"); EXPECT_TRUE(refl->HasOneof(*message, oneof)); @@ -1019,8 +949,8 @@ void TestSwapRepeatedField(Arena* arena1, Arena* arena2) { field1.Swap(&field2); EXPECT_EQ(5, field1.size()); EXPECT_EQ(10, field2.size()); - EXPECT_TRUE(string("field1") == field2.Get(0).optional_string()); - EXPECT_TRUE(string("field2") == field1.Get(0).optional_string()); + EXPECT_TRUE(std::string("field1") == field2.Get(0).optional_string()); + EXPECT_TRUE(std::string("field2") == field1.Get(0).optional_string()); // Ensure that fields retained their original order: for (int i = 0; i < field1.size(); i++) { EXPECT_EQ(i, field1.Get(i).optional_int32()); @@ -1056,21 +986,18 @@ TEST(ArenaTest, ExtensionsOnArena) { // Ensure no leaks. TestAllExtensions* message_ext = Arena::CreateMessage(&arena); - message_ext->SetExtension( - protobuf_unittest::optional_int32_extension, 42); - message_ext->SetExtension( - protobuf_unittest::optional_string_extension, string("test")); - message_ext->MutableExtension( - protobuf_unittest::optional_nested_message_extension)->set_bb(42); + message_ext->SetExtension(protobuf_unittest::optional_int32_extension, 42); + message_ext->SetExtension(protobuf_unittest::optional_string_extension, + std::string("test")); + message_ext + ->MutableExtension(protobuf_unittest::optional_nested_message_extension) + ->set_bb(42); } TEST(ArenaTest, RepeatedFieldOnArena) { // Preallocate an initial arena block to avoid mallocs during hooked region. std::vector arena_block(1024 * 1024); - ArenaOptions options; - options.initial_block = &arena_block[0]; - options.initial_block_size = arena_block.size(); - Arena arena(options); + Arena arena(arena_block.data(), arena_block.size()); { internal::NoHeapChecker no_heap; @@ -1124,7 +1051,7 @@ TEST(ArenaTest, RepeatedFieldOnArena) { // code that may allocate messages or repeated fields of messages on an arena. { RepeatedPtrField* repeated_ptr_on_arena = - Arena::CreateMessage< RepeatedPtrField >(&arena); + Arena::CreateMessage >(&arena); for (int i = 0; i < 10; i++) { // Add some elements and let the leak-checker ensure that everything is // freed. @@ -1132,7 +1059,7 @@ TEST(ArenaTest, RepeatedFieldOnArena) { } RepeatedField* repeated_int_on_arena = - Arena::CreateMessage< RepeatedField >(&arena); + Arena::CreateMessage >(&arena); for (int i = 0; i < 100; i++) { repeated_int_on_arena->Add(i); } @@ -1143,7 +1070,7 @@ TEST(ArenaTest, RepeatedFieldOnArena) { } -#ifndef GOOGLE_PROTOBUF_NO_RTTI +#if PROTOBUF_RTTI TEST(ArenaTest, MutableMessageReflection) { Arena arena; TestAllTypes* message = Arena::CreateMessage(&arena); @@ -1159,7 +1086,8 @@ TEST(ArenaTest, MutableMessageReflection) { EXPECT_EQ(submessage_expected, submessage); EXPECT_EQ(&arena, submessage->GetArena()); - const FieldDescriptor* oneof_field = d->FindFieldByName("oneof_nested_message"); + const FieldDescriptor* oneof_field = + d->FindFieldByName("oneof_nested_message"); submessage = static_cast( r->MutableMessage(message, oneof_field)); submessage_expected = message->mutable_oneof_nested_message(); @@ -1167,11 +1095,11 @@ TEST(ArenaTest, MutableMessageReflection) { EXPECT_EQ(submessage_expected, submessage); EXPECT_EQ(&arena, submessage->GetArena()); } -#endif // !GOOGLE_PROTOBUF_NO_RTTI +#endif // PROTOBUF_RTTI void FillArenaAwareFields(TestAllTypes* message) { - string test_string = "hello world"; + std::string test_string = "hello world"; message->set_optional_int32(42); message->set_optional_string(test_string); message->set_optional_bytes(test_string); @@ -1213,7 +1141,7 @@ TEST(ArenaTest, ParseCorruptedString) { TestParseCorruptedString(message); } -#ifndef GOOGLE_PROTOBUF_NO_RTTI +#if PROTOBUF_RTTI // Test construction on an arena via generic MessageLite interface. We should be // able to successfully deserialize on the arena without incurring heap // allocations, i.e., everything should still be arena-allocation-aware. @@ -1223,16 +1151,16 @@ TEST(ArenaTest, MessageLiteOnArena) { options.initial_block = &arena_block[0]; options.initial_block_size = arena_block.size(); Arena arena(options); - const google::protobuf::MessageLite* prototype = &TestAllTypes::default_instance(); + const MessageLite* prototype = &TestAllTypes::default_instance(); TestAllTypes initial_message; FillArenaAwareFields(&initial_message); - string serialized; + std::string serialized; initial_message.SerializeToString(&serialized); { - google::protobuf::MessageLite* generic_message = prototype->New(&arena); + MessageLite* generic_message = prototype->New(&arena); EXPECT_TRUE(generic_message != NULL); EXPECT_EQ(&arena, generic_message->GetArena()); EXPECT_TRUE(generic_message->ParseFromString(serialized)); @@ -1242,22 +1170,21 @@ TEST(ArenaTest, MessageLiteOnArena) { arena.Reset(); } -#endif // !GOOGLE_PROTOBUF_NO_RTTI - +#endif // PROTOBUF_RTTI // RepeatedField should support non-POD types, and invoke constructors and // destructors appropriately, because it's used this way by lots of other code // (even if this was not its original intent). TEST(ArenaTest, RepeatedFieldWithNonPODType) { { - RepeatedField field_on_heap; + RepeatedField field_on_heap; for (int i = 0; i < 100; i++) { *field_on_heap.Add() = "test string long enough to exceed inline buffer"; } } { Arena arena; - RepeatedField field_on_arena(&arena); + RepeatedField field_on_arena(&arena); for (int i = 0; i < 100; i++) { *field_on_arena.Add() = "test string long enough to exceed inline buffer"; } @@ -1268,14 +1195,11 @@ TEST(ArenaTest, RepeatedFieldWithNonPODType) { uint64 Align8(uint64 n) { return (n + 7) & -8; } TEST(ArenaTest, SpaceAllocated_and_Used) { - ArenaOptions options; - options.start_block_size = 256; - options.max_block_size = 8192; - Arena arena_1(options); + Arena arena_1; EXPECT_EQ(0, arena_1.SpaceAllocated()); EXPECT_EQ(0, arena_1.SpaceUsed()); EXPECT_EQ(0, arena_1.Reset()); - ::google::protobuf::Arena::CreateArray(&arena_1, 320); + Arena::CreateArray(&arena_1, 320); // Arena will allocate slightly more than 320 for the block headers. EXPECT_LE(320, arena_1.SpaceAllocated()); EXPECT_EQ(Align8(320), arena_1.SpaceUsed()); @@ -1283,61 +1207,76 @@ TEST(ArenaTest, SpaceAllocated_and_Used) { // Test with initial block. std::vector arena_block(1024); + ArenaOptions options; + options.start_block_size = 256; + options.max_block_size = 8192; options.initial_block = &arena_block[0]; options.initial_block_size = arena_block.size(); Arena arena_2(options); EXPECT_EQ(1024, arena_2.SpaceAllocated()); EXPECT_EQ(0, arena_2.SpaceUsed()); EXPECT_EQ(1024, arena_2.Reset()); - ::google::protobuf::Arena::CreateArray(&arena_2, 55); + Arena::CreateArray(&arena_2, 55); EXPECT_EQ(1024, arena_2.SpaceAllocated()); EXPECT_EQ(Align8(55), arena_2.SpaceUsed()); EXPECT_EQ(1024, arena_2.Reset()); +} + +TEST(ArenaTest, BlockSizeDoubling) { + Arena arena; + EXPECT_EQ(0, arena.SpaceUsed()); + EXPECT_EQ(0, arena.SpaceAllocated()); + + // Allocate something to get initial block size. + Arena::CreateArray(&arena, 1); + auto first_block_size = arena.SpaceAllocated(); + + // Keep allocating until space used increases. + while (arena.SpaceAllocated() == first_block_size) { + Arena::CreateArray(&arena, 1); + } + ASSERT_GT(arena.SpaceAllocated(), first_block_size); + auto second_block_size = (arena.SpaceAllocated() - first_block_size); - // Reset options to test doubling policy explicitly. - options.initial_block = NULL; - options.initial_block_size = 0; - Arena arena_3(options); - EXPECT_EQ(0, arena_3.SpaceUsed()); - ::google::protobuf::Arena::CreateArray(&arena_3, 190); - EXPECT_EQ(256, arena_3.SpaceAllocated()); - EXPECT_EQ(Align8(190), arena_3.SpaceUsed()); - ::google::protobuf::Arena::CreateArray(&arena_3, 70); - EXPECT_EQ(256 + 512, arena_3.SpaceAllocated()); - EXPECT_EQ(Align8(190) + Align8(70), arena_3.SpaceUsed()); - EXPECT_EQ(256 + 512, arena_3.Reset()); + EXPECT_EQ(second_block_size, 2*first_block_size); } TEST(ArenaTest, Alignment) { - ::google::protobuf::Arena arena; + Arena arena; for (int i = 0; i < 200; i++) { - void* p = ::google::protobuf::Arena::CreateArray(&arena, i); + void* p = Arena::CreateArray(&arena, i); GOOGLE_CHECK_EQ(reinterpret_cast(p) % 8, 0) << i << ": " << p; } } TEST(ArenaTest, BlockSizeSmallerThanAllocation) { for (size_t i = 0; i <= 8; ++i) { - ::google::protobuf::ArenaOptions opt; + ArenaOptions opt; opt.start_block_size = opt.max_block_size = i; - ::google::protobuf::Arena arena(opt); + Arena arena(opt); - *::google::protobuf::Arena::Create(&arena) = 42; + *Arena::Create(&arena) = 42; EXPECT_GE(arena.SpaceAllocated(), 8); EXPECT_EQ(8, arena.SpaceUsed()); - *::google::protobuf::Arena::Create(&arena) = 42; + *Arena::Create(&arena) = 42; EXPECT_GE(arena.SpaceAllocated(), 16); EXPECT_EQ(16, arena.SpaceUsed()); } } TEST(ArenaTest, GetArenaShouldReturnTheArenaForArenaAllocatedMessages) { - ::google::protobuf::Arena arena; + Arena arena; ArenaMessage* message = Arena::CreateMessage(&arena); const ArenaMessage* const_pointer_to_message = message; EXPECT_EQ(&arena, Arena::GetArena(message)); EXPECT_EQ(&arena, Arena::GetArena(const_pointer_to_message)); + + // Test that the Message* / MessageLite* specialization SFINAE works. + const Message* const_pointer_to_message_type = message; + EXPECT_EQ(&arena, Arena::GetArena(const_pointer_to_message_type)); + const MessageLite* const_pointer_to_message_lite_type = message; + EXPECT_EQ(&arena, Arena::GetArena(const_pointer_to_message_lite_type)); } TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaAllocatedMessages) { @@ -1347,92 +1286,123 @@ TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaAllocatedMessages) { EXPECT_EQ(NULL, Arena::GetArena(const_pointer_to_message)); } -TEST(ArenaTest, UnsafeSetAllocatedOnArena) { - ::google::protobuf::Arena arena; - TestAllTypes* message = Arena::CreateMessage(&arena); - EXPECT_FALSE(message->has_optional_string()); +TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaCompatibleTypes) { + // Test that GetArena returns nullptr for types that have a GetArena method + // that doesn't return Arena*. + struct { + int GetArena() const { return 0; } + } has_get_arena_method_wrong_return_type; + EXPECT_EQ(nullptr, Arena::GetArena(&has_get_arena_method_wrong_return_type)); + + // Test that GetArena returns nullptr for types that have a GetArena alias. + struct { + using GetArena = Arena*; + GetArena unused; + } has_get_arena_alias; + EXPECT_EQ(nullptr, Arena::GetArena(&has_get_arena_alias)); + + // Test that GetArena returns nullptr for types that have a GetArena data + // member. + struct { + Arena GetArena; + } has_get_arena_data_member; + EXPECT_EQ(nullptr, Arena::GetArena(&has_get_arena_data_member)); +} - string owned_string = "test with long enough content to heap-allocate"; - message->unsafe_arena_set_allocated_optional_string(&owned_string); - EXPECT_TRUE(message->has_optional_string()); +TEST(ArenaTest, AddCleanup) { + Arena arena; + for (int i = 0; i < 100; i++) { + arena.Own(new int); + } +} - message->unsafe_arena_set_allocated_optional_string(NULL); - EXPECT_FALSE(message->has_optional_string()); +namespace { +uint32 hooks_num_init = 0; +uint32 hooks_num_allocations = 0; +uint32 hooks_num_reset = 0; +uint32 hooks_num_destruct = 0; + +void ClearHookCounts() { + hooks_num_init = 0; + hooks_num_allocations = 0; + hooks_num_reset = 0; + hooks_num_destruct = 0; } +} // namespace -// A helper utility class to only contain static hook functions, some -// counters to be used to verify the counters have been called and a cookie -// value to be verified. -class ArenaHooksTestUtil { +// A helper utility class that handles arena callbacks. +class ArenaOptionsTestFriend final : public internal::ArenaMetricsCollector { public: - static void* on_init(::google::protobuf::Arena* arena) { - ++num_init; - int* cookie = new int(kCookieValue); - return static_cast(cookie); + static internal::ArenaMetricsCollector* NewWithAllocs() { + return new ArenaOptionsTestFriend(true); } - static void on_allocation(const std::type_info* /*unused*/, uint64 alloc_size, - void* cookie) { - ++num_allocations; - int cookie_value = *static_cast(cookie); - EXPECT_EQ(kCookieValue, cookie_value); + static internal::ArenaMetricsCollector* NewWithoutAllocs() { + return new ArenaOptionsTestFriend(false); } - static void on_reset(::google::protobuf::Arena* arena, void* cookie, - uint64 space_used) { - ++num_reset; - int cookie_value = *static_cast(cookie); - EXPECT_EQ(kCookieValue, cookie_value); + static void Enable(ArenaOptions* options) { + ClearHookCounts(); + options->make_metrics_collector = &ArenaOptionsTestFriend::NewWithAllocs; } - static void on_destruction(::google::protobuf::Arena* arena, void* cookie, - uint64 space_used) { - ++num_destruct; - int cookie_value = *static_cast(cookie); - EXPECT_EQ(kCookieValue, cookie_value); - delete static_cast(cookie); + static void EnableWithoutAllocs(ArenaOptions* options) { + ClearHookCounts(); + options->make_metrics_collector = &ArenaOptionsTestFriend::NewWithoutAllocs; } - static const int kCookieValue = 999; - static uint32 num_init; - static uint32 num_allocations; - static uint32 num_reset; - static uint32 num_destruct; + explicit ArenaOptionsTestFriend(bool record_allocs) + : ArenaMetricsCollector(record_allocs) { + ++hooks_num_init; + } + void OnDestroy(uint64 space_allocated) override { + ++hooks_num_destruct; + delete this; + } + void OnReset(uint64 space_allocated) override { ++hooks_num_reset; } + void OnAlloc(const std::type_info* allocated_type, + uint64 alloc_size) override { + ++hooks_num_allocations; + } }; -uint32 ArenaHooksTestUtil::num_init = 0; -uint32 ArenaHooksTestUtil::num_allocations = 0; -uint32 ArenaHooksTestUtil::num_reset = 0; -uint32 ArenaHooksTestUtil::num_destruct = 0; -const int ArenaHooksTestUtil::kCookieValue; -// Test the hooks are correctly called and that the cookie is passed. +// Test the hooks are correctly called. TEST(ArenaTest, ArenaHooksSanity) { - ::google::protobuf::ArenaOptions options; - options.on_arena_init = ArenaHooksTestUtil::on_init; - options.on_arena_allocation = ArenaHooksTestUtil::on_allocation; - options.on_arena_reset = ArenaHooksTestUtil::on_reset; - options.on_arena_destruction = ArenaHooksTestUtil::on_destruction; + ArenaOptions options; + ArenaOptionsTestFriend::Enable(&options); // Scope for defining the arena { - ::google::protobuf::Arena arena(options); - EXPECT_EQ(1, ArenaHooksTestUtil::num_init); - EXPECT_EQ(0, ArenaHooksTestUtil::num_allocations); - ::google::protobuf::Arena::Create(&arena); - if (google::protobuf::internal::has_trivial_destructor::value) { - EXPECT_EQ(1, ArenaHooksTestUtil::num_allocations); + Arena arena(options); + EXPECT_EQ(1, hooks_num_init); + EXPECT_EQ(0, hooks_num_allocations); + Arena::Create(&arena); + if (std::is_trivially_destructible::value) { + EXPECT_EQ(1, hooks_num_allocations); } else { - EXPECT_EQ(2, ArenaHooksTestUtil::num_allocations); + EXPECT_EQ(2, hooks_num_allocations); } arena.Reset(); arena.Reset(); - EXPECT_EQ(2, ArenaHooksTestUtil::num_reset); + EXPECT_EQ(2, hooks_num_reset); } - EXPECT_EQ(3, ArenaHooksTestUtil::num_reset); - EXPECT_EQ(1, ArenaHooksTestUtil::num_destruct); + EXPECT_EQ(2, hooks_num_reset); + EXPECT_EQ(1, hooks_num_destruct); +} + +// Test that allocation hooks are not called when we don't need them. +TEST(ArenaTest, ArenaHooksWhenAllocationsNotNeeded) { + ArenaOptions options; + ArenaOptionsTestFriend::EnableWithoutAllocs(&options); + + Arena arena(options); + EXPECT_EQ(0, hooks_num_allocations); + Arena::Create(&arena); + EXPECT_EQ(0, hooks_num_allocations); } -} // namespace } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/arenastring.cc b/src/google/protobuf/arenastring.cc index 7f33a0c8658dc..452d2bfec8468 100644 --- a/src/google/protobuf/arenastring.cc +++ b/src/google/protobuf/arenastring.cc @@ -28,16 +28,229 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// The ArenaString implementation is not included in the open-source release. Do -// not include this file in the distribution. - #include +#include +#include +#include +#include +#include +#include +#include +#include + +// clang-format off +#include +// clang-format on + namespace google { namespace protobuf { namespace internal { +const std::string& LazyString::Init() const { + static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED}; + mu.Lock(); + const std::string* res = inited_.load(std::memory_order_acquire); + if (res == nullptr) { + auto init_value = init_value_; + res = ::new (static_cast(string_buf_)) + std::string(init_value.ptr, init_value.size); + inited_.store(res, std::memory_order_release); + } + mu.Unlock(); + return *res; +} + + +void ArenaStringPtr::Set(const std::string* default_value, + ConstStringParam value, ::google::protobuf::Arena* arena) { + if (IsDefault(default_value)) { + tagged_ptr_.Set(Arena::Create(arena, value)); + } else { + UnsafeMutablePointer()->assign(value.data(), value.length()); + } +} + +void ArenaStringPtr::Set(const std::string* default_value, std::string&& value, + ::google::protobuf::Arena* arena) { + if (IsDefault(default_value)) { + if (arena == nullptr) { + tagged_ptr_.Set(new std::string(std::move(value))); + } else { + tagged_ptr_.Set(Arena::Create(arena, std::move(value))); + } + } else if (IsDonatedString()) { + std::string* current = tagged_ptr_.Get(); + auto* s = new (current) std::string(std::move(value)); + arena->OwnDestructor(s); + tagged_ptr_.Set(s); + } else /* !IsDonatedString() */ { + *UnsafeMutablePointer() = std::move(value); + } +} + +void ArenaStringPtr::Set(EmptyDefault, ConstStringParam value, + ::google::protobuf::Arena* arena) { + Set(&GetEmptyStringAlreadyInited(), value, arena); +} + +void ArenaStringPtr::Set(EmptyDefault, std::string&& value, + ::google::protobuf::Arena* arena) { + Set(&GetEmptyStringAlreadyInited(), std::move(value), arena); +} + +void ArenaStringPtr::Set(NonEmptyDefault, ConstStringParam value, + ::google::protobuf::Arena* arena) { + Set(nullptr, value, arena); +} + +void ArenaStringPtr::Set(NonEmptyDefault, std::string&& value, + ::google::protobuf::Arena* arena) { + Set(nullptr, std::move(value), arena); +} + +std::string* ArenaStringPtr::Mutable(EmptyDefault, ::google::protobuf::Arena* arena) { + if (!IsDonatedString() && !IsDefault(&GetEmptyStringAlreadyInited())) { + return UnsafeMutablePointer(); + } else { + return MutableSlow(arena); + } +} + +std::string* ArenaStringPtr::Mutable(const LazyString& default_value, + ::google::protobuf::Arena* arena) { + if (!IsDonatedString() && !IsDefault(nullptr)) { + return UnsafeMutablePointer(); + } else { + return MutableSlow(arena, default_value); + } +} + +std::string* ArenaStringPtr::MutableNoCopy(const std::string* default_value, + ::google::protobuf::Arena* arena) { + if (!IsDonatedString() && !IsDefault(default_value)) { + return UnsafeMutablePointer(); + } else { + GOOGLE_DCHECK(IsDefault(default_value)); + // Allocate empty. The contents are not relevant. + std::string* new_string = Arena::Create(arena); + tagged_ptr_.Set(new_string); + return new_string; + } +} + +template +std::string* ArenaStringPtr::MutableSlow(::google::protobuf::Arena* arena, + const Lazy&... lazy_default) { + const std::string* const default_value = + sizeof...(Lazy) == 0 ? &GetEmptyStringAlreadyInited() : nullptr; + GOOGLE_DCHECK(IsDefault(default_value)); + std::string* new_string = + Arena::Create(arena, lazy_default.get()...); + tagged_ptr_.Set(new_string); + return new_string; +} + +std::string* ArenaStringPtr::Release(const std::string* default_value, + ::google::protobuf::Arena* arena) { + if (IsDefault(default_value)) { + return nullptr; + } else { + return ReleaseNonDefault(default_value, arena); + } +} + +std::string* ArenaStringPtr::ReleaseNonDefault(const std::string* default_value, + ::google::protobuf::Arena* arena) { + GOOGLE_DCHECK(!IsDefault(default_value)); + + if (!IsDonatedString()) { + std::string* released; + if (arena != nullptr) { + released = new std::string; + released->swap(*UnsafeMutablePointer()); + } else { + released = UnsafeMutablePointer(); + } + tagged_ptr_.Set(const_cast(default_value)); + return released; + } else /* IsDonatedString() */ { + GOOGLE_DCHECK(arena != nullptr); + std::string* released = new std::string(Get()); + tagged_ptr_.Set(const_cast(default_value)); + return released; + } +} + +void ArenaStringPtr::SetAllocated(const std::string* default_value, + std::string* value, ::google::protobuf::Arena* arena) { + // Release what we have first. + if (arena == nullptr && !IsDefault(default_value)) { + delete UnsafeMutablePointer(); + } + if (value == nullptr) { + tagged_ptr_.Set(const_cast(default_value)); + } else { +#ifdef NDEBUG + tagged_ptr_.Set(value); + if (arena != nullptr) { + arena->Own(value); + } +#else + // On debug builds, copy the string so the address differs. delete will + // fail if value was a stack-allocated temporary/etc., which would have + // failed when arena ran its cleanup list. + std::string* new_value = Arena::Create(arena, *value); + delete value; + tagged_ptr_.Set(new_value); +#endif + } +} + +void ArenaStringPtr::Destroy(const std::string* default_value, + ::google::protobuf::Arena* arena) { + if (arena == nullptr) { + GOOGLE_DCHECK(!IsDonatedString()); + if (!IsDefault(default_value)) { + delete UnsafeMutablePointer(); + } + } +} + +void ArenaStringPtr::Destroy(EmptyDefault, ::google::protobuf::Arena* arena) { + Destroy(&GetEmptyStringAlreadyInited(), arena); +} + +void ArenaStringPtr::Destroy(NonEmptyDefault, ::google::protobuf::Arena* arena) { + Destroy(nullptr, arena); +} + +void ArenaStringPtr::ClearToEmpty() { + if (IsDefault(&GetEmptyStringAlreadyInited())) { + // Already set to default -- do nothing. + } else { + // Unconditionally mask away the tag. + // + // UpdateDonatedString uses assign when capacity is larger than the new + // value, which is trivially true in the donated string case. + // const_cast(PtrValue())->clear(); + tagged_ptr_.Get()->clear(); + } +} + +void ArenaStringPtr::ClearToDefault(const LazyString& default_value, + ::google::protobuf::Arena* arena) { + (void)arena; + if (IsDefault(nullptr)) { + // Already set to default -- do nothing. + } else if (!IsDonatedString()) { + UnsafeMutablePointer()->assign(default_value.get()); + } +} + } // namespace internal } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h old mode 100755 new mode 100644 index 63fd00e567f2b..927553c3b55d0 --- a/src/google/protobuf/arenastring.h +++ b/src/google/protobuf/arenastring.h @@ -32,299 +32,350 @@ #define GOOGLE_PROTOBUF_ARENASTRING_H__ #include +#include +#include #include #include -#include #include +#include +#include +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif -// This is the implementation of arena string fields written for the open-source -// release. The ArenaStringPtr struct below is an internal implementation class -// and *should not be used* by user code. It is used to collect string -// operations together into one place and abstract away the underlying -// string-field pointer representation, so that (for example) an alternate -// implementation that knew more about ::std::string's internals could integrate more -// closely with the arena allocator. namespace google { namespace protobuf { namespace internal { -struct LIBPROTOBUF_EXPORT ArenaStringPtr { - inline void Set(const ::std::string* default_value, - const ::std::string& value, ::google::protobuf::Arena* arena) { - if (ptr_ == default_value) { - CreateInstance(arena, &value); - } else { - *ptr_ = value; - } +template +class ExplicitlyConstructed; + +// Lazy string instance to support string fields with non-empty default. +// These are initialized on the first call to .get(). +class PROTOBUF_EXPORT LazyString { + public: + // We explicitly make LazyString an aggregate so that MSVC can do constant + // initialization on it without marking it `constexpr`. + // We do not want to use `constexpr` because it makes it harder to have extern + // storage for it and causes library bloat. + struct InitValue { + const char* ptr; + size_t size; + }; + // We keep a union of the initialization value and the std::string to save on + // space. We don't need the string array after Init() is done. + union { + mutable InitValue init_value_; + alignas(std::string) mutable char string_buf_[sizeof(std::string)]; + }; + mutable std::atomic inited_; + + const std::string& get() const { + // This check generates less code than a call-once invocation. + auto* res = inited_.load(std::memory_order_acquire); + if (PROTOBUF_PREDICT_FALSE(res == nullptr)) return Init(); + return *res; } - // Basic accessors. - inline const ::std::string& Get() const { return *ptr_; } - - inline ::std::string* Mutable(const ::std::string* default_value, - ::google::protobuf::Arena* arena) { - if (ptr_ == default_value) { - CreateInstance(arena, default_value); - } - return ptr_; - } + private: + // Initialize the string in `string_buf_`, update `inited_` and return it. + // We return it here to avoid having to read it again in the inlined code. + const std::string& Init() const; +}; - // Release returns a ::std::string* instance that is heap-allocated and is not - // Own()'d by any arena. If the field was not set, it returns NULL. The caller - // retains ownership. Clears this field back to NULL state. Used to implement - // release_() methods on generated classes. - inline ::std::string* Release(const ::std::string* default_value, - ::google::protobuf::Arena* arena) { - if (ptr_ == default_value) { - return NULL; - } - ::std::string* released = NULL; - if (arena != NULL) { - // ptr_ is owned by the arena -- we need to return a copy. - released = new ::std::string(*ptr_); - } else { - released = ptr_; - } - ptr_ = const_cast< ::std::string* >(default_value); - return released; - } +template +class TaggedPtr { + public: + TaggedPtr() = default; + explicit constexpr TaggedPtr(const ExplicitlyConstructed* ptr) + : ptr_(const_cast*>(ptr)) {} - // UnsafeArenaRelease returns a ::std::string*, but it may be arena-owned (i.e. - // have its destructor already registered) if arena != NULL. If the field was - // not set, this returns NULL. This method clears this field back to NULL - // state. Used to implement unsafe_arena_release_() methods on - // generated classes. - inline ::std::string* UnsafeArenaRelease(const ::std::string* default_value, - ::google::protobuf::Arena* /* arena */) { - if (ptr_ == default_value) { - return NULL; - } - ::std::string* released = ptr_; - ptr_ = const_cast< ::std::string* >(default_value); - return released; + void SetTagged(T* p) { + Set(p); + ptr_ = reinterpret_cast(as_int() | 1); } + void Set(T* p) { ptr_ = p; } + T* Get() const { return reinterpret_cast(as_int() & -2); } + bool IsTagged() const { return as_int() & 1; } - // Takes a string that is heap-allocated, and takes ownership. The string's - // destructor is registered with the arena. Used to implement - // set_allocated_ in generated classes. - inline void SetAllocated(const ::std::string* default_value, - ::std::string* value, ::google::protobuf::Arena* arena) { - if (arena == NULL && ptr_ != default_value) { - Destroy(default_value, arena); - } - if (value != NULL) { - ptr_ = value; - if (arena != NULL) { - arena->Own(value); - } - } else { - ptr_ = const_cast< ::std::string* >(default_value); - } - } + // Returned value is only safe to dereference if IsTagged() == false. + // It is safe to compare. + T* UnsafeGet() const { return static_cast(ptr_); } + + bool IsNull() { return ptr_ == nullptr; } - // Takes a string that has lifetime equal to the arena's lifetime. The arena - // must be non-null. It is safe only to pass this method a value returned by - // UnsafeArenaRelease() on another field of a message in the same arena. Used - // to implement unsafe_arena_set_allocated_ in generated classes. - inline void UnsafeArenaSetAllocated(const ::std::string* default_value, - ::std::string* value, - ::google::protobuf::Arena* /* arena */) { - if (value != NULL) { - ptr_ = value; - } else { - ptr_ = const_cast< ::std::string* >(default_value); - } + private: + uintptr_t as_int() const { return reinterpret_cast(ptr_); } + void* ptr_; +}; + +static_assert(std::is_trivial>::value, + "TaggedPtr must be trivial"); + +// This class encapsulates a pointer to a std::string with or without a donated +// buffer, tagged by bottom bit. It is a high-level wrapper that almost directly +// corresponds to the interface required by string fields in generated +// code. It replaces the old std::string* pointer in such cases. +// +// The object has different but similar code paths for when the default value is +// the empty string and when it is a non-empty string. +// The empty string is handled different throughout the library and there is a +// single global instance of it we can share. +// +// For fields with an empty string default value, there are three distinct +// states: +// +// - Pointer set to 'String' tag (LSB is 0), equal to +// &GetEmptyStringAlreadyInited(): field is set to its default value. Points +// to a true std::string*, but we do not own that std::string* (it's a +// globally shared instance). +// +// - Pointer set to 'String' tag (LSB is 0), but not equal to the global empty +// string: field points to a true std::string* instance that we own. This +// instance is either on the heap or on the arena (i.e. registered on +// free()/destructor-call list) as appropriate. +// +// - Pointer set to 'DonatedString' tag (LSB is 1): points to a std::string +// instance with a buffer on the arena (arena != NULL, always, in this case). +// +// For fields with a non-empty string default value, there are three distinct +// states: +// +// - Pointer set to 'String' tag (LSB is 0), equal to `nullptr`: +// Field is in "default" mode and does not point to any actual instance. +// Methods that might need to create an instance of the object will pass a +// `const LazyString&` for it. +// +// - Pointer set to 'String' tag (LSB is 0), but not equal to `nullptr`: +// field points to a true std::string* instance that we own. This instance is +// either on the heap or on the arena (i.e. registered on +// free()/destructor-call list) as appropriate. +// +// - Pointer set to 'DonatedString' tag (LSB is 1): points to a std::string +// instance with a buffer on the arena (arena != NULL, always, in this case). +// +// Generated code and reflection code both ensure that ptr_ is never null for +// fields with an empty default. +// Because ArenaStringPtr is used in oneof unions, its constructor is a NOP and +// so the field is always manually initialized via method calls. +// +// Side-note: why pass information about the default on every API call? Because +// we don't want to hold it in a member variable, or else this would go into +// every proto message instance. This would be a huge waste of space, since the +// default instance pointer is typically a global (static class field). We want +// the generated code to be as efficient as possible, and if we take +// the default value information as a parameter that's in practice taken from a +// static class field, and compare ptr_ to the default value, we end up with a +// single "cmp %reg, GLOBAL" in the resulting machine code. (Note that this also +// requires the String tag to be 0 so we can avoid the mask before comparing.) +struct PROTOBUF_EXPORT ArenaStringPtr { + ArenaStringPtr() = default; + explicit constexpr ArenaStringPtr( + const ExplicitlyConstructed* default_value) + : tagged_ptr_(default_value) {} + + // Some methods below are overloaded on a `default_value` and on tags. + // The tagged overloads help reduce code size in the callers in generated + // code, while the `default_value` overloads are useful from reflection. + // By-value empty struct arguments are elided in the ABI. + struct EmptyDefault {}; + struct NonEmptyDefault {}; + + void Set(const std::string* default_value, ConstStringParam value, + ::google::protobuf::Arena* arena); + void Set(const std::string* default_value, std::string&& value, + ::google::protobuf::Arena* arena); + void Set(EmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena); + void Set(EmptyDefault, std::string&& value, ::google::protobuf::Arena* arena); + void Set(NonEmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena); + void Set(NonEmptyDefault, std::string&& value, ::google::protobuf::Arena* arena); + + // Basic accessors. + const std::string& Get() const PROTOBUF_NDEBUG_INLINE { + // Unconditionally mask away the tag. + return *tagged_ptr_.Get(); + } + const std::string* GetPointer() const PROTOBUF_NDEBUG_INLINE { + // Unconditionally mask away the tag. + return tagged_ptr_.Get(); } + // For fields with an empty default value. + std::string* Mutable(EmptyDefault, ::google::protobuf::Arena* arena); + // For fields with a non-empty default value. + std::string* Mutable(const LazyString& default_value, ::google::protobuf::Arena* arena); + + // Release returns a std::string* instance that is heap-allocated and is not + // Own()'d by any arena. If the field is not set, this returns NULL. The + // caller retains ownership. Clears this field back to NULL state. Used to + // implement release_() methods on generated classes. + std::string* Release(const std::string* default_value, + ::google::protobuf::Arena* arena); + std::string* ReleaseNonDefault(const std::string* default_value, + ::google::protobuf::Arena* arena); + + // Takes a std::string that is heap-allocated, and takes ownership. The + // std::string's destructor is registered with the arena. Used to implement + // set_allocated_ in generated classes. + void SetAllocated(const std::string* default_value, std::string* value, + ::google::protobuf::Arena* arena); + // Swaps internal pointers. Arena-safety semantics: this is guarded by the // logic in Swap()/UnsafeArenaSwap() at the message level, so this method is // 'unsafe' if called directly. - GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) { - std::swap(ptr_, other->ptr_); - } + inline void Swap(ArenaStringPtr* other, const std::string* default_value, + Arena* arena) PROTOBUF_NDEBUG_INLINE; // Frees storage (if not on an arena). - inline void Destroy(const ::std::string* default_value, - ::google::protobuf::Arena* arena) { - if (arena == NULL && ptr_ != default_value) { - delete ptr_; - } - } + void Destroy(const std::string* default_value, ::google::protobuf::Arena* arena); + void Destroy(EmptyDefault, ::google::protobuf::Arena* arena); + void Destroy(NonEmptyDefault, ::google::protobuf::Arena* arena); - // Clears content, but keeps allocated string if arena != NULL, to avoid the - // overhead of heap operations. After this returns, the content (as seen by - // the user) will always be the empty string. Assumes that |default_value| - // is an empty string. - inline void ClearToEmpty(const ::std::string* default_value, - ::google::protobuf::Arena* /* arena */) { - if (ptr_ == default_value) { - // Already set to default (which is empty) -- do nothing. - } else { - ptr_->clear(); - } - } + // Clears content, but keeps allocated std::string, to avoid the overhead of + // heap operations. After this returns, the content (as seen by the user) will + // always be the empty std::string. Assumes that |default_value| is an empty + // std::string. + void ClearToEmpty(); - // Clears content, but keeps allocated string if arena != NULL, to avoid the - // overhead of heap operations. After this returns, the content (as seen by - // the user) will always be equal to |default_value|. - inline void ClearToDefault(const ::std::string* default_value, - ::google::protobuf::Arena* /* arena */) { - if (ptr_ == default_value) { - // Already set to default -- do nothing. - } else { - // Have another allocated string -- rather than throwing this away and - // resetting ptr_ to the canonical default string instance, we just reuse - // this instance. - *ptr_ = *default_value; - } - } + // Clears content, assuming that the current value is not the empty + // string default. + void ClearNonDefaultToEmpty(); + + // Clears content, but keeps allocated std::string if arena != NULL, to avoid + // the overhead of heap operations. After this returns, the content (as seen + // by the user) will always be equal to |default_value|. + void ClearToDefault(const LazyString& default_value, ::google::protobuf::Arena* arena); // Called from generated code / reflection runtime only. Resets value to point - // to a default string pointer, with the semantics that this ArenaStringPtr - // does not own the pointed-to memory. Disregards initial value of ptr_ (so - // this is the *ONLY* safe method to call after construction or when - // reinitializing after becoming the active field in a oneof union). - inline void UnsafeSetDefault(const ::std::string* default_value) { - // Casting away 'const' is safe here: accessors ensure that ptr_ is only - // returned as a const if it is equal to default_value. - ptr_ = const_cast< ::std::string* >(default_value); + // to a default string pointer, with the semantics that this + // ArenaStringPtr does not own the pointed-to memory. Disregards initial value + // of ptr_ (so this is the *ONLY* safe method to call after construction or + // when reinitializing after becoming the active field in a oneof union). + inline void UnsafeSetDefault(const std::string* default_value); + + // Returns a mutable pointer, but doesn't initialize the string to the + // default value. + std::string* MutableNoArenaNoDefault(const std::string* default_value); + + // Get a mutable pointer with unspecified contents. + // Similar to `MutableNoArenaNoDefault`, but also handles the arena case. + // If the value was donated, the contents are discarded. + std::string* MutableNoCopy(const std::string* default_value, + ::google::protobuf::Arena* arena); + + // Destroy the string. Assumes `arena == nullptr`. + void DestroyNoArena(const std::string* default_value); + + // Internal setter used only at parse time to directly set a donated string + // value. + void UnsafeSetTaggedPointer(TaggedPtr value) { + tagged_ptr_ = value; } - - // The 'NoArena' variants of methods below assume arena == NULL and are - // optimized to provide very little overhead relative to a raw string pointer - // (while still being in-memory compatible with other code that assumes - // ArenaStringPtr). Note the invariant that a class instance that has only - // ever been mutated by NoArena methods must *only* be in the String state - // (i.e., tag bits are not used), *NEVER* ArenaString. This allows all - // tagged-pointer manipulations to be avoided. - inline void SetNoArena(const ::std::string* default_value, - const ::std::string& value) { - if (ptr_ == default_value) { - CreateInstanceNoArena(&value); - } else { - *ptr_ = value; - } + // Generated code only! An optimization, in certain cases the generated + // code is certain we can obtain a std::string with no default checks and + // tag tests. + std::string* UnsafeMutablePointer() PROTOBUF_RETURNS_NONNULL; + + inline bool IsDefault(const std::string* default_value) const { + // Relies on the fact that kPtrTagString == 0, so if IsString(), ptr_ is the + // actual std::string pointer (and if !IsString(), ptr_ will never be equal + // to any aligned |default_value| pointer). The key is that we want to avoid + // masking in the fastpath const-pointer Get() case for non-arena code. + return tagged_ptr_.UnsafeGet() == default_value; } -#if LANG_CXX11 - void SetNoArena(const ::std::string* default_value, ::std::string&& value) { - if (IsDefault(default_value)) { - ptr_ = new ::std::string(std::move(value)); - } else { - *ptr_ = std::move(value); - } - } -#endif + private: + TaggedPtr tagged_ptr_; - void AssignWithDefault(const ::std::string* default_value, ArenaStringPtr value); + bool IsDonatedString() const { return false; } - inline const ::std::string& GetNoArena() const { return *ptr_; } + // Slow paths. - inline ::std::string* MutableNoArena(const ::std::string* default_value) { - if (ptr_ == default_value) { - CreateInstanceNoArena(default_value); - } - return ptr_; - } + // MutableSlow requires that !IsString() || IsDefault + // Variadic to support 0 args for EmptyDefault and 1 arg for LazyString. + template + std::string* MutableSlow(::google::protobuf::Arena* arena, const Lazy&... lazy_default); - inline ::std::string* ReleaseNoArena(const ::std::string* default_value) { - if (ptr_ == default_value) { - return NULL; - } else { - ::std::string* released = ptr_; - ptr_ = const_cast< ::std::string* >(default_value); - return released; - } - } +}; - inline void SetAllocatedNoArena(const ::std::string* default_value, - ::std::string* value) { - if (ptr_ != default_value) { - delete ptr_; - } - if (value != NULL) { - ptr_ = value; - } else { - ptr_ = const_cast< ::std::string* >(default_value); - } - } +inline void ArenaStringPtr::UnsafeSetDefault(const std::string* value) { + tagged_ptr_.Set(const_cast(value)); +} - inline void DestroyNoArena(const ::std::string* default_value) { - if (ptr_ != default_value) { - delete ptr_; - } +inline void ArenaStringPtr::Swap(ArenaStringPtr* other, + const std::string* default_value, + Arena* arena) { +#ifndef NDEBUG + // For debug builds, we swap the contents of the string, rather than the + // std::string instances themselves. This invalidates previously taken const + // references that are (per our documentation) invalidated by calling Swap() + // on the message. + // + // If both strings are the default_value, swapping is uninteresting. + // Otherwise, we use ArenaStringPtr::Mutable() to access the std::string, to + // ensure that we do not try to mutate default_value itself. + if (IsDefault(default_value) && other->IsDefault(default_value)) { + return; } - inline void ClearToEmptyNoArena(const ::std::string* default_value) { - if (ptr_ == default_value) { - // Nothing: already equal to default (which is the empty string). - } else { - ptr_->clear(); - } - } + if (default_value == nullptr) { + // If we have non-empty default, then `default_value` is null and we can't + // call Mutable the same way. Just do the regular swap. + std::swap(tagged_ptr_, other->tagged_ptr_); + } else { + std::string* this_ptr = Mutable(EmptyDefault{}, arena); + std::string* other_ptr = other->Mutable(EmptyDefault{}, arena); - inline void ClearToDefaultNoArena(const ::std::string* default_value) { - if (ptr_ == default_value) { - // Nothing: already set to default. - } else { - // Reuse existing allocated instance. - *ptr_ = *default_value; - } + this_ptr->swap(*other_ptr); } +#else + (void)default_value; + (void)arena; + std::swap(tagged_ptr_, other->tagged_ptr_); +#endif +} - // Internal accessor used only at parse time to provide direct access to the - // raw pointer from the shared parse routine (in the non-arenas case). The - // parse routine does the string allocation in order to save code size in the - // generated parsing code. - inline ::std::string** UnsafeRawStringPointer() { - return &ptr_; - } +inline void ArenaStringPtr::ClearNonDefaultToEmpty() { + // Unconditionally mask away the tag. + tagged_ptr_.Get()->clear(); +} - inline bool IsDefault(const ::std::string* default_value) const { - return ptr_ == default_value; +inline std::string* ArenaStringPtr::MutableNoArenaNoDefault( + const std::string* default_value) { + // VERY IMPORTANT for performance and code size: this will reduce to a member + // variable load, a pointer check (against |default_value|, in practice a + // static global) and a branch to the slowpath (which calls operator new and + // the ctor). DO NOT add any tagged-pointer operations here. + if (IsDefault(default_value)) { + std::string* new_string = new std::string(); + tagged_ptr_.Set(new_string); + return new_string; + } else { + return UnsafeMutablePointer(); } +} - private: - ::std::string* ptr_; - - GOOGLE_ATTRIBUTE_NOINLINE void CreateInstance(::google::protobuf::Arena* arena, - const ::std::string* initial_value) { - GOOGLE_DCHECK(initial_value != NULL); - ptr_ = new ::std::string(*initial_value); - if (arena != NULL) { - arena->Own(ptr_); - } +inline void ArenaStringPtr::DestroyNoArena(const std::string* default_value) { + if (!IsDefault(default_value)) { + delete UnsafeMutablePointer(); } - GOOGLE_ATTRIBUTE_NOINLINE void CreateInstanceNoArena(const ::std::string* initial_value) { - GOOGLE_DCHECK(initial_value != NULL); - ptr_ = new ::std::string(*initial_value); - } -}; - -} // namespace internal -} // namespace protobuf - - - -namespace protobuf { -namespace internal { +} -inline void ArenaStringPtr::AssignWithDefault(const ::std::string* default_value, - ArenaStringPtr value) { - const ::std::string* me = *UnsafeRawStringPointer(); - const ::std::string* other = *value.UnsafeRawStringPointer(); - // If the pointers are the same then do nothing. - if (me != other) { - SetNoArena(default_value, value.GetNoArena()); - } +inline std::string* ArenaStringPtr::UnsafeMutablePointer() { + GOOGLE_DCHECK(!tagged_ptr_.IsTagged()); + GOOGLE_DCHECK(tagged_ptr_.UnsafeGet() != nullptr); + return tagged_ptr_.UnsafeGet(); } + } // namespace internal } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_ARENASTRING_H__ diff --git a/src/google/protobuf/arenastring_unittest.cc b/src/google/protobuf/arenastring_unittest.cc index c330b9031fe9c..bd4b4d8452a49 100644 --- a/src/google/protobuf/arenastring_unittest.cc +++ b/src/google/protobuf/arenastring_unittest.cc @@ -28,88 +28,151 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Based on mvels@'s frankenstring. - #include #include #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include #include #include -#include #include #include +#include +#include +#include +#include -namespace google { -using google::protobuf::internal::ArenaString; -using google::protobuf::internal::ArenaStringPtr; +// Must be included last. +#include +namespace google { namespace protobuf { +using internal::ArenaStringPtr; -static string WrapString(const char* value) { - return value; -} +static std::string WrapString(const char* value) { return value; } + +using EmptyDefault = ArenaStringPtr::EmptyDefault; + +const internal::LazyString nonempty_default{{{"default", 7}}, {nullptr}}; // Test ArenaStringPtr with arena == NULL. TEST(ArenaStringPtrTest, ArenaStringPtrOnHeap) { ArenaStringPtr field; - ::std::string default_value = "default"; - field.UnsafeSetDefault(&default_value); - EXPECT_EQ(string("default"), field.Get()); - field.Set(&default_value, WrapString("Test short"), NULL); - EXPECT_EQ(string("Test short"), field.Get()); - field.Set(&default_value, WrapString("Test long long long long value"), NULL); - EXPECT_EQ(string("Test long long long long value"), field.Get()); - field.Set(&default_value, string(""), NULL); - field.Destroy(&default_value, NULL); + const std::string* empty_default = &internal::GetEmptyString(); + field.UnsafeSetDefault(empty_default); + EXPECT_EQ(std::string(""), field.Get()); + field.Set(empty_default, WrapString("Test short"), NULL); + EXPECT_EQ(std::string("Test short"), field.Get()); + field.Set(empty_default, WrapString("Test long long long long value"), NULL); + EXPECT_EQ(std::string("Test long long long long value"), field.Get()); + field.Set(empty_default, std::string(""), NULL); + field.Destroy(empty_default, NULL); ArenaStringPtr field2; - field2.UnsafeSetDefault(&default_value); - ::std::string* mut = field2.Mutable(&default_value, NULL); - EXPECT_EQ(mut, field2.Mutable(&default_value, NULL)); + field2.UnsafeSetDefault(empty_default); + std::string* mut = field2.Mutable(EmptyDefault{}, NULL); + EXPECT_EQ(mut, field2.Mutable(EmptyDefault{}, NULL)); EXPECT_EQ(mut, &field2.Get()); - EXPECT_NE(&default_value, mut); - EXPECT_EQ(string("default"), *mut); + EXPECT_NE(empty_default, mut); + EXPECT_EQ(std::string(""), *mut); + *mut = "Test long long long long value"; // ensure string allocates storage + EXPECT_EQ(std::string("Test long long long long value"), field2.Get()); + field2.Destroy(empty_default, NULL); + + ArenaStringPtr field3; + field3.UnsafeSetDefault(nullptr); + mut = field3.Mutable(nonempty_default, NULL); + EXPECT_EQ(mut, field3.Mutable(nonempty_default, NULL)); + EXPECT_EQ(mut, &field3.Get()); + EXPECT_NE(nullptr, mut); + EXPECT_EQ(std::string("default"), *mut); *mut = "Test long long long long value"; // ensure string allocates storage - EXPECT_EQ(string("Test long long long long value"), field2.Get()); - field2.Destroy(&default_value, NULL); + EXPECT_EQ(std::string("Test long long long long value"), field3.Get()); + field3.Destroy(nullptr, NULL); } TEST(ArenaStringPtrTest, ArenaStringPtrOnArena) { - google::protobuf::Arena arena; + Arena arena; + ArenaStringPtr field; + const std::string* empty_default = &internal::GetEmptyString(); + field.UnsafeSetDefault(empty_default); + EXPECT_EQ(std::string(""), field.Get()); + field.Set(empty_default, WrapString("Test short"), &arena); + EXPECT_EQ(std::string("Test short"), field.Get()); + field.Set(empty_default, WrapString("Test long long long long value"), + &arena); + EXPECT_EQ(std::string("Test long long long long value"), field.Get()); + field.Set(empty_default, std::string(""), &arena); + field.Destroy(empty_default, &arena); + + ArenaStringPtr field2; + field2.UnsafeSetDefault(empty_default); + std::string* mut = field2.Mutable(EmptyDefault{}, &arena); + EXPECT_EQ(mut, field2.Mutable(EmptyDefault{}, &arena)); + EXPECT_EQ(mut, &field2.Get()); + EXPECT_NE(empty_default, mut); + EXPECT_EQ(std::string(""), *mut); + *mut = "Test long long long long value"; // ensure string allocates storage + EXPECT_EQ(std::string("Test long long long long value"), field2.Get()); + field2.Destroy(empty_default, &arena); + + ArenaStringPtr field3; + field3.UnsafeSetDefault(nullptr); + mut = field3.Mutable(nonempty_default, &arena); + EXPECT_EQ(mut, field3.Mutable(nonempty_default, &arena)); + EXPECT_EQ(mut, &field3.Get()); + EXPECT_NE(nullptr, mut); + EXPECT_EQ(std::string("default"), *mut); + *mut = "Test long long long long value"; // ensure string allocates storage + EXPECT_EQ(std::string("Test long long long long value"), field3.Get()); + field3.Destroy(nullptr, &arena); +} + +TEST(ArenaStringPtrTest, ArenaStringPtrOnArenaNoSSO) { + Arena arena; ArenaStringPtr field; - ::std::string default_value = "default"; - field.UnsafeSetDefault(&default_value); - EXPECT_EQ(string("default"), field.Get()); - field.Set(&default_value, WrapString("Test short"), &arena); - EXPECT_EQ(string("Test short"), field.Get()); - field.Set(&default_value, WrapString("Test long long long long value"), + const std::string* empty_default = &internal::GetEmptyString(); + field.UnsafeSetDefault(empty_default); + EXPECT_EQ(std::string(""), field.Get()); + + // Avoid triggering the SSO optimization by setting the string to something + // larger than the internal buffer. + field.Set(empty_default, WrapString("Test long long long long value"), &arena); - EXPECT_EQ(string("Test long long long long value"), field.Get()); - field.Set(&default_value, string(""), &arena); - field.Destroy(&default_value, &arena); + EXPECT_EQ(std::string("Test long long long long value"), field.Get()); + field.Set(empty_default, std::string(""), &arena); + field.Destroy(empty_default, &arena); ArenaStringPtr field2; - field2.UnsafeSetDefault(&default_value); - ::std::string* mut = field2.Mutable(&default_value, &arena); - EXPECT_EQ(mut, field2.Mutable(&default_value, &arena)); + field2.UnsafeSetDefault(empty_default); + std::string* mut = field2.Mutable(EmptyDefault{}, &arena); + EXPECT_EQ(mut, field2.Mutable(EmptyDefault{}, &arena)); EXPECT_EQ(mut, &field2.Get()); - EXPECT_NE(&default_value, mut); - EXPECT_EQ(string("default"), *mut); + EXPECT_NE(empty_default, mut); + EXPECT_EQ(std::string(""), *mut); *mut = "Test long long long long value"; // ensure string allocates storage - EXPECT_EQ(string("Test long long long long value"), field2.Get()); - field2.Destroy(&default_value, &arena); + EXPECT_EQ(std::string("Test long long long long value"), field2.Get()); + field2.Destroy(empty_default, &arena); + + ArenaStringPtr field3; + field3.UnsafeSetDefault(nullptr); + mut = field3.Mutable(nonempty_default, &arena); + EXPECT_EQ(mut, field3.Mutable(nonempty_default, &arena)); + EXPECT_EQ(mut, &field3.Get()); + EXPECT_NE(nullptr, mut); + EXPECT_EQ(std::string("default"), *mut); + *mut = "Test long long long long value"; // ensure string allocates storage + EXPECT_EQ(std::string("Test long long long long value"), field3.Get()); + field3.Destroy(nullptr, &arena); } } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/compiler/annotation_test_util.cc b/src/google/protobuf/compiler/annotation_test_util.cc new file mode 100644 index 0000000000000..fb659f627f512 --- /dev/null +++ b/src/google/protobuf/compiler/annotation_test_util.cc @@ -0,0 +1,167 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace annotation_test_util { +namespace { + +// A CodeGenerator that captures the FileDescriptor it's passed as a +// FileDescriptorProto. +class DescriptorCapturingGenerator : public CodeGenerator { + public: + // Does not own file; file must outlive the Generator. + explicit DescriptorCapturingGenerator(FileDescriptorProto* file) + : file_(file) {} + + virtual bool Generate(const FileDescriptor* file, + const std::string& parameter, GeneratorContext* context, + std::string* error) const { + file->CopyTo(file_); + return true; + } + + private: + FileDescriptorProto* file_; +}; +} // namespace + +void AddFile(const std::string& filename, const std::string& data) { + GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/" + filename, data, + true)); +} + +bool RunProtoCompiler(const std::string& filename, + const std::string& plugin_specific_args, + CommandLineInterface* cli, FileDescriptorProto* file) { + cli->SetInputsAreProtoPathRelative(true); + + DescriptorCapturingGenerator capturing_generator(file); + cli->RegisterGenerator("--capture_out", &capturing_generator, ""); + + std::string proto_path = "-I" + TestTempDir(); + std::string capture_out = "--capture_out=" + TestTempDir(); + + const char* argv[] = {"protoc", proto_path.c_str(), + plugin_specific_args.c_str(), capture_out.c_str(), + filename.c_str()}; + + return cli->Run(5, argv) == 0; +} + +bool DecodeMetadata(const std::string& path, GeneratedCodeInfo* info) { + std::string data; + GOOGLE_CHECK_OK(File::GetContents(path, &data, true)); + io::ArrayInputStream input(data.data(), data.size()); + return info->ParseFromZeroCopyStream(&input); +} + +void FindAnnotationsOnPath( + const GeneratedCodeInfo& info, const std::string& source_file, + const std::vector& path, + std::vector* annotations) { + for (int i = 0; i < info.annotation_size(); ++i) { + const GeneratedCodeInfo::Annotation* annotation = &info.annotation(i); + if (annotation->source_file() != source_file || + annotation->path_size() != path.size()) { + continue; + } + int node = 0; + for (; node < path.size(); ++node) { + if (annotation->path(node) != path[node]) { + break; + } + } + if (node == path.size()) { + annotations->push_back(annotation); + } + } +} + +const GeneratedCodeInfo::Annotation* FindAnnotationOnPath( + const GeneratedCodeInfo& info, const std::string& source_file, + const std::vector& path) { + std::vector annotations; + FindAnnotationsOnPath(info, source_file, path, &annotations); + if (annotations.empty()) { + return NULL; + } + return annotations[0]; +} + +bool AtLeastOneAnnotationMatchesSubstring( + const std::string& file_content, + const std::vector& annotations, + const std::string& expected_text) { + for (std::vector::const_iterator + i = annotations.begin(), + e = annotations.end(); + i != e; ++i) { + const GeneratedCodeInfo::Annotation* annotation = *i; + uint32 begin = annotation->begin(); + uint32 end = annotation->end(); + if (end < begin || end > file_content.size()) { + return false; + } + if (file_content.substr(begin, end - begin) == expected_text) { + return true; + } + } + return false; +} + +bool AnnotationMatchesSubstring(const std::string& file_content, + const GeneratedCodeInfo::Annotation* annotation, + const std::string& expected_text) { + std::vector annotations; + annotations.push_back(annotation); + return AtLeastOneAnnotationMatchesSubstring(file_content, annotations, + expected_text); +} +} // namespace annotation_test_util +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/annotation_test_util.h b/src/google/protobuf/compiler/annotation_test_util.h new file mode 100644 index 0000000000000..fa87c6cc88e41 --- /dev/null +++ b/src/google/protobuf/compiler/annotation_test_util.h @@ -0,0 +1,115 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__ +#define GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__ + +#include +#include +#include + +// Utilities that assist in writing tests for generator annotations. +// See java/internal/annotation_unittest.cc for an example. +namespace google { +namespace protobuf { +namespace compiler { +namespace annotation_test_util { + +// Struct that contains the file generated from a .proto file and its +// GeneratedCodeInfo. For example, the Java generator will fill this struct +// (for some 'foo.proto') with: +// file_path = "Foo.java" +// file_content = content of Foo.java +// file_info = parsed content of Foo.java.pb.meta +struct ExpectedOutput { + std::string file_path; + std::string file_content; + GeneratedCodeInfo file_info; + explicit ExpectedOutput(const std::string& file_path) + : file_path(file_path) {} +}; + +// Creates a file with name `filename` and content `data` in temp test +// directory. +void AddFile(const std::string& filename, const std::string& data); + +// Runs proto compiler. Captures proto file structure in FileDescriptorProto. +// Files will be generated in TestTempDir() folder. Callers of this +// function must read generated files themselves. +// +// filename: source .proto file used to generate code. +// plugin_specific_args: command line arguments specific to current generator. +// For Java, this value might be "--java_out=annotate_code:test_temp_dir" +// cli: instance of command line interface to run generator. See Java's +// annotation_unittest.cc for an example of how to initialize it. +// file: output parameter, will be set to the descriptor of the proto file +// specified in filename. +bool RunProtoCompiler(const std::string& filename, + const std::string& plugin_specific_args, + CommandLineInterface* cli, FileDescriptorProto* file); + +bool DecodeMetadata(const std::string& path, GeneratedCodeInfo* info); + +// Finds all of the Annotations for a given source file and path. +// See Location.path in http://google3/net/proto2/proto/descriptor.proto for +// explanation of what path vector is. +void FindAnnotationsOnPath( + const GeneratedCodeInfo& info, const std::string& source_file, + const std::vector& path, + std::vector* annotations); + +// Finds the Annotation for a given source file and path (or returns null if it +// couldn't). If there are several annotations for given path, returns the first +// one. See Location.path in +// http://google3/net/proto2/proto/descriptor.proto for explanation of what path +// vector is. +const GeneratedCodeInfo::Annotation* FindAnnotationOnPath( + const GeneratedCodeInfo& info, const std::string& source_file, + const std::vector& path); + +// Returns true if at least one of the provided annotations covers a given +// substring in file_content. +bool AtLeastOneAnnotationMatchesSubstring( + const std::string& file_content, + const std::vector& annotations, + const std::string& expected_text); + +// Returns true if the provided annotation covers a given substring in +// file_content. +bool AnnotationMatchesSubstring(const std::string& file_content, + const GeneratedCodeInfo::Annotation* annotation, + const std::string& expected_text); + +} // namespace annotation_test_util +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__ diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc index 11d0f33432c9d..4544f3e710576 100644 --- a/src/google/protobuf/compiler/code_generator.cc +++ b/src/google/protobuf/compiler/code_generator.cc @@ -34,9 +34,9 @@ #include -#include #include #include +#include #include #include @@ -46,20 +46,20 @@ namespace compiler { CodeGenerator::~CodeGenerator() {} -bool CodeGenerator::GenerateAll( - const std::vector& files, - const string& parameter, - GeneratorContext* generator_context, - string* error) const { - // Default implemenation is just to call the per file method, and prefix any +bool CodeGenerator::GenerateAll(const std::vector& files, + const std::string& parameter, + GeneratorContext* generator_context, + std::string* error) const { + // Default implementation is just to call the per file method, and prefix any // error string with the file to provide context. bool succeeded = true; for (int i = 0; i < files.size(); i++) { const FileDescriptor* file = files[i]; succeeded = Generate(file, parameter, generator_context, error); if (!succeeded && error && error->empty()) { - *error = "Code generator returned false but provided no error " - "description."; + *error = + "Code generator returned false but provided no error " + "description."; } if (error && !error->empty()) { *error = file->name() + ": " + *error; @@ -74,17 +74,23 @@ bool CodeGenerator::GenerateAll( GeneratorContext::~GeneratorContext() {} -io::ZeroCopyOutputStream* -GeneratorContext::OpenForAppend(const string& filename) { +io::ZeroCopyOutputStream* GeneratorContext::OpenForAppend( + const std::string& filename) { return NULL; } io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert( - const string& filename, const string& insertion_point) { + const std::string& filename, const std::string& insertion_point) { GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion."; return NULL; // make compiler happy } +io::ZeroCopyOutputStream* GeneratorContext::OpenForInsertWithGeneratedCodeInfo( + const std::string& filename, const std::string& insertion_point, + const google::protobuf::GeneratedCodeInfo& /*info*/) { + return OpenForInsert(filename, insertion_point); +} + void GeneratorContext::ListParsedFiles( std::vector* output) { GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles"; @@ -98,14 +104,15 @@ void GeneratorContext::GetCompilerVersion(Version* version) const { } // Parses a set of comma-delimited name/value pairs. -void ParseGeneratorParameter(const string& text, - std::vector >* output) { - std::vector parts = Split(text, ",", true); +void ParseGeneratorParameter( + const std::string& text, + std::vector >* output) { + std::vector parts = Split(text, ",", true); for (int i = 0; i < parts.size(); i++) { - string::size_type equals_pos = parts[i].find_first_of('='); - std::pair value; - if (equals_pos == string::npos) { + std::string::size_type equals_pos = parts[i].find_first_of('='); + std::pair value; + if (equals_pos == std::string::npos) { value.first = parts[i]; value.second = ""; } else { @@ -116,6 +123,15 @@ void ParseGeneratorParameter(const string& text, } } +// Strips ".proto" or ".protodevel" from the end of a filename. +std::string StripProto(const std::string& filename) { + if (HasSuffixString(filename, ".protodevel")) { + return StripSuffixString(filename, ".protodevel"); + } else { + return StripSuffixString(filename, ".proto"); + } +} + } // namespace compiler } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h index dd6a59d880695..c8d9e49b5aa56 100644 --- a/src/google/protobuf/compiler/code_generator.h +++ b/src/google/protobuf/compiler/code_generator.h @@ -38,19 +38,25 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__ #define GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__ -#include #include -#include #include +#include +#include + +#include namespace google { namespace protobuf { -namespace io { class ZeroCopyOutputStream; } +namespace io { +class ZeroCopyOutputStream; +} class FileDescriptor; +class GeneratedCodeInfo; namespace compiler { class AccessInfoMap; + class Version; // Defined in this file. @@ -60,7 +66,7 @@ class GeneratorContext; // The abstract interface to a class which generates code implementing a // particular proto file in a particular language. A number of these may // be registered with CommandLineInterface to support various languages. -class LIBPROTOC_EXPORT CodeGenerator { +class PROTOC_EXPORT CodeGenerator { public: inline CodeGenerator() {} virtual ~CodeGenerator(); @@ -77,9 +83,9 @@ class LIBPROTOC_EXPORT CodeGenerator { // Returns true if successful. Otherwise, sets *error to a description of // the problem (e.g. "invalid parameter") and returns false. virtual bool Generate(const FileDescriptor* file, - const string& parameter, + const std::string& parameter, GeneratorContext* generator_context, - string* error) const = 0; + std::string* error) const = 0; // Generates code for all given proto files. // @@ -93,9 +99,19 @@ class LIBPROTOC_EXPORT CodeGenerator { // Returns true if successful. Otherwise, sets *error to a description of // the problem (e.g. "invalid parameter") and returns false. virtual bool GenerateAll(const std::vector& files, - const string& parameter, + const std::string& parameter, GeneratorContext* generator_context, - string* error) const; + std::string* error) const; + + // Sync with plugin.proto. + enum Feature { + FEATURE_PROTO3_OPTIONAL = 1, + }; + + // Implement this to indicate what features this code generator supports. + // This should be a bitwise OR of features from the Features enum in + // plugin.proto. + virtual uint64_t GetSupportedFeatures() const { return 0; } // This is no longer used, but this class is part of the opensource protobuf // library, so it has to remain to keep vtables the same for the current @@ -111,7 +127,7 @@ class LIBPROTOC_EXPORT CodeGenerator { // abstract interface represents the directory to which the CodeGenerator is // to write and other information about the context in which the Generator // runs. -class LIBPROTOC_EXPORT GeneratorContext { +class PROTOC_EXPORT GeneratorContext { public: inline GeneratorContext() { } @@ -127,10 +143,10 @@ class LIBPROTOC_EXPORT GeneratorContext { // generate the files "foo/bar.pb.h" and "foo/bar.pb.cc"; note that // "foo/" is included in these filenames. The filename is not allowed to // contain "." or ".." components. - virtual io::ZeroCopyOutputStream* Open(const string& filename) = 0; + virtual io::ZeroCopyOutputStream* Open(const std::string& filename) = 0; // Similar to Open() but the output will be appended to the file if exists - virtual io::ZeroCopyOutputStream* OpenForAppend(const string& filename); + virtual io::ZeroCopyOutputStream* OpenForAppend(const std::string& filename); // Creates a ZeroCopyOutputStream which will insert code into the given file // at the given insertion point. See plugin.proto (plugin.pb.h) for more @@ -139,7 +155,16 @@ class LIBPROTOC_EXPORT GeneratorContext { // // WARNING: This feature is currently EXPERIMENTAL and is subject to change. virtual io::ZeroCopyOutputStream* OpenForInsert( - const string& filename, const string& insertion_point); + const std::string& filename, const std::string& insertion_point); + + // Similar to OpenForInsert, but if `info` is non-empty, will open (or create) + // filename.pb.meta and insert info at the appropriate place with the + // necessary shifts. The default implementation ignores `info`. + // + // WARNING: This feature will be REMOVED in the near future. + virtual io::ZeroCopyOutputStream* OpenForInsertWithGeneratedCodeInfo( + const std::string& filename, const std::string& insertion_point, + const google::protobuf::GeneratedCodeInfo& info); // Returns a vector of FileDescriptors for all the files being compiled // in this run. Useful for languages, such as Go, that treat files @@ -165,11 +190,16 @@ typedef GeneratorContext OutputDirectory; // "foo=bar,baz,qux=corge" // parses to the pairs: // ("foo", "bar"), ("baz", ""), ("qux", "corge") -LIBPROTOC_EXPORT void ParseGeneratorParameter( - const string&, std::vector >*); +PROTOC_EXPORT void ParseGeneratorParameter( + const std::string&, std::vector >*); + +// Strips ".proto" or ".protodevel" from the end of a filename. +PROTOC_EXPORT std::string StripProto(const std::string& filename); } // namespace compiler } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 5f8640419fe38..48594c438cab8 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -34,7 +34,6 @@ #include - #include #include @@ -45,33 +44,29 @@ #ifdef minor #undef minor #endif -#include #include +#include #ifndef _MSC_VER #include #endif +#include #include #include #include -#include -#include //For PATH_MAX +#include //For PATH_MAX #include -#ifndef _SHARED_PTR_H -#include -#endif -#ifdef __APPLE__ +#if defined(__APPLE__) #include +#elif defined(__FreeBSD__) +#include #endif #include #include #include -#include -#include -#include #include #include #include @@ -83,18 +78,15 @@ #include #include #include -#include -#include -#include -#include -#include -#include #include #include +#include #include #include +#include + namespace google { namespace protobuf { namespace compiler { @@ -103,20 +95,20 @@ namespace compiler { #ifdef _O_BINARY #define O_BINARY _O_BINARY #else -#define O_BINARY 0 // If this isn't defined, the platform doesn't need it. +#define O_BINARY 0 // If this isn't defined, the platform doesn't need it. #endif #endif namespace { -#if defined(_MSC_VER) +#if defined(_WIN32) // DO NOT include , instead create functions in io_win32.{h,cc} and import // them like we do below. -using google::protobuf::internal::win32::access; -using google::protobuf::internal::win32::close; -using google::protobuf::internal::win32::mkdir; -using google::protobuf::internal::win32::open; -using google::protobuf::internal::win32::setmode; -using google::protobuf::internal::win32::write; +using google::protobuf::io::win32::access; +using google::protobuf::io::win32::close; +using google::protobuf::io::win32::mkdir; +using google::protobuf::io::win32::open; +using google::protobuf::io::win32::setmode; +using google::protobuf::io::win32::write; #endif static const char* kDefaultDirectDependenciesViolationMsg = @@ -125,12 +117,10 @@ static const char* kDefaultDirectDependenciesViolationMsg = // Returns true if the text looks like a Windows-style absolute path, starting // with a drive letter. Example: "C:\foo". TODO(kenton): Share this with // copy in importer.cc? -static bool IsWindowsAbsolutePath(const string& text) { +static bool IsWindowsAbsolutePath(const std::string& text) { #if defined(_WIN32) || defined(__CYGWIN__) - return text.size() >= 3 && text[1] == ':' && - isalpha(text[0]) && - (text[2] == '/' || text[2] == '\\') && - text.find_last_of(':') == 1; + return text.size() >= 3 && text[1] == ':' && isalpha(text[0]) && + (text[2] == '/' || text[2] == '\\') && text.find_last_of(':') == 1; #else return false; #endif @@ -156,13 +146,13 @@ void SetFdToBinaryMode(int fd) { // (Text and binary are the same on non-Windows platforms.) } -void AddTrailingSlash(string* path) { +void AddTrailingSlash(std::string* path) { if (!path->empty() && path->at(path->size() - 1) != '/') { path->push_back('/'); } } -bool VerifyDirectoryExists(const string& path) { +bool VerifyDirectoryExists(const std::string& path) { if (path.empty()) return true; if (access(path.c_str(), F_OK) == -1) { @@ -177,11 +167,13 @@ bool VerifyDirectoryExists(const string& path) { // parent if necessary, and so on. The full file name is actually // (prefix + filename), but we assume |prefix| already exists and only create // directories listed in |filename|. -bool TryCreateParentDirectory(const string& prefix, const string& filename) { +bool TryCreateParentDirectory(const std::string& prefix, + const std::string& filename) { // Recursively create parent directories to the output file. - std::vector parts = - Split(filename, "/", true); - string path_so_far = prefix; + // On Windows, both '/' and '\' are valid path separators. + std::vector parts = + Split(filename, "/\\", true); + std::string path_so_far = prefix; for (int i = 0; i < parts.size() - 1; i++) { path_so_far += parts[i]; if (mkdir(path_so_far.c_str(), 0777) != 0) { @@ -198,11 +190,11 @@ bool TryCreateParentDirectory(const string& prefix, const string& filename) { } // Get the absolute path of this protoc binary. -bool GetProtocAbsolutePath(string* path) { +bool GetProtocAbsolutePath(std::string* path) { #ifdef _WIN32 char buffer[MAX_PATH]; int len = GetModuleFileNameA(NULL, buffer, MAX_PATH); -#elif __APPLE__ +#elif defined(__APPLE__) char buffer[PATH_MAX]; int len = 0; @@ -212,6 +204,13 @@ bool GetProtocAbsolutePath(string* path) { realpath(dirtybuffer, buffer); len = strlen(buffer); } +#elif defined(__FreeBSD__) + char buffer[PATH_MAX]; + size_t len = PATH_MAX; + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; + if (sysctl(mib, 4, &buffer, &len, NULL, 0) != 0) { + len = 0; + } #else char buffer[PATH_MAX]; int len = readlink("/proc/self/exe", buffer, PATH_MAX); @@ -226,51 +225,55 @@ bool GetProtocAbsolutePath(string* path) { // Whether a path is where google/protobuf/descriptor.proto and other well-known // type protos are installed. -bool IsInstalledProtoPath(const string& path) { +bool IsInstalledProtoPath(const std::string& path) { // Checking the descriptor.proto file should be good enough. - string file_path = path + "/google/protobuf/descriptor.proto"; + std::string file_path = path + "/google/protobuf/descriptor.proto"; return access(file_path.c_str(), F_OK) != -1; } -// Add the paths where google/protobuf/descritor.proto and other well-known +// Add the paths where google/protobuf/descriptor.proto and other well-known // type protos are installed. -void AddDefaultProtoPaths(vector >* paths) { +void AddDefaultProtoPaths( + std::vector>* paths) { // TODO(xiaofeng): The code currently only checks relative paths of where // the protoc binary is installed. We probably should make it handle more // cases than that. - string path; + std::string path; if (!GetProtocAbsolutePath(&path)) { return; } // Strip the binary name. size_t pos = path.find_last_of("/\\"); - if (pos == string::npos || pos == 0) { + if (pos == std::string::npos || pos == 0) { return; } path = path.substr(0, pos); // Check the binary's directory. if (IsInstalledProtoPath(path)) { - paths->push_back(pair("", path)); + paths->push_back(std::pair("", path)); return; } // Check if there is an include subdirectory. if (IsInstalledProtoPath(path + "/include")) { - paths->push_back(pair("", path + "/include")); + paths->push_back( + std::pair("", path + "/include")); return; } // Check if the upper level directory has an "include" subdirectory. pos = path.find_last_of("/\\"); - if (pos == string::npos || pos == 0) { + if (pos == std::string::npos || pos == 0) { return; } path = path.substr(0, pos); if (IsInstalledProtoPath(path + "/include")) { - paths->push_back(pair("", path + "/include")); + paths->push_back( + std::pair("", path + "/include")); return; } } -string PluginName(const string& plugin_prefix, const string& directive) { +std::string PluginName(const std::string& plugin_prefix, + const std::string& directive) { // Assuming the directive starts with "--" and ends with "_out" or "_opt", // strip the "--" and "_out/_opt" and add the plugin prefix. return plugin_prefix + "gen-" + directive.substr(2, directive.size() - 6); @@ -284,60 +287,53 @@ class CommandLineInterface::ErrorPrinter public io::ErrorCollector, public DescriptorPool::ErrorCollector { public: - ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL) - : format_(format), tree_(tree), found_errors_(false) {} + ErrorPrinter(ErrorFormat format, DiskSourceTree* tree = NULL) + : format_(format), tree_(tree), found_errors_(false) {} ~ErrorPrinter() {} // implements MultiFileErrorCollector ------------------------------ - void AddError(const string& filename, int line, int column, - const string& message) { + void AddError(const std::string& filename, int line, int column, + const std::string& message) { found_errors_ = true; AddErrorOrWarning(filename, line, column, message, "error", std::cerr); } - void AddWarning(const string& filename, int line, int column, - const string& message) { + void AddWarning(const std::string& filename, int line, int column, + const std::string& message) { AddErrorOrWarning(filename, line, column, message, "warning", std::clog); } // implements io::ErrorCollector ----------------------------------- - void AddError(int line, int column, const string& message) { + void AddError(int line, int column, const std::string& message) { AddError("input", line, column, message); } - void AddWarning(int line, int column, const string& message) { + void AddWarning(int line, int column, const std::string& message) { AddErrorOrWarning("input", line, column, message, "warning", std::clog); } // implements DescriptorPool::ErrorCollector------------------------- - void AddError( - const string& filename, - const string& element_name, - const Message* descriptor, - ErrorLocation location, - const string& message) { + void AddError(const std::string& filename, const std::string& element_name, + const Message* descriptor, ErrorLocation location, + const std::string& message) { AddErrorOrWarning(filename, -1, -1, message, "error", std::cerr); } - void AddWarning( - const string& filename, - const string& element_name, - const Message* descriptor, - ErrorLocation location, - const string& message) { + void AddWarning(const std::string& filename, const std::string& element_name, + const Message* descriptor, ErrorLocation location, + const std::string& message) { AddErrorOrWarning(filename, -1, -1, message, "warning", std::clog); } bool FoundErrors() const { return found_errors_; } private: - void AddErrorOrWarning(const string& filename, int line, int column, - const string& message, const string& type, + void AddErrorOrWarning(const std::string& filename, int line, int column, + const std::string& message, const std::string& type, std::ostream& out) { // Print full path when running under MSVS - string dfile; - if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS && - tree_ != NULL && + std::string dfile; + if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS && tree_ != NULL && tree_->VirtualFileToDiskFile(filename, &dfile)) { out << dfile; } else { @@ -353,8 +349,8 @@ class CommandLineInterface::ErrorPrinter out << ":" << (line + 1) << ":" << (column + 1); break; case CommandLineInterface::ERROR_FORMAT_MSVS: - out << "(" << (line + 1) << ") : " - << type << " in column=" << (column + 1); + out << "(" << (line + 1) << ") : " << type + << " in column=" << (column + 1); break; } } @@ -367,7 +363,7 @@ class CommandLineInterface::ErrorPrinter } const ErrorFormat format_; - DiskSourceTree *tree_; + DiskSourceTree* tree_; bool found_errors_; }; @@ -378,28 +374,30 @@ class CommandLineInterface::ErrorPrinter class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { public: GeneratorContextImpl(const std::vector& parsed_files); - ~GeneratorContextImpl(); // Write all files in the directory to disk at the given output location, // which must end in a '/'. - bool WriteAllToDisk(const string& prefix); + bool WriteAllToDisk(const std::string& prefix); // Write the contents of this directory to a ZIP-format archive with the // given name. - bool WriteAllToZip(const string& filename); + bool WriteAllToZip(const std::string& filename); // Add a boilerplate META-INF/MANIFEST.MF file as required by the Java JAR // format, unless one has already been written. void AddJarManifest(); // Get name of all output files. - void GetOutputFilenames(std::vector* output_filenames); + void GetOutputFilenames(std::vector* output_filenames); // implements GeneratorContext -------------------------------------- - io::ZeroCopyOutputStream* Open(const string& filename); - io::ZeroCopyOutputStream* OpenForAppend(const string& filename); - io::ZeroCopyOutputStream* OpenForInsert( - const string& filename, const string& insertion_point); + io::ZeroCopyOutputStream* Open(const std::string& filename); + io::ZeroCopyOutputStream* OpenForAppend(const std::string& filename); + io::ZeroCopyOutputStream* OpenForInsert(const std::string& filename, + const std::string& insertion_point); + io::ZeroCopyOutputStream* OpenForInsertWithGeneratedCodeInfo( + const std::string& filename, const std::string& insertion_point, + const google::protobuf::GeneratedCodeInfo& info); void ListParsedFiles(std::vector* output) { *output = parsed_files_; } @@ -407,9 +405,10 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { private: friend class MemoryOutputStream; - // map instead of hash_map so that files are written in order (good when + // The files_ field maps from path keys to file content values. It's a map + // instead of an unordered_map so that files are written in order (good when // writing zips). - std::map files_; + std::map files_; const std::vector& parsed_files_; bool had_error_; }; @@ -417,53 +416,69 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { class CommandLineInterface::MemoryOutputStream : public io::ZeroCopyOutputStream { public: - MemoryOutputStream(GeneratorContextImpl* directory, const string& filename, - bool append_mode); - MemoryOutputStream(GeneratorContextImpl* directory, const string& filename, - const string& insertion_point); + MemoryOutputStream(GeneratorContextImpl* directory, + const std::string& filename, bool append_mode); + MemoryOutputStream(GeneratorContextImpl* directory, + const std::string& filename, + const std::string& insertion_point); + MemoryOutputStream(GeneratorContextImpl* directory, + const std::string& filename, + const std::string& insertion_point, + const google::protobuf::GeneratedCodeInfo& info); virtual ~MemoryOutputStream(); // implements ZeroCopyOutputStream --------------------------------- - virtual bool Next(void** data, int* size) { return inner_->Next(data, size); } - virtual void BackUp(int count) { inner_->BackUp(count); } - virtual int64 ByteCount() const { return inner_->ByteCount(); } + bool Next(void** data, int* size) override { + return inner_->Next(data, size); + } + void BackUp(int count) override { inner_->BackUp(count); } + int64_t ByteCount() const override { return inner_->ByteCount(); } private: - // Checks to see if "filename_.meta" exists in directory_; if so, fixes the + // Checks to see if "filename_.pb.meta" exists in directory_; if so, fixes the // offsets in that GeneratedCodeInfo record to reflect bytes inserted in // filename_ at original offset insertion_offset with length insertion_length. - // We assume that insertions will not occur within any given annotated span - // of text. - void UpdateMetadata(size_t insertion_offset, size_t insertion_length); + // Also adds in the data from info_to_insert_ with updated offsets governed by + // insertion_offset and indent_length. We assume that insertions will not + // occur within any given annotated span of text. insertion_content must end + // with an endline. + void UpdateMetadata(const std::string& insertion_content, + size_t insertion_offset, size_t insertion_length, + size_t indent_length); + + // Inserts info_to_insert_ into target_info, assuming that the relevant + // insertion was made at insertion_offset in file_content with the given + // indent_length. insertion_content must end with an endline. + void InsertShiftedInfo(const std::string& insertion_content, + size_t insertion_offset, size_t indent_length, + google::protobuf::GeneratedCodeInfo& target_info); // Where to insert the string when it's done. GeneratorContextImpl* directory_; - string filename_; - string insertion_point_; + std::string filename_; + std::string insertion_point_; // The string we're building. - string data_; + std::string data_; // Whether we should append the output stream to the existing file. bool append_mode_; // StringOutputStream writing to data_. - google::protobuf::scoped_ptr inner_; + std::unique_ptr inner_; + + // The GeneratedCodeInfo to insert at the insertion point. + google::protobuf::GeneratedCodeInfo info_to_insert_; }; // ------------------------------------------------------------------- CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl( const std::vector& parsed_files) - : parsed_files_(parsed_files), - had_error_(false) {} - -CommandLineInterface::GeneratorContextImpl::~GeneratorContextImpl() { - STLDeleteValues(&files_); -} + : parsed_files_(parsed_files), had_error_(false) {} bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( - const string& prefix) { + const std::string& prefix) { if (had_error_) { return false; } @@ -472,22 +487,21 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( return false; } - for (std::map::const_iterator iter = files_.begin(); - iter != files_.end(); ++iter) { - const string& relative_filename = iter->first; - const char* data = iter->second->data(); - int size = iter->second->size(); + for (const auto& pair : files_) { + const std::string& relative_filename = pair.first; + const char* data = pair.second.data(); + int size = pair.second.size(); if (!TryCreateParentDirectory(prefix, relative_filename)) { return false; } - string filename = prefix + relative_filename; + std::string filename = prefix + relative_filename; // Create the output file. int file_descriptor; do { file_descriptor = - open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); } while (file_descriptor < 0 && errno == EINTR); if (file_descriptor < 0) { @@ -538,7 +552,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( } bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip( - const string& filename) { + const std::string& filename) { if (had_error_) { return false; } @@ -547,7 +561,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip( int file_descriptor; do { file_descriptor = - open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); } while (file_descriptor < 0 && errno == EINTR); if (file_descriptor < 0) { @@ -560,9 +574,8 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip( io::FileOutputStream stream(file_descriptor); ZipWriter zip_writer(&stream); - for (std::map::const_iterator iter = files_.begin(); - iter != files_.end(); ++iter) { - zip_writer.Write(iter->first, *iter->second); + for (const auto& pair : files_) { + zip_writer.Write(pair.first, pair.second); } zip_writer.WriteDirectory(); @@ -579,94 +592,172 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip( } void CommandLineInterface::GeneratorContextImpl::AddJarManifest() { - string** map_slot = &files_["META-INF/MANIFEST.MF"]; - if (*map_slot == NULL) { - *map_slot = new string( + auto pair = files_.insert({"META-INF/MANIFEST.MF", ""}); + if (pair.second) { + pair.first->second = "Manifest-Version: 1.0\n" "Created-By: 1.6.0 (protoc)\n" - "\n"); + "\n"; } } void CommandLineInterface::GeneratorContextImpl::GetOutputFilenames( - std::vector* output_filenames) { - for (std::map::iterator iter = files_.begin(); - iter != files_.end(); ++iter) { - output_filenames->push_back(iter->first); + std::vector* output_filenames) { + for (const auto& pair : files_) { + output_filenames->push_back(pair.first); } } io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open( - const string& filename) { + const std::string& filename) { return new MemoryOutputStream(this, filename, false); } io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::OpenForAppend( - const string& filename) { + const std::string& filename) { return new MemoryOutputStream(this, filename, true); } io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::OpenForInsert( - const string& filename, const string& insertion_point) { + const std::string& filename, const std::string& insertion_point) { return new MemoryOutputStream(this, filename, insertion_point); } +io::ZeroCopyOutputStream* +CommandLineInterface::GeneratorContextImpl::OpenForInsertWithGeneratedCodeInfo( + const std::string& filename, const std::string& insertion_point, + const google::protobuf::GeneratedCodeInfo& info) { + return new MemoryOutputStream(this, filename, insertion_point, info); +} + // ------------------------------------------------------------------- CommandLineInterface::MemoryOutputStream::MemoryOutputStream( - GeneratorContextImpl* directory, const string& filename, bool append_mode) + GeneratorContextImpl* directory, const std::string& filename, + bool append_mode) : directory_(directory), filename_(filename), append_mode_(append_mode), - inner_(new io::StringOutputStream(&data_)) { -} + inner_(new io::StringOutputStream(&data_)) {} + +CommandLineInterface::MemoryOutputStream::MemoryOutputStream( + GeneratorContextImpl* directory, const std::string& filename, + const std::string& insertion_point) + : directory_(directory), + filename_(filename), + insertion_point_(insertion_point), + inner_(new io::StringOutputStream(&data_)) {} CommandLineInterface::MemoryOutputStream::MemoryOutputStream( - GeneratorContextImpl* directory, const string& filename, - const string& insertion_point) + GeneratorContextImpl* directory, const std::string& filename, + const std::string& insertion_point, const google::protobuf::GeneratedCodeInfo& info) : directory_(directory), filename_(filename), insertion_point_(insertion_point), - inner_(new io::StringOutputStream(&data_)) { + inner_(new io::StringOutputStream(&data_)), + info_to_insert_(info) {} + +void CommandLineInterface::MemoryOutputStream::InsertShiftedInfo( + const std::string& insertion_content, size_t insertion_offset, + size_t indent_length, google::protobuf::GeneratedCodeInfo& target_info) { + // Keep track of how much extra data was added for indents before the + // current annotation being inserted. `pos` and `source_annotation.begin()` + // are offsets in `insertion_content`. `insertion_offset` is updated so that + // it can be added to an annotation's `begin` field to reflect that + // annotation's updated location after `insertion_content` was inserted into + // the target file. + size_t pos = 0; + insertion_offset += indent_length; + for (const auto& source_annotation : info_to_insert_.annotation()) { + GeneratedCodeInfo::Annotation* annotation = target_info.add_annotation(); + int inner_indent = 0; + // insertion_content is guaranteed to end in an endline. This last endline + // has no effect on indentation. + for (; pos < source_annotation.end() && pos < insertion_content.size() - 1; + ++pos) { + if (insertion_content[pos] == '\n') { + if (pos >= source_annotation.begin()) { + // The beginning of the annotation is at insertion_offset, but the end + // can still move further in the target file. + inner_indent += indent_length; + } else { + insertion_offset += indent_length; + } + } + } + *annotation = source_annotation; + annotation->set_begin(annotation->begin() + insertion_offset); + insertion_offset += inner_indent; + annotation->set_end(annotation->end() + insertion_offset); + } } void CommandLineInterface::MemoryOutputStream::UpdateMetadata( - size_t insertion_offset, size_t insertion_length) { - std::map::iterator meta_file = - directory_->files_.find(filename_ + ".meta"); - if (meta_file == directory_->files_.end() || !meta_file->second) { + const std::string& insertion_content, size_t insertion_offset, + size_t insertion_length, size_t indent_length) { + auto it = directory_->files_.find(filename_ + ".pb.meta"); + if (it == directory_->files_.end() && info_to_insert_.annotation().empty()) { // No metadata was recorded for this file. return; } - string* encoded_data = meta_file->second; GeneratedCodeInfo metadata; bool is_text_format = false; - if (!metadata.ParseFromString(*encoded_data)) { - if (!TextFormat::ParseFromString(*encoded_data, &metadata)) { - // The metadata is invalid. - std::cerr << filename_ - << ".meta: Could not parse metadata as wire or text format." - << std::endl; - return; - } - // Generators that use the public plugin interface emit text-format - // metadata (because in the public plugin protocol, file content must be - // UTF8-encoded strings). - is_text_format = true; - } - for (int i = 0; i < metadata.annotation_size(); ++i) { - GeneratedCodeInfo::Annotation* annotation = metadata.mutable_annotation(i); - if (annotation->begin() >= insertion_offset) { - annotation->set_begin(annotation->begin() + insertion_length); - annotation->set_end(annotation->end() + insertion_length); + std::string* encoded_data = nullptr; + if (it != directory_->files_.end()) { + encoded_data = &it->second; + // Try to decode a GeneratedCodeInfo proto from the .pb.meta file. It may be + // in wire or text format. Keep the same format when the data is written out + // later. + if (!metadata.ParseFromString(*encoded_data)) { + if (!TextFormat::ParseFromString(*encoded_data, &metadata)) { + // The metadata is invalid. + std::cerr + << filename_ + << ".pb.meta: Could not parse metadata as wire or text format." + << std::endl; + return; + } + // Generators that use the public plugin interface emit text-format + // metadata (because in the public plugin protocol, file content must be + // UTF8-encoded strings). + is_text_format = true; } + } else { + // Create a new file to store the new metadata in info_to_insert_. + encoded_data = + &directory_->files_.insert({filename_ + ".pb.meta", ""}).first->second; + } + GeneratedCodeInfo new_metadata; + bool crossed_offset = false; + size_t to_add = 0; + for (const auto& source_annotation : metadata.annotation()) { + // The first time an annotation at or after the insertion point is found, + // insert the new metadata from info_to_insert_. Shift all annotations + // after the new metadata by the length of the text that was inserted + // (including any additional indent length). + if (source_annotation.begin() >= insertion_offset && !crossed_offset) { + crossed_offset = true; + InsertShiftedInfo(insertion_content, insertion_offset, indent_length, + new_metadata); + to_add += insertion_length; + } + GeneratedCodeInfo::Annotation* annotation = new_metadata.add_annotation(); + *annotation = source_annotation; + annotation->set_begin(annotation->begin() + to_add); + annotation->set_end(annotation->end() + to_add); + } + // If there were never any annotations at or after the insertion point, + // make sure to still insert the new metadata from info_to_insert_. + if (!crossed_offset) { + InsertShiftedInfo(insertion_content, insertion_offset, indent_length, + new_metadata); } if (is_text_format) { - TextFormat::PrintToString(metadata, encoded_data); + TextFormat::PrintToString(new_metadata, encoded_data); } else { - metadata.SerializeToString(encoded_data); + new_metadata.SerializeToString(encoded_data); } } @@ -675,13 +766,15 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { inner_.reset(); // Insert into the directory. - string** map_slot = &directory_->files_[filename_]; + auto pair = directory_->files_.insert({filename_, ""}); + auto it = pair.first; + bool already_present = !pair.second; if (insertion_point_.empty()) { // This was just a regular Open(). - if (*map_slot != NULL) { + if (already_present) { if (append_mode_) { - (*map_slot)->append(data_); + it->second.append(data_); } else { std::cerr << filename_ << ": Tried to write the same file twice." << std::endl; @@ -690,8 +783,7 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { return; } - *map_slot = new string; - (*map_slot)->swap(data_); + it->second.swap(data_); } else { // This was an OpenForInsert(). @@ -701,21 +793,21 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { } // Find the file we are going to insert into. - if (*map_slot == NULL) { + if (!already_present) { std::cerr << filename_ << ": Tried to insert into file that doesn't exist." << std::endl; directory_->had_error_ = true; return; } - string* target = *map_slot; + std::string* target = &it->second; // Find the insertion point. - string magic_string = strings::Substitute( - "@@protoc_insertion_point($0)", insertion_point_); - string::size_type pos = target->find(magic_string); + std::string magic_string = + strings::Substitute("@@protoc_insertion_point($0)", insertion_point_); + std::string::size_type pos = target->find(magic_string); - if (pos == string::npos) { + if (pos == std::string::npos) { std::cerr << filename_ << ": insertion point \"" << insertion_point_ << "\" not found." << std::endl; directory_->had_error_ = true; @@ -732,7 +824,7 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { // intentional because it means that multiple insertions at the same point // will end up in the expected order in the final output. pos = target->find_last_of('\n', pos); - if (pos == string::npos) { + if (pos == std::string::npos) { // Insertion point is on the first line. pos = 0; } else { @@ -742,12 +834,13 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { } // Extract indent. - string indent_(*target, pos, target->find_first_not_of(" \t", pos) - pos); + std::string indent_(*target, pos, + target->find_first_not_of(" \t", pos) - pos); if (indent_.empty()) { // No indent. This makes things easier. target->insert(pos, data_); - UpdateMetadata(pos, data_.size()); + UpdateMetadata(data_, pos, data_.size(), 0); } else { // Calculate how much space we need. int indent_size = 0; @@ -757,11 +850,10 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { // Make a hole for it. target->insert(pos, data_.size() + indent_size, '\0'); - UpdateMetadata(pos, data_.size() + indent_size); // Now copy in the data. - string::size_type data_pos = 0; - char* target_ptr = string_as_array(target) + pos; + std::string::size_type data_pos = 0; + char* target_ptr = ::google::protobuf::string_as_array(target) + pos; while (data_pos < data_.size()) { // Copy indent. memcpy(target_ptr, indent_.data(), indent_.size()); @@ -770,15 +862,16 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { // Copy line from data_. // We already guaranteed that data_ ends with a newline (above), so this // search can't fail. - string::size_type line_length = + std::string::size_type line_length = data_.find_first_of('\n', data_pos) + 1 - data_pos; memcpy(target_ptr, data_.data() + data_pos, line_length); target_ptr += line_length; data_pos += line_length; } + UpdateMetadata(data_, pos, data_.size() + indent_size, indent_.size()); GOOGLE_CHECK_EQ(target_ptr, - string_as_array(target) + pos + data_.size() + indent_size); + ::google::protobuf::string_as_array(target) + pos + data_.size() + indent_size); } } } @@ -792,20 +885,14 @@ const char* const CommandLineInterface::kPathSeparator = ":"; #endif CommandLineInterface::CommandLineInterface() - : mode_(MODE_COMPILE), - print_mode_(PRINT_NONE), - error_format_(ERROR_FORMAT_GCC), - direct_dependencies_explicitly_set_(false), - direct_dependencies_violation_msg_( - kDefaultDirectDependenciesViolationMsg), - imports_in_descriptor_set_(false), - source_info_in_descriptor_set_(false), - disallow_services_(false) {} + : direct_dependencies_violation_msg_( + kDefaultDirectDependenciesViolationMsg) {} + CommandLineInterface::~CommandLineInterface() {} -void CommandLineInterface::RegisterGenerator(const string& flag_name, +void CommandLineInterface::RegisterGenerator(const std::string& flag_name, CodeGenerator* generator, - const string& help_text) { + const std::string& help_text) { GeneratorInfo info; info.flag_name = flag_name; info.generator = generator; @@ -813,10 +900,9 @@ void CommandLineInterface::RegisterGenerator(const string& flag_name, generators_by_flag_name_[flag_name] = info; } -void CommandLineInterface::RegisterGenerator(const string& flag_name, - const string& option_flag_name, - CodeGenerator* generator, - const string& help_text) { +void CommandLineInterface::RegisterGenerator( + const std::string& flag_name, const std::string& option_flag_name, + CodeGenerator* generator, const std::string& help_text) { GeneratorInfo info; info.flag_name = flag_name; info.option_flag_name = option_flag_name; @@ -826,10 +912,44 @@ void CommandLineInterface::RegisterGenerator(const string& flag_name, generators_by_option_name_[option_flag_name] = info; } -void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) { +void CommandLineInterface::AllowPlugins(const std::string& exe_name_prefix) { plugin_prefix_ = exe_name_prefix; } +namespace { + +bool ContainsProto3Optional(const Descriptor* desc) { + for (int i = 0; i < desc->field_count(); i++) { + if (desc->field(i)->has_optional_keyword()) { + return true; + } + } + for (int i = 0; i < desc->nested_type_count(); i++) { + if (ContainsProto3Optional(desc->nested_type(i))) { + return true; + } + } + return false; +} + +bool ContainsProto3Optional(const FileDescriptor* file) { + if (file->syntax() == FileDescriptor::SYNTAX_PROTO3) { + for (int i = 0; i < file->message_type_count(); i++) { + if (ContainsProto3Optional(file->message_type(i))) { + return true; + } + } + } + return false; +} + +} // namespace + +namespace { +std::unique_ptr +PopulateSingleSimpleDescriptorDatabase(const std::string& descriptor_set_name); +} + int CommandLineInterface::Run(int argc, const char* const argv[]) { Clear(); switch (ParseArguments(argc, argv)) { @@ -842,40 +962,90 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } std::vector parsed_files; - // null unless descriptor_set_in_names_.empty() - google::protobuf::scoped_ptr disk_source_tree; - google::protobuf::scoped_ptr error_collector; - google::protobuf::scoped_ptr descriptor_pool; - google::protobuf::scoped_ptr descriptor_database; - if (descriptor_set_in_names_.empty()) { + std::unique_ptr disk_source_tree; + std::unique_ptr error_collector; + std::unique_ptr descriptor_pool; + + // The SimpleDescriptorDatabases here are the constituents of the + // MergedDescriptorDatabase descriptor_set_in_database, so this vector is for + // managing their lifetimes. Its scope should match descriptor_set_in_database + std::vector> + databases_per_descriptor_set; + std::unique_ptr descriptor_set_in_database; + + std::unique_ptr source_tree_database; + + // Any --descriptor_set_in FileDescriptorSet objects will be used as a + // fallback to input_files on command line, so create that db first. + if (!descriptor_set_in_names_.empty()) { + for (const std::string& name : descriptor_set_in_names_) { + std::unique_ptr database_for_descriptor_set = + PopulateSingleSimpleDescriptorDatabase(name); + if (!database_for_descriptor_set) { + return EXIT_FAILURE; + } + databases_per_descriptor_set.push_back( + std::move(database_for_descriptor_set)); + } + + std::vector raw_databases_per_descriptor_set; + raw_databases_per_descriptor_set.reserve( + databases_per_descriptor_set.size()); + for (const std::unique_ptr& db : + databases_per_descriptor_set) { + raw_databases_per_descriptor_set.push_back(db.get()); + } + descriptor_set_in_database.reset( + new MergedDescriptorDatabase(raw_databases_per_descriptor_set)); + } + + if (proto_path_.empty()) { + // If there are no --proto_path flags, then just look in the specified + // --descriptor_set_in files. But first, verify that the input files are + // there. + if (!VerifyInputFilesInDescriptors(descriptor_set_in_database.get())) { + return 1; + } + + error_collector.reset(new ErrorPrinter(error_format_)); + descriptor_pool.reset(new DescriptorPool(descriptor_set_in_database.get(), + error_collector.get())); + } else { disk_source_tree.reset(new DiskSourceTree()); - if (!InitializeDiskSourceTree(disk_source_tree.get())) { + if (!InitializeDiskSourceTree(disk_source_tree.get(), + descriptor_set_in_database.get())) { return 1; } + error_collector.reset( new ErrorPrinter(error_format_, disk_source_tree.get())); - SourceTreeDescriptorDatabase* database = - new SourceTreeDescriptorDatabase(disk_source_tree.get()); - database->RecordErrorsTo(error_collector.get()); - descriptor_database.reset(database); - descriptor_pool.reset(new DescriptorPool( - descriptor_database.get(), database->GetValidationErrorCollector())); - } else { - error_collector.reset(new ErrorPrinter(error_format_)); + source_tree_database.reset(new SourceTreeDescriptorDatabase( + disk_source_tree.get(), descriptor_set_in_database.get())); + source_tree_database->RecordErrorsTo(error_collector.get()); - SimpleDescriptorDatabase* database = new SimpleDescriptorDatabase(); - descriptor_database.reset(database); - if (!PopulateSimpleDescriptorDatabase(database)) { - return 1; - } - descriptor_pool.reset(new DescriptorPool(database, error_collector.get())); + descriptor_pool.reset(new DescriptorPool( + source_tree_database.get(), + source_tree_database->GetValidationErrorCollector())); } + descriptor_pool->EnforceWeakDependencies(true); - if (!ParseInputFiles(descriptor_pool.get(), &parsed_files)) { + if (!ParseInputFiles(descriptor_pool.get(), disk_source_tree.get(), + &parsed_files)) { return 1; } + + for (auto fd : parsed_files) { + if (!AllowProto3Optional(*fd) && ContainsProto3Optional(fd)) { + std::cerr << fd->name() + << ": This file contains proto3 optional fields, but " + "--experimental_allow_proto3_optional was not set." + << std::endl; + return 1; + } + } + // We construct a separate GeneratorContext for each output location. Note // that two code generators may output to the same location, in which case // they should share a single GeneratorContext so that OpenForInsert() works. @@ -884,33 +1054,33 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { // Generate output. if (mode_ == MODE_COMPILE) { for (int i = 0; i < output_directives_.size(); i++) { - string output_location = output_directives_[i].output_location; + std::string output_location = output_directives_[i].output_location; if (!HasSuffixString(output_location, ".zip") && - !HasSuffixString(output_location, ".jar")) { + !HasSuffixString(output_location, ".jar") && + !HasSuffixString(output_location, ".srcjar")) { AddTrailingSlash(&output_location); } - GeneratorContextImpl** map_slot = &output_directories[output_location]; - if (*map_slot == NULL) { + auto& generator = output_directories[output_location]; + + if (!generator) { // First time we've seen this output location. - *map_slot = new GeneratorContextImpl(parsed_files); + generator.reset(new GeneratorContextImpl(parsed_files)); } - if (!GenerateOutput(parsed_files, output_directives_[i], *map_slot)) { - STLDeleteValues(&output_directories); + if (!GenerateOutput(parsed_files, output_directives_[i], + generator.get())) { return 1; } } } // Write all output to disk. - for (GeneratorContextMap::iterator iter = output_directories.begin(); - iter != output_directories.end(); ++iter) { - const string& location = iter->first; - GeneratorContextImpl* directory = iter->second; + for (const auto& pair : output_directories) { + const std::string& location = pair.first; + GeneratorContextImpl* directory = pair.second.get(); if (HasSuffixString(location, "/")) { if (!directory->WriteAllToDisk(location)) { - STLDeleteValues(&output_directories); return 1; } } else { @@ -919,7 +1089,6 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } if (!directory->WriteAllToZip(location)) { - STLDeleteValues(&output_directories); return 1; } } @@ -933,8 +1102,6 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } } - STLDeleteValues(&output_directories); - if (!descriptor_set_out_name_.empty()) { if (!WriteDescriptorSet(parsed_files)) { return 1; @@ -976,10 +1143,10 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { break; case PRINT_NONE: GOOGLE_LOG(ERROR) << "If the code reaches here, it usually means a bug of " - "flag parsing in the CommandLineInterface."; + "flag parsing in the CommandLineInterface."; return 1; - // Do not add a default case. + // Do not add a default case. } } @@ -987,7 +1154,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } bool CommandLineInterface::InitializeDiskSourceTree( - DiskSourceTree* source_tree) { + DiskSourceTree* source_tree, DescriptorDatabase* fallback_database) { AddDefaultProtoPaths(&proto_path_); // Set up the source tree. @@ -996,80 +1163,135 @@ bool CommandLineInterface::InitializeDiskSourceTree( } // Map input files to virtual paths if possible. - if (!MakeInputsBeProtoPathRelative(source_tree)) { + if (!MakeInputsBeProtoPathRelative(source_tree, fallback_database)) { return false; } + return true; } -bool CommandLineInterface::PopulateSimpleDescriptorDatabase( - SimpleDescriptorDatabase* database) { - for (int i = 0; i < descriptor_set_in_names_.size(); i++) { - int fd; - do { - fd = open(descriptor_set_in_names_[i].c_str(), O_RDONLY | O_BINARY); - } while (fd < 0 && errno == EINTR); - if (fd < 0) { - std::cerr << descriptor_set_in_names_[i] << ": " - << strerror(ENOENT) << std::endl; - return false; +namespace { +std::unique_ptr +PopulateSingleSimpleDescriptorDatabase(const std::string& descriptor_set_name) { + int fd; + do { + fd = open(descriptor_set_name.c_str(), O_RDONLY | O_BINARY); + } while (fd < 0 && errno == EINTR); + if (fd < 0) { + std::cerr << descriptor_set_name << ": " << strerror(ENOENT) << std::endl; + return nullptr; + } + + FileDescriptorSet file_descriptor_set; + bool parsed = file_descriptor_set.ParseFromFileDescriptor(fd); + if (close(fd) != 0) { + std::cerr << descriptor_set_name << ": close: " << strerror(errno) + << std::endl; + return nullptr; + } + + if (!parsed) { + std::cerr << descriptor_set_name << ": Unable to parse." << std::endl; + return nullptr; + } + + std::unique_ptr database{ + new SimpleDescriptorDatabase()}; + + for (int j = 0; j < file_descriptor_set.file_size(); j++) { + FileDescriptorProto previously_added_file_descriptor_proto; + if (database->FindFileByName(file_descriptor_set.file(j).name(), + &previously_added_file_descriptor_proto)) { + // already present - skip + continue; + } + if (!database->Add(file_descriptor_set.file(j))) { + return nullptr; } + } + return database; +} - FileDescriptorSet file_descriptor_set; - bool parsed = file_descriptor_set.ParseFromFileDescriptor(fd); - if (close(fd) != 0) { - std::cerr << descriptor_set_in_names_[i] << ": close: " - << strerror(errno); +} // namespace + +bool CommandLineInterface::AllowProto3Optional( + const FileDescriptor& file) const { + // Proto3 optional is enabled by default now, the experimental flag is no + // longer required. + return true; +} + + +bool CommandLineInterface::VerifyInputFilesInDescriptors( + DescriptorDatabase* database) { + for (const auto& input_file : input_files_) { + FileDescriptorProto file_descriptor; + if (!database->FindFileByName(input_file, &file_descriptor)) { + std::cerr << "Could not find file in descriptor database: " << input_file + << ": " << strerror(ENOENT) << std::endl; return false; } - if (!parsed) { - std::cerr << descriptor_set_in_names_[i] << ": Unable to parse." + // Enforce --disallow_services. + if (disallow_services_ && file_descriptor.service_size() > 0) { + std::cerr << file_descriptor.name() + << ": This file contains services, but " + "--disallow_services was used." << std::endl; return false; } - for (int j = 0; j < file_descriptor_set.file_size(); j++) { - FileDescriptorProto previously_added_file_descriptor_proto; - if (database->FindFileByName(file_descriptor_set.file(j).name(), - &previously_added_file_descriptor_proto)) { - // already present - skip - continue; - } - if (!database->Add(file_descriptor_set.file(j))) { - return false; - } - } } return true; } bool CommandLineInterface::ParseInputFiles( - DescriptorPool* descriptor_pool, + DescriptorPool* descriptor_pool, DiskSourceTree* source_tree, std::vector* parsed_files) { + if (!proto_path_.empty()) { + // Track unused imports in all source files that were loaded from the + // filesystem. We do not track unused imports for files loaded from + // descriptor sets as they may be programmatically generated in which case + // exerting this level of rigor is less desirable. We're also making the + // assumption that the initial parse of the proto from the filesystem + // was rigorous in checking unused imports and that the descriptor set + // being parsed was produced then and that it was subsequent mutations + // of that descriptor set that left unused imports. + // + // Note that relying on proto_path exclusively is limited in that we may + // be loading descriptors from both the filesystem and descriptor sets + // depending on the invocation. At least for invocations that are + // exclusively reading from descriptor sets, we can eliminate this failure + // condition. + for (const auto& input_file : input_files_) { + descriptor_pool->AddUnusedImportTrackFile(input_file); + } + } + + bool result = true; // Parse each file. - for (int i = 0; i < input_files_.size(); i++) { + for (const auto& input_file : input_files_) { // Import the file. - descriptor_pool->AddUnusedImportTrackFile(input_files_[i]); const FileDescriptor* parsed_file = - descriptor_pool->FindFileByName(input_files_[i]); - descriptor_pool->ClearUnusedImportTrackFiles(); + descriptor_pool->FindFileByName(input_file); if (parsed_file == NULL) { - if (!descriptor_set_in_names_.empty()) { - std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl; - } - return false; + result = false; + break; } parsed_files->push_back(parsed_file); // Enforce --disallow_services. if (disallow_services_ && parsed_file->service_count() > 0) { - std::cerr << parsed_file->name() << ": This file contains services, but " - "--disallow_services was used." << std::endl; - return false; + std::cerr << parsed_file->name() + << ": This file contains services, but " + "--disallow_services was used." + << std::endl; + result = false; + break; } + // Enforce --direct_dependencies if (direct_dependencies_explicitly_set_) { bool indirect_imports = false; @@ -1085,11 +1307,13 @@ bool CommandLineInterface::ParseInputFiles( } } if (indirect_imports) { - return false; + result = false; + break; } } } - return true; + descriptor_pool->ClearUnusedImportTrackFiles(); + return result; } void CommandLineInterface::Clear() { @@ -1106,91 +1330,146 @@ void CommandLineInterface::Clear() { descriptor_set_out_name_.clear(); dependency_out_name_.clear(); + mode_ = MODE_COMPILE; print_mode_ = PRINT_NONE; imports_in_descriptor_set_ = false; source_info_in_descriptor_set_ = false; disallow_services_ = false; direct_dependencies_explicitly_set_ = false; + allow_proto3_optional_ = false; + deterministic_output_ = false; } -bool CommandLineInterface::MakeInputsBeProtoPathRelative( - DiskSourceTree* source_tree) { - for (int i = 0; i < input_files_.size(); i++) { - // If the input file path is not a physical file path, it must be a virtual - // path. - if (access(input_files_[i].c_str(), F_OK) < 0) { - string disk_file; - if (source_tree->VirtualFileToDiskFile(input_files_[i], &disk_file)) { +bool CommandLineInterface::MakeProtoProtoPathRelative( + DiskSourceTree* source_tree, std::string* proto, + DescriptorDatabase* fallback_database) { + // If it's in the fallback db, don't report non-existent file errors. + FileDescriptorProto fallback_file; + bool in_fallback_database = + fallback_database != nullptr && + fallback_database->FindFileByName(*proto, &fallback_file); + + // If the input file path is not a physical file path, it must be a virtual + // path. + if (access(proto->c_str(), F_OK) < 0) { + std::string disk_file; + if (source_tree->VirtualFileToDiskFile(*proto, &disk_file) || + in_fallback_database) { + return true; + } else { + std::cerr << "Could not make proto path relative: " << *proto << ": " + << strerror(ENOENT) << std::endl; + return false; + } + } + + std::string virtual_file, shadowing_disk_file; + switch (source_tree->DiskFileToVirtualFile(*proto, &virtual_file, + &shadowing_disk_file)) { + case DiskSourceTree::SUCCESS: + *proto = virtual_file; + break; + case DiskSourceTree::SHADOWED: + std::cerr << *proto << ": Input is shadowed in the --proto_path by \"" + << shadowing_disk_file + << "\". Either use the latter file as your input or reorder " + "the --proto_path so that the former file's location " + "comes first." + << std::endl; + return false; + case DiskSourceTree::CANNOT_OPEN: { + if (in_fallback_database) { return true; - } else { - std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl; - return false; } + std::string error_str = source_tree->GetLastErrorMessage().empty() + ? strerror(errno) + : source_tree->GetLastErrorMessage(); + std::cerr << "Could not map to virtual file: " << *proto << ": " + << error_str << std::endl; + return false; } - string virtual_file, shadowing_disk_file; - switch (source_tree->DiskFileToVirtualFile( - input_files_[i], &virtual_file, &shadowing_disk_file)) { - case DiskSourceTree::SUCCESS: - input_files_[i] = virtual_file; - break; - case DiskSourceTree::SHADOWED: - std::cerr << input_files_[i] - << ": Input is shadowed in the --proto_path by \"" - << shadowing_disk_file - << "\". Either use the latter file as your input or reorder " - "the --proto_path so that the former file's location " - "comes first." << std::endl; - return false; - case DiskSourceTree::CANNOT_OPEN: - std::cerr << input_files_[i] << ": " << strerror(errno) << std::endl; + case DiskSourceTree::NO_MAPPING: { + // Try to interpret the path as a virtual path. + std::string disk_file; + if (source_tree->VirtualFileToDiskFile(*proto, &disk_file) || + in_fallback_database) { + return true; + } else { + // The input file path can't be mapped to any --proto_path and it also + // can't be interpreted as a virtual path. + std::cerr + << *proto + << ": File does not reside within any path " + "specified using --proto_path (or -I). You must specify a " + "--proto_path which encompasses this file. Note that the " + "proto_path must be an exact prefix of the .proto file " + "names -- protoc is too dumb to figure out when two paths " + "(e.g. absolute and relative) are equivalent (it's harder " + "than you think)." + << std::endl; return false; - case DiskSourceTree::NO_MAPPING: { - // Try to interpret the path as a virtual path. - string disk_file; - if (source_tree->VirtualFileToDiskFile(input_files_[i], &disk_file)) { - return true; - } else { - // The input file path can't be mapped to any --proto_path and it also - // can't be interpreted as a virtual path. - std::cerr - << input_files_[i] - << ": File does not reside within any path " - "specified using --proto_path (or -I). You must specify a " - "--proto_path which encompasses this file. Note that the " - "proto_path must be an exact prefix of the .proto file " - "names -- protoc is too dumb to figure out when two paths " - "(e.g. absolute and relative) are equivalent (it's harder " - "than you think)." - << std::endl; - return false; - } } } } + return true; +} + +bool CommandLineInterface::MakeInputsBeProtoPathRelative( + DiskSourceTree* source_tree, DescriptorDatabase* fallback_database) { + for (auto& input_file : input_files_) { + if (!MakeProtoProtoPathRelative(source_tree, &input_file, + fallback_database)) { + return false; + } + } return true; } -CommandLineInterface::ParseArgumentStatus -CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { +bool CommandLineInterface::ExpandArgumentFile( + const std::string& file, std::vector* arguments) { + // The argument file is searched in the working directory only. We don't + // use the proto import path here. + std::ifstream file_stream(file.c_str()); + if (!file_stream.is_open()) { + return false; + } + std::string argument; + // We don't support any kind of shell expansion right now. + while (std::getline(file_stream, argument)) { + arguments->push_back(argument); + } + return true; +} + +CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments( + int argc, const char* const argv[]) { executable_name_ = argv[0]; - std::vector arguments; + std::vector arguments; for (int i = 1; i < argc; ++i) { + if (argv[i][0] == '@') { + if (!ExpandArgumentFile(argv[i] + 1, &arguments)) { + std::cerr << "Failed to open argument file: " << (argv[i] + 1) + << std::endl; + return PARSE_ARGUMENT_FAIL; + } + continue; + } arguments.push_back(argv[i]); } // if no arguments are given, show help - if(arguments.empty()) { + if (arguments.empty()) { PrintHelpText(); return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler. } // Iterate through all arguments and parse them. for (int i = 0; i < arguments.size(); ++i) { - string name, value; + std::string name, value; if (ParseArgument(arguments[i].c_str(), &name, &value)) { // Returned true => Use the next argument as the flag value. @@ -1208,22 +1487,23 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { } ParseArgumentStatus status = InterpretArgument(name, value); - if (status != PARSE_ARGUMENT_DONE_AND_CONTINUE) - return status; + if (status != PARSE_ARGUMENT_DONE_AND_CONTINUE) return status; } // Make sure each plugin option has a matching plugin output. bool foundUnknownPluginOption = false; - for (std::map::const_iterator i = plugin_parameters_.begin(); + for (std::map::const_iterator i = + plugin_parameters_.begin(); i != plugin_parameters_.end(); ++i) { if (plugins_.find(i->first) != plugins_.end()) { continue; } bool foundImplicitPlugin = false; - for (std::vector::const_iterator j = output_directives_.begin(); + for (std::vector::const_iterator j = + output_directives_.begin(); j != output_directives_.end(); ++j) { if (j->generator == NULL) { - string plugin_name = PluginName(plugin_prefix_ , j->name); + std::string plugin_name = PluginName(plugin_prefix_, j->name); if (plugin_name == i->first) { foundImplicitPlugin = true; break; @@ -1242,21 +1522,45 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { return PARSE_ARGUMENT_FAIL; } - // If no --proto_path was given, use the current working directory. - if (proto_path_.empty()) { + // The --proto_path & --descriptor_set_in flags both specify places to look + // for proto files. If neither were given, use the current working directory. + if (proto_path_.empty() && descriptor_set_in_names_.empty()) { // Don't use make_pair as the old/default standard library on Solaris // doesn't support it without explicit template parameters, which are // incompatible with C++0x's make_pair. - proto_path_.push_back(std::pair("", ".")); + proto_path_.push_back(std::pair("", ".")); } - // Check some errror cases. - bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty(); - if (decoding_raw && !input_files_.empty()) { - std::cerr << "When using --decode_raw, no input files should be given." + // Check error cases that span multiple flag values. + bool missing_proto_definitions = false; + switch (mode_) { + case MODE_COMPILE: + missing_proto_definitions = input_files_.empty(); + break; + case MODE_DECODE: + // Handle --decode_raw separately, since it requires that no proto + // definitions are specified. + if (codec_type_.empty()) { + if (!input_files_.empty() || !descriptor_set_in_names_.empty()) { + std::cerr + << "When using --decode_raw, no input files should be given." << std::endl; - return PARSE_ARGUMENT_FAIL; - } else if (!decoding_raw && input_files_.empty()) { + return PARSE_ARGUMENT_FAIL; + } + missing_proto_definitions = false; + break; // only for --decode_raw + } + // --decode (not raw) is handled the same way as the rest of the modes. + PROTOBUF_FALLTHROUGH_INTENDED; + case MODE_ENCODE: + case MODE_PRINT: + missing_proto_definitions = + input_files_.empty() && descriptor_set_in_names_.empty(); + break; + default: + GOOGLE_LOG(FATAL) << "Unexpected mode: " << mode_; + } + if (missing_proto_definitions) { std::cerr << "Missing input file." << std::endl; return PARSE_ARGUMENT_FAIL; } @@ -1270,6 +1574,11 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { << std::endl; return PARSE_ARGUMENT_FAIL; } + if (mode_ != MODE_ENCODE && deterministic_output_) { + std::cerr << "Can only use --deterministic_output with --encode." + << std::endl; + return PARSE_ARGUMENT_FAIL; + } if (!dependency_out_name_.empty() && input_files_.size() > 1) { std::cerr << "Can only process one input file when using --dependency_out=FILE." @@ -1278,18 +1587,20 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { } if (imports_in_descriptor_set_ && descriptor_set_out_name_.empty()) { std::cerr << "--include_imports only makes sense when combined with " - "--descriptor_set_out." << std::endl; + "--descriptor_set_out." + << std::endl; } if (source_info_in_descriptor_set_ && descriptor_set_out_name_.empty()) { std::cerr << "--include_source_info only makes sense when combined with " - "--descriptor_set_out." << std::endl; + "--descriptor_set_out." + << std::endl; } return PARSE_ARGUMENT_DONE_AND_CONTINUE; } -bool CommandLineInterface::ParseArgument(const char* arg, - string* name, string* value) { +bool CommandLineInterface::ParseArgument(const char* arg, std::string* name, + std::string* value) { bool parsed_value = false; if (arg[0] != '-') { @@ -1302,7 +1613,7 @@ bool CommandLineInterface::ParseArgument(const char* arg, // value. const char* equals_pos = strchr(arg, '='); if (equals_pos != NULL) { - *name = string(arg, equals_pos - arg); + *name = std::string(arg, equals_pos - arg); *value = equals_pos + 1; parsed_value = true; } else { @@ -1318,7 +1629,7 @@ bool CommandLineInterface::ParseArgument(const char* arg, *value = arg; parsed_value = true; } else { - *name = string(arg, 2); + *name = std::string(arg, 2); *value = arg + 2; parsed_value = !value->empty(); } @@ -1332,13 +1643,12 @@ bool CommandLineInterface::ParseArgument(const char* arg, return false; } - if (*name == "-h" || *name == "--help" || - *name == "--disallow_services" || - *name == "--include_imports" || - *name == "--include_source_info" || - *name == "--version" || - *name == "--decode_raw" || - *name == "--print_free_field_numbers") { + if (*name == "-h" || *name == "--help" || *name == "--disallow_services" || + *name == "--include_imports" || *name == "--include_source_info" || + *name == "--version" || *name == "--decode_raw" || + *name == "--print_free_field_numbers" || + *name == "--experimental_allow_proto3_optional" || + *name == "--deterministic_output") { // HACK: These are the only flags that don't take a value. // They probably should not be hard-coded like this but for now it's // not worth doing better. @@ -1350,44 +1660,62 @@ bool CommandLineInterface::ParseArgument(const char* arg, } CommandLineInterface::ParseArgumentStatus -CommandLineInterface::InterpretArgument(const string& name, - const string& value) { +CommandLineInterface::InterpretArgument(const std::string& name, + const std::string& value) { if (name.empty()) { // Not a flag. Just a filename. if (value.empty()) { std::cerr << "You seem to have passed an empty string as one of the " - "arguments to " << executable_name_ + "arguments to " + << executable_name_ << ". This is actually " "sort of hard to do. Congrats. Unfortunately it is not valid " - "input so the program is going to die now." << std::endl; + "input so the program is going to die now." + << std::endl; return PARSE_ARGUMENT_FAIL; } +#if defined(_WIN32) + // On Windows, the shell (typically cmd.exe) does not expand wildcards in + // file names (e.g. foo\*.proto), so we do it ourselves. + switch (google::protobuf::io::win32::ExpandWildcards( + value, + [this](const string& path) { this->input_files_.push_back(path); })) { + case google::protobuf::io::win32::ExpandWildcardsResult::kSuccess: + break; + case google::protobuf::io::win32::ExpandWildcardsResult:: + kErrorNoMatchingFile: + // Path does not exist, is not a file, or it's longer than MAX_PATH and + // long path handling is disabled. + std::cerr << "Invalid file name pattern or missing input file \"" + << value << "\"" << std::endl; + return PARSE_ARGUMENT_FAIL; + default: + std::cerr << "Cannot convert path \"" << value + << "\" to or from Windows style" << std::endl; + return PARSE_ARGUMENT_FAIL; + } +#else // not _WIN32 + // On other platforms than Windows (e.g. Linux, Mac OS) the shell (typically + // Bash) expands wildcards. input_files_.push_back(value); +#endif // _WIN32 } else if (name == "-I" || name == "--proto_path") { - if (!descriptor_set_in_names_.empty()) { - std::cerr << "Only one of " << name - << " and --descriptor_set_in can be specified." - << std::endl; - return PARSE_ARGUMENT_FAIL; - } - // Java's -classpath (and some other languages) delimits path components // with colons. Let's accept that syntax too just to make things more // intuitive. - std::vector parts = Split( - value, - CommandLineInterface::kPathSeparator, + std::vector parts = Split( + value, CommandLineInterface::kPathSeparator, true); for (int i = 0; i < parts.size(); i++) { - string virtual_path; - string disk_path; + std::string virtual_path; + std::string disk_path; - string::size_type equals_pos = parts[i].find_first_of('='); - if (equals_pos == string::npos) { + std::string::size_type equals_pos = parts[i].find_first_of('='); + if (equals_pos == std::string::npos) { virtual_path = ""; disk_path = parts[i]; } else { @@ -1398,13 +1726,14 @@ CommandLineInterface::InterpretArgument(const string& name, if (disk_path.empty()) { std::cerr << "--proto_path passed empty directory name. (Use \".\" for " - "current directory.)" << std::endl; + "current directory.)" + << std::endl; return PARSE_ARGUMENT_FAIL; } // Make sure disk path exists, warn otherwise. if (access(disk_path.c_str(), F_OK) < 0) { - // Try the original path; it may have just happed to have a '=' in it. + // Try the original path; it may have just happened to have a '=' in it. if (access(parts[i].c_str(), F_OK) < 0) { std::cerr << disk_path << ": warning: directory does not exist." << std::endl; @@ -1417,21 +1746,23 @@ CommandLineInterface::InterpretArgument(const string& name, // Don't use make_pair as the old/default standard library on Solaris // doesn't support it without explicit template parameters, which are // incompatible with C++0x's make_pair. - proto_path_.push_back(std::pair(virtual_path, disk_path)); + proto_path_.push_back( + std::pair(virtual_path, disk_path)); } } else if (name == "--direct_dependencies") { if (direct_dependencies_explicitly_set_) { - std::cerr << name << " may only be passed once. To specify multiple " - "direct dependencies, pass them all as a single " - "parameter separated by ':'." + std::cerr << name + << " may only be passed once. To specify multiple " + "direct dependencies, pass them all as a single " + "parameter separated by ':'." << std::endl; return PARSE_ARGUMENT_FAIL; } direct_dependencies_explicitly_set_ = true; - std::vector direct = Split( - value, ":", true); + std::vector direct = + Split(value, ":", true); GOOGLE_DCHECK(direct_dependencies_.empty()); direct_dependencies_.insert(direct.begin(), direct.end()); @@ -1440,23 +1771,17 @@ CommandLineInterface::InterpretArgument(const string& name, } else if (name == "--descriptor_set_in") { if (!descriptor_set_in_names_.empty()) { - std::cerr << name << " may only be passed once. To specify multiple " - "descriptor sets, pass them all as a single " - "parameter separated by '" - << CommandLineInterface::kPathSeparator << "'." - << std::endl; + std::cerr << name + << " may only be passed once. To specify multiple " + "descriptor sets, pass them all as a single " + "parameter separated by '" + << CommandLineInterface::kPathSeparator << "'." << std::endl; return PARSE_ARGUMENT_FAIL; } if (value.empty()) { std::cerr << name << " requires a non-empty value." << std::endl; return PARSE_ARGUMENT_FAIL; } - if (!proto_path_.empty()) { - std::cerr << "Only one of " << name - << " and --proto_path can be specified." - << std::endl; - return PARSE_ARGUMENT_FAIL; - } if (!dependency_out_name_.empty()) { std::cerr << name << " cannot be used with --dependency_out." << std::endl; @@ -1464,9 +1789,8 @@ CommandLineInterface::InterpretArgument(const string& name, } descriptor_set_in_names_ = Split( - value, - CommandLineInterface::kPathSeparator, - true); + value, CommandLineInterface::kPathSeparator, + true); } else if (name == "-o" || name == "--descriptor_set_out") { if (!descriptor_set_out_name_.empty()) { @@ -1480,7 +1804,8 @@ CommandLineInterface::InterpretArgument(const string& name, if (mode_ != MODE_COMPILE) { std::cerr << "Cannot use --encode or --decode and generate descriptors at the " - "same time." << std::endl; + "same time." + << std::endl; return PARSE_ARGUMENT_FAIL; } descriptor_set_out_name_ = value; @@ -1523,14 +1848,17 @@ CommandLineInterface::InterpretArgument(const string& name, if (!version_info_.empty()) { std::cout << version_info_ << std::endl; } - std::cout << "libprotoc " - << protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION) - << std::endl; + std::cout << "libprotoc " << internal::VersionString(PROTOBUF_VERSION) + << PROTOBUF_VERSION_SUFFIX << std::endl; return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler. } else if (name == "--disallow_services") { disallow_services_ = true; + + } else if (name == "--experimental_allow_proto3_optional") { + allow_proto3_optional_ = true; + } else if (name == "--encode" || name == "--decode" || name == "--decode_raw") { if (mode_ != MODE_COMPILE) { @@ -1561,6 +1889,9 @@ CommandLineInterface::InterpretArgument(const string& name, codec_type_ = value; + } else if (name == "--deterministic_output") { + deterministic_output_ = true; + } else if (name == "--error_format") { if (value == "gcc") { error_format_ = ERROR_FORMAT_GCC; @@ -1577,14 +1908,14 @@ CommandLineInterface::InterpretArgument(const string& name, return PARSE_ARGUMENT_FAIL; } - string plugin_name; - string path; + std::string plugin_name; + std::string path; - string::size_type equals_pos = value.find_first_of('='); - if (equals_pos == string::npos) { + std::string::size_type equals_pos = value.find_first_of('='); + if (equals_pos == std::string::npos) { // Use the basename of the file. - string::size_type slash_pos = value.find_last_of('/'); - if (slash_pos == string::npos) { + std::string::size_type slash_pos = value.find_last_of('/'); + if (slash_pos == std::string::npos) { plugin_name = value; } else { plugin_name = value.substr(slash_pos + 1); @@ -1612,7 +1943,6 @@ CommandLineInterface::InterpretArgument(const string& name, } mode_ = MODE_PRINT; print_mode_ = PRINT_FREE_FIELDS; - } else if (name == "--profile_path") { } else { // Some other flag. Look it up in the generators list. const GeneratorInfo* generator_info = @@ -1622,13 +1952,14 @@ CommandLineInterface::InterpretArgument(const string& name, // Check if it's a generator option flag. generator_info = FindOrNull(generators_by_option_name_, name); if (generator_info != NULL) { - string* parameters = &generator_parameters_[generator_info->flag_name]; + std::string* parameters = + &generator_parameters_[generator_info->flag_name]; if (!parameters->empty()) { parameters->append(","); } parameters->append(value); } else if (HasPrefixString(name, "--") && HasSuffixString(name, "_opt")) { - string* parameters = + std::string* parameters = &plugin_parameters_[PluginName(plugin_prefix_, name)]; if (!parameters->empty()) { parameters->append(","); @@ -1642,7 +1973,8 @@ CommandLineInterface::InterpretArgument(const string& name, // It's an output flag. Add it to the output directives. if (mode_ != MODE_COMPILE) { std::cerr << "Cannot use --encode, --decode or print .proto info and " - "generate code at the same time." << std::endl; + "generate code at the same time." + << std::endl; return PARSE_ARGUMENT_FAIL; } @@ -1657,8 +1989,8 @@ CommandLineInterface::InterpretArgument(const string& name, // Split value at ':' to separate the generator parameter from the // filename. However, avoid doing this if the colon is part of a valid // Windows-style absolute path. - string::size_type colon_pos = value.find_first_of(':'); - if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) { + std::string::size_type colon_pos = value.find_first_of(':'); + if (colon_pos == std::string::npos || IsWindowsAbsolutePath(value)) { directive.output_location = value; } else { directive.parameter = value.substr(0, colon_pos); @@ -1674,70 +2006,76 @@ CommandLineInterface::InterpretArgument(const string& name, void CommandLineInterface::PrintHelpText() { // Sorry for indentation here; line wrapping would be uglier. - std::cout << -"Usage: " << executable_name_ << " [OPTION] PROTO_FILES\n" -"Parse PROTO_FILES and generate output based on the options given:\n" -" -IPATH, --proto_path=PATH Specify the directory in which to search for\n" -" imports. May be specified multiple times;\n" -" directories will be searched in order. If not\n" -" given, the current working directory is used.\n" -" --version Show version info and exit.\n" -" -h, --help Show this text and exit.\n" -" --encode=MESSAGE_TYPE Read a text-format message of the given type\n" -" from standard input and write it in binary\n" -" to standard output. The message type must\n" -" be defined in PROTO_FILES or their imports.\n" -" --decode=MESSAGE_TYPE Read a binary message of the given type from\n" -" standard input and write it in text format\n" -" to standard output. The message type must\n" -" be defined in PROTO_FILES or their imports.\n" -" --decode_raw Read an arbitrary protocol message from\n" -" standard input and write the raw tag/value\n" -" pairs in text format to standard output. No\n" -" PROTO_FILES should be given when using this\n" -" flag.\n" -" --descriptor_set_in=FILES Specifies a delimited list of FILES\n" -" each containing a FileDescriptorSet (a\n" -" protocol buffer defined in descriptor.proto).\n" -" The FileDescriptor for each of the PROTO_FILES\n" -" provided will be loaded from these\n" -" FileDescriptorSets. If a FileDescriptor\n" -" appears multiple times, the first occurrence\n" -" will be used.\n" -" -oFILE, Writes a FileDescriptorSet (a protocol buffer,\n" -" --descriptor_set_out=FILE defined in descriptor.proto) containing all of\n" -" the input files to FILE.\n" -" --include_imports When using --descriptor_set_out, also include\n" -" all dependencies of the input files in the\n" -" set, so that the set is self-contained.\n" -" --include_source_info When using --descriptor_set_out, do not strip\n" -" SourceCodeInfo from the FileDescriptorProto.\n" -" This results in vastly larger descriptors that\n" -" include information about the original\n" -" location of each decl in the source file as\n" -" well as surrounding comments.\n" -" --dependency_out=FILE Write a dependency output file in the format\n" -" expected by make. This writes the transitive\n" -" set of input file paths to FILE\n" -" --error_format=FORMAT Set the format in which to print errors.\n" -" FORMAT may be 'gcc' (the default) or 'msvs'\n" -" (Microsoft Visual Studio format).\n" -" --print_free_field_numbers Print the free field numbers of the messages\n" -" defined in the given proto files. Groups share\n" -" the same field number space with the parent \n" -" message. Extension ranges are counted as \n" -" occupied fields numbers.\n" - << std::endl; + std::cout << "Usage: " << executable_name_ << " [OPTION] PROTO_FILES"; + std::cout << R"( +Parse PROTO_FILES and generate output based on the options given: + -IPATH, --proto_path=PATH Specify the directory in which to search for + imports. May be specified multiple times; + directories will be searched in order. If not + given, the current working directory is used. + If not found in any of the these directories, + the --descriptor_set_in descriptors will be + checked for required proto file. + --version Show version info and exit. + -h, --help Show this text and exit. + --encode=MESSAGE_TYPE Read a text-format message of the given type + from standard input and write it in binary + to standard output. The message type must + be defined in PROTO_FILES or their imports. + --deterministic_output When using --encode, ensure map fields are + deterministically ordered. Note that this order + is not canonical, and changes across builds or + releases of protoc. + --decode=MESSAGE_TYPE Read a binary message of the given type from + standard input and write it in text format + to standard output. The message type must + be defined in PROTO_FILES or their imports. + --decode_raw Read an arbitrary protocol message from + standard input and write the raw tag/value + pairs in text format to standard output. No + PROTO_FILES should be given when using this + flag. + --descriptor_set_in=FILES Specifies a delimited list of FILES + each containing a FileDescriptorSet (a + protocol buffer defined in descriptor.proto). + The FileDescriptor for each of the PROTO_FILES + provided will be loaded from these + FileDescriptorSets. If a FileDescriptor + appears multiple times, the first occurrence + will be used. + -oFILE, Writes a FileDescriptorSet (a protocol buffer, + --descriptor_set_out=FILE defined in descriptor.proto) containing all of + the input files to FILE. + --include_imports When using --descriptor_set_out, also include + all dependencies of the input files in the + set, so that the set is self-contained. + --include_source_info When using --descriptor_set_out, do not strip + SourceCodeInfo from the FileDescriptorProto. + This results in vastly larger descriptors that + include information about the original + location of each decl in the source file as + well as surrounding comments. + --dependency_out=FILE Write a dependency output file in the format + expected by make. This writes the transitive + set of input file paths to FILE + --error_format=FORMAT Set the format in which to print errors. + FORMAT may be 'gcc' (the default) or 'msvs' + (Microsoft Visual Studio format). + --print_free_field_numbers Print the free field numbers of the messages + defined in the given proto files. Groups share + the same field number space with the parent + message. Extension ranges are counted as + occupied fields numbers.)"; if (!plugin_prefix_.empty()) { - std::cout << -" --plugin=EXECUTABLE Specifies a plugin executable to use.\n" -" Normally, protoc searches the PATH for\n" -" plugins, but you may specify additional\n" -" executables not in the path using this flag.\n" -" Additionally, EXECUTABLE may be of the form\n" -" NAME=PATH, in which case the given plugin name\n" -" is mapped to the given executable even if\n" -" the executable's own name differs." << std::endl; + std::cout << R"( + --plugin=EXECUTABLE Specifies a plugin executable to use. + Normally, protoc searches the PATH for + plugins, but you may specify additional + executables not in the path using this flag. + Additionally, EXECUTABLE may be of the form + NAME=PATH, in which case the given plugin name + is mapped to the given executable even if + the executable's own name differs.)"; } for (GeneratorMap::iterator iter = generators_by_flag_name_.begin(); @@ -1745,10 +2083,48 @@ void CommandLineInterface::PrintHelpText() { // FIXME(kenton): If the text is long enough it will wrap, which is ugly, // but fixing this nicely (e.g. splitting on spaces) is probably more // trouble than it's worth. - std::cout << " " << iter->first << "=OUT_DIR " - << string(19 - iter->first.size(), ' ') // Spaces for alignment. - << iter->second.help_text << std::endl; + std::cout << std::endl + << " " << iter->first << "=OUT_DIR " + << std::string(19 - iter->first.size(), + ' ') // Spaces for alignment. + << iter->second.help_text; + } + std::cout << R"( + @ Read options and filenames from file. If a + relative file path is specified, the file + will be searched in the working directory. + The --proto_path option will not affect how + this argument file is searched. Content of + the file will be expanded in the position of + @ as in the argument list. Note + that shell expansion is not applied to the + content of the file (i.e., you cannot use + quotes, wildcards, escapes, commands, etc.). + Each line corresponds to a single argument, + even if it contains spaces.)"; + std::cout << std::endl; +} + +bool CommandLineInterface::EnforceProto3OptionalSupport( + const std::string& codegen_name, uint64 supported_features, + const std::vector& parsed_files) const { + bool supports_proto3_optional = + supported_features & CodeGenerator::FEATURE_PROTO3_OPTIONAL; + if (!supports_proto3_optional) { + for (const auto fd : parsed_files) { + if (ContainsProto3Optional(fd)) { + std::cerr << fd->name() + << ": is a proto3 file that contains optional fields, but " + "code generator " + << codegen_name + << " hasn't been updated to support optional fields in " + "proto3. Please ask the owner of this code generator to " + "support proto3 optional."; + return false; + } + } } + return true; } bool CommandLineInterface::GenerateOutput( @@ -1756,38 +2132,43 @@ bool CommandLineInterface::GenerateOutput( const OutputDirective& output_directive, GeneratorContext* generator_context) { // Call the generator. - string error; + std::string error; if (output_directive.generator == NULL) { // This is a plugin. GOOGLE_CHECK(HasPrefixString(output_directive.name, "--") && HasSuffixString(output_directive.name, "_out")) << "Bad name for plugin generator: " << output_directive.name; - string plugin_name = PluginName(plugin_prefix_ , output_directive.name); - string parameters = output_directive.parameter; + std::string plugin_name = PluginName(plugin_prefix_, output_directive.name); + std::string parameters = output_directive.parameter; if (!plugin_parameters_[plugin_name].empty()) { if (!parameters.empty()) { parameters.append(","); } parameters.append(plugin_parameters_[plugin_name]); } - if (!GeneratePluginOutput(parsed_files, plugin_name, - parameters, + if (!GeneratePluginOutput(parsed_files, plugin_name, parameters, generator_context, &error)) { std::cerr << output_directive.name << ": " << error << std::endl; return false; } } else { // Regular generator. - string parameters = output_directive.parameter; + std::string parameters = output_directive.parameter; if (!generator_parameters_[output_directive.name].empty()) { if (!parameters.empty()) { parameters.append(","); } parameters.append(generator_parameters_[output_directive.name]); } - if (!output_directive.generator->GenerateAll( - parsed_files, parameters, generator_context, &error)) { + if (!EnforceProto3OptionalSupport( + output_directive.name, + output_directive.generator->GetSupportedFeatures(), parsed_files)) { + return false; + } + + if (!output_directive.generator->GenerateAll(parsed_files, parameters, + generator_context, &error)) { // Generator returned an error. std::cerr << output_directive.name << ": " << error << std::endl; return false; @@ -1805,22 +2186,18 @@ bool CommandLineInterface::GenerateDependencyManifestFile( std::set already_seen; for (int i = 0; i < parsed_files.size(); i++) { - GetTransitiveDependencies(parsed_files[i], - false, - false, - &already_seen, + GetTransitiveDependencies(parsed_files[i], false, false, &already_seen, file_set.mutable_file()); } - std::vector output_filenames; - for (GeneratorContextMap::const_iterator iter = output_directories.begin(); - iter != output_directories.end(); ++iter) { - const string& location = iter->first; - GeneratorContextImpl* directory = iter->second; - std::vector relative_output_filenames; + std::vector output_filenames; + for (const auto& pair : output_directories) { + const std::string& location = pair.first; + GeneratorContextImpl* directory = pair.second.get(); + std::vector relative_output_filenames; directory->GetOutputFilenames(&relative_output_filenames); for (int i = 0; i < relative_output_filenames.size(); i++) { - string output_filename = location + relative_output_filenames[i]; + std::string output_filename = location + relative_output_filenames[i]; if (output_filename.compare(0, 2, "./") == 0) { output_filename = output_filename.substr(2); } @@ -1853,8 +2230,8 @@ bool CommandLineInterface::GenerateDependencyManifestFile( for (int i = 0; i < file_set.file_size(); i++) { const FileDescriptorProto& file = file_set.file(i); - const string& virtual_file = file.name(); - string disk_file; + const std::string& virtual_file = file.name(); + std::string disk_file; if (source_tree && source_tree->VirtualFileToDiskFile(virtual_file, &disk_file)) { printer.Print(" $disk_file$", "disk_file", disk_file); @@ -1871,16 +2248,16 @@ bool CommandLineInterface::GenerateDependencyManifestFile( bool CommandLineInterface::GeneratePluginOutput( const std::vector& parsed_files, - const string& plugin_name, - const string& parameter, - GeneratorContext* generator_context, - string* error) { + const std::string& plugin_name, const std::string& parameter, + GeneratorContext* generator_context, std::string* error) { CodeGeneratorRequest request; CodeGeneratorResponse response; + std::string processed_parameter = parameter; + // Build the request. - if (!parameter.empty()) { - request.set_parameter(parameter); + if (!processed_parameter.empty()) { + request.set_parameter(processed_parameter); } @@ -1895,10 +2272,10 @@ bool CommandLineInterface::GeneratePluginOutput( google::protobuf::compiler::Version* version = request.mutable_compiler_version(); - version->set_major(GOOGLE_PROTOBUF_VERSION / 1000000); - version->set_minor(GOOGLE_PROTOBUF_VERSION / 1000 % 1000); - version->set_patch(GOOGLE_PROTOBUF_VERSION % 1000); - version->set_suffix(GOOGLE_PROTOBUF_VERSION_SUFFIX); + version->set_major(PROTOBUF_VERSION / 1000000); + version->set_minor(PROTOBUF_VERSION / 1000 % 1000); + version->set_patch(PROTOBUF_VERSION % 1000); + version->set_suffix(PROTOBUF_VERSION_SUFFIX); // Invoke the plugin. Subprocess subprocess; @@ -1909,7 +2286,7 @@ bool CommandLineInterface::GeneratePluginOutput( subprocess.Start(plugin_name, Subprocess::SEARCH_PATH); } - string communicate_error; + std::string communicate_error; if (!subprocess.Communicate(request, &response, &communicate_error)) { *error = strings::Substitute("$0: $1", plugin_name, communicate_error); return false; @@ -1917,17 +2294,20 @@ bool CommandLineInterface::GeneratePluginOutput( // Write the files. We do this even if there was a generator error in order // to match the behavior of a compiled-in generator. - google::protobuf::scoped_ptr current_output; + std::unique_ptr current_output; for (int i = 0; i < response.file_size(); i++) { const CodeGeneratorResponse::File& output_file = response.file(i); if (!output_file.insertion_point().empty()) { + std::string filename = output_file.name(); // Open a file for insert. // We reset current_output to NULL first so that the old file is closed // before the new one is opened. current_output.reset(); - current_output.reset(generator_context->OpenForInsert( - output_file.name(), output_file.insertion_point())); + current_output.reset( + generator_context->OpenForInsertWithGeneratedCodeInfo( + filename, output_file.insertion_point(), + output_file.generated_code_info())); } else if (!output_file.name().empty()) { // Starting a new file. Open it. // We reset current_output to NULL first so that the old file is closed @@ -1936,8 +2316,9 @@ bool CommandLineInterface::GeneratePluginOutput( current_output.reset(generator_context->Open(output_file.name())); } else if (current_output == NULL) { *error = strings::Substitute( - "$0: First file chunk returned by plugin did not specify a file name.", - plugin_name); + "$0: First file chunk returned by plugin did not specify a file " + "name.", + plugin_name); return false; } @@ -1952,6 +2333,9 @@ bool CommandLineInterface::GeneratePluginOutput( // Generator returned an error. *error = response.error(); return false; + } else if (!EnforceProto3OptionalSupport( + plugin_name, response.supported_features(), parsed_files)) { + return false; } return true; @@ -1966,7 +2350,7 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) { } DynamicMessageFactory dynamic_factory(pool); - google::protobuf::scoped_ptr message(dynamic_factory.GetPrototype(type)->New()); + std::unique_ptr message(dynamic_factory.GetPrototype(type)->New()); if (mode_ == MODE_ENCODE) { SetFdToTextMode(STDIN_FILENO); @@ -2005,7 +2389,9 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) { if (mode_ == MODE_ENCODE) { // Output is binary. - if (!message->SerializePartialToZeroCopyStream(&out)) { + io::CodedOutputStream coded_out(&out); + coded_out.SetSerializationDeterministic(deterministic_output_); + if (!message->SerializePartialToCodedStream(&coded_out)) { std::cerr << "output: I/O error." << std::endl; return false; } @@ -2046,8 +2432,8 @@ bool CommandLineInterface::WriteDescriptorSet( for (int i = 0; i < parsed_files.size(); i++) { GetTransitiveDependencies(parsed_files[i], true, // Include json_name - source_info_in_descriptor_set_, - &already_seen, file_set.mutable_file()); + source_info_in_descriptor_set_, &already_seen, + file_set.mutable_file()); } int fd; @@ -2062,12 +2448,20 @@ bool CommandLineInterface::WriteDescriptorSet( } io::FileOutputStream out(fd); - if (!file_set.SerializeToZeroCopyStream(&out)) { - std::cerr << descriptor_set_out_name_ << ": " << strerror(out.GetErrno()) - << std::endl; - out.Close(); - return false; + + { + io::CodedOutputStream coded_out(&out); + // Determinism is useful here because build outputs are sometimes checked + // into version control. + coded_out.SetSerializationDeterministic(true); + if (!file_set.SerializeToCodedStream(&coded_out)) { + std::cerr << descriptor_set_out_name_ << ": " << strerror(out.GetErrno()) + << std::endl; + out.Close(); + return false; + } } + if (!out.Close()) { std::cerr << descriptor_set_out_name_ << ": " << strerror(out.GetErrno()) << std::endl; @@ -2078,8 +2472,7 @@ bool CommandLineInterface::WriteDescriptorSet( } void CommandLineInterface::GetTransitiveDependencies( - const FileDescriptor* file, - bool include_json_name, + const FileDescriptor* file, bool include_json_name, bool include_source_code_info, std::set* already_seen, RepeatedPtrField* output) { @@ -2090,10 +2483,8 @@ void CommandLineInterface::GetTransitiveDependencies( // Add all dependencies. for (int i = 0; i < file->dependency_count(); i++) { - GetTransitiveDependencies(file->dependency(i), - include_json_name, - include_source_code_info, - already_seen, output); + GetTransitiveDependencies(file->dependency(i), include_json_name, + include_source_code_info, already_seen, output); } // Add this file. @@ -2117,7 +2508,7 @@ namespace { // Nested Messages: // Note that it only stores the nested message type, iff the nested type is // either a direct child of the given descriptor, or the nested type is a -// decendent of the given descriptor and all the nodes between the +// descendant of the given descriptor and all the nodes between the // nested type and the given descriptor are group types. e.g. // // message Foo { @@ -2175,9 +2566,9 @@ void GatherOccupiedFieldRanges( // Utility function for PrintFreeFieldNumbers. // Actually prints the formatted free field numbers for given message name and // occupied ranges. -void FormatFreeFieldNumbers(const string& name, +void FormatFreeFieldNumbers(const std::string& name, const std::set& ranges) { - string output; + std::string output; StringAppendF(&output, "%-35s free:", name.c_str()); int next_free_number = 1; for (std::set::const_iterator i = ranges.begin(); @@ -2205,8 +2596,7 @@ void FormatFreeFieldNumbers(const string& name, } // namespace -void CommandLineInterface::PrintFreeFieldNumbers( - const Descriptor* descriptor) { +void CommandLineInterface::PrintFreeFieldNumbers(const Descriptor* descriptor) { std::set ranges; std::vector nested_messages; GatherOccupiedFieldRanges(descriptor, &ranges, &nested_messages); @@ -2218,7 +2608,6 @@ void CommandLineInterface::PrintFreeFieldNumbers( } - } // namespace compiler } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index e65965754e51f..12ba653758d39 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -38,24 +38,30 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__ #define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__ -#include -#include -#include -#include #include +#include #include +#include +#include +#include #include +#include + +#include +#include namespace google { namespace protobuf { -class Descriptor; // descriptor.h -class DescriptorPool; // descriptor.h -class FileDescriptor; // descriptor.h -class FileDescriptorSet; // descriptor.h -class FileDescriptorProto; // descriptor.pb.h -template class RepeatedPtrField; // repeated_field.h -class SimpleDescriptorDatabase; // descriptor_database.h +class Descriptor; // descriptor.h +class DescriptorDatabase; // descriptor_database.h +class DescriptorPool; // descriptor.h +class FileDescriptor; // descriptor.h +class FileDescriptorSet; // descriptor.h +class FileDescriptorProto; // descriptor.pb.h +template +class RepeatedPtrField; // repeated_field.h +class SimpleDescriptorDatabase; // descriptor_database.h namespace compiler { @@ -91,17 +97,17 @@ class DiskSourceTree; // importer.h // protoc --cpp_out=outdir --foo_out=outdir --proto_path=src src/foo.proto // // The .proto file to compile can be specified on the command line using either -// its physical file path, or a virtual path relative to a diretory specified +// its physical file path, or a virtual path relative to a directory specified // in --proto_path. For example, for src/foo.proto, the following two protoc // invocations work the same way: // 1. protoc --proto_path=src src/foo.proto (physical file path) // 2. protoc --proto_path=src foo.proto (virtual path relative to src) // // If a file path can be interpreted both as a physical file path and as a -// relative virtual path, the physical file path takes precendence. +// relative virtual path, the physical file path takes precedence. // // For a full description of the command-line syntax, invoke it with --help. -class LIBPROTOC_EXPORT CommandLineInterface { +class PROTOC_EXPORT CommandLineInterface { public: static const char* const kPathSeparator; @@ -124,9 +130,8 @@ class LIBPROTOC_EXPORT CommandLineInterface { // protoc --foo_out=enable_bar:outdir // The text before the colon is passed to CodeGenerator::Generate() as the // "parameter". - void RegisterGenerator(const string& flag_name, - CodeGenerator* generator, - const string& help_text); + void RegisterGenerator(const std::string& flag_name, CodeGenerator* generator, + const std::string& help_text); // Register a code generator for a language. // Besides flag_name you can specify another option_flag_name that could be @@ -136,10 +141,10 @@ class LIBPROTOC_EXPORT CommandLineInterface { // Then you could invoke the compiler with a command like: // protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz // This will pass "enable_bar,enable_baz" as the parameter to the generator. - void RegisterGenerator(const string& flag_name, - const string& option_flag_name, + void RegisterGenerator(const std::string& flag_name, + const std::string& option_flag_name, CodeGenerator* generator, - const string& help_text); + const std::string& help_text); // Enables "plugins". In this mode, if a command-line flag ends with "_out" // but does not match any registered generator, the compiler will attempt to @@ -149,7 +154,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { // The compiler determines the executable name to search for by concatenating // exe_name_prefix with the unrecognized flag name, removing "_out". So, for // example, if exe_name_prefix is "protoc-" and you pass the flag --foo_out, - // the compiler will try to run the program "protoc-foo". + // the compiler will try to run the program "protoc-gen-foo". // // The plugin program should implement the following usage: // plugin [--out=OUTDIR] [--parameter=PARAMETER] PROTO_FILES < DESCRIPTORS @@ -177,7 +182,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { // protoc --plug_out=enable_bar:outdir --plug_opt=enable_baz // This will pass "enable_bar,enable_baz" as the parameter to the plugin. // - void AllowPlugins(const string& exe_name_prefix); + void AllowPlugins(const std::string& exe_name_prefix); // Run the Protocol Compiler with the given command-line parameters. // Returns the error code which should be returned by main(). @@ -189,15 +194,13 @@ class LIBPROTOC_EXPORT CommandLineInterface { // DEPRECATED. Calling this method has no effect. Protocol compiler now // always try to find the .proto file relative to the current directory // first and if the file is not found, it will then treat the input path - // as a virutal path. + // as a virtual path. void SetInputsAreProtoPathRelative(bool /* enable */) {} // Provides some text which will be printed when the --version flag is // used. The version of libprotoc will also be printed on the next line // after this text. - void SetVersionInfo(const string& text) { - version_info_ = text; - } + void SetVersionInfo(const std::string& text) { version_info_ = text; } private: @@ -206,16 +209,34 @@ class LIBPROTOC_EXPORT CommandLineInterface { class ErrorPrinter; class GeneratorContextImpl; class MemoryOutputStream; - typedef hash_map GeneratorContextMap; + typedef std::unordered_map> + GeneratorContextMap; // Clear state from previous Run(). void Clear(); + // Remaps the proto file so that it is relative to one of the directories + // in proto_path_. Returns false if an error occurred. + bool MakeProtoProtoPathRelative(DiskSourceTree* source_tree, + std::string* proto, + DescriptorDatabase* fallback_database); + // Remaps each file in input_files_ so that it is relative to one of the - // directories in proto_path_. Returns false if an error occurred. This - // is only used if inputs_are_proto_path_relative_ is false. - bool MakeInputsBeProtoPathRelative( - DiskSourceTree* source_tree); + // directories in proto_path_. Returns false if an error occurred. + bool MakeInputsBeProtoPathRelative(DiskSourceTree* source_tree, + DescriptorDatabase* fallback_database); + + // Is this .proto file whitelisted, or do we have a command-line flag allowing + // us to use proto3 optional? This is a temporary control to avoid people from + // using proto3 optional until code generators have implemented it. + bool AllowProto3Optional(const FileDescriptor& file) const; + + // Fails if these files use proto3 optional and the code generator doesn't + // support it. This is a permanent check. + bool EnforceProto3OptionalSupport( + const std::string& codegen_name, uint64 supported_features, + const std::vector& parsed_files) const; + // Return status for ParseArguments() and InterpretArgument(). enum ParseArgumentStatus { @@ -227,6 +248,10 @@ class LIBPROTOC_EXPORT CommandLineInterface { // Parse all command-line arguments. ParseArgumentStatus ParseArguments(int argc, const char* const argv[]); + // Read an argument file and append the file's content to the list of + // arguments. Return false if the file cannot be read. + bool ExpandArgumentFile(const std::string& file, + std::vector* arguments); // Parses a command-line argument into a name/value pair. Returns // true if the next argument in the argv should be used as the value, @@ -239,23 +264,25 @@ class LIBPROTOC_EXPORT CommandLineInterface { // name = "--cpp_out", value = "src/foo.pb2.cc" // "foo.proto" -> // name = "", value = "foo.proto" - bool ParseArgument(const char* arg, string* name, string* value); + bool ParseArgument(const char* arg, std::string* name, std::string* value); // Interprets arguments parsed with ParseArgument. - ParseArgumentStatus InterpretArgument(const string& name, - const string& value); + ParseArgumentStatus InterpretArgument(const std::string& name, + const std::string& value); // Print the --help text to stderr. void PrintHelpText(); // Loads proto_path_ into the provided source_tree. - bool InitializeDiskSourceTree(DiskSourceTree* source_tree); + bool InitializeDiskSourceTree(DiskSourceTree* source_tree, + DescriptorDatabase* fallback_database); - // Loads descriptor_set_in into the provided database - bool PopulateSimpleDescriptorDatabase(SimpleDescriptorDatabase* database); + // Verify that all the input files exist in the given database. + bool VerifyInputFilesInDescriptors(DescriptorDatabase* fallback_database); // Parses input_files_ into parsed_files bool ParseInputFiles(DescriptorPool* descriptor_pool, + DiskSourceTree* source_tree, std::vector* parsed_files); // Generate the given output file from the given input. @@ -265,8 +292,8 @@ class LIBPROTOC_EXPORT CommandLineInterface { GeneratorContext* generator_context); bool GeneratePluginOutput( const std::vector& parsed_files, - const string& plugin_name, const string& parameter, - GeneratorContext* generator_context, string* error); + const std::string& plugin_name, const std::string& parameter, + GeneratorContext* generator_context, std::string* error); // Implements --encode and --decode. bool EncodeOrDecode(const DescriptorPool* pool); @@ -291,8 +318,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { // If include_json_name is true, populate the json_name field of // FieldDescriptorProto for all fields. static void GetTransitiveDependencies( - const FileDescriptor* file, - bool include_json_name, + const FileDescriptor* file, bool include_json_name, bool include_source_code_info, std::set* already_seen, RepeatedPtrField* output); @@ -316,36 +342,36 @@ class LIBPROTOC_EXPORT CommandLineInterface { // ----------------------------------------------------------------- // The name of the executable as invoked (i.e. argv[0]). - string executable_name_; + std::string executable_name_; // Version info set with SetVersionInfo(). - string version_info_; + std::string version_info_; // Registered generators. struct GeneratorInfo { - string flag_name; - string option_flag_name; + std::string flag_name; + std::string option_flag_name; CodeGenerator* generator; - string help_text; + std::string help_text; }; - typedef std::map GeneratorMap; + typedef std::map GeneratorMap; GeneratorMap generators_by_flag_name_; GeneratorMap generators_by_option_name_; // A map from generator names to the parameters specified using the option // flag. For example, if the user invokes the compiler with: // protoc --foo_out=outputdir --foo_opt=enable_bar ... // Then there will be an entry ("--foo_out", "enable_bar") in this map. - std::map generator_parameters_; + std::map generator_parameters_; // Similar to generator_parameters_, but stores the parameters for plugins. - std::map plugin_parameters_; + std::map plugin_parameters_; // See AllowPlugins(). If this is empty, plugins aren't allowed. - string plugin_prefix_; + std::string plugin_prefix_; // Maps specific plugin names to files. When executing a plugin, this map // is searched first to find the plugin executable. If not found here, the // PATH (or other OS-specific search strategy) is searched. - std::map plugins_; + std::map plugins_; // Stuff parsed from command line. enum Mode { @@ -355,65 +381,60 @@ class LIBPROTOC_EXPORT CommandLineInterface { MODE_PRINT, // Print mode: print info of the given .proto files and exit. }; - Mode mode_; + Mode mode_ = MODE_COMPILE; enum PrintMode { - PRINT_NONE, // Not in MODE_PRINT - PRINT_FREE_FIELDS, // --print_free_fields + PRINT_NONE, // Not in MODE_PRINT + PRINT_FREE_FIELDS, // --print_free_fields }; - PrintMode print_mode_; + PrintMode print_mode_ = PRINT_NONE; enum ErrorFormat { - ERROR_FORMAT_GCC, // GCC error output format (default). - ERROR_FORMAT_MSVS // Visual Studio output (--error_format=msvs). + ERROR_FORMAT_GCC, // GCC error output format (default). + ERROR_FORMAT_MSVS // Visual Studio output (--error_format=msvs). }; - ErrorFormat error_format_; + ErrorFormat error_format_ = ERROR_FORMAT_GCC; - std::vector > - proto_path_; // Search path for proto files. - std::vector input_files_; // Names of the input proto files. + std::vector > + proto_path_; // Search path for proto files. + std::vector input_files_; // Names of the input proto files. // Names of proto files which are allowed to be imported. Used by build // systems to enforce depend-on-what-you-import. - std::set direct_dependencies_; - bool direct_dependencies_explicitly_set_; + std::set direct_dependencies_; + bool direct_dependencies_explicitly_set_ = false; // If there's a violation of depend-on-what-you-import, this string will be // presented to the user. "%s" will be replaced with the violating import. - string direct_dependencies_violation_msg_; + std::string direct_dependencies_violation_msg_; // output_directives_ lists all the files we are supposed to output and what // generator to use for each. struct OutputDirective { - string name; // E.g. "--foo_out" - CodeGenerator* generator; // NULL for plugins - string parameter; - string output_location; + std::string name; // E.g. "--foo_out" + CodeGenerator* generator; // NULL for plugins + std::string parameter; + std::string output_location; }; std::vector output_directives_; // When using --encode or --decode, this names the type we are encoding or // decoding. (Empty string indicates --decode_raw.) - string codec_type_; + std::string codec_type_; // If --descriptor_set_in was given, these are filenames containing // parsed FileDescriptorSets to be used for loading protos. Otherwise, empty. - std::vector descriptor_set_in_names_; + std::vector descriptor_set_in_names_; // If --descriptor_set_out was given, this is the filename to which the // FileDescriptorSet should be written. Otherwise, empty. - string descriptor_set_out_name_; + std::string descriptor_set_out_name_; // If --dependency_out was given, this is the path to the file where the // dependency file will be written. Otherwise, empty. - string dependency_out_name_; - - // Path to a file that contains serialized AccessInfo which provides - // relative hotness of fields per message. This helps protoc to generate - // better code. - string profile_path_; + std::string dependency_out_name_; // True if --include_imports was given, meaning that we should // write all transitive dependencies to the DescriptorSet. Otherwise, only @@ -422,16 +443,24 @@ class LIBPROTOC_EXPORT CommandLineInterface { // True if --include_source_info was given, meaning that we should not strip // SourceCodeInfo from the DescriptorSet. - bool source_info_in_descriptor_set_; + bool source_info_in_descriptor_set_ = false; // Was the --disallow_services flag used? - bool disallow_services_; + bool disallow_services_ = false; + + // Was the --experimental_allow_proto3_optional flag used? + bool allow_proto3_optional_ = false; + + // When using --encode, this will be passed to SetSerializationDeterministic. + bool deterministic_output_ = false; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface); }; } // namespace compiler } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__ diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 73d3e4c9a6d0a..2bf0582630f46 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -35,58 +35,60 @@ #include #include #include + #ifndef _MSC_VER #include #endif #include -#ifndef _SHARED_PTR_H -#include -#endif +#include #include #include #include #include +#include +#include #include #include #include #include +#include #include +#include #include #include #include #include -#include - -#include #include #include - #include -#include +#include +#include + namespace google { namespace protobuf { namespace compiler { -#if defined(_MSC_VER) +#if defined(_WIN32) // DO NOT include , instead create functions in io_win32.{h,cc} and import // them like we do below. -using google::protobuf::internal::win32::access; -using google::protobuf::internal::win32::dup; -using google::protobuf::internal::win32::dup2; -using google::protobuf::internal::win32::close; -using google::protobuf::internal::win32::open; -using google::protobuf::internal::win32::write; +using google::protobuf::io::win32::access; +using google::protobuf::io::win32::close; +using google::protobuf::io::win32::dup; +using google::protobuf::io::win32::dup2; +using google::protobuf::io::win32::open; +using google::protobuf::io::win32::write; #endif // Disable the whole test when we use tcmalloc for "draconian" heap checks, in // which case tcmalloc will print warnings that fail the plugin tests. #if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN + namespace { -bool FileExists(const string& path) { +bool FileExists(const std::string& path) { return File::Exists(path); } @@ -98,8 +100,8 @@ class CommandLineInterfaceTest : public testing::Test { // Runs the CommandLineInterface with the given command line. The // command is automatically split on spaces, and the string "$tmpdir" // is replaced with TestTempDir(). - void Run(const string& command); - void RunWithArgs(std::vector args); + void Run(const std::string& command); + void RunWithArgs(std::vector args); // ----------------------------------------------------------------- // Methods to set up the test (called before Run()). @@ -112,10 +114,10 @@ class CommandLineInterfaceTest : public testing::Test { // Create a temp file within temp_directory_ with the given name. // The containing directory is also created if necessary. - void CreateTempFile(const string& name, const string& contents); + void CreateTempFile(const std::string& name, const std::string& contents); // Create a subdirectory within temp_directory_. - void CreateTempDir(const string& name); + void CreateTempDir(const std::string& name); #ifdef PROTOBUF_OPENSOURCE // Change working directory to temp directory. @@ -137,27 +139,29 @@ class CommandLineInterfaceTest : public testing::Test { // Checks that Run() returned non-zero and the stderr output is exactly // the text given. expected_test may contain references to "$tmpdir", // which will be replaced by the temporary directory path. - void ExpectErrorText(const string& expected_text); + void ExpectErrorText(const std::string& expected_text); // Checks that Run() returned non-zero and the stderr contains the given // substring. - void ExpectErrorSubstring(const string& expected_substring); + void ExpectErrorSubstring(const std::string& expected_substring); - // Like ExpectErrorSubstring, but checks that Run() returned zero. - void ExpectErrorSubstringWithZeroReturnCode( - const string& expected_substring); + // Checks that Run() returned zero and the stderr contains the given + // substring. + void ExpectWarningSubstring(const std::string& expected_substring); // Checks that the captured stdout is the same as the expected_text. - void ExpectCapturedStdout(const string& expected_text); + void ExpectCapturedStdout(const std::string& expected_text); // Checks that Run() returned zero and the stdout contains the given // substring. void ExpectCapturedStdoutSubstringWithZeroReturnCode( - const string& expected_substring); + const std::string& expected_substring); +#if defined(_WIN32) && !defined(__CYGWIN__) // Returns true if ExpectErrorSubstring(expected_substring) would pass, but // does not fail otherwise. - bool HasAlternateErrorSubstring(const string& expected_substring); + bool HasAlternateErrorSubstring(const std::string& expected_substring); +#endif // _WIN32 && !__CYGWIN__ // Checks that MockCodeGenerator::Generate() was called in the given // context (or the generator in test_plugin.cc, which produces the same @@ -168,37 +172,51 @@ class CommandLineInterfaceTest : public testing::Test { // generate given these inputs. message_name is the name of the first // message that appeared in the proto file; this is just to make extra // sure that the correct file was parsed. - void ExpectGenerated(const string& generator_name, - const string& parameter, - const string& proto_name, - const string& message_name); - void ExpectGenerated(const string& generator_name, - const string& parameter, - const string& proto_name, - const string& message_name, - const string& output_directory); - void ExpectGeneratedWithMultipleInputs(const string& generator_name, - const string& all_proto_names, - const string& proto_name, - const string& message_name); - void ExpectGeneratedWithInsertions(const string& generator_name, - const string& parameter, - const string& insertions, - const string& proto_name, - const string& message_name); - void CheckGeneratedAnnotations(const string& name, const string& file); - - void ExpectNullCodeGeneratorCalled(const string& parameter); - - - void ReadDescriptorSet(const string& filename, + void ExpectGenerated(const std::string& generator_name, + const std::string& parameter, + const std::string& proto_name, + const std::string& message_name); + void ExpectGenerated(const std::string& generator_name, + const std::string& parameter, + const std::string& proto_name, + const std::string& message_name, + const std::string& output_directory); + void ExpectGeneratedWithMultipleInputs(const std::string& generator_name, + const std::string& all_proto_names, + const std::string& proto_name, + const std::string& message_name); + void ExpectGeneratedWithInsertions(const std::string& generator_name, + const std::string& parameter, + const std::string& insertions, + const std::string& proto_name, + const std::string& message_name); + void CheckGeneratedAnnotations(const std::string& name, + const std::string& file); + +#if defined(_WIN32) + void ExpectNullCodeGeneratorCalled(const std::string& parameter); +#endif // _WIN32 + + + void ReadDescriptorSet(const std::string& filename, FileDescriptorSet* descriptor_set); - void WriteDescriptorSet(const string& filename, + void WriteDescriptorSet(const std::string& filename, const FileDescriptorSet* descriptor_set); - void ExpectFileContent(const string& filename, - const string& content); + void ExpectFileContent(const std::string& filename, + const std::string& content); + + // The default code generators support all features. Use this to create a + // code generator that omits the given feature(s). + void CreateGeneratorWithMissingFeatures(const std::string& name, + const std::string& description, + uint64 features) { + MockCodeGenerator* generator = new MockCodeGenerator(name); + generator->SuppressFeatures(features); + mock_generators_to_delete_.push_back(generator); + cli_.RegisterGenerator(name, generator, description); + } private: // The object we are testing. @@ -211,16 +229,16 @@ class CommandLineInterfaceTest : public testing::Test { // protection against accidentally deleting user files (since we recursively // delete this directory during the test). This is the full path of that // directory. - string temp_directory_; + std::string temp_directory_; // The result of Run(). int return_code_; // The captured stderr output. - string error_text_; + std::string error_text_; // The captured stdout. - string captured_stdout_; + std::string captured_stdout_; // Pointers which need to be deleted later. std::vector mock_generators_to_delete_; @@ -234,13 +252,11 @@ class CommandLineInterfaceTest::NullCodeGenerator : public CodeGenerator { ~NullCodeGenerator() {} mutable bool called_; - mutable string parameter_; + mutable std::string parameter_; // implements CodeGenerator ---------------------------------------- - bool Generate(const FileDescriptor* file, - const string& parameter, - GeneratorContext* context, - string* error) const { + bool Generate(const FileDescriptor* file, const std::string& parameter, + GeneratorContext* context, std::string* error) const { called_ = true; parameter_ = parameter; return true; @@ -292,34 +308,36 @@ void CommandLineInterfaceTest::TearDown() { mock_generators_to_delete_.clear(); } -void CommandLineInterfaceTest::Run(const string& command) { +void CommandLineInterfaceTest::Run(const std::string& command) { RunWithArgs(Split(command, " ", true)); } -void CommandLineInterfaceTest::RunWithArgs(std::vector args) { +void CommandLineInterfaceTest::RunWithArgs(std::vector args) { if (!disallow_plugins_) { cli_.AllowPlugins("prefix-"); -#ifndef GOOGLE_THIRD_PARTY_PROTOBUF - string plugin_path; + std::string plugin_path; #ifdef GOOGLE_PROTOBUF_TEST_PLUGIN_PATH plugin_path = GOOGLE_PROTOBUF_TEST_PLUGIN_PATH; #else const char* possible_paths[] = { - // When building with shared libraries, libtool hides the real executable - // in .libs and puts a fake wrapper in the current directory. - // Unfortunately, due to an apparent bug on Cygwin/MinGW, if one program - // wrapped in this way (e.g. protobuf-tests.exe) tries to execute another - // program wrapped in this way (e.g. test_plugin.exe), the latter fails - // with error code 127 and no explanation message. Presumably the problem - // is that the wrapper for protobuf-tests.exe set some environment - // variables that confuse the wrapper for test_plugin.exe. Luckily, it - // turns out that if we simply invoke the wrapped test_plugin.exe - // directly, it works -- I guess the environment variables set by the - // protobuf-tests.exe wrapper happen to be correct for it too. So we do - // that. - ".libs/test_plugin.exe", // Win32 w/autotool (Cygwin / MinGW) - "test_plugin.exe", // Other Win32 (MSVC) - "test_plugin", // Unix + // When building with shared libraries, libtool hides the real + // executable + // in .libs and puts a fake wrapper in the current directory. + // Unfortunately, due to an apparent bug on Cygwin/MinGW, if one program + // wrapped in this way (e.g. protobuf-tests.exe) tries to execute + // another + // program wrapped in this way (e.g. test_plugin.exe), the latter fails + // with error code 127 and no explanation message. Presumably the + // problem + // is that the wrapper for protobuf-tests.exe set some environment + // variables that confuse the wrapper for test_plugin.exe. Luckily, it + // turns out that if we simply invoke the wrapped test_plugin.exe + // directly, it works -- I guess the environment variables set by the + // protobuf-tests.exe wrapper happen to be correct for it too. So we do + // that. + ".libs/test_plugin.exe", // Win32 w/autotool (Cygwin / MinGW) + "test_plugin.exe", // Other Win32 (MSVC) + "test_plugin", // Unix }; for (int i = 0; i < GOOGLE_ARRAYSIZE(possible_paths); i++) { if (access(possible_paths[i], F_OK) == 0) { @@ -330,11 +348,6 @@ void CommandLineInterfaceTest::RunWithArgs(std::vector args) { #endif if (plugin_path.empty()) { -#else - string plugin_path = "third_party/protobuf/test_plugin"; - - if (access(plugin_path.c_str(), F_OK) != 0) { -#endif // GOOGLE_THIRD_PARTY_PROTOBUF GOOGLE_LOG(ERROR) << "Plugin executable not found. Plugin tests are likely to fail."; } else { @@ -342,7 +355,7 @@ void CommandLineInterfaceTest::RunWithArgs(std::vector args) { } } - google::protobuf::scoped_array argv(new const char* [args.size()]); + std::unique_ptr argv(new const char*[args.size()]); for (int i = 0; i < args.size(); i++) { args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true); @@ -367,13 +380,12 @@ void CommandLineInterfaceTest::RunWithArgs(std::vector args) { // ------------------------------------------------------------------- -void CommandLineInterfaceTest::CreateTempFile( - const string& name, - const string& contents) { +void CommandLineInterfaceTest::CreateTempFile(const std::string& name, + const std::string& contents) { // Create parent directory, if necessary. - string::size_type slash_pos = name.find_last_of('/'); - if (slash_pos != string::npos) { - string dir = name.substr(0, slash_pos); + std::string::size_type slash_pos = name.find_last_of('/'); + if (slash_pos != std::string::npos) { + std::string dir = name.substr(0, slash_pos); if (!FileExists(temp_directory_ + "/" + dir)) { GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + dir, 0777)); @@ -381,13 +393,13 @@ void CommandLineInterfaceTest::CreateTempFile( } // Write file. - string full_name = temp_directory_ + "/" + name; + std::string full_name = temp_directory_ + "/" + name; GOOGLE_CHECK_OK(File::SetContents( full_name, StringReplace(contents, "$tmpdir", temp_directory_, true), true)); } -void CommandLineInterfaceTest::CreateTempDir(const string& name) { +void CommandLineInterfaceTest::CreateTempDir(const std::string& name) { GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + name, 0777)); } @@ -399,89 +411,84 @@ void CommandLineInterfaceTest::ExpectNoErrors() { EXPECT_EQ("", error_text_); } -void CommandLineInterfaceTest::ExpectErrorText(const string& expected_text) { +void CommandLineInterfaceTest::ExpectErrorText( + const std::string& expected_text) { EXPECT_NE(0, return_code_); EXPECT_EQ(StringReplace(expected_text, "$tmpdir", temp_directory_, true), error_text_); } void CommandLineInterfaceTest::ExpectErrorSubstring( - const string& expected_substring) { + const std::string& expected_substring) { EXPECT_NE(0, return_code_); EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_); } -void CommandLineInterfaceTest::ExpectErrorSubstringWithZeroReturnCode( - const string& expected_substring) { +void CommandLineInterfaceTest::ExpectWarningSubstring( + const std::string& expected_substring) { EXPECT_EQ(0, return_code_); EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_); } +#if defined(_WIN32) && !defined(__CYGWIN__) bool CommandLineInterfaceTest::HasAlternateErrorSubstring( - const string& expected_substring) { + const std::string& expected_substring) { EXPECT_NE(0, return_code_); - return error_text_.find(expected_substring) != string::npos; + return error_text_.find(expected_substring) != std::string::npos; } +#endif // _WIN32 && !__CYGWIN__ void CommandLineInterfaceTest::ExpectGenerated( - const string& generator_name, - const string& parameter, - const string& proto_name, - const string& message_name) { - MockCodeGenerator::ExpectGenerated( - generator_name, parameter, "", proto_name, message_name, proto_name, - temp_directory_); + const std::string& generator_name, const std::string& parameter, + const std::string& proto_name, const std::string& message_name) { + MockCodeGenerator::ExpectGenerated(generator_name, parameter, "", proto_name, + message_name, proto_name, temp_directory_); } void CommandLineInterfaceTest::ExpectGenerated( - const string& generator_name, - const string& parameter, - const string& proto_name, - const string& message_name, - const string& output_directory) { - MockCodeGenerator::ExpectGenerated( - generator_name, parameter, "", proto_name, message_name, proto_name, - temp_directory_ + "/" + output_directory); + const std::string& generator_name, const std::string& parameter, + const std::string& proto_name, const std::string& message_name, + const std::string& output_directory) { + MockCodeGenerator::ExpectGenerated(generator_name, parameter, "", proto_name, + message_name, proto_name, + temp_directory_ + "/" + output_directory); } void CommandLineInterfaceTest::ExpectGeneratedWithMultipleInputs( - const string& generator_name, - const string& all_proto_names, - const string& proto_name, - const string& message_name) { - MockCodeGenerator::ExpectGenerated( - generator_name, "", "", proto_name, message_name, - all_proto_names, - temp_directory_); + const std::string& generator_name, const std::string& all_proto_names, + const std::string& proto_name, const std::string& message_name) { + MockCodeGenerator::ExpectGenerated(generator_name, "", "", proto_name, + message_name, all_proto_names, + temp_directory_); } void CommandLineInterfaceTest::ExpectGeneratedWithInsertions( - const string& generator_name, - const string& parameter, - const string& insertions, - const string& proto_name, - const string& message_name) { - MockCodeGenerator::ExpectGenerated( - generator_name, parameter, insertions, proto_name, message_name, - proto_name, temp_directory_); -} - -void CommandLineInterfaceTest::CheckGeneratedAnnotations(const string& name, - const string& file) { + const std::string& generator_name, const std::string& parameter, + const std::string& insertions, const std::string& proto_name, + const std::string& message_name) { + MockCodeGenerator::ExpectGenerated(generator_name, parameter, insertions, + proto_name, message_name, proto_name, + temp_directory_); +} + +void CommandLineInterfaceTest::CheckGeneratedAnnotations( + const std::string& name, const std::string& file) { MockCodeGenerator::CheckGeneratedAnnotations(name, file, temp_directory_); } +#if defined(_WIN32) void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled( - const string& parameter) { + const std::string& parameter) { EXPECT_TRUE(null_generator_->called_); EXPECT_EQ(parameter, null_generator_->parameter_); } +#endif // _WIN32 void CommandLineInterfaceTest::ReadDescriptorSet( - const string& filename, FileDescriptorSet* descriptor_set) { - string path = temp_directory_ + "/" + filename; - string file_contents; + const std::string& filename, FileDescriptorSet* descriptor_set) { + std::string path = temp_directory_ + "/" + filename; + std::string file_contents; GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true)); if (!descriptor_set->ParseFromString(file_contents)) { @@ -490,28 +497,28 @@ void CommandLineInterfaceTest::ReadDescriptorSet( } void CommandLineInterfaceTest::WriteDescriptorSet( - const string& filename, const FileDescriptorSet* descriptor_set) { - string binary_proto; + const std::string& filename, const FileDescriptorSet* descriptor_set) { + std::string binary_proto; GOOGLE_CHECK(descriptor_set->SerializeToString(&binary_proto)); CreateTempFile(filename, binary_proto); } void CommandLineInterfaceTest::ExpectCapturedStdout( - const string& expected_text) { + const std::string& expected_text) { EXPECT_EQ(expected_text, captured_stdout_); } void CommandLineInterfaceTest::ExpectCapturedStdoutSubstringWithZeroReturnCode( - const string& expected_substring) { + const std::string& expected_substring) { EXPECT_EQ(0, return_code_); - EXPECT_PRED_FORMAT2( - testing::IsSubstring, expected_substring, captured_stdout_); + EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, + captured_stdout_); } -void CommandLineInterfaceTest::ExpectFileContent( - const string& filename, const string& content) { - string path = temp_directory_ + "/" + filename; - string file_contents; +void CommandLineInterfaceTest::ExpectFileContent(const std::string& filename, + const std::string& content) { + std::string path = temp_directory_ + "/" + filename; + std::string file_contents; GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true)); EXPECT_EQ(StringReplace(content, "$tmpdir", temp_directory_, true), @@ -524,8 +531,8 @@ TEST_F(CommandLineInterfaceTest, BasicOutput) { // Test that the common case works. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --test_out=$tmpdir " "--proto_path=$tmpdir foo.proto"); @@ -554,8 +561,8 @@ TEST_F(CommandLineInterfaceTest, BasicPlugin) { // Test that basic plugins work. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --plug_out=$tmpdir " "--proto_path=$tmpdir foo.proto"); @@ -585,8 +592,8 @@ TEST_F(CommandLineInterfaceTest, GeneratorAndPlugin) { // Invoke a generator and a plugin at the same time. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " "--proto_path=$tmpdir foo.proto"); @@ -618,11 +625,11 @@ TEST_F(CommandLineInterfaceTest, MultipleInputs) { // Test parsing multiple input files. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); CreateTempFile("bar.proto", - "syntax = \"proto2\";\n" - "message Bar {}\n"); + "syntax = \"proto2\";\n" + "message Bar {}\n"); Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " "--proto_path=$tmpdir foo.proto bar.proto"); @@ -666,21 +673,91 @@ TEST_F(CommandLineInterfaceTest, MultipleInputs_DescriptorSetIn) { "bar.proto", "Bar"); } +TEST_F(CommandLineInterfaceTest, MultipleInputs_UnusedImport_DescriptorSetIn) { + // Test unused import warning is not raised when descriptor_set_in is called + // and custom options are in unknown field instead of uninterpreted_options. + FileDescriptorSet file_descriptor_set; + + const FileDescriptor* descriptor_file = + FileDescriptorProto::descriptor()->file(); + descriptor_file->CopyTo(file_descriptor_set.add_file()); + + FileDescriptorProto& any_proto = *file_descriptor_set.add_file(); + google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto); + + const FileDescriptor* custom_file = + protobuf_unittest::AggregateMessage::descriptor()->file(); + FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file(); + custom_file->CopyTo(file_descriptor_proto); + file_descriptor_proto->set_name("custom_options.proto"); + // Add a custom message option. + FieldDescriptorProto* extension_option = + file_descriptor_proto->add_extension(); + extension_option->set_name("unknown_option"); + extension_option->set_extendee(".google.protobuf.MessageOptions"); + extension_option->set_number(1111); + extension_option->set_label(FieldDescriptorProto::LABEL_OPTIONAL); + extension_option->set_type(FieldDescriptorProto::TYPE_INT64); + + file_descriptor_proto = file_descriptor_set.add_file(); + file_descriptor_proto->set_name("import_custom_unknown_options.proto"); + file_descriptor_proto->add_dependency("custom_options.proto"); + // Add custom message option to unknown field. This custom option is + // not known in generated pool, thus option will be in unknown fields. + file_descriptor_proto->add_message_type()->set_name("Bar"); + file_descriptor_proto->mutable_message_type(0) + ->mutable_options() + ->mutable_unknown_fields() + ->AddVarint(1111, 2222); + + WriteDescriptorSet("foo.bin", &file_descriptor_set); + + Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " + "--descriptor_set_in=$tmpdir/foo.bin " + "import_custom_unknown_options.proto"); + + // TODO(jieluo): Fix this test. This test case only happens when + // CommandLineInterface::Run() is used instead of invoke protoc combined + // with descriptor_set_in, and same custom options are defined in both + // generated pool and descriptor_set_in. There's no such uages for now but + // still need to be fixed. + /* + file_descriptor_proto = file_descriptor_set.add_file(); + file_descriptor_proto->set_name("import_custom_extension_options.proto"); + file_descriptor_proto->add_dependency("custom_options.proto"); + // Add custom message option to unknown field. This custom option is + // also defined in generated pool, thus option will be in extensions. + file_descriptor_proto->add_message_type()->set_name("Foo"); + file_descriptor_proto->mutable_message_type(0) + ->mutable_options() + ->mutable_unknown_fields() + ->AddVarint(protobuf_unittest::message_opt1.number(), 2222); + + WriteDescriptorSet("foo.bin", &file_descriptor_set); + + Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " + "--descriptor_set_in=$tmpdir/foo.bin import_custom_unknown_options.proto " + "import_custom_extension_options.proto"); + */ + + ExpectNoErrors(); +} + TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport) { // Test parsing multiple input files with an import of a separate file. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); CreateTempFile("bar.proto", - "syntax = \"proto2\";\n" - "import \"baz.proto\";\n" - "message Bar {\n" - " optional Baz a = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "import \"baz.proto\";\n" + "message Bar {\n" + " optional Baz a = 1;\n" + "}\n"); CreateTempFile("baz.proto", - "syntax = \"proto2\";\n" - "message Baz {}\n"); + "syntax = \"proto2\";\n" + "message Baz {}\n"); Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " "--proto_path=$tmpdir foo.proto bar.proto"); @@ -735,9 +812,8 @@ TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport_DescriptorSetIn) { Run(strings::Substitute( "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir " "--descriptor_set_in=$0 foo.proto bar.proto", - string("$tmpdir/foo_and_bar.bin") + - CommandLineInterface::kPathSeparator + - "$tmpdir/baz_and_bat.bin")); + std::string("$tmpdir/foo_and_bar.bin") + + CommandLineInterface::kPathSeparator + "$tmpdir/baz_and_bat.bin")); ExpectNoErrors(); ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", @@ -752,9 +828,8 @@ TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport_DescriptorSetIn) { Run(strings::Substitute( "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir " "--descriptor_set_in=$0 baz.proto bat.proto", - string("$tmpdir/foo_and_bar.bin") + - CommandLineInterface::kPathSeparator + - "$tmpdir/baz_and_bat.bin")); + std::string("$tmpdir/foo_and_bar.bin") + + CommandLineInterface::kPathSeparator + "$tmpdir/baz_and_bat.bin")); ExpectNoErrors(); ExpectGeneratedWithMultipleInputs("test_generator", "baz.proto,bat.proto", @@ -811,9 +886,8 @@ TEST_F(CommandLineInterfaceTest, Run(strings::Substitute( "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir " "--descriptor_set_in=$0 bar.proto", - string("$tmpdir/foo_and_bar.bin") + - CommandLineInterface::kPathSeparator + - "$tmpdir/foo_and_baz.bin")); + std::string("$tmpdir/foo_and_bar.bin") + + CommandLineInterface::kPathSeparator + "$tmpdir/foo_and_baz.bin")); ExpectNoErrors(); ExpectGenerated("test_generator", "", "bar.proto", "Bar"); @@ -855,12 +929,126 @@ TEST_F(CommandLineInterfaceTest, ExpectErrorSubstring("bar.proto: \"Baz\" is not defined."); } +TEST_F(CommandLineInterfaceTest, + InputsOnlyFromDescriptorSetIn_UnusedImportIsNotReported) { + FileDescriptorSet file_descriptor_set; + + FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file(); + file_descriptor_proto->set_name("unused.proto"); + file_descriptor_proto->add_message_type()->set_name("Unused"); + + file_descriptor_proto = file_descriptor_set.add_file(); + file_descriptor_proto->set_name("bar.proto"); + file_descriptor_proto->add_dependency("unused.proto"); + file_descriptor_proto->add_message_type()->set_name("Bar"); + + WriteDescriptorSet("unused_and_bar.bin", &file_descriptor_set); + + Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " + "--descriptor_set_in=$tmpdir/unused_and_bar.bin unused.proto bar.proto"); + ExpectNoErrors(); +} + +TEST_F(CommandLineInterfaceTest, + InputsFromDescriptorSetInAndFileSystem_UnusedImportIsReported) { + FileDescriptorSet file_descriptor_set; + + FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file(); + file_descriptor_proto->set_name("unused.proto"); + file_descriptor_proto->add_message_type()->set_name("Unused"); + + file_descriptor_proto = file_descriptor_set.add_file(); + file_descriptor_proto->set_name("bar.proto"); + file_descriptor_proto->add_dependency("unused.proto"); + file_descriptor_proto->add_message_type()->set_name("Bar"); + + WriteDescriptorSet("unused_and_bar.bin", &file_descriptor_set); + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n" + "message Foo {\n" + " optional Bar bar = 1;\n" + "}\n"); + + Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " + "--descriptor_set_in=$tmpdir/unused_and_bar.bin " + "--proto_path=$tmpdir unused.proto bar.proto foo.proto"); + // Reporting unused imports here is unfair, since it's unactionable. Notice + // the lack of a line number. + // TODO(b/144853061): If the file with unused import is from the descriptor + // set and not from the file system, suppress the warning. + ExpectWarningSubstring("bar.proto: warning: Import unused.proto is unused."); +} + +TEST_F(CommandLineInterfaceTest, + OnlyReportsUnusedImportsForFilesBeingGenerated) { + CreateTempFile("unused.proto", + "syntax = \"proto2\";\n" + "message Unused {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"unused.proto\";\n" + "message Bar {}\n"); + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n" + "message Foo {\n" + " optional Bar bar = 1;\n" + "}\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + ExpectNoErrors(); +} + +TEST_F(CommandLineInterfaceTest, ReportsTransitiveMisingImports_LeafFirst) { + CreateTempFile("unused.proto", + "syntax = \"proto2\";\n" + "message Unused {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"unused.proto\";\n" + "message Bar {}\n"); + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n" + "message Foo {\n" + " optional Bar bar = 1;\n" + "}\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir bar.proto foo.proto"); + ExpectWarningSubstring( + "bar.proto:2:1: warning: Import unused.proto is unused."); +} + +TEST_F(CommandLineInterfaceTest, ReportsTransitiveMisingImports_LeafLast) { + CreateTempFile("unused.proto", + "syntax = \"proto2\";\n" + "message Unused {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"unused.proto\";\n" + "message Bar {}\n"); + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n" + "message Foo {\n" + " optional Bar bar = 1;\n" + "}\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir foo.proto bar.proto"); + ExpectWarningSubstring( + "bar.proto:2:1: warning: Import unused.proto is unused."); +} TEST_F(CommandLineInterfaceTest, CreateDirectory) { // Test that when we output to a sub-directory, it is created. CreateTempFile("bar/baz/foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); CreateTempDir("out"); CreateTempDir("plugout"); @@ -876,8 +1064,8 @@ TEST_F(CommandLineInterfaceTest, GeneratorParameters) { // Test that generator parameters are correctly parsed from the command line. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --test_out=TestParameter:$tmpdir " "--plug_out=TestPluginParameter:$tmpdir " @@ -893,8 +1081,8 @@ TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) { // correctly passed to the code generator. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); // Create the "a" and "b" sub-directories. CreateTempDir("a"); CreateTempDir("b"); @@ -908,10 +1096,10 @@ TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) { "--proto_path=$tmpdir foo.proto"); ExpectNoErrors(); - ExpectGenerated( - "test_generator", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a"); - ExpectGenerated( - "test_generator", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b"); + ExpectGenerated("test_generator", "bar,foo1,foo2,foo3", "foo.proto", "Foo", + "a"); + ExpectGenerated("test_generator", "baz,foo1,foo2,foo3", "foo.proto", "Foo", + "b"); } TEST_F(CommandLineInterfaceTest, ExtraPluginParameters) { @@ -919,8 +1107,8 @@ TEST_F(CommandLineInterfaceTest, ExtraPluginParameters) { // correctly passed to the code generator. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); // Create the "a" and "b" sub-directories. CreateTempDir("a"); CreateTempDir("b"); @@ -934,16 +1122,14 @@ TEST_F(CommandLineInterfaceTest, ExtraPluginParameters) { "--proto_path=$tmpdir foo.proto"); ExpectNoErrors(); - ExpectGenerated( - "test_plugin", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a"); - ExpectGenerated( - "test_plugin", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b"); + ExpectGenerated("test_plugin", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a"); + ExpectGenerated("test_plugin", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b"); } TEST_F(CommandLineInterfaceTest, UnrecognizedExtraParameters) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --plug_out=TestParameter:$tmpdir " "--unknown_plug_a_opt=Foo " @@ -955,7 +1141,7 @@ TEST_F(CommandLineInterfaceTest, UnrecognizedExtraParameters) { } TEST_F(CommandLineInterfaceTest, ExtraPluginParametersForOutParameters) { - // This doesn't rely on the plugin having been registred and instead that + // This doesn't rely on the plugin having been registered and instead that // the existence of --[name]_out is enough to make the --[name]_opt valid. // However, running out of process plugins found via the search path (i.e. - // not pre registered with --plugin) isn't support in this test suite, so we @@ -966,8 +1152,8 @@ TEST_F(CommandLineInterfaceTest, ExtraPluginParametersForOutParameters) { // directives appear, they both are reported. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --plug_out=TestParameter:$tmpdir " "--xyz_opt=foo=bar --xyz_out=$tmpdir " @@ -982,8 +1168,8 @@ TEST_F(CommandLineInterfaceTest, Insert) { // Test running a generator that inserts code into another's output. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler " "--test_out=TestParameter:$tmpdir " @@ -993,12 +1179,12 @@ TEST_F(CommandLineInterfaceTest, Insert) { "--proto_path=$tmpdir foo.proto"); ExpectNoErrors(); - ExpectGeneratedWithInsertions( - "test_generator", "TestParameter", "test_generator,test_plugin", - "foo.proto", "Foo"); - ExpectGeneratedWithInsertions( - "test_plugin", "TestPluginParameter", "test_generator,test_plugin", - "foo.proto", "Foo"); + ExpectGeneratedWithInsertions("test_generator", "TestParameter", + "test_generator,test_plugin", "foo.proto", + "Foo"); + ExpectGeneratedWithInsertions("test_plugin", "TestPluginParameter", + "test_generator,test_plugin", "foo.proto", + "Foo"); } TEST_F(CommandLineInterfaceTest, InsertWithAnnotationFixup) { @@ -1011,8 +1197,8 @@ TEST_F(CommandLineInterfaceTest, InsertWithAnnotationFixup) { Run("protocol_compiler " "--test_out=TestParameter:$tmpdir " "--plug_out=TestPluginParameter:$tmpdir " - "--test_out=insert=test_generator,test_plugin:$tmpdir " - "--plug_out=insert=test_generator,test_plugin:$tmpdir " + "--test_out=insert_endlines=test_generator,test_plugin:$tmpdir " + "--plug_out=insert_endlines=test_generator,test_plugin:$tmpdir " "--proto_path=$tmpdir foo.proto"); ExpectNoErrors(); @@ -1025,8 +1211,7 @@ TEST_F(CommandLineInterfaceTest, InsertWithAnnotationFixup) { TEST_F(CommandLineInterfaceTest, WindowsOutputPath) { // Test that the output path can be a Windows-style path. - CreateTempFile("foo.proto", - "syntax = \"proto2\";\n"); + CreateTempFile("foo.proto", "syntax = \"proto2\";\n"); Run("protocol_compiler --null_out=C:\\ " "--proto_path=$tmpdir foo.proto"); @@ -1038,8 +1223,7 @@ TEST_F(CommandLineInterfaceTest, WindowsOutputPath) { TEST_F(CommandLineInterfaceTest, WindowsOutputPathAndParameter) { // Test that we can have a windows-style output path and a parameter. - CreateTempFile("foo.proto", - "syntax = \"proto2\";\n"); + CreateTempFile("foo.proto", "syntax = \"proto2\";\n"); Run("protocol_compiler --null_out=bar:C:\\ " "--proto_path=$tmpdir foo.proto"); @@ -1053,8 +1237,8 @@ TEST_F(CommandLineInterfaceTest, TrailingBackslash) { // doesn't work on their system. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --test_out=$tmpdir\\ " "--proto_path=$tmpdir\\ foo.proto"); @@ -1074,14 +1258,14 @@ TEST_F(CommandLineInterfaceTest, PathLookup) { // Test that specifying multiple directories in the proto search path works. CreateTempFile("b/bar.proto", - "syntax = \"proto2\";\n" - "message Bar {}\n"); + "syntax = \"proto2\";\n" + "message Bar {}\n"); CreateTempFile("a/foo.proto", - "syntax = \"proto2\";\n" - "import \"bar.proto\";\n" - "message Foo {\n" - " optional Bar a = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n" + "message Foo {\n" + " optional Bar a = 1;\n" + "}\n"); CreateTempFile("b/foo.proto", "this should not be parsed\n"); Run("protocol_compiler --test_out=$tmpdir " @@ -1095,21 +1279,20 @@ TEST_F(CommandLineInterfaceTest, ColonDelimitedPath) { // Same as PathLookup, but we provide the proto_path in a single flag. CreateTempFile("b/bar.proto", - "syntax = \"proto2\";\n" - "message Bar {}\n"); + "syntax = \"proto2\";\n" + "message Bar {}\n"); CreateTempFile("a/foo.proto", - "syntax = \"proto2\";\n" - "import \"bar.proto\";\n" - "message Foo {\n" - " optional Bar a = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n" + "message Foo {\n" + " optional Bar a = 1;\n" + "}\n"); CreateTempFile("b/foo.proto", "this should not be parsed\n"); Run(strings::Substitute( "protocol_compiler --test_out=$$tmpdir --proto_path=$0 foo.proto", - string("$tmpdir/a") + - CommandLineInterface::kPathSeparator + - "$tmpdir/b")); + std::string("$tmpdir/a") + CommandLineInterface::kPathSeparator + + "$tmpdir/b")); ExpectNoErrors(); ExpectGenerated("test_generator", "", "foo.proto", "Foo"); @@ -1119,8 +1302,8 @@ TEST_F(CommandLineInterfaceTest, NonRootMapping) { // Test setting up a search path mapping a directory to a non-root location. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --test_out=$tmpdir " "--proto_path=bar=$tmpdir bar/foo.proto"); @@ -1134,8 +1317,8 @@ TEST_F(CommandLineInterfaceTest, PathWithEqualsSign) { CreateTempDir("with=sign"); CreateTempFile("with=sign/foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --test_out=$tmpdir " "--proto_path=$tmpdir/with=sign foo.proto"); @@ -1149,8 +1332,8 @@ TEST_F(CommandLineInterfaceTest, MultipleGenerators) { // each with a different output directory. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); // Create the "a" and "b" sub-directories. CreateTempDir("a"); CreateTempDir("b"); @@ -1170,8 +1353,8 @@ TEST_F(CommandLineInterfaceTest, DisallowServicesNoServices) { // services. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --disallow_services --test_out=$tmpdir " "--proto_path=$tmpdir foo.proto"); @@ -1184,9 +1367,9 @@ TEST_F(CommandLineInterfaceTest, DisallowServicesHasService) { // Test that --disallow_services produces an error when there are services. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n" - "service Bar {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n" + "service Bar {}\n"); Run("protocol_compiler --disallow_services --test_out=$tmpdir " "--proto_path=$tmpdir foo.proto"); @@ -1198,9 +1381,9 @@ TEST_F(CommandLineInterfaceTest, AllowServicesHasService) { // Test that services work fine as long as --disallow_services is not used. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n" - "service Bar {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n" + "service Bar {}\n"); Run("protocol_compiler --test_out=$tmpdir " "--proto_path=$tmpdir foo.proto"); @@ -1209,6 +1392,7 @@ TEST_F(CommandLineInterfaceTest, AllowServicesHasService) { ExpectGenerated("test_generator", "", "foo.proto", "Foo"); } + TEST_F(CommandLineInterfaceTest, DirectDependencies_Missing_EmptyList) { CreateTempFile("foo.proto", "syntax = \"proto2\";\n" @@ -1282,8 +1466,7 @@ TEST_F(CommandLineInterfaceTest, DirectDependencies_NoViolation_MultiImports) { } TEST_F(CommandLineInterfaceTest, DirectDependencies_ProvidedMultipleTimes) { - CreateTempFile("foo.proto", - "syntax = \"proto2\";\n"); + CreateTempFile("foo.proto", "syntax = \"proto2\";\n"); Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir " "--direct_dependencies=bar.proto --direct_dependencies=bla.proto " @@ -1304,7 +1487,7 @@ TEST_F(CommandLineInterfaceTest, DirectDependencies_CustomErrorMessage) { "syntax = \"proto2\";\n" "message Bar { optional string text = 1; }"); - std::vector commands; + std::vector commands; commands.push_back("protocol_compiler"); commands.push_back("--test_out=$tmpdir"); commands.push_back("--proto_path=$tmpdir"); @@ -1320,8 +1503,8 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) { // Test that we can accept working-directory-relative input files. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --test_out=$tmpdir " "--proto_path=$tmpdir $tmpdir/foo.proto"); @@ -1332,14 +1515,14 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) { TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); CreateTempFile("bar.proto", - "syntax = \"proto2\";\n" - "import \"foo.proto\";\n" - "message Bar {\n" - " optional Foo foo = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " "--proto_path=$tmpdir bar.proto"); @@ -1361,20 +1544,20 @@ TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) { TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithDuplicates) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); CreateTempFile("bar.proto", - "syntax = \"proto2\";\n" - "import \"foo.proto\";\n" - "message Bar {\n" - " optional Foo foo = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); CreateTempFile("baz.proto", - "syntax = \"proto2\";\n" - "import \"foo.proto\";\n" - "message Baz {\n" - " optional Foo foo = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Baz {\n" + " optional Foo foo = 1;\n" + "}\n"); Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " "--proto_path=$tmpdir bar.proto foo.proto bar.proto baz.proto"); @@ -1400,14 +1583,14 @@ TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithDuplicates) { TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); CreateTempFile("bar.proto", - "syntax = \"proto2\";\n" - "import \"foo.proto\";\n" - "message Bar {\n" - " optional Foo foo = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " "--include_source_info --proto_path=$tmpdir bar.proto"); @@ -1425,14 +1608,14 @@ TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) { TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); CreateTempFile("bar.proto", - "syntax = \"proto2\";\n" - "import \"foo.proto\";\n" - "message Bar {\n" - " optional Foo foo = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " "--include_imports --proto_path=$tmpdir bar.proto"); @@ -1456,14 +1639,14 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) { TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); CreateTempFile("bar.proto", - "syntax = \"proto2\";\n" - "import \"foo.proto\";\n" - "message Bar {\n" - " optional Foo foo = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " "--include_imports --include_source_info --proto_path=$tmpdir bar.proto"); @@ -1490,14 +1673,14 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) { #else TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileGivenTwoInputs) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); CreateTempFile("bar.proto", - "syntax = \"proto2\";\n" - "import \"foo.proto\";\n" - "message Bar {\n" - " optional Foo foo = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); Run("protocol_compiler --dependency_out=$tmpdir/manifest " "--test_out=$tmpdir --proto_path=$tmpdir bar.proto foo.proto"); @@ -1509,16 +1692,16 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileGivenTwoInputs) { #ifdef PROTOBUF_OPENSOURCE TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); CreateTempFile("bar.proto", - "syntax = \"proto2\";\n" - "import \"foo.proto\";\n" - "message Bar {\n" - " optional Foo foo = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); - string current_working_directory = getcwd(NULL, 0); + std::string current_working_directory = getcwd(NULL, 0); SwitchToTempDirectory(); Run("protocol_compiler --dependency_out=manifest --test_out=. " @@ -1539,14 +1722,14 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); CreateTempFile("bar.proto", - "syntax = \"proto2\";\n" - "import \"foo.proto\";\n" - "message Bar {\n" - " optional Foo foo = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); Run("protocol_compiler --dependency_out=$tmpdir/manifest " "--test_out=$tmpdir --proto_path=$tmpdir bar.proto"); @@ -1559,6 +1742,36 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) { } #endif // !_WIN32 +TEST_F(CommandLineInterfaceTest, TestArgumentFile) { + // Test parsing multiple input files using an argument file. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "message Bar {}\n"); + CreateTempFile("arguments.txt", + "--test_out=$tmpdir\n" + "--plug_out=$tmpdir\n" + "--proto_path=$tmpdir\n" + "--direct_dependencies_violation_msg=%s is not imported\n" + "foo.proto\n" + "bar.proto"); + + Run("protocol_compiler @$tmpdir/arguments.txt"); + + ExpectNoErrors(); + ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", + "foo.proto", "Foo"); + ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", + "bar.proto", "Bar"); + ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", + "foo.proto", "Foo"); + ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", + "bar.proto", "Bar"); +} + // ------------------------------------------------------------------- @@ -1566,14 +1779,14 @@ TEST_F(CommandLineInterfaceTest, ParseErrors) { // Test that parse errors are reported. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "badsyntax\n"); + "syntax = \"proto2\";\n" + "badsyntax\n"); Run("protocol_compiler --test_out=$tmpdir " "--proto_path=$tmpdir foo.proto"); ExpectErrorText( - "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n"); + "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n"); } TEST_F(CommandLineInterfaceTest, ParseErrors_DescriptorSetIn) { @@ -1583,8 +1796,7 @@ TEST_F(CommandLineInterfaceTest, ParseErrors_DescriptorSetIn) { Run("protocol_compiler --test_out=$tmpdir " "--descriptor_set_in=$tmpdir/foo.bin foo.proto"); - ExpectErrorText( - "$tmpdir/foo.bin: Unable to parse.\n"); + ExpectErrorText("$tmpdir/foo.bin: Unable to parse.\n"); } TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) { @@ -1594,37 +1806,38 @@ TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) { // two ways: Directly and through baz.proto. bar.proto's errors should // only be reported once. CreateTempFile("bar.proto", - "syntax = \"proto2\";\n" - "badsyntax\n"); + "syntax = \"proto2\";\n" + "badsyntax\n"); CreateTempFile("baz.proto", - "syntax = \"proto2\";\n" - "import \"bar.proto\";\n"); + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n"); CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "import \"bar.proto\";\n" - "import \"baz.proto\";\n"); + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n" + "import \"baz.proto\";\n"); Run("protocol_compiler --test_out=$tmpdir " "--proto_path=$tmpdir foo.proto"); ExpectErrorText( - "bar.proto:2:1: Expected top-level statement (e.g. \"message\").\n" - "baz.proto: Import \"bar.proto\" was not found or had errors.\n" - "foo.proto: Import \"bar.proto\" was not found or had errors.\n" - "foo.proto: Import \"baz.proto\" was not found or had errors.\n"); + "bar.proto:2:1: Expected top-level statement (e.g. \"message\").\n" + "baz.proto:2:1: Import \"bar.proto\" was not found or had errors.\n" + "foo.proto:2:1: Import \"bar.proto\" was not found or had errors.\n" + "foo.proto:3:1: Import \"baz.proto\" was not found or had errors.\n"); } TEST_F(CommandLineInterfaceTest, RecursiveImportFails) { // Create a proto file that imports itself. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "import \"foo.proto\";\n"); + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n"); Run("protocol_compiler --test_out=$tmpdir " "--proto_path=$tmpdir foo.proto"); ExpectErrorSubstring( - "foo.proto: File recursively imports itself: foo.proto -> foo.proto\n"); + "foo.proto:2:1: File recursively imports itself: " + "foo.proto -> foo.proto\n"); } TEST_F(CommandLineInterfaceTest, InputNotFoundError) { @@ -1633,7 +1846,9 @@ TEST_F(CommandLineInterfaceTest, InputNotFoundError) { Run("protocol_compiler --test_out=$tmpdir " "--proto_path=$tmpdir foo.proto"); - ExpectErrorText("foo.proto: No such file or directory\n"); + ExpectErrorText( + "Could not make proto path relative: foo.proto: No such file or " + "directory\n"); } TEST_F(CommandLineInterfaceTest, InputNotFoundError_DescriptorSetIn) { @@ -1642,8 +1857,7 @@ TEST_F(CommandLineInterfaceTest, InputNotFoundError_DescriptorSetIn) { Run("protocol_compiler --test_out=$tmpdir " "--descriptor_set_in=$tmpdir/foo.bin foo.proto"); - ExpectErrorText( - "$tmpdir/foo.bin: No such file or directory\n"); + ExpectErrorText("$tmpdir/foo.bin: No such file or directory\n"); } TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundError) { @@ -1654,7 +1868,8 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundError) { "--proto_path=$tmpdir $tmpdir/foo.proto"); ExpectErrorText( - "$tmpdir/foo.proto: No such file or directory\n"); + "Could not make proto path relative: $tmpdir/foo.proto: No such file or " + "directory\n"); } TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotMappedError) { @@ -1662,8 +1877,8 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotMappedError) { // mapped to a virtual path. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); // Create a directory called "bar" so that we can point --proto_path at it. CreateTempFile("bar/dummy", ""); @@ -1672,7 +1887,7 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotMappedError) { "--proto_path=$tmpdir/bar $tmpdir/foo.proto"); ExpectErrorText( - "$tmpdir/foo.proto: File does not reside within any path " + "$tmpdir/foo.proto: File does not reside within any path " "specified using --proto_path (or -I). You must specify a " "--proto_path which encompasses this file. Note that the " "proto_path must be an exact prefix of the .proto file " @@ -1692,7 +1907,8 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundAndNotMappedError) { "--proto_path=$tmpdir/bar $tmpdir/foo.proto"); ExpectErrorText( - "$tmpdir/foo.proto: No such file or directory\n"); + "Could not make proto path relative: $tmpdir/foo.proto: No such file or " + "directory\n"); } TEST_F(CommandLineInterfaceTest, CwdRelativeInputShadowedError) { @@ -1700,21 +1916,21 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputShadowedError) { // by another file in the virtual path. CreateTempFile("foo/foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); CreateTempFile("bar/foo.proto", - "syntax = \"proto2\";\n" - "message Bar {}\n"); + "syntax = \"proto2\";\n" + "message Bar {}\n"); Run("protocol_compiler --test_out=$tmpdir " "--proto_path=$tmpdir/foo --proto_path=$tmpdir/bar " "$tmpdir/bar/foo.proto"); ExpectErrorText( - "$tmpdir/bar/foo.proto: Input is shadowed in the --proto_path " - "by \"$tmpdir/foo/foo.proto\". Either use the latter " - "file as your input or reorder the --proto_path so that the " - "former file's location comes first.\n"); + "$tmpdir/bar/foo.proto: Input is shadowed in the --proto_path " + "by \"$tmpdir/foo/foo.proto\". Either use the latter " + "file as your input or reorder the --proto_path so that the " + "former file's location comes first.\n"); } TEST_F(CommandLineInterfaceTest, ProtoPathNotFoundError) { @@ -1725,19 +1941,56 @@ TEST_F(CommandLineInterfaceTest, ProtoPathNotFoundError) { ExpectErrorText( "$tmpdir/foo: warning: directory does not exist.\n" - "foo.proto: No such file or directory\n"); + "Could not make proto path relative: foo.proto: No such file or " + "directory\n"); } TEST_F(CommandLineInterfaceTest, ProtoPathAndDescriptorSetIn) { Run("protocol_compiler --test_out=$tmpdir " "--proto_path=$tmpdir --descriptor_set_in=$tmpdir/foo.bin foo.proto"); - ExpectErrorText( - "Only one of --descriptor_set_in and --proto_path can be specified.\n"); + ExpectErrorText("$tmpdir/foo.bin: No such file or directory\n"); Run("protocol_compiler --test_out=$tmpdir " "--descriptor_set_in=$tmpdir/foo.bin --proto_path=$tmpdir foo.proto"); - ExpectErrorText( - "Only one of --proto_path and --descriptor_set_in can be specified.\n"); + ExpectErrorText("$tmpdir/foo.bin: No such file or directory\n"); +} + +TEST_F(CommandLineInterfaceTest, ProtoPathAndDescriptorSetIn_CompileFiles) { + // Test what happens if a proto is in a --descriptor_set_in and also exists + // on disk. + FileDescriptorSet file_descriptor_set; + + // NOTE: This file desc SHOULD be different from the one created as a temp + // to make it easier to test that the file was output instead of the + // contents of the --descriptor_set_in file. + FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file(); + file_descriptor_proto->set_name("foo.proto"); + file_descriptor_proto->add_message_type()->set_name("Foo"); + + WriteDescriptorSet("foo.bin", &file_descriptor_set); + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message FooBar { required string foo_message = 1; }\n"); + + Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " + "--descriptor_set_in=$tmpdir/foo.bin " + "--include_source_info " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + + FileDescriptorSet descriptor_set; + ReadDescriptorSet("descriptor_set", &descriptor_set); + + EXPECT_EQ(1, descriptor_set.file_size()); + EXPECT_EQ("foo.proto", descriptor_set.file(0).name()); + // Descriptor set SHOULD have source code info. + EXPECT_TRUE(descriptor_set.file(0).has_source_code_info()); + + EXPECT_EQ("FooBar", descriptor_set.file(0).message_type(0).name()); + EXPECT_EQ("foo_message", + descriptor_set.file(0).message_type(0).field(0).name()); } TEST_F(CommandLineInterfaceTest, ProtoPathAndDependencyOut) { @@ -1765,8 +2018,8 @@ TEST_F(CommandLineInterfaceTest, MissingInputError) { TEST_F(CommandLineInterfaceTest, MissingOutputError) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --proto_path=$tmpdir foo.proto"); @@ -1775,10 +2028,10 @@ TEST_F(CommandLineInterfaceTest, MissingOutputError) { TEST_F(CommandLineInterfaceTest, OutputWriteError) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); - string output_file = + std::string output_file = MockCodeGenerator::GetOutputFileName("test_generator", "foo.proto"); // Create a directory blocking our output location. @@ -1804,10 +2057,10 @@ TEST_F(CommandLineInterfaceTest, OutputWriteError) { TEST_F(CommandLineInterfaceTest, PluginOutputWriteError) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); - string output_file = + std::string output_file = MockCodeGenerator::GetOutputFileName("test_plugin", "foo.proto"); // Create a directory blocking our output location. @@ -1828,8 +2081,8 @@ TEST_F(CommandLineInterfaceTest, PluginOutputWriteError) { TEST_F(CommandLineInterfaceTest, OutputDirectoryNotFoundError) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --test_out=$tmpdir/nosuchdir " "--proto_path=$tmpdir foo.proto"); @@ -1839,8 +2092,8 @@ TEST_F(CommandLineInterfaceTest, OutputDirectoryNotFoundError) { TEST_F(CommandLineInterfaceTest, PluginOutputDirectoryNotFoundError) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --plug_out=$tmpdir/nosuchdir " "--proto_path=$tmpdir foo.proto"); @@ -1850,8 +2103,8 @@ TEST_F(CommandLineInterfaceTest, PluginOutputDirectoryNotFoundError) { TEST_F(CommandLineInterfaceTest, OutputDirectoryIsFileError) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --test_out=$tmpdir/foo.proto " "--proto_path=$tmpdir foo.proto"); @@ -1868,8 +2121,8 @@ TEST_F(CommandLineInterfaceTest, OutputDirectoryIsFileError) { TEST_F(CommandLineInterfaceTest, GeneratorError) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message MockCodeGenerator_Error {}\n"); + "syntax = \"proto2\";\n" + "message MockCodeGenerator_Error {}\n"); Run("protocol_compiler --test_out=$tmpdir " "--proto_path=$tmpdir foo.proto"); @@ -1882,8 +2135,8 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginError) { // Test a generator plugin that returns an error. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message MockCodeGenerator_Error {}\n"); + "syntax = \"proto2\";\n" + "message MockCodeGenerator_Error {}\n"); Run("protocol_compiler --plug_out=TestParameter:$tmpdir " "--proto_path=$tmpdir foo.proto"); @@ -1896,8 +2149,8 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginFail) { // Test a generator plugin that exits with an error code. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message MockCodeGenerator_Exit {}\n"); + "syntax = \"proto2\";\n" + "message MockCodeGenerator_Exit {}\n"); Run("protocol_compiler --plug_out=TestParameter:$tmpdir " "--proto_path=$tmpdir foo.proto"); @@ -1911,8 +2164,8 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginCrash) { // Test a generator plugin that crashes. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message MockCodeGenerator_Abort {}\n"); + "syntax = \"proto2\";\n" + "message MockCodeGenerator_Abort {}\n"); Run("protocol_compiler --plug_out=TestParameter:$tmpdir " "--proto_path=$tmpdir foo.proto"); @@ -1926,15 +2179,14 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginCrash) { "--plug_out: prefix-gen-plug: Plugin failed with status code"); #else // Don't depend on the exact signal number. - ExpectErrorSubstring( - "--plug_out: prefix-gen-plug: Plugin killed by signal"); + ExpectErrorSubstring("--plug_out: prefix-gen-plug: Plugin killed by signal"); #endif } TEST_F(CommandLineInterfaceTest, PluginReceivesSourceCodeInfo) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message MockCodeGenerator_HasSourceCodeInfo {}\n"); + "syntax = \"proto2\";\n" + "message MockCodeGenerator_HasSourceCodeInfo {}\n"); Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto"); @@ -1944,10 +2196,10 @@ TEST_F(CommandLineInterfaceTest, PluginReceivesSourceCodeInfo) { TEST_F(CommandLineInterfaceTest, PluginReceivesJsonName) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message MockCodeGenerator_HasJsonName {\n" - " optional int32 value = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "message MockCodeGenerator_HasJsonName {\n" + " optional int32 value = 1;\n" + "}\n"); Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto"); @@ -1956,25 +2208,24 @@ TEST_F(CommandLineInterfaceTest, PluginReceivesJsonName) { TEST_F(CommandLineInterfaceTest, PluginReceivesCompilerVersion) { CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message MockCodeGenerator_ShowVersionNumber {\n" - " optional int32 value = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "message MockCodeGenerator_ShowVersionNumber {\n" + " optional int32 value = 1;\n" + "}\n"); Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto"); - ExpectErrorSubstring( - StringPrintf("Saw compiler_version: %d %s", - GOOGLE_PROTOBUF_VERSION, - GOOGLE_PROTOBUF_VERSION_SUFFIX)); + ExpectErrorSubstring(StringPrintf("Saw compiler_version: %d %s", + GOOGLE_PROTOBUF_VERSION, + GOOGLE_PROTOBUF_VERSION_SUFFIX)); } TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) { // Test what happens if the plugin isn't found. CreateTempFile("error.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --badplug_out=TestParameter:$tmpdir " "--plugin=prefix-gen-badplug=no_such_file " @@ -1982,11 +2233,14 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) { #ifdef _WIN32 ExpectErrorSubstring("--badplug_out: prefix-gen-badplug: " + - Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND)); + Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND)); #else // Error written to stdout by child process after exec() fails. + ExpectErrorSubstring("no_such_file: program not found or is not executable"); + ExpectErrorSubstring( - "no_such_file: program not found or is not executable"); + "Please specify a program using absolute path or make sure " + "the program is available in your PATH system variable"); // Error written by parent process when child fails. ExpectErrorSubstring( @@ -1998,8 +2252,8 @@ TEST_F(CommandLineInterfaceTest, GeneratorPluginNotAllowed) { // Test what happens if plugins aren't allowed. CreateTempFile("error.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); DisallowPlugins(); Run("protocol_compiler --plug_out=TestParameter:$tmpdir " @@ -2023,28 +2277,28 @@ TEST_F(CommandLineInterfaceTest, GccFormatErrors) { // that it can be set explicitly). CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "badsyntax\n"); + "syntax = \"proto2\";\n" + "badsyntax\n"); Run("protocol_compiler --test_out=$tmpdir " "--proto_path=$tmpdir --error_format=gcc foo.proto"); ExpectErrorText( - "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n"); + "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n"); } TEST_F(CommandLineInterfaceTest, MsvsFormatErrors) { // Test --error_format=msvs CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "badsyntax\n"); + "syntax = \"proto2\";\n" + "badsyntax\n"); Run("protocol_compiler --test_out=$tmpdir " "--proto_path=$tmpdir --error_format=msvs foo.proto"); ExpectErrorText( - "$tmpdir/foo.proto(2) : error in column=1: Expected top-level statement " + "$tmpdir/foo.proto(2) : error in column=1: Expected top-level statement " "(e.g. \"message\").\n"); } @@ -2052,14 +2306,13 @@ TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) { // Test --error_format=msvs CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "badsyntax\n"); + "syntax = \"proto2\";\n" + "badsyntax\n"); Run("protocol_compiler --test_out=$tmpdir " "--proto_path=$tmpdir --error_format=invalid foo.proto"); - ExpectErrorText( - "Unknown error format: invalid\n"); + ExpectErrorText("Unknown error format: invalid\n"); } // ------------------------------------------------------------------- @@ -2069,8 +2322,8 @@ TEST_F(CommandLineInterfaceTest, ParseSingleCharacterFlag) { // Test that a single-character flag works. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler -t$tmpdir " "--proto_path=$tmpdir foo.proto"); @@ -2083,8 +2336,8 @@ TEST_F(CommandLineInterfaceTest, ParseSpaceDelimitedValue) { // Test that separating the flag value with a space works. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler --test_out $tmpdir " "--proto_path=$tmpdir foo.proto"); @@ -2098,8 +2351,8 @@ TEST_F(CommandLineInterfaceTest, ParseSingleCharacterSpaceDelimitedValue) { // single-character flags. CreateTempFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); Run("protocol_compiler -t $tmpdir " "--proto_path=$tmpdir foo.proto"); @@ -2125,39 +2378,68 @@ TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) { ExpectErrorText("Missing value for flag: --test_out\n"); } + +TEST_F(CommandLineInterfaceTest, Proto3OptionalDisallowedNoCodegenSupport) { + CreateTempFile("google/foo.proto", + "syntax = \"proto3\";\n" + "message Foo {\n" + " optional int32 i = 1;\n" + "}\n"); + + CreateGeneratorWithMissingFeatures("--no_proto3_optional_out", + "Doesn't support proto3 optional", + CodeGenerator::FEATURE_PROTO3_OPTIONAL); + + Run("protocol_compiler --experimental_allow_proto3_optional " + "--proto_path=$tmpdir google/foo.proto --no_proto3_optional_out=$tmpdir"); + + ExpectErrorSubstring( + "code generator --no_proto3_optional_out hasn't been updated to support " + "optional fields in proto3"); +} + +TEST_F(CommandLineInterfaceTest, Proto3OptionalAllowWithFlag) { + CreateTempFile("google/foo.proto", + "syntax = \"proto3\";\n" + "message Foo {\n" + " optional int32 i = 1;\n" + "}\n"); + + Run("protocol_compiler --experimental_allow_proto3_optional " + "--proto_path=$tmpdir google/foo.proto --test_out=$tmpdir"); + ExpectNoErrors(); +} + TEST_F(CommandLineInterfaceTest, PrintFreeFieldNumbers) { - CreateTempFile( - "foo.proto", - "syntax = \"proto2\";\n" - "package foo;\n" - "message Foo {\n" - " optional int32 a = 2;\n" - " optional string b = 4;\n" - " optional string c = 5;\n" - " optional int64 d = 8;\n" - " optional double e = 10;\n" - "}\n"); - CreateTempFile( - "bar.proto", - "syntax = \"proto2\";\n" - "message Bar {\n" - " optional int32 a = 2;\n" - " extensions 4 to 5;\n" - " optional int64 d = 8;\n" - " extensions 10;\n" - "}\n"); - CreateTempFile( - "baz.proto", - "syntax = \"proto2\";\n" - "message Baz {\n" - " optional int32 a = 2;\n" - " optional int64 d = 8;\n" - " extensions 15 to max;\n" // unordered. - " extensions 13;\n" - " extensions 10 to 12;\n" - " extensions 5;\n" - " extensions 4;\n" - "}\n"); + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "package foo;\n" + "message Foo {\n" + " optional int32 a = 2;\n" + " optional string b = 4;\n" + " optional string c = 5;\n" + " optional int64 d = 8;\n" + " optional double e = 10;\n" + "}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "message Bar {\n" + " optional int32 a = 2;\n" + " extensions 4 to 5;\n" + " optional int64 d = 8;\n" + " extensions 10;\n" + "}\n"); + CreateTempFile("baz.proto", + "syntax = \"proto2\";\n" + "message Baz {\n" + " optional int32 a = 2;\n" + " optional int64 d = 8;\n" + " extensions 15 to max;\n" // unordered. + " extensions 13;\n" + " extensions 10 to 12;\n" + " extensions 5;\n" + " extensions 4;\n" + "}\n"); CreateTempFile( "quz.proto", "syntax = \"proto2\";\n" @@ -2202,10 +2484,7 @@ TEST_F(CommandLineInterfaceTest, PrintFreeFieldNumbers) { // platforms that don't have a Bourne-compatible shell available (especially // Windows/MSVC). -enum EncodeDecodeTestMode { - PROTO_PATH, - DESCRIPTOR_SET_IN -}; +enum EncodeDecodeTestMode { PROTO_PATH, DESCRIPTOR_SET_IN }; class EncodeDecodeTest : public testing::TestWithParam { protected: @@ -2219,13 +2498,13 @@ class EncodeDecodeTest : public testing::TestWithParam { close(duped_stdin_); } - void RedirectStdinFromText(const string& input) { - string filename = TestTempDir() + "/test_stdin"; + void RedirectStdinFromText(const std::string& input) { + std::string filename = TestTempDir() + "/test_stdin"; GOOGLE_CHECK_OK(File::SetContents(filename, input, true)); GOOGLE_CHECK(RedirectStdinFromFile(filename)); } - bool RedirectStdinFromFile(const string& filename) { + bool RedirectStdinFromFile(const std::string& filename) { int fd = open(filename.c_str(), O_RDONLY); if (fd < 0) return false; dup2(fd, STDIN_FILENO); @@ -2234,8 +2513,8 @@ class EncodeDecodeTest : public testing::TestWithParam { } // Remove '\r' characters from text. - string StripCR(const string& text) { - string result; + std::string StripCR(const std::string& text) { + std::string result; for (int i = 0; i < text.size(); i++) { if (text[i] != '\r') { @@ -2249,24 +2528,28 @@ class EncodeDecodeTest : public testing::TestWithParam { enum Type { TEXT, BINARY }; enum ReturnCode { SUCCESS, ERROR }; - bool Run(const string& command) { - std::vector args; + bool Run(const std::string& command, bool specify_proto_files = true) { + std::vector args; args.push_back("protoc"); - SplitStringUsing(command, " ", &args); - switch (GetParam()) { - case PROTO_PATH: - args.push_back("--proto_path=" + TestSourceDir()); - break; - case DESCRIPTOR_SET_IN: - args.push_back(StrCat( - "--descriptor_set_in=", - unittest_proto_descriptor_set_filename_)); - break; - default: - ADD_FAILURE() << "unexpected EncodeDecodeTestMode: " << GetParam(); + for (StringPiece split_piece : + Split(command, " ", true)) { + args.push_back(std::string(split_piece)); + } + if (specify_proto_files) { + switch (GetParam()) { + case PROTO_PATH: + args.push_back("--proto_path=" + TestUtil::TestSourceDir()); + break; + case DESCRIPTOR_SET_IN: + args.push_back(StrCat("--descriptor_set_in=", + unittest_proto_descriptor_set_filename_)); + break; + default: + ADD_FAILURE() << "unexpected EncodeDecodeTestMode: " << GetParam(); + } } - google::protobuf::scoped_array argv(new const char* [args.size()]); + std::unique_ptr argv(new const char*[args.size()]); for (int i = 0; i < args.size(); i++) { argv[i] = args[i].c_str(); } @@ -2284,8 +2567,8 @@ class EncodeDecodeTest : public testing::TestWithParam { return result == 0; } - void ExpectStdoutMatchesBinaryFile(const string& filename) { - string expected_output; + void ExpectStdoutMatchesBinaryFile(const std::string& filename) { + std::string expected_output; GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true)); // Don't use EXPECT_EQ because we don't want to print raw binary data to @@ -2293,21 +2576,26 @@ class EncodeDecodeTest : public testing::TestWithParam { EXPECT_TRUE(captured_stdout_ == expected_output); } - void ExpectStdoutMatchesTextFile(const string& filename) { - string expected_output; + void ExpectStdoutMatchesTextFile(const std::string& filename) { + std::string expected_output; GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true)); ExpectStdoutMatchesText(expected_output); } - void ExpectStdoutMatchesText(const string& expected_text) { + void ExpectStdoutMatchesText(const std::string& expected_text) { EXPECT_EQ(StripCR(expected_text), StripCR(captured_stdout_)); } - void ExpectStderrMatchesText(const string& expected_text) { + void ExpectStderrMatchesText(const std::string& expected_text) { EXPECT_EQ(StripCR(expected_text), StripCR(captured_stderr_)); } + void ExpectStderrContainsText(const std::string& expected_text) { + EXPECT_NE(StripCR(captured_stderr_).find(StripCR(expected_text)), + std::string::npos); + } + private: void WriteUnittestProtoDescriptorSet() { unittest_proto_descriptor_set_filename_ = @@ -2319,88 +2607,120 @@ class EncodeDecodeTest : public testing::TestWithParam { protobuf_unittest_import::ImportMessage import_message; import_message.descriptor()->file()->CopyTo(file_descriptor_set.add_file()); - protobuf_unittest_import::PublicImportMessage public_import_message; public_import_message.descriptor()->file()->CopyTo( file_descriptor_set.add_file()); GOOGLE_DCHECK(file_descriptor_set.IsInitialized()); - string binary_proto; + std::string binary_proto; GOOGLE_CHECK(file_descriptor_set.SerializeToString(&binary_proto)); - GOOGLE_CHECK_OK(File::SetContents( - unittest_proto_descriptor_set_filename_, - binary_proto, - true)); + GOOGLE_CHECK_OK(File::SetContents(unittest_proto_descriptor_set_filename_, + binary_proto, true)); } int duped_stdin_; - string captured_stdout_; - string captured_stderr_; - string unittest_proto_descriptor_set_filename_; + std::string captured_stdout_; + std::string captured_stderr_; + std::string unittest_proto_descriptor_set_filename_; }; TEST_P(EncodeDecodeTest, Encode) { - RedirectStdinFromFile(TestSourceDir() + "/google/protobuf/" - "testdata/text_format_unittest_data_oneof_implemented.txt"); - EXPECT_TRUE(Run("google/protobuf/unittest.proto " - "--encode=protobuf_unittest.TestAllTypes")); - ExpectStdoutMatchesBinaryFile(TestSourceDir() + - "/google/protobuf/testdata/golden_message_oneof_implemented"); + RedirectStdinFromFile(TestUtil::GetTestDataPath( + "net/proto2/internal/" + "testdata/text_format_unittest_data_oneof_implemented.txt")); + std::string args; + if (GetParam() != DESCRIPTOR_SET_IN) { + args.append( + TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto")); + } + EXPECT_TRUE(Run(args + " --encode=protobuf_unittest.TestAllTypes")); + ExpectStdoutMatchesBinaryFile(TestUtil::GetTestDataPath( + "net/proto2/internal/testdata/golden_message_oneof_implemented")); ExpectStderrMatchesText(""); } TEST_P(EncodeDecodeTest, Decode) { - RedirectStdinFromFile(TestSourceDir() + - "/google/protobuf/testdata/golden_message_oneof_implemented"); - EXPECT_TRUE(Run("google/protobuf/unittest.proto " - "--decode=protobuf_unittest.TestAllTypes")); - ExpectStdoutMatchesTextFile(TestSourceDir() + - "/google/protobuf/" - "testdata/text_format_unittest_data_oneof_implemented.txt"); + RedirectStdinFromFile(TestUtil::GetTestDataPath( + "net/proto2/internal/testdata/golden_message_oneof_implemented")); + EXPECT_TRUE( + Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") + + " --decode=protobuf_unittest.TestAllTypes")); + ExpectStdoutMatchesTextFile(TestUtil::GetTestDataPath( + "net/proto2/internal/" + "testdata/text_format_unittest_data_oneof_implemented.txt")); ExpectStderrMatchesText(""); } TEST_P(EncodeDecodeTest, Partial) { RedirectStdinFromText(""); - EXPECT_TRUE(Run("google/protobuf/unittest.proto " - "--encode=protobuf_unittest.TestRequired")); + EXPECT_TRUE( + Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") + + " --encode=protobuf_unittest.TestRequired")); ExpectStdoutMatchesText(""); ExpectStderrMatchesText( - "warning: Input message is missing required fields: a, b, c\n"); + "warning: Input message is missing required fields: a, b, c\n"); } TEST_P(EncodeDecodeTest, DecodeRaw) { protobuf_unittest::TestAllTypes message; message.set_optional_int32(123); message.set_optional_string("foo"); - string data; + std::string data; message.SerializeToString(&data); RedirectStdinFromText(data); - EXPECT_TRUE(Run("--decode_raw")); - ExpectStdoutMatchesText("1: 123\n" - "14: \"foo\"\n"); + EXPECT_TRUE(Run("--decode_raw", /*specify_proto_files=*/false)); + ExpectStdoutMatchesText( + "1: 123\n" + "14: \"foo\"\n"); ExpectStderrMatchesText(""); } TEST_P(EncodeDecodeTest, UnknownType) { - EXPECT_FALSE(Run("google/protobuf/unittest.proto " - "--encode=NoSuchType")); + EXPECT_FALSE( + Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") + + " --encode=NoSuchType")); ExpectStdoutMatchesText(""); ExpectStderrMatchesText("Type not defined: NoSuchType\n"); } TEST_P(EncodeDecodeTest, ProtoParseError) { - EXPECT_FALSE(Run("google/protobuf/no_such_file.proto " - "--encode=NoSuchType")); + EXPECT_FALSE( + Run("net/proto2/internal/no_such_file.proto " + "--encode=NoSuchType")); ExpectStdoutMatchesText(""); + ExpectStderrContainsText( + "net/proto2/internal/no_such_file.proto: No such file or directory\n"); +} + +TEST_P(EncodeDecodeTest, EncodeDeterministicOutput) { + RedirectStdinFromFile(TestUtil::GetTestDataPath( + "net/proto2/internal/" + "testdata/text_format_unittest_data_oneof_implemented.txt")); + std::string args; + if (GetParam() != DESCRIPTOR_SET_IN) { + args.append( + TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto")); + } + EXPECT_TRUE(Run( + args + " --encode=protobuf_unittest.TestAllTypes --deterministic_output")); + ExpectStdoutMatchesBinaryFile(TestUtil::GetTestDataPath( + "net/proto2/internal/testdata/golden_message_oneof_implemented")); + ExpectStderrMatchesText(""); +} + +TEST_P(EncodeDecodeTest, DecodeDeterministicOutput) { + RedirectStdinFromFile(TestUtil::GetTestDataPath( + "net/proto2/internal/testdata/golden_message_oneof_implemented")); + EXPECT_FALSE( + Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") + + " --decode=protobuf_unittest.TestAllTypes --deterministic_output")); ExpectStderrMatchesText( - "google/protobuf/no_such_file.proto: No such file or directory\n"); + "Can only use --deterministic_output with --encode.\n"); } -INSTANTIATE_TEST_CASE_P(FileDescriptorSetSource, - EncodeDecodeTest, - testing::Values(PROTO_PATH, DESCRIPTOR_SET_IN)); +INSTANTIATE_TEST_SUITE_P(FileDescriptorSetSource, EncodeDecodeTest, + testing::Values(PROTO_PATH, DESCRIPTOR_SET_IN)); } // anonymous namespace #endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc index f99159f5e99fa..31fe5a6841280 100644 --- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc @@ -32,7 +32,7 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. // -// This test insures that google/protobuf/descriptor.pb.{h,cc} match exactly +// This test insures that net/proto2/proto/descriptor.pb.{h,cc} match exactly // what would be generated by the protocol compiler. These files are not // generated automatically at build time because they are compiled into the // protocol compiler itself. So, if they were auto-generated, you'd have a @@ -44,19 +44,21 @@ #include +#include +#include +#include #include #include +#include #include #include +#include +#include +#include #include #include #include -#include -#include -#include -#include - namespace google { namespace protobuf { namespace compiler { @@ -69,84 +71,124 @@ class MockErrorCollector : public MultiFileErrorCollector { MockErrorCollector() {} ~MockErrorCollector() {} - string text_; + std::string text_; // implements ErrorCollector --------------------------------------- - void AddError(const string& filename, int line, int column, - const string& message) { - strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", - filename, line, column, message); + void AddError(const std::string& filename, int line, int column, + const std::string& message) { + strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column, + message); } }; class MockGeneratorContext : public GeneratorContext { public: - MockGeneratorContext() {} - ~MockGeneratorContext() { - STLDeleteValues(&files_); - } - - void ExpectFileMatches(const string& virtual_filename, - const string& physical_filename) { - string* expected_contents = FindPtrOrNull(files_, virtual_filename); - ASSERT_TRUE(expected_contents != NULL) - << "Generator failed to generate file: " << virtual_filename; - - string actual_contents; + void ExpectFileMatches(const std::string& virtual_filename, + const std::string& physical_filename) { + auto it = files_.find(virtual_filename); + ASSERT_TRUE(it != files_.end()) + << "Generator failed to generate file: " << virtual_filename; + + std::string expected_contents = *it->second; + std::string actual_contents; + GOOGLE_CHECK_OK( + File::GetContents(TestUtil::TestSourceDir() + "/" + physical_filename, + &actual_contents, true)) + << physical_filename; + CleanStringLineEndings(&actual_contents, false); + +#ifdef WRITE_FILES // Define to debug mismatched files. + GOOGLE_CHECK_OK(File::SetContents("/tmp/expected.cc", expected_contents, + true)); GOOGLE_CHECK_OK( - File::GetContents(TestSourceDir() + "/" + physical_filename, - &actual_contents, true)); - EXPECT_TRUE(actual_contents == *expected_contents) - << physical_filename << " needs to be regenerated. Please run " - "generate_descriptor_proto.sh. Then add this file " - "to your CL."; + File::SetContents("/tmp/actual.cc", actual_contents, true)); +#endif + + ASSERT_EQ(expected_contents, actual_contents) + << physical_filename + << " needs to be regenerated. Please run " + "generate_descriptor_proto.sh. " + "Then add this file to your CL."; } // implements GeneratorContext -------------------------------------- - virtual io::ZeroCopyOutputStream* Open(const string& filename) { - string** map_slot = &files_[filename]; - delete *map_slot; - *map_slot = new string; - - return new io::StringOutputStream(*map_slot); + virtual io::ZeroCopyOutputStream* Open(const std::string& filename) { + auto& map_slot = files_[filename]; + map_slot.reset(new std::string); + return new io::StringOutputStream(map_slot.get()); } private: - std::map files_; + std::map> files_; }; -TEST(BootstrapTest, GeneratedDescriptorMatches) { - MockErrorCollector error_collector; +const char kDescriptorParameter[] = "dllexport_decl=PROTOBUF_EXPORT"; +const char kPluginParameter[] = "dllexport_decl=PROTOC_EXPORT"; + + +const char* test_protos[][2] = { + {"google/protobuf/descriptor", kDescriptorParameter}, + {"google/protobuf/compiler/plugin", kPluginParameter}, +}; + +TEST(BootstrapTest, GeneratedFilesMatch) { + // We need a mapping from the actual file to virtual and actual path + // of the data to compare to. + std::map vpath_map; + std::map rpath_map; + rpath_map + ["third_party/protobuf_legacy_opensource/src/google/protobuf/" + "test_messages_proto2"] = + "net/proto2/z_generated_example/test_messages_proto2"; + rpath_map + ["third_party/protobuf_legacy_opensource/src/google/protobuf/" + "test_messages_proto3"] = + "net/proto2/z_generated_example/test_messages_proto3"; + rpath_map["net/proto2/internal/proto2_weak"] = + "net/proto2/z_generated_example/proto2_weak"; + DiskSourceTree source_tree; - source_tree.MapPath("", TestSourceDir()); - Importer importer(&source_tree, &error_collector); - const FileDescriptor* proto_file = - importer.Import("google/protobuf/descriptor.proto"); - const FileDescriptor* plugin_proto_file = - importer.Import("google/protobuf/compiler/plugin.proto"); - EXPECT_EQ("", error_collector.text_); - ASSERT_TRUE(proto_file != NULL); - ASSERT_TRUE(plugin_proto_file != NULL); - - CppGenerator generator; - MockGeneratorContext context; - string error; - string parameter = "dllexport_decl=LIBPROTOBUF_EXPORT"; - ASSERT_TRUE(generator.Generate(proto_file, parameter, - &context, &error)); - parameter = "dllexport_decl=LIBPROTOC_EXPORT"; - ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter, - &context, &error)); - - context.ExpectFileMatches("google/protobuf/descriptor.pb.h", - "google/protobuf/descriptor.pb.h"); - context.ExpectFileMatches("google/protobuf/descriptor.pb.cc", - "google/protobuf/descriptor.pb.cc"); - context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h", - "google/protobuf/compiler/plugin.pb.h"); - context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc", - "google/protobuf/compiler/plugin.pb.cc"); + source_tree.MapPath("", TestUtil::TestSourceDir()); + + for (auto file_parameter : test_protos) { + MockErrorCollector error_collector; + Importer importer(&source_tree, &error_collector); + const FileDescriptor* file = + importer.Import(file_parameter[0] + std::string(".proto")); + ASSERT_TRUE(file != nullptr) + << "Can't import file " << file_parameter[0] + std::string(".proto") + << "\n"; + EXPECT_EQ("", error_collector.text_); + CppGenerator generator; + MockGeneratorContext context; +#ifdef GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE + generator.set_opensource_runtime(true); + generator.set_runtime_include_base(GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE); +#endif + std::string error; + ASSERT_TRUE(generator.Generate(file, file_parameter[1], &context, &error)); + + std::string vpath = + FindWithDefault(vpath_map, file_parameter[0], file_parameter[0]); + std::string rpath = + FindWithDefault(rpath_map, file_parameter[0], file_parameter[0]); + context.ExpectFileMatches(vpath + ".pb.cc", rpath + ".pb.cc"); + context.ExpectFileMatches(vpath + ".pb.h", rpath + ".pb.h"); + } +} + +// test Generate in cpp_generator.cc +TEST(BootstrapTest, OptionNotExist) { + cpp::CppGenerator generator; + DescriptorPool pool; + GeneratorContext* generator_context = nullptr; + std::string parameter = "aaa"; + std::string error; + ASSERT_FALSE(generator.Generate( + pool.FindFileByName("google/protobuf/descriptor.proto"), parameter, + generator_context, &error)); + EXPECT_EQ(error, "Unknown generator option: " + parameter); } } // namespace diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc index 3b4b97e654ad8..7f9754f67f4b7 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -46,7 +46,7 @@ namespace cpp { namespace { // The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value -// is ::google::protobuf::kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the +// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the // generation of the GOOGLE_ARRAYSIZE constant. bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { int32 max_value = descriptor->value(0)->number(); @@ -55,61 +55,61 @@ bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { max_value = descriptor->value(i)->number(); } } - return max_value != ::google::protobuf::kint32max; + return max_value != kint32max; } + +// Returns the number of unique numeric enum values. This is less than +// descriptor->value_count() when there are aliased values. +int CountUniqueValues(const EnumDescriptor* descriptor) { + std::set values; + for (int i = 0; i < descriptor->value_count(); ++i) { + values.insert(descriptor->value(i)->number()); + } + return values.size(); +} + } // namespace EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, + const std::map& vars, const Options& options) - : descriptor_(descriptor), - classname_(ClassName(descriptor, false)), - options_(options), - generate_array_size_(ShouldGenerateArraySize(descriptor)) { + : descriptor_(descriptor), + classname_(ClassName(descriptor, false)), + options_(options), + generate_array_size_(ShouldGenerateArraySize(descriptor)), + variables_(vars) { + variables_["classname"] = classname_; + variables_["classtype"] = QualifiedClassName(descriptor_, options); + variables_["short_name"] = descriptor_->name(); + variables_["nested_name"] = descriptor_->name(); + variables_["resolved_name"] = ResolveKeyword(descriptor_->name()); + variables_["prefix"] = + (descriptor_->containing_type() == NULL) ? "" : classname_ + "_"; } EnumGenerator::~EnumGenerator() {} -void EnumGenerator::FillForwardDeclaration( - std::map* enum_names) { - if (!options_.proto_h) { - return; - } - (*enum_names)[classname_] = descriptor_; -} - void EnumGenerator::GenerateDefinition(io::Printer* printer) { - std::map vars; - vars["classname"] = classname_; - vars["short_name"] = descriptor_->name(); - vars["enumbase"] = options_.proto_h ? " : int" : ""; - // These variables are placeholders to pick out the beginning and ends of - // identifiers for annotations (when doing so with existing variables would - // be ambiguous or impossible). They should never be set to anything but the - // empty string. - vars["{"] = ""; - vars["}"] = ""; - - printer->Print(vars, "enum $classname$$enumbase$ {\n"); - printer->Annotate("classname", descriptor_); - printer->Indent(); + Formatter format(printer, variables_); + format("enum ${1$$classname$$}$ : int {\n", descriptor_); + format.Indent(); const EnumValueDescriptor* min_value = descriptor_->value(0); const EnumValueDescriptor* max_value = descriptor_->value(0); for (int i = 0; i < descriptor_->value_count(); i++) { - vars["name"] = EnumValueName(descriptor_->value(i)); + auto format_value = format; + format_value.Set("name", EnumValueName(descriptor_->value(i))); // In C++, an value of -2147483648 gets interpreted as the negative of // 2147483648, and since 2147483648 can't fit in an integer, this produces a // compiler warning. This works around that issue. - vars["number"] = Int32ToString(descriptor_->value(i)->number()); - vars["prefix"] = (descriptor_->containing_type() == NULL) ? - "" : classname_ + "_"; - vars["deprecation"] = descriptor_->value(i)->options().deprecated() ? - " PROTOBUF_DEPRECATED" : ""; + format_value.Set("number", Int32ToString(descriptor_->value(i)->number())); + format_value.Set("deprecation", + DeprecatedAttribute(options_, descriptor_->value(i))); - if (i > 0) printer->Print(",\n"); - printer->Print(vars, "${$$prefix$$name$$}$$deprecation$ = $number$"); - printer->Annotate("{", "}", descriptor_->value(i)); + if (i > 0) format_value(",\n"); + format_value("${1$$prefix$$name$$}$ $deprecation$= $number$", + descriptor_->value(i)); if (descriptor_->value(i)->number() < min_value->number()) { min_value = descriptor_->value(i); @@ -119,166 +119,164 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { } } - if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { + if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { // For new enum semantics: generate min and max sentinel values equal to // INT32_MIN and INT32_MAX - if (descriptor_->value_count() > 0) printer->Print(",\n"); - printer->Print(vars, - "$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,\n" - "$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max"); + if (descriptor_->value_count() > 0) format(",\n"); + format( + "$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = " + "std::numeric_limits<$int32$>::min(),\n" + "$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = " + "std::numeric_limits<$int32$>::max()"); } - printer->Outdent(); - printer->Print("\n};\n"); + format.Outdent(); + format("\n};\n"); - vars["min_name"] = EnumValueName(min_value); - vars["max_name"] = EnumValueName(max_value); + format( + "$dllexport_decl $bool $classname$_IsValid(int value);\n" + "constexpr $classname$ ${1$$prefix$$short_name$_MIN$}$ = " + "$prefix$$2$;\n" + "constexpr $classname$ ${1$$prefix$$short_name$_MAX$}$ = " + "$prefix$$3$;\n", + descriptor_, EnumValueName(min_value), EnumValueName(max_value)); - if (options_.dllexport_decl.empty()) { - vars["dllexport"] = ""; - } else { - vars["dllexport"] = options_.dllexport_decl + " "; + if (generate_array_size_) { + format( + "constexpr int ${1$$prefix$$short_name$_ARRAYSIZE$}$ = " + "$prefix$$short_name$_MAX + 1;\n\n", + descriptor_); } - printer->Print(vars, - "$dllexport$bool $classname$_IsValid(int value);\n" - "const $classname$ ${$$prefix$$short_name$_MIN$}$ = " - "$prefix$$min_name$;\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(vars, - "const $classname$ ${$$prefix$$short_name$_MAX$}$ = " - "$prefix$$max_name$;\n"); - printer->Annotate("{", "}", descriptor_); + if (HasDescriptorMethods(descriptor_->file(), options_)) { + format( + "$dllexport_decl $const ::$proto_ns$::EnumDescriptor* " + "$classname$_descriptor();\n"); + } - if (generate_array_size_) { - printer->Print(vars, - "const int ${$$prefix$$short_name$_ARRAYSIZE$}$ = " - "$prefix$$short_name$_MAX + 1;\n\n"); - printer->Annotate("{", "}", descriptor_); + // The _Name and _Parse functions. The lite implementation is table-based, so + // we make sure to keep the tables hidden in the .cc file. + if (!HasDescriptorMethods(descriptor_->file(), options_)) { + format("const std::string& $classname$_Name($classname$ value);\n"); + } + // The _Name() function accepts the enum type itself but also any integral + // type. + format( + "template\n" + "inline const std::string& $classname$_Name(T enum_t_value) {\n" + " static_assert(::std::is_same::value ||\n" + " ::std::is_integral::value,\n" + " \"Incorrect type passed to function $classname$_Name.\");\n"); + if (HasDescriptorMethods(descriptor_->file(), options_)) { + format( + " return ::$proto_ns$::internal::NameOfEnum(\n" + " $classname$_descriptor(), enum_t_value);\n"); + } else { + format( + " return $classname$_Name(static_cast<$classname$>(enum_t_value));\n"); } + format("}\n"); if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print(vars, - "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n"); - // The _Name and _Parse methods - printer->Print( - vars, - "inline const ::std::string& $classname$_Name($classname$ value) {\n" - " return ::google::protobuf::internal::NameOfEnum(\n" - " $classname$_descriptor(), value);\n" + format( + "inline bool $classname$_Parse(\n" + " ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* " + "value) " + "{\n" + " return ::$proto_ns$::internal::ParseNamedEnum<$classname$>(\n" + " $classname$_descriptor(), name, value);\n" "}\n"); - printer->Print(vars, - "inline bool $classname$_Parse(\n" - " const ::std::string& name, $classname$* value) {\n" - " return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n" - " $classname$_descriptor(), name, value);\n" - "}\n"); + } else { + format( + "bool $classname$_Parse(\n" + " ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* " + "value);\n"); } } -void EnumGenerator:: -GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { - printer->Print( - "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type " - "{};\n", - "classname", ClassName(descriptor_, true)); +void EnumGenerator::GenerateGetEnumDescriptorSpecializations( + io::Printer* printer) { + Formatter format(printer, variables_); + format( + "template <> struct is_proto_enum< $classtype$> : ::std::true_type " + "{};\n"); if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print( - "template <>\n" - "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n" - " return $classname$_descriptor();\n" - "}\n", - "classname", ClassName(descriptor_, true)); + format( + "template <>\n" + "inline const EnumDescriptor* GetEnumDescriptor< $classtype$>() {\n" + " return $classtype$_descriptor();\n" + "}\n"); } } -void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { - std::map vars; - vars["nested_name"] = descriptor_->name(); - vars["classname"] = classname_; - vars["constexpr"] = options_.proto_h ? "constexpr " : ""; - printer->Print(vars, "typedef $classname$ $nested_name$;\n"); +void EnumGenerator::GenerateSymbolImports(io::Printer* printer) const { + Formatter format(printer, variables_); + format("typedef $classname$ $resolved_name$;\n"); for (int j = 0; j < descriptor_->value_count(); j++) { - vars["tag"] = EnumValueName(descriptor_->value(j)); - vars["deprecated_attr"] = descriptor_->value(j)->options().deprecated() ? - "GOOGLE_PROTOBUF_DEPRECATED_ATTR " : ""; - printer->Print(vars, - "$deprecated_attr$static $constexpr$const $nested_name$ $tag$ =\n" - " $classname$_$tag$;\n"); + std::string deprecated_attr = + DeprecatedAttribute(options_, descriptor_->value(j)); + format( + "$1$static constexpr $resolved_name$ ${2$$3$$}$ =\n" + " $classname$_$3$;\n", + deprecated_attr, descriptor_->value(j), + EnumValueName(descriptor_->value(j))); } - printer->Print(vars, - "static inline bool $nested_name$_IsValid(int value) {\n" - " return $classname$_IsValid(value);\n" - "}\n" - "static const $nested_name$ $nested_name$_MIN =\n" - " $classname$_$nested_name$_MIN;\n" - "static const $nested_name$ $nested_name$_MAX =\n" - " $classname$_$nested_name$_MAX;\n"); + format( + "static inline bool $nested_name$_IsValid(int value) {\n" + " return $classname$_IsValid(value);\n" + "}\n" + "static constexpr $resolved_name$ ${1$$nested_name$_MIN$}$ =\n" + " $classname$_$nested_name$_MIN;\n" + "static constexpr $resolved_name$ ${1$$nested_name$_MAX$}$ =\n" + " $classname$_$nested_name$_MAX;\n", + descriptor_); if (generate_array_size_) { - printer->Print(vars, - "static const int $nested_name$_ARRAYSIZE =\n" - " $classname$_$nested_name$_ARRAYSIZE;\n"); + format( + "static constexpr int ${1$$nested_name$_ARRAYSIZE$}$ =\n" + " $classname$_$nested_name$_ARRAYSIZE;\n", + descriptor_); } if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print(vars, - "static inline const ::google::protobuf::EnumDescriptor*\n" - "$nested_name$_descriptor() {\n" - " return $classname$_descriptor();\n" + format( + "static inline const ::$proto_ns$::EnumDescriptor*\n" + "$nested_name$_descriptor() {\n" + " return $classname$_descriptor();\n" + "}\n"); + } + + format( + "template\n" + "static inline const std::string& $nested_name$_Name(T enum_t_value) {\n" + " static_assert(::std::is_same::value ||\n" + " ::std::is_integral::value,\n" + " \"Incorrect type passed to function $nested_name$_Name.\");\n" + " return $classname$_Name(enum_t_value);\n" "}\n"); - printer->Print(vars, - "static inline const ::std::string& " - "$nested_name$_Name($nested_name$ value) {" - "\n" - " return $classname$_Name(value);\n" - "}\n"); - printer->Print(vars, - "static inline bool $nested_name$_Parse(const ::std::string& name,\n" - " $nested_name$* value) {\n" + format( + "static inline bool " + "$nested_name$_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,\n" + " $resolved_name$* value) {\n" " return $classname$_Parse(name, value);\n" "}\n"); - } -} - -void EnumGenerator::GenerateDescriptorInitializer(io::Printer* printer) { - std::map vars; - vars["index"] = SimpleItoa(descriptor_->index()); - vars["index_in_metadata"] = SimpleItoa(index_in_metadata_); - - if (descriptor_->containing_type() == NULL) { - printer->Print(vars, - "file_level_enum_descriptors[$index_in_metadata$] = " - "file->enum_type($index$);\n"); - } else { - vars["parent"] = ClassName(descriptor_->containing_type(), false); - printer->Print(vars, - "file_level_enum_descriptors[$index_in_metadata$] = " - "$parent$_descriptor->enum_type($index$);\n"); - } } -void EnumGenerator::GenerateMethods(io::Printer* printer) { - std::map vars; - vars["classname"] = classname_; - vars["index_in_metadata"] = SimpleItoa(index_in_metadata_); - vars["constexpr"] = options_.proto_h ? "constexpr " : ""; - vars["file_namespace"] = FileLevelNamespace(descriptor_->file()->name()); - +void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) { + Formatter format(printer, variables_); if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print( - vars, - "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n" - " $file_namespace$::protobuf_AssignDescriptorsOnce();\n" - " return " - "$file_namespace$::file_level_enum_descriptors[$index_in_metadata$];\n" - "}\n"); + format( + "const ::$proto_ns$::EnumDescriptor* $classname$_descriptor() {\n" + " ::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n" + " return $file_level_enum_descriptors$[$1$];\n" + "}\n", + idx); } - printer->Print(vars, - "bool $classname$_IsValid(int value) {\n" - " switch (value) {\n"); + format( + "bool $classname$_IsValid(int value) {\n" + " switch (value) {\n"); // Multiple values may have the same number. Make sure we only cover // each number once by first constructing a set containing all valid @@ -290,44 +288,143 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) { numbers.insert(value->number()); } - for (std::set::iterator iter = numbers.begin(); - iter != numbers.end(); ++iter) { - printer->Print( - " case $number$:\n", - "number", Int32ToString(*iter)); + for (std::set::iterator iter = numbers.begin(); iter != numbers.end(); + ++iter) { + format(" case $1$:\n", Int32ToString(*iter)); } - printer->Print(vars, - " return true;\n" - " default:\n" - " return false;\n" - " }\n" - "}\n" - "\n"); + format( + " return true;\n" + " default:\n" + " return false;\n" + " }\n" + "}\n" + "\n"); + + if (!HasDescriptorMethods(descriptor_->file(), options_)) { + // In lite mode (where descriptors are unavailable), we generate separate + // tables for mapping between enum names and numbers. The _entries table + // contains the bulk of the data and is sorted by name, while + // _entries_by_number is sorted by number and just contains pointers into + // _entries. The two tables allow mapping from name to number and number to + // name, both in time logarithmic in the number of enum entries. This could + // probably be made faster, but for now the tables are intended to be simple + // and compact. + // + // Enums with allow_alias = true support multiple entries with the same + // numerical value. In cases where there are multiple names for the same + // number, we treat the first name appearing in the .proto file as the + // canonical one. + std::map name_to_number; + std::map number_to_canonical_name; + for (int i = 0; i < descriptor_->value_count(); i++) { + const EnumValueDescriptor* value = descriptor_->value(i); + name_to_number.emplace(value->name(), value->number()); + // The same number may appear with multiple names, so we use emplace() to + // let the first name win. + number_to_canonical_name.emplace(value->number(), value->name()); + } + + format( + "static ::$proto_ns$::internal::ExplicitlyConstructed " + "$classname$_strings[$1$] = {};\n\n", + CountUniqueValues(descriptor_)); + + // We concatenate all the names for a given enum into one big string + // literal. If instead we store an array of string literals, the linker + // seems to put all enum strings for a given .proto file in the same + // section, which hinders its ability to strip out unused strings. + format("static const char $classname$_names[] ="); + for (const auto& p : name_to_number) { + format("\n \"$1$\"", p.first); + } + format(";\n\n"); + + format( + "static const ::$proto_ns$::internal::EnumEntry $classname$_entries[] " + "= {\n"); + int i = 0; + std::map number_to_index; + int data_index = 0; + for (const auto& p : name_to_number) { + format(" { {$classname$_names + $1$, $2$}, $3$ },\n", data_index, + p.first.size(), p.second); + if (number_to_canonical_name[p.second] == p.first) { + number_to_index.emplace(p.second, i); + } + ++i; + data_index += p.first.size(); + } + + format( + "};\n" + "\n" + "static const int $classname$_entries_by_number[] = {\n"); + for (const auto& p : number_to_index) { + format(" $1$, // $2$ -> $3$\n", p.second, p.first, + number_to_canonical_name[p.first]); + } + format( + "};\n" + "\n"); + + format( + "const std::string& $classname$_Name(\n" + " $classname$ value) {\n" + " static const bool dummy =\n" + " ::$proto_ns$::internal::InitializeEnumStrings(\n" + " $classname$_entries,\n" + " $classname$_entries_by_number,\n" + " $1$, $classname$_strings);\n" + " (void) dummy;\n" + " int idx = ::$proto_ns$::internal::LookUpEnumName(\n" + " $classname$_entries,\n" + " $classname$_entries_by_number,\n" + " $1$, value);\n" + " return idx == -1 ? ::$proto_ns$::internal::GetEmptyString() :\n" + " $classname$_strings[idx].get();\n" + "}\n", + CountUniqueValues(descriptor_)); + format( + "bool $classname$_Parse(\n" + " ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* " + "value) " + "{\n" + " int int_value;\n" + " bool success = ::$proto_ns$::internal::LookUpEnumValue(\n" + " $classname$_entries, $1$, name, &int_value);\n" + " if (success) {\n" + " *value = static_cast<$classname$>(int_value);\n" + " }\n" + " return success;\n" + "}\n", + descriptor_->value_count()); + } if (descriptor_->containing_type() != NULL) { - // We need to "define" the static constants which were declared in the - // header, to give the linker a place to put them. Or at least the C++ - // standard says we have to. MSVC actually insists that we do _not_ define - // them again in the .cc file, prior to VC++ 2015. - printer->Print("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"); - - vars["parent"] = ClassName(descriptor_->containing_type(), false); - vars["nested_name"] = descriptor_->name(); + std::string parent = ClassName(descriptor_->containing_type(), false); + // Before C++17, we must define the static constants which were + // declared in the header, to give the linker a place to put them. + // But pre-2015 MSVC++ insists that we not. + format( + "#if (__cplusplus < 201703) && " + "(!defined(_MSC_VER) || _MSC_VER >= 1900)\n"); + for (int i = 0; i < descriptor_->value_count(); i++) { - vars["value"] = EnumValueName(descriptor_->value(i)); - printer->Print(vars, - "$constexpr$const $classname$ $parent$::$value$;\n"); + format("constexpr $classname$ $1$::$2$;\n", parent, + EnumValueName(descriptor_->value(i))); } - printer->Print(vars, - "const $classname$ $parent$::$nested_name$_MIN;\n" - "const $classname$ $parent$::$nested_name$_MAX;\n"); + format( + "constexpr $classname$ $1$::$nested_name$_MIN;\n" + "constexpr $classname$ $1$::$nested_name$_MAX;\n", + parent); if (generate_array_size_) { - printer->Print(vars, - "const int $parent$::$nested_name$_ARRAYSIZE;\n"); + format("constexpr int $1$::$nested_name$_ARRAYSIZE;\n", parent); } - printer->Print("#endif // !defined(_MSC_VER) || _MSC_VER >= 1900\n"); + format( + "#endif // (__cplusplus < 201703) && " + "(!defined(_MSC_VER) || _MSC_VER >= 1900)\n"); } } diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h index 0b568c57b926f..3687f04c271f8 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum.h @@ -43,11 +43,13 @@ namespace google { namespace protobuf { - namespace io { - class Printer; // printer.h - } +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace cpp { @@ -55,20 +57,11 @@ namespace cpp { class EnumGenerator { public: // See generator.cc for the meaning of dllexport_decl. - EnumGenerator(const EnumDescriptor* descriptor, const Options& options); + EnumGenerator(const EnumDescriptor* descriptor, + const std::map& vars, + const Options& options); ~EnumGenerator(); - // Header stuff. - - // Fills the name to use when declaring the enum. This is for use when - // generating other .proto.h files. This code should be placed within the - // enum's package namespace, but NOT within any class, even for nested - // enums. A given key in enum_names will map from an enum class name to the - // EnumDescriptor that was responsible for its inclusion in the map. This can - // be used to associate the descriptor with the code generated for it. - void FillForwardDeclaration( - std::map* enum_names); - // Generate header code defining the enum. This code should be placed // within the enum's package namespace, but NOT within any class, even for // nested enums. @@ -82,26 +75,23 @@ class EnumGenerator { // symbols (e.g. the enum type name, all its values, etc.) into the class's // namespace. This should be placed inside the class definition in the // header. - void GenerateSymbolImports(io::Printer* printer); + void GenerateSymbolImports(io::Printer* printer) const; // Source file stuff. - // Generate code that initializes the global variable storing the enum's - // descriptor. - void GenerateDescriptorInitializer(io::Printer* printer); - // Generate non-inline methods related to the enum, such as IsValidValue(). - // Goes in the .cc file. - void GenerateMethods(io::Printer* printer); + // Goes in the .cc file. EnumDescriptors are stored in an array, idx is + // the index in this array that corresponds with this enum. + void GenerateMethods(int idx, io::Printer* printer); private: const EnumDescriptor* descriptor_; - const string classname_; + const std::string classname_; const Options& options_; // whether to generate the *_ARRAYSIZE constant. const bool generate_array_size_; - int index_in_metadata_; + std::map variables_; friend class FileGenerator; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); @@ -110,6 +100,6 @@ class EnumGenerator { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index 08a635fa97501..57e6d7e6ce9d8 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -46,11 +46,11 @@ namespace cpp { namespace { void SetEnumVariables(const FieldDescriptor* descriptor, - std::map* variables, + std::map* variables, const Options& options) { SetCommonFieldVariables(descriptor, variables, options); const EnumValueDescriptor* default_value = descriptor->default_value_enum(); - (*variables)["type"] = ClassName(descriptor->enum_type(), true); + (*variables)["type"] = QualifiedClassName(descriptor->enum_type(), options); (*variables)["default"] = Int32ToString(default_value->number()); (*variables)["full_name"] = descriptor->full_name(); } @@ -61,467 +61,443 @@ void SetEnumVariables(const FieldDescriptor* descriptor, EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), descriptor_(descriptor) { + : FieldGenerator(descriptor, options) { SetEnumVariables(descriptor, &variables_, options); } EnumFieldGenerator::~EnumFieldGenerator() {} -void EnumFieldGenerator:: -GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, "int $name$_;\n"); -} - -void EnumFieldGenerator:: -GenerateAccessorDeclarations(io::Printer* printer) const { - printer->Print(variables_, "$deprecated_attr$$type$ $name$() const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$set_$name$$}$($type$ value);\n"); - printer->Annotate("{", "}", descriptor_); -} - -void EnumFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const { - std::map variables(variables_); - variables["inline"] = is_inline ? "inline " : ""; - printer->Print(variables, - "$inline$$type$ $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return static_cast< $type$ >($name$_);\n" - "}\n" - "$inline$void $classname$::set_$name$($type$ value) {\n"); - if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables, - " assert($type$_IsValid(value));\n"); +void EnumFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const { + Formatter format(printer, variables_); + format("int $name$_;\n"); +} + +void EnumFieldGenerator::GenerateAccessorDeclarations( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "$deprecated_attr$$type$ ${1$$name$$}$() const;\n" + "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n" + "private:\n" + "$type$ ${1$_internal_$name$$}$() const;\n" + "void ${1$_internal_set_$name$$}$($type$ value);\n" + "public:\n", + descriptor_); +} + +void EnumFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "inline $type$ $classname$::_internal_$name$() const {\n" + " return static_cast< $type$ >($name$_);\n" + "}\n" + "inline $type$ $classname$::$name$() const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return _internal_$name$();\n" + "}\n" + "inline void $classname$::_internal_set_$name$($type$ value) {\n"); + if (!HasPreservingUnknownEnumSemantics(descriptor_)) { + format(" assert($type$_IsValid(value));\n"); } - printer->Print(variables, - " $set_hasbit$\n" - " $name$_ = value;\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n"); + format( + " $set_hasbit$\n" + " $name$_ = value;\n" + "}\n" + "inline void $classname$::set_$name$($type$ value) {\n" + "$annotate_accessor$" + " _internal_set_$name$(value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + "}\n"); } -void EnumFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $default$;\n"); +void EnumFieldGenerator::GenerateClearingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_ = $default$;\n"); } -void EnumFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "set_$name$(from.$name$());\n"); +void EnumFieldGenerator::GenerateMergingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("_internal_set_$name$(from._internal_$name$());\n"); } -void EnumFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "swap($name$_, other->$name$_);\n"); +void EnumFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("swap($name$_, other->$name$_);\n"); } -void EnumFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $default$;\n"); +void EnumFieldGenerator::GenerateConstructorCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_ = $default$;\n"); } -void EnumFieldGenerator:: -GenerateCopyConstructorCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = from.$name$_;\n"); +void EnumFieldGenerator::GenerateCopyConstructorCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_ = from.$name$_;\n"); } -void EnumFieldGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "int value;\n" - "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" - " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n" - " input, &value)));\n"); - if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, - "set_$name$(static_cast< $type$ >(value));\n"); - } else { - printer->Print(variables_, - "if ($type$_IsValid(value)) {\n" - " set_$name$(static_cast< $type$ >(value));\n"); - if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(variables_, - "} else {\n" - " mutable_unknown_fields()->AddVarint(\n" - " $number$, static_cast< ::google::protobuf::uint64>(value));\n"); - } else { - printer->Print( - "} else {\n" - " unknown_fields_stream.WriteVarint32($tag$u);\n" - " unknown_fields_stream.WriteVarint32(\n" - " static_cast< ::google::protobuf::uint32>(value));\n", - "tag", SimpleItoa(internal::WireFormat::MakeTag(descriptor_))); - } - printer->Print(variables_, - "}\n"); - } -} - -void EnumFieldGenerator:: -GenerateSerializeWithCachedSizes(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::internal::WireFormatLite::WriteEnum(\n" - " $number$, this->$name$(), output);\n"); +void EnumFieldGenerator::GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "target = stream->EnsureSpace(target);\n" + "target = ::$proto_ns$::internal::WireFormatLite::WriteEnumToArray(\n" + " $number$, this->_internal_$name$(), target);\n"); } -void EnumFieldGenerator:: -GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n" - " $number$, this->$name$(), target);\n"); +void EnumFieldGenerator::GenerateByteSize(io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "total_size += $tag_size$ +\n" + " " + "::$proto_ns$::internal::WireFormatLite::EnumSize(this->_internal_$name$(" + "));\n"); } -void EnumFieldGenerator:: -GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, - "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormatLite::EnumSize(this->$name$());\n"); +void EnumFieldGenerator::GenerateConstinitInitializer( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_($default$)\n"); } // =================================================================== -EnumOneofFieldGenerator:: -EnumOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : EnumFieldGenerator(descriptor, options) { +EnumOneofFieldGenerator::EnumOneofFieldGenerator( + const FieldDescriptor* descriptor, const Options& options) + : EnumFieldGenerator(descriptor, options) { SetCommonOneofFieldVariables(descriptor, &variables_); } EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {} -void EnumOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const { - std::map variables(variables_); - variables["inline"] = is_inline ? "inline " : ""; - printer->Print(variables, - "$inline$$type$ $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " if (has_$name$()) {\n" - " return static_cast< $type$ >($oneof_prefix$$name$_);\n" - " }\n" - " return static_cast< $type$ >($default$);\n" - "}\n" - "$inline$void $classname$::set_$name$($type$ value) {\n"); - if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables, - " assert($type$_IsValid(value));\n"); +void EnumOneofFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "inline $type$ $classname$::_internal_$name$() const {\n" + " if (_internal_has_$name$()) {\n" + " return static_cast< $type$ >($field_member$);\n" + " }\n" + " return static_cast< $type$ >($default$);\n" + "}\n" + "inline $type$ $classname$::$name$() const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return _internal_$name$();\n" + "}\n" + "inline void $classname$::_internal_set_$name$($type$ value) {\n"); + if (!HasPreservingUnknownEnumSemantics(descriptor_)) { + format(" assert($type$_IsValid(value));\n"); } - printer->Print(variables, - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " }\n" - " $oneof_prefix$$name$_ = value;\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n"); + format( + " if (!_internal_has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " }\n" + " $field_member$ = value;\n" + "}\n" + "inline void $classname$::set_$name$($type$ value) {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + " _internal_set_$name$(value);\n" + "}\n"); } -void EnumOneofFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n"); +void EnumOneofFieldGenerator::GenerateClearingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("$field_member$ = $default$;\n"); } -void EnumOneofFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { +void EnumOneofFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { // Don't print any swapping code. Swapping the union will swap this field. } -void EnumOneofFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { - printer->Print( - variables_, - "_$classname$_default_instance_.$name$_ = $default$;\n"); +void EnumOneofFieldGenerator::GenerateConstructorCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n"); } // =================================================================== RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), descriptor_(descriptor) { + : FieldGenerator(descriptor, options) { SetEnumVariables(descriptor, &variables_, options); } RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} -void RepeatedEnumFieldGenerator:: -GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::RepeatedField $name$_;\n"); +void RepeatedEnumFieldGenerator::GeneratePrivateMembers( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("::$proto_ns$::RepeatedField $name$_;\n"); if (descriptor_->is_packed() && HasGeneratedMethods(descriptor_->file(), options_)) { - printer->Print(variables_, - "mutable int _$name$_cached_byte_size_;\n"); + format("mutable std::atomic _$name$_cached_byte_size_;\n"); } } -void RepeatedEnumFieldGenerator:: -GenerateAccessorDeclarations(io::Printer* printer) const { - printer->Print(variables_, - "$deprecated_attr$$type$ $name$(int index) const;\n"); - printer->Annotate("name", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$void ${$set_$name$$}$(int index, $type$ value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$add_$name$$}$($type$ value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$const ::google::protobuf::RepeatedField& $name$() const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$::google::protobuf::RepeatedField* " - "${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); -} - -void RepeatedEnumFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const { - std::map variables(variables_); - variables["inline"] = is_inline ? "inline " : ""; - printer->Print(variables, - "$inline$$type$ $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return static_cast< $type$ >($name$_.Get(index));\n" - "}\n" - "$inline$void $classname$::set_$name$(int index, $type$ value) {\n"); - if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables, - " assert($type$_IsValid(value));\n"); +void RepeatedEnumFieldGenerator::GenerateAccessorDeclarations( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "private:\n" + "$type$ ${1$_internal_$name$$}$(int index) const;\n" + "void ${1$_internal_add_$name$$}$($type$ value);\n" + "::$proto_ns$::RepeatedField* " + "${1$_internal_mutable_$name$$}$();\n" + "public:\n" + "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n" + "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n" + "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n" + "$deprecated_attr$const ::$proto_ns$::RepeatedField& " + "${1$$name$$}$() const;\n" + "$deprecated_attr$::$proto_ns$::RepeatedField* " + "${1$mutable_$name$$}$();\n", + descriptor_); +} + +void RepeatedEnumFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "inline $type$ $classname$::_internal_$name$(int index) const {\n" + " return static_cast< $type$ >($name$_.Get(index));\n" + "}\n" + "inline $type$ $classname$::$name$(int index) const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return _internal_$name$(index);\n" + "}\n" + "inline void $classname$::set_$name$(int index, $type$ value) {\n" + "$annotate_accessor$"); + if (!HasPreservingUnknownEnumSemantics(descriptor_)) { + format(" assert($type$_IsValid(value));\n"); } - printer->Print(variables, - " $name$_.Set(index, value);\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n" - "$inline$void $classname$::add_$name$($type$ value) {\n"); - if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables, - " assert($type$_IsValid(value));\n"); + format( + " $name$_.Set(index, value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + "}\n" + "inline void $classname$::_internal_add_$name$($type$ value) {\n"); + if (!HasPreservingUnknownEnumSemantics(descriptor_)) { + format(" assert($type$_IsValid(value));\n"); } - printer->Print(variables, - " $name$_.Add(value);\n" - " // @@protoc_insertion_point(field_add:$full_name$)\n" - "}\n" - "$inline$const ::google::protobuf::RepeatedField&\n" - "$classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_list:$full_name$)\n" - " return $name$_;\n" - "}\n" - "$inline$::google::protobuf::RepeatedField*\n" - "$classname$::mutable_$name$() {\n" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - " return &$name$_;\n" - "}\n"); + format( + " $name$_.Add(value);\n" + "}\n" + "inline void $classname$::add_$name$($type$ value) {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_add:$full_name$)\n" + " _internal_add_$name$(value);\n" + "}\n" + "inline const ::$proto_ns$::RepeatedField&\n" + "$classname$::$name$() const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_list:$full_name$)\n" + " return $name$_;\n" + "}\n" + "inline ::$proto_ns$::RepeatedField*\n" + "$classname$::_internal_mutable_$name$() {\n" + " return &$name$_;\n" + "}\n" + "inline ::$proto_ns$::RepeatedField*\n" + "$classname$::mutable_$name$() {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" + " return _internal_mutable_$name$();\n" + "}\n"); } -void RepeatedEnumFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Clear();\n"); +void RepeatedEnumFieldGenerator::GenerateClearingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.Clear();\n"); } -void RepeatedEnumFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); +void RepeatedEnumFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.MergeFrom(from.$name$_);\n"); } -void RepeatedEnumFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n"); +void RepeatedEnumFieldGenerator::GenerateSwappingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.InternalSwap(&other->$name$_);\n"); } -void RepeatedEnumFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { +void RepeatedEnumFieldGenerator::GenerateConstructorCode( + io::Printer* printer) const { // Not needed for repeated fields. } -void RepeatedEnumFieldGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) const { +void RepeatedEnumFieldGenerator::GenerateMergeFromCodedStream( + io::Printer* printer) const { + Formatter format(printer, variables_); // Don't use ReadRepeatedPrimitive here so that the enum can be validated. - printer->Print(variables_, - "int value;\n" - "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" - " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n" - " input, &value)));\n"); - if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, - "add_$name$(static_cast< $type$ >(value));\n"); + format( + "int value = 0;\n" + "DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n" + " int, ::$proto_ns$::internal::WireFormatLite::TYPE_ENUM>(\n" + " input, &value)));\n"); + if (HasPreservingUnknownEnumSemantics(descriptor_)) { + format("add_$name$(static_cast< $type$ >(value));\n"); } else { - printer->Print(variables_, - "if ($type$_IsValid(value)) {\n" - " add_$name$(static_cast< $type$ >(value));\n"); + format( + "if ($type$_IsValid(value)) {\n" + " add_$name$(static_cast< $type$ >(value));\n"); if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(variables_, - "} else {\n" - " mutable_unknown_fields()->AddVarint(\n" - " $number$, static_cast< ::google::protobuf::uint64>(value));\n"); + format( + "} else {\n" + " mutable_unknown_fields()->AddVarint(\n" + " $number$, static_cast<$uint64$>(value));\n"); } else { - printer->Print( - "} else {\n" - " unknown_fields_stream.WriteVarint32(tag);\n" - " unknown_fields_stream.WriteVarint32(\n" - " static_cast< ::google::protobuf::uint32>(value));\n"); + format( + "} else {\n" + " unknown_fields_stream.WriteVarint32(tag);\n" + " unknown_fields_stream.WriteVarint32(\n" + " static_cast<$uint32$>(value));\n"); } - printer->Print("}\n"); + format("}\n"); } } -void RepeatedEnumFieldGenerator:: -GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { +void RepeatedEnumFieldGenerator::GenerateMergeFromCodedStreamWithPacking( + io::Printer* printer) const { + Formatter format(printer, variables_); if (!descriptor_->is_packed()) { - // This path is rarely executed, so we use a non-inlined implementation. - if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, - "DO_((::google::protobuf::internal::" - "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n" - " input,\n" - " $number$,\n" - " NULL,\n" - " NULL,\n" - " this->mutable_$name$())));\n"); + // This path is rarely executed, so we use a non-inlined implementation. + if (HasPreservingUnknownEnumSemantics(descriptor_)) { + format( + "DO_((::$proto_ns$::internal::" + "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n" + " input,\n" + " $number$,\n" + " nullptr,\n" + " nullptr,\n" + " this->_internal_mutable_$name$())));\n"); } else if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(variables_, - "DO_((::google::protobuf::internal::WireFormat::ReadPackedEnumPreserveUnknowns(\n" - " input,\n" - " $number$,\n" - " $type$_IsValid,\n" - " mutable_unknown_fields(),\n" - " this->mutable_$name$())));\n"); + format( + "DO_((::$proto_ns$::internal::WireFormat::" + "ReadPackedEnumPreserveUnknowns(\n" + " input,\n" + " $number$,\n" + " $type$_IsValid,\n" + " mutable_unknown_fields(),\n" + " this->_internal_mutable_$name$())));\n"); } else { - printer->Print(variables_, - "DO_((::google::protobuf::internal::" - "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n" - " input,\n" - " $number$,\n" - " $type$_IsValid,\n" - " &unknown_fields_stream,\n" - " this->mutable_$name$())));\n"); + format( + "DO_((::$proto_ns$::internal::" + "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n" + " input,\n" + " $number$,\n" + " $type$_IsValid,\n" + " &unknown_fields_stream,\n" + " this->_internal_mutable_$name$())));\n"); } } else { - printer->Print(variables_, - "::google::protobuf::uint32 length;\n" - "DO_(input->ReadVarint32(&length));\n" - "::google::protobuf::io::CodedInputStream::Limit limit = " - "input->PushLimit(static_cast(length));\n" - "while (input->BytesUntilLimit() > 0) {\n" - " int value;\n" - " DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" - " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n" - " input, &value)));\n"); - if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, - " add_$name$(static_cast< $type$ >(value));\n"); + format( + "$uint32$ length;\n" + "DO_(input->ReadVarint32(&length));\n" + "::$proto_ns$::io::CodedInputStream::Limit limit = " + "input->PushLimit(static_cast(length));\n" + "while (input->BytesUntilLimit() > 0) {\n" + " int value = 0;\n" + " DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n" + " int, ::$proto_ns$::internal::WireFormatLite::TYPE_ENUM>(\n" + " input, &value)));\n"); + if (HasPreservingUnknownEnumSemantics(descriptor_)) { + format(" add_$name$(static_cast< $type$ >(value));\n"); } else { - printer->Print(variables_, - " if ($type$_IsValid(value)) {\n" - " add_$name$(static_cast< $type$ >(value));\n" - " } else {\n"); + format( + " if ($type$_IsValid(value)) {\n" + " _internal_add_$name$(static_cast< $type$ >(value));\n" + " } else {\n"); if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(variables_, - " mutable_unknown_fields()->AddVarint(\n" - " $number$, static_cast< ::google::protobuf::uint64>(value));\n"); + format( + " mutable_unknown_fields()->AddVarint(\n" + " $number$, static_cast<$uint64$>(value));\n"); } else { - printer->Print(variables_, - " unknown_fields_stream.WriteVarint32(tag);\n" - " unknown_fields_stream.WriteVarint32(\n" - " static_cast< ::google::protobuf::uint32>(value));\n"); + format( + " unknown_fields_stream.WriteVarint32(tag);\n" + " unknown_fields_stream.WriteVarint32(\n" + " static_cast<$uint32$>(value));\n"); } - printer->Print( - " }\n"); + format(" }\n"); } - printer->Print(variables_, - "}\n" - "input->PopLimit(limit);\n"); + format( + "}\n" + "input->PopLimit(limit);\n"); } } -void RepeatedEnumFieldGenerator:: -GenerateSerializeWithCachedSizes(io::Printer* printer) const { +void RepeatedEnumFieldGenerator::GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const { + Formatter format(printer, variables_); if (descriptor_->is_packed()) { // Write the tag and the size. - printer->Print(variables_, - "if (this->$name$_size() > 0) {\n" - " ::google::protobuf::internal::WireFormatLite::WriteTag(\n" - " $number$,\n" - " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" - " output);\n" - " output->WriteVarint32(\n" - " static_cast< ::google::protobuf::uint32>(_$name$_cached_byte_size_));\n" - "}\n"); - } - printer->Print(variables_, - "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n"); - if (descriptor_->is_packed()) { - printer->Print(variables_, - " ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n" - " this->$name$(i), output);\n"); + format( + "{\n" + " int byte_size = " + "_$name$_cached_byte_size_.load(std::memory_order_relaxed);\n" + " if (byte_size > 0) {\n" + " target = stream->WriteEnumPacked(\n" + " $number$, $name$_, byte_size, target);\n" + " }\n" + "}\n"); } else { - printer->Print(variables_, - " ::google::protobuf::internal::WireFormatLite::WriteEnum(\n" - " $number$, this->$name$(i), output);\n"); + format( + "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n" + " target = stream->EnsureSpace(target);\n" + " target = ::$proto_ns$::internal::WireFormatLite::WriteEnumToArray(\n" + " $number$, this->_internal_$name$(i), target);\n" + "}\n"); } - printer->Print("}\n"); } -void RepeatedEnumFieldGenerator:: -GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - if (descriptor_->is_packed()) { - // Write the tag and the size. - printer->Print(variables_, - "if (this->$name$_size() > 0) {\n" - " target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n" - " $number$,\n" - " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" - " target);\n" - " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(" - " static_cast< ::google::protobuf::uint32>(\n" - " _$name$_cached_byte_size_), target);\n" - " target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n" - " this->$name$_, target);\n" - "}\n"); - } else { - printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n" - " $number$, this->$name$_, target);\n"); - } -} - -void RepeatedEnumFieldGenerator:: -GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, - "{\n" - " size_t data_size = 0;\n" - " unsigned int count = static_cast(this->$name$_size());"); - printer->Indent(); - printer->Print(variables_, +void RepeatedEnumFieldGenerator::GenerateByteSize(io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "{\n" + " size_t data_size = 0;\n" + " unsigned int count = static_cast(this->_internal_$name$_size());"); + format.Indent(); + format( "for (unsigned int i = 0; i < count; i++) {\n" - " data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n" - " this->$name$(static_cast(i)));\n" + " data_size += ::$proto_ns$::internal::WireFormatLite::EnumSize(\n" + " this->_internal_$name$(static_cast(i)));\n" "}\n"); if (descriptor_->is_packed()) { - printer->Print(variables_, - "if (data_size > 0) {\n" - " total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormatLite::Int32Size(\n" - " static_cast< ::google::protobuf::int32>(data_size));\n" - "}\n" - "int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n" - "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" - "_$name$_cached_byte_size_ = cached_size;\n" - "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" - "total_size += data_size;\n"); + format( + "if (data_size > 0) {\n" + " total_size += $tag_size$ +\n" + " ::$proto_ns$::internal::WireFormatLite::Int32Size(\n" + " static_cast<$int32$>(data_size));\n" + "}\n" + "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n" + "_$name$_cached_byte_size_.store(cached_size,\n" + " std::memory_order_relaxed);\n" + "total_size += data_size;\n"); } else { - printer->Print(variables_, - "total_size += ($tag_size$UL * count) + data_size;\n"); + format("total_size += ($tag_size$UL * count) + data_size;\n"); + } + format.Outdent(); + format("}\n"); +} + +void RepeatedEnumFieldGenerator::GenerateConstinitInitializer( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_()"); + if (descriptor_->is_packed() && + HasGeneratedMethods(descriptor_->file(), options_)) { + format("\n, _$name$_cached_byte_size_()"); } - printer->Outdent(); - printer->Print("}\n"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h index 3ecd7ba871155..3fa64a864059a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h @@ -52,21 +52,15 @@ class EnumFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; void GenerateCopyConstructorCode(io::Printer* printer) const; - void GenerateMergeFromCodedStream(io::Printer* printer) const; - void GenerateSerializeWithCachedSizes(io::Printer* printer) const; void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - - protected: - const FieldDescriptor* descriptor_; - std::map variables_; + void GenerateConstinitInitializer(io::Printer* printer) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); @@ -79,8 +73,7 @@ class EnumOneofFieldGenerator : public EnumFieldGenerator { ~EnumOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; @@ -98,8 +91,7 @@ class RepeatedEnumFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; @@ -107,20 +99,17 @@ class RepeatedEnumFieldGenerator : public FieldGenerator { void GenerateCopyConstructorCode(io::Printer* printer) const {} void GenerateMergeFromCodedStream(io::Printer* printer) const; void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const; - void GenerateSerializeWithCachedSizes(io::Printer* printer) const; void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; + void GenerateConstinitInitializer(io::Printer* printer) const; private: - const FieldDescriptor* descriptor_; - std::map variables_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); }; } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc index 6b1673b25946d..3792db81a80e0 100644 --- a/src/google/protobuf/compiler/cpp/cpp_extension.cc +++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc @@ -35,11 +35,10 @@ #include #include #include -#include #include +#include #include - namespace google { namespace protobuf { namespace compiler { @@ -50,7 +49,7 @@ namespace { // Returns the fully-qualified class name of the message that this field // extends. This function is used in the Google-internal code to handle some // legacy cases. -string ExtendeeClassName(const FieldDescriptor* descriptor) { +std::string ExtendeeClassName(const FieldDescriptor* descriptor) { const Descriptor* extendee = descriptor->containing_type(); return ClassName(extendee, true); } @@ -59,8 +58,7 @@ string ExtendeeClassName(const FieldDescriptor* descriptor) { ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor, const Options& options) - : descriptor_(descriptor), - options_(options) { + : descriptor_(descriptor), options_(options) { // Construct type_traits_. if (descriptor_->is_repeated()) { type_traits_ = "Repeated"; @@ -84,127 +82,103 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor, break; default: type_traits_.append("PrimitiveTypeTraits< "); - type_traits_.append(PrimitiveTypeName(descriptor_->cpp_type())); + type_traits_.append(PrimitiveTypeName(options_, descriptor_->cpp_type())); type_traits_.append(" >"); break; } + SetCommonVars(options, &variables_); + variables_["extendee"] = ExtendeeClassName(descriptor_); + variables_["type_traits"] = type_traits_; + std::string name = descriptor_->name(); + variables_["name"] = ResolveKeyword(name); + variables_["constant_name"] = FieldConstantName(descriptor_); + variables_["field_type"] = + StrCat(static_cast(descriptor_->type())); + variables_["packed"] = descriptor_->is_packed() ? "true" : "false"; + + std::string scope = + IsScoped() ? ClassName(descriptor_->extension_scope(), false) + "::" : ""; + variables_["scope"] = scope; + variables_["scoped_name"] = ExtensionName(descriptor_); + variables_["number"] = StrCat(descriptor_->number()); } ExtensionGenerator::~ExtensionGenerator() {} -void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) { - std::map vars; - vars["extendee" ] = ExtendeeClassName(descriptor_); - vars["number" ] = SimpleItoa(descriptor_->number()); - vars["type_traits" ] = type_traits_; - vars["name" ] = descriptor_->name(); - vars["field_type" ] = SimpleItoa(static_cast(descriptor_->type())); - vars["packed" ] = descriptor_->options().packed() ? "true" : "false"; - vars["constant_name"] = FieldConstantName(descriptor_); +bool ExtensionGenerator::IsScoped() const { + return descriptor_->extension_scope() != nullptr; +} + +void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) const { + Formatter format(printer, variables_); // If this is a class member, it needs to be declared "static". Otherwise, // it needs to be "extern". In the latter case, it also needs the DLL // export/import specifier. - if (descriptor_->extension_scope() == NULL) { - vars["qualifier"] = "extern"; + std::string qualifier; + if (!IsScoped()) { + qualifier = "extern"; if (!options_.dllexport_decl.empty()) { - vars["qualifier"] = options_.dllexport_decl + " " + vars["qualifier"]; + qualifier = options_.dllexport_decl + " " + qualifier; } } else { - vars["qualifier"] = "static"; + qualifier = "static"; } - printer->Print(vars, - "static const int $constant_name$ = $number$;\n" - "$qualifier$ ::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n" - " ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n" - " $name$;\n" - ); - + format( + "static const int $constant_name$ = $number$;\n" + "$1$ ::$proto_ns$::internal::ExtensionIdentifier< $extendee$,\n" + " ::$proto_ns$::internal::$type_traits$, $field_type$, $packed$ >\n" + " ${2$$name$$}$;\n", + qualifier, descriptor_); } void ExtensionGenerator::GenerateDefinition(io::Printer* printer) { - // If this is a class member, it needs to be declared in its class scope. - string scope = (descriptor_->extension_scope() == NULL) ? "" : - ClassName(descriptor_->extension_scope(), false) + "::"; - string name = scope + descriptor_->name(); - - std::map vars; - vars["extendee" ] = ExtendeeClassName(descriptor_); - vars["type_traits" ] = type_traits_; - vars["name" ] = name; - vars["constant_name"] = FieldConstantName(descriptor_); - vars["default" ] = DefaultValue(descriptor_); - vars["field_type" ] = SimpleItoa(static_cast(descriptor_->type())); - vars["packed" ] = descriptor_->options().packed() ? "true" : "false"; - vars["scope" ] = scope; + // If we are building for lite with implicit weak fields, we want to skip over + // any custom options (i.e. extensions of messages from descriptor.proto). + // This prevents the creation of any unnecessary linker references to the + // descriptor messages. + if (options_.lite_implicit_weak_fields && + descriptor_->containing_type()->file()->name() == + "net/proto2/proto/descriptor.proto") { + return; + } + Formatter format(printer, variables_); + std::string default_str; + // If this is a class member, it needs to be declared in its class scope. if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { // We need to declare a global string which will contain the default value. // We cannot declare it at class scope because that would require exposing // it in the header which would be annoying for other reasons. So we // replace :: with _ in the name and declare it as a global. - string global_name = StringReplace(name, "::", "_", true); - vars["global_name"] = global_name; - printer->Print(vars, - "const ::std::string $global_name$_default($default$);\n"); - - // Update the default to refer to the string global. - vars["default"] = global_name + "_default"; + default_str = + StringReplace(variables_["scoped_name"], "::", "_", true) + "_default"; + format("const std::string $1$($2$);\n", default_str, + DefaultValue(options_, descriptor_)); + } else if (descriptor_->message_type()) { + // We have to initialize the default instance for extensions at registration + // time. + default_str = + FieldMessageTypeName(descriptor_, options_) + "::default_instance()"; + } else { + default_str = DefaultValue(options_, descriptor_); } // Likewise, class members need to declare the field constant variable. - if (descriptor_->extension_scope() != NULL) { - printer->Print(vars, - "#if !defined(_MSC_VER) || _MSC_VER >= 1900\n" - "const int $scope$$constant_name$;\n" - "#endif\n"); + if (IsScoped()) { + format( + "#if !defined(_MSC_VER) || _MSC_VER >= 1900\n" + "const int $scope$$constant_name$;\n" + "#endif\n"); } - printer->Print(vars, - "::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n" - " ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n" - " $name$($constant_name$, $default$);\n"); -} - -void ExtensionGenerator::GenerateRegistration(io::Printer* printer) { - std::map vars; - vars["extendee" ] = ExtendeeClassName(descriptor_); - vars["number" ] = SimpleItoa(descriptor_->number()); - vars["field_type" ] = SimpleItoa(static_cast(descriptor_->type())); - vars["is_repeated"] = descriptor_->is_repeated() ? "true" : "false"; - vars["is_packed" ] = (descriptor_->is_repeated() && - descriptor_->options().packed()) - ? "true" : "false"; - - switch (descriptor_->cpp_type()) { - case FieldDescriptor::CPPTYPE_ENUM: - printer->Print( - vars, - "::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n" - " $extendee$::internal_default_instance(),\n" - " $number$, $field_type$, $is_repeated$, $is_packed$,\n"); - printer->Print( - " &$type$_IsValid);\n", - "type", ClassName(descriptor_->enum_type(), true)); - break; - case FieldDescriptor::CPPTYPE_MESSAGE: - printer->Print( - vars, - "::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n" - " $extendee$::internal_default_instance(),\n" - " $number$, $field_type$, $is_repeated$, $is_packed$,\n"); - printer->Print(" $type$::internal_default_instance());\n", "type", - ClassName(descriptor_->message_type(), true)); - break; - default: - printer->Print( - vars, - "::google::protobuf::internal::ExtensionSet::RegisterExtension(\n" - " $extendee$::internal_default_instance(),\n" - " $number$, $field_type$, $is_repeated$, $is_packed$);\n"); - break; - } + format( + "PROTOBUF_ATTRIBUTE_INIT_PRIORITY " + "::$proto_ns$::internal::ExtensionIdentifier< $extendee$,\n" + " ::$proto_ns$::internal::$type_traits$, $field_type$, $packed$ >\n" + " $scoped_name$($constant_name$, $1$);\n", + default_str); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.h b/src/google/protobuf/compiler/cpp/cpp_extension.h index 1c1caf1f90082..72413f6b28f71 100644 --- a/src/google/protobuf/compiler/cpp/cpp_extension.h +++ b/src/google/protobuf/compiler/cpp/cpp_extension.h @@ -35,18 +35,22 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__ +#include #include + #include #include namespace google { namespace protobuf { - class FieldDescriptor; // descriptor.h - namespace io { - class Printer; // printer.h - } +class FieldDescriptor; // descriptor.h +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace cpp { @@ -62,25 +66,26 @@ class ExtensionGenerator { ~ExtensionGenerator(); // Header stuff. - void GenerateDeclaration(io::Printer* printer); + void GenerateDeclaration(io::Printer* printer) const; // Source file stuff. void GenerateDefinition(io::Printer* printer); - // Generate code to register the extension. - void GenerateRegistration(io::Printer* printer); + bool IsScoped() const; private: const FieldDescriptor* descriptor_; - string type_traits_; + std::string type_traits_; Options options_; + std::map variables_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); }; } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc index dce9617c598b6..f95e14e58bdb2 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_field.cc @@ -34,21 +34,18 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include #include +#include +#include #include #include #include #include -#include #include -#include -#include +#include #include namespace google { @@ -59,42 +56,30 @@ namespace cpp { using internal::WireFormat; void SetCommonFieldVariables(const FieldDescriptor* descriptor, - std::map* variables, + std::map* variables, const Options& options) { + SetCommonVars(options, variables); + (*variables)["ns"] = Namespace(descriptor, options); (*variables)["name"] = FieldName(descriptor); - (*variables)["index"] = SimpleItoa(descriptor->index()); - (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["index"] = StrCat(descriptor->index()); + (*variables)["number"] = StrCat(descriptor->number()); (*variables)["classname"] = ClassName(FieldScope(descriptor), false); (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type()); + (*variables)["field_member"] = FieldName(descriptor) + "_"; - // non_null_ptr_to_name is usable only if has_$name$ is true. It yields a - // pointer that will not be NULL. Subclasses of FieldGenerator may set - // (*variables)["non_null_ptr_to_name"] differently. - (*variables)["non_null_ptr_to_name"] = - StrCat("&this->", FieldName(descriptor), "()"); - - (*variables)["tag_size"] = SimpleItoa( - WireFormat::TagSize(descriptor->number(), descriptor->type())); - (*variables)["deprecation"] = descriptor->options().deprecated() - ? " PROTOBUF_DEPRECATED" : ""; - (*variables)["deprecated_attr"] = descriptor->options().deprecated() - ? "GOOGLE_PROTOBUF_DEPRECATED_ATTR " : ""; - - (*variables)["cppget"] = "Get"; - - if (HasFieldPresence(descriptor->file())) { - (*variables)["set_hasbit"] = - "set_has_" + FieldName(descriptor) + "();"; - (*variables)["clear_hasbit"] = - "clear_has_" + FieldName(descriptor) + "();"; + (*variables)["tag_size"] = StrCat( + WireFormat::TagSize(descriptor->number(), descriptor->type())); + (*variables)["deprecated_attr"] = DeprecatedAttribute(options, descriptor); + + (*variables)["set_hasbit"] = ""; + (*variables)["clear_hasbit"] = ""; + if (HasHasbit(descriptor)) { + (*variables)["set_hasbit_io"] = + "_Internal::set_has_" + FieldName(descriptor) + "(&_has_bits_);"; } else { - (*variables)["set_hasbit"] = ""; - (*variables)["clear_hasbit"] = ""; + (*variables)["set_hasbit_io"] = ""; } - - // By default, empty string, so that generic code used for both oneofs and - // singular fields can be written. - (*variables)["oneof_prefix"] = ""; + (*variables)["annotate_accessor"] = ""; // These variables are placeholders to pick out the beginning and ends of // identifiers for annotations (when doing so with existing variables would @@ -104,72 +89,79 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*variables)["}"] = ""; } -void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor, - std::map* variables) { - const string prefix = descriptor->containing_oneof()->name() + "_."; - (*variables)["oneof_prefix"] = prefix; +void FieldGenerator::SetHasBitIndex(int32 has_bit_index) { + if (!HasHasbit(descriptor_)) { + GOOGLE_CHECK_EQ(has_bit_index, -1); + return; + } + variables_["set_hasbit"] = StrCat( + "_has_bits_[", has_bit_index / 32, "] |= 0x", + strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;"); + variables_["clear_hasbit"] = StrCat( + "_has_bits_[", has_bit_index / 32, "] &= ~0x", + strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;"); +} + +void SetCommonOneofFieldVariables( + const FieldDescriptor* descriptor, + std::map* variables) { + const std::string prefix = descriptor->containing_oneof()->name() + "_."; (*variables)["oneof_name"] = descriptor->containing_oneof()->name(); - (*variables)["non_null_ptr_to_name"] = + (*variables)["field_member"] = StrCat(prefix, (*variables)["name"], "_"); } FieldGenerator::~FieldGenerator() {} -void FieldGenerator:: -GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { - // Reaching here indicates a bug. Cases are: - // - This FieldGenerator should support packing, but this method should be - // overridden. - // - This FieldGenerator doesn't support packing, and this method should - // never have been called. - GOOGLE_LOG(FATAL) << "GenerateMergeFromCodedStreamWithPacking() " - << "called on field generator that does not support packing."; - -} - FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, - const Options& options) - : descriptor_(descriptor), - options_(options), - field_generators_( - new google::protobuf::scoped_ptr[descriptor->field_count()]) { + const Options& options, + MessageSCCAnalyzer* scc_analyzer) + : descriptor_(descriptor), field_generators_(descriptor->field_count()) { // Construct all the FieldGenerators. for (int i = 0; i < descriptor->field_count(); i++) { - field_generators_[i].reset(MakeGenerator(descriptor->field(i), options)); + field_generators_[i].reset( + MakeGenerator(descriptor->field(i), options, scc_analyzer)); } } -FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, - const Options& options) { +FieldGenerator* FieldGeneratorMap::MakeGoogleInternalGenerator( + const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer) { + + return nullptr; +} + +FieldGenerator* FieldGeneratorMap::MakeGenerator( + const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer) { + FieldGenerator* generator = + MakeGoogleInternalGenerator(field, options, scc_analyzer); + if (generator) { + return generator; + } + if (field->is_repeated()) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: if (field->is_map()) { return new MapFieldGenerator(field, options); } else { - return new RepeatedMessageFieldGenerator(field, options); + return new RepeatedMessageFieldGenerator(field, options, + scc_analyzer); } case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // RepeatedStringFieldGenerator handles unknown ctypes. - case FieldOptions::STRING: - return new RepeatedStringFieldGenerator(field, options); - } + return new RepeatedStringFieldGenerator(field, options); case FieldDescriptor::CPPTYPE_ENUM: return new RepeatedEnumFieldGenerator(field, options); default: return new RepeatedPrimitiveFieldGenerator(field, options); } - } else if (field->containing_oneof()) { + } else if (field->real_containing_oneof()) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: - return new MessageOneofFieldGenerator(field, options); + return new MessageOneofFieldGenerator(field, options, scc_analyzer); case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // StringOneofFieldGenerator handles unknown ctypes. - case FieldOptions::STRING: - return new StringOneofFieldGenerator(field, options); - } + return new StringOneofFieldGenerator(field, options); case FieldDescriptor::CPPTYPE_ENUM: return new EnumOneofFieldGenerator(field, options); default: @@ -178,13 +170,9 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, } else { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: - return new MessageFieldGenerator(field, options); + return new MessageFieldGenerator(field, options, scc_analyzer); case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // StringFieldGenerator handles unknown ctypes. - case FieldOptions::STRING: - return new StringFieldGenerator(field, options); - } + return new StringFieldGenerator(field, options); case FieldDescriptor::CPPTYPE_ENUM: return new EnumFieldGenerator(field, options); default: diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h index d9dd38505d0b8..5a7763940734e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_field.h @@ -37,21 +37,21 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include -#include +#include #include +#include namespace google { namespace protobuf { - namespace io { - class Printer; // printer.h - } +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace cpp { @@ -61,17 +61,21 @@ namespace cpp { // ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size', // 'deprecation']. void SetCommonFieldVariables(const FieldDescriptor* descriptor, - std::map* variables, + std::map* variables, const Options& options); -void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor, - std::map* variables); +void SetCommonOneofFieldVariables( + const FieldDescriptor* descriptor, + std::map* variables); class FieldGenerator { public: - explicit FieldGenerator(const Options& options) : options_(options) {} + explicit FieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : descriptor_(descriptor), options_(options) {} virtual ~FieldGenerator(); - + virtual void GenerateSerializeWithCachedSizes( + io::Printer* printer) const final{}; // Generate lines of code declaring members fields of the message class // needed to represent this field. These are placed inside the message // class. @@ -82,58 +86,42 @@ class FieldGenerator { // implementation is empty. virtual void GenerateStaticMembers(io::Printer* /*printer*/) const {} - // Generate prototypes for accessors that will manipulate imported - // messages inline. These are for .proto.h headers. - // - // In .proto.h mode, the headers of imports are not #included. However, - // functions that manipulate the imported message types need access to - // the class definition of the imported message, meaning that the headers - // must be #included. To get around this, functions that manipulate - // imported message objects are defined as dependent functions in a base - // template class. By making them dependent template functions, the - // function templates will not be instantiated until they are called, so - // we can defer to those translation units to #include the necessary - // generated headers. - // - // See: - // http://en.cppreference.com/w/cpp/language/class_template#Implicit_instantiation - // - // Most field types don't need this, so the default implementation is empty. - virtual void GenerateDependentAccessorDeclarations( - io::Printer* printer) const {} - // Generate prototypes for all of the accessor functions related to this // field. These are placed inside the class definition. virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0; - // Generate inline definitions of depenent accessor functions for this field. - // These are placed inside the header after all class definitions. - virtual void GenerateDependentInlineAccessorDefinitions( - io::Printer* printer) const {} - // Generate inline definitions of accessor functions for this field. // These are placed inside the header after all class definitions. - // In non-.proto.h mode, this generates dependent accessor functions as well. virtual void GenerateInlineAccessorDefinitions( - io::Printer* printer, bool is_inline) const = 0; + io::Printer* printer) const = 0; // Generate definitions of accessors that aren't inlined. These are // placed somewhere in the .cc file. // Most field types don't need this, so the default implementation is empty. virtual void GenerateNonInlineAccessorDefinitions( - io::Printer* /*printer*/) const {} + io::Printer* /*printer*/) const {} + + // Generate declarations of accessors that are for internal purposes only. + // Most field types don't need this, so the default implementation is empty. + virtual void GenerateInternalAccessorDefinitions( + io::Printer* /*printer*/) const {} + + // Generate definitions of accessors that are for internal purposes only. + // Most field types don't need this, so the default implementation is empty. + virtual void GenerateInternalAccessorDeclarations( + io::Printer* /*printer*/) const {} // Generate lines of code (statements, not declarations) which clear the // field. This is used to define the clear_$name$() method virtual void GenerateClearingCode(io::Printer* printer) const = 0; - // Generate lines of code (statements, not declarations) which clear the field - // as part of the Clear() method for the whole message. For message types - // which have field presence bits, MessageGenerator::GenerateClear will have - // already checked the presence bits. + // Generate lines of code (statements, not declarations) which clear the + // field as part of the Clear() method for the whole message. For message + // types which have field presence bits, MessageGenerator::GenerateClear + // will have already checked the presence bits. // - // Since most field types can re-use GenerateClearingCode, this method is not - // pure virtual. + // Since most field types can re-use GenerateClearingCode, this method is + // not pure virtual. virtual void GenerateMessageClearingCode(io::Printer* printer) const { GenerateClearingCode(printer); } @@ -168,30 +156,19 @@ class FieldGenerator { // Generate a manual destructor invocation for use when the message is on an // arena. The code that this method generates will be executed inside a - // shared-for-the-whole-message-class method registered with OwnDestructor(). - // The method should return |true| if it generated any code that requires a - // call; this allows the message generator to eliminate the OwnDestructor() - // registration if no fields require it. + // shared-for-the-whole-message-class method registered with + // OwnDestructor(). The method should return |true| if it generated any code + // that requires a call; this allows the message generator to eliminate the + // OwnDestructor() registration if no fields require it. virtual bool GenerateArenaDestructorCode(io::Printer* printer) const { return false; } - // Generate code that allocates the fields's default instance. - virtual void GenerateDefaultInstanceAllocator(io::Printer* /*printer*/) - const {} - - // Generate lines to decode this field, which will be placed inside the - // message's MergeFromCodedStream() method. - virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0; - - // Generate lines to decode this field from a packed value, which will be - // placed inside the message's MergeFromCodedStream() method. - virtual void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) - const; - - // Generate lines to serialize this field, which are placed within the - // message's SerializeWithCachedSizes() method. - virtual void GenerateSerializeWithCachedSizes(io::Printer* printer) const = 0; + // Generate initialization code for private members declared by + // GeneratePrivateMembers(), specifically for the constexpr constructor. + // These go into the constructor's initializer list and must follow that + // syntax (eg `field_(args)`). Does not include `:` or `,` separators. + virtual void GenerateConstinitInitializer(io::Printer* printer) const {} // Generate lines to serialize this field directly to the array "target", // which are placed within the message's SerializeWithCachedSizesToArray() @@ -203,8 +180,12 @@ class FieldGenerator { // are placed in the message's ByteSize() method. virtual void GenerateByteSize(io::Printer* printer) const = 0; + void SetHasBitIndex(int32 has_bit_index); + protected: + const FieldDescriptor* descriptor_; const Options& options_; + std::map variables_; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); @@ -213,18 +194,28 @@ class FieldGenerator { // Convenience class which constructs FieldGenerators for a Descriptor. class FieldGeneratorMap { public: - FieldGeneratorMap(const Descriptor* descriptor, const Options& options); + FieldGeneratorMap(const Descriptor* descriptor, const Options& options, + MessageSCCAnalyzer* scc_analyzer); ~FieldGeneratorMap(); const FieldGenerator& get(const FieldDescriptor* field) const; + void SetHasBitIndices(const std::vector& has_bit_indices_) { + for (int i = 0; i < descriptor_->field_count(); ++i) { + field_generators_[i]->SetHasBitIndex(has_bit_indices_[i]); + } + } + private: const Descriptor* descriptor_; - const Options& options_; - google::protobuf::scoped_array > field_generators_; + std::vector> field_generators_; + static FieldGenerator* MakeGoogleInternalGenerator( + const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer); static FieldGenerator* MakeGenerator(const FieldDescriptor* field, - const Options& options); + const Options& options, + MessageSCCAnalyzer* scc_analyzer); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); }; @@ -232,6 +223,6 @@ class FieldGeneratorMap { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index a066a6a7c7378..70941d8b9bee4 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -33,595 +33,939 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include + +#include #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include +#include +#include #include #include -#include #include +#include #include #include -#include -#include +#include +#include #include +#include #include +// Must be last. +#include + namespace google { namespace protobuf { namespace compiler { namespace cpp { + namespace { -// The list of names that are defined as macros on some platforms. We need to -// #undef them for the generated code to compile. -const char* kMacroNames[] = {"major", "minor"}; -bool IsMacroName(const string& name) { - // Just do a linear search as the number of elements is very small. - for (int i = 0; i < GOOGLE_ARRAYSIZE(kMacroNames); ++i) { - if (name == kMacroNames[i]) return true; - } - return false; +// When we forward-declare things, we want to create a sorted order so our +// output is deterministic and minimizes namespace changes. +template +std::string GetSortKey(const T& val) { + return val.full_name(); } -void CollectMacroNames(const Descriptor* message, std::vector* names) { - for (int i = 0; i < message->field_count(); ++i) { - const FieldDescriptor* field = message->field(i); - if (IsMacroName(field->name())) { - names->push_back(field->name()); - } - } - for (int i = 0; i < message->nested_type_count(); ++i) { - CollectMacroNames(message->nested_type(i), names); - } +template <> +std::string GetSortKey(const FileDescriptor& val) { + return val.name(); } -void CollectMacroNames(const FileDescriptor* file, std::vector* names) { - // Only do this for protobuf's own types. There are some google3 protos using - // macros as field names and the generated code compiles after the macro - // expansion. Undefing these macros actually breaks such code. - if (file->name() != "google/protobuf/compiler/plugin.proto") { - return; - } - for (int i = 0; i < file->message_type_count(); ++i) { - CollectMacroNames(file->message_type(i), names); - } +template +bool CompareSortKeys(const T* a, const T* b) { + return GetSortKey(*a) < GetSortKey(*b); } +template +std::vector Sorted(const std::unordered_set& vals) { + std::vector sorted(vals.begin(), vals.end()); + std::sort(sorted.begin(), sorted.end(), CompareSortKeys); + return sorted; +} } // namespace -// =================================================================== - FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) - : file_(file), - options_(options), - scc_analyzer_(options), - message_generators_owner_( - new google::protobuf::scoped_ptr[file->message_type_count()]), - enum_generators_owner_( - new google::protobuf::scoped_ptr[file->enum_type_count()]), - service_generators_owner_( - new google::protobuf::scoped_ptr[file->service_count()]), - extension_generators_owner_( - new google::protobuf::scoped_ptr[file->extension_count()]) { - - for (int i = 0; i < file->message_type_count(); i++) { - message_generators_owner_[i].reset( - new MessageGenerator(file->message_type(i), options, &scc_analyzer_)); - message_generators_owner_[i]->Flatten(&message_generators_); - } - - for (int i = 0; i < message_generators_.size(); i++) { - message_generators_[i]->AddGenerators(&enum_generators_, - &extension_generators_); + : file_(file), options_(options), scc_analyzer_(options) { + // These variables are the same on a file level + SetCommonVars(options, &variables_); + variables_["dllexport_decl"] = options.dllexport_decl; + variables_["tablename"] = UniqueName("TableStruct", file_, options_); + variables_["file_level_metadata"] = + UniqueName("file_level_metadata", file_, options_); + variables_["desc_table"] = DescriptorTableName(file_, options_); + variables_["file_level_enum_descriptors"] = + UniqueName("file_level_enum_descriptors", file_, options_); + variables_["file_level_service_descriptors"] = + UniqueName("file_level_service_descriptors", file_, options_); + variables_["filename"] = file_->name(); + variables_["package_ns"] = Namespace(file_, options); + + std::vector msgs = FlattenMessagesInFile(file); + for (int i = 0; i < msgs.size(); i++) { + // Deleted in destructor + MessageGenerator* msg_gen = + new MessageGenerator(msgs[i], variables_, i, options, &scc_analyzer_); + message_generators_.emplace_back(msg_gen); + msg_gen->AddGenerators(&enum_generators_, &extension_generators_); } for (int i = 0; i < file->enum_type_count(); i++) { - enum_generators_owner_[i].reset( - new EnumGenerator(file->enum_type(i), options)); - enum_generators_.push_back(enum_generators_owner_[i].get()); - } - for (int i = 0; i < enum_generators_.size(); i++) { - enum_generators_[i]->index_in_metadata_ = i; + enum_generators_.emplace_back( + new EnumGenerator(file->enum_type(i), variables_, options)); } for (int i = 0; i < file->service_count(); i++) { - service_generators_owner_[i].reset( - new ServiceGenerator(file->service(i), options)); - service_generators_.push_back(service_generators_owner_[i].get()); + service_generators_.emplace_back( + new ServiceGenerator(file->service(i), variables_, options)); } if (HasGenericServices(file_, options_)) { for (int i = 0; i < service_generators_.size(); i++) { service_generators_[i]->index_in_metadata_ = i; } } - for (int i = 0; i < file->extension_count(); i++) { - extension_generators_owner_[i].reset( + extension_generators_.emplace_back( new ExtensionGenerator(file->extension(i), options)); - extension_generators_.push_back(extension_generators_owner_[i].get()); } - - package_parts_ = Split(file_->package(), ".", true); + for (int i = 0; i < file->weak_dependency_count(); ++i) { + weak_deps_.insert(file->weak_dependency(i)); + } } -FileGenerator::~FileGenerator() {} +FileGenerator::~FileGenerator() = default; void FileGenerator::GenerateMacroUndefs(io::Printer* printer) { - std::vector names_to_undef; - CollectMacroNames(file_, &names_to_undef); + Formatter format(printer, variables_); + // Only do this for protobuf's own types. There are some google3 protos using + // macros as field names and the generated code compiles after the macro + // expansion. Undefing these macros actually breaks such code. + if (file_->name() != "net/proto2/compiler/proto/plugin.proto" && + file_->name() != "google/protobuf/compiler/plugin.proto") { + return; + } + std::vector names_to_undef; + std::vector fields; + ListAllFields(file_, &fields); + for (int i = 0; i < fields.size(); i++) { + const std::string& name = fields[i]->name(); + static const char* kMacroNames[] = {"major", "minor"}; + for (int i = 0; i < GOOGLE_ARRAYSIZE(kMacroNames); ++i) { + if (name == kMacroNames[i]) { + names_to_undef.push_back(name); + break; + } + } + } for (int i = 0; i < names_to_undef.size(); ++i) { - printer->Print( - "#ifdef $name$\n" - "#undef $name$\n" + format( + "#ifdef $1$\n" + "#undef $1$\n" "#endif\n", - "name", names_to_undef[i]); + names_to_undef[i]); } } void FileGenerator::GenerateHeader(io::Printer* printer) { - printer->Print( - "// @@protoc_insertion_point(includes)\n"); + Formatter format(printer, variables_); + // port_def.inc must be included after all other includes. + IncludeFile("net/proto2/public/port_def.inc", printer); + format("#define $1$$ dllexport_decl$\n", FileDllExport(file_, options_)); GenerateMacroUndefs(printer); - GenerateForwardDeclarations(printer); - - // Open namespace. - GenerateNamespaceOpeners(printer); + // For Any support with lite protos, we need to friend AnyMetadata, so we + // forward-declare it here. + format( + "PROTOBUF_NAMESPACE_OPEN\n" + "namespace internal {\n" + "class AnyMetadata;\n" + "} // namespace internal\n" + "PROTOBUF_NAMESPACE_CLOSE\n"); GenerateGlobalStateFunctionDeclarations(printer); - printer->Print("\n"); + GenerateForwardDeclarations(printer); + + { + NamespaceOpener ns(Namespace(file_, options_), format); - GenerateEnumDefinitions(printer); + format("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); + GenerateEnumDefinitions(printer); - GenerateMessageDefinitions(printer); + format(kThickSeparator); + format("\n"); - printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); + GenerateMessageDefinitions(printer); - GenerateServiceDefinitions(printer); + format("\n"); + format(kThickSeparator); + format("\n"); - GenerateExtensionIdentifiers(printer); + GenerateServiceDefinitions(printer); - printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); + GenerateExtensionIdentifiers(printer); - GenerateInlineFunctionDefinitions(printer); + format("\n"); + format(kThickSeparator); + format("\n"); - printer->Print( - "\n" - "// @@protoc_insertion_point(namespace_scope)\n" - "\n"); + GenerateInlineFunctionDefinitions(printer); - // Close up namespace. - GenerateNamespaceClosers(printer); + format( + "\n" + "// @@protoc_insertion_point(namespace_scope)\n" + "\n"); + } // We need to specialize some templates in the ::google::protobuf namespace: GenerateProto2NamespaceEnumSpecializations(printer); - printer->Print( - "\n" - "// @@protoc_insertion_point(global_scope)\n" - "\n"); + format( + "\n" + "// @@protoc_insertion_point(global_scope)\n" + "\n"); + IncludeFile("net/proto2/public/port_undef.inc", printer); } void FileGenerator::GenerateProtoHeader(io::Printer* printer, - const string& info_path) { + const std::string& info_path) { + Formatter format(printer, variables_); if (!options_.proto_h) { return; } - string filename_identifier = FilenameIdentifier(file_->name()); - GenerateTopHeaderGuard(printer, filename_identifier); + GenerateTopHeaderGuard(printer, false); + if (!options_.opensource_runtime) { + format( + "#ifdef SWIG\n" + "#error \"Do not SWIG-wrap protobufs.\"\n" + "#endif // SWIG\n" + "\n"); + } + + if (IsBootstrapProto(options_, file_)) { + format("// IWYU pragma: private, include \"$1$.proto.h\"\n\n", + StripProto(file_->name())); + } GenerateLibraryIncludes(printer); for (int i = 0; i < file_->public_dependency_count(); i++) { const FileDescriptor* dep = file_->public_dependency(i); - const char* extension = ".proto.h"; - string dependency = StripProto(dep->name()) + extension; - printer->Print( - "#include \"$dependency$\" // IWYU pragma: export\n", - "dependency", dependency); + format("#include \"$1$.proto.h\"\n", StripProto(dep->name())); } + format("// @@protoc_insertion_point(includes)\n"); + GenerateMetadataPragma(printer, info_path); GenerateHeader(printer); - GenerateBottomHeaderGuard(printer, filename_identifier); + GenerateBottomHeaderGuard(printer, false); } void FileGenerator::GeneratePBHeader(io::Printer* printer, - const string& info_path) { - string filename_identifier = - FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : "")); - GenerateTopHeaderGuard(printer, filename_identifier); + const std::string& info_path) { + Formatter format(printer, variables_); + GenerateTopHeaderGuard(printer, true); if (options_.proto_h) { - printer->Print("#include \"$basename$.proto.h\" // IWYU pragma: export\n", - "basename", StripProto(file_->name())); + std::string target_basename = StripProto(file_->name()); + if (!options_.opensource_runtime) { + GetBootstrapBasename(options_, target_basename, &target_basename); + } + format("#include \"$1$.proto.h\" // IWYU pragma: export\n", + target_basename); } else { GenerateLibraryIncludes(printer); } - GenerateDependencyIncludes(printer); + if (options_.transitive_pb_h) { + GenerateDependencyIncludes(printer); + } + + // This is unfortunately necessary for some plugins. I don't see why we + // need two of the same insertion points. + // TODO(gerbens) remove this. + format("// @@protoc_insertion_point(includes)\n"); + GenerateMetadataPragma(printer, info_path); if (!options_.proto_h) { GenerateHeader(printer); } else { - // This is unfortunately necessary for some plugins. I don't see why we - // need two of the same insertion points. - // TODO(gerbens) remove this. - printer->Print( - "// @@protoc_insertion_point(includes)\n"); - - // Open namespace. - GenerateNamespaceOpeners(printer); - printer->Print( - "\n" - "// @@protoc_insertion_point(namespace_scope)\n"); - // Close up namespace. - GenerateNamespaceClosers(printer); + { + NamespaceOpener ns(Namespace(file_, options_), format); + format( + "\n" + "// @@protoc_insertion_point(namespace_scope)\n"); + } + format( + "\n" + "// @@protoc_insertion_point(global_scope)\n" + "\n"); + } - printer->Print( - "\n" - "// @@protoc_insertion_point(global_scope)\n" - "\n"); + GenerateBottomHeaderGuard(printer, true); +} + +void FileGenerator::DoIncludeFile(const std::string& google3_name, + bool do_export, io::Printer* printer) { + Formatter format(printer, variables_); + const std::string prefix = "net/proto2/"; + GOOGLE_CHECK(google3_name.find(prefix) == 0) << google3_name; + + if (options_.opensource_runtime) { + std::string path = google3_name.substr(prefix.size()); + + path = StringReplace(path, "internal/", "", false); + path = StringReplace(path, "proto/", "", false); + path = StringReplace(path, "public/", "", false); + if (options_.runtime_include_base.empty()) { + format("#include ", path); + } else { + format("#include \"$1$google/protobuf/$2$\"", + options_.runtime_include_base, path); + } + } else { + format("#include \"$1$\"", google3_name); } - GenerateBottomHeaderGuard(printer, filename_identifier); + if (do_export) { + format(" // IWYU pragma: export"); + } + + format("\n"); } -void FileGenerator::GenerateSource(io::Printer* printer) { - const bool use_system_include = IsWellKnownMessage(file_); - string header = - StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h"); - printer->Print( - "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "// source: $filename$\n" - "\n" - // The generated code calls accessors that might be deprecated. We don't - // want the compiler to warn in generated code. - "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n" - "#include $left$$header$$right$\n" - "\n" - "#include \n" // for swap() - "\n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n", - "filename", file_->name(), - "header", header, - "left", use_system_include ? "<" : "\"", - "right", use_system_include ? ">" : "\""); +std::string FileGenerator::CreateHeaderInclude(const std::string& basename, + const FileDescriptor* file) { + bool use_system_include = false; + std::string name = basename; + + if (options_.opensource_runtime) { + if (IsWellKnownMessage(file)) { + if (options_.runtime_include_base.empty()) { + use_system_include = true; + } else { + name = options_.runtime_include_base + basename; + } + } + } + + std::string left = "\""; + std::string right = "\""; + if (use_system_include) { + left = "<"; + right = ">"; + } + return left + name + right; +} + +void FileGenerator::GenerateSourceIncludes(io::Printer* printer) { + Formatter format(printer, variables_); + std::string target_basename = StripProto(file_->name()); + if (!options_.opensource_runtime) { + GetBootstrapBasename(options_, target_basename, &target_basename); + } + target_basename += options_.proto_h ? ".proto.h" : ".pb.h"; + format( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n" + "#include $1$\n" + "\n" + "#include \n" // for swap() + "\n", + CreateHeaderInclude(target_basename, file_)); + + IncludeFile("net/proto2/io/public/coded_stream.h", printer); + // TODO(gerbens) This is to include parse_context.h, we need a better way + IncludeFile("net/proto2/public/extension_set.h", printer); + IncludeFile("net/proto2/public/wire_format_lite.h", printer); // Unknown fields implementation in lite mode uses StringOutputStream if (!UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) { - printer->Print( - "#include \n"); + IncludeFile("net/proto2/io/public/zero_copy_stream_impl_lite.h", printer); } if (HasDescriptorMethods(file_, options_)) { - printer->Print( - "#include \n" - "#include \n" - "#include \n" - "#include \n"); + IncludeFile("net/proto2/public/descriptor.h", printer); + IncludeFile("net/proto2/public/generated_message_reflection.h", printer); + IncludeFile("net/proto2/public/reflection_ops.h", printer); + IncludeFile("net/proto2/public/wire_format.h", printer); } if (options_.proto_h) { // Use the smaller .proto.h files. for (int i = 0; i < file_->dependency_count(); i++) { const FileDescriptor* dep = file_->dependency(i); - const char* extension = ".proto.h"; - string dependency = StripProto(dep->name()) + extension; - printer->Print( - "#include \"$dependency$\"\n", - "dependency", dependency); + // Do not import weak deps. + if (!options_.opensource_runtime && IsDepWeak(dep)) continue; + std::string basename = StripProto(dep->name()); + if (IsBootstrapProto(options_, file_)) { + GetBootstrapBasename(options_, basename, &basename); + } + format("#include \"$1$.proto.h\"\n", basename); } } + if (HasCordFields(file_, options_)) { + format( + "#include \"third_party/absl/strings/internal/string_constant.h\"\n"); + } - printer->Print( - "// @@protoc_insertion_point(includes)\n"); + format("// @@protoc_insertion_point(includes)\n"); + IncludeFile("net/proto2/public/port_def.inc", printer); - GenerateNamespaceOpeners(printer); + // For MSVC builds, we use #pragma init_seg to move the initialization of our + // libraries to happen before the user code. + // This worksaround the fact that MSVC does not do constant initializers when + // required by the standard. + format("\nPROTOBUF_PRAGMA_INIT_SEG\n"); +} - for (int i = 0; i < message_generators_.size(); i++) { - string parent; - if (IsMapEntryMessage(message_generators_[i]->descriptor_)) { - parent = ClassName(message_generators_[i]->descriptor_->containing_type(), - false) + - "::"; - } - printer->Print( - "class $classname$DefaultTypeInternal {\n" - "public:\n" - " ::google::protobuf::internal::ExplicitlyConstructed<$parent$$classname$>\n" - " _instance;\n", - "parent", parent, "classname", message_generators_[i]->classname_); - printer->Indent(); - message_generators_[i]->GenerateExtraDefaultFields(printer); - printer->Outdent(); - printer->Print( - "} _$classname$_default_instance_;\n", - "classname", message_generators_[i]->classname_); +void FileGenerator::GenerateSourceDefaultInstance(int idx, + io::Printer* printer) { + Formatter format(printer, variables_); + MessageGenerator* generator = message_generators_[idx].get(); + generator->GenerateConstexprConstructor(printer); + // Use a union to disable the destructor of the _instance member. + // We can constant initialize, but the object will still have a non-trivial + // destructor that we need to elide. + format( + "struct $1$ {\n" + " constexpr $1$()\n" + " : _instance(::$proto_ns$::internal::ConstantInitialized{}) {}\n" + " ~$1$() {}\n" + " union {\n" + " $2$ _instance;\n" + " };\n" + "};\n", + DefaultInstanceType(generator->descriptor_, options_), + generator->classname_); + // NO_DESTROY is not necessary for correctness. The empty destructor is + // enough. However, the empty destructor fails to be elided in some + // configurations (like non-opt or with certain sanitizers). NO_DESTROY is + // there just to improve performance and binary size in these builds. + format("PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT $1$ $2$;\n", + DefaultInstanceType(generator->descriptor_, options_), + DefaultInstanceName(generator->descriptor_, options_)); + + if (options_.lite_implicit_weak_fields) { + format("$1$* $2$ = &$3$;\n", + DefaultInstanceType(generator->descriptor_, options_), + DefaultInstancePtr(generator->descriptor_, options_), + DefaultInstanceName(generator->descriptor_, options_)); } +} - for (int i = 0; i < enum_generators_.size(); i++) { - enum_generators_[i]->index_in_metadata_ = i; - } - if (HasGenericServices(file_, options_)) { - for (int i = 0; i < service_generators_.size(); i++) { - service_generators_[i]->index_in_metadata_ = i; - } +// A list of things defined in one .pb.cc file that we need to reference from +// another .pb.cc file. +struct FileGenerator::CrossFileReferences { + // Populated if we are referencing from messages or files. + std::unordered_set weak_default_instances; + + // Only if we are referencing from files. + std::unordered_set strong_reflection_files; + std::unordered_set weak_reflection_files; +}; + +void FileGenerator::GetCrossFileReferencesForField(const FieldDescriptor* field, + CrossFileReferences* refs) { + const Descriptor* msg = field->message_type(); + if (msg == nullptr) return; + + if (IsImplicitWeakField(field, options_, &scc_analyzer_) || + IsWeak(field, options_)) { + refs->weak_default_instances.insert(msg); } +} - printer->Print( - "\n" - "namespace $file_namespace$ {\n" - "\n", - "file_namespace", FileLevelNamespace(file_->name())); +void FileGenerator::GetCrossFileReferencesForFile(const FileDescriptor* file, + CrossFileReferences* refs) { + ForEachField(file, [this, refs](const FieldDescriptor* field) { + GetCrossFileReferencesForField(field, refs); + }); - if (HasDescriptorMethods(file_, options_)) { - printer->Print( - "\n" - "namespace {\n" - "\n"); + if (!HasDescriptorMethods(file, options_)) return; - if (!message_generators_.empty()) { - printer->Print("::google::protobuf::Metadata file_level_metadata[$size$];\n", - "size", SimpleItoa(message_generators_.size())); - } - if (!enum_generators_.empty()) { - printer->Print( - "const ::google::protobuf::EnumDescriptor* " - "file_level_enum_descriptors[$size$];\n", - "size", SimpleItoa(enum_generators_.size())); + for (int i = 0; i < file->dependency_count(); i++) { + const FileDescriptor* dep = file->dependency(i); + if (IsDepWeak(dep)) { + refs->weak_reflection_files.insert(dep); + } else { + refs->strong_reflection_files.insert(dep); } - if (HasGenericServices(file_, options_) && file_->service_count() > 0) { - printer->Print( - "const ::google::protobuf::ServiceDescriptor* " - "file_level_service_descriptors[$size$];\n", - "size", SimpleItoa(file_->service_count())); + } +} + +// Generates references to variables defined in other files. +void FileGenerator::GenerateInternalForwardDeclarations( + const CrossFileReferences& refs, io::Printer* printer) { + Formatter format(printer, variables_); + + { + NamespaceOpener ns(format); + for (auto instance : Sorted(refs.weak_default_instances)) { + ns.ChangeTo(Namespace(instance, options_)); + if (options_.lite_implicit_weak_fields) { + format("extern $1$ $2$;\n", DefaultInstanceType(instance, options_), + DefaultInstanceName(instance, options_)); + format("__attribute__((weak)) $1$* $2$ = nullptr;\n", + DefaultInstanceType(instance, options_), + DefaultInstancePtr(instance, options_)); + } else { + format("extern __attribute__((weak)) $1$ $2$;\n", + DefaultInstanceType(instance, options_), + DefaultInstanceName(instance, options_)); + } } + } - printer->Print( - "\n" - "} // namespace\n" - "\n"); + for (auto file : Sorted(refs.weak_reflection_files)) { + format( + "extern __attribute__((weak)) const " + "::$proto_ns$::internal::DescriptorTable $1$;\n", + DescriptorTableName(file, options_)); } +} - // Define our externally-visible BuildDescriptors() function. (For the lite - // library, all this does is initialize default instances.) - GenerateBuildDescriptors(printer); +void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) { + Formatter format(printer, variables_); + GenerateSourceIncludes(printer); - printer->Print( + CrossFileReferences refs; + ForEachField(message_generators_[idx]->descriptor_, + [this, &refs](const FieldDescriptor* field) { + GetCrossFileReferencesForField(field, &refs); + }); + GenerateInternalForwardDeclarations(refs, printer); + + { // package namespace + NamespaceOpener ns(Namespace(file_, options_), format); + + // Define default instances + GenerateSourceDefaultInstance(idx, printer); + + // Generate classes. + format("\n"); + message_generators_[idx]->GenerateClassMethods(printer); + + format( + "\n" + "// @@protoc_insertion_point(namespace_scope)\n"); + } // end package namespace + + { + NamespaceOpener proto_ns(ProtobufNamespace(options_), format); + message_generators_[idx]->GenerateSourceInProto2Namespace(printer); + } + + format( "\n" - "} // namespace $file_namespace$\n" - "\n", - "file_namespace", FileLevelNamespace(file_->name())); + "// @@protoc_insertion_point(global_scope)\n"); +} + +void FileGenerator::GenerateGlobalSource(io::Printer* printer) { + Formatter format(printer, variables_); + GenerateSourceIncludes(printer); + + { + GenerateTables(printer); + + // Define the code to initialize reflection. This code uses a global + // constructor to register reflection data with the runtime pre-main. + if (HasDescriptorMethods(file_, options_)) { + GenerateReflectionInitializationCode(printer); + } + } + + NamespaceOpener ns(Namespace(file_, options_), format); // Generate enums. for (int i = 0; i < enum_generators_.size(); i++) { - enum_generators_[i]->GenerateMethods(printer); + enum_generators_[i]->GenerateMethods(i, printer); } - // Generate classes. - for (int i = 0; i < message_generators_.size(); i++) { - printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); - message_generators_[i]->GenerateClassMethods(printer); - - printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n"); - // Generate class inline methods. - message_generators_[i]->GenerateInlineMethods(printer, - /* is_inline = */ false); - printer->Print("#endif // PROTOBUF_INLINE_NOT_IN_HEADERS\n"); + // Define extensions. + for (int i = 0; i < extension_generators_.size(); i++) { + extension_generators_[i]->GenerateDefinition(printer); } if (HasGenericServices(file_, options_)) { // Generate services. for (int i = 0; i < service_generators_.size(); i++) { - if (i == 0) printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); + if (i == 0) format("\n"); + format(kThickSeparator); + format("\n"); service_generators_[i]->GenerateImplementation(printer); } } +} - // Define extensions. - for (int i = 0; i < extension_generators_.size(); i++) { - extension_generators_[i]->GenerateDefinition(printer); - } - - printer->Print( - "\n" - "// @@protoc_insertion_point(namespace_scope)\n"); +void FileGenerator::GenerateSource(io::Printer* printer) { + Formatter format(printer, variables_); + GenerateSourceIncludes(printer); + CrossFileReferences refs; + GetCrossFileReferencesForFile(file_, &refs); + GenerateInternalForwardDeclarations(refs, printer); - GenerateNamespaceClosers(printer); + { + NamespaceOpener ns(Namespace(file_, options_), format); - printer->Print( - "\n" - "// @@protoc_insertion_point(global_scope)\n"); -} - -class FileGenerator::ForwardDeclarations { - public: - ~ForwardDeclarations() { - for (std::map::iterator - it = namespaces_.begin(), - end = namespaces_.end(); - it != end; ++it) { - delete it->second; + // Define default instances + for (int i = 0; i < message_generators_.size(); i++) { + GenerateSourceDefaultInstance(i, printer); } - namespaces_.clear(); } - ForwardDeclarations* AddOrGetNamespace(const string& ns_name) { - ForwardDeclarations*& ns = namespaces_[ns_name]; - if (ns == NULL) { - ns = new ForwardDeclarations; + { + GenerateTables(printer); + + if (HasDescriptorMethods(file_, options_)) { + // Define the code to initialize reflection. This code uses a global + // constructor to register reflection data with the runtime pre-main. + GenerateReflectionInitializationCode(printer); } - return ns; } - std::map& classes() { return classes_; } - std::map& enums() { return enums_; } + { + NamespaceOpener ns(Namespace(file_, options_), format); - void Print(io::Printer* printer, const Options& options) const { - for (std::map::const_iterator - it = enums_.begin(), - end = enums_.end(); - it != end; ++it) { - printer->Print("enum $enumname$ : int;\n", "enumname", it->first); - printer->Annotate("enumname", it->second); - printer->Print("bool $enumname$_IsValid(int value);\n", "enumname", - it->first); - } - for (std::map::const_iterator - it = classes_.begin(), - end = classes_.end(); - it != end; ++it) { - printer->Print("class $classname$;\n", "classname", it->first); - printer->Annotate("classname", it->second); - - printer->Print( - "class $classname$DefaultTypeInternal;\n" - "$dllexport_decl$" - "extern $classname$DefaultTypeInternal " - "_$classname$_default_instance_;\n", // NOLINT - "dllexport_decl", - options.dllexport_decl.empty() ? "" : options.dllexport_decl + " ", - "classname", - it->first); + // Actually implement the protos + + // Generate enums. + for (int i = 0; i < enum_generators_.size(); i++) { + enum_generators_[i]->GenerateMethods(i, printer); } - for (std::map::const_iterator - it = namespaces_.begin(), - end = namespaces_.end(); - it != end; ++it) { - printer->Print("namespace $nsname$ {\n", - "nsname", it->first); - it->second->Print(printer, options); - printer->Print("} // namespace $nsname$\n", - "nsname", it->first); + + // Generate classes. + for (int i = 0; i < message_generators_.size(); i++) { + format("\n"); + format(kThickSeparator); + format("\n"); + message_generators_[i]->GenerateClassMethods(printer); } - } + if (HasGenericServices(file_, options_)) { + // Generate services. + for (int i = 0; i < service_generators_.size(); i++) { + if (i == 0) format("\n"); + format(kThickSeparator); + format("\n"); + service_generators_[i]->GenerateImplementation(printer); + } + } - private: - std::map namespaces_; - std::map classes_; - std::map enums_; -}; + // Define extensions. + for (int i = 0; i < extension_generators_.size(); i++) { + extension_generators_[i]->GenerateDefinition(printer); + } -void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { - // AddDescriptors() is a file-level procedure which adds the encoded - // FileDescriptorProto for this .proto file to the global DescriptorPool for - // generated files (DescriptorPool::generated_pool()). It ordinarily runs at - // static initialization time, but is not used at all in LITE_RUNTIME mode - // except when extensions are used. This procedure also constructs default - // instances and registers extensions. - // - // Its sibling, AssignDescriptors(), actually pulls the compiled - // FileDescriptor from the DescriptorPool and uses it to populate all of - // the global variables which store pointers to the descriptor objects. - // It also constructs the reflection objects. It is called the first time - // anyone calls descriptor() or GetReflection() on one of the types defined - // in the file. - - // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors() - // and we only use AddDescriptors() to allocate default instances. - - // TODO(ckennelly): Gate this with the same options flag to enable - // table-driven parsing. - - printer->Print("PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField\n" - " const TableStruct::entries[] " - "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n"); - printer->Indent(); - - std::vector entries; - size_t count = 0; - for (int i = 0; i < message_generators_.size(); i++) { - size_t value = message_generators_[i]->GenerateParseOffsets(printer); - entries.push_back(value); - count += value; + format( + "\n" + "// @@protoc_insertion_point(namespace_scope)\n"); } - // We need these arrays to exist, and MSVC does not like empty arrays. - if (count == 0) { - printer->Print("{0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},\n"); + { + NamespaceOpener proto_ns(ProtobufNamespace(options_), format); + for (int i = 0; i < message_generators_.size(); i++) { + message_generators_[i]->GenerateSourceInProto2Namespace(printer); + } } - printer->Outdent(); - printer->Print( - "};\n" + format( "\n" - "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField\n" - " const TableStruct::aux[] " - "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n"); - printer->Indent(); + "// @@protoc_insertion_point(global_scope)\n"); - std::vector aux_entries; - count = 0; - for (int i = 0; i < message_generators_.size(); i++) { - size_t value = message_generators_[i]->GenerateParseAuxTable(printer); - aux_entries.push_back(value); - count += value; - } + IncludeFile("net/proto2/public/port_undef.inc", printer); +} - if (count == 0) { - printer->Print("::google::protobuf::internal::AuxillaryParseTableField(),\n"); - } +void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) { + Formatter format(printer, variables_); - printer->Outdent(); - printer->Print( - "};\n" - "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const\n" - " TableStruct::schema[] " - "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n"); - printer->Indent(); + if (!message_generators_.empty()) { + format("static ::$proto_ns$::Metadata $file_level_metadata$[$1$];\n", + message_generators_.size()); + } else { + format( + "static " + "constexpr ::$proto_ns$::Metadata* $file_level_metadata$ = nullptr;\n"); + } + if (!enum_generators_.empty()) { + format( + "static " + "const ::$proto_ns$::EnumDescriptor* " + "$file_level_enum_descriptors$[$1$];\n", + enum_generators_.size()); + } else { + format( + "static " + "constexpr ::$proto_ns$::EnumDescriptor const** " + "$file_level_enum_descriptors$ = nullptr;\n"); + } + if (HasGenericServices(file_, options_) && file_->service_count() > 0) { + format( + "static " + "const ::$proto_ns$::ServiceDescriptor* " + "$file_level_service_descriptors$[$1$];\n", + file_->service_count()); + } else { + format( + "static " + "constexpr ::$proto_ns$::ServiceDescriptor const** " + "$file_level_service_descriptors$ = nullptr;\n"); + } - size_t offset = 0; - size_t aux_offset = 0; - for (int i = 0; i < message_generators_.size(); i++) { - message_generators_[i]->GenerateParseTable(printer, offset, aux_offset); - offset += entries[i]; - aux_offset += aux_entries[i]; + if (!message_generators_.empty()) { + format( + "\n" + "const $uint32$ $tablename$::offsets[] " + "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n"); + format.Indent(); + std::vector > pairs; + pairs.reserve(message_generators_.size()); + for (int i = 0; i < message_generators_.size(); i++) { + pairs.push_back(message_generators_[i]->GenerateOffsets(printer)); + } + format.Outdent(); + format( + "};\n" + "static const ::$proto_ns$::internal::MigrationSchema schemas[] " + "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n"); + format.Indent(); + { + int offset = 0; + for (int i = 0; i < message_generators_.size(); i++) { + message_generators_[i]->GenerateSchema(printer, offset, + pairs[i].second); + offset += pairs[i].first; + } + } + format.Outdent(); + format( + "};\n" + "\nstatic " + "::$proto_ns$::Message const * const file_default_instances[] = {\n"); + format.Indent(); + for (int i = 0; i < message_generators_.size(); i++) { + const Descriptor* descriptor = message_generators_[i]->descriptor_; + format( + "reinterpret_cast(&$1$::_$2$_default_instance_),\n", + Namespace(descriptor, options_), // 1 + ClassName(descriptor)); // 2 + } + format.Outdent(); + format( + "};\n" + "\n"); + } else { + // we still need these symbols to exist + format( + // MSVC doesn't like empty arrays, so we add a dummy. + "const $uint32$ $tablename$::offsets[1] = {};\n" + "static constexpr ::$proto_ns$::internal::MigrationSchema* schemas = " + "nullptr;" + "\n" + "static constexpr ::$proto_ns$::Message* const* " + "file_default_instances = nullptr;\n" + "\n"); } - if (message_generators_.empty()) { - printer->Print("{ NULL, NULL, 0, -1, -1, -1, -1, NULL, false },\n"); + // --------------------------------------------------------------- + + // Embed the descriptor. We simply serialize the entire + // FileDescriptorProto/ and embed it as a string literal, which is parsed and + // built into real descriptors at initialization time. + const std::string protodef_name = + UniqueName("descriptor_table_protodef", file_, options_); + format("const char $1$[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =\n", + protodef_name); + format.Indent(); + FileDescriptorProto file_proto; + file_->CopyTo(&file_proto); + std::string file_data; + file_proto.SerializeToString(&file_data); + + { + if (file_data.size() > 65535) { + // Workaround for MSVC: "Error C1091: compiler limit: string exceeds + // 65535 bytes in length". Declare a static array of chars rather than + // use a string literal. Only write 25 bytes per line. + static const int kBytesPerLine = 25; + format("{ "); + for (int i = 0; i < file_data.size();) { + for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) { + format("'$1$', ", CEscape(file_data.substr(i, 1))); + } + format("\n"); + } + format("'\\0' }"); // null-terminate + } else { + // Only write 40 bytes per line. + static const int kBytesPerLine = 40; + for (int i = 0; i < file_data.size(); i += kBytesPerLine) { + format( + "\"$1$\"\n", + EscapeTrigraphs(CEscape(file_data.substr(i, kBytesPerLine)))); + } + } + format(";\n"); } + format.Outdent(); + + CrossFileReferences refs; + GetCrossFileReferencesForFile(file_, &refs); + int num_deps = + refs.strong_reflection_files.size() + refs.weak_reflection_files.size(); + + // Build array of DescriptorTable deps. + if (num_deps > 0) { + format( + "static const ::$proto_ns$::internal::DescriptorTable*const " + "$desc_table$_deps[$1$] = {\n", + num_deps); + + for (auto dep : Sorted(refs.strong_reflection_files)) { + format(" &::$1$,\n", DescriptorTableName(dep, options_)); + } + for (auto dep : Sorted(refs.weak_reflection_files)) { + format(" &::$1$,\n", DescriptorTableName(dep, options_)); + } - printer->Outdent(); - printer->Print( + format("};\n"); + } + + // The DescriptorTable itself. + // Should be "bool eager = NeedsEagerDescriptorAssignment(file_, options_);" + // however this might cause a tsan failure in superroot b/148382879, + // so disable for now. + bool eager = false; + format( + "static ::$proto_ns$::internal::once_flag $desc_table$_once;\n" + "const ::$proto_ns$::internal::DescriptorTable $desc_table$ = {\n" + " false, $1$, $2$, $3$, \"$filename$\", \n" + " &$desc_table$_once, $4$, $5$, $6$,\n" + " schemas, file_default_instances, $tablename$::offsets,\n" + " $file_level_metadata$, $file_level_enum_descriptors$, " + "$file_level_service_descriptors$,\n" "};\n" - "\n"); + // This function exists to be marked as weak. + // It can significantly speed up compilation by breaking up the SCC. + // Without the weak attribute all the messages in the file, including all + // the vtables and everything they use become part of the same SCC. + // By adding a weak function here we break the connection from the + // individual vtables back into the descriptor table. + "PROTOBUF_ATTRIBUTE_WEAK ::$proto_ns$::Metadata\n" + "$desc_table$_metadata_getter(int index) {\n" + " ::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n" + " return $desc_table$.file_level_metadata[index];\n" + "}\n" + "\n", + eager ? "true" : "false", file_data.size(), protodef_name, + num_deps == 0 ? "nullptr" : variables_["desc_table"] + "_deps", num_deps, + message_generators_.size()); + + // For descriptor.proto we want to avoid doing any dynamic initialization, + // because in some situations that would otherwise pull in a lot of + // unnecessary code that can't be stripped by --gc-sections. Descriptor + // initialization will still be performed lazily when it's needed. + if (file_->name() != "net/proto2/proto/descriptor.proto") { + format( + "// Force running AddDescriptors() at dynamic initialization time.\n" + "PROTOBUF_ATTRIBUTE_INIT_PRIORITY " + "static ::$proto_ns$::internal::AddDescriptorsRunner " + "$1$(&$desc_table$);\n", + UniqueName("dynamic_init_dummy", file_, options_)); + } +} + +void FileGenerator::GenerateTables(io::Printer* printer) { + Formatter format(printer, variables_); + if (options_.table_driven_parsing) { + // TODO(ckennelly): Gate this with the same options flag to enable + // table-driven parsing. + format( + "PROTOBUF_CONSTEXPR_VAR ::$proto_ns$::internal::ParseTableField\n" + " const $tablename$::entries[] " + "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n"); + format.Indent(); + + std::vector entries; + size_t count = 0; + for (int i = 0; i < message_generators_.size(); i++) { + size_t value = message_generators_[i]->GenerateParseOffsets(printer); + entries.push_back(value); + count += value; + } + + // We need these arrays to exist, and MSVC does not like empty arrays. + if (count == 0) { + format("{0, 0, 0, ::$proto_ns$::internal::kInvalidMask, 0, 0},\n"); + } + + format.Outdent(); + format( + "};\n" + "\n" + "PROTOBUF_CONSTEXPR_VAR " + "::$proto_ns$::internal::AuxiliaryParseTableField\n" + " const $tablename$::aux[] " + "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n"); + format.Indent(); + + std::vector aux_entries; + count = 0; + for (int i = 0; i < message_generators_.size(); i++) { + size_t value = message_generators_[i]->GenerateParseAuxTable(printer); + aux_entries.push_back(value); + count += value; + } + + if (count == 0) { + format("::$proto_ns$::internal::AuxiliaryParseTableField(),\n"); + } + + format.Outdent(); + format( + "};\n" + "PROTOBUF_CONSTEXPR_VAR ::$proto_ns$::internal::ParseTable const\n" + " $tablename$::schema[] " + "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n"); + format.Indent(); + + size_t offset = 0; + size_t aux_offset = 0; + for (int i = 0; i < message_generators_.size(); i++) { + message_generators_[i]->GenerateParseTable(printer, offset, aux_offset); + offset += entries[i]; + aux_offset += aux_entries[i]; + } + + if (message_generators_.empty()) { + format("{ nullptr, nullptr, 0, -1, -1, false },\n"); + } + + format.Outdent(); + format( + "};\n" + "\n"); + } if (!message_generators_.empty() && options_.table_driven_serialization) { - printer->Print( - "const ::google::protobuf::internal::FieldMetadata TableStruct::field_metadata[] " + format( + "const ::$proto_ns$::internal::FieldMetadata " + "$tablename$::field_metadata[] " "= {\n"); - printer->Indent(); + format.Indent(); std::vector field_metadata_offsets; int idx = 0; for (int i = 0; i < message_generators_.size(); i++) { @@ -629,12 +973,12 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { idx += message_generators_[i]->GenerateFieldMetadata(printer); } field_metadata_offsets.push_back(idx); - printer->Outdent(); - printer->Print( + format.Outdent(); + format( "};\n" - "const ::google::protobuf::internal::SerializationTable " - "TableStruct::serialization_table[] = {\n"); - printer->Indent(); + "const ::$proto_ns$::internal::SerializationTable " + "$tablename$::serialization_table[] = {\n"); + format.Indent(); // We rely on the order we layout the tables to match the order we // calculate them with FlattenMessagesInFile, so we check here that // these match exactly. @@ -643,511 +987,321 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { GOOGLE_CHECK_EQ(calculated_order.size(), message_generators_.size()); for (int i = 0; i < message_generators_.size(); i++) { GOOGLE_CHECK_EQ(calculated_order[i], message_generators_[i]->descriptor_); - printer->Print( - "{$num_fields$, TableStruct::field_metadata + $index$},\n", - "classname", message_generators_[i]->classname_, "num_fields", - SimpleItoa(field_metadata_offsets[i + 1] - field_metadata_offsets[i]), - "index", SimpleItoa(field_metadata_offsets[i])); + format("{$1$, $tablename$::field_metadata + $2$},\n", + field_metadata_offsets[i + 1] - field_metadata_offsets[i], // 1 + field_metadata_offsets[i]); // 2 } - printer->Outdent(); - printer->Print( + format.Outdent(); + format( "};\n" "\n"); } - if (HasDescriptorMethods(file_, options_)) { - if (!message_generators_.empty()) { - printer->Print("const ::google::protobuf::uint32 TableStruct::offsets[] " - "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n"); - printer->Indent(); - std::vector > pairs; - for (int i = 0; i < message_generators_.size(); i++) { - pairs.push_back(message_generators_[i]->GenerateOffsets(printer)); - } - printer->Outdent(); - printer->Print( - "};\n" - "static const ::google::protobuf::internal::MigrationSchema schemas[] " - "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n"); - printer->Indent(); - { - int offset = 0; - for (int i = 0; i < message_generators_.size(); i++) { - message_generators_[i]->GenerateSchema(printer, offset, - pairs[i].second); - offset += pairs[i].first; - } - } - printer->Outdent(); - printer->Print( - "};\n" - "\nstatic " - "::google::protobuf::Message const * const file_default_instances[] = {\n"); - printer->Indent(); - for (int i = 0; i < message_generators_.size(); i++) { - const Descriptor* descriptor = message_generators_[i]->descriptor_; - printer->Print( - "reinterpret_cast(&_$classname$_default_instance_),\n", - "classname", ClassName(descriptor, false)); - } - printer->Outdent(); - printer->Print( - "};\n" - "\n"); - } else { - // we still need these symbols to exist - printer->Print( - // MSVC doesn't like empty arrays, so we add a dummy. - "const ::google::protobuf::uint32 TableStruct::offsets[1] = {};\n" - "static const ::google::protobuf::internal::MigrationSchema* schemas = NULL;\n" - "static const ::google::protobuf::Message* const* " - "file_default_instances = NULL;\n"); - } - - // --------------------------------------------------------------- +} - // protobuf_AssignDescriptorsOnce(): The first time it is called, calls - // AssignDescriptors(). All later times, waits for the first call to - // complete and then returns. - string message_factory = "NULL"; - printer->Print( - "namespace {\n" - "\n" - "void protobuf_AssignDescriptors() {\n" - // Make sure the file has found its way into the pool. If a descriptor - // is requested *during* static init then AddDescriptors() may not have - // been called yet, so we call it manually. Note that it's fine if - // AddDescriptors() is called multiple times. - " AddDescriptors();\n" - " ::google::protobuf::MessageFactory* factory = $factory$;\n" - " AssignDescriptors(\n" - " \"$filename$\", schemas, file_default_instances, " - "TableStruct::offsets, factory,\n" - " $metadata$, $enum_descriptors$, $service_descriptors$);\n", - "filename", file_->name(), "metadata", - !message_generators_.empty() ? "file_level_metadata" : "NULL", - "enum_descriptors", - !enum_generators_.empty() ? "file_level_enum_descriptors" : "NULL", - "service_descriptors", - HasGenericServices(file_, options_) && file_->service_count() > 0 - ? "file_level_service_descriptors" - : "NULL", - "factory", message_factory); - // TODO(gerbens) have the compiler include the schemas for map types - // so that this can go away, and we can potentially use table driven - // serialization for map types as well. - for (int i = 0; i < message_generators_.size(); i++) { - if (!IsMapEntryMessage(message_generators_[i]->descriptor_)) continue; - printer->Print( - "file_level_metadata[$index$].reflection = " - "$parent$::$classname$::CreateReflection(file_level_metadata[$index$]" - ".descriptor, _$classname$_default_instance_._instance.get_mutable());\n", - "index", SimpleItoa(i), "parent", - ClassName(message_generators_[i]->descriptor_->containing_type(), - false), - "classname", ClassName(message_generators_[i]->descriptor_, false)); +class FileGenerator::ForwardDeclarations { + public: + void AddMessage(const Descriptor* d) { classes_[ClassName(d)] = d; } + void AddEnum(const EnumDescriptor* d) { enums_[ClassName(d)] = d; } + + void Print(const Formatter& format, const Options& options) const { + for (const auto& p : enums_) { + const std::string& enumname = p.first; + const EnumDescriptor* enum_desc = p.second; + format( + "enum ${1$$2$$}$ : int;\n" + "bool $2$_IsValid(int value);\n", + enum_desc, enumname); } - printer->Print( - "}\n" - "\n" - "void protobuf_AssignDescriptorsOnce() {\n" - " static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n" - " ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);\n" - "}\n" - "\n", - "filename", file_->name(), "metadata", - !message_generators_.empty() ? "file_level_metadata" : "NULL", - "enum_descriptors", - !enum_generators_.empty() ? "file_level_enum_descriptors" : "NULL", - "service_descriptors", - HasGenericServices(file_, options_) && file_->service_count() > 0 - ? "file_level_service_descriptors" - : "NULL", - "factory", message_factory); - - // Only here because of useless string reference that we don't want in - // protobuf_AssignDescriptorsOnce, because that is called from all the - // GetMetadata member methods. - printer->Print( - "void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;\n" - "void protobuf_RegisterTypes(const ::std::string&) {\n" - " protobuf_AssignDescriptorsOnce();\n"); - printer->Indent(); - - // All normal messages can be done generically - if (!message_generators_.empty()) { - printer->Print( - "::google::protobuf::internal::RegisterAllTypes(file_level_metadata, $size$);\n", - "size", SimpleItoa(message_generators_.size())); + for (const auto& p : classes_) { + const std::string& classname = p.first; + const Descriptor* class_desc = p.second; + format( + "class ${1$$2$$}$;\n" + "struct $3$;\n" + "$dllexport_decl $extern $3$ $4$;\n", + class_desc, classname, DefaultInstanceType(class_desc, options), + DefaultInstanceName(class_desc, options)); } - - printer->Outdent(); - printer->Print( - "}\n" - "\n" - "} // namespace\n"); - } - - // Now generate the InitDefaultsImpl() function. - printer->Print( - "void TableStruct::InitDefaultsImpl() {\n" - " GOOGLE_PROTOBUF_VERIFY_VERSION;\n\n" - // Force initialization of primitive values we depend on. - " ::google::protobuf::internal::InitProtobufDefaults();\n"); - - printer->Indent(); - - // Call the InitDefaults() methods for all of our dependencies, to make - // sure they get added first. - for (int i = 0; i < file_->dependency_count(); i++) { - const FileDescriptor* dependency = file_->dependency(i); - // Print the namespace prefix for the dependency. - string file_namespace = QualifiedFileLevelSymbol( - dependency->package(), FileLevelNamespace(dependency->name())); - // Call its AddDescriptors function. - printer->Print("$file_namespace$::InitDefaults();\n", "file_namespace", - file_namespace); - } - - // Allocate and initialize default instances. This can't be done lazily - // since default instances are returned by simple accessors and are used with - // extensions. Speaking of which, we also register extensions at this time. - for (int i = 0; i < message_generators_.size(); i++) { - message_generators_[i]->GenerateDefaultInstanceAllocator(printer); } - for (int i = 0; i < extension_generators_.size(); i++) { - extension_generators_[i]->GenerateRegistration(printer); - } - for (int i = 0; i < message_generators_.size(); i++) { - message_generators_[i]->GenerateDefaultInstanceInitializer(printer); - } - printer->Outdent(); - printer->Print( - "}\n" - "\n" - "void InitDefaults() {\n" - " static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n" - " ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);\n" - "}\n"); - // ----------------------------------------------------------------- - - // Now generate the AddDescriptors() function. - printer->Print( - "namespace {\n" - "void AddDescriptorsImpl() {\n" - " InitDefaults();\n"); - - printer->Indent(); - if (HasDescriptorMethods(file_, options_)) { - // Embed the descriptor. We simply serialize the entire - // FileDescriptorProto - // and embed it as a string literal, which is parsed and built into real - // descriptors at initialization time. - FileDescriptorProto file_proto; - file_->CopyTo(&file_proto); - string file_data; - file_proto.SerializeToString(&file_data); - - printer->Print("static const char descriptor[] " - "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n"); - printer->Indent(); - - if (file_data.size() > 66535) { - // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535 - // bytes in length". Declare a static array of characters rather than use - // a string literal. Only write 25 bytes per line. - static const int kBytesPerLine = 25; - for (int i = 0; i < file_data.size();) { - for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) { - printer->Print("'$char$', ", "char", - CEscape(file_data.substr(i, 1))); - } - printer->Print("\n"); - } - } else { - // Only write 40 bytes per line. - static const int kBytesPerLine = 40; - for (int i = 0; i < file_data.size(); i += kBytesPerLine) { - printer->Print(" \"$data$\"\n", "data", - EscapeTrigraphs(CEscape( - file_data.substr(i, kBytesPerLine)))); - } + void PrintTopLevelDecl(const Formatter& format, + const Options& options) const { + for (const auto& pair : classes_) { + format( + "template<> $dllexport_decl $" + "$1$* Arena::CreateMaybeMessage<$1$>(Arena*);\n", + QualifiedClassName(pair.second, options)); } - - printer->Outdent(); - printer->Print("};\n"); - printer->Print( - "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(\n" - " descriptor, $size$);\n", - "size", SimpleItoa(file_data.size())); - - // Call MessageFactory::InternalRegisterGeneratedFile(). - printer->Print( - "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n" - " \"$filename$\", &protobuf_RegisterTypes);\n", - "filename", file_->name()); } - // Call the AddDescriptors() methods for all of our dependencies, to make - // sure they get added first. - for (int i = 0; i < file_->dependency_count(); i++) { - const FileDescriptor* dependency = file_->dependency(i); - // Print the namespace prefix for the dependency. - string file_namespace = QualifiedFileLevelSymbol( - dependency->package(), FileLevelNamespace(dependency->name())); - // Call its AddDescriptors function. - printer->Print("$file_namespace$::AddDescriptors();\n", "file_namespace", - file_namespace); - } + private: + std::map classes_; + std::map enums_; +}; - printer->Outdent(); - printer->Print( - "}\n" - "} // anonymous namespace\n" - "\n" - "void AddDescriptors() {\n" - " static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n" - " ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);\n" - "}\n"); - - if (StaticInitializersForced(file_, options_)) { - printer->Print( - "// Force AddDescriptors() to be called at dynamic initialization " - "time.\n" - "struct StaticDescriptorInitializer {\n" - " StaticDescriptorInitializer() {\n" - " AddDescriptors();\n" - " }\n" - "} static_descriptor_initializer;\n"); +static void PublicImportDFS(const FileDescriptor* fd, + std::unordered_set* fd_set) { + for (int i = 0; i < fd->public_dependency_count(); i++) { + const FileDescriptor* dep = fd->public_dependency(i); + if (fd_set->insert(dep).second) PublicImportDFS(dep, fd_set); } } -void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) { - if (package_parts_.size() > 0) printer->Print("\n"); - - for (int i = 0; i < package_parts_.size(); i++) { - printer->Print("namespace $part$ {\n", - "part", package_parts_[i]); +void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) { + Formatter format(printer, variables_); + std::vector classes; + std::vector enums; + + FlattenMessagesInFile(file_, &classes); // All messages need forward decls. + + if (options_.proto_h) { // proto.h needs extra forward declarations. + // All classes / enums referred to as field members + std::vector fields; + ListAllFields(file_, &fields); + for (int i = 0; i < fields.size(); i++) { + classes.push_back(fields[i]->containing_type()); + classes.push_back(fields[i]->message_type()); + enums.push_back(fields[i]->enum_type()); + } + ListAllTypesForServices(file_, &classes); } -} -void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) { - if (package_parts_.size() > 0) printer->Print("\n"); + // Calculate the set of files whose definitions we get through include. + // No need to forward declare types that are defined in these. + std::unordered_set public_set; + PublicImportDFS(file_, &public_set); - for (int i = package_parts_.size() - 1; i >= 0; i--) { - printer->Print("} // namespace $part$\n", - "part", package_parts_[i]); + std::map decls; + for (int i = 0; i < classes.size(); i++) { + const Descriptor* d = classes[i]; + if (d && !public_set.count(d->file())) + decls[Namespace(d, options_)].AddMessage(d); } -} - -void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) { - ForwardDeclarations decls; - FillForwardDeclarations(&decls); - decls.Print(printer, options_); -} - -void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) { - for (int i = 0; i < package_parts_.size(); i++) { - decls = decls->AddOrGetNamespace(package_parts_[i]); + for (int i = 0; i < enums.size(); i++) { + const EnumDescriptor* d = enums[i]; + if (d && !public_set.count(d->file())) + decls[Namespace(d, options_)].AddEnum(d); } - // Generate enum definitions. - for (int i = 0; i < enum_generators_.size(); i++) { - enum_generators_[i]->FillForwardDeclaration(&decls->enums()); + + { + NamespaceOpener ns(format); + for (const auto& pair : decls) { + ns.ChangeTo(pair.first); + pair.second.Print(format, options_); + } } - // Generate forward declarations of classes. - for (int i = 0; i < message_generators_.size(); i++) { - message_generators_[i]->FillMessageForwardDeclarations( - &decls->classes()); + format("PROTOBUF_NAMESPACE_OPEN\n"); + for (const auto& pair : decls) { + pair.second.PrintTopLevelDecl(format, options_); } + format("PROTOBUF_NAMESPACE_CLOSE\n"); } -void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer, - const string& filename_identifier) { +void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer, bool pb_h) { + Formatter format(printer, variables_); // Generate top of header. - printer->Print( + format( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" "// source: $filename$\n" "\n" - "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n" - "#define PROTOBUF_$filename_identifier$__INCLUDED\n" + "#ifndef $1$\n" + "#define $1$\n" "\n" + "#include \n" "#include \n", - "filename", file_->name(), "filename_identifier", filename_identifier); - printer->Print("\n"); + IncludeGuard(file_, pb_h, options_)); + if (!options_.opensource_runtime && !enum_generators_.empty()) { + // Add header to provide std::is_integral for safe Enum_Name() function. + format("#include \n"); + } + format("\n"); } -void FileGenerator::GenerateBottomHeaderGuard( - io::Printer* printer, const string& filename_identifier) { - printer->Print( - "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n", - "filename_identifier", filename_identifier); +void FileGenerator::GenerateBottomHeaderGuard(io::Printer* printer, bool pb_h) { + Formatter format(printer, variables_); + format("#endif // $GOOGLE_PROTOBUF$_INCLUDED_$1$\n", + IncludeGuard(file_, pb_h, options_)); } void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { - - printer->Print( - "#include \n" - "\n"); - - // Verify the protobuf library header version is compatible with the protoc - // version before going any further. - printer->Print( - "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n" - "#error This file was generated by a newer version of protoc which is\n" - "#error incompatible with your Protocol Buffer headers. Please update\n" - "#error your headers.\n" - "#endif\n" - "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n" - "#error This file was generated by an older version of protoc which is\n" - "#error incompatible with your Protocol Buffer headers. Please\n" - "#error regenerate this file with a newer version of protoc.\n" - "#endif\n" - "\n", - "min_header_version", - SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc), - "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION)); + Formatter format(printer, variables_); + if (UsingImplicitWeakFields(file_, options_)) { + IncludeFile("net/proto2/public/implicit_weak_message.h", printer); + } + if (HasWeakFields(file_, options_)) { + GOOGLE_CHECK(!options_.opensource_runtime); + IncludeFile("net/proto2/public/weak_field_map.h", printer); + } + if (HasLazyFields(file_, options_)) { + GOOGLE_CHECK(!options_.opensource_runtime); + IncludeFile("net/proto2/public/lazy_field.h", printer); + } + + if (options_.opensource_runtime) { + // Verify the protobuf library header version is compatible with the protoc + // version before going any further. + IncludeFile("net/proto2/public/port_def.inc", printer); + format( + "#if PROTOBUF_VERSION < $1$\n" + "#error This file was generated by a newer version of protoc which is\n" + "#error incompatible with your Protocol Buffer headers. Please update\n" + "#error your headers.\n" + "#endif\n" + "#if $2$ < PROTOBUF_MIN_PROTOC_VERSION\n" + "#error This file was generated by an older version of protoc which " + "is\n" + "#error incompatible with your Protocol Buffer headers. Please\n" + "#error regenerate this file with a newer version of protoc.\n" + "#endif\n" + "\n", + PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC, // 1 + PROTOBUF_VERSION); // 2 + IncludeFile("net/proto2/public/port_undef.inc", printer); + } // OK, it's now safe to #include other files. - printer->Print( - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n"); + IncludeFile("net/proto2/io/public/coded_stream.h", printer); + IncludeFile("net/proto2/public/arena.h", printer); + IncludeFile("net/proto2/public/arenastring.h", printer); + IncludeFile("net/proto2/public/generated_message_table_driven.h", printer); + IncludeFile("net/proto2/public/generated_message_util.h", printer); + IncludeFile("net/proto2/public/metadata_lite.h", printer); if (HasDescriptorMethods(file_, options_)) { - printer->Print( - "#include \n"); - } else { - printer->Print( - "#include \n"); + IncludeFile("net/proto2/public/generated_message_reflection.h", printer); } if (!message_generators_.empty()) { if (HasDescriptorMethods(file_, options_)) { - printer->Print( - "#include \n"); + IncludeFile("net/proto2/public/message.h", printer); } else { - printer->Print( - "#include \n"); + IncludeFile("net/proto2/public/message_lite.h", printer); + } + } + if (options_.opensource_runtime) { + // Open-source relies on unconditional includes of these. + IncludeFileAndExport("net/proto2/public/repeated_field.h", printer); + IncludeFileAndExport("net/proto2/public/extension_set.h", printer); + } else { + // Google3 includes these files only when they are necessary. + if (HasExtensionsOrExtendableMessage(file_)) { + IncludeFileAndExport("net/proto2/public/extension_set.h", printer); + } + if (HasRepeatedFields(file_)) { + IncludeFileAndExport("net/proto2/public/repeated_field.h", printer); + } + if (HasStringPieceFields(file_, options_)) { + IncludeFile("net/proto2/public/string_piece_field_support.h", printer); + } + if (HasCordFields(file_, options_)) { + format("#include \"third_party/absl/strings/cord.h\"\n"); } } - printer->Print( - "#include " - " // IWYU pragma: export\n" - "#include " - " // IWYU pragma: export\n"); if (HasMapFields(file_)) { - printer->Print( - "#include " - " // IWYU pragma: export\n"); + IncludeFileAndExport("net/proto2/public/map.h", printer); if (HasDescriptorMethods(file_, options_)) { - printer->Print("#include \n"); - printer->Print("#include \n"); + IncludeFile("net/proto2/public/map_entry.h", printer); + IncludeFile("net/proto2/public/map_field_inl.h", printer); } else { - printer->Print("#include \n"); - printer->Print("#include \n"); + IncludeFile("net/proto2/public/map_entry_lite.h", printer); + IncludeFile("net/proto2/public/map_field_lite.h", printer); } } if (HasEnumDefinitions(file_)) { if (HasDescriptorMethods(file_, options_)) { - printer->Print( - "#include \n"); + IncludeFile("net/proto2/public/generated_enum_reflection.h", printer); } else { - printer->Print( - "#include \n"); + IncludeFile("net/proto2/public/generated_enum_util.h", printer); } } if (HasGenericServices(file_, options_)) { - printer->Print( - "#include \n"); + IncludeFile("net/proto2/public/service.h", printer); } if (UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) { - printer->Print( - "#include \n"); - } - - - if (IsAnyMessage(file_)) { - printer->Print( - "#include \n"); + IncludeFile("net/proto2/public/unknown_field_set.h", printer); } } void FileGenerator::GenerateMetadataPragma(io::Printer* printer, - const string& info_path) { + const std::string& info_path) { + Formatter format(printer, variables_); if (!info_path.empty() && !options_.annotation_pragma_name.empty() && !options_.annotation_guard_name.empty()) { - printer->Print( + format.Set("guard", options_.annotation_guard_name); + format.Set("pragma", options_.annotation_pragma_name); + format.Set("info_path", info_path); + format( "#ifdef $guard$\n" "#pragma $pragma$ \"$info_path$\"\n" - "#endif // $guard$\n", - "guard", options_.annotation_guard_name, "pragma", - options_.annotation_pragma_name, "info_path", info_path); + "#endif // $guard$\n"); } } void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) { - std::set public_import_names; - for (int i = 0; i < file_->public_dependency_count(); i++) { - public_import_names.insert(file_->public_dependency(i)->name()); - } - + Formatter format(printer, variables_); for (int i = 0; i < file_->dependency_count(); i++) { - const bool use_system_include = IsWellKnownMessage(file_->dependency(i)); - const string& name = file_->dependency(i)->name(); - bool public_import = (public_import_names.count(name) != 0); + std::string basename = StripProto(file_->dependency(i)->name()); + + // Do not import weak deps. + if (IsDepWeak(file_->dependency(i))) continue; + if (IsBootstrapProto(options_, file_)) { + GetBootstrapBasename(options_, basename, &basename); + } - printer->Print( - "#include $left$$dependency$.pb.h$right$$iwyu$\n", - "dependency", StripProto(name), - "iwyu", (public_import) ? " // IWYU pragma: export" : "", - "left", use_system_include ? "<" : "\"", - "right", use_system_include ? ">" : "\""); + format("#include $1$\n", + CreateHeaderInclude(basename + ".pb.h", file_->dependency(i))); } } void FileGenerator::GenerateGlobalStateFunctionDeclarations( io::Printer* printer) { - // Forward-declare the AddDescriptors, AssignDescriptors - // functions, so that we can declare them to be friends of each class. - printer->Print( + Formatter format(printer, variables_); + // Forward-declare the DescriptorTable because this is referenced by .pb.cc + // files depending on this file. + // + // The TableStruct is also outputted in weak_message_field.cc, because the + // weak fields must refer to table struct but cannot include the header. + // Also it annotates extra weak attributes. + // TODO(gerbens) make sure this situation is handled better. + format( "\n" - "namespace $file_namespace$ {\n" - "// Internal implementation detail -- do not call these.\n" - "struct $dllexport_decl$TableStruct {\n" - " static const ::google::protobuf::internal::ParseTableField entries[];\n" - " static const ::google::protobuf::internal::AuxillaryParseTableField aux[];\n" - " static const ::google::protobuf::internal::ParseTable schema[];\n" - " static const ::google::protobuf::uint32 offsets[];\n" - " static const ::google::protobuf::internal::FieldMetadata field_metadata[];\n" - " static const ::google::protobuf::internal::SerializationTable " + "// Internal implementation detail -- do not use these members.\n" + "struct $dllexport_decl $$tablename$ {\n" + // These tables describe how to serialize and parse messages. Used + // for table driven code. + " static const ::$proto_ns$::internal::ParseTableField entries[]\n" + " PROTOBUF_SECTION_VARIABLE(protodesc_cold);\n" + " static const ::$proto_ns$::internal::AuxiliaryParseTableField aux[]\n" + " PROTOBUF_SECTION_VARIABLE(protodesc_cold);\n" + " static const ::$proto_ns$::internal::ParseTable schema[$1$]\n" + " PROTOBUF_SECTION_VARIABLE(protodesc_cold);\n" + " static const ::$proto_ns$::internal::FieldMetadata field_metadata[];\n" + " static const ::$proto_ns$::internal::SerializationTable " "serialization_table[];\n" - // The following function(s) need to be able to access private members of - // the messages defined in the file. So we make them static members. - // This is the internal implementation of InitDefaults. It should only - // be called by InitDefaults which makes sure it will be called only once. - " static void InitDefaultsImpl();\n" - "};\n" - "void $dllexport_decl$AddDescriptors();\n" - "void $dllexport_decl$InitDefaults();\n" - "} // namespace $file_namespace$\n", - "file_namespace", FileLevelNamespace(file_->name()), "dllexport_decl", - options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " "); + " static const $uint32$ offsets[];\n" + "};\n", + std::max(size_t(1), message_generators_.size())); + if (HasDescriptorMethods(file_, options_)) { + format( + "extern $dllexport_decl $const ::$proto_ns$::internal::DescriptorTable " + "$desc_table$;\n" + "$dllexport_decl $::$proto_ns$::Metadata " + "$desc_table$_metadata_getter(int index);\n"); + } } void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) { + Formatter format(printer, variables_); // Generate class definitions. for (int i = 0; i < message_generators_.size(); i++) { if (i > 0) { - printer->Print("\n"); - printer->Print(kThinSeparator); - printer->Print("\n"); + format("\n"); + format(kThinSeparator); + format("\n"); } message_generators_[i]->GenerateClassDefinition(printer); } @@ -1161,113 +1315,77 @@ void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) { } void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) { + Formatter format(printer, variables_); if (HasGenericServices(file_, options_)) { // Generate service definitions. for (int i = 0; i < service_generators_.size(); i++) { if (i > 0) { - printer->Print("\n"); - printer->Print(kThinSeparator); - printer->Print("\n"); + format("\n"); + format(kThinSeparator); + format("\n"); } service_generators_[i]->GenerateDeclarations(printer); } - printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); + format("\n"); + format(kThickSeparator); + format("\n"); } } void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) { // Declare extension identifiers. These are in global scope and so only // the global scope extensions. - for (int i = 0; i < file_->extension_count(); i++) { - extension_generators_owner_[i]->GenerateDeclaration(printer); + for (auto& extension_generator : extension_generators_) { + if (extension_generator->IsScoped()) continue; + extension_generator->GenerateDeclaration(printer); } } void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) { - // An aside about inline functions in .proto.h mode: - // - // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally - // moving much of the inline functions to the .pb.cc file, which can be a - // significant performance benefit for compilation time, at the expense - // of non-inline function calls. - // - // However, in .proto.h mode, the definition of the internal dependent - // base class must remain in the header, and can never be out-lined. The - // dependent base class also needs access to has-bit manipuation - // functions, so the has-bit functions must be unconditionally inlined in - // proto_h mode. - // - // This gives us three flavors of functions: - // - // 1. Functions on the message not used by the internal dependent base - // class: in .proto.h mode, only some functions are defined on the - // message class; others are defined on the dependent base class. - // These are guarded and can be out-lined. These are generated by - // GenerateInlineMethods, and include has_* bit functions in - // non-proto_h mode. - // - // 2. Functions on the internal dependent base class: these functions - // are dependent on a template parameter, so they always need to - // remain in the header. - // - // 3. Functions on the message that are used by the dependent base: the - // dependent base class down casts itself to the message - // implementation class to access these functions (the has_* bit - // manipulation functions). Unlike #1, these functions must - // unconditionally remain in the header. These are emitted by - // GenerateDependentInlineMethods, even though they are not actually - // dependent. - - printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n"); + Formatter format(printer, variables_); // TODO(gerbens) remove pragmas when gcc is no longer used. Current version // of gcc fires a bogus error when compiled with strict-aliasing. - printer->Print( - "#ifdef __GNUC__\n" - " #pragma GCC diagnostic push\n" - " #pragma GCC diagnostic ignored \"-Wstrict-aliasing\"\n" - "#endif // __GNUC__\n"); + format( + "#ifdef __GNUC__\n" + " #pragma GCC diagnostic push\n" + " #pragma GCC diagnostic ignored \"-Wstrict-aliasing\"\n" + "#endif // __GNUC__\n"); // Generate class inline methods. for (int i = 0; i < message_generators_.size(); i++) { if (i > 0) { - printer->Print(kThinSeparator); - printer->Print("\n"); + format(kThinSeparator); + format("\n"); } - message_generators_[i]->GenerateInlineMethods(printer, - /* is_inline = */ true); + message_generators_[i]->GenerateInlineMethods(printer); } - printer->Print( - "#ifdef __GNUC__\n" - " #pragma GCC diagnostic pop\n" - "#endif // __GNUC__\n"); - printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n"); + format( + "#ifdef __GNUC__\n" + " #pragma GCC diagnostic pop\n" + "#endif // __GNUC__\n"); for (int i = 0; i < message_generators_.size(); i++) { if (i > 0) { - printer->Print(kThinSeparator); - printer->Print("\n"); + format(kThinSeparator); + format("\n"); } - // Methods of the dependent base class must always be inline in the header. - message_generators_[i]->GenerateDependentInlineMethods(printer); } } void FileGenerator::GenerateProto2NamespaceEnumSpecializations( io::Printer* printer) { + Formatter format(printer, variables_); // Emit GetEnumDescriptor specializations into google::protobuf namespace: if (HasEnumDefinitions(file_)) { - printer->Print( - "\n" - "namespace google {\nnamespace protobuf {\n" - "\n"); - for (int i = 0; i < enum_generators_.size(); i++) { - enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + format("\n"); + { + NamespaceOpener proto_ns(ProtobufNamespace(options_), format); + format("\n"); + for (int i = 0; i < enum_generators_.size(); i++) { + enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } + format("\n"); } - printer->Print( - "\n" - "} // namespace protobuf\n} // namespace google\n"); } } diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h index e10fe2f3d0422..35a9085fd4c3d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.h +++ b/src/google/protobuf/compiler/cpp/cpp_file.h @@ -35,33 +35,35 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__ +#include #include -#ifndef _SHARED_PTR_H -#include -#endif +#include #include #include #include #include #include #include +#include namespace google { namespace protobuf { - class FileDescriptor; // descriptor.h - namespace io { - class Printer; // printer.h - } +class FileDescriptor; // descriptor.h +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace cpp { -class EnumGenerator; // enum.h -class MessageGenerator; // message.h -class ServiceGenerator; // service.h -class ExtensionGenerator; // extension.h +class EnumGenerator; // enum.h +class MessageGenerator; // message.h +class ServiceGenerator; // service.h +class ExtensionGenerator; // extension.h class FileGenerator { public: @@ -72,40 +74,56 @@ class FileGenerator { // Shared code between the two header generators below. void GenerateHeader(io::Printer* printer); - // info_path, if non-empty, should be the path (relative to printer's output) - // to the metadata file describing this proto header. - void GenerateProtoHeader(io::Printer* printer, - const string& info_path); - // info_path, if non-empty, should be the path (relative to printer's output) - // to the metadata file describing this PB header. - void GeneratePBHeader(io::Printer* printer, - const string& info_path); + // info_path, if non-empty, should be the path (relative to printer's + // output) to the metadata file describing this proto header. + void GenerateProtoHeader(io::Printer* printer, const std::string& info_path); + // info_path, if non-empty, should be the path (relative to printer's + // output) to the metadata file describing this PB header. + void GeneratePBHeader(io::Printer* printer, const std::string& info_path); void GenerateSource(io::Printer* printer); + int NumMessages() const { return message_generators_.size(); } + // Similar to GenerateSource but generates only one message + void GenerateSourceForMessage(int idx, io::Printer* printer); + void GenerateGlobalSource(io::Printer* printer); + private: // Internal type used by GenerateForwardDeclarations (defined in file.cc). class ForwardDeclarations; + struct CrossFileReferences; - // Generate the BuildDescriptors() procedure, which builds all descriptors - // for types defined in the file. - void GenerateBuildDescriptors(io::Printer* printer); - - void GenerateNamespaceOpeners(io::Printer* printer); - void GenerateNamespaceClosers(io::Printer* printer); + void IncludeFile(const std::string& google3_name, io::Printer* printer) { + DoIncludeFile(google3_name, false, printer); + } + void IncludeFileAndExport(const std::string& google3_name, + io::Printer* printer) { + DoIncludeFile(google3_name, true, printer); + } + void DoIncludeFile(const std::string& google3_name, bool do_export, + io::Printer* printer); + + std::string CreateHeaderInclude(const std::string& basename, + const FileDescriptor* file); + void GetCrossFileReferencesForField(const FieldDescriptor* field, + CrossFileReferences* refs); + void GetCrossFileReferencesForFile(const FileDescriptor* file, + CrossFileReferences* refs); + void GenerateInternalForwardDeclarations(const CrossFileReferences& refs, + io::Printer* printer); + void GenerateSourceIncludes(io::Printer* printer); + void GenerateSourceDefaultInstance(int idx, io::Printer* printer); + + void GenerateInitForSCC(const SCC* scc, const CrossFileReferences& refs, + io::Printer* printer); + void GenerateTables(io::Printer* printer); + void GenerateReflectionInitializationCode(io::Printer* printer); // For other imports, generates their forward-declarations. void GenerateForwardDeclarations(io::Printer* printer); - // Internal helper used by GenerateForwardDeclarations: fills 'decls' - // with all necessary forward-declarations for this file and its - // transient depednencies. - void FillForwardDeclarations(ForwardDeclarations* decls); - // Generates top or bottom of a header file. - void GenerateTopHeaderGuard(io::Printer* printer, - const string& filename_identifier); - void GenerateBottomHeaderGuard(io::Printer* printer, - const string& filename_identifier); + void GenerateTopHeaderGuard(io::Printer* printer, bool pb_h); + void GenerateBottomHeaderGuard(io::Printer* printer, bool pb_h); // Generates #include directives. void GenerateLibraryIncludes(io::Printer* printer); @@ -113,7 +131,8 @@ class FileGenerator { // Generate a pragma to pull in metadata using the given info_path (if // non-empty). info_path should be relative to printer's output. - void GenerateMetadataPragma(io::Printer* printer, const string& info_path); + void GenerateMetadataPragma(io::Printer* printer, + const std::string& info_path); // Generates a couple of different pieces before definitions: void GenerateGlobalStateFunctionDeclarations(io::Printer* printer); @@ -129,44 +148,43 @@ class FileGenerator { // Generates extension identifiers. void GenerateExtensionIdentifiers(io::Printer* printer); - // Generates inline function defintions. + // Generates inline function definitions. void GenerateInlineFunctionDefinitions(io::Printer* printer); void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer); - // Sometimes the names we use in a .proto file happen to be defined as macros - // on some platforms (e.g., macro/minor used in plugin.proto are defined as - // macros in sys/types.h on FreeBSD and a few other platforms). To make the - // generated code compile on these platforms, we either have to undef the - // macro for these few platforms, or rename the field name for all platforms. - // Since these names are part of protobuf public API, renaming is generally - // a breaking change so we prefer the #undef approach. + // Sometimes the names we use in a .proto file happen to be defined as + // macros on some platforms (e.g., macro/minor used in plugin.proto are + // defined as macros in sys/types.h on FreeBSD and a few other platforms). + // To make the generated code compile on these platforms, we either have to + // undef the macro for these few platforms, or rename the field name for all + // platforms. Since these names are part of protobuf public API, renaming is + // generally a breaking change so we prefer the #undef approach. void GenerateMacroUndefs(io::Printer* printer); + bool IsDepWeak(const FileDescriptor* dep) const { + if (weak_deps_.count(dep) != 0) { + GOOGLE_CHECK(!options_.opensource_runtime); + return true; + } + return false; + } + + std::set weak_deps_; + const FileDescriptor* file_; const Options options_; - SCCAnalyzer scc_analyzer_; + MessageSCCAnalyzer scc_analyzer_; + + std::map variables_; // Contains the post-order walk of all the messages (and child messages) in // this file. If you need a pre-order walk just reverse iterate. - std::vector message_generators_; - std::vector enum_generators_; - std::vector service_generators_; - std::vector extension_generators_; - - // These members are just for owning (and thus proper deleting). Some of the - // message_ and enum_generators above are owned by child messages. - google::protobuf::scoped_array > - message_generators_owner_; - google::protobuf::scoped_array > enum_generators_owner_; - google::protobuf::scoped_array > - service_generators_owner_; - google::protobuf::scoped_array > - extension_generators_owner_; - - // E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}. - std::vector package_parts_; + std::vector> message_generators_; + std::vector> enum_generators_; + std::vector> service_generators_; + std::vector> extension_generators_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); }; @@ -174,6 +192,6 @@ class FileGenerator { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc index 68abd0ef55901..2c45ca8fa289e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.cc +++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc @@ -34,18 +34,16 @@ #include -#include #include -#ifndef _SHARED_PTR_H -#include -#endif #include +#include +#include #include #include +#include #include #include -#include namespace google { namespace protobuf { @@ -56,21 +54,15 @@ CppGenerator::CppGenerator() {} CppGenerator::~CppGenerator() {} bool CppGenerator::Generate(const FileDescriptor* file, - const string& parameter, + const std::string& parameter, GeneratorContext* generator_context, - string* error) const { - std::vector > options; + std::string* error) const { + std::vector > options; ParseGeneratorParameter(parameter, &options); // ----------------------------------------------------------------- // parse generator options - // TODO(kenton): If we ever have more options, we may want to create a - // class that encapsulates them which we can pass down to all the - // generator classes. Currently we pass dllexport_decl down to all of - // them via the constructors, but we don't want to have to add another - // constructor parameter for every option. - // If the dllexport_decl option is passed to the compiler, we need to write // it in front of every symbol that should be exported if this .proto is // compiled into a Windows DLL. E.g., if the user invokes the protocol @@ -85,6 +77,9 @@ bool CppGenerator::Generate(const FileDescriptor* file, // Options file_options; + file_options.opensource_runtime = opensource_runtime_; + file_options.runtime_include_base = runtime_include_base_; + for (int i = 0; i < options.size(); i++) { if (options[i].first == "dllexport_decl") { file_options.dllexport_decl = options[i].second; @@ -96,8 +91,19 @@ bool CppGenerator::Generate(const FileDescriptor* file, file_options.annotation_pragma_name = options[i].second; } else if (options[i].first == "annotation_guard_name") { file_options.annotation_guard_name = options[i].second; + } else if (options[i].first == "speed") { + file_options.enforce_mode = EnforceOptimizeMode::kSpeed; + } else if (options[i].first == "code_size") { + file_options.enforce_mode = EnforceOptimizeMode::kCodeSize; } else if (options[i].first == "lite") { - file_options.enforce_lite = true; + file_options.enforce_mode = EnforceOptimizeMode::kLiteRuntime; + } else if (options[i].first == "lite_implicit_weak_fields") { + file_options.enforce_mode = EnforceOptimizeMode::kLiteRuntime; + file_options.lite_implicit_weak_fields = true; + if (!options[i].second.empty()) { + file_options.num_cc_files = + strto32(options[i].second.c_str(), NULL, 10); + } } else if (options[i].first == "table_driven_parsing") { file_options.table_driven_parsing = true; } else if (options[i].first == "table_driven_serialization") { @@ -108,57 +114,98 @@ bool CppGenerator::Generate(const FileDescriptor* file, } } + // The safe_boundary_check option controls behavior for Google-internal + // protobuf APIs. + if (file_options.safe_boundary_check && file_options.opensource_runtime) { + *error = + "The safe_boundary_check option is not supported outside of Google."; + return false; + } + // ----------------------------------------------------------------- - string basename = StripProto(file->name()); + std::string basename = StripProto(file->name()); + + if (MaybeBootstrap(file_options, generator_context, file_options.bootstrap, + &basename)) { + return true; + } FileGenerator file_generator(file, file_options); // Generate header(s). if (file_options.proto_h) { - google::protobuf::scoped_ptr output( + std::unique_ptr output( generator_context->Open(basename + ".proto.h")); GeneratedCodeInfo annotations; io::AnnotationProtoCollector annotation_collector( &annotations); - string info_path = basename + ".proto.h.meta"; - io::Printer printer(output.get(), '$', file_options.annotate_headers - ? &annotation_collector - : NULL); + std::string info_path = basename + ".proto.h.meta"; + io::Printer printer( + output.get(), '$', + file_options.annotate_headers ? &annotation_collector : NULL); file_generator.GenerateProtoHeader( &printer, file_options.annotate_headers ? info_path : ""); if (file_options.annotate_headers) { - google::protobuf::scoped_ptr info_output( + std::unique_ptr info_output( generator_context->Open(info_path)); annotations.SerializeToZeroCopyStream(info_output.get()); } } - basename.append(".pb"); { - google::protobuf::scoped_ptr output( - generator_context->Open(basename + ".h")); + std::unique_ptr output( + generator_context->Open(basename + ".pb.h")); GeneratedCodeInfo annotations; io::AnnotationProtoCollector annotation_collector( &annotations); - string info_path = basename + ".h.meta"; - io::Printer printer(output.get(), '$', file_options.annotate_headers - ? &annotation_collector - : NULL); + std::string info_path = basename + ".pb.h.meta"; + io::Printer printer( + output.get(), '$', + file_options.annotate_headers ? &annotation_collector : NULL); file_generator.GeneratePBHeader( &printer, file_options.annotate_headers ? info_path : ""); if (file_options.annotate_headers) { - google::protobuf::scoped_ptr info_output( + std::unique_ptr info_output( generator_context->Open(info_path)); annotations.SerializeToZeroCopyStream(info_output.get()); } } - // Generate cc file. - { - google::protobuf::scoped_ptr output( - generator_context->Open(basename + ".cc")); + // Generate cc file(s). + if (UsingImplicitWeakFields(file, file_options)) { + { + // This is the global .cc file, containing + // enum/services/tables/reflection + std::unique_ptr output( + generator_context->Open(basename + ".pb.cc")); + io::Printer printer(output.get(), '$'); + file_generator.GenerateGlobalSource(&printer); + } + + int num_cc_files = file_generator.NumMessages(); + + // If we're using implicit weak fields then we allow the user to + // optionally specify how many files to generate, not counting the global + // pb.cc file. If we have more files than messages, then some files will + // be generated as empty placeholders. + if (file_options.num_cc_files > 0) { + GOOGLE_CHECK_LE(file_generator.NumMessages(), file_options.num_cc_files) + << "There must be at least as many numbered .cc files as messages."; + num_cc_files = file_options.num_cc_files; + } + for (int i = 0; i < num_cc_files; i++) { + std::unique_ptr output( + generator_context->Open(StrCat(basename, ".out/", i, ".cc"))); + io::Printer printer(output.get(), '$'); + if (i < file_generator.NumMessages()) { + file_generator.GenerateSourceForMessage(i, &printer); + } + } + } else { + std::unique_ptr output( + generator_context->Open(basename + ".pb.cc")); io::Printer printer(output.get(), '$'); file_generator.GenerateSource(&printer); } diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.h b/src/google/protobuf/compiler/cpp/cpp_generator.h index 3d517cf4a5ba1..97e848dc4f50e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.h +++ b/src/google/protobuf/compiler/cpp/cpp_generator.h @@ -40,6 +40,8 @@ #include #include +#include + namespace google { namespace protobuf { namespace compiler { @@ -49,24 +51,56 @@ namespace cpp { // header. If you create your own protocol compiler binary and you want // it to support C++ output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT CppGenerator : public CodeGenerator { +class PROTOC_EXPORT CppGenerator : public CodeGenerator { public: CppGenerator(); ~CppGenerator(); + enum class Runtime { + kGoogle3, // Use the internal google3 runtime. + kOpensource, // Use the open-source runtime. + + // Use the open-source runtime with google3 #include paths. We make these + // absolute to avoid ambiguity, so the runtime will be #included like: + // #include "third_party/protobuf/.../google/protobuf/message.h" + kOpensourceGoogle3 + }; + + void set_opensource_runtime(bool opensource) { + opensource_runtime_ = opensource; + } + + // If set to a non-empty string, generated code will do: + // #include "/google/protobuf/message.h" + // instead of: + // #include + // This has no effect if opensource_runtime = false. + void set_runtime_include_base(const std::string& base) { + runtime_include_base_ = base; + } + // implements CodeGenerator ---------------------------------------- - bool Generate(const FileDescriptor* file, - const string& parameter, + bool Generate(const FileDescriptor* file, const std::string& parameter, GeneratorContext* generator_context, - string* error) const; + std::string* error) const override; + + uint64_t GetSupportedFeatures() const override { + // We don't fully support this yet, but this is needed to unblock the tests, + // and we will have full support before the experimental flag is removed. + return FEATURE_PROTO3_OPTIONAL; + } private: + bool opensource_runtime_ = true; + std::string runtime_include_base_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CppGenerator); }; } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 0095979634014..5825af2181680 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -32,20 +32,32 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include + +#include #include #include +#include +#include #include -#include -#include #include -#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include #include #include +#include - - +#include namespace google { namespace protobuf { @@ -56,59 +68,214 @@ namespace { static const char kAnyMessageName[] = "Any"; static const char kAnyProtoFile[] = "google/protobuf/any.proto"; -static const char kGoogleProtobufPrefix[] = "google/protobuf/"; - -string DotsToUnderscores(const string& name) { - return StringReplace(name, ".", "_", true); -} -string DotsToColons(const string& name) { +std::string DotsToColons(const std::string& name) { return StringReplace(name, ".", "::", true); } -const char* const kKeywordList[] = { - "alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor", - "bool", "break", "case", "catch", "char", "class", "compl", "const", - "constexpr", "const_cast", "continue", "decltype", "default", "delete", "do", - "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", - "false", "float", "for", "friend", "goto", "if", "inline", "int", "long", - "mutable", "namespace", "new", "noexcept", "not", "not_eq", "NULL", - "operator", "or", "or_eq", "private", "protected", "public", "register", - "reinterpret_cast", "return", "short", "signed", "sizeof", "static", - "static_assert", "static_cast", "struct", "switch", "template", "this", - "thread_local", "throw", "true", "try", "typedef", "typeid", "typename", - "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t", - "while", "xor", "xor_eq" -}; - -hash_set MakeKeywordsMap() { - hash_set result; - for (int i = 0; i < GOOGLE_ARRAYSIZE(kKeywordList); i++) { - result.insert(kKeywordList[i]); +static const char* const kKeywordList[] = { // + "NULL", + "alignas", + "alignof", + "and", + "and_eq", + "asm", + "auto", + "bitand", + "bitor", + "bool", + "break", + "case", + "catch", + "char", + "class", + "compl", + "const", + "constexpr", + "const_cast", + "continue", + "decltype", + "default", + "delete", + "do", + "double", + "dynamic_cast", + "else", + "enum", + "explicit", + "export", + "extern", + "false", + "float", + "for", + "friend", + "goto", + "if", + "inline", + "int", + "long", + "mutable", + "namespace", + "new", + "noexcept", + "not", + "not_eq", + "nullptr", + "operator", + "or", + "or_eq", + "private", + "protected", + "public", + "register", + "reinterpret_cast", + "return", + "short", + "signed", + "sizeof", + "static", + "static_assert", + "static_cast", + "struct", + "switch", + "template", + "this", + "thread_local", + "throw", + "true", + "try", + "typedef", + "typeid", + "typename", + "union", + "unsigned", + "using", + "virtual", + "void", + "volatile", + "wchar_t", + "while", + "xor", + "xor_eq"}; + +static std::unordered_set* MakeKeywordsMap() { + auto* result = new std::unordered_set(); + for (const auto keyword : kKeywordList) { + result->emplace(keyword); } return result; } -hash_set kKeywords = MakeKeywordsMap(); +static std::unordered_set& kKeywords = *MakeKeywordsMap(); + +// Encode [0..63] as 'A'-'Z', 'a'-'z', '0'-'9', '_' +char Base63Char(int value) { + GOOGLE_CHECK_GE(value, 0); + if (value < 26) return 'A' + value; + value -= 26; + if (value < 26) return 'a' + value; + value -= 26; + if (value < 10) return '0' + value; + GOOGLE_CHECK_EQ(value, 10); + return '_'; +} -// Returns whether the provided descriptor has an extension. This includes its -// nested types. -bool HasExtension(const Descriptor* descriptor) { - if (descriptor->extension_count() > 0) { - return true; +// Given a c identifier has 63 legal characters we can't implement base64 +// encoding. So we return the k least significant "digits" in base 63. +template +std::string Base63(I n, int k) { + std::string res; + while (k-- > 0) { + res += Base63Char(static_cast(n % 63)); + n /= 63; } - for (int i = 0; i < descriptor->nested_type_count(); ++i) { - if (HasExtension(descriptor->nested_type(i))) { - return true; - } + return res; +} + +std::string IntTypeName(const Options& options, const std::string& type) { + if (options.opensource_runtime) { + return "::PROTOBUF_NAMESPACE_ID::" + type; + } else { + return "::" + type; } - return false; +} + +void SetIntVar(const Options& options, const std::string& type, + std::map* variables) { + (*variables)[type] = IntTypeName(options, type); +} + +bool HasInternalAccessors(const FieldOptions::CType ctype) { + return ctype == FieldOptions::STRING || ctype == FieldOptions::CORD; } } // namespace -string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { - string result; +void SetCommonVars(const Options& options, + std::map* variables) { + (*variables)["proto_ns"] = ProtobufNamespace(options); + + // Warning: there is some clever naming/splitting here to avoid extract script + // rewrites. The names of these variables must not be things that the extract + // script will rewrite. That's why we use "CHK" (for example) instead of + // "GOOGLE_CHECK". + if (options.opensource_runtime) { + (*variables)["GOOGLE_PROTOBUF"] = "GOOGLE_PROTOBUF"; + (*variables)["CHK"] = "GOOGLE_CHECK"; + (*variables)["DCHK"] = "GOOGLE_DCHECK"; + } else { + // These values are things the extract script would rewrite if we did not + // split them. It might not strictly matter since we don't generate google3 + // code in open-source. But it's good to prevent surprising things from + // happening. + (*variables)["GOOGLE_PROTOBUF"] = + "GOOGLE3" + "_PROTOBUF"; + (*variables)["CHK"] = + "CH" + "ECK"; + (*variables)["DCHK"] = + "DCH" + "ECK"; + } + + SetIntVar(options, "int8", variables); + SetIntVar(options, "uint8", variables); + SetIntVar(options, "uint32", variables); + SetIntVar(options, "uint64", variables); + SetIntVar(options, "int32", variables); + SetIntVar(options, "int64", variables); + (*variables)["string"] = "std::string"; +} + +void SetUnknkownFieldsVariable(const Descriptor* descriptor, + const Options& options, + std::map* variables) { + std::string proto_ns = ProtobufNamespace(options); + std::string unknown_fields_type; + if (UseUnknownFieldSet(descriptor->file(), options)) { + unknown_fields_type = "::" + proto_ns + "::UnknownFieldSet"; + (*variables)["unknown_fields"] = + "_internal_metadata_.unknown_fields<" + unknown_fields_type + ">(" + + unknown_fields_type + "::default_instance)"; + } else { + unknown_fields_type = + PrimitiveTypeName(options, FieldDescriptor::CPPTYPE_STRING); + (*variables)["unknown_fields"] = "_internal_metadata_.unknown_fields<" + + unknown_fields_type + ">(::" + proto_ns + + "::internal::GetEmptyString)"; + } + (*variables)["unknown_fields_type"] = unknown_fields_type; + (*variables)["have_unknown_fields"] = + "_internal_metadata_.have_unknown_fields()"; + (*variables)["mutable_unknown_fields"] = + "_internal_metadata_.mutable_unknown_fields<" + unknown_fields_type + + ">()"; +} + +std::string UnderscoresToCamelCase(const std::string& input, + bool cap_next_letter) { + std::string result; // Note: I distrust ctype.h due to locales. for (int i = 0; i < input.size(); i++) { if ('a' <= input[i] && input[i] <= 'z') { @@ -133,68 +300,166 @@ string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { } const char kThickSeparator[] = - "// ===================================================================\n"; + "// ===================================================================\n"; const char kThinSeparator[] = - "// -------------------------------------------------------------------\n"; - -string ClassName(const Descriptor* descriptor, bool qualified) { + "// -------------------------------------------------------------------\n"; - // Find "outer", the descriptor of the top-level message in which - // "descriptor" is embedded. - const Descriptor* outer = descriptor; - while (outer->containing_type() != NULL) outer = outer->containing_type(); +bool CanInitializeByZeroing(const FieldDescriptor* field) { + if (field->is_repeated() || field->is_extension()) return false; + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_ENUM: + return field->default_value_enum()->number() == 0; + case FieldDescriptor::CPPTYPE_INT32: + return field->default_value_int32() == 0; + case FieldDescriptor::CPPTYPE_INT64: + return field->default_value_int64() == 0; + case FieldDescriptor::CPPTYPE_UINT32: + return field->default_value_uint32() == 0; + case FieldDescriptor::CPPTYPE_UINT64: + return field->default_value_uint64() == 0; + case FieldDescriptor::CPPTYPE_FLOAT: + return field->default_value_float() == 0; + case FieldDescriptor::CPPTYPE_DOUBLE: + return field->default_value_double() == 0; + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() == false; + default: + return false; + } +} - const string& outer_name = outer->full_name(); - string inner_name = descriptor->full_name().substr(outer_name.size()); +std::string ClassName(const Descriptor* descriptor) { + const Descriptor* parent = descriptor->containing_type(); + std::string res; + if (parent) res += ClassName(parent) + "_"; + res += descriptor->name(); + if (IsMapEntryMessage(descriptor)) res += "_DoNotUse"; + return ResolveKeyword(res); +} - if (qualified) { - return "::" + DotsToColons(outer_name) + DotsToUnderscores(inner_name); +std::string ClassName(const EnumDescriptor* enum_descriptor) { + if (enum_descriptor->containing_type() == nullptr) { + return ResolveKeyword(enum_descriptor->name()); } else { - return outer->name() + DotsToUnderscores(inner_name); + return ClassName(enum_descriptor->containing_type()) + "_" + + enum_descriptor->name(); } } -string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) { - if (enum_descriptor->containing_type() == NULL) { - if (qualified) { - return "::" + DotsToColons(enum_descriptor->full_name()); - } else { - return enum_descriptor->name(); - } - } else { - string result = ClassName(enum_descriptor->containing_type(), qualified); - result += '_'; - result += enum_descriptor->name(); - return result; +std::string QualifiedClassName(const Descriptor* d, const Options& options) { + return QualifiedFileLevelSymbol(d->file(), ClassName(d), options); +} + +std::string QualifiedClassName(const EnumDescriptor* d, + const Options& options) { + return QualifiedFileLevelSymbol(d->file(), ClassName(d), options); +} + +std::string QualifiedClassName(const Descriptor* d) { + return QualifiedClassName(d, Options()); +} + +std::string QualifiedClassName(const EnumDescriptor* d) { + return QualifiedClassName(d, Options()); +} + +std::string ExtensionName(const FieldDescriptor* d) { + if (const Descriptor* scope = d->extension_scope()) + return StrCat(ClassName(scope), "::", ResolveKeyword(d->name())); + return ResolveKeyword(d->name()); +} + +std::string QualifiedExtensionName(const FieldDescriptor* d, + const Options& options) { + GOOGLE_DCHECK(d->is_extension()); + return QualifiedFileLevelSymbol(d->file(), ExtensionName(d), options); +} + +std::string QualifiedExtensionName(const FieldDescriptor* d) { + return QualifiedExtensionName(d, Options()); +} + +std::string Namespace(const std::string& package) { + if (package.empty()) return ""; + return "::" + DotsToColons(package); +} + +std::string Namespace(const FileDescriptor* d, const Options& options) { + std::string ret = Namespace(d->package()); + if (IsWellKnownMessage(d) && options.opensource_runtime) { + // Written with string concatenation to prevent rewriting of + // ::google::protobuf. + ret = StringReplace(ret, + "::google::" + "protobuf", + "PROTOBUF_NAMESPACE_ID", false); } + return ret; } -string DefaultInstanceName(const Descriptor* descriptor) { - string prefix = descriptor->file()->package().empty() ? "" : "::"; - return prefix + DotsToColons(descriptor->file()->package()) + "::_" + - ClassName(descriptor, false) + "_default_instance_"; +std::string Namespace(const Descriptor* d, const Options& options) { + return Namespace(d->file(), options); } -string DependentBaseClassTemplateName(const Descriptor* descriptor) { - return ClassName(descriptor, false) + "_InternalBase"; +std::string Namespace(const FieldDescriptor* d, const Options& options) { + return Namespace(d->file(), options); } -string SuperClassName(const Descriptor* descriptor, const Options& options) { - return HasDescriptorMethods(descriptor->file(), options) - ? "::google::protobuf::Message" - : "::google::protobuf::MessageLite"; +std::string Namespace(const EnumDescriptor* d, const Options& options) { + return Namespace(d->file(), options); } -string DependentBaseDownCast() { - return "reinterpret_cast(this)->"; +std::string DefaultInstanceType(const Descriptor* descriptor, + const Options& options) { + return ClassName(descriptor) + "DefaultTypeInternal"; } -string DependentBaseConstDownCast() { - return "reinterpret_cast(this)->"; +std::string DefaultInstanceName(const Descriptor* descriptor, + const Options& options) { + return "_" + ClassName(descriptor, false) + "_default_instance_"; } -string FieldName(const FieldDescriptor* field) { - string result = field->name(); +std::string DefaultInstancePtr(const Descriptor* descriptor, + const Options& options) { + return DefaultInstanceName(descriptor, options) + "ptr_"; +} + +std::string QualifiedDefaultInstanceName(const Descriptor* descriptor, + const Options& options) { + return QualifiedFileLevelSymbol( + descriptor->file(), DefaultInstanceName(descriptor, options), options); +} + +std::string QualifiedDefaultInstancePtr(const Descriptor* descriptor, + const Options& options) { + return QualifiedDefaultInstanceName(descriptor, options) + "ptr_"; +} + +std::string DescriptorTableName(const FileDescriptor* file, + const Options& options) { + return UniqueName("descriptor_table", file, options); +} + +std::string FileDllExport(const FileDescriptor* file, const Options& options) { + return UniqueName("PROTOBUF_INTERNAL_EXPORT", file, options); +} + +std::string SuperClassName(const Descriptor* descriptor, + const Options& options) { + return "::" + ProtobufNamespace(options) + + (HasDescriptorMethods(descriptor->file(), options) ? "::Message" + : "::MessageLite"); +} + +std::string ResolveKeyword(const std::string& name) { + if (kKeywords.count(name) > 0) { + return name + "_"; + } + return name; +} + +std::string FieldName(const FieldDescriptor* field) { + std::string result = field->name(); LowerString(&result); if (kKeywords.count(result) > 0) { result.append("_"); @@ -202,227 +467,269 @@ string FieldName(const FieldDescriptor* field) { return result; } -string EnumValueName(const EnumValueDescriptor* enum_value) { - string result = enum_value->name(); +std::string EnumValueName(const EnumValueDescriptor* enum_value) { + std::string result = enum_value->name(); if (kKeywords.count(result) > 0) { result.append("_"); } return result; } -string FieldConstantName(const FieldDescriptor *field) { - string field_name = UnderscoresToCamelCase(field->name(), true); - string result = "k" + field_name + "FieldNumber"; +int EstimateAlignmentSize(const FieldDescriptor* field) { + if (field == nullptr) return 0; + if (field->is_repeated()) return 8; + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_BOOL: + return 1; + + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_FLOAT: + return 4; + + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + return 8; + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return -1; // Make compiler happy. +} + +std::string FieldConstantName(const FieldDescriptor* field) { + std::string field_name = UnderscoresToCamelCase(field->name(), true); + std::string result = "k" + field_name + "FieldNumber"; if (!field->is_extension() && field->containing_type()->FindFieldByCamelcaseName( - field->camelcase_name()) != field) { + field->camelcase_name()) != field) { // This field's camelcase name is not unique. As a hack, add the field // number to the constant name. This makes the constant rather useless, // but what can we do? - result += "_" + SimpleItoa(field->number()); + result += "_" + StrCat(field->number()); } return result; } -bool IsFieldDependent(const FieldDescriptor* field) { - if (field->containing_oneof() != NULL && - field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { - return true; - } - if (field->is_map()) { - const Descriptor* map_descriptor = field->message_type(); - for (int i = 0; i < map_descriptor->field_count(); i++) { - if (IsFieldDependent(map_descriptor->field(i))) { - return true; - } - } - return false; - } - if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { - return false; - } - if (field->containing_oneof() != NULL) { - // Oneof fields will always be dependent. - // - // This is a unique case for field codegen. Field generators are - // responsible for generating all the field-specific accessor - // functions, except for the clear_*() function; instead, field - // generators produce inline clearing code. - // - // For non-oneof fields, the Message class uses the inline clearing - // code to define the field's clear_*() function, as well as in the - // destructor. For oneof fields, the Message class generates a much - // more complicated clear_*() function, which clears only the oneof - // member that is set, in addition to clearing methods for each of the - // oneof members individually. - // - // Since oneofs do not have their own generator class, the Message code - // generation logic would be significantly complicated in order to - // split dependent and non-dependent manipulation logic based on - // whether the oneof truly needs to be dependent; so, for oneof fields, - // we just assume it (and its constituents) should be manipulated by a - // dependent base class function. - // - // This is less precise than how dependent message-typed fields are - // handled, but the cost is limited to only the generated code for the - // oneof field, which seems like an acceptable tradeoff. - return true; - } - if (field->file() == field->message_type()->file()) { - return false; - } - return true; +std::string FieldMessageTypeName(const FieldDescriptor* field, + const Options& options) { + // Note: The Google-internal version of Protocol Buffers uses this function + // as a hook point for hacks to support legacy code. + return QualifiedClassName(field->message_type(), options); } -string DependentTypeName(const FieldDescriptor* field) { - return "InternalBase_" + field->name() + "_T"; +std::string StripProto(const std::string& filename) { + /* + * TODO(github/georgthegreat) remove this proxy method + * once Google's internal codebase will become ready + */ + return compiler::StripProto(filename); } -string FieldMessageTypeName(const FieldDescriptor* field) { - // Note: The Google-internal version of Protocol Buffers uses this function - // as a hook point for hacks to support legacy code. - return ClassName(field->message_type(), true); -} +const char* PrimitiveTypeName(FieldDescriptor::CppType type) { + switch (type) { + case FieldDescriptor::CPPTYPE_INT32: + return "::google::protobuf::int32"; + case FieldDescriptor::CPPTYPE_INT64: + return "::google::protobuf::int64"; + case FieldDescriptor::CPPTYPE_UINT32: + return "::google::protobuf::uint32"; + case FieldDescriptor::CPPTYPE_UINT64: + return "::google::protobuf::uint64"; + case FieldDescriptor::CPPTYPE_DOUBLE: + return "double"; + case FieldDescriptor::CPPTYPE_FLOAT: + return "float"; + case FieldDescriptor::CPPTYPE_BOOL: + return "bool"; + case FieldDescriptor::CPPTYPE_ENUM: + return "int"; + case FieldDescriptor::CPPTYPE_STRING: + return "std::string"; + case FieldDescriptor::CPPTYPE_MESSAGE: + return nullptr; -string StripProto(const string& filename) { - if (HasSuffixString(filename, ".protodevel")) { - return StripSuffixString(filename, ".protodevel"); - } else { - return StripSuffixString(filename, ".proto"); + // No default because we want the compiler to complain if any new + // CppTypes are added. } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return nullptr; } -const char* PrimitiveTypeName(FieldDescriptor::CppType type) { +std::string PrimitiveTypeName(const Options& options, + FieldDescriptor::CppType type) { switch (type) { - case FieldDescriptor::CPPTYPE_INT32 : return "::google::protobuf::int32"; - case FieldDescriptor::CPPTYPE_INT64 : return "::google::protobuf::int64"; - case FieldDescriptor::CPPTYPE_UINT32 : return "::google::protobuf::uint32"; - case FieldDescriptor::CPPTYPE_UINT64 : return "::google::protobuf::uint64"; - case FieldDescriptor::CPPTYPE_DOUBLE : return "double"; - case FieldDescriptor::CPPTYPE_FLOAT : return "float"; - case FieldDescriptor::CPPTYPE_BOOL : return "bool"; - case FieldDescriptor::CPPTYPE_ENUM : return "int"; - case FieldDescriptor::CPPTYPE_STRING : return "::std::string"; - case FieldDescriptor::CPPTYPE_MESSAGE: return NULL; + case FieldDescriptor::CPPTYPE_INT32: + return IntTypeName(options, "int32"); + case FieldDescriptor::CPPTYPE_INT64: + return IntTypeName(options, "int64"); + case FieldDescriptor::CPPTYPE_UINT32: + return IntTypeName(options, "uint32"); + case FieldDescriptor::CPPTYPE_UINT64: + return IntTypeName(options, "uint64"); + case FieldDescriptor::CPPTYPE_DOUBLE: + return "double"; + case FieldDescriptor::CPPTYPE_FLOAT: + return "float"; + case FieldDescriptor::CPPTYPE_BOOL: + return "bool"; + case FieldDescriptor::CPPTYPE_ENUM: + return "int"; + case FieldDescriptor::CPPTYPE_STRING: + return "std::string"; + case FieldDescriptor::CPPTYPE_MESSAGE: + return ""; - // No default because we want the compiler to complain if any new - // CppTypes are added. + // No default because we want the compiler to complain if any new + // CppTypes are added. } GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; + return ""; } const char* DeclaredTypeMethodName(FieldDescriptor::Type type) { switch (type) { - case FieldDescriptor::TYPE_INT32 : return "Int32"; - case FieldDescriptor::TYPE_INT64 : return "Int64"; - case FieldDescriptor::TYPE_UINT32 : return "UInt32"; - case FieldDescriptor::TYPE_UINT64 : return "UInt64"; - case FieldDescriptor::TYPE_SINT32 : return "SInt32"; - case FieldDescriptor::TYPE_SINT64 : return "SInt64"; - case FieldDescriptor::TYPE_FIXED32 : return "Fixed32"; - case FieldDescriptor::TYPE_FIXED64 : return "Fixed64"; - case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; - case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; - case FieldDescriptor::TYPE_FLOAT : return "Float"; - case FieldDescriptor::TYPE_DOUBLE : return "Double"; - - case FieldDescriptor::TYPE_BOOL : return "Bool"; - case FieldDescriptor::TYPE_ENUM : return "Enum"; - - case FieldDescriptor::TYPE_STRING : return "String"; - case FieldDescriptor::TYPE_BYTES : return "Bytes"; - case FieldDescriptor::TYPE_GROUP : return "Group"; - case FieldDescriptor::TYPE_MESSAGE : return "Message"; - - // No default because we want the compiler to complain if any new - // types are added. + case FieldDescriptor::TYPE_INT32: + return "Int32"; + case FieldDescriptor::TYPE_INT64: + return "Int64"; + case FieldDescriptor::TYPE_UINT32: + return "UInt32"; + case FieldDescriptor::TYPE_UINT64: + return "UInt64"; + case FieldDescriptor::TYPE_SINT32: + return "SInt32"; + case FieldDescriptor::TYPE_SINT64: + return "SInt64"; + case FieldDescriptor::TYPE_FIXED32: + return "Fixed32"; + case FieldDescriptor::TYPE_FIXED64: + return "Fixed64"; + case FieldDescriptor::TYPE_SFIXED32: + return "SFixed32"; + case FieldDescriptor::TYPE_SFIXED64: + return "SFixed64"; + case FieldDescriptor::TYPE_FLOAT: + return "Float"; + case FieldDescriptor::TYPE_DOUBLE: + return "Double"; + + case FieldDescriptor::TYPE_BOOL: + return "Bool"; + case FieldDescriptor::TYPE_ENUM: + return "Enum"; + + case FieldDescriptor::TYPE_STRING: + return "String"; + case FieldDescriptor::TYPE_BYTES: + return "Bytes"; + case FieldDescriptor::TYPE_GROUP: + return "Group"; + case FieldDescriptor::TYPE_MESSAGE: + return "Message"; + + // No default because we want the compiler to complain if any new + // types are added. } GOOGLE_LOG(FATAL) << "Can't get here."; return ""; } -string Int32ToString(int number) { - // gcc rejects the decimal form of kint32min. +std::string Int32ToString(int number) { if (number == kint32min) { - GOOGLE_COMPILE_ASSERT(kint32min == (~0x7fffffff), kint32min_value_error); - return "(~0x7fffffff)"; + // This needs to be special-cased, see explanation here: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661 + return StrCat(number + 1, " - 1"); } else { - return SimpleItoa(number); + return StrCat(number); } } -string Int64ToString(int64 number) { - // gcc rejects the decimal form of kint64min +std::string Int64ToString(const std::string& macro_prefix, int64 number) { if (number == kint64min) { - // Make sure we are in a 2's complement system. - GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(~0x7fffffffffffffff), - kint64min_value_error); - return "GOOGLE_LONGLONG(~0x7fffffffffffffff)"; + // This needs to be special-cased, see explanation here: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661 + return StrCat(macro_prefix, "_LONGLONG(", number + 1, ") - 1"); + } + return StrCat(macro_prefix, "_LONGLONG(", number, ")"); +} + +std::string UInt64ToString(const std::string& macro_prefix, uint64 number) { + return StrCat(macro_prefix, "_ULONGLONG(", number, ")"); +} + +std::string DefaultValue(const FieldDescriptor* field) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT64: + return Int64ToString("GG", field->default_value_int64()); + case FieldDescriptor::CPPTYPE_UINT64: + return UInt64ToString("GG", field->default_value_uint64()); + default: + return DefaultValue(Options(), field); } - return "GOOGLE_LONGLONG(" + SimpleItoa(number) + ")"; } -string DefaultValue(const FieldDescriptor* field) { +std::string DefaultValue(const Options& options, const FieldDescriptor* field) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: return Int32ToString(field->default_value_int32()); case FieldDescriptor::CPPTYPE_UINT32: - return SimpleItoa(field->default_value_uint32()) + "u"; + return StrCat(field->default_value_uint32()) + "u"; case FieldDescriptor::CPPTYPE_INT64: - return Int64ToString(field->default_value_int64()); + return Int64ToString("PROTOBUF", field->default_value_int64()); case FieldDescriptor::CPPTYPE_UINT64: - return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")"; + return UInt64ToString("PROTOBUF", field->default_value_uint64()); case FieldDescriptor::CPPTYPE_DOUBLE: { double value = field->default_value_double(); if (value == std::numeric_limits::infinity()) { - return "::google::protobuf::internal::Infinity()"; + return "std::numeric_limits::infinity()"; } else if (value == -std::numeric_limits::infinity()) { - return "-::google::protobuf::internal::Infinity()"; + return "-std::numeric_limits::infinity()"; } else if (value != value) { - return "::google::protobuf::internal::NaN()"; + return "std::numeric_limits::quiet_NaN()"; } else { return SimpleDtoa(value); } } - case FieldDescriptor::CPPTYPE_FLOAT: - { - float value = field->default_value_float(); - if (value == std::numeric_limits::infinity()) { - return "static_cast(::google::protobuf::internal::Infinity())"; - } else if (value == -std::numeric_limits::infinity()) { - return "static_cast(-::google::protobuf::internal::Infinity())"; - } else if (value != value) { - return "static_cast(::google::protobuf::internal::NaN())"; - } else { - string float_value = SimpleFtoa(value); - // If floating point value contains a period (.) or an exponent - // (either E or e), then append suffix 'f' to make it a float - // literal. - if (float_value.find_first_of(".eE") != string::npos) { - float_value.push_back('f'); - } - return float_value; + case FieldDescriptor::CPPTYPE_FLOAT: { + float value = field->default_value_float(); + if (value == std::numeric_limits::infinity()) { + return "std::numeric_limits::infinity()"; + } else if (value == -std::numeric_limits::infinity()) { + return "-std::numeric_limits::infinity()"; + } else if (value != value) { + return "std::numeric_limits::quiet_NaN()"; + } else { + std::string float_value = SimpleFtoa(value); + // If floating point value contains a period (.) or an exponent + // (either E or e), then append suffix 'f' to make it a float + // literal. + if (float_value.find_first_of(".eE") != std::string::npos) { + float_value.push_back('f'); } + return float_value; } + } case FieldDescriptor::CPPTYPE_BOOL: return field->default_value_bool() ? "true" : "false"; case FieldDescriptor::CPPTYPE_ENUM: // Lazy: Generate a static_cast because we don't have a helper function // that constructs the full name of an enum value. return strings::Substitute( - "static_cast< $0 >($1)", - ClassName(field->enum_type(), true), + "static_cast< $0 >($1)", ClassName(field->enum_type(), true), Int32ToString(field->default_value_enum()->number())); case FieldDescriptor::CPPTYPE_STRING: - return "\"" + EscapeTrigraphs( - CEscape(field->default_value_string())) + - "\""; + return "\"" + + EscapeTrigraphs(CEscape(field->default_value_string())) + + "\""; case FieldDescriptor::CPPTYPE_MESSAGE: - return "*" + FieldMessageTypeName(field) + + return "*" + FieldMessageTypeName(field, options) + "::internal_default_instance()"; } // Can't actually get here; make compiler happy. (We could add a default @@ -433,8 +740,8 @@ string DefaultValue(const FieldDescriptor* field) { } // Convert a file name into a valid identifier. -string FilenameIdentifier(const string& filename) { - string result; +std::string FilenameIdentifier(const std::string& filename) { + std::string result; for (int i = 0; i < filename.size(); i++) { if (ascii_isalnum(filename[i])) { result.push_back(filename[i]); @@ -447,31 +754,34 @@ string FilenameIdentifier(const string& filename) { return result; } -string FileLevelNamespace(const string& filename) { - return "protobuf_" + FilenameIdentifier(filename); +std::string UniqueName(const std::string& name, const std::string& filename, + const Options& options) { + return name + "_" + FilenameIdentifier(filename); } // Return the qualified C++ name for a file level symbol. -string QualifiedFileLevelSymbol(const string& package, const string& name) { - if (package.empty()) { +std::string QualifiedFileLevelSymbol(const FileDescriptor* file, + const std::string& name, + const Options& options) { + if (file->package().empty()) { return StrCat("::", name); } - return StrCat("::", DotsToColons(package), "::", name); + return StrCat(Namespace(file, options), "::", name); } // Escape C++ trigraphs by escaping question marks to \? -string EscapeTrigraphs(const string& to_escape) { +std::string EscapeTrigraphs(const std::string& to_escape) { return StringReplace(to_escape, "?", "\\?", true); } // Escaped function name to eliminate naming conflict. -string SafeFunctionName(const Descriptor* descriptor, - const FieldDescriptor* field, - const string& prefix) { +std::string SafeFunctionName(const Descriptor* descriptor, + const FieldDescriptor* field, + const std::string& prefix) { // Do not use FieldName() since it will escape keywords. - string name = field->name(); + std::string name = field->name(); LowerString(&name); - string function_name = prefix + name; + std::string function_name = prefix + name; if (descriptor->FindFieldByName(function_name)) { // Single underscore will also make it conflicting with the private data // member. We use double underscore to escape function names. @@ -484,19 +794,126 @@ string SafeFunctionName(const Descriptor* descriptor, return function_name; } -bool StaticInitializersForced(const FileDescriptor* file, - const Options& options) { - if (HasDescriptorMethods(file, options) || file->extension_count() > 0) { - return true; +static bool HasLazyFields(const Descriptor* descriptor, + const Options& options) { + for (int field_idx = 0; field_idx < descriptor->field_count(); field_idx++) { + if (IsLazy(descriptor->field(field_idx), options)) { + return true; + } + } + for (int idx = 0; idx < descriptor->extension_count(); idx++) { + if (IsLazy(descriptor->extension(idx), options)) { + return true; + } + } + for (int idx = 0; idx < descriptor->nested_type_count(); idx++) { + if (HasLazyFields(descriptor->nested_type(idx), options)) { + return true; + } + } + return false; +} + +// Does the given FileDescriptor use lazy fields? +bool HasLazyFields(const FileDescriptor* file, const Options& options) { + for (int i = 0; i < file->message_type_count(); i++) { + const Descriptor* descriptor(file->message_type(i)); + if (HasLazyFields(descriptor, options)) { + return true; + } + } + for (int field_idx = 0; field_idx < file->extension_count(); field_idx++) { + if (IsLazy(file->extension(field_idx), options)) { + return true; + } + } + return false; +} + +static bool HasRepeatedFields(const Descriptor* descriptor) { + for (int i = 0; i < descriptor->field_count(); ++i) { + if (descriptor->field(i)->label() == FieldDescriptor::LABEL_REPEATED) { + return true; + } + } + for (int i = 0; i < descriptor->nested_type_count(); ++i) { + if (HasRepeatedFields(descriptor->nested_type(i))) return true; + } + return false; +} + +bool HasRepeatedFields(const FileDescriptor* file) { + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasRepeatedFields(file->message_type(i))) return true; + } + return false; +} + +static bool IsStringPieceField(const FieldDescriptor* field, + const Options& options) { + return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE; +} + +static bool HasStringPieceFields(const Descriptor* descriptor, + const Options& options) { + for (int i = 0; i < descriptor->field_count(); ++i) { + if (IsStringPieceField(descriptor->field(i), options)) return true; + } + for (int i = 0; i < descriptor->nested_type_count(); ++i) { + if (HasStringPieceFields(descriptor->nested_type(i), options)) return true; + } + return false; +} + +bool HasStringPieceFields(const FileDescriptor* file, const Options& options) { + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasStringPieceFields(file->message_type(i), options)) return true; } + return false; +} + +static bool IsCordField(const FieldDescriptor* field, const Options& options) { + return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + EffectiveStringCType(field, options) == FieldOptions::CORD; +} + +static bool HasCordFields(const Descriptor* descriptor, + const Options& options) { + for (int i = 0; i < descriptor->field_count(); ++i) { + if (IsCordField(descriptor->field(i), options)) return true; + } + for (int i = 0; i < descriptor->nested_type_count(); ++i) { + if (HasCordFields(descriptor->nested_type(i), options)) return true; + } + return false; +} + +bool HasCordFields(const FileDescriptor* file, const Options& options) { for (int i = 0; i < file->message_type_count(); ++i) { - if (HasExtension(file->message_type(i))) { + if (HasCordFields(file->message_type(i), options)) return true; + } + return false; +} + +static bool HasExtensionsOrExtendableMessage(const Descriptor* descriptor) { + if (descriptor->extension_range_count() > 0) return true; + if (descriptor->extension_count() > 0) return true; + for (int i = 0; i < descriptor->nested_type_count(); ++i) { + if (HasExtensionsOrExtendableMessage(descriptor->nested_type(i))) { return true; } } return false; } +bool HasExtensionsOrExtendableMessage(const FileDescriptor* file) { + if (file->extension_count() > 0) return true; + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasExtensionsOrExtendableMessage(file->message_type(i))) return true; + } + return false; +} static bool HasMapFields(const Descriptor* descriptor) { for (int i = 0; i < descriptor->field_count(); ++i) { @@ -553,39 +970,64 @@ bool IsStringOrMessage(const FieldDescriptor* field) { return false; } -FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field) { +FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field, + const Options& options) { GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING); - // Open-source protobuf release only supports STRING ctype. - return FieldOptions::STRING; - + if (options.opensource_runtime) { + // Open-source protobuf release only supports STRING ctype. + return FieldOptions::STRING; + } else { + // Google-internal supports all ctypes. + return field->options().ctype(); + } } -bool IsAnyMessage(const FileDescriptor* descriptor) { +bool IsAnyMessage(const FileDescriptor* descriptor, const Options& options) { return descriptor->name() == kAnyProtoFile; } -bool IsAnyMessage(const Descriptor* descriptor) { +bool IsAnyMessage(const Descriptor* descriptor, const Options& options) { return descriptor->name() == kAnyMessageName && - descriptor->file()->name() == kAnyProtoFile; + IsAnyMessage(descriptor->file(), options); } -bool IsWellKnownMessage(const FileDescriptor* descriptor) { - return !descriptor->name().compare(0, 16, kGoogleProtobufPrefix); +bool IsWellKnownMessage(const FileDescriptor* file) { + static const std::unordered_set well_known_files{ + "google/protobuf/any.proto", + "google/protobuf/api.proto", + "google/protobuf/compiler/plugin.proto", + "google/protobuf/descriptor.proto", + "google/protobuf/duration.proto", + "google/protobuf/empty.proto", + "google/protobuf/field_mask.proto", + "google/protobuf/source_context.proto", + "google/protobuf/struct.proto", + "google/protobuf/timestamp.proto", + "google/protobuf/type.proto", + "google/protobuf/wrappers.proto", + }; + return well_known_files.find(file->name()) != well_known_files.end(); } -enum Utf8CheckMode { - STRICT = 0, // Parsing will fail if non UTF-8 data is in string fields. - VERIFY = 1, // Only log an error but parsing will succeed. - NONE = 2, // No UTF-8 check. -}; +static bool FieldEnforceUtf8(const FieldDescriptor* field, + const Options& options) { + return true; +} + +static bool FileUtf8Verification(const FileDescriptor* file, + const Options& options) { + return true; +} // Which level of UTF-8 enforcemant is placed on this file. -static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, - const Options& options) { - if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { +Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, + const Options& options) { + if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 && + FieldEnforceUtf8(field, options)) { return STRICT; } else if (GetOptimizeFor(field->file(), options) != - FileOptions::LITE_RUNTIME) { + FileOptions::LITE_RUNTIME && + FileUtf8Verification(field->file(), options)) { return VERIFY; } else { return NONE; @@ -594,47 +1036,42 @@ static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, static void GenerateUtf8CheckCode(const FieldDescriptor* field, const Options& options, bool for_parse, - const std::map& variables, const char* parameters, const char* strict_function, const char* verify_function, - io::Printer* printer) { + const Formatter& format) { switch (GetUtf8CheckMode(field, options)) { case STRICT: { if (for_parse) { - printer->Print("DO_("); + format("DO_("); } - printer->Print( - "::google::protobuf::internal::WireFormatLite::$function$(\n", - "function", strict_function); - printer->Indent(); - printer->Print(variables, parameters); + format("::$proto_ns$::internal::WireFormatLite::$1$(\n", strict_function); + format.Indent(); + format(parameters); if (for_parse) { - printer->Print("::google::protobuf::internal::WireFormatLite::PARSE,\n"); + format("::$proto_ns$::internal::WireFormatLite::PARSE,\n"); } else { - printer->Print("::google::protobuf::internal::WireFormatLite::SERIALIZE,\n"); + format("::$proto_ns$::internal::WireFormatLite::SERIALIZE,\n"); } - printer->Print("\"$full_name$\")", "full_name", field->full_name()); + format("\"$1$\")", field->full_name()); if (for_parse) { - printer->Print(")"); + format(")"); } - printer->Print(";\n"); - printer->Outdent(); + format(";\n"); + format.Outdent(); break; } case VERIFY: { - printer->Print( - "::google::protobuf::internal::WireFormat::$function$(\n", - "function", verify_function); - printer->Indent(); - printer->Print(variables, parameters); + format("::$proto_ns$::internal::WireFormat::$1$(\n", verify_function); + format.Indent(); + format(parameters); if (for_parse) { - printer->Print("::google::protobuf::internal::WireFormat::PARSE,\n"); + format("::$proto_ns$::internal::WireFormat::PARSE,\n"); } else { - printer->Print("::google::protobuf::internal::WireFormat::SERIALIZE,\n"); + format("::$proto_ns$::internal::WireFormat::SERIALIZE,\n"); } - printer->Print("\"$full_name$\");\n", "full_name", field->full_name()); - printer->Outdent(); + format("\"$1$\");\n", field->full_name()); + format.Outdent(); break; } case NONE: @@ -644,21 +1081,19 @@ static void GenerateUtf8CheckCode(const FieldDescriptor* field, void GenerateUtf8CheckCodeForString(const FieldDescriptor* field, const Options& options, bool for_parse, - const std::map& variables, const char* parameters, - io::Printer* printer) { - GenerateUtf8CheckCode(field, options, for_parse, variables, parameters, + const Formatter& format) { + GenerateUtf8CheckCode(field, options, for_parse, parameters, "VerifyUtf8String", "VerifyUTF8StringNamedField", - printer); + format); } void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field, const Options& options, bool for_parse, - const std::map& variables, const char* parameters, - io::Printer* printer) { - GenerateUtf8CheckCode(field, options, for_parse, variables, parameters, - "VerifyUtf8Cord", "VerifyUTF8CordNamedField", printer); + const Formatter& format) { + GenerateUtf8CheckCode(field, options, for_parse, parameters, "VerifyUtf8Cord", + "VerifyUTF8CordNamedField", format); } namespace { @@ -672,69 +1107,51 @@ void Flatten(const Descriptor* descriptor, } // namespace -std::vector FlattenMessagesInFile( - const FileDescriptor* file) { - std::vector result; +void FlattenMessagesInFile(const FileDescriptor* file, + std::vector* result) { for (int i = 0; i < file->message_type_count(); i++) { - Flatten(file->message_type(i), &result); + Flatten(file->message_type(i), result); } - return result; } -bool HasWeakFields(const Descriptor* descriptor) { +bool HasWeakFields(const Descriptor* descriptor, const Options& options) { + for (int i = 0; i < descriptor->field_count(); i++) { + if (IsWeak(descriptor->field(i), options)) return true; + } return false; } -bool HasWeakFields(const FileDescriptor* file) { +bool HasWeakFields(const FileDescriptor* file, const Options& options) { + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasWeakFields(file->message_type(i), options)) return true; + } return false; } -SCCAnalyzer::NodeData SCCAnalyzer::DFS(const Descriptor* descriptor) { - // Must not have visited already. - GOOGLE_DCHECK_EQ(cache_.count(descriptor), 0); - - // Mark visited by inserting in map. - NodeData& result = cache_[descriptor]; - // Initialize data structures. - result.index = result.lowlink = index_++; - stack_.push_back(descriptor); - - // Recurse the fields / nodes in graph - for (int i = 0; i < descriptor->field_count(); i++) { - const Descriptor* child = descriptor->field(i)->message_type(); - if (child) { - if (cache_.count(child) == 0) { - // unexplored node - NodeData child_data = DFS(child); - result.lowlink = std::min(result.lowlink, child_data.lowlink); - } else { - NodeData child_data = cache_[child]; - if (child_data.scc == NULL) { - // Still in the stack_ so we found a back edge - result.lowlink = std::min(result.lowlink, child_data.index); - } - } - } - } - if (result.index == result.lowlink) { - // This is the root of a strongly connected component - SCC* scc = CreateSCC(); - while (true) { - const Descriptor* scc_desc = stack_.back(); - scc->descriptors.push_back(scc_desc); - // Remove from stack - stack_.pop_back(); - cache_[scc_desc].scc = scc; +bool UsingImplicitWeakFields(const FileDescriptor* file, + const Options& options) { + return options.lite_implicit_weak_fields && + GetOptimizeFor(file, options) == FileOptions::LITE_RUNTIME; +} - if (scc_desc == descriptor) break; - } - } - return result; +bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer) { + return UsingImplicitWeakFields(field->file(), options) && + field->type() == FieldDescriptor::TYPE_MESSAGE && + !field->is_required() && !field->is_map() && !field->is_extension() && + !field->real_containing_oneof() && + !IsWellKnownMessage(field->message_type()->file()) && + field->message_type()->file()->name() != + "net/proto2/proto/descriptor.proto" && + // We do not support implicit weak fields between messages in the same + // strongly-connected component. + scc_analyzer->GetSCC(field->containing_type()) != + scc_analyzer->GetSCC(field->message_type()); } -MessageAnalysis SCCAnalyzer::GetSCCAnalysis(const SCC* scc) { +MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) { if (analysis_cache_.count(scc)) return analysis_cache_[scc]; - MessageAnalysis result = MessageAnalysis(); + MessageAnalysis result{}; for (int i = 0; i < scc->descriptors.size(); i++) { const Descriptor* descriptor = scc->descriptors[i]; if (descriptor->extension_range_count() > 0) { @@ -755,7 +1172,7 @@ MessageAnalysis SCCAnalyzer::GetSCCAnalysis(const SCC* scc) { } case FieldDescriptor::TYPE_GROUP: case FieldDescriptor::TYPE_MESSAGE: { - const SCC* child = GetSCC(field->message_type()); + const SCC* child = analyzer_.GetSCC(field->message_type()); if (child != scc) { MessageAnalysis analysis = GetSCCAnalysis(child); result.contains_cord |= analysis.contains_cord; @@ -784,6 +1201,793 @@ MessageAnalysis SCCAnalyzer::GetSCCAnalysis(const SCC* scc) { return analysis_cache_[scc] = result; } +void ListAllFields(const Descriptor* d, + std::vector* fields) { + // Collect sub messages + for (int i = 0; i < d->nested_type_count(); i++) { + ListAllFields(d->nested_type(i), fields); + } + // Collect message level extensions. + for (int i = 0; i < d->extension_count(); i++) { + fields->push_back(d->extension(i)); + } + // Add types of fields necessary + for (int i = 0; i < d->field_count(); i++) { + fields->push_back(d->field(i)); + } +} + +void ListAllFields(const FileDescriptor* d, + std::vector* fields) { + // Collect file level message. + for (int i = 0; i < d->message_type_count(); i++) { + ListAllFields(d->message_type(i), fields); + } + // Collect message level extensions. + for (int i = 0; i < d->extension_count(); i++) { + fields->push_back(d->extension(i)); + } +} + +void ListAllTypesForServices(const FileDescriptor* fd, + std::vector* types) { + for (int i = 0; i < fd->service_count(); i++) { + const ServiceDescriptor* sd = fd->service(i); + for (int j = 0; j < sd->method_count(); j++) { + const MethodDescriptor* method = sd->method(j); + types->push_back(method->input_type()); + types->push_back(method->output_type()); + } + } +} + +bool GetBootstrapBasename(const Options& options, const std::string& basename, + std::string* bootstrap_basename) { + if (options.opensource_runtime) { + return false; + } + + std::unordered_map bootstrap_mapping{ + {"net/proto2/proto/descriptor", + "net/proto2/internal/descriptor"}, + {"net/proto2/compiler/proto/plugin", + "net/proto2/compiler/proto/plugin"}, + {"net/proto2/compiler/proto/profile", + "net/proto2/compiler/proto/profile_bootstrap"}, + }; + auto iter = bootstrap_mapping.find(basename); + if (iter == bootstrap_mapping.end()) { + *bootstrap_basename = basename; + return false; + } else { + *bootstrap_basename = iter->second; + return true; + } +} + +bool IsBootstrapProto(const Options& options, const FileDescriptor* file) { + std::string my_name = StripProto(file->name()); + return GetBootstrapBasename(options, my_name, &my_name); +} + +bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context, + bool bootstrap_flag, std::string* basename) { + std::string bootstrap_basename; + if (!GetBootstrapBasename(options, *basename, &bootstrap_basename)) { + return false; + } + + if (bootstrap_flag) { + // Adjust basename, but don't abort code generation. + *basename = bootstrap_basename; + return false; + } else { + std::string forward_to_basename = bootstrap_basename; + + // Generate forwarding headers and empty .pb.cc. + { + std::unique_ptr output( + generator_context->Open(*basename + ".pb.h")); + io::Printer printer(output.get(), '$', nullptr); + printer.Print( + "#ifndef PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n" + "#define PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n" + "#include \"$forward_to_basename$.pb.h\" // IWYU pragma: export\n" + "#endif // PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n", + "forward_to_basename", forward_to_basename, "filename_identifier", + FilenameIdentifier(*basename)); + + if (!options.opensource_runtime) { + // HACK HACK HACK, tech debt from the deeps of proto1 and SWIG + // protocoltype is SWIG'ed and we need to forward + if (*basename == "net/proto/protocoltype") { + printer.Print( + "#ifdef SWIG\n" + "%include \"$forward_to_basename$.pb.h\"\n" + "#endif // SWIG\n", + "forward_to_basename", forward_to_basename); + } + } + } + + { + std::unique_ptr output( + generator_context->Open(*basename + ".proto.h")); + io::Printer printer(output.get(), '$', nullptr); + printer.Print( + "#ifndef PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n" + "#define PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n" + "#include \"$forward_to_basename$.proto.h\" // IWYU pragma: " + "export\n" + "#endif // " + "PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n", + "forward_to_basename", forward_to_basename, "filename_identifier", + FilenameIdentifier(*basename)); + } + + { + std::unique_ptr output( + generator_context->Open(*basename + ".pb.cc")); + io::Printer printer(output.get(), '$', nullptr); + printer.Print("\n"); + } + + { + std::unique_ptr output( + generator_context->Open(*basename + ".pb.h.meta")); + } + + { + std::unique_ptr output( + generator_context->Open(*basename + ".proto.h.meta")); + } + + // Abort code generation. + return true; + } +} + +class ParseLoopGenerator { + public: + ParseLoopGenerator(int num_hasbits, const Options& options, + MessageSCCAnalyzer* scc_analyzer, io::Printer* printer) + : scc_analyzer_(scc_analyzer), + options_(options), + format_(printer), + num_hasbits_(num_hasbits) {} + + void GenerateParserLoop(const Descriptor* descriptor) { + format_.Set("classname", ClassName(descriptor)); + format_.Set("p_ns", "::" + ProtobufNamespace(options_)); + format_.Set("pi_ns", + StrCat("::", ProtobufNamespace(options_), "::internal")); + format_.Set("GOOGLE_PROTOBUF", MacroPrefix(options_)); + std::map vars; + SetCommonVars(options_, &vars); + SetUnknkownFieldsVariable(descriptor, options_, &vars); + format_.AddMap(vars); + + std::vector ordered_fields; + for (auto field : FieldRange(descriptor)) { + if (!IsFieldStripped(field, options_)) { + ordered_fields.push_back(field); + } + } + std::sort(ordered_fields.begin(), ordered_fields.end(), + [](const FieldDescriptor* a, const FieldDescriptor* b) { + return a->number() < b->number(); + }); + + format_( + "const char* $classname$::_InternalParse(const char* ptr, " + "$pi_ns$::ParseContext* ctx) {\n" + "#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure\n"); + format_.Indent(); + int hasbits_size = 0; + if (num_hasbits_ > 0) { + hasbits_size = (num_hasbits_ + 31) / 32; + } + // For now only optimize small hasbits. + if (hasbits_size != 1) hasbits_size = 0; + if (hasbits_size) { + format_("_Internal::HasBits has_bits{};\n"); + format_.Set("has_bits", "has_bits"); + } else { + format_.Set("has_bits", "_has_bits_"); + } + + GenerateParseLoop(descriptor, ordered_fields); + format_.Outdent(); + format_("success:\n"); + if (hasbits_size) format_(" _has_bits_.Or(has_bits);\n"); + + format_( + " return ptr;\n" + "failure:\n" + " ptr = nullptr;\n" + " goto success;\n" + "#undef CHK_\n" + "}\n"); + } + + private: + MessageSCCAnalyzer* scc_analyzer_; + const Options& options_; + Formatter format_; + int num_hasbits_; + + using WireFormat = internal::WireFormat; + using WireFormatLite = internal::WireFormatLite; + + void GenerateArenaString(const FieldDescriptor* field) { + if (HasHasbit(field)) { + format_("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field)); + } + std::string default_string = + field->default_value_string().empty() + ? "::" + ProtobufNamespace(options_) + + "::internal::GetEmptyStringAlreadyInited()" + : QualifiedClassName(field->containing_type(), options_) + + "::" + MakeDefaultName(field) + ".get()"; + format_( + "if (arena != nullptr) {\n" + " ptr = ctx->ReadArenaString(ptr, &$1$_, arena);\n" + "} else {\n" + " ptr = " + "$pi_ns$::InlineGreedyStringParser($1$_.MutableNoArenaNoDefault(&$2$" + "), ptr, ctx);" + "\n}\n" + "const std::string* str = &$1$_.Get(); (void)str;\n", + FieldName(field), default_string); + } + + void GenerateStrings(const FieldDescriptor* field, bool check_utf8) { + FieldOptions::CType ctype = FieldOptions::STRING; + if (!options_.opensource_runtime) { + // Open source doesn't support other ctypes; + ctype = field->options().ctype(); + } + if (!field->is_repeated() && !options_.opensource_runtime && + GetOptimizeFor(field->file(), options_) != FileOptions::LITE_RUNTIME && + // For now only use arena string for strings with empty defaults. + field->default_value_string().empty() && + !field->real_containing_oneof() && ctype == FieldOptions::STRING) { + GenerateArenaString(field); + } else { + std::string name; + switch (ctype) { + case FieldOptions::STRING: + name = "GreedyStringParser"; + break; + case FieldOptions::CORD: + name = "CordParser"; + break; + case FieldOptions::STRING_PIECE: + name = "StringPieceParser"; + break; + } + format_( + "auto str = $1$$2$_$3$();\n" + "ptr = $pi_ns$::Inline$4$(str, ptr, ctx);\n", + HasInternalAccessors(ctype) ? "_internal_" : "", + field->is_repeated() && !field->is_packable() ? "add" : "mutable", + FieldName(field), name); + } + if (!check_utf8) return; // return if this is a bytes field + auto level = GetUtf8CheckMode(field, options_); + switch (level) { + case NONE: + return; + case VERIFY: + format_("#ifndef NDEBUG\n"); + break; + case STRICT: + format_("CHK_("); + break; + } + std::string field_name; + field_name = "nullptr"; + if (HasDescriptorMethods(field->file(), options_)) { + field_name = StrCat("\"", field->full_name(), "\""); + } + format_("$pi_ns$::VerifyUTF8(str, $1$)", field_name); + switch (level) { + case NONE: + return; + case VERIFY: + format_( + ";\n" + "#endif // !NDEBUG\n"); + break; + case STRICT: + format_(");\n"); + break; + } + } + + void GenerateLengthDelim(const FieldDescriptor* field) { + if (field->is_packable()) { + std::string enum_validator; + if (field->type() == FieldDescriptor::TYPE_ENUM && + !HasPreservingUnknownEnumSemantics(field)) { + enum_validator = + StrCat(", ", QualifiedClassName(field->enum_type(), options_), + "_IsValid, &_internal_metadata_, ", field->number()); + format_( + "ptr = " + "$pi_ns$::Packed$1$Parser<$unknown_fields_type$>(_internal_mutable_" + "$2$(), ptr, " + "ctx$3$);\n", + DeclaredTypeMethodName(field->type()), FieldName(field), + enum_validator); + } else { + format_( + "ptr = $pi_ns$::Packed$1$Parser(_internal_mutable_$2$(), ptr, " + "ctx$3$);\n", + DeclaredTypeMethodName(field->type()), FieldName(field), + enum_validator); + } + } else { + auto field_type = field->type(); + switch (field_type) { + case FieldDescriptor::TYPE_STRING: + GenerateStrings(field, true /* utf8 */); + break; + case FieldDescriptor::TYPE_BYTES: + GenerateStrings(field, false /* utf8 */); + break; + case FieldDescriptor::TYPE_MESSAGE: { + if (field->is_map()) { + const FieldDescriptor* val = + field->message_type()->FindFieldByName("value"); + GOOGLE_CHECK(val); + if (val->type() == FieldDescriptor::TYPE_ENUM && + !HasPreservingUnknownEnumSemantics(field)) { + format_( + "auto object = " + "::$proto_ns$::internal::InitEnumParseWrapper<$unknown_" + "fields_type$>(" + "&$1$_, $2$_IsValid, $3$, &_internal_metadata_);\n" + "ptr = ctx->ParseMessage(&object, ptr);\n", + FieldName(field), QualifiedClassName(val->enum_type()), + field->number()); + } else { + format_("ptr = ctx->ParseMessage(&$1$_, ptr);\n", + FieldName(field)); + } + } else if (IsLazy(field, options_)) { + if (field->real_containing_oneof()) { + format_( + "if (!_internal_has_$1$()) {\n" + " clear_$2$();\n" + " $2$_.$1$_ = ::$proto_ns$::Arena::CreateMessage<\n" + " $pi_ns$::LazyField>(GetArena());\n" + " set_has_$1$();\n" + "}\n" + "ptr = ctx->ParseMessage($2$_.$1$_, ptr);\n", + FieldName(field), field->containing_oneof()->name()); + } else if (HasHasbit(field)) { + format_( + "_Internal::set_has_$1$(&$has_bits$);\n" + "ptr = ctx->ParseMessage(&$1$_, ptr);\n", + FieldName(field)); + } else { + format_("ptr = ctx->ParseMessage(&$1$_, ptr);\n", + FieldName(field)); + } + } else if (IsImplicitWeakField(field, options_, scc_analyzer_)) { + if (!field->is_repeated()) { + format_( + "ptr = ctx->ParseMessage(_Internal::mutable_$1$(this), " + "ptr);\n", + FieldName(field)); + } else { + format_( + "ptr = ctx->ParseMessage($1$_.AddWeak(reinterpret_cast($2$::_$3$_default_instance_ptr_)" + "), ptr);\n", + FieldName(field), Namespace(field->message_type(), options_), + ClassName(field->message_type())); + } + } else if (IsWeak(field, options_)) { + format_( + "{\n" + " auto* default_ = &reinterpret_cast($1$);\n" + " ptr = ctx->ParseMessage(_weak_field_map_.MutableMessage($2$," + " default_), ptr);\n" + "}\n", + QualifiedDefaultInstanceName(field->message_type(), options_), + field->number()); + } else { + format_("ptr = ctx->ParseMessage(_internal_$1$_$2$(), ptr);\n", + field->is_repeated() ? "add" : "mutable", FieldName(field)); + } + break; + } + default: + GOOGLE_LOG(FATAL) << "Illegal combination for length delimited wiretype " + << " filed type is " << field->type(); + } + } + } + + // Convert a 1 or 2 byte varint into the equivalent value upon a direct load. + static uint32 SmallVarintValue(uint32 x) { + GOOGLE_DCHECK(x < 128 * 128); + if (x >= 128) x += (x & 0xFF80) + 128; + return x; + } + + static bool ShouldRepeat(const FieldDescriptor* descriptor, + internal::WireFormatLite::WireType wiretype) { + constexpr int kMaxTwoByteFieldNumber = 16 * 128; + return descriptor->number() < kMaxTwoByteFieldNumber && + descriptor->is_repeated() && + (!descriptor->is_packable() || + wiretype != internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + } + + void GenerateFieldBody(internal::WireFormatLite::WireType wiretype, + const FieldDescriptor* field) { + uint32 tag = WireFormatLite::MakeTag(field->number(), wiretype); + switch (wiretype) { + case WireFormatLite::WIRETYPE_VARINT: { + std::string type = PrimitiveTypeName(options_, field->cpp_type()); + std::string prefix = field->is_repeated() ? "add" : "set"; + if (field->type() == FieldDescriptor::TYPE_ENUM) { + format_( + "$uint64$ val = $pi_ns$::ReadVarint64(&ptr);\n" + "CHK_(ptr);\n"); + if (!HasPreservingUnknownEnumSemantics(field)) { + format_("if (PROTOBUF_PREDICT_TRUE($1$_IsValid(val))) {\n", + QualifiedClassName(field->enum_type(), options_)); + format_.Indent(); + } + format_("_internal_$1$_$2$(static_cast<$3$>(val));\n", prefix, + FieldName(field), + QualifiedClassName(field->enum_type(), options_)); + if (!HasPreservingUnknownEnumSemantics(field)) { + format_.Outdent(); + format_( + "} else {\n" + " $pi_ns$::WriteVarint($1$, val, mutable_unknown_fields());\n" + "}\n", + field->number()); + } + } else { + std::string size = (field->type() == FieldDescriptor::TYPE_SINT32 || + field->type() == FieldDescriptor::TYPE_UINT32) + ? "32" + : "64"; + std::string zigzag; + if ((field->type() == FieldDescriptor::TYPE_SINT32 || + field->type() == FieldDescriptor::TYPE_SINT64)) { + zigzag = "ZigZag"; + } + if (field->is_repeated() || field->real_containing_oneof()) { + std::string prefix = field->is_repeated() ? "add" : "set"; + format_( + "_internal_$1$_$2$($pi_ns$::ReadVarint$3$$4$(&ptr));\n" + "CHK_(ptr);\n", + prefix, FieldName(field), zigzag, size); + } else { + if (HasHasbit(field)) { + format_("_Internal::set_has_$1$(&$has_bits$);\n", + FieldName(field)); + } + format_( + "$1$_ = $pi_ns$::ReadVarint$2$$3$(&ptr);\n" + "CHK_(ptr);\n", + FieldName(field), zigzag, size); + } + } + break; + } + case WireFormatLite::WIRETYPE_FIXED32: + case WireFormatLite::WIRETYPE_FIXED64: { + std::string type = PrimitiveTypeName(options_, field->cpp_type()); + if (field->is_repeated() || field->real_containing_oneof()) { + std::string prefix = field->is_repeated() ? "add" : "set"; + format_( + "_internal_$1$_$2$($pi_ns$::UnalignedLoad<$3$>(ptr));\n" + "ptr += sizeof($3$);\n", + prefix, FieldName(field), type); + } else { + if (HasHasbit(field)) { + format_("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field)); + } + format_( + "$1$_ = $pi_ns$::UnalignedLoad<$2$>(ptr);\n" + "ptr += sizeof($2$);\n", + FieldName(field), type); + } + break; + } + case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: { + GenerateLengthDelim(field); + format_("CHK_(ptr);\n"); + break; + } + case WireFormatLite::WIRETYPE_START_GROUP: { + format_( + "ptr = ctx->ParseGroup(_internal_$1$_$2$(), ptr, $3$);\n" + "CHK_(ptr);\n", + field->is_repeated() ? "add" : "mutable", FieldName(field), tag); + break; + } + case WireFormatLite::WIRETYPE_END_GROUP: { + GOOGLE_LOG(FATAL) << "Can't have end group field\n"; + break; + } + } // switch (wire_type) + } + + // Returns the tag for this field and in case of repeated packable fields, + // sets a fallback tag in fallback_tag_ptr. + static uint32 ExpectedTag(const FieldDescriptor* field, + uint32* fallback_tag_ptr) { + uint32 expected_tag; + if (field->is_packable()) { + auto expected_wiretype = WireFormat::WireTypeForFieldType(field->type()); + expected_tag = + WireFormatLite::MakeTag(field->number(), expected_wiretype); + GOOGLE_CHECK(expected_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + auto fallback_wiretype = WireFormatLite::WIRETYPE_LENGTH_DELIMITED; + uint32 fallback_tag = + WireFormatLite::MakeTag(field->number(), fallback_wiretype); + + if (field->is_packed()) std::swap(expected_tag, fallback_tag); + *fallback_tag_ptr = fallback_tag; + } else { + auto expected_wiretype = WireFormat::WireTypeForField(field); + expected_tag = + WireFormatLite::MakeTag(field->number(), expected_wiretype); + } + return expected_tag; + } + + void GenerateParseLoop( + const Descriptor* descriptor, + const std::vector& ordered_fields) { + format_( + "while (!ctx->Done(&ptr)) {\n" + " $uint32$ tag;\n" + " ptr = $pi_ns$::ReadTag(ptr, &tag);\n" + " CHK_(ptr);\n"); + if (!ordered_fields.empty()) format_(" switch (tag >> 3) {\n"); + + format_.Indent(); + format_.Indent(); + + for (const auto* field : ordered_fields) { + PrintFieldComment(format_, field); + format_("case $1$:\n", field->number()); + format_.Indent(); + uint32 fallback_tag = 0; + uint32 expected_tag = ExpectedTag(field, &fallback_tag); + format_( + "if (PROTOBUF_PREDICT_TRUE(static_cast<$uint8$>(tag) == $1$)) {\n", + expected_tag & 0xFF); + format_.Indent(); + auto wiretype = WireFormatLite::GetTagWireType(expected_tag); + uint32 tag = WireFormatLite::MakeTag(field->number(), wiretype); + int tag_size = io::CodedOutputStream::VarintSize32(tag); + bool is_repeat = ShouldRepeat(field, wiretype); + if (is_repeat) { + format_( + "ptr -= $1$;\n" + "do {\n" + " ptr += $1$;\n", + tag_size); + format_.Indent(); + } + GenerateFieldBody(wiretype, field); + if (is_repeat) { + format_.Outdent(); + format_( + " if (!ctx->DataAvailable(ptr)) break;\n" + "} while ($pi_ns$::ExpectTag<$1$>(ptr));\n", + tag); + } + format_.Outdent(); + if (fallback_tag) { + format_("} else if (static_cast<$uint8$>(tag) == $1$) {\n", + fallback_tag & 0xFF); + format_.Indent(); + GenerateFieldBody(WireFormatLite::GetTagWireType(fallback_tag), field); + format_.Outdent(); + } + format_.Outdent(); + format_( + " } else goto handle_unusual;\n" + " continue;\n"); + } // for loop over ordered fields + + // Default case + if (!ordered_fields.empty()) format_("default: {\n"); + if (!ordered_fields.empty()) format_("handle_unusual:\n"); + format_( + " if ((tag & 7) == 4 || tag == 0) {\n" + " ctx->SetLastTag(tag);\n" + " goto success;\n" + " }\n"); + if (IsMapEntryMessage(descriptor)) { + format_(" continue;\n"); + } else { + if (descriptor->extension_range_count() > 0) { + format_("if ("); + for (int i = 0; i < descriptor->extension_range_count(); i++) { + const Descriptor::ExtensionRange* range = + descriptor->extension_range(i); + if (i > 0) format_(" ||\n "); + + uint32 start_tag = WireFormatLite::MakeTag( + range->start, static_cast(0)); + uint32 end_tag = WireFormatLite::MakeTag( + range->end, static_cast(0)); + + if (range->end > FieldDescriptor::kMaxNumber) { + format_("($1$u <= tag)", start_tag); + } else { + format_("($1$u <= tag && tag < $2$u)", start_tag, end_tag); + } + } + format_(") {\n"); + format_( + " ptr = _extensions_.ParseField(tag, ptr,\n" + " internal_default_instance(), &_internal_metadata_, ctx);\n" + " CHK_(ptr != nullptr);\n" + " continue;\n" + "}\n"); + } + format_( + " ptr = UnknownFieldParse(tag,\n" + " _internal_metadata_.mutable_unknown_fields<$unknown_" + "fields_type$>(),\n" + " ptr, ctx);\n" + " CHK_(ptr != nullptr);\n" + " continue;\n"); + } + if (!ordered_fields.empty()) format_("}\n"); // default case + format_.Outdent(); + format_.Outdent(); + if (!ordered_fields.empty()) format_(" } // switch\n"); + format_("} // while\n"); + } +}; + +void GenerateParserLoop(const Descriptor* descriptor, int num_hasbits, + const Options& options, + MessageSCCAnalyzer* scc_analyzer, + io::Printer* printer) { + ParseLoopGenerator generator(num_hasbits, options, scc_analyzer, printer); + generator.GenerateParserLoop(descriptor); +} + +static bool HasExtensionFromFile(const Message& msg, const FileDescriptor* file, + const Options& options, + bool* has_opt_codesize_extension) { + std::vector fields; + auto reflection = msg.GetReflection(); + reflection->ListFields(msg, &fields); + for (auto field : fields) { + const auto* field_msg = field->message_type(); + if (field_msg == nullptr) { + // It so happens that enums Is_Valid are still generated so enums work. + // Only messages have potential problems. + continue; + } + // If this option has an extension set AND that extension is defined in the + // same file we have bootstrap problem. + if (field->is_extension()) { + const auto* msg_extension_file = field->message_type()->file(); + if (msg_extension_file == file) return true; + if (has_opt_codesize_extension && + GetOptimizeFor(msg_extension_file, options) == + FileOptions::CODE_SIZE) { + *has_opt_codesize_extension = true; + } + } + // Recurse in this field to see if there is a problem in there + if (field->is_repeated()) { + for (int i = 0; i < reflection->FieldSize(msg, field); i++) { + if (HasExtensionFromFile(reflection->GetRepeatedMessage(msg, field, i), + file, options, has_opt_codesize_extension)) { + return true; + } + } + } else { + if (HasExtensionFromFile(reflection->GetMessage(msg, field), file, + options, has_opt_codesize_extension)) { + return true; + } + } + } + return false; +} + +static bool HasBootstrapProblem(const FileDescriptor* file, + const Options& options, + bool* has_opt_codesize_extension) { + static auto& cache = *new std::unordered_map; + auto it = cache.find(file); + if (it != cache.end()) return it->second; + // In order to build the data structures for the reflective parse, it needs + // to parse the serialized descriptor describing all the messages defined in + // this file. Obviously this presents a bootstrap problem for descriptor + // messages. + if (file->name() == "net/proto2/proto/descriptor.proto" || + file->name() == "google/protobuf/descriptor.proto") { + return true; + } + // Unfortunately we're not done yet. The descriptor option messages allow + // for extensions. So we need to be able to parse these extensions in order + // to parse the file descriptor for a file that has custom options. This is a + // problem when these custom options extensions are defined in the same file. + FileDescriptorProto linkedin_fd_proto; + const DescriptorPool* pool = file->pool(); + const Descriptor* fd_proto_descriptor = + pool->FindMessageTypeByName(linkedin_fd_proto.GetTypeName()); + // Not all pools have descriptor.proto in them. In these cases there for sure + // are no custom options. + if (fd_proto_descriptor == nullptr) return false; + + // It's easier to inspect file as a proto, because we can use reflection on + // the proto to iterate over all content. + file->CopyTo(&linkedin_fd_proto); + + // linkedin_fd_proto is a generated proto linked in the proto compiler. As + // such it doesn't know the extensions that are potentially present in the + // descriptor pool constructed from the protos that are being compiled. These + // custom options are therefore in the unknown fields. + // By building the corresponding FileDescriptorProto in the pool constructed + // by the protos that are being compiled, ie. file's pool, the unknown fields + // are converted to extensions. + DynamicMessageFactory factory(pool); + Message* fd_proto = factory.GetPrototype(fd_proto_descriptor)->New(); + fd_proto->ParseFromString(linkedin_fd_proto.SerializeAsString()); + + bool& res = cache[file]; + res = HasExtensionFromFile(*fd_proto, file, options, + has_opt_codesize_extension); + delete fd_proto; + return res; +} + +FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file, + const Options& options, + bool* has_opt_codesize_extension) { + if (has_opt_codesize_extension) *has_opt_codesize_extension = false; + switch (options.enforce_mode) { + case EnforceOptimizeMode::kSpeed: + return FileOptions::SPEED; + case EnforceOptimizeMode::kLiteRuntime: + return FileOptions::LITE_RUNTIME; + case EnforceOptimizeMode::kCodeSize: + if (file->options().optimize_for() == FileOptions::LITE_RUNTIME) { + return FileOptions::LITE_RUNTIME; + } + if (HasBootstrapProblem(file, options, has_opt_codesize_extension)) { + return FileOptions::SPEED; + } + return FileOptions::CODE_SIZE; + case EnforceOptimizeMode::kNoEnforcement: + if (file->options().optimize_for() == FileOptions::CODE_SIZE) { + if (HasBootstrapProblem(file, options, has_opt_codesize_extension)) { + GOOGLE_LOG(WARNING) << "Proto states optimize_for = CODE_SIZE, but we " + "cannot honor that because it contains custom option " + "extensions defined in the same proto."; + return FileOptions::SPEED; + } + } + return file->options().optimize_for(); + } + + GOOGLE_LOG(FATAL) << "Unknown optimization enforcement requested."; + // The phony return below serves to silence a warning from GCC 8. + return FileOptions::SPEED; +} + } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index 6ae68591b8c82..46d9477f5e475 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -35,27 +35,87 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ +#include +#include #include #include + #include +#include +#include #include +#include #include +#include +#include + +// Must be included last. +#include namespace google { namespace protobuf { +namespace compiler { +namespace cpp { -namespace io { -class Printer; +inline std::string ProtobufNamespace(const Options& options) { + return "PROTOBUF_NAMESPACE_ID"; } -namespace compiler { -namespace cpp { +inline std::string MacroPrefix(const Options& options) { + return options.opensource_runtime ? "GOOGLE_PROTOBUF" : "GOOGLE_PROTOBUF"; +} + +inline std::string DeprecatedAttribute(const Options& options, + const FieldDescriptor* d) { + return d->options().deprecated() ? "PROTOBUF_DEPRECATED " : ""; +} + +inline std::string DeprecatedAttribute(const Options& options, + const EnumValueDescriptor* d) { + return d->options().deprecated() ? "PROTOBUF_DEPRECATED_ENUM " : ""; +} // Commonly-used separator comments. Thick is a line of '=', thin is a line // of '-'. extern const char kThickSeparator[]; extern const char kThinSeparator[]; +void SetCommonVars(const Options& options, + std::map* variables); + +void SetUnknkownFieldsVariable(const Descriptor* descriptor, + const Options& options, + std::map* variables); + +bool GetBootstrapBasename(const Options& options, const std::string& basename, + std::string* bootstrap_basename); +bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context, + bool bootstrap_flag, std::string* basename); +bool IsBootstrapProto(const Options& options, const FileDescriptor* file); + +// Name space of the proto file. This namespace is such that the string +// "::some_name" is the correct fully qualified namespace. +// This means if the package is empty the namespace is "", and otherwise +// the namespace is "::foo::bar::...::baz" without trailing semi-colons. +std::string Namespace(const FileDescriptor* d, const Options& options); +std::string Namespace(const Descriptor* d, const Options& options); +std::string Namespace(const FieldDescriptor* d, const Options& options); +std::string Namespace(const EnumDescriptor* d, const Options& options); + +// Returns true if it's safe to reset "field" to zero. +bool CanInitializeByZeroing(const FieldDescriptor* field); + +std::string ClassName(const Descriptor* descriptor); +std::string ClassName(const EnumDescriptor* enum_descriptor); + +std::string QualifiedClassName(const Descriptor* d, const Options& options); +std::string QualifiedClassName(const EnumDescriptor* d, const Options& options); + +std::string QualifiedClassName(const Descriptor* d); +std::string QualifiedClassName(const EnumDescriptor* d); + +// DEPRECATED just use ClassName or QualifiedClassName, a boolean is very +// unreadable at the callsite. // Returns the non-nested type name for the given type. If "qualified" is // true, prefix the type with the full namespace. For example, if you had: // package foo.bar; @@ -64,113 +124,176 @@ extern const char kThinSeparator[]; // ::foo::bar::Baz_Qux // While the non-qualified version would be: // Baz_Qux -string ClassName(const Descriptor* descriptor, bool qualified); -string ClassName(const EnumDescriptor* enum_descriptor, bool qualified); +inline std::string ClassName(const Descriptor* descriptor, bool qualified) { + return qualified ? QualifiedClassName(descriptor, Options()) + : ClassName(descriptor); +} + +inline std::string ClassName(const EnumDescriptor* descriptor, bool qualified) { + return qualified ? QualifiedClassName(descriptor, Options()) + : ClassName(descriptor); +} + +// Returns the extension name prefixed with the class name if nested but without +// the package name. +std::string ExtensionName(const FieldDescriptor* d); + +std::string QualifiedExtensionName(const FieldDescriptor* d, + const Options& options); +std::string QualifiedExtensionName(const FieldDescriptor* d); + +// Type name of default instance. +std::string DefaultInstanceType(const Descriptor* descriptor, + const Options& options); + +// Non-qualified name of the default_instance of this message. +std::string DefaultInstanceName(const Descriptor* descriptor, + const Options& options); + +// Non-qualified name of the default instance pointer. This is used only for +// implicit weak fields, where we need an extra indirection. +std::string DefaultInstancePtr(const Descriptor* descriptor, + const Options& options); // Fully qualified name of the default_instance of this message. -string DefaultInstanceName(const Descriptor* descriptor); +std::string QualifiedDefaultInstanceName(const Descriptor* descriptor, + const Options& options); + +// Fully qualified name of the default instance pointer. +std::string QualifiedDefaultInstancePtr(const Descriptor* descriptor, + const Options& options); -// Name of the CRTP class template (for use with proto_h). -// This is a class name, like "ProtoName_InternalBase". -string DependentBaseClassTemplateName(const Descriptor* descriptor); +// DescriptorTable variable name. +std::string DescriptorTableName(const FileDescriptor* file, + const Options& options); -// Name of the base class: either the dependent base class (for use with -// proto_h) or google::protobuf::Message. -string SuperClassName(const Descriptor* descriptor, const Options& options); +// When declaring symbol externs from another file, this macro will supply the +// dllexport needed for the target file, if any. +std::string FileDllExport(const FileDescriptor* file, const Options& options); -// Returns a string that down-casts from the dependent base class to the -// derived class. -string DependentBaseDownCast(); -string DependentBaseConstDownCast(); +// Name of the base class: google::protobuf::Message or google::protobuf::MessageLite. +std::string SuperClassName(const Descriptor* descriptor, + const Options& options); + +// Adds an underscore if necessary to prevent conflicting with a keyword. +std::string ResolveKeyword(const std::string& name); // Get the (unqualified) name that should be used for this field in C++ code. // The name is coerced to lower-case to emulate proto1 behavior. People // should be using lowercase-with-underscores style for proto field names // anyway, so normally this just returns field->name(). -string FieldName(const FieldDescriptor* field); +std::string FieldName(const FieldDescriptor* field); // Get the sanitized name that should be used for the given enum in C++ code. -string EnumValueName(const EnumValueDescriptor* enum_value); +std::string EnumValueName(const EnumValueDescriptor* enum_value); + +// Returns an estimate of the compiler's alignment for the field. This +// can't guarantee to be correct because the generated code could be compiled on +// different systems with different alignment rules. The estimates below assume +// 64-bit pointers. +int EstimateAlignmentSize(const FieldDescriptor* field); // Get the unqualified name that should be used for a field's field // number constant. -string FieldConstantName(const FieldDescriptor *field); +std::string FieldConstantName(const FieldDescriptor* field); // Returns the scope where the field was defined (for extensions, this is // different from the message type to which the field applies). inline const Descriptor* FieldScope(const FieldDescriptor* field) { - return field->is_extension() ? - field->extension_scope() : field->containing_type(); + return field->is_extension() ? field->extension_scope() + : field->containing_type(); } -// Returns true if the given 'field_descriptor' has a message type that is -// a dependency of the file where the field is defined (i.e., the field -// type is defined in a different file than the message holding the field). -// -// This only applies to Message-typed fields. Enum-typed fields may refer -// to an enum in a dependency; however, enums are specified and -// forward-declared with an enum-base, so the definition is not required to -// manipulate the field value. -bool IsFieldDependent(const FieldDescriptor* field_descriptor); - -// Returns the name that should be used for forcing dependent lookup from a -// dependent base class. -string DependentTypeName(const FieldDescriptor* field); - // Returns the fully-qualified type name field->message_type(). Usually this // is just ClassName(field->message_type(), true); -string FieldMessageTypeName(const FieldDescriptor* field); - -// Strips ".proto" or ".protodevel" from the end of a filename. -LIBPROTOC_EXPORT string StripProto(const string& filename); +std::string FieldMessageTypeName(const FieldDescriptor* field, + const Options& options); // Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.). -// Note: non-built-in type names will be qualified, meaning they will start -// with a ::. If you are using the type as a template parameter, you will -// need to insure there is a space between the < and the ::, because the -// ridiculous C++ standard defines "<:" to be a synonym for "[". const char* PrimitiveTypeName(FieldDescriptor::CppType type); +std::string PrimitiveTypeName(const Options& options, + FieldDescriptor::CppType type); // Get the declared type name in CamelCase format, as is used e.g. for the // methods of WireFormat. For example, TYPE_INT32 becomes "Int32". const char* DeclaredTypeMethodName(FieldDescriptor::Type type); // Return the code that evaluates to the number when compiled. -string Int32ToString(int number); +std::string Int32ToString(int number); // Return the code that evaluates to the number when compiled. -string Int64ToString(int64 number); +std::string Int64ToString(const Options& options, int64 number); // Get code that evaluates to the field's default value. -string DefaultValue(const FieldDescriptor* field); +std::string DefaultValue(const Options& options, const FieldDescriptor* field); + +// Compatibility function for callers outside proto2. +std::string DefaultValue(const FieldDescriptor* field); // Convert a file name into a valid identifier. -string FilenameIdentifier(const string& filename); +std::string FilenameIdentifier(const std::string& filename); + +// For each .proto file generates a unique name. To prevent collisions of +// symbols in the global namespace +std::string UniqueName(const std::string& name, const std::string& filename, + const Options& options); +inline std::string UniqueName(const std::string& name, const FileDescriptor* d, + const Options& options) { + return UniqueName(name, d->name(), options); +} +inline std::string UniqueName(const std::string& name, const Descriptor* d, + const Options& options) { + return UniqueName(name, d->file(), options); +} +inline std::string UniqueName(const std::string& name, const EnumDescriptor* d, + const Options& options) { + return UniqueName(name, d->file(), options); +} +inline std::string UniqueName(const std::string& name, + const ServiceDescriptor* d, + const Options& options) { + return UniqueName(name, d->file(), options); +} -// For each .proto file generates a unique namespace. In this namespace global -// definitions are put to prevent collisions. -string FileLevelNamespace(const string& filename); +// Versions for call sites that only support the internal runtime (like proto1 +// support). +inline Options InternalRuntimeOptions() { + Options options; + options.opensource_runtime = false; + return options; +} +inline std::string UniqueName(const std::string& name, + const std::string& filename) { + return UniqueName(name, filename, InternalRuntimeOptions()); +} +inline std::string UniqueName(const std::string& name, + const FileDescriptor* d) { + return UniqueName(name, d->name(), InternalRuntimeOptions()); +} +inline std::string UniqueName(const std::string& name, const Descriptor* d) { + return UniqueName(name, d->file(), InternalRuntimeOptions()); +} +inline std::string UniqueName(const std::string& name, + const EnumDescriptor* d) { + return UniqueName(name, d->file(), InternalRuntimeOptions()); +} +inline std::string UniqueName(const std::string& name, + const ServiceDescriptor* d) { + return UniqueName(name, d->file(), InternalRuntimeOptions()); +} // Return the qualified C++ name for a file level symbol. -string QualifiedFileLevelSymbol(const string& package, const string& name); +std::string QualifiedFileLevelSymbol(const FileDescriptor* file, + const std::string& name, + const Options& options); // Escape C++ trigraphs by escaping question marks to \? -string EscapeTrigraphs(const string& to_escape); +std::string EscapeTrigraphs(const std::string& to_escape); // Escaped function name to eliminate naming conflict. -string SafeFunctionName(const Descriptor* descriptor, - const FieldDescriptor* field, - const string& prefix); - -// Returns true if unknown fields are always preserved after parsing. -inline bool AlwaysPreserveUnknownFields(const FileDescriptor* file) { - return file->syntax() != FileDescriptor::SYNTAX_PROTO3; -} - -// Returns true if unknown fields are preserved after parsing. -inline bool AlwaysPreserveUnknownFields(const Descriptor* message) { - return AlwaysPreserveUnknownFields(message->file()); -} +std::string SafeFunctionName(const Descriptor* descriptor, + const FieldDescriptor* field, + const std::string& prefix); // Returns true if generated messages have public unknown fields accessors inline bool PublicUnknownFieldsAccessors(const Descriptor* message) { @@ -178,8 +301,8 @@ inline bool PublicUnknownFieldsAccessors(const Descriptor* message) { } // Returns the optimize mode for , respecting . -::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor( - const FileDescriptor* file, const Options& options); +FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file, + const Options& options); // Determines whether unknown fields will be stored in an UnknownFieldSet or // a string. @@ -188,6 +311,66 @@ inline bool UseUnknownFieldSet(const FileDescriptor* file, return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME; } +inline bool IsWeak(const FieldDescriptor* field, const Options& options) { + if (field->options().weak()) { + GOOGLE_CHECK(!options.opensource_runtime); + return true; + } + return false; +} + +// For a string field, returns the effective ctype. If the actual ctype is +// not supported, returns the default of STRING. +FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field, + const Options& options); + +inline bool IsCord(const FieldDescriptor* field, const Options& options) { + return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + EffectiveStringCType(field, options) == FieldOptions::CORD; +} + +inline bool IsStringPiece(const FieldDescriptor* field, + const Options& options) { + return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE; +} + +// Does the given FileDescriptor use lazy fields? +bool HasLazyFields(const FileDescriptor* file, const Options& options); + +// Is the given field a supported lazy field? +inline bool IsLazy(const FieldDescriptor* field, const Options& options) { + return field->options().lazy() && !field->is_repeated() && + field->type() == FieldDescriptor::TYPE_MESSAGE && + GetOptimizeFor(field->file(), options) != FileOptions::LITE_RUNTIME && + !options.opensource_runtime; +} + +inline bool IsFieldUsed(const FieldDescriptor* field, const Options& options) { + return true; +} + +// Returns true if "field" is stripped. +inline bool IsFieldStripped(const FieldDescriptor* /*field*/, + const Options& /*options*/) { + return false; +} + +// Does the file contain any definitions that need extension_set.h? +bool HasExtensionsOrExtendableMessage(const FileDescriptor* file); + +// Does the file have any repeated fields, necessitating the file to include +// repeated_field.h? This does not include repeated extensions, since those are +// all stored internally in an ExtensionSet, not a separate RepeatedField*. +bool HasRepeatedFields(const FileDescriptor* file); + +// Does the file have any string/bytes fields with ctype=STRING_PIECE? This +// does not include extensions, since ctype is ignored for extensions. +bool HasStringPieceFields(const FileDescriptor* file, const Options& options); + +// Does the file have any string/bytes fields with ctype=CORD? This does not +// include extensions, since ctype is ignored for extensions. +bool HasCordFields(const FileDescriptor* file, const Options& options); // Does the file have any map fields, necessitating the file to include // map_field_inl.h and map.h. @@ -217,19 +400,15 @@ inline bool HasGenericServices(const FileDescriptor* file, file->options().cc_generic_services(); } -// Should we generate a separate, super-optimized code path for serializing to -// flat arrays? We don't do this in Lite mode because we'd rather reduce code -// size. -inline bool HasFastArraySerialization(const FileDescriptor* file, - const Options& options) { - return GetOptimizeFor(file, options) == FileOptions::SPEED; +inline bool IsProto2MessageSet(const Descriptor* descriptor, + const Options& options) { + return !options.opensource_runtime && + options.enforce_mode != EnforceOptimizeMode::kLiteRuntime && + !options.lite_implicit_weak_fields && + descriptor->options().message_set_wire_format() && + descriptor->full_name() == "google.protobuf.bridge.MessageSet"; } -// Returns whether we have to generate code with static initializers. -bool StaticInitializersForced(const FileDescriptor* file, - const Options& options); - - inline bool IsMapEntryMessage(const Descriptor* descriptor) { return descriptor->options().map_entry(); } @@ -237,75 +416,124 @@ inline bool IsMapEntryMessage(const Descriptor* descriptor) { // Returns true if the field's CPPTYPE is string or message. bool IsStringOrMessage(const FieldDescriptor* field); -// For a string field, returns the effective ctype. If the actual ctype is -// not supported, returns the default of STRING. -FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field); - -string UnderscoresToCamelCase(const string& input, bool cap_next_letter); +std::string UnderscoresToCamelCase(const std::string& input, + bool cap_next_letter); inline bool HasFieldPresence(const FileDescriptor* file) { return file->syntax() != FileDescriptor::SYNTAX_PROTO3; } -// Returns true if 'enum' semantics are such that unknown values are preserved -// in the enum field itself, rather than going to the UnknownFieldSet. -inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) { - return file->syntax() == FileDescriptor::SYNTAX_PROTO3; +inline bool HasHasbit(const FieldDescriptor* field) { + // This predicate includes proto3 message fields only if they have "optional". + // Foo submsg1 = 1; // HasHasbit() == false + // optional Foo submsg2 = 2; // HasHasbit() == true + // This is slightly odd, as adding "optional" to a singular proto3 field does + // not change the semantics or API. However whenever any field in a message + // has a hasbit, it forces reflection to include hasbit offsets for *all* + // fields, even if almost all of them are set to -1 (no hasbit). So to avoid + // causing a sudden size regression for ~all proto3 messages, we give proto3 + // message fields a hasbit only if "optional" is present. If the user is + // explicitly writing "optional", it is likely they are writing it on + // primitive fields also. + return (field->has_optional_keyword() || field->is_required()) && + !field->options().weak(); } -inline bool SupportsArenas(const FileDescriptor* file) { - return file->options().cc_enable_arenas(); +// Returns true if 'enum' semantics are such that unknown values are preserved +// in the enum field itself, rather than going to the UnknownFieldSet. +inline bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) { + return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3; } -inline bool SupportsArenas(const Descriptor* desc) { - return SupportsArenas(desc->file()); +inline bool IsCrossFileMessage(const FieldDescriptor* field) { + return field->type() == FieldDescriptor::TYPE_MESSAGE && + field->message_type()->file() != field->file(); } -inline bool SupportsArenas(const FieldDescriptor* field) { - return SupportsArenas(field->file()); +inline std::string MakeDefaultName(const FieldDescriptor* field) { + return "_i_give_permission_to_break_this_code_default_" + FieldName(field) + + "_"; } -bool IsAnyMessage(const FileDescriptor* descriptor); -bool IsAnyMessage(const Descriptor* descriptor); +bool IsAnyMessage(const FileDescriptor* descriptor, const Options& options); +bool IsAnyMessage(const Descriptor* descriptor, const Options& options); bool IsWellKnownMessage(const FileDescriptor* descriptor); -void GenerateUtf8CheckCodeForString(const FieldDescriptor* field, - const Options& options, bool for_parse, - const std::map& variables, - const char* parameters, - io::Printer* printer); - -void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field, - const Options& options, bool for_parse, - const std::map& variables, - const char* parameters, io::Printer* printer); +inline std::string IncludeGuard(const FileDescriptor* file, bool pb_h, + const Options& options) { + // If we are generating a .pb.h file and the proto_h option is enabled, then + // the .pb.h gets an extra suffix. + std::string filename_identifier = FilenameIdentifier( + file->name() + (pb_h && options.proto_h ? ".pb.h" : "")); + + if (IsWellKnownMessage(file)) { + // For well-known messages we need third_party/protobuf and net/proto2 to + // have distinct include guards, because some source files include both and + // both need to be defined (the third_party copies will be in the + // google::protobuf_opensource namespace). + return MacroPrefix(options) + "_INCLUDED_" + filename_identifier; + } else { + // Ideally this case would use distinct include guards for opensource and + // google3 protos also. (The behavior of "first #included wins" is not + // ideal). But unfortunately some legacy code includes both and depends on + // the identical include guards to avoid compile errors. + // + // We should clean this up so that this case can be removed. + return "GOOGLE_PROTOBUF_INCLUDED_" + filename_identifier; + } +} -inline ::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor( - const FileDescriptor* file, const Options& options) { - return options.enforce_lite - ? FileOptions::LITE_RUNTIME - : file->options().optimize_for(); +// Returns the OptimizeMode for this file, furthermore it updates a status +// bool if has_opt_codesize_extension is non-null. If this status bool is true +// it means this file contains an extension that itself is defined as +// optimized_for = CODE_SIZE. +FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file, + const Options& options, + bool* has_opt_codesize_extension); +inline FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file, + const Options& options) { + return GetOptimizeFor(file, options, nullptr); +} +inline bool NeedsEagerDescriptorAssignment(const FileDescriptor* file, + const Options& options) { + bool has_opt_codesize_extension; + if (GetOptimizeFor(file, options, &has_opt_codesize_extension) == + FileOptions::CODE_SIZE && + has_opt_codesize_extension) { + // If this filedescriptor contains an extension from another file which + // is optimized_for = CODE_SIZE. We need to be careful in the ordering so + // we eagerly build the descriptors in the dependencies before building + // the descriptors of this file. + return true; + } else { + // If we have a generated code based parser we never need eager + // initialization of descriptors of our deps. + return false; + } } // This orders the messages in a .pb.cc as it's outputted by file.cc -std::vector FlattenMessagesInFile( - const FileDescriptor* file); +void FlattenMessagesInFile(const FileDescriptor* file, + std::vector* result); +inline std::vector FlattenMessagesInFile( + const FileDescriptor* file) { + std::vector result; + FlattenMessagesInFile(file, &result); + return result; +} -bool HasWeakFields(const Descriptor* desc); -bool HasWeakFields(const FileDescriptor* desc); +bool HasWeakFields(const Descriptor* desc, const Options& options); +bool HasWeakFields(const FileDescriptor* desc, const Options& options); // Returns true if the "required" restriction check should be ignored for the // given field. inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field, const Options& options) { - return false; + // Do not check "required" for lazy fields. + return IsLazy(field, options); } -struct SCC { - std::vector descriptors; -}; - struct MessageAnalysis { bool is_recursive; bool contains_cord; @@ -317,17 +545,9 @@ struct MessageAnalysis { // quadratic performance, if we do this per message we would get O(V*(V+E)). // Logically this is just only used in message.cc, but in the header for // FileGenerator to help share it. -class LIBPROTOC_EXPORT SCCAnalyzer { +class PROTOC_EXPORT MessageSCCAnalyzer { public: - explicit SCCAnalyzer(const Options& options) : options_(options), index_(0) {} - ~SCCAnalyzer() { - for (int i = 0; i < garbage_bin_.size(); i++) delete garbage_bin_[i]; - } - - const SCC* GetSCC(const Descriptor* descriptor) { - if (cache_.count(descriptor)) return cache_[descriptor].scc; - return DFS(descriptor).scc; - } + explicit MessageSCCAnalyzer(const Options& options) : options_(options) {} MessageAnalysis GetSCCAnalysis(const SCC* scc); @@ -335,33 +555,328 @@ class LIBPROTOC_EXPORT SCCAnalyzer { MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor)); return result.contains_required || result.contains_extension; } + const SCC* GetSCC(const Descriptor* descriptor) { + return analyzer_.GetSCC(descriptor); + } private: - struct NodeData { - const SCC* scc; // if null it means its still on the stack - int index; - int lowlink; + struct DepsGenerator { + std::vector operator()(const Descriptor* desc) const { + std::vector deps; + for (int i = 0; i < desc->field_count(); i++) { + if (desc->field(i)->message_type()) { + deps.push_back(desc->field(i)->message_type()); + } + } + return deps; + } }; - + SCCAnalyzer analyzer_; Options options_; - std::map cache_; std::map analysis_cache_; - std::vector stack_; - int index_; - std::vector garbage_bin_; +}; + +void ListAllFields(const Descriptor* d, + std::vector* fields); +void ListAllFields(const FileDescriptor* d, + std::vector* fields); + +template +void ForEachField(const Descriptor* d, T&& func) { + for (int i = 0; i < d->nested_type_count(); i++) { + ForEachField(d->nested_type(i), std::forward(func)); + } + for (int i = 0; i < d->extension_count(); i++) { + func(d->extension(i)); + } + for (int i = 0; i < d->field_count(); i++) { + func(d->field(i)); + } +} + +template +void ForEachField(const FileDescriptor* d, T&& func) { + for (int i = 0; i < d->message_type_count(); i++) { + ForEachField(d->message_type(i), std::forward(func)); + } + for (int i = 0; i < d->extension_count(); i++) { + func(d->extension(i)); + } +} + +void ListAllTypesForServices(const FileDescriptor* fd, + std::vector* types); + +// Indicates whether we should use implicit weak fields for this file. +bool UsingImplicitWeakFields(const FileDescriptor* file, + const Options& options); + +// Indicates whether to treat this field as implicitly weak. +bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer); + +// Formatter is a functor class which acts as a closure around printer and +// the variable map. It's much like printer->Print except it supports both named +// variables that are substituted using a key value map and direct arguments. In +// the format string $1$, $2$, etc... are substituted for the first, second, ... +// direct argument respectively in the format call, it accepts both strings and +// integers. The implementation verifies all arguments are used and are "first" +// used in order of appearance in the argument list. For example, +// +// Format("return array[$1$];", 3) -> "return array[3];" +// Format("array[$2$] = $1$;", "Bla", 3) -> FATAL error (wrong order) +// Format("array[$1$] = $2$;", 3, "Bla") -> "array[3] = Bla;" +// +// The arguments can be used more than once like +// +// Format("array[$1$] = $2$; // Index = $1$", 3, "Bla") -> +// "array[3] = Bla; // Index = 3" +// +// If you use more arguments use the following style to help the reader, +// +// Format("int $1$() {\n" +// " array[$2$] = $3$;\n" +// " return $4$;" +// "}\n", +// funname, // 1 +// idx, // 2 +// varname, // 3 +// retval); // 4 +// +// but consider using named variables. Named variables like $foo$, with some +// identifier foo, are looked up in the map. One additional feature is that +// spaces are accepted between the '$' delimiters, $ foo$ will +// substiture to " bar" if foo stands for "bar", but in case it's empty +// will substitute to "". Hence, for example, +// +// Format(vars, "$dllexport $void fun();") -> "void fun();" +// "__declspec(export) void fun();" +// +// which is convenient to prevent double, leading or trailing spaces. +class PROTOC_EXPORT Formatter { + public: + explicit Formatter(io::Printer* printer) : printer_(printer) {} + Formatter(io::Printer* printer, + const std::map& vars) + : printer_(printer), vars_(vars) {} + + template + void Set(const std::string& key, const T& value) { + vars_[key] = ToString(value); + } + + void AddMap(const std::map& vars) { + for (const auto& keyval : vars) vars_[keyval.first] = keyval.second; + } + + template + void operator()(const char* format, const Args&... args) const { + printer_->FormatInternal({ToString(args)...}, vars_, format); + } + + void Indent() const { printer_->Indent(); } + void Outdent() const { printer_->Outdent(); } + io::Printer* printer() const { return printer_; } + + class PROTOC_EXPORT SaveState { + public: + explicit SaveState(Formatter* format) + : format_(format), vars_(format->vars_) {} + ~SaveState() { format_->vars_.swap(vars_); } + + private: + Formatter* format_; + std::map vars_; + }; + + private: + io::Printer* printer_; + std::map vars_; + + // Convenience overloads to accept different types as arguments. + static std::string ToString(const std::string& s) { return s; } + template ::value>::type> + static std::string ToString(I x) { + return StrCat(x); + } + static std::string ToString(strings::Hex x) { return StrCat(x); } + static std::string ToString(const FieldDescriptor* d) { return Payload(d); } + static std::string ToString(const Descriptor* d) { return Payload(d); } + static std::string ToString(const EnumDescriptor* d) { return Payload(d); } + static std::string ToString(const EnumValueDescriptor* d) { + return Payload(d); + } + static std::string ToString(const OneofDescriptor* d) { return Payload(d); } + + template + static std::string Payload(const Descriptor* descriptor) { + std::vector path; + descriptor->GetLocationPath(&path); + GeneratedCodeInfo::Annotation annotation; + for (int i = 0; i < path.size(); ++i) { + annotation.add_path(path[i]); + } + annotation.set_source_file(descriptor->file()->name()); + return annotation.SerializeAsString(); + } +}; + +template +void PrintFieldComment(const Formatter& format, const T* field) { + // Print the field's (or oneof's) proto-syntax definition as a comment. + // We don't want to print group bodies so we cut off after the first + // line. + DebugStringOptions options; + options.elide_group_body = true; + options.elide_oneof_body = true; + std::string def = field->DebugStringWithOptions(options); + format("// $1$\n", def.substr(0, def.find_first_of('\n'))); +} + +class PROTOC_EXPORT NamespaceOpener { + public: + explicit NamespaceOpener(const Formatter& format) + : printer_(format.printer()) {} + NamespaceOpener(const std::string& name, const Formatter& format) + : NamespaceOpener(format) { + ChangeTo(name); + } + ~NamespaceOpener() { ChangeTo(""); } + + void ChangeTo(const std::string& name) { + std::vector new_stack_ = + Split(name, "::", true); + int len = std::min(name_stack_.size(), new_stack_.size()); + int common_idx = 0; + while (common_idx < len) { + if (name_stack_[common_idx] != new_stack_[common_idx]) break; + common_idx++; + } + for (int i = name_stack_.size() - 1; i >= common_idx; i--) { + if (name_stack_[i] == "PROTOBUF_NAMESPACE_ID") { + printer_->Print("PROTOBUF_NAMESPACE_CLOSE\n"); + } else { + printer_->Print("} // namespace $ns$\n", "ns", name_stack_[i]); + } + } + name_stack_.swap(new_stack_); + for (int i = common_idx; i < name_stack_.size(); i++) { + if (name_stack_[i] == "PROTOBUF_NAMESPACE_ID") { + printer_->Print("PROTOBUF_NAMESPACE_OPEN\n"); + } else { + printer_->Print("namespace $ns$ {\n", "ns", name_stack_[i]); + } + } + } + + private: + io::Printer* printer_; + std::vector name_stack_; +}; + +enum Utf8CheckMode { + STRICT = 0, // Parsing will fail if non UTF-8 data is in string fields. + VERIFY = 1, // Only log an error but parsing will succeed. + NONE = 2, // No UTF-8 check. +}; - SCC* CreateSCC() { - garbage_bin_.push_back(new SCC()); - return garbage_bin_.back(); +Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, + const Options& options); + +void GenerateUtf8CheckCodeForString(const FieldDescriptor* field, + const Options& options, bool for_parse, + const char* parameters, + const Formatter& format); + +void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field, + const Options& options, bool for_parse, + const char* parameters, + const Formatter& format); + +template +struct FieldRangeImpl { + struct Iterator { + using iterator_category = std::forward_iterator_tag; + using value_type = const FieldDescriptor*; + using difference_type = int; + + value_type operator*() { return descriptor->field(idx); } + + friend bool operator==(const Iterator& a, const Iterator& b) { + GOOGLE_DCHECK(a.descriptor == b.descriptor); + return a.idx == b.idx; + } + friend bool operator!=(const Iterator& a, const Iterator& b) { + return !(a == b); + } + + Iterator& operator++() { + idx++; + return *this; + } + + int idx; + const T* descriptor; + }; + + Iterator begin() const { return {0, descriptor}; } + Iterator end() const { return {descriptor->field_count(), descriptor}; } + + const T* descriptor; +}; + +template +FieldRangeImpl FieldRange(const T* desc) { + return {desc}; +} + +struct OneOfRangeImpl { + struct Iterator { + using iterator_category = std::forward_iterator_tag; + using value_type = const OneofDescriptor*; + using difference_type = int; + + value_type operator*() { return descriptor->oneof_decl(idx); } + + friend bool operator==(const Iterator& a, const Iterator& b) { + GOOGLE_DCHECK(a.descriptor == b.descriptor); + return a.idx == b.idx; + } + friend bool operator!=(const Iterator& a, const Iterator& b) { + return !(a == b); + } + + Iterator& operator++() { + idx++; + return *this; + } + + int idx; + const Descriptor* descriptor; + }; + + Iterator begin() const { return {0, descriptor}; } + Iterator end() const { + return {descriptor->real_oneof_decl_count(), descriptor}; } - // Tarjan's Strongly Connected Components algo - NodeData DFS(const Descriptor* descriptor); + const Descriptor* descriptor; }; +inline OneOfRangeImpl OneOfRange(const Descriptor* desc) { return {desc}; } + +void GenerateParserLoop(const Descriptor* descriptor, int num_hasbits, + const Options& options, + MessageSCCAnalyzer* scc_analyzer, io::Printer* printer); + +PROTOC_EXPORT std::string StripProto(const std::string& filename); + } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc index da33d29b9249d..c9c30e0c635b7 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc @@ -29,12 +29,13 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include + #include #include #include - #include + namespace google { namespace protobuf { namespace compiler { @@ -46,317 +47,162 @@ bool IsProto3Field(const FieldDescriptor* field_descriptor) { } void SetMessageVariables(const FieldDescriptor* descriptor, - std::map* variables, + std::map* variables, const Options& options) { SetCommonFieldVariables(descriptor, variables, options); (*variables)["type"] = ClassName(descriptor->message_type(), false); - (*variables)["file_namespace"] = - FileLevelNamespace(descriptor->file()->name()); - (*variables)["stream_writer"] = - (*variables)["declared_type"] + - (HasFastArraySerialization(descriptor->message_type()->file(), options) - ? "MaybeToArray" - : ""); (*variables)["full_name"] = descriptor->full_name(); const FieldDescriptor* key = descriptor->message_type()->FindFieldByName("key"); const FieldDescriptor* val = descriptor->message_type()->FindFieldByName("value"); - (*variables)["key_cpp"] = PrimitiveTypeName(key->cpp_type()); + (*variables)["key_cpp"] = PrimitiveTypeName(options, key->cpp_type()); switch (val->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: - (*variables)["val_cpp"] = FieldMessageTypeName(val); - (*variables)["wrapper"] = "EntryWrapper"; + (*variables)["val_cpp"] = FieldMessageTypeName(val, options); break; case FieldDescriptor::CPPTYPE_ENUM: (*variables)["val_cpp"] = ClassName(val->enum_type(), true); - (*variables)["wrapper"] = "EnumEntryWrapper"; break; default: - (*variables)["val_cpp"] = PrimitiveTypeName(val->cpp_type()); - (*variables)["wrapper"] = "EntryWrapper"; + (*variables)["val_cpp"] = PrimitiveTypeName(options, val->cpp_type()); } (*variables)["key_wire_type"] = - "::google::protobuf::internal::WireFormatLite::TYPE_" + - ToUpper(DeclaredTypeMethodName(key->type())); + "TYPE_" + ToUpper(DeclaredTypeMethodName(key->type())); (*variables)["val_wire_type"] = - "::google::protobuf::internal::WireFormatLite::TYPE_" + - ToUpper(DeclaredTypeMethodName(val->type())); + "TYPE_" + ToUpper(DeclaredTypeMethodName(val->type())); (*variables)["map_classname"] = ClassName(descriptor->message_type(), false); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); + (*variables)["number"] = StrCat(descriptor->number()); + (*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor)); if (HasDescriptorMethods(descriptor->file(), options)) { (*variables)["lite"] = ""; } else { (*variables)["lite"] = "Lite"; } - - if (!IsProto3Field(descriptor) && - val->type() == FieldDescriptor::TYPE_ENUM) { - const EnumValueDescriptor* default_value = val->default_value_enum(); - (*variables)["default_enum_value"] = Int32ToString(default_value->number()); - } else { - (*variables)["default_enum_value"] = "0"; - } } MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), - descriptor_(descriptor), - dependent_field_(options.proto_h && IsFieldDependent(descriptor)) { + : FieldGenerator(descriptor, options) { SetMessageVariables(descriptor, &variables_, options); } MapFieldGenerator::~MapFieldGenerator() {} -void MapFieldGenerator:: -GeneratePrivateMembers(io::Printer* printer) const { - if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print( - variables_, - "public:\n" - "class $map_classname$ : public " - "::google::protobuf::internal::MapEntry<$map_classname$, \n" - " $key_cpp$, $val_cpp$,\n" - " $key_wire_type$,\n" - " $val_wire_type$,\n" - " $default_enum_value$ > {\n" - "public:\n" - " typedef ::google::protobuf::internal::MapEntry<$map_classname$, \n" - " $key_cpp$, $val_cpp$,\n" - " $key_wire_type$,\n" - " $val_wire_type$,\n" - " $default_enum_value$ > SuperType;\n" - " $map_classname$();\n" - " $map_classname$(::google::protobuf::Arena* arena);\n" - " void MergeFrom(const ::google::protobuf::Message& other) PROTOBUF_FINAL;\n" - " void MergeFrom(const $map_classname$& other);\n" - " static const Message* internal_default_instance() { return " - "reinterpret_cast(&_$map_classname$_default_instance_); }\n" - " ::google::protobuf::Metadata GetMetadata() const;\n" - "};\n"); - } else { - printer->Print(variables_, - "public:\n" - "typedef ::google::protobuf::internal::MapEntryLite<\n" - " $key_cpp$, $val_cpp$,\n" - " $key_wire_type$,\n" - " $val_wire_type$,\n" - " $default_enum_value$ >\n" - " $map_classname$;\n"); - } - printer->Print(variables_, - "private:\n" - "::google::protobuf::internal::MapField$lite$<\n" - " $map_classname$,\n" - " $key_cpp$, $val_cpp$,\n" - " $key_wire_type$,\n" - " $val_wire_type$,\n" - " $default_enum_value$ > $name$_;\n" - "private:\n"); +void MapFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "::$proto_ns$::internal::MapField$lite$<\n" + " $map_classname$,\n" + " $key_cpp$, $val_cpp$,\n" + " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n" + " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> " + "$name$_;\n"); } -void MapFieldGenerator:: -GenerateAccessorDeclarations(io::Printer* printer) const { - printer->Print( - variables_, - "$deprecated_attr$const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" - " $name$() const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" - " ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); +void MapFieldGenerator::GenerateAccessorDeclarations( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "private:\n" + "const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n" + " ${1$_internal_$name$$}$() const;\n" + "::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n" + " ${1$_internal_mutable_$name$$}$();\n" + "public:\n" + "$deprecated_attr$const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n" + " ${1$$name$$}$() const;\n" + "$deprecated_attr$::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n" + " ${1$mutable_$name$$}$();\n", + descriptor_); } -void MapFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const { - std::map variables(variables_); - variables["inline"] = is_inline ? "inline" : ""; - printer->Print(variables, - "$inline$ const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" +void MapFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "inline const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n" + "$classname$::_internal_$name$() const {\n" + " return $name$_.GetMap();\n" + "}\n" + "inline const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n" "$classname$::$name$() const {\n" + "$annotate_accessor$" " // @@protoc_insertion_point(field_map:$full_name$)\n" - " return $name$_.GetMap();\n" + " return _internal_$name$();\n" + "}\n" + "inline ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n" + "$classname$::_internal_mutable_$name$() {\n" + " return $name$_.MutableMap();\n" "}\n" - "$inline$ ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" + "inline ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n" "$classname$::mutable_$name$() {\n" + "$annotate_accessor$" " // @@protoc_insertion_point(field_mutable_map:$full_name$)\n" - " return $name$_.MutableMap();\n" + " return _internal_mutable_$name$();\n" "}\n"); } -void MapFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - std::map variables(variables_); - variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : ""; - printer->Print(variables, "$this_message$$name$_.Clear();\n"); +void MapFieldGenerator::GenerateClearingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.Clear();\n"); } -void MapFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); +void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.MergeFrom(from.$name$_);\n"); } -void MapFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n"); +void MapFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.Swap(&other->$name$_);\n"); } -void MapFieldGenerator:: -GenerateCopyConstructorCode(io::Printer* printer) const { +void MapFieldGenerator::GenerateCopyConstructorCode( + io::Printer* printer) const { GenerateConstructorCode(printer); GenerateMergingCode(printer); } -void MapFieldGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) const { - const FieldDescriptor* key_field = - descriptor_->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_field = - descriptor_->message_type()->FindFieldByName("value"); - bool using_entry = false; - string key; - string value; - if (IsProto3Field(descriptor_) || - value_field->type() != FieldDescriptor::TYPE_ENUM) { - printer->Print( - variables_, - "$map_classname$::Parser< ::google::protobuf::internal::MapField$lite$<\n" - " $map_classname$,\n" - " $key_cpp$, $val_cpp$,\n" - " $key_wire_type$,\n" - " $val_wire_type$,\n" - " $default_enum_value$ >,\n" - " ::google::protobuf::Map< $key_cpp$, $val_cpp$ > >" - " parser(&$name$_);\n" - "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" - " input, &parser));\n"); - key = "parser.key()"; - value = "parser.value()"; +static void GenerateSerializationLoop(const Formatter& format, bool string_key, + bool string_value, + bool is_deterministic) { + std::string ptr; + if (is_deterministic) { + format("for (size_type i = 0; i < n; i++) {\n"); + ptr = string_key ? "items[static_cast(i)]" + : "items[static_cast(i)].second"; } else { - using_entry = true; - key = "entry->key()"; - value = "entry->value()"; - printer->Print(variables_, - "::google::protobuf::scoped_ptr<$map_classname$> entry($name$_.NewEntry());\n"); - printer->Print(variables_, - "{\n" - " ::std::string data;\n" - " DO_(::google::protobuf::internal::WireFormatLite::ReadString(input, &data));\n" - " DO_(entry->ParseFromString(data));\n" - " if ($val_cpp$_IsValid(*entry->mutable_value())) {\n" - " (*mutable_$name$())[entry->key()] =\n" - " static_cast< $val_cpp$ >(*entry->mutable_value());\n" - " } else {\n"); - if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print(variables_, - " mutable_unknown_fields()" - "->AddLengthDelimited($number$, data);\n"); - } else { - printer->Print(variables_, - " unknown_fields_stream.WriteVarint32($tag$u);\n" - " unknown_fields_stream.WriteVarint32(\n" - " static_cast(data.size()));\n" - " unknown_fields_stream.WriteString(data);\n"); - } - - printer->Print(variables_, - " }\n" - "}\n"); + format( + "for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" + " it = this->_internal_$name$().begin();\n" + " it != this->_internal_$name$().end(); ++it) {\n"); + ptr = "it"; } + format.Indent(); - if (key_field->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString( - key_field, options_, true, variables_, - StrCat(key, ".data(), static_cast(", key, ".length()),\n").data(), - printer); - } - if (value_field->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString( - value_field, options_, true, variables_, - StrCat(value, ".data(), static_cast(", value, ".length()),\n") - .data(), - printer); - } + format( + "target = $map_classname$::Funcs::InternalSerialize($number$, " + "$1$->first, $1$->second, target, stream);\n", + ptr); - // If entry is allocated by arena, its desctructor should be avoided. - if (using_entry && SupportsArenas(descriptor_)) { - printer->Print(variables_, - "if (entry->GetArena() != NULL) entry.release();\n"); - } -} - -static void GenerateSerializationLoop(io::Printer* printer, - const std::map& variables, - bool supports_arenas, - const string& utf8_check, - const string& loop_header, - const string& ptr, - bool loop_via_iterators) { - printer->Print(variables, - StrCat("::google::protobuf::scoped_ptr<$map_classname$> entry;\n", - loop_header, " {\n").c_str()); - printer->Indent(); - - printer->Print(variables, StrCat( - "entry.reset($name$_.New$wrapper$(\n" - " ", ptr, "->first, ", ptr, "->second));\n" - "$write_entry$;\n").c_str()); - - // If entry is allocated by arena, its desctructor should be avoided. - if (supports_arenas) { - printer->Print( - "if (entry->GetArena() != NULL) {\n" - " entry.release();\n" - "}\n"); - } - - if (!utf8_check.empty()) { - // If loop_via_iterators is true then ptr is actually an iterator, and we - // create a pointer by prefixing it with "&*". - printer->Print( - StrCat(utf8_check, "(", (loop_via_iterators ? "&*" : ""), ptr, ");\n") - .c_str()); + if (string_key || string_value) { + // ptr is either an actual pointer or an iterator, either way we can + // create a pointer by taking the address after de-referencing it. + format("Utf8Check::Check(&(*$1$));\n", ptr); } - printer->Outdent(); - printer->Print( - "}\n"); -} - -void MapFieldGenerator:: -GenerateSerializeWithCachedSizes(io::Printer* printer) const { - std::map variables(variables_); - variables["write_entry"] = "::google::protobuf::internal::WireFormatLite::Write" + - variables["stream_writer"] + "(\n " + - variables["number"] + ", *entry, output)"; - variables["deterministic"] = "output->IsSerializationDeterministic()"; - GenerateSerializeWithCachedSizes(printer, variables); + format.Outdent(); + format("}\n"); } -void MapFieldGenerator:: -GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - std::map variables(variables_); - variables["write_entry"] = - "target = ::google::protobuf::internal::WireFormatLite::\n" - " InternalWrite" + variables["declared_type"] + - "NoVirtualToArray(\n " + variables["number"] + - ", *entry, deterministic, target);\n"; - variables["deterministic"] = "deterministic"; - GenerateSerializeWithCachedSizes(printer, variables); -} - -void MapFieldGenerator::GenerateSerializeWithCachedSizes( - io::Printer* printer, const std::map& variables) const { - printer->Print(variables, - "if (!this->$name$().empty()) {\n"); - printer->Indent(); +void MapFieldGenerator::GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("if (!this->_internal_$name$().empty()) {\n"); + format.Indent(); const FieldDescriptor* key_field = descriptor_->message_type()->FindFieldByName("key"); const FieldDescriptor* value_field = @@ -364,114 +210,94 @@ void MapFieldGenerator::GenerateSerializeWithCachedSizes( const bool string_key = key_field->type() == FieldDescriptor::TYPE_STRING; const bool string_value = value_field->type() == FieldDescriptor::TYPE_STRING; - printer->Print(variables, - "typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_pointer\n" + format( + "typedef ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_pointer\n" " ConstPtr;\n"); if (string_key) { - printer->Print(variables, + format( "typedef ConstPtr SortItem;\n" - "typedef ::google::protobuf::internal::" + "typedef ::$proto_ns$::internal::" "CompareByDerefFirst Less;\n"); } else { - printer->Print(variables, - "typedef ::google::protobuf::internal::SortItem< $key_cpp$, ConstPtr > " + format( + "typedef ::$proto_ns$::internal::SortItem< $key_cpp$, ConstPtr > " "SortItem;\n" - "typedef ::google::protobuf::internal::CompareByFirstField Less;\n"); + "typedef ::$proto_ns$::internal::CompareByFirstField " + "Less;\n"); } - string utf8_check; - if (string_key || string_value) { - printer->Print( + bool utf8_check = string_key || string_value; + if (utf8_check) { + format( "struct Utf8Check {\n" " static void Check(ConstPtr p) {\n"); - printer->Indent(); - printer->Indent(); + format.Indent(); + format.Indent(); if (string_key) { GenerateUtf8CheckCodeForString( - key_field, options_, false, variables, - "p->first.data(), static_cast(p->first.length()),\n", printer); + key_field, options_, false, + "p->first.data(), static_cast(p->first.length()),\n", format); } if (string_value) { GenerateUtf8CheckCodeForString( - value_field, options_, false, variables, - "p->second.data(), static_cast(p->second.length()),\n", printer); + value_field, options_, false, + "p->second.data(), static_cast(p->second.length()),\n", format); } - printer->Outdent(); - printer->Outdent(); - printer->Print( + format.Outdent(); + format.Outdent(); + format( " }\n" "};\n"); - utf8_check = "Utf8Check::Check"; } - printer->Print(variables, + format( "\n" - "if ($deterministic$ &&\n" - " this->$name$().size() > 1) {\n" - " ::google::protobuf::scoped_array items(\n" - " new SortItem[this->$name$().size()]);\n" - " typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::size_type size_type;\n" + "if (stream->IsSerializationDeterministic() &&\n" + " this->_internal_$name$().size() > 1) {\n" + " ::std::unique_ptr items(\n" + " new SortItem[this->_internal_$name$().size()]);\n" + " typedef ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::size_type " + "size_type;\n" " size_type n = 0;\n" - " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" - " it = this->$name$().begin();\n" - " it != this->$name$().end(); ++it, ++n) {\n" + " for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" + " it = this->_internal_$name$().begin();\n" + " it != this->_internal_$name$().end(); ++it, ++n) {\n" " items[static_cast(n)] = SortItem(&*it);\n" " }\n" " ::std::sort(&items[0], &items[static_cast(n)], Less());\n"); - printer->Indent(); - GenerateSerializationLoop(printer, variables, SupportsArenas(descriptor_), - utf8_check, "for (size_type i = 0; i < n; i++)", - string_key ? "items[static_cast(i)]" : - "items[static_cast(i)].second", false); - printer->Outdent(); - printer->Print( - "} else {\n"); - printer->Indent(); - GenerateSerializationLoop( - printer, variables, SupportsArenas(descriptor_), utf8_check, - "for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" - " it = this->$name$().begin();\n" - " it != this->$name$().end(); ++it)", - "it", true); - printer->Outdent(); - printer->Print("}\n"); - printer->Outdent(); - printer->Print("}\n"); + format.Indent(); + GenerateSerializationLoop(format, string_key, string_value, true); + format.Outdent(); + format("} else {\n"); + format.Indent(); + GenerateSerializationLoop(format, string_key, string_value, false); + format.Outdent(); + format("}\n"); + format.Outdent(); + format("}\n"); } -void MapFieldGenerator:: -GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, +void MapFieldGenerator::GenerateByteSize(io::Printer* printer) const { + Formatter format(printer, variables_); + format( "total_size += $tag_size$ *\n" - " ::google::protobuf::internal::FromIntSize(this->$name$_size());\n" - "{\n" - " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n" - " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" - " it = this->$name$().begin();\n" - " it != this->$name$().end(); ++it) {\n"); - - // If entry is allocated by arena, its desctructor should be avoided. - if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" - " entry.release();\n" - " }\n"); - } - - printer->Print(variables_, - " entry.reset($name$_.New$wrapper$(it->first, it->second));\n" - " total_size += ::google::protobuf::internal::WireFormatLite::\n" - " $declared_type$SizeNoVirtual(*entry);\n" - " }\n"); + " " + "::$proto_ns$::internal::FromIntSize(this->_internal_$name$_size());\n" + "for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" + " it = this->_internal_$name$().begin();\n" + " it != this->_internal_$name$().end(); ++it) {\n" + " total_size += $map_classname$::Funcs::ByteSizeLong(it->first, " + "it->second);\n" + "}\n"); +} - // If entry is allocated by arena, its desctructor should be avoided. - if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" - " entry.release();\n" - " }\n"); +void MapFieldGenerator::GenerateConstinitInitializer( + io::Printer* printer) const { + Formatter format(printer, variables_); + if (HasDescriptorMethods(descriptor_->file(), options_)) { + format("$name$_(::$proto_ns$::internal::ConstantInitialized{})"); + } else { + format("$name$_()"); } - - printer->Print("}\n"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h index 02e664976667b..149e8a35e90a6 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h @@ -49,33 +49,23 @@ class MapFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const {} void GenerateCopyConstructorCode(io::Printer* printer) const; - void GenerateMergeFromCodedStream(io::Printer* printer) const; - void GenerateSerializeWithCachedSizes(io::Printer* printer) const; void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; + void GenerateConstinitInitializer(io::Printer* printer) const; private: - // A helper for GenerateSerializeWithCachedSizes{,ToArray}. - void GenerateSerializeWithCachedSizes( - io::Printer* printer, const std::map& variables) const; - - const FieldDescriptor* descriptor_; - const bool dependent_field_; - std::map variables_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator); }; } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 63ebb3c50dbf0..4878d18a154ef 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -35,12 +35,10 @@ #include #include -#include +#include #include #include -#ifndef _SHARED_PTR_H -#include -#endif +#include #include #include @@ -48,15 +46,17 @@ #include #include #include +#include +#include #include #include -#include #include #include #include #include #include #include +#include namespace google { @@ -69,17 +69,48 @@ using internal::WireFormatLite; namespace { -template -void PrintFieldComment(io::Printer* printer, const T* field) { - // Print the field's (or oneof's) proto-syntax definition as a comment. - // We don't want to print group bodies so we cut off after the first - // line. - DebugStringOptions options; - options.elide_group_body = true; - options.elide_oneof_body = true; - string def = field->DebugStringWithOptions(options); - printer->Print("// $def$\n", - "def", def.substr(0, def.find_first_of('\n'))); +static constexpr int kNoHasbit = -1; + +// Create an expression that evaluates to +// "for all i, (_has_bits_[i] & masks[i]) == masks[i]" +// masks is allowed to be shorter than _has_bits_, but at least one element of +// masks must be non-zero. +std::string ConditionalToCheckBitmasks( + const std::vector& masks, bool return_success = true, + StringPiece has_bits_var = "_has_bits_") { + std::vector parts; + for (int i = 0; i < masks.size(); i++) { + if (masks[i] == 0) continue; + std::string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8)); + // Each xor evaluates to 0 if the expected bits are present. + parts.push_back( + StrCat("((", has_bits_var, "[", i, "] & ", m, ") ^ ", m, ")")); + } + GOOGLE_CHECK(!parts.empty()); + // If we have multiple parts, each expected to be 0, then bitwise-or them. + std::string result = + parts.size() == 1 + ? parts[0] + : StrCat("(", Join(parts, "\n | "), ")"); + return result + (return_success ? " == 0" : " != 0"); +} + +void PrintPresenceCheck(const Formatter& format, const FieldDescriptor* field, + const std::vector& has_bit_indices, + io::Printer* printer, int* cached_has_word_index) { + if (!field->options().weak()) { + int has_bit_index = has_bit_indices[field->index()]; + if (*cached_has_word_index != (has_bit_index / 32)) { + *cached_has_word_index = (has_bit_index / 32); + format("cached_has_bits = _has_bits_[$1$];\n", *cached_has_word_index); + } + const std::string mask = + StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); + format("if (cached_has_bits & 0x$1$u) {\n", mask); + } else { + format("if (has_$1$()) {\n", FieldName(field)); + } + format.Indent(); } struct FieldOrderingByNumber { @@ -109,300 +140,95 @@ struct ExtensionRangeSorter { } }; -// This returns an estimate of the compiler's alignment for the field. This -// can't guarantee to be correct because the generated code could be compiled on -// different systems with different alignment rules. The estimates below assume -// 64-bit pointers. -int EstimateAlignmentSize(const FieldDescriptor* field) { - if (field == NULL) return 0; - if (field->is_repeated()) return 8; +bool IsPOD(const FieldDescriptor* field) { + if (field->is_repeated() || field->is_extension()) return false; switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_BOOL: - return 1; - - case FieldDescriptor::CPPTYPE_INT32: - case FieldDescriptor::CPPTYPE_UINT32: case FieldDescriptor::CPPTYPE_ENUM: - case FieldDescriptor::CPPTYPE_FLOAT: - return 4; - + case FieldDescriptor::CPPTYPE_INT32: case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT32: case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_FLOAT: case FieldDescriptor::CPPTYPE_DOUBLE: - case FieldDescriptor::CPPTYPE_STRING: - case FieldDescriptor::CPPTYPE_MESSAGE: - return 8; - } - GOOGLE_LOG(FATAL) << "Can't get here."; - return -1; // Make compiler happy. -} - -// FieldGroup is just a helper for OptimizePadding below. It holds a vector of -// fields that are grouped together because they have compatible alignment, and -// a preferred location in the final field ordering. -class FieldGroup { - public: - FieldGroup() - : preferred_location_(0) {} - - // A group with a single field. - FieldGroup(float preferred_location, const FieldDescriptor* field) - : preferred_location_(preferred_location), - fields_(1, field) {} - - // Append the fields in 'other' to this group. - void Append(const FieldGroup& other) { - if (other.fields_.empty()) { - return; - } - // Preferred location is the average among all the fields, so we weight by - // the number of fields on each FieldGroup object. - preferred_location_ = - (preferred_location_ * fields_.size() + - (other.preferred_location_ * other.fields_.size())) / - (fields_.size() + other.fields_.size()); - fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end()); - } - - void SetPreferredLocation(float location) { preferred_location_ = location; } - const std::vector& fields() const { return fields_; } - - // FieldGroup objects sort by their preferred location. - bool operator<(const FieldGroup& other) const { - return preferred_location_ < other.preferred_location_; - } - - private: - // "preferred_location_" is an estimate of where this group should go in the - // final list of fields. We compute this by taking the average index of each - // field in this group in the original ordering of fields. This is very - // approximate, but should put this group close to where its member fields - // originally went. - float preferred_location_; - std::vector fields_; - // We rely on the default copy constructor and operator= so this type can be - // used in a vector. -}; - -// Helper for the code that emits the Clear() method. -bool CanInitializeByZeroing(const FieldDescriptor* field) { - if (field->is_repeated() || field->is_extension()) return false; - switch (field->cpp_type()) { - case internal::WireFormatLite::CPPTYPE_ENUM: - return field->default_value_enum()->number() == 0; - case internal::WireFormatLite::CPPTYPE_INT32: - return field->default_value_int32() == 0; - case internal::WireFormatLite::CPPTYPE_INT64: - return field->default_value_int64() == 0; - case internal::WireFormatLite::CPPTYPE_UINT32: - return field->default_value_uint32() == 0; - case internal::WireFormatLite::CPPTYPE_UINT64: - return field->default_value_uint64() == 0; - case internal::WireFormatLite::CPPTYPE_FLOAT: - return field->default_value_float() == 0; - case internal::WireFormatLite::CPPTYPE_DOUBLE: - return field->default_value_double() == 0; - case internal::WireFormatLite::CPPTYPE_BOOL: - return field->default_value_bool() == false; - default: - return false; - } -} - -bool IsPOD(const FieldDescriptor* field) { - if (field->is_repeated() || field->is_extension()) return false; - switch (field->cpp_type()) { - case internal::WireFormatLite::CPPTYPE_ENUM: - case internal::WireFormatLite::CPPTYPE_INT32: - case internal::WireFormatLite::CPPTYPE_INT64: - case internal::WireFormatLite::CPPTYPE_UINT32: - case internal::WireFormatLite::CPPTYPE_UINT64: - case internal::WireFormatLite::CPPTYPE_FLOAT: - case internal::WireFormatLite::CPPTYPE_DOUBLE: - case internal::WireFormatLite::CPPTYPE_BOOL: + case FieldDescriptor::CPPTYPE_BOOL: return true; - case internal::WireFormatLite::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_STRING: return false; default: return false; } } -// Helper for the code that emits the SharedCtor() method. -bool CanConstructByZeroing(const FieldDescriptor* field, - const Options& options) { +// Helper for the code that emits the SharedCtor() and InternalSwap() methods. +// Anything that is a POD or a "normal" message (represented by a pointer) can +// be manipulated as raw bytes. +bool CanBeManipulatedAsRawBytes(const FieldDescriptor* field, + const Options& options) { bool ret = CanInitializeByZeroing(field); // Non-repeated, non-lazy message fields are simply raw pointers, so we can - // use memset to initialize these in SharedCtor. We cannot use this in - // Clear, as we need to potentially delete the existing value. - ret = ret || - (!field->is_repeated() && - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE); + // swap them or use memset to initialize these in SharedCtor. We cannot use + // this in Clear, as we need to potentially delete the existing value. + ret = ret || (!field->is_repeated() && !IsLazy(field, options) && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE); return ret; } -// Reorder 'fields' so that if the fields are output into a c++ class in the new -// order, fields of similiar family (see below) are together and within each -// family, alignment padding is minimized. -// -// We try to do this while keeping each field as close as possible to its field -// number order so that we don't reduce cache locality much for function that -// access each field in order. Originally, OptimizePadding used declaration -// order for its decisions, but generated code minus the serializer/parsers uses -// the output of OptimizePadding as well (stored in -// MessageGenerator::optimized_order_). Since the serializers use field number -// order, we use that as a tie-breaker. -// -// TODO(ckennelly): If/when we have profiles available for the compiler, use -// those rather than respect declaration order. -// -// We classify each field into a particular "family" of fields, that we perform -// the same operation on in our generated functions. -// -// REPEATED is placed first, as the C++ compiler automatically initializes -// these fields in layout order. -// -// STRING is grouped next, as our Clear/SharedCtor/SharedDtor walks it and -// calls ArenaStringPtr::Destroy on each. -// -// -// MESSAGE is grouped next, as our Clear/SharedDtor code walks it and calls -// delete on each. We initialize these fields with a NULL pointer (see -// MessageFieldGenerator::GenerateConstructorCode), which allows them to be -// memset. -// -// ZERO_INITIALIZABLE is memset in Clear/SharedCtor -// -// OTHER these fields are initialized one-by-one. -void OptimizePadding(std::vector* fields, - const Options& options) { - // The sorted numeric order of Family determines the declaration order in the - // memory layout. - enum Family { - REPEATED = 0, - STRING = 1, - MESSAGE = 3, - ZERO_INITIALIZABLE = 4, - OTHER = 5, - kMaxFamily - }; - - // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes. - std::vector aligned_to_1[kMaxFamily]; - std::vector aligned_to_4[kMaxFamily]; - std::vector aligned_to_8[kMaxFamily]; - for (int i = 0; i < fields->size(); ++i) { - const FieldDescriptor* field = (*fields)[i]; - - Family f = OTHER; - if (field->is_repeated()) { - f = REPEATED; - } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { - f = STRING; - } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - f = MESSAGE; - - } else if (CanInitializeByZeroing(field)) { - f = ZERO_INITIALIZABLE; - } - - const int j = field->number(); - switch (EstimateAlignmentSize(field)) { - case 1: aligned_to_1[f].push_back(FieldGroup(j, field)); break; - case 4: aligned_to_4[f].push_back(FieldGroup(j, field)); break; - case 8: aligned_to_8[f].push_back(FieldGroup(j, field)); break; - default: - GOOGLE_LOG(FATAL) << "Unknown alignment size."; - } - } +// Finds runs of fields for which `predicate` is true. +// RunMap maps from fields that start each run to the number of fields in that +// run. This is optimized for the common case that there are very few runs in +// a message and that most of the eligible fields appear together. +using RunMap = std::unordered_map; +RunMap FindRuns(const std::vector& fields, + const std::function& predicate) { + RunMap runs; + const FieldDescriptor* last_start = nullptr; - // For each family, group fields to optimize padding. - for (int f = 0; f < kMaxFamily; f++) { - // Now group fields aligned to 1 byte into sets of 4, and treat those like a - // single field aligned to 4 bytes. - for (int i = 0; i < aligned_to_1[f].size(); i += 4) { - FieldGroup field_group; - for (int j = i; j < aligned_to_1[f].size() && j < i + 4; ++j) { - field_group.Append(aligned_to_1[f][j]); - } - aligned_to_4[f].push_back(field_group); - } - // Sort by preferred location to keep fields as close to their field number - // order as possible. Using stable_sort ensures that the output is - // consistent across runs. - std::stable_sort(aligned_to_4[f].begin(), aligned_to_4[f].end()); - - // Now group fields aligned to 4 bytes (or the 4-field groups created above) - // into pairs, and treat those like a single field aligned to 8 bytes. - for (int i = 0; i < aligned_to_4[f].size(); i += 2) { - FieldGroup field_group; - for (int j = i; j < aligned_to_4[f].size() && j < i + 2; ++j) { - field_group.Append(aligned_to_4[f][j]); - } - if (i == aligned_to_4[f].size() - 1) { - if (f == OTHER) { - // Move incomplete 4-byte block to the beginning. This is done to - // pair with the (possible) leftover blocks from the - // ZERO_INITIALIZABLE family. - field_group.SetPreferredLocation(-1); - } else { - // Move incomplete 4-byte block to the end. - field_group.SetPreferredLocation(fields->size() + 1); - } + for (auto field : fields) { + if (predicate(field)) { + if (last_start == nullptr) { + last_start = field; } - aligned_to_8[f].push_back(field_group); - } - // Sort by preferred location. - std::stable_sort(aligned_to_8[f].begin(), aligned_to_8[f].end()); - } - // Now pull out all the FieldDescriptors in order. - fields->clear(); - for (int f = 0; f < kMaxFamily; ++f) { - for (int i = 0; i < aligned_to_8[f].size(); ++i) { - fields->insert(fields->end(), - aligned_to_8[f][i].fields().begin(), - aligned_to_8[f][i].fields().end()); + runs[last_start]++; + } else { + last_start = nullptr; } } + return runs; } - // Emits an if-statement with a condition that evaluates to true if |field| is // considered non-default (will be sent over the wire), for message types // without true field presence. Should only be called if -// !HasFieldPresence(message_descriptor). +// !HasHasbit(field). bool EmitFieldNonDefaultCondition(io::Printer* printer, - const string& prefix, + const std::string& prefix, const FieldDescriptor* field) { + GOOGLE_CHECK(!HasHasbit(field)); + Formatter format(printer); + format.Set("prefix", prefix); + format.Set("name", FieldName(field)); // Merge and serialize semantics: primitive fields are merged/serialized only // if non-zero (numeric) or non-empty (string). if (!field->is_repeated() && !field->containing_oneof()) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { - printer->Print( - "if ($prefix$$name$().size() > 0) {\n", - "prefix", prefix, - "name", FieldName(field)); + format("if ($prefix$$name$().size() > 0) {\n"); } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { // Message fields still have has_$name$() methods. - printer->Print( - "if ($prefix$has_$name$()) {\n", - "prefix", prefix, - "name", FieldName(field)); + format("if ($prefix$has_$name$()) {\n"); + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE || + field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT) { + // Handle float comparison to prevent -Wfloat-equal warnings + format("if (!($prefix$$name$() <= 0 && $prefix$$name$() >= 0)) {\n"); } else { - printer->Print( - "if ($prefix$$name$() != 0) {\n", - "prefix", prefix, - "name", FieldName(field)); + format("if ($prefix$$name$() != 0) {\n"); } - printer->Indent(); + format.Indent(); return true; - } else if (field->containing_oneof()) { - printer->Print( - "if (has_$name$()) {\n", - "name", FieldName(field)); - printer->Indent(); + } else if (field->real_containing_oneof()) { + format("if (_internal_has_$name$()) {\n"); + format.Indent(); return true; } return false; @@ -415,33 +241,33 @@ bool HasHasMethod(const FieldDescriptor* field) { return true; } // For message types without true field presence, only fields with a message - // type have a has_$name$() method. - return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE; + // type or inside an one-of have a has_$name$() method. + return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || + field->has_optional_keyword() || field->real_containing_oneof(); } // Collects map entry message type information. -void CollectMapInfo(const Descriptor* descriptor, - std::map* variables) { +void CollectMapInfo(const Options& options, const Descriptor* descriptor, + std::map* variables) { GOOGLE_CHECK(IsMapEntryMessage(descriptor)); + std::map& vars = *variables; const FieldDescriptor* key = descriptor->FindFieldByName("key"); const FieldDescriptor* val = descriptor->FindFieldByName("value"); - (*variables)["key"] = PrimitiveTypeName(key->cpp_type()); + vars["key_cpp"] = PrimitiveTypeName(options, key->cpp_type()); switch (val->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: - (*variables)["val"] = FieldMessageTypeName(val); + vars["val_cpp"] = FieldMessageTypeName(val, options); break; case FieldDescriptor::CPPTYPE_ENUM: - (*variables)["val"] = ClassName(val->enum_type(), true); + vars["val_cpp"] = ClassName(val->enum_type(), true); break; default: - (*variables)["val"] = PrimitiveTypeName(val->cpp_type()); - } - (*variables)["key_wire_type"] = - "::google::protobuf::internal::WireFormatLite::TYPE_" + - ToUpper(DeclaredTypeMethodName(key->type())); - (*variables)["val_wire_type"] = - "::google::protobuf::internal::WireFormatLite::TYPE_" + - ToUpper(DeclaredTypeMethodName(val->type())); + vars["val_cpp"] = PrimitiveTypeName(options, val->cpp_type()); + } + vars["key_wire_type"] = + "TYPE_" + ToUpper(DeclaredTypeMethodName(key->type())); + vars["val_wire_type"] = + "TYPE_" + ToUpper(DeclaredTypeMethodName(val->type())); } // Does the given field have a private (internal helper only) has_$name$() @@ -449,13 +275,40 @@ void CollectMapInfo(const Descriptor* descriptor, bool HasPrivateHasMethod(const FieldDescriptor* field) { // Only for oneofs in message types with no field presence. has_$name$(), // based on the oneof case, is still useful internally for generated code. - return (!HasFieldPresence(field->file()) && - field->containing_oneof() != NULL); + return (!HasFieldPresence(field->file()) && field->real_containing_oneof()); +} + +// TODO(ckennelly): Cull these exclusions if/when these protos do not have +// their methods overridden by subclasses. + +bool ShouldMarkClassAsFinal(const Descriptor* descriptor, + const Options& options) { + return true; } +bool ShouldMarkClearAsFinal(const Descriptor* descriptor, + const Options& options) { + static std::set exclusions{ + }; + + const std::string name = ClassName(descriptor, true); + return exclusions.find(name) == exclusions.end() || + options.opensource_runtime; +} + +// Returns true to make the message serialize in order, decided by the following +// factors in the order of precedence. +// --options().message_set_wire_format() == true +// --the message is in the allowlist (true) +// --GOOGLE_PROTOBUF_SHUFFLE_SERIALIZE is defined (false) +// --a ranage of message names that are allowed to stay in order (true) +bool ShouldSerializeInOrder(const Descriptor* descriptor, + const Options& options) { + return true; +} -bool TableDrivenParsingEnabled( - const Descriptor* descriptor, const Options& options) { +bool TableDrivenParsingEnabled(const Descriptor* descriptor, + const Options& options) { if (!options.table_driven_parsing) { return false; } @@ -463,20 +316,30 @@ bool TableDrivenParsingEnabled( // Consider table-driven parsing. We only do this if: // - We have has_bits for fields. This avoids a check on every field we set // when are present (the common case). - if (!HasFieldPresence(descriptor->file())) { - return false; + bool has_hasbit = false; + for (int i = 0; i < descriptor->field_count(); i++) { + if (HasHasbit(descriptor->field(i))) { + has_hasbit = true; + break; + } } + if (!has_hasbit) return false; + const double table_sparseness = 0.5; int max_field_number = 0; - for (int i = 0; i < descriptor->field_count(); i++) { - const FieldDescriptor* field = descriptor->field(i); + for (auto field : FieldRange(descriptor)) { if (max_field_number < field->number()) { max_field_number = field->number(); } // - There are no weak fields. - if (field->options().weak()) { + if (IsWeak(field, options)) { + return false; + } + + // - There are no lazy fields (they require the non-lite library). + if (IsLazy(field, options)) { return false; } } @@ -501,91 +364,240 @@ bool TableDrivenParsingEnabled( return true; } -void SetUnknkownFieldsVariable(const Descriptor* descriptor, - const Options& options, - std::map* variables) { - if (UseUnknownFieldSet(descriptor->file(), options)) { - (*variables)["unknown_fields_type"] = "::google::protobuf::UnknownFieldSet"; - } else { - (*variables)["unknown_fields_type"] = "::std::string"; +bool IsCrossFileMapField(const FieldDescriptor* field) { + if (!field->is_map()) { + return false; } - if (AlwaysPreserveUnknownFields(descriptor)) { - (*variables)["have_unknown_fields"] = - "_internal_metadata_.have_unknown_fields()"; - (*variables)["unknown_fields"] = "_internal_metadata_.unknown_fields()"; - } else { - (*variables)["have_unknown_fields"] = - "(_internal_metadata_.have_unknown_fields() && " - " ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())"; - (*variables)["unknown_fields"] = - "(::google::protobuf::internal::GetProto3PreserveUnknownsDefault()" - " ? _internal_metadata_.unknown_fields()" - " : _internal_metadata_.default_instance())"; - } - (*variables)["mutable_unknown_fields"] = - "_internal_metadata_.mutable_unknown_fields()"; + + const Descriptor* d = field->message_type(); + const FieldDescriptor* value = d->FindFieldByNumber(2); + + return IsCrossFileMessage(value); +} + +bool IsCrossFileMaybeMap(const FieldDescriptor* field) { + if (IsCrossFileMapField(field)) { + return true; + } + + return IsCrossFileMessage(field); +} + +bool IsRequired(const std::vector& v) { + return v.front()->is_required(); +} + +// Collects neighboring fields based on a given criteria (equivalent predicate). +template +std::vector> CollectFields( + const std::vector& fields, + const Predicate& equivalent) { + std::vector> chunks; + for (auto field : fields) { + if (chunks.empty() || !equivalent(chunks.back().back(), field)) { + chunks.emplace_back(); + } + chunks.back().push_back(field); + } + return chunks; +} + +// Returns a bit mask based on has_bit index of "fields" that are typically on +// the same chunk. It is used in a group presence check where _has_bits_ is +// masked to tell if any thing in "fields" is present. +uint32 GenChunkMask(const std::vector& fields, + const std::vector& has_bit_indices) { + GOOGLE_CHECK(!fields.empty()); + int first_index_offset = has_bit_indices[fields.front()->index()] / 32; + uint32 chunk_mask = 0; + for (auto field : fields) { + // "index" defines where in the _has_bits_ the field appears. + int index = has_bit_indices[field->index()]; + GOOGLE_CHECK_EQ(first_index_offset, index / 32); + chunk_mask |= static_cast(1) << (index % 32); + } + GOOGLE_CHECK_NE(0, chunk_mask); + return chunk_mask; +} + +// Return the number of bits set in n, a non-negative integer. +static int popcnt(uint32 n) { + int result = 0; + while (n != 0) { + result += (n & 1); + n = n / 2; + } + return result; +} + +// For a run of cold chunks, opens and closes an external if statement that +// checks multiple has_bits words to skip bulk of cold fields. +class ColdChunkSkipper { + public: + ColdChunkSkipper( + const Options& options, + const std::vector>& chunks, + const std::vector& has_bit_indices, const double cold_threshold) + : chunks_(chunks), + has_bit_indices_(has_bit_indices), + access_info_map_(options.access_info_map), + cold_threshold_(cold_threshold) { + SetCommonVars(options, &variables_); + } + + // May open an external if check for a batch of cold fields. "from" is the + // prefix to _has_bits_ to allow MergeFrom to use "from._has_bits_". + // Otherwise, it should be "". + void OnStartChunk(int chunk, int cached_has_word_index, + const std::string& from, io::Printer* printer); + bool OnEndChunk(int chunk, io::Printer* printer); + + private: + bool IsColdChunk(int chunk); + + int HasbitWord(int chunk, int offset) { + return has_bit_indices_[chunks_[chunk][offset]->index()] / 32; + } + + const std::vector>& chunks_; + const std::vector& has_bit_indices_; + const AccessInfoMap* access_info_map_; + const double cold_threshold_; + std::map variables_; + int limit_chunk_ = -1; +}; + +// Tuning parameters for ColdChunkSkipper. +const double kColdRatio = 0.005; + +bool ColdChunkSkipper::IsColdChunk(int chunk) { + // Mark this variable as used until it is actually used + (void)cold_threshold_; + return false; +} + + +void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_word_index, + const std::string& from, + io::Printer* printer) { + Formatter format(printer, variables_); + if (!access_info_map_) { + return; + } else if (chunk < limit_chunk_) { + // We are already inside a run of cold chunks. + return; + } else if (!IsColdChunk(chunk)) { + // We can't start a run of cold chunks. + return; + } + + // Find the end of consecutive cold chunks. + limit_chunk_ = chunk; + while (limit_chunk_ < chunks_.size() && IsColdChunk(limit_chunk_)) { + limit_chunk_++; + } + + if (limit_chunk_ <= chunk + 1) { + // Require at least two chunks to emit external has_bit checks. + limit_chunk_ = -1; + return; + } + + // Emit has_bit check for each has_bit_dword index. + format("if (PROTOBUF_PREDICT_FALSE("); + int first_word = HasbitWord(chunk, 0); + while (chunk < limit_chunk_) { + uint32 mask = 0; + int this_word = HasbitWord(chunk, 0); + // Generate mask for chunks on the same word. + for (; chunk < limit_chunk_ && HasbitWord(chunk, 0) == this_word; chunk++) { + for (auto field : chunks_[chunk]) { + int hasbit_index = has_bit_indices_[field->index()]; + // Fields on a chunk must be in the same word. + GOOGLE_CHECK_EQ(this_word, hasbit_index / 32); + mask |= 1 << (hasbit_index % 32); + } + } + + if (this_word != first_word) { + format(" ||\n "); + } + format.Set("mask", strings::Hex(mask, strings::ZERO_PAD_8)); + if (this_word == cached_has_word_index) { + format("(cached_has_bits & 0x$mask$u) != 0"); + } else { + format("($1$_has_bits_[$2$] & 0x$mask$u) != 0", from, this_word); + } + } + format(")) {\n"); + format.Indent(); +} + +bool ColdChunkSkipper::OnEndChunk(int chunk, io::Printer* printer) { + Formatter format(printer, variables_); + if (chunk != limit_chunk_ - 1) { + return false; + } + format.Outdent(); + format("}\n"); + return true; } } // anonymous namespace // =================================================================== -MessageGenerator::MessageGenerator(const Descriptor* descriptor, - const Options& options, - SCCAnalyzer* scc_analyzer) +MessageGenerator::MessageGenerator( + const Descriptor* descriptor, + const std::map& vars, int index_in_file_messages, + const Options& options, MessageSCCAnalyzer* scc_analyzer) : descriptor_(descriptor), + index_in_file_messages_(index_in_file_messages), classname_(ClassName(descriptor, false)), options_(options), - field_generators_(descriptor, options), + field_generators_(descriptor, options, scc_analyzer), max_has_bit_index_(0), - nested_generators_(new google::protobuf::scoped_ptr< - MessageGenerator>[descriptor->nested_type_count()]), - enum_generators_( - new google::protobuf::scoped_ptr[descriptor->enum_type_count()]), - extension_generators_(new google::protobuf::scoped_ptr< - ExtensionGenerator>[descriptor->extension_count()]), - use_dependent_base_(false), num_weak_fields_(0), - scc_analyzer_(scc_analyzer) { + scc_analyzer_(scc_analyzer), + variables_(vars) { + if (!message_layout_helper_) { + message_layout_helper_.reset(new PaddingOptimizer()); + } + + // Variables that apply to this class + variables_["classname"] = classname_; + variables_["classtype"] = QualifiedClassName(descriptor_, options); + variables_["full_name"] = descriptor_->full_name(); + variables_["superclass"] = SuperClassName(descriptor_, options_); + // Compute optimized field order to be used for layout and initialization // purposes. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->options().weak()) { + for (auto field : FieldRange(descriptor_)) { + if (IsFieldStripped(field, options_)) { + continue; + } + + if (IsWeak(field, options_)) { num_weak_fields_++; - } else if (!field->containing_oneof()) { + } else if (!field->real_containing_oneof()) { optimized_order_.push_back(field); } } - OptimizePadding(&optimized_order_, options_); - if (HasFieldPresence(descriptor_->file())) { - // We use -1 as a sentinel. - has_bit_indices_.resize(descriptor_->field_count(), -1); - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - // Skip fields that do not have has bits. - if (field->is_repeated()) { - continue; - } + message_layout_helper_->OptimizeLayout(&optimized_order_, options_); + // This message has hasbits iff one or more fields need one. + for (auto field : optimized_order_) { + if (HasHasbit(field)) { + if (has_bit_indices_.empty()) { + has_bit_indices_.resize(descriptor_->field_count(), kNoHasbit); + } has_bit_indices_[field->index()] = max_has_bit_index_++; } } - for (int i = 0; i < descriptor->nested_type_count(); i++) { - nested_generators_[i].reset(new MessageGenerator(descriptor->nested_type(i), - options, scc_analyzer)); - } - - for (int i = 0; i < descriptor->enum_type_count(); i++) { - enum_generators_[i].reset( - new EnumGenerator(descriptor->enum_type(i), options)); - } - - for (int i = 0; i < descriptor->extension_count(); i++) { - extension_generators_[i].reset( - new ExtensionGenerator(descriptor->extension(i), options)); + if (!has_bit_indices_.empty()) { + field_generators_.SetHasBitIndices(has_bit_indices_); } num_required_fields_ = 0; @@ -593,83 +605,51 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, if (descriptor->field(i)->is_required()) { ++num_required_fields_; } - if (options.proto_h && IsFieldDependent(descriptor->field(i))) { - use_dependent_base_ = true; - } - } - if (options.proto_h && descriptor->oneof_decl_count() > 0) { - // Always make oneofs dependent. - use_dependent_base_ = true; } table_driven_ = TableDrivenParsingEnabled(descriptor_, options_); } -MessageGenerator::~MessageGenerator() {} +MessageGenerator::~MessageGenerator() = default; size_t MessageGenerator::HasBitsSize() const { - size_t sizeof_has_bits = (max_has_bit_index_ + 31) / 32 * 4; - if (sizeof_has_bits == 0) { - // Zero-size arrays aren't technically allowed, and MSVC in particular - // doesn't like them. We still need to declare these arrays to make - // other code compile. Since this is an uncommon case, we'll just declare - // them with size 1 and waste some space. Oh well. - sizeof_has_bits = 4; - } + return (max_has_bit_index_ + 31) / 32; +} - return sizeof_has_bits; +int MessageGenerator::HasBitIndex(const FieldDescriptor* field) const { + return has_bit_indices_.empty() ? kNoHasbit + : has_bit_indices_[field->index()]; } -void MessageGenerator::Flatten(std::vector* list) { - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - nested_generators_[i]->Flatten(list); - } - index_in_file_messages_ = list->size(); - list->push_back(this); +int MessageGenerator::HasByteIndex(const FieldDescriptor* field) const { + int hasbit = HasBitIndex(field); + return hasbit == kNoHasbit ? kNoHasbit : hasbit / 8; +} + +int MessageGenerator::HasWordIndex(const FieldDescriptor* field) const { + int hasbit = HasBitIndex(field); + return hasbit == kNoHasbit ? kNoHasbit : hasbit / 32; } void MessageGenerator::AddGenerators( - std::vector* enum_generators, - std::vector* extension_generators) { + std::vector>* enum_generators, + std::vector>* extension_generators) { for (int i = 0; i < descriptor_->enum_type_count(); i++) { - enum_generators->push_back(enum_generators_[i].get()); + enum_generators->emplace_back( + new EnumGenerator(descriptor_->enum_type(i), variables_, options_)); + enum_generators_.push_back(enum_generators->back().get()); } for (int i = 0; i < descriptor_->extension_count(); i++) { - extension_generators->push_back(extension_generators_[i].get()); - } -} - -void MessageGenerator::FillMessageForwardDeclarations( - std::map* class_names) { - (*class_names)[classname_] = descriptor_; -} - -void MessageGenerator:: -GenerateDependentFieldAccessorDeclarations(io::Printer* printer) { - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - - PrintFieldComment(printer, field); - - std::map vars; - SetCommonFieldVariables(field, &vars, options_); - - if (use_dependent_base_ && IsFieldDependent(field)) { - // If the message is dependent, the inline clear_*() method will need - // to delete the message type, so it must be in the dependent base - // class. (See also GenerateFieldAccessorDeclarations.) - printer->Print(vars, "$deprecated_attr$void clear_$name$();\n"); - } - // Generate type-specific accessor declarations. - field_generators_.get(field).GenerateDependentAccessorDeclarations(printer); - printer->Print("\n"); + extension_generators->emplace_back( + new ExtensionGenerator(descriptor_->extension(i), options_)); + extension_generators_.push_back(extension_generators->back().get()); } } -void MessageGenerator:: -GenerateFieldAccessorDeclarations(io::Printer* printer) { +void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) { + Formatter format(printer, variables_); // optimized_fields_ does not contain fields where - // field->containing_oneof() != NULL + // field->real_containing_oneof() // so we need to iterate over those as well. // // We place the non-oneof fields in optimized_order_, as that controls the @@ -678,461 +658,487 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { std::vector ordered_fields; ordered_fields.reserve(descriptor_->field_count()); - ordered_fields.insert( - ordered_fields.begin(), optimized_order_.begin(), optimized_order_.end()); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof() == NULL && !field->options().weak()) { + ordered_fields.insert(ordered_fields.begin(), optimized_order_.begin(), + optimized_order_.end()); + for (auto field : FieldRange(descriptor_)) { + if (!field->real_containing_oneof() && !field->options().weak() && + !IsFieldStripped(field, options_)) { continue; } ordered_fields.push_back(field); } - for (int i = 0; i < ordered_fields.size(); i++) { - const FieldDescriptor* field = ordered_fields[i]; + if (!ordered_fields.empty()) { + format("enum : int {\n"); + for (auto field : ordered_fields) { + Formatter::SaveState save(&format); + + std::map vars; + SetCommonFieldVariables(field, &vars, options_); + format.AddMap(vars); + format(" ${1$$2$$}$ = $number$,\n", field, FieldConstantName(field)); + } + format("};\n"); + } + for (auto field : ordered_fields) { + PrintFieldComment(format, field); - PrintFieldComment(printer, field); + Formatter::SaveState save(&format); - std::map vars; + std::map vars; SetCommonFieldVariables(field, &vars, options_); - vars["constant_name"] = FieldConstantName(field); - - bool dependent_field = use_dependent_base_ && IsFieldDependent(field); - if (dependent_field && - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && - !field->is_map()) { - // If this field is dependent, the dependent base class determines - // the message type from the derived class (which is a template - // parameter). This typedef is for that: - printer->Print( - "private:\n" - "typedef $field_type$ $dependent_type$;\n" - "public:\n", - "field_type", FieldMessageTypeName(field), - "dependent_type", DependentTypeName(field)); - } + format.AddMap(vars); if (field->is_repeated()) { - printer->Print(vars, "$deprecated_attr$int ${$$name$_size$}$() const;\n"); - printer->Annotate("{", "}", field); + format("$deprecated_attr$int ${1$$name$_size$}$() const$2$\n", field, + !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}"); + if (!IsFieldStripped(field, options_)) { + format( + "private:\n" + "int ${1$_internal_$name$_size$}$() const;\n" + "public:\n", + field); + } } else if (HasHasMethod(field)) { - printer->Print(vars, "$deprecated_attr$bool ${$has_$name$$}$() const;\n"); - printer->Annotate("{", "}", field); + format("$deprecated_attr$bool ${1$has_$name$$}$() const$2$\n", field, + !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}"); + if (!IsFieldStripped(field, options_)) { + format( + "private:\n" + "bool _internal_has_$name$() const;\n" + "public:\n"); + } } else if (HasPrivateHasMethod(field)) { - printer->Print(vars, - "private:\n" - "bool ${$has_$name$$}$() const;\n" - "public:\n"); - printer->Annotate("{", "}", field); - } - - if (!dependent_field) { - // If this field is dependent, then its clear_() method is in the - // depenent base class. (See also GenerateDependentAccessorDeclarations.) - printer->Print(vars, "$deprecated_attr$void ${$clear_$name$$}$();\n"); - printer->Annotate("{", "}", field); + if (!IsFieldStripped(field, options_)) { + format( + "private:\n" + "bool ${1$_internal_has_$name$$}$() const;\n" + "public:\n", + field); + } } - printer->Print(vars, - "$deprecated_attr$static const int $constant_name$ = " - "$number$;\n"); - printer->Annotate("constant_name", field); + format("$deprecated_attr$void ${1$clear_$name$$}$()$2$\n", field, + !IsFieldStripped(field, options_) ? ";" : "{__builtin_trap();}"); // Generate type-specific accessor declarations. field_generators_.get(field).GenerateAccessorDeclarations(printer); - printer->Print("\n"); + format("\n"); } if (descriptor_->extension_range_count() > 0) { // Generate accessors for extensions. We just call a macro located in // extension_set.h since the accessors about 80 lines of static code. - printer->Print( - "GOOGLE_PROTOBUF_EXTENSION_ACCESSORS($classname$)\n", - "classname", classname_); - } - - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( + format("$GOOGLE_PROTOBUF$_EXTENSION_ACCESSORS($classname$)\n"); + // Generate MessageSet specific APIs for proto2 MessageSet. + // For testing purposes we don't check for bridge.MessageSet, so + // we don't use IsProto2MessageSet + if (descriptor_->options().message_set_wire_format() && + !options_.opensource_runtime && !options_.lite_implicit_weak_fields) { + // Special-case MessageSet + format("GOOGLE_PROTOBUF_EXTENSION_MESSAGE_SET_ACCESSORS($classname$)\n"); + } + } + + for (auto oneof : OneOfRange(descriptor_)) { + Formatter::SaveState saver(&format); + format.Set("oneof_name", oneof->name()); + format.Set("camel_oneof_name", UnderscoresToCamelCase(oneof->name(), true)); + format( + "void ${1$clear_$oneof_name$$}$();\n" "$camel_oneof_name$Case $oneof_name$_case() const;\n", - "camel_oneof_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true), - "oneof_name", descriptor_->oneof_decl(i)->name()); + oneof); } } -void MessageGenerator:: -GenerateDependentFieldAccessorDefinitions(io::Printer* printer) { - if (!use_dependent_base_) return; - - printer->Print("// $classname$\n\n", "classname", - DependentBaseClassTemplateName(descriptor_)); - - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - - if (field->options().weak()) continue; - - PrintFieldComment(printer, field); - - // These functions are not really dependent: they are part of the - // (non-dependent) derived class. However, they need to live outside - // any #ifdef guards, so we treat them as if they were dependent. - // - // See the comment in FileGenerator::GenerateInlineFunctionDefinitions - // for a more complete explanation. - if (use_dependent_base_ && IsFieldDependent(field)) { - std::map vars; - SetCommonFieldVariables(field, &vars, options_); - vars["inline"] = "inline "; - if (field->containing_oneof()) { - vars["field_name"] = UnderscoresToCamelCase(field->name(), true); - vars["oneof_name"] = field->containing_oneof()->name(); - vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index()); - GenerateOneofMemberHasBits(field, vars, printer); - } else if (!field->is_repeated()) { - // There will be no header guard, so this always has to be inline. - GenerateSingularFieldHasBits(field, vars, printer); - } - // vars needed for clear_(), which is in the dependent base: - // (See also GenerateDependentFieldAccessorDeclarations.) - vars["tmpl"] = "template\n"; - vars["dependent_classname"] = - DependentBaseClassTemplateName(descriptor_) + ""; - vars["this_message"] = DependentBaseDownCast(); - vars["this_const_message"] = DependentBaseConstDownCast(); - GenerateFieldClear(field, vars, printer); - } - - // Generate type-specific accessors. - field_generators_.get(field) - .GenerateDependentInlineAccessorDefinitions(printer); - - printer->Print("\n"); +void MessageGenerator::GenerateSingularFieldHasBits( + const FieldDescriptor* field, Formatter format) { + if (IsFieldStripped(field, options_)) { + format( + "inline bool $classname$::has_$name$() const { " + "__builtin_trap(); }\n"); + return; } - - // Generate has_$name$() and clear_has_$name$() functions for oneofs - // Similar to other has-bits, these must always be in the header if we - // are using a dependent base class. - GenerateOneofHasBits(printer, true /* is_inline */); -} - -void MessageGenerator:: -GenerateSingularFieldHasBits(const FieldDescriptor* field, - std::map vars, - io::Printer* printer) { if (field->options().weak()) { - printer->Print( - vars, - "$inline$" - "bool $classname$::has_$name$() const {\n" + format( + "inline bool $classname$::has_$name$() const {\n" + "$annotate_accessor$" " return _weak_field_map_.Has($number$);\n" "}\n"); return; } - if (HasFieldPresence(descriptor_->file())) { - // N.B.: without field presence, we do not use has-bits or generate - // has_$name$() methods. - int has_bit_index = has_bit_indices_[field->index()]; - GOOGLE_CHECK_GE(has_bit_index, 0); - - vars["has_array_index"] = SimpleItoa(has_bit_index / 32); - vars["has_mask"] = StrCat(strings::Hex(1u << (has_bit_index % 32), - strings::ZERO_PAD_8)); - printer->Print(vars, - "$inline$" - "bool $classname$::has_$name$() const {\n" - " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n" - "}\n" - "$inline$" - "void $classname$::set_has_$name$() {\n" - " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n" - "}\n" - "$inline$" - "void $classname$::clear_has_$name$() {\n" - " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n" - "}\n"); - } else { + if (HasHasbit(field)) { + int has_bit_index = HasBitIndex(field); + GOOGLE_CHECK_NE(has_bit_index, kNoHasbit); + + format.Set("has_array_index", has_bit_index / 32); + format.Set("has_mask", + strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); + format( + "inline bool $classname$::_internal_has_$name$() const {\n" + " bool value = " + "(_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"); + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !IsLazy(field, options_)) { + // We maintain the invariant that for a submessage x, has_x() returning + // true implies that x_ is not null. By giving this information to the + // compiler, we allow it to eliminate unnecessary null checks later on. + format(" PROTOBUF_ASSUME(!value || $name$_ != nullptr);\n"); + } + + format( + " return value;\n" + "}\n" + "inline bool $classname$::has_$name$() const {\n" + "$annotate_accessor$" + " return _internal_has_$name$();\n" + "}\n"); + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { // Message fields have a has_$name$() method. - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - bool is_lazy = false; - if (is_lazy) { - printer->Print(vars, - "$inline$" - "bool $classname$::has_$name$() const {\n" + if (IsLazy(field, options_)) { + format( + "inline bool $classname$::_internal_has_$name$() const {\n" " return !$name$_.IsCleared();\n" "}\n"); - } else { - printer->Print( - vars, - "$inline$" - "bool $classname$::has_$name$() const {\n" - " return this != internal_default_instance() && $name$_ != NULL;\n" - "}\n"); - } + } else { + format( + "inline bool $classname$::_internal_has_$name$() const {\n" + " return this != internal_default_instance() " + "&& $name$_ != nullptr;\n" + "}\n"); } + format( + "inline bool $classname$::has_$name$() const {\n" + "$annotate_accessor$" + " return _internal_has_$name$();\n" + "}\n"); } } -void MessageGenerator:: -GenerateOneofHasBits(io::Printer* printer, bool is_inline) { - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - std::map vars; - vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); - vars["cap_oneof_name"] = - ToUpper(descriptor_->oneof_decl(i)->name()); - vars["classname"] = classname_; - vars["inline"] = (is_inline ? "inline " : ""); - printer->Print( - vars, - "$inline$" - "bool $classname$::has_$oneof_name$() const {\n" +void MessageGenerator::GenerateOneofHasBits(io::Printer* printer) { + Formatter format(printer, variables_); + for (auto oneof : OneOfRange(descriptor_)) { + format.Set("oneof_name", oneof->name()); + format.Set("oneof_index", oneof->index()); + format.Set("cap_oneof_name", ToUpper(oneof->name())); + format( + "inline bool $classname$::has_$oneof_name$() const {\n" " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n" "}\n" - "$inline$" - "void $classname$::clear_has_$oneof_name$() {\n" + "inline void $classname$::clear_has_$oneof_name$() {\n" " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n" "}\n"); } } -void MessageGenerator:: -GenerateOneofMemberHasBits(const FieldDescriptor* field, - const std::map& vars, - io::Printer* printer) { +void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field, + const Formatter& format) { + if (IsFieldStripped(field, options_)) { + if (HasHasMethod(field)) { + format( + "inline bool $classname$::has_$name$() const { " + "__builtin_trap(); }\n"); + } + format( + "inline void $classname$::set_has_$name$() { __builtin_trap(); " + "}\n"); + return; + } // Singular field in a oneof // N.B.: Without field presence, we do not use has-bits or generate // has_$name$() methods, but oneofs still have set_has_$name$(). // Oneofs also have has_$name$() but only as a private helper // method, so that generated code is slightly cleaner (vs. comparing // _oneof_case_[index] against a constant everywhere). - printer->Print(vars, - "$inline$" - "bool $classname$::has_$name$() const {\n" - " return $oneof_name$_case() == k$field_name$;\n" - "}\n"); - printer->Print(vars, - "$inline$" - "void $classname$::set_has_$name$() {\n" - " _oneof_case_[$oneof_index$] = k$field_name$;\n" - "}\n"); + // + // If has_$name$() is private, there is no need to add an internal accessor. + // Only annotate public accessors. + if (HasHasMethod(field)) { + format( + "inline bool $classname$::_internal_has_$name$() const {\n" + " return $oneof_name$_case() == k$field_name$;\n" + "}\n" + "inline bool $classname$::has_$name$() const {\n" + "$annotate_accessor$" + " return _internal_has_$name$();\n" + "}\n"); + } else if (HasPrivateHasMethod(field)) { + format( + "inline bool $classname$::_internal_has_$name$() const {\n" + " return $oneof_name$_case() == k$field_name$;\n" + "}\n"); + } + // set_has_$name$() for oneof fields is always private; hence should not be + // annotated. + format( + "inline void $classname$::set_has_$name$() {\n" + " _oneof_case_[$oneof_index$] = k$field_name$;\n" + "}\n"); } -void MessageGenerator:: -GenerateFieldClear(const FieldDescriptor* field, - const std::map& vars, - io::Printer* printer) { - // Generate clear_$name$() (See GenerateFieldAccessorDeclarations and - // GenerateDependentFieldAccessorDeclarations, $dependent_classname$ is - // set by the Generate*Definitions functions.) - printer->Print(vars, - "$tmpl$" - "$inline$" - "void $dependent_classname$::clear_$name$() {\n"); - - printer->Indent(); - - if (field->containing_oneof()) { +void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field, + bool is_inline, Formatter format) { + if (IsFieldStripped(field, options_)) { + format("void $classname$::clear_$name$() { __builtin_trap(); }\n"); + return; + } + + // Generate clear_$name$(). + if (is_inline) { + format("inline "); + } + format( + "void $classname$::clear_$name$() {\n" + "$annotate_accessor$"); + + format.Indent(); + + if (field->real_containing_oneof()) { // Clear this field only if it is the active field in this oneof, // otherwise ignore - printer->Print(vars, - "if ($this_message$has_$name$()) {\n"); - printer->Indent(); - field_generators_.get(field) - .GenerateClearingCode(printer); - printer->Print(vars, - "$this_message$clear_has_$oneof_name$();\n"); - printer->Outdent(); - printer->Print("}\n"); + format("if (_internal_has_$name$()) {\n"); + format.Indent(); + field_generators_.get(field).GenerateClearingCode(format.printer()); + format("clear_has_$oneof_name$();\n"); + format.Outdent(); + format("}\n"); } else { - field_generators_.get(field) - .GenerateClearingCode(printer); - if (HasFieldPresence(descriptor_->file())) { - if (!field->is_repeated() && !field->options().weak()) { - printer->Print(vars, - "$this_message$clear_has_$name$();\n"); - } + field_generators_.get(field).GenerateClearingCode(format.printer()); + if (HasHasbit(field)) { + int has_bit_index = HasBitIndex(field); + format.Set("has_array_index", has_bit_index / 32); + format.Set("has_mask", + strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); + format("_has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"); } } - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } -void MessageGenerator:: -GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) { - printer->Print("// $classname$\n\n", "classname", classname_); +void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) { + Formatter format(printer, variables_); + format("// $classname$\n\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); + for (auto field : FieldRange(descriptor_)) { + PrintFieldComment(format, field); - PrintFieldComment(printer, field); + if (IsFieldStripped(field, options_)) { + continue; + } - std::map vars; + std::map vars; SetCommonFieldVariables(field, &vars, options_); - vars["inline"] = is_inline ? "inline " : ""; - if (use_dependent_base_ && IsFieldDependent(field)) { - vars["tmpl"] = "template\n"; - vars["dependent_classname"] = - DependentBaseClassTemplateName(descriptor_) + ""; - vars["this_message"] = "reinterpret_cast(this)->"; - vars["this_const_message"] = "reinterpret_cast(this)->"; - } else { - vars["tmpl"] = ""; - vars["dependent_classname"] = vars["classname"]; - vars["this_message"] = ""; - vars["this_const_message"] = ""; - } + + Formatter::SaveState saver(&format); + format.AddMap(vars); // Generate has_$name$() or $name$_size(). if (field->is_repeated()) { - printer->Print(vars, - "$inline$" - "int $classname$::$name$_size() const {\n" - " return $name$_.size();\n" - "}\n"); - } else if (field->containing_oneof()) { - vars["field_name"] = UnderscoresToCamelCase(field->name(), true); - vars["oneof_name"] = field->containing_oneof()->name(); - vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index()); - if (!use_dependent_base_ || !IsFieldDependent(field)) { - GenerateOneofMemberHasBits(field, vars, printer); + if (IsFieldStripped(field, options_)) { + format( + "inline int $classname$::$name$_size() const { " + "__builtin_trap(); }\n"); + } else { + format( + "inline int $classname$::_internal_$name$_size() const {\n" + " return $name$_$1$.size();\n" + "}\n" + "inline int $classname$::$name$_size() const {\n" + "$annotate_accessor$" + " return _internal_$name$_size();\n" + "}\n", + IsImplicitWeakField(field, options_, scc_analyzer_) && + field->message_type() + ? ".weak" + : ""); } + } else if (field->real_containing_oneof()) { + format.Set("field_name", UnderscoresToCamelCase(field->name(), true)); + format.Set("oneof_name", field->containing_oneof()->name()); + format.Set("oneof_index", + StrCat(field->containing_oneof()->index())); + GenerateOneofMemberHasBits(field, format); } else { // Singular field. - if (!use_dependent_base_ || !IsFieldDependent(field)) { - GenerateSingularFieldHasBits(field, vars, printer); - } + GenerateSingularFieldHasBits(field, format); } - if (!use_dependent_base_ || !IsFieldDependent(field)) { - GenerateFieldClear(field, vars, printer); + if (!IsCrossFileMaybeMap(field)) { + GenerateFieldClear(field, true, format); } // Generate type-specific accessors. - field_generators_.get(field).GenerateInlineAccessorDefinitions(printer, - is_inline); + if (!IsFieldStripped(field, options_)) { + field_generators_.get(field).GenerateInlineAccessorDefinitions(printer); + } - printer->Print("\n"); + format("\n"); } - if (!use_dependent_base_) { - // Generate has_$name$() and clear_has_$name$() functions for oneofs - // If we aren't using a dependent base, they can be with the other functions - // that are #ifdef-guarded. - GenerateOneofHasBits(printer, is_inline); - } + // Generate has_$name$() and clear_has_$name$() functions for oneofs. + GenerateOneofHasBits(printer); } -void MessageGenerator:: -GenerateDependentBaseClassDefinition(io::Printer* printer) { - if (!use_dependent_base_) { +void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { + Formatter format(printer, variables_); + format.Set("class_final", ShouldMarkClassAsFinal(descriptor_, options_) + ? "PROTOBUF_FINAL" + : ""); + + if (IsMapEntryMessage(descriptor_)) { + std::map vars; + CollectMapInfo(options_, descriptor_, &vars); + vars["lite"] = + HasDescriptorMethods(descriptor_->file(), options_) ? "" : "Lite"; + format.AddMap(vars); + format( + "class $classname$ : public " + "::$proto_ns$::internal::MapEntry$lite$<$classname$, \n" + " $key_cpp$, $val_cpp$,\n" + " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n" + " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> {\n" + "public:\n" + " typedef ::$proto_ns$::internal::MapEntry$lite$<$classname$, \n" + " $key_cpp$, $val_cpp$,\n" + " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n" + " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> " + "SuperType;\n" + " $classname$();\n" + " explicit constexpr $classname$(\n" + " ::$proto_ns$::internal::ConstantInitialized);\n" + " explicit $classname$(::$proto_ns$::Arena* arena);\n" + " void MergeFrom(const $classname$& other);\n" + " static const $classname$* internal_default_instance() { return " + "reinterpret_cast(&_$classname$_default_instance_); }\n"); + auto utf8_check = GetUtf8CheckMode(descriptor_->field(0), options_); + if (descriptor_->field(0)->type() == FieldDescriptor::TYPE_STRING && + utf8_check != NONE) { + if (utf8_check == STRICT) { + format( + " static bool ValidateKey(std::string* s) {\n" + " return ::$proto_ns$::internal::WireFormatLite::" + "VerifyUtf8String(s->data(), static_cast(s->size()), " + "::$proto_ns$::internal::WireFormatLite::PARSE, \"$1$\");\n" + " }\n", + descriptor_->field(0)->full_name()); + } else { + GOOGLE_CHECK_EQ(utf8_check, VERIFY); + format( + " static bool ValidateKey(std::string* s) {\n" + "#ifndef NDEBUG\n" + " ::$proto_ns$::internal::WireFormatLite::VerifyUtf8String(\n" + " s->data(), static_cast(s->size()), " + "::$proto_ns$::internal::" + "WireFormatLite::PARSE, \"$1$\");\n" + "#else\n" + " (void) s;\n" + "#endif\n" + " return true;\n" + " }\n", + descriptor_->field(0)->full_name()); + } + } else { + format(" static bool ValidateKey(void*) { return true; }\n"); + } + if (descriptor_->field(1)->type() == FieldDescriptor::TYPE_STRING && + utf8_check != NONE) { + if (utf8_check == STRICT) { + format( + " static bool ValidateValue(std::string* s) {\n" + " return ::$proto_ns$::internal::WireFormatLite::" + "VerifyUtf8String(s->data(), static_cast(s->size()), " + "::$proto_ns$::internal::WireFormatLite::PARSE, \"$1$\");\n" + " }\n", + descriptor_->field(1)->full_name()); + } else { + GOOGLE_CHECK_EQ(utf8_check, VERIFY); + format( + " static bool ValidateValue(std::string* s) {\n" + "#ifndef NDEBUG\n" + " ::$proto_ns$::internal::WireFormatLite::VerifyUtf8String(\n" + " s->data(), static_cast(s->size()), " + "::$proto_ns$::internal::" + "WireFormatLite::PARSE, \"$1$\");\n" + "#else\n" + " (void) s;\n" + "#endif\n" + " return true;\n" + " }\n", + descriptor_->field(1)->full_name()); + } + } else { + format(" static bool ValidateValue(void*) { return true; }\n"); + } + if (HasDescriptorMethods(descriptor_->file(), options_)) { + format( + " void MergeFrom(const ::$proto_ns$::Message& other) final;\n" + " ::$proto_ns$::Metadata GetMetadata() const final;\n" + " private:\n" + " static ::$proto_ns$::Metadata GetMetadataStatic() {\n" + " ::$proto_ns$::internal::AssignDescriptors(&::$desc_table$);\n" + " return ::$desc_table$.file_level_metadata[$1$];\n" + " }\n" + "\n" + " public:\n" + "};\n", + index_in_file_messages_); + } else { + format("};\n"); + } return; } - std::map vars; - vars["classname"] = DependentBaseClassTemplateName(descriptor_); - vars["full_name"] = descriptor_->full_name(); - vars["superclass"] = SuperClassName(descriptor_, options_); - - printer->Print(vars, - "template \n" - "class $classname$ : public $superclass$ " - "/* @@protoc_insertion_point(dep_base_class_definition:$full_name$) */ {\n" - " public:\n"); - printer->Indent(); - - printer->Print(vars, - "$classname$() {}\n" - "virtual ~$classname$() {}\n" - "\n"); - - // Generate dependent accessor methods for all fields. - GenerateDependentFieldAccessorDeclarations(printer); - - printer->Outdent(); - printer->Print("};\n"); -} + format( + "class $dllexport_decl $${1$$classname$$}$$ class_final$ :\n" + " public $superclass$ /* @@protoc_insertion_point(" + "class_definition:$full_name$) */ {\n", + descriptor_); + format(" public:\n"); + format.Indent(); -void MessageGenerator:: -GenerateClassDefinition(io::Printer* printer) { - if (IsMapEntryMessage(descriptor_)) return; - if (use_dependent_base_) { - GenerateDependentBaseClassDefinition(printer); - printer->Print("\n"); - } - - std::map vars; - vars["classname"] = classname_; - vars["full_name"] = descriptor_->full_name(); - vars["field_count"] = SimpleItoa(descriptor_->field_count()); - vars["oneof_decl_count"] = SimpleItoa(descriptor_->oneof_decl_count()); - if (options_.dllexport_decl.empty()) { - vars["dllexport"] = ""; - } else { - vars["dllexport"] = options_.dllexport_decl + " "; - } - if (use_dependent_base_) { - vars["superclass"] = - DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">"; - } else { - vars["superclass"] = SuperClassName(descriptor_, options_); - } - printer->Print(vars, - "class $dllexport$$classname$ : public $superclass$ " - "/* @@protoc_insertion_point(class_definition:$full_name$) */ " - "{\n"); - printer->Annotate("classname", descriptor_); - if (use_dependent_base_) { - printer->Print(vars, " friend class $superclass$;\n"); - } - printer->Print(" public:\n"); - printer->Indent(); - - printer->Print( - vars, - "$classname$();\n" + format( + "inline $classname$() : $classname$(nullptr) {}\n" "virtual ~$classname$();\n" + "explicit constexpr " + "$classname$(::$proto_ns$::internal::ConstantInitialized);\n" "\n" "$classname$(const $classname$& from);\n" - "\n" - "inline $classname$& operator=(const $classname$& from) {\n" - " CopyFrom(from);\n" - " return *this;\n" - "}\n"); - - if (options_.table_driven_serialization) { - printer->Print( - "private:\n" - "const void* InternalGetTable() const;\n" - "public:\n" - "\n"); - } - - // Generate move constructor and move assignment operator for types other than - // Any. - if (!IsAnyMessage(descriptor_)) { - printer->Print(vars, - "#if LANG_CXX11\n" "$classname$($classname$&& from) noexcept\n" " : $classname$() {\n" " *this = ::std::move(from);\n" "}\n" "\n" + "inline $classname$& operator=(const $classname$& from) {\n" + " CopyFrom(from);\n" + " return *this;\n" + "}\n" "inline $classname$& operator=($classname$&& from) noexcept {\n" - " if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {\n" + " if (GetArena() == from.GetArena()) {\n" " if (this != &from) InternalSwap(&from);\n" " } else {\n" " CopyFrom(from);\n" " }\n" " return *this;\n" "}\n" - "#endif\n"); + "\n"); + + if (options_.table_driven_serialization) { + format( + "private:\n" + "const void* InternalGetTable() const;\n" + "public:\n" + "\n"); } + std::map vars; SetUnknkownFieldsVariable(descriptor_, options_, &vars); + format.AddMap(vars); if (PublicUnknownFieldsAccessors(descriptor_)) { - printer->Print(vars, + format( "inline const $unknown_fields_type$& unknown_fields() const {\n" " return $unknown_fields$;\n" "}\n" @@ -1142,239 +1148,280 @@ GenerateClassDefinition(io::Printer* printer) { "\n"); } - // N.B.: We exclude GetArena() when arena support is disabled, falling back on - // MessageLite's implementation which returns NULL rather than generating our - // own method which returns NULL, in order to reduce code size. - if (SupportsArenas(descriptor_)) { - // virtual method version of GetArenaNoVirtual(), required for generic dispatch given a - // MessageLite* (e.g., in RepeatedField::AddAllocated()). - printer->Print( - "inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {\n" - " return GetArenaNoVirtual();\n" - "}\n" - "inline void* GetMaybeArenaPointer() const PROTOBUF_FINAL {\n" - " return MaybeArenaPtr();\n" - "}\n"); - } - // Only generate this member if it's not disabled. if (HasDescriptorMethods(descriptor_->file(), options_) && !descriptor_->options().no_standard_descriptor_accessor()) { - printer->Print(vars, - "static const ::google::protobuf::Descriptor* descriptor();\n"); + format( + "static const ::$proto_ns$::Descriptor* descriptor() {\n" + " return GetDescriptor();\n" + "}\n"); + } + + if (HasDescriptorMethods(descriptor_->file(), options_)) { + // These shadow non-static methods of the same names in Message. We + // redefine them here because calls directly on the generated class can be + // statically analyzed -- we know what descriptor types are being requested. + // It also avoids a vtable dispatch. + // + // We would eventually like to eliminate the methods in Message, and having + // this separate also lets us track calls to the base class methods + // separately. + format( + "static const ::$proto_ns$::Descriptor* GetDescriptor() {\n" + " return GetMetadataStatic().descriptor;\n" + "}\n" + "static const ::$proto_ns$::Reflection* GetReflection() {\n" + " return GetMetadataStatic().reflection;\n" + "}\n"); } - printer->Print(vars, - "static const $classname$& default_instance();\n" - "\n"); + format( + "static const $classname$& default_instance() {\n" + " return *internal_default_instance();\n" + "}\n"); // Generate enum values for every field in oneofs. One list is generated for // each oneof with an additional *_NOT_SET value. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "enum $camel_oneof_name$Case {\n", - "camel_oneof_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - printer->Print( - "k$field_name$ = $field_number$,\n", - "field_name", - UnderscoresToCamelCase( - descriptor_->oneof_decl(i)->field(j)->name(), true), - "field_number", - SimpleItoa(descriptor_->oneof_decl(i)->field(j)->number())); - } - printer->Print( - "$cap_oneof_name$_NOT_SET = 0,\n", - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( + for (auto oneof : OneOfRange(descriptor_)) { + format("enum $1$Case {\n", UnderscoresToCamelCase(oneof->name(), true)); + format.Indent(); + for (auto field : FieldRange(oneof)) { + std::string oneof_enum_case_field_name = + UnderscoresToCamelCase(field->name(), true); + format("k$1$ = $2$,\n", oneof_enum_case_field_name, // 1 + field->number()); // 2 + } + format("$1$_NOT_SET = 0,\n", ToUpper(oneof->name())); + format.Outdent(); + format( "};\n" "\n"); } // TODO(gerbens) make this private, while still granting other protos access. - vars["message_index"] = SimpleItoa(index_in_file_messages_); - printer->Print( - vars, + format( "static inline const $classname$* internal_default_instance() {\n" " return reinterpret_cast(\n" " &_$classname$_default_instance_);\n" "}\n" - "static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =\n" - " $message_index$;\n" - "\n"); + "static constexpr int kIndexInFileMessages =\n" + " $1$;\n" + "\n", + index_in_file_messages_); - if (SupportsArenas(descriptor_)) { - printer->Print(vars, - "void UnsafeArenaSwap($classname$* other);\n"); + if (IsAnyMessage(descriptor_, options_)) { + format( + "// implements Any -----------------------------------------------\n" + "\n"); + if (HasDescriptorMethods(descriptor_->file(), options_)) { + format( + "bool PackFrom(const ::$proto_ns$::Message& message) {\n" + " return _any_metadata_.PackFrom(message);\n" + "}\n" + "bool PackFrom(const ::$proto_ns$::Message& message,\n" + " ::PROTOBUF_NAMESPACE_ID::ConstStringParam " + "type_url_prefix) {\n" + " return _any_metadata_.PackFrom(message, type_url_prefix);\n" + "}\n" + "bool UnpackTo(::$proto_ns$::Message* message) const {\n" + " return _any_metadata_.UnpackTo(message);\n" + "}\n" + "static bool GetAnyFieldDescriptors(\n" + " const ::$proto_ns$::Message& message,\n" + " const ::$proto_ns$::FieldDescriptor** type_url_field,\n" + " const ::$proto_ns$::FieldDescriptor** value_field);\n" + "template " + "::value>::type>\n" + "bool PackFrom(const T& message) {\n" + " return _any_metadata_.PackFrom(message);\n" + "}\n" + "template " + "::value>::type>\n" + "bool PackFrom(const T& message,\n" + " ::PROTOBUF_NAMESPACE_ID::ConstStringParam " + "type_url_prefix) {\n" + " return _any_metadata_.PackFrom(message, type_url_prefix);" + "}\n" + "template " + "::value>::type>\n" + "bool UnpackTo(T* message) const {\n" + " return _any_metadata_.UnpackTo(message);\n" + "}\n"); + } else { + format( + "template \n" + "bool PackFrom(const T& message) {\n" + " return _any_metadata_.PackFrom(message);\n" + "}\n" + "template \n" + "bool PackFrom(const T& message,\n" + " ::PROTOBUF_NAMESPACE_ID::ConstStringParam " + "type_url_prefix) {\n" + " return _any_metadata_.PackFrom(message, type_url_prefix);\n" + "}\n" + "template \n" + "bool UnpackTo(T* message) const {\n" + " return _any_metadata_.UnpackTo(message);\n" + "}\n"); + } + format( + "template bool Is() const {\n" + " return _any_metadata_.Is();\n" + "}\n" + "static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam " + "type_url,\n" + " std::string* full_type_name);\n"); } - if (IsAnyMessage(descriptor_)) { - printer->Print(vars, - "// implements Any -----------------------------------------------\n" - "\n" - "void PackFrom(const ::google::protobuf::Message& message);\n" - "void PackFrom(const ::google::protobuf::Message& message,\n" - " const ::std::string& type_url_prefix);\n" - "bool UnpackTo(::google::protobuf::Message* message) const;\n" - "template bool Is() const {\n" - " return _any_metadata_.Is();\n" + format( + "friend void swap($classname$& a, $classname$& b) {\n" + " a.Swap(&b);\n" "}\n" - "\n"); - } - - vars["new_final"] = " PROTOBUF_FINAL"; + "inline void Swap($classname$* other) {\n" + " if (other == this) return;\n" + " if (GetArena() == other->GetArena()) {\n" + " InternalSwap(other);\n" + " } else {\n" + " ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);\n" + " }\n" + "}\n" + "void UnsafeArenaSwap($classname$* other) {\n" + " if (other == this) return;\n" + " $DCHK$(GetArena() == other->GetArena());\n" + " InternalSwap(other);\n" + "}\n"); - printer->Print(vars, - "void Swap($classname$* other);\n" - "friend void swap($classname$& a, $classname$& b) {\n" - " a.Swap(&b);\n" - "}\n" - "\n" - "// implements Message ----------------------------------------------\n" - "\n" - "inline $classname$* New() const$new_final$ { return New(NULL); }\n" - "\n" - "$classname$* New(::google::protobuf::Arena* arena) const$new_final$;\n"); + format( + "\n" + "// implements Message ----------------------------------------------\n" + "\n" + "inline $classname$* New() const final {\n" + " return CreateMaybeMessage<$classname$>(nullptr);\n" + "}\n" + "\n" + "$classname$* New(::$proto_ns$::Arena* arena) const final {\n" + " return CreateMaybeMessage<$classname$>(arena);\n" + "}\n"); // For instances that derive from Message (rather than MessageLite), some // methods are virtual and should be marked as final. - string use_final = HasDescriptorMethods(descriptor_->file(), options_) ? - " PROTOBUF_FINAL" : ""; + format.Set("full_final", HasDescriptorMethods(descriptor_->file(), options_) + ? "final" + : ""); if (HasGeneratedMethods(descriptor_->file(), options_)) { if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print(vars, - "void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;\n" - "void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;\n"); + format( + "void CopyFrom(const ::$proto_ns$::Message& from) final;\n" + "void MergeFrom(const ::$proto_ns$::Message& from) final;\n"); } else { - printer->Print(vars, - "void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from)\n" - " PROTOBUF_FINAL;\n"); + format( + "void CheckTypeAndMergeFrom(const ::$proto_ns$::MessageLite& from)\n" + " final;\n"); } - vars["clear_final"] = " PROTOBUF_FINAL"; - vars["is_initialized_final"] = " PROTOBUF_FINAL"; - vars["merge_partial_final"] = " PROTOBUF_FINAL"; + format.Set("clear_final", + ShouldMarkClearAsFinal(descriptor_, options_) ? "final" : ""); - printer->Print( - vars, + format( "void CopyFrom(const $classname$& from);\n" "void MergeFrom(const $classname$& from);\n" - "void Clear()$clear_final$;\n" - "bool IsInitialized() const$is_initialized_final$;\n" + "PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear()$ clear_final$;\n" + "bool IsInitialized() const final;\n" "\n" - "size_t ByteSizeLong() const PROTOBUF_FINAL;\n" - "bool MergePartialFromCodedStream(\n" - " ::google::protobuf::io::CodedInputStream* input)$merge_partial_final$;\n"); - if (!options_.table_driven_serialization || - descriptor_->options().message_set_wire_format()) { - printer->Print( - "void SerializeWithCachedSizes(\n" - " ::google::protobuf::io::CodedOutputStream* output) const " - "PROTOBUF_FINAL;\n"); - } + "size_t ByteSizeLong() const final;\n" + "const char* _InternalParse(const char* ptr, " + "::$proto_ns$::internal::ParseContext* ctx) final;\n" + "$uint8$* _InternalSerialize(\n" + " $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) " + "const final;\n"); + // DiscardUnknownFields() is implemented in message.cc using reflections. We // need to implement this function in generated code for messages. if (!UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print( - "void DiscardUnknownFields()$final$;\n", - "final", use_final); - } - if (HasFastArraySerialization(descriptor_->file(), options_)) { - printer->Print( - "::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(\n" - " bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;\n"); + format("void DiscardUnknownFields()$ full_final$;\n"); } } - printer->Print( - "int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }\n" - "private:\n" - "void SharedCtor();\n" - "void SharedDtor();\n" - "void SetCachedSize(int size) const$final$;\n" - "void InternalSwap($classname$* other);\n", - "classname", classname_, - "final", use_final); - if (SupportsArenas(descriptor_)) { - printer->Print( + format( + "int GetCachedSize() const final { return _cached_size_.Get(); }" + "\n\nprivate:\n" + "inline void SharedCtor();\n" + "inline void SharedDtor();\n" + "void SetCachedSize(int size) const$ full_final$;\n" + "void InternalSwap($classname$* other);\n"); + + format( + // Friend AnyMetadata so that it can call this FullMessageName() method. + "friend class ::$proto_ns$::internal::AnyMetadata;\n" + "static $1$ FullMessageName() {\n" + " return \"$full_name$\";\n" + "}\n", + options_.opensource_runtime ? "::PROTOBUF_NAMESPACE_ID::StringPiece" + : "::StringPiece"); + + format( // TODO(gerbens) Make this private! Currently people are deriving from // protos to give access to this constructor, breaking the invariants // we rely on. "protected:\n" - "explicit $classname$(::google::protobuf::Arena* arena);\n" + "explicit $classname$(::$proto_ns$::Arena* arena);\n" "private:\n" "static void ArenaDtor(void* object);\n" - "inline void RegisterArenaDtor(::google::protobuf::Arena* arena);\n", - "classname", classname_); - } - - if (SupportsArenas(descriptor_)) { - printer->Print( - "private:\n" - "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n" - " return _internal_metadata_.arena();\n" - "}\n" - "inline void* MaybeArenaPtr() const {\n" - " return _internal_metadata_.raw_arena_ptr();\n" - "}\n"); - } else { - printer->Print( - "private:\n" - "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n" - " return NULL;\n" - "}\n" - "inline void* MaybeArenaPtr() const {\n" - " return NULL;\n" - "}\n"); - } + "inline void RegisterArenaDtor(::$proto_ns$::Arena* arena);\n"); - printer->Print( + format( "public:\n" "\n"); if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print( - "::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;\n" - "\n"); + format( + "::$proto_ns$::Metadata GetMetadata() const final;\n" + "private:\n" + "static ::$proto_ns$::Metadata GetMetadataStatic() {\n" + " return ::$desc_table$_metadata_getter(kIndexInFileMessages);\n" + "}\n" + "\n" + "public:\n" + "\n"); } else { - printer->Print( - "::std::string GetTypeName() const PROTOBUF_FINAL;\n" - "\n"); + format( + "std::string GetTypeName() const final;\n" + "\n"); } - printer->Print( - "// nested types ----------------------------------------------------\n" - "\n"); + format( + "// nested types ----------------------------------------------------\n" + "\n"); // Import all nested message classes into this class's scope with typedefs. for (int i = 0; i < descriptor_->nested_type_count(); i++) { const Descriptor* nested_type = descriptor_->nested_type(i); if (!IsMapEntryMessage(nested_type)) { - printer->Print("typedef $nested_full_name$ $nested_name$;\n", - "nested_name", nested_type->name(), - "nested_full_name", ClassName(nested_type, false)); + format.Set("nested_full_name", ClassName(nested_type, false)); + format.Set("nested_name", ResolveKeyword(nested_type->name())); + format("typedef ${1$$nested_full_name$$}$ ${1$$nested_name$$}$;\n", + nested_type); } } if (descriptor_->nested_type_count() > 0) { - printer->Print("\n"); + format("\n"); } // Import all nested enums and their values into this class's scope with // typedefs and constants. for (int i = 0; i < descriptor_->enum_type_count(); i++) { enum_generators_[i]->GenerateSymbolImports(printer); - printer->Print("\n"); + format("\n"); } - printer->Print( - "// accessors -------------------------------------------------------\n" - "\n"); + format( + "// accessors -------------------------------------------------------\n" + "\n"); // Generate accessor methods for all fields. GenerateFieldAccessorDeclarations(printer); @@ -1385,50 +1432,36 @@ GenerateClassDefinition(io::Printer* printer) { } - printer->Print( - "// @@protoc_insertion_point(class_scope:$full_name$)\n", - "full_name", descriptor_->full_name()); + format("// @@protoc_insertion_point(class_scope:$full_name$)\n"); // Generate private members. - printer->Outdent(); - printer->Print(" private:\n"); - printer->Indent(); - - - for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->is_repeated() && - !descriptor_->field(i)->options().weak()) { - // set_has_***() generated in all proto1/2 code and in oneofs (only) for - // messages without true field presence. - if (HasFieldPresence(descriptor_->file()) || - descriptor_->field(i)->containing_oneof()) { - printer->Print("void set_has_$name$();\n", "name", - FieldName(descriptor_->field(i))); - } - // clear_has_***() generated only for non-oneof fields - // in proto1/2. - if (!descriptor_->field(i)->containing_oneof() && - HasFieldPresence(descriptor_->file())) { - printer->Print("void clear_has_$name$();\n", "name", - FieldName(descriptor_->field(i))); - } + format.Outdent(); + format(" private:\n"); + format.Indent(); + // TODO(seongkim): Remove hack to track field access and remove this class. + format("class _Internal;\n"); + + for (auto field : FieldRange(descriptor_)) { + // set_has_***() generated in all oneofs. + if (!field->is_repeated() && !field->options().weak() && + field->real_containing_oneof()) { + format("void set_has_$1$();\n", FieldName(field)); } } - printer->Print("\n"); + format("\n"); // Generate oneof function declarations - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "inline bool has_$oneof_name$() const;\n" - "void clear_$oneof_name$();\n" - "inline void clear_has_$oneof_name$();\n\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); + for (auto oneof : OneOfRange(descriptor_)) { + format( + "inline bool has_$1$() const;\n" + "inline void clear_has_$1$();\n\n", + oneof->name()); } if (HasGeneratedMethods(descriptor_->file(), options_) && !descriptor_->options().message_set_wire_format() && num_required_fields_ > 1) { - printer->Print( + format( "// helper for ByteSizeLong()\n" "size_t RequiredFieldsByteSizeFallback() const;\n\n"); } @@ -1437,13 +1470,14 @@ GenerateClassDefinition(io::Printer* printer) { // output will be determined later. bool need_to_emit_cached_size = true; - // TODO(kenton): Make _cached_size_ an atomic when C++ supports it. - const string cached_size_decl = "mutable int _cached_size_;\n"; + const std::string cached_size_decl = + "mutable ::$proto_ns$::internal::CachedSize _cached_size_;\n"; const size_t sizeof_has_bits = HasBitsSize(); - const string has_bits_decl = sizeof_has_bits == 0 ? "" : - "::google::protobuf::internal::HasBits<" + SimpleItoa(sizeof_has_bits / 4) + - "> _has_bits_;\n"; + const std::string has_bits_decl = + sizeof_has_bits == 0 ? "" + : StrCat("::$proto_ns$::internal::HasBits<", + sizeof_has_bits, "> _has_bits_;\n"); // To minimize padding, data members are divided into three sections: // (1) members assumed to align to 8 bytes @@ -1454,341 +1488,219 @@ GenerateClassDefinition(io::Printer* printer) { // Members assumed to align to 8 bytes: if (descriptor_->extension_range_count() > 0) { - printer->Print( - "::google::protobuf::internal::ExtensionSet _extensions_;\n" - "\n"); - } - - if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print( - "::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;\n"); - } else { - printer->Print( - "::google::protobuf::internal::InternalMetadataWithArenaLite " - "_internal_metadata_;\n"); + format( + "::$proto_ns$::internal::ExtensionSet _extensions_;\n" + "\n"); } - if (SupportsArenas(descriptor_)) { - printer->Print( - "template friend class ::google::protobuf::Arena::InternalHelper;\n" + format( + "template friend class " + "::$proto_ns$::Arena::InternalHelper;\n" "typedef void InternalArenaConstructable_;\n" "typedef void DestructorSkippable_;\n"); - } - if (HasFieldPresence(descriptor_->file())) { + if (!has_bit_indices_.empty()) { // _has_bits_ is frequently accessed, so to reduce code size and improve - // speed, it should be close to the start of the object. But, try not to - // waste space:_has_bits_ by itself always makes sense if its size is a - // multiple of 8, but, otherwise, maybe _has_bits_ and cached_size_ together - // will work well. - printer->Print(has_bits_decl.c_str()); - if ((sizeof_has_bits % 8) != 0) { - printer->Print(cached_size_decl.c_str()); - need_to_emit_cached_size = false; - } + // speed, it should be close to the start of the object. Placing + // _cached_size_ together with _has_bits_ improves cache locality despite + // potential alignment padding. + format(has_bits_decl.c_str()); + format(cached_size_decl.c_str()); + need_to_emit_cached_size = false; } // Field members: // Emit some private and static members - for (int i = 0; i < optimized_order_.size(); ++i) { - const FieldDescriptor* field = optimized_order_[i]; + for (auto field : optimized_order_) { const FieldGenerator& generator = field_generators_.get(field); generator.GenerateStaticMembers(printer); generator.GeneratePrivateMembers(printer); } // For each oneof generate a union - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "union $camel_oneof_name$Union {\n" + for (auto oneof : OneOfRange(descriptor_)) { + std::string camel_oneof_name = UnderscoresToCamelCase(oneof->name(), true); + format("union $1$Union {\n", camel_oneof_name); + format.Indent(); + format( // explicit empty constructor is needed when union contains // ArenaStringPtr members for string fields. - " $camel_oneof_name$Union() {}\n", - "camel_oneof_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - field_generators_.get(descriptor_->oneof_decl(i)-> - field(j)).GeneratePrivateMembers(printer); + "constexpr $1$Union() : _constinit_{} {}\n" + " ::$proto_ns$::internal::ConstantInitialized _constinit_;\n", + camel_oneof_name); + for (auto field : FieldRange(oneof)) { + if (!IsFieldStripped(field, options_)) { + field_generators_.get(field).GeneratePrivateMembers(printer); + } } - printer->Outdent(); - printer->Print( - "} $oneof_name$_;\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - field_generators_.get(descriptor_->oneof_decl(i)-> - field(j)).GenerateStaticMembers(printer); + format.Outdent(); + format("} $1$_;\n", oneof->name()); + for (auto field : FieldRange(oneof)) { + if (!IsFieldStripped(field, options_)) { + field_generators_.get(field).GenerateStaticMembers(printer); + } } } // Members assumed to align to 4 bytes: if (need_to_emit_cached_size) { - printer->Print(cached_size_decl.c_str()); + format(cached_size_decl.c_str()); need_to_emit_cached_size = false; } // Generate _oneof_case_. - if (descriptor_->oneof_decl_count() > 0) { - printer->Print(vars, - "::google::protobuf::uint32 _oneof_case_[$oneof_decl_count$];\n" - "\n"); + if (descriptor_->real_oneof_decl_count() > 0) { + format( + "$uint32$ _oneof_case_[$1$];\n" + "\n", + descriptor_->real_oneof_decl_count()); } if (num_weak_fields_) { - printer->Print( - "::google::protobuf::internal::WeakFieldMap _weak_field_map_;\n"); + format("::$proto_ns$::internal::WeakFieldMap _weak_field_map_;\n"); } // Generate _any_metadata_ for the Any type. - if (IsAnyMessage(descriptor_)) { - printer->Print(vars, - "::google::protobuf::internal::AnyMetadata _any_metadata_;\n"); + if (IsAnyMessage(descriptor_, options_)) { + format("::$proto_ns$::internal::AnyMetadata _any_metadata_;\n"); } // The TableStruct struct needs access to the private parts, in order to // construct the offsets of all members. - // - // Some InitDefault and Shutdown are defined as static member functions of - // TableStruct such that they are also allowed to access private members. - printer->Print( - "friend struct $file_namespace$::TableStruct;\n", - // Vars. - "file_namespace", - FileLevelNamespace(descriptor_->file()->name())); - - printer->Outdent(); - printer->Print("};"); - GOOGLE_DCHECK(!need_to_emit_cached_size); -} + format("friend struct ::$tablename$;\n"); -void MessageGenerator:: -GenerateDependentInlineMethods(io::Printer* printer) { - if (IsMapEntryMessage(descriptor_)) return; - for (int i = 0; i < descriptor_->field_count(); i++) { - if (descriptor_->field(i)->options().weak()) { - field_generators_.get(descriptor_->field(i)) - .GenerateDependentInlineAccessorDefinitions(printer); - } - } - GenerateDependentFieldAccessorDefinitions(printer); -} + format.Outdent(); + format("};"); + GOOGLE_DCHECK(!need_to_emit_cached_size); +} // NOLINT(readability/fn_size) -void MessageGenerator:: -GenerateInlineMethods(io::Printer* printer, bool is_inline) { +void MessageGenerator::GenerateInlineMethods(io::Printer* printer) { if (IsMapEntryMessage(descriptor_)) return; - GenerateFieldAccessorDefinitions(printer, is_inline); + GenerateFieldAccessorDefinitions(printer); // Generate oneof_case() functions. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - std::map vars; - vars["class_name"] = classname_; - vars["camel_oneof_name"] = UnderscoresToCamelCase( - descriptor_->oneof_decl(i)->name(), true); - vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); - vars["inline"] = is_inline ? "inline " : ""; - printer->Print( - vars, - "$inline$" - "$class_name$::$camel_oneof_name$Case $class_name$::" - "$oneof_name$_case() const {\n" - " return $class_name$::$camel_oneof_name$Case(" + for (auto oneof : OneOfRange(descriptor_)) { + Formatter format(printer, variables_); + format.Set("camel_oneof_name", UnderscoresToCamelCase(oneof->name(), true)); + format.Set("oneof_name", oneof->name()); + format.Set("oneof_index", oneof->index()); + format( + "inline $classname$::$camel_oneof_name$Case $classname$::" + "${1$$oneof_name$_case$}$() const {\n" + " return $classname$::$camel_oneof_name$Case(" "_oneof_case_[$oneof_index$]);\n" - "}\n"); - } -} - -void MessageGenerator:: -GenerateExtraDefaultFields(io::Printer* printer) { - // Generate oneof default instance and weak field instances for reflection - // usage. - if (descriptor_->oneof_decl_count() > 0 || num_weak_fields_ > 0) { - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || - (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && - EffectiveStringCType(field) != FieldOptions::STRING)) { - printer->Print("const "); - } - field_generators_.get(field).GeneratePrivateMembers(printer); - } - } - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->options().weak()) { - printer->Print( - " const ::google::protobuf::Message* $name$_;\n", "name", FieldName(field)); - } - } + "}\n", + oneof); } } bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset, size_t aux_offset) { + Formatter format(printer, variables_); + if (!table_driven_) { - printer->Print("{ NULL, NULL, 0, -1, -1, -1, -1, NULL, false },\n"); + format("{ nullptr, nullptr, 0, -1, -1, -1, -1, nullptr, false },\n"); return false; } - std::map vars; - - vars["classname"] = classname_; - vars["offset"] = SimpleItoa(offset); - vars["aux_offset"] = SimpleItoa(aux_offset); - int max_field_number = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); + for (auto field : FieldRange(descriptor_)) { if (max_field_number < field->number()) { max_field_number = field->number(); } } - vars["max_field_number"] = SimpleItoa(max_field_number); - - printer->Print("{\n"); - printer->Indent(); + format("{\n"); + format.Indent(); - printer->Print(vars, - "TableStruct::entries + $offset$,\n" - "TableStruct::aux + $aux_offset$,\n" - "$max_field_number$,\n"); + format( + "$tablename$::entries + $1$,\n" + "$tablename$::aux + $2$,\n" + "$3$,\n", + offset, aux_offset, max_field_number); - if (!HasFieldPresence(descriptor_->file())) { - // If we don't have field presence, then _has_bits_ does not exist. - printer->Print(vars, "-1,\n"); + if (has_bit_indices_.empty()) { + // If no fields have hasbits, then _has_bits_ does not exist. + format("-1,\n"); } else { - printer->Print(vars, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n" - " $classname$, _has_bits_),\n"); + format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n"); } - if (descriptor_->oneof_decl_count() > 0) { - printer->Print(vars, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n" - " $classname$, _oneof_case_),\n"); + if (descriptor_->real_oneof_decl_count() > 0) { + format("PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_),\n"); } else { - printer->Print("-1, // no _oneof_case_\n"); + format("-1, // no _oneof_case_\n"); } if (descriptor_->extension_range_count() > 0) { - printer->Print(vars, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "_extensions_),\n"); + format("PROTOBUF_FIELD_OFFSET($classtype$, _extensions_),\n"); } else { - printer->Print("-1, // no _extensions_\n"); + format("-1, // no _extensions_\n"); } // TODO(ckennelly): Consolidate this with the calculation for - // AuxillaryParseTableField. - std::vector package_parts; - - const Descriptor* outer = descriptor_; - while (outer->containing_type() != NULL) { - outer = outer->containing_type(); - } - - package_parts = Split( - outer->full_name(), ".", true); - // outer->full_name() contains the class itself. Remove it as it is - // used in the name of the default instance variable. - GOOGLE_DCHECK_NE(package_parts.size(), 0); - package_parts.back().clear(); - - vars["ns"] = Join(package_parts, "::"); - - printer->Print(vars, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n" - " $classname$, _internal_metadata_),\n" - "&::$ns$_$classname$_default_instance_,\n"); + // AuxiliaryParseTableField. + format( + "PROTOBUF_FIELD_OFFSET($classtype$, _internal_metadata_),\n" + "&$package_ns$::_$classname$_default_instance_,\n"); if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(vars, "true,\n"); + format("true,\n"); } else { - printer->Print(vars, "false,\n"); + format("false,\n"); } - printer->Outdent(); - printer->Print("},\n"); + format.Outdent(); + format("},\n"); return true; } void MessageGenerator::GenerateSchema(io::Printer* printer, int offset, int has_offset) { - if (IsMapEntryMessage(descriptor_)) return; + Formatter format(printer, variables_); + has_offset = !has_bit_indices_.empty() || IsMapEntryMessage(descriptor_) + ? offset + has_offset + : -1; - std::map vars; - - vars["classname"] = classname_; - vars["offset"] = SimpleItoa(offset); - vars["has_bits_offsets"] = HasFieldPresence(descriptor_->file()) - ? SimpleItoa(offset + has_offset) - : "-1"; - - printer->Print(vars, - "{ $offset$, $has_bits_offsets$, sizeof($classname$)},\n"); + format("{ $1$, $2$, sizeof($classtype$)},\n", offset, has_offset); } namespace { -// TODO(gerbens) remove this after the next sync with GitHub code base. -// Then the opensource testing has gained the functionality to compile -// the CalcFieldNum given the symbols defined in generated-message-util. -#ifdef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP -// We need a clean version of CalcFieldNum that doesn't use new functionality -// in the runtime, because this functionality is not yet in the opensource -// runtime - -uint32 CalculateType(uint32 type, uint32 type_class) { - return (type - 1) + type_class * 20; -} - -uint32 CalcFieldNum(const FieldDescriptor* field, const Options& options) { - bool is_a_map = IsMapEntryMessage(field->containing_type()); - int type = field->type(); - if (field->containing_oneof()) { - return CalculateType(type, 4); - } - if (field->is_packed()) { - return CalculateType(type, 3); - } else if (field->is_repeated()) { - return CalculateType(type, 2); - } else if (!HasFieldPresence(field->file()) && - field->containing_oneof() == NULL && !is_a_map) { - return CalculateType(type, 1); - } else { - return CalculateType(type, 0); - } -} - -#else // We need to calculate for each field what function the table driven code // should use to serialize it. This returns the index in a lookup table. -uint32 CalcFieldNum(const FieldDescriptor* field, const Options& options) { +uint32 CalcFieldNum(const FieldGenerator& generator, + const FieldDescriptor* field, const Options& options) { bool is_a_map = IsMapEntryMessage(field->containing_type()); int type = field->type(); - if (field->containing_oneof()) { + if (type == FieldDescriptor::TYPE_STRING || + type == FieldDescriptor::TYPE_BYTES) { + // string field + if (IsCord(field, options)) { + type = internal::FieldMetadata::kCordType; + } else if (IsStringPiece(field, options)) { + type = internal::FieldMetadata::kStringPieceType; + } + } + + if (field->real_containing_oneof()) { return internal::FieldMetadata::CalculateType( type, internal::FieldMetadata::kOneOf); - } - if (field->is_packed()) { + } else if (field->is_packed()) { return internal::FieldMetadata::CalculateType( type, internal::FieldMetadata::kPacked); } else if (field->is_repeated()) { return internal::FieldMetadata::CalculateType( type, internal::FieldMetadata::kRepeated); - } else if (!HasFieldPresence(field->file()) && - field->containing_oneof() == NULL && !is_a_map) { + } else if (HasHasbit(field) || field->real_containing_oneof() || is_a_map) { return internal::FieldMetadata::CalculateType( - type, internal::FieldMetadata::kNoPresence); + type, internal::FieldMetadata::kPresence); } else { return internal::FieldMetadata::CalculateType( - type, internal::FieldMetadata::kPresence); + type, internal::FieldMetadata::kNoPresence); } } -#endif int FindMessageIndexInFile(const Descriptor* descriptor) { std::vector flatten = @@ -1800,6 +1712,7 @@ int FindMessageIndexInFile(const Descriptor* descriptor) { } // namespace int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) { + Formatter format(printer, variables_); if (!options_.table_driven_serialization) { return 0; } @@ -1808,48 +1721,43 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) { if (IsMapEntryMessage(descriptor_)) { for (int i = 0; i < 2; i++) { const FieldDescriptor* field = sorted[i]; + const FieldGenerator& generator = field_generators_.get(field); + uint32 tag = internal::WireFormatLite::MakeTag( field->number(), WireFormat::WireTypeForFieldType(field->type())); - std::map vars; - vars["classname"] = classname_; - vars["parent_classname"] = - ClassName(descriptor_->containing_type(), false); + std::map vars; + vars["classtype"] = QualifiedClassName(descriptor_, options_); vars["field_name"] = FieldName(field); - vars["tag"] = SimpleItoa(tag); - vars["hasbit"] = SimpleItoa(i); - vars["type"] = SimpleItoa(CalcFieldNum(field, options_)); - vars["ptr"] = "NULL"; + vars["tag"] = StrCat(tag); + vars["hasbit"] = StrCat(i); + vars["type"] = StrCat(CalcFieldNum(generator, field, options_)); + vars["ptr"] = "nullptr"; if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { GOOGLE_CHECK(!IsMapEntryMessage(field->message_type())); - { - vars["ptr"] = - QualifiedFileLevelSymbol( - field->message_type()->file()->package(), - FileLevelNamespace(field->message_type()->file()->name())) + - "::TableStruct::serialization_table + " + - SimpleItoa(FindMessageIndexInFile(field->message_type())); - } + vars["ptr"] = + "::" + UniqueName("TableStruct", field->message_type(), options_) + + "::serialization_table + " + + StrCat(FindMessageIndexInFile(field->message_type())); } - vars["extra"] = HasDescriptorMethods(descriptor_->file(), options_) - ? "::SuperType" - : ""; - printer->Print(vars, - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" - "::google::protobuf::internal::MapEntryHelper<$parent_classname$::$" - "classname$$extra$>, $field_name$_), $tag$," - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" - "::google::protobuf::internal::MapEntryHelper<$parent_classname$::$" - "classname$$extra$>, _has_bits_) * 8 + $hasbit$, $type$, " - "$ptr$},\n"); + Formatter::SaveState saver(&format); + format.AddMap(vars); + format( + "{PROTOBUF_FIELD_OFFSET(" + "::$proto_ns$::internal::MapEntryHelper<$classtype$::" + "SuperType>, $field_name$_), $tag$," + "PROTOBUF_FIELD_OFFSET(" + "::$proto_ns$::internal::MapEntryHelper<$classtype$::" + "SuperType>, _has_bits_) * 8 + $hasbit$, $type$, " + "$ptr$},\n"); } return 2; } - printer->Print( - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "_cached_size_), 0, 0, 0, NULL},\n", - "classname", classname_); + format( + "{PROTOBUF_FIELD_OFFSET($classtype$, _cached_size_)," + " 0, 0, 0, nullptr},\n"); std::vector sorted_extensions; + sorted_extensions.reserve(descriptor_->extension_range_count()); for (int i = 0; i < descriptor_->extension_range_count(); ++i) { sorted_extensions.push_back(descriptor_->extension_range(i)); } @@ -1862,14 +1770,12 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) { extension_idx++) { const Descriptor::ExtensionRange* range = sorted_extensions[extension_idx]; - printer->Print( - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "_extensions_), $start$, $end$, " - "::google::protobuf::internal::FieldMetadata::kSpecial, " + format( + "{PROTOBUF_FIELD_OFFSET($classtype$, _extensions_), " + "$1$, $2$, ::$proto_ns$::internal::FieldMetadata::kSpecial, " "reinterpret_cast(::google::protobuf::internal::ExtensionSerializer)},\n", - "classname", classname_, "start", SimpleItoa(range->start), "end", - SimpleItoa(range->end)); + "void*>(::$proto_ns$::internal::ExtensionSerializer)},\n", + range->start, range->end); } if (i == sorted.size()) break; const FieldDescriptor* field = sorted[i]; @@ -1881,309 +1787,284 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) { field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED); } - string classfieldname = FieldName(field); - if (field->containing_oneof()) { + std::string classfieldname = FieldName(field); + if (field->real_containing_oneof()) { classfieldname = field->containing_oneof()->name(); } - std::map vars; - vars["classname"] = classname_; - vars["field_name"] = classfieldname; - vars["tag"] = SimpleItoa(tag); - vars["ptr"] = "NULL"; + format.Set("field_name", classfieldname); + std::string ptr = "nullptr"; if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (IsMapEntryMessage(field->message_type())) { - vars["idx"] = SimpleItoa(FindMessageIndexInFile(field->message_type())); - vars["fieldclassname"] = ClassName(field->message_type(), false); - printer->Print(vars, - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($" - "classname$, $field_name$_), $tag$, $idx$, " - "::google::protobuf::internal::FieldMetadata::kSpecial, " - "reinterpret_cast(static_cast< " - "::google::protobuf::internal::SpecialSerializer>(" - "::google::protobuf::internal::MapFieldSerializer< " - "::google::protobuf::internal::MapEntryToMapField<$classname$::$" - "fieldclassname$>::MapFieldType, " - "TableStruct::serialization_table>))},\n"); + format( + "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), $1$, $2$, " + "::$proto_ns$::internal::FieldMetadata::kSpecial, " + "reinterpret_cast(static_cast< " + "::$proto_ns$::internal::SpecialSerializer>(" + "::$proto_ns$::internal::MapFieldSerializer< " + "::$proto_ns$::internal::MapEntryToMapField<" + "$3$>::MapFieldType, " + "$tablename$::serialization_table>))},\n", + tag, FindMessageIndexInFile(field->message_type()), + QualifiedClassName(field->message_type(), options_)); continue; - } else { - vars["ptr"] = - QualifiedFileLevelSymbol( - field->message_type()->file()->package(), - FileLevelNamespace(field->message_type()->file()->name())) + - "::TableStruct::serialization_table + " + - SimpleItoa(FindMessageIndexInFile(field->message_type())); + } else if (!field->message_type()->options().message_set_wire_format()) { + // message_set doesn't have the usual table and we need to + // dispatch to generated serializer, hence ptr stays zero. + ptr = + "::" + UniqueName("TableStruct", field->message_type(), options_) + + "::serialization_table + " + + StrCat(FindMessageIndexInFile(field->message_type())); } } - vars["type"] = SimpleItoa(CalcFieldNum(field, options_)); + const FieldGenerator& generator = field_generators_.get(field); + int type = CalcFieldNum(generator, field, options_); + + if (IsLazy(field, options_)) { + type = internal::FieldMetadata::kSpecial; + ptr = "reinterpret_cast(::" + variables_["proto_ns"] + + "::internal::LazyFieldSerializer"; + if (field->real_containing_oneof()) { + ptr += "OneOf"; + } else if (!HasHasbit(field)) { + ptr += "NoPresence"; + } + ptr += ")"; + } if (field->options().weak()) { // TODO(gerbens) merge weak fields into ranges - printer->Print(vars, - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($" - "classname$, _weak_field_map_), $tag$, $tag$, " - "::google::protobuf::internal::FieldMetadata::kSpecial, " - "reinterpret_cast(::google::protobuf::internal::WeakFieldSerializer)},\n"); - } else if (field->containing_oneof()) { - vars["oneofoffset"] = - SimpleItoa(sizeof(uint32) * field->containing_oneof()->index()); - printer->Print(vars, - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($" - "classname$, $field_name$_), $tag$, " - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($" - "classname$, _oneof_case_) + $oneofoffset$, " - "$type$, $ptr$},\n"); - } else if (HasFieldPresence(descriptor_->file()) && - has_bit_indices_[field->index()] != -1) { - vars["hasbitsoffset"] = SimpleItoa(has_bit_indices_[field->index()]); - printer->Print(vars, - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($" - "classname$, $field_name$_), $tag$, " - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($" - "classname$, _has_bits_) * 8 + $hasbitsoffset$, $type$, " - "$ptr$},\n"); + format( + "{PROTOBUF_FIELD_OFFSET(" + "$classtype$, _weak_field_map_), $1$, $1$, " + "::$proto_ns$::internal::FieldMetadata::kSpecial, " + "reinterpret_cast(::$proto_ns$::internal::WeakFieldSerializer)},\n", + tag); + } else if (field->real_containing_oneof()) { + format.Set("oneofoffset", + sizeof(uint32) * field->containing_oneof()->index()); + format( + "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), $1$," + " PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_) + " + "$oneofoffset$, $2$, $3$},\n", + tag, type, ptr); + } else if (HasHasbit(field)) { + format.Set("hasbitsoffset", has_bit_indices_[field->index()]); + format( + "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), " + "$1$, PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_) * 8 + " + "$hasbitsoffset$, $2$, $3$},\n", + tag, type, ptr); } else { - printer->Print(vars, - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($" - "classname$, $field_name$_), $tag$, ~0u, $type$, " - "$ptr$},\n"); + format( + "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), " + "$1$, ~0u, $2$, $3$},\n", + tag, type, ptr); } } int num_field_metadata = 1 + sorted.size() + sorted_extensions.size(); num_field_metadata++; - string serializer = UseUnknownFieldSet(descriptor_->file(), options_) - ? "::google::protobuf::internal::UnknownFieldSetSerializer" - : "::google::protobuf::internal::UnknownFieldSerializerLite"; - printer->Print( - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "_internal_metadata_), 0, ~0u, " - "::google::protobuf::internal::FieldMetadata::kSpecial, reinterpret_cast($serializer$)},\n", - "classname", classname_, "serializer", serializer); + std::string serializer = UseUnknownFieldSet(descriptor_->file(), options_) + ? "UnknownFieldSetSerializer" + : "UnknownFieldSerializerLite"; + format( + "{PROTOBUF_FIELD_OFFSET($classtype$, _internal_metadata_), 0, ~0u, " + "::$proto_ns$::internal::FieldMetadata::kSpecial, reinterpret_cast(::$proto_ns$::internal::$1$)},\n", + serializer); return num_field_metadata; } -void MessageGenerator:: -GenerateDefaultInstanceAllocator(io::Printer* printer) { - // Construct the default instances of all fields, as they will be used - // when creating the default instance of the entire message. - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateDefaultInstanceAllocator(printer); - } - - // Construct the default instance. We can't call InitAsDefaultInstance() yet - // because we need to make sure all default instances that this one might - // depend on are constructed first. - printer->Print("_$classname$_default_instance_._instance.DefaultConstruct();\n" - "::google::protobuf::internal::OnShutdownDestroyMessage(\n" - " &_$classname$_default_instance_);", - "classname", classname_); -} - -void MessageGenerator:: -GenerateDefaultInstanceInitializer(io::Printer* printer) { +void MessageGenerator::GenerateClassMethods(io::Printer* printer) { + Formatter format(printer, variables_); if (IsMapEntryMessage(descriptor_)) { - printer->Print( - "_$classname$_default_instance_._instance.get_mutable()->set_default_instance(_$" - "classname$_default_instance_._instance.get_mutable());\n" - "_$classname$_default_instance_._instance.get_mutable()->InitAsDefaultInstance();" - "\n", - "classname", classname_); + format( + "$classname$::$classname$() {}\n" + "$classname$::$classname$(::$proto_ns$::Arena* arena)\n" + " : SuperType(arena) {}\n" + "void $classname$::MergeFrom(const $classname$& other) {\n" + " MergeFromInternal(other);\n" + "}\n"); + if (HasDescriptorMethods(descriptor_->file(), options_)) { + format( + "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n" + " return GetMetadataStatic();\n" + "}\n"); + format( + "void $classname$::MergeFrom(\n" + " const ::$proto_ns$::Message& other) {\n" + " ::$proto_ns$::Message::MergeFrom(other);\n" + "}\n" + "\n"); + } return; } - // The default instance needs all of its embedded message pointers - // cross-linked to other default instances. We can't do this initialization - // in the constructor because some other default instances may not have been - // constructed yet at that time. - // TODO(kenton): Maybe all message fields (even for non-default messages) - // should be initialized to point at default instances rather than NULL? - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - - if (!field->is_repeated() && - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && - (field->containing_oneof() == NULL || - HasDescriptorMethods(descriptor_->file(), options_))) { - string name; - if (field->containing_oneof() || field->options().weak()) { - name = "_" + classname_ + "_default_instance_."; - } else { - name = - "_" + classname_ + "_default_instance_._instance.get_mutable()->"; - } - name += FieldName(field); - printer->Print( - "$name$_ = const_cast< $type$*>(\n" - " $type$::internal_default_instance());\n", - // Vars. - "name", name, "type", FieldMessageTypeName(field)); - } else if (field->containing_oneof() && - HasDescriptorMethods(descriptor_->file(), options_)) { - field_generators_.get(descriptor_->field(i)) - .GenerateConstructorCode(printer); + if (IsAnyMessage(descriptor_, options_)) { + if (HasDescriptorMethods(descriptor_->file(), options_)) { + format( + "bool $classname$::GetAnyFieldDescriptors(\n" + " const ::$proto_ns$::Message& message,\n" + " const ::$proto_ns$::FieldDescriptor** type_url_field,\n" + " const ::$proto_ns$::FieldDescriptor** value_field) {\n" + " return ::$proto_ns$::internal::GetAnyFieldDescriptors(\n" + " message, type_url_field, value_field);\n" + "}\n"); } + format( + "bool $classname$::ParseAnyTypeUrl(\n" + " ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,\n" + " std::string* full_type_name) {\n" + " return ::$proto_ns$::internal::ParseAnyTypeUrl(type_url,\n" + " full_type_name);\n" + "}\n" + "\n"); } -} -void MessageGenerator:: -GenerateClassMethods(io::Printer* printer) { - if (IsMapEntryMessage(descriptor_)) { - if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print( - "$parent$::$classname$::$classname$() {}\n" - "$parent$::$classname$::$classname$(::google::protobuf::Arena* arena) : " - "SuperType(arena) {}\n" - "::google::protobuf::Metadata $parent$::$classname$::GetMetadata() const {\n" - " $file_namespace$::protobuf_AssignDescriptorsOnce();\n" - " return $file_namespace$::file_level_metadata[$index$];\n" - "}\n" - "void $parent$::$classname$::MergeFrom(\n" - " const ::google::protobuf::Message& other) {\n" - " ::google::protobuf::Message::MergeFrom(other);\n" - "}\n" - "void $parent$::$classname$::MergeFrom(const $classname$& other) {\n" - " MergeFromInternal(other);\n" - "}\n" - "\n", - "file_namespace", FileLevelNamespace(descriptor_->file()->name()), - "parent", ClassName(descriptor_->containing_type(), false), - "classname", classname_, "index", - SimpleItoa(index_in_file_messages_)); + format( + "class $classname$::_Internal {\n" + " public:\n"); + format.Indent(); + if (!has_bit_indices_.empty()) { + format( + "using HasBits = decltype(std::declval<$classname$>()._has_bits_);\n"); + } + for (auto field : FieldRange(descriptor_)) { + field_generators_.get(field).GenerateInternalAccessorDeclarations(printer); + if (IsFieldStripped(field, options_)) { + continue; + } + if (HasHasbit(field)) { + int has_bit_index = HasBitIndex(field); + GOOGLE_CHECK_NE(has_bit_index, kNoHasbit) << field->full_name(); + format( + "static void set_has_$1$(HasBits* has_bits) {\n" + " (*has_bits)[$2$] |= $3$u;\n" + "}\n", + FieldName(field), has_bit_index / 32, (1u << (has_bit_index % 32))); } - return; } - - if (IsAnyMessage(descriptor_)) { - printer->Print( - "void $classname$::PackFrom(const ::google::protobuf::Message& message) {\n" - " _any_metadata_.PackFrom(message);\n" - "}\n" - "\n" - "void $classname$::PackFrom(const ::google::protobuf::Message& message,\n" - " const ::std::string& type_url_prefix) {\n" - " _any_metadata_.PackFrom(message, type_url_prefix);\n" - "}\n" - "\n" - "bool $classname$::UnpackTo(::google::protobuf::Message* message) const {\n" - " return _any_metadata_.UnpackTo(message);\n" - "}\n" - "\n", - "classname", classname_); + if (num_required_fields_ > 0) { + const std::vector masks_for_has_bits = RequiredFieldsBitMask(); + format( + "static bool MissingRequiredFields(const HasBits& has_bits) " + "{\n" + " return $1$;\n" + "}\n", + ConditionalToCheckBitmasks(masks_for_has_bits, false, "has_bits")); } - // Generate non-inline field definitions. - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateNonInlineAccessorDefinitions(printer); + format.Outdent(); + format("};\n\n"); + for (auto field : FieldRange(descriptor_)) { + if (!IsFieldStripped(field, options_)) { + field_generators_.get(field).GenerateInternalAccessorDefinitions(printer); + } } - // Generate field number constants. - printer->Print("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor *field = descriptor_->field(i); - printer->Print( - "const int $classname$::$constant_name$;\n", - "classname", ClassName(FieldScope(field), false), - "constant_name", FieldConstantName(field)); + // Generate non-inline field definitions. + for (auto field : FieldRange(descriptor_)) { + if (IsFieldStripped(field, options_)) { + continue; + } + field_generators_.get(field).GenerateNonInlineAccessorDefinitions(printer); + if (IsCrossFileMaybeMap(field)) { + Formatter::SaveState saver(&format); + std::map vars; + SetCommonFieldVariables(field, &vars, options_); + if (field->real_containing_oneof()) { + SetCommonOneofFieldVariables(field, &vars); + } + format.AddMap(vars); + GenerateFieldClear(field, false, format); + } } - printer->Print( - "#endif // !defined(_MSC_VER) || _MSC_VER >= 1900\n" - "\n"); GenerateStructors(printer); - printer->Print("\n"); + format("\n"); - if (descriptor_->oneof_decl_count() > 0) { + if (descriptor_->real_oneof_decl_count() > 0) { GenerateOneofClear(printer); - printer->Print("\n"); + format("\n"); } if (HasGeneratedMethods(descriptor_->file(), options_)) { GenerateClear(printer); - printer->Print("\n"); + format("\n"); GenerateMergeFromCodedStream(printer); - printer->Print("\n"); + format("\n"); - GenerateSerializeWithCachedSizes(printer); - printer->Print("\n"); - - if (HasFastArraySerialization(descriptor_->file(), options_)) { - GenerateSerializeWithCachedSizesToArray(printer); - printer->Print("\n"); - } + GenerateSerializeWithCachedSizesToArray(printer); + format("\n"); GenerateByteSize(printer); - printer->Print("\n"); + format("\n"); GenerateMergeFrom(printer); - printer->Print("\n"); + format("\n"); + + GenerateClassSpecificMergeFrom(printer); + format("\n"); GenerateCopyFrom(printer); - printer->Print("\n"); + format("\n"); GenerateIsInitialized(printer); - printer->Print("\n"); + format("\n"); } GenerateSwap(printer); - printer->Print("\n"); + format("\n"); if (options_.table_driven_serialization) { - printer->Print( - "const void* $classname$::InternalGetTable() const {\n" - " return $file_namespace$::TableStruct::serialization_table + $index$;\n" - "}\n" - "\n", - "classname", classname_, "index", SimpleItoa(index_in_file_messages_), - "file_namespace", FileLevelNamespace(descriptor_->file()->name())); + format( + "const void* $classname$::InternalGetTable() const {\n" + " return ::$tablename$::serialization_table + $1$;\n" + "}\n" + "\n", + index_in_file_messages_); } if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print( - "::google::protobuf::Metadata $classname$::GetMetadata() const {\n" - " $file_namespace$::protobuf_AssignDescriptorsOnce();\n" - " return " - "$file_namespace$::file_level_metadata[kIndexInFileMessages];\n" + format( + "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n" + " return GetMetadataStatic();\n" "}\n" - "\n", - "classname", classname_, "file_namespace", - FileLevelNamespace(descriptor_->file()->name())); + "\n"); } else { - printer->Print( - "::std::string $classname$::GetTypeName() const {\n" - " return \"$type_name$\";\n" - "}\n" - "\n", - "classname", classname_, - "type_name", descriptor_->full_name()); + format( + "std::string $classname$::GetTypeName() const {\n" + " return \"$full_name$\";\n" + "}\n" + "\n"); } } size_t MessageGenerator::GenerateParseOffsets(io::Printer* printer) { + Formatter format(printer, variables_); + if (!table_driven_) { return 0; } // Field "0" is special: We use it in our switch statement of processing // types to handle the successful end tag case. - printer->Print("{0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},\n"); + format("{0, 0, 0, ::$proto_ns$::internal::kInvalidMask, 0, 0},\n"); int last_field_number = 1; std::vector ordered_fields = SortFieldsByNumber(descriptor_); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = ordered_fields[i]; + for (auto field : ordered_fields) { + Formatter::SaveState saver(&format); GOOGLE_CHECK_GE(field->number(), last_field_number); for (; last_field_number < field->number(); last_field_number++) { - printer->Print( - "{ 0, 0, ::google::protobuf::internal::kInvalidMask,\n" - " ::google::protobuf::internal::kInvalidMask, 0, 0 },\n"); + format( + "{ 0, 0, ::$proto_ns$::internal::kInvalidMask,\n" + " ::$proto_ns$::internal::kInvalidMask, 0, 0 },\n"); } last_field_number++; @@ -2198,58 +2079,70 @@ size_t MessageGenerator::GenerateParseOffsets(io::Printer* printer) { processing_type = static_cast(field->type()); if (field->type() == FieldDescriptor::TYPE_STRING) { - switch (EffectiveStringCType(field)) { + switch (EffectiveStringCType(field, options_)) { case FieldOptions::STRING: - default: + break; + case FieldOptions::CORD: + processing_type = internal::TYPE_STRING_CORD; + break; + case FieldOptions::STRING_PIECE: + processing_type = internal::TYPE_STRING_STRING_PIECE; break; } } else if (field->type() == FieldDescriptor::TYPE_BYTES) { - switch (EffectiveStringCType(field)) { + switch (EffectiveStringCType(field, options_)) { case FieldOptions::STRING: - default: + break; + case FieldOptions::CORD: + processing_type = internal::TYPE_BYTES_CORD; + break; + case FieldOptions::STRING_PIECE: + processing_type = internal::TYPE_BYTES_STRING_PIECE; break; } } processing_type |= static_cast( - field->is_repeated() ? internal::kRepeatedMask : 0); + field->is_repeated() ? internal::kRepeatedMask : 0); processing_type |= static_cast( - field->containing_oneof() ? internal::kOneofMask : 0); + field->real_containing_oneof() ? internal::kOneofMask : 0); if (field->is_map()) { processing_type = internal::TYPE_MAP; } const unsigned char tag_size = - WireFormat::TagSize(field->number(), field->type()); + WireFormat::TagSize(field->number(), field->type()); - std::map vars; - vars["classname"] = classname_; - if (field->containing_oneof() != NULL) { + std::map vars; + if (field->real_containing_oneof()) { vars["name"] = field->containing_oneof()->name(); - vars["presence"] = SimpleItoa(field->containing_oneof()->index()); + vars["presence"] = StrCat(field->containing_oneof()->index()); } else { vars["name"] = FieldName(field); - vars["presence"] = SimpleItoa(has_bit_indices_[field->index()]); + vars["presence"] = StrCat(has_bit_indices_[field->index()]); } - vars["nwtype"] = SimpleItoa(normal_wiretype); - vars["pwtype"] = SimpleItoa(packed_wiretype); - vars["ptype"] = SimpleItoa(processing_type); - vars["tag_size"] = SimpleItoa(tag_size); + vars["nwtype"] = StrCat(normal_wiretype); + vars["pwtype"] = StrCat(packed_wiretype); + vars["ptype"] = StrCat(processing_type); + vars["tag_size"] = StrCat(tag_size); - printer->Print(vars, - "{\n" - " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n" - " $classname$, $name$_),\n" - " static_cast< ::google::protobuf::uint32>($presence$),\n" - " $nwtype$, $pwtype$, $ptype$, $tag_size$\n" - "},\n"); + format.AddMap(vars); + + format( + "{\n" + " PROTOBUF_FIELD_OFFSET($classtype$, $name$_),\n" + " static_cast<$uint32$>($presence$),\n" + " $nwtype$, $pwtype$, $ptype$, $tag_size$\n" + "},\n"); } return last_field_number; } size_t MessageGenerator::GenerateParseAuxTable(io::Printer* printer) { + Formatter format(printer, variables_); + if (!table_driven_) { return 0; } @@ -2257,99 +2150,79 @@ size_t MessageGenerator::GenerateParseAuxTable(io::Printer* printer) { std::vector ordered_fields = SortFieldsByNumber(descriptor_); - printer->Print("::google::protobuf::internal::AuxillaryParseTableField(),\n"); + format("::$proto_ns$::internal::AuxiliaryParseTableField(),\n"); int last_field_number = 1; - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = ordered_fields[i]; + for (auto field : ordered_fields) { + Formatter::SaveState saver(&format); GOOGLE_CHECK_GE(field->number(), last_field_number); for (; last_field_number < field->number(); last_field_number++) { - printer->Print("::google::protobuf::internal::AuxillaryParseTableField(),\n"); + format("::$proto_ns$::internal::AuxiliaryParseTableField(),\n"); } - std::map vars; + std::map vars; SetCommonFieldVariables(field, &vars, options_); + format.AddMap(vars); switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_ENUM: - vars["type"] = ClassName(field->enum_type(), true); - printer->Print( - vars, - "{::google::protobuf::internal::AuxillaryParseTableField::enum_aux{" - "$type$_IsValid}},\n"); + if (HasPreservingUnknownEnumSemantics(field)) { + format( + "{::$proto_ns$::internal::AuxiliaryParseTableField::enum_aux{" + "nullptr}},\n"); + } else { + format( + "{::$proto_ns$::internal::AuxiliaryParseTableField::enum_aux{" + "$1$_IsValid}},\n", + ClassName(field->enum_type(), true)); + } last_field_number++; break; case FieldDescriptor::CPPTYPE_MESSAGE: { - std::vector package_parts; - - const Descriptor* outer = field->message_type(); - while (outer->containing_type() != NULL) { - outer = outer->containing_type(); - } - - package_parts = Split( - outer->full_name(), ".", true); - // outer->full_name() contains the class itself. Remove it as it is - // used in the name of the default instance variable. - GOOGLE_DCHECK_NE(package_parts.size(), 0); - package_parts.back().clear(); - if (field->is_map()) { - vars["classname"] = ClassName(field->containing_type(), false) + - "::" + ClassName(field->message_type(), false); - printer->Print(vars, - "{::google::protobuf::internal::AuxillaryParseTableField::map_" - "aux{&::google::protobuf::internal::ParseMap<$classname$>}},\n"); + format( + "{::$proto_ns$::internal::AuxiliaryParseTableField::map_" + "aux{&::$proto_ns$::internal::ParseMap<$1$>}},\n", + QualifiedClassName(field->message_type(), options_)); last_field_number++; break; - } else { - vars["classname"] = ClassName(field->message_type(), false); - } - vars["ns"] = Join(package_parts, "::"); - vars["type"] = FieldMessageTypeName(field); - vars["file_namespace"] = FileLevelNamespace(outer->file()->name()); - - printer->Print(vars, - "{::google::protobuf::internal::AuxillaryParseTableField::message_aux{\n" - " &::$ns$_$classname$_default_instance_,\n"); - - bool dont_emit_table = - !TableDrivenParsingEnabled(field->message_type(), options_); - - if (dont_emit_table) { - printer->Print(" NULL,\n"); - } else { - printer->Print(vars, - " ::$ns$$file_namespace$::TableStruct::schema +\n" - " ::$ns$$classname$::kIndexInFileMessages,\n"); } + format.Set("field_classname", ClassName(field->message_type(), false)); + format.Set("default_instance", QualifiedDefaultInstanceName( + field->message_type(), options_)); - printer->Print("}},\n"); + format( + "{::$proto_ns$::internal::AuxiliaryParseTableField::message_aux{\n" + " &$default_instance$}},\n"); last_field_number++; break; } - case FieldDescriptor::CPPTYPE_STRING: - switch (EffectiveStringCType(field)) { + case FieldDescriptor::CPPTYPE_STRING: { + std::string default_val; + switch (EffectiveStringCType(field, options_)) { case FieldOptions::STRING: - vars["default"] = - field->default_value_string().empty() - ? "&::google::protobuf::internal::fixed_address_empty_string" - : "&" + classname_ + "::_default_" + FieldName(field) + "_"; + default_val = field->default_value_string().empty() + ? "&::" + variables_["proto_ns"] + + "::internal::fixed_address_empty_string" + : "&" + + QualifiedClassName(descriptor_, options_) + + "::" + MakeDefaultName(field); break; case FieldOptions::CORD: case FieldOptions::STRING_PIECE: - vars["default"] = + default_val = "\"" + CEscape(field->default_value_string()) + "\""; break; } - vars["full_name"] = field->full_name(); - printer->Print(vars, - "{::google::protobuf::internal::AuxillaryParseTableField::string_aux{\n" - " $default$,\n" - " \"$full_name$\"\n" - "}},\n"); + format( + "{::$proto_ns$::internal::AuxiliaryParseTableField::string_aux{\n" + " $1$,\n" + " \"$2$\"\n" + "}},\n", + default_val, field->full_name()); last_field_number++; break; + } default: break; } @@ -2360,183 +2233,145 @@ size_t MessageGenerator::GenerateParseAuxTable(io::Printer* printer) { std::pair MessageGenerator::GenerateOffsets( io::Printer* printer) { - if (IsMapEntryMessage(descriptor_)) return std::make_pair(0, 0); - std::map variables; - variables["classname"] = classname_; - - if (HasFieldPresence(descriptor_->file())) { - printer->Print( - variables, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "_has_bits_),\n"); + Formatter format(printer, variables_); + + if (!has_bit_indices_.empty() || IsMapEntryMessage(descriptor_)) { + format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n"); } else { - printer->Print("~0u, // no _has_bits_\n"); + format("~0u, // no _has_bits_\n"); } - printer->Print(variables, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "_internal_metadata_),\n"); + format("PROTOBUF_FIELD_OFFSET($classtype$, _internal_metadata_),\n"); if (descriptor_->extension_range_count() > 0) { - printer->Print( - variables, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "_extensions_),\n"); + format("PROTOBUF_FIELD_OFFSET($classtype$, _extensions_),\n"); } else { - printer->Print("~0u, // no _extensions_\n"); + format("~0u, // no _extensions_\n"); } - if (descriptor_->oneof_decl_count() > 0) { - printer->Print(variables, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" - "$classname$, _oneof_case_[0]),\n"); + if (descriptor_->real_oneof_decl_count() > 0) { + format("PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_[0]),\n"); } else { - printer->Print("~0u, // no _oneof_case_\n"); + format("~0u, // no _oneof_case_\n"); } if (num_weak_fields_ > 0) { - printer->Print(variables, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$," - " _weak_field_map_),\n"); + format("PROTOBUF_FIELD_OFFSET($classtype$, _weak_field_map_),\n"); } else { - printer->Print("~0u, // no _weak_field_map_\n"); + format("~0u, // no _weak_field_map_\n"); } const int kNumGenericOffsets = 5; // the number of fixed offsets above - const size_t offsets = kNumGenericOffsets + - descriptor_->field_count() + - descriptor_->oneof_decl_count(); + const size_t offsets = kNumGenericOffsets + descriptor_->field_count() + + descriptor_->real_oneof_decl_count(); size_t entries = offsets; - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof() || field->options().weak()) { - printer->Print( - "offsetof($classname$DefaultTypeInternal, $name$_),\n", - "classname", classname_, "name", FieldName(field)); + for (auto field : FieldRange(descriptor_)) { + if (IsFieldStripped(field, options_)) { + format("~0u, // stripped\n"); + continue; + } + // TODO(sbenza): We should not have an entry in the offset table for fields + // that do not use them. + if (field->options().weak() || field->real_containing_oneof()) { + // Mark the field to prevent unintentional access through reflection. + // Don't use the top bit because that is for unused fields. + format("::$proto_ns$::internal::kInvalidFieldOffsetTag"); } else { - printer->Print( - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "$name$_),\n", - "classname", classname_, - "name", FieldName(field)); + format("PROTOBUF_FIELD_OFFSET($classtype$, $1$_)", FieldName(field)); + } + + if (!IsFieldUsed(field, options_)) { + format(" | 0x80000000u, // unused\n"); + } else { + format(",\n"); } } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - const OneofDescriptor* oneof = descriptor_->oneof_decl(i); - printer->Print( - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n", - "classname", classname_, - "name", oneof->name()); + int count = 0; + for (auto oneof : OneOfRange(descriptor_)) { + format("PROTOBUF_FIELD_OFFSET($classtype$, $1$_),\n", oneof->name()); + count++; } + GOOGLE_CHECK_EQ(count, descriptor_->real_oneof_decl_count()); - if (HasFieldPresence(descriptor_->file())) { + if (IsMapEntryMessage(descriptor_)) { + entries += 2; + format( + "0,\n" + "1,\n"); + } else if (!has_bit_indices_.empty()) { entries += has_bit_indices_.size(); for (int i = 0; i < has_bit_indices_.size(); i++) { - const string index = has_bit_indices_[i] >= 0 ? - SimpleItoa(has_bit_indices_[i]) : "~0u"; - printer->Print("$index$,\n", "index", index); + const std::string index = + has_bit_indices_[i] >= 0 ? StrCat(has_bit_indices_[i]) : "~0u"; + format("$1$,\n", index); } } return std::make_pair(entries, offsets); } -void MessageGenerator:: -GenerateSharedConstructorCode(io::Printer* printer) { - printer->Print( - "void $classname$::SharedCtor() {\n", - "classname", classname_); - printer->Indent(); +void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) { + Formatter format(printer, variables_); - bool need_to_clear_cached_size = true; - // We reproduce the logic used for laying out _cached_sized_ in the class - // definition, as to initialize it in-order. - if (HasFieldPresence(descriptor_->file()) && - (HasBitsSize() % 8) != 0) { - printer->Print("_cached_size_ = 0;\n"); - need_to_clear_cached_size = false; - } + format("void $classname$::SharedCtor() {\n"); std::vector processed(optimized_order_.size(), false); GenerateConstructorBody(printer, processed, false); - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "clear_has_$oneof_name$();\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); - } - - if (need_to_clear_cached_size) { - printer->Print("_cached_size_ = 0;\n"); + for (auto oneof : OneOfRange(descriptor_)) { + format("clear_has_$1$();\n", oneof->name()); } - printer->Outdent(); - printer->Print("}\n\n"); + format("}\n\n"); } -void MessageGenerator:: -GenerateSharedDestructorCode(io::Printer* printer) { - printer->Print( - "void $classname$::SharedDtor() {\n", - "classname", classname_); - printer->Indent(); - if (SupportsArenas(descriptor_)) { - // Do nothing when the message is allocated in an arena. - printer->Print( - "::google::protobuf::Arena* arena = GetArenaNoVirtual();\n" - "GOOGLE_DCHECK(arena == NULL);\n" - "if (arena != NULL) {\n" - " return;\n" - "}\n" - "\n"); - } +void MessageGenerator::GenerateSharedDestructorCode(io::Printer* printer) { + Formatter format(printer, variables_); + format("void $classname$::SharedDtor() {\n"); + format.Indent(); + format("$DCHK$(GetArena() == nullptr);\n"); // Write the destructors for each field except oneof members. // optimized_order_ does not contain oneof fields. - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; + for (auto field : optimized_order_) { field_generators_.get(field).GenerateDestructorCode(printer); } // Generate code to destruct oneofs. Clearing should do the work. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "if (has_$oneof_name$()) {\n" - " clear_$oneof_name$();\n" + for (auto oneof : OneOfRange(descriptor_)) { + format( + "if (has_$1$()) {\n" + " clear_$1$();\n" "}\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); + oneof->name()); } if (num_weak_fields_) { - printer->Print("_weak_field_map_.ClearAll();\n"); + format("_weak_field_map_.ClearAll();\n"); } - printer->Outdent(); - printer->Print( - "}\n" - "\n"); + format.Outdent(); + format( + "}\n" + "\n"); } -void MessageGenerator:: -GenerateArenaDestructorCode(io::Printer* printer) { +void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) { + Formatter format(printer, variables_); + // Generate the ArenaDtor() method. Track whether any fields actually produced // code that needs to be called. - printer->Print( - "void $classname$::ArenaDtor(void* object) {\n", - "classname", classname_); - printer->Indent(); + format("void $classname$::ArenaDtor(void* object) {\n"); + format.Indent(); // This code is placed inside a static method, rather than an ordinary one, // since that simplifies Arena's destructor list (ordinary function pointers // rather than member function pointers). _this is the object being // destructed. - printer->Print( + format( "$classname$* _this = reinterpret_cast< $classname$* >(object);\n" // avoid an "unused variable" warning in case no fields have dtor code. - "(void)_this;\n", - "classname", classname_); + "(void)_this;\n"); bool need_registration = false; // Process non-oneof fields first. - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - if (field_generators_.get(field) - .GenerateArenaDestructorCode(printer)) { + for (auto field : optimized_order_) { + if (field_generators_.get(field).GenerateArenaDestructorCode(printer)) { need_registration = true; } } @@ -2545,69 +2380,82 @@ GenerateArenaDestructorCode(io::Printer* printer) { // // Note: As of 10/5/2016, GenerateArenaDestructorCode does not emit anything // and returns false for oneof fields. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - const OneofDescriptor* oneof = descriptor_->oneof_decl(i); - - for (int j = 0; j < oneof->field_count(); j++) { - const FieldDescriptor* field = oneof->field(j); - if (field_generators_.get(field) - .GenerateArenaDestructorCode(printer)) { + for (auto oneof : OneOfRange(descriptor_)) { + for (auto field : FieldRange(oneof)) { + if (!IsFieldStripped(field, options_) && + field_generators_.get(field).GenerateArenaDestructorCode(printer)) { need_registration = true; } } } - if (num_weak_fields_) { - // _this is the object being destructed (we are inside a static method - // here). - printer->Print("_this->_weak_field_map_.ClearAll();\n"); - need_registration = true; - } - printer->Outdent(); - printer->Print( - "}\n"); + format.Outdent(); + format("}\n"); if (need_registration) { - printer->Print( - "inline void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n" - " if (arena != NULL) {\n" + format( + "inline void $classname$::RegisterArenaDtor(::$proto_ns$::Arena* " + "arena) {\n" + " if (arena != nullptr) {\n" " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n" " }\n" - "}\n", - "classname", classname_); + "}\n"); } else { - printer->Print( - "void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n" - "}\n", - "classname", classname_); + format( + "void $classname$::RegisterArenaDtor(::$proto_ns$::Arena*) {\n" + "}\n"); } } -void MessageGenerator::GenerateConstructorBody(io::Printer* printer, - std::vector processed, - bool copy_constructor) const { - const FieldDescriptor* last_start = NULL; - // RunMap maps from fields that start each run to the number of fields in that - // run. This is optimized for the common case that there are very few runs in - // a message and that most of the eligible fields appear together. - typedef hash_map RunMap; - RunMap runs; +void MessageGenerator::GenerateConstexprConstructor(io::Printer* printer) { + Formatter format(printer, variables_); - for (int i = 0; i < optimized_order_.size(); ++i) { - const FieldDescriptor* field = optimized_order_[i]; - if ((copy_constructor && IsPOD(field)) || - (!copy_constructor && CanConstructByZeroing(field, options_))) { - if (last_start == NULL) { - last_start = field; - } + format( + "constexpr $classname$::$classname$(\n" + " ::$proto_ns$::internal::ConstantInitialized)"); + format.Indent(); + const char* field_sep = ":"; + const auto put_sep = [&] { + format("\n$1$ ", field_sep); + field_sep = ","; + }; - runs[last_start]++; - } else { - last_start = NULL; + if (!IsMapEntryMessage(descriptor_)) { + // Process non-oneof fields first. + for (auto field : optimized_order_) { + auto& gen = field_generators_.get(field); + put_sep(); + gen.GenerateConstinitInitializer(printer); + } + + if (IsAnyMessage(descriptor_, options_)) { + put_sep(); + format("_any_metadata_(&type_url_, &value_)"); + } + + if (descriptor_->real_oneof_decl_count() != 0) { + put_sep(); + format("_oneof_case_{}"); } } - string pod_template; + format.Outdent(); + format("{}\n"); +} + +void MessageGenerator::GenerateConstructorBody(io::Printer* printer, + std::vector processed, + bool copy_constructor) const { + Formatter format(printer, variables_); + + const RunMap runs = FindRuns( + optimized_order_, [copy_constructor, this](const FieldDescriptor* field) { + return (copy_constructor && IsPOD(field)) || + (!copy_constructor && + CanBeManipulatedAsRawBytes(field, options_)); + }); + + std::string pod_template; if (copy_constructor) { pod_template = "::memcpy(&$first$_, &from.$first$_,\n" @@ -2615,8 +2463,10 @@ void MessageGenerator::GenerateConstructorBody(io::Printer* printer, " reinterpret_cast(&$first$_)) + sizeof($last$_));\n"; } else { pod_template = - "::memset(&$first$_, 0, static_cast(\n" - " reinterpret_cast(&$last$_) -\n" + "::memset(reinterpret_cast(this) + static_cast(\n" + " reinterpret_cast(&$first$_) - " + "reinterpret_cast(this)),\n" + " 0, static_cast(reinterpret_cast(&$last$_) -\n" " reinterpret_cast(&$first$_)) + sizeof($last$_));\n"; } @@ -2626,20 +2476,21 @@ void MessageGenerator::GenerateConstructorBody(io::Printer* printer, } const FieldDescriptor* field = optimized_order_[i]; - RunMap::const_iterator it = runs.find(field); + const auto it = runs.find(field); // We only apply the memset technique to runs of more than one field, as // assignment is better than memset for generated code clarity. if (it != runs.end() && it->second > 1) { // Use a memset, then skip run_length fields. const size_t run_length = it->second; - const string first_field_name = FieldName(field); - const string last_field_name = + const std::string first_field_name = FieldName(field); + const std::string last_field_name = FieldName(optimized_order_[i + run_length - 1]); - printer->Print(pod_template.c_str(), - "first", first_field_name, - "last", last_field_name); + format.Set("first", first_field_name); + format.Set("last", last_field_name); + + format(pod_template.c_str()); i += run_length - 1; // ++i at the top of the loop. @@ -2653,830 +2504,625 @@ void MessageGenerator::GenerateConstructorBody(io::Printer* printer, } } -void MessageGenerator:: -GenerateStructors(io::Printer* printer) { - string superclass; - if (use_dependent_base_) { - superclass = - DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">"; - } else { - superclass = SuperClassName(descriptor_, options_); - } - string initializer_with_arena = superclass + "()"; +void MessageGenerator::GenerateStructors(io::Printer* printer) { + Formatter format(printer, variables_); + + std::string superclass; + superclass = SuperClassName(descriptor_, options_); + std::string initializer_with_arena = superclass + "(arena)"; if (descriptor_->extension_range_count() > 0) { initializer_with_arena += ",\n _extensions_(arena)"; } - initializer_with_arena += ",\n _internal_metadata_(arena)"; - // Initialize member variables with arena constructor. - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - + for (auto field : optimized_order_) { + GOOGLE_DCHECK(!IsFieldStripped(field, options_)); bool has_arena_constructor = field->is_repeated(); + if (!field->real_containing_oneof() && + (IsLazy(field, options_) || IsStringPiece(field, options_))) { + has_arena_constructor = true; + } if (has_arena_constructor) { - initializer_with_arena += string(",\n ") + - FieldName(field) + string("_(arena)"); + initializer_with_arena += + std::string(",\n ") + FieldName(field) + std::string("_(arena)"); } } - if (IsAnyMessage(descriptor_)) { + if (IsAnyMessage(descriptor_, options_)) { initializer_with_arena += ",\n _any_metadata_(&type_url_, &value_)"; } if (num_weak_fields_ > 0) { initializer_with_arena += ", _weak_field_map_(arena)"; } - string initializer_null = superclass + "(), _internal_metadata_(NULL)"; - if (IsAnyMessage(descriptor_)) { + std::string initializer_null = superclass + "()"; + if (IsAnyMessage(descriptor_, options_)) { initializer_null += ", _any_metadata_(&type_url_, &value_)"; } if (num_weak_fields_ > 0) { - initializer_null += ", _weak_field_map_(NULL)"; + initializer_null += ", _weak_field_map_(nullptr)"; } - printer->Print( - "$classname$::$classname$()\n" - " : $initializer$ {\n" - " if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {\n" - " $file_namespace$::InitDefaults();\n" - " }\n" + format( + "$classname$::$classname$(::$proto_ns$::Arena* arena)\n" + " : $1$ {\n" " SharedCtor();\n" - " // @@protoc_insertion_point(constructor:$full_name$)\n" + " RegisterArenaDtor(arena);\n" + " // @@protoc_insertion_point(arena_constructor:$full_name$)\n" "}\n", - "classname", classname_, "full_name", descriptor_->full_name(), - "initializer", initializer_null, "file_namespace", - FileLevelNamespace(descriptor_->file()->name())); - - if (SupportsArenas(descriptor_)) { - printer->Print( - "$classname$::$classname$(::google::protobuf::Arena* arena)\n" - " : $initializer$ {\n" - " $file_namespace$::InitDefaults();\n" - " SharedCtor();\n" - " RegisterArenaDtor(arena);\n" - " // @@protoc_insertion_point(arena_constructor:$full_name$)\n" - "}\n", - "initializer", initializer_with_arena, "classname", classname_, - "superclass", superclass, "full_name", descriptor_->full_name(), - "file_namespace", FileLevelNamespace(descriptor_->file()->name())); - } + initializer_with_arena); - // Generate the copy constructor. - printer->Print( - "$classname$::$classname$(const $classname$& from)\n" - " : $superclass$()", - "classname", classname_, - "superclass", superclass, - "full_name", descriptor_->full_name()); - printer->Indent(); - printer->Indent(); - printer->Indent(); - - printer->Print( - ",\n_internal_metadata_(NULL)"); - - if (HasFieldPresence(descriptor_->file())) { - printer->Print(",\n_has_bits_(from._has_bits_)"); - } - - bool need_to_emit_cached_size = true; - const string cached_size_decl = ",\n_cached_size_(0)"; - // We reproduce the logic used for laying out _cached_sized_ in the class - // definition, as to initialize it in-order. - if (HasFieldPresence(descriptor_->file()) && - (HasBitsSize() % 8) != 0) { - printer->Print(cached_size_decl.c_str()); - need_to_emit_cached_size = false; - } + std::map vars; + SetUnknkownFieldsVariable(descriptor_, options_, &vars); + format.AddMap(vars); - std::vector processed(optimized_order_.size(), false); - for (int i = 0; i < optimized_order_.size(); ++i) { - const FieldDescriptor* field = optimized_order_[i]; + // Generate the copy constructor. + if (UsingImplicitWeakFields(descriptor_->file(), options_)) { + // If we are in lite mode and using implicit weak fields, we generate a + // one-liner copy constructor that delegates to MergeFrom. This saves some + // code size and also cuts down on the complexity of implicit weak fields. + // We might eventually want to do this for all lite protos. + format( + "$classname$::$classname$(const $classname$& from)\n" + " : $classname$() {\n" + " MergeFrom(from);\n" + "}\n"); + } else { + format( + "$classname$::$classname$(const $classname$& from)\n" + " : $superclass$()"); + format.Indent(); + format.Indent(); + format.Indent(); - if (!(field->is_repeated() && !(field->is_map())) - ) { - continue; + if (!has_bit_indices_.empty()) { + format(",\n_has_bits_(from._has_bits_)"); } - processed[i] = true; - printer->Print(",\n$name$_(from.$name$_)", - "name", FieldName(field)); - } + std::vector processed(optimized_order_.size(), false); + for (int i = 0; i < optimized_order_.size(); i++) { + auto field = optimized_order_[i]; + if (!(field->is_repeated() && !(field->is_map())) && + !IsCord(field, options_)) { + continue; + } - if (need_to_emit_cached_size) { - printer->Print(cached_size_decl.c_str()); - need_to_emit_cached_size = false; - } + processed[i] = true; + format(",\n$1$_(from.$1$_)", FieldName(field)); + } - if (IsAnyMessage(descriptor_)) { - printer->Print(",\n_any_metadata_(&type_url_, &value_)"); - } - if (num_weak_fields_ > 0) { - printer->Print(",\n_weak_field_map_(from._weak_field_map_)"); - } + if (IsAnyMessage(descriptor_, options_)) { + format(",\n_any_metadata_(&type_url_, &value_)"); + } + if (num_weak_fields_ > 0) { + format(",\n_weak_field_map_(from._weak_field_map_)"); + } - printer->Outdent(); - printer->Outdent(); - printer->Print(" {\n"); + format.Outdent(); + format.Outdent(); + format(" {\n"); - printer->Print( - "_internal_metadata_.MergeFrom(from._internal_metadata_);\n"); + format( + "_internal_metadata_.MergeFrom<$unknown_fields_type$>(from._internal_" + "metadata_);\n"); - if (descriptor_->extension_range_count() > 0) { - printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); - } - - GenerateConstructorBody(printer, processed, true); - - // Copy oneof fields. Oneof field requires oneof case check. - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - printer->Print( - "clear_has_$oneofname$();\n" - "switch (from.$oneofname$_case()) {\n", - "oneofname", descriptor_->oneof_decl(i)->name()); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case k$field_name$: {\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); - field_generators_.get(field).GenerateMergingCode(printer); - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); - } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" - " break;\n" - "}\n", - "oneof_index", - SimpleItoa(descriptor_->oneof_decl(i)->index()), - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( - "}\n"); + if (descriptor_->extension_range_count() > 0) { + format("_extensions_.MergeFrom(from._extensions_);\n"); + } + + GenerateConstructorBody(printer, processed, true); + + // Copy oneof fields. Oneof field requires oneof case check. + for (auto oneof : OneOfRange(descriptor_)) { + format( + "clear_has_$1$();\n" + "switch (from.$1$_case()) {\n", + oneof->name()); + format.Indent(); + for (auto field : FieldRange(oneof)) { + format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); + format.Indent(); + if (!IsFieldStripped(field, options_)) { + field_generators_.get(field).GenerateMergingCode(printer); + } + format("break;\n"); + format.Outdent(); + format("}\n"); + } + format( + "case $1$_NOT_SET: {\n" + " break;\n" + "}\n", + ToUpper(oneof->name())); + format.Outdent(); + format("}\n"); + } + + format.Outdent(); + format( + " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" + "}\n" + "\n"); } - printer->Outdent(); - printer->Print( - " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" - "}\n" - "\n", - "full_name", descriptor_->full_name()); - // Generate the shared constructor code. GenerateSharedConstructorCode(printer); // Generate the destructor. - printer->Print( - "$classname$::~$classname$() {\n" - " // @@protoc_insertion_point(destructor:$full_name$)\n" - " SharedDtor();\n" - "}\n" - "\n", - "classname", classname_, - "full_name", descriptor_->full_name()); + format( + "$classname$::~$classname$() {\n" + " // @@protoc_insertion_point(destructor:$full_name$)\n" + " SharedDtor();\n" + " _internal_metadata_.Delete<$unknown_fields_type$>();\n" + "}\n" + "\n"); // Generate the shared destructor code. GenerateSharedDestructorCode(printer); // Generate the arena-specific destructor code. - if (SupportsArenas(descriptor_)) { - GenerateArenaDestructorCode(printer); - } + GenerateArenaDestructorCode(printer); // Generate SetCachedSize. - printer->Print( - "void $classname$::SetCachedSize(int size) const {\n" - " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" - " _cached_size_ = size;\n" - " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" - "}\n", - "classname", classname_); - - // Only generate this member if it's not disabled. - if (HasDescriptorMethods(descriptor_->file(), options_) && - !descriptor_->options().no_standard_descriptor_accessor()) { - printer->Print( - "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n" - " $file_namespace$::protobuf_AssignDescriptorsOnce();\n" - " return " - "$file_namespace$::file_level_metadata[kIndexInFileMessages]." - "descriptor;\n" - "}\n" - "\n", - "classname", classname_, "file_namespace", - FileLevelNamespace(descriptor_->file()->name())); - } - - printer->Print( - "const $classname$& $classname$::default_instance() {\n" - " $file_namespace$::InitDefaults();\n" - " return *internal_default_instance();\n" - "}\n\n", - "classname", classname_, "file_namespace", - FileLevelNamespace(descriptor_->file()->name())); - - if (SupportsArenas(descriptor_)) { - printer->Print( - "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n" - " return ::google::protobuf::Arena::CreateMessage<$classname$>(arena);\n" - "}\n", - "classname", classname_); - } else { - printer->Print( - "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n" - " $classname$* n = new $classname$;\n" - " if (arena != NULL) {\n" - " arena->Own(n);\n" - " }\n" - " return n;\n" - "}\n", - "classname", classname_); - } + format( + "void $classname$::SetCachedSize(int size) const {\n" + " _cached_size_.Set(size);\n" + "}\n"); } -// Return the number of bits set in n, a non-negative integer. -static int popcnt(uint32 n) { - int result = 0; - while (n != 0) { - result += (n & 1); - n = n / 2; - } - return result; +void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) { + Formatter format(printer, variables_); + format( + "template<> " + "PROTOBUF_NOINLINE " + "$classtype$* Arena::CreateMaybeMessage< $classtype$ >(Arena* arena) {\n" + " return Arena::CreateMessageInternal< $classtype$ >(arena);\n" + "}\n"); } -bool MessageGenerator::MaybeGenerateOptionalFieldCondition( - io::Printer* printer, const FieldDescriptor* field, - int expected_has_bits_index) { - int has_bit_index = has_bit_indices_[field->index()]; - if (!field->options().weak() && - expected_has_bits_index == has_bit_index / 32) { - const string mask = - StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); - printer->Print( - "if (cached_has_bits & 0x$mask$u) {\n", - "mask", mask); - return true; - } - return false; -} +void MessageGenerator::GenerateClear(io::Printer* printer) { + Formatter format(printer, variables_); + + // The maximum number of bytes we will memset to zero without checking their + // hasbit to see if a zero-init is necessary. + const int kMaxUnconditionalPrimitiveBytesClear = 4; -void MessageGenerator:: -GenerateClear(io::Printer* printer) { - printer->Print( + format( "void $classname$::Clear() {\n" - "// @@protoc_insertion_point(message_clear_start:$full_name$)\n", - "classname", classname_, "full_name", descriptor_->full_name()); - printer->Indent(); + "// @@protoc_insertion_point(message_clear_start:$full_name$)\n"); + format.Indent(); - printer->Print( + format( // TODO(jwb): It would be better to avoid emitting this if it is not used, // rather than emitting a workaround for the resulting warning. - "::google::protobuf::uint32 cached_has_bits = 0;\n" + "$uint32$ cached_has_bits = 0;\n" "// Prevent compiler warnings about cached_has_bits being unused\n" "(void) cached_has_bits;\n\n"); - int cached_has_bit_index = -1; - - // Step 1: Extensions if (descriptor_->extension_range_count() > 0) { - printer->Print("_extensions_.Clear();\n"); - } - - int last_i = -1; - for (int i = 0; i < optimized_order_.size(); ) { - // Detect infinite loops. - GOOGLE_CHECK_NE(i, last_i); - last_i = i; - - // Step 2: Repeated fields don't use _has_bits_; emit code to clear them - // here. - for (; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - const FieldGenerator& generator = field_generators_.get(field); - - if (!field->is_repeated()) { - break; - } - - if (use_dependent_base_ && IsFieldDependent(field)) { - printer->Print("clear_$name$();\n", "name", FieldName(field)); + format("_extensions_.Clear();\n"); + } + + // Collect fields into chunks. Each chunk may have an if() condition that + // checks all hasbits in the chunk and skips it if none are set. + int zero_init_bytes = 0; + for (const auto& field : optimized_order_) { + if (CanInitializeByZeroing(field)) { + zero_init_bytes += EstimateAlignmentSize(field); + } + } + bool merge_zero_init = zero_init_bytes > kMaxUnconditionalPrimitiveBytesClear; + int chunk_count = 0; + + std::vector> chunks = CollectFields( + optimized_order_, + [&](const FieldDescriptor* a, const FieldDescriptor* b) -> bool { + chunk_count++; + // This predicate guarantees that there is only a single zero-init + // (memset) per chunk, and if present it will be at the beginning. + bool same = HasByteIndex(a) == HasByteIndex(b) && + a->is_repeated() == b->is_repeated() && + (CanInitializeByZeroing(a) == CanInitializeByZeroing(b) || + (CanInitializeByZeroing(a) && + (chunk_count == 1 || merge_zero_init))); + if (!same) chunk_count = 0; + return same; + }); + + ColdChunkSkipper cold_skipper(options_, chunks, has_bit_indices_, kColdRatio); + int cached_has_word_index = -1; + + for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) { + std::vector& chunk = chunks[chunk_index]; + cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", printer); + + const FieldDescriptor* memset_start = nullptr; + const FieldDescriptor* memset_end = nullptr; + bool saw_non_zero_init = false; + + for (const auto& field : chunk) { + if (CanInitializeByZeroing(field)) { + GOOGLE_CHECK(!saw_non_zero_init); + if (!memset_start) memset_start = field; + memset_end = field; } else { - generator.GenerateMessageClearingCode(printer); + saw_non_zero_init = true; } } - // Step 3: Greedily seek runs of fields that can be cleared by - // memset-to-0. - int last_chunk = -1; - int last_chunk_start = -1; - int last_chunk_end = -1; - uint32 last_chunk_mask = 0; - - int memset_run_start = -1; - int memset_run_end = -1; - for (; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - - if (!CanInitializeByZeroing(field)) { - break; - } - - // "index" defines where in the _has_bits_ the field appears. - // "i" is our loop counter within optimized_order_. - int index = HasFieldPresence(descriptor_->file()) ? - has_bit_indices_[field->index()] : 0; - int chunk = index / 8; - - if (last_chunk == -1) { - last_chunk = chunk; - last_chunk_start = i; - } else if (chunk != last_chunk) { - // Emit the fields for this chunk so far. - break; - } - - if (memset_run_start == -1) { - memset_run_start = i; + // Whether we wrap this chunk in: + // if (cached_has_bits & 1 && + (memset_end != chunk.back() || merge_zero_init); + + if (have_outer_if) { + // Emit an if() that will let us skip the whole chunk if none are set. + uint32 chunk_mask = GenChunkMask(chunk, has_bit_indices_); + std::string chunk_mask_str = + StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8)); + + // Check (up to) 8 has_bits at a time if we have more than one field in + // this chunk. Due to field layout ordering, we may check + // _has_bits_[last_chunk * 8 / 32] multiple times. + GOOGLE_DCHECK_LE(2, popcnt(chunk_mask)); + GOOGLE_DCHECK_GE(8, popcnt(chunk_mask)); + + if (cached_has_word_index != HasWordIndex(chunk.front())) { + cached_has_word_index = HasWordIndex(chunk.front()); + format("cached_has_bits = _has_bits_[$1$];\n", cached_has_word_index); } - - memset_run_end = i; - last_chunk_end = i; - last_chunk_mask |= static_cast(1) << (index % 32); + format("if (cached_has_bits & 0x$1$u) {\n", chunk_mask_str); + format.Indent(); } - // Step 4: Non-repeated, non-zero initializable fields. - for (; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - if (field->is_repeated() || CanInitializeByZeroing(field)) { - break; - } - - // "index" defines where in the _has_bits_ the field appears. - // "i" is our loop counter within optimized_order_. - int index = HasFieldPresence(descriptor_->file()) ? - has_bit_indices_[field->index()] : 0; - int chunk = index / 8; - - if (last_chunk == -1) { - last_chunk = chunk; - last_chunk_start = i; - } else if (chunk != last_chunk) { - // Emit the fields for this chunk so far. - break; + if (memset_start) { + if (memset_start == memset_end) { + // For clarity, do not memset a single field. + field_generators_.get(memset_start) + .GenerateMessageClearingCode(printer); + } else { + format( + "::memset(&$1$_, 0, static_cast(\n" + " reinterpret_cast(&$2$_) -\n" + " reinterpret_cast(&$1$_)) + sizeof($2$_));\n", + FieldName(memset_start), FieldName(memset_end)); } - - last_chunk_end = i; - last_chunk_mask |= static_cast(1) << (index % 32); } - if (last_chunk != -1) { - GOOGLE_DCHECK_NE(-1, last_chunk_start); - GOOGLE_DCHECK_NE(-1, last_chunk_end); - GOOGLE_DCHECK_NE(0, last_chunk_mask); - - const int count = popcnt(last_chunk_mask); - const bool have_outer_if = HasFieldPresence(descriptor_->file()) && - (last_chunk_start != last_chunk_end); - - if (have_outer_if) { - // Check (up to) 8 has_bits at a time if we have more than one field in - // this chunk. Due to field layout ordering, we may check - // _has_bits_[last_chunk * 8 / 32] multiple times. - GOOGLE_DCHECK_LE(2, count); - GOOGLE_DCHECK_GE(8, count); - - if (cached_has_bit_index != last_chunk / 4) { - cached_has_bit_index = last_chunk / 4; - printer->Print( - "cached_has_bits = _has_bits_[$idx$];\n", - "idx", SimpleItoa(cached_has_bit_index)); - } - printer->Print( - "if (cached_has_bits & $mask$u) {\n", - "mask", SimpleItoa(last_chunk_mask)); - printer->Indent(); + // Clear all non-zero-initializable fields in the chunk. + for (const auto& field : chunk) { + if (CanInitializeByZeroing(field)) continue; + // It's faster to just overwrite primitive types, but we should only + // clear strings and messages if they were set. + // + // TODO(kenton): Let the CppFieldGenerator decide this somehow. + bool have_enclosing_if = + HasBitIndex(field) != kNoHasbit && + (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || + field->cpp_type() == FieldDescriptor::CPPTYPE_STRING); + + if (have_enclosing_if) { + PrintPresenceCheck(format, field, has_bit_indices_, printer, + &cached_has_word_index); } - if (memset_run_start != -1) { - if (memset_run_start == memset_run_end) { - // For clarity, do not memset a single field. - const FieldGenerator& generator = - field_generators_.get(optimized_order_[memset_run_start]); - generator.GenerateMessageClearingCode(printer); - } else { - const string first_field_name = - FieldName(optimized_order_[memset_run_start]); - const string last_field_name = - FieldName(optimized_order_[memset_run_end]); - - printer->Print( - "::memset(&$first$_, 0, static_cast(\n" - " reinterpret_cast(&$last$_) -\n" - " reinterpret_cast(&$first$_)) + sizeof($last$_));\n", - "first", first_field_name, - "last", last_field_name); - } + field_generators_.get(field).GenerateMessageClearingCode(printer); - // Advance last_chunk_start to skip over the fields we zeroed/memset. - last_chunk_start = memset_run_end + 1; + if (have_enclosing_if) { + format.Outdent(); + format("}\n"); } + } - // Go back and emit clears for each of the fields we processed. - for (int j = last_chunk_start; j <= last_chunk_end; j++) { - const FieldDescriptor* field = optimized_order_[j]; - const string fieldname = FieldName(field); - const FieldGenerator& generator = field_generators_.get(field); - - // It's faster to just overwrite primitive types, but we should only - // clear strings and messages if they were set. - // - // TODO(kenton): Let the CppFieldGenerator decide this somehow. - bool should_check_bit = - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || - field->cpp_type() == FieldDescriptor::CPPTYPE_STRING; - - bool have_enclosing_if = false; - if (should_check_bit && - // If no field presence, then always clear strings/messages as well. - HasFieldPresence(descriptor_->file())) { - if (!MaybeGenerateOptionalFieldCondition(printer, field, - cached_has_bit_index)) { - printer->Print( - "if (has_$name$()) {\n", - "name", fieldname); - } - printer->Indent(); - have_enclosing_if = true; - } - - generator.GenerateMessageClearingCode(printer); - - if (have_enclosing_if) { - printer->Outdent(); - printer->Print("}\n"); - } - } + if (have_outer_if) { + format.Outdent(); + format("}\n"); + } - if (have_outer_if) { - printer->Outdent(); - printer->Print("}\n"); - } + if (cold_skipper.OnEndChunk(chunk_index, printer)) { + // Reset here as it may have been updated in just closed if statement. + cached_has_word_index = -1; } } // Step 4: Unions. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "clear_$oneof_name$();\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); + for (auto oneof : OneOfRange(descriptor_)) { + format("clear_$1$();\n", oneof->name()); } if (num_weak_fields_) { - printer->Print("_weak_field_map_.ClearAll();\n"); + format("_weak_field_map_.ClearAll();\n"); } - if (HasFieldPresence(descriptor_->file())) { + if (!has_bit_indices_.empty()) { // Step 5: Everything else. - printer->Print("_has_bits_.Clear();\n"); + format("_has_bits_.Clear();\n"); } - printer->Print("_internal_metadata_.Clear();\n"); + std::map vars; + SetUnknkownFieldsVariable(descriptor_, options_, &vars); + format.AddMap(vars); + format("_internal_metadata_.Clear<$unknown_fields_type$>();\n"); - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } -void MessageGenerator:: -GenerateOneofClear(io::Printer* printer) { +void MessageGenerator::GenerateOneofClear(io::Printer* printer) { // Generated function clears the active field and union case (e.g. foo_case_). - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - std::map oneof_vars; - oneof_vars["classname"] = classname_; - oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name(); - oneof_vars["full_name"] = descriptor_->full_name(); - string message_class; - - printer->Print(oneof_vars, - "void $classname$::clear_$oneofname$() {\n" - "// @@protoc_insertion_point(one_of_clear_start:" - "$full_name$)\n"); - printer->Indent(); - printer->Print(oneof_vars, - "switch ($oneofname$_case()) {\n"); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case k$field_name$: {\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); + int i = 0; + for (auto oneof : OneOfRange(descriptor_)) { + Formatter format(printer, variables_); + format.Set("oneofname", oneof->name()); + + format( + "void $classname$::clear_$oneofname$() {\n" + "// @@protoc_insertion_point(one_of_clear_start:$full_name$)\n"); + format.Indent(); + format("switch ($oneofname$_case()) {\n"); + format.Indent(); + for (auto field : FieldRange(oneof)) { + format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); + format.Indent(); // We clear only allocated objects in oneofs - if (!IsStringOrMessage(field)) { - printer->Print( - "// No need to clear\n"); + if (!IsStringOrMessage(field) || IsFieldStripped(field, options_)) { + format("// No need to clear\n"); } else { field_generators_.get(field).GenerateClearingCode(printer); } - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); + format("break;\n"); + format.Outdent(); + format("}\n"); } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" + format( + "case $1$_NOT_SET: {\n" " break;\n" "}\n", - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( + ToUpper(oneof->name())); + format.Outdent(); + format( "}\n" - "_oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n", - "oneof_index", SimpleItoa(i), - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( + "_oneof_case_[$1$] = $2$_NOT_SET;\n", + i, ToUpper(oneof->name())); + format.Outdent(); + format( "}\n" "\n"); + i++; } } -void MessageGenerator:: -GenerateSwap(io::Printer* printer) { - if (SupportsArenas(descriptor_)) { - // Generate the Swap member function. This is a lightweight wrapper around - // UnsafeArenaSwap() / MergeFrom() with temporaries, depending on the memory - // ownership situation: swapping across arenas or between an arena and a - // heap requires copying. - printer->Print( - "void $classname$::Swap($classname$* other) {\n" - " if (other == this) return;\n" - " if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {\n" - " InternalSwap(other);\n" - " } else {\n" - " $classname$* temp = New(GetArenaNoVirtual());\n" - " temp->MergeFrom(*other);\n" - " other->CopyFrom(*this);\n" - " InternalSwap(temp);\n" - " if (GetArenaNoVirtual() == NULL) {\n" - " delete temp;\n" - " }\n" - " }\n" - "}\n" - "void $classname$::UnsafeArenaSwap($classname$* other) {\n" - " if (other == this) return;\n" - " GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());\n" - " InternalSwap(other);\n" - "}\n", - "classname", classname_); - } else { - printer->Print( - "void $classname$::Swap($classname$* other) {\n" - " if (other == this) return;\n" - " InternalSwap(other);\n" - "}\n", - "classname", classname_); - } +void MessageGenerator::GenerateSwap(io::Printer* printer) { + Formatter format(printer, variables_); - // Generate the UnsafeArenaSwap member function. - printer->Print("void $classname$::InternalSwap($classname$* other) {\n", - "classname", classname_); - printer->Indent(); - printer->Print("using std::swap;\n"); + format("void $classname$::InternalSwap($classname$* other) {\n"); + format.Indent(); + format("using std::swap;\n"); if (HasGeneratedMethods(descriptor_->file(), options_)) { - for (int i = 0; i < optimized_order_.size(); i++) { - // optimized_order_ does not contain oneof fields, but the field - // generators for these fields do not emit swapping code on their own. - const FieldDescriptor* field = optimized_order_[i]; - field_generators_.get(field).GenerateSwappingCode(printer); + if (descriptor_->extension_range_count() > 0) { + format("_extensions_.Swap(&other->_extensions_);\n"); } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "swap($oneof_name$_, other->$oneof_name$_);\n" - "swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n", - "oneof_name", descriptor_->oneof_decl(i)->name(), - "i", SimpleItoa(i)); + std::map vars; + SetUnknkownFieldsVariable(descriptor_, options_, &vars); + format.AddMap(vars); + format( + "_internal_metadata_.Swap<$unknown_fields_type$>(&other->_internal_" + "metadata_);\n"); + + if (!has_bit_indices_.empty()) { + for (int i = 0; i < HasBitsSize(); ++i) { + format("swap(_has_bits_[$1$], other->_has_bits_[$1$]);\n", i); + } } - if (HasFieldPresence(descriptor_->file())) { - for (int i = 0; i < HasBitsSize() / 4; ++i) { - printer->Print("swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n", - "i", SimpleItoa(i)); + // If possible, we swap several fields at once, including padding. + const RunMap runs = + FindRuns(optimized_order_, [this](const FieldDescriptor* field) { + return CanBeManipulatedAsRawBytes(field, options_); + }); + + for (int i = 0; i < optimized_order_.size(); ++i) { + const FieldDescriptor* field = optimized_order_[i]; + const auto it = runs.find(field); + + // We only apply the memswap technique to runs of more than one field, as + // `swap(field_, other.field_)` is better than + // `memswap<...>(&field_, &other.field_)` for generated code readability. + if (it != runs.end() && it->second > 1) { + // Use a memswap, then skip run_length fields. + const size_t run_length = it->second; + const std::string first_field_name = FieldName(field); + const std::string last_field_name = + FieldName(optimized_order_[i + run_length - 1]); + + format.Set("first", first_field_name); + format.Set("last", last_field_name); + + format( + "::PROTOBUF_NAMESPACE_ID::internal::memswap<\n" + " PROTOBUF_FIELD_OFFSET($classname$, $last$_)\n" + " + sizeof($classname$::$last$_)\n" + " - PROTOBUF_FIELD_OFFSET($classname$, $first$_)>(\n" + " reinterpret_cast(&$first$_),\n" + " reinterpret_cast(&other->$first$_));\n"); + + i += run_length - 1; + // ++i at the top of the loop. + } else { + field_generators_.get(field).GenerateSwappingCode(printer); } } - printer->Print("_internal_metadata_.Swap(&other->_internal_metadata_);\n"); + for (auto oneof : OneOfRange(descriptor_)) { + format("swap($1$_, other->$1$_);\n", oneof->name()); + } - printer->Print("swap(_cached_size_, other->_cached_size_);\n"); - if (descriptor_->extension_range_count() > 0) { - printer->Print("_extensions_.Swap(&other->_extensions_);\n"); + for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { + format("swap(_oneof_case_[$1$], other->_oneof_case_[$1$]);\n", i); } + if (num_weak_fields_) { - printer->Print( - "_weak_field_map_.UnsafeArenaSwap(&other->_weak_field_map_);\n"); + format("_weak_field_map_.UnsafeArenaSwap(&other->_weak_field_map_);\n"); } } else { - printer->Print("GetReflection()->Swap(this, other);"); + format("GetReflection()->Swap(this, other);"); } - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } -void MessageGenerator:: -GenerateMergeFrom(io::Printer* printer) { +void MessageGenerator::GenerateMergeFrom(io::Printer* printer) { + Formatter format(printer, variables_); if (HasDescriptorMethods(descriptor_->file(), options_)) { // Generate the generalized MergeFrom (aka that which takes in the Message // base class as a parameter). - printer->Print( - "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n" + format( + "void $classname$::MergeFrom(const ::$proto_ns$::Message& from) {\n" "// @@protoc_insertion_point(generalized_merge_from_start:" "$full_name$)\n" - " GOOGLE_DCHECK_NE(&from, this);\n", - "classname", classname_, "full_name", descriptor_->full_name()); - printer->Indent(); + " $DCHK$_NE(&from, this);\n"); + format.Indent(); // Cast the message to the proper type. If we find that the message is // *not* of the proper type, we can still call Merge via the reflection // system, as the GOOGLE_CHECK above ensured that we have the same descriptor // for each message. - printer->Print( - "const $classname$* source =\n" - " ::google::protobuf::internal::DynamicCastToGenerated(\n" - " &from);\n" - "if (source == NULL) {\n" - "// @@protoc_insertion_point(generalized_merge_from_cast_fail:" - "$full_name$)\n" - " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n" - "} else {\n" - "// @@protoc_insertion_point(generalized_merge_from_cast_success:" - "$full_name$)\n" - " MergeFrom(*source);\n" - "}\n", - "classname", classname_, "full_name", descriptor_->full_name()); + format( + "const $classname$* source =\n" + " ::$proto_ns$::DynamicCastToGenerated<$classname$>(\n" + " &from);\n" + "if (source == nullptr) {\n" + "// @@protoc_insertion_point(generalized_merge_from_cast_fail:" + "$full_name$)\n" + " ::$proto_ns$::internal::ReflectionOps::Merge(from, this);\n" + "} else {\n" + "// @@protoc_insertion_point(generalized_merge_from_cast_success:" + "$full_name$)\n" + " MergeFrom(*source);\n" + "}\n"); - printer->Outdent(); - printer->Print("}\n\n"); + format.Outdent(); + format("}\n"); } else { // Generate CheckTypeAndMergeFrom(). - printer->Print( - "void $classname$::CheckTypeAndMergeFrom(\n" - " const ::google::protobuf::MessageLite& from) {\n" - " MergeFrom(*::google::protobuf::down_cast(&from));\n" - "}\n" - "\n", - "classname", classname_); + format( + "void $classname$::CheckTypeAndMergeFrom(\n" + " const ::$proto_ns$::MessageLite& from) {\n" + " MergeFrom(*::$proto_ns$::internal::DownCast(\n" + " &from));\n" + "}\n"); } +} +void MessageGenerator::GenerateClassSpecificMergeFrom(io::Printer* printer) { // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast. - printer->Print( + Formatter format(printer, variables_); + format( "void $classname$::MergeFrom(const $classname$& from) {\n" - "// @@protoc_insertion_point(class_specific_merge_from_start:" - "$full_name$)\n" - " GOOGLE_DCHECK_NE(&from, this);\n", - "classname", classname_, "full_name", descriptor_->full_name()); - printer->Indent(); - - if (descriptor_->extension_range_count() > 0) { - printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); - } - - printer->Print( - "_internal_metadata_.MergeFrom(from._internal_metadata_);\n" - "::google::protobuf::uint32 cached_has_bits = 0;\n" - "(void) cached_has_bits;\n\n"); - - // cached_has_bit_index maintains that: - // cached_has_bits = from._has_bits_[cached_has_bit_index] - // for cached_has_bit_index >= 0 - int cached_has_bit_index = -1; - - int last_i = -1; - for (int i = 0; i < optimized_order_.size(); ) { - // Detect infinite loops. - GOOGLE_CHECK_NE(i, last_i); - last_i = i; - - // Merge Repeated fields. These fields do not require a - // check as we can simply iterate over them. - for (; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - if (!field->is_repeated()) { - break; - } - - const FieldGenerator& generator = field_generators_.get(field); - generator.GenerateMergingCode(printer); - } + "// @@protoc_insertion_point(class_specific_merge_from_start:" + "$full_name$)\n" + " $DCHK$_NE(&from, this);\n"); + format.Indent(); - // Merge Optional and Required fields (after a _has_bit_ check). - int last_chunk = -1; - int last_chunk_start = -1; - int last_chunk_end = -1; - uint32 last_chunk_mask = 0; - for (; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - if (field->is_repeated()) { - break; - } + if (descriptor_->extension_range_count() > 0) { + format("_extensions_.MergeFrom(from._extensions_);\n"); + } + std::map vars; + SetUnknkownFieldsVariable(descriptor_, options_, &vars); + format.AddMap(vars); + format( + "_internal_metadata_.MergeFrom<$unknown_fields_type$>(from._internal_" + "metadata_);\n" + "$uint32$ cached_has_bits = 0;\n" + "(void) cached_has_bits;\n\n"); - // "index" defines where in the _has_bits_ the field appears. - // "i" is our loop counter within optimized_order_. - int index = HasFieldPresence(descriptor_->file()) ? - has_bit_indices_[field->index()] : 0; - int chunk = index / 8; - - if (last_chunk == -1) { - last_chunk = chunk; - last_chunk_start = i; - } else if (chunk != last_chunk) { - // Emit the fields for this chunk so far. - break; + std::vector> chunks = CollectFields( + optimized_order_, + [&](const FieldDescriptor* a, const FieldDescriptor* b) -> bool { + return HasByteIndex(a) == HasByteIndex(b); + }); + + ColdChunkSkipper cold_skipper(options_, chunks, has_bit_indices_, kColdRatio); + + // cached_has_word_index maintains that: + // cached_has_bits = from._has_bits_[cached_has_word_index] + // for cached_has_word_index >= 0 + int cached_has_word_index = -1; + + for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) { + const std::vector& chunk = chunks[chunk_index]; + bool have_outer_if = + chunk.size() > 1 && HasByteIndex(chunk.front()) != kNoHasbit; + cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "from.", + printer); + + if (have_outer_if) { + // Emit an if() that will let us skip the whole chunk if none are set. + uint32 chunk_mask = GenChunkMask(chunk, has_bit_indices_); + std::string chunk_mask_str = + StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8)); + + // Check (up to) 8 has_bits at a time if we have more than one field in + // this chunk. Due to field layout ordering, we may check + // _has_bits_[last_chunk * 8 / 32] multiple times. + GOOGLE_DCHECK_LE(2, popcnt(chunk_mask)); + GOOGLE_DCHECK_GE(8, popcnt(chunk_mask)); + + if (cached_has_word_index != HasWordIndex(chunk.front())) { + cached_has_word_index = HasWordIndex(chunk.front()); + format("cached_has_bits = from._has_bits_[$1$];\n", + cached_has_word_index); } - last_chunk_end = i; - last_chunk_mask |= static_cast(1) << (index % 32); + format("if (cached_has_bits & 0x$1$u) {\n", chunk_mask_str); + format.Indent(); } - if (last_chunk != -1) { - GOOGLE_DCHECK_NE(-1, last_chunk_start); - GOOGLE_DCHECK_NE(-1, last_chunk_end); - GOOGLE_DCHECK_NE(0, last_chunk_mask); - - const int count = popcnt(last_chunk_mask); - const bool have_outer_if = HasFieldPresence(descriptor_->file()) && - (last_chunk_start != last_chunk_end); - - if (have_outer_if) { - // Check (up to) 8 has_bits at a time if we have more than one field in - // this chunk. Due to field layout ordering, we may check - // _has_bits_[last_chunk * 8 / 32] multiple times. - GOOGLE_DCHECK_LE(2, count); - GOOGLE_DCHECK_GE(8, count); - - if (cached_has_bit_index != last_chunk / 4) { - int new_index = last_chunk / 4; - printer->Print("cached_has_bits = from._has_bits_[$new_index$];\n", - "new_index", SimpleItoa(new_index)); - cached_has_bit_index = new_index; - } - - printer->Print( - "if (cached_has_bits & $mask$u) {\n", - "mask", SimpleItoa(last_chunk_mask)); - printer->Indent(); - } - - // Go back and emit clears for each of the fields we processed. - bool deferred_has_bit_changes = false; - for (int j = last_chunk_start; j <= last_chunk_end; j++) { - const FieldDescriptor* field = optimized_order_[j]; - const FieldGenerator& generator = field_generators_.get(field); - - bool have_enclosing_if = false; - if (HasFieldPresence(descriptor_->file())) { - // Attempt to use the state of cached_has_bits, if possible. - int has_bit_index = has_bit_indices_[field->index()]; - if (!field->options().weak() && - cached_has_bit_index == has_bit_index / 32) { - const string mask = StrCat( - strings::Hex(1u << (has_bit_index % 32), - strings::ZERO_PAD_8)); - - printer->Print( - "if (cached_has_bits & 0x$mask$u) {\n", "mask", mask); - } else { - printer->Print( - "if (from.has_$name$()) {\n", - "name", FieldName(field)); - } + // Go back and emit merging code for each of the fields we processed. + bool deferred_has_bit_changes = false; + for (const auto field : chunk) { + const FieldGenerator& generator = field_generators_.get(field); - printer->Indent(); - have_enclosing_if = true; - } else { - // Merge semantics without true field presence: primitive fields are - // merged only if non-zero (numeric) or non-empty (string). - have_enclosing_if = EmitFieldNonDefaultCondition( - printer, "from.", field); + if (field->is_repeated()) { + generator.GenerateMergingCode(printer); + } else if (field->is_optional() && !HasHasbit(field)) { + // Merge semantics without true field presence: primitive fields are + // merged only if non-zero (numeric) or non-empty (string). + bool have_enclosing_if = + EmitFieldNonDefaultCondition(printer, "from.", field); + generator.GenerateMergingCode(printer); + if (have_enclosing_if) { + format.Outdent(); + format("}\n"); } + } else if (field->options().weak() || + cached_has_word_index != HasWordIndex(field)) { + // Check hasbit, not using cached bits. + GOOGLE_CHECK(HasHasbit(field)); + format("if (from._internal_has_$1$()) {\n", FieldName(field)); + format.Indent(); + generator.GenerateMergingCode(printer); + format.Outdent(); + format("}\n"); + } else { + // Check hasbit, using cached bits. + GOOGLE_CHECK(HasHasbit(field)); + int has_bit_index = has_bit_indices_[field->index()]; + const std::string mask = StrCat( + strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); + format("if (cached_has_bits & 0x$1$u) {\n", mask); + format.Indent(); if (have_outer_if && IsPOD(field)) { - // GenerateCopyConstructorCode for enum and primitive scalar fields - // does not do _has_bits_ modifications. We defer _has_bits_ - // manipulation until the end of the outer if. - // + // Defer hasbit modification until the end of chunk. // This can reduce the number of loads/stores by up to 7 per 8 fields. deferred_has_bit_changes = true; generator.GenerateCopyConstructorCode(printer); @@ -3484,595 +3130,286 @@ GenerateMergeFrom(io::Printer* printer) { generator.GenerateMergingCode(printer); } - if (have_enclosing_if) { - printer->Outdent(); - printer->Print("}\n"); - } + format.Outdent(); + format("}\n"); } + } - if (have_outer_if) { - if (deferred_has_bit_changes) { - // Flush the has bits for the primitives we deferred. - GOOGLE_CHECK_LE(0, cached_has_bit_index); - printer->Print( - "_has_bits_[$index$] |= cached_has_bits;\n", - "index", SimpleItoa(cached_has_bit_index)); - } - - printer->Outdent(); - printer->Print("}\n"); + if (have_outer_if) { + if (deferred_has_bit_changes) { + // Flush the has bits for the primitives we deferred. + GOOGLE_CHECK_LE(0, cached_has_word_index); + format("_has_bits_[$1$] |= cached_has_bits;\n", cached_has_word_index); } + + format.Outdent(); + format("}\n"); + } + + if (cold_skipper.OnEndChunk(chunk_index, printer)) { + // Reset here as it may have been updated in just closed if statement. + cached_has_word_index = -1; } } // Merge oneof fields. Oneof field requires oneof case check. - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - printer->Print( - "switch (from.$oneofname$_case()) {\n", - "oneofname", descriptor_->oneof_decl(i)->name()); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case k$field_name$: {\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); - field_generators_.get(field).GenerateMergingCode(printer); - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); + for (auto oneof : OneOfRange(descriptor_)) { + format("switch (from.$1$_case()) {\n", oneof->name()); + format.Indent(); + for (auto field : FieldRange(oneof)) { + format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); + format.Indent(); + if (!IsFieldStripped(field, options_)) { + field_generators_.get(field).GenerateMergingCode(printer); + } + format("break;\n"); + format.Outdent(); + format("}\n"); } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" + format( + "case $1$_NOT_SET: {\n" " break;\n" "}\n", - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( - "}\n"); + ToUpper(oneof->name())); + format.Outdent(); + format("}\n"); } if (num_weak_fields_) { - printer->Print("_weak_field_map_.MergeFrom(from._weak_field_map_);\n"); + format("_weak_field_map_.MergeFrom(from._weak_field_map_);\n"); } - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } -void MessageGenerator:: -GenerateCopyFrom(io::Printer* printer) { +void MessageGenerator::GenerateCopyFrom(io::Printer* printer) { + Formatter format(printer, variables_); if (HasDescriptorMethods(descriptor_->file(), options_)) { // Generate the generalized CopyFrom (aka that which takes in the Message // base class as a parameter). - printer->Print( - "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n" + format( + "void $classname$::CopyFrom(const ::$proto_ns$::Message& from) {\n" "// @@protoc_insertion_point(generalized_copy_from_start:" - "$full_name$)\n", - "classname", classname_, "full_name", descriptor_->full_name()); - printer->Indent(); - - printer->Print( - "if (&from == this) return;\n" - "Clear();\n" - "MergeFrom(from);\n"); + "$full_name$)\n"); + format.Indent(); + + format("if (&from == this) return;\n"); + + if (!options_.opensource_runtime) { + // This check is disabled in the opensource release because we're + // concerned that many users do not define NDEBUG in their release + // builds. + format( + "#ifndef NDEBUG\n" + "size_t from_size = from.ByteSizeLong();\n" + "#endif\n" + "Clear();\n" + "#ifndef NDEBUG\n" + "$CHK$_EQ(from_size, from.ByteSizeLong())\n" + " << \"Source of CopyFrom changed when clearing target. Either \"\n" + " << \"source is a nested message in target (not allowed), or \"\n" + " << \"another thread is modifying the source.\";\n" + "#endif\n"); + } else { + format("Clear();\n"); + } + format("MergeFrom(from);\n"); - printer->Outdent(); - printer->Print("}\n\n"); + format.Outdent(); + format("}\n\n"); } // Generate the class-specific CopyFrom. - printer->Print( + format( "void $classname$::CopyFrom(const $classname$& from) {\n" "// @@protoc_insertion_point(class_specific_copy_from_start:" - "$full_name$)\n", - "classname", classname_, "full_name", descriptor_->full_name()); - printer->Indent(); - - printer->Print( - "if (&from == this) return;\n" - "Clear();\n" - "MergeFrom(from);\n"); + "$full_name$)\n"); + format.Indent(); + + format("if (&from == this) return;\n"); + + if (!options_.opensource_runtime) { + // This check is disabled in the opensource release because we're + // concerned that many users do not define NDEBUG in their release builds. + format( + "#ifndef NDEBUG\n" + "size_t from_size = from.ByteSizeLong();\n" + "#endif\n" + "Clear();\n" + "#ifndef NDEBUG\n" + "$CHK$_EQ(from_size, from.ByteSizeLong())\n" + " << \"Source of CopyFrom changed when clearing target. Either \"\n" + " << \"source is a nested message in target (not allowed), or \"\n" + " << \"another thread is modifying the source.\";\n" + "#endif\n"); + } else { + format("Clear();\n"); + } + format("MergeFrom(from);\n"); - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } -void MessageGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) { - std::map vars; +void MessageGenerator::GenerateMergeFromCodedStream(io::Printer* printer) { + std::map vars = variables_; SetUnknkownFieldsVariable(descriptor_, options_, &vars); + Formatter format(printer, vars); if (descriptor_->options().message_set_wire_format()) { // Special-case MessageSet. - vars["classname"] = classname_; - printer->Print(vars, - "bool $classname$::MergePartialFromCodedStream(\n" - " ::google::protobuf::io::CodedInputStream* input) {\n" - " return _extensions_.ParseMessageSet(input,\n" - " internal_default_instance(), $mutable_unknown_fields$);\n" - "}\n"); - return; - } - - std::vector ordered_fields = - SortFieldsByNumber(descriptor_); - - printer->Print( - "bool $classname$::MergePartialFromCodedStream(\n" - " ::google::protobuf::io::CodedInputStream* input) {\n", - "classname", classname_); - - if (table_driven_) { - printer->Indent(); - - const string lite = UseUnknownFieldSet(descriptor_->file(), options_) ? - "" : "Lite"; - - printer->Print( - "return ::google::protobuf::internal::MergePartialFromCodedStream$lite$(\n" - " this,\n" - " $file_namespace$::TableStruct::schema[\n" - " $classname$::kIndexInFileMessages],\n" - " input);\n", - "classname", classname_, - "file_namespace", FileLevelNamespace(descriptor_->file()->name()), - "lite", lite); - - printer->Outdent(); - - printer->Print("}\n"); - return; - } - - printer->Print( - "#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure\n" - " ::google::protobuf::uint32 tag;\n"); - - if (!UseUnknownFieldSet(descriptor_->file(), options_)) { - // Use LazyStringOutputString to avoid initializing unknown fields string - // unless it is actually needed. For the same reason, disable eager refresh - // on the CodedOutputStream. - printer->Print( - " ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n" - " ::google::protobuf::NewPermanentCallback(&_internal_metadata_,\n" - " &::google::protobuf::internal::InternalMetadataWithArenaLite::\n" - " mutable_unknown_fields));\n" - " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n" - " &unknown_fields_string, false);\n", - "classname", classname_); - } - - printer->Print( - " // @@protoc_insertion_point(parse_start:$full_name$)\n", - "full_name", descriptor_->full_name()); - - printer->Indent(); - printer->Print("for (;;) {\n"); - printer->Indent(); - - uint32 maxtag = descriptor_->field_count() == 0 ? 0 : - WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]); - const int kCutoff0 = 127; // fits in 1-byte varint - const int kCutoff1 = (127 << 7) + 127; // fits in 2-byte varint - - // We need to capture the last tag when parsing if this is a Group type, as - // our caller will verify (via CodedInputStream::LastTagWas) that the correct - // closing tag was received. - bool capture_last_tag = false; - const Descriptor* parent = descriptor_->containing_type(); - if (parent) { - for (int i = 0; i < parent->field_count(); i++) { - const FieldDescriptor* field = parent->field(i); - if (field->type() == FieldDescriptor::TYPE_GROUP && - field->message_type() == descriptor_) { - capture_last_tag = true; - break; - } - } - } - - for (int i = 0; i < descriptor_->file()->extension_count(); i++) { - const FieldDescriptor* field = descriptor_->file()->extension(i); - if (field->type() == FieldDescriptor::TYPE_GROUP && - field->message_type() == descriptor_) { - capture_last_tag = true; - break; - } - } - - printer->Print("::std::pair< ::google::protobuf::uint32, bool> p = " - "input->ReadTagWithCutoffNoLastTag($max$u);\n" - "tag = p.first;\n" - "if (!p.second) goto handle_unusual;\n", - "max", SimpleItoa(maxtag <= kCutoff0 ? kCutoff0 : - (maxtag <= kCutoff1 ? kCutoff1 : - maxtag))); - - if (descriptor_->field_count() > 0) { - // We don't even want to print the switch() if we have no fields because - // MSVC dislikes switch() statements that contain only a default value. - - // Note: If we just switched on the tag rather than the field number, we - // could avoid the need for the if() to check the wire type at the beginning - // of each case. However, this is actually a bit slower in practice as it - // creates a jump table that is 8x larger and sparser, and meanwhile the - // if()s are highly predictable. - // - // Historically, we inserted checks to peek at the next tag on the wire and - // jump directly to the next case statement. While this avoids the jump - // table that the switch uses, it greatly increases code size (20-60%) and - // inserts branches that may fail (especially for real world protos that - // interleave--in field number order--hot and cold fields). Loadtests - // confirmed that removing this optimization is performance neutral. - printer->Print("switch (::google::protobuf::internal::WireFormatLite::" - "GetTagFieldNumber(tag)) {\n"); - - printer->Indent(); - - for (int i = 0; i < ordered_fields.size(); i++) { - const FieldDescriptor* field = ordered_fields[i]; - - PrintFieldComment(printer, field); - - printer->Print( - "case $number$: {\n", - "number", SimpleItoa(field->number())); - printer->Indent(); - const FieldGenerator& field_generator = field_generators_.get(field); - - // Emit code to parse the common, expected case. - printer->Print( - "if (static_cast< ::google::protobuf::uint8>(tag) ==\n" - " static_cast< ::google::protobuf::uint8>($truncated$u /* $full$ & 0xFF */)) {\n", - "truncated", SimpleItoa(WireFormat::MakeTag(field) & 0xFF), - "full", SimpleItoa(WireFormat::MakeTag(field))); - - printer->Indent(); - if (field->is_packed()) { - field_generator.GenerateMergeFromCodedStreamWithPacking(printer); - } else { - field_generator.GenerateMergeFromCodedStream(printer); - } - printer->Outdent(); - - // Emit code to parse unexpectedly packed or unpacked values. - if (field->is_packed()) { - internal::WireFormatLite::WireType wiretype = - WireFormat::WireTypeForFieldType(field->type()); - const uint32 tag = internal::WireFormatLite::MakeTag( - field->number(), wiretype); - printer->Print( - "} else if (\n" - " static_cast< ::google::protobuf::uint8>(tag) ==\n" - " static_cast< ::google::protobuf::uint8>($truncated$u /* $full$ & 0xFF */)) {\n", - "truncated", SimpleItoa(tag & 0xFF), - "full", SimpleItoa(tag)); - - printer->Indent(); - field_generator.GenerateMergeFromCodedStream(printer); - printer->Outdent(); - } else if (field->is_packable() && !field->is_packed()) { - internal::WireFormatLite::WireType wiretype = - internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED; - const uint32 tag = internal::WireFormatLite::MakeTag( - field->number(), wiretype); - - printer->Print( - "} else if (\n" - " static_cast< ::google::protobuf::uint8>(tag) ==\n" - " static_cast< ::google::protobuf::uint8>($truncated$u /* $full$ & 0xFF */)) {\n", - "truncated", SimpleItoa(tag & 0xFF), - "full", SimpleItoa(tag)); - printer->Indent(); - field_generator.GenerateMergeFromCodedStreamWithPacking(printer); - printer->Outdent(); - } - - printer->Print( - "} else {\n" - " goto handle_unusual;\n" + format( + "const char* $classname$::_InternalParse(const char* ptr,\n" + " ::$proto_ns$::internal::ParseContext* ctx) {\n" + " return _extensions_.ParseMessageSet(ptr, \n" + " internal_default_instance(), &_internal_metadata_, ctx);\n" "}\n"); - - printer->Print( - "break;\n"); - - printer->Outdent(); - printer->Print("}\n\n"); - } - - printer->Print("default: {\n"); - printer->Indent(); - } - - printer->Outdent(); - printer->Print("handle_unusual:\n"); - printer->Indent(); - // If tag is 0 or an end-group tag then this must be the end of the message. - if (capture_last_tag) { - printer->Print( - "if (tag == 0 ||\n" - " ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" - " ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n" - " input->SetLastTag(tag);\n" - " goto success;\n" - "}\n"); - } else { - printer->Print( - "if (tag == 0) {\n" - " goto success;\n" - "}\n"); - } - - // Handle extension ranges. - if (descriptor_->extension_range_count() > 0) { - printer->Print( - "if ("); - for (int i = 0; i < descriptor_->extension_range_count(); i++) { - const Descriptor::ExtensionRange* range = - descriptor_->extension_range(i); - if (i > 0) printer->Print(" ||\n "); - - uint32 start_tag = WireFormatLite::MakeTag( - range->start, static_cast(0)); - uint32 end_tag = WireFormatLite::MakeTag( - range->end, static_cast(0)); - - if (range->end > FieldDescriptor::kMaxNumber) { - printer->Print( - "($start$u <= tag)", - "start", SimpleItoa(start_tag)); - } else { - printer->Print( - "($start$u <= tag && tag < $end$u)", - "start", SimpleItoa(start_tag), - "end", SimpleItoa(end_tag)); - } - } - printer->Print(") {\n"); - if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(vars, - " DO_(_extensions_.ParseField(tag, input,\n" - " internal_default_instance(),\n" - " $mutable_unknown_fields$));\n"); - } else { - printer->Print( - " DO_(_extensions_.ParseField(tag, input,\n" - " internal_default_instance(),\n" - " &unknown_fields_stream));\n"); - } - printer->Print( - " continue;\n" - "}\n"); + return; } - - // We really don't recognize this tag. Skip it. - if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(vars, - "DO_(::google::protobuf::internal::WireFormat::SkipField(\n" - " input, tag, $mutable_unknown_fields$));\n"); - } else { - printer->Print( - "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n" - " input, tag, &unknown_fields_stream));\n"); - } - - if (descriptor_->field_count() > 0) { - printer->Print("break;\n"); - printer->Outdent(); - printer->Print("}\n"); // default: - printer->Outdent(); - printer->Print("}\n"); // switch - } - - printer->Outdent(); - printer->Outdent(); - printer->Print( - " }\n" // for (;;) - "success:\n" - " // @@protoc_insertion_point(parse_success:$full_name$)\n" - " return true;\n" - "failure:\n" - " // @@protoc_insertion_point(parse_failure:$full_name$)\n" - " return false;\n" - "#undef DO_\n" - "}\n", "full_name", descriptor_->full_name()); + GenerateParserLoop(descriptor_, max_has_bit_index_, options_, scc_analyzer_, + printer); } void MessageGenerator::GenerateSerializeOneofFields( - io::Printer* printer, const std::vector& fields, - bool to_array) { + io::Printer* printer, const std::vector& fields) { + Formatter format(printer, variables_); GOOGLE_CHECK(!fields.empty()); if (fields.size() == 1) { - GenerateSerializeOneField(printer, fields[0], to_array, -1); + GenerateSerializeOneField(printer, fields[0], -1); return; } // We have multiple mutually exclusive choices. Emit a switch statement. const OneofDescriptor* oneof = fields[0]->containing_oneof(); - printer->Print( - "switch ($oneofname$_case()) {\n", - "oneofname", oneof->name()); - printer->Indent(); - for (int i = 0; i < fields.size(); i++) { - const FieldDescriptor* field = fields[i]; - printer->Print( - "case k$field_name$:\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); - if (to_array) { - field_generators_.get(field).GenerateSerializeWithCachedSizesToArray( - printer); - } else { - field_generators_.get(field).GenerateSerializeWithCachedSizes(printer); - } - printer->Print( - "break;\n"); - printer->Outdent(); + format("switch ($1$_case()) {\n", oneof->name()); + format.Indent(); + for (auto field : fields) { + format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); + format.Indent(); + field_generators_.get(field).GenerateSerializeWithCachedSizesToArray( + printer); + format("break;\n"); + format.Outdent(); + format("}\n"); } - printer->Outdent(); + format.Outdent(); // Doing nothing is an option. - printer->Print( - " default: ;\n" - "}\n"); + format( + " default: ;\n" + "}\n"); } -void MessageGenerator::GenerateSerializeOneField( - io::Printer* printer, const FieldDescriptor* field, bool to_array, - int cached_has_bits_index) { +void MessageGenerator::GenerateSerializeOneField(io::Printer* printer, + const FieldDescriptor* field, + int cached_has_bits_index) { + Formatter format(printer, variables_); if (!field->options().weak()) { // For weakfields, PrintFieldComment is called during iteration. - PrintFieldComment(printer, field); + PrintFieldComment(format, field); } bool have_enclosing_if = false; if (field->options().weak()) { - } else if (!field->is_repeated() && HasFieldPresence(descriptor_->file())) { + } else if (HasHasbit(field)) { // Attempt to use the state of cached_has_bits, if possible. - int has_bit_index = has_bit_indices_[field->index()]; + int has_bit_index = HasBitIndex(field); if (cached_has_bits_index == has_bit_index / 32) { - const string mask = StrCat( - strings::Hex(1u << (has_bit_index % 32), - strings::ZERO_PAD_8)); + const std::string mask = + StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); - printer->Print( - "if (cached_has_bits & 0x$mask$u) {\n", "mask", mask); + format("if (cached_has_bits & 0x$1$u) {\n", mask); } else { - printer->Print( - "if (has_$name$()) {\n", - "name", FieldName(field)); + format("if (_internal_has_$1$()) {\n", FieldName(field)); } - printer->Indent(); + format.Indent(); have_enclosing_if = true; - } else if (!HasFieldPresence(descriptor_->file())) { + } else if (field->is_optional() && !HasHasbit(field)) { have_enclosing_if = EmitFieldNonDefaultCondition(printer, "this->", field); } - if (to_array) { - field_generators_.get(field).GenerateSerializeWithCachedSizesToArray( - printer); - } else { - field_generators_.get(field).GenerateSerializeWithCachedSizes(printer); - } + field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(printer); if (have_enclosing_if) { - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } - printer->Print("\n"); + format("\n"); } void MessageGenerator::GenerateSerializeOneExtensionRange( - io::Printer* printer, const Descriptor::ExtensionRange* range, - bool to_array) { - std::map vars; - vars["start"] = SimpleItoa(range->start); - vars["end"] = SimpleItoa(range->end); - printer->Print(vars, - "// Extension range [$start$, $end$)\n"); - if (to_array) { - printer->Print(vars, - "target = _extensions_.InternalSerializeWithCachedSizesToArray(\n" - " $start$, $end$, deterministic, target);\n\n"); - } else { - printer->Print(vars, - "_extensions_.SerializeWithCachedSizes(\n" - " $start$, $end$, output);\n\n"); - } -} - -void MessageGenerator:: -GenerateSerializeWithCachedSizes(io::Printer* printer) { + io::Printer* printer, const Descriptor::ExtensionRange* range) { + std::map vars = variables_; + vars["start"] = StrCat(range->start); + vars["end"] = StrCat(range->end); + Formatter format(printer, vars); + format("// Extension range [$start$, $end$)\n"); + format( + "target = _extensions_._InternalSerialize(\n" + " $start$, $end$, target, stream);\n\n"); +} + +void MessageGenerator::GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) { + Formatter format(printer, variables_); if (descriptor_->options().message_set_wire_format()) { // Special-case MessageSet. - printer->Print( - "void $classname$::SerializeWithCachedSizes(\n" - " ::google::protobuf::io::CodedOutputStream* output) const {\n" - " _extensions_.SerializeMessageSetWithCachedSizes(output);\n", - "classname", classname_); - GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); - std::map vars; + format( + "$uint8$* $classname$::_InternalSerialize(\n" + " $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) " + "const {\n" + " target = _extensions_." + "InternalSerializeMessageSetWithCachedSizesToArray(target, stream);\n"); + std::map vars; SetUnknkownFieldsVariable(descriptor_, options_, &vars); - printer->Print(vars, - " ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n" - " $unknown_fields$, output);\n"); - printer->Print( - "}\n"); + format.AddMap(vars); + format( + " target = ::$proto_ns$::internal::" + "InternalSerializeUnknownMessageSetItemsToArray(\n" + " $unknown_fields$, target, stream);\n"); + format( + " return target;\n" + "}\n"); return; } - if (options_.table_driven_serialization) return; - printer->Print( - "void $classname$::SerializeWithCachedSizes(\n" - " ::google::protobuf::io::CodedOutputStream* output) const {\n", - "classname", classname_); - printer->Indent(); + format( + "$uint8$* $classname$::_InternalSerialize(\n" + " $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) " + "const {\n"); + format.Indent(); - printer->Print( - "// @@protoc_insertion_point(serialize_start:$full_name$)\n", - "full_name", descriptor_->full_name()); - - GenerateSerializeWithCachedSizesBody(printer, false); - - printer->Print( - "// @@protoc_insertion_point(serialize_end:$full_name$)\n", - "full_name", descriptor_->full_name()); - - printer->Outdent(); - printer->Print( - "}\n"); -} + format("// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n"); -void MessageGenerator:: -GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { - if (descriptor_->options().message_set_wire_format()) { - // Special-case MessageSet. - printer->Print( - "::google::protobuf::uint8* $classname$::InternalSerializeWithCachedSizesToArray(\n" - " bool deterministic, ::google::protobuf::uint8* target) const {\n" - " target = _extensions_." - "InternalSerializeMessageSetWithCachedSizesToArray(\n" - " deterministic, target);\n", - "classname", classname_); - GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); - std::map vars; - SetUnknkownFieldsVariable(descriptor_, options_, &vars); - printer->Print(vars, - " target = ::google::protobuf::internal::WireFormat::\n" - " SerializeUnknownMessageSetItemsToArray(\n" - " $unknown_fields$, target);\n"); - printer->Print( - " return target;\n" - "}\n"); - return; + if (!ShouldSerializeInOrder(descriptor_, options_)) { + format.Outdent(); + format("#ifdef NDEBUG\n"); + format.Indent(); } - printer->Print( - "::google::protobuf::uint8* $classname$::InternalSerializeWithCachedSizesToArray(\n" - " bool deterministic, ::google::protobuf::uint8* target) const {\n", - "classname", classname_); - printer->Indent(); + GenerateSerializeWithCachedSizesBody(printer); - printer->Print("(void)deterministic; // Unused\n"); - printer->Print( - "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n", - "full_name", descriptor_->full_name()); + if (!ShouldSerializeInOrder(descriptor_, options_)) { + format.Outdent(); + format("#else // NDEBUG\n"); + format.Indent(); - GenerateSerializeWithCachedSizesBody(printer, true); + GenerateSerializeWithCachedSizesBodyShuffled(printer); + + format.Outdent(); + format("#endif // !NDEBUG\n"); + format.Indent(); + } - printer->Print( - "// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n", - "full_name", descriptor_->full_name()); + format("// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n"); - printer->Outdent(); - printer->Print( - " return target;\n" - "}\n"); + format.Outdent(); + format( + " return target;\n" + "}\n"); } -void MessageGenerator:: -GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { +void MessageGenerator::GenerateSerializeWithCachedSizesBody( + io::Printer* printer) { + Formatter format(printer, variables_); // If there are multiple fields in a row from the same oneof then we // coalesce them and emit a switch statement. This is more efficient // because it lets the C++ compiler know this is a "at most one can happen" @@ -4080,13 +3417,11 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { // compiler's emitted code might check has_y() even when has_x() is true. class LazySerializerEmitter { public: - LazySerializerEmitter(MessageGenerator* mg, io::Printer* printer, - bool to_array) + LazySerializerEmitter(MessageGenerator* mg, io::Printer* printer) : mg_(mg), - printer_(printer), - to_array_(to_array), + format_(printer), eager_(!HasFieldPresence(mg->descriptor_->file())), - cached_has_bit_index_(-1) {} + cached_has_bit_index_(kNoHasbit) {} ~LazySerializerEmitter() { Flush(); } @@ -4096,7 +3431,7 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { if (eager_ || MustFlush(field)) { Flush(); } - if (field->containing_oneof() == NULL) { + if (!field->real_containing_oneof()) { // TODO(ckennelly): Defer non-oneof fields similarly to oneof fields. if (!field->options().weak() && !field->is_repeated() && !eager_) { @@ -4108,16 +3443,14 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { // Reload. int new_index = has_bit_index / 32; - printer_->Print( - "cached_has_bits = _has_bits_[$new_index$];\n", - "new_index", SimpleItoa(new_index)); + format_("cached_has_bits = _has_bits_[$1$];\n", new_index); cached_has_bit_index_ = new_index; } } - mg_->GenerateSerializeOneField( - printer_, field, to_array_, cached_has_bit_index_); + mg_->GenerateSerializeOneField(format_.printer(), field, + cached_has_bit_index_); } else { v_.push_back(field); } @@ -4125,7 +3458,7 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { void Flush() { if (!v_.empty()) { - mg_->GenerateSerializeOneofFields(printer_, v_, to_array_); + mg_->GenerateSerializeOneofFields(format_.printer(), v_); v_.clear(); } } @@ -4139,8 +3472,7 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { } MessageGenerator* mg_; - io::Printer* printer_; - const bool to_array_; + Formatter format_; const bool eager_; std::vector v_; @@ -4154,25 +3486,26 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { SortFieldsByNumber(descriptor_); std::vector sorted_extensions; + sorted_extensions.reserve(descriptor_->extension_range_count()); for (int i = 0; i < descriptor_->extension_range_count(); ++i) { sorted_extensions.push_back(descriptor_->extension_range(i)); } std::sort(sorted_extensions.begin(), sorted_extensions.end(), ExtensionRangeSorter()); if (num_weak_fields_) { - printer->Print( - "::google::protobuf::internal::WeakFieldMap::FieldWriter field_writer(" + format( + "::$proto_ns$::internal::WeakFieldMap::FieldWriter field_writer(" "_weak_field_map_);\n"); } - printer->Print( - "::google::protobuf::uint32 cached_has_bits = 0;\n" + format( + "$uint32$ cached_has_bits = 0;\n" "(void) cached_has_bits;\n\n"); // Merge the fields and the extension ranges, both sorted by field number. { - LazySerializerEmitter e(this, printer, to_array); - const FieldDescriptor* last_weak_field = NULL; + LazySerializerEmitter e(this, printer); + const FieldDescriptor* last_weak_field = nullptr; int i, j; for (i = 0, j = 0; i < ordered_fields.size() || j < sorted_extensions.size();) { @@ -4180,464 +3513,479 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { (i < descriptor_->field_count() && ordered_fields[i]->number() < sorted_extensions[j]->start)) { const FieldDescriptor* field = ordered_fields[i++]; + if (IsFieldStripped(field, options_)) { + continue; + } if (field->options().weak()) { - last_weak_field = field; - PrintFieldComment(printer, field); + if (last_weak_field == nullptr || + last_weak_field->number() < field->number()) { + last_weak_field = field; + } + PrintFieldComment(format, field); } else { - if (last_weak_field != NULL) { + if (last_weak_field != nullptr) { e.Emit(last_weak_field); - last_weak_field = NULL; + last_weak_field = nullptr; } e.Emit(field); } - } else { - if (last_weak_field != NULL) { + } else { + if (last_weak_field != nullptr) { e.Emit(last_weak_field); - last_weak_field = NULL; + last_weak_field = nullptr; } e.Flush(); - GenerateSerializeOneExtensionRange(printer, - sorted_extensions[j++], - to_array); + GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]); } } - if (last_weak_field != NULL) { + if (last_weak_field != nullptr) { e.Emit(last_weak_field); } } - std::map vars; + std::map vars; SetUnknkownFieldsVariable(descriptor_, options_, &vars); + format.AddMap(vars); + format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n"); + format.Indent(); if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(vars, - "if ($have_unknown_fields$) {\n"); - printer->Indent(); - if (to_array) { - printer->Print(vars, + format( "target = " - "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n" - " $unknown_fields$, target);\n"); - } else { - printer->Print(vars, - "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n" - " $unknown_fields$, output);\n"); - } - printer->Outdent(); + "::$proto_ns$::internal::WireFormat::" + "InternalSerializeUnknownFieldsToArray(\n" + " $unknown_fields$, target, stream);\n"); + } else { + format( + "target = stream->WriteRaw($unknown_fields$.data(),\n" + " static_cast($unknown_fields$.size()), target);\n"); + } + format.Outdent(); + format("}\n"); +} + +void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled( + io::Printer* printer) { + Formatter format(printer, variables_); + + std::vector ordered_fields = + SortFieldsByNumber(descriptor_); + ordered_fields.erase( + std::remove_if(ordered_fields.begin(), ordered_fields.end(), + [this](const FieldDescriptor* f) { + return !IsFieldUsed(f, options_); + }), + ordered_fields.end()); + + std::vector sorted_extensions; + sorted_extensions.reserve(descriptor_->extension_range_count()); + for (int i = 0; i < descriptor_->extension_range_count(); ++i) { + sorted_extensions.push_back(descriptor_->extension_range(i)); + } + std::sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeSorter()); + + int num_fields = ordered_fields.size() + sorted_extensions.size(); + constexpr int kLargePrime = 1000003; + GOOGLE_CHECK_LT(num_fields, kLargePrime) + << "Prime offset must be greater than the number of fields to ensure " + "those are coprime."; + + if (num_weak_fields_) { + format( + "::$proto_ns$::internal::WeakFieldMap::FieldWriter field_writer(" + "_weak_field_map_);\n"); + } + + format("for (int i = $1$; i >= 0; i-- ) {\n", num_fields - 1); + + format.Indent(); + format("switch(i) {\n"); + format.Indent(); + + int index = 0; + for (const auto* f : ordered_fields) { + format("case $1$: {\n", index++); + format.Indent(); + + GenerateSerializeOneField(printer, f, -1); + + format("break;\n"); + format.Outdent(); + format("}\n"); + } + + for (const auto* r : sorted_extensions) { + format("case $1$: {\n", index++); + format.Indent(); + + GenerateSerializeOneExtensionRange(printer, r); + + format("break;\n"); + format.Outdent(); + format("}\n"); + } + + format( + "default: {\n" + " $DCHK$(false) << \"Unexpected index: \" << i;\n" + "}\n"); + format.Outdent(); + format("}\n"); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); + + std::map vars; + SetUnknkownFieldsVariable(descriptor_, options_, &vars); + format.AddMap(vars); + format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n"); + format.Indent(); + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + format( + "target = " + "::$proto_ns$::internal::WireFormat::" + "InternalSerializeUnknownFieldsToArray(\n" + " $unknown_fields$, target, stream);\n"); } else { - printer->Print(vars, - "output->WriteRaw($unknown_fields$.data(),\n" - " static_cast($unknown_fields$.size()));\n"); + format( + "target = stream->WriteRaw($unknown_fields$.data(),\n" + " static_cast($unknown_fields$.size()), target);\n"); } + format.Outdent(); + format("}\n"); } std::vector MessageGenerator::RequiredFieldsBitMask() const { const int array_size = HasBitsSize(); std::vector masks(array_size, 0); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); + for (auto field : FieldRange(descriptor_)) { if (!field->is_required()) { continue; } const int has_bit_index = has_bit_indices_[field->index()]; - masks[has_bit_index / 32] |= - static_cast(1) << (has_bit_index % 32); + masks[has_bit_index / 32] |= static_cast(1) << (has_bit_index % 32); } return masks; } -// Create an expression that evaluates to -// "for all i, (_has_bits_[i] & masks[i]) == masks[i]" -// masks is allowed to be shorter than _has_bits_, but at least one element of -// masks must be non-zero. -static string ConditionalToCheckBitmasks(const std::vector& masks) { - std::vector parts; - for (int i = 0; i < masks.size(); i++) { - if (masks[i] == 0) continue; - string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8)); - // Each xor evaluates to 0 if the expected bits are present. - parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")")); - } - GOOGLE_CHECK(!parts.empty()); - // If we have multiple parts, each expected to be 0, then bitwise-or them. - string result = parts.size() == 1 ? parts[0] : - StrCat("(", Join(parts, "\n | "), ")"); - return result + " == 0"; -} +void MessageGenerator::GenerateByteSize(io::Printer* printer) { + Formatter format(printer, variables_); -void MessageGenerator:: -GenerateByteSize(io::Printer* printer) { if (descriptor_->options().message_set_wire_format()) { // Special-case MessageSet. - GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); - std::map vars; + std::map vars; SetUnknkownFieldsVariable(descriptor_, options_, &vars); - vars["classname"] = classname_; - vars["full_name"] = descriptor_->full_name(); - printer->Print(vars, - "size_t $classname$::ByteSizeLong() const {\n" - "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n" - " size_t total_size = _extensions_.MessageSetByteSize();\n" - " if ($have_unknown_fields$) {\n" - " total_size += ::google::protobuf::internal::WireFormat::\n" - " ComputeUnknownMessageSetItemsSize($unknown_fields$);\n" - " }\n" - " int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);\n" - " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" - " _cached_size_ = cached_size;\n" - " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" - " return total_size;\n" - "}\n"); + format.AddMap(vars); + format( + "size_t $classname$::ByteSizeLong() const {\n" + "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n" + " size_t total_size = _extensions_.MessageSetByteSize();\n" + " if ($have_unknown_fields$) {\n" + " total_size += ::$proto_ns$::internal::\n" + " ComputeUnknownMessageSetItemsSize($unknown_fields$);\n" + " }\n" + " int cached_size = " + "::$proto_ns$::internal::ToCachedSize(total_size);\n" + " SetCachedSize(cached_size);\n" + " return total_size;\n" + "}\n"); return; } - if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) { + if (num_required_fields_ > 1) { // Emit a function (rarely used, we hope) that handles the required fields // by checking for each one individually. - printer->Print( + format( "size_t $classname$::RequiredFieldsByteSizeFallback() const {\n" "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:" - "$full_name$)\n", - "classname", classname_, "full_name", descriptor_->full_name()); - printer->Indent(); - printer->Print("size_t total_size = 0;\n"); - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; + "$full_name$)\n"); + format.Indent(); + format("size_t total_size = 0;\n"); + for (auto field : optimized_order_) { if (field->is_required()) { - printer->Print("\n" - "if (has_$name$()) {\n", - "name", FieldName(field)); - printer->Indent(); - PrintFieldComment(printer, field); + format( + "\n" + "if (_internal_has_$1$()) {\n", + FieldName(field)); + format.Indent(); + PrintFieldComment(format, field); field_generators_.get(field).GenerateByteSize(printer); - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } } - printer->Print("\n" - "return total_size;\n"); - printer->Outdent(); - printer->Print("}\n"); + format( + "\n" + "return total_size;\n"); + format.Outdent(); + format("}\n"); } - printer->Print( + format( "size_t $classname$::ByteSizeLong() const {\n" - "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n", - "classname", classname_, "full_name", descriptor_->full_name()); - printer->Indent(); - printer->Print( - "size_t total_size = 0;\n" - "\n"); + "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n"); + format.Indent(); + format( + "size_t total_size = 0;\n" + "\n"); if (descriptor_->extension_range_count() > 0) { - printer->Print( - "total_size += _extensions_.ByteSize();\n" - "\n"); + format( + "total_size += _extensions_.ByteSize();\n" + "\n"); } - std::map vars; + std::map vars; SetUnknkownFieldsVariable(descriptor_, options_, &vars); - if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(vars, - "if ($have_unknown_fields$) {\n" - " total_size +=\n" - " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n" - " $unknown_fields$);\n" - "}\n"); - } else { - printer->Print(vars, - "total_size += $unknown_fields$.size();\n" - "\n"); - } + format.AddMap(vars); // Handle required fields (if any). We expect all of them to be // present, so emit one conditional that checks for that. If they are all // present then the fast path executes; otherwise the slow path executes. - if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) { + if (num_required_fields_ > 1) { // The fast path works if all required fields are present. const std::vector masks_for_has_bits = RequiredFieldsBitMask(); - printer->Print((string("if (") + - ConditionalToCheckBitmasks(masks_for_has_bits) + - ") { // All required fields are present.\n").c_str()); - printer->Indent(); + format("if ($1$) { // All required fields are present.\n", + ConditionalToCheckBitmasks(masks_for_has_bits)); + format.Indent(); // Oneof fields cannot be required, so optimized_order_ contains all of the // fields that we need to potentially emit. - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; + for (auto field : optimized_order_) { if (!field->is_required()) continue; - PrintFieldComment(printer, field); + PrintFieldComment(format, field); field_generators_.get(field).GenerateByteSize(printer); - printer->Print("\n"); + format("\n"); } - printer->Outdent(); - printer->Print("} else {\n" // the slow path - " total_size += RequiredFieldsByteSizeFallback();\n" - "}\n"); + format.Outdent(); + format( + "} else {\n" // the slow path + " total_size += RequiredFieldsByteSizeFallback();\n" + "}\n"); } else { // num_required_fields_ <= 1: no need to be tricky - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; + for (auto field : optimized_order_) { if (!field->is_required()) continue; - PrintFieldComment(printer, field); - printer->Print("if (has_$name$()) {\n", - "name", FieldName(field)); - printer->Indent(); + PrintFieldComment(format, field); + format("if (_internal_has_$1$()) {\n", FieldName(field)); + format.Indent(); field_generators_.get(field).GenerateByteSize(printer); - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } } - int last_i = -1; - for (int i = 0; i < optimized_order_.size(); ) { - // Detect infinite loops. - GOOGLE_CHECK_NE(i, last_i); - last_i = i; + std::vector> chunks = CollectFields( + optimized_order_, + [&](const FieldDescriptor* a, const FieldDescriptor* b) -> bool { + return a->label() == b->label() && HasByteIndex(a) == HasByteIndex(b); + }); - // Skip required fields. - for (; i < optimized_order_.size() && - optimized_order_[i]->is_required(); i++) { - } - - // Handle repeated fields. - for (; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - if (!field->is_repeated()) { - break; - } + // Remove chunks with required fields. + chunks.erase(std::remove_if(chunks.begin(), chunks.end(), IsRequired), + chunks.end()); - PrintFieldComment(printer, field); - const FieldGenerator& generator = field_generators_.get(field); - generator.GenerateByteSize(printer); - printer->Print("\n"); - } + ColdChunkSkipper cold_skipper(options_, chunks, has_bit_indices_, kColdRatio); + int cached_has_word_index = -1; - // Handle optional (non-repeated/oneof) fields. - // - // These are handled in chunks of 8. The first chunk is - // the non-requireds-non-repeateds-non-unions-non-extensions in - // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7), - // and the second chunk is the same for - // descriptor_->field(8), descriptor_->field(9), ... - // descriptor_->field(15), - // etc. - int last_chunk = -1; - int last_chunk_start = -1; - int last_chunk_end = -1; - uint32 last_chunk_mask = 0; - for (; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - if (field->is_repeated() || field->is_required()) { - break; - } + format( + "$uint32$ cached_has_bits = 0;\n" + "// Prevent compiler warnings about cached_has_bits being unused\n" + "(void) cached_has_bits;\n\n"); - // "index" defines where in the _has_bits_ the field appears. - // "i" is our loop counter within optimized_order_. - int index = HasFieldPresence(descriptor_->file()) ? - has_bit_indices_[field->index()] : 0; - int chunk = index / 8; - - if (last_chunk == -1) { - last_chunk = chunk; - last_chunk_start = i; - } else if (chunk != last_chunk) { - // Emit the fields for this chunk so far. - break; + for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) { + const std::vector& chunk = chunks[chunk_index]; + const bool have_outer_if = + chunk.size() > 1 && HasWordIndex(chunk[0]) != kNoHasbit; + cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", printer); + + if (have_outer_if) { + // Emit an if() that will let us skip the whole chunk if none are set. + uint32 chunk_mask = GenChunkMask(chunk, has_bit_indices_); + std::string chunk_mask_str = + StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8)); + + // Check (up to) 8 has_bits at a time if we have more than one field in + // this chunk. Due to field layout ordering, we may check + // _has_bits_[last_chunk * 8 / 32] multiple times. + GOOGLE_DCHECK_LE(2, popcnt(chunk_mask)); + GOOGLE_DCHECK_GE(8, popcnt(chunk_mask)); + + if (cached_has_word_index != HasWordIndex(chunk.front())) { + cached_has_word_index = HasWordIndex(chunk.front()); + format("cached_has_bits = _has_bits_[$1$];\n", cached_has_word_index); } - - last_chunk_end = i; - last_chunk_mask |= static_cast(1) << (index % 32); + format("if (cached_has_bits & 0x$1$u) {\n", chunk_mask_str); + format.Indent(); } - if (last_chunk != -1) { - GOOGLE_DCHECK_NE(-1, last_chunk_start); - GOOGLE_DCHECK_NE(-1, last_chunk_end); - GOOGLE_DCHECK_NE(0, last_chunk_mask); - - const int count = popcnt(last_chunk_mask); - const bool have_outer_if = HasFieldPresence(descriptor_->file()) && - (last_chunk_start != last_chunk_end); - - if (have_outer_if) { - // Check (up to) 8 has_bits at a time if we have more than one field in - // this chunk. Due to field layout ordering, we may check - // _has_bits_[last_chunk * 8 / 32] multiple times. - GOOGLE_DCHECK_LE(2, count); - GOOGLE_DCHECK_GE(8, count); - - printer->Print( - "if (_has_bits_[$index$ / 32] & $mask$u) {\n", - "index", SimpleItoa(last_chunk * 8), - "mask", SimpleItoa(last_chunk_mask)); - printer->Indent(); - } - - // Go back and emit checks for each of the fields we processed. - for (int j = last_chunk_start; j <= last_chunk_end; j++) { - const FieldDescriptor* field = optimized_order_[j]; - const FieldGenerator& generator = field_generators_.get(field); + // Go back and emit checks for each of the fields we processed. + for (int j = 0; j < chunk.size(); j++) { + const FieldDescriptor* field = chunk[j]; + const FieldGenerator& generator = field_generators_.get(field); + bool have_enclosing_if = false; + bool need_extra_newline = false; - PrintFieldComment(printer, field); + PrintFieldComment(format, field); - bool have_enclosing_if = false; - if (HasFieldPresence(descriptor_->file())) { - printer->Print( - "if (has_$name$()) {\n", - "name", FieldName(field)); - printer->Indent(); - have_enclosing_if = true; - } else { - // Without field presence: field is serialized only if it has a - // non-default value. - have_enclosing_if = EmitFieldNonDefaultCondition( - printer, "this->", field); - } + if (field->is_repeated()) { + // No presence check is required. + need_extra_newline = true; + } else if (HasHasbit(field)) { + PrintPresenceCheck(format, field, has_bit_indices_, printer, + &cached_has_word_index); + have_enclosing_if = true; + } else { + // Without field presence: field is serialized only if it has a + // non-default value. + have_enclosing_if = + EmitFieldNonDefaultCondition(printer, "this->", field); + } - generator.GenerateByteSize(printer); + generator.GenerateByteSize(printer); - if (have_enclosing_if) { - printer->Outdent(); - printer->Print( + if (have_enclosing_if) { + format.Outdent(); + format( "}\n" "\n"); - } } - - if (have_outer_if) { - printer->Outdent(); - printer->Print("}\n"); + if (need_extra_newline) { + format("\n"); } } + + if (have_outer_if) { + format.Outdent(); + format("}\n"); + } + + if (cold_skipper.OnEndChunk(chunk_index, printer)) { + // Reset here as it may have been updated in just closed if statement. + cached_has_word_index = -1; + } } // Fields inside a oneof don't use _has_bits_ so we count them in a separate // pass. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "switch ($oneofname$_case()) {\n", - "oneofname", descriptor_->oneof_decl(i)->name()); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - PrintFieldComment(printer, field); - printer->Print( - "case k$field_name$: {\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); - field_generators_.get(field).GenerateByteSize(printer); - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); + for (auto oneof : OneOfRange(descriptor_)) { + format("switch ($1$_case()) {\n", oneof->name()); + format.Indent(); + for (auto field : FieldRange(oneof)) { + PrintFieldComment(format, field); + format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); + format.Indent(); + if (!IsFieldStripped(field, options_)) { + field_generators_.get(field).GenerateByteSize(printer); + } + format("break;\n"); + format.Outdent(); + format("}\n"); } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" + format( + "case $1$_NOT_SET: {\n" " break;\n" "}\n", - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( - "}\n"); + ToUpper(oneof->name())); + format.Outdent(); + format("}\n"); } if (num_weak_fields_) { // TagSize + MessageSize - printer->Print("total_size += _weak_field_map_.ByteSizeLong();\n"); - } - - // We update _cached_size_ even though this is a const method. In theory, - // this is not thread-compatible, because concurrent writes have undefined - // results. In practice, since any concurrent writes will be writing the - // exact same value, it works on all common processors. In a future version - // of C++, _cached_size_ should be made into an atomic. - printer->Print( - "int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);\n" - "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" - "_cached_size_ = cached_size;\n" - "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" - "return total_size;\n"); - - printer->Outdent(); - printer->Print("}\n"); + format("total_size += _weak_field_map_.ByteSizeLong();\n"); + } + + format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n"); + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + // We go out of our way to put the computation of the uncommon path of + // unknown fields in tail position. This allows for better code generation + // of this function for simple protos. + format( + " return ::$proto_ns$::internal::ComputeUnknownFieldsSize(\n" + " _internal_metadata_, total_size, &_cached_size_);\n"); + } else { + format(" total_size += $unknown_fields$.size();\n"); + } + format("}\n"); + + // We update _cached_size_ even though this is a const method. Because + // const methods might be called concurrently this needs to be atomic + // operations or the program is undefined. In practice, since any concurrent + // writes will be writing the exact same value, normal writes will work on + // all common processors. We use a dedicated wrapper class to abstract away + // the underlying atomic. This makes it easier on platforms where even relaxed + // memory order might have perf impact to replace it with ordinary loads and + // stores. + format( + "int cached_size = ::$proto_ns$::internal::ToCachedSize(total_size);\n" + "SetCachedSize(cached_size);\n" + "return total_size;\n"); + + format.Outdent(); + format("}\n"); } -void MessageGenerator:: -GenerateIsInitialized(io::Printer* printer) { - printer->Print( - "bool $classname$::IsInitialized() const {\n", - "classname", classname_); - printer->Indent(); +void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { + Formatter format(printer, variables_); + format("bool $classname$::IsInitialized() const {\n"); + format.Indent(); if (descriptor_->extension_range_count() > 0) { - printer->Print( - "if (!_extensions_.IsInitialized()) {\n" - " return false;\n" - "}\n\n"); + format( + "if (!_extensions_.IsInitialized()) {\n" + " return false;\n" + "}\n\n"); } - if (HasFieldPresence(descriptor_->file())) { - // Check that all required fields in this message are set. We can do this - // most efficiently by checking 32 "has bits" at a time. - const std::vector masks = RequiredFieldsBitMask(); - - for (int i = 0; i < masks.size(); i++) { - uint32 mask = masks[i]; - if (mask == 0) { - continue; - } - - // TODO(ckennelly): Consider doing something similar to ByteSizeLong(), - // where we check all of the required fields in a single branch (assuming - // that we aren't going to benefit from early termination). - printer->Print( - "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n", - "i", SimpleItoa(i), - "mask", StrCat(strings::Hex(mask, strings::ZERO_PAD_8))); - } + if (num_required_fields_ > 0) { + format( + "if (_Internal::MissingRequiredFields(_has_bits_))" + " return false;\n"); } // Now check that all non-oneof embedded messages are initialized. - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; + for (auto field : optimized_order_) { // TODO(ckennelly): Push this down into a generator? if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && !ShouldIgnoreRequiredFieldCheck(field, options_) && scc_analyzer_->HasRequiredFields(field->message_type())) { if (field->is_repeated()) { - printer->Print( - "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))" - " return false;\n", - "name", FieldName(field)); + if (IsImplicitWeakField(field, options_, scc_analyzer_)) { + format( + "if " + "(!::$proto_ns$::internal::AllAreInitializedWeak($1$_.weak)" + ")" + " return false;\n", + FieldName(field)); + } else { + format( + "if (!::$proto_ns$::internal::AllAreInitialized($1$_))" + " return false;\n", + FieldName(field)); + } } else if (field->options().weak()) { continue; } else { - GOOGLE_CHECK(!field->containing_oneof()); - printer->Print( - "if (has_$name$()) {\n" - " if (!this->$name$_->IsInitialized()) return false;\n" + GOOGLE_CHECK(!field->real_containing_oneof()); + format( + "if (_internal_has_$1$()) {\n" + " if (!$1$_->IsInitialized()) return false;\n" "}\n", - "name", FieldName(field)); + FieldName(field)); } } } if (num_weak_fields_) { // For Weak fields. - printer->Print("if (!_weak_field_map_.IsInitialized()) return false;\n"); + format("if (!_weak_field_map_.IsInitialized()) return false;\n"); } // Go through the oneof fields, emitting a switch if any might have required // fields. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - const OneofDescriptor* oneof = descriptor_->oneof_decl(i); - + for (auto oneof : OneOfRange(descriptor_)) { bool has_required_fields = false; - for (int j = 0; j < oneof->field_count(); j++) { - const FieldDescriptor* field = oneof->field(j); - + for (auto field : FieldRange(oneof)) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && !ShouldIgnoreRequiredFieldCheck(field, options_) && scc_analyzer_->HasRequiredFields(field->message_type())) { @@ -4650,53 +3998,45 @@ GenerateIsInitialized(io::Printer* printer) { continue; } - printer->Print( - "switch ($oneofname$_case()) {\n", - "oneofname", oneof->name()); - printer->Indent(); - for (int j = 0; j < oneof->field_count(); j++) { - const FieldDescriptor* field = oneof->field(j); - printer->Print( - "case k$field_name$: {\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); + format("switch ($1$_case()) {\n", oneof->name()); + format.Indent(); + for (auto field : FieldRange(oneof)) { + format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); + format.Indent(); - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + if (!IsFieldStripped(field, options_) && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && !ShouldIgnoreRequiredFieldCheck(field, options_) && scc_analyzer_->HasRequiredFields(field->message_type())) { - GOOGLE_CHECK(!(field->options().weak() || !field->containing_oneof())); + GOOGLE_CHECK(!(field->options().weak() || !field->real_containing_oneof())); if (field->options().weak()) { // Just skip. } else { - printer->Print( - "if (has_$name$()) {\n" - " if (!this->$name$().IsInitialized()) return false;\n" - "}\n", - "name", FieldName(field)); + format( + "if (has_$1$()) {\n" + " if (!this->$1$().IsInitialized()) return false;\n" + "}\n", + FieldName(field)); } } - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); + format("break;\n"); + format.Outdent(); + format("}\n"); } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" + format( + "case $1$_NOT_SET: {\n" " break;\n" "}\n", - "cap_oneof_name", ToUpper(oneof->name())); - printer->Outdent(); - printer->Print( - "}\n"); + format.Outdent(); + format("}\n"); } - printer->Outdent(); - printer->Print( - " return true;\n" - "}\n"); + format.Outdent(); + format( + " return true;\n" + "}\n"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index 352069eb44651..4e3f4b9822acb 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -36,95 +36,73 @@ #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include #include #include +#include #include namespace google { namespace protobuf { - namespace io { - class Printer; // printer.h - } +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace cpp { -class EnumGenerator; // enum.h -class ExtensionGenerator; // extension.h +class EnumGenerator; // enum.h +class ExtensionGenerator; // extension.h class MessageGenerator { public: // See generator.cc for the meaning of dllexport_decl. - MessageGenerator(const Descriptor* descriptor, const Options& options, - SCCAnalyzer* scc_analyzer); + MessageGenerator(const Descriptor* descriptor, + const std::map& vars, + int index_in_file_messages, const Options& options, + MessageSCCAnalyzer* scc_analyzer); ~MessageGenerator(); - // Appends the pre-order walk of the nested generators to list. - void Flatten(std::vector* list); // Append the two types of nested generators to the corresponding vector. - void AddGenerators(std::vector* enum_generators, - std::vector* extension_generators); - - // Header stuff. - - // Return names for forward declarations of this class and all its nested - // types. A given key in {class,enum}_names will map from a class name to the - // descriptor that was responsible for its inclusion in the map. This can be - // used to associate the descriptor with the code generated for it. - void FillMessageForwardDeclarations( - std::map* class_names); + void AddGenerators( + std::vector>* enum_generators, + std::vector>* extension_generators); // Generate definitions for this class and all its nested types. void GenerateClassDefinition(io::Printer* printer); // Generate definitions of inline methods (placed at the end of the header // file). - void GenerateInlineMethods(io::Printer* printer, bool is_inline); - - // Dependent methods are always inline. - void GenerateDependentInlineMethods(io::Printer* printer); + void GenerateInlineMethods(io::Printer* printer); // Source file stuff. - // Generate extra fields - void GenerateExtraDefaultFields(io::Printer* printer); - - // Generates code that allocates the message's default instance. - void GenerateDefaultInstanceAllocator(io::Printer* printer); - - // Generates code that initializes the message's default instance. This - // is separate from allocating because all default instances must be - // allocated before any can be initialized. - void GenerateDefaultInstanceInitializer(io::Printer* printer); - // Generate all non-inline methods for this class. void GenerateClassMethods(io::Printer* printer); + // Generate source file code that should go outside any namespace. + void GenerateSourceInProto2Namespace(io::Printer* printer); + private: // Generate declarations and definitions of accessors for fields. - void GenerateDependentBaseClassDefinition(io::Printer* printer); - void GenerateDependentFieldAccessorDeclarations(io::Printer* printer); void GenerateFieldAccessorDeclarations(io::Printer* printer); - void GenerateDependentFieldAccessorDefinitions(io::Printer* printer); - void GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline); + void GenerateFieldAccessorDefinitions(io::Printer* printer); // Generate the table-driven parsing array. Returns the number of entries // generated. size_t GenerateParseOffsets(io::Printer* printer); size_t GenerateParseAuxTable(io::Printer* printer); - // Generates a ParseTable entry. Returns whether the proto uses table-driven - // parsing. + // Generates a ParseTable entry. Returns whether the proto uses + // table-driven parsing. bool GenerateParseTable(io::Printer* printer, size_t offset, size_t aux_offset); - // Generate the field offsets array. Returns the a pair of the total numer + // Generate the field offsets array. Returns the a pair of the total number // of entries generated and the index of the first has_bit entry. std::pair GenerateOffsets(io::Printer* printer); void GenerateSchema(io::Printer* printer, int offset, int has_offset); @@ -146,12 +124,9 @@ class MessageGenerator { // Generate the arena-specific destructor code. void GenerateArenaDestructorCode(io::Printer* printer); - // Helper for GenerateClear and others. Optionally emits a condition that - // assumes the existence of the cached_has_bits variable, and returns true if - // the condition was printed. - bool MaybeGenerateOptionalFieldCondition(io::Printer* printer, - const FieldDescriptor* field, - int expected_has_bits_index); + // Generate the constexpr constructor for constant initialization of the + // default instance. + void GenerateConstexprConstructor(io::Printer* printer); // Generate standard Message methods. void GenerateClear(io::Printer* printer); @@ -159,10 +134,11 @@ class MessageGenerator { void GenerateMergeFromCodedStream(io::Printer* printer); void GenerateSerializeWithCachedSizes(io::Printer* printer); void GenerateSerializeWithCachedSizesToArray(io::Printer* printer); - void GenerateSerializeWithCachedSizesBody(io::Printer* printer, - bool to_array); + void GenerateSerializeWithCachedSizesBody(io::Printer* printer); + void GenerateSerializeWithCachedSizesBodyShuffled(io::Printer* printer); void GenerateByteSize(io::Printer* printer); void GenerateMergeFrom(io::Printer* printer); + void GenerateClassSpecificMergeFrom(io::Printer* printer); void GenerateCopyFrom(io::Printer* printer); void GenerateSwap(io::Printer* printer); void GenerateIsInitialized(io::Printer* printer); @@ -174,62 +150,62 @@ class MessageGenerator { // for cached_has_bit_index >= 0 void GenerateSerializeOneField(io::Printer* printer, const FieldDescriptor* field, - bool unbounded, int cached_has_bits_index); // Generate a switch statement to serialize 2+ fields from the same oneof. // Or, if fields.size() == 1, just call GenerateSerializeOneField(). void GenerateSerializeOneofFields( - io::Printer* printer, const std::vector& fields, - bool to_array); + io::Printer* printer, const std::vector& fields); void GenerateSerializeOneExtensionRange( - io::Printer* printer, const Descriptor::ExtensionRange* range, - bool unbounded); + io::Printer* printer, const Descriptor::ExtensionRange* range); // Generates has_foo() functions and variables for singular field has-bits. void GenerateSingularFieldHasBits(const FieldDescriptor* field, - std::map vars, - io::Printer* printer); + Formatter format); // Generates has_foo() functions and variables for oneof field has-bits. - void GenerateOneofHasBits(io::Printer* printer, bool is_inline); + void GenerateOneofHasBits(io::Printer* printer); // Generates has_foo_bar() functions for oneof members. void GenerateOneofMemberHasBits(const FieldDescriptor* field, - const std::map& vars, - io::Printer* printer); + const Formatter& format); // Generates the clear_foo() method for a field. - void GenerateFieldClear(const FieldDescriptor* field, - const std::map& vars, - io::Printer* printer); + void GenerateFieldClear(const FieldDescriptor* field, bool is_inline, + Formatter format); void GenerateConstructorBody(io::Printer* printer, std::vector already_processed, bool copy_constructor) const; size_t HasBitsSize() const; + int HasBitIndex(const FieldDescriptor* a) const; + int HasByteIndex(const FieldDescriptor* a) const; + int HasWordIndex(const FieldDescriptor* a) const; + bool SameHasByte(const FieldDescriptor* a, const FieldDescriptor* b) const; std::vector RequiredFieldsBitMask() const; const Descriptor* descriptor_; - string classname_; + int index_in_file_messages_; + std::string classname_; Options options_; FieldGeneratorMap field_generators_; - // optimized_order_ is the order we layout the message's fields in the class. - // This is reused to initialize the fields in-order for cache efficiency. + // optimized_order_ is the order we layout the message's fields in the + // class. This is reused to initialize the fields in-order for cache + // efficiency. // // optimized_order_ excludes oneof fields and weak fields. - std::vector optimized_order_; + std::vector optimized_order_; std::vector has_bit_indices_; int max_has_bit_index_; - google::protobuf::scoped_array > nested_generators_; - google::protobuf::scoped_array > enum_generators_; - google::protobuf::scoped_array > extension_generators_; + std::vector enum_generators_; + std::vector extension_generators_; int num_required_fields_; - bool use_dependent_base_; int num_weak_fields_; // table_driven_ indicates the generated message uses table-driven parsing. bool table_driven_; - int index_in_file_messages_; + std::unique_ptr message_layout_helper_; - SCCAnalyzer* scc_analyzer_; + MessageSCCAnalyzer* scc_analyzer_; + + std::map variables_; friend class FileGenerator; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); @@ -238,6 +214,6 @@ class MessageGenerator { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index da4c3950343be..7bad24ca84f7c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -44,37 +44,38 @@ namespace compiler { namespace cpp { namespace { +std::string ReinterpretCast(const std::string& type, + const std::string& expression, + bool implicit_weak_field) { + if (implicit_weak_field) { + return "reinterpret_cast< " + type + " >(" + expression + ")"; + } else { + return expression; + } +} void SetMessageVariables(const FieldDescriptor* descriptor, - std::map* variables, - const Options& options) { + const Options& options, bool implicit_weak, + std::map* variables) { SetCommonFieldVariables(descriptor, variables, options); - (*variables)["type"] = FieldMessageTypeName(descriptor); + (*variables)["type"] = FieldMessageTypeName(descriptor, options); + (*variables)["casted_member"] = ReinterpretCast( + (*variables)["type"] + "*", (*variables)["name"] + "_", implicit_weak); (*variables)["type_default_instance"] = - DefaultInstanceName(descriptor->message_type()); - if (descriptor->options().weak() || !descriptor->containing_oneof()) { - (*variables)["non_null_ptr_to_name"] = - StrCat("this->", (*variables)["name"], "_"); - } - (*variables)["stream_writer"] = - (*variables)["declared_type"] + - (HasFastArraySerialization(descriptor->message_type()->file(), options) - ? "MaybeToArray" - : ""); + QualifiedDefaultInstanceName(descriptor->message_type(), options); + (*variables)["type_default_instance_ptr"] = + QualifiedDefaultInstancePtr(descriptor->message_type(), options); + (*variables)["type_reference_function"] = + implicit_weak ? (" ::" + (*variables)["proto_ns"] + + "::internal::StrongReference(reinterpret_cast(\n" + + (*variables)["type_default_instance"] + "));\n") + : ""; // NOTE: Escaped here to unblock proto1->proto2 migration. // TODO(liujisi): Extend this to apply for other conflicting methods. (*variables)["release_name"] = - SafeFunctionName(descriptor->containing_type(), - descriptor, "release_"); + SafeFunctionName(descriptor->containing_type(), descriptor, "release_"); (*variables)["full_name"] = descriptor->full_name(); - if (options.proto_h && IsFieldDependent(descriptor)) { - (*variables)["dependent_type"] = "T::" + DependentTypeName(descriptor); - (*variables)["dependent_typename"] = - "typename T::" + DependentTypeName(descriptor); - } else { - (*variables)["dependent_type"] = FieldMessageTypeName(descriptor); - (*variables)["dependent_typename"] = FieldMessageTypeName(descriptor); - } } } // namespace @@ -82,144 +83,106 @@ void SetMessageVariables(const FieldDescriptor* descriptor, // =================================================================== MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : FieldGenerator(options), - descriptor_(descriptor), - dependent_field_(options.proto_h && IsFieldDependent(descriptor)) { - SetMessageVariables(descriptor, &variables_, options); + const Options& options, + MessageSCCAnalyzer* scc_analyzer) + : FieldGenerator(descriptor, options), + implicit_weak_field_( + IsImplicitWeakField(descriptor, options, scc_analyzer)) { + SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_); } MessageFieldGenerator::~MessageFieldGenerator() {} -void MessageFieldGenerator:: -GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, "$type$* $name$_;\n"); -} - -void MessageFieldGenerator:: -GenerateGetterDeclaration(io::Printer* printer) const { - printer->Print(variables_, - "$deprecated_attr$const $type$& $name$() const;\n"); - printer->Annotate("name", descriptor_); +void MessageFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const { + Formatter format(printer, variables_); + if (implicit_weak_field_) { + format("::$proto_ns$::MessageLite* $name$_;\n"); + } else { + format("$type$* $name$_;\n"); + } } -void MessageFieldGenerator:: -GenerateDependentAccessorDeclarations(io::Printer* printer) const { - if (!dependent_field_) { +void MessageFieldGenerator::GenerateAccessorDeclarations( + io::Printer* printer) const { + Formatter format(printer, variables_); + if (IsFieldStripped(descriptor_, options_)) { + format( + "$deprecated_attr$const $type$& ${1$$name$$}$() const { " + "__builtin_trap(); }\n" + "$deprecated_attr$$type$* ${1$$release_name$$}$() { " + "__builtin_trap(); }\n" + "$deprecated_attr$$type$* ${1$mutable_$name$$}$() { " + "__builtin_trap(); }\n" + "$deprecated_attr$void ${1$set_allocated_$name$$}$" + "($type$* $name$) { __builtin_trap(); }\n" + "$deprecated_attr$void " + "${1$unsafe_arena_set_allocated_$name$$}$(\n" + " $type$* $name$) { __builtin_trap(); }\n" + "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$() { " + "__builtin_trap(); }\n", + descriptor_); return; } - // Arena manipulation code is out-of-line in the derived message class. - printer->Print(variables_, - "$deprecated_attr$$type$* ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, "$deprecated_attr$$type$* $release_name$();\n"); - printer->Annotate("release_name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$set_allocated_$name$$}$" - "($type$* $name$);\n"); - printer->Annotate("{", "}", descriptor_); + format( + "$deprecated_attr$const $type$& ${1$$name$$}$() const;\n" + "$deprecated_attr$$type$* ${1$$release_name$$}$();\n" + "$deprecated_attr$$type$* ${1$mutable_$name$$}$();\n" + "$deprecated_attr$void ${1$set_allocated_$name$$}$" + "($type$* $name$);\n", + descriptor_); + if (!IsFieldStripped(descriptor_, options_)) { + format( + "private:\n" + "const $type$& ${1$_internal_$name$$}$() const;\n" + "$type$* ${1$_internal_mutable_$name$$}$();\n" + "public:\n", + descriptor_); + } + format( + "$deprecated_attr$void " + "${1$unsafe_arena_set_allocated_$name$$}$(\n" + " $type$* $name$);\n" + "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$();\n", + descriptor_); } -void MessageFieldGenerator:: -GenerateAccessorDeclarations(io::Printer* printer) const { - if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "private:\n" - "void _slow_mutable_$name$();\n"); - if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables_, - "void _slow_set_allocated_$name$(\n" - " ::google::protobuf::Arena* message_arena, $type$** $name$);\n"); - } - printer->Print(variables_, - "$type$* _slow_$release_name$();\n" - "public:\n"); - } - GenerateGetterDeclaration(printer); - if (!dependent_field_) { - printer->Print(variables_, - "$deprecated_attr$$type$* ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, "$deprecated_attr$$type$* $release_name$();\n"); - printer->Annotate("release_name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$set_allocated_$name$$}$" - "($type$* $name$);\n"); - printer->Annotate("{", "}", descriptor_); - } - if (SupportsArenas(descriptor_)) { - printer->Print( - variables_, - "$deprecated_attr$$type$* ${$unsafe_arena_release_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void " - "${$unsafe_arena_set_allocated_$name$$}$(\n" - " $type$* $name$);\n"); - printer->Annotate("{", "}", descriptor_); - } +void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( + io::Printer* printer) const { } -void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( +void MessageFieldGenerator::GenerateInlineAccessorDefinitions( io::Printer* printer) const { - if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "void $classname$::_slow_mutable_$name$() {\n"); - if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables_, - " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n" - " GetArenaNoVirtual());\n"); - } else { - printer->Print(variables_, - " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n" - " GetArenaNoVirtual());\n"); - } - printer->Print(variables_, - "}\n" - "$type$* $classname$::_slow_$release_name$() {\n" - " if ($name$_ == NULL) {\n" - " return NULL;\n" - " } else {\n" - " $type$* temp = new $type$(*$name$_);\n" - " $name$_ = NULL;\n" - " return temp;\n" - " }\n" + Formatter format(printer, variables_); + format( + "inline const $type$& $classname$::_internal_$name$() const {\n" + "$type_reference_function$" + " const $type$* p = $casted_member$;\n" + " return p != nullptr ? *p : reinterpret_cast(\n" + " $type_default_instance$);\n" "}\n" - "$type$* $classname$::unsafe_arena_release_$name$() {\n" - " // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n" - " $clear_hasbit$\n" - " $type$* temp = $name$_;\n" - " $name$_ = NULL;\n" - " return temp;\n" + "inline const $type$& $classname$::$name$() const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return _internal_$name$();\n" "}\n"); - if (SupportsArenas(descriptor_->message_type())) { - // NOTE: the same logic is mirrored in weak_message_field.cc. Any - // arena-related semantics changes should be made in both places. - printer->Print(variables_, - "void $classname$::_slow_set_allocated_$name$(\n" - " ::google::protobuf::Arena* message_arena, $type$** $name$) {\n" - " if (message_arena != NULL && \n" - " ::google::protobuf::Arena::GetArena(*$name$) == NULL) {\n" - " message_arena->Own(*$name$);\n" - " } else if (message_arena !=\n" - " ::google::protobuf::Arena::GetArena(*$name$)) {\n" - " $type$* new_$name$ = \n" - " ::google::protobuf::Arena::CreateMessage< $type$ >(\n" - " message_arena);\n" - " new_$name$->CopyFrom(**$name$);\n" - " *$name$ = new_$name$;\n" - " }\n" - "}\n"); - } - printer->Print(variables_, - "void $classname$::unsafe_arena_set_allocated_$name$(\n" + + format( + "inline void $classname$::unsafe_arena_set_allocated_$name$(\n" " $type$* $name$) {\n" + "$annotate_accessor$" // If we're not on an arena, free whatever we were holding before. // (If we are on arena, we can just forget the earlier pointer.) - " if (GetArenaNoVirtual() == NULL) {\n" - " delete $name$_;\n" - " }\n" - " $name$_ = $name$;\n" + " if (GetArena() == nullptr) {\n" + " delete reinterpret_cast<::$proto_ns$::MessageLite*>($name$_);\n" + " }\n"); + if (implicit_weak_field_) { + format( + " $name$_ = " + "reinterpret_cast<::$proto_ns$::MessageLite*>($name$);\n"); + } else { + format(" $name$_ = $name$;\n"); + } + format( " if ($name$) {\n" " $set_hasbit$\n" " } else {\n" @@ -228,657 +191,433 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( " // @@protoc_insertion_point(field_unsafe_arena_set_allocated" ":$full_name$)\n" "}\n"); - } -} - -void MessageFieldGenerator:: -GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { - if (!dependent_field_) { - return; - } - - std::map variables(variables_); - // For the CRTP base class, all mutation methods are dependent, and so - // they must be in the header. - variables["dependent_classname"] = - DependentBaseClassTemplateName(descriptor_->containing_type()) + ""; - variables["this_message"] = DependentBaseDownCast(); - if (!variables["set_hasbit"].empty()) { - variables["set_hasbit"] = - variables["this_message"] + variables["set_hasbit"]; - } - if (!variables["clear_hasbit"].empty()) { - variables["clear_hasbit"] = - variables["this_message"] + variables["clear_hasbit"]; - } - - if (SupportsArenas(descriptor_)) { - printer->Print(variables, - "template \n" - "inline $type$* $dependent_classname$::mutable_$name$() {\n" - " $set_hasbit$\n" - " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" - " if ($name$_ == NULL) {\n" - " $this_message$_slow_mutable_$name$();\n" - " }\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $name$_;\n" - "}\n" - "template \n" - "inline $type$* $dependent_classname$::$release_name$() {\n" - " // @@protoc_insertion_point(field_release:$full_name$)\n" - " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" + format( + "inline $type$* $classname$::$release_name$() {\n" + "$type_reference_function$" " $clear_hasbit$\n" - " if ($this_message$GetArenaNoVirtual() != NULL) {\n" - " return $this_message$_slow_$release_name$();\n" - " } else {\n" - " $dependent_typename$* temp = $name$_;\n" - " $name$_ = NULL;\n" - " return temp;\n" - " }\n" - "}\n" - "template \n" - "inline void $dependent_classname$::" - "set_allocated_$name$($type$* $name$) {\n" - " ::google::protobuf::Arena* message_arena = $this_message$GetArenaNoVirtual();\n" - " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" - " if (message_arena == NULL) {\n" - " delete $name$_;\n" - " }\n" - " if ($name$ != NULL) {\n"); - if (SupportsArenas(descriptor_->message_type())) { - // If we're on an arena and the incoming message is not, simply Own() it - // rather than copy to the arena -- either way we need a heap dealloc, - // so we might as well defer it. Otherwise, if incoming message is on a - // different ownership domain (specific arena, or the heap) than we are, - // copy to our arena (or heap, as the case may be). - printer->Print(variables, - " $this_message$_slow_set_allocated_$name$(message_arena, " - "&$name$);\n"); - } else { - printer->Print(variables, - " if (message_arena != NULL) {\n" - " message_arena->Own($name$);\n" - " }\n"); - } - printer->Print(variables, + " $type$* temp = $casted_member$;\n" + " $name$_ = nullptr;\n" + " if (GetArena() != nullptr) {\n" + " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n" " }\n" - " $name$_ = $name$;\n" - " if ($name$) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" - " }\n" - // TODO(dlj): move insertion points to message class. - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n"); - } else { - printer->Print(variables, - "template \n" - "inline $type$* $dependent_classname$::mutable_$name$() {\n" - " $set_hasbit$\n" - " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" - " if ($name$_ == NULL) {\n" - " $name$_ = new $dependent_typename$;\n" - " }\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $name$_;\n" + " return temp;\n" "}\n" - "template \n" - "inline $type$* $dependent_classname$::$release_name$() {\n" + "inline $type$* $classname$::unsafe_arena_release_$name$() {\n" + "$annotate_accessor$" " // @@protoc_insertion_point(field_release:$full_name$)\n" + "$type_reference_function$" " $clear_hasbit$\n" - " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" - " $dependent_typename$* temp = $name$_;\n" - " $name$_ = NULL;\n" + " $type$* temp = $casted_member$;\n" + " $name$_ = nullptr;\n" " return temp;\n" - "}\n" - "template \n" - "inline void $dependent_classname$::" - "set_allocated_$name$($type$* $name$) {\n" - " $dependent_typename$*& $name$_ = $this_message$$name$_;\n" - " delete $name$_;\n"); - - if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables, - " if ($name$ != NULL && static_cast< $dependent_typename$* >($name$)" - "->GetArena() != NULL) {\n" - " $dependent_typename$* new_$name$ = new $dependent_typename$;\n" - " new_$name$->CopyFrom(*$name$);\n" - " $name$ = new_$name$;\n" - " }\n"); - } - - printer->Print(variables, - " $name$_ = $name$;\n" - " if ($name$) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" - " }\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n"); - } -} -void MessageFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const { - std::map variables(variables_); - variables["inline"] = is_inline ? "inline " : ""; - printer->Print(variables, - "$inline$const $type$& $classname$::$name$() const {\n" - " const $type$* p = $name$_;\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return p != NULL ? *p : *reinterpret_cast(\n" - " &$type_default_instance$);\n" - "}\n"); - - if (dependent_field_) return; - - if (SupportsArenas(descriptor_)) { - printer->Print(variables, - "$inline$" - "$type$* $classname$::mutable_$name$() {\n" + format( + "inline $type$* $classname$::_internal_mutable_$name$() {\n" + "$type_reference_function$" " $set_hasbit$\n" - " if ($name$_ == NULL) {\n" - " _slow_mutable_$name$();\n" - " }\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $name$_;\n" - "}\n" - "$inline$" - "$type$* $classname$::$release_name$() {\n" - " // @@protoc_insertion_point(field_release:$full_name$)\n" - " $clear_hasbit$\n" - " if (GetArenaNoVirtual() != NULL) {\n" - " return _slow_$release_name$();\n" - " } else {\n" - " $type$* temp = $name$_;\n" - " $name$_ = NULL;\n" - " return temp;\n" + " if ($name$_ == nullptr) {\n" + " auto* p = CreateMaybeMessage<$type$>(GetArena());\n"); + if (implicit_weak_field_) { + format(" $name$_ = reinterpret_cast<::$proto_ns$::MessageLite*>(p);\n"); + } else { + format(" $name$_ = p;\n"); + } + format( " }\n" + " return $casted_member$;\n" "}\n" - "$inline$ " - "void $classname$::set_allocated_$name$($type$* $name$) {\n" - " ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n" - " if (message_arena == NULL) {\n" - " delete $name$_;\n" - " }\n" - " if ($name$ != NULL) {\n"); - if (SupportsArenas(descriptor_->message_type())) { - // If we're on an arena and the incoming message is not, simply Own() it - // rather than copy to the arena -- either way we need a heap dealloc, - // so we might as well defer it. Otherwise, if incoming message is on a - // different ownership domain (specific arena, or the heap) than we are, - // copy to our arena (or heap, as the case may be). - printer->Print(variables, - " _slow_set_allocated_$name$(message_arena, &$name$);\n"); - } else { - printer->Print(variables, - " if (message_arena != NULL) {\n" - " message_arena->Own($name$);\n" - " }\n"); - } - printer->Print(variables, - " }\n" - " $name$_ = $name$;\n" - " if ($name$) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" - " }\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + "inline $type$* $classname$::mutable_$name$() {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + " return _internal_mutable_$name$();\n" "}\n"); + + // We handle the most common case inline, and delegate less common cases to + // the slow fallback function. + format( + "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" + "$annotate_accessor$" + " ::$proto_ns$::Arena* message_arena = GetArena();\n"); + format(" if (message_arena == nullptr) {\n"); + if (IsCrossFileMessage(descriptor_)) { + format( + " delete reinterpret_cast< ::$proto_ns$::MessageLite*>($name$_);\n"); } else { - printer->Print(variables, - "$inline$" - "$type$* $classname$::mutable_$name$() {\n" - " $set_hasbit$\n" - " if ($name$_ == NULL) {\n" - " $name$_ = new $type$;\n" + format(" delete $name$_;\n"); + } + format( " }\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $name$_;\n" - "}\n" - "$inline$" - "$type$* $classname$::$release_name$() {\n" - " // @@protoc_insertion_point(field_release:$full_name$)\n" - " $clear_hasbit$\n" - " $type$* temp = $name$_;\n" - " $name$_ = NULL;\n" - " return temp;\n" - "}\n" - "$inline$" - "void $classname$::set_allocated_$name$($type$* $name$) {\n" - " delete $name$_;\n"); - - if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables, - " if ($name$ != NULL && $name$->GetArena() != NULL) {\n" - " $type$* new_$name$ = new $type$;\n" - " new_$name$->CopyFrom(*$name$);\n" - " $name$ = new_$name$;\n" - " }\n"); - } - - printer->Print(variables, - " $name$_ = $name$;\n" - " if ($name$) {\n" + " if ($name$) {\n"); + if (IsCrossFileMessage(descriptor_)) { + // We have to read the arena through the virtual method, because the type + // isn't defined in this file. + format( + " ::$proto_ns$::Arena* submessage_arena =\n" + " " + "reinterpret_cast<::$proto_ns$::MessageLite*>($name$)->GetArena();\n"); + } else { + format( + " ::$proto_ns$::Arena* submessage_arena =\n" + " ::$proto_ns$::Arena::GetArena($name$);\n"); + } + format( + " if (message_arena != submessage_arena) {\n" + " $name$ = ::$proto_ns$::internal::GetOwnedMessage(\n" + " message_arena, $name$, submessage_arena);\n" + " }\n" " $set_hasbit$\n" " } else {\n" " $clear_hasbit$\n" - " }\n" + " }\n"); + if (implicit_weak_field_) { + format(" $name$_ = reinterpret_cast($name$);\n"); + } else { + format(" $name$_ = $name$;\n"); + } + format( " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n"); +} + +void MessageFieldGenerator::GenerateInternalAccessorDeclarations( + io::Printer* printer) const { + Formatter format(printer, variables_); + if (implicit_weak_field_) { + format( + "static const ::$proto_ns$::MessageLite& $name$(" + "const $classname$* msg);\n" + "static ::$proto_ns$::MessageLite* mutable_$name$(" + "$classname$* msg);\n"); + } else { + format("static const $type$& $name$(const $classname$* msg);\n"); + } +} + +void MessageFieldGenerator::GenerateInternalAccessorDefinitions( + io::Printer* printer) const { + // In theory, these accessors could be inline in _Internal. However, in + // practice, the linker is then not able to throw them out making implicit + // weak dependencies not work at all. + Formatter format(printer, variables_); + if (implicit_weak_field_) { + // These private accessors are used by MergeFrom and + // MergePartialFromCodedStream, and their purpose is to provide access to + // the field without creating a strong dependency on the message type. + format( + "const ::$proto_ns$::MessageLite& $classname$::_Internal::$name$(\n" + " const $classname$* msg) {\n" + " if (msg->$name$_ != nullptr) {\n" + " return *msg->$name$_;\n" + " } else if ($type_default_instance_ptr$ != nullptr) {\n" + " return *reinterpret_cast(\n" + " $type_default_instance_ptr$);\n" + " } else {\n" + " return " + "*::$proto_ns$::internal::ImplicitWeakMessage::default_instance();\n" + " }\n" + "}\n"); + format( + "::$proto_ns$::MessageLite*\n" + "$classname$::_Internal::mutable_$name$($classname$* msg) {\n"); + if (HasFieldPresence(descriptor_->file())) { + format(" msg->$set_hasbit$\n"); + } + format( + " if (msg->$name$_ == nullptr) {\n" + " if ($type_default_instance_ptr$ == nullptr) {\n" + " msg->$name$_ = ::$proto_ns$::Arena::CreateMessage<\n" + " ::$proto_ns$::internal::ImplicitWeakMessage>(\n" + " msg->GetArena());\n" + " } else {\n" + " msg->$name$_ = reinterpret_cast(\n" + " $type_default_instance_ptr$)->New(msg->GetArena());\n" + " }\n" + " }\n" + " return msg->$name$_;\n" + "}\n"); + } else { + // This inline accessor directly returns member field and is used in + // Serialize such that AFDO profile correctly captures access information to + // message fields under serialize. + format( + "const $type$&\n" + "$classname$::_Internal::$name$(const $classname$* msg) {\n" + " return *msg->$field_member$;\n" + "}\n"); } } -void MessageFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - std::map variables(variables_); - variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : ""; +void MessageFieldGenerator::GenerateClearingCode(io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); + + Formatter format(printer, variables_); if (!HasFieldPresence(descriptor_->file())) { // If we don't have has-bits, message presence is indicated only by ptr != // NULL. Thus on clear, we need to delete the object. - printer->Print(variables, - "if ($this_message$GetArenaNoVirtual() == NULL && " - "$this_message$$name$_ != NULL) delete $this_message$$name$_;\n" - "$this_message$$name$_ = NULL;\n"); + format( + "if (GetArena() == nullptr && $name$_ != nullptr) {\n" + " delete $name$_;\n" + "}\n" + "$name$_ = nullptr;\n"); } else { - printer->Print(variables, - "if ($this_message$$name$_ != NULL) $this_message$$name$_->" - "$dependent_type$::Clear();\n"); + format("if ($name$_ != nullptr) $name$_->Clear();\n"); } } -void MessageFieldGenerator:: -GenerateMessageClearingCode(io::Printer* printer) const { +void MessageFieldGenerator::GenerateMessageClearingCode( + io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); + + Formatter format(printer, variables_); if (!HasFieldPresence(descriptor_->file())) { // If we don't have has-bits, message presence is indicated only by ptr != // NULL. Thus on clear, we need to delete the object. - printer->Print(variables_, - "if (GetArenaNoVirtual() == NULL && $name$_ != NULL) {\n" - " delete $name$_;\n" - "}\n" - "$name$_ = NULL;\n"); + format( + "if (GetArena() == nullptr && $name$_ != nullptr) {\n" + " delete $name$_;\n" + "}\n" + "$name$_ = nullptr;\n"); } else { - printer->Print(variables_, - "GOOGLE_DCHECK($name$_ != NULL);\n" - "$name$_->$type$::Clear();\n"); + format( + "$DCHK$($name$_ != nullptr);\n" + "$name$_->Clear();\n"); } } -void MessageFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "mutable_$name$()->$type$::MergeFrom(from.$name$());\n"); -} +void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); -void MessageFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "swap($name$_, other->$name$_);\n"); + Formatter format(printer, variables_); + if (implicit_weak_field_) { + format( + "_Internal::mutable_$name$(this)->CheckTypeAndMergeFrom(\n" + " _Internal::$name$(&from));\n"); + } else { + format( + "_internal_mutable_$name$()->$type$::MergeFrom(from._internal_$name$())" + ";\n"); + } } -void MessageFieldGenerator:: -GenerateDestructorCode(io::Printer* printer) const { - // TODO(gerbens) Remove this when we don't need to destruct default instances. - // In google3 a default instance will never get deleted so we don't need to - // worry about that but in opensource protobuf default instances are deleted - // in shutdown process and we need to take special care when handling them. - printer->Print(variables_, - "if (this != internal_default_instance()) "); - printer->Print(variables_, "delete $name$_;\n"); -} +void MessageFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); -void MessageFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = NULL;\n"); + Formatter format(printer, variables_); + format("swap($name$_, other->$name$_);\n"); } -void MessageFieldGenerator:: -GenerateCopyConstructorCode(io::Printer* printer) const { - // For non-Arena enabled messages, everything always goes on the heap. - // - // For Arena enabled messages, the logic is a bit more convoluted. - // - // In the copy constructor, we call InternalMetadataWithArena::MergeFrom, - // which does *not* copy the Arena pointer. In the generated MergeFrom - // (see MessageFieldGenerator::GenerateMergingCode), we: - // -> copy the has bits (but this is done in bulk by a memcpy in the copy - // constructor) - // -> check whether the destination field pointer is NULL (it will be, since - // we're initializing it and would have called SharedCtor) and if so: - // -> call _slow_mutable_$name$(), which calls either - // ::google::protobuf::Arena::CreateMessage<>(GetArenaNoVirtual()), or - // ::google::protobuf::Arena::Create<>(GetArenaNoVirtual()) - // - // At this point, GetArenaNoVirtual returns NULL since the Arena pointer - // wasn't copied, so both of these methods allocate the submessage on the - // heap. - - printer->Print(variables_, - "if (from.has_$name$()) {\n" - " $name$_ = new $type$(*from.$name$_);\n" - "} else {\n" - " $name$_ = NULL;\n" - "}\n"); -} +void MessageFieldGenerator::GenerateDestructorCode(io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); -void MessageFieldGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) const { - if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" - " input, mutable_$name$()));\n"); - } else { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n" - " $number$, input, mutable_$name$()));\n"); + Formatter format(printer, variables_); + if (options_.opensource_runtime) { + // TODO(gerbens) Remove this when we don't need to destruct default + // instances. In google3 a default instance will never get deleted so we + // don't need to worry about that but in opensource protobuf default + // instances are deleted in shutdown process and we need to take special + // care when handling them. + format("if (this != internal_default_instance()) "); } + format("delete $name$_;\n"); } -void MessageFieldGenerator:: -GenerateSerializeWithCachedSizes(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" - " $number$, *$non_null_ptr_to_name$, output);\n"); -} +void MessageFieldGenerator::GenerateConstructorCode( + io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); -void MessageFieldGenerator:: -GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormatLite::\n" - " InternalWrite$declared_type$NoVirtualToArray(\n" - " $number$, *$non_null_ptr_to_name$, deterministic, target);\n"); + Formatter format(printer, variables_); + format("$name$_ = nullptr;\n"); } -void MessageFieldGenerator:: -GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, - "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n" - " *$non_null_ptr_to_name$);\n"); +void MessageFieldGenerator::GenerateCopyConstructorCode( + io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); + + Formatter format(printer, variables_); + format( + "if (from._internal_has_$name$()) {\n" + " $name$_ = new $type$(*from.$name$_);\n" + "} else {\n" + " $name$_ = nullptr;\n" + "}\n"); } -// =================================================================== +void MessageFieldGenerator::GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); -MessageOneofFieldGenerator:: -MessageOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : MessageFieldGenerator(descriptor, options), - dependent_base_(options.proto_h) { - SetCommonOneofFieldVariables(descriptor, &variables_); + Formatter format(printer, variables_); + format( + "target = stream->EnsureSpace(target);\n" + "target = ::$proto_ns$::internal::WireFormatLite::\n" + " InternalWrite$declared_type$(\n" + " $number$, _Internal::$name$(this), target, stream);\n"); } -MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} - +void MessageFieldGenerator::GenerateByteSize(io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); -void MessageOneofFieldGenerator:: -GenerateDependentAccessorDeclarations(io::Printer* printer) const { - // Oneof field getters must be dependent as they call default_instance(). - // Otherwise, the logic is the same as MessageFields. - if (!dependent_field_) { - return; - } - printer->Print(variables_, - "$deprecated_attr$const $type$& $name$() const;\n"); - MessageFieldGenerator::GenerateDependentAccessorDeclarations(printer); + Formatter format(printer, variables_); + format( + "total_size += $tag_size$ +\n" + " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n" + " *$field_member$);\n"); } -void MessageOneofFieldGenerator:: -GenerateGetterDeclaration(io::Printer* printer) const { - // Oneof field getters must be dependent as they call default_instance(). - // Unlike MessageField, this means there is no (non-dependent) getter to - // generate. - if (dependent_field_) { - return; - } - printer->Print(variables_, - "$deprecated_attr$const $type$& $name$() const;\n"); +void MessageFieldGenerator::GenerateConstinitInitializer( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_(nullptr)"); } -void MessageOneofFieldGenerator:: -GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { - // For the CRTP base class, all mutation methods are dependent, and so - // they must be in the header. - if (!dependent_base_) { - return; - } - std::map variables(variables_); - variables["inline"] = "inline "; - variables["dependent_classname"] = - DependentBaseClassTemplateName(descriptor_->containing_type()) + ""; - variables["this_message"] = "reinterpret_cast(this)->"; - // Const message access is needed for the dependent getter. - variables["this_const_message"] = "reinterpret_cast(this)->"; - variables["tmpl"] = "template \n"; - variables["field_member"] = variables["this_message"] + - variables["oneof_prefix"] + variables["name"] + - "_"; - InternalGenerateInlineAccessorDefinitions(variables, printer); -} +// =================================================================== -void MessageOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const { - if (dependent_base_) { - return; - } - std::map variables(variables_); - variables["inline"] = is_inline ? "inline " : ""; - variables["dependent_classname"] = variables["classname"]; - variables["this_message"] = ""; - variables["this_const_message"] = ""; - variables["tmpl"] = ""; - variables["field_member"] = - variables["oneof_prefix"] + variables["name"] + "_"; - variables["dependent_type"] = variables["type"]; - InternalGenerateInlineAccessorDefinitions(variables, printer); +MessageOneofFieldGenerator::MessageOneofFieldGenerator( + const FieldDescriptor* descriptor, const Options& options, + MessageSCCAnalyzer* scc_analyzer) + : MessageFieldGenerator(descriptor, options, scc_analyzer) { + SetCommonOneofFieldVariables(descriptor, &variables_); } -void MessageOneofFieldGenerator::InternalGenerateInlineAccessorDefinitions( - const std::map& variables, io::Printer* printer) const { - printer->Print(variables, - "$tmpl$" - "$inline$ " - "const $type$& $dependent_classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $this_const_message$has_$name$()\n" - " ? *$this_const_message$$oneof_prefix$$name$_\n" - " : $dependent_type$::default_instance();\n" - "}\n"); - - if (SupportsArenas(descriptor_)) { - printer->Print(variables, - "$tmpl$" - "$inline$" - "$type$* $dependent_classname$::mutable_$name$() {\n" - " if (!$this_message$has_$name$()) {\n" - " $this_message$clear_$oneof_name$();\n" - " $this_message$set_has_$name$();\n"); - if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables, - " $field_member$ = \n" - " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n" - " $this_message$GetArenaNoVirtual());\n"); - } else { - printer->Print(variables, - " $this_message$$oneof_prefix$$name$_ = \n" - " ::google::protobuf::Arena::Create< $dependent_typename$ >(\n" - " $this_message$GetArenaNoVirtual());\n"); - } - printer->Print(variables, +MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} + +void MessageOneofFieldGenerator::GenerateNonInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "void $classname$::set_allocated_$name$($type$* $name$) {\n" + "$annotate_accessor$" + " ::$proto_ns$::Arena* message_arena = GetArena();\n" + " clear_$oneof_name$();\n" + " if ($name$) {\n"); + if (descriptor_->file() != descriptor_->message_type()->file()) { + // We have to read the arena through the virtual method, because the type + // isn't defined in this file. + format( + " ::$proto_ns$::Arena* submessage_arena =\n" + " " + "reinterpret_cast<::$proto_ns$::MessageLite*>($name$)->GetArena();\n"); + } else { + format( + " ::$proto_ns$::Arena* submessage_arena =\n" + " ::$proto_ns$::Arena::GetArena($name$);\n"); + } + format( + " if (message_arena != submessage_arena) {\n" + " $name$ = ::$proto_ns$::internal::GetOwnedMessage(\n" + " message_arena, $name$, submessage_arena);\n" + " }\n" + " set_has_$name$();\n" + " $field_member$ = $name$;\n" " }\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $field_member$;\n" - "}\n" - "$tmpl$" - "$inline$" - "$type$* $dependent_classname$::$release_name$() {\n" + " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + "}\n"); +} + +void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "inline $type$* $classname$::$release_name$() {\n" + "$annotate_accessor$" " // @@protoc_insertion_point(field_release:$full_name$)\n" - " if ($this_message$has_$name$()) {\n" - " $this_message$clear_has_$oneof_name$();\n" - " if ($this_message$GetArenaNoVirtual() != NULL) {\n" - // N.B.: safe to use the underlying field pointer here because we are sure - // that it is non-NULL (because has_$name$() returned true). - " $dependent_typename$* temp = " - "new $dependent_typename$(*$field_member$);\n" - " $field_member$ = NULL;\n" - " return temp;\n" - " } else {\n" - " $dependent_typename$* temp = $field_member$;\n" - " $field_member$ = NULL;\n" - " return temp;\n" + " if (_internal_has_$name$()) {\n" + " clear_has_$oneof_name$();\n" + " $type$* temp = $field_member$;\n" + " if (GetArena() != nullptr) {\n" + " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n" " }\n" + " $field_member$ = nullptr;\n" + " return temp;\n" " } else {\n" - " return NULL;\n" + " return nullptr;\n" " }\n" - "}\n" - "$tmpl$" - "$inline$" - "void $dependent_classname$::" - "set_allocated_$name$($type$* $name$) {\n" - " $this_message$clear_$oneof_name$();\n" - " if ($name$) {\n"); - - if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables, - // If incoming message is on the heap and we are on an arena, just Own() - // it (see above). If it's on a different arena than we are or one of us - // is on the heap, we make a copy to our arena/heap. - " if ($this_message$GetArenaNoVirtual() != NULL &&\n" - " ::google::protobuf::Arena::GetArena($name$) == NULL) {\n" - " $this_message$GetArenaNoVirtual()->Own($name$);\n" - " } else if ($this_message$GetArenaNoVirtual() !=\n" - " ::google::protobuf::Arena::GetArena($name$)) {\n" - " $dependent_typename$* new_$name$ = \n" - " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n" - " $this_message$GetArenaNoVirtual());\n" - " new_$name$->CopyFrom(*$name$);\n" - " $name$ = new_$name$;\n" - " }\n"); - } else { - printer->Print(variables, - " if ($this_message$GetArenaNoVirtual() != NULL) {\n" - " $this_message$GetArenaNoVirtual()->Own($name$);\n" - " }\n"); - } + "}\n"); - printer->Print(variables, - " $this_message$set_has_$name$();\n" - " $field_member$ = $name$;\n" - " }\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + format( + "inline const $type$& $classname$::_internal_$name$() const {\n" + " return _internal_has_$name$()\n" + " ? *$field_member$\n" + " : reinterpret_cast< $type$&>($type_default_instance$);\n" + "}\n" + "inline const $type$& $classname$::$name$() const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return _internal_$name$();\n" "}\n" - "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n" + "inline $type$* $classname$::unsafe_arena_release_$name$() {\n" + "$annotate_accessor$" " // @@protoc_insertion_point(field_unsafe_arena_release" ":$full_name$)\n" - " if (has_$name$()) {\n" + " if (_internal_has_$name$()) {\n" " clear_has_$oneof_name$();\n" - " $type$* temp = $oneof_prefix$$name$_;\n" - " $oneof_prefix$$name$_ = NULL;\n" + " $type$* temp = $field_member$;\n" + " $field_member$ = nullptr;\n" " return temp;\n" " } else {\n" - " return NULL;\n" + " return nullptr;\n" " }\n" "}\n" - "$inline$ void $classname$::unsafe_arena_set_allocated_$name$" + "inline void $classname$::unsafe_arena_set_allocated_$name$" "($type$* $name$) {\n" - // We rely on the oneof clear method to free the earlier contents of this - // oneof. We can directly use the pointer we're given to set the new - // value. + "$annotate_accessor$" + // We rely on the oneof clear method to free the earlier contents of + // this oneof. We can directly use the pointer we're given to set the + // new value. " clear_$oneof_name$();\n" " if ($name$) {\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_ = $name$;\n" + " $field_member$ = $name$;\n" " }\n" " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" "$full_name$)\n" - "}\n"); - } else { - printer->Print(variables, - "$tmpl$" - "$inline$" - "$type$* $dependent_classname$::mutable_$name$() {\n" - " if (!$this_message$has_$name$()) {\n" - " $this_message$clear_$oneof_name$();\n" - " $this_message$set_has_$name$();\n" - " $field_member$ = new $dependent_typename$;\n" - " }\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $field_member$;\n" "}\n" - "$tmpl$" - "$inline$" - "$type$* $dependent_classname$::$release_name$() {\n" - " // @@protoc_insertion_point(field_release:$full_name$)\n" - " if ($this_message$has_$name$()) {\n" - " $this_message$clear_has_$oneof_name$();\n" - " $dependent_typename$* temp = $field_member$;\n" - " $field_member$ = NULL;\n" - " return temp;\n" - " } else {\n" - " return NULL;\n" + "inline $type$* $classname$::_internal_mutable_$name$() {\n" + " if (!_internal_has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$ = CreateMaybeMessage< $type$ >(GetArena());\n" " }\n" + " return $field_member$;\n" "}\n" - "$tmpl$" - "$inline$" - "void $dependent_classname$::" - "set_allocated_$name$($type$* $name$) {\n" - " $this_message$clear_$oneof_name$();\n" - " if ($name$) {\n"); - if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables, - " if (static_cast< $dependent_typename$*>($name$)->" - "GetArena() != NULL) {\n" - " $dependent_typename$* new_$name$ = new $dependent_typename$;\n" - " new_$name$->CopyFrom(*$name$);\n" - " $name$ = new_$name$;\n" - " }\n"); - } - printer->Print(variables, - " $this_message$set_has_$name$();\n" - " $field_member$ = $name$;\n" - " }\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + "inline $type$* $classname$::mutable_$name$() {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + " return _internal_mutable_$name$();\n" "}\n"); - } } -void MessageOneofFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - std::map variables(variables_); - variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : ""; - if (SupportsArenas(descriptor_)) { - printer->Print(variables, - "if ($this_message$GetArenaNoVirtual() == NULL) {\n" - " delete $this_message$$oneof_prefix$$name$_;\n" +void MessageOneofFieldGenerator::GenerateClearingCode( + io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); + + Formatter format(printer, variables_); + format( + "if (GetArena() == nullptr) {\n" + " delete $field_member$;\n" "}\n"); - } else { - printer->Print(variables, - "delete $this_message$$oneof_prefix$$name$_;\n"); - } } -void MessageOneofFieldGenerator:: -GenerateMessageClearingCode(io::Printer* printer) const { +void MessageOneofFieldGenerator::GenerateMessageClearingCode( + io::Printer* printer) const { GenerateClearingCode(printer); } -void MessageOneofFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { +void MessageOneofFieldGenerator::GenerateSwappingCode( + io::Printer* printer) const { // Don't print any swapping code. Swapping the union will swap this field. } -void MessageOneofFieldGenerator:: -GenerateDestructorCode(io::Printer* printer) const { +void MessageOneofFieldGenerator::GenerateDestructorCode( + io::Printer* printer) const { // We inherit from MessageFieldGenerator, so we need to override the default // behavior. } -void MessageOneofFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { +void MessageOneofFieldGenerator::GenerateConstructorCode( + io::Printer* printer) const { // Don't print any constructor code. The field is in a union. We allocate // space only when this field is used. } @@ -886,250 +625,200 @@ GenerateConstructorCode(io::Printer* printer) const { // =================================================================== RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( - const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), - descriptor_(descriptor), - dependent_field_(options.proto_h && IsFieldDependent(descriptor)), - dependent_getter_(dependent_field_ && options.safe_boundary_check) { - SetMessageVariables(descriptor, &variables_, options); + const FieldDescriptor* descriptor, const Options& options, + MessageSCCAnalyzer* scc_analyzer) + : FieldGenerator(descriptor, options), + implicit_weak_field_( + IsImplicitWeakField(descriptor, options, scc_analyzer)) { + SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_); } RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} -void RepeatedMessageFieldGenerator:: -GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n"); -} - -void RepeatedMessageFieldGenerator:: -InternalGenerateTypeDependentAccessorDeclarations(io::Printer* printer) const { - printer->Print(variables_, - "$deprecated_attr$$type$* ${$mutable_$name$$}$(int index);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, "$deprecated_attr$$type$* ${$add_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); - if (dependent_getter_) { - printer->Print(variables_, - "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n" - " $name$() const;\n"); - printer->Annotate("name", descriptor_); - } - printer->Print(variables_, - "$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n" - " ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); -} - -void RepeatedMessageFieldGenerator:: -GenerateDependentAccessorDeclarations(io::Printer* printer) const { - if (dependent_getter_) { - printer->Print(variables_, - "$deprecated_attr$const $type$& $name$(int index) const;\n"); - printer->Annotate("name", descriptor_); - } - if (dependent_field_) { - InternalGenerateTypeDependentAccessorDeclarations(printer); - } -} - -void RepeatedMessageFieldGenerator:: -GenerateAccessorDeclarations(io::Printer* printer) const { - if (!dependent_getter_) { - printer->Print(variables_, - "$deprecated_attr$const $type$& $name$(int index) const;\n"); - printer->Annotate("name", descriptor_); - } - if (!dependent_field_) { - InternalGenerateTypeDependentAccessorDeclarations(printer); - } - if (!dependent_getter_) { - printer->Print(variables_, - "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n" - " $name$() const;\n"); - printer->Annotate("name", descriptor_); +void RepeatedMessageFieldGenerator::GeneratePrivateMembers( + io::Printer* printer) const { + Formatter format(printer, variables_); + if (implicit_weak_field_) { + format("::$proto_ns$::WeakRepeatedPtrField< $type$ > $name$_;\n"); + } else { + format("::$proto_ns$::RepeatedPtrField< $type$ > $name$_;\n"); } } -void RepeatedMessageFieldGenerator:: -GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { - if (!dependent_field_) { +void RepeatedMessageFieldGenerator::GenerateAccessorDeclarations( + io::Printer* printer) const { + Formatter format(printer, variables_); + if (IsFieldStripped(descriptor_, options_)) { + format( + "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index) { " + "__builtin_trap(); }\n" + "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n" + " ${1$mutable_$name$$}$() { __builtin_trap(); }\n" + "$deprecated_attr$const $type$& ${1$$name$$}$(int index) const { " + "__builtin_trap(); }\n" + "$deprecated_attr$$type$* ${1$add_$name$$}$() { " + "__builtin_trap(); }\n" + "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField< $type$ >&\n" + " ${1$$name$$}$() const { __builtin_trap(); }\n", + descriptor_); return; } - std::map variables(variables_); - // For the CRTP base class, all mutation methods are dependent, and so - // they must be in the header. - variables["dependent_classname"] = - DependentBaseClassTemplateName(descriptor_->containing_type()) + ""; - variables["this_message"] = DependentBaseDownCast(); - variables["this_const_message"] = DependentBaseConstDownCast(); - - if (dependent_getter_) { - printer->Print(variables, - "template \n" - "inline const $type$& $dependent_classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $this_const_message$$name$_.$cppget$(index);\n" - "}\n"); - } + format( + "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index);\n" + "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n" + " ${1$mutable_$name$$}$();\n", + descriptor_); + if (!IsFieldStripped(descriptor_, options_)) { + format( + "private:\n" + "const $type$& ${1$_internal_$name$$}$(int index) const;\n" + "$type$* ${1$_internal_add_$name$$}$();\n" + "public:\n", + descriptor_); + } + format( + "$deprecated_attr$const $type$& ${1$$name$$}$(int index) const;\n" + "$deprecated_attr$$type$* ${1$add_$name$$}$();\n" + "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField< $type$ >&\n" + " ${1$$name$$}$() const;\n", + descriptor_); +} + +void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format.Set("weak", implicit_weak_field_ ? ".weak" : ""); - // Generate per-element accessors: - printer->Print(variables, - "template \n" - "inline $type$* $dependent_classname$::mutable_$name$(int index) {\n" - // TODO(dlj): move insertion points - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $this_message$$name$_.Mutable(index);\n" - "}\n" - "template \n" - "inline $type$* $dependent_classname$::add_$name$() {\n" - " // @@protoc_insertion_point(field_add:$full_name$)\n" - " return $this_message$$name$_.Add();\n" - "}\n"); - - if (dependent_getter_) { - printer->Print(variables, - "template \n" - "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" - "$dependent_classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_list:$full_name$)\n" - " return $this_const_message$$name$_;\n" + format( + "inline $type$* $classname$::mutable_$name$(int index) {\n" + "$annotate_accessor$" + // TODO(dlj): move insertion points + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + "$type_reference_function$" + " return $name$_$weak$.Mutable(index);\n" + "}\n" + "inline ::$proto_ns$::RepeatedPtrField< $type$ >*\n" + "$classname$::mutable_$name$() {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" + "$type_reference_function$" + " return &$name$_$weak$;\n" "}\n"); - } - // Generate mutable access to the entire list: - printer->Print(variables, - "template \n" - "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" - "$dependent_classname$::mutable_$name$() {\n" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - " return &$this_message$$name$_;\n" - "}\n"); -} - -void RepeatedMessageFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const { - std::map variables(variables_); - variables["inline"] = is_inline ? "inline " : ""; - - if (!dependent_getter_) { - printer->Print(variables, - "$inline$" - "const $type$& $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_.$cppget$(index);\n" - "}\n"); + if (options_.safe_boundary_check) { + format( + "inline const $type$& $classname$::_internal_$name$(int index) const " + "{\n" + " return $name$_$weak$.InternalCheckedGet(index,\n" + " reinterpret_cast($type_default_instance$));\n" + "}\n"); + } else { + format( + "inline const $type$& $classname$::_internal_$name$(int index) const " + "{\n" + "$type_reference_function$" + " return $name$_$weak$.Get(index);\n" + "}\n"); } - if (!dependent_field_) { - printer->Print(variables, - "$inline$" - "$type$* $classname$::mutable_$name$(int index) {\n" - // TODO(dlj): move insertion points - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $name$_.Mutable(index);\n" + format( + "inline const $type$& $classname$::$name$(int index) const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return _internal_$name$(index);\n" "}\n" - "$inline$" - "$type$* $classname$::add_$name$() {\n" + "inline $type$* $classname$::_internal_add_$name$() {\n" + " return $name$_$weak$.Add();\n" + "}\n" + "inline $type$* $classname$::add_$name$() {\n" + "$annotate_accessor$" " // @@protoc_insertion_point(field_add:$full_name$)\n" - " return $name$_.Add();\n" + " return _internal_add_$name$();\n" "}\n"); - } - if (!dependent_field_) { - printer->Print(variables, - "$inline$" - "::google::protobuf::RepeatedPtrField< $type$ >*\n" - "$classname$::mutable_$name$() {\n" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - " return &$name$_;\n" - "}\n"); - } - if (!dependent_getter_) { - printer->Print(variables, - "$inline$" - "const ::google::protobuf::RepeatedPtrField< $type$ >&\n" + format( + "inline const ::$proto_ns$::RepeatedPtrField< $type$ >&\n" "$classname$::$name$() const {\n" + "$annotate_accessor$" " // @@protoc_insertion_point(field_list:$full_name$)\n" - " return $name$_;\n" + "$type_reference_function$" + " return $name$_$weak$;\n" "}\n"); - } } -void RepeatedMessageFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - std::map variables(variables_); - variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : ""; - printer->Print(variables, "$this_message$$name$_.Clear();\n"); +void RepeatedMessageFieldGenerator::GenerateClearingCode( + io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); + + Formatter format(printer, variables_); + format("$name$_.Clear();\n"); } -void RepeatedMessageFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); +void RepeatedMessageFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); + + Formatter format(printer, variables_); + format("$name$_.MergeFrom(from.$name$_);\n"); } -void RepeatedMessageFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n"); +void RepeatedMessageFieldGenerator::GenerateSwappingCode( + io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); + + Formatter format(printer, variables_); + format("$name$_.InternalSwap(&other->$name$_);\n"); } -void RepeatedMessageFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { +void RepeatedMessageFieldGenerator::GenerateConstructorCode( + io::Printer* printer) const { // Not needed for repeated fields. } -void RepeatedMessageFieldGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) const { - if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::" - "ReadMessageNoVirtual(\n" - " input, add_$name$()));\n"); +void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); + + Formatter format(printer, variables_); + if (implicit_weak_field_) { + format( + "for (auto it = this->$name$_.pointer_begin(),\n" + " end = this->$name$_.pointer_end(); it < end; ++it) {\n" + " target = stream->EnsureSpace(target);\n" + " target = ::$proto_ns$::internal::WireFormatLite::\n" + " InternalWrite$declared_type$($number$, **it, target, stream);\n" + "}\n"); } else { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::" - "ReadGroupNoVirtual(\n" - " $number$, input, add_$name$()));\n"); + format( + "for (unsigned int i = 0,\n" + " n = static_cast(this->_internal_$name$_size()); i < " + "n; i++) " + "{\n" + " target = stream->EnsureSpace(target);\n" + " target = ::$proto_ns$::internal::WireFormatLite::\n" + " InternalWrite$declared_type$($number$, " + "this->_internal_$name$(i), target, stream);\n" + "}\n"); } } -void RepeatedMessageFieldGenerator:: -GenerateSerializeWithCachedSizes(io::Printer* printer) const { - printer->Print(variables_, - "for (unsigned int i = 0,\n" - " n = static_cast(this->$name$_size()); i < n; i++) {\n" - " ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" - " $number$, this->$name$(static_cast(i)), output);\n" - "}\n"); -} - -void RepeatedMessageFieldGenerator:: -GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - printer->Print(variables_, - "for (unsigned int i = 0,\n" - " n = static_cast(this->$name$_size()); i < n; i++) {\n" - " target = ::google::protobuf::internal::WireFormatLite::\n" - " InternalWrite$declared_type$NoVirtualToArray(\n" - " $number$, this->$name$(static_cast(i)), deterministic, target);\n" - "}\n"); +void RepeatedMessageFieldGenerator::GenerateByteSize( + io::Printer* printer) const { + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); + + Formatter format(printer, variables_); + format( + "total_size += $tag_size$UL * this->_internal_$name$_size();\n" + "for (const auto& msg : this->$name$_) {\n" + " total_size +=\n" + " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(msg);\n" + "}\n"); } -void RepeatedMessageFieldGenerator:: -GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, - "{\n" - " unsigned int count = static_cast(this->$name$_size());\n"); - printer->Indent(); - printer->Print(variables_, - "total_size += $tag_size$UL * count;\n" - "for (unsigned int i = 0; i < count; i++) {\n" - " total_size +=\n" - " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n" - " this->$name$(static_cast(i)));\n" - "}\n"); - printer->Outdent(); - printer->Print("}\n"); +void RepeatedMessageFieldGenerator::GenerateConstinitInitializer( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_()"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h index cd9737f0e3724..4b4b8ea59b0ee 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h @@ -38,6 +38,7 @@ #include #include #include +#include namespace google { namespace protobuf { @@ -47,17 +48,17 @@ namespace cpp { class MessageFieldGenerator : public FieldGenerator { public: MessageFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + const Options& options, + MessageSCCAnalyzer* scc_analyzer); ~MessageFieldGenerator(); // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; - void GenerateDependentAccessorDeclarations(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInternalAccessorDeclarations(io::Printer* printer) const; + void GenerateInternalAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMessageClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; @@ -65,20 +66,12 @@ class MessageFieldGenerator : public FieldGenerator { void GenerateDestructorCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; void GenerateCopyConstructorCode(io::Printer* printer) const; - void GenerateMergeFromCodedStream(io::Printer* printer) const; - void GenerateSerializeWithCachedSizes(io::Printer* printer) const; void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; + void GenerateConstinitInitializer(io::Printer* printer) const; protected: - void GenerateArenaManipulationCode(const std::map& variables, - io::Printer* printer) const; - - virtual void GenerateGetterDeclaration(io::Printer* printer) const; - - const FieldDescriptor* descriptor_; - const bool dependent_field_; - std::map variables_; + const bool implicit_weak_field_; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); @@ -87,15 +80,13 @@ class MessageFieldGenerator : public FieldGenerator { class MessageOneofFieldGenerator : public MessageFieldGenerator { public: MessageOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + const Options& options, + MessageSCCAnalyzer* scc_analyzer); ~MessageOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- - void GenerateDependentAccessorDeclarations(io::Printer* printer) const; - void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const; - void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const { } + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; // MessageFieldGenerator, from which we inherit, overrides this so we need to @@ -105,48 +96,32 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator { void GenerateDestructorCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; - protected: - void GenerateGetterDeclaration(io::Printer* printer) const; - private: - void InternalGenerateInlineAccessorDefinitions( - const std::map& variables, io::Printer* printer) const; - - const bool dependent_base_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator); }; class RepeatedMessageFieldGenerator : public FieldGenerator { public: RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); + const Options& options, + MessageSCCAnalyzer* scc_analyzer); ~RepeatedMessageFieldGenerator(); // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; - void GenerateDependentAccessorDeclarations(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; void GenerateCopyConstructorCode(io::Printer* printer) const {} - void GenerateMergeFromCodedStream(io::Printer* printer) const; - void GenerateSerializeWithCachedSizes(io::Printer* printer) const; void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; + void GenerateConstinitInitializer(io::Printer* printer) const; private: - void InternalGenerateTypeDependentAccessorDeclarations( - io::Printer* printer) const; - - const FieldDescriptor* descriptor_; - const bool dependent_field_; - const bool dependent_getter_; - std::map variables_; + const bool implicit_weak_field_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); }; @@ -154,6 +129,6 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h b/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h new file mode 100644 index 0000000000000..67eeff0ae7304 --- /dev/null +++ b/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h @@ -0,0 +1,61 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: seongkim@google.com (Seong Beom Kim) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__ + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +// Provides an abstract interface to optimize message layout +// by rearranging the fields of a message. +class MessageLayoutHelper { + public: + virtual ~MessageLayoutHelper() {} + + virtual void OptimizeLayout(std::vector* fields, + const Options& options) = 0; +}; + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_move_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_move_unittest.cc index f72a7d601462e..eb7cd1c775fff 100644 --- a/src/google/protobuf/compiler/cpp/cpp_move_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_move_unittest.cc @@ -34,7 +34,7 @@ #include #if LANG_CXX11 -#include +#include #endif namespace google { diff --git a/src/google/protobuf/compiler/cpp/cpp_names.h b/src/google/protobuf/compiler/cpp/cpp_names.h new file mode 100644 index 0000000000000..9bede74fc8a32 --- /dev/null +++ b/src/google/protobuf/compiler/cpp/cpp_names.h @@ -0,0 +1,85 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__ + +#include + +#include + +namespace google { +namespace protobuf { + +class Descriptor; +class EnumDescriptor; +class FieldDescriptor; + +namespace compiler { +namespace cpp { + +// Returns the unqualified C++ name. +// +// For example, if you had: +// package foo.bar; +// message Baz { message Qux {} } +// Then the non-qualified version would be: +// Baz_Qux +std::string ClassName(const Descriptor* descriptor); +std::string ClassName(const EnumDescriptor* enum_descriptor); + +// Returns the fully qualified C++ name. +// +// For example, if you had: +// package foo.bar; +// message Baz { message Qux {} } +// Then the qualified ClassName for Qux would be: +// ::foo::bar::Baz_Qux +std::string QualifiedClassName(const Descriptor* d); +std::string QualifiedClassName(const EnumDescriptor* d); +std::string QualifiedExtensionName(const FieldDescriptor* d); + +// Get the (unqualified) name that should be used for this field in C++ code. +// The name is coerced to lower-case to emulate proto1 behavior. People +// should be using lowercase-with-underscores style for proto field names +// anyway, so normally this just returns field->name(). +std::string FieldName(const FieldDescriptor* field); + +// Strips ".proto" or ".protodevel" from the end of a filename. +PROTOC_EXPORT std::string StripProto(const std::string& filename); + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include + +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h index 04338083bdf7a..92b55484676ca 100644 --- a/src/google/protobuf/compiler/cpp/cpp_options.h +++ b/src/google/protobuf/compiler/cpp/cpp_options.h @@ -35,39 +35,45 @@ #include -#include namespace google { namespace protobuf { namespace compiler { +class AccessInfoMap; + namespace cpp { +enum class EnforceOptimizeMode { + kNoEnforcement, // Use the runtime specified by the file specific options. + kSpeed, // Full runtime with a generated code implementation. + kCodeSize, // Full runtime with a reflective implementation. + kLiteRuntime, +}; + // Generator options (see generator.cc for a description of each): struct Options { - Options() - : safe_boundary_check(false), - proto_h(false), - transitive_pb_h(true), - annotate_headers(false), - enforce_lite(false), - table_driven_parsing(false), - table_driven_serialization(false) {} - - string dllexport_decl; - bool safe_boundary_check; - bool proto_h; - bool transitive_pb_h; - bool annotate_headers; - bool enforce_lite; - bool table_driven_parsing; - bool table_driven_serialization; - string annotation_pragma_name; - string annotation_guard_name; + std::string dllexport_decl; + bool safe_boundary_check = false; + bool proto_h = false; + bool transitive_pb_h = true; + bool annotate_headers = false; + EnforceOptimizeMode enforce_mode = EnforceOptimizeMode::kNoEnforcement; + bool table_driven_parsing = false; + bool table_driven_serialization = false; + bool lite_implicit_weak_fields = false; + bool bootstrap = false; + bool opensource_runtime = false; + bool annotate_accessor = false; + bool unused_field_stripping = false; + std::string runtime_include_base; + int num_cc_files = 0; + std::string annotation_pragma_name; + std::string annotation_guard_name; + const AccessInfoMap* access_info_map = nullptr; }; } // namespace cpp } // namespace compiler } // namespace protobuf - - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc new file mode 100644 index 0000000000000..2f78bda520d20 --- /dev/null +++ b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc @@ -0,0 +1,227 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +namespace { + +// FieldGroup is just a helper for PaddingOptimizer below. It holds a vector of +// fields that are grouped together because they have compatible alignment, and +// a preferred location in the final field ordering. +class FieldGroup { + public: + FieldGroup() : preferred_location_(0) {} + + // A group with a single field. + FieldGroup(float preferred_location, const FieldDescriptor* field) + : preferred_location_(preferred_location), fields_(1, field) {} + + // Append the fields in 'other' to this group. + void Append(const FieldGroup& other) { + if (other.fields_.empty()) { + return; + } + // Preferred location is the average among all the fields, so we weight by + // the number of fields on each FieldGroup object. + preferred_location_ = (preferred_location_ * fields_.size() + + (other.preferred_location_ * other.fields_.size())) / + (fields_.size() + other.fields_.size()); + fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end()); + } + + void SetPreferredLocation(float location) { preferred_location_ = location; } + const std::vector& fields() const { return fields_; } + + // FieldGroup objects sort by their preferred location. + bool operator<(const FieldGroup& other) const { + return preferred_location_ < other.preferred_location_; + } + + private: + // "preferred_location_" is an estimate of where this group should go in the + // final list of fields. We compute this by taking the average index of each + // field in this group in the original ordering of fields. This is very + // approximate, but should put this group close to where its member fields + // originally went. + float preferred_location_; + std::vector fields_; + // We rely on the default copy constructor and operator= so this type can be + // used in a vector. +}; + +} // namespace + +// Reorder 'fields' so that if the fields are output into a c++ class in the new +// order, fields of similar family (see below) are together and within each +// family, alignment padding is minimized. +// +// We try to do this while keeping each field as close as possible to its field +// number order so that we don't reduce cache locality much for function that +// access each field in order. Originally, OptimizePadding used declaration +// order for its decisions, but generated code minus the serializer/parsers uses +// the output of OptimizePadding as well (stored in +// MessageGenerator::optimized_order_). Since the serializers use field number +// order, we use that as a tie-breaker. +// +// We classify each field into a particular "family" of fields, that we perform +// the same operation on in our generated functions. +// +// REPEATED is placed first, as the C++ compiler automatically initializes +// these fields in layout order. +// +// STRING is grouped next, as our Clear/SharedCtor/SharedDtor walks it and +// calls ArenaStringPtr::Destroy on each. +// +// LAZY_MESSAGE is grouped next, as it interferes with the ability to memset +// non-repeated fields otherwise. +// +// MESSAGE is grouped next, as our Clear/SharedDtor code walks it and calls +// delete on each. We initialize these fields with a NULL pointer (see +// MessageFieldGenerator::GenerateConstructorCode), which allows them to be +// memset. +// +// ZERO_INITIALIZABLE is memset in Clear/SharedCtor +// +// OTHER these fields are initialized one-by-one. +void PaddingOptimizer::OptimizeLayout( + std::vector* fields, const Options& options) { + // The sorted numeric order of Family determines the declaration order in the + // memory layout. + enum Family { + REPEATED = 0, + STRING = 1, + // Laying out LAZY_MESSAGE before MESSAGE allows a single memset to zero + // MESSAGE and ZERO_INITIALIZABLE fields together. + LAZY_MESSAGE = 2, + MESSAGE = 3, + ZERO_INITIALIZABLE = 4, + OTHER = 5, + kMaxFamily + }; + + // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes. + std::vector aligned_to_1[kMaxFamily]; + std::vector aligned_to_4[kMaxFamily]; + std::vector aligned_to_8[kMaxFamily]; + for (int i = 0; i < fields->size(); ++i) { + const FieldDescriptor* field = (*fields)[i]; + + Family f = OTHER; + if (field->is_repeated()) { + f = REPEATED; + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + f = STRING; + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + f = MESSAGE; + if (IsLazy(field, options)) { + f = LAZY_MESSAGE; + } + } else if (CanInitializeByZeroing(field)) { + f = ZERO_INITIALIZABLE; + } + + const int j = field->number(); + switch (EstimateAlignmentSize(field)) { + case 1: + aligned_to_1[f].push_back(FieldGroup(j, field)); + break; + case 4: + aligned_to_4[f].push_back(FieldGroup(j, field)); + break; + case 8: + aligned_to_8[f].push_back(FieldGroup(j, field)); + break; + default: + GOOGLE_LOG(FATAL) << "Unknown alignment size " << EstimateAlignmentSize(field) + << "for a field " << field->full_name() << "."; + } + } + + // For each family, group fields to optimize padding. + for (int f = 0; f < kMaxFamily; f++) { + // Now group fields aligned to 1 byte into sets of 4, and treat those like a + // single field aligned to 4 bytes. + for (int i = 0; i < aligned_to_1[f].size(); i += 4) { + FieldGroup field_group; + for (int j = i; j < aligned_to_1[f].size() && j < i + 4; ++j) { + field_group.Append(aligned_to_1[f][j]); + } + aligned_to_4[f].push_back(field_group); + } + // Sort by preferred location to keep fields as close to their field number + // order as possible. Using stable_sort ensures that the output is + // consistent across runs. + std::stable_sort(aligned_to_4[f].begin(), aligned_to_4[f].end()); + + // Now group fields aligned to 4 bytes (or the 4-field groups created above) + // into pairs, and treat those like a single field aligned to 8 bytes. + for (int i = 0; i < aligned_to_4[f].size(); i += 2) { + FieldGroup field_group; + for (int j = i; j < aligned_to_4[f].size() && j < i + 2; ++j) { + field_group.Append(aligned_to_4[f][j]); + } + if (i == aligned_to_4[f].size() - 1) { + if (f == OTHER) { + // Move incomplete 4-byte block to the beginning. This is done to + // pair with the (possible) leftover blocks from the + // ZERO_INITIALIZABLE family. + field_group.SetPreferredLocation(-1); + } else { + // Move incomplete 4-byte block to the end. + field_group.SetPreferredLocation(fields->size() + 1); + } + } + aligned_to_8[f].push_back(field_group); + } + // Sort by preferred location. + std::stable_sort(aligned_to_8[f].begin(), aligned_to_8[f].end()); + } + + // Now pull out all the FieldDescriptors in order. + fields->clear(); + for (int f = 0; f < kMaxFamily; ++f) { + for (int i = 0; i < aligned_to_8[f].size(); ++i) { + fields->insert(fields->end(), aligned_to_8[f][i].fields().begin(), + aligned_to_8[f][i].fields().end()); + } + } +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h new file mode 100644 index 0000000000000..2382081babb14 --- /dev/null +++ b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h @@ -0,0 +1,64 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: seongkim@google.com (Seong Beom Kim) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__ + +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +// Rearranges the fields of a message to minimize padding. +// Fields are grouped by the type and the size. +// For example, grouping four boolean fields and one int32 +// field results in zero padding overhead. See OptimizeLayout's +// comment for details. +class PaddingOptimizer : public MessageLayoutHelper { + public: + PaddingOptimizer() {} + ~PaddingOptimizer() override {} + + void OptimizeLayout(std::vector* fields, + const Options& options) override; +}; + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc index 34a41d8232ef5..31f3f0cc0dc5c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc @@ -35,17 +35,13 @@ // worth. #include -#ifndef _SHARED_PTR_H -#include -#endif +#include +#include #include #include -#include #include - -#include -#include +#include #include #include @@ -61,9 +57,8 @@ class TestGenerator : public CodeGenerator { ~TestGenerator() {} virtual bool Generate(const FileDescriptor* file, - const string& parameter, - GeneratorContext* context, - string* error) const { + const std::string& parameter, GeneratorContext* context, + std::string* error) const { TryInsert("test.pb.h", "includes", context); TryInsert("test.pb.h", "namespace_scope", context); TryInsert("test.pb.h", "global_scope", context); @@ -132,7 +127,8 @@ class TestGenerator : public CodeGenerator { // Check field accessors for a message inside oneof{}: TryInsert("test.pb.h", "field_get:foo.Bar.oneOfMessage", context); TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfMessage", context); - TryInsert("test.pb.h", "field_set_allocated:foo.Bar.oneOfMessage", context); + TryInsert("test.pb.cc", "field_set_allocated:foo.Bar.oneOfMessage", + context); // Check field accessors for an optional enum: TryInsert("test.pb.h", "field_get:foo.Bar.optEnum", context); @@ -170,9 +166,10 @@ class TestGenerator : public CodeGenerator { return true; } - void TryInsert(const string& filename, const string& insertion_point, + void TryInsert(const std::string& filename, + const std::string& insertion_point, GeneratorContext* context) const { - google::protobuf::scoped_ptr output( + std::unique_ptr output( context->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); @@ -222,7 +219,7 @@ TEST(CppPluginTest, PluginTest) { "}\n", true)); - google::protobuf::compiler::CommandLineInterface cli; + CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); CppGenerator cpp_generator; @@ -230,17 +227,12 @@ TEST(CppPluginTest, PluginTest) { cli.RegisterGenerator("--cpp_out", &cpp_generator, ""); cli.RegisterGenerator("--test_out", &test_generator, ""); - string proto_path = "-I" + TestTempDir(); - string cpp_out = "--cpp_out=" + TestTempDir(); - string test_out = "--test_out=" + TestTempDir(); - - const char* argv[] = { - "protoc", - proto_path.c_str(), - cpp_out.c_str(), - test_out.c_str(), - "test.proto" - }; + std::string proto_path = "-I" + TestTempDir(); + std::string cpp_out = "--cpp_out=" + TestTempDir(); + std::string test_out = "--test_out=" + TestTempDir(); + + const char* argv[] = {"protoc", proto_path.c_str(), cpp_out.c_str(), + test_out.c_str(), "test.proto"}; EXPECT_EQ(0, cli.Run(5, argv)); } diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc index b05fcc4e3d663..d840492b6873b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -51,48 +51,65 @@ namespace { // returns -1. int FixedSize(FieldDescriptor::Type type) { switch (type) { - case FieldDescriptor::TYPE_INT32 : return -1; - case FieldDescriptor::TYPE_INT64 : return -1; - case FieldDescriptor::TYPE_UINT32 : return -1; - case FieldDescriptor::TYPE_UINT64 : return -1; - case FieldDescriptor::TYPE_SINT32 : return -1; - case FieldDescriptor::TYPE_SINT64 : return -1; - case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; - case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; - case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; - case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; - case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; - case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; - - case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; - case FieldDescriptor::TYPE_ENUM : return -1; - - case FieldDescriptor::TYPE_STRING : return -1; - case FieldDescriptor::TYPE_BYTES : return -1; - case FieldDescriptor::TYPE_GROUP : return -1; - case FieldDescriptor::TYPE_MESSAGE : return -1; - - // No default because we want the compiler to complain if any new - // types are added. + case FieldDescriptor::TYPE_INT32: + return -1; + case FieldDescriptor::TYPE_INT64: + return -1; + case FieldDescriptor::TYPE_UINT32: + return -1; + case FieldDescriptor::TYPE_UINT64: + return -1; + case FieldDescriptor::TYPE_SINT32: + return -1; + case FieldDescriptor::TYPE_SINT64: + return -1; + case FieldDescriptor::TYPE_FIXED32: + return WireFormatLite::kFixed32Size; + case FieldDescriptor::TYPE_FIXED64: + return WireFormatLite::kFixed64Size; + case FieldDescriptor::TYPE_SFIXED32: + return WireFormatLite::kSFixed32Size; + case FieldDescriptor::TYPE_SFIXED64: + return WireFormatLite::kSFixed64Size; + case FieldDescriptor::TYPE_FLOAT: + return WireFormatLite::kFloatSize; + case FieldDescriptor::TYPE_DOUBLE: + return WireFormatLite::kDoubleSize; + + case FieldDescriptor::TYPE_BOOL: + return WireFormatLite::kBoolSize; + case FieldDescriptor::TYPE_ENUM: + return -1; + + case FieldDescriptor::TYPE_STRING: + return -1; + case FieldDescriptor::TYPE_BYTES: + return -1; + case FieldDescriptor::TYPE_GROUP: + return -1; + case FieldDescriptor::TYPE_MESSAGE: + return -1; + + // No default because we want the compiler to complain if any new + // types are added. } GOOGLE_LOG(FATAL) << "Can't get here."; return -1; } void SetPrimitiveVariables(const FieldDescriptor* descriptor, - std::map* variables, + std::map* variables, const Options& options) { SetCommonFieldVariables(descriptor, variables, options); - (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type()); - (*variables)["default"] = DefaultValue(descriptor); - (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); + (*variables)["type"] = PrimitiveTypeName(options, descriptor->cpp_type()); + (*variables)["default"] = DefaultValue(options, descriptor); + (*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor)); int fixed_size = FixedSize(descriptor->type()); if (fixed_size != -1) { - (*variables)["fixed_size"] = SimpleItoa(fixed_size); + (*variables)["fixed_size"] = StrCat(fixed_size); } - (*variables)["wire_format_field_type"] = - "::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name( - static_cast(descriptor->type())); + (*variables)["wire_format_field_type"] = FieldDescriptorProto_Type_Name( + static_cast(descriptor->type())); (*variables)["full_name"] = descriptor->full_name(); } @@ -102,169 +119,171 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, PrimitiveFieldGenerator::PrimitiveFieldGenerator( const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), descriptor_(descriptor) { + : FieldGenerator(descriptor, options) { SetPrimitiveVariables(descriptor, &variables_, options); } PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} -void PrimitiveFieldGenerator:: -GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, "$type$ $name$_;\n"); -} - -void PrimitiveFieldGenerator:: -GenerateAccessorDeclarations(io::Printer* printer) const { - printer->Print(variables_, "$deprecated_attr$$type$ $name$() const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$set_$name$$}$($type$ value);\n"); - printer->Annotate("{", "}", descriptor_); -} - -void PrimitiveFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const { - std::map variables(variables_); - variables["inline"] = is_inline ? "inline " : ""; - printer->Print(variables, - "$inline$$type$ $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_;\n" - "}\n" - "$inline$void $classname$::set_$name$($type$ value) {\n" - " $set_hasbit$\n" - " $name$_ = value;\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n"); -} - -void PrimitiveFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $default$;\n"); -} - -void PrimitiveFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "set_$name$(from.$name$());\n"); +void PrimitiveFieldGenerator::GeneratePrivateMembers( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$type$ $name$_;\n"); +} + +void PrimitiveFieldGenerator::GenerateAccessorDeclarations( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "$deprecated_attr$$type$ ${1$$name$$}$() const;\n" + "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n" + "private:\n" + "$type$ ${1$_internal_$name$$}$() const;\n" + "void ${1$_internal_set_$name$$}$($type$ value);\n" + "public:\n", + descriptor_); +} + +void PrimitiveFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "inline $type$ $classname$::_internal_$name$() const {\n" + " return $name$_;\n" + "}\n" + "inline $type$ $classname$::$name$() const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return _internal_$name$();\n" + "}\n" + "inline void $classname$::_internal_set_$name$($type$ value) {\n" + " $set_hasbit$\n" + " $name$_ = value;\n" + "}\n" + "inline void $classname$::set_$name$($type$ value) {\n" + "$annotate_accessor$" + " _internal_set_$name$(value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + "}\n"); } -void PrimitiveFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "swap($name$_, other->$name$_);\n"); +void PrimitiveFieldGenerator::GenerateClearingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_ = $default$;\n"); } -void PrimitiveFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $default$;\n"); +void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("_internal_set_$name$(from._internal_$name$());\n"); } -void PrimitiveFieldGenerator:: -GenerateCopyConstructorCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = from.$name$_;\n"); +void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("swap($name$_, other->$name$_);\n"); } -void PrimitiveFieldGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "$set_hasbit$\n" - "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" - " $type$, $wire_format_field_type$>(\n" - " input, &$name$_)));\n"); +void PrimitiveFieldGenerator::GenerateConstructorCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_ = $default$;\n"); } -void PrimitiveFieldGenerator:: -GenerateSerializeWithCachedSizes(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::internal::WireFormatLite::Write$declared_type$(" - "$number$, this->$name$(), output);\n"); +void PrimitiveFieldGenerator::GenerateCopyConstructorCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_ = from.$name$_;\n"); } -void PrimitiveFieldGenerator:: -GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(" - "$number$, this->$name$(), target);\n"); +void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "target = stream->EnsureSpace(target);\n" + "target = " + "::$proto_ns$::internal::WireFormatLite::Write$declared_type$ToArray(" + "$number$, this->_internal_$name$(), target);\n"); } -void PrimitiveFieldGenerator:: -GenerateByteSize(io::Printer* printer) const { +void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const { + Formatter format(printer, variables_); int fixed_size = FixedSize(descriptor_->type()); if (fixed_size == -1) { - printer->Print(variables_, - "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" - " this->$name$());\n"); + format( + "total_size += $tag_size$ +\n" + " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n" + " this->_internal_$name$());\n"); } else { - printer->Print(variables_, - "total_size += $tag_size$ + $fixed_size$;\n"); + format("total_size += $tag_size$ + $fixed_size$;\n"); } } +void PrimitiveFieldGenerator::GenerateConstinitInitializer( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_($default$)"); +} + // =================================================================== -PrimitiveOneofFieldGenerator:: -PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : PrimitiveFieldGenerator(descriptor, options) { +PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator( + const FieldDescriptor* descriptor, const Options& options) + : PrimitiveFieldGenerator(descriptor, options) { SetCommonOneofFieldVariables(descriptor, &variables_); } PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {} -void PrimitiveOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const { - std::map variables(variables_); - variables["inline"] = is_inline ? "inline " : ""; - printer->Print(variables, - "$inline$$type$ $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " if (has_$name$()) {\n" - " return $oneof_prefix$$name$_;\n" - " }\n" - " return $default$;\n" - "}\n" - "$inline$void $classname$::set_$name$($type$ value) {\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " }\n" - " $oneof_prefix$$name$_ = value;\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n"); +void PrimitiveOneofFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "inline $type$ $classname$::_internal_$name$() const {\n" + " if (_internal_has_$name$()) {\n" + " return $field_member$;\n" + " }\n" + " return $default$;\n" + "}\n" + "inline void $classname$::_internal_set_$name$($type$ value) {\n" + " if (!_internal_has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " }\n" + " $field_member$ = value;\n" + "}\n" + "inline $type$ $classname$::$name$() const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return _internal_$name$();\n" + "}\n" + "inline void $classname$::set_$name$($type$ value) {\n" + "$annotate_accessor$" + " _internal_set_$name$(value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + "}\n"); } -void PrimitiveOneofFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n"); +void PrimitiveOneofFieldGenerator::GenerateClearingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$field_member$ = $default$;\n"); } -void PrimitiveOneofFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { +void PrimitiveOneofFieldGenerator::GenerateSwappingCode( + io::Printer* printer) const { // Don't print any swapping code. Swapping the union will swap this field. } -void PrimitiveOneofFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { - printer->Print( - variables_, - "_$classname$_default_instance_.$name$_ = $default$;\n"); -} - -void PrimitiveOneofFieldGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "clear_$oneof_name$();\n" - "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" - " $type$, $wire_format_field_type$>(\n" - " input, &$oneof_prefix$$name$_)));\n" - "set_has_$name$();\n"); +void PrimitiveOneofFieldGenerator::GenerateConstructorCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n"); } // =================================================================== RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), descriptor_(descriptor) { + : FieldGenerator(descriptor, options) { SetPrimitiveVariables(descriptor, &variables_, options); if (descriptor->is_packed()) { @@ -278,208 +297,193 @@ RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} -void RepeatedPrimitiveFieldGenerator:: -GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::RepeatedField< $type$ > $name$_;\n"); +void RepeatedPrimitiveFieldGenerator::GeneratePrivateMembers( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n"); if (descriptor_->is_packed() && HasGeneratedMethods(descriptor_->file(), options_)) { - printer->Print(variables_, - "mutable int _$name$_cached_byte_size_;\n"); + format("mutable std::atomic _$name$_cached_byte_size_;\n"); } } -void RepeatedPrimitiveFieldGenerator:: -GenerateAccessorDeclarations(io::Printer* printer) const { - printer->Print(variables_, - "$deprecated_attr$$type$ $name$(int index) const;\n"); - printer->Annotate("name", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$void ${$set_$name$$}$(int index, $type$ value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$add_$name$$}$($type$ value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$const ::google::protobuf::RepeatedField< $type$ >&\n" - " $name$() const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$::google::protobuf::RepeatedField< $type$ >*\n" - " ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); -} - -void RepeatedPrimitiveFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const { - std::map variables(variables_); - variables["inline"] = is_inline ? "inline " : ""; - printer->Print(variables, - "$inline$$type$ $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_.Get(index);\n" - "}\n" - "$inline$void $classname$::set_$name$(int index, $type$ value) {\n" - " $name$_.Set(index, value);\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n" - "$inline$void $classname$::add_$name$($type$ value) {\n" - " $name$_.Add(value);\n" - " // @@protoc_insertion_point(field_add:$full_name$)\n" - "}\n" - "$inline$const ::google::protobuf::RepeatedField< $type$ >&\n" - "$classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_list:$full_name$)\n" - " return $name$_;\n" - "}\n" - "$inline$::google::protobuf::RepeatedField< $type$ >*\n" - "$classname$::mutable_$name$() {\n" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - " return &$name$_;\n" - "}\n"); +void RepeatedPrimitiveFieldGenerator::GenerateAccessorDeclarations( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "private:\n" + "$type$ ${1$_internal_$name$$}$(int index) const;\n" + "const ::$proto_ns$::RepeatedField< $type$ >&\n" + " ${1$_internal_$name$$}$() const;\n" + "void ${1$_internal_add_$name$$}$($type$ value);\n" + "::$proto_ns$::RepeatedField< $type$ >*\n" + " ${1$_internal_mutable_$name$$}$();\n" + "public:\n" + "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n" + "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n" + "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n" + "$deprecated_attr$const ::$proto_ns$::RepeatedField< $type$ >&\n" + " ${1$$name$$}$() const;\n" + "$deprecated_attr$::$proto_ns$::RepeatedField< $type$ >*\n" + " ${1$mutable_$name$$}$();\n", + descriptor_); +} + +void RepeatedPrimitiveFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "inline $type$ $classname$::_internal_$name$(int index) const {\n" + " return $name$_.Get(index);\n" + "}\n" + "inline $type$ $classname$::$name$(int index) const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return _internal_$name$(index);\n" + "}\n" + "inline void $classname$::set_$name$(int index, $type$ value) {\n" + "$annotate_accessor$" + " $name$_.Set(index, value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + "}\n" + "inline void $classname$::_internal_add_$name$($type$ value) {\n" + " $name$_.Add(value);\n" + "}\n" + "inline void $classname$::add_$name$($type$ value) {\n" + "$annotate_accessor$" + " _internal_add_$name$(value);\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" + "}\n" + "inline const ::$proto_ns$::RepeatedField< $type$ >&\n" + "$classname$::_internal_$name$() const {\n" + " return $name$_;\n" + "}\n" + "inline const ::$proto_ns$::RepeatedField< $type$ >&\n" + "$classname$::$name$() const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_list:$full_name$)\n" + " return _internal_$name$();\n" + "}\n" + "inline ::$proto_ns$::RepeatedField< $type$ >*\n" + "$classname$::_internal_mutable_$name$() {\n" + " return &$name$_;\n" + "}\n" + "inline ::$proto_ns$::RepeatedField< $type$ >*\n" + "$classname$::mutable_$name$() {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" + " return _internal_mutable_$name$();\n" + "}\n"); } -void RepeatedPrimitiveFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Clear();\n"); +void RepeatedPrimitiveFieldGenerator::GenerateClearingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.Clear();\n"); } -void RepeatedPrimitiveFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); +void RepeatedPrimitiveFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.MergeFrom(from.$name$_);\n"); } -void RepeatedPrimitiveFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n"); +void RepeatedPrimitiveFieldGenerator::GenerateSwappingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.InternalSwap(&other->$name$_);\n"); } -void RepeatedPrimitiveFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { +void RepeatedPrimitiveFieldGenerator::GenerateConstructorCode( + io::Printer* printer) const { // Not needed for repeated fields. } -void RepeatedPrimitiveFieldGenerator:: -GenerateCopyConstructorCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.CopyFrom(from.$name$_);\n"); +void RepeatedPrimitiveFieldGenerator::GenerateCopyConstructorCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.CopyFrom(from.$name$_);\n"); } -void RepeatedPrimitiveFieldGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n" - " $type$, $wire_format_field_type$>(\n" - " $tag_size$, $tag$u, input, this->mutable_$name$())));\n"); -} - -void RepeatedPrimitiveFieldGenerator:: -GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { - printer->Print(variables_, - "DO_((::google::protobuf::internal::WireFormatLite::$packed_reader$<\n" - " $type$, $wire_format_field_type$>(\n" - " input, this->mutable_$name$())));\n"); -} - -void RepeatedPrimitiveFieldGenerator:: -GenerateSerializeWithCachedSizes(io::Printer* printer) const { - bool array_written = false; +void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const { + Formatter format(printer, variables_); if (descriptor_->is_packed()) { - // Write the tag and the size. - printer->Print(variables_, - "if (this->$name$_size() > 0) {\n" - " ::google::protobuf::internal::WireFormatLite::WriteTag(" - "$number$, " - "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, " - "output);\n" - " output->WriteVarint32(static_cast< ::google::protobuf::uint32>(\n" - " _$name$_cached_byte_size_));\n"); - if (FixedSize(descriptor_->type()) > 0) { - // TODO(ckennelly): Use RepeatedField::unsafe_data() via - // WireFormatLite to access the contents of this->$name$_ to save a branch - // here. - printer->Print(variables_, - " ::google::protobuf::internal::WireFormatLite::Write$declared_type$Array(\n" - " this->$name$().data(), this->$name$_size(), output);\n"); - array_written = true; // Wrote array all at once - } - printer->Print(variables_, "}\n"); - } - if (!array_written) { - printer->Print(variables_, - "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n"); - if (descriptor_->is_packed()) { - printer->Print(variables_, - " ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n" - " this->$name$(i), output);\n"); + format( + "if (this->_internal_$name$_size() > 0) {\n" + " target = stream->WriteFixedPacked($number$, _internal_$name$(), " + "target);\n" + "}\n"); } else { - printer->Print(variables_, - " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" - " $number$, this->$name$(i), output);\n"); + format( + "{\n" + " int byte_size = " + "_$name$_cached_byte_size_.load(std::memory_order_relaxed);\n" + " if (byte_size > 0) {\n" + " target = stream->Write$declared_type$Packed(\n" + " $number$, _internal_$name$(), byte_size, target);\n" + " }\n" + "}\n"); } - printer->Print("}\n"); - } -} - -void RepeatedPrimitiveFieldGenerator:: -GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - if (descriptor_->is_packed()) { - // Write the tag and the size. - printer->Print(variables_, - "if (this->$name$_size() > 0) {\n" - " target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n" - " $number$,\n" - " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" - " target);\n" - " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n" - " static_cast< ::google::protobuf::uint32>(\n" - " _$name$_cached_byte_size_), target);\n" - " target = ::google::protobuf::internal::WireFormatLite::\n" - " Write$declared_type$NoTagToArray(this->$name$_, target);\n" - "}\n"); } else { - printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormatLite::\n" - " Write$declared_type$ToArray($number$, this->$name$_, target);\n"); + format( + "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n" + " target = stream->EnsureSpace(target);\n" + " target = ::$proto_ns$::internal::WireFormatLite::" + "Write$declared_type$ToArray($number$, this->_internal_$name$(i), " + "target);\n" + "}\n"); } } -void RepeatedPrimitiveFieldGenerator:: -GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, "{\n"); - printer->Indent(); +void RepeatedPrimitiveFieldGenerator::GenerateByteSize( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("{\n"); + format.Indent(); int fixed_size = FixedSize(descriptor_->type()); if (fixed_size == -1) { - printer->Print(variables_, - "size_t data_size = ::google::protobuf::internal::WireFormatLite::\n" - " $declared_type$Size(this->$name$_);\n"); + format( + "size_t data_size = ::$proto_ns$::internal::WireFormatLite::\n" + " $declared_type$Size(this->$name$_);\n"); } else { - printer->Print(variables_, - "unsigned int count = static_cast(this->$name$_size());\n" - "size_t data_size = $fixed_size$UL * count;\n"); + format( + "unsigned int count = static_cast(this->_internal_$name$_size());\n" + "size_t data_size = $fixed_size$UL * count;\n"); } if (descriptor_->is_packed()) { - printer->Print(variables_, - "if (data_size > 0) {\n" - " total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormatLite::Int32Size(\n" - " static_cast< ::google::protobuf::int32>(data_size));\n" - "}\n" - "int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n" - "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" - "_$name$_cached_byte_size_ = cached_size;\n" - "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" - "total_size += data_size;\n"); + format( + "if (data_size > 0) {\n" + " total_size += $tag_size$ +\n" + " ::$proto_ns$::internal::WireFormatLite::Int32Size(\n" + " static_cast<$int32$>(data_size));\n" + "}\n" + "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n" + "_$name$_cached_byte_size_.store(cached_size,\n" + " std::memory_order_relaxed);\n" + "total_size += data_size;\n"); } else { - printer->Print(variables_, - "total_size += $tag_size$ *\n" - " ::google::protobuf::internal::FromIntSize(this->$name$_size());\n" - "total_size += data_size;\n"); + format( + "total_size += $tag_size$ *\n" + " " + "::$proto_ns$::internal::FromIntSize(this->_internal_$name$_size());\n" + "total_size += data_size;\n"); + } + format.Outdent(); + format("}\n"); +} + +void RepeatedPrimitiveFieldGenerator::GenerateConstinitInitializer( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_()"); + if (descriptor_->is_packed() && + HasGeneratedMethods(descriptor_->file(), options_)) { + format("\n, _$name$_cached_byte_size_()"); } - printer->Outdent(); - printer->Print("}\n"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h index 44c9ff3ee5318..394b304770fcb 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h @@ -53,21 +53,15 @@ class PrimitiveFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; void GenerateCopyConstructorCode(io::Printer* printer) const; - void GenerateMergeFromCodedStream(io::Printer* printer) const; - void GenerateSerializeWithCachedSizes(io::Printer* printer) const; void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - - protected: - const FieldDescriptor* descriptor_; - std::map variables_; + void GenerateConstinitInitializer(io::Printer* printer) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); @@ -80,12 +74,10 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { ~PrimitiveOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; - void GenerateMergeFromCodedStream(io::Printer* printer) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator); @@ -100,29 +92,23 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; void GenerateCopyConstructorCode(io::Printer* printer) const; - void GenerateMergeFromCodedStream(io::Printer* printer) const; - void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const; - void GenerateSerializeWithCachedSizes(io::Printer* printer) const; void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; + void GenerateConstinitInitializer(io::Printer* printer) const; private: - const FieldDescriptor* descriptor_; - std::map variables_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); }; } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc index 95357d9f43f83..994e653e84097 100644 --- a/src/google/protobuf/compiler/cpp/cpp_service.cc +++ b/src/google/protobuf/compiler/cpp/cpp_service.cc @@ -42,151 +42,147 @@ namespace protobuf { namespace compiler { namespace cpp { -ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor, - const Options& options) - : descriptor_(descriptor) { +namespace { + +void InitMethodVariables(const MethodDescriptor* method, const Options& options, + Formatter* format) { + format->Set("name", method->name()); + format->Set("input_type", QualifiedClassName(method->input_type(), options)); + format->Set("output_type", + QualifiedClassName(method->output_type(), options)); +} + +} // namespace + +ServiceGenerator::ServiceGenerator( + const ServiceDescriptor* descriptor, + const std::map& vars, const Options& options) + : descriptor_(descriptor), vars_(vars), options_(options) { vars_["classname"] = descriptor_->name(); - vars_["file_namespace"] = FileLevelNamespace(descriptor_->file()->name()); vars_["full_name"] = descriptor_->full_name(); - if (options.dllexport_decl.empty()) { - vars_["dllexport"] = ""; - } else { - vars_["dllexport"] = options.dllexport_decl + " "; - } } ServiceGenerator::~ServiceGenerator() {} void ServiceGenerator::GenerateDeclarations(io::Printer* printer) { + Formatter format(printer, vars_); // Forward-declare the stub type. - printer->Print(vars_, - "class $classname$_Stub;\n" - "\n"); + format( + "class $classname$_Stub;\n" + "\n"); GenerateInterface(printer); GenerateStubDefinition(printer); } void ServiceGenerator::GenerateInterface(io::Printer* printer) { - printer->Print(vars_, - "class $dllexport$$classname$ : public ::google::protobuf::Service {\n" - " protected:\n" - " // This class should be treated as an abstract interface.\n" - " inline $classname$() {};\n" - " public:\n" - " virtual ~$classname$();\n"); + Formatter format(printer, vars_); + format( + "class $dllexport_decl $$classname$ : public ::$proto_ns$::Service {\n" + " protected:\n" + " // This class should be treated as an abstract interface.\n" + " inline $classname$() {};\n" + " public:\n" + " virtual ~$classname$();\n"); printer->Indent(); - printer->Print(vars_, - "\n" - "typedef $classname$_Stub Stub;\n" - "\n" - "static const ::google::protobuf::ServiceDescriptor* descriptor();\n" - "\n"); + format( + "\n" + "typedef $classname$_Stub Stub;\n" + "\n" + "static const ::$proto_ns$::ServiceDescriptor* descriptor();\n" + "\n"); GenerateMethodSignatures(VIRTUAL, printer); - printer->Print( - "\n" - "// implements Service ----------------------------------------------\n" - "\n" - "const ::google::protobuf::ServiceDescriptor* GetDescriptor();\n" - "void CallMethod(const ::google::protobuf::MethodDescriptor* method,\n" - " ::google::protobuf::RpcController* controller,\n" - " const ::google::protobuf::Message* request,\n" - " ::google::protobuf::Message* response,\n" - " ::google::protobuf::Closure* done);\n" - "const ::google::protobuf::Message& GetRequestPrototype(\n" - " const ::google::protobuf::MethodDescriptor* method) const;\n" - "const ::google::protobuf::Message& GetResponsePrototype(\n" - " const ::google::protobuf::MethodDescriptor* method) const;\n"); + format( + "\n" + "// implements Service ----------------------------------------------\n" + "\n" + "const ::$proto_ns$::ServiceDescriptor* GetDescriptor();\n" + "void CallMethod(const ::$proto_ns$::MethodDescriptor* method,\n" + " ::$proto_ns$::RpcController* controller,\n" + " const ::$proto_ns$::Message* request,\n" + " ::$proto_ns$::Message* response,\n" + " ::google::protobuf::Closure* done);\n" + "const ::$proto_ns$::Message& GetRequestPrototype(\n" + " const ::$proto_ns$::MethodDescriptor* method) const;\n" + "const ::$proto_ns$::Message& GetResponsePrototype(\n" + " const ::$proto_ns$::MethodDescriptor* method) const;\n"); printer->Outdent(); - printer->Print(vars_, - "\n" - " private:\n" - " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$);\n" - "};\n" - "\n"); + format( + "\n" + " private:\n" + " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$);\n" + "};\n" + "\n"); } void ServiceGenerator::GenerateStubDefinition(io::Printer* printer) { - printer->Print(vars_, - "class $dllexport$$classname$_Stub : public $classname$ {\n" - " public:\n"); + Formatter format(printer, vars_); + format( + "class $dllexport_decl $$classname$_Stub : public $classname$ {\n" + " public:\n"); printer->Indent(); - printer->Print(vars_, - "$classname$_Stub(::google::protobuf::RpcChannel* channel);\n" - "$classname$_Stub(::google::protobuf::RpcChannel* channel,\n" - " ::google::protobuf::Service::ChannelOwnership ownership);\n" - "~$classname$_Stub();\n" - "\n" - "inline ::google::protobuf::RpcChannel* channel() { return channel_; }\n" - "\n" - "// implements $classname$ ------------------------------------------\n" - "\n"); + format( + "$classname$_Stub(::$proto_ns$::RpcChannel* channel);\n" + "$classname$_Stub(::$proto_ns$::RpcChannel* channel,\n" + " ::$proto_ns$::Service::ChannelOwnership ownership);\n" + "~$classname$_Stub();\n" + "\n" + "inline ::$proto_ns$::RpcChannel* channel() { return channel_; }\n" + "\n" + "// implements $classname$ ------------------------------------------\n" + "\n"); GenerateMethodSignatures(NON_VIRTUAL, printer); printer->Outdent(); - printer->Print(vars_, - " private:\n" - " ::google::protobuf::RpcChannel* channel_;\n" - " bool owns_channel_;\n" - " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$_Stub);\n" - "};\n" - "\n"); + format( + " private:\n" + " ::$proto_ns$::RpcChannel* channel_;\n" + " bool owns_channel_;\n" + " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$_Stub);\n" + "};\n" + "\n"); } -void ServiceGenerator::GenerateMethodSignatures( - VirtualOrNon virtual_or_non, io::Printer* printer) { +void ServiceGenerator::GenerateMethodSignatures(VirtualOrNon virtual_or_non, + io::Printer* printer) { for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - std::map sub_vars; - sub_vars["name"] = method->name(); - sub_vars["input_type"] = ClassName(method->input_type(), true); - sub_vars["output_type"] = ClassName(method->output_type(), true); - sub_vars["virtual"] = virtual_or_non == VIRTUAL ? "virtual " : ""; - - printer->Print(sub_vars, - "$virtual$void $name$(::google::protobuf::RpcController* controller,\n" - " const $input_type$* request,\n" - " $output_type$* response,\n" - " ::google::protobuf::Closure* done);\n"); + Formatter format(printer, vars_); + InitMethodVariables(method, options_, &format); + format.Set("virtual", virtual_or_non == VIRTUAL ? "virtual " : ""); + format( + "$virtual$void $name$(::$proto_ns$::RpcController* controller,\n" + " const $input_type$* request,\n" + " $output_type$* response,\n" + " ::google::protobuf::Closure* done);\n"); } } // =================================================================== -void ServiceGenerator::GenerateDescriptorInitializer( - io::Printer* printer, int index) { - std::map vars; - vars["classname"] = descriptor_->name(); - vars["index"] = SimpleItoa(index); - - printer->Print(vars, - "$classname$_descriptor_ = file->service($index$);\n"); -} - -// =================================================================== - void ServiceGenerator::GenerateImplementation(io::Printer* printer) { - vars_["index"] = SimpleItoa(index_in_metadata_); - printer->Print( - vars_, + Formatter format(printer, vars_); + format( "$classname$::~$classname$() {}\n" "\n" - "const ::google::protobuf::ServiceDescriptor* $classname$::descriptor() {\n" - " $file_namespace$::protobuf_AssignDescriptorsOnce();\n" - " return $file_namespace$::file_level_service_descriptors[$index$];\n" + "const ::$proto_ns$::ServiceDescriptor* $classname$::descriptor() {\n" + " " + "::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n" + " return $file_level_service_descriptors$[$1$];\n" "}\n" "\n" - "const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() {\n" + "const ::$proto_ns$::ServiceDescriptor* $classname$::GetDescriptor() {\n" " return descriptor();\n" "}\n" - "\n"); + "\n", + index_in_metadata_); // Generate methods of the interface. GenerateNotImplementedMethods(printer); @@ -195,18 +191,20 @@ void ServiceGenerator::GenerateImplementation(io::Printer* printer) { GenerateGetPrototype(RESPONSE, printer); // Generate stub implementation. - printer->Print(vars_, - "$classname$_Stub::$classname$_Stub(::google::protobuf::RpcChannel* channel)\n" - " : channel_(channel), owns_channel_(false) {}\n" - "$classname$_Stub::$classname$_Stub(\n" - " ::google::protobuf::RpcChannel* channel,\n" - " ::google::protobuf::Service::ChannelOwnership ownership)\n" - " : channel_(channel),\n" - " owns_channel_(ownership == ::google::protobuf::Service::STUB_OWNS_CHANNEL) {}\n" - "$classname$_Stub::~$classname$_Stub() {\n" - " if (owns_channel_) delete channel_;\n" - "}\n" - "\n"); + format( + "$classname$_Stub::$classname$_Stub(::$proto_ns$::RpcChannel* channel)\n" + " : channel_(channel), owns_channel_(false) {}\n" + "$classname$_Stub::$classname$_Stub(\n" + " ::$proto_ns$::RpcChannel* channel,\n" + " ::$proto_ns$::Service::ChannelOwnership ownership)\n" + " : channel_(channel),\n" + " owns_channel_(ownership == " + "::$proto_ns$::Service::STUB_OWNS_CHANNEL) " + "{}\n" + "$classname$_Stub::~$classname$_Stub() {\n" + " if (owns_channel_) delete channel_;\n" + "}\n" + "\n"); GenerateStubMethods(printer); } @@ -214,123 +212,112 @@ void ServiceGenerator::GenerateImplementation(io::Printer* printer) { void ServiceGenerator::GenerateNotImplementedMethods(io::Printer* printer) { for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - std::map sub_vars; - sub_vars["classname"] = descriptor_->name(); - sub_vars["name"] = method->name(); - sub_vars["index"] = SimpleItoa(i); - sub_vars["input_type"] = ClassName(method->input_type(), true); - sub_vars["output_type"] = ClassName(method->output_type(), true); - - printer->Print(sub_vars, - "void $classname$::$name$(::google::protobuf::RpcController* controller,\n" - " const $input_type$*,\n" - " $output_type$*,\n" - " ::google::protobuf::Closure* done) {\n" - " controller->SetFailed(\"Method $name$() not implemented.\");\n" - " done->Run();\n" - "}\n" - "\n"); + Formatter format(printer, vars_); + InitMethodVariables(method, options_, &format); + format( + "void $classname$::$name$(::$proto_ns$::RpcController* controller,\n" + " const $input_type$*,\n" + " $output_type$*,\n" + " ::google::protobuf::Closure* done) {\n" + " controller->SetFailed(\"Method $name$() not implemented.\");\n" + " done->Run();\n" + "}\n" + "\n"); } } void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { - printer->Print( - vars_, - "void $classname$::CallMethod(const ::google::protobuf::MethodDescriptor* method,\n" - " ::google::protobuf::RpcController* controller,\n" - " const ::google::protobuf::Message* request,\n" - " ::google::protobuf::Message* response,\n" + Formatter format(printer, vars_); + format( + "void $classname$::CallMethod(const ::$proto_ns$::MethodDescriptor* " + "method,\n" + " ::$proto_ns$::RpcController* controller,\n" + " const ::$proto_ns$::Message* request,\n" + " ::$proto_ns$::Message* response,\n" " ::google::protobuf::Closure* done) {\n" - " GOOGLE_DCHECK_EQ(method->service(), " - "$file_namespace$::file_level_service_descriptors[$index$]);\n" - " switch(method->index()) {\n"); + " GOOGLE_DCHECK_EQ(method->service(), $file_level_service_descriptors$[$1$]);\n" + " switch(method->index()) {\n", + index_in_metadata_); for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - std::map sub_vars; - sub_vars["name"] = method->name(); - sub_vars["index"] = SimpleItoa(i); - sub_vars["input_type"] = ClassName(method->input_type(), true); - sub_vars["output_type"] = ClassName(method->output_type(), true); + Formatter format(printer, vars_); + InitMethodVariables(method, options_, &format); // Note: down_cast does not work here because it only works on pointers, // not references. - printer->Print(sub_vars, - " case $index$:\n" - " $name$(controller,\n" - " ::google::protobuf::down_cast(request),\n" - " ::google::protobuf::down_cast< $output_type$*>(response),\n" - " done);\n" - " break;\n"); + format( + " case $1$:\n" + " $name$(controller,\n" + " ::$proto_ns$::internal::DownCast(\n" + " request),\n" + " ::$proto_ns$::internal::DownCast<$output_type$*>(\n" + " response),\n" + " done);\n" + " break;\n", + i); } - printer->Print(vars_, - " default:\n" - " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n" - " break;\n" - " }\n" - "}\n" - "\n"); + format( + " default:\n" + " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n" + " break;\n" + " }\n" + "}\n" + "\n"); } void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, io::Printer* printer) { + Formatter format(printer, vars_); if (which == REQUEST) { - printer->Print(vars_, - "const ::google::protobuf::Message& $classname$::GetRequestPrototype(\n"); + format("const ::$proto_ns$::Message& $classname$::GetRequestPrototype(\n"); } else { - printer->Print(vars_, - "const ::google::protobuf::Message& $classname$::GetResponsePrototype(\n"); + format("const ::$proto_ns$::Message& $classname$::GetResponsePrototype(\n"); } - printer->Print(vars_, - " const ::google::protobuf::MethodDescriptor* method) const {\n" - " GOOGLE_DCHECK_EQ(method->service(), descriptor());\n" - " switch(method->index()) {\n"); + format( + " const ::$proto_ns$::MethodDescriptor* method) const {\n" + " GOOGLE_DCHECK_EQ(method->service(), descriptor());\n" + " switch(method->index()) {\n"); for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); const Descriptor* type = - (which == REQUEST) ? method->input_type() : method->output_type(); + (which == REQUEST) ? method->input_type() : method->output_type(); - std::map sub_vars; - sub_vars["index"] = SimpleItoa(i); - sub_vars["type"] = ClassName(type, true); - - printer->Print(sub_vars, - " case $index$:\n" - " return $type$::default_instance();\n"); + format( + " case $1$:\n" + " return $2$::default_instance();\n", + i, QualifiedClassName(type, options_)); } - printer->Print( - " default:\n" - " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n" - " return *::google::protobuf::MessageFactory::generated_factory()\n" - " ->GetPrototype(method->$input_or_output$_type());\n" - " }\n" - "}\n" - "\n", - "input_or_output", which == REQUEST ? "input" : "output"); + format( + " default:\n" + " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n" + " return *::$proto_ns$::MessageFactory::generated_factory()\n" + " ->GetPrototype(method->$1$_type());\n" + " }\n" + "}\n" + "\n", + which == REQUEST ? "input" : "output"); } void ServiceGenerator::GenerateStubMethods(io::Printer* printer) { for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - std::map sub_vars; - sub_vars["classname"] = descriptor_->name(); - sub_vars["name"] = method->name(); - sub_vars["index"] = SimpleItoa(i); - sub_vars["input_type"] = ClassName(method->input_type(), true); - sub_vars["output_type"] = ClassName(method->output_type(), true); - - printer->Print(sub_vars, - "void $classname$_Stub::$name$(::google::protobuf::RpcController* controller,\n" - " const $input_type$* request,\n" - " $output_type$* response,\n" - " ::google::protobuf::Closure* done) {\n" - " channel_->CallMethod(descriptor()->method($index$),\n" - " controller, request, response, done);\n" - "}\n"); + Formatter format(printer, vars_); + InitMethodVariables(method, options_, &format); + format( + "void $classname$_Stub::$name$(::$proto_ns$::RpcController* " + "controller,\n" + " const $input_type$* request,\n" + " $output_type$* response,\n" + " ::google::protobuf::Closure* done) {\n" + " channel_->CallMethod(descriptor()->method($1$),\n" + " controller, request, response, done);\n" + "}\n", + i); } } diff --git a/src/google/protobuf/compiler/cpp/cpp_service.h b/src/google/protobuf/compiler/cpp/cpp_service.h index 33c025476ae4b..63c7ca44f8523 100644 --- a/src/google/protobuf/compiler/cpp/cpp_service.h +++ b/src/google/protobuf/compiler/cpp/cpp_service.h @@ -42,11 +42,13 @@ namespace google { namespace protobuf { - namespace io { - class Printer; // printer.h - } +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace cpp { @@ -55,6 +57,7 @@ class ServiceGenerator { public: // See generator.cc for the meaning of dllexport_decl. explicit ServiceGenerator(const ServiceDescriptor* descriptor, + const std::map& vars, const Options& options); ~ServiceGenerator(); @@ -66,11 +69,8 @@ class ServiceGenerator { // Source file stuff. - // Generate code that initializes the global variable storing the service's - // descriptor. - void GenerateDescriptorInitializer(io::Printer* printer, int index); - - // Generate implementations of everything declared by GenerateDeclarations(). + // Generate implementations of everything declared by + // GenerateDeclarations(). void GenerateImplementation(io::Printer* printer); private: @@ -105,7 +105,8 @@ class ServiceGenerator { void GenerateStubMethods(io::Printer* printer); const ServiceDescriptor* descriptor_; - std::map vars_; + std::map vars_; + const Options& options_; int index_in_metadata_; @@ -116,6 +117,6 @@ class ServiceGenerator { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index fec13b6dd062e..3769437e2269d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -34,11 +34,11 @@ #include #include -#include #include - +#include #include + namespace google { namespace protobuf { namespace compiler { @@ -47,30 +47,53 @@ namespace cpp { namespace { void SetStringVariables(const FieldDescriptor* descriptor, - std::map* variables, + std::map* variables, const Options& options) { SetCommonFieldVariables(descriptor, variables, options); - (*variables)["default"] = DefaultValue(descriptor); + (*variables)["default"] = DefaultValue(options, descriptor); (*variables)["default_length"] = - SimpleItoa(descriptor->default_value_string().length()); - string default_variable_string = "_default_" + FieldName(descriptor) + "_"; + StrCat(descriptor->default_value_string().length()); + std::string default_variable_string = MakeDefaultName(descriptor); (*variables)["default_variable_name"] = default_variable_string; - (*variables)["default_variable"] = + + if (!descriptor->default_value_string().empty()) { + (*variables)["lazy_variable"] = + QualifiedClassName(descriptor->containing_type(), options) + + "::" + default_variable_string; + } + + (*variables)["default_string"] = + descriptor->default_value_string().empty() + ? "::" + (*variables)["proto_ns"] + + "::internal::GetEmptyStringAlreadyInited()" + : (*variables)["lazy_variable"] + ".get()"; + (*variables)["init_value"] = descriptor->default_value_string().empty() - ? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()" - : "&" + (*variables)["classname"] + "::" + default_variable_string + - ".get()"; + ? "&::" + (*variables)["proto_ns"] + + "::internal::GetEmptyStringAlreadyInited()" + : "nullptr"; + (*variables)["default_value_tag"] = + "::" + (*variables)["proto_ns"] + "::internal::ArenaStringPtr::" + + (descriptor->default_value_string().empty() ? "Empty" : "NonEmpty") + + "Default{}"; + (*variables)["default_variable_or_tag"] = + (*variables)[descriptor->default_value_string().empty() + ? "default_value_tag" + : "lazy_variable"]; (*variables)["pointer_type"] = descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char"; - (*variables)["null_check"] = "GOOGLE_DCHECK(value != NULL);\n"; + (*variables)["null_check"] = (*variables)["DCHK"] + "(value != nullptr);\n"; // NOTE: Escaped here to unblock proto1->proto2 migration. // TODO(liujisi): Extend this to apply for other conflicting methods. (*variables)["release_name"] = - SafeFunctionName(descriptor->containing_type(), - descriptor, "release_"); + SafeFunctionName(descriptor->containing_type(), descriptor, "release_"); (*variables)["full_name"] = descriptor->full_name(); - (*variables)["string_piece"] = "::std::string"; + if (options.opensource_runtime) { + (*variables)["string_piece"] = "::std::string"; + } else { + (*variables)["string_piece"] = "::StringPiece"; + } } } // namespace @@ -79,40 +102,29 @@ void SetStringVariables(const FieldDescriptor* descriptor, StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), descriptor_(descriptor) { + : FieldGenerator(descriptor, options) { SetStringVariables(descriptor, &variables_, options); } StringFieldGenerator::~StringFieldGenerator() {} -void StringFieldGenerator:: -GeneratePrivateMembers(io::Printer* printer) const { - // N.B. that we continue to use |ArenaStringPtr| instead of |string*| for - // string fields, even when SupportArenas(descriptor_) == false. Why? - // The simple answer is to avoid unmaintainable complexity. The reflection - // code assumes ArenaStringPtrs. These are *almost* in-memory-compatible with - // string*, except for the pointer tags and related ownership semantics. We - // could modify the runtime code to use string* for the not-supporting-arenas - // case, but this would require a way to detect which type of class was - // generated (adding overhead and complexity to GeneratedMessageReflection) - // and littering the runtime code paths with conditionals. It's simpler to - // stick with this but use lightweight accessors that assume arena == NULL. - // There should be very little overhead anyway because it's just a tagged - // pointer in-memory. - printer->Print(variables_, "::google::protobuf::internal::ArenaStringPtr $name$_;\n"); +void StringFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const { + Formatter format(printer, variables_); + format("::$proto_ns$::internal::ArenaStringPtr $name$_;\n"); } -void StringFieldGenerator:: -GenerateStaticMembers(io::Printer* printer) const { +void StringFieldGenerator::GenerateStaticMembers(io::Printer* printer) const { + Formatter format(printer, variables_); if (!descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "static ::google::protobuf::internal::ExplicitlyConstructed< ::std::string>" - " $default_variable_name$;\n"); + format( + "static const ::$proto_ns$::internal::LazyString" + " $default_variable_name$;\n"); } } -void StringFieldGenerator:: -GenerateAccessorDeclarations(io::Printer* printer) const { +void StringFieldGenerator::GenerateAccessorDeclarations( + io::Printer* printer) const { + Formatter format(printer, variables_); // If we're using StringFieldGenerator for a field with a ctype, it's // because that ctype isn't actually implemented. In particular, this is // true of ctype=CORD and ctype=STRING_PIECE in the open source release. @@ -130,968 +142,696 @@ GenerateAccessorDeclarations(io::Printer* printer) const { // reflection interface since the reflection interface is independent of // the string's underlying representation. - bool unknown_ctype = - descriptor_->options().ctype() != EffectiveStringCType(descriptor_); + bool unknown_ctype = descriptor_->options().ctype() != + EffectiveStringCType(descriptor_, options_); if (unknown_ctype) { - printer->Outdent(); - printer->Print( - " private:\n" - " // Hidden due to unknown ctype option.\n"); - printer->Indent(); + format.Outdent(); + format( + " private:\n" + " // Hidden due to unknown ctype option.\n"); + format.Indent(); } - printer->Print(variables_, - "$deprecated_attr$const ::std::string& $name$() const;\n"); - printer->Annotate("name", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$void ${$set_$name$$}$(const ::std::string& value);\n"); - printer->Annotate("{", "}", descriptor_); - - printer->Print(variables_, - "#if LANG_CXX11\n" - "$deprecated_attr$void ${$set_$name$$}$(::std::string&& value);\n" - "#endif\n"); - printer->Annotate("{", "}", descriptor_); - - printer->Print( - variables_, - "$deprecated_attr$void ${$set_$name$$}$(const char* value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$set_$name$$}$(const $pointer_type$* " - "value, size_t size)" - ";\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$::std::string* ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, "$deprecated_attr$::std::string* $release_name$();\n"); - printer->Annotate("release_name", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$void ${$set_allocated_$name$$}$(::std::string* $name$);\n"); - printer->Annotate("{", "}", descriptor_); - if (SupportsArenas(descriptor_)) { - printer->Print( - variables_, - "$deprecated_attr$::std::string* ${$unsafe_arena_release_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$void ${$unsafe_arena_set_allocated_$name$$}$(\n" - " ::std::string* $name$);\n"); - printer->Annotate("{", "}", descriptor_); + format( + "$deprecated_attr$const std::string& ${1$$name$$}$() const;\n" + "$deprecated_attr$void ${1$set_$name$$}$(const std::string& value);\n" + "$deprecated_attr$void ${1$set_$name$$}$(std::string&& value);\n" + "$deprecated_attr$void ${1$set_$name$$}$(const char* value);\n", + descriptor_); + if (!options_.opensource_runtime) { + format( + "$deprecated_attr$void ${1$set_$name$$}$(::StringPiece value);\n", + descriptor_); } - + format( + "$deprecated_attr$void ${1$set_$name$$}$(const $pointer_type$* " + "value, size_t size)" + ";\n" + "$deprecated_attr$std::string* ${1$mutable_$name$$}$();\n" + "$deprecated_attr$std::string* ${1$$release_name$$}$();\n" + "$deprecated_attr$void ${1$set_allocated_$name$$}$(std::string* " + "$name$);\n", + descriptor_); + format( + "private:\n" + "const std::string& _internal_$name$() const;\n" + "void _internal_set_$name$(const std::string& value);\n" + "std::string* _internal_mutable_$name$();\n" + "public:\n"); if (unknown_ctype) { - printer->Outdent(); - printer->Print(" public:\n"); - printer->Indent(); + format.Outdent(); + format(" public:\n"); + format.Indent(); } } -void StringFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const { - std::map variables(variables_); - variables["inline"] = is_inline ? "inline " : ""; - if (SupportsArenas(descriptor_)) { - printer->Print( - variables, - "$inline$const ::std::string& $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_.Get();\n" - "}\n" - "$inline$void $classname$::set_$name$(const ::std::string& value) {\n" - " $set_hasbit$\n" - " $name$_.Set($default_variable$, value, GetArenaNoVirtual());\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n" - "#if LANG_CXX11\n" - "$inline$void $classname$::set_$name$(::std::string&& value) {\n" - " $set_hasbit$\n" - " $name$_.Set(\n" - " $default_variable$, ::std::move(value), GetArenaNoVirtual());\n" - " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" - "}\n" - "#endif\n" - "$inline$void $classname$::set_$name$(const char* value) {\n" - " $null_check$" - " $set_hasbit$\n" - " $name$_.Set($default_variable$, $string_piece$(value),\n" - " GetArenaNoVirtual());\n" - " // @@protoc_insertion_point(field_set_char:$full_name$)\n" - "}\n" - "$inline$" - "void $classname$::set_$name$(const $pointer_type$* value,\n" - " size_t size) {\n" - " $set_hasbit$\n" - " $name$_.Set($default_variable$, $string_piece$(\n" - " reinterpret_cast(value), size), " - "GetArenaNoVirtual());\n" - " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" - "}\n" - "$inline$::std::string* $classname$::mutable_$name$() {\n" +void StringFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "inline const std::string& $classname$::$name$() const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_get:$full_name$)\n"); + if (!descriptor_->default_value_string().empty()) { + format( + " if ($name$_.IsDefault(nullptr)) return " + "$default_variable_name$.get();\n"); + } + format( + " return _internal_$name$();\n" + "}\n" + "inline void $classname$::set_$name$(const std::string& value) {\n" + "$annotate_accessor$" + " _internal_set_$name$(value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + "}\n" + "inline std::string* $classname$::mutable_$name$() {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + " return _internal_mutable_$name$();\n" + "}\n" + "inline const std::string& $classname$::_internal_$name$() const {\n" + " return $name$_.Get();\n" + "}\n" + "inline void $classname$::_internal_set_$name$(const std::string& " + "value) {\n" + " $set_hasbit$\n" + " $name$_.Set($default_value_tag$, value, GetArena());\n" + "}\n" + "inline void $classname$::set_$name$(std::string&& value) {\n" + "$annotate_accessor$" + " $set_hasbit$\n" + " $name$_.Set(\n" + " $default_value_tag$, ::std::move(value), GetArena());\n" + " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" + "}\n" + "inline void $classname$::set_$name$(const char* value) {\n" + "$annotate_accessor$" + " $null_check$" + " $set_hasbit$\n" + " $name$_.Set($default_value_tag$, $string_piece$(value), GetArena());\n" + " // @@protoc_insertion_point(field_set_char:$full_name$)\n" + "}\n"); + if (!options_.opensource_runtime) { + format( + "inline void $classname$::set_$name$(::StringPiece value) {\n" + "$annotate_accessor$" " $set_hasbit$\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n" - "}\n" - "$inline$::std::string* $classname$::$release_name$() {\n" - " // @@protoc_insertion_point(field_release:$full_name$)\n" - " $clear_hasbit$\n" - " return $name$_.Release($default_variable$, GetArenaNoVirtual());\n" - "}\n" - "$inline$::std::string* $classname$::unsafe_arena_release_$name$() {\n" - " // " - "@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n" - " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" - " $clear_hasbit$\n" - " return $name$_.UnsafeArenaRelease($default_variable$,\n" - " GetArenaNoVirtual());\n" - "}\n" - "$inline$void $classname$::set_allocated_$name$(::std::string* $name$) {\n" - " if ($name$ != NULL) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" - " }\n" - " $name$_.SetAllocated($default_variable$, $name$,\n" - " GetArenaNoVirtual());\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n" - "$inline$void $classname$::unsafe_arena_set_allocated_$name$(\n" - " ::std::string* $name$) {\n" - " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" - " if ($name$ != NULL) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" - " }\n" - " $name$_.UnsafeArenaSetAllocated($default_variable$,\n" - " $name$, GetArenaNoVirtual());\n" - " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" - "$full_name$)\n" + " $name$_.Set($default_value_tag$, value,GetArena());\n" + " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" "}\n"); - } else { - // No-arena case. - printer->Print( - variables, - "$inline$const ::std::string& $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_.GetNoArena();\n" - "}\n" - "$inline$void $classname$::set_$name$(const ::std::string& value) {\n" - " $set_hasbit$\n" - " $name$_.SetNoArena($default_variable$, value);\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n" - "#if LANG_CXX11\n" - "$inline$void $classname$::set_$name$(::std::string&& value) {\n" - " $set_hasbit$\n" - " $name$_.SetNoArena(\n" - " $default_variable$, ::std::move(value));\n" - " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" - "}\n" - "#endif\n" - "$inline$void $classname$::set_$name$(const char* value) {\n" - " $null_check$" - " $set_hasbit$\n" - " $name$_.SetNoArena($default_variable$, $string_piece$(value));\n" - " // @@protoc_insertion_point(field_set_char:$full_name$)\n" - "}\n" - "$inline$" - "void $classname$::set_$name$(const $pointer_type$* value, " - "size_t size) {\n" - " $set_hasbit$\n" - " $name$_.SetNoArena($default_variable$,\n" - " $string_piece$(reinterpret_cast(value), size));\n" - " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" - "}\n" - "$inline$::std::string* $classname$::mutable_$name$() {\n" - " $set_hasbit$\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $name$_.MutableNoArena($default_variable$);\n" - "}\n" - "$inline$::std::string* $classname$::$release_name$() {\n" - " // @@protoc_insertion_point(field_release:$full_name$)\n" - " $clear_hasbit$\n" - " return $name$_.ReleaseNoArena($default_variable$);\n" - "}\n" - "$inline$void $classname$::set_allocated_$name$(::std::string* $name$) {\n" - " if ($name$ != NULL) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" + } + format( + "inline " + "void $classname$::set_$name$(const $pointer_type$* value,\n" + " size_t size) {\n" + "$annotate_accessor$" + " $set_hasbit$\n" + " $name$_.Set($default_value_tag$, $string_piece$(\n" + " reinterpret_cast(value), size), GetArena());\n" + " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" + "}\n" + "inline std::string* $classname$::_internal_mutable_$name$() {\n" + " $set_hasbit$\n" + " return $name$_.Mutable($default_variable_or_tag$, GetArena());\n" + "}\n" + "inline std::string* $classname$::$release_name$() {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_release:$full_name$)\n"); + + if (HasHasbit(descriptor_)) { + format( + " if (!_internal_has_$name$()) {\n" + " return nullptr;\n" " }\n" - " $name$_.SetAllocatedNoArena($default_variable$, $name$);\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n"); + " $clear_hasbit$\n" + " return $name$_.ReleaseNonDefault($init_value$, GetArena());\n"); + } else { + format(" return $name$_.Release($init_value$, GetArena());\n"); } + + format( + "}\n" + "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n" + "$annotate_accessor$" + " if ($name$ != nullptr) {\n" + " $set_hasbit$\n" + " } else {\n" + " $clear_hasbit$\n" + " }\n" + " $name$_.SetAllocated($init_value$, $name$,\n" + " GetArena());\n" + " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + "}\n"); } -void StringFieldGenerator:: -GenerateNonInlineAccessorDefinitions(io::Printer* printer) const { +void StringFieldGenerator::GenerateNonInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); if (!descriptor_->default_value_string().empty()) { - // Initialized in GenerateDefaultInstanceAllocator. - printer->Print(variables_, - "::google::protobuf::internal::ExplicitlyConstructed< ::std::string> " - "$classname$::$default_variable_name$;\n"); + format( + "const ::$proto_ns$::internal::LazyString " + "$classname$::$default_variable_name$" + "{{{$default$, $default_length$}}, {nullptr}};\n"); } } -void StringFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - // Two-dimension specialization here: supporting arenas or not, and default - // value is the empty string or not. Complexity here ensures the minimal - // number of branches / amount of extraneous code at runtime (given that the - // below methods are inlined one-liners)! - if (SupportsArenas(descriptor_)) { - if (descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "$name$_.ClearToEmpty($default_variable$, GetArenaNoVirtual());\n"); - } else { - printer->Print(variables_, - "$name$_.ClearToDefault($default_variable$, GetArenaNoVirtual());\n"); - } +void StringFieldGenerator::GenerateClearingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + if (descriptor_->default_value_string().empty()) { + format("$name$_.ClearToEmpty();\n"); } else { - if (descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "$name$_.ClearToEmptyNoArena($default_variable$);\n"); - } else { - printer->Print(variables_, - "$name$_.ClearToDefaultNoArena($default_variable$);\n"); - } + format("$name$_.ClearToDefault($lazy_variable$, GetArena());\n"); } } -void StringFieldGenerator:: -GenerateMessageClearingCode(io::Printer* printer) const { +void StringFieldGenerator::GenerateMessageClearingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); // Two-dimension specialization here: supporting arenas, field presence, or // not, and default value is the empty string or not. Complexity here ensures // the minimal number of branches / amount of extraneous code at runtime // (given that the below methods are inlined one-liners)! - // If we have field presence, then the Clear() method of the protocol buffer + // If we have a hasbit, then the Clear() method of the protocol buffer // will have checked that this field is set. If so, we can avoid redundant - // checks against default_variable. - const bool must_be_present = HasFieldPresence(descriptor_->file()); + // checks against the default variable. + const bool must_be_present = HasHasbit(descriptor_); - if (must_be_present) { - printer->Print(variables_, - "GOOGLE_DCHECK(!$name$_.IsDefault($default_variable$));\n"); - } - - if (SupportsArenas(descriptor_)) { - if (descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "$name$_.ClearToEmpty($default_variable$, GetArenaNoVirtual());\n"); + if (descriptor_->default_value_string().empty()) { + if (must_be_present) { + format("$name$_.ClearNonDefaultToEmpty();\n"); } else { - printer->Print(variables_, - "$name$_.ClearToDefault($default_variable$, GetArenaNoVirtual());\n"); - } - } else if (must_be_present) { - // When Arenas are disabled and field presence has been checked, we can - // safely treat the ArenaStringPtr as a string*. - if (descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "(*$name$_.UnsafeRawStringPointer())->clear();\n"); - } else { - printer->Print(variables_, - "(*$name$_.UnsafeRawStringPointer())->assign(*$default_variable$);\n"); + format("$name$_.ClearToEmpty();\n"); } } else { - if (descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "$name$_.ClearToEmptyNoArena($default_variable$);\n"); - } else { - printer->Print(variables_, - "$name$_.ClearToDefaultNoArena($default_variable$);\n"); - } + // Clear to a non-empty default is more involved, as we try to use the + // Arena if one is present and may need to reallocate the string. + format("$name$_.ClearToDefault($lazy_variable$, GetArena());\n "); } } -void StringFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) { - // TODO(gpike): improve this - printer->Print(variables_, "set_$name$(from.$name$());\n"); - } else { - printer->Print(variables_, - "$set_hasbit$\n" - "$name$_.AssignWithDefault($default_variable$, from.$name$_);\n"); - } +void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + // TODO(gpike): improve this + format("_internal_set_$name$(from._internal_$name$());\n"); } -void StringFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n"); +void StringFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.Swap(&other->$name$_, $init_value$, GetArena());\n"); } -void StringFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_.UnsafeSetDefault($default_variable$);\n"); +void StringFieldGenerator::GenerateConstructorCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.UnsafeSetDefault($init_value$);\n"); } -void StringFieldGenerator:: -GenerateCopyConstructorCode(io::Printer* printer) const { +void StringFieldGenerator::GenerateCopyConstructorCode( + io::Printer* printer) const { + Formatter format(printer, variables_); GenerateConstructorCode(printer); - if (HasFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "if (from.has_$name$()) {\n"); + if (HasHasbit(descriptor_)) { + format("if (from._internal_has_$name$()) {\n"); } else { - printer->Print(variables_, - "if (from.$name$().size() > 0) {\n"); + format("if (!from._internal_$name$().empty()) {\n"); } - printer->Indent(); + format.Indent(); - if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) { - // TODO(gpike): improve this - printer->Print(variables_, - "$name$_.Set($default_variable$, from.$name$(),\n" - " GetArenaNoVirtual());\n"); - } else { - printer->Print(variables_, - "$name$_.AssignWithDefault($default_variable$, from.$name$_);\n"); - } + // TODO(gpike): improve this + format( + "$name$_.Set($default_value_tag$, from._internal_$name$(), \n" + " GetArena());\n"); - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } -void StringFieldGenerator:: -GenerateDestructorCode(io::Printer* printer) const { - if (SupportsArenas(descriptor_)) { - // The variable |arena| is defined by the enclosing code. - // See MessageGenerator::GenerateSharedDestructorCode. - printer->Print(variables_, - "$name$_.Destroy($default_variable$, arena);\n"); - } else { - printer->Print(variables_, - "$name$_.DestroyNoArena($default_variable$);\n"); - } +void StringFieldGenerator::GenerateDestructorCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.DestroyNoArena($init_value$);\n"); } -void StringFieldGenerator:: -GenerateDefaultInstanceAllocator(io::Printer* printer) const { - if (!descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "$classname$::$default_variable_name$.DefaultConstruct();\n" - "*$classname$::$default_variable_name$.get_mutable() = " - "::std::string($default$, $default_length$);\n" - "::google::protobuf::internal::OnShutdownDestroyString(\n" - " $classname$::$default_variable_name$.get_mutable());\n" - ); - } -} - -void StringFieldGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" - " input, this->mutable_$name$()));\n"); - +void StringFieldGenerator::GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const { + Formatter format(printer, variables_); if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, options_, true, variables_, - "this->$name$().data(), static_cast(this->$name$().length()),\n", - printer); + descriptor_, options_, false, + "this->_internal_$name$().data(), " + "static_cast(this->_internal_$name$().length()),\n", + format); } + format( + "target = stream->Write$declared_type$MaybeAliased(\n" + " $number$, this->_internal_$name$(), target);\n"); } -void StringFieldGenerator:: -GenerateSerializeWithCachedSizes(io::Printer* printer) const { - if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString( - descriptor_, options_, false, variables_, - "this->$name$().data(), static_cast(this->$name$().length()),\n", - printer); - } - printer->Print(variables_, - "::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n" - " $number$, this->$name$(), output);\n"); +void StringFieldGenerator::GenerateByteSize(io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "total_size += $tag_size$ +\n" + " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n" + " this->_internal_$name$());\n"); } -void StringFieldGenerator:: -GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString( - descriptor_, options_, false, variables_, - "this->$name$().data(), static_cast(this->$name$().length()),\n", - printer); +void StringFieldGenerator::GenerateConstinitInitializer( + io::Printer* printer) const { + Formatter format(printer, variables_); + if (descriptor_->default_value_string().empty()) { + format("$name$_(&::$proto_ns$::internal::fixed_address_empty_string)"); + } else { + format("$name$_(nullptr)"); } - printer->Print(variables_, - "target =\n" - " ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(\n" - " $number$, this->$name$(), target);\n"); -} - -void StringFieldGenerator:: -GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, - "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" - " this->$name$());\n"); } // =================================================================== -StringOneofFieldGenerator:: -StringOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : StringFieldGenerator(descriptor, options), - dependent_field_(options.proto_h) { +StringOneofFieldGenerator::StringOneofFieldGenerator( + const FieldDescriptor* descriptor, const Options& options) + : StringFieldGenerator(descriptor, options) { SetCommonOneofFieldVariables(descriptor, &variables_); + variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true); + variables_["oneof_index"] = + StrCat(descriptor->containing_oneof()->index()); } StringOneofFieldGenerator::~StringOneofFieldGenerator() {} -void StringOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const { - std::map variables(variables_); - variables["inline"] = is_inline ? "inline " : ""; - if (SupportsArenas(descriptor_)) { - printer->Print( - variables, - "$inline$const ::std::string& $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " if (has_$name$()) {\n" - " return $oneof_prefix$$name$_.Get();\n" - " }\n" - " return *$default_variable$;\n" - "}\n" - "$inline$void $classname$::set_$name$(const ::std::string& value) {\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $oneof_prefix$$name$_.Set($default_variable$, value,\n" - " GetArenaNoVirtual());\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n" - "#if LANG_CXX11\n" - "$inline$void $classname$::set_$name$(::std::string&& value) {\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $oneof_prefix$$name$_.Set(\n" - " $default_variable$, ::std::move(value), GetArenaNoVirtual());\n" - " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" - "}\n" - "#endif\n" - "$inline$void $classname$::set_$name$(const char* value) {\n" - " $null_check$" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $oneof_prefix$$name$_.Set($default_variable$,\n" - " $string_piece$(value), GetArenaNoVirtual());\n" - " // @@protoc_insertion_point(field_set_char:$full_name$)\n" - "}\n" - "$inline$" - "void $classname$::set_$name$(const $pointer_type$* value,\n" - " size_t size) {\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $oneof_prefix$$name$_.Set($default_variable$, $string_piece$(\n" - " reinterpret_cast(value), size),\n" - " GetArenaNoVirtual());\n" - " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" - "}\n" - "$inline$::std::string* $classname$::mutable_$name$() {\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" - " }\n" - " return $oneof_prefix$$name$_.Mutable($default_variable$,\n" - " GetArenaNoVirtual());\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - "}\n" - "$inline$::std::string* $classname$::$release_name$() {\n" - " // @@protoc_insertion_point(field_release:$full_name$)\n" - " if (has_$name$()) {\n" - " clear_has_$oneof_name$();\n" - " return $oneof_prefix$$name$_.Release($default_variable$,\n" - " GetArenaNoVirtual());\n" - " } else {\n" - " return NULL;\n" - " }\n" - "}\n" - "$inline$::std::string* $classname$::unsafe_arena_release_$name$() {\n" - " // " - "@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n" - " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" - " if (has_$name$()) {\n" - " clear_has_$oneof_name$();\n" - " return $oneof_prefix$$name$_.UnsafeArenaRelease(\n" - " $default_variable$, GetArenaNoVirtual());\n" - " } else {\n" - " return NULL;\n" - " }\n" - "}\n" - "$inline$void $classname$::set_allocated_$name$(::std::string* $name$) {\n" - " if (!has_$name$()) {\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" - " }\n" - " clear_$oneof_name$();\n" - " if ($name$ != NULL) {\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_.SetAllocated($default_variable$, $name$,\n" - " GetArenaNoVirtual());\n" - " }\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n" - "$inline$void $classname$::unsafe_arena_set_allocated_$name$(" - "::std::string* $name$) {\n" - " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" - " if (!has_$name$()) {\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" - " }\n" - " clear_$oneof_name$();\n" - " if ($name$) {\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeArenaSetAllocated($default_variable$, " - "$name$, GetArenaNoVirtual());\n" - " }\n" - " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" - "$full_name$)\n" - "}\n"); - } else { - // No-arena case. - printer->Print( - variables, - "$inline$const ::std::string& $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " if (has_$name$()) {\n" - " return $oneof_prefix$$name$_.GetNoArena();\n" - " }\n" - " return *$default_variable$;\n" - "}\n" - "$inline$void $classname$::set_$name$(const ::std::string& value) {\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n" - "#if LANG_CXX11\n" - "$inline$void $classname$::set_$name$(::std::string&& value) {\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $oneof_prefix$$name$_.SetNoArena(\n" - " $default_variable$, ::std::move(value));\n" - " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" - "}\n" - "#endif\n" - "$inline$void $classname$::set_$name$(const char* value) {\n" - " $null_check$" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $oneof_prefix$$name$_.SetNoArena($default_variable$,\n" - " $string_piece$(value));\n" - " // @@protoc_insertion_point(field_set_char:$full_name$)\n" - "}\n" - "$inline$" - "void $classname$::set_$name$(const $pointer_type$* value, size_t " - "size) {\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $oneof_prefix$$name$_.SetNoArena($default_variable$, " - "$string_piece$(\n" - " reinterpret_cast(value), size));\n" - " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" - "}\n" - "$inline$::std::string* $classname$::mutable_$name$() {\n" - " if (!has_$name$()) {\n" +void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "inline const std::string& $classname$::$name$() const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return _internal_$name$();\n" + "}\n" + "inline void $classname$::set_$name$(const std::string& value) {\n" + "$annotate_accessor$" + " _internal_set_$name$(value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + "}\n" + "inline std::string* $classname$::mutable_$name$() {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + " return _internal_mutable_$name$();\n" + "}\n" + "inline const std::string& $classname$::_internal_$name$() const {\n" + " if (_internal_has_$name$()) {\n" + " return $field_member$.Get();\n" + " }\n" + " return $default_string$;\n" + "}\n" + "inline void $classname$::_internal_set_$name$(const std::string& " + "value) {\n" + " if (!_internal_has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($init_value$);\n" + " }\n" + " $field_member$.Set($default_value_tag$, value, GetArena());\n" + "}\n" + "inline void $classname$::set_$name$(std::string&& value) {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + " if (!_internal_has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($init_value$);\n" + " }\n" + " $field_member$.Set(\n" + " $default_value_tag$, ::std::move(value), GetArena());\n" + " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" + "}\n" + "inline void $classname$::set_$name$(const char* value) {\n" + "$annotate_accessor$" + " $null_check$" + " if (!_internal_has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($init_value$);\n" + " }\n" + " $field_member$.Set($default_value_tag$,\n" + " $string_piece$(value), GetArena());\n" + " // @@protoc_insertion_point(field_set_char:$full_name$)\n" + "}\n"); + if (!options_.opensource_runtime) { + format( + "inline void $classname$::set_$name$(::StringPiece value) {\n" + "$annotate_accessor$" + " if (!_internal_has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" - " }\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n" - "}\n" - "$inline$::std::string* $classname$::$release_name$() {\n" - " // @@protoc_insertion_point(field_release:$full_name$)\n" - " if (has_$name$()) {\n" - " clear_has_$oneof_name$();\n" - " return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n" - " } else {\n" - " return NULL;\n" + " $field_member$.UnsafeSetDefault($init_value$);\n" " }\n" - "}\n" - "$inline$void $classname$::set_allocated_$name$(::std::string* $name$) {\n" - " if (!has_$name$()) {\n" - " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" - " }\n" - " clear_$oneof_name$();\n" - " if ($name$ != NULL) {\n" - " set_has_$name$();\n" - " $oneof_prefix$$name$_.SetAllocatedNoArena($default_variable$,\n" - " $name$);\n" - " }\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + " $field_member$.Set($default_value_tag$, value, GetArena());\n" + " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" "}\n"); } + format( + "inline " + "void $classname$::set_$name$(const $pointer_type$* value,\n" + " size_t size) {\n" + "$annotate_accessor$" + " if (!_internal_has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($init_value$);\n" + " }\n" + " $field_member$.Set(\n" + " $default_value_tag$, $string_piece$(\n" + " reinterpret_cast(value), size),\n" + " GetArena());\n" + " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" + "}\n" + "inline std::string* $classname$::_internal_mutable_$name$() {\n" + " if (!_internal_has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($init_value$);\n" + " }\n" + " return $field_member$.Mutable(\n" + " $default_variable_or_tag$, GetArena());\n" + "}\n" + "inline std::string* $classname$::$release_name$() {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_release:$full_name$)\n" + " if (_internal_has_$name$()) {\n" + " clear_has_$oneof_name$();\n" + " return $field_member$.ReleaseNonDefault($init_value$, GetArena());\n" + " } else {\n" + " return nullptr;\n" + " }\n" + "}\n" + "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n" + "$annotate_accessor$" + " if (has_$oneof_name$()) {\n" + " clear_$oneof_name$();\n" + " }\n" + " if ($name$ != nullptr) {\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($name$);\n" + " ::$proto_ns$::Arena* arena = GetArena();\n" + " if (arena != nullptr) {\n" + " arena->Own($name$);\n" + " }\n" + " }\n" + " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + "}\n"); } -void StringOneofFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - std::map variables(variables_); - if (dependent_field_) { - variables["this_message"] = DependentBaseDownCast(); - // This clearing code may be in the dependent base class. If the default - // value is an empty string, then the $default_variable$ is a global - // singleton. If the default is not empty, we need to down-cast to get the - // default value's global singleton instance. See SetStringVariables() for - // possible values of default_variable. - if (!descriptor_->default_value_string().empty()) { - variables["default_variable"] = "&" + DependentBaseDownCast() + - variables["default_variable_name"] + - ".get()"; - } - } else { - variables["this_message"] = ""; - } - if (SupportsArenas(descriptor_)) { - printer->Print(variables, - "$this_message$$oneof_prefix$$name$_.Destroy($default_variable$,\n" - " $this_message$GetArenaNoVirtual());\n"); - } else { - printer->Print(variables, - "$this_message$$oneof_prefix$$name$_." - "DestroyNoArena($default_variable$);\n"); - } +void StringOneofFieldGenerator::GenerateClearingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$field_member$.Destroy($default_value_tag$, GetArena());\n"); } -void StringOneofFieldGenerator:: -GenerateMessageClearingCode(io::Printer* printer) const { +void StringOneofFieldGenerator::GenerateMessageClearingCode( + io::Printer* printer) const { return GenerateClearingCode(printer); } -void StringOneofFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { +void StringOneofFieldGenerator::GenerateSwappingCode( + io::Printer* printer) const { // Don't print any swapping code. Swapping the union will swap this field. } -void StringOneofFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { - printer->Print( - variables_, - "_$classname$_default_instance_.$name$_.UnsafeSetDefault(\n" - " $default_variable$);\n"); +void StringOneofFieldGenerator::GenerateConstructorCode( + io::Printer* printer) const { + // Nothing required here. } -void StringOneofFieldGenerator:: -GenerateDestructorCode(io::Printer* printer) const { - if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "if (has_$name$()) {\n" - " $oneof_prefix$$name$_.Destroy($default_variable$,\n" - " GetArenaNoVirtual());\n" - "}\n"); - } else { - printer->Print(variables_, - "if (has_$name$()) {\n" - " $oneof_prefix$$name$_.DestroyNoArena($default_variable$);\n" - "}\n"); - } -} - -void StringOneofFieldGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" - " input, this->mutable_$name$()));\n"); - - if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString( - descriptor_, options_, true, variables_, - "this->$name$().data(), static_cast(this->$name$().length()),\n", - printer); - } -} - - // =================================================================== RepeatedStringFieldGenerator::RepeatedStringFieldGenerator( const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), descriptor_(descriptor) { + : FieldGenerator(descriptor, options) { SetStringVariables(descriptor, &variables_, options); } RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {} -void RepeatedStringFieldGenerator:: -GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::RepeatedPtrField< ::std::string> $name$_;\n"); +void RepeatedStringFieldGenerator::GeneratePrivateMembers( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("::$proto_ns$::RepeatedPtrField $name$_;\n"); } -void RepeatedStringFieldGenerator:: -GenerateAccessorDeclarations(io::Printer* printer) const { +void RepeatedStringFieldGenerator::GenerateAccessorDeclarations( + io::Printer* printer) const { + Formatter format(printer, variables_); // See comment above about unknown ctypes. - bool unknown_ctype = - descriptor_->options().ctype() != EffectiveStringCType(descriptor_); + bool unknown_ctype = descriptor_->options().ctype() != + EffectiveStringCType(descriptor_, options_); if (unknown_ctype) { - printer->Outdent(); - printer->Print( - " private:\n" - " // Hidden due to unknown ctype option.\n"); - printer->Indent(); + format.Outdent(); + format( + " private:\n" + " // Hidden due to unknown ctype option.\n"); + format.Indent(); } - printer->Print(variables_, - "$deprecated_attr$const ::std::string& $name$(int index) const;\n"); - printer->Annotate("name", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$::std::string* ${$mutable_$name$$}$(int index);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$set_$name$$}$(int index, const " - "::std::string& value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print( - variables_, - "#if LANG_CXX11\n" - "$deprecated_attr$void ${$set_$name$$}$(int index, ::std::string&& value);\n" - "#endif\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$set_$name$$}$(int index, const " - "char* value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "" - "$deprecated_attr$void ${$set_$name$$}$(" - "int index, const $pointer_type$* value, size_t size);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$::std::string* ${$add_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$void ${$add_$name$$}$(const ::std::string& value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "#if LANG_CXX11\n" - "$deprecated_attr$void ${$add_$name$$}$(::std::string&& value);\n" - "#endif\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$void ${$add_$name$$}$(const char* value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$add_$name$$}$(const $pointer_type$* " - "value, size_t size)" - ";\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() " - "const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$::google::protobuf::RepeatedPtrField< ::std::string>* " - "${$mutable_$name$$}$()" - ";\n"); - printer->Annotate("{", "}", descriptor_); + format( + "$deprecated_attr$const std::string& ${1$$name$$}$(int index) const;\n" + "$deprecated_attr$std::string* ${1$mutable_$name$$}$(int index);\n" + "$deprecated_attr$void ${1$set_$name$$}$(int index, const " + "std::string& value);\n" + "$deprecated_attr$void ${1$set_$name$$}$(int index, std::string&& " + "value);\n" + "$deprecated_attr$void ${1$set_$name$$}$(int index, const " + "char* value);\n", + descriptor_); + if (!options_.opensource_runtime) { + format( + "$deprecated_attr$void ${1$set_$name$$}$(int index, " + "StringPiece value);\n", + descriptor_); + } + format( + "$deprecated_attr$void ${1$set_$name$$}$(" + "int index, const $pointer_type$* value, size_t size);\n" + "$deprecated_attr$std::string* ${1$add_$name$$}$();\n" + "$deprecated_attr$void ${1$add_$name$$}$(const std::string& value);\n" + "$deprecated_attr$void ${1$add_$name$$}$(std::string&& value);\n" + "$deprecated_attr$void ${1$add_$name$$}$(const char* value);\n", + descriptor_); + if (!options_.opensource_runtime) { + format( + "$deprecated_attr$void ${1$add_$name$$}$(StringPiece value);\n", + descriptor_); + } + format( + "$deprecated_attr$void ${1$add_$name$$}$(const $pointer_type$* " + "value, size_t size)" + ";\n" + "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField& " + "${1$$name$$}$() " + "const;\n" + "$deprecated_attr$::$proto_ns$::RepeatedPtrField* " + "${1$mutable_$name$$}$()" + ";\n" + "private:\n" + "const std::string& ${1$_internal_$name$$}$(int index) const;\n" + "std::string* _internal_add_$name$();\n" + "public:\n", + descriptor_); if (unknown_ctype) { - printer->Outdent(); - printer->Print(" public:\n"); - printer->Indent(); + format.Outdent(); + format(" public:\n"); + format.Indent(); } } -void RepeatedStringFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const { - std::map variables(variables_); - variables["inline"] = is_inline ? "inline " : ""; - printer->Print(variables, - "$inline$const ::std::string& $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_.$cppget$(index);\n" - "}\n" - "$inline$::std::string* $classname$::mutable_$name$(int index) {\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $name$_.Mutable(index);\n" - "}\n" - "$inline$void $classname$::set_$name$(int index, const ::std::string& value) {\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - " $name$_.Mutable(index)->assign(value);\n" - "}\n" - "#if LANG_CXX11\n" - "$inline$void $classname$::set_$name$(int index, ::std::string&& value) {\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - " $name$_.Mutable(index)->assign(std::move(value));\n" - "}\n" - "#endif\n" - "$inline$void $classname$::set_$name$(int index, const char* value) {\n" - " $null_check$" - " $name$_.Mutable(index)->assign(value);\n" - " // @@protoc_insertion_point(field_set_char:$full_name$)\n" - "}\n" - "$inline$void " - "$classname$::set_$name$" - "(int index, const $pointer_type$* value, size_t size) {\n" - " $name$_.Mutable(index)->assign(\n" - " reinterpret_cast(value), size);\n" - " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" - "}\n" - "$inline$::std::string* $classname$::add_$name$() {\n" - " // @@protoc_insertion_point(field_add_mutable:$full_name$)\n" - " return $name$_.Add();\n" - "}\n" - "$inline$void $classname$::add_$name$(const ::std::string& value) {\n" - " $name$_.Add()->assign(value);\n" - " // @@protoc_insertion_point(field_add:$full_name$)\n" - "}\n" - "#if LANG_CXX11\n" - "$inline$void $classname$::add_$name$(::std::string&& value) {\n" - " $name$_.Add(std::move(value));\n" - " // @@protoc_insertion_point(field_add:$full_name$)\n" - "}\n" - "#endif\n" - "$inline$void $classname$::add_$name$(const char* value) {\n" - " $null_check$" - " $name$_.Add()->assign(value);\n" - " // @@protoc_insertion_point(field_add_char:$full_name$)\n" - "}\n" - "$inline$void " - "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n" - " $name$_.Add()->assign(reinterpret_cast(value), size);\n" - " // @@protoc_insertion_point(field_add_pointer:$full_name$)\n" - "}\n" - "$inline$const ::google::protobuf::RepeatedPtrField< ::std::string>&\n" - "$classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_list:$full_name$)\n" - " return $name$_;\n" - "}\n" - "$inline$::google::protobuf::RepeatedPtrField< ::std::string>*\n" - "$classname$::mutable_$name$() {\n" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - " return &$name$_;\n" - "}\n"); +void RepeatedStringFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "inline std::string* $classname$::add_$name$() {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_add_mutable:$full_name$)\n" + " return _internal_add_$name$();\n" + "}\n"); + if (options_.safe_boundary_check) { + format( + "inline const std::string& $classname$::_internal_$name$(int index) " + "const {\n" + " return $name$_.InternalCheckedGet(\n" + " index, ::$proto_ns$::internal::GetEmptyStringAlreadyInited());\n" + "}\n"); + } else { + format( + "inline const std::string& $classname$::_internal_$name$(int index) " + "const {\n" + " return $name$_.Get(index);\n" + "}\n"); + } + format( + "inline const std::string& $classname$::$name$(int index) const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return _internal_$name$(index);\n" + "}\n" + "inline std::string* $classname$::mutable_$name$(int index) {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + " return $name$_.Mutable(index);\n" + "}\n" + "inline void $classname$::set_$name$(int index, const std::string& " + "value) " + "{\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + " $name$_.Mutable(index)->assign(value);\n" + "}\n" + "inline void $classname$::set_$name$(int index, std::string&& value) {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + " $name$_.Mutable(index)->assign(std::move(value));\n" + "}\n" + "inline void $classname$::set_$name$(int index, const char* value) {\n" + "$annotate_accessor$" + " $null_check$" + " $name$_.Mutable(index)->assign(value);\n" + " // @@protoc_insertion_point(field_set_char:$full_name$)\n" + "}\n"); + if (!options_.opensource_runtime) { + format( + "inline void " + "$classname$::set_$name$(int index, StringPiece value) {\n" + "$annotate_accessor$" + " $name$_.Mutable(index)->assign(value.data(), value.size());\n" + " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" + "}\n"); + } + format( + "inline void " + "$classname$::set_$name$" + "(int index, const $pointer_type$* value, size_t size) {\n" + "$annotate_accessor$" + " $name$_.Mutable(index)->assign(\n" + " reinterpret_cast(value), size);\n" + " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" + "}\n" + "inline std::string* $classname$::_internal_add_$name$() {\n" + " return $name$_.Add();\n" + "}\n" + "inline void $classname$::add_$name$(const std::string& value) {\n" + "$annotate_accessor$" + " $name$_.Add()->assign(value);\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" + "}\n" + "inline void $classname$::add_$name$(std::string&& value) {\n" + "$annotate_accessor$" + " $name$_.Add(std::move(value));\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" + "}\n" + "inline void $classname$::add_$name$(const char* value) {\n" + "$annotate_accessor$" + " $null_check$" + " $name$_.Add()->assign(value);\n" + " // @@protoc_insertion_point(field_add_char:$full_name$)\n" + "}\n"); + if (!options_.opensource_runtime) { + format( + "inline void $classname$::add_$name$(StringPiece value) {\n" + "$annotate_accessor$" + " $name$_.Add()->assign(value.data(), value.size());\n" + " // @@protoc_insertion_point(field_add_string_piece:$full_name$)\n" + "}\n"); + } + format( + "inline void " + "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n" + "$annotate_accessor$" + " $name$_.Add()->assign(reinterpret_cast(value), size);\n" + " // @@protoc_insertion_point(field_add_pointer:$full_name$)\n" + "}\n" + "inline const ::$proto_ns$::RepeatedPtrField&\n" + "$classname$::$name$() const {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_list:$full_name$)\n" + " return $name$_;\n" + "}\n" + "inline ::$proto_ns$::RepeatedPtrField*\n" + "$classname$::mutable_$name$() {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" + " return &$name$_;\n" + "}\n"); } -void RepeatedStringFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Clear();\n"); +void RepeatedStringFieldGenerator::GenerateClearingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.Clear();\n"); } -void RepeatedStringFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); +void RepeatedStringFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.MergeFrom(from.$name$_);\n"); } -void RepeatedStringFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n"); +void RepeatedStringFieldGenerator::GenerateSwappingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.InternalSwap(&other->$name$_);\n"); } -void RepeatedStringFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { +void RepeatedStringFieldGenerator::GenerateConstructorCode( + io::Printer* printer) const { // Not needed for repeated fields. } -void RepeatedStringFieldGenerator:: -GenerateCopyConstructorCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.CopyFrom(from.$name$_);"); +void RepeatedStringFieldGenerator::GenerateCopyConstructorCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.CopyFrom(from.$name$_);"); } -void RepeatedStringFieldGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" - " input, this->add_$name$()));\n"); +void RepeatedStringFieldGenerator::GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n" + " const auto& s = this->_internal_$name$(i);\n"); + // format("for (const std::string& s : this->$name$()) {\n"); + format.Indent(); if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString( - descriptor_, options_, true, variables_, - "this->$name$(this->$name$_size() - 1).data(),\n" - "static_cast(this->$name$(this->$name$_size() - 1).length()),\n", - printer); + GenerateUtf8CheckCodeForString(descriptor_, options_, false, + "s.data(), static_cast(s.length()),\n", + format); } + format.Outdent(); + format( + " target = stream->Write$declared_type$($number$, s, target);\n" + "}\n"); } -void RepeatedStringFieldGenerator:: -GenerateSerializeWithCachedSizes(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n"); - printer->Indent(); - if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString( - descriptor_, options_, false, variables_, - "this->$name$(i).data(), static_cast(this->$name$(i).length()),\n", - printer); - } - printer->Outdent(); - printer->Print(variables_, - " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" - " $number$, this->$name$(i), output);\n" - "}\n"); -} - -void RepeatedStringFieldGenerator:: -GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n"); - printer->Indent(); - if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString( - descriptor_, options_, false, variables_, - "this->$name$(i).data(), static_cast(this->$name$(i).length()),\n", - printer); - } - printer->Outdent(); - printer->Print(variables_, - " target = ::google::protobuf::internal::WireFormatLite::\n" - " Write$declared_type$ToArray($number$, this->$name$(i), target);\n" - "}\n"); +void RepeatedStringFieldGenerator::GenerateByteSize( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "total_size += $tag_size$ *\n" + " ::$proto_ns$::internal::FromIntSize($name$_.size());\n" + "for (int i = 0, n = $name$_.size(); i < n; i++) {\n" + " total_size += " + "::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n" + " $name$_.Get(i));\n" + "}\n"); } -void RepeatedStringFieldGenerator:: -GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, - "total_size += $tag_size$ *\n" - " ::google::protobuf::internal::FromIntSize(this->$name$_size());\n" - "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n" - " total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" - " this->$name$(i));\n" - "}\n"); +void RepeatedStringFieldGenerator::GenerateConstinitInitializer( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_()"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h index 531252b0aeab6..213f13465d432 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h @@ -54,8 +54,7 @@ class StringFieldGenerator : public FieldGenerator { void GeneratePrivateMembers(io::Printer* printer) const; void GenerateStaticMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMessageClearingCode(io::Printer* printer) const; @@ -64,15 +63,9 @@ class StringFieldGenerator : public FieldGenerator { void GenerateConstructorCode(io::Printer* printer) const; void GenerateCopyConstructorCode(io::Printer* printer) const; void GenerateDestructorCode(io::Printer* printer) const; - void GenerateDefaultInstanceAllocator(io::Printer* printer) const; - void GenerateMergeFromCodedStream(io::Printer* printer) const; - void GenerateSerializeWithCachedSizes(io::Printer* printer) const; void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - - protected: - const FieldDescriptor* descriptor_; - std::map variables_; + void GenerateConstinitInitializer(io::Printer* printer) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator); @@ -85,8 +78,7 @@ class StringOneofFieldGenerator : public StringFieldGenerator { ~StringOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; // StringFieldGenerator, from which we inherit, overrides this so we need to @@ -94,11 +86,8 @@ class StringOneofFieldGenerator : public StringFieldGenerator { void GenerateMessageClearingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; - void GenerateDestructorCode(io::Printer* printer) const; - void GenerateMergeFromCodedStream(io::Printer* printer) const; private: - const bool dependent_field_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator); }; @@ -111,28 +100,23 @@ class RepeatedStringFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer, - bool is_inline) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; void GenerateCopyConstructorCode(io::Printer* printer) const; - void GenerateMergeFromCodedStream(io::Printer* printer) const; - void GenerateSerializeWithCachedSizes(io::Printer* printer) const; void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; + void GenerateConstinitInitializer(io::Printer* printer) const; private: - const FieldDescriptor* descriptor_; - std::map variables_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator); }; } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto index 4e25b2ea8fffd..479710821fbb5 100644 --- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto +++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto @@ -35,11 +35,13 @@ // This file tests that various identifiers work as field and type names even // though the same identifiers are used internally by the C++ code generator. +// LINT: LEGACY_NAMES + syntax = "proto2"; // Some generic_services option(s) added automatically. // See: http://go/proto2-generic-services-default -option cc_generic_services = true; // auto-added +option cc_generic_services = true; // auto-added // We don't put this in a package within proto2 because we need to make sure // that the generated code doesn't depend on being in the proto2 namespace. @@ -55,17 +57,29 @@ message TestConflictingSymbolNames { optional int32 output = 2; optional string length = 3; repeated int32 i = 4; - repeated string new_element = 5 [ctype=STRING_PIECE]; + repeated string new_element = 5 [ctype = STRING_PIECE]; optional int32 total_size = 6; optional int32 tag = 7; enum TestEnum { FOO = 0; } - message Data1 { repeated int32 data = 1; } - message Data2 { repeated TestEnum data = 1; } - message Data3 { repeated string data = 1; } - message Data4 { repeated Data4 data = 1; } - message Data5 { repeated string data = 1 [ctype=STRING_PIECE]; } - message Data6 { repeated string data = 1 [ctype=CORD]; } + message Data1 { + repeated int32 data = 1; + } + message Data2 { + repeated TestEnum data = 1; + } + message Data3 { + repeated string data = 1; + } + message Data4 { + repeated Data4 data = 1; + } + message Data5 { + repeated string data = 1 [ctype = STRING_PIECE]; + } + message Data6 { + repeated string data = 1 [ctype = CORD]; + } optional int32 source = 8; optional int32 value = 9; @@ -91,10 +105,10 @@ message TestConflictingSymbolNames { optional uint32 reflection = 27; message Cord {} - optional string some_cord = 28 [ctype=CORD]; + optional string some_cord = 28 [ctype = CORD]; message StringPiece {} - optional string some_string_piece = 29 [ctype=STRING_PIECE]; + optional string some_string_piece = 29 [ctype = STRING_PIECE]; // Some keywords. optional uint32 int = 30; @@ -125,14 +139,15 @@ message TestConflictingSymbolNames { extensions 1000 to max; // NO_PROTO3 } -message TestConflictingSymbolNamesExtension { // NO_PROTO3 - extend TestConflictingSymbolNames { // NO_PROTO3 - repeated int32 repeated_int32_ext = 20423638 [packed=true]; // NO_PROTO3 - } // NO_PROTO3 -} // NO_PROTO3 +message TestConflictingSymbolNamesExtension { // NO_PROTO3 + extend TestConflictingSymbolNames { // NO_PROTO3 + repeated int32 repeated_int32_ext = 20423638 [packed = true]; // NO_PROTO3 + } // NO_PROTO3 +} // NO_PROTO3 message TestConflictingEnumNames { // NO_PROTO3 - enum NestedConflictingEnum { // NO_PROTO3 + enum while { // NO_PROTO3 + default = 0; // NO_PROTO3 and = 1; // NO_PROTO3 class = 2; // NO_PROTO3 int = 3; // NO_PROTO3 @@ -140,10 +155,11 @@ message TestConflictingEnumNames { // NO_PROTO3 XOR = 5; // NO_PROTO3 } // NO_PROTO3 - optional NestedConflictingEnum conflicting_enum = 1; // NO_PROTO3 + optional while conflicting_enum = 1; // NO_PROTO3 } // NO_PROTO3 -enum ConflictingEnum { // NO_PROTO3 +enum bool { // NO_PROTO3 + default = 0; // NO_PROTO3 NOT_EQ = 1; // NO_PROTO3 volatile = 2; // NO_PROTO3 return = 3; // NO_PROTO3 @@ -151,6 +167,18 @@ enum ConflictingEnum { // NO_PROTO3 message DummyMessage {} +message NULL { + optional int32 int = 1; +} + +extend TestConflictingSymbolNames { // NO_PROTO3 + optional int32 void = 314253; // NO_PROTO3 +} // NO_PROTO3 + +// Message names that could conflict. +message Shutdown {} +message TableStruct {} + service TestConflictingMethodNames { rpc Closure(DummyMessage) returns (DummyMessage); } diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index fdde771b82e9a..74310a7fd720c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -33,7 +33,7 @@ // Sanjay Ghemawat, Jeff Dean, and others. // // To test the code generator, we actually use it to generate code for -// google/protobuf/unittest.proto, then test that. This means that we +// net/proto2/internal/unittest.proto, then test that. This means that we // are actually testing the parser and other parts of the system at the same // time, and that problems in the generator may show up as compile-time errors // rather than unittest failures, which may be surprising. However, testing @@ -46,40 +46,26 @@ #include -#include -#ifndef _SHARED_PTR_H -#include -#endif -#include - #include -#include -#include #include -#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER) -// We exclude this large proto from cmake build because it's too large for -// visual studio to compile (report internal errors). -#include -#endif -#include +#include + #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#define MESSAGE_TEST_NAME MessageTest +#define GENERATED_DESCRIPTOR_TEST_NAME GeneratedDescriptorTest +#define GENERATED_MESSAGE_TEST_NAME GeneratedMessageTest +#define GENERATED_ENUM_TEST_NAME GeneratedEnumTest +#define GENERATED_SERVICE_TEST_NAME GeneratedServiceTest +#define HELPERS_TEST_NAME HelpersTest +#define DESCRIPTOR_INIT_TEST_NAME DescriptorInitializationTest + +#define UNITTEST_PROTO_PATH "net/proto2/internal/unittest.proto" +#define UNITTEST ::protobuf_unittest +#define UNITTEST_IMPORT ::protobuf_unittest_import + +// Must include after the above macros. +#include namespace google { namespace protobuf { @@ -91,863 +77,14 @@ namespace cpp_unittest { namespace protobuf_unittest = ::protobuf_unittest; - -class MockErrorCollector : public MultiFileErrorCollector { - public: - MockErrorCollector() {} - ~MockErrorCollector() {} - - string text_; - - // implements ErrorCollector --------------------------------------- - void AddError(const string& filename, int line, int column, - const string& message) { - strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", - filename, line, column, message); - } -}; - -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - -// Test that generated code has proper descriptors: -// Parse a descriptor directly (using google::protobuf::compiler::Importer) and -// compare it to the one that was produced by generated code. -TEST(GeneratedDescriptorTest, IdenticalDescriptors) { - const FileDescriptor* generated_descriptor = - unittest::TestAllTypes::descriptor()->file(); - - // Set up the Importer. - MockErrorCollector error_collector; - DiskSourceTree source_tree; - source_tree.MapPath("", TestSourceDir()); - Importer importer(&source_tree, &error_collector); - - // Import (parse) unittest.proto. - const FileDescriptor* parsed_descriptor = - importer.Import("google/protobuf/unittest.proto"); - EXPECT_EQ("", error_collector.text_); - ASSERT_TRUE(parsed_descriptor != NULL); - - // Test that descriptors are generated correctly by converting them to - // FileDescriptorProtos and comparing. - FileDescriptorProto generated_descriptor_proto, parsed_descriptor_proto; - generated_descriptor->CopyTo(&generated_descriptor_proto); - parsed_descriptor->CopyTo(&parsed_descriptor_proto); - - EXPECT_EQ(parsed_descriptor_proto.DebugString(), - generated_descriptor_proto.DebugString()); -} - -#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER) -// Test that generated code has proper descriptors: -// Touch a descriptor generated from an enormous message to validate special -// handling for descriptors exceeding the C++ standard's recommended minimum -// limit for string literal size -TEST(GeneratedDescriptorTest, EnormousDescriptor) { - const Descriptor* generated_descriptor = - TestEnormousDescriptor::descriptor(); - - EXPECT_TRUE(generated_descriptor != NULL); -} -#endif - -#endif // !PROTOBUF_TEST_NO_DESCRIPTORS - -// =================================================================== - -TEST(GeneratedMessageTest, Defaults) { - // Check that all default values are set correctly in the initial message. - unittest::TestAllTypes message; - - TestUtil::ExpectClear(message); - - // Messages should return pointers to default instances until first use. - // (This is not checked by ExpectClear() since it is not actually true after - // the fields have been set and then cleared.) - EXPECT_EQ(&unittest::TestAllTypes::OptionalGroup::default_instance(), - &message.optionalgroup()); - EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(), - &message.optional_nested_message()); - EXPECT_EQ(&unittest::ForeignMessage::default_instance(), - &message.optional_foreign_message()); - EXPECT_EQ(&unittest_import::ImportMessage::default_instance(), - &message.optional_import_message()); -} - -#ifndef PROTOBUF_USE_DLLS -TEST(GeneratedMessageTest, Int32StringConversion) { - EXPECT_EQ("971", Int32ToString(971)); - EXPECT_EQ("(~0x7fffffff)", Int32ToString(kint32min)); - EXPECT_EQ("2147483647", Int32ToString(kint32max)); -} - -TEST(GeneratedMessageTest, Int64StringConversion) { - EXPECT_EQ("GOOGLE_LONGLONG(971)", Int64ToString(971)); - EXPECT_EQ("GOOGLE_LONGLONG(-2147483648)", Int64ToString(kint32min)); - EXPECT_EQ("GOOGLE_LONGLONG(~0x7fffffffffffffff)", Int64ToString(kint64min)); - EXPECT_EQ("GOOGLE_LONGLONG(9223372036854775807)", Int64ToString(kint64max)); -} -#endif // !PROTOBUF_USE_DLLS - -TEST(GeneratedMessageTest, FloatingPointDefaults) { - const unittest::TestExtremeDefaultValues& extreme_default = - unittest::TestExtremeDefaultValues::default_instance(); - - EXPECT_EQ(0.0f, extreme_default.zero_float()); - EXPECT_EQ(1.0f, extreme_default.one_float()); - EXPECT_EQ(1.5f, extreme_default.small_float()); - EXPECT_EQ(-1.0f, extreme_default.negative_one_float()); - EXPECT_EQ(-1.5f, extreme_default.negative_float()); - EXPECT_EQ(2.0e8f, extreme_default.large_float()); - EXPECT_EQ(-8e-28f, extreme_default.small_negative_float()); - EXPECT_EQ(std::numeric_limits::infinity(), - extreme_default.inf_double()); - EXPECT_EQ(-std::numeric_limits::infinity(), - extreme_default.neg_inf_double()); - EXPECT_TRUE(extreme_default.nan_double() != extreme_default.nan_double()); - EXPECT_EQ(std::numeric_limits::infinity(), - extreme_default.inf_float()); - EXPECT_EQ(-std::numeric_limits::infinity(), - extreme_default.neg_inf_float()); - EXPECT_TRUE(extreme_default.nan_float() != extreme_default.nan_float()); -} - -TEST(GeneratedMessageTest, Trigraph) { - const unittest::TestExtremeDefaultValues& extreme_default = - unittest::TestExtremeDefaultValues::default_instance(); - - EXPECT_EQ("? ? ?? ?? ??? ?\?/ ?\?-", extreme_default.cpp_trigraph()); -} - -TEST(GeneratedMessageTest, ExtremeSmallIntegerDefault) { - const unittest::TestExtremeDefaultValues& extreme_default = - unittest::TestExtremeDefaultValues::default_instance(); - EXPECT_EQ(~0x7fffffff, kint32min); - EXPECT_EQ(GOOGLE_LONGLONG(~0x7fffffffffffffff), kint64min); - EXPECT_EQ(kint32min, extreme_default.really_small_int32()); - EXPECT_EQ(kint64min, extreme_default.really_small_int64()); -} - -TEST(GeneratedMessageTest, Accessors) { - // Set every field to a unique value then go back and check all those - // values. - unittest::TestAllTypes message; - - TestUtil::SetAllFields(&message); - TestUtil::ExpectAllFieldsSet(message); - - TestUtil::ModifyRepeatedFields(&message); - TestUtil::ExpectRepeatedFieldsModified(message); -} - -TEST(GeneratedMessageTest, MutableStringDefault) { - // mutable_foo() for a string should return a string initialized to its - // default value. - unittest::TestAllTypes message; - - EXPECT_EQ("hello", *message.mutable_default_string()); - - // Note that the first time we call mutable_foo(), we get a newly-allocated - // string, but if we clear it and call it again, we get the same object again. - // We should verify that it has its default value in both cases. - message.set_default_string("blah"); - message.Clear(); - - EXPECT_EQ("hello", *message.mutable_default_string()); -} - -TEST(GeneratedMessageTest, StringDefaults) { - unittest::TestExtremeDefaultValues message; - // Check if '\000' can be used in default string value. - EXPECT_EQ(string("hel\000lo", 6), message.string_with_zero()); - EXPECT_EQ(string("wor\000ld", 6), message.bytes_with_zero()); -} - -TEST(GeneratedMessageTest, ReleaseString) { - // Check that release_foo() starts out NULL, and gives us a value - // that we can delete after it's been set. - unittest::TestAllTypes message; - - EXPECT_EQ(NULL, message.release_default_string()); - EXPECT_FALSE(message.has_default_string()); - EXPECT_EQ("hello", message.default_string()); - - message.set_default_string("blah"); - EXPECT_TRUE(message.has_default_string()); - google::protobuf::scoped_ptr str(message.release_default_string()); - EXPECT_FALSE(message.has_default_string()); - ASSERT_TRUE(str != NULL); - EXPECT_EQ("blah", *str); - - EXPECT_EQ(NULL, message.release_default_string()); - EXPECT_FALSE(message.has_default_string()); - EXPECT_EQ("hello", message.default_string()); -} - -TEST(GeneratedMessageTest, ReleaseMessage) { - // Check that release_foo() starts out NULL, and gives us a value - // that we can delete after it's been set. - unittest::TestAllTypes message; - - EXPECT_EQ(NULL, message.release_optional_nested_message()); - EXPECT_FALSE(message.has_optional_nested_message()); - - message.mutable_optional_nested_message()->set_bb(1); - google::protobuf::scoped_ptr nest( - message.release_optional_nested_message()); - EXPECT_FALSE(message.has_optional_nested_message()); - ASSERT_TRUE(nest != NULL); - EXPECT_EQ(1, nest->bb()); - - EXPECT_EQ(NULL, message.release_optional_nested_message()); - EXPECT_FALSE(message.has_optional_nested_message()); -} - -TEST(GeneratedMessageTest, SetAllocatedString) { - // Check that set_allocated_foo() works for strings. - unittest::TestAllTypes message; - - EXPECT_FALSE(message.has_optional_string()); - const string kHello("hello"); - message.set_optional_string(kHello); - EXPECT_TRUE(message.has_optional_string()); - - message.set_allocated_optional_string(NULL); - EXPECT_FALSE(message.has_optional_string()); - EXPECT_EQ("", message.optional_string()); - - message.set_allocated_optional_string(new string(kHello)); - EXPECT_TRUE(message.has_optional_string()); - EXPECT_EQ(kHello, message.optional_string()); -} - -TEST(GeneratedMessageTest, SetAllocatedMessage) { - // Check that set_allocated_foo() can be called in all cases. - unittest::TestAllTypes message; - - EXPECT_FALSE(message.has_optional_nested_message()); - - message.mutable_optional_nested_message()->set_bb(1); - EXPECT_TRUE(message.has_optional_nested_message()); - - message.set_allocated_optional_nested_message(NULL); - EXPECT_FALSE(message.has_optional_nested_message()); - EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(), - &message.optional_nested_message()); - - message.mutable_optional_nested_message()->set_bb(1); - unittest::TestAllTypes::NestedMessage* nest = - message.release_optional_nested_message(); - ASSERT_TRUE(nest != NULL); - EXPECT_FALSE(message.has_optional_nested_message()); - - message.set_allocated_optional_nested_message(nest); - EXPECT_TRUE(message.has_optional_nested_message()); - EXPECT_EQ(1, message.optional_nested_message().bb()); -} - -TEST(GeneratedMessageTest, Clear) { - // Set every field to a unique value, clear the message, then check that - // it is cleared. - unittest::TestAllTypes message; - - TestUtil::SetAllFields(&message); - message.Clear(); - TestUtil::ExpectClear(message); - - // Unlike with the defaults test, we do NOT expect that requesting embedded - // messages will return a pointer to the default instance. Instead, they - // should return the objects that were created when mutable_blah() was - // called. - EXPECT_NE(&unittest::TestAllTypes::OptionalGroup::default_instance(), - &message.optionalgroup()); - EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(), - &message.optional_nested_message()); - EXPECT_NE(&unittest::ForeignMessage::default_instance(), - &message.optional_foreign_message()); - EXPECT_NE(&unittest_import::ImportMessage::default_instance(), - &message.optional_import_message()); -} - -TEST(GeneratedMessageTest, EmbeddedNullsInBytesCharStar) { - unittest::TestAllTypes message; - - const char* value = "\0lalala\0\0"; - message.set_optional_bytes(value, 9); - ASSERT_EQ(9, message.optional_bytes().size()); - EXPECT_EQ(0, memcmp(value, message.optional_bytes().data(), 9)); - - message.add_repeated_bytes(value, 9); - ASSERT_EQ(9, message.repeated_bytes(0).size()); - EXPECT_EQ(0, memcmp(value, message.repeated_bytes(0).data(), 9)); -} - -TEST(GeneratedMessageTest, ClearOneField) { - // Set every field to a unique value, then clear one value and insure that - // only that one value is cleared. - unittest::TestAllTypes message; - - TestUtil::SetAllFields(&message); - int64 original_value = message.optional_int64(); - - // Clear the field and make sure it shows up as cleared. - message.clear_optional_int64(); - EXPECT_FALSE(message.has_optional_int64()); - EXPECT_EQ(0, message.optional_int64()); - - // Other adjacent fields should not be cleared. - EXPECT_TRUE(message.has_optional_int32()); - EXPECT_TRUE(message.has_optional_uint32()); - - // Make sure if we set it again, then all fields are set. - message.set_optional_int64(original_value); - TestUtil::ExpectAllFieldsSet(message); -} - -TEST(GeneratedMessageTest, StringCharStarLength) { - // Verify that we can use a char*,length to set one of the string fields. - unittest::TestAllTypes message; - message.set_optional_string("abcdef", 3); - EXPECT_EQ("abc", message.optional_string()); - - // Verify that we can use a char*,length to add to a repeated string field. - message.add_repeated_string("abcdef", 3); - EXPECT_EQ(1, message.repeated_string_size()); - EXPECT_EQ("abc", message.repeated_string(0)); - - // Verify that we can use a char*,length to set a repeated string field. - message.set_repeated_string(0, "wxyz", 2); - EXPECT_EQ("wx", message.repeated_string(0)); -} - -#if LANG_CXX11 -TEST(GeneratedMessageTest, StringMove) { - // Verify that we trigger the move behavior on a scalar setter. - protobuf_unittest_no_arena::TestAllTypes message; - { - string tmp(32, 'a'); - - const char* old_data = tmp.data(); - message.set_optional_string(std::move(tmp)); - const char* new_data = message.optional_string().data(); - - EXPECT_EQ(old_data, new_data); - EXPECT_EQ(string(32, 'a'), message.optional_string()); - - string tmp2(32, 'b'); - old_data = tmp2.data(); - message.set_optional_string(std::move(tmp2)); - new_data = message.optional_string().data(); - - EXPECT_EQ(old_data, new_data); - EXPECT_EQ(string(32, 'b'), message.optional_string()); - } - - // Verify that we trigger the move behavior on a oneof setter. - { - string tmp(32, 'a'); - - const char* old_data = tmp.data(); - message.set_oneof_string(std::move(tmp)); - const char* new_data = message.oneof_string().data(); - - EXPECT_EQ(old_data, new_data); - EXPECT_EQ(string(32, 'a'), message.oneof_string()); - - string tmp2(32, 'b'); - old_data = tmp2.data(); - message.set_oneof_string(std::move(tmp2)); - new_data = message.oneof_string().data(); - - EXPECT_EQ(old_data, new_data); - EXPECT_EQ(string(32, 'b'), message.oneof_string()); - } - - // Verify that we trigger the move behavior on a repeated setter. - { - string tmp(32, 'a'); - - const char* old_data = tmp.data(); - message.add_repeated_string(std::move(tmp)); - const char* new_data = message.repeated_string(0).data(); - - EXPECT_EQ(old_data, new_data); - EXPECT_EQ(string(32, 'a'), message.repeated_string(0)); - - string tmp2(32, 'b'); - old_data = tmp2.data(); - message.set_repeated_string(0, std::move(tmp2)); - new_data = message.repeated_string(0).data(); - - EXPECT_EQ(old_data, new_data); - EXPECT_EQ(string(32, 'b'), message.repeated_string(0)); - } -} -#endif - - -TEST(GeneratedMessageTest, CopyFrom) { - unittest::TestAllTypes message1, message2; - - TestUtil::SetAllFields(&message1); - message2.CopyFrom(message1); - TestUtil::ExpectAllFieldsSet(message2); - - // Copying from self should be a no-op. - message2.CopyFrom(message2); - TestUtil::ExpectAllFieldsSet(message2); -} - - -TEST(GeneratedMessageTest, SwapWithEmpty) { - unittest::TestAllTypes message1, message2; - TestUtil::SetAllFields(&message1); - - TestUtil::ExpectAllFieldsSet(message1); - TestUtil::ExpectClear(message2); - message1.Swap(&message2); - TestUtil::ExpectAllFieldsSet(message2); - TestUtil::ExpectClear(message1); -} - -TEST(GeneratedMessageTest, SwapWithSelf) { - unittest::TestAllTypes message; - TestUtil::SetAllFields(&message); - TestUtil::ExpectAllFieldsSet(message); - message.Swap(&message); - TestUtil::ExpectAllFieldsSet(message); -} - -TEST(GeneratedMessageTest, SwapWithOther) { - unittest::TestAllTypes message1, message2; - - message1.set_optional_int32(123); - message1.set_optional_string("abc"); - message1.mutable_optional_nested_message()->set_bb(1); - message1.set_optional_nested_enum(unittest::TestAllTypes::FOO); - message1.add_repeated_int32(1); - message1.add_repeated_int32(2); - message1.add_repeated_string("a"); - message1.add_repeated_string("b"); - message1.add_repeated_nested_message()->set_bb(7); - message1.add_repeated_nested_message()->set_bb(8); - message1.add_repeated_nested_enum(unittest::TestAllTypes::FOO); - message1.add_repeated_nested_enum(unittest::TestAllTypes::BAR); - - message2.set_optional_int32(456); - message2.set_optional_string("def"); - message2.mutable_optional_nested_message()->set_bb(2); - message2.set_optional_nested_enum(unittest::TestAllTypes::BAR); - message2.add_repeated_int32(3); - message2.add_repeated_string("c"); - message2.add_repeated_nested_message()->set_bb(9); - message2.add_repeated_nested_enum(unittest::TestAllTypes::BAZ); - - message1.Swap(&message2); - - EXPECT_EQ(456, message1.optional_int32()); - EXPECT_EQ("def", message1.optional_string()); - EXPECT_EQ(2, message1.optional_nested_message().bb()); - EXPECT_EQ(unittest::TestAllTypes::BAR, message1.optional_nested_enum()); - ASSERT_EQ(1, message1.repeated_int32_size()); - EXPECT_EQ(3, message1.repeated_int32(0)); - ASSERT_EQ(1, message1.repeated_string_size()); - EXPECT_EQ("c", message1.repeated_string(0)); - ASSERT_EQ(1, message1.repeated_nested_message_size()); - EXPECT_EQ(9, message1.repeated_nested_message(0).bb()); - ASSERT_EQ(1, message1.repeated_nested_enum_size()); - EXPECT_EQ(unittest::TestAllTypes::BAZ, message1.repeated_nested_enum(0)); - - EXPECT_EQ(123, message2.optional_int32()); - EXPECT_EQ("abc", message2.optional_string()); - EXPECT_EQ(1, message2.optional_nested_message().bb()); - EXPECT_EQ(unittest::TestAllTypes::FOO, message2.optional_nested_enum()); - ASSERT_EQ(2, message2.repeated_int32_size()); - EXPECT_EQ(1, message2.repeated_int32(0)); - EXPECT_EQ(2, message2.repeated_int32(1)); - ASSERT_EQ(2, message2.repeated_string_size()); - EXPECT_EQ("a", message2.repeated_string(0)); - EXPECT_EQ("b", message2.repeated_string(1)); - ASSERT_EQ(2, message2.repeated_nested_message_size()); - EXPECT_EQ(7, message2.repeated_nested_message(0).bb()); - EXPECT_EQ(8, message2.repeated_nested_message(1).bb()); - ASSERT_EQ(2, message2.repeated_nested_enum_size()); - EXPECT_EQ(unittest::TestAllTypes::FOO, message2.repeated_nested_enum(0)); - EXPECT_EQ(unittest::TestAllTypes::BAR, message2.repeated_nested_enum(1)); -} - -TEST(GeneratedMessageTest, ADLSwap) { - unittest::TestAllTypes message1, message2; - TestUtil::SetAllFields(&message1); - - // Note the address of one of the repeated fields, to verify it was swapped - // rather than copied. - const int32* addr = &message1.repeated_int32().Get(0); - - using std::swap; - swap(message1, message2); - - TestUtil::ExpectAllFieldsSet(message2); - TestUtil::ExpectClear(message1); - - EXPECT_EQ(addr, &message2.repeated_int32().Get(0)); -} - -TEST(GeneratedMessageTest, CopyConstructor) { - // All set. - { - unittest::TestAllTypes message1; - TestUtil::SetAllFields(&message1); - - unittest::TestAllTypes message2(message1); - TestUtil::ExpectAllFieldsSet(message2); - } - - // None set. - { - unittest::TestAllTypes message1; - unittest::TestAllTypes message2(message1); - - EXPECT_FALSE(message1.has_optional_string()); - EXPECT_FALSE(message2.has_optional_string()); - EXPECT_EQ(&message1.optional_string(), - &message2.optional_string()); - - EXPECT_FALSE(message1.has_optional_bytes()); - EXPECT_FALSE(message2.has_optional_bytes()); - EXPECT_EQ(&message1.optional_bytes(), - &message2.optional_bytes()); - - EXPECT_FALSE(message1.has_optional_nested_message()); - EXPECT_FALSE(message2.has_optional_nested_message()); - EXPECT_EQ(&message1.optional_nested_message(), - &message2.optional_nested_message()); - - EXPECT_FALSE(message1.has_optional_foreign_message()); - EXPECT_FALSE(message2.has_optional_foreign_message()); - EXPECT_EQ(&message1.optional_foreign_message(), - &message2.optional_foreign_message()); - - EXPECT_FALSE(message1.has_optional_import_message()); - EXPECT_FALSE(message2.has_optional_import_message()); - EXPECT_EQ(&message1.optional_import_message(), - &message2.optional_import_message()); - - EXPECT_FALSE(message1.has_optional_public_import_message()); - EXPECT_FALSE(message2.has_optional_public_import_message()); - EXPECT_EQ(&message1.optional_public_import_message(), - &message2.optional_public_import_message()); - - EXPECT_FALSE(message1.has_optional_lazy_message()); - EXPECT_FALSE(message2.has_optional_lazy_message()); - EXPECT_EQ(&message1.optional_lazy_message(), - &message2.optional_lazy_message()); - } -} - -TEST(GeneratedMessageTest, CopyConstructorWithArenas) { - Arena arena; - unittest::TestAllTypes* message1 = - Arena::CreateMessage(&arena); - TestUtil::SetAllFields(message1); - - unittest::TestAllTypes message2_stack(*message1); - TestUtil::ExpectAllFieldsSet(message2_stack); - - google::protobuf::scoped_ptr message2_heap( - new unittest::TestAllTypes(*message1)); - TestUtil::ExpectAllFieldsSet(*message2_heap); - - arena.Reset(); - - // Verify that the copies are still intact. - TestUtil::ExpectAllFieldsSet(message2_stack); - TestUtil::ExpectAllFieldsSet(*message2_heap); -} - -TEST(GeneratedMessageTest, CopyAssignmentOperator) { - unittest::TestAllTypes message1; - TestUtil::SetAllFields(&message1); - - unittest::TestAllTypes message2; - message2 = message1; - TestUtil::ExpectAllFieldsSet(message2); - - // Make sure that self-assignment does something sane. - message2.operator=(message2); - TestUtil::ExpectAllFieldsSet(message2); -} - -#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \ - !defined(GOOGLE_PROTOBUF_NO_RTTI) -TEST(GeneratedMessageTest, UpcastCopyFrom) { - // Test the CopyFrom method that takes in the generic const Message& - // parameter. - unittest::TestAllTypes message1, message2; - - TestUtil::SetAllFields(&message1); - - const Message* source = implicit_cast(&message1); - message2.CopyFrom(*source); - - TestUtil::ExpectAllFieldsSet(message2); -} -#endif - -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - -TEST(GeneratedMessageTest, DynamicMessageCopyFrom) { - // Test copying from a DynamicMessage, which must fall back to using - // reflection. - unittest::TestAllTypes message2; - - // Construct a new version of the dynamic message via the factory. - DynamicMessageFactory factory; - google::protobuf::scoped_ptr message1; - message1.reset(factory.GetPrototype( - unittest::TestAllTypes::descriptor())->New()); - - TestUtil::ReflectionTester reflection_tester( - unittest::TestAllTypes::descriptor()); - reflection_tester.SetAllFieldsViaReflection(message1.get()); - - message2.CopyFrom(*message1); - - TestUtil::ExpectAllFieldsSet(message2); -} - -#endif // !PROTOBUF_TEST_NO_DESCRIPTORS - -TEST(GeneratedMessageTest, NonEmptyMergeFrom) { - // Test merging with a non-empty message. Code is a modified form - // of that found in google/protobuf/reflection_ops_unittest.cc. - unittest::TestAllTypes message1, message2; - - TestUtil::SetAllFields(&message1); - - // This field will test merging into an empty spot. - message2.set_optional_int32(message1.optional_int32()); - message1.clear_optional_int32(); - - // This tests overwriting. - message2.set_optional_string(message1.optional_string()); - message1.set_optional_string("something else"); - - // This tests concatenating. - message2.add_repeated_int32(message1.repeated_int32(1)); - int32 i = message1.repeated_int32(0); - message1.clear_repeated_int32(); - message1.add_repeated_int32(i); - - message1.MergeFrom(message2); - - TestUtil::ExpectAllFieldsSet(message1); -} - -#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \ - !defined(GOOGLE_PROTOBUF_NO_RTTI) -#ifdef PROTOBUF_HAS_DEATH_TEST -#ifndef NDEBUG - -TEST(GeneratedMessageTest, MergeFromSelf) { - unittest::TestAllTypes message; - EXPECT_DEATH(message.MergeFrom(message), "pb[.]cc.*Check failed:"); - EXPECT_DEATH(message.MergeFrom(implicit_cast(message)), - "pb[.]cc.*Check failed:"); -} - -#endif // NDEBUG -#endif // PROTOBUF_HAS_DEATH_TEST -#endif // !PROTOBUF_TEST_NO_DESCRIPTORS || !GOOGLE_PROTOBUF_NO_RTTI - -// Test the generated SerializeWithCachedSizesToArray(), -TEST(GeneratedMessageTest, SerializationToArray) { - unittest::TestAllTypes message1, message2; - string data; - TestUtil::SetAllFields(&message1); - int size = message1.ByteSize(); - data.resize(size); - uint8* start = reinterpret_cast(string_as_array(&data)); - uint8* end = message1.SerializeWithCachedSizesToArray(start); - EXPECT_EQ(size, end - start); - EXPECT_TRUE(message2.ParseFromString(data)); - TestUtil::ExpectAllFieldsSet(message2); - -} - -TEST(GeneratedMessageTest, PackedFieldsSerializationToArray) { - unittest::TestPackedTypes packed_message1, packed_message2; - string packed_data; - TestUtil::SetPackedFields(&packed_message1); - int packed_size = packed_message1.ByteSize(); - packed_data.resize(packed_size); - uint8* start = reinterpret_cast(string_as_array(&packed_data)); - uint8* end = packed_message1.SerializeWithCachedSizesToArray(start); - EXPECT_EQ(packed_size, end - start); - EXPECT_TRUE(packed_message2.ParseFromString(packed_data)); - TestUtil::ExpectPackedFieldsSet(packed_message2); -} - -// Test the generated SerializeWithCachedSizes() by forcing the buffer to write -// one byte at a time. -TEST(GeneratedMessageTest, SerializationToStream) { - unittest::TestAllTypes message1, message2; - TestUtil::SetAllFields(&message1); - int size = message1.ByteSize(); - string data; - data.resize(size); - { - // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); - io::CodedOutputStream output_stream(&array_stream); - message1.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); - } - EXPECT_TRUE(message2.ParseFromString(data)); - TestUtil::ExpectAllFieldsSet(message2); - -} - -TEST(GeneratedMessageTest, PackedFieldsSerializationToStream) { - unittest::TestPackedTypes message1, message2; - TestUtil::SetPackedFields(&message1); - int size = message1.ByteSize(); - string data; - data.resize(size); - { - // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); - io::CodedOutputStream output_stream(&array_stream); - message1.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); - } - EXPECT_TRUE(message2.ParseFromString(data)); - TestUtil::ExpectPackedFieldsSet(message2); -} - - -TEST(GeneratedMessageTest, Required) { - // Test that IsInitialized() returns false if required fields are missing. - unittest::TestRequired message; - - EXPECT_FALSE(message.IsInitialized()); - message.set_a(1); - EXPECT_FALSE(message.IsInitialized()); - message.set_b(2); - EXPECT_FALSE(message.IsInitialized()); - message.set_c(3); - EXPECT_TRUE(message.IsInitialized()); -} - -TEST(GeneratedMessageTest, RequiredForeign) { - // Test that IsInitialized() returns false if required fields in nested - // messages are missing. - unittest::TestRequiredForeign message; - - EXPECT_TRUE(message.IsInitialized()); - - message.mutable_optional_message(); - EXPECT_FALSE(message.IsInitialized()); - - message.mutable_optional_message()->set_a(1); - message.mutable_optional_message()->set_b(2); - message.mutable_optional_message()->set_c(3); - EXPECT_TRUE(message.IsInitialized()); - - message.add_repeated_message(); - EXPECT_FALSE(message.IsInitialized()); - - message.mutable_repeated_message(0)->set_a(1); - message.mutable_repeated_message(0)->set_b(2); - message.mutable_repeated_message(0)->set_c(3); - EXPECT_TRUE(message.IsInitialized()); -} - -TEST(GeneratedMessageTest, ForeignNested) { - // Test that TestAllTypes::NestedMessage can be embedded directly into - // another message. - unittest::TestForeignNested message; - - // If this compiles and runs without crashing, it must work. We have - // nothing more to test. - unittest::TestAllTypes::NestedMessage* nested = - message.mutable_foreign_nested(); - nested->set_bb(1); -} - -TEST(GeneratedMessageTest, ReallyLargeTagNumber) { - // Test that really large tag numbers don't break anything. - unittest::TestReallyLargeTagNumber message1, message2; - string data; - - // For the most part, if this compiles and runs then we're probably good. - // (The most likely cause for failure would be if something were attempting - // to allocate a lookup table of some sort using tag numbers as the index.) - // We'll try serializing just for fun. - message1.set_a(1234); - message1.set_bb(5678); - message1.SerializeToString(&data); - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(1234, message2.a()); - EXPECT_EQ(5678, message2.bb()); -} - -TEST(GeneratedMessageTest, MutualRecursion) { - // Test that mutually-recursive message types work. - unittest::TestMutualRecursionA message; - unittest::TestMutualRecursionA* nested = message.mutable_bb()->mutable_a(); - unittest::TestMutualRecursionA* nested2 = nested->mutable_bb()->mutable_a(); - - // Again, if the above compiles and runs, that's all we really have to - // test, but just for run we'll check that the system didn't somehow come - // up with a pointer loop... - EXPECT_NE(&message, nested); - EXPECT_NE(&message, nested2); - EXPECT_NE(nested, nested2); -} - -TEST(GeneratedMessageTest, CamelCaseFieldNames) { - // This test is mainly checking that the following compiles, which verifies - // that the field names were coerced to lower-case. - // - // Protocol buffers standard style is to use lowercase-with-underscores for - // field names. Some old proto1 .protos unfortunately used camel-case field - // names. In proto1, these names were forced to lower-case. So, we do the - // same thing in proto2. - - unittest::TestCamelCaseFieldNames message; - - message.set_primitivefield(2); - message.set_stringfield("foo"); - message.set_enumfield(unittest::FOREIGN_FOO); - message.mutable_messagefield()->set_c(6); - - message.add_repeatedprimitivefield(8); - message.add_repeatedstringfield("qux"); - message.add_repeatedenumfield(unittest::FOREIGN_BAR); - message.add_repeatedmessagefield()->set_c(15); - - EXPECT_EQ(2, message.primitivefield()); - EXPECT_EQ("foo", message.stringfield()); - EXPECT_EQ(unittest::FOREIGN_FOO, message.enumfield()); - EXPECT_EQ(6, message.messagefield().c()); - - EXPECT_EQ(8, message.repeatedprimitivefield(0)); - EXPECT_EQ("qux", message.repeatedstringfield(0)); - EXPECT_EQ(unittest::FOREIGN_BAR, message.repeatedenumfield(0)); - EXPECT_EQ(15, message.repeatedmessagefield(0).c()); -} - -TEST(GeneratedMessageTest, TestConflictingSymbolNames) { +TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingSymbolNames) { // test_bad_identifiers.proto successfully compiled, then it works. The // following is just a token usage to insure that the code is, in fact, // being compiled and linked. protobuf_unittest::TestConflictingSymbolNames message; message.set_uint32(1); - EXPECT_EQ(3, message.ByteSize()); + EXPECT_EQ(3, message.ByteSizeLong()); message.set_friend_(5); EXPECT_EQ(5, message.friend_()); @@ -959,1384 +96,38 @@ TEST(GeneratedMessageTest, TestConflictingSymbolNames) { // parameter names. typedef protobuf_unittest::TestConflictingSymbolNamesExtension ExtensionMessage; message.AddExtension(ExtensionMessage::repeated_int32_ext, 123); - EXPECT_EQ(123, - message.GetExtension(ExtensionMessage::repeated_int32_ext, 0)); + EXPECT_EQ(123, message.GetExtension(ExtensionMessage::repeated_int32_ext, 0)); } -TEST(GeneratedMessageTest, TestConflictingEnumNames) { +TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingEnumNames) { protobuf_unittest::TestConflictingEnumNames message; - message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_and_); + message.set_conflicting_enum( + protobuf_unittest::TestConflictingEnumNames_while_and_); EXPECT_EQ(1, message.conflicting_enum()); - message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_XOR); + message.set_conflicting_enum( + protobuf_unittest::TestConflictingEnumNames_while_XOR); EXPECT_EQ(5, message.conflicting_enum()); - - protobuf_unittest::ConflictingEnum conflicting_enum; + protobuf_unittest::bool_ conflicting_enum; conflicting_enum = protobuf_unittest::NOT_EQ; EXPECT_EQ(1, conflicting_enum); conflicting_enum = protobuf_unittest::return_; EXPECT_EQ(3, conflicting_enum); } -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - -TEST(GeneratedMessageTest, TestOptimizedForSize) { - // We rely on the tests in reflection_ops_unittest and wire_format_unittest - // to really test that reflection-based methods work. Here we are mostly - // just making sure that TestOptimizedForSize actually builds and seems to - // function. - - protobuf_unittest::TestOptimizedForSize message, message2; - message.set_i(1); - message.mutable_msg()->set_c(2); - message2.CopyFrom(message); - EXPECT_EQ(1, message2.i()); - EXPECT_EQ(2, message2.msg().c()); -} - -TEST(GeneratedMessageTest, TestEmbedOptimizedForSize) { - // Verifies that something optimized for speed can contain something optimized - // for size. - - protobuf_unittest::TestEmbedOptimizedForSize message, message2; - message.mutable_optional_message()->set_i(1); - message.add_repeated_message()->mutable_msg()->set_c(2); - string data; - message.SerializeToString(&data); - ASSERT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(1, message2.optional_message().i()); - EXPECT_EQ(2, message2.repeated_message(0).msg().c()); -} - -TEST(GeneratedMessageTest, TestSpaceUsed) { - unittest::TestAllTypes message1; - // sizeof provides a lower bound on SpaceUsed(). - EXPECT_LE(sizeof(unittest::TestAllTypes), message1.SpaceUsed()); - const int empty_message_size = message1.SpaceUsed(); - - // Setting primitive types shouldn't affect the space used. - message1.set_optional_int32(123); - message1.set_optional_int64(12345); - message1.set_optional_uint32(123); - message1.set_optional_uint64(12345); - EXPECT_EQ(empty_message_size, message1.SpaceUsed()); - - // On some STL implementations, setting the string to a small value should - // only increase SpaceUsed() by the size of a string object, though this is - // not true everywhere. - message1.set_optional_string("abc"); - EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsed()); - - // Setting a string to a value larger than the string object itself should - // increase SpaceUsed(), because it cannot store the value internally. - message1.set_optional_string(string(sizeof(string) + 1, 'x')); - int min_expected_increase = message1.optional_string().capacity() + - sizeof(string); - EXPECT_LE(empty_message_size + min_expected_increase, - message1.SpaceUsed()); - - int previous_size = message1.SpaceUsed(); - // Adding an optional message should increase the size by the size of the - // nested message type. NestedMessage is simple enough (1 int field) that it - // is equal to sizeof(NestedMessage) - message1.mutable_optional_nested_message(); - ASSERT_EQ(sizeof(unittest::TestAllTypes::NestedMessage), - message1.optional_nested_message().SpaceUsed()); - EXPECT_EQ(previous_size + - sizeof(unittest::TestAllTypes::NestedMessage), - message1.SpaceUsed()); -} - -TEST(GeneratedMessageTest, TestOneofSpaceUsed) { - unittest::TestOneof2 message1; - EXPECT_LE(sizeof(unittest::TestOneof2), message1.SpaceUsed()); - - const int empty_message_size = message1.SpaceUsed(); - // Setting primitive types shouldn't affect the space used. - message1.set_foo_int(123); - message1.set_bar_int(12345); - EXPECT_EQ(empty_message_size, message1.SpaceUsed()); - - // Setting a string in oneof to a small value should only increase SpaceUsed() - // by the size of a string object. - message1.set_foo_string("abc"); - EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsed()); - - // Setting a string in oneof to a value larger than the string object itself - // should increase SpaceUsed(), because it cannot store the value internally. - message1.set_foo_string(string(sizeof(string) + 1, 'x')); - int min_expected_increase = message1.foo_string().capacity() + - sizeof(string); - EXPECT_LE(empty_message_size + min_expected_increase, - message1.SpaceUsed()); - - // Setting a message in oneof should delete the other fields and increase the - // size by the size of the nested message type. NestedMessage is simple enough - // that it is equal to sizeof(NestedMessage) - message1.mutable_foo_message(); - ASSERT_EQ(sizeof(unittest::TestOneof2::NestedMessage), - message1.foo_message().SpaceUsed()); - EXPECT_EQ(empty_message_size + - sizeof(unittest::TestOneof2::NestedMessage), - message1.SpaceUsed()); -} - -#endif // !PROTOBUF_TEST_NO_DESCRIPTORS - - -TEST(GeneratedMessageTest, FieldConstantValues) { - unittest::TestRequired message; - EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1); - EXPECT_EQ(unittest::TestAllTypes::kOptionalInt32FieldNumber, 1); - EXPECT_EQ(unittest::TestAllTypes::kOptionalgroupFieldNumber, 16); - EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedMessageFieldNumber, 18); - EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedEnumFieldNumber, 21); - EXPECT_EQ(unittest::TestAllTypes::kRepeatedInt32FieldNumber, 31); - EXPECT_EQ(unittest::TestAllTypes::kRepeatedgroupFieldNumber, 46); - EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedMessageFieldNumber, 48); - EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedEnumFieldNumber, 51); -} - -TEST(GeneratedMessageTest, ExtensionConstantValues) { - EXPECT_EQ(unittest::TestRequired::kSingleFieldNumber, 1000); - EXPECT_EQ(unittest::TestRequired::kMultiFieldNumber, 1001); - EXPECT_EQ(unittest::kOptionalInt32ExtensionFieldNumber, 1); - EXPECT_EQ(unittest::kOptionalgroupExtensionFieldNumber, 16); - EXPECT_EQ(unittest::kOptionalNestedMessageExtensionFieldNumber, 18); - EXPECT_EQ(unittest::kOptionalNestedEnumExtensionFieldNumber, 21); - EXPECT_EQ(unittest::kRepeatedInt32ExtensionFieldNumber, 31); - EXPECT_EQ(unittest::kRepeatedgroupExtensionFieldNumber, 46); - EXPECT_EQ(unittest::kRepeatedNestedMessageExtensionFieldNumber, 48); - EXPECT_EQ(unittest::kRepeatedNestedEnumExtensionFieldNumber, 51); -} - -TEST(GeneratedMessageTest, ParseFromTruncated) { - const string long_string = string(128, 'q'); - FileDescriptorProto p; - p.add_extension()->set_name(long_string); - const string msg = p.SerializeAsString(); - int successful_count = 0; - for (int i = 0; i <= msg.size(); i++) { - if (p.ParseFromArray(msg.c_str(), i)) { - ++successful_count; - } - } - // We don't really care about how often we succeeded. - // As long as we didn't crash, we're happy. - EXPECT_GE(successful_count, 1); -} - -// =================================================================== - -TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) { - // Test that our nested enum values can be used as switch cases. This test - // doesn't actually do anything, the proof that it works is that it - // compiles. - int i =0; - unittest::TestAllTypes::NestedEnum a = unittest::TestAllTypes::BAR; - switch (a) { - case unittest::TestAllTypes::FOO: - i = 1; - break; - case unittest::TestAllTypes::BAR: - i = 2; - break; - case unittest::TestAllTypes::BAZ: - i = 3; - break; - case unittest::TestAllTypes::NEG: - i = -1; - break; - // no default case: We want to make sure the compiler recognizes that - // all cases are covered. (GCC warns if you do not cover all cases of - // an enum in a switch.) - } - - // Token check just for fun. - EXPECT_EQ(2, i); -} - -TEST(GeneratedEnumTest, IsValidValue) { - // Test enum IsValidValue. - EXPECT_TRUE(unittest::TestAllTypes::NestedEnum_IsValid(1)); - EXPECT_TRUE(unittest::TestAllTypes::NestedEnum_IsValid(2)); - EXPECT_TRUE(unittest::TestAllTypes::NestedEnum_IsValid(3)); - - EXPECT_FALSE(unittest::TestAllTypes::NestedEnum_IsValid(0)); - EXPECT_FALSE(unittest::TestAllTypes::NestedEnum_IsValid(4)); - - // Make sure it also works when there are dups. - EXPECT_TRUE(unittest::TestEnumWithDupValue_IsValid(1)); - EXPECT_TRUE(unittest::TestEnumWithDupValue_IsValid(2)); - EXPECT_TRUE(unittest::TestEnumWithDupValue_IsValid(3)); - - EXPECT_FALSE(unittest::TestEnumWithDupValue_IsValid(0)); - EXPECT_FALSE(unittest::TestEnumWithDupValue_IsValid(4)); -} - -TEST(GeneratedEnumTest, MinAndMax) { - EXPECT_EQ(unittest::TestAllTypes::NEG, - unittest::TestAllTypes::NestedEnum_MIN); - EXPECT_EQ(unittest::TestAllTypes::BAZ, - unittest::TestAllTypes::NestedEnum_MAX); - EXPECT_EQ(4, unittest::TestAllTypes::NestedEnum_ARRAYSIZE); - - EXPECT_EQ(unittest::FOREIGN_FOO, unittest::ForeignEnum_MIN); - EXPECT_EQ(unittest::FOREIGN_BAZ, unittest::ForeignEnum_MAX); - EXPECT_EQ(7, unittest::ForeignEnum_ARRAYSIZE); - - EXPECT_EQ(1, unittest::TestEnumWithDupValue_MIN); - EXPECT_EQ(3, unittest::TestEnumWithDupValue_MAX); - EXPECT_EQ(4, unittest::TestEnumWithDupValue_ARRAYSIZE); - - EXPECT_EQ(unittest::SPARSE_E, unittest::TestSparseEnum_MIN); - EXPECT_EQ(unittest::SPARSE_C, unittest::TestSparseEnum_MAX); - EXPECT_EQ(12589235, unittest::TestSparseEnum_ARRAYSIZE); - - // Make sure we can take the address of _MIN, _MAX and _ARRAYSIZE. - void* null_pointer = 0; // NULL may be integer-type, not pointer-type. - EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_MIN); - EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_MAX); - EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_ARRAYSIZE); - - EXPECT_NE(null_pointer, &unittest::ForeignEnum_MIN); - EXPECT_NE(null_pointer, &unittest::ForeignEnum_MAX); - EXPECT_NE(null_pointer, &unittest::ForeignEnum_ARRAYSIZE); - - // Make sure we can use _MIN and _MAX as switch cases. - switch (unittest::SPARSE_A) { - case unittest::TestSparseEnum_MIN: - case unittest::TestSparseEnum_MAX: - break; - default: - break; - } -} - -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - -TEST(GeneratedEnumTest, Name) { - // "Names" in the presence of dup values are a bit arbitrary. - EXPECT_EQ("FOO1", unittest::TestEnumWithDupValue_Name(unittest::FOO1)); - EXPECT_EQ("FOO1", unittest::TestEnumWithDupValue_Name(unittest::FOO2)); - - EXPECT_EQ("SPARSE_A", unittest::TestSparseEnum_Name(unittest::SPARSE_A)); - EXPECT_EQ("SPARSE_B", unittest::TestSparseEnum_Name(unittest::SPARSE_B)); - EXPECT_EQ("SPARSE_C", unittest::TestSparseEnum_Name(unittest::SPARSE_C)); - EXPECT_EQ("SPARSE_D", unittest::TestSparseEnum_Name(unittest::SPARSE_D)); - EXPECT_EQ("SPARSE_E", unittest::TestSparseEnum_Name(unittest::SPARSE_E)); - EXPECT_EQ("SPARSE_F", unittest::TestSparseEnum_Name(unittest::SPARSE_F)); - EXPECT_EQ("SPARSE_G", unittest::TestSparseEnum_Name(unittest::SPARSE_G)); -} - -TEST(GeneratedEnumTest, Parse) { - unittest::TestEnumWithDupValue dup_value = unittest::FOO1; - EXPECT_TRUE(unittest::TestEnumWithDupValue_Parse("FOO1", &dup_value)); - EXPECT_EQ(unittest::FOO1, dup_value); - EXPECT_TRUE(unittest::TestEnumWithDupValue_Parse("FOO2", &dup_value)); - EXPECT_EQ(unittest::FOO2, dup_value); - EXPECT_FALSE(unittest::TestEnumWithDupValue_Parse("FOO", &dup_value)); -} - -TEST(GeneratedEnumTest, GetEnumDescriptor) { - EXPECT_EQ(unittest::TestAllTypes::NestedEnum_descriptor(), - GetEnumDescriptor()); - EXPECT_EQ(unittest::ForeignEnum_descriptor(), - GetEnumDescriptor()); - EXPECT_EQ(unittest::TestEnumWithDupValue_descriptor(), - GetEnumDescriptor()); - EXPECT_EQ(unittest::TestSparseEnum_descriptor(), - GetEnumDescriptor()); -} - -enum NonProtoEnum { - kFoo = 1, -}; - -TEST(GeneratedEnumTest, IsProtoEnumTypeTrait) { - EXPECT_TRUE(is_proto_enum::value); - EXPECT_TRUE(is_proto_enum::value); - EXPECT_TRUE(is_proto_enum::value); - EXPECT_TRUE(is_proto_enum::value); - - EXPECT_FALSE(is_proto_enum::value); - EXPECT_FALSE(is_proto_enum::value); -} - -#endif // PROTOBUF_TEST_NO_DESCRIPTORS - -// =================================================================== - -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - -// Support code for testing services. -class GeneratedServiceTest : public testing::Test { - protected: - class MockTestService : public unittest::TestService { - public: - MockTestService() - : called_(false), - method_(""), - controller_(NULL), - request_(NULL), - response_(NULL), - done_(NULL) {} - - ~MockTestService() {} - - void Reset() { called_ = false; } - - // implements TestService ---------------------------------------- - - void Foo(RpcController* controller, - const unittest::FooRequest* request, - unittest::FooResponse* response, - Closure* done) { - ASSERT_FALSE(called_); - called_ = true; - method_ = "Foo"; - controller_ = controller; - request_ = request; - response_ = response; - done_ = done; - } - - void Bar(RpcController* controller, - const unittest::BarRequest* request, - unittest::BarResponse* response, - Closure* done) { - ASSERT_FALSE(called_); - called_ = true; - method_ = "Bar"; - controller_ = controller; - request_ = request; - response_ = response; - done_ = done; - } - - // --------------------------------------------------------------- - - bool called_; - string method_; - RpcController* controller_; - const Message* request_; - Message* response_; - Closure* done_; - }; - - class MockRpcChannel : public RpcChannel { - public: - MockRpcChannel() - : called_(false), - method_(NULL), - controller_(NULL), - request_(NULL), - response_(NULL), - done_(NULL), - destroyed_(NULL) {} - - ~MockRpcChannel() { - if (destroyed_ != NULL) *destroyed_ = true; - } - - void Reset() { called_ = false; } - - // implements TestService ---------------------------------------- - - void CallMethod(const MethodDescriptor* method, - RpcController* controller, - const Message* request, - Message* response, - Closure* done) { - ASSERT_FALSE(called_); - called_ = true; - method_ = method; - controller_ = controller; - request_ = request; - response_ = response; - done_ = done; - } - - // --------------------------------------------------------------- - - bool called_; - const MethodDescriptor* method_; - RpcController* controller_; - const Message* request_; - Message* response_; - Closure* done_; - bool* destroyed_; - }; - - class MockController : public RpcController { - public: - void Reset() { - ADD_FAILURE() << "Reset() not expected during this test."; - } - bool Failed() const { - ADD_FAILURE() << "Failed() not expected during this test."; - return false; - } - string ErrorText() const { - ADD_FAILURE() << "ErrorText() not expected during this test."; - return ""; - } - void StartCancel() { - ADD_FAILURE() << "StartCancel() not expected during this test."; - } - void SetFailed(const string& reason) { - ADD_FAILURE() << "SetFailed() not expected during this test."; - } - bool IsCanceled() const { - ADD_FAILURE() << "IsCanceled() not expected during this test."; - return false; - } - void NotifyOnCancel(Closure* callback) { - ADD_FAILURE() << "NotifyOnCancel() not expected during this test."; - } - }; - - GeneratedServiceTest() - : descriptor_(unittest::TestService::descriptor()), - foo_(descriptor_->FindMethodByName("Foo")), - bar_(descriptor_->FindMethodByName("Bar")), - stub_(&mock_channel_), - done_(::google::protobuf::NewPermanentCallback(&DoNothing)) {} - - virtual void SetUp() { - ASSERT_TRUE(foo_ != NULL); - ASSERT_TRUE(bar_ != NULL); - } - - const ServiceDescriptor* descriptor_; - const MethodDescriptor* foo_; - const MethodDescriptor* bar_; - - MockTestService mock_service_; - MockController mock_controller_; - - MockRpcChannel mock_channel_; - unittest::TestService::Stub stub_; - - // Just so we don't have to re-define these with every test. - unittest::FooRequest foo_request_; - unittest::FooResponse foo_response_; - unittest::BarRequest bar_request_; - unittest::BarResponse bar_response_; - google::protobuf::scoped_ptr done_; -}; - -TEST_F(GeneratedServiceTest, GetDescriptor) { - // Test that GetDescriptor() works. - - EXPECT_EQ(descriptor_, mock_service_.GetDescriptor()); -} - -TEST_F(GeneratedServiceTest, GetChannel) { - EXPECT_EQ(&mock_channel_, stub_.channel()); -} - -TEST_F(GeneratedServiceTest, OwnsChannel) { - MockRpcChannel* channel = new MockRpcChannel; - bool destroyed = false; - channel->destroyed_ = &destroyed; - - { - unittest::TestService::Stub owning_stub(channel, - Service::STUB_OWNS_CHANNEL); - EXPECT_FALSE(destroyed); - } - - EXPECT_TRUE(destroyed); -} - -TEST_F(GeneratedServiceTest, CallMethod) { - // Test that CallMethod() works. - - // Call Foo() via CallMethod(). - mock_service_.CallMethod(foo_, &mock_controller_, - &foo_request_, &foo_response_, done_.get()); - - ASSERT_TRUE(mock_service_.called_); - - EXPECT_EQ("Foo" , mock_service_.method_ ); - EXPECT_EQ(&mock_controller_, mock_service_.controller_); - EXPECT_EQ(&foo_request_ , mock_service_.request_ ); - EXPECT_EQ(&foo_response_ , mock_service_.response_ ); - EXPECT_EQ(done_.get() , mock_service_.done_ ); - - // Try again, but call Bar() instead. - mock_service_.Reset(); - mock_service_.CallMethod(bar_, &mock_controller_, - &bar_request_, &bar_response_, done_.get()); - - ASSERT_TRUE(mock_service_.called_); - EXPECT_EQ("Bar", mock_service_.method_); -} - -TEST_F(GeneratedServiceTest, CallMethodTypeFailure) { - // Verify death if we call Foo() with Bar's message types. - -#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet - EXPECT_DEBUG_DEATH( - mock_service_.CallMethod(foo_, &mock_controller_, - &foo_request_, &bar_response_, done_.get()), - "dynamic_cast"); - - mock_service_.Reset(); - EXPECT_DEBUG_DEATH( - mock_service_.CallMethod(foo_, &mock_controller_, - &bar_request_, &foo_response_, done_.get()), - "dynamic_cast"); -#endif // PROTOBUF_HAS_DEATH_TEST +TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingMessageNames) { + protobuf_unittest::NULL_ message; + message.set_int_(123); + EXPECT_EQ(message.int_(), 123); } -TEST_F(GeneratedServiceTest, GetPrototypes) { - // Test Get{Request,Response}Prototype() methods. - - EXPECT_EQ(&unittest::FooRequest::default_instance(), - &mock_service_.GetRequestPrototype(foo_)); - EXPECT_EQ(&unittest::BarRequest::default_instance(), - &mock_service_.GetRequestPrototype(bar_)); - - EXPECT_EQ(&unittest::FooResponse::default_instance(), - &mock_service_.GetResponsePrototype(foo_)); - EXPECT_EQ(&unittest::BarResponse::default_instance(), - &mock_service_.GetResponsePrototype(bar_)); -} - -TEST_F(GeneratedServiceTest, Stub) { - // Test that the stub class works. - - // Call Foo() via the stub. - stub_.Foo(&mock_controller_, &foo_request_, &foo_response_, done_.get()); - - ASSERT_TRUE(mock_channel_.called_); - - EXPECT_EQ(foo_ , mock_channel_.method_ ); - EXPECT_EQ(&mock_controller_, mock_channel_.controller_); - EXPECT_EQ(&foo_request_ , mock_channel_.request_ ); - EXPECT_EQ(&foo_response_ , mock_channel_.response_ ); - EXPECT_EQ(done_.get() , mock_channel_.done_ ); - - // Call Bar() via the stub. - mock_channel_.Reset(); - stub_.Bar(&mock_controller_, &bar_request_, &bar_response_, done_.get()); - - ASSERT_TRUE(mock_channel_.called_); - EXPECT_EQ(bar_, mock_channel_.method_); -} - -TEST_F(GeneratedServiceTest, NotImplemented) { - // Test that failing to implement a method of a service causes it to fail - // with a "not implemented" error message. - - // A service which doesn't implement any methods. - class UnimplementedService : public unittest::TestService { - public: - UnimplementedService() {} - }; - - UnimplementedService unimplemented_service; - - // And a controller which expects to get a "not implemented" error. - class ExpectUnimplementedController : public MockController { - public: - ExpectUnimplementedController() : called_(false) {} - - void SetFailed(const string& reason) { - EXPECT_FALSE(called_); - called_ = true; - EXPECT_EQ("Method Foo() not implemented.", reason); - } - - bool called_; - }; - - ExpectUnimplementedController controller; - - // Call Foo. - unimplemented_service.Foo(&controller, &foo_request_, &foo_response_, - done_.get()); - - EXPECT_TRUE(controller.called_); -} - -// =================================================================== - -class OneofTest : public testing::Test { - protected: - virtual void SetUp() { - } - - void ExpectEnumCasesWork(const unittest::TestOneof2 &message) { - switch (message.foo_case()) { - case unittest::TestOneof2::kFooInt: - EXPECT_TRUE(message.has_foo_int()); - break; - case unittest::TestOneof2::kFooString: - EXPECT_TRUE(message.has_foo_string()); - break; - case unittest::TestOneof2::kFooCord: - EXPECT_TRUE(message.has_foo_cord()); - break; - case unittest::TestOneof2::kFooStringPiece: - EXPECT_TRUE(message.has_foo_string_piece()); - break; - case unittest::TestOneof2::kFooBytes: - EXPECT_TRUE(message.has_foo_bytes()); - break; - case unittest::TestOneof2::kFooEnum: - EXPECT_TRUE(message.has_foo_enum()); - break; - case unittest::TestOneof2::kFooMessage: - EXPECT_TRUE(message.has_foo_message()); - break; - case unittest::TestOneof2::kFoogroup: - EXPECT_TRUE(message.has_foogroup()); - break; - case unittest::TestOneof2::kFooLazyMessage: - EXPECT_TRUE(message.has_foo_lazy_message()); - break; - case unittest::TestOneof2::FOO_NOT_SET: - break; - } - } -}; - -TEST_F(OneofTest, SettingOneFieldClearsOthers) { - unittest::TestOneof2 message; - - message.set_foo_int(123); - EXPECT_TRUE(message.has_foo_int()); - TestUtil::ExpectAtMostOneFieldSetInOneof(message); - - message.set_foo_string("foo"); - EXPECT_TRUE(message.has_foo_string()); - TestUtil::ExpectAtMostOneFieldSetInOneof(message); - - - message.set_foo_bytes("qux"); - EXPECT_TRUE(message.has_foo_bytes()); - TestUtil::ExpectAtMostOneFieldSetInOneof(message); - - message.set_foo_enum(unittest::TestOneof2::FOO); - EXPECT_TRUE(message.has_foo_enum()); - TestUtil::ExpectAtMostOneFieldSetInOneof(message); - - message.mutable_foo_message()->set_qux_int(234); - EXPECT_TRUE(message.has_foo_message()); - TestUtil::ExpectAtMostOneFieldSetInOneof(message); - - message.mutable_foogroup()->set_a(345); - EXPECT_TRUE(message.has_foogroup()); - TestUtil::ExpectAtMostOneFieldSetInOneof(message); - - - // we repeat this because we didn't test if this properly clears other fields - // at the beginning. - message.set_foo_int(123); - EXPECT_TRUE(message.has_foo_int()); - TestUtil::ExpectAtMostOneFieldSetInOneof(message); -} - -TEST_F(OneofTest, EnumCases) { - unittest::TestOneof2 message; - - message.set_foo_int(123); - ExpectEnumCasesWork(message); - message.set_foo_string("foo"); - ExpectEnumCasesWork(message); - message.set_foo_bytes("qux"); - ExpectEnumCasesWork(message); - message.set_foo_enum(unittest::TestOneof2::FOO); - ExpectEnumCasesWork(message); - message.mutable_foo_message()->set_qux_int(234); - ExpectEnumCasesWork(message); - message.mutable_foogroup()->set_a(345); - ExpectEnumCasesWork(message); -} - -TEST_F(OneofTest, PrimitiveType) { - unittest::TestOneof2 message; - // Unset field returns default value - EXPECT_EQ(message.foo_int(), 0); - - message.set_foo_int(123); - EXPECT_TRUE(message.has_foo_int()); - EXPECT_EQ(message.foo_int(), 123); - message.clear_foo_int(); - EXPECT_FALSE(message.has_foo_int()); -} - -TEST_F(OneofTest, EnumType) { - unittest::TestOneof2 message; - // Unset field returns default value - EXPECT_EQ(message.foo_enum(), 1); - - message.set_foo_enum(unittest::TestOneof2::FOO); - EXPECT_TRUE(message.has_foo_enum()); - EXPECT_EQ(message.foo_enum(), unittest::TestOneof2::FOO); - message.clear_foo_enum(); - EXPECT_FALSE(message.has_foo_enum()); -} - -TEST_F(OneofTest, SetString) { - // Check that setting a string field in various ways works - unittest::TestOneof2 message; - - // Unset field returns default value - EXPECT_EQ(message.foo_string(), ""); - - message.set_foo_string("foo"); - EXPECT_TRUE(message.has_foo_string()); - EXPECT_EQ(message.foo_string(), "foo"); - message.clear_foo_string(); - EXPECT_FALSE(message.has_foo_string()); - - message.set_foo_string(string("bar")); - EXPECT_TRUE(message.has_foo_string()); - EXPECT_EQ(message.foo_string(), "bar"); - message.clear_foo_string(); - EXPECT_FALSE(message.has_foo_string()); - - - message.set_foo_string("qux", 3); - EXPECT_TRUE(message.has_foo_string()); - EXPECT_EQ(message.foo_string(), "qux"); - message.clear_foo_string(); - EXPECT_FALSE(message.has_foo_string()); - - message.mutable_foo_string()->assign("quux"); - EXPECT_TRUE(message.has_foo_string()); - EXPECT_EQ(message.foo_string(), "quux"); - message.clear_foo_string(); - EXPECT_FALSE(message.has_foo_string()); - - message.set_foo_string("corge"); - EXPECT_TRUE(message.has_foo_string()); - EXPECT_EQ(message.foo_string(), "corge"); - message.clear_foo_string(); - EXPECT_FALSE(message.has_foo_string()); -} - -TEST_F(OneofTest, ReleaseString) { - // Check that release_foo() starts out NULL, and gives us a value - // that we can delete after it's been set. - unittest::TestOneof2 message; - - EXPECT_EQ(NULL, message.release_foo_string()); - EXPECT_FALSE(message.has_foo_string()); - - message.set_foo_string("blah"); - EXPECT_TRUE(message.has_foo_string()); - google::protobuf::scoped_ptr str(message.release_foo_string()); - EXPECT_FALSE(message.has_foo_string()); - ASSERT_TRUE(str != NULL); - EXPECT_EQ("blah", *str); - - EXPECT_EQ(NULL, message.release_foo_string()); - EXPECT_FALSE(message.has_foo_string()); -} - -TEST_F(OneofTest, SetAllocatedString) { - // Check that set_allocated_foo() works for strings. - unittest::TestOneof2 message; - - EXPECT_FALSE(message.has_foo_string()); - const string kHello("hello"); - message.set_foo_string(kHello); - EXPECT_TRUE(message.has_foo_string()); - - message.set_allocated_foo_string(NULL); - EXPECT_FALSE(message.has_foo_string()); - EXPECT_EQ("", message.foo_string()); - - message.set_allocated_foo_string(new string(kHello)); - EXPECT_TRUE(message.has_foo_string()); - EXPECT_EQ(kHello, message.foo_string()); -} - - -TEST_F(OneofTest, SetMessage) { - // Check that setting a message field works - unittest::TestOneof2 message; - - // Unset field returns default instance - EXPECT_EQ(&message.foo_message(), - &unittest::TestOneof2_NestedMessage::default_instance()); - EXPECT_EQ(message.foo_message().qux_int(), 0); - - message.mutable_foo_message()->set_qux_int(234); - EXPECT_TRUE(message.has_foo_message()); - EXPECT_EQ(message.foo_message().qux_int(), 234); - message.clear_foo_message(); - EXPECT_FALSE(message.has_foo_message()); -} - -TEST_F(OneofTest, ReleaseMessage) { - // Check that release_foo() starts out NULL, and gives us a value - // that we can delete after it's been set. - unittest::TestOneof2 message; - - EXPECT_EQ(NULL, message.release_foo_message()); - EXPECT_FALSE(message.has_foo_message()); - - message.mutable_foo_message()->set_qux_int(1); - EXPECT_TRUE(message.has_foo_message()); - google::protobuf::scoped_ptr mes( - message.release_foo_message()); - EXPECT_FALSE(message.has_foo_message()); - ASSERT_TRUE(mes != NULL); - EXPECT_EQ(1, mes->qux_int()); - - EXPECT_EQ(NULL, message.release_foo_message()); - EXPECT_FALSE(message.has_foo_message()); -} - -TEST_F(OneofTest, SetAllocatedMessage) { - // Check that set_allocated_foo() works for messages. - unittest::TestOneof2 message; - - EXPECT_FALSE(message.has_foo_message()); - - message.mutable_foo_message()->set_qux_int(1); - EXPECT_TRUE(message.has_foo_message()); - - message.set_allocated_foo_message(NULL); - EXPECT_FALSE(message.has_foo_message()); - EXPECT_EQ(&message.foo_message(), - &unittest::TestOneof2_NestedMessage::default_instance()); - - message.mutable_foo_message()->set_qux_int(1); - unittest::TestOneof2_NestedMessage* mes = message.release_foo_message(); - ASSERT_TRUE(mes != NULL); - EXPECT_FALSE(message.has_foo_message()); - - message.set_allocated_foo_message(mes); - EXPECT_TRUE(message.has_foo_message()); - EXPECT_EQ(1, message.foo_message().qux_int()); -} - - -TEST_F(OneofTest, Clear) { - unittest::TestOneof2 message; - - message.set_foo_int(1); - EXPECT_TRUE(message.has_foo_int()); - message.clear_foo_int(); - EXPECT_FALSE(message.has_foo_int()); -} - -TEST_F(OneofTest, Defaults) { - unittest::TestOneof2 message; - - EXPECT_FALSE(message.has_foo_int()); - EXPECT_EQ(message.foo_int(), 0); - - EXPECT_FALSE(message.has_foo_string()); - EXPECT_EQ(message.foo_string(), ""); - - - EXPECT_FALSE(message.has_foo_bytes()); - EXPECT_EQ(message.foo_bytes(), ""); - - EXPECT_FALSE(message.has_foo_enum()); - EXPECT_EQ(message.foo_enum(), 1); - - EXPECT_FALSE(message.has_foo_message()); - EXPECT_EQ(message.foo_message().qux_int(), 0); - - EXPECT_FALSE(message.has_foogroup()); - EXPECT_EQ(message.foogroup().a(), 0); - - - EXPECT_FALSE(message.has_bar_int()); - EXPECT_EQ(message.bar_int(), 5); - - EXPECT_FALSE(message.has_bar_string()); - EXPECT_EQ(message.bar_string(), "STRING"); - - - EXPECT_FALSE(message.has_bar_bytes()); - EXPECT_EQ(message.bar_bytes(), "BYTES"); - - EXPECT_FALSE(message.has_bar_enum()); - EXPECT_EQ(message.bar_enum(), 2); -} - -TEST_F(OneofTest, SwapWithEmpty) { - unittest::TestOneof2 message1, message2; - message1.set_foo_string("FOO"); - EXPECT_TRUE(message1.has_foo_string()); - message1.Swap(&message2); - EXPECT_FALSE(message1.has_foo_string()); - EXPECT_TRUE(message2.has_foo_string()); - EXPECT_EQ(message2.foo_string(), "FOO"); -} - -TEST_F(OneofTest, SwapWithSelf) { - unittest::TestOneof2 message; - message.set_foo_string("FOO"); - EXPECT_TRUE(message.has_foo_string()); - message.Swap(&message); - EXPECT_TRUE(message.has_foo_string()); - EXPECT_EQ(message.foo_string(), "FOO"); -} - -TEST_F(OneofTest, SwapBothHasFields) { - unittest::TestOneof2 message1, message2; - - message1.set_foo_string("FOO"); - EXPECT_TRUE(message1.has_foo_string()); - message2.mutable_foo_message()->set_qux_int(1); - EXPECT_TRUE(message2.has_foo_message()); - - message1.Swap(&message2); - EXPECT_FALSE(message1.has_foo_string()); - EXPECT_FALSE(message2.has_foo_message()); - EXPECT_TRUE(message1.has_foo_message()); - EXPECT_EQ(message1.foo_message().qux_int(), 1); - EXPECT_TRUE(message2.has_foo_string()); - EXPECT_EQ(message2.foo_string(), "FOO"); -} - -TEST_F(OneofTest, CopyConstructor) { - unittest::TestOneof2 message1; - message1.set_foo_bytes("FOO"); - - unittest::TestOneof2 message2(message1); - EXPECT_TRUE(message2.has_foo_bytes()); - EXPECT_EQ(message2.foo_bytes(), "FOO"); -} - -TEST_F(OneofTest, CopyFrom) { - unittest::TestOneof2 message1, message2; - message1.set_foo_enum(unittest::TestOneof2::BAR); - EXPECT_TRUE(message1.has_foo_enum()); - - message2.CopyFrom(message1); - EXPECT_TRUE(message2.has_foo_enum()); - EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::BAR); - - // Copying from self should be a no-op. - message2.CopyFrom(message2); - EXPECT_TRUE(message2.has_foo_enum()); - EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::BAR); -} - -TEST_F(OneofTest, CopyAssignmentOperator) { - unittest::TestOneof2 message1; - message1.mutable_foo_message()->set_qux_int(123); - EXPECT_TRUE(message1.has_foo_message()); - - unittest::TestOneof2 message2; - message2 = message1; - EXPECT_EQ(message2.foo_message().qux_int(), 123); - - // Make sure that self-assignment does something sane. - message2 = message2; - EXPECT_EQ(message2.foo_message().qux_int(), 123); -} - -TEST_F(OneofTest, UpcastCopyFrom) { - // Test the CopyFrom method that takes in the generic const Message& - // parameter. - unittest::TestOneof2 message1, message2; - message1.mutable_foogroup()->set_a(123); - EXPECT_TRUE(message1.has_foogroup()); - - const Message* source = implicit_cast(&message1); - message2.CopyFrom(*source); - - EXPECT_TRUE(message2.has_foogroup()); - EXPECT_EQ(message2.foogroup().a(), 123); -} - -// Test the generated SerializeWithCachedSizesToArray(), -// This indirectly tests MergePartialFromCodedStream() -// We have to test each field type separately because we cannot set them at the -// same time -TEST_F(OneofTest, SerializationToArray) { - // Primitive type - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_int(123); - int size = message1.ByteSize(); - data.resize(size); - uint8* start = reinterpret_cast(string_as_array(&data)); - uint8* end = message1.SerializeWithCachedSizesToArray(start); - EXPECT_EQ(size, end - start); - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_int(), 123); - } - - // String - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_string("foo"); - int size = message1.ByteSize(); - data.resize(size); - uint8* start = reinterpret_cast(string_as_array(&data)); - uint8* end = message1.SerializeWithCachedSizesToArray(start); - EXPECT_EQ(size, end - start); - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_string(), "foo"); - } - - - // Bytes - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_bytes("qux"); - int size = message1.ByteSize(); - data.resize(size); - uint8* start = reinterpret_cast(string_as_array(&data)); - uint8* end = message1.SerializeWithCachedSizesToArray(start); - EXPECT_EQ(size, end - start); - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_bytes(), "qux"); - } - - // Enum - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_enum(unittest::TestOneof2::FOO); - int size = message1.ByteSize(); - data.resize(size); - uint8* start = reinterpret_cast(string_as_array(&data)); - uint8* end = message1.SerializeWithCachedSizesToArray(start); - EXPECT_EQ(size, end - start); - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO); - } - - // Message - { - unittest::TestOneof2 message1, message2; - string data; - message1.mutable_foo_message()->set_qux_int(234); - int size = message1.ByteSize(); - data.resize(size); - uint8* start = reinterpret_cast(string_as_array(&data)); - uint8* end = message1.SerializeWithCachedSizesToArray(start); - EXPECT_EQ(size, end - start); - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_message().qux_int(), 234); - } - - // Group - { - unittest::TestOneof2 message1, message2; - string data; - message1.mutable_foogroup()->set_a(345); - int size = message1.ByteSize(); - data.resize(size); - uint8* start = reinterpret_cast(string_as_array(&data)); - uint8* end = message1.SerializeWithCachedSizesToArray(start); - EXPECT_EQ(size, end - start); - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foogroup().a(), 345); - } - -} - -// Test the generated SerializeWithCachedSizes() by forcing the buffer to write -// one byte at a time. -// This indirectly tests MergePartialFromCodedStream() -// We have to test each field type separately because we cannot set them at the -// same time -TEST_F(OneofTest, SerializationToStream) { - // Primitive type - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_int(123); - int size = message1.ByteSize(); - data.resize(size); - - { - // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); - io::CodedOutputStream output_stream(&array_stream); - message1.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); - } - - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_int(), 123); - } - - // String - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_string("foo"); - int size = message1.ByteSize(); - data.resize(size); - - { - // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); - io::CodedOutputStream output_stream(&array_stream); - message1.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); - } - - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_string(), "foo"); - } - - - // Bytes - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_bytes("qux"); - int size = message1.ByteSize(); - data.resize(size); - - { - // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); - io::CodedOutputStream output_stream(&array_stream); - message1.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); - } - - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_bytes(), "qux"); - } - - // Enum - { - unittest::TestOneof2 message1, message2; - string data; - message1.set_foo_enum(unittest::TestOneof2::FOO); - int size = message1.ByteSize(); - data.resize(size); - - { - // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); - io::CodedOutputStream output_stream(&array_stream); - message1.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); - } - - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO); - } - - // Message - { - unittest::TestOneof2 message1, message2; - string data; - message1.mutable_foo_message()->set_qux_int(234); - int size = message1.ByteSize(); - data.resize(size); - - { - // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); - io::CodedOutputStream output_stream(&array_stream); - message1.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); - } - - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foo_message().qux_int(), 234); - } - - // Group - { - unittest::TestOneof2 message1, message2; - string data; - message1.mutable_foogroup()->set_a(345); - int size = message1.ByteSize(); - data.resize(size); - - { - // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); - io::CodedOutputStream output_stream(&array_stream); - message1.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); - } - - EXPECT_TRUE(message2.ParseFromString(data)); - EXPECT_EQ(message2.foogroup().a(), 345); - } - -} - -TEST_F(OneofTest, MergeFrom) { - unittest::TestOneof2 message1, message2; - - message1.set_foo_int(123); - message2.MergeFrom(message1); - TestUtil::ExpectAtMostOneFieldSetInOneof(message2); - EXPECT_TRUE(message2.has_foo_int()); - EXPECT_EQ(message2.foo_int(), 123); - - message1.set_foo_string("foo"); - message2.MergeFrom(message1); - TestUtil::ExpectAtMostOneFieldSetInOneof(message2); - EXPECT_TRUE(message2.has_foo_string()); - EXPECT_EQ(message2.foo_string(), "foo"); - - - message1.set_foo_bytes("qux"); - message2.MergeFrom(message1); - TestUtil::ExpectAtMostOneFieldSetInOneof(message2); - EXPECT_TRUE(message2.has_foo_bytes()); - EXPECT_EQ(message2.foo_bytes(), "qux"); - - message1.set_foo_enum(unittest::TestOneof2::FOO); - message2.MergeFrom(message1); - TestUtil::ExpectAtMostOneFieldSetInOneof(message2); - EXPECT_TRUE(message2.has_foo_enum()); - EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO); - - message1.mutable_foo_message()->set_qux_int(234); - message2.MergeFrom(message1); - TestUtil::ExpectAtMostOneFieldSetInOneof(message2); - EXPECT_TRUE(message2.has_foo_message()); - EXPECT_EQ(message2.foo_message().qux_int(), 234); - - message1.mutable_foogroup()->set_a(345); - message2.MergeFrom(message1); - TestUtil::ExpectAtMostOneFieldSetInOneof(message2); - EXPECT_TRUE(message2.has_foogroup()); - EXPECT_EQ(message2.foogroup().a(), 345); - -} - -TEST(HelpersTest, TestSCC) { - protobuf_unittest::TestMutualRecursionA a; - SCCAnalyzer scc_analyzer((Options())); - const SCC* scc = scc_analyzer.GetSCC(a.GetDescriptor()); - std::vector names; - for (int i = 0; i < scc->descriptors.size(); i++) { - names.push_back(scc->descriptors[i]->full_name()); - } - ASSERT_EQ(names.size(), 4); - std::sort(names.begin(), names.end()); - EXPECT_EQ(names[0], "protobuf_unittest.TestMutualRecursionA"); - EXPECT_EQ(names[1], "protobuf_unittest.TestMutualRecursionA.SubGroup"); - EXPECT_EQ(names[2], "protobuf_unittest.TestMutualRecursionA.SubMessage"); - EXPECT_EQ(names[3], "protobuf_unittest.TestMutualRecursionB"); - - MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc); - EXPECT_EQ(result.is_recursive, true); - EXPECT_EQ(result.contains_required, false); - EXPECT_EQ(result.contains_cord, true); // TestAllTypes - EXPECT_EQ(result.contains_extension, false); // TestAllTypes -} - -TEST(HelpersTest, TestSCCAnalysis) { - { - protobuf_unittest::TestRecursiveMessage msg; - SCCAnalyzer scc_analyzer((Options())); - const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor()); - MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc); - EXPECT_EQ(result.is_recursive, true); - EXPECT_EQ(result.contains_required, false); - EXPECT_EQ(result.contains_cord, false); - EXPECT_EQ(result.contains_extension, false); - } - { - protobuf_unittest::TestAllExtensions msg; - SCCAnalyzer scc_analyzer((Options())); - const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor()); - MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc); - EXPECT_EQ(result.is_recursive, false); - EXPECT_EQ(result.contains_required, false); - EXPECT_EQ(result.contains_cord, false); - EXPECT_EQ(result.contains_extension, true); - } - { - protobuf_unittest::TestRequired msg; - SCCAnalyzer scc_analyzer((Options())); - const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor()); - MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc); - EXPECT_EQ(result.is_recursive, false); - EXPECT_EQ(result.contains_required, true); - EXPECT_EQ(result.contains_cord, false); - EXPECT_EQ(result.contains_extension, false); - } -} - -} // namespace cpp_unittest -} // namespace cpp -} // namespace compiler - -namespace no_generic_services_test { - // Verify that no class called "TestService" was defined in - // unittest_no_generic_services.pb.h by defining a different type by the same - // name. If such a service was generated, this will not compile. - struct TestService { - int i; - }; -} - -namespace compiler { -namespace cpp { -namespace cpp_unittest { - -TEST_F(GeneratedServiceTest, NoGenericServices) { - // Verify that non-services in unittest_no_generic_services.proto were - // generated. - no_generic_services_test::TestMessage message; - message.set_a(1); - message.SetExtension(no_generic_services_test::test_extension, 123); - no_generic_services_test::TestEnum e = no_generic_services_test::FOO; - EXPECT_EQ(e, 1); - - // Verify that a ServiceDescriptor is generated for the service even if the - // class itself is not. - const FileDescriptor* file = - no_generic_services_test::TestMessage::descriptor()->file(); - - ASSERT_EQ(1, file->service_count()); - EXPECT_EQ("TestService", file->service(0)->name()); - ASSERT_EQ(1, file->service(0)->method_count()); - EXPECT_EQ("Foo", file->service(0)->method(0)->name()); -} - -#endif // !PROTOBUF_TEST_NO_DESCRIPTORS - -// =================================================================== - -// This test must run last. It verifies that descriptors were or were not -// initialized depending on whether PROTOBUF_TEST_NO_DESCRIPTORS was defined. -// When this is defined, we skip all tests which are expected to trigger -// descriptor initialization. This verifies that everything else still works -// if descriptors are not initialized. -TEST(DescriptorInitializationTest, Initialized) { -#ifdef PROTOBUF_TEST_NO_DESCRIPTORS - bool should_have_descriptors = false; -#else - bool should_have_descriptors = true; -#endif - - EXPECT_EQ(should_have_descriptors, - DescriptorPool::generated_pool()->InternalIsFileLoaded( - "google/protobuf/unittest.proto")); +TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingExtension) { + protobuf_unittest::TestConflictingSymbolNames message; + message.SetExtension(protobuf_unittest::void_, 123); + EXPECT_EQ(123, message.GetExtension(protobuf_unittest::void_)); } } // namespace cpp_unittest - } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.h b/src/google/protobuf/compiler/cpp/cpp_unittest.h index 69c8f44c1d9ca..c5dc767ae5d28 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.h +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.h @@ -46,6 +46,6 @@ namespace google { namespace protobuf { namespace protobuf_unittest {} } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.inc b/src/google/protobuf/compiler/cpp/cpp_unittest.inc new file mode 100644 index 0000000000000..c8238abdef3bd --- /dev/null +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.inc @@ -0,0 +1,2231 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// To test the code generator, we actually use it to generate code for +// net/proto2/internal/unittest.proto, then test that. This means that we +// are actually testing the parser and other parts of the system at the same +// time, and that problems in the generator may show up as compile-time errors +// rather than unittest failures, which may be surprising. However, testing +// the output of the C++ generator directly would be very hard. We can't very +// well just check it against golden files since those files would have to be +// updated for any small change; such a test would be very brittle and probably +// not very helpful. What we really want to test is that the code compiles +// correctly and produces the interfaces we expect, which is why this test +// is written this way. + +#include +#include + +#include +#include +#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER) +// We exclude this large proto from cmake build because it's too large for +// visual studio to compile (report internal errors). +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// Must be included last. +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +// Can't use an anonymous namespace here due to brokenness of Tru64 compiler. +namespace cpp_unittest { + + +class MockErrorCollector : public MultiFileErrorCollector { + public: + MockErrorCollector() {} + ~MockErrorCollector() {} + + std::string text_; + + // implements ErrorCollector --------------------------------------- + void AddError(const std::string& filename, int line, int column, + const std::string& message) { + strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column, + message); + } +}; + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + +// Test that generated code has proper descriptors: +// Parse a descriptor directly (using google::protobuf::compiler::Importer) and +// compare it to the one that was produced by generated code. +TEST(GENERATED_DESCRIPTOR_TEST_NAME, IdenticalDescriptors) { + const FileDescriptor* generated_descriptor = + UNITTEST::TestAllTypes::descriptor()->file(); + + // Set up the Importer. + MockErrorCollector error_collector; + DiskSourceTree source_tree; + source_tree.MapPath("", TestUtil::TestSourceDir()); + Importer importer(&source_tree, &error_collector); + + // Import (parse) unittest.proto. + const FileDescriptor* parsed_descriptor = + importer.Import(TestUtil::MaybeTranslatePath(UNITTEST_PROTO_PATH)); + EXPECT_EQ("", error_collector.text_); + ASSERT_TRUE(parsed_descriptor != NULL); + + // Test that descriptors are generated correctly by converting them to + // FileDescriptorProtos and comparing. + FileDescriptorProto generated_descriptor_proto, parsed_descriptor_proto; + generated_descriptor->CopyTo(&generated_descriptor_proto); + parsed_descriptor->CopyTo(&parsed_descriptor_proto); + + EXPECT_EQ(parsed_descriptor_proto.DebugString(), + generated_descriptor_proto.DebugString()); +} + +#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER) +// Test that generated code has proper descriptors: +// Touch a descriptor generated from an enormous message to validate special +// handling for descriptors exceeding the C++ standard's recommended minimum +// limit for string literal size +TEST(GENERATED_DESCRIPTOR_TEST_NAME, EnormousDescriptor) { + const Descriptor* generated_descriptor = + ::protobuf_unittest::TestEnormousDescriptor::descriptor(); + + EXPECT_TRUE(generated_descriptor != NULL); +} +#endif + +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS + +// =================================================================== + +TEST(GENERATED_MESSAGE_TEST_NAME, Defaults) { + // Check that all default values are set correctly in the initial message. + UNITTEST::TestAllTypes message; + + TestUtil::ExpectClear(message); + + // Messages should return pointers to default instances until first use. + // (This is not checked by ExpectClear() since it is not actually true after + // the fields have been set and then cleared.) + EXPECT_EQ(&UNITTEST::TestAllTypes::OptionalGroup::default_instance(), + &message.optionalgroup()); + EXPECT_EQ(&UNITTEST::TestAllTypes::NestedMessage::default_instance(), + &message.optional_nested_message()); + EXPECT_EQ(&UNITTEST::ForeignMessage::default_instance(), + &message.optional_foreign_message()); + EXPECT_EQ(&UNITTEST_IMPORT::ImportMessage::default_instance(), + &message.optional_import_message()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, FloatingPointDefaults) { + const UNITTEST::TestExtremeDefaultValues& extreme_default = + UNITTEST::TestExtremeDefaultValues::default_instance(); + + EXPECT_EQ(0.0f, extreme_default.zero_float()); + EXPECT_EQ(1.0f, extreme_default.one_float()); + EXPECT_EQ(1.5f, extreme_default.small_float()); + EXPECT_EQ(-1.0f, extreme_default.negative_one_float()); + EXPECT_EQ(-1.5f, extreme_default.negative_float()); + EXPECT_EQ(2.0e8f, extreme_default.large_float()); + EXPECT_EQ(-8e-28f, extreme_default.small_negative_float()); + EXPECT_EQ(std::numeric_limits::infinity(), + extreme_default.inf_double()); + EXPECT_EQ(-std::numeric_limits::infinity(), + extreme_default.neg_inf_double()); + EXPECT_TRUE(extreme_default.nan_double() != extreme_default.nan_double()); + EXPECT_EQ(std::numeric_limits::infinity(), + extreme_default.inf_float()); + EXPECT_EQ(-std::numeric_limits::infinity(), + extreme_default.neg_inf_float()); + EXPECT_TRUE(extreme_default.nan_float() != extreme_default.nan_float()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, Trigraph) { + const UNITTEST::TestExtremeDefaultValues& extreme_default = + UNITTEST::TestExtremeDefaultValues::default_instance(); + + EXPECT_EQ("? ? ?? ?? ??? ?\?/ ?\?-", extreme_default.cpp_trigraph()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, ExtremeSmallIntegerDefault) { + const UNITTEST::TestExtremeDefaultValues& extreme_default = + UNITTEST::TestExtremeDefaultValues::default_instance(); + EXPECT_EQ(~0x7fffffff, kint32min); + EXPECT_EQ(PROTOBUF_LONGLONG(~0x7fffffffffffffff), kint64min); + EXPECT_EQ(kint32min, extreme_default.really_small_int32()); + EXPECT_EQ(kint64min, extreme_default.really_small_int64()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, Accessors) { + // Set every field to a unique value then go back and check all those + // values. + UNITTEST::TestAllTypes message; + + TestUtil::SetAllFields(&message); + TestUtil::ExpectAllFieldsSet(message); + + TestUtil::ModifyRepeatedFields(&message); + TestUtil::ExpectRepeatedFieldsModified(message); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, MutableStringDefault) { + // mutable_foo() for a string should return a string initialized to its + // default value. + UNITTEST::TestAllTypes message; + + EXPECT_EQ("hello", *message.mutable_default_string()); + + // Note that the first time we call mutable_foo(), we get a newly-allocated + // string, but if we clear it and call it again, we get the same object again. + // We should verify that it has its default value in both cases. + message.set_default_string("blah"); + message.Clear(); + + EXPECT_EQ("hello", *message.mutable_default_string()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, StringDefaults) { + UNITTEST::TestExtremeDefaultValues message; + // Check if '\000' can be used in default string value. + EXPECT_EQ(std::string("hel\000lo", 6), message.string_with_zero()); + EXPECT_EQ(std::string("wor\000ld", 6), message.bytes_with_zero()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, ReleaseString) { + // Check that release_foo() starts out NULL, and gives us a value + // that we can delete after it's been set. + UNITTEST::TestAllTypes message; + + EXPECT_EQ(NULL, message.release_default_string()); + EXPECT_FALSE(message.has_default_string()); + EXPECT_EQ("hello", message.default_string()); + + message.set_default_string("blah"); + EXPECT_TRUE(message.has_default_string()); + std::unique_ptr str(message.release_default_string()); + EXPECT_FALSE(message.has_default_string()); + ASSERT_TRUE(str != NULL); + EXPECT_EQ("blah", *str); + + EXPECT_EQ(NULL, message.release_default_string()); + EXPECT_FALSE(message.has_default_string()); + EXPECT_EQ("hello", message.default_string()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, ReleaseMessage) { + // Check that release_foo() starts out NULL, and gives us a value + // that we can delete after it's been set. + UNITTEST::TestAllTypes message; + + EXPECT_EQ(NULL, message.release_optional_nested_message()); + EXPECT_FALSE(message.has_optional_nested_message()); + + message.mutable_optional_nested_message()->set_bb(1); + std::unique_ptr nest( + message.release_optional_nested_message()); + EXPECT_FALSE(message.has_optional_nested_message()); + ASSERT_TRUE(nest != NULL); + EXPECT_EQ(1, nest->bb()); + + EXPECT_EQ(NULL, message.release_optional_nested_message()); + EXPECT_FALSE(message.has_optional_nested_message()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, SetAllocatedString) { + // Check that set_allocated_foo() works for strings. + UNITTEST::TestAllTypes message; + + EXPECT_FALSE(message.has_optional_string()); + const std::string kHello("hello"); + message.set_optional_string(kHello); + EXPECT_TRUE(message.has_optional_string()); + + message.set_allocated_optional_string(NULL); + EXPECT_FALSE(message.has_optional_string()); + EXPECT_EQ("", message.optional_string()); + + message.set_allocated_optional_string(new std::string(kHello)); + EXPECT_TRUE(message.has_optional_string()); + EXPECT_EQ(kHello, message.optional_string()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, SetAllocatedMessage) { + // Check that set_allocated_foo() can be called in all cases. + UNITTEST::TestAllTypes message; + + EXPECT_FALSE(message.has_optional_nested_message()); + + message.mutable_optional_nested_message()->set_bb(1); + EXPECT_TRUE(message.has_optional_nested_message()); + + message.set_allocated_optional_nested_message(NULL); + EXPECT_FALSE(message.has_optional_nested_message()); + EXPECT_EQ(&UNITTEST::TestAllTypes::NestedMessage::default_instance(), + &message.optional_nested_message()); + + message.mutable_optional_nested_message()->set_bb(1); + UNITTEST::TestAllTypes::NestedMessage* nest = + message.release_optional_nested_message(); + ASSERT_TRUE(nest != NULL); + EXPECT_FALSE(message.has_optional_nested_message()); + + message.set_allocated_optional_nested_message(nest); + EXPECT_TRUE(message.has_optional_nested_message()); + EXPECT_EQ(1, message.optional_nested_message().bb()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, Clear) { + // Set every field to a unique value, clear the message, then check that + // it is cleared. + UNITTEST::TestAllTypes message; + + TestUtil::SetAllFields(&message); + message.Clear(); + TestUtil::ExpectClear(message); + + // Unlike with the defaults test, we do NOT expect that requesting embedded + // messages will return a pointer to the default instance. Instead, they + // should return the objects that were created when mutable_blah() was + // called. + EXPECT_NE(&UNITTEST::TestAllTypes::OptionalGroup::default_instance(), + &message.optionalgroup()); + EXPECT_NE(&UNITTEST::TestAllTypes::NestedMessage::default_instance(), + &message.optional_nested_message()); + EXPECT_NE(&UNITTEST::ForeignMessage::default_instance(), + &message.optional_foreign_message()); + EXPECT_NE(&UNITTEST_IMPORT::ImportMessage::default_instance(), + &message.optional_import_message()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, EmbeddedNullsInBytesCharStar) { + UNITTEST::TestAllTypes message; + + const char* value = "\0lalala\0\0"; + message.set_optional_bytes(value, 9); + ASSERT_EQ(9, message.optional_bytes().size()); + EXPECT_EQ(0, memcmp(value, message.optional_bytes().data(), 9)); + + message.add_repeated_bytes(value, 9); + ASSERT_EQ(9, message.repeated_bytes(0).size()); + EXPECT_EQ(0, memcmp(value, message.repeated_bytes(0).data(), 9)); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, ClearOneField) { + // Set every field to a unique value, then clear one value and insure that + // only that one value is cleared. + UNITTEST::TestAllTypes message; + + TestUtil::SetAllFields(&message); + int64 original_value = message.optional_int64(); + + // Clear the field and make sure it shows up as cleared. + message.clear_optional_int64(); + EXPECT_FALSE(message.has_optional_int64()); + EXPECT_EQ(0, message.optional_int64()); + + // Other adjacent fields should not be cleared. + EXPECT_TRUE(message.has_optional_int32()); + EXPECT_TRUE(message.has_optional_uint32()); + + // Make sure if we set it again, then all fields are set. + message.set_optional_int64(original_value); + TestUtil::ExpectAllFieldsSet(message); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, StringCharStarLength) { + // Verify that we can use a char*,length to set one of the string fields. + UNITTEST::TestAllTypes message; + message.set_optional_string("abcdef", 3); + EXPECT_EQ("abc", message.optional_string()); + + // Verify that we can use a char*,length to add to a repeated string field. + message.add_repeated_string("abcdef", 3); + EXPECT_EQ(1, message.repeated_string_size()); + EXPECT_EQ("abc", message.repeated_string(0)); + + // Verify that we can use a char*,length to set a repeated string field. + message.set_repeated_string(0, "wxyz", 2); + EXPECT_EQ("wx", message.repeated_string(0)); +} + + +TEST(GENERATED_MESSAGE_TEST_NAME, CopyFrom) { + UNITTEST::TestAllTypes message1, message2; + + TestUtil::SetAllFields(&message1); + message2.CopyFrom(message1); + TestUtil::ExpectAllFieldsSet(message2); + + // Copying from self should be a no-op. + message2.CopyFrom(message2); + TestUtil::ExpectAllFieldsSet(message2); +} + + +TEST(GENERATED_MESSAGE_TEST_NAME, SwapWithEmpty) { + UNITTEST::TestAllTypes message1, message2; + TestUtil::SetAllFields(&message1); + + TestUtil::ExpectAllFieldsSet(message1); + TestUtil::ExpectClear(message2); + message1.Swap(&message2); + TestUtil::ExpectAllFieldsSet(message2); + TestUtil::ExpectClear(message1); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, SwapWithSelf) { + UNITTEST::TestAllTypes message; + TestUtil::SetAllFields(&message); + TestUtil::ExpectAllFieldsSet(message); + message.Swap(&message); + TestUtil::ExpectAllFieldsSet(message); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, SwapWithOther) { + UNITTEST::TestAllTypes message1, message2; + + message1.set_optional_int32(123); + message1.set_optional_string("abc"); + message1.mutable_optional_nested_message()->set_bb(1); + message1.set_optional_nested_enum(UNITTEST::TestAllTypes::FOO); + message1.add_repeated_int32(1); + message1.add_repeated_int32(2); + message1.add_repeated_string("a"); + message1.add_repeated_string("b"); + message1.add_repeated_nested_message()->set_bb(7); + message1.add_repeated_nested_message()->set_bb(8); + message1.add_repeated_nested_enum(UNITTEST::TestAllTypes::FOO); + message1.add_repeated_nested_enum(UNITTEST::TestAllTypes::BAR); + + message2.set_optional_int32(456); + message2.set_optional_string("def"); + message2.mutable_optional_nested_message()->set_bb(2); + message2.set_optional_nested_enum(UNITTEST::TestAllTypes::BAR); + message2.add_repeated_int32(3); + message2.add_repeated_string("c"); + message2.add_repeated_nested_message()->set_bb(9); + message2.add_repeated_nested_enum(UNITTEST::TestAllTypes::BAZ); + + message1.Swap(&message2); + + EXPECT_EQ(456, message1.optional_int32()); + EXPECT_EQ("def", message1.optional_string()); + EXPECT_EQ(2, message1.optional_nested_message().bb()); + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message1.optional_nested_enum()); + ASSERT_EQ(1, message1.repeated_int32_size()); + EXPECT_EQ(3, message1.repeated_int32(0)); + ASSERT_EQ(1, message1.repeated_string_size()); + EXPECT_EQ("c", message1.repeated_string(0)); + ASSERT_EQ(1, message1.repeated_nested_message_size()); + EXPECT_EQ(9, message1.repeated_nested_message(0).bb()); + ASSERT_EQ(1, message1.repeated_nested_enum_size()); + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, message1.repeated_nested_enum(0)); + + EXPECT_EQ(123, message2.optional_int32()); + EXPECT_EQ("abc", message2.optional_string()); + EXPECT_EQ(1, message2.optional_nested_message().bb()); + EXPECT_EQ(UNITTEST::TestAllTypes::FOO, message2.optional_nested_enum()); + ASSERT_EQ(2, message2.repeated_int32_size()); + EXPECT_EQ(1, message2.repeated_int32(0)); + EXPECT_EQ(2, message2.repeated_int32(1)); + ASSERT_EQ(2, message2.repeated_string_size()); + EXPECT_EQ("a", message2.repeated_string(0)); + EXPECT_EQ("b", message2.repeated_string(1)); + ASSERT_EQ(2, message2.repeated_nested_message_size()); + EXPECT_EQ(7, message2.repeated_nested_message(0).bb()); + EXPECT_EQ(8, message2.repeated_nested_message(1).bb()); + ASSERT_EQ(2, message2.repeated_nested_enum_size()); + EXPECT_EQ(UNITTEST::TestAllTypes::FOO, message2.repeated_nested_enum(0)); + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message2.repeated_nested_enum(1)); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, ADLSwap) { + UNITTEST::TestAllTypes message1, message2; + TestUtil::SetAllFields(&message1); + + // Note the address of one of the repeated fields, to verify it was swapped + // rather than copied. + const int32* addr = &message1.repeated_int32().Get(0); + + using std::swap; + swap(message1, message2); + + TestUtil::ExpectAllFieldsSet(message2); + TestUtil::ExpectClear(message1); + + EXPECT_EQ(addr, &message2.repeated_int32().Get(0)); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, CopyConstructor) { + // All set. + { + UNITTEST::TestAllTypes message1; + TestUtil::SetAllFields(&message1); + + UNITTEST::TestAllTypes message2(message1); + TestUtil::ExpectAllFieldsSet(message2); + } + + // None set. + { + UNITTEST::TestAllTypes message1; + UNITTEST::TestAllTypes message2(message1); + + EXPECT_FALSE(message1.has_optional_string()); + EXPECT_FALSE(message2.has_optional_string()); + EXPECT_EQ(message1.optional_string(), message2.optional_string()); + + EXPECT_FALSE(message1.has_optional_bytes()); + EXPECT_FALSE(message2.has_optional_bytes()); + EXPECT_EQ(message1.optional_bytes(), message2.optional_bytes()); + + EXPECT_FALSE(message1.has_optional_nested_message()); + EXPECT_FALSE(message2.has_optional_nested_message()); + EXPECT_EQ(&message1.optional_nested_message(), + &message2.optional_nested_message()); + + EXPECT_FALSE(message1.has_optional_foreign_message()); + EXPECT_FALSE(message2.has_optional_foreign_message()); + EXPECT_EQ(&message1.optional_foreign_message(), + &message2.optional_foreign_message()); + + EXPECT_FALSE(message1.has_optional_import_message()); + EXPECT_FALSE(message2.has_optional_import_message()); + EXPECT_EQ(&message1.optional_import_message(), + &message2.optional_import_message()); + + EXPECT_FALSE(message1.has_optional_public_import_message()); + EXPECT_FALSE(message2.has_optional_public_import_message()); + EXPECT_EQ(&message1.optional_public_import_message(), + &message2.optional_public_import_message()); + + EXPECT_FALSE(message1.has_optional_lazy_message()); + EXPECT_FALSE(message2.has_optional_lazy_message()); + EXPECT_EQ(&message1.optional_lazy_message(), + &message2.optional_lazy_message()); + } +} + +TEST(GENERATED_MESSAGE_TEST_NAME, CopyConstructorWithArenas) { + Arena arena; + UNITTEST::TestAllTypes* message1 = + Arena::CreateMessage(&arena); + TestUtil::SetAllFields(message1); + + UNITTEST::TestAllTypes message2_stack(*message1); + TestUtil::ExpectAllFieldsSet(message2_stack); + + std::unique_ptr message2_heap( + new UNITTEST::TestAllTypes(*message1)); + TestUtil::ExpectAllFieldsSet(*message2_heap); + + arena.Reset(); + + // Verify that the copies are still intact. + TestUtil::ExpectAllFieldsSet(message2_stack); + TestUtil::ExpectAllFieldsSet(*message2_heap); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, CopyAssignmentOperator) { + UNITTEST::TestAllTypes message1; + TestUtil::SetAllFields(&message1); + + UNITTEST::TestAllTypes message2; + message2 = message1; + TestUtil::ExpectAllFieldsSet(message2); + + // Make sure that self-assignment does something sane. + message2.operator=(message2); + TestUtil::ExpectAllFieldsSet(message2); +} + +#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || PROTOBUF_RTTI +TEST(GENERATED_MESSAGE_TEST_NAME, UpcastCopyFrom) { + // Test the CopyFrom method that takes in the generic const Message& + // parameter. + UNITTEST::TestAllTypes message1, message2; + + TestUtil::SetAllFields(&message1); + + const Message* source = implicit_cast(&message1); + message2.CopyFrom(*source); + + TestUtil::ExpectAllFieldsSet(message2); +} +#endif + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + +TEST(GENERATED_MESSAGE_TEST_NAME, DynamicMessageCopyFrom) { + // Test copying from a DynamicMessage, which must fall back to using + // reflection. + UNITTEST::TestAllTypes message2; + + // Construct a new version of the dynamic message via the factory. + DynamicMessageFactory factory; + std::unique_ptr message1; + message1.reset(factory.GetPrototype( + UNITTEST::TestAllTypes::descriptor())->New()); + + TestUtil::ReflectionTester reflection_tester( + UNITTEST::TestAllTypes::descriptor()); + reflection_tester.SetAllFieldsViaReflection(message1.get()); + + message2.CopyFrom(*message1); + + TestUtil::ExpectAllFieldsSet(message2); +} + +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS + +TEST(GENERATED_MESSAGE_TEST_NAME, NonEmptyMergeFrom) { + // Test merging with a non-empty message. Code is a modified form + // of that found in net/proto2/internal/reflection_ops_unittest.cc. + UNITTEST::TestAllTypes message1, message2; + + TestUtil::SetAllFields(&message1); + + // This field will test merging into an empty spot. + message2.set_optional_int32(message1.optional_int32()); + message1.clear_optional_int32(); + + // This tests overwriting. + message2.set_optional_string(message1.optional_string()); + message1.set_optional_string("something else"); + + // This tests concatenating. + message2.add_repeated_int32(message1.repeated_int32(1)); + int32 i = message1.repeated_int32(0); + message1.clear_repeated_int32(); + message1.add_repeated_int32(i); + + message1.MergeFrom(message2); + + TestUtil::ExpectAllFieldsSet(message1); +} + + +// Test the generated SerializeWithCachedSizesToArray(), +TEST(GENERATED_MESSAGE_TEST_NAME, SerializationToArray) { + UNITTEST::TestAllTypes message1, message2; + std::string data; + TestUtil::SetAllFields(&message1); + int size = message1.ByteSizeLong(); + data.resize(size); + uint8* start = reinterpret_cast(::google::protobuf::string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + TestUtil::ExpectAllFieldsSet(message2); + +} + +TEST(GENERATED_MESSAGE_TEST_NAME, PackedFieldsSerializationToArray) { + UNITTEST::TestPackedTypes packed_message1, packed_message2; + std::string packed_data; + TestUtil::SetPackedFields(&packed_message1); + int packed_size = packed_message1.ByteSizeLong(); + packed_data.resize(packed_size); + uint8* start = reinterpret_cast(::google::protobuf::string_as_array(&packed_data)); + uint8* end = packed_message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(packed_size, end - start); + EXPECT_TRUE(packed_message2.ParseFromString(packed_data)); + TestUtil::ExpectPackedFieldsSet(packed_message2); +} + +// Test the generated SerializeWithCachedSizes() by forcing the buffer to write +// one byte at a time. +TEST(GENERATED_MESSAGE_TEST_NAME, SerializationToStream) { + UNITTEST::TestAllTypes message1, message2; + TestUtil::SetAllFields(&message1); + int size = message1.ByteSizeLong(); + std::string data; + data.resize(size); + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + EXPECT_TRUE(message2.ParseFromString(data)); + TestUtil::ExpectAllFieldsSet(message2); + +} + +TEST(GENERATED_MESSAGE_TEST_NAME, PackedFieldsSerializationToStream) { + UNITTEST::TestPackedTypes message1, message2; + TestUtil::SetPackedFields(&message1); + int size = message1.ByteSizeLong(); + std::string data; + data.resize(size); + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + EXPECT_TRUE(message2.ParseFromString(data)); + TestUtil::ExpectPackedFieldsSet(message2); +} + + +TEST(GENERATED_MESSAGE_TEST_NAME, Required) { + // Test that IsInitialized() returns false if required fields are missing. + UNITTEST::TestRequired message; + + EXPECT_FALSE(message.IsInitialized()); + message.set_a(1); + EXPECT_FALSE(message.IsInitialized()); + message.set_b(2); + EXPECT_FALSE(message.IsInitialized()); + message.set_c(3); + EXPECT_TRUE(message.IsInitialized()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, RequiredForeign) { + // Test that IsInitialized() returns false if required fields in nested + // messages are missing. + UNITTEST::TestRequiredForeign message; + + EXPECT_TRUE(message.IsInitialized()); + + message.mutable_optional_message(); + EXPECT_FALSE(message.IsInitialized()); + + message.mutable_optional_message()->set_a(1); + message.mutable_optional_message()->set_b(2); + message.mutable_optional_message()->set_c(3); + EXPECT_TRUE(message.IsInitialized()); + + message.add_repeated_message(); + EXPECT_FALSE(message.IsInitialized()); + + message.mutable_repeated_message(0)->set_a(1); + message.mutable_repeated_message(0)->set_b(2); + message.mutable_repeated_message(0)->set_c(3); + EXPECT_TRUE(message.IsInitialized()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, ForeignNested) { + // Test that TestAllTypes::NestedMessage can be embedded directly into + // another message. + UNITTEST::TestForeignNested message; + + // If this compiles and runs without crashing, it must work. We have + // nothing more to test. + UNITTEST::TestAllTypes::NestedMessage* nested = + message.mutable_foreign_nested(); + nested->set_bb(1); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, ReallyLargeTagNumber) { + // Test that really large tag numbers don't break anything. + UNITTEST::TestReallyLargeTagNumber message1, message2; + std::string data; + + // For the most part, if this compiles and runs then we're probably good. + // (The most likely cause for failure would be if something were attempting + // to allocate a lookup table of some sort using tag numbers as the index.) + // We'll try serializing just for fun. + message1.set_a(1234); + message1.set_bb(5678); + message1.SerializeToString(&data); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(1234, message2.a()); + EXPECT_EQ(5678, message2.bb()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, MutualRecursion) { + // Test that mutually-recursive message types work. + UNITTEST::TestMutualRecursionA message; + UNITTEST::TestMutualRecursionA* nested = message.mutable_bb()->mutable_a(); + UNITTEST::TestMutualRecursionA* nested2 = nested->mutable_bb()->mutable_a(); + + // Again, if the above compiles and runs, that's all we really have to + // test, but just for run we'll check that the system didn't somehow come + // up with a pointer loop... + EXPECT_NE(&message, nested); + EXPECT_NE(&message, nested2); + EXPECT_NE(nested, nested2); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, CamelCaseFieldNames) { + // This test is mainly checking that the following compiles, which verifies + // that the field names were coerced to lower-case. + // + // Protocol buffers standard style is to use lowercase-with-underscores for + // field names. Some old proto1 .protos unfortunately used camel-case field + // names. In proto1, these names were forced to lower-case. So, we do the + // same thing in proto2. + + UNITTEST::TestCamelCaseFieldNames message; + + message.set_primitivefield(2); + message.set_stringfield("foo"); + message.set_enumfield(UNITTEST::FOREIGN_FOO); + message.mutable_messagefield()->set_c(6); + + message.add_repeatedprimitivefield(8); + message.add_repeatedstringfield("qux"); + message.add_repeatedenumfield(UNITTEST::FOREIGN_BAR); + message.add_repeatedmessagefield()->set_c(15); + + EXPECT_EQ(2, message.primitivefield()); + EXPECT_EQ("foo", message.stringfield()); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, message.enumfield()); + EXPECT_EQ(6, message.messagefield().c()); + + EXPECT_EQ(8, message.repeatedprimitivefield(0)); + EXPECT_EQ("qux", message.repeatedstringfield(0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.repeatedenumfield(0)); + EXPECT_EQ(15, message.repeatedmessagefield(0).c()); +} + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + +TEST(GENERATED_MESSAGE_TEST_NAME, TestOptimizedForSize) { + // We rely on the tests in reflection_ops_unittest and wire_format_unittest + // to really test that reflection-based methods work. Here we are mostly + // just making sure that TestOptimizedForSize actually builds and seems to + // function. + + UNITTEST::TestOptimizedForSize message, message2; + message.set_i(1); + message.mutable_msg()->set_c(2); + message2.CopyFrom(message); + EXPECT_EQ(1, message2.i()); + EXPECT_EQ(2, message2.msg().c()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, TestEmbedOptimizedForSize) { + // Verifies that something optimized for speed can contain something optimized + // for size. + + UNITTEST::TestEmbedOptimizedForSize message, message2; + message.mutable_optional_message()->set_i(1); + message.add_repeated_message()->mutable_msg()->set_c(2); + std::string data; + message.SerializeToString(&data); + ASSERT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(1, message2.optional_message().i()); + EXPECT_EQ(2, message2.repeated_message(0).msg().c()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, TestSpaceUsed) { + UNITTEST::TestAllTypes message1; + // sizeof provides a lower bound on SpaceUsedLong(). + EXPECT_LE(sizeof(UNITTEST::TestAllTypes), message1.SpaceUsedLong()); + const size_t empty_message_size = message1.SpaceUsedLong(); + + // Setting primitive types shouldn't affect the space used. + message1.set_optional_int32(123); + message1.set_optional_int64(12345); + message1.set_optional_uint32(123); + message1.set_optional_uint64(12345); + EXPECT_EQ(empty_message_size, message1.SpaceUsedLong()); + + // On some STL implementations, setting the string to a small value should + // only increase SpaceUsedLong() by the size of a string object, though this + // is not true everywhere. + message1.set_optional_string("abc"); + EXPECT_LE(empty_message_size + message1.optional_string().size(), + message1.SpaceUsedLong()); + + // Setting a string to a value larger than the string object itself should + // increase SpaceUsedLong(), because it cannot store the value internally. + message1.set_optional_string(std::string(sizeof(std::string) + 1, 'x')); + int min_expected_increase = message1.optional_string().capacity(); + EXPECT_LE(empty_message_size + min_expected_increase, + message1.SpaceUsedLong()); + + size_t previous_size = message1.SpaceUsedLong(); + // Adding an optional message should increase the size by the size of the + // nested message type. NestedMessage is simple enough (1 int field) that it + // is equal to sizeof(NestedMessage) + message1.mutable_optional_nested_message(); + ASSERT_EQ(sizeof(UNITTEST::TestAllTypes::NestedMessage), + message1.optional_nested_message().SpaceUsedLong()); + EXPECT_EQ(previous_size + + sizeof(UNITTEST::TestAllTypes::NestedMessage), + message1.SpaceUsedLong()); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, TestOneofSpaceUsed) { + UNITTEST::TestOneof2 message1; + EXPECT_LE(sizeof(UNITTEST::TestOneof2), message1.SpaceUsedLong()); + + const size_t empty_message_size = message1.SpaceUsedLong(); + // Setting primitive types shouldn't affect the space used. + message1.set_foo_int(123); + message1.set_bar_int(12345); + EXPECT_EQ(empty_message_size, message1.SpaceUsedLong()); + + // Setting a string in oneof to a small value should only increase + // SpaceUsedLong() by the size of a string object. + message1.set_foo_string("abc"); + EXPECT_LE(empty_message_size + sizeof(std::string), message1.SpaceUsedLong()); + + // Setting a string in oneof to a value larger than the string object itself + // should increase SpaceUsedLong(), because it cannot store the value + // internally. + message1.set_foo_string(std::string(sizeof(std::string) + 1, 'x')); + int min_expected_increase = + message1.foo_string().capacity() + sizeof(std::string); + EXPECT_LE(empty_message_size + min_expected_increase, + message1.SpaceUsedLong()); + + // Setting a message in oneof should delete the other fields and increase the + // size by the size of the nested message type. NestedMessage is simple enough + // that it is equal to sizeof(NestedMessage) + message1.mutable_foo_message(); + ASSERT_EQ(sizeof(UNITTEST::TestOneof2::NestedMessage), + message1.foo_message().SpaceUsedLong()); + EXPECT_EQ(empty_message_size + + sizeof(UNITTEST::TestOneof2::NestedMessage), + message1.SpaceUsedLong()); +} + +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS + + +TEST(GENERATED_MESSAGE_TEST_NAME, FieldConstantValues) { + UNITTEST::TestRequired message; + EXPECT_EQ(UNITTEST::TestAllTypes_NestedMessage::kBbFieldNumber, 1); + EXPECT_EQ(UNITTEST::TestAllTypes::kOptionalInt32FieldNumber, 1); + EXPECT_EQ(UNITTEST::TestAllTypes::kOptionalgroupFieldNumber, 16); + EXPECT_EQ(UNITTEST::TestAllTypes::kOptionalNestedMessageFieldNumber, 18); + EXPECT_EQ(UNITTEST::TestAllTypes::kOptionalNestedEnumFieldNumber, 21); + EXPECT_EQ(UNITTEST::TestAllTypes::kRepeatedInt32FieldNumber, 31); + EXPECT_EQ(UNITTEST::TestAllTypes::kRepeatedgroupFieldNumber, 46); + EXPECT_EQ(UNITTEST::TestAllTypes::kRepeatedNestedMessageFieldNumber, 48); + EXPECT_EQ(UNITTEST::TestAllTypes::kRepeatedNestedEnumFieldNumber, 51); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, ExtensionConstantValues) { + EXPECT_EQ(UNITTEST::TestRequired::kSingleFieldNumber, 1000); + EXPECT_EQ(UNITTEST::TestRequired::kMultiFieldNumber, 1001); + EXPECT_EQ(UNITTEST::kOptionalInt32ExtensionFieldNumber, 1); + EXPECT_EQ(UNITTEST::kOptionalgroupExtensionFieldNumber, 16); + EXPECT_EQ(UNITTEST::kOptionalNestedMessageExtensionFieldNumber, 18); + EXPECT_EQ(UNITTEST::kOptionalNestedEnumExtensionFieldNumber, 21); + EXPECT_EQ(UNITTEST::kRepeatedInt32ExtensionFieldNumber, 31); + EXPECT_EQ(UNITTEST::kRepeatedgroupExtensionFieldNumber, 46); + EXPECT_EQ(UNITTEST::kRepeatedNestedMessageExtensionFieldNumber, 48); + EXPECT_EQ(UNITTEST::kRepeatedNestedEnumExtensionFieldNumber, 51); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, ParseFromTruncated) { + const std::string long_string = std::string(128, 'q'); + FileDescriptorProto p; + p.add_extension()->set_name(long_string); + const std::string msg = p.SerializeAsString(); + int successful_count = 0; + for (int i = 0; i <= msg.size(); i++) { + if (p.ParseFromArray(msg.c_str(), i)) { + ++successful_count; + } + } + // We don't really care about how often we succeeded. + // As long as we didn't crash, we're happy. + EXPECT_GE(successful_count, 1); +} + +// =================================================================== + +TEST(GENERATED_ENUM_TEST_NAME, EnumValuesAsSwitchCases) { + // Test that our nested enum values can be used as switch cases. This test + // doesn't actually do anything, the proof that it works is that it + // compiles. + int i =0; + UNITTEST::TestAllTypes::NestedEnum a = UNITTEST::TestAllTypes::BAR; + switch (a) { + case UNITTEST::TestAllTypes::FOO: + i = 1; + break; + case UNITTEST::TestAllTypes::BAR: + i = 2; + break; + case UNITTEST::TestAllTypes::BAZ: + i = 3; + break; + case UNITTEST::TestAllTypes::NEG: + i = -1; + break; + // no default case: We want to make sure the compiler recognizes that + // all cases are covered. (GCC warns if you do not cover all cases of + // an enum in a switch.) + } + + // Token check just for fun. + EXPECT_EQ(2, i); +} + +TEST(GENERATED_ENUM_TEST_NAME, IsValidValue) { + // Test enum IsValidValue. + EXPECT_TRUE(UNITTEST::TestAllTypes::NestedEnum_IsValid(1)); + EXPECT_TRUE(UNITTEST::TestAllTypes::NestedEnum_IsValid(2)); + EXPECT_TRUE(UNITTEST::TestAllTypes::NestedEnum_IsValid(3)); + + EXPECT_FALSE(UNITTEST::TestAllTypes::NestedEnum_IsValid(0)); + EXPECT_FALSE(UNITTEST::TestAllTypes::NestedEnum_IsValid(4)); + + // Make sure it also works when there are dups. + EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_IsValid(1)); + EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_IsValid(2)); + EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_IsValid(3)); + + EXPECT_FALSE(UNITTEST::TestEnumWithDupValue_IsValid(0)); + EXPECT_FALSE(UNITTEST::TestEnumWithDupValue_IsValid(4)); +} + +TEST(GENERATED_ENUM_TEST_NAME, MinAndMax) { + EXPECT_EQ(UNITTEST::TestAllTypes::NEG, + UNITTEST::TestAllTypes::NestedEnum_MIN); + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, + UNITTEST::TestAllTypes::NestedEnum_MAX); + EXPECT_EQ(4, UNITTEST::TestAllTypes::NestedEnum_ARRAYSIZE); + + EXPECT_EQ(UNITTEST::FOREIGN_FOO, UNITTEST::ForeignEnum_MIN); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, UNITTEST::ForeignEnum_MAX); + EXPECT_EQ(7, UNITTEST::ForeignEnum_ARRAYSIZE); + + EXPECT_EQ(1, UNITTEST::TestEnumWithDupValue_MIN); + EXPECT_EQ(3, UNITTEST::TestEnumWithDupValue_MAX); + EXPECT_EQ(4, UNITTEST::TestEnumWithDupValue_ARRAYSIZE); + + EXPECT_EQ(UNITTEST::SPARSE_E, UNITTEST::TestSparseEnum_MIN); + EXPECT_EQ(UNITTEST::SPARSE_C, UNITTEST::TestSparseEnum_MAX); + EXPECT_EQ(12589235, UNITTEST::TestSparseEnum_ARRAYSIZE); + + // Make sure we can take the address of _MIN, _MAX and _ARRAYSIZE. + void* null_pointer = 0; // NULL may be integer-type, not pointer-type. + EXPECT_NE(null_pointer, &UNITTEST::TestAllTypes::NestedEnum_MIN); + EXPECT_NE(null_pointer, &UNITTEST::TestAllTypes::NestedEnum_MAX); + EXPECT_NE(null_pointer, &UNITTEST::TestAllTypes::NestedEnum_ARRAYSIZE); + + EXPECT_NE(null_pointer, &UNITTEST::ForeignEnum_MIN); + EXPECT_NE(null_pointer, &UNITTEST::ForeignEnum_MAX); + EXPECT_NE(null_pointer, &UNITTEST::ForeignEnum_ARRAYSIZE); + + // Make sure we can use _MIN and _MAX as switch cases. + switch (UNITTEST::SPARSE_A) { + case UNITTEST::TestSparseEnum_MIN: + case UNITTEST::TestSparseEnum_MAX: + break; + default: + break; + } +} + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + +TEST(GENERATED_ENUM_TEST_NAME, Name) { + // "Names" in the presence of dup values map to the first alias. + EXPECT_EQ("FOO1", UNITTEST::TestEnumWithDupValue_Name(UNITTEST::FOO1)); + EXPECT_EQ("FOO1", UNITTEST::TestEnumWithDupValue_Name(UNITTEST::FOO2)); + + EXPECT_EQ("SPARSE_A", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_A)); + EXPECT_EQ("SPARSE_B", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_B)); + EXPECT_EQ("SPARSE_C", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_C)); + EXPECT_EQ("SPARSE_D", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_D)); + EXPECT_EQ("SPARSE_E", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_E)); + EXPECT_EQ("SPARSE_F", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_F)); + EXPECT_EQ("SPARSE_G", UNITTEST::TestSparseEnum_Name(UNITTEST::SPARSE_G)); +} + +TEST(GENERATED_ENUM_TEST_NAME, Parse) { + UNITTEST::TestEnumWithDupValue dup_value = UNITTEST::FOO1; + EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_Parse("FOO1", &dup_value)); + EXPECT_EQ(UNITTEST::FOO1, dup_value); + EXPECT_TRUE(UNITTEST::TestEnumWithDupValue_Parse("FOO2", &dup_value)); + EXPECT_EQ(UNITTEST::FOO2, dup_value); + EXPECT_FALSE(UNITTEST::TestEnumWithDupValue_Parse("FOO", &dup_value)); +} + +TEST(GENERATED_ENUM_TEST_NAME, GetEnumDescriptor) { + EXPECT_EQ(UNITTEST::TestAllTypes::NestedEnum_descriptor(), + GetEnumDescriptor()); + EXPECT_EQ(UNITTEST::ForeignEnum_descriptor(), + GetEnumDescriptor()); + EXPECT_EQ(UNITTEST::TestEnumWithDupValue_descriptor(), + GetEnumDescriptor()); + EXPECT_EQ(UNITTEST::TestSparseEnum_descriptor(), + GetEnumDescriptor()); +} + +enum NonProtoEnum { + kFoo = 1, +}; + +TEST(GENERATED_ENUM_TEST_NAME, IsProtoEnumTypeTrait) { + EXPECT_TRUE(is_proto_enum::value); + EXPECT_TRUE(is_proto_enum::value); + EXPECT_TRUE(is_proto_enum::value); + EXPECT_TRUE(is_proto_enum::value); + + EXPECT_FALSE(is_proto_enum::value); + EXPECT_FALSE(is_proto_enum::value); +} + +#endif // PROTOBUF_TEST_NO_DESCRIPTORS + +// =================================================================== + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + +// Support code for testing services. +class GENERATED_SERVICE_TEST_NAME : public testing::Test { + protected: + class MockTestService : public UNITTEST::TestService { + public: + MockTestService() + : called_(false), + method_(""), + controller_(NULL), + request_(NULL), + response_(NULL), + done_(NULL) {} + + ~MockTestService() {} + + void Reset() { called_ = false; } + + // implements TestService ---------------------------------------- + + void Foo(RpcController* controller, + const UNITTEST::FooRequest* request, + UNITTEST::FooResponse* response, + Closure* done) { + ASSERT_FALSE(called_); + called_ = true; + method_ = "Foo"; + controller_ = controller; + request_ = request; + response_ = response; + done_ = done; + } + + void Bar(RpcController* controller, + const UNITTEST::BarRequest* request, + UNITTEST::BarResponse* response, + Closure* done) { + ASSERT_FALSE(called_); + called_ = true; + method_ = "Bar"; + controller_ = controller; + request_ = request; + response_ = response; + done_ = done; + } + + // --------------------------------------------------------------- + + bool called_; + std::string method_; + RpcController* controller_; + const Message* request_; + Message* response_; + Closure* done_; + }; + + class MockRpcChannel : public RpcChannel { + public: + MockRpcChannel() + : called_(false), + method_(NULL), + controller_(NULL), + request_(NULL), + response_(NULL), + done_(NULL), + destroyed_(NULL) {} + + ~MockRpcChannel() { + if (destroyed_ != NULL) *destroyed_ = true; + } + + void Reset() { called_ = false; } + + // implements TestService ---------------------------------------- + + void CallMethod(const MethodDescriptor* method, + RpcController* controller, + const Message* request, + Message* response, + Closure* done) { + ASSERT_FALSE(called_); + called_ = true; + method_ = method; + controller_ = controller; + request_ = request; + response_ = response; + done_ = done; + } + + // --------------------------------------------------------------- + + bool called_; + const MethodDescriptor* method_; + RpcController* controller_; + const Message* request_; + Message* response_; + Closure* done_; + bool* destroyed_; + }; + + class MockController : public RpcController { + public: + void Reset() { + ADD_FAILURE() << "Reset() not expected during this test."; + } + bool Failed() const { + ADD_FAILURE() << "Failed() not expected during this test."; + return false; + } + std::string ErrorText() const { + ADD_FAILURE() << "ErrorText() not expected during this test."; + return ""; + } + void StartCancel() { + ADD_FAILURE() << "StartCancel() not expected during this test."; + } + void SetFailed(const std::string& reason) { + ADD_FAILURE() << "SetFailed() not expected during this test."; + } + bool IsCanceled() const { + ADD_FAILURE() << "IsCanceled() not expected during this test."; + return false; + } + void NotifyOnCancel(Closure* callback) { + ADD_FAILURE() << "NotifyOnCancel() not expected during this test."; + } + }; + + GENERATED_SERVICE_TEST_NAME() + : descriptor_(UNITTEST::TestService::descriptor()), + foo_(descriptor_->FindMethodByName("Foo")), + bar_(descriptor_->FindMethodByName("Bar")), + stub_(&mock_channel_), + done_(::google::protobuf::NewPermanentCallback(&DoNothing)) {} + + virtual void SetUp() { + ASSERT_TRUE(foo_ != NULL); + ASSERT_TRUE(bar_ != NULL); + } + + const ServiceDescriptor* descriptor_; + const MethodDescriptor* foo_; + const MethodDescriptor* bar_; + + MockTestService mock_service_; + MockController mock_controller_; + + MockRpcChannel mock_channel_; + UNITTEST::TestService::Stub stub_; + + // Just so we don't have to re-define these with every test. + UNITTEST::FooRequest foo_request_; + UNITTEST::FooResponse foo_response_; + UNITTEST::BarRequest bar_request_; + UNITTEST::BarResponse bar_response_; + std::unique_ptr done_; +}; + +TEST_F(GENERATED_SERVICE_TEST_NAME, GetDescriptor) { + // Test that GetDescriptor() works. + + EXPECT_EQ(descriptor_, mock_service_.GetDescriptor()); +} + +TEST_F(GENERATED_SERVICE_TEST_NAME, GetChannel) { + EXPECT_EQ(&mock_channel_, stub_.channel()); +} + +TEST_F(GENERATED_SERVICE_TEST_NAME, OwnsChannel) { + MockRpcChannel* channel = new MockRpcChannel; + bool destroyed = false; + channel->destroyed_ = &destroyed; + + { + UNITTEST::TestService::Stub owning_stub(channel, + Service::STUB_OWNS_CHANNEL); + EXPECT_FALSE(destroyed); + } + + EXPECT_TRUE(destroyed); +} + +TEST_F(GENERATED_SERVICE_TEST_NAME, CallMethod) { + // Test that CallMethod() works. + + // Call Foo() via CallMethod(). + mock_service_.CallMethod(foo_, &mock_controller_, + &foo_request_, &foo_response_, done_.get()); + + ASSERT_TRUE(mock_service_.called_); + + EXPECT_EQ("Foo" , mock_service_.method_ ); + EXPECT_EQ(&mock_controller_, mock_service_.controller_); + EXPECT_EQ(&foo_request_ , mock_service_.request_ ); + EXPECT_EQ(&foo_response_ , mock_service_.response_ ); + EXPECT_EQ(done_.get() , mock_service_.done_ ); + + // Try again, but call Bar() instead. + mock_service_.Reset(); + mock_service_.CallMethod(bar_, &mock_controller_, + &bar_request_, &bar_response_, done_.get()); + + ASSERT_TRUE(mock_service_.called_); + EXPECT_EQ("Bar", mock_service_.method_); +} + +TEST_F(GENERATED_SERVICE_TEST_NAME, CallMethodTypeFailure) { + // Verify death if we call Foo() with Bar's message types. + +#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet + EXPECT_DEBUG_DEATH( + mock_service_.CallMethod(foo_, &mock_controller_, + &foo_request_, &bar_response_, done_.get()), + "dynamic_cast"); + + mock_service_.Reset(); + EXPECT_DEBUG_DEATH( + mock_service_.CallMethod(foo_, &mock_controller_, + &bar_request_, &foo_response_, done_.get()), + "dynamic_cast"); +#endif // PROTOBUF_HAS_DEATH_TEST +} + +TEST_F(GENERATED_SERVICE_TEST_NAME, GetPrototypes) { + // Test Get{Request,Response}Prototype() methods. + + EXPECT_EQ(&UNITTEST::FooRequest::default_instance(), + &mock_service_.GetRequestPrototype(foo_)); + EXPECT_EQ(&UNITTEST::BarRequest::default_instance(), + &mock_service_.GetRequestPrototype(bar_)); + + EXPECT_EQ(&UNITTEST::FooResponse::default_instance(), + &mock_service_.GetResponsePrototype(foo_)); + EXPECT_EQ(&UNITTEST::BarResponse::default_instance(), + &mock_service_.GetResponsePrototype(bar_)); +} + +TEST_F(GENERATED_SERVICE_TEST_NAME, Stub) { + // Test that the stub class works. + + // Call Foo() via the stub. + stub_.Foo(&mock_controller_, &foo_request_, &foo_response_, done_.get()); + + ASSERT_TRUE(mock_channel_.called_); + + EXPECT_EQ(foo_ , mock_channel_.method_ ); + EXPECT_EQ(&mock_controller_, mock_channel_.controller_); + EXPECT_EQ(&foo_request_ , mock_channel_.request_ ); + EXPECT_EQ(&foo_response_ , mock_channel_.response_ ); + EXPECT_EQ(done_.get() , mock_channel_.done_ ); + + // Call Bar() via the stub. + mock_channel_.Reset(); + stub_.Bar(&mock_controller_, &bar_request_, &bar_response_, done_.get()); + + ASSERT_TRUE(mock_channel_.called_); + EXPECT_EQ(bar_, mock_channel_.method_); +} + +TEST_F(GENERATED_SERVICE_TEST_NAME, NotImplemented) { + // Test that failing to implement a method of a service causes it to fail + // with a "not implemented" error message. + + // A service which doesn't implement any methods. + class UnimplementedService : public UNITTEST::TestService { + public: + UnimplementedService() {} + }; + + UnimplementedService unimplemented_service; + + // And a controller which expects to get a "not implemented" error. + class ExpectUnimplementedController : public MockController { + public: + ExpectUnimplementedController() : called_(false) {} + + void SetFailed(const std::string& reason) { + EXPECT_FALSE(called_); + called_ = true; + EXPECT_EQ("Method Foo() not implemented.", reason); + } + + bool called_; + }; + + ExpectUnimplementedController controller; + + // Call Foo. + unimplemented_service.Foo(&controller, &foo_request_, &foo_response_, + done_.get()); + + EXPECT_TRUE(controller.called_); +} + +// =================================================================== + +class OneofTest : public testing::Test { + protected: + virtual void SetUp() { + } + + void ExpectEnumCasesWork(const UNITTEST::TestOneof2 &message) { + switch (message.foo_case()) { + case UNITTEST::TestOneof2::kFooInt: + EXPECT_TRUE(message.has_foo_int()); + break; + case UNITTEST::TestOneof2::kFooString: + EXPECT_TRUE(message.has_foo_string()); + break; + case UNITTEST::TestOneof2::kFooCord: + EXPECT_TRUE(message.has_foo_cord()); + break; + case UNITTEST::TestOneof2::kFooStringPiece: + EXPECT_TRUE(message.has_foo_string_piece()); + break; + case UNITTEST::TestOneof2::kFooBytes: + EXPECT_TRUE(message.has_foo_bytes()); + break; + case UNITTEST::TestOneof2::kFooEnum: + EXPECT_TRUE(message.has_foo_enum()); + break; + case UNITTEST::TestOneof2::kFooMessage: + EXPECT_TRUE(message.has_foo_message()); + break; + case UNITTEST::TestOneof2::kFoogroup: + EXPECT_TRUE(message.has_foogroup()); + break; + case UNITTEST::TestOneof2::kFooLazyMessage: + EXPECT_TRUE(message.has_foo_lazy_message()); + break; + case UNITTEST::TestOneof2::FOO_NOT_SET: + break; + } + } +}; + +TEST_F(OneofTest, SettingOneFieldClearsOthers) { + UNITTEST::TestOneof2 message; + + message.set_foo_int(123); + EXPECT_TRUE(message.has_foo_int()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + message.set_foo_string("foo"); + EXPECT_TRUE(message.has_foo_string()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + + message.set_foo_bytes("qux"); + EXPECT_TRUE(message.has_foo_bytes()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + message.set_foo_enum(UNITTEST::TestOneof2::FOO); + EXPECT_TRUE(message.has_foo_enum()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + message.mutable_foo_message()->set_qux_int(234); + EXPECT_TRUE(message.has_foo_message()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + message.mutable_foogroup()->set_a(345); + EXPECT_TRUE(message.has_foogroup()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + + // we repeat this because we didn't test if this properly clears other fields + // at the beginning. + message.set_foo_int(123); + EXPECT_TRUE(message.has_foo_int()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); +} + +TEST_F(OneofTest, EnumCases) { + UNITTEST::TestOneof2 message; + + message.set_foo_int(123); + ExpectEnumCasesWork(message); + message.set_foo_string("foo"); + ExpectEnumCasesWork(message); + message.set_foo_bytes("qux"); + ExpectEnumCasesWork(message); + message.set_foo_enum(UNITTEST::TestOneof2::FOO); + ExpectEnumCasesWork(message); + message.mutable_foo_message()->set_qux_int(234); + ExpectEnumCasesWork(message); + message.mutable_foogroup()->set_a(345); + ExpectEnumCasesWork(message); +} + +TEST_F(OneofTest, PrimitiveType) { + UNITTEST::TestOneof2 message; + // Unset field returns default value + EXPECT_EQ(message.foo_int(), 0); + + message.set_foo_int(123); + EXPECT_TRUE(message.has_foo_int()); + EXPECT_EQ(message.foo_int(), 123); + message.clear_foo_int(); + EXPECT_FALSE(message.has_foo_int()); +} + +TEST_F(OneofTest, EnumType) { + UNITTEST::TestOneof2 message; + // Unset field returns default value + EXPECT_EQ(message.foo_enum(), 1); + + message.set_foo_enum(UNITTEST::TestOneof2::FOO); + EXPECT_TRUE(message.has_foo_enum()); + EXPECT_EQ(message.foo_enum(), UNITTEST::TestOneof2::FOO); + message.clear_foo_enum(); + EXPECT_FALSE(message.has_foo_enum()); +} + +TEST_F(OneofTest, SetString) { + // Check that setting a string field in various ways works + UNITTEST::TestOneof2 message; + + // Unset field returns default value + EXPECT_EQ(message.foo_string(), ""); + + message.set_foo_string("foo"); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "foo"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); + + message.set_foo_string(std::string("bar")); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "bar"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); + + + message.set_foo_string("qux", 3); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "qux"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); + + message.mutable_foo_string()->assign("quux"); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "quux"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); + + message.set_foo_string("corge"); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "corge"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); +} + +TEST_F(OneofTest, ReleaseString) { + // Check that release_foo() starts out NULL, and gives us a value + // that we can delete after it's been set. + UNITTEST::TestOneof2 message; + + EXPECT_EQ(NULL, message.release_foo_string()); + EXPECT_FALSE(message.has_foo_string()); + + message.set_foo_string("blah"); + EXPECT_TRUE(message.has_foo_string()); + std::unique_ptr str(message.release_foo_string()); + EXPECT_FALSE(message.has_foo_string()); + ASSERT_TRUE(str != NULL); + EXPECT_EQ("blah", *str); + + EXPECT_EQ(NULL, message.release_foo_string()); + EXPECT_FALSE(message.has_foo_string()); +} + +TEST_F(OneofTest, SetAllocatedString) { + // Check that set_allocated_foo() works for strings. + UNITTEST::TestOneof2 message; + + EXPECT_FALSE(message.has_foo_string()); + const std::string kHello("hello"); + message.set_foo_string(kHello); + EXPECT_TRUE(message.has_foo_string()); + + message.set_allocated_foo_string(NULL); + EXPECT_FALSE(message.has_foo_string()); + EXPECT_EQ("", message.foo_string()); + + message.set_allocated_foo_string(new std::string(kHello)); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(kHello, message.foo_string()); +} + +TEST_F(OneofTest, ArenaSetAllocatedString) { + // Check that set_allocated_foo() works for strings. + Arena arena; + UNITTEST::TestOneof2* message = + Arena::CreateMessage(&arena); + + EXPECT_FALSE(message->has_foo_string()); + const std::string kHello("hello"); + message->set_foo_string(kHello); + EXPECT_TRUE(message->has_foo_string()); + + message->set_allocated_foo_string(NULL); + EXPECT_FALSE(message->has_foo_string()); + EXPECT_EQ("", message->foo_string()); + + message->set_allocated_foo_string(new std::string(kHello)); + EXPECT_TRUE(message->has_foo_string()); + EXPECT_EQ(kHello, message->foo_string()); +} + + +TEST_F(OneofTest, SetMessage) { + // Check that setting a message field works + UNITTEST::TestOneof2 message; + + // Unset field returns default instance + EXPECT_EQ(&message.foo_message(), + &UNITTEST::TestOneof2_NestedMessage::default_instance()); + EXPECT_EQ(message.foo_message().qux_int(), 0); + + message.mutable_foo_message()->set_qux_int(234); + EXPECT_TRUE(message.has_foo_message()); + EXPECT_EQ(message.foo_message().qux_int(), 234); + message.clear_foo_message(); + EXPECT_FALSE(message.has_foo_message()); +} + +TEST_F(OneofTest, ReleaseMessage) { + // Check that release_foo() starts out NULL, and gives us a value + // that we can delete after it's been set. + UNITTEST::TestOneof2 message; + + EXPECT_EQ(NULL, message.release_foo_message()); + EXPECT_FALSE(message.has_foo_message()); + + message.mutable_foo_message()->set_qux_int(1); + EXPECT_TRUE(message.has_foo_message()); + std::unique_ptr mes( + message.release_foo_message()); + EXPECT_FALSE(message.has_foo_message()); + ASSERT_TRUE(mes != NULL); + EXPECT_EQ(1, mes->qux_int()); + + EXPECT_EQ(NULL, message.release_foo_message()); + EXPECT_FALSE(message.has_foo_message()); +} + +TEST_F(OneofTest, SetAllocatedMessage) { + // Check that set_allocated_foo() works for messages. + UNITTEST::TestOneof2 message; + + EXPECT_FALSE(message.has_foo_message()); + + message.mutable_foo_message()->set_qux_int(1); + EXPECT_TRUE(message.has_foo_message()); + + message.set_allocated_foo_message(NULL); + EXPECT_FALSE(message.has_foo_message()); + EXPECT_EQ(&message.foo_message(), + &UNITTEST::TestOneof2_NestedMessage::default_instance()); + + message.mutable_foo_message()->set_qux_int(1); + UNITTEST::TestOneof2_NestedMessage* mes = message.release_foo_message(); + ASSERT_TRUE(mes != NULL); + EXPECT_FALSE(message.has_foo_message()); + + message.set_allocated_foo_message(mes); + EXPECT_TRUE(message.has_foo_message()); + EXPECT_EQ(1, message.foo_message().qux_int()); +} + + +TEST_F(OneofTest, Clear) { + UNITTEST::TestOneof2 message; + + message.set_foo_int(1); + EXPECT_TRUE(message.has_foo_int()); + message.clear_foo_int(); + EXPECT_FALSE(message.has_foo_int()); +} + +TEST_F(OneofTest, Defaults) { + UNITTEST::TestOneof2 message; + + EXPECT_FALSE(message.has_foo_int()); + EXPECT_EQ(message.foo_int(), 0); + + EXPECT_FALSE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), ""); + + + EXPECT_FALSE(message.has_foo_bytes()); + EXPECT_EQ(message.foo_bytes(), ""); + + EXPECT_FALSE(message.has_foo_enum()); + EXPECT_EQ(message.foo_enum(), 1); + + EXPECT_FALSE(message.has_foo_message()); + EXPECT_EQ(message.foo_message().qux_int(), 0); + + EXPECT_FALSE(message.has_foogroup()); + EXPECT_EQ(message.foogroup().a(), 0); + + + EXPECT_FALSE(message.has_bar_int()); + EXPECT_EQ(message.bar_int(), 5); + + EXPECT_FALSE(message.has_bar_string()); + EXPECT_EQ(message.bar_string(), "STRING"); + + + EXPECT_FALSE(message.has_bar_bytes()); + EXPECT_EQ(message.bar_bytes(), "BYTES"); + + EXPECT_FALSE(message.has_bar_enum()); + EXPECT_EQ(message.bar_enum(), 2); +} + +TEST_F(OneofTest, SwapWithEmpty) { + UNITTEST::TestOneof2 message1, message2; + message1.set_foo_string("FOO"); + EXPECT_TRUE(message1.has_foo_string()); + message1.Swap(&message2); + EXPECT_FALSE(message1.has_foo_string()); + EXPECT_TRUE(message2.has_foo_string()); + EXPECT_EQ(message2.foo_string(), "FOO"); +} + +TEST_F(OneofTest, SwapWithSelf) { + UNITTEST::TestOneof2 message; + message.set_foo_string("FOO"); + EXPECT_TRUE(message.has_foo_string()); + message.Swap(&message); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "FOO"); +} + +TEST_F(OneofTest, SwapBothHasFields) { + UNITTEST::TestOneof2 message1, message2; + + message1.set_foo_string("FOO"); + EXPECT_TRUE(message1.has_foo_string()); + message2.mutable_foo_message()->set_qux_int(1); + EXPECT_TRUE(message2.has_foo_message()); + + message1.Swap(&message2); + EXPECT_FALSE(message1.has_foo_string()); + EXPECT_FALSE(message2.has_foo_message()); + EXPECT_TRUE(message1.has_foo_message()); + EXPECT_EQ(message1.foo_message().qux_int(), 1); + EXPECT_TRUE(message2.has_foo_string()); + EXPECT_EQ(message2.foo_string(), "FOO"); +} + +TEST_F(OneofTest, CopyConstructor) { + UNITTEST::TestOneof2 message1; + message1.set_foo_bytes("FOO"); + + UNITTEST::TestOneof2 message2(message1); + EXPECT_TRUE(message2.has_foo_bytes()); + EXPECT_EQ(message2.foo_bytes(), "FOO"); +} + +TEST_F(OneofTest, CopyFrom) { + UNITTEST::TestOneof2 message1, message2; + message1.set_foo_enum(UNITTEST::TestOneof2::BAR); + EXPECT_TRUE(message1.has_foo_enum()); + + message2.CopyFrom(message1); + EXPECT_TRUE(message2.has_foo_enum()); + EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::BAR); + + // Copying from self should be a no-op. + message2.CopyFrom(message2); + EXPECT_TRUE(message2.has_foo_enum()); + EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::BAR); +} + +TEST_F(OneofTest, CopyAssignmentOperator) { + UNITTEST::TestOneof2 message1; + message1.mutable_foo_message()->set_qux_int(123); + EXPECT_TRUE(message1.has_foo_message()); + + UNITTEST::TestOneof2 message2; + message2 = message1; + EXPECT_EQ(message2.foo_message().qux_int(), 123); + + // Make sure that self-assignment does something sane. + message2 = *&message2; // Avoid -Wself-assign. + EXPECT_EQ(message2.foo_message().qux_int(), 123); +} + +TEST_F(OneofTest, UpcastCopyFrom) { + // Test the CopyFrom method that takes in the generic const Message& + // parameter. + UNITTEST::TestOneof2 message1, message2; + message1.mutable_foogroup()->set_a(123); + EXPECT_TRUE(message1.has_foogroup()); + + const Message* source = implicit_cast(&message1); + message2.CopyFrom(*source); + + EXPECT_TRUE(message2.has_foogroup()); + EXPECT_EQ(message2.foogroup().a(), 123); +} + +// Test the generated SerializeWithCachedSizesToArray(), +// This indirectly tests MergePartialFromCodedStream() +// We have to test each field type separately because we cannot set them at the +// same time +TEST_F(OneofTest, SerializationToArray) { + // Primitive type + { + UNITTEST::TestOneof2 message1, message2; +std::string data; +message1.set_foo_int(123); +int size = message1.ByteSizeLong(); +data.resize(size); +uint8* start = reinterpret_cast(::google::protobuf::string_as_array(&data)); +uint8* end = message1.SerializeWithCachedSizesToArray(start); +EXPECT_EQ(size, end - start); +EXPECT_TRUE(message2.ParseFromString(data)); +EXPECT_EQ(message2.foo_int(), 123); + } + + // String + { + UNITTEST::TestOneof2 message1, message2; + std::string data; + message1.set_foo_string("foo"); + int size = message1.ByteSizeLong(); + data.resize(size); + uint8* start = reinterpret_cast(::google::protobuf::string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_string(), "foo"); + } + + + // Bytes + { + UNITTEST::TestOneof2 message1, message2; + std::string data; + message1.set_foo_bytes("qux"); + int size = message1.ByteSizeLong(); + data.resize(size); + uint8* start = reinterpret_cast(::google::protobuf::string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_bytes(), "qux"); + } + + // Enum + { + UNITTEST::TestOneof2 message1, message2; + std::string data; + message1.set_foo_enum(UNITTEST::TestOneof2::FOO); + int size = message1.ByteSizeLong(); + data.resize(size); + uint8* start = reinterpret_cast(::google::protobuf::string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::FOO); + } + + // Message + { + UNITTEST::TestOneof2 message1, message2; + std::string data; + message1.mutable_foo_message()->set_qux_int(234); + int size = message1.ByteSizeLong(); + data.resize(size); + uint8* start = reinterpret_cast(::google::protobuf::string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_message().qux_int(), 234); + } + + // Group + { + UNITTEST::TestOneof2 message1, message2; + std::string data; + message1.mutable_foogroup()->set_a(345); + int size = message1.ByteSizeLong(); + data.resize(size); + uint8* start = reinterpret_cast(::google::protobuf::string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foogroup().a(), 345); + } + +} + +// Test the generated SerializeWithCachedSizes() by forcing the buffer to write +// one byte at a time. +// This indirectly tests MergePartialFromCodedStream() +// We have to test each field type separately because we cannot set them at the +// same time +TEST_F(OneofTest, SerializationToStream) { + // Primitive type + { + UNITTEST::TestOneof2 message1, message2; +std::string data; +message1.set_foo_int(123); +int size = message1.ByteSizeLong(); +data.resize(size); + +{ + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); +} + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_int(), 123); + } + + // String + { + UNITTEST::TestOneof2 message1, message2; + std::string data; + message1.set_foo_string("foo"); + int size = message1.ByteSizeLong(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_string(), "foo"); + } + + + // Bytes + { + UNITTEST::TestOneof2 message1, message2; + std::string data; + message1.set_foo_bytes("qux"); + int size = message1.ByteSizeLong(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_bytes(), "qux"); + } + + // Enum + { + UNITTEST::TestOneof2 message1, message2; + std::string data; + message1.set_foo_enum(UNITTEST::TestOneof2::FOO); + int size = message1.ByteSizeLong(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::FOO); + } + + // Message + { + UNITTEST::TestOneof2 message1, message2; + std::string data; + message1.mutable_foo_message()->set_qux_int(234); + int size = message1.ByteSizeLong(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_message().qux_int(), 234); + } + + // Group + { + UNITTEST::TestOneof2 message1, message2; + std::string data; + message1.mutable_foogroup()->set_a(345); + int size = message1.ByteSizeLong(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foogroup().a(), 345); + } + +} + +TEST_F(OneofTest, MergeFrom) { + UNITTEST::TestOneof2 message1, message2; + + message1.set_foo_int(123); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_int()); + EXPECT_EQ(message2.foo_int(), 123); + + message1.set_foo_string("foo"); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_string()); + EXPECT_EQ(message2.foo_string(), "foo"); + + + message1.set_foo_bytes("qux"); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_bytes()); + EXPECT_EQ(message2.foo_bytes(), "qux"); + + message1.set_foo_enum(UNITTEST::TestOneof2::FOO); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_enum()); + EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::FOO); + + message1.mutable_foo_message()->set_qux_int(234); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_message()); + EXPECT_EQ(message2.foo_message().qux_int(), 234); + + message1.mutable_foogroup()->set_a(345); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foogroup()); + EXPECT_EQ(message2.foogroup().a(), 345); + +} + +TEST(HELPERS_TEST_NAME, TestSCC) { + UNITTEST::TestMutualRecursionA a; + MessageSCCAnalyzer scc_analyzer((Options())); + const SCC* scc = scc_analyzer.GetSCC(a.GetDescriptor()); + std::vector names; + names.reserve(scc->descriptors.size()); + for (int i = 0; i < scc->descriptors.size(); i++) { + names.push_back(scc->descriptors[i]->full_name()); + } + std::string package = a.GetDescriptor()->file()->package(); + ASSERT_EQ(names.size(), 4); + std::sort(names.begin(), names.end()); + EXPECT_EQ(names[0], package + ".TestMutualRecursionA"); + EXPECT_EQ(names[1], package + ".TestMutualRecursionA.SubGroup"); + EXPECT_EQ(names[2], package + ".TestMutualRecursionA.SubMessage"); + EXPECT_EQ(names[3], package + ".TestMutualRecursionB"); + + MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc); + EXPECT_EQ(result.is_recursive, true); + EXPECT_EQ(result.contains_required, false); + EXPECT_EQ(result.contains_cord, true); // TestAllTypes + EXPECT_EQ(result.contains_extension, false); // TestAllTypes +} + +TEST(HELPERS_TEST_NAME, TestSCCAnalysis) { + { + UNITTEST::TestRecursiveMessage msg; + MessageSCCAnalyzer scc_analyzer((Options())); + const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor()); + MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc); + EXPECT_EQ(result.is_recursive, true); + EXPECT_EQ(result.contains_required, false); + EXPECT_EQ(result.contains_cord, false); + EXPECT_EQ(result.contains_extension, false); + } + { + UNITTEST::TestAllExtensions msg; + MessageSCCAnalyzer scc_analyzer((Options())); + const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor()); + MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc); + EXPECT_EQ(result.is_recursive, false); + EXPECT_EQ(result.contains_required, false); + EXPECT_EQ(result.contains_cord, false); + EXPECT_EQ(result.contains_extension, true); + } + { + UNITTEST::TestRequired msg; + MessageSCCAnalyzer scc_analyzer((Options())); + const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor()); + MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc); + EXPECT_EQ(result.is_recursive, false); + EXPECT_EQ(result.contains_required, true); + EXPECT_EQ(result.contains_cord, false); + EXPECT_EQ(result.contains_extension, false); + } +} + +} // namespace cpp_unittest +} // namespace cpp +} // namespace compiler + +namespace no_generic_services_test { + // Verify that no class called "TestService" was defined in + // unittest_no_generic_services.pb.h by defining a different type by the same + // name. If such a service was generated, this will not compile. + struct TestService { + int i; + }; +} + +namespace compiler { +namespace cpp { +namespace cpp_unittest { + +TEST_F(GENERATED_SERVICE_TEST_NAME, NoGenericServices) { + // Verify that non-services in unittest_no_generic_services.proto were + // generated. + ::protobuf_unittest::no_generic_services_test::TestMessage message; + message.set_a(1); + message.SetExtension( + ::protobuf_unittest::no_generic_services_test::test_extension, 123); + ::protobuf_unittest::no_generic_services_test::TestEnum e = + ::protobuf_unittest::no_generic_services_test::FOO; + EXPECT_EQ(e, 1); + + // Verify that a ServiceDescriptor is generated for the service even if the + // class itself is not. + const FileDescriptor* file = + ::google::protobuf::unittest::no_generic_services_test::TestMessage::descriptor() + ->file(); + + ASSERT_EQ(1, file->service_count()); + EXPECT_EQ("TestService", file->service(0)->name()); + ASSERT_EQ(1, file->service(0)->method_count()); + EXPECT_EQ("Foo", file->service(0)->method(0)->name()); +} + +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS + +// =================================================================== + +// This test must run last. It verifies that descriptors were or were not +// initialized depending on whether PROTOBUF_TEST_NO_DESCRIPTORS was defined. +// When this is defined, we skip all tests which are expected to trigger +// descriptor initialization. This verifies that everything else still works +// if descriptors are not initialized. +TEST(DESCRIPTOR_INIT_TEST_NAME, Initialized) { +#ifdef PROTOBUF_TEST_NO_DESCRIPTORS + bool should_have_descriptors = false; +#else + bool should_have_descriptors = true; +#endif + + EXPECT_EQ(should_have_descriptors, + DescriptorPool::generated_pool()->InternalIsFileLoaded( + TestUtil::MaybeTranslatePath(UNITTEST_PROTO_PATH))); +} + +} // namespace cpp_unittest + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include diff --git a/src/google/protobuf/compiler/cpp/metadata_test.cc b/src/google/protobuf/compiler/cpp/metadata_test.cc index 03f6b12b4a887..b5cac8f42f7f0 100644 --- a/src/google/protobuf/compiler/cpp/metadata_test.cc +++ b/src/google/protobuf/compiler/cpp/metadata_test.cc @@ -29,20 +29,14 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#ifndef _SHARED_PTR_H -#include -#endif +#include +#include #include #include +#include #include -#include -#include -#include #include - -#include -#include #include #include @@ -50,66 +44,37 @@ namespace google { namespace protobuf { namespace compiler { namespace cpp { -namespace { -// A CodeGenerator that captures the FileDescriptor it's passed as a -// FileDescriptorProto. -class DescriptorCapturingGenerator : public CodeGenerator { - public: - // Does not own file; file must outlive the Generator. - explicit DescriptorCapturingGenerator(FileDescriptorProto* file) - : file_(file) {} +namespace atu = annotation_test_util; - virtual bool Generate(const FileDescriptor* file, const string& parameter, - GeneratorContext* context, string* error) const { - file->CopyTo(file_); - return true; - } - - private: - FileDescriptorProto* file_; -}; +namespace { class CppMetadataTest : public ::testing::Test { public: - // Adds a file with name `filename` and content `data`. - void AddFile(const string& filename, const string& data) { - GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/" + filename, data, - true)); - } - // Tries to capture a FileDescriptorProto, GeneratedCodeInfo, and output // code from the previously added file with name `filename`. Returns true on // success. If pb_h is non-null, expects a .pb.h and a .pb.h.meta (copied to // pb_h and pb_h_info respecfively); similarly for proto_h and proto_h_info. - bool CaptureMetadata(const string& filename, FileDescriptorProto* file, - string* pb_h, GeneratedCodeInfo* pb_h_info, - string* proto_h, GeneratedCodeInfo* proto_h_info, - string* pb_cc) { - google::protobuf::compiler::CommandLineInterface cli; - cli.SetInputsAreProtoPathRelative(true); - + bool CaptureMetadata(const std::string& filename, FileDescriptorProto* file, + std::string* pb_h, GeneratedCodeInfo* pb_h_info, + std::string* proto_h, GeneratedCodeInfo* proto_h_info, + std::string* pb_cc) { + CommandLineInterface cli; CppGenerator cpp_generator; - DescriptorCapturingGenerator capturing_generator(file); cli.RegisterGenerator("--cpp_out", &cpp_generator, ""); - cli.RegisterGenerator("--capture_out", &capturing_generator, ""); - - string proto_path = "-I" + TestTempDir(); - string cpp_out = + std::string cpp_out = "--cpp_out=annotate_headers=true," "annotation_pragma_name=pragma_name," "annotation_guard_name=guard_name:" + TestTempDir(); - string capture_out = "--capture_out=" + TestTempDir(); - const char* argv[] = {"protoc", proto_path.c_str(), cpp_out.c_str(), - capture_out.c_str(), filename.c_str()}; + const bool result = atu::RunProtoCompiler(filename, cpp_out, &cli, file); - if (cli.Run(5, argv) != 0) { - return false; + if (!result) { + return result; } - string output_base = TestTempDir() + "/" + StripProto(filename); + std::string output_base = TestTempDir() + "/" + StripProto(filename); if (pb_cc != NULL) { GOOGLE_CHECK_OK( @@ -119,7 +84,7 @@ class CppMetadataTest : public ::testing::Test { if (pb_h != NULL && pb_h_info != NULL) { GOOGLE_CHECK_OK( File::GetContents(output_base + ".pb.h", pb_h, true)); - if (!DecodeMetadata(output_base + ".pb.h.meta", pb_h_info)) { + if (!atu::DecodeMetadata(output_base + ".pb.h.meta", pb_h_info)) { return false; } } @@ -127,23 +92,13 @@ class CppMetadataTest : public ::testing::Test { if (proto_h != NULL && proto_h_info != NULL) { GOOGLE_CHECK_OK(File::GetContents(output_base + ".proto.h", proto_h, true)); - if (!DecodeMetadata(output_base + ".proto.h.meta", proto_h_info)) { + if (!atu::DecodeMetadata(output_base + ".proto.h.meta", proto_h_info)) { return false; } } return true; } - - private: - // Decodes GeneratedCodeInfo stored in path and copies it to info. - // Returns true on success. - bool DecodeMetadata(const string& path, GeneratedCodeInfo* info) { - string data; - GOOGLE_CHECK_OK(File::GetContents(path, &data, true)); - io::ArrayInputStream input(data.data(), data.size()); - return info->ParseFromZeroCopyStream(&input); - } }; const char kSmallTestFile[] = @@ -152,48 +107,11 @@ const char kSmallTestFile[] = "enum Enum { VALUE = 0; }\n" "message Message { }\n"; -// Finds the Annotation for a given source file and path (or returns null if it -// couldn't). -const GeneratedCodeInfo::Annotation* FindAnnotationOnPath( - const GeneratedCodeInfo& info, const string& source_file, - const std::vector& path) { - for (int i = 0; i < info.annotation_size(); ++i) { - const GeneratedCodeInfo::Annotation* annotation = &info.annotation(i); - if (annotation->source_file() != source_file || - annotation->path_size() != path.size()) { - continue; - } - int node = 0; - for (; node < path.size(); ++node) { - if (annotation->path(node) != path[node]) { - break; - } - } - if (node == path.size()) { - return annotation; - } - } - return NULL; -} - -// Returns true if the provided annotation covers a given substring in -// file_content. -bool AnnotationMatchesSubstring(const string& file_content, - const GeneratedCodeInfo::Annotation* annotation, - const string& expected_text) { - uint32 begin = annotation->begin(); - uint32 end = annotation->end(); - if (end < begin || end > file_content.size()) { - return false; - } - return file_content.substr(begin, end - begin) == expected_text; -} - TEST_F(CppMetadataTest, CapturesEnumNames) { FileDescriptorProto file; GeneratedCodeInfo info; - string pb_h; - AddFile("test.proto", kSmallTestFile); + std::string pb_h; + atu::AddFile("test.proto", kSmallTestFile); EXPECT_TRUE( CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL)); EXPECT_EQ("Enum", file.enum_type(0).name()); @@ -201,28 +119,28 @@ TEST_F(CppMetadataTest, CapturesEnumNames) { enum_path.push_back(FileDescriptorProto::kEnumTypeFieldNumber); enum_path.push_back(0); const GeneratedCodeInfo::Annotation* enum_annotation = - FindAnnotationOnPath(info, "test.proto", enum_path); + atu::FindAnnotationOnPath(info, "test.proto", enum_path); EXPECT_TRUE(NULL != enum_annotation); - EXPECT_TRUE(AnnotationMatchesSubstring(pb_h, enum_annotation, "Enum")); + EXPECT_TRUE(atu::AnnotationMatchesSubstring(pb_h, enum_annotation, "Enum")); } TEST_F(CppMetadataTest, AddsPragma) { FileDescriptorProto file; GeneratedCodeInfo info; - string pb_h; - AddFile("test.proto", kSmallTestFile); + std::string pb_h; + atu::AddFile("test.proto", kSmallTestFile); EXPECT_TRUE( CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL)); - EXPECT_TRUE(pb_h.find("#ifdef guard_name") != string::npos); + EXPECT_TRUE(pb_h.find("#ifdef guard_name") != std::string::npos); EXPECT_TRUE(pb_h.find("#pragma pragma_name \"test.pb.h.meta\"") != - string::npos); + std::string::npos); } TEST_F(CppMetadataTest, CapturesMessageNames) { FileDescriptorProto file; GeneratedCodeInfo info; - string pb_h; - AddFile("test.proto", kSmallTestFile); + std::string pb_h; + atu::AddFile("test.proto", kSmallTestFile); EXPECT_TRUE( CaptureMetadata("test.proto", &file, &pb_h, &info, NULL, NULL, NULL)); EXPECT_EQ("Message", file.message_type(0).name()); @@ -230,9 +148,10 @@ TEST_F(CppMetadataTest, CapturesMessageNames) { message_path.push_back(FileDescriptorProto::kMessageTypeFieldNumber); message_path.push_back(0); const GeneratedCodeInfo::Annotation* message_annotation = - FindAnnotationOnPath(info, "test.proto", message_path); + atu::FindAnnotationOnPath(info, "test.proto", message_path); EXPECT_TRUE(NULL != message_annotation); - EXPECT_TRUE(AnnotationMatchesSubstring(pb_h, message_annotation, "Message")); + EXPECT_TRUE( + atu::AnnotationMatchesSubstring(pb_h, message_annotation, "Message")); } } // namespace diff --git a/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc index 5c54270e4cf2c..86bacf8103bd2 100644 --- a/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc +++ b/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc @@ -65,11 +65,11 @@ class MockErrorCollector : public MultiFileErrorCollector { MockErrorCollector() {} ~MockErrorCollector() {} - string text_; + std::string text_; // implements ErrorCollector --------------------------------------- - void AddError(const string& filename, int line, int column, - const string& message) { + void AddError(const std::string& filename, int line, int column, + const std::string& message) { strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column, message); } @@ -77,23 +77,19 @@ class MockErrorCollector : public MultiFileErrorCollector { class MockGeneratorContext : public GeneratorContext { public: - MockGeneratorContext() {} - ~MockGeneratorContext() { - STLDeleteValues(&files_); - } - - void ExpectFileMatches(const string& virtual_filename, - const string& physical_filename) { - string* expected_contents = FindPtrOrNull(files_, virtual_filename); - ASSERT_TRUE(expected_contents != NULL) + void ExpectFileMatches(const std::string& virtual_filename, + const std::string& physical_filename) { + auto it = files_.find(virtual_filename); + ASSERT_TRUE(it != files_.end()) << "Generator failed to generate file: " << virtual_filename; + std::string expected_contents = *it->second; - string actual_contents; + std::string actual_contents; GOOGLE_CHECK_OK( - File::GetContents(TestSourceDir() + "/" + physical_filename, + File::GetContentsAsText(TestSourceDir() + "/" + physical_filename, &actual_contents, true)) << "Unable to get " << physical_filename; - EXPECT_TRUE(actual_contents == *expected_contents) + EXPECT_TRUE(actual_contents == expected_contents) << physical_filename << " needs to be regenerated. Please run " "generate_descriptor_proto.sh. Then add this file " "to your CL."; @@ -101,22 +97,20 @@ class MockGeneratorContext : public GeneratorContext { // implements GeneratorContext -------------------------------------- - virtual io::ZeroCopyOutputStream* Open(const string& filename) { - string** map_slot = &files_[filename]; - delete *map_slot; - *map_slot = new string; - - return new io::StringOutputStream(*map_slot); + virtual io::ZeroCopyOutputStream* Open(const std::string& filename) { + auto& map_slot = files_[filename]; + map_slot.reset(new std::string); + return new io::StringOutputStream(map_slot.get()); } private: - std::map files_; + std::map> files_; }; class GenerateAndTest { public: GenerateAndTest() {} - void Run(const FileDescriptor* proto_file, string file1, string file2) { + void Run(const FileDescriptor* proto_file, std::string file1, std::string file2) { ASSERT_TRUE(proto_file != NULL) << TestSourceDir(); ASSERT_TRUE(generator_.Generate(proto_file, parameter_, &context_, &error_)); @@ -129,14 +123,14 @@ class GenerateAndTest { private: Generator generator_; MockGeneratorContext context_; - string error_; - string parameter_; + std::string error_; + std::string parameter_; }; TEST(CsharpBootstrapTest, GeneratedCsharpDescriptorMatches) { // Skip this whole test if the csharp directory doesn't exist (i.e., a C++11 // only distribution). - string descriptor_file_name = + std::string descriptor_file_name = "../csharp/src/Google.Protobuf/Reflection/Descriptor.cs"; if (!File::Exists(TestSourceDir() + "/" + descriptor_file_name)) { return; @@ -184,11 +178,6 @@ TEST(CsharpBootstrapTest, GeneratedCsharpDescriptorMatches) { "../csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs"); generate_test.SetParameter(""); - source_tree.MapPath("", TestSourceDir() + "/../examples"); - generate_test.Run(importer.Import("addressbook.proto"), - "Addressbook.cs", - "../csharp/src/AddressBook/Addressbook.cs"); - source_tree.MapPath("", TestSourceDir() + "/../conformance"); generate_test.Run(importer.Import("conformance.proto"), "Conformance.cs", diff --git a/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc b/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc index 636a76a0b920c..225d6dc54ea18 100644 --- a/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc +++ b/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc @@ -47,7 +47,7 @@ namespace csharp { // is inlined in the relevant code. If more control is required, that code can be moved here. void WriteDocCommentBodyImpl(io::Printer* printer, SourceLocation location) { - string comments = location.leading_comments.empty() ? + std::string comments = location.leading_comments.empty() ? location.trailing_comments : location.leading_comments; if (comments.empty()) { return; @@ -56,7 +56,8 @@ void WriteDocCommentBodyImpl(io::Printer* printer, SourceLocation location) { // node of a summary element, not part of an attribute. comments = StringReplace(comments, "&", "&", true); comments = StringReplace(comments, "<", "<", true); - vector lines = Split(comments, "\n", false /* skip_empty */); + std::vector lines; + lines = Split(comments, "\n", false); // TODO: We really should work out which part to put in the summary and which to put in the remarks... // but that needs to be part of a bigger effort to understand the markdown better anyway. printer->Print("/// \n"); @@ -65,17 +66,18 @@ void WriteDocCommentBodyImpl(io::Printer* printer, SourceLocation location) { // to preserve the blank lines themselves, as this is relevant in the markdown. // Note that we can't remove leading or trailing whitespace as *that's* relevant in markdown too. // (We don't skip "just whitespace" lines, either.) - for (std::vector::iterator it = lines.begin(); it != lines.end(); ++it) { - string line = *it; - if (line.empty()) { - last_was_empty = true; - } else { - if (last_was_empty) { - printer->Print("///\n"); - } - last_was_empty = false; - printer->Print("///$line$\n", "line", *it); + for (std::vector::iterator it = lines.begin(); + it != lines.end(); ++it) { + std::string line = *it; + if (line.empty()) { + last_was_empty = true; + } else { + if (last_was_empty) { + printer->Print("///\n"); } + last_was_empty = false; + printer->Print("///$line$\n", "line", *it); + } } printer->Print("/// \n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc index 9759e3ef267f9..6d379235ce2c8 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -43,8 +42,6 @@ #include #include -using google::protobuf::internal::scoped_ptr; - namespace google { namespace protobuf { namespace compiler { @@ -64,12 +61,13 @@ void EnumGenerator::Generate(io::Printer* printer) { "access_level", class_access_level(), "name", descriptor_->name()); printer->Indent(); - std::set used_names; + std::set used_names; std::set used_number; for (int i = 0; i < descriptor_->value_count(); i++) { WriteEnumValueDocComment(printer, descriptor_->value(i)); - string original_name = descriptor_->value(i)->name(); - string name = GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name()); + std::string original_name = descriptor_->value(i)->name(); + std::string name = + GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name()); // Make sure we don't get any duplicate names due to prefix removal. while (!used_names.insert(name).second) { // It's possible we'll end up giving this warning multiple times, but that's better than not at all. @@ -82,12 +80,12 @@ void EnumGenerator::Generate(io::Printer* printer) { printer->Print("[pbr::OriginalName(\"$original_name$\", PreferredAlias = false)] $name$ = $number$,\n", "original_name", original_name, "name", name, - "number", SimpleItoa(number)); + "number", StrCat(number)); } else { printer->Print("[pbr::OriginalName(\"$original_name$\")] $name$ = $number$,\n", "original_name", original_name, "name", name, - "number", SimpleItoa(number)); + "number", StrCat(number)); } } printer->Outdent(); diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.h b/src/google/protobuf/compiler/csharp/csharp_enum.h index 8925cdf2bedfa..e409c2e4b261a 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum.h +++ b/src/google/protobuf/compiler/csharp/csharp_enum.h @@ -35,6 +35,8 @@ #include #include +#include +#include namespace google { namespace protobuf { @@ -46,12 +48,13 @@ class EnumGenerator : public SourceGeneratorBase { EnumGenerator(const EnumDescriptor* descriptor, const Options* options); ~EnumGenerator(); + EnumGenerator(const EnumGenerator&) = delete; + EnumGenerator& operator=(const EnumGenerator&) = delete; + void Generate(io::Printer* printer); private: const EnumDescriptor* descriptor_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); }; } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index 67c0b5961acfc..186fa27e5b36c 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -31,12 +31,12 @@ #include #include -#include #include #include #include #include +#include #include #include #include @@ -47,8 +47,8 @@ namespace compiler { namespace csharp { EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, const Options *options) - : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) { + int presenceIndex, const Options *options) + : PrimitiveFieldGenerator(descriptor, presenceIndex, options) { } EnumFieldGenerator::~EnumFieldGenerator() { @@ -56,7 +56,7 @@ EnumFieldGenerator::~EnumFieldGenerator() { void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print(variables_, - "$name$_ = ($type_name$) input.ReadEnum();\n"); + "$property_name$ = ($type_name$) input.ReadEnum();\n"); } void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { @@ -76,19 +76,34 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { } void EnumFieldGenerator::GenerateCodecCode(io::Printer* printer) { - printer->Print( - variables_, - "pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x)"); + printer->Print( + variables_, + "pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x, $default_value$)"); +} + +void EnumFieldGenerator::GenerateExtensionCode(io::Printer* printer) { + WritePropertyDocComment(printer, descriptor_); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n" + " new pb::Extension<$extended_type$, $type_name$>($number$, "); + GenerateCodecCode(printer); + printer->Print(");\n"); } EnumOneofFieldGenerator::EnumOneofFieldGenerator( - const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) - : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options) { + const FieldDescriptor* descriptor, int presenceIndex, const Options *options) + : PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options) { } EnumOneofFieldGenerator::~EnumOneofFieldGenerator() { } +void EnumOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print(variables_, "$property_name$ = other.$property_name$;\n"); +} + void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { // TODO(jonskeet): What about if we read the default value? printer->Print( diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h index 9b7669ba5dc04..9f1a2ea777c41 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h @@ -44,32 +44,34 @@ namespace csharp { class EnumFieldGenerator : public PrimitiveFieldGenerator { public: EnumFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~EnumFieldGenerator(); + EnumFieldGenerator(const EnumFieldGenerator&) = delete; + EnumFieldGenerator& operator=(const EnumFieldGenerator&) = delete; + virtual void GenerateCodecCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); + virtual void GenerateExtensionCode(io::Printer* printer); }; class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator { public: EnumOneofFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~EnumOneofFieldGenerator(); + EnumOneofFieldGenerator(const EnumOneofFieldGenerator&) = delete; + EnumOneofFieldGenerator& operator=(const EnumOneofFieldGenerator&) = delete; + + virtual void GenerateMergingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator); }; } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index ecf29ecea5d78..f5f4c2391ea7f 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -28,17 +28,16 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include #include #include #include -#include #include #include #include #include #include -#include #include #include @@ -46,65 +45,101 @@ #include #include -using google::protobuf::internal::scoped_ptr; - namespace google { namespace protobuf { namespace compiler { namespace csharp { void FieldGeneratorBase::SetCommonFieldVariables( - std::map* variables) { + std::map* variables) { // Note: this will be valid even though the tag emitted for packed and unpacked versions of // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which // never effects the tag size. int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); + int part_tag_size = tag_size; + if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { + part_tag_size /= 2; + } uint tag = internal::WireFormat::MakeTag(descriptor_); uint8 tag_array[5]; io::CodedOutputStream::WriteTagToArray(tag, tag_array); - string tag_bytes = SimpleItoa(tag_array[0]); - for (int i = 1; i < tag_size; i++) { - tag_bytes += ", " + SimpleItoa(tag_array[i]); + std::string tag_bytes = StrCat(tag_array[0]); + for (int i = 1; i < part_tag_size; i++) { + tag_bytes += ", " + StrCat(tag_array[i]); } - (*variables)["access_level"] = "public"; - (*variables)["tag"] = SimpleItoa(tag); - (*variables)["tag_size"] = SimpleItoa(tag_size); + (*variables)["tag"] = StrCat(tag); + (*variables)["tag_size"] = StrCat(tag_size); (*variables)["tag_bytes"] = tag_bytes; + if (descriptor_->type() == FieldDescriptor::Type::TYPE_GROUP) { + tag = internal::WireFormatLite::MakeTag( + descriptor_->number(), + internal::WireFormatLite::WIRETYPE_END_GROUP); + io::CodedOutputStream::WriteTagToArray(tag, tag_array); + tag_bytes = StrCat(tag_array[0]); + for (int i = 1; i < part_tag_size; i++) { + tag_bytes += ", " + StrCat(tag_array[i]); + } + + variables_["end_tag"] = StrCat(tag); + variables_["end_tag_bytes"] = tag_bytes; + } + + (*variables)["access_level"] = "public"; + (*variables)["property_name"] = property_name(); (*variables)["type_name"] = type_name(); + (*variables)["extended_type"] = GetClassName(descriptor_->containing_type()); (*variables)["name"] = name(); (*variables)["descriptor_name"] = descriptor_->name(); (*variables)["default_value"] = default_value(); - if (has_default_value()) { + (*variables)["capitalized_type_name"] = capitalized_type_name(); + (*variables)["number"] = number(); + if (has_default_value() && !SupportsPresenceApi(descriptor_)) { (*variables)["name_def_message"] = (*variables)["name"] + "_ = " + (*variables)["default_value"]; } else { (*variables)["name_def_message"] = (*variables)["name"] + "_"; } - (*variables)["capitalized_type_name"] = capitalized_type_name(); - (*variables)["number"] = number(); - (*variables)["has_property_check"] = - (*variables)["property_name"] + " != " + (*variables)["default_value"]; - (*variables)["other_has_property_check"] = "other." + - (*variables)["property_name"] + " != " + (*variables)["default_value"]; + if (SupportsPresenceApi(descriptor_)) { + (*variables)["has_property_check"] = "Has" + (*variables)["property_name"]; + (*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"]; + (*variables)["has_not_property_check"] = "!" + (*variables)["has_property_check"]; + (*variables)["other_has_not_property_check"] = "!" + (*variables)["other_has_property_check"]; + if (presenceIndex_ != -1) { + std::string hasBitsNumber = StrCat(presenceIndex_ / 32); + std::string hasBitsMask = StrCat(1 << (presenceIndex_ % 32)); + (*variables)["has_field_check"] = "(_hasBits" + hasBitsNumber + " & " + hasBitsMask + ") != 0"; + (*variables)["set_has_field"] = "_hasBits" + hasBitsNumber + " |= " + hasBitsMask; + (*variables)["clear_has_field"] = "_hasBits" + hasBitsNumber + " &= ~" + hasBitsMask; + } + } else { + (*variables)["has_property_check"] = + (*variables)["property_name"] + " != " + (*variables)["default_value"]; + (*variables)["other_has_property_check"] = "other." + + (*variables)["property_name"] + " != " + (*variables)["default_value"]; + } } void FieldGeneratorBase::SetCommonOneofFieldVariables( - std::map* variables) { + std::map* variables) { (*variables)["oneof_name"] = oneof_name(); - (*variables)["has_property_check"] = - oneof_name() + "Case_ == " + oneof_property_name() + - "OneofCase." + property_name(); + if (SupportsPresenceApi(descriptor_)) { + (*variables)["has_property_check"] = "Has" + property_name(); + } else { + (*variables)["has_property_check"] = + oneof_name() + "Case_ == " + oneof_property_name() + + "OneofCase." + property_name(); + } (*variables)["oneof_property_name"] = oneof_property_name(); } FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor, - int fieldOrdinal, const Options* options) + int presenceIndex, const Options* options) : SourceGeneratorBase(descriptor->file(), options), descriptor_(descriptor), - fieldOrdinal_(fieldOrdinal) { + presenceIndex_(presenceIndex) { SetCommonFieldVariables(&variables_); } @@ -121,6 +156,23 @@ void FieldGeneratorBase::GenerateCodecCode(io::Printer* printer) { // Could fail if we get called here though... } +void FieldGeneratorBase::GenerateExtensionCode(io::Printer* printer) { + // No-op: only message fields, enum fields, primitives, + // and repeated fields need this default is to not generate any code +} + +void FieldGeneratorBase::GenerateParsingCode(io::Printer* printer, bool use_parse_context) { + // for some field types the value of "use_parse_context" doesn't matter, + // so we fallback to the default implementation. + GenerateParsingCode(printer); +} + +void FieldGeneratorBase::GenerateSerializationCode(io::Printer* printer, bool use_write_context) { + // for some field types the value of "use_write_context" doesn't matter, + // so we fallback to the default implementation. + GenerateSerializationCode(printer); +} + void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) { if (descriptor_->options().deprecated()) { printer->Print("[global::System.ObsoleteAttribute]\n"); @@ -164,7 +216,7 @@ std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) { if (IsWrapperType(descriptor)) { const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); - string wrapped_field_type_name = type_name(wrapped_field); + std::string wrapped_field_type_name = type_name(wrapped_field); // String and ByteString go to the same type; other wrapped types // go to the nullable equivalent. if (wrapped_field->type() == FieldDescriptor::TYPE_STRING || @@ -253,36 +305,6 @@ bool FieldGeneratorBase::has_default_value() { } } -bool FieldGeneratorBase::is_nullable_type() { - switch (descriptor_->type()) { - case FieldDescriptor::TYPE_ENUM: - case FieldDescriptor::TYPE_DOUBLE: - case FieldDescriptor::TYPE_FLOAT: - case FieldDescriptor::TYPE_INT64: - case FieldDescriptor::TYPE_UINT64: - case FieldDescriptor::TYPE_INT32: - case FieldDescriptor::TYPE_FIXED64: - case FieldDescriptor::TYPE_FIXED32: - case FieldDescriptor::TYPE_BOOL: - case FieldDescriptor::TYPE_UINT32: - case FieldDescriptor::TYPE_SFIXED32: - case FieldDescriptor::TYPE_SFIXED64: - case FieldDescriptor::TYPE_SINT32: - case FieldDescriptor::TYPE_SINT64: - return false; - - case FieldDescriptor::TYPE_MESSAGE: - case FieldDescriptor::TYPE_GROUP: - case FieldDescriptor::TYPE_STRING: - case FieldDescriptor::TYPE_BYTES: - return true; - - default: - GOOGLE_LOG(FATAL)<< "Unknown field type."; - return true; - } -} - bool AllPrintableAscii(const std::string& text) { for(int i = 0; i < text.size(); i++) { if (text[i] < 0x20 || text[i] > 0x7e) { @@ -292,14 +314,20 @@ bool AllPrintableAscii(const std::string& text) { return true; } -std::string FieldGeneratorBase::GetStringDefaultValueInternal() { - // No other default values needed for proto3... - return "\"\""; +std::string FieldGeneratorBase::GetStringDefaultValueInternal(const FieldDescriptor* descriptor) { + if (descriptor->default_value_string().empty()) + return "\"\""; + else + return "global::System.Text.Encoding.UTF8.GetString(global::System." + "Convert.FromBase64String(\"" + + StringToBase64(descriptor->default_value_string()) + "\"), 0, " + StrCat(descriptor->default_value_string().length()) + ")"; } -std::string FieldGeneratorBase::GetBytesDefaultValueInternal() { - // No other default values needed for proto3... - return "pb::ByteString.Empty"; +std::string FieldGeneratorBase::GetBytesDefaultValueInternal(const FieldDescriptor* descriptor) { + if (descriptor->default_value_string().empty()) + return "pb::ByteString.Empty"; + else + return "pb::ByteString.FromBase64(\"" + StringToBase64(descriptor->default_value_string()) + "\")"; } std::string FieldGeneratorBase::default_value() { @@ -309,9 +337,8 @@ std::string FieldGeneratorBase::default_value() { std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) { switch (descriptor->type()) { case FieldDescriptor::TYPE_ENUM: - // All proto3 enums have a default value of 0, and there's an implicit conversion from the constant 0 to - // any C# enum. This means we don't need to work out what we actually mapped the enum value name to. - return "0"; + return GetClassName(descriptor->default_value_enum()->type()) + "." + + GetEnumValueName(descriptor->default_value_enum()->type()->name(), descriptor->default_value_enum()->name()); case FieldDescriptor::TYPE_MESSAGE: case FieldDescriptor::TYPE_GROUP: if (IsWrapperType(descriptor)) { @@ -326,10 +353,10 @@ std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) return "double.PositiveInfinity"; } else if (value == -std::numeric_limits::infinity()) { return "double.NegativeInfinity"; - } else if (MathLimits::IsNaN(value)) { + } else if (std::isnan(value)) { return "double.NaN"; } - return SimpleDtoa(value) + "D"; + return StrCat(value) + "D"; } case FieldDescriptor::TYPE_FLOAT: { float value = descriptor->default_value_float(); @@ -337,21 +364,21 @@ std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) return "float.PositiveInfinity"; } else if (value == -std::numeric_limits::infinity()) { return "float.NegativeInfinity"; - } else if (MathLimits::IsNaN(value)) { + } else if (std::isnan(value)) { return "float.NaN"; } - return SimpleFtoa(value) + "F"; + return StrCat(value) + "F"; } case FieldDescriptor::TYPE_INT64: - return SimpleItoa(descriptor->default_value_int64()) + "L"; + return StrCat(descriptor->default_value_int64()) + "L"; case FieldDescriptor::TYPE_UINT64: - return SimpleItoa(descriptor->default_value_uint64()) + "UL"; + return StrCat(descriptor->default_value_uint64()) + "UL"; case FieldDescriptor::TYPE_INT32: - return SimpleItoa(descriptor->default_value_int32()); + return StrCat(descriptor->default_value_int32()); case FieldDescriptor::TYPE_FIXED64: - return SimpleItoa(descriptor->default_value_uint64()) + "UL"; + return StrCat(descriptor->default_value_uint64()) + "UL"; case FieldDescriptor::TYPE_FIXED32: - return SimpleItoa(descriptor->default_value_uint32()); + return StrCat(descriptor->default_value_uint32()); case FieldDescriptor::TYPE_BOOL: if (descriptor->default_value_bool()) { return "true"; @@ -359,19 +386,19 @@ std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) return "false"; } case FieldDescriptor::TYPE_STRING: - return GetStringDefaultValueInternal(); + return GetStringDefaultValueInternal(descriptor); case FieldDescriptor::TYPE_BYTES: - return GetBytesDefaultValueInternal(); + return GetBytesDefaultValueInternal(descriptor); case FieldDescriptor::TYPE_UINT32: - return SimpleItoa(descriptor->default_value_uint32()); + return StrCat(descriptor->default_value_uint32()); case FieldDescriptor::TYPE_SFIXED32: - return SimpleItoa(descriptor->default_value_int32()); + return StrCat(descriptor->default_value_int32()); case FieldDescriptor::TYPE_SFIXED64: - return SimpleItoa(descriptor->default_value_int64()) + "L"; + return StrCat(descriptor->default_value_int64()) + "L"; case FieldDescriptor::TYPE_SINT32: - return SimpleItoa(descriptor->default_value_int32()); + return StrCat(descriptor->default_value_int32()); case FieldDescriptor::TYPE_SINT64: - return SimpleItoa(descriptor->default_value_int64()) + "L"; + return StrCat(descriptor->default_value_int64()) + "L"; default: GOOGLE_LOG(FATAL)<< "Unknown field type."; return ""; @@ -379,7 +406,7 @@ std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) } std::string FieldGeneratorBase::number() { - return SimpleItoa(descriptor_->number()); + return StrCat(descriptor_->number()); } std::string FieldGeneratorBase::capitalized_type_name() { diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h index df26853b177ba..f875fa11ace42 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h @@ -36,6 +36,8 @@ #include #include +#include +#include namespace google { namespace protobuf { @@ -45,17 +47,23 @@ namespace csharp { class FieldGeneratorBase : public SourceGeneratorBase { public: FieldGeneratorBase(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options* options); ~FieldGeneratorBase(); + FieldGeneratorBase(const FieldGeneratorBase&) = delete; + FieldGeneratorBase& operator=(const FieldGeneratorBase&) = delete; + virtual void GenerateCloningCode(io::Printer* printer) = 0; virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateCodecCode(io::Printer* printer); + virtual void GenerateExtensionCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer) = 0; virtual void GenerateMergingCode(io::Printer* printer) = 0; virtual void GenerateParsingCode(io::Printer* printer) = 0; + virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context); virtual void GenerateSerializationCode(io::Printer* printer) = 0; + virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context); virtual void GenerateSerializedSizeCode(io::Printer* printer) = 0; virtual void WriteHash(io::Printer* printer) = 0; @@ -65,15 +73,16 @@ class FieldGeneratorBase : public SourceGeneratorBase { protected: const FieldDescriptor* descriptor_; - const int fieldOrdinal_; - std::map variables_; + const int presenceIndex_; + std::map variables_; void AddDeprecatedFlag(io::Printer* printer); void AddNullCheck(io::Printer* printer); void AddNullCheck(io::Printer* printer, const std::string& name); void AddPublicMemberAttributes(io::Printer* printer); - void SetCommonOneofFieldVariables(std::map* variables); + void SetCommonOneofFieldVariables( + std::map* variables); std::string oneof_property_name(); std::string oneof_name(); @@ -82,18 +91,15 @@ class FieldGeneratorBase : public SourceGeneratorBase { std::string type_name(); std::string type_name(const FieldDescriptor* descriptor); bool has_default_value(); - bool is_nullable_type(); std::string default_value(); std::string default_value(const FieldDescriptor* descriptor); std::string number(); std::string capitalized_type_name(); private: - void SetCommonFieldVariables(std::map* variables); - std::string GetStringDefaultValueInternal(); - std::string GetBytesDefaultValueInternal(); - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorBase); + void SetCommonFieldVariables(std::map* variables); + std::string GetStringDefaultValueInternal(const FieldDescriptor* descriptor); + std::string GetBytesDefaultValueInternal(const FieldDescriptor* descriptor); }; } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc index c13ed65beced9..5ce0651738b22 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -44,35 +43,31 @@ #include #include -using google::protobuf::internal::scoped_ptr; - namespace google { namespace protobuf { namespace compiler { namespace csharp { -void GenerateFile(const google::protobuf::FileDescriptor* file, - io::Printer* printer, +Generator::Generator() {} +Generator::~Generator() {} + +uint64_t Generator::GetSupportedFeatures() const { + return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL; +} + +void GenerateFile(const FileDescriptor* file, io::Printer* printer, const Options* options) { ReflectionClassGenerator reflectionClassGenerator(file, options); reflectionClassGenerator.Generate(printer); } -bool Generator::Generate( - const FileDescriptor* file, - const string& parameter, - GeneratorContext* generator_context, - string* error) const { - - vector > options; +bool Generator::Generate(const FileDescriptor* file, + const std::string& parameter, + GeneratorContext* generator_context, + std::string* error) const { + std::vector > options; ParseGeneratorParameter(parameter, &options); - // We only support proto3 - but we make an exception for descriptor.proto. - if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && !IsDescriptorProto(file)) { - *error = "C# code generation only supports proto3 syntax"; - return false; - } - struct Options cli_options; for (int i = 0; i < options.size(); i++) { @@ -83,13 +78,15 @@ bool Generator::Generate( cli_options.base_namespace_specified = true; } else if (options[i].first == "internal_access") { cli_options.internal_access = true; + } else if (options[i].first == "serializable") { + cli_options.serializable = true; } else { *error = "Unknown generator option: " + options[i].first; return false; } } - string filename_error = ""; + std::string filename_error = ""; std::string filename = GetOutputFile(file, cli_options.file_extension, cli_options.base_namespace_specified, @@ -100,7 +97,7 @@ bool Generator::Generate( *error = filename_error; return false; } - scoped_ptr output( + std::unique_ptr output( generator_context->Open(filename)); io::Printer printer(output.get(), '$'); diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.h b/src/google/protobuf/compiler/csharp/csharp_generator.h index c8b19529139d2..f41f9b8358adc 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.h +++ b/src/google/protobuf/compiler/csharp/csharp_generator.h @@ -37,6 +37,8 @@ #include +#include + namespace google { namespace protobuf { namespace compiler { @@ -46,14 +48,16 @@ namespace csharp { // header. If you create your own protocol compiler binary and you want // it to support C# output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT Generator - : public google::protobuf::compiler::CodeGenerator { -public: - virtual bool Generate( - const FileDescriptor* file, - const string& parameter, - GeneratorContext* generator_context, - string* error) const; +class PROTOC_EXPORT Generator : public CodeGenerator { + public: + Generator(); + ~Generator(); + bool Generate( + const FileDescriptor* file, + const std::string& parameter, + GeneratorContext* generator_context, + std::string* error) const override; + uint64_t GetSupportedFeatures() const override; }; } // namespace csharp @@ -61,4 +65,6 @@ class LIBPROTOC_EXPORT Generator } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 5bca1ffa72c35..32ef3994f16e0 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -33,9 +33,9 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include -#include #include #include +#include #include #include @@ -43,7 +43,6 @@ #include #include #include -#include #include #include @@ -134,11 +133,17 @@ std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor) return GetFileNameBase(descriptor) + "Reflection"; } +std::string GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor) { + // TODO: Detect collisions with existing messages, + // and append an underscore if necessary. + return GetFileNameBase(descriptor) + "Extensions"; +} + // TODO(jtattermusch): can we reuse a utility function? std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter, bool preserve_period) { - string result; + std::string result; // Note: I distrust ctype.h due to locales. for (int i = 0; i < input.size(); i++) { if ('a' <= input[i] && input[i] <= 'z') { @@ -169,7 +174,7 @@ std::string UnderscoresToCamelCase(const std::string& input, } } // Add a trailing "_" if the name should be altered. - if (input[input.size() - 1] == '#') { + if (input.size() > 0 && input[input.size() - 1] == '#') { result += '_'; } return result; @@ -190,14 +195,14 @@ std::string UnderscoresToPascalCase(const std::string& input) { // Lower letter Alphanumeric Same as current // Upper letter Alphanumeric Lower std::string ShoutyToPascalCase(const std::string& input) { - string result; + std::string result; // Simple way of implementing "always start with upper" char previous = '_'; for (int i = 0; i < input.size(); i++) { char current = input[i]; if (!ascii_isalnum(current)) { previous = current; - continue; + continue; } if (!ascii_isalnum(previous)) { result += ascii_toupper(current); @@ -227,7 +232,7 @@ std::string TryRemovePrefix(const std::string& prefix, const std::string& value) prefix_to_match += ascii_tolower(prefix[i]); } } - + // This keeps track of how much of value we've consumed size_t prefix_index, value_index; for (prefix_index = 0, value_index = 0; @@ -277,12 +282,50 @@ std::string GetEnumValueName(const std::string& enum_name, const std::string& en return result; } +uint GetGroupEndTag(const Descriptor* descriptor) { + const Descriptor* containing_type = descriptor->containing_type(); + if (containing_type != NULL) { + const FieldDescriptor* field; + for (int i = 0; i < containing_type->field_count(); i++) { + field = containing_type->field(i); + if (field->type() == FieldDescriptor::Type::TYPE_GROUP && + field->message_type() == descriptor) { + return internal::WireFormatLite::MakeTag( + field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP); + } + } + for (int i = 0; i < containing_type->extension_count(); i++) { + field = containing_type->extension(i); + if (field->type() == FieldDescriptor::Type::TYPE_GROUP && + field->message_type() == descriptor) { + return internal::WireFormatLite::MakeTag( + field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP); + } + } + } else { + const FileDescriptor* containing_file = descriptor->file(); + if (containing_file != NULL) { + const FieldDescriptor* field; + for (int i = 0; i < containing_file->extension_count(); i++) { + field = containing_file->extension(i); + if (field->type() == FieldDescriptor::Type::TYPE_GROUP && + field->message_type() == descriptor) { + return internal::WireFormatLite::MakeTag( + field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP); + } + } + } + } + + return 0; +} + std::string ToCSharpName(const std::string& name, const FileDescriptor* file) { std::string result = GetFileNamespace(file); - if (result != "") { + if (!result.empty()) { result += '.'; } - string classname; + std::string classname; if (file->package().empty()) { classname = name; } else { @@ -303,6 +346,15 @@ std::string GetReflectionClassName(const FileDescriptor* descriptor) { return "global::" + result; } +std::string GetFullExtensionName(const FieldDescriptor* descriptor) { + if (descriptor->extension_scope()) { + return GetClassName(descriptor->extension_scope()) + ".Extensions." + GetPropertyName(descriptor); + } + else { + return GetExtensionClassUnqualifiedName(descriptor->file()) + "." + GetPropertyName(descriptor); + } +} + std::string GetClassName(const Descriptor* descriptor) { return ToCSharpName(descriptor->full_name(), descriptor->file()); } @@ -341,24 +393,23 @@ std::string GetPropertyName(const FieldDescriptor* descriptor) { return property_name; } -std::string GetOutputFile( - const google::protobuf::FileDescriptor* descriptor, - const std::string file_extension, - const bool generate_directories, - const std::string base_namespace, - string* error) { - string relative_filename = GetFileNameBase(descriptor) + file_extension; +std::string GetOutputFile(const FileDescriptor* descriptor, + const std::string file_extension, + const bool generate_directories, + const std::string base_namespace, + std::string* error) { + std::string relative_filename = GetFileNameBase(descriptor) + file_extension; if (!generate_directories) { return relative_filename; } - string ns = GetFileNamespace(descriptor); - string namespace_suffix = ns; + std::string ns = GetFileNamespace(descriptor); + std::string namespace_suffix = ns; if (!base_namespace.empty()) { // Check that the base_namespace is either equal to or a leading part of // the file namespace. This isn't just a simple prefix; "Foo.B" shouldn't // be regarded as a prefix of "Foo.Bar". The simplest option is to add "." // to both. - string extended_ns = ns + "."; + std::string extended_ns = ns + "."; if (extended_ns.find(base_namespace + ".") != 0) { *error = "Namespace " + ns + " is not a prefix namespace of base namespace " + base_namespace; return ""; // This will be ignored, because we've set an error. @@ -369,7 +420,7 @@ std::string GetOutputFile( } } - string namespace_dir = StringReplace(namespace_suffix, ".", "/", true); + std::string namespace_dir = StringReplace(namespace_suffix, ".", "/", true); if (!namespace_dir.empty()) { namespace_dir += "/"; } @@ -452,55 +503,89 @@ std::string FileDescriptorToBase64(const FileDescriptor* descriptor) { } FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options* options) { switch (descriptor->type()) { case FieldDescriptor::TYPE_GROUP: case FieldDescriptor::TYPE_MESSAGE: if (descriptor->is_repeated()) { if (descriptor->is_map()) { - return new MapFieldGenerator(descriptor, fieldOrdinal, options); + return new MapFieldGenerator(descriptor, presenceIndex, options); } else { - return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal, options); + return new RepeatedMessageFieldGenerator(descriptor, presenceIndex, options); } } else { if (IsWrapperType(descriptor)) { - if (descriptor->containing_oneof()) { - return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal, options); + if (descriptor->real_containing_oneof()) { + return new WrapperOneofFieldGenerator(descriptor, presenceIndex, options); } else { - return new WrapperFieldGenerator(descriptor, fieldOrdinal, options); + return new WrapperFieldGenerator(descriptor, presenceIndex, options); } } else { - if (descriptor->containing_oneof()) { - return new MessageOneofFieldGenerator(descriptor, fieldOrdinal, options); + if (descriptor->real_containing_oneof()) { + return new MessageOneofFieldGenerator(descriptor, presenceIndex, options); } else { - return new MessageFieldGenerator(descriptor, fieldOrdinal, options); + return new MessageFieldGenerator(descriptor, presenceIndex, options); } } } case FieldDescriptor::TYPE_ENUM: if (descriptor->is_repeated()) { - return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal, options); + return new RepeatedEnumFieldGenerator(descriptor, presenceIndex, options); } else { - if (descriptor->containing_oneof()) { - return new EnumOneofFieldGenerator(descriptor, fieldOrdinal, options); + if (descriptor->real_containing_oneof()) { + return new EnumOneofFieldGenerator(descriptor, presenceIndex, options); } else { - return new EnumFieldGenerator(descriptor, fieldOrdinal, options); + return new EnumFieldGenerator(descriptor, presenceIndex, options); } } default: if (descriptor->is_repeated()) { - return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal, options); + return new RepeatedPrimitiveFieldGenerator(descriptor, presenceIndex, options); } else { - if (descriptor->containing_oneof()) { - return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options); + if (descriptor->real_containing_oneof()) { + return new PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options); } else { - return new PrimitiveFieldGenerator(descriptor, fieldOrdinal, options); + return new PrimitiveFieldGenerator(descriptor, presenceIndex, options); } } } } +bool IsNullable(const FieldDescriptor* descriptor) { + if (descriptor->is_repeated()) { + return true; + } + + switch (descriptor->type()) { + case FieldDescriptor::TYPE_ENUM: + case FieldDescriptor::TYPE_DOUBLE: + case FieldDescriptor::TYPE_FLOAT: + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_FIXED64: + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_BOOL: + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_SFIXED32: + case FieldDescriptor::TYPE_SFIXED64: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_SINT64: + return false; + + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_BYTES: + return true; + + default: + GOOGLE_LOG(FATAL) << "Unknown field type."; + return true; + } +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h index c317ad0e5548f..a6009c8b1e4ec 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.h +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -36,12 +36,15 @@ #define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__ #include -#include +#include +#include #include #include #include #include +#include + namespace google { namespace protobuf { namespace compiler { @@ -73,6 +76,8 @@ std::string StripDotProto(const std::string& proto_file); // Gets unqualified name of the reflection class std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor); +// Gets unqualified name of the extension class +std::string GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor); std::string GetClassName(const EnumDescriptor* descriptor); @@ -96,7 +101,8 @@ std::string UnderscoresToPascalCase(const std::string& input); // Note that we wouldn't normally want to export this (we're not expecting // it to be used outside libprotoc itself) but this exposes it for testing. -std::string LIBPROTOBUF_EXPORT GetEnumValueName(const std::string& enum_name, const std::string& enum_value_name); +std::string PROTOC_EXPORT GetEnumValueName(const std::string& enum_name, + const std::string& enum_value_name); // TODO(jtattermusch): perhaps we could move this to strutil std::string StringToBase64(const std::string& input); @@ -104,15 +110,22 @@ std::string StringToBase64(const std::string& input); std::string FileDescriptorToBase64(const FileDescriptor* descriptor); FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options* options); +std::string GetFullExtensionName(const FieldDescriptor* descriptor); + +bool IsNullable(const FieldDescriptor* descriptor); + // Determines whether the given message is a map entry message, // i.e. one implicitly created by protoc due to a map field. inline bool IsMapEntryMessage(const Descriptor* descriptor) { return descriptor->options().map_entry(); } +// Checks if this descriptor is for a group and gets its end tag or 0 if it's not a group +uint GetGroupEndTag(const Descriptor* descriptor); + // Determines whether we're generating code for the proto representation of // descriptors etc, for use in the runtime. This is the only type which is // allowed to use proto2 syntax, and it generates internal classes. @@ -125,7 +138,7 @@ inline bool IsDescriptorOptionMessage(const Descriptor* descriptor) { if (!IsDescriptorProto(descriptor->file())) { return false; } - const string name = descriptor->full_name(); + const std::string name = descriptor->full_name(); return name == "google.protobuf.FileOptions" || name == "google.protobuf.MessageOptions" || name == "google.protobuf.FieldOptions" || @@ -141,8 +154,42 @@ inline bool IsWrapperType(const FieldDescriptor* descriptor) { descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto"; } +inline bool IsProto2(const FileDescriptor* descriptor) { + return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2; +} + +inline bool SupportsPresenceApi(const FieldDescriptor* descriptor) { + // Unlike most languages, we don't generate Has/Clear members for message + // types, because they can always be set to null in C#. They're not really + // needed for oneof fields in proto2 either, as everything can be done via + // oneof case, but we follow the convention from other languages. Proto3 + // oneof fields never have Has/Clear members - but will also never have + // the explicit optional keyword either. + // + // None of the built-in helpers (descriptor->has_presence() etc) describe + // quite the behavior we want, so the rules are explicit below. + + if (descriptor->is_repeated() || + descriptor->type() == FieldDescriptor::TYPE_MESSAGE) { + return false; + } + // has_optional_keyword() has more complex rules for proto2, but that + // doesn't matter given the first part of this condition. + return IsProto2(descriptor->file()) || descriptor->has_optional_keyword(); +} + +inline bool RequiresPresenceBit(const FieldDescriptor* descriptor) { + return SupportsPresenceApi(descriptor) && + !IsNullable(descriptor) && + !descriptor->is_extension() && + !descriptor->real_containing_oneof(); +} + } // namespace csharp } // namespace compiler } // namespace protobuf } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__ diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc index e6eac6edb2076..44c13e2f637ad 100644 --- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -48,24 +47,24 @@ namespace compiler { namespace csharp { MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options* options) - : FieldGeneratorBase(descriptor, fieldOrdinal, options) { + : FieldGeneratorBase(descriptor, presenceIndex, options) { } MapFieldGenerator::~MapFieldGenerator() { } -void MapFieldGenerator::GenerateMembers(io::Printer* printer) { +void MapFieldGenerator::GenerateMembers(io::Printer* printer) { const FieldDescriptor* key_descriptor = descriptor_->message_type()->FindFieldByName("key"); const FieldDescriptor* value_descriptor = descriptor_->message_type()->FindFieldByName("value"); variables_["key_type_name"] = type_name(key_descriptor); variables_["value_type_name"] = type_name(value_descriptor); - scoped_ptr key_generator( + std::unique_ptr key_generator( CreateFieldGenerator(key_descriptor, 1, this->options())); - scoped_ptr value_generator( + std::unique_ptr value_generator( CreateFieldGenerator(value_descriptor, 2, this->options())); printer->Print( @@ -95,15 +94,27 @@ void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) { } void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) { + GenerateParsingCode(printer, true); +} + +void MapFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) { printer->Print( variables_, - "$name$_.AddEntriesFrom(input, _map_$name$_codec);\n"); + use_parse_context + ? "$name$_.AddEntriesFrom(ref input, _map_$name$_codec);\n" + : "$name$_.AddEntriesFrom(input, _map_$name$_codec);\n"); } void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + GenerateSerializationCode(printer, true); +} + +void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) { printer->Print( variables_, - "$name$_.WriteTo(output, _map_$name$_codec);\n"); + use_write_context + ? "$name$_.WriteTo(ref output, _map_$name$_codec);\n" + : "$name$_.WriteTo(output, _map_$name$_codec);\n"); } void MapFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.h b/src/google/protobuf/compiler/csharp/csharp_map_field.h index 84a33a03675a0..54156ecf54083 100644 --- a/src/google/protobuf/compiler/csharp/csharp_map_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_map_field.h @@ -44,24 +44,26 @@ namespace csharp { class MapFieldGenerator : public FieldGeneratorBase { public: MapFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options* options); ~MapFieldGenerator(); + MapFieldGenerator(const MapFieldGenerator&) = delete; + MapFieldGenerator& operator=(const MapFieldGenerator&) = delete; + virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context); virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context); virtual void GenerateSerializedSizeCode(io::Printer* printer); virtual void WriteHash(io::Printer* printer); virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator); }; } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 5ef0e4e860999..5aec7ca743e0c 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -33,7 +33,6 @@ #include #include -#include #include #include #include @@ -42,6 +41,7 @@ #include #include +#include #include #include #include @@ -49,8 +49,6 @@ #include #include -using google::protobuf::internal::scoped_ptr; - namespace google { namespace protobuf { namespace compiler { @@ -63,20 +61,27 @@ bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) { MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Options* options) : SourceGeneratorBase(descriptor->file(), options), - descriptor_(descriptor) { - - // sorted field names - for (int i = 0; i < descriptor_->field_count(); i++) { - field_names_.push_back(descriptor_->field(i)->name()); - } - std::sort(field_names_.begin(), field_names_.end()); - + descriptor_(descriptor), + has_bit_field_count_(0), + end_tag_(GetGroupEndTag(descriptor)), + has_extension_ranges_(descriptor->extension_range_count() > 0) { // fields by number for (int i = 0; i < descriptor_->field_count(); i++) { fields_by_number_.push_back(descriptor_->field(i)); } std::sort(fields_by_number_.begin(), fields_by_number_.end(), CompareFieldNumbers); + + int presence_bit_count = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (RequiresPresenceBit(field)) { + presence_bit_count++; + if (has_bit_field_count_ == 0 || (presence_bit_count % 32) == 0) { + has_bit_field_count_++; + } + } + } } MessageGenerator::~MessageGenerator() { @@ -90,10 +95,6 @@ std::string MessageGenerator::full_class_name() { return GetClassName(descriptor_); } -const std::vector& MessageGenerator::field_names() { - return field_names_; -} - const std::vector& MessageGenerator::fields_by_number() { return fields_by_number_; } @@ -104,59 +105,94 @@ void MessageGenerator::AddDeprecatedFlag(io::Printer* printer) { } } +void MessageGenerator::AddSerializableAttribute(io::Printer* printer) { + if (this->options()->serializable) { + printer->Print("[global::System.SerializableAttribute]\n"); + } +} + void MessageGenerator::Generate(io::Printer* printer) { - std::map vars; + std::map vars; vars["class_name"] = class_name(); vars["access_level"] = class_access_level(); WriteMessageDocComment(printer, descriptor_); AddDeprecatedFlag(printer); - + AddSerializableAttribute(printer); + printer->Print( vars, - "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n"); + "$access_level$ sealed partial class $class_name$ : "); + + if (has_extension_ranges_) { + printer->Print(vars, "pb::IExtendableMessage<$class_name$>\n"); + } + else { + printer->Print(vars, "pb::IMessage<$class_name$>\n"); + } + printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n"); + printer->Print(" , pb::IBufferMessage\n"); + printer->Print("#endif\n"); + printer->Print("{\n"); printer->Indent(); // All static fields and properties printer->Print( - vars, - "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n"); + vars, + "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n"); + + printer->Print( + "private pb::UnknownFieldSet _unknownFields;\n"); + + if (has_extension_ranges_) { + if (IsDescriptorProto(descriptor_->file())) { + printer->Print(vars, "internal pb::ExtensionSet<$class_name$> _extensions;\n"); // CustomOptions compatibility + } else { + printer->Print(vars, "private pb::ExtensionSet<$class_name$> _extensions;\n"); + } + + // a read-only property for fast + // retrieval of the set in IsInitialized + printer->Print(vars, + "private pb::ExtensionSet<$class_name$> _Extensions { get { " + "return _extensions; } }\n"); + } + + for (int i = 0; i < has_bit_field_count_; i++) { + // don't use arrays since all arrays are heap allocated, saving allocations + // use ints instead of bytes since bytes lack bitwise operators, saving casts + printer->Print("private int _hasBits$i$;\n", "i", StrCat(i)); + } WriteGeneratedCodeAttributes(printer); printer->Print( - vars, - "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n"); + vars, + "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n"); // Access the message descriptor via the relevant file descriptor or containing message descriptor. if (!descriptor_->containing_type()) { vars["descriptor_accessor"] = GetReflectionClassName(descriptor_->file()) - + ".Descriptor.MessageTypes[" + SimpleItoa(descriptor_->index()) + "]"; + + ".Descriptor.MessageTypes[" + StrCat(descriptor_->index()) + "]"; } else { vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type()) - + ".Descriptor.NestedTypes[" + SimpleItoa(descriptor_->index()) + "]"; + + ".Descriptor.NestedTypes[" + StrCat(descriptor_->index()) + "]"; } WriteGeneratedCodeAttributes(printer); printer->Print( - vars, - "public static pbr::MessageDescriptor Descriptor {\n" - " get { return $descriptor_accessor$; }\n" - "}\n" - "\n"); + vars, + "public static pbr::MessageDescriptor Descriptor {\n" + " get { return $descriptor_accessor$; }\n" + "}\n" + "\n"); WriteGeneratedCodeAttributes(printer); printer->Print( - vars, + vars, "pbr::MessageDescriptor pb::IMessage.Descriptor {\n" " get { return Descriptor; }\n" "}\n" "\n"); - // CustomOptions property, only for options messages - if (IsDescriptorOptionMessage(descriptor_)) { - printer->Print( - "internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty;\n" - "\n"); - } // Parameterless constructor and partial OnConstruction method. WriteGeneratedCodeAttributes(printer); @@ -180,18 +216,19 @@ void MessageGenerator::Generate(io::Printer* printer) { "public const int $field_constant_name$ = $index$;\n", "field_name", fieldDescriptor->name(), "field_constant_name", GetFieldConstantName(fieldDescriptor), - "index", SimpleItoa(fieldDescriptor->number())); - scoped_ptr generator( + "index", StrCat(fieldDescriptor->number())); + std::unique_ptr generator( CreateFieldGeneratorInternal(fieldDescriptor)); generator->GenerateMembers(printer); printer->Print("\n"); } - // oneof properties - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - vars["original_name"] = descriptor_->oneof_decl(i)->name(); + // oneof properties (for real oneofs, which come before synthetic ones) + for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + vars["name"] = UnderscoresToCamelCase(oneof->name(), false); + vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true); + vars["original_name"] = oneof->name(); printer->Print( vars, "private object $name$_;\n" @@ -199,28 +236,28 @@ void MessageGenerator::Generate(io::Printer* printer) { "public enum $property_name$OneofCase {\n"); printer->Indent(); printer->Print("None = 0,\n"); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + for (int j = 0; j < oneof->field_count(); j++) { + const FieldDescriptor* field = oneof->field(j); printer->Print("$field_property_name$ = $index$,\n", "field_property_name", GetPropertyName(field), - "index", SimpleItoa(field->number())); + "index", StrCat(field->number())); } printer->Outdent(); printer->Print("}\n"); // TODO: Should we put the oneof .proto comments here? // It's unclear exactly where they should go. - printer->Print( - vars, - "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n"); - WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, - "public $property_name$OneofCase $property_name$Case {\n" - " get { return $name$Case_; }\n" - "}\n\n"); - WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, + printer->Print( + vars, + "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print( + vars, + "public $property_name$OneofCase $property_name$Case {\n" + " get { return $name$Case_; }\n" + "}\n\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print( + vars, "public void Clear$property_name$() {\n" " $name$Case_ = $property_name$OneofCase.None;\n" " $name$_ = null;\n" @@ -232,6 +269,43 @@ void MessageGenerator::Generate(io::Printer* printer) { GenerateMessageSerializationMethods(printer); GenerateMergingMethods(printer); + if (has_extension_ranges_) { + printer->Print( + vars, + "public TValue GetExtension(pb::Extension<$class_name$, " + "TValue> extension) {\n" + " return pb::ExtensionSet.Get(ref _extensions, extension);\n" + "}\n" + "public pbc::RepeatedField " + "GetExtension(pb::RepeatedExtension<$class_name$, TValue> " + "extension) {\n" + " return pb::ExtensionSet.Get(ref _extensions, extension);\n" + "}\n" + "public pbc::RepeatedField " + "GetOrInitializeExtension(pb::RepeatedExtension<$class_name$, " + "TValue> extension) {\n" + " return pb::ExtensionSet.GetOrInitialize(ref _extensions, " + "extension);\n" + "}\n" + "public void SetExtension(pb::Extension<$class_name$, TValue> " + "extension, TValue value) {\n" + " pb::ExtensionSet.Set(ref _extensions, extension, value);\n" + "}\n" + "public bool HasExtension(pb::Extension<$class_name$, TValue> " + "extension) {\n" + " return pb::ExtensionSet.Has(ref _extensions, extension);\n" + "}\n" + "public void ClearExtension(pb::Extension<$class_name$, " + "TValue> extension) {\n" + " pb::ExtensionSet.Clear(ref _extensions, extension);\n" + "}\n" + "public void " + "ClearExtension(pb::RepeatedExtension<$class_name$, TValue> " + "extension) {\n" + " pb::ExtensionSet.Clear(ref _extensions, extension);\n" + "}\n\n"); + } + // Nested messages and enums if (HasNestedGeneratedTypes()) { printer->Print( @@ -259,6 +333,26 @@ void MessageGenerator::Generate(io::Printer* printer) { "\n"); } + if (descriptor_->extension_count() > 0) { + printer->Print( + vars, + "#region Extensions\n" + "/// Container for extensions for other messages declared in the $class_name$ message type.\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print("public static partial class Extensions {\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->extension_count(); i++) { + std::unique_ptr generator( + CreateFieldGeneratorInternal(descriptor_->extension(i))); + generator->GenerateExtensionCode(printer); + } + printer->Outdent(); + printer->Print( + "}\n" + "#endregion\n" + "\n"); + } + printer->Outdent(); printer->Print("}\n"); printer->Print("\n"); @@ -280,31 +374,35 @@ bool MessageGenerator::HasNestedGeneratedTypes() } void MessageGenerator::GenerateCloningCode(io::Printer* printer) { - std::map vars; + std::map vars; WriteGeneratedCodeAttributes(printer); vars["class_name"] = class_name(); printer->Print( vars, "public $class_name$($class_name$ other) : this() {\n"); printer->Indent(); - // Clone non-oneof fields first + for (int i = 0; i < has_bit_field_count_; i++) { + printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", StrCat(i)); + } + // Clone non-oneof fields first (treating optional proto3 fields as non-oneof) for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - scoped_ptr generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateCloningCode(printer); + const FieldDescriptor* field = descriptor_->field(i); + if (field->real_containing_oneof()) { + continue; } + std::unique_ptr generator(CreateFieldGeneratorInternal(field)); + generator->GenerateCloningCode(printer); } - // Clone just the right field for each oneof - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - vars["property_name"] = UnderscoresToCamelCase( - descriptor_->oneof_decl(i)->name(), true); + // Clone just the right field for each real oneof + for (int i = 0; i < descriptor_->real_oneof_decl_count(); ++i) { + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + vars["name"] = UnderscoresToCamelCase(oneof->name(), false); + vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true); printer->Print(vars, "switch (other.$property_name$Case) {\n"); printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - scoped_ptr generator(CreateFieldGeneratorInternal(field)); + for (int j = 0; j < oneof->field_count(); j++) { + const FieldDescriptor* field = oneof->field(j); + std::unique_ptr generator(CreateFieldGeneratorInternal(field)); vars["field_property_name"] = GetPropertyName(field); printer->Print( vars, @@ -317,6 +415,13 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) { printer->Outdent(); printer->Print("}\n\n"); } + // Clone unknown fields + printer->Print( + "_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);\n"); + if (has_extension_ranges_) { + printer->Print( + "_extensions = pb::ExtensionSet.Clone(other._extensions);\n"); + } printer->Outdent(); printer->Print("}\n\n"); @@ -333,19 +438,19 @@ void MessageGenerator::GenerateFreezingCode(io::Printer* printer) { } void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { - std::map vars; + std::map vars; vars["class_name"] = class_name(); // Equality - WriteGeneratedCodeAttributes(printer); + WriteGeneratedCodeAttributes(printer); printer->Print( vars, "public override bool Equals(object other) {\n" " return Equals(other as $class_name$);\n" "}\n\n"); - WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, + WriteGeneratedCodeAttributes(printer); + printer->Print( + vars, "public bool Equals($class_name$ other) {\n" " if (ReferenceEquals(other, null)) {\n" " return false;\n" @@ -355,41 +460,57 @@ void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { " }\n"); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - scoped_ptr generator( + std::unique_ptr generator( CreateFieldGeneratorInternal(descriptor_->field(i))); generator->WriteEquals(printer); } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n", - "property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { + printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n", + "property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + } + if (has_extension_ranges_) { + printer->Print( + "if (!Equals(_extensions, other._extensions)) {\n" + " return false;\n" + "}\n"); } printer->Outdent(); printer->Print( - " return true;\n" + " return Equals(_unknownFields, other._unknownFields);\n" "}\n\n"); // GetHashCode // Start with a non-zero value to easily distinguish between null and "empty" messages. - WriteGeneratedCodeAttributes(printer); - printer->Print( + WriteGeneratedCodeAttributes(printer); + printer->Print( "public override int GetHashCode() {\n" " int hash = 1;\n"); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - scoped_ptr generator( + std::unique_ptr generator( CreateFieldGeneratorInternal(descriptor_->field(i))); generator->WriteHash(printer); } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print("hash ^= (int) $name$Case_;\n", - "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false)); + for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { + printer->Print("hash ^= (int) $name$Case_;\n", + "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false)); } - printer->Print("return hash;\n"); + if (has_extension_ranges_) { + printer->Print( + "if (_extensions != null) {\n" + " hash ^= _extensions.GetHashCode();\n" + "}\n"); + } + printer->Print( + "if (_unknownFields != null) {\n" + " hash ^= _unknownFields.GetHashCode();\n" + "}\n" + "return hash;\n"); printer->Outdent(); printer->Print("}\n\n"); - WriteGeneratedCodeAttributes(printer); - printer->Print( + WriteGeneratedCodeAttributes(printer); + printer->Print( "public override string ToString() {\n" " return pb::JsonFormatter.ToDiagnosticString(this);\n" "}\n\n"); @@ -399,40 +520,92 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) WriteGeneratedCodeAttributes(printer); printer->Print( "public void WriteTo(pb::CodedOutputStream output) {\n"); + printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n"); printer->Indent(); + printer->Print("output.WriteRawMessage(this);\n"); + printer->Outdent(); + printer->Print("#else\n"); + printer->Indent(); + GenerateWriteToBody(printer, false); + printer->Outdent(); + printer->Print("#endif\n"); + printer->Print("}\n\n"); - // Serialize all the fields - for (int i = 0; i < fields_by_number().size(); i++) { - scoped_ptr generator( - CreateFieldGeneratorInternal(fields_by_number()[i])); - generator->GenerateSerializationCode(printer); - } - - // TODO(jonskeet): Memoize size of frozen messages? + printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print("void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {\n"); + printer->Indent(); + GenerateWriteToBody(printer, true); printer->Outdent(); - printer->Print( - "}\n" - "\n"); + printer->Print("}\n"); + printer->Print("#endif\n\n"); + WriteGeneratedCodeAttributes(printer); printer->Print( "public int CalculateSize() {\n"); printer->Indent(); printer->Print("int size = 0;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { - scoped_ptr generator( + std::unique_ptr generator( CreateFieldGeneratorInternal(descriptor_->field(i))); generator->GenerateSerializedSizeCode(printer); } + + if (has_extension_ranges_) { + printer->Print( + "if (_extensions != null) {\n" + " size += _extensions.CalculateSize();\n" + "}\n"); + } + + printer->Print( + "if (_unknownFields != null) {\n" + " size += _unknownFields.CalculateSize();\n" + "}\n"); + printer->Print("return size;\n"); printer->Outdent(); printer->Print("}\n\n"); } +void MessageGenerator::GenerateWriteToBody(io::Printer* printer, bool use_write_context) { + // Serialize all the fields + for (int i = 0; i < fields_by_number().size(); i++) { + std::unique_ptr generator( + CreateFieldGeneratorInternal(fields_by_number()[i])); + generator->GenerateSerializationCode(printer, use_write_context); + } + + if (has_extension_ranges_) { + // Serialize extensions + printer->Print( + use_write_context + ? "if (_extensions != null) {\n" + " _extensions.WriteTo(ref output);\n" + "}\n" + : "if (_extensions != null) {\n" + " _extensions.WriteTo(output);\n" + "}\n"); + } + + // Serialize unknown fields + printer->Print( + use_write_context + ? "if (_unknownFields != null) {\n" + " _unknownFields.WriteTo(ref output);\n" + "}\n" + : "if (_unknownFields != null) {\n" + " _unknownFields.WriteTo(output);\n" + "}\n"); + + // TODO(jonskeet): Memoize size of frozen messages? +} + void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { // Note: These are separate from GenerateMessageSerializationMethods() // because they need to be generated even for messages that are optimized // for code size. - std::map vars; + std::map vars; vars["class_name"] = class_name(); WriteGeneratedCodeAttributes(printer); @@ -444,53 +617,100 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { "if (other == null) {\n" " return;\n" "}\n"); - // Merge non-oneof fields + // Merge non-oneof fields, treating optional proto3 fields as normal fields for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - scoped_ptr generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateMergingCode(printer); + const FieldDescriptor* field = descriptor_->field(i); + if (field->real_containing_oneof()) { + continue; } + std::unique_ptr generator(CreateFieldGeneratorInternal(field)); + generator->GenerateMergingCode(printer); } - // Merge oneof fields - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + // Merge oneof fields (for non-synthetic oneofs) + for (int i = 0; i < descriptor_->real_oneof_decl_count(); ++i) { + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + vars["name"] = UnderscoresToCamelCase(oneof->name(), false); + vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true); printer->Print(vars, "switch (other.$property_name$Case) {\n"); printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + for (int j = 0; j < oneof->field_count(); j++) { + const FieldDescriptor* field = oneof->field(j); vars["field_property_name"] = GetPropertyName(field); printer->Print( vars, - "case $property_name$OneofCase.$field_property_name$:\n" - " $field_property_name$ = other.$field_property_name$;\n" - " break;\n"); + "case $property_name$OneofCase.$field_property_name$:\n"); + printer->Indent(); + std::unique_ptr generator(CreateFieldGeneratorInternal(field)); + generator->GenerateMergingCode(printer); + printer->Print("break;\n"); + printer->Outdent(); } printer->Outdent(); printer->Print("}\n\n"); } + // Merge extensions + if (has_extension_ranges_) { + printer->Print("pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions);\n"); + } + + // Merge unknown fields. + printer->Print( + "_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);\n"); + printer->Outdent(); printer->Print("}\n\n"); + WriteGeneratedCodeAttributes(printer); printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n"); + printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n"); printer->Indent(); + printer->Print("input.ReadRawMessage(this);\n"); + printer->Outdent(); + printer->Print("#else\n"); + printer->Indent(); + GenerateMainParseLoop(printer, false); + printer->Outdent(); + printer->Print("#endif\n"); + printer->Print("}\n\n"); + + printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print("void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {\n"); + printer->Indent(); + GenerateMainParseLoop(printer, true); + printer->Outdent(); + printer->Print("}\n"); // method + printer->Print("#endif\n\n"); + +} + +void MessageGenerator::GenerateMainParseLoop(io::Printer* printer, bool use_parse_context) { + std::map vars; + vars["maybe_ref_input"] = use_parse_context ? "ref input" : "input"; + printer->Print( "uint tag;\n" "while ((tag = input.ReadTag()) != 0) {\n" " switch(tag) {\n"); printer->Indent(); printer->Indent(); - // Option messages need to store unknown fields so that options can be parsed later. - if (IsDescriptorOptionMessage(descriptor_)) { - printer->Print( + if (end_tag_ != 0) { + printer->Print( + "case $end_tag$:\n" + " return;\n", + "end_tag", StrCat(end_tag_)); + } + if (has_extension_ranges_) { + printer->Print(vars, "default:\n" - " CustomOptions = CustomOptions.ReadOrSkipUnknownField(input);\n" + " if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, $maybe_ref_input$)) {\n" + " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, $maybe_ref_input$);\n" + " }\n" " break;\n"); } else { - printer->Print( + printer->Print(vars, "default:\n" - " input.SkipLastField();\n" // We're not storing the data, but we still need to consume it. + " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, $maybe_ref_input$);\n" " break;\n"); } for (int i = 0; i < fields_by_number().size(); i++) { @@ -507,17 +727,17 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { printer->Print( "case $packed_tag$:\n", "packed_tag", - SimpleItoa( + StrCat( internal::WireFormatLite::MakeTag( field->number(), internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED))); } - printer->Print("case $tag$: {\n", "tag", SimpleItoa(tag)); + printer->Print("case $tag$: {\n", "tag", StrCat(tag)); printer->Indent(); - scoped_ptr generator( + std::unique_ptr generator( CreateFieldGeneratorInternal(field)); - generator->GenerateParsingCode(printer); + generator->GenerateParsingCode(printer, use_parse_context); printer->Print("break;\n"); printer->Outdent(); printer->Print("}\n"); @@ -526,23 +746,31 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { printer->Print("}\n"); // switch printer->Outdent(); printer->Print("}\n"); // while - printer->Outdent(); - printer->Print("}\n\n"); // method } -int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) { - for (int i = 0; i < field_names().size(); i++) { - if (field_names()[i] == descriptor->name()) { - return i; +// it's a waste of space to track presence for all values, so we only track them if they're not nullable +int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) { + if (!RequiresPresenceBit(descriptor)) { + return -1; + } + + int index = 0; + for (int i = 0; i < fields_by_number().size(); i++) { + const FieldDescriptor* field = fields_by_number()[i]; + if (field == descriptor) { + return index; + } + if (RequiresPresenceBit(field)) { + index++; } } - GOOGLE_LOG(DFATAL)<< "Could not find ordinal for field " << descriptor->name(); + GOOGLE_LOG(DFATAL)<< "Could not find presence index for field " << descriptor->name(); return -1; } FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal( const FieldDescriptor* descriptor) { - return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor), this->options()); + return CreateFieldGenerator(descriptor, GetPresenceIndex(descriptor), this->options()); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h index e7f3b4d009fa1..d02767e44b48d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.h +++ b/src/google/protobuf/compiler/csharp/csharp_message.h @@ -50,6 +50,9 @@ class MessageGenerator : public SourceGeneratorBase { MessageGenerator(const Descriptor* descriptor, const Options* options); ~MessageGenerator(); + MessageGenerator(const MessageGenerator&) = delete; + MessageGenerator& operator=(const MessageGenerator&) = delete; + void GenerateCloningCode(io::Printer* printer); void GenerateFreezingCode(io::Printer* printer); void GenerateFrameworkMethods(io::Printer* printer); @@ -57,30 +60,30 @@ class MessageGenerator : public SourceGeneratorBase { private: const Descriptor* descriptor_; - std::vector field_names_; std::vector fields_by_number_; + int has_bit_field_count_; + uint end_tag_; + bool has_extension_ranges_; void GenerateMessageSerializationMethods(io::Printer* printer); + void GenerateWriteToBody(io::Printer* printer, bool use_write_context); void GenerateMergingMethods(io::Printer* printer); + void GenerateMainParseLoop(io::Printer* printer, bool use_parse_context); - int GetFieldOrdinal(const FieldDescriptor* descriptor); + int GetPresenceIndex(const FieldDescriptor* descriptor); FieldGeneratorBase* CreateFieldGeneratorInternal( const FieldDescriptor* descriptor); bool HasNestedGeneratedTypes(); void AddDeprecatedFlag(io::Printer* printer); - + void AddSerializableAttribute(io::Printer* printer); + std::string class_name(); std::string full_class_name(); - // field names sorted alphabetically - const std::vector& field_names(); - // field descriptors sorted by number const std::vector& fields_by_number(); - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); }; } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc index 438f310221ff4..034fbd924270d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -31,12 +31,13 @@ #include #include -#include #include #include #include #include #include +#include +#include #include #include @@ -49,11 +50,13 @@ namespace compiler { namespace csharp { MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options) - : FieldGeneratorBase(descriptor, fieldOrdinal, options) { - variables_["has_property_check"] = name() + "_ != null"; - variables_["has_not_property_check"] = name() + "_ == null"; + : FieldGeneratorBase(descriptor, presenceIndex, options) { + if (!SupportsPresenceApi(descriptor_)) { + variables_["has_property_check"] = name() + "_ != null"; + variables_["has_not_property_check"] = name() + "_ == null"; + } } MessageFieldGenerator::~MessageFieldGenerator() { @@ -74,6 +77,26 @@ void MessageFieldGenerator::GenerateMembers(io::Printer* printer) { " $name$_ = value;\n" " }\n" "}\n"); + if (SupportsPresenceApi(descriptor_)) { + printer->Print( + variables_, + "/// Gets whether the $descriptor_name$ field is set\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ bool Has$property_name$ {\n" + " get { return $name$_ != null; }\n" + "}\n"); + printer->Print( + variables_, + "/// Clears the value of the $descriptor_name$ field\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ void Clear$property_name$() {\n" + " $name$_ = null;\n" + "}\n"); + } } void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { @@ -81,7 +104,7 @@ void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { variables_, "if (other.$has_property_check$) {\n" " if ($has_not_property_check$) {\n" - " $name$_ = new $type_name$();\n" + " $property_name$ = new $type_name$();\n" " }\n" " $property_name$.MergeFrom(other.$property_name$);\n" "}\n"); @@ -91,27 +114,48 @@ void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, "if ($has_not_property_check$) {\n" - " $name$_ = new $type_name$();\n" - "}\n" - // TODO(jonskeet): Do we really need merging behaviour like this? - "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP... + " $property_name$ = new $type_name$();\n" + "}\n"); + if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) { + printer->Print(variables_, "input.ReadMessage($property_name$);\n"); + } else { + printer->Print(variables_, "input.ReadGroup($property_name$);\n"); + } } void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { - printer->Print( - variables_, - "if ($has_property_check$) {\n" - " output.WriteRawTag($tag_bytes$);\n" - " output.WriteMessage($property_name$);\n" - "}\n"); + if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " output.WriteRawTag($tag_bytes$);\n" + " output.WriteMessage($property_name$);\n" + "}\n"); + } else { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " output.WriteRawTag($tag_bytes$);\n" + " output.WriteGroup($property_name$);\n" + " output.WriteRawTag($end_tag_bytes$);\n" + "}\n"); + } } void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { - printer->Print( - variables_, - "if ($has_property_check$) {\n" - " size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n" - "}\n"); + if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n" + "}\n"); + } else { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += $tag_size$ + pb::CodedOutputStream.ComputeGroupSize($property_name$);\n" + "}\n"); + } } void MessageFieldGenerator::WriteHash(io::Printer* printer) { @@ -130,26 +174,41 @@ void MessageFieldGenerator::WriteToString(io::Printer* printer) { variables_, "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n"); } - +void MessageFieldGenerator::GenerateExtensionCode(io::Printer* printer) { + WritePropertyDocComment(printer, descriptor_); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n" + " new pb::Extension<$extended_type$, $type_name$>($number$, "); + GenerateCodecCode(printer); + printer->Print(");\n"); +} void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) { printer->Print(variables_, - "$property_name$ = other.$has_property_check$ ? other.$property_name$.Clone() : null;\n"); + "$name$_ = other.$has_property_check$ ? other.$name$_.Clone() : null;\n"); } void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) { } void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) { - printer->Print( - variables_, - "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)"); + if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) { + printer->Print( + variables_, + "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)"); + } else { + printer->Print( + variables_, + "pb::FieldCodec.ForGroup($tag$, $end_tag$, $type_name$.Parser)"); + } } MessageOneofFieldGenerator::MessageOneofFieldGenerator( const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options) - : MessageFieldGenerator(descriptor, fieldOrdinal, options) { + : MessageFieldGenerator(descriptor, presenceIndex, options) { SetCommonOneofFieldVariables(&variables_); } @@ -169,6 +228,36 @@ void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) { " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" " }\n" "}\n"); + if (SupportsPresenceApi(descriptor_)) { + printer->Print( + variables_, + "/// Gets whether the \"$descriptor_name$\" field is set\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ bool Has$property_name$ {\n" + " get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n" + "}\n"); + printer->Print( + variables_, + "/// Clears the value of the oneof if it's currently set to \"$descriptor_name$\" \n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ void Clear$property_name$() {\n" + " if ($has_property_check$) {\n" + " Clear$oneof_property_name$();\n" + " }\n" + "}\n"); + } +} + +void MessageOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print(variables_, + "if ($property_name$ == null) {\n" + " $property_name$ = new $type_name$();\n" + "}\n" + "$property_name$.MergeFrom(other.$property_name$);\n"); } void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { @@ -178,9 +267,13 @@ void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { "$type_name$ subBuilder = new $type_name$();\n" "if ($has_property_check$) {\n" " subBuilder.MergeFrom($property_name$);\n" - "}\n" - "input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP - "$property_name$ = subBuilder;\n"); + "}\n"); + if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) { + printer->Print("input.ReadMessage(subBuilder);\n"); + } else { + printer->Print("input.ReadGroup(subBuilder);\n"); + } + printer->Print(variables_, "$property_name$ = subBuilder;\n"); } void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h index 7d614756fa032..2463d912ba983 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h @@ -44,10 +44,13 @@ namespace csharp { class MessageFieldGenerator : public FieldGeneratorBase { public: MessageFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~MessageFieldGenerator(); + MessageFieldGenerator(const MessageFieldGenerator&) = delete; + MessageFieldGenerator& operator=(const MessageFieldGenerator&) = delete; + virtual void GenerateCodecCode(io::Printer* printer); virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateFreezingCode(io::Printer* printer); @@ -56,29 +59,29 @@ class MessageFieldGenerator : public FieldGeneratorBase { virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); + virtual void GenerateExtensionCode(io::Printer* printer); virtual void WriteHash(io::Printer* printer); virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); }; class MessageOneofFieldGenerator : public MessageFieldGenerator { public: MessageOneofFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~MessageOneofFieldGenerator(); + MessageOneofFieldGenerator(const MessageOneofFieldGenerator&) = delete; + MessageOneofFieldGenerator& operator=(const MessageOneofFieldGenerator&) = + delete; + virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); virtual void WriteToString(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator); }; } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_names.h b/src/google/protobuf/compiler/csharp/csharp_names.h index 21758f2882c74..67e53b6401082 100644 --- a/src/google/protobuf/compiler/csharp/csharp_names.h +++ b/src/google/protobuf/compiler/csharp/csharp_names.h @@ -39,7 +39,10 @@ #define GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ #include -#include +#include +#include + +#include namespace google { namespace protobuf { @@ -57,14 +60,14 @@ namespace csharp { // // Returns: // The namespace to use for given file descriptor. -string LIBPROTOC_EXPORT GetFileNamespace(const FileDescriptor* descriptor); +std::string PROTOC_EXPORT GetFileNamespace(const FileDescriptor* descriptor); // Requires: // descriptor != NULL // // Returns: // The fully-qualified C# class name. -string LIBPROTOC_EXPORT GetClassName(const Descriptor* descriptor); +std::string PROTOC_EXPORT GetClassName(const Descriptor* descriptor); // Requires: // descriptor != NULL @@ -73,7 +76,8 @@ string LIBPROTOC_EXPORT GetClassName(const Descriptor* descriptor); // The fully-qualified name of the C# class that provides // access to the file descriptor. Proto compiler generates // such class for each .proto file processed. -string LIBPROTOC_EXPORT GetReflectionClassName(const FileDescriptor* descriptor); +std::string PROTOC_EXPORT +GetReflectionClassName(const FileDescriptor* descriptor); // Generates output file name for given file descriptor. If generate_directories // is true, the output file will be put under directory corresponding to file's @@ -89,16 +93,17 @@ string LIBPROTOC_EXPORT GetReflectionClassName(const FileDescriptor* descriptor) // The file name to use as output file for given file descriptor. In case // of failure, this function will return empty string and error parameter // will contain the error message. -string LIBPROTOC_EXPORT GetOutputFile( - const google::protobuf::FileDescriptor* descriptor, - const string file_extension, - const bool generate_directories, - const string base_namespace, - string* error); +std::string PROTOC_EXPORT GetOutputFile(const FileDescriptor* descriptor, + const std::string file_extension, + const bool generate_directories, + const std::string base_namespace, + std::string* error); } // namespace csharp } // namespace compiler } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ diff --git a/src/google/protobuf/compiler/csharp/csharp_options.h b/src/google/protobuf/compiler/csharp/csharp_options.h index 426fb3b50f1ae..42ff6d8662775 100644 --- a/src/google/protobuf/compiler/csharp/csharp_options.h +++ b/src/google/protobuf/compiler/csharp/csharp_options.h @@ -33,7 +33,6 @@ #include -#include namespace google { namespace protobuf { namespace compiler { @@ -45,10 +44,11 @@ struct Options { file_extension(".cs"), base_namespace(""), base_namespace_specified(false), - internal_access(false) { + internal_access(false), + serializable(false) { } // Extension of the generated file. Defaults to ".cs" - string file_extension; + std::string file_extension; // Base namespace to use to create directory hierarchy. Defaults to "". // This option allows the simple creation of a conventional C# file layout, // where directories are created relative to a project-specific base @@ -59,7 +59,7 @@ struct Options { // // If no base namespace is specified, all files are generated in the // --csharp_out directory, with no subdirectories created automatically. - string base_namespace; + std::string base_namespace; // Whether the base namespace has been explicitly specified by the user. // This is required as the base namespace can be explicitly set to the empty // string, meaning "create a full directory hierarchy, starting from the first @@ -68,12 +68,14 @@ struct Options { // Whether the generated classes should have accessibility level of "internal". // Defaults to false that generates "public" classes. bool internal_access; + // Whether the generated classes should have a global::System.Serializable attribute added + // Defaults to false + bool serializable; }; } // namespace csharp } // namespace compiler } // namespace protobuf - - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_OPTIONS_H__ diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index 169122e6bea55..9df1dd6abd73e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -49,12 +48,12 @@ namespace compiler { namespace csharp { PrimitiveFieldGenerator::PrimitiveFieldGenerator( - const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) - : FieldGeneratorBase(descriptor, fieldOrdinal, options) { + const FieldDescriptor* descriptor, int presenceIndex, const Options *options) + : FieldGeneratorBase(descriptor, presenceIndex, options) { // TODO(jonskeet): Make this cleaner... is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING && descriptor->type() != FieldDescriptor::TYPE_BYTES; - if (!is_value_type) { + if (!is_value_type && !SupportsPresenceApi(descriptor_)) { variables_["has_property_check"] = variables_["property_name"] + ".Length != 0"; variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0"; } @@ -64,19 +63,70 @@ PrimitiveFieldGenerator::~PrimitiveFieldGenerator() { } void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { - // TODO(jonskeet): Work out whether we want to prevent the fields from ever being - // null, or whether we just handle it, in the cases of bytes and string. - // (Basically, should null-handling code be in the getter or the setter?) + + // Note: in multiple places, this code assumes that all fields + // that support presence are either nullable, or use a presence field bit. + // Fields which are oneof members are not generated here; they're generated in PrimitiveOneofFieldGenerator below. + // Extensions are not generated here either. + + + // Proto2 allows different default values to be specified. These are retained + // via static fields. They don't particularly need to be, but we don't need + // to change that. In Proto3 the default value we don't generate these + // fields, just using the literal instead. + if (IsProto2(descriptor_->file())) { + // Note: "private readonly static" isn't as idiomatic as + // "private static readonly", but changing this now would create a lot of + // churn in generated code with near-to-zero benefit. + printer->Print( + variables_, + "private readonly static $type_name$ $property_name$DefaultValue = $default_value$;\n\n"); + variables_["default_value_access"] = + variables_["property_name"] + "DefaultValue"; + } else { + variables_["default_value_access"] = variables_["default_value"]; + } + + // Declare the field itself. printer->Print( variables_, "private $type_name$ $name_def_message$;\n"); + WritePropertyDocComment(printer, descriptor_); AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "$access_level$ $type_name$ $property_name$ {\n" - " get { return $name$_; }\n" - " set {\n"); + + // Most of the work is done in the property: + // Declare the property itself (the same for all options) + printer->Print(variables_, "$access_level$ $type_name$ $property_name$ {\n"); + + // Specify the "getter", which may need to check for a presence field. + if (SupportsPresenceApi(descriptor_)) { + if (IsNullable(descriptor_)) { + printer->Print( + variables_, + " get { return $name$_ ?? $default_value_access$; }\n"); + } else { + printer->Print( + variables_, + // Note: it's possible that this could be rewritten as a + // conditional ?: expression, but there's no significant benefit + // to changing it. + " get { if ($has_field_check$) { return $name$_; } else { return $default_value_access$; } }\n"); + } + } else { + printer->Print( + variables_, + " get { return $name$_; }\n"); + } + + // Specify the "setter", which may need to set a field bit as well as the + // value. + printer->Print(" set {\n"); + if (presenceIndex_ != -1) { + printer->Print( + variables_, + " $set_has_field$;\n"); + } if (is_value_type) { printer->Print( variables_, @@ -89,6 +139,42 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { printer->Print( " }\n" "}\n"); + + // The "HasFoo" property, where required. + if (SupportsPresenceApi(descriptor_)) { + printer->Print(variables_, + "/// Gets whether the \"$descriptor_name$\" field is set\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ bool Has$property_name$ {\n" + " get { return "); + if (IsNullable(descriptor_)) { + printer->Print( + variables_, + "$name$_ != null; }\n}\n"); + } else { + printer->Print( + variables_, + "$has_field_check$; }\n}\n"); + } + } + + // The "ClearFoo" method, where required. + if (SupportsPresenceApi(descriptor_)) { + printer->Print(variables_, + "/// Clears the value of the \"$descriptor_name$\" field\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ void Clear$property_name$() {\n"); + if (IsNullable(descriptor_)) { + printer->Print(variables_, " $name$_ = null;\n"); + } else { + printer->Print(variables_, " $clear_has_field$;\n"); + } + printer->Print("}\n"); + } } void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { @@ -129,7 +215,7 @@ void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { } else { printer->Print( "size += $tag_size$ + $fixed_size$;\n", - "fixed_size", SimpleItoa(fixedSize), + "fixed_size", StrCat(fixedSize), "tag_size", variables_["tag_size"]); } printer->Outdent(); @@ -137,14 +223,22 @@ void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { } void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) { - printer->Print( - variables_, - "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); + const char *text = "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"; + if (descriptor_->type() == FieldDescriptor::TYPE_FLOAT) { + text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode($property_name$);\n"; + } else if (descriptor_->type() == FieldDescriptor::TYPE_DOUBLE) { + text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode($property_name$);\n"; + } + printer->Print(variables_, text); } void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { - printer->Print( - variables_, - "if ($property_name$ != other.$property_name$) return false;\n"); + const char *text = "if ($property_name$ != other.$property_name$) return false;\n"; + if (descriptor_->type() == FieldDescriptor::TYPE_FLOAT) { + text = "if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n"; + } else if (descriptor_->type() == FieldDescriptor::TYPE_DOUBLE) { + text = "if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n"; + } + printer->Print(variables_, text); } void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) { printer->Print( @@ -160,12 +254,23 @@ void PrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) { void PrimitiveFieldGenerator::GenerateCodecCode(io::Printer* printer) { printer->Print( variables_, - "pb::FieldCodec.For$capitalized_type_name$($tag$)"); + "pb::FieldCodec.For$capitalized_type_name$($tag$, $default_value$)"); +} + +void PrimitiveFieldGenerator::GenerateExtensionCode(io::Printer* printer) { + WritePropertyDocComment(printer, descriptor_); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n" + " new pb::Extension<$extended_type$, $type_name$>($number$, "); + GenerateCodecCode(printer); + printer->Print(");\n"); } PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator( - const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) - : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) { + const FieldDescriptor* descriptor, int presenceIndex, const Options *options) + : PrimitiveFieldGenerator(descriptor, presenceIndex, options) { SetCommonOneofFieldVariables(&variables_); } @@ -180,20 +285,46 @@ void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) { "$access_level$ $type_name$ $property_name$ {\n" " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" " set {\n"); - if (is_value_type) { - printer->Print( - variables_, - " $oneof_name$_ = value;\n"); - } else { - printer->Print( - variables_, - " $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n"); - } + if (is_value_type) { printer->Print( variables_, - " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " $oneof_name$_ = value;\n"); + } else { + printer->Print( + variables_, + " $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n"); + } + printer->Print( + variables_, + " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " }\n" + "}\n"); + if (SupportsPresenceApi(descriptor_)) { + printer->Print( + variables_, + "/// Gets whether the \"$descriptor_name$\" field is set\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ bool Has$property_name$ {\n" + " get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n" + "}\n"); + printer->Print( + variables_, + "/// Clears the value of the oneof if it's currently set to \"$descriptor_name$\" \n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ void Clear$property_name$() {\n" + " if ($has_property_check$) {\n" + " Clear$oneof_property_name$();\n" " }\n" "}\n"); + } +} + +void PrimitiveOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print(variables_, "$property_name$ = other.$property_name$;\n"); } void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h index 5f466fc47cc22..5edcc42b7ba4d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h @@ -46,10 +46,13 @@ struct Options; class PrimitiveFieldGenerator : public FieldGeneratorBase { public: PrimitiveFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~PrimitiveFieldGenerator(); + PrimitiveFieldGenerator(const PrimitiveFieldGenerator&) = delete; + PrimitiveFieldGenerator& operator=(const PrimitiveFieldGenerator&) = delete; + virtual void GenerateCodecCode(io::Printer* printer); virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); @@ -57,6 +60,7 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase { virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); + virtual void GenerateExtensionCode(io::Printer* printer); virtual void WriteHash(io::Printer* printer); virtual void WriteEquals(io::Printer* printer); @@ -64,25 +68,24 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase { protected: bool is_value_type; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); }; class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { public: PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~PrimitiveOneofFieldGenerator(); + PrimitiveOneofFieldGenerator(const PrimitiveOneofFieldGenerator&) = delete; + PrimitiveOneofFieldGenerator& operator=(const PrimitiveOneofFieldGenerator&) = + delete; + virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); virtual void WriteToString(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator); }; } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc index bac9aef7b84fa..37154e3ce82ed 100644 --- a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc +++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -41,6 +40,7 @@ #include #include +#include #include #include #include @@ -57,6 +57,7 @@ ReflectionClassGenerator::ReflectionClassGenerator(const FileDescriptor* file, file_(file) { namespace_ = GetFileNamespace(file); reflectionClassname_ = GetReflectionClassUnqualifiedName(file); + extensionClassname_ = GetExtensionClassUnqualifiedName(file); } ReflectionClassGenerator::~ReflectionClassGenerator() { @@ -70,6 +71,25 @@ void ReflectionClassGenerator::Generate(io::Printer* printer) { printer->Outdent(); printer->Print("}\n"); + if (file_->extension_count() > 0) { + printer->Print( + "/// Holder for extension identifiers generated from the top " + "level of $file_name$\n" + "$access_level$ static partial class $class_name$ {\n", + "access_level", class_access_level(), "class_name", extensionClassname_, + "file_name", file_->name()); + printer->Indent(); + for (int i = 0; i < file_->extension_count(); i++) { + std::unique_ptr generator( + CreateFieldGenerator(file_->extension(i), -1, this->options())); + generator->GenerateExtensionCode(printer); + } + printer->Outdent(); + printer->Print( + "}\n" + "\n"); + } + // write children: Enums if (file_->enum_type_count() > 0) { printer->Print("#region Enums\n"); @@ -104,8 +124,10 @@ void ReflectionClassGenerator::Generate(io::Printer* printer) { void ReflectionClassGenerator::WriteIntroduction(io::Printer* printer) { printer->Print( - "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "// source: $file_name$\n" + "// \n" + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $file_name$\n" + "// \n" "#pragma warning disable 1591, 0612, 3021\n" "#region Designer generated code\n" "\n" @@ -168,17 +190,10 @@ void ReflectionClassGenerator::WriteDescriptor(io::Printer* printer) { "descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,\n"); printer->Print(" new pbr::FileDescriptor[] { "); for (int i = 0; i < file_->dependency_count(); i++) { - // descriptor.proto is special: we don't allow access to the generated code, but there's - // a separately-exposed property to get at the file descriptor, specifically to allow this - // kind of dependency. - if (IsDescriptorProto(file_->dependency(i))) { - printer->Print("pbr::FileDescriptor.DescriptorProtoFileDescriptor, "); - } else { printer->Print( "$full_reflection_class_name$.Descriptor, ", "full_reflection_class_name", GetReflectionClassName(file_->dependency(i))); - } } printer->Print("},\n" " new pbr::GeneratedClrTypeInfo("); @@ -192,6 +207,16 @@ void ReflectionClassGenerator::WriteDescriptor(io::Printer* printer) { } else { printer->Print("null, "); + } + if (file_->extension_count() > 0) { + std::vector extensions; + for (int i = 0; i < file_->extension_count(); i++) { + extensions.push_back(GetFullExtensionName(file_->extension(i))); + } + printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", Join(extensions, ", ")); + } + else { + printer->Print("null, "); } if (file_->message_type_count() > 0) { printer->Print("new pbr::GeneratedClrTypeInfo[] {\n"); @@ -232,14 +257,15 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript } // Generated message type printer->Print("new pbr::GeneratedClrTypeInfo(typeof($type_name$), $type_name$.Parser, ", "type_name", GetClassName(descriptor)); - + // Fields if (descriptor->field_count() > 0) { std::vector fields; + fields.reserve(descriptor->field_count()); for (int i = 0; i < descriptor->field_count(); i++) { fields.push_back(GetPropertyName(descriptor->field(i))); } - printer->Print("new[]{ \"$fields$\" }, ", "fields", JoinStrings(fields, "\", \"")); + printer->Print("new[]{ \"$fields$\" }, ", "fields", Join(fields, "\", \"")); } else { printer->Print("null, "); @@ -248,10 +274,11 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript // Oneofs if (descriptor->oneof_decl_count() > 0) { std::vector oneofs; + oneofs.reserve(descriptor->oneof_decl_count()); for (int i = 0; i < descriptor->oneof_decl_count(); i++) { oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true)); } - printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", JoinStrings(oneofs, "\", \"")); + printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", Join(oneofs, "\", \"")); } else { printer->Print("null, "); @@ -260,18 +287,31 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript // Nested enums if (descriptor->enum_type_count() > 0) { std::vector enums; + enums.reserve(descriptor->enum_type_count()); for (int i = 0; i < descriptor->enum_type_count(); i++) { enums.push_back(GetClassName(descriptor->enum_type(i))); } - printer->Print("new[]{ typeof($enums$) }, ", "enums", JoinStrings(enums, "), typeof(")); + printer->Print("new[]{ typeof($enums$) }, ", "enums", Join(enums, "), typeof(")); } else { printer->Print("null, "); } + // Extensions + if (descriptor->extension_count() > 0) { + std::vector extensions; + for (int i = 0; i < descriptor->extension_count(); i++) { + extensions.push_back(GetFullExtensionName(descriptor->extension(i))); + } + printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", Join(extensions, ", ")); + } + else { + printer->Print("null, "); + } + // Nested types if (descriptor->nested_type_count() > 0) { - // Need to specify array type explicitly here, as all elements may be null. + // Need to specify array type explicitly here, as all elements may be null. printer->Print("new pbr::GeneratedClrTypeInfo[] { "); for (int i = 0; i < descriptor->nested_type_count(); i++) { WriteGeneratedCodeInfo(descriptor->nested_type(i), printer, i == descriptor->nested_type_count() - 1); diff --git a/src/google/protobuf/compiler/csharp/csharp_reflection_class.h b/src/google/protobuf/compiler/csharp/csharp_reflection_class.h index e0c69f31fb88b..9554727766864 100644 --- a/src/google/protobuf/compiler/csharp/csharp_reflection_class.h +++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.h @@ -35,6 +35,8 @@ #include #include +#include +#include namespace google { namespace protobuf { @@ -46,6 +48,9 @@ class ReflectionClassGenerator : public SourceGeneratorBase { ReflectionClassGenerator(const FileDescriptor* file, const Options* options); ~ReflectionClassGenerator(); + ReflectionClassGenerator(const ReflectionClassGenerator&) = delete; + ReflectionClassGenerator& operator=(const ReflectionClassGenerator&) = delete; + void Generate(io::Printer* printer); private: @@ -53,14 +58,13 @@ class ReflectionClassGenerator : public SourceGeneratorBase { std::string namespace_; std::string reflectionClassname_; + std::string extensionClassname_; void WriteIntroduction(io::Printer* printer); void WriteDescriptor(io::Printer* printer); void WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last); - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionClassGenerator); }; } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index 683c4b0b7af06..04bc7bbb1bd2a 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -48,8 +47,8 @@ namespace compiler { namespace csharp { RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( - const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) - : FieldGeneratorBase(descriptor, fieldOrdinal, options) { + const FieldDescriptor* descriptor, int presenceIndex, const Options *options) + : FieldGeneratorBase(descriptor, presenceIndex, options) { } RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() { @@ -79,18 +78,30 @@ void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) { } void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { + GenerateParsingCode(printer, true); +} + +void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) { printer->Print( variables_, - "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); + use_parse_context + ? "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n" + : "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); } void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + GenerateSerializationCode(printer, true); +} + +void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) { printer->Print( variables_, - "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); + use_write_context + ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n" + : "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); } -void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { +void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "size += $name$_.CalculateSize(_repeated_$name$_codec);\n"); @@ -118,6 +129,16 @@ void RepeatedEnumFieldGenerator::GenerateCloningCode(io::Printer* printer) { "$name$_ = other.$name$_.Clone();\n"); } +void RepeatedEnumFieldGenerator::GenerateExtensionCode(io::Printer* printer) { + WritePropertyDocComment(printer, descriptor_); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ static readonly pb::RepeatedExtension<$extended_type$, $type_name$> $property_name$ =\n" + " new pb::RepeatedExtension<$extended_type$, $type_name$>($number$, " + "pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x));\n"); +} + void RepeatedEnumFieldGenerator::GenerateFreezingCode(io::Printer* printer) { } diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h index 819b583262eaf..9b9ebd48facda 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h @@ -41,29 +41,33 @@ namespace protobuf { namespace compiler { namespace csharp { -// TODO(jonskeet): Refactor repeated field support; all the implementations are *really* similar. We -// should probably have a RepeatedFieldGeneratorBase. +// TODO(jonskeet): Refactor repeated field support; all the implementations are +// *really* similar. We should probably have a RepeatedFieldGeneratorBase. class RepeatedEnumFieldGenerator : public FieldGeneratorBase { public: RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~RepeatedEnumFieldGenerator(); + RepeatedEnumFieldGenerator(const RepeatedEnumFieldGenerator&) = delete; + RepeatedEnumFieldGenerator& operator=(const RepeatedEnumFieldGenerator&) = + delete; + virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context); virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context); virtual void GenerateSerializedSizeCode(io::Printer* printer); + virtual void GenerateExtensionCode(io::Printer* printer); virtual void WriteHash(io::Printer* printer); virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); }; } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 8fa0b0504f85e..8a93cd13cfca0 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -49,8 +48,8 @@ namespace compiler { namespace csharp { RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( - const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) - : FieldGeneratorBase(descriptor, fieldOrdinal, options) { + const FieldDescriptor* descriptor, int presenceIndex, const Options *options) + : FieldGeneratorBase(descriptor, presenceIndex, options) { } RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() { @@ -66,12 +65,12 @@ void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) { // "create single field generator for this repeated field" // function, but it doesn't seem worth it for just this. if (IsWrapperType(descriptor_)) { - scoped_ptr single_generator( - new WrapperFieldGenerator(descriptor_, fieldOrdinal_, this->options())); + std::unique_ptr single_generator( + new WrapperFieldGenerator(descriptor_, presenceIndex_, this->options())); single_generator->GenerateCodecCode(printer); } else { - scoped_ptr single_generator( - new MessageFieldGenerator(descriptor_, fieldOrdinal_, this->options())); + std::unique_ptr single_generator( + new MessageFieldGenerator(descriptor_, presenceIndex_, this->options())); single_generator->GenerateCodecCode(printer); } printer->Print(";\n"); @@ -94,15 +93,27 @@ void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { } void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { + GenerateParsingCode(printer, true); +} + +void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) { printer->Print( variables_, - "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); + use_parse_context + ? "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n" + : "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); } void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + GenerateSerializationCode(printer, true); +} + +void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) { printer->Print( variables_, - "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); + use_write_context + ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n" + : "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); } void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { @@ -138,6 +149,25 @@ void RepeatedMessageFieldGenerator::GenerateCloningCode(io::Printer* printer) { void RepeatedMessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) { } +void RepeatedMessageFieldGenerator::GenerateExtensionCode(io::Printer* printer) { + WritePropertyDocComment(printer, descriptor_); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ static readonly pb::RepeatedExtension<$extended_type$, $type_name$> $property_name$ =\n" + " new pb::RepeatedExtension<$extended_type$, $type_name$>($number$, "); + if (IsWrapperType(descriptor_)) { + std::unique_ptr single_generator( + new WrapperFieldGenerator(descriptor_, -1, this->options())); + single_generator->GenerateCodecCode(printer); + } else { + std::unique_ptr single_generator( + new MessageFieldGenerator(descriptor_, -1, this->options())); + single_generator->GenerateCodecCode(printer); + } + printer->Print(");\n"); +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h index 6e33648b6c990..90441b82ef329 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h @@ -46,24 +46,28 @@ struct Options; class RepeatedMessageFieldGenerator : public FieldGeneratorBase { public: RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~RepeatedMessageFieldGenerator(); + RepeatedMessageFieldGenerator(const RepeatedMessageFieldGenerator&) = delete; + RepeatedMessageFieldGenerator& operator=( + const RepeatedMessageFieldGenerator&) = delete; + virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context); virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context); virtual void GenerateSerializedSizeCode(io::Printer* printer); + virtual void GenerateExtensionCode(io::Printer* printer); virtual void WriteHash(io::Printer* printer); virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); }; } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index cd91506ff190e..0eacf91ce6cad 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -48,8 +47,8 @@ namespace compiler { namespace csharp { RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( - const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) - : FieldGeneratorBase(descriptor, fieldOrdinal, options) { + const FieldDescriptor* descriptor, int presenceIndex, const Options *options) + : FieldGeneratorBase(descriptor, presenceIndex, options) { } RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() { @@ -79,15 +78,27 @@ void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) } void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { + GenerateParsingCode(printer, true); +} + +void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) { printer->Print( variables_, - "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); + use_parse_context + ? "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n" + : "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); } void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + GenerateSerializationCode(printer, true); +} + +void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) { printer->Print( variables_, - "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); + use_write_context + ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n" + : "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); } void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { @@ -119,6 +130,15 @@ void RepeatedPrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) void RepeatedPrimitiveFieldGenerator::GenerateFreezingCode(io::Printer* printer) { } +void RepeatedPrimitiveFieldGenerator::GenerateExtensionCode(io::Printer* printer) { + WritePropertyDocComment(printer, descriptor_); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ static readonly pb::RepeatedExtension<$extended_type$, $type_name$> $property_name$ =\n" + " new pb::RepeatedExtension<$extended_type$, $type_name$>($number$, pb::FieldCodec.For$capitalized_type_name$($tag$));\n"); +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h index a59348a95f52d..23e77a9a2eaa3 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h @@ -43,23 +43,27 @@ namespace csharp { class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase { public: - RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options); + RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int presenceIndex, const Options* options); ~RepeatedPrimitiveFieldGenerator(); + RepeatedPrimitiveFieldGenerator(const RepeatedPrimitiveFieldGenerator&) = delete; + RepeatedPrimitiveFieldGenerator& operator=(const RepeatedPrimitiveFieldGenerator&) = delete; + virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context); virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context); virtual void GenerateSerializedSizeCode(io::Printer* printer); + virtual void GenerateExtensionCode(io::Printer* printer); virtual void WriteHash(io::Printer* printer); virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); }; } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc index 1fda7ddf31b52..ee7502fb04814 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -60,7 +59,7 @@ void SourceGeneratorBase::WriteGeneratedCodeAttributes(io::Printer* printer) { } std::string SourceGeneratorBase::class_access_level() { - return (IsDescriptorProto(descriptor_) || this->options()->internal_access) ? "internal" : "public"; + return this->options()->internal_access ? "internal" : "public"; } const Options* SourceGeneratorBase::options() { diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h index c741080ed885b..695c4225d3e86 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h @@ -34,6 +34,7 @@ #include #include +#include namespace google { namespace protobuf { @@ -47,6 +48,9 @@ class SourceGeneratorBase { SourceGeneratorBase(const FileDescriptor* descriptor, const Options* options); virtual ~SourceGeneratorBase(); + SourceGeneratorBase(const SourceGeneratorBase&) = delete; + SourceGeneratorBase& operator=(const SourceGeneratorBase&) = delete; + std::string class_access_level(); const Options* options(); @@ -57,8 +61,6 @@ class SourceGeneratorBase { private: const FileDescriptor* descriptor_; const Options *options_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceGeneratorBase); }; } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc index 797d498ed3714..578f54ba697e1 100644 --- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -48,8 +47,8 @@ namespace compiler { namespace csharp { WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, const Options *options) - : FieldGeneratorBase(descriptor, fieldOrdinal, options) { + int presenceIndex, const Options *options) + : FieldGeneratorBase(descriptor, presenceIndex, options) { variables_["has_property_check"] = name() + "_ != null"; variables_["has_not_property_check"] = name() + "_ == null"; const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); @@ -81,7 +80,27 @@ void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) { " set {\n" " $name$_ = value;\n" " }\n" - "}\n"); + "}\n\n"); + if (SupportsPresenceApi(descriptor_)) { + printer->Print( + variables_, + "/// Gets whether the $descriptor_name$ field is set\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ bool Has$property_name$ {\n" + " get { return $name$_ != null; }\n" + "}\n\n"); + printer->Print( + variables_, + "/// Clears the value of the $descriptor_name$ field\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ void Clear$property_name$() {\n" + " $name$_ = null;\n" + "}\n"); + } } void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) { @@ -95,20 +114,37 @@ void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) { } void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer) { + GenerateParsingCode(printer, true); +} + +void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) { printer->Print( variables_, - "$type_name$ value = _single_$name$_codec.Read(input);\n" - "if ($has_not_property_check$ || value != $default_value$) {\n" - " $property_name$ = value;\n" - "}\n"); + use_parse_context + ? "$type_name$ value = _single_$name$_codec.Read(ref input);\n" + "if ($has_not_property_check$ || value != $default_value$) {\n" + " $property_name$ = value;\n" + "}\n" + : "$type_name$ value = _single_$name$_codec.Read(input);\n" + "if ($has_not_property_check$ || value != $default_value$) {\n" + " $property_name$ = value;\n" + "}\n"); } void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + GenerateSerializationCode(printer, true); +} + +void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) { printer->Print( variables_, - "if ($has_property_check$) {\n" - " _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n" - "}\n"); + use_write_context + ? "if ($has_property_check$) {\n" + " _single_$name$_codec.WriteTagAndValue(ref output, $property_name$);\n" + "}\n" + : "if ($has_property_check$) {\n" + " _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n" + "}\n"); } void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { @@ -120,15 +156,25 @@ void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { } void WrapperFieldGenerator::WriteHash(io::Printer* printer) { - printer->Print( - variables_, - "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); + const char *text = "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"; + if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_FLOAT) { + text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.GetHashCode($property_name$);\n"; + } + else if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_DOUBLE) { + text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode($property_name$);\n"; + } + printer->Print(variables_, text); } void WrapperFieldGenerator::WriteEquals(io::Printer* printer) { - printer->Print( - variables_, - "if ($property_name$ != other.$property_name$) return false;\n"); + const char *text = "if ($property_name$ != other.$property_name$) return false;\n"; + if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_FLOAT) { + text = "if (!pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n"; + } + else if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_DOUBLE) { + text = "if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n"; + } + printer->Print(variables_, text); } void WrapperFieldGenerator::WriteToString(io::Printer* printer) { @@ -152,9 +198,20 @@ void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) { } } +void WrapperFieldGenerator::GenerateExtensionCode(io::Printer* printer) { + WritePropertyDocComment(printer, descriptor_); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n" + " new pb::Extension<$extended_type$, $type_name$>($number$, "); + GenerateCodecCode(printer); + printer->Print(");\n"); +} + WrapperOneofFieldGenerator::WrapperOneofFieldGenerator( - const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) - : WrapperFieldGenerator(descriptor, fieldOrdinal, options) { + const FieldDescriptor* descriptor, int presenceIndex, const Options *options) + : WrapperFieldGenerator(descriptor, presenceIndex, options) { SetCommonOneofFieldVariables(&variables_); } @@ -179,21 +236,61 @@ void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) { " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" " }\n" "}\n"); + if (SupportsPresenceApi(descriptor_)) { + printer->Print( + variables_, + "/// Gets whether the \"$descriptor_name$\" field is set\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ bool Has$property_name$ {\n" + " get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n" + "}\n"); + printer->Print( + variables_, + "/// Clears the value of the oneof if it's currently set to \"$descriptor_name$\" \n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ void Clear$property_name$() {\n" + " if ($has_property_check$) {\n" + " Clear$oneof_property_name$();\n" + " }\n" + "}\n"); + } +} + +void WrapperOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print(variables_, "$property_name$ = other.$property_name$;\n"); } void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + GenerateParsingCode(printer, true); +} + +void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) { printer->Print( variables_, - "$property_name$ = _oneof_$name$_codec.Read(input);\n"); + use_parse_context + ? "$property_name$ = _oneof_$name$_codec.Read(ref input);\n" + : "$property_name$ = _oneof_$name$_codec.Read(input);\n"); } void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + GenerateSerializationCode(printer, true); +} + +void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) { // TODO: I suspect this is wrong... printer->Print( variables_, - "if ($has_property_check$) {\n" - " _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n" - "}\n"); + use_write_context + ? "if ($has_property_check$) {\n" + " _oneof_$name$_codec.WriteTagAndValue(ref output, ($type_name$) $oneof_name$_);\n" + "}\n" + : "if ($has_property_check$) {\n" + " _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n" + "}\n"); } void WrapperOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h index 250dfd25486d1..e9bd043f2276d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h @@ -46,17 +46,23 @@ struct Options; class WrapperFieldGenerator : public FieldGeneratorBase { public: WrapperFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~WrapperFieldGenerator(); + WrapperFieldGenerator(const WrapperFieldGenerator&) = delete; + WrapperFieldGenerator& operator=(const WrapperFieldGenerator&) = delete; + virtual void GenerateCodecCode(io::Printer* printer); virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context); virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context); virtual void GenerateSerializedSizeCode(io::Printer* printer); + virtual void GenerateExtensionCode(io::Printer* printer); virtual void WriteHash(io::Printer* printer); virtual void WriteEquals(io::Printer* printer); @@ -64,23 +70,25 @@ class WrapperFieldGenerator : public FieldGeneratorBase { private: bool is_value_type; // True for int32 etc; false for bytes and string - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WrapperFieldGenerator); }; class WrapperOneofFieldGenerator : public WrapperFieldGenerator { public: WrapperOneofFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~WrapperOneofFieldGenerator(); + WrapperOneofFieldGenerator(const WrapperOneofFieldGenerator&) = delete; + WrapperOneofFieldGenerator& operator=(const WrapperOneofFieldGenerator&) = delete; + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context); virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context); virtual void GenerateSerializedSizeCode(io::Printer* printer); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WrapperOneofFieldGenerator); }; } // namespace csharp diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc index 4c357aa0e6c0e..c629b2e22b7a4 100644 --- a/src/google/protobuf/compiler/importer.cc +++ b/src/google/protobuf/compiler/importer.cc @@ -32,55 +32,48 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. - #ifdef _MSC_VER #include #else #include #endif -#include -#include -#include #include +#include +#include +#include #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include - #include #include #include -#include #include +#include #ifdef _WIN32 #include #endif -#ifdef _MSC_VER -// DO NOT include , instead create functions in io_win32.{h,cc} and import -// them like we do below. -using google::protobuf::internal::win32::access; -using google::protobuf::internal::win32::open; -#endif - namespace google { namespace protobuf { namespace compiler { +#ifdef _WIN32 +// DO NOT include , instead create functions in io_win32.{h,cc} and import +// them like we do below. +using google::protobuf::io::win32::access; +using google::protobuf::io::win32::open; +#endif + // Returns true if the text looks like a Windows-style absolute path, starting // with a drive letter. Example: "C:\foo". TODO(kenton): Share this with // copy in command_line_interface.cc? -static bool IsWindowsAbsolutePath(const string& text) { +static bool IsWindowsAbsolutePath(const std::string& text) { #if defined(_WIN32) || defined(__CYGWIN__) - return text.size() >= 3 && text[1] == ':' && - isalpha(text[0]) && - (text[2] == '/' || text[2] == '\\') && - text.find_last_of(':') == 1; + return text.size() >= 3 && text[1] == ':' && isalpha(text[0]) && + (text[2] == '/' || text[2] == '\\') && text.find_last_of(':') == 1; #else return false; #endif @@ -95,17 +88,17 @@ MultiFileErrorCollector::~MultiFileErrorCollector() {} class SourceTreeDescriptorDatabase::SingleFileErrorCollector : public io::ErrorCollector { public: - SingleFileErrorCollector(const string& filename, + SingleFileErrorCollector(const std::string& filename, MultiFileErrorCollector* multi_file_error_collector) - : filename_(filename), - multi_file_error_collector_(multi_file_error_collector), - had_errors_(false) {} + : filename_(filename), + multi_file_error_collector_(multi_file_error_collector), + had_errors_(false) {} ~SingleFileErrorCollector() {} bool had_errors() { return had_errors_; } // implements ErrorCollector --------------------------------------- - void AddError(int line, int column, const string& message) { + void AddError(int line, int column, const std::string& message) override { if (multi_file_error_collector_ != NULL) { multi_file_error_collector_->AddError(filename_, line, column, message); } @@ -113,7 +106,7 @@ class SourceTreeDescriptorDatabase::SingleFileErrorCollector } private: - string filename_; + std::string filename_; MultiFileErrorCollector* multi_file_error_collector_; bool had_errors_; }; @@ -122,17 +115,30 @@ class SourceTreeDescriptorDatabase::SingleFileErrorCollector SourceTreeDescriptorDatabase::SourceTreeDescriptorDatabase( SourceTree* source_tree) - : source_tree_(source_tree), - error_collector_(NULL), - using_validation_error_collector_(false), - validation_error_collector_(this) {} + : source_tree_(source_tree), + fallback_database_(nullptr), + error_collector_(nullptr), + using_validation_error_collector_(false), + validation_error_collector_(this) {} + +SourceTreeDescriptorDatabase::SourceTreeDescriptorDatabase( + SourceTree* source_tree, DescriptorDatabase* fallback_database) + : source_tree_(source_tree), + fallback_database_(fallback_database), + error_collector_(nullptr), + using_validation_error_collector_(false), + validation_error_collector_(this) {} SourceTreeDescriptorDatabase::~SourceTreeDescriptorDatabase() {} -bool SourceTreeDescriptorDatabase::FindFileByName( - const string& filename, FileDescriptorProto* output) { - google::protobuf::scoped_ptr input(source_tree_->Open(filename)); +bool SourceTreeDescriptorDatabase::FindFileByName(const std::string& filename, + FileDescriptorProto* output) { + std::unique_ptr input(source_tree_->Open(filename)); if (input == NULL) { + if (fallback_database_ != nullptr && + fallback_database_->FindFileByName(filename, output)) { + return true; + } if (error_collector_ != NULL) { error_collector_->AddError(filename, -1, 0, source_tree_->GetLastErrorMessage()); @@ -154,17 +160,16 @@ bool SourceTreeDescriptorDatabase::FindFileByName( // Parse it. output->set_name(filename); - return parser.Parse(&tokenizer, output) && - !file_error_collector.had_errors(); + return parser.Parse(&tokenizer, output) && !file_error_collector.had_errors(); } bool SourceTreeDescriptorDatabase::FindFileContainingSymbol( - const string& symbol_name, FileDescriptorProto* output) { + const std::string& symbol_name, FileDescriptorProto* output) { return false; } bool SourceTreeDescriptorDatabase::FindFileContainingExtension( - const string& containing_type, int field_number, + const std::string& containing_type, int field_number, FileDescriptorProto* output) { return false; } @@ -172,35 +177,41 @@ bool SourceTreeDescriptorDatabase::FindFileContainingExtension( // ------------------------------------------------------------------- SourceTreeDescriptorDatabase::ValidationErrorCollector:: -ValidationErrorCollector(SourceTreeDescriptorDatabase* owner) - : owner_(owner) {} + ValidationErrorCollector(SourceTreeDescriptorDatabase* owner) + : owner_(owner) {} SourceTreeDescriptorDatabase::ValidationErrorCollector:: -~ValidationErrorCollector() {} + ~ValidationErrorCollector() {} void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddError( - const string& filename, - const string& element_name, - const Message* descriptor, - ErrorLocation location, - const string& message) { + const std::string& filename, const std::string& element_name, + const Message* descriptor, ErrorLocation location, + const std::string& message) { if (owner_->error_collector_ == NULL) return; int line, column; - owner_->source_locations_.Find(descriptor, location, &line, &column); + if (location == DescriptorPool::ErrorCollector::IMPORT) { + owner_->source_locations_.FindImport(descriptor, element_name, &line, + &column); + } else { + owner_->source_locations_.Find(descriptor, location, &line, &column); + } owner_->error_collector_->AddError(filename, line, column, message); } void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddWarning( - const string& filename, - const string& element_name, - const Message* descriptor, - ErrorLocation location, - const string& message) { + const std::string& filename, const std::string& element_name, + const Message* descriptor, ErrorLocation location, + const std::string& message) { if (owner_->error_collector_ == NULL) return; int line, column; - owner_->source_locations_.Find(descriptor, location, &line, &column); + if (location == DescriptorPool::ErrorCollector::IMPORT) { + owner_->source_locations_.FindImport(descriptor, element_name, &line, + &column); + } else { + owner_->source_locations_.Find(descriptor, location, &line, &column); + } owner_->error_collector_->AddWarning(filename, line, column, message); } @@ -208,20 +219,21 @@ void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddWarning( Importer::Importer(SourceTree* source_tree, MultiFileErrorCollector* error_collector) - : database_(source_tree), - pool_(&database_, database_.GetValidationErrorCollector()) { + : database_(source_tree), + pool_(&database_, database_.GetValidationErrorCollector()) { pool_.EnforceWeakDependencies(true); database_.RecordErrorsTo(error_collector); } Importer::~Importer() {} -const FileDescriptor* Importer::Import(const string& filename) { +const FileDescriptor* Importer::Import(const std::string& filename) { return pool_.FindFileByName(filename); } -void Importer::AddUnusedImportTrackFile(const string& file_name) { - pool_.AddUnusedImportTrackFile(file_name); +void Importer::AddUnusedImportTrackFile(const std::string& file_name, + bool is_error) { + pool_.AddUnusedImportTrackFile(file_name, is_error); } void Importer::ClearUnusedImportTrackFiles() { @@ -233,15 +245,13 @@ void Importer::ClearUnusedImportTrackFiles() { SourceTree::~SourceTree() {} -string SourceTree::GetLastErrorMessage() { - return "File not found."; -} +std::string SourceTree::GetLastErrorMessage() { return "File not found."; } DiskSourceTree::DiskSourceTree() {} DiskSourceTree::~DiskSourceTree() {} -static inline char LastChar(const string& str) { +static inline char LastChar(const std::string& str) { return str[str.size() - 1]; } @@ -264,7 +274,7 @@ static inline char LastChar(const string& str) { // then if foo/bar is a symbolic link, foo/bar/baz.proto will canonicalize // to a path which does not appear to be under foo, and thus the compiler // will complain that baz.proto is not inside the --proto_path. -static string CanonicalizePath(string path) { +static std::string CanonicalizePath(std::string path) { #ifdef _WIN32 // The Win32 API accepts forward slashes as a path delimiter even though // backslashes are standard. Let's avoid confusion and use only forward @@ -277,8 +287,8 @@ static string CanonicalizePath(string path) { } #endif - std::vector canonical_parts; - std::vector parts = Split( + std::vector canonical_parts; + std::vector parts = Split( path, "/", true); // Note: Removes empty parts. for (int i = 0; i < parts.size(); i++) { if (parts[i] == ".") { @@ -287,22 +297,22 @@ static string CanonicalizePath(string path) { canonical_parts.push_back(parts[i]); } } - string result = Join(canonical_parts, "/"); + std::string result = Join(canonical_parts, "/"); if (!path.empty() && path[0] == '/') { // Restore leading slash. result = '/' + result; } - if (!path.empty() && LastChar(path) == '/' && - !result.empty() && LastChar(result) != '/') { + if (!path.empty() && LastChar(path) == '/' && !result.empty() && + LastChar(result) != '/') { // Restore trailing slash. result += '/'; } return result; } -static inline bool ContainsParentReference(const string& path) { +static inline bool ContainsParentReference(const std::string& path) { return path == ".." || HasPrefixString(path, "../") || - HasSuffixString(path, "/..") || path.find("/../") != string::npos; + HasSuffixString(path, "/..") || path.find("/../") != std::string::npos; } // Maps a file from an old location to a new one. Typically, old_prefix is @@ -322,10 +332,9 @@ static inline bool ContainsParentReference(const string& path) { // assert(!ApplyMapping("foo/bar", "baz", "qux", &result)); // assert(!ApplyMapping("foo/bar", "baz", "qux", &result)); // assert(!ApplyMapping("foobar", "foo", "baz", &result)); -static bool ApplyMapping(const string& filename, - const string& old_prefix, - const string& new_prefix, - string* result) { +static bool ApplyMapping(const std::string& filename, + const std::string& old_prefix, + const std::string& new_prefix, std::string* result) { if (old_prefix.empty()) { // old_prefix matches any relative path. if (ContainsParentReference(filename)) { @@ -361,7 +370,7 @@ static bool ApplyMapping(const string& filename, if (after_prefix_start != -1) { // Yep. So the prefixes are directories and the filename is a file // inside them. - string after_prefix = filename.substr(after_prefix_start); + std::string after_prefix = filename.substr(after_prefix_start); if (ContainsParentReference(after_prefix)) { // We do not allow the file name to use "..". return false; @@ -377,18 +386,17 @@ static bool ApplyMapping(const string& filename, return false; } -void DiskSourceTree::MapPath(const string& virtual_path, - const string& disk_path) { +void DiskSourceTree::MapPath(const std::string& virtual_path, + const std::string& disk_path) { mappings_.push_back(Mapping(virtual_path, CanonicalizePath(disk_path))); } DiskSourceTree::DiskFileToVirtualFileResult -DiskSourceTree::DiskFileToVirtualFile( - const string& disk_file, - string* virtual_file, - string* shadowing_disk_file) { +DiskSourceTree::DiskFileToVirtualFile(const std::string& disk_file, + std::string* virtual_file, + std::string* shadowing_disk_file) { int mapping_index = -1; - string canonical_disk_file = CanonicalizePath(disk_file); + std::string canonical_disk_file = CanonicalizePath(disk_file); for (int i = 0; i < mappings_.size(); i++) { // Apply the mapping in reverse. @@ -420,7 +428,7 @@ DiskSourceTree::DiskFileToVirtualFile( // Verify that we can open the file. Note that this also has the side-effect // of verifying that we are not canonicalizing away any non-existent // directories. - google::protobuf::scoped_ptr stream(OpenDiskFile(disk_file)); + std::unique_ptr stream(OpenDiskFile(disk_file)); if (stream == NULL) { return CANNOT_OPEN; } @@ -428,36 +436,36 @@ DiskSourceTree::DiskFileToVirtualFile( return SUCCESS; } -bool DiskSourceTree::VirtualFileToDiskFile(const string& virtual_file, - string* disk_file) { - google::protobuf::scoped_ptr stream( +bool DiskSourceTree::VirtualFileToDiskFile(const std::string& virtual_file, + std::string* disk_file) { + std::unique_ptr stream( OpenVirtualFile(virtual_file, disk_file)); return stream != NULL; } -io::ZeroCopyInputStream* DiskSourceTree::Open(const string& filename) { +io::ZeroCopyInputStream* DiskSourceTree::Open(const std::string& filename) { return OpenVirtualFile(filename, NULL); } -string DiskSourceTree::GetLastErrorMessage() { +std::string DiskSourceTree::GetLastErrorMessage() { return last_error_message_; } io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( - const string& virtual_file, - string* disk_file) { + const std::string& virtual_file, std::string* disk_file) { if (virtual_file != CanonicalizePath(virtual_file) || ContainsParentReference(virtual_file)) { // We do not allow importing of paths containing things like ".." or // consecutive slashes since the compiler expects files to be uniquely // identified by file name. - last_error_message_ = "Backslashes, consecutive slashes, \".\", or \"..\" " - "are not allowed in the virtual path"; + last_error_message_ = + "Backslashes, consecutive slashes, \".\", or \"..\" " + "are not allowed in the virtual path"; return NULL; } for (int i = 0; i < mappings_.size(); i++) { - string temp_disk_file; + std::string temp_disk_file; if (ApplyMapping(virtual_file, mappings_[i].virtual_path, mappings_[i].disk_path, &temp_disk_file)) { io::ZeroCopyInputStream* stream = OpenDiskFile(temp_disk_file); @@ -470,8 +478,8 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( if (errno == EACCES) { // The file exists but is not readable. - last_error_message_ = "Read access is denied for file: " + - temp_disk_file; + last_error_message_ = + "Read access is denied for file: " + temp_disk_file; return NULL; } } @@ -481,7 +489,23 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( } io::ZeroCopyInputStream* DiskSourceTree::OpenDiskFile( - const string& filename) { + const std::string& filename) { + struct stat sb; + int ret = 0; + do { + ret = stat(filename.c_str(), &sb); + } while (ret != 0 && errno == EINTR); +#if defined(_WIN32) + if (ret == 0 && sb.st_mode & S_IFDIR) { + last_error_message_ = "Input file is a directory."; + return NULL; + } +#else + if (ret == 0 && S_ISDIR(sb.st_mode)) { + last_error_message_ = "Input file is a directory."; + return NULL; + } +#endif int file_descriptor; do { file_descriptor = open(filename.c_str(), O_RDONLY); diff --git a/src/google/protobuf/compiler/importer.h b/src/google/protobuf/compiler/importer.h index a4ffcf87de32a..db4a876c5bb67 100644 --- a/src/google/protobuf/compiler/importer.h +++ b/src/google/protobuf/compiler/importer.h @@ -37,18 +37,22 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__ #define GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__ -#include -#include #include +#include #include +#include +#include #include #include -#include + +#include namespace google { namespace protobuf { -namespace io { class ZeroCopyInputStream; } +namespace io { +class ZeroCopyInputStream; +} namespace compiler { @@ -73,9 +77,14 @@ class DiskSourceTree; // // Note: This class does not implement FindFileContainingSymbol() or // FindFileContainingExtension(); these will always return false. -class LIBPROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabase { +class PROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabase { public: SourceTreeDescriptorDatabase(SourceTree* source_tree); + + // If non-NULL, fallback_database will be checked if a file doesn't exist in + // the specified source_tree. + SourceTreeDescriptorDatabase(SourceTree* source_tree, + DescriptorDatabase* fallback_database); ~SourceTreeDescriptorDatabase(); // Instructs the SourceTreeDescriptorDatabase to report any parse errors @@ -96,36 +105,36 @@ class LIBPROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabas } // implements DescriptorDatabase ----------------------------------- - bool FindFileByName(const string& filename, FileDescriptorProto* output); - bool FindFileContainingSymbol(const string& symbol_name, - FileDescriptorProto* output); - bool FindFileContainingExtension(const string& containing_type, + bool FindFileByName(const std::string& filename, + FileDescriptorProto* output) override; + bool FindFileContainingSymbol(const std::string& symbol_name, + FileDescriptorProto* output) override; + bool FindFileContainingExtension(const std::string& containing_type, int field_number, - FileDescriptorProto* output); + FileDescriptorProto* output) override; private: class SingleFileErrorCollector; SourceTree* source_tree_; + DescriptorDatabase* fallback_database_; MultiFileErrorCollector* error_collector_; - class LIBPROTOBUF_EXPORT ValidationErrorCollector : public DescriptorPool::ErrorCollector { + class PROTOBUF_EXPORT ValidationErrorCollector + : public DescriptorPool::ErrorCollector { public: ValidationErrorCollector(SourceTreeDescriptorDatabase* owner); ~ValidationErrorCollector(); // implements ErrorCollector --------------------------------------- - void AddError(const string& filename, - const string& element_name, - const Message* descriptor, - ErrorLocation location, - const string& message); - - virtual void AddWarning(const string& filename, - const string& element_name, - const Message* descriptor, - ErrorLocation location, - const string& message); + void AddError(const std::string& filename, const std::string& element_name, + const Message* descriptor, ErrorLocation location, + const std::string& message) override; + + void AddWarning(const std::string& filename, + const std::string& element_name, const Message* descriptor, + ErrorLocation location, + const std::string& message) override; private: SourceTreeDescriptorDatabase* owner_; @@ -145,10 +154,9 @@ class LIBPROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabas // You may find that SourceTreeDescriptorDatabase is more flexible. // // TODO(kenton): I feel like this class is not well-named. -class LIBPROTOBUF_EXPORT Importer { +class PROTOBUF_EXPORT Importer { public: - Importer(SourceTree* source_tree, - MultiFileErrorCollector* error_collector); + Importer(SourceTree* source_tree, MultiFileErrorCollector* error_collector); ~Importer(); // Import the given file and build a FileDescriptor representing it. If @@ -164,15 +172,14 @@ class LIBPROTOBUF_EXPORT Importer { // you want to see errors for the same files repeatedly, you can use a // separate Importer object to import each one (but use the same // DescriptorPool so that they can be cross-linked). - const FileDescriptor* Import(const string& filename); + const FileDescriptor* Import(const std::string& filename); // The DescriptorPool in which all imported FileDescriptors and their // contents are stored. - inline const DescriptorPool* pool() const { - return &pool_; - } + inline const DescriptorPool* pool() const { return &pool_; } - void AddUnusedImportTrackFile(const string& file_name); + void AddUnusedImportTrackFile(const std::string& file_name, + bool is_error = false); void ClearUnusedImportTrackFiles(); @@ -185,18 +192,18 @@ class LIBPROTOBUF_EXPORT Importer { // If the importer encounters problems while trying to import the proto files, // it reports them to a MultiFileErrorCollector. -class LIBPROTOBUF_EXPORT MultiFileErrorCollector { +class PROTOBUF_EXPORT MultiFileErrorCollector { public: inline MultiFileErrorCollector() {} virtual ~MultiFileErrorCollector(); // Line and column numbers are zero-based. A line number of -1 indicates // an error with the entire file (e.g. "not found"). - virtual void AddError(const string& filename, int line, int column, - const string& message) = 0; + virtual void AddError(const std::string& filename, int line, int column, + const std::string& message) = 0; - virtual void AddWarning(const string& filename, int line, int column, - const string& message) {} + virtual void AddWarning(const std::string& filename, int line, int column, + const std::string& message) {} private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultiFileErrorCollector); @@ -206,7 +213,7 @@ class LIBPROTOBUF_EXPORT MultiFileErrorCollector { // Used by the default implementation of Importer to resolve import statements // Most users will probably want to use the DiskSourceTree implementation, // below. -class LIBPROTOBUF_EXPORT SourceTree { +class PROTOBUF_EXPORT SourceTree { public: inline SourceTree() {} virtual ~SourceTree(); @@ -215,14 +222,14 @@ class LIBPROTOBUF_EXPORT SourceTree { // found. The caller takes ownership of the returned object. The filename // must be a path relative to the root of the source tree and must not // contain "." or ".." components. - virtual io::ZeroCopyInputStream* Open(const string& filename) = 0; + virtual io::ZeroCopyInputStream* Open(const std::string& filename) = 0; // If Open() returns NULL, calling this method immediately will return an // description of the error. // Subclasses should implement this method and return a meaningful value for // better error reporting. // TODO(xiaofeng): change this to a pure virtual function. - virtual string GetLastErrorMessage(); + virtual std::string GetLastErrorMessage(); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceTree); @@ -231,7 +238,7 @@ class LIBPROTOBUF_EXPORT SourceTree { // An implementation of SourceTree which loads files from locations on disk. // Multiple mappings can be set up to map locations in the DiskSourceTree to // locations in the physical filesystem. -class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree { +class PROTOBUF_EXPORT DiskSourceTree : public SourceTree { public: DiskSourceTree(); ~DiskSourceTree(); @@ -248,11 +255,11 @@ class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree { // and then you do: // Open("bar/qux"); // the DiskSourceTree will first try to open foo/bar/qux, then baz/bar/qux, - // returning the first one that opens successfuly. + // returning the first one that opens successfully. // // disk_path may be an absolute path or relative to the current directory, // just like a path you'd pass to open(). - void MapPath(const string& virtual_path, const string& disk_path); + void MapPath(const std::string& virtual_path, const std::string& disk_path); // Return type for DiskFileToVirtualFile(). enum DiskFileToVirtualFileResult { @@ -282,46 +289,48 @@ class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree { // it is not useful. // * NO_MAPPING: Indicates that no mapping was found which contains this // file. - DiskFileToVirtualFileResult - DiskFileToVirtualFile(const string& disk_file, - string* virtual_file, - string* shadowing_disk_file); + DiskFileToVirtualFileResult DiskFileToVirtualFile( + const std::string& disk_file, std::string* virtual_file, + std::string* shadowing_disk_file); // Given a virtual path, find the path to the file on disk. // Return true and update disk_file with the on-disk path if the file exists. // Return false and leave disk_file untouched if the file doesn't exist. - bool VirtualFileToDiskFile(const string& virtual_file, string* disk_file); + bool VirtualFileToDiskFile(const std::string& virtual_file, + std::string* disk_file); // implements SourceTree ------------------------------------------- - virtual io::ZeroCopyInputStream* Open(const string& filename); + io::ZeroCopyInputStream* Open(const std::string& filename) override; - virtual string GetLastErrorMessage(); + std::string GetLastErrorMessage() override; private: struct Mapping { - string virtual_path; - string disk_path; + std::string virtual_path; + std::string disk_path; - inline Mapping(const string& virtual_path_param, - const string& disk_path_param) - : virtual_path(virtual_path_param), disk_path(disk_path_param) {} + inline Mapping(const std::string& virtual_path_param, + const std::string& disk_path_param) + : virtual_path(virtual_path_param), disk_path(disk_path_param) {} }; std::vector mappings_; - string last_error_message_; + std::string last_error_message_; // Like Open(), but returns the on-disk path in disk_file if disk_file is // non-NULL and the file could be successfully opened. - io::ZeroCopyInputStream* OpenVirtualFile(const string& virtual_file, - string* disk_file); + io::ZeroCopyInputStream* OpenVirtualFile(const std::string& virtual_file, + std::string* disk_file); // Like Open() but given the actual on-disk path. - io::ZeroCopyInputStream* OpenDiskFile(const string& filename); + io::ZeroCopyInputStream* OpenDiskFile(const std::string& filename); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DiskSourceTree); }; } // namespace compiler } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__ diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc index a96ac8533935f..daa197f460659 100644 --- a/src/google/protobuf/compiler/importer_unittest.cc +++ b/src/google/protobuf/compiler/importer_unittest.cc @@ -34,11 +34,8 @@ #include -#include #include -#ifndef _SHARED_PTR_H -#include -#endif +#include #include #include @@ -47,9 +44,9 @@ #include #include #include -#include #include #include +#include #include #include @@ -59,7 +56,7 @@ namespace compiler { namespace { -bool FileExists(const string& path) { +bool FileExists(const std::string& path) { return File::Exists(path); } @@ -71,20 +68,20 @@ class MockErrorCollector : public MultiFileErrorCollector { MockErrorCollector() {} ~MockErrorCollector() {} - string text_; - string warning_text_; + std::string text_; + std::string warning_text_; // implements ErrorCollector --------------------------------------- - void AddError(const string& filename, int line, int column, - const string& message) { - strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", - filename, line, column, message); + void AddError(const std::string& filename, int line, int column, + const std::string& message) { + strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column, + message); } - void AddWarning(const string& filename, int line, int column, - const string& message) { - strings::SubstituteAndAppend(&warning_text_, "$0:$1:$2: $3\n", - filename, line, column, message); + void AddWarning(const std::string& filename, int line, int column, + const std::string& message) { + strings::SubstituteAndAppend(&warning_text_, "$0:$1:$2: $3\n", filename, line, + column, message); } }; @@ -96,12 +93,12 @@ class MockSourceTree : public SourceTree { MockSourceTree() {} ~MockSourceTree() {} - void AddFile(const string& name, const char* contents) { + void AddFile(const std::string& name, const char* contents) { files_[name] = contents; } // implements SourceTree ------------------------------------------- - io::ZeroCopyInputStream* Open(const string& filename) { + io::ZeroCopyInputStream* Open(const std::string& filename) { const char* contents = FindPtrOrNull(files_, filename); if (contents == NULL) { return NULL; @@ -110,28 +107,24 @@ class MockSourceTree : public SourceTree { } } - string GetLastErrorMessage() { - return "File not found."; - } + std::string GetLastErrorMessage() { return "File not found."; } private: - hash_map files_; + std::unordered_map files_; }; // =================================================================== class ImporterTest : public testing::Test { protected: - ImporterTest() - : importer_(&source_tree_, &error_collector_) {} + ImporterTest() : importer_(&source_tree_, &error_collector_) {} - void AddFile(const string& filename, const char* text) { + void AddFile(const std::string& filename, const char* text) { source_tree_.AddFile(filename, text); } // Return the collected error text - string error() const { return error_collector_.text_; } - string warning() const { return error_collector_.warning_text_; } + std::string warning() const { return error_collector_.warning_text_; } MockErrorCollector error_collector_; MockSourceTree source_tree_; @@ -141,8 +134,8 @@ class ImporterTest : public testing::Test { TEST_F(ImporterTest, Import) { // Test normal importing. AddFile("foo.proto", - "syntax = \"proto2\";\n" - "message Foo {}\n"); + "syntax = \"proto2\";\n" + "message Foo {}\n"); const FileDescriptor* file = importer_.Import("foo.proto"); EXPECT_EQ("", error_collector_.text_); @@ -158,14 +151,14 @@ TEST_F(ImporterTest, Import) { TEST_F(ImporterTest, ImportNested) { // Test that importing a file which imports another file works. AddFile("foo.proto", - "syntax = \"proto2\";\n" - "import \"bar.proto\";\n" - "message Foo {\n" - " optional Bar bar = 1;\n" - "}\n"); + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n" + "message Foo {\n" + " optional Bar bar = 1;\n" + "}\n"); AddFile("bar.proto", - "syntax = \"proto2\";\n" - "message Bar {}\n"); + "syntax = \"proto2\";\n" + "message Bar {}\n"); // Note that both files are actually parsed by the first call to Import() // here, since foo.proto imports bar.proto. The second call just returns @@ -195,42 +188,73 @@ TEST_F(ImporterTest, ImportNested) { TEST_F(ImporterTest, FileNotFound) { // Error: Parsing a file that doesn't exist. EXPECT_TRUE(importer_.Import("foo.proto") == NULL); - EXPECT_EQ( - "foo.proto:-1:0: File not found.\n", - error_collector_.text_); + EXPECT_EQ("foo.proto:-1:0: File not found.\n", error_collector_.text_); } TEST_F(ImporterTest, ImportNotFound) { // Error: Importing a file that doesn't exist. AddFile("foo.proto", - "syntax = \"proto2\";\n" - "import \"bar.proto\";\n"); + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n"); EXPECT_TRUE(importer_.Import("foo.proto") == NULL); EXPECT_EQ( - "bar.proto:-1:0: File not found.\n" - "foo.proto:-1:0: Import \"bar.proto\" was not found or had errors.\n", - error_collector_.text_); + "bar.proto:-1:0: File not found.\n" + "foo.proto:1:0: Import \"bar.proto\" was not found or had errors.\n", + error_collector_.text_); } TEST_F(ImporterTest, RecursiveImport) { // Error: Recursive import. AddFile("recursive1.proto", - "syntax = \"proto2\";\n" - "import \"recursive2.proto\";\n"); + "syntax = \"proto2\";\n" + "\n" + "import \"recursive2.proto\";\n"); AddFile("recursive2.proto", - "syntax = \"proto2\";\n" - "import \"recursive1.proto\";\n"); + "syntax = \"proto2\";\n" + "import \"recursive1.proto\";\n"); EXPECT_TRUE(importer_.Import("recursive1.proto") == NULL); EXPECT_EQ( - "recursive1.proto:-1:0: File recursively imports itself: recursive1.proto " + "recursive1.proto:2:0: File recursively imports itself: " + "recursive1.proto " "-> recursive2.proto -> recursive1.proto\n" - "recursive2.proto:-1:0: Import \"recursive1.proto\" was not found " + "recursive2.proto:1:0: Import \"recursive1.proto\" was not found " "or had errors.\n" - "recursive1.proto:-1:0: Import \"recursive2.proto\" was not found " + "recursive1.proto:2:0: Import \"recursive2.proto\" was not found " "or had errors.\n", - error_collector_.text_); + error_collector_.text_); +} + +TEST_F(ImporterTest, RecursiveImportSelf) { + // Error: Recursive import. + AddFile("recursive.proto", + "syntax = \"proto2\";\n" + "\n" + "import \"recursive.proto\";\n"); + + EXPECT_TRUE(importer_.Import("recursive.proto") == nullptr); + EXPECT_EQ( + "recursive.proto:2:0: File recursively imports itself: " + "recursive.proto -> recursive.proto\n", + error_collector_.text_); +} + +TEST_F(ImporterTest, LiteRuntimeImport) { + // Error: Recursive import. + AddFile("bar.proto", + "syntax = \"proto2\";\n" + "option optimize_for = LITE_RUNTIME;\n"); + AddFile("foo.proto", + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n"); + + EXPECT_TRUE(importer_.Import("foo.proto") == nullptr); + EXPECT_EQ( + "foo.proto:1:0: Files that do not use optimize_for = LITE_RUNTIME " + "cannot import files which do use this option. This file is not " + "lite, but it imports \"bar.proto\" which is.\n", + error_collector_.text_); } @@ -258,22 +282,22 @@ class DiskSourceTreeTest : public testing::Test { } } - void AddFile(const string& filename, const char* contents) { + void AddFile(const std::string& filename, const char* contents) { GOOGLE_CHECK_OK(File::SetContents(filename, contents, true)); } - void AddSubdir(const string& dirname) { + void AddSubdir(const std::string& dirname) { GOOGLE_CHECK_OK(File::CreateDir(dirname, 0777)); } - void ExpectFileContents(const string& filename, + void ExpectFileContents(const std::string& filename, const char* expected_contents) { - google::protobuf::scoped_ptr input(source_tree_.Open(filename)); + std::unique_ptr input(source_tree_.Open(filename)); ASSERT_FALSE(input == NULL); // Read all the data from the file. - string file_contents; + std::string file_contents; const void* data; int size; while (input->Next(&data, &size)) { @@ -283,9 +307,9 @@ class DiskSourceTreeTest : public testing::Test { EXPECT_EQ(expected_contents, file_contents); } - void ExpectCannotOpenFile(const string& filename, - const string& error_message) { - google::protobuf::scoped_ptr input(source_tree_.Open(filename)); + void ExpectCannotOpenFile(const std::string& filename, + const std::string& error_message) { + std::unique_ptr input(source_tree_.Open(filename)); EXPECT_TRUE(input == NULL); EXPECT_EQ(error_message, source_tree_.GetLastErrorMessage()); } @@ -293,7 +317,7 @@ class DiskSourceTreeTest : public testing::Test { DiskSourceTree source_tree_; // Paths of two on-disk directories to use during the test. - std::vector dirnames_; + std::vector dirnames_; }; TEST_F(DiskSourceTreeTest, MapRoot) { @@ -397,27 +421,27 @@ TEST_F(DiskSourceTreeTest, DiskFileToVirtualFile) { source_tree_.MapPath("bar", dirnames_[0]); source_tree_.MapPath("bar", dirnames_[1]); - string virtual_file; - string shadowing_disk_file; + std::string virtual_file; + std::string shadowing_disk_file; EXPECT_EQ(DiskSourceTree::NO_MAPPING, - source_tree_.DiskFileToVirtualFile( - "/foo", &virtual_file, &shadowing_disk_file)); + source_tree_.DiskFileToVirtualFile("/foo", &virtual_file, + &shadowing_disk_file)); EXPECT_EQ(DiskSourceTree::SHADOWED, - source_tree_.DiskFileToVirtualFile( - dirnames_[1] + "/foo", &virtual_file, &shadowing_disk_file)); + source_tree_.DiskFileToVirtualFile( + dirnames_[1] + "/foo", &virtual_file, &shadowing_disk_file)); EXPECT_EQ("bar/foo", virtual_file); EXPECT_EQ(dirnames_[0] + "/foo", shadowing_disk_file); EXPECT_EQ(DiskSourceTree::CANNOT_OPEN, - source_tree_.DiskFileToVirtualFile( - dirnames_[1] + "/baz", &virtual_file, &shadowing_disk_file)); + source_tree_.DiskFileToVirtualFile( + dirnames_[1] + "/baz", &virtual_file, &shadowing_disk_file)); EXPECT_EQ("bar/baz", virtual_file); EXPECT_EQ(DiskSourceTree::SUCCESS, - source_tree_.DiskFileToVirtualFile( - dirnames_[0] + "/foo", &virtual_file, &shadowing_disk_file)); + source_tree_.DiskFileToVirtualFile( + dirnames_[0] + "/foo", &virtual_file, &shadowing_disk_file)); EXPECT_EQ("bar/foo", virtual_file); } @@ -431,60 +455,61 @@ TEST_F(DiskSourceTreeTest, DiskFileToVirtualFileCanonicalization) { source_tree_.MapPath("", "/qux"); source_tree_.MapPath("dir5", "/quux/"); - string virtual_file; - string shadowing_disk_file; + std::string virtual_file; + std::string shadowing_disk_file; // "../.." should not be considered to be under "..". EXPECT_EQ(DiskSourceTree::NO_MAPPING, - source_tree_.DiskFileToVirtualFile( - "../../baz", &virtual_file, &shadowing_disk_file)); + source_tree_.DiskFileToVirtualFile("../../baz", &virtual_file, + &shadowing_disk_file)); - // "/foo" is not mapped (it should not be misintepreted as being under "."). + // "/foo" is not mapped (it should not be misinterpreted as being under "."). EXPECT_EQ(DiskSourceTree::NO_MAPPING, - source_tree_.DiskFileToVirtualFile( - "/foo", &virtual_file, &shadowing_disk_file)); + source_tree_.DiskFileToVirtualFile("/foo", &virtual_file, + &shadowing_disk_file)); #ifdef WIN32 - // "C:\foo" is not mapped (it should not be misintepreted as being under "."). + // "C:\foo" is not mapped (it should not be misinterpreted as being under + // "."). EXPECT_EQ(DiskSourceTree::NO_MAPPING, - source_tree_.DiskFileToVirtualFile( - "C:\\foo", &virtual_file, &shadowing_disk_file)); + source_tree_.DiskFileToVirtualFile("C:\\foo", &virtual_file, + &shadowing_disk_file)); #endif // WIN32 // But "../baz" should be. EXPECT_EQ(DiskSourceTree::CANNOT_OPEN, - source_tree_.DiskFileToVirtualFile( - "../baz", &virtual_file, &shadowing_disk_file)); + source_tree_.DiskFileToVirtualFile("../baz", &virtual_file, + &shadowing_disk_file)); EXPECT_EQ("dir1/baz", virtual_file); // "../../foo/baz" is under "../../foo". EXPECT_EQ(DiskSourceTree::CANNOT_OPEN, - source_tree_.DiskFileToVirtualFile( - "../../foo/baz", &virtual_file, &shadowing_disk_file)); + source_tree_.DiskFileToVirtualFile("../../foo/baz", &virtual_file, + &shadowing_disk_file)); EXPECT_EQ("dir2/baz", virtual_file); // "foo/./bar/baz" is under "./foo/bar/.". EXPECT_EQ(DiskSourceTree::CANNOT_OPEN, - source_tree_.DiskFileToVirtualFile( - "foo/bar/baz", &virtual_file, &shadowing_disk_file)); + source_tree_.DiskFileToVirtualFile("foo/bar/baz", &virtual_file, + &shadowing_disk_file)); EXPECT_EQ("dir3/baz", virtual_file); // "bar" is under ".". EXPECT_EQ(DiskSourceTree::CANNOT_OPEN, - source_tree_.DiskFileToVirtualFile( - "bar", &virtual_file, &shadowing_disk_file)); + source_tree_.DiskFileToVirtualFile("bar", &virtual_file, + &shadowing_disk_file)); EXPECT_EQ("dir4/bar", virtual_file); // "/qux/baz" is under "/qux". EXPECT_EQ(DiskSourceTree::CANNOT_OPEN, - source_tree_.DiskFileToVirtualFile( - "/qux/baz", &virtual_file, &shadowing_disk_file)); + source_tree_.DiskFileToVirtualFile("/qux/baz", &virtual_file, + &shadowing_disk_file)); EXPECT_EQ("baz", virtual_file); // "/quux/bar" is under "/quux". EXPECT_EQ(DiskSourceTree::CANNOT_OPEN, - source_tree_.DiskFileToVirtualFile( - "/quux/bar", &virtual_file, &shadowing_disk_file)); + source_tree_.DiskFileToVirtualFile("/quux/bar", &virtual_file, + &shadowing_disk_file)); EXPECT_EQ("dir5/bar", virtual_file); } @@ -498,14 +523,14 @@ TEST_F(DiskSourceTreeTest, VirtualFileToDiskFile) { source_tree_.MapPath("bar", dirnames_[1]); // Existent files, shadowed and non-shadowed case. - string disk_file; + std::string disk_file; EXPECT_TRUE(source_tree_.VirtualFileToDiskFile("bar/foo", &disk_file)); EXPECT_EQ(dirnames_[0] + "/foo", disk_file); EXPECT_TRUE(source_tree_.VirtualFileToDiskFile("bar/quux", &disk_file)); EXPECT_EQ(dirnames_[1] + "/quux", disk_file); // Nonexistent file in existent directory and vice versa. - string not_touched = "not touched"; + std::string not_touched = "not touched"; EXPECT_FALSE(source_tree_.VirtualFileToDiskFile("bar/baz", ¬_touched)); EXPECT_EQ("not touched", not_touched); EXPECT_FALSE(source_tree_.VirtualFileToDiskFile("baz/foo", ¬_touched)); diff --git a/src/google/protobuf/compiler/java/java_context.cc b/src/google/protobuf/compiler/java/java_context.cc index 0771d5e19c1ec..d74a7ed63dcfb 100644 --- a/src/google/protobuf/compiler/java/java_context.cc +++ b/src/google/protobuf/compiler/java/java_context.cc @@ -47,8 +47,7 @@ Context::Context(const FileDescriptor* file, const Options& options) InitializeFieldGeneratorInfo(file); } -Context::~Context() { -} +Context::~Context() {} ClassNameResolver* Context::GetNameResolver() const { return name_resolver_.get(); @@ -58,9 +57,9 @@ namespace { // Whether two fields have conflicting accessors (assuming name1 and name2 // are different). name1 and name2 are field1 and field2's camel-case name // respectively. -bool IsConflicting(const FieldDescriptor* field1, const string& name1, - const FieldDescriptor* field2, const string& name2, - string* info) { +bool IsConflicting(const FieldDescriptor* field1, const std::string& name1, + const FieldDescriptor* field2, const std::string& name2, + std::string* info) { if (field1->is_repeated()) { if (field2->is_repeated()) { // Both fields are repeated. @@ -69,14 +68,14 @@ bool IsConflicting(const FieldDescriptor* field1, const string& name1, // field1 is repeated, and field2 is not. if (name1 + "Count" == name2) { *info = "both repeated field \"" + field1->name() + "\" and singular " + - "field \"" + field2->name() + "\" generates the method \"" + - "get" + name1 + "Count()\""; + "field \"" + field2->name() + "\" generate the method \"" + + "get" + name1 + "Count()\""; return true; } if (name1 + "List" == name2) { *info = "both repeated field \"" + field1->name() + "\" and singular " + - "field \"" + field2->name() + "\" generates the method \"" + - "get" + name1 + "List()\""; + "field \"" + field2->name() + "\" generate the method \"" + + "get" + name1 + "List()\""; return true; } // Well, there are obviously many more conflicting cases, but it probably @@ -128,13 +127,13 @@ void Context::InitializeFieldGeneratorInfoForFields( // Find out all fields that conflict with some other field in the same // message. std::vector is_conflict(fields.size()); - std::vector conflict_reason(fields.size()); + std::vector conflict_reason(fields.size()); for (int i = 0; i < fields.size(); ++i) { const FieldDescriptor* field = fields[i]; - const string& name = UnderscoresToCapitalizedCamelCase(field); + const std::string& name = UnderscoresToCapitalizedCamelCase(field); for (int j = i + 1; j < fields.size(); ++j) { const FieldDescriptor* other = fields[j]; - const string& other_name = UnderscoresToCapitalizedCamelCase(other); + const std::string& other_name = UnderscoresToCapitalizedCamelCase(other); if (name == other_name) { is_conflict[i] = is_conflict[j] = true; conflict_reason[i] = conflict_reason[j] = @@ -159,8 +158,8 @@ void Context::InitializeFieldGeneratorInfoForFields( // For fields conflicting with some other fields, we append the field // number to their field names in generated code to avoid conflicts. if (is_conflict[i]) { - info.name += SimpleItoa(field->number()); - info.capitalized_name += SimpleItoa(field->number()); + info.name += StrCat(field->number()); + info.capitalized_name += StrCat(field->number()); info.disambiguated_reason = conflict_reason[i]; } field_generator_info_map_[field] = info; diff --git a/src/google/protobuf/compiler/java/java_context.h b/src/google/protobuf/compiler/java/java_context.h index 9a74c4303da20..3fa6af17789af 100644 --- a/src/google/protobuf/compiler/java/java_context.h +++ b/src/google/protobuf/compiler/java/java_context.h @@ -33,9 +33,6 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include @@ -43,18 +40,20 @@ namespace google { namespace protobuf { - class FileDescriptor; - class FieldDescriptor; - class OneofDescriptor; - class Descriptor; - class EnumDescriptor; - namespace compiler { - namespace java { - class ClassNameResolver; // name_resolver.h - } - } +class FileDescriptor; +class FieldDescriptor; +class OneofDescriptor; +class Descriptor; +class EnumDescriptor; +namespace compiler { +namespace java { +class ClassNameResolver; // name_resolver.h +} +} // namespace compiler } // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -97,7 +96,7 @@ class Context { void InitializeFieldGeneratorInfoForFields( const std::vector& fields); - google::protobuf::scoped_ptr name_resolver_; + std::unique_ptr name_resolver_; std::map field_generator_info_map_; std::map @@ -109,6 +108,6 @@ class Context { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__ diff --git a/src/google/protobuf/compiler/java/java_doc_comment.cc b/src/google/protobuf/compiler/java/java_doc_comment.cc index 59c04ad412763..2376488f02e33 100644 --- a/src/google/protobuf/compiler/java/java_doc_comment.cc +++ b/src/google/protobuf/compiler/java/java_doc_comment.cc @@ -44,13 +44,13 @@ namespace protobuf { namespace compiler { namespace java { -string EscapeJavadoc(const string& input) { - string result; +std::string EscapeJavadoc(const std::string& input) { + std::string result; result.reserve(input.size() * 2); char prev = '*'; - for (string::size_type i = 0; i < input.size(); i++) { + for (std::string::size_type i = 0; i < input.size(); i++) { char c = input[i]; switch (c) { case '*': @@ -102,10 +102,11 @@ string EscapeJavadoc(const string& input) { return result; } -static void WriteDocCommentBodyForLocation( - io::Printer* printer, const SourceLocation& location) { - string comments = location.leading_comments.empty() ? - location.trailing_comments : location.leading_comments; +static void WriteDocCommentBodyForLocation(io::Printer* printer, + const SourceLocation& location) { + std::string comments = location.leading_comments.empty() + ? location.trailing_comments + : location.leading_comments; if (!comments.empty()) { // TODO(kenton): Ideally we should parse the comment text as Markdown and // write it back as HTML, but this requires a Markdown parser. For now @@ -115,7 +116,7 @@ static void WriteDocCommentBodyForLocation( // HTML-escape them so that they don't accidentally close the doc comment. comments = EscapeJavadoc(comments); - std::vector lines = Split(comments, "\n"); + std::vector lines = Split(comments, "\n"); while (!lines.empty() && lines.back().empty()) { lines.pop_back(); } @@ -138,19 +139,19 @@ static void WriteDocCommentBodyForLocation( } template -static void WriteDocCommentBody( - io::Printer* printer, const DescriptorType* descriptor) { +static void WriteDocCommentBody(io::Printer* printer, + const DescriptorType* descriptor) { SourceLocation location; if (descriptor->GetSourceLocation(&location)) { WriteDocCommentBodyForLocation(printer, location); } } -static string FirstLineOf(const string& value) { - string result = value; +static std::string FirstLineOf(const std::string& value) { + std::string result = value; - string::size_type pos = result.find_first_of('\n'); - if (pos != string::npos) { + std::string::size_type pos = result.find_first_of('\n'); + if (pos != std::string::npos) { result.erase(pos); } @@ -166,35 +167,217 @@ void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) { printer->Print("/**\n"); WriteDocCommentBody(printer, message); printer->Print( - " * Protobuf type {@code $fullname$}\n" - " */\n", - "fullname", EscapeJavadoc(message->full_name())); + " * Protobuf type {@code $fullname$}\n" + " */\n", + "fullname", EscapeJavadoc(message->full_name())); } void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) { - // In theory we should have slightly different comments for setters, getters, - // etc., but in practice everyone already knows the difference between these - // so it's redundant information. - // We start the comment with the main body based on the comments from the - // .proto file (if present). We then end with the field declaration, e.g.: + // .proto file (if present). We then continue with the field declaration, + // e.g.: // optional string foo = 5; + // And then we end with the javadoc tags if applicable. // If the field is a group, the debug string might end with {. printer->Print("/**\n"); WriteDocCommentBody(printer, field); - printer->Print( - " * $def$\n", - "def", EscapeJavadoc(FirstLineOf(field->DebugString()))); + printer->Print(" * $def$\n", "def", + EscapeJavadoc(FirstLineOf(field->DebugString()))); + printer->Print(" */\n"); +} + +void WriteFieldAccessorDocComment(io::Printer* printer, + const FieldDescriptor* field, + const FieldAccessorType type, + const bool builder) { + printer->Print("/**\n"); + WriteDocCommentBody(printer, field); + printer->Print(" * $def$\n", "def", + EscapeJavadoc(FirstLineOf(field->DebugString()))); + switch (type) { + case HAZZER: + printer->Print(" * @return Whether the $name$ field is set.\n", "name", + field->camelcase_name()); + break; + case GETTER: + printer->Print(" * @return The $name$.\n", "name", + field->camelcase_name()); + break; + case SETTER: + printer->Print(" * @param value The $name$ to set.\n", "name", + field->camelcase_name()); + break; + case CLEARER: + // Print nothing + break; + // Repeated + case LIST_COUNT: + printer->Print(" * @return The count of $name$.\n", "name", + field->camelcase_name()); + break; + case LIST_GETTER: + printer->Print(" * @return A list containing the $name$.\n", "name", + field->camelcase_name()); + break; + case LIST_INDEXED_GETTER: + printer->Print(" * @param index The index of the element to return.\n"); + printer->Print(" * @return The $name$ at the given index.\n", "name", + field->camelcase_name()); + break; + case LIST_INDEXED_SETTER: + printer->Print(" * @param index The index to set the value at.\n"); + printer->Print(" * @param value The $name$ to set.\n", "name", + field->camelcase_name()); + break; + case LIST_ADDER: + printer->Print(" * @param value The $name$ to add.\n", "name", + field->camelcase_name()); + break; + case LIST_MULTI_ADDER: + printer->Print(" * @param values The $name$ to add.\n", "name", + field->camelcase_name()); + break; + } + if (builder) { + printer->Print(" * @return This builder for chaining.\n"); + } + printer->Print(" */\n"); +} + +void WriteFieldEnumValueAccessorDocComment(io::Printer* printer, + const FieldDescriptor* field, + const FieldAccessorType type, + const bool builder) { + printer->Print("/**\n"); + WriteDocCommentBody(printer, field); + printer->Print(" * $def$\n", "def", + EscapeJavadoc(FirstLineOf(field->DebugString()))); + switch (type) { + case HAZZER: + // Should never happen + break; + case GETTER: + printer->Print( + " * @return The enum numeric value on the wire for $name$.\n", "name", + field->camelcase_name()); + break; + case SETTER: + printer->Print( + " * @param value The enum numeric value on the wire for $name$ to " + "set.\n", + "name", field->camelcase_name()); + break; + case CLEARER: + // Print nothing + break; + // Repeated + case LIST_COUNT: + // Should never happen + break; + case LIST_GETTER: + printer->Print( + " * @return A list containing the enum numeric values on the wire " + "for $name$.\n", + "name", field->camelcase_name()); + break; + case LIST_INDEXED_GETTER: + printer->Print(" * @param index The index of the value to return.\n"); + printer->Print( + " * @return The enum numeric value on the wire of $name$ at the " + "given index.\n", + "name", field->camelcase_name()); + break; + case LIST_INDEXED_SETTER: + printer->Print(" * @param index The index to set the value at.\n"); + printer->Print( + " * @param value The enum numeric value on the wire for $name$ to " + "set.\n", + "name", field->camelcase_name()); + break; + case LIST_ADDER: + printer->Print( + " * @param value The enum numeric value on the wire for $name$ to " + "add.\n", + "name", field->camelcase_name()); + break; + case LIST_MULTI_ADDER: + printer->Print( + " * @param values The enum numeric values on the wire for $name$ to " + "add.\n", + "name", field->camelcase_name()); + break; + } + if (builder) { + printer->Print(" * @return This builder for chaining.\n"); + } + printer->Print(" */\n"); +} + +void WriteFieldStringBytesAccessorDocComment(io::Printer* printer, + const FieldDescriptor* field, + const FieldAccessorType type, + const bool builder) { + printer->Print("/**\n"); + WriteDocCommentBody(printer, field); + printer->Print(" * $def$\n", "def", + EscapeJavadoc(FirstLineOf(field->DebugString()))); + switch (type) { + case HAZZER: + // Should never happen + break; + case GETTER: + printer->Print(" * @return The bytes for $name$.\n", "name", + field->camelcase_name()); + break; + case SETTER: + printer->Print(" * @param value The bytes for $name$ to set.\n", "name", + field->camelcase_name()); + break; + case CLEARER: + // Print nothing + break; + // Repeated + case LIST_COUNT: + // Should never happen + break; + case LIST_GETTER: + printer->Print(" * @return A list containing the bytes for $name$.\n", + "name", field->camelcase_name()); + break; + case LIST_INDEXED_GETTER: + printer->Print(" * @param index The index of the value to return.\n"); + printer->Print(" * @return The bytes of the $name$ at the given index.\n", + "name", field->camelcase_name()); + break; + case LIST_INDEXED_SETTER: + printer->Print(" * @param index The index to set the value at.\n"); + printer->Print(" * @param value The bytes of the $name$ to set.\n", + "name", field->camelcase_name()); + break; + case LIST_ADDER: + printer->Print(" * @param value The bytes of the $name$ to add.\n", + "name", field->camelcase_name()); + break; + case LIST_MULTI_ADDER: + printer->Print(" * @param values The bytes of the $name$ to add.\n", + "name", field->camelcase_name()); + break; + } + if (builder) { + printer->Print(" * @return This builder for chaining.\n"); + } printer->Print(" */\n"); } +// Enum + void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) { printer->Print("/**\n"); WriteDocCommentBody(printer, enum_); printer->Print( - " * Protobuf enum {@code $fullname$}\n" - " */\n", - "fullname", EscapeJavadoc(enum_->full_name())); + " * Protobuf enum {@code $fullname$}\n" + " */\n", + "fullname", EscapeJavadoc(enum_->full_name())); } void WriteEnumValueDocComment(io::Printer* printer, @@ -202,9 +385,9 @@ void WriteEnumValueDocComment(io::Printer* printer, printer->Print("/**\n"); WriteDocCommentBody(printer, value); printer->Print( - " * $def$\n" - " */\n", - "def", EscapeJavadoc(FirstLineOf(value->DebugString()))); + " * $def$\n" + " */\n", + "def", EscapeJavadoc(FirstLineOf(value->DebugString()))); } void WriteServiceDocComment(io::Printer* printer, @@ -212,9 +395,9 @@ void WriteServiceDocComment(io::Printer* printer, printer->Print("/**\n"); WriteDocCommentBody(printer, service); printer->Print( - " * Protobuf service {@code $fullname$}\n" - " */\n", - "fullname", EscapeJavadoc(service->full_name())); + " * Protobuf service {@code $fullname$}\n" + " */\n", + "fullname", EscapeJavadoc(service->full_name())); } void WriteMethodDocComment(io::Printer* printer, @@ -222,9 +405,9 @@ void WriteMethodDocComment(io::Printer* printer, printer->Print("/**\n"); WriteDocCommentBody(printer, method); printer->Print( - " * $def$\n" - " */\n", - "def", EscapeJavadoc(FirstLineOf(method->DebugString()))); + " * $def$\n" + " */\n", + "def", EscapeJavadoc(FirstLineOf(method->DebugString()))); } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_doc_comment.h b/src/google/protobuf/compiler/java/java_doc_comment.h index 7d9535c959e2c..b7de8776708d4 100644 --- a/src/google/protobuf/compiler/java/java_doc_comment.h +++ b/src/google/protobuf/compiler/java/java_doc_comment.h @@ -37,19 +37,49 @@ #include +#include + namespace google { namespace protobuf { - namespace io { - class Printer; // printer.h - } +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { +enum FieldAccessorType { + HAZZER, + GETTER, + SETTER, + CLEARER, + // Repeated + LIST_COUNT, + LIST_GETTER, + LIST_INDEXED_GETTER, + LIST_INDEXED_SETTER, + LIST_ADDER, + LIST_MULTI_ADDER +}; + void WriteMessageDocComment(io::Printer* printer, const Descriptor* message); void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field); +void WriteFieldAccessorDocComment(io::Printer* printer, + const FieldDescriptor* field, + const FieldAccessorType type, + const bool builder = false); +void WriteFieldEnumValueAccessorDocComment(io::Printer* printer, + const FieldDescriptor* field, + const FieldAccessorType type, + const bool builder = false); +void WriteFieldStringBytesAccessorDocComment(io::Printer* printer, + const FieldDescriptor* field, + const FieldAccessorType type, + const bool builder = false); void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_); void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value); @@ -59,11 +89,13 @@ void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method); // Exposed for testing only. -LIBPROTOC_EXPORT string EscapeJavadoc(const string& input); +PROTOC_EXPORT std::string EscapeJavadoc(const std::string& input); } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc index d125ebe52cc8a..51032c2742b39 100644 --- a/src/google/protobuf/compiler/java/java_enum.cc +++ b/src/google/protobuf/compiler/java/java_enum.cc @@ -36,12 +36,12 @@ #include #include -#include #include +#include #include #include -#include #include +#include #include namespace google { @@ -50,15 +50,15 @@ namespace compiler { namespace java { EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, - bool immutable_api, - Context* context) - : descriptor_(descriptor), immutable_api_(immutable_api), - context_(context), - name_resolver_(context->GetNameResolver()) { + bool immutable_api, Context* context) + : descriptor_(descriptor), + immutable_api_(immutable_api), + context_(context), + name_resolver_(context->GetNameResolver()) { for (int i = 0; i < descriptor_->value_count(); i++) { const EnumValueDescriptor* value = descriptor_->value(i); const EnumValueDescriptor* canonical_value = - descriptor_->FindValueByNumber(value->number()); + descriptor_->FindValueByNumber(value->number()); if (value == canonical_value) { canonical_values_.push_back(value); @@ -77,14 +77,15 @@ void EnumGenerator::Generate(io::Printer* printer) { WriteEnumDocComment(printer, descriptor_); MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_); printer->Print( - "public enum $classname$\n" + "$deprecation$public enum $classname$\n" " implements com.google.protobuf.ProtocolMessageEnum {\n", - "classname", descriptor_->name()); + "classname", descriptor_->name(), "deprecation", + descriptor_->options().deprecated() ? "@java.lang.Deprecated " : ""); printer->Annotate("classname", descriptor_); printer->Indent(); bool ordinal_is_index = true; - string index_text = "ordinal()"; + std::string index_text = "ordinal()"; for (int i = 0; i < canonical_values_.size(); i++) { if (canonical_values_[i]->index() != i) { ordinal_is_index = false; @@ -94,20 +95,18 @@ void EnumGenerator::Generate(io::Printer* printer) { } for (int i = 0; i < canonical_values_.size(); i++) { - std::map vars; + std::map vars; vars["name"] = canonical_values_[i]->name(); - vars["index"] = SimpleItoa(canonical_values_[i]->index()); - vars["number"] = SimpleItoa(canonical_values_[i]->number()); + vars["index"] = StrCat(canonical_values_[i]->index()); + vars["number"] = StrCat(canonical_values_[i]->number()); WriteEnumValueDocComment(printer, canonical_values_[i]); if (canonical_values_[i]->options().deprecated()) { printer->Print("@java.lang.Deprecated\n"); } if (ordinal_is_index) { - printer->Print(vars, - "$name$($number$),\n"); + printer->Print(vars, "$name$($number$),\n"); } else { - printer->Print(vars, - "$name$($index$, $number$),\n"); + printer->Print(vars, "$name$($index$, $number$),\n"); } printer->Annotate("name", canonical_values_[i]); } @@ -122,31 +121,35 @@ void EnumGenerator::Generate(io::Printer* printer) { } printer->Print( - ";\n" - "\n"); + ";\n" + "\n"); // ----------------------------------------------------------------- for (int i = 0; i < aliases_.size(); i++) { - std::map vars; + std::map vars; vars["classname"] = descriptor_->name(); vars["name"] = aliases_[i].value->name(); vars["canonical_name"] = aliases_[i].canonical_value->name(); WriteEnumValueDocComment(printer, aliases_[i].value); - printer->Print(vars, - "public static final $classname$ $name$ = $canonical_name$;\n"); + printer->Print( + vars, "public static final $classname$ $name$ = $canonical_name$;\n"); printer->Annotate("name", aliases_[i].value); } for (int i = 0; i < descriptor_->value_count(); i++) { - std::map vars; + std::map vars; vars["name"] = descriptor_->value(i)->name(); - vars["number"] = SimpleItoa(descriptor_->value(i)->number()); + vars["number"] = StrCat(descriptor_->value(i)->number()); vars["{"] = ""; vars["}"] = ""; + vars["deprecation"] = descriptor_->value(i)->options().deprecated() + ? "@java.lang.Deprecated " + : ""; WriteEnumValueDocComment(printer, descriptor_->value(i)); printer->Print(vars, - "public static final int ${$$name$_VALUE$}$ = $number$;\n"); + "$deprecation$public static final int ${$$name$_VALUE$}$ = " + "$number$;\n"); printer->Annotate("{", "}", descriptor_->value(i)); } printer->Print("\n"); @@ -154,85 +157,110 @@ void EnumGenerator::Generate(io::Printer* printer) { // ----------------------------------------------------------------- printer->Print( - "\n" - "public final int getNumber() {\n"); + "\n" + "public final int getNumber() {\n"); if (SupportUnknownEnumValue(descriptor_->file())) { if (ordinal_is_index) { printer->Print( - " if (this == UNRECOGNIZED) {\n" - " throw new java.lang.IllegalArgumentException(\n" - " \"Can't get the number of an unknown enum value.\");\n" - " }\n"); + " if (this == UNRECOGNIZED) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"Can't get the number of an unknown enum value.\");\n" + " }\n"); } else { printer->Print( - " if (index == -1) {\n" - " throw new java.lang.IllegalArgumentException(\n" - " \"Can't get the number of an unknown enum value.\");\n" - " }\n"); + " if (index == -1) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"Can't get the number of an unknown enum value.\");\n" + " }\n"); } } printer->Print( - " return value;\n" - "}\n" - "\n" - "/**\n" - " * @deprecated Use {@link #forNumber(int)} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public static $classname$ valueOf(int value) {\n" - " return forNumber(value);\n" - "}\n" - "\n" - "public static $classname$ forNumber(int value) {\n" - " switch (value) {\n", - "classname", descriptor_->name()); + " return value;\n" + "}\n" + "\n" + "/**\n" + " * @param value The numeric wire value of the corresponding enum " + "entry.\n" + " * @return The enum associated with the given numeric wire value.\n" + " * @deprecated Use {@link #forNumber(int)} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "public static $classname$ valueOf(int value) {\n" + " return forNumber(value);\n" + "}\n" + "\n" + "/**\n" + " * @param value The numeric wire value of the corresponding enum " + "entry.\n" + " * @return The enum associated with the given numeric wire value.\n" + " */\n" + "public static $classname$ forNumber(int value) {\n" + " switch (value) {\n", + "classname", descriptor_->name()); printer->Indent(); printer->Indent(); for (int i = 0; i < canonical_values_.size(); i++) { - printer->Print( - "case $number$: return $name$;\n", - "name", canonical_values_[i]->name(), - "number", SimpleItoa(canonical_values_[i]->number())); + printer->Print("case $number$: return $name$;\n", "name", + canonical_values_[i]->name(), "number", + StrCat(canonical_values_[i]->number())); } printer->Outdent(); printer->Outdent(); printer->Print( - " default: return null;\n" - " }\n" - "}\n" - "\n" - "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" - " internalGetValueMap() {\n" - " return internalValueMap;\n" - "}\n" - "private static final com.google.protobuf.Internal.EnumLiteMap<\n" - " $classname$> internalValueMap =\n" - " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" - " public $classname$ findValueByNumber(int number) {\n" - " return $classname$.forNumber(number);\n" - " }\n" - " };\n" - "\n", - "classname", descriptor_->name()); + " default: return null;\n" + " }\n" + "}\n" + "\n" + "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" + " internalGetValueMap() {\n" + " return internalValueMap;\n" + "}\n" + "private static final com.google.protobuf.Internal.EnumLiteMap<\n" + " $classname$> internalValueMap =\n" + " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" + " public $classname$ findValueByNumber(int number) {\n" + " return $classname$.forNumber(number);\n" + " }\n" + " };\n" + "\n", + "classname", descriptor_->name()); // ----------------------------------------------------------------- // Reflection if (HasDescriptorMethods(descriptor_, context_->EnforceLite())) { printer->Print( - "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n" - " getValueDescriptor() {\n" - " return getDescriptor().getValues().get($index_text$);\n" - "}\n" - "public final com.google.protobuf.Descriptors.EnumDescriptor\n" - " getDescriptorForType() {\n" - " return getDescriptor();\n" - "}\n" - "public static final com.google.protobuf.Descriptors.EnumDescriptor\n" - " getDescriptor() {\n", - "index_text", index_text); + "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n" + " getValueDescriptor() {\n"); + if (SupportUnknownEnumValue(descriptor_->file())) { + if (ordinal_is_index) { + printer->Print( + " if (this == UNRECOGNIZED) {\n" + " throw new java.lang.IllegalStateException(\n" + " \"Can't get the descriptor of an unrecognized enum " + "value.\");\n" + " }\n"); + } else { + printer->Print( + " if (index == -1) {\n" + " throw new java.lang.IllegalStateException(\n" + " \"Can't get the descriptor of an unrecognized enum " + "value.\");\n" + " }\n"); + } + } + printer->Print( + " return getDescriptor().getValues().get($index_text$);\n" + "}\n" + "public final com.google.protobuf.Descriptors.EnumDescriptor\n" + " getDescriptorForType() {\n" + " return getDescriptor();\n" + "}\n" + "public static final com.google.protobuf.Descriptors.EnumDescriptor\n" + " getDescriptor() {\n", + "index_text", index_text); // TODO(kenton): Cache statically? Note that we can't access descriptors // at module init time because it wouldn't work with descriptor.proto, but @@ -242,27 +270,30 @@ void EnumGenerator::Generate(io::Printer* printer) { // extensions in both the mutable and immutable cases. (In the mutable api // this is accomplished by attempting to load the immutable outer class). printer->Print( - " return $file$.getDescriptor().getEnumTypes().get($index$);\n", - "file", name_resolver_->GetClassName(descriptor_->file(), - immutable_api_), - "index", SimpleItoa(descriptor_->index())); + " return $file$.getDescriptor().getEnumTypes().get($index$);\n", + "file", + name_resolver_->GetClassName(descriptor_->file(), immutable_api_), + "index", StrCat(descriptor_->index())); } else { printer->Print( " return $parent$.$descriptor$.getEnumTypes().get($index$);\n", - "parent", name_resolver_->GetClassName(descriptor_->containing_type(), - immutable_api_), - "descriptor", descriptor_->containing_type()->options() - .no_standard_descriptor_accessor() - ? "getDefaultInstance().getDescriptorForType()" - : "getDescriptor()", - "index", SimpleItoa(descriptor_->index())); + "parent", + name_resolver_->GetClassName(descriptor_->containing_type(), + immutable_api_), + "descriptor", + descriptor_->containing_type() + ->options() + .no_standard_descriptor_accessor() + ? "getDefaultInstance().getDescriptorForType()" + : "getDescriptor()", + "index", StrCat(descriptor_->index())); } printer->Print( - "}\n" - "\n" - "private static final $classname$[] VALUES = ", - "classname", descriptor_->name()); + "}\n" + "\n" + "private static final $classname$[] VALUES = ", + "classname", descriptor_->name()); if (CanUseEnumValues()) { // If the constants we are going to output are exactly the ones we @@ -271,37 +302,43 @@ void EnumGenerator::Generate(io::Printer* printer) { // for every enum. printer->Print("values();\n"); } else { + printer->Print("getStaticValuesArray();\n"); + printer->Print("private static $classname$[] getStaticValuesArray() {\n", + "classname", descriptor_->name()); + printer->Indent(); printer->Print( - "{\n" - " "); + "return new $classname$[] {\n" + " ", + "classname", descriptor_->name()); for (int i = 0; i < descriptor_->value_count(); i++) { - printer->Print("$name$, ", - "name", descriptor_->value(i)->name()); + printer->Print("$name$, ", "name", descriptor_->value(i)->name()); } printer->Print( "\n" "};\n"); + printer->Outdent(); + printer->Print("}"); } printer->Print( - "\n" - "public static $classname$ valueOf(\n" - " com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n" - " if (desc.getType() != getDescriptor()) {\n" - " throw new java.lang.IllegalArgumentException(\n" - " \"EnumValueDescriptor is not for this type.\");\n" - " }\n", - "classname", descriptor_->name()); + "\n" + "public static $classname$ valueOf(\n" + " com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n" + " if (desc.getType() != getDescriptor()) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"EnumValueDescriptor is not for this type.\");\n" + " }\n", + "classname", descriptor_->name()); if (SupportUnknownEnumValue(descriptor_->file())) { printer->Print( - " if (desc.getIndex() == -1) {\n" - " return UNRECOGNIZED;\n" - " }\n"); + " if (desc.getIndex() == -1) {\n" + " return UNRECOGNIZED;\n" + " }\n"); } printer->Print( - " return VALUES[desc.getIndex()];\n" - "}\n" - "\n"); + " return VALUES[desc.getIndex()];\n" + "}\n" + "\n"); if (!ordinal_is_index) { printer->Print("private final int index;\n"); @@ -310,30 +347,27 @@ void EnumGenerator::Generate(io::Printer* printer) { // ----------------------------------------------------------------- - printer->Print( - "private final int value;\n\n"); + printer->Print("private final int value;\n\n"); if (ordinal_is_index) { - printer->Print( - "private $classname$(int value) {\n", - "classname", descriptor_->name()); + printer->Print("private $classname$(int value) {\n", "classname", + descriptor_->name()); } else { - printer->Print( - "private $classname$(int index, int value) {\n", - "classname", descriptor_->name()); + printer->Print("private $classname$(int index, int value) {\n", "classname", + descriptor_->name()); } if (HasDescriptorMethods(descriptor_, context_->EnforceLite()) && !ordinal_is_index) { printer->Print(" this.index = index;\n"); } printer->Print( - " this.value = value;\n" - "}\n"); + " this.value = value;\n" + "}\n"); printer->Print( - "\n" - "// @@protoc_insertion_point(enum_scope:$full_name$)\n", - "full_name", descriptor_->full_name()); + "\n" + "// @@protoc_insertion_point(enum_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); printer->Outdent(); printer->Print("}\n\n"); diff --git a/src/google/protobuf/compiler/java/java_enum.h b/src/google/protobuf/compiler/java/java_enum.h index 13dfc32d49051..0a2c363b5335b 100644 --- a/src/google/protobuf/compiler/java/java_enum.h +++ b/src/google/protobuf/compiler/java/java_enum.h @@ -41,17 +41,19 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -67,9 +69,9 @@ class EnumGenerator { private: const EnumDescriptor* descriptor_; - // The proto language allows multiple enum constants to have the same numeric - // value. Java, however, does not allow multiple enum constants to be - // considered equivalent. We treat the first defined constant for any + // The proto language allows multiple enum constants to have the same + // numeric value. Java, however, does not allow multiple enum constants to + // be considered equivalent. We treat the first defined constant for any // given numeric value as "canonical" and the rest as aliases of that // canonical value. std::vector canonical_values_; @@ -93,6 +95,6 @@ class EnumGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__ diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc index 9f7bb3490baf3..9706c6d027580 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.cc +++ b/src/google/protobuf/compiler/java/java_enum_field.cc @@ -53,12 +53,10 @@ namespace java { namespace { -void SetEnumVariables(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - const FieldGeneratorInfo* info, +void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, - std::map* variables) { + std::map* variables) { SetCommonFieldVariables(descriptor, info, variables); (*variables)["type"] = @@ -66,24 +64,24 @@ void SetEnumVariables(const FieldDescriptor* descriptor, (*variables)["mutable_type"] = name_resolver->GetMutableClassName(descriptor->enum_type()); (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); - (*variables)["default_number"] = SimpleItoa( - descriptor->default_value_enum()->number()); - (*variables)["tag"] = - SimpleItoa(static_cast(internal::WireFormat::MakeTag(descriptor))); - (*variables)["tag_size"] = SimpleItoa( + (*variables)["default_number"] = + StrCat(descriptor->default_value_enum()->number()); + (*variables)["tag"] = StrCat( + static_cast(internal::WireFormat::MakeTag(descriptor))); + (*variables)["tag_size"] = StrCat( internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor))); // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler - (*variables)["deprecation"] = descriptor->options().deprecated() - ? "@java.lang.Deprecated " : ""; + (*variables)["deprecation"] = + descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; (*variables)["on_changed"] = "onChanged();"; // Use deprecated valueOf() method to be compatible with old generated code // for v2.5.0/v2.6.1. // TODO(xiaofeng): Use "forNumber" when we no longer support compatibility - // with v2.5.0/v2.6.1. + // with v2.5.0/v2.6.1, and remove the @SuppressWarnings annotations. (*variables)["for_number"] = "valueOf"; - if (SupportFieldPresence(descriptor->file())) { + if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); @@ -103,11 +101,11 @@ void SetEnumVariables(const FieldDescriptor* descriptor, (*variables)["clear_has_field_bit_builder"] = ""; (*variables)["is_field_present_message"] = - (*variables)["name"] + "_ != " + - (*variables)["default"] + ".getNumber()"; + (*variables)["name"] + "_ != " + (*variables)["default"] + + ".getNumber()"; } - // For repated builders, one bit is used for whether the array is immutable. + // For repeated builders, one bit is used for whether the array is immutable. (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); @@ -135,454 +133,471 @@ void SetEnumVariables(const FieldDescriptor* descriptor, // =================================================================== -ImmutableEnumFieldGenerator:: -ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), - name_resolver_(context->GetNameResolver()) { +ImmutableEnumFieldGenerator::ImmutableEnumFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + Context* context) + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); + context->GetFieldGeneratorInfo(descriptor), name_resolver_, + &variables_); } ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {} int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const { - return 1; + return HasHasbit(descriptor_) ? 1 : 0; } int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { - return 1; + return GetNumBitsForMessage(); } -void ImmutableEnumFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); +void ImmutableEnumFieldGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); + "$deprecation$boolean has$capitalized_name$();\n"); } if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Value();\n"); + "$deprecation$int get$capitalized_name$Value();\n"); } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n"); } -void ImmutableEnumFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private int $name$_;\n"); +void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, "private int $name$_;\n"); PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); + "@java.lang.Override $deprecation$public boolean " + "${$has$capitalized_name$$}$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n" - " return $name$_;\n" - "}\n"); + "@java.lang.Override $deprecation$public int " + "${$get$capitalized_name$Value$}$() {\n" + " return $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " $type$ result = $type$.$for_number$($name$_);\n" - " return result == null ? $unknown$ : result;\n" - "}\n"); + "@java.lang.Override $deprecation$public $type$ " + "${$get$capitalized_name$$}$() {\n" + " @SuppressWarnings(\"deprecation\")\n" + " $type$ result = $type$.$for_number$($name$_);\n" + " return result == null ? $unknown$ : result;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutableEnumFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - printer->Print(variables_, - "private int $name$_ = $default_number$;\n"); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); +void ImmutableEnumFieldGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + printer->Print(variables_, "private int $name$_ = $default_number$;\n"); + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); + "@java.lang.Override $deprecation$public boolean " + "${$has$capitalized_name$$}$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n" - " return $name$_;\n" - "}\n"); + "@java.lang.Override $deprecation$public int " + "${$get$capitalized_name$Value$}$() {\n" + " return $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); printer->Print(variables_, - "$deprecation$public Builder " - "${$set$capitalized_name$Value$}$(int value) {\n" - " $name$_ = value;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder " + "${$set$capitalized_name$Value$}$(int value) {\n" + " $set_has_field_bit_builder$\n" + " $name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " $type$ result = $type$.$for_number$($name$_);\n" - " return result == null ? $unknown$ : result;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " @SuppressWarnings(\"deprecation\")\n" + " $type$ result = $type$.$for_number$($name$_);\n" + " return result == null ? $unknown$ : result;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " $set_has_field_bit_builder$\n" - " $name$_ = value.getNumber();\n" - " $on_changed$\n" - " return this;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " $clear_has_field_bit_builder$\n" - " $name$_ = $default_number$;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder " + "${$set$capitalized_name$$}$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " $set_has_field_bit_builder$\n" + " $name$_ = value.getNumber();\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " $clear_has_field_bit_builder$\n" + " $name$_ = $default_number$;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutableEnumFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { +void ImmutableEnumFieldGenerator::GenerateFieldBuilderInitializationCode( + io::Printer* printer) const { // noop for enums } -void ImmutableEnumFieldGenerator:: -GenerateInitializationCode(io::Printer* printer) const { +void ImmutableEnumFieldGenerator::GenerateInitializationCode( + io::Printer* printer) const { printer->Print(variables_, "$name$_ = $default_number$;\n"); } -void ImmutableEnumFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { +void ImmutableEnumFieldGenerator::GenerateBuilderClearCode( + io::Printer* printer) const { printer->Print(variables_, - "$name$_ = $default_number$;\n" - "$clear_has_field_bit_builder$\n"); + "$name$_ = $default_number$;\n" + "$clear_has_field_bit_builder$\n"); } -void ImmutableEnumFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { +void ImmutableEnumFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + "if (other.has$capitalized_name$()) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); } else if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print(variables_, - "if (other.$name$_ != $default_number$) {\n" - " set$capitalized_name$Value(other.get$capitalized_name$Value());\n" - "}\n"); + printer->Print( + variables_, + "if (other.$name$_ != $default_number$) {\n" + " set$capitalized_name$Value(other.get$capitalized_name$Value());\n" + "}\n"); } else { GOOGLE_LOG(FATAL) << "Can't reach here."; } } -void ImmutableEnumFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { +void ImmutableEnumFieldGenerator::GenerateBuildingCode( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); } - printer->Print(variables_, - "result.$name$_ = $name$_;\n"); + printer->Print(variables_, "result.$name$_ = $name$_;\n"); } -void ImmutableEnumFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +void ImmutableEnumFieldGenerator::GenerateParsingCode( + io::Printer* printer) const { if (SupportUnknownEnumValue(descriptor_->file())) { printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "$set_has_field_bit_message$\n" - "$name$_ = rawValue;\n"); + "int rawValue = input.readEnum();\n" + "$set_has_field_bit_message$\n" + "$name$_ = rawValue;\n"); } else { printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "$type$ value = $type$.$for_number$(rawValue);\n" - "if (value == null) {\n" - " unknownFields.mergeVarintField($number$, rawValue);\n" - "} else {\n" - " $set_has_field_bit_message$\n" - " $name$_ = rawValue;\n" - "}\n"); + "int rawValue = input.readEnum();\n" + " @SuppressWarnings(\"deprecation\")\n" + "$type$ value = $type$.$for_number$(rawValue);\n" + "if (value == null) {\n" + " unknownFields.mergeVarintField($number$, rawValue);\n" + "} else {\n" + " $set_has_field_bit_message$\n" + " $name$_ = rawValue;\n" + "}\n"); } } -void ImmutableEnumFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { +void ImmutableEnumFieldGenerator::GenerateParsingDoneCode( + io::Printer* printer) const { // noop for enums } -void ImmutableEnumFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { +void ImmutableEnumFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " output.writeEnum($number$, $name$_);\n" - "}\n"); + "if ($is_field_present_message$) {\n" + " output.writeEnum($number$, $name$_);\n" + "}\n"); } -void ImmutableEnumFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { +void ImmutableEnumFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeEnumSize($number$, $name$_);\n" - "}\n"); + "if ($is_field_present_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeEnumSize($number$, $name$_);\n" + "}\n"); } -void ImmutableEnumFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && $name$_ == other.$name$_;\n"); +void ImmutableEnumFieldGenerator::GenerateEqualsCode( + io::Printer* printer) const { + printer->Print(variables_, "if ($name$_ != other.$name$_) return false;\n"); } -void ImmutableEnumFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { +void ImmutableEnumFieldGenerator::GenerateHashCode(io::Printer* printer) const { printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n" - "hash = (53 * hash) + $name$_;\n"); + "hash = (37 * hash) + $constant_name$;\n" + "hash = (53 * hash) + $name$_;\n"); } -string ImmutableEnumFieldGenerator::GetBoxedType() const { +std::string ImmutableEnumFieldGenerator::GetBoxedType() const { return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); } // =================================================================== -ImmutableEnumOneofFieldGenerator:: -ImmutableEnumOneofFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableEnumFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { +ImmutableEnumOneofFieldGenerator::ImmutableEnumOneofFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + Context* context) + : ImmutableEnumFieldGenerator(descriptor, messageBitIndex, builderBitIndex, + context) { const OneofGeneratorInfo* info = context->GetOneofGeneratorInfo(descriptor->containing_oneof()); SetCommonOneofVariables(descriptor, info, &variables_); } -ImmutableEnumOneofFieldGenerator:: -~ImmutableEnumOneofFieldGenerator() {} +ImmutableEnumOneofFieldGenerator::~ImmutableEnumOneofFieldGenerator() {} -void ImmutableEnumOneofFieldGenerator:: -GenerateMembers(io::Printer* printer) const { +void ImmutableEnumOneofFieldGenerator::GenerateMembers( + io::Printer* printer) const { PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } + GOOGLE_DCHECK(HasHazzer(descriptor_)); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print(variables_, + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " return (java.lang.Integer) $oneof_name$_;\n" - " }\n" - " return $default_number$;\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " return (java.lang.Integer) $oneof_name$_;\n" + " }\n" + " return $default_number$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " $type$ result = $type$.$for_number$(\n" - " (java.lang.Integer) $oneof_name$_);\n" - " return result == null ? $unknown$ : result;\n" - " }\n" - " return $default$;\n" - "}\n"); + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " @SuppressWarnings(\"deprecation\")\n" + " $type$ result = $type$.$for_number$(\n" + " (java.lang.Integer) $oneof_name$_);\n" + " return result == null ? $unknown$ : result;\n" + " }\n" + " return $default$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutableEnumOneofFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } +void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + GOOGLE_DCHECK(HasHazzer(descriptor_)); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ((java.lang.Integer) $oneof_name$_).intValue();\n" - " }\n" - " return $default_number$;\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ((java.lang.Integer) $oneof_name$_).intValue();\n" + " }\n" + " return $default_number$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); printer->Print(variables_, - "$deprecation$public Builder " - "${$set$capitalized_name$Value$}$(int value) {\n" - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder " + "${$set$capitalized_name$Value$}$(int value) {\n" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " $type$ result = $type$.$for_number$(\n" - " (java.lang.Integer) $oneof_name$_);\n" - " return result == null ? $unknown$ : result;\n" - " }\n" - " return $default$;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " @SuppressWarnings(\"deprecation\")\n" + " $type$ result = $type$.$for_number$(\n" + " (java.lang.Integer) $oneof_name$_);\n" + " return result == null ? $unknown$ : result;\n" + " }\n" + " return $default$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value.getNumber();\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder " + "${$set$capitalized_name$$}$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value.getNumber();\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " $on_changed$\n" - " }\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " $on_changed$\n" + " }\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutableEnumOneofFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { +void ImmutableEnumOneofFieldGenerator::GenerateBuildingCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " result.$oneof_name$_ = $oneof_name$_;\n" - "}\n"); + "if ($has_oneof_case_message$) {\n" + " result.$oneof_name$_ = $oneof_name$_;\n" + "}\n"); } -void ImmutableEnumOneofFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { +void ImmutableEnumOneofFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print(variables_, - "set$capitalized_name$Value(other.get$capitalized_name$Value());\n"); + printer->Print( + variables_, + "set$capitalized_name$Value(other.get$capitalized_name$Value());\n"); } else { printer->Print(variables_, - "set$capitalized_name$(other.get$capitalized_name$());\n"); + "set$capitalized_name$(other.get$capitalized_name$());\n"); } } -void ImmutableEnumOneofFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +void ImmutableEnumOneofFieldGenerator::GenerateParsingCode( + io::Printer* printer) const { if (SupportUnknownEnumValue(descriptor_->file())) { printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "$set_oneof_case_message$;\n" - "$oneof_name$_ = rawValue;\n"); + "int rawValue = input.readEnum();\n" + "$set_oneof_case_message$;\n" + "$oneof_name$_ = rawValue;\n"); } else { printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "$type$ value = $type$.$for_number$(rawValue);\n" - "if (value == null) {\n" - " unknownFields.mergeVarintField($number$, rawValue);\n" - "} else {\n" - " $set_oneof_case_message$;\n" - " $oneof_name$_ = rawValue;\n" - "}\n"); + "int rawValue = input.readEnum();\n" + "@SuppressWarnings(\"deprecation\")\n" + "$type$ value = $type$.$for_number$(rawValue);\n" + "if (value == null) {\n" + " unknownFields.mergeVarintField($number$, rawValue);\n" + "} else {\n" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = rawValue;\n" + "}\n"); } } -void ImmutableEnumOneofFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n" - "}\n"); +void ImmutableEnumOneofFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { + printer->Print( + variables_, + "if ($has_oneof_case_message$) {\n" + " output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n" + "}\n"); } -void ImmutableEnumOneofFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n" - "}\n"); +void ImmutableEnumOneofFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { + printer->Print( + variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n" + "}\n"); } -void ImmutableEnumOneofFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { +void ImmutableEnumOneofFieldGenerator::GenerateEqualsCode( + io::Printer* printer) const { if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print(variables_, - "result = result && get$capitalized_name$Value()\n" - " == other.get$capitalized_name$Value();\n"); + printer->Print( + variables_, + "if (get$capitalized_name$Value()\n" + " != other.get$capitalized_name$Value()) return false;\n"); } else { - printer->Print(variables_, - "result = result && get$capitalized_name$()\n" - " .equals(other.get$capitalized_name$());\n"); + printer->Print( + variables_, + "if (!get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$())) return false;\n"); } } -void ImmutableEnumOneofFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { +void ImmutableEnumOneofFieldGenerator::GenerateHashCode( + io::Printer* printer) const { if (SupportUnknownEnumValue(descriptor_->file())) { printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n" - "hash = (53 * hash) + get$capitalized_name$Value();\n"); + "hash = (37 * hash) + $constant_name$;\n" + "hash = (53 * hash) + get$capitalized_name$Value();\n"); } else { - printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n" - "hash = (53 * hash) + get$capitalized_name$().getNumber();\n"); + printer->Print( + variables_, + "hash = (37 * hash) + $constant_name$;\n" + "hash = (53 * hash) + get$capitalized_name$().getNumber();\n"); } } // =================================================================== -RepeatedImmutableEnumFieldGenerator:: -RepeatedImmutableEnumFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { +RepeatedImmutableEnumFieldGenerator::RepeatedImmutableEnumFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + Context* context) + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); + context->GetFieldGeneratorInfo(descriptor), name_resolver_, + &variables_); } RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {} @@ -595,400 +610,432 @@ int RepeatedImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { return 1; } -void RepeatedImmutableEnumFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"); - WriteFieldDocComment(printer, descriptor_); +void RepeatedImmutableEnumFieldGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); + printer->Print( + variables_, + "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); - WriteFieldDocComment(printer, descriptor_); + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$(int index);\n"); + "$deprecation$$type$ get$capitalized_name$(int index);\n"); if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, - "$deprecation$java.util.List\n" - "get$capitalized_name$ValueList();\n"); - WriteFieldDocComment(printer, descriptor_); + "$deprecation$java.util.List\n" + "get$capitalized_name$ValueList();\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, + LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Value(int index);\n"); + "$deprecation$int get$capitalized_name$Value(int index);\n"); } } -void RepeatedImmutableEnumFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private java.util.List $name$_;\n" - "private static final com.google.protobuf.Internal.ListAdapter.Converter<\n" - " java.lang.Integer, $type$> $name$_converter_ =\n" - " new com.google.protobuf.Internal.ListAdapter.Converter<\n" - " java.lang.Integer, $type$>() {\n" - " public $type$ convert(java.lang.Integer from) {\n" - " $type$ result = $type$.$for_number$(from);\n" - " return result == null ? $unknown$ : result;\n" - " }\n" - " };\n"); +void RepeatedImmutableEnumFieldGenerator::GenerateMembers( + io::Printer* printer) const { + printer->Print( + variables_, + "private java.util.List $name$_;\n" + "private static final " + "com.google.protobuf.Internal.ListAdapter.Converter<\n" + " java.lang.Integer, $type$> $name$_converter_ =\n" + " new com.google.protobuf.Internal.ListAdapter.Converter<\n" + " java.lang.Integer, $type$>() {\n" + " public $type$ convert(java.lang.Integer from) {\n" + " @SuppressWarnings(\"deprecation\")\n" + " $type$ result = $type$.$for_number$(from);\n" + " return result == null ? $unknown$ : result;\n" + " }\n" + " };\n"); PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$> " - "${$get$capitalized_name$List$}$() {\n" - " return new com.google.protobuf.Internal.ListAdapter<\n" - " java.lang.Integer, $type$>($name$_, $name$_converter_);\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public java.util.List<$type$> " + "${$get$capitalized_name$List$}$() {\n" + " return new com.google.protobuf.Internal.ListAdapter<\n" + " java.lang.Integer, $type$>($name$_, $name$_converter_);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return $name$_.size();\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return $name$_.size();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return $name$_converter_.convert($name$_.get(index));\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" + " return $name$_converter_.convert($name$_.get(index));\n" + "}\n"); printer->Annotate("{", "}", descriptor_); if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, - "$deprecation$public java.util.List\n" - "${$get$capitalized_name$ValueList$}$() {\n" - " return $name$_;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public java.util.List\n" + "${$get$capitalized_name$ValueList$}$() {\n" + " return $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, + LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Value$}$(int index) {\n" - " return $name$_.get(index);\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public int " + "${$get$capitalized_name$Value$}$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - if (descriptor_->is_packed() && - context_->HasGeneratedMethods(descriptor_->containing_type())) { - printer->Print(variables_, - "private int $name$MemoizedSerializedSize;\n"); + if (descriptor_->is_packed()) { + printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); } } -void RepeatedImmutableEnumFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - printer->Print(variables_, - // One field is the list and the other field keeps track of whether the - // list is immutable. If it's immutable, the invariant is that it must - // either an instance of Collections.emptyList() or it's an ArrayList - // wrapped in a Collections.unmodifiableList() wrapper and nobody else has - // a refererence to the underlying ArrayList. This invariant allows us to - // share instances of lists between protocol buffers avoiding expensive - // memory allocations. Note, immutable is a strong guarantee here -- not - // just that the list cannot be modified via the reference but that the - // list can never be modified. - "private java.util.List $name$_ =\n" - " java.util.Collections.emptyList();\n" - - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$get_mutable_bit_builder$) {\n" - " $name$_ = new java.util.ArrayList($name$_);\n" - " $set_mutable_bit_builder$;\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - // Note: We return an unmodifiable list because otherwise the caller - // could hold on to the returned list and modify it after the message - // has been built, thus mutating the message which is supposed to be - // immutable. - "$deprecation$public java.util.List<$type$> " - "${$get$capitalized_name$List$}$() {\n" - " return new com.google.protobuf.Internal.ListAdapter<\n" - " java.lang.Integer, $type$>($name$_, $name$_converter_);\n" - "}\n"); +void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + printer->Print( + variables_, + // One field is the list and the other field keeps track of whether the + // list is immutable. If it's immutable, the invariant is that it must + // either an instance of Collections.emptyList() or it's an ArrayList + // wrapped in a Collections.unmodifiableList() wrapper and nobody else has + // a reference to the underlying ArrayList. This invariant allows us to + // share instances of lists between protocol buffers avoiding expensive + // memory allocations. Note, immutable is a strong guarantee here -- not + // just that the list cannot be modified via the reference but that the + // list can never be modified. + "private java.util.List $name$_ =\n" + " java.util.Collections.emptyList();\n" + + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new java.util.ArrayList($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n"); + + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); + printer->Print( + variables_, + // Note: We return an unmodifiable list because otherwise the caller + // could hold on to the returned list and modify it after the message + // has been built, thus mutating the message which is supposed to be + // immutable. + "$deprecation$public java.util.List<$type$> " + "${$get$capitalized_name$List$}$() {\n" + " return new com.google.protobuf.Internal.ListAdapter<\n" + " java.lang.Integer, $type$>($name$_, $name$_converter_);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return $name$_.size();\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); + printer->Print( + variables_, + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return $name$_.size();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return $name$_converter_.convert($name$_.get(index));\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); + printer->Print( + variables_, + "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" + " return $name$_converter_.convert($name$_.get(index));\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, + /* builder */ true); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " int index, $type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, value.getNumber());\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " int index, $type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value.getNumber());\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, + /* builder */ true); printer->Print(variables_, - "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value.getNumber());\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder " + "${$add$capitalized_name$$}$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value.getNumber());\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, + /* builder */ true); printer->Print(variables_, - "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" - " java.lang.Iterable values) {\n" - " ensure$capitalized_name$IsMutable();\n" - " for ($type$ value : values) {\n" - " $name$_.add(value.getNumber());\n" - " }\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " for ($type$ value : values) {\n" + " $name$_.add(value.getNumber());\n" + " }\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " $name$_ = java.util.Collections.emptyList();\n" - " $clear_mutable_bit_builder$;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " $name$_ = java.util.Collections.emptyList();\n" + " $clear_mutable_bit_builder$;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, - "$deprecation$public java.util.List\n" - "${$get$capitalized_name$ValueList$}$() {\n" - " return java.util.Collections.unmodifiableList($name$_);\n" - "}\n"); + "$deprecation$public java.util.List\n" + "${$get$capitalized_name$ValueList$}$() {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, + LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Value$}$(int index) {\n" - " return $name$_.get(index);\n" - "}\n"); + "$deprecation$public int " + "${$get$capitalized_name$Value$}$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n" - " int index, int value) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, value);\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, + LIST_INDEXED_GETTER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n" + " int index, int value) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_ADDER, + /* builder */ true); printer->Print(variables_, - "$deprecation$public Builder " - "${$add$capitalized_name$Value$}$(int value) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value);\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder " + "${$add$capitalized_name$Value$}$(int value) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n" - " java.lang.Iterable values) {\n" - " ensure$capitalized_name$IsMutable();\n" - " for (int value : values) {\n" - " $name$_.add(value);\n" - " }\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, + LIST_MULTI_ADDER, /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " for (int value : values) {\n" + " $name$_.add(value);\n" + " }\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } } void RepeatedImmutableEnumFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + GenerateFieldBuilderInitializationCode(io::Printer* printer) const { // noop for enums } -void RepeatedImmutableEnumFieldGenerator:: -GenerateInitializationCode(io::Printer* printer) const { +void RepeatedImmutableEnumFieldGenerator::GenerateInitializationCode( + io::Printer* printer) const { printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); } -void RepeatedImmutableEnumFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { +void RepeatedImmutableEnumFieldGenerator::GenerateBuilderClearCode( + io::Printer* printer) const { printer->Print(variables_, - "$name$_ = java.util.Collections.emptyList();\n" - "$clear_mutable_bit_builder$;\n"); + "$name$_ = java.util.Collections.emptyList();\n" + "$clear_mutable_bit_builder$;\n"); } -void RepeatedImmutableEnumFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { +void RepeatedImmutableEnumFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { // The code below does two optimizations: // 1. If the other list is empty, there's nothing to do. This ensures we // don't allocate a new array if we already have an immutable one. // 2. If the other list is non-empty and our current list is empty, we can // reuse the other list which is guaranteed to be immutable. printer->Print(variables_, - "if (!other.$name$_.isEmpty()) {\n" - " if ($name$_.isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " $clear_mutable_bit_builder$;\n" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" - " }\n" - " $on_changed$\n" - "}\n"); + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n"); } -void RepeatedImmutableEnumFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { +void RepeatedImmutableEnumFieldGenerator::GenerateBuildingCode( + io::Printer* printer) const { // The code below ensures that the result has an immutable list. If our // list is immutable, we can just reuse it. If not, we make it immutable. - printer->Print(variables_, - "if ($get_mutable_bit_builder$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - " $clear_mutable_bit_builder$;\n" - "}\n" - "result.$name$_ = $name$_;\n"); + printer->Print( + variables_, + "if ($get_mutable_bit_builder$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); } -void RepeatedImmutableEnumFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +void RepeatedImmutableEnumFieldGenerator::GenerateParsingCode( + io::Printer* printer) const { // Read and store the enum if (SupportUnknownEnumValue(descriptor_->file())) { printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ = new java.util.ArrayList();\n" - " $set_mutable_bit_parser$;\n" - "}\n" - "$name$_.add(rawValue);\n"); + "int rawValue = input.readEnum();\n" + "if (!$get_mutable_bit_parser$) {\n" + " $name$_ = new java.util.ArrayList();\n" + " $set_mutable_bit_parser$;\n" + "}\n" + "$name$_.add(rawValue);\n"); } else { - printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "$type$ value = $type$.$for_number$(rawValue);\n" - "if (value == null) {\n" - " unknownFields.mergeVarintField($number$, rawValue);\n" - "} else {\n" - " if (!$get_mutable_bit_parser$) {\n" - " $name$_ = new java.util.ArrayList();\n" - " $set_mutable_bit_parser$;\n" - " }\n" - " $name$_.add(rawValue);\n" - "}\n"); + printer->Print( + variables_, + "int rawValue = input.readEnum();\n" + "@SuppressWarnings(\"deprecation\")\n" + "$type$ value = $type$.$for_number$(rawValue);\n" + "if (value == null) {\n" + " unknownFields.mergeVarintField($number$, rawValue);\n" + "} else {\n" + " if (!$get_mutable_bit_parser$) {\n" + " $name$_ = new java.util.ArrayList();\n" + " $set_mutable_bit_parser$;\n" + " }\n" + " $name$_.add(rawValue);\n" + "}\n"); } } -void RepeatedImmutableEnumFieldGenerator:: -GenerateParsingCodeFromPacked(io::Printer* printer) const { +void RepeatedImmutableEnumFieldGenerator::GenerateParsingCodeFromPacked( + io::Printer* printer) const { // Wrap GenerateParsingCode's contents with a while loop. printer->Print(variables_, - "int length = input.readRawVarint32();\n" - "int oldLimit = input.pushLimit(length);\n" - "while(input.getBytesUntilLimit() > 0) {\n"); + "int length = input.readRawVarint32();\n" + "int oldLimit = input.pushLimit(length);\n" + "while(input.getBytesUntilLimit() > 0) {\n"); printer->Indent(); GenerateParsingCode(printer); printer->Outdent(); printer->Print(variables_, - "}\n" - "input.popLimit(oldLimit);\n"); + "}\n" + "input.popLimit(oldLimit);\n"); } -void RepeatedImmutableEnumFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_mutable_bit_parser$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - "}\n"); +void RepeatedImmutableEnumFieldGenerator::GenerateParsingDoneCode( + io::Printer* printer) const { + printer->Print( + variables_, + "if ($get_mutable_bit_parser$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + "}\n"); } -void RepeatedImmutableEnumFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { +void RepeatedImmutableEnumFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { if (descriptor_->is_packed()) { printer->Print(variables_, - "if (get$capitalized_name$List().size() > 0) {\n" - " output.writeUInt32NoTag($tag$);\n" - " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n" - "}\n" - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeEnumNoTag($name$_.get(i));\n" - "}\n"); + "if (get$capitalized_name$List().size() > 0) {\n" + " output.writeUInt32NoTag($tag$);\n" + " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n" + "}\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeEnumNoTag($name$_.get(i));\n" + "}\n"); } else { printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeEnum($number$, $name$_.get(i));\n" - "}\n"); + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeEnum($number$, $name$_.get(i));\n" + "}\n"); } } -void RepeatedImmutableEnumFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { +void RepeatedImmutableEnumFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { printer->Print(variables_, - "{\n" - " int dataSize = 0;\n"); + "{\n" + " int dataSize = 0;\n"); printer->Indent(); printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " dataSize += com.google.protobuf.CodedOutputStream\n" - " .computeEnumSizeNoTag($name$_.get(i));\n" - "}\n"); - printer->Print( - "size += dataSize;\n"); + "for (int i = 0; i < $name$_.size(); i++) {\n" + " dataSize += com.google.protobuf.CodedOutputStream\n" + " .computeEnumSizeNoTag($name$_.get(i));\n" + "}\n"); + printer->Print("size += dataSize;\n"); if (descriptor_->is_packed()) { printer->Print(variables_, - "if (!get$capitalized_name$List().isEmpty()) {" - " size += $tag_size$;\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeUInt32SizeNoTag(dataSize);\n" - "}"); + "if (!get$capitalized_name$List().isEmpty()) {" + " size += $tag_size$;\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeUInt32SizeNoTag(dataSize);\n" + "}"); } else { - printer->Print(variables_, - "size += $tag_size$ * $name$_.size();\n"); + printer->Print(variables_, "size += $tag_size$ * $name$_.size();\n"); } // cache the data size for packed fields. if (descriptor_->is_packed()) { - printer->Print(variables_, - "$name$MemoizedSerializedSize = dataSize;\n"); + printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n"); } printer->Outdent(); printer->Print("}\n"); } -void RepeatedImmutableEnumFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { +void RepeatedImmutableEnumFieldGenerator::GenerateEqualsCode( + io::Printer* printer) const { printer->Print(variables_, - "result = result && $name$_.equals(other.$name$_);\n"); + "if (!$name$_.equals(other.$name$_)) return false;\n"); } -void RepeatedImmutableEnumFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { +void RepeatedImmutableEnumFieldGenerator::GenerateHashCode( + io::Printer* printer) const { printer->Print(variables_, - "if (get$capitalized_name$Count() > 0) {\n" - " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + $name$_.hashCode();\n" - "}\n"); + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + $name$_.hashCode();\n" + "}\n"); } -string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const { +std::string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const { return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); } diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h index 924ff2814918a..95c7db578f2f4 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.h +++ b/src/google/protobuf/compiler/java/java_enum_field.h @@ -41,26 +41,29 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator { public: - explicit ImmutableEnumFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex, + Context* context); ~ImmutableEnumFieldGenerator(); - // implements ImmutableFieldGenerator --------------------------------------- + // implements ImmutableFieldGenerator + // --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -78,14 +81,11 @@ class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; + std::map variables_; ClassNameResolver* name_resolver_; private: @@ -94,9 +94,9 @@ class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator { class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator { public: - ImmutableEnumOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutableEnumOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex, + Context* context); ~ImmutableEnumOneofFieldGenerator(); void GenerateMembers(io::Printer* printer) const; @@ -139,14 +139,11 @@ class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; + std::map variables_; ClassNameResolver* name_resolver_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldGenerator); @@ -155,6 +152,6 @@ class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc index a4de1e233440e..dfa051c16d30b 100644 --- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc @@ -52,13 +52,18 @@ namespace compiler { namespace java { namespace { +bool EnableExperimentalRuntimeForLite() { +#ifdef PROTOBUF_EXPERIMENT + return PROTOBUF_EXPERIMENT; +#else // PROTOBUF_EXPERIMENT + return false; +#endif // !PROTOBUF_EXPERIMENT +} -void SetEnumVariables(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - const FieldGeneratorInfo* info, +void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, - std::map* variables) { + std::map* variables) { SetCommonFieldVariables(descriptor, info, variables); (*variables)["type"] = @@ -66,19 +71,19 @@ void SetEnumVariables(const FieldDescriptor* descriptor, (*variables)["mutable_type"] = name_resolver->GetMutableClassName(descriptor->enum_type()); (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); - (*variables)["default_number"] = SimpleItoa( - descriptor->default_value_enum()->number()); - (*variables)["tag"] = - SimpleItoa(static_cast(internal::WireFormat::MakeTag(descriptor))); - (*variables)["tag_size"] = SimpleItoa( + (*variables)["default_number"] = + StrCat(descriptor->default_value_enum()->number()); + (*variables)["tag"] = StrCat( + static_cast(internal::WireFormat::MakeTag(descriptor))); + (*variables)["tag_size"] = StrCat( internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor))); // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler - (*variables)["deprecation"] = descriptor->options().deprecated() - ? "@java.lang.Deprecated " : ""; + (*variables)["deprecation"] = + descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; (*variables)["required"] = descriptor->is_required() ? "true" : "false"; - if (SupportFieldPresence(descriptor->file())) { + if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); @@ -94,13 +99,10 @@ void SetEnumVariables(const FieldDescriptor* descriptor, (*variables)["clear_has_field_bit_message"] = ""; (*variables)["is_field_present_message"] = - (*variables)["name"] + "_ != " + - (*variables)["default"] + ".getNumber()"; + (*variables)["name"] + "_ != " + (*variables)["default"] + + ".getNumber()"; } - // For repeated builders, the underlying list tracks mutability state. - (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()"; - (*variables)["get_has_field_bit_from_local"] = GenerateGetBitFromLocal(builderBitIndex); (*variables)["set_has_field_bit_to_local"] = @@ -111,885 +113,666 @@ void SetEnumVariables(const FieldDescriptor* descriptor, } else { (*variables)["unknown"] = (*variables)["default"]; } + + // We use `x.getClass()` as a null check because it generates less bytecode + // than an `if (x == null) { throw ... }` statement. + (*variables)["null_check"] = "value.getClass();\n"; } } // namespace // =================================================================== -ImmutableEnumFieldLiteGenerator:: -ImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), - name_resolver_(context->GetNameResolver()) { - SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); +ImmutableEnumFieldLiteGenerator::ImmutableEnumFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, Context* context) + : descriptor_(descriptor), + messageBitIndex_(messageBitIndex), + context_(context), + name_resolver_(context->GetNameResolver()) { + SetEnumVariables(descriptor, messageBitIndex, 0, + context->GetFieldGeneratorInfo(descriptor), name_resolver_, + &variables_); } ImmutableEnumFieldLiteGenerator::~ImmutableEnumFieldLiteGenerator() {} int ImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const { - return 1; -} - -int ImmutableEnumFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; + return HasHasbit(descriptor_) ? 1 : 0; } -void ImmutableEnumFieldLiteGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); +void ImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); + "$deprecation$boolean has$capitalized_name$();\n"); } if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Value();\n"); + "$deprecation$int get$capitalized_name$Value();\n"); } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n"); } -void ImmutableEnumFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private int $name$_;\n"); +void ImmutableEnumFieldLiteGenerator::GenerateMembers( + io::Printer* printer) const { + printer->Print(variables_, "private int $name$_;\n"); PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n" - " return $name$_;\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n" + " return $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " $type$ result = $type$.forNumber($name$_);\n" - " return result == null ? $unknown$ : result;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " $type$ result = $type$.forNumber($name$_);\n" + " return result == null ? $unknown$ : result;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Generate private setters for the builder to proxy into. if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER); printer->Print(variables_, - "private void set$capitalized_name$Value(int value) {\n" - " $set_has_field_bit_message$" - " $name$_ = value;\n" - "}\n"); + "private void set$capitalized_name$Value(int value) {\n" + " $set_has_field_bit_message$" + " $name$_ = value;\n" + "}\n"); } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " $set_has_field_bit_message$\n" - " $name$_ = value.getNumber();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " $clear_has_field_bit_message$\n" - " $name$_ = $default_number$;\n" - "}\n"); -} - -void ImmutableEnumFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return instance.has$capitalized_name$();\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER); + printer->Print(variables_, + "private void set$capitalized_name$($type$ value) {\n" + " $name$_ = value.getNumber();\n" + " $set_has_field_bit_message$\n" + "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " $clear_has_field_bit_message$\n" + " $name$_ = $default_number$;\n" + "}\n"); +} + +void ImmutableEnumFieldLiteGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n" - " return instance.get$capitalized_name$Value();\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n" + " return instance.get$capitalized_name$Value();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder " - "${$set$capitalized_name$Value$}$(int value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$Value(value);\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder " + "${$set$capitalized_name$Value$}$(int value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$Value(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return instance.get$capitalized_name$();\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(value);\n" - " return this;\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder " + "${$set$capitalized_name$$}$($type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutableEnumFieldLiteGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - // noop for enums -} - -void ImmutableEnumFieldLiteGenerator:: -GenerateInitializationCode(io::Printer* printer) const { +void ImmutableEnumFieldLiteGenerator::GenerateInitializationCode( + io::Printer* printer) const { if (!IsDefaultValueJavaDefault(descriptor_)) { printer->Print(variables_, "$name$_ = $default_number$;\n"); } } -void ImmutableEnumFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "$name$_ = visitor.visitInt(has$capitalized_name$(), $name$_,\n" - " other.has$capitalized_name$(), other.$name$_);\n"); - } else if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print(variables_, - "$name$_ = visitor.visitInt($name$_ != $default_number$, $name$_," - " other.$name$_ != $default_number$, other.$name$_);\n"); - } else { - GOOGLE_LOG(FATAL) << "Can't reach here."; +void ImmutableEnumFieldLiteGenerator::GenerateFieldInfo( + io::Printer* printer, std::vector* output) const { + WriteIntToUtf16CharSequence(descriptor_->number(), output); + WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_), + output); + if (HasHasbit(descriptor_)) { + WriteIntToUtf16CharSequence(messageBitIndex_, output); } -} - -void ImmutableEnumFieldLiteGenerator:: -GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { - // noop for scalars -} - -void ImmutableEnumFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "$set_has_field_bit_message$\n" - "$name$_ = rawValue;\n"); - } else { - printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "$type$ value = $type$.forNumber(rawValue);\n" - "if (value == null) {\n" - " super.mergeVarintField($number$, rawValue);\n" - "} else {\n" - " $set_has_field_bit_message$\n" - " $name$_ = rawValue;\n" - "}\n"); + printer->Print(variables_, "\"$name$_\",\n"); + if (!SupportUnknownEnumValue((descriptor_))) { + PrintEnumVerifierLogic(printer, descriptor_, variables_, + /*var_name=*/"$type$", + /*terminating_string=*/",\n", + /*enforce_lite=*/context_->EnforceLite()); } } -void ImmutableEnumFieldLiteGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - // noop for enums -} - - -void ImmutableEnumFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " output.writeEnum($number$, $name$_);\n" - "}\n"); -} - -void ImmutableEnumFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeEnumSize($number$, $name$_);\n" - "}\n"); -} - -void ImmutableEnumFieldLiteGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && $name$_ == other.$name$_;\n"); -} - -void ImmutableEnumFieldLiteGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n" - "hash = (53 * hash) + $name$_;\n"); -} - -string ImmutableEnumFieldLiteGenerator::GetBoxedType() const { +std::string ImmutableEnumFieldLiteGenerator::GetBoxedType() const { return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); } // =================================================================== -ImmutableEnumOneofFieldLiteGenerator:: -ImmutableEnumOneofFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableEnumFieldLiteGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { +ImmutableEnumOneofFieldLiteGenerator::ImmutableEnumOneofFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, Context* context) + : ImmutableEnumFieldLiteGenerator(descriptor, messageBitIndex, context) { const OneofGeneratorInfo* info = context->GetOneofGeneratorInfo(descriptor->containing_oneof()); SetCommonOneofVariables(descriptor, info, &variables_); } -ImmutableEnumOneofFieldLiteGenerator:: -~ImmutableEnumOneofFieldLiteGenerator() {} +ImmutableEnumOneofFieldLiteGenerator::~ImmutableEnumOneofFieldLiteGenerator() {} -void ImmutableEnumOneofFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { +void ImmutableEnumOneofFieldLiteGenerator::GenerateMembers( + io::Printer* printer) const { PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } + GOOGLE_DCHECK(HasHazzer(descriptor_)); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " return (java.lang.Integer) $oneof_name$_;\n" - " }\n" - " return $default_number$;\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " return (java.lang.Integer) $oneof_name$_;\n" + " }\n" + " return $default_number$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n" - " return result == null ? $unknown$ : result;\n" - " }\n" - " return $default$;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " $type$ result = $type$.forNumber((java.lang.Integer) " + "$oneof_name$_);\n" + " return result == null ? $unknown$ : result;\n" + " }\n" + " return $default$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Generate private setters for the builder to proxy into. if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER); printer->Print(variables_, - "private void set$capitalized_name$Value(int value) {\n" - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value;\n" - "}\n"); + "private void set$capitalized_name$Value(int value) {\n" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + "}\n"); + } + WriteFieldAccessorDocComment(printer, descriptor_, SETTER); + printer->Print(variables_, + "private void set$capitalized_name$($type$ value) {\n" + " $oneof_name$_ = value.getNumber();\n" + " $set_oneof_case_message$;\n" + "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " }\n" + "}\n"); +} + +void ImmutableEnumOneofFieldLiteGenerator::GenerateFieldInfo( + io::Printer* printer, std::vector* output) const { + WriteIntToUtf16CharSequence(descriptor_->number(), output); + WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_), + output); + WriteIntToUtf16CharSequence(descriptor_->containing_oneof()->index(), output); + if (!SupportUnknownEnumValue(descriptor_)) { + PrintEnumVerifierLogic(printer, descriptor_, variables_, + /*var_name=*/"$type$", + /*terminating_string=*/",\n", + /*enforce_lite=*/context_->EnforceLite()); } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value.getNumber();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " }\n" - "}\n"); } +void ImmutableEnumOneofFieldLiteGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + GOOGLE_DCHECK(HasHazzer(descriptor_)); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); -void ImmutableEnumOneofFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return instance.has$capitalized_name$();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n" - " return instance.get$capitalized_name$Value();\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n" + " return instance.get$capitalized_name$Value();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder " - "${$set$capitalized_name$Value$}$(int value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$Value(value);\n" - " return this;\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder " + "${$set$capitalized_name$Value$}$(int value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$Value(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return instance.get$capitalized_name$();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(value);\n" - " return this;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder " + "${$set$capitalized_name$$}$($type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); -} - -void ImmutableEnumOneofFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - printer->Print(variables_, - "$oneof_name$_ = visitor.visitOneofInt(\n" - " $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n"); -} - -void ImmutableEnumOneofFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "$set_oneof_case_message$;\n" - "$oneof_name$_ = rawValue;\n"); - } else { - printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "$type$ value = $type$.forNumber(rawValue);\n" - "if (value == null) {\n" - " super.mergeVarintField($number$, rawValue);\n" - "} else {\n" - " $set_oneof_case_message$;\n" - " $oneof_name$_ = rawValue;\n" + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" "}\n"); - } -} - -void ImmutableEnumOneofFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n" - "}\n"); -} - -void ImmutableEnumOneofFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n" - "}\n"); -} - -void ImmutableEnumOneofFieldLiteGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print(variables_, - "result = result && get$capitalized_name$Value()\n" - " == other.get$capitalized_name$Value();\n"); - } else { - printer->Print(variables_, - "result = result && get$capitalized_name$()\n" - " .equals(other.get$capitalized_name$());\n"); - } -} - -void ImmutableEnumOneofFieldLiteGenerator:: -GenerateHashCode(io::Printer* printer) const { - if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n" - "hash = (53 * hash) + get$capitalized_name$Value();\n"); - } else { - printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n" - "hash = (53 * hash) + get$capitalized_name$().getNumber();\n"); - } + printer->Annotate("{", "}", descriptor_); } // =================================================================== RepeatedImmutableEnumFieldLiteGenerator:: -RepeatedImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); + RepeatedImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context) + : descriptor_(descriptor), + context_(context), + name_resolver_(context->GetNameResolver()) { + SetEnumVariables(descriptor, messageBitIndex, 0, + context->GetFieldGeneratorInfo(descriptor), name_resolver_, + &variables_); } RepeatedImmutableEnumFieldLiteGenerator:: -~RepeatedImmutableEnumFieldLiteGenerator() {} + ~RepeatedImmutableEnumFieldLiteGenerator() {} int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const { return 0; } -int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; -} - -void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"); - WriteFieldDocComment(printer, descriptor_); +void RepeatedImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); + printer->Print( + variables_, + "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); - WriteFieldDocComment(printer, descriptor_); + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$(int index);\n"); + "$deprecation$$type$ get$capitalized_name$(int index);\n"); if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, - "$deprecation$java.util.List\n" - "get$capitalized_name$ValueList();\n"); - WriteFieldDocComment(printer, descriptor_); + "$deprecation$java.util.List\n" + "get$capitalized_name$ValueList();\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, + LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Value(int index);\n"); + "$deprecation$int get$capitalized_name$Value(int index);\n"); } } -void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private com.google.protobuf.Internal.IntList $name$_;\n" - "private static final com.google.protobuf.Internal.ListAdapter.Converter<\n" - " java.lang.Integer, $type$> $name$_converter_ =\n" - " new com.google.protobuf.Internal.ListAdapter.Converter<\n" - " java.lang.Integer, $type$>() {\n" - " public $type$ convert(java.lang.Integer from) {\n" - " $type$ result = $type$.forNumber(from);\n" - " return result == null ? $unknown$ : result;\n" - " }\n" - " };\n"); +void RepeatedImmutableEnumFieldLiteGenerator::GenerateMembers( + io::Printer* printer) const { + printer->Print( + variables_, + "private com.google.protobuf.Internal.IntList $name$_;\n" + "private static final " + "com.google.protobuf.Internal.ListAdapter.Converter<\n" + " java.lang.Integer, $type$> $name$_converter_ =\n" + " new com.google.protobuf.Internal.ListAdapter.Converter<\n" + " java.lang.Integer, $type$>() {\n" + " @java.lang.Override\n" + " public $type$ convert(java.lang.Integer from) {\n" + " $type$ result = $type$.forNumber(from);\n" + " return result == null ? $unknown$ : result;\n" + " }\n" + " };\n"); PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$> " - "${$get$capitalized_name$List$}$() {\n" - " return new com.google.protobuf.Internal.ListAdapter<\n" - " java.lang.Integer, $type$>($name$_, $name$_converter_);\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public java.util.List<$type$> " + "${$get$capitalized_name$List$}$() {\n" + " return new com.google.protobuf.Internal.ListAdapter<\n" + " java.lang.Integer, $type$>($name$_, $name$_converter_);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return $name$_.size();\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return $name$_.size();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return $name$_converter_.convert($name$_.getInt(index));\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" + " return $name$_converter_.convert($name$_.getInt(index));\n" + "}\n"); printer->Annotate("{", "}", descriptor_); if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, - "$deprecation$public java.util.List\n" - "${$get$capitalized_name$ValueList$}$() {\n" - " return $name$_;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public java.util.List\n" + "${$get$capitalized_name$ValueList$}$() {\n" + " return $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Value$}$(int index) {\n" - " return $name$_.getInt(index);\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, + LIST_INDEXED_GETTER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public int " + "${$get$capitalized_name$Value$}$(int index) {\n" + " return $name$_.getInt(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - if (descriptor_->is_packed() && + if (!EnableExperimentalRuntimeForLite() && descriptor_->is_packed() && context_->HasGeneratedMethods(descriptor_->containing_type())) { - printer->Print(variables_, - "private int $name$MemoizedSerializedSize;\n"); + printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); } // Generate private setters for the builder to proxy into. - printer->Print(variables_, - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$is_mutable$) {\n" - " $name$_ =\n" - " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" - " }\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$(\n" - " int index, $type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.setInt(index, value.getNumber());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addInt(value.getNumber());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void addAll$capitalized_name$(\n" - " java.lang.Iterable values) {\n" - " ensure$capitalized_name$IsMutable();\n" - " for ($type$ value : values) {\n" - " $name$_.addInt(value.getNumber());\n" - " }\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " $name$_ = emptyIntList();\n" - "}\n"); - - if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$Value(\n" - " int index, int value) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.setInt(index, value);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$Value(int value) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addInt(value);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void addAll$capitalized_name$Value(\n" - " java.lang.Iterable values) {\n" - " ensure$capitalized_name$IsMutable();\n" - " for (int value : values) {\n" - " $name$_.addInt(value);\n" + printer->Print( + variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + // Use a temporary to avoid a redundant iget-object. + " com.google.protobuf.Internal.IntList tmp = $name$_;\n" + " if (!tmp.isModifiable()) {\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n" " }\n" "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " int index, $type$ value) {\n" + " $null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.setInt(index, value.getNumber());\n" + "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER); + printer->Print(variables_, + "private void add$capitalized_name$($type$ value) {\n" + " $null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addInt(value.getNumber());\n" + "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER); + printer->Print(variables_, + "private void addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " for ($type$ value : values) {\n" + " $name$_.addInt(value.getNumber());\n" + " }\n" + "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " $name$_ = emptyIntList();\n" + "}\n"); + + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER); + printer->Print(variables_, + "private void set$capitalized_name$Value(\n" + " int index, int value) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.setInt(index, value);\n" + "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_ADDER); + printer->Print(variables_, + "private void add$capitalized_name$Value(int value) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addInt(value);\n" + "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, + LIST_MULTI_ADDER); + printer->Print(variables_, + "private void addAll$capitalized_name$Value(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " for (int value : values) {\n" + " $name$_.addInt(value);\n" + " }\n" + "}\n"); } } +void RepeatedImmutableEnumFieldLiteGenerator::GenerateFieldInfo( + io::Printer* printer, std::vector* output) const { + WriteIntToUtf16CharSequence(descriptor_->number(), output); + WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_), + output); + printer->Print(variables_, "\"$name$_\",\n"); + if (!SupportUnknownEnumValue(descriptor_->file())) { + PrintEnumVerifierLogic(printer, descriptor_, variables_, + /*var_name=*/"$type$", + /*terminating_string=*/",\n", + /*enforce_lite=*/context_->EnforceLite()); + } +} -void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); +void RepeatedImmutableEnumFieldLiteGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, - "$deprecation$public java.util.List<$type$> " - "${$get$capitalized_name$List$}$() {\n" - " return instance.get$capitalized_name$List();\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public java.util.List<$type$> " + "${$get$capitalized_name$List$}$() {\n" + " return instance.get$capitalized_name$List();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return instance.get$capitalized_name$Count();\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return instance.get$capitalized_name$Count();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return instance.get$capitalized_name$(index);\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" + " return instance.get$capitalized_name$(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " int index, $type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(index, value);\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " int index, $type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(index, value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(value);\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder " + "${$add$capitalized_name$$}$($type$ value) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" - " java.lang.Iterable values) {\n" - " copyOnWrite();\n" - " instance.addAll$capitalized_name$(values);" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" + " java.lang.Iterable values) {\n" + " copyOnWrite();\n" + " instance.addAll$capitalized_name$(values);" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); if (SupportUnknownEnumValue(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List\n" - "${$get$capitalized_name$ValueList$}$() {\n" - " return java.util.Collections.unmodifiableList(\n" - " instance.get$capitalized_name$ValueList());\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public java.util.List\n" + "${$get$capitalized_name$ValueList$}$() {\n" + " return java.util.Collections.unmodifiableList(\n" + " instance.get$capitalized_name$ValueList());\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Value$}$(int index) {\n" - " return instance.get$capitalized_name$Value(index);\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, + LIST_INDEXED_GETTER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public int " + "${$get$capitalized_name$Value$}$(int index) {\n" + " return instance.get$capitalized_name$Value(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n" - " int index, int value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$Value(index, value);\n" - " return this;\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, + LIST_INDEXED_SETTER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n" + " int index, int value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$Value(index, value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder " - "${$add$capitalized_name$Value$}$(int value) {\n" - " instance.add$capitalized_name$Value(value);\n" - " return this;\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_ADDER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder " + "${$add$capitalized_name$Value$}$(int value) {\n" + " instance.add$capitalized_name$Value(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n" - " java.lang.Iterable values) {\n" - " copyOnWrite();\n" - " instance.addAll$capitalized_name$Value(values);\n" - " return this;\n" - "}\n"); + WriteFieldEnumValueAccessorDocComment(printer, descriptor_, + LIST_MULTI_ADDER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n" + " java.lang.Iterable values) {\n" + " copyOnWrite();\n" + " instance.addAll$capitalized_name$Value(values);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } } -void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - // noop for enums -} - -void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateInitializationCode(io::Printer* printer) const { +void RepeatedImmutableEnumFieldLiteGenerator::GenerateInitializationCode( + io::Printer* printer) const { printer->Print(variables_, "$name$_ = emptyIntList();\n"); } -void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_= visitor.visitIntList($name$_, other.$name$_);\n"); -} - -void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_.makeImmutable();\n"); -} - -void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - // Read and store the enum - printer->Print(variables_, - "if (!$is_mutable$) {\n" - " $name$_ =\n" - " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" - "}\n"); - - if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print(variables_, - "$name$_.addInt(input.readEnum());\n"); - } else { - printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "$type$ value = $type$.forNumber(rawValue);\n" - "if (value == null) {\n" - // We store the unknown value in unknown fields. - " super.mergeVarintField($number$, rawValue);\n" - "} else {\n" - " $name$_.addInt(rawValue);\n" - "}\n"); - } -} - -void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateParsingCodeFromPacked(io::Printer* printer) const { - printer->Print(variables_, - "if (!$is_mutable$) {\n" - " $name$_ =\n" - " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" - "}\n"); - - printer->Print(variables_, - "int length = input.readRawVarint32();\n" - "int oldLimit = input.pushLimit(length);\n" - "while(input.getBytesUntilLimit() > 0) {\n"); - printer->Indent(); - - // Read and store the enum - if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print(variables_, - "$name$_.addInt(input.readEnum());\n"); - } else { - printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "$type$ value = $type$.forNumber(rawValue);\n" - "if (value == null) {\n" - // We store the unknown value in unknown fields. - " super.mergeVarintField($number$, rawValue);\n" - "} else {\n" - " $name$_.addInt(rawValue);\n" - "}\n"); - } - - printer->Outdent(); - printer->Print(variables_, - "}\n" - "input.popLimit(oldLimit);\n"); -} - -void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_mutable$) {\n" - " $name$_.makeImmutable();\n" - "}\n"); -} - -void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - if (descriptor_->is_packed()) { - printer->Print(variables_, - "if (get$capitalized_name$List().size() > 0) {\n" - " output.writeUInt32NoTag($tag$);\n" - " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n" - "}\n" - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeEnumNoTag($name$_.getInt(i));\n" - "}\n"); - } else { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeEnum($number$, $name$_.getInt(i));\n" - "}\n"); - } -} - -void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "{\n" - " int dataSize = 0;\n"); - printer->Indent(); - - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " dataSize += com.google.protobuf.CodedOutputStream\n" - " .computeEnumSizeNoTag($name$_.getInt(i));\n" - "}\n"); - printer->Print( - "size += dataSize;\n"); - if (descriptor_->is_packed()) { - printer->Print(variables_, - "if (!get$capitalized_name$List().isEmpty()) {" - " size += $tag_size$;\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeUInt32SizeNoTag(dataSize);\n" - "}"); - } else { - printer->Print(variables_, - "size += $tag_size$ * $name$_.size();\n"); - } - - // cache the data size for packed fields. - if (descriptor_->is_packed()) { - printer->Print(variables_, - "$name$MemoizedSerializedSize = dataSize;\n"); - } - - printer->Outdent(); - printer->Print("}\n"); -} - -void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && $name$_.equals(other.$name$_);\n"); -} - -void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "if (get$capitalized_name$Count() > 0) {\n" - " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + $name$_.hashCode();\n" - "}\n"); -} - -string RepeatedImmutableEnumFieldLiteGenerator::GetBoxedType() const { +std::string RepeatedImmutableEnumFieldLiteGenerator::GetBoxedType() const { return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); } diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.h b/src/google/protobuf/compiler/java/java_enum_field_lite.h index fa004720fd6f8..b5e9807728fc4 100644 --- a/src/google/protobuf/compiler/java/java_enum_field_lite.h +++ b/src/google/protobuf/compiler/java/java_enum_field_lite.h @@ -41,49 +41,43 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: - explicit ImmutableEnumFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context); ~ImmutableEnumFieldLiteGenerator(); - // implements ImmutableFieldLiteGenerator ------------------------------------ + // implements ImmutableFieldLiteGenerator + // ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; - - string GetBoxedType() const; + void GenerateFieldInfo(io::Printer* printer, + std::vector* output) const; + + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map variables_; + std::map variables_; const int messageBitIndex_; - const int builderBitIndex_; Context* context_; ClassNameResolver* name_resolver_; @@ -94,19 +88,14 @@ class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator { class ImmutableEnumOneofFieldLiteGenerator : public ImmutableEnumFieldLiteGenerator { public: - ImmutableEnumOneofFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutableEnumOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, Context* context); ~ImmutableEnumOneofFieldLiteGenerator(); void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; + void GenerateFieldInfo(io::Printer* printer, + std::vector* output) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldLiteGenerator); @@ -116,35 +105,23 @@ class RepeatedImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: explicit RepeatedImmutableEnumFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + const FieldDescriptor* descriptor, int messageBitIndex, Context* context); ~RepeatedImmutableEnumFieldLiteGenerator(); // implements ImmutableFieldLiteGenerator ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingCodeFromPacked(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; - - string GetBoxedType() const; + void GenerateFieldInfo(io::Printer* printer, + std::vector* output) const; + + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map variables_; - const int messageBitIndex_; - const int builderBitIndex_; + std::map variables_; Context* context_; ClassNameResolver* name_resolver_; @@ -154,6 +131,6 @@ class RepeatedImmutableEnumFieldLiteGenerator } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_enum_lite.cc b/src/google/protobuf/compiler/java/java_enum_lite.cc index ab3b332345715..aa64c97127a55 100644 --- a/src/google/protobuf/compiler/java/java_enum_lite.cc +++ b/src/google/protobuf/compiler/java/java_enum_lite.cc @@ -36,13 +36,14 @@ #include #include -#include #include +#include #include #include -#include #include +#include #include +#include namespace google { namespace protobuf { @@ -58,7 +59,7 @@ EnumLiteGenerator::EnumLiteGenerator(const EnumDescriptor* descriptor, for (int i = 0; i < descriptor_->value_count(); i++) { const EnumValueDescriptor* value = descriptor_->value(i); const EnumValueDescriptor* canonical_value = - descriptor_->FindValueByNumber(value->number()); + descriptor_->FindValueByNumber(value->number()); if (value == canonical_value) { canonical_values_.push_back(value); @@ -77,22 +78,22 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { WriteEnumDocComment(printer, descriptor_); MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_); printer->Print( - "public enum $classname$\n" + "$deprecation$public enum $classname$\n" " implements com.google.protobuf.Internal.EnumLite {\n", - "classname", descriptor_->name()); + "classname", descriptor_->name(), "deprecation", + descriptor_->options().deprecated() ? "@java.lang.Deprecated " : ""); printer->Annotate("classname", descriptor_); printer->Indent(); for (int i = 0; i < canonical_values_.size(); i++) { - std::map vars; + std::map vars; vars["name"] = canonical_values_[i]->name(); - vars["number"] = SimpleItoa(canonical_values_[i]->number()); + vars["number"] = StrCat(canonical_values_[i]->number()); WriteEnumValueDocComment(printer, canonical_values_[i]); if (canonical_values_[i]->options().deprecated()) { printer->Print("@java.lang.Deprecated\n"); } - printer->Print(vars, - "$name$($number$),\n"); + printer->Print(vars, "$name$($number$),\n"); printer->Annotate("name", canonical_values_[i]); } @@ -102,31 +103,35 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { } printer->Print( - ";\n" - "\n"); + ";\n" + "\n"); // ----------------------------------------------------------------- for (int i = 0; i < aliases_.size(); i++) { - std::map vars; + std::map vars; vars["classname"] = descriptor_->name(); vars["name"] = aliases_[i].value->name(); vars["canonical_name"] = aliases_[i].canonical_value->name(); WriteEnumValueDocComment(printer, aliases_[i].value); - printer->Print(vars, - "public static final $classname$ $name$ = $canonical_name$;\n"); + printer->Print( + vars, "public static final $classname$ $name$ = $canonical_name$;\n"); printer->Annotate("name", aliases_[i].value); } for (int i = 0; i < descriptor_->value_count(); i++) { - std::map vars; + std::map vars; vars["name"] = descriptor_->value(i)->name(); - vars["number"] = SimpleItoa(descriptor_->value(i)->number()); + vars["number"] = StrCat(descriptor_->value(i)->number()); vars["{"] = ""; vars["}"] = ""; + vars["deprecation"] = descriptor_->value(i)->options().deprecated() + ? "@java.lang.Deprecated " + : ""; WriteEnumValueDocComment(printer, descriptor_->value(i)); printer->Print(vars, - "public static final int ${$$name$_VALUE$}$ = $number$;\n"); + "$deprecation$public static final int ${$$name$_VALUE$}$ = " + "$number$;\n"); printer->Annotate("{", "}", descriptor_->value(i)); } printer->Print("\n"); @@ -135,6 +140,7 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { printer->Print( "\n" + "@java.lang.Override\n" "public final int getNumber() {\n"); if (SupportUnknownEnumValue(descriptor_->file())) { printer->Print( @@ -148,6 +154,8 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { "}\n" "\n" "/**\n" + " * @param value The number of the enum to look for.\n" + " * @return The enum associated with the given number.\n" " * @deprecated Use {@link #forNumber(int)} instead.\n" " */\n" "@java.lang.Deprecated\n" @@ -162,62 +170,65 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { printer->Indent(); for (int i = 0; i < canonical_values_.size(); i++) { - printer->Print( - "case $number$: return $name$;\n", - "name", canonical_values_[i]->name(), - "number", SimpleItoa(canonical_values_[i]->number())); + printer->Print("case $number$: return $name$;\n", "name", + canonical_values_[i]->name(), "number", + StrCat(canonical_values_[i]->number())); } printer->Outdent(); printer->Outdent(); printer->Print( - " default: return null;\n" - " }\n" - "}\n" - "\n" - "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" - " internalGetValueMap() {\n" - " return internalValueMap;\n" - "}\n" - "private static final com.google.protobuf.Internal.EnumLiteMap<\n" - " $classname$> internalValueMap =\n" - " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" - " public $classname$ findValueByNumber(int number) {\n" - " return $classname$.forNumber(number);\n" - " }\n" - " };\n" - "\n", - "classname", descriptor_->name()); + " default: return null;\n" + " }\n" + "}\n" + "\n" + "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" + " internalGetValueMap() {\n" + " return internalValueMap;\n" + "}\n" + "private static final com.google.protobuf.Internal.EnumLiteMap<\n" + " $classname$> internalValueMap =\n" + " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" + " @java.lang.Override\n" + " public $classname$ findValueByNumber(int number) {\n" + " return $classname$.forNumber(number);\n" + " }\n" + " };\n" + "\n" + "public static com.google.protobuf.Internal.EnumVerifier \n" + " internalGetVerifier() {\n" + " return $classname$Verifier.INSTANCE;\n" + "}\n" + "\n" + "private static final class $classname$Verifier implements \n" + " com.google.protobuf.Internal.EnumVerifier { \n" + " static final com.google.protobuf.Internal.EnumVerifier " + " INSTANCE = new $classname$Verifier();\n" + " @java.lang.Override\n" + " public boolean isInRange(int number) {\n" + " return $classname$.forNumber(number) != null;\n" + " }\n" + " };\n" + "\n", + "classname", descriptor_->name()); printer->Print( - "private final int value;\n\n" - "private $classname$(int value) {\n", - "classname", descriptor_->name()); + "private final int value;\n\n" + "private $classname$(int value) {\n", + "classname", descriptor_->name()); printer->Print( - " this.value = value;\n" - "}\n"); + " this.value = value;\n" + "}\n"); printer->Print( - "\n" - "// @@protoc_insertion_point(enum_scope:$full_name$)\n", - "full_name", descriptor_->full_name()); + "\n" + "// @@protoc_insertion_point(enum_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); printer->Outdent(); printer->Print("}\n\n"); } -bool EnumLiteGenerator::CanUseEnumValues() { - if (canonical_values_.size() != descriptor_->value_count()) { - return false; - } - for (int i = 0; i < descriptor_->value_count(); i++) { - if (descriptor_->value(i)->name() != canonical_values_[i]->name()) { - return false; - } - } - return true; -} - } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_enum_lite.h b/src/google/protobuf/compiler/java/java_enum_lite.h index b7be912cb95e5..50f3fe7b1aac7 100644 --- a/src/google/protobuf/compiler/java/java_enum_lite.h +++ b/src/google/protobuf/compiler/java/java_enum_lite.h @@ -41,17 +41,19 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -67,9 +69,9 @@ class EnumLiteGenerator { private: const EnumDescriptor* descriptor_; - // The proto language allows multiple enum constants to have the same numeric - // value. Java, however, does not allow multiple enum constants to be - // considered equivalent. We treat the first defined constant for any + // The proto language allows multiple enum constants to have the same + // numeric value. Java, however, does not allow multiple enum constants to + // be considered equivalent. We treat the first defined constant for any // given numeric value as "canonical" and the rest as aliases of that // canonical value. std::vector canonical_values_; @@ -85,14 +87,12 @@ class EnumLiteGenerator { Context* context_; ClassNameResolver* name_resolver_; - bool CanUseEnumValues(); - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumLiteGenerator); }; } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc index 9b9be55b424b6..db210fb3e503b 100644 --- a/src/google/protobuf/compiler/java/java_extension.cc +++ b/src/google/protobuf/compiler/java/java_extension.cc @@ -48,11 +48,10 @@ namespace java { ImmutableExtensionGenerator::ImmutableExtensionGenerator( const FieldDescriptor* descriptor, Context* context) - : descriptor_(descriptor), context_(context), - name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { if (descriptor_->extension_scope() != NULL) { - scope_ = name_resolver_->GetImmutableClassName( - descriptor_->extension_scope()); + scope_ = + name_resolver_->GetImmutableClassName(descriptor_->extension_scope()); } else { scope_ = name_resolver_->GetImmutableClassName(descriptor_->file()); } @@ -62,34 +61,36 @@ ImmutableExtensionGenerator::~ImmutableExtensionGenerator() {} // Initializes the vars referenced in the generated code templates. void ExtensionGenerator::InitTemplateVars( - const FieldDescriptor* descriptor, const string& scope, bool immutable, - ClassNameResolver* name_resolver, std::map* vars_pointer) { - std::map &vars = *vars_pointer; + const FieldDescriptor* descriptor, const std::string& scope, bool immutable, + ClassNameResolver* name_resolver, + std::map* vars_pointer) { + std::map& vars = *vars_pointer; vars["scope"] = scope; - vars["name"] = UnderscoresToCamelCase(descriptor); + vars["name"] = UnderscoresToCamelCaseCheckReserved(descriptor); vars["containing_type"] = name_resolver->GetClassName(descriptor->containing_type(), immutable); - vars["number"] = SimpleItoa(descriptor->number()); + vars["number"] = StrCat(descriptor->number()); vars["constant_name"] = FieldConstantName(descriptor); - vars["index"] = SimpleItoa(descriptor->index()); - vars["default"] = descriptor->is_repeated() ? - "" : DefaultValue(descriptor, immutable, name_resolver); + vars["index"] = StrCat(descriptor->index()); + vars["default"] = descriptor->is_repeated() + ? "" + : DefaultValue(descriptor, immutable, name_resolver); vars["type_constant"] = FieldTypeName(GetType(descriptor)); vars["packed"] = descriptor->is_packed() ? "true" : "false"; vars["enum_map"] = "null"; vars["prototype"] = "null"; JavaType java_type = GetJavaType(descriptor); - string singular_type; + std::string singular_type; switch (java_type) { case JAVATYPE_MESSAGE: - singular_type = name_resolver->GetClassName(descriptor->message_type(), - immutable); + singular_type = + name_resolver->GetClassName(descriptor->message_type(), immutable); vars["prototype"] = singular_type + ".getDefaultInstance()"; break; case JAVATYPE_ENUM: - singular_type = name_resolver->GetClassName(descriptor->enum_type(), - immutable); + singular_type = + name_resolver->GetClassName(descriptor->enum_type(), immutable); vars["enum_map"] = singular_type + ".internalGetValueMap()"; break; case JAVATYPE_STRING: @@ -102,18 +103,18 @@ void ExtensionGenerator::InitTemplateVars( singular_type = BoxedPrimitiveTypeName(java_type); break; } - vars["type"] = descriptor->is_repeated() ? - "java.util.List<" + singular_type + ">" : singular_type; + vars["type"] = descriptor->is_repeated() + ? "java.util.List<" + singular_type + ">" + : singular_type; vars["singular_type"] = singular_type; } void ImmutableExtensionGenerator::Generate(io::Printer* printer) { - std::map vars; + std::map vars; const bool kUseImmutableNames = true; InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_, &vars); - printer->Print(vars, - "public static final int $constant_name$ = $number$;\n"); + printer->Print(vars, "public static final int $constant_name$ = $number$;\n"); WriteFieldDocComment(printer, descriptor_); if (descriptor_->extension_scope() == NULL) { @@ -141,6 +142,7 @@ void ImmutableExtensionGenerator::Generate(io::Printer* printer) { " $singular_type$.class,\n" " $prototype$);\n"); } + printer->Annotate("name", descriptor_); } int ImmutableExtensionGenerator::GenerateNonNestedInitializationCode( @@ -150,8 +152,8 @@ int ImmutableExtensionGenerator::GenerateNonNestedInitializationCode( // Only applies to non-nested extensions. printer->Print( "$name$.internalInit(descriptor.getExtensions().get($index$));\n", - "name", UnderscoresToCamelCase(descriptor_), - "index", SimpleItoa(descriptor_->index())); + "name", UnderscoresToCamelCaseCheckReserved(descriptor_), "index", + StrCat(descriptor_->index())); bytecode_estimate += 21; } return bytecode_estimate; @@ -159,10 +161,8 @@ int ImmutableExtensionGenerator::GenerateNonNestedInitializationCode( int ImmutableExtensionGenerator::GenerateRegistrationCode( io::Printer* printer) { - printer->Print( - "registry.add($scope$.$name$);\n", - "scope", scope_, - "name", UnderscoresToCamelCase(descriptor_)); + printer->Print("registry.add($scope$.$name$);\n", "scope", scope_, "name", + UnderscoresToCamelCaseCheckReserved(descriptor_)); return 7; } diff --git a/src/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h index fb8d52015bb03..ab878907712f8 100644 --- a/src/google/protobuf/compiler/java/java_extension.h +++ b/src/google/protobuf/compiler/java/java_extension.h @@ -42,18 +42,20 @@ namespace google { namespace protobuf { - class FieldDescriptor; // descriptor.h - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +class FieldDescriptor; // descriptor.h +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -68,18 +70,19 @@ class ExtensionGenerator { virtual void Generate(io::Printer* printer) = 0; - // Returns an estimate of the number of bytes the printed code will compile to + // Returns an estimate of the number of bytes the printed code will compile + // to virtual int GenerateNonNestedInitializationCode(io::Printer* printer) = 0; - // Returns an estimate of the number of bytes the printed code will compile to + // Returns an estimate of the number of bytes the printed code will compile + // to virtual int GenerateRegistrationCode(io::Printer* printer) = 0; protected: - static void InitTemplateVars(const FieldDescriptor* descriptor, - const string& scope, - bool immutable, - ClassNameResolver* name_resolver, - std::map* vars_pointer); + static void InitTemplateVars( + const FieldDescriptor* descriptor, const std::string& scope, + bool immutable, ClassNameResolver* name_resolver, + std::map* vars_pointer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); @@ -97,9 +100,8 @@ class ImmutableExtensionGenerator : public ExtensionGenerator { protected: const FieldDescriptor* descriptor_; - Context* context_; ClassNameResolver* name_resolver_; - string scope_; + std::string scope_; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionGenerator); @@ -108,6 +110,6 @@ class ImmutableExtensionGenerator : public ExtensionGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__ diff --git a/src/google/protobuf/compiler/java/java_extension_lite.cc b/src/google/protobuf/compiler/java/java_extension_lite.cc index c48c92e9fc7ef..71bf4e23f3cb3 100644 --- a/src/google/protobuf/compiler/java/java_extension_lite.cc +++ b/src/google/protobuf/compiler/java/java_extension_lite.cc @@ -44,11 +44,10 @@ namespace java { ImmutableExtensionLiteGenerator::ImmutableExtensionLiteGenerator( const FieldDescriptor* descriptor, Context* context) - : descriptor_(descriptor), context_(context), - name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { if (descriptor_->extension_scope() != NULL) { - scope_ = name_resolver_->GetImmutableClassName( - descriptor_->extension_scope()); + scope_ = + name_resolver_->GetImmutableClassName(descriptor_->extension_scope()); } else { scope_ = name_resolver_->GetImmutableClassName(descriptor_->file()); } @@ -57,12 +56,11 @@ ImmutableExtensionLiteGenerator::ImmutableExtensionLiteGenerator( ImmutableExtensionLiteGenerator::~ImmutableExtensionLiteGenerator() {} void ImmutableExtensionLiteGenerator::Generate(io::Printer* printer) { - std::map vars; + std::map vars; const bool kUseImmutableNames = true; InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_, &vars); - printer->Print(vars, - "public static final int $constant_name$ = $number$;\n"); + printer->Print(vars, "public static final int $constant_name$ = $number$;\n"); WriteFieldDocComment(printer, descriptor_); if (descriptor_->is_repeated()) { @@ -96,6 +94,7 @@ void ImmutableExtensionLiteGenerator::Generate(io::Printer* printer) { " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" " $singular_type$.class);\n"); } + printer->Annotate("name", descriptor_); } int ImmutableExtensionLiteGenerator::GenerateNonNestedInitializationCode( @@ -105,10 +104,8 @@ int ImmutableExtensionLiteGenerator::GenerateNonNestedInitializationCode( int ImmutableExtensionLiteGenerator::GenerateRegistrationCode( io::Printer* printer) { - printer->Print( - "registry.add($scope$.$name$);\n", - "scope", scope_, - "name", UnderscoresToCamelCase(descriptor_)); + printer->Print("registry.add($scope$.$name$);\n", "scope", scope_, "name", + UnderscoresToCamelCaseCheckReserved(descriptor_)); return 7; } diff --git a/src/google/protobuf/compiler/java/java_extension_lite.h b/src/google/protobuf/compiler/java/java_extension_lite.h index 4cd49bda20fe8..410781dd3326d 100644 --- a/src/google/protobuf/compiler/java/java_extension_lite.h +++ b/src/google/protobuf/compiler/java/java_extension_lite.h @@ -61,9 +61,8 @@ class ImmutableExtensionLiteGenerator : public ExtensionGenerator { private: const FieldDescriptor* descriptor_; - Context* context_; ClassNameResolver* name_resolver_; - string scope_; + std::string scope_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionLiteGenerator); }; @@ -71,6 +70,6 @@ class ImmutableExtensionLiteGenerator : public ExtensionGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc index 1ab1862953a77..2f775a68a66e2 100644 --- a/src/google/protobuf/compiler/java/java_field.cc +++ b/src/google/protobuf/compiler/java/java_field.cc @@ -35,9 +35,6 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include @@ -65,15 +62,16 @@ namespace java { namespace { -ImmutableFieldGenerator* MakeImmutableGenerator( - const FieldDescriptor* field, int messageBitIndex, int builderBitIndex, - Context* context) { +ImmutableFieldGenerator* MakeImmutableGenerator(const FieldDescriptor* field, + int messageBitIndex, + int builderBitIndex, + Context* context) { if (field->is_repeated()) { switch (GetJavaType(field)) { case JAVATYPE_MESSAGE: if (IsMapEntry(field->message_type())) { - return new ImmutableMapFieldGenerator( - field, messageBitIndex, builderBitIndex, context); + return new ImmutableMapFieldGenerator(field, messageBitIndex, + builderBitIndex, context); } else { return new RepeatedImmutableMessageFieldGenerator( field, messageBitIndex, builderBitIndex, context); @@ -89,14 +87,14 @@ ImmutableFieldGenerator* MakeImmutableGenerator( field, messageBitIndex, builderBitIndex, context); } } else { - if (field->containing_oneof()) { + if (IsRealOneof(field)) { switch (GetJavaType(field)) { case JAVATYPE_MESSAGE: return new ImmutableMessageOneofFieldGenerator( field, messageBitIndex, builderBitIndex, context); case JAVATYPE_ENUM: - return new ImmutableEnumOneofFieldGenerator( - field, messageBitIndex, builderBitIndex, context); + return new ImmutableEnumOneofFieldGenerator(field, messageBitIndex, + builderBitIndex, context); case JAVATYPE_STRING: return new ImmutableStringOneofFieldGenerator( field, messageBitIndex, builderBitIndex, context); @@ -107,75 +105,74 @@ ImmutableFieldGenerator* MakeImmutableGenerator( } else { switch (GetJavaType(field)) { case JAVATYPE_MESSAGE: - return new ImmutableMessageFieldGenerator( - field, messageBitIndex, builderBitIndex, context); + return new ImmutableMessageFieldGenerator(field, messageBitIndex, + builderBitIndex, context); case JAVATYPE_ENUM: - return new ImmutableEnumFieldGenerator( - field, messageBitIndex, builderBitIndex, context); + return new ImmutableEnumFieldGenerator(field, messageBitIndex, + builderBitIndex, context); case JAVATYPE_STRING: - return new ImmutableStringFieldGenerator( - field, messageBitIndex, builderBitIndex, context); + return new ImmutableStringFieldGenerator(field, messageBitIndex, + builderBitIndex, context); default: - return new ImmutablePrimitiveFieldGenerator( - field, messageBitIndex, builderBitIndex, context); + return new ImmutablePrimitiveFieldGenerator(field, messageBitIndex, + builderBitIndex, context); } } } } ImmutableFieldLiteGenerator* MakeImmutableLiteGenerator( - const FieldDescriptor* field, int messageBitIndex, int builderBitIndex, - Context* context) { + const FieldDescriptor* field, int messageBitIndex, Context* context) { if (field->is_repeated()) { switch (GetJavaType(field)) { case JAVATYPE_MESSAGE: if (IsMapEntry(field->message_type())) { - return new ImmutableMapFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + return new ImmutableMapFieldLiteGenerator(field, messageBitIndex, + context); } else { return new RepeatedImmutableMessageFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); } case JAVATYPE_ENUM: return new RepeatedImmutableEnumFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); case JAVATYPE_STRING: return new RepeatedImmutableStringFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); default: return new RepeatedImmutablePrimitiveFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); } } else { - if (field->containing_oneof()) { + if (IsRealOneof(field)) { switch (GetJavaType(field)) { case JAVATYPE_MESSAGE: return new ImmutableMessageOneofFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); case JAVATYPE_ENUM: return new ImmutableEnumOneofFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); case JAVATYPE_STRING: return new ImmutableStringOneofFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); default: return new ImmutablePrimitiveOneofFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); } } else { switch (GetJavaType(field)) { case JAVATYPE_MESSAGE: - return new ImmutableMessageFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + return new ImmutableMessageFieldLiteGenerator(field, messageBitIndex, + context); case JAVATYPE_ENUM: - return new ImmutableEnumFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + return new ImmutableEnumFieldLiteGenerator(field, messageBitIndex, + context); case JAVATYPE_STRING: - return new ImmutableStringFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + return new ImmutableStringFieldLiteGenerator(field, messageBitIndex, + context); default: return new ImmutablePrimitiveFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); } } } @@ -196,27 +193,19 @@ static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) { ImmutableFieldGenerator::~ImmutableFieldGenerator() {} -void ImmutableFieldGenerator:: -GenerateParsingCodeFromPacked(io::Printer* printer) const { +void ImmutableFieldGenerator::GenerateParsingCodeFromPacked( + io::Printer* printer) const { ReportUnexpectedPackedFieldsCall(printer); } ImmutableFieldLiteGenerator::~ImmutableFieldLiteGenerator() {} -void ImmutableFieldLiteGenerator:: -GenerateParsingCodeFromPacked(io::Printer* printer) const { - ReportUnexpectedPackedFieldsCall(printer); -} - // =================================================================== template <> FieldGeneratorMap::FieldGeneratorMap( const Descriptor* descriptor, Context* context) - : descriptor_(descriptor), - field_generators_(new google::protobuf::scoped_ptr< - ImmutableFieldGenerator>[descriptor->field_count()]) { - + : descriptor_(descriptor), field_generators_(descriptor->field_count()) { // Construct all the FieldGenerators and assign them bit indices for their // bit fields. int messageBitIndex = 0; @@ -230,42 +219,39 @@ FieldGeneratorMap::FieldGeneratorMap( } } -template<> +template <> FieldGeneratorMap::~FieldGeneratorMap() {} template <> FieldGeneratorMap::FieldGeneratorMap( const Descriptor* descriptor, Context* context) - : descriptor_(descriptor), - field_generators_(new google::protobuf::scoped_ptr< - ImmutableFieldLiteGenerator>[descriptor->field_count()]) { + : descriptor_(descriptor), field_generators_(descriptor->field_count()) { // Construct all the FieldGenerators and assign them bit indices for their // bit fields. int messageBitIndex = 0; - int builderBitIndex = 0; for (int i = 0; i < descriptor->field_count(); i++) { ImmutableFieldLiteGenerator* generator = MakeImmutableLiteGenerator( - descriptor->field(i), messageBitIndex, builderBitIndex, context); + descriptor->field(i), messageBitIndex, context); field_generators_[i].reset(generator); messageBitIndex += generator->GetNumBitsForMessage(); - builderBitIndex += generator->GetNumBitsForBuilder(); } } -template<> +template <> FieldGeneratorMap::~FieldGeneratorMap() {} void SetCommonFieldVariables(const FieldDescriptor* descriptor, const FieldGeneratorInfo* info, - std::map* variables) { + std::map* variables) { (*variables)["field_name"] = descriptor->name(); (*variables)["name"] = info->name; (*variables)["classname"] = descriptor->containing_type()->name(); (*variables)["capitalized_name"] = info->capitalized_name; (*variables)["disambiguated_reason"] = info->disambiguated_reason; (*variables)["constant_name"] = FieldConstantName(descriptor); - (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["number"] = StrCat(descriptor->number()); + (*variables)["kt_dsl_builder"] = "_builder"; // These variables are placeholders to pick out the beginning and ends of // identifiers for annotations (when doing so with existing variables would // be ambiguous or impossible). They should never be set to anything but the @@ -276,22 +262,22 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, void SetCommonOneofVariables(const FieldDescriptor* descriptor, const OneofGeneratorInfo* info, - std::map* variables) { + std::map* variables) { (*variables)["oneof_name"] = info->name; (*variables)["oneof_capitalized_name"] = info->capitalized_name; (*variables)["oneof_index"] = - SimpleItoa(descriptor->containing_oneof()->index()); - (*variables)["set_oneof_case_message"] = info->name + - "Case_ = " + SimpleItoa(descriptor->number()); - (*variables)["clear_oneof_case_message"] = info->name + - "Case_ = 0"; - (*variables)["has_oneof_case_message"] = info->name + - "Case_ == " + SimpleItoa(descriptor->number()); + StrCat(descriptor->containing_oneof()->index()); + (*variables)["oneof_stored_type"] = GetOneofStoredType(descriptor); + (*variables)["set_oneof_case_message"] = + info->name + "Case_ = " + StrCat(descriptor->number()); + (*variables)["clear_oneof_case_message"] = info->name + "Case_ = 0"; + (*variables)["has_oneof_case_message"] = + info->name + "Case_ == " + StrCat(descriptor->number()); } -void PrintExtraFieldInfo(const std::map& variables, +void PrintExtraFieldInfo(const std::map& variables, io::Printer* printer) { - const std::map::const_iterator it = + const std::map::const_iterator it = variables.find("disambiguated_reason"); if (it != variables.end() && !it->second.empty()) { printer->Print( diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h index cc1d83d9815db..9d04dc8455e14 100644 --- a/src/google/protobuf/compiler/java/java_field.h +++ b/src/google/protobuf/compiler/java/java_field.h @@ -37,28 +37,27 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include +#include #include #include -#include namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -82,13 +81,13 @@ class ImmutableFieldGenerator { virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0; virtual void GenerateSerializationCode(io::Printer* printer) const = 0; virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; - virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer) - const = 0; + virtual void GenerateFieldBuilderInitializationCode( + io::Printer* printer) const = 0; virtual void GenerateEqualsCode(io::Printer* printer) const = 0; virtual void GenerateHashCode(io::Printer* printer) const = 0; - virtual string GetBoxedType() const = 0; + virtual std::string GetBoxedType() const = 0; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldGenerator); @@ -100,27 +99,14 @@ class ImmutableFieldLiteGenerator { virtual ~ImmutableFieldLiteGenerator(); virtual int GetNumBitsForMessage() const = 0; - virtual int GetNumBitsForBuilder() const = 0; virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0; virtual void GenerateMembers(io::Printer* printer) const = 0; virtual void GenerateBuilderMembers(io::Printer* printer) const = 0; virtual void GenerateInitializationCode(io::Printer* printer) const = 0; - virtual void GenerateVisitCode(io::Printer* printer) const = 0; - virtual void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) - const = 0; - virtual void GenerateParsingCode(io::Printer* printer) const = 0; - virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const; - virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0; - virtual void GenerateSerializationCode(io::Printer* printer) const = 0; - virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; - virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer) - const = 0; - - virtual void GenerateEqualsCode(io::Printer* printer) const = 0; - virtual void GenerateHashCode(io::Printer* printer) const = 0; + virtual void GenerateFieldInfo(io::Printer* printer, + std::vector* output) const = 0; - - virtual string GetBoxedType() const = 0; + virtual std::string GetBoxedType() const = 0; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldLiteGenerator); @@ -128,71 +114,75 @@ class ImmutableFieldLiteGenerator { // Convenience class which constructs FieldGenerators for a Descriptor. -template +template class FieldGeneratorMap { public: - explicit FieldGeneratorMap(const Descriptor* descriptor, - Context* context); + explicit FieldGeneratorMap(const Descriptor* descriptor, Context* context); ~FieldGeneratorMap(); const FieldGeneratorType& get(const FieldDescriptor* field) const; private: const Descriptor* descriptor_; - Context* context_; - ClassNameResolver* name_resolver_; - google::protobuf::scoped_array > field_generators_; + std::vector> field_generators_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); }; -template -inline const FieldGeneratorType& -FieldGeneratorMap::get(const FieldDescriptor* field) const { +template +inline const FieldGeneratorType& FieldGeneratorMap::get( + const FieldDescriptor* field) const { GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); return *field_generators_[field->index()]; } // Instantiate template for mutable and immutable maps. -template<> -FieldGeneratorMap:: -FieldGeneratorMap(const Descriptor* descriptor, - Context* context); +template <> +FieldGeneratorMap::FieldGeneratorMap( + const Descriptor* descriptor, Context* context); -template<> +template <> FieldGeneratorMap::~FieldGeneratorMap(); +template <> +FieldGeneratorMap::FieldGeneratorMap( + const Descriptor* descriptor, Context* context); + +template <> +FieldGeneratorMap::~FieldGeneratorMap(); + + // Field information used in FieldGeneartors. struct FieldGeneratorInfo { - string name; - string capitalized_name; - string disambiguated_reason; + std::string name; + std::string capitalized_name; + std::string disambiguated_reason; }; // Oneof information used in OneofFieldGenerators. struct OneofGeneratorInfo { - string name; - string capitalized_name; + std::string name; + std::string capitalized_name; }; // Set some common variables used in variable FieldGenerators. void SetCommonFieldVariables(const FieldDescriptor* descriptor, const FieldGeneratorInfo* info, - std::map* variables); + std::map* variables); // Set some common oneof variables used in OneofFieldGenerators. void SetCommonOneofVariables(const FieldDescriptor* descriptor, const OneofGeneratorInfo* info, - std::map* variables); + std::map* variables); // Print useful comments before a field's accessors. -void PrintExtraFieldInfo(const std::map& variables, +void PrintExtraFieldInfo(const std::map& variables, io::Printer* printer); } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc index 2d5465ba2da9c..5cdb00d5c1373 100644 --- a/src/google/protobuf/compiler/java/java_file.cc +++ b/src/google/protobuf/compiler/java/java_file.cc @@ -35,9 +35,6 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include @@ -51,9 +48,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -65,26 +62,26 @@ namespace java { namespace { struct FieldDescriptorCompare { - bool operator ()(const FieldDescriptor* f1, const FieldDescriptor* f2) const { - if(f1 == NULL) { + bool operator()(const FieldDescriptor* f1, const FieldDescriptor* f2) const { + if (f1 == NULL) { return false; } - if(f2 == NULL) { + if (f2 == NULL) { return true; } return f1->full_name() < f2->full_name(); } }; -typedef std::set FieldDescriptorSet; +typedef std::set + FieldDescriptorSet; // Recursively searches the given message to collect extensions. // Returns true if all the extensions can be recognized. The extensions will be // appended in to the extensions parameter. // Returns false when there are unknown fields, in which case the data in the // extensions output parameter is not reliable and should be discarded. -bool CollectExtensions(const Message& message, - FieldDescriptorSet* extensions) { +bool CollectExtensions(const Message& message, FieldDescriptorSet* extensions) { const Reflection* reflection = message.GetReflection(); // There are unknown fields that could be extensions, thus this call fails. @@ -94,14 +91,16 @@ bool CollectExtensions(const Message& message, reflection->ListFields(message, &fields); for (int i = 0; i < fields.size(); i++) { - if (fields[i]->is_extension()) extensions->insert(fields[i]); + if (fields[i]->is_extension()) { + extensions->insert(fields[i]); + } if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) { if (fields[i]->is_repeated()) { int size = reflection->FieldSize(message, fields[i]); for (int j = 0; j < size; j++) { const Message& sub_message = - reflection->GetRepeatedMessage(message, fields[i], j); + reflection->GetRepeatedMessage(message, fields[i], j); if (!CollectExtensions(sub_message, extensions)) return false; } } else { @@ -122,7 +121,7 @@ bool CollectExtensions(const Message& message, void CollectExtensions(const FileDescriptorProto& file_proto, const DescriptorPool& alternate_pool, FieldDescriptorSet* extensions, - const string& file_data) { + const std::string& file_data) { if (!CollectExtensions(file_proto, extensions)) { // There are unknown fields in the file_proto, which are probably // extensions. We need to parse the data into a dynamic message based on the @@ -136,7 +135,7 @@ void CollectExtensions(const FileDescriptorProto& file_proto, "descriptor.proto is not in the transitive dependencies. " "This normally should not happen. Please report a bug."; DynamicMessageFactory factory; - google::protobuf::scoped_ptr dynamic_file_proto( + std::unique_ptr dynamic_file_proto( factory.GetPrototype(file_proto_desc)->New()); GOOGLE_CHECK(dynamic_file_proto.get() != NULL); GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data)); @@ -162,11 +161,9 @@ void CollectExtensions(const FileDescriptorProto& file_proto, // extend our methods by simply chaining them to another method // with a tail call. This inserts the sequence call-next-method, // end this one, begin-next-method as needed. -void MaybeRestartJavaMethod(io::Printer* printer, - int *bytecode_estimate, - int *method_num, - const char *chain_statement, - const char *method_decl) { +void MaybeRestartJavaMethod(io::Printer* printer, int* bytecode_estimate, + int* method_num, const char* chain_statement, + const char* method_decl) { // The goal here is to stay under 64K bytes of jvm bytecode/method, // since otherwise we hit a hardcoded limit in the jvm and javac will // then fail with the error "code too large". This limit lets our @@ -175,10 +172,10 @@ void MaybeRestartJavaMethod(io::Printer* printer, if ((*bytecode_estimate) > bytesPerMethod) { ++(*method_num); - printer->Print(chain_statement, "method_num", SimpleItoa(*method_num)); + printer->Print(chain_statement, "method_num", StrCat(*method_num)); printer->Outdent(); printer->Print("}\n"); - printer->Print(method_decl, "method_num", SimpleItoa(*method_num)); + printer->Print(method_decl, "method_num", StrCat(*method_num)); printer->Indent(); *bytecode_estimate = 0; } @@ -189,17 +186,14 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options, bool immutable_api) : file_(file), java_package_(FileJavaPackage(file, immutable_api)), - message_generators_( - new google::protobuf::scoped_ptr[file->message_type_count()]), - extension_generators_( - new google::protobuf::scoped_ptr[file->extension_count()]), + message_generators_(file->message_type_count()), + extension_generators_(file->extension_count()), context_(new Context(file, options)), name_resolver_(context_->GetNameResolver()), options_(options), immutable_api_(immutable_api) { classname_ = name_resolver_->GetFileClassName(file, immutable_api); - generator_factory_.reset( - new ImmutableGeneratorFactory(context_.get())); + generator_factory_.reset(new ImmutableGeneratorFactory(context_.get())); for (int i = 0; i < file_->message_type_count(); ++i) { message_generators_[i].reset( generator_factory_->NewMessageGenerator(file_->message_type(i))); @@ -212,22 +206,50 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options, FileGenerator::~FileGenerator() {} -bool FileGenerator::Validate(string* error) { +bool FileGenerator::Validate(std::string* error) { // Check that no class name matches the file's class name. This is a common // problem that leads to Java compile errors that can be hard to understand. // It's especially bad when using the java_multiple_files, since we would // end up overwriting the outer class with one of the inner ones. - if (name_resolver_->HasConflictingClassName(file_, classname_)) { + if (name_resolver_->HasConflictingClassName(file_, classname_, + NameEquality::EXACT_EQUAL)) { error->assign(file_->name()); error->append( - ": Cannot generate Java output because the file's outer class name, \""); + ": Cannot generate Java output because the file's outer class name, " + "\""); error->append(classname_); error->append( - "\", matches the name of one of the types declared inside it. " - "Please either rename the type or use the java_outer_classname " - "option to specify a different outer class name for the .proto file."); + "\", matches the name of one of the types declared inside it. " + "Please either rename the type or use the java_outer_classname " + "option to specify a different outer class name for the .proto file."); return false; } + // Similar to the check above, but ignore the case this time. This is not a + // problem on Linux, but will lead to Java compile errors on Windows / Mac + // because filenames are case-insensitive on those platforms. + if (name_resolver_->HasConflictingClassName( + file_, classname_, NameEquality::EQUAL_IGNORE_CASE)) { + GOOGLE_LOG(WARNING) + << file_->name() << ": The file's outer class name, \"" << classname_ + << "\", matches the name of one of the types declared inside it when " + << "case is ignored. This can cause compilation issues on Windows / " + << "MacOS. Please either rename the type or use the " + << "java_outer_classname option to specify a different outer class " + << "name for the .proto file to be safe."; + } + + // Print a warning if optimize_for = LITE_RUNTIME is used. + if (file_->options().optimize_for() == FileOptions::LITE_RUNTIME && + !options_.enforce_lite) { + GOOGLE_LOG(WARNING) + << "The optimize_for = LITE_RUNTIME option is no longer supported by " + << "protobuf Java code generator and is ignored--protoc will always " + << "generate full runtime code for Java. To use Java Lite runtime, " + << "users should use the Java Lite plugin instead. See:\n" + << " " + "https://github.com/protocolbuffers/protobuf/blob/master/java/" + "lite.md"; + } return true; } @@ -235,21 +257,24 @@ void FileGenerator::Generate(io::Printer* printer) { // We don't import anything because we refer to all classes by their // fully-qualified names in the generated source. printer->Print( - "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "// source: $filename$\n" - "\n", - "filename", file_->name()); + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n", + "filename", file_->name()); if (!java_package_.empty()) { printer->Print( - "package $package$;\n" - "\n", - "package", java_package_); + "package $package$;\n" + "\n", + "package", java_package_); } PrintGeneratedAnnotation( printer, '$', options_.annotate_code ? classname_ + ".java.pb.meta" : ""); + printer->Print( - "public final class $classname$ {\n" + "$deprecation$public final class $classname$ {\n" " private $ctor$() {}\n", + "deprecation", + file_->options().deprecated() ? "@java.lang.Deprecated " : "", "classname", classname_, "ctor", classname_); printer->Annotate("classname", file_->name()); printer->Indent(); @@ -257,8 +282,8 @@ void FileGenerator::Generate(io::Printer* printer) { // ----------------------------------------------------------------- printer->Print( - "public static void registerAllExtensions(\n" - " com.google.protobuf.ExtensionRegistryLite registry) {\n"); + "public static void registerAllExtensions(\n" + " com.google.protobuf.ExtensionRegistryLite registry) {\n"); printer->Indent(); @@ -271,8 +296,7 @@ void FileGenerator::Generate(io::Printer* printer) { } printer->Outdent(); - printer->Print( - "}\n"); + printer->Print("}\n"); if (HasDescriptorMethods(file_, context_->EnforceLite())) { // Overload registerAllExtensions for the non-lite usage to // redundantly maintain the original signature (this is @@ -280,12 +304,12 @@ void FileGenerator::Generate(io::Printer* printer) { // ExtensionRegistry in the non-lite usage). Intent is // to remove this in the future. printer->Print( - "\n" - "public static void registerAllExtensions(\n" - " com.google.protobuf.ExtensionRegistry registry) {\n" - " registerAllExtensions(\n" - " (com.google.protobuf.ExtensionRegistryLite) registry);\n" - "}\n"); + "\n" + "public static void registerAllExtensions(\n" + " com.google.protobuf.ExtensionRegistry registry) {\n" + " registerAllExtensions(\n" + " (com.google.protobuf.ExtensionRegistryLite) registry);\n" + "}\n"); } // ----------------------------------------------------------------- @@ -306,7 +330,7 @@ void FileGenerator::Generate(io::Printer* printer) { } if (HasGenericServices(file_, context_->EnforceLite())) { for (int i = 0; i < file_->service_count(); i++) { - google::protobuf::scoped_ptr generator( + std::unique_ptr generator( generator_factory_->NewServiceGenerator(file_->service(i))); generator->Generate(printer); } @@ -337,29 +361,27 @@ void FileGenerator::Generate(io::Printer* printer) { GenerateDescriptorInitializationCodeForMutable(printer); } } else { - printer->Print( - "static {\n"); + printer->Print("static {\n"); printer->Indent(); int bytecode_estimate = 0; int method_num = 0; for (int i = 0; i < file_->message_type_count(); i++) { - bytecode_estimate += message_generators_[i]->GenerateStaticVariableInitializers(printer); + bytecode_estimate += + message_generators_[i]->GenerateStaticVariableInitializers(printer); MaybeRestartJavaMethod( - printer, - &bytecode_estimate, &method_num, - "_clinit_autosplit_$method_num$();\n", - "private static void _clinit_autosplit_$method_num$() {\n"); + printer, &bytecode_estimate, &method_num, + "_clinit_autosplit_$method_num$();\n", + "private static void _clinit_autosplit_$method_num$() {\n"); } printer->Outdent(); - printer->Print( - "}\n"); + printer->Print("}\n"); } printer->Print( - "\n" - "// @@protoc_insertion_point(outer_class_scope)\n"); + "\n" + "// @@protoc_insertion_point(outer_class_scope)\n"); printer->Outdent(); printer->Print("}\n"); @@ -368,15 +390,15 @@ void FileGenerator::Generate(io::Printer* printer) { void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( io::Printer* printer) { printer->Print( - "public static com.google.protobuf.Descriptors.FileDescriptor\n" - " getDescriptor() {\n" - " return descriptor;\n" - "}\n" - "private static $final$ com.google.protobuf.Descriptors.FileDescriptor\n" - " descriptor;\n" - "static {\n", - // TODO(dweis): Mark this as final. - "final", ""); + "public static com.google.protobuf.Descriptors.FileDescriptor\n" + " getDescriptor() {\n" + " return descriptor;\n" + "}\n" + "private static $final$ com.google.protobuf.Descriptors.FileDescriptor\n" + " descriptor;\n" + "static {\n", + // TODO(dweis): Mark this as final. + "final", ""); printer->Indent(); SharedCodeGenerator shared_code_generator(file_, options_); @@ -386,20 +408,20 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( int method_num = 0; for (int i = 0; i < file_->message_type_count(); i++) { - bytecode_estimate += message_generators_[i]->GenerateStaticVariableInitializers(printer); + bytecode_estimate += + message_generators_[i]->GenerateStaticVariableInitializers(printer); MaybeRestartJavaMethod( - printer, - &bytecode_estimate, &method_num, - "_clinit_autosplit_dinit_$method_num$();\n", - "private static void _clinit_autosplit_dinit_$method_num$() {\n"); + printer, &bytecode_estimate, &method_num, + "_clinit_autosplit_dinit_$method_num$();\n", + "private static void _clinit_autosplit_dinit_$method_num$() {\n"); } for (int i = 0; i < file_->extension_count(); i++) { - bytecode_estimate += extension_generators_[i]->GenerateNonNestedInitializationCode(printer); + bytecode_estimate += + extension_generators_[i]->GenerateNonNestedInitializationCode(printer); MaybeRestartJavaMethod( - printer, - &bytecode_estimate, &method_num, - "_clinit_autosplit_dinit_$method_num$();\n", - "private static void _clinit_autosplit_dinit_$method_num$() {\n"); + printer, &bytecode_estimate, &method_num, + "_clinit_autosplit_dinit_$method_num$();\n", + "private static void _clinit_autosplit_dinit_$method_num$() {\n"); } // Proto compiler builds a DescriptorPool, which holds all the descriptors to @@ -419,7 +441,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( // reflections to find all extension fields FileDescriptorProto file_proto; file_->CopyTo(&file_proto); - string file_data; + std::string file_data; file_proto.SerializeToString(&file_data); FieldDescriptorSet extensions; CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); @@ -428,56 +450,54 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( // Must construct an ExtensionRegistry containing all existing extensions // and use it to parse the descriptor data again to recognize extensions. printer->Print( - "com.google.protobuf.ExtensionRegistry registry =\n" - " com.google.protobuf.ExtensionRegistry.newInstance();\n"); + "com.google.protobuf.ExtensionRegistry registry =\n" + " com.google.protobuf.ExtensionRegistry.newInstance();\n"); FieldDescriptorSet::iterator it; for (it = extensions.begin(); it != extensions.end(); it++) { - google::protobuf::scoped_ptr generator( + std::unique_ptr generator( generator_factory_->NewExtensionGenerator(*it)); bytecode_estimate += generator->GenerateRegistrationCode(printer); MaybeRestartJavaMethod( - printer, - &bytecode_estimate, &method_num, - "_clinit_autosplit_dinit_$method_num$(registry);\n", - "private static void _clinit_autosplit_dinit_$method_num$(\n" - " com.google.protobuf.ExtensionRegistry registry) {\n"); + printer, &bytecode_estimate, &method_num, + "_clinit_autosplit_dinit_$method_num$(registry);\n", + "private static void _clinit_autosplit_dinit_$method_num$(\n" + " com.google.protobuf.ExtensionRegistry registry) {\n"); } printer->Print( - "com.google.protobuf.Descriptors.FileDescriptor\n" - " .internalUpdateFileDescriptor(descriptor, registry);\n"); + "com.google.protobuf.Descriptors.FileDescriptor\n" + " .internalUpdateFileDescriptor(descriptor, registry);\n"); } // Force descriptor initialization of all dependencies. for (int i = 0; i < file_->dependency_count(); i++) { if (ShouldIncludeDependency(file_->dependency(i), true)) { - string dependency = + std::string dependency = name_resolver_->GetImmutableClassName(file_->dependency(i)); - printer->Print( - "$dependency$.getDescriptor();\n", - "dependency", dependency); + printer->Print("$dependency$.getDescriptor();\n", "dependency", + dependency); } } printer->Outdent(); - printer->Print( - "}\n"); + printer->Print("}\n"); } -void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer* printer) { +void FileGenerator::GenerateDescriptorInitializationCodeForMutable( + io::Printer* printer) { printer->Print( - "public static com.google.protobuf.Descriptors.FileDescriptor\n" - " getDescriptor() {\n" - " return descriptor;\n" - "}\n" - "private static final com.google.protobuf.Descriptors.FileDescriptor\n" - " descriptor;\n" - "static {\n"); + "public static com.google.protobuf.Descriptors.FileDescriptor\n" + " getDescriptor() {\n" + " return descriptor;\n" + "}\n" + "private static final com.google.protobuf.Descriptors.FileDescriptor\n" + " descriptor;\n" + "static {\n"); printer->Indent(); printer->Print( - "descriptor = $immutable_package$.$descriptor_classname$.descriptor;\n", - "immutable_package", FileJavaPackage(file_, true), - "descriptor_classname", name_resolver_->GetDescriptorClassName(file_)); + "descriptor = $immutable_package$.$descriptor_classname$.descriptor;\n", + "immutable_package", FileJavaPackage(file_, true), "descriptor_classname", + name_resolver_->GetDescriptorClassName(file_)); for (int i = 0; i < file_->message_type_count(); i++) { message_generators_[i]->GenerateStaticVariableInitializers(printer); @@ -490,7 +510,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer* // custom options are only represented with immutable messages. FileDescriptorProto file_proto; file_->CopyTo(&file_proto); - string file_data; + std::string file_data; file_proto.SerializeToString(&file_data); FieldDescriptorSet extensions; CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); @@ -504,7 +524,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer* // we want the mutable code to be independent from the immutable code // at compile time. It is required to implement dual-compile for // mutable and immutable API in blaze. - " java.lang.Class immutableClass = java.lang.Class.forName(\n" + " java.lang.Class immutableClass = java.lang.Class.forName(\n" " \"$immutable_classname$\");\n" "} catch (java.lang.ClassNotFoundException e) {\n", "immutable_classname", name_resolver_->GetImmutableClassName(file_)); @@ -519,7 +539,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer* FieldDescriptorSet::iterator it; for (it = extensions.begin(); it != extensions.end(); it++) { const FieldDescriptor* field = *it; - string scope; + std::string scope; if (field->extension_scope() != NULL) { scope = name_resolver_->GetMutableClassName(field->extension_scope()) + ".getDescriptor()"; @@ -537,11 +557,11 @@ void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer* " $scope$.getExtensions().get($index$),\n" " (com.google.protobuf.Message) defaultExtensionInstance);\n" "}\n", - "scope", scope, "index", SimpleItoa(field->index()), "class", + "scope", scope, "index", StrCat(field->index()), "class", name_resolver_->GetImmutableClassName(field->message_type())); } else { printer->Print("registry.add($scope$.getExtensions().get($index$));\n", - "scope", scope, "index", SimpleItoa(field->index())); + "scope", scope, "index", StrCat(field->index())); } } printer->Print( @@ -555,66 +575,63 @@ void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer* // Force descriptor initialization of all dependencies. for (int i = 0; i < file_->dependency_count(); i++) { if (ShouldIncludeDependency(file_->dependency(i), false)) { - string dependency = name_resolver_->GetMutableClassName( - file_->dependency(i)); - printer->Print( - "$dependency$.getDescriptor();\n", - "dependency", dependency); + std::string dependency = + name_resolver_->GetMutableClassName(file_->dependency(i)); + printer->Print("$dependency$.getDescriptor();\n", "dependency", + dependency); } } printer->Outdent(); - printer->Print( - "}\n"); + printer->Print("}\n"); } template -static void GenerateSibling(const string& package_dir, - const string& java_package, - const DescriptorClass* descriptor, - GeneratorContext* context, - std::vector* file_list, bool annotate_code, - std::vector* annotation_list, - const string& name_suffix, - GeneratorClass* generator, - void (GeneratorClass::*pfn)(io::Printer* printer)) { - string filename = package_dir + descriptor->name() + name_suffix + ".java"; +static void GenerateSibling( + const std::string& package_dir, const std::string& java_package, + const DescriptorClass* descriptor, GeneratorContext* context, + std::vector* file_list, bool annotate_code, + std::vector* annotation_list, const std::string& name_suffix, + GeneratorClass* generator, + void (GeneratorClass::*pfn)(io::Printer* printer)) { + std::string filename = + package_dir + descriptor->name() + name_suffix + ".java"; file_list->push_back(filename); - string info_full_path = filename + ".pb.meta"; + std::string info_full_path = filename + ".pb.meta"; GeneratedCodeInfo annotations; io::AnnotationProtoCollector annotation_collector( &annotations); - google::protobuf::scoped_ptr output(context->Open(filename)); + std::unique_ptr output(context->Open(filename)); io::Printer printer(output.get(), '$', annotate_code ? &annotation_collector : NULL); printer.Print( - "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "// source: $filename$\n" - "\n", - "filename", descriptor->file()->name()); + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n", + "filename", descriptor->file()->name()); if (!java_package.empty()) { printer.Print( - "package $package$;\n" - "\n", - "package", java_package); + "package $package$;\n" + "\n", + "package", java_package); } (generator->*pfn)(&printer); if (annotate_code) { - google::protobuf::scoped_ptr info_output( + std::unique_ptr info_output( context->Open(info_full_path)); annotations.SerializeToZeroCopyStream(info_output.get()); annotation_list->push_back(info_full_path); } } -void FileGenerator::GenerateSiblings(const string& package_dir, - GeneratorContext* context, - std::vector* file_list, - std::vector* annotation_list) { +void FileGenerator::GenerateSiblings( + const std::string& package_dir, GeneratorContext* context, + std::vector* file_list, + std::vector* annotation_list) { if (MultipleJavaFiles(file_, immutable_api_)) { for (int i = 0; i < file_->enum_type_count(); i++) { if (HasDescriptorMethods(file_, context_->EnforceLite())) { @@ -647,7 +664,7 @@ void FileGenerator::GenerateSiblings(const string& package_dir, } if (HasGenericServices(file_, context_->EnforceLite())) { for (int i = 0; i < file_->service_count(); i++) { - google::protobuf::scoped_ptr generator( + std::unique_ptr generator( generator_factory_->NewServiceGenerator(file_->service(i))); GenerateSibling( package_dir, java_package_, file_->service(i), context, file_list, @@ -658,8 +675,9 @@ void FileGenerator::GenerateSiblings(const string& package_dir, } } -bool FileGenerator::ShouldIncludeDependency( - const FileDescriptor* descriptor, bool immutable_api) { + +bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor, + bool immutable_api) { return true; } diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h index e95aef0912d56..9f1f719237b04 100644 --- a/src/google/protobuf/compiler/java/java_file.h +++ b/src/google/protobuf/compiler/java/java_file.h @@ -36,9 +36,6 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__ #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include #include @@ -46,22 +43,24 @@ namespace google { namespace protobuf { - class FileDescriptor; // descriptor.h - namespace io { - class Printer; // printer.h - } - namespace compiler { - class GeneratorContext; // code_generator.h - namespace java { - class Context; // context.h - class MessageGenerator; // message.h - class GeneratorFactory; // generator_factory.h - class ExtensionGenerator; // extension.h - class ClassNameResolver; // name_resolver.h - } - } +class FileDescriptor; // descriptor.h +namespace io { +class Printer; // printer.h } +namespace compiler { +class GeneratorContext; // code_generator.h +namespace java { +class Context; // context.h +class MessageGenerator; // message.h +class GeneratorFactory; // generator_factory.h +class ExtensionGenerator; // extension.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -75,20 +74,21 @@ class FileGenerator { // Checks for problems that would otherwise lead to cryptic compile errors. // Returns true if there are no problems, or writes an error description to // the given string and returns false otherwise. - bool Validate(string* error); + bool Validate(std::string* error); void Generate(io::Printer* printer); + // If we aren't putting everything into one file, this will write all the // files other than the outer file (i.e. one for each message, enum, and // service type). - void GenerateSiblings(const string& package_dir, + void GenerateSiblings(const std::string& package_dir, GeneratorContext* generator_context, - std::vector* file_list, - std::vector* annotation_list); + std::vector* file_list, + std::vector* annotation_list); - const string& java_package() { return java_package_; } - const string& classname() { return classname_; } + const std::string& java_package() { return java_package_; } + const std::string& classname() { return classname_; } private: void GenerateDescriptorInitializationCodeForImmutable(io::Printer* printer); @@ -98,13 +98,13 @@ class FileGenerator { bool immutable_api_); const FileDescriptor* file_; - string java_package_; - string classname_; + std::string java_package_; + std::string classname_; - google::protobuf::scoped_array > message_generators_; - google::protobuf::scoped_array > extension_generators_; - google::protobuf::scoped_ptr generator_factory_; - google::protobuf::scoped_ptr context_; + std::vector> message_generators_; + std::vector> extension_generators_; + std::unique_ptr generator_factory_; + std::unique_ptr context_; ClassNameResolver* name_resolver_; const Options options_; bool immutable_api_; @@ -115,6 +115,6 @@ class FileGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__ diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc index 84a3b90d6c774..29ae2cf9f4c23 100644 --- a/src/google/protobuf/compiler/java/java_generator.cc +++ b/src/google/protobuf/compiler/java/java_generator.cc @@ -34,10 +34,8 @@ #include + #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include @@ -45,9 +43,9 @@ #include #include #include +#include #include #include -#include #include @@ -60,15 +58,18 @@ namespace java { JavaGenerator::JavaGenerator() {} JavaGenerator::~JavaGenerator() {} +uint64_t JavaGenerator::GetSupportedFeatures() const { + return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL; +} + bool JavaGenerator::Generate(const FileDescriptor* file, - const string& parameter, + const std::string& parameter, GeneratorContext* context, - string* error) const { + std::string* error) const { // ----------------------------------------------------------------- // parse generator options - - std::vector > options; + std::vector > options; ParseGeneratorParameter(parameter, &options); Options file_options; @@ -81,6 +82,10 @@ bool JavaGenerator::Generate(const FileDescriptor* file, file_options.generate_mutable_code = true; } else if (options[i].first == "shared") { file_options.generate_shared_code = true; + } else if (options[i].first == "lite") { + // Note: Java Lite does not guarantee API/ABI stability. We may choose to + // break existing API in order to boost performance / reduce code size. + file_options.enforce_lite = true; } else if (options[i].first == "annotate_code") { file_options.annotate_code = true; } else if (options[i].first == "annotation_list_file") { @@ -107,8 +112,8 @@ bool JavaGenerator::Generate(const FileDescriptor* file, // ----------------------------------------------------------------- - std::vector all_files; - std::vector all_annotations; + std::vector all_files; + std::vector all_annotations; std::vector file_generators; @@ -120,6 +125,7 @@ bool JavaGenerator::Generate(const FileDescriptor* file, file_generators.push_back(new FileGenerator(file, file_options, /* mutable = */ false)); } + for (int i = 0; i < file_generators.size(); ++i) { if (!file_generators[i]->Validate(error)) { for (int j = 0; j < file_generators.size(); ++j) { @@ -132,26 +138,26 @@ bool JavaGenerator::Generate(const FileDescriptor* file, for (int i = 0; i < file_generators.size(); ++i) { FileGenerator* file_generator = file_generators[i]; - string package_dir = JavaPackageToDir(file_generator->java_package()); + std::string package_dir = JavaPackageToDir(file_generator->java_package()); - string java_filename = package_dir; + std::string java_filename = package_dir; java_filename += file_generator->classname(); java_filename += ".java"; all_files.push_back(java_filename); - string info_full_path = java_filename + ".pb.meta"; + std::string info_full_path = java_filename + ".pb.meta"; if (file_options.annotate_code) { all_annotations.push_back(info_full_path); } // Generate main java file. - google::protobuf::scoped_ptr output( + std::unique_ptr output( context->Open(java_filename)); GeneratedCodeInfo annotations; io::AnnotationProtoCollector annotation_collector( &annotations); - io::Printer printer(output.get(), '$', file_options.annotate_code - ? &annotation_collector - : NULL); + io::Printer printer( + output.get(), '$', + file_options.annotate_code ? &annotation_collector : NULL); file_generator->Generate(&printer); @@ -160,12 +166,13 @@ bool JavaGenerator::Generate(const FileDescriptor* file, &all_annotations); if (file_options.annotate_code) { - google::protobuf::scoped_ptr info_output( + std::unique_ptr info_output( context->Open(info_full_path)); annotations.SerializeToZeroCopyStream(info_output.get()); } } + for (int i = 0; i < file_generators.size(); ++i) { delete file_generators[i]; } @@ -175,7 +182,7 @@ bool JavaGenerator::Generate(const FileDescriptor* file, if (!file_options.output_list_file.empty()) { // Generate output list. This is just a simple text file placed in a // deterministic location which lists the .java files being generated. - google::protobuf::scoped_ptr srclist_raw_output( + std::unique_ptr srclist_raw_output( context->Open(file_options.output_list_file)); io::Printer srclist_printer(srclist_raw_output.get(), '$'); for (int i = 0; i < all_files.size(); i++) { @@ -186,7 +193,7 @@ bool JavaGenerator::Generate(const FileDescriptor* file, if (!file_options.annotation_list_file.empty()) { // Generate output list. This is just a simple text file placed in a // deterministic location which lists the .java files being generated. - google::protobuf::scoped_ptr annotation_list_raw_output( + std::unique_ptr annotation_list_raw_output( context->Open(file_options.annotation_list_file)); io::Printer annotation_list_printer(annotation_list_raw_output.get(), '$'); for (int i = 0; i < all_annotations.size(); i++) { diff --git a/src/google/protobuf/compiler/java/java_generator.h b/src/google/protobuf/compiler/java/java_generator.h index 47f76be983d1a..6315e7c3fedc2 100644 --- a/src/google/protobuf/compiler/java/java_generator.h +++ b/src/google/protobuf/compiler/java/java_generator.h @@ -40,6 +40,8 @@ #include #include +#include + namespace google { namespace protobuf { namespace compiler { @@ -49,16 +51,16 @@ namespace java { // own protocol compiler binary and you want it to support Java output, you // can do so by registering an instance of this CodeGenerator with the // CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT JavaGenerator : public CodeGenerator { +class PROTOC_EXPORT JavaGenerator : public CodeGenerator { public: JavaGenerator(); ~JavaGenerator(); // implements CodeGenerator ---------------------------------------- - bool Generate(const FileDescriptor* file, - const string& parameter, - GeneratorContext* context, - string* error) const; + bool Generate(const FileDescriptor* file, const std::string& parameter, + GeneratorContext* context, std::string* error) const override; + + uint64_t GetSupportedFeatures() const override; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaGenerator); @@ -67,6 +69,8 @@ class LIBPROTOC_EXPORT JavaGenerator : public CodeGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/java/java_generator_factory.cc b/src/google/protobuf/compiler/java/java_generator_factory.cc index 3218b4107648d..3a62adb103c8c 100644 --- a/src/google/protobuf/compiler/java/java_generator_factory.cc +++ b/src/google/protobuf/compiler/java/java_generator_factory.cc @@ -52,9 +52,8 @@ GeneratorFactory::~GeneratorFactory() {} // =================================================================== -ImmutableGeneratorFactory::ImmutableGeneratorFactory( - Context* context) : context_(context) { -} +ImmutableGeneratorFactory::ImmutableGeneratorFactory(Context* context) + : context_(context) {} ImmutableGeneratorFactory::~ImmutableGeneratorFactory() {} MessageGenerator* ImmutableGeneratorFactory::NewMessageGenerator( diff --git a/src/google/protobuf/compiler/java/java_generator_factory.h b/src/google/protobuf/compiler/java/java_generator_factory.h index 55365a9d4e94f..16688a56d0434 100644 --- a/src/google/protobuf/compiler/java/java_generator_factory.h +++ b/src/google/protobuf/compiler/java/java_generator_factory.h @@ -37,19 +37,21 @@ namespace google { namespace protobuf { - class FieldDescriptor; // descriptor.h - class Descriptor; // descriptor.h - class ServiceDescriptor; // descriptor.h - namespace compiler { - namespace java { - class MessageGenerator; // message.h - class ExtensionGenerator; // extension.h - class ServiceGenerator; // service.h - class Context; // context.h - } - } -} +class FieldDescriptor; // descriptor.h +class Descriptor; // descriptor.h +class ServiceDescriptor; // descriptor.h +namespace compiler { +namespace java { +class MessageGenerator; // message.h +class ExtensionGenerator; // extension.h +class ServiceGenerator; // service.h +class Context; // context.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -96,6 +98,6 @@ class ImmutableGeneratorFactory : public GeneratorFactory { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__ diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc index d8ac2db374005..3aebf72c7ecf5 100644 --- a/src/google/protobuf/compiler/java/java_helpers.cc +++ b/src/google/protobuf/compiler/java/java_helpers.cc @@ -32,19 +32,20 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include + #include -#include #include +#include #include -#include +#include #include +#include #include #include #include #include - - #include // for hash namespace google { @@ -56,9 +57,9 @@ using internal::WireFormat; using internal::WireFormatLite; const char kThickSeparator[] = - "// ===================================================================\n"; + "// ===================================================================\n"; const char kThinSeparator[] = - "// -------------------------------------------------------------------\n"; + "// -------------------------------------------------------------------\n"; namespace { @@ -68,13 +69,28 @@ const char* kDefaultPackage = ""; // Using them will cause the compiler to generate accessors whose names are // colliding with methods defined in base classes. const char* kForbiddenWordList[] = { - // message base class: - "cached_size", "serialized_size", - // java.lang.Object: - "class", + // message base class: + "cached_size", + "serialized_size", + // java.lang.Object: + "class", }; -bool IsForbidden(const string& field_name) { +const std::unordered_set* kReservedNames = + new std::unordered_set({ + "abstract", "assert", "boolean", "break", "byte", + "case", "catch", "char", "class", "const", + "continue", "default", "do", "double", "else", + "enum", "extends", "final", "finally", "float", + "for", "goto", "if", "implements", "import", + "instanceof", "int", "interface", "long", "native", + "new", "package", "private", "protected", "public", + "return", "short", "static", "strictfp", "super", + "switch", "synchronized", "this", "throw", "throws", + "transient", "try", "void", "volatile", "while", + }); + +bool IsForbidden(const std::string& field_name) { for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) { if (field_name == kForbiddenWordList[i]) { return true; @@ -83,8 +99,8 @@ bool IsForbidden(const string& field_name) { return false; } -string FieldName(const FieldDescriptor* field) { - string field_name; +std::string FieldName(const FieldDescriptor* field) { + std::string field_name; // Groups are hacky: The name of the field is just the lower-cased name // of the group type. In Java, though, we would like to retain the original // capitalization of the type name. @@ -105,11 +121,11 @@ string FieldName(const FieldDescriptor* field) { } // namespace void PrintGeneratedAnnotation(io::Printer* printer, char delimiter, - const string& annotation_file) { + const std::string& annotation_file) { if (annotation_file.empty()) { return; } - string ptemplate = + std::string ptemplate = "@javax.annotation.Generated(value=\"protoc\", comments=\"annotations:"; ptemplate.push_back(delimiter); ptemplate.append("annotation_file"); @@ -118,8 +134,31 @@ void PrintGeneratedAnnotation(io::Printer* printer, char delimiter, printer->Print(ptemplate.c_str(), "annotation_file", annotation_file); } -string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { - string result; +void PrintEnumVerifierLogic(io::Printer* printer, + const FieldDescriptor* descriptor, + const std::map& variables, + const char* var_name, + const char* terminating_string, bool enforce_lite) { + std::string enum_verifier_string = + enforce_lite ? StrCat(var_name, ".internalGetVerifier()") + : StrCat( + "new com.google.protobuf.Internal.EnumVerifier() {\n" + " @java.lang.Override\n" + " public boolean isInRange(int number) {\n" + " return ", + var_name, + ".forNumber(number) != null;\n" + " }\n" + " }"); + printer->Print( + variables, + StrCat(enum_verifier_string, terminating_string).c_str()); +} + +std::string UnderscoresToCamelCase(const std::string& input, + bool cap_next_letter) { + GOOGLE_CHECK(!input.empty()); + std::string result; // Note: I distrust ctype.h due to locales. for (int i = 0; i < input.size(); i++) { if ('a' <= input[i] && input[i] <= 'z') { @@ -153,45 +192,50 @@ string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { return result; } -string UnderscoresToCamelCase(const FieldDescriptor* field) { +std::string UnderscoresToCamelCase(const FieldDescriptor* field) { return UnderscoresToCamelCase(FieldName(field), false); } -string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { +std::string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { return UnderscoresToCamelCase(FieldName(field), true); } -string UnderscoresToCamelCase(const MethodDescriptor* method) { +std::string CapitalizedFieldName(const FieldDescriptor* field) { + return UnderscoresToCapitalizedCamelCase(field); +} + +std::string UnderscoresToCamelCase(const MethodDescriptor* method) { return UnderscoresToCamelCase(method->name(), false); } -string UniqueFileScopeIdentifier(const Descriptor* descriptor) { +std::string UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field) { + std::string name = UnderscoresToCamelCase(field); + if (kReservedNames->find(name) != kReservedNames->end()) { + return name + "_"; + } + return name; +} + + +std::string UniqueFileScopeIdentifier(const Descriptor* descriptor) { return "static_" + StringReplace(descriptor->full_name(), ".", "_", true); } -string CamelCaseFieldName(const FieldDescriptor* field) { - string fieldName = UnderscoresToCamelCase(field); +std::string CamelCaseFieldName(const FieldDescriptor* field) { + std::string fieldName = UnderscoresToCamelCase(field); if ('0' <= fieldName[0] && fieldName[0] <= '9') { return '_' + fieldName; } return fieldName; } -string StripProto(const string& filename) { - if (HasSuffixString(filename, ".protodevel")) { - return StripSuffixString(filename, ".protodevel"); - } else { - return StripSuffixString(filename, ".proto"); - } -} - -string FileClassName(const FileDescriptor* file, bool immutable) { +std::string FileClassName(const FileDescriptor* file, bool immutable) { ClassNameResolver name_resolver; return name_resolver.GetFileClassName(file, immutable); } -string FileJavaPackage(const FileDescriptor* file, bool immutable) { - string result; +std::string FileJavaPackage(const FileDescriptor* file, bool immutable) { + std::string result; if (file->options().has_java_package()) { result = file->options().java_package(); @@ -206,79 +250,59 @@ string FileJavaPackage(const FileDescriptor* file, bool immutable) { return result; } -string JavaPackageToDir(string package_name) { - string package_dir = - StringReplace(package_name, ".", "/", true); - if (!package_dir.empty()) package_dir += "/"; - return package_dir; +std::string FileJavaPackage(const FileDescriptor* file) { + return FileJavaPackage(file, true /* immutable */); } -// TODO(xiaofeng): This function is only kept for it's publicly referenced. -// It should be removed after mutable API up-integration. -string ToJavaName(const string& full_name, - const FileDescriptor* file) { - string result; - if (file->options().java_multiple_files()) { - result = FileJavaPackage(file); - } else { - result = ClassName(file); - } - if (!result.empty()) { - result += '.'; - } - if (file->package().empty()) { - result += full_name; - } else { - // Strip the proto package from full_name since we've replaced it with - // the Java package. - result += full_name.substr(file->package().size() + 1); - } - return result; +std::string JavaPackageToDir(std::string package_name) { + std::string package_dir = StringReplace(package_name, ".", "/", true); + if (!package_dir.empty()) package_dir += "/"; + return package_dir; } -string ClassName(const Descriptor* descriptor) { +std::string ClassName(const Descriptor* descriptor) { ClassNameResolver name_resolver; return name_resolver.GetClassName(descriptor, true); } -string ClassName(const EnumDescriptor* descriptor) { +std::string ClassName(const EnumDescriptor* descriptor) { ClassNameResolver name_resolver; return name_resolver.GetClassName(descriptor, true); } -string ClassName(const ServiceDescriptor* descriptor) { +std::string ClassName(const ServiceDescriptor* descriptor) { ClassNameResolver name_resolver; return name_resolver.GetClassName(descriptor, true); } -string ClassName(const FileDescriptor* descriptor) { +std::string ClassName(const FileDescriptor* descriptor) { ClassNameResolver name_resolver; return name_resolver.GetClassName(descriptor, true); } -string ExtraMessageInterfaces(const Descriptor* descriptor) { - string interfaces = "// @@protoc_insertion_point(message_implements:" - + descriptor->full_name() + ")"; +std::string ExtraMessageInterfaces(const Descriptor* descriptor) { + std::string interfaces = "// @@protoc_insertion_point(message_implements:" + + descriptor->full_name() + ")"; return interfaces; } -string ExtraBuilderInterfaces(const Descriptor* descriptor) { - string interfaces = "// @@protoc_insertion_point(builder_implements:" - + descriptor->full_name() + ")"; +std::string ExtraBuilderInterfaces(const Descriptor* descriptor) { + std::string interfaces = "// @@protoc_insertion_point(builder_implements:" + + descriptor->full_name() + ")"; return interfaces; } -string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) { - string interfaces = "// @@protoc_insertion_point(interface_extends:" - + descriptor->full_name() + ")"; +std::string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) { + std::string interfaces = "// @@protoc_insertion_point(interface_extends:" + + descriptor->full_name() + ")"; return interfaces; } -string FieldConstantName(const FieldDescriptor *field) { - string name = field->name() + "_FIELD_NUMBER"; - UpperString(&name); +std::string FieldConstantName(const FieldDescriptor* field) { + std::string name = field->name() + "_FIELD_NUMBER"; + ToUpper(&name); return name; } @@ -324,8 +348,8 @@ JavaType GetJavaType(const FieldDescriptor* field) { case FieldDescriptor::TYPE_MESSAGE: return JAVATYPE_MESSAGE; - // No default because we want the compiler to complain if any new - // types are added. + // No default because we want the compiler to complain if any new + // types are added. } GOOGLE_LOG(FATAL) << "Can't get here."; @@ -334,75 +358,131 @@ JavaType GetJavaType(const FieldDescriptor* field) { const char* PrimitiveTypeName(JavaType type) { switch (type) { - case JAVATYPE_INT : return "int"; - case JAVATYPE_LONG : return "long"; - case JAVATYPE_FLOAT : return "float"; - case JAVATYPE_DOUBLE : return "double"; - case JAVATYPE_BOOLEAN: return "boolean"; - case JAVATYPE_STRING : return "java.lang.String"; - case JAVATYPE_BYTES : return "com.google.protobuf.ByteString"; - case JAVATYPE_ENUM : return NULL; - case JAVATYPE_MESSAGE: return NULL; - - // No default because we want the compiler to complain if any new - // JavaTypes are added. + case JAVATYPE_INT: + return "int"; + case JAVATYPE_LONG: + return "long"; + case JAVATYPE_FLOAT: + return "float"; + case JAVATYPE_DOUBLE: + return "double"; + case JAVATYPE_BOOLEAN: + return "boolean"; + case JAVATYPE_STRING: + return "java.lang.String"; + case JAVATYPE_BYTES: + return "com.google.protobuf.ByteString"; + case JAVATYPE_ENUM: + return NULL; + case JAVATYPE_MESSAGE: + return NULL; + + // No default because we want the compiler to complain if any new + // JavaTypes are added. } GOOGLE_LOG(FATAL) << "Can't get here."; return NULL; } +const char* PrimitiveTypeName(const FieldDescriptor* descriptor) { + return PrimitiveTypeName(GetJavaType(descriptor)); +} + const char* BoxedPrimitiveTypeName(JavaType type) { switch (type) { - case JAVATYPE_INT : return "java.lang.Integer"; - case JAVATYPE_LONG : return "java.lang.Long"; - case JAVATYPE_FLOAT : return "java.lang.Float"; - case JAVATYPE_DOUBLE : return "java.lang.Double"; - case JAVATYPE_BOOLEAN: return "java.lang.Boolean"; - case JAVATYPE_STRING : return "java.lang.String"; - case JAVATYPE_BYTES : return "com.google.protobuf.ByteString"; - case JAVATYPE_ENUM : return NULL; - case JAVATYPE_MESSAGE: return NULL; - - // No default because we want the compiler to complain if any new - // JavaTypes are added. + case JAVATYPE_INT: + return "java.lang.Integer"; + case JAVATYPE_LONG: + return "java.lang.Long"; + case JAVATYPE_FLOAT: + return "java.lang.Float"; + case JAVATYPE_DOUBLE: + return "java.lang.Double"; + case JAVATYPE_BOOLEAN: + return "java.lang.Boolean"; + case JAVATYPE_STRING: + return "java.lang.String"; + case JAVATYPE_BYTES: + return "com.google.protobuf.ByteString"; + case JAVATYPE_ENUM: + return NULL; + case JAVATYPE_MESSAGE: + return NULL; + + // No default because we want the compiler to complain if any new + // JavaTypes are added. } GOOGLE_LOG(FATAL) << "Can't get here."; return NULL; } +const char* BoxedPrimitiveTypeName(const FieldDescriptor* descriptor) { + return BoxedPrimitiveTypeName(GetJavaType(descriptor)); +} + + +std::string GetOneofStoredType(const FieldDescriptor* field) { + const JavaType javaType = GetJavaType(field); + switch (javaType) { + case JAVATYPE_ENUM: + return "java.lang.Integer"; + case JAVATYPE_MESSAGE: + return ClassName(field->message_type()); + default: + return BoxedPrimitiveTypeName(javaType); + } +} const char* FieldTypeName(FieldDescriptor::Type field_type) { switch (field_type) { - case FieldDescriptor::TYPE_INT32 : return "INT32"; - case FieldDescriptor::TYPE_UINT32 : return "UINT32"; - case FieldDescriptor::TYPE_SINT32 : return "SINT32"; - case FieldDescriptor::TYPE_FIXED32 : return "FIXED32"; - case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32"; - case FieldDescriptor::TYPE_INT64 : return "INT64"; - case FieldDescriptor::TYPE_UINT64 : return "UINT64"; - case FieldDescriptor::TYPE_SINT64 : return "SINT64"; - case FieldDescriptor::TYPE_FIXED64 : return "FIXED64"; - case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64"; - case FieldDescriptor::TYPE_FLOAT : return "FLOAT"; - case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE"; - case FieldDescriptor::TYPE_BOOL : return "BOOL"; - case FieldDescriptor::TYPE_STRING : return "STRING"; - case FieldDescriptor::TYPE_BYTES : return "BYTES"; - case FieldDescriptor::TYPE_ENUM : return "ENUM"; - case FieldDescriptor::TYPE_GROUP : return "GROUP"; - case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE"; - - // No default because we want the compiler to complain if any new - // types are added. + case FieldDescriptor::TYPE_INT32: + return "INT32"; + case FieldDescriptor::TYPE_UINT32: + return "UINT32"; + case FieldDescriptor::TYPE_SINT32: + return "SINT32"; + case FieldDescriptor::TYPE_FIXED32: + return "FIXED32"; + case FieldDescriptor::TYPE_SFIXED32: + return "SFIXED32"; + case FieldDescriptor::TYPE_INT64: + return "INT64"; + case FieldDescriptor::TYPE_UINT64: + return "UINT64"; + case FieldDescriptor::TYPE_SINT64: + return "SINT64"; + case FieldDescriptor::TYPE_FIXED64: + return "FIXED64"; + case FieldDescriptor::TYPE_SFIXED64: + return "SFIXED64"; + case FieldDescriptor::TYPE_FLOAT: + return "FLOAT"; + case FieldDescriptor::TYPE_DOUBLE: + return "DOUBLE"; + case FieldDescriptor::TYPE_BOOL: + return "BOOL"; + case FieldDescriptor::TYPE_STRING: + return "STRING"; + case FieldDescriptor::TYPE_BYTES: + return "BYTES"; + case FieldDescriptor::TYPE_ENUM: + return "ENUM"; + case FieldDescriptor::TYPE_GROUP: + return "GROUP"; + case FieldDescriptor::TYPE_MESSAGE: + return "MESSAGE"; + + // No default because we want the compiler to complain if any new + // types are added. } GOOGLE_LOG(FATAL) << "Can't get here."; return NULL; } -bool AllAscii(const string& text) { +bool AllAscii(const std::string& text) { for (int i = 0; i < text.size(); i++) { if ((text[i] & 0x80) != 0) { return false; @@ -411,20 +491,20 @@ bool AllAscii(const string& text) { return true; } -string DefaultValue(const FieldDescriptor* field, bool immutable, - ClassNameResolver* name_resolver) { +std::string DefaultValue(const FieldDescriptor* field, bool immutable, + ClassNameResolver* name_resolver) { // Switch on CppType since we need to know which default_value_* method // of FieldDescriptor to call. switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: - return SimpleItoa(field->default_value_int32()); + return StrCat(field->default_value_int32()); case FieldDescriptor::CPPTYPE_UINT32: // Need to print as a signed int since Java has no unsigned. - return SimpleItoa(static_cast(field->default_value_uint32())); + return StrCat(static_cast(field->default_value_uint32())); case FieldDescriptor::CPPTYPE_INT64: - return SimpleItoa(field->default_value_int64()) + "L"; + return StrCat(field->default_value_int64()) + "L"; case FieldDescriptor::CPPTYPE_UINT64: - return SimpleItoa(static_cast(field->default_value_uint64())) + + return StrCat(static_cast(field->default_value_uint64())) + "L"; case FieldDescriptor::CPPTYPE_DOUBLE: { double value = field->default_value_double(); @@ -457,8 +537,8 @@ string DefaultValue(const FieldDescriptor* field, bool immutable, if (field->has_default_value()) { // See comments in Internal.java for gory details. return strings::Substitute( - "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")", - CEscape(field->default_value_string())); + "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")", + CEscape(field->default_value_string())); } else { return "com.google.protobuf.ByteString.EMPTY"; } @@ -476,14 +556,14 @@ string DefaultValue(const FieldDescriptor* field, bool immutable, case FieldDescriptor::CPPTYPE_ENUM: return name_resolver->GetClassName(field->enum_type(), immutable) + "." + - field->default_value_enum()->name(); + field->default_value_enum()->name(); case FieldDescriptor::CPPTYPE_MESSAGE: return name_resolver->GetClassName(field->message_type(), immutable) + - ".getDefaultInstance()"; + ".getDefaultInstance()"; - // No default because we want the compiler to complain if any new - // types are added. + // No default because we want the compiler to complain if any new + // types are added. } GOOGLE_LOG(FATAL) << "Can't get here."; @@ -514,8 +594,8 @@ bool IsDefaultValueJavaDefault(const FieldDescriptor* field) { case FieldDescriptor::CPPTYPE_MESSAGE: return false; - // No default because we want the compiler to complain if any new - // types are added. + // No default because we want the compiler to complain if any new + // types are added. } GOOGLE_LOG(FATAL) << "Can't get here."; @@ -528,123 +608,108 @@ bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field) { } const char* bit_masks[] = { - "0x00000001", - "0x00000002", - "0x00000004", - "0x00000008", - "0x00000010", - "0x00000020", - "0x00000040", - "0x00000080", - - "0x00000100", - "0x00000200", - "0x00000400", - "0x00000800", - "0x00001000", - "0x00002000", - "0x00004000", - "0x00008000", - - "0x00010000", - "0x00020000", - "0x00040000", - "0x00080000", - "0x00100000", - "0x00200000", - "0x00400000", - "0x00800000", - - "0x01000000", - "0x02000000", - "0x04000000", - "0x08000000", - "0x10000000", - "0x20000000", - "0x40000000", - "0x80000000", + "0x00000001", "0x00000002", "0x00000004", "0x00000008", + "0x00000010", "0x00000020", "0x00000040", "0x00000080", + + "0x00000100", "0x00000200", "0x00000400", "0x00000800", + "0x00001000", "0x00002000", "0x00004000", "0x00008000", + + "0x00010000", "0x00020000", "0x00040000", "0x00080000", + "0x00100000", "0x00200000", "0x00400000", "0x00800000", + + "0x01000000", "0x02000000", "0x04000000", "0x08000000", + "0x10000000", "0x20000000", "0x40000000", "0x80000000", }; -string GetBitFieldName(int index) { - string varName = "bitField"; - varName += SimpleItoa(index); +std::string GetBitFieldName(int index) { + std::string varName = "bitField"; + varName += StrCat(index); varName += "_"; return varName; } -string GetBitFieldNameForBit(int bitIndex) { +std::string GetBitFieldNameForBit(int bitIndex) { return GetBitFieldName(bitIndex / 32); } namespace { -string GenerateGetBitInternal(const string& prefix, int bitIndex) { - string varName = prefix + GetBitFieldNameForBit(bitIndex); +std::string GenerateGetBitInternal(const std::string& prefix, int bitIndex) { + std::string varName = prefix + GetBitFieldNameForBit(bitIndex); int bitInVarIndex = bitIndex % 32; - string mask = bit_masks[bitInVarIndex]; - string result = "((" + varName + " & " + mask + ") == " + mask + ")"; + std::string mask = bit_masks[bitInVarIndex]; + std::string result = "((" + varName + " & " + mask + ") != 0)"; return result; } -string GenerateSetBitInternal(const string& prefix, int bitIndex) { - string varName = prefix + GetBitFieldNameForBit(bitIndex); +std::string GenerateSetBitInternal(const std::string& prefix, int bitIndex) { + std::string varName = prefix + GetBitFieldNameForBit(bitIndex); int bitInVarIndex = bitIndex % 32; - string mask = bit_masks[bitInVarIndex]; - string result = varName + " |= " + mask; + std::string mask = bit_masks[bitInVarIndex]; + std::string result = varName + " |= " + mask; return result; } } // namespace -string GenerateGetBit(int bitIndex) { +std::string GenerateGetBit(int bitIndex) { return GenerateGetBitInternal("", bitIndex); } -string GenerateSetBit(int bitIndex) { +std::string GenerateSetBit(int bitIndex) { return GenerateSetBitInternal("", bitIndex); } -string GenerateClearBit(int bitIndex) { - string varName = GetBitFieldNameForBit(bitIndex); +std::string GenerateClearBit(int bitIndex) { + std::string varName = GetBitFieldNameForBit(bitIndex); int bitInVarIndex = bitIndex % 32; - string mask = bit_masks[bitInVarIndex]; - string result = varName + " = (" + varName + " & ~" + mask + ")"; + std::string mask = bit_masks[bitInVarIndex]; + std::string result = varName + " = (" + varName + " & ~" + mask + ")"; return result; } -string GenerateGetBitFromLocal(int bitIndex) { +std::string GenerateGetBitFromLocal(int bitIndex) { return GenerateGetBitInternal("from_", bitIndex); } -string GenerateSetBitToLocal(int bitIndex) { +std::string GenerateSetBitToLocal(int bitIndex) { return GenerateSetBitInternal("to_", bitIndex); } -string GenerateGetBitMutableLocal(int bitIndex) { +std::string GenerateGetBitMutableLocal(int bitIndex) { return GenerateGetBitInternal("mutable_", bitIndex); } -string GenerateSetBitMutableLocal(int bitIndex) { +std::string GenerateSetBitMutableLocal(int bitIndex) { return GenerateSetBitInternal("mutable_", bitIndex); } bool IsReferenceType(JavaType type) { switch (type) { - case JAVATYPE_INT : return false; - case JAVATYPE_LONG : return false; - case JAVATYPE_FLOAT : return false; - case JAVATYPE_DOUBLE : return false; - case JAVATYPE_BOOLEAN: return false; - case JAVATYPE_STRING : return true; - case JAVATYPE_BYTES : return true; - case JAVATYPE_ENUM : return true; - case JAVATYPE_MESSAGE: return true; + case JAVATYPE_INT: + return false; + case JAVATYPE_LONG: + return false; + case JAVATYPE_FLOAT: + return false; + case JAVATYPE_DOUBLE: + return false; + case JAVATYPE_BOOLEAN: + return false; + case JAVATYPE_STRING: + return true; + case JAVATYPE_BYTES: + return true; + case JAVATYPE_ENUM: + return true; + case JAVATYPE_MESSAGE: + return true; - // No default because we want the compiler to complain if any new - // JavaTypes are added. + // No default because we want the compiler to complain if any new + // JavaTypes are added. } GOOGLE_LOG(FATAL) << "Can't get here."; @@ -653,29 +718,46 @@ bool IsReferenceType(JavaType type) { const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) { switch (GetType(field)) { - case FieldDescriptor::TYPE_INT32 : return "Int32"; - case FieldDescriptor::TYPE_UINT32 : return "UInt32"; - case FieldDescriptor::TYPE_SINT32 : return "SInt32"; - case FieldDescriptor::TYPE_FIXED32 : return "Fixed32"; - case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; - case FieldDescriptor::TYPE_INT64 : return "Int64"; - case FieldDescriptor::TYPE_UINT64 : return "UInt64"; - case FieldDescriptor::TYPE_SINT64 : return "SInt64"; - case FieldDescriptor::TYPE_FIXED64 : return "Fixed64"; - case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; - case FieldDescriptor::TYPE_FLOAT : return "Float"; - case FieldDescriptor::TYPE_DOUBLE : return "Double"; - case FieldDescriptor::TYPE_BOOL : return "Bool"; - case FieldDescriptor::TYPE_STRING : return "String"; - case FieldDescriptor::TYPE_BYTES : { + case FieldDescriptor::TYPE_INT32: + return "Int32"; + case FieldDescriptor::TYPE_UINT32: + return "UInt32"; + case FieldDescriptor::TYPE_SINT32: + return "SInt32"; + case FieldDescriptor::TYPE_FIXED32: + return "Fixed32"; + case FieldDescriptor::TYPE_SFIXED32: + return "SFixed32"; + case FieldDescriptor::TYPE_INT64: + return "Int64"; + case FieldDescriptor::TYPE_UINT64: + return "UInt64"; + case FieldDescriptor::TYPE_SINT64: + return "SInt64"; + case FieldDescriptor::TYPE_FIXED64: + return "Fixed64"; + case FieldDescriptor::TYPE_SFIXED64: + return "SFixed64"; + case FieldDescriptor::TYPE_FLOAT: + return "Float"; + case FieldDescriptor::TYPE_DOUBLE: + return "Double"; + case FieldDescriptor::TYPE_BOOL: + return "Bool"; + case FieldDescriptor::TYPE_STRING: + return "String"; + case FieldDescriptor::TYPE_BYTES: { return "Bytes"; } - case FieldDescriptor::TYPE_ENUM : return "Enum"; - case FieldDescriptor::TYPE_GROUP : return "Group"; - case FieldDescriptor::TYPE_MESSAGE : return "Message"; + case FieldDescriptor::TYPE_ENUM: + return "Enum"; + case FieldDescriptor::TYPE_GROUP: + return "Group"; + case FieldDescriptor::TYPE_MESSAGE: + return "Message"; - // No default because we want the compiler to complain if any new - // types are added. + // No default because we want the compiler to complain if any new + // types are added. } GOOGLE_LOG(FATAL) << "Can't get here."; @@ -686,29 +768,47 @@ const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) { // returns -1. int FixedSize(FieldDescriptor::Type type) { switch (type) { - case FieldDescriptor::TYPE_INT32 : return -1; - case FieldDescriptor::TYPE_INT64 : return -1; - case FieldDescriptor::TYPE_UINT32 : return -1; - case FieldDescriptor::TYPE_UINT64 : return -1; - case FieldDescriptor::TYPE_SINT32 : return -1; - case FieldDescriptor::TYPE_SINT64 : return -1; - case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; - case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; - case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; - case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; - case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; - case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; - - case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; - case FieldDescriptor::TYPE_ENUM : return -1; - - case FieldDescriptor::TYPE_STRING : return -1; - case FieldDescriptor::TYPE_BYTES : return -1; - case FieldDescriptor::TYPE_GROUP : return -1; - case FieldDescriptor::TYPE_MESSAGE : return -1; - - // No default because we want the compiler to complain if any new - // types are added. + case FieldDescriptor::TYPE_INT32: + return -1; + case FieldDescriptor::TYPE_INT64: + return -1; + case FieldDescriptor::TYPE_UINT32: + return -1; + case FieldDescriptor::TYPE_UINT64: + return -1; + case FieldDescriptor::TYPE_SINT32: + return -1; + case FieldDescriptor::TYPE_SINT64: + return -1; + case FieldDescriptor::TYPE_FIXED32: + return WireFormatLite::kFixed32Size; + case FieldDescriptor::TYPE_FIXED64: + return WireFormatLite::kFixed64Size; + case FieldDescriptor::TYPE_SFIXED32: + return WireFormatLite::kSFixed32Size; + case FieldDescriptor::TYPE_SFIXED64: + return WireFormatLite::kSFixed64Size; + case FieldDescriptor::TYPE_FLOAT: + return WireFormatLite::kFloatSize; + case FieldDescriptor::TYPE_DOUBLE: + return WireFormatLite::kDoubleSize; + + case FieldDescriptor::TYPE_BOOL: + return WireFormatLite::kBoolSize; + case FieldDescriptor::TYPE_ENUM: + return -1; + + case FieldDescriptor::TYPE_STRING: + return -1; + case FieldDescriptor::TYPE_BYTES: + return -1; + case FieldDescriptor::TYPE_GROUP: + return -1; + case FieldDescriptor::TYPE_MESSAGE: + return -1; + + // No default because we want the compiler to complain if any new + // types are added. } GOOGLE_LOG(FATAL) << "Can't get here."; return -1; @@ -718,7 +818,7 @@ int FixedSize(FieldDescriptor::Type type) { // and return it. The caller should delete the returned array. const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { const FieldDescriptor** fields = - new const FieldDescriptor*[descriptor->field_count()]; + new const FieldDescriptor*[descriptor->field_count()]; for (int i = 0; i < descriptor->field_count(); i++) { fields[i] = descriptor->field(i); } @@ -732,9 +832,8 @@ const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { // // already_seen is used to avoid checking the same type multiple times // (and also to protect against recursion). -bool HasRequiredFields( - const Descriptor* type, - hash_set* already_seen) { +bool HasRequiredFields(const Descriptor* type, + std::unordered_set* already_seen) { if (already_seen->count(type) > 0) { // The type is already in cache. This means that either: // a. The type has no required fields. @@ -769,7 +868,7 @@ bool HasRequiredFields( } bool HasRequiredFields(const Descriptor* type) { - hash_set already_seen; + std::unordered_set already_seen; return HasRequiredFields(type, &already_seen); } @@ -783,6 +882,142 @@ bool HasRepeatedFields(const Descriptor* descriptor) { return false; } +// Encode an unsigned 32-bit value into a sequence of UTF-16 characters. +// +// If the value is in [0x0000, 0xD7FF], we encode it with a single character +// with the same numeric value. +// +// If the value is larger than 0xD7FF, we encode its lowest 13 bits into a +// character in the range [0xE000, 0xFFFF] by combining these 13 bits with +// 0xE000 using logic-or. Then we shift the value to the right by 13 bits, and +// encode the remaining value by repeating this same process until we get to +// a value in [0x0000, 0xD7FF] where we will encode it using a character with +// the same numeric value. +// +// Note that we only use code points in [0x0000, 0xD7FF] and [0xE000, 0xFFFF]. +// There will be no surrogate pairs in the encoded character sequence. +void WriteUInt32ToUtf16CharSequence(uint32 number, + std::vector* output) { + // For values in [0x0000, 0xD7FF], only use one char to encode it. + if (number < 0xD800) { + output->push_back(static_cast(number)); + return; + } + // Encode into multiple chars. All except the last char will be in the range + // [0xE000, 0xFFFF], and the last char will be in the range [0x0000, 0xD7FF]. + // Note that we don't use any value in range [0xD800, 0xDFFF] because they + // have to come in pairs and the encoding is just more space-efficient w/o + // them. + while (number >= 0xD800) { + // [0xE000, 0xFFFF] can represent 13 bits of info. + output->push_back(static_cast(0xE000 | (number & 0x1FFF))); + number >>= 13; + } + output->push_back(static_cast(number)); +} + +int GetExperimentalJavaFieldTypeForSingular(const FieldDescriptor* field) { + // j/c/g/protobuf/FieldType.java lists field types in a slightly different + // order from FieldDescriptor::Type so we can't do a simple cast. + // + // TODO(xiaofeng): Make j/c/g/protobuf/FieldType.java follow the same order. + int result = field->type(); + if (result == FieldDescriptor::TYPE_GROUP) { + return 17; + } else if (result < FieldDescriptor::TYPE_GROUP) { + return result - 1; + } else { + return result - 2; + } +} + +int GetExperimentalJavaFieldTypeForRepeated(const FieldDescriptor* field) { + if (field->type() == FieldDescriptor::TYPE_GROUP) { + return 49; + } else { + return GetExperimentalJavaFieldTypeForSingular(field) + 18; + } +} + +int GetExperimentalJavaFieldTypeForPacked(const FieldDescriptor* field) { + int result = field->type(); + if (result < FieldDescriptor::TYPE_STRING) { + return result + 34; + } else if (result > FieldDescriptor::TYPE_BYTES) { + return result + 30; + } else { + GOOGLE_LOG(FATAL) << field->full_name() << " can't be packed."; + return 0; + } +} + +int GetExperimentalJavaFieldType(const FieldDescriptor* field) { + static const int kMapFieldType = 50; + static const int kOneofFieldTypeOffset = 51; + static const int kRequiredBit = 0x100; + static const int kUtf8CheckBit = 0x200; + static const int kCheckInitialized = 0x400; + static const int kMapWithProto2EnumValue = 0x800; + static const int kHasHasBit = 0x1000; + int extra_bits = field->is_required() ? kRequiredBit : 0; + if (field->type() == FieldDescriptor::TYPE_STRING && CheckUtf8(field)) { + extra_bits |= kUtf8CheckBit; + } + if (field->is_required() || (GetJavaType(field) == JAVATYPE_MESSAGE && + HasRequiredFields(field->message_type()))) { + extra_bits |= kCheckInitialized; + } + if (HasHasbit(field)) { + extra_bits |= kHasHasBit; + } + + if (field->is_map()) { + if (!SupportUnknownEnumValue(field)) { + const FieldDescriptor* value = + field->message_type()->FindFieldByName("value"); + if (GetJavaType(value) == JAVATYPE_ENUM) { + extra_bits |= kMapWithProto2EnumValue; + } + } + return kMapFieldType | extra_bits; + } else if (field->is_packed()) { + return GetExperimentalJavaFieldTypeForPacked(field); + } else if (field->is_repeated()) { + return GetExperimentalJavaFieldTypeForRepeated(field) | extra_bits; + } else if (IsRealOneof(field)) { + return (GetExperimentalJavaFieldTypeForSingular(field) + + kOneofFieldTypeOffset) | + extra_bits; + } else { + return GetExperimentalJavaFieldTypeForSingular(field) | extra_bits; + } +} + +// Escape a UTF-16 character to be embedded in a Java string. +void EscapeUtf16ToString(uint16 code, std::string* output) { + if (code == '\t') { + output->append("\\t"); + } else if (code == '\b') { + output->append("\\b"); + } else if (code == '\n') { + output->append("\\n"); + } else if (code == '\r') { + output->append("\\r"); + } else if (code == '\f') { + output->append("\\f"); + } else if (code == '\'') { + output->append("\\'"); + } else if (code == '\"') { + output->append("\\\""); + } else if (code == '\\') { + output->append("\\\\"); + } else if (code >= 0x20 && code <= 0x7f) { + output->push_back(static_cast(code)); + } else { + output->append(StringPrintf("\\u%04x", code)); + } +} + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h index bd565ced0da87..8cc2f5af80e5a 100644 --- a/src/google/protobuf/compiler/java/java_helpers.h +++ b/src/google/protobuf/compiler/java/java_helpers.h @@ -37,8 +37,8 @@ #include #include -#include #include +#include #include namespace google { @@ -51,6 +51,7 @@ namespace java { extern const char kThickSeparator[]; extern const char kThinSeparator[]; + // If annotation_file is non-empty, prints a javax.annotation.Generated // annotation to the given Printer. annotation_file will be referenced in the // annotation's comments field. delimiter should be the Printer's delimiter @@ -60,89 +61,94 @@ extern const char kThinSeparator[]; // annotation_file should be generated from the filename of the source file // being annotated (which in turn must be a Java identifier plus ".java"). void PrintGeneratedAnnotation(io::Printer* printer, char delimiter = '$', - const string& annotation_file = ""); + const std::string& annotation_file = ""); + +// If a GeneratedMessageLite contains non-lite enums, then its verifier +// must be instantiated inline, rather than retrieved from the enum class. +void PrintEnumVerifierLogic(io::Printer* printer, + const FieldDescriptor* descriptor, + const std::map& variables, + const char* var_name, + const char* terminating_string, bool enforce_lite); // Converts a name to camel-case. If cap_first_letter is true, capitalize the // first letter. -string UnderscoresToCamelCase(const string& name, bool cap_first_letter); +std::string UnderscoresToCamelCase(const std::string& name, + bool cap_first_letter); // Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes // "fooBarBaz" or "FooBarBaz", respectively. -string UnderscoresToCamelCase(const FieldDescriptor* field); -string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); +std::string UnderscoresToCamelCase(const FieldDescriptor* field); +std::string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); // Similar, but for method names. (Typically, this merely has the effect // of lower-casing the first letter of the name.) -string UnderscoresToCamelCase(const MethodDescriptor* method); +std::string UnderscoresToCamelCase(const MethodDescriptor* method); -// Similar to UnderscoresToCamelCase, but guarentees that the result is a +// Same as UnderscoresToCamelCase, but checks for reserved keywords +std::string UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field); + +// Similar to UnderscoresToCamelCase, but guarantees that the result is a // complete Java identifier by adding a _ if needed. -string CamelCaseFieldName(const FieldDescriptor* field); +std::string CamelCaseFieldName(const FieldDescriptor* field); // Get an identifier that uniquely identifies this type within the file. // This is used to declare static variables related to this type at the // outermost file scope. -string UniqueFileScopeIdentifier(const Descriptor* descriptor); - -// Strips ".proto" or ".protodevel" from the end of a filename. -string StripProto(const string& filename); +std::string UniqueFileScopeIdentifier(const Descriptor* descriptor); // Gets the unqualified class name for the file. For each .proto file, there // will be one Java class containing all the immutable messages and another // Java class containing all the mutable messages. // TODO(xiaofeng): remove the default value after updating client code. -string FileClassName(const FileDescriptor* file, bool immutable = true); +std::string FileClassName(const FileDescriptor* file, bool immutable = true); // Returns the file's Java package name. -string FileJavaPackage(const FileDescriptor* file, bool immutable = true); +std::string FileJavaPackage(const FileDescriptor* file, bool immutable); // Returns output directory for the given package name. -string JavaPackageToDir(string package_name); - -// Converts the given fully-qualified name in the proto namespace to its -// fully-qualified name in the Java namespace, given that it is in the given -// file. -// TODO(xiaofeng): this method is deprecated and should be removed in the -// future. -string ToJavaName(const string& full_name, - const FileDescriptor* file); - -// TODO(xiaofeng): the following methods are kept for they are exposed -// publicly in //google/protobuf/compiler/java/names.h. They return -// immutable names only and should be removed after mutable API is -// integrated into google3. -string ClassName(const Descriptor* descriptor); -string ClassName(const EnumDescriptor* descriptor); -string ClassName(const ServiceDescriptor* descriptor); -string ClassName(const FileDescriptor* descriptor); +std::string JavaPackageToDir(std::string package_name); // Comma-separate list of option-specified interfaces implemented by the // Message, to follow the "implements" declaration of the Message definition. -string ExtraMessageInterfaces(const Descriptor* descriptor); +std::string ExtraMessageInterfaces(const Descriptor* descriptor); // Comma-separate list of option-specified interfaces implemented by the // MutableMessage, to follow the "implements" declaration of the MutableMessage // definition. -string ExtraMutableMessageInterfaces(const Descriptor* descriptor); +std::string ExtraMutableMessageInterfaces(const Descriptor* descriptor); // Comma-separate list of option-specified interfaces implemented by the // Builder, to follow the "implements" declaration of the Builder definition. -string ExtraBuilderInterfaces(const Descriptor* descriptor); +std::string ExtraBuilderInterfaces(const Descriptor* descriptor); // Comma-separate list of option-specified interfaces extended by the // MessageOrBuilder, to follow the "extends" declaration of the // MessageOrBuilder definition. -string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor); +std::string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor); // Get the unqualified Java class name for mutable messages. i.e. without // package or outer classnames. -inline string ShortMutableJavaClassName(const Descriptor* descriptor) { +inline std::string ShortMutableJavaClassName(const Descriptor* descriptor) { return descriptor->name(); } +// Whether the given descriptor is for one of the core descriptor protos. We +// cannot currently use the new runtime with core protos since there is a +// bootstrapping problem with obtaining their descriptors. +inline bool IsDescriptorProto(const Descriptor* descriptor) { + return descriptor->file()->name() == "net/proto2/proto/descriptor.proto" || + descriptor->file()->name() == "google/protobuf/descriptor.proto"; +} + +// Returns the stored type string used by the experimental runtime for oneof +// fields. +std::string GetOneofStoredType(const FieldDescriptor* field); + // Whether we should generate multiple java files for messages. -inline bool MultipleJavaFiles( - const FileDescriptor* descriptor, bool immutable) { +inline bool MultipleJavaFiles(const FileDescriptor* descriptor, + bool immutable) { return descriptor->options().java_multiple_files(); } + // Returns true if `descriptor` will be written to its own .java file. // `immutable` should be set to true if we're generating for the immutable API. template @@ -161,23 +167,26 @@ inline bool IsOwnFile(const ServiceDescriptor* descriptor, bool immutable) { // annotation data for that descriptor. `suffix` is usually empty, but may // (e.g.) be "OrBuilder" for some generated interfaces. template -string AnnotationFileName(const Descriptor* descriptor, const string& suffix) { +std::string AnnotationFileName(const Descriptor* descriptor, + const std::string& suffix) { return descriptor->name() + suffix + ".java.pb.meta"; } template void MaybePrintGeneratedAnnotation(Context* context, io::Printer* printer, Descriptor* descriptor, bool immutable, - const string& suffix = "") { - if (context->options().annotate_code && IsOwnFile(descriptor, immutable)) { + const std::string& suffix = "") { + if (IsOwnFile(descriptor, immutable)) { PrintGeneratedAnnotation(printer, '$', - AnnotationFileName(descriptor, suffix)); + context->options().annotate_code + ? AnnotationFileName(descriptor, suffix) + : ""); } } // Get the unqualified name that should be used for a field's field // number constant. -string FieldConstantName(const FieldDescriptor *field); +std::string FieldConstantName(const FieldDescriptor* field); // Returns the type of the FieldDescriptor. // This does nothing interesting for the open source release, but is used for @@ -205,16 +214,17 @@ const char* PrimitiveTypeName(JavaType type); // types. const char* BoxedPrimitiveTypeName(JavaType type); + // Get the name of the java enum constant representing this type. E.g., // "INT32" for FieldDescriptor::TYPE_INT32. The enum constant's full // name is "com.google.protobuf.WireFormat.FieldType.INT32". const char* FieldTypeName(const FieldDescriptor::Type field_type); class ClassNameResolver; -string DefaultValue(const FieldDescriptor* field, bool immutable, - ClassNameResolver* name_resolver); -inline string ImmutableDefaultValue(const FieldDescriptor* field, - ClassNameResolver* name_resolver) { +std::string DefaultValue(const FieldDescriptor* field, bool immutable, + ClassNameResolver* name_resolver); +inline std::string ImmutableDefaultValue(const FieldDescriptor* field, + ClassNameResolver* name_resolver) { return DefaultValue(field, true, name_resolver); } bool IsDefaultValueJavaDefault(const FieldDescriptor* field); @@ -223,24 +233,19 @@ bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field); // Does this message class have descriptor and reflection methods? inline bool HasDescriptorMethods(const Descriptor* descriptor, bool enforce_lite) { - return !enforce_lite && - descriptor->file()->options().optimize_for() != - FileOptions::LITE_RUNTIME; + return !enforce_lite; } inline bool HasDescriptorMethods(const EnumDescriptor* descriptor, bool enforce_lite) { - return !enforce_lite && - descriptor->file()->options().optimize_for() != - FileOptions::LITE_RUNTIME; + return !enforce_lite; } inline bool HasDescriptorMethods(const FileDescriptor* descriptor, bool enforce_lite) { - return !enforce_lite && - descriptor->options().optimize_for() != FileOptions::LITE_RUNTIME; + return !enforce_lite; } // Should we generate generic services for this file? -inline bool HasGenericServices(const FileDescriptor *file, bool enforce_lite) { +inline bool HasGenericServices(const FileDescriptor* file, bool enforce_lite) { return file->service_count() > 0 && HasDescriptorMethods(file, enforce_lite) && file->options().java_generic_services(); @@ -249,50 +254,50 @@ inline bool HasGenericServices(const FileDescriptor *file, bool enforce_lite) { // Methods for shared bitfields. // Gets the name of the shared bitfield for the given index. -string GetBitFieldName(int index); +std::string GetBitFieldName(int index); // Gets the name of the shared bitfield for the given bit index. // Effectively, GetBitFieldName(bitIndex / 32) -string GetBitFieldNameForBit(int bitIndex); +std::string GetBitFieldNameForBit(int bitIndex); // Generates the java code for the expression that returns the boolean value // of the bit of the shared bitfields for the given bit index. // Example: "((bitField1_ & 0x04) == 0x04)" -string GenerateGetBit(int bitIndex); +std::string GenerateGetBit(int bitIndex); // Generates the java code for the expression that sets the bit of the shared // bitfields for the given bit index. // Example: "bitField1_ = (bitField1_ | 0x04)" -string GenerateSetBit(int bitIndex); +std::string GenerateSetBit(int bitIndex); // Generates the java code for the expression that clears the bit of the shared // bitfields for the given bit index. // Example: "bitField1_ = (bitField1_ & ~0x04)" -string GenerateClearBit(int bitIndex); +std::string GenerateClearBit(int bitIndex); // Does the same as GenerateGetBit but operates on the bit field on a local // variable. This is used by the builder to copy the value in the builder to // the message. // Example: "((from_bitField1_ & 0x04) == 0x04)" -string GenerateGetBitFromLocal(int bitIndex); +std::string GenerateGetBitFromLocal(int bitIndex); // Does the same as GenerateSetBit but operates on the bit field on a local // variable. This is used by the builder to copy the value in the builder to // the message. // Example: "to_bitField1_ = (to_bitField1_ | 0x04)" -string GenerateSetBitToLocal(int bitIndex); +std::string GenerateSetBitToLocal(int bitIndex); // Does the same as GenerateGetBit but operates on the bit field on a local // variable. This is used by the parsing constructor to record if a repeated // field is mutable. // Example: "((mutable_bitField1_ & 0x04) == 0x04)" -string GenerateGetBitMutableLocal(int bitIndex); +std::string GenerateGetBitMutableLocal(int bitIndex); // Does the same as GenerateSetBit but operates on the bit field on a local // variable. This is used by the parsing constructor to record if a repeated // field is mutable. // Example: "mutable_bitField1_ = (mutable_bitField1_ | 0x04)" -string GenerateSetBitMutableLocal(int bitIndex); +std::string GenerateSetBitMutableLocal(int bitIndex); // Returns whether the JavaType is a reference type. bool IsReferenceType(JavaType type); @@ -338,9 +343,28 @@ inline bool HasPackedFields(const Descriptor* descriptor) { // them has a required field. Return true if a required field is found. bool HasRequiredFields(const Descriptor* descriptor); -// Whether a .proto file supports field presence test for non-message types. -inline bool SupportFieldPresence(const FileDescriptor* descriptor) { - return descriptor->syntax() != FileDescriptor::SYNTAX_PROTO3; +inline bool IsProto2(const FileDescriptor* descriptor) { + return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2; +} + +inline bool IsRealOneof(const FieldDescriptor* descriptor) { + return descriptor->containing_oneof() && + !descriptor->containing_oneof()->is_synthetic(); +} + +inline bool HasHazzer(const FieldDescriptor* descriptor) { + return !descriptor->is_repeated() && + (descriptor->message_type() || descriptor->has_optional_keyword() || + IsProto2(descriptor->file()) || IsRealOneof(descriptor)); +} + +inline bool HasHasbit(const FieldDescriptor* descriptor) { + // Note that currently message fields inside oneofs have hasbits. This is + // surprising, as the oneof case should avoid any need for a hasbit. But if + // you change this method to remove hasbits for oneofs, a few tests fail. + // TODO(b/124347790): remove hasbits for oneofs + return !descriptor->is_repeated() && + (descriptor->has_optional_keyword() || IsProto2(descriptor->file())); } // Whether generate classes expose public PARSER instances. @@ -356,7 +380,11 @@ inline bool SupportUnknownEnumValue(const FileDescriptor* descriptor) { return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3; } -// Check whether a mesasge has repeated fields. +inline bool SupportUnknownEnumValue(const FieldDescriptor* field) { + return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3; +} + +// Check whether a message has repeated fields. bool HasRepeatedFields(const Descriptor* descriptor); inline bool IsMapEntry(const Descriptor* descriptor) { @@ -371,17 +399,46 @@ inline bool IsAnyMessage(const Descriptor* descriptor) { return descriptor->full_name() == "google.protobuf.Any"; } +inline bool IsWrappersProtoFile(const FileDescriptor* descriptor) { + return descriptor->name() == "google/protobuf/wrappers.proto"; +} + inline bool CheckUtf8(const FieldDescriptor* descriptor) { return descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 || - descriptor->file()->options().java_string_check_utf8(); + descriptor->file()->options().java_string_check_utf8(); } -inline string GeneratedCodeVersionSuffix() { +inline std::string GeneratedCodeVersionSuffix() { return "V3"; } + +void WriteUInt32ToUtf16CharSequence(uint32 number, std::vector* output); + +inline void WriteIntToUtf16CharSequence(int value, + std::vector* output) { + WriteUInt32ToUtf16CharSequence(static_cast(value), output); +} + +// Escape a UTF-16 character so it can be embedded in a Java string literal. +void EscapeUtf16ToString(uint16 code, std::string* output); + +// Only the lowest two bytes of the return value are used. The lowest byte +// is the integer value of a j/c/g/protobuf/FieldType enum. For the other +// byte: +// bit 0: whether the field is required. +// bit 1: whether the field requires UTF-8 validation. +// bit 2: whether the field needs isInitialized check. +// bit 3: whether the field is a map field with proto2 enum value. +// bits 4-7: unused +int GetExperimentalJavaFieldType(const FieldDescriptor* field); + +// To get the total number of entries need to be built for experimental runtime +// and the first field number that are not in the table part +std::pair GetTableDrivenNumberOfEntriesAndLookUpStartFieldNumber( + const FieldDescriptor** fields, int count); } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc deleted file mode 100644 index abf8e55cf7192..0000000000000 --- a/src/google/protobuf/compiler/java/java_lazy_message_field.cc +++ /dev/null @@ -1,814 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: niwasaki@google.com (Naoki Iwasaki) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace java { - -ImmutableLazyMessageFieldGenerator:: -ImmutableLazyMessageFieldGenerator( - const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableMessageFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { -} - -ImmutableLazyMessageFieldGenerator::~ImmutableLazyMessageFieldGenerator() {} - -void ImmutableLazyMessageFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private com.google.protobuf.LazyFieldLite $name$_ =\n" - " new com.google.protobuf.LazyFieldLite();\n"); - - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" - " return $name$_;\n" - "}\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // When using nested-builders, the code initially works just like the - // non-nested builder case. It only creates a nested builder lazily on - // demand and then forever delegates to it after creation. - - printer->Print(variables_, - "private com.google.protobuf.LazyFieldLite $name$_ =\n" - " new com.google.protobuf.LazyFieldLite();\n"); - - printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.SingleFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" - "\n"); - - // The comments above the methods below are based on a hypothetical - // field of type "Field" called "Field". - - // boolean hasField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n" - "}\n"); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$($type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "$name$_.setValue(value);\n" - "$on_changed$\n", - - NULL, // Lazy fields are supported only for lite-runtime. - - "$set_has_field_bit_builder$;\n" - "return this;\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " $type$.Builder builderForValue)", - - "$name$_.setValue(builderForValue.build());\n" - "$on_changed$\n", - - NULL, - - "$set_has_field_bit_builder$;\n" - "return this;\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder merge$capitalized_name$($type$ value)", - - "if ($get_has_field_bit_builder$ &&\n" - " !$name$_.containsDefaultInstance()) {\n" - " $name$_.setValue(\n" - " $type$.newBuilder(\n" - " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" - "} else {\n" - " $name$_.setValue(value);\n" - "}\n" - "$on_changed$\n", - - NULL, - - "$set_has_field_bit_builder$;\n" - "return this;\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder clear$capitalized_name$()", - - "$name$_.clear();\n" - "$on_changed$\n", - - NULL, - - "$clear_has_field_bit_builder$;\n" - "return this;\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" - " $set_has_field_bit_builder$;\n" - " $on_changed$\n" - " return get$capitalized_name$FieldBuilder().getBuilder();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" - " if ($name$Builder_ != null) {\n" - " return $name$Builder_.getMessageOrBuilder();\n" - " } else {\n" - " return $name$_;\n" - " }\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private com.google.protobuf.SingleFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " $name$_,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); -} - - -void ImmutableLazyMessageFieldGenerator:: -GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.clear();\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.clear();\n"); - printer->Print(variables_, "$clear_has_field_bit_builder$;\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " $name$_.merge(other.$name$_);\n" - " $set_has_field_bit_builder$;\n" - "}\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); - - printer->Print(variables_, - "result.$name$_.set(\n" - " $name$_);\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_.setByteString(input.readBytes(), extensionRegistry);\n"); - printer->Print(variables_, - "$set_has_field_bit_message$;\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - // Do not de-serialize lazy fields. - printer->Print(variables_, - "if ($get_has_field_bit_message$) {\n" - " output.writeBytes($number$, $name$_.toByteString());\n" - "}\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_has_field_bit_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, $name$_);\n" - "}\n"); -} - -// =================================================================== - -ImmutableLazyMessageOneofFieldGenerator:: -ImmutableLazyMessageOneofFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableLazyMessageFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { - const OneofGeneratorInfo* info = - context->GetOneofGeneratorInfo(descriptor->containing_oneof()); - SetCommonOneofVariables(descriptor, info, &variables_); - variables_["lazy_type"] = "com.google.protobuf.LazyFieldLite"; -} - -ImmutableLazyMessageOneofFieldGenerator:: -~ImmutableLazyMessageOneofFieldGenerator() {} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n" - " $type$.getDefaultInstance());\n" - " }\n" - " return $type$.getDefaultInstance();\n" - "}\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // boolean hasField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n" - " $type$.getDefaultInstance());\n" - " }\n" - " return $type$.getDefaultInstance();\n" - "}\n"); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$($type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - "}\n" - "(($lazy_type$) $oneof_name$_).setValue(value);\n" - "$on_changed$\n", - - NULL, // Lazy fields are supported only for lite-runtime. - - "return this;\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " $type$.Builder builderForValue)", - - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - "}\n" - "(($lazy_type$) $oneof_name$_).setValue(builderForValue.build());\n" - "$on_changed$\n", - - NULL, - - "return this;\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder merge$capitalized_name$($type$ value)", - - "if ($has_oneof_case_message$ &&\n" - " !(($lazy_type$) $oneof_name$_).containsDefaultInstance()) {\n" - " (($lazy_type$) $oneof_name$_).setValue(\n" - " $type$.newBuilder(\n" - " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" - "} else {\n" - " if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - " }\n" - " (($lazy_type$) $oneof_name$_).setValue(value);\n" - "}\n" - "$on_changed$\n", - - NULL, - - "return this;\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder clear$capitalized_name$()", - - "if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " $on_changed$\n" - "}\n", - - NULL, - - "return this;\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - "}\n" - "(($lazy_type$) $oneof_name$_).merge(\n" - " ($lazy_type$) other.$oneof_name$_);\n" - "$set_oneof_case_message$;\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n"); - printer->Indent(); - - printer->Print(variables_, - "result.$oneof_name$_ = new $lazy_type$();\n" - "(($lazy_type$) result.$oneof_name$_).set(\n" - " (($lazy_type$) $oneof_name$_));\n"); - printer->Outdent(); - printer->Print("}\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - "}\n" - "(($lazy_type$) $oneof_name$_).setByteString(\n" - " input.readBytes(), extensionRegistry);\n" - "$set_oneof_case_message$;\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - // Do not de-serialize lazy fields. - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.writeBytes(\n" - " $number$, (($lazy_type$) $oneof_name$_).toByteString());\n" - "}\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, ($lazy_type$) $oneof_name$_);\n" - "}\n"); -} - -// =================================================================== - -RepeatedImmutableLazyMessageFieldGenerator:: -RepeatedImmutableLazyMessageFieldGenerator( - const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : RepeatedImmutableMessageFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { -} - - -RepeatedImmutableLazyMessageFieldGenerator:: -~RepeatedImmutableLazyMessageFieldGenerator() {} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private java.util.List $name$_;\n"); - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$>\n" - " get$capitalized_name$List() {\n" - " java.util.List<$type$> list =\n" - " new java.util.ArrayList<$type$>($name$_.size());\n" - " for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n" - " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n" - " }\n" - " return list;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List\n" - " get$capitalized_name$OrBuilderList() {\n" - " return get$capitalized_name$List();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int get$capitalized_name$Count() {\n" - " return $name$_.size();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$(int index) {\n" - " return ($type$)\n" - " $name$_.get(index).getValue($type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index) {\n" - " return ($type$OrBuilder)\n" - " $name$_.get(index).getValue($type$.getDefaultInstance());\n" - "}\n"); -} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // When using nested-builders, the code initially works just like the - // non-nested builder case. It only creates a nested builder lazily on - // demand and then forever delegates to it after creation. - - printer->Print(variables_, - "private java.util.List $name$_ =\n" - " java.util.Collections.emptyList();\n" - - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$get_mutable_bit_builder$) {\n" - " $name$_ =\n" - " new java.util.ArrayList(\n" - " $name$_);\n" - " $set_mutable_bit_builder$;\n" - " }\n" - "}\n" - "\n"); - - printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n" - "\n"); - - // The comments above the methods below are based on a hypothetical - // repeated field of type "Field" called "RepeatedField". - - // List getRepeatedFieldList() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public java.util.List<$type$> get$capitalized_name$List()", - - "java.util.List<$type$> list =\n" - " new java.util.ArrayList<$type$>($name$_.size());\n" - "for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n" - " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n" - "}\n" - "return java.util.Collections.unmodifiableList(list);\n", - - "return $name$Builder_.getMessageList();\n", - - NULL); - - // int getRepeatedFieldCount() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public int get$capitalized_name$Count()", - - "return $name$_.size();\n", - "return $name$Builder_.getCount();\n", - - NULL); - - // Field getRepeatedField(int index) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public $type$ get$capitalized_name$(int index)", - - "return ($type$) $name$_.get(index).getValue(\n" - " $type$.getDefaultInstance());\n", - - "return $name$Builder_.getMessage(index);\n", - - NULL); - - // Builder setRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, $type$ value)", - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" - "$on_changed$\n", - "$name$Builder_.setMessage(index, value);\n", - "return this;\n"); - - // Builder setRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, $type$.Builder builderForValue)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "$on_changed$\n", - - "$name$Builder_.setMessage(index, builderForValue.build());\n", - - "return this;\n"); - - // Builder addRepeatedField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$($type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(com.google.protobuf.LazyFieldLite.fromValue(value));\n" - - "$on_changed$\n", - - "$name$Builder_.addMessage(value);\n", - - "return this;\n"); - - // Builder addRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$(\n" - " int index, $type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" - "$on_changed$\n", - - "$name$Builder_.addMessage(index, value);\n", - - "return this;\n"); - - // Builder addRepeatedField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$(\n" - " $type$.Builder builderForValue)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "$on_changed$\n", - - "$name$Builder_.addMessage(builderForValue.build());\n", - - "return this;\n"); - - // Builder addRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$(\n" - " int index, $type$.Builder builderForValue)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "$on_changed$\n", - - "$name$Builder_.addMessage(index, builderForValue.build());\n", - - "return this;\n"); - - // Builder addAllRepeatedField(Iterable values) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder addAll$capitalized_name$(\n" - " java.lang.Iterable values)", - - "ensure$capitalized_name$IsMutable();\n" - "for (com.google.protobuf.MessageLite v : values) {\n" - " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(v));\n" - "}\n" - "$on_changed$\n", - - "$name$Builder_.addAllMessages(values);\n", - - "return this;\n"); - - // Builder clearAllRepeatedField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder clear$capitalized_name$()", - - "$name$_ = java.util.Collections.emptyList();\n" - "$clear_mutable_bit_builder$;\n" - "$on_changed$\n", - - "$name$Builder_.clear();\n", - - "return this;\n"); - - // Builder removeRepeatedField(int index) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder remove$capitalized_name$(int index)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.remove(index);\n" - "$on_changed$\n", - - "$name$Builder_.remove(index);\n", - - "return this;\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n" - " int index) {\n" - " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index) {\n" - " if ($name$Builder_ == null) {\n" - " return $name$_.get(index);" - " } else {\n" - " return $name$Builder_.getMessageOrBuilder(index);\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List \n" - " get$capitalized_name$OrBuilderList() {\n" - " if ($name$Builder_ != null) {\n" - " return $name$Builder_.getMessageOrBuilderList();\n" - " } else {\n" - " return java.util.Collections.unmodifiableList($name$_);\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" - " $type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n" - " int index) {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" - " index, $type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$.Builder> \n" - " get$capitalized_name$BuilderList() {\n" - " return get$capitalized_name$FieldBuilder().getBuilderList();\n" - "}\n" - "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " $name$_,\n" - " $get_mutable_bit_builder$,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); -} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ =\n" - " new java.util.ArrayList();\n" - " $set_mutable_bit_parser$;\n" - "}\n" - "$name$_.add(new com.google.protobuf.LazyFieldLite(\n" - " extensionRegistry, input.readBytes()));\n"); -} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeBytes($number$, $name$_.get(i).toByteString());\n" - "}\n"); -} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, $name$_.get(i));\n" - "}\n"); -} - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.h b/src/google/protobuf/compiler/java/java_lazy_message_field.h deleted file mode 100644 index b1b7f2820e495..0000000000000 --- a/src/google/protobuf/compiler/java/java_lazy_message_field.h +++ /dev/null @@ -1,121 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: niwasaki@google.com (Naoki Iwasaki) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ - -#include -#include - -namespace google { -namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - } - } -} - -namespace protobuf { -namespace compiler { -namespace java { - -class ImmutableLazyMessageFieldGenerator - : public ImmutableMessageFieldGenerator { - public: - explicit ImmutableLazyMessageFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableLazyMessageFieldGenerator(); - - // overroads ImmutableMessageFieldGenerator --------------------------------- - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateInitializationCode(io::Printer* printer) const; - void GenerateBuilderClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageFieldGenerator); -}; - -class ImmutableLazyMessageOneofFieldGenerator - : public ImmutableLazyMessageFieldGenerator { - public: - ImmutableLazyMessageOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableLazyMessageOneofFieldGenerator(); - - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageOneofFieldGenerator); -}; - -class RepeatedImmutableLazyMessageFieldGenerator - : public RepeatedImmutableMessageFieldGenerator { - public: - explicit RepeatedImmutableLazyMessageFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~RepeatedImmutableLazyMessageFieldGenerator(); - - // overroads RepeatedImmutableMessageFieldGenerator ------------------------- - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableLazyMessageFieldGenerator); -}; - -} // namespace java -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc deleted file mode 100644 index 51bb11f1c7182..0000000000000 --- a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc +++ /dev/null @@ -1,725 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: niwasaki@google.com (Naoki Iwasaki) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace java { - -ImmutableLazyMessageFieldLiteGenerator:: -ImmutableLazyMessageFieldLiteGenerator( - const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableMessageFieldLiteGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { -} - -ImmutableLazyMessageFieldLiteGenerator:: -~ImmutableLazyMessageFieldLiteGenerator() {} - -void ImmutableLazyMessageFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private com.google.protobuf.LazyFieldLite $name$_;"); - - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); - } else { - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $name$_ != null;\n" - "}\n"); - } - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($name$_ == null) {\n" - " return $type$.getDefaultInstance();\n" - " }\n" - " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n" - "}\n"); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " if ($name$_ == null) {\n" - " $name$_ = new com.google.protobuf.LazyFieldLite();\n" - " }\n" - " $name$_.setValue(value);\n" - " $set_has_field_bit_message$\n" - "}\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " if ($name$_ == null) {\n" - " $name$_ = new com.google.protobuf.LazyFieldLite();\n" - " }\n" - " $name$_.setValue(builderForValue.build());\n" - " $set_has_field_bit_message$\n" - "}\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void merge$capitalized_name$($type$ value) {\n" - " if (has$capitalized_name$() &&\n" - " !$name$_.containsDefaultInstance()) {\n" - " $name$_.setValue(\n" - " $type$.newBuilder(\n" - " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" - " } else {\n" - " if ($name$_ == null) {\n" - " $name$_ = new com.google.protobuf.LazyFieldLite();\n" - " }\n" - " $name$_.setValue(value);\n" - " $set_has_field_bit_message$\n" - " }\n" - "}\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " $name$_ = null;\n" - " $clear_has_field_bit_message$;\n" - "}\n"); -} - -void ImmutableLazyMessageFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // The comments above the methods below are based on a hypothetical - // field of type "Field" called "Field". - - // boolean hasField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return instance.has$capitalized_name$();\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return instance.get$capitalized_name$();\n" - "}\n"); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(value);\n" - " return this;\n" - "}\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(builderForValue);\n" - " return this;\n" - "}\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n" - " copyOnWrite();\n" - " instance.merge$capitalized_name$(value);\n" - " return this;\n" - "}\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); -} - - -void ImmutableLazyMessageFieldLiteGenerator:: -GenerateInitializationCode(io::Printer* printer) const {} - -void ImmutableLazyMessageFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = visitor.visitLazyMessage($name$_, other.$name$_);\n"); -} - -void ImmutableLazyMessageFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($name$_ == null) {\n" - " $name$_ = new com.google.protobuf.LazyFieldLite();\n" - "}\n" - "$name$_.mergeFrom(input, extensionRegistry);\n"); - printer->Print(variables_, - "$set_has_field_bit_message$\n"); -} - -void ImmutableLazyMessageFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - // Do not de-serialize lazy fields. - printer->Print(variables_, - "if (has$capitalized_name$()) {\n" - " output.writeBytes($number$, $name$_.toByteString());\n" - "}\n"); -} - -void ImmutableLazyMessageFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if (has$capitalized_name$()) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, $name$_);\n" - "}\n"); -} - - -// =================================================================== - -ImmutableLazyMessageOneofFieldLiteGenerator:: -ImmutableLazyMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableLazyMessageFieldLiteGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { - const OneofGeneratorInfo* info = - context->GetOneofGeneratorInfo(descriptor->containing_oneof()); - SetCommonOneofVariables(descriptor, info, &variables_); - variables_["lazy_type"] = "com.google.protobuf.LazyFieldLite"; -} - -ImmutableLazyMessageOneofFieldLiteGenerator:: -~ImmutableLazyMessageOneofFieldLiteGenerator() {} - -void ImmutableLazyMessageOneofFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n" - " $type$.getDefaultInstance());\n" - " }\n" - " return $type$.getDefaultInstance();\n" - "}\n"); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - " }\n" - " (($lazy_type$) $oneof_name$_).setValue(value);\n" - "}\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - " }\n" - " (($lazy_type$) $oneof_name$_).setValue(builderForValue.build());\n" - "}\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void merge$capitalized_name$($type$ value) {\n" - " if ($has_oneof_case_message$ &&\n" - " !(($lazy_type$) $oneof_name$_).containsDefaultInstance()) {\n" - " (($lazy_type$) $oneof_name$_).setValue(\n" - " $type$.newBuilder(\n" - " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" - " } else {\n" - " if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - " }\n" - " (($lazy_type$) $oneof_name$_).setValue(value);\n" - " }\n" - "}\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " }\n" - "}\n"); -} - -void ImmutableLazyMessageOneofFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // boolean hasField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return instance.has$capitalized_name$();\n" - "}\n"); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return instance.get$capitalized_name$();\n" - "}\n"); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(value);\n" - " return this;\n" - "}\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(builderForValue);\n" - " return this;\n" - "}\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n" - " copyOnWrite();\n" - " instance.merge$capitalized_name$(value);\n" - " return this;\n" - "}\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); -} - -void ImmutableLazyMessageOneofFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - printer->Print(variables_, - "$oneof_name$_ = visitor.visitOneofLazyMessage(\n" - " $has_oneof_case_message$,\n" - " ($lazy_type$) $oneof_name$_,\n" - " ($lazy_type$) other.$oneof_name$_);\n"); -} - -void ImmutableLazyMessageOneofFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - "}\n" - "(($lazy_type$) $oneof_name$_).mergeFrom(input, extensionRegistry);\n" - "$set_oneof_case_message$;\n"); -} - -void ImmutableLazyMessageOneofFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - // Do not de-serialize lazy fields. - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.writeBytes(\n" - " $number$, (($lazy_type$) $oneof_name$_).toByteString());\n" - "}\n"); -} - -void ImmutableLazyMessageOneofFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, ($lazy_type$) $oneof_name$_);\n" - "}\n"); -} - - -// =================================================================== - -RepeatedImmutableLazyMessageFieldLiteGenerator:: -RepeatedImmutableLazyMessageFieldLiteGenerator( - const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : RepeatedImmutableMessageFieldLiteGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { -} - - -RepeatedImmutableLazyMessageFieldLiteGenerator:: -~RepeatedImmutableLazyMessageFieldLiteGenerator() {} - -void RepeatedImmutableLazyMessageFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private com.google.protobuf.Internal.ProtobufList<\n" - " com.google.protobuf.LazyFieldLite> $name$_;\n"); - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$>\n" - " get$capitalized_name$List() {\n" - " java.util.List<$type$> list =\n" - " new java.util.ArrayList<$type$>($name$_.size());\n" - " for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n" - " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n" - " }\n" - " return java.util.Collections.unmodifiableList(list);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List\n" - " get$capitalized_name$OrBuilderList() {\n" - " return get$capitalized_name$List();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int get$capitalized_name$Count() {\n" - " return $name$_.size();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$(int index) {\n" - " return ($type$)\n" - " $name$_.get(index).getValue($type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index) {\n" - " return ($type$OrBuilder)\n" - " $name$_.get(index).getValue($type$.getDefaultInstance());\n" - "}\n"); - - printer->Print(variables_, - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$is_mutable$) {\n" - " $name$_ =\n" - " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" - " }\n" - "}\n" - "\n"); - - // Builder setRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$(\n" - " int index, $type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(\n" - " index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" - "}\n"); - - // Builder setRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$(\n" - " int index, $type$.Builder builderForValue) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "}\n"); - - // Builder addRepeatedField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(value));\n" - "}\n"); - - // Builder addRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$(\n" - " int index, $type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(\n" - " index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" - "}\n"); - - // Builder addRepeatedField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "}\n"); - - // Builder addRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$(\n" - " int index, $type$.Builder builderForValue) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "}\n"); - - // Builder addAllRepeatedField(Iterable values) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void addAll$capitalized_name$(\n" - " java.lang.Iterable values) {\n" - " ensure$capitalized_name$IsMutable();\n" - " for (com.google.protobuf.MessageLite v : values) {\n" - " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(v));\n" - " }\n" - "}\n"); - - // Builder clearAllRepeatedField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " $name$_ = emptyProtobufList();\n" - "}\n"); - - // Builder removeRepeatedField(int index) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void remove$capitalized_name$(int index) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.remove(index);\n" - "}\n"); -} - -void RepeatedImmutableLazyMessageFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // List getRepeatedFieldList() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" - " return java.util.Collections.unmodifiableList(\n" - " instance.get$capitalized_name$List());\n" - "}\n"); - - // int getRepeatedFieldCount() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int get$capitalized_name$Count() {\n" - " return instance.get$capitalized_name$Count();\n" - "}\n"); - - // Field getRepeatedField(int index) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$(int index) {\n" - " return instance.get$capitalized_name$(index);\n" - "}\n"); - - // Builder setRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, $type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(index, value);\n" - " return this;\n" - "}\n"); - - // Builder setRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(index, builderForValue);\n" - " return this;\n" - "}\n"); - - // Builder addRepeatedField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(value);\n" - " return this;\n" - "}\n"); - - // Builder addRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder add$capitalized_name$(\n" - " int index, $type$ value) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(index, value);\n" - " return this;\n" - "}\n"); - - // Builder addRepeatedField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder add$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(builderForValue);\n" - " return this;\n" - "}\n"); - - // Builder addRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder add$capitalized_name$(\n" - " int index, $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(index, builderForValue);\n" - " return this;\n" - "}\n"); - - // Builder addAllRepeatedField(Iterable values) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder addAll$capitalized_name$(\n" - " java.lang.Iterable values) {\n" - " copyOnWrite();\n" - " instance.addAll$capitalized_name$(values);\n" - " return this;\n" - "}\n"); - - // Builder clearAllRepeatedField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); - - // Builder removeRepeatedField(int index) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder remove$capitalized_name$(int index) {\n" - " copyOnWrite();\n" - " instance.remove$capitalized_name$(index);\n" - " return this;\n" - "}\n"); -} - -void RepeatedImmutableLazyMessageFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!$is_mutable$) {\n" - " $name$_ =\n" - " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" - "}\n" - "$name$_.add(new com.google.protobuf.LazyFieldLite(\n" - " extensionRegistry, input.readBytes()));\n"); -} - -void RepeatedImmutableLazyMessageFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeBytes($number$, $name$_.get(i).toByteString());\n" - "}\n"); -} - -void RepeatedImmutableLazyMessageFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, $name$_.get(i));\n" - "}\n"); -} - - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h deleted file mode 100644 index 65b84fbcabb01..0000000000000 --- a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h +++ /dev/null @@ -1,121 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: niwasaki@google.com (Naoki Iwasaki) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__ - -#include -#include - -namespace google { -namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - } - } -} - -namespace protobuf { -namespace compiler { -namespace java { - -class ImmutableLazyMessageFieldLiteGenerator - : public ImmutableMessageFieldLiteGenerator { - public: - explicit ImmutableLazyMessageFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableLazyMessageFieldLiteGenerator(); - - // overroads ImmutableMessageFieldLiteGenerator ------------------------------ - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateInitializationCode(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageFieldLiteGenerator); -}; - -class ImmutableLazyMessageOneofFieldLiteGenerator - : public ImmutableLazyMessageFieldLiteGenerator { - public: - ImmutableLazyMessageOneofFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableLazyMessageOneofFieldLiteGenerator(); - - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageOneofFieldLiteGenerator); -}; - -class RepeatedImmutableLazyMessageFieldLiteGenerator - : public RepeatedImmutableMessageFieldLiteGenerator { - public: - explicit RepeatedImmutableLazyMessageFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~RepeatedImmutableLazyMessageFieldLiteGenerator(); - - // overroads RepeatedImmutableMessageFieldLiteGenerator ---------------------- - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableLazyMessageFieldLiteGenerator); -}; - -} // namespace java -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc index b22a21993f4a9..5db199d38fa46 100644 --- a/src/google/protobuf/compiler/java/java_map_field.cc +++ b/src/google/protobuf/compiler/java/java_map_field.cc @@ -57,9 +57,8 @@ const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) { return message->FindFieldByName("value"); } -string TypeName(const FieldDescriptor* field, - ClassNameResolver* name_resolver, - bool boxed) { +std::string TypeName(const FieldDescriptor* field, + ClassNameResolver* name_resolver, bool boxed) { if (GetJavaType(field) == JAVATYPE_MESSAGE) { return name_resolver->GetImmutableClassName(field->message_type()); } else if (GetJavaType(field) == JAVATYPE_ENUM) { @@ -70,17 +69,15 @@ string TypeName(const FieldDescriptor* field, } } -string WireType(const FieldDescriptor* field) { +std::string WireType(const FieldDescriptor* field) { return "com.google.protobuf.WireFormat.FieldType." + - string(FieldTypeName(field->type())); + std::string(FieldTypeName(field->type())); } -void SetMessageVariables(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - const FieldGeneratorInfo* info, +void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, const FieldGeneratorInfo* info, Context* context, - std::map* variables) { + std::map* variables) { SetCommonFieldVariables(descriptor, info, variables); ClassNameResolver* name_resolver = context->GetNameResolver(); @@ -92,17 +89,21 @@ void SetMessageVariables(const FieldDescriptor* descriptor, const JavaType valueJavaType = GetJavaType(value); (*variables)["key_type"] = TypeName(key, name_resolver, false); - string boxed_key_type = TypeName(key, name_resolver, true); + std::string boxed_key_type = TypeName(key, name_resolver, true); (*variables)["boxed_key_type"] = boxed_key_type; // Used for calling the serialization function. (*variables)["short_key_type"] = boxed_key_type.substr(boxed_key_type.rfind('.') + 1); (*variables)["key_wire_type"] = WireType(key); (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver); - (*variables)["key_null_check"] = IsReferenceType(keyJavaType) ? - "if (key == null) { throw new java.lang.NullPointerException(); }" : ""; - (*variables)["value_null_check"] = IsReferenceType(valueJavaType) ? - "if (value == null) { throw new java.lang.NullPointerException(); }" : ""; + (*variables)["key_null_check"] = + IsReferenceType(keyJavaType) + ? "if (key == null) { throw new java.lang.NullPointerException(); }" + : ""; + (*variables)["value_null_check"] = + IsReferenceType(valueJavaType) + ? "if (value == null) { throw new java.lang.NullPointerException(); }" + : ""; if (valueJavaType == JAVATYPE_ENUM) { // We store enums as Integers internally. (*variables)["value_type"] = "int"; @@ -133,8 +134,8 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"]; // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler - (*variables)["deprecation"] = descriptor->options().deprecated() - ? "@java.lang.Deprecated " : ""; + (*variables)["deprecation"] = + descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; (*variables)["on_changed"] = "onChanged();"; // For repeated fields, one bit is used for whether the array is immutable @@ -144,62 +145,51 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["set_mutable_bit_parser"] = GenerateSetBitMutableLocal(builderBitIndex); - (*variables)["default_entry"] = (*variables)["capitalized_name"] + - "DefaultEntryHolder.defaultEntry"; + (*variables)["default_entry"] = + (*variables)["capitalized_name"] + "DefaultEntryHolder.defaultEntry"; (*variables)["map_field_parameter"] = (*variables)["default_entry"]; (*variables)["descriptor"] = - name_resolver->GetImmutableClassName(descriptor->file()) + - ".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) + - "_descriptor, "; + name_resolver->GetImmutableClassName(descriptor->file()) + ".internal_" + + UniqueFileScopeIdentifier(descriptor->message_type()) + "_descriptor, "; (*variables)["ver"] = GeneratedCodeVersionSuffix(); } } // namespace -ImmutableMapFieldGenerator:: -ImmutableMapFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { +ImmutableMapFieldGenerator::ImmutableMapFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + Context* context) + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - context, &variables_); + context->GetFieldGeneratorInfo(descriptor), context, + &variables_); } -ImmutableMapFieldGenerator:: -~ImmutableMapFieldGenerator() {} +ImmutableMapFieldGenerator::~ImmutableMapFieldGenerator() {} -int ImmutableMapFieldGenerator::GetNumBitsForMessage() const { - return 0; -} +int ImmutableMapFieldGenerator::GetNumBitsForMessage() const { return 0; } -int ImmutableMapFieldGenerator::GetNumBitsForBuilder() const { - return 1; -} +int ImmutableMapFieldGenerator::GetNumBitsForBuilder() const { return 1; } -void ImmutableMapFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { +void ImmutableMapFieldGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$int ${$get$capitalized_name$Count$}$();\n"); + printer->Print(variables_, + "$deprecation$int ${$get$capitalized_name$Count$}$();\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$boolean ${$contains$capitalized_name$$}$(\n" - " $key_type$ key);\n"); + printer->Print(variables_, + "$deprecation$boolean ${$contains$capitalized_name$$}$(\n" + " $key_type$ key);\n"); printer->Annotate("{", "}", descriptor_); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { - printer->Print( - variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "java.util.Map<$boxed_key_type$, $value_enum_type$>\n" - "${$get$capitalized_name$$}$();\n"); + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "${$get$capitalized_name$$}$();\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print( @@ -231,63 +221,55 @@ GenerateInterfaceMembers(io::Printer* printer) const { "${$get$capitalized_name$Value$}$();\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$java.util.Map<$type_parameters$>\n" - "${$get$capitalized_name$ValueMap$}$();\n"); + printer->Print(variables_, + "$deprecation$java.util.Map<$type_parameters$>\n" + "${$get$capitalized_name$ValueMap$}$();\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n" - " $key_type$ key,\n" - " $value_type$ defaultValue);\n"); + printer->Print(variables_, + "$deprecation$\n" + "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n" + " $key_type$ key,\n" + " $value_type$ defaultValue);\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n" - " $key_type$ key);\n"); + printer->Print(variables_, + "$deprecation$\n" + "$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n" + " $key_type$ key);\n"); printer->Annotate("{", "}", descriptor_); } } else { - printer->Print( - variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "java.util.Map<$type_parameters$>\n" - "${$get$capitalized_name$$}$();\n"); + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "java.util.Map<$type_parameters$>\n" + "${$get$capitalized_name$$}$();\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$java.util.Map<$type_parameters$>\n" - "${$get$capitalized_name$Map$}$();\n"); + printer->Print(variables_, + "$deprecation$java.util.Map<$type_parameters$>\n" + "${$get$capitalized_name$Map$}$();\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "$value_type$ ${$get$capitalized_name$OrDefault$}$(\n" - " $key_type$ key,\n" - " $value_type$ defaultValue);\n"); + printer->Print(variables_, + "$deprecation$\n" + "$value_type$ ${$get$capitalized_name$OrDefault$}$(\n" + " $key_type$ key,\n" + " $value_type$ defaultValue);\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "$value_type$ ${$get$capitalized_name$OrThrow$}$(\n" - " $key_type$ key);\n"); + printer->Print(variables_, + "$deprecation$\n" + "$value_type$ ${$get$capitalized_name$OrThrow$}$(\n" + " $key_type$ key);\n"); printer->Annotate("{", "}", descriptor_); } } -void ImmutableMapFieldGenerator:: -GenerateMembers(io::Printer* printer) const { +void ImmutableMapFieldGenerator::GenerateMembers(io::Printer* printer) const { printer->Print( variables_, "private static final class $capitalized_name$DefaultEntryHolder {\n" @@ -301,18 +283,17 @@ GenerateMembers(io::Printer* printer) const { " $value_wire_type$,\n" " $value_default_value$);\n" "}\n"); - printer->Print( - variables_, - "private com.google.protobuf.MapField<\n" - " $type_parameters$> $name$_;\n" - "private com.google.protobuf.MapField<$type_parameters$>\n" - "internalGet$capitalized_name$() {\n" - " if ($name$_ == null) {\n" - " return com.google.protobuf.MapField.emptyMapField(\n" - " $map_field_parameter$);\n" - " }\n" - " return $name$_;\n" - "}\n"); + printer->Print(variables_, + "private com.google.protobuf.MapField<\n" + " $type_parameters$> $name$_;\n" + "private com.google.protobuf.MapField<$type_parameters$>\n" + "internalGet$capitalized_name$() {\n" + " if ($name$_ == null) {\n" + " return com.google.protobuf.MapField.emptyMapField(\n" + " $map_field_parameter$);\n" + " }\n" + " return $name$_;\n" + "}\n"); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { printer->Print( variables_, @@ -336,53 +317,50 @@ GenerateMembers(io::Printer* printer) const { GenerateMapGetters(printer); } -void ImmutableMapFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - printer->Print( - variables_, - "private com.google.protobuf.MapField<\n" - " $type_parameters$> $name$_;\n" - "private com.google.protobuf.MapField<$type_parameters$>\n" - "internalGet$capitalized_name$() {\n" - " if ($name$_ == null) {\n" - " return com.google.protobuf.MapField.emptyMapField(\n" - " $map_field_parameter$);\n" - " }\n" - " return $name$_;\n" - "}\n" - "private com.google.protobuf.MapField<$type_parameters$>\n" - "internalGetMutable$capitalized_name$() {\n" - " $on_changed$;\n" - " if ($name$_ == null) {\n" - " $name$_ = com.google.protobuf.MapField.newMapField(\n" - " $map_field_parameter$);\n" - " }\n" - " if (!$name$_.isMutable()) {\n" - " $name$_ = $name$_.copy();\n" - " }\n" - " return $name$_;\n" - "}\n"); +void ImmutableMapFieldGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + printer->Print(variables_, + "private com.google.protobuf.MapField<\n" + " $type_parameters$> $name$_;\n" + "private com.google.protobuf.MapField<$type_parameters$>\n" + "internalGet$capitalized_name$() {\n" + " if ($name$_ == null) {\n" + " return com.google.protobuf.MapField.emptyMapField(\n" + " $map_field_parameter$);\n" + " }\n" + " return $name$_;\n" + "}\n" + "private com.google.protobuf.MapField<$type_parameters$>\n" + "internalGetMutable$capitalized_name$() {\n" + " $on_changed$;\n" + " if ($name$_ == null) {\n" + " $name$_ = com.google.protobuf.MapField.newMapField(\n" + " $map_field_parameter$);\n" + " }\n" + " if (!$name$_.isMutable()) {\n" + " $name$_ = $name$_.copy();\n" + " }\n" + " return $name$_;\n" + "}\n"); GenerateMapGetters(printer); - printer->Print( - variables_, - "$deprecation$\n" - "public Builder ${$clear$capitalized_name$$}$() {\n" - " internalGetMutable$capitalized_name$().getMutableMap()\n" - " .clear();\n" - " return this;\n" - "}\n"); + printer->Print(variables_, + "$deprecation$\n" + "public Builder ${$clear$capitalized_name$$}$() {\n" + " internalGetMutable$capitalized_name$().getMutableMap()\n" + " .clear();\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "public Builder ${$remove$capitalized_name$$}$(\n" - " $key_type$ key) {\n" - " $key_null_check$\n" - " internalGetMutable$capitalized_name$().getMutableMap()\n" - " .remove(key);\n" - " return this;\n" - "}\n"); + printer->Print(variables_, + "$deprecation$\n" + "public Builder ${$remove$capitalized_name$$}$(\n" + " $key_type$ key) {\n" + " $key_null_check$\n" + " internalGetMutable$capitalized_name$().getMutableMap()\n" + " .remove(key);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { printer->Print( @@ -468,46 +446,44 @@ GenerateBuilderMembers(io::Printer* printer) const { "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$" - "public Builder ${$put$capitalized_name$$}$(\n" - " $key_type$ key,\n" - " $value_type$ value) {\n" - " $key_null_check$\n" - " $value_null_check$\n" - " internalGetMutable$capitalized_name$().getMutableMap()\n" - " .put(key, value);\n" - " return this;\n" - "}\n"); + printer->Print(variables_, + "$deprecation$" + "public Builder ${$put$capitalized_name$$}$(\n" + " $key_type$ key,\n" + " $value_type$ value) {\n" + " $key_null_check$\n" + " $value_null_check$\n" + " internalGetMutable$capitalized_name$().getMutableMap()\n" + " .put(key, value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "public Builder ${$putAll$capitalized_name$$}$(\n" - " java.util.Map<$type_parameters$> values) {\n" - " internalGetMutable$capitalized_name$().getMutableMap()\n" - " .putAll(values);\n" - " return this;\n" - "}\n"); + printer->Print(variables_, + "$deprecation$\n" + "public Builder ${$putAll$capitalized_name$$}$(\n" + " java.util.Map<$type_parameters$> values) {\n" + " internalGetMutable$capitalized_name$().getMutableMap()\n" + " .putAll(values);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } } -void ImmutableMapFieldGenerator:: -GenerateMapGetters(io::Printer* printer) const { - printer->Print( - variables_, - "$deprecation$\n" - "public int ${$get$capitalized_name$Count$}$() {\n" - " return internalGet$capitalized_name$().getMap().size();\n" - "}\n"); +void ImmutableMapFieldGenerator::GenerateMapGetters( + io::Printer* printer) const { + printer->Print(variables_, + "$deprecation$\n" + "public int ${$get$capitalized_name$Count$}$() {\n" + " return internalGet$capitalized_name$().getMap().size();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, "$deprecation$\n" + "@java.lang.Override\n" "public boolean ${$contains$capitalized_name$$}$(\n" " $key_type$ key) {\n" " $key_null_check$\n" @@ -515,30 +491,31 @@ GenerateMapGetters(io::Printer* printer) const { "}\n"); printer->Annotate("{", "}", descriptor_); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { - printer->Print( - variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" - "${$get$capitalized_name$$}$() {\n" - " return get$capitalized_name$Map();\n" - "}\n"); + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Override\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "${$get$capitalized_name$$}$() {\n" + " return get$capitalized_name$Map();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" - "${$get$capitalized_name$Map$}$() {\n" - " return internalGetAdapted$capitalized_name$Map(\n" - " internalGet$capitalized_name$().getMap());" - "}\n"); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$\n" + "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "${$get$capitalized_name$Map$}$() {\n" + " return internalGetAdapted$capitalized_name$Map(\n" + " internalGet$capitalized_name$().getMap());" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n" " $key_type$ key,\n" @@ -554,6 +531,7 @@ GenerateMapGetters(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n" " $key_type$ key) {\n" @@ -572,6 +550,7 @@ GenerateMapGetters(io::Printer* printer) const { "/**\n" " * Use {@link #get$capitalized_name$ValueMap()} instead.\n" " */\n" + "@java.lang.Override\n" "@java.lang.Deprecated\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "${$get$capitalized_name$Value$}$() {\n" @@ -581,6 +560,7 @@ GenerateMapGetters(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "${$get$capitalized_name$ValueMap$}$() {\n" @@ -590,6 +570,7 @@ GenerateMapGetters(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n" " $key_type$ key,\n" @@ -603,6 +584,7 @@ GenerateMapGetters(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n" " $key_type$ key) {\n" @@ -617,29 +599,30 @@ GenerateMapGetters(io::Printer* printer) const { printer->Annotate("{", "}", descriptor_); } } else { - printer->Print( - variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$type_parameters$> " - "${$get$capitalized_name$$}$() {\n" - " return get$capitalized_name$Map();\n" - "}\n"); + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Override\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$type_parameters$> " + "${$get$capitalized_name$$}$() {\n" + " return get$capitalized_name$Map();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "public java.util.Map<$type_parameters$> " - "${$get$capitalized_name$Map$}$() {\n" - " return internalGet$capitalized_name$().getMap();\n" - "}\n"); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$\n" + "public java.util.Map<$type_parameters$> " + "${$get$capitalized_name$Map$}$() {\n" + " return internalGet$capitalized_name$().getMap();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n" " $key_type$ key,\n" @@ -651,65 +634,61 @@ GenerateMapGetters(io::Printer* printer) const { "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n" - " $key_type$ key) {\n" - " $key_null_check$\n" - " java.util.Map<$type_parameters$> map =\n" - " internalGet$capitalized_name$().getMap();\n" - " if (!map.containsKey(key)) {\n" - " throw new java.lang.IllegalArgumentException();\n" - " }\n" - " return map.get(key);\n" - "}\n"); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$\n" + "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n" + " $key_type$ key) {\n" + " $key_null_check$\n" + " java.util.Map<$type_parameters$> map =\n" + " internalGet$capitalized_name$().getMap();\n" + " if (!map.containsKey(key)) {\n" + " throw new java.lang.IllegalArgumentException();\n" + " }\n" + " return map.get(key);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } } -void ImmutableMapFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { +void ImmutableMapFieldGenerator::GenerateFieldBuilderInitializationCode( + io::Printer* printer) const { // Nothing to initialize. } -void ImmutableMapFieldGenerator:: -GenerateInitializationCode(io::Printer* printer) const { +void ImmutableMapFieldGenerator::GenerateInitializationCode( + io::Printer* printer) const { // Nothing to initialize. } -void ImmutableMapFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - printer->Print( - variables_, - "internalGetMutable$capitalized_name$().clear();\n"); +void ImmutableMapFieldGenerator::GenerateBuilderClearCode( + io::Printer* printer) const { + printer->Print(variables_, + "internalGetMutable$capitalized_name$().clear();\n"); } -void ImmutableMapFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print( - variables_, - "internalGetMutable$capitalized_name$().mergeFrom(\n" - " other.internalGet$capitalized_name$());\n"); +void ImmutableMapFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { + printer->Print(variables_, + "internalGetMutable$capitalized_name$().mergeFrom(\n" + " other.internalGet$capitalized_name$());\n"); } -void ImmutableMapFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - printer->Print( - variables_, - "result.$name$_ = internalGet$capitalized_name$();\n" - "result.$name$_.makeImmutable();\n"); +void ImmutableMapFieldGenerator::GenerateBuildingCode( + io::Printer* printer) const { + printer->Print(variables_, + "result.$name$_ = internalGet$capitalized_name$();\n" + "result.$name$_.makeImmutable();\n"); } -void ImmutableMapFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print( - variables_, - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ = com.google.protobuf.MapField.newMapField(\n" - " $map_field_parameter$);\n" - " $set_mutable_bit_parser$;\n" - "}\n"); +void ImmutableMapFieldGenerator::GenerateParsingCode( + io::Printer* printer) const { + printer->Print(variables_, + "if (!$get_mutable_bit_parser$) {\n" + " $name$_ = com.google.protobuf.MapField.newMapField(\n" + " $map_field_parameter$);\n" + " $set_mutable_bit_parser$;\n" + "}\n"); if (!SupportUnknownEnumValue(descriptor_->file()) && GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { printer->Print( @@ -736,25 +715,24 @@ GenerateParsingCode(io::Printer* printer) const { } } -void ImmutableMapFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { +void ImmutableMapFieldGenerator::GenerateParsingDoneCode( + io::Printer* printer) const { // Nothing to do here. } -void ImmutableMapFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print( - variables_, - "com.google.protobuf.GeneratedMessage$ver$\n" - " .serialize$short_key_type$MapTo(\n" - " output,\n" - " internalGet$capitalized_name$(),\n" - " $default_entry$,\n" - " $number$);\n"); +void ImmutableMapFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { + printer->Print(variables_, + "com.google.protobuf.GeneratedMessage$ver$\n" + " .serialize$short_key_type$MapTo(\n" + " output,\n" + " internalGet$capitalized_name$(),\n" + " $default_entry$,\n" + " $number$);\n"); } -void ImmutableMapFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { +void ImmutableMapFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { printer->Print( variables_, "for (java.util.Map.Entry<$type_parameters$> entry\n" @@ -769,16 +747,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const { "}\n"); } -void ImmutableMapFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print( - variables_, - "result = result && internalGet$capitalized_name$().equals(\n" - " other.internalGet$capitalized_name$());\n"); +void ImmutableMapFieldGenerator::GenerateEqualsCode( + io::Printer* printer) const { + printer->Print(variables_, + "if (!internalGet$capitalized_name$().equals(\n" + " other.internalGet$capitalized_name$())) return false;\n"); } -void ImmutableMapFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { +void ImmutableMapFieldGenerator::GenerateHashCode(io::Printer* printer) const { printer->Print( variables_, "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n" @@ -787,7 +763,7 @@ GenerateHashCode(io::Printer* printer) const { "}\n"); } -string ImmutableMapFieldGenerator::GetBoxedType() const { +std::string ImmutableMapFieldGenerator::GetBoxedType() const { return name_resolver_->GetImmutableClassName(descriptor_->message_type()); } diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h index 4702174063a8e..2ff1f7673e9cf 100644 --- a/src/google/protobuf/compiler/java/java_map_field.h +++ b/src/google/protobuf/compiler/java/java_map_field.h @@ -40,9 +40,9 @@ namespace java { class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { public: - explicit ImmutableMapFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableMapFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex, + Context* context); ~ImmutableMapFieldGenerator(); // implements ImmutableFieldGenerator --------------------------------------- @@ -63,11 +63,11 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map variables_; + std::map variables_; ClassNameResolver* name_resolver_; void GenerateMapGetters(io::Printer* printer) const; }; @@ -75,6 +75,6 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc index f19ec271e043a..4fa939f3b8bf7 100644 --- a/src/google/protobuf/compiler/java/java_map_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc @@ -57,9 +57,8 @@ const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) { return message->FindFieldByName("value"); } -string TypeName(const FieldDescriptor* field, - ClassNameResolver* name_resolver, - bool boxed) { +std::string TypeName(const FieldDescriptor* field, + ClassNameResolver* name_resolver, bool boxed) { if (GetJavaType(field) == JAVATYPE_MESSAGE) { return name_resolver->GetImmutableClassName(field->message_type()); } else if (GetJavaType(field) == JAVATYPE_ENUM) { @@ -70,17 +69,15 @@ string TypeName(const FieldDescriptor* field, } } -string WireType(const FieldDescriptor* field) { +std::string WireType(const FieldDescriptor* field) { return "com.google.protobuf.WireFormat.FieldType." + - string(FieldTypeName(field->type())); + std::string(FieldTypeName(field->type())); } -void SetMessageVariables(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - const FieldGeneratorInfo* info, +void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, const FieldGeneratorInfo* info, Context* context, - std::map* variables) { + std::map* variables) { SetCommonFieldVariables(descriptor, info, variables); ClassNameResolver* name_resolver = context->GetNameResolver(); @@ -95,10 +92,12 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true); (*variables)["key_wire_type"] = WireType(key); (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver); - (*variables)["key_null_check"] = IsReferenceType(keyJavaType) ? - "if (key == null) { throw new java.lang.NullPointerException(); }" : ""; - (*variables)["value_null_check"] = IsReferenceType(valueJavaType) ? - "if (value == null) { throw new java.lang.NullPointerException(); }" : ""; + // We use `x.getClass()` as a null check because it generates less bytecode + // than an `if (x == null) { throw ... }` statement. + (*variables)["key_null_check"] = + IsReferenceType(keyJavaType) ? "key.getClass();" : ""; + (*variables)["value_null_check"] = + IsReferenceType(valueJavaType) ? "value.getClass();" : ""; if (GetJavaType(value) == JAVATYPE_ENUM) { // We store enums as Integers internally. @@ -130,59 +129,48 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"]; // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler - (*variables)["deprecation"] = descriptor->options().deprecated() - ? "@java.lang.Deprecated " : ""; + (*variables)["deprecation"] = + descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - (*variables)["default_entry"] = (*variables)["capitalized_name"] + - "DefaultEntryHolder.defaultEntry"; + (*variables)["default_entry"] = + (*variables)["capitalized_name"] + "DefaultEntryHolder.defaultEntry"; } } // namespace -ImmutableMapFieldLiteGenerator:: -ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { - SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - context, &variables_); +ImmutableMapFieldLiteGenerator::ImmutableMapFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, Context* context) + : descriptor_(descriptor), + context_(context), + name_resolver_(context->GetNameResolver()) { + SetMessageVariables(descriptor, messageBitIndex, 0, + context->GetFieldGeneratorInfo(descriptor), context, + &variables_); } -ImmutableMapFieldLiteGenerator:: -~ImmutableMapFieldLiteGenerator() {} +ImmutableMapFieldLiteGenerator::~ImmutableMapFieldLiteGenerator() {} -int ImmutableMapFieldLiteGenerator::GetNumBitsForMessage() const { - return 0; -} - -int ImmutableMapFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; -} +int ImmutableMapFieldLiteGenerator::GetNumBitsForMessage() const { return 0; } -void ImmutableMapFieldLiteGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { +void ImmutableMapFieldLiteGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$int ${$get$capitalized_name$Count$}$();\n"); + printer->Print(variables_, + "$deprecation$int ${$get$capitalized_name$Count$}$();\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$boolean ${$contains$capitalized_name$$}$(\n" - " $key_type$ key);\n"); + printer->Print(variables_, + "$deprecation$boolean ${$contains$capitalized_name$$}$(\n" + " $key_type$ key);\n"); printer->Annotate("{", "}", descriptor_); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { - printer->Print( - variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "java.util.Map<$boxed_key_type$, $value_enum_type$>\n" - "${$get$capitalized_name$$}$();\n"); + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "${$get$capitalized_name$$}$();\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print( @@ -214,63 +202,56 @@ GenerateInterfaceMembers(io::Printer* printer) const { "${$get$capitalized_name$Value$}$();\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$java.util.Map<$type_parameters$>\n" - "${$get$capitalized_name$ValueMap$}$();\n"); + printer->Print(variables_, + "$deprecation$java.util.Map<$type_parameters$>\n" + "${$get$capitalized_name$ValueMap$}$();\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n" - " $key_type$ key,\n" - " $value_type$ defaultValue);\n"); + printer->Print(variables_, + "$deprecation$\n" + "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n" + " $key_type$ key,\n" + " $value_type$ defaultValue);\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n" - " $key_type$ key);\n"); + printer->Print(variables_, + "$deprecation$\n" + "$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n" + " $key_type$ key);\n"); printer->Annotate("{", "}", descriptor_); } } else { - printer->Print( - variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "java.util.Map<$type_parameters$>\n" - "${$get$capitalized_name$$}$();\n"); + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "java.util.Map<$type_parameters$>\n" + "${$get$capitalized_name$$}$();\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$java.util.Map<$type_parameters$>\n" - "${$get$capitalized_name$Map$}$();\n"); + printer->Print(variables_, + "$deprecation$java.util.Map<$type_parameters$>\n" + "${$get$capitalized_name$Map$}$();\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "$value_type$ ${$get$capitalized_name$OrDefault$}$(\n" - " $key_type$ key,\n" - " $value_type$ defaultValue);\n"); + printer->Print(variables_, + "$deprecation$\n" + "$value_type$ ${$get$capitalized_name$OrDefault$}$(\n" + " $key_type$ key,\n" + " $value_type$ defaultValue);\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "$value_type$ ${$get$capitalized_name$OrThrow$}$(\n" - " $key_type$ key);\n"); + printer->Print(variables_, + "$deprecation$\n" + "$value_type$ ${$get$capitalized_name$OrThrow$}$(\n" + " $key_type$ key);\n"); printer->Annotate("{", "}", descriptor_); } } -void ImmutableMapFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { +void ImmutableMapFieldLiteGenerator::GenerateMembers( + io::Printer* printer) const { printer->Print( variables_, "private static final class $capitalized_name$DefaultEntryHolder {\n" @@ -283,38 +264,37 @@ GenerateMembers(io::Printer* printer) const { " $value_wire_type$,\n" " $value_default_value$);\n" "}\n"); - printer->Print( - variables_, - "private com.google.protobuf.MapFieldLite<\n" - " $type_parameters$> $name$_ =\n" - " com.google.protobuf.MapFieldLite.emptyMapField();\n" - "private com.google.protobuf.MapFieldLite<$type_parameters$>\n" - "internalGet$capitalized_name$() {\n" - " return $name$_;\n" - "}\n" - "private com.google.protobuf.MapFieldLite<$type_parameters$>\n" - "internalGetMutable$capitalized_name$() {\n" - " if (!$name$_.isMutable()) {\n" - " $name$_ = $name$_.mutableCopy();\n" - " }\n" - " return $name$_;\n" - "}\n"); - printer->Print( - variables_, - "$deprecation$\n" - "public int ${$get$capitalized_name$Count$}$() {\n" - " return internalGet$capitalized_name$().size();\n" - "}\n"); + printer->Print(variables_, + "private com.google.protobuf.MapFieldLite<\n" + " $type_parameters$> $name$_ =\n" + " com.google.protobuf.MapFieldLite.emptyMapField();\n" + "private com.google.protobuf.MapFieldLite<$type_parameters$>\n" + "internalGet$capitalized_name$() {\n" + " return $name$_;\n" + "}\n" + "private com.google.protobuf.MapFieldLite<$type_parameters$>\n" + "internalGetMutable$capitalized_name$() {\n" + " if (!$name$_.isMutable()) {\n" + " $name$_ = $name$_.mutableCopy();\n" + " }\n" + " return $name$_;\n" + "}\n"); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$\n" + "public int ${$get$capitalized_name$Count$}$() {\n" + " return internalGet$capitalized_name$().size();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "public boolean ${$contains$capitalized_name$$}$(\n" - " $key_type$ key) {\n" - " $key_null_check$\n" - " return internalGet$capitalized_name$().containsKey(key);\n" - "}\n"); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$\n" + "public boolean ${$contains$capitalized_name$$}$(\n" + " $key_type$ key) {\n" + " $key_null_check$\n" + " return internalGet$capitalized_name$().containsKey(key);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { printer->Print( @@ -325,20 +305,20 @@ GenerateMembers(io::Printer* printer) const { " com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n" " $value_enum_type$.internalGetValueMap(),\n" " $unrecognized_value$);\n"); - printer->Print( - variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" - "${$get$capitalized_name$$}$() {\n" - " return get$capitalized_name$Map();\n" - "}\n"); + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "${$get$capitalized_name$$}$() {\n" + " return get$capitalized_name$Map();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" "${$get$capitalized_name$Map$}$() {\n" @@ -352,6 +332,7 @@ GenerateMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n" " $key_type$ key,\n" @@ -367,6 +348,7 @@ GenerateMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n" " $key_type$ key) {\n" @@ -385,6 +367,7 @@ GenerateMembers(io::Printer* printer) const { "/**\n" " * Use {@link #get$capitalized_name$ValueMap()} instead.\n" " */\n" + "@java.lang.Override\n" "@java.lang.Deprecated\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "${$get$capitalized_name$Value$}$() {\n" @@ -394,6 +377,7 @@ GenerateMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "${$get$capitalized_name$ValueMap$}$() {\n" @@ -404,6 +388,7 @@ GenerateMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n" " $key_type$ key,\n" @@ -417,6 +402,7 @@ GenerateMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n" " $key_type$ key) {\n" @@ -431,30 +417,31 @@ GenerateMembers(io::Printer* printer) const { printer->Annotate("{", "}", descriptor_); } } else { - printer->Print( - variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$type_parameters$> " - "${$get$capitalized_name$$}$() {\n" - " return get$capitalized_name$Map();\n" - "}\n"); + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Override\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$type_parameters$> " + "${$get$capitalized_name$$}$() {\n" + " return get$capitalized_name$Map();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "public java.util.Map<$type_parameters$> " - "${$get$capitalized_name$Map$}$() {\n" - " return java.util.Collections.unmodifiableMap(\n" - " internalGet$capitalized_name$());\n" - "}\n"); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$\n" + "public java.util.Map<$type_parameters$> " + "${$get$capitalized_name$Map$}$() {\n" + " return java.util.Collections.unmodifiableMap(\n" + " internalGet$capitalized_name$());\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n" " $key_type$ key,\n" @@ -466,19 +453,19 @@ GenerateMembers(io::Printer* printer) const { "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n" - " $key_type$ key) {\n" - " $key_null_check$\n" - " java.util.Map<$type_parameters$> map =\n" - " internalGet$capitalized_name$();\n" - " if (!map.containsKey(key)) {\n" - " throw new java.lang.IllegalArgumentException();\n" - " }\n" - " return map.get(key);\n" - "}\n"); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$\n" + "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n" + " $key_type$ key) {\n" + " $key_null_check$\n" + " java.util.Map<$type_parameters$> map =\n" + " internalGet$capitalized_name$();\n" + " if (!map.containsKey(key)) {\n" + " throw new java.lang.IllegalArgumentException();\n" + " }\n" + " return map.get(key);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } @@ -505,28 +492,44 @@ GenerateMembers(io::Printer* printer) const { } } else { WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "private java.util.Map<$type_parameters$>\n" - "getMutable$capitalized_name$Map() {\n" - " return internalGetMutable$capitalized_name$();\n" - "}\n"); + printer->Print(variables_, + "private java.util.Map<$type_parameters$>\n" + "getMutable$capitalized_name$Map() {\n" + " return internalGetMutable$capitalized_name$();\n" + "}\n"); } } +void ImmutableMapFieldLiteGenerator::GenerateFieldInfo( + io::Printer* printer, std::vector* output) const { + WriteIntToUtf16CharSequence(descriptor_->number(), output); + WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_), + output); + printer->Print(variables_, + "\"$name$_\",\n" + "$default_entry$,\n"); + if (!SupportUnknownEnumValue(descriptor_) && + GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { + PrintEnumVerifierLogic(printer, ValueField(descriptor_), variables_, + /*var_name=*/"$value_enum_type$", + /*terminating_string=*/",\n", + /*enforce_lite=*/context_->EnforceLite()); + } +} -void ImmutableMapFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - printer->Print( - variables_, - "$deprecation$\n" - "public int ${$get$capitalized_name$Count$}$() {\n" - " return instance.get$capitalized_name$Map().size();\n" - "}\n"); +void ImmutableMapFieldLiteGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$\n" + "public int ${$get$capitalized_name$Count$}$() {\n" + " return instance.get$capitalized_name$Map().size();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public boolean ${$contains$capitalized_name$$}$(\n" " $key_type$ key) {\n" @@ -534,52 +537,50 @@ GenerateBuilderMembers(io::Printer* printer) const { " return instance.get$capitalized_name$Map().containsKey(key);\n" "}\n"); printer->Annotate("{", "}", descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "public Builder ${$clear$capitalized_name$$}$() {\n" - " copyOnWrite();\n" - " instance.getMutable$capitalized_name$Map().clear();\n" - " return this;\n" - "}\n"); + printer->Print(variables_, + "$deprecation$\n" + "public Builder ${$clear$capitalized_name$$}$() {\n" + " copyOnWrite();\n" + " instance.getMutable$capitalized_name$Map().clear();\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "public Builder ${$remove$capitalized_name$$}$(\n" - " $key_type$ key) {\n" - " $key_null_check$\n" - " copyOnWrite();\n" - " instance.getMutable$capitalized_name$Map().remove(key);\n" - " return this;\n" - "}\n"); + printer->Print(variables_, + "$deprecation$\n" + "public Builder ${$remove$capitalized_name$$}$(\n" + " $key_type$ key) {\n" + " $key_null_check$\n" + " copyOnWrite();\n" + " instance.getMutable$capitalized_name$Map().remove(key);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { - printer->Print( - variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" - "${$get$capitalized_name$$}$() {\n" - " return get$capitalized_name$Map();\n" - "}\n"); + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "${$get$capitalized_name$$}$() {\n" + " return get$capitalized_name$Map();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" - "${$get$capitalized_name$Map$}$() {\n" - " return java.util.Collections.unmodifiableMap(\n" - " instance.get$capitalized_name$Map());\n" - "}\n"); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$\n" + "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "${$get$capitalized_name$Map$}$() {\n" + " return java.util.Collections.unmodifiableMap(\n" + " instance.get$capitalized_name$Map());\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n" " $key_type$ key,\n" @@ -595,6 +596,7 @@ GenerateBuilderMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n" " $key_type$ key) {\n" @@ -636,6 +638,7 @@ GenerateBuilderMembers(io::Printer* printer) const { "/**\n" " * Use {@link #get$capitalized_name$ValueMap()} instead.\n" " */\n" + "@java.lang.Override\n" "@java.lang.Deprecated\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "${$get$capitalized_name$Value$}$() {\n" @@ -645,6 +648,7 @@ GenerateBuilderMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "${$get$capitalized_name$ValueMap$}$() {\n" @@ -655,6 +659,7 @@ GenerateBuilderMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n" " $key_type$ key,\n" @@ -668,6 +673,7 @@ GenerateBuilderMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n" " $key_type$ key) {\n" @@ -704,30 +710,31 @@ GenerateBuilderMembers(io::Printer* printer) const { printer->Annotate("{", "}", descriptor_); } } else { - printer->Print( - variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$type_parameters$> " - "${$get$capitalized_name$$}$() {\n" - " return get$capitalized_name$Map();\n" - "}\n"); + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Override\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$type_parameters$> " + "${$get$capitalized_name$$}$() {\n" + " return get$capitalized_name$Map();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$" - "public java.util.Map<$type_parameters$> " - "${$get$capitalized_name$Map$}$() {\n" - " return java.util.Collections.unmodifiableMap(\n" - " instance.get$capitalized_name$Map());\n" - "}\n"); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$" + "public java.util.Map<$type_parameters$> " + "${$get$capitalized_name$Map$}$() {\n" + " return java.util.Collections.unmodifiableMap(\n" + " instance.get$capitalized_name$Map());\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, + "@java.lang.Override\n" "$deprecation$\n" "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n" " $key_type$ key,\n" @@ -739,19 +746,19 @@ GenerateBuilderMembers(io::Printer* printer) const { "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "$deprecation$\n" - "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n" - " $key_type$ key) {\n" - " $key_null_check$\n" - " java.util.Map<$type_parameters$> map =\n" - " instance.get$capitalized_name$Map();\n" - " if (!map.containsKey(key)) {\n" - " throw new java.lang.IllegalArgumentException();\n" - " }\n" - " return map.get(key);\n" - "}\n"); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$\n" + "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n" + " $key_type$ key) {\n" + " $key_null_check$\n" + " java.util.Map<$type_parameters$> map =\n" + " instance.get$capitalized_name$Map();\n" + " if (!map.containsKey(key)) {\n" + " throw new java.lang.IllegalArgumentException();\n" + " }\n" + " return map.get(key);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print( @@ -781,104 +788,12 @@ GenerateBuilderMembers(io::Printer* printer) const { } } -void ImmutableMapFieldLiteGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { +void ImmutableMapFieldLiteGenerator::GenerateInitializationCode( + io::Printer* printer) const { // Nothing to initialize. } -void ImmutableMapFieldLiteGenerator:: -GenerateInitializationCode(io::Printer* printer) const { - // Nothing to initialize. -} - -void ImmutableMapFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - printer->Print( - variables_, - "$name$_ = visitor.visitMap(\n" - " $name$_, other.internalGet$capitalized_name$());\n"); -} - -void ImmutableMapFieldLiteGenerator:: -GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_.makeImmutable();\n"); -} - -void ImmutableMapFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print( - variables_, - "if (!$name$_.isMutable()) {\n" - " $name$_ = $name$_.mutableCopy();\n" - "}\n"); - if (!SupportUnknownEnumValue(descriptor_->file()) && - GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { - printer->Print( - variables_, - "com.google.protobuf.ByteString bytes = input.readBytes();\n" - "java.util.Map.Entry<$type_parameters$> $name$__ =\n" - " $default_entry$.parseEntry(bytes, extensionRegistry);\n"); - printer->Print( - variables_, - "if ($value_enum_type$.forNumber($name$__.getValue()) == null) {\n" - " super.mergeLengthDelimitedField($number$, bytes);\n" - "} else {\n" - " $name$_.put($name$__);\n" - "}\n"); - } else { - printer->Print( - variables_, - "$default_entry$.parseInto($name$_, input, extensionRegistry);"); - } -} - -void ImmutableMapFieldLiteGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - // Nothing to do here. -} - -void ImmutableMapFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print( - variables_, - "for (java.util.Map.Entry<$type_parameters$> entry\n" - " : internalGet$capitalized_name$().entrySet()) {\n" - " $default_entry$.serializeTo(\n" - " output, $number$, entry.getKey(), entry.getValue());\n" - "}\n"); -} - -void ImmutableMapFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print( - variables_, - "for (java.util.Map.Entry<$type_parameters$> entry\n" - " : internalGet$capitalized_name$().entrySet()) {\n" - " size += $default_entry$.computeMessageSize(\n" - " $number$, entry.getKey(), entry.getValue());\n" - "}\n"); -} - -void ImmutableMapFieldLiteGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print( - variables_, - "result = result && internalGet$capitalized_name$().equals(\n" - " other.internalGet$capitalized_name$());\n"); -} - -void ImmutableMapFieldLiteGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print( - variables_, - "if (!internalGet$capitalized_name$().isEmpty()) {\n" - " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n" - "}\n"); -} - -string ImmutableMapFieldLiteGenerator::GetBoxedType() const { +std::string ImmutableMapFieldLiteGenerator::GetBoxedType() const { return name_resolver_->GetImmutableClassName(descriptor_->message_type()); } diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.h b/src/google/protobuf/compiler/java/java_map_field_lite.h index 94aa48136bc5a..49cbf6cca7248 100644 --- a/src/google/protobuf/compiler/java/java_map_field_lite.h +++ b/src/google/protobuf/compiler/java/java_map_field_lite.h @@ -40,40 +40,32 @@ namespace java { class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: - explicit ImmutableMapFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context); ~ImmutableMapFieldLiteGenerator(); // implements ImmutableFieldLiteGenerator ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; + void GenerateFieldInfo(io::Printer* printer, + std::vector* output) const; - - string GetBoxedType() const; + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map variables_; + std::map variables_; + Context* context_; ClassNameResolver* name_resolver_; }; } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index ecc67575a5f09..f9d4e43ff84a2 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -35,12 +35,8 @@ #include #include -#include #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include @@ -52,13 +48,12 @@ #include #include #include +#include #include #include -#include #include -#include #include - +#include namespace google { namespace protobuf { @@ -69,13 +64,8 @@ using internal::WireFormat; using internal::WireFormatLite; namespace { -bool GenerateHasBits(const Descriptor* descriptor) { - return SupportFieldPresence(descriptor->file()) || - HasRepeatedFields(descriptor); -} - -string MapValueImmutableClassdName(const Descriptor* descriptor, - ClassNameResolver* name_resolver) { +std::string MapValueImmutableClassdName(const Descriptor* descriptor, + ClassNameResolver* name_resolver) { const FieldDescriptor* value_field = descriptor->FindFieldByName("value"); GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type()); return name_resolver->GetImmutableClassName(value_field->message_type()); @@ -85,16 +75,23 @@ string MapValueImmutableClassdName(const Descriptor* descriptor, // =================================================================== MessageGenerator::MessageGenerator(const Descriptor* descriptor) - : descriptor_(descriptor) {} + : descriptor_(descriptor) { + for (int i = 0; i < descriptor_->field_count(); i++) { + if (IsRealOneof(descriptor_->field(i))) { + oneofs_.insert(descriptor_->field(i)->containing_oneof()); + } + } +} MessageGenerator::~MessageGenerator() {} // =================================================================== ImmutableMessageGenerator::ImmutableMessageGenerator( const Descriptor* descriptor, Context* context) - : MessageGenerator(descriptor), context_(context), - name_resolver_(context->GetNameResolver()), - field_generators_(descriptor, context_) { + : MessageGenerator(descriptor), + context_(context), + name_resolver_(context->GetNameResolver()), + field_generators_(descriptor, context_) { GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite())) << "Generator factory error: A non-lite message generator is used to " "generate lite messages."; @@ -111,13 +108,12 @@ void ImmutableMessageGenerator::GenerateStaticVariables( // the outermost class in the file. This way, they will be initialized in // a deterministic order. - std::map vars; + std::map vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); - vars["index"] = SimpleItoa(descriptor_->index()); + vars["index"] = StrCat(descriptor_->index()); vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); if (descriptor_->containing_type() != NULL) { - vars["parent"] = UniqueFileScopeIdentifier( - descriptor_->containing_type()); + vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type()); } if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { // We can only make these package-private since the classes that use them @@ -133,12 +129,13 @@ void ImmutableMessageGenerator::GenerateStaticVariables( } // The descriptor for this type. - printer->Print(vars, - // TODO(teboring): final needs to be added back. The way to fix it is to - // generate methods that can construct the types, and then still declare the - // types, and then init them in clinit with the new method calls. - "$private$static $final$com.google.protobuf.Descriptors.Descriptor\n" - " internal_$identifier$_descriptor;\n"); + printer->Print( + vars, + // TODO(teboring): final needs to be added back. The way to fix it is to + // generate methods that can construct the types, and then still declare + // the types, and then init them in clinit with the new method calls. + "$private$static $final$com.google.protobuf.Descriptors.Descriptor\n" + " internal_$identifier$_descriptor;\n"); *bytecode_estimate += 30; // And the FieldAccessorTable. @@ -155,25 +152,25 @@ void ImmutableMessageGenerator::GenerateStaticVariables( int ImmutableMessageGenerator::GenerateStaticVariableInitializers( io::Printer* printer) { int bytecode_estimate = 0; - std::map vars; + std::map vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); - vars["index"] = SimpleItoa(descriptor_->index()); + vars["index"] = StrCat(descriptor_->index()); vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); if (descriptor_->containing_type() != NULL) { - vars["parent"] = UniqueFileScopeIdentifier( - descriptor_->containing_type()); + vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type()); } // The descriptor for this type. if (descriptor_->containing_type() == NULL) { printer->Print(vars, - "internal_$identifier$_descriptor =\n" - " getDescriptor().getMessageTypes().get($index$);\n"); + "internal_$identifier$_descriptor =\n" + " getDescriptor().getMessageTypes().get($index$);\n"); bytecode_estimate += 30; } else { - printer->Print(vars, - "internal_$identifier$_descriptor =\n" - " internal_$parent$_descriptor.getNestedTypes().get($index$);\n"); + printer->Print( + vars, + "internal_$identifier$_descriptor =\n" + " internal_$parent$_descriptor.getNestedTypes().get($index$);\n"); bytecode_estimate += 30; } @@ -190,9 +187,9 @@ int ImmutableMessageGenerator::GenerateStaticVariableInitializers( return bytecode_estimate; } -void ImmutableMessageGenerator:: -GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate) { - std::map vars; +void ImmutableMessageGenerator::GenerateFieldAccessorTable( + io::Printer* printer, int* bytecode_estimate) { + std::map vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { // We can only make these package-private since the classes that use them @@ -207,41 +204,39 @@ GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate) { vars["final"] = ""; } vars["ver"] = GeneratedCodeVersionSuffix(); - printer->Print(vars, - "$private$static $final$\n" - " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n" - " internal_$identifier$_fieldAccessorTable;\n"); + printer->Print( + vars, + "$private$static $final$\n" + " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n" + " internal_$identifier$_fieldAccessorTable;\n"); // 6 bytes per field and oneof - *bytecode_estimate += 10 + 6 * descriptor_->field_count() - + 6 * descriptor_->oneof_decl_count(); + *bytecode_estimate += + 10 + 6 * descriptor_->field_count() + 6 * oneofs_.size(); } -int ImmutableMessageGenerator:: -GenerateFieldAccessorTableInitializer(io::Printer* printer) { +int ImmutableMessageGenerator::GenerateFieldAccessorTableInitializer( + io::Printer* printer) { int bytecode_estimate = 10; printer->Print( - "internal_$identifier$_fieldAccessorTable = new\n" - " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable(\n" - " internal_$identifier$_descriptor,\n" - " new java.lang.String[] { ", - "identifier", UniqueFileScopeIdentifier(descriptor_), - "ver", GeneratedCodeVersionSuffix()); + "internal_$identifier$_fieldAccessorTable = new\n" + " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable(\n" + " internal_$identifier$_descriptor,\n" + " new java.lang.String[] { ", + "identifier", UniqueFileScopeIdentifier(descriptor_), "ver", + GeneratedCodeVersionSuffix()); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); bytecode_estimate += 6; - printer->Print( - "\"$field_name$\", ", - "field_name", info->capitalized_name); + printer->Print("\"$field_name$\", ", "field_name", info->capitalized_name); } + // We reproduce synthetic oneofs here since proto reflection needs these. for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { const OneofDescriptor* oneof = descriptor_->oneof_decl(i); const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof); bytecode_estimate += 6; - printer->Print( - "\"$oneof_name$\", ", - "oneof_name", info->capitalized_name); + printer->Print("\"$oneof_name$\", ", "oneof_name", info->capitalized_name); } printer->Print("});\n"); return bytecode_estimate; @@ -258,42 +253,38 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { " $extra_interfaces$\n" " com.google.protobuf.GeneratedMessage$ver$.\n" " ExtendableMessageOrBuilder<$classname$> {\n", - "deprecation", descriptor_->options().deprecated() ? - "@java.lang.Deprecated " : "", + "deprecation", + descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "", "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name(), - "{", "", "}", "", "ver", GeneratedCodeVersionSuffix()); + "classname", descriptor_->name(), "{", "", "}", "", "ver", + GeneratedCodeVersionSuffix()); } else { printer->Print( "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n" " $extra_interfaces$\n" " com.google.protobuf.MessageOrBuilder {\n", - "deprecation", descriptor_->options().deprecated() ? - "@java.lang.Deprecated " : "", + "deprecation", + descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "", "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name(), - "{", "", "}", ""); + "classname", descriptor_->name(), "{", "", "}", ""); } printer->Annotate("{", "}", descriptor_); printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print("\n"); - field_generators_.get(descriptor_->field(i)) - .GenerateInterfaceMembers(printer); - } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "\n" - "public $classname$.$oneof_capitalized_name$Case " - "get$oneof_capitalized_name$Case();\n", - "oneof_capitalized_name", - context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name, - "classname", - context_->GetNameResolver()->GetImmutableClassName( - descriptor_)); - } + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print("\n"); + field_generators_.get(descriptor_->field(i)) + .GenerateInterfaceMembers(printer); + } + for (auto oneof : oneofs_) { + printer->Print( + "\n" + "public $classname$.$oneof_capitalized_name$Case " + "get$oneof_capitalized_name$Case();\n", + "oneof_capitalized_name", + context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "classname", + context_->GetNameResolver()->GetImmutableClassName(descriptor_)); + } printer->Outdent(); printer->Print("}\n"); @@ -304,20 +295,20 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { void ImmutableMessageGenerator::Generate(io::Printer* printer) { bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true); - std::map variables; - variables["static"] = is_own_file ? " " : " static "; + std::map variables; + variables["static"] = is_own_file ? "" : "static "; variables["classname"] = descriptor_->name(); variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_); variables["ver"] = GeneratedCodeVersionSuffix(); - variables["deprecation"] = descriptor_->options().deprecated() - ? "@java.lang.Deprecated " : ""; + variables["deprecation"] = + descriptor_->options().deprecated() ? "@java.lang.Deprecated " : ""; WriteMessageDocComment(printer, descriptor_); MaybePrintGeneratedAnnotation(context_, printer, descriptor_, /* immutable = */ true); // The builder_type stores the super type name of the nested Builder class. - string builder_type; + std::string builder_type; if (descriptor_->extension_range_count() > 0) { printer->Print( variables, @@ -339,15 +330,14 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { "$deprecation$public $static$final class $classname$ extends\n"); printer->Annotate("classname", descriptor_); printer->Print(variables, - " com.google.protobuf.GeneratedMessage$ver$ implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n"); - builder_type = strings::Substitute( - "com.google.protobuf.GeneratedMessage$0.Builder", - GeneratedCodeVersionSuffix()); + " com.google.protobuf.GeneratedMessage$ver$ implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + builder_type = + strings::Substitute("com.google.protobuf.GeneratedMessage$0.Builder", + GeneratedCodeVersionSuffix()); } - printer->Print( - "private static final long serialVersionUID = 0L;\n"); + printer->Print("private static final long serialVersionUID = 0L;\n"); printer->Indent(); // Using builder_type, instead of Builder, prevents the Builder class from @@ -355,28 +345,34 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // This optimizes the PermGen space usage for clients that do not modify // messages. printer->Print( - "// Use $classname$.newBuilder() to construct.\n" - "private $classname$($buildertype$ builder) {\n" - " super(builder);\n" - "}\n", - "classname", descriptor_->name(), - "buildertype", builder_type); - printer->Print( - "private $classname$() {\n", - "classname", descriptor_->name()); + "// Use $classname$.newBuilder() to construct.\n" + "private $classname$($buildertype$ builder) {\n" + " super(builder);\n" + "}\n", + "classname", descriptor_->name(), "buildertype", builder_type); + printer->Print("private $classname$() {\n", "classname", descriptor_->name()); printer->Indent(); GenerateInitializers(printer); printer->Outdent(); printer->Print( - "}\n" - "\n"); + "}\n" + "\n"); + + printer->Print(variables, + "@java.lang.Override\n" + "@SuppressWarnings({\"unused\"})\n" + "protected java.lang.Object newInstance(\n" + " UnusedPrivateParameter unused) {\n" + " return new $classname$();\n" + "}\n" + "\n"); printer->Print( - "@java.lang.Override\n" - "public final com.google.protobuf.UnknownFieldSet\n" - "getUnknownFields() {\n" - " return this.unknownFields;\n" - "}\n"); + "@java.lang.Override\n" + "public final com.google.protobuf.UnknownFieldSet\n" + "getUnknownFields() {\n" + " return this.unknownFields;\n" + "}\n"); if (context_->HasGeneratedMethods(descriptor_)) { GenerateParsingConstructor(printer); @@ -386,107 +382,104 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // Nested types for (int i = 0; i < descriptor_->enum_type_count(); i++) { - EnumGenerator(descriptor_->enum_type(i), true, context_) - .Generate(printer); + EnumGenerator(descriptor_->enum_type(i), true, context_).Generate(printer); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { // Don't generate Java classes for map entry messages. if (IsMapEntry(descriptor_->nested_type(i))) continue; - ImmutableMessageGenerator messageGenerator( - descriptor_->nested_type(i), context_); + ImmutableMessageGenerator messageGenerator(descriptor_->nested_type(i), + context_); messageGenerator.GenerateInterface(printer); messageGenerator.Generate(printer); } - if (GenerateHasBits(descriptor_)) { - // Integers for bit fields. - int totalBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - totalBits += field_generators_.get(descriptor_->field(i)) - .GetNumBitsForMessage(); - } - int totalInts = (totalBits + 31) / 32; - for (int i = 0; i < totalInts; i++) { - printer->Print("private int $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } + // Integers for bit fields. + int totalBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + totalBits += + field_generators_.get(descriptor_->field(i)).GetNumBitsForMessage(); + } + int totalInts = (totalBits + 31) / 32; + for (int i = 0; i < totalInts; i++) { + printer->Print("private int $bit_field_name$;\n", "bit_field_name", + GetBitFieldName(i)); } // oneof - std::map vars; - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - vars["oneof_name"] = context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name; - vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name; - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + std::map vars; + for (auto oneof : oneofs_) { + vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name; + vars["oneof_capitalized_name"] = + context_->GetOneofGeneratorInfo(oneof)->capitalized_name; + vars["oneof_index"] = StrCat((oneof)->index()); // oneofCase_ and oneof_ printer->Print(vars, - "private int $oneof_name$Case_ = 0;\n" - "private java.lang.Object $oneof_name$_;\n"); + "private int $oneof_name$Case_ = 0;\n" + "private java.lang.Object $oneof_name$_;\n"); // OneofCase enum - printer->Print(vars, - "public enum $oneof_capitalized_name$Case\n" - " implements com.google.protobuf.Internal.EnumLite {\n"); + printer->Print( + vars, + "public enum $oneof_capitalized_name$Case\n" + // TODO(dweis): Remove EnumLite when we want to break compatibility with + // 3.x users + " implements com.google.protobuf.Internal.EnumLite,\n" + " com.google.protobuf.AbstractMessage.InternalOneOfEnum {\n"); printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + for (int j = 0; j < (oneof)->field_count(); j++) { + const FieldDescriptor* field = (oneof)->field(j); printer->Print( - "$field_name$($field_number$),\n", - "field_name", - ToUpper(field->name()), - "field_number", - SimpleItoa(field->number())); + "$deprecation$$field_name$($field_number$),\n", "deprecation", + field->options().deprecated() ? "@java.lang.Deprecated " : "", + "field_name", ToUpper(field->name()), "field_number", + StrCat(field->number())); } - printer->Print( - "$cap_oneof_name$_NOT_SET(0);\n", - "cap_oneof_name", - ToUpper(vars["oneof_name"])); + printer->Print("$cap_oneof_name$_NOT_SET(0);\n", "cap_oneof_name", + ToUpper(vars["oneof_name"])); printer->Print(vars, - "private final int value;\n" - "private $oneof_capitalized_name$Case(int value) {\n" - " this.value = value;\n" - "}\n"); - printer->Print(vars, - "/**\n" - " * @deprecated Use {@link #forNumber(int)} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public static $oneof_capitalized_name$Case valueOf(int value) {\n" - " return forNumber(value);\n" - "}\n" - "\n" - "public static $oneof_capitalized_name$Case forNumber(int value) {\n" - " switch (value) {\n"); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - " case $field_number$: return $field_name$;\n", - "field_number", - SimpleItoa(field->number()), - "field_name", - ToUpper(field->name())); + "private final int value;\n" + "private $oneof_capitalized_name$Case(int value) {\n" + " this.value = value;\n" + "}\n"); + printer->Print( + vars, + "/**\n" + " * @param value The number of the enum to look for.\n" + " * @return The enum associated with the given number.\n" + " * @deprecated Use {@link #forNumber(int)} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "public static $oneof_capitalized_name$Case valueOf(int value) {\n" + " return forNumber(value);\n" + "}\n" + "\n" + "public static $oneof_capitalized_name$Case forNumber(int value) {\n" + " switch (value) {\n"); + for (int j = 0; j < (oneof)->field_count(); j++) { + const FieldDescriptor* field = (oneof)->field(j); + printer->Print(" case $field_number$: return $field_name$;\n", + "field_number", StrCat(field->number()), + "field_name", ToUpper(field->name())); } printer->Print( - " case 0: return $cap_oneof_name$_NOT_SET;\n" - " default: return null;\n" - " }\n" - "}\n" - "public int getNumber() {\n" - " return this.value;\n" - "}\n", - "cap_oneof_name", ToUpper(vars["oneof_name"])); + " case 0: return $cap_oneof_name$_NOT_SET;\n" + " default: return null;\n" + " }\n" + "}\n" + "public int getNumber() {\n" + " return this.value;\n" + "}\n", + "cap_oneof_name", ToUpper(vars["oneof_name"])); printer->Outdent(); printer->Print("};\n\n"); // oneofCase() printer->Print(vars, - "public $oneof_capitalized_name$Case\n" - "get$oneof_capitalized_name$Case() {\n" - " return $oneof_capitalized_name$Case.forNumber(\n" - " $oneof_name$Case_);\n" - "}\n" - "\n"); + "public $oneof_capitalized_name$Case\n" + "get$oneof_capitalized_name$Case() {\n" + " return $oneof_capitalized_name$Case.forNumber(\n" + " $oneof_name$Case_);\n" + "}\n" + "\n"); } if (IsAnyMessage(descriptor_)) { @@ -496,8 +489,9 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // Fields for (int i = 0; i < descriptor_->field_count(); i++) { printer->Print("public static final int $constant_name$ = $number$;\n", - "constant_name", FieldConstantName(descriptor_->field(i)), - "number", SimpleItoa(descriptor_->field(i)->number())); + "constant_name", FieldConstantName(descriptor_->field(i)), + "number", StrCat(descriptor_->field(i)->number())); + printer->Annotate("constant_name", descriptor_->field(i)); field_generators_.get(descriptor_->field(i)).GenerateMembers(printer); printer->Print("\n"); } @@ -513,22 +507,21 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { GenerateBuilder(printer); printer->Print( - "\n" - "// @@protoc_insertion_point(class_scope:$full_name$)\n", - "full_name", descriptor_->full_name()); - + "\n" + "// @@protoc_insertion_point(class_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); // Carefully initialize the default instance in such a way that it doesn't // conflict with other initialization. + printer->Print("private static final $classname$ DEFAULT_INSTANCE;\n", + "classname", + name_resolver_->GetImmutableClassName(descriptor_)); printer->Print( - "private static final $classname$ DEFAULT_INSTANCE;\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - printer->Print( - "static {\n" - " DEFAULT_INSTANCE = new $classname$();\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "static {\n" + " DEFAULT_INSTANCE = new $classname$();\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Print( "public static $classname$ getDefaultInstance() {\n" @@ -537,14 +530,26 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); + // 'of' method for Wrappers + if (IsWrappersProtoFile(descriptor_->file())) { + printer->Print( + "public static $classname$ of($field_type$ value) {\n" + " return newBuilder().setValue(value).build();\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "field_type", PrimitiveTypeName(GetJavaType(descriptor_->field(0)))); + } + GenerateParser(printer); printer->Print( - "public $classname$ getDefaultInstanceForType() {\n" - " return DEFAULT_INSTANCE;\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "@java.lang.Override\n" + "public $classname$ getDefaultInstanceForType() {\n" + " return DEFAULT_INSTANCE;\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); // Extensions must be declared after the DEFAULT_INSTANCE is initialized // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve @@ -558,12 +563,11 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { printer->Print("}\n\n"); } - // =================================================================== -void ImmutableMessageGenerator:: -GenerateMessageSerializationMethods(io::Printer* printer) { - google::protobuf::scoped_array sorted_fields( +void ImmutableMessageGenerator::GenerateMessageSerializationMethods( + io::Printer* printer) { + std::unique_ptr sorted_fields( SortFieldsByNumber(descriptor_)); std::vector sorted_extensions; @@ -573,42 +577,42 @@ GenerateMessageSerializationMethods(io::Printer* printer) { std::sort(sorted_extensions.begin(), sorted_extensions.end(), ExtensionRangeOrdering()); printer->Print( - "public void writeTo(com.google.protobuf.CodedOutputStream output)\n" - " throws java.io.IOException {\n"); + "@java.lang.Override\n" + "public void writeTo(com.google.protobuf.CodedOutputStream output)\n" + " throws java.io.IOException {\n"); printer->Indent(); + if (HasPackedFields(descriptor_)) { // writeTo(CodedOutputStream output) might be invoked without // getSerializedSize() ever being called, but we need the memoized - // sizes in case this message has packed fields. Rather than emit checks for - // each packed field, just call getSerializedSize() up front. - // In most cases, getSerializedSize() will have already been called anyway - // by one of the wrapper writeTo() methods, making this call cheap. - printer->Print( - "getSerializedSize();\n"); + // sizes in case this message has packed fields. Rather than emit checks + // for each packed field, just call getSerializedSize() up front. In most + // cases, getSerializedSize() will have already been called anyway by one + // of the wrapper writeTo() methods, making this call cheap. + printer->Print("getSerializedSize();\n"); } if (descriptor_->extension_range_count() > 0) { if (descriptor_->options().message_set_wire_format()) { printer->Print( - "com.google.protobuf.GeneratedMessage$ver$\n" - " .ExtendableMessage<$classname$>.ExtensionWriter\n" - " extensionWriter = newMessageSetExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "ver", GeneratedCodeVersionSuffix()); + "com.google.protobuf.GeneratedMessage$ver$\n" + " .ExtendableMessage<$classname$>.ExtensionWriter\n" + " extensionWriter = newMessageSetExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "ver", GeneratedCodeVersionSuffix()); } else { printer->Print( - "com.google.protobuf.GeneratedMessage$ver$\n" - " .ExtendableMessage<$classname$>.ExtensionWriter\n" - " extensionWriter = newExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "ver", GeneratedCodeVersionSuffix()); + "com.google.protobuf.GeneratedMessage$ver$\n" + " .ExtendableMessage<$classname$>.ExtensionWriter\n" + " extensionWriter = newExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "ver", GeneratedCodeVersionSuffix()); } } // Merge the fields and the extension ranges, both sorted by field number. for (int i = 0, j = 0; - i < descriptor_->field_count() || j < sorted_extensions.size(); - ) { + i < descriptor_->field_count() || j < sorted_extensions.size();) { if (i == descriptor_->field_count()) { GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]); } else if (j == sorted_extensions.size()) { @@ -621,132 +625,131 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "unknownFields.writeAsMessageSetTo(output);\n"); + printer->Print("unknownFields.writeAsMessageSetTo(output);\n"); } else { - printer->Print( - "unknownFields.writeTo(output);\n"); + printer->Print("unknownFields.writeTo(output);\n"); } printer->Outdent(); printer->Print( - "}\n" - "\n" - "public int getSerializedSize() {\n" - " int size = memoizedSize;\n" - " if (size != -1) return size;\n" - "\n" - " size = 0;\n"); + "}\n" + "\n" + "@java.lang.Override\n" + "public int getSerializedSize() {\n" + " int size = memoizedSize;\n" + " if (size != -1) return size;\n" + "\n"); printer->Indent(); + printer->Print("size = 0;\n"); + for (int i = 0; i < descriptor_->field_count(); i++) { field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer); } if (descriptor_->extension_range_count() > 0) { if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "size += extensionsSerializedSizeAsMessageSet();\n"); + printer->Print("size += extensionsSerializedSizeAsMessageSet();\n"); } else { - printer->Print( - "size += extensionsSerializedSize();\n"); + printer->Print("size += extensionsSerializedSize();\n"); } } if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "size += unknownFields.getSerializedSizeAsMessageSet();\n"); + printer->Print("size += unknownFields.getSerializedSizeAsMessageSet();\n"); } else { - printer->Print( - "size += unknownFields.getSerializedSize();\n"); + printer->Print("size += unknownFields.getSerializedSize();\n"); } + printer->Print( + "memoizedSize = size;\n" + "return size;\n"); + printer->Outdent(); printer->Print( - " memoizedSize = size;\n" - " return size;\n" - "}\n" - "\n"); + "}\n" + "\n"); } -void ImmutableMessageGenerator:: -GenerateParseFromMethods(io::Printer* printer) { +void ImmutableMessageGenerator::GenerateParseFromMethods(io::Printer* printer) { // Note: These are separate from GenerateMessageSerializationMethods() // because they need to be generated even for messages that are optimized // for code size. printer->Print( - "public static $classname$ parseFrom(\n" - " java.nio.ByteBuffer data)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return PARSER.parseFrom(data);\n" - "}\n" - "public static $classname$ parseFrom(\n" - " java.nio.ByteBuffer data,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return PARSER.parseFrom(data, extensionRegistry);\n" - "}\n" - "public static $classname$ parseFrom(\n" - " com.google.protobuf.ByteString data)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return PARSER.parseFrom(data);\n" - "}\n" - "public static $classname$ parseFrom(\n" - " com.google.protobuf.ByteString data,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return PARSER.parseFrom(data, extensionRegistry);\n" - "}\n" - "public static $classname$ parseFrom(byte[] data)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return PARSER.parseFrom(data);\n" - "}\n" - "public static $classname$ parseFrom(\n" - " byte[] data,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return PARSER.parseFrom(data, extensionRegistry);\n" - "}\n" - "public static $classname$ parseFrom(java.io.InputStream input)\n" - " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage$ver$\n" - " .parseWithIOException(PARSER, input);\n" - "}\n" - "public static $classname$ parseFrom(\n" - " java.io.InputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage$ver$\n" - " .parseWithIOException(PARSER, input, extensionRegistry);\n" - "}\n" - "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n" - " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage$ver$\n" - " .parseDelimitedWithIOException(PARSER, input);\n" - "}\n" - "public static $classname$ parseDelimitedFrom(\n" - " java.io.InputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage$ver$\n" - " .parseDelimitedWithIOException(PARSER, input, extensionRegistry);\n" - "}\n" - "public static $classname$ parseFrom(\n" - " com.google.protobuf.CodedInputStream input)\n" - " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage$ver$\n" - " .parseWithIOException(PARSER, input);\n" - "}\n" - "public static $classname$ parseFrom(\n" - " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage$ver$\n" - " .parseWithIOException(PARSER, input, extensionRegistry);\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "ver", GeneratedCodeVersionSuffix()); + "public static $classname$ parseFrom(\n" + " java.nio.ByteBuffer data)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return PARSER.parseFrom(data);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " java.nio.ByteBuffer data,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return PARSER.parseFrom(data, extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " com.google.protobuf.ByteString data)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return PARSER.parseFrom(data);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " com.google.protobuf.ByteString data,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return PARSER.parseFrom(data, extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(byte[] data)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return PARSER.parseFrom(data);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " byte[] data,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return PARSER.parseFrom(data, extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(java.io.InputStream input)\n" + " throws java.io.IOException {\n" + " return com.google.protobuf.GeneratedMessage$ver$\n" + " .parseWithIOException(PARSER, input);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " java.io.InputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " return com.google.protobuf.GeneratedMessage$ver$\n" + " .parseWithIOException(PARSER, input, extensionRegistry);\n" + "}\n" + "public static $classname$ parseDelimitedFrom(java.io.InputStream " + "input)\n" + " throws java.io.IOException {\n" + " return com.google.protobuf.GeneratedMessage$ver$\n" + " .parseDelimitedWithIOException(PARSER, input);\n" + "}\n" + "public static $classname$ parseDelimitedFrom(\n" + " java.io.InputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " return com.google.protobuf.GeneratedMessage$ver$\n" + " .parseDelimitedWithIOException(PARSER, input, " + "extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " com.google.protobuf.CodedInputStream input)\n" + " throws java.io.IOException {\n" + " return com.google.protobuf.GeneratedMessage$ver$\n" + " .parseWithIOException(PARSER, input);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " com.google.protobuf.CodedInputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " return com.google.protobuf.GeneratedMessage$ver$\n" + " .parseWithIOException(PARSER, input, extensionRegistry);\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), "ver", + GeneratedCodeVersionSuffix()); } void ImmutableMessageGenerator::GenerateSerializeOneField( @@ -756,9 +759,8 @@ void ImmutableMessageGenerator::GenerateSerializeOneField( void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( io::Printer* printer, const Descriptor::ExtensionRange* range) { - printer->Print( - "extensionWriter.writeUntil($end$, output);\n", - "end", SimpleItoa(range->end)); + printer->Print("extensionWriter.writeUntil($end$, output);\n", "end", + StrCat(range->end)); } // =================================================================== @@ -766,46 +768,48 @@ void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { // LITE_RUNTIME implements this at the GeneratedMessageLite level. printer->Print( - "public Builder newBuilderForType() { return newBuilder(); }\n"); + "@java.lang.Override\n" + "public Builder newBuilderForType() { return newBuilder(); }\n"); printer->Print( - "public static Builder newBuilder() {\n" - " return DEFAULT_INSTANCE.toBuilder();\n" - "}\n" - "public static Builder newBuilder($classname$ prototype) {\n" - " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n" - "}\n" - "public Builder toBuilder() {\n" - " return this == DEFAULT_INSTANCE\n" - " ? new Builder() : new Builder().mergeFrom(this);\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "public static Builder newBuilder() {\n" + " return DEFAULT_INSTANCE.toBuilder();\n" + "}\n" + "public static Builder newBuilder($classname$ prototype) {\n" + " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n" + "}\n" + "@java.lang.Override\n" + "public Builder toBuilder() {\n" + " return this == DEFAULT_INSTANCE\n" + " ? new Builder() : new Builder().mergeFrom(this);\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Print( - "@java.lang.Override\n" - "protected Builder newBuilderForType(\n" - " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n" - " Builder builder = new Builder(parent);\n" - " return builder;\n" - "}\n", - "ver", GeneratedCodeVersionSuffix()); + "@java.lang.Override\n" + "protected Builder newBuilderForType(\n" + " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n" + " Builder builder = new Builder(parent);\n" + " return builder;\n" + "}\n", + "ver", GeneratedCodeVersionSuffix()); MessageBuilderGenerator builderGenerator(descriptor_, context_); builderGenerator.Generate(printer); } -void ImmutableMessageGenerator:: -GenerateDescriptorMethods(io::Printer* printer) { +void ImmutableMessageGenerator::GenerateDescriptorMethods( + io::Printer* printer) { if (!descriptor_->options().no_standard_descriptor_accessor()) { printer->Print( - "public static final com.google.protobuf.Descriptors.Descriptor\n" - " getDescriptor() {\n" - " return $fileclass$.internal_$identifier$_descriptor;\n" - "}\n" - "\n", - "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_)); + "public static final com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptor() {\n" + " return $fileclass$.internal_$identifier$_descriptor;\n" + "}\n" + "\n", + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); } std::vector map_fields; for (int i = 0; i < descriptor_->field_count(); i++) { @@ -817,20 +821,21 @@ GenerateDescriptorMethods(io::Printer* printer) { } if (!map_fields.empty()) { printer->Print( - "@SuppressWarnings({\"rawtypes\"})\n" - "protected com.google.protobuf.MapField internalGetMapField(\n" - " int number) {\n" - " switch (number) {\n"); + "@SuppressWarnings({\"rawtypes\"})\n" + "@java.lang.Override\n" + "protected com.google.protobuf.MapField internalGetMapField(\n" + " int number) {\n" + " switch (number) {\n"); printer->Indent(); printer->Indent(); for (int i = 0; i < map_fields.size(); ++i) { const FieldDescriptor* field = map_fields[i]; const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); printer->Print( - "case $number$:\n" - " return internalGet$capitalized_name$();\n", - "number", SimpleItoa(field->number()), - "capitalized_name", info->capitalized_name); + "case $number$:\n" + " return internalGet$capitalized_name$();\n", + "number", StrCat(field->number()), "capitalized_name", + info->capitalized_name); } printer->Print( "default:\n" @@ -843,38 +848,38 @@ GenerateDescriptorMethods(io::Printer* printer) { "}\n"); } printer->Print( - "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n" - " internalGetFieldAccessorTable() {\n" - " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" - " .ensureFieldAccessorsInitialized(\n" - " $classname$.class, $classname$.Builder.class);\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_), - "ver", GeneratedCodeVersionSuffix()); + "@java.lang.Override\n" + "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n" + " internalGetFieldAccessorTable() {\n" + " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" + " .ensureFieldAccessorsInitialized(\n" + " $classname$.class, $classname$.Builder.class);\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_), "ver", + GeneratedCodeVersionSuffix()); } // =================================================================== -void ImmutableMessageGenerator::GenerateIsInitialized( - io::Printer* printer) { +void ImmutableMessageGenerator::GenerateIsInitialized(io::Printer* printer) { // Memoizes whether the protocol buffer is fully initialized (has all // required fields). -1 means not yet computed. 0 means false and 1 means // true. + printer->Print("private byte memoizedIsInitialized = -1;\n"); printer->Print( - "private byte memoizedIsInitialized = -1;\n"); - printer->Print( - "public final boolean isInitialized() {\n"); + "@java.lang.Override\n" + "public final boolean isInitialized() {\n"); printer->Indent(); // Don't directly compare to -1 to avoid an Android x86 JIT bug. printer->Print( - "byte isInitialized = memoizedIsInitialized;\n" - "if (isInitialized == 1) return true;\n" - "if (isInitialized == 0) return false;\n" - "\n"); + "byte isInitialized = memoizedIsInitialized;\n" + "if (isInitialized == 1) return true;\n" + "if (isInitialized == 0) return false;\n" + "\n"); // Check that all required fields in this message are set. // TODO(kenton): We can optimize this when we switch to putting all the @@ -885,11 +890,11 @@ void ImmutableMessageGenerator::GenerateIsInitialized( if (field->is_required()) { printer->Print( - "if (!has$name$()) {\n" - " memoizedIsInitialized = 0;\n" - " return false;\n" - "}\n", - "name", info->capitalized_name); + "if (!has$name$()) {\n" + " memoizedIsInitialized = 0;\n" + " return false;\n" + "}\n", + "name", info->capitalized_name); } } @@ -902,60 +907,48 @@ void ImmutableMessageGenerator::GenerateIsInitialized( switch (field->label()) { case FieldDescriptor::LABEL_REQUIRED: printer->Print( - "if (!get$name$().isInitialized()) {\n" - " memoizedIsInitialized = 0;\n" - " return false;\n" - "}\n", - "type", name_resolver_->GetImmutableClassName( - field->message_type()), - "name", info->capitalized_name); + "if (!get$name$().isInitialized()) {\n" + " memoizedIsInitialized = 0;\n" + " return false;\n" + "}\n", + "type", + name_resolver_->GetImmutableClassName(field->message_type()), + "name", info->capitalized_name); break; case FieldDescriptor::LABEL_OPTIONAL: - if (!SupportFieldPresence(descriptor_->file()) && - field->containing_oneof() != NULL) { - const OneofDescriptor* oneof = field->containing_oneof(); - const OneofGeneratorInfo* oneof_info = - context_->GetOneofGeneratorInfo(oneof); - printer->Print( - "if ($oneof_name$Case_ == $field_number$) {\n", - "oneof_name", oneof_info->name, - "field_number", SimpleItoa(field->number())); - } else { - printer->Print( - "if (has$name$()) {\n", - "name", info->capitalized_name); - } printer->Print( - " if (!get$name$().isInitialized()) {\n" - " memoizedIsInitialized = 0;\n" - " return false;\n" - " }\n" - "}\n", - "name", info->capitalized_name); - break; - case FieldDescriptor::LABEL_REPEATED: - if (IsMapEntry(field->message_type())) { - printer->Print( - "for ($type$ item : get$name$Map().values()) {\n" - " if (!item.isInitialized()) {\n" + "if (has$name$()) {\n" + " if (!get$name$().isInitialized()) {\n" " memoizedIsInitialized = 0;\n" " return false;\n" " }\n" "}\n", - "type", MapValueImmutableClassdName(field->message_type(), - name_resolver_), "name", info->capitalized_name); + break; + case FieldDescriptor::LABEL_REPEATED: + if (IsMapEntry(field->message_type())) { + printer->Print( + "for ($type$ item : get$name$Map().values()) {\n" + " if (!item.isInitialized()) {\n" + " memoizedIsInitialized = 0;\n" + " return false;\n" + " }\n" + "}\n", + "type", + MapValueImmutableClassdName(field->message_type(), + name_resolver_), + "name", info->capitalized_name); } else { printer->Print( - "for (int i = 0; i < get$name$Count(); i++) {\n" - " if (!get$name$(i).isInitialized()) {\n" - " memoizedIsInitialized = 0;\n" - " return false;\n" - " }\n" - "}\n", - "type", name_resolver_->GetImmutableClassName( - field->message_type()), - "name", info->capitalized_name); + "for (int i = 0; i < get$name$Count(); i++) {\n" + " if (!get$name$(i).isInitialized()) {\n" + " memoizedIsInitialized = 0;\n" + " return false;\n" + " }\n" + "}\n", + "type", + name_resolver_->GetImmutableClassName(field->message_type()), + "name", info->capitalized_name); } break; } @@ -964,21 +957,20 @@ void ImmutableMessageGenerator::GenerateIsInitialized( if (descriptor_->extension_range_count() > 0) { printer->Print( - "if (!extensionsAreInitialized()) {\n" - " memoizedIsInitialized = 0;\n" - " return false;\n" - "}\n"); + "if (!extensionsAreInitialized()) {\n" + " memoizedIsInitialized = 0;\n" + " return false;\n" + "}\n"); } printer->Outdent(); - printer->Print( - " memoizedIsInitialized = 1;\n"); + printer->Print(" memoizedIsInitialized = 1;\n"); printer->Print( - " return true;\n" - "}\n" - "\n"); + " return true;\n" + "}\n" + "\n"); } // =================================================================== @@ -988,82 +980,73 @@ bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) { if (field->is_repeated()) { return false; } - if (SupportFieldPresence(field->file())) { + if (HasHasbit(field)) { return true; } - return GetJavaType(field) == JAVATYPE_MESSAGE && - field->containing_oneof() == NULL; + return GetJavaType(field) == JAVATYPE_MESSAGE && !IsRealOneof(field); } } // namespace -void ImmutableMessageGenerator:: -GenerateEqualsAndHashCode(io::Printer* printer) { +void ImmutableMessageGenerator::GenerateEqualsAndHashCode( + io::Printer* printer) { printer->Print( - "@java.lang.Override\n" - "public boolean equals(final java.lang.Object obj) {\n"); + "@java.lang.Override\n" + "public boolean equals("); + printer->Print("final java.lang.Object obj) {\n"); printer->Indent(); printer->Print( - "if (obj == this) {\n" - " return true;\n" - "}\n" - "if (!(obj instanceof $classname$)) {\n" - " return super.equals(obj);\n" - "}\n" - "$classname$ other = ($classname$) obj;\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - - printer->Print("boolean result = true;\n"); + "if (obj == this) {\n" + " return true;\n" + "}\n" + "if (!(obj instanceof $classname$)) {\n" + " return super.equals(obj);\n" + "}\n" + "$classname$ other = ($classname$) obj;\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof() == NULL) { + if (!IsRealOneof(field)) { const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); if (check_has_bits) { printer->Print( - "result = result && (has$name$() == other.has$name$());\n" - "if (has$name$()) {\n", - "name", info->capitalized_name); + "if (has$name$() != other.has$name$()) return false;\n" + "if (has$name$()) {\n", + "name", info->capitalized_name); printer->Indent(); } field_generators_.get(field).GenerateEqualsCode(printer); if (check_has_bits) { printer->Outdent(); - printer->Print( - "}\n"); + printer->Print("}\n"); } } } // Compare oneofs. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "result = result && get$oneof_capitalized_name$Case().equals(\n" - " other.get$oneof_capitalized_name$Case());\n", - "oneof_capitalized_name", - context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name); + for (auto oneof : oneofs_) { printer->Print( - "if (!result) return false;\n" - "switch ($oneof_name$Case_) {\n", - "oneof_name", - context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name); + "if (!get$oneof_capitalized_name$Case().equals(" + "other.get$oneof_capitalized_name$Case())) return false;\n", + "oneof_capitalized_name", + context_->GetOneofGeneratorInfo(oneof)->capitalized_name); + printer->Print("switch ($oneof_name$Case_) {\n", "oneof_name", + context_->GetOneofGeneratorInfo(oneof)->name); printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case $field_number$:\n", - "field_number", - SimpleItoa(field->number())); + for (int j = 0; j < (oneof)->field_count(); j++) { + const FieldDescriptor* field = (oneof)->field(j); + printer->Print("case $field_number$:\n", "field_number", + StrCat(field->number())); printer->Indent(); field_generators_.get(field).GenerateEqualsCode(printer); printer->Print("break;\n"); printer->Outdent(); } printer->Print( - "case 0:\n" - "default:\n"); + "case 0:\n" + "default:\n"); printer->Outdent(); printer->Print("}\n"); } @@ -1072,32 +1055,29 @@ GenerateEqualsAndHashCode(io::Printer* printer) { // false for non-canonical ordering when running in LITE_RUNTIME but it's // the best we can do. printer->Print( - "result = result && unknownFields.equals(other.unknownFields);\n"); + "if (!unknownFields.equals(other.unknownFields)) return false;\n"); if (descriptor_->extension_range_count() > 0) { printer->Print( - "result = result &&\n" - " getExtensionFields().equals(other.getExtensionFields());\n"); + "if (!getExtensionFields().equals(other.getExtensionFields()))\n" + " return false;\n"); } - printer->Print( - "return result;\n"); + printer->Print("return true;\n"); printer->Outdent(); printer->Print( - "}\n" - "\n"); + "}\n" + "\n"); printer->Print( - "@java.lang.Override\n" - "public int hashCode() {\n"); + "@java.lang.Override\n" + "public int hashCode() {\n"); printer->Indent(); - printer->Print( - "if (memoizedHashCode != 0) {\n"); + printer->Print("if (memoizedHashCode != 0) {\n"); printer->Indent(); - printer->Print( - "return memoizedHashCode;\n"); + printer->Print("return memoizedHashCode;\n"); printer->Outdent(); printer->Print( - "}\n" - "int hash = 41;\n"); + "}\n" + "int hash = 41;\n"); // If we output a getDescriptor() method, use that as it is more efficient. if (descriptor_->options().no_standard_descriptor_accessor()) { @@ -1109,13 +1089,11 @@ GenerateEqualsAndHashCode(io::Printer* printer) { // hashCode non-oneofs. for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof() == NULL) { + if (!IsRealOneof(field)) { const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); if (check_has_bits) { - printer->Print( - "if (has$name$()) {\n", - "name", info->capitalized_name); + printer->Print("if (has$name$()) {\n", "name", info->capitalized_name); printer->Indent(); } field_generators_.get(field).GenerateHashCode(printer); @@ -1127,66 +1105,59 @@ GenerateEqualsAndHashCode(io::Printer* printer) { } // hashCode oneofs. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "switch ($oneof_name$Case_) {\n", - "oneof_name", - context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name); + for (auto oneof : oneofs_) { + printer->Print("switch ($oneof_name$Case_) {\n", "oneof_name", + context_->GetOneofGeneratorInfo(oneof)->name); printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case $field_number$:\n", - "field_number", - SimpleItoa(field->number())); + for (int j = 0; j < (oneof)->field_count(); j++) { + const FieldDescriptor* field = (oneof)->field(j); + printer->Print("case $field_number$:\n", "field_number", + StrCat(field->number())); printer->Indent(); field_generators_.get(field).GenerateHashCode(printer); printer->Print("break;\n"); printer->Outdent(); } printer->Print( - "case 0:\n" - "default:\n"); + "case 0:\n" + "default:\n"); printer->Outdent(); printer->Print("}\n"); } if (descriptor_->extension_range_count() > 0) { - printer->Print( - "hash = hashFields(hash, getExtensionFields());\n"); + printer->Print("hash = hashFields(hash, getExtensionFields());\n"); } + printer->Print("hash = (29 * hash) + unknownFields.hashCode();\n"); printer->Print( - "hash = (29 * hash) + unknownFields.hashCode();\n"); - printer->Print( - "memoizedHashCode = hash;\n" - "return hash;\n"); + "memoizedHashCode = hash;\n" + "return hash;\n"); printer->Outdent(); printer->Print( - "}\n" - "\n"); + "}\n" + "\n"); } // =================================================================== -void ImmutableMessageGenerator:: -GenerateExtensionRegistrationCode(io::Printer* printer) { +void ImmutableMessageGenerator::GenerateExtensionRegistrationCode( + io::Printer* printer) { for (int i = 0; i < descriptor_->extension_count(); i++) { ImmutableExtensionGenerator(descriptor_->extension(i), context_) - .GenerateRegistrationCode(printer); + .GenerateRegistrationCode(printer); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { ImmutableMessageGenerator(descriptor_->nested_type(i), context_) - .GenerateExtensionRegistrationCode(printer); + .GenerateExtensionRegistrationCode(printer); } } // =================================================================== -void ImmutableMessageGenerator:: -GenerateParsingConstructor(io::Printer* printer) { - google::protobuf::scoped_array sorted_fields( +void ImmutableMessageGenerator::GenerateParsingConstructor( + io::Printer* printer) { + std::unique_ptr sorted_fields( SortFieldsByNumber(descriptor_)); printer->Print( @@ -1199,7 +1170,10 @@ GenerateParsingConstructor(io::Printer* printer) { // Initialize all fields to default. printer->Print( - "this();\n"); + "this();\n" + "if (extensionRegistry == null) {\n" + " throw new java.lang.NullPointerException();\n" + "}\n"); // Use builder bits to track mutable repeated fields. int totalBuilderBits = 0; @@ -1210,84 +1184,80 @@ GenerateParsingConstructor(io::Printer* printer) { } int totalBuilderInts = (totalBuilderBits + 31) / 32; for (int i = 0; i < totalBuilderInts; i++) { - printer->Print("int mutable_$bit_field_name$ = 0;\n", - "bit_field_name", GetBitFieldName(i)); + printer->Print("int mutable_$bit_field_name$ = 0;\n", "bit_field_name", + GetBitFieldName(i)); } printer->Print( "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" " com.google.protobuf.UnknownFieldSet.newBuilder();\n"); - printer->Print( - "try {\n"); + printer->Print("try {\n"); printer->Indent(); printer->Print( - "boolean done = false;\n" - "while (!done) {\n"); + "boolean done = false;\n" + "while (!done) {\n"); printer->Indent(); printer->Print( - "int tag = input.readTag();\n" - "switch (tag) {\n"); + "int tag = input.readTag();\n" + "switch (tag) {\n"); printer->Indent(); printer->Print( - "case 0:\n" // zero signals EOF / limit reached - " done = true;\n" - " break;\n" - "default: {\n" - " if (!parseUnknownField$suffix$(\n" - " input, unknownFields, extensionRegistry, tag)) {\n" - " done = true;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n", - "suffix", - descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ? "Proto3" - : ""); + "case 0:\n" // zero signals EOF / limit reached + " done = true;\n" + " break;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = sorted_fields[i]; - uint32 tag = WireFormatLite::MakeTag(field->number(), - WireFormat::WireTypeForFieldType(field->type())); + uint32 tag = WireFormatLite::MakeTag( + field->number(), WireFormat::WireTypeForFieldType(field->type())); - printer->Print( - "case $tag$: {\n", - "tag", SimpleItoa(static_cast(tag))); + printer->Print("case $tag$: {\n", "tag", + StrCat(static_cast(tag))); printer->Indent(); field_generators_.get(field).GenerateParsingCode(printer); printer->Outdent(); printer->Print( - " break;\n" - "}\n"); + " break;\n" + "}\n"); if (field->is_packable()) { // To make packed = true wire compatible, we generate parsing code from a // packed version of this field regardless of field->options().packed(). - uint32 packed_tag = WireFormatLite::MakeTag(field->number(), - WireFormatLite::WIRETYPE_LENGTH_DELIMITED); - printer->Print( - "case $tag$: {\n", - "tag", SimpleItoa(static_cast(packed_tag))); + uint32 packed_tag = WireFormatLite::MakeTag( + field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + printer->Print("case $tag$: {\n", "tag", + StrCat(static_cast(packed_tag))); printer->Indent(); field_generators_.get(field).GenerateParsingCodeFromPacked(printer); printer->Outdent(); printer->Print( - " break;\n" - "}\n"); + " break;\n" + "}\n"); } } + printer->Print( + "default: {\n" + " if (!parseUnknownField(\n" + " input, unknownFields, extensionRegistry, tag)) {\n" + " done = true;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); + printer->Outdent(); printer->Outdent(); printer->Print( - " }\n" // switch (tag) - "}\n"); // while (!done) + " }\n" // switch (tag) + "}\n"); // while (!done) printer->Outdent(); printer->Print( @@ -1309,13 +1279,12 @@ GenerateParsingConstructor(io::Printer* printer) { printer->Print("this.unknownFields = unknownFields.build();\n"); // Make extensions immutable. - printer->Print( - "makeExtensionsImmutable();\n"); + printer->Print("makeExtensionsImmutable();\n"); printer->Outdent(); printer->Outdent(); printer->Print( - " }\n" // finally + " }\n" // finally "}\n"); } @@ -1330,15 +1299,15 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { "classname", descriptor_->name()); printer->Indent(); printer->Print( + "@java.lang.Override\n" "public $classname$ parsePartialFrom(\n" " com.google.protobuf.CodedInputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n", "classname", descriptor_->name()); if (context_->HasGeneratedMethods(descriptor_)) { - printer->Print( - " return new $classname$(input, extensionRegistry);\n", - "classname", descriptor_->name()); + printer->Print(" return new $classname$(input, extensionRegistry);\n", + "classname", descriptor_->name()); } else { // When parsing constructor isn't generated, use builder to parse // messages. Note, will fallback to use reflection based mergeFieldFrom() @@ -1358,8 +1327,7 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { "return builder.buildPartial();\n"); printer->Outdent(); } - printer->Print( - "}\n"); + printer->Print("}\n"); printer->Outdent(); printer->Print( "};\n" @@ -1381,82 +1349,85 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { // =================================================================== void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) { for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { + if (!IsRealOneof(descriptor_->field(i))) { field_generators_.get(descriptor_->field(i)) .GenerateInitializationCode(printer); } } } - void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) { printer->Print( - "private static String getTypeUrl(\n" - " java.lang.String typeUrlPrefix,\n" - " com.google.protobuf.Descriptors.Descriptor descriptor) {\n" - " return typeUrlPrefix.endsWith(\"/\")\n" - " ? typeUrlPrefix + descriptor.getFullName()\n" - " : typeUrlPrefix + \"/\" + descriptor.getFullName();\n" - "}\n" - "\n" - "private static String getTypeNameFromTypeUrl(\n" - " java.lang.String typeUrl) {\n" - " int pos = typeUrl.lastIndexOf('/');\n" - " return pos == -1 ? \"\" : typeUrl.substring(pos + 1);\n" - "}\n" - "\n" - "public static Any pack(\n" - " T message) {\n" - " return Any.newBuilder()\n" - " .setTypeUrl(getTypeUrl(\"type.googleapis.com\",\n" - " message.getDescriptorForType()))\n" - " .setValue(message.toByteString())\n" - " .build();\n" - "}\n" - "\n" - "/**\n" - " * Packs a message using the given type URL prefix. The type URL will\n" - " * be constructed by concatenating the message type's full name to the\n" - " * prefix with an optional \"/\" separator if the prefix doesn't end\n" - " * with \"/\" already.\n" - " */\n" - "public static Any pack(\n" - " T message, java.lang.String typeUrlPrefix) {\n" - " return Any.newBuilder()\n" - " .setTypeUrl(getTypeUrl(typeUrlPrefix,\n" - " message.getDescriptorForType()))\n" - " .setValue(message.toByteString())\n" - " .build();\n" - "}\n" - "\n" - "public boolean is(\n" - " java.lang.Class clazz) {\n" - " T defaultInstance =\n" - " com.google.protobuf.Internal.getDefaultInstance(clazz);\n" - " return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n" - " defaultInstance.getDescriptorForType().getFullName());\n" - "}\n" - "\n" - "private volatile com.google.protobuf.Message cachedUnpackValue;\n" - "\n" - "@java.lang.SuppressWarnings(\"unchecked\")\n" - "public T unpack(\n" - " java.lang.Class clazz)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " if (!is(clazz)) {\n" - " throw new com.google.protobuf.InvalidProtocolBufferException(\n" - " \"Type of the Any message does not match the given class.\");\n" - " }\n" - " if (cachedUnpackValue != null) {\n" - " return (T) cachedUnpackValue;\n" - " }\n" - " T defaultInstance =\n" - " com.google.protobuf.Internal.getDefaultInstance(clazz);\n" - " T result = (T) defaultInstance.getParserForType()\n" - " .parseFrom(getValue());\n" - " cachedUnpackValue = result;\n" - " return result;\n" - "}\n"); + "private static String getTypeUrl(\n" + " java.lang.String typeUrlPrefix,\n" + " com.google.protobuf.Descriptors.Descriptor descriptor) {\n" + " return typeUrlPrefix.endsWith(\"/\")\n" + " ? typeUrlPrefix + descriptor.getFullName()\n" + " : typeUrlPrefix + \"/\" + descriptor.getFullName();\n" + "}\n" + "\n" + "private static String getTypeNameFromTypeUrl(\n" + " java.lang.String typeUrl) {\n" + " int pos = typeUrl.lastIndexOf('/');\n" + " return pos == -1 ? \"\" : typeUrl.substring(pos + 1);\n" + "}\n" + "\n" + "public static Any pack(\n" + " T message) {\n" + " return Any.newBuilder()\n" + " .setTypeUrl(getTypeUrl(\"type.googleapis.com\",\n" + " message.getDescriptorForType()))\n" + " .setValue(message.toByteString())\n" + " .build();\n" + "}\n" + "\n" + "/**\n" + " * Packs a message using the given type URL prefix. The type URL will\n" + " * be constructed by concatenating the message type's full name to the\n" + " * prefix with an optional \"/\" separator if the prefix doesn't end\n" + " * with \"/\" already.\n" + " */\n" + "public static Any pack(\n" + " T message, java.lang.String typeUrlPrefix) {\n" + " return Any.newBuilder()\n" + " .setTypeUrl(getTypeUrl(typeUrlPrefix,\n" + " message.getDescriptorForType()))\n" + " .setValue(message.toByteString())\n" + " .build();\n" + "}\n" + "\n" + "public boolean is(\n" + " java.lang.Class clazz) {\n" + " T defaultInstance =\n" + " com.google.protobuf.Internal.getDefaultInstance(clazz);\n" + " return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n" + " defaultInstance.getDescriptorForType().getFullName());\n" + "}\n" + "\n" + "private volatile com.google.protobuf.Message cachedUnpackValue;\n" + "\n" + "@java.lang.SuppressWarnings(\"unchecked\")\n" + "public T unpack(\n" + " java.lang.Class clazz)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " boolean invalidClazz = false;\n" + " if (cachedUnpackValue != null) {\n" + " if (cachedUnpackValue.getClass() == clazz) {\n" + " return (T) cachedUnpackValue;\n" + " }\n" + " invalidClazz = true;\n" + " }\n" + " if (invalidClazz || !is(clazz)) {\n" + " throw new com.google.protobuf.InvalidProtocolBufferException(\n" + " \"Type of the Any message does not match the given class.\");\n" + " }\n" + " T defaultInstance =\n" + " com.google.protobuf.Internal.getDefaultInstance(clazz);\n" + " T result = (T) defaultInstance.getParserForType()\n" + " .parseFrom(getValue());\n" + " cachedUnpackValue = result;\n" + " return result;\n" + "}\n"); } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h index da1447c176d84..87b9df5e598b1 100644 --- a/src/google/protobuf/compiler/java/java_message.h +++ b/src/google/protobuf/compiler/java/java_message.h @@ -35,23 +35,25 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ -#include #include +#include #include namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -66,8 +68,8 @@ class MessageGenerator { // All static variables have to be declared at the top-level of the file // so that we can control initialization order, which is important for // DescriptorProto bootstrapping to work. - virtual void GenerateStaticVariables( - io::Printer* printer, int* bytecode_estimate) = 0; + virtual void GenerateStaticVariables(io::Printer* printer, + int* bytecode_estimate) = 0; // Output code which initializes the static variables generated by // GenerateStaticVariables(). Returns an estimate of bytecode size. @@ -76,7 +78,8 @@ class MessageGenerator { // Generate the class itself. virtual void Generate(io::Printer* printer) = 0; - // Generates the base interface that both the class and its builder implement + // Generates the base interface that both the class and its builder + // implement virtual void GenerateInterface(io::Printer* printer) = 0; // Generate code to register all contained extensions with an @@ -85,6 +88,7 @@ class MessageGenerator { protected: const Descriptor* descriptor_; + std::set oneofs_; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); @@ -98,14 +102,13 @@ class ImmutableMessageGenerator : public MessageGenerator { virtual void Generate(io::Printer* printer); virtual void GenerateInterface(io::Printer* printer); virtual void GenerateExtensionRegistrationCode(io::Printer* printer); - virtual void GenerateStaticVariables( - io::Printer* printer, int* bytecode_estimate); + virtual void GenerateStaticVariables(io::Printer* printer, + int* bytecode_estimate); // Returns an estimate of the number of bytes the printed code will compile to virtual int GenerateStaticVariableInitializers(io::Printer* printer); private: - void GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate); // Returns an estimate of the number of bytes the printed code will compile to @@ -137,6 +140,6 @@ class ImmutableMessageGenerator : public MessageGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ diff --git a/src/google/protobuf/compiler/java/java_message_builder.cc b/src/google/protobuf/compiler/java/java_message_builder.cc index f9bbfbf4c9543..320852b1be975 100644 --- a/src/google/protobuf/compiler/java/java_message_builder.cc +++ b/src/google/protobuf/compiler/java/java_message_builder.cc @@ -35,12 +35,8 @@ #include #include -#include #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include @@ -50,13 +46,12 @@ #include #include #include +#include #include #include -#include #include -#include #include - +#include namespace google { namespace protobuf { @@ -64,53 +59,54 @@ namespace compiler { namespace java { namespace { -bool GenerateHasBits(const Descriptor* descriptor) { - return SupportFieldPresence(descriptor->file()) || - HasRepeatedFields(descriptor); -} - -string MapValueImmutableClassdName(const Descriptor* descriptor, - ClassNameResolver* name_resolver) { +std::string MapValueImmutableClassdName(const Descriptor* descriptor, + ClassNameResolver* name_resolver) { const FieldDescriptor* value_field = descriptor->FindFieldByName("value"); GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type()); return name_resolver->GetImmutableClassName(value_field->message_type()); } } // namespace -MessageBuilderGenerator::MessageBuilderGenerator( - const Descriptor* descriptor, Context* context) - : descriptor_(descriptor), context_(context), - name_resolver_(context->GetNameResolver()), - field_generators_(descriptor, context_) { +MessageBuilderGenerator::MessageBuilderGenerator(const Descriptor* descriptor, + Context* context) + : descriptor_(descriptor), + context_(context), + name_resolver_(context->GetNameResolver()), + field_generators_(descriptor, context_) { GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite())) << "Generator factory error: A non-lite message generator is used to " "generate lite messages."; + for (int i = 0; i < descriptor_->field_count(); i++) { + if (IsRealOneof(descriptor_->field(i))) { + oneofs_.insert(descriptor_->field(i)->containing_oneof()); + } + } } MessageBuilderGenerator::~MessageBuilderGenerator() {} -void MessageBuilderGenerator:: -Generate(io::Printer* printer) { +void MessageBuilderGenerator::Generate(io::Printer* printer) { WriteMessageDocComment(printer, descriptor_); if (descriptor_->extension_range_count() > 0) { printer->Print( - "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage$ver$.ExtendableBuilder<\n" - " $classname$, Builder> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_), - "ver", GeneratedCodeVersionSuffix()); + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessage$ver$.ExtendableBuilder<\n" + " $classname$, Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_), "ver", + GeneratedCodeVersionSuffix()); } else { printer->Print( - "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage$ver$.Builder implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_), - "ver", GeneratedCodeVersionSuffix()); + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessage$ver$.Builder " + "implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_), "ver", + GeneratedCodeVersionSuffix()); } printer->Indent(); @@ -123,79 +119,75 @@ Generate(io::Printer* printer) { } // oneof - std::map vars; - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - vars["oneof_name"] = context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name; - vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name; - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + std::map vars; + for (auto oneof : oneofs_) { + vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name; + vars["oneof_capitalized_name"] = + context_->GetOneofGeneratorInfo(oneof)->capitalized_name; + vars["oneof_index"] = StrCat(oneof->index()); // oneofCase_ and oneof_ printer->Print(vars, - "private int $oneof_name$Case_ = 0;\n" - "private java.lang.Object $oneof_name$_;\n"); + "private int $oneof_name$Case_ = 0;\n" + "private java.lang.Object $oneof_name$_;\n"); // oneofCase() and clearOneof() printer->Print(vars, - "public $oneof_capitalized_name$Case\n" - " get$oneof_capitalized_name$Case() {\n" - " return $oneof_capitalized_name$Case.forNumber(\n" - " $oneof_name$Case_);\n" - "}\n" - "\n" - "public Builder clear$oneof_capitalized_name$() {\n" - " $oneof_name$Case_ = 0;\n" - " $oneof_name$_ = null;\n"); + "public $oneof_capitalized_name$Case\n" + " get$oneof_capitalized_name$Case() {\n" + " return $oneof_capitalized_name$Case.forNumber(\n" + " $oneof_name$Case_);\n" + "}\n" + "\n" + "public Builder clear$oneof_capitalized_name$() {\n" + " $oneof_name$Case_ = 0;\n" + " $oneof_name$_ = null;\n"); printer->Print(" onChanged();\n"); printer->Print( - " return this;\n" - "}\n" - "\n"); + " return this;\n" + "}\n" + "\n"); } - if (GenerateHasBits(descriptor_)) { - // Integers for bit fields. - int totalBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - totalBits += field_generators_.get(descriptor_->field(i)) - .GetNumBitsForBuilder(); - } - int totalInts = (totalBits + 31) / 32; - for (int i = 0; i < totalInts; i++) { - printer->Print("private int $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } + // Integers for bit fields. + int totalBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + totalBits += + field_generators_.get(descriptor_->field(i)).GetNumBitsForBuilder(); + } + int totalInts = (totalBits + 31) / 32; + for (int i = 0; i < totalInts; i++) { + printer->Print("private int $bit_field_name$;\n", "bit_field_name", + GetBitFieldName(i)); } for (int i = 0; i < descriptor_->field_count(); i++) { printer->Print("\n"); field_generators_.get(descriptor_->field(i)) - .GenerateBuilderMembers(printer); + .GenerateBuilderMembers(printer); } - bool is_proto3 = - descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3; - // Override methods declared in GeneratedMessage to return the concrete - // generated type so callsites won't depend on GeneratedMessage. This - // is needed to keep binary compatibility when we change generated code - // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release - // we changed all generated code to subclass GeneratedMessageV3). + // Override methods declared in GeneratedMessage to return the concrete + // generated type so callsites won't depend on GeneratedMessage. This + // is needed to keep binary compatibility when we change generated code + // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release + // we changed all generated code to subclass GeneratedMessageV3). printer->Print( - "public final Builder setUnknownFields(\n" - " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" - " return super.setUnknownFields$suffix$(unknownFields);\n" - "}\n" - "\n" - "public final Builder mergeUnknownFields(\n" - " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" - " return super.mergeUnknownFields(unknownFields);\n" - "}\n" - "\n", - "suffix", is_proto3 ? "Proto3" : ""); + "@java.lang.Override\n" + "public final Builder setUnknownFields(\n" + " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" + " return super.setUnknownFields(unknownFields);\n" + "}\n" + "\n" + "@java.lang.Override\n" + "public final Builder mergeUnknownFields(\n" + " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" + " return super.mergeUnknownFields(unknownFields);\n" + "}\n" + "\n"); printer->Print( - "\n" - "// @@protoc_insertion_point(builder_scope:$full_name$)\n", - "full_name", descriptor_->full_name()); + "\n" + "// @@protoc_insertion_point(builder_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); printer->Outdent(); printer->Print("}\n"); @@ -203,17 +195,16 @@ Generate(io::Printer* printer) { // =================================================================== -void MessageBuilderGenerator:: -GenerateDescriptorMethods(io::Printer* printer) { +void MessageBuilderGenerator::GenerateDescriptorMethods(io::Printer* printer) { if (!descriptor_->options().no_standard_descriptor_accessor()) { printer->Print( - "public static final com.google.protobuf.Descriptors.Descriptor\n" - " getDescriptor() {\n" - " return $fileclass$.internal_$identifier$_descriptor;\n" - "}\n" - "\n", - "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_)); + "public static final com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptor() {\n" + " return $fileclass$.internal_$identifier$_descriptor;\n" + "}\n" + "\n", + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); } std::vector map_fields; for (int i = 0; i < descriptor_->field_count(); i++) { @@ -225,20 +216,20 @@ GenerateDescriptorMethods(io::Printer* printer) { } if (!map_fields.empty()) { printer->Print( - "@SuppressWarnings({\"rawtypes\"})\n" - "protected com.google.protobuf.MapField internalGetMapField(\n" - " int number) {\n" - " switch (number) {\n"); + "@SuppressWarnings({\"rawtypes\"})\n" + "protected com.google.protobuf.MapField internalGetMapField(\n" + " int number) {\n" + " switch (number) {\n"); printer->Indent(); printer->Indent(); for (int i = 0; i < map_fields.size(); ++i) { const FieldDescriptor* field = map_fields[i]; const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); printer->Print( - "case $number$:\n" - " return internalGet$capitalized_name$();\n", - "number", SimpleItoa(field->number()), - "capitalized_name", info->capitalized_name); + "case $number$:\n" + " return internalGet$capitalized_name$();\n", + "number", StrCat(field->number()), "capitalized_name", + info->capitalized_name); } printer->Print( "default:\n" @@ -250,21 +241,20 @@ GenerateDescriptorMethods(io::Printer* printer) { " }\n" "}\n"); printer->Print( - "@SuppressWarnings({\"rawtypes\"})\n" - "protected com.google.protobuf.MapField internalGetMutableMapField(\n" - " int number) {\n" - " switch (number) {\n"); + "@SuppressWarnings({\"rawtypes\"})\n" + "protected com.google.protobuf.MapField internalGetMutableMapField(\n" + " int number) {\n" + " switch (number) {\n"); printer->Indent(); printer->Indent(); for (int i = 0; i < map_fields.size(); ++i) { const FieldDescriptor* field = map_fields[i]; - const FieldGeneratorInfo* info = - context_->GetFieldGeneratorInfo(field); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); printer->Print( - "case $number$:\n" - " return internalGetMutable$capitalized_name$();\n", - "number", SimpleItoa(field->number()), - "capitalized_name", info->capitalized_name); + "case $number$:\n" + " return internalGetMutable$capitalized_name$();\n", + "number", StrCat(field->number()), "capitalized_name", + info->capitalized_name); } printer->Print( "default:\n" @@ -277,23 +267,24 @@ GenerateDescriptorMethods(io::Printer* printer) { "}\n"); } printer->Print( - "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n" - " internalGetFieldAccessorTable() {\n" - " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" - " .ensureFieldAccessorsInitialized(\n" - " $classname$.class, $classname$.Builder.class);\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_), - "ver", GeneratedCodeVersionSuffix()); + "@java.lang.Override\n" + "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n" + " internalGetFieldAccessorTable() {\n" + " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" + " .ensureFieldAccessorsInitialized(\n" + " $classname$.class, $classname$.Builder.class);\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_), "ver", + GeneratedCodeVersionSuffix()); } // =================================================================== -void MessageBuilderGenerator:: -GenerateCommonBuilderMethods(io::Printer* printer) { +void MessageBuilderGenerator::GenerateCommonBuilderMethods( + io::Printer* printer) { printer->Print( "// Construct using $classname$.newBuilder()\n" "private Builder() {\n" @@ -303,24 +294,24 @@ GenerateCommonBuilderMethods(io::Printer* printer) { "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Print( - "private Builder(\n" - " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n" - " super(parent);\n" - " maybeForceBuilderInitialization();\n" - "}\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "ver", GeneratedCodeVersionSuffix()); + "private Builder(\n" + " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n" + " super(parent);\n" + " maybeForceBuilderInitialization();\n" + "}\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), "ver", + GeneratedCodeVersionSuffix()); printer->Print( - "private void maybeForceBuilderInitialization() {\n" - " if (com.google.protobuf.GeneratedMessage$ver$\n" - " .alwaysUseFieldBuilders) {\n", - "ver", GeneratedCodeVersionSuffix()); + "private void maybeForceBuilderInitialization() {\n" + " if (com.google.protobuf.GeneratedMessage$ver$\n" + " .alwaysUseFieldBuilders) {\n", + "ver", GeneratedCodeVersionSuffix()); printer->Indent(); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { + if (!IsRealOneof(descriptor_->field(i))) { field_generators_.get(descriptor_->field(i)) .GenerateFieldBuilderInitializationCode(printer); } @@ -329,69 +320,73 @@ GenerateCommonBuilderMethods(io::Printer* printer) { printer->Outdent(); printer->Print( - " }\n" - "}\n"); + " }\n" + "}\n"); printer->Print( - "public Builder clear() {\n" - " super.clear();\n"); + "@java.lang.Override\n" + "public Builder clear() {\n" + " super.clear();\n"); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { + if (!IsRealOneof(descriptor_->field(i))) { field_generators_.get(descriptor_->field(i)) .GenerateBuilderClearCode(printer); } } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + for (auto oneof : oneofs_) { printer->Print( - "$oneof_name$Case_ = 0;\n" - "$oneof_name$_ = null;\n", - "oneof_name", context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name); + "$oneof_name$Case_ = 0;\n" + "$oneof_name$_ = null;\n", + "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name); } printer->Outdent(); printer->Print( - " return this;\n" - "}\n" - "\n"); + " return this;\n" + "}\n" + "\n"); printer->Print( - "public com.google.protobuf.Descriptors.Descriptor\n" - " getDescriptorForType() {\n" - " return $fileclass$.internal_$identifier$_descriptor;\n" - "}\n" - "\n", - "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_)); + "@java.lang.Override\n" + "public com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptorForType() {\n" + " return $fileclass$.internal_$identifier$_descriptor;\n" + "}\n" + "\n", + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); // LITE runtime implements this in GeneratedMessageLite. printer->Print( - "public $classname$ getDefaultInstanceForType() {\n" - " return $classname$.getDefaultInstance();\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "@java.lang.Override\n" + "public $classname$ getDefaultInstanceForType() {\n" + " return $classname$.getDefaultInstance();\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Print( - "public $classname$ build() {\n" - " $classname$ result = buildPartial();\n" - " if (!result.isInitialized()) {\n" - " throw newUninitializedMessageException(result);\n" - " }\n" - " return result;\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "@java.lang.Override\n" + "public $classname$ build() {\n" + " $classname$ result = buildPartial();\n" + " if (!result.isInitialized()) {\n" + " throw newUninitializedMessageException(result);\n" + " }\n" + " return result;\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Print( - "public $classname$ buildPartial() {\n" - " $classname$ result = new $classname$(this);\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "@java.lang.Override\n" + "public $classname$ buildPartial() {\n" + " $classname$ result = new $classname$(this);\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Indent(); @@ -406,19 +401,17 @@ GenerateCommonBuilderMethods(io::Printer* printer) { int totalBuilderInts = (totalBuilderBits + 31) / 32; int totalMessageInts = (totalMessageBits + 31) / 32; - if (GenerateHasBits(descriptor_)) { - // Local vars for from and to bit fields to avoid accessing the builder and - // message over and over for these fields. Seems to provide a slight - // perforamance improvement in micro benchmark and this is also what proto1 - // code does. - for (int i = 0; i < totalBuilderInts; i++) { - printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } - for (int i = 0; i < totalMessageInts; i++) { - printer->Print("int to_$bit_field_name$ = 0;\n", - "bit_field_name", GetBitFieldName(i)); - } + // Local vars for from and to bit fields to avoid accessing the builder and + // message over and over for these fields. Seems to provide a slight + // perforamance improvement in micro benchmark and this is also what proto1 + // code does. + for (int i = 0; i < totalBuilderInts; i++) { + printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + for (int i = 0; i < totalMessageInts; i++) { + printer->Print("int to_$bit_field_name$ = 0;\n", "bit_field_name", + GetBitFieldName(i)); } // Output generation code for each field. @@ -426,30 +419,26 @@ GenerateCommonBuilderMethods(io::Printer* printer) { field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer); } - if (GenerateHasBits(descriptor_)) { - // Copy the bit field results to the generated message - for (int i = 0; i < totalMessageInts; i++) { - printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } + // Copy the bit field results to the generated message + for (int i = 0; i < totalMessageInts; i++) { + printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + for (auto oneof : oneofs_) { printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n", - "oneof_name", context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name); + "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name); } printer->Outdent(); - printer->Print( - " onBuilt();\n"); + printer->Print(" onBuilt();\n"); printer->Print( - " return result;\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + " return result;\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); // Override methods declared in GeneratedMessage to return the concrete // generated type so callsites won't depend on GeneratedMessage. This @@ -457,177 +446,178 @@ GenerateCommonBuilderMethods(io::Printer* printer) { // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release // we changed all generated code to subclass GeneratedMessageV3). printer->Print( - "public Builder clone() {\n" - " return (Builder) super.clone();\n" - "}\n" - "public Builder setField(\n" - " com.google.protobuf.Descriptors.FieldDescriptor field,\n" - " java.lang.Object value) {\n" - " return (Builder) super.setField(field, value);\n" - "}\n" - "public Builder clearField(\n" - " com.google.protobuf.Descriptors.FieldDescriptor field) {\n" - " return (Builder) super.clearField(field);\n" - "}\n" - "public Builder clearOneof(\n" - " com.google.protobuf.Descriptors.OneofDescriptor oneof) {\n" - " return (Builder) super.clearOneof(oneof);\n" - "}\n" - "public Builder setRepeatedField(\n" - " com.google.protobuf.Descriptors.FieldDescriptor field,\n" - " int index, java.lang.Object value) {\n" - " return (Builder) super.setRepeatedField(field, index, value);\n" - "}\n" - "public Builder addRepeatedField(\n" - " com.google.protobuf.Descriptors.FieldDescriptor field,\n" - " java.lang.Object value) {\n" - " return (Builder) super.addRepeatedField(field, value);\n" - "}\n"); - - if (descriptor_->extension_range_count() > 0) { - printer->Print( - "public Builder setExtension(\n" - " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" - " $classname$, Type> extension,\n" - " Type value) {\n" - " return (Builder) super.setExtension(extension, value);\n" + "@java.lang.Override\n" + "public Builder clone() {\n" + " return super.clone();\n" "}\n" - "public Builder setExtension(\n" - " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" - " $classname$, java.util.List> extension,\n" - " int index, Type value) {\n" - " return (Builder) super.setExtension(extension, index, value);\n" + "@java.lang.Override\n" + "public Builder setField(\n" + " com.google.protobuf.Descriptors.FieldDescriptor field,\n" + " java.lang.Object value) {\n" + " return super.setField(field, value);\n" "}\n" - "public Builder addExtension(\n" - " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" - " $classname$, java.util.List> extension,\n" - " Type value) {\n" - " return (Builder) super.addExtension(extension, value);\n" + "@java.lang.Override\n" + "public Builder clearField(\n" + " com.google.protobuf.Descriptors.FieldDescriptor field) {\n" + " return super.clearField(field);\n" "}\n" - "public Builder clearExtension(\n" - " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" - " $classname$, ?> extension) {\n" - " return (Builder) super.clearExtension(extension);\n" - "}\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "@java.lang.Override\n" + "public Builder clearOneof(\n" + " com.google.protobuf.Descriptors.OneofDescriptor oneof) {\n" + " return super.clearOneof(oneof);\n" + "}\n" + "@java.lang.Override\n" + "public Builder setRepeatedField(\n" + " com.google.protobuf.Descriptors.FieldDescriptor field,\n" + " int index, java.lang.Object value) {\n" + " return super.setRepeatedField(field, index, value);\n" + "}\n" + "@java.lang.Override\n" + "public Builder addRepeatedField(\n" + " com.google.protobuf.Descriptors.FieldDescriptor field,\n" + " java.lang.Object value) {\n" + " return super.addRepeatedField(field, value);\n" + "}\n"); + + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "@java.lang.Override\n" + "public Builder setExtension(\n" + " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " $classname$, Type> extension,\n" + " Type value) {\n" + " return super.setExtension(extension, value);\n" + "}\n" + "@java.lang.Override\n" + "public Builder setExtension(\n" + " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " $classname$, java.util.List> extension,\n" + " int index, Type value) {\n" + " return super.setExtension(extension, index, value);\n" + "}\n" + "@java.lang.Override\n" + "public Builder addExtension(\n" + " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " $classname$, java.util.List> extension,\n" + " Type value) {\n" + " return super.addExtension(extension, value);\n" + "}\n" + "@java.lang.Override\n" + "public Builder clearExtension(\n" + " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " $classname$, ?> extension) {\n" + " return super.clearExtension(extension);\n" + "}\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } // ----------------------------------------------------------------- if (context_->HasGeneratedMethods(descriptor_)) { printer->Print( - "public Builder mergeFrom(com.google.protobuf.Message other) {\n" - " if (other instanceof $classname$) {\n" - " return mergeFrom(($classname$)other);\n" - " } else {\n" - " super.mergeFrom(other);\n" - " return this;\n" - " }\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "@java.lang.Override\n" + "public Builder mergeFrom(com.google.protobuf.Message other) {\n" + " if (other instanceof $classname$) {\n" + " return mergeFrom(($classname$)other);\n" + " } else {\n" + " super.mergeFrom(other);\n" + " return this;\n" + " }\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Print( - "public Builder mergeFrom($classname$ other) {\n" - // Optimization: If other is the default instance, we know none of its - // fields are set so we can skip the merge. - " if (other == $classname$.getDefaultInstance()) return this;\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "public Builder mergeFrom($classname$ other) {\n" + // Optimization: If other is the default instance, we know none of its + // fields are set so we can skip the merge. + " if (other == $classname$.getDefaultInstance()) return this;\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - field_generators_.get( - descriptor_->field(i)).GenerateMergingCode(printer); + if (!IsRealOneof(descriptor_->field(i))) { + field_generators_.get(descriptor_->field(i)) + .GenerateMergingCode(printer); } } // Merge oneof fields. - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - printer->Print( - "switch (other.get$oneof_capitalized_name$Case()) {\n", - "oneof_capitalized_name", - context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name); + for (auto oneof : oneofs_) { + printer->Print("switch (other.get$oneof_capitalized_name$Case()) {\n", + "oneof_capitalized_name", + context_->GetOneofGeneratorInfo(oneof)->capitalized_name); printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case $field_name$: {\n", - "field_name", - ToUpper(field->name())); + for (int j = 0; j < oneof->field_count(); j++) { + const FieldDescriptor* field = oneof->field(j); + printer->Print("case $field_name$: {\n", "field_name", + ToUpper(field->name())); printer->Indent(); field_generators_.get(field).GenerateMergingCode(printer); - printer->Print( - "break;\n"); + printer->Print("break;\n"); printer->Outdent(); - printer->Print( - "}\n"); + printer->Print("}\n"); } printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" - " break;\n" - "}\n", - "cap_oneof_name", - ToUpper(context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name)); + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(context_->GetOneofGeneratorInfo(oneof)->name)); printer->Outdent(); - printer->Print( - "}\n"); + printer->Print("}\n"); } printer->Outdent(); // if message type has extensions if (descriptor_->extension_range_count() > 0) { - printer->Print( - " this.mergeExtensionFields(other);\n"); + printer->Print(" this.mergeExtensionFields(other);\n"); } - printer->Print( - " this.mergeUnknownFields(other.unknownFields);\n"); + printer->Print(" this.mergeUnknownFields(other.unknownFields);\n"); - printer->Print( - " onChanged();\n"); + printer->Print(" onChanged();\n"); printer->Print( - " return this;\n" - "}\n" - "\n"); + " return this;\n" + "}\n" + "\n"); } } // =================================================================== -void MessageBuilderGenerator:: -GenerateBuilderParsingMethods(io::Printer* printer) { +void MessageBuilderGenerator::GenerateBuilderParsingMethods( + io::Printer* printer) { printer->Print( - "public Builder mergeFrom(\n" - " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws java.io.IOException {\n" - " $classname$ parsedMessage = null;\n" - " try {\n" - " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n" - " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " parsedMessage = ($classname$) e.getUnfinishedMessage();\n" - " throw e.unwrapIOException();\n" - " } finally {\n" - " if (parsedMessage != null) {\n" - " mergeFrom(parsedMessage);\n" - " }\n" - " }\n" - " return this;\n" - "}\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "@java.lang.Override\n" + "public Builder mergeFrom(\n" + " com.google.protobuf.CodedInputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " $classname$ parsedMessage = null;\n" + " try {\n" + " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n" + " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" + " parsedMessage = ($classname$) e.getUnfinishedMessage();\n" + " throw e.unwrapIOException();\n" + " } finally {\n" + " if (parsedMessage != null) {\n" + " mergeFrom(parsedMessage);\n" + " }\n" + " }\n" + " return this;\n" + "}\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } // =================================================================== -void MessageBuilderGenerator::GenerateIsInitialized( - io::Printer* printer) { +void MessageBuilderGenerator::GenerateIsInitialized(io::Printer* printer) { printer->Print( - "public final boolean isInitialized() {\n"); + "@java.lang.Override\n" + "public final boolean isInitialized() {\n"); printer->Indent(); // Check that all required fields in this message are set. @@ -639,10 +629,10 @@ void MessageBuilderGenerator::GenerateIsInitialized( if (field->is_required()) { printer->Print( - "if (!has$name$()) {\n" - " return false;\n" - "}\n", - "name", info->capitalized_name); + "if (!has$name$()) {\n" + " return false;\n" + "}\n", + "name", info->capitalized_name); } } @@ -655,56 +645,44 @@ void MessageBuilderGenerator::GenerateIsInitialized( switch (field->label()) { case FieldDescriptor::LABEL_REQUIRED: printer->Print( - "if (!get$name$().isInitialized()) {\n" - " return false;\n" - "}\n", - "type", name_resolver_->GetImmutableClassName( - field->message_type()), - "name", info->capitalized_name); + "if (!get$name$().isInitialized()) {\n" + " return false;\n" + "}\n", + "type", + name_resolver_->GetImmutableClassName(field->message_type()), + "name", info->capitalized_name); break; case FieldDescriptor::LABEL_OPTIONAL: - if (!SupportFieldPresence(descriptor_->file()) && - field->containing_oneof() != NULL) { - const OneofDescriptor* oneof = field->containing_oneof(); - const OneofGeneratorInfo* oneof_info = - context_->GetOneofGeneratorInfo(oneof); - printer->Print( - "if ($oneof_name$Case_ == $field_number$) {\n", - "oneof_name", oneof_info->name, - "field_number", SimpleItoa(field->number())); - } else { - printer->Print( - "if (has$name$()) {\n", - "name", info->capitalized_name); - } printer->Print( - " if (!get$name$().isInitialized()) {\n" - " return false;\n" - " }\n" - "}\n", - "name", info->capitalized_name); - break; - case FieldDescriptor::LABEL_REPEATED: - if (IsMapEntry(field->message_type())) { - printer->Print( - "for ($type$ item : get$name$Map().values()) {\n" - " if (!item.isInitialized()) {\n" + "if (has$name$()) {\n" + " if (!get$name$().isInitialized()) {\n" " return false;\n" " }\n" "}\n", - "type", MapValueImmutableClassdName(field->message_type(), - name_resolver_), "name", info->capitalized_name); + break; + case FieldDescriptor::LABEL_REPEATED: + if (IsMapEntry(field->message_type())) { + printer->Print( + "for ($type$ item : get$name$Map().values()) {\n" + " if (!item.isInitialized()) {\n" + " return false;\n" + " }\n" + "}\n", + "type", + MapValueImmutableClassdName(field->message_type(), + name_resolver_), + "name", info->capitalized_name); } else { printer->Print( - "for (int i = 0; i < get$name$Count(); i++) {\n" - " if (!get$name$(i).isInitialized()) {\n" - " return false;\n" - " }\n" - "}\n", - "type", name_resolver_->GetImmutableClassName( - field->message_type()), - "name", info->capitalized_name); + "for (int i = 0; i < get$name$Count(); i++) {\n" + " if (!get$name$(i).isInitialized()) {\n" + " return false;\n" + " }\n" + "}\n", + "type", + name_resolver_->GetImmutableClassName(field->message_type()), + "name", info->capitalized_name); } break; } @@ -713,17 +691,17 @@ void MessageBuilderGenerator::GenerateIsInitialized( if (descriptor_->extension_range_count() > 0) { printer->Print( - "if (!extensionsAreInitialized()) {\n" - " return false;\n" - "}\n"); + "if (!extensionsAreInitialized()) {\n" + " return false;\n" + "}\n"); } printer->Outdent(); printer->Print( - " return true;\n" - "}\n" - "\n"); + " return true;\n" + "}\n" + "\n"); } // =================================================================== diff --git a/src/google/protobuf/compiler/java/java_message_builder.h b/src/google/protobuf/compiler/java/java_message_builder.h index 015ea06206c96..fcd73b3436269 100644 --- a/src/google/protobuf/compiler/java/java_message_builder.h +++ b/src/google/protobuf/compiler/java/java_message_builder.h @@ -35,23 +35,25 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__ -#include #include +#include #include namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -74,6 +76,7 @@ class MessageBuilderGenerator { Context* context_; ClassNameResolver* name_resolver_; FieldGeneratorMap field_generators_; + std::set oneofs_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderGenerator); }; @@ -81,6 +84,6 @@ class MessageBuilderGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__ diff --git a/src/google/protobuf/compiler/java/java_message_builder_lite.cc b/src/google/protobuf/compiler/java/java_message_builder_lite.cc index 1ad58c09ce3d2..7b69a9ab3894e 100644 --- a/src/google/protobuf/compiler/java/java_message_builder_lite.cc +++ b/src/google/protobuf/compiler/java/java_message_builder_lite.cc @@ -35,12 +35,8 @@ #include #include -#include #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include @@ -50,9 +46,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -62,90 +58,73 @@ namespace protobuf { namespace compiler { namespace java { -namespace { -bool GenerateHasBits(const Descriptor* descriptor) { - return SupportFieldPresence(descriptor->file()) || - HasRepeatedFields(descriptor); -} -} // namespace - MessageBuilderLiteGenerator::MessageBuilderLiteGenerator( const Descriptor* descriptor, Context* context) - : descriptor_(descriptor), context_(context), - name_resolver_(context->GetNameResolver()), - field_generators_(descriptor, context_) { + : descriptor_(descriptor), + context_(context), + name_resolver_(context->GetNameResolver()), + field_generators_(descriptor, context_) { GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite())) << "Generator factory error: A lite message generator is used to " "generate non-lite messages."; + for (int i = 0; i < descriptor_->field_count(); i++) { + if (IsRealOneof(descriptor_->field(i))) { + oneofs_.insert(descriptor_->field(i)->containing_oneof()); + } + } } MessageBuilderLiteGenerator::~MessageBuilderLiteGenerator() {} -void MessageBuilderLiteGenerator:: -Generate(io::Printer* printer) { +void MessageBuilderLiteGenerator::Generate(io::Printer* printer) { WriteMessageDocComment(printer, descriptor_); printer->Print( - "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessageLite.$extendible$Builder<\n" - " $classname$, Builder> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_), - "extendible", - descriptor_->extension_range_count() > 0 ? "Extendable" : ""); + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessageLite.$extendible$Builder<\n" + " $classname$, Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_), "extendible", + descriptor_->extension_range_count() > 0 ? "Extendable" : ""); printer->Indent(); GenerateCommonBuilderMethods(printer); // oneof - std::map vars; - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - vars["oneof_name"] = context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name; - vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name; - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + std::map vars; + for (auto oneof : oneofs_) { + vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name; + vars["oneof_capitalized_name"] = + context_->GetOneofGeneratorInfo(oneof)->capitalized_name; + vars["oneof_index"] = StrCat(oneof->index()); // oneofCase() and clearOneof() printer->Print(vars, - "public $oneof_capitalized_name$Case\n" - " get$oneof_capitalized_name$Case() {\n" - " return instance.get$oneof_capitalized_name$Case();\n" - "}\n" - "\n" - "public Builder clear$oneof_capitalized_name$() {\n" - " copyOnWrite();\n" - " instance.clear$oneof_capitalized_name$();\n" - " return this;\n" - "}\n" - "\n"); - } - - if (GenerateHasBits(descriptor_)) { - // Integers for bit fields. - int totalBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - totalBits += field_generators_.get(descriptor_->field(i)) - .GetNumBitsForBuilder(); - } - int totalInts = (totalBits + 31) / 32; - for (int i = 0; i < totalInts; i++) { - printer->Print("private int $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } + "@java.lang.Override\n" + "public $oneof_capitalized_name$Case\n" + " get$oneof_capitalized_name$Case() {\n" + " return instance.get$oneof_capitalized_name$Case();\n" + "}\n" + "\n" + "public Builder clear$oneof_capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$oneof_capitalized_name$();\n" + " return this;\n" + "}\n" + "\n"); } for (int i = 0; i < descriptor_->field_count(); i++) { printer->Print("\n"); field_generators_.get(descriptor_->field(i)) - .GenerateBuilderMembers(printer); + .GenerateBuilderMembers(printer); } printer->Print( - "\n" - "// @@protoc_insertion_point(builder_scope:$full_name$)\n", - "full_name", descriptor_->full_name()); + "\n" + "// @@protoc_insertion_point(builder_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); printer->Outdent(); printer->Print("}\n"); @@ -153,15 +132,15 @@ Generate(io::Printer* printer) { // =================================================================== -void MessageBuilderLiteGenerator:: -GenerateCommonBuilderMethods(io::Printer* printer) { +void MessageBuilderLiteGenerator::GenerateCommonBuilderMethods( + io::Printer* printer) { printer->Print( - "// Construct using $classname$.newBuilder()\n" - "private Builder() {\n" - " super(DEFAULT_INSTANCE);\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "// Construct using $classname$.newBuilder()\n" + "private Builder() {\n" + " super(DEFAULT_INSTANCE);\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } // =================================================================== diff --git a/src/google/protobuf/compiler/java/java_message_builder_lite.h b/src/google/protobuf/compiler/java/java_message_builder_lite.h index 8597b2e66f389..3402adf3322bb 100644 --- a/src/google/protobuf/compiler/java/java_message_builder_lite.h +++ b/src/google/protobuf/compiler/java/java_message_builder_lite.h @@ -35,23 +35,25 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__ -#include #include +#include #include namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -59,7 +61,7 @@ namespace java { class MessageBuilderLiteGenerator { public: explicit MessageBuilderLiteGenerator(const Descriptor* descriptor, - Context* context); + Context* context); virtual ~MessageBuilderLiteGenerator(); virtual void Generate(io::Printer* printer); @@ -71,6 +73,7 @@ class MessageBuilderLiteGenerator { Context* context_; ClassNameResolver* name_resolver_; FieldGeneratorMap field_generators_; + std::set oneofs_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderLiteGenerator); }; @@ -78,6 +81,6 @@ class MessageBuilderLiteGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc index baa7f872757ac..f657c17957422 100644 --- a/src/google/protobuf/compiler/java/java_message_field.cc +++ b/src/google/protobuf/compiler/java/java_message_field.cc @@ -36,9 +36,9 @@ #include #include -#include #include #include +#include #include #include #include @@ -49,14 +49,13 @@ namespace protobuf { namespace compiler { namespace java { + namespace { -void SetMessageVariables(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - const FieldGeneratorInfo* info, +void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, - std::map* variables) { + std::map* variables) { SetCommonFieldVariables(descriptor, info, variables); (*variables)["type"] = @@ -64,19 +63,19 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["mutable_type"] = name_resolver->GetMutableClassName(descriptor->message_type()); (*variables)["group_or_message"] = - (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ? - "Group" : "Message"; + (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ? "Group" + : "Message"; // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler - (*variables)["deprecation"] = descriptor->options().deprecated() - ? "@java.lang.Deprecated " : ""; + (*variables)["deprecation"] = + descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; (*variables)["on_changed"] = "onChanged();"; (*variables)["ver"] = GeneratedCodeVersionSuffix(); (*variables)["get_parser"] = - ExposePublicParser(descriptor->message_type()->file()) - ? "PARSER" : "parser()"; + ExposePublicParser(descriptor->message_type()->file()) ? "PARSER" + : "parser()"; - if (SupportFieldPresence(descriptor->file())) { + if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); @@ -99,7 +98,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["name"] + "_ != null"; } - // For repated builders, one bit is used for whether the array is immutable. + // For repeated builders, one bit is used for whether the array is immutable. (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); @@ -121,101 +120,105 @@ void SetMessageVariables(const FieldDescriptor* descriptor, // =================================================================== -ImmutableMessageFieldGenerator:: -ImmutableMessageFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); +ImmutableMessageFieldGenerator::ImmutableMessageFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + Context* context) + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { + SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); } ImmutableMessageFieldGenerator::~ImmutableMessageFieldGenerator() {} int ImmutableMessageFieldGenerator::GetNumBitsForMessage() const { - return 1; + return HasHasbit(descriptor_) ? 1 : 0; } int ImmutableMessageFieldGenerator::GetNumBitsForBuilder() const { - return 1; + return GetNumBitsForMessage(); } -void ImmutableMessageFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { +void ImmutableMessageFieldGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { // TODO(jonp): In the future, consider having a method specific to the // interface so that builders can choose dynamically to either return a // message or a nested builder, so that asking for the interface doesn't // cause a message to ever be built. - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print(variables_, "$deprecation$boolean has$capitalized_name$();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n"); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n"); + printer->Print( + variables_, + "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n"); } -void ImmutableMessageFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private $type$ $name$_;\n"); +void ImmutableMessageFieldGenerator::GenerateMembers( + io::Printer* printer) const { + printer->Print(variables_, "private $type$ $name$_;\n"); PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); + if (HasHasbit(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder " - "${$get$capitalized_name$OrBuilder$}$() {\n" - " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" - "}\n"); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$OrBuilder " + "${$get$capitalized_name$OrBuilder$}$() {\n" + " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } else { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $name$_ != null;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $name$_ != null;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public $type$OrBuilder " - "${$get$capitalized_name$OrBuilder$}$() {\n" - " return get$capitalized_name$();\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$OrBuilder " + "${$get$capitalized_name$OrBuilder$}$() {\n" + " return get$capitalized_name$();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } } void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition( - io::Printer* printer, - const char* regular_case, + io::Printer* printer, const char* regular_case, const char* nested_builder_case) const { printer->Print(variables_, "if ($name$Builder_ == null) {\n"); printer->Indent(); @@ -229,10 +232,8 @@ void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition( } void ImmutableMessageFieldGenerator::PrintNestedBuilderFunction( - io::Printer* printer, - const char* method_prototype, - const char* regular_case, - const char* nested_builder_case, + io::Printer* printer, const char* method_prototype, + const char* regular_case, const char* nested_builder_case, const char* trailing_code) const { printer->Print(variables_, method_prototype); printer->Annotate("{", "}", descriptor_); @@ -246,566 +247,576 @@ void ImmutableMessageFieldGenerator::PrintNestedBuilderFunction( printer->Print("}\n"); } -void ImmutableMessageFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { +void ImmutableMessageFieldGenerator::GenerateBuilderMembers( + io::Printer* printer) const { // When using nested-builders, the code initially works just like the // non-nested builder case. It only creates a nested builder lazily on // demand and then forever delegates to it after creation. - bool support_field_presence = SupportFieldPresence(descriptor_->file()); + bool has_hasbit = HasHasbit(descriptor_); - printer->Print(variables_, - "private $type$ $name$_ = null;\n"); + printer->Print(variables_, "private $type$ $name$_;\n"); printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.SingleFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" - "\n"); + // If this builder is non-null, it is used and the other fields + // are ignored. + "private com.google.protobuf.SingleFieldBuilder$ver$<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" + "\n"); // The comments above the methods below are based on a hypothetical // field of type "Field" called "Field". // boolean hasField() - WriteFieldDocComment(printer, descriptor_); - if (support_field_presence) { - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + if (has_hasbit) { + printer->Print( + variables_, + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } else { - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $name$Builder_ != null || $name$_ != null;\n" - "}\n"); + printer->Print( + variables_, + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $name$Builder_ != null || $name$_ != null;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } // Field getField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public $type$ ${$get$capitalized_name$$}$()", - "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n", - "return $name$Builder_.getMessage();\n", - NULL); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + PrintNestedBuilderFunction( + printer, "$deprecation$public $type$ ${$get$capitalized_name$$}$()", + "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n", + "return $name$Builder_.getMessage();\n", NULL); // Field.Builder setField(Field value) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value)", + PrintNestedBuilderFunction( + printer, + "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value)", - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "$name$_ = value;\n" - "$on_changed$\n", + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "$name$_ = value;\n" + "$on_changed$\n", - "$name$Builder_.setMessage(value);\n", + "$name$Builder_.setMessage(value);\n", - "$set_has_field_bit_builder$\n" - "return this;\n"); + "$set_has_field_bit_builder$\n" + "return this;\n"); // Field.Builder setField(Field.Builder builderForValue) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " $type$.Builder builderForValue)", + PrintNestedBuilderFunction( + printer, + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " $type$.Builder builderForValue)", - "$name$_ = builderForValue.build();\n" - "$on_changed$\n", + "$name$_ = builderForValue.build();\n" + "$on_changed$\n", - "$name$Builder_.setMessage(builderForValue.build());\n", + "$name$Builder_.setMessage(builderForValue.build());\n", - "$set_has_field_bit_builder$\n" - "return this;\n"); + "$set_has_field_bit_builder$\n" + "return this;\n"); // Field.Builder mergeField(Field value) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$merge$capitalized_name$$}$($type$ value)", - - support_field_presence - ? "if ($get_has_field_bit_builder$ &&\n" - " $name$_ != null &&\n" - " $name$_ != $type$.getDefaultInstance()) {\n" - " $name$_ =\n" - " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" - "} else {\n" - " $name$_ = value;\n" - "}\n" - "$on_changed$\n" - : "if ($name$_ != null) {\n" - " $name$_ =\n" - " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" - "} else {\n" - " $name$_ = value;\n" - "}\n" - "$on_changed$\n", - - "$name$Builder_.mergeFrom(value);\n", - - "$set_has_field_bit_builder$\n" - "return this;\n"); + PrintNestedBuilderFunction( + printer, + "$deprecation$public Builder ${$merge$capitalized_name$$}$($type$ value)", + + has_hasbit + ? "if ($get_has_field_bit_builder$ &&\n" + " $name$_ != null &&\n" + " $name$_ != $type$.getDefaultInstance()) {\n" + " $name$_ =\n" + " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" + "} else {\n" + " $name$_ = value;\n" + "}\n" + "$on_changed$\n" + : "if ($name$_ != null) {\n" + " $name$_ =\n" + " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" + "} else {\n" + " $name$_ = value;\n" + "}\n" + "$on_changed$\n", + + "$name$Builder_.mergeFrom(value);\n", + + "$set_has_field_bit_builder$\n" + "return this;\n"); // Field.Builder clearField() WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$clear$capitalized_name$$}$()", + PrintNestedBuilderFunction( + printer, "$deprecation$public Builder ${$clear$capitalized_name$$}$()", - "$name$_ = null;\n" - "$on_changed$\n", + "$name$_ = null;\n" + "$on_changed$\n", - support_field_presence - ? "$name$Builder_.clear();\n" - : "$name$_ = null;\n" - "$name$Builder_ = null;\n", + has_hasbit ? "$name$Builder_.clear();\n" + : "$name$_ = null;\n" + "$name$Builder_ = null;\n", - "$clear_has_field_bit_builder$\n" - "return this;\n"); + "$clear_has_field_bit_builder$\n" + "return this;\n"); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public $type$.Builder " - "${$get$capitalized_name$Builder$}$() {\n" - " $set_has_field_bit_builder$\n" - " $on_changed$\n" - " return get$capitalized_name$FieldBuilder().getBuilder();\n" - "}\n"); + "$deprecation$public $type$.Builder " + "${$get$capitalized_name$Builder$}$() {\n" + " $set_has_field_bit_builder$\n" + " $on_changed$\n" + " return get$capitalized_name$FieldBuilder().getBuilder();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public $type$OrBuilder " - "${$get$capitalized_name$OrBuilder$}$() {\n" - " if ($name$Builder_ != null) {\n" - " return $name$Builder_.getMessageOrBuilder();\n" - " } else {\n" - " return $name$_ == null ?\n" - " $type$.getDefaultInstance() : $name$_;\n" - " }\n" - "}\n"); + "$deprecation$public $type$OrBuilder " + "${$get$capitalized_name$OrBuilder$}$() {\n" + " if ($name$Builder_ != null) {\n" + " return $name$Builder_.getMessageOrBuilder();\n" + " } else {\n" + " return $name$_ == null ?\n" + " $type$.getDefaultInstance() : $name$_;\n" + " }\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private com.google.protobuf.SingleFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " get$capitalized_name$(),\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); + printer->Print( + variables_, + "private com.google.protobuf.SingleFieldBuilder$ver$<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder$ver$<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " get$capitalized_name$(),\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); } -void ImmutableMessageFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "get$capitalized_name$FieldBuilder();\n"); +void ImmutableMessageFieldGenerator::GenerateFieldBuilderInitializationCode( + io::Printer* printer) const { + if (HasHasbit(descriptor_)) { + printer->Print(variables_, "get$capitalized_name$FieldBuilder();\n"); } } +void ImmutableMessageFieldGenerator::GenerateInitializationCode( + io::Printer* printer) const {} -void ImmutableMessageFieldGenerator:: -GenerateInitializationCode(io::Printer* printer) const {} - -void ImmutableMessageFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - PrintNestedBuilderCondition(printer, - "$name$_ = null;\n", +void ImmutableMessageFieldGenerator::GenerateBuilderClearCode( + io::Printer* printer) const { + if (HasHasbit(descriptor_)) { + PrintNestedBuilderCondition(printer, "$name$_ = null;\n", - "$name$Builder_.clear();\n"); + "$name$Builder_.clear();\n"); printer->Print(variables_, "$clear_has_field_bit_builder$\n"); } else { - PrintNestedBuilderCondition(printer, - "$name$_ = null;\n", + PrintNestedBuilderCondition(printer, "$name$_ = null;\n", - "$name$_ = null;\n" - "$name$Builder_ = null;\n"); + "$name$_ = null;\n" + "$name$Builder_ = null;\n"); } } -void ImmutableMessageFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { +void ImmutableMessageFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " merge$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + "if (other.has$capitalized_name$()) {\n" + " merge$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); } -void ImmutableMessageFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { +void ImmutableMessageFieldGenerator::GenerateBuildingCode( + io::Printer* printer) const { + if (HasHasbit(descriptor_)) { + printer->Print(variables_, "if ($get_has_field_bit_from_local$) {\n"); + printer->Indent(); + PrintNestedBuilderCondition(printer, "result.$name$_ = $name$_;\n", + "result.$name$_ = $name$Builder_.build();\n"); + printer->Outdent(); printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); + " $set_has_field_bit_to_local$;\n" + "}\n"); + } else { + PrintNestedBuilderCondition(printer, "result.$name$_ = $name$_;\n", + "result.$name$_ = $name$Builder_.build();\n"); } - - PrintNestedBuilderCondition(printer, - "result.$name$_ = $name$_;\n", - - "result.$name$_ = $name$Builder_.build();\n"); } -void ImmutableMessageFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +void ImmutableMessageFieldGenerator::GenerateParsingCode( + io::Printer* printer) const { printer->Print(variables_, - "$type$.Builder subBuilder = null;\n" - "if ($is_field_present_message$) {\n" - " subBuilder = $name$_.toBuilder();\n" - "}\n"); + "$type$.Builder subBuilder = null;\n" + "if ($is_field_present_message$) {\n" + " subBuilder = $name$_.toBuilder();\n" + "}\n"); if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, - "$name$_ = input.readGroup($number$, $type$.$get_parser$,\n" - " extensionRegistry);\n"); + "$name$_ = input.readGroup($number$, $type$.$get_parser$,\n" + " extensionRegistry);\n"); } else { printer->Print(variables_, - "$name$_ = input.readMessage($type$.$get_parser$, extensionRegistry);\n"); + "$name$_ = input.readMessage($type$.$get_parser$, " + "extensionRegistry);\n"); } printer->Print(variables_, - "if (subBuilder != null) {\n" - " subBuilder.mergeFrom($name$_);\n" - " $name$_ = subBuilder.buildPartial();\n" - "}\n" - "$set_has_field_bit_message$\n"); + "if (subBuilder != null) {\n" + " subBuilder.mergeFrom($name$_);\n" + " $name$_ = subBuilder.buildPartial();\n" + "}\n" + "$set_has_field_bit_message$\n"); } -void ImmutableMessageFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { +void ImmutableMessageFieldGenerator::GenerateParsingDoneCode( + io::Printer* printer) const { // noop for messages. } -void ImmutableMessageFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " output.write$group_or_message$($number$, get$capitalized_name$());\n" - "}\n"); +void ImmutableMessageFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { + printer->Print( + variables_, + "if ($is_field_present_message$) {\n" + " output.write$group_or_message$($number$, get$capitalized_name$());\n" + "}\n"); } -void ImmutableMessageFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .compute$group_or_message$Size($number$, get$capitalized_name$());\n" - "}\n"); +void ImmutableMessageFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { + printer->Print( + variables_, + "if ($is_field_present_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$group_or_message$Size($number$, get$capitalized_name$());\n" + "}\n"); } -void ImmutableMessageFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { +void ImmutableMessageFieldGenerator::GenerateEqualsCode( + io::Printer* printer) const { printer->Print(variables_, - "result = result && get$capitalized_name$()\n" - " .equals(other.get$capitalized_name$());\n"); + "if (!get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$())) return false;\n"); } -void ImmutableMessageFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { +void ImmutableMessageFieldGenerator::GenerateHashCode( + io::Printer* printer) const { printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n" - "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); + "hash = (37 * hash) + $constant_name$;\n" + "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); } -string ImmutableMessageFieldGenerator::GetBoxedType() const { +std::string ImmutableMessageFieldGenerator::GetBoxedType() const { return name_resolver_->GetImmutableClassName(descriptor_->message_type()); } // =================================================================== -ImmutableMessageOneofFieldGenerator:: -ImmutableMessageOneofFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableMessageFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { +ImmutableMessageOneofFieldGenerator::ImmutableMessageOneofFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + Context* context) + : ImmutableMessageFieldGenerator(descriptor, messageBitIndex, + builderBitIndex, context) { const OneofGeneratorInfo* info = context->GetOneofGeneratorInfo(descriptor->containing_oneof()); SetCommonOneofVariables(descriptor, info, &variables_); } -ImmutableMessageOneofFieldGenerator:: -~ImmutableMessageOneofFieldGenerator() {} +ImmutableMessageOneofFieldGenerator::~ImmutableMessageOneofFieldGenerator() {} -void ImmutableMessageOneofFieldGenerator:: -GenerateMembers(io::Printer* printer) const { +void ImmutableMessageOneofFieldGenerator::GenerateMembers( + io::Printer* printer) const { PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) $oneof_name$_;\n" - " }\n" - " return $type$.getDefaultInstance();\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $type$.getDefaultInstance();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public $type$OrBuilder " - "${$get$capitalized_name$OrBuilder$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) $oneof_name$_;\n" - " }\n" - " return $type$.getDefaultInstance();\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$OrBuilder " + "${$get$capitalized_name$OrBuilder$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $type$.getDefaultInstance();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutableMessageOneofFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { +void ImmutableMessageOneofFieldGenerator::GenerateBuilderMembers( + io::Printer* printer) const { // When using nested-builders, the code initially works just like the // non-nested builder case. It only creates a nested builder lazily on // demand and then forever delegates to it after creation. printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.SingleFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" - "\n"); + // If this builder is non-null, it is used and the other fields + // are ignored. + "private com.google.protobuf.SingleFieldBuilder$ver$<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" + "\n"); // The comments above the methods below are based on a hypothetical // field of type "Field" called "Field". // boolean hasField() - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Field getField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public $type$ ${$get$capitalized_name$$}$()", + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + PrintNestedBuilderFunction( + printer, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$()", - "if ($has_oneof_case_message$) {\n" - " return ($type$) $oneof_name$_;\n" - "}\n" - "return $type$.getDefaultInstance();\n", + "if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + "}\n" + "return $type$.getDefaultInstance();\n", - "if ($has_oneof_case_message$) {\n" - " return $name$Builder_.getMessage();\n" - "}\n" - "return $type$.getDefaultInstance();\n", + "if ($has_oneof_case_message$) {\n" + " return $name$Builder_.getMessage();\n" + "}\n" + "return $type$.getDefaultInstance();\n", - NULL); + NULL); // Field.Builder setField(Field value) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value)", + PrintNestedBuilderFunction( + printer, + "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value)", - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "$oneof_name$_ = value;\n" - "$on_changed$\n", + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "$oneof_name$_ = value;\n" + "$on_changed$\n", - "$name$Builder_.setMessage(value);\n", + "$name$Builder_.setMessage(value);\n", - "$set_oneof_case_message$;\n" - "return this;\n"); + "$set_oneof_case_message$;\n" + "return this;\n"); // Field.Builder setField(Field.Builder builderForValue) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " $type$.Builder builderForValue)", + PrintNestedBuilderFunction( + printer, + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " $type$.Builder builderForValue)", - "$oneof_name$_ = builderForValue.build();\n" - "$on_changed$\n", + "$oneof_name$_ = builderForValue.build();\n" + "$on_changed$\n", - "$name$Builder_.setMessage(builderForValue.build());\n", + "$name$Builder_.setMessage(builderForValue.build());\n", - "$set_oneof_case_message$;\n" - "return this;\n"); + "$set_oneof_case_message$;\n" + "return this;\n"); // Field.Builder mergeField(Field value) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$merge$capitalized_name$$}$($type$ value)", - - "if ($has_oneof_case_message$ &&\n" - " $oneof_name$_ != $type$.getDefaultInstance()) {\n" - " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n" - " .mergeFrom(value).buildPartial();\n" - "} else {\n" - " $oneof_name$_ = value;\n" - "}\n" - "$on_changed$\n", - - "if ($has_oneof_case_message$) {\n" - " $name$Builder_.mergeFrom(value);\n" - "}\n" - "$name$Builder_.setMessage(value);\n", - - "$set_oneof_case_message$;\n" - "return this;\n"); + PrintNestedBuilderFunction( + printer, + "$deprecation$public Builder ${$merge$capitalized_name$$}$($type$ value)", + + "if ($has_oneof_case_message$ &&\n" + " $oneof_name$_ != $type$.getDefaultInstance()) {\n" + " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n" + " .mergeFrom(value).buildPartial();\n" + "} else {\n" + " $oneof_name$_ = value;\n" + "}\n" + "$on_changed$\n", + + "if ($has_oneof_case_message$) {\n" + " $name$Builder_.mergeFrom(value);\n" + "}\n" + "$name$Builder_.setMessage(value);\n", + + "$set_oneof_case_message$;\n" + "return this;\n"); // Field.Builder clearField() WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$clear$capitalized_name$$}$()", + PrintNestedBuilderFunction( + printer, "$deprecation$public Builder ${$clear$capitalized_name$$}$()", - "if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " $on_changed$\n" - "}\n", + "if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " $on_changed$\n" + "}\n", - "if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - "}\n" - "$name$Builder_.clear();\n", + "if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + "}\n" + "$name$Builder_.clear();\n", - "return this;\n"); + "return this;\n"); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public $type$.Builder " - "${$get$capitalized_name$Builder$}$() {\n" - " return get$capitalized_name$FieldBuilder().getBuilder();\n" - "}\n"); + "$deprecation$public $type$.Builder " + "${$get$capitalized_name$Builder$}$() {\n" + " return get$capitalized_name$FieldBuilder().getBuilder();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder " - "${$get$capitalized_name$OrBuilder$}$() {\n" - " if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n" - " return $name$Builder_.getMessageOrBuilder();\n" - " } else {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) $oneof_name$_;\n" - " }\n" - " return $type$.getDefaultInstance();\n" - " }\n" - "}\n"); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$OrBuilder " + "${$get$capitalized_name$OrBuilder$}$() {\n" + " if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n" + " return $name$Builder_.getMessageOrBuilder();\n" + " } else {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $type$.getDefaultInstance();\n" + " }\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private com.google.protobuf.SingleFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " ${$get$capitalized_name$FieldBuilder$}$() {\n" - " if ($name$Builder_ == null) {\n" - " if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = $type$.getDefaultInstance();\n" - " }\n" - " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " ($type$) $oneof_name$_,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $oneof_name$_ = null;\n" - " }\n" - " $set_oneof_case_message$;\n" - " $on_changed$;\n" - " return $name$Builder_;\n" - "}\n"); + printer->Print( + variables_, + "private com.google.protobuf.SingleFieldBuilder$ver$<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " ${$get$capitalized_name$FieldBuilder$}$() {\n" + " if ($name$Builder_ == null) {\n" + " if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = $type$.getDefaultInstance();\n" + " }\n" + " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder$ver$<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " ($type$) $oneof_name$_,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $oneof_name$_ = null;\n" + " }\n" + " $set_oneof_case_message$;\n" + " $on_changed$;\n" + " return $name$Builder_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutableMessageOneofFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n"); +void ImmutableMessageOneofFieldGenerator::GenerateBuildingCode( + io::Printer* printer) const { + printer->Print(variables_, "if ($has_oneof_case_message$) {\n"); printer->Indent(); - PrintNestedBuilderCondition(printer, - "result.$oneof_name$_ = $oneof_name$_;\n", + PrintNestedBuilderCondition( + printer, "result.$oneof_name$_ = $oneof_name$_;\n", - "result.$oneof_name$_ = $name$Builder_.build();\n"); + "result.$oneof_name$_ = $name$Builder_.build();\n"); printer->Outdent(); printer->Print("}\n"); } -void ImmutableMessageOneofFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { +void ImmutableMessageOneofFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { printer->Print(variables_, - "merge$capitalized_name$(other.get$capitalized_name$());\n"); + "merge$capitalized_name$(other.get$capitalized_name$());\n"); } -void ImmutableMessageOneofFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +void ImmutableMessageOneofFieldGenerator::GenerateParsingCode( + io::Printer* printer) const { printer->Print(variables_, - "$type$.Builder subBuilder = null;\n" - "if ($has_oneof_case_message$) {\n" - " subBuilder = (($type$) $oneof_name$_).toBuilder();\n" - "}\n"); + "$type$.Builder subBuilder = null;\n" + "if ($has_oneof_case_message$) {\n" + " subBuilder = (($type$) $oneof_name$_).toBuilder();\n" + "}\n"); if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { - printer->Print(variables_, - "$oneof_name$_ = input.readGroup($number$, $type$.$get_parser$,\n" - " extensionRegistry);\n"); + printer->Print( + variables_, + "$oneof_name$_ = input.readGroup($number$, $type$.$get_parser$,\n" + " extensionRegistry);\n"); } else { - printer->Print(variables_, - "$oneof_name$_ =\n" - " input.readMessage($type$.$get_parser$, extensionRegistry);\n"); + printer->Print( + variables_, + "$oneof_name$_ =\n" + " input.readMessage($type$.$get_parser$, extensionRegistry);\n"); } printer->Print(variables_, - "if (subBuilder != null) {\n" - " subBuilder.mergeFrom(($type$) $oneof_name$_);\n" - " $oneof_name$_ = subBuilder.buildPartial();\n" - "}\n"); - printer->Print(variables_, - "$set_oneof_case_message$;\n"); + "if (subBuilder != null) {\n" + " subBuilder.mergeFrom(($type$) $oneof_name$_);\n" + " $oneof_name$_ = subBuilder.buildPartial();\n" + "}\n"); + printer->Print(variables_, "$set_oneof_case_message$;\n"); } -void ImmutableMessageOneofFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n" - "}\n"); +void ImmutableMessageOneofFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { + printer->Print( + variables_, + "if ($has_oneof_case_message$) {\n" + " output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n" + "}\n"); } -void ImmutableMessageOneofFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .compute$group_or_message$Size($number$, ($type$) $oneof_name$_);\n" - "}\n"); +void ImmutableMessageOneofFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { + printer->Print( + variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$group_or_message$Size($number$, ($type$) $oneof_name$_);\n" + "}\n"); } // =================================================================== -RepeatedImmutableMessageFieldGenerator:: -RepeatedImmutableMessageFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { +RepeatedImmutableMessageFieldGenerator::RepeatedImmutableMessageFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + Context* context) + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); } RepeatedImmutableMessageFieldGenerator:: -~RepeatedImmutableMessageFieldGenerator() {} + ~RepeatedImmutableMessageFieldGenerator() {} int RepeatedImmutableMessageFieldGenerator::GetNumBitsForMessage() const { return 0; @@ -815,78 +826,84 @@ int RepeatedImmutableMessageFieldGenerator::GetNumBitsForBuilder() const { return 1; } -void RepeatedImmutableMessageFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { +void RepeatedImmutableMessageFieldGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { // TODO(jonp): In the future, consider having methods specific to the // interface so that builders can choose dynamically to either return a // message or a nested builder, so that asking for the interface doesn't // cause a message to ever be built. WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$java.util.List<$type$> \n" - " get$capitalized_name$List();\n"); + "$deprecation$java.util.List<$type$> \n" + " get$capitalized_name$List();\n"); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$(int index);\n"); + "$deprecation$$type$ get$capitalized_name$(int index);\n"); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); + "$deprecation$int get$capitalized_name$Count();\n"); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$java.util.List \n" - " get$capitalized_name$OrBuilderList();\n"); + "$deprecation$java.util.List \n" + " get$capitalized_name$OrBuilderList();\n"); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index);\n"); + printer->Print( + variables_, + "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index);\n"); } -void RepeatedImmutableMessageFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private java.util.List<$type$> $name$_;\n"); +void RepeatedImmutableMessageFieldGenerator::GenerateMembers( + io::Printer* printer) const { + printer->Print(variables_, "private java.util.List<$type$> $name$_;\n"); PrintExtraFieldInfo(variables_, printer); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public java.util.List<$type$> " - "${$get$capitalized_name$List$}$() {\n" - " return $name$_;\n" // note: unmodifiable list - "}\n"); + "@java.lang.Override\n" + "$deprecation$public java.util.List<$type$> " + "${$get$capitalized_name$List$}$() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List \n" - " ${$get$capitalized_name$OrBuilderList$}$() {\n" - " return $name$_;\n" - "}\n"); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public java.util.List \n" + " ${$get$capitalized_name$OrBuilderList$}$() {\n" + " return $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return $name$_.size();\n" - "}\n"); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return $name$_.size();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return $name$_.get(index);\n" - "}\n"); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public $type$OrBuilder " - "${$get$capitalized_name$OrBuilder$}$(\n" - " int index) {\n" - " return $name$_.get(index);\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$OrBuilder " + "${$get$capitalized_name$OrBuilder$}$(\n" + " int index) {\n" + " return $name$_.get(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - } void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderCondition( - io::Printer* printer, - const char* regular_case, + io::Printer* printer, const char* regular_case, const char* nested_builder_case) const { printer->Print(variables_, "if ($name$Builder_ == null) {\n"); printer->Indent(); @@ -900,10 +917,8 @@ void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderCondition( } void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderFunction( - io::Printer* printer, - const char* method_prototype, - const char* regular_case, - const char* nested_builder_case, + io::Printer* printer, const char* method_prototype, + const char* regular_case, const char* nested_builder_case, const char* trailing_code) const { printer->Print(variables_, method_prototype); printer->Annotate("{", "}", descriptor_); @@ -917,409 +932,432 @@ void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderFunction( printer->Print("}\n"); } -void RepeatedImmutableMessageFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { +void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers( + io::Printer* printer) const { // When using nested-builders, the code initially works just like the // non-nested builder case. It only creates a nested builder lazily on // demand and then forever delegates to it after creation. - printer->Print(variables_, - // Used when the builder is null. - // One field is the list and the other field keeps track of whether the - // list is immutable. If it's immutable, the invariant is that it must - // either an instance of Collections.emptyList() or it's an ArrayList - // wrapped in a Collections.unmodifiableList() wrapper and nobody else has - // a refererence to the underlying ArrayList. This invariant allows us to - // share instances of lists between protocol buffers avoiding expensive - // memory allocations. Note, immutable is a strong guarantee here -- not - // just that the list cannot be modified via the reference but that the - // list can never be modified. - "private java.util.List<$type$> $name$_ =\n" - " java.util.Collections.emptyList();\n" - - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$get_mutable_bit_builder$) {\n" - " $name$_ = new java.util.ArrayList<$type$>($name$_);\n" - " $set_mutable_bit_builder$;\n" - " }\n" - "}\n" - "\n"); + printer->Print( + variables_, + // Used when the builder is null. + // One field is the list and the other field keeps track of whether the + // list is immutable. If it's immutable, the invariant is that it must + // either an instance of Collections.emptyList() or it's an ArrayList + // wrapped in a Collections.unmodifiableList() wrapper and nobody else has + // a reference to the underlying ArrayList. This invariant allows us to + // share instances of lists between protocol buffers avoiding expensive + // memory allocations. Note, immutable is a strong guarantee here -- not + // just that the list cannot be modified via the reference but that the + // list can never be modified. + "private java.util.List<$type$> $name$_ =\n" + " java.util.Collections.emptyList();\n" + + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new java.util.ArrayList<$type$>($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n" + "\n"); - printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n" - "\n"); + printer->Print( + variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n" + "\n"); // The comments above the methods below are based on a hypothetical // repeated field of type "Field" called "RepeatedField". // List getRepeatedFieldList() WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public java.util.List<$type$> " - "${$get$capitalized_name$List$}$()", + PrintNestedBuilderFunction( + printer, + "$deprecation$public java.util.List<$type$> " + "${$get$capitalized_name$List$}$()", - "return java.util.Collections.unmodifiableList($name$_);\n", - "return $name$Builder_.getMessageList();\n", + "return java.util.Collections.unmodifiableList($name$_);\n", + "return $name$Builder_.getMessageList();\n", - NULL); + NULL); // int getRepeatedFieldCount() WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public int ${$get$capitalized_name$Count$}$()", + PrintNestedBuilderFunction( + printer, "$deprecation$public int ${$get$capitalized_name$Count$}$()", - "return $name$_.size();\n", - "return $name$Builder_.getCount();\n", + "return $name$_.size();\n", "return $name$Builder_.getCount();\n", - NULL); + NULL); // Field getRepeatedField(int index) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index)", + PrintNestedBuilderFunction( + printer, + "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index)", - "return $name$_.get(index);\n", + "return $name$_.get(index);\n", - "return $name$Builder_.getMessage(index);\n", + "return $name$Builder_.getMessage(index);\n", - NULL); + NULL); // Builder setRepeatedField(int index, Field value) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " int index, $type$ value)", - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.set(index, value);\n" - "$on_changed$\n", - "$name$Builder_.setMessage(index, value);\n", - "return this;\n"); + PrintNestedBuilderFunction( + printer, + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " int index, $type$ value)", + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.set(index, value);\n" + "$on_changed$\n", + "$name$Builder_.setMessage(index, value);\n", "return this;\n"); // Builder setRepeatedField(int index, Field.Builder builderForValue) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " int index, $type$.Builder builderForValue)", + PrintNestedBuilderFunction( + printer, + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " int index, $type$.Builder builderForValue)", - "ensure$capitalized_name$IsMutable();\n" - "$name$_.set(index, builderForValue.build());\n" - "$on_changed$\n", + "ensure$capitalized_name$IsMutable();\n" + "$name$_.set(index, builderForValue.build());\n" + "$on_changed$\n", - "$name$Builder_.setMessage(index, builderForValue.build());\n", + "$name$Builder_.setMessage(index, builderForValue.build());\n", - "return this;\n"); + "return this;\n"); // Builder addRepeatedField(Field value) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value)", + PrintNestedBuilderFunction( + printer, + "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value)", - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(value);\n" + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(value);\n" - "$on_changed$\n", + "$on_changed$\n", - "$name$Builder_.addMessage(value);\n", + "$name$Builder_.addMessage(value);\n", - "return this;\n"); + "return this;\n"); // Builder addRepeatedField(int index, Field value) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" - " int index, $type$ value)", + PrintNestedBuilderFunction( + printer, + "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" + " int index, $type$ value)", - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(index, value);\n" - "$on_changed$\n", + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(index, value);\n" + "$on_changed$\n", - "$name$Builder_.addMessage(index, value);\n", + "$name$Builder_.addMessage(index, value);\n", - "return this;\n"); + "return this;\n"); // Builder addRepeatedField(Field.Builder builderForValue) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" - " $type$.Builder builderForValue)", + PrintNestedBuilderFunction( + printer, + "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" + " $type$.Builder builderForValue)", - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(builderForValue.build());\n" - "$on_changed$\n", + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(builderForValue.build());\n" + "$on_changed$\n", - "$name$Builder_.addMessage(builderForValue.build());\n", + "$name$Builder_.addMessage(builderForValue.build());\n", - "return this;\n"); + "return this;\n"); // Builder addRepeatedField(int index, Field.Builder builderForValue) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" - " int index, $type$.Builder builderForValue)", + PrintNestedBuilderFunction( + printer, + "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" + " int index, $type$.Builder builderForValue)", - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(index, builderForValue.build());\n" - "$on_changed$\n", + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(index, builderForValue.build());\n" + "$on_changed$\n", - "$name$Builder_.addMessage(index, builderForValue.build());\n", + "$name$Builder_.addMessage(index, builderForValue.build());\n", - "return this;\n"); + "return this;\n"); // Builder addAllRepeatedField(Iterable values) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" - " java.lang.Iterable values)", + PrintNestedBuilderFunction( + printer, + "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" + " java.lang.Iterable values)", - "ensure$capitalized_name$IsMutable();\n" - "com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" - " values, $name$_);\n" - "$on_changed$\n", + "ensure$capitalized_name$IsMutable();\n" + "com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" + " values, $name$_);\n" + "$on_changed$\n", - "$name$Builder_.addAllMessages(values);\n", + "$name$Builder_.addAllMessages(values);\n", - "return this;\n"); + "return this;\n"); // Builder clearAllRepeatedField() WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$clear$capitalized_name$$}$()", + PrintNestedBuilderFunction( + printer, "$deprecation$public Builder ${$clear$capitalized_name$$}$()", - "$name$_ = java.util.Collections.emptyList();\n" - "$clear_mutable_bit_builder$;\n" - "$on_changed$\n", + "$name$_ = java.util.Collections.emptyList();\n" + "$clear_mutable_bit_builder$;\n" + "$on_changed$\n", - "$name$Builder_.clear();\n", + "$name$Builder_.clear();\n", - "return this;\n"); + "return this;\n"); // Builder removeRepeatedField(int index) WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder ${$remove$capitalized_name$$}$(int index)", + PrintNestedBuilderFunction( + printer, + "$deprecation$public Builder ${$remove$capitalized_name$$}$(int index)", - "ensure$capitalized_name$IsMutable();\n" - "$name$_.remove(index);\n" - "$on_changed$\n", + "ensure$capitalized_name$IsMutable();\n" + "$name$_.remove(index);\n" + "$on_changed$\n", - "$name$Builder_.remove(index);\n", + "$name$Builder_.remove(index);\n", - "return this;\n"); + "return this;\n"); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder ${$get$capitalized_name$Builder$}$(\n" - " int index) {\n" - " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" - "}\n"); + printer->Print( + variables_, + "$deprecation$public $type$.Builder ${$get$capitalized_name$Builder$}$(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder " - "${$get$capitalized_name$OrBuilder$}$(\n" - " int index) {\n" - " if ($name$Builder_ == null) {\n" - " return $name$_.get(index);" - " } else {\n" - " return $name$Builder_.getMessageOrBuilder(index);\n" - " }\n" - "}\n"); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder " + "${$get$capitalized_name$OrBuilder$}$(\n" + " int index) {\n" + " if ($name$Builder_ == null) {\n" + " return $name$_.get(index);" + " } else {\n" + " return $name$Builder_.getMessageOrBuilder(index);\n" + " }\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List \n" - " ${$get$capitalized_name$OrBuilderList$}$() {\n" - " if ($name$Builder_ != null) {\n" - " return $name$Builder_.getMessageOrBuilderList();\n" - " } else {\n" - " return java.util.Collections.unmodifiableList($name$_);\n" - " }\n" - "}\n"); + printer->Print( + variables_, + "$deprecation$public java.util.List \n" + " ${$get$capitalized_name$OrBuilderList$}$() {\n" + " if ($name$Builder_ != null) {\n" + " return $name$Builder_.getMessageOrBuilderList();\n" + " } else {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" + " }\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder " - "${$add$capitalized_name$Builder$}$() {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" - " $type$.getDefaultInstance());\n" - "}\n"); + printer->Print(variables_, + "$deprecation$public $type$.Builder " + "${$add$capitalized_name$Builder$}$() {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " $type$.getDefaultInstance());\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder ${$add$capitalized_name$Builder$}$(\n" - " int index) {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" - " index, $type$.getDefaultInstance());\n" - "}\n"); + printer->Print( + variables_, + "$deprecation$public $type$.Builder ${$add$capitalized_name$Builder$}$(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " index, $type$.getDefaultInstance());\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$.Builder> \n" - " ${$get$capitalized_name$BuilderList$}$() {\n" - " return get$capitalized_name$FieldBuilder().getBuilderList();\n" - "}\n" - "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " $name$_,\n" - " $get_mutable_bit_builder$,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); + printer->Print( + variables_, + "$deprecation$public java.util.List<$type$.Builder> \n" + " ${$get$capitalized_name$BuilderList$}$() {\n" + " return get$capitalized_name$FieldBuilder().getBuilderList();\n" + "}\n" + "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new " + "com.google.protobuf.RepeatedFieldBuilder$ver$<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " $name$_,\n" + " $get_mutable_bit_builder$,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } void RepeatedImmutableMessageFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - printer->Print(variables_, - "get$capitalized_name$FieldBuilder();\n"); + GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "get$capitalized_name$FieldBuilder();\n"); } -void RepeatedImmutableMessageFieldGenerator:: -GenerateInitializationCode(io::Printer* printer) const { +void RepeatedImmutableMessageFieldGenerator::GenerateInitializationCode( + io::Printer* printer) const { printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); } -void RepeatedImmutableMessageFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { +void RepeatedImmutableMessageFieldGenerator::GenerateBuilderClearCode( + io::Printer* printer) const { PrintNestedBuilderCondition(printer, - "$name$_ = java.util.Collections.emptyList();\n" - "$clear_mutable_bit_builder$;\n", + "$name$_ = java.util.Collections.emptyList();\n" + "$clear_mutable_bit_builder$;\n", - "$name$Builder_.clear();\n"); + "$name$Builder_.clear();\n"); } -void RepeatedImmutableMessageFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { +void RepeatedImmutableMessageFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { // The code below does two optimizations (non-nested builder case): // 1. If the other list is empty, there's nothing to do. This ensures we // don't allocate a new array if we already have an immutable one. // 2. If the other list is non-empty and our current list is empty, we can // reuse the other list which is guaranteed to be immutable. - PrintNestedBuilderCondition(printer, - "if (!other.$name$_.isEmpty()) {\n" - " if ($name$_.isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " $clear_mutable_bit_builder$;\n" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" - " }\n" - " $on_changed$\n" - "}\n", - - "if (!other.$name$_.isEmpty()) {\n" - " if ($name$Builder_.isEmpty()) {\n" - " $name$Builder_.dispose();\n" - " $name$Builder_ = null;\n" - " $name$_ = other.$name$_;\n" - " $clear_mutable_bit_builder$;\n" - " $name$Builder_ = \n" - " com.google.protobuf.GeneratedMessage$ver$.alwaysUseFieldBuilders ?\n" - " get$capitalized_name$FieldBuilder() : null;\n" - " } else {\n" - " $name$Builder_.addAllMessages(other.$name$_);\n" - " }\n" - "}\n"); + PrintNestedBuilderCondition( + printer, + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n", + + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$Builder_.isEmpty()) {\n" + " $name$Builder_.dispose();\n" + " $name$Builder_ = null;\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " $name$Builder_ = \n" + " com.google.protobuf.GeneratedMessage$ver$.alwaysUseFieldBuilders " + "?\n" + " get$capitalized_name$FieldBuilder() : null;\n" + " } else {\n" + " $name$Builder_.addAllMessages(other.$name$_);\n" + " }\n" + "}\n"); } -void RepeatedImmutableMessageFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { +void RepeatedImmutableMessageFieldGenerator::GenerateBuildingCode( + io::Printer* printer) const { // The code below (non-nested builder case) ensures that the result has an // immutable list. If our list is immutable, we can just reuse it. If not, // we make it immutable. - PrintNestedBuilderCondition(printer, - "if ($get_mutable_bit_builder$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - " $clear_mutable_bit_builder$;\n" - "}\n" - "result.$name$_ = $name$_;\n", - - "result.$name$_ = $name$Builder_.build();\n"); + PrintNestedBuilderCondition( + printer, + "if ($get_mutable_bit_builder$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n", + + "result.$name$_ = $name$Builder_.build();\n"); } -void RepeatedImmutableMessageFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +void RepeatedImmutableMessageFieldGenerator::GenerateParsingCode( + io::Printer* printer) const { printer->Print(variables_, - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ = new java.util.ArrayList<$type$>();\n" - " $set_mutable_bit_parser$;\n" - "}\n"); + "if (!$get_mutable_bit_parser$) {\n" + " $name$_ = new java.util.ArrayList<$type$>();\n" + " $set_mutable_bit_parser$;\n" + "}\n"); if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { - printer->Print(variables_, - "$name$_.add(input.readGroup($number$, $type$.$get_parser$,\n" - " extensionRegistry));\n"); + printer->Print( + variables_, + "$name$_.add(input.readGroup($number$, $type$.$get_parser$,\n" + " extensionRegistry));\n"); } else { - printer->Print(variables_, - "$name$_.add(\n" - " input.readMessage($type$.$get_parser$, extensionRegistry));\n"); + printer->Print( + variables_, + "$name$_.add(\n" + " input.readMessage($type$.$get_parser$, extensionRegistry));\n"); } } -void RepeatedImmutableMessageFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_mutable_bit_parser$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - "}\n"); +void RepeatedImmutableMessageFieldGenerator::GenerateParsingDoneCode( + io::Printer* printer) const { + printer->Print( + variables_, + "if ($get_mutable_bit_parser$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + "}\n"); } -void RepeatedImmutableMessageFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { +void RepeatedImmutableMessageFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$group_or_message$($number$, $name$_.get(i));\n" - "}\n"); + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$group_or_message$($number$, $name$_.get(i));\n" + "}\n"); } -void RepeatedImmutableMessageFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .compute$group_or_message$Size($number$, $name$_.get(i));\n" - "}\n"); +void RepeatedImmutableMessageFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { + printer->Print( + variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$group_or_message$Size($number$, $name$_.get(i));\n" + "}\n"); } -void RepeatedImmutableMessageFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && get$capitalized_name$List()\n" - " .equals(other.get$capitalized_name$List());\n"); +void RepeatedImmutableMessageFieldGenerator::GenerateEqualsCode( + io::Printer* printer) const { + printer->Print( + variables_, + "if (!get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List())) return false;\n"); } -void RepeatedImmutableMessageFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "if (get$capitalized_name$Count() > 0) {\n" - " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" - "}\n"); +void RepeatedImmutableMessageFieldGenerator::GenerateHashCode( + io::Printer* printer) const { + printer->Print( + variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" + "}\n"); } -string RepeatedImmutableMessageFieldGenerator::GetBoxedType() const { +std::string RepeatedImmutableMessageFieldGenerator::GetBoxedType() const { return name_resolver_->GetImmutableClassName(descriptor_->message_type()); } diff --git a/src/google/protobuf/compiler/java/java_message_field.h b/src/google/protobuf/compiler/java/java_message_field.h index 7ee0edb269f1d..36fa49208cbe1 100644 --- a/src/google/protobuf/compiler/java/java_message_field.h +++ b/src/google/protobuf/compiler/java/java_message_field.h @@ -41,26 +41,30 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { public: - explicit ImmutableMessageFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableMessageFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context); ~ImmutableMessageFieldGenerator(); - // implements ImmutableFieldGenerator --------------------------------------- + // implements ImmutableFieldGenerator + // --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -78,22 +82,21 @@ class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; + std::map variables_; ClassNameResolver* name_resolver_; void PrintNestedBuilderCondition(io::Printer* printer, - const char* regular_case, const char* nested_builder_case) const; + const char* regular_case, + const char* nested_builder_case) const; void PrintNestedBuilderFunction(io::Printer* printer, - const char* method_prototype, const char* regular_case, - const char* nested_builder_case, - const char* trailing_code) const; + const char* method_prototype, + const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldGenerator); @@ -102,9 +105,9 @@ class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { class ImmutableMessageOneofFieldGenerator : public ImmutableMessageFieldGenerator { public: - ImmutableMessageOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutableMessageOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex, + Context* context); ~ImmutableMessageOneofFieldGenerator(); void GenerateMembers(io::Printer* printer) const; @@ -144,22 +147,21 @@ class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; + std::map variables_; ClassNameResolver* name_resolver_; void PrintNestedBuilderCondition(io::Printer* printer, - const char* regular_case, const char* nested_builder_case) const; + const char* regular_case, + const char* nested_builder_case) const; void PrintNestedBuilderFunction(io::Printer* printer, - const char* method_prototype, const char* regular_case, - const char* nested_builder_case, - const char* trailing_code) const; + const char* method_prototype, + const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldGenerator); @@ -168,6 +170,6 @@ class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc index df3e80d4e02af..b17859d6b32c7 100644 --- a/src/google/protobuf/compiler/java/java_message_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc @@ -36,9 +36,9 @@ #include #include -#include #include #include +#include #include #include #include @@ -51,12 +51,10 @@ namespace java { namespace { -void SetMessageVariables(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - const FieldGeneratorInfo* info, +void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, - std::map* variables) { + std::map* variables) { SetCommonFieldVariables(descriptor, info, variables); (*variables)["type"] = @@ -64,15 +62,15 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["mutable_type"] = name_resolver->GetMutableClassName(descriptor->message_type()); (*variables)["group_or_message"] = - (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ? - "Group" : "Message"; + (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ? "Group" + : "Message"; // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler - (*variables)["deprecation"] = descriptor->options().deprecated() - ? "@java.lang.Deprecated " : ""; + (*variables)["deprecation"] = + descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; (*variables)["required"] = descriptor->is_required() ? "true" : "false"; - if (SupportFieldPresence(descriptor->file())) { + if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); @@ -91,880 +89,663 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["name"] + "_ != null"; } - // For repeated builders, the underlying list tracks mutability state. - (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()"; - (*variables)["get_has_field_bit_from_local"] = GenerateGetBitFromLocal(builderBitIndex); (*variables)["set_has_field_bit_to_local"] = GenerateSetBitToLocal(messageBitIndex); + + // We use `x.getClass()` as a null check because it generates less bytecode + // than an `if (x == null) { throw ... }` statement. + (*variables)["null_check"] = "value.getClass();\n"; } } // namespace // =================================================================== -ImmutableMessageFieldLiteGenerator:: -ImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); +ImmutableMessageFieldLiteGenerator::ImmutableMessageFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, Context* context) + : descriptor_(descriptor), + messageBitIndex_(messageBitIndex), + name_resolver_(context->GetNameResolver()) { + SetMessageVariables(descriptor, messageBitIndex, 0, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); } ImmutableMessageFieldLiteGenerator::~ImmutableMessageFieldLiteGenerator() {} int ImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const { - return 1; -} - -int ImmutableMessageFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; + // TODO(dweis): We don't need a has bit for messages as they have null + // sentinels and no user should be reflecting on this. We could save some + // bits by setting to 0 and updating the runtimes but this might come at a + // runtime performance cost since we can't memoize has-bit reads. + return HasHasbit(descriptor_) ? 1 : 0; } -void ImmutableMessageFieldLiteGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$();\n"); +void ImmutableMessageFieldLiteGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print(variables_, "$deprecation$boolean has$capitalized_name$();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n"); } -void ImmutableMessageFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { +void ImmutableMessageFieldLiteGenerator::GenerateMembers( + io::Printer* printer) const { - printer->Print(variables_, - "private $type$ $name$_;\n"); + printer->Print(variables_, "private $type$ $name$_;\n"); PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { + if (HasHasbit(descriptor_)) { WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" - "}\n"); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } else { WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $name$_ != null;\n" - "}\n"); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $name$_ != null;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" - "}\n"); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } // Field.Builder setField(Field value) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "private void set$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " $name$_ = value;\n" - " $set_has_field_bit_message$\n" - " }\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " $name$_ = builderForValue.build();\n" - " $set_has_field_bit_message$\n" - "}\n"); + "private void set$capitalized_name$($type$ value) {\n" + " $null_check$" + " $name$_ = value;\n" + " $set_has_field_bit_message$\n" + " }\n"); // Field.Builder mergeField(Field value) WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void merge$capitalized_name$($type$ value) {\n" - " if ($name$_ != null &&\n" - " $name$_ != $type$.getDefaultInstance()) {\n" - " $name$_ =\n" - " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" - " } else {\n" - " $name$_ = value;\n" - " }\n" - " $set_has_field_bit_message$\n" - "}\n"); + printer->Print( + variables_, + "@java.lang.SuppressWarnings({\"ReferenceEquality\"})\n" + "private void merge$capitalized_name$($type$ value) {\n" + " $null_check$" + " if ($name$_ != null &&\n" + " $name$_ != $type$.getDefaultInstance()) {\n" + " $name$_ =\n" + " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" + " } else {\n" + " $name$_ = value;\n" + " }\n" + " $set_has_field_bit_message$\n" + "}\n"); // Field.Builder clearField() WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "private void clear$capitalized_name$() {" - " $name$_ = null;\n" - " $clear_has_field_bit_message$\n" - "}\n"); + "private void clear$capitalized_name$() {" + " $name$_ = null;\n" + " $clear_has_field_bit_message$\n" + "}\n"); } -void ImmutableMessageFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { +void ImmutableMessageFieldLiteGenerator::GenerateBuilderMembers( + io::Printer* printer) const { // The comments above the methods below are based on a hypothetical // field of type "Field" called "Field". // boolean hasField() WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return instance.has$capitalized_name$();\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Field getField() WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return instance.get$capitalized_name$();\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Field.Builder setField(Field value) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(value);\n" - " return this;\n" - " }\n"); + "$deprecation$public Builder " + "${$set$capitalized_name$$}$($type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + " }\n"); printer->Annotate("{", "}", descriptor_); // Field.Builder setField(Field.Builder builderForValue) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(builderForValue);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(builderForValue.build());\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Field.Builder mergeField(Field value) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder " - "${$merge$capitalized_name$$}$($type$ value) {\n" - " copyOnWrite();\n" - " instance.merge$capitalized_name$(value);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder " + "${$merge$capitalized_name$$}$($type$ value) {\n" + " copyOnWrite();\n" + " instance.merge$capitalized_name$(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Field.Builder clearField() WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutableMessageFieldLiteGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "get$capitalized_name$FieldBuilder();\n"); +void ImmutableMessageFieldLiteGenerator::GenerateFieldInfo( + io::Printer* printer, std::vector* output) const { + WriteIntToUtf16CharSequence(descriptor_->number(), output); + WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_), + output); + if (HasHasbit(descriptor_)) { + WriteIntToUtf16CharSequence(messageBitIndex_, output); } + printer->Print(variables_, "\"$name$_\",\n"); } +void ImmutableMessageFieldLiteGenerator::GenerateInitializationCode( + io::Printer* printer) const {} -void ImmutableMessageFieldLiteGenerator:: -GenerateInitializationCode(io::Printer* printer) const {} - -void ImmutableMessageFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = visitor.visitMessage($name$_, other.$name$_);\n"); -} - -void ImmutableMessageFieldLiteGenerator:: -GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { - // noop for scalars -} - -void ImmutableMessageFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - // TODO(dweis): Update this code to avoid the builder allocation and instead - // only allocate a submessage that isn't made immutable. Rely on the top - // message calling makeImmutable once done to actually traverse the tree and - // finalize state. This will avoid: - // - transitive builder allocations - // - the extra transitive iteration for streamed fields - // - reallocations for copying repeated fields - printer->Print(variables_, - "$type$.Builder subBuilder = null;\n" - "if ($is_field_present_message$) {\n" - " subBuilder = $name$_.toBuilder();\n" - "}\n"); - - if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { - printer->Print(variables_, - "$name$_ = input.readGroup($number$, $type$.parser(),\n" - " extensionRegistry);\n"); - } else { - printer->Print(variables_, - "$name$_ = input.readMessage($type$.parser(), extensionRegistry);\n"); - } - - printer->Print(variables_, - "if (subBuilder != null) {\n" - " subBuilder.mergeFrom($name$_);\n" - " $name$_ = subBuilder.buildPartial();\n" - "}\n" - "$set_has_field_bit_message$\n"); -} - -void ImmutableMessageFieldLiteGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - // noop for messages. -} - -void ImmutableMessageFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " output.write$group_or_message$($number$, get$capitalized_name$());\n" - "}\n"); -} - -void ImmutableMessageFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .compute$group_or_message$Size($number$, get$capitalized_name$());\n" - "}\n"); -} - -void ImmutableMessageFieldLiteGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && get$capitalized_name$()\n" - " .equals(other.get$capitalized_name$());\n"); -} - -void ImmutableMessageFieldLiteGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n" - "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); -} - -string ImmutableMessageFieldLiteGenerator::GetBoxedType() const { +std::string ImmutableMessageFieldLiteGenerator::GetBoxedType() const { return name_resolver_->GetImmutableClassName(descriptor_->message_type()); } // =================================================================== ImmutableMessageOneofFieldLiteGenerator:: -ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableMessageFieldLiteGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { + ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context) + : ImmutableMessageFieldLiteGenerator(descriptor, messageBitIndex, context) { const OneofGeneratorInfo* info = context->GetOneofGeneratorInfo(descriptor->containing_oneof()); SetCommonOneofVariables(descriptor, info, &variables_); } ImmutableMessageOneofFieldLiteGenerator:: -~ImmutableMessageOneofFieldLiteGenerator() {} + ~ImmutableMessageOneofFieldLiteGenerator() {} -void ImmutableMessageOneofFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { +void ImmutableMessageOneofFieldLiteGenerator::GenerateMembers( + io::Printer* printer) const { PrintExtraFieldInfo(variables_, printer); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) $oneof_name$_;\n" - " }\n" - " return $type$.getDefaultInstance();\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $type$.getDefaultInstance();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Field.Builder setField(Field value) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "private void set$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " $oneof_name$_ = value;\n" - " $set_oneof_case_message$;\n" - "}\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " $oneof_name$_ = builderForValue.build();\n" - " $set_oneof_case_message$;\n" - "}\n"); + "private void set$capitalized_name$($type$ value) {\n" + " $null_check$" + " $oneof_name$_ = value;\n" + " $set_oneof_case_message$;\n" + "}\n"); // Field.Builder mergeField(Field value) WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void merge$capitalized_name$($type$ value) {\n" - " if ($has_oneof_case_message$ &&\n" - " $oneof_name$_ != $type$.getDefaultInstance()) {\n" - " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n" - " .mergeFrom(value).buildPartial();\n" - " } else {\n" - " $oneof_name$_ = value;\n" - " }\n" - " $set_oneof_case_message$;\n" - "}\n"); + printer->Print( + variables_, + "private void merge$capitalized_name$($type$ value) {\n" + " $null_check$" + " if ($has_oneof_case_message$ &&\n" + " $oneof_name$_ != $type$.getDefaultInstance()) {\n" + " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n" + " .mergeFrom(value).buildPartial();\n" + " } else {\n" + " $oneof_name$_ = value;\n" + " }\n" + " $set_oneof_case_message$;\n" + "}\n"); // Field.Builder clearField() WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " }\n" - "}\n"); + "private void clear$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " }\n" + "}\n"); } +void ImmutableMessageOneofFieldLiteGenerator::GenerateFieldInfo( + io::Printer* printer, std::vector* output) const { + WriteIntToUtf16CharSequence(descriptor_->number(), output); + WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_), + output); + WriteIntToUtf16CharSequence(descriptor_->containing_oneof()->index(), output); + printer->Print(variables_, "$oneof_stored_type$.class,\n"); +} -void ImmutableMessageOneofFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { +void ImmutableMessageOneofFieldLiteGenerator::GenerateBuilderMembers( + io::Printer* printer) const { // The comments above the methods below are based on a hypothetical // field of type "Field" called "Field". // boolean hasField() WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return instance.has$capitalized_name$();\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Field getField() WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return instance.get$capitalized_name$();\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Field.Builder setField(Field value) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(value);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder " + "${$set$capitalized_name$$}$($type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Field.Builder setField(Field.Builder builderForValue) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(builderForValue);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(builderForValue.build());\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Field.Builder mergeField(Field value) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder " - "${$merge$capitalized_name$$}$($type$ value) {\n" - " copyOnWrite();\n" - " instance.merge$capitalized_name$(value);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder " + "${$merge$capitalized_name$$}$($type$ value) {\n" + " copyOnWrite();\n" + " instance.merge$capitalized_name$(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Field.Builder clearField() WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutableMessageOneofFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - printer->Print(variables_, - "$oneof_name$_ = visitor.visitOneofMessage(\n" - " $has_oneof_case_message$,\n" - " $oneof_name$_,\n" - " other.$oneof_name$_);\n"); -} - -void ImmutableMessageOneofFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "$type$.Builder subBuilder = null;\n" - "if ($has_oneof_case_message$) {\n" - " subBuilder = (($type$) $oneof_name$_).toBuilder();\n" - "}\n"); - - if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { - printer->Print(variables_, - "$oneof_name$_ = input.readGroup($number$, $type$.parser(),\n" - " extensionRegistry);\n"); - } else { - printer->Print(variables_, - "$oneof_name$_ =\n" - " input.readMessage($type$.parser(), extensionRegistry);\n"); - } - - printer->Print(variables_, - "if (subBuilder != null) {\n" - " subBuilder.mergeFrom(($type$) $oneof_name$_);\n" - " $oneof_name$_ = subBuilder.buildPartial();\n" - "}\n"); - printer->Print(variables_, - "$set_oneof_case_message$;\n"); -} - -void ImmutableMessageOneofFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n" - "}\n"); -} - -void ImmutableMessageOneofFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .compute$group_or_message$Size($number$, ($type$) $oneof_name$_);\n" - "}\n"); -} - // =================================================================== RepeatedImmutableMessageFieldLiteGenerator:: -RepeatedImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, + RepeatedImmutableMessageFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + Context* context) + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { + SetMessageVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); } RepeatedImmutableMessageFieldLiteGenerator:: -~RepeatedImmutableMessageFieldLiteGenerator() {} + ~RepeatedImmutableMessageFieldLiteGenerator() {} int RepeatedImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const { return 0; } -int RepeatedImmutableMessageFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; -} - -void RepeatedImmutableMessageFieldLiteGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { +void RepeatedImmutableMessageFieldLiteGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { // TODO(jonp): In the future, consider having methods specific to the // interface so that builders can choose dynamically to either return a // message or a nested builder, so that asking for the interface doesn't // cause a message to ever be built. WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$java.util.List<$type$> \n" - " get$capitalized_name$List();\n"); + "$deprecation$java.util.List<$type$> \n" + " get$capitalized_name$List();\n"); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$(int index);\n"); + "$deprecation$$type$ get$capitalized_name$(int index);\n"); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); + "$deprecation$int get$capitalized_name$Count();\n"); } -void RepeatedImmutableMessageFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private com.google.protobuf.Internal.ProtobufList<$type$> $name$_;\n"); +void RepeatedImmutableMessageFieldLiteGenerator::GenerateMembers( + io::Printer* printer) const { + printer->Print( + variables_, + "private com.google.protobuf.Internal.ProtobufList<$type$> $name$_;\n"); PrintExtraFieldInfo(variables_, printer); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public java.util.List<$type$> " - "${$get$capitalized_name$List$}$() {\n" - " return $name$_;\n" // note: unmodifiable list - "}\n"); + "@java.lang.Override\n" + "$deprecation$public java.util.List<$type$> " + "${$get$capitalized_name$List$}$() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List \n" - " ${$get$capitalized_name$OrBuilderList$}$() {\n" - " return $name$_;\n" - "}\n"); + printer->Print( + variables_, + "$deprecation$public java.util.List \n" + " ${$get$capitalized_name$OrBuilderList$}$() {\n" + " return $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return $name$_.size();\n" - "}\n"); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return $name$_.size();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return $name$_.get(index);\n" - "}\n"); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public $type$OrBuilder " - "${$get$capitalized_name$OrBuilder$}$(\n" - " int index) {\n" - " return $name$_.get(index);\n" - "}\n"); + "$deprecation$public $type$OrBuilder " + "${$get$capitalized_name$OrBuilder$}$(\n" + " int index) {\n" + " return $name$_.get(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$is_mutable$) {\n" - " $name$_ =\n" - " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" - " }\n" - "}\n" - "\n"); + printer->Print( + variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + // Use a temporary to avoid a redundant iget-object. + " com.google.protobuf.Internal.ProtobufList<$type$> tmp = $name$_;\n" + " if (!tmp.isModifiable()) {\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n" + " }\n" + "}\n" + "\n"); // Builder setRepeatedField(int index, Field value) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "private void set$capitalized_name$(\n" - " int index, $type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, value);\n" - "}\n"); - - // Builder setRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$(\n" - " int index, $type$.Builder builderForValue) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, builderForValue.build());\n" - "}\n"); + "private void set$capitalized_name$(\n" + " int index, $type$ value) {\n" + " $null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + "}\n"); // Builder addRepeatedField(Field value) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "private void add$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value);\n" - "}\n"); + "private void add$capitalized_name$($type$ value) {\n" + " $null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + "}\n"); // Builder addRepeatedField(int index, Field value) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "private void add$capitalized_name$(\n" - " int index, $type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(index, value);\n" - "}\n"); - // Builder addRepeatedField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(builderForValue.build());\n" - "}\n"); - - // Builder addRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$(\n" - " int index, $type$.Builder builderForValue) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(index, builderForValue.build());\n" - "}\n"); + "private void add$capitalized_name$(\n" + " int index, $type$ value) {\n" + " $null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(index, value);\n" + "}\n"); // Builder addAllRepeatedField(Iterable values) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "private void addAll$capitalized_name$(\n" - " java.lang.Iterable values) {\n" - " ensure$capitalized_name$IsMutable();\n" - " com.google.protobuf.AbstractMessageLite.addAll(\n" - " values, $name$_);\n" - "}\n"); + "private void addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " com.google.protobuf.AbstractMessageLite.addAll(\n" + " values, $name$_);\n" + "}\n"); // Builder clearAllRepeatedField() WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " $name$_ = emptyProtobufList();\n" - "}\n"); + "private void clear$capitalized_name$() {\n" + " $name$_ = emptyProtobufList();\n" + "}\n"); // Builder removeRepeatedField(int index) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "private void remove$capitalized_name$(int index) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.remove(index);\n" - "}\n"); + "private void remove$capitalized_name$(int index) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.remove(index);\n" + "}\n"); } -void RepeatedImmutableMessageFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { +void RepeatedImmutableMessageFieldLiteGenerator::GenerateBuilderMembers( + io::Printer* printer) const { // The comments above the methods below are based on a hypothetical // repeated field of type "Field" called "RepeatedField". // List getRepeatedFieldList() WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public java.util.List<$type$> " - "${$get$capitalized_name$List$}$() {\n" - " return java.util.Collections.unmodifiableList(\n" - " instance.get$capitalized_name$List());\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public java.util.List<$type$> " + "${$get$capitalized_name$List$}$() {\n" + " return java.util.Collections.unmodifiableList(\n" + " instance.get$capitalized_name$List());\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // int getRepeatedFieldCount() WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return instance.get$capitalized_name$Count();\n" - "}"); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return instance.get$capitalized_name$Count();\n" + "}"); printer->Annotate("{", "}", descriptor_); // Field getRepeatedField(int index) WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return instance.get$capitalized_name$(index);\n" - "}\n"); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" + " return instance.get$capitalized_name$(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Builder setRepeatedField(int index, Field value) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " int index, $type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(index, value);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " int index, $type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(index, value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Builder setRepeatedField(int index, Field.Builder builderForValue) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " int index, $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(index, builderForValue);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " int index, $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(index,\n" + " builderForValue.build());\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Builder addRepeatedField(Field value) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(value);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder " + "${$add$capitalized_name$$}$($type$ value) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Builder addRepeatedField(int index, Field value) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" - " int index, $type$ value) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(index, value);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" + " int index, $type$ value) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(index, value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Builder addRepeatedField(Field.Builder builderForValue) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" - " $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(builderForValue);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" + " $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(builderForValue.build());\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Builder addRepeatedField(int index, Field.Builder builderForValue) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" - " int index, $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(index, builderForValue);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" + " int index, $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(index,\n" + " builderForValue.build());\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Builder addAllRepeatedField(Iterable values) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" - " java.lang.Iterable values) {\n" - " copyOnWrite();\n" - " instance.addAll$capitalized_name$(values);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" + " java.lang.Iterable values) {\n" + " copyOnWrite();\n" + " instance.addAll$capitalized_name$(values);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Builder clearAllRepeatedField() WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); // Builder removeRepeatedField(int index) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public Builder ${$remove$capitalized_name$$}$(int index) {\n" - " copyOnWrite();\n" - " instance.remove$capitalized_name$(index);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder " + "${$remove$capitalized_name$$}$(int index) {\n" + " copyOnWrite();\n" + " instance.remove$capitalized_name$(index);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void RepeatedImmutableMessageFieldLiteGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { +void RepeatedImmutableMessageFieldLiteGenerator::GenerateFieldInfo( + io::Printer* printer, std::vector* output) const { + WriteIntToUtf16CharSequence(descriptor_->number(), output); + WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_), + output); printer->Print(variables_, - "get$capitalized_name$FieldBuilder();\n"); + "\"$name$_\",\n" + "$type$.class,\n"); } - -void RepeatedImmutableMessageFieldLiteGenerator:: -GenerateInitializationCode(io::Printer* printer) const { +void RepeatedImmutableMessageFieldLiteGenerator::GenerateInitializationCode( + io::Printer* printer) const { printer->Print(variables_, "$name$_ = emptyProtobufList();\n"); } -void RepeatedImmutableMessageFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_= visitor.visitList($name$_, other.$name$_);\n"); -} - -void RepeatedImmutableMessageFieldLiteGenerator:: -GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_.makeImmutable();\n"); -} - -void RepeatedImmutableMessageFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!$is_mutable$) {\n" - " $name$_ =\n" - " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" - "}\n"); - - if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { - printer->Print(variables_, - "$name$_.add(input.readGroup($number$, $type$.parser(),\n" - " extensionRegistry));\n"); - } else { - printer->Print(variables_, - "$name$_.add(\n" - " input.readMessage($type$.parser(), extensionRegistry));\n"); - } -} - -void RepeatedImmutableMessageFieldLiteGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_mutable$) {\n" - " $name$_.makeImmutable();\n" - "}\n"); -} - -void RepeatedImmutableMessageFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$group_or_message$($number$, $name$_.get(i));\n" - "}\n"); -} - -void RepeatedImmutableMessageFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .compute$group_or_message$Size($number$, $name$_.get(i));\n" - "}\n"); -} - -void RepeatedImmutableMessageFieldLiteGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && get$capitalized_name$List()\n" - " .equals(other.get$capitalized_name$List());\n"); -} - -void RepeatedImmutableMessageFieldLiteGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "if (get$capitalized_name$Count() > 0) {\n" - " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" - "}\n"); -} - -string RepeatedImmutableMessageFieldLiteGenerator::GetBoxedType() const { +std::string RepeatedImmutableMessageFieldLiteGenerator::GetBoxedType() const { return name_resolver_->GetImmutableClassName(descriptor_->message_type()); } diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.h b/src/google/protobuf/compiler/java/java_message_field_lite.h index 7c814c6d7e058..c0a9b37f4f6d1 100644 --- a/src/google/protobuf/compiler/java/java_message_field_lite.h +++ b/src/google/protobuf/compiler/java/java_message_field_lite.h @@ -41,50 +41,43 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: - explicit ImmutableMessageFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context); ~ImmutableMessageFieldLiteGenerator(); - // implements ImmutableFieldLiteGenerator ------------------------------------ + // implements ImmutableFieldLiteGenerator + // ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; - - string GetBoxedType() const; + void GenerateFieldInfo(io::Printer* printer, + std::vector* output) const; + + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map variables_; + std::map variables_; const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; ClassNameResolver* name_resolver_; private: @@ -94,18 +87,15 @@ class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator { class ImmutableMessageOneofFieldLiteGenerator : public ImmutableMessageFieldLiteGenerator { public: - ImmutableMessageOneofFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context); ~ImmutableMessageOneofFieldLiteGenerator(); void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - + void GenerateFieldInfo(io::Printer* printer, + std::vector* output) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldLiteGenerator); @@ -115,36 +105,23 @@ class RepeatedImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: explicit RepeatedImmutableMessageFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + const FieldDescriptor* descriptor, int messageBitIndex, Context* context); ~RepeatedImmutableMessageFieldLiteGenerator(); // implements ImmutableFieldLiteGenerator ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; - + void GenerateFieldInfo(io::Printer* printer, + std::vector* output) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; + std::map variables_; ClassNameResolver* name_resolver_; private: @@ -154,6 +131,6 @@ class RepeatedImmutableMessageFieldLiteGenerator } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc index 26f16439a45cb..4afffdc7a979c 100644 --- a/src/google/protobuf/compiler/java/java_message_lite.cc +++ b/src/google/protobuf/compiler/java/java_message_lite.cc @@ -35,12 +35,8 @@ #include #include -#include #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include @@ -52,13 +48,12 @@ #include #include #include +#include #include #include -#include #include -#include #include - +#include namespace google { namespace protobuf { @@ -68,29 +63,21 @@ namespace java { using internal::WireFormat; using internal::WireFormatLite; -namespace { -bool GenerateHasBits(const Descriptor* descriptor) { - return SupportFieldPresence(descriptor->file()) || - HasRepeatedFields(descriptor); -} - -string MapValueImmutableClassdName(const Descriptor* descriptor, - ClassNameResolver* name_resolver) { - const FieldDescriptor* value_field = descriptor->FindFieldByName("value"); - GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type()); - return name_resolver->GetImmutableClassName(value_field->message_type()); -} -} // namespace - // =================================================================== ImmutableMessageLiteGenerator::ImmutableMessageLiteGenerator( const Descriptor* descriptor, Context* context) - : MessageGenerator(descriptor), context_(context), - name_resolver_(context->GetNameResolver()), - field_generators_(descriptor, context_) { + : MessageGenerator(descriptor), + context_(context), + name_resolver_(context->GetNameResolver()), + field_generators_(descriptor, context_) { GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite())) << "Generator factory error: A lite message generator is used to " "generate non-lite messages."; + for (int i = 0; i < descriptor_->field_count(); i++) { + if (IsRealOneof(descriptor_->field(i))) { + oneofs_.insert(descriptor_->field(i)->containing_oneof()); + } + } } ImmutableMessageLiteGenerator::~ImmutableMessageLiteGenerator() {} @@ -130,41 +117,37 @@ void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) { " com.google.protobuf.GeneratedMessageLite.\n" " ExtendableMessageOrBuilder<\n" " $classname$, $classname$.Builder> {\n", - "deprecation", descriptor_->options().deprecated() ? - "@java.lang.Deprecated " : "", + "deprecation", + descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "", "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name(), - "{", "", "}", ""); + "classname", descriptor_->name(), "{", "", "}", ""); } else { printer->Print( "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n" " $extra_interfaces$\n" " com.google.protobuf.MessageLiteOrBuilder {\n", - "deprecation", descriptor_->options().deprecated() ? - "@java.lang.Deprecated " : "", + "deprecation", + descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "", "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name(), - "{", "", "}", ""); + "classname", descriptor_->name(), "{", "", "}", ""); } printer->Annotate("{", "}", descriptor_); printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print("\n"); - field_generators_.get(descriptor_->field(i)) - .GenerateInterfaceMembers(printer); - } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "\n" - "public $classname$.$oneof_capitalized_name$Case " - "get$oneof_capitalized_name$Case();\n", - "oneof_capitalized_name", - context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name, - "classname", - context_->GetNameResolver()->GetImmutableClassName(descriptor_)); - } + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print("\n"); + field_generators_.get(descriptor_->field(i)) + .GenerateInterfaceMembers(printer); + } + for (auto oneof : oneofs_) { + printer->Print( + "\n" + "public $classname$.$oneof_capitalized_name$Case " + "get$oneof_capitalized_name$Case();\n", + "oneof_capitalized_name", + context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "classname", + context_->GetNameResolver()->GetImmutableClassName(descriptor_)); + } printer->Outdent(); printer->Print("}\n"); @@ -175,12 +158,12 @@ void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) { void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true); - std::map variables; + std::map variables; variables["static"] = is_own_file ? " " : " static "; variables["classname"] = descriptor_->name(); variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_); - variables["deprecation"] = descriptor_->options().deprecated() - ? "@java.lang.Deprecated " : ""; + variables["deprecation"] = + descriptor_->options().deprecated() ? "@java.lang.Deprecated " : ""; WriteMessageDocComment(printer, descriptor_); MaybePrintGeneratedAnnotation(context_, printer, descriptor_, @@ -188,19 +171,21 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { // The builder_type stores the super type name of the nested Builder class. - string builder_type; + std::string builder_type; if (descriptor_->extension_range_count() > 0) { - printer->Print(variables, - "$deprecation$public $static$final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" - " $classname$, $classname$.Builder> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n"); + printer->Print( + variables, + "$deprecation$public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" + " $classname$, $classname$.Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); builder_type = strings::Substitute( "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>", name_resolver_->GetImmutableClassName(descriptor_)); } else { - printer->Print(variables, + printer->Print( + variables, "$deprecation$public $static$final class $classname$ extends\n" " com.google.protobuf.GeneratedMessageLite<\n" " $classname$, $classname$.Builder> implements\n" @@ -222,130 +207,119 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { for (int i = 0; i < descriptor_->nested_type_count(); i++) { // Don't generate Java classes for map entry messages. if (IsMapEntry(descriptor_->nested_type(i))) continue; - ImmutableMessageLiteGenerator messageGenerator( - descriptor_->nested_type(i), context_); + ImmutableMessageLiteGenerator messageGenerator(descriptor_->nested_type(i), + context_); messageGenerator.GenerateInterface(printer); messageGenerator.Generate(printer); } - if (GenerateHasBits(descriptor_)) { - // Integers for bit fields. - int totalBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - totalBits += field_generators_.get(descriptor_->field(i)) - .GetNumBitsForMessage(); - } - int totalInts = (totalBits + 31) / 32; - for (int i = 0; i < totalInts; i++) { - printer->Print("private int $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } + // Integers for bit fields. + int totalBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + totalBits += + field_generators_.get(descriptor_->field(i)).GetNumBitsForMessage(); + } + int totalInts = (totalBits + 31) / 32; + for (int i = 0; i < totalInts; i++) { + printer->Print("private int $bit_field_name$;\n", "bit_field_name", + GetBitFieldName(i)); } // oneof - std::map vars; - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + std::map vars; + for (auto oneof : oneofs_) { vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name; - vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( - oneof)->capitalized_name; - vars["oneof_index"] = SimpleItoa(oneof->index()); + vars["oneof_capitalized_name"] = + context_->GetOneofGeneratorInfo(oneof)->capitalized_name; + vars["oneof_index"] = StrCat((oneof)->index()); // oneofCase_ and oneof_ printer->Print(vars, - "private int $oneof_name$Case_ = 0;\n" - "private java.lang.Object $oneof_name$_;\n"); + "private int $oneof_name$Case_ = 0;\n" + "private java.lang.Object $oneof_name$_;\n"); // OneofCase enum - printer->Print(vars, - "public enum $oneof_capitalized_name$Case\n" - " implements com.google.protobuf.Internal.EnumLite {\n"); + printer->Print(vars, "public enum $oneof_capitalized_name$Case {\n"); printer->Indent(); - for (int j = 0; j < oneof->field_count(); j++) { - const FieldDescriptor* field = oneof->field(j); - printer->Print( - "$field_name$($field_number$),\n", - "field_name", - ToUpper(field->name()), - "field_number", - SimpleItoa(field->number())); + for (int j = 0; j < (oneof)->field_count(); j++) { + const FieldDescriptor* field = (oneof)->field(j); + printer->Print("$field_name$($field_number$),\n", "field_name", + ToUpper(field->name()), "field_number", + StrCat(field->number())); } - printer->Print( - "$cap_oneof_name$_NOT_SET(0);\n", - "cap_oneof_name", - ToUpper(vars["oneof_name"])); - printer->Print(vars, - "private final int value;\n" - "private $oneof_capitalized_name$Case(int value) {\n" - " this.value = value;\n" - "}\n"); + printer->Print("$cap_oneof_name$_NOT_SET(0);\n", "cap_oneof_name", + ToUpper(vars["oneof_name"])); printer->Print(vars, - "/**\n" - " * @deprecated Use {@link #forNumber(int)} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public static $oneof_capitalized_name$Case valueOf(int value) {\n" - " return forNumber(value);\n" - "}\n" - "\n" - "public static $oneof_capitalized_name$Case forNumber(int value) {\n" - " switch (value) {\n"); - for (int j = 0; j < oneof->field_count(); j++) { - const FieldDescriptor* field = oneof->field(j); - printer->Print( - " case $field_number$: return $field_name$;\n", - "field_number", - SimpleItoa(field->number()), - "field_name", - ToUpper(field->name())); + "private final int value;\n" + "private $oneof_capitalized_name$Case(int value) {\n" + " this.value = value;\n" + "}\n"); + printer->Print( + vars, + "/**\n" + " * @deprecated Use {@link #forNumber(int)} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "public static $oneof_capitalized_name$Case valueOf(int value) {\n" + " return forNumber(value);\n" + "}\n" + "\n" + "public static $oneof_capitalized_name$Case forNumber(int value) {\n" + " switch (value) {\n"); + for (int j = 0; j < (oneof)->field_count(); j++) { + const FieldDescriptor* field = (oneof)->field(j); + printer->Print(" case $field_number$: return $field_name$;\n", + "field_number", StrCat(field->number()), + "field_name", ToUpper(field->name())); } printer->Print( - " case 0: return $cap_oneof_name$_NOT_SET;\n" - " default: return null;\n" - " }\n" - "}\n" - "public int getNumber() {\n" - " return this.value;\n" - "}\n", - "cap_oneof_name", ToUpper(vars["oneof_name"])); + " case 0: return $cap_oneof_name$_NOT_SET;\n" + " default: return null;\n" + " }\n" + "}\n" + // TODO(b/135620659): Rename this to "getFieldNumber" or something to + // disambiguate it from actual proto enums. + "public int getNumber() {\n" + " return this.value;\n" + "}\n", + "cap_oneof_name", ToUpper(vars["oneof_name"])); printer->Outdent(); printer->Print("};\n\n"); // oneofCase() printer->Print(vars, - "public $oneof_capitalized_name$Case\n" - "get$oneof_capitalized_name$Case() {\n" - " return $oneof_capitalized_name$Case.forNumber(\n" - " $oneof_name$Case_);\n" - "}\n" - "\n" - "private void clear$oneof_capitalized_name$() {\n" - " $oneof_name$Case_ = 0;\n" - " $oneof_name$_ = null;\n" - "}\n" - "\n"); + "@java.lang.Override\n" + "public $oneof_capitalized_name$Case\n" + "get$oneof_capitalized_name$Case() {\n" + " return $oneof_capitalized_name$Case.forNumber(\n" + " $oneof_name$Case_);\n" + "}\n" + "\n" + "private void clear$oneof_capitalized_name$() {\n" + " $oneof_name$Case_ = 0;\n" + " $oneof_name$_ = null;\n" + "}\n" + "\n"); } // Fields for (int i = 0; i < descriptor_->field_count(); i++) { printer->Print("public static final int $constant_name$ = $number$;\n", - "constant_name", FieldConstantName(descriptor_->field(i)), - "number", SimpleItoa(descriptor_->field(i)->number())); + "constant_name", FieldConstantName(descriptor_->field(i)), + "number", StrCat(descriptor_->field(i)->number())); field_generators_.get(descriptor_->field(i)).GenerateMembers(printer); printer->Print("\n"); } - GenerateMessageSerializationMethods(printer); - GenerateParseFromMethods(printer); GenerateBuilder(printer); if (HasRequiredFields(descriptor_)) { // Memoizes whether the protocol buffer is fully initialized (has all - // required fields). -1 means not yet computed. 0 means false and 1 means - // true. - printer->Print( - "private byte memoizedIsInitialized = -1;\n"); + // required fields). 0 means false, 1 means true, and all other values + // mean not yet computed. + printer->Print("private byte memoizedIsInitialized = 2;\n"); } printer->Print( + "@java.lang.Override\n" "@java.lang.SuppressWarnings({\"unchecked\", \"fallthrough\"})\n" "protected final java.lang.Object dynamicMethod(\n" " com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n" @@ -359,95 +333,106 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Indent(); printer->Indent(); - printer->Print( - "case IS_INITIALIZED: {\n"); - printer->Indent(); - GenerateDynamicMethodIsInitialized(printer); - printer->Outdent(); - - printer->Print( - "}\n" - "case MAKE_IMMUTABLE: {\n"); - - printer->Indent(); - GenerateDynamicMethodMakeImmutable(printer); - printer->Outdent(); - - printer->Print( - "}\n" - "case NEW_BUILDER: {\n"); + printer->Print("case NEW_BUILDER: {\n"); printer->Indent(); GenerateDynamicMethodNewBuilder(printer); printer->Outdent(); printer->Print( - "}\n" - "case VISIT: {\n"); + "}\n" + "case BUILD_MESSAGE_INFO: {\n"); printer->Indent(); - GenerateDynamicMethodVisit(printer); + GenerateDynamicMethodNewBuildMessageInfo(printer); printer->Outdent(); printer->Print( - "}\n" - "case MERGE_FROM_STREAM: {\n"); + "}\n" + "// fall through\n" + "case GET_DEFAULT_INSTANCE: {\n" + " return DEFAULT_INSTANCE;\n" + "}\n" + "case GET_PARSER: {\n" + // Generally one would use the lazy initialization holder pattern for + // manipulating static fields but that has exceptional cost on Android as + // it will generate an extra class for every message. Instead, use the + // double-check locking pattern which works just as well. + // + // The "parser" temporary mirrors the "PARSER" field to eliminate a read + // at the final return statement. + " com.google.protobuf.Parser<$classname$> parser = PARSER;\n" + " if (parser == null) {\n" + " synchronized ($classname$.class) {\n" + " parser = PARSER;\n" + " if (parser == null) {\n" + " parser =\n" + " new DefaultInstanceBasedParser<$classname$>(\n" + " DEFAULT_INSTANCE);\n" + " PARSER = parser;\n" + " }\n" + " }\n" + " }\n" + " return parser;\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); - printer->Indent(); - GenerateDynamicMethodMergeFromStream(printer); printer->Outdent(); - printer->Print( - "}\n" - "// fall through\n" - "case GET_DEFAULT_INSTANCE: {\n" - " return DEFAULT_INSTANCE;\n" - "}\n" - "case GET_PARSER: {\n" - // Generally one would use the lazy initialization holder pattern for - // manipulating static fields but that has exceptional cost on Android as - // it will generate an extra class for every message. Instead, use the - // double-check locking pattern which works just as well. - " if (PARSER == null) {" - " synchronized ($classname$.class) {\n" - " if (PARSER == null) {\n" - " PARSER = new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n" - " }\n" - " }\n" - " }\n" - " return PARSER;\n" - "}\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + if (HasRequiredFields(descriptor_)) { + printer->Print( + "}\n" + "case GET_MEMOIZED_IS_INITIALIZED: {\n" + " return memoizedIsInitialized;\n" + "}\n" + "case SET_MEMOIZED_IS_INITIALIZED: {\n" + " memoizedIsInitialized = (byte) (arg0 == null ? 0 : 1);\n" + " return null;\n" + "}\n"); + } else { + printer->Print( + "}\n" + "case GET_MEMOIZED_IS_INITIALIZED: {\n" + " return (byte) 1;\n" + "}\n" + "case SET_MEMOIZED_IS_INITIALIZED: {\n" + " return null;\n" + "}\n"); + } printer->Outdent(); - printer->Outdent(); - printer->Print( - " }\n" - " throw new UnsupportedOperationException();\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + " }\n" + " throw new UnsupportedOperationException();\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Print( - "\n" - "// @@protoc_insertion_point(class_scope:$full_name$)\n", - "full_name", descriptor_->full_name()); - + "\n" + "// @@protoc_insertion_point(class_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); // Carefully initialize the default instance in such a way that it doesn't // conflict with other initialization. - printer->Print( - "private static final $classname$ DEFAULT_INSTANCE;\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + printer->Print("private static final $classname$ DEFAULT_INSTANCE;\n", + "classname", + name_resolver_->GetImmutableClassName(descriptor_)); + + printer->Print( + "static {\n" + " $classname$ defaultInstance = new $classname$();\n" + " // New instances are implicitly immutable so no need to make\n" + " // immutable.\n" + " DEFAULT_INSTANCE = defaultInstance;\n" + // Register the default instance in a map. This map will be used by + // experimental runtime to lookup default instance given a class instance + // without using Java reflection. + " com.google.protobuf.GeneratedMessageLite.registerDefaultInstance(\n" + " $classname$.class, defaultInstance);\n" + "}\n" + "\n", + "classname", descriptor_->name()); - printer->Print( - "static {\n" - " DEFAULT_INSTANCE = new $classname$();\n" - " DEFAULT_INSTANCE.makeImmutable();\n" - "}\n" - "\n", - "classname", descriptor_->name()); printer->Print( "public static $classname$ getDefaultInstance() {\n" " return DEFAULT_INSTANCE;\n" @@ -455,6 +440,17 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); + // 'of' method for Wrappers + if (IsWrappersProtoFile(descriptor_->file())) { + printer->Print( + "public static $classname$ of($field_type$ value) {\n" + " return newBuilder().setValue(value).build();\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "field_type", PrimitiveTypeName(GetJavaType(descriptor_->field(0)))); + } + GenerateParser(printer); // Extensions must be declared after the DEFAULT_INSTANCE is initialized @@ -469,224 +465,203 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Print("}\n\n"); } -// =================================================================== +void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuildMessageInfo( + io::Printer* printer) { + printer->Indent(); -void ImmutableMessageLiteGenerator:: -GenerateMessageSerializationMethods(io::Printer* printer) { - google::protobuf::scoped_array sorted_fields( - SortFieldsByNumber(descriptor_)); + // Collect field info into a sequence of UTF-16 chars. It will be embedded + // as a Java string in the generated code. + std::vector chars; - std::vector sorted_extensions; - for (int i = 0; i < descriptor_->extension_range_count(); ++i) { - sorted_extensions.push_back(descriptor_->extension_range(i)); + int flags = 0; + if (IsProto2(descriptor_->file())) { + flags |= 0x1; } - std::sort(sorted_extensions.begin(), sorted_extensions.end(), - ExtensionRangeOrdering()); - - printer->Print( - "public void writeTo(com.google.protobuf.CodedOutputStream output)\n" - " throws java.io.IOException {\n"); - printer->Indent(); - if (HasPackedFields(descriptor_)) { - // writeTo(CodedOutputStream output) might be invoked without - // getSerializedSize() ever being called, but we need the memoized - // sizes in case this message has packed fields. Rather than emit checks for - // each packed field, just call getSerializedSize() up front. - // In most cases, getSerializedSize() will have already been called anyway - // by one of the wrapper writeTo() methods, making this call cheap. - printer->Print( - "getSerializedSize();\n"); + if (descriptor_->options().message_set_wire_format()) { + flags |= 0x2; } + WriteIntToUtf16CharSequence(flags, &chars); + WriteIntToUtf16CharSequence(descriptor_->field_count(), &chars); - if (descriptor_->extension_range_count() > 0) { - if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "com.google.protobuf.GeneratedMessageLite\n" - " .ExtendableMessage<$classname$, $classname$.Builder>\n" - " .ExtensionWriter extensionWriter =\n" - " newMessageSetExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } else { + if (descriptor_->field_count() == 0) { + printer->Print("java.lang.Object[] objects = null;"); + } else { + // A single array of all fields (including oneof, oneofCase, hasBits). + printer->Print("java.lang.Object[] objects = new java.lang.Object[] {\n"); + printer->Indent(); + + // Record the number of oneofs. + WriteIntToUtf16CharSequence(oneofs_.size(), &chars); + for (auto oneof : oneofs_) { printer->Print( - "com.google.protobuf.GeneratedMessageLite\n" - " .ExtendableMessage<$classname$, $classname$.Builder>\n" - " .ExtensionWriter extensionWriter =\n" - " newExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "\"$oneof_name$_\",\n" + "\"$oneof_name$Case_\",\n", + "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name); } - } - // Merge the fields and the extension ranges, both sorted by field number. - for (int i = 0, j = 0; - i < descriptor_->field_count() || j < sorted_extensions.size(); - ) { - if (i == descriptor_->field_count()) { - GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]); - } else if (j == sorted_extensions.size()) { - GenerateSerializeOneField(printer, sorted_fields[i++]); - } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) { - GenerateSerializeOneField(printer, sorted_fields[i++]); - } else { - GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]); + // Integers for bit fields. + int total_bits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + total_bits += + field_generators_.get(descriptor_->field(i)).GetNumBitsForMessage(); } - } + int total_ints = (total_bits + 31) / 32; + for (int i = 0; i < total_ints; i++) { + printer->Print("\"$bit_field_name$\",\n", "bit_field_name", + GetBitFieldName(i)); + } + WriteIntToUtf16CharSequence(total_ints, &chars); - if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "unknownFields.writeAsMessageSetTo(output);\n"); - } else { - printer->Print( - "unknownFields.writeTo(output);\n"); - } + int map_count = 0; + int repeated_count = 0; + std::unique_ptr sorted_fields( + SortFieldsByNumber(descriptor_)); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = sorted_fields[i]; + if (field->is_map()) { + map_count++; + } else if (field->is_repeated()) { + repeated_count++; + } + } - printer->Outdent(); - printer->Print( - "}\n" - "\n" - "public int getSerializedSize() {\n" - " int size = memoizedSerializedSize;\n" - " if (size != -1) return size;\n" - "\n" - " size = 0;\n"); - printer->Indent(); + WriteIntToUtf16CharSequence(sorted_fields[0]->number(), &chars); + WriteIntToUtf16CharSequence( + sorted_fields[descriptor_->field_count() - 1]->number(), &chars); + WriteIntToUtf16CharSequence(descriptor_->field_count(), &chars); + WriteIntToUtf16CharSequence(map_count, &chars); + WriteIntToUtf16CharSequence(repeated_count, &chars); - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer); - } + std::vector fields_for_is_initialized_check; + for (int i = 0; i < descriptor_->field_count(); i++) { + if (descriptor_->field(i)->is_required() || + (GetJavaType(descriptor_->field(i)) == JAVATYPE_MESSAGE && + HasRequiredFields(descriptor_->field(i)->message_type()))) { + fields_for_is_initialized_check.push_back(descriptor_->field(i)); + } + } + WriteIntToUtf16CharSequence(fields_for_is_initialized_check.size(), &chars); - if (descriptor_->extension_range_count() > 0) { - if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "size += extensionsSerializedSizeAsMessageSet();\n"); - } else { - printer->Print( - "size += extensionsSerializedSize();\n"); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = sorted_fields[i]; + field_generators_.get(field).GenerateFieldInfo(printer, &chars); } + printer->Outdent(); + printer->Print("};\n"); } - if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "size += unknownFields.getSerializedSizeAsMessageSet();\n"); - } else { - printer->Print( - "size += unknownFields.getSerializedSize();\n"); + printer->Print("java.lang.String info =\n"); + std::string line; + for (size_t i = 0; i < chars.size(); i++) { + uint16 code = chars[i]; + EscapeUtf16ToString(code, &line); + if (line.size() >= 80) { + printer->Print(" \"$string$\" +\n", "string", line); + line.clear(); + } } + printer->Print(" \"$string$\";\n", "string", line); + printer->Print("return newMessageInfo(DEFAULT_INSTANCE, info, objects);\n"); printer->Outdent(); - printer->Print( - " memoizedSerializedSize = size;\n" - " return size;\n" - "}\n" - "\n"); -} - -void ImmutableMessageLiteGenerator:: -GenerateParseFromMethods(io::Printer* printer) { - // Note: These are separate from GenerateMessageSerializationMethods() - // because they need to be generated even for messages that are optimized - // for code size. - printer->Print( - "public static $classname$ parseFrom(\n" - " java.nio.ByteBuffer data)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" - " DEFAULT_INSTANCE, data);\n" - "}\n" - "public static $classname$ parseFrom(\n" - " java.nio.ByteBuffer data,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" - " DEFAULT_INSTANCE, data, extensionRegistry);\n" - "}\n" - "public static $classname$ parseFrom(\n" - " com.google.protobuf.ByteString data)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" - " DEFAULT_INSTANCE, data);\n" - "}\n" - "public static $classname$ parseFrom(\n" - " com.google.protobuf.ByteString data,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" - " DEFAULT_INSTANCE, data, extensionRegistry);\n" - "}\n" - "public static $classname$ parseFrom(byte[] data)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" - " DEFAULT_INSTANCE, data);\n" - "}\n" - "public static $classname$ parseFrom(\n" - " byte[] data,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" - " DEFAULT_INSTANCE, data, extensionRegistry);\n" - "}\n" - "public static $classname$ parseFrom(java.io.InputStream input)\n" - " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" - " DEFAULT_INSTANCE, input);\n" - "}\n" - "public static $classname$ parseFrom(\n" - " java.io.InputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" - " DEFAULT_INSTANCE, input, extensionRegistry);\n" - "}\n" - "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n" - " throws java.io.IOException {\n" - " return parseDelimitedFrom(DEFAULT_INSTANCE, input);\n" - "}\n" - "public static $classname$ parseDelimitedFrom(\n" - " java.io.InputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws java.io.IOException {\n" - " return parseDelimitedFrom(DEFAULT_INSTANCE, input, extensionRegistry);\n" - "}\n" - "public static $classname$ parseFrom(\n" - " com.google.protobuf.CodedInputStream input)\n" - " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" - " DEFAULT_INSTANCE, input);\n" - "}\n" - "public static $classname$ parseFrom(\n" - " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" - " DEFAULT_INSTANCE, input, extensionRegistry);\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); } -void ImmutableMessageLiteGenerator::GenerateSerializeOneField( - io::Printer* printer, const FieldDescriptor* field) { - field_generators_.get(field).GenerateSerializationCode(printer); -} +// =================================================================== -void ImmutableMessageLiteGenerator::GenerateSerializeOneExtensionRange( - io::Printer* printer, const Descriptor::ExtensionRange* range) { +void ImmutableMessageLiteGenerator::GenerateParseFromMethods( + io::Printer* printer) { printer->Print( - "extensionWriter.writeUntil($end$, output);\n", - "end", SimpleItoa(range->end)); + "public static $classname$ parseFrom(\n" + " java.nio.ByteBuffer data)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, data);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " java.nio.ByteBuffer data,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, data, extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " com.google.protobuf.ByteString data)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, data);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " com.google.protobuf.ByteString data,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, data, extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(byte[] data)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, data);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " byte[] data,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, data, extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(java.io.InputStream input)\n" + " throws java.io.IOException {\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, input);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " java.io.InputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, input, extensionRegistry);\n" + "}\n" + "public static $classname$ parseDelimitedFrom(java.io.InputStream " + "input)\n" + " throws java.io.IOException {\n" + " return parseDelimitedFrom(DEFAULT_INSTANCE, input);\n" + "}\n" + "public static $classname$ parseDelimitedFrom(\n" + " java.io.InputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " return parseDelimitedFrom(DEFAULT_INSTANCE, input, " + "extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " com.google.protobuf.CodedInputStream input)\n" + " throws java.io.IOException {\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, input);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " com.google.protobuf.CodedInputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " return com.google.protobuf.GeneratedMessageLite.parseFrom(\n" + " DEFAULT_INSTANCE, input, extensionRegistry);\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } // =================================================================== void ImmutableMessageLiteGenerator::GenerateBuilder(io::Printer* printer) { printer->Print( - "public static Builder newBuilder() {\n" - " return DEFAULT_INSTANCE.toBuilder();\n" - "}\n" - "public static Builder newBuilder($classname$ prototype) {\n" - " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "public static Builder newBuilder() {\n" + " return (Builder) DEFAULT_INSTANCE.createBuilder();\n" + "}\n" + "public static Builder newBuilder($classname$ prototype) {\n" + " return (Builder) DEFAULT_INSTANCE.createBuilder(prototype);\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); MessageBuilderLiteGenerator builderGenerator(descriptor_, context_); builderGenerator.Generate(printer); @@ -694,403 +669,43 @@ void ImmutableMessageLiteGenerator::GenerateBuilder(io::Printer* printer) { // =================================================================== -void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized( - io::Printer* printer) { - // Returns null for false, DEFAULT_INSTANCE for true. - if (!HasRequiredFields(descriptor_)) { - printer->Print("return DEFAULT_INSTANCE;\n"); - return; - } - - // Don't directly compare to -1 to avoid an Android x86 JIT bug. - printer->Print( - "byte isInitialized = memoizedIsInitialized;\n" - "if (isInitialized == 1) return DEFAULT_INSTANCE;\n" - "if (isInitialized == 0) return null;\n" - "\n" - "boolean shouldMemoize = ((Boolean) arg0).booleanValue();\n"); - - // Check that all required fields in this message are set. - // TODO(kenton): We can optimize this when we switch to putting all the - // "has" fields into a single bitfield. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); - - if (field->is_required()) { - printer->Print( - "if (!has$name$()) {\n" - " if (shouldMemoize) {\n" - " memoizedIsInitialized = 0;\n" - " }\n" - " return null;\n" - "}\n", - "name", info->capitalized_name); - } - } - - // Now check that all embedded messages are initialized. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); - if (GetJavaType(field) == JAVATYPE_MESSAGE && - HasRequiredFields(field->message_type())) { - switch (field->label()) { - case FieldDescriptor::LABEL_REQUIRED: - printer->Print( - "if (!get$name$().isInitialized()) {\n" - " if (shouldMemoize) {\n" - " memoizedIsInitialized = 0;\n" - " }\n" - " return null;\n" - "}\n", - "type", name_resolver_->GetImmutableClassName( - field->message_type()), - "name", info->capitalized_name); - break; - case FieldDescriptor::LABEL_OPTIONAL: - if (!SupportFieldPresence(descriptor_->file()) && - field->containing_oneof() != NULL) { - const OneofDescriptor* oneof = field->containing_oneof(); - const OneofGeneratorInfo* oneof_info = - context_->GetOneofGeneratorInfo(oneof); - printer->Print( - "if ($oneof_name$Case_ == $field_number$) {\n", - "oneof_name", oneof_info->name, - "field_number", SimpleItoa(field->number())); - } else { - printer->Print( - "if (has$name$()) {\n", - "name", info->capitalized_name); - } - printer->Print( - " if (!get$name$().isInitialized()) {\n" - " if (shouldMemoize) {\n" - " memoizedIsInitialized = 0;\n" - " }\n" - " return null;\n" - " }\n" - "}\n", - "name", info->capitalized_name); - break; - case FieldDescriptor::LABEL_REPEATED: - if (IsMapEntry(field->message_type())) { - printer->Print( - "for ($type$ item : get$name$Map().values()) {\n" - " if (!item.isInitialized()) {\n" - " if (shouldMemoize) {\n" - " memoizedIsInitialized = 0;\n" - " }\n" - " return null;\n" - " }\n" - "}\n", - "type", MapValueImmutableClassdName(field->message_type(), - name_resolver_), - "name", info->capitalized_name); - } else { - printer->Print( - "for (int i = 0; i < get$name$Count(); i++) {\n" - " if (!get$name$(i).isInitialized()) {\n" - " if (shouldMemoize) {\n" - " memoizedIsInitialized = 0;\n" - " }\n" - " return null;\n" - " }\n" - "}\n", - "type", name_resolver_->GetImmutableClassName( - field->message_type()), - "name", info->capitalized_name); - } - break; - } - } - } - - if (descriptor_->extension_range_count() > 0) { - printer->Print( - "if (!extensionsAreInitialized()) {\n" - " if (shouldMemoize) {\n" - " memoizedIsInitialized = 0;\n" - " }\n" - " return null;\n" - "}\n"); - } - - printer->Print( - "if (shouldMemoize) memoizedIsInitialized = 1;\n"); - - printer->Print( - "return DEFAULT_INSTANCE;\n" - "\n"); -} - -// =================================================================== - -void ImmutableMessageLiteGenerator::GenerateDynamicMethodMakeImmutable( - io::Printer* printer) { - - // Output generation code for each field. - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateDynamicMethodMakeImmutableCode(printer); - } - - printer->Print( - "return null;\n"); -} - -// =================================================================== - void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuilder( io::Printer* printer) { - printer->Print( - "return new Builder();\n"); -} - -// =================================================================== - -void ImmutableMessageLiteGenerator::GenerateDynamicMethodVisit( - io::Printer* printer) { - printer->Print( - "Visitor visitor = (Visitor) arg0;\n" - "$classname$ other = ($classname$) arg1;\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - - for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - field_generators_.get( - descriptor_->field(i)).GenerateVisitCode(printer); - } - } - - // Merge oneof fields. - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - printer->Print( - "switch (other.get$oneof_capitalized_name$Case()) {\n", - "oneof_capitalized_name", - context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case $field_name$: {\n", - "field_name", - ToUpper(field->name())); - printer->Indent(); - field_generators_.get(field).GenerateVisitCode(printer); - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); - } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" - " visitor.visitOneofNotSet($oneof_name$Case_ != 0);\n" - " break;\n" - "}\n", - "cap_oneof_name", - ToUpper(context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name), - "oneof_name", - context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name); - printer->Outdent(); - printer->Print( - "}\n"); - } - - printer->Print( - "if (visitor == com.google.protobuf.GeneratedMessageLite.MergeFromVisitor\n" - " .INSTANCE) {\n"); - printer->Indent(); - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - const OneofDescriptor* field = descriptor_->oneof_decl(i); - printer->Print( - "if (other.$oneof_name$Case_ != 0) {\n" - " $oneof_name$Case_ = other.$oneof_name$Case_;\n" - "}\n", - "oneof_name", context_->GetOneofGeneratorInfo(field)->name); - } - - if (GenerateHasBits(descriptor_)) { - // Integers for bit fields. - int totalBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - totalBits += field_generators_.get(descriptor_->field(i)) - .GetNumBitsForMessage(); - } - int totalInts = (totalBits + 31) / 32; - - for (int i = 0; i < totalInts; i++) { - printer->Print( - "$bit_field_name$ |= other.$bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } - } - printer->Outdent(); - printer->Print( - "}\n"); - - - printer->Print( - "return this;\n"); + printer->Print("return new Builder();\n"); } // =================================================================== -void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFromStream( +void ImmutableMessageLiteGenerator::GenerateExtensionRegistrationCode( io::Printer* printer) { - printer->Print( - "com.google.protobuf.CodedInputStream input =\n" - " (com.google.protobuf.CodedInputStream) arg0;\n" - "com.google.protobuf.ExtensionRegistryLite extensionRegistry =\n" - " (com.google.protobuf.ExtensionRegistryLite) arg1;\n"); - printer->Print( - "try {\n"); - printer->Indent(); - printer->Print( - "boolean done = false;\n" - "while (!done) {\n"); - printer->Indent(); - - printer->Print( - "int tag = input.readTag();\n" - "switch (tag) {\n"); - printer->Indent(); - - printer->Print( - "case 0:\n" // zero signals EOF / limit reached - " done = true;\n" - " break;\n"); - - if (descriptor_->extension_range_count() > 0) { - if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "default: {\n" - " if (!parseUnknownFieldAsMessageSet(\n" - " getDefaultInstanceForType(), input, extensionRegistry,\n" - " tag)) {\n" - " done = true;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); - } else { - printer->Print( - "default: {\n" - " if (!parseUnknownField(getDefaultInstanceForType(),\n" - " input, extensionRegistry, tag)) {\n" - " done = true;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); - } - } else { - printer->Print( - "default: {\n" - " if (!parseUnknownField(tag, input)) {\n" - " done = true;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); - } - - google::protobuf::scoped_array sorted_fields( - SortFieldsByNumber(descriptor_)); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = sorted_fields[i]; - uint32 tag = WireFormatLite::MakeTag(field->number(), - WireFormat::WireTypeForFieldType(field->type())); - - printer->Print( - "case $tag$: {\n", - "tag", SimpleItoa(static_cast(tag))); - printer->Indent(); - - field_generators_.get(field).GenerateParsingCode(printer); - - printer->Outdent(); - printer->Print( - " break;\n" - "}\n"); - - if (field->is_packable()) { - // To make packed = true wire compatible, we generate parsing code from a - // packed version of this field regardless of field->options().packed(). - uint32 packed_tag = WireFormatLite::MakeTag(field->number(), - WireFormatLite::WIRETYPE_LENGTH_DELIMITED); - printer->Print( - "case $tag$: {\n", - "tag", SimpleItoa(static_cast(packed_tag))); - printer->Indent(); - - field_generators_.get(field).GenerateParsingCodeFromPacked(printer); - - printer->Outdent(); - printer->Print( - " break;\n" - "}\n"); - } - } - - printer->Outdent(); - printer->Outdent(); - printer->Print( - " }\n" // switch (tag) - "}\n"); // while (!done) - - printer->Outdent(); - printer->Print( - "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " throw new RuntimeException(e.setUnfinishedMessage(this));\n" - "} catch (java.io.IOException e) {\n" - " throw new RuntimeException(\n" - " new com.google.protobuf.InvalidProtocolBufferException(\n" - " e.getMessage()).setUnfinishedMessage(this));\n" - "} finally {\n"); - printer->Indent(); - - printer->Outdent(); - printer->Print( - "}\n"); // finally -} - -// =================================================================== - -void ImmutableMessageLiteGenerator:: -GenerateExtensionRegistrationCode(io::Printer* printer) { for (int i = 0; i < descriptor_->extension_count(); i++) { ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_) - .GenerateRegistrationCode(printer); + .GenerateRegistrationCode(printer); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_) - .GenerateExtensionRegistrationCode(printer); + .GenerateExtensionRegistrationCode(printer); } } // =================================================================== -void ImmutableMessageLiteGenerator:: -GenerateConstructor(io::Printer* printer) { - printer->Print( - "private $classname$() {\n", - "classname", descriptor_->name()); +void ImmutableMessageLiteGenerator::GenerateConstructor(io::Printer* printer) { + printer->Print("private $classname$() {\n", "classname", descriptor_->name()); printer->Indent(); // Initialize all fields to default. GenerateInitializers(printer); printer->Outdent(); - printer->Print( - "}\n"); + printer->Print("}\n"); } // =================================================================== void ImmutableMessageLiteGenerator::GenerateParser(io::Printer* printer) { printer->Print( - "private static volatile com.google.protobuf.Parser<$classname$> PARSER;\n" + "private static volatile com.google.protobuf.Parser<$classname$> " + "PARSER;\n" "\n" "public static com.google.protobuf.Parser<$classname$> parser() {\n" " return DEFAULT_INSTANCE.getParserForType();\n" @@ -1101,7 +716,7 @@ void ImmutableMessageLiteGenerator::GenerateParser(io::Printer* printer) { // =================================================================== void ImmutableMessageLiteGenerator::GenerateInitializers(io::Printer* printer) { for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { + if (!IsRealOneof(descriptor_->field(i))) { field_generators_.get(descriptor_->field(i)) .GenerateInitializationCode(printer); } diff --git a/src/google/protobuf/compiler/java/java_message_lite.h b/src/google/protobuf/compiler/java/java_message_lite.h index 1e319c6d6e69d..5290b1e641201 100644 --- a/src/google/protobuf/compiler/java/java_message_lite.h +++ b/src/google/protobuf/compiler/java/java_message_lite.h @@ -35,8 +35,8 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__ -#include #include +#include #include #include @@ -53,29 +53,19 @@ class ImmutableMessageLiteGenerator : public MessageGenerator { virtual void Generate(io::Printer* printer); virtual void GenerateInterface(io::Printer* printer); virtual void GenerateExtensionRegistrationCode(io::Printer* printer); - virtual void GenerateStaticVariables( - io::Printer* printer, int* bytecode_estimate); + virtual void GenerateStaticVariables(io::Printer* printer, + int* bytecode_estimate); virtual int GenerateStaticVariableInitializers(io::Printer* printer); private: - - void GenerateMessageSerializationMethods(io::Printer* printer); void GenerateParseFromMethods(io::Printer* printer); - void GenerateSerializeOneField(io::Printer* printer, - const FieldDescriptor* field); - void GenerateSerializeOneExtensionRange( - io::Printer* printer, const Descriptor::ExtensionRange* range); void GenerateBuilder(io::Printer* printer); - void GenerateDynamicMethodIsInitialized(io::Printer* printer); - void GenerateDynamicMethodMakeImmutable(io::Printer* printer); - void GenerateDynamicMethodVisit(io::Printer* printer); - void GenerateDynamicMethodMergeFromStream(io::Printer* printer); void GenerateDynamicMethodNewBuilder(io::Printer* printer); void GenerateInitializers(io::Printer* printer); - void GenerateEqualsAndHashCode(io::Printer* printer); void GenerateParser(io::Printer* printer); void GenerateConstructor(io::Printer* printer); + void GenerateDynamicMethodNewBuildMessageInfo(io::Printer* printer); Context* context_; ClassNameResolver* name_resolver_; @@ -87,6 +77,6 @@ class ImmutableMessageLiteGenerator : public MessageGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_name_resolver.cc b/src/google/protobuf/compiler/java/java_name_resolver.cc index 1673b4ee7619d..ed33dae5ff57d 100644 --- a/src/google/protobuf/compiler/java/java_name_resolver.cc +++ b/src/google/protobuf/compiler/java/java_name_resolver.cc @@ -33,8 +33,9 @@ #include #include - #include +#include +#include #include namespace google { @@ -52,8 +53,8 @@ const char* kOuterClassNameSuffix = "OuterClass"; // Full name : foo.Bar.Baz // Package name: foo // After strip : Bar.Baz -string StripPackageName(const string& full_name, - const FileDescriptor* file) { +std::string StripPackageName(const std::string& full_name, + const FileDescriptor* file) { if (file->package().empty()) { return full_name; } else { @@ -63,46 +64,62 @@ string StripPackageName(const string& full_name, } // Get the name of a message's Java class without package name prefix. -string ClassNameWithoutPackage(const Descriptor* descriptor, - bool immutable) { - return StripPackageName(descriptor->full_name(), - descriptor->file()); +std::string ClassNameWithoutPackage(const Descriptor* descriptor, + bool immutable) { + return StripPackageName(descriptor->full_name(), descriptor->file()); } + // Get the name of an enum's Java class without package name prefix. -string ClassNameWithoutPackage(const EnumDescriptor* descriptor, - bool immutable) { +std::string ClassNameWithoutPackage(const EnumDescriptor* descriptor, + bool immutable) { // Doesn't append "Mutable" for enum type's name. const Descriptor* message_descriptor = descriptor->containing_type(); if (message_descriptor == NULL) { return descriptor->name(); } else { - return ClassNameWithoutPackage(message_descriptor, immutable) + - "." + descriptor->name(); + return ClassNameWithoutPackage(message_descriptor, immutable) + "." + + descriptor->name(); } } // Get the name of a service's Java class without package name prefix. -string ClassNameWithoutPackage(const ServiceDescriptor* descriptor, - bool immutable) { - string full_name = StripPackageName(descriptor->full_name(), - descriptor->file()); +std::string ClassNameWithoutPackage(const ServiceDescriptor* descriptor, + bool immutable) { + std::string full_name = + StripPackageName(descriptor->full_name(), descriptor->file()); // We don't allow nested service definitions. - GOOGLE_CHECK(full_name.find('.') == string::npos); + GOOGLE_CHECK(full_name.find('.') == std::string::npos); return full_name; } +// Return true if a and b are equals (case insensitive). +NameEquality CheckNameEquality(const std::string& a, const std::string& b) { + if (ToUpper(a) == ToUpper(b)) { + if (a == b) { + return NameEquality::EXACT_EQUAL; + } + return NameEquality::EQUAL_IGNORE_CASE; + } + return NameEquality::NO_MATCH; +} + // Check whether a given message or its nested types has the given class name. bool MessageHasConflictingClassName(const Descriptor* message, - const string& classname) { - if (message->name() == classname) return true; + const std::string& classname, + NameEquality equality_mode) { + if (CheckNameEquality(message->name(), classname) == equality_mode) { + return true; + } for (int i = 0; i < message->nested_type_count(); ++i) { - if (MessageHasConflictingClassName(message->nested_type(i), classname)) { + if (MessageHasConflictingClassName(message->nested_type(i), classname, + equality_mode)) { return true; } } for (int i = 0; i < message->enum_type_count(); ++i) { - if (message->enum_type(i)->name() == classname) { + if (CheckNameEquality(message->enum_type(i)->name(), classname) == + equality_mode) { return true; } } @@ -111,17 +128,15 @@ bool MessageHasConflictingClassName(const Descriptor* message, } // namespace -ClassNameResolver::ClassNameResolver() { -} +ClassNameResolver::ClassNameResolver() {} -ClassNameResolver::~ClassNameResolver() { -} +ClassNameResolver::~ClassNameResolver() {} -string ClassNameResolver::GetFileDefaultImmutableClassName( +std::string ClassNameResolver::GetFileDefaultImmutableClassName( const FileDescriptor* file) { - string basename; - string::size_type last_slash = file->name().find_last_of('/'); - if (last_slash == string::npos) { + std::string basename; + std::string::size_type last_slash = file->name().find_last_of('/'); + if (last_slash == std::string::npos) { basename = file->name(); } else { basename = file->name().substr(last_slash + 1); @@ -129,15 +144,16 @@ string ClassNameResolver::GetFileDefaultImmutableClassName( return UnderscoresToCamelCase(StripProto(basename), true); } -string ClassNameResolver::GetFileImmutableClassName( +std::string ClassNameResolver::GetFileImmutableClassName( const FileDescriptor* file) { - string& class_name = file_immutable_outer_class_names_[file]; + std::string& class_name = file_immutable_outer_class_names_[file]; if (class_name.empty()) { if (file->options().has_java_outer_classname()) { class_name = file->options().java_outer_classname(); } else { class_name = GetFileDefaultImmutableClassName(file); - if (HasConflictingClassName(file, class_name)) { + if (HasConflictingClassName(file, class_name, + NameEquality::EXACT_EQUAL)) { class_name += kOuterClassNameSuffix; } } @@ -145,9 +161,16 @@ string ClassNameResolver::GetFileImmutableClassName( return class_name; } -string ClassNameResolver::GetFileClassName(const FileDescriptor* file, - bool immutable) { - if (immutable) { +std::string ClassNameResolver::GetFileClassName(const FileDescriptor* file, + bool immutable) { + return GetFileClassName(file, immutable, false); +} + +std::string ClassNameResolver::GetFileClassName(const FileDescriptor* file, + bool immutable, bool kotlin) { + if (kotlin) { + return GetFileImmutableClassName(file) + "Kt"; + } else if (immutable) { return GetFileImmutableClassName(file); } else { return "Mutable" + GetFileImmutableClassName(file); @@ -156,115 +179,153 @@ string ClassNameResolver::GetFileClassName(const FileDescriptor* file, // Check whether there is any type defined in the proto file that has // the given class name. -bool ClassNameResolver::HasConflictingClassName( - const FileDescriptor* file, const string& classname) { +bool ClassNameResolver::HasConflictingClassName(const FileDescriptor* file, + const std::string& classname, + NameEquality equality_mode) { for (int i = 0; i < file->enum_type_count(); i++) { - if (file->enum_type(i)->name() == classname) { + if (CheckNameEquality(file->enum_type(i)->name(), classname) == + equality_mode) { return true; } } for (int i = 0; i < file->service_count(); i++) { - if (file->service(i)->name() == classname) { + if (CheckNameEquality(file->service(i)->name(), classname) == + equality_mode) { return true; } } for (int i = 0; i < file->message_type_count(); i++) { - if (MessageHasConflictingClassName(file->message_type(i), classname)) { + if (MessageHasConflictingClassName(file->message_type(i), classname, + equality_mode)) { return true; } } return false; } -string ClassNameResolver::GetDescriptorClassName( +std::string ClassNameResolver::GetDescriptorClassName( const FileDescriptor* descriptor) { return GetFileImmutableClassName(descriptor); } -string ClassNameResolver::GetClassName(const FileDescriptor* descriptor, - bool immutable) { - string result = FileJavaPackage(descriptor, immutable); +std::string ClassNameResolver::GetClassName(const FileDescriptor* descriptor, + bool immutable) { + return GetClassName(descriptor, immutable, false); +} + +std::string ClassNameResolver::GetClassName(const FileDescriptor* descriptor, + bool immutable, bool kotlin) { + std::string result = FileJavaPackage(descriptor, immutable); if (!result.empty()) result += '.'; - result += GetFileClassName(descriptor, immutable); + result += GetFileClassName(descriptor, immutable, kotlin); return result; } // Get the full name of a Java class by prepending the Java package name // or outer class name. -string ClassNameResolver::GetClassFullName(const string& name_without_package, - const FileDescriptor* file, - bool immutable, - bool multiple_files) { - string result; - if (multiple_files) { +std::string ClassNameResolver::GetClassFullName( + const std::string& name_without_package, const FileDescriptor* file, + bool immutable, bool is_own_file) { + return GetClassFullName(name_without_package, file, immutable, is_own_file, + false); +} + +std::string ClassNameResolver::GetClassFullName( + const std::string& name_without_package, const FileDescriptor* file, + bool immutable, bool is_own_file, bool kotlin) { + std::string result; + if (is_own_file) { result = FileJavaPackage(file, immutable); } else { - result = GetClassName(file, immutable); + result = GetClassName(file, immutable, kotlin); } if (!result.empty()) { result += '.'; } result += name_without_package; + if (kotlin) result += "Kt"; return result; } -string ClassNameResolver::GetClassName(const Descriptor* descriptor, - bool immutable) { - return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), - descriptor->file(), immutable, - MultipleJavaFiles(descriptor->file(), immutable)); +std::string ClassNameResolver::GetClassName(const Descriptor* descriptor, + bool immutable) { + return GetClassName(descriptor, immutable, false); } -string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor, - bool immutable) { - return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), - descriptor->file(), immutable, - MultipleJavaFiles(descriptor->file(), immutable)); +std::string ClassNameResolver::GetClassName(const Descriptor* descriptor, + bool immutable, bool kotlin) { + return GetClassFullName( + ClassNameWithoutPackage(descriptor, immutable), descriptor->file(), + immutable, MultipleJavaFiles(descriptor->file(), immutable), kotlin); +} + +std::string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor, + bool immutable) { + return GetClassName(descriptor, immutable, false); +} + +std::string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor, + bool immutable, bool kotlin) { + return GetClassFullName( + ClassNameWithoutPackage(descriptor, immutable), descriptor->file(), + immutable, MultipleJavaFiles(descriptor->file(), immutable), kotlin); } -string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor, - bool immutable) { +std::string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor, + bool immutable) { + return GetClassName(descriptor, immutable, false); +} + +std::string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor, + bool immutable, bool kotlin) { return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), descriptor->file(), immutable, - MultipleJavaFiles(descriptor->file(), immutable)); + IsOwnFile(descriptor, immutable), kotlin); } // Get the Java Class style full name of a message. -string ClassNameResolver::GetJavaClassFullName( - const string& name_without_package, - const FileDescriptor* file, +std::string ClassNameResolver::GetJavaClassFullName( + const std::string& name_without_package, const FileDescriptor* file, bool immutable) { - string result; + return GetJavaClassFullName(name_without_package, file, immutable, false); +} + +std::string ClassNameResolver::GetJavaClassFullName( + const std::string& name_without_package, const FileDescriptor* file, + bool immutable, bool kotlin) { + std::string result; if (MultipleJavaFiles(file, immutable)) { result = FileJavaPackage(file, immutable); if (!result.empty()) result += '.'; } else { - result = GetClassName(file, immutable); + result = GetClassName(file, immutable, kotlin); if (!result.empty()) result += '$'; } result += StringReplace(name_without_package, ".", "$", true); return result; } -string ClassNameResolver::GetExtensionIdentifierName( +std::string ClassNameResolver::GetExtensionIdentifierName( const FieldDescriptor* descriptor, bool immutable) { - return GetClassName(descriptor->containing_type(), immutable) + "." + - descriptor->name(); + return GetExtensionIdentifierName(descriptor, immutable, false); } +std::string ClassNameResolver::GetExtensionIdentifierName( + const FieldDescriptor* descriptor, bool immutable, bool kotlin) { + return GetClassName(descriptor->containing_type(), immutable, kotlin) + "." + + descriptor->name(); +} -string ClassNameResolver::GetJavaImmutableClassName( +std::string ClassNameResolver::GetJavaImmutableClassName( const Descriptor* descriptor) { - return GetJavaClassFullName( - ClassNameWithoutPackage(descriptor, true), - descriptor->file(), true); + return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, true), + descriptor->file(), true); } -string ClassNameResolver::GetJavaImmutableClassName( +std::string ClassNameResolver::GetJavaImmutableClassName( const EnumDescriptor* descriptor) { - return GetJavaClassFullName( - ClassNameWithoutPackage(descriptor, true), - descriptor->file(), true); + return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, true), + descriptor->file(), true); } diff --git a/src/google/protobuf/compiler/java/java_name_resolver.h b/src/google/protobuf/compiler/java/java_name_resolver.h index 28b049d1e53e1..8461df9009752 100644 --- a/src/google/protobuf/compiler/java/java_name_resolver.h +++ b/src/google/protobuf/compiler/java/java_name_resolver.h @@ -47,6 +47,9 @@ class ServiceDescriptor; namespace compiler { namespace java { +// Indicates how closely the two class names match. +enum NameEquality { NO_MATCH, EXACT_EQUAL, EQUAL_IGNORE_CASE }; + // Used to get the Java class related names for a given descriptor. It caches // the results to avoid redundant calculation across multiple name queries. // Thread-safety note: This class is *not* thread-safe. @@ -56,63 +59,80 @@ class ClassNameResolver { ~ClassNameResolver(); // Gets the unqualified outer class name for the file. - string GetFileClassName(const FileDescriptor* file, bool immutable); + std::string GetFileClassName(const FileDescriptor* file, bool immutable); + std::string GetFileClassName(const FileDescriptor* file, bool immutable, + bool kotlin); // Gets the unqualified immutable outer class name of a file. - string GetFileImmutableClassName(const FileDescriptor* file); + std::string GetFileImmutableClassName(const FileDescriptor* file); // Gets the unqualified default immutable outer class name of a file // (converted from the proto file's name). - string GetFileDefaultImmutableClassName(const FileDescriptor* file); + std::string GetFileDefaultImmutableClassName(const FileDescriptor* file); // Check whether there is any type defined in the proto file that has // the given class name. bool HasConflictingClassName(const FileDescriptor* file, - const string& classname); + const std::string& classname, + NameEquality equality_mode); // Gets the name of the outer class that holds descriptor information. // Descriptors are shared between immutable messages and mutable messages. // Since both of them are generated optionally, the descriptors need to be // put in another common place. - string GetDescriptorClassName(const FileDescriptor* file); + std::string GetDescriptorClassName(const FileDescriptor* file); // Gets the fully-qualified class name corresponding to the given descriptor. - string GetClassName(const Descriptor* descriptor, bool immutable); - string GetClassName(const EnumDescriptor* descriptor, bool immutable); - string GetClassName(const ServiceDescriptor* descriptor, bool immutable); - string GetClassName(const FileDescriptor* descriptor, bool immutable); - - template - string GetImmutableClassName(const DescriptorType* descriptor) { + std::string GetClassName(const Descriptor* descriptor, bool immutable); + std::string GetClassName(const Descriptor* descriptor, bool immutable, + bool kotlin); + std::string GetClassName(const EnumDescriptor* descriptor, bool immutable); + std::string GetClassName(const EnumDescriptor* descriptor, bool immutable, + bool kotlin); + std::string GetClassName(const ServiceDescriptor* descriptor, bool immutable); + std::string GetClassName(const ServiceDescriptor* descriptor, bool immutable, + bool kotlin); + std::string GetClassName(const FileDescriptor* descriptor, bool immutable); + std::string GetClassName(const FileDescriptor* descriptor, bool immutable, + bool kotlin); + + template + std::string GetImmutableClassName(const DescriptorType* descriptor) { return GetClassName(descriptor, true); } - template - string GetMutableClassName(const DescriptorType* descriptor) { + template + std::string GetMutableClassName(const DescriptorType* descriptor) { return GetClassName(descriptor, false); } // Gets the fully qualified name of an extension identifier. - string GetExtensionIdentifierName(const FieldDescriptor* descriptor, - bool immutable); + std::string GetExtensionIdentifierName(const FieldDescriptor* descriptor, + bool immutable); + std::string GetExtensionIdentifierName(const FieldDescriptor* descriptor, + bool immutable, bool kotlin); // Gets the fully qualified name for generated classes in Java convention. // Nested classes will be separated using '$' instead of '.' // For example: // com.package.OuterClass$OuterMessage$InnerMessage - string GetJavaImmutableClassName(const Descriptor* descriptor); - string GetJavaImmutableClassName(const EnumDescriptor* descriptor); + std::string GetJavaImmutableClassName(const Descriptor* descriptor); + std::string GetJavaImmutableClassName(const EnumDescriptor* descriptor); private: // Get the full name of a Java class by prepending the Java package name // or outer class name. - string GetClassFullName(const string& name_without_package, - const FileDescriptor* file, - bool immutable, - bool multiple_files); + std::string GetClassFullName(const std::string& name_without_package, + const FileDescriptor* file, bool immutable, + bool is_own_file); + std::string GetClassFullName(const std::string& name_without_package, + const FileDescriptor* file, bool immutable, + bool is_own_file, bool kotlin); // Get the Java Class style full name of a message. - string GetJavaClassFullName( - const string& name_without_package, - const FileDescriptor* file, - bool immutable); + std::string GetJavaClassFullName(const std::string& name_without_package, + const FileDescriptor* file, bool immutable); + std::string GetJavaClassFullName(const std::string& name_without_package, + const FileDescriptor* file, bool immutable, + bool kotlin); // Caches the result to provide better performance. - std::map file_immutable_outer_class_names_; + std::map + file_immutable_outer_class_names_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ClassNameResolver); }; @@ -120,6 +140,6 @@ class ClassNameResolver { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__ diff --git a/src/google/protobuf/compiler/java/java_names.h b/src/google/protobuf/compiler/java/java_names.h index 0d6143353a000..313ace4feb058 100644 --- a/src/google/protobuf/compiler/java/java_names.h +++ b/src/google/protobuf/compiler/java/java_names.h @@ -46,6 +46,7 @@ namespace protobuf { class Descriptor; class EnumDescriptor; class FileDescriptor; +class FieldDescriptor; class ServiceDescriptor; namespace compiler { @@ -56,32 +57,44 @@ namespace java { // // Returns: // The fully-qualified Java class name. -string ClassName(const Descriptor* descriptor); +std::string ClassName(const Descriptor* descriptor); // Requires: // descriptor != NULL // // Returns: // The fully-qualified Java class name. -string ClassName(const EnumDescriptor* descriptor); +std::string ClassName(const EnumDescriptor* descriptor); // Requires: // descriptor != NULL // // Returns: // The fully-qualified Java class name. -string ClassName(const FileDescriptor* descriptor); +std::string ClassName(const FileDescriptor* descriptor); // Requires: // descriptor != NULL // // Returns: // The fully-qualified Java class name. -string ClassName(const ServiceDescriptor* descriptor); +std::string ClassName(const ServiceDescriptor* descriptor); + +// Requires: +// descriptor != NULL +// +// Returns: +// Java package name. +std::string FileJavaPackage(const FileDescriptor* descriptor); + +// Requires: +// descriptor != NULL +// Returns: +// Capitalized camel case name field name. +std::string CapitalizedFieldName(const FieldDescriptor* descriptor); } // namespace java } // namespace compiler } // namespace protobuf } // namespace google - #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_NAMES_H__ diff --git a/src/google/protobuf/compiler/java/java_options.h b/src/google/protobuf/compiler/java/java_options.h index e4e7d5e266bf9..6c29be1500b89 100644 --- a/src/google/protobuf/compiler/java/java_options.h +++ b/src/google/protobuf/compiler/java/java_options.h @@ -68,6 +68,6 @@ struct Options { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_OPTIONS_H__ diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc index 3e4910c88ab10..3bdd53bff67e4 100644 --- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc +++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc @@ -35,17 +35,13 @@ // worth. #include -#ifndef _SHARED_PTR_H -#include -#endif +#include +#include #include #include -#include #include - -#include -#include +#include #include #include @@ -61,10 +57,9 @@ class TestGenerator : public CodeGenerator { ~TestGenerator() {} virtual bool Generate(const FileDescriptor* file, - const string& parameter, - GeneratorContext* context, - string* error) const { - string filename = "Test.java"; + const std::string& parameter, GeneratorContext* context, + std::string* error) const { + std::string filename = "Test.java"; TryInsert(filename, "outer_class_scope", context); TryInsert(filename, "class_scope:foo.Bar", context); TryInsert(filename, "class_scope:foo.Bar.Baz", context); @@ -74,9 +69,10 @@ class TestGenerator : public CodeGenerator { return true; } - void TryInsert(const string& filename, const string& insertion_point, + void TryInsert(const std::string& filename, + const std::string& insertion_point, GeneratorContext* context) const { - google::protobuf::scoped_ptr output( + std::unique_ptr output( context->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); @@ -98,7 +94,7 @@ TEST(JavaPluginTest, PluginTest) { "enum Qux { BLAH = 1; }\n", true)); - google::protobuf::compiler::CommandLineInterface cli; + CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); JavaGenerator java_generator; @@ -106,17 +102,12 @@ TEST(JavaPluginTest, PluginTest) { cli.RegisterGenerator("--java_out", &java_generator, ""); cli.RegisterGenerator("--test_out", &test_generator, ""); - string proto_path = "-I" + TestTempDir(); - string java_out = "--java_out=" + TestTempDir(); - string test_out = "--test_out=" + TestTempDir(); + std::string proto_path = "-I" + TestTempDir(); + std::string java_out = "--java_out=" + TestTempDir(); + std::string test_out = "--test_out=" + TestTempDir(); - const char* argv[] = { - "protoc", - proto_path.c_str(), - java_out.c_str(), - test_out.c_str(), - "test.proto" - }; + const char* argv[] = {"protoc", proto_path.c_str(), java_out.c_str(), + test_out.c_str(), "test.proto"}; EXPECT_EQ(0, cli.Run(5, argv)); } diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index 074a6be86788f..8bc68b7b22c55 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -57,27 +57,63 @@ using internal::WireFormatLite; namespace { void SetPrimitiveVariables(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, + int messageBitIndex, int builderBitIndex, const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, - std::map* variables) { + std::map* variables) { SetCommonFieldVariables(descriptor, info, variables); + JavaType javaType = GetJavaType(descriptor); - (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); - (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); + (*variables)["type"] = PrimitiveTypeName(javaType); + (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType); (*variables)["field_type"] = (*variables)["type"]; - (*variables)["field_list_type"] = "java.util.List<" + - (*variables)["boxed_type"] + ">"; - (*variables)["empty_list"] = "java.util.Collections.emptyList()"; + + if (javaType == JAVATYPE_BOOLEAN || javaType == JAVATYPE_DOUBLE || + javaType == JAVATYPE_FLOAT || javaType == JAVATYPE_INT || + javaType == JAVATYPE_LONG) { + std::string capitalized_type = UnderscoresToCamelCase( + PrimitiveTypeName(javaType), /*cap_first_letter=*/true); + (*variables)["field_list_type"] = + "com.google.protobuf.Internal." + capitalized_type + "List"; + (*variables)["empty_list"] = "empty" + capitalized_type + "List()"; + (*variables)["create_list"] = "new" + capitalized_type + "List()"; + (*variables)["mutable_copy_list"] = + "mutableCopy(" + (*variables)["name"] + "_)"; + (*variables)["name_make_immutable"] = + (*variables)["name"] + "_.makeImmutable()"; + (*variables)["repeated_get"] = + (*variables)["name"] + "_.get" + capitalized_type; + (*variables)["repeated_add"] = + (*variables)["name"] + "_.add" + capitalized_type; + (*variables)["repeated_set"] = + (*variables)["name"] + "_.set" + capitalized_type; + } else { + (*variables)["field_list_type"] = + "java.util.List<" + (*variables)["boxed_type"] + ">"; + (*variables)["create_list"] = + "new java.util.ArrayList<" + (*variables)["boxed_type"] + ">()"; + (*variables)["mutable_copy_list"] = "new java.util.ArrayList<" + + (*variables)["boxed_type"] + ">(" + + (*variables)["name"] + "_)"; + (*variables)["empty_list"] = "java.util.Collections.emptyList()"; + (*variables)["name_make_immutable"] = + (*variables)["name"] + "_ = java.util.Collections.unmodifiableList(" + + (*variables)["name"] + "_)"; + (*variables)["repeated_get"] = (*variables)["name"] + "_.get"; + (*variables)["repeated_add"] = (*variables)["name"] + "_.add"; + (*variables)["repeated_set"] = (*variables)["name"] + "_.set"; + } + (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); - (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ? - "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver)); + (*variables)["default_init"] = + IsDefaultValueJavaDefault(descriptor) + ? "" + : ("= " + ImmutableDefaultValue(descriptor, name_resolver)); (*variables)["capitalized_type"] = GetCapitalizedType(descriptor, /* immutable = */ true); (*variables)["tag"] = - SimpleItoa(static_cast(WireFormat::MakeTag(descriptor))); - (*variables)["tag_size"] = SimpleItoa( + StrCat(static_cast(WireFormat::MakeTag(descriptor))); + (*variables)["tag_size"] = StrCat( WireFormat::TagSize(descriptor->number(), GetType(descriptor))); if (IsReferenceType(GetJavaType(descriptor))) { (*variables)["null_check"] = @@ -89,15 +125,15 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, } // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler - (*variables)["deprecation"] = descriptor->options().deprecated() - ? "@java.lang.Deprecated " : ""; + (*variables)["deprecation"] = + descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; int fixed_size = FixedSize(GetType(descriptor)); if (fixed_size != -1) { - (*variables)["fixed_size"] = SimpleItoa(fixed_size); + (*variables)["fixed_size"] = StrCat(fixed_size); } (*variables)["on_changed"] = "onChanged();"; - if (SupportFieldPresence(descriptor->file())) { + if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); @@ -125,7 +161,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, } } - // For repated builders, one bit is used for whether the array is immutable. + // For repeated builders, one bit is used for whether the array is immutable. (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); @@ -147,14 +183,10 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, // =================================================================== -ImmutablePrimitiveFieldGenerator:: -ImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { +ImmutablePrimitiveFieldGenerator::ImmutablePrimitiveFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + Context* context) + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); @@ -163,205 +195,225 @@ ImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor, ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {} int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const { - return 1; + return HasHasbit(descriptor_) ? 1 : 0; } int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { - return 1; + return GetNumBitsForMessage(); } -void ImmutablePrimitiveFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); +void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); + "$deprecation$boolean has$capitalized_name$();\n"); } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n"); } -void ImmutablePrimitiveFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private $field_type$ $name$_;\n"); +void ImmutablePrimitiveFieldGenerator::GenerateMembers( + io::Printer* printer) const { + printer->Print(variables_, "private $field_type$ $name$_;\n"); PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return $name$_;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutablePrimitiveFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - printer->Print(variables_, - "private $field_type$ $name$_ $default_init$;\n"); +void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + printer->Print(variables_, "private $field_type$ $name$_ $default_init$;\n"); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return $name$_;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n" - "$null_check$" - " $set_has_field_bit_builder$\n" - " $name$_ = value;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder " + "${$set$capitalized_name$$}$($type$ value) {\n" + "$null_check$" + " $set_has_field_bit_builder$\n" + " $name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " $clear_has_field_bit_builder$\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " $clear_has_field_bit_builder$\n"); printer->Annotate("{", "}", descriptor_); JavaType type = GetJavaType(descriptor_); if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) { // The default value is not a simple literal so we want to avoid executing // it multiple times. Instead, get the default out of the default instance. - printer->Print(variables_, - " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); + printer->Print( + variables_, + " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); } else { - printer->Print(variables_, - " $name$_ = $default$;\n"); + printer->Print(variables_, " $name$_ = $default$;\n"); } printer->Print(variables_, - " $on_changed$\n" - " return this;\n" - "}\n"); + " $on_changed$\n" + " return this;\n" + "}\n"); } -void ImmutablePrimitiveFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + +void ImmutablePrimitiveFieldGenerator::GenerateFieldBuilderInitializationCode( + io::Printer* printer) const { // noop for primitives } -void ImmutablePrimitiveFieldGenerator:: -GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $default$;\n"); +void ImmutablePrimitiveFieldGenerator::GenerateInitializationCode( + io::Printer* printer) const { + if (!IsDefaultValueJavaDefault(descriptor_)) { + printer->Print(variables_, "$name$_ = $default$;\n"); + } } -void ImmutablePrimitiveFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { +void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode( + io::Printer* printer) const { printer->Print(variables_, - "$name$_ = $default$;\n" - "$clear_has_field_bit_builder$\n"); + "$name$_ = $default$;\n" + "$clear_has_field_bit_builder$\n"); } -void ImmutablePrimitiveFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { +void ImmutablePrimitiveFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + "if (other.has$capitalized_name$()) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); } else { printer->Print(variables_, - "if (other.get$capitalized_name$() != $default$) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + "if (other.get$capitalized_name$() != $default$) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); } } -void ImmutablePrimitiveFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); +void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { + if (IsDefaultValueJavaDefault(descriptor_)) { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " result.$name$_ = $name$_;\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); + } else { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); + } + } else { + printer->Print(variables_, "result.$name$_ = $name$_;\n"); } - printer->Print(variables_, - "result.$name$_ = $name$_;\n"); } -void ImmutablePrimitiveFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +void ImmutablePrimitiveFieldGenerator::GenerateParsingCode( + io::Printer* printer) const { printer->Print(variables_, - "$set_has_field_bit_message$\n" - "$name$_ = input.read$capitalized_type$();\n"); + "$set_has_field_bit_message$\n" + "$name$_ = input.read$capitalized_type$();\n"); } -void ImmutablePrimitiveFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { +void ImmutablePrimitiveFieldGenerator::GenerateParsingDoneCode( + io::Printer* printer) const { // noop for primitives. } -void ImmutablePrimitiveFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { +void ImmutablePrimitiveFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " output.write$capitalized_type$($number$, $name$_);\n" - "}\n"); + "if ($is_field_present_message$) {\n" + " output.write$capitalized_type$($number$, $name$_);\n" + "}\n"); } -void ImmutablePrimitiveFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { +void ImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$Size($number$, $name$_);\n" - "}\n"); + "if ($is_field_present_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$capitalized_type$Size($number$, $name$_);\n" + "}\n"); } -void ImmutablePrimitiveFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { +void ImmutablePrimitiveFieldGenerator::GenerateEqualsCode( + io::Printer* printer) const { switch (GetJavaType(descriptor_)) { case JAVATYPE_INT: case JAVATYPE_LONG: case JAVATYPE_BOOLEAN: printer->Print(variables_, - "result = result && (get$capitalized_name$()\n" - " == other.get$capitalized_name$());\n"); + "if (get$capitalized_name$()\n" + " != other.get$capitalized_name$()) return false;\n"); break; case JAVATYPE_FLOAT: - printer->Print(variables_, - "result = result && (\n" - " java.lang.Float.floatToIntBits(get$capitalized_name$())\n" - " == java.lang.Float.floatToIntBits(\n" - " other.get$capitalized_name$()));\n"); + printer->Print( + variables_, + "if (java.lang.Float.floatToIntBits(get$capitalized_name$())\n" + " != java.lang.Float.floatToIntBits(\n" + " other.get$capitalized_name$())) return false;\n"); break; case JAVATYPE_DOUBLE: - printer->Print(variables_, - "result = result && (\n" - " java.lang.Double.doubleToLongBits(get$capitalized_name$())\n" - " == java.lang.Double.doubleToLongBits(\n" - " other.get$capitalized_name$()));\n"); + printer->Print( + variables_, + "if (java.lang.Double.doubleToLongBits(get$capitalized_name$())\n" + " != java.lang.Double.doubleToLongBits(\n" + " other.get$capitalized_name$())) return false;\n"); break; case JAVATYPE_STRING: case JAVATYPE_BYTES: - printer->Print(variables_, - "result = result && get$capitalized_name$()\n" - " .equals(other.get$capitalized_name$());\n"); + printer->Print( + variables_, + "if (!get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$())) return false;\n"); break; case JAVATYPE_ENUM: @@ -372,44 +424,47 @@ GenerateEqualsCode(io::Printer* printer) const { } } -void ImmutablePrimitiveFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n"); +void ImmutablePrimitiveFieldGenerator::GenerateHashCode( + io::Printer* printer) const { + printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n"); switch (GetJavaType(descriptor_)) { case JAVATYPE_INT: printer->Print(variables_, - "hash = (53 * hash) + get$capitalized_name$();\n"); + "hash = (53 * hash) + get$capitalized_name$();\n"); break; case JAVATYPE_LONG: - printer->Print(variables_, - "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n" - " get$capitalized_name$());\n"); + printer->Print( + variables_, + "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n" + " get$capitalized_name$());\n"); break; case JAVATYPE_BOOLEAN: - printer->Print(variables_, - "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n" - " get$capitalized_name$());\n"); + printer->Print( + variables_, + "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n" + " get$capitalized_name$());\n"); break; case JAVATYPE_FLOAT: printer->Print(variables_, - "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n" - " get$capitalized_name$());\n"); + "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n" + " get$capitalized_name$());\n"); break; case JAVATYPE_DOUBLE: - printer->Print(variables_, - "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n" - " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n"); + printer->Print( + variables_, + "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n" + " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n"); break; case JAVATYPE_STRING: case JAVATYPE_BYTES: - printer->Print(variables_, - "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); + printer->Print( + variables_, + "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); break; case JAVATYPE_ENUM: @@ -420,171 +475,168 @@ GenerateHashCode(io::Printer* printer) const { } } -string ImmutablePrimitiveFieldGenerator::GetBoxedType() const { +std::string ImmutablePrimitiveFieldGenerator::GetBoxedType() const { return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); } // =================================================================== -ImmutablePrimitiveOneofFieldGenerator:: -ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutablePrimitiveFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { +ImmutablePrimitiveOneofFieldGenerator::ImmutablePrimitiveOneofFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + Context* context) + : ImmutablePrimitiveFieldGenerator(descriptor, messageBitIndex, + builderBitIndex, context) { const OneofGeneratorInfo* info = context->GetOneofGeneratorInfo(descriptor->containing_oneof()); SetCommonOneofVariables(descriptor, info, &variables_); } ImmutablePrimitiveOneofFieldGenerator:: -~ImmutablePrimitiveOneofFieldGenerator() {} + ~ImmutablePrimitiveOneofFieldGenerator() {} -void ImmutablePrimitiveOneofFieldGenerator:: -GenerateMembers(io::Printer* printer) const { +void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers( + io::Printer* printer) const { PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } + GOOGLE_DCHECK(HasHazzer(descriptor_)); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($boxed_type$) $oneof_name$_;\n" - " }\n" - " return $default$;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($boxed_type$) $oneof_name$_;\n" + " }\n" + " return $default$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - -void ImmutablePrimitiveOneofFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } - - WriteFieldDocComment(printer, descriptor_); +void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + GOOGLE_DCHECK(HasHazzer(descriptor_)); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($boxed_type$) $oneof_name$_;\n" - " }\n" - " return $default$;\n" - "}\n"); + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n" - "$null_check$" - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($boxed_type$) $oneof_name$_;\n" + " }\n" + " return $default$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " $on_changed$\n" - " }\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder " + "${$set$capitalized_name$$}$($type$ value) {\n" + "$null_check$" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " $on_changed$\n" + " }\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutablePrimitiveOneofFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { +void ImmutablePrimitiveOneofFieldGenerator::GenerateBuildingCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " result.$oneof_name$_ = $oneof_name$_;\n" - "}\n"); + "if ($has_oneof_case_message$) {\n" + " result.$oneof_name$_ = $oneof_name$_;\n" + "}\n"); } -void ImmutablePrimitiveOneofFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { +void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { printer->Print(variables_, - "set$capitalized_name$(other.get$capitalized_name$());\n"); + "set$capitalized_name$(other.get$capitalized_name$());\n"); } -void ImmutablePrimitiveOneofFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +void ImmutablePrimitiveOneofFieldGenerator::GenerateParsingCode( + io::Printer* printer) const { printer->Print(variables_, - "$set_oneof_case_message$;\n" - "$oneof_name$_ = input.read$capitalized_type$();\n"); + "$set_oneof_case_message$;\n" + "$oneof_name$_ = input.read$capitalized_type$();\n"); } -void ImmutablePrimitiveOneofFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { +void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.write$capitalized_type$(\n"); + "if ($has_oneof_case_message$) {\n" + " output.write$capitalized_type$(\n"); // $type$ and $boxed_type$ is the same for bytes fields so we don't need to // do redundant casts. if (GetJavaType(descriptor_) == JAVATYPE_BYTES) { - printer->Print(variables_, - " $number$, ($type$) $oneof_name$_);\n"); + printer->Print(variables_, " $number$, ($type$) $oneof_name$_);\n"); } else { - printer->Print(variables_, - " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"); + printer->Print( + variables_, + " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"); } - printer->Print( - "}\n"); + printer->Print("}\n"); } -void ImmutablePrimitiveOneofFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { +void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$Size(\n"); + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$capitalized_type$Size(\n"); // $type$ and $boxed_type$ is the same for bytes fields so we don't need to // do redundant casts. if (GetJavaType(descriptor_) == JAVATYPE_BYTES) { - printer->Print(variables_, - " $number$, ($type$) $oneof_name$_);\n"); + printer->Print(variables_, " $number$, ($type$) $oneof_name$_);\n"); } else { - printer->Print(variables_, - " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"); + printer->Print( + variables_, + " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"); } - printer->Print( - "}\n"); + printer->Print("}\n"); } // =================================================================== RepeatedImmutablePrimitiveFieldGenerator:: -RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { + RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); } RepeatedImmutablePrimitiveFieldGenerator:: -~RepeatedImmutablePrimitiveFieldGenerator() {} + ~RepeatedImmutablePrimitiveFieldGenerator() {} int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const { return 0; @@ -594,304 +646,320 @@ int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { return 1; } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); +void RepeatedImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, - "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n"); - WriteFieldDocComment(printer, descriptor_); + "$deprecation$java.util.List<$boxed_type$> " + "get$capitalized_name$List();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); - WriteFieldDocComment(printer, descriptor_); + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$(int index);\n"); + "$deprecation$$type$ get$capitalized_name$(int index);\n"); } - -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private $field_list_type$ $name$_;\n"); +void RepeatedImmutablePrimitiveFieldGenerator::GenerateMembers( + io::Printer* printer) const { + printer->Print(variables_, "private $field_list_type$ $name$_;\n"); PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, - "$deprecation$public java.util.List<$boxed_type$>\n" - " ${$get$capitalized_name$List$}$() {\n" - " return $name$_;\n" // note: unmodifiable list - "}\n"); + "@java.lang.Override\n" + "$deprecation$public java.util.List<$boxed_type$>\n" + " ${$get$capitalized_name$List$}$() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return $name$_.size();\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); + printer->Print( + variables_, + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return $name$_.size();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return $name$_.get(index);\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); + printer->Print( + variables_, + "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" + " return $repeated_get$(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - if (descriptor_->is_packed() && - context_->HasGeneratedMethods(descriptor_->containing_type())) { + if (descriptor_->is_packed()) { printer->Print(variables_, - "private int $name$MemoizedSerializedSize = -1;\n"); + "private int $name$MemoizedSerializedSize = -1;\n"); } } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { +void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers( + io::Printer* printer) const { // One field is the list and the bit field keeps track of whether the // list is immutable. If it's immutable, the invariant is that it must // either an instance of Collections.emptyList() or it's an ArrayList // wrapped in a Collections.unmodifiableList() wrapper and nobody else has - // a refererence to the underlying ArrayList. This invariant allows us to + // a reference to the underlying ArrayList. This invariant allows us to // share instances of lists between protocol buffers avoiding expensive // memory allocations. Note, immutable is a strong guarantee here -- not // just that the list cannot be modified via the reference but that the // list can never be modified. printer->Print(variables_, - "private $field_list_type$ $name$_ = $empty_list$;\n"); + "private $field_list_type$ $name$_ = $empty_list$;\n"); printer->Print(variables_, - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$get_mutable_bit_builder$) {\n" - " $name$_ = new java.util.ArrayList<$boxed_type$>($name$_);\n" - " $set_mutable_bit_builder$;\n" - " }\n" - "}\n"); + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = $mutable_copy_list$;\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n"); - // Note: We return an unmodifiable list because otherwise the caller - // could hold on to the returned list and modify it after the message - // has been built, thus mutating the message which is supposed to be - // immutable. - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$boxed_type$>\n" - " ${$get$capitalized_name$List$}$() {\n" - " return java.util.Collections.unmodifiableList($name$_);\n" - "}\n"); + // Note: We return an unmodifiable list because otherwise the caller + // could hold on to the returned list and modify it after the message + // has been built, thus mutating the message which is supposed to be + // immutable. + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); + printer->Print( + variables_, + "$deprecation$public java.util.List<$boxed_type$>\n" + " ${$get$capitalized_name$List$}$() {\n" + " return $get_mutable_bit_builder$ ?\n" + " java.util.Collections.unmodifiableList($name$_) : $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return $name$_.size();\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); + printer->Print( + variables_, + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return $name$_.size();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return $name$_.get(index);\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); + printer->Print( + variables_, + "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" + " return $repeated_get$(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " int index, $type$ value) {\n" - "$null_check$" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, value);\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " int index, $type$ value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $repeated_set$(index, value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n" - "$null_check$" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value);\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder " + "${$add$capitalized_name$$}$($type$ value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $repeated_add$(value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" - " java.lang.Iterable values) {\n" - " ensure$capitalized_name$IsMutable();\n" - " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" - " values, $name$_);\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" + " values, $name$_);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " $name$_ = $empty_list$;\n" - " $clear_mutable_bit_builder$;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " $name$_ = $empty_list$;\n" + " $clear_mutable_bit_builder$;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + GenerateFieldBuilderInitializationCode(io::Printer* printer) const { // noop for primitives } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateInitializationCode(io::Printer* printer) const { +void RepeatedImmutablePrimitiveFieldGenerator::GenerateInitializationCode( + io::Printer* printer) const { printer->Print(variables_, "$name$_ = $empty_list$;\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { +void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode( + io::Printer* printer) const { printer->Print(variables_, - "$name$_ = $empty_list$;\n" - "$clear_mutable_bit_builder$;\n"); + "$name$_ = $empty_list$;\n" + "$clear_mutable_bit_builder$;\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { +void RepeatedImmutablePrimitiveFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { // The code below does two optimizations: // 1. If the other list is empty, there's nothing to do. This ensures we // don't allocate a new array if we already have an immutable one. // 2. If the other list is non-empty and our current list is empty, we can // reuse the other list which is guaranteed to be immutable. printer->Print(variables_, - "if (!other.$name$_.isEmpty()) {\n" - " if ($name$_.isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " $clear_mutable_bit_builder$;\n" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" - " }\n" - " $on_changed$\n" - "}\n"); + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { +void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuildingCode( + io::Printer* printer) const { // The code below ensures that the result has an immutable list. If our // list is immutable, we can just reuse it. If not, we make it immutable. printer->Print(variables_, - "if ($get_mutable_bit_builder$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - " $clear_mutable_bit_builder$;\n" - "}\n" - "result.$name$_ = $name$_;\n"); + "if ($get_mutable_bit_builder$) {\n" + " $name_make_immutable$;\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingCode( + io::Printer* printer) const { printer->Print(variables_, - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ = new java.util.ArrayList<$boxed_type$>();\n" - " $set_mutable_bit_parser$;\n" - "}\n" - "$name$_.add(input.read$capitalized_type$());\n"); + "if (!$get_mutable_bit_parser$) {\n" + " $name$_ = $create_list$;\n" + " $set_mutable_bit_parser$;\n" + "}\n" + "$repeated_add$(input.read$capitalized_type$());\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateParsingCodeFromPacked(io::Printer* printer) const { - printer->Print(variables_, - "int length = input.readRawVarint32();\n" - "int limit = input.pushLimit(length);\n" - "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n" - " $name$_ = new java.util.ArrayList<$boxed_type$>();\n" - " $set_mutable_bit_parser$;\n" - "}\n" - "while (input.getBytesUntilLimit() > 0) {\n" - " $name$_.add(input.read$capitalized_type$());\n" - "}\n" - "input.popLimit(limit);\n"); +void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingCodeFromPacked( + io::Printer* printer) const { + printer->Print( + variables_, + "int length = input.readRawVarint32();\n" + "int limit = input.pushLimit(length);\n" + "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n" + " $name$_ = $create_list$;\n" + " $set_mutable_bit_parser$;\n" + "}\n" + "while (input.getBytesUntilLimit() > 0) {\n" + " $repeated_add$(input.read$capitalized_type$());\n" + "}\n" + "input.popLimit(limit);\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { +void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingDoneCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($get_mutable_bit_parser$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - "}\n"); + "if ($get_mutable_bit_parser$) {\n" + " $name_make_immutable$; // C\n" + "}\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { +void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { if (descriptor_->is_packed()) { // We invoke getSerializedSize in writeTo for messages that have packed // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods. // That makes it safe to rely on the memoized size here. printer->Print(variables_, - "if (get$capitalized_name$List().size() > 0) {\n" - " output.writeUInt32NoTag($tag$);\n" - " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n" - "}\n" - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$capitalized_type$NoTag($name$_.get(i));\n" - "}\n"); + "if (get$capitalized_name$List().size() > 0) {\n" + " output.writeUInt32NoTag($tag$);\n" + " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n" + "}\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$capitalized_type$NoTag($repeated_get$(i));\n" + "}\n"); } else { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$capitalized_type$($number$, $name$_.get(i));\n" - "}\n"); + printer->Print( + variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$capitalized_type$($number$, $repeated_get$(i));\n" + "}\n"); } } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { +void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { printer->Print(variables_, - "{\n" - " int dataSize = 0;\n"); + "{\n" + " int dataSize = 0;\n"); printer->Indent(); if (FixedSize(GetType(descriptor_)) == -1) { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " dataSize += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$SizeNoTag($name$_.get(i));\n" - "}\n"); + printer->Print( + variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " dataSize += com.google.protobuf.CodedOutputStream\n" + " .compute$capitalized_type$SizeNoTag($repeated_get$(i));\n" + "}\n"); } else { - printer->Print(variables_, - "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n"); + printer->Print( + variables_, + "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n"); } - printer->Print( - "size += dataSize;\n"); + printer->Print("size += dataSize;\n"); if (descriptor_->is_packed()) { printer->Print(variables_, - "if (!get$capitalized_name$List().isEmpty()) {\n" - " size += $tag_size$;\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeInt32SizeNoTag(dataSize);\n" - "}\n"); + "if (!get$capitalized_name$List().isEmpty()) {\n" + " size += $tag_size$;\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeInt32SizeNoTag(dataSize);\n" + "}\n"); } else { - printer->Print(variables_, - "size += $tag_size$ * get$capitalized_name$List().size();\n"); + printer->Print( + variables_, + "size += $tag_size$ * get$capitalized_name$List().size();\n"); } // cache the data size for packed fields. if (descriptor_->is_packed()) { - printer->Print(variables_, - "$name$MemoizedSerializedSize = dataSize;\n"); + printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n"); } printer->Outdent(); printer->Print("}\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && get$capitalized_name$List()\n" - " .equals(other.get$capitalized_name$List());\n"); +void RepeatedImmutablePrimitiveFieldGenerator::GenerateEqualsCode( + io::Printer* printer) const { + printer->Print( + variables_, + "if (!get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List())) return false;\n"); } -void RepeatedImmutablePrimitiveFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "if (get$capitalized_name$Count() > 0) {\n" - " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" - "}\n"); +void RepeatedImmutablePrimitiveFieldGenerator::GenerateHashCode( + io::Printer* printer) const { + printer->Print( + variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" + "}\n"); } -string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const { +std::string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const { return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); } diff --git a/src/google/protobuf/compiler/java/java_primitive_field.h b/src/google/protobuf/compiler/java/java_primitive_field.h index 7ac9bbfb74ba3..db20750e262df 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.h +++ b/src/google/protobuf/compiler/java/java_primitive_field.h @@ -41,26 +41,30 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator { public: - explicit ImmutablePrimitiveFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context); ~ImmutablePrimitiveFieldGenerator(); - // implements ImmutableFieldGenerator --------------------------------------- + // implements ImmutableFieldGenerator + // --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -78,14 +82,11 @@ class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; + std::map variables_; ClassNameResolver* name_resolver_; private: @@ -95,9 +96,9 @@ class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator { class ImmutablePrimitiveOneofFieldGenerator : public ImmutablePrimitiveFieldGenerator { public: - ImmutablePrimitiveOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, Context* context); ~ImmutablePrimitiveOneofFieldGenerator(); void GenerateMembers(io::Printer* printer) const; @@ -139,14 +140,11 @@ class RepeatedImmutablePrimitiveFieldGenerator void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; + std::map variables_; ClassNameResolver* name_resolver_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldGenerator); @@ -155,6 +153,6 @@ class RepeatedImmutablePrimitiveFieldGenerator } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc index f92931711f1a0..e80706624757f 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc @@ -32,6 +32,8 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include + #include #include @@ -41,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -55,13 +56,19 @@ using internal::WireFormat; using internal::WireFormatLite; namespace { +bool EnableExperimentalRuntimeForLite() { +#ifdef PROTOBUF_EXPERIMENT + return PROTOBUF_EXPERIMENT; +#else // PROTOBUF_EXPERIMENT + return false; +#endif // !PROTOBUF_EXPERIMENT +} void SetPrimitiveVariables(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, + int messageBitIndex, int builderBitIndex, const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, - std::map* variables) { + std::map* variables) { SetCommonFieldVariables(descriptor, info, variables); JavaType javaType = GetJavaType(descriptor); (*variables)["type"] = PrimitiveTypeName(javaType); @@ -71,13 +78,13 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, (*variables)["capitalized_type"] = GetCapitalizedType(descriptor, /* immutable = */ true); (*variables)["tag"] = - SimpleItoa(static_cast(WireFormat::MakeTag(descriptor))); - (*variables)["tag_size"] = SimpleItoa( + StrCat(static_cast(WireFormat::MakeTag(descriptor))); + (*variables)["tag_size"] = StrCat( WireFormat::TagSize(descriptor->number(), GetType(descriptor))); (*variables)["required"] = descriptor->is_required() ? "true" : "false"; - string capitalized_type = UnderscoresToCamelCase(PrimitiveTypeName(javaType), - true /* cap_next_letter */); + std::string capitalized_type = UnderscoresToCamelCase( + PrimitiveTypeName(javaType), true /* cap_next_letter */); switch (javaType) { case JAVATYPE_INT: case JAVATYPE_LONG: @@ -118,23 +125,22 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, } if (IsReferenceType(javaType)) { - (*variables)["null_check"] = - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n"; + // We use `x.getClass()` as a null check because it generates less bytecode + // than an `if (x == null) { throw ... }` statement. + (*variables)["null_check"] = " value.getClass();\n"; } else { (*variables)["null_check"] = ""; } // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler - (*variables)["deprecation"] = descriptor->options().deprecated() - ? "@java.lang.Deprecated " : ""; + (*variables)["deprecation"] = + descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; int fixed_size = FixedSize(GetType(descriptor)); if (fixed_size != -1) { - (*variables)["fixed_size"] = SimpleItoa(fixed_size); + (*variables)["fixed_size"] = StrCat(fixed_size); } - if (SupportFieldPresence(descriptor->file())) { + if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); @@ -159,9 +165,6 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, } } - // For repeated builders, the underlying list tracks mutability state. - (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()"; - (*variables)["get_has_field_bit_from_local"] = GenerateGetBitFromLocal(builderBitIndex); (*variables)["set_has_field_bit_to_local"] = @@ -172,15 +175,12 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, // =================================================================== -ImmutablePrimitiveFieldLiteGenerator:: -ImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, +ImmutablePrimitiveFieldLiteGenerator::ImmutablePrimitiveFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, Context* context) + : descriptor_(descriptor), + messageBitIndex_(messageBitIndex), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); } @@ -188,27 +188,22 @@ ImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor, ImmutablePrimitiveFieldLiteGenerator::~ImmutablePrimitiveFieldLiteGenerator() {} int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const { - return 1; -} - -int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; + return HasHasbit(descriptor_) ? 1 : 0; } -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); +void ImmutablePrimitiveFieldLiteGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); + "$deprecation$boolean has$capitalized_name$();\n"); } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n"); } -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { +void ImmutablePrimitiveFieldLiteGenerator::GenerateMembers( + io::Printer* printer) const { if (IsByteStringWithCustomDefaultValue(descriptor_)) { // allocate this once statically since we know ByteStrings are immutable // values that can be reused. @@ -216,96 +211,110 @@ GenerateMembers(io::Printer* printer) const { variables_, "private static final $field_type$ $bytes_default$ = $default$;\n"); } - printer->Print(variables_, - "private $field_type$ $name$_;\n"); + printer->Print(variables_, "private $field_type$ $name$_;\n"); PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return $name$_;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER); printer->Print(variables_, - "private void set$capitalized_name$($type$ value) {\n" - "$null_check$" - " $set_has_field_bit_message$\n" - " $name$_ = value;\n" - "}\n"); + "private void set$capitalized_name$($type$ value) {\n" + "$null_check$" + " $set_has_field_bit_message$\n" + " $name$_ = value;\n" + "}\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER); printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " $clear_has_field_bit_message$\n"); + "private void clear$capitalized_name$() {\n" + " $clear_has_field_bit_message$\n"); JavaType type = GetJavaType(descriptor_); if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) { // The default value is not a simple literal so we want to avoid executing // it multiple times. Instead, get the default out of the default instance. - printer->Print(variables_, - " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); + printer->Print( + variables_, + " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); } else { - printer->Print(variables_, - " $name$_ = $default$;\n"); + printer->Print(variables_, " $name$_ = $default$;\n"); } - printer->Print(variables_, - "}\n"); + printer->Print(variables_, "}\n"); } -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return instance.has$capitalized_name$();\n" - "}\n"); +void ImmutablePrimitiveFieldLiteGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return instance.get$capitalized_name$();\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(value);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder " + "${$set$capitalized_name$$}$($type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - // noop for primitives -} +void ImmutablePrimitiveFieldLiteGenerator::GenerateFieldInfo( + io::Printer* printer, std::vector* output) const { + WriteIntToUtf16CharSequence(descriptor_->number(), output); + WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_), + output); + if (HasHasbit(descriptor_)) { + WriteIntToUtf16CharSequence(messageBitIndex_, output); + } + printer->Print(variables_, "\"$name$_\",\n"); +} -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateInitializationCode(io::Printer* printer) const { +void ImmutablePrimitiveFieldLiteGenerator::GenerateInitializationCode( + io::Printer* printer) const { if (IsByteStringWithCustomDefaultValue(descriptor_)) { printer->Print(variables_, "$name$_ = $bytes_default$;\n"); } else if (!IsDefaultValueJavaDefault(descriptor_)) { @@ -313,624 +322,311 @@ GenerateInitializationCode(io::Printer* printer) const { } } -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - // noop for primitives -} - -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "$name$_ = visitor.visit$visit_type$(\n" - " has$capitalized_name$(), $name$_,\n" - " other.has$capitalized_name$(), other.$name$_);\n"); - } else { - printer->Print(variables_, - "$name$_ = visitor.visit$visit_type$($name$_ != $default$, $name$_,\n" - " other.$name$_ != $default$, other.$name$_);\n"); - } -} - -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - // noop for primitives -} - -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { - // noop for scalars -} - -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "$set_has_field_bit_message$\n" - "$name$_ = input.read$capitalized_type$();\n"); -} - -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - // noop for primitives. -} - -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " output.write$capitalized_type$($number$, $name$_);\n" - "}\n"); -} - -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$Size($number$, $name$_);\n" - "}\n"); -} - -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - switch (GetJavaType(descriptor_)) { - case JAVATYPE_INT: - case JAVATYPE_LONG: - case JAVATYPE_BOOLEAN: - printer->Print(variables_, - "result = result && (get$capitalized_name$()\n" - " == other.get$capitalized_name$());\n"); - break; - - case JAVATYPE_FLOAT: - printer->Print(variables_, - "result = result && (\n" - " java.lang.Float.floatToIntBits(get$capitalized_name$())\n" - " == java.lang.Float.floatToIntBits(\n" - " other.get$capitalized_name$()));\n"); - break; - - case JAVATYPE_DOUBLE: - printer->Print(variables_, - "result = result && (\n" - " java.lang.Double.doubleToLongBits(get$capitalized_name$())\n" - " == java.lang.Double.doubleToLongBits(\n" - " other.get$capitalized_name$()));\n"); - break; - - case JAVATYPE_STRING: - case JAVATYPE_BYTES: - printer->Print(variables_, - "result = result && get$capitalized_name$()\n" - " .equals(other.get$capitalized_name$());\n"); - break; - - case JAVATYPE_ENUM: - case JAVATYPE_MESSAGE: - default: - GOOGLE_LOG(FATAL) << "Can't get here."; - break; - } -} - -void ImmutablePrimitiveFieldLiteGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n"); - switch (GetJavaType(descriptor_)) { - case JAVATYPE_INT: - printer->Print(variables_, - "hash = (53 * hash) + get$capitalized_name$();\n"); - break; - - case JAVATYPE_LONG: - printer->Print(variables_, - "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n" - " get$capitalized_name$());\n"); - break; - - case JAVATYPE_BOOLEAN: - printer->Print(variables_, - "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n" - " get$capitalized_name$());\n"); - break; - - case JAVATYPE_FLOAT: - printer->Print(variables_, - "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n" - " get$capitalized_name$());\n"); - break; - - case JAVATYPE_DOUBLE: - printer->Print(variables_, - "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n" - " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n"); - break; - - case JAVATYPE_STRING: - case JAVATYPE_BYTES: - printer->Print(variables_, - "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); - break; - - case JAVATYPE_ENUM: - case JAVATYPE_MESSAGE: - default: - GOOGLE_LOG(FATAL) << "Can't get here."; - break; - } -} - -string ImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const { +std::string ImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const { return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); } // =================================================================== ImmutablePrimitiveOneofFieldLiteGenerator:: -ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutablePrimitiveFieldLiteGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { + ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context) + : ImmutablePrimitiveFieldLiteGenerator(descriptor, messageBitIndex, + context) { const OneofGeneratorInfo* info = context->GetOneofGeneratorInfo(descriptor->containing_oneof()); SetCommonOneofVariables(descriptor, info, &variables_); } ImmutablePrimitiveOneofFieldLiteGenerator:: -~ImmutablePrimitiveOneofFieldLiteGenerator() {} + ~ImmutablePrimitiveOneofFieldLiteGenerator() {} -void ImmutablePrimitiveOneofFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { +void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateMembers( + io::Printer* printer) const { PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } - - WriteFieldDocComment(printer, descriptor_); + GOOGLE_DCHECK(HasHazzer(descriptor_)); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($boxed_type$) $oneof_name$_;\n" - " }\n" - " return $default$;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$($type$ value) {\n" - "$null_check$" - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value;\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " }\n" - "}\n"); -} - - -void ImmutablePrimitiveOneofFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return instance.has$capitalized_name$();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } - - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return instance.get$capitalized_name$();\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($boxed_type$) $oneof_name$_;\n" + " }\n" + " return $default$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(value);\n" - " return this;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); + "private void set$capitalized_name$($type$ value) {\n" + "$null_check$" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + "}\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER); printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); + "private void clear$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " }\n" + "}\n"); } -void ImmutablePrimitiveOneofFieldLiteGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - // noop for primitives +void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateFieldInfo( + io::Printer* printer, std::vector* output) const { + WriteIntToUtf16CharSequence(descriptor_->number(), output); + WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_), + output); + WriteIntToUtf16CharSequence(descriptor_->containing_oneof()->index(), output); } -void ImmutablePrimitiveOneofFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { +void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + GOOGLE_DCHECK(HasHazzer(descriptor_)); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$oneof_name$_ = visitor.visitOneof$visit_type$(\n" - " $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n"); -} + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); -void ImmutablePrimitiveOneofFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$set_oneof_case_message$;\n" - "$oneof_name$_ = input.read$capitalized_type$();\n"); -} + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); -void ImmutablePrimitiveOneofFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { + WriteFieldAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.write$capitalized_type$(\n" - " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n" - "}\n"); -} + "$deprecation$public Builder " + "${$set$capitalized_name$$}$($type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); -void ImmutablePrimitiveOneofFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$Size(\n" - " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); } // =================================================================== RepeatedImmutablePrimitiveFieldLiteGenerator:: -RepeatedImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + RepeatedImmutablePrimitiveFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + Context* context) + : descriptor_(descriptor), + context_(context), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); } RepeatedImmutablePrimitiveFieldLiteGenerator:: -~RepeatedImmutablePrimitiveFieldLiteGenerator() {} + ~RepeatedImmutablePrimitiveFieldLiteGenerator() {} int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const { return 0; } -int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; -} - -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); +void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, - "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n"); - WriteFieldDocComment(printer, descriptor_); + "$deprecation$java.util.List<$boxed_type$> " + "get$capitalized_name$List();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); - WriteFieldDocComment(printer, descriptor_); + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$(int index);\n"); + "$deprecation$$type$ get$capitalized_name$(int index);\n"); } - -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private $field_list_type$ $name$_;\n"); +void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateMembers( + io::Printer* printer) const { + printer->Print(variables_, "private $field_list_type$ $name$_;\n"); PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, - "$deprecation$public java.util.List<$boxed_type$>\n" - " ${$get$capitalized_name$List$}$() {\n" - " return $name$_;\n" // note: unmodifiable list - "}\n"); + "@java.lang.Override\n" + "$deprecation$public java.util.List<$boxed_type$>\n" + " ${$get$capitalized_name$List$}$() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return $name$_.size();\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return $name$_.size();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return $repeated_get$(index);\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" + " return $repeated_get$(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - if (descriptor_->is_packed() && + if (!EnableExperimentalRuntimeForLite() && descriptor_->is_packed() && context_->HasGeneratedMethods(descriptor_->containing_type())) { printer->Print(variables_, - "private int $name$MemoizedSerializedSize = -1;\n"); + "private int $name$MemoizedSerializedSize = -1;\n"); } - printer->Print(variables_, - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$is_mutable$) {\n" - " $name$_ =\n" - " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$(\n" - " int index, $type$ value) {\n" - "$null_check$" - " ensure$capitalized_name$IsMutable();\n" - " $repeated_set$(index, value);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$($type$ value) {\n" - "$null_check$" - " ensure$capitalized_name$IsMutable();\n" - " $repeated_add$(value);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void addAll$capitalized_name$(\n" - " java.lang.Iterable values) {\n" - " ensure$capitalized_name$IsMutable();\n" - " com.google.protobuf.AbstractMessageLite.addAll(\n" - " values, $name$_);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " $name$_ = $empty_list$;\n" - "}\n"); -} + printer->Print( + variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + // Use a temporary to avoid a redundant iget-object. + " $field_list_type$ tmp = $name$_;\n" + " if (!tmp.isModifiable()) {\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n" + " }\n" + "}\n"); -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$boxed_type$>\n" - " ${$get$capitalized_name$List$}$() {\n" - " return java.util.Collections.unmodifiableList(\n" - " instance.get$capitalized_name$List());\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " int index, $type$ value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $repeated_set$(index, value);\n" + "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER); + printer->Print(variables_, + "private void add$capitalized_name$($type$ value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $repeated_add$(value);\n" + "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER); + printer->Print(variables_, + "private void addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " com.google.protobuf.AbstractMessageLite.addAll(\n" + " values, $name$_);\n" + "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " $name$_ = $empty_list$;\n" + "}\n"); +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public java.util.List<$boxed_type$>\n" + " ${$get$capitalized_name$List$}$() {\n" + " return java.util.Collections.unmodifiableList(\n" + " instance.get$capitalized_name$List());\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return instance.get$capitalized_name$Count();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return instance.get$capitalized_name$(index);\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return instance.get$capitalized_name$Count();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " int index, $type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(index, value);\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" + " return instance.get$capitalized_name$(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(value);\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " int index, $type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(index, value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" - " java.lang.Iterable values) {\n" - " copyOnWrite();\n" - " instance.addAll$capitalized_name$(values);\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder " + "${$add$capitalized_name$$}$($type$ value) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" + " java.lang.Iterable values) {\n" + " copyOnWrite();\n" + " instance.addAll$capitalized_name$(values);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); -} - -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - // noop for primitives -} - - -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $empty_list$;\n"); -} - -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - // noop for primitives -} - -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_= visitor.$visit_type_list$($name$_, other.$name$_);\n"); -} - -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - // noop for primitives -} - -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_.makeImmutable();\n"); -} - -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - // TODO(dweis): Scan the input buffer to count, then initialize - // appropriately. - // TODO(dweis): Scan the input buffer to count and ensure capacity. - printer->Print(variables_, - "if (!$is_mutable$) {\n" - " $name$_ =\n" - " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" - "}\n" - "$repeated_add$(input.read$capitalized_type$());\n"); -} - -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateParsingCodeFromPacked(io::Printer* printer) const { - printer->Print(variables_, - "int length = input.readRawVarint32();\n" - "int limit = input.pushLimit(length);\n" - "if (!$is_mutable$ && input.getBytesUntilLimit() > 0) {\n"); - - int fixed_size = FixedSize(GetType(descriptor_)); - if (fixed_size == -1) { - // TODO(dweis): Scan the input buffer to count, then initialize - // appropriately. - printer->Print(variables_, - " $name$_ =\n" - " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"); - } else { - printer->Print(variables_, - " final int currentSize = $name$_.size();\n" - " $name$_ = $name$_.mutableCopyWithCapacity(\n" - " currentSize + (length/$fixed_size$));\n"); - } - - // TODO(dweis): Scan the input buffer to count and ensure capacity. - printer->Print(variables_, - "}\n" - "while (input.getBytesUntilLimit() > 0) {\n" - " $repeated_add$(input.read$capitalized_type$());\n" - "}\n" - "input.popLimit(limit);\n"); -} - -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_mutable$) {\n" - " $make_name_unmodifiable$;\n" - "}\n"); -} - -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - if (descriptor_->is_packed()) { - // We invoke getSerializedSize in writeTo for messages that have packed - // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods. - // That makes it safe to rely on the memoized size here. - printer->Print(variables_, - "if (get$capitalized_name$List().size() > 0) {\n" - " output.writeUInt32NoTag($tag$);\n" - " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n" - "}\n" - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$capitalized_type$NoTag($repeated_get$(i));\n" - "}\n"); - } else { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$capitalized_type$($number$, $repeated_get$(i));\n" - "}\n"); - } -} - -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "{\n" - " int dataSize = 0;\n"); - printer->Indent(); - - if (FixedSize(GetType(descriptor_)) == -1) { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " dataSize += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$SizeNoTag($repeated_get$(i));\n" - "}\n"); - } else { - printer->Print(variables_, - "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n"); - } - + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); printer->Print( - "size += dataSize;\n"); - - if (descriptor_->is_packed()) { - printer->Print(variables_, - "if (!get$capitalized_name$List().isEmpty()) {\n" - " size += $tag_size$;\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeInt32SizeNoTag(dataSize);\n" + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" "}\n"); - } else { - printer->Print(variables_, - "size += $tag_size$ * get$capitalized_name$List().size();\n"); - } - - // cache the data size for packed fields. - if (descriptor_->is_packed()) { - printer->Print(variables_, - "$name$MemoizedSerializedSize = dataSize;\n"); - } - - printer->Outdent(); - printer->Print("}\n"); + printer->Annotate("{", "}", descriptor_); } -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && get$capitalized_name$List()\n" - " .equals(other.get$capitalized_name$List());\n"); +void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateFieldInfo( + io::Printer* printer, std::vector* output) const { + WriteIntToUtf16CharSequence(descriptor_->number(), output); + WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_), + output); + printer->Print(variables_, "\"$name$_\",\n"); } -void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "if (get$capitalized_name$Count() > 0) {\n" - " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" - "}\n"); +void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateInitializationCode( + io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $empty_list$;\n"); } -string RepeatedImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const { +std::string RepeatedImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const { return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); } diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.h b/src/google/protobuf/compiler/java/java_primitive_field_lite.h index 93416f0b6826f..5867cee74659b 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field_lite.h +++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.h @@ -41,14 +41,16 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -57,38 +59,25 @@ class ImmutablePrimitiveFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: explicit ImmutablePrimitiveFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + const FieldDescriptor* descriptor, int messageBitIndex, Context* context); ~ImmutablePrimitiveFieldLiteGenerator(); - // implements ImmutableFieldLiteGenerator ------------------------------------ + // implements ImmutableFieldLiteGenerator + // ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateBuilderClearCode(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; - + void GenerateFieldInfo(io::Printer* printer, + std::vector* output) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map variables_; + std::map variables_; const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; ClassNameResolver* name_resolver_; private: @@ -98,19 +87,16 @@ class ImmutablePrimitiveFieldLiteGenerator class ImmutablePrimitiveOneofFieldLiteGenerator : public ImmutablePrimitiveFieldLiteGenerator { public: - ImmutablePrimitiveOneofFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context); ~ImmutablePrimitiveOneofFieldLiteGenerator(); void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldInfo(io::Printer* printer, + std::vector* output) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldLiteGenerator); @@ -120,38 +106,23 @@ class RepeatedImmutablePrimitiveFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: explicit RepeatedImmutablePrimitiveFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + const FieldDescriptor* descriptor, int messageBitIndex, Context* context); virtual ~RepeatedImmutablePrimitiveFieldLiteGenerator(); // implements ImmutableFieldLiteGenerator ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateBuilderClearCode(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingCodeFromPacked(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; - - - string GetBoxedType() const; + void GenerateFieldInfo(io::Printer* printer, + std::vector* output) const; + + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map variables_; - const int messageBitIndex_; - const int builderBitIndex_; + std::map variables_; Context* context_; ClassNameResolver* name_resolver_; @@ -161,6 +132,6 @@ class RepeatedImmutablePrimitiveFieldLiteGenerator } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc index 988e1942b74d3..e30d155e47eb6 100644 --- a/src/google/protobuf/compiler/java/java_service.cc +++ b/src/google/protobuf/compiler/java/java_service.cc @@ -47,15 +47,16 @@ namespace compiler { namespace java { ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor) - : descriptor_(descriptor) {} + : descriptor_(descriptor) {} ServiceGenerator::~ServiceGenerator() {} // =================================================================== ImmutableServiceGenerator::ImmutableServiceGenerator( const ServiceDescriptor* descriptor, Context* context) - : ServiceGenerator(descriptor), context_(context), - name_resolver_(context->GetNameResolver()) {} + : ServiceGenerator(descriptor), + context_(context), + name_resolver_(context->GetNameResolver()) {} ImmutableServiceGenerator::~ImmutableServiceGenerator() {} @@ -65,15 +66,13 @@ void ImmutableServiceGenerator::Generate(io::Printer* printer) { MaybePrintGeneratedAnnotation(context_, printer, descriptor_, /* immutable = */ true); printer->Print( - "public $static$ abstract class $classname$\n" - " implements com.google.protobuf.Service {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + "public $static$ abstract class $classname$\n" + " implements com.google.protobuf.Service {\n", + "static", is_own_file ? "" : "static", "classname", descriptor_->name()); printer->Indent(); - printer->Print( - "protected $classname$() {}\n\n", - "classname", descriptor_->name()); + printer->Print("protected $classname$() {}\n\n", "classname", + descriptor_->name()); GenerateInterface(printer); @@ -84,13 +83,13 @@ void ImmutableServiceGenerator::Generate(io::Printer* printer) { // Generate getDescriptor() and getDescriptorForType(). printer->Print( - "public static final\n" - " com.google.protobuf.Descriptors.ServiceDescriptor\n" - " getDescriptor() {\n" - " return $file$.getDescriptor().getServices().get($index$);\n" - "}\n", - "file", name_resolver_->GetImmutableClassName(descriptor_->file()), - "index", SimpleItoa(descriptor_->index())); + "public static final\n" + " com.google.protobuf.Descriptors.ServiceDescriptor\n" + " getDescriptor() {\n" + " return $file$.getDescriptor().getServices().get($index$);\n" + "}\n", + "file", name_resolver_->GetImmutableClassName(descriptor_->file()), + "index", StrCat(descriptor_->index())); GenerateGetDescriptorForType(printer); // Generate more stuff. @@ -102,9 +101,9 @@ void ImmutableServiceGenerator::Generate(io::Printer* printer) { // Add an insertion point. printer->Print( - "\n" - "// @@protoc_insertion_point(class_scope:$full_name$)\n", - "full_name", descriptor_->full_name()); + "\n" + "// @@protoc_insertion_point(class_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); printer->Outdent(); printer->Print("}\n\n"); @@ -113,10 +112,10 @@ void ImmutableServiceGenerator::Generate(io::Printer* printer) { void ImmutableServiceGenerator::GenerateGetDescriptorForType( io::Printer* printer) { printer->Print( - "public final com.google.protobuf.Descriptors.ServiceDescriptor\n" - " getDescriptorForType() {\n" - " return getDescriptor();\n" - "}\n"); + "public final com.google.protobuf.Descriptors.ServiceDescriptor\n" + " getDescriptorForType() {\n" + " return getDescriptor();\n" + "}\n"); } void ImmutableServiceGenerator::GenerateInterface(io::Printer* printer) { @@ -130,10 +129,10 @@ void ImmutableServiceGenerator::GenerateInterface(io::Printer* printer) { void ImmutableServiceGenerator::GenerateNewReflectiveServiceMethod( io::Printer* printer) { printer->Print( - "public static com.google.protobuf.Service newReflectiveService(\n" - " final Interface impl) {\n" - " return new $classname$() {\n", - "classname", descriptor_->name()); + "public static com.google.protobuf.Service newReflectiveService(\n" + " final Interface impl) {\n" + " return new $classname$() {\n", + "classname", descriptor_->name()); printer->Indent(); printer->Indent(); @@ -142,10 +141,10 @@ void ImmutableServiceGenerator::GenerateNewReflectiveServiceMethod( printer->Print("@java.lang.Override\n"); GenerateMethodSignature(printer, method, IS_CONCRETE); printer->Print( - " {\n" - " impl.$method$(controller, request, done);\n" - "}\n\n", - "method", UnderscoresToCamelCase(method)); + " {\n" + " impl.$method$(controller, request, done);\n" + "}\n\n", + "method", UnderscoresToCamelCase(method)); } printer->Outdent(); @@ -157,9 +156,9 @@ void ImmutableServiceGenerator::GenerateNewReflectiveServiceMethod( void ImmutableServiceGenerator::GenerateNewReflectiveBlockingServiceMethod( io::Printer* printer) { printer->Print( - "public static com.google.protobuf.BlockingService\n" - " newReflectiveBlockingService(final BlockingInterface impl) {\n" - " return new com.google.protobuf.BlockingService() {\n"); + "public static com.google.protobuf.BlockingService\n" + " newReflectiveBlockingService(final BlockingInterface impl) {\n" + " return new com.google.protobuf.BlockingService() {\n"); printer->Indent(); printer->Indent(); @@ -184,167 +183,170 @@ void ImmutableServiceGenerator::GenerateAbstractMethods(io::Printer* printer) { } } -string ImmutableServiceGenerator::GetOutput(const MethodDescriptor* method) { +std::string ImmutableServiceGenerator::GetOutput( + const MethodDescriptor* method) { return name_resolver_->GetImmutableClassName(method->output_type()); } void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) { printer->Print( - "\n" - "public final void callMethod(\n" - " com.google.protobuf.Descriptors.MethodDescriptor method,\n" - " com.google.protobuf.RpcController controller,\n" - " com.google.protobuf.Message request,\n" - " com.google.protobuf.RpcCallback<\n" - " com.google.protobuf.Message> done) {\n" - " if (method.getService() != getDescriptor()) {\n" - " throw new java.lang.IllegalArgumentException(\n" - " \"Service.callMethod() given method descriptor for wrong \" +\n" - " \"service type.\");\n" - " }\n" - " switch(method.getIndex()) {\n"); + "\n" + "public final void callMethod(\n" + " com.google.protobuf.Descriptors.MethodDescriptor method,\n" + " com.google.protobuf.RpcController controller,\n" + " com.google.protobuf.Message request,\n" + " com.google.protobuf.RpcCallback<\n" + " com.google.protobuf.Message> done) {\n" + " if (method.getService() != getDescriptor()) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"Service.callMethod() given method descriptor for wrong \" +\n" + " \"service type.\");\n" + " }\n" + " switch(method.getIndex()) {\n"); printer->Indent(); printer->Indent(); for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - std::map vars; - vars["index"] = SimpleItoa(i); + std::map vars; + vars["index"] = StrCat(i); vars["method"] = UnderscoresToCamelCase(method); - vars["input"] = name_resolver_->GetImmutableClassName( - method->input_type()); + vars["input"] = name_resolver_->GetImmutableClassName(method->input_type()); vars["output"] = GetOutput(method); - printer->Print(vars, - "case $index$:\n" - " this.$method$(controller, ($input$)request,\n" - " com.google.protobuf.RpcUtil.<$output$>specializeCallback(\n" - " done));\n" - " return;\n"); + printer->Print( + vars, + "case $index$:\n" + " this.$method$(controller, ($input$)request,\n" + " com.google.protobuf.RpcUtil.<$output$>specializeCallback(\n" + " done));\n" + " return;\n"); } printer->Print( - "default:\n" - " throw new java.lang.AssertionError(\"Can't get here.\");\n"); + "default:\n" + " throw new java.lang.AssertionError(\"Can't get here.\");\n"); printer->Outdent(); printer->Outdent(); printer->Print( - " }\n" - "}\n" - "\n"); + " }\n" + "}\n" + "\n"); } void ImmutableServiceGenerator::GenerateCallBlockingMethod( io::Printer* printer) { printer->Print( - "\n" - "public final com.google.protobuf.Message callBlockingMethod(\n" - " com.google.protobuf.Descriptors.MethodDescriptor method,\n" - " com.google.protobuf.RpcController controller,\n" - " com.google.protobuf.Message request)\n" - " throws com.google.protobuf.ServiceException {\n" - " if (method.getService() != getDescriptor()) {\n" - " throw new java.lang.IllegalArgumentException(\n" - " \"Service.callBlockingMethod() given method descriptor for \" +\n" - " \"wrong service type.\");\n" - " }\n" - " switch(method.getIndex()) {\n"); + "\n" + "public final com.google.protobuf.Message callBlockingMethod(\n" + " com.google.protobuf.Descriptors.MethodDescriptor method,\n" + " com.google.protobuf.RpcController controller,\n" + " com.google.protobuf.Message request)\n" + " throws com.google.protobuf.ServiceException {\n" + " if (method.getService() != getDescriptor()) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"Service.callBlockingMethod() given method descriptor for \" +\n" + " \"wrong service type.\");\n" + " }\n" + " switch(method.getIndex()) {\n"); printer->Indent(); printer->Indent(); for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - std::map vars; - vars["index"] = SimpleItoa(i); + std::map vars; + vars["index"] = StrCat(i); vars["method"] = UnderscoresToCamelCase(method); - vars["input"] = name_resolver_->GetImmutableClassName( - method->input_type()); + vars["input"] = name_resolver_->GetImmutableClassName(method->input_type()); vars["output"] = GetOutput(method); printer->Print(vars, - "case $index$:\n" - " return impl.$method$(controller, ($input$)request);\n"); + "case $index$:\n" + " return impl.$method$(controller, ($input$)request);\n"); } printer->Print( - "default:\n" - " throw new java.lang.AssertionError(\"Can't get here.\");\n"); + "default:\n" + " throw new java.lang.AssertionError(\"Can't get here.\");\n"); printer->Outdent(); printer->Outdent(); printer->Print( - " }\n" - "}\n" - "\n"); + " }\n" + "}\n" + "\n"); } void ImmutableServiceGenerator::GenerateGetPrototype(RequestOrResponse which, - io::Printer* printer) { + io::Printer* printer) { /* * TODO(cpovirk): The exception message says "Service.foo" when it may be * "BlockingService.foo." Consider fixing. */ printer->Print( - "public final com.google.protobuf.Message\n" - " get$request_or_response$Prototype(\n" - " com.google.protobuf.Descriptors.MethodDescriptor method) {\n" - " if (method.getService() != getDescriptor()) {\n" - " throw new java.lang.IllegalArgumentException(\n" - " \"Service.get$request_or_response$Prototype() given method \" +\n" - " \"descriptor for wrong service type.\");\n" - " }\n" - " switch(method.getIndex()) {\n", - "request_or_response", (which == REQUEST) ? "Request" : "Response"); + "public final com.google.protobuf.Message\n" + " get$request_or_response$Prototype(\n" + " com.google.protobuf.Descriptors.MethodDescriptor method) {\n" + " if (method.getService() != getDescriptor()) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"Service.get$request_or_response$Prototype() given method \" +\n" + " \"descriptor for wrong service type.\");\n" + " }\n" + " switch(method.getIndex()) {\n", + "request_or_response", (which == REQUEST) ? "Request" : "Response"); printer->Indent(); printer->Indent(); for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - std::map vars; - vars["index"] = SimpleItoa(i); - vars["type"] = name_resolver_->GetImmutableClassName( - (which == REQUEST) ? method->input_type() : method->output_type()); + std::map vars; + vars["index"] = StrCat(i); + vars["type"] = + (which == REQUEST) + ? name_resolver_->GetImmutableClassName(method->input_type()) + : GetOutput(method); printer->Print(vars, - "case $index$:\n" - " return $type$.getDefaultInstance();\n"); + "case $index$:\n" + " return $type$.getDefaultInstance();\n"); } printer->Print( - "default:\n" - " throw new java.lang.AssertionError(\"Can't get here.\");\n"); + "default:\n" + " throw new java.lang.AssertionError(\"Can't get here.\");\n"); printer->Outdent(); printer->Outdent(); printer->Print( - " }\n" - "}\n" - "\n"); + " }\n" + "}\n" + "\n"); } void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) { printer->Print( - "public static Stub newStub(\n" - " com.google.protobuf.RpcChannel channel) {\n" - " return new Stub(channel);\n" - "}\n" - "\n" - "public static final class Stub extends $classname$ implements Interface {" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "public static Stub newStub(\n" + " com.google.protobuf.RpcChannel channel) {\n" + " return new Stub(channel);\n" + "}\n" + "\n" + "public static final class Stub extends $classname$ implements Interface " + "{" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Indent(); printer->Print( - "private Stub(com.google.protobuf.RpcChannel channel) {\n" - " this.channel = channel;\n" - "}\n" - "\n" - "private final com.google.protobuf.RpcChannel channel;\n" - "\n" - "public com.google.protobuf.RpcChannel getChannel() {\n" - " return channel;\n" - "}\n"); + "private Stub(com.google.protobuf.RpcChannel channel) {\n" + " this.channel = channel;\n" + "}\n" + "\n" + "private final com.google.protobuf.RpcChannel channel;\n" + "\n" + "public com.google.protobuf.RpcChannel getChannel() {\n" + " return channel;\n" + "}\n"); for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); @@ -353,19 +355,19 @@ void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) { printer->Print(" {\n"); printer->Indent(); - std::map vars; - vars["index"] = SimpleItoa(i); + std::map vars; + vars["index"] = StrCat(i); vars["output"] = GetOutput(method); printer->Print(vars, - "channel.callMethod(\n" - " getDescriptor().getMethods().get($index$),\n" - " controller,\n" - " request,\n" - " $output$.getDefaultInstance(),\n" - " com.google.protobuf.RpcUtil.generalizeCallback(\n" - " done,\n" - " $output$.class,\n" - " $output$.getDefaultInstance()));\n"); + "channel.callMethod(\n" + " getDescriptor().getMethods().get($index$),\n" + " controller,\n" + " request,\n" + " $output$.getDefaultInstance(),\n" + " com.google.protobuf.RpcUtil.generalizeCallback(\n" + " done,\n" + " $output$.class,\n" + " $output$.getDefaultInstance()));\n"); printer->Outdent(); printer->Print("}\n"); @@ -373,20 +375,19 @@ void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) { printer->Outdent(); printer->Print( - "}\n" - "\n"); + "}\n" + "\n"); } void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) { printer->Print( - "public static BlockingInterface newBlockingStub(\n" - " com.google.protobuf.BlockingRpcChannel channel) {\n" - " return new BlockingStub(channel);\n" - "}\n" - "\n"); + "public static BlockingInterface newBlockingStub(\n" + " com.google.protobuf.BlockingRpcChannel channel) {\n" + " return new BlockingStub(channel);\n" + "}\n" + "\n"); - printer->Print( - "public interface BlockingInterface {"); + printer->Print("public interface BlockingInterface {"); printer->Indent(); for (int i = 0; i < descriptor_->method_count(); i++) { @@ -397,19 +398,20 @@ void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) { printer->Outdent(); printer->Print( - "}\n" - "\n"); + "}\n" + "\n"); printer->Print( - "private static final class BlockingStub implements BlockingInterface {\n"); + "private static final class BlockingStub implements BlockingInterface " + "{\n"); printer->Indent(); printer->Print( - "private BlockingStub(com.google.protobuf.BlockingRpcChannel channel) {\n" - " this.channel = channel;\n" - "}\n" - "\n" - "private final com.google.protobuf.BlockingRpcChannel channel;\n"); + "private BlockingStub(com.google.protobuf.BlockingRpcChannel channel) {\n" + " this.channel = channel;\n" + "}\n" + "\n" + "private final com.google.protobuf.BlockingRpcChannel channel;\n"); for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); @@ -417,54 +419,53 @@ void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) { printer->Print(" {\n"); printer->Indent(); - std::map vars; - vars["index"] = SimpleItoa(i); + std::map vars; + vars["index"] = StrCat(i); vars["output"] = GetOutput(method); printer->Print(vars, - "return ($output$) channel.callBlockingMethod(\n" - " getDescriptor().getMethods().get($index$),\n" - " controller,\n" - " request,\n" - " $output$.getDefaultInstance());\n"); + "return ($output$) channel.callBlockingMethod(\n" + " getDescriptor().getMethods().get($index$),\n" + " controller,\n" + " request,\n" + " $output$.getDefaultInstance());\n"); printer->Outdent(); printer->Print( - "}\n" - "\n"); + "}\n" + "\n"); } printer->Outdent(); printer->Print("}\n"); } -void ImmutableServiceGenerator::GenerateMethodSignature(io::Printer* printer, - const MethodDescriptor* method, - IsAbstract is_abstract) { - std::map vars; +void ImmutableServiceGenerator::GenerateMethodSignature( + io::Printer* printer, const MethodDescriptor* method, + IsAbstract is_abstract) { + std::map vars; vars["name"] = UnderscoresToCamelCase(method); vars["input"] = name_resolver_->GetImmutableClassName(method->input_type()); vars["output"] = GetOutput(method); vars["abstract"] = (is_abstract == IS_ABSTRACT) ? "abstract" : ""; printer->Print(vars, - "public $abstract$ void $name$(\n" - " com.google.protobuf.RpcController controller,\n" - " $input$ request,\n" - " com.google.protobuf.RpcCallback<$output$> done)"); + "public $abstract$ void $name$(\n" + " com.google.protobuf.RpcController controller,\n" + " $input$ request,\n" + " com.google.protobuf.RpcCallback<$output$> done)"); } void ImmutableServiceGenerator::GenerateBlockingMethodSignature( - io::Printer* printer, - const MethodDescriptor* method) { - std::map vars; + io::Printer* printer, const MethodDescriptor* method) { + std::map vars; vars["method"] = UnderscoresToCamelCase(method); vars["input"] = name_resolver_->GetImmutableClassName(method->input_type()); vars["output"] = GetOutput(method); printer->Print(vars, - "\n" - "public $output$ $method$(\n" - " com.google.protobuf.RpcController controller,\n" - " $input$ request)\n" - " throws com.google.protobuf.ServiceException"); + "\n" + "public $output$ $method$(\n" + " com.google.protobuf.RpcController controller,\n" + " $input$ request)\n" + " throws com.google.protobuf.ServiceException"); } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_service.h b/src/google/protobuf/compiler/java/java_service.h index 12b3f94266fff..1c82c16c1c0b1 100644 --- a/src/google/protobuf/compiler/java/java_service.h +++ b/src/google/protobuf/compiler/java/java_service.h @@ -40,17 +40,19 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -81,7 +83,6 @@ class ImmutableServiceGenerator : public ServiceGenerator { virtual void Generate(io::Printer* printer); private: - // Generate the getDescriptorForType() method. void GenerateGetDescriptorForType(io::Printer* printer); @@ -123,7 +124,7 @@ class ImmutableServiceGenerator : public ServiceGenerator { const MethodDescriptor* method); // Return the output type of the method. - string GetOutput(const MethodDescriptor* method); + std::string GetOutput(const MethodDescriptor* method); Context* context_; ClassNameResolver* name_resolver_; @@ -133,6 +134,6 @@ class ImmutableServiceGenerator : public ServiceGenerator { } // namespace java } // namespace compiler } // namespace protobuf +} // namespace google #endif // NET_PROTO2_COMPILER_JAVA_SERVICE_H__ -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc index f73bfb0461898..45943d76226df 100644 --- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc +++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc @@ -33,16 +33,14 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include +#include #include +#include #include #include -#include #include #include @@ -55,29 +53,28 @@ SharedCodeGenerator::SharedCodeGenerator(const FileDescriptor* file, const Options& options) : name_resolver_(new ClassNameResolver), file_(file), options_(options) {} -SharedCodeGenerator::~SharedCodeGenerator() { -} +SharedCodeGenerator::~SharedCodeGenerator() {} -void SharedCodeGenerator::Generate(GeneratorContext* context, - std::vector* file_list, - std::vector* annotation_file_list) { - string java_package = FileJavaPackage(file_); - string package_dir = JavaPackageToDir(java_package); +void SharedCodeGenerator::Generate( + GeneratorContext* context, std::vector* file_list, + std::vector* annotation_file_list) { + std::string java_package = FileJavaPackage(file_); + std::string package_dir = JavaPackageToDir(java_package); if (HasDescriptorMethods(file_, options_.enforce_lite)) { // Generate descriptors. - string classname = name_resolver_->GetDescriptorClassName(file_); - string filename = package_dir + classname + ".java"; + std::string classname = name_resolver_->GetDescriptorClassName(file_); + std::string filename = package_dir + classname + ".java"; file_list->push_back(filename); - google::protobuf::scoped_ptr output(context->Open(filename)); + std::unique_ptr output(context->Open(filename)); GeneratedCodeInfo annotations; io::AnnotationProtoCollector annotation_collector( &annotations); - google::protobuf::scoped_ptr printer( + std::unique_ptr printer( new io::Printer(output.get(), '$', options_.annotate_code ? &annotation_collector : NULL)); - string info_relative_path = classname + ".java.pb.meta"; - string info_full_path = filename + ".pb.meta"; + std::string info_relative_path = classname + ".java.pb.meta"; + std::string info_full_path = filename + ".pb.meta"; printer->Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" "// source: $filename$\n" @@ -85,9 +82,9 @@ void SharedCodeGenerator::Generate(GeneratorContext* context, "filename", file_->name()); if (!java_package.empty()) { printer->Print( - "package $package$;\n" - "\n", - "package", java_package); + "package $package$;\n" + "\n", + "package", java_package); } PrintGeneratedAnnotation(printer.get(), '$', options_.annotate_code ? info_relative_path : ""); @@ -104,11 +101,11 @@ void SharedCodeGenerator::Generate(GeneratorContext* context, printer->Outdent(); printer->Outdent(); printer->Print( - " }\n" - "}\n"); + " }\n" + "}\n"); if (options_.annotate_code) { - google::protobuf::scoped_ptr info_output( + std::unique_ptr info_output( context->Open(info_full_path)); annotations.SerializeToZeroCopyStream(info_output.get()); annotation_file_list->push_back(info_full_path); @@ -133,59 +130,43 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { FileDescriptorProto file_proto; file_->CopyTo(&file_proto); - string file_data; + std::string file_data; file_proto.SerializeToString(&file_data); - printer->Print( - "java.lang.String[] descriptorData = {\n"); + printer->Print("java.lang.String[] descriptorData = {\n"); printer->Indent(); - // Only write 40 bytes per line. + // Limit the number of bytes per line. static const int kBytesPerLine = 40; + // Limit the number of lines per string part. + static const int kLinesPerPart = 400; + // Every block of bytes, start a new string literal, in order to avoid the + // 64k length limit. Note that this value needs to be <64k. + static const int kBytesPerPart = kBytesPerLine * kLinesPerPart; for (int i = 0; i < file_data.size(); i += kBytesPerLine) { if (i > 0) { - // Every 400 lines, start a new string literal, in order to avoid the - // 64k length limit. - if (i % 400 == 0) { + if (i % kBytesPerPart == 0) { printer->Print(",\n"); } else { printer->Print(" +\n"); } } - printer->Print("\"$data$\"", - "data", CEscape(file_data.substr(i, kBytesPerLine))); + printer->Print("\"$data$\"", "data", + CEscape(file_data.substr(i, kBytesPerLine))); } printer->Outdent(); printer->Print("\n};\n"); - // ----------------------------------------------------------------- - // Create the InternalDescriptorAssigner. - - printer->Print( - "com.google.protobuf.Descriptors.FileDescriptor." - "InternalDescriptorAssigner assigner =\n" - " new com.google.protobuf.Descriptors.FileDescriptor." - " InternalDescriptorAssigner() {\n" - " public com.google.protobuf.ExtensionRegistry assignDescriptors(\n" - " com.google.protobuf.Descriptors.FileDescriptor root) {\n" - " descriptor = root;\n" - // Custom options will be handled when immutable messages' outer class is - // loaded. Here we just return null and let custom options be unknown - // fields. - " return null;\n" - " }\n" - " };\n"); - // ----------------------------------------------------------------- // Find out all dependencies. - std::vector > dependencies; + std::vector > dependencies; for (int i = 0; i < file_->dependency_count(); i++) { - string filename = file_->dependency(i)->name(); - string package = FileJavaPackage(file_->dependency(i)); - string classname = name_resolver_->GetDescriptorClassName( - file_->dependency(i)); - string full_name; + std::string filename = file_->dependency(i)->name(); + std::string package = FileJavaPackage(file_->dependency(i)); + std::string classname = + name_resolver_->GetDescriptorClassName(file_->dependency(i)); + std::string full_name; if (package.empty()) { full_name = classname; } else { @@ -197,20 +178,18 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { // ----------------------------------------------------------------- // Invoke internalBuildGeneratedFileFrom() to build the file. printer->Print( - "com.google.protobuf.Descriptors.FileDescriptor\n" - " .internalBuildGeneratedFileFrom(descriptorData,\n"); + "descriptor = com.google.protobuf.Descriptors.FileDescriptor\n" + " .internalBuildGeneratedFileFrom(descriptorData,\n"); printer->Print( - " new com.google.protobuf.Descriptors.FileDescriptor[] {\n"); + " new com.google.protobuf.Descriptors.FileDescriptor[] {\n"); for (int i = 0; i < dependencies.size(); i++) { - const string& dependency = dependencies[i].second; - printer->Print( - " $dependency$.getDescriptor(),\n", - "dependency", dependency); + const std::string& dependency = dependencies[i].second; + printer->Print(" $dependency$.getDescriptor(),\n", "dependency", + dependency); } - printer->Print( - " }, assigner);\n"); + printer->Print(" });\n"); } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.h b/src/google/protobuf/compiler/java/java_shared_code_generator.h index 40502270acbfe..7c79abe2e11f4 100644 --- a/src/google/protobuf/compiler/java/java_shared_code_generator.h +++ b/src/google/protobuf/compiler/java/java_shared_code_generator.h @@ -36,9 +36,6 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__ #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include @@ -47,18 +44,20 @@ namespace google { namespace protobuf { - class FileDescriptor; // descriptor.h - namespace compiler { - class GeneratorContext; // code_generator.h - namespace java { - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +class FileDescriptor; // descriptor.h +namespace compiler { +class GeneratorContext; // code_generator.h +namespace java { +class ClassNameResolver; // name_resolver.h } +} // namespace compiler +namespace io { +class Printer; // printer.h +} +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -71,22 +70,21 @@ class SharedCodeGenerator { ~SharedCodeGenerator(); void Generate(GeneratorContext* generator_context, - std::vector* file_list, - std::vector* annotation_file_list); + std::vector* file_list, + std::vector* annotation_file_list); void GenerateDescriptors(io::Printer* printer); private: - google::protobuf::scoped_ptr name_resolver_; + std::unique_ptr name_resolver_; const FileDescriptor* file_; const Options options_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SharedCodeGenerator); }; - } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc index 2b6e9381802d9..485fcf812e8d5 100644 --- a/src/google/protobuf/compiler/java/java_string_field.cc +++ b/src/google/protobuf/compiler/java/java_string_field.cc @@ -58,11 +58,10 @@ using internal::WireFormatLite; namespace { void SetPrimitiveVariables(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, + int messageBitIndex, int builderBitIndex, const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, - std::map* variables) { + std::map* variables) { SetCommonFieldVariables(descriptor, info, variables); (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY"; @@ -72,27 +71,26 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, "= " + ImmutableDefaultValue(descriptor, name_resolver); (*variables)["capitalized_type"] = "String"; (*variables)["tag"] = - SimpleItoa(static_cast(WireFormat::MakeTag(descriptor))); - (*variables)["tag_size"] = SimpleItoa( + StrCat(static_cast(WireFormat::MakeTag(descriptor))); + (*variables)["tag_size"] = StrCat( WireFormat::TagSize(descriptor->number(), GetType(descriptor))); (*variables)["null_check"] = " if (value == null) {\n" " throw new NullPointerException();\n" " }\n"; - (*variables)["writeString"] = - "com.google.protobuf.GeneratedMessage" + GeneratedCodeVersionSuffix() + - ".writeString"; - (*variables)["computeStringSize"] = - "com.google.protobuf.GeneratedMessage" + GeneratedCodeVersionSuffix() + - ".computeStringSize"; + (*variables)["writeString"] = "com.google.protobuf.GeneratedMessage" + + GeneratedCodeVersionSuffix() + ".writeString"; + (*variables)["computeStringSize"] = "com.google.protobuf.GeneratedMessage" + + GeneratedCodeVersionSuffix() + + ".computeStringSize"; // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler - (*variables)["deprecation"] = descriptor->options().deprecated() - ? "@java.lang.Deprecated " : ""; + (*variables)["deprecation"] = + descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; (*variables)["on_changed"] = "onChanged();"; - if (SupportFieldPresence(descriptor->file())) { + if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); @@ -137,14 +135,10 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, // =================================================================== -ImmutableStringFieldGenerator:: -ImmutableStringFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { +ImmutableStringFieldGenerator::ImmutableStringFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + Context* context) + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); @@ -153,17 +147,17 @@ ImmutableStringFieldGenerator(const FieldDescriptor* descriptor, ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {} int ImmutableStringFieldGenerator::GetNumBitsForMessage() const { - return 1; + return HasHasbit(descriptor_) ? 1 : 0; } int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const { - return 1; + return GetNumBitsForMessage(); } // A note about how strings are handled. This code used to just store a String // in the Message. This had two issues: // -// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded +// 1. It wouldn't roundtrip byte arrays that were not valid UTF-8 encoded // strings, but rather fields that were raw bytes incorrectly marked // as strings in the proto file. This is common because in the proto1 // syntax, string was the way to indicate bytes and C++ engineers can @@ -192,534 +186,538 @@ int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const { // For single fields, the logic for this is done inside the generated code. For // repeated fields, the logic is done in LazyStringArrayList and // UnmodifiableLazyStringList. -void ImmutableStringFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); +void ImmutableStringFieldGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); + "$deprecation$boolean has$capitalized_name$();\n"); } - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$java.lang.String get$capitalized_name$();\n"); - WriteFieldDocComment(printer, descriptor_); + "$deprecation$java.lang.String get$capitalized_name$();\n"); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$com.google.protobuf.ByteString\n" - " get$capitalized_name$Bytes();\n"); + "$deprecation$com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes();\n"); } -void ImmutableStringFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private volatile java.lang.Object $name$_;\n"); +void ImmutableStringFieldGenerator::GenerateMembers( + io::Printer* printer) const { + printer->Print(variables_, "private volatile java.lang.Object $name$_;\n"); PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" - " java.lang.Object ref = $name$_;\n" - " if (ref instanceof java.lang.String) {\n" - " return (java.lang.String) ref;\n" - " } else {\n" - " com.google.protobuf.ByteString bs = \n" - " (com.google.protobuf.ByteString) ref;\n" + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" + " java.lang.Object ref = $name$_;\n" + " if (ref instanceof java.lang.String) {\n" + " return (java.lang.String) ref;\n" + " } else {\n" + " com.google.protobuf.ByteString bs = \n" + " (com.google.protobuf.ByteString) ref;\n" " java.lang.String s = bs.toStringUtf8();\n"); printer->Annotate("{", "}", descriptor_); if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " $name$_ = s;\n"); + printer->Print(variables_, " $name$_ = s;\n"); } else { printer->Print(variables_, - " if (bs.isValidUtf8()) {\n" - " $name$_ = s;\n" - " }\n"); + " if (bs.isValidUtf8()) {\n" + " $name$_ = s;\n" + " }\n"); } printer->Print(variables_, - " return s;\n" - " }\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " ${$get$capitalized_name$Bytes$}$() {\n" - " java.lang.Object ref = $name$_;\n" - " if (ref instanceof java.lang.String) {\n" - " com.google.protobuf.ByteString b = \n" - " com.google.protobuf.ByteString.copyFromUtf8(\n" - " (java.lang.String) ref);\n" - " $name$_ = b;\n" - " return b;\n" - " } else {\n" - " return (com.google.protobuf.ByteString) ref;\n" - " }\n" - "}\n"); + " return s;\n" + " }\n" + "}\n"); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public com.google.protobuf.ByteString\n" + " ${$get$capitalized_name$Bytes$}$() {\n" + " java.lang.Object ref = $name$_;\n" + " if (ref instanceof java.lang.String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " (java.lang.String) ref);\n" + " $name$_ = b;\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutableStringFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - printer->Print(variables_, - "private java.lang.Object $name$_ $default_init$;\n"); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); +void ImmutableStringFieldGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + printer->Print(variables_, + "private java.lang.Object $name$_ $default_init$;\n"); + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print( + variables_, + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" - " java.lang.Object ref = $name$_;\n" - " if (!(ref instanceof java.lang.String)) {\n" - " com.google.protobuf.ByteString bs =\n" - " (com.google.protobuf.ByteString) ref;\n" - " java.lang.String s = bs.toStringUtf8();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" + " java.lang.Object ref = $name$_;\n" + " if (!(ref instanceof java.lang.String)) {\n" + " com.google.protobuf.ByteString bs =\n" + " (com.google.protobuf.ByteString) ref;\n" + " java.lang.String s = bs.toStringUtf8();\n"); printer->Annotate("{", "}", descriptor_); if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " $name$_ = s;\n"); + printer->Print(variables_, " $name$_ = s;\n"); } else { printer->Print(variables_, - " if (bs.isValidUtf8()) {\n" - " $name$_ = s;\n" - " }\n"); + " if (bs.isValidUtf8()) {\n" + " $name$_ = s;\n" + " }\n"); } printer->Print(variables_, - " return s;\n" - " } else {\n" - " return (java.lang.String) ref;\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " ${$get$capitalized_name$Bytes$}$() {\n" - " java.lang.Object ref = $name$_;\n" - " if (ref instanceof String) {\n" - " com.google.protobuf.ByteString b = \n" - " com.google.protobuf.ByteString.copyFromUtf8(\n" - " (java.lang.String) ref);\n" - " $name$_ = b;\n" - " return b;\n" - " } else {\n" - " return (com.google.protobuf.ByteString) ref;\n" - " }\n" - "}\n"); + " return s;\n" + " } else {\n" + " return (java.lang.String) ref;\n" + " }\n" + "}\n"); + + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " ${$get$capitalized_name$Bytes$}$() {\n" + " java.lang.Object ref = $name$_;\n" + " if (ref instanceof String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " (java.lang.String) ref);\n" + " $name$_ = b;\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " java.lang.String value) {\n" - "$null_check$" - " $set_has_field_bit_builder$\n" - " $name$_ = value;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " java.lang.String value) {\n" + "$null_check$" + " $set_has_field_bit_builder$\n" + " $name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " $clear_has_field_bit_builder$\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " $clear_has_field_bit_builder$\n"); printer->Annotate("{", "}", descriptor_); // The default value is not a simple literal so we want to avoid executing // it multiple times. Instead, get the default out of the default instance. printer->Print(variables_, - " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); + " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); printer->Print(variables_, - " $on_changed$\n" - " return this;\n" - "}\n"); + " $on_changed$\n" + " return this;\n" + "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n" - " com.google.protobuf.ByteString value) {\n" - "$null_check$"); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n" + " com.google.protobuf.ByteString value) {\n" + "$null_check$"); printer->Annotate("{", "}", descriptor_); if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " checkByteStringIsUtf8(value);\n"); + printer->Print(variables_, " checkByteStringIsUtf8(value);\n"); } printer->Print(variables_, - " $set_has_field_bit_builder$\n" - " $name$_ = value;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + " $set_has_field_bit_builder$\n" + " $name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); } -void ImmutableStringFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { +void ImmutableStringFieldGenerator::GenerateFieldBuilderInitializationCode( + io::Printer* printer) const { // noop for primitives } -void ImmutableStringFieldGenerator:: -GenerateInitializationCode(io::Printer* printer) const { +void ImmutableStringFieldGenerator::GenerateInitializationCode( + io::Printer* printer) const { printer->Print(variables_, "$name$_ = $default$;\n"); } -void ImmutableStringFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { +void ImmutableStringFieldGenerator::GenerateBuilderClearCode( + io::Printer* printer) const { printer->Print(variables_, - "$name$_ = $default$;\n" - "$clear_has_field_bit_builder$\n"); + "$name$_ = $default$;\n" + "$clear_has_field_bit_builder$\n"); } -void ImmutableStringFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { +void ImmutableStringFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { // Allow a slight breach of abstraction here in order to avoid forcing // all string fields to Strings when copying fields from a Message. printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " $set_has_field_bit_builder$\n" - " $name$_ = other.$name$_;\n" - " $on_changed$\n" - "}\n"); + "if (other.has$capitalized_name$()) {\n" + " $set_has_field_bit_builder$\n" + " $name$_ = other.$name$_;\n" + " $on_changed$\n" + "}\n"); } else { printer->Print(variables_, - "if (!other.get$capitalized_name$().isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " $on_changed$\n" - "}\n"); + "if (!other.get$capitalized_name$().isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $on_changed$\n" + "}\n"); } } -void ImmutableStringFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { +void ImmutableStringFieldGenerator::GenerateBuildingCode( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); } - printer->Print(variables_, - "result.$name$_ = $name$_;\n"); + printer->Print(variables_, "result.$name$_ = $name$_;\n"); } -void ImmutableStringFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +void ImmutableStringFieldGenerator::GenerateParsingCode( + io::Printer* printer) const { if (CheckUtf8(descriptor_)) { printer->Print(variables_, - "java.lang.String s = input.readStringRequireUtf8();\n" - "$set_has_field_bit_message$\n" - "$name$_ = s;\n"); + "java.lang.String s = input.readStringRequireUtf8();\n" + "$set_has_field_bit_message$\n" + "$name$_ = s;\n"); } else { printer->Print(variables_, - "com.google.protobuf.ByteString bs = input.readBytes();\n" - "$set_has_field_bit_message$\n" - "$name$_ = bs;\n"); + "com.google.protobuf.ByteString bs = input.readBytes();\n" + "$set_has_field_bit_message$\n" + "$name$_ = bs;\n"); } } -void ImmutableStringFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { +void ImmutableStringFieldGenerator::GenerateParsingDoneCode( + io::Printer* printer) const { // noop for strings. } -void ImmutableStringFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { +void ImmutableStringFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " $writeString$(output, $number$, $name$_);\n" - "}\n"); + "if ($is_field_present_message$) {\n" + " $writeString$(output, $number$, $name$_);\n" + "}\n"); } -void ImmutableStringFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { +void ImmutableStringFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " size += $computeStringSize$($number$, $name$_);\n" - "}\n"); + "if ($is_field_present_message$) {\n" + " size += $computeStringSize$($number$, $name$_);\n" + "}\n"); } -void ImmutableStringFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { +void ImmutableStringFieldGenerator::GenerateEqualsCode( + io::Printer* printer) const { printer->Print(variables_, - "result = result && get$capitalized_name$()\n" - " .equals(other.get$capitalized_name$());\n"); + "if (!get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$())) return false;\n"); } -void ImmutableStringFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n"); +void ImmutableStringFieldGenerator::GenerateHashCode( + io::Printer* printer) const { + printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n"); printer->Print(variables_, - "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); + "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); } -string ImmutableStringFieldGenerator::GetBoxedType() const { +std::string ImmutableStringFieldGenerator::GetBoxedType() const { return "java.lang.String"; } // =================================================================== -ImmutableStringOneofFieldGenerator:: -ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableStringFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { +ImmutableStringOneofFieldGenerator::ImmutableStringOneofFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + Context* context) + : ImmutableStringFieldGenerator(descriptor, messageBitIndex, + builderBitIndex, context) { const OneofGeneratorInfo* info = context->GetOneofGeneratorInfo(descriptor->containing_oneof()); SetCommonOneofVariables(descriptor, info, &variables_); } -ImmutableStringOneofFieldGenerator:: -~ImmutableStringOneofFieldGenerator() {} +ImmutableStringOneofFieldGenerator::~ImmutableStringOneofFieldGenerator() {} -void ImmutableStringOneofFieldGenerator:: -GenerateMembers(io::Printer* printer) const { +void ImmutableStringOneofFieldGenerator::GenerateMembers( + io::Printer* printer) const { PrintExtraFieldInfo(variables_, printer); - - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); + GOOGLE_DCHECK(HasHazzer(descriptor_)); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" - " java.lang.Object ref $default_init$;\n" - " if ($has_oneof_case_message$) {\n" - " ref = $oneof_name$_;\n" - " }\n" - " if (ref instanceof java.lang.String) {\n" - " return (java.lang.String) ref;\n" - " } else {\n" - " com.google.protobuf.ByteString bs = \n" - " (com.google.protobuf.ByteString) ref;\n" - " java.lang.String s = bs.toStringUtf8();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" + " java.lang.Object ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = $oneof_name$_;\n" + " }\n" + " if (ref instanceof java.lang.String) {\n" + " return (java.lang.String) ref;\n" + " } else {\n" + " com.google.protobuf.ByteString bs = \n" + " (com.google.protobuf.ByteString) ref;\n" + " java.lang.String s = bs.toStringUtf8();\n"); printer->Annotate("{", "}", descriptor_); if (CheckUtf8(descriptor_)) { printer->Print(variables_, - " if ($has_oneof_case_message$) {\n" - " $oneof_name$_ = s;\n" - " }\n"); + " if ($has_oneof_case_message$) {\n" + " $oneof_name$_ = s;\n" + " }\n"); } else { printer->Print(variables_, - " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n" - " $oneof_name$_ = s;\n" - " }\n"); + " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n" + " $oneof_name$_ = s;\n" + " }\n"); } printer->Print(variables_, - " return s;\n" - " }\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " ${$get$capitalized_name$Bytes$}$() {\n" - " java.lang.Object ref $default_init$;\n" - " if ($has_oneof_case_message$) {\n" - " ref = $oneof_name$_;\n" - " }\n" - " if (ref instanceof java.lang.String) {\n" - " com.google.protobuf.ByteString b = \n" - " com.google.protobuf.ByteString.copyFromUtf8(\n" - " (java.lang.String) ref);\n" - " if ($has_oneof_case_message$) {\n" - " $oneof_name$_ = b;\n" - " }\n" - " return b;\n" - " } else {\n" - " return (com.google.protobuf.ByteString) ref;\n" - " }\n" - "}\n"); + " return s;\n" + " }\n" + "}\n"); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER); + + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " ${$get$capitalized_name$Bytes$}$() {\n" + " java.lang.Object ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = $oneof_name$_;\n" + " }\n" + " if (ref instanceof java.lang.String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " (java.lang.String) ref);\n" + " if ($has_oneof_case_message$) {\n" + " $oneof_name$_ = b;\n" + " }\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutableStringOneofFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } - - WriteFieldDocComment(printer, descriptor_); +void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + GOOGLE_DCHECK(HasHazzer(descriptor_)); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" - " java.lang.Object ref $default_init$;\n" - " if ($has_oneof_case_message$) {\n" - " ref = $oneof_name$_;\n" - " }\n" - " if (!(ref instanceof java.lang.String)) {\n" - " com.google.protobuf.ByteString bs =\n" - " (com.google.protobuf.ByteString) ref;\n" - " java.lang.String s = bs.toStringUtf8();\n" - " if ($has_oneof_case_message$) {\n"); + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" + " java.lang.Object ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = $oneof_name$_;\n" + " }\n" + " if (!(ref instanceof java.lang.String)) {\n" + " com.google.protobuf.ByteString bs =\n" + " (com.google.protobuf.ByteString) ref;\n" + " java.lang.String s = bs.toStringUtf8();\n" + " if ($has_oneof_case_message$) {\n"); printer->Annotate("{", "}", descriptor_); if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " $oneof_name$_ = s;\n"); + printer->Print(variables_, " $oneof_name$_ = s;\n"); } else { printer->Print(variables_, - " if (bs.isValidUtf8()) {\n" - " $oneof_name$_ = s;\n" - " }\n"); + " if (bs.isValidUtf8()) {\n" + " $oneof_name$_ = s;\n" + " }\n"); } printer->Print(variables_, - " }\n" - " return s;\n" - " } else {\n" - " return (java.lang.String) ref;\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " ${$get$capitalized_name$Bytes$}$() {\n" - " java.lang.Object ref $default_init$;\n" - " if ($has_oneof_case_message$) {\n" - " ref = $oneof_name$_;\n" - " }\n" - " if (ref instanceof String) {\n" - " com.google.protobuf.ByteString b = \n" - " com.google.protobuf.ByteString.copyFromUtf8(\n" - " (java.lang.String) ref);\n" - " if ($has_oneof_case_message$) {\n" - " $oneof_name$_ = b;\n" - " }\n" - " return b;\n" - " } else {\n" - " return (com.google.protobuf.ByteString) ref;\n" - " }\n" - "}\n"); + " }\n" + " return s;\n" + " } else {\n" + " return (java.lang.String) ref;\n" + " }\n" + "}\n"); + + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public com.google.protobuf.ByteString\n" + " ${$get$capitalized_name$Bytes$}$() {\n" + " java.lang.Object ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = $oneof_name$_;\n" + " }\n" + " if (ref instanceof String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " (java.lang.String) ref);\n" + " if ($has_oneof_case_message$) {\n" + " $oneof_name$_ = b;\n" + " }\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " java.lang.String value) {\n" - "$null_check$" - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " java.lang.String value) {\n" + "$null_check$" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " $on_changed$\n" - " }\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " $on_changed$\n" + " }\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n" - " com.google.protobuf.ByteString value) {\n" - "$null_check$"); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n" + " com.google.protobuf.ByteString value) {\n" + "$null_check$"); printer->Annotate("{", "}", descriptor_); if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " checkByteStringIsUtf8(value);\n"); + printer->Print(variables_, " checkByteStringIsUtf8(value);\n"); } printer->Print(variables_, - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); } -void ImmutableStringOneofFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { +void ImmutableStringOneofFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { // Allow a slight breach of abstraction here in order to avoid forcing // all string fields to Strings when copying fields from a Message. printer->Print(variables_, - "$set_oneof_case_message$;\n" - "$oneof_name$_ = other.$oneof_name$_;\n" - "$on_changed$\n"); + "$set_oneof_case_message$;\n" + "$oneof_name$_ = other.$oneof_name$_;\n" + "$on_changed$\n"); } -void ImmutableStringOneofFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { +void ImmutableStringOneofFieldGenerator::GenerateBuildingCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " result.$oneof_name$_ = $oneof_name$_;\n" - "}\n"); + "if ($has_oneof_case_message$) {\n" + " result.$oneof_name$_ = $oneof_name$_;\n" + "}\n"); } -void ImmutableStringOneofFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +void ImmutableStringOneofFieldGenerator::GenerateParsingCode( + io::Printer* printer) const { if (CheckUtf8(descriptor_)) { printer->Print(variables_, - "java.lang.String s = input.readStringRequireUtf8();\n" - "$set_oneof_case_message$;\n" - "$oneof_name$_ = s;\n"); + "java.lang.String s = input.readStringRequireUtf8();\n" + "$set_oneof_case_message$;\n" + "$oneof_name$_ = s;\n"); } else { printer->Print(variables_, - "com.google.protobuf.ByteString bs = input.readBytes();\n" - "$set_oneof_case_message$;\n" - "$oneof_name$_ = bs;\n"); + "com.google.protobuf.ByteString bs = input.readBytes();\n" + "$set_oneof_case_message$;\n" + "$oneof_name$_ = bs;\n"); } } -void ImmutableStringOneofFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { +void ImmutableStringOneofFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " $writeString$(output, $number$, $oneof_name$_);\n" - "}\n"); + "if ($has_oneof_case_message$) {\n" + " $writeString$(output, $number$, $oneof_name$_);\n" + "}\n"); } -void ImmutableStringOneofFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { +void ImmutableStringOneofFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += $computeStringSize$($number$, $oneof_name$_);\n" - "}\n"); + "if ($has_oneof_case_message$) {\n" + " size += $computeStringSize$($number$, $oneof_name$_);\n" + "}\n"); } // =================================================================== -RepeatedImmutableStringFieldGenerator:: -RepeatedImmutableStringFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { +RepeatedImmutableStringFieldGenerator::RepeatedImmutableStringFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + Context* context) + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); } RepeatedImmutableStringFieldGenerator:: -~RepeatedImmutableStringFieldGenerator() {} + ~RepeatedImmutableStringFieldGenerator() {} int RepeatedImmutableStringFieldGenerator::GetNumBitsForMessage() const { return 0; @@ -729,307 +727,320 @@ int RepeatedImmutableStringFieldGenerator::GetNumBitsForBuilder() const { return 1; } -void RepeatedImmutableStringFieldGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - // NOTE: the same method in the implementation class actually returns - // com.google.protobuf.ProtocolStringList (a subclass of List). It's - // changed between protobuf 2.5.0 release and protobuf 2.6.1 release. - // To retain binary compatibility with both 2.5.0 and 2.6.1 generated - // code, we make this interface method return List so both methods - // with different return types exist in the compiled byte code. - "$deprecation$java.util.List\n" - " get$capitalized_name$List();\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$java.lang.String get$capitalized_name$(int index);\n"); - WriteFieldDocComment(printer, descriptor_); +void RepeatedImmutableStringFieldGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); + printer->Print( + variables_, + // NOTE: the same method in the implementation class actually returns + // com.google.protobuf.ProtocolStringList (a subclass of List). It's + // changed between protobuf 2.5.0 release and protobuf 2.6.1 release. + // To retain binary compatibility with both 2.5.0 and 2.6.1 generated + // code, we make this interface method return List so both methods + // with different return types exist in the compiled byte code. + "$deprecation$java.util.List\n" + " get$capitalized_name$List();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); + printer->Print( + variables_, + "$deprecation$java.lang.String get$capitalized_name$(int index);\n"); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, + LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$com.google.protobuf.ByteString\n" - " get$capitalized_name$Bytes(int index);\n"); + "$deprecation$com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes(int index);\n"); } - -void RepeatedImmutableStringFieldGenerator:: -GenerateMembers(io::Printer* printer) const { +void RepeatedImmutableStringFieldGenerator::GenerateMembers( + io::Printer* printer) const { printer->Print(variables_, - "private com.google.protobuf.LazyStringList $name$_;\n"); + "private com.google.protobuf.LazyStringList $name$_;\n"); PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, - "$deprecation$public com.google.protobuf.ProtocolStringList\n" - " ${$get$capitalized_name$List$}$() {\n" - " return $name$_;\n" // note: unmodifiable list - "}\n"); + "$deprecation$public com.google.protobuf.ProtocolStringList\n" + " ${$get$capitalized_name$List$}$() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return $name$_.size();\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); + printer->Print( + variables_, + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return $name$_.size();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$public java.lang.String " - "${$get$capitalized_name$$}$(int index) {\n" - " return $name$_.get(index);\n" - "}\n"); + "$deprecation$public java.lang.String " + "${$get$capitalized_name$$}$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, + LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " ${$get$capitalized_name$Bytes$}$(int index) {\n" - " return $name$_.getByteString(index);\n" - "}\n"); + "$deprecation$public com.google.protobuf.ByteString\n" + " ${$get$capitalized_name$Bytes$}$(int index) {\n" + " return $name$_.getByteString(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void RepeatedImmutableStringFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { +void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers( + io::Printer* printer) const { // One field is the list and the bit field keeps track of whether the // list is immutable. If it's immutable, the invariant is that it must // either an instance of Collections.emptyList() or it's an ArrayList // wrapped in a Collections.unmodifiableList() wrapper and nobody else has - // a refererence to the underlying ArrayList. This invariant allows us to + // a reference to the underlying ArrayList. This invariant allows us to // share instances of lists between protocol buffers avoiding expensive // memory allocations. Note, immutable is a strong guarantee here -- not // just that the list cannot be modified via the reference but that the // list can never be modified. - printer->Print(variables_, - "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n"); + printer->Print( + variables_, + "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n"); + printer->Print( + variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n"); + + // Note: We return an unmodifiable list because otherwise the caller + // could hold on to the returned list and modify it after the message + // has been built, thus mutating the message which is supposed to be + // immutable. + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$get_mutable_bit_builder$) {\n" - " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n" - " $set_mutable_bit_builder$;\n" - " }\n" - "}\n"); - - // Note: We return an unmodifiable list because otherwise the caller - // could hold on to the returned list and modify it after the message - // has been built, thus mutating the message which is supposed to be - // immutable. - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ProtocolStringList\n" - " ${$get$capitalized_name$List$}$() {\n" - " return $name$_.getUnmodifiableView();\n" - "}\n"); + "$deprecation$public com.google.protobuf.ProtocolStringList\n" + " ${$get$capitalized_name$List$}$() {\n" + " return $name$_.getUnmodifiableView();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return $name$_.size();\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); + printer->Print( + variables_, + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return $name$_.size();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$public java.lang.String " - "${$get$capitalized_name$$}$(int index) {\n" - " return $name$_.get(index);\n" - "}\n"); + "$deprecation$public java.lang.String " + "${$get$capitalized_name$$}$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, + LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " ${$get$capitalized_name$Bytes$}$(int index) {\n" - " return $name$_.getByteString(index);\n" - "}\n"); + "$deprecation$public com.google.protobuf.ByteString\n" + " ${$get$capitalized_name$Bytes$}$(int index) {\n" + " return $name$_.getByteString(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " int index, java.lang.String value) {\n" - "$null_check$" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, value);\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " int index, java.lang.String value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" - " java.lang.String value) {\n" - "$null_check$" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value);\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" + " java.lang.String value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" - " java.lang.Iterable values) {\n" - " ensure$capitalized_name$IsMutable();\n" - " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" - " values, $name$_);\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" + " values, $name$_);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " $name$_ = $empty_list$;\n" - " $clear_mutable_bit_builder$;\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " $name$_ = $empty_list$;\n" + " $clear_mutable_bit_builder$;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n" - " com.google.protobuf.ByteString value) {\n" - "$null_check$"); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, LIST_ADDER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n" + " com.google.protobuf.ByteString value) {\n" + "$null_check$"); printer->Annotate("{", "}", descriptor_); if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " checkByteStringIsUtf8(value);\n"); + printer->Print(variables_, " checkByteStringIsUtf8(value);\n"); } printer->Print(variables_, - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value);\n" - " $on_changed$\n" - " return this;\n" - "}\n"); + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); } void RepeatedImmutableStringFieldGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + GenerateFieldBuilderInitializationCode(io::Printer* printer) const { // noop for primitives } -void RepeatedImmutableStringFieldGenerator:: -GenerateInitializationCode(io::Printer* printer) const { +void RepeatedImmutableStringFieldGenerator::GenerateInitializationCode( + io::Printer* printer) const { printer->Print(variables_, "$name$_ = $empty_list$;\n"); } -void RepeatedImmutableStringFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { +void RepeatedImmutableStringFieldGenerator::GenerateBuilderClearCode( + io::Printer* printer) const { printer->Print(variables_, - "$name$_ = $empty_list$;\n" - "$clear_mutable_bit_builder$;\n"); + "$name$_ = $empty_list$;\n" + "$clear_mutable_bit_builder$;\n"); } -void RepeatedImmutableStringFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { +void RepeatedImmutableStringFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { // The code below does two optimizations: // 1. If the other list is empty, there's nothing to do. This ensures we // don't allocate a new array if we already have an immutable one. // 2. If the other list is non-empty and our current list is empty, we can // reuse the other list which is guaranteed to be immutable. printer->Print(variables_, - "if (!other.$name$_.isEmpty()) {\n" - " if ($name$_.isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " $clear_mutable_bit_builder$;\n" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" - " }\n" - " $on_changed$\n" - "}\n"); + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n"); } -void RepeatedImmutableStringFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { +void RepeatedImmutableStringFieldGenerator::GenerateBuildingCode( + io::Printer* printer) const { // The code below ensures that the result has an immutable list. If our // list is immutable, we can just reuse it. If not, we make it immutable. printer->Print(variables_, - "if ($get_mutable_bit_builder$) {\n" - " $name$_ = $name$_.getUnmodifiableView();\n" - " $clear_mutable_bit_builder$;\n" - "}\n" - "result.$name$_ = $name$_;\n"); + "if ($get_mutable_bit_builder$) {\n" + " $name$_ = $name$_.getUnmodifiableView();\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); } -void RepeatedImmutableStringFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { +void RepeatedImmutableStringFieldGenerator::GenerateParsingCode( + io::Printer* printer) const { if (CheckUtf8(descriptor_)) { printer->Print(variables_, - "java.lang.String s = input.readStringRequireUtf8();\n"); + "java.lang.String s = input.readStringRequireUtf8();\n"); } else { printer->Print(variables_, - "com.google.protobuf.ByteString bs = input.readBytes();\n"); + "com.google.protobuf.ByteString bs = input.readBytes();\n"); } printer->Print(variables_, - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" - " $set_mutable_bit_parser$;\n" - "}\n"); + "if (!$get_mutable_bit_parser$) {\n" + " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" + " $set_mutable_bit_parser$;\n" + "}\n"); if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - "$name$_.add(s);\n"); + printer->Print(variables_, "$name$_.add(s);\n"); } else { - printer->Print(variables_, - "$name$_.add(bs);\n"); + printer->Print(variables_, "$name$_.add(bs);\n"); } } -void RepeatedImmutableStringFieldGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { +void RepeatedImmutableStringFieldGenerator::GenerateParsingDoneCode( + io::Printer* printer) const { printer->Print(variables_, - "if ($get_mutable_bit_parser$) {\n" - " $name$_ = $name$_.getUnmodifiableView();\n" - "}\n"); + "if ($get_mutable_bit_parser$) {\n" + " $name$_ = $name$_.getUnmodifiableView();\n" + "}\n"); } -void RepeatedImmutableStringFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { +void RepeatedImmutableStringFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " $writeString$(output, $number$, $name$_.getRaw(i));\n" - "}\n"); + "for (int i = 0; i < $name$_.size(); i++) {\n" + " $writeString$(output, $number$, $name$_.getRaw(i));\n" + "}\n"); } -void RepeatedImmutableStringFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { +void RepeatedImmutableStringFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { printer->Print(variables_, - "{\n" - " int dataSize = 0;\n"); + "{\n" + " int dataSize = 0;\n"); printer->Indent(); printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " dataSize += computeStringSizeNoTag($name$_.getRaw(i));\n" - "}\n"); + "for (int i = 0; i < $name$_.size(); i++) {\n" + " dataSize += computeStringSizeNoTag($name$_.getRaw(i));\n" + "}\n"); - printer->Print( - "size += dataSize;\n"); + printer->Print("size += dataSize;\n"); printer->Print(variables_, - "size += $tag_size$ * get$capitalized_name$List().size();\n"); + "size += $tag_size$ * get$capitalized_name$List().size();\n"); printer->Outdent(); printer->Print("}\n"); } -void RepeatedImmutableStringFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && get$capitalized_name$List()\n" - " .equals(other.get$capitalized_name$List());\n"); +void RepeatedImmutableStringFieldGenerator::GenerateEqualsCode( + io::Printer* printer) const { + printer->Print( + variables_, + "if (!get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List())) return false;\n"); } -void RepeatedImmutableStringFieldGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "if (get$capitalized_name$Count() > 0) {\n" - " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" - "}\n"); +void RepeatedImmutableStringFieldGenerator::GenerateHashCode( + io::Printer* printer) const { + printer->Print( + variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" + "}\n"); } -string RepeatedImmutableStringFieldGenerator::GetBoxedType() const { +std::string RepeatedImmutableStringFieldGenerator::GetBoxedType() const { return "String"; } diff --git a/src/google/protobuf/compiler/java/java_string_field.h b/src/google/protobuf/compiler/java/java_string_field.h index 0f7c705b8fa31..1c00ae81c2915 100644 --- a/src/google/protobuf/compiler/java/java_string_field.h +++ b/src/google/protobuf/compiler/java/java_string_field.h @@ -42,26 +42,29 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { class ImmutableStringFieldGenerator : public ImmutableFieldGenerator { public: - explicit ImmutableStringFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableStringFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, Context* context); ~ImmutableStringFieldGenerator(); - // implements ImmutableFieldGenerator --------------------------------------- + // implements ImmutableFieldGenerator + // --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -79,14 +82,11 @@ class ImmutableStringFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; + std::map variables_; ClassNameResolver* name_resolver_; private: @@ -96,9 +96,9 @@ class ImmutableStringFieldGenerator : public ImmutableFieldGenerator { class ImmutableStringOneofFieldGenerator : public ImmutableStringFieldGenerator { public: - ImmutableStringOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex, + Context* context); ~ImmutableStringOneofFieldGenerator(); private: @@ -138,14 +138,11 @@ class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; + std::map variables_; ClassNameResolver* name_resolver_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldGenerator); @@ -154,6 +151,6 @@ class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc index adda307cf94ee..25bfedcae2ae4 100644 --- a/src/google/protobuf/compiler/java/java_string_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc @@ -58,11 +58,10 @@ using internal::WireFormatLite; namespace { void SetPrimitiveVariables(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, + int messageBitIndex, int builderBitIndex, const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, - std::map* variables) { + std::map* variables) { SetCommonFieldVariables(descriptor, info, variables); (*variables)["empty_list"] = @@ -73,21 +72,20 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, "= " + ImmutableDefaultValue(descriptor, name_resolver); (*variables)["capitalized_type"] = "java.lang.String"; (*variables)["tag"] = - SimpleItoa(static_cast(WireFormat::MakeTag(descriptor))); - (*variables)["tag_size"] = SimpleItoa( + StrCat(static_cast(WireFormat::MakeTag(descriptor))); + (*variables)["tag_size"] = StrCat( WireFormat::TagSize(descriptor->number(), GetType(descriptor))); - (*variables)["null_check"] = - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n"; + // We use `x.getClass()` as a null check because it generates less bytecode + // than an `if (x == null) { throw ... }` statement. + (*variables)["null_check"] = " value.getClass();\n"; // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler - (*variables)["deprecation"] = descriptor->options().deprecated() - ? "@java.lang.Deprecated " : ""; + (*variables)["deprecation"] = + descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; (*variables)["required"] = descriptor->is_required() ? "true" : "false"; - if (SupportFieldPresence(descriptor->file())) { + if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); @@ -106,9 +104,6 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, "!" + (*variables)["name"] + "_.isEmpty()"; } - // For repeated builders, the underlying list tracks mutability state. - (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()"; - (*variables)["get_has_field_bit_from_local"] = GenerateGetBitFromLocal(builderBitIndex); (*variables)["set_has_field_bit_to_local"] = @@ -119,15 +114,12 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, // =================================================================== -ImmutableStringFieldLiteGenerator:: -ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, +ImmutableStringFieldLiteGenerator::ImmutableStringFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, Context* context) + : descriptor_(descriptor), + messageBitIndex_(messageBitIndex), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); } @@ -135,18 +127,14 @@ ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {} int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const { - return 1; -} - -int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; + return HasHasbit(descriptor_) ? 1 : 0; } // A note about how strings are handled. In the SPEED and CODE_SIZE runtimes, // strings are not stored as java.lang.String in the Message because of two // issues: // -// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded +// 1. It wouldn't roundtrip byte arrays that were not valid UTF-8 encoded // strings, but rather fields that were raw bytes incorrectly marked // as strings in the proto file. This is common because in the proto1 // syntax, string was the way to indicate bytes and C++ engineers can @@ -167,745 +155,566 @@ int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const { // TODO(dweis): Consider dropping all of the *Bytes() methods. They really // shouldn't be necessary or used on devices. -void ImmutableStringFieldLiteGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); +void ImmutableStringFieldLiteGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); + "$deprecation$boolean has$capitalized_name$();\n"); } - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$java.lang.String get$capitalized_name$();\n"); - WriteFieldDocComment(printer, descriptor_); + "$deprecation$java.lang.String get$capitalized_name$();\n"); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$com.google.protobuf.ByteString\n" - " get$capitalized_name$Bytes();\n"); + "$deprecation$com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes();\n"); } -void ImmutableStringFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private java.lang.String $name$_;\n"); +void ImmutableStringFieldLiteGenerator::GenerateMembers( + io::Printer* printer) const { + printer->Print(variables_, "private java.lang.String $name$_;\n"); PrintExtraFieldInfo(variables_, printer); - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" - " return $name$_;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" + " return $name$_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " ${$get$capitalized_name$Bytes$}$() {\n" - " return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n" - "}\n"); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public com.google.protobuf.ByteString\n" + " ${$get$capitalized_name$Bytes$}$() {\n" + " return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER); printer->Print(variables_, - "private void set$capitalized_name$(\n" - " java.lang.String value) {\n" - "$null_check$" - " $set_has_field_bit_message$\n" - " $name$_ = value;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); + "private void set$capitalized_name$(\n" + " java.lang.String value) {\n" + "$null_check$" + " $set_has_field_bit_message$\n" + " $name$_ = value;\n" + "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER); printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " $clear_has_field_bit_message$\n" - // The default value is not a simple literal so we want to avoid executing - // it multiple times. Instead, get the default out of the default instance. - " $name$_ = getDefaultInstance().get$capitalized_name$();\n" - "}\n"); + "private void clear$capitalized_name$() {\n" + " $clear_has_field_bit_message$\n" + // The default value is not a simple literal so we want to + // avoid executing it multiple times. Instead, get the default + // out of the default instance. + " $name$_ = getDefaultInstance().get$capitalized_name$();\n" + "}\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER); printer->Print(variables_, - "private void set$capitalized_name$Bytes(\n" - " com.google.protobuf.ByteString value) {\n" - "$null_check$"); + "private void set$capitalized_name$Bytes(\n" + " com.google.protobuf.ByteString value) {\n"); if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " checkByteStringIsUtf8(value);\n"); + printer->Print(variables_, " checkByteStringIsUtf8(value);\n"); } printer->Print(variables_, - " $set_has_field_bit_message$\n" - " $name$_ = value.toStringUtf8();\n" - "}\n"); -} - -void ImmutableStringFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return instance.has$capitalized_name$();\n" - "}\n"); + " $name$_ = value.toStringUtf8();\n" + " $set_has_field_bit_message$\n" + "}\n"); +} + +void ImmutableStringFieldLiteGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + if (HasHazzer(descriptor_)) { + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" - " return instance.get$capitalized_name$();\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " ${$get$capitalized_name$Bytes$}$() {\n" - " return instance.get$capitalized_name$Bytes();\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public com.google.protobuf.ByteString\n" + " ${$get$capitalized_name$Bytes$}$() {\n" + " return instance.get$capitalized_name$Bytes();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " java.lang.String value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(value);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " java.lang.String value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n" - " com.google.protobuf.ByteString value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$Bytes(value);\n" - " return this;\n" - "}\n"); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n" + " com.google.protobuf.ByteString value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$Bytes(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutableStringFieldLiteGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - // noop for strings -} - - -void ImmutableStringFieldLiteGenerator:: -GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $default$;\n"); -} - -void ImmutableStringFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "$name$_ = visitor.visitString(\n" - " has$capitalized_name$(), $name$_,\n" - " other.has$capitalized_name$(), other.$name$_);\n"); - } else { - printer->Print(variables_, - "$name$_ = visitor.visitString(!$name$_.isEmpty(), $name$_,\n" - " !other.$name$_.isEmpty(), other.$name$_);\n"); +void ImmutableStringFieldLiteGenerator::GenerateFieldInfo( + io::Printer* printer, std::vector* output) const { + WriteIntToUtf16CharSequence(descriptor_->number(), output); + WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_), + output); + if (HasHasbit(descriptor_)) { + WriteIntToUtf16CharSequence(messageBitIndex_, output); } + printer->Print(variables_, "\"$name$_\",\n"); } -void ImmutableStringFieldLiteGenerator:: -GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { - // noop for scalars -} - -void ImmutableStringFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - "java.lang.String s = input.readStringRequireUtf8();\n" - "$set_has_field_bit_message$\n" - "$name$_ = s;\n"); - } else { - // Lite runtime should attempt to reduce allocations by attempting to - // construct the string directly from the input stream buffer. This avoids - // spurious intermediary ByteString allocations, cutting overall allocations - // in half. - printer->Print(variables_, - "java.lang.String s = input.readString();\n" - "$set_has_field_bit_message$\n" - "$name$_ = s;\n"); - } -} - -void ImmutableStringFieldLiteGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - // noop for strings -} - -void ImmutableStringFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - // Lite runtime should reduce allocations by serializing the string directly. - // This avoids spurious intermediary ByteString allocations, cutting overall - // allocations in half. - printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " output.writeString($number$, get$capitalized_name$());\n" - "}\n"); -} - -void ImmutableStringFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - // Lite runtime should reduce allocations by computing on the string directly. - // This avoids spurious intermediary ByteString allocations, cutting overall - // allocations in half. - printer->Print(variables_, - "if ($is_field_present_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeStringSize($number$, get$capitalized_name$());\n" - "}\n"); -} - -void ImmutableStringFieldLiteGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && get$capitalized_name$()\n" - " .equals(other.get$capitalized_name$());\n"); -} - -void ImmutableStringFieldLiteGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "hash = (37 * hash) + $constant_name$;\n"); - printer->Print(variables_, - "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); +void ImmutableStringFieldLiteGenerator::GenerateInitializationCode( + io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $default$;\n"); } -string ImmutableStringFieldLiteGenerator::GetBoxedType() const { +std::string ImmutableStringFieldLiteGenerator::GetBoxedType() const { return "java.lang.String"; } // =================================================================== -ImmutableStringOneofFieldLiteGenerator:: -ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableStringFieldLiteGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { +ImmutableStringOneofFieldLiteGenerator::ImmutableStringOneofFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, Context* context) + : ImmutableStringFieldLiteGenerator(descriptor, messageBitIndex, context) { const OneofGeneratorInfo* info = context->GetOneofGeneratorInfo(descriptor->containing_oneof()); SetCommonOneofVariables(descriptor, info, &variables_); } ImmutableStringOneofFieldLiteGenerator:: -~ImmutableStringOneofFieldLiteGenerator() {} + ~ImmutableStringOneofFieldLiteGenerator() {} -void ImmutableStringOneofFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { +void ImmutableStringOneofFieldLiteGenerator::GenerateMembers( + io::Printer* printer) const { PrintExtraFieldInfo(variables_, printer); - - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); + GOOGLE_DCHECK(HasHazzer(descriptor_)); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - } - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" - " java.lang.String ref $default_init$;\n" - " if ($has_oneof_case_message$) {\n" - " ref = (java.lang.String) $oneof_name$_;\n" - " }\n" - " return ref;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" + " java.lang.String ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = (java.lang.String) $oneof_name$_;\n" + " }\n" + " return ref;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " ${$get$capitalized_name$Bytes$}$() {\n" - " java.lang.String ref $default_init$;\n" - " if ($has_oneof_case_message$) {\n" - " ref = (java.lang.String) $oneof_name$_;\n" - " }\n" - " return com.google.protobuf.ByteString.copyFromUtf8(ref);\n" - "}\n"); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public com.google.protobuf.ByteString\n" + " ${$get$capitalized_name$Bytes$}$() {\n" + " java.lang.String ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = (java.lang.String) $oneof_name$_;\n" + " }\n" + " return com.google.protobuf.ByteString.copyFromUtf8(ref);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER); printer->Print(variables_, - "private void ${$set$capitalized_name$$}$(\n" - " java.lang.String value) {\n" - "$null_check$" - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value;\n" - "}\n"); + "private void ${$set$capitalized_name$$}$(\n" + " java.lang.String value) {\n" + "$null_check$" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void ${$clear$capitalized_name$$}$() {\n" - " if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " }\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER); + printer->Print(variables_, + "private void ${$clear$capitalized_name$$}$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " }\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER); printer->Print(variables_, - "private void ${$set$capitalized_name$Bytes$}$(\n" - " com.google.protobuf.ByteString value) {\n" - "$null_check$"); + "private void ${$set$capitalized_name$Bytes$}$(\n" + " com.google.protobuf.ByteString value) {\n"); printer->Annotate("{", "}", descriptor_); if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " checkByteStringIsUtf8(value);\n"); + printer->Print(variables_, " checkByteStringIsUtf8(value);\n"); } printer->Print(variables_, - " $set_oneof_case_message$;\n" - " $oneof_name$_ = value.toStringUtf8();\n" - "}\n"); + " $oneof_name$_ = value.toStringUtf8();\n" + " $set_oneof_case_message$;\n" + "}\n"); } +void ImmutableStringOneofFieldLiteGenerator::GenerateFieldInfo( + io::Printer* printer, std::vector* output) const { + WriteIntToUtf16CharSequence(descriptor_->number(), output); + WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_), + output); + WriteIntToUtf16CharSequence(descriptor_->containing_oneof()->index(), output); +} -void ImmutableStringOneofFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - if (SupportFieldPresence(descriptor_->file())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return instance.has$capitalized_name$();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } - - WriteFieldDocComment(printer, descriptor_); +void ImmutableStringOneofFieldLiteGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + GOOGLE_DCHECK(HasHazzer(descriptor_)); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" - " return instance.get$capitalized_name$();\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " ${$get$capitalized_name$Bytes$}$() {\n" - " return instance.get$capitalized_name$Bytes();\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " java.lang.String value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(value);\n" - " return this;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public com.google.protobuf.ByteString\n" + " ${$get$capitalized_name$Bytes$}$() {\n" + " return instance.get$capitalized_name$Bytes();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n" - " com.google.protobuf.ByteString value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$Bytes(value);\n" - " return this;\n" - "}\n"); + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " java.lang.String value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); -} - -void ImmutableStringOneofFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - printer->Print(variables_, - "$oneof_name$_ = visitor.visitOneofString(\n" - " $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n"); -} - -void ImmutableStringOneofFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - "java.lang.String s = input.readStringRequireUtf8();\n" - "$set_oneof_case_message$;\n" - "$oneof_name$_ = s;\n"); - } else { - // Lite runtime should attempt to reduce allocations by attempting to - // construct the string directly from the input stream buffer. This avoids - // spurious intermediary ByteString allocations, cutting overall allocations - // in half. - printer->Print(variables_, - "java.lang.String s = input.readString();\n" - "$set_oneof_case_message$;\n" - "$oneof_name$_ = s;\n"); - } -} - -void ImmutableStringOneofFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - // Lite runtime should reduce allocations by serializing the string directly. - // This avoids spurious intermediary ByteString allocations, cutting overall - // allocations in half. - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.writeString($number$, get$capitalized_name$());\n" - "}\n"); -} -void ImmutableStringOneofFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - // Lite runtime should reduce allocations by computing on the string directly. - // This avoids spurious intermediary ByteString allocations, cutting overall - // allocations in half. - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeStringSize($number$, get$capitalized_name$());\n" - "}\n"); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n" + " com.google.protobuf.ByteString value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$Bytes(value);\n" + " return this;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); } // =================================================================== RepeatedImmutableStringFieldLiteGenerator:: -RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context) + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); } RepeatedImmutableStringFieldLiteGenerator:: -~RepeatedImmutableStringFieldLiteGenerator() {} + ~RepeatedImmutableStringFieldLiteGenerator() {} int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const { return 0; } -int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; -} - -void RepeatedImmutableStringFieldLiteGenerator:: -GenerateInterfaceMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$java.util.List\n" - " get$capitalized_name$List();\n"); - WriteFieldDocComment(printer, descriptor_); +void RepeatedImmutableStringFieldLiteGenerator::GenerateInterfaceMembers( + io::Printer* printer) const { + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); - WriteFieldDocComment(printer, descriptor_); + "$deprecation$java.util.List\n" + " get$capitalized_name$List();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); printer->Print(variables_, - "$deprecation$java.lang.String get$capitalized_name$(int index);\n"); - WriteFieldDocComment(printer, descriptor_); + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); + printer->Print( + variables_, + "$deprecation$java.lang.String get$capitalized_name$(int index);\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$com.google.protobuf.ByteString\n" - " get$capitalized_name$Bytes(int index);\n"); + "$deprecation$com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes(int index);\n"); } - -void RepeatedImmutableStringFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private com.google.protobuf.Internal.ProtobufList " - "$name$_;\n"); +void RepeatedImmutableStringFieldLiteGenerator::GenerateMembers( + io::Printer* printer) const { + printer->Print( + variables_, + "private com.google.protobuf.Internal.ProtobufList " + "$name$_;\n"); PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List " - "${$get$capitalized_name$List$}$() {\n" - " return $name$_;\n" // note: unmodifiable list - "}\n"); - printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return $name$_.size();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.lang.String " - "${$get$capitalized_name$$}$(int index) {\n" - " return $name$_.get(index);\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " ${$get$capitalized_name$Bytes$}$(int index) {\n" - " return com.google.protobuf.ByteString.copyFromUtf8(\n" - " $name$_.get(index));\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - - printer->Print(variables_, - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$is_mutable$) {\n" - " $name$_ =\n" - " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$(\n" - " int index, java.lang.String value) {\n" - "$null_check$" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, value);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$(\n" - " java.lang.String value) {\n" - "$null_check$" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void addAll$capitalized_name$(\n" - " java.lang.Iterable values) {\n" - " ensure$capitalized_name$IsMutable();\n" - " com.google.protobuf.AbstractMessageLite.addAll(\n" - " values, $name$_);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " $name$_ = $empty_list$;\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$Bytes(\n" - " com.google.protobuf.ByteString value) {\n" - "$null_check$"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public java.util.List " + "${$get$capitalized_name$List$}$() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); + printer->Annotate("{", "}", descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return $name$_.size();\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public java.lang.String " + "${$get$capitalized_name$$}$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, + LIST_INDEXED_GETTER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public com.google.protobuf.ByteString\n" + " ${$get$capitalized_name$Bytes$}$(int index) {\n" + " return com.google.protobuf.ByteString.copyFromUtf8(\n" + " $name$_.get(index));\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + + printer->Print( + variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + // Use a temporary to avoid a redundant iget-object. + " com.google.protobuf.Internal.ProtobufList tmp =\n" + " $name$_;" + " if (!tmp.isModifiable()) {\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n" + " }\n" + "}\n"); + + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " int index, java.lang.String value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER); + printer->Print(variables_, + "private void add$capitalized_name$(\n" + " java.lang.String value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER); + printer->Print(variables_, + "private void addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " com.google.protobuf.AbstractMessageLite.addAll(\n" + " values, $name$_);\n" + "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " $name$_ = $empty_list$;\n" + "}\n"); + + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, LIST_ADDER); + printer->Print(variables_, + "private void add$capitalized_name$Bytes(\n" + " com.google.protobuf.ByteString value) {\n"); if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - " checkByteStringIsUtf8(value);\n"); + printer->Print(variables_, " checkByteStringIsUtf8(value);\n"); } printer->Print(variables_, - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value.toStringUtf8());\n" - "}\n"); + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value.toStringUtf8());\n" + "}\n"); } -void RepeatedImmutableStringFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); +void RepeatedImmutableStringFieldLiteGenerator::GenerateBuilderMembers( + io::Printer* printer) const { + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, - "$deprecation$public java.util.List\n" - " ${$get$capitalized_name$List$}$() {\n" - " return java.util.Collections.unmodifiableList(\n" - " instance.get$capitalized_name$List());\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public java.util.List\n" + " ${$get$capitalized_name$List$}$() {\n" + " return java.util.Collections.unmodifiableList(\n" + " instance.get$capitalized_name$List());\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" - " return instance.get$capitalized_name$Count();\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return instance.get$capitalized_name$Count();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); printer->Print(variables_, - "$deprecation$public java.lang.String " - "${$get$capitalized_name$$}$(int index) {\n" - " return instance.get$capitalized_name$(index);\n" - "}\n"); + "@java.lang.Override\n" + "$deprecation$public java.lang.String " + "${$get$capitalized_name$$}$(int index) {\n" + " return instance.get$capitalized_name$(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public com.google.protobuf.ByteString\n" - " ${$get$capitalized_name$Bytes$}$(int index) {\n" - " return instance.get$capitalized_name$Bytes(index);\n" - "}\n"); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, + LIST_INDEXED_GETTER); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public com.google.protobuf.ByteString\n" + " ${$get$capitalized_name$Bytes$}$(int index) {\n" + " return instance.get$capitalized_name$Bytes(index);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" - " int index, java.lang.String value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(index, value);\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" + " int index, java.lang.String value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(index, value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" - " java.lang.String value) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(value);\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" + " java.lang.String value) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" - " java.lang.Iterable values) {\n" - " copyOnWrite();\n" - " instance.addAll$capitalized_name$(values);\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, + /* builder */ true); + printer->Print(variables_, + "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n" + " java.lang.Iterable values) {\n" + " copyOnWrite();\n" + " instance.addAll$capitalized_name$(values);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n" - " com.google.protobuf.ByteString value) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$Bytes(value);\n" - " return this;\n" - "}\n"); + WriteFieldStringBytesAccessorDocComment(printer, descriptor_, LIST_ADDER, + /* builder */ true); + printer->Print( + variables_, + "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n" + " com.google.protobuf.ByteString value) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$Bytes(value);\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } -void RepeatedImmutableStringFieldLiteGenerator:: -GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - // noop for strings +void RepeatedImmutableStringFieldLiteGenerator::GenerateFieldInfo( + io::Printer* printer, std::vector* output) const { + WriteIntToUtf16CharSequence(descriptor_->number(), output); + WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_), + output); + printer->Print(variables_, "\"$name$_\",\n"); } - -void RepeatedImmutableStringFieldLiteGenerator:: -GenerateInitializationCode(io::Printer* printer) const { +void RepeatedImmutableStringFieldLiteGenerator::GenerateInitializationCode( + io::Printer* printer) const { printer->Print(variables_, "$name$_ = $empty_list$;\n"); } -void RepeatedImmutableStringFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_= visitor.visitList($name$_, other.$name$_);\n"); -} - -void RepeatedImmutableStringFieldLiteGenerator:: -GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_.makeImmutable();\n"); -} - -void RepeatedImmutableStringFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, - "java.lang.String s = input.readStringRequireUtf8();\n"); - } else { - // Lite runtime should attempt to reduce allocations by attempting to - // construct the string directly from the input stream buffer. This avoids - // spurious intermediary ByteString allocations, cutting overall allocations - // in half. - printer->Print(variables_, - "java.lang.String s = input.readString();\n"); - } - printer->Print(variables_, - "if (!$is_mutable$) {\n" - " $name$_ =\n" - " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" - "}\n"); - printer->Print(variables_, - "$name$_.add(s);\n"); -} - -void RepeatedImmutableStringFieldLiteGenerator:: -GenerateParsingDoneCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($is_mutable$) {\n" - " $name$_.makeImmutable();\n" - "}\n"); -} - -void RepeatedImmutableStringFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - // Lite runtime should reduce allocations by serializing the string directly. - // This avoids spurious intermediary ByteString allocations, cutting overall - // allocations in half. - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeString($number$, $name$_.get(i));\n" - "}\n"); -} - -void RepeatedImmutableStringFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - // Lite runtime should reduce allocations by computing on the string directly. - // This avoids spurious intermediary ByteString allocations, cutting overall - // allocations in half. - printer->Print(variables_, - "{\n" - " int dataSize = 0;\n"); - printer->Indent(); - - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " dataSize += com.google.protobuf.CodedOutputStream\n" - " .computeStringSizeNoTag($name$_.get(i));\n" - "}\n"); - - printer->Print( - "size += dataSize;\n"); - - - printer->Print(variables_, - "size += $tag_size$ * get$capitalized_name$List().size();\n"); - - printer->Outdent(); - printer->Print("}\n"); -} - -void RepeatedImmutableStringFieldLiteGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "result = result && get$capitalized_name$List()\n" - " .equals(other.get$capitalized_name$List());\n"); -} - -void RepeatedImmutableStringFieldLiteGenerator:: -GenerateHashCode(io::Printer* printer) const { - printer->Print(variables_, - "if (get$capitalized_name$Count() > 0) {\n" - " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" - "}\n"); -} - -string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const { +std::string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const { return "java.lang.String"; } diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.h b/src/google/protobuf/compiler/java/java_string_field_lite.h index b7fb640959e50..b67135cd81955 100644 --- a/src/google/protobuf/compiler/java/java_string_field_lite.h +++ b/src/google/protobuf/compiler/java/java_string_field_lite.h @@ -42,51 +42,43 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: - explicit ImmutableStringFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context); ~ImmutableStringFieldLiteGenerator(); - // implements ImmutableFieldLiteGenerator ------------------------------------ + // implements ImmutableFieldLiteGenerator + // ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; - + void GenerateFieldInfo(io::Printer* printer, + std::vector* output) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map variables_; + std::map variables_; const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; ClassNameResolver* name_resolver_; private: @@ -96,19 +88,15 @@ class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator { class ImmutableStringOneofFieldLiteGenerator : public ImmutableStringFieldLiteGenerator { public: - ImmutableStringOneofFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, Context* context); ~ImmutableStringOneofFieldLiteGenerator(); private: void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - + void GenerateFieldInfo(io::Printer* printer, + std::vector* output) const; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldLiteGenerator); }; @@ -117,36 +105,23 @@ class RepeatedImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: explicit RepeatedImmutableStringFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + const FieldDescriptor* descriptor, int messageBitIndex, Context* context); ~RepeatedImmutableStringFieldLiteGenerator(); // implements ImmutableFieldLiteGenerator ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateParsingDoneCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCode(io::Printer* printer) const; - + void GenerateFieldInfo(io::Printer* printer, + std::vector* output) const; - string GetBoxedType() const; + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; + std::map variables_; ClassNameResolver* name_resolver_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldLiteGenerator); @@ -155,6 +130,6 @@ class RepeatedImmutableStringFieldLiteGenerator } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc deleted file mode 100644 index c6e8dfe90d288..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_enum.cc +++ /dev/null @@ -1,143 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Params& params) - : params_(params), descriptor_(descriptor) { - for (int i = 0; i < descriptor_->value_count(); i++) { - const EnumValueDescriptor* value = descriptor_->value(i); - const EnumValueDescriptor* canonical_value = - descriptor_->FindValueByNumber(value->number()); - - if (value == canonical_value) { - canonical_values_.push_back(value); - } else { - Alias alias; - alias.value = value; - alias.canonical_value = canonical_value; - aliases_.push_back(alias); - } - } -} - -EnumGenerator::~EnumGenerator() {} - -void EnumGenerator::Generate(io::Printer* printer) { - printer->Print( - "\n" - "// enum $classname$\n", - "classname", descriptor_->name()); - - const string classname = RenameJavaKeywords(descriptor_->name()); - - // Start of container interface - // If generating intdefs, we use the container interface as the intdef if - // present. Otherwise, we just make an empty @interface parallel to the - // constants. - bool use_intdef = params_.generate_intdefs(); - bool use_shell_class = params_.java_enum_style(); - if (use_intdef) { - // @IntDef annotation so tools can enforce correctness - // Annotations will be discarded by the compiler - printer->Print("@java.lang.annotation.Retention(" - "java.lang.annotation.RetentionPolicy.SOURCE)\n" - "@android.support.annotation.IntDef({\n"); - printer->Indent(); - for (int i = 0; i < canonical_values_.size(); i++) { - const string constant_name = - RenameJavaKeywords(canonical_values_[i]->name()); - if (use_shell_class) { - printer->Print("$classname$.$name$,\n", - "classname", classname, - "name", constant_name); - } else { - printer->Print("$name$,\n", "name", constant_name); - } - } - printer->Outdent(); - printer->Print("})\n"); - } - if (use_shell_class || use_intdef) { - printer->Print( - "public $at_for_intdef$interface $classname$ {\n", - "classname", classname, - "at_for_intdef", use_intdef ? "@" : ""); - if (use_shell_class) { - printer->Indent(); - } else { - printer->Print("}\n\n"); - } - } - - // Canonical values - for (int i = 0; i < canonical_values_.size(); i++) { - printer->Print( - "public static final int $name$ = $canonical_value$;\n", - "name", RenameJavaKeywords(canonical_values_[i]->name()), - "canonical_value", SimpleItoa(canonical_values_[i]->number())); - } - - // Aliases - for (int i = 0; i < aliases_.size(); i++) { - printer->Print( - "public static final int $name$ = $canonical_name$;\n", - "name", RenameJavaKeywords(aliases_[i].value->name()), - "canonical_name", RenameJavaKeywords(aliases_[i].canonical_value->name())); - } - - // End of container interface - if (use_shell_class) { - printer->Outdent(); - printer->Print("}\n"); - } -} - -} // namespace javanano -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.h b/src/google/protobuf/compiler/javanano/javanano_enum.h deleted file mode 100644 index 10dd364876f9c..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_enum.h +++ /dev/null @@ -1,87 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__ - -#include -#include - -#include -#include - -namespace google { -namespace protobuf { - namespace io { - class Printer; // printer.h - } -} - -namespace protobuf { -namespace compiler { -namespace javanano { - -class EnumGenerator { - public: - explicit EnumGenerator(const EnumDescriptor* descriptor, const Params& params); - ~EnumGenerator(); - - void Generate(io::Printer* printer); - - private: - const Params& params_; - const EnumDescriptor* descriptor_; - - // The proto language allows multiple enum constants to have the same numeric - // value. Java, however, does not allow multiple enum constants to be - // considered equivalent. We treat the first defined constant for any - // given numeric value as "canonical" and the rest as aliases of that - // canonical value. - vector canonical_values_; - - struct Alias { - const EnumValueDescriptor* value; - const EnumValueDescriptor* canonical_value; - }; - vector aliases_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); -}; - -} // namespace javanano -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_H__ diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc deleted file mode 100644 index 26bc7f85d470a..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc +++ /dev/null @@ -1,544 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -namespace { - -// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of -// repeat code between this and the other field types. -void SetEnumVariables(const Params& params, - const FieldDescriptor* descriptor, std::map* variables) { - (*variables)["name"] = - RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); - (*variables)["capitalized_name"] = - RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); - (*variables)["number"] = SimpleItoa(descriptor->number()); - if (params.use_reference_types_for_primitives() - && !params.reftypes_primitive_enums() - && !descriptor->is_repeated()) { - (*variables)["type"] = "java.lang.Integer"; - (*variables)["default"] = "null"; - } else { - (*variables)["type"] = "int"; - (*variables)["default"] = DefaultValue(params, descriptor); - } - (*variables)["repeated_default"] = - "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY"; - (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); - (*variables)["tag_size"] = SimpleItoa( - internal::WireFormat::TagSize(descriptor->number(), descriptor->type())); - (*variables)["non_packed_tag"] = SimpleItoa( - internal::WireFormatLite::MakeTag(descriptor->number(), - internal::WireFormat::WireTypeForFieldType(descriptor->type()))); - (*variables)["message_name"] = descriptor->containing_type()->name(); - const EnumDescriptor* enum_type = descriptor->enum_type(); - (*variables)["message_type_intdef"] = "@" - + ToJavaName(params, enum_type->name(), true, - enum_type->containing_type(), enum_type->file()); -} - -void LoadEnumValues(const Params& params, - const EnumDescriptor* enum_descriptor, vector* canonical_values) { - string enum_class_name = ClassName(params, enum_descriptor); - for (int i = 0; i < enum_descriptor->value_count(); i++) { - const EnumValueDescriptor* value = enum_descriptor->value(i); - const EnumValueDescriptor* canonical_value = - enum_descriptor->FindValueByNumber(value->number()); - if (value == canonical_value) { - canonical_values->push_back( - enum_class_name + "." + RenameJavaKeywords(value->name())); - } - } -} - -void PrintCaseLabels( - io::Printer* printer, const vector& canonical_values) { - for (int i = 0; i < canonical_values.size(); i++) { - printer->Print( - " case $value$:\n", - "value", canonical_values[i]); - } -} - -} // namespace - -// =================================================================== - -EnumFieldGenerator:: -EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params) - : FieldGenerator(params), descriptor_(descriptor) { - SetEnumVariables(params, descriptor, &variables_); - LoadEnumValues(params, descriptor->enum_type(), &canonical_values_); -} - -EnumFieldGenerator::~EnumFieldGenerator() {} - -void EnumFieldGenerator:: -GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { - if (params_.generate_intdefs()) { - printer->Print(variables_, "$message_type_intdef$\n"); - } - printer->Print(variables_, "public $type$ $name$;\n"); - - if (params_.generate_has()) { - printer->Print(variables_, - "public boolean has$capitalized_name$;\n"); - } -} - -void EnumFieldGenerator:: -GenerateClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$ = $default$;\n"); - - if (params_.generate_has()) { - printer->Print(variables_, - "has$capitalized_name$ = false;\n"); - } -} - -void EnumFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "int value = input.readInt32();\n" - "switch (value) {\n"); - PrintCaseLabels(printer, canonical_values_); - printer->Print(variables_, - " this.$name$ = value;\n"); - if (params_.generate_has()) { - printer->Print(variables_, - " has$capitalized_name$ = true;\n"); - } - printer->Print( - " break;\n" - "}\n"); - // No default case: in case of invalid value from the wire, preserve old - // field value. Also we are not storing the invalid value into the unknown - // fields, because there is no way to get the value out. -} - -void EnumFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - if (descriptor_->is_required() && !params_.generate_has()) { - // Always serialize a required field if we don't have the 'has' signal. - printer->Print(variables_, - "output.writeInt32($number$, this.$name$);\n"); - } else { - if (params_.generate_has()) { - printer->Print(variables_, - "if (this.$name$ != $default$ || has$capitalized_name$) {\n"); - } else { - printer->Print(variables_, - "if (this.$name$ != $default$) {\n"); - } - printer->Print(variables_, - " output.writeInt32($number$, this.$name$);\n" - "}\n"); - } -} - -void EnumFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - if (descriptor_->is_required() && !params_.generate_has()) { - printer->Print(variables_, - "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .computeInt32Size($number$, this.$name$);\n"); - } else { - if (params_.generate_has()) { - printer->Print(variables_, - "if (this.$name$ != $default$ || has$capitalized_name$) {\n"); - } else { - printer->Print(variables_, - "if (this.$name$ != $default$) {\n"); - } - printer->Print(variables_, - " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .computeInt32Size($number$, this.$name$);\n" - "}\n"); - } -} - -void EnumFieldGenerator::GenerateEqualsCode(io::Printer* printer) const { - if (params_.use_reference_types_for_primitives() - && !params_.reftypes_primitive_enums()) { - printer->Print(variables_, - "if (this.$name$ == null) {\n" - " if (other.$name$ != null) {\n" - " return false;\n" - " }\n" - "} else if (!this.$name$.equals(other.$name$)) {\n" - " return false;" - "}\n"); - } else { - // We define equality as serialized form equality. If generate_has(), - // then if the field value equals the default value in both messages, - // but one's 'has' field is set and the other's is not, the serialized - // forms are different and we should return false. - printer->Print(variables_, - "if (this.$name$ != other.$name$"); - if (params_.generate_has()) { - printer->Print(variables_, - "\n" - " || (this.$name$ == $default$\n" - " && this.has$capitalized_name$ != other.has$capitalized_name$)"); - } - printer->Print(") {\n" - " return false;\n" - "}\n"); - } -} - -void EnumFieldGenerator::GenerateHashCodeCode(io::Printer* printer) const { - printer->Print( - "result = 31 * result + "); - if (params_.use_reference_types_for_primitives() - && !params_.reftypes_primitive_enums()) { - printer->Print(variables_, - "(this.$name$ == null ? 0 : this.$name$)"); - } else { - printer->Print(variables_, - "this.$name$"); - } - printer->Print(";\n"); -} - -// =================================================================== - -AccessorEnumFieldGenerator:: -AccessorEnumFieldGenerator(const FieldDescriptor* descriptor, - const Params& params, int has_bit_index) - : FieldGenerator(params), descriptor_(descriptor) { - SetEnumVariables(params, descriptor, &variables_); - LoadEnumValues(params, descriptor->enum_type(), &canonical_values_); - SetBitOperationVariables("has", has_bit_index, &variables_); -} - -AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {} - -void AccessorEnumFieldGenerator:: -GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { - printer->Print(variables_, "private int $name$_;\n"); - if (params_.generate_intdefs()) { - printer->Print(variables_, "$message_type_intdef$\n"); - } - printer->Print(variables_, - "public int get$capitalized_name$() {\n" - " return $name$_;\n" - "}\n" - "public $message_name$ set$capitalized_name$("); - if (params_.generate_intdefs()) { - printer->Print(variables_, - "\n" - " $message_type_intdef$ "); - } - printer->Print(variables_, - "int value) {\n" - " $name$_ = value;\n" - " $set_has$;\n" - " return this;\n" - "}\n" - "public boolean has$capitalized_name$() {\n" - " return $get_has$;\n" - "}\n" - "public $message_name$ clear$capitalized_name$() {\n" - " $name$_ = $default$;\n" - " $clear_has$;\n" - " return this;\n" - "}\n"); -} - -void AccessorEnumFieldGenerator:: -GenerateClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = $default$;\n"); -} - -void AccessorEnumFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "int value = input.readInt32();\n" - "switch (value) {\n"); - PrintCaseLabels(printer, canonical_values_); - printer->Print(variables_, - " $name$_ = value;\n" - " $set_has$;\n" - " break;\n" - "}\n"); - // No default case: in case of invalid value from the wire, preserve old - // field value. Also we are not storing the invalid value into the unknown - // fields, because there is no way to get the value out. -} - -void AccessorEnumFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_has$) {\n" - " output.writeInt32($number$, $name$_);\n" - "}\n"); -} - -void AccessorEnumFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_has$) {\n" - " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .computeInt32Size($number$, $name$_);\n" - "}\n"); -} - -void AccessorEnumFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($different_has$\n" - " || $name$_ != other.$name$_) {\n" - " return false;\n" - "}\n"); -} - -void AccessorEnumFieldGenerator:: -GenerateHashCodeCode(io::Printer* printer) const { - printer->Print(variables_, - "result = 31 * result + $name$_;\n"); -} - -// =================================================================== - -RepeatedEnumFieldGenerator:: -RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params) - : FieldGenerator(params), descriptor_(descriptor) { - SetEnumVariables(params, descriptor, &variables_); - LoadEnumValues(params, descriptor->enum_type(), &canonical_values_); -} - -RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} - -void RepeatedEnumFieldGenerator:: -GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { - printer->Print(variables_, - "public $type$[] $name$;\n"); -} - -void RepeatedEnumFieldGenerator:: -GenerateClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$ = $repeated_default$;\n"); -} - -void RepeatedEnumFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - // First, figure out the maximum length of the array, then parse, - // and finally copy the valid values to the field. - printer->Print(variables_, - "int length = com.google.protobuf.nano.WireFormatNano\n" - " .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n" - "int[] validValues = new int[length];\n" - "int validCount = 0;\n" - "for (int i = 0; i < length; i++) {\n" - " if (i != 0) { // tag for first value already consumed.\n" - " input.readTag();\n" - " }\n" - " int value = input.readInt32();\n" - " switch (value) {\n"); - printer->Indent(); - PrintCaseLabels(printer, canonical_values_); - printer->Outdent(); - printer->Print(variables_, - " validValues[validCount++] = value;\n" - " break;\n" - " }\n" - "}\n" - "if (validCount != 0) {\n" - " int i = this.$name$ == null ? 0 : this.$name$.length;\n" - " if (i == 0 && validCount == validValues.length) {\n" - " this.$name$ = validValues;\n" - " } else {\n" - " int[] newArray = new int[i + validCount];\n" - " if (i != 0) {\n" - " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" - " }\n" - " java.lang.System.arraycopy(validValues, 0, newArray, i, validCount);\n" - " this.$name$ = newArray;\n" - " }\n" - "}\n"); -} - -void RepeatedEnumFieldGenerator:: -GenerateMergingCodeFromPacked(io::Printer* printer) const { - printer->Print(variables_, - "int bytes = input.readRawVarint32();\n" - "int limit = input.pushLimit(bytes);\n" - "// First pass to compute array length.\n" - "int arrayLength = 0;\n" - "int startPos = input.getPosition();\n" - "while (input.getBytesUntilLimit() > 0) {\n" - " switch (input.readInt32()) {\n"); - printer->Indent(); - PrintCaseLabels(printer, canonical_values_); - printer->Outdent(); - printer->Print(variables_, - " arrayLength++;\n" - " break;\n" - " }\n" - "}\n" - "if (arrayLength != 0) {\n" - " input.rewindToPosition(startPos);\n" - " int i = this.$name$ == null ? 0 : this.$name$.length;\n" - " int[] newArray = new int[i + arrayLength];\n" - " if (i != 0) {\n" - " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" - " }\n" - " while (input.getBytesUntilLimit() > 0) {\n" - " int value = input.readInt32();\n" - " switch (value) {\n"); - printer->Indent(); - printer->Indent(); - PrintCaseLabels(printer, canonical_values_); - printer->Outdent(); - printer->Outdent(); - printer->Print(variables_, - " newArray[i++] = value;\n" - " break;\n" - " }\n" - " }\n" - " this.$name$ = newArray;\n" - "}\n" - "input.popLimit(limit);\n"); -} - -void RepeatedEnumFieldGenerator:: -GenerateRepeatedDataSizeCode(io::Printer* printer) const { - // Creates a variable dataSize and puts the serialized size in there. - printer->Print(variables_, - "int dataSize = 0;\n" - "for (int i = 0; i < this.$name$.length; i++) {\n" - " int element = this.$name$[i];\n" - " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .computeInt32SizeNoTag(element);\n" - "}\n"); -} - -void RepeatedEnumFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null && this.$name$.length > 0) {\n"); - printer->Indent(); - - if (descriptor_->options().packed()) { - GenerateRepeatedDataSizeCode(printer); - printer->Print(variables_, - "output.writeRawVarint32($tag$);\n" - "output.writeRawVarint32(dataSize);\n" - "for (int i = 0; i < this.$name$.length; i++) {\n" - " output.writeRawVarint32(this.$name$[i]);\n" - "}\n"); - } else { - printer->Print(variables_, - "for (int i = 0; i < this.$name$.length; i++) {\n" - " output.writeInt32($number$, this.$name$[i]);\n" - "}\n"); - } - - printer->Outdent(); - printer->Print(variables_, - "}\n"); -} - -void RepeatedEnumFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null && this.$name$.length > 0) {\n"); - printer->Indent(); - - GenerateRepeatedDataSizeCode(printer); - - printer->Print( - "size += dataSize;\n"); - if (descriptor_->options().packed()) { - printer->Print(variables_, - "size += $tag_size$;\n" - "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .computeRawVarint32Size(dataSize);\n"); - } else { - printer->Print(variables_, - "size += $tag_size$ * this.$name$.length;\n"); - } - - printer->Outdent(); - - printer->Print( - "}\n"); -} - -void RepeatedEnumFieldGenerator:: -GenerateFixClonedCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null && this.$name$.length > 0) {\n" - " cloned.$name$ = this.$name$.clone();\n" - "}\n"); -} - -void RepeatedEnumFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!com.google.protobuf.nano.InternalNano.equals(\n" - " this.$name$, other.$name$)) {\n" - " return false;\n" - "}\n"); -} - -void RepeatedEnumFieldGenerator:: -GenerateHashCodeCode(io::Printer* printer) const { - printer->Print(variables_, - "result = 31 * result\n" - " + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n"); -} - -} // namespace javanano -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.h b/src/google/protobuf/compiler/javanano/javanano_enum_field.h deleted file mode 100644 index 1be25d10ab80a..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_enum_field.h +++ /dev/null @@ -1,126 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_FIELD_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_FIELD_H__ - -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -class EnumFieldGenerator : public FieldGenerator { - public: - explicit EnumFieldGenerator( - const FieldDescriptor* descriptor, const Params& params); - ~EnumFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - void GenerateMembers(io::Printer* printer, bool lazy_init) const; - void GenerateClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCodeCode(io::Printer* printer) const; - - private: - const FieldDescriptor* descriptor_; - std::map variables_; - vector canonical_values_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); -}; - -class AccessorEnumFieldGenerator : public FieldGenerator { - public: - explicit AccessorEnumFieldGenerator(const FieldDescriptor* descriptor, - const Params& params, int has_bit_index); - ~AccessorEnumFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - void GenerateMembers(io::Printer* printer, bool lazy_init) const; - void GenerateClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCodeCode(io::Printer* printer) const; - - private: - const FieldDescriptor* descriptor_; - std::map variables_; - vector canonical_values_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorEnumFieldGenerator); -}; - -class RepeatedEnumFieldGenerator : public FieldGenerator { - public: - explicit RepeatedEnumFieldGenerator( - const FieldDescriptor* descriptor, const Params& params); - ~RepeatedEnumFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - void GenerateMembers(io::Printer* printer, bool lazy_init) const; - void GenerateClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateMergingCodeFromPacked(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCodeCode(io::Printer* printer) const; - void GenerateFixClonedCode(io::Printer* printer) const; - - private: - void GenerateRepeatedDataSizeCode(io::Printer* printer) const; - - const FieldDescriptor* descriptor_; - std::map variables_; - vector canonical_values_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); -}; - -} // namespace javanano -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_ENUM_FIELD_H__ diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.cc b/src/google/protobuf/compiler/javanano/javanano_extension.cc deleted file mode 100644 index 4c61f915c79b1..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_extension.cc +++ /dev/null @@ -1,150 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: bduff@google.com (Brian Duff) - -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -using internal::WireFormat; -using internal::WireFormatLite; - -namespace { - -const char* GetTypeConstantName(const FieldDescriptor::Type type) { - switch (type) { - case FieldDescriptor::TYPE_INT32 : return "TYPE_INT32" ; - case FieldDescriptor::TYPE_UINT32 : return "TYPE_UINT32" ; - case FieldDescriptor::TYPE_SINT32 : return "TYPE_SINT32" ; - case FieldDescriptor::TYPE_FIXED32 : return "TYPE_FIXED32" ; - case FieldDescriptor::TYPE_SFIXED32: return "TYPE_SFIXED32"; - case FieldDescriptor::TYPE_INT64 : return "TYPE_INT64" ; - case FieldDescriptor::TYPE_UINT64 : return "TYPE_UINT64" ; - case FieldDescriptor::TYPE_SINT64 : return "TYPE_SINT64" ; - case FieldDescriptor::TYPE_FIXED64 : return "TYPE_FIXED64" ; - case FieldDescriptor::TYPE_SFIXED64: return "TYPE_SFIXED64"; - case FieldDescriptor::TYPE_FLOAT : return "TYPE_FLOAT" ; - case FieldDescriptor::TYPE_DOUBLE : return "TYPE_DOUBLE" ; - case FieldDescriptor::TYPE_BOOL : return "TYPE_BOOL" ; - case FieldDescriptor::TYPE_STRING : return "TYPE_STRING" ; - case FieldDescriptor::TYPE_BYTES : return "TYPE_BYTES" ; - case FieldDescriptor::TYPE_ENUM : return "TYPE_ENUM" ; - case FieldDescriptor::TYPE_GROUP : return "TYPE_GROUP" ; - case FieldDescriptor::TYPE_MESSAGE : return "TYPE_MESSAGE" ; - - // No default because we want the compiler to complain if any new - // types are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; -} - -} // namespace - -void SetVariables(const FieldDescriptor* descriptor, const Params params, - std::map* variables) { - (*variables)["extends"] = ClassName(params, descriptor->containing_type()); - (*variables)["name"] = RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); - bool repeated = descriptor->is_repeated(); - (*variables)["repeated"] = repeated ? "Repeated" : ""; - (*variables)["type"] = GetTypeConstantName(descriptor->type()); - JavaType java_type = GetJavaType(descriptor->type()); - string tag = SimpleItoa(WireFormat::MakeTag(descriptor)); - if (java_type == JAVATYPE_MESSAGE) { - (*variables)["ext_type"] = "MessageTyped"; - string message_type = ClassName(params, descriptor->message_type()); - if (repeated) { - message_type += "[]"; - } - (*variables)["class"] = message_type; - // For message typed extensions, tags_params contains a single tag - // for both singular and repeated cases. - (*variables)["tag_params"] = tag; - } else { - (*variables)["ext_type"] = "PrimitiveTyped"; - if (!repeated) { - (*variables)["class"] = BoxedPrimitiveTypeName(java_type); - (*variables)["tag_params"] = tag; - } else { - (*variables)["class"] = PrimitiveTypeName(java_type) + "[]"; - if (!descriptor->is_packable()) { - // Non-packable: nonPackedTag == tag, packedTag == 0 - (*variables)["tag_params"] = tag + ", " + tag + ", 0"; - } else if (descriptor->options().packed()) { - // Packable and packed: tag == packedTag - string non_packed_tag = SimpleItoa(WireFormatLite::MakeTag( - descriptor->number(), - WireFormat::WireTypeForFieldType(descriptor->type()))); - (*variables)["tag_params"] = tag + ", " + non_packed_tag + ", " + tag; - } else { - // Packable and not packed: tag == nonPackedTag - string packed_tag = SimpleItoa(WireFormatLite::MakeTag( - descriptor->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); - (*variables)["tag_params"] = tag + ", " + tag + ", " + packed_tag; - } - } - } -} - -ExtensionGenerator:: -ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params) - : params_(params), descriptor_(descriptor) { - SetVariables(descriptor, params, &variables_); -} - -ExtensionGenerator::~ExtensionGenerator() {} - -void ExtensionGenerator::Generate(io::Printer* printer) const { - printer->Print("\n"); - PrintFieldComment(printer, descriptor_); - printer->Print(variables_, - "public static final com.google.protobuf.nano.Extension<\n" - " $extends$,\n" - " $class$> $name$ =\n" - " com.google.protobuf.nano.Extension.create$repeated$$ext_type$(\n" - " com.google.protobuf.nano.Extension.$type$,\n" - " $class$.class,\n" - " $tag_params$L);\n"); -} - -} // namespace javanano -} // namespace compiler -} // namespace protobuf -} // namespace google - diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.h b/src/google/protobuf/compiler/javanano/javanano_extension.h deleted file mode 100644 index f4e9eb2d0bb6b..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_extension.h +++ /dev/null @@ -1,74 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: bduff@google.com (Brian Duff) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_ -#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_ - -#include -#include -#include - - -namespace google { -namespace protobuf { - namespace io { - class Printer; // printer.h - } -} - -namespace protobuf { -namespace compiler { -namespace javanano { - -class ExtensionGenerator { - public: - explicit ExtensionGenerator(const FieldDescriptor* descriptor, const Params& params); - ~ExtensionGenerator(); - - void Generate(io::Printer* printer) const; - - private: - const Params& params_; - const FieldDescriptor* descriptor_; - std::map variables_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); -}; - -} // namespace javanano -} // namespace compiler -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_EXTENSION_H_ diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc deleted file mode 100644 index e31d11777effe..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_field.cc +++ /dev/null @@ -1,209 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include -#include -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -FieldGenerator::~FieldGenerator() {} - -bool FieldGenerator::SavedDefaultNeeded() const { - // No saved default for this field by default. - // Subclasses whose instances may need saved defaults will override this - // and return the appropriate value. - return false; -} - -void FieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const { - // No saved default for this field by default. - // Subclasses whose instances may need saved defaults will override this - // and generate the appropriate init code to the printer. -} - -void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const { - // Reaching here indicates a bug. Cases are: - // - This FieldGenerator should support packing, but this method should be - // overridden. - // - This FieldGenerator doesn't support packing, and this method should - // never have been called. - GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() " - << "called on field generator that does not support packing."; -} - -// ============================================= - -FieldGeneratorMap::FieldGeneratorMap( - const Descriptor* descriptor, const Params ¶ms) - : descriptor_(descriptor), - field_generators_( - new scoped_ptr[descriptor->field_count()]) { - - int next_has_bit_index = 0; - bool saved_defaults_needed = false; - // Construct all the FieldGenerators. - for (int i = 0; i < descriptor->field_count(); i++) { - FieldGenerator* field_generator = MakeGenerator( - descriptor->field(i), params, &next_has_bit_index); - saved_defaults_needed = saved_defaults_needed - || field_generator->SavedDefaultNeeded(); - field_generators_[i].reset(field_generator); - } - total_bits_ = next_has_bit_index; - saved_defaults_needed_ = saved_defaults_needed; -} - -FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, - const Params ¶ms, int* next_has_bit_index) { - JavaType java_type = GetJavaType(field); - if (field->is_repeated()) { - switch (java_type) { - case JAVATYPE_MESSAGE: - if (IsMapEntry(field->message_type())) { - return new MapFieldGenerator(field, params); - } else { - return new RepeatedMessageFieldGenerator(field, params); - } - case JAVATYPE_ENUM: - return new RepeatedEnumFieldGenerator(field, params); - default: - return new RepeatedPrimitiveFieldGenerator(field, params); - } - } else if (field->containing_oneof()) { - switch (java_type) { - case JAVATYPE_MESSAGE: - return new MessageOneofFieldGenerator(field, params); - case JAVATYPE_ENUM: - default: - return new PrimitiveOneofFieldGenerator(field, params); - } - } else if (params.optional_field_accessors() && field->is_optional() - && java_type != JAVATYPE_MESSAGE) { - // We need a has-bit for each primitive/enum field because their default - // values could be same as explicitly set values. But we don't need it - // for a message field because they have no defaults and Nano uses 'null' - // for unset messages, which cannot be set explicitly. - switch (java_type) { - case JAVATYPE_ENUM: - return new AccessorEnumFieldGenerator( - field, params, (*next_has_bit_index)++); - default: - return new AccessorPrimitiveFieldGenerator( - field, params, (*next_has_bit_index)++); - } - } else { - switch (java_type) { - case JAVATYPE_MESSAGE: - return new MessageFieldGenerator(field, params); - case JAVATYPE_ENUM: - return new EnumFieldGenerator(field, params); - default: - return new PrimitiveFieldGenerator(field, params); - } - } -} - -FieldGeneratorMap::~FieldGeneratorMap() {} - -const FieldGenerator& FieldGeneratorMap::get( - const FieldDescriptor* field) const { - GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); - return *field_generators_[field->index()]; -} - -void SetCommonOneofVariables(const FieldDescriptor* descriptor, - std::map* variables) { - (*variables)["oneof_name"] = - UnderscoresToCamelCase(descriptor->containing_oneof()); - (*variables)["oneof_capitalized_name"] = - UnderscoresToCapitalizedCamelCase(descriptor->containing_oneof()); - (*variables)["oneof_index"] = - SimpleItoa(descriptor->containing_oneof()->index()); - (*variables)["set_oneof_case"] = - "this." + (*variables)["oneof_name"] + - "Case_ = " + SimpleItoa(descriptor->number()); - (*variables)["clear_oneof_case"] = - "this." + (*variables)["oneof_name"] + "Case_ = 0"; - (*variables)["has_oneof_case"] = - "this." + (*variables)["oneof_name"] + "Case_ == " + - SimpleItoa(descriptor->number()); -} - -void GenerateOneofFieldEquals(const FieldDescriptor* descriptor, - const std::map& variables, - io::Printer* printer) { - if (GetJavaType(descriptor) == JAVATYPE_BYTES) { - printer->Print(variables, - "if (this.has$capitalized_name$()) {\n" - " if (!java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n" - " (byte[]) other.$oneof_name$_)) {\n" - " return false;\n" - " }\n" - "}\n"); - } else { - printer->Print(variables, - "if (this.has$capitalized_name$()) {\n" - " if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n" - " return false;\n" - " }\n" - "}\n"); - } -} - -void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor, - const std::map& variables, - io::Printer* printer) { - if (GetJavaType(descriptor) == JAVATYPE_BYTES) { - printer->Print(variables, - "result = 31 * result + ($has_oneof_case$\n" - " ? java.util.Arrays.hashCode((byte[]) this.$oneof_name$_) : 0);\n"); - } else { - printer->Print(variables, - "result = 31 * result +\n" - " ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n"); - } -} - -} // namespace javanano -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h deleted file mode 100644 index 347c888c9b1ab..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_field.h +++ /dev/null @@ -1,130 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__ - -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { - namespace io { - class Printer; // printer.h - } -} - -namespace protobuf { -namespace compiler { -namespace javanano { - -class FieldGenerator { - public: - FieldGenerator(const Params& params) : params_(params) {} - virtual ~FieldGenerator(); - - virtual bool SavedDefaultNeeded() const; - virtual void GenerateInitSavedDefaultCode(io::Printer* printer) const; - - // Generates code for Java fields and methods supporting this field. - // If this field needs a saved default (SavedDefaultNeeded() is true), - // then @lazy_init controls how the static field for that default value - // and its initialization code should be generated. If @lazy_init is - // true, the static field is not declared final and the initialization - // code is generated only when GenerateInitSavedDefaultCode is called; - // otherwise, the static field is declared final and initialized inline. - // GenerateInitSavedDefaultCode will not be called in the latter case. - virtual void GenerateMembers( - io::Printer* printer, bool lazy_init) const = 0; - - virtual void GenerateClearCode(io::Printer* printer) const = 0; - virtual void GenerateMergingCode(io::Printer* printer) const = 0; - - // Generates code to merge from packed serialized form. The default - // implementation will fail; subclasses which can handle packed serialized - // forms will override this and print appropriate code to the printer. - virtual void GenerateMergingCodeFromPacked(io::Printer* printer) const; - - virtual void GenerateSerializationCode(io::Printer* printer) const = 0; - virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; - virtual void GenerateEqualsCode(io::Printer* printer) const = 0; - virtual void GenerateHashCodeCode(io::Printer* printer) const = 0; - virtual void GenerateFixClonedCode(io::Printer* printer) const {} - - protected: - const Params& params_; - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); -}; - -// Convenience class which constructs FieldGenerators for a Descriptor. -class FieldGeneratorMap { - public: - explicit FieldGeneratorMap(const Descriptor* descriptor, const Params ¶ms); - ~FieldGeneratorMap(); - - const FieldGenerator& get(const FieldDescriptor* field) const; - int total_bits() const { return total_bits_; } - bool saved_defaults_needed() const { return saved_defaults_needed_; } - - private: - const Descriptor* descriptor_; - scoped_array > field_generators_; - int total_bits_; - bool saved_defaults_needed_; - - static FieldGenerator* MakeGenerator(const FieldDescriptor* field, - const Params ¶ms, int* next_has_bit_index); - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); -}; - -void SetCommonOneofVariables(const FieldDescriptor* descriptor, - std::map* variables); -void GenerateOneofFieldEquals(const FieldDescriptor* descriptor, - const std::map& variables, - io::Printer* printer); -void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor, - const std::map& variables, - io::Printer* printer); - -} // namespace javanano -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__ diff --git a/src/google/protobuf/compiler/javanano/javanano_file.cc b/src/google/protobuf/compiler/javanano/javanano_file.cc deleted file mode 100644 index 17f7386e77d5d..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_file.cc +++ /dev/null @@ -1,263 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -namespace { - -// Recursively searches the given message to see if it contains any extensions. -bool UsesExtensions(const Message& message) { - const Reflection* reflection = message.GetReflection(); - - // We conservatively assume that unknown fields are extensions. - if (reflection->GetUnknownFields(message).field_count() > 0) return true; - - vector fields; - reflection->ListFields(message, &fields); - - for (int i = 0; i < fields.size(); i++) { - if (fields[i]->is_extension()) return true; - - if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - if (fields[i]->is_repeated()) { - int size = reflection->FieldSize(message, fields[i]); - for (int j = 0; j < size; j++) { - const Message& sub_message = - reflection->GetRepeatedMessage(message, fields[i], j); - if (UsesExtensions(sub_message)) return true; - } - } else { - const Message& sub_message = reflection->GetMessage(message, fields[i]); - if (UsesExtensions(sub_message)) return true; - } - } - } - - return false; -} - -} // namespace - -FileGenerator::FileGenerator(const FileDescriptor* file, const Params& params) - : file_(file), - params_(params), - java_package_(FileJavaPackage(params, file)), - classname_(FileClassName(params, file)) {} - -FileGenerator::~FileGenerator() {} - -bool FileGenerator::Validate(string* error) { - // Check for extensions - FileDescriptorProto file_proto; - file_->CopyTo(&file_proto); - if (UsesExtensions(file_proto) && !params_.store_unknown_fields()) { - error->assign(file_->name()); - error->append( - ": Java NANO_RUNTIME only supports extensions when the " - "'store_unknown_fields' generator option is 'true'."); - return false; - } - - if (file_->service_count() != 0 && !params_.ignore_services()) { - error->assign(file_->name()); - error->append( - ": Java NANO_RUNTIME does not support services\""); - return false; - } - - if (!IsOuterClassNeeded(params_, file_)) { - return true; - } - - // Check whether legacy javanano generator would omit the outer class. - if (!params_.has_java_outer_classname(file_->name()) - && file_->message_type_count() == 1 - && file_->enum_type_count() == 0 && file_->extension_count() == 0) { - std::cout << "INFO: " << file_->name() << ":" << std::endl; - std::cout << "Javanano generator has changed to align with java generator. " - "An outer class will be created for this file and the single message " - "in the file will become a nested class. Use java_multiple_files to " - "skip generating the outer class, or set an explicit " - "java_outer_classname to suppress this message." << std::endl; - } - - // Check that no class name matches the file's class name. This is a common - // problem that leads to Java compile errors that can be hard to understand. - // It's especially bad when using the java_multiple_files, since we would - // end up overwriting the outer class with one of the inner ones. - bool found_conflict = false; - for (int i = 0; !found_conflict && i < file_->message_type_count(); i++) { - if (file_->message_type(i)->name() == classname_) { - found_conflict = true; - } - } - if (params_.java_enum_style()) { - for (int i = 0; !found_conflict && i < file_->enum_type_count(); i++) { - if (file_->enum_type(i)->name() == classname_) { - found_conflict = true; - } - } - } - if (found_conflict) { - error->assign(file_->name()); - error->append( - ": Cannot generate Java output because the file's outer class name, \""); - error->append(classname_); - error->append( - "\", matches the name of one of the types declared inside it. " - "Please either rename the type or use the java_outer_classname " - "option to specify a different outer class name for the .proto file."); - return false; - } - return true; -} - -void FileGenerator::Generate(io::Printer* printer) { - // We don't import anything because we refer to all classes by their - // fully-qualified names in the generated source. - printer->Print( - "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"); - if (!java_package_.empty()) { - printer->Print( - "\n" - "package $package$;\n", - "package", java_package_); - } - - // Note: constants (from enums, emitted in the loop below) may have the same names as constants - // in the nested classes. This causes Java warnings, but is not fatal, so we suppress those - // warnings here in the top-most class declaration. - printer->Print( - "\n" - "@SuppressWarnings(\"hiding\")\n" - "public interface $classname$ {\n", - "classname", classname_); - printer->Indent(); - - // ----------------------------------------------------------------- - - // Extensions. - for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator(file_->extension(i), params_).Generate(printer); - } - - // Enums. - for (int i = 0; i < file_->enum_type_count(); i++) { - EnumGenerator(file_->enum_type(i), params_).Generate(printer); - } - - // Messages. - if (!params_.java_multiple_files(file_->name())) { - for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator(file_->message_type(i), params_).Generate(printer); - } - } - - // Static variables. - for (int i = 0; i < file_->message_type_count(); i++) { - // TODO(kenton): Reuse MessageGenerator objects? - MessageGenerator(file_->message_type(i), params_).GenerateStaticVariables(printer); - } - - printer->Outdent(); - printer->Print( - "}\n"); -} - -template -static void GenerateSibling(const string& package_dir, - const string& java_package, - const DescriptorClass* descriptor, - GeneratorContext* output_directory, - vector* file_list, - const Params& params) { - string filename = package_dir + descriptor->name() + ".java"; - file_list->push_back(filename); - - scoped_ptr output( - output_directory->Open(filename)); - io::Printer printer(output.get(), '$'); - - printer.Print( - "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"); - if (!java_package.empty()) { - printer.Print( - "\n" - "package $package$;\n", - "package", java_package); - } - - GeneratorClass(descriptor, params).Generate(&printer); -} - -void FileGenerator::GenerateSiblings(const string& package_dir, - GeneratorContext* output_directory, - vector* file_list) { - if (params_.java_multiple_files(file_->name())) { - for (int i = 0; i < file_->message_type_count(); i++) { - GenerateSibling(package_dir, java_package_, - file_->message_type(i), - output_directory, file_list, params_); - } - - if (params_.java_enum_style()) { - for (int i = 0; i < file_->enum_type_count(); i++) { - GenerateSibling(package_dir, java_package_, - file_->enum_type(i), - output_directory, file_list, params_); - } - } - } -} - -} // namespace javanano -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/javanano/javanano_file.h b/src/google/protobuf/compiler/javanano/javanano_file.h deleted file mode 100644 index 217eafe2a88e6..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_file.h +++ /dev/null @@ -1,94 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__ - -#include -#include -#include -#include - -namespace google { -namespace protobuf { - class FileDescriptor; // descriptor.h - namespace io { - class Printer; // printer.h - } - namespace compiler { - class GeneratorContext; // code_generator.h - } -} - -namespace protobuf { -namespace compiler { -namespace javanano { - -class FileGenerator { - public: - explicit FileGenerator(const FileDescriptor* file, const Params& params); - ~FileGenerator(); - - // Checks for problems that would otherwise lead to cryptic compile errors. - // Returns true if there are no problems, or writes an error description to - // the given string and returns false otherwise. - bool Validate(string* error); - - void Generate(io::Printer* printer); - - // If we aren't putting everything into one file, this will write all the - // files other than the outer file (i.e. one for each message, enum, and - // service type). - void GenerateSiblings(const string& package_dir, - GeneratorContext* output_directory, - vector* file_list); - - const string& java_package() { return java_package_; } - const string& classname() { return classname_; } - - private: - const FileDescriptor* file_; - const Params& params_; - string java_package_; - string classname_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); -}; - -} // namespace javanano -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_FILE_H__ diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc deleted file mode 100644 index 7c3a04212fb07..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_generator.cc +++ /dev/null @@ -1,230 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -namespace { - -string TrimString(const string& s) { - string::size_type start = s.find_first_not_of(" \n\r\t"); - if (start == string::npos) { - return ""; - } - string::size_type end = s.find_last_not_of(" \n\r\t") + 1; - return s.substr(start, end - start); -} - -} // namespace - -void UpdateParamsRecursively(Params& params, - const FileDescriptor* file) { - // Add any parameters for this file - if (file->options().has_java_outer_classname()) { - params.set_java_outer_classname( - file->name(), file->options().java_outer_classname()); - } - if (file->options().has_java_package()) { - string result = file->options().java_package(); - if (!result.empty()) { - result += "."; - } - result += "nano"; - params.set_java_package( - file->name(), result); - } - if (file->options().has_java_multiple_files()) { - params.set_java_multiple_files( - file->name(), file->options().java_multiple_files()); - } - - // Loop through all dependent files recursively - // adding dep - for (int i = 0; i < file->dependency_count(); i++) { - UpdateParamsRecursively(params, file->dependency(i)); - } -} - -JavaNanoGenerator::JavaNanoGenerator() {} -JavaNanoGenerator::~JavaNanoGenerator() {} - -bool JavaNanoGenerator::Generate(const FileDescriptor* file, - const string& parameter, - GeneratorContext* output_directory, - string* error) const { - vector > options; - - ParseGeneratorParameter(parameter, &options); - - // ----------------------------------------------------------------- - // parse generator options - - // Name a file where we will write a list of generated file names, one - // per line. - string output_list_file; - Params params(file->name()); - - // Update per file params - UpdateParamsRecursively(params, file); - - // Replace any existing options with ones from command line - for (int i = 0; i < options.size(); i++) { - string option_name = TrimString(options[i].first); - string option_value = TrimString(options[i].second); - if (option_name == "output_list_file") { - output_list_file = option_value; - } else if (option_name == "java_package") { - vector parts; - SplitStringUsing(option_value, "|", &parts); - if (parts.size() != 2) { - *error = "Bad java_package, expecting filename|PackageName found '" - + option_value + "'"; - return false; - } - params.set_java_package(parts[0], parts[1]); - } else if (option_name == "java_outer_classname") { - vector parts; - SplitStringUsing(option_value, "|", &parts); - if (parts.size() != 2) { - *error = "Bad java_outer_classname, " - "expecting filename|ClassName found '" - + option_value + "'"; - return false; - } - params.set_java_outer_classname(parts[0], parts[1]); - } else if (option_name == "store_unknown_fields") { - params.set_store_unknown_fields(option_value == "true"); - } else if (option_name == "java_multiple_files") { - params.set_override_java_multiple_files(option_value == "true"); - } else if (option_name == "java_nano_generate_has") { - params.set_generate_has(option_value == "true"); - } else if (option_name == "enum_style") { - params.set_java_enum_style(option_value == "java"); - } else if (option_name == "optional_field_style") { - params.set_optional_field_accessors(option_value == "accessors"); - params.set_use_reference_types_for_primitives(option_value == "reftypes" - || option_value == "reftypes_compat_mode"); - params.set_reftypes_primitive_enums( - option_value == "reftypes_compat_mode"); - if (option_value == "reftypes_compat_mode") { - params.set_generate_clear(false); - } - } else if (option_name == "generate_equals") { - params.set_generate_equals(option_value == "true"); - } else if (option_name == "ignore_services") { - params.set_ignore_services(option_value == "true"); - } else if (option_name == "parcelable_messages") { - params.set_parcelable_messages(option_value == "true"); - } else if (option_name == "generate_clone") { - params.set_generate_clone(option_value == "true"); - } else if (option_name == "generate_intdefs") { - params.set_generate_intdefs(option_value == "true"); - } else if (option_name == "generate_clear") { - params.set_generate_clear(option_value == "true"); - } else { - *error = "Ignore unknown javanano generator option: " + option_name; - } - } - - // Check illegal parameter combinations - // Note: the enum-like optional_field_style generator param ensures - // that we can never have illegal combinations of field styles - // (e.g. reftypes and accessors can't be on at the same time). - if (params.generate_has() - && (params.optional_field_accessors() - || params.use_reference_types_for_primitives())) { - error->assign("java_nano_generate_has=true cannot be used in conjunction" - " with optional_field_style=accessors or optional_field_style=reftypes"); - return false; - } - - // ----------------------------------------------------------------- - - FileGenerator file_generator(file, params); - if (!file_generator.Validate(error)) { - return false; - } - - string package_dir = - StringReplace(file_generator.java_package(), ".", "/", true); - if (!package_dir.empty()) package_dir += "/"; - - vector all_files; - - if (IsOuterClassNeeded(params, file)) { - string java_filename = package_dir; - java_filename += file_generator.classname(); - java_filename += ".java"; - all_files.push_back(java_filename); - - // Generate main java file. - scoped_ptr output( - output_directory->Open(java_filename)); - io::Printer printer(output.get(), '$'); - file_generator.Generate(&printer); - } - - // Generate sibling files. - file_generator.GenerateSiblings(package_dir, output_directory, &all_files); - - // Generate output list if requested. - if (!output_list_file.empty()) { - // Generate output list. This is just a simple text file placed in a - // deterministic location which lists the .java files being generated. - scoped_ptr srclist_raw_output( - output_directory->Open(output_list_file)); - io::Printer srclist_printer(srclist_raw_output.get(), '$'); - for (int i = 0; i < all_files.size(); i++) { - srclist_printer.Print("$filename$\n", "filename", all_files[i]); - } - } - - return true; -} - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.h b/src/google/protobuf/compiler/javanano/javanano_generator.h deleted file mode 100644 index 6f9f7f2a4a01d..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_generator.h +++ /dev/null @@ -1,72 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. -// -// Generates Java nano code for a given .proto file. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__ - -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -// CodeGenerator implementation which generates Java nano code. If you create your -// own protocol compiler binary and you want it to support Java output for the -// nano runtime, you can do so by registering an instance of this CodeGenerator with -// the CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT JavaNanoGenerator : public CodeGenerator { - public: - JavaNanoGenerator(); - ~JavaNanoGenerator(); - - // implements CodeGenerator ---------------------------------------- - bool Generate(const FileDescriptor* file, - const string& parameter, - GeneratorContext* output_directory, - string* error) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaNanoGenerator); -}; - -} // namespace javanano -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_NANO_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc deleted file mode 100644 index 1927ba12f27b6..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc +++ /dev/null @@ -1,591 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -const char kThickSeparator[] = - "// ===================================================================\n"; -const char kThinSeparator[] = - "// -------------------------------------------------------------------\n"; - -class RenameKeywords { - private: - hash_set java_keywords_set_; - - public: - RenameKeywords() { - static const char* kJavaKeywordsList[] = { - // Reserved Java Keywords - "abstract", "assert", "boolean", "break", "byte", "case", "catch", - "char", "class", "const", "continue", "default", "do", "double", "else", - "enum", "extends", "final", "finally", "float", "for", "goto", "if", - "implements", "import", "instanceof", "int", "interface", "long", - "native", "new", "package", "private", "protected", "public", "return", - "short", "static", "strictfp", "super", "switch", "synchronized", - "this", "throw", "throws", "transient", "try", "void", "volatile", "while", - - // Reserved Keywords for Literals - "false", "null", "true" - }; - - for (int i = 0; i < GOOGLE_ARRAYSIZE(kJavaKeywordsList); i++) { - java_keywords_set_.insert(kJavaKeywordsList[i]); - } - } - - // Used to rename the a field name if it's a java keyword. Specifically - // this is used to rename the ["name"] or ["capitalized_name"] field params. - // (http://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html) - string RenameJavaKeywordsImpl(const string& input) { - string result = input; - - if (java_keywords_set_.find(result) != java_keywords_set_.end()) { - result += "_"; - } - - return result; - } - -}; - -static RenameKeywords sRenameKeywords; - -namespace { - -const char* kDefaultPackage = ""; - -const string& FieldName(const FieldDescriptor* field) { - // Groups are hacky: The name of the field is just the lower-cased name - // of the group type. In Java, though, we would like to retain the original - // capitalization of the type name. - if (field->type() == FieldDescriptor::TYPE_GROUP) { - return field->message_type()->name(); - } else { - return field->name(); - } -} - -string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) { - string result; - // Note: I distrust ctype.h due to locales. - for (int i = 0; i < input.size(); i++) { - if ('a' <= input[i] && input[i] <= 'z') { - if (cap_next_letter) { - result += input[i] + ('A' - 'a'); - } else { - result += input[i]; - } - cap_next_letter = false; - } else if ('A' <= input[i] && input[i] <= 'Z') { - if (i == 0 && !cap_next_letter) { - // Force first letter to lower-case unless explicitly told to - // capitalize it. - result += input[i] + ('a' - 'A'); - } else { - // Capital letters after the first are left as-is. - result += input[i]; - } - cap_next_letter = false; - } else if ('0' <= input[i] && input[i] <= '9') { - result += input[i]; - cap_next_letter = true; - } else { - cap_next_letter = true; - } - } - return result; -} - -} // namespace - -string UnderscoresToCamelCase(const FieldDescriptor* field) { - return UnderscoresToCamelCaseImpl(FieldName(field), false); -} - -string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { - return UnderscoresToCamelCaseImpl(FieldName(field), true); -} - -string UnderscoresToCamelCase(const MethodDescriptor* method) { - return UnderscoresToCamelCaseImpl(method->name(), false); -} - -string UnderscoresToCamelCase(const OneofDescriptor* oneof) { - return UnderscoresToCamelCaseImpl(oneof->name(), false); -} - -string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof) { - return UnderscoresToCamelCaseImpl(oneof->name(), true); -} - -string RenameJavaKeywords(const string& input) { - return sRenameKeywords.RenameJavaKeywordsImpl(input); -} - -string StripProto(const string& filename) { - if (HasSuffixString(filename, ".protodevel")) { - return StripSuffixString(filename, ".protodevel"); - } else { - return StripSuffixString(filename, ".proto"); - } -} - -string FileClassName(const Params& params, const FileDescriptor* file) { - if (params.has_java_outer_classname(file->name())) { - return params.java_outer_classname(file->name()); - } else { - // Use the filename itself with underscores removed - // and a CamelCase style name. - string basename; - string::size_type last_slash = file->name().find_last_of('/'); - if (last_slash == string::npos) { - basename = file->name(); - } else { - basename = file->name().substr(last_slash + 1); - } - return UnderscoresToCamelCaseImpl(StripProto(basename), true); - } -} - -string FileJavaPackage(const Params& params, const FileDescriptor* file) { - if (params.has_java_package(file->name())) { - return params.java_package(file->name()); - } else { - string result = kDefaultPackage; - if (!file->package().empty()) { - if (!result.empty()) result += '.'; - result += file->package(); - } - - if (!result.empty()) { - result += "."; - } - result += "nano"; - - return result; - } -} - -bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file) { - // If java_multiple_files is false, the outer class is always needed. - if (!params.java_multiple_files(file->name())) { - return true; - } - - // File-scope extensions need the outer class as the scope. - if (file->extension_count() != 0) { - return true; - } - - // If container interfaces are not generated, file-scope enums need the - // outer class as the scope. - if (file->enum_type_count() != 0 && !params.java_enum_style()) { - return true; - } - - return false; -} - -string ToJavaName(const Params& params, const string& name, bool is_class, - const Descriptor* parent, const FileDescriptor* file) { - string result; - if (parent != NULL) { - result.append(ClassName(params, parent)); - } else if (is_class && params.java_multiple_files(file->name())) { - result.append(FileJavaPackage(params, file)); - } else { - result.append(ClassName(params, file)); - } - if (!result.empty()) result.append(1, '.'); - result.append(RenameJavaKeywords(name)); - return result; -} - -string ClassName(const Params& params, const FileDescriptor* descriptor) { - string result = FileJavaPackage(params, descriptor); - if (!result.empty()) result += '.'; - result += FileClassName(params, descriptor); - return result; -} - -string ClassName(const Params& params, const EnumDescriptor* descriptor) { - const Descriptor* parent = descriptor->containing_type(); - // When using Java enum style, an enum's class name contains the enum name. - // Use the standard ToJavaName translation. - if (params.java_enum_style()) { - return ToJavaName(params, descriptor->name(), true, parent, - descriptor->file()); - } - // Otherwise the enum members are accessed from the enclosing class. - if (parent != NULL) { - return ClassName(params, parent); - } else { - return ClassName(params, descriptor->file()); - } -} - -string FieldConstantName(const FieldDescriptor *field) { - string name = field->name() + "_FIELD_NUMBER"; - UpperString(&name); - return name; -} - -string FieldDefaultConstantName(const FieldDescriptor *field) { - return "_" + RenameJavaKeywords(UnderscoresToCamelCase(field)) + "Default"; -} - -void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) { - // We don't want to print group bodies so we cut off after the first line - // (the second line for extensions). - string def = field->DebugString(); - string::size_type first_line_end = def.find_first_of('\n'); - printer->Print("// $def$\n", - "def", def.substr(0, first_line_end)); - if (field->is_extension()) { - string::size_type second_line_start = first_line_end + 1; - string::size_type second_line_length = - def.find('\n', second_line_start) - second_line_start; - printer->Print("// $def$\n", - "def", def.substr(second_line_start, second_line_length)); - } -} - -JavaType GetJavaType(FieldDescriptor::Type field_type) { - switch (field_type) { - case FieldDescriptor::TYPE_INT32: - case FieldDescriptor::TYPE_UINT32: - case FieldDescriptor::TYPE_SINT32: - case FieldDescriptor::TYPE_FIXED32: - case FieldDescriptor::TYPE_SFIXED32: - return JAVATYPE_INT; - - case FieldDescriptor::TYPE_INT64: - case FieldDescriptor::TYPE_UINT64: - case FieldDescriptor::TYPE_SINT64: - case FieldDescriptor::TYPE_FIXED64: - case FieldDescriptor::TYPE_SFIXED64: - return JAVATYPE_LONG; - - case FieldDescriptor::TYPE_FLOAT: - return JAVATYPE_FLOAT; - - case FieldDescriptor::TYPE_DOUBLE: - return JAVATYPE_DOUBLE; - - case FieldDescriptor::TYPE_BOOL: - return JAVATYPE_BOOLEAN; - - case FieldDescriptor::TYPE_STRING: - return JAVATYPE_STRING; - - case FieldDescriptor::TYPE_BYTES: - return JAVATYPE_BYTES; - - case FieldDescriptor::TYPE_ENUM: - return JAVATYPE_ENUM; - - case FieldDescriptor::TYPE_GROUP: - case FieldDescriptor::TYPE_MESSAGE: - return JAVATYPE_MESSAGE; - - // No default because we want the compiler to complain if any new - // types are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return JAVATYPE_INT; -} - -string PrimitiveTypeName(JavaType type) { - switch (type) { - case JAVATYPE_INT : return "int"; - case JAVATYPE_LONG : return "long"; - case JAVATYPE_FLOAT : return "float"; - case JAVATYPE_DOUBLE : return "double"; - case JAVATYPE_BOOLEAN: return "boolean"; - case JAVATYPE_STRING : return "java.lang.String"; - case JAVATYPE_BYTES : return "byte[]"; - case JAVATYPE_ENUM : return "int"; - case JAVATYPE_MESSAGE: return ""; - - // No default because we want the compiler to complain if any new - // JavaTypes are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return ""; -} - -string BoxedPrimitiveTypeName(JavaType type) { - switch (type) { - case JAVATYPE_INT : return "java.lang.Integer"; - case JAVATYPE_LONG : return "java.lang.Long"; - case JAVATYPE_FLOAT : return "java.lang.Float"; - case JAVATYPE_DOUBLE : return "java.lang.Double"; - case JAVATYPE_BOOLEAN: return "java.lang.Boolean"; - case JAVATYPE_STRING : return "java.lang.String"; - case JAVATYPE_BYTES : return "byte[]"; - case JAVATYPE_ENUM : return "java.lang.Integer"; - case JAVATYPE_MESSAGE: return ""; - - // No default because we want the compiler to complain if any new - // JavaTypes are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return ""; -} - -string EmptyArrayName(const Params& params, const FieldDescriptor* field) { - switch (GetJavaType(field)) { - case JAVATYPE_INT : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY"; - case JAVATYPE_LONG : return "com.google.protobuf.nano.WireFormatNano.EMPTY_LONG_ARRAY"; - case JAVATYPE_FLOAT : return "com.google.protobuf.nano.WireFormatNano.EMPTY_FLOAT_ARRAY"; - case JAVATYPE_DOUBLE : return "com.google.protobuf.nano.WireFormatNano.EMPTY_DOUBLE_ARRAY"; - case JAVATYPE_BOOLEAN: return "com.google.protobuf.nano.WireFormatNano.EMPTY_BOOLEAN_ARRAY"; - case JAVATYPE_STRING : return "com.google.protobuf.nano.WireFormatNano.EMPTY_STRING_ARRAY"; - case JAVATYPE_BYTES : return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES_ARRAY"; - case JAVATYPE_ENUM : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY"; - case JAVATYPE_MESSAGE: return ClassName(params, field->message_type()) + ".EMPTY_ARRAY"; - - // No default because we want the compiler to complain if any new - // JavaTypes are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return ""; -} - -string DefaultValue(const Params& params, const FieldDescriptor* field) { - if (field->label() == FieldDescriptor::LABEL_REPEATED) { - return EmptyArrayName(params, field); - } - - if (params.use_reference_types_for_primitives()) { - if (params.reftypes_primitive_enums() - && field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { - return "Integer.MIN_VALUE"; - } - return "null"; - } - - // Switch on cpp_type since we need to know which default_value_* method - // of FieldDescriptor to call. - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: - return SimpleItoa(field->default_value_int32()); - case FieldDescriptor::CPPTYPE_UINT32: - // Need to print as a signed int since Java has no unsigned. - return SimpleItoa(static_cast(field->default_value_uint32())); - case FieldDescriptor::CPPTYPE_INT64: - return SimpleItoa(field->default_value_int64()) + "L"; - case FieldDescriptor::CPPTYPE_UINT64: - return SimpleItoa(static_cast(field->default_value_uint64())) + - "L"; - case FieldDescriptor::CPPTYPE_DOUBLE: { - double value = field->default_value_double(); - if (value == std::numeric_limits::infinity()) { - return "Double.POSITIVE_INFINITY"; - } else if (value == -std::numeric_limits::infinity()) { - return "Double.NEGATIVE_INFINITY"; - } else if (value != value) { - return "Double.NaN"; - } else { - return SimpleDtoa(value) + "D"; - } - } - case FieldDescriptor::CPPTYPE_FLOAT: { - float value = field->default_value_float(); - if (value == std::numeric_limits::infinity()) { - return "Float.POSITIVE_INFINITY"; - } else if (value == -std::numeric_limits::infinity()) { - return "Float.NEGATIVE_INFINITY"; - } else if (value != value) { - return "Float.NaN"; - } else { - return SimpleFtoa(value) + "F"; - } - } - case FieldDescriptor::CPPTYPE_BOOL: - return field->default_value_bool() ? "true" : "false"; - case FieldDescriptor::CPPTYPE_STRING: - if (!field->default_value_string().empty()) { - // Point it to the static final in the generated code. - return FieldDefaultConstantName(field); - } else { - if (field->type() == FieldDescriptor::TYPE_BYTES) { - return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES"; - } else { - return "\"\""; - } - } - - case FieldDescriptor::CPPTYPE_ENUM: - return ClassName(params, field->enum_type()) + "." + - RenameJavaKeywords(field->default_value_enum()->name()); - - case FieldDescriptor::CPPTYPE_MESSAGE: - return "null"; - - // No default because we want the compiler to complain if any new - // types are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return ""; -} - - -static const char* kBitMasks[] = { - "0x00000001", - "0x00000002", - "0x00000004", - "0x00000008", - "0x00000010", - "0x00000020", - "0x00000040", - "0x00000080", - - "0x00000100", - "0x00000200", - "0x00000400", - "0x00000800", - "0x00001000", - "0x00002000", - "0x00004000", - "0x00008000", - - "0x00010000", - "0x00020000", - "0x00040000", - "0x00080000", - "0x00100000", - "0x00200000", - "0x00400000", - "0x00800000", - - "0x01000000", - "0x02000000", - "0x04000000", - "0x08000000", - "0x10000000", - "0x20000000", - "0x40000000", - "0x80000000", -}; - -string GetBitFieldName(int index) { - string var_name = "bitField"; - var_name += SimpleItoa(index); - var_name += "_"; - return var_name; -} - -string GetBitFieldNameForBit(int bit_index) { - return GetBitFieldName(bit_index / 32); -} - -string GenerateGetBit(int bit_index) { - string var_name = GetBitFieldNameForBit(bit_index); - int bit_in_var_index = bit_index % 32; - - string mask = kBitMasks[bit_in_var_index]; - string result = "((" + var_name + " & " + mask + ") != 0)"; - return result; -} - -string GenerateSetBit(int bit_index) { - string var_name = GetBitFieldNameForBit(bit_index); - int bit_in_var_index = bit_index % 32; - - string mask = kBitMasks[bit_in_var_index]; - string result = var_name + " |= " + mask; - return result; -} - -string GenerateClearBit(int bit_index) { - string var_name = GetBitFieldNameForBit(bit_index); - int bit_in_var_index = bit_index % 32; - - string mask = kBitMasks[bit_in_var_index]; - string result = var_name + " = (" + var_name + " & ~" + mask + ")"; - return result; -} - -string GenerateDifferentBit(int bit_index) { - string var_name = GetBitFieldNameForBit(bit_index); - int bit_in_var_index = bit_index % 32; - - string mask = kBitMasks[bit_in_var_index]; - string result = "((" + var_name + " & " + mask - + ") != (other." + var_name + " & " + mask + "))"; - return result; -} - -void SetBitOperationVariables(const string name, - int bitIndex, std::map* variables) { - (*variables)["get_" + name] = GenerateGetBit(bitIndex); - (*variables)["set_" + name] = GenerateSetBit(bitIndex); - (*variables)["clear_" + name] = GenerateClearBit(bitIndex); - (*variables)["different_" + name] = GenerateDifferentBit(bitIndex); -} - -bool HasMapField(const Descriptor* descriptor) { - for (int i = 0; i < descriptor->field_count(); ++i) { - const FieldDescriptor* field = descriptor->field(i); - if (field->type() == FieldDescriptor::TYPE_MESSAGE && - IsMapEntry(field->message_type())) { - return true; - } - } - return false; -} - -} // namespace javanano -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h deleted file mode 100644 index 04b2d6335301d..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.h +++ /dev/null @@ -1,199 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__ - -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -// Commonly-used separator comments. Thick is a line of '=', thin is a line -// of '-'. -extern const char kThickSeparator[]; -extern const char kThinSeparator[]; - -// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes -// "fooBarBaz" or "FooBarBaz", respectively. -string UnderscoresToCamelCase(const FieldDescriptor* field); -string UnderscoresToCamelCase(const OneofDescriptor* oneof); -string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); -string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof); - -// Appends an "_" to the end of a field where the name is a reserved java -// keyword. For example int32 public = 1 will generate int public_. -string RenameJavaKeywords(const string& input); - -// Similar, but for method names. (Typically, this merely has the effect -// of lower-casing the first letter of the name.) -string UnderscoresToCamelCase(const MethodDescriptor* method); - -// Strips ".proto" or ".protodevel" from the end of a filename. -string StripProto(const string& filename); - -// Gets the unqualified class name for the file. Each .proto file becomes a -// single Java class, with all its contents nested in that class. -string FileClassName(const Params& params, const FileDescriptor* file); - -// Returns the file's Java package name. -string FileJavaPackage(const Params& params, const FileDescriptor* file); - -// Returns whether the Java outer class is needed, i.e. whether the option -// java_multiple_files is false, or the proto file contains any file-scope -// enums/extensions. -bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file); - -// Converts the given simple name of a proto entity to its fully-qualified name -// in the Java namespace, given that it is in the given file enclosed in the -// given parent message (or NULL for file-scope entities). Whether the file's -// outer class name should be included in the return value depends on factors -// inferrable from the given arguments, including is_class which indicates -// whether the entity translates to a Java class. -string ToJavaName(const Params& params, const string& name, bool is_class, - const Descriptor* parent, const FileDescriptor* file); - -// These return the fully-qualified class name corresponding to the given -// descriptor. -inline string ClassName(const Params& params, const Descriptor* descriptor) { - return ToJavaName(params, descriptor->name(), true, - descriptor->containing_type(), descriptor->file()); -} -string ClassName(const Params& params, const EnumDescriptor* descriptor); -inline string ClassName(const Params& params, - const ServiceDescriptor* descriptor) { - return ToJavaName(params, descriptor->name(), true, NULL, descriptor->file()); -} -inline string ExtensionIdentifierName(const Params& params, - const FieldDescriptor* descriptor) { - return ToJavaName(params, descriptor->name(), false, - descriptor->extension_scope(), descriptor->file()); -} -string ClassName(const Params& params, const FileDescriptor* descriptor); - -// Get the unqualified name that should be used for a field's field -// number constant. -string FieldConstantName(const FieldDescriptor *field); - -string FieldDefaultConstantName(const FieldDescriptor *field); - -// Print the field's proto-syntax definition as a comment. -void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field); - -enum JavaType { - JAVATYPE_INT, - JAVATYPE_LONG, - JAVATYPE_FLOAT, - JAVATYPE_DOUBLE, - JAVATYPE_BOOLEAN, - JAVATYPE_STRING, - JAVATYPE_BYTES, - JAVATYPE_ENUM, - JAVATYPE_MESSAGE -}; - -JavaType GetJavaType(FieldDescriptor::Type field_type); - -inline JavaType GetJavaType(const FieldDescriptor* field) { - return GetJavaType(field->type()); -} - -string PrimitiveTypeName(JavaType type); - -// Get the fully-qualified class name for a boxed primitive type, e.g. -// "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message -// types. -string BoxedPrimitiveTypeName(JavaType type); - -string EmptyArrayName(const Params& params, const FieldDescriptor* field); - -string DefaultValue(const Params& params, const FieldDescriptor* field); - - -// Methods for shared bitfields. - -// Gets the name of the shared bitfield for the given field index. -string GetBitFieldName(int index); - -// Gets the name of the shared bitfield for the given bit index. -// Effectively, GetBitFieldName(bit_index / 32) -string GetBitFieldNameForBit(int bit_index); - -// Generates the java code for the expression that returns whether the bit at -// the given bit index is set. -// Example: "((bitField1_ & 0x04000000) != 0)" -string GenerateGetBit(int bit_index); - -// Generates the java code for the expression that sets the bit at the given -// bit index. -// Example: "bitField1_ |= 0x04000000" -string GenerateSetBit(int bit_index); - -// Generates the java code for the expression that clears the bit at the given -// bit index. -// Example: "bitField1_ = (bitField1_ & ~0x04000000)" -string GenerateClearBit(int bit_index); - -// Generates the java code for the expression that returns whether the bit at -// the given bit index contains different values in the current object and -// another object accessible via the variable 'other'. -// Example: "((bitField1_ & 0x04000000) != (other.bitField1_ & 0x04000000))" -string GenerateDifferentBit(int bit_index); - -// Sets the 'get_*', 'set_*', 'clear_*' and 'different_*' variables, where * is -// the given name of the bit, to the appropriate Java expressions for the given -// bit index. -void SetBitOperationVariables(const string name, - int bitIndex, std::map* variables); - -inline bool IsMapEntry(const Descriptor* descriptor) { - // TODO(liujisi): Add an option to turn on maps for proto2 syntax as well. - return descriptor->options().map_entry() && - descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3; -} - -bool HasMapField(const Descriptor* descriptor); - -} // namespace javanano -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_HELPERS_H__ diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc deleted file mode 100644 index a4ab8858f28fa..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_map_field.cc +++ /dev/null @@ -1,186 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -namespace { - -string TypeName(const Params& params, const FieldDescriptor* field, - bool boxed) { - JavaType java_type = GetJavaType(field); - switch (java_type) { - case JAVATYPE_MESSAGE: - return ClassName(params, field->message_type()); - case JAVATYPE_INT: - case JAVATYPE_LONG: - case JAVATYPE_FLOAT: - case JAVATYPE_DOUBLE: - case JAVATYPE_BOOLEAN: - case JAVATYPE_STRING: - case JAVATYPE_BYTES: - case JAVATYPE_ENUM: - if (boxed) { - return BoxedPrimitiveTypeName(java_type); - } else { - return PrimitiveTypeName(java_type); - } - // No default because we want the compiler to complain if any new JavaTypes - // are added.. - } - - GOOGLE_LOG(FATAL) << "should not reach here."; - return ""; -} - -const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) { - GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); - const Descriptor* message = descriptor->message_type(); - GOOGLE_CHECK(message->options().map_entry()); - return message->FindFieldByName("key"); -} - -const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) { - GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); - const Descriptor* message = descriptor->message_type(); - GOOGLE_CHECK(message->options().map_entry()); - return message->FindFieldByName("value"); -} - -void SetMapVariables(const Params& params, - const FieldDescriptor* descriptor, std::map* variables) { - const FieldDescriptor* key = KeyField(descriptor); - const FieldDescriptor* value = ValueField(descriptor); - (*variables)["name"] = - RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["key_type"] = TypeName(params, key, false); - (*variables)["boxed_key_type"] = TypeName(params,key, true); - (*variables)["key_desc_type"] = - "TYPE_" + ToUpper(FieldDescriptor::TypeName(key->type())); - (*variables)["key_tag"] = SimpleItoa(internal::WireFormat::MakeTag(key)); - (*variables)["value_type"] = TypeName(params, value, false); - (*variables)["boxed_value_type"] = TypeName(params, value, true); - (*variables)["value_desc_type"] = - "TYPE_" + ToUpper(FieldDescriptor::TypeName(value->type())); - (*variables)["value_tag"] = SimpleItoa(internal::WireFormat::MakeTag(value)); - (*variables)["type_parameters"] = - (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"]; - (*variables)["value_default"] = - value->type() == FieldDescriptor::TYPE_MESSAGE - ? "new " + (*variables)["value_type"] + "()" - : "null"; -} -} // namespace - -// =================================================================== -MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, - const Params& params) - : FieldGenerator(params), descriptor_(descriptor) { - SetMapVariables(params, descriptor, &variables_); -} - -MapFieldGenerator::~MapFieldGenerator() {} - -void MapFieldGenerator:: -GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { - printer->Print(variables_, - "public java.util.Map<$type_parameters$> $name$;\n"); -} - -void MapFieldGenerator:: -GenerateClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$ = null;\n"); -} - -void MapFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "this.$name$ = com.google.protobuf.nano.InternalNano.mergeMapEntry(\n" - " input, this.$name$, mapFactory,\n" - " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" - " com.google.protobuf.nano.InternalNano.$value_desc_type$,\n" - " $value_default$,\n" - " $key_tag$, $value_tag$);\n" - "\n"); -} - -void MapFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null) {\n" - " com.google.protobuf.nano.InternalNano.serializeMapField(\n" - " output, this.$name$, $number$,\n" - " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" - " com.google.protobuf.nano.InternalNano.$value_desc_type$);\n" - "}\n"); -} - -void MapFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null) {\n" - " size += com.google.protobuf.nano.InternalNano.computeMapFieldSize(\n" - " this.$name$, $number$,\n" - " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" - " com.google.protobuf.nano.InternalNano.$value_desc_type$);\n" - "}\n"); -} - -void MapFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!com.google.protobuf.nano.InternalNano.equals(\n" - " this.$name$, other.$name$)) {\n" - " return false;\n" - "}\n"); -} - -void MapFieldGenerator:: -GenerateHashCodeCode(io::Printer* printer) const { - printer->Print(variables_, - "result = 31 * result +\n" - " com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n"); -} - -} // namespace javanano -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.h b/src/google/protobuf/compiler/javanano/javanano_map_field.h deleted file mode 100644 index 81e5915dfe13f..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_map_field.h +++ /dev/null @@ -1,70 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__ - -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -class MapFieldGenerator : public FieldGenerator { - public: - explicit MapFieldGenerator( - const FieldDescriptor* descriptor, const Params& params); - ~MapFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - void GenerateMembers(io::Printer* printer, bool lazy_init) const; - void GenerateClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCodeCode(io::Printer* printer) const; - - private: - const FieldDescriptor* descriptor_; - std::map variables_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator); -}; - -} // namespace javanano -} // namespace compiler -} // namespace protobuf -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__ diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc deleted file mode 100644 index 7842188784b3d..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ /dev/null @@ -1,676 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -using internal::WireFormat; -using internal::WireFormatLite; - -namespace { - -struct FieldOrderingByNumber { - inline bool operator()(const FieldDescriptor* a, - const FieldDescriptor* b) const { - return a->number() < b->number(); - } -}; - -// Sort the fields of the given Descriptor by number into a new[]'d array -// and return it. -const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { - const FieldDescriptor** fields = - new const FieldDescriptor*[descriptor->field_count()]; - for (int i = 0; i < descriptor->field_count(); i++) { - fields[i] = descriptor->field(i); - } - std::sort(fields, fields + descriptor->field_count(), - FieldOrderingByNumber()); - return fields; -} - -} // namespace - -// =================================================================== - -MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params) - : params_(params), - descriptor_(descriptor), - field_generators_(descriptor, params) { -} - -MessageGenerator::~MessageGenerator() {} - -void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { - // Generate static members for all nested types. - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - // TODO(kenton): Reuse MessageGenerator objects? - if (IsMapEntry(descriptor_->nested_type(i))) continue; - MessageGenerator(descriptor_->nested_type(i), params_) - .GenerateStaticVariables(printer); - } -} - -void MessageGenerator::GenerateStaticVariableInitializers( - io::Printer* printer) { - // Generate static member initializers for all nested types. - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - // TODO(kenton): Reuse MessageGenerator objects? - if (IsMapEntry(descriptor_->nested_type(i))) continue; - MessageGenerator(descriptor_->nested_type(i), params_) - .GenerateStaticVariableInitializers(printer); - } -} - -void MessageGenerator::Generate(io::Printer* printer) { - if (!params_.store_unknown_fields() && - (descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) { - GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the " - "'store_unknown_fields' generator option is 'true'\n"; - } - - const string& file_name = descriptor_->file()->name(); - bool is_own_file = - params_.java_multiple_files(file_name) - && descriptor_->containing_type() == NULL; - - if (is_own_file) { - // Note: constants (from enums and fields requiring stored defaults, emitted in the loop below) - // may have the same names as constants in the nested classes. This causes Java warnings, but - // is not fatal, so we suppress those warnings here in the top-most class declaration. - printer->Print( - "\n" - "@SuppressWarnings(\"hiding\")\n" - "public final class $classname$ extends\n", - "classname", descriptor_->name()); - } else { - printer->Print( - "\n" - "public static final class $classname$ extends\n", - "classname", descriptor_->name()); - } - if (params_.store_unknown_fields() && params_.parcelable_messages()) { - printer->Print( - " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$>", - "classname", descriptor_->name()); - } else if (params_.store_unknown_fields()) { - printer->Print( - " com.google.protobuf.nano.ExtendableMessageNano<$classname$>", - "classname", descriptor_->name()); - } else if (params_.parcelable_messages()) { - printer->Print( - " com.google.protobuf.nano.android.ParcelableMessageNano"); - } else { - printer->Print( - " com.google.protobuf.nano.MessageNano"); - } - if (params_.generate_clone()) { - printer->Print(" implements java.lang.Cloneable {\n"); - } else { - printer->Print(" {\n"); - } - printer->Indent(); - - if (params_.parcelable_messages()) { - printer->Print( - "\n" - "// Used by Parcelable\n" - "@SuppressWarnings({\"unused\"})\n" - "public static final android.os.Parcelable.Creator<$classname$> CREATOR =\n" - " new com.google.protobuf.nano.android.ParcelableMessageNanoCreator<\n" - " $classname$>($classname$.class);\n", - "classname", descriptor_->name()); - } - - // Nested types and extensions - for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer); - } - - for (int i = 0; i < descriptor_->enum_type_count(); i++) { - EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer); - } - - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - if (IsMapEntry(descriptor_->nested_type(i))) continue; - MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer); - } - - // oneof - std::map vars; - vars["message_name"] = descriptor_->name(); - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i); - vars["oneof_name"] = UnderscoresToCamelCase(oneof_desc); - vars["oneof_capitalized_name"] = - UnderscoresToCapitalizedCamelCase(oneof_desc); - vars["oneof_index"] = SimpleItoa(oneof_desc->index()); - // Oneof Constants - for (int j = 0; j < oneof_desc->field_count(); j++) { - const FieldDescriptor* field = oneof_desc->field(j); - vars["number"] = SimpleItoa(field->number()); - vars["cap_field_name"] = ToUpper(field->name()); - printer->Print(vars, - "public static final int $cap_field_name$_FIELD_NUMBER = $number$;\n"); - } - // oneofCase_ and oneof_ - printer->Print(vars, - "private int $oneof_name$Case_ = 0;\n" - "private java.lang.Object $oneof_name$_;\n"); - printer->Print(vars, - "public int get$oneof_capitalized_name$Case() {\n" - " return this.$oneof_name$Case_;\n" - "}\n"); - // Oneof clear - printer->Print(vars, - "public $message_name$ clear$oneof_capitalized_name$() {\n" - " this.$oneof_name$Case_ = 0;\n" - " this.$oneof_name$_ = null;\n" - " return this;\n" - "}\n"); - } - - // Lazy initialization of otherwise static final fields can help prevent the - // class initializer from being generated. We want to prevent it because it - // stops ProGuard from inlining any methods in this class into call sites and - // therefore reducing the method count. However, extensions are best kept as - // public static final fields with initializers, so with their existence we - // won't bother with lazy initialization. - bool lazy_init = descriptor_->extension_count() == 0; - - // Empty array - if (lazy_init) { - printer->Print( - "\n" - "private static volatile $classname$[] _emptyArray;\n" - "public static $classname$[] emptyArray() {\n" - " // Lazily initializes the empty array\n" - " if (_emptyArray == null) {\n" - " synchronized (\n" - " com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n" - " if (_emptyArray == null) {\n" - " _emptyArray = new $classname$[0];\n" - " }\n" - " }\n" - " }\n" - " return _emptyArray;\n" - "}\n", - "classname", descriptor_->name()); - } else { - printer->Print( - "\n" - "private static final $classname$[] EMPTY_ARRAY = {};\n" - "public static $classname$[] emptyArray() {\n" - " return EMPTY_ARRAY;\n" - "}\n", - "classname", descriptor_->name()); - } - - // Integers for bit fields - int totalInts = (field_generators_.total_bits() + 31) / 32; - if (totalInts > 0) { - printer->Print("\n"); - for (int i = 0; i < totalInts; i++) { - printer->Print("private int $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } - } - - // Fields and maybe their default values - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print("\n"); - PrintFieldComment(printer, descriptor_->field(i)); - field_generators_.get(descriptor_->field(i)).GenerateMembers( - printer, lazy_init); - } - - // Constructor, with lazy init code if needed - if (lazy_init && field_generators_.saved_defaults_needed()) { - printer->Print( - "\n" - "private static volatile boolean _classInitialized;\n" - "\n" - "public $classname$() {\n" - " // Lazily initializes the field defaults\n" - " if (!_classInitialized) {\n" - " synchronized (\n" - " com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n" - " if (!_classInitialized) {\n", - "classname", descriptor_->name()); - printer->Indent(); - printer->Indent(); - printer->Indent(); - printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateInitSavedDefaultCode(printer); - } - printer->Outdent(); - printer->Outdent(); - printer->Outdent(); - printer->Outdent(); - printer->Print( - " _classInitialized = true;\n" - " }\n" - " }\n" - " }\n"); - if (params_.generate_clear()) { - printer->Print(" clear();\n"); - } - printer->Print("}\n"); - } else { - printer->Print( - "\n" - "public $classname$() {\n", - "classname", descriptor_->name()); - if (params_.generate_clear()) { - printer->Print(" clear();\n"); - } else { - printer->Indent(); - GenerateFieldInitializers(printer); - printer->Outdent(); - } - printer->Print("}\n"); - } - - // Other methods in this class - - GenerateClear(printer); - - if (params_.generate_clone()) { - GenerateClone(printer); - } - - if (params_.generate_equals()) { - GenerateEquals(printer); - GenerateHashCode(printer); - } - - GenerateMessageSerializationMethods(printer); - GenerateMergeFromMethods(printer); - GenerateParseFromMethods(printer); - - printer->Outdent(); - printer->Print("}\n"); -} - -// =================================================================== - -void MessageGenerator:: -GenerateMessageSerializationMethods(io::Printer* printer) { - // Rely on the parent implementations of writeTo() and getSerializedSize() - // if there are no fields to serialize in this message. - if (descriptor_->field_count() == 0) { - return; - } - - scoped_array sorted_fields( - SortFieldsByNumber(descriptor_)); - - printer->Print( - "\n" - "@Override\n" - "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n" - " throws java.io.IOException {\n"); - printer->Indent(); - - // Output the fields in sorted order - for (int i = 0; i < descriptor_->field_count(); i++) { - GenerateSerializeOneField(printer, sorted_fields[i]); - } - - // The parent implementation will write any unknown fields if necessary. - printer->Print( - "super.writeTo(output);\n"); - - printer->Outdent(); - printer->Print("}\n"); - - // The parent implementation will get the serialized size for unknown - // fields if necessary. - printer->Print( - "\n" - "@Override\n" - "protected int computeSerializedSize() {\n" - " int size = super.computeSerializedSize();\n"); - printer->Indent(); - - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer); - } - - printer->Outdent(); - printer->Print( - " return size;\n" - "}\n"); -} - -void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) { - scoped_array sorted_fields( - SortFieldsByNumber(descriptor_)); - - printer->Print( - "\n" - "@Override\n" - "public $classname$ mergeFrom(\n" - " com.google.protobuf.nano.CodedInputByteBufferNano input)\n" - " throws java.io.IOException {\n", - "classname", descriptor_->name()); - - printer->Indent(); - if (HasMapField(descriptor_)) { - printer->Print( - "com.google.protobuf.nano.MapFactories.MapFactory mapFactory =\n" - " com.google.protobuf.nano.MapFactories.getMapFactory();\n"); - } - - printer->Print( - "while (true) {\n"); - printer->Indent(); - - printer->Print( - "int tag = input.readTag();\n" - "switch (tag) {\n"); - printer->Indent(); - - printer->Print( - "case 0:\n" // zero signals EOF / limit reached - " return this;\n" - "default: {\n"); - - printer->Indent(); - if (params_.store_unknown_fields()) { - printer->Print( - "if (!storeUnknownField(input, tag)) {\n" - " return this;\n" - "}\n"); - } else { - printer->Print( - "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n" - " return this;\n" // it's an endgroup tag - "}\n"); - } - printer->Print("break;\n"); - printer->Outdent(); - printer->Print("}\n"); - - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = sorted_fields[i]; - uint32 tag = WireFormatLite::MakeTag(field->number(), - WireFormat::WireTypeForFieldType(field->type())); - - printer->Print( - "case $tag$: {\n", - "tag", SimpleItoa(tag)); - printer->Indent(); - - field_generators_.get(field).GenerateMergingCode(printer); - - printer->Outdent(); - printer->Print( - " break;\n" - "}\n"); - - if (field->is_packable()) { - // To make packed = true wire compatible, we generate parsing code from a - // packed version of this field regardless of field->options().packed(). - uint32 packed_tag = WireFormatLite::MakeTag(field->number(), - WireFormatLite::WIRETYPE_LENGTH_DELIMITED); - printer->Print( - "case $tag$: {\n", - "tag", SimpleItoa(packed_tag)); - printer->Indent(); - - field_generators_.get(field).GenerateMergingCodeFromPacked(printer); - - printer->Outdent(); - printer->Print( - " break;\n" - "}\n"); - } - } - - printer->Outdent(); - printer->Outdent(); - printer->Outdent(); - printer->Print( - " }\n" // switch (tag) - " }\n" // while (true) - "}\n"); -} - -void MessageGenerator:: -GenerateParseFromMethods(io::Printer* printer) { - // Note: These are separate from GenerateMessageSerializationMethods() - // because they need to be generated even for messages that are optimized - // for code size. - printer->Print( - "\n" - "public static $classname$ parseFrom(byte[] data)\n" - " throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n" - " return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n" - "}\n" - "\n" - "public static $classname$ parseFrom(\n" - " com.google.protobuf.nano.CodedInputByteBufferNano input)\n" - " throws java.io.IOException {\n" - " return new $classname$().mergeFrom(input);\n" - "}\n", - "classname", descriptor_->name()); -} - -void MessageGenerator::GenerateSerializeOneField( - io::Printer* printer, const FieldDescriptor* field) { - field_generators_.get(field).GenerateSerializationCode(printer); -} - -void MessageGenerator::GenerateClear(io::Printer* printer) { - if (!params_.generate_clear()) { - return; - } - printer->Print( - "\n" - "public $classname$ clear() {\n", - "classname", descriptor_->name()); - printer->Indent(); - - GenerateFieldInitializers(printer); - - printer->Outdent(); - printer->Print( - " return this;\n" - "}\n"); -} - -void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) { - // Clear bit fields. - int totalInts = (field_generators_.total_bits() + 31) / 32; - for (int i = 0; i < totalInts; i++) { - printer->Print("$bit_field_name$ = 0;\n", - "bit_field_name", GetBitFieldName(i)); - } - - // Call clear for all of the fields. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - field_generators_.get(field).GenerateClearCode(printer); - } - - // Clear oneofs. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "clear$oneof_capitalized_name$();\n", - "oneof_capitalized_name", UnderscoresToCapitalizedCamelCase( - descriptor_->oneof_decl(i))); - } - - // Clear unknown fields. - if (params_.store_unknown_fields()) { - printer->Print("unknownFieldData = null;\n"); - } - printer->Print("cachedSize = -1;\n"); -} - -void MessageGenerator::GenerateClone(io::Printer* printer) { - printer->Print( - "@Override\n" - "public $classname$ clone() {\n", - "classname", descriptor_->name()); - printer->Indent(); - - printer->Print( - "$classname$ cloned;\n" - "try {\n" - " cloned = ($classname$) super.clone();\n" - "} catch (java.lang.CloneNotSupportedException e) {\n" - " throw new java.lang.AssertionError(e);\n" - "}\n", - "classname", descriptor_->name()); - - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)).GenerateFixClonedCode(printer); - } - - printer->Outdent(); - printer->Print( - " return cloned;\n" - "}\n" - "\n"); -} - -void MessageGenerator::GenerateEquals(io::Printer* printer) { - // Don't override if there are no fields. We could generate an - // equals method that compares types, but often empty messages - // are used as namespaces. - if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) { - return; - } - - printer->Print( - "\n" - "@Override\n" - "public boolean equals(Object o) {\n"); - printer->Indent(); - printer->Print( - "if (o == this) {\n" - " return true;\n" - "}\n" - "if (!(o instanceof $classname$)) {\n" - " return false;\n" - "}\n" - "$classname$ other = ($classname$) o;\n", - "classname", descriptor_->name()); - - // Checking oneof case before checking each oneof field. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i); - printer->Print( - "if (this.$oneof_name$Case_ != other.$oneof_name$Case_) {\n" - " return false;\n" - "}\n", - "oneof_name", UnderscoresToCamelCase(oneof_desc)); - } - - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - field_generators_.get(field).GenerateEqualsCode(printer); - } - - if (params_.store_unknown_fields()) { - printer->Print( - "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n" - " return other.unknownFieldData == null || other.unknownFieldData.isEmpty();\n" - "} else {\n" - " return unknownFieldData.equals(other.unknownFieldData);\n" - "}"); - } else { - printer->Print( - "return true;\n"); - } - - printer->Outdent(); - printer->Print("}\n"); -} - -void MessageGenerator::GenerateHashCode(io::Printer* printer) { - if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) { - return; - } - - printer->Print( - "\n" - "@Override\n" - "public int hashCode() {\n"); - printer->Indent(); - - printer->Print("int result = 17;\n"); - printer->Print("result = 31 * result + getClass().getName().hashCode();\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - field_generators_.get(field).GenerateHashCodeCode(printer); - } - - if (params_.store_unknown_fields()) { - printer->Print( - "result = 31 * result + \n" - " (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : \n" - " unknownFieldData.hashCode());\n"); - } - - printer->Print("return result;\n"); - - printer->Outdent(); - printer->Print("}\n"); -} - -// =================================================================== - -} // namespace javanano -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/javanano/javanano_message.h b/src/google/protobuf/compiler/javanano/javanano_message.h deleted file mode 100644 index 281ec64fdda85..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_message.h +++ /dev/null @@ -1,97 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__ - -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { - namespace io { - class Printer; // printer.h - } -} - -namespace protobuf { -namespace compiler { -namespace javanano { - -class MessageGenerator { - public: - explicit MessageGenerator(const Descriptor* descriptor, const Params& params); - ~MessageGenerator(); - - // All static variables have to be declared at the top-level of the file - // so that we can control initialization order, which is important for - // DescriptorProto bootstrapping to work. - void GenerateStaticVariables(io::Printer* printer); - - // Output code which initializes the static variables generated by - // GenerateStaticVariables(). - void GenerateStaticVariableInitializers(io::Printer* printer); - - // Generate the class itself. - void Generate(io::Printer* printer); - - private: - void GenerateMessageSerializationMethods(io::Printer* printer); - void GenerateMergeFromMethods(io::Printer* printer); - void GenerateParseFromMethods(io::Printer* printer); - void GenerateSerializeOneField(io::Printer* printer, - const FieldDescriptor* field); - - void GenerateClear(io::Printer* printer); - void GenerateFieldInitializers(io::Printer* printer); - void GenerateEquals(io::Printer* printer); - void GenerateHashCode(io::Printer* printer); - void GenerateClone(io::Printer* printer); - - const Params& params_; - const Descriptor* descriptor_; - FieldGeneratorMap field_generators_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); -}; - -} // namespace javanano -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_H__ diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc deleted file mode 100644 index 2ed8a3aa66e70..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc +++ /dev/null @@ -1,363 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include -#include - -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -using internal::WireFormat; -using internal::WireFormatLite; - -namespace { - -// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of -// repeat code between this and the other field types. -void SetMessageVariables(const Params& params, - const FieldDescriptor* descriptor, std::map* variables) { - (*variables)["name"] = - RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); - (*variables)["capitalized_name"] = - RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["type"] = ClassName(params, descriptor->message_type()); - (*variables)["group_or_message"] = - (descriptor->type() == FieldDescriptor::TYPE_GROUP) ? - "Group" : "Message"; - (*variables)["message_name"] = descriptor->containing_type()->name(); - //(*variables)["message_type"] = descriptor->message_type()->name(); - (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); -} - -} // namespace - -// =================================================================== - -MessageFieldGenerator:: -MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params) - : FieldGenerator(params), descriptor_(descriptor) { - SetMessageVariables(params, descriptor, &variables_); -} - -MessageFieldGenerator::~MessageFieldGenerator() {} - -void MessageFieldGenerator:: -GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { - printer->Print(variables_, - "public $type$ $name$;\n"); -} - -void MessageFieldGenerator:: -GenerateClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$ = null;\n"); -} - -void MessageFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ == null) {\n" - " this.$name$ = new $type$();\n" - "}\n"); - - if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { - printer->Print(variables_, - "input.readGroup(this.$name$, $number$);\n"); - } else { - printer->Print(variables_, - "input.readMessage(this.$name$);\n"); - } -} - -void MessageFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null) {\n" - " output.write$group_or_message$($number$, this.$name$);\n" - "}\n"); -} - -void MessageFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null) {\n" - " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .compute$group_or_message$Size($number$, this.$name$);\n" - "}\n"); -} - -void MessageFieldGenerator:: -GenerateFixClonedCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null) {\n" - " cloned.$name$ = this.$name$.clone();\n" - "}\n"); -} - -void MessageFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ == null) { \n" - " if (other.$name$ != null) {\n" - " return false;\n" - " }\n" - "} else {\n" - " if (!this.$name$.equals(other.$name$)) {\n" - " return false;\n" - " }\n" - "}\n"); -} - -void MessageFieldGenerator:: -GenerateHashCodeCode(io::Printer* printer) const { - printer->Print(variables_, - "result = 31 * result +\n" - " (this.$name$ == null ? 0 : this.$name$.hashCode());\n"); -} -// =================================================================== - -MessageOneofFieldGenerator::MessageOneofFieldGenerator( - const FieldDescriptor* descriptor, const Params& params) - : FieldGenerator(params), descriptor_(descriptor) { - SetMessageVariables(params, descriptor, &variables_); - SetCommonOneofVariables(descriptor, &variables_); -} - -MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} - -void MessageOneofFieldGenerator:: -GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { - printer->Print(variables_, - "public boolean has$capitalized_name$() {\n" - " return $has_oneof_case$;\n" - "}\n" - "public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case$) {\n" - " return ($type$) this.$oneof_name$_;\n" - " }\n" - " return null;\n" - "}\n" - "public $message_name$ set$capitalized_name$($type$ value) {\n" - " if (value == null) { throw new java.lang.NullPointerException(); }\n" - " $set_oneof_case$;\n" - " this.$oneof_name$_ = value;\n" - " return this;\n" - "}\n"); -} - -void MessageOneofFieldGenerator:: -GenerateClearCode(io::Printer* printer) const { - // No clear method for oneof fields. -} - -void MessageOneofFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!($has_oneof_case$)) {\n" - " this.$oneof_name$_ = new $type$();\n" - "}\n" - "input.readMessage(\n" - " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n" - "$set_oneof_case$;\n"); -} - -void MessageOneofFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case$) {\n" - " output.writeMessage($number$,\n" - " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n" - "}\n"); -} - -void MessageOneofFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case$) {\n" - " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .computeMessageSize($number$,\n" - " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n" - "}\n"); -} - -void MessageOneofFieldGenerator:: -GenerateFixClonedCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$oneof_name$ != null) {\n" - " cloned.$oneof_name$ = this.$oneof_name$.clone();\n" - "}\n"); -} - -void MessageOneofFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - GenerateOneofFieldEquals(descriptor_, variables_, printer); -} - -void MessageOneofFieldGenerator:: -GenerateHashCodeCode(io::Printer* printer) const { - GenerateOneofFieldHashCode(descriptor_, variables_, printer); -} - -// =================================================================== - -RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( - const FieldDescriptor* descriptor, const Params& params) - : FieldGenerator(params), descriptor_(descriptor) { - SetMessageVariables(params, descriptor, &variables_); -} - -RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} - -void RepeatedMessageFieldGenerator:: -GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { - printer->Print(variables_, - "public $type$[] $name$;\n"); -} - -void RepeatedMessageFieldGenerator:: -GenerateClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$ = $type$.emptyArray();\n"); -} - -void RepeatedMessageFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - // First, figure out the length of the array, then parse. - printer->Print(variables_, - "int arrayLength = com.google.protobuf.nano.WireFormatNano\n" - " .getRepeatedFieldArrayLength(input, $tag$);\n" - "int i = this.$name$ == null ? 0 : this.$name$.length;\n" - "$type$[] newArray =\n" - " new $type$[i + arrayLength];\n" - "if (i != 0) {\n" - " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" - "}\n" - "for (; i < newArray.length - 1; i++) {\n" - " newArray[i] = new $type$();\n"); - - if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { - printer->Print(variables_, - " input.readGroup(newArray[i], $number$);\n"); - } else { - printer->Print(variables_, - " input.readMessage(newArray[i]);\n"); - } - - printer->Print(variables_, - " input.readTag();\n" - "}\n" - "// Last one without readTag.\n" - "newArray[i] = new $type$();\n"); - - if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { - printer->Print(variables_, - "input.readGroup(newArray[i], $number$);\n"); - } else { - printer->Print(variables_, - "input.readMessage(newArray[i]);\n"); - } - - printer->Print(variables_, - "this.$name$ = newArray;\n"); -} - -void RepeatedMessageFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null && this.$name$.length > 0) {\n" - " for (int i = 0; i < this.$name$.length; i++) {\n" - " $type$ element = this.$name$[i];\n" - " if (element != null) {\n" - " output.write$group_or_message$($number$, element);\n" - " }\n" - " }\n" - "}\n"); -} - -void RepeatedMessageFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null && this.$name$.length > 0) {\n" - " for (int i = 0; i < this.$name$.length; i++) {\n" - " $type$ element = this.$name$[i];\n" - " if (element != null) {\n" - " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .compute$group_or_message$Size($number$, element);\n" - " }\n" - " }\n" - "}\n"); -} - -void RepeatedMessageFieldGenerator:: -GenerateFixClonedCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null && this.$name$.length > 0) {\n" - " cloned.$name$ = new $type$[this.$name$.length];\n" - " for (int i = 0; i < this.$name$.length; i++) {\n" - " if (this.$name$[i] != null) {\n" - " cloned.$name$[i] = this.$name$[i].clone();\n" - " }\n" - " }\n" - "}\n"); -} - -void RepeatedMessageFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!com.google.protobuf.nano.InternalNano.equals(\n" - " this.$name$, other.$name$)) {\n" - " return false;\n" - "}\n"); -} - -void RepeatedMessageFieldGenerator:: -GenerateHashCodeCode(io::Printer* printer) const { - printer->Print(variables_, - "result = 31 * result\n" - " + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n"); -} - -} // namespace javanano -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h deleted file mode 100644 index 0ae8879ba23eb..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.h +++ /dev/null @@ -1,121 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_FIELD_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_FIELD_H__ - -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -class MessageFieldGenerator : public FieldGenerator { - public: - explicit MessageFieldGenerator( - const FieldDescriptor* descriptor, const Params& params); - ~MessageFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - void GenerateMembers(io::Printer* printer, bool lazy_init) const; - void GenerateClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCodeCode(io::Printer* printer) const; - void GenerateFixClonedCode(io::Printer* printer) const; - - private: - const FieldDescriptor* descriptor_; - std::map variables_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); -}; - -class MessageOneofFieldGenerator : public FieldGenerator { - public: - explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor, - const Params& params); - ~MessageOneofFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - void GenerateMembers(io::Printer* printer, bool lazy_init) const; - void GenerateClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCodeCode(io::Printer* printer) const; - void GenerateFixClonedCode(io::Printer* printer) const; - - private: - const FieldDescriptor* descriptor_; - std::map variables_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator); -}; - -class RepeatedMessageFieldGenerator : public FieldGenerator { - public: - explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, - const Params& params); - ~RepeatedMessageFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - void GenerateMembers(io::Printer* printer, bool lazy_init) const; - void GenerateClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCodeCode(io::Printer* printer) const; - void GenerateFixClonedCode(io::Printer* printer) const; - - private: - const FieldDescriptor* descriptor_; - std::map variables_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); -}; - -} // namespace javanano -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MESSAGE_FIELD_H__ diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h deleted file mode 100644 index 3594767d6767c..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_params.h +++ /dev/null @@ -1,258 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2010 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: wink@google.com (Wink Saville) - -#ifndef PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_ -#define PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_ - -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -enum eMultipleFiles { JAVANANO_MUL_UNSET, JAVANANO_MUL_FALSE, JAVANANO_MUL_TRUE }; - -// Parameters for used by the generators -class Params { - public: - typedef std::map NameMap; - typedef std::set NameSet; - private: - string empty_; - string base_name_; - eMultipleFiles override_java_multiple_files_; - bool store_unknown_fields_; - NameMap java_packages_; - NameMap java_outer_classnames_; - NameSet java_multiple_files_; - bool generate_has_; - bool java_enum_style_; - bool optional_field_accessors_; - bool use_reference_types_for_primitives_; - bool generate_equals_; - bool ignore_services_; - bool parcelable_messages_; - bool reftypes_primitive_enums_; - bool generate_clear_; - bool generate_clone_; - bool generate_intdefs_; - - public: - Params(const string & base_name) : - empty_(""), - base_name_(base_name), - override_java_multiple_files_(JAVANANO_MUL_UNSET), - store_unknown_fields_(false), - generate_has_(false), - java_enum_style_(false), - optional_field_accessors_(false), - use_reference_types_for_primitives_(false), - generate_equals_(false), - ignore_services_(false), - parcelable_messages_(false), - reftypes_primitive_enums_(false), - generate_clear_(true), - generate_clone_(false), - generate_intdefs_(false) { - } - - const string& base_name() const { - return base_name_; - } - - bool has_java_package(const string& file_name) const { - return java_packages_.find(file_name) - != java_packages_.end(); - } - void set_java_package(const string& file_name, - const string& java_package) { - java_packages_[file_name] = java_package; - } - const string& java_package(const string& file_name) const { - NameMap::const_iterator itr; - - itr = java_packages_.find(file_name); - if (itr == java_packages_.end()) { - return empty_; - } else { - return itr->second; - } - } - const NameMap& java_packages() { - return java_packages_; - } - - bool has_java_outer_classname(const string& file_name) const { - return java_outer_classnames_.find(file_name) - != java_outer_classnames_.end(); - } - void set_java_outer_classname(const string& file_name, - const string& java_outer_classname) { - java_outer_classnames_[file_name] = java_outer_classname; - } - const string& java_outer_classname(const string& file_name) const { - NameMap::const_iterator itr; - - itr = java_outer_classnames_.find(file_name); - if (itr == java_outer_classnames_.end()) { - return empty_; - } else { - return itr->second; - } - } - const NameMap& java_outer_classnames() { - return java_outer_classnames_; - } - - void set_override_java_multiple_files(bool java_multiple_files) { - if (java_multiple_files) { - override_java_multiple_files_ = JAVANANO_MUL_TRUE; - } else { - override_java_multiple_files_ = JAVANANO_MUL_FALSE; - } - } - void clear_override_java_multiple_files() { - override_java_multiple_files_ = JAVANANO_MUL_UNSET; - } - - void set_java_multiple_files(const string& file_name, bool value) { - if (value) { - java_multiple_files_.insert(file_name); - } else { - java_multiple_files_.erase(file_name); - } - } - bool java_multiple_files(const string& file_name) const { - switch (override_java_multiple_files_) { - case JAVANANO_MUL_FALSE: - return false; - case JAVANANO_MUL_TRUE: - return true; - default: - return java_multiple_files_.find(file_name) - != java_multiple_files_.end(); - } - } - - void set_store_unknown_fields(bool value) { - store_unknown_fields_ = value; - } - bool store_unknown_fields() const { - return store_unknown_fields_; - } - - void set_generate_has(bool value) { - generate_has_ = value; - } - bool generate_has() const { - return generate_has_; - } - - void set_java_enum_style(bool value) { - java_enum_style_ = value; - } - bool java_enum_style() const { - return java_enum_style_; - } - - void set_optional_field_accessors(bool value) { - optional_field_accessors_ = value; - } - bool optional_field_accessors() const { - return optional_field_accessors_; - } - - void set_use_reference_types_for_primitives(bool value) { - use_reference_types_for_primitives_ = value; - } - bool use_reference_types_for_primitives() const { - return use_reference_types_for_primitives_; - } - - void set_generate_equals(bool value) { - generate_equals_ = value; - } - bool generate_equals() const { - return generate_equals_; - } - - void set_ignore_services(bool value) { - ignore_services_ = value; - } - bool ignore_services() const { - return ignore_services_; - } - - void set_parcelable_messages(bool value) { - parcelable_messages_ = value; - } - bool parcelable_messages() const { - return parcelable_messages_; - } - - void set_reftypes_primitive_enums(bool value) { - reftypes_primitive_enums_ = value; - } - bool reftypes_primitive_enums() const { - return reftypes_primitive_enums_; - } - - void set_generate_clear(bool value) { - generate_clear_ = value; - } - bool generate_clear() const { - return generate_clear_; - } - - void set_generate_clone(bool value) { - generate_clone_ = value; - } - bool generate_clone() const { - return generate_clone_; - } - - void set_generate_intdefs(bool value) { - generate_intdefs_ = value; - } - bool generate_intdefs() const { - return generate_intdefs_; - } -}; - -} // namespace javanano -} // namespace compiler -} // namespace protobuf -} // namespace google -#endif // PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_ diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc deleted file mode 100644 index 66a0ff057ce87..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc +++ /dev/null @@ -1,968 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -using internal::WireFormat; -using internal::WireFormatLite; - -namespace { - -bool IsReferenceType(JavaType type) { - switch (type) { - case JAVATYPE_INT : return false; - case JAVATYPE_LONG : return false; - case JAVATYPE_FLOAT : return false; - case JAVATYPE_DOUBLE : return false; - case JAVATYPE_BOOLEAN: return false; - case JAVATYPE_STRING : return true; - case JAVATYPE_BYTES : return true; - case JAVATYPE_ENUM : return false; - case JAVATYPE_MESSAGE: return true; - - // No default because we want the compiler to complain if any new - // JavaTypes are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return false; -} - -bool IsArrayType(JavaType type) { - switch (type) { - case JAVATYPE_INT : return false; - case JAVATYPE_LONG : return false; - case JAVATYPE_FLOAT : return false; - case JAVATYPE_DOUBLE : return false; - case JAVATYPE_BOOLEAN: return false; - case JAVATYPE_STRING : return false; - case JAVATYPE_BYTES : return true; - case JAVATYPE_ENUM : return false; - case JAVATYPE_MESSAGE: return false; - - // No default because we want the compiler to complain if any new - // JavaTypes are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return false; -} - -const char* GetCapitalizedType(const FieldDescriptor* field) { - switch (field->type()) { - case FieldDescriptor::TYPE_INT32 : return "Int32" ; - case FieldDescriptor::TYPE_UINT32 : return "UInt32" ; - case FieldDescriptor::TYPE_SINT32 : return "SInt32" ; - case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ; - case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; - case FieldDescriptor::TYPE_INT64 : return "Int64" ; - case FieldDescriptor::TYPE_UINT64 : return "UInt64" ; - case FieldDescriptor::TYPE_SINT64 : return "SInt64" ; - case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ; - case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; - case FieldDescriptor::TYPE_FLOAT : return "Float" ; - case FieldDescriptor::TYPE_DOUBLE : return "Double" ; - case FieldDescriptor::TYPE_BOOL : return "Bool" ; - case FieldDescriptor::TYPE_STRING : return "String" ; - case FieldDescriptor::TYPE_BYTES : return "Bytes" ; - case FieldDescriptor::TYPE_ENUM : return "Enum" ; - case FieldDescriptor::TYPE_GROUP : return "Group" ; - case FieldDescriptor::TYPE_MESSAGE : return "Message" ; - - // No default because we want the compiler to complain if any new - // types are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; -} - -// For encodings with fixed sizes, returns that size in bytes. Otherwise -// returns -1. -int FixedSize(FieldDescriptor::Type type) { - switch (type) { - case FieldDescriptor::TYPE_INT32 : return -1; - case FieldDescriptor::TYPE_INT64 : return -1; - case FieldDescriptor::TYPE_UINT32 : return -1; - case FieldDescriptor::TYPE_UINT64 : return -1; - case FieldDescriptor::TYPE_SINT32 : return -1; - case FieldDescriptor::TYPE_SINT64 : return -1; - case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; - case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; - case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; - case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; - case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; - case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; - - case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; - case FieldDescriptor::TYPE_ENUM : return -1; - - case FieldDescriptor::TYPE_STRING : return -1; - case FieldDescriptor::TYPE_BYTES : return -1; - case FieldDescriptor::TYPE_GROUP : return -1; - case FieldDescriptor::TYPE_MESSAGE : return -1; - - // No default because we want the compiler to complain if any new - // types are added. - } - GOOGLE_LOG(FATAL) << "Can't get here."; - return -1; -} - -bool AllAscii(const string& text) { - for (int i = 0; i < text.size(); i++) { - if ((text[i] & 0x80) != 0) { - return false; - } - } - return true; -} - - -void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params, - std::map* variables) { - (*variables)["name"] = - RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); - (*variables)["capitalized_name"] = - RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); - (*variables)["number"] = SimpleItoa(descriptor->number()); - if (params.use_reference_types_for_primitives() - && !descriptor->is_repeated()) { - (*variables)["type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); - } else { - (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); - } - // Deals with defaults. For C++-string types (string and bytes), - // we might need to have the generated code do the unicode decoding - // (see comments in InternalNano.java for gory details.). We would - // like to do this once into a static field and re-use that from - // then on. - if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING && - !descriptor->default_value_string().empty() && - !params.use_reference_types_for_primitives()) { - if (descriptor->type() == FieldDescriptor::TYPE_BYTES) { - (*variables)["default"] = DefaultValue(params, descriptor); - (*variables)["default_constant"] = FieldDefaultConstantName(descriptor); - (*variables)["default_constant_value"] = strings::Substitute( - "com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")", - CEscape(descriptor->default_value_string())); - (*variables)["default_copy_if_needed"] = - (*variables)["default"] + ".clone()"; - } else if (AllAscii(descriptor->default_value_string())) { - // All chars are ASCII. In this case directly referencing a - // CEscape()'d string literal works fine. - (*variables)["default"] = - "\"" + CEscape(descriptor->default_value_string()) + "\""; - (*variables)["default_copy_if_needed"] = (*variables)["default"]; - } else { - // Strings where some chars are non-ASCII. We need to save the - // default value. - (*variables)["default"] = DefaultValue(params, descriptor); - (*variables)["default_constant"] = FieldDefaultConstantName(descriptor); - (*variables)["default_constant_value"] = strings::Substitute( - "com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")", - CEscape(descriptor->default_value_string())); - (*variables)["default_copy_if_needed"] = (*variables)["default"]; - } - } else { - // Non-string, non-bytes field. Defaults are literals. - (*variables)["default"] = DefaultValue(params, descriptor); - (*variables)["default_copy_if_needed"] = (*variables)["default"]; - } - (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); - (*variables)["capitalized_type"] = GetCapitalizedType(descriptor); - (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); - (*variables)["tag_size"] = SimpleItoa( - WireFormat::TagSize(descriptor->number(), descriptor->type())); - (*variables)["non_packed_tag"] = SimpleItoa( - internal::WireFormatLite::MakeTag(descriptor->number(), - internal::WireFormat::WireTypeForFieldType(descriptor->type()))); - int fixed_size = FixedSize(descriptor->type()); - if (fixed_size != -1) { - (*variables)["fixed_size"] = SimpleItoa(fixed_size); - } - (*variables)["message_name"] = descriptor->containing_type()->name(); - (*variables)["empty_array_name"] = EmptyArrayName(params, descriptor); -} -} // namespace - -// =================================================================== - -PrimitiveFieldGenerator:: -PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) - : FieldGenerator(params), descriptor_(descriptor) { - SetPrimitiveVariables(descriptor, params, &variables_); -} - -PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} - -bool PrimitiveFieldGenerator::SavedDefaultNeeded() const { - return variables_.find("default_constant") != variables_.end(); -} - -void PrimitiveFieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const { - if (variables_.find("default_constant") != variables_.end()) { - printer->Print(variables_, - "$default_constant$ = $default_constant_value$;\n"); - } -} - -void PrimitiveFieldGenerator:: -GenerateMembers(io::Printer* printer, bool lazy_init) const { - if (variables_.find("default_constant") != variables_.end()) { - // Those primitive types that need a saved default. - if (lazy_init) { - printer->Print(variables_, - "private static $type$ $default_constant$;\n"); - } else { - printer->Print(variables_, - "private static final $type$ $default_constant$ =\n" - " $default_constant_value$;\n"); - } - } - - printer->Print(variables_, - "public $type$ $name$;\n"); - - if (params_.generate_has()) { - printer->Print(variables_, - "public boolean has$capitalized_name$;\n"); - } -} - -void PrimitiveFieldGenerator:: -GenerateClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$ = $default_copy_if_needed$;\n"); - - if (params_.generate_has()) { - printer->Print(variables_, - "has$capitalized_name$ = false;\n"); - } -} - -void PrimitiveFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "this.$name$ = input.read$capitalized_type$();\n"); - - if (params_.generate_has()) { - printer->Print(variables_, - "has$capitalized_name$ = true;\n"); - } -} - -void PrimitiveFieldGenerator:: -GenerateSerializationConditional(io::Printer* printer) const { - if (params_.use_reference_types_for_primitives()) { - // For reference type mode, serialize based on equality - // to null. - printer->Print(variables_, - "if (this.$name$ != null) {\n"); - return; - } - if (params_.generate_has()) { - printer->Print(variables_, - "if (has$capitalized_name$ || "); - } else { - printer->Print(variables_, - "if ("); - } - JavaType java_type = GetJavaType(descriptor_); - if (IsArrayType(java_type)) { - printer->Print(variables_, - "!java.util.Arrays.equals(this.$name$, $default$)) {\n"); - } else if (IsReferenceType(java_type)) { - printer->Print(variables_, - "!this.$name$.equals($default$)) {\n"); - } else if (java_type == JAVATYPE_FLOAT) { - printer->Print(variables_, - "java.lang.Float.floatToIntBits(this.$name$)\n" - " != java.lang.Float.floatToIntBits($default$)) {\n"); - } else if (java_type == JAVATYPE_DOUBLE) { - printer->Print(variables_, - "java.lang.Double.doubleToLongBits(this.$name$)\n" - " != java.lang.Double.doubleToLongBits($default$)) {\n"); - } else { - printer->Print(variables_, - "this.$name$ != $default$) {\n"); - } -} - -void PrimitiveFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - if (descriptor_->is_required() && !params_.generate_has()) { - // Always serialize a required field if we don't have the 'has' signal. - printer->Print(variables_, - "output.write$capitalized_type$($number$, this.$name$);\n"); - } else { - GenerateSerializationConditional(printer); - printer->Print(variables_, - " output.write$capitalized_type$($number$, this.$name$);\n" - "}\n"); - } -} - -void PrimitiveFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - if (descriptor_->is_required() && !params_.generate_has()) { - printer->Print(variables_, - "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .compute$capitalized_type$Size($number$, this.$name$);\n"); - } else { - GenerateSerializationConditional(printer); - printer->Print(variables_, - " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .compute$capitalized_type$Size($number$, this.$name$);\n" - "}\n"); - } -} - -void RepeatedPrimitiveFieldGenerator:: -GenerateFixClonedCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null && this.$name$.length > 0) {\n" - " cloned.$name$ = this.$name$.clone();\n" - "}\n"); -} - -void PrimitiveFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - // We define equality as serialized form equality. If generate_has(), - // then if the field value equals the default value in both messages, - // but one's 'has' field is set and the other's is not, the serialized - // forms are different and we should return false. - JavaType java_type = GetJavaType(descriptor_); - if (java_type == JAVATYPE_BYTES) { - printer->Print(variables_, - "if (!java.util.Arrays.equals(this.$name$, other.$name$)"); - if (params_.generate_has()) { - printer->Print(variables_, - "\n" - " || (java.util.Arrays.equals(this.$name$, $default$)\n" - " && this.has$capitalized_name$ != other.has$capitalized_name$)"); - } - printer->Print(") {\n" - " return false;\n" - "}\n"); - } else if (java_type == JAVATYPE_STRING - || params_.use_reference_types_for_primitives()) { - printer->Print(variables_, - "if (this.$name$ == null) {\n" - " if (other.$name$ != null) {\n" - " return false;\n" - " }\n" - "} else if (!this.$name$.equals(other.$name$)"); - if (params_.generate_has()) { - printer->Print(variables_, - "\n" - " || (this.$name$.equals($default$)\n" - " && this.has$capitalized_name$ != other.has$capitalized_name$)"); - } - printer->Print(") {\n" - " return false;\n" - "}\n"); - } else if (java_type == JAVATYPE_FLOAT) { - printer->Print(variables_, - "{\n" - " int bits = java.lang.Float.floatToIntBits(this.$name$);\n" - " if (bits != java.lang.Float.floatToIntBits(other.$name$)"); - if (params_.generate_has()) { - printer->Print(variables_, - "\n" - " || (bits == java.lang.Float.floatToIntBits($default$)\n" - " && this.has$capitalized_name$ != other.has$capitalized_name$)"); - } - printer->Print(") {\n" - " return false;\n" - " }\n" - "}\n"); - } else if (java_type == JAVATYPE_DOUBLE) { - printer->Print(variables_, - "{\n" - " long bits = java.lang.Double.doubleToLongBits(this.$name$);\n" - " if (bits != java.lang.Double.doubleToLongBits(other.$name$)"); - if (params_.generate_has()) { - printer->Print(variables_, - "\n" - " || (bits == java.lang.Double.doubleToLongBits($default$)\n" - " && this.has$capitalized_name$ != other.has$capitalized_name$)"); - } - printer->Print(") {\n" - " return false;\n" - " }\n" - "}\n"); - } else { - printer->Print(variables_, - "if (this.$name$ != other.$name$"); - if (params_.generate_has()) { - printer->Print(variables_, - "\n" - " || (this.$name$ == $default$\n" - " && this.has$capitalized_name$ != other.has$capitalized_name$)"); - } - printer->Print(") {\n" - " return false;\n" - "}\n"); - } -} - -void PrimitiveFieldGenerator:: -GenerateHashCodeCode(io::Printer* printer) const { - JavaType java_type = GetJavaType(descriptor_); - if (java_type == JAVATYPE_BYTES) { - printer->Print(variables_, - "result = 31 * result + java.util.Arrays.hashCode(this.$name$);\n"); - } else if (java_type == JAVATYPE_STRING - || params_.use_reference_types_for_primitives()) { - printer->Print(variables_, - "result = 31 * result\n" - " + (this.$name$ == null ? 0 : this.$name$.hashCode());\n"); - } else { - switch (java_type) { - // For all Java primitive types below, the hash codes match the - // results of BoxedType.valueOf(primitiveValue).hashCode(). - case JAVATYPE_INT: - printer->Print(variables_, - "result = 31 * result + this.$name$;\n"); - break; - case JAVATYPE_LONG: - printer->Print(variables_, - "result = 31 * result\n" - " + (int) (this.$name$ ^ (this.$name$ >>> 32));\n"); - break; - case JAVATYPE_FLOAT: - printer->Print(variables_, - "result = 31 * result\n" - " + java.lang.Float.floatToIntBits(this.$name$);\n"); - break; - case JAVATYPE_DOUBLE: - printer->Print(variables_, - "{\n" - " long v = java.lang.Double.doubleToLongBits(this.$name$);\n" - " result = 31 * result + (int) (v ^ (v >>> 32));\n" - "}\n"); - break; - case JAVATYPE_BOOLEAN: - printer->Print(variables_, - "result = 31 * result + (this.$name$ ? 1231 : 1237);\n"); - break; - default: - GOOGLE_LOG(ERROR) << "unknown java type for primitive field"; - break; - } - } -} - -// =================================================================== - -AccessorPrimitiveFieldGenerator:: -AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor, - const Params& params, int has_bit_index) - : FieldGenerator(params), descriptor_(descriptor) { - SetPrimitiveVariables(descriptor, params, &variables_); - SetBitOperationVariables("has", has_bit_index, &variables_); -} - -AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {} - -bool AccessorPrimitiveFieldGenerator::SavedDefaultNeeded() const { - return variables_.find("default_constant") != variables_.end(); -} - -void AccessorPrimitiveFieldGenerator:: -GenerateInitSavedDefaultCode(io::Printer* printer) const { - if (variables_.find("default_constant") != variables_.end()) { - printer->Print(variables_, - "$default_constant$ = $default_constant_value$;\n"); - } -} - -void AccessorPrimitiveFieldGenerator:: -GenerateMembers(io::Printer* printer, bool lazy_init) const { - if (variables_.find("default_constant") != variables_.end()) { - // Those primitive types that need a saved default. - if (lazy_init) { - printer->Print(variables_, - "private static $type$ $default_constant$;\n"); - } else { - printer->Print(variables_, - "private static final $type$ $default_constant$ =\n" - " $default_constant_value$;\n"); - } - } - printer->Print(variables_, - "private $type$ $name$_;\n" - "public $type$ get$capitalized_name$() {\n" - " return $name$_;\n" - "}\n" - "public $message_name$ set$capitalized_name$($type$ value) {\n"); - if (IsReferenceType(GetJavaType(descriptor_))) { - printer->Print(variables_, - " if (value == null) {\n" - " throw new java.lang.NullPointerException();\n" - " }\n"); - } - printer->Print(variables_, - " $name$_ = value;\n" - " $set_has$;\n" - " return this;\n" - "}\n" - "public boolean has$capitalized_name$() {\n" - " return $get_has$;\n" - "}\n" - "public $message_name$ clear$capitalized_name$() {\n" - " $name$_ = $default_copy_if_needed$;\n" - " $clear_has$;\n" - " return this;\n" - "}\n"); -} - -void AccessorPrimitiveFieldGenerator:: -GenerateClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = $default_copy_if_needed$;\n"); -} - -void AccessorPrimitiveFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = input.read$capitalized_type$();\n" - "$set_has$;\n"); -} - -void AccessorPrimitiveFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_has$) {\n" - " output.write$capitalized_type$($number$, $name$_);\n" - "}\n"); -} - -void AccessorPrimitiveFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_has$) {\n" - " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .compute$capitalized_type$Size($number$, $name$_);\n" - "}\n"); -} - -void AccessorPrimitiveFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - switch (GetJavaType(descriptor_)) { - // For all Java primitive types below, the equality checks match the - // results of BoxedType.valueOf(primitiveValue).equals(otherValue). - case JAVATYPE_FLOAT: - printer->Print(variables_, - "if ($different_has$\n" - " || java.lang.Float.floatToIntBits($name$_)\n" - " != java.lang.Float.floatToIntBits(other.$name$_)) {\n" - " return false;\n" - "}\n"); - break; - case JAVATYPE_DOUBLE: - printer->Print(variables_, - "if ($different_has$\n" - " || java.lang.Double.doubleToLongBits($name$_)\n" - " != java.lang.Double.doubleToLongBits(other.$name$_)) {\n" - " return false;\n" - "}\n"); - break; - case JAVATYPE_INT: - case JAVATYPE_LONG: - case JAVATYPE_BOOLEAN: - printer->Print(variables_, - "if ($different_has$\n" - " || $name$_ != other.$name$_) {\n" - " return false;\n" - "}\n"); - break; - case JAVATYPE_STRING: - // Accessor style would guarantee $name$_ non-null - printer->Print(variables_, - "if ($different_has$\n" - " || !$name$_.equals(other.$name$_)) {\n" - " return false;\n" - "}\n"); - break; - case JAVATYPE_BYTES: - // Accessor style would guarantee $name$_ non-null - printer->Print(variables_, - "if ($different_has$\n" - " || !java.util.Arrays.equals($name$_, other.$name$_)) {\n" - " return false;\n" - "}\n"); - break; - default: - GOOGLE_LOG(ERROR) << "unknown java type for primitive field"; - break; - } -} - -void AccessorPrimitiveFieldGenerator:: -GenerateHashCodeCode(io::Printer* printer) const { - switch (GetJavaType(descriptor_)) { - // For all Java primitive types below, the hash codes match the - // results of BoxedType.valueOf(primitiveValue).hashCode(). - case JAVATYPE_INT: - printer->Print(variables_, - "result = 31 * result + $name$_;\n"); - break; - case JAVATYPE_LONG: - printer->Print(variables_, - "result = 31 * result + (int) ($name$_ ^ ($name$_ >>> 32));\n"); - break; - case JAVATYPE_FLOAT: - printer->Print(variables_, - "result = 31 * result +\n" - " java.lang.Float.floatToIntBits($name$_);\n"); - break; - case JAVATYPE_DOUBLE: - printer->Print(variables_, - "{\n" - " long v = java.lang.Double.doubleToLongBits($name$_);\n" - " result = 31 * result + (int) (v ^ (v >>> 32));\n" - "}\n"); - break; - case JAVATYPE_BOOLEAN: - printer->Print(variables_, - "result = 31 * result + ($name$_ ? 1231 : 1237);\n"); - break; - case JAVATYPE_STRING: - // Accessor style would guarantee $name$_ non-null - printer->Print(variables_, - "result = 31 * result + $name$_.hashCode();\n"); - break; - case JAVATYPE_BYTES: - // Accessor style would guarantee $name$_ non-null - printer->Print(variables_, - "result = 31 * result + java.util.Arrays.hashCode($name$_);\n"); - break; - default: - GOOGLE_LOG(ERROR) << "unknown java type for primitive field"; - break; - } -} - -// =================================================================== - -PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator( - const FieldDescriptor* descriptor, const Params& params) - : FieldGenerator(params), descriptor_(descriptor) { - SetPrimitiveVariables(descriptor, params, &variables_); - SetCommonOneofVariables(descriptor, &variables_); -} - -PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {} - -void PrimitiveOneofFieldGenerator::GenerateMembers( - io::Printer* printer, bool /*unused lazy_init*/) const { - printer->Print(variables_, - "public boolean has$capitalized_name$() {\n" - " return $has_oneof_case$;\n" - "}\n" - "public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case$) {\n" - " return ($type$) ($boxed_type$) this.$oneof_name$_;\n" - " }\n" - " return $default$;\n" - "}\n" - "public $message_name$ set$capitalized_name$($type$ value) {\n" - " $set_oneof_case$;\n" - " this.$oneof_name$_ = value;\n" - " return this;\n" - "}\n"); -} - -void PrimitiveOneofFieldGenerator::GenerateClearCode( - io::Printer* printer) const { - // No clear method for oneof fields. -} - -void PrimitiveOneofFieldGenerator::GenerateMergingCode( - io::Printer* printer) const { - printer->Print(variables_, - "this.$oneof_name$_ = input.read$capitalized_type$();\n" - "$set_oneof_case$;\n"); -} - -void PrimitiveOneofFieldGenerator::GenerateSerializationCode( - io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case$) {\n" - " output.write$capitalized_type$(\n" - " $number$, ($boxed_type$) this.$oneof_name$_);\n" - "}\n"); -} - -void PrimitiveOneofFieldGenerator::GenerateSerializedSizeCode( - io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case$) {\n" - " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .compute$capitalized_type$Size(\n" - " $number$, ($boxed_type$) this.$oneof_name$_);\n" - "}\n"); -} - -void PrimitiveOneofFieldGenerator::GenerateEqualsCode( - io::Printer* printer) const { - GenerateOneofFieldEquals(descriptor_, variables_, printer); -} - -void PrimitiveOneofFieldGenerator::GenerateHashCodeCode( - io::Printer* printer) const { - GenerateOneofFieldHashCode(descriptor_, variables_, printer); -} - -// =================================================================== - -RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( - const FieldDescriptor* descriptor, const Params& params) - : FieldGenerator(params), descriptor_(descriptor) { - SetPrimitiveVariables(descriptor, params, &variables_); -} - -RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} - -void RepeatedPrimitiveFieldGenerator:: -GenerateMembers(io::Printer* printer, bool /*unused init_defaults*/) const { - printer->Print(variables_, - "public $type$[] $name$;\n"); -} - -void RepeatedPrimitiveFieldGenerator:: -GenerateClearCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$ = $default$;\n"); -} - -void RepeatedPrimitiveFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - // First, figure out the length of the array, then parse. - printer->Print(variables_, - "int arrayLength = com.google.protobuf.nano.WireFormatNano\n" - " .getRepeatedFieldArrayLength(input, $non_packed_tag$);\n" - "int i = this.$name$ == null ? 0 : this.$name$.length;\n"); - - if (GetJavaType(descriptor_) == JAVATYPE_BYTES) { - printer->Print(variables_, - "byte[][] newArray = new byte[i + arrayLength][];\n"); - } else { - printer->Print(variables_, - "$type$[] newArray = new $type$[i + arrayLength];\n"); - } - printer->Print(variables_, - "if (i != 0) {\n" - " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" - "}\n" - "for (; i < newArray.length - 1; i++) {\n" - " newArray[i] = input.read$capitalized_type$();\n" - " input.readTag();\n" - "}\n" - "// Last one without readTag.\n" - "newArray[i] = input.read$capitalized_type$();\n" - "this.$name$ = newArray;\n"); -} - -void RepeatedPrimitiveFieldGenerator:: -GenerateMergingCodeFromPacked(io::Printer* printer) const { - printer->Print( - "int length = input.readRawVarint32();\n" - "int limit = input.pushLimit(length);\n"); - - // If we know the elements will all be of the same size, the arrayLength - // can be calculated much more easily. However, FixedSize() returns 1 for - // repeated bool fields, which are guaranteed to have the fixed size of - // 1 byte per value only if we control the output. On the wire they can - // legally appear as variable-size integers, so we need to use the slow - // way for repeated bool fields. - if (descriptor_->type() == FieldDescriptor::TYPE_BOOL - || FixedSize(descriptor_->type()) == -1) { - printer->Print(variables_, - "// First pass to compute array length.\n" - "int arrayLength = 0;\n" - "int startPos = input.getPosition();\n" - "while (input.getBytesUntilLimit() > 0) {\n" - " input.read$capitalized_type$();\n" - " arrayLength++;\n" - "}\n" - "input.rewindToPosition(startPos);\n"); - } else { - printer->Print(variables_, - "int arrayLength = length / $fixed_size$;\n"); - } - - printer->Print(variables_, - "int i = this.$name$ == null ? 0 : this.$name$.length;\n" - "$type$[] newArray = new $type$[i + arrayLength];\n" - "if (i != 0) {\n" - " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" - "}\n" - "for (; i < newArray.length; i++) {\n" - " newArray[i] = input.read$capitalized_type$();\n" - "}\n" - "this.$name$ = newArray;\n" - "input.popLimit(limit);\n"); -} - -void RepeatedPrimitiveFieldGenerator:: -GenerateRepeatedDataSizeCode(io::Printer* printer) const { - // Creates a variable dataSize and puts the serialized size in there. - // If the element type is a Java reference type, also generates - // dataCount which stores the number of non-null elements in the field. - if (IsReferenceType(GetJavaType(descriptor_))) { - printer->Print(variables_, - "int dataCount = 0;\n" - "int dataSize = 0;\n" - "for (int i = 0; i < this.$name$.length; i++) {\n" - " $type$ element = this.$name$[i];\n" - " if (element != null) {\n" - " dataCount++;\n" - " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .compute$capitalized_type$SizeNoTag(element);\n" - " }\n" - "}\n"); - } else if (FixedSize(descriptor_->type()) == -1) { - printer->Print(variables_, - "int dataSize = 0;\n" - "for (int i = 0; i < this.$name$.length; i++) {\n" - " $type$ element = this.$name$[i];\n" - " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .compute$capitalized_type$SizeNoTag(element);\n" - "}\n"); - } else { - printer->Print(variables_, - "int dataSize = $fixed_size$ * this.$name$.length;\n"); - } -} - -void RepeatedPrimitiveFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null && this.$name$.length > 0) {\n"); - printer->Indent(); - - if (descriptor_->is_packable() && descriptor_->options().packed()) { - GenerateRepeatedDataSizeCode(printer); - printer->Print(variables_, - "output.writeRawVarint32($tag$);\n" - "output.writeRawVarint32(dataSize);\n" - "for (int i = 0; i < this.$name$.length; i++) {\n" - " output.write$capitalized_type$NoTag(this.$name$[i]);\n" - "}\n"); - } else if (IsReferenceType(GetJavaType(descriptor_))) { - printer->Print(variables_, - "for (int i = 0; i < this.$name$.length; i++) {\n" - " $type$ element = this.$name$[i];\n" - " if (element != null) {\n" - " output.write$capitalized_type$($number$, element);\n" - " }\n" - "}\n"); - } else { - printer->Print(variables_, - "for (int i = 0; i < this.$name$.length; i++) {\n" - " output.write$capitalized_type$($number$, this.$name$[i]);\n" - "}\n"); - } - - printer->Outdent(); - printer->Print("}\n"); -} - -void RepeatedPrimitiveFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.$name$ != null && this.$name$.length > 0) {\n"); - printer->Indent(); - - GenerateRepeatedDataSizeCode(printer); - - printer->Print( - "size += dataSize;\n"); - if (descriptor_->is_packable() && descriptor_->options().packed()) { - printer->Print(variables_, - "size += $tag_size$;\n" - "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" - " .computeRawVarint32Size(dataSize);\n"); - } else if (IsReferenceType(GetJavaType(descriptor_))) { - printer->Print(variables_, - "size += $tag_size$ * dataCount;\n"); - } else { - printer->Print(variables_, - "size += $tag_size$ * this.$name$.length;\n"); - } - - printer->Outdent(); - - printer->Print( - "}\n"); -} - -void RepeatedPrimitiveFieldGenerator:: -GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!com.google.protobuf.nano.InternalNano.equals(\n" - " this.$name$, other.$name$)) {\n" - " return false;\n" - "}\n"); -} - -void RepeatedPrimitiveFieldGenerator:: -GenerateHashCodeCode(io::Printer* printer) const { - printer->Print(variables_, - "result = 31 * result\n" - " + com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n"); -} - -} // namespace javanano -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h deleted file mode 100644 index d7d72d578dfdd..0000000000000 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h +++ /dev/null @@ -1,150 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__ - -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace javanano { - -class PrimitiveFieldGenerator : public FieldGenerator { - public: - explicit PrimitiveFieldGenerator( - const FieldDescriptor* descriptor, const Params& params); - ~PrimitiveFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - bool SavedDefaultNeeded() const; - void GenerateInitSavedDefaultCode(io::Printer* printer) const; - void GenerateMembers(io::Printer* printer, bool lazy_init) const; - void GenerateClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCodeCode(io::Printer* printer) const; - - private: - void GenerateSerializationConditional(io::Printer* printer) const; - - const FieldDescriptor* descriptor_; - std::map variables_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); -}; - -class AccessorPrimitiveFieldGenerator : public FieldGenerator { - public: - explicit AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor, - const Params ¶ms, int has_bit_index); - ~AccessorPrimitiveFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - bool SavedDefaultNeeded() const; - void GenerateInitSavedDefaultCode(io::Printer* printer) const; - void GenerateMembers(io::Printer* printer, bool lazy_init) const; - void GenerateClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCodeCode(io::Printer* printer) const; - - private: - const FieldDescriptor* descriptor_; - std::map variables_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorPrimitiveFieldGenerator); -}; - -class PrimitiveOneofFieldGenerator : public FieldGenerator { - public: - explicit PrimitiveOneofFieldGenerator( - const FieldDescriptor* descriptor, const Params& params); - ~PrimitiveOneofFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - void GenerateMembers(io::Printer* printer, bool lazy_init) const; - void GenerateClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCodeCode(io::Printer* printer) const; - - private: - const FieldDescriptor* descriptor_; - std::map variables_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator); -}; - -class RepeatedPrimitiveFieldGenerator : public FieldGenerator { - public: - explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, - const Params& params); - ~RepeatedPrimitiveFieldGenerator(); - - // implements FieldGenerator --------------------------------------- - void GenerateMembers(io::Printer* printer, bool lazy_init) const; - void GenerateClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateMergingCodeFromPacked(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - void GenerateEqualsCode(io::Printer* printer) const; - void GenerateHashCodeCode(io::Printer* printer) const; - void GenerateFixClonedCode(io::Printer* printer) const; - - private: - void GenerateRepeatedDataSizeCode(io::Printer* printer) const; - - const FieldDescriptor* descriptor_; - std::map variables_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); -}; - -} // namespace javanano -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__ diff --git a/src/google/protobuf/compiler/js/embed.cc b/src/google/protobuf/compiler/js/embed.cc deleted file mode 100644 index a725b62eb8c68..0000000000000 --- a/src/google/protobuf/compiler/js/embed.cc +++ /dev/null @@ -1,112 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include -#include -#include -#include -#include - -const char output_file[] = "well_known_types_embed.cc"; - -static bool AsciiIsPrint(unsigned char c) { - return c >= 32 && c < 127; -} - -static char ToDecimalDigit(int num) { - assert(num < 10); - return '0' + num; -} - -static std::string CEscape(const std::string& str) { - std::string dest; - - for (size_t i = 0; i < str.size(); ++i) { - unsigned char ch = str[i]; - switch (ch) { - case '\n': dest += "\\n"; break; - case '\r': dest += "\\r"; break; - case '\t': dest += "\\t"; break; - case '\"': dest += "\\\""; break; - case '\\': dest += "\\\\"; break; - default: - if (AsciiIsPrint(ch)) { - dest += ch; - } else { - dest += "\\"; - dest += ToDecimalDigit(ch / 64); - dest += ToDecimalDigit((ch % 64) / 8); - dest += ToDecimalDigit(ch % 8); - } - break; - } - } - - return dest; -} - -static void AddFile(const char* name, std::basic_ostream* out) { - std::ifstream in(name); - - if (!in.is_open()) { - std::cerr << "Couldn't open input file: " << name << "\n"; - std::exit(EXIT_FAILURE); - } - - // Make canonical name only include the final element. - for (const char *p = name; *p; p++) { - if (*p == '/') { - name = p + 1; - } - } - - *out << "{\"" << CEscape(name) << "\",\n"; - - for (std::string line; std::getline(in, line); ) { - *out << " \"" << CEscape(line) << "\\n\"\n"; - } - - *out << "},\n"; -} - -int main(int argc, char *argv[]) { - std::cout << "#include " - "\"google/protobuf/compiler/js/well_known_types_embed.h\"\n"; - std::cout << "struct FileToc well_known_types_js[] = {\n"; - - for (int i = 1; i < argc; i++) { - AddFile(argv[i], &std::cout); - } - - std::cout << " {NULL, NULL} // Terminate the list.\n"; - std::cout << "};\n"; - - return EXIT_SUCCESS; -} diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc old mode 100755 new mode 100644 index 73d3276297b3a..819622e9ab42a --- a/src/google/protobuf/compiler/js/js_generator.cc +++ b/src/google/protobuf/compiler/js/js_generator.cc @@ -28,30 +28,27 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include #include #include #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include - namespace google { namespace protobuf { namespace compiler { @@ -60,64 +57,18 @@ namespace js { // Sorted list of JavaScript keywords. These cannot be used as names. If they // appear, we prefix them with "pb_". const char* kKeyword[] = { - "abstract", - "boolean", - "break", - "byte", - "case", - "catch", - "char", - "class", - "const", - "continue", - "debugger", - "default", - "delete", - "do", - "double", - "else", - "enum", - "export", - "extends", - "false", - "final", - "finally", - "float", - "for", - "function", - "goto", - "if", - "implements", - "import", - "in", - "instanceof", - "int", - "interface", - "long", - "native", - "new", - "null", - "package", - "private", - "protected", - "public", - "return", - "short", - "static", - "super", - "switch", - "synchronized", - "this", - "throw", - "throws", - "transient", - "try", - "typeof", - "var", - "void", - "volatile", - "while", - "with", + "abstract", "boolean", "break", "byte", "case", + "catch", "char", "class", "const", "continue", + "debugger", "default", "delete", "do", "double", + "else", "enum", "export", "extends", "false", + "final", "finally", "float", "for", "function", + "goto", "if", "implements", "import", "in", + "instanceof", "int", "interface", "long", "native", + "new", "null", "package", "private", "protected", + "public", "return", "short", "static", "super", + "switch", "synchronized", "this", "throw", "throws", + "transient", "try", "typeof", "var", "void", + "volatile", "while", "with", }; static const int kNumKeyword = sizeof(kKeyword) / sizeof(char*); @@ -134,7 +85,7 @@ enum BytesMode { BYTES_U8, // Explicitly coerce to Uint8Array where needed. }; -bool IsReserved(const string& ident) { +bool IsReserved(const std::string& ident) { for (int i = 0; i < kNumKeyword; i++) { if (ident == kKeyword[i]) { return true; @@ -147,24 +98,23 @@ bool StrEndsWith(StringPiece sp, StringPiece x) { return sp.size() >= x.size() && sp.substr(sp.size() - x.size()) == x; } -// Returns a copy of |filename| with any trailing ".protodevel" or ".proto -// suffix stripped. -// TODO(haberman): Unify with copy in compiler/cpp/internal/helpers.cc. -string StripProto(const string& filename) { - const char* suffix = - StrEndsWith(filename, ".protodevel") ? ".protodevel" : ".proto"; - return StripSuffixString(filename, suffix); +std::string GetSnakeFilename(const std::string& filename) { + std::string snake_name = filename; + ReplaceCharacters(&snake_name, "/", '_'); + return snake_name; } // Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript // file foo/bar/baz.js. -string GetJSFilename(const GeneratorOptions& options, const string& filename) { +std::string GetJSFilename(const GeneratorOptions& options, + const std::string& filename) { return StripProto(filename) + options.GetFileNameExtension(); } // Given a filename like foo/bar/baz.proto, returns the root directory // path ../../ -string GetRootPath(const string& from_filename, const string& to_filename) { +std::string GetRootPath(const std::string& from_filename, + const std::string& to_filename) { if (to_filename.find("google/protobuf") == 0) { // Well-known types (.proto files in the google/protobuf directory) are // assumed to come from the 'google-protobuf' npm package. We may want to @@ -177,7 +127,7 @@ string GetRootPath(const string& from_filename, const string& to_filename) { if (slashes == 0) { return "./"; } - string result = ""; + std::string result = ""; for (size_t i = 0; i < slashes; i++) { result += "../"; } @@ -186,7 +136,7 @@ string GetRootPath(const string& from_filename, const string& to_filename) { // Returns the alias we assign to the module of the given .proto filename // when importing. -string ModuleAlias(const string& filename) { +std::string ModuleAlias(const std::string& filename) { // This scheme could technically cause problems if a file includes any 2 of: // foo/bar_baz.proto // foo_bar_baz.proto @@ -194,17 +144,17 @@ string ModuleAlias(const string& filename) { // // We'll worry about this problem if/when we actually see it. This name isn't // exposed to users so we can change it later if we need to. - string basename = StripProto(filename); - StripString(&basename, "-", '$'); - StripString(&basename, "/", '_'); - StripString(&basename, ".", '_'); + std::string basename = StripProto(filename); + ReplaceCharacters(&basename, "-", '$'); + ReplaceCharacters(&basename, "/", '_'); + ReplaceCharacters(&basename, ".", '_'); return basename + "_pb"; } -// Returns the fully normalized JavaScript path for the given +// Returns the fully normalized JavaScript namespace for the given // file descriptor's package. -string GetFilePath(const GeneratorOptions& options, - const FileDescriptor* file) { +std::string GetNamespace(const GeneratorOptions& options, + const FileDescriptor* file) { if (!options.namespace_prefix.empty()) { return options.namespace_prefix; } else if (!file->package().empty()) { @@ -218,11 +168,11 @@ string GetFilePath(const GeneratorOptions& options, // nesting, for example ".OuterMessage.InnerMessage", or returns empty if // descriptor is null. This function does not handle namespacing, only message // nesting. -string GetNestedMessageName(const Descriptor* descriptor) { +std::string GetNestedMessageName(const Descriptor* descriptor) { if (descriptor == NULL) { return ""; } - string result = + std::string result = StripPrefixString(descriptor->full_name(), descriptor->file()->package()); // Add a leading dot if one is not already present. if (!result.empty() && result[0] != '.') { @@ -233,39 +183,51 @@ string GetNestedMessageName(const Descriptor* descriptor) { // Returns the path prefix for a message or enumeration that // lives under the given file and containing type. -string GetPrefix(const GeneratorOptions& options, - const FileDescriptor* file_descriptor, - const Descriptor* containing_type) { - string prefix = GetFilePath(options, file_descriptor) + - GetNestedMessageName(containing_type); +std::string GetPrefix(const GeneratorOptions& options, + const FileDescriptor* file_descriptor, + const Descriptor* containing_type) { + std::string prefix = GetNamespace(options, file_descriptor) + + GetNestedMessageName(containing_type); if (!prefix.empty()) { prefix += "."; } return prefix; } +// Returns the fully normalized JavaScript path prefix for the given +// message descriptor. +std::string GetMessagePathPrefix(const GeneratorOptions& options, + const Descriptor* descriptor) { + return GetPrefix(options, descriptor->file(), descriptor->containing_type()); +} + // Returns the fully normalized JavaScript path for the given // message descriptor. -string GetMessagePath(const GeneratorOptions& options, - const Descriptor* descriptor) { - return GetPrefix( - options, descriptor->file(), - descriptor->containing_type()) + descriptor->name(); +std::string GetMessagePath(const GeneratorOptions& options, + const Descriptor* descriptor) { + return GetMessagePathPrefix(options, descriptor) + descriptor->name(); +} + +// Returns the fully normalized JavaScript path prefix for the given +// enumeration descriptor. +std::string GetEnumPathPrefix(const GeneratorOptions& options, + const EnumDescriptor* enum_descriptor) { + return GetPrefix(options, enum_descriptor->file(), + enum_descriptor->containing_type()); } // Returns the fully normalized JavaScript path for the given // enumeration descriptor. -string GetEnumPath(const GeneratorOptions& options, - const EnumDescriptor* enum_descriptor) { - return GetPrefix( - options, enum_descriptor->file(), - enum_descriptor->containing_type()) + enum_descriptor->name(); +std::string GetEnumPath(const GeneratorOptions& options, + const EnumDescriptor* enum_descriptor) { + return GetEnumPathPrefix(options, enum_descriptor) + enum_descriptor->name(); } -string MaybeCrossFileRef(const GeneratorOptions& options, - const FileDescriptor* from_file, - const Descriptor* to_message) { - if (options.import_style == GeneratorOptions::kImportCommonJs && +std::string MaybeCrossFileRef(const GeneratorOptions& options, + const FileDescriptor* from_file, + const Descriptor* to_message) { + if ((options.import_style == GeneratorOptions::kImportCommonJs || + options.import_style == GeneratorOptions::kImportCommonJsStrict) && from_file != to_message->file()) { // Cross-file ref in CommonJS needs to use the module alias instead of // the global name. @@ -278,8 +240,8 @@ string MaybeCrossFileRef(const GeneratorOptions& options, } } -string SubmessageTypeRef(const GeneratorOptions& options, - const FieldDescriptor* field) { +std::string SubmessageTypeRef(const GeneratorOptions& options, + const FieldDescriptor* field) { GOOGLE_CHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE); return MaybeCrossFileRef(options, field->file(), field->message_type()); } @@ -301,9 +263,9 @@ char ToLowerASCII(char c) { } } -std::vector ParseLowerUnderscore(const string& input) { - std::vector words; - string running = ""; +std::vector ParseLowerUnderscore(const std::string& input) { + std::vector words; + std::string running = ""; for (int i = 0; i < input.size(); i++) { if (input[i] == '_') { if (!running.empty()) { @@ -320,9 +282,9 @@ std::vector ParseLowerUnderscore(const string& input) { return words; } -std::vector ParseUpperCamel(const string& input) { - std::vector words; - string running = ""; +std::vector ParseUpperCamel(const std::string& input) { + std::vector words; + std::string running = ""; for (int i = 0; i < input.size(); i++) { if (input[i] >= 'A' && input[i] <= 'Z' && !running.empty()) { words.push_back(running); @@ -336,10 +298,10 @@ std::vector ParseUpperCamel(const string& input) { return words; } -string ToLowerCamel(const std::vector& words) { - string result; +std::string ToLowerCamel(const std::vector& words) { + std::string result; for (int i = 0; i < words.size(); i++) { - string word = words[i]; + std::string word = words[i]; if (i == 0 && (word[0] >= 'A' && word[0] <= 'Z')) { word[0] = (word[0] - 'A') + 'a'; } else if (i != 0 && (word[0] >= 'a' && word[0] <= 'z')) { @@ -350,10 +312,10 @@ string ToLowerCamel(const std::vector& words) { return result; } -string ToUpperCamel(const std::vector& words) { - string result; +std::string ToUpperCamel(const std::vector& words) { + std::string result; for (int i = 0; i < words.size(); i++) { - string word = words[i]; + std::string word = words[i]; if (word[0] >= 'a' && word[0] <= 'z') { word[0] = (word[0] - 'a') + 'A'; } @@ -365,8 +327,8 @@ string ToUpperCamel(const std::vector& words) { // Based on code from descriptor.cc (Thanks Kenton!) // Uppercases the entire string, turning ValueName into // VALUENAME. -string ToEnumCase(const string& input) { - string result; +std::string ToEnumCase(const std::string& input) { + std::string result; result.reserve(input.size()); for (int i = 0; i < input.size(); i++) { @@ -380,8 +342,8 @@ string ToEnumCase(const string& input) { return result; } -string ToFileName(const string& input) { - string result; +std::string ToLower(const std::string& input) { + std::string result; result.reserve(input.size()); for (int i = 0; i < input.size(); i++) { @@ -395,44 +357,90 @@ string ToFileName(const string& input) { return result; } -// When we're generating one output file per type name, this is the filename +// When we're generating one output file per SCC, this is the filename // that top-level extensions should go in. -string GetExtensionFileName(const GeneratorOptions& options, - const FileDescriptor* file) { - return options.output_dir + "/" + ToFileName(GetFilePath(options, file)) + +// e.g. one proto file (test.proto): +// package a; +// extends Foo { +// ... +// } +// If "with_filename" equals true, the extension filename will be +// "proto.a_test_extensions.js", otherwise will be "proto.a.js" +std::string GetExtensionFileName(const GeneratorOptions& options, + const FileDescriptor* file, + bool with_filename) { + std::string snake_name = StripProto(GetSnakeFilename(file->name())); + return options.output_dir + "/" + ToLower(GetNamespace(options, file)) + + (with_filename ? ("_" + snake_name + "_extensions") : "") + options.GetFileNameExtension(); } - -// When we're generating one output file per type name, this is the filename -// that a top-level message should go in. -string GetMessageFileName(const GeneratorOptions& options, - const Descriptor* desc) { - return options.output_dir + "/" + ToFileName(desc->name()) + +// When we're generating one output file per SCC, this is the filename +// that all messages in the SCC should go in. +// If with_package equals true, filename will have package prefix, +// If the filename length is longer than 200, the filename will be the +// SCC's proto filename with suffix "_long_sccs_(index)" (if with_package equals +// true it still has package prefix) +std::string GetMessagesFileName(const GeneratorOptions& options, const SCC* scc, + bool with_package) { + static std::map* long_name_dict = + new std::map(); + std::string package_base = + with_package + ? ToLower(GetNamespace(options, scc->GetRepresentative()->file()) + + "_") + : ""; + std::string filename_base = ""; + std::vector all_message_names; + for (auto one_desc : scc->descriptors) { + if (one_desc->containing_type() == nullptr) { + all_message_names.push_back(ToLower(one_desc->name())); + } + } + sort(all_message_names.begin(), all_message_names.end()); + for (auto one_message : all_message_names) { + if (!filename_base.empty()) { + filename_base += "_"; + } + filename_base += one_message; + } + if (filename_base.size() + package_base.size() > 200) { + if ((*long_name_dict).find(scc->GetRepresentative()) == + (*long_name_dict).end()) { + std::string snake_name = StripProto( + GetSnakeFilename(scc->GetRepresentative()->file()->name())); + (*long_name_dict)[scc->GetRepresentative()] = + StrCat(snake_name, "_long_sccs_", + static_cast((*long_name_dict).size())); + } + filename_base = (*long_name_dict)[scc->GetRepresentative()]; + } + return options.output_dir + "/" + package_base + filename_base + options.GetFileNameExtension(); } // When we're generating one output file per type name, this is the filename -// that a top-level message should go in. -string GetEnumFileName(const GeneratorOptions& options, - const EnumDescriptor* desc) { - return options.output_dir + "/" + ToFileName(desc->name()) + - options.GetFileNameExtension(); +// that a top-level enum should go in. +// If with_package equals true, filename will have package prefix. +std::string GetEnumFileName(const GeneratorOptions& options, + const EnumDescriptor* desc, bool with_package) { + return options.output_dir + "/" + + (with_package ? ToLower(GetNamespace(options, desc->file()) + "_") + : "") + + ToLower(desc->name()) + options.GetFileNameExtension(); } // Returns the message/response ID, if set. -string GetMessageId(const Descriptor* desc) { - return string(); -} +std::string GetMessageId(const Descriptor* desc) { return std::string(); } bool IgnoreExtensionField(const FieldDescriptor* field) { // Exclude descriptor extensions from output "to avoid clutter" (from original // codegen). - return field->is_extension() && - field->containing_type()->file()->name() == - "google/protobuf/descriptor.proto"; + if (!field->is_extension()) return false; + const FileDescriptor* file = field->containing_type()->file(); + return file->name() == "net/proto2/proto/descriptor.proto" || + file->name() == "google/protobuf/descriptor.proto"; } - // Used inside Google only -- do not remove. bool IsResponse(const Descriptor* desc) { return false; } @@ -440,24 +448,12 @@ bool IgnoreField(const FieldDescriptor* field) { return IgnoreExtensionField(field); } - -// Used inside Google only -- do not remove. -bool ShouldTreatMapsAsRepeatedFields(const FileDescriptor& descriptor) { - return false; -} - // Do we ignore this message type? -bool IgnoreMessage(const GeneratorOptions& options, const Descriptor* d) { - return d->options().map_entry() && - !ShouldTreatMapsAsRepeatedFields(*d->file()); -} - -bool IsMap(const GeneratorOptions& options, const FieldDescriptor* field) { - return field->is_map() && !ShouldTreatMapsAsRepeatedFields(*field->file()); -} +bool IgnoreMessage(const Descriptor* d) { return d->options().map_entry(); } // Does JSPB ignore this entire oneof? True only if all fields are ignored. bool IgnoreOneof(const OneofDescriptor* oneof) { + if (oneof->is_synthetic()) return true; for (int i = 0; i < oneof->field_count(); i++) { if (!IgnoreField(oneof->field(i))) { return false; @@ -466,19 +462,19 @@ bool IgnoreOneof(const OneofDescriptor* oneof) { return true; } -string JSIdent(const GeneratorOptions& options, const FieldDescriptor* field, - bool is_upper_camel, bool is_map, bool drop_list) { - string result; +std::string JSIdent(const GeneratorOptions& options, + const FieldDescriptor* field, bool is_upper_camel, + bool is_map, bool drop_list) { + std::string result; if (field->type() == FieldDescriptor::TYPE_GROUP) { - result = is_upper_camel ? - ToUpperCamel(ParseUpperCamel(field->message_type()->name())) : - ToLowerCamel(ParseUpperCamel(field->message_type()->name())); + result = is_upper_camel + ? ToUpperCamel(ParseUpperCamel(field->message_type()->name())) + : ToLowerCamel(ParseUpperCamel(field->message_type()->name())); } else { - result = is_upper_camel ? - ToUpperCamel(ParseLowerUnderscore(field->name())) : - ToLowerCamel(ParseLowerUnderscore(field->name())); + result = is_upper_camel ? ToUpperCamel(ParseLowerUnderscore(field->name())) + : ToLowerCamel(ParseLowerUnderscore(field->name())); } - if (is_map || IsMap(options, field)) { + if (is_map || field->is_map()) { // JSPB-style or proto3-style map. result += "Map"; } else if (!drop_list && field->is_repeated()) { @@ -488,19 +484,19 @@ string JSIdent(const GeneratorOptions& options, const FieldDescriptor* field, return result; } -string JSObjectFieldName(const GeneratorOptions& options, - const FieldDescriptor* field) { - string name = JSIdent(options, field, - /* is_upper_camel = */ false, - /* is_map = */ false, - /* drop_list = */ false); +std::string JSObjectFieldName(const GeneratorOptions& options, + const FieldDescriptor* field) { + std::string name = JSIdent(options, field, + /* is_upper_camel = */ false, + /* is_map = */ false, + /* drop_list = */ false); if (IsReserved(name)) { name = "pb_" + name; } return name; } -string JSByteGetterSuffix(BytesMode bytes_mode) { +std::string JSByteGetterSuffix(BytesMode bytes_mode) { switch (bytes_mode) { case BYTES_DEFAULT: return ""; @@ -516,15 +512,15 @@ string JSByteGetterSuffix(BytesMode bytes_mode) { // Returns the field name as a capitalized portion of a getter/setter method // name, e.g. MyField for .getMyField(). -string JSGetterName(const GeneratorOptions& options, - const FieldDescriptor* field, - BytesMode bytes_mode = BYTES_DEFAULT, - bool drop_list = false) { - string name = JSIdent(options, field, - /* is_upper_camel = */ true, - /* is_map = */ false, drop_list); +std::string JSGetterName(const GeneratorOptions& options, + const FieldDescriptor* field, + BytesMode bytes_mode = BYTES_DEFAULT, + bool drop_list = false) { + std::string name = JSIdent(options, field, + /* is_upper_camel = */ true, + /* is_map = */ false, drop_list); if (field->type() == FieldDescriptor::TYPE_BYTES) { - string suffix = JSByteGetterSuffix(bytes_mode); + std::string suffix = JSByteGetterSuffix(bytes_mode); if (!suffix.empty()) { name += "_as" + suffix; } @@ -536,15 +532,13 @@ string JSGetterName(const GeneratorOptions& options, return name; } - - -string JSOneofName(const OneofDescriptor* oneof) { +std::string JSOneofName(const OneofDescriptor* oneof) { return ToUpperCamel(ParseLowerUnderscore(oneof->name())); } // Returns the index corresponding to this field in the JSPB array (underlying // data storage array). -string JSFieldIndex(const FieldDescriptor* field) { +std::string JSFieldIndex(const FieldDescriptor* field) { // Determine whether this field is a member of a group. Group fields are a bit // wonky: their "containing type" is a message type created just for the // group, and that type's parent type has a field with the group-message type @@ -557,17 +551,18 @@ string JSFieldIndex(const FieldDescriptor* field) { for (int i = 0; i < parent_type->field_count(); i++) { if (parent_type->field(i)->type() == FieldDescriptor::TYPE_GROUP && parent_type->field(i)->message_type() == containing_type) { - return SimpleItoa(field->number() - parent_type->field(i)->number()); + return StrCat(field->number() - parent_type->field(i)->number()); } } } - return SimpleItoa(field->number()); + return StrCat(field->number()); } -string JSOneofIndex(const OneofDescriptor* oneof) { +std::string JSOneofIndex(const OneofDescriptor* oneof) { int index = -1; for (int i = 0; i < oneof->containing_type()->oneof_decl_count(); i++) { const OneofDescriptor* o = oneof->containing_type()->oneof_decl(i); + if (o->is_synthetic()) continue; // If at least one field in this oneof is not JSPB-ignored, count the oneof. for (int j = 0; j < o->field_count(); j++) { const FieldDescriptor* f = o->field(j); @@ -580,7 +575,7 @@ string JSOneofIndex(const OneofDescriptor* oneof) { break; } } - return SimpleItoa(index); + return StrCat(index); } // Decodes a codepoint in \x0000 -- \xFFFF. @@ -609,13 +604,15 @@ uint16 DecodeUTF8Codepoint(uint8* bytes, size_t* length) { *length = expected; switch (expected) { - case 1: return bytes[0]; - case 2: return ((bytes[0] & 0x1F) << 6) | - ((bytes[1] & 0x3F) << 0); - case 3: return ((bytes[0] & 0x0F) << 12) | - ((bytes[1] & 0x3F) << 6) | - ((bytes[2] & 0x3F) << 0); - default: return 0; + case 1: + return bytes[0]; + case 2: + return ((bytes[0] & 0x1F) << 6) | ((bytes[1] & 0x3F) << 0); + case 3: + return ((bytes[0] & 0x0F) << 12) | ((bytes[1] & 0x3F) << 6) | + ((bytes[2] & 0x3F) << 0); + default: + return 0; } } @@ -623,8 +620,8 @@ uint16 DecodeUTF8Codepoint(uint8* bytes, size_t* length) { // JavaScript. The input data should be a UTF-8 encoded C++ string of chars. // Returns false if |out| was truncated because |in| contained invalid UTF-8 or // codepoints outside the BMP. -// TODO(lukestebbing): Support codepoints outside the BMP. -bool EscapeJSString(const string& in, string* out) { +// TODO(b/115551870): Support codepoints outside the BMP. +bool EscapeJSString(const std::string& in, std::string* out) { size_t decoded = 0; for (size_t i = 0; i < in.size(); i += decoded) { uint16 codepoint = 0; @@ -642,20 +639,44 @@ bool EscapeJSString(const string& in, string* out) { decoded = have_bytes; switch (codepoint) { - case '\'': *out += "\\x27"; break; - case '"': *out += "\\x22"; break; - case '<': *out += "\\x3c"; break; - case '=': *out += "\\x3d"; break; - case '>': *out += "\\x3e"; break; - case '&': *out += "\\x26"; break; - case '\b': *out += "\\b"; break; - case '\t': *out += "\\t"; break; - case '\n': *out += "\\n"; break; - case '\f': *out += "\\f"; break; - case '\r': *out += "\\r"; break; - case '\\': *out += "\\\\"; break; + case '\'': + *out += "\\x27"; + break; + case '"': + *out += "\\x22"; + break; + case '<': + *out += "\\x3c"; + break; + case '=': + *out += "\\x3d"; + break; + case '>': + *out += "\\x3e"; + break; + case '&': + *out += "\\x26"; + break; + case '\b': + *out += "\\b"; + break; + case '\t': + *out += "\\t"; + break; + case '\n': + *out += "\\n"; + break; + case '\f': + *out += "\\f"; + break; + case '\r': + *out += "\\r"; + break; + case '\\': + *out += "\\\\"; + break; default: - // TODO(lukestebbing): Once we're supporting codepoints outside the BMP, + // TODO(b/115551870): Once we're supporting codepoints outside the BMP, // use a single Unicode codepoint escape if the output language is // ECMAScript 2015 or above. Otherwise, use a surrogate pair. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#String_literals @@ -672,24 +693,23 @@ bool EscapeJSString(const string& in, string* out) { return true; } -string EscapeBase64(const string& in) { +std::string EscapeBase64(const std::string& in) { static const char* kAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - string result; + std::string result; for (size_t i = 0; i < in.size(); i += 3) { - int value = (in[i] << 16) | - (((i + 1) < in.size()) ? (in[i + 1] << 8) : 0) | - (((i + 2) < in.size()) ? (in[i + 2] << 0) : 0); + int value = (in[i] << 16) | (((i + 1) < in.size()) ? (in[i + 1] << 8) : 0) | + (((i + 2) < in.size()) ? (in[i + 2] << 0) : 0); result += kAlphabet[(value >> 18) & 0x3f]; result += kAlphabet[(value >> 12) & 0x3f]; if ((i + 1) < in.size()) { - result += kAlphabet[(value >> 6) & 0x3f]; + result += kAlphabet[(value >> 6) & 0x3f]; } else { result += '='; } if ((i + 2) < in.size()) { - result += kAlphabet[(value >> 0) & 0x3f]; + result += kAlphabet[(value >> 0) & 0x3f]; } else { result += '='; } @@ -701,7 +721,7 @@ string EscapeBase64(const string& in) { // Post-process the result of SimpleFtoa/SimpleDtoa to *exactly* match the // original codegen's formatting (which is just .toString() on java.lang.Double // or java.lang.Float). -string PostProcessFloat(string result) { +std::string PostProcessFloat(std::string result) { // If inf, -inf or nan, replace with +Infinity, -Infinity or NaN. if (result == "inf") { return "Infinity"; @@ -715,13 +735,13 @@ string PostProcessFloat(string result) { // ensure that the mantissa (portion prior to the "e") has at least one // fractional digit (after the decimal point), and (iii) strip any unnecessary // leading zeroes and/or '+' signs from the exponent. - string::size_type exp_pos = result.find('e'); - if (exp_pos != string::npos) { - string mantissa = result.substr(0, exp_pos); - string exponent = result.substr(exp_pos + 1); + std::string::size_type exp_pos = result.find('e'); + if (exp_pos != std::string::npos) { + std::string mantissa = result.substr(0, exp_pos); + std::string exponent = result.substr(exp_pos + 1); // Add ".0" to mantissa if no fractional part exists. - if (mantissa.find('.') == string::npos) { + if (mantissa.find('.') == std::string::npos) { mantissa += ".0"; } @@ -739,28 +759,33 @@ string PostProcessFloat(string result) { exponent = exponent.substr(1); } - return mantissa + "E" + string(exp_neg ? "-" : "") + exponent; + return mantissa + "E" + std::string(exp_neg ? "-" : "") + exponent; } // Otherwise, this is an ordinary decimal number. Append ".0" if result has no // decimal/fractional part in order to match output of original codegen. - if (result.find('.') == string::npos) { + if (result.find('.') == std::string::npos) { result += ".0"; } return result; } -string FloatToString(float value) { - string result = SimpleFtoa(value); +std::string FloatToString(float value) { + std::string result = SimpleFtoa(value); return PostProcessFloat(result); } -string DoubleToString(double value) { - string result = SimpleDtoa(value); +std::string DoubleToString(double value) { + std::string result = SimpleDtoa(value); return PostProcessFloat(result); } +bool InRealOneof(const FieldDescriptor* field) { + return field->containing_oneof() && + !field->containing_oneof()->is_synthetic(); +} + // Return true if this is an integral field that should be represented as string // in JS. bool IsIntegralFieldWithStringJSType(const FieldDescriptor* field) { @@ -769,40 +794,39 @@ bool IsIntegralFieldWithStringJSType(const FieldDescriptor* field) { case FieldDescriptor::CPPTYPE_UINT64: // The default value of JSType is JS_NORMAL, which behaves the same as // JS_NUMBER. - return field->options().jstype() == google::protobuf::FieldOptions::JS_STRING; + return field->options().jstype() == FieldOptions::JS_STRING; default: return false; } } -string MaybeNumberString(const FieldDescriptor* field, const string& orig) { +std::string MaybeNumberString(const FieldDescriptor* field, + const std::string& orig) { return IsIntegralFieldWithStringJSType(field) ? ("\"" + orig + "\"") : orig; } -string JSFieldDefault(const FieldDescriptor* field) { +std::string JSFieldDefault(const FieldDescriptor* field) { if (field->is_repeated()) { return "[]"; } switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: - return MaybeNumberString( - field, SimpleItoa(field->default_value_int32())); + return MaybeNumberString(field, StrCat(field->default_value_int32())); case FieldDescriptor::CPPTYPE_UINT32: // The original codegen is in Java, and Java protobufs store unsigned // integer values as signed integer values. In order to exactly match the // output, we need to reinterpret as base-2 signed. Ugh. return MaybeNumberString( - field, SimpleItoa(static_cast(field->default_value_uint32()))); + field, StrCat(static_cast(field->default_value_uint32()))); case FieldDescriptor::CPPTYPE_INT64: - return MaybeNumberString( - field, SimpleItoa(field->default_value_int64())); + return MaybeNumberString(field, StrCat(field->default_value_int64())); case FieldDescriptor::CPPTYPE_UINT64: // See above note for uint32 -- reinterpreting as signed. return MaybeNumberString( - field, SimpleItoa(static_cast(field->default_value_uint64()))); + field, StrCat(static_cast(field->default_value_uint64()))); case FieldDescriptor::CPPTYPE_ENUM: - return SimpleItoa(field->default_value_enum()->number()); + return StrCat(field->default_value_enum()->number()); case FieldDescriptor::CPPTYPE_BOOL: return field->default_value_bool() ? "true" : "false"; case FieldDescriptor::CPPTYPE_FLOAT: @@ -811,13 +835,14 @@ string JSFieldDefault(const FieldDescriptor* field) { return DoubleToString(field->default_value_double()); case FieldDescriptor::CPPTYPE_STRING: if (field->type() == FieldDescriptor::TYPE_STRING) { - string out; + std::string out; bool is_valid = EscapeJSString(field->default_value_string(), &out); if (!is_valid) { - // TODO(lukestebbing): Decide whether this should be a hard error. - GOOGLE_LOG(WARNING) << "The default value for field " << field->full_name() - << " was truncated since it contained invalid UTF-8 or" - " codepoints outside the basic multilingual plane."; + // TODO(b/115551870): Decide whether this should be a hard error. + GOOGLE_LOG(WARNING) + << "The default value for field " << field->full_name() + << " was truncated since it contained invalid UTF-8 or" + " codepoints outside the basic multilingual plane."; } return "\"" + out + "\""; } else { // Bytes @@ -830,8 +855,8 @@ string JSFieldDefault(const FieldDescriptor* field) { return ""; } -string ProtoTypeName(const GeneratorOptions& options, - const FieldDescriptor* field) { +std::string ProtoTypeName(const GeneratorOptions& options, + const FieldDescriptor* field) { switch (field->type()) { case FieldDescriptor::TYPE_BOOL: return "bool"; @@ -874,13 +899,13 @@ string ProtoTypeName(const GeneratorOptions& options, } } -string JSIntegerTypeName(const FieldDescriptor* field) { +std::string JSIntegerTypeName(const FieldDescriptor* field) { return IsIntegralFieldWithStringJSType(field) ? "string" : "number"; } -string JSStringTypeName(const GeneratorOptions& options, - const FieldDescriptor* field, - BytesMode bytes_mode) { +std::string JSStringTypeName(const GeneratorOptions& options, + const FieldDescriptor* field, + BytesMode bytes_mode) { if (field->type() == FieldDescriptor::TYPE_BYTES) { switch (bytes_mode) { case BYTES_DEFAULT: @@ -896,9 +921,8 @@ string JSStringTypeName(const GeneratorOptions& options, return "string"; } -string JSTypeName(const GeneratorOptions& options, - const FieldDescriptor* field, - BytesMode bytes_mode) { +std::string JSTypeName(const GeneratorOptions& options, + const FieldDescriptor* field, BytesMode bytes_mode) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_BOOL: return "boolean"; @@ -932,8 +956,8 @@ bool UseBrokenPresenceSemantics(const GeneratorOptions& options, } // Returns true for fields that return "null" from accessors when they are -// unset. This should normally only be true for non-repeated submessages, but -// we have legacy users who relied on old behavior where accessors behaved this +// unset. This should normally only be true for non-repeated submessages, but we +// have legacy users who relied on old behavior where accessors behaved this // way. bool ReturnsNullWhenUnset(const GeneratorOptions& options, const FieldDescriptor* field) { @@ -992,21 +1016,20 @@ bool SetterAcceptsNull(const GeneratorOptions& options, // Returns types which are known to by non-nullable by default. // The style guide requires that we omit "!" in this case. -bool IsPrimitive(const string& type) { +bool IsPrimitive(const std::string& type) { return type == "undefined" || type == "string" || type == "number" || type == "boolean"; } -string JSFieldTypeAnnotation(const GeneratorOptions& options, - const FieldDescriptor* field, - bool is_setter_argument, - bool force_present, - bool singular_if_not_packed, - BytesMode bytes_mode = BYTES_DEFAULT) { - GOOGLE_CHECK(!(is_setter_argument && force_present)); - string jstype = JSTypeName(options, field, bytes_mode); - - if (field->is_repeated() && +std::string JSFieldTypeAnnotation(const GeneratorOptions& options, + const FieldDescriptor* field, + bool is_setter_argument, bool force_present, + bool singular_if_not_packed, + BytesMode bytes_mode = BYTES_DEFAULT, + bool force_singular = false) { + std::string jstype = JSTypeName(options, field, bytes_mode); + + if (!force_singular && field->is_repeated() && (field->is_packed() || !singular_if_not_packed)) { if (field->type() == FieldDescriptor::TYPE_BYTES && bytes_mode == BYTES_DEFAULT) { @@ -1015,7 +1038,7 @@ string JSFieldTypeAnnotation(const GeneratorOptions& options, if (!IsPrimitive(jstype)) { jstype = "!" + jstype; } - jstype = "Array.<" + jstype + ">"; + jstype = "Array<" + jstype + ">"; } } @@ -1047,17 +1070,17 @@ string JSFieldTypeAnnotation(const GeneratorOptions& options, return jstype; } -string JSBinaryReaderMethodType(const FieldDescriptor* field) { - string name = field->type_name(); +std::string JSBinaryReaderMethodType(const FieldDescriptor* field) { + std::string name = field->type_name(); if (name[0] >= 'a' && name[0] <= 'z') { name[0] = (name[0] - 'a') + 'A'; } return IsIntegralFieldWithStringJSType(field) ? (name + "String") : name; } -string JSBinaryReadWriteMethodName(const FieldDescriptor* field, - bool is_writer) { - string name = JSBinaryReaderMethodType(field); +std::string JSBinaryReadWriteMethodName(const FieldDescriptor* field, + bool is_writer) { + std::string name = JSBinaryReaderMethodType(field); if (field->is_packed()) { name = "Packed" + name; } else if (is_writer && field->is_repeated()) { @@ -1066,31 +1089,60 @@ string JSBinaryReadWriteMethodName(const FieldDescriptor* field, return name; } -string JSBinaryReaderMethodName(const GeneratorOptions& options, - const FieldDescriptor* field) { +std::string JSBinaryReaderMethodName(const GeneratorOptions& options, + const FieldDescriptor* field) { return "jspb.BinaryReader.prototype.read" + JSBinaryReadWriteMethodName(field, /* is_writer = */ false); } -string JSBinaryWriterMethodName(const GeneratorOptions& options, - const FieldDescriptor* field) { +std::string JSBinaryWriterMethodName(const GeneratorOptions& options, + const FieldDescriptor* field) { + if (field->containing_type() && + field->containing_type()->options().message_set_wire_format()) { + return "jspb.BinaryWriter.prototype.writeMessageSet"; + } return "jspb.BinaryWriter.prototype.write" + JSBinaryReadWriteMethodName(field, /* is_writer = */ true); } -string JSReturnClause(const FieldDescriptor* desc) { - return ""; -} - -string JSReturnDoc(const GeneratorOptions& options, - const FieldDescriptor* desc) { +std::string JSTypeTag(const FieldDescriptor* desc) { + switch (desc->type()) { + case FieldDescriptor::TYPE_DOUBLE: + case FieldDescriptor::TYPE_FLOAT: + return "Float"; + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_FIXED64: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_SINT64: + case FieldDescriptor::TYPE_SFIXED32: + case FieldDescriptor::TYPE_SFIXED64: + if (IsIntegralFieldWithStringJSType(desc)) { + return "StringInt"; + } else { + return "Int"; + } + case FieldDescriptor::TYPE_BOOL: + return "Boolean"; + case FieldDescriptor::TYPE_STRING: + return "String"; + case FieldDescriptor::TYPE_BYTES: + return "Bytes"; + case FieldDescriptor::TYPE_ENUM: + return "Enum"; + default: + assert(false); + } return ""; } bool HasRepeatedFields(const GeneratorOptions& options, const Descriptor* desc) { for (int i = 0; i < desc->field_count(); i++) { - if (desc->field(i)->is_repeated() && !IsMap(options, desc->field(i))) { + if (desc->field(i)->is_repeated() && !desc->field(i)->is_map()) { return true; } } @@ -1099,8 +1151,8 @@ bool HasRepeatedFields(const GeneratorOptions& options, static const char* kRepeatedFieldArrayName = ".repeatedFields_"; -string RepeatedFieldsArrayName(const GeneratorOptions& options, - const Descriptor* desc) { +std::string RepeatedFieldsArrayName(const GeneratorOptions& options, + const Descriptor* desc) { return HasRepeatedFields(options, desc) ? (GetMessagePath(options, desc) + kRepeatedFieldArrayName) : "null"; @@ -1108,7 +1160,7 @@ string RepeatedFieldsArrayName(const GeneratorOptions& options, bool HasOneofFields(const Descriptor* desc) { for (int i = 0; i < desc->field_count(); i++) { - if (desc->field(i)->containing_oneof()) { + if (InRealOneof(desc->field(i))) { return true; } } @@ -1117,34 +1169,34 @@ bool HasOneofFields(const Descriptor* desc) { static const char* kOneofGroupArrayName = ".oneofGroups_"; -string OneofFieldsArrayName(const GeneratorOptions& options, - const Descriptor* desc) { +std::string OneofFieldsArrayName(const GeneratorOptions& options, + const Descriptor* desc) { return HasOneofFields(desc) ? (GetMessagePath(options, desc) + kOneofGroupArrayName) : "null"; } -string RepeatedFieldNumberList(const GeneratorOptions& options, - const Descriptor* desc) { - std::vector numbers; +std::string RepeatedFieldNumberList(const GeneratorOptions& options, + const Descriptor* desc) { + std::vector numbers; for (int i = 0; i < desc->field_count(); i++) { - if (desc->field(i)->is_repeated() && !IsMap(options, desc->field(i))) { + if (desc->field(i)->is_repeated() && !desc->field(i)->is_map()) { numbers.push_back(JSFieldIndex(desc->field(i))); } } return "[" + Join(numbers, ",") + "]"; } -string OneofGroupList(const Descriptor* desc) { +std::string OneofGroupList(const Descriptor* desc) { // List of arrays (one per oneof), each of which is a list of field indices - std::vector oneof_entries; + std::vector oneof_entries; for (int i = 0; i < desc->oneof_decl_count(); i++) { const OneofDescriptor* oneof = desc->oneof_decl(i); if (IgnoreOneof(oneof)) { continue; } - std::vector oneof_fields; + std::vector oneof_fields; for (int j = 0; j < oneof->field_count(); j++) { if (IgnoreField(oneof->field(j))) { continue; @@ -1156,21 +1208,22 @@ string OneofGroupList(const Descriptor* desc) { return "[" + Join(oneof_entries, ",") + "]"; } -string JSOneofArray(const GeneratorOptions& options, - const FieldDescriptor* field) { +std::string JSOneofArray(const GeneratorOptions& options, + const FieldDescriptor* field) { return OneofFieldsArrayName(options, field->containing_type()) + "[" + - JSOneofIndex(field->containing_oneof()) + "]"; + JSOneofIndex(field->containing_oneof()) + "]"; } -string RelativeTypeName(const FieldDescriptor* field) { +std::string RelativeTypeName(const FieldDescriptor* field) { assert(field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM || field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE); // For a field with an enum or message type, compute a name relative to the // path name of the message type containing this field. - string package = field->file()->package(); - string containing_type = field->containing_type()->full_name() + "."; - string type = (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) ? - field->enum_type()->full_name() : field->message_type()->full_name(); + std::string package = field->file()->package(); + std::string containing_type = field->containing_type()->full_name() + "."; + std::string type = (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) + ? field->enum_type()->full_name() + : field->message_type()->full_name(); // |prefix| is advanced as we find separators '.' past the common package // prefix that yield common prefixes in the containing type's name and this @@ -1188,9 +1241,9 @@ string RelativeTypeName(const FieldDescriptor* field) { return type.substr(prefix); } -string JSExtensionsObjectName(const GeneratorOptions& options, - const FileDescriptor* from_file, - const Descriptor* desc) { +std::string JSExtensionsObjectName(const GeneratorOptions& options, + const FileDescriptor* from_file, + const Descriptor* desc) { if (desc->full_name() == "google.protobuf.bridge.MessageSet") { // TODO(haberman): fix this for the kImportCommonJs case. return "jspb.Message.messageSetExtensions"; @@ -1212,28 +1265,27 @@ const FieldDescriptor* MapFieldValue(const FieldDescriptor* field) { return field->message_type()->FindFieldByNumber(kMapValueField); } -string FieldDefinition(const GeneratorOptions& options, - const FieldDescriptor* field) { - if (IsMap(options, field)) { +std::string FieldDefinition(const GeneratorOptions& options, + const FieldDescriptor* field) { + if (field->is_map()) { const FieldDescriptor* key_field = MapFieldKey(field); const FieldDescriptor* value_field = MapFieldValue(field); - string key_type = ProtoTypeName(options, key_field); - string value_type; + std::string key_type = ProtoTypeName(options, key_field); + std::string value_type; if (value_field->type() == FieldDescriptor::TYPE_ENUM || value_field->type() == FieldDescriptor::TYPE_MESSAGE) { value_type = RelativeTypeName(value_field); } else { value_type = ProtoTypeName(options, value_field); } - return StringPrintf("map<%s, %s> %s = %d;", - key_type.c_str(), - value_type.c_str(), - field->name().c_str(), + return StringPrintf("map<%s, %s> %s = %d;", key_type.c_str(), + value_type.c_str(), field->name().c_str(), field->number()); } else { - string qualifier = field->is_repeated() ? "repeated" : - (field->is_optional() ? "optional" : "required"); - string type, name; + std::string qualifier = + field->is_repeated() ? "repeated" + : (field->is_optional() ? "optional" : "required"); + std::string type, name; if (field->type() == FieldDescriptor::TYPE_ENUM || field->type() == FieldDescriptor::TYPE_MESSAGE) { type = RelativeTypeName(field); @@ -1245,23 +1297,13 @@ string FieldDefinition(const GeneratorOptions& options, type = ProtoTypeName(options, field); name = field->name(); } - return StringPrintf("%s %s %s = %d;", - qualifier.c_str(), - type.c_str(), - name.c_str(), - field->number()); + return StringPrintf("%s %s %s = %d;", qualifier.c_str(), type.c_str(), + name.c_str(), field->number()); } } -string FieldComments(const FieldDescriptor* field, BytesMode bytes_mode) { - string comments; - if (field->cpp_type() == FieldDescriptor::CPPTYPE_BOOL) { - comments += - " * Note that Boolean fields may be set to 0/1 when serialized from " - "a Java server.\n" - " * You should avoid comparisons like {@code val === true/false} in " - "those cases.\n"; - } +std::string FieldComments(const FieldDescriptor* field, BytesMode bytes_mode) { + std::string comments; if (field->type() == FieldDescriptor::TYPE_BYTES && bytes_mode == BYTES_U8) { comments += " * Note that Uint8Array is not supported on all browsers.\n" @@ -1271,9 +1313,7 @@ string FieldComments(const FieldDescriptor* field, BytesMode bytes_mode) { } bool ShouldGenerateExtension(const FieldDescriptor* field) { - return - field->is_extension() && - !IgnoreField(field); + return field->is_extension() && !IgnoreField(field); } bool HasExtensions(const Descriptor* desc) { @@ -1306,7 +1346,7 @@ bool HasExtensions(const FileDescriptor* file) { bool HasMap(const GeneratorOptions& options, const Descriptor* desc) { for (int i = 0; i < desc->field_count(); i++) { - if (IsMap(options, desc->field(i))) { + if (desc->field(i)->is_map()) { return true; } } @@ -1333,7 +1373,7 @@ bool IsExtendable(const Descriptor* desc) { // Returns the max index in the underlying data storage array beyond which the // extension object is used. -string GetPivot(const Descriptor* desc) { +std::string GetPivot(const Descriptor* desc) { static const int kDefaultPivot = 500; // Find the max field number @@ -1347,65 +1387,73 @@ string GetPivot(const Descriptor* desc) { int pivot = -1; if (IsExtendable(desc) || (max_field_number >= kDefaultPivot)) { - pivot = ((max_field_number + 1) < kDefaultPivot) ? - (max_field_number + 1) : kDefaultPivot; + pivot = ((max_field_number + 1) < kDefaultPivot) ? (max_field_number + 1) + : kDefaultPivot; } - return SimpleItoa(pivot); + return StrCat(pivot); } // Whether this field represents presence. For fields with presence, we // generate extra methods (clearFoo() and hasFoo()) for this field. bool HasFieldPresence(const GeneratorOptions& options, const FieldDescriptor* field) { - if (field->is_repeated() || field->is_map()) { - // We say repeated fields and maps don't have presence, but we still do - // generate clearFoo() methods for them through a special case elsewhere. - return false; - } - - if (UseBrokenPresenceSemantics(options, field)) { - // Proto3 files with broken presence semantics have field presence. - return true; - } - - return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || - field->containing_oneof() != NULL || - field->file()->syntax() == FileDescriptor::SYNTAX_PROTO2; + // This returns false for repeated fields and maps, but we still do + // generate clearFoo() methods for these through a special case elsewhere. + return field->has_presence(); } // We use this to implement the semantics that same file can be generated -// multiple times, but the last one wins. We never actually write the files, -// but we keep a set of which descriptors were the final one for a given -// filename. +// multiple times, but only the last one keep the short name. Others all use +// long name with extra information to distinguish (For message and enum, the +// extra information is package name, for file level extension, the extra +// information is proto's filename). +// We never actually write the files, but we keep a set of which descriptors +// were the final one for a given filename. class FileDeduplicator { public: explicit FileDeduplicator(const GeneratorOptions& options) : error_on_conflict_(options.error_on_name_conflict) {} - bool AddFile(const string& filename, const void* desc, string* error) { - if (descs_by_filename_.find(filename) != descs_by_filename_.end()) { + // params: + // filenames: a pair of {short filename, full filename} + // (short filename don't have extra information, full filename + // contains extra information) + // desc: The Descriptor or SCC pointer or EnumDescriptor. + // error: The returned error information. + bool AddFile(const std::pair filenames, + const void* desc, std::string* error) { + if (descs_by_shortname_.find(filenames.first) != + descs_by_shortname_.end()) { if (error_on_conflict_) { - *error = "Name conflict: file name " + filename + + *error = "Name conflict: file name " + filenames.first + " would be generated by two descriptors"; return false; } - allowed_descs_.erase(descs_by_filename_[filename]); + // Change old pointer's actual name to full name. + auto short_name_desc = descs_by_shortname_[filenames.first]; + allowed_descs_actual_name_[short_name_desc] = + allowed_descs_full_name_[short_name_desc]; } + descs_by_shortname_[filenames.first] = desc; + allowed_descs_actual_name_[desc] = filenames.first; + allowed_descs_full_name_[desc] = filenames.second; - descs_by_filename_[filename] = desc; - allowed_descs_.insert(desc); return true; } - void GetAllowedSet(std::set* allowed_set) { - *allowed_set = allowed_descs_; + void GetAllowedMap(std::map* allowed_set) { + *allowed_set = allowed_descs_actual_name_; } private: bool error_on_conflict_; - std::map descs_by_filename_; - std::set allowed_descs_; + // The map that restores all the descs that are using short name as filename. + std::map descs_by_shortname_; + // The final actual filename map. + std::map allowed_descs_actual_name_; + // The full name map. + std::map allowed_descs_full_name_; }; void DepthFirstSearch(const FileDescriptor* file, @@ -1466,25 +1514,58 @@ void GenerateJspbFileOrder(const std::vector& input, // by choosing the last descriptor that writes each filename and permitting // only those to generate code. -bool GenerateJspbAllowedSet(const GeneratorOptions& options, +struct DepsGenerator { + std::vector operator()(const Descriptor* desc) const { + std::vector deps; + auto maybe_add = [&](const Descriptor* d) { + if (d) deps.push_back(d); + }; + for (int i = 0; i < desc->field_count(); i++) { + if (!IgnoreField(desc->field(i))) { + maybe_add(desc->field(i)->message_type()); + } + } + for (int i = 0; i < desc->extension_count(); i++) { + maybe_add(desc->extension(i)->message_type()); + maybe_add(desc->extension(i)->containing_type()); + } + for (int i = 0; i < desc->nested_type_count(); i++) { + maybe_add(desc->nested_type(i)); + } + maybe_add(desc->containing_type()); + + return deps; + } +}; + +bool GenerateJspbAllowedMap(const GeneratorOptions& options, const std::vector& files, - std::set* allowed_set, - string* error) { + std::map* allowed_set, + SCCAnalyzer* analyzer, + std::string* error) { std::vector files_ordered; GenerateJspbFileOrder(files, &files_ordered); // Choose the last descriptor for each filename. FileDeduplicator dedup(options); + std::set added; for (int i = 0; i < files_ordered.size(); i++) { for (int j = 0; j < files_ordered[i]->message_type_count(); j++) { const Descriptor* desc = files_ordered[i]->message_type(j); - if (!dedup.AddFile(GetMessageFileName(options, desc), desc, error)) { + if (added.insert(analyzer->GetSCC(desc)).second && + !dedup.AddFile( + std::make_pair( + GetMessagesFileName(options, analyzer->GetSCC(desc), false), + GetMessagesFileName(options, analyzer->GetSCC(desc), true)), + analyzer->GetSCC(desc), error)) { return false; } } for (int j = 0; j < files_ordered[i]->enum_type_count(); j++) { const EnumDescriptor* desc = files_ordered[i]->enum_type(j); - if (!dedup.AddFile(GetEnumFileName(options, desc), desc, error)) { + if (!dedup.AddFile(std::make_pair(GetEnumFileName(options, desc, false), + GetEnumFileName(options, desc, true)), + desc, error)) { return false; } } @@ -1499,39 +1580,71 @@ bool GenerateJspbAllowedSet(const GeneratorOptions& options, } if (has_extension) { - if (!dedup.AddFile(GetExtensionFileName(options, files_ordered[i]), - files_ordered[i], error)) { + if (!dedup.AddFile( + std::make_pair( + GetExtensionFileName(options, files_ordered[i], false), + GetExtensionFileName(options, files_ordered[i], true)), + files_ordered[i], error)) { return false; } } } - dedup.GetAllowedSet(allowed_set); + dedup.GetAllowedMap(allowed_set); return true; } +// Embeds base64 encoded GeneratedCodeInfo proto in a comment at the end of +// file. +void EmbedCodeAnnotations(const GeneratedCodeInfo& annotations, + io::Printer* printer) { + // Serialize annotations proto into base64 string. + std::string meta_content; + annotations.SerializeToString(&meta_content); + std::string meta_64; + Base64Escape(meta_content, &meta_64); + + // Print base64 encoded annotations at the end of output file in + // a comment. + printer->Print("\n// Below is base64 encoded GeneratedCodeInfo proto"); + printer->Print("\n// $encoded_proto$\n", "encoded_proto", meta_64); +} + +bool IsWellKnownTypeFile(const FileDescriptor* file) { + return HasPrefixString(file->name(), "google/protobuf/"); +} + } // anonymous namespace void Generator::GenerateHeader(const GeneratorOptions& options, + const FileDescriptor* file, io::Printer* printer) const { - printer->Print("/**\n" - " * @fileoverview\n" - " * @enhanceable\n" - " * @suppress {messageConventions} JS Compiler reports an " - "error if a variable or\n" - " * field starts with 'MSG_' and isn't a translatable " - "message.\n" - " * @public\n" - " */\n" - "// GENERATED CODE -- DO NOT EDIT!\n" - "\n"); + if (file != nullptr) { + printer->Print("// source: $filename$\n", "filename", file->name()); + } + printer->Print( + "/**\n" + " * @fileoverview\n" + " * @enhanceable\n" + // TODO(b/152440355): requireType/requires diverged from internal version. + " * @suppress {missingRequire} reports error on implicit type usages.\n" + " * @suppress {messageConventions} JS Compiler reports an " + "error if a variable or\n" + " * field starts with 'MSG_' and isn't a translatable " + "message.\n" + " * @public\n" + " */\n" + "// GENERATED CODE -- DO NOT EDIT!\n" + "/* eslint-disable */\n" + "// @ts-nocheck\n" + "\n"); } void Generator::FindProvidesForFile(const GeneratorOptions& options, io::Printer* printer, const FileDescriptor* file, - std::set* provided) const { + std::set* provided) const { for (int i = 0; i < file->message_type_count(); i++) { FindProvidesForMessage(options, printer, file->message_type(i), provided); } @@ -1543,7 +1656,7 @@ void Generator::FindProvidesForFile(const GeneratorOptions& options, void Generator::FindProvides(const GeneratorOptions& options, io::Printer* printer, const std::vector& files, - std::set* provided) const { + std::set* provided) const { for (int i = 0; i < files.size(); i++) { FindProvidesForFile(options, printer, files[i], provided); } @@ -1551,41 +1664,60 @@ void Generator::FindProvides(const GeneratorOptions& options, printer->Print("\n"); } -void Generator::FindProvidesForMessage( - const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc, - std::set* provided) const { - if (IgnoreMessage(options, desc)) { +void FindProvidesForOneOfEnum(const GeneratorOptions& options, + const OneofDescriptor* oneof, + std::set* provided) { + std::string name = GetMessagePath(options, oneof->containing_type()) + "." + + JSOneofName(oneof) + "Case"; + provided->insert(name); +} + +void FindProvidesForOneOfEnums(const GeneratorOptions& options, + io::Printer* printer, const Descriptor* desc, + std::set* provided) { + if (HasOneofFields(desc)) { + for (int i = 0; i < desc->oneof_decl_count(); i++) { + if (IgnoreOneof(desc->oneof_decl(i))) { + continue; + } + FindProvidesForOneOfEnum(options, desc->oneof_decl(i), provided); + } + } +} + +void Generator::FindProvidesForMessage(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc, + std::set* provided) const { + if (IgnoreMessage(desc)) { return; } - string name = GetMessagePath(options, desc); + std::string name = GetMessagePath(options, desc); provided->insert(name); for (int i = 0; i < desc->enum_type_count(); i++) { - FindProvidesForEnum(options, printer, desc->enum_type(i), - provided); + FindProvidesForEnum(options, printer, desc->enum_type(i), provided); } + + FindProvidesForOneOfEnums(options, printer, desc, provided); + for (int i = 0; i < desc->nested_type_count(); i++) { - FindProvidesForMessage(options, printer, desc->nested_type(i), - provided); + FindProvidesForMessage(options, printer, desc->nested_type(i), provided); } } - void Generator::FindProvidesForEnum(const GeneratorOptions& options, io::Printer* printer, const EnumDescriptor* enumdesc, - std::set* provided) const { - string name = GetEnumPath(options, enumdesc); + std::set* provided) const { + std::string name = GetEnumPath(options, enumdesc); provided->insert(name); } void Generator::FindProvidesForFields( - const GeneratorOptions& options, - io::Printer* printer, + const GeneratorOptions& options, io::Printer* printer, const std::vector& fields, - std::set* provided) const { + std::set* provided) const { for (int i = 0; i < fields.size(); i++) { const FieldDescriptor* field = fields[i]; @@ -1593,16 +1725,16 @@ void Generator::FindProvidesForFields( continue; } - string name = GetFilePath(options, field->file()) + "." + - JSObjectFieldName(options, field); + std::string name = GetNamespace(options, field->file()) + "." + + JSObjectFieldName(options, field); provided->insert(name); } } void Generator::GenerateProvides(const GeneratorOptions& options, io::Printer* printer, - std::set* provided) const { - for (std::set::iterator it = provided->begin(); + std::set* provided) const { + for (std::set::iterator it = provided->begin(); it != provided->end(); ++it) { if (options.import_style == GeneratorOptions::kImportClosure) { printer->Print("goog.provide('$name$');\n", "name", *it); @@ -1614,36 +1746,54 @@ void Generator::GenerateProvides(const GeneratorOptions& options, // // // Later generated code expects foo.bar = {} to exist: // foo.bar.Baz = function() { /* ... */ } - printer->Print("goog.exportSymbol('$name$', null, global);\n", "name", - *it); + + // Do not use global scope in strict mode + if (options.import_style == GeneratorOptions::kImportCommonJsStrict) { + std::string namespaceObject = *it; + // Remove "proto." from the namespace object + GOOGLE_CHECK_EQ(0, namespaceObject.compare(0, 6, "proto.")); + namespaceObject.erase(0, 6); + printer->Print("goog.exportSymbol('$name$', null, proto);\n", "name", + namespaceObject); + } else { + printer->Print("goog.exportSymbol('$name$', null, global);\n", "name", + *it); + } } } } -void Generator::GenerateRequiresForMessage(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc, - std::set* provided) const { - std::set required; - std::set forwards; +void Generator::GenerateRequiresForSCC(const GeneratorOptions& options, + io::Printer* printer, const SCC* scc, + std::set* provided) const { + std::set required; + std::set forwards; bool have_message = false; - FindRequiresForMessage(options, desc, - &required, &forwards, &have_message); + bool has_extension = false; + bool has_map = false; + for (auto desc : scc->descriptors) { + if (desc->containing_type() == nullptr) { + FindRequiresForMessage(options, desc, &required, &forwards, + &have_message); + has_extension = (has_extension || HasExtensions(desc)); + has_map = (has_map || HasMap(options, desc)); + } + } GenerateRequiresImpl(options, printer, &required, &forwards, provided, /* require_jspb = */ have_message, - /* require_extension = */ HasExtensions(desc), - /* require_map = */ HasMap(options, desc)); + /* require_extension = */ has_extension, + /* require_map = */ has_map); } void Generator::GenerateRequiresForLibrary( const GeneratorOptions& options, io::Printer* printer, const std::vector& files, - std::set* provided) const { + std::set* provided) const { GOOGLE_CHECK_EQ(options.import_style, GeneratorOptions::kImportClosure); // For Closure imports we need to import every message type individually. - std::set required; - std::set forwards; + std::set required; + std::set forwards; bool have_extensions = false; bool have_map = false; bool have_message = false; @@ -1651,7 +1801,7 @@ void Generator::GenerateRequiresForLibrary( for (int i = 0; i < files.size(); i++) { for (int j = 0; j < files[i]->message_type_count(); j++) { const Descriptor* desc = files[i]->message_type(j); - if (!IgnoreMessage(options, desc)) { + if (!IgnoreMessage(desc)) { FindRequiresForMessage(options, desc, &required, &forwards, &have_message); } @@ -1671,7 +1821,7 @@ void Generator::GenerateRequiresForLibrary( continue; } if (extension->containing_type()->full_name() != - "google.protobuf.bridge.MessageSet") { + "google.protobuf.bridge.MessageSet") { required.insert(GetMessagePath(options, extension->containing_type())); } FindRequiresForField(options, extension, &required, &forwards); @@ -1688,9 +1838,9 @@ void Generator::GenerateRequiresForLibrary( void Generator::GenerateRequiresForExtensions( const GeneratorOptions& options, io::Printer* printer, const std::vector& fields, - std::set* provided) const { - std::set required; - std::set forwards; + std::set* provided) const { + std::set required; + std::set forwards; for (int i = 0; i < fields.size(); i++) { const FieldDescriptor* field = fields[i]; if (IgnoreField(field)) { @@ -1707,9 +1857,9 @@ void Generator::GenerateRequiresForExtensions( void Generator::GenerateRequiresImpl(const GeneratorOptions& options, io::Printer* printer, - std::set* required, - std::set* forwards, - std::set* provided, + std::set* required, + std::set* forwards, + std::set* provided, bool require_jspb, bool require_extension, bool require_map) const { if (require_jspb) { @@ -1725,13 +1875,12 @@ void Generator::GenerateRequiresImpl(const GeneratorOptions& options, required->insert("jspb.Map"); } - std::set::iterator it; + std::set::iterator it; for (it = required->begin(); it != required->end(); ++it) { if (provided->find(*it) != provided->end()) { continue; } - printer->Print("goog.require('$name$');\n", - "name", *it); + printer->Print("goog.require('$name$');\n", "name", *it); } printer->Print("\n"); @@ -1740,23 +1889,17 @@ void Generator::GenerateRequiresImpl(const GeneratorOptions& options, if (provided->find(*it) != provided->end()) { continue; } - printer->Print("goog.forwardDeclare('$name$');\n", - "name", *it); + printer->Print("goog.forwardDeclare('$name$');\n", "name", *it); } } -bool NamespaceOnly(const Descriptor* desc) { - return false; -} - -void Generator::FindRequiresForMessage( - const GeneratorOptions& options, - const Descriptor* desc, - std::set* required, - std::set* forwards, - bool* have_message) const { - +bool NamespaceOnly(const Descriptor* desc) { return false; } +void Generator::FindRequiresForMessage(const GeneratorOptions& options, + const Descriptor* desc, + std::set* required, + std::set* forwards, + bool* have_message) const { if (!NamespaceOnly(desc)) { *have_message = true; for (int i = 0; i < desc->field_count(); i++) { @@ -1784,32 +1927,32 @@ void Generator::FindRequiresForMessage( void Generator::FindRequiresForField(const GeneratorOptions& options, const FieldDescriptor* field, - std::set* required, - std::set* forwards) const { - if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM && - // N.B.: file-level extensions with enum type do *not* create - // dependencies, as per original codegen. - !(field->is_extension() && field->extension_scope() == NULL)) { - if (options.add_require_for_enums) { - required->insert(GetEnumPath(options, field->enum_type())); - } else { - forwards->insert(GetEnumPath(options, field->enum_type())); - } - } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - if (!IgnoreMessage(options, field->message_type())) { - required->insert(GetMessagePath(options, field->message_type())); - } + std::set* required, + std::set* forwards) const { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM && + // N.B.: file-level extensions with enum type do *not* create + // dependencies, as per original codegen. + !(field->is_extension() && field->extension_scope() == nullptr)) { + if (options.add_require_for_enums) { + required->insert(GetEnumPath(options, field->enum_type())); + } else { + forwards->insert(GetEnumPath(options, field->enum_type())); } + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (!IgnoreMessage(field->message_type())) { + required->insert(GetMessagePath(options, field->message_type())); + } + } } -void Generator::FindRequiresForExtension(const GeneratorOptions& options, - const FieldDescriptor* field, - std::set* required, - std::set* forwards) const { - if (field->containing_type()->full_name() != "google.protobuf.bridge.MessageSet") { - required->insert(GetMessagePath(options, field->containing_type())); - } - FindRequiresForField(options, field, required, forwards); +void Generator::FindRequiresForExtension( + const GeneratorOptions& options, const FieldDescriptor* field, + std::set* required, std::set* forwards) const { + if (field->containing_type()->full_name() != + "google.protobuf.bridge.MessageSet") { + required->insert(GetMessagePath(options, field->containing_type())); + } + FindRequiresForField(options, field, required, forwards); } void Generator::GenerateTestOnly(const GeneratorOptions& options, @@ -1823,6 +1966,10 @@ void Generator::GenerateTestOnly(const GeneratorOptions& options, void Generator::GenerateClassesAndEnums(const GeneratorOptions& options, io::Printer* printer, const FileDescriptor* file) const { + for (int i = 0; i < file->message_type_count(); i++) { + GenerateClassConstructorAndDeclareExtensionFieldInfo(options, printer, + file->message_type(i)); + } for (int i = 0; i < file->message_type_count(); i++) { GenerateClass(options, printer, file->message_type(i)); } @@ -1834,16 +1981,14 @@ void Generator::GenerateClassesAndEnums(const GeneratorOptions& options, void Generator::GenerateClass(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const { - if (IgnoreMessage(options, desc)) { + if (IgnoreMessage(desc)) { return; } if (!NamespaceOnly(desc)) { printer->Print("\n"); - GenerateClassConstructor(options, printer, desc); GenerateClassFieldInfo(options, printer, desc); - GenerateClassToObject(options, printer, desc); // These must come *before* the extension-field info generation in // GenerateClassRegistration so that references to the binary @@ -1866,9 +2011,6 @@ void Generator::GenerateClass(const GeneratorOptions& options, if (!NamespaceOnly(desc)) { GenerateClassRegistration(options, printer, desc); GenerateClassFields(options, printer, desc); - if (IsExtendable(desc) && desc->full_name() != "google.protobuf.bridge.MessageSet") { - GenerateClassExtensionFieldInfo(options, printer, desc); - } if (options.import_style != GeneratorOptions::kImportClosure) { for (int i = 0; i < desc->extension_count(); i++) { @@ -1896,27 +2038,53 @@ void Generator::GenerateClassConstructor(const GeneratorOptions& options, " * @extends {jspb.Message}\n" " * @constructor\n" " */\n" - "$classname$ = function(opt_data) {\n", - "classname", GetMessagePath(options, desc)); - string message_id = GetMessageId(desc); + "$classprefix$$classname$ = function(opt_data) {\n", + "classprefix", GetMessagePathPrefix(options, desc), "classname", + desc->name()); + printer->Annotate("classname", desc); + std::string message_id = GetMessageId(desc); printer->Print( " jspb.Message.initialize(this, opt_data, $messageId$, $pivot$, " "$rptfields$, $oneoffields$);\n", - "messageId", !message_id.empty() ? - ("'" + message_id + "'") : - (IsResponse(desc) ? "''" : "0"), - "pivot", GetPivot(desc), - "rptfields", RepeatedFieldsArrayName(options, desc), - "oneoffields", OneofFieldsArrayName(options, desc)); + "messageId", + !message_id.empty() ? ("'" + message_id + "'") + : (IsResponse(desc) ? "''" : "0"), + "pivot", GetPivot(desc), "rptfields", + RepeatedFieldsArrayName(options, desc), "oneoffields", + OneofFieldsArrayName(options, desc)); printer->Print( "};\n" "goog.inherits($classname$, jspb.Message);\n" "if (goog.DEBUG && !COMPILED) {\n" + // displayName overrides Function.prototype.displayName + // http://google3/javascript/externs/es3.js?l=511 + " /**\n" + " * @public\n" + " * @override\n" + " */\n" " $classname$.displayName = '$classname$';\n" "}\n", "classname", GetMessagePath(options, desc)); } +void Generator::GenerateClassConstructorAndDeclareExtensionFieldInfo( + const GeneratorOptions& options, io::Printer* printer, + const Descriptor* desc) const { + if (!NamespaceOnly(desc)) { + GenerateClassConstructor(options, printer, desc); + if (IsExtendable(desc) && + desc->full_name() != "google.protobuf.bridge.MessageSet") { + GenerateClassExtensionFieldInfo(options, printer, desc); + } + } + for (int i = 0; i < desc->nested_type_count(); i++) { + if (!IgnoreMessage(desc->nested_type(i))) { + GenerateClassConstructorAndDeclareExtensionFieldInfo( + options, printer, desc->nested_type(i)); + } + } +} + void Generator::GenerateClassFieldInfo(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const { @@ -1929,9 +2097,9 @@ void Generator::GenerateClassFieldInfo(const GeneratorOptions& options, " */\n" "$classname$$rptfieldarray$ = $rptfields$;\n" "\n", - "classname", GetMessagePath(options, desc), - "rptfieldarray", kRepeatedFieldArrayName, - "rptfields", RepeatedFieldNumberList(options, desc)); + "classname", GetMessagePath(options, desc), "rptfieldarray", + kRepeatedFieldArrayName, "rptfields", + RepeatedFieldNumberList(options, desc)); } if (HasOneofFields(desc)) { @@ -1950,9 +2118,8 @@ void Generator::GenerateClassFieldInfo(const GeneratorOptions& options, " */\n" "$classname$$oneofgrouparray$ = $oneofgroups$;\n" "\n", - "classname", GetMessagePath(options, desc), - "oneofgrouparray", kOneofGroupArrayName, - "oneofgroups", OneofGroupList(desc)); + "classname", GetMessagePath(options, desc), "oneofgrouparray", + kOneofGroupArrayName, "oneofgroups", OneofGroupList(desc)); for (int i = 0; i < desc->oneof_decl_count(); i++) { if (IgnoreOneof(desc->oneof_decl(i))) { @@ -1974,8 +2141,7 @@ void Generator::GenerateClassXid(const GeneratorOptions& options, } void Generator::GenerateOneofCaseDefinition( - const GeneratorOptions& options, - io::Printer* printer, + const GeneratorOptions& options, io::Printer* printer, const OneofDescriptor* oneof) const { printer->Print( "/**\n" @@ -1983,9 +2149,8 @@ void Generator::GenerateOneofCaseDefinition( " */\n" "$classname$.$oneof$Case = {\n" " $upcase$_NOT_SET: 0", - "classname", GetMessagePath(options, oneof->containing_type()), - "oneof", JSOneofName(oneof), - "upcase", ToEnumCase(oneof->name())); + "classname", GetMessagePath(options, oneof->containing_type()), "oneof", + JSOneofName(oneof), "upcase", ToEnumCase(oneof->name())); for (int i = 0; i < oneof->field_count(); i++) { if (IgnoreField(oneof->field(i))) { @@ -1995,8 +2160,9 @@ void Generator::GenerateOneofCaseDefinition( printer->Print( ",\n" " $upcase$: $number$", - "upcase", ToEnumCase(oneof->field(i)->name()), - "number", JSFieldIndex(oneof->field(i))); + "upcase", ToEnumCase(oneof->field(i)->name()), "number", + JSFieldIndex(oneof->field(i))); + printer->Annotate("upcase", oneof->field(i)); } printer->Print( @@ -2011,9 +2177,8 @@ void Generator::GenerateOneofCaseDefinition( "computeOneofCase(this, $class$.oneofGroups_[$oneofindex$]));\n" "};\n" "\n", - "class", GetMessagePath(options, oneof->containing_type()), - "oneof", JSOneofName(oneof), - "oneofindex", JSOneofIndex(oneof)); + "class", GetMessagePath(options, oneof->containing_type()), "oneof", + JSOneofName(oneof), "oneofindex", JSOneofIndex(oneof)); } void Generator::GenerateClassToObject(const GeneratorOptions& options, @@ -2024,17 +2189,17 @@ void Generator::GenerateClassToObject(const GeneratorOptions& options, "\n" "if (jspb.Message.GENERATE_TO_OBJECT) {\n" "/**\n" - " * Creates an object representation of this proto suitable for use in " - "Soy templates.\n" + " * Creates an object representation of this proto.\n" " * Field names that are reserved in JavaScript and will be renamed to " "pb_name.\n" + " * Optional fields that are not set will be set to undefined.\n" " * To access a reserved field use, foo.pb_, eg, foo.pb_default.\n" " * For the list of reserved names please see:\n" - " * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.\n" - " * @param {boolean=} opt_includeInstance Whether to include the JSPB " - "instance\n" - " * for transitional soy proto support: http://goto/soy-param-" - "migration\n" + " * net/proto2/compiler/js/internal/generator.cc#kKeyword.\n" + " * @param {boolean=} opt_includeInstance Deprecated. whether to include " + "the\n" + " * JSPB instance for transitional soy proto support:\n" + " * http://goto/soy-param-migration\n" " * @return {!Object}\n" " */\n" "$classname$.prototype.toObject = function(opt_includeInstance) {\n" @@ -2044,9 +2209,9 @@ void Generator::GenerateClassToObject(const GeneratorOptions& options, "\n" "/**\n" " * Static version of the {@see toObject} method.\n" - " * @param {boolean|undefined} includeInstance Whether to include the " - "JSPB\n" - " * instance for transitional soy proto support:\n" + " * @param {boolean|undefined} includeInstance Deprecated. Whether to " + "include\n" + " * the JSPB instance for transitional soy proto support:\n" " * http://goto/soy-param-migration\n" " * @param {!$classname$} msg The msg instance to transform.\n" " * @return {!Object}\n" @@ -2102,62 +2267,64 @@ void Generator::GenerateClassToObject(const GeneratorOptions& options, } void Generator::GenerateFieldValueExpression(io::Printer* printer, - const char *obj_reference, + const char* obj_reference, const FieldDescriptor* field, bool use_default) const { - bool is_float_or_double = + const bool is_float_or_double = field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT || field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE; - if (use_default) { - if (is_float_or_double) { - // Coerce "Nan" and "Infinity" to actual float values. - // - // This will change null to 0, but that doesn't matter since we're getting - // with a default. - printer->Print("+"); - } - + const bool is_boolean = field->cpp_type() == FieldDescriptor::CPPTYPE_BOOL; + + const std::string with_default = use_default ? "WithDefault" : ""; + const std::string default_arg = + use_default ? StrCat(", ", JSFieldDefault(field)) : ""; + const std::string cardinality = field->is_repeated() ? "Repeated" : ""; + std::string type = ""; + if (is_float_or_double) { + type = "FloatingPoint"; + } + if (is_boolean) { + type = "Boolean"; + } + + // Prints the appropriate function, among: + // - getField + // - getBooleanField + // - getFloatingPointField => Replaced by getOptionalFloatingPointField to + // preserve backward compatibility. + // - getFieldWithDefault + // - getBooleanFieldWithDefault + // - getFloatingPointFieldWithDefault + // - getRepeatedField + // - getRepeatedBooleanField + // - getRepeatedFloatingPointField + if (is_float_or_double && !field->is_repeated() && !use_default) { printer->Print( - "jspb.Message.getFieldWithDefault($obj$, $index$, $default$)", - "obj", obj_reference, - "index", JSFieldIndex(field), - "default", JSFieldDefault(field)); + "jspb.Message.getOptionalFloatingPointField($obj$, " + "$index$$default$)", + "obj", obj_reference, "index", JSFieldIndex(field), "default", + default_arg); } else { - if (is_float_or_double) { - if (field->is_required()) { - // Use "+" to convert all fields to numeric (including null). - printer->Print( - "+jspb.Message.getField($obj$, $index$)", - "index", JSFieldIndex(field), - "obj", obj_reference); - } else { - // Converts "NaN" and "Infinity" while preserving null. - printer->Print( - "jspb.Message.get$cardinality$FloatingPointField($obj$, $index$)", - "cardinality", field->is_repeated() ? "Repeated" : "Optional", - "index", JSFieldIndex(field), - "obj", obj_reference); - } - } else { - printer->Print("jspb.Message.get$cardinality$Field($obj$, $index$)", - "cardinality", field->is_repeated() ? "Repeated" : "", - "index", JSFieldIndex(field), - "obj", obj_reference); - } + printer->Print( + "jspb.Message.get$cardinality$$type$Field$with_default$($obj$, " + "$index$$default$)", + "cardinality", cardinality, "type", type, "with_default", with_default, + "obj", obj_reference, "index", JSFieldIndex(field), "default", + default_arg); } } void Generator::GenerateClassFieldToObject(const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field) const { - printer->Print("$fieldname$: ", - "fieldname", JSObjectFieldName(options, field)); + printer->Print("$fieldname$: ", "fieldname", + JSObjectFieldName(options, field)); - if (IsMap(options, field)) { + if (field->is_map()) { const FieldDescriptor* value_field = MapFieldValue(field); // If the map values are of a message type, we must provide their static // toObject() method; otherwise we pass undefined for that argument. - string value_to_object; + std::string value_to_object; if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { value_to_object = GetMessagePath(options, value_field->message_type()) + ".toObject"; @@ -2172,28 +2339,30 @@ void Generator::GenerateClassFieldToObject(const GeneratorOptions& options, // Message field. if (field->is_repeated()) { { - printer->Print("jspb.Message.toObjectList(msg.get$getter$(),\n" - " $type$.toObject, includeInstance)", - "getter", JSGetterName(options, field), - "type", SubmessageTypeRef(options, field)); + printer->Print( + "jspb.Message.toObjectList(msg.get$getter$(),\n" + " $type$.toObject, includeInstance)", + "getter", JSGetterName(options, field), "type", + SubmessageTypeRef(options, field)); } } else { - printer->Print("(f = msg.get$getter$()) && " - "$type$.toObject(includeInstance, f)", - "getter", JSGetterName(options, field), - "type", SubmessageTypeRef(options, field)); + printer->Print( + "(f = msg.get$getter$()) && " + "$type$.toObject(includeInstance, f)", + "getter", JSGetterName(options, field), "type", + SubmessageTypeRef(options, field)); } } else if (field->type() == FieldDescriptor::TYPE_BYTES) { // For bytes fields we want to always return the B64 data. - printer->Print("msg.get$getter$()", - "getter", JSGetterName(options, field, BYTES_B64)); + printer->Print("msg.get$getter$()", "getter", + JSGetterName(options, field, BYTES_B64)); } else { bool use_default = field->has_default_value(); if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 && // Repeated fields get initialized to their default in the constructor // (why?), so we emit a plain getField() call for them. - !field->is_repeated() && !UseBrokenPresenceSemantics(options, field)) { + !field->is_repeated()) { // Proto3 puts all defaults (including implicit defaults) in toObject(). // But for proto2 we leave the existing semantics unchanged: unset fields // without default are unset. @@ -2205,91 +2374,132 @@ void Generator::GenerateClassFieldToObject(const GeneratorOptions& options, // We are migrating the accessors to return defaults instead of null, but // it may take longer to migrate toObject (or we might not want to do it at // all). So we want to generate independent code. + // The accessor for unset optional values without default should return + // null. Those are converted to undefined in the generated object. + if (!use_default) { + printer->Print("(f = "); + } GenerateFieldValueExpression(printer, "msg", field, use_default); + if (!use_default) { + printer->Print(") == null ? undefined : f"); + } + } +} + +void Generator::GenerateObjectTypedef(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const { + // TODO(b/122687752): Consider renaming nested messages called ObjectFormat + // to prevent collisions. + const std::string type_name = GetMessagePath(options, desc) + ".ObjectFormat"; + + printer->Print( + "/**\n" + " * The raw object form of $messageName$ as accepted by the `fromObject` " + "method.\n" + " * @record\n" + " */\n" + "$typeName$ = function() {\n", + "messageName", desc->name(), "typeName", type_name); + + for (int i = 0; i < desc->field_count(); i++) { + if (i > 0) { + printer->Print("\n"); + } + printer->Print( + " /** @type {$fieldType$|undefined} */\n" + " this.$fieldName$;\n", + "fieldName", JSObjectFieldName(options, desc->field(i)), + // TODO(b/121097361): Add type checking for field values. + "fieldType", "?"); } + + printer->Print("};\n\n"); } void Generator::GenerateClassFromObject(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const { + printer->Print("if (jspb.Message.GENERATE_FROM_OBJECT) {\n\n"); + + GenerateObjectTypedef(options, printer, desc); + printer->Print( - "if (jspb.Message.GENERATE_FROM_OBJECT) {\n" "/**\n" " * Loads data from an object into a new instance of this proto.\n" - " * @param {!Object} obj The object representation of this proto to\n" - " * load the data from.\n" + " * @param {!$classname$.ObjectFormat} obj\n" + " * The object representation of this proto to load the data from.\n" " * @return {!$classname$}\n" " */\n" "$classname$.fromObject = function(obj) {\n" - " var f, msg = new $classname$();\n", + " var msg = new $classname$();\n", "classname", GetMessagePath(options, desc)); for (int i = 0; i < desc->field_count(); i++) { const FieldDescriptor* field = desc->field(i); - GenerateClassFieldFromObject(options, printer, field); + if (!IgnoreField(field)) { + GenerateClassFieldFromObject(options, printer, field); + } } printer->Print( " return msg;\n" "};\n" - "}\n"); + "}\n\n"); } void Generator::GenerateClassFieldFromObject( - const GeneratorOptions& options, - io::Printer* printer, + const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field) const { - if (IsMap(options, field)) { + if (field->is_map()) { const FieldDescriptor* value_field = MapFieldValue(field); if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { // Since the map values are of message type, we have to do some extra work // to recursively call fromObject() on them before setting the map field. printer->Print( - " goog.isDef(obj.$name$) && jspb.Message.setWrapperField(\n" + " obj.$name$ && jspb.Message.setWrapperField(\n" " msg, $index$, jspb.Map.fromObject(obj.$name$, $fieldclass$, " "$fieldclass$.fromObject));\n", - "name", JSObjectFieldName(options, field), - "index", JSFieldIndex(field), - "fieldclass", GetMessagePath(options, value_field->message_type())); + "name", JSObjectFieldName(options, field), "index", + JSFieldIndex(field), "fieldclass", + GetMessagePath(options, value_field->message_type())); } else { // `msg` is a newly-constructed message object that has not yet built any // map containers wrapping underlying arrays, so we can simply directly // set the array here without fear of a stale wrapper. printer->Print( - " goog.isDef(obj.$name$) && " + " obj.$name$ && " "jspb.Message.setField(msg, $index$, obj.$name$);\n", - "name", JSObjectFieldName(options, field), - "index", JSFieldIndex(field)); + "name", JSObjectFieldName(options, field), "index", + JSFieldIndex(field)); } } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { // Message field (singular or repeated) if (field->is_repeated()) { { printer->Print( - " goog.isDef(obj.$name$) && " + " obj.$name$ && " "jspb.Message.setRepeatedWrapperField(\n" - " msg, $index$, goog.array.map(obj.$name$, function(i) {\n" - " return $fieldclass$.fromObject(i);\n" - " }));\n", - "name", JSObjectFieldName(options, field), - "index", JSFieldIndex(field), - "fieldclass", SubmessageTypeRef(options, field)); + " msg, $index$, obj.$name$.map(\n" + " $fieldclass$.fromObject));\n", + "name", JSObjectFieldName(options, field), "index", + JSFieldIndex(field), "fieldclass", + SubmessageTypeRef(options, field)); } } else { printer->Print( - " goog.isDef(obj.$name$) && jspb.Message.setWrapperField(\n" + " obj.$name$ && jspb.Message.setWrapperField(\n" " msg, $index$, $fieldclass$.fromObject(obj.$name$));\n", - "name", JSObjectFieldName(options, field), - "index", JSFieldIndex(field), - "fieldclass", SubmessageTypeRef(options, field)); + "name", JSObjectFieldName(options, field), "index", + JSFieldIndex(field), "fieldclass", SubmessageTypeRef(options, field)); } } else { // Simple (primitive) field. printer->Print( - " goog.isDef(obj.$name$) && jspb.Message.setField(msg, $index$, " + " obj.$name$ != null && jspb.Message.setField(msg, $index$, " "obj.$name$);\n", - "name", JSObjectFieldName(options, field), - "index", JSFieldIndex(field)); + "name", JSObjectFieldName(options, field), "index", + JSFieldIndex(field)); } } @@ -2303,7 +2513,6 @@ void Generator::GenerateClassRegistration(const GeneratorOptions& options, GenerateExtension(options, printer, extension); } } - } void Generator::GenerateClassFields(const GeneratorOptions& options, @@ -2316,15 +2525,13 @@ void Generator::GenerateClassFields(const GeneratorOptions& options, } } -void GenerateBytesWrapper(const GeneratorOptions& options, - io::Printer* printer, - const FieldDescriptor* field, - BytesMode bytes_mode) { - string type = JSFieldTypeAnnotation( - options, field, - /* is_setter_argument = */ false, - /* force_present = */ false, - /* singular_if_not_packed = */ false, bytes_mode); +void GenerateBytesWrapper(const GeneratorOptions& options, io::Printer* printer, + const FieldDescriptor* field, BytesMode bytes_mode) { + std::string type = + JSFieldTypeAnnotation(options, field, + /* is_setter_argument = */ false, + /* force_present = */ false, + /* singular_if_not_packed = */ false, bytes_mode); printer->Print( "/**\n" " * $fielddef$\n" @@ -2338,35 +2545,32 @@ void GenerateBytesWrapper(const GeneratorOptions& options, "};\n" "\n" "\n", - "fielddef", FieldDefinition(options, field), - "comment", FieldComments(field, bytes_mode), - "type", type, - "class", GetMessagePath(options, field->containing_type()), - "name", JSGetterName(options, field, bytes_mode), - "list", field->is_repeated() ? "List" : "", - "suffix", JSByteGetterSuffix(bytes_mode), - "defname", JSGetterName(options, field, BYTES_DEFAULT)); + "fielddef", FieldDefinition(options, field), "comment", + FieldComments(field, bytes_mode), "type", type, "class", + GetMessagePath(options, field->containing_type()), "name", + JSGetterName(options, field, bytes_mode), "list", + field->is_repeated() ? "List" : "", "suffix", + JSByteGetterSuffix(bytes_mode), "defname", + JSGetterName(options, field, BYTES_DEFAULT)); } void Generator::GenerateClassField(const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field) const { - if (IsMap(options, field)) { + if (field->is_map()) { const FieldDescriptor* key_field = MapFieldKey(field); const FieldDescriptor* value_field = MapFieldValue(field); // Map field: special handling to instantiate the map object on demand. - string key_type = - JSFieldTypeAnnotation( - options, key_field, - /* is_setter_argument = */ false, - /* force_present = */ true, - /* singular_if_not_packed = */ false); - string value_type = - JSFieldTypeAnnotation( - options, value_field, - /* is_setter_argument = */ false, - /* force_present = */ true, - /* singular_if_not_packed = */ false); + std::string key_type = + JSFieldTypeAnnotation(options, key_field, + /* is_setter_argument = */ false, + /* force_present = */ true, + /* singular_if_not_packed = */ false); + std::string value_type = + JSFieldTypeAnnotation(options, value_field, + /* is_setter_argument = */ false, + /* force_present = */ true, + /* singular_if_not_packed = */ false); printer->Print( "/**\n" @@ -2375,16 +2579,15 @@ void Generator::GenerateClassField(const GeneratorOptions& options, " * empty, instead returning `undefined`\n" " * @return {!jspb.Map<$keytype$,$valuetype$>}\n" " */\n", - "fielddef", FieldDefinition(options, field), - "keytype", key_type, + "fielddef", FieldDefinition(options, field), "keytype", key_type, "valuetype", value_type); printer->Print( - "$class$.prototype.get$name$ = function(opt_noLazyCreate) {\n" + "$class$.prototype.$gettername$ = function(opt_noLazyCreate) {\n" " return /** @type {!jspb.Map<$keytype$,$valuetype$>} */ (\n", "class", GetMessagePath(options, field->containing_type()), - "name", JSGetterName(options, field), - "keytype", key_type, + "gettername", "get" + JSGetterName(options, field), "keytype", key_type, "valuetype", value_type); + printer->Annotate("gettername", field); printer->Print( " jspb.Message.getMapField(this, $index$, opt_noLazyCreate", "index", JSFieldIndex(field)); @@ -2395,12 +2598,12 @@ void Generator::GenerateClassField(const GeneratorOptions& options, " $messageType$", "messageType", GetMessagePath(options, value_field->message_type())); } else { - printer->Print(",\n" + printer->Print( + ",\n" " null"); } - printer->Print( - "));\n"); + printer->Print("));\n"); printer->Print( "};\n" @@ -2416,14 +2619,14 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "$comment$" " * @return {$type$}\n" " */\n", - "fielddef", FieldDefinition(options, field), - "comment", FieldComments(field, BYTES_DEFAULT), - "type", JSFieldTypeAnnotation(options, field, - /* is_setter_argument = */ false, - /* force_present = */ false, - /* singular_if_not_packed = */ false)); + "fielddef", FieldDefinition(options, field), "comment", + FieldComments(field, BYTES_DEFAULT), "type", + JSFieldTypeAnnotation(options, field, + /* is_setter_argument = */ false, + /* force_present = */ false, + /* singular_if_not_packed = */ false)); printer->Print( - "$class$.prototype.get$name$ = function() {\n" + "$class$.prototype.$gettername$ = function() {\n" " return /** @type{$type$} */ (\n" " jspb.Message.get$rpt$WrapperField(this, $wrapperclass$, " "$index$$required$));\n" @@ -2431,48 +2634,48 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "\n" "\n", "class", GetMessagePath(options, field->containing_type()), - "name", JSGetterName(options, field), - "type", JSFieldTypeAnnotation(options, field, - /* is_setter_argument = */ false, - /* force_present = */ false, - /* singular_if_not_packed = */ false), - "rpt", (field->is_repeated() ? "Repeated" : ""), - "index", JSFieldIndex(field), - "wrapperclass", SubmessageTypeRef(options, field), - "required", (field->label() == FieldDescriptor::LABEL_REQUIRED ? - ", 1" : "")); + "gettername", "get" + JSGetterName(options, field), "type", + JSFieldTypeAnnotation(options, field, + /* is_setter_argument = */ false, + /* force_present = */ false, + /* singular_if_not_packed = */ false), + "rpt", (field->is_repeated() ? "Repeated" : ""), "index", + JSFieldIndex(field), "wrapperclass", SubmessageTypeRef(options, field), + "required", + (field->label() == FieldDescriptor::LABEL_REQUIRED ? ", 1" : "")); + printer->Annotate("gettername", field); printer->Print( - "/** @param {$optionaltype$} value$returndoc$ */\n" - "$class$.prototype.set$name$ = function(value) {\n" - " jspb.Message.set$oneoftag$$repeatedtag$WrapperField(", + "/**\n" + " * @param {$optionaltype$} value\n" + " * @return {!$class$} returns this\n" + "*/\n" + "$class$.prototype.$settername$ = function(value) {\n" + " return jspb.Message.set$oneoftag$$repeatedtag$WrapperField(", "optionaltype", JSFieldTypeAnnotation(options, field, /* is_setter_argument = */ true, /* force_present = */ false, /* singular_if_not_packed = */ false), - "returndoc", JSReturnDoc(options, field), "class", GetMessagePath(options, field->containing_type()), - "name", JSGetterName(options, field), - "oneoftag", (field->containing_oneof() ? "Oneof" : ""), - "repeatedtag", (field->is_repeated() ? "Repeated" : "")); + "settername", "set" + JSGetterName(options, field), "oneoftag", + (InRealOneof(field) ? "Oneof" : ""), "repeatedtag", + (field->is_repeated() ? "Repeated" : "")); + printer->Annotate("settername", field); printer->Print( - "this, $index$$oneofgroup$, value);$returnvalue$\n" + "this, $index$$oneofgroup$, value);\n" "};\n" "\n" "\n", - "index", JSFieldIndex(field), - "oneofgroup", (field->containing_oneof() ? - (", " + JSOneofArray(options, field)) : ""), - "returnvalue", JSReturnClause(field)); + "index", JSFieldIndex(field), "oneofgroup", + (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : "")); if (field->is_repeated()) { GenerateRepeatedMessageHelperMethods(options, printer, field); } } else { - bool untyped = - false; + bool untyped = false; // Simple (primitive) field, either singular or repeated. @@ -2480,14 +2683,15 @@ void Generator::GenerateClassField(const GeneratorOptions& options, // at this point we "lie" to non-binary users and tell the return // type is always base64 string, pending a LSC to migrate to typed getters. BytesMode bytes_mode = - field->type() == FieldDescriptor::TYPE_BYTES && !options.binary ? - BYTES_B64 : BYTES_DEFAULT; - string typed_annotation = JSFieldTypeAnnotation( - options, field, - /* is_setter_argument = */ false, - /* force_present = */ false, - /* singular_if_not_packed = */ false, - /* bytes_mode = */ bytes_mode); + field->type() == FieldDescriptor::TYPE_BYTES && !options.binary + ? BYTES_B64 + : BYTES_DEFAULT; + std::string typed_annotation = + JSFieldTypeAnnotation(options, field, + /* is_setter_argument = */ false, + /* force_present = */ false, + /* singular_if_not_packed = */ false, + /* bytes_mode = */ bytes_mode); if (untyped) { printer->Print( "/**\n" @@ -2500,23 +2704,20 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "$comment$" " * @return {$type$}\n" " */\n", - "fielddef", FieldDefinition(options, field), - "comment", FieldComments(field, bytes_mode), - "type", typed_annotation); + "fielddef", FieldDefinition(options, field), "comment", + FieldComments(field, bytes_mode), "type", typed_annotation); } - printer->Print( - "$class$.prototype.get$name$ = function() {\n", - "class", GetMessagePath(options, field->containing_type()), - "name", JSGetterName(options, field)); + printer->Print("$class$.prototype.$gettername$ = function() {\n", "class", + GetMessagePath(options, field->containing_type()), + "gettername", "get" + JSGetterName(options, field)); + printer->Annotate("gettername", field); if (untyped) { - printer->Print( - " return "); + printer->Print(" return "); } else { - printer->Print( - " return /** @type {$type$} */ (", - "type", typed_annotation); + printer->Print(" return /** @type {$type$} */ (", "type", + typed_annotation); } bool use_default = !ReturnsNullWhenUnset(options, field); @@ -2553,52 +2754,66 @@ void Generator::GenerateClassField(const GeneratorOptions& options, GenerateBytesWrapper(options, printer, field, BYTES_U8); } - if (untyped) { + printer->Print( + "/**\n" + " * @param {$optionaltype$} value\n" + " * @return {!$class$} returns this\n" + " */\n", + "class", GetMessagePath(options, field->containing_type()), + "optionaltype", + untyped ? "*" + : JSFieldTypeAnnotation(options, field, + /* is_setter_argument = */ true, + /* force_present = */ false, + /* singular_if_not_packed = */ false)); + + if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 && + !field->is_repeated() && !field->is_map() && + !HasFieldPresence(options, field)) { + // Proto3 non-repeated and non-map fields without presence use the + // setProto3*Field function. printer->Print( - "/**\n" - " * @param {*} value$returndoc$\n" - " */\n", - "returndoc", JSReturnDoc(options, field)); + "$class$.prototype.$settername$ = function(value) {\n" + " return jspb.Message.setProto3$typetag$Field(this, $index$, " + "value);" + "\n" + "};\n" + "\n" + "\n", + "class", GetMessagePath(options, field->containing_type()), + "settername", "set" + JSGetterName(options, field), "typetag", + JSTypeTag(field), "index", JSFieldIndex(field)); + printer->Annotate("settername", field); } else { + // Otherwise, use the regular setField function. printer->Print( - "/** @param {$optionaltype$} value$returndoc$ */\n", "optionaltype", - JSFieldTypeAnnotation( - options, field, - /* is_setter_argument = */ true, - /* force_present = */ false, - /* singular_if_not_packed = */ false), - "returndoc", JSReturnDoc(options, field)); + "$class$.prototype.$settername$ = function(value) {\n" + " return jspb.Message.set$oneoftag$Field(this, $index$", + "class", GetMessagePath(options, field->containing_type()), + "settername", "set" + JSGetterName(options, field), "oneoftag", + (InRealOneof(field) ? "Oneof" : ""), "index", JSFieldIndex(field)); + printer->Annotate("settername", field); + printer->Print( + "$oneofgroup$, $type$value$rptvalueinit$$typeclose$);\n" + "};\n" + "\n" + "\n", + "type", + untyped ? "/** @type{string|number|boolean|Array|undefined} */(" : "", + "typeclose", untyped ? ")" : "", "oneofgroup", + (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""), + "rptvalueinit", (field->is_repeated() ? " || []" : "")); } - printer->Print( - "$class$.prototype.set$name$ = function(value) {\n" - " jspb.Message.set$oneoftag$Field(this, $index$", - "class", GetMessagePath(options, field->containing_type()), - "name", JSGetterName(options, field), - "oneoftag", (field->containing_oneof() ? "Oneof" : ""), - "index", JSFieldIndex(field)); - printer->Print( - "$oneofgroup$, $type$value$rptvalueinit$$typeclose$);$returnvalue$\n" - "};\n" - "\n" - "\n", - "type", - untyped ? "/** @type{string|number|boolean|Array|undefined} */(" : "", - "typeclose", untyped ? ")" : "", - "oneofgroup", - (field->containing_oneof() ? (", " + JSOneofArray(options, field)) - : ""), - "returnvalue", JSReturnClause(field), "rptvalueinit", - (field->is_repeated() ? " || []" : "")); if (untyped) { printer->Print( "/**\n" - " * Clears the value.$returndoc$\n" + " * Clears the value.\n" + " * @return {!$class$} returns this\n" " */\n", - "returndoc", JSReturnDoc(options, field)); + "class", GetMessagePath(options, field->containing_type())); } - if (field->is_repeated()) { GenerateRepeatedPrimitiveHelperMethods(options, printer, field, untyped); } @@ -2606,93 +2821,131 @@ void Generator::GenerateClassField(const GeneratorOptions& options, // Generate clearFoo() method for map fields, repeated fields, and other // fields with presence. - if (IsMap(options, field)) { + if (field->is_map()) { + // clang-format off printer->Print( - "$class$.prototype.clear$name$ = function() {\n" - " this.get$name$().clear();$returnvalue$\n" + "/**\n" + " * Clears values from the map. The map will be non-null.\n" + " * @return {!$class$} returns this\n" + " */\n" + "$class$.prototype.$clearername$ = function() {\n" + " this.$gettername$().clear();\n" + " return this;" "};\n" "\n" "\n", "class", GetMessagePath(options, field->containing_type()), - "name", JSGetterName(options, field), - "returnvalue", JSReturnClause(field)); + "clearername", "clear" + JSGetterName(options, field), + "gettername", "get" + JSGetterName(options, field)); + // clang-format on + printer->Annotate("clearername", field); } else if (field->is_repeated() || (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && !field->is_required())) { // Fields where we can delegate to the regular setter. + // clang-format off printer->Print( - "$class$.prototype.clear$name$ = function() {\n" - " this.set$name$($clearedvalue$);$returnvalue$\n" + "/**\n" + " * $jsdoc$\n" + " * @return {!$class$} returns this\n" + " */\n" + "$class$.prototype.$clearername$ = function() {\n" + " return this.$settername$($clearedvalue$);\n" "};\n" "\n" "\n", + "jsdoc", field->is_repeated() + ? "Clears the list making it empty but non-null." + : "Clears the message field making it undefined.", "class", GetMessagePath(options, field->containing_type()), - "name", JSGetterName(options, field), - "clearedvalue", (field->is_repeated() ? "[]" : "undefined"), - "returnvalue", JSReturnClause(field)); + "clearername", "clear" + JSGetterName(options, field), + "settername", "set" + JSGetterName(options, field), + "clearedvalue", (field->is_repeated() ? "[]" : "undefined")); + // clang-format on + printer->Annotate("clearername", field); } else if (HasFieldPresence(options, field)) { // Fields where we can't delegate to the regular setter because it doesn't // accept "undefined" as an argument. + // clang-format off printer->Print( - "$class$.prototype.clear$name$ = function() {\n" - " jspb.Message.set$maybeoneof$Field(this, " - "$index$$maybeoneofgroup$, ", + "/**\n" + " * Clears the field making it undefined.\n" + " * @return {!$class$} returns this\n" + " */\n" + "$class$.prototype.$clearername$ = function() {\n" + " return jspb.Message.set$maybeoneof$Field(this, " + "$index$$maybeoneofgroup$, ", "class", GetMessagePath(options, field->containing_type()), - "name", JSGetterName(options, field), - "maybeoneof", (field->containing_oneof() ? "Oneof" : ""), - "maybeoneofgroup", (field->containing_oneof() ? - (", " + JSOneofArray(options, field)) : ""), + "clearername", "clear" + JSGetterName(options, field), + "maybeoneof", (InRealOneof(field) ? "Oneof" : ""), + "maybeoneofgroup", (InRealOneof(field) + ? (", " + JSOneofArray(options, field)) + : ""), "index", JSFieldIndex(field)); + // clang-format on + printer->Annotate("clearername", field); printer->Print( - "$clearedvalue$);$returnvalue$\n" + "$clearedvalue$);\n" "};\n" "\n" "\n", - "clearedvalue", (field->is_repeated() ? "[]" : "undefined"), - "returnvalue", JSReturnClause(field)); + "clearedvalue", (field->is_repeated() ? "[]" : "undefined")); } if (HasFieldPresence(options, field)) { printer->Print( "/**\n" " * Returns whether this field is set.\n" - " * @return {!boolean}\n" + " * @return {boolean}\n" " */\n" - "$class$.prototype.has$name$ = function() {\n" + "$class$.prototype.$hasername$ = function() {\n" " return jspb.Message.getField(this, $index$) != null;\n" "};\n" "\n" "\n", - "class", GetMessagePath(options, field->containing_type()), - "name", JSGetterName(options, field), - "index", JSFieldIndex(field)); + "class", GetMessagePath(options, field->containing_type()), "hasername", + "has" + JSGetterName(options, field), "index", JSFieldIndex(field)); + printer->Annotate("hasername", field); } } void Generator::GenerateRepeatedPrimitiveHelperMethods( const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field, bool untyped) const { + // clang-format off printer->Print( "/**\n" - " * @param {!$optionaltype$} value\n" + " * @param {$optionaltype$} value\n" " * @param {number=} opt_index\n" + " * @return {!$class$} returns this\n" " */\n" - "$class$.prototype.add$name$ = function(value, opt_index) {\n" - " jspb.Message.addToRepeatedField(this, $index$", - "class", GetMessagePath(options, field->containing_type()), - "name", JSGetterName(options, field, BYTES_DEFAULT, - /* drop_list = */ true), - "optionaltype", JSTypeName(options, field, BYTES_DEFAULT), "index", - JSFieldIndex(field)); + "$class$.prototype.$addername$ = function(value, opt_index) {\n" + " return jspb.Message.addToRepeatedField(this, " + "$index$", + "class", GetMessagePath(options, field->containing_type()), "addername", + "add" + JSGetterName(options, field, BYTES_DEFAULT, + /* drop_list = */ true), + "optionaltype", + JSFieldTypeAnnotation( + options, field, + /* is_setter_argument = */ false, + /* force_present = */ true, + /* singular_if_not_packed = */ false, + BYTES_DEFAULT, + /* force_singular = */ true), + "index", JSFieldIndex(field)); + printer->Annotate("addername", field); printer->Print( - "$oneofgroup$, $type$value$rptvalueinit$$typeclose$, opt_index);\n" + "$oneofgroup$, $type$value$rptvalueinit$$typeclose$, " + "opt_index);\n" "};\n" "\n" "\n", "type", untyped ? "/** @type{string|number|boolean|!Uint8Array} */(" : "", "typeclose", untyped ? ")" : "", "oneofgroup", - (field->containing_oneof() ? (", " + JSOneofArray(options, field)) : ""), + (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""), "rptvalueinit", ""); + // clang-format on } void Generator::GenerateRepeatedMessageHelperMethods( @@ -2704,22 +2957,23 @@ void Generator::GenerateRepeatedMessageHelperMethods( " * @param {number=} opt_index\n" " * @return {!$optionaltype$}\n" " */\n" - "$class$.prototype.add$name$ = function(opt_value, opt_index) {\n" + "$class$.prototype.$addername$ = function(opt_value, opt_index) {\n" " return jspb.Message.addTo$repeatedtag$WrapperField(", - "optionaltype", JSTypeName(options, field, BYTES_DEFAULT), - "class", GetMessagePath(options, field->containing_type()), - "name", JSGetterName(options, field, BYTES_DEFAULT, - /* drop_list = */ true), + "optionaltype", JSTypeName(options, field, BYTES_DEFAULT), "class", + GetMessagePath(options, field->containing_type()), "addername", + "add" + JSGetterName(options, field, BYTES_DEFAULT, + /* drop_list = */ true), "repeatedtag", (field->is_repeated() ? "Repeated" : "")); + printer->Annotate("addername", field); printer->Print( "this, $index$$oneofgroup$, opt_value, $ctor$, opt_index);\n" "};\n" "\n" "\n", "index", JSFieldIndex(field), "oneofgroup", - (field->containing_oneof() ? (", " + JSOneofArray(options, field)) : ""), - "ctor", GetMessagePath(options, field->message_type())); + (InRealOneof(field) ? (", " + JSOneofArray(options, field)) : ""), "ctor", + GetMessagePath(options, field->message_type())); } void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options, @@ -2741,7 +2995,7 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options, "so that it\n" " * works in OPTIMIZED mode.\n" " *\n" - " * @type {!Object.}\n" + " * @type {!Object}\n" " */\n" "$class$.extensions = {};\n" "\n", @@ -2762,7 +3016,7 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options, "so that it\n" " * works in OPTIMIZED mode.\n" " *\n" - " * @type {!Object.}\n" + " * @type {!Object}\n" " */\n" "$class$.extensionsBinary = {};\n" "\n", @@ -2770,7 +3024,6 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options, } } - void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const { @@ -2798,13 +3051,14 @@ void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options, " * @return {!$class$}\n" " */\n" "$class$.deserializeBinaryFromReader = function(msg, reader) {\n" - " while (reader.nextField()) {\n" + " while (reader.nextField()) {\n", + "class", GetMessagePath(options, desc)); + printer->Print( " if (reader.isEndGroup()) {\n" " break;\n" " }\n" " var field = reader.getFieldNumber();\n" - " switch (field) {\n", - "class", GetMessagePath(options, desc)); + " switch (field) {\n"); for (int i = 0; i < desc->field_count(); i++) { if (!IgnoreField(desc->field(i))) { @@ -2812,24 +3066,25 @@ void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options, } } - printer->Print( - " default:\n"); + printer->Print(" default:\n"); if (IsExtendable(desc)) { printer->Print( - " jspb.Message.readBinaryExtension(msg, reader, $extobj$Binary,\n" + " jspb.Message.readBinaryExtension(msg, reader,\n" + " $extobj$Binary,\n" " $class$.prototype.getExtension,\n" " $class$.prototype.setExtension);\n" - " break;\n", - "extobj", JSExtensionsObjectName(options, desc->file(), desc), - "class", GetMessagePath(options, desc)); + " break;\n" + " }\n", + "extobj", JSExtensionsObjectName(options, desc->file(), desc), "class", + GetMessagePath(options, desc)); } else { printer->Print( " reader.skipField();\n" - " break;\n"); + " break;\n" + " }\n"); } printer->Print( - " }\n" " }\n" " return msg;\n" "};\n" @@ -2838,14 +3093,11 @@ void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options, } void Generator::GenerateClassDeserializeBinaryField( - const GeneratorOptions& options, - io::Printer* printer, + const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field) const { + printer->Print(" case $num$:\n", "num", StrCat(field->number())); - printer->Print(" case $num$:\n", - "num", SimpleItoa(field->number())); - - if (IsMap(options, field)) { + if (field->is_map()) { const FieldDescriptor* key_field = MapFieldKey(field); const FieldDescriptor* value_field = MapFieldValue(field); printer->Print( @@ -2853,16 +3105,27 @@ void Generator::GenerateClassDeserializeBinaryField( " reader.readMessage(value, function(message, reader) {\n", "name", JSGetterName(options, field)); - printer->Print(" jspb.Map.deserializeBinary(message, reader, " - "$keyReaderFn$, $valueReaderFn$", - "keyReaderFn", JSBinaryReaderMethodName(options, key_field), - "valueReaderFn", JSBinaryReaderMethodName(options, value_field)); + printer->Print( + " jspb.Map.deserializeBinary(message, reader, " + "$keyReaderFn$, $valueReaderFn$", + "keyReaderFn", JSBinaryReaderMethodName(options, key_field), + "valueReaderFn", JSBinaryReaderMethodName(options, value_field)); if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { printer->Print(", $messageType$.deserializeBinaryFromReader", - "messageType", GetMessagePath(options, value_field->message_type())); + "messageType", + GetMessagePath(options, value_field->message_type())); + } else { + printer->Print(", null"); + } + printer->Print(", $defaultKey$", "defaultKey", JSFieldDefault(key_field)); + if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { + printer->Print(", new $messageType$()", "messageType", + GetMessagePath(options, value_field->message_type())); + } else { + printer->Print(", $defaultValue$", "defaultValue", + JSFieldDefault(value_field)); } - printer->Print(");\n"); printer->Print(" });\n"); } else { @@ -2871,23 +3134,40 @@ void Generator::GenerateClassDeserializeBinaryField( " var value = new $fieldclass$;\n" " reader.read$msgOrGroup$($grpfield$value," "$fieldclass$.deserializeBinaryFromReader);\n", - "fieldclass", SubmessageTypeRef(options, field), - "msgOrGroup", (field->type() == FieldDescriptor::TYPE_GROUP) ? - "Group" : "Message", - "grpfield", (field->type() == FieldDescriptor::TYPE_GROUP) ? - (SimpleItoa(field->number()) + ", ") : ""); + "fieldclass", SubmessageTypeRef(options, field), "msgOrGroup", + (field->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message", + "grpfield", + (field->type() == FieldDescriptor::TYPE_GROUP) + ? (StrCat(field->number()) + ", ") + : ""); + } else if (field->is_packable()) { + printer->Print( + " var values = /** @type {$fieldtype$} */ " + "(reader.isDelimited() " + "? reader.readPacked$reader$() : [reader.read$reader$()]);\n", + "fieldtype", + JSFieldTypeAnnotation(options, field, false, true, + /* singular_if_not_packed */ false, BYTES_U8), + "reader", JSBinaryReaderMethodType(field)); } else { printer->Print( " var value = /** @type {$fieldtype$} */ " "(reader.read$reader$());\n", - "fieldtype", JSFieldTypeAnnotation(options, field, false, true, - /* singular_if_not_packed */ true, - BYTES_U8), + "fieldtype", + JSFieldTypeAnnotation(options, field, false, true, + /* singular_if_not_packed */ true, BYTES_U8), "reader", JSBinaryReadWriteMethodName(field, /* is_writer = */ false)); } - if (field->is_repeated() && !field->is_packed()) { + if (field->is_packable()) { + printer->Print( + " for (var i = 0; i < values.length; i++) {\n" + " msg.add$name$(values[i]);\n" + " }\n", + "name", + JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ true)); + } else if (field->is_repeated()) { printer->Print( " msg.add$name$(value);\n", "name", JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ true)); @@ -2895,9 +3175,8 @@ void Generator::GenerateClassDeserializeBinaryField( // Singular fields, and packed repeated fields, receive a |value| either // as the field's value or as the array of all the field's values; set // this as the field's value directly. - printer->Print( - " msg.set$name$(value);\n", - "name", JSGetterName(options, field)); + printer->Print(" msg.set$name$(value);\n", "name", + JSGetterName(options, field)); } } @@ -2941,8 +3220,8 @@ void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options, printer->Print( " jspb.Message.serializeBinaryExtensions(message, writer,\n" " $extobj$Binary, $class$.prototype.getExtension);\n", - "extobj", JSExtensionsObjectName(options, desc->file(), desc), - "class", GetMessagePath(options, desc)); + "extobj", JSExtensionsObjectName(options, desc->file(), desc), "class", + GetMessagePath(options, desc)); } printer->Print( @@ -2952,42 +3231,37 @@ void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options, } void Generator::GenerateClassSerializeBinaryField( - const GeneratorOptions& options, - io::Printer* printer, + const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field) const { if (HasFieldPresence(options, field) && field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { - string typed_annotation = JSFieldTypeAnnotation( - options, field, - /* is_setter_argument = */ false, - /* force_present = */ false, - /* singular_if_not_packed = */ false, - /* bytes_mode = */ BYTES_DEFAULT); + std::string typed_annotation = + JSFieldTypeAnnotation(options, field, + /* is_setter_argument = */ false, + /* force_present = */ false, + /* singular_if_not_packed = */ false, + /* bytes_mode = */ BYTES_DEFAULT); printer->Print( " f = /** @type {$type$} */ " "(jspb.Message.getField(message, $index$));\n", - "index", JSFieldIndex(field), - "type", typed_annotation); + "index", JSFieldIndex(field), "type", typed_annotation); } else { printer->Print( - " f = message.get$name$($nolazy$);\n", - "name", JSGetterName(options, field, BYTES_U8), + " f = message.get$name$($nolazy$);\n", "name", + JSGetterName(options, field, BYTES_U8), // No lazy creation for maps containers -- fastpath the empty case. - "nolazy", IsMap(options, field) ? "true" : ""); + "nolazy", field->is_map() ? "true" : ""); } // Print an `if (condition)` statement that evaluates to true if the field // goes on the wire. - if (IsMap(options, field)) { - printer->Print( - " if (f && f.getLength() > 0) {\n"); + if (field->is_map()) { + printer->Print(" if (f && f.getLength() > 0) {\n"); } else if (field->is_repeated()) { - printer->Print( - " if (f.length > 0) {\n"); + printer->Print(" if (f.length > 0) {\n"); } else { if (HasFieldPresence(options, field)) { - printer->Print( - " if (f != null) {\n"); + printer->Print(" if (f != null) {\n"); } else { // No field presence: serialize onto the wire only if value is // non-default. Defaults are documented here: @@ -3012,16 +3286,13 @@ void Generator::GenerateClassSerializeBinaryField( case FieldDescriptor::CPPTYPE_ENUM: case FieldDescriptor::CPPTYPE_FLOAT: case FieldDescriptor::CPPTYPE_DOUBLE: - printer->Print( - " if (f !== 0.0) {\n"); + printer->Print(" if (f !== 0.0) {\n"); break; case FieldDescriptor::CPPTYPE_BOOL: - printer->Print( - " if (f) {\n"); + printer->Print(" if (f) {\n"); break; case FieldDescriptor::CPPTYPE_STRING: - printer->Print( - " if (f.length > 0) {\n"); + printer->Print(" if (f.length > 0) {\n"); break; default: assert(false); @@ -3031,19 +3302,19 @@ void Generator::GenerateClassSerializeBinaryField( } // Write the field on the wire. - if (IsMap(options, field)) { + if (field->is_map()) { const FieldDescriptor* key_field = MapFieldKey(field); const FieldDescriptor* value_field = MapFieldValue(field); printer->Print( " f.serializeBinary($index$, writer, " - "$keyWriterFn$, $valueWriterFn$", - "index", SimpleItoa(field->number()), - "keyWriterFn", JSBinaryWriterMethodName(options, key_field), - "valueWriterFn", JSBinaryWriterMethodName(options, value_field)); + "$keyWriterFn$, $valueWriterFn$", + "index", StrCat(field->number()), "keyWriterFn", + JSBinaryWriterMethodName(options, key_field), "valueWriterFn", + JSBinaryWriterMethodName(options, value_field)); if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { - printer->Print(", $messageType$.serializeBinaryToWriter", - "messageType", GetMessagePath(options, value_field->message_type())); + printer->Print(", $messageType$.serializeBinaryToWriter", "messageType", + GetMessagePath(options, value_field->message_type())); } printer->Print(");\n"); @@ -3053,25 +3324,23 @@ void Generator::GenerateClassSerializeBinaryField( " $index$,\n" " f", "method", JSBinaryReadWriteMethodName(field, /* is_writer = */ true), - "index", SimpleItoa(field->number())); + "index", StrCat(field->number())); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && - !IsMap(options, field)) { + !field->is_map()) { printer->Print( ",\n" " $submsg$.serializeBinaryToWriter\n", - "submsg", SubmessageTypeRef(options, field)); + "submsg", SubmessageTypeRef(options, field)); } else { printer->Print("\n"); } - printer->Print( - " );\n"); + printer->Print(" );\n"); } // Close the `if`. - printer->Print( - " }\n"); + printer->Print(" }\n"); } void Generator::GenerateEnum(const GeneratorOptions& options, @@ -3081,16 +3350,26 @@ void Generator::GenerateEnum(const GeneratorOptions& options, "/**\n" " * @enum {number}\n" " */\n" - "$name$ = {\n", - "name", GetEnumPath(options, enumdesc)); + "$enumprefix$$name$ = {\n", + "enumprefix", GetEnumPathPrefix(options, enumdesc), "name", + enumdesc->name()); + printer->Annotate("name", enumdesc); + std::set used_name; + std::vector valid_index; for (int i = 0; i < enumdesc->value_count(); i++) { + if (enumdesc->options().allow_alias() && + !used_name.insert(ToEnumCase(enumdesc->value(i)->name())).second) { + continue; + } + valid_index.push_back(i); + } + for (auto i : valid_index) { const EnumValueDescriptor* value = enumdesc->value(i); - printer->Print( - " $name$: $value$$comma$\n", - "name", ToEnumCase(value->name()), - "value", SimpleItoa(value->number()), - "comma", (i == enumdesc->value_count() - 1) ? "" : ","); + printer->Print(" $name$: $value$$comma$\n", "name", + ToEnumCase(value->name()), "value", StrCat(value->number()), + "comma", (i == valid_index.back()) ? "" : ","); + printer->Annotate("name", value); } printer->Print( @@ -3101,26 +3380,27 @@ void Generator::GenerateEnum(const GeneratorOptions& options, void Generator::GenerateExtension(const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field) const { - string extension_scope = + std::string extension_scope = (field->extension_scope() ? GetMessagePath(options, field->extension_scope()) - : GetFilePath(options, field->file())); + : GetNamespace(options, field->file())); + const std::string extension_object_name = JSObjectFieldName(options, field); printer->Print( "\n" "/**\n" " * A tuple of {field number, class constructor} for the extension\n" - " * field named `$name$`.\n" - " * @type {!jspb.ExtensionFieldInfo.<$extensionType$>}\n" + " * field named `$nameInComment$`.\n" + " * @type {!jspb.ExtensionFieldInfo<$extensionType$>}\n" " */\n" "$class$.$name$ = new jspb.ExtensionFieldInfo(\n", - "name", JSObjectFieldName(options, field), - "class", extension_scope, - "extensionType", JSFieldTypeAnnotation( - options, field, - /* is_setter_argument = */ false, - /* force_present = */ true, - /* singular_if_not_packed = */ false)); + "nameInComment", extension_object_name, "name", extension_object_name, + "class", extension_scope, "extensionType", + JSFieldTypeAnnotation(options, field, + /* is_setter_argument = */ false, + /* force_present = */ true, + /* singular_if_not_packed = */ false)); + printer->Annotate("name", field); printer->Print( " $index$,\n" " {$name$: 0},\n" @@ -3129,13 +3409,14 @@ void Generator::GenerateExtension(const GeneratorOptions& options, "!Object} */ (\n" " $toObject$),\n" " $repeated$);\n", - "index", SimpleItoa(field->number()), - "name", JSObjectFieldName(options, field), - "ctor", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ? - SubmessageTypeRef(options, field) : string("null")), - "toObject", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ? - (SubmessageTypeRef(options, field) + ".toObject") : - string("null")), + "index", StrCat(field->number()), "name", extension_object_name, "ctor", + (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE + ? SubmessageTypeRef(options, field) + : std::string("null")), + "toObject", + (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE + ? (SubmessageTypeRef(options, field) + ".toObject") + : std::string("null")), "repeated", (field->is_repeated() ? "1" : "0")); printer->Print( @@ -3148,8 +3429,8 @@ void Generator::GenerateExtension(const GeneratorOptions& options, " $binaryMessageDeserializeFn$,\n", "extendName", JSExtensionsObjectName(options, field->file(), field->containing_type()), - "index", SimpleItoa(field->number()), "class", extension_scope, "name", - JSObjectFieldName(options, field), "binaryReaderFn", + "index", StrCat(field->number()), "class", extension_scope, "name", + extension_object_name, "binaryReaderFn", JSBinaryReaderMethodName(options, field), "binaryWriterFn", JSBinaryWriterMethodName(options, field), "binaryMessageSerializeFn", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) @@ -3168,16 +3449,15 @@ void Generator::GenerateExtension(const GeneratorOptions& options, "// toObject() will function correctly.\n" "$extendName$[$index$] = $class$.$name$;\n" "\n", - "extendName", JSExtensionsObjectName(options, field->file(), - field->containing_type()), - "index", SimpleItoa(field->number()), - "class", extension_scope, - "name", JSObjectFieldName(options, field)); + "extendName", + JSExtensionsObjectName(options, field->file(), field->containing_type()), + "index", StrCat(field->number()), "class", extension_scope, "name", + extension_object_name); } bool GeneratorOptions::ParseFromOptions( - const std::vector< std::pair< string, string > >& options, - string* error) { + const std::vector >& options, + std::string* error) { for (int i = 0; i < options.size(); i++) { if (options[i].first == "add_require_for_enums") { if (options[i].second != "") { @@ -3214,6 +3494,8 @@ bool GeneratorOptions::ParseFromOptions( import_style = kImportClosure; } else if (options[i].second == "commonjs") { import_style = kImportCommonJs; + } else if (options[i].second == "commonjs_strict") { + import_style = kImportCommonJsStrict; } else if (options[i].second == "browser") { import_style = kImportBrowser; } else if (options[i].second == "es6") { @@ -3230,6 +3512,12 @@ bool GeneratorOptions::ParseFromOptions( return false; } one_output_file_per_input_file = true; + } else if (options[i].first == "annotate_code") { + if (!options[i].second.empty()) { + *error = "Unexpected option value for annotate_code"; + return false; + } + annotate_code = true; } else { // Assume any other option is an output directory, as long as it is a bare // `key` rather than a `key=value` option. @@ -3267,13 +3555,12 @@ GeneratorOptions::OutputMode GeneratorOptions::output_mode() const { return kEverythingInOneFile; } - // Otherwise, we create one output file per type. - return kOneOutputFilePerType; + // Otherwise, we create one output file per SCC. + return kOneOutputFilePerSCC; } void Generator::GenerateFilesInDepOrder( - const GeneratorOptions& options, - io::Printer* printer, + const GeneratorOptions& options, io::Printer* printer, const std::vector& files) const { // Build a std::set over all files so that the DFS can detect when it recurses // into a dep not specified in the user's command line. @@ -3286,10 +3573,8 @@ void Generator::GenerateFilesInDepOrder( } void Generator::GenerateFileAndDeps( - const GeneratorOptions& options, - io::Printer* printer, - const FileDescriptor* root, - std::set* all_files, + const GeneratorOptions& options, io::Printer* printer, + const FileDescriptor* root, std::set* all_files, std::set* generated) const { // Skip if already generated. if (generated->find(root) != generated->end()) { @@ -3311,28 +3596,65 @@ void Generator::GenerateFileAndDeps( } } +bool Generator::GenerateFile(const FileDescriptor* file, + const GeneratorOptions& options, + GeneratorContext* context, + bool use_short_name) const { + std::string filename = + options.output_dir + "/" + + GetJSFilename(options, use_short_name + ? file->name().substr(file->name().rfind('/')) + : file->name()); + std::unique_ptr output(context->Open(filename)); + GOOGLE_CHECK(output); + GeneratedCodeInfo annotations; + io::AnnotationProtoCollector annotation_collector( + &annotations); + io::Printer printer(output.get(), '$', + options.annotate_code ? &annotation_collector : nullptr); + + GenerateFile(options, &printer, file); + + if (printer.failed()) { + return false; + } + + if (options.annotate_code) { + EmbedCodeAnnotations(annotations, &printer); + } + + return true; +} + void Generator::GenerateFile(const GeneratorOptions& options, io::Printer* printer, const FileDescriptor* file) const { - GenerateHeader(options, printer); + GenerateHeader(options, file, printer); // Generate "require" statements. - if (options.import_style == GeneratorOptions::kImportCommonJs) { + if ((options.import_style == GeneratorOptions::kImportCommonJs || + options.import_style == GeneratorOptions::kImportCommonJsStrict)) { printer->Print("var jspb = require('google-protobuf');\n"); printer->Print("var goog = jspb;\n"); - printer->Print("var global = Function('return this')();\n\n"); + + // Do not use global scope in strict mode + if (options.import_style == GeneratorOptions::kImportCommonJsStrict) { + printer->Print("var proto = {};\n\n"); + } else { + printer->Print("var global = Function('return this')();\n\n"); + } for (int i = 0; i < file->dependency_count(); i++) { - const string& name = file->dependency(i)->name(); + const std::string& name = file->dependency(i)->name(); printer->Print( - "var $alias$ = require('$file$');\n", - "alias", ModuleAlias(name), - "file", + "var $alias$ = require('$file$');\n" + "goog.object.extend(proto, $alias$);\n", + "alias", ModuleAlias(name), "file", GetRootPath(file->name(), name) + GetJSFilename(options, name)); } } - std::set provided; + std::set provided; std::set extensions; for (int i = 0; i < file->extension_count(); i++) { // We honor the jspb::ignore option here only when working with @@ -3342,7 +3664,7 @@ void Generator::GenerateFile(const GeneratorOptions& options, IgnoreField(file->extension(i))) { continue; } - provided.insert(GetFilePath(options, file) + "." + + provided.insert(GetNamespace(options, file) + "." + JSObjectFieldName(options, file->extension(i))); extensions.insert(file->extension(i)); } @@ -3364,14 +3686,19 @@ void Generator::GenerateFile(const GeneratorOptions& options, GenerateExtension(options, printer, *it); } - if (options.import_style == GeneratorOptions::kImportCommonJs) { - printer->Print("goog.object.extend(exports, $package$);\n", - "package", GetFilePath(options, file)); + // if provided is empty, do not export anything + if (options.import_style == GeneratorOptions::kImportCommonJs && + !provided.empty()) { + printer->Print("goog.object.extend(exports, $package$);\n", "package", + GetNamespace(options, file)); + } else if (options.import_style == GeneratorOptions::kImportCommonJsStrict) { + printer->Print("goog.object.extend(exports, proto);\n", "package", + GetNamespace(options, file)); } // Emit well-known type methods. for (FileToc* toc = well_known_types_js; toc->name != NULL; toc++) { - string name = string("google/protobuf/") + toc->name; + std::string name = std::string("google/protobuf/") + toc->name; if (name == StripProto(file->name()) + ".js") { printer->Print(toc->data); } @@ -3379,24 +3706,28 @@ void Generator::GenerateFile(const GeneratorOptions& options, } bool Generator::GenerateAll(const std::vector& files, - const string& parameter, + const std::string& parameter, GeneratorContext* context, - string* error) const { - std::vector< std::pair< string, string > > option_pairs; + std::string* error) const { + std::vector > option_pairs; ParseGeneratorParameter(parameter, &option_pairs); GeneratorOptions options; if (!options.ParseFromOptions(option_pairs, error)) { return false; } - if (options.output_mode() == GeneratorOptions::kEverythingInOneFile) { // All output should go in a single file. - string filename = options.output_dir + "/" + options.library + - options.GetFileNameExtension(); - google::protobuf::scoped_ptr output(context->Open(filename)); + std::string filename = options.output_dir + "/" + options.library + + options.GetFileNameExtension(); + std::unique_ptr output(context->Open(filename)); GOOGLE_CHECK(output.get()); - io::Printer printer(output.get(), '$'); + GeneratedCodeInfo annotations; + io::AnnotationProtoCollector annotation_collector( + &annotations); + io::Printer printer( + output.get(), '$', + options.annotate_code ? &annotation_collector : nullptr); // Pull out all extensions -- we need these to generate all // provides/requires. @@ -3408,9 +3739,13 @@ bool Generator::GenerateAll(const std::vector& files, } } - GenerateHeader(options, &printer); + if (files.size() == 1) { + GenerateHeader(options, files[0], &printer); + } else { + GenerateHeader(options, nullptr, &printer); + } - std::set provided; + std::set provided; FindProvides(options, &printer, files, &provided); FindProvidesForFields(options, &printer, extensions, &provided); GenerateProvides(options, &printer, &provided); @@ -3428,55 +3763,105 @@ bool Generator::GenerateAll(const std::vector& files, if (printer.failed()) { return false; } - } else if (options.output_mode() == GeneratorOptions::kOneOutputFilePerType) { - std::set allowed_set; - if (!GenerateJspbAllowedSet(options, files, &allowed_set, error)) { + if (options.annotate_code) { + EmbedCodeAnnotations(annotations, &printer); + } + } else if (options.output_mode() == GeneratorOptions::kOneOutputFilePerSCC) { + std::set have_printed; + SCCAnalyzer analyzer; + std::map allowed_map; + if (!GenerateJspbAllowedMap(options, files, &allowed_map, &analyzer, + error)) { return false; } + bool generated = false; for (int i = 0; i < files.size(); i++) { const FileDescriptor* file = files[i]; + // Force well known type to generate in a whole file. + if (IsWellKnownTypeFile(file)) { + if (!GenerateFile(file, options, context, true)) { + return false; + } + generated = true; + continue; + } for (int j = 0; j < file->message_type_count(); j++) { const Descriptor* desc = file->message_type(j); - if (allowed_set.count(desc) == 0) { + if (have_printed.count(desc) || + allowed_map.count(analyzer.GetSCC(desc)) == 0) { continue; } - string filename = GetMessageFileName(options, desc); - google::protobuf::scoped_ptr output( + generated = true; + const SCC* scc = analyzer.GetSCC(desc); + const std::string& filename = allowed_map[scc]; + std::unique_ptr output( context->Open(filename)); GOOGLE_CHECK(output.get()); - io::Printer printer(output.get(), '$'); - - GenerateHeader(options, &printer); - - std::set provided; - FindProvidesForMessage(options, &printer, desc, &provided); + GeneratedCodeInfo annotations; + io::AnnotationProtoCollector annotation_collector( + &annotations); + io::Printer printer( + output.get(), '$', + options.annotate_code ? &annotation_collector : nullptr); + + GenerateHeader(options, file, &printer); + + std::set provided; + for (auto one_desc : scc->descriptors) { + if (one_desc->containing_type() == nullptr) { + FindProvidesForMessage(options, &printer, one_desc, &provided); + } + } GenerateProvides(options, &printer, &provided); GenerateTestOnly(options, &printer); - GenerateRequiresForMessage(options, &printer, desc, &provided); + GenerateRequiresForSCC(options, &printer, scc, &provided); + + for (auto one_desc : scc->descriptors) { + if (one_desc->containing_type() == nullptr) { + GenerateClassConstructorAndDeclareExtensionFieldInfo( + options, &printer, one_desc); + } + } + for (auto one_desc : scc->descriptors) { + if (one_desc->containing_type() == nullptr) { + GenerateClass(options, &printer, one_desc); + } + } - GenerateClass(options, &printer, desc); + for (auto one_desc : scc->descriptors) { + have_printed.insert(one_desc); + } if (printer.failed()) { return false; } + if (options.annotate_code) { + EmbedCodeAnnotations(annotations, &printer); + } } for (int j = 0; j < file->enum_type_count(); j++) { const EnumDescriptor* enumdesc = file->enum_type(j); - if (allowed_set.count(enumdesc) == 0) { + if (allowed_map.count(enumdesc) == 0) { continue; } - string filename = GetEnumFileName(options, enumdesc); - google::protobuf::scoped_ptr output( + generated = true; + const std::string& filename = allowed_map[enumdesc]; + std::unique_ptr output( context->Open(filename)); GOOGLE_CHECK(output.get()); - io::Printer printer(output.get(), '$'); + GeneratedCodeInfo annotations; + io::AnnotationProtoCollector annotation_collector( + &annotations); + io::Printer printer( + output.get(), '$', + options.annotate_code ? &annotation_collector : nullptr); - GenerateHeader(options, &printer); + GenerateHeader(options, file, &printer); - std::set provided; + std::set provided; FindProvidesForEnum(options, &printer, enumdesc, &provided); GenerateProvides(options, &printer, &provided); GenerateTestOnly(options, &printer); @@ -3486,20 +3871,29 @@ bool Generator::GenerateAll(const std::vector& files, if (printer.failed()) { return false; } + if (options.annotate_code) { + EmbedCodeAnnotations(annotations, &printer); + } } // File-level extensions (message-level extensions are generated under // the enclosing message). - if (allowed_set.count(file) == 1) { - string filename = GetExtensionFileName(options, file); + if (allowed_map.count(file) == 1) { + generated = true; + const std::string& filename = allowed_map[file]; - google::protobuf::scoped_ptr output( + std::unique_ptr output( context->Open(filename)); GOOGLE_CHECK(output.get()); - io::Printer printer(output.get(), '$'); + GeneratedCodeInfo annotations; + io::AnnotationProtoCollector annotation_collector( + &annotations); + io::Printer printer( + output.get(), '$', + options.annotate_code ? &annotation_collector : nullptr); - GenerateHeader(options, &printer); + GenerateHeader(options, file, &printer); - std::set provided; + std::set provided; std::vector fields; for (int j = 0; j < files[i]->extension_count(); j++) { @@ -3518,28 +3912,27 @@ bool Generator::GenerateAll(const std::vector& files, GenerateExtension(options, &printer, files[i]->extension(j)); } } + if (options.annotate_code) { + EmbedCodeAnnotations(annotations, &printer); + } } } + if (!generated) { + std::string filename = options.output_dir + "/" + + "empty_no_content_void_file" + + options.GetFileNameExtension(); + std::unique_ptr output(context->Open(filename)); + } } else /* options.output_mode() == kOneOutputFilePerInputFile */ { // Generate one output file per input (.proto) file. for (int i = 0; i < files.size(); i++) { - const google::protobuf::FileDescriptor* file = files[i]; - - string filename = - options.output_dir + "/" + GetJSFilename(options, file->name()); - google::protobuf::scoped_ptr output(context->Open(filename)); - GOOGLE_CHECK(output.get()); - io::Printer printer(output.get(), '$'); - - GenerateFile(options, &printer, file); - - if (printer.failed()) { + const FileDescriptor* file = files[i]; + if (!GenerateFile(file, options, context, false)) { return false; } } } - return true; } diff --git a/src/google/protobuf/compiler/js/js_generator.h b/src/google/protobuf/compiler/js/js_generator.h old mode 100755 new mode 100644 index 6e932d7f3d0e1..e452020a77c6f --- a/src/google/protobuf/compiler/js/js_generator.h +++ b/src/google/protobuf/compiler/js/js_generator.h @@ -33,13 +33,16 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__ #define GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__ -#include #include +#include #include #include +#include #include +#include + namespace google { namespace protobuf { @@ -49,24 +52,27 @@ class FieldDescriptor; class OneofDescriptor; class FileDescriptor; -namespace io { class Printer; } +namespace io { +class Printer; +} namespace compiler { namespace js { struct GeneratorOptions { // Output path. - string output_dir; + std::string output_dir; // Namespace prefix. - string namespace_prefix; + std::string namespace_prefix; // Enable binary-format support? bool binary; // What style of imports should be used. enum ImportStyle { - kImportClosure, // goog.require() - kImportCommonJs, // require() - kImportBrowser, // no import statements - kImportEs6, // import { member } from '' + kImportClosure, // goog.require() + kImportCommonJs, // require() + kImportCommonJsStrict, // require() with no global export + kImportBrowser, // no import statements + kImportEs6, // import { member } from '' } import_style; GeneratorOptions() @@ -79,14 +85,15 @@ struct GeneratorOptions { library(""), error_on_name_conflict(false), extension(".js"), - one_output_file_per_input_file(false) {} + one_output_file_per_input_file(false), + annotate_code(false) {} bool ParseFromOptions( - const std::vector< std::pair< string, string > >& options, - string* error); + const std::vector >& options, + std::string* error); // Returns the file name extension to use for generated code. - string GetFileNameExtension() const { + std::string GetFileNameExtension() const { return import_style == kImportClosure ? extension : "_pb.js"; } @@ -94,7 +101,7 @@ struct GeneratorOptions { // Create an output file for each input .proto file. kOneOutputFilePerInputFile, // Create an output file for each type. - kOneOutputFilePerType, + kOneOutputFilePerSCC, // Put everything in a single file named by the library option. kEverythingInOneFile, }; @@ -111,69 +118,71 @@ struct GeneratorOptions { bool testonly; // Create a library with name _lib.js rather than a separate .js file // per type? - string library; + std::string library; // Error if there are two types that would generate the same output file? bool error_on_name_conflict; // The extension to use for output file names. - string extension; + std::string extension; // Create a separate output file for each input file? bool one_output_file_per_input_file; + // If true, we should append annotations as comments on the last line for + // generated .js file. Annotations used by tools like https://kythe.io + // to provide cross-references between .js and .proto files. Annotations + // are encoded as base64 proto of GeneratedCodeInfo message (see + // descriptor.proto). + bool annotate_code; }; // CodeGenerator implementation which generates a JavaScript source file and // header. If you create your own protocol compiler binary and you want it to // support JavaScript output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT Generator : public CodeGenerator { +class PROTOC_EXPORT Generator : public CodeGenerator { public: Generator() {} virtual ~Generator() {} - virtual bool Generate(const FileDescriptor* file, - const string& parameter, - GeneratorContext* context, - string* error) const { + bool Generate(const FileDescriptor* file, const std::string& parameter, + GeneratorContext* context, std::string* error) const override { *error = "Unimplemented Generate() method. Call GenerateAll() instead."; return false; } - virtual bool HasGenerateAll() const { return true; } + bool HasGenerateAll() const override { return true; } - virtual bool GenerateAll(const std::vector& files, - const string& parameter, - GeneratorContext* context, - string* error) const; + bool GenerateAll(const std::vector& files, + const std::string& parameter, GeneratorContext* context, + std::string* error) const override; + + uint64 GetSupportedFeatures() const override { + return FEATURE_PROTO3_OPTIONAL; + } private: void GenerateHeader(const GeneratorOptions& options, - io::Printer* printer) const; + const FileDescriptor* file, io::Printer* printer) const; // Generate goog.provides() calls. - void FindProvides(const GeneratorOptions& options, - io::Printer* printer, + void FindProvides(const GeneratorOptions& options, io::Printer* printer, const std::vector& file, - std::set* provided) const; + std::set* provided) const; void FindProvidesForFile(const GeneratorOptions& options, - io::Printer* printer, - const FileDescriptor* file, - std::set* provided) const; + io::Printer* printer, const FileDescriptor* file, + std::set* provided) const; void FindProvidesForMessage(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc, - std::set* provided) const; + io::Printer* printer, const Descriptor* desc, + std::set* provided) const; void FindProvidesForEnum(const GeneratorOptions& options, - io::Printer* printer, - const EnumDescriptor* enumdesc, - std::set* provided) const; + io::Printer* printer, const EnumDescriptor* enumdesc, + std::set* provided) const; // For extension fields at file scope. void FindProvidesForFields(const GeneratorOptions& options, io::Printer* printer, const std::vector& fields, - std::set* provided) const; + std::set* provided) const; // Print the goog.provides() found by the methods above. - void GenerateProvides(const GeneratorOptions& options, - io::Printer* printer, - std::set* provided) const; + void GenerateProvides(const GeneratorOptions& options, io::Printer* printer, + std::set* provided) const; // Generate goog.setTestOnly() if indicated. void GenerateTestOnly(const GeneratorOptions& options, @@ -183,37 +192,40 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void GenerateRequiresForLibrary( const GeneratorOptions& options, io::Printer* printer, const std::vector& files, - std::set* provided) const; - void GenerateRequiresForMessage(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc, - std::set* provided) const; + std::set* provided) const; + void GenerateRequiresForSCC(const GeneratorOptions& options, + io::Printer* printer, const SCC* scc, + std::set* provided) const; // For extension fields at file scope. void GenerateRequiresForExtensions( const GeneratorOptions& options, io::Printer* printer, const std::vector& fields, - std::set* provided) const; + std::set* provided) const; void GenerateRequiresImpl(const GeneratorOptions& options, - io::Printer* printer, std::set* required, - std::set* forwards, - std::set* provided, bool require_jspb, + io::Printer* printer, + std::set* required, + std::set* forwards, + std::set* provided, bool require_jspb, bool require_extension, bool require_map) const; void FindRequiresForMessage(const GeneratorOptions& options, const Descriptor* desc, - std::set* required, - std::set* forwards, + std::set* required, + std::set* forwards, bool* have_message) const; void FindRequiresForField(const GeneratorOptions& options, const FieldDescriptor* field, - std::set* required, - std::set* forwards) const; + std::set* required, + std::set* forwards) const; void FindRequiresForExtension(const GeneratorOptions& options, const FieldDescriptor* field, - std::set* required, - std::set* forwards) const; - - void GenerateFile(const GeneratorOptions& options, - io::Printer* printer, + std::set* required, + std::set* forwards) const; + // Generate all things in a proto file into one file. + // If use_short_name is true, the generated file's name will only be short + // name that without directory, otherwise filename equals file->name() + bool GenerateFile(const FileDescriptor* file, const GeneratorOptions& options, + GeneratorContext* context, bool use_short_name) const; + void GenerateFile(const GeneratorOptions& options, io::Printer* printer, const FileDescriptor* file) const; // Generate definitions for all message classes and enums in all files, @@ -223,8 +235,7 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { const std::vector& file) const; // Helper for above. void GenerateFileAndDeps(const GeneratorOptions& options, - io::Printer* printer, - const FileDescriptor* root, + io::Printer* printer, const FileDescriptor* root, std::set* all_files, std::set* generated) const; @@ -239,8 +250,7 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { bool use_default) const; // Generate definition for one class. - void GenerateClass(const GeneratorOptions& options, - io::Printer* printer, + void GenerateClass(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const; void GenerateClassConstructor(const GeneratorOptions& options, io::Printer* printer, @@ -248,12 +258,17 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void GenerateClassFieldInfo(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const; - void GenerateClassXid(const GeneratorOptions& options, - io::Printer* printer, + void GenerateClassConstructorAndDeclareExtensionFieldInfo( + const GeneratorOptions& options, io::Printer* printer, + const Descriptor* desc) const; + void GenerateClassXid(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const; void GenerateOneofCaseDefinition(const GeneratorOptions& options, io::Printer* printer, const OneofDescriptor* oneof) const; + void GenerateObjectTypedef(const GeneratorOptions& options, + io::Printer* printer, + const Descriptor* desc) const; void GenerateClassToObject(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const; @@ -266,17 +281,12 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void GenerateClassFieldFromObject(const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field) const; - void GenerateClassClone(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const; void GenerateClassRegistration(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const; void GenerateClassFields(const GeneratorOptions& options, - io::Printer* printer, - const Descriptor* desc) const; - void GenerateClassField(const GeneratorOptions& options, - io::Printer* printer, + io::Printer* printer, const Descriptor* desc) const; + void GenerateClassField(const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* desc) const; void GenerateClassExtensionFieldInfo(const GeneratorOptions& options, io::Printer* printer, @@ -298,13 +308,11 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { const FieldDescriptor* field) const; // Generate definition for one enum. - void GenerateEnum(const GeneratorOptions& options, - io::Printer* printer, + void GenerateEnum(const GeneratorOptions& options, io::Printer* printer, const EnumDescriptor* enumdesc) const; // Generate an extension definition. - void GenerateExtension(const GeneratorOptions& options, - io::Printer* printer, + void GenerateExtension(const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field) const; // Generate addFoo() method for repeated primitive fields. @@ -324,6 +332,8 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { } // namespace js } // namespace compiler } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/js/well_known_types/any.js b/src/google/protobuf/compiler/js/well_known_types/any.js deleted file mode 100644 index d7ca6e3a40a85..0000000000000 --- a/src/google/protobuf/compiler/js/well_known_types/any.js +++ /dev/null @@ -1,80 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -/* This code will be inserted into generated code for - * google/protobuf/any.proto. */ - -/** - * Returns the type name contained in this instance, if any. - * @return {string|undefined} - */ -proto.google.protobuf.Any.prototype.getTypeName = function() { - return this.getTypeUrl().split('/').pop(); -}; - - -/** - * Packs the given message instance into this Any. - * @param {!Uint8Array} serialized The serialized data to pack. - * @param {string} name The type name of this message object. - * @param {string=} opt_typeUrlPrefix the type URL prefix. - */ -proto.google.protobuf.Any.prototype.pack = function(serialized, name, - opt_typeUrlPrefix) { - if (!opt_typeUrlPrefix) { - opt_typeUrlPrefix = 'type.googleapis.com/'; - } - - if (opt_typeUrlPrefix.substr(-1) != '/') { - this.setTypeUrl(opt_typeUrlPrefix + '/' + name); - } else { - this.setTypeUrl(opt_typeUrlPrefix + name); - } - - this.setValue(serialized); -}; - - -/** - * @template T - * Unpacks this Any into the given message object. - * @param {function(Uint8Array):T} deserialize Function that will deserialize - * the binary data properly. - * @param {string} name The expected type name of this message object. - * @return {?T} If the name matched the expected name, returns the deserialized - * object, otherwise returns null. - */ -proto.google.protobuf.Any.prototype.unpack = function(deserialize, name) { - if (this.getTypeName() == name) { - return deserialize(this.getValue_asU8()); - } else { - return null; - } -}; diff --git a/src/google/protobuf/compiler/js/well_known_types/struct.js b/src/google/protobuf/compiler/js/well_known_types/struct.js deleted file mode 100644 index 30e3d02a6b16e..0000000000000 --- a/src/google/protobuf/compiler/js/well_known_types/struct.js +++ /dev/null @@ -1,168 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -/* This code will be inserted into generated code for - * google/protobuf/struct.proto. */ - -/** - * Typedef representing plain JavaScript values that can go into a - * Struct. - * @typedef {null|number|string|boolean|Array|Object} - */ -proto.google.protobuf.JavaScriptValue; - - -/** - * Converts this Value object to a plain JavaScript value. - * @return {?proto.google.protobuf.JavaScriptValue} a plain JavaScript - * value representing this Struct. - */ -proto.google.protobuf.Value.prototype.toJavaScript = function() { - var kindCase = proto.google.protobuf.Value.KindCase; - switch (this.getKindCase()) { - case kindCase.NULL_VALUE: - return null; - case kindCase.NUMBER_VALUE: - return this.getNumberValue(); - case kindCase.STRING_VALUE: - return this.getStringValue(); - case kindCase.BOOL_VALUE: - return this.getBoolValue(); - case kindCase.STRUCT_VALUE: - return this.getStructValue().toJavaScript(); - case kindCase.LIST_VALUE: - return this.getListValue().toJavaScript(); - default: - throw new Error('Unexpected struct type'); - } -}; - - -/** - * Converts this JavaScript value to a new Value proto. - * @param {!proto.google.protobuf.JavaScriptValue} value The value to - * convert. - * @return {!proto.google.protobuf.Value} The newly constructed value. - */ -proto.google.protobuf.Value.fromJavaScript = function(value) { - var ret = new proto.google.protobuf.Value(); - switch (goog.typeOf(value)) { - case 'string': - ret.setStringValue(/** @type {string} */ (value)); - break; - case 'number': - ret.setNumberValue(/** @type {number} */ (value)); - break; - case 'boolean': - ret.setBoolValue(/** @type {boolean} */ (value)); - break; - case 'null': - ret.setNullValue(proto.google.protobuf.NullValue.NULL_VALUE); - break; - case 'array': - ret.setListValue(proto.google.protobuf.ListValue.fromJavaScript( - /** @type{!Array} */ (value))); - break; - case 'object': - ret.setStructValue(proto.google.protobuf.Struct.fromJavaScript( - /** @type{!Object} */ (value))); - break; - default: - throw new Error('Unexpected struct type.'); - } - - return ret; -}; - - -/** - * Converts this ListValue object to a plain JavaScript array. - * @return {!Array} a plain JavaScript array representing this List. - */ -proto.google.protobuf.ListValue.prototype.toJavaScript = function() { - var ret = []; - var values = this.getValuesList(); - - for (var i = 0; i < values.length; i++) { - ret[i] = values[i].toJavaScript(); - } - - return ret; -}; - - -/** - * Constructs a ListValue protobuf from this plain JavaScript array. - * @param {!Array} array a plain JavaScript array - * @return {proto.google.protobuf.ListValue} a new ListValue object - */ -proto.google.protobuf.ListValue.fromJavaScript = function(array) { - var ret = new proto.google.protobuf.ListValue(); - - for (var i = 0; i < array.length; i++) { - ret.addValues(proto.google.protobuf.Value.fromJavaScript(array[i])); - } - - return ret; -}; - - -/** - * Converts this Struct object to a plain JavaScript object. - * @return {!Object} a plain - * JavaScript object representing this Struct. - */ -proto.google.protobuf.Struct.prototype.toJavaScript = function() { - var ret = {}; - - this.getFieldsMap().forEach(function(value, key) { - ret[key] = value.toJavaScript(); - }); - - return ret; -}; - - -/** - * Constructs a Struct protobuf from this plain JavaScript object. - * @param {!Object} obj a plain JavaScript object - * @return {proto.google.protobuf.Struct} a new Struct object - */ -proto.google.protobuf.Struct.fromJavaScript = function(obj) { - var ret = new proto.google.protobuf.Struct(); - var map = ret.getFieldsMap(); - - for (var property in obj) { - var val = obj[property]; - map.set(property, proto.google.protobuf.Value.fromJavaScript(val)); - } - - return ret; -}; diff --git a/src/google/protobuf/compiler/js/well_known_types/timestamp.js b/src/google/protobuf/compiler/js/well_known_types/timestamp.js deleted file mode 100644 index b7e43f1967529..0000000000000 --- a/src/google/protobuf/compiler/js/well_known_types/timestamp.js +++ /dev/null @@ -1,53 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -/* This code will be inserted into generated code for - * google/protobuf/timestamp.proto. */ - -/** - * Returns a JavaScript 'Date' object corresponding to this Timestamp. - * @return {!Date} - */ -proto.google.protobuf.Timestamp.prototype.toDate = function() { - var seconds = this.getSeconds(); - var nanos = this.getNanos(); - - return new Date((seconds * 1000) + (nanos / 1000000)); -}; - - -/** - * Sets the value of this Timestamp object to be the given Date. - * @param {!Date} value The value to set. - */ -proto.google.protobuf.Timestamp.prototype.fromDate = function(value) { - this.setSeconds(Math.floor(value.getTime() / 1000)); - this.setNanos(value.getMilliseconds() * 1000000); -}; diff --git a/src/google/protobuf/compiler/js/well_known_types_embed.cc b/src/google/protobuf/compiler/js/well_known_types_embed.cc new file mode 100644 index 0000000000000..5cb73657e7223 --- /dev/null +++ b/src/google/protobuf/compiler/js/well_known_types_embed.cc @@ -0,0 +1,270 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +struct FileToc well_known_types_js[] = { + {"any.js", + "/* This code will be inserted into generated code for\n" + " * google/protobuf/any.proto. */\n" + "\n" + "/**\n" + " * Returns the type name contained in this instance, if any.\n" + " * @return {string|undefined}\n" + " */\n" + "proto.google.protobuf.Any.prototype.getTypeName = function() {\n" + " return this.getTypeUrl().split('/').pop();\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Packs the given message instance into this Any.\n" + " * For binary format usage only.\n" + " * @param {!Uint8Array} serialized The serialized data to pack.\n" + " * @param {string} name The type name of this message object.\n" + " * @param {string=} opt_typeUrlPrefix the type URL prefix.\n" + " */\n" + "proto.google.protobuf.Any.prototype.pack = function(serialized, name,\n" + " opt_typeUrlPrefix) " + "{\n" + " if (!opt_typeUrlPrefix) {\n" + " opt_typeUrlPrefix = 'type.googleapis.com/';\n" + " }\n" + "\n" + " if (opt_typeUrlPrefix.substr(-1) != '/') {\n" + " this.setTypeUrl(opt_typeUrlPrefix + '/' + name);\n" + " } else {\n" + " this.setTypeUrl(opt_typeUrlPrefix + name);\n" + " }\n" + "\n" + " this.setValue(serialized);\n" + "};\n" + "\n" + "\n" + "/**\n" + " * @template T\n" + " * Unpacks this Any into the given message object.\n" + " * @param {function(Uint8Array):T} deserialize Function that will " + "deserialize\n" + " * the binary data properly.\n" + " * @param {string} name The expected type name of this message object.\n" + " * @return {?T} If the name matched the expected name, returns the " + "deserialized\n" + " * object, otherwise returns null.\n" + " */\n" + "proto.google.protobuf.Any.prototype.unpack = function(deserialize, name) " + "{\n" + " if (this.getTypeName() == name) {\n" + " return deserialize(this.getValue_asU8());\n" + " } else {\n" + " return null;\n" + " }\n" + "};\n" + }, + {"timestamp.js", + "/* This code will be inserted into generated code for\n" + " * google/protobuf/timestamp.proto. */\n" + "\n" + "/**\n" + " * Returns a JavaScript 'Date' object corresponding to this Timestamp.\n" + " * @return {!Date}\n" + " */\n" + "proto.google.protobuf.Timestamp.prototype.toDate = function() {\n" + " var seconds = this.getSeconds();\n" + " var nanos = this.getNanos();\n" + "\n" + " return new Date((seconds * 1000) + (nanos / 1000000));\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Sets the value of this Timestamp object to be the given Date.\n" + " * @param {!Date} value The value to set.\n" + " */\n" + "proto.google.protobuf.Timestamp.prototype.fromDate = function(value) {\n" + " this.setSeconds(Math.floor(value.getTime() / 1000));\n" + " this.setNanos(value.getMilliseconds() * 1000000);\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Factory method that returns a Timestamp object with value equal to\n" + " * the given Date.\n" + " * @param {!Date} value The value to set.\n" + " * @return {!proto.google.protobuf.Timestamp}\n" + " */\n" + "proto.google.protobuf.Timestamp.fromDate = function(value) {\n" + " var timestamp = new proto.google.protobuf.Timestamp();\n" + " timestamp.fromDate(value);\n" + " return timestamp;\n" + "};\n"}, + {"struct.js", + "/* This code will be inserted into generated code for\n" + " * google/protobuf/struct.proto. */\n" + "\n" + "/**\n" + " * Typedef representing plain JavaScript values that can go into a\n" + " * Struct.\n" + " * @typedef {null|number|string|boolean|Array|Object}\n" + " */\n" + "proto.google.protobuf.JavaScriptValue;\n" + "\n" + "\n" + "/**\n" + " * Converts this Value object to a plain JavaScript value.\n" + " * @return {?proto.google.protobuf.JavaScriptValue} a plain JavaScript\n" + " * value representing this Struct.\n" + " */\n" + "proto.google.protobuf.Value.prototype.toJavaScript = function() {\n" + " var kindCase = proto.google.protobuf.Value.KindCase;\n" + " switch (this.getKindCase()) {\n" + " case kindCase.NULL_VALUE:\n" + " return null;\n" + " case kindCase.NUMBER_VALUE:\n" + " return this.getNumberValue();\n" + " case kindCase.STRING_VALUE:\n" + " return this.getStringValue();\n" + " case kindCase.BOOL_VALUE:\n" + " return this.getBoolValue();\n" + " case kindCase.STRUCT_VALUE:\n" + " return this.getStructValue().toJavaScript();\n" + " case kindCase.LIST_VALUE:\n" + " return this.getListValue().toJavaScript();\n" + " default:\n" + " throw new Error('Unexpected struct type');\n" + " }\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Converts this JavaScript value to a new Value proto.\n" + " * @param {!proto.google.protobuf.JavaScriptValue} value The value to\n" + " * convert.\n" + " * @return {!proto.google.protobuf.Value} The newly constructed value.\n" + " */\n" + "proto.google.protobuf.Value.fromJavaScript = function(value) {\n" + " var ret = new proto.google.protobuf.Value();\n" + " switch (goog.typeOf(value)) {\n" + " case 'string':\n" + " ret.setStringValue(/** @type {string} */ (value));\n" + " break;\n" + " case 'number':\n" + " ret.setNumberValue(/** @type {number} */ (value));\n" + " break;\n" + " case 'boolean':\n" + " ret.setBoolValue(/** @type {boolean} */ (value));\n" + " break;\n" + " case 'null':\n" + " ret.setNullValue(proto.google.protobuf.NullValue.NULL_VALUE);\n" + " break;\n" + " case 'array':\n" + " ret.setListValue(proto.google.protobuf.ListValue.fromJavaScript(\n" + " /** @type{!Array} */ (value)));\n" + " break;\n" + " case 'object':\n" + " ret.setStructValue(proto.google.protobuf.Struct.fromJavaScript(\n" + " /** @type{!Object} */ (value)));\n" + " break;\n" + " default:\n" + " throw new Error('Unexpected struct type.');\n" + " }\n" + "\n" + " return ret;\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Converts this ListValue object to a plain JavaScript array.\n" + " * @return {!Array} a plain JavaScript array representing this List.\n" + " */\n" + "proto.google.protobuf.ListValue.prototype.toJavaScript = function() {\n" + " var ret = [];\n" + " var values = this.getValuesList();\n" + "\n" + " for (var i = 0; i < values.length; i++) {\n" + " ret[i] = values[i].toJavaScript();\n" + " }\n" + "\n" + " return ret;\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Constructs a ListValue protobuf from this plain JavaScript array.\n" + " * @param {!Array} array a plain JavaScript array\n" + " * @return {proto.google.protobuf.ListValue} a new ListValue object\n" + " */\n" + "proto.google.protobuf.ListValue.fromJavaScript = function(array) {\n" + " var ret = new proto.google.protobuf.ListValue();\n" + "\n" + " for (var i = 0; i < array.length; i++) {\n" + " " + "ret.addValues(proto.google.protobuf.Value.fromJavaScript(array[i]));\n" + " }\n" + "\n" + " return ret;\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Converts this Struct object to a plain JavaScript object.\n" + " * @return {!Object} a " + "plain\n" + " * JavaScript object representing this Struct.\n" + " */\n" + "proto.google.protobuf.Struct.prototype.toJavaScript = function() {\n" + " var ret = {};\n" + "\n" + " this.getFieldsMap().forEach(function(value, key) {\n" + " ret[key] = value.toJavaScript();\n" + " });\n" + "\n" + " return ret;\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Constructs a Struct protobuf from this plain JavaScript object.\n" + " * @param {!Object} obj a plain JavaScript object\n" + " * @return {proto.google.protobuf.Struct} a new Struct object\n" + " */\n" + "proto.google.protobuf.Struct.fromJavaScript = function(obj) {\n" + " var ret = new proto.google.protobuf.Struct();\n" + " var map = ret.getFieldsMap();\n" + "\n" + " for (var property in obj) {\n" + " var val = obj[property];\n" + " map.set(property, proto.google.protobuf.Value.fromJavaScript(val));\n" + " }\n" + "\n" + " return ret;\n" + "};\n"}, + {NULL, NULL} // Terminate the list. +}; diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc index 680d642857bd9..895b47dee65d3 100644 --- a/src/google/protobuf/compiler/main.cc +++ b/src/google/protobuf/compiler/main.cc @@ -28,79 +28,81 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Author: kenton@google.com (Kenton Varda) - -#include #include - -#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP -#include #include -#endif // ! OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP - -#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP -#include -#include #include +#include +#include +#include #include #include #include -#endif // ! OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP -int main(int argc, char* argv[]) { +#include - google::protobuf::compiler::CommandLineInterface cli; +namespace google { +namespace protobuf { +namespace compiler { + +int ProtobufMain(int argc, char* argv[]) { + + CommandLineInterface cli; cli.AllowPlugins("protoc-"); // Proto2 C++ - google::protobuf::compiler::cpp::CppGenerator cpp_generator; + cpp::CppGenerator cpp_generator; cli.RegisterGenerator("--cpp_out", "--cpp_opt", &cpp_generator, "Generate C++ header and source."); -#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP +#ifdef GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE + cpp_generator.set_opensource_runtime(true); + cpp_generator.set_runtime_include_base(GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE); +#endif + // Proto2 Java - google::protobuf::compiler::java::JavaGenerator java_generator; + java::JavaGenerator java_generator; cli.RegisterGenerator("--java_out", "--java_opt", &java_generator, "Generate Java source file."); -#endif // !OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP -#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP + // Proto2 Python - google::protobuf::compiler::python::Generator py_generator; - cli.RegisterGenerator("--python_out", &py_generator, + python::Generator py_generator; + cli.RegisterGenerator("--python_out", "--python_opt", &py_generator, "Generate Python source file."); - // Java Nano - google::protobuf::compiler::javanano::JavaNanoGenerator javanano_generator; - cli.RegisterGenerator("--javanano_out", &javanano_generator, - "Generate Java Nano source file."); - // PHP - google::protobuf::compiler::php::Generator php_generator; - cli.RegisterGenerator("--php_out", &php_generator, + php::Generator php_generator; + cli.RegisterGenerator("--php_out", "--php_opt", &php_generator, "Generate PHP source file."); // Ruby - google::protobuf::compiler::ruby::Generator rb_generator; - cli.RegisterGenerator("--ruby_out", &rb_generator, + ruby::Generator rb_generator; + cli.RegisterGenerator("--ruby_out", "--ruby_opt", &rb_generator, "Generate Ruby source file."); // CSharp - google::protobuf::compiler::csharp::Generator csharp_generator; + csharp::Generator csharp_generator; cli.RegisterGenerator("--csharp_out", "--csharp_opt", &csharp_generator, "Generate C# source file."); - // Objective C - google::protobuf::compiler::objectivec::ObjectiveCGenerator objc_generator; + // Objective-C + objectivec::ObjectiveCGenerator objc_generator; cli.RegisterGenerator("--objc_out", "--objc_opt", &objc_generator, - "Generate Objective C header and source."); + "Generate Objective-C header and source."); // JavaScript - google::protobuf::compiler::js::Generator js_generator; - cli.RegisterGenerator("--js_out", &js_generator, + js::Generator js_generator; + cli.RegisterGenerator("--js_out", "--js_opt", &js_generator, "Generate JavaScript source."); -#endif // !OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP return cli.Run(argc, argv); } + +} // namespace compiler +} // namespace protobuf +} // namespace google + +int main(int argc, char* argv[]) { + return PROTOBUF_NAMESPACE_ID::compiler::ProtobufMain(argc, argv); +} diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc index cc660f4abeca4..3abb5c0b13516 100644 --- a/src/google/protobuf/compiler/mock_code_generator.cc +++ b/src/google/protobuf/compiler/mock_code_generator.cc @@ -33,14 +33,11 @@ #include #include + #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include - #include #include @@ -54,15 +51,15 @@ #include #include #include -#include #include +#include -#ifdef major -#undef major -#endif -#ifdef minor -#undef minor -#endif +#ifdef major +#undef major +#endif +#ifdef minor +#undef minor +#endif namespace google { namespace protobuf { @@ -70,8 +67,9 @@ namespace compiler { // Returns the list of the names of files in all_files in the form of a // comma-separated string. -string CommaSeparatedList(const std::vector all_files) { - std::vector names; +std::string CommaSeparatedList( + const std::vector& all_files) { + std::vector names; for (size_t i = 0; i < all_files.size(); i++) { names.push_back(all_files[i]->name()); } @@ -85,25 +83,31 @@ static const char* kFirstInsertionPoint = static const char* kSecondInsertionPoint = " # @@protoc_insertion_point(second_mock_insertion_point) is here\n"; -MockCodeGenerator::MockCodeGenerator(const string& name) - : name_(name) {} +MockCodeGenerator::MockCodeGenerator(const std::string& name) : name_(name) {} MockCodeGenerator::~MockCodeGenerator() {} +uint64_t MockCodeGenerator::GetSupportedFeatures() const { + uint64 all_features = CodeGenerator::FEATURE_PROTO3_OPTIONAL; + return all_features & ~suppressed_features_; +} + +void MockCodeGenerator::SuppressFeatures(uint64 features) { + suppressed_features_ = features; +} + void MockCodeGenerator::ExpectGenerated( - const string& name, - const string& parameter, - const string& insertions, - const string& file, - const string& first_message_name, - const string& first_parsed_file_name, - const string& output_directory) { - string content; + const std::string& name, const std::string& parameter, + const std::string& insertions, const std::string& file, + const std::string& first_message_name, + const std::string& first_parsed_file_name, + const std::string& output_directory) { + std::string content; GOOGLE_CHECK_OK( File::GetContents(output_directory + "/" + GetOutputFileName(name, file), &content, true)); - std::vector lines = + std::vector lines = Split(content, "\n", true); while (!lines.empty() && lines.back().empty()) { @@ -113,22 +117,22 @@ void MockCodeGenerator::ExpectGenerated( lines[i] += "\n"; } - std::vector insertion_list; + std::vector insertion_list; if (!insertions.empty()) { - SplitStringUsing(insertions, ",", &insertion_list); + insertion_list = Split(insertions, ",", true); } EXPECT_EQ(lines.size(), 3 + insertion_list.size() * 2); - EXPECT_EQ(GetOutputFileContent(name, parameter, file, - first_parsed_file_name, first_message_name), + EXPECT_EQ(GetOutputFileContent(name, parameter, file, first_parsed_file_name, + first_message_name), lines[0]); EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]); EXPECT_EQ(kSecondInsertionPoint, lines[2 + insertion_list.size() * 2]); for (size_t i = 0; i < insertion_list.size(); i++) { - EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert", - file, file, first_message_name), + EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert", file, + file, first_message_name), lines[1 + i]); // Second insertion point is indented, so the inserted text should // automatically be indented too. @@ -139,9 +143,9 @@ void MockCodeGenerator::ExpectGenerated( } namespace { -void CheckSingleAnnotation(const string& expected_file, - const string& expected_text, - const string& file_content, +void CheckSingleAnnotation(const std::string& expected_file, + const std::string& expected_text, + const std::string& file_content, const GeneratedCodeInfo::Annotation& annotation) { EXPECT_EQ(expected_file, annotation.source_file()); ASSERT_GE(file_content.size(), annotation.begin()); @@ -154,36 +158,55 @@ void CheckSingleAnnotation(const string& expected_file, } // anonymous namespace void MockCodeGenerator::CheckGeneratedAnnotations( - const string& name, const string& file, const string& output_directory) { - string file_content; + const std::string& name, const std::string& file, + const std::string& output_directory) { + std::string file_content; GOOGLE_CHECK_OK( File::GetContents(output_directory + "/" + GetOutputFileName(name, file), &file_content, true)); - string meta_content; + std::string meta_content; GOOGLE_CHECK_OK(File::GetContents( - output_directory + "/" + GetOutputFileName(name, file) + ".meta", + output_directory + "/" + GetOutputFileName(name, file) + ".pb.meta", &meta_content, true)); GeneratedCodeInfo annotations; GOOGLE_CHECK(TextFormat::ParseFromString(meta_content, &annotations)); - ASSERT_EQ(3, annotations.annotation_size()); + ASSERT_EQ(7, annotations.annotation_size()); + CheckSingleAnnotation("first_annotation", "first", file_content, annotations.annotation(0)); + CheckSingleAnnotation("first_path", + "test_generator: first_insert,\n foo.proto,\n " + "MockCodeGenerator_Annotate,\n foo.proto\n", + file_content, annotations.annotation(1)); + CheckSingleAnnotation("first_path", + "test_plugin: first_insert,\n foo.proto,\n " + "MockCodeGenerator_Annotate,\n foo.proto\n", + file_content, annotations.annotation(2)); CheckSingleAnnotation("second_annotation", "second", file_content, - annotations.annotation(1)); + annotations.annotation(3)); + // This annotated text has changed because it was inserted at an indented + // insertion point. + CheckSingleAnnotation("second_path", + "test_generator: second_insert,\n foo.proto,\n " + "MockCodeGenerator_Annotate,\n foo.proto\n", + file_content, annotations.annotation(4)); + CheckSingleAnnotation("second_path", + "test_plugin: second_insert,\n foo.proto,\n " + "MockCodeGenerator_Annotate,\n foo.proto\n", + file_content, annotations.annotation(5)); CheckSingleAnnotation("third_annotation", "third", file_content, - annotations.annotation(2)); + annotations.annotation(6)); } -bool MockCodeGenerator::Generate( - const FileDescriptor* file, - const string& parameter, - GeneratorContext* context, - string* error) const { +bool MockCodeGenerator::Generate(const FileDescriptor* file, + const std::string& parameter, + GeneratorContext* context, + std::string* error) const { bool annotate = false; for (int i = 0; i < file->message_type_count(); i++) { if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) { - string command = StripPrefixString(file->message_type(i)->name(), - "MockCodeGenerator_"); + std::string command = StripPrefixString( + file->message_type(i)->name(), "MockCodeGenerator_"); if (command == "Error") { *error = "Saw message type MockCodeGenerator_Error."; return false; @@ -205,8 +228,8 @@ bool MockCodeGenerator::Generate( } else if (command == "HasJsonName") { FieldDescriptorProto field_descriptor_proto; file->message_type(i)->field(0)->CopyTo(&field_descriptor_proto); - std::cerr << "Saw json_name: " - << field_descriptor_proto.has_json_name() << std::endl; + std::cerr << "Saw json_name: " << field_descriptor_proto.has_json_name() + << std::endl; abort(); } else if (command == "Annotate") { annotate = true; @@ -215,8 +238,8 @@ bool MockCodeGenerator::Generate( context->GetCompilerVersion(&compiler_version); std::cerr << "Saw compiler_version: " << compiler_version.major() * 1000000 + - compiler_version.minor() * 1000 + - compiler_version.patch() + compiler_version.minor() * 1000 + + compiler_version.patch() << " " << compiler_version.suffix() << std::endl; abort(); } else { @@ -225,18 +248,33 @@ bool MockCodeGenerator::Generate( } } - if (HasPrefixString(parameter, "insert=")) { - std::vector insert_into; - SplitStringUsing(StripPrefixString(parameter, "insert="), - ",", &insert_into); + bool insert_endlines = HasPrefixString(parameter, "insert_endlines="); + if (insert_endlines || HasPrefixString(parameter, "insert=")) { + std::vector insert_into = Split( + StripPrefixString( + parameter, insert_endlines ? "insert_endlines=" : "insert="), + ",", true); for (size_t i = 0; i < insert_into.size(); i++) { { - google::protobuf::scoped_ptr output(context->OpenForInsert( - GetOutputFileName(insert_into[i], file), kFirstInsertionPointName)); + google::protobuf::GeneratedCodeInfo info; + std::string content = + GetOutputFileContent(name_, "first_insert", file, context); + if (insert_endlines) { + GlobalReplaceSubstring(",", ",\n", &content); + } + if (annotate) { + auto* annotation = info.add_annotation(); + annotation->set_begin(0); + annotation->set_end(content.size()); + annotation->set_source_file("first_path"); + } + std::unique_ptr output( + context->OpenForInsertWithGeneratedCodeInfo( + GetOutputFileName(insert_into[i], file), + kFirstInsertionPointName, info)); io::Printer printer(output.get(), '$'); - printer.PrintRaw(GetOutputFileContent(name_, "first_insert", - file, context)); + printer.PrintRaw(content); if (printer.failed()) { *error = "MockCodeGenerator detected write error."; return false; @@ -244,12 +282,24 @@ bool MockCodeGenerator::Generate( } { - google::protobuf::scoped_ptr output( - context->OpenForInsert(GetOutputFileName(insert_into[i], file), - kSecondInsertionPointName)); + google::protobuf::GeneratedCodeInfo info; + std::string content = + GetOutputFileContent(name_, "second_insert", file, context); + if (insert_endlines) { + GlobalReplaceSubstring(",", ",\n", &content); + } + if (annotate) { + auto* annotation = info.add_annotation(); + annotation->set_begin(0); + annotation->set_end(content.size()); + annotation->set_source_file("second_path"); + } + std::unique_ptr output( + context->OpenForInsertWithGeneratedCodeInfo( + GetOutputFileName(insert_into[i], file), + kSecondInsertionPointName, info)); io::Printer printer(output.get(), '$'); - printer.PrintRaw(GetOutputFileContent(name_, "second_insert", - file, context)); + printer.PrintRaw(content); if (printer.failed()) { *error = "MockCodeGenerator detected write error."; return false; @@ -257,7 +307,7 @@ bool MockCodeGenerator::Generate( } } } else { - google::protobuf::scoped_ptr output( + std::unique_ptr output( context->Open(GetOutputFileName(name_, file))); GeneratedCodeInfo annotations; @@ -266,19 +316,19 @@ bool MockCodeGenerator::Generate( io::Printer printer(output.get(), '$', annotate ? &annotation_collector : NULL); printer.PrintRaw(GetOutputFileContent(name_, parameter, file, context)); - string annotate_suffix = "_annotation"; + std::string annotate_suffix = "_annotation"; if (annotate) { - printer.Print("$p$", "p", "first"); + printer.Print("$p$\n", "p", "first"); printer.Annotate("p", "first" + annotate_suffix); } printer.PrintRaw(kFirstInsertionPoint); if (annotate) { - printer.Print("$p$", "p", "second"); + printer.Print("$p$\n", "p", "second"); printer.Annotate("p", "second" + annotate_suffix); } printer.PrintRaw(kSecondInsertionPoint); if (annotate) { - printer.Print("$p$", "p", "third"); + printer.Print("$p$\n", "p", "third"); printer.Annotate("p", "third" + annotate_suffix); } @@ -287,10 +337,10 @@ bool MockCodeGenerator::Generate( return false; } if (annotate) { - google::protobuf::scoped_ptr meta_output( - context->Open(GetOutputFileName(name_, file) + ".meta")); + std::unique_ptr meta_output( + context->Open(GetOutputFileName(name_, file) + ".pb.meta")); if (!TextFormat::Print(annotations, meta_output.get())) { - *error = "MockCodeGenerator couldn't write .meta"; + *error = "MockCodeGenerator couldn't write .pb.meta"; return false; } } @@ -299,39 +349,33 @@ bool MockCodeGenerator::Generate( return true; } -string MockCodeGenerator::GetOutputFileName(const string& generator_name, - const FileDescriptor* file) { +std::string MockCodeGenerator::GetOutputFileName( + const std::string& generator_name, const FileDescriptor* file) { return GetOutputFileName(generator_name, file->name()); } -string MockCodeGenerator::GetOutputFileName(const string& generator_name, - const string& file) { +std::string MockCodeGenerator::GetOutputFileName( + const std::string& generator_name, const std::string& file) { return file + ".MockCodeGenerator." + generator_name; } -string MockCodeGenerator::GetOutputFileContent( - const string& generator_name, - const string& parameter, - const FileDescriptor* file, - GeneratorContext *context) { +std::string MockCodeGenerator::GetOutputFileContent( + const std::string& generator_name, const std::string& parameter, + const FileDescriptor* file, GeneratorContext* context) { std::vector all_files; context->ListParsedFiles(&all_files); return GetOutputFileContent( - generator_name, parameter, file->name(), - CommaSeparatedList(all_files), - file->message_type_count() > 0 ? - file->message_type(0)->name() : "(none)"); + generator_name, parameter, file->name(), CommaSeparatedList(all_files), + file->message_type_count() > 0 ? file->message_type(0)->name() + : "(none)"); } -string MockCodeGenerator::GetOutputFileContent( - const string& generator_name, - const string& parameter, - const string& file, - const string& parsed_file_list, - const string& first_message_name) { - return strings::Substitute("$0: $1, $2, $3, $4\n", - generator_name, parameter, file, - first_message_name, parsed_file_list); +std::string MockCodeGenerator::GetOutputFileContent( + const std::string& generator_name, const std::string& parameter, + const std::string& file, const std::string& parsed_file_list, + const std::string& first_message_name) { + return strings::Substitute("$0: $1, $2, $3, $4\n", generator_name, parameter, + file, first_message_name, parsed_file_list); } } // namespace compiler diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h index cdd9138c9566d..9677d1904dc1a 100644 --- a/src/google/protobuf/compiler/mock_code_generator.h +++ b/src/google/protobuf/compiler/mock_code_generator.h @@ -41,7 +41,9 @@ namespace google { namespace protobuf { class FileDescriptor; } // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { @@ -54,7 +56,9 @@ namespace compiler { // If the parameter is "insert=NAMES", the MockCodeGenerator will insert lines // into the files generated by other MockCodeGenerators instead of creating // its own file. NAMES is a comma-separated list of the names of those other -// MockCodeGenerators. +// MockCodeGenerators. If the parameter is "insert_endlines=NAMES", the +// MockCodeGenerator will insert data guaranteed to contain more than one +// endline into the files generated by NAMES. // // MockCodeGenerator will also modify its behavior slightly if the input file // contains a message type with one of the following names: @@ -72,7 +76,7 @@ namespace compiler { // that can later be verified with CheckGeneratedAnnotations. class MockCodeGenerator : public CodeGenerator { public: - MockCodeGenerator(const string& name); + MockCodeGenerator(const std::string& name); virtual ~MockCodeGenerator(); // Expect (via gTest) that a MockCodeGenerator with the given name was called @@ -82,49 +86,50 @@ class MockCodeGenerator : public CodeGenerator { // should have inserted lines into this file. // |parsed_file_list| is a comma-separated list of names of the files // that are being compiled together in this run. - static void ExpectGenerated(const string& name, - const string& parameter, - const string& insertions, - const string& file, - const string& first_message_name, - const string& parsed_file_list, - const string& output_directory); + static void ExpectGenerated(const std::string& name, + const std::string& parameter, + const std::string& insertions, + const std::string& file, + const std::string& first_message_name, + const std::string& parsed_file_list, + const std::string& output_directory); // Checks that the correct text ranges were annotated by the // MockCodeGenerator_Annotate directive. - static void CheckGeneratedAnnotations(const string& name, - const string& file, - const string& output_directory); + static void CheckGeneratedAnnotations(const std::string& name, + const std::string& file, + const std::string& output_directory); // Get the name of the file which would be written by the given generator. - static string GetOutputFileName(const string& generator_name, - const FileDescriptor* file); - static string GetOutputFileName(const string& generator_name, - const string& file); + static std::string GetOutputFileName(const std::string& generator_name, + const FileDescriptor* file); + static std::string GetOutputFileName(const std::string& generator_name, + const std::string& file); // implements CodeGenerator ---------------------------------------- - virtual bool Generate(const FileDescriptor* file, - const string& parameter, - GeneratorContext* context, - string* error) const; + bool Generate(const FileDescriptor* file, const std::string& parameter, + GeneratorContext* context, std::string* error) const override; + + uint64_t GetSupportedFeatures() const override; + void SuppressFeatures(uint64 features); private: - string name_; - - static string GetOutputFileContent(const string& generator_name, - const string& parameter, - const FileDescriptor* file, - GeneratorContext *context); - static string GetOutputFileContent(const string& generator_name, - const string& parameter, - const string& file, - const string& parsed_file_list, - const string& first_message_name); + std::string name_; + uint64 suppressed_features_ = 0; + + static std::string GetOutputFileContent(const std::string& generator_name, + const std::string& parameter, + const FileDescriptor* file, + GeneratorContext* context); + static std::string GetOutputFileContent( + const std::string& generator_name, const std::string& parameter, + const std::string& file, const std::string& parsed_file_list, + const std::string& first_message_name); }; } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/objectivec/method_dump.sh b/src/google/protobuf/compiler/objectivec/method_dump.sh new file mode 100755 index 0000000000000..193825dbc1285 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/method_dump.sh @@ -0,0 +1,179 @@ +#!/bin/bash + +# Updates objectivec_nsobject_methods.h by generating a list of all of the properties +# and methods on NSObject that Protobufs should not overload from iOS and macOS combined. +# +# The rules: +# - No property should ever be overloaded. +# - Do not overload any methods that have 0 args such as "autorelease". +# - Do not overload any methods that start with "set[A-Z]" and have 1 arg such as +# "setValuesForKeysWithDictionary:". Note that these will end up in the list as just +# the "proto field" name, so "setValuesForKeysWithDictionary:" will become +# "valuesForKeysWithDictionary". + +set -eu + +trim() { + local var="$*" + # remove leading whitespace characters + var="${var#"${var%%[![:space:]]*}"}" + # remove trailing whitespace characters + var="${var%"${var##*[![:space:]]}"}" + echo -n "$var" +} + +objc_code=$(cat <<'END_CODE' +#import +#import + +int main(int argc, const char * argv[]) { + @autoreleasepool { + Class cls = [NSObject class]; + + // List out the protocols on NSObject just so we are aware if they change. + unsigned int protocolCount; + __unsafe_unretained Protocol **protocols = + class_copyProtocolList(cls, &protocolCount); + for (unsigned int i = 0; i < protocolCount; i++) { + printf("// Protocol: %s\n", protocol_getName(protocols[i])); + } + free(protocols); + + // Grab all the properties. + unsigned int propCount; + objc_property_t *props = class_copyPropertyList(cls, &propCount); + NSMutableSet *reservedNames = [[NSMutableSet alloc] init]; + for (unsigned int i = 0; i < propCount; ++i) { + NSString *propertyName = [NSString stringWithUTF8String:property_getName(props[i])]; + [reservedNames addObject:propertyName]; + } + free(props); + + // Note that methods have 2 defaults args (_cmd and SEL) so a method "0 arg method" + // actually has 2. + unsigned int methodCount; + Method *methods = class_copyMethodList(cls, &methodCount); + for (unsigned int i = 0; i < methodCount; ++i) { + int argCount = method_getNumberOfArguments(methods[i]); + NSString *methodName = + [NSString stringWithUTF8String:sel_getName(method_getName(methods[i]))]; + if (argCount == 2) { + [reservedNames addObject:methodName]; + } + if (argCount == 3 && [methodName hasPrefix:@"set"] && methodName.length > 4) { + NSString *firstLetter = [methodName substringWithRange:NSMakeRange(3,1)]; + NSString *lowerFirstLetter = [firstLetter lowercaseString]; + if ([lowerFirstLetter isEqual:firstLetter]) { + // Make sure the next letter is a capital letter so we do not take things like + // settingSomething: + continue; + } + // -5 because 3 for set, 1 for the firstLetter and 1 for the colon on the end. + NSString *restOfString = + [methodName substringWithRange:NSMakeRange(4, methodName.length - 5)]; + methodName = [lowerFirstLetter stringByAppendingString:restOfString]; + [reservedNames addObject:methodName]; + } + } + free(methods); + + SEL sortSelector = @selector(caseInsensitiveCompare:); + NSArray *array = [reservedNames.allObjects sortedArrayUsingSelector:sortSelector]; + for (NSString *item in array) { + // Some items with _ in them get returned in quotes, so do not add more. + if ([item hasPrefix:@"\""]) { + printf("\t%s,\n", item.UTF8String); + } else { + printf("\t\"%s\",\n", item.UTF8String); + } + } + } + return 0; +} +END_CODE +) + +file_header=$(cat <<'END_HEADER' +// NSObject methods +// Autogenerated by method_dump.sh. Do not edit by hand. +// Date: %DATE% +// macOS: %MACOS% +// iOS: %IOS% + +const char* const kNSObjectMethodsList[] = { +END_HEADER +) + +file_footer=$(cat <<'END_FOOTER' +}; +END_FOOTER +) + +# Check to make sure we are updating the correct file. +if [[ ! -e "objectivec_nsobject_methods.h" ]]; then + echo "error: Must be run in the src/google/protobuf/compiler/objectivec directory" + exit 1 +fi + +temp_dir=$(mktemp -d) + +echo "$objc_code" >> "$temp_dir"/method_dump.m + +# Compile up iphonesimulator and macos version of cmd line app. +iphone_simulator_sdk=$(xcrun --sdk iphonesimulator --show-sdk-path) +clang -isysroot "$iphone_simulator_sdk" -o "$temp_dir"/method_dump_ios \ + -framework Foundation -framework UIKit "$temp_dir"/method_dump.m +macos_sdk=$(xcrun --sdk macosx --show-sdk-path) +clang -isysroot "$macos_sdk" -o "$temp_dir"/method_dump_macos -framework Foundation \ + -framework Cocoa "$temp_dir"/method_dump.m + +# Create a device of the latest phone and iphonesimulator SDK and run our iOS cmd line. +device_type=$(xcrun simctl list devicetypes | grep \.iPhone- | tail -1 | sed 's/.*(\(.*\))/\1/') +# runtimes come with a space at the end (for Xcode 10) so let's trim all of our input to +# be safe. +device_type=$(trim "$device_type") +runtime=$(xcrun simctl list runtimes | grep \.iOS- | tail -1 | \ + sed 's/.*\(com\.apple.\CoreSimulator\.SimRuntime\.iOS.*\)/\1/') +runtime=$(trim "$runtime") +uuid=$(uuidgen) +device_name="method_dump_device_$uuid" +device=$(xcrun simctl create "$device_name" "$device_type" "$runtime") +xcrun simctl spawn "$device" "$temp_dir"/method_dump_ios > "$temp_dir"/methods_unsorted_ios.txt +xcrun simctl delete "$device" + +# Run the Mac version +"$temp_dir"/method_dump_macos >> "$temp_dir"/methods_unsorted_macos.txt + +# Generate sorted output +echo "$file_header" | sed -e "s|%DATE%|$(date)|" -e "s|%MACOS%|$(basename $macos_sdk)|" \ + -e "s|%IOS%|$(basename $iphone_simulator_sdk)|" > "$temp_dir"/methods_sorted.txt +sort -u "$temp_dir"/methods_unsorted_ios.txt \ + "$temp_dir"/methods_unsorted_macos.txt >> "$temp_dir"/methods_sorted.txt +echo $"$file_footer" >> "$temp_dir"/methods_sorted.txt + +# Check for differences. Turn off error checking because we expect diff to fail when +# there are no differences. +set +e +diff_out=$(diff -I "^//.*$" "$temp_dir"/methods_sorted.txt objectivec_nsobject_methods.h) +removed_methods=$(echo "$diff_out" | grep '^>.*$') +set -e +if [[ -n "$removed_methods" ]]; then + echo "error: Methods removed from NSObject" + echo "It appears that some methods may have been removed from NSObject." + echo "This could mean that there may be some backwards compatibility issues." + echo "You could potentially build apps that may not work on earlier systems than:" + echo "$iphone_simulator_sdk" + echo "$macos_sdk" + echo "If they declare protobuf types that use any of the following as names:" + echo "$removed_methods" + echo "" + echo "New Version: $temp_dir/methods_sorted.txt" + echo "Old Version: objectivec_nsobject_methods.h" + exit 1 +fi +if [[ -n "$diff_out" ]]; then + echo "Added Methods:" + echo "$(echo "$diff_out" | grep '^<.*$' | sed -e 's/^< "\(.*\)",$/ \1/')" +fi; +cp "$temp_dir"/methods_sorted.txt objectivec_nsobject_methods.h +rm -rf "$temp_dir" diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc index 02d60b3e97ac8..12c475ff5a5b0 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc @@ -35,6 +35,7 @@ #include #include #include +#include // std::find() namespace google { namespace protobuf { @@ -44,6 +45,17 @@ namespace objectivec { EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) : descriptor_(descriptor), name_(EnumName(descriptor_)) { + // Track the names for the enum values, and if an alias overlaps a base + // value, skip making a name for it. Likewise if two alias overlap, the + // first one wins. + // The one gap in this logic is if two base values overlap, but for that + // to happen you have to have "Foo" and "FOO" or "FOO_BAR" and "FooBar", + // and if an enum has that, it is already going to be confusing and a + // compile error is just fine. + // The values are still tracked to support the reflection apis and + // TextFormat handing since they are different there. + std::set value_names; + for (int i = 0; i < descriptor_->value_count(); i++) { const EnumValueDescriptor* value = descriptor_->value(i); const EnumValueDescriptor* canonical_value = @@ -51,6 +63,14 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) if (value == canonical_value) { base_values_.push_back(value); + value_names.insert(EnumValueName(value)); + } else { + std::string value_name(EnumValueName(value)); + if (value_names.find(value_name) != value_names.end()) { + alias_values_to_skip_.insert(value); + } else { + value_names.insert(value_name); + } } all_values_.push_back(value); } @@ -59,7 +79,7 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) EnumGenerator::~EnumGenerator() {} void EnumGenerator::GenerateHeader(io::Printer* printer) { - string enum_comments; + std::string enum_comments; SourceLocation location; if (descriptor_->GetSourceLocation(&location)) { enum_comments = BuildCommentsString(location, true); @@ -72,6 +92,20 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) { "\n", "name", name_); + // Swift 5 included SE0192 "Handling Future Enum Cases" + // https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md + // Since a .proto file can get new values added to an enum at any time, they + // are effectively "non-frozen". Even in a proto3 syntax file where there is + // support for the unknown value, an edit to the file can always add a new + // value moving something from unknown to known. Since Swift is now ABI + // stable, it also means a binary could contain Swift compiled against one + // version of the .pbobjc.h file, but finally linked against an enum with + // more cases. So the Swift code will always have to treat ObjC Proto Enums + // as "non-frozen". The default behavior in SE0192 is for all objc enums to + // be "non-frozen" unless marked as otherwise, so this means this generation + // doesn't have to bother with the `enum_extensibility` attribute, as the + // default will be what is needed. + printer->Print("$comments$typedef$deprecated_attribute$ GPB_ENUM($name$) {\n", "comments", enum_comments, "deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file()), @@ -90,9 +124,12 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) { "name", name_); } for (int i = 0; i < all_values_.size(); i++) { + if (alias_values_to_skip_.find(all_values_[i]) != alias_values_to_skip_.end()) { + continue; + } SourceLocation location; if (all_values_[i]->GetSourceLocation(&location)) { - string comments = BuildCommentsString(location, true).c_str(); + std::string comments = BuildCommentsString(location, true).c_str(); if (comments.length() > 0) { if (i > 0) { printer->Print("\n"); @@ -105,7 +142,7 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) { "$name$$deprecated_attribute$ = $value$,\n", "name", EnumValueName(all_values_[i]), "deprecated_attribute", GetOptionalDeprecatedAttribute(all_values_[i]), - "value", SimpleItoa(all_values_[i]->number())); + "value", StrCat(all_values_[i]->number())); } printer->Outdent(); printer->Print( @@ -135,11 +172,11 @@ void EnumGenerator::GenerateSource(io::Printer* printer) { // will be zero. TextFormatDecodeData text_format_decode_data; int enum_value_description_key = -1; - string text_blob; + std::string text_blob; for (int i = 0; i < all_values_.size(); i++) { ++enum_value_description_key; - string short_name(EnumValueShortName(all_values_[i])); + std::string short_name(EnumValueShortName(all_values_[i])); text_blob += short_name + '\0'; if (UnCamelCaseEnumShortName(short_name) != all_values_[i]->name()) { text_format_decode_data.AddString(enum_value_description_key, short_name, @@ -149,7 +186,7 @@ void EnumGenerator::GenerateSource(io::Printer* printer) { printer->Print( "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n" - " static GPBEnumDescriptor *descriptor = NULL;\n" + " static _Atomic(GPBEnumDescriptor*) descriptor = nil;\n" " if (!descriptor) {\n", "name", name_); @@ -192,7 +229,8 @@ void EnumGenerator::GenerateSource(io::Printer* printer) { "extraTextFormatInfo", CEscape(text_format_decode_data.Data())); } printer->Print( - " if (!OSAtomicCompareAndSwapPtrBarrier(nil, worker, (void * volatile *)&descriptor)) {\n" + " GPBEnumDescriptor *expected = nil;\n" + " if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {\n" " [worker release];\n" " }\n" " }\n" diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.h b/src/google/protobuf/compiler/objectivec/objectivec_enum.h index 0b41cf7352efb..1d5741a53ce2e 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.h @@ -35,14 +35,9 @@ #include #include #include +#include namespace google { -namespace protobuf { -namespace io { -class Printer; // printer.h -} -} - namespace protobuf { namespace compiler { namespace objectivec { @@ -52,22 +47,25 @@ class EnumGenerator { explicit EnumGenerator(const EnumDescriptor* descriptor); ~EnumGenerator(); + EnumGenerator(const EnumGenerator&) = delete; + EnumGenerator& operator=(const EnumGenerator&) = delete; + void GenerateHeader(io::Printer* printer); void GenerateSource(io::Printer* printer); - const string& name() const { return name_; } + const std::string& name() const { return name_; } private: const EnumDescriptor* descriptor_; - vector base_values_; - vector all_values_; - const string name_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); + std::vector base_values_; + std::vector all_values_; + std::set alias_values_to_skip_; + const std::string name_; }; } // namespace objectivec } // namespace compiler } // namespace protobuf } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc index 8899a13aa9fe7..ff69f39f484ff 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc @@ -32,11 +32,9 @@ #include #include -#include #include #include #include -#include namespace google { namespace protobuf { @@ -46,8 +44,8 @@ namespace objectivec { namespace { void SetEnumVariables(const FieldDescriptor* descriptor, - std::map* variables) { - string type = EnumName(descriptor->enum_type()); + std::map* variables) { + std::string type = EnumName(descriptor->enum_type()); (*variables)["storage_type"] = type; // For non repeated fields, if it was defined in a different file, the // property decls need to use "enum NAME" rather than just "NAME" to support @@ -106,26 +104,26 @@ void EnumFieldGenerator::GenerateCFunctionImplementations( "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) {\n" " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n" " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n" - " return GPBGetMessageInt32Field(message, field);\n" + " return GPBGetMessageRawEnumField(message, field);\n" "}\n" "\n" "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value) {\n" " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n" " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n" - " GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);\n" + " GPBSetMessageRawEnumField(message, field, value);\n" "}\n" "\n"); } void EnumFieldGenerator::DetermineForwardDeclarations( - std::set* fwd_decls) const { + std::set* fwd_decls) const { SingleFieldGenerator::DetermineForwardDeclarations(fwd_decls); // If it is an enum defined in a different file, then we'll need a forward // declaration for it. When it is in our file, all the enums are output // before the message, so it will be declared before it is needed. if (descriptor_->file() != descriptor_->enum_type()->file()) { // Enum name is already in "storage_type". - const string& name = variable("storage_type"); + const std::string& name = variable("storage_type"); fwd_decls->insert("GPB_ENUM_FWD_DECLARE(" + name + ")"); } } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h index ae56c069a176a..f89a7bf22fb05 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h @@ -44,17 +44,18 @@ class EnumFieldGenerator : public SingleFieldGenerator { friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, const Options& options); + EnumFieldGenerator(const EnumFieldGenerator&) = delete; + EnumFieldGenerator& operator=(const EnumFieldGenerator&) = delete; + public: virtual void GenerateCFunctionDeclarations(io::Printer* printer) const; virtual void GenerateCFunctionImplementations(io::Printer* printer) const; - virtual void DetermineForwardDeclarations(std::set* fwd_decls) const; + virtual void DetermineForwardDeclarations( + std::set* fwd_decls) const; protected: EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options); virtual ~EnumFieldGenerator(); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); }; class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator { @@ -68,9 +69,6 @@ class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator { RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options); virtual ~RepeatedEnumFieldGenerator(); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); }; } // namespace objectivec diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc index b788d0a32aee1..9cebcb22afa68 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc @@ -41,7 +41,7 @@ namespace protobuf { namespace compiler { namespace objectivec { -ExtensionGenerator::ExtensionGenerator(const string& root_class_name, +ExtensionGenerator::ExtensionGenerator(const std::string& root_class_name, const FieldDescriptor* descriptor) : method_name_(ExtensionMethodName(descriptor)), root_class_and_method_name_(root_class_name + "_" + method_name_), @@ -59,8 +59,13 @@ ExtensionGenerator::ExtensionGenerator(const string& root_class_name, ExtensionGenerator::~ExtensionGenerator() {} void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) { - std::map vars; + std::map vars; vars["method_name"] = method_name_; + if (IsRetainedName(method_name_)) { + vars["storage_attribute"] = " NS_RETURNS_NOT_RETAINED"; + } else { + vars["storage_attribute"] = ""; + } SourceLocation location; if (descriptor_->GetSourceLocation(&location)) { vars["comments"] = BuildCommentsString(location, true); @@ -72,31 +77,31 @@ void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) { vars["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file()); printer->Print(vars, "$comments$" - "+ (GPBExtensionDescriptor *)$method_name$$deprecated_attribute$;\n"); + "+ (GPBExtensionDescriptor *)$method_name$$storage_attribute$$deprecated_attribute$;\n"); } void ExtensionGenerator::GenerateStaticVariablesInitialization( io::Printer* printer) { - std::map vars; + std::map vars; vars["root_class_and_method_name"] = root_class_and_method_name_; - vars["extended_type"] = ClassName(descriptor_->containing_type()); - vars["number"] = SimpleItoa(descriptor_->number()); + const std::string containing_type = ClassName(descriptor_->containing_type()); + vars["extended_type"] = ObjCClass(containing_type); + vars["number"] = StrCat(descriptor_->number()); - std::vector options; + std::vector options; if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated"); if (descriptor_->is_packed()) options.push_back("GPBExtensionPacked"); - if (descriptor_->containing_type()->options().message_set_wire_format()) + if (descriptor_->containing_type()->options().message_set_wire_format()) { options.push_back("GPBExtensionSetWireFormat"); - + } vars["options"] = BuildFlagsString(FLAGTYPE_EXTENSION, options); ObjectiveCType objc_type = GetObjectiveCType(descriptor_); - string singular_type; if (objc_type == OBJECTIVECTYPE_MESSAGE) { - vars["type"] = string("GPBStringifySymbol(") + - ClassName(descriptor_->message_type()) + ")"; + std::string message_type = ClassName(descriptor_->message_type()); + vars["type"] = ObjCClass(message_type); } else { - vars["type"] = "NULL"; + vars["type"] = "Nil"; } vars["default_name"] = GPBGenericValueFieldName(descriptor_); @@ -105,8 +110,8 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( } else { vars["default"] = DefaultValue(descriptor_); } - string type = GetCapitalizedType(descriptor_); - vars["extension_type"] = string("GPBDataType") + type; + std::string type = GetCapitalizedType(descriptor_); + vars["extension_type"] = std::string("GPBDataType") + type; if (objc_type == OBJECTIVECTYPE_ENUM) { vars["enum_desc_func_name"] = @@ -119,8 +124,8 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( "{\n" " .defaultValue.$default_name$ = $default$,\n" " .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n" - " .extendedClass = GPBStringifySymbol($extended_type$),\n" - " .messageOrGroupClassName = $type$,\n" + " .extendedClass.clazz = $extended_type$,\n" + " .messageOrGroupClass.clazz = $type$,\n" " .enumDescriptorFunc = $enum_desc_func_name$,\n" " .fieldNumber = $number$,\n" " .dataType = $extension_type$,\n" @@ -128,11 +133,23 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( "},\n"); } +void ExtensionGenerator::DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) { + std::string extended_type = ClassName(descriptor_->containing_type()); + fwd_decls->insert(ObjCClassDeclaration(extended_type)); + ObjectiveCType objc_type = GetObjectiveCType(descriptor_); + if (objc_type == OBJECTIVECTYPE_MESSAGE) { + std::string message_type = ClassName(descriptor_->message_type()); + fwd_decls->insert(ObjCClassDeclaration(message_type)); + } +} + void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) { printer->Print( "[registry addExtension:$root_class_and_method_name$];\n", "root_class_and_method_name", root_class_and_method_name_); } + } // namespace objectivec } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/google/protobuf/compiler/objectivec/objectivec_extension.h index e361e639bd644..d412f4a9f2a8a 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.h @@ -31,39 +31,37 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__ #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__ -#include +#include +#include namespace google { -namespace protobuf { -class FieldDescriptor; // descriptor.h -namespace io { -class Printer; // printer.h -} -} - namespace protobuf { namespace compiler { namespace objectivec { class ExtensionGenerator { public: - ExtensionGenerator(const string& root_class_name, + ExtensionGenerator(const std::string& root_class_name, const FieldDescriptor* descriptor); ~ExtensionGenerator(); + ExtensionGenerator(const ExtensionGenerator&) = delete; + ExtensionGenerator& operator=(const ExtensionGenerator&) = delete; + void GenerateMembersHeader(io::Printer* printer); void GenerateStaticVariablesInitialization(io::Printer* printer); void GenerateRegistrationSource(io::Printer* printer); + void DetermineObjectiveCClassDefinitions(std::set* fwd_decls); private: - string method_name_; - string root_class_and_method_name_; + std::string method_name_; + std::string root_class_and_method_name_; const FieldDescriptor* descriptor_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); }; + } // namespace objectivec } // namespace compiler } // namespace protobuf } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc index b6123fad7bb82..9d5fa9933a618 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -38,7 +38,6 @@ #include #include #include -#include #include namespace google { @@ -49,16 +48,16 @@ namespace objectivec { namespace { void SetCommonFieldVariables(const FieldDescriptor* descriptor, - std::map* variables) { - string camel_case_name = FieldName(descriptor); - string raw_field_name; + std::map* variables) { + std::string camel_case_name = FieldName(descriptor); + std::string raw_field_name; if (descriptor->type() == FieldDescriptor::TYPE_GROUP) { raw_field_name = descriptor->message_type()->name(); } else { raw_field_name = descriptor->name(); } // The logic here has to match -[GGPBFieldDescriptor textFormatName]. - const string un_camel_case_name( + const std::string un_camel_case_name( UnCamelCaseFieldName(camel_case_name, descriptor)); const bool needs_custom_name = (raw_field_name != un_camel_case_name); @@ -68,18 +67,18 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, } else { (*variables)["comments"] = "\n"; } - const string& classname = ClassName(descriptor->containing_type()); + const std::string& classname = ClassName(descriptor->containing_type()); (*variables)["classname"] = classname; (*variables)["name"] = camel_case_name; - const string& capitalized_name = FieldNameCapitalized(descriptor); + const std::string& capitalized_name = FieldNameCapitalized(descriptor); (*variables)["capitalized_name"] = capitalized_name; (*variables)["raw_field_name"] = raw_field_name; (*variables)["field_number_name"] = classname + "_FieldNumber_" + capitalized_name; - (*variables)["field_number"] = SimpleItoa(descriptor->number()); + (*variables)["field_number"] = StrCat(descriptor->number()); (*variables)["field_type"] = GetCapitalizedType(descriptor); (*variables)["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor); - std::vector field_flags; + std::vector field_flags; if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated"); if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired"); if (descriptor->is_optional()) field_flags.push_back("GPBFieldOptional"); @@ -92,14 +91,22 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { field_flags.push_back("GPBFieldHasEnumDescriptor"); } + // It will clear on a zero value if... + // - not repeated/map + // - doesn't have presence + bool clear_on_zero = + (!descriptor->is_repeated() && !descriptor->has_presence()); + if (clear_on_zero) { + field_flags.push_back("GPBFieldClearHasIvarOnZero"); + } (*variables)["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags); (*variables)["default"] = DefaultValue(descriptor); (*variables)["default_name"] = GPBGenericValueFieldName(descriptor); - (*variables)["dataTypeSpecific_name"] = "className"; - (*variables)["dataTypeSpecific_value"] = "NULL"; + (*variables)["dataTypeSpecific_name"] = "clazz"; + (*variables)["dataTypeSpecific_value"] = "Nil"; (*variables)["storage_offset_value"] = "(uint32_t)offsetof(" + classname + "__storage_, " + camel_case_name + ")"; @@ -178,7 +185,12 @@ void FieldGenerator::GenerateCFunctionImplementations( } void FieldGenerator::DetermineForwardDeclarations( - std::set* fwd_decls) const { + std::set* fwd_decls) const { + // Nothing +} + +void FieldGenerator::DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) const { // Nothing } @@ -214,7 +226,7 @@ void FieldGenerator::GenerateFieldDescription( } void FieldGenerator::SetRuntimeHasBit(int has_index) { - variables_["has_index"] = SimpleItoa(has_index); + variables_["has_index"] = StrCat(has_index); } void FieldGenerator::SetNoHasBit(void) { @@ -234,13 +246,18 @@ void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) { } void FieldGenerator::SetOneofIndexBase(int index_base) { - if (descriptor_->containing_oneof() != NULL) { - int index = descriptor_->containing_oneof()->index() + index_base; + const OneofDescriptor *oneof = descriptor_->real_containing_oneof(); + if (oneof != NULL) { + int index = oneof->index() + index_base; // Flip the sign to mark it as a oneof. - variables_["has_index"] = SimpleItoa(-index); + variables_["has_index"] = StrCat(-index); } } +bool FieldGenerator::WantsHasProperty(void) const { + return descriptor_->has_presence() && !descriptor_->real_containing_oneof(); +} + void FieldGenerator::FinishInitialization(void) { // If "property_type" wasn't set, make it "storage_type". if ((variables_.find("property_type") == variables_.end()) && @@ -285,20 +302,8 @@ void SingleFieldGenerator::GeneratePropertyImplementation( } } -bool SingleFieldGenerator::WantsHasProperty(void) const { - if (descriptor_->containing_oneof() != NULL) { - // If in a oneof, it uses the oneofcase instead of a has bit. - return false; - } - if (HasFieldPresence(descriptor_->file())) { - // In proto1/proto2, every field has a has_$name$() method. - return true; - } - return false; -} - bool SingleFieldGenerator::RuntimeUsesHasBit(void) const { - if (descriptor_->containing_oneof() != NULL) { + if (descriptor_->real_containing_oneof()) { // The oneof tracks what is set instead. return false; } @@ -398,22 +403,15 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration( printer->Print("\n"); } -bool RepeatedFieldGenerator::WantsHasProperty(void) const { - // Consumer check the array size/existance rather than a has bit. - return false; -} - bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const { - return false; // The array having anything is what is used. + return false; // The array (or map/dict) having anything is what is used. } FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, const Options& options) : descriptor_(descriptor), - field_generators_( - new scoped_ptr[descriptor->field_count()]), - extension_generators_( - new scoped_ptr[descriptor->extension_count()]) { + field_generators_(descriptor->field_count()), + extension_generators_(descriptor->extension_count()) { // Construct all the FieldGenerators. for (int i = 0; i < descriptor->field_count(); i++) { field_generators_[i].reset( diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h index 6bd5db2eebe96..0b0e3058f9c9e 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.h @@ -34,16 +34,11 @@ #include #include #include -#include #include +#include namespace google { namespace protobuf { - -namespace io { -class Printer; // printer.h -} // namespace io - namespace compiler { namespace objectivec { @@ -54,6 +49,9 @@ class FieldGenerator { virtual ~FieldGenerator(); + FieldGenerator(const FieldGenerator&) = delete; + FieldGenerator& operator=(const FieldGenerator&) = delete; + // Exposed for subclasses to fill in. virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const = 0; virtual void GeneratePropertyDeclaration(io::Printer* printer) const = 0; @@ -67,7 +65,10 @@ class FieldGenerator { virtual void GenerateCFunctionImplementations(io::Printer* printer) const; // Exposed for subclasses, should always call it on the parent class also. - virtual void DetermineForwardDeclarations(std::set* fwd_decls) const; + virtual void DetermineForwardDeclarations( + std::set* fwd_decls) const; + virtual void DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) const; // Used during generation, not intended to be extended by subclasses. void GenerateFieldDescription( @@ -82,34 +83,35 @@ class FieldGenerator { virtual void SetExtraRuntimeHasBitsBase(int index_base); void SetOneofIndexBase(int index_base); - string variable(const char* key) const { + std::string variable(const char* key) const { return variables_.find(key)->second; } bool needs_textformat_name_support() const { - const string& field_flags = variable("fieldflags"); - return field_flags.find("GPBFieldTextFormatNameCustom") != string::npos; + const std::string& field_flags = variable("fieldflags"); + return field_flags.find("GPBFieldTextFormatNameCustom") != + std::string::npos; } - string generated_objc_name() const { return variable("name"); } - string raw_field_name() const { return variable("raw_field_name"); } + std::string generated_objc_name() const { return variable("name"); } + std::string raw_field_name() const { return variable("raw_field_name"); } protected: FieldGenerator(const FieldDescriptor* descriptor, const Options& options); virtual void FinishInitialization(void); - virtual bool WantsHasProperty(void) const = 0; + bool WantsHasProperty(void) const; const FieldDescriptor* descriptor_; - std::map variables_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); + std::map variables_; }; class SingleFieldGenerator : public FieldGenerator { public: virtual ~SingleFieldGenerator(); + SingleFieldGenerator(const SingleFieldGenerator&) = delete; + SingleFieldGenerator& operator=(const SingleFieldGenerator&) = delete; + virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const; virtual void GeneratePropertyDeclaration(io::Printer* printer) const; @@ -120,10 +122,6 @@ class SingleFieldGenerator : public FieldGenerator { protected: SingleFieldGenerator(const FieldDescriptor* descriptor, const Options& options); - virtual bool WantsHasProperty(void) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingleFieldGenerator); }; // Subclass with common support for when the field ends up as an ObjC Object. @@ -131,21 +129,24 @@ class ObjCObjFieldGenerator : public SingleFieldGenerator { public: virtual ~ObjCObjFieldGenerator(); + ObjCObjFieldGenerator(const ObjCObjFieldGenerator&) = delete; + ObjCObjFieldGenerator& operator=(const ObjCObjFieldGenerator&) = delete; + virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const; virtual void GeneratePropertyDeclaration(io::Printer* printer) const; protected: ObjCObjFieldGenerator(const FieldDescriptor* descriptor, const Options& options); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjCObjFieldGenerator); }; class RepeatedFieldGenerator : public ObjCObjFieldGenerator { public: virtual ~RepeatedFieldGenerator(); + RepeatedFieldGenerator(const RepeatedFieldGenerator&) = delete; + RepeatedFieldGenerator& operator=(const RepeatedFieldGenerator&) = delete; + virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const; virtual void GeneratePropertyDeclaration(io::Printer* printer) const; @@ -157,10 +158,6 @@ class RepeatedFieldGenerator : public ObjCObjFieldGenerator { RepeatedFieldGenerator(const FieldDescriptor* descriptor, const Options& options); virtual void FinishInitialization(void); - virtual bool WantsHasProperty(void) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedFieldGenerator); }; // Convenience class which constructs FieldGenerators for a Descriptor. @@ -169,6 +166,9 @@ class FieldGeneratorMap { FieldGeneratorMap(const Descriptor* descriptor, const Options& options); ~FieldGeneratorMap(); + FieldGeneratorMap(const FieldGeneratorMap&) = delete; + FieldGeneratorMap& operator=(const FieldGeneratorMap&) = delete; + const FieldGenerator& get(const FieldDescriptor* field) const; const FieldGenerator& get_extension(int index) const; @@ -182,13 +182,13 @@ class FieldGeneratorMap { private: const Descriptor* descriptor_; - scoped_array > field_generators_; - scoped_array > extension_generators_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); + std::vector> field_generators_; + std::vector> extension_generators_; }; + } // namespace objectivec } // namespace compiler } // namespace protobuf } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index 954b26885bf18..417733ef4727d 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -52,10 +52,24 @@ namespace objectivec { namespace { // This is also found in GPBBootstrap.h, and needs to be kept in sync. -const int32 GOOGLE_PROTOBUF_OBJC_VERSION = 30002; +const int32 GOOGLE_PROTOBUF_OBJC_VERSION = 30004; const char* kHeaderExtension = ".pbobjc.h"; +// Checks if a message contains any enums definitions (on the message or +// a nested message under it). +bool MessageContainsEnums(const Descriptor* message) { + if (message->enum_type_count() > 0) { + return true; + } + for (int i = 0; i < message->nested_type_count(); i++) { + if (MessageContainsEnums(message->nested_type(i))) { + return true; + } + } + return false; +} + // Checks if a message contains any extension definitions (on the message or // a nested message under it). bool MessageContainsExtensions(const Descriptor* message) { @@ -70,6 +84,20 @@ bool MessageContainsExtensions(const Descriptor* message) { return false; } +// Checks if the file contains any enum definitions (at the root or +// nested under a message). +bool FileContainsEnums(const FileDescriptor* file) { + if (file->enum_type_count() > 0) { + return true; + } + for (int i = 0; i < file->message_type_count(); i++) { + if (MessageContainsEnums(file->message_type(i))) { + return true; + } + } + return false; +} + // Checks if the file contains any extensions definitions (at the root or // nested under a message). bool FileContainsExtensions(const FileDescriptor* file) { @@ -88,9 +116,9 @@ bool FileContainsExtensions(const FileDescriptor* file) { // deps as visited and prunes them from the needed files list. void PruneFileAndDepsMarkingAsVisited( const FileDescriptor* file, - vector* files, + std::vector* files, std::set* files_visited) { - vector::iterator iter = + std::vector::iterator iter = std::find(files->begin(), files->end(), file); if (iter != files->end()) { files->erase(iter); @@ -104,7 +132,7 @@ void PruneFileAndDepsMarkingAsVisited( // Helper for CollectMinimalFileDepsContainingExtensions. void CollectMinimalFileDepsContainingExtensionsWorker( const FileDescriptor* file, - vector* files, + std::vector* files, std::set* files_visited) { if (files_visited->find(file) != files_visited->end()) { return; @@ -137,7 +165,7 @@ void CollectMinimalFileDepsContainingExtensionsWorker( // specifically). void CollectMinimalFileDepsContainingExtensions( const FileDescriptor* file, - vector* files) { + std::vector* files) { std::set files_visited; for (int i = 0; i < file->dependency_count(); i++) { const FileDescriptor* dep = file->dependency(i); @@ -160,33 +188,38 @@ bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) { FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options) : file_(file), root_class_name_(FileClassName(file)), + is_bundled_proto_(IsProtobufLibraryBundledProtoFile(file)), options_(options) { for (int i = 0; i < file_->enum_type_count(); i++) { EnumGenerator *generator = new EnumGenerator(file_->enum_type(i)); - enum_generators_.push_back(generator); + enum_generators_.emplace_back(generator); } for (int i = 0; i < file_->message_type_count(); i++) { MessageGenerator *generator = new MessageGenerator(root_class_name_, file_->message_type(i), options_); - message_generators_.push_back(generator); + message_generators_.emplace_back(generator); } for (int i = 0; i < file_->extension_count(); i++) { ExtensionGenerator *generator = new ExtensionGenerator(root_class_name_, file_->extension(i)); - extension_generators_.push_back(generator); + extension_generators_.emplace_back(generator); } } -FileGenerator::~FileGenerator() { - STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end()); - STLDeleteContainerPointers(message_generators_.begin(), - message_generators_.end()); - STLDeleteContainerPointers(extension_generators_.begin(), - extension_generators_.end()); -} +FileGenerator::~FileGenerator() {} void FileGenerator::GenerateHeader(io::Printer *printer) { - PrintFileRuntimePreamble(printer, "GPBProtocolBuffers.h"); + std::vector headers; + // Generated files bundled with the library get minimal imports, everything + // else gets the wrapper so everything is usable. + if (is_bundled_proto_) { + headers.push_back("GPBDescriptor.h"); + headers.push_back("GPBMessage.h"); + headers.push_back("GPBRootObject.h"); + } else { + headers.push_back("GPBProtocolBuffers.h"); + } + PrintFileRuntimePreamble(printer, headers); // Add some verification that the generated code matches the source the // code is being compiled with. @@ -202,14 +235,16 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { "#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.\n" "#endif\n" "\n", - "google_protobuf_objc_version", SimpleItoa(GOOGLE_PROTOBUF_OBJC_VERSION)); + "google_protobuf_objc_version", StrCat(GOOGLE_PROTOBUF_OBJC_VERSION)); // #import any headers for "public imports" in the proto file. { ImportWriter import_writer( options_.generate_for_named_framework, - options_.named_framework_to_proto_path_mappings_path); - const string header_extension(kHeaderExtension); + options_.named_framework_to_proto_path_mappings_path, + options_.runtime_import_prefix, + is_bundled_proto_); + const std::string header_extension(kHeaderExtension); for (int i = 0; i < file_->public_dependency_count(); i++) { import_writer.AddFile(file_->public_dependency(i), header_extension); } @@ -229,12 +264,11 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { "CF_EXTERN_C_BEGIN\n" "\n"); - std::set fwd_decls; - for (vector::iterator iter = message_generators_.begin(); - iter != message_generators_.end(); ++iter) { - (*iter)->DetermineForwardDeclarations(&fwd_decls); + std::set fwd_decls; + for (const auto& generator : message_generators_) { + generator->DetermineForwardDeclarations(&fwd_decls); } - for (std::set::const_iterator i(fwd_decls.begin()); + for (std::set::const_iterator i(fwd_decls.begin()); i != fwd_decls.end(); ++i) { printer->Print("$value$;\n", "value", *i); } @@ -247,14 +281,12 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { "\n"); // need to write out all enums first - for (vector::iterator iter = enum_generators_.begin(); - iter != enum_generators_.end(); ++iter) { - (*iter)->GenerateHeader(printer); + for (const auto& generator : enum_generators_) { + generator->GenerateHeader(printer); } - for (vector::iterator iter = message_generators_.begin(); - iter != message_generators_.end(); ++iter) { - (*iter)->GenerateEnumHeader(printer); + for (const auto& generator : message_generators_) { + generator->GenerateEnumHeader(printer); } // For extensions to chain together, the Root gets created even if there @@ -272,29 +304,26 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { " * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n" " * this file and all files that it depends on.\n" " **/\n" - "@interface $root_class_name$ : GPBRootObject\n" + "GPB_FINAL @interface $root_class_name$ : GPBRootObject\n" "@end\n" "\n", "root_class_name", root_class_name_); - if (extension_generators_.size() > 0) { + if (!extension_generators_.empty()) { // The dynamic methods block is only needed if there are extensions. printer->Print( "@interface $root_class_name$ (DynamicMethods)\n", "root_class_name", root_class_name_); - for (vector::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateMembersHeader(printer); + for (const auto& generator : extension_generators_) { + generator->GenerateMembersHeader(printer); } printer->Print("@end\n\n"); - } // extension_generators_.size() > 0 + } // !extension_generators_.empty() - for (vector::iterator iter = message_generators_.begin(); - iter != message_generators_.end(); ++iter) { - (*iter)->GenerateMessageHeader(printer); + for (const auto& generator : message_generators_) { + generator->GenerateMessageHeader(printer); } printer->Print( @@ -309,23 +338,34 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { void FileGenerator::GenerateSource(io::Printer *printer) { // #import the runtime support. - PrintFileRuntimePreamble(printer, "GPBProtocolBuffers_RuntimeSupport.h"); + std::vector headers; + headers.push_back("GPBProtocolBuffers_RuntimeSupport.h"); + PrintFileRuntimePreamble(printer, headers); - vector deps_with_extensions; + // Enums use atomic in the generated code, so add the system import as needed. + if (FileContainsEnums(file_)) { + printer->Print( + "#import \n" + "\n"); + } + + std::vector deps_with_extensions; CollectMinimalFileDepsContainingExtensions(file_, &deps_with_extensions); { ImportWriter import_writer( options_.generate_for_named_framework, - options_.named_framework_to_proto_path_mappings_path); - const string header_extension(kHeaderExtension); + options_.named_framework_to_proto_path_mappings_path, + options_.runtime_import_prefix, + is_bundled_proto_); + const std::string header_extension(kHeaderExtension); // #import the header for this proto file. import_writer.AddFile(file_, header_extension); // #import the headers for anything that a plain dependency of this proto // file (that means they were just an include, not a "public" include). - std::set public_import_names; + std::set public_import_names; for (int i = 0; i < file_->public_dependency_count(); i++) { public_import_names.insert(file_->public_dependency(i)->name()); } @@ -341,7 +381,7 @@ void FileGenerator::GenerateSource(io::Printer *printer) { // imported so it can get merged into the root's extensions registry. // See the Note by CollectMinimalFileDepsContainingExtensions before // changing this. - for (vector::iterator iter = + for (std::vector::iterator iter = deps_with_extensions.begin(); iter != deps_with_extensions.end(); ++iter) { if (!IsDirectDependency(*iter, file_)) { @@ -353,18 +393,27 @@ void FileGenerator::GenerateSource(io::Printer *printer) { } bool includes_oneof = false; - for (vector::iterator iter = message_generators_.begin(); - iter != message_generators_.end(); ++iter) { - if ((*iter)->IncludesOneOfDefinition()) { + for (const auto& generator : message_generators_) { + if (generator->IncludesOneOfDefinition()) { includes_oneof = true; break; } } + std::set fwd_decls; + for (const auto& generator : message_generators_) { + generator->DetermineObjectiveCClassDefinitions(&fwd_decls); + } + for (const auto& generator : extension_generators_) { + generator->DetermineObjectiveCClassDefinitions(&fwd_decls); + } + // Note: // deprecated-declarations suppression is only needed if some place in this // proto file is something deprecated or if it references something from // another file that is deprecated. + // dollar-in-identifier-extension is needed because we use references to + // objc class names that have $ in identifiers. printer->Print( "// @@protoc_insertion_point(imports)\n" "\n" @@ -372,14 +421,31 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"); if (includes_oneof) { // The generated code for oneof's uses direct ivar access, suppress the - // warning incase developer turn that on in the context they compile the + // warning in case developer turn that on in the context they compile the // generated code. printer->Print( "#pragma clang diagnostic ignored \"-Wdirect-ivar-access\"\n"); } - + if (!fwd_decls.empty()) { + printer->Print( + "#pragma clang diagnostic ignored \"-Wdollar-in-identifier-extension\"\n"); + } + printer->Print( + "\n"); + if (!fwd_decls.empty()) { + printer->Print( + "#pragma mark - Objective C Class declarations\n" + "// Forward declarations of Objective C classes that we can use as\n" + "// static values in struct initializers.\n" + "// We don't use [Foo class] because it is not a static value.\n"); + } + for (const auto& i : fwd_decls) { + printer->Print("$value$\n", "value", i); + } + if (!fwd_decls.empty()) { + printer->Print("\n"); + } printer->Print( - "\n" "#pragma mark - $root_class_name$\n" "\n" "@implementation $root_class_name$\n\n", @@ -406,22 +472,19 @@ void FileGenerator::GenerateSource(io::Printer *printer) { printer->Print( "static GPBExtensionDescription descriptions[] = {\n"); printer->Indent(); - for (vector::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization(printer); + for (const auto& generator : extension_generators_) { + generator->GenerateStaticVariablesInitialization(printer); } - for (vector::iterator iter = - message_generators_.begin(); - iter != message_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization(printer); + for (const auto& generator : message_generators_) { + generator->GenerateStaticVariablesInitialization(printer); } printer->Outdent(); printer->Print( "};\n" "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n" " GPBExtensionDescriptor *extension =\n" - " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]];\n" + " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]\n" + " usesClassRefs:YES];\n" " [registry addExtension:extension];\n" " [self globallyRegisterExtension:extension];\n" " [extension release];\n" @@ -435,10 +498,10 @@ void FileGenerator::GenerateSource(io::Printer *printer) { } else { printer->Print( "// Merge in the imports (direct or indirect) that defined extensions.\n"); - for (vector::iterator iter = + for (std::vector::iterator iter = deps_with_extensions.begin(); iter != deps_with_extensions.end(); ++iter) { - const string root_class_name(FileClassName((*iter))); + const std::string root_class_name(FileClassName((*iter))); printer->Print( "[registry addExtensions:[$dependency$ extensionRegistry]];\n", "dependency", root_class_name); @@ -467,8 +530,8 @@ void FileGenerator::GenerateSource(io::Printer *printer) { printer->Print("\n@end\n\n"); // File descriptor only needed if there are messages to use it. - if (message_generators_.size() > 0) { - std::map vars; + if (!message_generators_.empty()) { + std::map vars; vars["root_class_name"] = root_class_name_; vars["package"] = file_->package(); vars["objc_prefix"] = FileClassPrefix(file_); @@ -492,7 +555,7 @@ void FileGenerator::GenerateSource(io::Printer *printer) { " static GPBFileDescriptor *descriptor = NULL;\n" " if (!descriptor) {\n" " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"); - if (vars["objc_prefix"].size() > 0) { + if (!vars["objc_prefix"].empty()) { printer->Print( vars, " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" @@ -511,13 +574,11 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "\n"); } - for (vector::iterator iter = enum_generators_.begin(); - iter != enum_generators_.end(); ++iter) { - (*iter)->GenerateSource(printer); + for (const auto& generator : enum_generators_) { + generator->GenerateSource(printer); } - for (vector::iterator iter = message_generators_.begin(); - iter != message_generators_.end(); ++iter) { - (*iter)->GenerateSource(printer); + for (const auto& generator : message_generators_) { + generator->GenerateSource(printer); } printer->Print( @@ -531,31 +592,16 @@ void FileGenerator::GenerateSource(io::Printer *printer) { // files. This currently only supports the runtime coming from a framework // as defined by the official CocoaPod. void FileGenerator::PrintFileRuntimePreamble( - io::Printer* printer, const string& header_to_import) const { + io::Printer* printer, + const std::vector& headers_to_import) const { printer->Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" "// source: $filename$\n" "\n", "filename", file_->name()); - - const string framework_name(ProtobufLibraryFrameworkName); - const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name)); - printer->Print( - "// This CPP symbol can be defined to use imports that match up to the framework\n" - "// imports needed when using CocoaPods.\n" - "#if !defined($cpp_symbol$)\n" - " #define $cpp_symbol$ 0\n" - "#endif\n" - "\n" - "#if $cpp_symbol$\n" - " #import <$framework_name$/$header$>\n" - "#else\n" - " #import \"$header$\"\n" - "#endif\n" - "\n", - "cpp_symbol", cpp_symbol, - "header", header_to_import, - "framework_name", framework_name); + ImportWriter::PrintRuntimeImports( + printer, headers_to_import, options_.runtime_import_prefix, true); + printer->Print("\n"); } } // namespace objectivec diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h index a60a6885c01d4..cecbda2e336c7 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h @@ -35,16 +35,10 @@ #include #include #include -#include +#include +#include namespace google { -namespace protobuf { -class FileDescriptor; // descriptor.h -namespace io { -class Printer; // printer.h -} -} - namespace protobuf { namespace compiler { namespace objectivec { @@ -58,25 +52,28 @@ class FileGenerator { FileGenerator(const FileDescriptor* file, const Options& options); ~FileGenerator(); + FileGenerator(const FileGenerator&) = delete; + FileGenerator& operator=(const FileGenerator&) = delete; + void GenerateSource(io::Printer* printer); void GenerateHeader(io::Printer* printer); - const string& RootClassName() const { return root_class_name_; } + const std::string& RootClassName() const { return root_class_name_; } private: const FileDescriptor* file_; - string root_class_name_; + std::string root_class_name_; + bool is_bundled_proto_; - vector enum_generators_; - vector message_generators_; - vector extension_generators_; + std::vector> enum_generators_; + std::vector> message_generators_; + std::vector> extension_generators_; const Options options_; void PrintFileRuntimePreamble( - io::Printer* printer, const string& header_to_import) const; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); + io::Printer* printer, + const std::vector& headers_to_import) const; }; } // namespace objectivec diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc index 3640746798fad..f41bf63ce0410 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc @@ -29,6 +29,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include #include #include #include @@ -50,17 +51,17 @@ bool ObjectiveCGenerator::HasGenerateAll() const { } bool ObjectiveCGenerator::Generate(const FileDescriptor* file, - const string& parameter, + const std::string& parameter, GeneratorContext* context, - string* error) const { + std::string* error) const { *error = "Unimplemented Generate() method. Call GenerateAll() instead."; return false; } -bool ObjectiveCGenerator::GenerateAll(const vector& files, - const string& parameter, - GeneratorContext* context, - string* error) const { +bool ObjectiveCGenerator::GenerateAll( + const std::vector& files, + const std::string& parameter, GeneratorContext* context, + std::string* error) const { // ----------------------------------------------------------------- // Parse generator options. These options are passed to the compiler using the // --objc_opt flag. The options are passed as a comma separated list of @@ -71,7 +72,7 @@ bool ObjectiveCGenerator::GenerateAll(const vector& files Options generation_options; - vector > options; + std::vector > options; ParseGeneratorParameter(parameter, &options); for (int i = 0; i < options.size(); i++) { if (options[i].first == "expected_prefixes_path") { @@ -89,6 +90,15 @@ bool ObjectiveCGenerator::GenerateAll(const vector& files // There is no validation that the prefixes are good prefixes, it is // assumed that they are when you create the file. generation_options.expected_prefixes_path = options[i].second; + } else if (options[i].first == "expected_prefixes_suppressions") { + // A semicolon delimited string that lists the paths of .proto files to + // exclude from the package prefix validations (expected_prefixes_path). + // This is provided as an "out", to skip some files being checked. + for (StringPiece split_piece : Split( + options[i].second, ";", true)) { + generation_options.expected_prefixes_suppressions.push_back( + std::string(split_piece)); + } } else if (options[i].first == "generate_for_named_framework") { // The name of the framework that protos are being generated for. This // will cause the #import statements to be framework based using this @@ -114,13 +124,20 @@ bool ObjectiveCGenerator::GenerateAll(const vector& files // Any number of files can be listed for a framework, just separate them // with commas. // - // There can be multiple lines listing the same frameworkName incase it + // There can be multiple lines listing the same frameworkName in case it // has a lot of proto files included in it; having multiple lines makes // things easier to read. If a proto file is not configured in the // mappings file, it will use the default framework name if one was passed // with generate_for_named_framework, or the relative path to it's include // path otherwise. generation_options.named_framework_to_proto_path_mappings_path = options[i].second; + } else if (options[i].first == "runtime_import_prefix") { + // Path to use as a prefix on #imports of runtime provided headers in the + // generated files. When integrating ObjC protos into a build system, + // this can be used to avoid having to add the runtime directory to the + // header search path since the generate #import will be more complete. + generation_options.runtime_import_prefix = + StripSuffixString(options[i].second, "/"); } else { *error = "error: Unknown generator option: " + options[i].first; return false; @@ -138,11 +155,11 @@ bool ObjectiveCGenerator::GenerateAll(const vector& files for (int i = 0; i < files.size(); i++) { const FileDescriptor* file = files[i]; FileGenerator file_generator(file, generation_options); - string filepath = FilePath(file); + std::string filepath = FilePath(file); // Generate header. { - scoped_ptr output( + std::unique_ptr output( context->Open(filepath + ".pbobjc.h")); io::Printer printer(output.get(), '$'); file_generator.GenerateHeader(&printer); @@ -150,7 +167,7 @@ bool ObjectiveCGenerator::GenerateAll(const vector& files // Generate m file. { - scoped_ptr output( + std::unique_ptr output( context->Open(filepath + ".pbobjc.m")); io::Printer printer(output.get(), '$'); file_generator.GenerateSource(&printer); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h index b172331861b2c..1dbc666af16f7 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h @@ -35,6 +35,9 @@ #include #include +#include + +#include namespace google { namespace protobuf { @@ -45,28 +48,32 @@ namespace objectivec { // header. If you create your own protocol compiler binary and you want it to // support ObjectiveC output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator { +class PROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator { public: ObjectiveCGenerator(); ~ObjectiveCGenerator(); + ObjectiveCGenerator(const ObjectiveCGenerator&) = delete; + ObjectiveCGenerator& operator=(const ObjectiveCGenerator&) = delete; + // implements CodeGenerator ---------------------------------------- - bool HasGenerateAll() const; - bool Generate(const FileDescriptor* file, - const string& parameter, - GeneratorContext* context, - string* error) const; - bool GenerateAll(const vector& files, - const string& parameter, - GeneratorContext* context, - string* error) const; + bool HasGenerateAll() const override; + bool Generate(const FileDescriptor* file, const std::string& parameter, + GeneratorContext* context, std::string* error) const override; + bool GenerateAll(const std::vector& files, + const std::string& parameter, GeneratorContext* context, + std::string* error) const override; - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectiveCGenerator); + uint64_t GetSupportedFeatures() const override { + return FEATURE_PROTO3_OPTIONAL; + } }; } // namespace objectivec } // namespace compiler } // namespace protobuf } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index 54dc7455d92d2..cce1695a844ec 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -38,24 +38,21 @@ #include #include #include +#include #include -#include +#include #include +#include #include #include #include #include +#include +#include #include -#include #include -#if defined(_MSC_VER) -// DO NOT include , instead create functions in io_win32.{h,cc} and import -// them like we do below. -using google::protobuf::internal::win32::open; -#endif - // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some // error cases, so it seems to be ok to use as a back door for errors. @@ -64,18 +61,34 @@ namespace protobuf { namespace compiler { namespace objectivec { +// is transitively included in this file. Import the functions explicitly +// in this port namespace to avoid ambiguous definition. +namespace posix { +#ifdef _WIN32 +using ::google::protobuf::io::win32::open; +#else +using ::open; +#endif +} // namespace port + Options::Options() { // Default is the value of the env for the package prefixes. const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES"); if (file_path) { expected_prefixes_path = file_path; } + const char* suppressions = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES_SUPPRESSIONS"); + if (suppressions) { + expected_prefixes_suppressions = + Split(suppressions, ";", true); + } } namespace { -hash_set MakeWordsMap(const char* const words[], size_t num_words) { - hash_set result; +std::unordered_set MakeWordsMap(const char* const words[], + size_t num_words) { + std::unordered_set result; for (int i = 0; i < num_words; i++) { result.insert(words[i]); } @@ -84,7 +97,7 @@ hash_set MakeWordsMap(const char* const words[], size_t num_words) { const char* const kUpperSegmentsList[] = {"url", "http", "https"}; -hash_set kUpperSegments = +std::unordered_set kUpperSegments = MakeWordsMap(kUpperSegmentsList, GOOGLE_ARRAYSIZE(kUpperSegmentsList)); bool ascii_isnewline(char c) { @@ -94,9 +107,10 @@ bool ascii_isnewline(char c) { // Internal helper for name handing. // Do not expose this outside of helpers, stick to having functions for specific // cases (ClassName(), FieldName()), so there is always consistent suffix rules. -string UnderscoresToCamelCase(const string& input, bool first_capitalized) { - vector values; - string current; +std::string UnderscoresToCamelCase(const std::string& input, + bool first_capitalized) { + std::vector values; + std::string current; bool last_char_was_number = false; bool last_char_was_lower = false; @@ -134,10 +148,11 @@ string UnderscoresToCamelCase(const string& input, bool first_capitalized) { } values.push_back(current); - string result; + std::string result; bool first_segment_forces_upper = false; - for (vector::iterator i = values.begin(); i != values.end(); ++i) { - string value = *i; + for (std::vector::iterator i = values.begin(); i != values.end(); + ++i) { + std::string value = *i; bool all_upper = (kUpperSegments.count(value) > 0); if (all_upper && (result.length() == 0)) { first_segment_forces_upper = true; @@ -160,73 +175,114 @@ string UnderscoresToCamelCase(const string& input, bool first_capitalized) { } const char* const kReservedWordList[] = { - // Objective C "keywords" that aren't in C - // From - // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c - "id", "_cmd", "super", "in", "out", "inout", "bycopy", "byref", "oneway", - "self", - - // C/C++ keywords (Incl C++ 0x11) - // From http://en.cppreference.com/w/cpp/keywords - "and", "and_eq", "alignas", "alignof", "asm", "auto", "bitand", "bitor", - "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class", - "compl", "const", "constexpr", "const_cast", "continue", "decltype", - "default", "delete", "double", "dynamic_cast", "else", "enum", "explicit", - "export", "extern ", "false", "float", "for", "friend", "goto", "if", - "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not", - "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected", - "public", "register", "reinterpret_cast", "return", "short", "signed", - "sizeof", "static", "static_assert", "static_cast", "struct", "switch", - "template", "this", "thread_local", "throw", "true", "try", "typedef", - "typeid", "typename", "union", "unsigned", "using", "virtual", "void", - "volatile", "wchar_t", "while", "xor", "xor_eq", - - // C99 keywords - // From - // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm - "restrict", - - // Objective-C Runtime typedefs - // From - "Category", "Ivar", "Method", "Protocol", - - // NSObject Methods - // new is covered by C++ keywords. - "description", "debugDescription", "finalize", "hash", "dealloc", "init", - "class", "superclass", "retain", "release", "autorelease", "retainCount", - "zone", "isProxy", "copy", "mutableCopy", "classForCoder", - - // GPBMessage Methods - // Only need to add instance methods that may conflict with - // method declared in protos. The main cases are methods - // that take no arguments, or setFoo:/hasFoo: type methods. - "clear", "data", "delimitedData", "descriptor", "extensionRegistry", - "extensionsCurrentlySet", "initialized", "isInitialized", "serializedSize", - "sortedExtensionsInUse", "unknownFields", - - // MacTypes.h names - "Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount", - "ByteOffset", "Duration", "AbsoluteTime", "OptionBits", "ItemCount", - "PBVersion", "ScriptCode", "LangCode", "RegionCode", "OSType", - "ProcessSerialNumber", "Point", "Rect", "FixedPoint", "FixedRect", "Style", - "StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord", + // Note NSObject Methods: + // These are brought in from objectivec_nsobject_methods.h that is generated + // using method_dump.sh. See kNSObjectMethods below. + + // Objective C "keywords" that aren't in C + // From + // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c + // with some others added on. + "id", "_cmd", "super", "in", "out", "inout", "bycopy", "byref", "oneway", + "self", "instancetype", "nullable", "nonnull", "nil", "Nil", + "YES", "NO", "weak", + + // C/C++ keywords (Incl C++ 0x11) + // From http://en.cppreference.com/w/cpp/keywords + "and", "and_eq", "alignas", "alignof", "asm", "auto", "bitand", "bitor", + "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class", + "compl", "const", "constexpr", "const_cast", "continue", "decltype", + "default", "delete", "double", "dynamic_cast", "else", "enum", "explicit", + "export", "extern ", "false", "float", "for", "friend", "goto", "if", + "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not", + "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected", + "public", "register", "reinterpret_cast", "return", "short", "signed", + "sizeof", "static", "static_assert", "static_cast", "struct", "switch", + "template", "this", "thread_local", "throw", "true", "try", "typedef", + "typeid", "typename", "union", "unsigned", "using", "virtual", "void", + "volatile", "wchar_t", "while", "xor", "xor_eq", + + // C99 keywords + // From + // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm + "restrict", + + // GCC/Clang extension + "typeof", + + // Not a keyword, but will break you + "NULL", + + // Objective-C Runtime typedefs + // From + "Category", "Ivar", "Method", "Protocol", + + // GPBMessage Methods + // Only need to add instance methods that may conflict with + // method declared in protos. The main cases are methods + // that take no arguments, or setFoo:/hasFoo: type methods. + "clear", "data", "delimitedData", "descriptor", "extensionRegistry", + "extensionsCurrentlySet", "initialized", "isInitialized", "serializedSize", + "sortedExtensionsInUse", "unknownFields", + + // MacTypes.h names + "Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount", + "ByteOffset", "Duration", "AbsoluteTime", "OptionBits", "ItemCount", + "PBVersion", "ScriptCode", "LangCode", "RegionCode", "OSType", + "ProcessSerialNumber", "Point", "Rect", "FixedPoint", "FixedRect", "Style", + "StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord", }; -hash_set kReservedWords = - MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList)); +// returns true is input starts with __ or _[A-Z] which are reserved identifiers +// in C/ C++. All calls should go through UnderscoresToCamelCase before getting here +// but this verifies and allows for future expansion if we decide to redefine what a +// reserved C identifier is (for example the GNU list +// https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html ) +bool IsReservedCIdentifier(const std::string& input) { + if (input.length() > 2) { + if (input.at(0) == '_') { + if (isupper(input.at(1)) || input.at(1) == '_') { + return true; + } + } + } + return false; +} -string SanitizeNameForObjC(const string& input, - const string& extension, - string* out_suffix_added) { - if (kReservedWords.count(input) > 0) { +std::string SanitizeNameForObjC(const std::string& prefix, + const std::string& input, + const std::string& extension, + std::string* out_suffix_added) { + static const std::unordered_set kReservedWords = + MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList)); + static const std::unordered_set kNSObjectMethods = + MakeWordsMap(kNSObjectMethodsList, GOOGLE_ARRAYSIZE(kNSObjectMethodsList)); + std::string sanitized; + // We add the prefix in the cases where the string is missing a prefix. + // We define "missing a prefix" as where 'input': + // a) Doesn't start with the prefix or + // b) Isn't equivalent to the prefix or + // c) Has the prefix, but the letter after the prefix is lowercase + if (HasPrefixString(input, prefix)) { + if (input.length() == prefix.length() || !ascii_isupper(input[prefix.length()])) { + sanitized = prefix + input; + } else { + sanitized = input; + } + } else { + sanitized = prefix + input; + } + if (IsReservedCIdentifier(sanitized) || + (kReservedWords.count(sanitized) > 0) || + (kNSObjectMethods.count(sanitized) > 0)) { if (out_suffix_added) *out_suffix_added = extension; - return input + extension; + return sanitized + extension; } if (out_suffix_added) out_suffix_added->clear(); - return input; + return sanitized; } -string NameFromFieldDescriptor(const FieldDescriptor* field) { +std::string NameFromFieldDescriptor(const FieldDescriptor* field) { if (field->type() == FieldDescriptor::TYPE_GROUP) { return field->message_type()->name(); } else { @@ -234,9 +290,10 @@ string NameFromFieldDescriptor(const FieldDescriptor* field) { } } -void PathSplit(const string& path, string* directory, string* basename) { - string::size_type last_slash = path.rfind('/'); - if (last_slash == string::npos) { +void PathSplit(const std::string& path, std::string* directory, + std::string* basename) { + std::string::size_type last_slash = path.rfind('/'); + if (last_slash == std::string::npos) { if (directory) { *directory = ""; } @@ -253,7 +310,7 @@ void PathSplit(const string& path, string* directory, string* basename) { } } -bool IsSpecialName(const string& name, const string* special_names, +bool IsSpecialName(const std::string& name, const std::string* special_names, size_t count) { for (size_t i = 0; i < count; ++i) { size_t length = special_names[i].length(); @@ -271,7 +328,7 @@ bool IsSpecialName(const string& name, const string* special_names, return false; } -string GetZeroEnumNameForFlagType(const FlagType flag_type) { +std::string GetZeroEnumNameForFlagType(const FlagType flag_type) { switch(flag_type) { case FLAGTYPE_DESCRIPTOR_INITIALIZATION: return "GPBDescriptorInitializationFlag_None"; @@ -285,7 +342,7 @@ string GetZeroEnumNameForFlagType(const FlagType flag_type) { } } -string GetEnumNameForFlagType(const FlagType flag_type) { +std::string GetEnumNameForFlagType(const FlagType flag_type) { switch(flag_type) { case FLAGTYPE_DESCRIPTOR_INITIALIZATION: return "GPBDescriptorInitializationFlags"; @@ -295,26 +352,18 @@ string GetEnumNameForFlagType(const FlagType flag_type) { return "GPBFieldFlags"; default: GOOGLE_LOG(FATAL) << "Can't get here."; - return string(); + return std::string(); } } } // namespace // Escape C++ trigraphs by escaping question marks to \? -string EscapeTrigraphs(const string& to_escape) { +std::string EscapeTrigraphs(const std::string& to_escape) { return StringReplace(to_escape, "?", "\\?", true); } -string StripProto(const string& filename) { - if (HasSuffixString(filename, ".protodevel")) { - return StripSuffixString(filename, ".protodevel"); - } else { - return StripSuffixString(filename, ".proto"); - } -} - -void StringPieceTrimWhitespace(StringPiece* input) { +void TrimWhitespace(StringPiece* input) { while (!input->empty() && ascii_isspace(*input->data())) { input->remove_prefix(1); } @@ -323,38 +372,37 @@ void StringPieceTrimWhitespace(StringPiece* input) { } } - -bool IsRetainedName(const string& name) { +bool IsRetainedName(const std::string& name) { // List of prefixes from // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html - static const string retained_names[] = {"new", "alloc", "copy", - "mutableCopy"}; + static const std::string retained_names[] = {"new", "alloc", "copy", + "mutableCopy"}; return IsSpecialName(name, retained_names, sizeof(retained_names) / sizeof(retained_names[0])); } -bool IsInitName(const string& name) { - static const string init_names[] = {"init"}; +bool IsInitName(const std::string& name) { + static const std::string init_names[] = {"init"}; return IsSpecialName(name, init_names, sizeof(init_names) / sizeof(init_names[0])); } -string BaseFileName(const FileDescriptor* file) { - string basename; +std::string BaseFileName(const FileDescriptor* file) { + std::string basename; PathSplit(file->name(), NULL, &basename); return basename; } -string FileClassPrefix(const FileDescriptor* file) { +std::string FileClassPrefix(const FileDescriptor* file) { // Default is empty string, no need to check has_objc_class_prefix. - string result = file->options().objc_class_prefix(); + std::string result = file->options().objc_class_prefix(); return result; } -string FilePath(const FileDescriptor* file) { - string output; - string basename; - string directory; +std::string FilePath(const FileDescriptor* file) { + std::string output; + std::string basename; + std::string directory; PathSplit(file->name(), &directory, &basename); if (directory.length() > 0) { output = directory + "/"; @@ -368,10 +416,10 @@ string FilePath(const FileDescriptor* file) { return output; } -string FilePathBasename(const FileDescriptor* file) { - string output; - string basename; - string directory; +std::string FilePathBasename(const FileDescriptor* file) { + std::string output; + std::string basename; + std::string directory; PathSplit(file->name(), &directory, &basename); basename = StripProto(basename); @@ -381,17 +429,17 @@ string FilePathBasename(const FileDescriptor* file) { return output; } -string FileClassName(const FileDescriptor* file) { - string name = FileClassPrefix(file); - name += UnderscoresToCamelCase(StripProto(BaseFileName(file)), true); - name += "Root"; +std::string FileClassName(const FileDescriptor* file) { + const std::string prefix = FileClassPrefix(file); + const std::string name = + UnderscoresToCamelCase(StripProto(BaseFileName(file)), true) + "Root"; // There aren't really any reserved words that end in "Root", but playing // it safe and checking. - return SanitizeNameForObjC(name, "_RootClass", NULL); + return SanitizeNameForObjC(prefix, name, "_RootClass", NULL); } -string ClassNameWorker(const Descriptor* descriptor) { - string name; +std::string ClassNameWorker(const Descriptor* descriptor) { + std::string name; if (descriptor->containing_type() != NULL) { name = ClassNameWorker(descriptor->containing_type()); name += "_"; @@ -399,8 +447,8 @@ string ClassNameWorker(const Descriptor* descriptor) { return name + descriptor->name(); } -string ClassNameWorker(const EnumDescriptor* descriptor) { - string name; +std::string ClassNameWorker(const EnumDescriptor* descriptor) { + std::string name; if (descriptor->containing_type() != NULL) { name = ClassNameWorker(descriptor->containing_type()); name += "_"; @@ -408,19 +456,20 @@ string ClassNameWorker(const EnumDescriptor* descriptor) { return name + descriptor->name(); } -string ClassName(const Descriptor* descriptor) { +std::string ClassName(const Descriptor* descriptor) { return ClassName(descriptor, NULL); } -string ClassName(const Descriptor* descriptor, string* out_suffix_added) { +std::string ClassName(const Descriptor* descriptor, + std::string* out_suffix_added) { // 1. Message names are used as is (style calls for CamelCase, trust it). // 2. Check for reserved word at the very end and then suffix things. - string prefix = FileClassPrefix(descriptor->file()); - string name = ClassNameWorker(descriptor); - return SanitizeNameForObjC(prefix + name, "_Class", out_suffix_added); + const std::string prefix = FileClassPrefix(descriptor->file()); + const std::string name = ClassNameWorker(descriptor); + return SanitizeNameForObjC(prefix, name, "_Class", out_suffix_added); } -string EnumName(const EnumDescriptor* descriptor) { +std::string EnumName(const EnumDescriptor* descriptor) { // 1. Enum names are used as is (style calls for CamelCase, trust it). // 2. Check for reserved word at the every end and then suffix things. // message Fixed { @@ -429,27 +478,28 @@ string EnumName(const EnumDescriptor* descriptor) { // ... // } // yields Fixed_Class, Fixed_Size. - string name = FileClassPrefix(descriptor->file()); - name += ClassNameWorker(descriptor); - return SanitizeNameForObjC(name, "_Enum", NULL); + const std::string prefix = FileClassPrefix(descriptor->file()); + const std::string name = ClassNameWorker(descriptor); + return SanitizeNameForObjC(prefix, name, "_Enum", NULL); } -string EnumValueName(const EnumValueDescriptor* descriptor) { +std::string EnumValueName(const EnumValueDescriptor* descriptor) { // Because of the Switch enum compatibility, the name on the enum has to have // the suffix handing, so it slightly diverges from how nested classes work. // enum Fixed { // FOO = 1 // } // yields Fixed_Enum and Fixed_Enum_Foo (not Fixed_Foo). - const string& class_name = EnumName(descriptor->type()); - const string& value_str = UnderscoresToCamelCase(descriptor->name(), true); - const string& name = class_name + "_" + value_str; + const std::string class_name = EnumName(descriptor->type()); + const std::string value_str = + UnderscoresToCamelCase(descriptor->name(), true); + const std::string name = class_name + "_" + value_str; // There aren't really any reserved words with an underscore and a leading // capital letter, but playing it safe and checking. - return SanitizeNameForObjC(name, "_Value", NULL); + return SanitizeNameForObjC("", name, "_Value", NULL); } -string EnumValueShortName(const EnumValueDescriptor* descriptor) { +std::string EnumValueShortName(const EnumValueDescriptor* descriptor) { // Enum value names (EnumValueName above) are the enum name turned into // a class name and then the value name is CamelCased and concatenated; the // whole thing then gets sanitized for reserved words. @@ -462,14 +512,14 @@ string EnumValueShortName(const EnumValueDescriptor* descriptor) { // So the right way to get the short name is to take the full enum name // and then strip off the enum name (leaving the value name and anything // done by sanitize). - const string& class_name = EnumName(descriptor->type()); - const string& long_name_prefix = class_name + "_"; - const string& long_name = EnumValueName(descriptor); + const std::string class_name = EnumName(descriptor->type()); + const std::string long_name_prefix = class_name + "_"; + const std::string long_name = EnumValueName(descriptor); return StripPrefixString(long_name, long_name_prefix); } -string UnCamelCaseEnumShortName(const string& name) { - string result; +std::string UnCamelCaseEnumShortName(const std::string& name) { + std::string result; for (int i = 0; i < name.size(); i++) { char c = name[i]; if (i > 0 && ascii_isupper(c)) { @@ -480,15 +530,15 @@ string UnCamelCaseEnumShortName(const string& name) { return result; } -string ExtensionMethodName(const FieldDescriptor* descriptor) { - const string& name = NameFromFieldDescriptor(descriptor); - const string& result = UnderscoresToCamelCase(name, false); - return SanitizeNameForObjC(result, "_Extension", NULL); +std::string ExtensionMethodName(const FieldDescriptor* descriptor) { + const std::string name = NameFromFieldDescriptor(descriptor); + const std::string result = UnderscoresToCamelCase(name, false); + return SanitizeNameForObjC("", result, "_Extension", NULL); } -string FieldName(const FieldDescriptor* field) { - const string& name = NameFromFieldDescriptor(field); - string result = UnderscoresToCamelCase(name, false); +std::string FieldName(const FieldDescriptor* field) { + const std::string name = NameFromFieldDescriptor(field); + std::string result = UnderscoresToCamelCase(name, false); if (field->is_repeated() && !field->is_map()) { // Add "Array" before do check for reserved worlds. result += "Array"; @@ -498,45 +548,53 @@ string FieldName(const FieldDescriptor* field) { result += "_p"; } } - return SanitizeNameForObjC(result, "_p", NULL); + return SanitizeNameForObjC("", result, "_p", NULL); } -string FieldNameCapitalized(const FieldDescriptor* field) { +std::string FieldNameCapitalized(const FieldDescriptor* field) { // Want the same suffix handling, so upcase the first letter of the other // name. - string result = FieldName(field); + std::string result = FieldName(field); if (result.length() > 0) { result[0] = ascii_toupper(result[0]); } return result; } -string OneofEnumName(const OneofDescriptor* descriptor) { +std::string OneofEnumName(const OneofDescriptor* descriptor) { const Descriptor* fieldDescriptor = descriptor->containing_type(); - string name = ClassName(fieldDescriptor); + std::string name = ClassName(fieldDescriptor); name += "_" + UnderscoresToCamelCase(descriptor->name(), true) + "_OneOfCase"; // No sanitize needed because the OS never has names that end in _OneOfCase. return name; } -string OneofName(const OneofDescriptor* descriptor) { - string name = UnderscoresToCamelCase(descriptor->name(), false); +std::string OneofName(const OneofDescriptor* descriptor) { + std::string name = UnderscoresToCamelCase(descriptor->name(), false); // No sanitize needed because it gets OneOfCase added and that shouldn't // ever conflict. return name; } -string OneofNameCapitalized(const OneofDescriptor* descriptor) { +std::string OneofNameCapitalized(const OneofDescriptor* descriptor) { // Use the common handling and then up-case the first letter. - string result = OneofName(descriptor); + std::string result = OneofName(descriptor); if (result.length() > 0) { result[0] = ascii_toupper(result[0]); } return result; } -string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field) { - string worker(name); +std::string ObjCClass(const std::string& class_name) { + return std::string("GPBObjCClass(") + class_name + ")"; +} + +std::string ObjCClassDeclaration(const std::string& class_name) { + return std::string("GPBObjCClassDeclaration(") + class_name + ");"; +} + +std::string UnCamelCaseFieldName(const std::string& name, const FieldDescriptor* field) { + std::string worker(name); if (HasSuffixString(worker, "_p")) { worker = StripSuffixString(worker, "_p"); } @@ -551,7 +609,7 @@ string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field) { } return worker; } else { - string result; + std::string result; for (int i = 0; i < worker.size(); i++) { char c = worker[i]; if (ascii_isupper(c)) { @@ -567,7 +625,7 @@ string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field) { } } -string GetCapitalizedType(const FieldDescriptor* field) { +std::string GetCapitalizedType(const FieldDescriptor* field) { switch (field->type()) { case FieldDescriptor::TYPE_INT32: return "Int32"; @@ -610,7 +668,7 @@ string GetCapitalizedType(const FieldDescriptor* field) { // Some compilers report reaching end of function even though all cases of // the enum are handed in the switch. GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; + return std::string(); } ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type) { @@ -684,7 +742,8 @@ bool IsReferenceType(const FieldDescriptor* field) { return !IsPrimitiveType(field); } -static string HandleExtremeFloatingPoint(string val, bool add_float_suffix) { +static std::string HandleExtremeFloatingPoint(std::string val, + bool add_float_suffix) { if (val == "nan") { return "NAN"; } else if (val == "inf") { @@ -693,16 +752,16 @@ static string HandleExtremeFloatingPoint(string val, bool add_float_suffix) { return "-INFINITY"; } else { // float strings with ., e or E need to have f appended - if (add_float_suffix && - (val.find(".") != string::npos || val.find("e") != string::npos || - val.find("E") != string::npos)) { + if (add_float_suffix && (val.find(".") != std::string::npos || + val.find("e") != std::string::npos || + val.find("E") != std::string::npos)) { val += "f"; } return val; } } -string GPBGenericValueFieldName(const FieldDescriptor* field) { +std::string GPBGenericValueFieldName(const FieldDescriptor* field) { // Returns the field within the GPBGenericValue union to use for the given // field. if (field->is_repeated()) { @@ -738,11 +797,11 @@ string GPBGenericValueFieldName(const FieldDescriptor* field) { // Some compilers report reaching end of function even though all cases of // the enum are handed in the switch. GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; + return std::string(); } -string DefaultValue(const FieldDescriptor* field) { +std::string DefaultValue(const FieldDescriptor* field) { // Repeated fields don't have defaults. if (field->is_repeated()) { return "nil"; @@ -756,17 +815,17 @@ string DefaultValue(const FieldDescriptor* field) { if (field->default_value_int32() == INT_MIN) { return "-0x80000000"; } - return SimpleItoa(field->default_value_int32()); + return StrCat(field->default_value_int32()); case FieldDescriptor::CPPTYPE_UINT32: - return SimpleItoa(field->default_value_uint32()) + "U"; + return StrCat(field->default_value_uint32()) + "U"; case FieldDescriptor::CPPTYPE_INT64: // gcc and llvm reject the decimal form of kint32min and kint64min. if (field->default_value_int64() == LLONG_MIN) { return "-0x8000000000000000LL"; } - return SimpleItoa(field->default_value_int64()) + "LL"; + return StrCat(field->default_value_int64()) + "LL"; case FieldDescriptor::CPPTYPE_UINT64: - return SimpleItoa(field->default_value_uint64()) + "ULL"; + return StrCat(field->default_value_uint64()) + "ULL"; case FieldDescriptor::CPPTYPE_DOUBLE: return HandleExtremeFloatingPoint( SimpleDtoa(field->default_value_double()), false); @@ -777,7 +836,7 @@ string DefaultValue(const FieldDescriptor* field) { return field->default_value_bool() ? "YES" : "NO"; case FieldDescriptor::CPPTYPE_STRING: { const bool has_default_value = field->has_default_value(); - const string& default_string = field->default_value_string(); + const std::string& default_string = field->default_value_string(); if (!has_default_value || default_string.length() == 0) { // If the field is defined as being the empty string, // then we will just assign to nil, as the empty string is the @@ -794,7 +853,7 @@ string DefaultValue(const FieldDescriptor* field) { // Must convert to a standard byte order for packing length into // a cstring. uint32 length = ghtonl(default_string.length()); - string bytes((const char*)&length, sizeof(length)); + std::string bytes((const char*)&length, sizeof(length)); bytes.append(default_string); return "(NSData*)\"" + EscapeTrigraphs(CEscape(bytes)) + "\""; } else { @@ -810,7 +869,7 @@ string DefaultValue(const FieldDescriptor* field) { // Some compilers report reaching end of function even though all cases of // the enum are handed in the switch. GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; + return std::string(); } bool HasNonZeroDefaultValue(const FieldDescriptor* field) { @@ -843,7 +902,7 @@ bool HasNonZeroDefaultValue(const FieldDescriptor* field) { case FieldDescriptor::CPPTYPE_BOOL: return field->default_value_bool(); case FieldDescriptor::CPPTYPE_STRING: { - const string& default_string = field->default_value_string(); + const std::string& default_string = field->default_value_string(); return default_string.length() != 0; } case FieldDescriptor::CPPTYPE_ENUM: @@ -858,14 +917,14 @@ bool HasNonZeroDefaultValue(const FieldDescriptor* field) { return false; } -string BuildFlagsString(const FlagType flag_type, - const vector& strings) { - if (strings.size() == 0) { +std::string BuildFlagsString(const FlagType flag_type, + const std::vector& strings) { + if (strings.empty()) { return GetZeroEnumNameForFlagType(flag_type); } else if (strings.size() == 1) { return strings[0]; } - string string("(" + GetEnumNameForFlagType(flag_type) + ")("); + std::string string("(" + GetEnumNameForFlagType(flag_type) + ")("); for (size_t i = 0; i != strings.size(); ++i) { if (i > 0) { string.append(" | "); @@ -876,25 +935,25 @@ string BuildFlagsString(const FlagType flag_type, return string; } -string BuildCommentsString(const SourceLocation& location, +std::string BuildCommentsString(const SourceLocation& location, bool prefer_single_line) { - const string& comments = location.leading_comments.empty() + const std::string& comments = location.leading_comments.empty() ? location.trailing_comments : location.leading_comments; - vector lines; - SplitStringAllowEmpty(comments, "\n", &lines); + std::vector lines; + lines = Split(comments, "\n", false); while (!lines.empty() && lines.back().empty()) { lines.pop_back(); } // If there are no comments, just return an empty string. - if (lines.size() == 0) { + if (lines.empty()) { return ""; } - string prefix; - string suffix; - string final_comments; - string epilogue; + std::string prefix; + std::string suffix; + std::string final_comments; + std::string epilogue; bool add_leading_space = false; @@ -910,7 +969,7 @@ string BuildCommentsString(const SourceLocation& location, } for (int i = 0; i < lines.size(); i++) { - string line = StripPrefixString(lines[i], " "); + std::string line = StripPrefixString(lines[i], " "); // HeaderDoc and appledoc use '\' and '@' for markers; escape them. line = StringReplace(line, "\\", "\\\\", true); line = StringReplace(line, "@", "\\@", true); @@ -934,9 +993,9 @@ string BuildCommentsString(const SourceLocation& location, // use a different value; so it isn't as simple as a option. const char* const ProtobufLibraryFrameworkName = "Protobuf"; -string ProtobufFrameworkImportSymbol(const string& framework_name) { +std::string ProtobufFrameworkImportSymbol(const std::string& framework_name) { // GPB_USE_[framework_name]_FRAMEWORK_IMPORTS - string result = string("GPB_USE_"); + std::string result = std::string("GPB_USE_"); result += ToUpper(framework_name); result += "_FRAMEWORK_IMPORTS"; return result; @@ -946,7 +1005,7 @@ bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file) { // We don't check the name prefix or proto package because some files // (descriptor.proto), aren't shipped generated by the library, so this // seems to be the safest way to only catch the ones shipped. - const string name = file->name(); + const std::string name = file->name(); if (name == "google/protobuf/any.proto" || name == "google/protobuf/api.proto" || name == "google/protobuf/duration.proto" || @@ -985,37 +1044,36 @@ namespace { class ExpectedPrefixesCollector : public LineConsumer { public: - ExpectedPrefixesCollector(std::map* inout_package_to_prefix_map) + ExpectedPrefixesCollector(std::map* inout_package_to_prefix_map) : prefix_map_(inout_package_to_prefix_map) {} - virtual bool ConsumeLine(const StringPiece& line, string* out_error); + virtual bool ConsumeLine(const StringPiece& line, std::string* out_error); private: - std::map* prefix_map_; + std::map* prefix_map_; }; bool ExpectedPrefixesCollector::ConsumeLine( - const StringPiece& line, string* out_error) { + const StringPiece& line, std::string* out_error) { int offset = line.find('='); if (offset == StringPiece::npos) { - *out_error = - string("Expected prefixes file line without equal sign: '") + - line.ToString() + "'."; + *out_error = std::string("Expected prefixes file line without equal sign: '") + + std::string(line) + "'."; return false; } - StringPiece package(line, 0, offset); - StringPiece prefix(line, offset + 1, line.length() - offset - 1); - StringPieceTrimWhitespace(&package); - StringPieceTrimWhitespace(&prefix); + StringPiece package = line.substr(0, offset); + StringPiece prefix = line.substr(offset + 1); + TrimWhitespace(&package); + TrimWhitespace(&prefix); // Don't really worry about error checking the package/prefix for // being valid. Assume the file is validated when it is created/edited. - (*prefix_map_)[package.ToString()] = prefix.ToString(); + (*prefix_map_)[std::string(package)] = std::string(prefix); return true; } -bool LoadExpectedPackagePrefixes(const Options &generation_options, - std::map* prefix_map, - string* out_error) { +bool LoadExpectedPackagePrefixes(const Options& generation_options, + std::map* prefix_map, + std::string* out_error) { if (generation_options.expected_prefixes_path.empty()) { return true; } @@ -1026,19 +1084,18 @@ bool LoadExpectedPackagePrefixes(const Options &generation_options, } bool ValidateObjCClassPrefix( - const FileDescriptor* file, - const string& expected_prefixes_path, - const std::map& expected_package_prefixes, - string* out_error) { - const string prefix = file->options().objc_class_prefix(); - const string package = file->package(); + const FileDescriptor* file, const std::string& expected_prefixes_path, + const std::map& expected_package_prefixes, + std::string* out_error) { + const std::string prefix = file->options().objc_class_prefix(); + const std::string package = file->package(); // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some // error cases, so it seems to be ok to use as a back door for warnings. // Check: Error - See if there was an expected prefix for the package and // report if it doesn't match (wrong or missing). - std::map::const_iterator package_match = + std::map::const_iterator package_match = expected_package_prefixes.find(package); if (package_match != expected_package_prefixes.end()) { // There was an entry, and... @@ -1068,7 +1125,7 @@ bool ValidateObjCClassPrefix( // to Apple's rules (the checks above implicitly whitelist anything that // doesn't meet these rules). if (!ascii_isupper(prefix[0])) { - std::cerr << std::endl + std::cerr << "protoc:0: warning: Invalid 'option objc_class_prefix = \"" << prefix << "\";' in '" << file->name() << "';" << " it should start with a capital letter." << std::endl; @@ -1077,7 +1134,7 @@ bool ValidateObjCClassPrefix( if (prefix.length() < 3) { // Apple reserves 2 character prefixes for themselves. They do use some // 3 character prefixes, but they haven't updated the rules/docs. - std::cerr << std::endl + std::cerr << "protoc:0: warning: Invalid 'option objc_class_prefix = \"" << prefix << "\";' in '" << file->name() << "';" << " Apple recommends they should be at least 3 characters long." @@ -1086,8 +1143,9 @@ bool ValidateObjCClassPrefix( } // Look for any other package that uses the same prefix. - string other_package_for_prefix; - for (std::map::const_iterator i = expected_package_prefixes.begin(); + std::string other_package_for_prefix; + for (std::map::const_iterator i = + expected_package_prefixes.begin(); i != expected_package_prefixes.end(); ++i) { if (i->second == prefix) { other_package_for_prefix = i->first; @@ -1101,7 +1159,7 @@ bool ValidateObjCClassPrefix( // The file does not have a package and ... if (other_package_for_prefix.empty()) { // ... no other package has declared that prefix. - std::cerr << std::endl + std::cerr << "protoc:0: warning: File '" << file->name() << "' has no " << "package. Consider adding a new package to the proto and adding '" << "new.package = " << prefix << "' to the expected prefixes file (" @@ -1109,7 +1167,7 @@ bool ValidateObjCClassPrefix( std::cerr.flush(); } else { // ... another package has declared the same prefix. - std::cerr << std::endl + std::cerr << "protoc:0: warning: File '" << file->name() << "' has no package " << "and package '" << other_package_for_prefix << "' already uses '" << prefix << "' as its prefix. Consider either adding a new package " @@ -1138,7 +1196,7 @@ bool ValidateObjCClassPrefix( // Check: Warning - If the given package/prefix pair wasn't expected, issue a // warning issue a warning suggesting it gets added to the file. if (!expected_package_prefixes.empty()) { - std::cerr << std::endl + std::cerr << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \"" << prefix << "\";' in '" << file->name() << "';" << " consider adding it to the expected prefixes file (" @@ -1151,11 +1209,11 @@ bool ValidateObjCClassPrefix( } // namespace -bool ValidateObjCClassPrefixes(const vector& files, +bool ValidateObjCClassPrefixes(const std::vector& files, const Options& generation_options, - string* out_error) { + std::string* out_error) { // Load the expected package prefixes, if available, to validate against. - std::map expected_package_prefixes; + std::map expected_package_prefixes; if (!LoadExpectedPackagePrefixes(generation_options, &expected_package_prefixes, out_error)) { @@ -1163,6 +1221,15 @@ bool ValidateObjCClassPrefixes(const vector& files, } for (int i = 0; i < files.size(); i++) { + bool should_skip = + (std::find(generation_options.expected_prefixes_suppressions.begin(), + generation_options.expected_prefixes_suppressions.end(), + files[i]->name()) + != generation_options.expected_prefixes_suppressions.end()); + if (should_skip) { + continue; + } + bool is_valid = ValidateObjCClassPrefix(files[i], generation_options.expected_prefixes_path, @@ -1180,9 +1247,9 @@ TextFormatDecodeData::TextFormatDecodeData() { } TextFormatDecodeData::~TextFormatDecodeData() { } void TextFormatDecodeData::AddString(int32 key, - const string& input_for_decode, - const string& desired_output) { - for (vector::const_iterator i = entries_.begin(); + const std::string& input_for_decode, + const std::string& desired_output) { + for (std::vector::const_iterator i = entries_.begin(); i != entries_.end(); ++i) { if (i->first == key) { std::cerr << "error: duplicate key (" << key @@ -1193,12 +1260,12 @@ void TextFormatDecodeData::AddString(int32 key, } } - const string& data = TextFormatDecodeData::DecodeDataForString( + const std::string& data = TextFormatDecodeData::DecodeDataForString( input_for_decode, desired_output); entries_.push_back(DataEntry(key, data)); } -string TextFormatDecodeData::Data() const { +std::string TextFormatDecodeData::Data() const { std::ostringstream data_stringstream; if (num_entries() > 0) { @@ -1206,7 +1273,7 @@ string TextFormatDecodeData::Data() const { io::CodedOutputStream output_stream(&data_outputstream); output_stream.WriteVarint32(num_entries()); - for (vector::const_iterator i = entries_.begin(); + for (std::vector::const_iterator i = entries_.begin(); i != entries_.end(); ++i) { output_stream.WriteVarint32(i->first); output_stream.WriteString(i->second); @@ -1229,20 +1296,20 @@ class DecodeDataBuilder { Push(); need_underscore_ = true; } - string Finish() { + std::string Finish() { Push(); return decode_data_; } private: - static const uint8 kAddUnderscore = 0x80; + static constexpr uint8 kAddUnderscore = 0x80; - static const uint8 kOpAsIs = 0x00; - static const uint8 kOpFirstUpper = 0x40; - static const uint8 kOpFirstLower = 0x20; - static const uint8 kOpAllUpper = 0x60; + static constexpr uint8 kOpAsIs = 0x00; + static constexpr uint8 kOpFirstUpper = 0x40; + static constexpr uint8 kOpFirstLower = 0x20; + static constexpr uint8 kOpAllUpper = 0x60; - static const int kMaxSegmentLen = 0x1f; + static constexpr int kMaxSegmentLen = 0x1f; void AddChar(const char desired) { ++segment_len_; @@ -1285,7 +1352,7 @@ class DecodeDataBuilder { uint8 op_; int segment_len_; - string decode_data_; + std::string decode_data_; }; bool DecodeDataBuilder::AddCharacter(const char desired, const char input) { @@ -1326,8 +1393,8 @@ bool DecodeDataBuilder::AddCharacter(const char desired, const char input) { // If decode data can't be generated, a directive for the raw string // is used instead. -string DirectDecodeString(const string& str) { - string result; +std::string DirectDecodeString(const std::string& str) { + std::string result; result += (char)'\0'; // Marker for full string. result += str; result += (char)'\0'; // End of string. @@ -1337,17 +1404,17 @@ string DirectDecodeString(const string& str) { } // namespace // static -string TextFormatDecodeData::DecodeDataForString(const string& input_for_decode, - const string& desired_output) { - if ((input_for_decode.size() == 0) || (desired_output.size() == 0)) { +std::string TextFormatDecodeData::DecodeDataForString( + const std::string& input_for_decode, const std::string& desired_output) { + if (input_for_decode.empty() || desired_output.empty()) { std::cerr << "error: got empty string for making TextFormat data, input: \"" << input_for_decode << "\", desired: \"" << desired_output << "\"." << std::endl; std::cerr.flush(); abort(); } - if ((input_for_decode.find('\0') != string::npos) || - (desired_output.find('\0') != string::npos)) { + if ((input_for_decode.find('\0') != std::string::npos) || + (desired_output.find('\0') != std::string::npos)) { std::cerr << "error: got a null char in a string for making TextFormat data," << " input: \"" << CEscape(input_for_decode) << "\", desired: \"" << CEscape(desired_output) << "\"." << std::endl; @@ -1402,21 +1469,21 @@ class Parser { bool Finish(); int last_line() const { return line_; } - string error_str() const { return error_str_; } + std::string error_str() const { return error_str_; } private: bool ParseLoop(); LineConsumer* line_consumer_; int line_; - string error_str_; + std::string error_str_; StringPiece p_; - string leftover_; + std::string leftover_; }; bool Parser::ParseChunk(StringPiece chunk) { if (!leftover_.empty()) { - chunk.AppendToString(&leftover_); + leftover_ += std::string(chunk); p_ = StringPiece(leftover_); } else { p_ = chunk; @@ -1425,7 +1492,7 @@ bool Parser::ParseChunk(StringPiece chunk) { if (p_.empty()) { leftover_.clear(); } else { - leftover_ = p_.ToString(); + leftover_ = std::string(p_); } return result; } @@ -1448,8 +1515,8 @@ bool Parser::ParseLoop() { while (ReadLine(&p_, &line)) { ++line_; RemoveComment(&line); - StringPieceTrimWhitespace(&line); - if (line.size() == 0) { + TrimWhitespace(&line); + if (line.empty()) { continue; // Blank line. } if (!line_consumer_->ConsumeLine(line, &error_str_)) { @@ -1465,15 +1532,15 @@ LineConsumer::LineConsumer() {} LineConsumer::~LineConsumer() {} -bool ParseSimpleFile( - const string& path, LineConsumer* line_consumer, string* out_error) { +bool ParseSimpleFile(const std::string& path, LineConsumer* line_consumer, + std::string* out_error) { int fd; do { - fd = open(path.c_str(), O_RDONLY); + fd = posix::open(path.c_str(), O_RDONLY); } while (fd < 0 && errno == EINTR); if (fd < 0) { - *out_error = - string("error: Unable to open \"") + path + "\", " + strerror(errno); + *out_error = std::string("error: Unable to open \"") + path + "\", " + + strerror(errno); return false; } io::FileInputStream file_stream(fd); @@ -1489,8 +1556,8 @@ bool ParseSimpleFile( if (!parser.ParseChunk(StringPiece(static_cast(buf), buf_len))) { *out_error = - string("error: ") + path + - " Line " + SimpleItoa(parser.last_line()) + ", " + parser.error_str(); + std::string("error: ") + path + + " Line " + StrCat(parser.last_line()) + ", " + parser.error_str(); return false; } } @@ -1498,24 +1565,29 @@ bool ParseSimpleFile( } ImportWriter::ImportWriter( - const string& generate_for_named_framework, - const string& named_framework_to_proto_path_mappings_path) + const std::string& generate_for_named_framework, + const std::string& named_framework_to_proto_path_mappings_path, + const std::string& runtime_import_prefix, bool include_wkt_imports) : generate_for_named_framework_(generate_for_named_framework), named_framework_to_proto_path_mappings_path_( named_framework_to_proto_path_mappings_path), - need_to_parse_mapping_file_(true) { -} + runtime_import_prefix_(runtime_import_prefix), + include_wkt_imports_(include_wkt_imports), + need_to_parse_mapping_file_(true) {} ImportWriter::~ImportWriter() {} void ImportWriter::AddFile(const FileDescriptor* file, - const string& header_extension) { - const string file_path(FilePath(file)); - + const std::string& header_extension) { if (IsProtobufLibraryBundledProtoFile(file)) { - protobuf_framework_imports_.push_back( - FilePathBasename(file) + header_extension); - protobuf_non_framework_imports_.push_back(file_path + header_extension); + // The imports of the WKTs are only needed within the library itself, + // in other cases, they get skipped because the generated code already + // import GPBProtocolBuffers.h and hence proves them. + if (include_wkt_imports_) { + const std::string header_name = + "GPB" + FilePathBasename(file) + header_extension; + protobuf_imports_.push_back(header_name); + } return; } @@ -1524,7 +1596,7 @@ void ImportWriter::AddFile(const FileDescriptor* file, ParseFrameworkMappings(); } - std::map::iterator proto_lookup = + std::map::iterator proto_lookup = proto_file_to_framework_name_.find(file->name()); if (proto_lookup != proto_file_to_framework_name_.end()) { other_framework_imports_.push_back( @@ -1540,72 +1612,95 @@ void ImportWriter::AddFile(const FileDescriptor* file, return; } - other_imports_.push_back(file_path + header_extension); + other_imports_.push_back(FilePath(file) + header_extension); } void ImportWriter::Print(io::Printer* printer) const { - assert(protobuf_non_framework_imports_.size() == - protobuf_framework_imports_.size()); - bool add_blank_line = false; - if (protobuf_framework_imports_.size() > 0) { - const string framework_name(ProtobufLibraryFrameworkName); - const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name)); - - printer->Print( - "#if $cpp_symbol$\n", - "cpp_symbol", cpp_symbol); - for (vector::const_iterator iter = protobuf_framework_imports_.begin(); - iter != protobuf_framework_imports_.end(); ++iter) { - printer->Print( - " #import <$framework_name$/$header$>\n", - "framework_name", framework_name, - "header", *iter); - } - printer->Print( - "#else\n"); - for (vector::const_iterator iter = protobuf_non_framework_imports_.begin(); - iter != protobuf_non_framework_imports_.end(); ++iter) { - printer->Print( - " #import \"$header$\"\n", - "header", *iter); - } - printer->Print( - "#endif\n"); - + if (!protobuf_imports_.empty()) { + PrintRuntimeImports(printer, protobuf_imports_, runtime_import_prefix_); add_blank_line = true; } - if (other_framework_imports_.size() > 0) { + if (!other_framework_imports_.empty()) { if (add_blank_line) { printer->Print("\n"); } - for (vector::const_iterator iter = other_framework_imports_.begin(); + for (std::vector::const_iterator iter = + other_framework_imports_.begin(); iter != other_framework_imports_.end(); ++iter) { printer->Print( - " #import <$header$>\n", + "#import <$header$>\n", "header", *iter); } add_blank_line = true; } - if (other_imports_.size() > 0) { + if (!other_imports_.empty()) { if (add_blank_line) { printer->Print("\n"); } - for (vector::const_iterator iter = other_imports_.begin(); + for (std::vector::const_iterator iter = other_imports_.begin(); iter != other_imports_.end(); ++iter) { printer->Print( - " #import \"$header$\"\n", + "#import \"$header$\"\n", "header", *iter); } } } +void ImportWriter::PrintRuntimeImports( + io::Printer* printer, const std::vector& header_to_import, + const std::string& runtime_import_prefix, bool default_cpp_symbol) { + // Given an override, use that. + if (!runtime_import_prefix.empty()) { + for (const auto& header : header_to_import) { + printer->Print( + " #import \"$import_prefix$/$header$\"\n", + "import_prefix", runtime_import_prefix, + "header", header); + } + return; + } + + const std::string framework_name(ProtobufLibraryFrameworkName); + const std::string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name)); + + if (default_cpp_symbol) { + printer->Print( + "// This CPP symbol can be defined to use imports that match up to the framework\n" + "// imports needed when using CocoaPods.\n" + "#if !defined($cpp_symbol$)\n" + " #define $cpp_symbol$ 0\n" + "#endif\n" + "\n", + "cpp_symbol", cpp_symbol); + } + + printer->Print( + "#if $cpp_symbol$\n", + "cpp_symbol", cpp_symbol); + for (const auto& header : header_to_import) { + printer->Print( + " #import <$framework_name$/$header$>\n", + "framework_name", framework_name, + "header", header); + } + printer->Print( + "#else\n"); + for (const auto& header : header_to_import) { + printer->Print( + " #import \"$header$\"\n", + "header", header); + } + printer->Print( + "#endif\n"); +} + void ImportWriter::ParseFrameworkMappings() { need_to_parse_mapping_file_ = false; if (named_framework_to_proto_path_mappings_path_.empty()) { @@ -1613,7 +1708,7 @@ void ImportWriter::ParseFrameworkMappings() { } ProtoFrameworkCollector collector(&proto_file_to_framework_name_); - string parse_error; + std::string parse_error; if (!ParseSimpleFile(named_framework_to_proto_path_mappings_path_, &collector, &parse_error)) { std::cerr << "error parsing " << named_framework_to_proto_path_mappings_path_ @@ -1623,17 +1718,17 @@ void ImportWriter::ParseFrameworkMappings() { } bool ImportWriter::ProtoFrameworkCollector::ConsumeLine( - const StringPiece& line, string* out_error) { + const StringPiece& line, std::string* out_error) { int offset = line.find(':'); if (offset == StringPiece::npos) { *out_error = - string("Framework/proto file mapping line without colon sign: '") + - line.ToString() + "'."; + std::string("Framework/proto file mapping line without colon sign: '") + + std::string(line) + "'."; return false; } - StringPiece framework_name(line, 0, offset); - StringPiece proto_file_list(line, offset + 1, line.length() - offset - 1); - StringPieceTrimWhitespace(&framework_name); + StringPiece framework_name = line.substr(0, offset); + StringPiece proto_file_list = line.substr(offset + 1); + TrimWhitespace(&framework_name); int start = 0; while (start < proto_file_list.length()) { @@ -1642,25 +1737,27 @@ bool ImportWriter::ProtoFrameworkCollector::ConsumeLine( offset = proto_file_list.length(); } - StringPiece proto_file(proto_file_list, start, offset - start); - StringPieceTrimWhitespace(&proto_file); - if (proto_file.size() != 0) { - std::map::iterator existing_entry = - map_->find(proto_file.ToString()); + StringPiece proto_file = proto_file_list.substr(start, offset - start); + TrimWhitespace(&proto_file); + if (!proto_file.empty()) { + std::map::iterator existing_entry = + map_->find(string(proto_file)); if (existing_entry != map_->end()) { - std::cerr << "warning: duplicate proto file reference, replacing framework entry for '" - << proto_file.ToString() << "' with '" << framework_name.ToString() - << "' (was '" << existing_entry->second << "')." << std::endl; + std::cerr << "warning: duplicate proto file reference, replacing " + "framework entry for '" + << std::string(proto_file) << "' with '" << std::string(framework_name) + << "' (was '" << existing_entry->second << "')." << std::endl; std::cerr.flush(); } if (proto_file.find(' ') != StringPiece::npos) { - std::cerr << "note: framework mapping file had a proto file with a space in, hopefully that isn't a missing comma: '" - << proto_file.ToString() << "'" << std::endl; + std::cerr << "note: framework mapping file had a proto file with a " + "space in, hopefully that isn't a missing comma: '" + << std::string(proto_file) << "'" << std::endl; std::cerr.flush(); } - (*map_)[proto_file.ToString()] = framework_name.ToString(); + (*map_)[std::string(proto_file)] = std::string(framework_name); } start = offset + 1; @@ -1669,7 +1766,6 @@ bool ImportWriter::ProtoFrameworkCollector::ConsumeLine( return true; } - } // namespace objectivec } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index daea7609e5923..ce2d92cf3cf37 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -39,6 +39,8 @@ #include #include +#include + namespace google { namespace protobuf { namespace compiler { @@ -47,76 +49,80 @@ namespace objectivec { // Generator options (see objectivec_generator.cc for a description of each): struct Options { Options(); - string expected_prefixes_path; - string generate_for_named_framework; - string named_framework_to_proto_path_mappings_path; + std::string expected_prefixes_path; + std::vector expected_prefixes_suppressions; + std::string generate_for_named_framework; + std::string named_framework_to_proto_path_mappings_path; + std::string runtime_import_prefix; }; // Escape C++ trigraphs by escaping question marks to "\?". -string LIBPROTOC_EXPORT EscapeTrigraphs(const string& to_escape); - -// Strips ".proto" or ".protodevel" from the end of a filename. -string LIBPROTOC_EXPORT StripProto(const string& filename); +std::string PROTOC_EXPORT EscapeTrigraphs(const std::string& to_escape); // Remove white space from either end of a StringPiece. -void LIBPROTOC_EXPORT StringPieceTrimWhitespace(StringPiece* input); +void PROTOC_EXPORT TrimWhitespace(StringPiece* input); // Returns true if the name requires a ns_returns_not_retained attribute applied // to it. -bool LIBPROTOC_EXPORT IsRetainedName(const string& name); +bool PROTOC_EXPORT IsRetainedName(const std::string& name); // Returns true if the name starts with "init" and will need to have special // handling under ARC. -bool LIBPROTOC_EXPORT IsInitName(const string& name); +bool PROTOC_EXPORT IsInitName(const std::string& name); // Gets the objc_class_prefix. -string LIBPROTOC_EXPORT FileClassPrefix(const FileDescriptor* file); +std::string PROTOC_EXPORT FileClassPrefix(const FileDescriptor* file); // Gets the path of the file we're going to generate (sans the .pb.h // extension). The path will be dependent on the objectivec package // declared in the proto package. -string LIBPROTOC_EXPORT FilePath(const FileDescriptor* file); +std::string PROTOC_EXPORT FilePath(const FileDescriptor* file); // Just like FilePath(), but without the directory part. -string LIBPROTOC_EXPORT FilePathBasename(const FileDescriptor* file); +std::string PROTOC_EXPORT FilePathBasename(const FileDescriptor* file); // Gets the name of the root class we'll generate in the file. This class // is not meant for external consumption, but instead contains helpers that // the rest of the classes need -string LIBPROTOC_EXPORT FileClassName(const FileDescriptor* file); +std::string PROTOC_EXPORT FileClassName(const FileDescriptor* file); // These return the fully-qualified class name corresponding to the given // descriptor. -string LIBPROTOC_EXPORT ClassName(const Descriptor* descriptor); -string LIBPROTOC_EXPORT ClassName(const Descriptor* descriptor, string* out_suffix_added); -string LIBPROTOC_EXPORT EnumName(const EnumDescriptor* descriptor); +std::string PROTOC_EXPORT ClassName(const Descriptor* descriptor); +std::string PROTOC_EXPORT ClassName(const Descriptor* descriptor, + std::string* out_suffix_added); +std::string PROTOC_EXPORT EnumName(const EnumDescriptor* descriptor); // Returns the fully-qualified name of the enum value corresponding to the // the descriptor. -string LIBPROTOC_EXPORT EnumValueName(const EnumValueDescriptor* descriptor); +std::string PROTOC_EXPORT EnumValueName(const EnumValueDescriptor* descriptor); // Returns the name of the enum value corresponding to the descriptor. -string LIBPROTOC_EXPORT EnumValueShortName(const EnumValueDescriptor* descriptor); +std::string PROTOC_EXPORT EnumValueShortName(const EnumValueDescriptor* descriptor); // Reverse what an enum does. -string LIBPROTOC_EXPORT UnCamelCaseEnumShortName(const string& name); +std::string PROTOC_EXPORT UnCamelCaseEnumShortName(const std::string& name); // Returns the name to use for the extension (used as the method off the file's // Root class). -string LIBPROTOC_EXPORT ExtensionMethodName(const FieldDescriptor* descriptor); +std::string PROTOC_EXPORT ExtensionMethodName(const FieldDescriptor* descriptor); // Returns the transformed field name. -string LIBPROTOC_EXPORT FieldName(const FieldDescriptor* field); -string LIBPROTOC_EXPORT FieldNameCapitalized(const FieldDescriptor* field); +std::string PROTOC_EXPORT FieldName(const FieldDescriptor* field); +std::string PROTOC_EXPORT FieldNameCapitalized(const FieldDescriptor* field); // Returns the transformed oneof name. -string LIBPROTOC_EXPORT OneofEnumName(const OneofDescriptor* descriptor); -string LIBPROTOC_EXPORT OneofName(const OneofDescriptor* descriptor); -string LIBPROTOC_EXPORT OneofNameCapitalized(const OneofDescriptor* descriptor); +std::string PROTOC_EXPORT OneofEnumName(const OneofDescriptor* descriptor); +std::string PROTOC_EXPORT OneofName(const OneofDescriptor* descriptor); +std::string PROTOC_EXPORT OneofNameCapitalized(const OneofDescriptor* descriptor); -inline bool HasFieldPresence(const FileDescriptor* file) { - return file->syntax() != FileDescriptor::SYNTAX_PROTO3; -} +// Returns a symbol that can be used in C code to refer to an Objective C +// class without initializing the class. +std::string PROTOC_EXPORT ObjCClass(const std::string& class_name); + +// Declares an Objective C class without initializing the class so that it can +// be refrerred to by ObjCClass. +std::string PROTOC_EXPORT ObjCClassDeclaration(const std::string& class_name); inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) { return file->syntax() == FileDescriptor::SYNTAX_PROTO3; @@ -127,7 +133,8 @@ inline bool IsMapEntryMessage(const Descriptor* descriptor) { } // Reverse of the above. -string LIBPROTOC_EXPORT UnCamelCaseFieldName(const string& name, const FieldDescriptor* field); +std::string PROTOC_EXPORT UnCamelCaseFieldName(const std::string& name, + const FieldDescriptor* field); enum ObjectiveCType { OBJECTIVECTYPE_INT32, @@ -149,20 +156,31 @@ enum FlagType { FLAGTYPE_FIELD }; -template -string GetOptionalDeprecatedAttribute( - const TDescriptor* descriptor, - const FileDescriptor* file = NULL, - bool preSpace = true, bool postNewline = false) { +template +std::string GetOptionalDeprecatedAttribute(const TDescriptor* descriptor, + const FileDescriptor* file = NULL, + bool preSpace = true, + bool postNewline = false) { bool isDeprecated = descriptor->options().deprecated(); // The file is only passed when checking Messages & Enums, so those types // get tagged. At the moment, it doesn't seem to make sense to tag every // field or enum value with when the file is deprecated. + bool isFileLevelDeprecation = false; if (!isDeprecated && file) { - isDeprecated = file->options().deprecated(); + isFileLevelDeprecation = file->options().deprecated(); + isDeprecated = isFileLevelDeprecation; } if (isDeprecated) { - string result = "DEPRECATED_ATTRIBUTE"; + std::string message; + const FileDescriptor* sourceFile = descriptor->file(); + if (isFileLevelDeprecation) { + message = sourceFile->name() + " is deprecated."; + } else { + message = descriptor->full_name() + " is deprecated (see " + + sourceFile->name() + ")."; + } + + std::string result = std::string("GPB_DEPRECATED_MSG(\"") + message + "\")"; if (preSpace) { result.insert(0, " "); } @@ -175,117 +193,134 @@ string GetOptionalDeprecatedAttribute( } } -string LIBPROTOC_EXPORT GetCapitalizedType(const FieldDescriptor* field); +std::string PROTOC_EXPORT GetCapitalizedType(const FieldDescriptor* field); -ObjectiveCType LIBPROTOC_EXPORT GetObjectiveCType(FieldDescriptor::Type field_type); +ObjectiveCType PROTOC_EXPORT +GetObjectiveCType(FieldDescriptor::Type field_type); inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) { return GetObjectiveCType(field->type()); } -bool LIBPROTOC_EXPORT IsPrimitiveType(const FieldDescriptor* field); -bool LIBPROTOC_EXPORT IsReferenceType(const FieldDescriptor* field); +bool PROTOC_EXPORT IsPrimitiveType(const FieldDescriptor* field); +bool PROTOC_EXPORT IsReferenceType(const FieldDescriptor* field); -string LIBPROTOC_EXPORT GPBGenericValueFieldName(const FieldDescriptor* field); -string LIBPROTOC_EXPORT DefaultValue(const FieldDescriptor* field); -bool LIBPROTOC_EXPORT HasNonZeroDefaultValue(const FieldDescriptor* field); +std::string PROTOC_EXPORT +GPBGenericValueFieldName(const FieldDescriptor* field); +std::string PROTOC_EXPORT DefaultValue(const FieldDescriptor* field); +bool PROTOC_EXPORT HasNonZeroDefaultValue(const FieldDescriptor* field); -string LIBPROTOC_EXPORT BuildFlagsString(const FlagType type, const vector& strings); +std::string PROTOC_EXPORT +BuildFlagsString(const FlagType type, const std::vector& strings); // Builds HeaderDoc/appledoc style comments out of the comments in the .proto // file. -string LIBPROTOC_EXPORT BuildCommentsString(const SourceLocation& location, - bool prefer_single_line); +std::string PROTOC_EXPORT BuildCommentsString(const SourceLocation& location, + bool prefer_single_line); // The name the commonly used by the library when built as a framework. // This lines up to the name used in the CocoaPod. -extern LIBPROTOC_EXPORT const char* const ProtobufLibraryFrameworkName; +extern PROTOC_EXPORT const char* const ProtobufLibraryFrameworkName; // Returns the CPP symbol name to use as the gate for framework style imports // for the given framework name to use. -string LIBPROTOC_EXPORT ProtobufFrameworkImportSymbol(const string& framework_name); +std::string PROTOC_EXPORT +ProtobufFrameworkImportSymbol(const std::string& framework_name); // Checks if the file is one of the proto's bundled with the library. -bool LIBPROTOC_EXPORT IsProtobufLibraryBundledProtoFile(const FileDescriptor* file); +bool PROTOC_EXPORT +IsProtobufLibraryBundledProtoFile(const FileDescriptor* file); // Checks the prefix for the given files and outputs any warnings as needed. If // there are flat out errors, then out_error is filled in with the first error // and the result is false. -bool LIBPROTOC_EXPORT ValidateObjCClassPrefixes(const vector& files, - const Options& generation_options, - string* out_error); +bool PROTOC_EXPORT ValidateObjCClassPrefixes( + const std::vector& files, + const Options& generation_options, std::string* out_error); // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform // the input into the expected output. -class LIBPROTOC_EXPORT TextFormatDecodeData { +class PROTOC_EXPORT TextFormatDecodeData { public: TextFormatDecodeData(); ~TextFormatDecodeData(); - void AddString(int32 key, const string& input_for_decode, - const string& desired_output); + TextFormatDecodeData(const TextFormatDecodeData&) = delete; + TextFormatDecodeData& operator=(const TextFormatDecodeData&) = delete; + + void AddString(int32 key, const std::string& input_for_decode, + const std::string& desired_output); size_t num_entries() const { return entries_.size(); } - string Data() const; + std::string Data() const; - static string DecodeDataForString(const string& input_for_decode, - const string& desired_output); + static std::string DecodeDataForString(const std::string& input_for_decode, + const std::string& desired_output); private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormatDecodeData); - - typedef std::pair DataEntry; - vector entries_; + typedef std::pair DataEntry; + std::vector entries_; }; // Helper for parsing simple files. -class LIBPROTOC_EXPORT LineConsumer { +class PROTOC_EXPORT LineConsumer { public: LineConsumer(); virtual ~LineConsumer(); - virtual bool ConsumeLine(const StringPiece& line, string* out_error) = 0; + virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) = 0; }; -bool LIBPROTOC_EXPORT ParseSimpleFile( - const string& path, LineConsumer* line_consumer, string* out_error); - +bool PROTOC_EXPORT ParseSimpleFile(const std::string& path, + LineConsumer* line_consumer, + std::string* out_error); // Helper class for parsing framework import mappings and generating // import statements. -class LIBPROTOC_EXPORT ImportWriter { +class PROTOC_EXPORT ImportWriter { public: - ImportWriter(const string& generate_for_named_framework, - const string& named_framework_to_proto_path_mappings_path); + ImportWriter(const std::string& generate_for_named_framework, + const std::string& named_framework_to_proto_path_mappings_path, + const std::string& runtime_import_prefix, + bool include_wkt_imports); ~ImportWriter(); - void AddFile(const FileDescriptor* file, const string& header_extension); + void AddFile(const FileDescriptor* file, const std::string& header_extension); void Print(io::Printer *printer) const; + static void PrintRuntimeImports(io::Printer *printer, + const std::vector& header_to_import, + const std::string& runtime_import_prefix, + bool default_cpp_symbol = false); + private: class ProtoFrameworkCollector : public LineConsumer { public: - ProtoFrameworkCollector(std::map* inout_proto_file_to_framework_name) + ProtoFrameworkCollector(std::map* inout_proto_file_to_framework_name) : map_(inout_proto_file_to_framework_name) {} - virtual bool ConsumeLine(const StringPiece& line, string* out_error); + virtual bool ConsumeLine(const StringPiece& line, std::string* out_error); private: - std::map* map_; + std::map* map_; }; void ParseFrameworkMappings(); - const string generate_for_named_framework_; - const string named_framework_to_proto_path_mappings_path_; - std::map proto_file_to_framework_name_; + const std::string generate_for_named_framework_; + const std::string named_framework_to_proto_path_mappings_path_; + const std::string runtime_import_prefix_; + const bool include_wkt_imports_; + std::map proto_file_to_framework_name_; bool need_to_parse_mapping_file_; - vector protobuf_framework_imports_; - vector protobuf_non_framework_imports_; - vector other_framework_imports_; - vector other_imports_; + std::vector protobuf_imports_; + std::vector other_framework_imports_; + std::vector other_imports_; }; } // namespace objectivec } // namespace compiler } // namespace protobuf } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc index dc1cef556f35b..0aef94fe3f82f 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc @@ -39,21 +39,21 @@ namespace objectivec { namespace { TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_RawStrings) { - string input_for_decode("abcdefghIJ"); - string desired_output_for_decode; - string expected; - string result; + std::string input_for_decode("abcdefghIJ"); + std::string desired_output_for_decode; + std::string expected; + std::string result; // Different data, can't transform. desired_output_for_decode = "zbcdefghIJ"; - expected = string("\0zbcdefghIJ\0", 12); + expected = std::string("\0zbcdefghIJ\0", 12); result = TextFormatDecodeData::DecodeDataForString(input_for_decode, desired_output_for_decode); EXPECT_EQ(expected, result); desired_output_for_decode = "abcdezghIJ"; - expected = string("\0abcdezghIJ\0", 12); + expected = std::string("\0abcdezghIJ\0", 12); result = TextFormatDecodeData::DecodeDataForString(input_for_decode, desired_output_for_decode); EXPECT_EQ(expected, result); @@ -61,7 +61,7 @@ TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_RawStrings) { // Shortened data, can't transform. desired_output_for_decode = "abcdefghI"; - expected = string("\0abcdefghI\0", 11); + expected = std::string("\0abcdefghI\0", 11); result = TextFormatDecodeData::DecodeDataForString(input_for_decode, desired_output_for_decode); EXPECT_EQ(expected, result); @@ -69,32 +69,32 @@ TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_RawStrings) { // Extra data, can't transform. desired_output_for_decode = "abcdefghIJz"; - expected = string("\0abcdefghIJz\0", 13); + expected = std::string("\0abcdefghIJz\0", 13); result = TextFormatDecodeData::DecodeDataForString(input_for_decode, desired_output_for_decode); EXPECT_EQ(expected, result); } TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_ByteCodes) { - string input_for_decode("abcdefghIJ"); - string desired_output_for_decode; - string expected; - string result; + std::string input_for_decode("abcdefghIJ"); + std::string desired_output_for_decode; + std::string expected; + std::string result; desired_output_for_decode = "abcdefghIJ"; - expected = string("\x0A\x0", 2); + expected = std::string("\x0A\x0", 2); result = TextFormatDecodeData::DecodeDataForString(input_for_decode, desired_output_for_decode); EXPECT_EQ(expected, result); desired_output_for_decode = "_AbcdefghIJ"; - expected = string("\xCA\x0", 2); + expected = std::string("\xCA\x0", 2); result = TextFormatDecodeData::DecodeDataForString(input_for_decode, desired_output_for_decode); EXPECT_EQ(expected, result); desired_output_for_decode = "ABCD__EfghI_j"; - expected = string("\x64\x80\xC5\xA1\x0", 5); + expected = std::string("\x64\x80\xC5\xA1\x0", 5); result = TextFormatDecodeData::DecodeDataForString(input_for_decode, desired_output_for_decode); EXPECT_EQ(expected, result); @@ -105,7 +105,7 @@ TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_ByteCodes) { "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000"; desired_output_for_decode = "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000"; - expected = string("\x04\xA5\xA4\xA2\xBF\x1F\x0E\x84\x0", 9); + expected = std::string("\x04\xA5\xA4\xA2\xBF\x1F\x0E\x84\x0", 9); result = TextFormatDecodeData::DecodeDataForString(input_for_decode, desired_output_for_decode); EXPECT_EQ(expected, result); @@ -128,7 +128,7 @@ TEST(ObjCHelperDeathTest, TextFormatDecodeData_DecodeDataForString_Failures) { // Null char in the string. - string str_with_null_char("ab\0c", 4); + std::string str_with_null_char("ab\0c", 4); EXPECT_EXIT( TextFormatDecodeData::DecodeDataForString(str_with_null_char, "def"), ::testing::KilledBySignal(SIGABRT), @@ -160,7 +160,7 @@ TEST(ObjCHelper, TextFormatDecodeData_RawStrings) { 0x2, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 0x0, 0x4, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 'z', 0x0, }; - string expected((const char*)expected_data, sizeof(expected_data)); + std::string expected((const char*)expected_data, sizeof(expected_data)); EXPECT_EQ(expected, decode_data.Data()); } @@ -196,7 +196,7 @@ TEST(ObjCHelper, TextFormatDecodeData_ByteCodes) { // underscore, as is + 3 (00 op) 0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0, }; - string expected((const char*)expected_data, sizeof(expected_data)); + std::string expected((const char*)expected_data, sizeof(expected_data)); EXPECT_EQ(expected, decode_data.Data()); } @@ -221,7 +221,7 @@ TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) { // Null char in the string. - string str_with_null_char("ab\0c", 4); + std::string str_with_null_char("ab\0c", 4); EXPECT_EXIT( decode_data.AddString(1, str_with_null_char, "def"), ::testing::KilledBySignal(SIGABRT), diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc index bcaf570900662..746224ff86b24 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc @@ -32,11 +32,8 @@ #include #include -#include #include #include -#include -#include namespace google { namespace protobuf { @@ -88,9 +85,9 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options) : RepeatedFieldGenerator(descriptor, options) { const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); + descriptor->message_type()->map_key(); const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); + descriptor->message_type()->map_value(); value_field_generator_.reset(FieldGenerator::Make(value_descriptor, options)); // Pull over some variables_ from the value. @@ -99,22 +96,24 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, variables_["default_name"] = value_field_generator_->variable("default_name"); // Build custom field flags. - std::vector field_flags; + std::vector field_flags; field_flags.push_back("GPBFieldMapKey" + GetCapitalizedType(key_descriptor)); // Pull over the current text format custom name values that was calculated. if (variables_["fieldflags"].find("GPBFieldTextFormatNameCustom") != - string::npos) { + std::string::npos) { field_flags.push_back("GPBFieldTextFormatNameCustom"); } // Pull over some info from the value's flags. - const string& value_field_flags = + const std::string& value_field_flags = value_field_generator_->variable("fieldflags"); - if (value_field_flags.find("GPBFieldHasDefaultValue") != string::npos) { + if (value_field_flags.find("GPBFieldHasDefaultValue") != std::string::npos) { field_flags.push_back("GPBFieldHasDefaultValue"); } - if (value_field_flags.find("GPBFieldHasEnumDescriptor") != string::npos) { + if (value_field_flags.find("GPBFieldHasEnumDescriptor") != + std::string::npos) { field_flags.push_back("GPBFieldHasEnumDescriptor"); } + variables_["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags); ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor); @@ -129,7 +128,7 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, "NSMutableDictionaryvariable("storage_type") + "*>"; } else { - string class_name("GPB"); + std::string class_name("GPB"); class_name += MapEntryTypeName(key_descriptor, true); class_name += MapEntryTypeName(value_descriptor, false); class_name += "Dictionary"; @@ -162,17 +161,27 @@ void MapFieldGenerator::FinishInitialization(void) { } void MapFieldGenerator::DetermineForwardDeclarations( - std::set* fwd_decls) const { + std::set* fwd_decls) const { RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls); const FieldDescriptor* value_descriptor = descriptor_->message_type()->FindFieldByName("value"); if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) { - const string& value_storage_type = + const std::string& value_storage_type = value_field_generator_->variable("storage_type"); fwd_decls->insert("@class " + value_storage_type); } } +void MapFieldGenerator::DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) const { + // Class name is already in "storage_type". + const FieldDescriptor* value_descriptor = + descriptor_->message_type()->FindFieldByName("value"); + if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) { + fwd_decls->insert(ObjCClassDeclaration( + value_field_generator_->variable("storage_type"))); + } +} } // namespace objectivec } // namespace compiler diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h index 6664d849391e7..55fd56c125d29 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h @@ -47,16 +47,20 @@ class MapFieldGenerator : public RepeatedFieldGenerator { public: virtual void FinishInitialization(void); + MapFieldGenerator(const MapFieldGenerator&) = delete; + MapFieldGenerator& operator=(const MapFieldGenerator&) = delete; + protected: MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options); virtual ~MapFieldGenerator(); - virtual void DetermineForwardDeclarations(std::set* fwd_decls) const; + virtual void DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) const; + virtual void DetermineForwardDeclarations( + std::set* fwd_decls) const; private: - scoped_ptr value_field_generator_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator); + std::unique_ptr value_field_generator_; }; } // namespace objectivec diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc index 4f22e290fa01d..917cc64861e8a 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -43,7 +42,7 @@ #include #include #include -#include +#include #include namespace google { @@ -51,9 +50,6 @@ namespace protobuf { namespace compiler { namespace objectivec { -using internal::WireFormat; -using internal::WireFormatLite; - namespace { struct FieldOrderingByNumber { inline bool operator()(const FieldDescriptor* a, @@ -174,29 +170,28 @@ const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) { } } // namespace -MessageGenerator::MessageGenerator(const string& root_classname, +MessageGenerator::MessageGenerator(const std::string& root_classname, const Descriptor* descriptor, const Options& options) : root_classname_(root_classname), descriptor_(descriptor), field_generators_(descriptor, options), class_name_(ClassName(descriptor_)), - deprecated_attribute_( - GetOptionalDeprecatedAttribute(descriptor, descriptor->file(), false, true)) { - + deprecated_attribute_(GetOptionalDeprecatedAttribute( + descriptor, descriptor->file(), false, true)) { for (int i = 0; i < descriptor_->extension_count(); i++) { - extension_generators_.push_back( + extension_generators_.emplace_back( new ExtensionGenerator(class_name_, descriptor_->extension(i))); } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i)); - oneof_generators_.push_back(generator); + oneof_generators_.emplace_back(generator); } for (int i = 0; i < descriptor_->enum_type_count(); i++) { EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i)); - enum_generators_.push_back(generator); + enum_generators_.emplace_back(generator); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { @@ -204,36 +199,25 @@ MessageGenerator::MessageGenerator(const string& root_classname, new MessageGenerator(root_classname_, descriptor_->nested_type(i), options); - nested_message_generators_.push_back(generator); + nested_message_generators_.emplace_back(generator); } } -MessageGenerator::~MessageGenerator() { - STLDeleteContainerPointers(extension_generators_.begin(), - extension_generators_.end()); - STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end()); - STLDeleteContainerPointers(nested_message_generators_.begin(), - nested_message_generators_.end()); - STLDeleteContainerPointers(oneof_generators_.begin(), - oneof_generators_.end()); -} +MessageGenerator::~MessageGenerator() {} void MessageGenerator::GenerateStaticVariablesInitialization( io::Printer* printer) { - for (vector::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization(printer); + for (const auto& generator : extension_generators_) { + generator->GenerateStaticVariablesInitialization(printer); } - for (vector::iterator iter = - nested_message_generators_.begin(); - iter != nested_message_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization(printer); + for (const auto& generator : nested_message_generators_) { + generator->GenerateStaticVariablesInitialization(printer); } } -void MessageGenerator::DetermineForwardDeclarations(std::set* fwd_decls) { +void MessageGenerator::DetermineForwardDeclarations( + std::set* fwd_decls) { if (!IsMapEntryMessage(descriptor_)) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* fieldDescriptor = descriptor_->field(i); @@ -242,10 +226,33 @@ void MessageGenerator::DetermineForwardDeclarations(std::set* fwd_decls) } } - for (vector::iterator iter = - nested_message_generators_.begin(); - iter != nested_message_generators_.end(); ++iter) { - (*iter)->DetermineForwardDeclarations(fwd_decls); + for (const auto& generator : nested_message_generators_) { + generator->DetermineForwardDeclarations(fwd_decls); + } +} + +void MessageGenerator::DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) { + if (!IsMapEntryMessage(descriptor_)) { + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* fieldDescriptor = descriptor_->field(i); + field_generators_.get(fieldDescriptor) + .DetermineObjectiveCClassDefinitions(fwd_decls); + } + } + + for (const auto& generator : extension_generators_) { + generator->DetermineObjectiveCClassDefinitions(fwd_decls); + } + + for (const auto& generator : nested_message_generators_) { + generator->DetermineObjectiveCClassDefinitions(fwd_decls); + } + + const Descriptor* containing_descriptor = descriptor_->containing_type(); + if (containing_descriptor != NULL) { + std::string containing_class = ClassName(containing_descriptor); + fwd_decls->insert(ObjCClassDeclaration(containing_class)); } } @@ -254,10 +261,8 @@ bool MessageGenerator::IncludesOneOfDefinition() const { return true; } - for (vector::const_iterator iter = - nested_message_generators_.begin(); - iter != nested_message_generators_.end(); ++iter) { - if ((*iter)->IncludesOneOfDefinition()) { + for (const auto& generator : nested_message_generators_) { + if (generator->IncludesOneOfDefinition()) { return true; } } @@ -266,40 +271,31 @@ bool MessageGenerator::IncludesOneOfDefinition() const { } void MessageGenerator::GenerateEnumHeader(io::Printer* printer) { - for (vector::iterator iter = enum_generators_.begin(); - iter != enum_generators_.end(); ++iter) { - (*iter)->GenerateHeader(printer); + for (const auto& generator : enum_generators_) { + generator->GenerateHeader(printer); } - for (vector::iterator iter = - nested_message_generators_.begin(); - iter != nested_message_generators_.end(); ++iter) { - (*iter)->GenerateEnumHeader(printer); + for (const auto& generator : nested_message_generators_) { + generator->GenerateEnumHeader(printer); } } void MessageGenerator::GenerateExtensionRegistrationSource( io::Printer* printer) { - for (vector::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateRegistrationSource(printer); + for (const auto& generator : extension_generators_) { + generator->GenerateRegistrationSource(printer); } - for (vector::iterator iter = - nested_message_generators_.begin(); - iter != nested_message_generators_.end(); ++iter) { - (*iter)->GenerateExtensionRegistrationSource(printer); + for (const auto& generator : nested_message_generators_) { + generator->GenerateExtensionRegistrationSource(printer); } } void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { // This a a map entry message, just recurse and do nothing directly. if (IsMapEntryMessage(descriptor_)) { - for (vector::iterator iter = - nested_message_generators_.begin(); - iter != nested_message_generators_.end(); ++iter) { - (*iter)->GenerateMessageHeader(printer); + for (const auto& generator : nested_message_generators_) { + generator->GenerateMessageHeader(printer); } return; } @@ -310,7 +306,7 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { "classname", class_name_); if (descriptor_->field_count()) { - scoped_array sorted_fields( + std::unique_ptr sorted_fields( SortFieldsByNumber(descriptor_)); printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n", @@ -326,12 +322,11 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { printer->Print("};\n\n"); } - for (vector::iterator iter = oneof_generators_.begin(); - iter != oneof_generators_.end(); ++iter) { - (*iter)->GenerateCaseEnum(printer); + for (const auto& generator : oneof_generators_) { + generator->GenerateCaseEnum(printer); } - string message_comments; + std::string message_comments; SourceLocation location; if (descriptor_->GetSourceLocation(&location)) { message_comments = BuildCommentsString(location, false); @@ -340,16 +335,17 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { } printer->Print( - "$comments$$deprecated_attribute$@interface $classname$ : GPBMessage\n\n", + "$comments$$deprecated_attribute$GPB_FINAL @interface $classname$ : GPBMessage\n\n", "classname", class_name_, "deprecated_attribute", deprecated_attribute_, "comments", message_comments); - vector seen_oneofs(descriptor_->oneof_decl_count(), 0); + std::vector seen_oneofs(oneof_generators_.size(), 0); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof() != NULL) { - const int oneof_index = field->containing_oneof()->index(); + const OneofDescriptor *oneof = field->real_containing_oneof(); + if (oneof) { + const int oneof_index = oneof->index(); if (!seen_oneofs[oneof_index]) { seen_oneofs[oneof_index] = 1; oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration( @@ -367,9 +363,8 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { } if (!oneof_generators_.empty()) { - for (vector::iterator iter = oneof_generators_.begin(); - iter != oneof_generators_.end(); ++iter) { - (*iter)->GenerateClearFunctionDeclaration(printer); + for (const auto& generator : oneof_generators_) { + generator->GenerateClearFunctionDeclaration(printer); } printer->Print("\n"); } @@ -377,18 +372,14 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { if (descriptor_->extension_count() > 0) { printer->Print("@interface $classname$ (DynamicMethods)\n\n", "classname", class_name_); - for (vector::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateMembersHeader(printer); + for (const auto& generator : extension_generators_) { + generator->GenerateMembersHeader(printer); } printer->Print("@end\n\n"); } - for (vector::iterator iter = - nested_message_generators_.begin(); - iter != nested_message_generators_.end(); ++iter) { - (*iter)->GenerateMessageHeader(printer); + for (const auto& generator : nested_message_generators_) { + generator->GenerateMessageHeader(printer); } } @@ -410,9 +401,8 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { printer->Print("@implementation $classname$\n\n", "classname", class_name_); - for (vector::iterator iter = oneof_generators_.begin(); - iter != oneof_generators_.end(); ++iter) { - (*iter)->GeneratePropertyImplementation(printer); + for (const auto& generator : oneof_generators_) { + generator->GeneratePropertyImplementation(printer); } for (int i = 0; i < descriptor_->field_count(); i++) { @@ -420,12 +410,13 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { .GeneratePropertyImplementation(printer); } - scoped_array sorted_fields( + std::unique_ptr sorted_fields( SortFieldsByNumber(descriptor_)); - scoped_array size_order_fields( + std::unique_ptr size_order_fields( SortFieldsByStorageSize(descriptor_)); - vector sorted_extensions; + std::vector sorted_extensions; + sorted_extensions.reserve(descriptor_->extension_range_count()); for (int i = 0; i < descriptor_->extension_range_count(); ++i) { sorted_extensions.push_back(descriptor_->extension_range(i)); } @@ -448,21 +439,20 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { sizeof_has_storage = 1; } // Tell all the fields the oneof base. - for (vector::iterator iter = oneof_generators_.begin(); - iter != oneof_generators_.end(); ++iter) { - (*iter)->SetOneofIndexBase(sizeof_has_storage); + for (const auto& generator : oneof_generators_) { + generator->SetOneofIndexBase(sizeof_has_storage); } field_generators_.SetOneofIndexBase(sizeof_has_storage); // sizeof_has_storage needs enough bits for the single fields that aren't in // any oneof, and then one int32 for each oneof (to store the field number). - sizeof_has_storage += descriptor_->oneof_decl_count(); + sizeof_has_storage += oneof_generators_.size(); printer->Print( "\n" "typedef struct $classname$__storage_ {\n" " uint32_t _has_storage_[$sizeof_has_storage$];\n", "classname", class_name_, - "sizeof_has_storage", SimpleItoa(sizeof_has_storage)); + "sizeof_has_storage", StrCat(sizeof_has_storage)); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { @@ -484,18 +474,18 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { TextFormatDecodeData text_format_decode_data; bool has_fields = descriptor_->field_count() > 0; bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault(); - string field_description_type; + std::string field_description_type; if (need_defaults) { field_description_type = "GPBMessageFieldDescriptionWithDefault"; } else { field_description_type = "GPBMessageFieldDescription"; } if (has_fields) { - printer->Print( - " static $field_description_type$ fields[] = {\n", - "field_description_type", field_description_type); printer->Indent(); printer->Indent(); + printer->Print( + "static $field_description_type$ fields[] = {\n", + "field_description_type", field_description_type); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); ++i) { const FieldGenerator& field_generator = @@ -508,13 +498,13 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { } } printer->Outdent(); + printer->Print( + "};\n"); printer->Outdent(); printer->Outdent(); - printer->Print( - " };\n"); } - std::map vars; + std::map vars; vars["classname"] = class_name_; vars["rootclassname"] = root_classname_; vars["fields"] = has_fields ? "fields" : "NULL"; @@ -525,7 +515,9 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { vars["fields_count"] = "0"; } - std::vector init_flags; + std::vector init_flags; + init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs"); + init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown"); if (need_defaults) { init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault"); } @@ -545,14 +537,12 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { " fieldCount:$fields_count$\n" " storageSize:sizeof($classname$__storage_)\n" " flags:$init_flags$];\n"); - if (oneof_generators_.size() != 0) { + if (!oneof_generators_.empty()) { printer->Print( " static const char *oneofs[] = {\n"); - for (vector::iterator iter = oneof_generators_.begin(); - iter != oneof_generators_.end(); ++iter) { - printer->Print( - " \"$name$\",\n", - "name", (*iter)->DescriptorName()); + for (const auto& generator : oneof_generators_) { + printer->Print(" \"$name$\",\n", "name", + generator->DescriptorName()); } printer->Print( " };\n" @@ -562,7 +552,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { "first_has_index", oneof_generators_[0]->HasIndexAsString()); } if (text_format_decode_data.num_entries() != 0) { - const string text_format_data_str(text_format_decode_data.Data()); + const std::string text_format_data_str(text_format_decode_data.Data()); printer->Print( "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n" " static const char *extraTextFormatInfo ="); @@ -578,13 +568,13 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { " [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n" "#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"); } - if (sorted_extensions.size() != 0) { + if (!sorted_extensions.empty()) { printer->Print( " static const GPBExtensionRange ranges[] = {\n"); for (int i = 0; i < sorted_extensions.size(); i++) { printer->Print(" { .start = $start$, .end = $end$ },\n", - "start", SimpleItoa(sorted_extensions[i]->start), - "end", SimpleItoa(sorted_extensions[i]->end)); + "start", StrCat(sorted_extensions[i]->start), + "end", StrCat(sorted_extensions[i]->end)); } printer->Print( " };\n" @@ -592,20 +582,23 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { " count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n"); } if (descriptor_->containing_type() != NULL) { - string parent_class_name = ClassName(descriptor_->containing_type()); + std::string containing_class = ClassName(descriptor_->containing_type()); + std::string parent_class_ref = ObjCClass(containing_class); printer->Print( - " [localDescriptor setupContainingMessageClassName:GPBStringifySymbol($parent_name$)];\n", - "parent_name", parent_class_name); + " [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n", + "parent_class_ref", parent_class_ref); } - string suffix_added; + std::string suffix_added; ClassName(descriptor_, &suffix_added); - if (suffix_added.size() > 0) { + if (!suffix_added.empty()) { printer->Print( " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n", "suffix", suffix_added); } printer->Print( - " NSAssert(descriptor == nil, @\"Startup recursed!\");\n" + " #if defined(DEBUG) && DEBUG\n" + " NSAssert(descriptor == nil, @\"Startup recursed!\");\n" + " #endif // DEBUG\n" " descriptor = localDescriptor;\n" " }\n" " return descriptor;\n" @@ -623,21 +616,17 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { .GenerateCFunctionImplementations(printer); } - for (vector::iterator iter = oneof_generators_.begin(); - iter != oneof_generators_.end(); ++iter) { - (*iter)->GenerateClearFunctionImplementation(printer); + for (const auto& generator : oneof_generators_) { + generator->GenerateClearFunctionImplementation(printer); } } - for (vector::iterator iter = enum_generators_.begin(); - iter != enum_generators_.end(); ++iter) { - (*iter)->GenerateSource(printer); + for (const auto& generator : enum_generators_) { + generator->GenerateSource(printer); } - for (vector::iterator iter = - nested_message_generators_.begin(); - iter != nested_message_generators_.end(); ++iter) { - (*iter)->GenerateSource(printer); + for (const auto& generator : nested_message_generators_) { + generator->GenerateSource(printer); } } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h index 8f317ac05c5a8..01108d29e75ae 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h @@ -37,15 +37,11 @@ #include #include #include -#include +#include +#include namespace google { namespace protobuf { - -namespace io { -class Printer; // printer.h -} // namespace io - namespace compiler { namespace objectivec { @@ -54,17 +50,20 @@ class EnumGenerator; class MessageGenerator { public: - MessageGenerator(const string& root_classname, - const Descriptor* descriptor, - const Options& options); + MessageGenerator(const std::string& root_classname, + const Descriptor* descriptor, const Options& options); ~MessageGenerator(); + MessageGenerator(const MessageGenerator&) = delete; + MessageGenerator& operator=(const MessageGenerator&) = delete; + void GenerateStaticVariablesInitialization(io::Printer* printer); void GenerateEnumHeader(io::Printer* printer); void GenerateMessageHeader(io::Printer* printer); void GenerateSource(io::Printer* printer); void GenerateExtensionRegistrationSource(io::Printer* printer); - void DetermineForwardDeclarations(std::set* fwd_decls); + void DetermineObjectiveCClassDefinitions(std::set* fwd_decls); + void DetermineForwardDeclarations(std::set* fwd_decls); // Checks if the message or a nested message includes a oneof definition. bool IncludesOneOfDefinition() const; @@ -81,20 +80,20 @@ class MessageGenerator { void GenerateDescriptionOneFieldSource(io::Printer* printer, const FieldDescriptor* field); - const string root_classname_; + const std::string root_classname_; const Descriptor* descriptor_; FieldGeneratorMap field_generators_; - const string class_name_; - const string deprecated_attribute_; - vector extension_generators_; - vector enum_generators_; - vector nested_message_generators_; - vector oneof_generators_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); + const std::string class_name_; + const std::string deprecated_attribute_; + std::vector> extension_generators_; + std::vector> enum_generators_; + std::vector> nested_message_generators_; + std::vector> oneof_generators_; }; + } // namespace objectivec } // namespace compiler } // namespace protobuf } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc index 699d25b31ffa8..299a20b152eeb 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc @@ -35,7 +35,6 @@ #include #include #include -#include namespace google { namespace protobuf { @@ -45,15 +44,16 @@ namespace objectivec { namespace { void SetMessageVariables(const FieldDescriptor* descriptor, - std::map* variables) { - const string& message_type = ClassName(descriptor->message_type()); + std::map* variables) { + const std::string& message_type = ClassName(descriptor->message_type()); + const std::string& containing_class = + ClassName(descriptor->containing_type()); (*variables)["type"] = message_type; - (*variables)["containing_class"] = ClassName(descriptor->containing_type()); + (*variables)["containing_class"] = containing_class; (*variables)["storage_type"] = message_type; (*variables)["group_or_message"] = (descriptor->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; - - (*variables)["dataTypeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")"; + (*variables)["dataTypeSpecific_value"] = ObjCClass(message_type); } } // namespace @@ -67,20 +67,15 @@ MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, MessageFieldGenerator::~MessageFieldGenerator() {} void MessageFieldGenerator::DetermineForwardDeclarations( - std::set* fwd_decls) const { + std::set* fwd_decls) const { ObjCObjFieldGenerator::DetermineForwardDeclarations(fwd_decls); // Class name is already in "storage_type". fwd_decls->insert("@class " + variable("storage_type")); } -bool MessageFieldGenerator::WantsHasProperty(void) const { - if (descriptor_->containing_oneof() != NULL) { - // If in a oneof, it uses the oneofcase instead of a has bit. - return false; - } - // In both proto2 & proto3, message fields have a has* property to tell - // when it is a non default value. - return true; +void MessageFieldGenerator::DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) const { + fwd_decls->insert(ObjCClassDeclaration(variable("storage_type"))); } RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( @@ -95,12 +90,16 @@ RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} void RepeatedMessageFieldGenerator::DetermineForwardDeclarations( - std::set* fwd_decls) const { + std::set* fwd_decls) const { RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls); // Class name is already in "storage_type". fwd_decls->insert("@class " + variable("storage_type")); } +void RepeatedMessageFieldGenerator::DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) const { + fwd_decls->insert(ObjCClassDeclaration(variable("storage_type"))); +} } // namespace objectivec } // namespace compiler diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h index 50f4b6d4a9117..01dd6ed21f0cf 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h @@ -47,14 +47,17 @@ class MessageFieldGenerator : public ObjCObjFieldGenerator { protected: MessageFieldGenerator(const FieldDescriptor* descriptor, const Options& options); + + MessageFieldGenerator(const MessageFieldGenerator&) = delete; + MessageFieldGenerator& operator=(const MessageFieldGenerator&) = delete; + virtual ~MessageFieldGenerator(); - virtual bool WantsHasProperty(void) const; public: - virtual void DetermineForwardDeclarations(std::set* fwd_decls) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); + virtual void DetermineForwardDeclarations( + std::set* fwd_decls) const; + virtual void DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) const; }; class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator { @@ -66,11 +69,14 @@ class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator { const Options& options); virtual ~RepeatedMessageFieldGenerator(); - public: - virtual void DetermineForwardDeclarations(std::set* fwd_decls) const; + RepeatedMessageFieldGenerator(const RepeatedMessageFieldGenerator&) = delete; + RepeatedMessageFieldGenerator operator=(const RepeatedMessageFieldGenerator&) = delete; - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); + public: + virtual void DetermineForwardDeclarations( + std::set* fwd_decls) const; + virtual void DetermineObjectiveCClassDefinitions( + std::set* fwd_decls) const; }; } // namespace objectivec diff --git a/src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h b/src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h new file mode 100644 index 0000000000000..163304665cb30 --- /dev/null +++ b/src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h @@ -0,0 +1,197 @@ +// NSObject methods +// Autogenerated by method_dump.sh. Do not edit by hand. +// Date: Thu Nov 1 14:12:16 PDT 2018 +// macOS: MacOSX10.14.sdk +// iOS: iPhoneSimulator12.1.sdk + +const char* const kNSObjectMethodsList[] = { + "CAMLType", + "CA_copyRenderValue", + "CA_prepareRenderValue", + "NS_copyCGImage", + "NS_tiledLayerVisibleRect", + "___tryRetain_OA", + "__autorelease_OA", + "__dealloc_zombie", + "__release_OA", + "__retain_OA", + "_accessibilityFinalize", + "_accessibilityIsTableViewDescendant", + "_accessibilityUIElementSpecifier", + "_accessibilityUseConvenienceAPI", + "_allowsDirectEncoding", + "_asScriptTerminologyNameArray", + "_asScriptTerminologyNameString", + "_bindingAdaptor", + "_cfTypeID", + "_copyDescription", + "_destroyObserverList", + "_didEndKeyValueObserving", + "_implicitObservationInfo", + "_internalAccessibilityAttributedHint", + "_internalAccessibilityAttributedLabel", + "_internalAccessibilityAttributedValue", + "_isAXConnector", + "_isAccessibilityContainerSectionCandidate", + "_isAccessibilityContentNavigatorSectionCandidate", + "_isAccessibilityContentSectionCandidate", + "_isAccessibilityTopLevelNavigatorSectionCandidate", + "_isDeallocating", + "_isKVOA", + "_isToManyChangeInformation", + "_ivarDescription", + "_localClassNameForClass", + "_methodDescription", + "_observerStorage", + "_overrideUseFastBlockObservers", + "_propertyDescription", + "_releaseBindingAdaptor", + "_scriptingCount", + "_scriptingCountNonrecursively", + "_scriptingDebugDescription", + "_scriptingExists", + "_scriptingShouldCheckObjectIndexes", + "_shortMethodDescription", + "_shouldSearchChildrenForSection", + "_traitStorageList", + "_tryRetain", + "_ui_descriptionBuilder", + "_uikit_variesByTraitCollections", + "_web_description", + "_webkit_invokeOnMainThread", + "_willBeginKeyValueObserving", + "accessibilityActivate", + "accessibilityActivationPoint", + "accessibilityAllowsOverriddenAttributesWhenIgnored", + "accessibilityAssistiveTechnologyFocusedIdentifiers", + "accessibilityAttributedHint", + "accessibilityAttributedLabel", + "accessibilityAttributedValue", + "accessibilityContainer", + "accessibilityContainerType", + "accessibilityCustomActions", + "accessibilityCustomRotors", + "accessibilityDecrement", + "accessibilityDragSourceDescriptors", + "accessibilityDropPointDescriptors", + "accessibilityElementCount", + "accessibilityElementDidBecomeFocused", + "accessibilityElementDidLoseFocus", + "accessibilityElementIsFocused", + "accessibilityElements", + "accessibilityElementsHidden", + "accessibilityFrame", + "accessibilityHeaderElements", + "accessibilityHint", + "accessibilityIdentification", + "accessibilityIdentifier", + "accessibilityIncrement", + "accessibilityLabel", + "accessibilityLanguage", + "accessibilityLocalizedStringKey", + "accessibilityNavigationStyle", + "accessibilityOverriddenAttributes", + "accessibilityParameterizedAttributeNames", + "accessibilityPath", + "accessibilityPerformEscape", + "accessibilityPerformMagicTap", + "accessibilityPresenterProcessIdentifier", + "accessibilityShouldUseUniqueId", + "accessibilitySupportsNotifications", + "accessibilitySupportsOverriddenAttributes", + "accessibilityTemporaryChildren", + "accessibilityTraits", + "accessibilityValue", + "accessibilityViewIsModal", + "accessibilityVisibleArea", + "allPropertyKeys", + "allowsWeakReference", + "attributeKeys", + "autoContentAccessingProxy", + "autorelease", + "awakeFromNib", + "boolValueSafe", + "bs_encoded", + "bs_isPlistableType", + "bs_secureEncoded", + "cl_json_serializeKey", + "class", + "classCode", + "classDescription", + "classForArchiver", + "classForCoder", + "classForKeyedArchiver", + "classForPortCoder", + "className", + "clearProperties", + "copy", + "dealloc", + "debugDescription", + "defaultAccessibilityTraits", + "description", + "doubleValueSafe", + "entityName", + "exposedBindings", + "finalize", + "finishObserving", + "flushKeyBindings", + "hash", + "init", + "int64ValueSafe", + "isAccessibilityElement", + "isAccessibilityElementByDefault", + "isElementAccessibilityExposedToInterfaceBuilder", + "isFault", + "isNSArray__", + "isNSCFConstantString__", + "isNSData__", + "isNSDate__", + "isNSDictionary__", + "isNSNumber__", + "isNSObject__", + "isNSOrderedSet__", + "isNSSet__", + "isNSString__", + "isNSTimeZone__", + "isNSValue__", + "isProxy", + "mutableCopy", + "nilValueForKey", + "objectSpecifier", + "observationInfo", + "pep_onDetachedThread", + "pep_onMainThread", + "pep_onMainThreadIfNecessary", + "prepareForInterfaceBuilder", + "release", + "releaseOnMainThread", + "retain", + "retainCount", + "retainWeakReference", + "scriptingProperties", + "self", + "shouldGroupAccessibilityChildren", + "storedAccessibilityActivationPoint", + "storedAccessibilityContainerType", + "storedAccessibilityElementsHidden", + "storedAccessibilityFrame", + "storedAccessibilityNavigationStyle", + "storedAccessibilityTraits", + "storedAccessibilityViewIsModal", + "storedIsAccessibilityElement", + "storedShouldGroupAccessibilityChildren", + "stringValueSafe", + "superclass", + "toManyRelationshipKeys", + "toOneRelationshipKeys", + "traitStorageList", + "un_safeBoolValue", + "userInterfaceItemIdentifier", + "utf8ValueSafe", + "valuesForKeysWithDictionary", + "zone", +// Protocol: CAAnimatableValue +// Protocol: CARenderValue +// Protocol: NSObject +// Protocol: ROCKRemoteInvocationInterface +}; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc index 5531ae249f861..1bef293e2885e 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc @@ -46,11 +46,11 @@ OneofGenerator::OneofGenerator(const OneofDescriptor* descriptor) variables_["enum_name"] = OneofEnumName(descriptor_); variables_["name"] = OneofName(descriptor_); variables_["capitalized_name"] = OneofNameCapitalized(descriptor_); - variables_["raw_index"] = SimpleItoa(descriptor_->index()); + variables_["raw_index"] = StrCat(descriptor_->index()); const Descriptor* msg_descriptor = descriptor_->containing_type(); variables_["owning_message_class"] = ClassName(msg_descriptor); - string comments; + std::string comments; SourceLocation location; if (descriptor_->GetSourceLocation(&location)) { comments = BuildCommentsString(location, true); @@ -65,7 +65,7 @@ OneofGenerator::~OneofGenerator() {} void OneofGenerator::SetOneofIndexBase(int index_base) { int index = descriptor_->index() + index_base; // Flip the sign to mark it as a oneof. - variables_["index"] = SimpleItoa(-index); + variables_["index"] = StrCat(-index); } void OneofGenerator::GenerateCaseEnum(io::Printer* printer) { @@ -76,15 +76,15 @@ void OneofGenerator::GenerateCaseEnum(io::Printer* printer) { printer->Print( variables_, "$enum_name$_GPBUnsetOneOfCase = 0,\n"); - string enum_name = variables_["enum_name"]; + std::string enum_name = variables_["enum_name"]; for (int j = 0; j < descriptor_->field_count(); j++) { const FieldDescriptor* field = descriptor_->field(j); - string field_name = FieldNameCapitalized(field); + std::string field_name = FieldNameCapitalized(field); printer->Print( "$enum_name$_$field_name$ = $field_number$,\n", "enum_name", enum_name, "field_name", field_name, - "field_number", SimpleItoa(field->number())); + "field_number", StrCat(field->number())); } printer->Outdent(); printer->Print( @@ -120,17 +120,17 @@ void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) { printer->Print( variables_, "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n" - " GPBDescriptor *descriptor = [message descriptor];\n" + " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n" " GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:$raw_index$];\n" - " GPBMaybeClearOneof(message, oneof, $index$, 0);\n" + " GPBClearOneof(message, oneof);\n" "}\n"); } -string OneofGenerator::DescriptorName(void) const { +std::string OneofGenerator::DescriptorName(void) const { return variables_.find("name")->second; } -string OneofGenerator::HasIndexAsString(void) const { +std::string OneofGenerator::HasIndexAsString(void) const { return variables_.find("index")->second; } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h index ff353a6c62dca..034f07fb3306e 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h @@ -35,14 +35,9 @@ #include #include #include +#include namespace google { -namespace protobuf { -namespace io { -class Printer; // printer.h -} -} - namespace protobuf { namespace compiler { namespace objectivec { @@ -52,6 +47,9 @@ class OneofGenerator { explicit OneofGenerator(const OneofDescriptor* descriptor); ~OneofGenerator(); + OneofGenerator(const OneofGenerator&) = delete; + OneofGenerator& operator=(const OneofGenerator&) = delete; + void SetOneofIndexBase(int index_base); void GenerateCaseEnum(io::Printer* printer); @@ -62,18 +60,17 @@ class OneofGenerator { void GeneratePropertyImplementation(io::Printer* printer); void GenerateClearFunctionImplementation(io::Printer* printer); - string DescriptorName(void) const; - string HasIndexAsString(void) const; + std::string DescriptorName(void) const; + std::string HasIndexAsString(void) const; private: const OneofDescriptor* descriptor_; - std::map variables_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OneofGenerator); + std::map variables_; }; } // namespace objectivec } // namespace compiler } // namespace protobuf } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc index aa8ac32430ccd..e198c5c182ca3 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc @@ -31,14 +31,12 @@ #include #include -#include -#include #include +#include #include -#include -#include #include -#include +#include +#include namespace google { namespace protobuf { @@ -118,7 +116,7 @@ const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) { } void SetPrimitiveVariables(const FieldDescriptor* descriptor, - std::map* variables) { + std::map* variables) { std::string primitive_name = PrimitiveTypeName(descriptor); (*variables)["type"] = primitive_name; (*variables)["storage_type"] = primitive_name; @@ -154,7 +152,7 @@ int PrimitiveFieldGenerator::ExtraRuntimeHasBitsNeeded(void) const { void PrimitiveFieldGenerator::SetExtraRuntimeHasBitsBase(int has_base) { if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) { // Set into the offset the has bit to use for the actual value. - variables_["storage_offset_value"] = SimpleItoa(has_base); + variables_["storage_offset_value"] = StrCat(has_base); variables_["storage_offset_comment"] = " // Stored in _has_storage_ to save space."; } @@ -174,7 +172,7 @@ RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( : RepeatedFieldGenerator(descriptor, options) { SetPrimitiveVariables(descriptor, &variables_); - string base_name = PrimitiveArrayTypeName(descriptor); + std::string base_name = PrimitiveArrayTypeName(descriptor); if (base_name.length()) { variables_["array_storage_type"] = "GPB" + base_name + "Array"; } else { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h index 69bb1fddc1bdf..642f2d6323471 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h @@ -49,13 +49,13 @@ class PrimitiveFieldGenerator : public SingleFieldGenerator { const Options& options); virtual ~PrimitiveFieldGenerator(); + PrimitiveFieldGenerator(const PrimitiveFieldGenerator&) = delete; + PrimitiveFieldGenerator& operator=(const PrimitiveFieldGenerator&) = delete; + virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const; virtual int ExtraRuntimeHasBitsNeeded(void) const; virtual void SetExtraRuntimeHasBitsBase(int index_base); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); }; class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator { @@ -67,8 +67,9 @@ class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator { const Options& options); virtual ~PrimitiveObjFieldGenerator(); - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveObjFieldGenerator); + PrimitiveObjFieldGenerator(const PrimitiveObjFieldGenerator&) = delete; + PrimitiveObjFieldGenerator& operator=(const PrimitiveObjFieldGenerator&) = + delete; }; class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator { @@ -80,8 +81,10 @@ class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator { const Options& options); virtual ~RepeatedPrimitiveFieldGenerator(); - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); + RepeatedPrimitiveFieldGenerator(const RepeatedPrimitiveFieldGenerator&) = + delete; + RepeatedPrimitiveFieldGenerator& operator=( + const RepeatedPrimitiveFieldGenerator&) = delete; }; } // namespace objectivec diff --git a/src/google/protobuf/compiler/package_info.h b/src/google/protobuf/compiler/package_info.h index fb6b473e1c306..105ef601a5b36 100644 --- a/src/google/protobuf/compiler/package_info.h +++ b/src/google/protobuf/compiler/package_info.h @@ -37,7 +37,6 @@ // documentation generator. namespace google { - namespace protobuf { // Implementation of the Protocol Buffer compiler. diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index bb4a44c35409c..d92cd558735dc 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -34,20 +34,24 @@ // // Recursive descent FTW. +#include + #include -#include -#include +#include +#include +#include -#include -#include -#include -#include -#include +#include #include #include +#include +#include +#include +#include #include #include +#include namespace google { namespace protobuf { @@ -57,28 +61,28 @@ using internal::WireFormat; namespace { -typedef hash_map TypeNameMap; +typedef std::unordered_map TypeNameMap; TypeNameMap MakeTypeNameTable() { TypeNameMap result; - result["double" ] = FieldDescriptorProto::TYPE_DOUBLE; - result["float" ] = FieldDescriptorProto::TYPE_FLOAT; - result["uint64" ] = FieldDescriptorProto::TYPE_UINT64; - result["fixed64" ] = FieldDescriptorProto::TYPE_FIXED64; - result["fixed32" ] = FieldDescriptorProto::TYPE_FIXED32; - result["bool" ] = FieldDescriptorProto::TYPE_BOOL; - result["string" ] = FieldDescriptorProto::TYPE_STRING; - result["group" ] = FieldDescriptorProto::TYPE_GROUP; - - result["bytes" ] = FieldDescriptorProto::TYPE_BYTES; - result["uint32" ] = FieldDescriptorProto::TYPE_UINT32; + result["double"] = FieldDescriptorProto::TYPE_DOUBLE; + result["float"] = FieldDescriptorProto::TYPE_FLOAT; + result["uint64"] = FieldDescriptorProto::TYPE_UINT64; + result["fixed64"] = FieldDescriptorProto::TYPE_FIXED64; + result["fixed32"] = FieldDescriptorProto::TYPE_FIXED32; + result["bool"] = FieldDescriptorProto::TYPE_BOOL; + result["string"] = FieldDescriptorProto::TYPE_STRING; + result["group"] = FieldDescriptorProto::TYPE_GROUP; + + result["bytes"] = FieldDescriptorProto::TYPE_BYTES; + result["uint32"] = FieldDescriptorProto::TYPE_UINT32; result["sfixed32"] = FieldDescriptorProto::TYPE_SFIXED32; result["sfixed64"] = FieldDescriptorProto::TYPE_SFIXED64; - result["int32" ] = FieldDescriptorProto::TYPE_INT32; - result["int64" ] = FieldDescriptorProto::TYPE_INT64; - result["sint32" ] = FieldDescriptorProto::TYPE_SINT32; - result["sint64" ] = FieldDescriptorProto::TYPE_SINT64; + result["int32"] = FieldDescriptorProto::TYPE_INT32; + result["int64"] = FieldDescriptorProto::TYPE_INT64; + result["sint32"] = FieldDescriptorProto::TYPE_SINT32; + result["sint64"] = FieldDescriptorProto::TYPE_SINT64; return result; } @@ -87,8 +91,8 @@ const TypeNameMap kTypeNames = MakeTypeNameTable(); // Camel-case the field name and append "Entry" for generated map entry name. // e.g. map foo_map => FooMapEntry -string MapEntryName(const string& field_name) { - string result; +std::string MapEntryName(const std::string& field_name) { + std::string result; static const char kSuffix[] = "Entry"; result.reserve(field_name.size() + sizeof(kSuffix)); bool cap_next = true; @@ -111,26 +115,81 @@ string MapEntryName(const string& field_name) { return result; } +bool IsUppercase(char c) { return c >= 'A' && c <= 'Z'; } + +bool IsLowercase(char c) { return c >= 'a' && c <= 'z'; } + +bool IsNumber(char c) { return c >= '0' && c <= '9'; } + +bool IsUpperCamelCase(const std::string& name) { + if (name.empty()) { + return true; + } + // Name must start with an upper case character. + if (!IsUppercase(name[0])) { + return false; + } + // Must not contains underscore. + for (int i = 1; i < name.length(); i++) { + if (name[i] == '_') { + return false; + } + } + return true; +} + +bool IsUpperUnderscore(const std::string& name) { + for (int i = 0; i < name.length(); i++) { + const char c = name[i]; + if (!IsUppercase(c) && c != '_' && !IsNumber(c)) { + return false; + } + } + return true; +} + +bool IsLowerUnderscore(const std::string& name) { + for (int i = 0; i < name.length(); i++) { + const char c = name[i]; + if (!IsLowercase(c) && c != '_' && !IsNumber(c)) { + return false; + } + } + return true; +} + +bool IsNumberFollowUnderscore(const std::string& name) { + for (int i = 1; i < name.length(); i++) { + const char c = name[i]; + if (IsNumber(c) && name[i - 1] == '_') { + return true; + } + } + return false; +} + } // anonymous namespace // Makes code slightly more readable. The meaning of "DO(foo)" is // "Execute foo and fail if it fails.", where failure is indicated by // returning false. -#define DO(STATEMENT) if (STATEMENT) {} else return false +#define DO(STATEMENT) \ + if (STATEMENT) { \ + } else \ + return false // =================================================================== Parser::Parser() - : input_(NULL), - error_collector_(NULL), - source_location_table_(NULL), - had_errors_(false), - require_syntax_identifier_(false), - stop_after_syntax_identifier_(false) { + : input_(NULL), + error_collector_(NULL), + source_location_table_(NULL), + had_errors_(false), + require_syntax_identifier_(false), + stop_after_syntax_identifier_(false) { } -Parser::~Parser() { -} +Parser::~Parser() {} // =================================================================== @@ -142,9 +201,7 @@ inline bool Parser::LookingAtType(io::Tokenizer::TokenType token_type) { return input_->current().type == token_type; } -inline bool Parser::AtEnd() { - return LookingAtType(io::Tokenizer::TYPE_END); -} +inline bool Parser::AtEnd() { return LookingAtType(io::Tokenizer::TYPE_END); } bool Parser::TryConsume(const char* text) { if (LookingAt(text)) { @@ -168,12 +225,12 @@ bool Parser::Consume(const char* text) { if (TryConsume(text)) { return true; } else { - AddError("Expected \"" + string(text) + "\"."); + AddError("Expected \"" + std::string(text) + "\"."); return false; } } -bool Parser::ConsumeIdentifier(string* output, const char* error) { +bool Parser::ConsumeIdentifier(std::string* output, const char* error) { if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { *output = input_->current().text; input_->Next(); @@ -187,8 +244,8 @@ bool Parser::ConsumeIdentifier(string* output, const char* error) { bool Parser::ConsumeInteger(int* output, const char* error) { if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { uint64 value = 0; - if (!io::Tokenizer::ParseInteger(input_->current().text, - kint32max, &value)) { + if (!io::Tokenizer::ParseInteger(input_->current().text, kint32max, + &value)) { AddError("Integer out of range."); // We still return true because we did, in fact, parse an integer. } @@ -240,8 +297,8 @@ bool Parser::ConsumeNumber(double* output, const char* error) { } else if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { // Also accept integers. uint64 value = 0; - if (!io::Tokenizer::ParseInteger(input_->current().text, - kuint64max, &value)) { + if (!io::Tokenizer::ParseInteger(input_->current().text, kuint64max, + &value)) { AddError("Integer out of range."); // We still return true because we did, in fact, parse a number. } @@ -262,7 +319,7 @@ bool Parser::ConsumeNumber(double* output, const char* error) { } } -bool Parser::ConsumeString(string* output, const char* error) { +bool Parser::ConsumeString(std::string* output, const char* error) { if (LookingAtType(io::Tokenizer::TYPE_STRING)) { io::Tokenizer::ParseString(input_->current().text, output); input_->Next(); @@ -278,11 +335,11 @@ bool Parser::ConsumeString(string* output, const char* error) { } } -bool Parser::TryConsumeEndOfDeclaration( - const char* text, const LocationRecorder* location) { +bool Parser::TryConsumeEndOfDeclaration(const char* text, + const LocationRecorder* location) { if (LookingAt(text)) { - string leading, trailing; - std::vector detached; + std::string leading, trailing; + std::vector detached; input_->NextWithComments(&trailing, &detached, &leading); // Save the leading comments for next time, and recall the leading comments @@ -309,58 +366,76 @@ bool Parser::TryConsumeEndOfDeclaration( } } -bool Parser::ConsumeEndOfDeclaration( - const char* text, const LocationRecorder* location) { +bool Parser::ConsumeEndOfDeclaration(const char* text, + const LocationRecorder* location) { if (TryConsumeEndOfDeclaration(text, location)) { return true; } else { - AddError("Expected \"" + string(text) + "\"."); + AddError("Expected \"" + std::string(text) + "\"."); return false; } } // ------------------------------------------------------------------- -void Parser::AddError(int line, int column, const string& error) { +void Parser::AddError(int line, int column, const std::string& error) { if (error_collector_ != NULL) { error_collector_->AddError(line, column, error); } had_errors_ = true; } -void Parser::AddError(const string& error) { +void Parser::AddError(const std::string& error) { AddError(input_->current().line, input_->current().column, error); } +void Parser::AddWarning(const std::string& warning) { + if (error_collector_ != nullptr) { + error_collector_->AddWarning(input_->current().line, + input_->current().column, warning); + } +} + // ------------------------------------------------------------------- Parser::LocationRecorder::LocationRecorder(Parser* parser) - : parser_(parser), - location_(parser_->source_code_info_->add_location()) { + : parser_(parser), + source_code_info_(parser->source_code_info_), + location_(parser_->source_code_info_->add_location()) { location_->add_span(parser_->input_->current().line); location_->add_span(parser_->input_->current().column); } Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent) { - Init(parent); + Init(parent, parent.source_code_info_); +} + +Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent, + int path1, + SourceCodeInfo* source_code_info) { + Init(parent, source_code_info); + AddPath(path1); } Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent, int path1) { - Init(parent); + Init(parent, parent.source_code_info_); AddPath(path1); } Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent, int path1, int path2) { - Init(parent); + Init(parent, parent.source_code_info_); AddPath(path1); AddPath(path2); } -void Parser::LocationRecorder::Init(const LocationRecorder& parent) { +void Parser::LocationRecorder::Init(const LocationRecorder& parent, + SourceCodeInfo* source_code_info) { parser_ = parent.parser_; - location_ = parser_->source_code_info_->add_location(); + source_code_info_ = source_code_info; + + location_ = source_code_info_->add_location(); location_->mutable_path()->CopyFrom(parent.location_->path()); location_->add_span(parser_->input_->current().line); @@ -394,7 +469,8 @@ void Parser::LocationRecorder::EndAt(const io::Tokenizer::Token& token) { location_->add_span(token.end_column); } -void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor, +void Parser::LocationRecorder::RecordLegacyLocation( + const Message* descriptor, DescriptorPool::ErrorCollector::ErrorLocation location) { if (parser_->source_location_table_ != NULL) { parser_->source_location_table_->Add( @@ -402,9 +478,21 @@ void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor, } } +void Parser::LocationRecorder::RecordLegacyImportLocation( + const Message* descriptor, const std::string& name) { + if (parser_->source_location_table_ != nullptr) { + parser_->source_location_table_->AddImport( + descriptor, name, location_->span(0), location_->span(1)); + } +} + +int Parser::LocationRecorder::CurrentPathSize() const { + return location_->path_size(); +} + void Parser::LocationRecorder::AttachComments( - string* leading, string* trailing, - std::vector* detached_comments) const { + std::string* leading, std::string* trailing, + std::vector* detached_comments) const { GOOGLE_CHECK(!location_->has_leading_comments()); GOOGLE_CHECK(!location_->has_trailing_comments()); @@ -415,8 +503,7 @@ void Parser::LocationRecorder::AttachComments( location_->mutable_trailing_comments()->swap(*trailing); } for (int i = 0; i < detached_comments->size(); ++i) { - location_->add_leading_detached_comments()->swap( - (*detached_comments)[i]); + location_->add_leading_detached_comments()->swap((*detached_comments)[i]); } detached_comments->clear(); } @@ -478,7 +565,7 @@ bool Parser::ValidateEnum(const EnumDescriptorProto* proto) { } if (has_allow_alias && !allow_alias) { - string error = + std::string error = "\"" + proto->name() + "\" declares 'option allow_alias = false;' which has no effect. " "Please remove the declaration."; @@ -490,7 +577,7 @@ bool Parser::ValidateEnum(const EnumDescriptorProto* proto) { std::set used_values; bool has_duplicates = false; for (int i = 0; i < proto->value_size(); ++i) { - const EnumValueDescriptorProto enum_value = proto->value(i); + const EnumValueDescriptorProto& enum_value = proto->value(i); if (used_values.find(enum_value.number()) != used_values.end()) { has_duplicates = true; break; @@ -499,7 +586,7 @@ bool Parser::ValidateEnum(const EnumDescriptorProto* proto) { } } if (allow_alias && !has_duplicates) { - string error = + std::string error = "\"" + proto->name() + "\" declares support for enum aliases but no enum values share field " "numbers. Please remove the unnecessary 'option allow_alias = true;' " @@ -510,6 +597,19 @@ bool Parser::ValidateEnum(const EnumDescriptorProto* proto) { return false; } + // Enforce that enum constants must be UPPER_CASE except in case of + // enum_alias. + if (!allow_alias) { + for (const auto& enum_value : proto->value()) { + if (!IsUpperUnderscore(enum_value.name())) { + AddWarning( + "Enum constant should be in UPPER_CASE. Found: " + + enum_value.name() + + ". See https://developers.google.com/protocol-buffers/docs/style"); + } + } + } + return true; } @@ -533,6 +633,8 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { { LocationRecorder root_location(this); + root_location.RecordLegacyLocation(file, + DescriptorPool::ErrorCollector::OTHER); if (require_syntax_identifier_ || LookingAt("syntax")) { if (!ParseSyntaxIdentifier(root_location)) { @@ -543,8 +645,8 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { // Store the syntax into the file. if (file != NULL) file->set_syntax(syntax_identifier_); } else if (!stop_after_syntax_identifier_) { - GOOGLE_LOG(WARNING) << "No syntax specified for the proto file: " - << file->name() << ". Please use 'syntax = \"proto2\";' " + GOOGLE_LOG(WARNING) << "No syntax specified for the proto file: " << file->name() + << ". Please use 'syntax = \"proto2\";' " << "or 'syntax = \"proto3\";' to specify a syntax " << "version. (Defaulted to proto2 syntax.)"; syntax_identifier_ = "proto2"; @@ -583,7 +685,7 @@ bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) { "File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'.")); DO(Consume("=")); io::Tokenizer::Token syntax_token = input_->current(); - string syntax; + std::string syntax; DO(ConsumeString(&syntax, "Expected syntax identifier.")); DO(ConsumeEndOfDeclaration(";", &syntax_location)); @@ -592,8 +694,9 @@ bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) { if (syntax != "proto2" && syntax != "proto3" && !stop_after_syntax_identifier_) { AddError(syntax_token.line, syntax_token.column, - "Unrecognized syntax identifier \"" + syntax + "\". This parser " - "only recognizes \"proto2\" and \"proto3\"."); + "Unrecognized syntax identifier \"" + syntax + + "\". This parser " + "only recognizes \"proto2\" and \"proto3\"."); return false; } @@ -607,34 +710,34 @@ bool Parser::ParseTopLevelStatement(FileDescriptorProto* file, return true; } else if (LookingAt("message")) { LocationRecorder location(root_location, - FileDescriptorProto::kMessageTypeFieldNumber, file->message_type_size()); + FileDescriptorProto::kMessageTypeFieldNumber, + file->message_type_size()); return ParseMessageDefinition(file->add_message_type(), location, file); } else if (LookingAt("enum")) { LocationRecorder location(root_location, - FileDescriptorProto::kEnumTypeFieldNumber, file->enum_type_size()); + FileDescriptorProto::kEnumTypeFieldNumber, + file->enum_type_size()); return ParseEnumDefinition(file->add_enum_type(), location, file); } else if (LookingAt("service")) { LocationRecorder location(root_location, - FileDescriptorProto::kServiceFieldNumber, file->service_size()); + FileDescriptorProto::kServiceFieldNumber, + file->service_size()); return ParseServiceDefinition(file->add_service(), location, file); } else if (LookingAt("extend")) { LocationRecorder location(root_location, - FileDescriptorProto::kExtensionFieldNumber); - return ParseExtend(file->mutable_extension(), - file->mutable_message_type(), - root_location, - FileDescriptorProto::kMessageTypeFieldNumber, - location, file); + FileDescriptorProto::kExtensionFieldNumber); + return ParseExtend( + file->mutable_extension(), file->mutable_message_type(), root_location, + FileDescriptorProto::kMessageTypeFieldNumber, location, file); } else if (LookingAt("import")) { return ParseImport(file->mutable_dependency(), file->mutable_public_dependency(), - file->mutable_weak_dependency(), - root_location, file); + file->mutable_weak_dependency(), root_location, file); } else if (LookingAt("package")) { return ParsePackage(file, root_location, file); } else if (LookingAt("option")) { LocationRecorder location(root_location, - FileDescriptorProto::kOptionsFieldNumber); + FileDescriptorProto::kOptionsFieldNumber); return ParseOption(file->mutable_options(), location, file, OPTION_STATEMENT); } else { @@ -647,18 +750,60 @@ bool Parser::ParseTopLevelStatement(FileDescriptorProto* file, // Messages bool Parser::ParseMessageDefinition( - DescriptorProto* message, - const LocationRecorder& message_location, + DescriptorProto* message, const LocationRecorder& message_location, const FileDescriptorProto* containing_file) { DO(Consume("message")); { LocationRecorder location(message_location, DescriptorProto::kNameFieldNumber); - location.RecordLegacyLocation( - message, DescriptorPool::ErrorCollector::NAME); + location.RecordLegacyLocation(message, + DescriptorPool::ErrorCollector::NAME); DO(ConsumeIdentifier(message->mutable_name(), "Expected message name.")); + if (!IsUpperCamelCase(message->name())) { + AddWarning( + "Message name should be in UpperCamelCase. Found: " + + message->name() + + ". See https://developers.google.com/protocol-buffers/docs/style"); + } } DO(ParseMessageBlock(message, message_location, containing_file)); + + if (syntax_identifier_ == "proto3") { + // Add synthetic one-field oneofs for optional fields, except messages which + // already have presence in proto3. + // + // We have to make sure the oneof names don't conflict with any other + // field or oneof. + std::unordered_set names; + for (const auto& field : message->field()) { + names.insert(field.name()); + } + for (const auto& oneof : message->oneof_decl()) { + names.insert(oneof.name()); + } + + for (auto& field : *message->mutable_field()) { + if (field.proto3_optional()) { + std::string oneof_name = field.name(); + + // Prepend 'XXXXX_' until we are no longer conflicting. + // Avoid prepending a double-underscore because such names are + // reserved in C++. + if (oneof_name.empty() || oneof_name[0] != '_') { + oneof_name = '_' + oneof_name; + } + while (names.count(oneof_name) > 0) { + oneof_name = 'X' + oneof_name; + } + + names.insert(oneof_name); + field.set_oneof_index(message->oneof_decl_size()); + OneofDescriptorProto* oneof = message->add_oneof_decl(); + oneof->set_name(oneof_name); + } + } + } + return true; } @@ -684,9 +829,8 @@ bool IsMessageSetWireFormatMessage(const DescriptorProto& message) { // tag number can only be determined after all options have been parsed. void AdjustExtensionRangesWithMaxEndNumber(DescriptorProto* message) { const bool is_message_set = IsMessageSetWireFormatMessage(*message); - const int max_extension_number = is_message_set ? - kint32max : - FieldDescriptor::kMaxNumber + 1; + const int max_extension_number = + is_message_set ? kint32max : FieldDescriptor::kMaxNumber + 1; for (int i = 0; i < message->extension_range_size(); ++i) { if (message->extension_range(i).end() == kMaxRangeSentinel) { message->mutable_extension_range(i)->set_end(max_extension_number); @@ -699,9 +843,8 @@ void AdjustExtensionRangesWithMaxEndNumber(DescriptorProto* message) { // tag number can only be determined after all options have been parsed. void AdjustReservedRangesWithMaxEndNumber(DescriptorProto* message) { const bool is_message_set = IsMessageSetWireFormatMessage(*message); - const int max_field_number = is_message_set ? - kint32max : - FieldDescriptor::kMaxNumber + 1; + const int max_field_number = + is_message_set ? kint32max : FieldDescriptor::kMaxNumber + 1; for (int i = 0; i < message->reserved_range_size(); ++i) { if (message->reserved_range(i).end() == kMaxRangeSentinel) { message->mutable_reserved_range(i)->set_end(max_field_number); @@ -766,34 +909,28 @@ bool Parser::ParseMessageStatement(DescriptorProto* message, LocationRecorder location(message_location, DescriptorProto::kExtensionFieldNumber); return ParseExtend(message->mutable_extension(), - message->mutable_nested_type(), - message_location, - DescriptorProto::kNestedTypeFieldNumber, - location, containing_file); + message->mutable_nested_type(), message_location, + DescriptorProto::kNestedTypeFieldNumber, location, + containing_file); } else if (LookingAt("option")) { LocationRecorder location(message_location, DescriptorProto::kOptionsFieldNumber); - return ParseOption(message->mutable_options(), location, - containing_file, OPTION_STATEMENT); + return ParseOption(message->mutable_options(), location, containing_file, + OPTION_STATEMENT); } else if (LookingAt("oneof")) { int oneof_index = message->oneof_decl_size(); - LocationRecorder oneof_location(message_location, - DescriptorProto::kOneofDeclFieldNumber, - oneof_index); + LocationRecorder oneof_location( + message_location, DescriptorProto::kOneofDeclFieldNumber, oneof_index); - return ParseOneof(message->add_oneof_decl(), message, - oneof_index, oneof_location, message_location, - containing_file); + return ParseOneof(message->add_oneof_decl(), message, oneof_index, + oneof_location, message_location, containing_file); } else { LocationRecorder location(message_location, DescriptorProto::kFieldFieldNumber, message->field_size()); - return ParseMessageField(message->add_field(), - message->mutable_nested_type(), - message_location, - DescriptorProto::kNestedTypeFieldNumber, - location, - containing_file); + return ParseMessageField( + message->add_field(), message->mutable_nested_type(), message_location, + DescriptorProto::kNestedTypeFieldNumber, location, containing_file); } } @@ -804,30 +941,23 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field, const LocationRecorder& field_location, const FileDescriptorProto* containing_file) { { - LocationRecorder location(field_location, - FieldDescriptorProto::kLabelFieldNumber); FieldDescriptorProto::Label label; - if (ParseLabel(&label, containing_file)) { + if (ParseLabel(&label, field_location, containing_file)) { field->set_label(label); if (label == FieldDescriptorProto::LABEL_OPTIONAL && syntax_identifier_ == "proto3") { - AddError( - "Explicit 'optional' labels are disallowed in the Proto3 syntax. " - "To define 'optional' fields in Proto3, simply remove the " - "'optional' label, as fields are 'optional' by default."); + field->set_proto3_optional(true); } } } return ParseMessageFieldNoLabel(field, messages, parent_location, location_field_number_for_nested_type, - field_location, - containing_file); + field_location, containing_file); } bool Parser::ParseMessageFieldNoLabel( - FieldDescriptorProto* field, - RepeatedPtrField* messages, + FieldDescriptorProto* field, RepeatedPtrField* messages, const LocationRecorder& parent_location, int location_field_number_for_nested_type, const LocationRecorder& field_location, @@ -840,7 +970,7 @@ bool Parser::ParseMessageFieldNoLabel( bool type_parsed = false; FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32; - string type_name; + std::string type_name; // Special case map field. We only treat the field as a map field if the // field type name starts with the word "map" with a following "<". @@ -911,6 +1041,18 @@ bool Parser::ParseMessageFieldNoLabel( FieldDescriptorProto::kNameFieldNumber); location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::NAME); DO(ConsumeIdentifier(field->mutable_name(), "Expected field name.")); + + if (!IsLowerUnderscore(field->name())) { + AddWarning( + "Field name should be lowercase. Found: " + field->name() + + ". See: https://developers.google.com/protocol-buffers/docs/style"); + } + if (IsNumberFollowUnderscore(field->name())) { + AddWarning( + "Number should not come right after an underscore. Found: " + + field->name() + + ". See: https://developers.google.com/protocol-buffers/docs/style"); + } } DO(Consume("=", "Missing field number.")); @@ -918,8 +1060,8 @@ bool Parser::ParseMessageFieldNoLabel( { LocationRecorder location(field_location, FieldDescriptorProto::kNumberFieldNumber); - location.RecordLegacyLocation( - field, DescriptorPool::ErrorCollector::NUMBER); + location.RecordLegacyLocation(field, + DescriptorPool::ErrorCollector::NUMBER); int number; DO(ConsumeInteger(&number, "Expected field number.")); field->set_number(number); @@ -946,8 +1088,8 @@ bool Parser::ParseMessageFieldNoLabel( DescriptorProto::kNameFieldNumber); location.StartAt(name_token); location.EndAt(name_token); - location.RecordLegacyLocation( - group, DescriptorPool::ErrorCollector::NAME); + location.RecordLegacyLocation(group, + DescriptorPool::ErrorCollector::NAME); } // The field's type_name also comes from the name. Confusing! @@ -963,7 +1105,7 @@ bool Parser::ParseMessageFieldNoLabel( // not use groups; it should use nested messages. if (group->name()[0] < 'A' || 'Z' < group->name()[0]) { AddError(name_token.line, name_token.column, - "Group names must start with a capital letter."); + "Group names must start with a capital letter."); } LowerString(field->mutable_name()); @@ -990,7 +1132,7 @@ void Parser::GenerateMapEntry(const MapField& map_field, FieldDescriptorProto* field, RepeatedPtrField* messages) { DescriptorProto* entry = messages->Add(); - string entry_name = MapEntryName(field->name()); + std::string entry_name = MapEntryName(field->name()); field->set_type_name(entry_name); entry->set_name(entry_name); entry->mutable_options()->set_map_entry(true); @@ -1039,12 +1181,12 @@ void Parser::GenerateMapEntry(const MapField& map_field, option.name(0).name_part() == "enforce_utf8" && !option.name(0).is_extension()) { if (key_field->type() == FieldDescriptorProto::TYPE_STRING) { - key_field->mutable_options()->add_uninterpreted_option() - ->CopyFrom(option); + key_field->mutable_options()->add_uninterpreted_option()->CopyFrom( + option); } if (value_field->type() == FieldDescriptorProto::TYPE_STRING) { - value_field->mutable_options()->add_uninterpreted_option() - ->CopyFrom(option); + value_field->mutable_options()->add_uninterpreted_option()->CopyFrom( + option); } } } @@ -1070,8 +1212,8 @@ bool Parser::ParseFieldOptions(FieldDescriptorProto* field, // Like default value, this "json_name" is not an actual option. DO(ParseJsonName(field, field_location, containing_file)); } else { - DO(ParseOption(field->mutable_options(), location, - containing_file, OPTION_ASSIGNMENT)); + DO(ParseOption(field->mutable_options(), location, containing_file, + OPTION_ASSIGNMENT)); } } while (TryConsume(",")); @@ -1080,8 +1222,7 @@ bool Parser::ParseFieldOptions(FieldDescriptorProto* field, } bool Parser::ParseDefaultAssignment( - FieldDescriptorProto* field, - const LocationRecorder& field_location, + FieldDescriptorProto* field, const LocationRecorder& field_location, const FileDescriptorProto* containing_file) { if (field->has_default_value()) { AddError("Already set option \"default\"."); @@ -1093,9 +1234,9 @@ bool Parser::ParseDefaultAssignment( LocationRecorder location(field_location, FieldDescriptorProto::kDefaultValueFieldNumber); - location.RecordLegacyLocation( - field, DescriptorPool::ErrorCollector::DEFAULT_VALUE); - string* default_value = field->mutable_default_value(); + location.RecordLegacyLocation(field, + DescriptorPool::ErrorCollector::DEFAULT_VALUE); + std::string* default_value = field->mutable_default_value(); if (!field->has_type()) { // The field has a type name, but we don't know if it is a message or an @@ -1137,7 +1278,7 @@ bool Parser::ParseDefaultAssignment( DO(ConsumeInteger64(max_value, &value, "Expected integer for field default value.")); // And stringify it again. - default_value->append(SimpleItoa(value)); + default_value->append(StrCat(value)); break; } @@ -1160,7 +1301,7 @@ bool Parser::ParseDefaultAssignment( DO(ConsumeInteger64(max_value, &value, "Expected integer for field default value.")); // And stringify it again. - default_value->append(SimpleItoa(value)); + default_value->append(StrCat(value)); break; } @@ -1190,10 +1331,11 @@ bool Parser::ParseDefaultAssignment( break; case FieldDescriptorProto::TYPE_STRING: - // Note: When file opton java_string_check_utf8 is true, if a + // Note: When file option java_string_check_utf8 is true, if a // non-string representation (eg byte[]) is later supported, it must // be checked for UTF-8-ness. - DO(ConsumeString(default_value, "Expected string for field default " + DO(ConsumeString(default_value, + "Expected string for field default " "value.")); break; @@ -1203,8 +1345,9 @@ bool Parser::ParseDefaultAssignment( break; case FieldDescriptorProto::TYPE_ENUM: - DO(ConsumeIdentifier(default_value, "Expected enum identifier for field " - "default value.")); + DO(ConsumeIdentifier(default_value, + "Expected enum identifier for field " + "default value.")); break; case FieldDescriptorProto::TYPE_MESSAGE: @@ -1216,34 +1359,37 @@ bool Parser::ParseDefaultAssignment( return true; } -bool Parser::ParseJsonName( - FieldDescriptorProto* field, - const LocationRecorder& field_location, - const FileDescriptorProto* containing_file) { +bool Parser::ParseJsonName(FieldDescriptorProto* field, + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file) { if (field->has_json_name()) { AddError("Already set option \"json_name\"."); field->clear_json_name(); } + LocationRecorder location(field_location, + FieldDescriptorProto::kJsonNameFieldNumber); + location.RecordLegacyLocation(field, + DescriptorPool::ErrorCollector::OPTION_NAME); + DO(Consume("json_name")); DO(Consume("=")); - LocationRecorder location(field_location, - FieldDescriptorProto::kJsonNameFieldNumber); - location.RecordLegacyLocation( + LocationRecorder value_location(location); + value_location.RecordLegacyLocation( field, DescriptorPool::ErrorCollector::OPTION_VALUE); + DO(ConsumeString(field->mutable_json_name(), "Expected string for JSON name.")); return true; } - bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option, const LocationRecorder& part_location, const FileDescriptorProto* containing_file) { UninterpretedOption::NamePart* name = uninterpreted_option->add_name(); - string identifier; // We parse identifiers into this string. - if (LookingAt("(")) { // This is an extension. + std::string identifier; // We parse identifiers into this string. + if (LookingAt("(")) { // This is an extension. DO(Consume("(")); { @@ -1275,7 +1421,7 @@ bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option, return true; } -bool Parser::ParseUninterpretedBlock(string* value) { +bool Parser::ParseUninterpretedBlock(std::string* value) { // Note that enclosing braces are not added to *value. // We do NOT use ConsumeEndOfStatement for this brace because it's delimiting // an expression, not a block of statements. @@ -1307,8 +1453,8 @@ bool Parser::ParseOption(Message* options, const FileDescriptorProto* containing_file, OptionStyle style) { // Create an entry in the uninterpreted_option field. - const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()-> - FindFieldByName("uninterpreted_option"); + const FieldDescriptor* uninterpreted_option_field = + options->GetDescriptor()->FindFieldByName("uninterpreted_option"); GOOGLE_CHECK(uninterpreted_option_field != NULL) << "No field named \"uninterpreted_option\" in the Options proto."; @@ -1322,9 +1468,9 @@ bool Parser::ParseOption(Message* options, DO(Consume("option")); } - UninterpretedOption* uninterpreted_option = down_cast( - options->GetReflection()->AddMessage(options, - uninterpreted_option_field)); + UninterpretedOption* uninterpreted_option = + down_cast(options->GetReflection()->AddMessage( + options, uninterpreted_option_field)); // Parse dot-separated name. { @@ -1376,7 +1522,7 @@ bool Parser::ParseOption(Message* options, AddError("Invalid '-' symbol before identifier."); return false; } - string value; + std::string value; DO(ConsumeIdentifier(&value, "Expected identifier.")); uninterpreted_option->set_identifier_value(value); break; @@ -1414,7 +1560,7 @@ bool Parser::ParseOption(Message* options, AddError("Invalid '-' symbol before string."); return false; } - string value; + std::string value; DO(ConsumeString(&value, "Expected string.")); uninterpreted_option->set_string_value(value); break; @@ -1455,8 +1601,8 @@ bool Parser::ParseExtensions(DescriptorProto* message, message->extension_range_size()); DescriptorProto::ExtensionRange* range = message->add_extension_range(); - location.RecordLegacyLocation( - range, DescriptorPool::ErrorCollector::NUMBER); + location.RecordLegacyLocation(range, + DescriptorPool::ErrorCollector::NUMBER); int start, end; io::Tokenizer::Token start_token; @@ -1496,26 +1642,46 @@ bool Parser::ParseExtensions(DescriptorProto* message, } while (TryConsume(",")); if (LookingAt("[")) { - LocationRecorder location( - extensions_location, - DescriptorProto::ExtensionRange::kOptionsFieldNumber); - - DO(Consume("[")); + int range_number_index = extensions_location.CurrentPathSize(); + SourceCodeInfo info; // Parse extension range options in the first range. ExtensionRangeOptions* options = message->mutable_extension_range(old_range_size)->mutable_options(); - do { - DO(ParseOption(options, location, containing_file, OPTION_ASSIGNMENT)); - } while (TryConsume(",")); - DO(Consume("]")); + { + LocationRecorder index_location( + extensions_location, 0 /* we fill this in w/ actual index below */, + &info); + LocationRecorder location( + index_location, DescriptorProto::ExtensionRange::kOptionsFieldNumber); + DO(Consume("[")); + + do { + DO(ParseOption(options, location, containing_file, OPTION_ASSIGNMENT)); + } while (TryConsume(",")); + + DO(Consume("]")); + } // Then copy the extension range options to all of the other ranges we've // parsed. for (int i = old_range_size + 1; i < message->extension_range_size(); i++) { - message->mutable_extension_range(i)->mutable_options() - ->CopyFrom(*options); + message->mutable_extension_range(i)->mutable_options()->CopyFrom( + *options); + } + // and copy source locations to the other ranges, too + for (int i = old_range_size; i < message->extension_range_size(); i++) { + for (int j = 0; j < info.location_size(); j++) { + if (info.location(j).path_size() == range_number_index + 1) { + // this location's path is up to the extension range index, but + // doesn't include options; so it's redundant with location above + continue; + } + SourceCodeInfo_Location* dest = source_code_info_->add_location(); + *dest = info.location(j); + dest->set_path(range_number_index, i); + } } } @@ -1527,20 +1693,22 @@ bool Parser::ParseExtensions(DescriptorProto* message, // name literals. bool Parser::ParseReserved(DescriptorProto* message, const LocationRecorder& message_location) { + io::Tokenizer::Token start_token = input_->current(); // Parse the declaration. DO(Consume("reserved")); if (LookingAtType(io::Tokenizer::TYPE_STRING)) { LocationRecorder location(message_location, DescriptorProto::kReservedNameFieldNumber); + location.StartAt(start_token); return ParseReservedNames(message, location); } else { LocationRecorder location(message_location, DescriptorProto::kReservedRangeFieldNumber); + location.StartAt(start_token); return ParseReservedNumbers(message, location); } } - bool Parser::ParseReservedNames(DescriptorProto* message, const LocationRecorder& parent_location) { do { @@ -1564,9 +1732,8 @@ bool Parser::ParseReservedNumbers(DescriptorProto* message, LocationRecorder start_location( location, DescriptorProto::ReservedRange::kStartFieldNumber); start_token = input_->current(); - DO(ConsumeInteger(&start, (first ? - "Expected field name or number range." : - "Expected field number range."))); + DO(ConsumeInteger(&start, (first ? "Expected field name or number range." + : "Expected field number range."))); } if (TryConsume("to")) { @@ -1601,6 +1768,80 @@ bool Parser::ParseReservedNumbers(DescriptorProto* message, return true; } +bool Parser::ParseReserved(EnumDescriptorProto* message, + const LocationRecorder& message_location) { + io::Tokenizer::Token start_token = input_->current(); + // Parse the declaration. + DO(Consume("reserved")); + if (LookingAtType(io::Tokenizer::TYPE_STRING)) { + LocationRecorder location(message_location, + DescriptorProto::kReservedNameFieldNumber); + location.StartAt(start_token); + return ParseReservedNames(message, location); + } else { + LocationRecorder location(message_location, + DescriptorProto::kReservedRangeFieldNumber); + location.StartAt(start_token); + return ParseReservedNumbers(message, location); + } +} + +bool Parser::ParseReservedNames(EnumDescriptorProto* message, + const LocationRecorder& parent_location) { + do { + LocationRecorder location(parent_location, message->reserved_name_size()); + DO(ConsumeString(message->add_reserved_name(), "Expected enum value.")); + } while (TryConsume(",")); + DO(ConsumeEndOfDeclaration(";", &parent_location)); + return true; +} + +bool Parser::ParseReservedNumbers(EnumDescriptorProto* message, + const LocationRecorder& parent_location) { + bool first = true; + do { + LocationRecorder location(parent_location, message->reserved_range_size()); + + EnumDescriptorProto::EnumReservedRange* range = + message->add_reserved_range(); + int start, end; + io::Tokenizer::Token start_token; + { + LocationRecorder start_location( + location, EnumDescriptorProto::EnumReservedRange::kStartFieldNumber); + start_token = input_->current(); + DO(ConsumeSignedInteger(&start, + (first ? "Expected enum value or number range." + : "Expected enum number range."))); + } + + if (TryConsume("to")) { + LocationRecorder end_location( + location, EnumDescriptorProto::EnumReservedRange::kEndFieldNumber); + if (TryConsume("max")) { + // This is in the enum descriptor path, which doesn't have the message + // set duality to fix up, so it doesn't integrate with the sentinel. + end = INT_MAX; + } else { + DO(ConsumeSignedInteger(&end, "Expected integer.")); + } + } else { + LocationRecorder end_location( + location, EnumDescriptorProto::EnumReservedRange::kEndFieldNumber); + end_location.StartAt(start_token); + end_location.EndAt(start_token); + end = start; + } + + range->set_start(start); + range->set_end(end); + first = false; + } while (TryConsume(",")); + + DO(ConsumeEndOfDeclaration(";", &parent_location)); + return true; +} + bool Parser::ParseExtend(RepeatedPtrField* extensions, RepeatedPtrField* messages, const LocationRecorder& parent_location, @@ -1611,7 +1852,7 @@ bool Parser::ParseExtend(RepeatedPtrField* extensions, // Parse the extendee type. io::Tokenizer::Token extendee_start = input_->current(); - string extendee; + std::string extendee; DO(ParseUserDefinedType(&extendee)); io::Tokenizer::Token extendee_end = input_->previous(); @@ -1647,8 +1888,7 @@ bool Parser::ParseExtend(RepeatedPtrField* extensions, field->set_extendee(extendee); if (!ParseMessageField(field, messages, parent_location, - location_field_number_for_nested_type, - location, + location_field_number_for_nested_type, location, containing_file)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. @@ -1660,8 +1900,7 @@ bool Parser::ParseExtend(RepeatedPtrField* extensions, } bool Parser::ParseOneof(OneofDescriptorProto* oneof_decl, - DescriptorProto* containing_type, - int oneof_index, + DescriptorProto* containing_type, int oneof_index, const LocationRecorder& oneof_location, const LocationRecorder& containing_type_location, const FileDescriptorProto* containing_file) { @@ -1693,11 +1932,11 @@ bool Parser::ParseOneof(OneofDescriptorProto* oneof_decl, // Print a nice error if the user accidentally tries to place a label // on an individual member of a oneof. - if (LookingAt("required") || - LookingAt("optional") || + if (LookingAt("required") || LookingAt("optional") || LookingAt("repeated")) { - AddError("Fields in oneofs must not have labels (required / optional " - "/ repeated)."); + AddError( + "Fields in oneofs must not have labels (required / optional " + "/ repeated)."); // We can continue parsing here because we understand what the user // meant. The error report will still make parsing fail overall. input_->Next(); @@ -1711,12 +1950,10 @@ bool Parser::ParseOneof(OneofDescriptorProto* oneof_decl, field->set_label(FieldDescriptorProto::LABEL_OPTIONAL); field->set_oneof_index(oneof_index); - if (!ParseMessageFieldNoLabel(field, - containing_type->mutable_nested_type(), + if (!ParseMessageFieldNoLabel(field, containing_type->mutable_nested_type(), containing_type_location, DescriptorProto::kNestedTypeFieldNumber, - field_location, - containing_file)) { + field_location, containing_file)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); @@ -1737,8 +1974,8 @@ bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type, { LocationRecorder location(enum_location, EnumDescriptorProto::kNameFieldNumber); - location.RecordLegacyLocation( - enum_type, DescriptorPool::ErrorCollector::NAME); + location.RecordLegacyLocation(enum_type, + DescriptorPool::ErrorCollector::NAME); DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name.")); } @@ -1779,11 +2016,14 @@ bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type, } else if (LookingAt("option")) { LocationRecorder location(enum_location, EnumDescriptorProto::kOptionsFieldNumber); - return ParseOption(enum_type->mutable_options(), location, - containing_file, OPTION_STATEMENT); + return ParseOption(enum_type->mutable_options(), location, containing_file, + OPTION_STATEMENT); + } else if (LookingAt("reserved")) { + return ParseReserved(enum_type, enum_location); } else { LocationRecorder location(enum_location, - EnumDescriptorProto::kValueFieldNumber, enum_type->value_size()); + EnumDescriptorProto::kValueFieldNumber, + enum_type->value_size()); return ParseEnumConstant(enum_type->add_value(), location, containing_file); } } @@ -1795,8 +2035,8 @@ bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value, { LocationRecorder location(enum_value_location, EnumValueDescriptorProto::kNameFieldNumber); - location.RecordLegacyLocation( - enum_value, DescriptorPool::ErrorCollector::NAME); + location.RecordLegacyLocation(enum_value, + DescriptorPool::ErrorCollector::NAME); DO(ConsumeIdentifier(enum_value->mutable_name(), "Expected enum constant name.")); } @@ -1805,10 +2045,10 @@ bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value, // Parse value. { - LocationRecorder location( - enum_value_location, EnumValueDescriptorProto::kNumberFieldNumber); - location.RecordLegacyLocation( - enum_value, DescriptorPool::ErrorCollector::NUMBER); + LocationRecorder location(enum_value_location, + EnumValueDescriptorProto::kNumberFieldNumber); + location.RecordLegacyLocation(enum_value, + DescriptorPool::ErrorCollector::NUMBER); int number; DO(ConsumeSignedInteger(&number, "Expected integer.")); @@ -1829,14 +2069,14 @@ bool Parser::ParseEnumConstantOptions( const FileDescriptorProto* containing_file) { if (!LookingAt("[")) return true; - LocationRecorder location( - enum_value_location, EnumValueDescriptorProto::kOptionsFieldNumber); + LocationRecorder location(enum_value_location, + EnumValueDescriptorProto::kOptionsFieldNumber); DO(Consume("[")); do { - DO(ParseOption(value->mutable_options(), location, - containing_file, OPTION_ASSIGNMENT)); + DO(ParseOption(value->mutable_options(), location, containing_file, + OPTION_ASSIGNMENT)); } while (TryConsume(",")); DO(Consume("]")); @@ -1847,16 +2087,15 @@ bool Parser::ParseEnumConstantOptions( // Services bool Parser::ParseServiceDefinition( - ServiceDescriptorProto* service, - const LocationRecorder& service_location, + ServiceDescriptorProto* service, const LocationRecorder& service_location, const FileDescriptorProto* containing_file) { DO(Consume("service")); { LocationRecorder location(service_location, ServiceDescriptorProto::kNameFieldNumber); - location.RecordLegacyLocation( - service, DescriptorPool::ErrorCollector::NAME); + location.RecordLegacyLocation(service, + DescriptorPool::ErrorCollector::NAME); DO(ConsumeIdentifier(service->mutable_name(), "Expected service name.")); } @@ -1892,13 +2131,14 @@ bool Parser::ParseServiceStatement(ServiceDescriptorProto* service, // empty statement; ignore return true; } else if (LookingAt("option")) { - LocationRecorder location( - service_location, ServiceDescriptorProto::kOptionsFieldNumber); - return ParseOption(service->mutable_options(), location, - containing_file, OPTION_STATEMENT); + LocationRecorder location(service_location, + ServiceDescriptorProto::kOptionsFieldNumber); + return ParseOption(service->mutable_options(), location, containing_file, + OPTION_STATEMENT); } else { LocationRecorder location(service_location, - ServiceDescriptorProto::kMethodFieldNumber, service->method_size()); + ServiceDescriptorProto::kMethodFieldNumber, + service->method_size()); return ParseServiceMethod(service->add_method(), location, containing_file); } } @@ -1911,8 +2151,7 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method, { LocationRecorder location(method_location, MethodDescriptorProto::kNameFieldNumber); - location.RecordLegacyLocation( - method, DescriptorPool::ErrorCollector::NAME); + location.RecordLegacyLocation(method, DescriptorPool::ErrorCollector::NAME); DO(ConsumeIdentifier(method->mutable_name(), "Expected method name.")); } @@ -1922,16 +2161,16 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method, if (LookingAt("stream")) { LocationRecorder location( method_location, MethodDescriptorProto::kClientStreamingFieldNumber); - location.RecordLegacyLocation( - method, DescriptorPool::ErrorCollector::OTHER); + location.RecordLegacyLocation(method, + DescriptorPool::ErrorCollector::OTHER); method->set_client_streaming(true); DO(Consume("stream")); } LocationRecorder location(method_location, MethodDescriptorProto::kInputTypeFieldNumber); - location.RecordLegacyLocation( - method, DescriptorPool::ErrorCollector::INPUT_TYPE); + location.RecordLegacyLocation(method, + DescriptorPool::ErrorCollector::INPUT_TYPE); DO(ParseUserDefinedType(method->mutable_input_type())); } DO(Consume(")")); @@ -1943,16 +2182,16 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method, if (LookingAt("stream")) { LocationRecorder location( method_location, MethodDescriptorProto::kServerStreamingFieldNumber); - location.RecordLegacyLocation( - method, DescriptorPool::ErrorCollector::OTHER); + location.RecordLegacyLocation(method, + DescriptorPool::ErrorCollector::OTHER); DO(Consume("stream")); method->set_server_streaming(true); } LocationRecorder location(method_location, MethodDescriptorProto::kOutputTypeFieldNumber); - location.RecordLegacyLocation( - method, DescriptorPool::ErrorCollector::OUTPUT_TYPE); + location.RecordLegacyLocation(method, + DescriptorPool::ErrorCollector::OUTPUT_TYPE); DO(ParseUserDefinedType(method->mutable_output_type())); } DO(Consume(")")); @@ -1985,10 +2224,9 @@ bool Parser::ParseMethodOptions(const LocationRecorder& parent_location, if (TryConsumeEndOfDeclaration(";", NULL)) { // empty statement; ignore } else { - LocationRecorder location(parent_location, - optionsFieldNumber); - if (!ParseOption(mutable_options, location, - containing_file, OPTION_STATEMENT)) { + LocationRecorder location(parent_location, optionsFieldNumber); + if (!ParseOption(mutable_options, location, containing_file, + OPTION_STATEMENT)) { // This statement failed to parse. Skip it, but keep looping to // parse other statements. SkipStatement(); @@ -2002,22 +2240,27 @@ bool Parser::ParseMethodOptions(const LocationRecorder& parent_location, // ------------------------------------------------------------------- bool Parser::ParseLabel(FieldDescriptorProto::Label* label, + const LocationRecorder& field_location, const FileDescriptorProto* containing_file) { + if (!LookingAt("optional") && !LookingAt("repeated") && + !LookingAt("required")) { + return false; + } + LocationRecorder location(field_location, + FieldDescriptorProto::kLabelFieldNumber); if (TryConsume("optional")) { *label = FieldDescriptorProto::LABEL_OPTIONAL; - return true; } else if (TryConsume("repeated")) { *label = FieldDescriptorProto::LABEL_REPEATED; - return true; - } else if (TryConsume("required")) { + } else { + Consume("required"); *label = FieldDescriptorProto::LABEL_REQUIRED; - return true; } - return false; + return true; } bool Parser::ParseType(FieldDescriptorProto::Type* type, - string* type_name) { + std::string* type_name) { TypeNameMap::const_iterator iter = kTypeNames.find(input_->current().text); if (iter != kTypeNames.end()) { *type = iter->second; @@ -2028,7 +2271,7 @@ bool Parser::ParseType(FieldDescriptorProto::Type* type, return true; } -bool Parser::ParseUserDefinedType(string* type_name) { +bool Parser::ParseUserDefinedType(std::string* type_name) { type_name->clear(); TypeNameMap::const_iterator iter = kTypeNames.find(input_->current().text); @@ -2049,7 +2292,7 @@ bool Parser::ParseUserDefinedType(string* type_name) { if (TryConsume(".")) type_name->append("."); // Consume the first part of the name. - string identifier; + std::string identifier; DO(ConsumeIdentifier(&identifier, "Expected type name.")); type_name->append(identifier); @@ -2075,59 +2318,59 @@ bool Parser::ParsePackage(FileDescriptorProto* file, file->clear_package(); } - DO(Consume("package")); - - { - LocationRecorder location(root_location, - FileDescriptorProto::kPackageFieldNumber); - location.RecordLegacyLocation(file, DescriptorPool::ErrorCollector::NAME); - - while (true) { - string identifier; - DO(ConsumeIdentifier(&identifier, "Expected identifier.")); - file->mutable_package()->append(identifier); - if (!TryConsume(".")) break; - file->mutable_package()->append("."); - } + LocationRecorder location(root_location, + FileDescriptorProto::kPackageFieldNumber); + location.RecordLegacyLocation(file, DescriptorPool::ErrorCollector::NAME); - location.EndAt(input_->previous()); + DO(Consume("package")); - DO(ConsumeEndOfDeclaration(";", &location)); + while (true) { + std::string identifier; + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + file->mutable_package()->append(identifier); + if (!TryConsume(".")) break; + file->mutable_package()->append("."); } + DO(ConsumeEndOfDeclaration(";", &location)); + return true; } -bool Parser::ParseImport(RepeatedPtrField* dependency, +bool Parser::ParseImport(RepeatedPtrField* dependency, RepeatedField* public_dependency, RepeatedField* weak_dependency, const LocationRecorder& root_location, const FileDescriptorProto* containing_file) { + LocationRecorder location(root_location, + FileDescriptorProto::kDependencyFieldNumber, + dependency->size()); + DO(Consume("import")); + if (LookingAt("public")) { - LocationRecorder location( + LocationRecorder public_location( root_location, FileDescriptorProto::kPublicDependencyFieldNumber, public_dependency->size()); DO(Consume("public")); *public_dependency->Add() = dependency->size(); } else if (LookingAt("weak")) { - LocationRecorder location( + LocationRecorder weak_location( root_location, FileDescriptorProto::kWeakDependencyFieldNumber, weak_dependency->size()); + weak_location.RecordLegacyImportLocation(containing_file, "weak"); DO(Consume("weak")); *weak_dependency->Add() = dependency->size(); } - { - LocationRecorder location(root_location, - FileDescriptorProto::kDependencyFieldNumber, - dependency->size()); - DO(ConsumeString(dependency->Add(), - "Expected a string naming the file to import.")); - location.EndAt(input_->previous()); + std::string import_file; + DO(ConsumeString(&import_file, + "Expected a string naming the file to import.")); + *dependency->Add() = import_file; + location.RecordLegacyImportLocation(containing_file, import_file); + + DO(ConsumeEndOfDeclaration(";", &location)); - DO(ConsumeEndOfDeclaration(";", &location)); - } return true; } @@ -2138,16 +2381,32 @@ SourceLocationTable::~SourceLocationTable() {} bool SourceLocationTable::Find( const Message* descriptor, - DescriptorPool::ErrorCollector::ErrorLocation location, - int* line, int* column) const { + DescriptorPool::ErrorCollector::ErrorLocation location, int* line, + int* column) const { const std::pair* result = FindOrNull(location_map_, std::make_pair(descriptor, location)); if (result == NULL) { - *line = -1; + *line = -1; *column = 0; return false; } else { - *line = result->first; + *line = result->first; + *column = result->second; + return true; + } +} + +bool SourceLocationTable::FindImport(const Message* descriptor, + const std::string& name, int* line, + int* column) const { + const std::pair* result = + FindOrNull(import_location_map_, std::make_pair(descriptor, name)); + if (result == nullptr) { + *line = -1; + *column = 0; + return false; + } else { + *line = result->first; *column = result->second; return true; } @@ -2155,16 +2414,21 @@ bool SourceLocationTable::Find( void SourceLocationTable::Add( const Message* descriptor, - DescriptorPool::ErrorCollector::ErrorLocation location, - int line, int column) { + DescriptorPool::ErrorCollector::ErrorLocation location, int line, + int column) { location_map_[std::make_pair(descriptor, location)] = std::make_pair(line, column); } -void SourceLocationTable::Clear() { - location_map_.clear(); +void SourceLocationTable::AddImport(const Message* descriptor, + const std::string& name, int line, + int column) { + import_location_map_[std::make_pair(descriptor, name)] = + std::make_pair(line, column); } +void SourceLocationTable::Clear() { location_map_.clear(); } + } // namespace compiler } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h index dd8b6586ee95a..e8afdbc4d834b 100644 --- a/src/google/protobuf/compiler/parser.h +++ b/src/google/protobuf/compiler/parser.h @@ -40,15 +40,18 @@ #include #include #include -#include #include -#include #include +#include +#include -namespace google { -namespace protobuf { class Message; } +#include +namespace google { namespace protobuf { + +class Message; + namespace compiler { // Defined in this file. @@ -62,7 +65,7 @@ class SourceLocationTable; // to a FileDescriptorProto. It does not resolve import directives or perform // many other kinds of validation needed to construct a complete // FileDescriptor. -class LIBPROTOBUF_EXPORT Parser { +class PROTOBUF_EXPORT Parser { public: Parser(); ~Parser(); @@ -92,7 +95,7 @@ class LIBPROTOBUF_EXPORT Parser { // Returns the identifier used in the "syntax = " declaration, if one was // seen during the last call to Parse(), or the empty string otherwise. - const string& GetSyntaxIdentifier() { return syntax_identifier_; } + const std::string& GetSyntaxIdentifier() { return syntax_identifier_; } // If set true, input files will be required to begin with a syntax // identifier. Otherwise, files may omit this. If a syntax identifier @@ -162,7 +165,7 @@ class LIBPROTOBUF_EXPORT Parser { // where "text" is the expected token text. bool Consume(const char* text); // Consume a token of type IDENTIFIER and store its text in "output". - bool ConsumeIdentifier(string* output, const char* error); + bool ConsumeIdentifier(std::string* output, const char* error); // Consume an integer and store its value in "output". bool ConsumeInteger(int* output, const char* error); // Consume a signed integer and store its value in "output". @@ -174,7 +177,7 @@ class LIBPROTOBUF_EXPORT Parser { // tokens of either INTEGER or FLOAT type. bool ConsumeNumber(double* output, const char* error); // Consume a string literal and store its (unescaped) value in "output". - bool ConsumeString(string* output, const char* error); + bool ConsumeString(std::string* output, const char* error); // Consume a token representing the end of the statement. Comments between // this token and the next will be harvested for documentation. The given @@ -185,30 +188,34 @@ class LIBPROTOBUF_EXPORT Parser { // have been passed around by const reference, for no particularly good // reason. We should probably go through and change them all to mutable // pointer to make this more intuitive. - bool TryConsumeEndOfDeclaration( - const char* text, const LocationRecorder* location); - bool TryConsumeEndOfDeclarationFinishScope( - const char* text, const LocationRecorder* location); + bool TryConsumeEndOfDeclaration(const char* text, + const LocationRecorder* location); + bool TryConsumeEndOfDeclarationFinishScope(const char* text, + const LocationRecorder* location); - bool ConsumeEndOfDeclaration( - const char* text, const LocationRecorder* location); + bool ConsumeEndOfDeclaration(const char* text, + const LocationRecorder* location); // ----------------------------------------------------------------- // Error logging helpers // Invokes error_collector_->AddError(), if error_collector_ is not NULL. - void AddError(int line, int column, const string& error); + void AddError(int line, int column, const std::string& error); // Invokes error_collector_->AddError() with the line and column number // of the current token. - void AddError(const string& error); + void AddError(const std::string& error); + + // Invokes error_collector_->AddWarning() with the line and column number + // of the current token. + void AddWarning(const std::string& warning); // Records a location in the SourceCodeInfo.location table (see // descriptor.proto). We use RAII to ensure that the start and end locations // are recorded -- the constructor records the start location and the // destructor records the end location. Since the parser is // recursive-descent, this works out beautifully. - class LIBPROTOBUF_EXPORT LocationRecorder { + class PROTOBUF_EXPORT LocationRecorder { public: // Construct the file's "root" location. LocationRecorder(Parser* parser); @@ -224,6 +231,10 @@ class LIBPROTOBUF_EXPORT Parser { LocationRecorder(const LocationRecorder& parent, int path1); LocationRecorder(const LocationRecorder& parent, int path1, int path2); + // Creates a recorder that generates locations into given source code info. + LocationRecorder(const LocationRecorder& parent, int path1, + SourceCodeInfo* source_code_info); + ~LocationRecorder(); // Add a path component. See SourceCodeInfo.Location.path in @@ -247,8 +258,14 @@ class LIBPROTOBUF_EXPORT Parser { // was passed to RecordSourceLocationsTo(), if any. SourceLocationTable // is an older way of keeping track of source locations which is still // used in some places. - void RecordLegacyLocation(const Message* descriptor, + void RecordLegacyLocation( + const Message* descriptor, DescriptorPool::ErrorCollector::ErrorLocation location); + void RecordLegacyImportLocation(const Message* descriptor, + const std::string& name); + + // Returns the number of path components in the recorder's current location. + int CurrentPathSize() const; // Attaches leading and trailing comments to the location. The two strings // will be swapped into place, so after this is called *leading and @@ -256,17 +273,18 @@ class LIBPROTOBUF_EXPORT Parser { // // TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for // why this is const. - void AttachComments(string* leading, string* trailing, - std::vector* detached_comments) const; + void AttachComments(std::string* leading, std::string* trailing, + std::vector* detached_comments) const; private: // Indexes of parent and current location in the parent // SourceCodeInfo.location repeated field. For top-level elements, // parent_index_ is -1. Parser* parser_; + SourceCodeInfo* source_code_info_; SourceCodeInfo::Location* location_; - void Init(const LocationRecorder& parent); + void Init(const LocationRecorder& parent, SourceCodeInfo* source_code_info); }; // ================================================================= @@ -304,7 +322,7 @@ class LIBPROTOBUF_EXPORT Parser { bool ParsePackage(FileDescriptorProto* file, const LocationRecorder& root_location, const FileDescriptorProto* containing_file); - bool ParseImport(RepeatedPtrField* dependency, + bool ParseImport(RepeatedPtrField* dependency, RepeatedField* public_dependency, RepeatedField* weak_dependency, const LocationRecorder& root_location, @@ -371,6 +389,12 @@ class LIBPROTOBUF_EXPORT Parser { const LocationRecorder& parent_location); bool ParseReservedNumbers(DescriptorProto* message, const LocationRecorder& parent_location); + bool ParseReserved(EnumDescriptorProto* message, + const LocationRecorder& message_location); + bool ParseReservedNames(EnumDescriptorProto* message, + const LocationRecorder& parent_location); + bool ParseReservedNumbers(EnumDescriptorProto* message, + const LocationRecorder& parent_location); // Parse an "extend" declaration. (See also comments for // ParseMessageField().) @@ -385,8 +409,7 @@ class LIBPROTOBUF_EXPORT Parser { // oneof_decl->label() since it will have had to parse the label before it // knew it was parsing a oneof. bool ParseOneof(OneofDescriptorProto* oneof_decl, - DescriptorProto* containing_type, - int oneof_index, + DescriptorProto* containing_type, int oneof_index, const LocationRecorder& oneof_location, const LocationRecorder& containing_type_location, const FileDescriptorProto* containing_file); @@ -417,15 +440,15 @@ class LIBPROTOBUF_EXPORT Parser { // Parse "required", "optional", or "repeated" and fill in "label" // with the value. Returns true if such a label is consumed. bool ParseLabel(FieldDescriptorProto::Label* label, + const LocationRecorder& field_location, const FileDescriptorProto* containing_file); // Parse a type name and fill in "type" (if it is a primitive) or // "type_name" (if it is not) with the type parsed. - bool ParseType(FieldDescriptorProto::Type* type, - string* type_name); + bool ParseType(FieldDescriptorProto::Type* type, std::string* type_name); // Parse a user-defined type and fill in "type_name" with the name. // If a primitive type is named, it is treated as an error. - bool ParseUserDefinedType(string* type_name); + bool ParseUserDefinedType(std::string* type_name); // Parses field options, i.e. the stuff in square brackets at the end // of a field definition. Also parses default value. @@ -451,8 +474,7 @@ class LIBPROTOBUF_EXPORT Parser { // Parse a single option name/value pair, e.g. "ctype = CORD". The name // identifies a field of the given Message, and the value of that field // is set to the parsed value. - bool ParseOption(Message* options, - const LocationRecorder& options_location, + bool ParseOption(Message* options, const LocationRecorder& options_location, const FileDescriptorProto* containing_file, OptionStyle style); @@ -474,7 +496,7 @@ class LIBPROTOBUF_EXPORT Parser { // REQUIRES: LookingAt("{") // When finished successfully, we are looking at the first token past // the ending brace. - bool ParseUninterpretedBlock(string* value); + bool ParseUninterpretedBlock(std::string* value); struct MapField { // Whether the field is a map field. @@ -483,8 +505,8 @@ class LIBPROTOBUF_EXPORT Parser { FieldDescriptorProto::Type key_type; FieldDescriptorProto::Type value_type; // Or the type names string if the types are customized types. - string key_type_name; - string value_type_name; + std::string key_type_name; + std::string value_type_name; MapField() : is_map_field(false) {} }; @@ -509,18 +531,18 @@ class LIBPROTOBUF_EXPORT Parser { bool had_errors_; bool require_syntax_identifier_; bool stop_after_syntax_identifier_; - string syntax_identifier_; + std::string syntax_identifier_; // Leading doc comments for the next declaration. These are not complete // yet; use ConsumeEndOfDeclaration() to get the complete comments. - string upcoming_doc_comments_; + std::string upcoming_doc_comments_; // Detached comments are not connected to any syntax entities. Elements in // this vector are paragraphs of comments separated by empty lines. The // detached comments will be put into the leading_detached_comments field for // the next element (See SourceCodeInfo.Location in descriptor.proto), when // ConsumeEndOfDeclaration() is called. - std::vector upcoming_detached_comments_; + std::vector upcoming_detached_comments_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser); }; @@ -533,7 +555,7 @@ class LIBPROTOBUF_EXPORT Parser { // far more complete information about source locations. However, as of this // writing you still need to use SourceLocationTable when integrating with // DescriptorPool. -class LIBPROTOBUF_EXPORT SourceLocationTable { +class PROTOBUF_EXPORT SourceLocationTable { public: SourceLocationTable(); ~SourceLocationTable(); @@ -544,26 +566,35 @@ class LIBPROTOBUF_EXPORT SourceLocationTable { // location" in the ErrorCollector interface). Returns true if found, false // otherwise. bool Find(const Message* descriptor, - DescriptorPool::ErrorCollector::ErrorLocation location, - int* line, int* column) const; + DescriptorPool::ErrorCollector::ErrorLocation location, int* line, + int* column) const; + bool FindImport(const Message* descriptor, const std::string& name, int* line, + int* column) const; // Adds a location to the table. void Add(const Message* descriptor, - DescriptorPool::ErrorCollector::ErrorLocation location, - int line, int column); + DescriptorPool::ErrorCollector::ErrorLocation location, int line, + int column); + void AddImport(const Message* descriptor, const std::string& name, int line, + int column); // Clears the contents of the table. void Clear(); private: typedef std::map< - std::pair, - std::pair > LocationMap; + std::pair, + std::pair > + LocationMap; LocationMap location_map_; + std::map, std::pair > + import_location_map_; }; } // namespace compiler } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_PARSER_H__ diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc index 97831f71cb644..a413d74d06f98 100644 --- a/src/google/protobuf/compiler/parser_unittest.cc +++ b/src/google/protobuf/compiler/parser_unittest.cc @@ -32,28 +32,26 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include -#ifndef _SHARED_PTR_H -#include -#endif -#include +#include + #include #include +#include +#include -#include - +#include #include +#include #include #include #include #include #include #include -#include -#include - #include #include +#include +#include namespace google { namespace protobuf { @@ -63,15 +61,19 @@ namespace { class MockErrorCollector : public io::ErrorCollector { public: - MockErrorCollector() {} - ~MockErrorCollector() {} + MockErrorCollector() = default; + ~MockErrorCollector() override = default; - string text_; + std::string warning_; + std::string text_; // implements ErrorCollector --------------------------------------- - void AddError(int line, int column, const string& message) { - strings::SubstituteAndAppend(&text_, "$0:$1: $2\n", - line, column, message); + void AddWarning(int line, int column, const std::string& message) override { + strings::SubstituteAndAppend(&warning_, "$0:$1: $2\n", line, column, message); + } + + void AddError(int line, int column, const std::string& message) override { + strings::SubstituteAndAppend(&text_, "$0:$1: $2\n", line, column, message); } }; @@ -79,18 +81,20 @@ class MockValidationErrorCollector : public DescriptorPool::ErrorCollector { public: MockValidationErrorCollector(const SourceLocationTable& source_locations, io::ErrorCollector* wrapped_collector) - : source_locations_(source_locations), - wrapped_collector_(wrapped_collector) {} + : source_locations_(source_locations), + wrapped_collector_(wrapped_collector) {} ~MockValidationErrorCollector() {} // implements ErrorCollector --------------------------------------- - void AddError(const string& filename, - const string& element_name, - const Message* descriptor, - ErrorLocation location, - const string& message) { + void AddError(const std::string& filename, const std::string& element_name, + const Message* descriptor, ErrorLocation location, + const std::string& message) { int line, column; - source_locations_.Find(descriptor, location, &line, &column); + if (location == DescriptorPool::ErrorCollector::IMPORT) { + source_locations_.FindImport(descriptor, element_name, &line, &column); + } else { + source_locations_.Find(descriptor, location, &line, &column); + } wrapped_collector_->AddError(line, column, message); } @@ -101,8 +105,7 @@ class MockValidationErrorCollector : public DescriptorPool::ErrorCollector { class ParserTest : public testing::Test { protected: - ParserTest() - : require_syntax_identifier_(false) {} + ParserTest() : require_syntax_identifier_(false) {} // Set up the parser to parse the given text. void SetupParser(const char* text) { @@ -167,19 +170,19 @@ class ParserTest : public testing::Test { EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); ASSERT_EQ("", error_collector_.text_); - MockValidationErrorCollector validation_error_collector( - source_locations, &error_collector_); + MockValidationErrorCollector validation_error_collector(source_locations, + &error_collector_); EXPECT_TRUE(pool_.BuildFileCollectingErrors( - file, &validation_error_collector) == NULL); + file, &validation_error_collector) == NULL); EXPECT_EQ(expected_errors, error_collector_.text_); } MockErrorCollector error_collector_; DescriptorPool pool_; - google::protobuf::scoped_ptr raw_input_; - google::protobuf::scoped_ptr input_; - google::protobuf::scoped_ptr parser_; + std::unique_ptr raw_input_; + std::unique_ptr input_; + std::unique_ptr parser_; bool require_syntax_identifier_; }; @@ -187,9 +190,9 @@ class ParserTest : public testing::Test { TEST_F(ParserTest, StopAfterSyntaxIdentifier) { SetupParser( - "// blah\n" - "syntax = \"foobar\";\n" - "this line will not be parsed\n"); + "// blah\n" + "syntax = \"foobar\";\n" + "this line will not be parsed\n"); parser_->SetStopAfterSyntaxIdentifier(true); EXPECT_TRUE(parser_->Parse(input_.get(), NULL)); EXPECT_EQ("", error_collector_.text_); @@ -198,8 +201,8 @@ TEST_F(ParserTest, StopAfterSyntaxIdentifier) { TEST_F(ParserTest, StopAfterOmittedSyntaxIdentifier) { SetupParser( - "// blah\n" - "this line will not be parsed\n"); + "// blah\n" + "this line will not be parsed\n"); parser_->SetStopAfterSyntaxIdentifier(true); EXPECT_TRUE(parser_->Parse(input_.get(), NULL)); EXPECT_EQ("", error_collector_.text_); @@ -208,8 +211,8 @@ TEST_F(ParserTest, StopAfterOmittedSyntaxIdentifier) { TEST_F(ParserTest, StopAfterSyntaxIdentifierWithErrors) { SetupParser( - "// blah\n" - "syntax = error;\n"); + "// blah\n" + "syntax = error;\n"); parser_->SetStopAfterSyntaxIdentifier(true); EXPECT_FALSE(parser_->Parse(input_.get(), NULL)); EXPECT_EQ("1:9: Expected syntax identifier.\n", error_collector_.text_); @@ -220,8 +223,45 @@ TEST_F(ParserTest, WarnIfSyntaxIdentifierOmmitted) { FileDescriptorProto file; CaptureTestStderr(); EXPECT_TRUE(parser_->Parse(input_.get(), &file)); - EXPECT_TRUE( - GetCapturedTestStderr().find("No syntax specified") != string::npos); + EXPECT_TRUE(GetCapturedTestStderr().find("No syntax specified") != + std::string::npos); +} + +TEST_F(ParserTest, WarnIfFieldNameIsNotUpperCamel) { + SetupParser( + "syntax = \"proto2\";" + "message abc {}"); + FileDescriptorProto file; + EXPECT_TRUE(parser_->Parse(input_.get(), &file)); + EXPECT_TRUE(error_collector_.warning_.find( + "Message name should be in UpperCamelCase. Found: abc.") != + std::string::npos); +} + +TEST_F(ParserTest, WarnIfFieldNameIsNotLowerUnderscore) { + SetupParser( + "syntax = \"proto2\";" + "message A {" + " optional string SongName = 1;" + "}"); + FileDescriptorProto file; + EXPECT_TRUE(parser_->Parse(input_.get(), &file)); + EXPECT_TRUE(error_collector_.warning_.find( + "Field name should be lowercase. Found: SongName") != + std::string::npos); +} + +TEST_F(ParserTest, WarnIfFieldNameContainsNumberImmediatelyFollowUnderscore) { + SetupParser( + "syntax = \"proto2\";" + "message A {" + " optional string song_name_1 = 1;" + "}"); + FileDescriptorProto file; + EXPECT_TRUE(parser_->Parse(input_.get(), &file)); + EXPECT_TRUE(error_collector_.warning_.find( + "Number should not come right after an underscore. Found: " + "song_name_1.") != std::string::npos); } // =================================================================== @@ -229,22 +269,25 @@ TEST_F(ParserTest, WarnIfSyntaxIdentifierOmmitted) { typedef ParserTest ParseMessageTest; TEST_F(ParseMessageTest, IgnoreBOM) { - char input[] = " message TestMessage {\n" + char input[] = + " message TestMessage {\n" " required int32 foo = 1;\n" "}\n"; // Set UTF-8 BOM. input[0] = (char)0xEF; input[1] = (char)0xBB; input[2] = (char)0xBF; - ExpectParsesTo(input, - "message_type {" - " name: \"TestMessage\"" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" - "}"); + ExpectParsesTo( + input, + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" + "}"); } TEST_F(ParseMessageTest, BOMError) { - char input[] = " message TestMessage {\n" + char input[] = + " message TestMessage {\n" " required int32 foo = 1;\n" "}\n"; input[0] = (char)0xEF; @@ -256,590 +299,634 @@ TEST_F(ParseMessageTest, BOMError) { TEST_F(ParseMessageTest, SimpleMessage) { ExpectParsesTo( - "message TestMessage {\n" - " required int32 foo = 1;\n" - "}\n", + "message TestMessage {\n" + " required int32 foo = 1;\n" + "}\n", - "message_type {" - " name: \"TestMessage\"" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" - "}"); + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" + "}"); } TEST_F(ParseMessageTest, ImplicitSyntaxIdentifier) { require_syntax_identifier_ = false; ExpectParsesTo( - "message TestMessage {\n" - " required int32 foo = 1;\n" - "}\n", - - "message_type {" - " name: \"TestMessage\"" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" - "}"); + "message TestMessage {\n" + " required int32 foo = 1;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" + "}"); EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); } TEST_F(ParseMessageTest, ExplicitSyntaxIdentifier) { ExpectParsesTo( - "syntax = \"proto2\";\n" - "message TestMessage {\n" - " required int32 foo = 1;\n" - "}\n", - - "syntax: 'proto2' " - "message_type {" - " name: \"TestMessage\"" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" - "}"); + "syntax = \"proto2\";\n" + "message TestMessage {\n" + " required int32 foo = 1;\n" + "}\n", + + "syntax: 'proto2' " + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" + "}"); EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); } TEST_F(ParseMessageTest, ExplicitRequiredSyntaxIdentifier) { require_syntax_identifier_ = true; ExpectParsesTo( - "syntax = \"proto2\";\n" - "message TestMessage {\n" - " required int32 foo = 1;\n" - "}\n", - - "syntax: 'proto2' " - "message_type {" - " name: \"TestMessage\"" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" - "}"); + "syntax = \"proto2\";\n" + "message TestMessage {\n" + " required int32 foo = 1;\n" + "}\n", + + "syntax: 'proto2' " + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" + "}"); EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); } TEST_F(ParseMessageTest, SimpleFields) { ExpectParsesTo( - "message TestMessage {\n" - " required int32 foo = 15;\n" - " optional int32 bar = 34;\n" - " repeated int32 baz = 3;\n" - "}\n", + "message TestMessage {\n" + " required int32 foo = 15;\n" + " optional int32 bar = 34;\n" + " repeated int32 baz = 3;\n" + "}\n", - "message_type {" - " name: \"TestMessage\"" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:15 }" - " field { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:34 }" - " field { name:\"baz\" label:LABEL_REPEATED type:TYPE_INT32 number:3 }" - "}"); + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:15 }" + " field { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:34 }" + " field { name:\"baz\" label:LABEL_REPEATED type:TYPE_INT32 number:3 }" + "}"); } TEST_F(ParseMessageTest, PrimitiveFieldTypes) { ExpectParsesTo( - "message TestMessage {\n" - " required int32 foo = 1;\n" - " required int64 foo = 1;\n" - " required uint32 foo = 1;\n" - " required uint64 foo = 1;\n" - " required sint32 foo = 1;\n" - " required sint64 foo = 1;\n" - " required fixed32 foo = 1;\n" - " required fixed64 foo = 1;\n" - " required sfixed32 foo = 1;\n" - " required sfixed64 foo = 1;\n" - " required float foo = 1;\n" - " required double foo = 1;\n" - " required string foo = 1;\n" - " required bytes foo = 1;\n" - " required bool foo = 1;\n" - "}\n", - - "message_type {" - " name: \"TestMessage\"" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT64 number:1 }" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT32 number:1 }" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT64 number:1 }" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT32 number:1 }" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT64 number:1 }" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED32 number:1 }" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED64 number:1 }" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED32 number:1 }" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED64 number:1 }" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FLOAT number:1 }" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_DOUBLE number:1 }" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_STRING number:1 }" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BYTES number:1 }" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BOOL number:1 }" - "}"); + "message TestMessage {\n" + " required int32 foo = 1;\n" + " required int64 foo = 1;\n" + " required uint32 foo = 1;\n" + " required uint64 foo = 1;\n" + " required sint32 foo = 1;\n" + " required sint64 foo = 1;\n" + " required fixed32 foo = 1;\n" + " required fixed64 foo = 1;\n" + " required sfixed32 foo = 1;\n" + " required sfixed64 foo = 1;\n" + " required float foo = 1;\n" + " required double foo = 1;\n" + " required string foo = 1;\n" + " required bytes foo = 1;\n" + " required bool foo = 1;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 " + "}" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT64 number:1 " + "}" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT32 number:1 " + "}" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT64 number:1 " + "}" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT32 number:1 " + "}" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT64 number:1 " + "}" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED32 number:1 " + "}" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED64 number:1 " + "}" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED32 number:1 " + "}" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED64 number:1 " + "}" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FLOAT number:1 " + "}" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_DOUBLE number:1 " + "}" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_STRING number:1 " + "}" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BYTES number:1 " + "}" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BOOL number:1 " + "}" + "}"); } TEST_F(ParseMessageTest, FieldDefaults) { ExpectParsesTo( - "message TestMessage {\n" - " required int32 foo = 1 [default= 1 ];\n" - " required int32 foo = 1 [default= -2 ];\n" - " required int64 foo = 1 [default= 3 ];\n" - " required int64 foo = 1 [default= -4 ];\n" - " required uint32 foo = 1 [default= 5 ];\n" - " required uint64 foo = 1 [default= 6 ];\n" - " required float foo = 1 [default= 7.5];\n" - " required float foo = 1 [default= -8.5];\n" - " required float foo = 1 [default= 9 ];\n" - " required double foo = 1 [default= 10.5];\n" - " required double foo = 1 [default=-11.5];\n" - " required double foo = 1 [default= 12 ];\n" - " required double foo = 1 [default= inf ];\n" - " required double foo = 1 [default=-inf ];\n" - " required double foo = 1 [default= nan ];\n" - " required string foo = 1 [default='13\\001'];\n" - " required string foo = 1 [default='a' \"b\" \n \"c\"];\n" - " required bytes foo = 1 [default='14\\002'];\n" - " required bytes foo = 1 [default='a' \"b\" \n 'c'];\n" - " required bool foo = 1 [default=true ];\n" - " required Foo foo = 1 [default=FOO ];\n" - - " required int32 foo = 1 [default= 0x7FFFFFFF];\n" - " required int32 foo = 1 [default=-0x80000000];\n" - " required uint32 foo = 1 [default= 0xFFFFFFFF];\n" - " required int64 foo = 1 [default= 0x7FFFFFFFFFFFFFFF];\n" - " required int64 foo = 1 [default=-0x8000000000000000];\n" - " required uint64 foo = 1 [default= 0xFFFFFFFFFFFFFFFF];\n" - " required double foo = 1 [default= 0xabcd];\n" - "}\n", + "message TestMessage {\n" + " required int32 foo = 1 [default= 1 ];\n" + " required int32 foo = 1 [default= -2 ];\n" + " required int64 foo = 1 [default= 3 ];\n" + " required int64 foo = 1 [default= -4 ];\n" + " required uint32 foo = 1 [default= 5 ];\n" + " required uint64 foo = 1 [default= 6 ];\n" + " required float foo = 1 [default= 7.5];\n" + " required float foo = 1 [default= -8.5];\n" + " required float foo = 1 [default= 9 ];\n" + " required double foo = 1 [default= 10.5];\n" + " required double foo = 1 [default=-11.5];\n" + " required double foo = 1 [default= 12 ];\n" + " required double foo = 1 [default= inf ];\n" + " required double foo = 1 [default=-inf ];\n" + " required double foo = 1 [default= nan ];\n" + " required string foo = 1 [default='13\\001'];\n" + " required string foo = 1 [default='a' \"b\" \n \"c\"];\n" + " required bytes foo = 1 [default='14\\002'];\n" + " required bytes foo = 1 [default='a' \"b\" \n 'c'];\n" + " required bool foo = 1 [default=true ];\n" + " required Foo foo = 1 [default=FOO ];\n" + + " required int32 foo = 1 [default= 0x7FFFFFFF];\n" + " required int32 foo = 1 [default=-0x80000000];\n" + " required uint32 foo = 1 [default= 0xFFFFFFFF];\n" + " required int64 foo = 1 [default= 0x7FFFFFFFFFFFFFFF];\n" + " required int64 foo = 1 [default=-0x8000000000000000];\n" + " required uint64 foo = 1 [default= 0xFFFFFFFFFFFFFFFF];\n" + " required double foo = 1 [default= 0xabcd];\n" + "}\n", #define ETC "name:\"foo\" label:LABEL_REQUIRED number:1" - "message_type {" - " name: \"TestMessage\"" - " field { type:TYPE_INT32 default_value:\"1\" " ETC " }" - " field { type:TYPE_INT32 default_value:\"-2\" " ETC " }" - " field { type:TYPE_INT64 default_value:\"3\" " ETC " }" - " field { type:TYPE_INT64 default_value:\"-4\" " ETC " }" - " field { type:TYPE_UINT32 default_value:\"5\" " ETC " }" - " field { type:TYPE_UINT64 default_value:\"6\" " ETC " }" - " field { type:TYPE_FLOAT default_value:\"7.5\" " ETC " }" - " field { type:TYPE_FLOAT default_value:\"-8.5\" " ETC " }" - " field { type:TYPE_FLOAT default_value:\"9\" " ETC " }" - " field { type:TYPE_DOUBLE default_value:\"10.5\" " ETC " }" - " field { type:TYPE_DOUBLE default_value:\"-11.5\" " ETC " }" - " field { type:TYPE_DOUBLE default_value:\"12\" " ETC " }" - " field { type:TYPE_DOUBLE default_value:\"inf\" " ETC " }" - " field { type:TYPE_DOUBLE default_value:\"-inf\" " ETC " }" - " field { type:TYPE_DOUBLE default_value:\"nan\" " ETC " }" - " field { type:TYPE_STRING default_value:\"13\\001\" " ETC " }" - " field { type:TYPE_STRING default_value:\"abc\" " ETC " }" - " field { type:TYPE_BYTES default_value:\"14\\\\002\" " ETC " }" - " field { type:TYPE_BYTES default_value:\"abc\" " ETC " }" - " field { type:TYPE_BOOL default_value:\"true\" " ETC " }" - " field { type_name:\"Foo\" default_value:\"FOO\" " ETC " }" - - " field {" - " type:TYPE_INT32 default_value:\"2147483647\" " ETC - " }" - " field {" - " type:TYPE_INT32 default_value:\"-2147483648\" " ETC - " }" - " field {" - " type:TYPE_UINT32 default_value:\"4294967295\" " ETC - " }" - " field {" - " type:TYPE_INT64 default_value:\"9223372036854775807\" " ETC - " }" - " field {" - " type:TYPE_INT64 default_value:\"-9223372036854775808\" " ETC - " }" - " field {" - " type:TYPE_UINT64 default_value:\"18446744073709551615\" " ETC - " }" - " field {" - " type:TYPE_DOUBLE default_value:\"43981\" " ETC - " }" - "}"); + "message_type {" + " name: \"TestMessage\"" + " field { type:TYPE_INT32 default_value:\"1\" " ETC + " }" + " field { type:TYPE_INT32 default_value:\"-2\" " ETC + " }" + " field { type:TYPE_INT64 default_value:\"3\" " ETC + " }" + " field { type:TYPE_INT64 default_value:\"-4\" " ETC + " }" + " field { type:TYPE_UINT32 default_value:\"5\" " ETC + " }" + " field { type:TYPE_UINT64 default_value:\"6\" " ETC + " }" + " field { type:TYPE_FLOAT default_value:\"7.5\" " ETC + " }" + " field { type:TYPE_FLOAT default_value:\"-8.5\" " ETC + " }" + " field { type:TYPE_FLOAT default_value:\"9\" " ETC + " }" + " field { type:TYPE_DOUBLE default_value:\"10.5\" " ETC + " }" + " field { type:TYPE_DOUBLE default_value:\"-11.5\" " ETC + " }" + " field { type:TYPE_DOUBLE default_value:\"12\" " ETC + " }" + " field { type:TYPE_DOUBLE default_value:\"inf\" " ETC + " }" + " field { type:TYPE_DOUBLE default_value:\"-inf\" " ETC + " }" + " field { type:TYPE_DOUBLE default_value:\"nan\" " ETC + " }" + " field { type:TYPE_STRING default_value:\"13\\001\" " ETC + " }" + " field { type:TYPE_STRING default_value:\"abc\" " ETC + " }" + " field { type:TYPE_BYTES default_value:\"14\\\\002\" " ETC + " }" + " field { type:TYPE_BYTES default_value:\"abc\" " ETC + " }" + " field { type:TYPE_BOOL default_value:\"true\" " ETC + " }" + " field { type_name:\"Foo\" default_value:\"FOO\" " ETC + " }" + + " field {" + " type:TYPE_INT32 default_value:\"2147483647\" " ETC + " }" + " field {" + " type:TYPE_INT32 default_value:\"-2147483648\" " ETC + " }" + " field {" + " type:TYPE_UINT32 default_value:\"4294967295\" " ETC + " }" + " field {" + " type:TYPE_INT64 default_value:\"9223372036854775807\" " ETC + " }" + " field {" + " type:TYPE_INT64 default_value:\"-9223372036854775808\" " ETC + " }" + " field {" + " type:TYPE_UINT64 default_value:\"18446744073709551615\" " ETC + " }" + " field {" + " type:TYPE_DOUBLE default_value:\"43981\" " ETC + " }" + "}"); #undef ETC } TEST_F(ParseMessageTest, FieldJsonName) { ExpectParsesTo( - "message TestMessage {\n" - " optional string foo = 1 [json_name = \"@type\"];\n" - "}\n", - "message_type {" - " name: \"TestMessage\"" - " field {\n" - " name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: 1" - " json_name: \"@type\"\n" - " }\n" - "}\n"); + "message TestMessage {\n" + " optional string foo = 1 [json_name = \"@type\"];\n" + "}\n", + "message_type {" + " name: \"TestMessage\"" + " field {\n" + " name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: 1" + " json_name: \"@type\"\n" + " }\n" + "}\n"); } TEST_F(ParseMessageTest, FieldOptions) { ExpectParsesTo( - "message TestMessage {\n" - " optional string foo = 1\n" - " [ctype=CORD, (foo)=7, foo.(.bar.baz).qux.quux.(corge)=-33, \n" - " (quux)=\"x\040y\", (baz.qux)=hey];\n" - "}\n", - - "message_type {" - " name: \"TestMessage\"" - " field { name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: 1" - " options { uninterpreted_option: { name { name_part: \"ctype\" " - " is_extension: false } " - " identifier_value: \"CORD\" }" - " uninterpreted_option: { name { name_part: \"foo\" " - " is_extension: true } " - " positive_int_value: 7 }" - " uninterpreted_option: { name { name_part: \"foo\" " - " is_extension: false } " - " name { name_part: \".bar.baz\"" - " is_extension: true } " - " name { name_part: \"qux\" " - " is_extension: false } " - " name { name_part: \"quux\" " - " is_extension: false } " - " name { name_part: \"corge\" " - " is_extension: true } " - " negative_int_value: -33 }" - " uninterpreted_option: { name { name_part: \"quux\" " - " is_extension: true } " - " string_value: \"x y\" }" - " uninterpreted_option: { name { name_part: \"baz.qux\" " - " is_extension: true } " - " identifier_value: \"hey\" }" - " }" - " }" - "}"); + "message TestMessage {\n" + " optional string foo = 1\n" + " [ctype=CORD, (foo)=7, foo.(.bar.baz).qux.quux.(corge)=-33, \n" + " (quux)=\"x\040y\", (baz.qux)=hey];\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: " + "1" + " options { uninterpreted_option: { name { name_part: \"ctype\" " + " is_extension: false " + "} " + " identifier_value: \"CORD\" " + "}" + " uninterpreted_option: { name { name_part: \"foo\" " + " is_extension: true } " + " positive_int_value: 7 }" + " uninterpreted_option: { name { name_part: \"foo\" " + " is_extension: false " + "} " + " name { name_part: " + "\".bar.baz\"" + " is_extension: true } " + " name { name_part: \"qux\" " + " is_extension: false " + "} " + " name { name_part: \"quux\" " + " is_extension: false " + "} " + " name { name_part: \"corge\" " + " is_extension: true } " + " negative_int_value: -33 }" + " uninterpreted_option: { name { name_part: \"quux\" " + " is_extension: true } " + " string_value: \"x y\" }" + " uninterpreted_option: { name { name_part: " + "\"baz.qux\" " + " is_extension: true } " + " identifier_value: \"hey\" }" + " }" + " }" + "}"); } TEST_F(ParseMessageTest, Oneof) { ExpectParsesTo( - "message TestMessage {\n" - " oneof foo {\n" - " int32 a = 1;\n" - " string b = 2;\n" - " TestMessage c = 3;\n" - " group D = 4 { optional int32 i = 5; }\n" - " }\n" - "}\n", - - "message_type {" - " name: \"TestMessage\"" - " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 " - " oneof_index:0 }" - " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 " - " oneof_index:0 }" - " field { name:\"c\" label:LABEL_OPTIONAL type_name:\"TestMessage\" " - " number:3 oneof_index:0 }" - " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_GROUP " - " type_name:\"D\" number:4 oneof_index:0 }" - " oneof_decl {" - " name: \"foo\"" - " }" - " nested_type {" - " name: \"D\"" - " field { name:\"i\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 }" - " }" - "}"); + "message TestMessage {\n" + " oneof foo {\n" + " int32 a = 1;\n" + " string b = 2;\n" + " TestMessage c = 3;\n" + " group D = 4 { optional int32 i = 5; }\n" + " }\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 " + " oneof_index:0 }" + " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 " + " oneof_index:0 }" + " field { name:\"c\" label:LABEL_OPTIONAL type_name:\"TestMessage\" " + " number:3 oneof_index:0 }" + " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_GROUP " + " type_name:\"D\" number:4 oneof_index:0 }" + " oneof_decl {" + " name: \"foo\"" + " }" + " nested_type {" + " name: \"D\"" + " field { name:\"i\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 }" + " }" + "}"); } TEST_F(ParseMessageTest, MultipleOneofs) { ExpectParsesTo( - "message TestMessage {\n" - " oneof foo {\n" - " int32 a = 1;\n" - " string b = 2;\n" - " }\n" - " oneof bar {\n" - " int32 c = 3;\n" - " string d = 4;\n" - " }\n" - "}\n", - - "message_type {" - " name: \"TestMessage\"" - " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 " - " oneof_index:0 }" - " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 " - " oneof_index:0 }" - " field { name:\"c\" label:LABEL_OPTIONAL type:TYPE_INT32 number:3 " - " oneof_index:1 }" - " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_STRING number:4 " - " oneof_index:1 }" - " oneof_decl {" - " name: \"foo\"" - " }" - " oneof_decl {" - " name: \"bar\"" - " }" - "}"); + "message TestMessage {\n" + " oneof foo {\n" + " int32 a = 1;\n" + " string b = 2;\n" + " }\n" + " oneof bar {\n" + " int32 c = 3;\n" + " string d = 4;\n" + " }\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 " + " oneof_index:0 }" + " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 " + " oneof_index:0 }" + " field { name:\"c\" label:LABEL_OPTIONAL type:TYPE_INT32 number:3 " + " oneof_index:1 }" + " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_STRING number:4 " + " oneof_index:1 }" + " oneof_decl {" + " name: \"foo\"" + " }" + " oneof_decl {" + " name: \"bar\"" + " }" + "}"); } TEST_F(ParseMessageTest, Maps) { ExpectParsesTo( - "message TestMessage {\n" - " map primitive_type_map = 1;\n" - " map composite_type_map = 2;\n" - "}\n", - - "message_type {" - " name: \"TestMessage\"" - " nested_type {" - " name: \"PrimitiveTypeMapEntry\"" - " field { " - " name: \"key\" number: 1 label:LABEL_OPTIONAL" - " type:TYPE_INT32" - " }" - " field { " - " name: \"value\" number: 2 label:LABEL_OPTIONAL" - " type:TYPE_STRING" - " }" - " options { map_entry: true }" - " }" - " nested_type {" - " name: \"CompositeTypeMapEntry\"" - " field { " - " name: \"key\" number: 1 label:LABEL_OPTIONAL" - " type_name: \"KeyType\"" - " }" - " field { " - " name: \"value\" number: 2 label:LABEL_OPTIONAL" - " type_name: \"ValueType\"" - " }" - " options { map_entry: true }" - " }" - " field {" - " name: \"primitive_type_map\"" - " label: LABEL_REPEATED" - " type_name: \"PrimitiveTypeMapEntry\"" - " number: 1" - " }" - " field {" - " name: \"composite_type_map\"" - " label: LABEL_REPEATED" - " type_name: \"CompositeTypeMapEntry\"" - " number: 2" - " }" - "}"); + "message TestMessage {\n" + " map primitive_type_map = 1;\n" + " map composite_type_map = 2;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " nested_type {" + " name: \"PrimitiveTypeMapEntry\"" + " field { " + " name: \"key\" number: 1 label:LABEL_OPTIONAL" + " type:TYPE_INT32" + " }" + " field { " + " name: \"value\" number: 2 label:LABEL_OPTIONAL" + " type:TYPE_STRING" + " }" + " options { map_entry: true }" + " }" + " nested_type {" + " name: \"CompositeTypeMapEntry\"" + " field { " + " name: \"key\" number: 1 label:LABEL_OPTIONAL" + " type_name: \"KeyType\"" + " }" + " field { " + " name: \"value\" number: 2 label:LABEL_OPTIONAL" + " type_name: \"ValueType\"" + " }" + " options { map_entry: true }" + " }" + " field {" + " name: \"primitive_type_map\"" + " label: LABEL_REPEATED" + " type_name: \"PrimitiveTypeMapEntry\"" + " number: 1" + " }" + " field {" + " name: \"composite_type_map\"" + " label: LABEL_REPEATED" + " type_name: \"CompositeTypeMapEntry\"" + " number: 2" + " }" + "}"); } TEST_F(ParseMessageTest, Group) { ExpectParsesTo( - "message TestMessage {\n" - " optional group TestGroup = 1 {};\n" - "}\n", + "message TestMessage {\n" + " optional group TestGroup = 1 {};\n" + "}\n", - "message_type {" - " name: \"TestMessage\"" - " nested_type { name: \"TestGroup\" }" - " field { name:\"testgroup\" label:LABEL_OPTIONAL number:1" - " type:TYPE_GROUP type_name: \"TestGroup\" }" - "}"); + "message_type {" + " name: \"TestMessage\"" + " nested_type { name: \"TestGroup\" }" + " field { name:\"testgroup\" label:LABEL_OPTIONAL number:1" + " type:TYPE_GROUP type_name: \"TestGroup\" }" + "}"); } TEST_F(ParseMessageTest, NestedMessage) { ExpectParsesTo( - "message TestMessage {\n" - " message Nested {}\n" - " optional Nested test_nested = 1;\n" - "}\n", + "message TestMessage {\n" + " message Nested {}\n" + " optional Nested test_nested = 1;\n" + "}\n", - "message_type {" - " name: \"TestMessage\"" - " nested_type { name: \"Nested\" }" - " field { name:\"test_nested\" label:LABEL_OPTIONAL number:1" - " type_name: \"Nested\" }" - "}"); + "message_type {" + " name: \"TestMessage\"" + " nested_type { name: \"Nested\" }" + " field { name:\"test_nested\" label:LABEL_OPTIONAL number:1" + " type_name: \"Nested\" }" + "}"); } TEST_F(ParseMessageTest, NestedEnum) { ExpectParsesTo( - "message TestMessage {\n" - " enum NestedEnum {}\n" - " optional NestedEnum test_enum = 1;\n" - "}\n", + "message TestMessage {\n" + " enum NestedEnum {}\n" + " optional NestedEnum test_enum = 1;\n" + "}\n", - "message_type {" - " name: \"TestMessage\"" - " enum_type { name: \"NestedEnum\" }" - " field { name:\"test_enum\" label:LABEL_OPTIONAL number:1" - " type_name: \"NestedEnum\" }" - "}"); + "message_type {" + " name: \"TestMessage\"" + " enum_type { name: \"NestedEnum\" }" + " field { name:\"test_enum\" label:LABEL_OPTIONAL number:1" + " type_name: \"NestedEnum\" }" + "}"); } TEST_F(ParseMessageTest, ReservedRange) { ExpectParsesTo( - "message TestMessage {\n" - " required int32 foo = 1;\n" - " reserved 2, 15, 9 to 11, 3, 20 to max;\n" - "}\n", - - "message_type {" - " name: \"TestMessage\"" - " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" - " reserved_range { start:2 end:3 }" - " reserved_range { start:15 end:16 }" - " reserved_range { start:9 end:12 }" - " reserved_range { start:3 end:4 }" - " reserved_range { start:20 end:536870912 }" - "}"); + "message TestMessage {\n" + " required int32 foo = 1;\n" + " reserved 2, 15, 9 to 11, 3, 20 to max;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" + " reserved_range { start:2 end:3 }" + " reserved_range { start:15 end:16 }" + " reserved_range { start:9 end:12 }" + " reserved_range { start:3 end:4 }" + " reserved_range { start:20 end:536870912 }" + "}"); } TEST_F(ParseMessageTest, ReservedRangeOnMessageSet) { ExpectParsesTo( - "message TestMessage {\n" - " option message_set_wire_format = true;\n" - " reserved 20 to max;\n" - "}\n", - - "message_type {" - " name: \"TestMessage\"" - " options {" - " uninterpreted_option {" - " name {" - " name_part: \"message_set_wire_format\"" - " is_extension: false" - " }" - " identifier_value: \"true\"" - " }" - " }" - " reserved_range { start:20 end:2147483647 }" - "}"); + "message TestMessage {\n" + " option message_set_wire_format = true;\n" + " reserved 20 to max;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " options {" + " uninterpreted_option {" + " name {" + " name_part: \"message_set_wire_format\"" + " is_extension: false" + " }" + " identifier_value: \"true\"" + " }" + " }" + " reserved_range { start:20 end:2147483647 }" + "}"); } TEST_F(ParseMessageTest, ReservedNames) { ExpectParsesTo( - "message TestMessage {\n" - " reserved \"foo\", \"bar\";\n" - "}\n", + "message TestMessage {\n" + " reserved \"foo\", \"bar\";\n" + "}\n", - "message_type {" - " name: \"TestMessage\"" - " reserved_name: \"foo\"" - " reserved_name: \"bar\"" - "}"); + "message_type {" + " name: \"TestMessage\"" + " reserved_name: \"foo\"" + " reserved_name: \"bar\"" + "}"); } TEST_F(ParseMessageTest, ExtensionRange) { ExpectParsesTo( - "message TestMessage {\n" - " extensions 10 to 19;\n" - " extensions 30 to max;\n" - "}\n", + "message TestMessage {\n" + " extensions 10 to 19;\n" + " extensions 30 to max;\n" + "}\n", - "message_type {" - " name: \"TestMessage\"" - " extension_range { start:10 end:20 }" - " extension_range { start:30 end:536870912 }" - "}"); + "message_type {" + " name: \"TestMessage\"" + " extension_range { start:10 end:20 }" + " extension_range { start:30 end:536870912 }" + "}"); } TEST_F(ParseMessageTest, ExtensionRangeWithOptions) { ExpectParsesTo( - "message TestMessage {\n" - " extensions 10 to 19 [(i) = 5];\n" - "}\n", - - "message_type {" - " name: \"TestMessage\"" - " extension_range {" - " start:10" - " end:20" - " options {" - " uninterpreted_option {" - " name {" - " name_part: \"i\"" - " is_extension: true" - " }" - " positive_int_value: 5" - " }" - " }" - " }" - "}"); + "message TestMessage {\n" + " extensions 10 to 19 [(i) = 5];\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " extension_range {" + " start:10" + " end:20" + " options {" + " uninterpreted_option {" + " name {" + " name_part: \"i\"" + " is_extension: true" + " }" + " positive_int_value: 5" + " }" + " }" + " }" + "}"); } TEST_F(ParseMessageTest, CompoundExtensionRange) { ExpectParsesTo( - "message TestMessage {\n" - " extensions 2, 15, 9 to 11, 100 to max, 3;\n" - "}\n", + "message TestMessage {\n" + " extensions 2, 15, 9 to 11, 100 to max, 3;\n" + "}\n", - "message_type {" - " name: \"TestMessage\"" - " extension_range { start:2 end:3 }" - " extension_range { start:15 end:16 }" - " extension_range { start:9 end:12 }" - " extension_range { start:100 end:536870912 }" - " extension_range { start:3 end:4 }" - "}"); + "message_type {" + " name: \"TestMessage\"" + " extension_range { start:2 end:3 }" + " extension_range { start:15 end:16 }" + " extension_range { start:9 end:12 }" + " extension_range { start:100 end:536870912 }" + " extension_range { start:3 end:4 }" + "}"); } TEST_F(ParseMessageTest, CompoundExtensionRangeWithOptions) { ExpectParsesTo( - "message TestMessage {\n" - " extensions 2, 15, 9 to 11, 100 to max, 3 [(i) = 5];\n" - "}\n", - - "message_type {" - " name: \"TestMessage\"" - " extension_range {" - " start:2" - " end:3" - " options {" - " uninterpreted_option {" - " name {" - " name_part: \"i\"" - " is_extension: true" - " }" - " positive_int_value: 5" - " }" - " }" - " }" - " extension_range {" - " start:15" - " end:16" - " options {" - " uninterpreted_option {" - " name {" - " name_part: \"i\"" - " is_extension: true" - " }" - " positive_int_value: 5" - " }" - " }" - " }" - " extension_range {" - " start:9" - " end:12" - " options {" - " uninterpreted_option {" - " name {" - " name_part: \"i\"" - " is_extension: true" - " }" - " positive_int_value: 5" - " }" - " }" - " }" - " extension_range {" - " start:100" - " end:536870912" - " options {" - " uninterpreted_option {" - " name {" - " name_part: \"i\"" - " is_extension: true" - " }" - " positive_int_value: 5" - " }" - " }" - " }" - " extension_range {" - " start:3" - " end:4" - " options {" - " uninterpreted_option {" - " name {" - " name_part: \"i\"" - " is_extension: true" - " }" - " positive_int_value: 5" - " }" - " }" - " }" - "}"); + "message TestMessage {\n" + " extensions 2, 15, 9 to 11, 100 to max, 3 [(i) = 5];\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " extension_range {" + " start:2" + " end:3" + " options {" + " uninterpreted_option {" + " name {" + " name_part: \"i\"" + " is_extension: true" + " }" + " positive_int_value: 5" + " }" + " }" + " }" + " extension_range {" + " start:15" + " end:16" + " options {" + " uninterpreted_option {" + " name {" + " name_part: \"i\"" + " is_extension: true" + " }" + " positive_int_value: 5" + " }" + " }" + " }" + " extension_range {" + " start:9" + " end:12" + " options {" + " uninterpreted_option {" + " name {" + " name_part: \"i\"" + " is_extension: true" + " }" + " positive_int_value: 5" + " }" + " }" + " }" + " extension_range {" + " start:100" + " end:536870912" + " options {" + " uninterpreted_option {" + " name {" + " name_part: \"i\"" + " is_extension: true" + " }" + " positive_int_value: 5" + " }" + " }" + " }" + " extension_range {" + " start:3" + " end:4" + " options {" + " uninterpreted_option {" + " name {" + " name_part: \"i\"" + " is_extension: true" + " }" + " positive_int_value: 5" + " }" + " }" + " }" + "}"); } TEST_F(ParseMessageTest, LargerMaxForMessageSetWireFormatMessages) { @@ -847,77 +934,116 @@ TEST_F(ParseMessageTest, LargerMaxForMessageSetWireFormatMessages) { // extension numbers, as the numbers are not encoded as int32 field values // rather than tags. ExpectParsesTo( - "message TestMessage {\n" - " extensions 4 to max;\n" - " option message_set_wire_format = true;\n" - "}\n", - - "message_type {" - " name: \"TestMessage\"" - " extension_range { start:4 end: 0x7fffffff }" - " options {\n" - " uninterpreted_option { \n" - " name {\n" - " name_part: \"message_set_wire_format\"\n" - " is_extension: false\n" - " }\n" - " identifier_value: \"true\"\n" - " }\n" - " }\n" - "}"); + "message TestMessage {\n" + " extensions 4 to max;\n" + " option message_set_wire_format = true;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " extension_range { start:4 end: 0x7fffffff }" + " options {\n" + " uninterpreted_option { \n" + " name {\n" + " name_part: \"message_set_wire_format\"\n" + " is_extension: false\n" + " }\n" + " identifier_value: \"true\"\n" + " }\n" + " }\n" + "}"); } TEST_F(ParseMessageTest, Extensions) { ExpectParsesTo( - "extend Extendee1 { optional int32 foo = 12; }\n" - "extend Extendee2 { repeated TestMessage bar = 22; }\n", + "extend Extendee1 { optional int32 foo = 12; }\n" + "extend Extendee2 { repeated TestMessage bar = 22; }\n", - "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12" - " extendee: \"Extendee1\" } " - "extension { name:\"bar\" label:LABEL_REPEATED number:22" - " type_name:\"TestMessage\" extendee: \"Extendee2\" }"); + "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12" + " extendee: \"Extendee1\" } " + "extension { name:\"bar\" label:LABEL_REPEATED number:22" + " type_name:\"TestMessage\" extendee: \"Extendee2\" }"); } TEST_F(ParseMessageTest, ExtensionsInMessageScope) { ExpectParsesTo( - "message TestMessage {\n" - " extend Extendee1 { optional int32 foo = 12; }\n" - " extend Extendee2 { repeated TestMessage bar = 22; }\n" - "}\n", + "message TestMessage {\n" + " extend Extendee1 { optional int32 foo = 12; }\n" + " extend Extendee2 { repeated TestMessage bar = 22; }\n" + "}\n", - "message_type {" - " name: \"TestMessage\"" - " extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12" - " extendee: \"Extendee1\" }" - " extension { name:\"bar\" label:LABEL_REPEATED number:22" - " type_name:\"TestMessage\" extendee: \"Extendee2\" }" - "}"); + "message_type {" + " name: \"TestMessage\"" + " extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 " + "number:12" + " extendee: \"Extendee1\" }" + " extension { name:\"bar\" label:LABEL_REPEATED number:22" + " type_name:\"TestMessage\" extendee: \"Extendee2\" }" + "}"); } TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) { ExpectParsesTo( - "extend Extendee1 {\n" - " optional int32 foo = 12;\n" - " repeated TestMessage bar = 22;\n" - "}\n", + "extend Extendee1 {\n" + " optional int32 foo = 12;\n" + " repeated TestMessage bar = 22;\n" + "}\n", - "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12" - " extendee: \"Extendee1\" } " - "extension { name:\"bar\" label:LABEL_REPEATED number:22" - " type_name:\"TestMessage\" extendee: \"Extendee1\" }"); + "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12" + " extendee: \"Extendee1\" } " + "extension { name:\"bar\" label:LABEL_REPEATED number:22" + " type_name:\"TestMessage\" extendee: \"Extendee1\" }"); } TEST_F(ParseMessageTest, OptionalLabelProto3) { ExpectParsesTo( - "syntax = \"proto3\";\n" - "message TestMessage {\n" - " int32 foo = 1;\n" - "}\n", + "syntax = \"proto3\";\n" + "message TestMessage {\n" + " int32 foo = 1;\n" + "}\n", + + "syntax: \"proto3\" " + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 } " + "}"); +} + +TEST_F(ParseMessageTest, ExplicitOptionalLabelProto3) { + ExpectParsesTo( + "syntax = 'proto3';\n" + "message TestMessage {\n" + " optional int32 foo = 1;\n" + "}\n", + + "syntax: \"proto3\" " + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 " + " proto3_optional: true oneof_index: 0 } " + " oneof_decl { name:\"_foo\" } " + "}"); - "syntax: \"proto3\" " - "message_type {" - " name: \"TestMessage\"" - " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 } }"); + // Handle collisions in the synthetic oneof name. + ExpectParsesTo( + "syntax = 'proto3';\n" + "message TestMessage {\n" + " optional int32 foo = 1;\n" + " oneof _foo {\n" + " int32 __foo = 2;\n" + " }\n" + "}\n", + + "syntax: \"proto3\" " + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 " + " proto3_optional: true oneof_index: 1 } " + " field { name:\"__foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:2 " + " oneof_index: 0 } " + " oneof_decl { name:\"_foo\" } " + " oneof_decl { name:\"X_foo\" } " + "}"); } // =================================================================== @@ -926,72 +1052,109 @@ typedef ParserTest ParseEnumTest; TEST_F(ParseEnumTest, SimpleEnum) { ExpectParsesTo( - "enum TestEnum {\n" - " FOO = 0;\n" - "}\n", + "enum TestEnum {\n" + " FOO = 0;\n" + "}\n", - "enum_type {" - " name: \"TestEnum\"" - " value { name:\"FOO\" number:0 }" - "}"); + "enum_type {" + " name: \"TestEnum\"" + " value { name:\"FOO\" number:0 }" + "}"); } TEST_F(ParseEnumTest, Values) { ExpectParsesTo( - "enum TestEnum {\n" - " FOO = 13;\n" - " BAR = -10;\n" - " BAZ = 500;\n" - " HEX_MAX = 0x7FFFFFFF;\n" - " HEX_MIN = -0x80000000;\n" - " INT_MAX = 2147483647;\n" - " INT_MIN = -2147483648;\n" - "}\n", - - "enum_type {" - " name: \"TestEnum\"" - " value { name:\"FOO\" number:13 }" - " value { name:\"BAR\" number:-10 }" - " value { name:\"BAZ\" number:500 }" - " value { name:\"HEX_MAX\" number:2147483647 }" - " value { name:\"HEX_MIN\" number:-2147483648 }" - " value { name:\"INT_MAX\" number:2147483647 }" - " value { name:\"INT_MIN\" number:-2147483648 }" - "}"); + "enum TestEnum {\n" + " FOO = 13;\n" + " BAR = -10;\n" + " BAZ = 500;\n" + " HEX_MAX = 0x7FFFFFFF;\n" + " HEX_MIN = -0x80000000;\n" + " INT_MAX = 2147483647;\n" + " INT_MIN = -2147483648;\n" + "}\n", + + "enum_type {" + " name: \"TestEnum\"" + " value { name:\"FOO\" number:13 }" + " value { name:\"BAR\" number:-10 }" + " value { name:\"BAZ\" number:500 }" + " value { name:\"HEX_MAX\" number:2147483647 }" + " value { name:\"HEX_MIN\" number:-2147483648 }" + " value { name:\"INT_MAX\" number:2147483647 }" + " value { name:\"INT_MIN\" number:-2147483648 }" + "}"); } TEST_F(ParseEnumTest, ValueOptions) { ExpectParsesTo( - "enum TestEnum {\n" - " FOO = 13;\n" - " BAR = -10 [ (something.text) = 'abc' ];\n" - " BAZ = 500 [ (something.text) = 'def', other = 1 ];\n" - "}\n", - - "enum_type {" - " name: \"TestEnum\"" - " value { name: \"FOO\" number: 13 }" - " value { name: \"BAR\" number: -10 " - " options { " - " uninterpreted_option { " - " name { name_part: \"something.text\" is_extension: true } " - " string_value: \"abc\" " - " } " - " } " - " } " - " value { name: \"BAZ\" number: 500 " - " options { " - " uninterpreted_option { " - " name { name_part: \"something.text\" is_extension: true } " - " string_value: \"def\" " - " } " - " uninterpreted_option { " - " name { name_part: \"other\" is_extension: false } " - " positive_int_value: 1 " - " } " - " } " - " } " - "}"); + "enum TestEnum {\n" + " FOO = 13;\n" + " BAR = -10 [ (something.text) = 'abc' ];\n" + " BAZ = 500 [ (something.text) = 'def', other = 1 ];\n" + "}\n", + + "enum_type {" + " name: \"TestEnum\"" + " value { name: \"FOO\" number: 13 }" + " value { name: \"BAR\" number: -10 " + " options { " + " uninterpreted_option { " + " name { name_part: \"something.text\" is_extension: true } " + " string_value: \"abc\" " + " } " + " } " + " } " + " value { name: \"BAZ\" number: 500 " + " options { " + " uninterpreted_option { " + " name { name_part: \"something.text\" is_extension: true } " + " string_value: \"def\" " + " } " + " uninterpreted_option { " + " name { name_part: \"other\" is_extension: false } " + " positive_int_value: 1 " + " } " + " } " + " } " + "}"); +} + +TEST_F(ParseEnumTest, ReservedRange) { + ExpectParsesTo( + "enum TestEnum {\n" + " FOO = 0;\n" + " reserved -2147483648, -6 to -4, -1 to 1, 2, 15, 9 to 11, 3, 20 to " + "max;\n" + "}\n", + + "enum_type {" + " name: \"TestEnum\"" + " value { name:\"FOO\" number:0 }" + " reserved_range { start:-2147483648 end:-2147483648 }" + " reserved_range { start:-6 end:-4 }" + " reserved_range { start:-1 end:1 }" + " reserved_range { start:2 end:2 }" + " reserved_range { start:15 end:15 }" + " reserved_range { start:9 end:11 }" + " reserved_range { start:3 end:3 }" + " reserved_range { start:20 end:2147483647 }" + "}"); +} + +TEST_F(ParseEnumTest, ReservedNames) { + ExpectParsesTo( + "enum TestEnum {\n" + " FOO = 0;\n" + " reserved \"foo\", \"bar\";\n" + "}\n", + + "enum_type {" + " name: \"TestEnum\"" + " value { name:\"FOO\" number:0 }" + " reserved_name: \"foo\"" + " reserved_name: \"bar\"" + "}"); } // =================================================================== @@ -1000,80 +1163,76 @@ typedef ParserTest ParseServiceTest; TEST_F(ParseServiceTest, SimpleService) { ExpectParsesTo( - "service TestService {\n" - " rpc Foo(In) returns (Out);\n" - "}\n", + "service TestService {\n" + " rpc Foo(In) returns (Out);\n" + "}\n", - "service {" - " name: \"TestService\"" - " method { name:\"Foo\" input_type:\"In\" output_type:\"Out\" }" - "}"); + "service {" + " name: \"TestService\"" + " method { name:\"Foo\" input_type:\"In\" output_type:\"Out\" }" + "}"); } TEST_F(ParseServiceTest, MethodsAndStreams) { ExpectParsesTo( - "service TestService {\n" - " rpc Foo(In1) returns (Out1);\n" - " rpc Bar(In2) returns (Out2);\n" - " rpc Baz(In3) returns (Out3);\n" - "}\n", + "service TestService {\n" + " rpc Foo(In1) returns (Out1);\n" + " rpc Bar(In2) returns (Out2);\n" + " rpc Baz(In3) returns (Out3);\n" + "}\n", - "service {" - " name: \"TestService\"" - " method { name:\"Foo\" input_type:\"In1\" output_type:\"Out1\" }" - " method { name:\"Bar\" input_type:\"In2\" output_type:\"Out2\" }" - " method { name:\"Baz\" input_type:\"In3\" output_type:\"Out3\" }" - "}"); + "service {" + " name: \"TestService\"" + " method { name:\"Foo\" input_type:\"In1\" output_type:\"Out1\" }" + " method { name:\"Bar\" input_type:\"In2\" output_type:\"Out2\" }" + " method { name:\"Baz\" input_type:\"In3\" output_type:\"Out3\" }" + "}"); } - // =================================================================== // imports and packages typedef ParserTest ParseMiscTest; TEST_F(ParseMiscTest, ParseImport) { - ExpectParsesTo( - "import \"foo/bar/baz.proto\";\n", - "dependency: \"foo/bar/baz.proto\""); + ExpectParsesTo("import \"foo/bar/baz.proto\";\n", + "dependency: \"foo/bar/baz.proto\""); } TEST_F(ParseMiscTest, ParseMultipleImports) { ExpectParsesTo( - "import \"foo.proto\";\n" - "import \"bar.proto\";\n" - "import \"baz.proto\";\n", - "dependency: \"foo.proto\"" - "dependency: \"bar.proto\"" - "dependency: \"baz.proto\""); + "import \"foo.proto\";\n" + "import \"bar.proto\";\n" + "import \"baz.proto\";\n", + "dependency: \"foo.proto\"" + "dependency: \"bar.proto\"" + "dependency: \"baz.proto\""); } TEST_F(ParseMiscTest, ParsePublicImports) { ExpectParsesTo( - "import \"foo.proto\";\n" - "import public \"bar.proto\";\n" - "import \"baz.proto\";\n" - "import public \"qux.proto\";\n", - "dependency: \"foo.proto\"" - "dependency: \"bar.proto\"" - "dependency: \"baz.proto\"" - "dependency: \"qux.proto\"" - "public_dependency: 1 " - "public_dependency: 3 "); + "import \"foo.proto\";\n" + "import public \"bar.proto\";\n" + "import \"baz.proto\";\n" + "import public \"qux.proto\";\n", + "dependency: \"foo.proto\"" + "dependency: \"bar.proto\"" + "dependency: \"baz.proto\"" + "dependency: \"qux.proto\"" + "public_dependency: 1 " + "public_dependency: 3 "); } TEST_F(ParseMiscTest, ParsePackage) { - ExpectParsesTo( - "package foo.bar.baz;\n", - "package: \"foo.bar.baz\""); + ExpectParsesTo("package foo.bar.baz;\n", "package: \"foo.bar.baz\""); } TEST_F(ParseMiscTest, ParsePackageWithSpaces) { ExpectParsesTo( - "package foo . bar. \n" - " baz;\n", - "package: \"foo.bar.baz\""); + "package foo . bar. \n" + " baz;\n", + "package: \"foo.bar.baz\""); } // =================================================================== @@ -1081,17 +1240,17 @@ TEST_F(ParseMiscTest, ParsePackageWithSpaces) { TEST_F(ParseMiscTest, ParseFileOptions) { ExpectParsesTo( - "option java_package = \"com.google.foo\";\n" - "option optimize_for = CODE_SIZE;", + "option java_package = \"com.google.foo\";\n" + "option optimize_for = CODE_SIZE;", - "options {" - "uninterpreted_option { name { name_part: \"java_package\" " - " is_extension: false }" - " string_value: \"com.google.foo\"} " - "uninterpreted_option { name { name_part: \"optimize_for\" " - " is_extension: false }" - " identifier_value: \"CODE_SIZE\" } " - "}"); + "options {" + "uninterpreted_option { name { name_part: \"java_package\" " + " is_extension: false }" + " string_value: \"com.google.foo\"} " + "uninterpreted_option { name { name_part: \"optimize_for\" " + " is_extension: false }" + " identifier_value: \"CODE_SIZE\" } " + "}"); } // =================================================================== @@ -1116,341 +1275,335 @@ TEST_F(ParseErrorTest, MissingSyntaxIdentifier) { TEST_F(ParseErrorTest, UnknownSyntaxIdentifier) { ExpectHasEarlyExitErrors( - "syntax = \"no_such_syntax\";", - "0:9: Unrecognized syntax identifier \"no_such_syntax\". This parser " + "syntax = \"no_such_syntax\";", + "0:9: Unrecognized syntax identifier \"no_such_syntax\". This parser " "only recognizes \"proto2\" and \"proto3\".\n"); EXPECT_EQ("no_such_syntax", parser_->GetSyntaxIdentifier()); } TEST_F(ParseErrorTest, SimpleSyntaxError) { - ExpectHasErrors( - "message TestMessage @#$ { blah }", - "0:20: Expected \"{\".\n"); + ExpectHasErrors("message TestMessage @#$ { blah }", + "0:20: Expected \"{\".\n"); EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); } TEST_F(ParseErrorTest, ExpectedTopLevel) { - ExpectHasErrors( - "blah;", - "0:0: Expected top-level statement (e.g. \"message\").\n"); + ExpectHasErrors("blah;", + "0:0: Expected top-level statement (e.g. \"message\").\n"); } TEST_F(ParseErrorTest, UnmatchedCloseBrace) { // This used to cause an infinite loop. Doh. - ExpectHasErrors( - "}", - "0:0: Expected top-level statement (e.g. \"message\").\n" - "0:0: Unmatched \"}\".\n"); + ExpectHasErrors("}", + "0:0: Expected top-level statement (e.g. \"message\").\n" + "0:0: Unmatched \"}\".\n"); } // ------------------------------------------------------------------- // Message errors TEST_F(ParseErrorTest, MessageMissingName) { - ExpectHasErrors( - "message {}", - "0:8: Expected message name.\n"); + ExpectHasErrors("message {}", "0:8: Expected message name.\n"); } TEST_F(ParseErrorTest, MessageMissingBody) { - ExpectHasErrors( - "message TestMessage;", - "0:19: Expected \"{\".\n"); + ExpectHasErrors("message TestMessage;", "0:19: Expected \"{\".\n"); } TEST_F(ParseErrorTest, EofInMessage) { ExpectHasErrors( - "message TestMessage {", - "0:21: Reached end of input in message definition (missing '}').\n"); + "message TestMessage {", + "0:21: Reached end of input in message definition (missing '}').\n"); } TEST_F(ParseErrorTest, MissingFieldNumber) { ExpectHasErrors( - "message TestMessage {\n" - " optional int32 foo;\n" - "}\n", - "1:20: Missing field number.\n"); + "message TestMessage {\n" + " optional int32 foo;\n" + "}\n", + "1:20: Missing field number.\n"); } TEST_F(ParseErrorTest, ExpectedFieldNumber) { ExpectHasErrors( - "message TestMessage {\n" - " optional int32 foo = ;\n" - "}\n", - "1:23: Expected field number.\n"); + "message TestMessage {\n" + " optional int32 foo = ;\n" + "}\n", + "1:23: Expected field number.\n"); } TEST_F(ParseErrorTest, FieldNumberOutOfRange) { ExpectHasErrors( - "message TestMessage {\n" - " optional int32 foo = 0x100000000;\n" - "}\n", - "1:23: Integer out of range.\n"); + "message TestMessage {\n" + " optional int32 foo = 0x100000000;\n" + "}\n", + "1:23: Integer out of range.\n"); } TEST_F(ParseErrorTest, MissingLabel) { ExpectHasErrors( - "message TestMessage {\n" - " int32 foo = 1;\n" - "}\n", - "1:2: Expected \"required\", \"optional\", or \"repeated\".\n"); + "message TestMessage {\n" + " int32 foo = 1;\n" + "}\n", + "1:2: Expected \"required\", \"optional\", or \"repeated\".\n"); } TEST_F(ParseErrorTest, ExpectedOptionName) { ExpectHasErrors( - "message TestMessage {\n" - " optional uint32 foo = 1 [];\n" - "}\n", - "1:27: Expected identifier.\n"); + "message TestMessage {\n" + " optional uint32 foo = 1 [];\n" + "}\n", + "1:27: Expected identifier.\n"); } TEST_F(ParseErrorTest, NonExtensionOptionNameBeginningWithDot) { ExpectHasErrors( - "message TestMessage {\n" - " optional uint32 foo = 1 [.foo=1];\n" - "}\n", - "1:27: Expected identifier.\n"); + "message TestMessage {\n" + " optional uint32 foo = 1 [.foo=1];\n" + "}\n", + "1:27: Expected identifier.\n"); } TEST_F(ParseErrorTest, DefaultValueTypeMismatch) { ExpectHasErrors( - "message TestMessage {\n" - " optional uint32 foo = 1 [default=true];\n" - "}\n", - "1:35: Expected integer for field default value.\n"); + "message TestMessage {\n" + " optional uint32 foo = 1 [default=true];\n" + "}\n", + "1:35: Expected integer for field default value.\n"); } TEST_F(ParseErrorTest, DefaultValueNotBoolean) { ExpectHasErrors( - "message TestMessage {\n" - " optional bool foo = 1 [default=blah];\n" - "}\n", - "1:33: Expected \"true\" or \"false\".\n"); + "message TestMessage {\n" + " optional bool foo = 1 [default=blah];\n" + "}\n", + "1:33: Expected \"true\" or \"false\".\n"); } TEST_F(ParseErrorTest, DefaultValueNotString) { ExpectHasErrors( - "message TestMessage {\n" - " optional string foo = 1 [default=1];\n" - "}\n", - "1:35: Expected string for field default value.\n"); + "message TestMessage {\n" + " optional string foo = 1 [default=1];\n" + "}\n", + "1:35: Expected string for field default value.\n"); } TEST_F(ParseErrorTest, DefaultValueUnsignedNegative) { ExpectHasErrors( - "message TestMessage {\n" - " optional uint32 foo = 1 [default=-1];\n" - "}\n", - "1:36: Unsigned field can't have negative default value.\n"); + "message TestMessage {\n" + " optional uint32 foo = 1 [default=-1];\n" + "}\n", + "1:36: Unsigned field can't have negative default value.\n"); } TEST_F(ParseErrorTest, DefaultValueTooLarge) { ExpectHasErrors( - "message TestMessage {\n" - " optional int32 foo = 1 [default= 0x80000000];\n" - " optional int32 foo = 1 [default=-0x80000001];\n" - " optional uint32 foo = 1 [default= 0x100000000];\n" - " optional int64 foo = 1 [default= 0x80000000000000000];\n" - " optional int64 foo = 1 [default=-0x80000000000000001];\n" - " optional uint64 foo = 1 [default= 0x100000000000000000];\n" - "}\n", - "1:36: Integer out of range.\n" - "2:36: Integer out of range.\n" - "3:36: Integer out of range.\n" - "4:36: Integer out of range.\n" - "5:36: Integer out of range.\n" - "6:36: Integer out of range.\n"); + "message TestMessage {\n" + " optional int32 foo = 1 [default= 0x80000000];\n" + " optional int32 foo = 1 [default=-0x80000001];\n" + " optional uint32 foo = 1 [default= 0x100000000];\n" + " optional int64 foo = 1 [default= 0x80000000000000000];\n" + " optional int64 foo = 1 [default=-0x80000000000000001];\n" + " optional uint64 foo = 1 [default= 0x100000000000000000];\n" + "}\n", + "1:36: Integer out of range.\n" + "2:36: Integer out of range.\n" + "3:36: Integer out of range.\n" + "4:36: Integer out of range.\n" + "5:36: Integer out of range.\n" + "6:36: Integer out of range.\n"); } TEST_F(ParseErrorTest, JsonNameNotString) { ExpectHasErrors( - "message TestMessage {\n" - " optional string foo = 1 [json_name=1];\n" - "}\n", - "1:37: Expected string for JSON name.\n"); + "message TestMessage {\n" + " optional string foo = 1 [json_name=1];\n" + "}\n", + "1:37: Expected string for JSON name.\n"); } TEST_F(ParseErrorTest, DuplicateJsonName) { ExpectHasErrors( - "message TestMessage {\n" - " optional uint32 foo = 1 [json_name=\"a\",json_name=\"b\"];\n" - "}\n", - "1:41: Already set option \"json_name\".\n"); + "message TestMessage {\n" + " optional uint32 foo = 1 [json_name=\"a\",json_name=\"b\"];\n" + "}\n", + "1:41: Already set option \"json_name\".\n"); } TEST_F(ParseErrorTest, EnumValueOutOfRange) { ExpectHasErrors( - "enum TestEnum {\n" - " HEX_TOO_BIG = 0x80000000;\n" - " HEX_TOO_SMALL = -0x80000001;\n" - " INT_TOO_BIG = 2147483648;\n" - " INT_TOO_SMALL = -2147483649;\n" - "}\n", - "1:19: Integer out of range.\n" - "2:19: Integer out of range.\n" - "3:19: Integer out of range.\n" - "4:19: Integer out of range.\n"); + "enum TestEnum {\n" + " HEX_TOO_BIG = 0x80000000;\n" + " HEX_TOO_SMALL = -0x80000001;\n" + " INT_TOO_BIG = 2147483648;\n" + " INT_TOO_SMALL = -2147483649;\n" + "}\n", + "1:19: Integer out of range.\n" + "2:19: Integer out of range.\n" + "3:19: Integer out of range.\n" + "4:19: Integer out of range.\n"); } TEST_F(ParseErrorTest, EnumAllowAliasFalse) { ExpectHasErrors( - "enum Foo {\n" - " option allow_alias = false;\n" - " BAR = 1;\n" - " BAZ = 2;\n" - "}\n", - "5:0: \"Foo\" declares 'option allow_alias = false;' which has no effect. " - "Please remove the declaration.\n"); + "enum Foo {\n" + " option allow_alias = false;\n" + " BAR = 1;\n" + " BAZ = 2;\n" + "}\n", + "5:0: \"Foo\" declares 'option allow_alias = false;' which has no " + "effect. " + "Please remove the declaration.\n"); } TEST_F(ParseErrorTest, UnnecessaryEnumAllowAlias) { ExpectHasErrors( - "enum Foo {\n" - " option allow_alias = true;\n" - " BAR = 1;\n" - " BAZ = 2;\n" - "}\n", - "5:0: \"Foo\" declares support for enum aliases but no enum values share " - "field numbers. Please remove the unnecessary 'option allow_alias = true;' " - "declaration.\n"); + "enum Foo {\n" + " option allow_alias = true;\n" + " BAR = 1;\n" + " BAZ = 2;\n" + "}\n", + "5:0: \"Foo\" declares support for enum aliases but no enum values share " + "field numbers. Please remove the unnecessary 'option allow_alias = " + "true;' " + "declaration.\n"); } TEST_F(ParseErrorTest, DefaultValueMissing) { ExpectHasErrors( - "message TestMessage {\n" - " optional uint32 foo = 1 [default=];\n" - "}\n", - "1:35: Expected integer for field default value.\n"); + "message TestMessage {\n" + " optional uint32 foo = 1 [default=];\n" + "}\n", + "1:35: Expected integer for field default value.\n"); } TEST_F(ParseErrorTest, DefaultValueForGroup) { ExpectHasErrors( - "message TestMessage {\n" - " optional group Foo = 1 [default=blah] {}\n" - "}\n", - "1:34: Messages can't have default values.\n"); + "message TestMessage {\n" + " optional group Foo = 1 [default=blah] {}\n" + "}\n", + "1:34: Messages can't have default values.\n"); } TEST_F(ParseErrorTest, DuplicateDefaultValue) { ExpectHasErrors( - "message TestMessage {\n" - " optional uint32 foo = 1 [default=1,default=2];\n" - "}\n", - "1:37: Already set option \"default\".\n"); + "message TestMessage {\n" + " optional uint32 foo = 1 [default=1,default=2];\n" + "}\n", + "1:37: Already set option \"default\".\n"); } TEST_F(ParseErrorTest, MissingOneofName) { ExpectHasErrors( - "message TestMessage {\n" - " oneof {\n" - " int32 bar = 1;\n" - " }\n" - "}\n", - "1:8: Expected oneof name.\n"); + "message TestMessage {\n" + " oneof {\n" + " int32 bar = 1;\n" + " }\n" + "}\n", + "1:8: Expected oneof name.\n"); } TEST_F(ParseErrorTest, LabelInOneof) { ExpectHasErrors( - "message TestMessage {\n" - " oneof foo {\n" - " optional int32 bar = 1;\n" - " }\n" - "}\n", - "2:4: Fields in oneofs must not have labels (required / optional " + "message TestMessage {\n" + " oneof foo {\n" + " optional int32 bar = 1;\n" + " }\n" + "}\n", + "2:4: Fields in oneofs must not have labels (required / optional " "/ repeated).\n"); } TEST_F(ParseErrorTest, MapInOneof) { ExpectHasErrors( - "message TestMessage {\n" - " oneof foo {\n" - " map foo_map = 1;\n" - " map message_field = 2;\n" // a normal message field is OK - " }\n" - "}\n", - "2:7: Map fields are not allowed in oneofs.\n"); + "message TestMessage {\n" + " oneof foo {\n" + " map foo_map = 1;\n" + " map message_field = 2;\n" // a normal message field is OK + " }\n" + "}\n", + "2:7: Map fields are not allowed in oneofs.\n"); } TEST_F(ParseErrorTest, LabelForMap) { ExpectHasErrors( - "message TestMessage {\n" - " optional map int_map = 1;\n" - " required map int_map2 = 2;\n" - " repeated map int_map3 = 3;\n" - " optional map map_message = 4;\n" // a normal message field is OK - "}\n", - "1:14: Field labels (required/optional/repeated) are not allowed on map " - "fields.\n" - "2:14: Field labels (required/optional/repeated) are not allowed on map " - "fields.\n" - "3:14: Field labels (required/optional/repeated) are not allowed on map " - "fields.\n"); + "message TestMessage {\n" + " optional map int_map = 1;\n" + " required map int_map2 = 2;\n" + " repeated map int_map3 = 3;\n" + " optional map map_message = 4;\n" // a normal message field is OK + "}\n", + "1:14: Field labels (required/optional/repeated) are not allowed on map " + "fields.\n" + "2:14: Field labels (required/optional/repeated) are not allowed on map " + "fields.\n" + "3:14: Field labels (required/optional/repeated) are not allowed on map " + "fields.\n"); } TEST_F(ParseErrorTest, MalformedMaps) { ExpectHasErrors( - "message TestMessage {\n" - " map map_message = 1;\n" // a normal message field lacking label - " map str_map = 2;\n" - " map str_map2 = 3;\n" - " map<,string> str_map3 = 4;\n" - " map<> empty_map = 5;\n" - " map int_map = 1;\n" - "}", - "1:6: Expected \"required\", \"optional\", or \"repeated\".\n" - "2:12: Expected \",\".\n" - "3:13: Expected type name.\n" - "4:6: Expected type name.\n" - "5:6: Expected type name.\n" - "6:20: Expected \">\".\n" - "8:5: Map fields are not allowed to be extensions.\n"); + "message TestMessage {\n" + " map map_message = 1;\n" // a normal message field lacking label + " map str_map = 2;\n" + " map str_map2 = 3;\n" + " map<,string> str_map3 = 4;\n" + " map<> empty_map = 5;\n" + " map int_map = 1;\n" + "}", + "1:6: Expected \"required\", \"optional\", or \"repeated\".\n" + "2:12: Expected \",\".\n" + "3:13: Expected type name.\n" + "4:6: Expected type name.\n" + "5:6: Expected type name.\n" + "6:20: Expected \">\".\n" + "8:5: Map fields are not allowed to be extensions.\n"); } TEST_F(ParseErrorTest, GroupNotCapitalized) { ExpectHasErrors( - "message TestMessage {\n" - " optional group foo = 1 {}\n" - "}\n", - "1:17: Group names must start with a capital letter.\n"); + "message TestMessage {\n" + " optional group foo = 1 {}\n" + "}\n", + "1:17: Group names must start with a capital letter.\n"); } TEST_F(ParseErrorTest, GroupMissingBody) { ExpectHasErrors( - "message TestMessage {\n" - " optional group Foo = 1;\n" - "}\n", - "1:24: Missing group body.\n"); + "message TestMessage {\n" + " optional group Foo = 1;\n" + "}\n", + "1:24: Missing group body.\n"); } TEST_F(ParseErrorTest, ExtendingPrimitive) { - ExpectHasErrors( - "extend int32 { optional string foo = 4; }\n", - "0:7: Expected message type.\n"); + ExpectHasErrors("extend int32 { optional string foo = 4; }\n", + "0:7: Expected message type.\n"); } TEST_F(ParseErrorTest, ErrorInExtension) { ExpectHasErrors( - "message Foo { extensions 100 to 199; }\n" - "extend Foo { optional string foo; }\n", - "1:32: Missing field number.\n"); + "message Foo { extensions 100 to 199; }\n" + "extend Foo { optional string foo; }\n", + "1:32: Missing field number.\n"); } TEST_F(ParseErrorTest, MultipleParseErrors) { // When a statement has a parse error, the parser should be able to continue // parsing at the next statement. ExpectHasErrors( - "message TestMessage {\n" - " optional int32 foo;\n" - " !invalid statement ending in a block { blah blah { blah } blah }\n" - " optional int32 bar = 3 {}\n" - "}\n", - "1:20: Missing field number.\n" - "2:2: Expected \"required\", \"optional\", or \"repeated\".\n" - "2:2: Expected type name.\n" - "3:25: Expected \";\".\n"); + "message TestMessage {\n" + " optional int32 foo;\n" + " !invalid statement ending in a block { blah blah { blah } blah }\n" + " optional int32 bar = 3 {}\n" + "}\n", + "1:20: Missing field number.\n" + "2:2: Expected \"required\", \"optional\", or \"repeated\".\n" + "2:2: Expected type name.\n" + "3:25: Expected \";\".\n"); } TEST_F(ParseErrorTest, EofInAggregateValue) { @@ -1459,33 +1612,66 @@ TEST_F(ParseErrorTest, EofInAggregateValue) { "1:0: Unexpected end of stream while parsing aggregate value.\n"); } -TEST_F(ParseErrorTest, ExplicitOptionalLabelProto3) { +// ------------------------------------------------------------------- +// Enum errors + +TEST_F(ParseErrorTest, EofInEnum) { ExpectHasErrors( - "syntax = 'proto3';\n" - "message TestMessage {\n" - " optional int32 foo = 1;\n" + "enum TestEnum {", + "0:15: Reached end of input in enum definition (missing '}').\n"); +} + +TEST_F(ParseErrorTest, EnumValueMissingNumber) { + ExpectHasErrors( + "enum TestEnum {\n" + " FOO;\n" "}\n", - "2:11: Explicit 'optional' labels are disallowed in the Proto3 syntax. " - "To define 'optional' fields in Proto3, simply remove the 'optional' " - "label, as fields are 'optional' by default.\n"); + "1:5: Missing numeric value for enum constant.\n"); } +TEST_F(ParseErrorTest, EnumReservedStandaloneMaxNotAllowed) { + ExpectHasErrors( + "enum TestEnum {\n" + " FOO = 1;\n" + " reserved max;\n" + "}\n", + "2:11: Expected enum value or number range.\n"); +} -// ------------------------------------------------------------------- -// Enum errors +TEST_F(ParseErrorTest, EnumReservedMixNameAndNumber) { + ExpectHasErrors( + "enum TestEnum {\n" + " FOO = 1;\n" + " reserved 10, \"foo\";\n" + "}\n", + "2:15: Expected enum number range.\n"); +} -TEST_F(ParseErrorTest, EofInEnum) { +TEST_F(ParseErrorTest, EnumReservedPositiveNumberOutOfRange) { ExpectHasErrors( - "enum TestEnum {", - "0:15: Reached end of input in enum definition (missing '}').\n"); + "enum TestEnum {\n" + "FOO = 1;\n" + " reserved 2147483648;\n" + "}\n", + "2:11: Integer out of range.\n"); } -TEST_F(ParseErrorTest, EnumValueMissingNumber) { +TEST_F(ParseErrorTest, EnumReservedNegativeNumberOutOfRange) { ExpectHasErrors( - "enum TestEnum {\n" - " FOO;\n" - "}\n", - "1:5: Missing numeric value for enum constant.\n"); + "enum TestEnum {\n" + "FOO = 1;\n" + " reserved -2147483649;\n" + "}\n", + "2:12: Integer out of range.\n"); +} + +TEST_F(ParseErrorTest, EnumReservedMissingQuotes) { + ExpectHasErrors( + "enum TestEnum {\n" + " FOO = 1;\n" + " reserved foo;\n" + "}\n", + "2:11: Expected enum value or number range.\n"); } // ------------------------------------------------------------------- @@ -1493,26 +1679,42 @@ TEST_F(ParseErrorTest, EnumValueMissingNumber) { TEST_F(ParseErrorTest, ReservedStandaloneMaxNotAllowed) { ExpectHasErrors( - "message Foo {\n" - " reserved max;\n" - "}\n", - "1:11: Expected field name or number range.\n"); + "message Foo {\n" + " reserved max;\n" + "}\n", + "1:11: Expected field name or number range.\n"); } TEST_F(ParseErrorTest, ReservedMixNameAndNumber) { ExpectHasErrors( - "message Foo {\n" - " reserved 10, \"foo\";\n" - "}\n", - "1:15: Expected field number range.\n"); + "message Foo {\n" + " reserved 10, \"foo\";\n" + "}\n", + "1:15: Expected field number range.\n"); } TEST_F(ParseErrorTest, ReservedMissingQuotes) { ExpectHasErrors( - "message Foo {\n" - " reserved foo;\n" - "}\n", - "1:11: Expected field name or number range.\n"); + "message Foo {\n" + " reserved foo;\n" + "}\n", + "1:11: Expected field name or number range.\n"); +} + +TEST_F(ParseErrorTest, ReservedNegativeNumber) { + ExpectHasErrors( + "message Foo {\n" + " reserved -10;\n" + "}\n", + "1:11: Expected field name or number range.\n"); +} + +TEST_F(ParseErrorTest, ReservedNumberOutOfRange) { + ExpectHasErrors( + "message Foo {\n" + " reserved 2147483648;\n" + "}\n", + "1:11: Integer out of range.\n"); } // ------------------------------------------------------------------- @@ -1520,46 +1722,46 @@ TEST_F(ParseErrorTest, ReservedMissingQuotes) { TEST_F(ParseErrorTest, EofInService) { ExpectHasErrors( - "service TestService {", - "0:21: Reached end of input in service definition (missing '}').\n"); + "service TestService {", + "0:21: Reached end of input in service definition (missing '}').\n"); } TEST_F(ParseErrorTest, ServiceMethodPrimitiveParams) { ExpectHasErrors( - "service TestService {\n" - " rpc Foo(int32) returns (string);\n" - "}\n", - "1:10: Expected message type.\n" - "1:26: Expected message type.\n"); + "service TestService {\n" + " rpc Foo(int32) returns (string);\n" + "}\n", + "1:10: Expected message type.\n" + "1:26: Expected message type.\n"); } TEST_F(ParseErrorTest, EofInMethodOptions) { ExpectHasErrors( - "service TestService {\n" - " rpc Foo(Bar) returns(Bar) {", - "1:29: Reached end of input in method options (missing '}').\n" - "1:29: Reached end of input in service definition (missing '}').\n"); + "service TestService {\n" + " rpc Foo(Bar) returns(Bar) {", + "1:29: Reached end of input in method options (missing '}').\n" + "1:29: Reached end of input in service definition (missing '}').\n"); } TEST_F(ParseErrorTest, PrimitiveMethodInput) { ExpectHasErrors( - "service TestService {\n" - " rpc Foo(int32) returns(Bar);\n" - "}\n", - "1:10: Expected message type.\n"); + "service TestService {\n" + " rpc Foo(int32) returns(Bar);\n" + "}\n", + "1:10: Expected message type.\n"); } TEST_F(ParseErrorTest, MethodOptionTypeError) { // This used to cause an infinite loop. ExpectHasErrors( - "message Baz {}\n" - "service Foo {\n" - " rpc Bar(Baz) returns(Baz) { option invalid syntax; }\n" - "}\n", - "2:45: Expected \"=\".\n"); + "message Baz {}\n" + "service Foo {\n" + " rpc Bar(Baz) returns(Baz) { option invalid syntax; }\n" + "}\n", + "2:45: Expected \"=\".\n"); } @@ -1567,16 +1769,15 @@ TEST_F(ParseErrorTest, MethodOptionTypeError) { // Import and package errors TEST_F(ParseErrorTest, ImportNotQuoted) { - ExpectHasErrors( - "import foo;\n", - "0:7: Expected a string naming the file to import.\n"); + ExpectHasErrors("import foo;\n", + "0:7: Expected a string naming the file to import.\n"); } TEST_F(ParseErrorTest, MultiplePackagesInFile) { ExpectHasErrors( - "package foo;\n" - "package bar;\n", - "1:0: Multiple package definitions.\n"); + "package foo;\n" + "package bar;\n", + "1:0: Multiple package definitions.\n"); } // =================================================================== @@ -1595,151 +1796,276 @@ TEST_F(ParserValidationErrorTest, PackageNameError) { // Now try to define it as a package. ExpectHasValidationErrors( - "package foo.bar;", - "0:8: \"foo\" is already defined (as something other than a package) " + "package foo.bar;", + "0:0: \"foo\" is already defined (as something other than a package) " "in file \"bar.proto\".\n"); } +TEST_F(ParserValidationErrorTest, ImportUnloadedError) { + ExpectHasValidationErrors( + "package test;\n" + "\n" + "import \"unloaded.proto\";", + "2:0: Import \"unloaded.proto\" has not been loaded.\n"); +} + +TEST_F(ParserValidationErrorTest, ImportTwice) { + FileDescriptorProto other_file; + other_file.set_name("bar.proto"); + other_file.add_message_type()->set_name("foo"); + EXPECT_TRUE(pool_.BuildFile(other_file) != nullptr); + + ExpectHasValidationErrors( + "package test;\n" + "\n" + "import \"bar.proto\";\n" + " import \"bar.proto\";", + "3:2: Import \"bar.proto\" was listed twice.\n"); +} + +TEST_F(ParserValidationErrorTest, DuplicateFileError) { + FileDescriptorProto other_file; + other_file.set_name("foo.proto"); + EXPECT_TRUE(pool_.BuildFile(other_file) != nullptr); + + ExpectHasValidationErrors( + "package test;", "0:0: A file with this name is already in the pool.\n"); +} + TEST_F(ParserValidationErrorTest, MessageNameError) { ExpectHasValidationErrors( - "message Foo {}\n" - "message Foo {}\n", - "1:8: \"Foo\" is already defined.\n"); + "message Foo {}\n" + "message Foo {}\n", + "1:8: \"Foo\" is already defined.\n"); } TEST_F(ParserValidationErrorTest, FieldNameError) { ExpectHasValidationErrors( - "message Foo {\n" - " optional int32 bar = 1;\n" - " optional int32 bar = 2;\n" - "}\n", - "2:17: \"bar\" is already defined in \"Foo\".\n"); + "message Foo {\n" + " optional int32 bar = 1;\n" + " optional int32 bar = 2;\n" + "}\n", + "2:17: \"bar\" is already defined in \"Foo\".\n"); } TEST_F(ParserValidationErrorTest, FieldTypeError) { ExpectHasValidationErrors( - "message Foo {\n" - " optional Baz bar = 1;\n" - "}\n", - "1:11: \"Baz\" is not defined.\n"); + "message Foo {\n" + " optional Baz bar = 1;\n" + "}\n", + "1:11: \"Baz\" is not defined.\n"); } TEST_F(ParserValidationErrorTest, FieldNumberError) { ExpectHasValidationErrors( - "message Foo {\n" - " optional int32 bar = 0;\n" - "}\n", - "1:23: Field numbers must be positive integers.\n"); + "message Foo {\n" + " optional int32 bar = 0;\n" + "}\n", + "1:23: Field numbers must be positive integers.\n"); } TEST_F(ParserValidationErrorTest, FieldExtendeeError) { + ExpectHasValidationErrors("extend Baz { optional int32 bar = 1; }\n", + "0:7: \"Baz\" is not defined.\n"); +} + +TEST_F(ParserValidationErrorTest, ExtensionJsonNameError) { ExpectHasValidationErrors( - "extend Baz { optional int32 bar = 1; }\n", - "0:7: \"Baz\" is not defined.\n"); + "message TestMessage {\n" + " extensions 1 to 100;\n" + "}\n" + "extend TestMessage {\n" + " optional int32 foo = 12 [json_name = \"bar\"];\n" + "}", + "4:27: option json_name is not allowed on extension fields.\n"); } TEST_F(ParserValidationErrorTest, FieldDefaultValueError) { ExpectHasValidationErrors( - "enum Baz { QUX = 1; }\n" - "message Foo {\n" - " optional Baz bar = 1 [default=NO_SUCH_VALUE];\n" - "}\n", - "2:32: Enum type \"Baz\" has no value named \"NO_SUCH_VALUE\".\n"); + "enum Baz { QUX = 1; }\n" + "message Foo {\n" + " optional Baz bar = 1 [default=NO_SUCH_VALUE];\n" + "}\n", + "2:32: Enum type \"Baz\" has no value named \"NO_SUCH_VALUE\".\n"); } TEST_F(ParserValidationErrorTest, FileOptionNameError) { ExpectHasValidationErrors( - "option foo = 5;", - "0:7: Option \"foo\" unknown.\n"); + "option foo = 5;", + "0:7: Option \"foo\" unknown. Ensure that your proto definition file " + "imports the proto which defines the option.\n"); } TEST_F(ParserValidationErrorTest, FileOptionValueError) { ExpectHasValidationErrors( - "option java_outer_classname = 5;", - "0:30: Value must be quoted string for string option " - "\"google.protobuf.FileOptions.java_outer_classname\".\n"); + "option java_outer_classname = 5;", + "0:30: Value must be quoted string for string option " + "\"google.protobuf.FileOptions.java_outer_classname\".\n"); } TEST_F(ParserValidationErrorTest, FieldOptionNameError) { ExpectHasValidationErrors( - "message Foo {\n" - " optional bool bar = 1 [foo=1];\n" - "}\n", - "1:25: Option \"foo\" unknown.\n"); + "message Foo {\n" + " optional bool bar = 1 [foo=1];\n" + "}\n", + "1:25: Option \"foo\" unknown. Ensure that your proto definition file " + "imports the proto which defines the option.\n"); } TEST_F(ParserValidationErrorTest, FieldOptionValueError) { ExpectHasValidationErrors( - "message Foo {\n" - " optional int32 bar = 1 [ctype=1];\n" - "}\n", - "1:32: Value must be identifier for enum-valued option " - "\"google.protobuf.FieldOptions.ctype\".\n"); + "message Foo {\n" + " optional int32 bar = 1 [ctype=1];\n" + "}\n", + "1:32: Value must be identifier for enum-valued option " + "\"google.protobuf.FieldOptions.ctype\".\n"); } TEST_F(ParserValidationErrorTest, ExtensionRangeNumberError) { ExpectHasValidationErrors( - "message Foo {\n" - " extensions 0;\n" - "}\n", - "1:13: Extension numbers must be positive integers.\n"); + "message Foo {\n" + " extensions 0;\n" + "}\n", + "1:13: Extension numbers must be positive integers.\n"); +} + +TEST_F(ParserValidationErrorTest, Proto3ExtensionError) { + ExpectHasValidationErrors( + "syntax = 'proto3';\n" + "message Foo { \n" + " extensions 100 to 199;\n" + "}\n" + "extend Foo { string foo = 101; }\n", + "4:7: Extensions in proto3 are only allowed for defining options.\n" + "2:13: Extension ranges are not allowed in proto3.\n"); +} + +TEST_F(ParserValidationErrorTest, Proto3MessageSet) { + ExpectHasValidationErrors( + "syntax = 'proto3';\n" + "message Foo { \n" + " option message_set_wire_format = true;\n" + "}\n", + "1:8: MessageSet is not supported in proto3.\n"); +} + +TEST_F(ParserValidationErrorTest, Proto3Required) { + ExpectHasValidationErrors( + "syntax = 'proto3';\n" + "message Foo { \n" + " required int32 field = 1;" + "}\n", + "2:11: Required fields are not allowed in proto3.\n"); +} + +TEST_F(ParserValidationErrorTest, Proto3Default) { + ExpectHasValidationErrors( + "syntax = 'proto3';\n" + "message Foo { \n" + " int32 field = 1 [default = 12];" + "}\n", + "2:29: Explicit default values are not allowed in proto3.\n"); +} + +TEST_F(ParserValidationErrorTest, Proto3JsonConflictError) { + ExpectHasValidationErrors( + "syntax = 'proto3';\n" + "message TestMessage {\n" + " uint32 foo = 1;\n" + " uint32 Foo = 2;\n" + "}\n", + "3:9: The JSON camel-case name of field \"Foo\" conflicts with field " + "\"foo\". This is not allowed in proto3.\n"); } TEST_F(ParserValidationErrorTest, EnumNameError) { ExpectHasValidationErrors( - "enum Foo {A = 1;}\n" - "enum Foo {B = 1;}\n", - "1:5: \"Foo\" is already defined.\n"); + "enum Foo {A = 1;}\n" + "enum Foo {B = 1;}\n", + "1:5: \"Foo\" is already defined.\n"); +} + +TEST_F(ParserValidationErrorTest, Proto3EnumError) { + ExpectHasValidationErrors( + "syntax = 'proto3';\n" + "enum Foo {A = 1;}\n", + "1:14: The first enum value must be zero in proto3.\n"); } TEST_F(ParserValidationErrorTest, EnumValueNameError) { ExpectHasValidationErrors( - "enum Foo {\n" - " BAR = 1;\n" - " BAR = 1;\n" - "}\n", - "2:2: \"BAR\" is already defined.\n"); + "enum Foo {\n" + " BAR = 1;\n" + " BAR = 1;\n" + "}\n", + "2:2: \"BAR\" is already defined.\n"); +} + +TEST_F(ParserValidationErrorTest, EnumValueAliasError) { + ExpectHasValidationErrors( + "enum Foo {\n" + " BAR = 1;\n" + " BAZ = 1;\n" + "}\n", + "2:8: \"BAZ\" uses the same enum value as \"BAR\". If this is " + "intended, set 'option allow_alias = true;' to the enum " + "definition.\n"); +} + +TEST_F(ParserValidationErrorTest, ExplicitlyMapEntryError) { + ExpectHasValidationErrors( + "message Foo {\n" + " message ValueEntry {\n" + " option map_entry = true;\n" + " optional int32 key = 1;\n" + " optional int32 value = 2;\n" + " extensions 99 to 999;\n" + " }\n" + " repeated ValueEntry value = 1;\n" + "}", + "7:11: map_entry should not be set explicitly. Use " + "map instead.\n"); } TEST_F(ParserValidationErrorTest, ServiceNameError) { ExpectHasValidationErrors( - "service Foo {}\n" - "service Foo {}\n", - "1:8: \"Foo\" is already defined.\n"); + "service Foo {}\n" + "service Foo {}\n", + "1:8: \"Foo\" is already defined.\n"); } TEST_F(ParserValidationErrorTest, MethodNameError) { ExpectHasValidationErrors( - "message Baz {}\n" - "service Foo {\n" - " rpc Bar(Baz) returns(Baz);\n" - " rpc Bar(Baz) returns(Baz);\n" - "}\n", - "3:6: \"Bar\" is already defined in \"Foo\".\n"); + "message Baz {}\n" + "service Foo {\n" + " rpc Bar(Baz) returns(Baz);\n" + " rpc Bar(Baz) returns(Baz);\n" + "}\n", + "3:6: \"Bar\" is already defined in \"Foo\".\n"); } TEST_F(ParserValidationErrorTest, MethodInputTypeError) { ExpectHasValidationErrors( - "message Baz {}\n" - "service Foo {\n" - " rpc Bar(Qux) returns(Baz);\n" - "}\n", - "2:10: \"Qux\" is not defined.\n"); + "message Baz {}\n" + "service Foo {\n" + " rpc Bar(Qux) returns(Baz);\n" + "}\n", + "2:10: \"Qux\" is not defined.\n"); } TEST_F(ParserValidationErrorTest, MethodOutputTypeError) { ExpectHasValidationErrors( - "message Baz {}\n" - "service Foo {\n" - " rpc Bar(Baz) returns(Qux);\n" - "}\n", - "2:23: \"Qux\" is not defined.\n"); + "message Baz {}\n" + "service Foo {\n" + " rpc Bar(Baz) returns(Qux);\n" + "}\n", + "2:23: \"Qux\" is not defined.\n"); } -TEST_F(ParserValidationErrorTest, ResovledUndefinedError) { +TEST_F(ParserValidationErrorTest, ResolvedUndefinedError) { // Create another file which defines symbol ".base.bar". FileDescriptorProto other_file; other_file.set_name("base.proto"); @@ -1750,16 +2076,16 @@ TEST_F(ParserValidationErrorTest, ResovledUndefinedError) { // Define "foo.base" and try "base.bar". // "base.bar" is resolved to "foo.base.bar" which is not defined. ExpectHasValidationErrors( - "package foo.base;\n" - "import \"base.proto\";\n" - "message qux {\n" - " optional base.bar baz = 1;\n" - " optional .base.bar quz = 2;\n" - "}\n", - "3:11: \"base.bar\" is resolved to \"foo.base.bar\"," - " which is not defined. The innermost scope is searched first " - "in name resolution. Consider using a leading '.'(i.e., \".base.bar\")" - " to start from the outermost scope.\n"); + "package foo.base;\n" + "import \"base.proto\";\n" + "message qux {\n" + " optional base.bar baz = 1;\n" + " optional .base.bar quz = 2;\n" + "}\n", + "3:11: \"base.bar\" is resolved to \"foo.base.bar\"," + " which is not defined. The innermost scope is searched first " + "in name resolution. Consider using a leading '.'(i.e., \".base.bar\")" + " to start from the outermost scope.\n"); } TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) { @@ -1770,7 +2096,7 @@ TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) { // base2.proto: // package baz - // import google/protobuf/descriptor.proto + // import net/proto2/proto/descriptor.proto // message Bar { optional int32 foo = 1; } // extend FileOptions { optional Bar bar = 7672757; } FileDescriptorProto other_file; @@ -1784,14 +2110,14 @@ TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) { FieldDescriptorProto* field(message->add_field()); field->set_name("foo"); field->set_number(1); - field->set_label(FieldDescriptorProto_Label_LABEL_OPTIONAL); - field->set_type(FieldDescriptorProto_Type_TYPE_INT32); + field->set_label(FieldDescriptorProto::LABEL_OPTIONAL); + field->set_type(FieldDescriptorProto::TYPE_INT32); FieldDescriptorProto* extension(other_file.add_extension()); extension->set_name("bar"); extension->set_number(7672757); - extension->set_label(FieldDescriptorProto_Label_LABEL_OPTIONAL); - extension->set_type(FieldDescriptorProto_Type_TYPE_MESSAGE); + extension->set_label(FieldDescriptorProto::LABEL_OPTIONAL); + extension->set_type(FieldDescriptorProto::TYPE_MESSAGE); extension->set_type_name("Bar"); extension->set_extendee("google.protobuf.FileOptions"); @@ -1831,35 +2157,35 @@ class CompareDescriptorNames { }; // Sorts nested DescriptorProtos of a DescriptoProto, by name. -void SortMessages(DescriptorProto *descriptor_proto) { +void SortMessages(DescriptorProto* descriptor_proto) { int size = descriptor_proto->nested_type_size(); // recursively sort; we can't guarantee the order of nested messages either for (int i = 0; i < size; ++i) { SortMessages(descriptor_proto->mutable_nested_type(i)); } - DescriptorProto **data = - descriptor_proto->mutable_nested_type()->mutable_data(); + DescriptorProto** data = + descriptor_proto->mutable_nested_type()->mutable_data(); std::sort(data, data + size, CompareDescriptorNames()); } // Sorts DescriptorProtos belonging to a FileDescriptorProto, by name. -void SortMessages(FileDescriptorProto *file_descriptor_proto) { +void SortMessages(FileDescriptorProto* file_descriptor_proto) { int size = file_descriptor_proto->message_type_size(); // recursively sort; we can't guarantee the order of nested messages either for (int i = 0; i < size; ++i) { SortMessages(file_descriptor_proto->mutable_message_type(i)); } - DescriptorProto **data = - file_descriptor_proto->mutable_message_type()->mutable_data(); + DescriptorProto** data = + file_descriptor_proto->mutable_message_type()->mutable_data(); std::sort(data, data + size, CompareDescriptorNames()); } // Strips the message and enum field type names for comparison purpose only. void StripFieldTypeName(DescriptorProto* proto) { for (int i = 0; i < proto->field_size(); ++i) { - string type_name = proto->field(i).type_name(); - string::size_type pos = type_name.find_last_of("."); - if (pos != string::npos) { + std::string type_name = proto->field(i).type_name(); + std::string::size_type pos = type_name.find_last_of('.'); + if (pos != std::string::npos) { proto->mutable_field(i)->mutable_type_name()->assign( type_name.begin() + pos + 1, type_name.end()); } @@ -1877,26 +2203,26 @@ void StripFieldTypeName(FileDescriptorProto* file_proto) { TEST_F(ParseDescriptorDebugTest, TestAllDescriptorTypes) { const FileDescriptor* original_file = - protobuf_unittest::TestAllTypes::descriptor()->file(); + protobuf_unittest::TestAllTypes::descriptor()->file(); FileDescriptorProto expected; original_file->CopyTo(&expected); // Get the DebugString of the unittest.proto FileDecriptor, which includes // all other descriptor types - string debug_string = original_file->DebugString(); + std::string debug_string = original_file->DebugString(); // Parse the debug string SetupParser(debug_string.c_str()); FileDescriptorProto parsed; parser_->Parse(input_.get(), &parsed); EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); - ASSERT_EQ("", error_collector_.text_) - << "Failed to parse:\n" << debug_string; + ASSERT_EQ("", error_collector_.text_) << "Failed to parse:\n" << debug_string; // We now have a FileDescriptorProto, but to compare with the expected we // need to link to a FileDecriptor, then output back to a proto. We'll // also need to give it the same name as the original. - parsed.set_name("google/protobuf/unittest.proto"); + parsed.set_name( + TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto")); // We need the imported dependency before we can build our parsed proto const FileDescriptor* public_import = protobuf_unittest_import::PublicImportMessage::descriptor()->file(); @@ -1904,14 +2230,13 @@ TEST_F(ParseDescriptorDebugTest, TestAllDescriptorTypes) { public_import->CopyTo(&public_import_proto); ASSERT_TRUE(pool_.BuildFile(public_import_proto) != NULL); const FileDescriptor* import = - protobuf_unittest_import::ImportMessage::descriptor()->file(); + protobuf_unittest_import::ImportMessage::descriptor()->file(); FileDescriptorProto import_proto; import->CopyTo(&import_proto); ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL); const FileDescriptor* actual = pool_.BuildFile(parsed); parsed.Clear(); - ASSERT_TRUE(actual != NULL) - << "Failed to validate:\n" << debug_string; + ASSERT_TRUE(actual != NULL) << "Failed to validate:\n" << debug_string; actual->CopyTo(&parsed); ASSERT_TRUE(actual != NULL); @@ -1929,11 +2254,11 @@ TEST_F(ParseDescriptorDebugTest, TestAllDescriptorTypes) { TEST_F(ParseDescriptorDebugTest, TestCustomOptions) { const FileDescriptor* original_file = - protobuf_unittest::AggregateMessage::descriptor()->file(); + protobuf_unittest::AggregateMessage::descriptor()->file(); FileDescriptorProto expected; original_file->CopyTo(&expected); - string debug_string = original_file->DebugString(); + std::string debug_string = original_file->DebugString(); // Parse the debug string SetupParser(debug_string.c_str()); @@ -1952,6 +2277,11 @@ TEST_F(ParseDescriptorDebugTest, TestCustomOptions) { FileDescriptorProto import_proto; import->CopyTo(&import_proto); ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL); + + FileDescriptorProto any_import; + google::protobuf::Any::descriptor()->file()->CopyTo(&any_import); + ASSERT_TRUE(pool_.BuildFile(any_import) != nullptr); + const FileDescriptor* actual = pool_.BuildFile(parsed); ASSERT_TRUE(actual != NULL); parsed.Clear(); @@ -2041,37 +2371,38 @@ TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) { // We don't test the exact comment placement or formatting, because we do not // want to be too fragile here. const char* expected_comments[] = { - "Detached comment before syntax.", - "Syntax comment.", - "Detached comment before package.", - "Package comment.", - "Detached comment before TestMessage1.", - "Message comment.", - "More detail in message comment.", - "Detached comment before foo.", - "Field comment", - "Detached comment before NestedMessage.", - "Nested-message comment", - "Detached comment before MyEnumType.", - "Enum comment", - "Detached comment before ASDF.", - "Enum-value comment", - "Detached comment before MyService.", - "Service comment", - "Detached comment before MyRPCCall.", - "RPC comment", + "Detached comment before syntax.", + "Syntax comment.", + "Detached comment before package.", + "Package comment.", + "Detached comment before TestMessage1.", + "Message comment.", + "More detail in message comment.", + "Detached comment before foo.", + "Field comment", + "Detached comment before NestedMessage.", + "Nested-message comment", + "Detached comment before MyEnumType.", + "Enum comment", + "Detached comment before ASDF.", + "Enum-value comment", + "Detached comment before MyService.", + "Service comment", + "Detached comment before MyRPCCall.", + "RPC comment", }; DebugStringOptions debug_string_options; debug_string_options.include_comments = true; { - const string debug_string = + const std::string debug_string = descriptor->DebugStringWithOptions(debug_string_options); for (int i = 0; i < GOOGLE_ARRAYSIZE(expected_comments); ++i) { - string::size_type found_pos = debug_string.find(expected_comments[i]); - EXPECT_TRUE(found_pos != string::npos) + std::string::size_type found_pos = + debug_string.find(expected_comments[i]); + EXPECT_TRUE(found_pos != std::string::npos) << "\"" << expected_comments[i] << "\" not found."; } @@ -2080,8 +2411,8 @@ TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) { FileDescriptorProto parsed; parser_->Parse(input_.get(), &parsed); EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); - ASSERT_EQ("", error_collector_.text_) - << "Failed to parse:\n" << debug_string; + ASSERT_EQ("", error_collector_.text_) << "Failed to parse:\n" + << debug_string; } } @@ -2102,10 +2433,10 @@ TEST_F(ParseDescriptorDebugTest, TestMaps) { // Make sure the debug string uses map syntax and does not have the auto // generated entry. - string debug_string = file->DebugString(); - EXPECT_TRUE(debug_string.find("map<") != string::npos); - EXPECT_TRUE(debug_string.find("option map_entry") == string::npos); - EXPECT_TRUE(debug_string.find("MapEntry") == string::npos); + std::string debug_string = file->DebugString(); + EXPECT_TRUE(debug_string.find("map<") != std::string::npos); + EXPECT_TRUE(debug_string.find("option map_entry") == std::string::npos); + EXPECT_TRUE(debug_string.find("MapEntry") == std::string::npos); // Make sure the descriptor debug string is parsable. FileDescriptorProto parsed; @@ -2135,11 +2466,9 @@ TEST_F(ParseDescriptorDebugTest, TestMaps) { // *output_field to the descriptor of the field, and *output_index to -1. // Returns true if the path was valid, false otherwise. A gTest failure is // recorded before returning false. -bool FollowPath(const Message& root, - const int* path_begin, const int* path_end, +bool FollowPath(const Message& root, const int* path_begin, const int* path_end, const Message** output_message, - const FieldDescriptor** output_field, - int* output_index) { + const FieldDescriptor** output_field, int* output_index) { if (path_begin == path_end) { // Path refers to this whole message. *output_message = &root; @@ -2154,8 +2483,8 @@ bool FollowPath(const Message& root, const FieldDescriptor* field = descriptor->FindFieldByNumber(*path_begin); if (field == NULL) { - ADD_FAILURE() << descriptor->name() << " has no field number: " - << *path_begin; + ADD_FAILURE() << descriptor->name() + << " has no field number: " << *path_begin; return false; } @@ -2175,16 +2504,16 @@ bool FollowPath(const Message& root, if (index >= size) { ADD_FAILURE() << descriptor->name() << "." << field->name() - << " has size " << size << ", but path contained index: " - << index; + << " has size " << size + << ", but path contained index: " << index; return false; } if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { // Descend into child message. const Message& child = reflection->GetRepeatedMessage(root, field, index); - return FollowPath(child, path_begin, path_end, - output_message, output_field, output_index); + return FollowPath(child, path_begin, path_end, output_message, + output_field, output_index); } else if (path_begin == path_end) { // Path refers to this element. *output_message = &root; @@ -2199,8 +2528,8 @@ bool FollowPath(const Message& root, } else { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { const Message& child = reflection->GetMessage(root, field); - return FollowPath(child, path_begin, path_end, - output_message, output_field, output_index); + return FollowPath(child, path_begin, path_end, output_message, + output_field, output_index); } else if (path_begin == path_end) { // Path refers to this field. *output_message = &root; @@ -2260,9 +2589,8 @@ class SourceInfoTest : public ParserTest { } virtual void TearDown() { - EXPECT_TRUE(spans_.empty()) - << "Forgot to call HasSpan() for:\n" - << spans_.begin()->second->DebugString(); + EXPECT_TRUE(spans_.empty()) << "Forgot to call HasSpan() for:\n" + << spans_.begin()->second->DebugString(); } // ----------------------------------------------------------------- @@ -2273,8 +2601,8 @@ class SourceInfoTest : public ParserTest { bool HasSpan(char start_marker, char end_marker, const Message& descriptor_proto) { - return HasSpanWithComment( - start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL, NULL); + return HasSpanWithComment(start_marker, end_marker, descriptor_proto, NULL, + -1, NULL, NULL, NULL); } bool HasSpanWithComment(char start_marker, char end_marker, @@ -2282,28 +2610,27 @@ class SourceInfoTest : public ParserTest { const char* expected_leading_comments, const char* expected_trailing_comments, const char* expected_leading_detached_comments) { - return HasSpanWithComment( - start_marker, end_marker, descriptor_proto, NULL, -1, - expected_leading_comments, expected_trailing_comments, - expected_leading_detached_comments); + return HasSpanWithComment(start_marker, end_marker, descriptor_proto, NULL, + -1, expected_leading_comments, + expected_trailing_comments, + expected_leading_detached_comments); } bool HasSpan(char start_marker, char end_marker, - const Message& descriptor_proto, const string& field_name) { + const Message& descriptor_proto, const std::string& field_name) { return HasSpan(start_marker, end_marker, descriptor_proto, field_name, -1); } bool HasSpan(char start_marker, char end_marker, - const Message& descriptor_proto, const string& field_name, + const Message& descriptor_proto, const std::string& field_name, int index) { - return HasSpan(start_marker, end_marker, descriptor_proto, - field_name, index, NULL, NULL, NULL); + return HasSpan(start_marker, end_marker, descriptor_proto, field_name, + index, NULL, NULL, NULL); } bool HasSpan(char start_marker, char end_marker, - const Message& descriptor_proto, - const string& field_name, int index, - const char* expected_leading_comments, + const Message& descriptor_proto, const std::string& field_name, + int index, const char* expected_leading_comments, const char* expected_trailing_comments, const char* expected_leading_detached_comments) { const FieldDescriptor* field = @@ -2314,32 +2641,27 @@ class SourceInfoTest : public ParserTest { return false; } - return HasSpanWithComment( - start_marker, end_marker, descriptor_proto, field, index, - expected_leading_comments, expected_trailing_comments, - expected_leading_detached_comments); + return HasSpanWithComment(start_marker, end_marker, descriptor_proto, field, + index, expected_leading_comments, + expected_trailing_comments, + expected_leading_detached_comments); } bool HasSpan(const Message& descriptor_proto) { - return HasSpanWithComment( - '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL, NULL); + return HasSpanWithComment('\0', '\0', descriptor_proto, NULL, -1, NULL, + NULL, NULL); } - bool HasSpan(const Message& descriptor_proto, const string& field_name) { + bool HasSpan(const Message& descriptor_proto, const std::string& field_name) { return HasSpan('\0', '\0', descriptor_proto, field_name, -1); } - bool HasSpan(const Message& descriptor_proto, const string& field_name, - int index) { - return HasSpan('\0', '\0', descriptor_proto, field_name, index); - } - - bool HasSpanWithComment( - char start_marker, char end_marker, const Message& descriptor_proto, - const FieldDescriptor* field, int index, - const char* expected_leading_comments, - const char* expected_trailing_comments, - const char* expected_leading_detached_comments) { + bool HasSpanWithComment(char start_marker, char end_marker, + const Message& descriptor_proto, + const FieldDescriptor* field, int index, + const char* expected_leading_comments, + const char* expected_trailing_comments, + const char* expected_leading_detached_comments) { std::pair range = spans_.equal_range(SpanKey(descriptor_proto, field, index)); @@ -2403,9 +2725,9 @@ class SourceInfoTest : public ParserTest { inline SpanKey() {} inline SpanKey(const Message& descriptor_proto_param, - const FieldDescriptor* field_param, - int index_param) - : descriptor_proto(&descriptor_proto_param), field(field_param), + const FieldDescriptor* field_param, int index_param) + : descriptor_proto(&descriptor_proto_param), + field(field_param), index(index_param) {} inline bool operator<(const SpanKey& other) const { @@ -2420,7 +2742,7 @@ class SourceInfoTest : public ParserTest { typedef std::multimap SpanMap; SpanMap spans_; std::map > markers_; - string text_without_markers_; + std::string text_without_markers_; void ExtractMarkers(const char* text) { markers_.clear(); @@ -2453,25 +2775,31 @@ class SourceInfoTest : public ParserTest { }; TEST_F(SourceInfoTest, BasicFileDecls) { - EXPECT_TRUE(Parse( - "$a$syntax = \"proto2\";$i$\n" - "package $b$foo.bar$c$;\n" - "import $d$\"baz.proto\"$e$;\n" - "import $f$\"qux.proto\"$g$;$h$\n" - "\n" - "// comment ignored\n")); - - EXPECT_TRUE(HasSpan('a', 'h', file_)); + EXPECT_TRUE( + Parse("$a$syntax = \"proto2\";$i$\n" + "$b$package foo.bar;$c$\n" + "$d$import \"baz.proto\";$e$\n" + "$f$import\"qux.proto\";$h$\n" + "$j$import $k$public$l$ \"bar.proto\";$m$\n" + "$n$import $o$weak$p$ \"bar.proto\";$q$\n" + "\n" + "// comment ignored\n")); + + EXPECT_TRUE(HasSpan('a', 'q', file_)); EXPECT_TRUE(HasSpan('b', 'c', file_, "package")); EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0)); - EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1)); + EXPECT_TRUE(HasSpan('f', 'h', file_, "dependency", 1)); + EXPECT_TRUE(HasSpan('j', 'm', file_, "dependency", 2)); + EXPECT_TRUE(HasSpan('k', 'l', file_, "public_dependency", 0)); + EXPECT_TRUE(HasSpan('n', 'q', file_, "dependency", 3)); + EXPECT_TRUE(HasSpan('o', 'p', file_, "weak_dependency", 0)); EXPECT_TRUE(HasSpan('a', 'i', file_, "syntax")); } TEST_F(SourceInfoTest, Messages) { - EXPECT_TRUE(Parse( - "$a$message $b$Foo$c$ {}$d$\n" - "$e$message $f$Bar$g$ {}$h$\n")); + EXPECT_TRUE( + Parse("$a$message $b$Foo$c$ {}$d$\n" + "$e$message $f$Bar$g$ {}$h$\n")); EXPECT_TRUE(HasSpan('a', 'd', file_.message_type(0))); EXPECT_TRUE(HasSpan('b', 'c', file_.message_type(0), "name")); @@ -2483,11 +2811,11 @@ TEST_F(SourceInfoTest, Messages) { } TEST_F(SourceInfoTest, Fields) { - EXPECT_TRUE(Parse( - "message Foo {\n" - " $a$optional$b$ $c$int32$d$ $e$bar$f$ = $g$1$h$;$i$\n" - " $j$repeated$k$ $l$X.Y$m$ $n$baz$o$ = $p$2$q$;$r$\n" - "}\n")); + EXPECT_TRUE( + Parse("message Foo {\n" + " $a$optional$b$ $c$int32$d$ $e$bar$f$ = $g$1$h$;$i$\n" + " $j$repeated$k$ $l$X.Y$m$ $n$baz$o$ = $p$2$q$;$r$\n" + "}\n")); const FieldDescriptorProto& field1 = file_.message_type(0).field(0); const FieldDescriptorProto& field2 = file_.message_type(0).field(1); @@ -2510,15 +2838,44 @@ TEST_F(SourceInfoTest, Fields) { EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); } +TEST_F(SourceInfoTest, Proto3Fields) { + EXPECT_TRUE( + Parse("syntax = \"proto3\";\n" + "message Foo {\n" + " $a$int32$b$ $c$bar$d$ = $e$1$f$;$g$\n" + " $h$repeated$i$ $j$X.Y$k$ $l$baz$m$ = $n$2$o$;$p$\n" + "}\n")); + + const FieldDescriptorProto& field1 = file_.message_type(0).field(0); + const FieldDescriptorProto& field2 = file_.message_type(0).field(1); + + EXPECT_TRUE(HasSpan('a', 'g', field1)); + EXPECT_TRUE(HasSpan('a', 'b', field1, "type")); + EXPECT_TRUE(HasSpan('c', 'd', field1, "name")); + EXPECT_TRUE(HasSpan('e', 'f', field1, "number")); + + EXPECT_TRUE(HasSpan('h', 'p', field2)); + EXPECT_TRUE(HasSpan('h', 'i', field2, "label")); + EXPECT_TRUE(HasSpan('j', 'k', field2, "type_name")); + EXPECT_TRUE(HasSpan('l', 'm', field2, "name")); + EXPECT_TRUE(HasSpan('n', 'o', field2, "number")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_, "syntax")); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); +} + TEST_F(SourceInfoTest, Extensions) { - EXPECT_TRUE(Parse( - "$a$extend $b$Foo$c$ {\n" - " $d$optional$e$ int32 bar = 1;$f$\n" - " $g$repeated$h$ X.Y baz = 2;$i$\n" - "}$j$\n" - "$k$extend $l$Bar$m$ {\n" - " $n$optional int32 qux = 1;$o$\n" - "}$p$\n")); + EXPECT_TRUE( + Parse("$a$extend $b$Foo$c$ {\n" + " $d$optional$e$ int32 bar = 1;$f$\n" + " $g$repeated$h$ X.Y baz = 2;$i$\n" + "}$j$\n" + "$k$extend $l$Bar$m$ {\n" + " $n$optional int32 qux = 1;$o$\n" + "}$p$\n")); const FieldDescriptorProto& field1 = file_.extension(0); const FieldDescriptorProto& field2 = file_.extension(1); @@ -2553,16 +2910,16 @@ TEST_F(SourceInfoTest, Extensions) { } TEST_F(SourceInfoTest, NestedExtensions) { - EXPECT_TRUE(Parse( - "message Message {\n" - " $a$extend $b$Foo$c$ {\n" - " $d$optional$e$ int32 bar = 1;$f$\n" - " $g$repeated$h$ X.Y baz = 2;$i$\n" - " }$j$\n" - " $k$extend $l$Bar$m$ {\n" - " $n$optional int32 qux = 1;$o$\n" - " }$p$\n" - "}\n")); + EXPECT_TRUE( + Parse("message Message {\n" + " $a$extend $b$Foo$c$ {\n" + " $d$optional$e$ int32 bar = 1;$f$\n" + " $g$repeated$h$ X.Y baz = 2;$i$\n" + " }$j$\n" + " $k$extend $l$Bar$m$ {\n" + " $n$optional int32 qux = 1;$o$\n" + " }$p$\n" + "}\n")); const FieldDescriptorProto& field1 = file_.message_type(0).extension(0); const FieldDescriptorProto& field2 = file_.message_type(0).extension(1); @@ -2599,11 +2956,11 @@ TEST_F(SourceInfoTest, NestedExtensions) { } TEST_F(SourceInfoTest, ExtensionRanges) { - EXPECT_TRUE(Parse( - "message Message {\n" - " $a$extensions $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n" - " $i$extensions $j$8$k$ to $l$max$m$;$n$\n" - "}\n")); + EXPECT_TRUE( + Parse("message Message {\n" + " $a$extensions $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n" + " $i$extensions $j$8$k$ to $l$max$m$;$n$\n" + "}\n")); const DescriptorProto::ExtensionRange& range1 = file_.message_type(0).extension_range(0); @@ -2633,13 +2990,40 @@ TEST_F(SourceInfoTest, ExtensionRanges) { EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); } +TEST_F(SourceInfoTest, ReservedRanges) { + EXPECT_TRUE( + Parse("message Message {\n" + " $a$reserved $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n" + "}\n")); + + const DescriptorProto::ReservedRange& range1 = + file_.message_type(0).reserved_range(0); + const DescriptorProto::ReservedRange& range2 = + file_.message_type(0).reserved_range(1); + + EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "reserved_range")); + + EXPECT_TRUE(HasSpan('b', 'e', range1)); + EXPECT_TRUE(HasSpan('b', 'c', range1, "start")); + EXPECT_TRUE(HasSpan('d', 'e', range1, "end")); + + EXPECT_TRUE(HasSpan('f', 'g', range2)); + EXPECT_TRUE(HasSpan('f', 'g', range2, "start")); + EXPECT_TRUE(HasSpan('f', 'g', range2, "end")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); +} + TEST_F(SourceInfoTest, Oneofs) { - EXPECT_TRUE(Parse( - "message Foo {\n" - " $a$oneof $c$foo$d$ {\n" - " $e$int32$f$ $g$a$h$ = $i$1$j$;$k$\n" - " }$r$\n" - "}\n")); + EXPECT_TRUE( + Parse("message Foo {\n" + " $a$oneof $c$foo$d$ {\n" + " $e$int32$f$ $g$a$h$ = $i$1$j$;$k$\n" + " }$r$\n" + "}\n")); const OneofDescriptorProto& oneof_decl = file_.message_type(0).oneof_decl(0); const FieldDescriptorProto& field = file_.message_type(0).field(0); @@ -2659,13 +3043,13 @@ TEST_F(SourceInfoTest, Oneofs) { } TEST_F(SourceInfoTest, NestedMessages) { - EXPECT_TRUE(Parse( - "message Foo {\n" - " $a$message $b$Bar$c$ {\n" - " $d$message $e$Baz$f$ {}$g$\n" - " }$h$\n" - " $i$message $j$Qux$k$ {}$l$\n" - "}\n")); + EXPECT_TRUE( + Parse("message Foo {\n" + " $a$message $b$Bar$c$ {\n" + " $d$message $e$Baz$f$ {}$g$\n" + " }$h$\n" + " $i$message $j$Qux$k$ {}$l$\n" + "}\n")); const DescriptorProto& bar = file_.message_type(0).nested_type(0); const DescriptorProto& baz = bar.nested_type(0); @@ -2685,13 +3069,13 @@ TEST_F(SourceInfoTest, NestedMessages) { } TEST_F(SourceInfoTest, Groups) { - EXPECT_TRUE(Parse( - "message Foo {\n" - " message Bar {}\n" - " $a$optional$b$ $c$group$d$ $e$Baz$f$ = $g$1$h$ {\n" - " $i$message Qux {}$j$\n" - " }$k$\n" - "}\n")); + EXPECT_TRUE( + Parse("message Foo {\n" + " message Bar {}\n" + " $a$optional$b$ $c$group$d$ $e$Baz$f$ = $g$1$h$ {\n" + " $i$message Qux {}$j$\n" + " }$k$\n" + "}\n")); const DescriptorProto& bar = file_.message_type(0).nested_type(0); const DescriptorProto& baz = file_.message_type(0).nested_type(1); @@ -2719,9 +3103,9 @@ TEST_F(SourceInfoTest, Groups) { } TEST_F(SourceInfoTest, Enums) { - EXPECT_TRUE(Parse( - "$a$enum $b$Foo$c$ {}$d$\n" - "$e$enum $f$Bar$g$ {}$h$\n")); + EXPECT_TRUE( + Parse("$a$enum $b$Foo$c$ {}$d$\n" + "$e$enum $f$Bar$g$ {}$h$\n")); EXPECT_TRUE(HasSpan('a', 'd', file_.enum_type(0))); EXPECT_TRUE(HasSpan('b', 'c', file_.enum_type(0), "name")); @@ -2733,11 +3117,11 @@ TEST_F(SourceInfoTest, Enums) { } TEST_F(SourceInfoTest, EnumValues) { - EXPECT_TRUE(Parse( - "enum Foo {\n" - " $a$BAR$b$ = $c$1$d$;$e$\n" - " $f$BAZ$g$ = $h$2$i$;$j$\n" - "}")); + EXPECT_TRUE( + Parse("enum Foo {\n" + " $a$BAR$b$ = $c$1$d$;$e$\n" + " $f$BAZ$g$ = $h$2$i$;$j$\n" + "}")); const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0); const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1); @@ -2756,11 +3140,11 @@ TEST_F(SourceInfoTest, EnumValues) { } TEST_F(SourceInfoTest, NestedEnums) { - EXPECT_TRUE(Parse( - "message Foo {\n" - " $a$enum $b$Bar$c$ {}$d$\n" - " $e$enum $f$Baz$g$ {}$h$\n" - "}\n")); + EXPECT_TRUE( + Parse("message Foo {\n" + " $a$enum $b$Bar$c$ {}$d$\n" + " $e$enum $f$Baz$g$ {}$h$\n" + "}\n")); const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0); const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1); @@ -2777,9 +3161,9 @@ TEST_F(SourceInfoTest, NestedEnums) { } TEST_F(SourceInfoTest, Services) { - EXPECT_TRUE(Parse( - "$a$service $b$Foo$c$ {}$d$\n" - "$e$service $f$Bar$g$ {}$h$\n")); + EXPECT_TRUE( + Parse("$a$service $b$Foo$c$ {}$d$\n" + "$e$service $f$Bar$g$ {}$h$\n")); EXPECT_TRUE(HasSpan('a', 'd', file_.service(0))); EXPECT_TRUE(HasSpan('b', 'c', file_.service(0), "name")); @@ -2791,11 +3175,11 @@ TEST_F(SourceInfoTest, Services) { } TEST_F(SourceInfoTest, MethodsAndStreams) { - EXPECT_TRUE(Parse( - "service Foo {\n" - " $a$rpc $b$Bar$c$($d$X$e$) returns($f$Y$g$);$h$" - " $i$rpc $j$Baz$k$($l$Z$m$) returns($n$W$o$);$p$" - "}")); + EXPECT_TRUE( + Parse("service Foo {\n" + " $a$rpc $b$Bar$c$($d$X$e$) returns($f$Y$g$);$h$" + " $i$rpc $j$Baz$k$($l$Z$m$) returns($n$W$o$);$p$" + "}")); const MethodDescriptorProto& bar = file_.service(0).method(0); const MethodDescriptorProto& baz = file_.service(0).method(1); @@ -2818,15 +3202,14 @@ TEST_F(SourceInfoTest, MethodsAndStreams) { TEST_F(SourceInfoTest, Options) { - EXPECT_TRUE(Parse( - "$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = " - "$h$123$i$;$j$\n" - "$k$option qux = $l$-123$m$;$n$\n" - "$o$option corge = $p$abc$q$;$r$\n" - "$s$option grault = $t$'blah'$u$;$v$\n" - "$w$option garply = $x${ yadda yadda }$y$;$z$\n" - "$0$option waldo = $1$123.0$2$;$3$\n" - )); + EXPECT_TRUE( + Parse("$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = " + "$h$123$i$;$j$\n" + "$k$option qux = $l$-123$m$;$n$\n" + "$o$option corge = $p$abc$q$;$r$\n" + "$s$option grault = $t$'blah'$u$;$v$\n" + "$w$option garply = $x${ yadda yadda }$y$;$z$\n" + "$0$option waldo = $1$123.0$2$;$3$\n")); const UninterpretedOption& option1 = file_.options().uninterpreted_option(0); const UninterpretedOption& option2 = file_.options().uninterpreted_option(1); @@ -2884,22 +3267,22 @@ TEST_F(SourceInfoTest, Options) { } TEST_F(SourceInfoTest, ScopedOptions) { - EXPECT_TRUE(Parse( - "message Foo {\n" - " $a$option mopt = 1;$b$\n" - "}\n" - "enum Bar {\n" - " $c$option eopt = 1;$d$\n" - "}\n" - "service Baz {\n" - " $e$option sopt = 1;$f$\n" - " rpc M(X) returns(Y) {\n" - " $g$option mopt = 1;$h$\n" - " }\n" - " rpc MS4($1$stream$2$ X) returns($3$stream$4$ Y) {\n" - " $k$option mopt = 1;$l$\n" - " }\n" - "}\n")); + EXPECT_TRUE( + Parse("message Foo {\n" + " $a$option mopt = 1;$b$\n" + "}\n" + "enum Bar {\n" + " $c$option eopt = 1;$d$\n" + "}\n" + "service Baz {\n" + " $e$option sopt = 1;$f$\n" + " rpc M(X) returns(Y) {\n" + " $g$option mopt = 1;$h$\n" + " }\n" + " rpc MS4($1$stream$2$ X) returns($3$stream$4$ Y) {\n" + " $k$option mopt = 1;$l$\n" + " }\n" + "}\n")); EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options())); EXPECT_TRUE(HasSpan('c', 'd', file_.enum_type(0).options())); @@ -2910,87 +3293,89 @@ TEST_F(SourceInfoTest, ScopedOptions) { EXPECT_TRUE(HasSpan(file_)); EXPECT_TRUE(HasSpan(file_.message_type(0))); EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); - EXPECT_TRUE(HasSpan(file_.message_type(0).options() - .uninterpreted_option(0))); - EXPECT_TRUE(HasSpan(file_.message_type(0).options() - .uninterpreted_option(0), "name")); - EXPECT_TRUE(HasSpan(file_.message_type(0).options() - .uninterpreted_option(0).name(0))); - EXPECT_TRUE(HasSpan(file_.message_type(0).options() - .uninterpreted_option(0).name(0), "name_part")); - EXPECT_TRUE(HasSpan(file_.message_type(0).options() - .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE(HasSpan(file_.message_type(0).options().uninterpreted_option(0))); + EXPECT_TRUE( + HasSpan(file_.message_type(0).options().uninterpreted_option(0), "name")); + EXPECT_TRUE( + HasSpan(file_.message_type(0).options().uninterpreted_option(0).name(0))); + EXPECT_TRUE( + HasSpan(file_.message_type(0).options().uninterpreted_option(0).name(0), + "name_part")); + EXPECT_TRUE(HasSpan(file_.message_type(0).options().uninterpreted_option(0), + "positive_int_value")); EXPECT_TRUE(HasSpan(file_.enum_type(0))); EXPECT_TRUE(HasSpan(file_.enum_type(0), "name")); - EXPECT_TRUE(HasSpan(file_.enum_type(0).options() - .uninterpreted_option(0))); - EXPECT_TRUE(HasSpan(file_.enum_type(0).options() - .uninterpreted_option(0), "name")); - EXPECT_TRUE(HasSpan(file_.enum_type(0).options() - .uninterpreted_option(0).name(0))); - EXPECT_TRUE(HasSpan(file_.enum_type(0).options() - .uninterpreted_option(0).name(0), "name_part")); - EXPECT_TRUE(HasSpan(file_.enum_type(0).options() - .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options().uninterpreted_option(0))); + EXPECT_TRUE( + HasSpan(file_.enum_type(0).options().uninterpreted_option(0), "name")); + EXPECT_TRUE( + HasSpan(file_.enum_type(0).options().uninterpreted_option(0).name(0))); + EXPECT_TRUE( + HasSpan(file_.enum_type(0).options().uninterpreted_option(0).name(0), + "name_part")); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options().uninterpreted_option(0), + "positive_int_value")); EXPECT_TRUE(HasSpan(file_.service(0))); EXPECT_TRUE(HasSpan(file_.service(0), "name")); EXPECT_TRUE(HasSpan(file_.service(0).method(0))); - EXPECT_TRUE(HasSpan(file_.service(0).options() - .uninterpreted_option(0))); - EXPECT_TRUE(HasSpan(file_.service(0).options() - .uninterpreted_option(0), "name")); - EXPECT_TRUE(HasSpan(file_.service(0).options() - .uninterpreted_option(0).name(0))); - EXPECT_TRUE(HasSpan(file_.service(0).options() - .uninterpreted_option(0).name(0), "name_part")); - EXPECT_TRUE(HasSpan(file_.service(0).options() - .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE(HasSpan(file_.service(0).options().uninterpreted_option(0))); + EXPECT_TRUE( + HasSpan(file_.service(0).options().uninterpreted_option(0), "name")); + EXPECT_TRUE( + HasSpan(file_.service(0).options().uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan( + file_.service(0).options().uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.service(0).options().uninterpreted_option(0), + "positive_int_value")); EXPECT_TRUE(HasSpan(file_.service(0).method(0), "name")); EXPECT_TRUE(HasSpan(file_.service(0).method(0), "input_type")); EXPECT_TRUE(HasSpan(file_.service(0).method(0), "output_type")); - EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() - .uninterpreted_option(0))); - EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() - .uninterpreted_option(0), "name")); - EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() - .uninterpreted_option(0).name(0))); - EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() - .uninterpreted_option(0).name(0), "name_part")); - EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() - .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE( + HasSpan(file_.service(0).method(0).options().uninterpreted_option(0))); + EXPECT_TRUE(HasSpan( + file_.service(0).method(0).options().uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan( + file_.service(0).method(0).options().uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan( + file_.service(0).method(0).options().uninterpreted_option(0).name(0), + "name_part")); + EXPECT_TRUE( + HasSpan(file_.service(0).method(0).options().uninterpreted_option(0), + "positive_int_value")); EXPECT_TRUE(HasSpan('k', 'l', file_.service(0).method(1).options())); EXPECT_TRUE(HasSpan(file_.service(0).method(1))); EXPECT_TRUE(HasSpan(file_.service(0).method(1), "name")); EXPECT_TRUE(HasSpan(file_.service(0).method(1), "input_type")); EXPECT_TRUE(HasSpan(file_.service(0).method(1), "output_type")); - EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() - .uninterpreted_option(0))); - EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() - .uninterpreted_option(0), "name")); - EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() - .uninterpreted_option(0).name(0))); - EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() - .uninterpreted_option(0).name(0), "name_part")); - EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() - .uninterpreted_option(0), "positive_int_value")); - EXPECT_TRUE(HasSpan('1', '2', file_.service(0).method(1), - "client_streaming")); - EXPECT_TRUE(HasSpan('3', '4', file_.service(0).method(1), - "server_streaming")); + EXPECT_TRUE( + HasSpan(file_.service(0).method(1).options().uninterpreted_option(0))); + EXPECT_TRUE(HasSpan( + file_.service(0).method(1).options().uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan( + file_.service(0).method(1).options().uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan( + file_.service(0).method(1).options().uninterpreted_option(0).name(0), + "name_part")); + EXPECT_TRUE( + HasSpan(file_.service(0).method(1).options().uninterpreted_option(0), + "positive_int_value")); + EXPECT_TRUE( + HasSpan('1', '2', file_.service(0).method(1), "client_streaming")); + EXPECT_TRUE( + HasSpan('3', '4', file_.service(0).method(1), "server_streaming")); } TEST_F(SourceInfoTest, FieldOptions) { // The actual "name = value" pairs are parsed by the same code as for // top-level options so we won't re-test that -- just make sure that the // syntax used for field options is understood. - EXPECT_TRUE(Parse( - "message Foo {" - " optional int32 bar = 1 " - "$a$[default=$b$123$c$,$d$opt1=123$e$," - "$f$opt2='hi'$g$]$h$;" - "}\n" - )); + EXPECT_TRUE( + Parse("message Foo {" + " optional int32 bar = 1 " + "$a$[default=$b$123$c$,$d$opt1=123$e$," + "$f$opt2='hi'$g$]$h$;" + "}\n")); const FieldDescriptorProto& field = file_.message_type(0).field(0); const UninterpretedOption& option1 = field.options().uninterpreted_option(0); @@ -3024,11 +3409,10 @@ TEST_F(SourceInfoTest, EnumValueOptions) { // The actual "name = value" pairs are parsed by the same code as for // top-level options so we won't re-test that -- just make sure that the // syntax used for enum options is understood. - EXPECT_TRUE(Parse( - "enum Foo {" - " BAR = 1 $a$[$b$opt1=123$c$,$d$opt2='hi'$e$]$f$;" - "}\n" - )); + EXPECT_TRUE( + Parse("enum Foo {" + " BAR = 1 $a$[$b$opt1=123$c$,$d$opt2='hi'$e$]$f$;" + "}\n")); const EnumValueDescriptorProto& value = file_.enum_type(0).value(0); const UninterpretedOption& option1 = value.options().uninterpreted_option(0); @@ -3056,33 +3440,28 @@ TEST_F(SourceInfoTest, EnumValueOptions) { } TEST_F(SourceInfoTest, DocComments) { - EXPECT_TRUE(Parse( - "// Foo leading\n" - "// line 2\n" - "$a$message Foo {\n" - " // Foo trailing\n" - " // line 2\n" - "\n" - " // detached\n" - "\n" - " // bar leading\n" - " $b$optional int32 bar = 1;$c$\n" - " // bar trailing\n" - "}$d$\n" - "// ignored\n" - )); + EXPECT_TRUE( + Parse("// Foo leading\n" + "// line 2\n" + "$a$message Foo {\n" + " // Foo trailing\n" + " // line 2\n" + "\n" + " // detached\n" + "\n" + " // bar leading\n" + " $b$optional int32 bar = 1;$c$\n" + " // bar trailing\n" + "}$d$\n" + "// ignored\n")); const DescriptorProto& foo = file_.message_type(0); const FieldDescriptorProto& bar = foo.field(0); - EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, - " Foo leading\n line 2\n", - " Foo trailing\n line 2\n", - NULL)); - EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, - " bar leading\n", - " bar trailing\n", - " detached\n")); + EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, " Foo leading\n line 2\n", + " Foo trailing\n line 2\n", NULL)); + EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n", + " bar trailing\n", " detached\n")); // Ignore these. EXPECT_TRUE(HasSpan(file_)); @@ -3094,45 +3473,40 @@ TEST_F(SourceInfoTest, DocComments) { } TEST_F(SourceInfoTest, DocComments2) { - EXPECT_TRUE(Parse( - "// detached before message.\n" - "\n" - "// Foo leading\n" - "// line 2\n" - "$a$message Foo {\n" - " /* Foo trailing\n" - " * line 2 */\n" - " // detached\n" - " /* bar leading\n" - " */" - " $b$optional int32 bar = 1;$c$ // bar trailing\n" - " // ignored detached\n" - "}$d$\n" - "// ignored\n" - "\n" - "// detached before option\n" - "\n" - "// option leading\n" - "$e$option baz = 123;$f$\n" - "// option trailing\n" - )); + EXPECT_TRUE( + Parse("// detached before message.\n" + "\n" + "// Foo leading\n" + "// line 2\n" + "$a$message Foo {\n" + " /* Foo trailing\n" + " * line 2 */\n" + " // detached\n" + " /* bar leading\n" + " */" + " $b$optional int32 bar = 1;$c$ // bar trailing\n" + " // ignored detached\n" + "}$d$\n" + "// ignored\n" + "\n" + "// detached before option\n" + "\n" + "// option leading\n" + "$e$option baz = 123;$f$\n" + "// option trailing\n")); const DescriptorProto& foo = file_.message_type(0); const FieldDescriptorProto& bar = foo.field(0); const UninterpretedOption& baz = file_.options().uninterpreted_option(0); - EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, - " Foo leading\n line 2\n", - " Foo trailing\n line 2 ", - " detached before message.\n")); - EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, - " bar leading\n", - " bar trailing\n", - " detached\n")); - EXPECT_TRUE(HasSpanWithComment('e', 'f', baz, - " option leading\n", - " option trailing\n", - " detached before option\n")); + EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, " Foo leading\n line 2\n", + " Foo trailing\n line 2 ", + " detached before message.\n")); + EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n", + " bar trailing\n", " detached\n")); + EXPECT_TRUE(HasSpanWithComment('e', 'f', baz, " option leading\n", + " option trailing\n", + " detached before option\n")); // Ignore these. EXPECT_TRUE(HasSpan(file_)); @@ -3149,22 +3523,19 @@ TEST_F(SourceInfoTest, DocComments2) { } TEST_F(SourceInfoTest, DocComments3) { - EXPECT_TRUE(Parse( - "$a$message Foo {\n" - " // bar leading\n" - " $b$optional int32 bar = 1 [(baz.qux) = {}];$c$\n" - " // bar trailing\n" - "}$d$\n" - "// ignored\n" - )); + EXPECT_TRUE( + Parse("$a$message Foo {\n" + " // bar leading\n" + " $b$optional int32 bar = 1 [(baz.qux) = {}];$c$\n" + " // bar trailing\n" + "}$d$\n" + "// ignored\n")); const DescriptorProto& foo = file_.message_type(0); const FieldDescriptorProto& bar = foo.field(0); - EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, - " bar leading\n", - " bar trailing\n", - NULL)); + EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n", + " bar trailing\n", NULL)); // Ignore these. EXPECT_TRUE(HasSpan(file_)); @@ -3178,88 +3549,82 @@ TEST_F(SourceInfoTest, DocComments3) { EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0))); EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0), "name")); EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0).name(0))); - EXPECT_TRUE(HasSpan( - bar.options().uninterpreted_option(0).name(0), "name_part")); - EXPECT_TRUE(HasSpan( - bar.options().uninterpreted_option(0), "aggregate_value")); + EXPECT_TRUE( + HasSpan(bar.options().uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE( + HasSpan(bar.options().uninterpreted_option(0), "aggregate_value")); } TEST_F(SourceInfoTest, DocCommentsTopLevel) { - EXPECT_TRUE(Parse( - "// detached before syntax paragraph 1\n" - "\n" - "// detached before syntax paragraph 2\n" - "\n" - "// syntax leading\n" - "$a$syntax = \"proto2\";$b$\n" - "// syntax trailing\n" - "\n" - "// syntax-package detached comments\n" - "\n" - ";\n" - "\n" - "// detached after empty before package\n" - "\n" - "// package leading\n" - "package $c$foo$d$;\n" - "// package trailing\n" - "\n" - "// ignored detach\n" - "\n")); - - EXPECT_TRUE(HasSpan('a', 'b', file_, "syntax", -1, - " syntax leading\n", - " syntax trailing\n", - " detached before syntax paragraph 1\n" - "\n" - " detached before syntax paragraph 2\n")); - EXPECT_TRUE(HasSpan('c', 'd', file_, "package", -1, - " package leading\n", - " package trailing\n", - " syntax-package detached comments\n" - "\n" - " detached after empty before package\n")); + EXPECT_TRUE( + Parse("// detached before syntax paragraph 1\n" + "\n" + "// detached before syntax paragraph 2\n" + "\n" + "// syntax leading\n" + "$a$syntax = \"proto2\";$b$\n" + "// syntax trailing\n" + "\n" + "// syntax-package detached comments\n" + "\n" + ";\n" + "\n" + "// detached after empty before package\n" + "\n" + "// package leading\n" + "$c$package foo;$d$\n" + "// package trailing\n" + "\n" + "// ignored detach\n" + "\n")); + + EXPECT_TRUE(HasSpan('a', 'b', file_, "syntax", -1, " syntax leading\n", + " syntax trailing\n", + " detached before syntax paragraph 1\n" + "\n" + " detached before syntax paragraph 2\n")); + EXPECT_TRUE(HasSpan('c', 'd', file_, "package", -1, " package leading\n", + " package trailing\n", + " syntax-package detached comments\n" + "\n" + " detached after empty before package\n")); // ignore these. EXPECT_TRUE(HasSpan(file_)); } TEST_F(SourceInfoTest, DocCommentsOneof) { - EXPECT_TRUE(Parse( - "// Foo leading\n" - "$a$message Foo {\n" - " /* Foo trailing\n" - " */\n" - " // detached before oneof\n" - " /* bar leading\n" - " * line 2 */\n" - " $b$oneof bar {\n" - " /* bar trailing\n" - " * line 2 */\n" - " // detached before bar_int\n" - " /* bar_int leading\n" - " */\n" - " $c$int32 bar_int = 1;$d$ // bar_int trailing\n" - " // detach comment ignored\n" - " }$e$\n" - "}$f$\n")); + EXPECT_TRUE( + Parse("// Foo leading\n" + "$a$message Foo {\n" + " /* Foo trailing\n" + " */\n" + " // detached before oneof\n" + " /* bar leading\n" + " * line 2 */\n" + " $b$oneof bar {\n" + " /* bar trailing\n" + " * line 2 */\n" + " // detached before bar_int\n" + " /* bar_int leading\n" + " */\n" + " $c$int32 bar_int = 1;$d$ // bar_int trailing\n" + " // detach comment ignored\n" + " }$e$\n" + "}$f$\n")); const DescriptorProto& foo = file_.message_type(0); const OneofDescriptorProto& bar = foo.oneof_decl(0); const FieldDescriptorProto& bar_int = foo.field(0); - EXPECT_TRUE(HasSpanWithComment('a', 'f', foo, - " Foo leading\n", - " Foo trailing\n", - NULL)); - EXPECT_TRUE(HasSpanWithComment('b', 'e', bar, - " bar leading\n line 2 ", - " bar trailing\n line 2 ", - " detached before oneof\n")); - EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int, - " bar_int leading\n", - " bar_int trailing\n", - " detached before bar_int\n")); + EXPECT_TRUE(HasSpanWithComment('a', 'f', foo, " Foo leading\n", + " Foo trailing\n", NULL)); + EXPECT_TRUE(HasSpanWithComment('b', 'e', bar, " bar leading\n line 2 ", + " bar trailing\n line 2 ", + " detached before oneof\n")); + EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int, " bar_int leading\n", + " bar_int trailing\n", + " detached before bar_int\n")); // Ignore these. EXPECT_TRUE(HasSpan(file_)); diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc index 60e6fce99d093..203b49f918f4d 100644 --- a/src/google/protobuf/compiler/php/php_generator.cc +++ b/src/google/protobuf/compiler/php/php_generator.cc @@ -40,8 +40,6 @@ #include -using google::protobuf::internal::scoped_ptr; - const std::string kDescriptorFile = "google/protobuf/descriptor.proto"; const std::string kEmptyFile = "google/protobuf/empty.proto"; const std::string kEmptyMetadataFile = "GPBMetadata/Google/Protobuf/GPBEmpty.php"; @@ -49,8 +47,28 @@ const std::string kDescriptorMetadataFile = "GPBMetadata/Google/Protobuf/Internal/Descriptor.php"; const std::string kDescriptorDirName = "Google/Protobuf/Internal"; const std::string kDescriptorPackageName = "Google\\Protobuf\\Internal"; -const char* const kReservedNames[] = {"ARRAY", "Empty", "ECHO"}; -const int kReservedNamesSize = 3; +const char* const kReservedNames[] = { + "abstract", "and", "array", "as", "break", + "callable", "case", "catch", "class", "clone", + "const", "continue", "declare", "default", "die", + "do", "echo", "else", "elseif", "empty", + "enddeclare", "endfor", "endforeach", "endif", "endswitch", + "endwhile", "eval", "exit", "extends", "final", + "for", "foreach", "function", "global", "goto", + "if", "implements", "include", "include_once", "instanceof", + "insteadof", "interface", "isset", "list", "namespace", + "new", "or", "print", "private", "protected", + "public", "require", "require_once", "return", "static", + "switch", "throw", "trait", "try", "unset", + "use", "var", "while", "xor", "int", + "float", "bool", "string", "true", "false", + "null", "void", "iterable"}; +const char* const kValidConstantNames[] = { + "int", "float", "bool", "string", "true", + "false", "null", "void", "iterable", +}; +const int kReservedNamesSize = 73; +const int kValidConstantNamesSize = 9; const int kFieldSetter = 1; const int kFieldGetter = 2; const int kFieldProperty = 3; @@ -60,26 +78,40 @@ namespace protobuf { namespace compiler { namespace php { +struct Options { + bool is_descriptor = false; + bool aggregate_metadata = false; + bool gen_c_wkt = false; + std::set aggregate_metadata_prefixes; +}; + +namespace { + // Forward decls. -std::string PhpName(const std::string& full_name, bool is_descriptor); -std::string DefaultForField(FieldDescriptor* field); +std::string PhpName(const std::string& full_name, const Options& options); std::string IntToString(int32 value); -std::string FilenameToClassname(const string& filename); -std::string GeneratedMetadataFileName(const std::string& proto_file, - bool is_descriptor); -std::string LabelForField(FieldDescriptor* field); -std::string TypeName(FieldDescriptor* field); -std::string UnderscoresToCamelCase(const string& name, bool cap_first_letter); -std::string EscapeDollor(const string& to_escape); -std::string BinaryToHex(const string& binary); +std::string FilenameToClassname(const std::string& filename); +std::string GeneratedMetadataFileName(const FileDescriptor* file, + const Options& options); +std::string UnderscoresToCamelCase(const std::string& name, + bool cap_first_letter); void Indent(io::Printer* printer); void Outdent(io::Printer* printer); +void GenerateAddFilesToPool(const FileDescriptor* file, const Options& options, + io::Printer* printer); void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message, - int is_descriptor); + const Options& options); +void GenerateMessageConstructorDocComment(io::Printer* printer, + const Descriptor* message, + const Options& options); void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field, - int is_descriptor, int function_type); + const Options& options, int function_type); +void GenerateWrapperFieldGetterDocComment(io::Printer* printer, + const FieldDescriptor* field); +void GenerateWrapperFieldSetterDocComment(io::Printer* printer, + const FieldDescriptor* field); void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_, - int is_descriptor); + const Options& options); void GenerateEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value); void GenerateServiceDocComment(io::Printer* printer, @@ -87,119 +119,188 @@ void GenerateServiceDocComment(io::Printer* printer, void GenerateServiceMethodDocComment(io::Printer* printer, const MethodDescriptor* method); -std::string RenameEmpty(const std::string& name) { - if (name == "Empty") { - return "GPBEmpty"; - } else { - return name; +std::string ReservedNamePrefix(const std::string& classname, + const FileDescriptor* file) { + bool is_reserved = false; + + std::string lower = classname; + std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + + for (int i = 0; i < kReservedNamesSize; i++) { + if (lower == kReservedNames[i]) { + is_reserved = true; + break; + } } -} -std::string MessageFullName(const Descriptor* message, bool is_descriptor) { - if (is_descriptor) { - return StringReplace(message->full_name(), - "google.protobuf", - "google.protobuf.internal", false); - } else { - return message->full_name(); + if (is_reserved) { + if (file->package() == "google.protobuf") { + return "GPB"; + } else { + return "PB"; + } } + + return ""; } -std::string EnumFullName(const EnumDescriptor* envm, bool is_descriptor) { - if (is_descriptor) { - return StringReplace(envm->full_name(), +template +std::string DescriptorFullName(const DescriptorType* desc, bool is_internal) { + if (is_internal) { + return StringReplace(desc->full_name(), "google.protobuf", "google.protobuf.internal", false); } else { - return envm->full_name(); + return desc->full_name(); } } template -std::string ClassNamePrefix(const string& classname, +std::string ClassNamePrefix(const std::string& classname, const DescriptorType* desc) { - const string& prefix = (desc->file()->options()).php_class_prefix(); - if (prefix != "") { + const std::string& prefix = (desc->file()->options()).php_class_prefix(); + if (!prefix.empty()) { return prefix; } + return ReservedNamePrefix(classname, desc->file()); +} + +template +std::string GeneratedClassNameImpl(const DescriptorType* desc) { + std::string classname = ClassNamePrefix(desc->name(), desc) + desc->name(); + const Descriptor* containing = desc->containing_type(); + while (containing != NULL) { + classname = ClassNamePrefix(containing->name(), desc) + containing->name() + + '\\' + classname; + containing = containing->containing_type(); + } + return classname; +} + +std::string GeneratedClassNameImpl(const ServiceDescriptor* desc) { + std::string classname = desc->name(); + return ClassNamePrefix(classname, desc) + classname; +} + +template +std::string LegacyGeneratedClassName(const DescriptorType* desc) { + std::string classname = desc->name(); + const Descriptor* containing = desc->containing_type(); + while (containing != NULL) { + classname = containing->name() + '_' + classname; + containing = containing->containing_type(); + } + return ClassNamePrefix(classname, desc) + classname; +} + +std::string ClassNamePrefix(const std::string& classname) { + std::string lower = classname; + std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + + for (int i = 0; i < kReservedNamesSize; i++) { + if (lower == kReservedNames[i]) { + return "PB"; + } + } + + return ""; +} + +std::string ConstantNamePrefix(const std::string& classname) { bool is_reserved = false; + std::string lower = classname; + std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + for (int i = 0; i < kReservedNamesSize; i++) { - if (classname == kReservedNames[i]) { + if (lower == kReservedNames[i]) { is_reserved = true; break; } } - if (is_reserved) { - if (desc->file()->package() == "google.protobuf") { - return "GPB"; - } else { - return "PB"; + for (int i = 0; i < kValidConstantNamesSize; i++) { + if (lower == kValidConstantNames[i]) { + is_reserved = false; + break; } } + if (is_reserved) { + return "PB"; + } + return ""; } template -std::string NamespacedName(const string& classname, - const DescriptorType* desc, bool is_descriptor) { +std::string RootPhpNamespace(const DescriptorType* desc, + const Options& options) { if (desc->file()->options().has_php_namespace()) { - const string& php_namespace = desc->file()->options().php_namespace(); - if (php_namespace != "") { - return php_namespace + '\\' + classname; - } else { - return classname; + const std::string& php_namespace = desc->file()->options().php_namespace(); + if (!php_namespace.empty()) { + return php_namespace; } + return ""; } - if (desc->file()->package() == "") { - return classname; - } else { - return PhpName(desc->file()->package(), is_descriptor) + '\\' + - classname; + if (!desc->file()->package().empty()) { + return PhpName(desc->file()->package(), options); } + return ""; } template -std::string FullClassName(const DescriptorType* desc, bool is_descriptor) { - string classname = desc->name(); - const Descriptor* containing = desc->containing_type(); - while (containing != NULL) { - classname = containing->name() + '_' + classname; - containing = containing->containing_type(); +std::string FullClassName(const DescriptorType* desc, const Options& options) { + std::string classname = GeneratedClassNameImpl(desc); + std::string php_namespace = RootPhpNamespace(desc, options); + if (!php_namespace.empty()) { + return php_namespace + "\\" + classname; } - classname = ClassNamePrefix(classname, desc) + classname; - return NamespacedName(classname, desc, is_descriptor); + return classname; } -std::string FullClassName(const ServiceDescriptor* desc, bool is_descriptor) { - string classname = desc->name(); - classname = ClassNamePrefix(classname, desc) + classname; - return NamespacedName(classname, desc, is_descriptor); +template +std::string FullClassName(const DescriptorType* desc, bool is_descriptor) { + Options options; + options.is_descriptor = is_descriptor; + return FullClassName(desc, options); +} + +template +std::string LegacyFullClassName(const DescriptorType* desc, + const Options& options) { + std::string classname = LegacyGeneratedClassName(desc); + std::string php_namespace = RootPhpNamespace(desc, options); + if (!php_namespace.empty()) { + return php_namespace + "\\" + classname; + } + return classname; } -std::string PhpName(const std::string& full_name, bool is_descriptor) { - if (is_descriptor) { +std::string PhpName(const std::string& full_name, const Options& options) { + if (options.is_descriptor) { return kDescriptorPackageName; } + std::string segment; std::string result; bool cap_next_letter = true; for (int i = 0; i < full_name.size(); i++) { if ('a' <= full_name[i] && full_name[i] <= 'z' && cap_next_letter) { - result += full_name[i] + ('A' - 'a'); + segment += full_name[i] + ('A' - 'a'); cap_next_letter = false; } else if (full_name[i] == '.') { - result += '\\'; + result += ClassNamePrefix(segment) + segment + '\\'; + segment = ""; cap_next_letter = true; } else { - result += full_name[i]; + segment += full_name[i]; cap_next_letter = false; } } + result += ClassNamePrefix(segment) + segment; return result; } @@ -227,16 +328,18 @@ std::string DefaultForField(const FieldDescriptor* field) { } } -std::string GeneratedMetadataFileName(const std::string& proto_file, - bool is_descriptor) { +std::string GeneratedMetadataFileName(const FileDescriptor* file, + const Options& options) { + const std::string& proto_file = file->name(); int start_index = 0; int first_index = proto_file.find_first_of("/", start_index); - std::string result = "GPBMetadata/"; + std::string result = ""; + std::string segment = ""; if (proto_file == kEmptyFile) { return kEmptyMetadataFile; } - if (is_descriptor) { + if (options.is_descriptor) { return kDescriptorMetadataFile; } @@ -249,24 +352,51 @@ std::string GeneratedMetadataFileName(const std::string& proto_file, file_no_suffix = proto_file.substr(0, lastindex); } - while (first_index != string::npos) { - result += UnderscoresToCamelCase( - file_no_suffix.substr(start_index, first_index - start_index), true); - result += "/"; - start_index = first_index + 1; - first_index = file_no_suffix.find_first_of("/", start_index); + if (file->options().has_php_metadata_namespace()) { + const std::string& php_metadata_namespace = + file->options().php_metadata_namespace(); + if (!php_metadata_namespace.empty() && php_metadata_namespace != "\\") { + result += php_metadata_namespace; + std::replace(result.begin(), result.end(), '\\', '/'); + if (result.at(result.size() - 1) != '/') { + result += "/"; + } + } + } else { + result += "GPBMetadata/"; + while (first_index != std::string::npos) { + segment = UnderscoresToCamelCase( + file_no_suffix.substr(start_index, first_index - start_index), true); + result += ReservedNamePrefix(segment, file) + segment + "/"; + start_index = first_index + 1; + first_index = file_no_suffix.find_first_of("/", start_index); + } } // Append file name. - result += RenameEmpty(UnderscoresToCamelCase( - file_no_suffix.substr(start_index, first_index - start_index), true)); + int file_name_start = file_no_suffix.find_last_of("/"); + if (file_name_start == std::string::npos) { + file_name_start = 0; + } else { + file_name_start += 1; + } + segment = UnderscoresToCamelCase( + file_no_suffix.substr(file_name_start, first_index - file_name_start), true); - return result += ".php"; + return result + ReservedNamePrefix(segment, file) + segment + ".php"; } -std::string GeneratedMessageFileName(const Descriptor* message, - bool is_descriptor) { - std::string result = FullClassName(message, is_descriptor); +std::string GeneratedMetadataFileName(const FileDescriptor* file, + bool is_descriptor) { + Options options; + options.is_descriptor = is_descriptor; + return GeneratedMetadataFileName(file, options); +} + +template +std::string GeneratedClassFileName(const DescriptorType* desc, + const Options& options) { + std::string result = FullClassName(desc, options); for (int i = 0; i < result.size(); i++) { if (result[i] == '\\') { result[i] = '/'; @@ -275,9 +405,11 @@ std::string GeneratedMessageFileName(const Descriptor* message, return result + ".php"; } -std::string GeneratedEnumFileName(const EnumDescriptor* en, - bool is_descriptor) { - std::string result = FullClassName(en, is_descriptor); +template +std::string LegacyGeneratedClassFileName(const DescriptorType* desc, + const Options& options) { + std::string result = LegacyFullClassName(desc, options); + for (int i = 0; i < result.size(); i++) { if (result[i] == '\\') { result[i] = '/'; @@ -287,8 +419,8 @@ std::string GeneratedEnumFileName(const EnumDescriptor* en, } std::string GeneratedServiceFileName(const ServiceDescriptor* service, - bool is_descriptor) { - std::string result = FullClassName(service, is_descriptor) + "Interface"; + const Options& options) { + std::string result = FullClassName(service, options) + "Interface"; for (int i = 0; i < result.size(); i++) { if (result[i] == '\\') { result[i] = '/'; @@ -312,35 +444,12 @@ std::string LabelForField(const FieldDescriptor* field) { } } -std::string TypeName(const FieldDescriptor* field) { - switch (field->type()) { - case FieldDescriptor::TYPE_INT32: return "int32"; - case FieldDescriptor::TYPE_INT64: return "int64"; - case FieldDescriptor::TYPE_UINT32: return "uint32"; - case FieldDescriptor::TYPE_UINT64: return "uint64"; - case FieldDescriptor::TYPE_SINT32: return "sint32"; - case FieldDescriptor::TYPE_SINT64: return "sint64"; - case FieldDescriptor::TYPE_FIXED32: return "fixed32"; - case FieldDescriptor::TYPE_FIXED64: return "fixed64"; - case FieldDescriptor::TYPE_SFIXED32: return "sfixed32"; - case FieldDescriptor::TYPE_SFIXED64: return "sfixed64"; - case FieldDescriptor::TYPE_DOUBLE: return "double"; - case FieldDescriptor::TYPE_FLOAT: return "float"; - case FieldDescriptor::TYPE_BOOL: return "bool"; - case FieldDescriptor::TYPE_ENUM: return "enum"; - case FieldDescriptor::TYPE_STRING: return "string"; - case FieldDescriptor::TYPE_BYTES: return "bytes"; - case FieldDescriptor::TYPE_MESSAGE: return "message"; - case FieldDescriptor::TYPE_GROUP: return "group"; - default: assert(false); return ""; - } -} - -std::string PhpSetterTypeName(const FieldDescriptor* field, bool is_descriptor) { +std::string PhpSetterTypeName(const FieldDescriptor* field, + const Options& options) { if (field->is_map()) { return "array|\\Google\\Protobuf\\Internal\\MapField"; } - string type; + std::string type; switch (field->type()) { case FieldDescriptor::TYPE_INT32: case FieldDescriptor::TYPE_UINT32: @@ -369,7 +478,7 @@ std::string PhpSetterTypeName(const FieldDescriptor* field, bool is_descriptor) type = "string"; break; case FieldDescriptor::TYPE_MESSAGE: - type = "\\" + FullClassName(field->message_type(), is_descriptor); + type = "\\" + FullClassName(field->message_type(), options); break; case FieldDescriptor::TYPE_GROUP: return "null"; @@ -386,7 +495,15 @@ std::string PhpSetterTypeName(const FieldDescriptor* field, bool is_descriptor) return type; } -std::string PhpGetterTypeName(const FieldDescriptor* field, bool is_descriptor) { +std::string PhpSetterTypeName(const FieldDescriptor* field, + bool is_descriptor) { + Options options; + options.is_descriptor = is_descriptor; + return PhpSetterTypeName(field, options); +} + +std::string PhpGetterTypeName(const FieldDescriptor* field, + const Options& options) { if (field->is_map()) { return "\\Google\\Protobuf\\Internal\\MapField"; } @@ -411,84 +528,77 @@ std::string PhpGetterTypeName(const FieldDescriptor* field, bool is_descriptor) case FieldDescriptor::TYPE_STRING: case FieldDescriptor::TYPE_BYTES: return "string"; case FieldDescriptor::TYPE_MESSAGE: - return "\\" + FullClassName(field->message_type(), is_descriptor); + return "\\" + FullClassName(field->message_type(), options); case FieldDescriptor::TYPE_GROUP: return "null"; default: assert(false); return ""; } } -std::string EnumOrMessageSuffix( - const FieldDescriptor* field, bool is_descriptor) { +std::string PhpGetterTypeName(const FieldDescriptor* field, + bool is_descriptor) { + Options options; + options.is_descriptor = is_descriptor; + return PhpGetterTypeName(field, options); +} + +std::string EnumOrMessageSuffix(const FieldDescriptor* field, + const Options& options) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - return ", '" + MessageFullName(field->message_type(), is_descriptor) + "'"; + return ", '" + + DescriptorFullName(field->message_type(), options.is_descriptor) + + "'"; } if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { - return ", '" + EnumFullName(field->enum_type(), is_descriptor) + "'"; + return ", '" + + DescriptorFullName(field->enum_type(), options.is_descriptor) + "'"; } return ""; } +std::string EnumOrMessageSuffix(const FieldDescriptor* field, + bool is_descriptor) { + Options options; + options.is_descriptor = is_descriptor; + return EnumOrMessageSuffix(field, options); +} + // Converts a name to camel-case. If cap_first_letter is true, capitalize the // first letter. -std::string UnderscoresToCamelCase(const string& input, bool cap_first_letter) { +std::string UnderscoresToCamelCase(const std::string& name, + bool cap_first_letter) { std::string result; - for (int i = 0; i < input.size(); i++) { - if ('a' <= input[i] && input[i] <= 'z') { + for (int i = 0; i < name.size(); i++) { + if ('a' <= name[i] && name[i] <= 'z') { if (cap_first_letter) { - result += input[i] + ('A' - 'a'); + result += name[i] + ('A' - 'a'); } else { - result += input[i]; + result += name[i]; } cap_first_letter = false; - } else if ('A' <= input[i] && input[i] <= 'Z') { + } else if ('A' <= name[i] && name[i] <= 'Z') { if (i == 0 && !cap_first_letter) { // Force first letter to lower-case unless explicitly told to // capitalize it. - result += input[i] + ('a' - 'A'); + result += name[i] + ('a' - 'A'); } else { // Capital letters after the first are left as-is. - result += input[i]; + result += name[i]; } cap_first_letter = false; - } else if ('0' <= input[i] && input[i] <= '9') { - result += input[i]; + } else if ('0' <= name[i] && name[i] <= '9') { + result += name[i]; cap_first_letter = true; } else { cap_first_letter = true; } } // Add a trailing "_" if the name should be altered. - if (input[input.size() - 1] == '#') { + if (name[name.size() - 1] == '#') { result += '_'; } return result; } -std::string EscapeDollor(const string& to_escape) { - return StringReplace(to_escape, "$", "\\$", true); -} - -std::string BinaryToHex(const string& src) { - string dest; - size_t i; - unsigned char symbol[16] = { - '0', '1', '2', '3', - '4', '5', '6', '7', - '8', '9', 'a', 'b', - 'c', 'd', 'e', 'f', - }; - - dest.resize(src.size() * 2); - char* append_ptr = &dest[0]; - - for (i = 0; i < src.size(); i++) { - *append_ptr++ = symbol[(src[i] & 0xf0) >> 4]; - *append_ptr++ = symbol[src[i] & 0x0f]; - } - - return dest; -} - void Indent(io::Printer* printer) { printer->Indent(); printer->Indent(); @@ -499,27 +609,23 @@ void Outdent(io::Printer* printer) { } void GenerateField(const FieldDescriptor* field, io::Printer* printer, - bool is_descriptor) { + const Options& options) { if (field->is_repeated()) { - GenerateFieldDocComment(printer, field, is_descriptor, kFieldProperty); + GenerateFieldDocComment(printer, field, options, kFieldProperty); printer->Print( "private $^name^;\n", "name", field->name()); - } else if (field->containing_oneof()) { + } else if (field->real_containing_oneof()) { // Oneof fields are handled by GenerateOneofField. return; } else { - GenerateFieldDocComment(printer, field, is_descriptor, kFieldProperty); + std::string initial_value = + field->has_presence() ? "null" : DefaultForField(field); + GenerateFieldDocComment(printer, field, options, kFieldProperty); printer->Print( - "private $^name^ = ^default^;\n", + "protected $^name^ = ^initial_value^;\n", "name", field->name(), - "default", DefaultForField(field)); - } - - if (is_descriptor) { - printer->Print( - "private $has_^name^ = false;\n", - "name", field->name()); + "initial_value", initial_value); } } @@ -531,33 +637,77 @@ void GenerateOneofField(const OneofDescriptor* oneof, io::Printer* printer) { "name", oneof->name()); } -void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor, +void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, io::Printer* printer) { - const OneofDescriptor* oneof = field->containing_oneof(); + const OneofDescriptor* oneof = field->real_containing_oneof(); // Generate getter. + GenerateFieldDocComment(printer, field, options, kFieldGetter); + + // deprecation + std::string deprecation_trigger = (field->options().deprecated()) ? "@trigger_error('" + + field->name() + " is deprecated.', E_USER_DEPRECATED);\n " : ""; + if (oneof != NULL) { - GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter); printer->Print( "public function get^camel_name^()\n" "{\n" - " return $this->readOneof(^number^);\n" + " ^deprecation_trigger^return $this->readOneof(^number^);\n" + "}\n\n" + "public function has^camel_name^()\n" + "{\n" + " ^deprecation_trigger^return $this->hasOneof(^number^);\n" "}\n\n", "camel_name", UnderscoresToCamelCase(field->name(), true), - "number", IntToString(field->number())); + "number", IntToString(field->number()), + "deprecation_trigger", deprecation_trigger); + } else if (field->has_presence()) { + printer->Print( + "public function get^camel_name^()\n" + "{\n" + " ^deprecation_trigger^return isset($this->^name^) ? $this->^name^ : ^default_value^;\n" + "}\n\n" + "public function has^camel_name^()\n" + "{\n" + " ^deprecation_trigger^return isset($this->^name^);\n" + "}\n\n" + "public function clear^camel_name^()\n" + "{\n" + " ^deprecation_trigger^unset($this->^name^);\n" + "}\n\n", + "camel_name", UnderscoresToCamelCase(field->name(), true), + "name", field->name(), + "default_value", DefaultForField(field), + "deprecation_trigger", deprecation_trigger); } else { - GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter); printer->Print( "public function get^camel_name^()\n" "{\n" - " return $this->^name^;\n" + " ^deprecation_trigger^return $this->^name^;\n" + "}\n\n", + "camel_name", UnderscoresToCamelCase(field->name(), true), + "name", field->name(), + "deprecation_trigger", deprecation_trigger); + } + + // For wrapper types, generate an additional getXXXUnwrapped getter + if (!field->is_map() && + !field->is_repeated() && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + IsWrapperType(field)) { + GenerateWrapperFieldGetterDocComment(printer, field); + printer->Print( + "public function get^camel_name^Unwrapped()\n" + "{\n" + " ^deprecation_trigger^return $this->readWrapperValue(\"^field_name^\");\n" "}\n\n", - "camel_name", UnderscoresToCamelCase(field->name(), true), "name", - field->name()); + "camel_name", UnderscoresToCamelCase(field->name(), true), + "field_name", field->name(), + "deprecation_trigger", deprecation_trigger); } // Generate setter. - GenerateFieldDocComment(printer, field, is_descriptor, kFieldSetter); + GenerateFieldDocComment(printer, field, options, kFieldSetter); printer->Print( "public function set^camel_name^($var)\n" "{\n", @@ -565,6 +715,13 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor, Indent(printer); + if (field->options().deprecated()) { + printer->Print( + "^deprecation_trigger^", + "deprecation_trigger", deprecation_trigger + ); + } + // Type check. if (field->is_map()) { const Descriptor* map_entry = field->message_type(); @@ -580,12 +737,12 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor, printer->Print( ", \\^class_name^);\n", "class_name", - FullClassName(value->message_type(), is_descriptor) + "::class"); + FullClassName(value->message_type(), options) + "::class"); } else if (value->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { printer->Print( ", \\^class_name^);\n", "class_name", - FullClassName(value->enum_type(), is_descriptor) + "::class"); + FullClassName(value->enum_type(), options) + "::class"); } else { printer->Print(");\n"); } @@ -598,23 +755,23 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor, printer->Print( ", \\^class_name^);\n", "class_name", - FullClassName(field->message_type(), is_descriptor) + "::class"); + FullClassName(field->message_type(), options) + "::class"); } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { printer->Print( ", \\^class_name^);\n", "class_name", - FullClassName(field->enum_type(), is_descriptor) + "::class"); + FullClassName(field->enum_type(), options) + "::class"); } else { printer->Print(");\n"); } } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { printer->Print( "GPBUtil::checkMessage($var, \\^class_name^::class);\n", - "class_name", FullClassName(field->message_type(), is_descriptor)); + "class_name", FullClassName(field->message_type(), options)); } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { printer->Print( "GPBUtil::checkEnum($var, \\^class_name^::class);\n", - "class_name", FullClassName(field->enum_type(), is_descriptor)); + "class_name", FullClassName(field->enum_type(), options)); } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { printer->Print( "GPBUtil::checkString($var, ^utf8^);\n", @@ -640,13 +797,6 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor, "name", field->name()); } - // Set has bit for proto2 only. - if (is_descriptor) { - printer->Print( - "$this->has_^field_name^ = true;\n", - "field_name", field->name()); - } - printer->Print("\nreturn $this;\n"); Outdent(printer); @@ -654,12 +804,17 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor, printer->Print( "}\n\n"); - // Generate has method for proto2 only. - if (is_descriptor) { + // For wrapper types, generate an additional setXXXValue getter + if (!field->is_map() && + !field->is_repeated() && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + IsWrapperType(field)) { + GenerateWrapperFieldSetterDocComment(printer, field); printer->Print( - "public function has^camel_name^()\n" + "public function set^camel_name^Unwrapped($var)\n" "{\n" - " return $this->has_^field_name^;\n" + " $this->writeWrapperValue(\"^field_name^\", $var);\n" + " return $this;" "}\n\n", "camel_name", UnderscoresToCamelCase(field->name(), true), "field_name", field->name()); @@ -670,7 +825,7 @@ void GenerateEnumToPool(const EnumDescriptor* en, io::Printer* printer) { printer->Print( "$pool->addEnum('^name^', " "\\Google\\Protobuf\\Internal\\^class_name^::class)\n", - "name", EnumFullName(en, true), + "name", DescriptorFullName(en, true), "class_name", en->name()); Indent(printer); @@ -678,7 +833,7 @@ void GenerateEnumToPool(const EnumDescriptor* en, io::Printer* printer) { const EnumValueDescriptor* value = en->value(i); printer->Print( "->value(\"^name^\", ^number^)\n", - "name", ClassNamePrefix(value->name(), en) + value->name(), + "name", ConstantNamePrefix(value->name()) + value->name(), "number", IntToString(value->number())); } printer->Print("->finalizeToPool();\n\n"); @@ -695,20 +850,21 @@ void GenerateServiceMethod(const MethodDescriptor* method, ); } -void GenerateMessageToPool(const string& name_prefix, const Descriptor* message, - io::Printer* printer) { +void GenerateMessageToPool(const std::string& name_prefix, + const Descriptor* message, io::Printer* printer) { // Don't generate MapEntry messages -- we use the PHP extension's native // support for map fields instead. if (message->options().map_entry()) { return; } - string class_name = name_prefix.empty()? - message->name() : name_prefix + "_" + message->name(); + std::string class_name = + (name_prefix.empty() ? "" : name_prefix + "\\") + + ReservedNamePrefix(message->name(), message->file()) + message->name(); printer->Print( "$pool->addMessage('^message^', " "\\Google\\Protobuf\\Internal\\^class_name^::class)\n", - "message", MessageFullName(message, true), + "message", DescriptorFullName(message, true), "class_name", class_name); Indent(printer); @@ -726,22 +882,22 @@ void GenerateMessageToPool(const string& name_prefix, const Descriptor* message, "field", field->name(), "key", ToUpper(key->type_name()), "value", ToUpper(val->type_name()), - "number", SimpleItoa(field->number()), + "number", StrCat(field->number()), "other", EnumOrMessageSuffix(val, true)); - } else if (!field->containing_oneof()) { + } else if (!field->real_containing_oneof()) { printer->Print( "->^label^('^field^', " "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n", "field", field->name(), "label", LabelForField(field), "type", ToUpper(field->type_name()), - "number", SimpleItoa(field->number()), + "number", StrCat(field->number()), "other", EnumOrMessageSuffix(field, true)); } } // oneofs. - for (int i = 0; i < message->oneof_decl_count(); i++) { + for (int i = 0; i < message->real_oneof_decl_count(); i++) { const OneofDescriptor* oneof = message->oneof_decl(i); printer->Print("->oneof(^name^)\n", "name", oneof->name()); @@ -753,7 +909,7 @@ void GenerateMessageToPool(const string& name_prefix, const Descriptor* message, "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n", "field", field->name(), "type", ToUpper(field->type_name()), - "number", SimpleItoa(field->number()), + "number", StrCat(field->number()), "other", EnumOrMessageSuffix(field, true)); } printer->Print("->finish()\n"); @@ -776,13 +932,16 @@ void GenerateMessageToPool(const string& name_prefix, const Descriptor* message, } } -void GenerateAddFileToPool(const FileDescriptor* file, bool is_descriptor, +void GenerateAddFileToPool(const FileDescriptor* file, const Options& options, io::Printer* printer) { - printer->Print( - "public static $is_initialized = false;\n\n" - "public static function initOnce() {\n"); - Indent(printer); + printer->Print( + "public static $is_initialized = false;\n\n" + "public static function initOnce() {\n"); + Indent(printer); + if (options.aggregate_metadata) { + GenerateAddFilesToPool(file, options, printer); + } else { printer->Print( "$pool = \\Google\\Protobuf\\Internal\\" "DescriptorPool::getGeneratedPool();\n\n" @@ -790,83 +949,236 @@ void GenerateAddFileToPool(const FileDescriptor* file, bool is_descriptor, " return;\n" "}\n"); - if (is_descriptor) { - for (int i = 0; i < file->message_type_count(); i++) { - GenerateMessageToPool("", file->message_type(i), printer); - } - for (int i = 0; i < file->enum_type_count(); i++) { - GenerateEnumToPool(file->enum_type(i), printer); - } + if (options.is_descriptor) { + for (int i = 0; i < file->message_type_count(); i++) { + GenerateMessageToPool("", file->message_type(i), printer); + } + for (int i = 0; i < file->enum_type_count(); i++) { + GenerateEnumToPool(file->enum_type(i), printer); + } + printer->Print( + "$pool->finish();\n"); + } else { + for (int i = 0; i < file->dependency_count(); i++) { + const std::string& name = file->dependency(i)->name(); + // Currently, descriptor.proto is not ready for external usage. Skip to + // import it for now, so that its dependencies can still work as long as + // they don't use protos defined in descriptor.proto. + if (name == kDescriptorFile) { + continue; + } + std::string dependency_filename = + GeneratedMetadataFileName(file->dependency(i), options); + printer->Print( + "\\^name^::initOnce();\n", + "name", FilenameToClassname(dependency_filename)); + } + + // Add messages and enums to descriptor pool. + FileDescriptorSet files; + FileDescriptorProto* file_proto = files.add_file(); + file->CopyTo(file_proto); + + // Filter out descriptor.proto as it cannot be depended on for now. + RepeatedPtrField* dependency = + file_proto->mutable_dependency(); + for (RepeatedPtrField::iterator it = dependency->begin(); + it != dependency->end(); ++it) { + if (*it != kDescriptorFile) { + dependency->erase(it); + break; + } + } + + // Filter out all extensions, since we do not support extension yet. + file_proto->clear_extension(); + RepeatedPtrField* message_type = + file_proto->mutable_message_type(); + for (RepeatedPtrField::iterator it = message_type->begin(); + it != message_type->end(); ++it) { + it->clear_extension(); + } + + std::string files_data; + files.SerializeToString(&files_data); + + printer->Print("$pool->internalAddGeneratedFile(\n"); + Indent(printer); + printer->Print("'"); + + for (auto ch : files_data) { + switch (ch) { + case '\\': + printer->Print(R"(\\)"); + break; + case '\'': + printer->Print(R"(\')"); + break; + default: + printer->Print("^char^", "char", std::string(1, ch)); + break; + } + } + + printer->Print("'\n"); + Outdent(printer); + printer->Print( + ", true);\n\n"); + } printer->Print( - "$pool->finish();\n"); + "static::$is_initialized = true;\n"); + } + + Outdent(printer); + printer->Print("}\n"); +} + +static void AnalyzeDependencyForFile( + const FileDescriptor* file, + std::set* nodes_without_dependency, + std::map>* deps, + std::map* dependency_count) { + int count = file->dependency_count(); + for (int i = 0; i < file->dependency_count(); i++) { + const FileDescriptor* dependency = file->dependency(i); + if (dependency->name() == kDescriptorFile) { + count--; + break; + } + } + + if (count == 0) { + nodes_without_dependency->insert(file); } else { + (*dependency_count)[file] = count; for (int i = 0; i < file->dependency_count(); i++) { - const std::string& name = file->dependency(i)->name(); - // Currently, descriptor.proto is not ready for external usage. Skip to - // import it for now, so that its dependencies can still work as long as - // they don't use protos defined in descriptor.proto. - if (name == kDescriptorFile) { + const FileDescriptor* dependency = file->dependency(i); + if (dependency->name() == kDescriptorFile) { continue; } - std::string dependency_filename = - GeneratedMetadataFileName(name, is_descriptor); - printer->Print( - "\\^name^::initOnce();\n", - "name", FilenameToClassname(dependency_filename)); + if (deps->find(dependency) == deps->end()) { + (*deps)[dependency] = std::set(); + } + (*deps)[dependency].insert(file); + AnalyzeDependencyForFile( + dependency, nodes_without_dependency, deps, dependency_count); } + } +} - // Add messages and enums to descriptor pool. - FileDescriptorSet files; - FileDescriptorProto* file_proto = files.add_file(); - file->CopyTo(file_proto); - - // Filter out descriptor.proto as it cannot be depended on for now. - RepeatedPtrField* dependency = file_proto->mutable_dependency(); - for (RepeatedPtrField::iterator it = dependency->begin(); - it != dependency->end(); ++it) { - if (*it != kDescriptorFile) { - dependency->erase(it); +static bool NeedsUnwrapping(const FileDescriptor* file, + const Options& options) { + bool has_aggregate_metadata_prefix = false; + if (options.aggregate_metadata_prefixes.empty()) { + has_aggregate_metadata_prefix = true; + } else { + for (const auto& prefix : options.aggregate_metadata_prefixes) { + if (HasPrefixString(file->package(), prefix)) { + has_aggregate_metadata_prefix = true; break; } } + } + + return has_aggregate_metadata_prefix; +} - // Filter out all extensions, since we do not support extension yet. - file_proto->clear_extension(); - RepeatedPtrField* message_type = - file_proto->mutable_message_type(); - for (RepeatedPtrField::iterator it = message_type->begin(); - it != message_type->end(); ++it) { - it->clear_extension(); +void GenerateAddFilesToPool(const FileDescriptor* file, const Options& options, + io::Printer* printer) { + printer->Print( + "$pool = \\Google\\Protobuf\\Internal\\" + "DescriptorPool::getGeneratedPool();\n" + "if (static::$is_initialized == true) {\n" + " return;\n" + "}\n"); + + // Sort files according to dependency + std::map> deps; + std::map dependency_count; + std::set nodes_without_dependency; + FileDescriptorSet sorted_file_set; + + AnalyzeDependencyForFile( + file, &nodes_without_dependency, &deps, &dependency_count); + + while (!nodes_without_dependency.empty()) { + auto file = *nodes_without_dependency.begin(); + nodes_without_dependency.erase(file); + for (auto dependent : deps[file]) { + if (dependency_count[dependent] == 1) { + dependency_count.erase(dependent); + nodes_without_dependency.insert(dependent); + } else { + dependency_count[dependent] -= 1; + } } - string files_data; - files.SerializeToString(&files_data); + bool needs_aggregate = NeedsUnwrapping(file, options); - printer->Print("$pool->internalAddGeneratedFile(hex2bin(\n"); - Indent(printer); + if (needs_aggregate) { + auto file_proto = sorted_file_set.add_file(); + file->CopyTo(file_proto); + + // Filter out descriptor.proto as it cannot be depended on for now. + RepeatedPtrField* dependency = + file_proto->mutable_dependency(); + for (RepeatedPtrField::iterator it = dependency->begin(); + it != dependency->end(); ++it) { + if (*it != kDescriptorFile) { + dependency->erase(it); + break; + } + } - // Only write 30 bytes per line. - static const int kBytesPerLine = 30; - for (int i = 0; i < files_data.size(); i += kBytesPerLine) { + // Filter out all extensions, since we do not support extension yet. + file_proto->clear_extension(); + RepeatedPtrField* message_type = + file_proto->mutable_message_type(); + for (RepeatedPtrField::iterator it = message_type->begin(); + it != message_type->end(); ++it) { + it->clear_extension(); + } + } else { + std::string dependency_filename = GeneratedMetadataFileName(file, false); printer->Print( - "\"^data^\"^dot^\n", - "data", BinaryToHex(files_data.substr(i, kBytesPerLine)), - "dot", i + kBytesPerLine < files_data.size() ? " ." : ""); + "\\^name^::initOnce();\n", + "name", FilenameToClassname(dependency_filename)); } + } - Outdent(printer); - printer->Print( - "));\n\n"); + std::string files_data; + sorted_file_set.SerializeToString(&files_data); + + printer->Print("$pool->internalAddGeneratedFile(\n"); + Indent(printer); + printer->Print("'"); + + for (auto ch : files_data) { + switch (ch) { + case '\\': + printer->Print(R"(\\)"); + break; + case '\'': + printer->Print(R"(\')"); + break; + default: + printer->Print("^char^", "char", std::string(1, ch)); + break; + } } + + printer->Print("'\n"); + Outdent(printer); + printer->Print( + ", true);\n"); + printer->Print( "static::$is_initialized = true;\n"); - Outdent(printer); - printer->Print("}\n"); } -void GenerateUseDeclaration(bool is_descriptor, io::Printer* printer) { - if (!is_descriptor) { +void GenerateUseDeclaration(const Options& options, io::Printer* printer) { + if (!options.is_descriptor) { printer->Print( "use Google\\Protobuf\\Internal\\GPBType;\n" "use Google\\Protobuf\\Internal\\RepeatedField;\n" @@ -890,7 +1202,7 @@ void GenerateHead(const FileDescriptor* file, io::Printer* printer) { "filename", file->name()); } -std::string FilenameToClassname(const string& filename) { +std::string FilenameToClassname(const std::string& filename) { int lastindex = filename.find_last_of("."); std::string result = filename.substr(0, lastindex); for (int i = 0; i < result.size(); i++) { @@ -901,11 +1213,10 @@ std::string FilenameToClassname(const string& filename) { return result; } -void GenerateMetadataFile(const FileDescriptor* file, - bool is_descriptor, +void GenerateMetadataFile(const FileDescriptor* file, const Options& options, GeneratorContext* generator_context) { - std::string filename = GeneratedMetadataFileName(file->name(), is_descriptor); - scoped_ptr output( + std::string filename = GeneratedMetadataFileName(file, options); + std::unique_ptr output( generator_context->Open(filename)); io::Printer printer(output.get(), '^'); @@ -914,11 +1225,11 @@ void GenerateMetadataFile(const FileDescriptor* file, std::string fullname = FilenameToClassname(filename); int lastindex = fullname.find_last_of("\\"); - printer.Print( - "namespace ^name^;\n\n", - "name", fullname.substr(0, lastindex)); + if (lastindex != std::string::npos) { + printer.Print( + "namespace ^name^;\n\n", + "name", fullname.substr(0, lastindex)); - if (lastindex != string::npos) { printer.Print( "class ^name^\n" "{\n", @@ -931,16 +1242,54 @@ void GenerateMetadataFile(const FileDescriptor* file, } Indent(&printer); - GenerateAddFileToPool(file, is_descriptor, &printer); + GenerateAddFileToPool(file, options, &printer); Outdent(&printer); printer.Print("}\n\n"); } +template +void LegacyGenerateClassFile(const FileDescriptor* file, + const DescriptorType* desc, const Options& options, + GeneratorContext* generator_context) { + std::string filename = LegacyGeneratedClassFileName(desc, options); + std::unique_ptr output( + generator_context->Open(filename)); + io::Printer printer(output.get(), '^'); + + GenerateHead(file, &printer); + + std::string php_namespace = RootPhpNamespace(desc, options); + if (!php_namespace.empty()) { + printer.Print( + "namespace ^name^;\n\n", + "name", php_namespace); + } + std::string newname = FullClassName(desc, options); + printer.Print("if (false) {\n"); + Indent(&printer); + printer.Print("/**\n"); + printer.Print(" * This class is deprecated. Use ^new^ instead.\n", + "new", newname); + printer.Print(" * @deprecated\n"); + printer.Print(" */\n"); + printer.Print("class ^old^ {}\n", + "old", LegacyGeneratedClassName(desc)); + Outdent(&printer); + printer.Print("}\n"); + printer.Print("class_exists(^new^::class);\n", + "new", GeneratedClassNameImpl(desc)); + printer.Print("@trigger_error('^old^ is deprecated and will be removed in " + "the next major release. Use ^fullname^ instead', E_USER_DEPRECATED);\n\n", + "old", LegacyFullClassName(desc, options), + "fullname", newname); +} + void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en, - bool is_descriptor, GeneratorContext* generator_context) { - std::string filename = GeneratedEnumFileName(en, is_descriptor); - scoped_ptr output( + const Options& options, + GeneratorContext* generator_context) { + std::string filename = GeneratedClassFileName(en, options); + std::unique_ptr output( generator_context->Open(filename)); io::Printer printer(output.get(), '^'); @@ -949,48 +1298,100 @@ void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en, std::string fullname = FilenameToClassname(filename); int lastindex = fullname.find_last_of("\\"); - if (file->options().has_php_namespace()) { - const string& php_namespace = file->options().php_namespace(); - if (!php_namespace.empty()) { - printer.Print( - "namespace ^name^;\n\n", - "name", php_namespace); - } - } else if (!file->package().empty()) { + if (lastindex != std::string::npos) { printer.Print( "namespace ^name^;\n\n", "name", fullname.substr(0, lastindex)); + + // We only need this 'use' statement if the enum has a namespace. + // Otherwise, we get a warning that the use statement has no effect. + printer.Print("use UnexpectedValueException;\n\n"); } - GenerateEnumDocComment(&printer, en, is_descriptor); + GenerateEnumDocComment(&printer, en, options); - if (lastindex != string::npos) { - printer.Print( - "class ^name^\n" - "{\n", - "name", fullname.substr(lastindex + 1)); - } else { - printer.Print( - "class ^name^\n" - "{\n", - "name", fullname); + if (lastindex != std::string::npos) { + fullname = fullname.substr(lastindex + 1); } + + printer.Print( + "class ^name^\n" + "{\n", + "name", fullname); Indent(&printer); for (int i = 0; i < en->value_count(); i++) { const EnumValueDescriptor* value = en->value(i); GenerateEnumValueDocComment(&printer, value); printer.Print("const ^name^ = ^number^;\n", - "name", ClassNamePrefix(value->name(), en) + value->name(), + "name", ConstantNamePrefix(value->name()) + value->name(), "number", IntToString(value->number())); } + printer.Print("\nprivate static $valueToName = [\n"); + Indent(&printer); + for (int i = 0; i < en->value_count(); i++) { + const EnumValueDescriptor* value = en->value(i); + printer.Print("self::^name^ => '^name^',\n", + "name", ConstantNamePrefix(value->name()) + value->name()); + } + Outdent(&printer); + printer.Print("];\n"); + + printer.Print( + "\npublic static function name($value)\n" + "{\n"); + Indent(&printer); + printer.Print("if (!isset(self::$valueToName[$value])) {\n"); + Indent(&printer); + printer.Print("throw new UnexpectedValueException(sprintf(\n"); + Indent(&printer); + Indent(&printer); + printer.Print("'Enum %s has no name defined for value %s', __CLASS__, $value));\n"); + Outdent(&printer); + Outdent(&printer); + Outdent(&printer); + printer.Print("}\n" + "return self::$valueToName[$value];\n"); Outdent(&printer); printer.Print("}\n\n"); + + printer.Print( + "\npublic static function value($name)\n" + "{\n"); + Indent(&printer); + printer.Print("$const = __CLASS__ . '::' . strtoupper($name);\n" + "if (!defined($const)) {\n"); + Indent(&printer); + printer.Print("throw new UnexpectedValueException(sprintf(\n"); + Indent(&printer); + Indent(&printer); + printer.Print("'Enum %s has no value defined for name %s', __CLASS__, $name));\n"); + Outdent(&printer); + Outdent(&printer); + Outdent(&printer); + printer.Print("}\n" + "return constant($const);\n"); + Outdent(&printer); + printer.Print("}\n"); + + Outdent(&printer); + printer.Print("}\n\n"); + + // write legacy file for backwards compatibility with nested messages and enums + if (en->containing_type() != NULL) { + printer.Print( + "// Adding a class alias for backwards compatibility with the previous class name.\n"); + printer.Print( + "class_alias(^new^::class, \\^old^::class);\n\n", + "new", fullname, + "old", LegacyFullClassName(en, options)); + LegacyGenerateClassFile(file, en, options, generator_context); + } } void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, - bool is_descriptor, + const Options& options, GeneratorContext* generator_context) { // Don't generate MapEntry messages -- we use the PHP extension's native // support for map fields instead. @@ -998,8 +1399,8 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, return; } - std::string filename = GeneratedMessageFileName(message, is_descriptor); - scoped_ptr output( + std::string filename = GeneratedClassFileName(message, options); + std::unique_ptr output( generator_context->Open(filename)); io::Printer printer(output.get(), '^'); @@ -1008,67 +1409,74 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, std::string fullname = FilenameToClassname(filename); int lastindex = fullname.find_last_of("\\"); - if (file->options().has_php_namespace()) { - const string& php_namespace = file->options().php_namespace(); - if (!php_namespace.empty()) { - printer.Print( - "namespace ^name^;\n\n", - "name", php_namespace); - } - } else if (!file->package().empty()) { + if (lastindex != std::string::npos) { printer.Print( "namespace ^name^;\n\n", "name", fullname.substr(0, lastindex)); } - GenerateUseDeclaration(is_descriptor, &printer); + GenerateUseDeclaration(options, &printer); - GenerateMessageDocComment(&printer, message, is_descriptor); - if (lastindex != string::npos) { - printer.Print( - "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n" - "{\n", - "name", fullname.substr(lastindex + 1)); - } else { - printer.Print( - "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n" - "{\n", - "name", fullname); + GenerateMessageDocComment(&printer, message, options); + if (lastindex != std::string::npos) { + fullname = fullname.substr(lastindex + 1); + } + + std::string base; + + switch (message->well_known_type()) { + case Descriptor::WELLKNOWNTYPE_ANY: + base = "\\Google\\Protobuf\\Internal\\AnyBase"; + break; + case Descriptor::WELLKNOWNTYPE_TIMESTAMP: + base = "\\Google\\Protobuf\\Internal\\TimestampBase"; + break; + default: + base = "\\Google\\Protobuf\\Internal\\Message"; + break; } + + printer.Print( + "class ^name^ extends ^base^\n" + "{\n", + "base", base, + "name", fullname); Indent(&printer); // Field and oneof definitions. for (int i = 0; i < message->field_count(); i++) { const FieldDescriptor* field = message->field(i); - GenerateField(field, &printer, is_descriptor); + GenerateField(field, &printer, options); } - for (int i = 0; i < message->oneof_decl_count(); i++) { + for (int i = 0; i < message->real_oneof_decl_count(); i++) { const OneofDescriptor* oneof = message->oneof_decl(i); GenerateOneofField(oneof, &printer); } printer.Print("\n"); + GenerateMessageConstructorDocComment(&printer, message, options); printer.Print( - "public function __construct() {\n"); + "public function __construct($data = NULL) {\n"); Indent(&printer); - std::string metadata_filename = - GeneratedMetadataFileName(file->name(), is_descriptor); + std::string metadata_filename = GeneratedMetadataFileName(file, options); std::string metadata_fullname = FilenameToClassname(metadata_filename); printer.Print( - "\\^fullname^::initOnce();\n" - "parent::__construct();\n", + "\\^fullname^::initOnce();\n", "fullname", metadata_fullname); + printer.Print( + "parent::__construct($data);\n"); + Outdent(&printer); printer.Print("}\n\n"); // Field and oneof accessors. for (int i = 0; i < message->field_count(); i++) { const FieldDescriptor* field = message->field(i); - GenerateFieldAccessor(field, is_descriptor, &printer); + GenerateFieldAccessor(field, options, &printer); } - for (int i = 0; i < message->oneof_decl_count(); i++) { + for (int i = 0; i < message->real_oneof_decl_count(); i++) { const OneofDescriptor* oneof = message->oneof_decl(i); printer.Print( "/**\n" @@ -1085,22 +1493,32 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, Outdent(&printer); printer.Print("}\n\n"); + // write legacy file for backwards compatibility with nested messages and enums + if (message->containing_type() != NULL) { + printer.Print( + "// Adding a class alias for backwards compatibility with the previous class name.\n"); + printer.Print( + "class_alias(^new^::class, \\^old^::class);\n\n", + "new", fullname, + "old", LegacyFullClassName(message, options)); + LegacyGenerateClassFile(file, message, options, generator_context); + } + // Nested messages and enums. for (int i = 0; i < message->nested_type_count(); i++) { - GenerateMessageFile(file, message->nested_type(i), is_descriptor, + GenerateMessageFile(file, message->nested_type(i), options, generator_context); } for (int i = 0; i < message->enum_type_count(); i++) { - GenerateEnumFile(file, message->enum_type(i), is_descriptor, - generator_context); + GenerateEnumFile(file, message->enum_type(i), options, generator_context); } } -void GenerateServiceFile(const FileDescriptor* file, - const ServiceDescriptor* service, bool is_descriptor, - GeneratorContext* generator_context) { - std::string filename = GeneratedServiceFileName(service, is_descriptor); - scoped_ptr output( +void GenerateServiceFile( + const FileDescriptor* file, const ServiceDescriptor* service, + const Options& options, GeneratorContext* generator_context) { + std::string filename = GeneratedServiceFileName(service, options); + std::unique_ptr output( generator_context->Open(filename)); io::Printer printer(output.get(), '^'); @@ -1109,14 +1527,9 @@ void GenerateServiceFile(const FileDescriptor* file, std::string fullname = FilenameToClassname(filename); int lastindex = fullname.find_last_of("\\"); - if (file->options().has_php_namespace()) { - const string& php_namespace = file->options().php_namespace(); - if (!php_namespace.empty()) { - printer.Print( - "namespace ^name^;\n\n", - "name", php_namespace); - } - } else if (!file->package().empty()) { + if (!file->options().php_namespace().empty() || + (!file->options().has_php_namespace() && !file->package().empty()) || + lastindex != std::string::npos) { printer.Print( "namespace ^name^;\n\n", "name", fullname.substr(0, lastindex)); @@ -1124,13 +1537,13 @@ void GenerateServiceFile(const FileDescriptor* file, GenerateServiceDocComment(&printer, service); - if (lastindex != string::npos) { - printer.Print( + if (lastindex != std::string::npos) { + printer.Print( "interface ^name^\n" "{\n", "name", fullname.substr(lastindex + 1)); } else { - printer.Print( + printer.Print( "interface ^name^\n" "{\n", "name", fullname); @@ -1148,32 +1561,31 @@ void GenerateServiceFile(const FileDescriptor* file, printer.Print("}\n\n"); } -void GenerateFile(const FileDescriptor* file, bool is_descriptor, +void GenerateFile(const FileDescriptor* file, const Options& options, GeneratorContext* generator_context) { - GenerateMetadataFile(file, is_descriptor, generator_context); + GenerateMetadataFile(file, options, generator_context); + for (int i = 0; i < file->message_type_count(); i++) { - GenerateMessageFile(file, file->message_type(i), is_descriptor, + GenerateMessageFile(file, file->message_type(i), options, generator_context); } for (int i = 0; i < file->enum_type_count(); i++) { - GenerateEnumFile(file, file->enum_type(i), is_descriptor, - generator_context); + GenerateEnumFile(file, file->enum_type(i), options, generator_context); } if (file->options().php_generic_services()) { for (int i = 0; i < file->service_count(); i++) { - GenerateServiceFile(file, file->service(i), is_descriptor, - generator_context); + GenerateServiceFile(file, file->service(i), options, generator_context); } } } -static string EscapePhpdoc(const string& input) { - string result; +static std::string EscapePhpdoc(const std::string& input) { + std::string result; result.reserve(input.size() * 2); char prev = '*'; - for (string::size_type i = 0; i < input.size(); i++) { + for (std::string::size_type i = 0; i < input.size(); i++) { char c = input[i]; switch (c) { case '*': @@ -1210,9 +1622,11 @@ static string EscapePhpdoc(const string& input) { } static void GenerateDocCommentBodyForLocation( - io::Printer* printer, const SourceLocation& location) { - string comments = location.leading_comments.empty() ? - location.trailing_comments : location.leading_comments; + io::Printer* printer, const SourceLocation& location, bool trailingNewline, + int indentCount) { + std::string comments = location.leading_comments.empty() + ? location.trailing_comments + : location.leading_comments; if (!comments.empty()) { // TODO(teboring): Ideally we should parse the comment text as Markdown and // write it back as HTML, but this requires a Markdown parser. For now @@ -1222,7 +1636,7 @@ static void GenerateDocCommentBodyForLocation( // HTML-escape them so that they don't accidentally close the doc comment. comments = EscapePhpdoc(comments); - vector lines = Split(comments, "\n"); + std::vector lines = Split(comments, "\n", true); while (!lines.empty() && lines.back().empty()) { lines.pop_back(); } @@ -1231,14 +1645,16 @@ static void GenerateDocCommentBodyForLocation( // Most lines should start with a space. Watch out for lines that start // with a /, since putting that right after the leading asterisk will // close the comment. - if (!lines[i].empty() && lines[i][0] == '/') { + if (indentCount == 0 && !lines[i].empty() && lines[i][0] == '/') { printer->Print(" * ^line^\n", "line", lines[i]); } else { - printer->Print(" *^line^\n", "line", lines[i]); + std::string indent = std::string(indentCount, ' '); + printer->Print(" *^ind^^line^\n", "ind", indent, "line", lines[i]); } } - printer->Print( - " *\n"); + if (trailingNewline) { + printer->Print(" *\n"); + } } } @@ -1247,32 +1663,63 @@ static void GenerateDocCommentBody( io::Printer* printer, const DescriptorType* descriptor) { SourceLocation location; if (descriptor->GetSourceLocation(&location)) { - GenerateDocCommentBodyForLocation(printer, location); + GenerateDocCommentBodyForLocation(printer, location, true, 0); } } -static string FirstLineOf(const string& value) { - string result = value; +static std::string FirstLineOf(const std::string& value) { + std::string result = value; - string::size_type pos = result.find_first_of('\n'); - if (pos != string::npos) { + std::string::size_type pos = result.find_first_of('\n'); + if (pos != std::string::npos) { result.erase(pos); } return result; } -void GenerateMessageDocComment(io::Printer* printer, - const Descriptor* message, int is_descriptor) { +void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message, + const Options& options) { printer->Print("/**\n"); GenerateDocCommentBody(printer, message); printer->Print( " * Generated from protobuf message ^messagename^\n" " */\n", - "fullname", EscapePhpdoc(PhpName(message->full_name(), is_descriptor)), + "fullname", EscapePhpdoc(FullClassName(message, options)), "messagename", EscapePhpdoc(message->full_name())); } +void GenerateMessageConstructorDocComment(io::Printer* printer, + const Descriptor* message, + const Options& options) { + // In theory we should have slightly different comments for setters, getters, + // etc., but in practice everyone already knows the difference between these + // so it's redundant information. + + // We start the comment with the main body based on the comments from the + // .proto file (if present). We then end with the field declaration, e.g.: + // optional string foo = 5; + // If the field is a group, the debug string might end with {. + printer->Print("/**\n"); + printer->Print(" * Constructor.\n"); + printer->Print(" *\n"); + printer->Print(" * @param array $data {\n"); + printer->Print(" * Optional. Data for populating the Message object.\n"); + printer->Print(" *\n"); + for (int i = 0; i < message->field_count(); i++) { + const FieldDescriptor* field = message->field(i); + printer->Print(" * @type ^php_type^ $^var^\n", + "php_type", PhpSetterTypeName(field, options), + "var", field->name()); + SourceLocation location; + if (field->GetSourceLocation(&location)) { + GenerateDocCommentBodyForLocation(printer, location, false, 10); + } + } + printer->Print(" * }\n"); + printer->Print(" */\n"); +} + void GenerateServiceDocComment(io::Printer* printer, const ServiceDescriptor* service) { printer->Print("/**\n"); @@ -1284,7 +1731,7 @@ void GenerateServiceDocComment(io::Printer* printer, } void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field, - int is_descriptor, int function_type) { + const Options& options, int function_type) { // In theory we should have slightly different comments for setters, getters, // etc., but in practice everyone already knows the difference between these // so it's redundant information. @@ -1300,23 +1747,64 @@ void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field, "def", EscapePhpdoc(FirstLineOf(field->DebugString()))); if (function_type == kFieldSetter) { printer->Print(" * @param ^php_type^ $var\n", - "php_type", PhpSetterTypeName(field, is_descriptor)); + "php_type", PhpSetterTypeName(field, options)); printer->Print(" * @return $this\n"); } else if (function_type == kFieldGetter) { - printer->Print(" * @return ^php_type^\n", - "php_type", PhpGetterTypeName(field, is_descriptor)); + bool can_return_null = field->has_presence() && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE; + printer->Print(" * @return ^php_type^^maybe_null^\n", + "php_type", PhpGetterTypeName(field, options), + "maybe_null", can_return_null ? "|null" : ""); + } + if (field->options().deprecated()) { + printer->Print(" * @deprecated\n"); } printer->Print(" */\n"); } +void GenerateWrapperFieldGetterDocComment(io::Printer* printer, const FieldDescriptor* field) { + // Generate a doc comment for the special getXXXValue methods that are + // generated for wrapper types. + const FieldDescriptor* primitiveField = field->message_type()->FindFieldByName("value"); + printer->Print("/**\n"); + printer->Print( + " * Returns the unboxed value from get^camel_name^()\n\n", + "camel_name", UnderscoresToCamelCase(field->name(), true)); + GenerateDocCommentBody(printer, field); + printer->Print( + " * Generated from protobuf field ^def^\n", + "def", EscapePhpdoc(FirstLineOf(field->DebugString()))); + printer->Print(" * @return ^php_type^|null\n", + "php_type", PhpGetterTypeName(primitiveField, false)); + printer->Print(" */\n"); +} + +void GenerateWrapperFieldSetterDocComment(io::Printer* printer, const FieldDescriptor* field) { + // Generate a doc comment for the special setXXXValue methods that are + // generated for wrapper types. + const FieldDescriptor* primitiveField = field->message_type()->FindFieldByName("value"); + printer->Print("/**\n"); + printer->Print( + " * Sets the field by wrapping a primitive type in a ^message_name^ object.\n\n", + "message_name", FullClassName(field->message_type(), false)); + GenerateDocCommentBody(printer, field); + printer->Print( + " * Generated from protobuf field ^def^\n", + "def", EscapePhpdoc(FirstLineOf(field->DebugString()))); + printer->Print(" * @param ^php_type^|null $var\n", + "php_type", PhpSetterTypeName(primitiveField, false)); + printer->Print(" * @return $this\n"); + printer->Print(" */\n"); +} + void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_, - int is_descriptor) { + const Options& options) { printer->Print("/**\n"); GenerateDocCommentBody(printer, enum_); printer->Print( - " * Protobuf enum ^fullname^\n" + " * Protobuf type ^fullname^\n" " */\n", - "fullname", EscapePhpdoc(PhpName(enum_->full_name(), is_descriptor))); + "fullname", EscapePhpdoc(enum_->full_name())); } void GenerateEnumValueDocComment(io::Printer* printer, @@ -1330,7 +1818,7 @@ void GenerateEnumValueDocComment(io::Printer* printer, } void GenerateServiceMethodDocComment(io::Printer* printer, - const MethodDescriptor* method) { + const MethodDescriptor* method) { printer->Print("/**\n"); GenerateDocCommentBody(printer, method); printer->Print( @@ -1346,25 +1834,464 @@ void GenerateServiceMethodDocComment(io::Printer* printer, "return_type", EscapePhpdoc(FullClassName(method->output_type(), false))); } -bool Generator::Generate(const FileDescriptor* file, const string& parameter, +std::string FilenameCName(const FileDescriptor* file) { + std::string c_name = file->name(); + c_name = StringReplace(c_name, ".", "_", true); + c_name = StringReplace(c_name, "/", "_", true); + return c_name; +} + +void GenerateCEnum(const EnumDescriptor* desc, io::Printer* printer) { + std::string c_name = desc->full_name(); + c_name = StringReplace(c_name, ".", "_", true); + std::string php_name = FullClassName(desc, Options()); + php_name = StringReplace(php_name, "\\", "\\\\", true); + printer->Print( + "/* $c_name$ */\n" + "\n" + "zend_class_entry* $c_name$_ce;\n" + "\n" + "PHP_METHOD($c_name$, name) {\n" + " $file_c_name$_AddDescriptor();\n" + " const upb_symtab *symtab = DescriptorPool_GetSymbolTable();\n" + " const upb_enumdef *e = upb_symtab_lookupenum(symtab, \"$name$\");\n" + " const char *name;\n" + " zend_long value;\n" + " if (zend_parse_parameters(ZEND_NUM_ARGS(), \"l\", &value) ==\n" + " FAILURE) {\n" + " return;\n" + " }\n" + " name = upb_enumdef_iton(e, value);\n" + " if (!name) {\n" + " zend_throw_exception_ex(NULL, 0,\n" + " \"$php_name$ has no name \"\n" + " \"defined for value \" ZEND_LONG_FMT \".\",\n" + " value);\n" + " return;\n" + " }\n" + " RETURN_STRING(name);\n" + "}\n" + "\n" + "PHP_METHOD($c_name$, value) {\n" + " $file_c_name$_AddDescriptor();\n" + " const upb_symtab *symtab = DescriptorPool_GetSymbolTable();\n" + " const upb_enumdef *e = upb_symtab_lookupenum(symtab, \"$name$\");\n" + " char *name = NULL;\n" + " size_t name_len;\n" + " int32_t num;\n" + " if (zend_parse_parameters(ZEND_NUM_ARGS(), \"s\", &name,\n" + " &name_len) == FAILURE) {\n" + " return;\n" + " }\n" + " if (!upb_enumdef_ntoi(e, name, name_len, &num)) {\n" + " zend_throw_exception_ex(NULL, 0,\n" + " \"$php_name$ has no value \"\n" + " \"defined for name %s.\",\n" + " name);\n" + " return;\n" + " }\n" + " RETURN_LONG(num);\n" + "}\n" + "\n" + "static zend_function_entry $c_name$_phpmethods[] = {\n" + " PHP_ME($c_name$, name, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n" + " PHP_ME($c_name$, value, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n" + " ZEND_FE_END\n" + "};\n" + "\n" + "static void $c_name$_ModuleInit() {\n" + " zend_class_entry tmp_ce;\n" + "\n" + " INIT_CLASS_ENTRY(tmp_ce, \"$php_name$\",\n" + " $c_name$_phpmethods);\n" + "\n" + " $c_name$_ce = zend_register_internal_class(&tmp_ce);\n", + "name", desc->full_name(), + "file_c_name", FilenameCName(desc->file()), + "c_name", c_name, + "php_name", php_name); + + for (int i = 0; i < desc->value_count(); i++) { + const EnumValueDescriptor* value = desc->value(i); + printer->Print( + " zend_declare_class_constant_long($c_name$_ce, \"$name$\",\n" + " strlen(\"$name$\"), $num$);\n", + "c_name", c_name, + "name", value->name(), + "num", std::to_string(value->number())); + } + + printer->Print( + "}\n" + "\n"); +} + +void GenerateCMessage(const Descriptor* message, io::Printer* printer) { + std::string c_name = message->full_name(); + c_name = StringReplace(c_name, ".", "_", true); + std::string php_name = FullClassName(message, Options()); + php_name = StringReplace(php_name, "\\", "\\\\", true); + printer->Print( + "/* $c_name$ */\n" + "\n" + "zend_class_entry* $c_name$_ce;\n" + "\n" + "static PHP_METHOD($c_name$, __construct) {\n" + " $file_c_name$_AddDescriptor();\n" + " zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n" + "}\n" + "\n", + "file_c_name", FilenameCName(message->file()), + "c_name", c_name); + + for (int i = 0; i < message->field_count(); i++) { + auto field = message->field(i); + printer->Print( + "static PHP_METHOD($c_name$, get$camel_name$) {\n" + " Message* intern = (Message*)Z_OBJ_P(getThis());\n" + " const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,\n" + " \"$name$\");\n" + " zval ret;\n" + " Message_get(intern, f, &ret);\n" + " RETURN_ZVAL(&ret, 1, 0);\n" + "}\n" + "\n" + "static PHP_METHOD($c_name$, set$camel_name$) {\n" + " Message* intern = (Message*)Z_OBJ_P(getThis());\n" + " const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef,\n" + " \"$name$\");\n" + " zval *val;\n" + " if (zend_parse_parameters(ZEND_NUM_ARGS(), \"z\", &val)\n" + " == FAILURE) {\n" + " return;\n" + " }\n" + " Message_set(intern, f, val);\n" + " RETURN_ZVAL(getThis(), 1, 0);\n" + "}\n" + "\n", + "c_name", c_name, + "name", field->name(), + "camel_name", UnderscoresToCamelCase(field->name(), true)); + } + + for (int i = 0; i < message->real_oneof_decl_count(); i++) { + auto oneof = message->oneof_decl(i); + printer->Print( + "static PHP_METHOD($c_name$, get$camel_name$) {\n" + " Message* intern = (Message*)Z_OBJ_P(getThis());\n" + " const upb_oneofdef *oneof = upb_msgdef_ntooz(intern->desc->msgdef,\n" + " \"$name$\");\n" + " const upb_fielddef *field = upb_msg_whichoneof(intern->msg, oneof);\n" + " RETURN_STRING(field ? upb_fielddef_name(field) : \"\");\n" + "}\n", + "c_name", c_name, + "name", oneof->name(), + "camel_name", UnderscoresToCamelCase(oneof->name(), true)); + } + + switch (message->well_known_type()) { + case Descriptor::WELLKNOWNTYPE_ANY: + printer->Print( + "ZEND_BEGIN_ARG_INFO_EX(arginfo_is, 0, 0, 1)\n" + " ZEND_ARG_INFO(0, proto)\n" + "ZEND_END_ARG_INFO()\n" + "\n" + ); + break; + case Descriptor::WELLKNOWNTYPE_TIMESTAMP: + printer->Print( + "ZEND_BEGIN_ARG_INFO_EX(arginfo_timestamp_fromdatetime, 0, 0, 1)\n" + " ZEND_ARG_INFO(0, datetime)\n" + "ZEND_END_ARG_INFO()\n" + "\n" + ); + break; + default: + break; + } + + printer->Print( + "static zend_function_entry $c_name$_phpmethods[] = {\n" + " PHP_ME($c_name$, __construct, arginfo_void, ZEND_ACC_PUBLIC)\n", + "c_name", c_name); + + for (int i = 0; i < message->field_count(); i++) { + auto field = message->field(i); + printer->Print( + " PHP_ME($c_name$, get$camel_name$, arginfo_void, ZEND_ACC_PUBLIC)\n" + " PHP_ME($c_name$, set$camel_name$, arginfo_setter, ZEND_ACC_PUBLIC)\n", + "c_name", c_name, + "camel_name", UnderscoresToCamelCase(field->name(), true)); + } + + for (int i = 0; i < message->real_oneof_decl_count(); i++) { + auto oneof = message->oneof_decl(i); + printer->Print( + " PHP_ME($c_name$, get$camel_name$, arginfo_void, ZEND_ACC_PUBLIC)\n", + "c_name", c_name, + "camel_name", UnderscoresToCamelCase(oneof->name(), true)); + } + + // Extra hand-written functions added to the well-known types. + switch (message->well_known_type()) { + case Descriptor::WELLKNOWNTYPE_ANY: + printer->Print( + " PHP_ME($c_name$, is, arginfo_is, ZEND_ACC_PUBLIC)\n" + " PHP_ME($c_name$, pack, arginfo_setter, ZEND_ACC_PUBLIC)\n" + " PHP_ME($c_name$, unpack, arginfo_void, ZEND_ACC_PUBLIC)\n", + "c_name", c_name); + break; + case Descriptor::WELLKNOWNTYPE_TIMESTAMP: + printer->Print( + " PHP_ME($c_name$, fromDateTime, arginfo_timestamp_fromdatetime, ZEND_ACC_PUBLIC)\n" + " PHP_ME($c_name$, toDateTime, arginfo_void, ZEND_ACC_PUBLIC)\n", + "c_name", c_name); + break; + default: + break; + } + + printer->Print( + " ZEND_FE_END\n" + "};\n" + "\n" + "static void $c_name$_ModuleInit() {\n" + " zend_class_entry tmp_ce;\n" + "\n" + " INIT_CLASS_ENTRY(tmp_ce, \"$php_name$\",\n" + " $c_name$_phpmethods);\n" + "\n" + " $c_name$_ce = zend_register_internal_class(&tmp_ce);\n" + " $c_name$_ce->ce_flags |= ZEND_ACC_FINAL;\n" + " $c_name$_ce->create_object = Message_create;\n" + " zend_do_inheritance($c_name$_ce, message_ce);\n" + "}\n" + "\n", + "c_name", c_name, + "php_name", php_name); + + for (int i = 0; i < message->nested_type_count(); i++) { + GenerateCMessage(message->nested_type(i), printer); + } + for (int i = 0; i < message->enum_type_count(); i++) { + GenerateCEnum(message->enum_type(i), printer); + } +} + +void GenerateEnumCInit(const EnumDescriptor* desc, io::Printer* printer) { + std::string c_name = desc->full_name(); + c_name = StringReplace(c_name, ".", "_", true); + + printer->Print( + " $c_name$_ModuleInit();\n", + "c_name", c_name); +} + +void GenerateCInit(const Descriptor* message, io::Printer* printer) { + std::string c_name = message->full_name(); + c_name = StringReplace(c_name, ".", "_", true); + + printer->Print( + " $c_name$_ModuleInit();\n", + "c_name", c_name); + + for (int i = 0; i < message->nested_type_count(); i++) { + GenerateCInit(message->nested_type(i), printer); + } + for (int i = 0; i < message->enum_type_count(); i++) { + GenerateEnumCInit(message->enum_type(i), printer); + } +} + +void GenerateCWellKnownTypes(const std::vector& files, + GeneratorContext* context) { + std::unique_ptr output( + context->Open("../ext/google/protobuf/wkt.inc")); + io::Printer printer(output.get(), '$'); + + printer.Print( + "// This file is generated from the .proto files for the well-known\n" + "// types. Do not edit!\n"); + + for (auto file : files) { + printer.Print( + "static void $c_name$_AddDescriptor();\n", + "c_name", FilenameCName(file)); + } + + for (auto file : files) { + std::string c_name = FilenameCName(file); + std::string metadata_filename = GeneratedMetadataFileName(file, Options()); + std::string metadata_classname = FilenameToClassname(metadata_filename); + std::string metadata_c_name = + StringReplace(metadata_classname, "\\", "_", true); + metadata_classname = StringReplace(metadata_classname, "\\", "\\\\", true); + FileDescriptorProto file_proto; + file->CopyTo(&file_proto); + std::string serialized; + file_proto.SerializeToString(&serialized); + printer.Print( + "/* $filename$ */\n" + "\n" + "zend_class_entry* $metadata_c_name$_ce;\n" + "\n" + "const char $c_name$_descriptor [$size$] = {\n", + "filename", file->name(), + "c_name", c_name, + "metadata_c_name", metadata_c_name, + "size", std::to_string(serialized.size())); + + for (size_t i = 0; i < serialized.size();) { + for (size_t j = 0; j < 25 && i < serialized.size(); ++i, ++j) { + printer.Print("'$ch$', ", "ch", CEscape(serialized.substr(i, 1))); + } + printer.Print("\n"); + } + + printer.Print( + "};\n" + "\n" + "static void $c_name$_AddDescriptor() {\n" + " if (DescriptorPool_HasFile(\"$filename$\")) return;\n", + "filename", file->name(), + "c_name", c_name, + "metadata_c_name", metadata_c_name); + + for (int i = 0; i < file->dependency_count(); i++) { + std::string dep_c_name = FilenameCName(file->dependency(i)); + printer.Print( + " $dep_c_name$_AddDescriptor();\n", + "dep_c_name", dep_c_name); + } + + printer.Print( + " DescriptorPool_AddDescriptor(\"$filename$\", $c_name$_descriptor,\n" + " sizeof($c_name$_descriptor));\n" + "}\n" + "\n" + "static PHP_METHOD($metadata_c_name$, initOnce) {\n" + " $c_name$_AddDescriptor();\n" + "}\n" + "\n" + "static zend_function_entry $metadata_c_name$_methods[] = {\n" + " PHP_ME($metadata_c_name$, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n" + " ZEND_FE_END\n" + "};\n" + "\n" + "static void $metadata_c_name$_ModuleInit() {\n" + " zend_class_entry tmp_ce;\n" + "\n" + " INIT_CLASS_ENTRY(tmp_ce, \"$metadata_classname$\",\n" + " $metadata_c_name$_methods);\n" + "\n" + " $metadata_c_name$_ce = zend_register_internal_class(&tmp_ce);\n" + "}\n" + "\n", + "filename", file->name(), + "c_name", c_name, + "metadata_c_name", metadata_c_name, + "metadata_classname", metadata_classname); + for (int i = 0; i < file->message_type_count(); i++) { + GenerateCMessage(file->message_type(i), &printer); + } + for (int i = 0; i < file->enum_type_count(); i++) { + GenerateCEnum(file->enum_type(i), &printer); + } + } + + printer.Print( + "static void WellKnownTypes_ModuleInit() {\n"); + + for (auto file : files) { + std::string metadata_filename = GeneratedMetadataFileName(file, Options()); + std::string metadata_classname = FilenameToClassname(metadata_filename); + std::string metadata_c_name = + StringReplace(metadata_classname, "\\", "_", true); + printer.Print( + " $metadata_c_name$_ModuleInit();\n", + "metadata_c_name", metadata_c_name); + for (int i = 0; i < file->message_type_count(); i++) { + GenerateCInit(file->message_type(i), &printer); + } + for (int i = 0; i < file->enum_type_count(); i++) { + GenerateEnumCInit(file->enum_type(i), &printer); + } + } + + printer.Print( + "}\n"); +} + +} // namespace + +std::string GeneratedClassName(const Descriptor* desc) { + return GeneratedClassNameImpl(desc); +} + +std::string GeneratedClassName(const EnumDescriptor* desc) { + return GeneratedClassNameImpl(desc); +} + +std::string GeneratedClassName(const ServiceDescriptor* desc) { + return GeneratedClassNameImpl(desc); +} + +bool Generator::Generate(const FileDescriptor* file, + const std::string& parameter, GeneratorContext* generator_context, - string* error) const { - bool is_descriptor = parameter == "internal"; + std::string* error) const { + return Generate(file, Options(), generator_context, error); +} - if (is_descriptor && file->name() != kDescriptorFile) { +bool Generator::Generate(const FileDescriptor* file, const Options& options, + GeneratorContext* generator_context, + std::string* error) const { + if (options.is_descriptor && file->name() != kDescriptorFile) { *error = "Can only generate PHP code for google/protobuf/descriptor.proto.\n"; return false; } - if (!is_descriptor && file->syntax() != FileDescriptor::SYNTAX_PROTO3) { + if (!options.is_descriptor && file->syntax() != FileDescriptor::SYNTAX_PROTO3) { *error = "Can only generate PHP code for proto3 .proto files.\n" "Please add 'syntax = \"proto3\";' to the top of your .proto file.\n"; return false; } - GenerateFile(file, is_descriptor, generator_context); + GenerateFile(file, options, generator_context); + + return true; +} + +bool Generator::GenerateAll(const std::vector& files, + const std::string& parameter, + GeneratorContext* generator_context, + std::string* error) const { + Options options; + + for (const auto& option : Split(parameter, ",", true)) { + const std::vector option_pair = Split(option, "=", true); + if (HasPrefixString(option_pair[0], "aggregate_metadata")) { + options.aggregate_metadata = true; + for (const auto& prefix : Split(option_pair[1], "#", false)) { + options.aggregate_metadata_prefixes.emplace(prefix); + GOOGLE_LOG(INFO) << prefix; + } + } else if (option_pair[0] == "internal") { + options.is_descriptor = true; + } else if (option_pair[0] == "internal_generate_c_wkt") { + GenerateCWellKnownTypes(files, generator_context); + } else { + GOOGLE_LOG(FATAL) << "Unknown codegen option: " << option_pair[0]; + } + } + + for (auto file : files) { + if (!Generate(file, options, generator_context, error)) { + return false; + } + } return true; } diff --git a/src/google/protobuf/compiler/php/php_generator.h b/src/google/protobuf/compiler/php/php_generator.h index ce2b000adb1af..17cb59c08b6a2 100644 --- a/src/google/protobuf/compiler/php/php_generator.h +++ b/src/google/protobuf/compiler/php/php_generator.h @@ -32,26 +32,61 @@ #define GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__ #include +#include #include +#include + namespace google { namespace protobuf { namespace compiler { namespace php { -class LIBPROTOC_EXPORT Generator - : public google::protobuf::compiler::CodeGenerator { +struct Options; + +class PROTOC_EXPORT Generator : public CodeGenerator { + public: virtual bool Generate( const FileDescriptor* file, - const string& parameter, + const std::string& parameter, + GeneratorContext* generator_context, + std::string* error) const override; + + bool GenerateAll(const std::vector& files, + const std::string& parameter, + GeneratorContext* generator_context, + std::string* error) const override; + + uint64_t GetSupportedFeatures() const override { + return FEATURE_PROTO3_OPTIONAL; + } + + private: + bool Generate( + const FileDescriptor* file, + const Options& options, GeneratorContext* generator_context, - string* error) const; + std::string* error) const; }; +// To skip reserved keywords in php, some generated classname are prefixed. +// Other code generators may need following API to figure out the actual +// classname. +PROTOC_EXPORT std::string GeneratedClassName(const Descriptor* desc); +PROTOC_EXPORT std::string GeneratedClassName(const EnumDescriptor* desc); +PROTOC_EXPORT std::string GeneratedClassName(const ServiceDescriptor* desc); + +inline bool IsWrapperType(const FieldDescriptor* descriptor) { + return descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto"; +} + } // namespace php } // namespace compiler } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc index cb5e37bb7f131..cb7801d53c967 100644 --- a/src/google/protobuf/compiler/plugin.cc +++ b/src/google/protobuf/compiler/plugin.cc @@ -41,29 +41,29 @@ #include #endif -#include #include #include #include #include -#include #include +#include +#include -#if defined(_MSC_VER) -// DO NOT include , instead create functions in io_win32.{h,cc} and import -// them like we do below. -using google::protobuf::internal::win32::setmode; -#endif namespace google { namespace protobuf { namespace compiler { +#if defined(_WIN32) +// DO NOT include , instead create functions in io_win32.{h,cc} and import +// them like we do below. +using google::protobuf::io::win32::setmode; +#endif + class GeneratorResponseContext : public GeneratorContext { public: GeneratorResponseContext( - const Version& compiler_version, - CodeGeneratorResponse* response, + const Version& compiler_version, CodeGeneratorResponse* response, const std::vector& parsed_files) : compiler_version_(compiler_version), response_(response), @@ -72,17 +72,27 @@ class GeneratorResponseContext : public GeneratorContext { // implements GeneratorContext -------------------------------------- - virtual io::ZeroCopyOutputStream* Open(const string& filename) { + virtual io::ZeroCopyOutputStream* Open(const std::string& filename) { CodeGeneratorResponse::File* file = response_->add_file(); file->set_name(filename); return new io::StringOutputStream(file->mutable_content()); } virtual io::ZeroCopyOutputStream* OpenForInsert( - const string& filename, const string& insertion_point) { + const std::string& filename, const std::string& insertion_point) { + CodeGeneratorResponse::File* file = response_->add_file(); + file->set_name(filename); + file->set_insertion_point(insertion_point); + return new io::StringOutputStream(file->mutable_content()); + } + + virtual io::ZeroCopyOutputStream* OpenForInsertWithGeneratedCodeInfo( + const std::string& filename, const std::string& insertion_point, + const google::protobuf::GeneratedCodeInfo& info) { CodeGeneratorResponse::File* file = response_->add_file(); file->set_name(filename); file->set_insertion_point(insertion_point); + *file->mutable_generated_code_info() = info; return new io::StringOutputStream(file->mutable_content()); } @@ -101,8 +111,8 @@ class GeneratorResponseContext : public GeneratorContext { }; bool GenerateCode(const CodeGeneratorRequest& request, - const CodeGenerator& generator, CodeGeneratorResponse* response, - string* error_msg) { + const CodeGenerator& generator, + CodeGeneratorResponse* response, std::string* error_msg) { DescriptorPool pool; for (int i = 0; i < request.proto_file_size(); i++) { const FileDescriptor* file = pool.BuildFile(request.proto_file(i)); @@ -116,24 +126,28 @@ bool GenerateCode(const CodeGeneratorRequest& request, for (int i = 0; i < request.file_to_generate_size(); i++) { parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i))); if (parsed_files.back() == NULL) { - *error_msg = "protoc asked plugin to generate a file but " - "did not provide a descriptor for the file: " + - request.file_to_generate(i); + *error_msg = + "protoc asked plugin to generate a file but " + "did not provide a descriptor for the file: " + + request.file_to_generate(i); return false; } } - GeneratorResponseContext context( - request.compiler_version(), response, parsed_files); + GeneratorResponseContext context(request.compiler_version(), response, + parsed_files); + + std::string error; + bool succeeded = generator.GenerateAll(parsed_files, request.parameter(), + &context, &error); - string error; - bool succeeded = generator.GenerateAll( - parsed_files, request.parameter(), &context, &error); + response->set_supported_features(generator.GetSupportedFeatures()); if (!succeeded && error.empty()) { - error = "Code generator returned false but provided no error " - "description."; + error = + "Code generator returned false but provided no error " + "description."; } if (!error.empty()) { response->set_error(error); @@ -161,7 +175,7 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { return 1; } - string error_msg; + std::string error_msg; CodeGeneratorResponse response; if (GenerateCode(request, *generator, &response, &error_msg)) { diff --git a/src/google/protobuf/compiler/plugin.h b/src/google/protobuf/compiler/plugin.h index d2793a9ff13b2..de581c12e5144 100644 --- a/src/google/protobuf/compiler/plugin.h +++ b/src/google/protobuf/compiler/plugin.h @@ -64,27 +64,31 @@ #include -#include +#include + namespace google { namespace protobuf { namespace compiler { -class CodeGenerator; // code_generator.h +class CodeGenerator; // code_generator.h class CodeGeneratorRequest; class CodeGeneratorResponse; // Implements main() for a protoc plugin exposing the given code generator. -LIBPROTOC_EXPORT int PluginMain(int argc, char* argv[], const CodeGenerator* generator); +PROTOC_EXPORT int PluginMain(int argc, char* argv[], + const CodeGenerator* generator); // Generates code using the given code generator. Returns true if the code -// generation is successful. If the code geneartion fails, error_msg may be +// generation is successful. If the code generation fails, error_msg may be // populated to describe the failure cause. bool GenerateCode(const CodeGeneratorRequest& request, - const CodeGenerator& generator, CodeGeneratorResponse* response, - string* error_msg); + const CodeGenerator& generator, + CodeGeneratorResponse* response, std::string* error_msg); } // namespace compiler } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__ diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 07883a3737644..f59504d00fd62 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -1,246 +1,251 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/compiler/plugin.proto -#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include #include -#include -#include -#include #include -#include +#include +#include #include #include #include #include // @@protoc_insertion_point(includes) +#include -namespace google { -namespace protobuf { +PROTOBUF_PRAGMA_INIT_SEG +PROTOBUF_NAMESPACE_OPEN namespace compiler { -class VersionDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _Version_default_instance_; -class CodeGeneratorRequestDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _CodeGeneratorRequest_default_instance_; -class CodeGeneratorResponse_FileDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _CodeGeneratorResponse_File_default_instance_; -class CodeGeneratorResponseDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _CodeGeneratorResponse_default_instance_; - -namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto { - - -namespace { - -::google::protobuf::Metadata file_level_metadata[4]; - -} // namespace - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField - const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0}, +constexpr Version::Version( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : suffix_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , major_(0) + , minor_(0) + , patch_(0){} +struct VersionDefaultTypeInternal { + constexpr VersionDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~VersionDefaultTypeInternal() {} + union { + Version _instance; + }; }; - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField - const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - ::google::protobuf::internal::AuxillaryParseTableField(), +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT VersionDefaultTypeInternal _Version_default_instance_; +constexpr CodeGeneratorRequest::CodeGeneratorRequest( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : file_to_generate_() + , proto_file_() + , parameter_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , compiler_version_(nullptr){} +struct CodeGeneratorRequestDefaultTypeInternal { + constexpr CodeGeneratorRequestDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~CodeGeneratorRequestDefaultTypeInternal() {} + union { + CodeGeneratorRequest _instance; + }; }; -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const - TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_; +constexpr CodeGeneratorResponse_File::CodeGeneratorResponse_File( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , insertion_point_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , content_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , generated_code_info_(nullptr){} +struct CodeGeneratorResponse_FileDefaultTypeInternal { + constexpr CodeGeneratorResponse_FileDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~CodeGeneratorResponse_FileDefaultTypeInternal() {} + union { + CodeGeneratorResponse_File _instance; + }; }; - -const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Version, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Version, _internal_metadata_), +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_; +constexpr CodeGeneratorResponse::CodeGeneratorResponse( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : file_() + , error_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , supported_features_(PROTOBUF_ULONGLONG(0)){} +struct CodeGeneratorResponseDefaultTypeInternal { + constexpr CodeGeneratorResponseDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~CodeGeneratorResponseDefaultTypeInternal() {} + union { + CodeGeneratorResponse _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_; +} // namespace compiler +PROTOBUF_NAMESPACE_CLOSE +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[4]; +static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto[1]; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto = nullptr; + +const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::Version, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::Version, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Version, major_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Version, minor_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Version, patch_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Version, suffix_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::Version, major_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::Version, minor_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::Version, patch_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::Version, suffix_), 1, 2, 3, 0, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, file_to_generate_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, parameter_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, proto_file_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, compiler_version_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, file_to_generate_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, parameter_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, proto_file_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, compiler_version_), ~0u, 0, ~0u, 1, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, insertion_point_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, content_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, insertion_point_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, content_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, generated_code_info_), 0, 1, 2, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _internal_metadata_), + 3, + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, error_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, file_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, error_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, supported_features_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, file_), 0, + 1, ~0u, }; -static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { 0, 9, sizeof(Version)}, - { 13, 22, sizeof(CodeGeneratorRequest)}, - { 26, 34, sizeof(CodeGeneratorResponse_File)}, - { 37, 44, sizeof(CodeGeneratorResponse)}, +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, 9, sizeof(PROTOBUF_NAMESPACE_ID::compiler::Version)}, + { 13, 22, sizeof(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest)}, + { 26, 35, sizeof(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File)}, + { 39, 47, sizeof(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse)}, }; -static ::google::protobuf::Message const * const file_default_instances[] = { - reinterpret_cast(&_Version_default_instance_), - reinterpret_cast(&_CodeGeneratorRequest_default_instance_), - reinterpret_cast(&_CodeGeneratorResponse_File_default_instance_), - reinterpret_cast(&_CodeGeneratorResponse_default_instance_), +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorRequest_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_File_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_default_instance_), }; -namespace { - -void protobuf_AssignDescriptors() { - AddDescriptors(); - ::google::protobuf::MessageFactory* factory = NULL; - AssignDescriptors( - "google/protobuf/compiler/plugin.proto", schemas, file_default_instances, TableStruct::offsets, factory, - file_level_metadata, NULL, NULL); -} - -void protobuf_AssignDescriptorsOnce() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors); -} - -void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; -void protobuf_RegisterTypes(const ::std::string&) { - protobuf_AssignDescriptorsOnce(); - ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 4); -} - -} // namespace -void TableStruct::InitDefaultsImpl() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - ::google::protobuf::internal::InitProtobufDefaults(); - ::google::protobuf::protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - _Version_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_Version_default_instance_);_CodeGeneratorRequest_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_CodeGeneratorRequest_default_instance_);_CodeGeneratorResponse_File_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_CodeGeneratorResponse_File_default_instance_);_CodeGeneratorResponse_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_CodeGeneratorResponse_default_instance_);_CodeGeneratorRequest_default_instance_._instance.get_mutable()->compiler_version_ = const_cast< ::google::protobuf::compiler::Version*>( - ::google::protobuf::compiler::Version::internal_default_instance()); -} - -void InitDefaults() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl); -} -namespace { -void AddDescriptorsImpl() { - InitDefaults(); - static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - "\n%google/protobuf/compiler/plugin.proto\022" - "\030google.protobuf.compiler\032 google/protob" - "uf/descriptor.proto\"F\n\007Version\022\r\n\005major\030" - "\001 \001(\005\022\r\n\005minor\030\002 \001(\005\022\r\n\005patch\030\003 \001(\005\022\016\n\006s" - "uffix\030\004 \001(\t\"\272\001\n\024CodeGeneratorRequest\022\030\n\020" - "file_to_generate\030\001 \003(\t\022\021\n\tparameter\030\002 \001(" - "\t\0228\n\nproto_file\030\017 \003(\0132$.google.protobuf." - "FileDescriptorProto\022;\n\020compiler_version\030" - "\003 \001(\0132!.google.protobuf.compiler.Version" - "\"\252\001\n\025CodeGeneratorResponse\022\r\n\005error\030\001 \001(" - "\t\022B\n\004file\030\017 \003(\01324.google.protobuf.compil" - "er.CodeGeneratorResponse.File\032>\n\004File\022\014\n" - "\004name\030\001 \001(\t\022\027\n\017insertion_point\030\002 \001(\t\022\017\n\007" - "content\030\017 \001(\tBg\n\034com.google.protobuf.com" - "pilerB\014PluginProtosZ9github.amrom.workers.dev/golang/p" - "rotobuf/protoc-gen-go/plugin;plugin_go" - }; - ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( - descriptor, 638); - ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( - "google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes); - ::google::protobuf::protobuf_google_2fprotobuf_2fdescriptor_2eproto::AddDescriptors(); +const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n%google/protobuf/compiler/plugin.proto\022" + "\030google.protobuf.compiler\032 google/protob" + "uf/descriptor.proto\"F\n\007Version\022\r\n\005major\030" + "\001 \001(\005\022\r\n\005minor\030\002 \001(\005\022\r\n\005patch\030\003 \001(\005\022\016\n\006s" + "uffix\030\004 \001(\t\"\272\001\n\024CodeGeneratorRequest\022\030\n\020" + "file_to_generate\030\001 \003(\t\022\021\n\tparameter\030\002 \001(" + "\t\0228\n\nproto_file\030\017 \003(\0132$.google.protobuf." + "FileDescriptorProto\022;\n\020compiler_version\030" + "\003 \001(\0132!.google.protobuf.compiler.Version" + "\"\301\002\n\025CodeGeneratorResponse\022\r\n\005error\030\001 \001(" + "\t\022\032\n\022supported_features\030\002 \001(\004\022B\n\004file\030\017 " + "\003(\01324.google.protobuf.compiler.CodeGener" + "atorResponse.File\032\177\n\004File\022\014\n\004name\030\001 \001(\t\022" + "\027\n\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(" + "\t\022\?\n\023generated_code_info\030\020 \001(\0132\".google." + "protobuf.GeneratedCodeInfo\"8\n\007Feature\022\020\n" + "\014FEATURE_NONE\020\000\022\033\n\027FEATURE_PROTO3_OPTION" + "AL\020\001BW\n\034com.google.protobuf.compilerB\014Pl" + "uginProtosZ)google.golang.org/protobuf/t" + "ypes/pluginpb" + ; +static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps[1] = { + &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, +}; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto = { + false, false, 773, descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto, "google/protobuf/compiler/plugin.proto", + &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once, descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps, 1, 4, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata +descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(int index) { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto); + return descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[index]; } -} // anonymous namespace -void AddDescriptors() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl); +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fcompiler_2fplugin_2eproto(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto); +PROTOBUF_NAMESPACE_OPEN +namespace compiler { +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* CodeGeneratorResponse_Feature_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto[0]; } -// Force AddDescriptors() to be called at dynamic initialization time. -struct StaticDescriptorInitializer { - StaticDescriptorInitializer() { - AddDescriptors(); +bool CodeGeneratorResponse_Feature_IsValid(int value) { + switch (value) { + case 0: + case 1: + return true; + default: + return false; } -} static_descriptor_initializer; - -} // namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto +} +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900) +constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::FEATURE_NONE; +constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL; +constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::Feature_MIN; +constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::Feature_MAX; +constexpr int CodeGeneratorResponse::Feature_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900) // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int Version::kMajorFieldNumber; -const int Version::kMinorFieldNumber; -const int Version::kPatchFieldNumber; -const int Version::kSuffixFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -Version::Version() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults(); +class Version::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_major(HasBits* has_bits) { + (*has_bits)[0] |= 2u; } + static void set_has_minor(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static void set_has_patch(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } + static void set_has_suffix(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } +}; + +Version::Version(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.compiler.Version) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.Version) } Version::Version(const Version& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - suffix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_suffix()) { - suffix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.suffix_); + : ::PROTOBUF_NAMESPACE_ID::Message(), + _has_bits_(from._has_bits_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + suffix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_suffix()) { + suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_suffix(), + GetArena()); } ::memcpy(&major_, &from.major_, static_cast(reinterpret_cast(&patch_) - @@ -249,229 +254,157 @@ Version::Version(const Version& from) } void Version::SharedCtor() { - _cached_size_ = 0; - suffix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - ::memset(&major_, 0, static_cast( - reinterpret_cast(&patch_) - - reinterpret_cast(&major_)) + sizeof(patch_)); +suffix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&major_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&patch_) - + reinterpret_cast(&major_)) + sizeof(patch_)); } Version::~Version() { // @@protoc_insertion_point(destructor:google.protobuf.compiler.Version) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void Version::SharedDtor() { - suffix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + suffix_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } -void Version::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void Version::ArenaDtor(void* object) { + Version* _this = reinterpret_cast< Version* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* Version::descriptor() { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void Version::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -const Version& Version::default_instance() { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -Version* Version::New(::google::protobuf::Arena* arena) const { - Version* n = new Version; - if (arena != NULL) { - arena->Own(n); - } - return n; +void Version::SetCachedSize(int size) const { + _cached_size_.Set(size); } void Version::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.Version) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - if (has_suffix()) { - GOOGLE_DCHECK(!suffix_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*suffix_.UnsafeRawStringPointer())->clear(); - } cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 14u) { + if (cached_has_bits & 0x00000001u) { + suffix_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x0000000eu) { ::memset(&major_, 0, static_cast( reinterpret_cast(&patch_) - reinterpret_cast(&major_)) + sizeof(patch_)); } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool Version::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.compiler.Version) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional int32 major = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { - set_has_major(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, &major_))); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* Version::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional int32 major = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + _Internal::set_has_major(&has_bits); + major_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional int32 minor = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) { - set_has_minor(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, &minor_))); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + _Internal::set_has_minor(&has_bits); + minor_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional int32 patch = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) { - set_has_patch(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, &patch_))); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + _Internal::set_has_patch(&has_bits); + patch_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string suffix = 4; - case 4: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_suffix())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->suffix().data(), static_cast(this->suffix().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.compiler.Version.suffix"); - } else { - goto handle_unusual; - } - break; - } - + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + auto str = _internal_mutable_suffix(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.compiler.Version.suffix"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.compiler.Version) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.Version) - return false; -#undef DO_ + ptr = nullptr; + goto success; +#undef CHK_ } -void Version::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.Version) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional int32 major = 1; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->major(), output); - } - - // optional int32 minor = 2; - if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->minor(), output); - } - - // optional int32 patch = 3; - if (cached_has_bits & 0x00000008u) { - ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->patch(), output); - } - - // optional string suffix = 4; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->suffix().data(), static_cast(this->suffix().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.Version.suffix"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 4, this->suffix(), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.Version) -} - -::google::protobuf::uint8* Version::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* Version::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.Version) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional int32 major = 1; if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->major(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_major(), target); } // optional int32 minor = 2; if (cached_has_bits & 0x00000004u) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->minor(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_minor(), target); } // optional int32 patch = 3; if (cached_has_bits & 0x00000008u) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->patch(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_patch(), target); } // optional string suffix = 4; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->suffix().data(), static_cast(this->suffix().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_suffix().data(), static_cast(this->_internal_suffix().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.compiler.Version.suffix"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 4, this->suffix(), target); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_suffix(), target); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.Version) return target; @@ -481,57 +414,59 @@ size_t Version::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.Version) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } - if (_has_bits_[0 / 32] & 15u) { + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { // optional string suffix = 4; - if (has_suffix()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->suffix()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_suffix()); } // optional int32 major = 1; - if (has_major()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - this->major()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_major()); } // optional int32 minor = 2; - if (has_minor()) { + if (cached_has_bits & 0x00000004u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - this->minor()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_minor()); } // optional int32 patch = 3; - if (has_patch()) { + if (cached_has_bits & 0x00000008u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - this->patch()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_patch()); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void Version::MergeFrom(const ::google::protobuf::Message& from) { +void Version::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.Version) GOOGLE_DCHECK_NE(&from, this); const Version* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.Version) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.Version) MergeFrom(*source); @@ -541,15 +476,14 @@ void Version::MergeFrom(const ::google::protobuf::Message& from) { void Version::MergeFrom(const Version& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.Version) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 15u) { + if (cached_has_bits & 0x0000000fu) { if (cached_has_bits & 0x00000001u) { - set_has_suffix(); - suffix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.suffix_); + _internal_set_suffix(from._internal_suffix()); } if (cached_has_bits & 0x00000002u) { major_ = from.major_; @@ -564,7 +498,7 @@ void Version::MergeFrom(const Version& from) { } } -void Version::CopyFrom(const ::google::protobuf::Message& from) { +void Version::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.Version) if (&from == this) return; Clear(); @@ -582,446 +516,244 @@ bool Version::IsInitialized() const { return true; } -void Version::Swap(Version* other) { - if (other == this) return; - InternalSwap(other); -} void Version::InternalSwap(Version* other) { using std::swap; - suffix_.Swap(&other->suffix_); - swap(major_, other->major_); - swap(minor_, other->minor_); - swap(patch_, other->patch_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); + suffix_.Swap(&other->suffix_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(Version, patch_) + + sizeof(Version::patch_) + - PROTOBUF_FIELD_OFFSET(Version, major_)>( + reinterpret_cast(&major_), + reinterpret_cast(&other->major_)); } -::google::protobuf::Metadata Version::GetMetadata() const { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages]; +::PROTOBUF_NAMESPACE_ID::Metadata Version::GetMetadata() const { + return GetMetadataStatic(); } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// Version -// optional int32 major = 1; -bool Version::has_major() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void Version::set_has_major() { - _has_bits_[0] |= 0x00000002u; -} -void Version::clear_has_major() { - _has_bits_[0] &= ~0x00000002u; -} -void Version::clear_major() { - major_ = 0; - clear_has_major(); -} -::google::protobuf::int32 Version::major() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.major) - return major_; -} -void Version::set_major(::google::protobuf::int32 value) { - set_has_major(); - major_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.major) -} +// =================================================================== -// optional int32 minor = 2; -bool Version::has_minor() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -void Version::set_has_minor() { - _has_bits_[0] |= 0x00000004u; -} -void Version::clear_has_minor() { - _has_bits_[0] &= ~0x00000004u; -} -void Version::clear_minor() { - minor_ = 0; - clear_has_minor(); -} -::google::protobuf::int32 Version::minor() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.minor) - return minor_; -} -void Version::set_minor(::google::protobuf::int32 value) { - set_has_minor(); - minor_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.minor) -} +class CodeGeneratorRequest::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_parameter(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static const PROTOBUF_NAMESPACE_ID::compiler::Version& compiler_version(const CodeGeneratorRequest* msg); + static void set_has_compiler_version(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; -// optional int32 patch = 3; -bool Version::has_patch() const { - return (_has_bits_[0] & 0x00000008u) != 0; -} -void Version::set_has_patch() { - _has_bits_[0] |= 0x00000008u; -} -void Version::clear_has_patch() { - _has_bits_[0] &= ~0x00000008u; +const PROTOBUF_NAMESPACE_ID::compiler::Version& +CodeGeneratorRequest::_Internal::compiler_version(const CodeGeneratorRequest* msg) { + return *msg->compiler_version_; } -void Version::clear_patch() { - patch_ = 0; - clear_has_patch(); -} -::google::protobuf::int32 Version::patch() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.patch) - return patch_; -} -void Version::set_patch(::google::protobuf::int32 value) { - set_has_patch(); - patch_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.patch) -} - -// optional string suffix = 4; -bool Version::has_suffix() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void Version::set_has_suffix() { - _has_bits_[0] |= 0x00000001u; -} -void Version::clear_has_suffix() { - _has_bits_[0] &= ~0x00000001u; -} -void Version::clear_suffix() { - suffix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_suffix(); -} -const ::std::string& Version::suffix() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.suffix) - return suffix_.GetNoArena(); -} -void Version::set_suffix(const ::std::string& value) { - set_has_suffix(); - suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.suffix) -} -#if LANG_CXX11 -void Version::set_suffix(::std::string&& value) { - set_has_suffix(); - suffix_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.Version.suffix) -} -#endif -void Version::set_suffix(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_suffix(); - suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.Version.suffix) -} -void Version::set_suffix(const char* value, size_t size) { - set_has_suffix(); - suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.Version.suffix) -} -::std::string* Version::mutable_suffix() { - set_has_suffix(); - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.Version.suffix) - return suffix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* Version::release_suffix() { - // @@protoc_insertion_point(field_release:google.protobuf.compiler.Version.suffix) - clear_has_suffix(); - return suffix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void Version::set_allocated_suffix(::std::string* suffix) { - if (suffix != NULL) { - set_has_suffix(); - } else { - clear_has_suffix(); - } - suffix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), suffix); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.Version.suffix) +void CodeGeneratorRequest::clear_proto_file() { + proto_file_.Clear(); } - -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS - -// =================================================================== - -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int CodeGeneratorRequest::kFileToGenerateFieldNumber; -const int CodeGeneratorRequest::kParameterFieldNumber; -const int CodeGeneratorRequest::kProtoFileFieldNumber; -const int CodeGeneratorRequest::kCompilerVersionFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -CodeGeneratorRequest::CodeGeneratorRequest() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults(); - } +CodeGeneratorRequest::CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + file_to_generate_(arena), + proto_file_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorRequest) } CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), _has_bits_(from._has_bits_), - _cached_size_(0), file_to_generate_(from.file_to_generate_), proto_file_(from.proto_file_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - parameter_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_parameter()) { - parameter_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.parameter_); - } - if (from.has_compiler_version()) { - compiler_version_ = new ::google::protobuf::compiler::Version(*from.compiler_version_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + parameter_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_parameter()) { + parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_parameter(), + GetArena()); + } + if (from._internal_has_compiler_version()) { + compiler_version_ = new PROTOBUF_NAMESPACE_ID::compiler::Version(*from.compiler_version_); } else { - compiler_version_ = NULL; + compiler_version_ = nullptr; } // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest) } void CodeGeneratorRequest::SharedCtor() { - _cached_size_ = 0; - parameter_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - compiler_version_ = NULL; +parameter_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +compiler_version_ = nullptr; } CodeGeneratorRequest::~CodeGeneratorRequest() { // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorRequest) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void CodeGeneratorRequest::SharedDtor() { - parameter_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + parameter_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (this != internal_default_instance()) delete compiler_version_; } -void CodeGeneratorRequest::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* CodeGeneratorRequest::descriptor() { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void CodeGeneratorRequest::ArenaDtor(void* object) { + CodeGeneratorRequest* _this = reinterpret_cast< CodeGeneratorRequest* >(object); + (void)_this; } - -const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults(); - return *internal_default_instance(); +void CodeGeneratorRequest::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -CodeGeneratorRequest* CodeGeneratorRequest::New(::google::protobuf::Arena* arena) const { - CodeGeneratorRequest* n = new CodeGeneratorRequest; - if (arena != NULL) { - arena->Own(n); - } - return n; +void CodeGeneratorRequest::SetCachedSize(int size) const { + _cached_size_.Set(size); } void CodeGeneratorRequest::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; file_to_generate_.Clear(); proto_file_.Clear(); cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - GOOGLE_DCHECK(!parameter_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*parameter_.UnsafeRawStringPointer())->clear(); + parameter_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000002u) { - GOOGLE_DCHECK(compiler_version_ != NULL); - compiler_version_->::google::protobuf::compiler::Version::Clear(); + GOOGLE_DCHECK(compiler_version_ != nullptr); + compiler_version_->Clear(); } } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool CodeGeneratorRequest::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorRequest) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // repeated string file_to_generate = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->add_file_to_generate())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->file_to_generate(this->file_to_generate_size() - 1).data(), - static_cast(this->file_to_generate(this->file_to_generate_size() - 1).length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate"); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* CodeGeneratorRequest::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // repeated string file_to_generate = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + ptr -= 1; + do { + ptr += 1; + auto str = _internal_add_file_to_generate(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate"); + #endif // !NDEBUG + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); + } else goto handle_unusual; + continue; // optional string parameter = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_parameter())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->parameter().data(), static_cast(this->parameter().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.compiler.CodeGeneratorRequest.parameter"); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + auto str = _internal_mutable_parameter(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorRequest.parameter"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional .google.protobuf.compiler.Version compiler_version = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, mutable_compiler_version())); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + ptr = ctx->ParseMessage(_internal_mutable_compiler_version(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated .google.protobuf.FileDescriptorProto proto_file = 15; - case 15: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_proto_file())); - } else { - goto handle_unusual; - } - break; - } - + case 15: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 122)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_proto_file(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<122>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorRequest) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorRequest) - return false; -#undef DO_ + ptr = nullptr; + goto success; +#undef CHK_ } -void CodeGeneratorRequest::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorRequest) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // repeated string file_to_generate = 1; - for (int i = 0, n = this->file_to_generate_size(); i < n; i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->file_to_generate(i).data(), static_cast(this->file_to_generate(i).length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate"); - ::google::protobuf::internal::WireFormatLite::WriteString( - 1, this->file_to_generate(i), output); - } - - cached_has_bits = _has_bits_[0]; - // optional string parameter = 2; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->parameter().data(), static_cast(this->parameter().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorRequest.parameter"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 2, this->parameter(), output); - } - - // optional .google.protobuf.compiler.Version compiler_version = 3; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 3, *this->compiler_version_, output); - } - - // repeated .google.protobuf.FileDescriptorProto proto_file = 15; - for (unsigned int i = 0, - n = static_cast(this->proto_file_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 15, this->proto_file(static_cast(i)), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorRequest) -} - -::google::protobuf::uint8* CodeGeneratorRequest::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* CodeGeneratorRequest::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorRequest) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // repeated string file_to_generate = 1; - for (int i = 0, n = this->file_to_generate_size(); i < n; i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->file_to_generate(i).data(), static_cast(this->file_to_generate(i).length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + for (int i = 0, n = this->_internal_file_to_generate_size(); i < n; i++) { + const auto& s = this->_internal_file_to_generate(i); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + s.data(), static_cast(s.length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate"); - target = ::google::protobuf::internal::WireFormatLite:: - WriteStringToArray(1, this->file_to_generate(i), target); + target = stream->WriteString(1, s, target); } cached_has_bits = _has_bits_[0]; // optional string parameter = 2; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->parameter().data(), static_cast(this->parameter().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_parameter().data(), static_cast(this->_internal_parameter().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.compiler.CodeGeneratorRequest.parameter"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 2, this->parameter(), target); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_parameter(), target); } // optional .google.protobuf.compiler.Version compiler_version = 3; if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 3, *this->compiler_version_, deterministic, target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 3, _Internal::compiler_version(this), target, stream); } // repeated .google.protobuf.FileDescriptorProto proto_file = 15; for (unsigned int i = 0, - n = static_cast(this->proto_file_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 15, this->proto_file(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_proto_file_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(15, this->_internal_proto_file(i), target, stream); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorRequest) return target; @@ -1031,62 +763,60 @@ size_t CodeGeneratorRequest::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorRequest) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated string file_to_generate = 1; total_size += 1 * - ::google::protobuf::internal::FromIntSize(this->file_to_generate_size()); - for (int i = 0, n = this->file_to_generate_size(); i < n; i++) { - total_size += ::google::protobuf::internal::WireFormatLite::StringSize( - this->file_to_generate(i)); + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(file_to_generate_.size()); + for (int i = 0, n = file_to_generate_.size(); i < n; i++) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + file_to_generate_.Get(i)); } // repeated .google.protobuf.FileDescriptorProto proto_file = 15; - { - unsigned int count = static_cast(this->proto_file_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->proto_file(static_cast(i))); - } + total_size += 1UL * this->_internal_proto_file_size(); + for (const auto& msg : this->proto_file_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - if (_has_bits_[0 / 32] & 3u) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000003u) { // optional string parameter = 2; - if (has_parameter()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->parameter()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_parameter()); } // optional .google.protobuf.compiler.Version compiler_version = 3; - if (has_compiler_version()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - *this->compiler_version_); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *compiler_version_); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) { +void CodeGeneratorRequest::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest) GOOGLE_DCHECK_NE(&from, this); const CodeGeneratorRequest* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorRequest) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorRequest) MergeFrom(*source); @@ -1096,25 +826,24 @@ void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) { void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; file_to_generate_.MergeFrom(from.file_to_generate_); proto_file_.MergeFrom(from.proto_file_); cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - set_has_parameter(); - parameter_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.parameter_); + _internal_set_parameter(from._internal_parameter()); } if (cached_has_bits & 0x00000002u) { - mutable_compiler_version()->::google::protobuf::compiler::Version::MergeFrom(from.compiler_version()); + _internal_mutable_compiler_version()->PROTOBUF_NAMESPACE_ID::compiler::Version::MergeFrom(from._internal_compiler_version()); } } } -void CodeGeneratorRequest::CopyFrom(const ::google::protobuf::Message& from) { +void CodeGeneratorRequest::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorRequest) if (&from == this) return; Clear(); @@ -1129,512 +858,262 @@ void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) { } bool CodeGeneratorRequest::IsInitialized() const { - if (!::google::protobuf::internal::AllAreInitialized(this->proto_file())) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(proto_file_)) return false; return true; } -void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) { - if (other == this) return; - InternalSwap(other); -} void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); file_to_generate_.InternalSwap(&other->file_to_generate_); proto_file_.InternalSwap(&other->proto_file_); - parameter_.Swap(&other->parameter_); + parameter_.Swap(&other->parameter_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); swap(compiler_version_, other->compiler_version_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); } -::google::protobuf::Metadata CodeGeneratorRequest::GetMetadata() const { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages]; +::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorRequest::GetMetadata() const { + return GetMetadataStatic(); } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// CodeGeneratorRequest -// repeated string file_to_generate = 1; -int CodeGeneratorRequest::file_to_generate_size() const { - return file_to_generate_.size(); -} -void CodeGeneratorRequest::clear_file_to_generate() { - file_to_generate_.Clear(); -} -const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) - return file_to_generate_.Get(index); -} -::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) - return file_to_generate_.Mutable(index); -} -void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) { - // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) - file_to_generate_.Mutable(index)->assign(value); -} -#if LANG_CXX11 -void CodeGeneratorRequest::set_file_to_generate(int index, ::std::string&& value) { - // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) - file_to_generate_.Mutable(index)->assign(std::move(value)); -} -#endif -void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) { - GOOGLE_DCHECK(value != NULL); - file_to_generate_.Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) -} -void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) { - file_to_generate_.Mutable(index)->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) -} -::std::string* CodeGeneratorRequest::add_file_to_generate() { - // @@protoc_insertion_point(field_add_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) - return file_to_generate_.Add(); -} -void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) { - file_to_generate_.Add()->assign(value); - // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) -} -#if LANG_CXX11 -void CodeGeneratorRequest::add_file_to_generate(::std::string&& value) { - file_to_generate_.Add(std::move(value)); - // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) -} -#endif -void CodeGeneratorRequest::add_file_to_generate(const char* value) { - GOOGLE_DCHECK(value != NULL); - file_to_generate_.Add()->assign(value); - // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) -} -void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) { - file_to_generate_.Add()->assign(reinterpret_cast(value), size); - // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) -} -const ::google::protobuf::RepeatedPtrField< ::std::string>& -CodeGeneratorRequest::file_to_generate() const { - // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) - return file_to_generate_; -} -::google::protobuf::RepeatedPtrField< ::std::string>* -CodeGeneratorRequest::mutable_file_to_generate() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) - return &file_to_generate_; -} - -// optional string parameter = 2; -bool CodeGeneratorRequest::has_parameter() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void CodeGeneratorRequest::set_has_parameter() { - _has_bits_[0] |= 0x00000001u; -} -void CodeGeneratorRequest::clear_has_parameter() { - _has_bits_[0] &= ~0x00000001u; -} -void CodeGeneratorRequest::clear_parameter() { - parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_parameter(); -} -const ::std::string& CodeGeneratorRequest::parameter() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter) - return parameter_.GetNoArena(); -} -void CodeGeneratorRequest::set_parameter(const ::std::string& value) { - set_has_parameter(); - parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter) -} -#if LANG_CXX11 -void CodeGeneratorRequest::set_parameter(::std::string&& value) { - set_has_parameter(); - parameter_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorRequest.parameter) -} -#endif -void CodeGeneratorRequest::set_parameter(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_parameter(); - parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter) -} -void CodeGeneratorRequest::set_parameter(const char* value, size_t size) { - set_has_parameter(); - parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter) -} -::std::string* CodeGeneratorRequest::mutable_parameter() { - set_has_parameter(); - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter) - return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* CodeGeneratorRequest::release_parameter() { - // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.parameter) - clear_has_parameter(); - return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) { - if (parameter != NULL) { - set_has_parameter(); - } else { - clear_has_parameter(); +// =================================================================== + +class CodeGeneratorResponse_File::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } - parameter_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter) -} + static void set_has_insertion_point(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_content(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& generated_code_info(const CodeGeneratorResponse_File* msg); + static void set_has_generated_code_info(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } +}; -// repeated .google.protobuf.FileDescriptorProto proto_file = 15; -int CodeGeneratorRequest::proto_file_size() const { - return proto_file_.size(); -} -void CodeGeneratorRequest::clear_proto_file() { - proto_file_.Clear(); +const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& +CodeGeneratorResponse_File::_Internal::generated_code_info(const CodeGeneratorResponse_File* msg) { + return *msg->generated_code_info_; } -const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file) - return proto_file_.Get(index); -} -::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file) - return proto_file_.Mutable(index); -} -::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() { - // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file) - return proto_file_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* -CodeGeneratorRequest::mutable_proto_file() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) - return &proto_file_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& -CodeGeneratorRequest::proto_file() const { - // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) - return proto_file_; -} - -// optional .google.protobuf.compiler.Version compiler_version = 3; -bool CodeGeneratorRequest::has_compiler_version() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void CodeGeneratorRequest::set_has_compiler_version() { - _has_bits_[0] |= 0x00000002u; -} -void CodeGeneratorRequest::clear_has_compiler_version() { - _has_bits_[0] &= ~0x00000002u; -} -void CodeGeneratorRequest::clear_compiler_version() { - if (compiler_version_ != NULL) compiler_version_->::google::protobuf::compiler::Version::Clear(); - clear_has_compiler_version(); -} -const ::google::protobuf::compiler::Version& CodeGeneratorRequest::compiler_version() const { - const ::google::protobuf::compiler::Version* p = compiler_version_; - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.compiler_version) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::compiler::_Version_default_instance_); -} -::google::protobuf::compiler::Version* CodeGeneratorRequest::mutable_compiler_version() { - set_has_compiler_version(); - if (compiler_version_ == NULL) { - compiler_version_ = new ::google::protobuf::compiler::Version; - } - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.compiler_version) - return compiler_version_; -} -::google::protobuf::compiler::Version* CodeGeneratorRequest::release_compiler_version() { - // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.compiler_version) - clear_has_compiler_version(); - ::google::protobuf::compiler::Version* temp = compiler_version_; - compiler_version_ = NULL; - return temp; -} -void CodeGeneratorRequest::set_allocated_compiler_version(::google::protobuf::compiler::Version* compiler_version) { - delete compiler_version_; - compiler_version_ = compiler_version; - if (compiler_version) { - set_has_compiler_version(); - } else { - clear_has_compiler_version(); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.compiler_version) +void CodeGeneratorResponse_File::clear_generated_code_info() { + if (generated_code_info_ != nullptr) generated_code_info_->Clear(); + _has_bits_[0] &= ~0x00000008u; } - -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS - -// =================================================================== - -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int CodeGeneratorResponse_File::kNameFieldNumber; -const int CodeGeneratorResponse_File::kInsertionPointFieldNumber; -const int CodeGeneratorResponse_File::kContentFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -CodeGeneratorResponse_File::CodeGeneratorResponse_File() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults(); - } +CodeGeneratorResponse_File::CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_name()) { - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); - } - insertion_point_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_insertion_point()) { - insertion_point_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.insertion_point_); - } - content_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_content()) { - content_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.content_); + : ::PROTOBUF_NAMESPACE_ID::Message(), + _has_bits_(from._has_bits_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_name()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArena()); + } + insertion_point_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_insertion_point()) { + insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_insertion_point(), + GetArena()); + } + content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_content()) { + content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_content(), + GetArena()); + } + if (from._internal_has_generated_code_info()) { + generated_code_info_ = new PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo(*from.generated_code_info_); + } else { + generated_code_info_ = nullptr; } // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } void CodeGeneratorResponse_File::SharedCtor() { - _cached_size_ = 0; - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - insertion_point_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - content_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +insertion_point_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +generated_code_info_ = nullptr; } CodeGeneratorResponse_File::~CodeGeneratorResponse_File() { // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse.File) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void CodeGeneratorResponse_File::SharedDtor() { - name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - insertion_point_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - content_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + insertion_point_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + content_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (this != internal_default_instance()) delete generated_code_info_; } -void CodeGeneratorResponse_File::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* CodeGeneratorResponse_File::descriptor() { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void CodeGeneratorResponse_File::ArenaDtor(void* object) { + CodeGeneratorResponse_File* _this = reinterpret_cast< CodeGeneratorResponse_File* >(object); + (void)_this; } - -const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults(); - return *internal_default_instance(); +void CodeGeneratorResponse_File::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -CodeGeneratorResponse_File* CodeGeneratorResponse_File::New(::google::protobuf::Arena* arena) const { - CodeGeneratorResponse_File* n = new CodeGeneratorResponse_File; - if (arena != NULL) { - arena->Own(n); - } - return n; +void CodeGeneratorResponse_File::SetCachedSize(int size) const { + _cached_size_.Set(size); } void CodeGeneratorResponse_File::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 7u) { + if (cached_has_bits & 0x0000000fu) { if (cached_has_bits & 0x00000001u) { - GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*name_.UnsafeRawStringPointer())->clear(); + name_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000002u) { - GOOGLE_DCHECK(!insertion_point_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*insertion_point_.UnsafeRawStringPointer())->clear(); + insertion_point_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000004u) { - GOOGLE_DCHECK(!content_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*content_.UnsafeRawStringPointer())->clear(); + content_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000008u) { + GOOGLE_DCHECK(generated_code_info_ != nullptr); + generated_code_info_->Clear(); } } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool CodeGeneratorResponse_File::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse.File) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional string name = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.compiler.CodeGeneratorResponse.File.name"); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* CodeGeneratorResponse_File::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.File.name"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string insertion_point = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_insertion_point())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->insertion_point().data(), static_cast(this->insertion_point().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point"); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + auto str = _internal_mutable_insertion_point(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string content = 15; - case 15: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_content())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->content().data(), static_cast(this->content().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.compiler.CodeGeneratorResponse.File.content"); - } else { - goto handle_unusual; - } - break; - } - + case 15: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 122)) { + auto str = _internal_mutable_content(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.File.content"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; + // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; + case 16: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 130)) { + ptr = ctx->ParseMessage(_internal_mutable_generated_code_info(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorResponse.File) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorResponse.File) - return false; -#undef DO_ + ptr = nullptr; + goto success; +#undef CHK_ } -void CodeGeneratorResponse_File::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorResponse.File) - ::google::protobuf::uint32 cached_has_bits = 0; +::PROTOBUF_NAMESPACE_ID::uint8* CodeGeneratorResponse_File::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse.File) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional string name = 1; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.compiler.CodeGeneratorResponse.File.name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->name(), output); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); } // optional string insertion_point = 2; if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->insertion_point().data(), static_cast(this->insertion_point().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_insertion_point().data(), static_cast(this->_internal_insertion_point().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 2, this->insertion_point(), output); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_insertion_point(), target); } // optional string content = 15; if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->content().data(), static_cast(this->content().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_content().data(), static_cast(this->_internal_content().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.compiler.CodeGeneratorResponse.File.content"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 15, this->content(), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorResponse.File) -} - -::google::protobuf::uint8* CodeGeneratorResponse_File::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse.File) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorResponse.File.name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->name(), target); + target = stream->WriteStringMaybeAliased( + 15, this->_internal_content(), target); } - // optional string insertion_point = 2; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->insertion_point().data(), static_cast(this->insertion_point().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 2, this->insertion_point(), target); - } - - // optional string content = 15; - if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->content().data(), static_cast(this->content().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorResponse.File.content"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 15, this->content(), target); + // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 16, _Internal::generated_code_info(this), target, stream); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse.File) return target; @@ -1644,50 +1123,59 @@ size_t CodeGeneratorResponse_File::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse.File) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } - if (_has_bits_[0 / 32] & 7u) { + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { // optional string name = 1; - if (has_name()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->name()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); } // optional string insertion_point = 2; - if (has_insertion_point()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->insertion_point()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_insertion_point()); } // optional string content = 15; - if (has_content()) { + if (cached_has_bits & 0x00000004u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->content()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_content()); + } + + // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; + if (cached_has_bits & 0x00000008u) { + total_size += 2 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *generated_code_info_); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) { +void CodeGeneratorResponse_File::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File) GOOGLE_DCHECK_NE(&from, this); const CodeGeneratorResponse_File* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorResponse.File) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorResponse.File) MergeFrom(*source); @@ -1697,28 +1185,28 @@ void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& fr void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 7u) { + if (cached_has_bits & 0x0000000fu) { if (cached_has_bits & 0x00000001u) { - set_has_name(); - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); + _internal_set_name(from._internal_name()); } if (cached_has_bits & 0x00000002u) { - set_has_insertion_point(); - insertion_point_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.insertion_point_); + _internal_set_insertion_point(from._internal_insertion_point()); } if (cached_has_bits & 0x00000004u) { - set_has_content(); - content_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.content_); + _internal_set_content(from._internal_content()); + } + if (cached_has_bits & 0x00000008u) { + _internal_mutable_generated_code_info()->PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo::MergeFrom(from._internal_generated_code_info()); } } } -void CodeGeneratorResponse_File::CopyFrom(const ::google::protobuf::Message& from) { +void CodeGeneratorResponse_File::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse.File) if (&from == this) return; Clear(); @@ -1736,419 +1224,193 @@ bool CodeGeneratorResponse_File::IsInitialized() const { return true; } -void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) { - if (other == this) return; - InternalSwap(other); -} void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) { using std::swap; - name_.Swap(&other->name_); - insertion_point_.Swap(&other->insertion_point_); - content_.Swap(&other->content_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata CodeGeneratorResponse_File::GetMetadata() const { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// CodeGeneratorResponse_File - -// optional string name = 1; -bool CodeGeneratorResponse_File::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void CodeGeneratorResponse_File::set_has_name() { - _has_bits_[0] |= 0x00000001u; -} -void CodeGeneratorResponse_File::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; -} -void CodeGeneratorResponse_File::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); -} -const ::std::string& CodeGeneratorResponse_File::name() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name) - return name_.GetNoArena(); -} -void CodeGeneratorResponse_File::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name) -} -#if LANG_CXX11 -void CodeGeneratorResponse_File::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.name) -} -#endif -void CodeGeneratorResponse_File::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name) -} -void CodeGeneratorResponse_File::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name) -} -::std::string* CodeGeneratorResponse_File::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* CodeGeneratorResponse_File::release_name() { - // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); - } else { - clear_has_name(); - } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name) -} - -// optional string insertion_point = 2; -bool CodeGeneratorResponse_File::has_insertion_point() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void CodeGeneratorResponse_File::set_has_insertion_point() { - _has_bits_[0] |= 0x00000002u; -} -void CodeGeneratorResponse_File::clear_has_insertion_point() { - _has_bits_[0] &= ~0x00000002u; -} -void CodeGeneratorResponse_File::clear_insertion_point() { - insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_insertion_point(); -} -const ::std::string& CodeGeneratorResponse_File::insertion_point() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) - return insertion_point_.GetNoArena(); -} -void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) { - set_has_insertion_point(); - insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) -} -#if LANG_CXX11 -void CodeGeneratorResponse_File::set_insertion_point(::std::string&& value) { - set_has_insertion_point(); - insertion_point_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) -} -#endif -void CodeGeneratorResponse_File::set_insertion_point(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_insertion_point(); - insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) -} -void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) { - set_has_insertion_point(); - insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) -} -::std::string* CodeGeneratorResponse_File::mutable_insertion_point() { - set_has_insertion_point(); - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) - return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* CodeGeneratorResponse_File::release_insertion_point() { - // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) - clear_has_insertion_point(); - return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) { - if (insertion_point != NULL) { - set_has_insertion_point(); - } else { - clear_has_insertion_point(); - } - insertion_point_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) -} - -// optional string content = 15; -bool CodeGeneratorResponse_File::has_content() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -void CodeGeneratorResponse_File::set_has_content() { - _has_bits_[0] |= 0x00000004u; -} -void CodeGeneratorResponse_File::clear_has_content() { - _has_bits_[0] &= ~0x00000004u; -} -void CodeGeneratorResponse_File::clear_content() { - content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_content(); -} -const ::std::string& CodeGeneratorResponse_File::content() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content) - return content_.GetNoArena(); -} -void CodeGeneratorResponse_File::set_content(const ::std::string& value) { - set_has_content(); - content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content) -} -#if LANG_CXX11 -void CodeGeneratorResponse_File::set_content(::std::string&& value) { - set_has_content(); - content_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.content) -} -#endif -void CodeGeneratorResponse_File::set_content(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_content(); - content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content) -} -void CodeGeneratorResponse_File::set_content(const char* value, size_t size) { - set_has_content(); - content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content) -} -::std::string* CodeGeneratorResponse_File::mutable_content() { - set_has_content(); - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content) - return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* CodeGeneratorResponse_File::release_content() { - // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.content) - clear_has_content(); - return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) { - if (content != NULL) { - set_has_content(); - } else { - clear_has_content(); - } - content_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content) + name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + insertion_point_.Swap(&other->insertion_point_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + content_.Swap(&other->content_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + swap(generated_code_info_, other->generated_code_info_); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS +::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorResponse_File::GetMetadata() const { + return GetMetadataStatic(); +} -// =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int CodeGeneratorResponse::kErrorFieldNumber; -const int CodeGeneratorResponse::kFileFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +// =================================================================== -CodeGeneratorResponse::CodeGeneratorResponse() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults(); +class CodeGeneratorResponse::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_error(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_supported_features(HasBits* has_bits) { + (*has_bits)[0] |= 2u; } +}; + +CodeGeneratorResponse::CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + file_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse) } CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), _has_bits_(from._has_bits_), - _cached_size_(0), file_(from.file_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - error_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_error()) { - error_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.error_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + error_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_error()) { + error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_error(), + GetArena()); } + supported_features_ = from.supported_features_; // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse) } void CodeGeneratorResponse::SharedCtor() { - _cached_size_ = 0; - error_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +error_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +supported_features_ = PROTOBUF_ULONGLONG(0); } CodeGeneratorResponse::~CodeGeneratorResponse() { // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void CodeGeneratorResponse::SharedDtor() { - error_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + error_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } -void CodeGeneratorResponse::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* CodeGeneratorResponse::descriptor() { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void CodeGeneratorResponse::ArenaDtor(void* object) { + CodeGeneratorResponse* _this = reinterpret_cast< CodeGeneratorResponse* >(object); + (void)_this; } - -const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::InitDefaults(); - return *internal_default_instance(); +void CodeGeneratorResponse::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -CodeGeneratorResponse* CodeGeneratorResponse::New(::google::protobuf::Arena* arena) const { - CodeGeneratorResponse* n = new CodeGeneratorResponse; - if (arena != NULL) { - arena->Own(n); - } - return n; +void CodeGeneratorResponse::SetCachedSize(int size) const { + _cached_size_.Set(size); } void CodeGeneratorResponse::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; file_.Clear(); - if (has_error()) { - GOOGLE_DCHECK(!error_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*error_.UnsafeRawStringPointer())->clear(); + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + error_.ClearNonDefaultToEmpty(); } + supported_features_ = PROTOBUF_ULONGLONG(0); _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool CodeGeneratorResponse::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional string error = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_error())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->error().data(), static_cast(this->error().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.compiler.CodeGeneratorResponse.error"); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* CodeGeneratorResponse::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional string error = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_error(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.error"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; + // optional uint64 supported_features = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + _Internal::set_has_supported_features(&has_bits); + supported_features_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; - case 15: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_file())); - } else { - goto handle_unusual; - } - break; - } - + case 15: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 122)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_file(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<122>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorResponse) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorResponse) - return false; -#undef DO_ + ptr = nullptr; + goto success; +#undef CHK_ } -void CodeGeneratorResponse::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorResponse) - ::google::protobuf::uint32 cached_has_bits = 0; +::PROTOBUF_NAMESPACE_ID::uint8* CodeGeneratorResponse::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional string error = 1; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->error().data(), static_cast(this->error().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_error().data(), static_cast(this->_internal_error().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.compiler.CodeGeneratorResponse.error"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->error(), output); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_error(), target); } - // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; - for (unsigned int i = 0, - n = static_cast(this->file_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 15, this->file(static_cast(i)), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorResponse) -} - -::google::protobuf::uint8* CodeGeneratorResponse::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional string error = 1; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->error().data(), static_cast(this->error().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorResponse.error"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->error(), target); + // optional uint64 supported_features = 2; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt64ToArray(2, this->_internal_supported_features(), target); } // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; for (unsigned int i = 0, - n = static_cast(this->file_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 15, this->file(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_file_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(15, this->_internal_file(i), target, stream); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse) return target; @@ -2158,45 +1420,52 @@ size_t CodeGeneratorResponse::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; + total_size += 1UL * this->_internal_file_size(); + for (const auto& msg : this->file_) { total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; - { - unsigned int count = static_cast(this->file_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->file(static_cast(i))); + + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional string error = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_error()); } - } - // optional string error = 1; - if (has_error()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->error()); - } + // optional uint64 supported_features = 2; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt64Size( + this->_internal_supported_features()); + } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + } + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) { +void CodeGeneratorResponse::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse) GOOGLE_DCHECK_NE(&from, this); const CodeGeneratorResponse* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorResponse) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorResponse) MergeFrom(*source); @@ -2206,18 +1475,24 @@ void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) { void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; file_.MergeFrom(from.file_); - if (from.has_error()) { - set_has_error(); - error_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.error_); + cached_has_bits = from._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _internal_set_error(from._internal_error()); + } + if (cached_has_bits & 0x00000002u) { + supported_features_ = from.supported_features_; + } + _has_bits_[0] |= cached_has_bits; } } -void CodeGeneratorResponse::CopyFrom(const ::google::protobuf::Message& from) { +void CodeGeneratorResponse::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse) if (&from == this) return; Clear(); @@ -2235,126 +1510,37 @@ bool CodeGeneratorResponse::IsInitialized() const { return true; } -void CodeGeneratorResponse::Swap(CodeGeneratorResponse* other) { - if (other == this) return; - InternalSwap(other); -} void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) { using std::swap; - file_.InternalSwap(&other->file_); - error_.Swap(&other->error_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata CodeGeneratorResponse::GetMetadata() const { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// CodeGeneratorResponse - -// optional string error = 1; -bool CodeGeneratorResponse::has_error() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void CodeGeneratorResponse::set_has_error() { - _has_bits_[0] |= 0x00000001u; -} -void CodeGeneratorResponse::clear_has_error() { - _has_bits_[0] &= ~0x00000001u; -} -void CodeGeneratorResponse::clear_error() { - error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_error(); -} -const ::std::string& CodeGeneratorResponse::error() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error) - return error_.GetNoArena(); -} -void CodeGeneratorResponse::set_error(const ::std::string& value) { - set_has_error(); - error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error) -} -#if LANG_CXX11 -void CodeGeneratorResponse::set_error(::std::string&& value) { - set_has_error(); - error_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.error) -} -#endif -void CodeGeneratorResponse::set_error(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_error(); - error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error) -} -void CodeGeneratorResponse::set_error(const char* value, size_t size) { - set_has_error(); - error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error) -} -::std::string* CodeGeneratorResponse::mutable_error() { - set_has_error(); - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error) - return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* CodeGeneratorResponse::release_error() { - // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.error) - clear_has_error(); - return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void CodeGeneratorResponse::set_allocated_error(::std::string* error) { - if (error != NULL) { - set_has_error(); - } else { - clear_has_error(); - } - error_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error) + file_.InternalSwap(&other->file_); + error_.Swap(&other->error_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + swap(supported_features_, other->supported_features_); } -// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; -int CodeGeneratorResponse::file_size() const { - return file_.size(); -} -void CodeGeneratorResponse::clear_file() { - file_.Clear(); -} -const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file) - return file_.Get(index); -} -::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file) - return file_.Mutable(index); -} -::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() { - // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file) - return file_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* -CodeGeneratorResponse::mutable_file() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file) - return &file_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& -CodeGeneratorResponse::file() const { - // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file) - return file_; +::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorResponse::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) - } // namespace compiler -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::compiler::Version* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::compiler::Version >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::compiler::Version >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse >(arena); +} +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) +#include diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index 2d66f035a6f49..e2932deac02ad 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -1,679 +1,986 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/compiler/plugin.proto -#ifndef PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED -#define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto +#include #include -#include - -#if GOOGLE_PROTOBUF_VERSION < 3004000 +#include +#if PROTOBUF_VERSION < 3015000 #error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update +#error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 3015000 < PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please +#error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif +#include #include #include #include #include #include -#include +#include +#include #include #include // IWYU pragma: export #include // IWYU pragma: export +#include #include #include // @@protoc_insertion_point(includes) +#include +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fcompiler_2fplugin_2eproto PROTOC_EXPORT #ifdef major #undef major #endif #ifdef minor #undef minor #endif -namespace google { -namespace protobuf { +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOC_EXPORT TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[4] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; +}; +extern PROTOC_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto; +PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(int index); +PROTOBUF_NAMESPACE_OPEN namespace compiler { class CodeGeneratorRequest; -class CodeGeneratorRequestDefaultTypeInternal; -LIBPROTOC_EXPORT extern CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_; +struct CodeGeneratorRequestDefaultTypeInternal; +PROTOC_EXPORT extern CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_; class CodeGeneratorResponse; -class CodeGeneratorResponseDefaultTypeInternal; -LIBPROTOC_EXPORT extern CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_; +struct CodeGeneratorResponseDefaultTypeInternal; +PROTOC_EXPORT extern CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_; class CodeGeneratorResponse_File; -class CodeGeneratorResponse_FileDefaultTypeInternal; -LIBPROTOC_EXPORT extern CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_; +struct CodeGeneratorResponse_FileDefaultTypeInternal; +PROTOC_EXPORT extern CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_; class Version; -class VersionDefaultTypeInternal; -LIBPROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_; +struct VersionDefaultTypeInternal; +PROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_; } // namespace compiler -} // namespace protobuf -} // namespace google - -namespace google { -namespace protobuf { +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOC_EXPORT PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest* Arena::CreateMaybeMessage(Arena*); +template<> PROTOC_EXPORT PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse* Arena::CreateMaybeMessage(Arena*); +template<> PROTOC_EXPORT PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* Arena::CreateMaybeMessage(Arena*); +template<> PROTOC_EXPORT PROTOBUF_NAMESPACE_ID::compiler::Version* Arena::CreateMaybeMessage(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN namespace compiler { -namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto { -// Internal implementation detail -- do not call these. -struct LIBPROTOC_EXPORT TableStruct { - static const ::google::protobuf::internal::ParseTableField entries[]; - static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; - static const ::google::protobuf::internal::ParseTable schema[]; - static const ::google::protobuf::uint32 offsets[]; - static const ::google::protobuf::internal::FieldMetadata field_metadata[]; - static const ::google::protobuf::internal::SerializationTable serialization_table[]; - static void InitDefaultsImpl(); +enum CodeGeneratorResponse_Feature : int { + CodeGeneratorResponse_Feature_FEATURE_NONE = 0, + CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL = 1 }; -void LIBPROTOC_EXPORT AddDescriptors(); -void LIBPROTOC_EXPORT InitDefaults(); -} // namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto - +PROTOC_EXPORT bool CodeGeneratorResponse_Feature_IsValid(int value); +constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MIN = CodeGeneratorResponse_Feature_FEATURE_NONE; +constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MAX = CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL; +constexpr int CodeGeneratorResponse_Feature_Feature_ARRAYSIZE = CodeGeneratorResponse_Feature_Feature_MAX + 1; + +PROTOC_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* CodeGeneratorResponse_Feature_descriptor(); +template +inline const std::string& CodeGeneratorResponse_Feature_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function CodeGeneratorResponse_Feature_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + CodeGeneratorResponse_Feature_descriptor(), enum_t_value); +} +inline bool CodeGeneratorResponse_Feature_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, CodeGeneratorResponse_Feature* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum( + CodeGeneratorResponse_Feature_descriptor(), name, value); +} // =================================================================== -class LIBPROTOC_EXPORT Version : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.Version) */ { +class PROTOC_EXPORT Version PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.Version) */ { public: - Version(); + inline Version() : Version(nullptr) {} virtual ~Version(); + explicit constexpr Version(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); Version(const Version& from); - - inline Version& operator=(const Version& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 Version(Version&& from) noexcept : Version() { *this = ::std::move(from); } + inline Version& operator=(const Version& from) { + CopyFrom(from); + return *this; + } inline Version& operator=(Version&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const Version& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const Version& default_instance() { + return *internal_default_instance(); + } static inline const Version* internal_default_instance() { return reinterpret_cast( &_Version_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 0; - void Swap(Version* other); friend void swap(Version& a, Version& b) { a.Swap(&b); } + inline void Swap(Version* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Version* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline Version* New() const PROTOBUF_FINAL { return New(NULL); } + inline Version* New() const final { + return CreateMaybeMessage(nullptr); + } - Version* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + Version* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const Version& from); void MergeFrom(const Version& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(Version* other); - private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.compiler.Version"; } + protected: + explicit Version(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kSuffixFieldNumber = 4, + kMajorFieldNumber = 1, + kMinorFieldNumber = 2, + kPatchFieldNumber = 3, + }; // optional string suffix = 4; bool has_suffix() const; + private: + bool _internal_has_suffix() const; + public: void clear_suffix(); - static const int kSuffixFieldNumber = 4; - const ::std::string& suffix() const; - void set_suffix(const ::std::string& value); - #if LANG_CXX11 - void set_suffix(::std::string&& value); - #endif + const std::string& suffix() const; + void set_suffix(const std::string& value); + void set_suffix(std::string&& value); void set_suffix(const char* value); void set_suffix(const char* value, size_t size); - ::std::string* mutable_suffix(); - ::std::string* release_suffix(); - void set_allocated_suffix(::std::string* suffix); + std::string* mutable_suffix(); + std::string* release_suffix(); + void set_allocated_suffix(std::string* suffix); + private: + const std::string& _internal_suffix() const; + void _internal_set_suffix(const std::string& value); + std::string* _internal_mutable_suffix(); + public: // optional int32 major = 1; bool has_major() const; + private: + bool _internal_has_major() const; + public: void clear_major(); - static const int kMajorFieldNumber = 1; - ::google::protobuf::int32 major() const; - void set_major(::google::protobuf::int32 value); + ::PROTOBUF_NAMESPACE_ID::int32 major() const; + void set_major(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_major() const; + void _internal_set_major(::PROTOBUF_NAMESPACE_ID::int32 value); + public: // optional int32 minor = 2; bool has_minor() const; + private: + bool _internal_has_minor() const; + public: void clear_minor(); - static const int kMinorFieldNumber = 2; - ::google::protobuf::int32 minor() const; - void set_minor(::google::protobuf::int32 value); + ::PROTOBUF_NAMESPACE_ID::int32 minor() const; + void set_minor(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_minor() const; + void _internal_set_minor(::PROTOBUF_NAMESPACE_ID::int32 value); + public: // optional int32 patch = 3; bool has_patch() const; + private: + bool _internal_has_patch() const; + public: void clear_patch(); - static const int kPatchFieldNumber = 3; - ::google::protobuf::int32 patch() const; - void set_patch(::google::protobuf::int32 value); + ::PROTOBUF_NAMESPACE_ID::int32 patch() const; + void set_patch(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_patch() const; + void _internal_set_patch(::PROTOBUF_NAMESPACE_ID::int32 value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.compiler.Version) private: - void set_has_major(); - void clear_has_major(); - void set_has_minor(); - void clear_has_minor(); - void set_has_patch(); - void clear_has_patch(); - void set_has_suffix(); - void clear_has_suffix(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::internal::ArenaStringPtr suffix_; - ::google::protobuf::int32 major_; - ::google::protobuf::int32 minor_; - ::google::protobuf::int32 patch_; - friend struct protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr suffix_; + ::PROTOBUF_NAMESPACE_ID::int32 major_; + ::PROTOBUF_NAMESPACE_ID::int32 minor_; + ::PROTOBUF_NAMESPACE_ID::int32 patch_; + friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorRequest) */ { +class PROTOC_EXPORT CodeGeneratorRequest PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorRequest) */ { public: - CodeGeneratorRequest(); + inline CodeGeneratorRequest() : CodeGeneratorRequest(nullptr) {} virtual ~CodeGeneratorRequest(); + explicit constexpr CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); CodeGeneratorRequest(const CodeGeneratorRequest& from); - - inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 CodeGeneratorRequest(CodeGeneratorRequest&& from) noexcept : CodeGeneratorRequest() { *this = ::std::move(from); } + inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) { + CopyFrom(from); + return *this; + } inline CodeGeneratorRequest& operator=(CodeGeneratorRequest&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const CodeGeneratorRequest& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const CodeGeneratorRequest& default_instance() { + return *internal_default_instance(); + } static inline const CodeGeneratorRequest* internal_default_instance() { return reinterpret_cast( &_CodeGeneratorRequest_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 1; - void Swap(CodeGeneratorRequest* other); friend void swap(CodeGeneratorRequest& a, CodeGeneratorRequest& b) { a.Swap(&b); } + inline void Swap(CodeGeneratorRequest* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(CodeGeneratorRequest* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline CodeGeneratorRequest* New() const PROTOBUF_FINAL { return New(NULL); } + inline CodeGeneratorRequest* New() const final { + return CreateMaybeMessage(nullptr); + } - CodeGeneratorRequest* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + CodeGeneratorRequest* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const CodeGeneratorRequest& from); void MergeFrom(const CodeGeneratorRequest& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(CodeGeneratorRequest* other); - private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.compiler.CodeGeneratorRequest"; } + protected: + explicit CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kFileToGenerateFieldNumber = 1, + kProtoFileFieldNumber = 15, + kParameterFieldNumber = 2, + kCompilerVersionFieldNumber = 3, + }; // repeated string file_to_generate = 1; int file_to_generate_size() const; + private: + int _internal_file_to_generate_size() const; + public: void clear_file_to_generate(); - static const int kFileToGenerateFieldNumber = 1; - const ::std::string& file_to_generate(int index) const; - ::std::string* mutable_file_to_generate(int index); - void set_file_to_generate(int index, const ::std::string& value); - #if LANG_CXX11 - void set_file_to_generate(int index, ::std::string&& value); - #endif + const std::string& file_to_generate(int index) const; + std::string* mutable_file_to_generate(int index); + void set_file_to_generate(int index, const std::string& value); + void set_file_to_generate(int index, std::string&& value); void set_file_to_generate(int index, const char* value); void set_file_to_generate(int index, const char* value, size_t size); - ::std::string* add_file_to_generate(); - void add_file_to_generate(const ::std::string& value); - #if LANG_CXX11 - void add_file_to_generate(::std::string&& value); - #endif + std::string* add_file_to_generate(); + void add_file_to_generate(const std::string& value); + void add_file_to_generate(std::string&& value); void add_file_to_generate(const char* value); void add_file_to_generate(const char* value, size_t size); - const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const; - ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField& file_to_generate() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField* mutable_file_to_generate(); + private: + const std::string& _internal_file_to_generate(int index) const; + std::string* _internal_add_file_to_generate(); + public: // repeated .google.protobuf.FileDescriptorProto proto_file = 15; int proto_file_size() const; + private: + int _internal_proto_file_size() const; + public: void clear_proto_file(); - static const int kProtoFileFieldNumber = 15; - const ::google::protobuf::FileDescriptorProto& proto_file(int index) const; - ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index); - ::google::protobuf::FileDescriptorProto* add_proto_file(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* + PROTOBUF_NAMESPACE_ID::FileDescriptorProto* mutable_proto_file(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >* mutable_proto_file(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& + private: + const PROTOBUF_NAMESPACE_ID::FileDescriptorProto& _internal_proto_file(int index) const; + PROTOBUF_NAMESPACE_ID::FileDescriptorProto* _internal_add_proto_file(); + public: + const PROTOBUF_NAMESPACE_ID::FileDescriptorProto& proto_file(int index) const; + PROTOBUF_NAMESPACE_ID::FileDescriptorProto* add_proto_file(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >& proto_file() const; // optional string parameter = 2; bool has_parameter() const; + private: + bool _internal_has_parameter() const; + public: void clear_parameter(); - static const int kParameterFieldNumber = 2; - const ::std::string& parameter() const; - void set_parameter(const ::std::string& value); - #if LANG_CXX11 - void set_parameter(::std::string&& value); - #endif + const std::string& parameter() const; + void set_parameter(const std::string& value); + void set_parameter(std::string&& value); void set_parameter(const char* value); void set_parameter(const char* value, size_t size); - ::std::string* mutable_parameter(); - ::std::string* release_parameter(); - void set_allocated_parameter(::std::string* parameter); + std::string* mutable_parameter(); + std::string* release_parameter(); + void set_allocated_parameter(std::string* parameter); + private: + const std::string& _internal_parameter() const; + void _internal_set_parameter(const std::string& value); + std::string* _internal_mutable_parameter(); + public: // optional .google.protobuf.compiler.Version compiler_version = 3; bool has_compiler_version() const; + private: + bool _internal_has_compiler_version() const; + public: void clear_compiler_version(); - static const int kCompilerVersionFieldNumber = 3; - const ::google::protobuf::compiler::Version& compiler_version() const; - ::google::protobuf::compiler::Version* mutable_compiler_version(); - ::google::protobuf::compiler::Version* release_compiler_version(); - void set_allocated_compiler_version(::google::protobuf::compiler::Version* compiler_version); + const PROTOBUF_NAMESPACE_ID::compiler::Version& compiler_version() const; + PROTOBUF_NAMESPACE_ID::compiler::Version* release_compiler_version(); + PROTOBUF_NAMESPACE_ID::compiler::Version* mutable_compiler_version(); + void set_allocated_compiler_version(PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version); + private: + const PROTOBUF_NAMESPACE_ID::compiler::Version& _internal_compiler_version() const; + PROTOBUF_NAMESPACE_ID::compiler::Version* _internal_mutable_compiler_version(); + public: + void unsafe_arena_set_allocated_compiler_version( + PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version); + PROTOBUF_NAMESPACE_ID::compiler::Version* unsafe_arena_release_compiler_version(); // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) private: - void set_has_parameter(); - void clear_has_parameter(); - void set_has_compiler_version(); - void clear_has_compiler_version(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_; - ::google::protobuf::internal::ArenaStringPtr parameter_; - ::google::protobuf::compiler::Version* compiler_version_; - friend struct protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField file_to_generate_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto > proto_file_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr parameter_; + PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version_; + friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse.File) */ { +class PROTOC_EXPORT CodeGeneratorResponse_File PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse.File) */ { public: - CodeGeneratorResponse_File(); + inline CodeGeneratorResponse_File() : CodeGeneratorResponse_File(nullptr) {} virtual ~CodeGeneratorResponse_File(); + explicit constexpr CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from); - - inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 CodeGeneratorResponse_File(CodeGeneratorResponse_File&& from) noexcept : CodeGeneratorResponse_File() { *this = ::std::move(from); } + inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) { + CopyFrom(from); + return *this; + } inline CodeGeneratorResponse_File& operator=(CodeGeneratorResponse_File&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const CodeGeneratorResponse_File& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const CodeGeneratorResponse_File& default_instance() { + return *internal_default_instance(); + } static inline const CodeGeneratorResponse_File* internal_default_instance() { return reinterpret_cast( &_CodeGeneratorResponse_File_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 2; - void Swap(CodeGeneratorResponse_File* other); friend void swap(CodeGeneratorResponse_File& a, CodeGeneratorResponse_File& b) { a.Swap(&b); } + inline void Swap(CodeGeneratorResponse_File* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(CodeGeneratorResponse_File* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline CodeGeneratorResponse_File* New() const PROTOBUF_FINAL { return New(NULL); } + inline CodeGeneratorResponse_File* New() const final { + return CreateMaybeMessage(nullptr); + } - CodeGeneratorResponse_File* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + CodeGeneratorResponse_File* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const CodeGeneratorResponse_File& from); void MergeFrom(const CodeGeneratorResponse_File& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(CodeGeneratorResponse_File* other); - private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.compiler.CodeGeneratorResponse.File"; } + protected: + explicit CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kNameFieldNumber = 1, + kInsertionPointFieldNumber = 2, + kContentFieldNumber = 15, + kGeneratedCodeInfoFieldNumber = 16, + }; // optional string name = 1; bool has_name() const; + private: + bool _internal_has_name() const; + public: void clear_name(); - static const int kNameFieldNumber = 1; - const ::std::string& name() const; - void set_name(const ::std::string& value); - #if LANG_CXX11 - void set_name(::std::string&& value); - #endif + const std::string& name() const; + void set_name(const std::string& value); + void set_name(std::string&& value); void set_name(const char* value); void set_name(const char* value, size_t size); - ::std::string* mutable_name(); - ::std::string* release_name(); - void set_allocated_name(::std::string* name); + std::string* mutable_name(); + std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: // optional string insertion_point = 2; bool has_insertion_point() const; + private: + bool _internal_has_insertion_point() const; + public: void clear_insertion_point(); - static const int kInsertionPointFieldNumber = 2; - const ::std::string& insertion_point() const; - void set_insertion_point(const ::std::string& value); - #if LANG_CXX11 - void set_insertion_point(::std::string&& value); - #endif + const std::string& insertion_point() const; + void set_insertion_point(const std::string& value); + void set_insertion_point(std::string&& value); void set_insertion_point(const char* value); void set_insertion_point(const char* value, size_t size); - ::std::string* mutable_insertion_point(); - ::std::string* release_insertion_point(); - void set_allocated_insertion_point(::std::string* insertion_point); + std::string* mutable_insertion_point(); + std::string* release_insertion_point(); + void set_allocated_insertion_point(std::string* insertion_point); + private: + const std::string& _internal_insertion_point() const; + void _internal_set_insertion_point(const std::string& value); + std::string* _internal_mutable_insertion_point(); + public: // optional string content = 15; bool has_content() const; + private: + bool _internal_has_content() const; + public: void clear_content(); - static const int kContentFieldNumber = 15; - const ::std::string& content() const; - void set_content(const ::std::string& value); - #if LANG_CXX11 - void set_content(::std::string&& value); - #endif + const std::string& content() const; + void set_content(const std::string& value); + void set_content(std::string&& value); void set_content(const char* value); void set_content(const char* value, size_t size); - ::std::string* mutable_content(); - ::std::string* release_content(); - void set_allocated_content(::std::string* content); + std::string* mutable_content(); + std::string* release_content(); + void set_allocated_content(std::string* content); + private: + const std::string& _internal_content() const; + void _internal_set_content(const std::string& value); + std::string* _internal_mutable_content(); + public: + + // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; + bool has_generated_code_info() const; + private: + bool _internal_has_generated_code_info() const; + public: + void clear_generated_code_info(); + const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& generated_code_info() const; + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* release_generated_code_info(); + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* mutable_generated_code_info(); + void set_allocated_generated_code_info(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info); + private: + const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& _internal_generated_code_info() const; + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* _internal_mutable_generated_code_info(); + public: + void unsafe_arena_set_allocated_generated_code_info( + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info); + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* unsafe_arena_release_generated_code_info(); // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) private: - void set_has_name(); - void clear_has_name(); - void set_has_insertion_point(); - void clear_has_insertion_point(); - void set_has_content(); - void clear_has_content(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::internal::ArenaStringPtr name_; - ::google::protobuf::internal::ArenaStringPtr insertion_point_; - ::google::protobuf::internal::ArenaStringPtr content_; - friend struct protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr insertion_point_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr content_; + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info_; + friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse) */ { +class PROTOC_EXPORT CodeGeneratorResponse PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse) */ { public: - CodeGeneratorResponse(); + inline CodeGeneratorResponse() : CodeGeneratorResponse(nullptr) {} virtual ~CodeGeneratorResponse(); + explicit constexpr CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); CodeGeneratorResponse(const CodeGeneratorResponse& from); - - inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 CodeGeneratorResponse(CodeGeneratorResponse&& from) noexcept : CodeGeneratorResponse() { *this = ::std::move(from); } + inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) { + CopyFrom(from); + return *this; + } inline CodeGeneratorResponse& operator=(CodeGeneratorResponse&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const CodeGeneratorResponse& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const CodeGeneratorResponse& default_instance() { + return *internal_default_instance(); + } static inline const CodeGeneratorResponse* internal_default_instance() { return reinterpret_cast( &_CodeGeneratorResponse_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 3; - void Swap(CodeGeneratorResponse* other); friend void swap(CodeGeneratorResponse& a, CodeGeneratorResponse& b) { a.Swap(&b); } + inline void Swap(CodeGeneratorResponse* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(CodeGeneratorResponse* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline CodeGeneratorResponse* New() const PROTOBUF_FINAL { return New(NULL); } + inline CodeGeneratorResponse* New() const final { + return CreateMaybeMessage(nullptr); + } - CodeGeneratorResponse* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + CodeGeneratorResponse* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const CodeGeneratorResponse& from); void MergeFrom(const CodeGeneratorResponse& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(CodeGeneratorResponse* other); - private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.compiler.CodeGeneratorResponse"; } + protected: + explicit CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- typedef CodeGeneratorResponse_File File; + typedef CodeGeneratorResponse_Feature Feature; + static constexpr Feature FEATURE_NONE = + CodeGeneratorResponse_Feature_FEATURE_NONE; + static constexpr Feature FEATURE_PROTO3_OPTIONAL = + CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL; + static inline bool Feature_IsValid(int value) { + return CodeGeneratorResponse_Feature_IsValid(value); + } + static constexpr Feature Feature_MIN = + CodeGeneratorResponse_Feature_Feature_MIN; + static constexpr Feature Feature_MAX = + CodeGeneratorResponse_Feature_Feature_MAX; + static constexpr int Feature_ARRAYSIZE = + CodeGeneratorResponse_Feature_Feature_ARRAYSIZE; + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* + Feature_descriptor() { + return CodeGeneratorResponse_Feature_descriptor(); + } + template + static inline const std::string& Feature_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function Feature_Name."); + return CodeGeneratorResponse_Feature_Name(enum_t_value); + } + static inline bool Feature_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, + Feature* value) { + return CodeGeneratorResponse_Feature_Parse(name, value); + } + // accessors ------------------------------------------------------- + enum : int { + kFileFieldNumber = 15, + kErrorFieldNumber = 1, + kSupportedFeaturesFieldNumber = 2, + }; // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; int file_size() const; + private: + int _internal_file_size() const; + public: void clear_file(); - static const int kFileFieldNumber = 15; - const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const; - ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index); - ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* + PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* mutable_file(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >* mutable_file(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& + private: + const PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File& _internal_file(int index) const; + PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* _internal_add_file(); + public: + const PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File& file(int index) const; + PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* add_file(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >& file() const; // optional string error = 1; bool has_error() const; + private: + bool _internal_has_error() const; + public: void clear_error(); - static const int kErrorFieldNumber = 1; - const ::std::string& error() const; - void set_error(const ::std::string& value); - #if LANG_CXX11 - void set_error(::std::string&& value); - #endif + const std::string& error() const; + void set_error(const std::string& value); + void set_error(std::string&& value); void set_error(const char* value); void set_error(const char* value, size_t size); - ::std::string* mutable_error(); - ::std::string* release_error(); - void set_allocated_error(::std::string* error); + std::string* mutable_error(); + std::string* release_error(); + void set_allocated_error(std::string* error); + private: + const std::string& _internal_error() const; + void _internal_set_error(const std::string& value); + std::string* _internal_mutable_error(); + public: + + // optional uint64 supported_features = 2; + bool has_supported_features() const; + private: + bool _internal_has_supported_features() const; + public: + void clear_supported_features(); + ::PROTOBUF_NAMESPACE_ID::uint64 supported_features() const; + void set_supported_features(::PROTOBUF_NAMESPACE_ID::uint64 value); + private: + ::PROTOBUF_NAMESPACE_ID::uint64 _internal_supported_features() const; + void _internal_set_supported_features(::PROTOBUF_NAMESPACE_ID::uint64 value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) private: - void set_has_error(); - void clear_has_error(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_; - ::google::protobuf::internal::ArenaStringPtr error_; - friend struct protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File > file_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr error_; + ::PROTOBUF_NAMESPACE_ID::uint64 supported_features_; + friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; }; // =================================================================== // =================================================================== -#if !PROTOBUF_INLINE_NOT_IN_HEADERS #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" @@ -681,137 +988,159 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag // Version // optional int32 major = 1; -inline bool Version::has_major() const { - return (_has_bits_[0] & 0x00000002u) != 0; +inline bool Version::_internal_has_major() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void Version::set_has_major() { - _has_bits_[0] |= 0x00000002u; -} -inline void Version::clear_has_major() { - _has_bits_[0] &= ~0x00000002u; +inline bool Version::has_major() const { + return _internal_has_major(); } inline void Version::clear_major() { major_ = 0; - clear_has_major(); + _has_bits_[0] &= ~0x00000002u; } -inline ::google::protobuf::int32 Version::major() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.major) +inline ::PROTOBUF_NAMESPACE_ID::int32 Version::_internal_major() const { return major_; } -inline void Version::set_major(::google::protobuf::int32 value) { - set_has_major(); +inline ::PROTOBUF_NAMESPACE_ID::int32 Version::major() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.major) + return _internal_major(); +} +inline void Version::_internal_set_major(::PROTOBUF_NAMESPACE_ID::int32 value) { + _has_bits_[0] |= 0x00000002u; major_ = value; +} +inline void Version::set_major(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_major(value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.major) } // optional int32 minor = 2; -inline bool Version::has_minor() const { - return (_has_bits_[0] & 0x00000004u) != 0; +inline bool Version::_internal_has_minor() const { + bool value = (_has_bits_[0] & 0x00000004u) != 0; + return value; } -inline void Version::set_has_minor() { - _has_bits_[0] |= 0x00000004u; -} -inline void Version::clear_has_minor() { - _has_bits_[0] &= ~0x00000004u; +inline bool Version::has_minor() const { + return _internal_has_minor(); } inline void Version::clear_minor() { minor_ = 0; - clear_has_minor(); + _has_bits_[0] &= ~0x00000004u; } -inline ::google::protobuf::int32 Version::minor() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.minor) +inline ::PROTOBUF_NAMESPACE_ID::int32 Version::_internal_minor() const { return minor_; } -inline void Version::set_minor(::google::protobuf::int32 value) { - set_has_minor(); +inline ::PROTOBUF_NAMESPACE_ID::int32 Version::minor() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.minor) + return _internal_minor(); +} +inline void Version::_internal_set_minor(::PROTOBUF_NAMESPACE_ID::int32 value) { + _has_bits_[0] |= 0x00000004u; minor_ = value; +} +inline void Version::set_minor(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_minor(value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.minor) } // optional int32 patch = 3; -inline bool Version::has_patch() const { - return (_has_bits_[0] & 0x00000008u) != 0; +inline bool Version::_internal_has_patch() const { + bool value = (_has_bits_[0] & 0x00000008u) != 0; + return value; } -inline void Version::set_has_patch() { - _has_bits_[0] |= 0x00000008u; -} -inline void Version::clear_has_patch() { - _has_bits_[0] &= ~0x00000008u; +inline bool Version::has_patch() const { + return _internal_has_patch(); } inline void Version::clear_patch() { patch_ = 0; - clear_has_patch(); + _has_bits_[0] &= ~0x00000008u; } -inline ::google::protobuf::int32 Version::patch() const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.patch) +inline ::PROTOBUF_NAMESPACE_ID::int32 Version::_internal_patch() const { return patch_; } -inline void Version::set_patch(::google::protobuf::int32 value) { - set_has_patch(); +inline ::PROTOBUF_NAMESPACE_ID::int32 Version::patch() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.patch) + return _internal_patch(); +} +inline void Version::_internal_set_patch(::PROTOBUF_NAMESPACE_ID::int32 value) { + _has_bits_[0] |= 0x00000008u; patch_ = value; +} +inline void Version::set_patch(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_patch(value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.patch) } // optional string suffix = 4; -inline bool Version::has_suffix() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void Version::set_has_suffix() { - _has_bits_[0] |= 0x00000001u; +inline bool Version::_internal_has_suffix() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void Version::clear_has_suffix() { - _has_bits_[0] &= ~0x00000001u; +inline bool Version::has_suffix() const { + return _internal_has_suffix(); } inline void Version::clear_suffix() { - suffix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_suffix(); + suffix_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& Version::suffix() const { +inline const std::string& Version::suffix() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.suffix) - return suffix_.GetNoArena(); + return _internal_suffix(); } -inline void Version::set_suffix(const ::std::string& value) { - set_has_suffix(); - suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void Version::set_suffix(const std::string& value) { + _internal_set_suffix(value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.suffix) } -#if LANG_CXX11 -inline void Version::set_suffix(::std::string&& value) { - set_has_suffix(); - suffix_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* Version::mutable_suffix() { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.Version.suffix) + return _internal_mutable_suffix(); +} +inline const std::string& Version::_internal_suffix() const { + return suffix_.Get(); +} +inline void Version::_internal_set_suffix(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void Version::set_suffix(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + suffix_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.Version.suffix) } -#endif inline void Version::set_suffix(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_suffix(); - suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.Version.suffix) } -inline void Version::set_suffix(const char* value, size_t size) { - set_has_suffix(); - suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void Version::set_suffix(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.Version.suffix) } -inline ::std::string* Version::mutable_suffix() { - set_has_suffix(); - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.Version.suffix) - return suffix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* Version::_internal_mutable_suffix() { + _has_bits_[0] |= 0x00000001u; + return suffix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* Version::release_suffix() { +inline std::string* Version::release_suffix() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.Version.suffix) - clear_has_suffix(); - return suffix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_suffix()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return suffix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void Version::set_allocated_suffix(::std::string* suffix) { - if (suffix != NULL) { - set_has_suffix(); +inline void Version::set_allocated_suffix(std::string* suffix) { + if (suffix != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_suffix(); + _has_bits_[0] &= ~0x00000001u; } - suffix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), suffix); + suffix_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), suffix, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.Version.suffix) } @@ -820,32 +1149,40 @@ inline void Version::set_allocated_suffix(::std::string* suffix) { // CodeGeneratorRequest // repeated string file_to_generate = 1; -inline int CodeGeneratorRequest::file_to_generate_size() const { +inline int CodeGeneratorRequest::_internal_file_to_generate_size() const { return file_to_generate_.size(); } +inline int CodeGeneratorRequest::file_to_generate_size() const { + return _internal_file_to_generate_size(); +} inline void CodeGeneratorRequest::clear_file_to_generate() { file_to_generate_.Clear(); } -inline const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) +inline std::string* CodeGeneratorRequest::add_file_to_generate() { + // @@protoc_insertion_point(field_add_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) + return _internal_add_file_to_generate(); +} +inline const std::string& CodeGeneratorRequest::_internal_file_to_generate(int index) const { return file_to_generate_.Get(index); } -inline ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) { +inline const std::string& CodeGeneratorRequest::file_to_generate(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) + return _internal_file_to_generate(index); +} +inline std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return file_to_generate_.Mutable(index); } -inline void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) { +inline void CodeGeneratorRequest::set_file_to_generate(int index, const std::string& value) { // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) file_to_generate_.Mutable(index)->assign(value); } -#if LANG_CXX11 -inline void CodeGeneratorRequest::set_file_to_generate(int index, ::std::string&& value) { +inline void CodeGeneratorRequest::set_file_to_generate(int index, std::string&& value) { // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) file_to_generate_.Mutable(index)->assign(std::move(value)); } -#endif inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); file_to_generate_.Mutable(index)->assign(value); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } @@ -854,22 +1191,19 @@ inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* va reinterpret_cast(value), size); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } -inline ::std::string* CodeGeneratorRequest::add_file_to_generate() { - // @@protoc_insertion_point(field_add_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) +inline std::string* CodeGeneratorRequest::_internal_add_file_to_generate() { return file_to_generate_.Add(); } -inline void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) { +inline void CodeGeneratorRequest::add_file_to_generate(const std::string& value) { file_to_generate_.Add()->assign(value); // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } -#if LANG_CXX11 -inline void CodeGeneratorRequest::add_file_to_generate(::std::string&& value) { +inline void CodeGeneratorRequest::add_file_to_generate(std::string&& value) { file_to_generate_.Add(std::move(value)); // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } -#endif inline void CodeGeneratorRequest::add_file_to_generate(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); file_to_generate_.Add()->assign(value); // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } @@ -877,153 +1211,206 @@ inline void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t file_to_generate_.Add()->assign(reinterpret_cast(value), size); // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } -inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField& CodeGeneratorRequest::file_to_generate() const { // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return file_to_generate_; } -inline ::google::protobuf::RepeatedPtrField< ::std::string>* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField* CodeGeneratorRequest::mutable_file_to_generate() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return &file_to_generate_; } // optional string parameter = 2; -inline bool CodeGeneratorRequest::has_parameter() const { - return (_has_bits_[0] & 0x00000001u) != 0; +inline bool CodeGeneratorRequest::_internal_has_parameter() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void CodeGeneratorRequest::set_has_parameter() { - _has_bits_[0] |= 0x00000001u; -} -inline void CodeGeneratorRequest::clear_has_parameter() { - _has_bits_[0] &= ~0x00000001u; +inline bool CodeGeneratorRequest::has_parameter() const { + return _internal_has_parameter(); } inline void CodeGeneratorRequest::clear_parameter() { - parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_parameter(); + parameter_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& CodeGeneratorRequest::parameter() const { +inline const std::string& CodeGeneratorRequest::parameter() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter) - return parameter_.GetNoArena(); + return _internal_parameter(); } -inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) { - set_has_parameter(); - parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void CodeGeneratorRequest::set_parameter(const std::string& value) { + _internal_set_parameter(value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter) } -#if LANG_CXX11 -inline void CodeGeneratorRequest::set_parameter(::std::string&& value) { - set_has_parameter(); - parameter_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* CodeGeneratorRequest::mutable_parameter() { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter) + return _internal_mutable_parameter(); +} +inline const std::string& CodeGeneratorRequest::_internal_parameter() const { + return parameter_.Get(); +} +inline void CodeGeneratorRequest::_internal_set_parameter(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void CodeGeneratorRequest::set_parameter(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + parameter_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorRequest.parameter) } -#endif inline void CodeGeneratorRequest::set_parameter(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_parameter(); - parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter) } -inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) { - set_has_parameter(); - parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void CodeGeneratorRequest::set_parameter(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter) } -inline ::std::string* CodeGeneratorRequest::mutable_parameter() { - set_has_parameter(); - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter) - return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* CodeGeneratorRequest::_internal_mutable_parameter() { + _has_bits_[0] |= 0x00000001u; + return parameter_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* CodeGeneratorRequest::release_parameter() { +inline std::string* CodeGeneratorRequest::release_parameter() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.parameter) - clear_has_parameter(); - return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_parameter()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return parameter_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) { - if (parameter != NULL) { - set_has_parameter(); +inline void CodeGeneratorRequest::set_allocated_parameter(std::string* parameter) { + if (parameter != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_parameter(); + _has_bits_[0] &= ~0x00000001u; } - parameter_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter); + parameter_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), parameter, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter) } // repeated .google.protobuf.FileDescriptorProto proto_file = 15; -inline int CodeGeneratorRequest::proto_file_size() const { +inline int CodeGeneratorRequest::_internal_proto_file_size() const { return proto_file_.size(); } -inline void CodeGeneratorRequest::clear_proto_file() { - proto_file_.Clear(); -} -inline const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file) - return proto_file_.Get(index); +inline int CodeGeneratorRequest::proto_file_size() const { + return _internal_proto_file_size(); } -inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) { +inline PROTOBUF_NAMESPACE_ID::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_.Mutable(index); } -inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() { - // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file) - return proto_file_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >* CodeGeneratorRequest::mutable_proto_file() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return &proto_file_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& +inline const PROTOBUF_NAMESPACE_ID::FileDescriptorProto& CodeGeneratorRequest::_internal_proto_file(int index) const { + return proto_file_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file) + return _internal_proto_file(index); +} +inline PROTOBUF_NAMESPACE_ID::FileDescriptorProto* CodeGeneratorRequest::_internal_add_proto_file() { + return proto_file_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() { + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file) + return _internal_add_proto_file(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >& CodeGeneratorRequest::proto_file() const { // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_; } // optional .google.protobuf.compiler.Version compiler_version = 3; -inline bool CodeGeneratorRequest::has_compiler_version() const { - return (_has_bits_[0] & 0x00000002u) != 0; +inline bool CodeGeneratorRequest::_internal_has_compiler_version() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + PROTOBUF_ASSUME(!value || compiler_version_ != nullptr); + return value; } -inline void CodeGeneratorRequest::set_has_compiler_version() { - _has_bits_[0] |= 0x00000002u; +inline bool CodeGeneratorRequest::has_compiler_version() const { + return _internal_has_compiler_version(); } -inline void CodeGeneratorRequest::clear_has_compiler_version() { +inline void CodeGeneratorRequest::clear_compiler_version() { + if (compiler_version_ != nullptr) compiler_version_->Clear(); _has_bits_[0] &= ~0x00000002u; } -inline void CodeGeneratorRequest::clear_compiler_version() { - if (compiler_version_ != NULL) compiler_version_->::google::protobuf::compiler::Version::Clear(); - clear_has_compiler_version(); +inline const PROTOBUF_NAMESPACE_ID::compiler::Version& CodeGeneratorRequest::_internal_compiler_version() const { + const PROTOBUF_NAMESPACE_ID::compiler::Version* p = compiler_version_; + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_); } -inline const ::google::protobuf::compiler::Version& CodeGeneratorRequest::compiler_version() const { - const ::google::protobuf::compiler::Version* p = compiler_version_; +inline const PROTOBUF_NAMESPACE_ID::compiler::Version& CodeGeneratorRequest::compiler_version() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.compiler_version) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::compiler::_Version_default_instance_); + return _internal_compiler_version(); } -inline ::google::protobuf::compiler::Version* CodeGeneratorRequest::mutable_compiler_version() { - set_has_compiler_version(); - if (compiler_version_ == NULL) { - compiler_version_ = new ::google::protobuf::compiler::Version; +inline void CodeGeneratorRequest::unsafe_arena_set_allocated_compiler_version( + PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version) { + if (GetArena() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(compiler_version_); } - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.compiler_version) - return compiler_version_; + compiler_version_ = compiler_version; + if (compiler_version) { + _has_bits_[0] |= 0x00000002u; + } else { + _has_bits_[0] &= ~0x00000002u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.compiler_version) +} +inline PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::release_compiler_version() { + _has_bits_[0] &= ~0x00000002u; + PROTOBUF_NAMESPACE_ID::compiler::Version* temp = compiler_version_; + compiler_version_ = nullptr; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + return temp; } -inline ::google::protobuf::compiler::Version* CodeGeneratorRequest::release_compiler_version() { +inline PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::unsafe_arena_release_compiler_version() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.compiler_version) - clear_has_compiler_version(); - ::google::protobuf::compiler::Version* temp = compiler_version_; - compiler_version_ = NULL; + _has_bits_[0] &= ~0x00000002u; + PROTOBUF_NAMESPACE_ID::compiler::Version* temp = compiler_version_; + compiler_version_ = nullptr; return temp; } -inline void CodeGeneratorRequest::set_allocated_compiler_version(::google::protobuf::compiler::Version* compiler_version) { - delete compiler_version_; - compiler_version_ = compiler_version; +inline PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::_internal_mutable_compiler_version() { + _has_bits_[0] |= 0x00000002u; + if (compiler_version_ == nullptr) { + auto* p = CreateMaybeMessage(GetArena()); + compiler_version_ = p; + } + return compiler_version_; +} +inline PROTOBUF_NAMESPACE_ID::compiler::Version* CodeGeneratorRequest::mutable_compiler_version() { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.compiler_version) + return _internal_mutable_compiler_version(); +} +inline void CodeGeneratorRequest::set_allocated_compiler_version(PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + if (message_arena == nullptr) { + delete compiler_version_; + } if (compiler_version) { - set_has_compiler_version(); + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(compiler_version); + if (message_arena != submessage_arena) { + compiler_version = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, compiler_version, submessage_arena); + } + _has_bits_[0] |= 0x00000002u; } else { - clear_has_compiler_version(); + _has_bits_[0] &= ~0x00000002u; } + compiler_version_ = compiler_version; // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.compiler_version) } @@ -1032,286 +1419,442 @@ inline void CodeGeneratorRequest::set_allocated_compiler_version(::google::proto // CodeGeneratorResponse_File // optional string name = 1; -inline bool CodeGeneratorResponse_File::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void CodeGeneratorResponse_File::set_has_name() { - _has_bits_[0] |= 0x00000001u; +inline bool CodeGeneratorResponse_File::_internal_has_name() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void CodeGeneratorResponse_File::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; +inline bool CodeGeneratorResponse_File::has_name() const { + return _internal_has_name(); } inline void CodeGeneratorResponse_File::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); + name_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& CodeGeneratorResponse_File::name() const { +inline const std::string& CodeGeneratorResponse_File::name() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name) - return name_.GetNoArena(); + return _internal_name(); } -inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void CodeGeneratorResponse_File::set_name(const std::string& value) { + _internal_set_name(value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name) } -#if LANG_CXX11 -inline void CodeGeneratorResponse_File::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* CodeGeneratorResponse_File::mutable_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name) + return _internal_mutable_name(); +} +inline const std::string& CodeGeneratorResponse_File::_internal_name() const { + return name_.Get(); +} +inline void CodeGeneratorResponse_File::_internal_set_name(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void CodeGeneratorResponse_File::set_name(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.name) } -#endif inline void CodeGeneratorResponse_File::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name) } -inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void CodeGeneratorResponse_File::set_name(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name) } -inline ::std::string* CodeGeneratorResponse_File::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* CodeGeneratorResponse_File::_internal_mutable_name() { + _has_bits_[0] |= 0x00000001u; + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* CodeGeneratorResponse_File::release_name() { +inline std::string* CodeGeneratorResponse_File::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_name()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); +inline void CodeGeneratorResponse_File::set_allocated_name(std::string* name) { + if (name != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_name(); + _has_bits_[0] &= ~0x00000001u; } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name) } // optional string insertion_point = 2; -inline bool CodeGeneratorResponse_File::has_insertion_point() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -inline void CodeGeneratorResponse_File::set_has_insertion_point() { - _has_bits_[0] |= 0x00000002u; +inline bool CodeGeneratorResponse_File::_internal_has_insertion_point() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void CodeGeneratorResponse_File::clear_has_insertion_point() { - _has_bits_[0] &= ~0x00000002u; +inline bool CodeGeneratorResponse_File::has_insertion_point() const { + return _internal_has_insertion_point(); } inline void CodeGeneratorResponse_File::clear_insertion_point() { - insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_insertion_point(); + insertion_point_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000002u; } -inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const { +inline const std::string& CodeGeneratorResponse_File::insertion_point() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) - return insertion_point_.GetNoArena(); + return _internal_insertion_point(); } -inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) { - set_has_insertion_point(); - insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void CodeGeneratorResponse_File::set_insertion_point(const std::string& value) { + _internal_set_insertion_point(value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } -#if LANG_CXX11 -inline void CodeGeneratorResponse_File::set_insertion_point(::std::string&& value) { - set_has_insertion_point(); - insertion_point_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* CodeGeneratorResponse_File::mutable_insertion_point() { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) + return _internal_mutable_insertion_point(); +} +inline const std::string& CodeGeneratorResponse_File::_internal_insertion_point() const { + return insertion_point_.Get(); +} +inline void CodeGeneratorResponse_File::_internal_set_insertion_point(const std::string& value) { + _has_bits_[0] |= 0x00000002u; + insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void CodeGeneratorResponse_File::set_insertion_point(std::string&& value) { + _has_bits_[0] |= 0x00000002u; + insertion_point_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } -#endif inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_insertion_point(); - insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000002u; + insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } -inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) { - set_has_insertion_point(); - insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000002u; + insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } -inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() { - set_has_insertion_point(); - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) - return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* CodeGeneratorResponse_File::_internal_mutable_insertion_point() { + _has_bits_[0] |= 0x00000002u; + return insertion_point_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() { +inline std::string* CodeGeneratorResponse_File::release_insertion_point() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) - clear_has_insertion_point(); - return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_insertion_point()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000002u; + return insertion_point_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) { - if (insertion_point != NULL) { - set_has_insertion_point(); +inline void CodeGeneratorResponse_File::set_allocated_insertion_point(std::string* insertion_point) { + if (insertion_point != nullptr) { + _has_bits_[0] |= 0x00000002u; } else { - clear_has_insertion_point(); + _has_bits_[0] &= ~0x00000002u; } - insertion_point_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point); + insertion_point_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), insertion_point, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } // optional string content = 15; -inline bool CodeGeneratorResponse_File::has_content() const { - return (_has_bits_[0] & 0x00000004u) != 0; +inline bool CodeGeneratorResponse_File::_internal_has_content() const { + bool value = (_has_bits_[0] & 0x00000004u) != 0; + return value; } -inline void CodeGeneratorResponse_File::set_has_content() { - _has_bits_[0] |= 0x00000004u; -} -inline void CodeGeneratorResponse_File::clear_has_content() { - _has_bits_[0] &= ~0x00000004u; +inline bool CodeGeneratorResponse_File::has_content() const { + return _internal_has_content(); } inline void CodeGeneratorResponse_File::clear_content() { - content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_content(); + content_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000004u; } -inline const ::std::string& CodeGeneratorResponse_File::content() const { +inline const std::string& CodeGeneratorResponse_File::content() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content) - return content_.GetNoArena(); + return _internal_content(); } -inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) { - set_has_content(); - content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void CodeGeneratorResponse_File::set_content(const std::string& value) { + _internal_set_content(value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content) } -#if LANG_CXX11 -inline void CodeGeneratorResponse_File::set_content(::std::string&& value) { - set_has_content(); - content_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* CodeGeneratorResponse_File::mutable_content() { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content) + return _internal_mutable_content(); +} +inline const std::string& CodeGeneratorResponse_File::_internal_content() const { + return content_.Get(); +} +inline void CodeGeneratorResponse_File::_internal_set_content(const std::string& value) { + _has_bits_[0] |= 0x00000004u; + content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void CodeGeneratorResponse_File::set_content(std::string&& value) { + _has_bits_[0] |= 0x00000004u; + content_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.content) } -#endif inline void CodeGeneratorResponse_File::set_content(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_content(); - content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000004u; + content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content) } -inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) { - set_has_content(); - content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void CodeGeneratorResponse_File::set_content(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000004u; + content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content) } -inline ::std::string* CodeGeneratorResponse_File::mutable_content() { - set_has_content(); - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content) - return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* CodeGeneratorResponse_File::_internal_mutable_content() { + _has_bits_[0] |= 0x00000004u; + return content_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* CodeGeneratorResponse_File::release_content() { +inline std::string* CodeGeneratorResponse_File::release_content() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.content) - clear_has_content(); - return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_content()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000004u; + return content_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) { - if (content != NULL) { - set_has_content(); +inline void CodeGeneratorResponse_File::set_allocated_content(std::string* content) { + if (content != nullptr) { + _has_bits_[0] |= 0x00000004u; } else { - clear_has_content(); + _has_bits_[0] &= ~0x00000004u; } - content_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content); + content_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), content, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content) } +// optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; +inline bool CodeGeneratorResponse_File::_internal_has_generated_code_info() const { + bool value = (_has_bits_[0] & 0x00000008u) != 0; + PROTOBUF_ASSUME(!value || generated_code_info_ != nullptr); + return value; +} +inline bool CodeGeneratorResponse_File::has_generated_code_info() const { + return _internal_has_generated_code_info(); +} +inline const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& CodeGeneratorResponse_File::_internal_generated_code_info() const { + const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* p = generated_code_info_; + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_default_instance_); +} +inline const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& CodeGeneratorResponse_File::generated_code_info() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info) + return _internal_generated_code_info(); +} +inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_generated_code_info( + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info) { + if (GetArena() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(generated_code_info_); + } + generated_code_info_ = generated_code_info; + if (generated_code_info) { + _has_bits_[0] |= 0x00000008u; + } else { + _has_bits_[0] &= ~0x00000008u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info) +} +inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::release_generated_code_info() { + _has_bits_[0] &= ~0x00000008u; + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* temp = generated_code_info_; + generated_code_info_ = nullptr; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + return temp; +} +inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::unsafe_arena_release_generated_code_info() { + // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info) + _has_bits_[0] &= ~0x00000008u; + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* temp = generated_code_info_; + generated_code_info_ = nullptr; + return temp; +} +inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::_internal_mutable_generated_code_info() { + _has_bits_[0] |= 0x00000008u; + if (generated_code_info_ == nullptr) { + auto* p = CreateMaybeMessage(GetArena()); + generated_code_info_ = p; + } + return generated_code_info_; +} +inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::mutable_generated_code_info() { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info) + return _internal_mutable_generated_code_info(); +} +inline void CodeGeneratorResponse_File::set_allocated_generated_code_info(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + if (message_arena == nullptr) { + delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(generated_code_info_); + } + if (generated_code_info) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(generated_code_info)->GetArena(); + if (message_arena != submessage_arena) { + generated_code_info = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, generated_code_info, submessage_arena); + } + _has_bits_[0] |= 0x00000008u; + } else { + _has_bits_[0] &= ~0x00000008u; + } + generated_code_info_ = generated_code_info; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info) +} + // ------------------------------------------------------------------- // CodeGeneratorResponse // optional string error = 1; -inline bool CodeGeneratorResponse::has_error() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void CodeGeneratorResponse::set_has_error() { - _has_bits_[0] |= 0x00000001u; +inline bool CodeGeneratorResponse::_internal_has_error() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void CodeGeneratorResponse::clear_has_error() { - _has_bits_[0] &= ~0x00000001u; +inline bool CodeGeneratorResponse::has_error() const { + return _internal_has_error(); } inline void CodeGeneratorResponse::clear_error() { - error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_error(); + error_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& CodeGeneratorResponse::error() const { +inline const std::string& CodeGeneratorResponse::error() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error) - return error_.GetNoArena(); + return _internal_error(); } -inline void CodeGeneratorResponse::set_error(const ::std::string& value) { - set_has_error(); - error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void CodeGeneratorResponse::set_error(const std::string& value) { + _internal_set_error(value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error) } -#if LANG_CXX11 -inline void CodeGeneratorResponse::set_error(::std::string&& value) { - set_has_error(); - error_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* CodeGeneratorResponse::mutable_error() { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error) + return _internal_mutable_error(); +} +inline const std::string& CodeGeneratorResponse::_internal_error() const { + return error_.Get(); +} +inline void CodeGeneratorResponse::_internal_set_error(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void CodeGeneratorResponse::set_error(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + error_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.error) } -#endif inline void CodeGeneratorResponse::set_error(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_error(); - error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error) } -inline void CodeGeneratorResponse::set_error(const char* value, size_t size) { - set_has_error(); - error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void CodeGeneratorResponse::set_error(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error) } -inline ::std::string* CodeGeneratorResponse::mutable_error() { - set_has_error(); - // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error) - return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* CodeGeneratorResponse::_internal_mutable_error() { + _has_bits_[0] |= 0x00000001u; + return error_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* CodeGeneratorResponse::release_error() { +inline std::string* CodeGeneratorResponse::release_error() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.error) - clear_has_error(); - return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_error()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return error_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) { - if (error != NULL) { - set_has_error(); +inline void CodeGeneratorResponse::set_allocated_error(std::string* error) { + if (error != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_error(); + _has_bits_[0] &= ~0x00000001u; } - error_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error); + error_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), error, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error) } +// optional uint64 supported_features = 2; +inline bool CodeGeneratorResponse::_internal_has_supported_features() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool CodeGeneratorResponse::has_supported_features() const { + return _internal_has_supported_features(); +} +inline void CodeGeneratorResponse::clear_supported_features() { + supported_features_ = PROTOBUF_ULONGLONG(0); + _has_bits_[0] &= ~0x00000002u; +} +inline ::PROTOBUF_NAMESPACE_ID::uint64 CodeGeneratorResponse::_internal_supported_features() const { + return supported_features_; +} +inline ::PROTOBUF_NAMESPACE_ID::uint64 CodeGeneratorResponse::supported_features() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.supported_features) + return _internal_supported_features(); +} +inline void CodeGeneratorResponse::_internal_set_supported_features(::PROTOBUF_NAMESPACE_ID::uint64 value) { + _has_bits_[0] |= 0x00000002u; + supported_features_ = value; +} +inline void CodeGeneratorResponse::set_supported_features(::PROTOBUF_NAMESPACE_ID::uint64 value) { + _internal_set_supported_features(value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.supported_features) +} + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; -inline int CodeGeneratorResponse::file_size() const { +inline int CodeGeneratorResponse::_internal_file_size() const { return file_.size(); } +inline int CodeGeneratorResponse::file_size() const { + return _internal_file_size(); +} inline void CodeGeneratorResponse::clear_file() { file_.Clear(); } -inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file) - return file_.Get(index); -} -inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) { +inline PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file) return file_.Mutable(index); } -inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() { - // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file) - return file_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >* CodeGeneratorResponse::mutable_file() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file) return &file_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& +inline const PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::_internal_file(int index) const { + return file_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file) + return _internal_file(index); +} +inline PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::_internal_add_file() { + return file_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() { + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file) + return _internal_add_file(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >& CodeGeneratorResponse::file() const { // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file) return file_; @@ -1320,7 +1863,6 @@ CodeGeneratorResponse::file() const { #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ -#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // ------------------------------------------------------------------- // ------------------------------------------------------------------- @@ -1330,11 +1872,20 @@ CodeGeneratorResponse::file() const { // @@protoc_insertion_point(namespace_scope) - } // namespace compiler -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE + +PROTOBUF_NAMESPACE_OPEN + +template <> struct is_proto_enum< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature> : ::std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor< PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature>() { + return PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature_descriptor(); +} + +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) -#endif // PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto index 5b5574529ed48..9242aacc5bd9b 100644 --- a/src/google/protobuf/compiler/plugin.proto +++ b/src/google/protobuf/compiler/plugin.proto @@ -45,11 +45,12 @@ // flag "--${NAME}_out" is passed to protoc. syntax = "proto2"; + package google.protobuf.compiler; option java_package = "com.google.protobuf.compiler"; option java_outer_classname = "PluginProtos"; -option go_package = "github.com/golang/protobuf/protoc-gen-go/plugin;plugin_go"; +option go_package = "google.golang.org/protobuf/types/pluginpb"; import "google/protobuf/descriptor.proto"; @@ -106,6 +107,16 @@ message CodeGeneratorResponse { // exiting with a non-zero status code. optional string error = 1; + // A bitmask of supported features that the code generator supports. + // This is a bitwise "or" of values from the Feature enum. + optional uint64 supported_features = 2; + + // Sync with code_generator.h. + enum Feature { + FEATURE_NONE = 0; + FEATURE_PROTO3_OPTIONAL = 1; + } + // Represents a single generated file. message File { // The file name, relative to the output directory. The name must not @@ -162,6 +173,11 @@ message CodeGeneratorResponse { // The file contents. optional string content = 15; + + // Information describing the file content being inserted. If an insertion + // point is used, this information will be appropriately offset and inserted + // into the code generation metadata for the generated files. + optional GeneratedCodeInfo generated_code_info = 16; } repeated File file = 15; } diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc index 97769835e8666..95de716f923ee 100644 --- a/src/google/protobuf/compiler/python/python_generator.cc +++ b/src/google/protobuf/compiler/python/python_generator.cc @@ -28,8 +28,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -//#PY25 compatible generated code for GAE. -// Copyright 2007 Google Inc. All Rights Reserved. // Author: robinson@google.com (Will Robinson) // // This module outputs pure-Python protocol message classes that will @@ -44,31 +42,26 @@ // performance-minded Python code leverage the fast C++ implementation // directly. +#include + #include -#include #include #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include #include -#include -#include - #include #include #include +#include #include #include #include #include #include - namespace google { namespace protobuf { namespace compiler { @@ -76,40 +69,21 @@ namespace python { namespace { -// Reimplemented here because we can't bring in -// absl/strings/string_view_utils.h because it needs C++11. -bool StrStartsWith(StringPiece sp, StringPiece x) { - return sp.size() >= x.size() && sp.substr(0, x.size()) == x; -} -bool StrEndsWith(StringPiece sp, StringPiece x) { - return sp.size() >= x.size() && sp.substr(sp.size() - x.size()) == x; -} - -// Returns a copy of |filename| with any trailing ".protodevel" or ".proto -// suffix stripped. -// TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc. -string StripProto(const string& filename) { - const char* suffix = - StrEndsWith(filename, ".protodevel") ? ".protodevel" : ".proto"; - return StripSuffixString(filename, suffix); -} - // Returns the Python module name expected for a given .proto filename. -string ModuleName(const string& filename) { - string basename = StripProto(filename); +std::string ModuleName(const std::string& filename) { + std::string basename = StripProto(filename); ReplaceCharacters(&basename, "-", '_'); ReplaceCharacters(&basename, "/", '.'); return basename + "_pb2"; } - // Returns the alias we assign to the module of the given .proto filename // when importing. See testPackageInitializationImport in -// google/protobuf/python/reflection_test.py +// net/proto2/python/internal/reflection_test.py // to see why we need the alias. -string ModuleAlias(const string& filename) { - string module_name = ModuleName(filename); +std::string ModuleAlias(const std::string& filename) { + std::string module_name = ModuleName(filename); // We can't have dots in the module name, so we replace each with _dot_. // But that could lead to a collision between a.b and a_dot_b, so we also // duplicate each underscore. @@ -120,17 +94,18 @@ string ModuleAlias(const string& filename) { // Keywords reserved by the Python language. const char* const kKeywords[] = { - "False", "None", "True", "and", "as", "assert", "break", - "class", "continue", "def", "del", "elif", "else", "except", - "finally", "for", "from", "global", "if", "import", "in", - "is", "lambda", "nonlocal", "not", "or", "pass", "raise", - "return", "try", "while", "with", "yield", + "False", "None", "True", "and", "as", "assert", + "async", "await", "break", "class", "continue", "def", + "del", "elif", "else", "except", "finally", "for", + "from", "global", "if", "import", "in", "is", + "lambda", "nonlocal", "not", "or", "pass", "raise", + "return", "try", "while", "with", "yield", "print", }; const char* const* kKeywordsEnd = kKeywords + (sizeof(kKeywords) / sizeof(kKeywords[0])); -bool ContainsPythonKeyword(const string& module_name) { - std::vector tokens = Split(module_name, "."); +bool ContainsPythonKeyword(const std::string& module_name) { + std::vector tokens = Split(module_name, "."); for (int i = 0; i < tokens.size(); ++i) { if (std::find(kKeywords, kKeywordsEnd, tokens[i]) != kKeywordsEnd) { return true; @@ -139,52 +114,65 @@ bool ContainsPythonKeyword(const string& module_name) { return false; } +inline bool IsPythonKeyword(const std::string& name) { + return (std::find(kKeywords, kKeywordsEnd, name) != kKeywordsEnd); +} + +std::string ResolveKeyword(const std::string& name) { + if (IsPythonKeyword(name)) { + return "globals()['" + name + "']"; + } + return name; +} // Returns the name of all containing types for descriptor, // in order from outermost to innermost, followed by descriptor's // own name. Each name is separated by |separator|. template -string NamePrefixedWithNestedTypes(const DescriptorT& descriptor, - const string& separator) { - string name = descriptor.name(); - for (const Descriptor* current = descriptor.containing_type(); - current != NULL; current = current->containing_type()) { - name = current->name() + separator + name; +std::string NamePrefixedWithNestedTypes(const DescriptorT& descriptor, + const std::string& separator) { + std::string name = descriptor.name(); + const Descriptor* parent = descriptor.containing_type(); + if (parent != nullptr) { + std::string prefix = NamePrefixedWithNestedTypes(*parent, separator); + if (separator == "." && IsPythonKeyword(name)) { + return "getattr(" + prefix + ", '" + name + "')"; + } else { + return prefix + separator + name; + } + } + if (separator == ".") { + name = ResolveKeyword(name); } return name; } - // Name of the class attribute where we store the Python // descriptor.Descriptor instance for the generated class. // Must stay consistent with the _DESCRIPTOR_KEY constant // in proto2/public/reflection.py. const char kDescriptorKey[] = "DESCRIPTOR"; - // Does the file have top-level enums? -inline bool HasTopLevelEnums(const FileDescriptor *file) { +inline bool HasTopLevelEnums(const FileDescriptor* file) { return file->enum_type_count() > 0; } - // Should we generate generic services for this file? -inline bool HasGenericServices(const FileDescriptor *file) { - return file->service_count() > 0 && - file->options().py_generic_services(); +inline bool HasGenericServices(const FileDescriptor* file) { + return file->service_count() > 0 && file->options().py_generic_services(); } - // Prints the common boilerplate needed at the top of every .py // file output by this generator. -void PrintTopBoilerplate( - io::Printer* printer, const FileDescriptor* file, bool descriptor_proto) { +void PrintTopBoilerplate(io::Printer* printer, const FileDescriptor* file, + bool descriptor_proto) { // TODO(robinson): Allow parameterization of Python version? printer->Print( + "# -*- coding: utf-8 -*-\n" "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" "# source: $filename$\n" - "\nimport sys\n_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))" //##PY25 - "\n", + "\"\"\"Generated protocol buffer code.\"\"\"\n", "filename", file->name()); if (HasTopLevelEnums(file)) { printer->Print( @@ -202,18 +190,12 @@ void PrintTopBoilerplate( "from google.protobuf import service_reflection\n"); } - // Avoid circular imports if this module is descriptor_pb2. - if (!descriptor_proto) { - printer->Print( - "from google.protobuf import descriptor_pb2\n"); - } printer->Print( "# @@protoc_insertion_point(imports)\n\n" "_sym_db = _symbol_database.Default()\n"); printer->Print("\n\n"); } - // Returns a Python literal giving the default value for a field. // If the field specifies no explicit default value, we'll return // the default default value for the field type (zero for numbers, @@ -224,20 +206,20 @@ void PrintTopBoilerplate( // //compiler/cpp/internal/primitive_field.cc // //compiler/cpp/internal/enum_field.cc // //compiler/cpp/internal/string_field.cc -string StringifyDefaultValue(const FieldDescriptor& field) { +std::string StringifyDefaultValue(const FieldDescriptor& field) { if (field.is_repeated()) { return "[]"; } switch (field.cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: - return SimpleItoa(field.default_value_int32()); + return StrCat(field.default_value_int32()); case FieldDescriptor::CPPTYPE_UINT32: - return SimpleItoa(field.default_value_uint32()); + return StrCat(field.default_value_uint32()); case FieldDescriptor::CPPTYPE_INT64: - return SimpleItoa(field.default_value_int64()); + return StrCat(field.default_value_int64()); case FieldDescriptor::CPPTYPE_UINT64: - return SimpleItoa(field.default_value_uint64()); + return StrCat(field.default_value_uint64()); case FieldDescriptor::CPPTYPE_DOUBLE: { double value = field.default_value_double(); if (value == std::numeric_limits::infinity()) { @@ -273,14 +255,12 @@ string StringifyDefaultValue(const FieldDescriptor& field) { case FieldDescriptor::CPPTYPE_BOOL: return field.default_value_bool() ? "True" : "False"; case FieldDescriptor::CPPTYPE_ENUM: - return SimpleItoa(field.default_value_enum()->number()); + return StrCat(field.default_value_enum()->number()); case FieldDescriptor::CPPTYPE_STRING: -//##!PY25 return "b\"" + CEscape(field.default_value_string()) + -//##!PY25 (field.type() != FieldDescriptor::TYPE_STRING ? "\"" : -//##!PY25 "\".decode('utf-8')"); - return "_b(\"" + CEscape(field.default_value_string()) + //##PY25 - (field.type() != FieldDescriptor::TYPE_STRING ? "\")" : //##PY25 - "\").decode('utf-8')"); //##PY25 + return "b\"" + CEscape(field.default_value_string()) + + (field.type() != FieldDescriptor::TYPE_STRING + ? "\"" + : "\".decode('utf-8')"); case FieldDescriptor::CPPTYPE_MESSAGE: return "None"; } @@ -290,7 +270,7 @@ string StringifyDefaultValue(const FieldDescriptor& field) { return ""; } -string StringifySyntax(FileDescriptor::Syntax syntax) { +std::string StringifySyntax(FileDescriptor::Syntax syntax) { switch (syntax) { case FileDescriptor::SYNTAX_PROTO2: return "proto2"; @@ -304,20 +284,34 @@ string StringifySyntax(FileDescriptor::Syntax syntax) { } } - } // namespace +Generator::Generator() : file_(nullptr) {} -Generator::Generator() : file_(NULL) { -} +Generator::~Generator() {} -Generator::~Generator() { +uint64_t Generator::GetSupportedFeatures() const { + return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL; } bool Generator::Generate(const FileDescriptor* file, - const string& parameter, - GeneratorContext* context, - string* error) const { + const std::string& parameter, + GeneratorContext* context, std::string* error) const { + // ----------------------------------------------------------------- + // parse generator options + bool cpp_generated_lib_linked = false; + + std::vector > options; + ParseGeneratorParameter(parameter, &options); + + for (int i = 0; i < options.size(); i++) { + if (options[i].first == "cpp_generated_lib_linked") { + cpp_generated_lib_linked = true; + } else { + *error = "Unknown generator option: " + options[i].first; + return false; + } + } // Completely serialize all Generate() calls on this instance. The // thread-safety constraints of the CodeGenerator interface aren't clear so @@ -328,58 +322,69 @@ bool Generator::Generate(const FileDescriptor* file, // to have any mutable members. Then it is implicitly thread-safe. MutexLock lock(&mutex_); file_ = file; - string module_name = ModuleName(file->name()); - string filename = module_name; + std::string module_name = ModuleName(file->name()); + std::string filename = module_name; ReplaceCharacters(&filename, ".", '/'); filename += ".py"; + pure_python_workable_ = !cpp_generated_lib_linked; + if (HasPrefixString(file->name(), "google/protobuf/")) { + pure_python_workable_ = true; + } + FileDescriptorProto fdp; file_->CopyTo(&fdp); fdp.SerializeToString(&file_descriptor_serialized_); - google::protobuf::scoped_ptr output(context->Open(filename)); + std::unique_ptr output(context->Open(filename)); GOOGLE_CHECK(output.get()); io::Printer printer(output.get(), '$'); printer_ = &printer; PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto()); - PrintImports(); + if (pure_python_workable_) { + PrintImports(); + } PrintFileDescriptor(); PrintTopLevelEnums(); PrintTopLevelExtensions(); - PrintAllNestedEnumsInFile(); - PrintMessageDescriptors(); - FixForeignFieldsInDescriptors(); + if (pure_python_workable_) { + PrintAllNestedEnumsInFile(); + PrintMessageDescriptors(); + FixForeignFieldsInDescriptors(); + } PrintMessages(); - // We have to fix up the extensions after the message classes themselves, - // since they need to call static RegisterExtension() methods on these - // classes. - FixForeignFieldsInExtensions(); - // Descriptor options may have custom extensions. These custom options - // can only be successfully parsed after we register corresponding - // extensions. Therefore we parse all options again here to recognize - // custom options that may be unknown when we define the descriptors. - // This does not apply to services because they are not used by extensions. - FixAllDescriptorOptions(); - PrintServiceDescriptors(); + if (pure_python_workable_) { + // We have to fix up the extensions after the message classes themselves, + // since they need to call static RegisterExtension() methods on these + // classes. + FixForeignFieldsInExtensions(); + // Descriptor options may have custom extensions. These custom options + // can only be successfully parsed after we register corresponding + // extensions. Therefore we parse all options again here to recognize + // custom options that may be unknown when we define the descriptors. + // This does not apply to services because they are not used by extensions. + FixAllDescriptorOptions(); + PrintServiceDescriptors(); + } if (HasGenericServices(file)) { PrintServices(); } - printer.Print( - "# @@protoc_insertion_point(module_scope)\n"); + printer.Print("# @@protoc_insertion_point(module_scope)\n"); return !printer.failed(); } + // Prints Python imports for all modules imported by |file|. void Generator::PrintImports() const { for (int i = 0; i < file_->dependency_count(); ++i) { - const string& filename = file_->dependency(i)->name(); + const std::string& filename = file_->dependency(i)->name(); - string module_name = ModuleName(filename); - string module_alias = ModuleAlias(filename); + std::string module_name = ModuleName(filename); + std::string module_alias = ModuleAlias(filename); if (ContainsPythonKeyword(module_name)) { // If the module path contains a Python keyword, we have to quote the // module name and import it using importlib. Otherwise the usual kind of @@ -390,8 +395,8 @@ void Generator::PrintImports() const { module_alias, "name", module_name); } else { int last_dot_pos = module_name.rfind('.'); - string import_statement; - if (last_dot_pos == string::npos) { + std::string import_statement; + if (last_dot_pos == std::string::npos) { // NOTE(petya): this is not tested as it would require a protocol buffer // outside of any package, and I don't think that is easily achievable. import_statement = "import " + module_name; @@ -409,7 +414,7 @@ void Generator::PrintImports() const { // Print public imports. for (int i = 0; i < file_->public_dependency_count(); ++i) { - string module_name = ModuleName(file_->public_dependency(i)->name()); + std::string module_name = ModuleName(file_->public_dependency(i)->name()); printer_->Print("from $module$ import *\n", "module", module_name); } printer_->Print("\n"); @@ -417,39 +422,45 @@ void Generator::PrintImports() const { // Prints the single file descriptor for this file. void Generator::PrintFileDescriptor() const { - std::map m; + std::map m; m["descriptor_name"] = kDescriptorKey; m["name"] = file_->name(); m["package"] = file_->package(); m["syntax"] = StringifySyntax(file_->syntax()); + m["options"] = OptionsValue(file_->options().SerializeAsString()); const char file_descriptor_template[] = "$descriptor_name$ = _descriptor.FileDescriptor(\n" " name='$name$',\n" " package='$package$',\n" - " syntax='$syntax$',\n"; + " syntax='$syntax$',\n" + " serialized_options=$options$,\n" + " create_key=_descriptor._internal_create_key,\n"; printer_->Print(m, file_descriptor_template); printer_->Indent(); - printer_->Print( -//##!PY25 "serialized_pb=b'$value$'\n", - "serialized_pb=_b('$value$')\n", //##PY25 - "value", strings::CHexEscape(file_descriptor_serialized_)); - if (file_->dependency_count() != 0) { - printer_->Print(",\ndependencies=["); - for (int i = 0; i < file_->dependency_count(); ++i) { - string module_alias = ModuleAlias(file_->dependency(i)->name()); - printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias", - module_alias); + if (pure_python_workable_) { + printer_->Print("serialized_pb=b'$value$'\n", "value", + strings::CHexEscape(file_descriptor_serialized_)); + if (file_->dependency_count() != 0) { + printer_->Print(",\ndependencies=["); + for (int i = 0; i < file_->dependency_count(); ++i) { + std::string module_alias = ModuleAlias(file_->dependency(i)->name()); + printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias", + module_alias); + } + printer_->Print("]"); } - printer_->Print("]"); - } - if (file_->public_dependency_count() > 0) { - printer_->Print(",\npublic_dependencies=["); - for (int i = 0; i < file_->public_dependency_count(); ++i) { - string module_alias = ModuleAlias(file_->public_dependency(i)->name()); - printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias", - module_alias); + if (file_->public_dependency_count() > 0) { + printer_->Print(",\npublic_dependencies=["); + for (int i = 0; i < file_->public_dependency_count(); ++i) { + std::string module_alias = + ModuleAlias(file_->public_dependency(i)->name()); + printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias", + module_alias); + } + printer_->Print("]"); } - printer_->Print("]"); + } else { + printer_->Print("serialized_pb=''\n"); } // TODO(falk): Also print options and fix the message_type, enum_type, @@ -463,15 +474,15 @@ void Generator::PrintFileDescriptor() const { // Prints descriptors and module-level constants for all top-level // enums defined in |file|. void Generator::PrintTopLevelEnums() const { - std::vector > top_level_enum_values; + std::vector > top_level_enum_values; for (int i = 0; i < file_->enum_type_count(); ++i) { const EnumDescriptor& enum_descriptor = *file_->enum_type(i); PrintEnum(enum_descriptor); - printer_->Print("$name$ = " - "enum_type_wrapper.EnumTypeWrapper($descriptor_name$)", - "name", enum_descriptor.name(), - "descriptor_name", - ModuleLevelDescriptorName(enum_descriptor)); + printer_->Print( + "$name$ = " + "enum_type_wrapper.EnumTypeWrapper($descriptor_name$)", + "name", ResolveKeyword(enum_descriptor.name()), "descriptor_name", + ModuleLevelDescriptorName(enum_descriptor)); printer_->Print("\n"); for (int j = 0; j < enum_descriptor.value_count(); ++j) { @@ -482,9 +493,9 @@ void Generator::PrintTopLevelEnums() const { } for (int i = 0; i < top_level_enum_values.size(); ++i) { - printer_->Print("$name$ = $value$\n", - "name", top_level_enum_values[i].first, - "value", SimpleItoa(top_level_enum_values[i].second)); + printer_->Print("$name$ = $value$\n", "name", + ResolveKeyword(top_level_enum_values[i].first), "value", + StrCat(top_level_enum_values[i].second)); } printer_->Print("\n"); } @@ -500,8 +511,8 @@ void Generator::PrintAllNestedEnumsInFile() const { // enum name to a Python EnumDescriptor object equivalent to // enum_descriptor. void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { - std::map m; - string module_level_descriptor_name = + std::map m; + std::string module_level_descriptor_name = ModuleLevelDescriptorName(enum_descriptor); m["descriptor_name"] = module_level_descriptor_name; m["name"] = enum_descriptor.name(); @@ -513,28 +524,34 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { " full_name='$full_name$',\n" " filename=None,\n" " file=$file$,\n" + " create_key=_descriptor._internal_create_key,\n" " values=[\n"; - string options_string; + std::string options_string; enum_descriptor.options().SerializeToString(&options_string); printer_->Print(m, enum_descriptor_template); printer_->Indent(); printer_->Indent(); - for (int i = 0; i < enum_descriptor.value_count(); ++i) { - PrintEnumValueDescriptor(*enum_descriptor.value(i)); - printer_->Print(",\n"); + + if (pure_python_workable_) { + for (int i = 0; i < enum_descriptor.value_count(); ++i) { + PrintEnumValueDescriptor(*enum_descriptor.value(i)); + printer_->Print(",\n"); + } } + printer_->Outdent(); printer_->Print("],\n"); printer_->Print("containing_type=None,\n"); - printer_->Print("options=$options_value$,\n", - "options_value", - OptionsValue("EnumOptions", options_string)); + printer_->Print("serialized_options=$options_value$,\n", "options_value", + OptionsValue(options_string)); EnumDescriptorProto edp; PrintSerializedPbInterval(enum_descriptor, edp); printer_->Outdent(); printer_->Print(")\n"); - printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name", - module_level_descriptor_name); + if (pure_python_workable_) { + printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name", + module_level_descriptor_name); + } printer_->Print("\n"); } @@ -554,12 +571,13 @@ void Generator::PrintTopLevelExtensions() const { const bool is_extension = true; for (int i = 0; i < file_->extension_count(); ++i) { const FieldDescriptor& extension_field = *file_->extension(i); - string constant_name = extension_field.name() + "_FIELD_NUMBER"; - UpperString(&constant_name); - printer_->Print("$constant_name$ = $number$\n", - "constant_name", constant_name, - "number", SimpleItoa(extension_field.number())); - printer_->Print("$name$ = ", "name", extension_field.name()); + std::string constant_name = extension_field.name() + "_FIELD_NUMBER"; + ToUpper(&constant_name); + printer_->Print("$constant_name$ = $number$\n", "constant_name", + constant_name, "number", + StrCat(extension_field.number())); + printer_->Print("$name$ = ", "name", + ResolveKeyword(extension_field.name())); PrintFieldDescriptor(extension_field, is_extension); printer_->Print("\n"); } @@ -593,26 +611,26 @@ void Generator::PrintServices() const { void Generator::PrintServiceDescriptor( const ServiceDescriptor& descriptor) const { printer_->Print("\n"); - string service_name = ModuleLevelServiceDescriptorName(descriptor); - string options_string; + std::string service_name = ModuleLevelServiceDescriptorName(descriptor); + std::string options_string; descriptor.options().SerializeToString(&options_string); - printer_->Print( - "$service_name$ = _descriptor.ServiceDescriptor(\n", - "service_name", service_name); + printer_->Print("$service_name$ = _descriptor.ServiceDescriptor(\n", + "service_name", service_name); printer_->Indent(); - std::map m; + std::map m; m["name"] = descriptor.name(); m["full_name"] = descriptor.full_name(); m["file"] = kDescriptorKey; - m["index"] = SimpleItoa(descriptor.index()); - m["options_value"] = OptionsValue("ServiceOptions", options_string); + m["index"] = StrCat(descriptor.index()); + m["options_value"] = OptionsValue(options_string); const char required_function_arguments[] = "name='$name$',\n" "full_name='$full_name$',\n" "file=$file$,\n" "index=$index$,\n" - "options=$options_value$,\n"; + "serialized_options=$options_value$,\n" + "create_key=_descriptor._internal_create_key,\n"; printer_->Print(m, required_function_arguments); ServiceDescriptorProto sdp; @@ -626,22 +644,22 @@ void Generator::PrintServiceDescriptor( m.clear(); m["name"] = method->name(); m["full_name"] = method->full_name(); - m["index"] = SimpleItoa(method->index()); + m["index"] = StrCat(method->index()); m["serialized_options"] = CEscape(options_string); m["input_type"] = ModuleLevelDescriptorName(*(method->input_type())); m["output_type"] = ModuleLevelDescriptorName(*(method->output_type())); - m["options_value"] = OptionsValue("MethodOptions", options_string); + m["options_value"] = OptionsValue(options_string); printer_->Print("_descriptor.MethodDescriptor(\n"); printer_->Indent(); - printer_->Print( - m, - "name='$name$',\n" - "full_name='$full_name$',\n" - "index=$index$,\n" - "containing_service=None,\n" - "input_type=$input_type$,\n" - "output_type=$output_type$,\n" - "options=$options_value$,\n"); + printer_->Print(m, + "name='$name$',\n" + "full_name='$full_name$',\n" + "index=$index$,\n" + "containing_service=None,\n" + "input_type=$input_type$,\n" + "output_type=$output_type$,\n" + "serialized_options=$options_value$,\n" + "create_key=_descriptor._internal_create_key,\n"); printer_->Outdent(); printer_->Print("),\n"); } @@ -653,23 +671,25 @@ void Generator::PrintServiceDescriptor( printer_->Print("\n"); } - void Generator::PrintDescriptorKeyAndModuleName( const ServiceDescriptor& descriptor) const { - printer_->Print( - "$descriptor_key$ = $descriptor_name$,\n", - "descriptor_key", kDescriptorKey, - "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); - printer_->Print( - "__module__ = '$module_name$'\n", - "module_name", ModuleName(file_->name())); + std::string name = ModuleLevelServiceDescriptorName(descriptor); + if (!pure_python_workable_) { + name = "_descriptor.ServiceDescriptor(full_name='" + + descriptor.full_name() + "')"; + } + printer_->Print("$descriptor_key$ = $descriptor_name$,\n", "descriptor_key", + kDescriptorKey, "descriptor_name", name); + std::string module_name = ModuleName(file_->name()); + printer_->Print("__module__ = '$module_name$'\n", "module_name", module_name); } void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const { // Print the service. - printer_->Print("$class_name$ = service_reflection.GeneratedServiceType(" - "'$class_name$', (_service.Service,), dict(\n", - "class_name", descriptor.name()); + printer_->Print( + "$class_name$ = service_reflection.GeneratedServiceType(" + "'$class_name$', (_service.Service,), dict(\n", + "class_name", descriptor.name()); printer_->Indent(); Generator::PrintDescriptorKeyAndModuleName(descriptor); printer_->Print("))\n\n"); @@ -678,10 +698,11 @@ void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const { void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const { // Print the service stub. - printer_->Print("$class_name$_Stub = " - "service_reflection.GeneratedServiceStubType(" - "'$class_name$_Stub', ($class_name$,), dict(\n", - "class_name", descriptor.name()); + printer_->Print( + "$class_name$_Stub = " + "service_reflection.GeneratedServiceStubType(" + "'$class_name$_Stub', ($class_name$,), dict(\n", + "class_name", descriptor.name()); printer_->Indent(); Generator::PrintDescriptorKeyAndModuleName(descriptor); printer_->Print("))\n\n"); @@ -700,7 +721,7 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { "descriptor_name", ModuleLevelDescriptorName(message_descriptor)); printer_->Indent(); - std::map m; + std::map m; m["name"] = message_descriptor.name(); m["full_name"] = message_descriptor.full_name(); m["file"] = kDescriptorKey; @@ -709,7 +730,8 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { "full_name='$full_name$',\n" "filename=None,\n" "file=$file$,\n" - "containing_type=None,\n"; + "containing_type=None,\n" + "create_key=_descriptor._internal_create_key,\n"; printer_->Print(m, required_function_arguments); PrintFieldsInDescriptor(message_descriptor); PrintExtensionsInDescriptor(message_descriptor); @@ -717,8 +739,8 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { // Nested types printer_->Print("nested_types=["); for (int i = 0; i < message_descriptor.nested_type_count(); ++i) { - const string nested_name = ModuleLevelDescriptorName( - *message_descriptor.nested_type(i)); + const std::string nested_name = + ModuleLevelDescriptorName(*message_descriptor.nested_type(i)); printer_->Print("$name$, ", "name", nested_name); } printer_->Print("],\n"); @@ -727,22 +749,21 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { printer_->Print("enum_types=[\n"); printer_->Indent(); for (int i = 0; i < message_descriptor.enum_type_count(); ++i) { - const string descriptor_name = ModuleLevelDescriptorName( - *message_descriptor.enum_type(i)); + const std::string descriptor_name = + ModuleLevelDescriptorName(*message_descriptor.enum_type(i)); printer_->Print(descriptor_name.c_str()); printer_->Print(",\n"); } printer_->Outdent(); printer_->Print("],\n"); - string options_string; + std::string options_string; message_descriptor.options().SerializeToString(&options_string); printer_->Print( - "options=$options_value$,\n" + "serialized_options=$options_value$,\n" "is_extendable=$extendable$,\n" "syntax='$syntax$'", - "options_value", OptionsValue("MessageOptions", options_string), - "extendable", message_descriptor.extension_range_count() > 0 ? - "True" : "False", + "options_value", OptionsValue(options_string), "extendable", + message_descriptor.extension_range_count() > 0 ? "True" : "False", "syntax", StringifySyntax(message_descriptor.file()->syntax())); printer_->Print(",\n"); @@ -751,31 +772,31 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { for (int i = 0; i < message_descriptor.extension_range_count(); ++i) { const Descriptor::ExtensionRange* range = message_descriptor.extension_range(i); - printer_->Print("($start$, $end$), ", - "start", SimpleItoa(range->start), - "end", SimpleItoa(range->end)); + printer_->Print("($start$, $end$), ", "start", StrCat(range->start), + "end", StrCat(range->end)); } printer_->Print("],\n"); printer_->Print("oneofs=[\n"); printer_->Indent(); for (int i = 0; i < message_descriptor.oneof_decl_count(); ++i) { const OneofDescriptor* desc = message_descriptor.oneof_decl(i); - std::map m; + std::map m; m["name"] = desc->name(); m["full_name"] = desc->full_name(); - m["index"] = SimpleItoa(desc->index()); - string options_string = - OptionsValue("OneofOptions", desc->options().SerializeAsString()); + m["index"] = StrCat(desc->index()); + std::string options_string = + OptionsValue(desc->options().SerializeAsString()); if (options_string == "None") { - m["options"] = ""; + m["serialized_options"] = ""; } else { - m["options"] = ", options=" + options_string; + m["serialized_options"] = ", serialized_options=" + options_string; } - printer_->Print( - m, - "_descriptor.OneofDescriptor(\n" - " name='$name$', full_name='$full_name$',\n" - " index=$index$, containing_type=None, fields=[]$options$),\n"); + printer_->Print(m, + "_descriptor.OneofDescriptor(\n" + " name='$name$', full_name='$full_name$',\n" + " index=$index$, containing_type=None,\n" + " create_key=_descriptor._internal_create_key,\n" + "fields=[]$serialized_options$),\n"); } printer_->Outdent(); printer_->Print("],\n"); @@ -801,11 +822,11 @@ void Generator::PrintNestedDescriptors( // Prints all messages in |file|. void Generator::PrintMessages() const { for (int i = 0; i < file_->message_type_count(); ++i) { - std::vector to_register; - PrintMessage(*file_->message_type(i), "", &to_register); + std::vector to_register; + PrintMessage(*file_->message_type(i), "", &to_register, false); for (int j = 0; j < to_register.size(); ++j) { printer_->Print("_sym_db.RegisterMessage($name$)\n", "name", - to_register[j]); + ResolveKeyword(to_register[j])); } printer_->Print("\n"); } @@ -820,37 +841,60 @@ void Generator::PrintMessages() const { // Mutually recursive with PrintNestedMessages(). // Collect nested message names to_register for the symbol_database. void Generator::PrintMessage(const Descriptor& message_descriptor, - const string& prefix, - std::vector* to_register) const { - string qualified_name(prefix + message_descriptor.name()); - to_register->push_back(qualified_name); - printer_->Print( - "$name$ = _reflection.GeneratedProtocolMessageType('$name$', " - "(_message.Message,), dict(\n", - "name", message_descriptor.name()); + const std::string& prefix, + std::vector* to_register, + bool is_nested) const { + std::string qualified_name; + if (is_nested) { + if (IsPythonKeyword(message_descriptor.name())) { + qualified_name = + "getattr(" + prefix + ", '" + message_descriptor.name() + "')"; + } else { + qualified_name = prefix + "." + message_descriptor.name(); + } + printer_->Print( + "'$name$' : _reflection.GeneratedProtocolMessageType('$name$', " + "(_message.Message,), {\n", + "name", message_descriptor.name()); + } else { + qualified_name = ResolveKeyword(message_descriptor.name()); + printer_->Print( + "$qualified_name$ = _reflection.GeneratedProtocolMessageType('$name$', " + "(_message.Message,), {\n", + "qualified_name", qualified_name, "name", message_descriptor.name()); + } printer_->Indent(); - PrintNestedMessages(message_descriptor, qualified_name + ".", to_register); - std::map m; + to_register->push_back(qualified_name); + + PrintNestedMessages(message_descriptor, qualified_name, to_register); + std::map m; m["descriptor_key"] = kDescriptorKey; - m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor); - printer_->Print(m, "$descriptor_key$ = $descriptor_name$,\n"); - printer_->Print("__module__ = '$module_name$'\n", - "module_name", ModuleName(file_->name())); + if (pure_python_workable_) { + m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor); + } else { + m["descriptor_name"] = "_descriptor.Descriptor(full_name='" + + message_descriptor.full_name() + "')"; + } + printer_->Print(m, "'$descriptor_key$' : $descriptor_name$,\n"); + std::string module_name = ModuleName(file_->name()); + printer_->Print("'__module__' : '$module_name$'\n", "module_name", + module_name); printer_->Print("# @@protoc_insertion_point(class_scope:$full_name$)\n", "full_name", message_descriptor.full_name()); - printer_->Print("))\n"); + printer_->Print("})\n"); printer_->Outdent(); } // Prints all nested messages within |containing_descriptor|. // Mutually recursive with PrintMessage(). -void Generator::PrintNestedMessages(const Descriptor& containing_descriptor, - const string& prefix, - std::vector* to_register) const { +void Generator::PrintNestedMessages( + const Descriptor& containing_descriptor, const std::string& prefix, + std::vector* to_register) const { for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) { printer_->Print("\n"); - PrintMessage(*containing_descriptor.nested_type(i), prefix, to_register); + PrintMessage(*containing_descriptor.nested_type(i), prefix, to_register, + true); printer_->Print(",\n"); } } @@ -880,7 +924,7 @@ void Generator::FixForeignFieldsInDescriptor( FixContainingTypeInDescriptor(enum_descriptor, &descriptor); } for (int i = 0; i < descriptor.oneof_decl_count(); ++i) { - std::map m; + std::map m; const OneofDescriptor* oneof = descriptor.oneof_decl(i); m["descriptor_name"] = ModuleLevelDescriptorName(descriptor); m["oneof_name"] = oneof->name(); @@ -899,7 +943,7 @@ void Generator::FixForeignFieldsInDescriptor( } void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { - std::map m; + std::map m; m["descriptor_name"] = kDescriptorKey; m["message_name"] = descriptor.name(); m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor); @@ -911,7 +955,7 @@ void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { void Generator::AddServiceToFileDescriptor( const ServiceDescriptor& descriptor) const { - std::map m; + std::map m; m["descriptor_name"] = kDescriptorKey; m["service_name"] = descriptor.name(); m["service_descriptor_name"] = ModuleLevelServiceDescriptorName(descriptor); @@ -923,7 +967,7 @@ void Generator::AddServiceToFileDescriptor( void Generator::AddEnumToFileDescriptor( const EnumDescriptor& descriptor) const { - std::map m; + std::map m; m["descriptor_name"] = kDescriptorKey; m["enum_name"] = descriptor.name(); m["enum_descriptor_name"] = ModuleLevelDescriptorName(descriptor); @@ -935,12 +979,13 @@ void Generator::AddEnumToFileDescriptor( void Generator::AddExtensionToFileDescriptor( const FieldDescriptor& descriptor) const { - std::map m; + std::map m; m["descriptor_name"] = kDescriptorKey; m["field_name"] = descriptor.name(); + m["resolved_name"] = ResolveKeyword(descriptor.name()); const char file_descriptor_template[] = "$descriptor_name$.extensions_by_name['$field_name$'] = " - "$field_name$\n"; + "$resolved_name$\n"; printer_->Print(m, file_descriptor_template); } @@ -953,12 +998,12 @@ void Generator::AddExtensionToFileDescriptor( // look the field up in the containing type. (e.g., fields_by_name // or extensions_by_name). We ignore python_dict_name if containing_type // is NULL. -void Generator::FixForeignFieldsInField(const Descriptor* containing_type, - const FieldDescriptor& field, - const string& python_dict_name) const { - const string field_referencing_expression = FieldReferencingExpression( - containing_type, field, python_dict_name); - std::map m; +void Generator::FixForeignFieldsInField( + const Descriptor* containing_type, const FieldDescriptor& field, + const std::string& python_dict_name) const { + const std::string field_referencing_expression = + FieldReferencingExpression(containing_type, field, python_dict_name); + std::map m; m["field_ref"] = field_referencing_expression; const Descriptor* foreign_message_type = field.message_type(); if (foreign_message_type) { @@ -981,21 +1026,19 @@ void Generator::FixForeignFieldsInField(const Descriptor* containing_type, // look the field up in the containing type. (e.g., fields_by_name // or extensions_by_name). We ignore python_dict_name if containing_type // is NULL. -string Generator::FieldReferencingExpression( - const Descriptor* containing_type, - const FieldDescriptor& field, - const string& python_dict_name) const { +std::string Generator::FieldReferencingExpression( + const Descriptor* containing_type, const FieldDescriptor& field, + const std::string& python_dict_name) const { // We should only ever be looking up fields in the current file. // The only things we refer to from other files are message descriptors. - GOOGLE_CHECK_EQ(field.file(), file_) << field.file()->name() << " vs. " - << file_->name(); + GOOGLE_CHECK_EQ(field.file(), file_) + << field.file()->name() << " vs. " << file_->name(); if (!containing_type) { - return field.name(); + return ResolveKeyword(field.name()); } - return strings::Substitute( - "$0.$1['$2']", - ModuleLevelDescriptorName(*containing_type), - python_dict_name, field.name()); + return strings::Substitute("$0.$1['$2']", + ModuleLevelDescriptorName(*containing_type), + python_dict_name, field.name()); } // Prints containing_type for nested descriptors or enum descriptors. @@ -1003,24 +1046,22 @@ template void Generator::FixContainingTypeInDescriptor( const DescriptorT& descriptor, const Descriptor* containing_descriptor) const { - if (containing_descriptor != NULL) { - const string nested_name = ModuleLevelDescriptorName(descriptor); - const string parent_name = ModuleLevelDescriptorName( - *containing_descriptor); - printer_->Print( - "$nested_name$.containing_type = $parent_name$\n", - "nested_name", nested_name, - "parent_name", parent_name); + if (containing_descriptor != nullptr) { + const std::string nested_name = ModuleLevelDescriptorName(descriptor); + const std::string parent_name = + ModuleLevelDescriptorName(*containing_descriptor); + printer_->Print("$nested_name$.containing_type = $parent_name$\n", + "nested_name", nested_name, "parent_name", parent_name); } } // Prints statements setting the message_type and enum_type fields in the -// Python descriptor objects we've already output in ths file. We must +// Python descriptor objects we've already output in the file. We must // do this in a separate step due to circular references (otherwise, we'd // just set everything in the initial assignment statements). void Generator::FixForeignFieldsInDescriptors() const { for (int i = 0; i < file_->message_type_count(); ++i) { - FixForeignFieldsInDescriptor(*file_->message_type(i), NULL); + FixForeignFieldsInDescriptor(*file_->message_type(i), nullptr); } for (int i = 0; i < file_->message_type_count(); ++i) { AddMessageToFileDescriptor(*file_->message_type(i)); @@ -1031,6 +1072,7 @@ void Generator::FixForeignFieldsInDescriptors() const { for (int i = 0; i < file_->extension_count(); ++i) { AddExtensionToFileDescriptor(*file_->extension(i)); } + // TODO(jieluo): Move this register to PrintFileDescriptor() when // FieldDescriptor.file is added in generated file. printer_->Print("_sym_db.RegisterFileDescriptor($name$)\n", "name", @@ -1061,16 +1103,15 @@ void Generator::FixForeignFieldsInExtension( FixForeignFieldsInField(extension_field.extension_scope(), extension_field, "extensions_by_name"); - std::map m; + std::map m; // Confusingly, for FieldDescriptors that happen to be extensions, // containing_type() means "extended type." // On the other hand, extension_scope() will give us what we normally // mean by containing_type(). - m["extended_message_class"] = ModuleLevelMessageName( - *extension_field.containing_type()); - m["field"] = FieldReferencingExpression(extension_field.extension_scope(), - extension_field, - "extensions_by_name"); + m["extended_message_class"] = + ModuleLevelMessageName(*extension_field.containing_type()); + m["field"] = FieldReferencingExpression( + extension_field.extension_scope(), extension_field, "extensions_by_name"); printer_->Print(m, "$extended_message_class$.RegisterExtension($field$)\n"); } @@ -1092,81 +1133,75 @@ void Generator::PrintEnumValueDescriptor( const EnumValueDescriptor& descriptor) const { // TODO(robinson): Fix up EnumValueDescriptor "type" fields. // More circular references. ::sigh:: - string options_string; + std::string options_string; descriptor.options().SerializeToString(&options_string); - std::map m; + std::map m; m["name"] = descriptor.name(); - m["index"] = SimpleItoa(descriptor.index()); - m["number"] = SimpleItoa(descriptor.number()); - m["options"] = OptionsValue("EnumValueOptions", options_string); - printer_->Print( - m, - "_descriptor.EnumValueDescriptor(\n" - " name='$name$', index=$index$, number=$number$,\n" - " options=$options$,\n" - " type=None)"); -} - -// Returns a Python expression that calls descriptor._ParseOptions using -// the given descriptor class name and serialized options protobuf string. -string Generator::OptionsValue( - const string& class_name, const string& serialized_options) const { + m["index"] = StrCat(descriptor.index()); + m["number"] = StrCat(descriptor.number()); + m["options"] = OptionsValue(options_string); + printer_->Print(m, + "_descriptor.EnumValueDescriptor(\n" + " name='$name$', index=$index$, number=$number$,\n" + " serialized_options=$options$,\n" + " type=None,\n" + " create_key=_descriptor._internal_create_key)"); +} + +// Returns a CEscaped string of serialized_options. +std::string Generator::OptionsValue( + const std::string& serialized_options) const { if (serialized_options.length() == 0 || GeneratingDescriptorProto()) { return "None"; } else { - string full_class_name = "descriptor_pb2." + class_name; -//##!PY25 return "_descriptor._ParseOptions(" + full_class_name + "(), b'" -//##!PY25 + CEscape(serialized_options)+ "')"; - return "_descriptor._ParseOptions(" + full_class_name + "(), _b('" //##PY25 - + CEscape(serialized_options)+ "'))"; //##PY25 + return "b'" + CEscape(serialized_options) + "'"; } } // Prints an expression for a Python FieldDescriptor for |field|. -void Generator::PrintFieldDescriptor( - const FieldDescriptor& field, bool is_extension) const { - string options_string; +void Generator::PrintFieldDescriptor(const FieldDescriptor& field, + bool is_extension) const { + std::string options_string; field.options().SerializeToString(&options_string); - std::map m; + std::map m; m["name"] = field.name(); m["full_name"] = field.full_name(); - m["index"] = SimpleItoa(field.index()); - m["number"] = SimpleItoa(field.number()); - m["type"] = SimpleItoa(field.type()); - m["cpp_type"] = SimpleItoa(field.cpp_type()); - m["label"] = SimpleItoa(field.label()); + m["index"] = StrCat(field.index()); + m["number"] = StrCat(field.number()); + m["type"] = StrCat(field.type()); + m["cpp_type"] = StrCat(field.cpp_type()); + m["label"] = StrCat(field.label()); m["has_default_value"] = field.has_default_value() ? "True" : "False"; m["default_value"] = StringifyDefaultValue(field); m["is_extension"] = is_extension ? "True" : "False"; - m["options"] = OptionsValue("FieldOptions", options_string); - m["json_name"] = field.has_json_name() ? - ", json_name='" + field.json_name() + "'": ""; + m["serialized_options"] = OptionsValue(options_string); + m["json_name"] = + field.has_json_name() ? ", json_name='" + field.json_name() + "'" : ""; // We always set message_type and enum_type to None at this point, and then // these fields in correctly after all referenced descriptors have been // defined and/or imported (see FixForeignFieldsInDescriptors()). const char field_descriptor_decl[] = - "_descriptor.FieldDescriptor(\n" - " name='$name$', full_name='$full_name$', index=$index$,\n" - " number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n" - " has_default_value=$has_default_value$, default_value=$default_value$,\n" - " message_type=None, enum_type=None, containing_type=None,\n" - " is_extension=$is_extension$, extension_scope=None,\n" - " options=$options$$json_name$)"; + "_descriptor.FieldDescriptor(\n" + " name='$name$', full_name='$full_name$', index=$index$,\n" + " number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n" + " has_default_value=$has_default_value$, " + "default_value=$default_value$,\n" + " message_type=None, enum_type=None, containing_type=None,\n" + " is_extension=$is_extension$, extension_scope=None,\n" + " serialized_options=$serialized_options$$json_name$, file=DESCRIPTOR," + " create_key=_descriptor._internal_create_key)"; printer_->Print(m, field_descriptor_decl); } // Helper for Print{Fields,Extensions}InDescriptor(). void Generator::PrintFieldDescriptorsInDescriptor( - const Descriptor& message_descriptor, - bool is_extension, - const string& list_variable_name, - int (Descriptor::*CountFn)() const, - const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const { + const Descriptor& message_descriptor, bool is_extension, + const std::string& list_variable_name, int (Descriptor::*CountFn)() const, + const FieldDescriptor* (Descriptor::*GetterFn)(int)const) const { printer_->Print("$list$=[\n", "list", list_variable_name); printer_->Indent(); for (int i = 0; i < (message_descriptor.*CountFn)(); ++i) { - PrintFieldDescriptor(*(message_descriptor.*GetterFn)(i), - is_extension); + PrintFieldDescriptor(*(message_descriptor.*GetterFn)(i), is_extension); printer_->Print(",\n"); } printer_->Outdent(); @@ -1178,9 +1213,9 @@ void Generator::PrintFieldDescriptorsInDescriptor( void Generator::PrintFieldsInDescriptor( const Descriptor& message_descriptor) const { const bool is_extension = false; - PrintFieldDescriptorsInDescriptor( - message_descriptor, is_extension, "fields", - &Descriptor::field_count, &Descriptor::field); + PrintFieldDescriptorsInDescriptor(message_descriptor, is_extension, "fields", + &Descriptor::field_count, + &Descriptor::field); } // Prints a statement assigning "extensions" to a list of Python @@ -1188,20 +1223,21 @@ void Generator::PrintFieldsInDescriptor( void Generator::PrintExtensionsInDescriptor( const Descriptor& message_descriptor) const { const bool is_extension = true; - PrintFieldDescriptorsInDescriptor( - message_descriptor, is_extension, "extensions", - &Descriptor::extension_count, &Descriptor::extension); + PrintFieldDescriptorsInDescriptor(message_descriptor, is_extension, + "extensions", &Descriptor::extension_count, + &Descriptor::extension); } bool Generator::GeneratingDescriptorProto() const { - return file_->name() == "google/protobuf/descriptor.proto"; + return file_->name() == "net/proto2/proto/descriptor.proto" || + file_->name() == "google/protobuf/descriptor.proto"; } // Returns the unique Python module-level identifier given to a descriptor. // This name is module-qualified iff the given descriptor describes an // entity that doesn't come from the current file. template -string Generator::ModuleLevelDescriptorName( +std::string Generator::ModuleLevelDescriptorName( const DescriptorT& descriptor) const { // FIXME(robinson): // We currently don't worry about collisions with underscores in the type @@ -1215,8 +1251,8 @@ string Generator::ModuleLevelDescriptorName( // // The C++ implementation doesn't guard against this either. Leaving // it for now... - string name = NamePrefixedWithNestedTypes(descriptor, "_"); - UpperString(&name); + std::string name = NamePrefixedWithNestedTypes(descriptor, "_"); + ToUpper(&name); // Module-private for now. Easy to make public later; almost impossible // to make private later. name = "_" + name; @@ -1232,8 +1268,9 @@ string Generator::ModuleLevelDescriptorName( // Like ModuleLevelDescriptorName(), module-qualifies the name iff // the given descriptor describes an entity that doesn't come from // the current file. -string Generator::ModuleLevelMessageName(const Descriptor& descriptor) const { - string name = NamePrefixedWithNestedTypes(descriptor, "."); +std::string Generator::ModuleLevelMessageName( + const Descriptor& descriptor) const { + std::string name = NamePrefixedWithNestedTypes(descriptor, "."); if (descriptor.file() != file_) { name = ModuleAlias(descriptor.file()->name()) + "." + name; } @@ -1242,10 +1279,10 @@ string Generator::ModuleLevelMessageName(const Descriptor& descriptor) const { // Returns the unique Python module-level identifier given to a service // descriptor. -string Generator::ModuleLevelServiceDescriptorName( +std::string Generator::ModuleLevelServiceDescriptorName( const ServiceDescriptor& descriptor) const { - string name = descriptor.name(); - UpperString(&name); + std::string name = descriptor.name(); + ToUpper(&name); name = "_" + name; if (descriptor.file() != file_) { name = ModuleAlias(descriptor.file()->name()) + "." + name; @@ -1262,41 +1299,35 @@ string Generator::ModuleLevelServiceDescriptorName( // serialized_end=43, // template -void Generator::PrintSerializedPbInterval( - const DescriptorT& descriptor, DescriptorProtoT& proto) const { +void Generator::PrintSerializedPbInterval(const DescriptorT& descriptor, + DescriptorProtoT& proto) const { descriptor.CopyTo(&proto); - string sp; + std::string sp; proto.SerializeToString(&sp); int offset = file_descriptor_serialized_.find(sp); GOOGLE_CHECK_GE(offset, 0); - printer_->Print("serialized_start=$serialized_start$,\n" - "serialized_end=$serialized_end$,\n", - "serialized_start", SimpleItoa(offset), - "serialized_end", SimpleItoa(offset + sp.size())); + printer_->Print( + "serialized_start=$serialized_start$,\n" + "serialized_end=$serialized_end$,\n", + "serialized_start", StrCat(offset), "serialized_end", + StrCat(offset + sp.size())); } namespace { -void PrintDescriptorOptionsFixingCode(const string& descriptor, - const string& options, +void PrintDescriptorOptionsFixingCode(const std::string& descriptor, + const std::string& options, io::Printer* printer) { - // TODO(xiaofeng): I have added a method _SetOptions() to DescriptorBase - // in proto2 python runtime but it couldn't be used here because appengine - // uses a snapshot version of the library in which the new method is not - // yet present. After appengine has synced their runtime library, the code - // below should be cleaned up to use _SetOptions(). - printer->Print( - "$descriptor$.has_options = True\n" - "$descriptor$._options = $options$\n", - "descriptor", descriptor, "options", options); + // Reset the _options to None thus DescriptorBase.GetOptions() can + // parse _options again after extensions are registered. + printer->Print("$descriptor$._options = None\n", "descriptor", descriptor); } } // namespace // Prints expressions that set the options field of all descriptors. void Generator::FixAllDescriptorOptions() const { // Prints an expression that sets the file descriptor's options. - string file_options = OptionsValue( - "FileOptions", file_->options().SerializeAsString()); + std::string file_options = OptionsValue(file_->options().SerializeAsString()); if (file_options != "None") { PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_); } @@ -1318,12 +1349,10 @@ void Generator::FixAllDescriptorOptions() const { } void Generator::FixOptionsForOneof(const OneofDescriptor& oneof) const { - string oneof_options = OptionsValue( - "OneofOptions", oneof.options().SerializeAsString()); + std::string oneof_options = OptionsValue(oneof.options().SerializeAsString()); if (oneof_options != "None") { - string oneof_name = strings::Substitute( - "$0.$1['$2']", - ModuleLevelDescriptorName(*oneof.containing_type()), + std::string oneof_name = strings::Substitute( + "$0.$1['$2']", ModuleLevelDescriptorName(*oneof.containing_type()), "oneofs_by_name", oneof.name()); PrintDescriptorOptionsFixingCode(oneof_name, oneof_options, printer_); } @@ -1332,16 +1361,16 @@ void Generator::FixOptionsForOneof(const OneofDescriptor& oneof) const { // Prints expressions that set the options for an enum descriptor and its // value descriptors. void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const { - string descriptor_name = ModuleLevelDescriptorName(enum_descriptor); - string enum_options = OptionsValue( - "EnumOptions", enum_descriptor.options().SerializeAsString()); + std::string descriptor_name = ModuleLevelDescriptorName(enum_descriptor); + std::string enum_options = + OptionsValue(enum_descriptor.options().SerializeAsString()); if (enum_options != "None") { PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_); } for (int i = 0; i < enum_descriptor.value_count(); ++i) { const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i); - string value_options = OptionsValue( - "EnumValueOptions", value_descriptor.options().SerializeAsString()); + std::string value_options = + OptionsValue(value_descriptor.options().SerializeAsString()); if (value_options != "None") { PrintDescriptorOptionsFixingCode( StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(), @@ -1353,23 +1382,21 @@ void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const { // Prints expressions that set the options for field descriptors (including // extensions). -void Generator::FixOptionsForField( - const FieldDescriptor& field) const { - string field_options = OptionsValue( - "FieldOptions", field.options().SerializeAsString()); +void Generator::FixOptionsForField(const FieldDescriptor& field) const { + std::string field_options = OptionsValue(field.options().SerializeAsString()); if (field_options != "None") { - string field_name; + std::string field_name; if (field.is_extension()) { - if (field.extension_scope() == NULL) { + if (field.extension_scope() == nullptr) { // Top level extensions. field_name = field.name(); } else { - field_name = FieldReferencingExpression( - field.extension_scope(), field, "extensions_by_name"); + field_name = FieldReferencingExpression(field.extension_scope(), field, + "extensions_by_name"); } } else { - field_name = FieldReferencingExpression( - field.containing_type(), field, "fields_by_name"); + field_name = FieldReferencingExpression(field.containing_type(), field, + "fields_by_name"); } PrintDescriptorOptionsFixingCode(field_name, field_options, printer_); } @@ -1401,12 +1428,11 @@ void Generator::FixOptionsForMessage(const Descriptor& descriptor) const { FixOptionsForField(field); } // Message option for this message. - string message_options = OptionsValue( - "MessageOptions", descriptor.options().SerializeAsString()); + std::string message_options = + OptionsValue(descriptor.options().SerializeAsString()); if (message_options != "None") { - string descriptor_name = ModuleLevelDescriptorName(descriptor); - PrintDescriptorOptionsFixingCode(descriptor_name, - message_options, + std::string descriptor_name = ModuleLevelDescriptorName(descriptor); + PrintDescriptorOptionsFixingCode(descriptor_name, message_options, printer_); } } @@ -1414,20 +1440,19 @@ void Generator::FixOptionsForMessage(const Descriptor& descriptor) const { // If a dependency forwards other files through public dependencies, let's // copy over the corresponding module aliases. void Generator::CopyPublicDependenciesAliases( - const string& copy_from, const FileDescriptor* file) const { + const std::string& copy_from, const FileDescriptor* file) const { for (int i = 0; i < file->public_dependency_count(); ++i) { - string module_name = ModuleName(file->public_dependency(i)->name()); - string module_alias = ModuleAlias(file->public_dependency(i)->name()); + std::string module_name = ModuleName(file->public_dependency(i)->name()); + std::string module_alias = ModuleAlias(file->public_dependency(i)->name()); // There's no module alias in the dependent file if it was generated by // an old protoc (less than 3.0.0-alpha-1). Use module name in this // situation. - printer_->Print("try:\n" - " $alias$ = $copy_from$.$alias$\n" - "except AttributeError:\n" - " $alias$ = $copy_from$.$module$\n", - "alias", module_alias, - "module", module_name, - "copy_from", copy_from); + printer_->Print( + "try:\n" + " $alias$ = $copy_from$.$alias$\n" + "except AttributeError:\n" + " $alias$ = $copy_from$.$module$\n", + "alias", module_alias, "module", module_name, "copy_from", copy_from); CopyPublicDependenciesAliases(copy_from, file->public_dependency(i)); } } diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h index 2b5a028b3fef5..ed1c99504ca65 100644 --- a/src/google/protobuf/compiler/python/python_generator.h +++ b/src/google/protobuf/compiler/python/python_generator.h @@ -39,7 +39,8 @@ #include #include -#include + +#include namespace google { namespace protobuf { @@ -51,7 +52,9 @@ class FieldDescriptor; class OneofDescriptor; class ServiceDescriptor; -namespace io { class Printer; } +namespace io { +class Printer; +} namespace compiler { namespace python { @@ -60,16 +63,17 @@ namespace python { // If you create your own protocol compiler binary and you want it to support // Python output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT Generator : public CodeGenerator { +class PROTOC_EXPORT Generator : public CodeGenerator { public: Generator(); virtual ~Generator(); // CodeGenerator methods. - virtual bool Generate(const FileDescriptor* file, - const string& parameter, - GeneratorContext* generator_context, - string* error) const; + bool Generate(const FileDescriptor* file, const std::string& parameter, + GeneratorContext* generator_context, + std::string* error) const override; + + uint64_t GetSupportedFeatures() const override; private: void PrintImports() const; @@ -81,14 +85,12 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void PrintTopLevelExtensions() const; - void PrintFieldDescriptor( - const FieldDescriptor& field, bool is_extension) const; + void PrintFieldDescriptor(const FieldDescriptor& field, + bool is_extension) const; void PrintFieldDescriptorsInDescriptor( - const Descriptor& message_descriptor, - bool is_extension, - const string& list_variable_name, - int (Descriptor::*CountFn)() const, - const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const; + const Descriptor& message_descriptor, bool is_extension, + const std::string& list_variable_name, int (Descriptor::*CountFn)() const, + const FieldDescriptor* (Descriptor::*GetterFn)(int)const) const; void PrintFieldsInDescriptor(const Descriptor& message_descriptor) const; void PrintExtensionsInDescriptor(const Descriptor& message_descriptor) const; void PrintMessageDescriptors() const; @@ -96,11 +98,13 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void PrintNestedDescriptors(const Descriptor& containing_descriptor) const; void PrintMessages() const; - void PrintMessage(const Descriptor& message_descriptor, const string& prefix, - std::vector* to_register) const; + void PrintMessage(const Descriptor& message_descriptor, + const std::string& prefix, + std::vector* to_register, + bool is_nested) const; void PrintNestedMessages(const Descriptor& containing_descriptor, - const string& prefix, - std::vector* to_register) const; + const std::string& prefix, + std::vector* to_register) const; void FixForeignFieldsInDescriptors() const; void FixForeignFieldsInDescriptor( @@ -108,14 +112,14 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { const Descriptor* containing_descriptor) const; void FixForeignFieldsInField(const Descriptor* containing_type, const FieldDescriptor& field, - const string& python_dict_name) const; + const std::string& python_dict_name) const; void AddMessageToFileDescriptor(const Descriptor& descriptor) const; void AddEnumToFileDescriptor(const EnumDescriptor& descriptor) const; void AddExtensionToFileDescriptor(const FieldDescriptor& descriptor) const; void AddServiceToFileDescriptor(const ServiceDescriptor& descriptor) const; - string FieldReferencingExpression(const Descriptor* containing_type, - const FieldDescriptor& field, - const string& python_dict_name) const; + std::string FieldReferencingExpression( + const Descriptor* containing_type, const FieldDescriptor& field, + const std::string& python_dict_name) const; template void FixContainingTypeInDescriptor( const DescriptorT& descriptor, @@ -135,19 +139,18 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { const ServiceDescriptor& descriptor) const; void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const; - string OptionsValue(const string& class_name, - const string& serialized_options) const; + std::string OptionsValue(const std::string& serialized_options) const; bool GeneratingDescriptorProto() const; template - string ModuleLevelDescriptorName(const DescriptorT& descriptor) const; - string ModuleLevelMessageName(const Descriptor& descriptor) const; - string ModuleLevelServiceDescriptorName( + std::string ModuleLevelDescriptorName(const DescriptorT& descriptor) const; + std::string ModuleLevelMessageName(const Descriptor& descriptor) const; + std::string ModuleLevelServiceDescriptorName( const ServiceDescriptor& descriptor) const; template - void PrintSerializedPbInterval( - const DescriptorT& descriptor, DescriptorProtoT& proto) const; + void PrintSerializedPbInterval(const DescriptorT& descriptor, + DescriptorProtoT& proto) const; void FixAllDescriptorOptions() const; void FixOptionsForField(const FieldDescriptor& field) const; @@ -155,15 +158,16 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void FixOptionsForEnum(const EnumDescriptor& descriptor) const; void FixOptionsForMessage(const Descriptor& descriptor) const; - void CopyPublicDependenciesAliases( - const string& copy_from, const FileDescriptor* file) const; + void CopyPublicDependenciesAliases(const std::string& copy_from, + const FileDescriptor* file) const; // Very coarse-grained lock to ensure that Generate() is reentrant. // Guards file_, printer_ and file_descriptor_serialized_. mutable Mutex mutex_; mutable const FileDescriptor* file_; // Set in Generate(). Under mutex_. - mutable string file_descriptor_serialized_; + mutable std::string file_descriptor_serialized_; mutable io::Printer* printer_; // Set in Generate(). Under mutex_. + mutable bool pure_python_workable_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator); }; @@ -171,6 +175,8 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { } // namespace python } // namespace compiler } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc index 34f857fddb093..76ceef32a0af5 100644 --- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc +++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc @@ -35,17 +35,13 @@ // worth. #include -#ifndef _SHARED_PTR_H -#include -#endif - -#include -#include -#include -#include #include #include +#include +#include +#include +#include #include #include #include @@ -62,9 +58,8 @@ class TestGenerator : public CodeGenerator { ~TestGenerator() {} virtual bool Generate(const FileDescriptor* file, - const string& parameter, - GeneratorContext* context, - string* error) const { + const std::string& parameter, GeneratorContext* context, + std::string* error) const { TryInsert("test_pb2.py", "imports", context); TryInsert("test_pb2.py", "module_scope", context); TryInsert("test_pb2.py", "class_scope:foo.Bar", context); @@ -72,9 +67,10 @@ class TestGenerator : public CodeGenerator { return true; } - void TryInsert(const string& filename, const string& insertion_point, + void TryInsert(const std::string& filename, + const std::string& insertion_point, GeneratorContext* context) const { - google::protobuf::scoped_ptr output( + std::unique_ptr output( context->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); @@ -93,7 +89,7 @@ TEST(PythonPluginTest, PluginTest) { "}\n", true)); - google::protobuf::compiler::CommandLineInterface cli; + compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); python::Generator python_generator; @@ -101,17 +97,12 @@ TEST(PythonPluginTest, PluginTest) { cli.RegisterGenerator("--python_out", &python_generator, ""); cli.RegisterGenerator("--test_out", &test_generator, ""); - string proto_path = "-I" + TestTempDir(); - string python_out = "--python_out=" + TestTempDir(); - string test_out = "--test_out=" + TestTempDir(); + std::string proto_path = "-I" + TestTempDir(); + std::string python_out = "--python_out=" + TestTempDir(); + std::string test_out = "--test_out=" + TestTempDir(); - const char* argv[] = { - "protoc", - proto_path.c_str(), - python_out.c_str(), - test_out.c_str(), - "test.proto" - }; + const char* argv[] = {"protoc", proto_path.c_str(), python_out.c_str(), + test_out.c_str(), "test.proto"}; EXPECT_EQ(0, cli.Run(5, argv)); } @@ -136,29 +127,29 @@ TEST(PythonPluginTest, ImportTest) { "message Message2 {}\n", true)); - google::protobuf::compiler::CommandLineInterface cli; + compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); python::Generator python_generator; cli.RegisterGenerator("--python_out", &python_generator, ""); - string proto_path = "-I" + TestTempDir(); - string python_out = "--python_out=" + TestTempDir(); + std::string proto_path = "-I" + TestTempDir(); + std::string python_out = "--python_out=" + TestTempDir(); const char* argv[] = {"protoc", proto_path.c_str(), "-I.", python_out.c_str(), "test1.proto"}; ASSERT_EQ(0, cli.Run(5, argv)); // Loop over the lines of the generated code and verify that we find an // ordinary Python import but do not find the string "importlib". - string output; + std::string output; GOOGLE_CHECK_OK(File::GetContents(TestTempDir() + "/test1_pb2.py", &output, true)); - std::vector lines = Split(output, "\n"); - string expected_import = "import test2_pb2"; + std::vector lines = Split(output, "\n"); + std::string expected_import = "import test2_pb2"; bool found_expected_import = false; for (int i = 0; i < lines.size(); ++i) { - if (lines[i].find(expected_import) != string::npos) { + if (lines[i].find(expected_import) != std::string::npos) { found_expected_import = true; } - EXPECT_EQ(string::npos, lines[i].find("importlib")); + EXPECT_EQ(std::string::npos, lines[i].find("importlib")); } EXPECT_TRUE(found_expected_import); } diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb b/src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb index 49b23fbe8d254..7e66d1ecc8fd5 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb +++ b/src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb @@ -4,71 +4,73 @@ require 'google/protobuf' Google::Protobuf::DescriptorPool.generated_pool.build do - add_message "A.B.C.TestMessage" do - optional :optional_int32, :int32, 1 - optional :optional_int64, :int64, 2 - optional :optional_uint32, :uint32, 3 - optional :optional_uint64, :uint64, 4 - optional :optional_bool, :bool, 5 - optional :optional_double, :double, 6 - optional :optional_float, :float, 7 - optional :optional_string, :string, 8 - optional :optional_bytes, :bytes, 9 - optional :optional_enum, :enum, 10, "A.B.C.TestEnum" - optional :optional_msg, :message, 11, "A.B.C.TestMessage" - repeated :repeated_int32, :int32, 21 - repeated :repeated_int64, :int64, 22 - repeated :repeated_uint32, :uint32, 23 - repeated :repeated_uint64, :uint64, 24 - repeated :repeated_bool, :bool, 25 - repeated :repeated_double, :double, 26 - repeated :repeated_float, :float, 27 - repeated :repeated_string, :string, 28 - repeated :repeated_bytes, :bytes, 29 - repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum" - repeated :repeated_msg, :message, 31, "A.B.C.TestMessage" - map :map_int32_string, :int32, :string, 61 - map :map_int64_string, :int64, :string, 62 - map :map_uint32_string, :uint32, :string, 63 - map :map_uint64_string, :uint64, :string, 64 - map :map_bool_string, :bool, :string, 65 - map :map_string_string, :string, :string, 66 - map :map_string_msg, :string, :message, 67, "A.B.C.TestMessage" - map :map_string_enum, :string, :enum, 68, "A.B.C.TestEnum" - map :map_string_int32, :string, :int32, 69 - map :map_string_bool, :string, :bool, 70 - optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage" - oneof :my_oneof do - optional :oneof_int32, :int32, 41 - optional :oneof_int64, :int64, 42 - optional :oneof_uint32, :uint32, 43 - optional :oneof_uint64, :uint64, 44 - optional :oneof_bool, :bool, 45 - optional :oneof_double, :double, 46 - optional :oneof_float, :float, 47 - optional :oneof_string, :string, 48 - optional :oneof_bytes, :bytes, 49 - optional :oneof_enum, :enum, 50, "A.B.C.TestEnum" - optional :oneof_msg, :message, 51, "A.B.C.TestMessage" + add_file("ruby_generated_code.proto", :syntax => :proto3) do + add_message "A.B.C.TestMessage" do + optional :optional_int32, :int32, 1 + optional :optional_int64, :int64, 2 + optional :optional_uint32, :uint32, 3 + optional :optional_uint64, :uint64, 4 + optional :optional_bool, :bool, 5 + optional :optional_double, :double, 6 + optional :optional_float, :float, 7 + optional :optional_string, :string, 8 + optional :optional_bytes, :bytes, 9 + optional :optional_enum, :enum, 10, "A.B.C.TestEnum" + optional :optional_msg, :message, 11, "A.B.C.TestMessage" + repeated :repeated_int32, :int32, 21 + repeated :repeated_int64, :int64, 22 + repeated :repeated_uint32, :uint32, 23 + repeated :repeated_uint64, :uint64, 24 + repeated :repeated_bool, :bool, 25 + repeated :repeated_double, :double, 26 + repeated :repeated_float, :float, 27 + repeated :repeated_string, :string, 28 + repeated :repeated_bytes, :bytes, 29 + repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum" + repeated :repeated_msg, :message, 31, "A.B.C.TestMessage" + map :map_int32_string, :int32, :string, 61 + map :map_int64_string, :int64, :string, 62 + map :map_uint32_string, :uint32, :string, 63 + map :map_uint64_string, :uint64, :string, 64 + map :map_bool_string, :bool, :string, 65 + map :map_string_string, :string, :string, 66 + map :map_string_msg, :string, :message, 67, "A.B.C.TestMessage" + map :map_string_enum, :string, :enum, 68, "A.B.C.TestEnum" + map :map_string_int32, :string, :int32, 69 + map :map_string_bool, :string, :bool, 70 + optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage" + oneof :my_oneof do + optional :oneof_int32, :int32, 41 + optional :oneof_int64, :int64, 42 + optional :oneof_uint32, :uint32, 43 + optional :oneof_uint64, :uint64, 44 + optional :oneof_bool, :bool, 45 + optional :oneof_double, :double, 46 + optional :oneof_float, :float, 47 + optional :oneof_string, :string, 48 + optional :oneof_bytes, :bytes, 49 + optional :oneof_enum, :enum, 50, "A.B.C.TestEnum" + optional :oneof_msg, :message, 51, "A.B.C.TestMessage" + end + end + add_message "A.B.C.TestMessage.NestedMessage" do + optional :foo, :int32, 1 + end + add_enum "A.B.C.TestEnum" do + value :Default, 0 + value :A, 1 + value :B, 2 + value :C, 3 end - end - add_message "A.B.C.TestMessage.NestedMessage" do - optional :foo, :int32, 1 - end - add_enum "A.B.C.TestEnum" do - value :Default, 0 - value :A, 1 - value :B, 2 - value :C, 3 end end module A module B module C - TestMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass - TestMessage::NestedMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass - TestEnum = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule + TestMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass + TestMessage::NestedMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass + TestEnum = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule end end end diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code_proto2.proto b/src/google/protobuf/compiler/ruby/ruby_generated_code_proto2.proto new file mode 100644 index 0000000000000..8d3cc13e03d25 --- /dev/null +++ b/src/google/protobuf/compiler/ruby/ruby_generated_code_proto2.proto @@ -0,0 +1,68 @@ +syntax = "proto2"; + +package A.B.C; + +message TestMessage { + optional int32 optional_int32 = 1 [default = 1]; + optional int64 optional_int64 = 2 [default = 2]; + optional uint32 optional_uint32 = 3 [default = 3]; + optional uint64 optional_uint64 = 4 [default = 4]; + optional bool optional_bool = 5 [default = true]; + optional double optional_double = 6 [default = 6.0]; + optional float optional_float = 7 [default = 7.0]; + optional string optional_string = 8 [default = "default str"]; + optional bytes optional_bytes = 9 [default = "\0\1\2\100fubar"]; + optional TestEnum optional_enum = 10 [default = A]; + optional 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; + + required int32 required_int32 = 41; + required int64 required_int64 = 42; + required uint32 required_uint32 = 43; + required uint64 required_uint64 = 44; + required bool required_bool = 45; + required double required_double = 46; + required float required_float = 47; + required string required_string = 48; + required bytes required_bytes = 49; + required TestEnum required_enum = 50; + required TestMessage required_msg = 51; + + 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 { + optional int32 foo = 1; + } + + optional NestedMessage nested_message = 80; +} + +enum TestEnum { + Default = 0; + A = 1; + B = 2; + C = 3; +} diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code_proto2_pb.rb b/src/google/protobuf/compiler/ruby/ruby_generated_code_proto2_pb.rb new file mode 100644 index 0000000000000..c89738fe83da2 --- /dev/null +++ b/src/google/protobuf/compiler/ruby/ruby_generated_code_proto2_pb.rb @@ -0,0 +1,77 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: ruby_generated_code_proto2.proto + +require 'google/protobuf' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_file("ruby_generated_code_proto2.proto", :syntax => :proto2) do + add_message "A.B.C.TestMessage" do + optional :optional_int32, :int32, 1, default: 1 + optional :optional_int64, :int64, 2, default: 2 + optional :optional_uint32, :uint32, 3, default: 3 + optional :optional_uint64, :uint64, 4, default: 4 + optional :optional_bool, :bool, 5, default: true + optional :optional_double, :double, 6, default: 6 + optional :optional_float, :float, 7, default: 7 + optional :optional_string, :string, 8, default: "default str" + optional :optional_bytes, :bytes, 9, default: "\x00\x01\x02\x40\x66\x75\x62\x61\x72".force_encoding("ASCII-8BIT") + optional :optional_enum, :enum, 10, "A.B.C.TestEnum", default: 1 + optional :optional_msg, :message, 11, "A.B.C.TestMessage" + repeated :repeated_int32, :int32, 21 + repeated :repeated_int64, :int64, 22 + repeated :repeated_uint32, :uint32, 23 + repeated :repeated_uint64, :uint64, 24 + repeated :repeated_bool, :bool, 25 + repeated :repeated_double, :double, 26 + repeated :repeated_float, :float, 27 + repeated :repeated_string, :string, 28 + repeated :repeated_bytes, :bytes, 29 + repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum" + repeated :repeated_msg, :message, 31, "A.B.C.TestMessage" + required :required_int32, :int32, 41 + required :required_int64, :int64, 42 + required :required_uint32, :uint32, 43 + required :required_uint64, :uint64, 44 + required :required_bool, :bool, 45 + required :required_double, :double, 46 + required :required_float, :float, 47 + required :required_string, :string, 48 + required :required_bytes, :bytes, 49 + required :required_enum, :enum, 50, "A.B.C.TestEnum" + required :required_msg, :message, 51, "A.B.C.TestMessage" + optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage" + oneof :my_oneof do + optional :oneof_int32, :int32, 61 + optional :oneof_int64, :int64, 62 + optional :oneof_uint32, :uint32, 63 + optional :oneof_uint64, :uint64, 64 + optional :oneof_bool, :bool, 65 + optional :oneof_double, :double, 66 + optional :oneof_float, :float, 67 + optional :oneof_string, :string, 68 + optional :oneof_bytes, :bytes, 69 + optional :oneof_enum, :enum, 70, "A.B.C.TestEnum" + optional :oneof_msg, :message, 71, "A.B.C.TestMessage" + end + end + add_message "A.B.C.TestMessage.NestedMessage" do + optional :foo, :int32, 1 + end + add_enum "A.B.C.TestEnum" do + value :Default, 0 + value :A, 1 + value :B, 2 + value :C, 3 + end + end +end + +module A + module B + module C + TestMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass + TestMessage::NestedMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass + TestEnum = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule + end + end +end diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto new file mode 100644 index 0000000000000..8d7c948a180b6 --- /dev/null +++ b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +package one.two.a_three; + +option ruby_package = "A::B::C"; + +message Four { + string a_string = 1; +} diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto new file mode 100644 index 0000000000000..7a0d260865448 --- /dev/null +++ b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +package one.two.a_three.and; + +option ruby_package = "AA.BB.CC"; + +message Four { + string another_string = 1; +} diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy_pb.rb b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy_pb.rb new file mode 100644 index 0000000000000..cdbbe891bc2a2 --- /dev/null +++ b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy_pb.rb @@ -0,0 +1,20 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: ruby_generated_pkg_explicit_legacy.proto + +require 'google/protobuf' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_file("ruby_generated_pkg_explicit_legacy.proto", :syntax => :proto3) do + add_message "one.two.a_three.and.Four" do + optional :another_string, :string, 1 + end + end +end + +module AA + module BB + module CC + Four = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("one.two.a_three.and.Four").msgclass + end + end +end diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_pb.rb b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_pb.rb new file mode 100644 index 0000000000000..e6d47011e882a --- /dev/null +++ b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_pb.rb @@ -0,0 +1,20 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: ruby_generated_pkg_explicit.proto + +require 'google/protobuf' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_file("ruby_generated_pkg_explicit.proto", :syntax => :proto3) do + add_message "one.two.a_three.Four" do + optional :a_string, :string, 1 + end + end +end + +module A + module B + module C + Four = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("one.two.a_three.Four").msgclass + end + end +end diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto new file mode 100644 index 0000000000000..544db64d94e90 --- /dev/null +++ b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +package one.two.a_three; + +message Four { + string a_string = 1; +} diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_pkg_implicit_pb.rb b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_implicit_pb.rb new file mode 100644 index 0000000000000..1ac0ef7ad0458 --- /dev/null +++ b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_implicit_pb.rb @@ -0,0 +1,20 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: ruby_generated_pkg_implicit.proto + +require 'google/protobuf' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_file("ruby_generated_pkg_implicit.proto", :syntax => :proto3) do + add_message "one.two.a_three.Four" do + optional :a_string, :string, 1 + end + end +end + +module One + module Two + module AThree + Four = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("one.two.a_three.Four").msgclass + end + end +end diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index fbe3b4cb71884..a6935c76584df 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -28,6 +28,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include #include #include @@ -39,32 +40,28 @@ #include -using google::protobuf::internal::scoped_ptr; - namespace google { namespace protobuf { namespace compiler { namespace ruby { // Forward decls. -std::string IntToString(int32 value); +template +std::string NumberToString(numeric_type value); std::string GetRequireName(const std::string& proto_file); -std::string LabelForField(google::protobuf::FieldDescriptor* field); -std::string TypeName(google::protobuf::FieldDescriptor* field); -void GenerateMessage(const google::protobuf::Descriptor* message, - google::protobuf::io::Printer* printer); -void GenerateEnum(const google::protobuf::EnumDescriptor* en, - google::protobuf::io::Printer* printer); -void GenerateMessageAssignment( - const std::string& prefix, - const google::protobuf::Descriptor* message, - google::protobuf::io::Printer* printer); -void GenerateEnumAssignment( - const std::string& prefix, - const google::protobuf::EnumDescriptor* en, - google::protobuf::io::Printer* printer); - -std::string IntToString(int32 value) { +std::string LabelForField(FieldDescriptor* field); +std::string TypeName(FieldDescriptor* field); +bool GenerateMessage(const Descriptor* message, io::Printer* printer, + std::string* error); +void GenerateEnum(const EnumDescriptor* en, io::Printer* printer); +void GenerateMessageAssignment(const std::string& prefix, + const Descriptor* message, io::Printer* printer); +void GenerateEnumAssignment(const std::string& prefix, const EnumDescriptor* en, + io::Printer* printer); +std::string DefaultValueForField(const FieldDescriptor* field); + +template +std::string NumberToString(numeric_type value) { std::ostringstream os; os << value; return os.str(); @@ -79,7 +76,11 @@ std::string GetOutputFilename(const std::string& proto_file) { return GetRequireName(proto_file) + ".rb"; } -std::string LabelForField(const google::protobuf::FieldDescriptor* field) { +std::string LabelForField(const FieldDescriptor* field) { + if (field->has_optional_keyword() && + field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { + return "proto3_optional"; + } switch (field->label()) { case FieldDescriptor::LABEL_OPTIONAL: return "optional"; case FieldDescriptor::LABEL_REQUIRED: return "required"; @@ -88,7 +89,7 @@ std::string LabelForField(const google::protobuf::FieldDescriptor* field) { } } -std::string TypeName(const google::protobuf::FieldDescriptor* field) { +std::string TypeName(const FieldDescriptor* field) { switch (field->type()) { case FieldDescriptor::TYPE_INT32: return "int32"; case FieldDescriptor::TYPE_INT64: return "int64"; @@ -112,9 +113,63 @@ std::string TypeName(const google::protobuf::FieldDescriptor* field) { } } -void GenerateField(const google::protobuf::FieldDescriptor* field, - google::protobuf::io::Printer* printer) { +std::string StringifySyntax(FileDescriptor::Syntax syntax) { + switch (syntax) { + case FileDescriptor::SYNTAX_PROTO2: + return "proto2"; + case FileDescriptor::SYNTAX_PROTO3: + return "proto3"; + case FileDescriptor::SYNTAX_UNKNOWN: + default: + GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports " + "proto2 and proto3 syntax."; + return ""; + } +} + +std::string DefaultValueForField(const FieldDescriptor* field) { + switch(field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return NumberToString(field->default_value_int32()); + case FieldDescriptor::CPPTYPE_INT64: + return NumberToString(field->default_value_int64()); + case FieldDescriptor::CPPTYPE_UINT32: + return NumberToString(field->default_value_uint32()); + case FieldDescriptor::CPPTYPE_UINT64: + return NumberToString(field->default_value_uint64()); + case FieldDescriptor::CPPTYPE_FLOAT: + return NumberToString(field->default_value_float()); + case FieldDescriptor::CPPTYPE_DOUBLE: + return NumberToString(field->default_value_double()); + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() ? "true" : "false"; + case FieldDescriptor::CPPTYPE_ENUM: + return NumberToString(field->default_value_enum()->number()); + case FieldDescriptor::CPPTYPE_STRING: { + std::ostringstream os; + std::string default_str = field->default_value_string(); + + if (field->type() == FieldDescriptor::TYPE_STRING) { + os << "\"" << default_str << "\""; + } else if (field->type() == FieldDescriptor::TYPE_BYTES) { + os << "\""; + + os.fill('0'); + for (int i = 0; i < default_str.length(); ++i) { + // Write the hex form of each byte. + os << "\\x" << std::hex << std::setw(2) + << ((uint16)((unsigned char)default_str.at(i))); + } + os << "\".force_encoding(\"ASCII-8BIT\")"; + } + + return os.str(); + } + default: assert(false); return ""; + } +} +void GenerateField(const FieldDescriptor* field, io::Printer* printer) { if (field->is_map()) { const FieldDescriptor* key_field = field->message_type()->FindFieldByNumber(1); @@ -126,7 +181,7 @@ void GenerateField(const google::protobuf::FieldDescriptor* field, "name", field->name(), "key_type", TypeName(key_field), "value_type", TypeName(value_field), - "number", IntToString(field->number())); + "number", NumberToString(field->number())); if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { printer->Print( @@ -148,24 +203,28 @@ void GenerateField(const google::protobuf::FieldDescriptor* field, printer->Print( ":$type$, $number$", "type", TypeName(field), - "number", IntToString(field->number())); + "number", NumberToString(field->number())); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { printer->Print( - ", \"$subtype$\"\n", + ", \"$subtype$\"", "subtype", field->message_type()->full_name()); } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { printer->Print( - ", \"$subtype$\"\n", + ", \"$subtype$\"", "subtype", field->enum_type()->full_name()); - } else { - printer->Print("\n"); } + + if (field->has_default_value()) { + printer->Print(", default: $default$", "default", + DefaultValueForField(field)); + } + + printer->Print("\n"); } } -void GenerateOneof(const google::protobuf::OneofDescriptor* oneof, - google::protobuf::io::Printer* printer) { +void GenerateOneof(const OneofDescriptor* oneof, io::Printer* printer) { printer->Print( "oneof :$name$ do\n", "name", oneof->name()); @@ -180,13 +239,16 @@ void GenerateOneof(const google::protobuf::OneofDescriptor* oneof, printer->Print("end\n"); } -void GenerateMessage(const google::protobuf::Descriptor* message, - google::protobuf::io::Printer* printer) { +bool GenerateMessage(const Descriptor* message, io::Printer* printer, + std::string* error) { + if (message->extension_range_count() > 0 || message->extension_count() > 0) { + GOOGLE_LOG(WARNING) << "Extensions are not yet supported for proto2 .proto files."; + } // Don't generate MapEntry messages -- we use the Ruby extension's native // support for map fields instead. if (message->options().map_entry()) { - return; + return true; } printer->Print( @@ -196,12 +258,12 @@ void GenerateMessage(const google::protobuf::Descriptor* message, for (int i = 0; i < message->field_count(); i++) { const FieldDescriptor* field = message->field(i); - if (!field->containing_oneof()) { + if (!field->real_containing_oneof()) { GenerateField(field, printer); } } - for (int i = 0; i < message->oneof_decl_count(); i++) { + for (int i = 0; i < message->real_oneof_decl_count(); i++) { const OneofDescriptor* oneof = message->oneof_decl(i); GenerateOneof(oneof, printer); } @@ -210,15 +272,18 @@ void GenerateMessage(const google::protobuf::Descriptor* message, printer->Print("end\n"); for (int i = 0; i < message->nested_type_count(); i++) { - GenerateMessage(message->nested_type(i), printer); + if (!GenerateMessage(message->nested_type(i), printer, error)) { + return false; + } } for (int i = 0; i < message->enum_type_count(); i++) { GenerateEnum(message->enum_type(i), printer); } + + return true; } -void GenerateEnum(const google::protobuf::EnumDescriptor* en, - google::protobuf::io::Printer* printer) { +void GenerateEnum(const EnumDescriptor* en, io::Printer* printer) { printer->Print( "add_enum \"$name$\" do\n", "name", en->full_name()); @@ -229,7 +294,7 @@ void GenerateEnum(const google::protobuf::EnumDescriptor* en, printer->Print( "value :$name$, $number$\n", "name", value->name(), - "number", IntToString(value->number())); + "number", NumberToString(value->number())); } printer->Outdent(); @@ -244,7 +309,7 @@ bool IsUpper(char ch) { return ch >= 'A' && ch <= 'Z'; } bool IsAlpha(char ch) { return IsLower(ch) || IsUpper(ch); } -char ToUpper(char ch) { return IsLower(ch) ? (ch - 'a' + 'A') : ch; } +char UpperChar(char ch) { return IsLower(ch) ? (ch - 'a' + 'A') : ch; } // Package names in protobuf are snake_case by convention, but Ruby module @@ -261,7 +326,7 @@ std::string PackageToModule(const std::string& name) { next_upper = true; } else { if (next_upper) { - result.push_back(ToUpper(name[i])); + result.push_back(UpperChar(name[i])); } else { result.push_back(name[i]); } @@ -281,7 +346,7 @@ std::string RubifyConstant(const std::string& name) { if (!ret.empty()) { if (IsLower(ret[0])) { // If it starts with a lowercase letter, capitalize it. - ret[0] = ToUpper(ret[0]); + ret[0] = UpperChar(ret[0]); } else if (!IsAlpha(ret[0])) { // Otherwise (e.g. if it begins with an underscore), we need to come up // with some prefix that starts with a capital letter. We could be smarter @@ -295,11 +360,9 @@ std::string RubifyConstant(const std::string& name) { return ret; } -void GenerateMessageAssignment( - const std::string& prefix, - const google::protobuf::Descriptor* message, - google::protobuf::io::Printer* printer) { - +void GenerateMessageAssignment(const std::string& prefix, + const Descriptor* message, + io::Printer* printer) { // Don't generate MapEntry messages -- we use the Ruby extension's native // support for map fields instead. if (message->options().map_entry()) { @@ -311,11 +374,11 @@ void GenerateMessageAssignment( "prefix", prefix, "name", RubifyConstant(message->name())); printer->Print( - "Google::Protobuf::DescriptorPool.generated_pool." + "::Google::Protobuf::DescriptorPool.generated_pool." "lookup(\"$full_name$\").msgclass\n", "full_name", message->full_name()); - std::string nested_prefix = prefix + message->name() + "::"; + std::string nested_prefix = prefix + RubifyConstant(message->name()) + "::"; for (int i = 0; i < message->nested_type_count(); i++) { GenerateMessageAssignment(nested_prefix, message->nested_type(i), printer); } @@ -324,35 +387,61 @@ void GenerateMessageAssignment( } } -void GenerateEnumAssignment( - const std::string& prefix, - const google::protobuf::EnumDescriptor* en, - google::protobuf::io::Printer* printer) { +void GenerateEnumAssignment(const std::string& prefix, const EnumDescriptor* en, + io::Printer* printer) { printer->Print( "$prefix$$name$ = ", "prefix", prefix, "name", RubifyConstant(en->name())); printer->Print( - "Google::Protobuf::DescriptorPool.generated_pool." + "::Google::Protobuf::DescriptorPool.generated_pool." "lookup(\"$full_name$\").enummodule\n", "full_name", en->full_name()); } -int GeneratePackageModules( - std::string package_name, - google::protobuf::io::Printer* printer) { +int GeneratePackageModules(const FileDescriptor* file, io::Printer* printer) { int levels = 0; + bool need_change_to_module = true; + std::string package_name; + + // Determine the name to use in either format: + // proto package: one.two.three + // option ruby_package: One::Two::Three + if (file->options().has_ruby_package()) { + package_name = file->options().ruby_package(); + + // If :: is in the package use the Ruby formatted name as-is + // -> A::B::C + // otherwise, use the dot separator + // -> A.B.C + if (package_name.find("::") != std::string::npos) { + need_change_to_module = false; + } else { + GOOGLE_LOG(WARNING) << "ruby_package option should be in the form of:" + << " 'A::B::C' and not 'A.B.C'"; + } + } else { + package_name = file->package(); + } + + // Use the appropriate delimiter + std::string delimiter = need_change_to_module ? "." : "::"; + int delimiter_size = need_change_to_module ? 1 : 2; + + // Extract each module name and indent while (!package_name.empty()) { - size_t dot_index = package_name.find("."); - string component; - if (dot_index == string::npos) { + size_t dot_index = package_name.find(delimiter); + std::string component; + if (dot_index == std::string::npos) { component = package_name; package_name = ""; } else { component = package_name.substr(0, dot_index); - package_name = package_name.substr(dot_index + 1); + package_name = package_name.substr(dot_index + delimiter_size); + } + if (need_change_to_module) { + component = PackageToModule(component); } - component = PackageToModule(component); printer->Print( "module $name$\n", "name", component); @@ -362,9 +451,7 @@ int GeneratePackageModules( return levels; } -void EndPackageModules( - int levels, - google::protobuf::io::Printer* printer) { +void EndPackageModules(int levels, io::Printer* printer) { while (levels > 0) { levels--; printer->Outdent(); @@ -374,7 +461,7 @@ void EndPackageModules( } bool UsesTypeFromFile(const Descriptor* message, const FileDescriptor* file, - string* error) { + std::string* error) { for (int i = 0; i < message->field_count(); i++) { const FieldDescriptor* field = message->field(i); if ((field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && @@ -411,8 +498,9 @@ bool UsesTypeFromFile(const Descriptor* message, const FileDescriptor* file, bool MaybeEmitDependency(const FileDescriptor* import, const FileDescriptor* from, io::Printer* printer, - string* error) { - if (import->syntax() == FileDescriptor::SYNTAX_PROTO2) { + std::string* error) { + if (from->syntax() == FileDescriptor::SYNTAX_PROTO3 && + import->syntax() == FileDescriptor::SYNTAX_PROTO2) { for (int i = 0; i < from->message_type_count(); i++) { if (UsesTypeFromFile(from->message_type(i), import, error)) { // Error text was already set by UsesTypeFromFile(). @@ -435,7 +523,7 @@ bool MaybeEmitDependency(const FileDescriptor* import, } bool GenerateFile(const FileDescriptor* file, io::Printer* printer, - string* error) { + std::string* error) { printer->Print( "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" "# source: $filename$\n" @@ -451,20 +539,33 @@ bool GenerateFile(const FileDescriptor* file, io::Printer* printer, } } - printer->Print( - "Google::Protobuf::DescriptorPool.generated_pool.build do\n"); + // TODO: Remove this when ruby supports extensions for proto2 syntax. + if (file->syntax() == FileDescriptor::SYNTAX_PROTO2 && + file->extension_count() > 0) { + GOOGLE_LOG(WARNING) << "Extensions are not yet supported for proto2 .proto files."; + } + + printer->Print("Google::Protobuf::DescriptorPool.generated_pool.build do\n"); + printer->Indent(); + printer->Print("add_file(\"$filename$\", :syntax => :$syntax$) do\n", + "filename", file->name(), "syntax", + StringifySyntax(file->syntax())); printer->Indent(); for (int i = 0; i < file->message_type_count(); i++) { - GenerateMessage(file->message_type(i), printer); + if (!GenerateMessage(file->message_type(i), printer, error)) { + return false; + } } for (int i = 0; i < file->enum_type_count(); i++) { GenerateEnum(file->enum_type(i), printer); } printer->Outdent(); + printer->Print("end\n"); + printer->Outdent(); printer->Print( "end\n\n"); - int levels = GeneratePackageModules(file->package(), printer); + int levels = GeneratePackageModules(file, printer); for (int i = 0; i < file->message_type_count(); i++) { GenerateMessageAssignment("", file->message_type(i), printer); } @@ -477,18 +578,17 @@ bool GenerateFile(const FileDescriptor* file, io::Printer* printer, bool Generator::Generate( const FileDescriptor* file, - const string& parameter, + const std::string& parameter, GeneratorContext* generator_context, - string* error) const { + std::string* error) const { - if (file->syntax() != FileDescriptor::SYNTAX_PROTO3) { - *error = - "Can only generate Ruby code for proto3 .proto files.\n" - "Please add 'syntax = \"proto3\";' to the top of your .proto file.\n"; + if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && + file->syntax() != FileDescriptor::SYNTAX_PROTO2) { + *error = "Invalid or unsupported proto syntax"; return false; } - scoped_ptr output( + std::unique_ptr output( generator_context->Open(GetOutputFilename(file->name()))); io::Printer printer(output.get(), '$'); diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/google/protobuf/compiler/ruby/ruby_generator.h index 8c1dfa2671729..647bb836065a6 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.h +++ b/src/google/protobuf/compiler/ruby/ruby_generator.h @@ -37,6 +37,8 @@ #include +#include + namespace google { namespace protobuf { namespace compiler { @@ -46,13 +48,13 @@ namespace ruby { // If you create your own protocol compiler binary and you want it to support // Ruby output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT Generator - : public google::protobuf::compiler::CodeGenerator { - virtual bool Generate( - const FileDescriptor* file, - const string& parameter, - GeneratorContext* generator_context, - string* error) const; +class PROTOC_EXPORT Generator : public CodeGenerator { + bool Generate(const FileDescriptor* file, const std::string& parameter, + GeneratorContext* generator_context, + std::string* error) const override; + uint64_t GetSupportedFeatures() const override { + return FEATURE_PROTO3_OPTIONAL; + } }; } // namespace ruby @@ -60,5 +62,6 @@ class LIBPROTOC_EXPORT Generator } // namespace protobuf } // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__ +#include +#endif // GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc index 1aabe8aa98b5f..27439a737bbac 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -29,6 +29,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include #include #include @@ -45,7 +46,7 @@ namespace compiler { namespace ruby { namespace { -string FindRubyTestDir() { +std::string FindRubyTestDir() { return TestSourceDir() + "/google/protobuf/compiler/ruby"; } @@ -56,8 +57,8 @@ string FindRubyTestDir() { // Some day, we may integrate build systems between protoc and the language // extensions to the point where we can do this test in a more automated way. -TEST(RubyGeneratorTest, GeneratorTest) { - string ruby_tests = FindRubyTestDir(); +void RubyTest(string proto_file) { + std::string ruby_tests = FindRubyTestDir(); google::protobuf::compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); @@ -66,42 +67,63 @@ TEST(RubyGeneratorTest, GeneratorTest) { cli.RegisterGenerator("--ruby_out", &ruby_generator, ""); // Copy generated_code.proto to the temporary test directory. - string test_input; + std::string test_input; GOOGLE_CHECK_OK(File::GetContents( - ruby_tests + "/ruby_generated_code.proto", + ruby_tests + proto_file + ".proto", &test_input, true)); GOOGLE_CHECK_OK(File::SetContents( - TestTempDir() + "/ruby_generated_code.proto", + TestTempDir() + proto_file + ".proto", test_input, true)); // Invoke the proto compiler (we will be inside TestTempDir() at this point). - string ruby_out = "--ruby_out=" + TestTempDir(); - string proto_path = "--proto_path=" + TestTempDir(); + std::string ruby_out = "--ruby_out=" + TestTempDir(); + std::string proto_path = "--proto_path=" + TestTempDir(); + std::string proto_target = TestTempDir() + proto_file + ".proto"; const char* argv[] = { "protoc", ruby_out.c_str(), proto_path.c_str(), - "ruby_generated_code.proto", + proto_target.c_str(), }; EXPECT_EQ(0, cli.Run(4, argv)); // Load the generated output and compare to the expected result. - string output; - GOOGLE_CHECK_OK(File::GetContents( - TestTempDir() + "/ruby_generated_code_pb.rb", + std::string output; + GOOGLE_CHECK_OK(File::GetContentsAsText( + TestTempDir() + proto_file + "_pb.rb", &output, true)); - string expected_output; - GOOGLE_CHECK_OK(File::GetContents( - ruby_tests + "/ruby_generated_code_pb.rb", + std::string expected_output; + GOOGLE_CHECK_OK(File::GetContentsAsText( + ruby_tests + proto_file + "_pb.rb", &expected_output, true)); EXPECT_EQ(expected_output, output); } +TEST(RubyGeneratorTest, Proto3GeneratorTest) { + RubyTest("/ruby_generated_code"); +} + +TEST(RubyGeneratorTest, Proto2GeneratorTest) { + RubyTest("/ruby_generated_code_proto2"); +} + +TEST(RubyGeneratorTest, Proto3ImplicitPackageTest) { + RubyTest("/ruby_generated_pkg_implicit"); +} + +TEST(RubyGeneratorTest, Proto3ExplictPackageTest) { + RubyTest("/ruby_generated_pkg_explicit"); +} + +TEST(RubyGeneratorTest, Proto3ExplictLegacyPackageTest) { + RubyTest("/ruby_generated_pkg_explicit_legacy"); +} + } // namespace } // namespace ruby } // namespace compiler diff --git a/src/google/protobuf/compiler/scc.h b/src/google/protobuf/compiler/scc.h new file mode 100644 index 0000000000000..a1394602f78c2 --- /dev/null +++ b/src/google/protobuf/compiler/scc.h @@ -0,0 +1,164 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_SCC_H__ +#define GOOGLE_PROTOBUF_COMPILER_SCC_H__ + +#include + +#include +#include +#include + +#include + +namespace google { +namespace protobuf { +namespace compiler { + +// Description of each strongly connected component. Note that the order +// of both the descriptors in this SCC and the order of children is +// deterministic. +struct SCC { + std::vector descriptors; + std::vector children; + + const Descriptor* GetRepresentative() const { return descriptors[0]; } + + // All messages must necessarily be in the same file. + const FileDescriptor* GetFile() const { return descriptors[0]->file(); } +}; + +// This class is used for analyzing the SCC for each message, to ensure linear +// instead of quadratic performance, if we do this per message we would get +// O(V*(V+E)). +template +class PROTOC_EXPORT SCCAnalyzer { + public: + explicit SCCAnalyzer() : index_(0) {} + + const SCC* GetSCC(const Descriptor* descriptor) { + if (cache_.count(descriptor)) return cache_[descriptor].scc; + return DFS(descriptor).scc; + } + + private: + struct NodeData { + const SCC* scc; // if null it means its still on the stack + int index; + int lowlink; + }; + + std::map cache_; + std::vector stack_; + int index_; + std::vector> garbage_bin_; + + SCC* CreateSCC() { + garbage_bin_.emplace_back(new SCC()); + return garbage_bin_.back().get(); + } + + // Tarjan's Strongly Connected Components algo + NodeData DFS(const Descriptor* descriptor) { + // Must not have visited already. + GOOGLE_DCHECK_EQ(cache_.count(descriptor), 0); + + // Mark visited by inserting in map. + NodeData& result = cache_[descriptor]; + // Initialize data structures. + result.index = result.lowlink = index_++; + stack_.push_back(descriptor); + + // Recurse the fields / nodes in graph + for (auto dep : DepsGenerator()(descriptor)) { + GOOGLE_CHECK(dep); + if (cache_.count(dep) == 0) { + // unexplored node + NodeData child_data = DFS(dep); + result.lowlink = std::min(result.lowlink, child_data.lowlink); + } else { + NodeData child_data = cache_[dep]; + if (child_data.scc == nullptr) { + // Still in the stack_ so we found a back edge + result.lowlink = std::min(result.lowlink, child_data.index); + } + } + } + if (result.index == result.lowlink) { + // This is the root of a strongly connected component + SCC* scc = CreateSCC(); + while (true) { + const Descriptor* scc_desc = stack_.back(); + scc->descriptors.push_back(scc_desc); + // Remove from stack + stack_.pop_back(); + cache_[scc_desc].scc = scc; + + if (scc_desc == descriptor) break; + } + + // The order of descriptors is random and depends how this SCC was + // discovered. In-order to ensure maximum stability we sort it by name. + std::sort(scc->descriptors.begin(), scc->descriptors.end(), + [](const Descriptor* a, const Descriptor* b) { + return a->full_name() < b->full_name(); + }); + AddChildren(scc); + } + return result; + } + + // Add the SCC's that are children of this SCC to its children. + void AddChildren(SCC* scc) { + std::set seen; + for (auto descriptor : scc->descriptors) { + for (auto child_msg : DepsGenerator()(descriptor)) { + GOOGLE_CHECK(child_msg); + const SCC* child = GetSCC(child_msg); + if (child == scc) continue; + if (seen.insert(child).second) { + scc->children.push_back(child); + } + } + } + } + + // This is necessary for compiler bug in msvc2015. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SCCAnalyzer); +}; + +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include + +#endif // GOOGLE_PROTOBUF_COMPILER_SCC_H__ diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc index 2e5a89ac49940..7e59cd7d8d26c 100644 --- a/src/google/protobuf/compiler/subprocess.cc +++ b/src/google/protobuf/compiler/subprocess.cc @@ -38,9 +38,9 @@ #ifndef _WIN32 #include +#include #include #include -#include #endif #include @@ -54,7 +54,7 @@ namespace compiler { namespace { char* portable_strdup(const char* s) { - char* ns = (char*) malloc(strlen(s) + 1); + char* ns = (char*)malloc(strlen(s) + 1); if (ns != NULL) { strcpy(ns, s); } @@ -73,7 +73,9 @@ static void CloseHandleOrDie(HANDLE handle) { Subprocess::Subprocess() : process_start_error_(ERROR_SUCCESS), - child_handle_(NULL), child_stdin_(NULL), child_stdout_(NULL) {} + child_handle_(NULL), + child_stdin_(NULL), + child_stdout_(NULL) {} Subprocess::~Subprocess() { if (child_stdin_ != NULL) { @@ -84,7 +86,7 @@ Subprocess::~Subprocess() { } } -void Subprocess::Start(const string& program, SearchMode search_mode) { +void Subprocess::Start(const std::string& program, SearchMode search_mode) { // Create the pipes. HANDLE stdin_pipe_read; HANDLE stdin_pipe_write; @@ -99,13 +101,13 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { } // Make child side of the pipes inheritable. - if (!SetHandleInformation(stdin_pipe_read, - HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { + if (!SetHandleInformation(stdin_pipe_read, HANDLE_FLAG_INHERIT, + HANDLE_FLAG_INHERIT)) { GOOGLE_LOG(FATAL) << "SetHandleInformation: " << Win32ErrorMessage(GetLastError()); } - if (!SetHandleInformation(stdout_pipe_write, - HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { + if (!SetHandleInformation(stdout_pipe_write, HANDLE_FLAG_INHERIT, + HANDLE_FLAG_INHERIT)) { GOOGLE_LOG(FATAL) << "SetHandleInformation: " << Win32ErrorMessage(GetLastError()); } @@ -120,26 +122,27 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); if (startup_info.hStdError == INVALID_HANDLE_VALUE) { - GOOGLE_LOG(FATAL) << "GetStdHandle: " - << Win32ErrorMessage(GetLastError()); + GOOGLE_LOG(FATAL) << "GetStdHandle: " << Win32ErrorMessage(GetLastError()); } - // CreateProcess() mutates its second parameter. WTF? - char* name_copy = portable_strdup(program.c_str()); + // Invoking cmd.exe allows for '.bat' files from the path as well as '.exe'. + // Using a malloc'ed string because CreateProcess() can mutate its second + // parameter. + char* command_line = + portable_strdup(("cmd.exe /c \"" + program + "\"").c_str()); // Create the process. PROCESS_INFORMATION process_info; if (CreateProcessA((search_mode == SEARCH_PATH) ? NULL : program.c_str(), - (search_mode == SEARCH_PATH) ? name_copy : NULL, + (search_mode == SEARCH_PATH) ? command_line : NULL, NULL, // process security attributes NULL, // thread security attributes TRUE, // inherit handles? 0, // obscure creation flags NULL, // environment (inherit from parent) NULL, // current directory (inherit from parent) - &startup_info, - &process_info)) { + &startup_info, &process_info)) { child_handle_ = process_info.hProcess; CloseHandleOrDie(process_info.hThread); child_stdin_ = stdin_pipe_write; @@ -152,11 +155,11 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { CloseHandleOrDie(stdin_pipe_read); CloseHandleOrDie(stdout_pipe_write); - free(name_copy); + free(command_line); } bool Subprocess::Communicate(const Message& input, Message* output, - string* error) { + std::string* error) { if (process_start_error_ != ERROR_SUCCESS) { *error = Win32ErrorMessage(process_start_error_); return false; @@ -164,8 +167,8 @@ bool Subprocess::Communicate(const Message& input, Message* output, GOOGLE_CHECK(child_handle_ != NULL) << "Must call Start() first."; - string input_data = input.SerializeAsString(); - string output_data; + std::string input_data = input.SerializeAsString(); + std::string output_data; int input_pos = 0; @@ -197,10 +200,8 @@ bool Subprocess::Communicate(const Message& input, Message* output, if (signaled_handle == child_stdin_) { DWORD n; - if (!WriteFile(child_stdin_, - input_data.data() + input_pos, - input_data.size() - input_pos, - &n, NULL)) { + if (!WriteFile(child_stdin_, input_data.data() + input_pos, + input_data.size() - input_pos, &n, NULL)) { // Child closed pipe. Presumably it will report an error later. // Pretend we're done for now. input_pos = input_data.size(); @@ -254,8 +255,7 @@ bool Subprocess::Communicate(const Message& input, Message* output, child_handle_ = NULL; if (exit_code != 0) { - *error = strings::Substitute( - "Plugin failed with status code $0.", exit_code); + *error = strings::Substitute("Plugin failed with status code $0.", exit_code); return false; } @@ -267,17 +267,17 @@ bool Subprocess::Communicate(const Message& input, Message* output, return true; } -string Subprocess::Win32ErrorMessage(DWORD error_code) { +std::string Subprocess::Win32ErrorMessage(DWORD error_code) { char* message; // WTF? FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error_code, 0, + NULL, error_code, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (LPSTR)&message, // NOT A BUG! 0, NULL); - string result = message; + std::string result = message; LocalFree(message); return result; } @@ -298,7 +298,7 @@ Subprocess::~Subprocess() { } } -void Subprocess::Start(const string& program, SearchMode search_mode) { +void Subprocess::Start(const std::string& program, SearchMode search_mode) { // Note that we assume that there are no other threads, thus we don't have to // do crazy stuff like using socket pairs or avoiding libc locks. @@ -309,7 +309,7 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { GOOGLE_CHECK(pipe(stdin_pipe) != -1); GOOGLE_CHECK(pipe(stdout_pipe) != -1); - char* argv[2] = { portable_strdup(program.c_str()), NULL }; + char* argv[2] = {portable_strdup(program.c_str()), NULL}; child_pid_ = fork(); if (child_pid_ == -1) { @@ -337,9 +337,12 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { // stuff that is unsafe here. int ignored; ignored = write(STDERR_FILENO, argv[0], strlen(argv[0])); - const char* message = ": program not found or is not executable\n"; + const char* message = + ": program not found or is not executable\n" + "Please specify a program using absolute path or make sure " + "the program is available in your PATH system variable\n"; ignored = write(STDERR_FILENO, message, strlen(message)); - (void) ignored; + (void)ignored; // Must use _exit() rather than exit() to avoid flushing output buffers // that will also be flushed by the parent. @@ -356,7 +359,7 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { } bool Subprocess::Communicate(const Message& input, Message* output, - string* error) { + std::string* error) { GOOGLE_CHECK_NE(child_stdin_, -1) << "Must call Start() first."; // The "sighandler_t" typedef is GNU-specific, so define our own. @@ -365,8 +368,8 @@ bool Subprocess::Communicate(const Message& input, Message* output, // Make sure SIGPIPE is disabled so that if the child dies it doesn't kill us. SignalHandler* old_pipe_handler = signal(SIGPIPE, SIG_IGN); - string input_data = input.SerializeAsString(); - string output_data; + std::string input_data = input.SerializeAsString(); + std::string output_data; int input_pos = 0; int max_fd = std::max(child_stdin_, child_stdout_); @@ -394,7 +397,7 @@ bool Subprocess::Communicate(const Message& input, Message* output, if (child_stdin_ != -1 && FD_ISSET(child_stdin_, &write_fds)) { int n = write(child_stdin_, input_data.data() + input_pos, - input_data.size() - input_pos); + input_data.size() - input_pos); if (n < 0) { // Child closed pipe. Presumably it will report an error later. // Pretend we're done for now. @@ -444,14 +447,13 @@ bool Subprocess::Communicate(const Message& input, Message* output, if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) { int error_code = WEXITSTATUS(status); - *error = strings::Substitute( - "Plugin failed with status code $0.", error_code); + *error = + strings::Substitute("Plugin failed with status code $0.", error_code); return false; } } else if (WIFSIGNALED(status)) { int signal = WTERMSIG(status); - *error = strings::Substitute( - "Plugin killed by signal $0.", signal); + *error = strings::Substitute("Plugin killed by signal $0.", signal); return false; } else { *error = "Neither WEXITSTATUS nor WTERMSIG is true?"; diff --git a/src/google/protobuf/compiler/subprocess.h b/src/google/protobuf/compiler/subprocess.h index 9d980b0609085..c1ddaae531ded 100644 --- a/src/google/protobuf/compiler/subprocess.h +++ b/src/google/protobuf/compiler/subprocess.h @@ -34,7 +34,9 @@ #define GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__ #ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN // right... +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN // right... +#endif #include #else // _WIN32 #include @@ -44,6 +46,8 @@ #include +#include + namespace google { namespace protobuf { @@ -52,31 +56,31 @@ class Message; namespace compiler { // Utility class for launching sub-processes. -class LIBPROTOC_EXPORT Subprocess { +class PROTOC_EXPORT Subprocess { public: Subprocess(); ~Subprocess(); enum SearchMode { - SEARCH_PATH, // Use PATH environment variable. - EXACT_NAME // Program is an exact file name; don't use the PATH. + SEARCH_PATH, // Use PATH environment variable. + EXACT_NAME // Program is an exact file name; don't use the PATH. }; // Start the subprocess. Currently we don't provide a way to specify // arguments as protoc plugins don't have any. - void Start(const string& program, SearchMode search_mode); + void Start(const std::string& program, SearchMode search_mode); // Serialize the input message and pipe it to the subprocess's stdin, then // close the pipe. Meanwhile, read from the subprocess's stdout and parse // the data into *output. All this is done carefully to avoid deadlocks. // Returns true if successful. On any sort of error, returns false and sets // *error to a description of the problem. - bool Communicate(const Message& input, Message* output, string* error); + bool Communicate(const Message& input, Message* output, std::string* error); #ifdef _WIN32 // Given an error code, returns a human-readable error message. This is // defined here so that CommandLineInterface can share it. - static string Win32ErrorMessage(DWORD error_code); + static std::string Win32ErrorMessage(DWORD error_code); #endif private: @@ -102,6 +106,8 @@ class LIBPROTOC_EXPORT Subprocess { } // namespace compiler } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__ diff --git a/src/google/protobuf/compiler/test_plugin.cc b/src/google/protobuf/compiler/test_plugin.cc index c676ce8ce9f43..6b56170003e4b 100644 --- a/src/google/protobuf/compiler/test_plugin.cc +++ b/src/google/protobuf/compiler/test_plugin.cc @@ -33,10 +33,23 @@ // This is a dummy code generator plugin used by // command_line_interface_unittest. -#include #include -#include +#include #include +#include + +namespace google { +namespace protobuf { +namespace compiler { + +int ProtobufMain(int argc, char* argv[]) { + MockCodeGenerator generator("test_plugin"); + return PluginMain(argc, argv, &generator); +} + +} // namespace compiler +} // namespace protobuf +} // namespace google int main(int argc, char* argv[]) { #ifdef _MSC_VER @@ -44,7 +57,5 @@ int main(int argc, char* argv[]) { // please. _set_abort_behavior(0, ~0); #endif // !_MSC_VER - - google::protobuf::compiler::MockCodeGenerator generator("test_plugin"); - return google::protobuf::compiler::PluginMain(argc, argv, &generator); + return google::protobuf::compiler::ProtobufMain(argc, argv); } diff --git a/src/google/protobuf/compiler/zip_writer.cc b/src/google/protobuf/compiler/zip_writer.cc index 1799af6a4a2f5..5ae026154b207 100644 --- a/src/google/protobuf/compiler/zip_writer.cc +++ b/src/google/protobuf/compiler/zip_writer.cc @@ -28,36 +28,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - // Author: ambrose@google.com (Ambrose Feinstein), // kenton@google.com (Kenton Varda) // @@ -75,52 +45,51 @@ namespace compiler { static const uint16 kDosEpoch = 1 << 5 | 1; static const uint32 kCRC32Table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - -static uint32 ComputeCRC32(const string &buf) { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; + +static uint32 ComputeCRC32(const std::string& buf) { uint32 x = ~0U; for (int i = 0; i < buf.size(); ++i) { unsigned char c = buf[i]; @@ -129,7 +98,7 @@ static uint32 ComputeCRC32(const string &buf) { return ~x; } -static void WriteShort(io::CodedOutputStream *out, uint16 val) { +static void WriteShort(io::CodedOutputStream* out, uint16 val) { uint8 p[2]; p[0] = static_cast(val); p[1] = static_cast(val >> 8); @@ -137,10 +106,11 @@ static void WriteShort(io::CodedOutputStream *out, uint16 val) { } ZipWriter::ZipWriter(io::ZeroCopyOutputStream* raw_output) - : raw_output_(raw_output) {} + : raw_output_(raw_output) {} ZipWriter::~ZipWriter() {} -bool ZipWriter::Write(const string& filename, const string& contents) { +bool ZipWriter::Write(const std::string& filename, + const std::string& contents) { FileInfo info; info.name = filename; @@ -154,18 +124,18 @@ bool ZipWriter::Write(const string& filename, const string& contents) { // write file header io::CodedOutputStream output(raw_output_); output.WriteLittleEndian32(0x04034b50); // magic - WriteShort(&output, 10); // version needed to extract - WriteShort(&output, 0); // flags - WriteShort(&output, 0); // compression method: stored - WriteShort(&output, 0); // last modified time - WriteShort(&output, kDosEpoch); // last modified date + WriteShort(&output, 10); // version needed to extract + WriteShort(&output, 0); // flags + WriteShort(&output, 0); // compression method: stored + WriteShort(&output, 0); // last modified time + WriteShort(&output, kDosEpoch); // last modified date output.WriteLittleEndian32(info.crc32); // crc-32 - output.WriteLittleEndian32(info.size); // compressed size - output.WriteLittleEndian32(info.size); // uncompressed size - WriteShort(&output, filename_size); // file name length - WriteShort(&output, 0); // extra field length - output.WriteString(filename); // file name - output.WriteString(contents); // file data + output.WriteLittleEndian32(info.size); // compressed size + output.WriteLittleEndian32(info.size); // uncompressed size + WriteShort(&output, filename_size); // file name length + WriteShort(&output, 0); // extra field length + output.WriteString(filename); // file name + output.WriteString(contents); // file data return !output.HadError(); } @@ -177,42 +147,42 @@ bool ZipWriter::WriteDirectory() { // write central directory io::CodedOutputStream output(raw_output_); for (int i = 0; i < num_entries; ++i) { - const string &filename = files_[i].name; + const std::string& filename = files_[i].name; uint16 filename_size = filename.size(); uint32 crc32 = files_[i].crc32; uint32 size = files_[i].size; uint32 offset = files_[i].offset; output.WriteLittleEndian32(0x02014b50); // magic - WriteShort(&output, 10); // version made by - WriteShort(&output, 10); // version needed to extract - WriteShort(&output, 0); // flags - WriteShort(&output, 0); // compression method: stored - WriteShort(&output, 0); // last modified time - WriteShort(&output, kDosEpoch); // last modified date - output.WriteLittleEndian32(crc32); // crc-32 - output.WriteLittleEndian32(size); // compressed size - output.WriteLittleEndian32(size); // uncompressed size - WriteShort(&output, filename_size); // file name length - WriteShort(&output, 0); // extra field length - WriteShort(&output, 0); // file comment length - WriteShort(&output, 0); // starting disk number - WriteShort(&output, 0); // internal file attributes - output.WriteLittleEndian32(0); // external file attributes - output.WriteLittleEndian32(offset); // local header offset - output.WriteString(filename); // file name + WriteShort(&output, 10); // version made by + WriteShort(&output, 10); // version needed to extract + WriteShort(&output, 0); // flags + WriteShort(&output, 0); // compression method: stored + WriteShort(&output, 0); // last modified time + WriteShort(&output, kDosEpoch); // last modified date + output.WriteLittleEndian32(crc32); // crc-32 + output.WriteLittleEndian32(size); // compressed size + output.WriteLittleEndian32(size); // uncompressed size + WriteShort(&output, filename_size); // file name length + WriteShort(&output, 0); // extra field length + WriteShort(&output, 0); // file comment length + WriteShort(&output, 0); // starting disk number + WriteShort(&output, 0); // internal file attributes + output.WriteLittleEndian32(0); // external file attributes + output.WriteLittleEndian32(offset); // local header offset + output.WriteString(filename); // file name } uint32 dir_len = output.ByteCount(); // write end of central directory marker output.WriteLittleEndian32(0x06054b50); // magic - WriteShort(&output, 0); // disk number - WriteShort(&output, 0); // disk with start of central directory - WriteShort(&output, num_entries); // central directory entries (this disk) - WriteShort(&output, num_entries); // central directory entries (total) + WriteShort(&output, 0); // disk number + WriteShort(&output, 0); // disk with start of central directory + WriteShort(&output, num_entries); // central directory entries (this disk) + WriteShort(&output, num_entries); // central directory entries (total) output.WriteLittleEndian32(dir_len); // central directory byte size output.WriteLittleEndian32(dir_ofs); // central directory offset - WriteShort(&output, 0); // comment length + WriteShort(&output, 0); // comment length return output.HadError(); } diff --git a/src/google/protobuf/compiler/zip_writer.h b/src/google/protobuf/compiler/zip_writer.h index 03db4d573cc06..3a8903a3f34ca 100644 --- a/src/google/protobuf/compiler/zip_writer.h +++ b/src/google/protobuf/compiler/zip_writer.h @@ -28,36 +28,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - // Author: kenton@google.com (Kenton Varda) #include @@ -73,12 +43,12 @@ class ZipWriter { ZipWriter(io::ZeroCopyOutputStream* raw_output); ~ZipWriter(); - bool Write(const string& filename, const string& contents); + bool Write(const std::string& filename, const std::string& contents); bool WriteDirectory(); private: struct FileInfo { - string name; + std::string name; uint32 offset; uint32 size; uint32 crc32; diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 89b37ee33f64f..03c4e2b516ff2 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -32,45 +32,47 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include +#include + +#include +#include +#include #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include +#include +#include #include -#include -#include #include #include -#include -#include #include #include -#include +#include +#include #include #include #include -#include -#include #include #include #include #include #include #include +#include #include - +#include #include #include +#include #undef PACKAGE // autoheader #defines this. :( -namespace google { +#include + +namespace google { namespace protobuf { struct Symbol { @@ -97,7 +99,7 @@ struct Symbol { const FileDescriptor* package_file_descriptor; }; - inline Symbol() : type(NULL_SYMBOL) { descriptor = NULL; } + inline Symbol() : type(NULL_SYMBOL) { descriptor = nullptr; } inline bool IsNull() const { return type == NULL_SYMBOL; } inline bool IsType() const { return type == MESSAGE || type == ENUM; } inline bool IsAggregate() const { @@ -124,7 +126,7 @@ struct Symbol { const FileDescriptor* GetFile() const { switch (type) { case NULL_SYMBOL: - return NULL; + return nullptr; case MESSAGE: return descriptor->file(); case FIELD: @@ -142,78 +144,78 @@ struct Symbol { case PACKAGE: return package_file_descriptor; } - return NULL; + return nullptr; } }; const FieldDescriptor::CppType -FieldDescriptor::kTypeToCppTypeMap[MAX_TYPE + 1] = { - static_cast(0), // 0 is reserved for errors - - CPPTYPE_DOUBLE, // TYPE_DOUBLE - CPPTYPE_FLOAT, // TYPE_FLOAT - CPPTYPE_INT64, // TYPE_INT64 - CPPTYPE_UINT64, // TYPE_UINT64 - CPPTYPE_INT32, // TYPE_INT32 - CPPTYPE_UINT64, // TYPE_FIXED64 - CPPTYPE_UINT32, // TYPE_FIXED32 - CPPTYPE_BOOL, // TYPE_BOOL - CPPTYPE_STRING, // TYPE_STRING - CPPTYPE_MESSAGE, // TYPE_GROUP - CPPTYPE_MESSAGE, // TYPE_MESSAGE - CPPTYPE_STRING, // TYPE_BYTES - CPPTYPE_UINT32, // TYPE_UINT32 - CPPTYPE_ENUM, // TYPE_ENUM - CPPTYPE_INT32, // TYPE_SFIXED32 - CPPTYPE_INT64, // TYPE_SFIXED64 - CPPTYPE_INT32, // TYPE_SINT32 - CPPTYPE_INT64, // TYPE_SINT64 + FieldDescriptor::kTypeToCppTypeMap[MAX_TYPE + 1] = { + static_cast(0), // 0 is reserved for errors + + CPPTYPE_DOUBLE, // TYPE_DOUBLE + CPPTYPE_FLOAT, // TYPE_FLOAT + CPPTYPE_INT64, // TYPE_INT64 + CPPTYPE_UINT64, // TYPE_UINT64 + CPPTYPE_INT32, // TYPE_INT32 + CPPTYPE_UINT64, // TYPE_FIXED64 + CPPTYPE_UINT32, // TYPE_FIXED32 + CPPTYPE_BOOL, // TYPE_BOOL + CPPTYPE_STRING, // TYPE_STRING + CPPTYPE_MESSAGE, // TYPE_GROUP + CPPTYPE_MESSAGE, // TYPE_MESSAGE + CPPTYPE_STRING, // TYPE_BYTES + CPPTYPE_UINT32, // TYPE_UINT32 + CPPTYPE_ENUM, // TYPE_ENUM + CPPTYPE_INT32, // TYPE_SFIXED32 + CPPTYPE_INT64, // TYPE_SFIXED64 + CPPTYPE_INT32, // TYPE_SINT32 + CPPTYPE_INT64, // TYPE_SINT64 }; -const char * const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = { - "ERROR", // 0 is reserved for errors - - "double", // TYPE_DOUBLE - "float", // TYPE_FLOAT - "int64", // TYPE_INT64 - "uint64", // TYPE_UINT64 - "int32", // TYPE_INT32 - "fixed64", // TYPE_FIXED64 - "fixed32", // TYPE_FIXED32 - "bool", // TYPE_BOOL - "string", // TYPE_STRING - "group", // TYPE_GROUP - "message", // TYPE_MESSAGE - "bytes", // TYPE_BYTES - "uint32", // TYPE_UINT32 - "enum", // TYPE_ENUM - "sfixed32", // TYPE_SFIXED32 - "sfixed64", // TYPE_SFIXED64 - "sint32", // TYPE_SINT32 - "sint64", // TYPE_SINT64 +const char* const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = { + "ERROR", // 0 is reserved for errors + + "double", // TYPE_DOUBLE + "float", // TYPE_FLOAT + "int64", // TYPE_INT64 + "uint64", // TYPE_UINT64 + "int32", // TYPE_INT32 + "fixed64", // TYPE_FIXED64 + "fixed32", // TYPE_FIXED32 + "bool", // TYPE_BOOL + "string", // TYPE_STRING + "group", // TYPE_GROUP + "message", // TYPE_MESSAGE + "bytes", // TYPE_BYTES + "uint32", // TYPE_UINT32 + "enum", // TYPE_ENUM + "sfixed32", // TYPE_SFIXED32 + "sfixed64", // TYPE_SFIXED64 + "sint32", // TYPE_SINT32 + "sint64", // TYPE_SINT64 }; -const char * const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = { - "ERROR", // 0 is reserved for errors - - "int32", // CPPTYPE_INT32 - "int64", // CPPTYPE_INT64 - "uint32", // CPPTYPE_UINT32 - "uint64", // CPPTYPE_UINT64 - "double", // CPPTYPE_DOUBLE - "float", // CPPTYPE_FLOAT - "bool", // CPPTYPE_BOOL - "enum", // CPPTYPE_ENUM - "string", // CPPTYPE_STRING - "message", // CPPTYPE_MESSAGE +const char* const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = { + "ERROR", // 0 is reserved for errors + + "int32", // CPPTYPE_INT32 + "int64", // CPPTYPE_INT64 + "uint32", // CPPTYPE_UINT32 + "uint64", // CPPTYPE_UINT64 + "double", // CPPTYPE_DOUBLE + "float", // CPPTYPE_FLOAT + "bool", // CPPTYPE_BOOL + "enum", // CPPTYPE_ENUM + "string", // CPPTYPE_STRING + "message", // CPPTYPE_MESSAGE }; -const char * const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = { - "ERROR", // 0 is reserved for errors +const char* const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = { + "ERROR", // 0 is reserved for errors - "optional", // LABEL_OPTIONAL - "required", // LABEL_REQUIRED - "repeated", // LABEL_REPEATED + "optional", // LABEL_OPTIONAL + "required", // LABEL_REQUIRED + "repeated", // LABEL_REPEATED }; const char* FileDescriptor::SyntaxName(FileDescriptor::Syntax syntax) { @@ -226,10 +228,10 @@ const char* FileDescriptor::SyntaxName(FileDescriptor::Syntax syntax) { return "unknown"; } GOOGLE_LOG(FATAL) << "can't reach here."; - return NULL; + return nullptr; } -static const char * const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty"; +static const char* const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty"; #if !defined(_MSC_VER) || _MSC_VER >= 1900 const int FieldDescriptor::kMaxNumber; @@ -248,19 +250,19 @@ char ToLower(char ch) { return (ch >= 'A' && ch <= 'Z') ? (ch - 'A' + 'a') : ch; } -string ToCamelCase(const string& input, bool lower_first) { +std::string ToCamelCase(const std::string& input, bool lower_first) { bool capitalize_next = !lower_first; - string result; + std::string result; result.reserve(input.size()); - for (int i = 0; i < input.size(); i++) { - if (input[i] == '_') { + for (char character : input) { + if (character == '_') { capitalize_next = true; } else if (capitalize_next) { - result.push_back(ToUpper(input[i])); + result.push_back(ToUpper(character)); capitalize_next = false; } else { - result.push_back(input[i]); + result.push_back(character); } } @@ -272,38 +274,38 @@ string ToCamelCase(const string& input, bool lower_first) { return result; } -string ToJsonName(const string& input) { +std::string ToJsonName(const std::string& input) { bool capitalize_next = false; - string result; + std::string result; result.reserve(input.size()); - for (int i = 0; i < input.size(); i++) { - if (input[i] == '_') { + for (char character : input) { + if (character == '_') { capitalize_next = true; } else if (capitalize_next) { - result.push_back(ToUpper(input[i])); + result.push_back(ToUpper(character)); capitalize_next = false; } else { - result.push_back(input[i]); + result.push_back(character); } } return result; } -string EnumValueToPascalCase(const string& input) { +std::string EnumValueToPascalCase(const std::string& input) { bool next_upper = true; - string result; + std::string result; result.reserve(input.size()); - for (int i = 0; i < input.size(); i++) { - if (input[i] == '_') { + for (char character : input) { + if (character == '_') { next_upper = true; } else { if (next_upper) { - result.push_back(ToUpper(input[i])); + result.push_back(ToUpper(character)); } else { - result.push_back(ToLower(input[i])); + result.push_back(ToLower(character)); } next_upper = false; } @@ -317,16 +319,16 @@ class PrefixRemover { public: PrefixRemover(StringPiece prefix) { // Strip underscores and lower-case the prefix. - for (int i = 0; i < prefix.size(); i++) { - if (prefix[i] != '_') { - prefix_ += ascii_tolower(prefix[i]); + for (char character : prefix) { + if (character != '_') { + prefix_ += ascii_tolower(character); } } } // Tries to remove the enum prefix from this enum value. // If this is not possible, returns the input verbatim. - string MaybeRemove(StringPiece str) { + std::string MaybeRemove(StringPiece str) { // We can't just lowercase and strip str and look for a prefix. // We need to properly recognize the difference between: // @@ -346,14 +348,14 @@ class PrefixRemover { } if (ascii_tolower(str[i]) != prefix_[j++]) { - return str.as_string(); + return std::string(str); } } // If we didn't make it through the prefix, we've failed to strip the // prefix. if (j < prefix_.size()) { - return str.as_string(); + return std::string(str); } // Skip underscores between prefix and further characters. @@ -363,47 +365,42 @@ class PrefixRemover { // Enum label can't be the empty string. if (i == str.size()) { - return str.as_string(); + return std::string(str); } // We successfully stripped the prefix. str.remove_prefix(i); - return str.as_string(); + return std::string(str); } private: - string prefix_; + std::string prefix_; }; -// A DescriptorPool contains a bunch of hash_maps to implement the +// A DescriptorPool contains a bunch of hash-maps to implement the // various Find*By*() methods. Since hashtable lookups are O(1), it's -// most efficient to construct a fixed set of large hash_maps used by +// most efficient to construct a fixed set of large hash-maps used by // all objects in the pool rather than construct one or more small -// hash_maps for each object. +// hash-maps for each object. // -// The keys to these hash_maps are (parent, name) or (parent, number) -// pairs. Unfortunately STL doesn't provide hash functions for pair<>, -// so we must invent our own. -// -// TODO(kenton): Use StringPiece rather than const char* in keys? It would -// be a lot cleaner but we'd just have to convert it back to const char* -// for the open source release. +// The keys to these hash-maps are (parent, name) or (parent, number) pairs. -typedef std::pair PointerStringPair; +typedef std::pair PointerStringPair; -struct PointerStringPairEqual { - inline bool operator()(const PointerStringPair& a, - const PointerStringPair& b) const { - return a.first == b.first && strcmp(a.second, b.second) == 0; - } -}; +typedef std::pair DescriptorIntPair; +typedef std::pair EnumIntPair; + +#define HASH_MAP std::unordered_map +#define HASH_SET std::unordered_set +#define HASH_FXN hash -template +template struct PointerIntegerPairHash { size_t operator()(const PairType& p) const { - // FIXME(kenton): What is the best way to compute this hash? I have - // no idea! This seems a bit better than an XOR. - return reinterpret_cast(p.first) * ((1 << 16) - 1) + p.second; + static const size_t prime1 = 16777499; + static const size_t prime2 = 16777619; + return reinterpret_cast(p.first) * prime1 ^ + static_cast(p.second) * prime2; } #ifdef _MSC_VER @@ -412,21 +409,16 @@ struct PointerIntegerPairHash { static const size_t min_buckets = 8; #endif inline bool operator()(const PairType& a, const PairType& b) const { - return a.first < b.first || - (a.first == b.first && a.second < b.second); + return a < b; } }; -typedef std::pair DescriptorIntPair; -typedef std::pair EnumIntPair; - struct PointerStringPairHash { size_t operator()(const PointerStringPair& p) const { - // FIXME(kenton): What is the best way to compute this hash? I have - // no idea! This seems a bit better than an XOR. - hash cstring_hash; - return reinterpret_cast(p.first) * ((1 << 16) - 1) + - cstring_hash(p.second); + static const size_t prime = 16777619; + hash string_hash; + return reinterpret_cast(p.first) * prime ^ + static_cast(string_hash(p.second)); } #ifdef _MSC_VER @@ -436,75 +428,72 @@ struct PointerStringPairHash { #endif inline bool operator()(const PointerStringPair& a, const PointerStringPair& b) const { - if (a.first < b.first) return true; - if (a.first > b.first) return false; - return strcmp(a.second, b.second) < 0; + return a < b; } }; const Symbol kNullSymbol; -typedef hash_map, streq> - SymbolsByNameMap; -typedef hash_map - SymbolsByParentMap; -typedef hash_map, streq> - FilesByNameMap; -typedef hash_map - FieldsByNameMap; -typedef hash_map > - FieldsByNumberMap; -typedef hash_map > - EnumValuesByNumberMap; -// This is a map rather than a hash_map, since we use it to iterate +typedef HASH_MAP> + SymbolsByNameMap; + +typedef HASH_MAP + SymbolsByParentMap; + +typedef HASH_MAP> + FilesByNameMap; + +typedef HASH_MAP + FieldsByNameMap; + +typedef HASH_MAP, + std::equal_to> + FieldsByNumberMap; + +typedef HASH_MAP, + std::equal_to> + EnumValuesByNumberMap; +// This is a map rather than a hash-map, since we use it to iterate // through all the extensions that extend a given Descriptor, and an // ordered data structure that implements lower_bound is convenient // for that. typedef std::map - ExtensionsGroupedByDescriptorMap; -typedef hash_map LocationsByPathMap; - -std::set* allowed_proto3_extendees_ = NULL; -GOOGLE_PROTOBUF_DECLARE_ONCE(allowed_proto3_extendees_init_); - -void DeleteAllowedProto3Extendee() { - delete allowed_proto3_extendees_; -} + ExtensionsGroupedByDescriptorMap; +typedef HASH_MAP + LocationsByPathMap; -void InitAllowedProto3Extendee() { - allowed_proto3_extendees_ = new std::set; +std::set* NewAllowedProto3Extendee() { + auto allowed_proto3_extendees = new std::set; const char* kOptionNames[] = { - "FileOptions", "MessageOptions", "FieldOptions", "EnumOptions", + "FileOptions", "MessageOptions", "FieldOptions", "EnumOptions", "EnumValueOptions", "ServiceOptions", "MethodOptions", "OneofOptions"}; - for (int i = 0; i < GOOGLE_ARRAYSIZE(kOptionNames); ++i) { + for (const char* option_name : kOptionNames) { // descriptor.proto has a different package name in opensource. We allow // both so the opensource protocol compiler can also compile internal // proto3 files with custom options. See: b/27567912 - allowed_proto3_extendees_->insert(string("google.protobuf.") + - kOptionNames[i]); + allowed_proto3_extendees->insert(std::string("google.protobuf.") + + option_name); // Split the word to trick the opensource processing scripts so they - // will keep the origial package name. - allowed_proto3_extendees_->insert(string("proto") + "2." + kOptionNames[i]); + // will keep the original package name. + allowed_proto3_extendees->insert(std::string("proto") + "2." + option_name); } - - google::protobuf::internal::OnShutdown(&DeleteAllowedProto3Extendee); + return allowed_proto3_extendees; } // Checks whether the extendee type is allowed in proto3. // Only extensions to descriptor options are allowed. We use name comparison // instead of comparing the descriptor directly because the extensions may be // defined in a different pool. -bool AllowedExtendeeInProto3(const string& name) { - ::google::protobuf::GoogleOnceInit(&allowed_proto3_extendees_init_, &InitAllowedProto3Extendee); - return allowed_proto3_extendees_->find(name) != - allowed_proto3_extendees_->end(); +bool AllowedExtendeeInProto3(const std::string& name) { + static auto allowed_proto3_extendees = + internal::OnShutdownDelete(NewAllowedProto3Extendee()); + return allowed_proto3_extendees->find(name) != + allowed_proto3_extendees->end(); } } // anonymous namespace @@ -556,44 +545,49 @@ class DescriptorPool::Tables { // The stack of files which are currently being built. Used to detect // cyclic dependencies when loading files from a DescriptorDatabase. Not - // used when fallback_database_ == NULL. - std::vector pending_files_; + // used when fallback_database_ == nullptr. + std::vector pending_files_; // A set of files which we have tried to load from the fallback database // and encountered errors. We will not attempt to load them again during // execution of the current public API call, but for compatibility with // legacy clients, this is cleared at the beginning of each public API call. - // Not used when fallback_database_ == NULL. - hash_set known_bad_files_; + // Not used when fallback_database_ == nullptr. + HASH_SET known_bad_files_; // A set of symbols which we have tried to load from the fallback database // and encountered errors. We will not attempt to load them again during // execution of the current public API call, but for compatibility with // legacy clients, this is cleared at the beginning of each public API call. - hash_set known_bad_symbols_; + HASH_SET known_bad_symbols_; // The set of descriptors for which we've already loaded the full // set of extensions numbers from fallback_database_. - hash_set extensions_loaded_from_db_; + HASH_SET extensions_loaded_from_db_; + + // Maps type name to Descriptor::WellKnownType. This is logically global + // and const, but we make it a member here to simplify its construction and + // destruction. This only has 20-ish entries and is one per DescriptorPool, + // so the overhead is small. + HASH_MAP well_known_types_; // ----------------------------------------------------------------- // Finding items. // Find symbols. This returns a null Symbol (symbol.IsNull() is true) // if not found. - inline Symbol FindSymbol(const string& key) const; + inline Symbol FindSymbol(StringPiece key) const; // This implements the body of DescriptorPool::Find*ByName(). It should // really be a private method of DescriptorPool, but that would require // declaring Symbol in descriptor.h, which would drag all kinds of other // stuff into the header. Yay C++. - Symbol FindByNameHelper( - const DescriptorPool* pool, const string& name); + Symbol FindByNameHelper(const DescriptorPool* pool, StringPiece name); - // These return NULL if not found. - inline const FileDescriptor* FindFile(const string& key) const; + // These return nullptr if not found. + inline const FileDescriptor* FindFile(StringPiece key) const; inline const FieldDescriptor* FindExtension(const Descriptor* extendee, - int number); + int number) const; inline void FindAllExtensions(const Descriptor* extendee, std::vector* out) const; @@ -604,7 +598,7 @@ class DescriptorPool::Tables { // the key already exists in the table. For AddSymbol(), the string passed // in must be one that was constructed using AllocateString(), as it will // be used as a key in the symbols_by_name_ map without copying. - bool AddSymbol(const string& full_name, Symbol symbol); + bool AddSymbol(const std::string& full_name, Symbol symbol); bool AddFile(const FileDescriptor* file); bool AddExtension(const FieldDescriptor* field); @@ -615,40 +609,46 @@ class DescriptorPool::Tables { // destroyed. Note that the object's destructor will never be called, // so its fields must be plain old data (primitive data types and // pointers). All of the descriptor types are such objects. - template Type* Allocate(); + template + Type* Allocate(); // Allocate an array of objects which will be reclaimed when the // pool in destroyed. Again, destructors are never called. - template Type* AllocateArray(int count); + template + Type* AllocateArray(int count); // Allocate a string which will be destroyed when the pool is destroyed. // The string is initialized to the given value for convenience. - string* AllocateString(const string& value); + std::string* AllocateString(StringPiece value); + + // Allocate empty string which will be destroyed when the pool is destroyed. + std::string* AllocateEmptyString(); - // Allocate a GoogleOnceDynamic which will be destroyed when the pool is + // Allocate a internal::call_once which will be destroyed when the pool is // destroyed. - GoogleOnceDynamic* AllocateOnceDynamic(); + internal::once_flag* AllocateOnceDynamic(); // Allocate a protocol message object. Some older versions of GCC have // trouble understanding explicit template instantiations in some cases, so // in those cases we have to pass a dummy pointer of the right type as the // parameter instead of specifying the type explicitly. - template Type* AllocateMessage(Type* dummy = NULL); + template + Type* AllocateMessage(Type* dummy = nullptr); // Allocate a FileDescriptorTables object. FileDescriptorTables* AllocateFileTables(); private: - std::vector strings_; // All strings in the pool. - std::vector messages_; // All messages in the pool. - std::vector - once_dynamics_; // All GoogleOnceDynamics in the pool. - std::vector - file_tables_; // All file tables in the pool. - std::vector allocations_; // All other memory allocated in the pool. - - SymbolsByNameMap symbols_by_name_; - FilesByNameMap files_by_name_; + // All other memory allocated in the pool. Must be first as other objects can + // point into these. + std::vector> allocations_; + std::vector> strings_; + std::vector> messages_; + std::vector> once_dynamics_; + std::vector> file_tables_; + + SymbolsByNameMap symbols_by_name_; + FilesByNameMap files_by_name_; ExtensionsGroupedByDescriptorMap extensions_; struct CheckPoint { @@ -674,8 +674,8 @@ class DescriptorPool::Tables { int pending_extensions_before_checkpoint; }; std::vector checkpoints_; - std::vector symbols_after_checkpoint_; - std::vector files_after_checkpoint_; + std::vector symbols_after_checkpoint_; + std::vector files_after_checkpoint_; std::vector extensions_after_checkpoint_; // Allocate some bytes which will be reclaimed when the pool is @@ -706,20 +706,20 @@ class FileDescriptorTables { // Find symbols. These return a null Symbol (symbol.IsNull() is true) // if not found. inline Symbol FindNestedSymbol(const void* parent, - const string& name) const; + StringPiece name) const; inline Symbol FindNestedSymbolOfType(const void* parent, - const string& name, + StringPiece name, const Symbol::Type type) const; - // These return NULL if not found. - inline const FieldDescriptor* FindFieldByNumber( - const Descriptor* parent, int number) const; + // These return nullptr if not found. + inline const FieldDescriptor* FindFieldByNumber(const Descriptor* parent, + int number) const; inline const FieldDescriptor* FindFieldByLowercaseName( - const void* parent, const string& lowercase_name) const; + const void* parent, StringPiece lowercase_name) const; inline const FieldDescriptor* FindFieldByCamelcaseName( - const void* parent, const string& camelcase_name) const; + const void* parent, StringPiece camelcase_name) const; inline const EnumValueDescriptor* FindEnumValueByNumber( - const EnumDescriptor* parent, int number) const; + const EnumDescriptor* parent, int number) const; // This creates a new EnumValueDescriptor if not found, in a thread-safe way. inline const EnumValueDescriptor* FindEnumValueByNumberCreatingIfUnknown( const EnumDescriptor* parent, int number) const; @@ -731,7 +731,7 @@ class FileDescriptorTables { // the key already exists in the table. For AddAliasUnderParent(), the // string passed in must be one that was constructed using AllocateString(), // as it will be used as a key in the symbols_by_parent_ map without copying. - bool AddAliasUnderParent(const void* parent, const string& name, + bool AddAliasUnderParent(const void* parent, const std::string& name, Symbol symbol); bool AddFieldByNumber(const FieldDescriptor* field); bool AddEnumValueByNumber(const EnumValueDescriptor* value); @@ -741,94 +741,98 @@ class FileDescriptorTables { void AddFieldByStylizedNames(const FieldDescriptor* field); // Populates p->first->locations_by_path_ from p->second. - // Unusual signature dictated by GoogleOnceDynamic. + // Unusual signature dictated by internal::call_once. static void BuildLocationsByPath( std::pair* p); // Returns the location denoted by the specified path through info, - // or NULL if not found. + // or nullptr if not found. // The value of info must be that of the corresponding FileDescriptor. // (Conceptually a pure function, but stateful as an optimisation.) const SourceCodeInfo_Location* GetSourceLocation( const std::vector& path, const SourceCodeInfo* info) const; + // Must be called after BuildFileImpl(), even if the build failed and + // we are going to roll back to the last checkpoint. + void FinalizeTables(); + private: - SymbolsByParentMap symbols_by_parent_; - FieldsByNameMap fields_by_lowercase_name_; - FieldsByNameMap fields_by_camelcase_name_; - FieldsByNumberMap fields_by_number_; // Not including extensions. + const void* FindParentForFieldsByMap(const FieldDescriptor* field) const; + static void FieldsByLowercaseNamesLazyInitStatic( + const FileDescriptorTables* tables); + void FieldsByLowercaseNamesLazyInitInternal() const; + static void FieldsByCamelcaseNamesLazyInitStatic( + const FileDescriptorTables* tables); + void FieldsByCamelcaseNamesLazyInitInternal() const; + + SymbolsByParentMap symbols_by_parent_; + mutable FieldsByNameMap fields_by_lowercase_name_; + std::unique_ptr fields_by_lowercase_name_tmp_; + mutable internal::once_flag fields_by_lowercase_name_once_; + mutable FieldsByNameMap fields_by_camelcase_name_; + std::unique_ptr fields_by_camelcase_name_tmp_; + mutable internal::once_flag fields_by_camelcase_name_once_; + FieldsByNumberMap fields_by_number_; // Not including extensions. EnumValuesByNumberMap enum_values_by_number_; mutable EnumValuesByNumberMap unknown_enum_values_by_number_ - GOOGLE_GUARDED_BY(unknown_enum_values_mu_); + PROTOBUF_GUARDED_BY(unknown_enum_values_mu_); // Populated on first request to save space, hence constness games. - mutable GoogleOnceDynamic locations_by_path_once_; + mutable internal::once_flag locations_by_path_once_; mutable LocationsByPathMap locations_by_path_; // Mutex to protect the unknown-enum-value map due to dynamic // EnumValueDescriptor creation on unknown values. - mutable Mutex unknown_enum_values_mu_; + mutable internal::WrappedMutex unknown_enum_values_mu_; }; DescriptorPool::Tables::Tables() - // Start some hash_map and hash_set objects with a small # of buckets + // Start some hash-map and hash-set objects with a small # of buckets : known_bad_files_(3), known_bad_symbols_(3), extensions_loaded_from_db_(3), symbols_by_name_(3), - files_by_name_(3) {} - - -DescriptorPool::Tables::~Tables() { - GOOGLE_DCHECK(checkpoints_.empty()); - // Note that the deletion order is important, since the destructors of some - // messages may refer to objects in allocations_. - STLDeleteElements(&messages_); - for (int i = 0; i < allocations_.size(); i++) { - operator delete(allocations_[i]); - } - STLDeleteElements(&strings_); - STLDeleteElements(&file_tables_); - STLDeleteElements(&once_dynamics_); -} + files_by_name_(3) { + well_known_types_.insert({ + {"google.protobuf.DoubleValue", Descriptor::WELLKNOWNTYPE_DOUBLEVALUE}, + {"google.protobuf.FloatValue", Descriptor::WELLKNOWNTYPE_FLOATVALUE}, + {"google.protobuf.Int64Value", Descriptor::WELLKNOWNTYPE_INT64VALUE}, + {"google.protobuf.UInt64Value", Descriptor::WELLKNOWNTYPE_UINT64VALUE}, + {"google.protobuf.Int32Value", Descriptor::WELLKNOWNTYPE_INT32VALUE}, + {"google.protobuf.UInt32Value", Descriptor::WELLKNOWNTYPE_UINT32VALUE}, + {"google.protobuf.StringValue", Descriptor::WELLKNOWNTYPE_STRINGVALUE}, + {"google.protobuf.BytesValue", Descriptor::WELLKNOWNTYPE_BYTESVALUE}, + {"google.protobuf.BoolValue", Descriptor::WELLKNOWNTYPE_BOOLVALUE}, + {"google.protobuf.Any", Descriptor::WELLKNOWNTYPE_ANY}, + {"google.protobuf.FieldMask", Descriptor::WELLKNOWNTYPE_FIELDMASK}, + {"google.protobuf.Duration", Descriptor::WELLKNOWNTYPE_DURATION}, + {"google.protobuf.Timestamp", Descriptor::WELLKNOWNTYPE_TIMESTAMP}, + {"google.protobuf.Value", Descriptor::WELLKNOWNTYPE_VALUE}, + {"google.protobuf.ListValue", Descriptor::WELLKNOWNTYPE_LISTVALUE}, + {"google.protobuf.Struct", Descriptor::WELLKNOWNTYPE_STRUCT}, + }); +} + +DescriptorPool::Tables::~Tables() { GOOGLE_DCHECK(checkpoints_.empty()); } FileDescriptorTables::FileDescriptorTables() - // Initialize all the hash tables to start out with a small # of buckets + // Initialize all the hash tables to start out with a small # of buckets. : symbols_by_parent_(3), fields_by_lowercase_name_(3), + fields_by_lowercase_name_tmp_(new FieldsByNameMap()), fields_by_camelcase_name_(3), + fields_by_camelcase_name_tmp_(new FieldsByNameMap()), fields_by_number_(3), enum_values_by_number_(3), - unknown_enum_values_by_number_(3) { -} + unknown_enum_values_by_number_(3), + locations_by_path_(3) {} FileDescriptorTables::~FileDescriptorTables() {} -namespace { - -FileDescriptorTables* file_descriptor_tables_ = NULL; -GOOGLE_PROTOBUF_DECLARE_ONCE(file_descriptor_tables_once_init_); - -void DeleteFileDescriptorTables() { - delete file_descriptor_tables_; - file_descriptor_tables_ = NULL; -} - -void InitFileDescriptorTables() { - file_descriptor_tables_ = new FileDescriptorTables(); - internal::OnShutdown(&DeleteFileDescriptorTables); -} - -inline void InitFileDescriptorTablesOnce() { - ::google::protobuf::GoogleOnceInit( - &file_descriptor_tables_once_init_, &InitFileDescriptorTables); -} - -} // anonymous namespace - inline const FileDescriptorTables& FileDescriptorTables::GetEmptyInstance() { - InitFileDescriptorTablesOnce(); - return *file_descriptor_tables_; + static auto file_descriptor_tables = + internal::OnShutdownDelete(new FileDescriptorTables()); + return *file_descriptor_tables; } void DescriptorPool::Tables::AddCheckpoint() { @@ -851,19 +855,16 @@ void DescriptorPool::Tables::RollbackToLastCheckpoint() { GOOGLE_DCHECK(!checkpoints_.empty()); const CheckPoint& checkpoint = checkpoints_.back(); - for (int i = checkpoint.pending_symbols_before_checkpoint; - i < symbols_after_checkpoint_.size(); - i++) { + for (size_t i = checkpoint.pending_symbols_before_checkpoint; + i < symbols_after_checkpoint_.size(); i++) { symbols_by_name_.erase(symbols_after_checkpoint_[i]); } - for (int i = checkpoint.pending_files_before_checkpoint; - i < files_after_checkpoint_.size(); - i++) { + for (size_t i = checkpoint.pending_files_before_checkpoint; + i < files_after_checkpoint_.size(); i++) { files_by_name_.erase(files_after_checkpoint_[i]); } - for (int i = checkpoint.pending_extensions_before_checkpoint; - i < extensions_after_checkpoint_.size(); - i++) { + for (size_t i = checkpoint.pending_extensions_before_checkpoint; + i < extensions_after_checkpoint_.size(); i++) { extensions_.erase(extensions_after_checkpoint_[i]); } @@ -873,23 +874,6 @@ void DescriptorPool::Tables::RollbackToLastCheckpoint() { extensions_after_checkpoint_.resize( checkpoint.pending_extensions_before_checkpoint); - STLDeleteContainerPointers( - strings_.begin() + checkpoint.strings_before_checkpoint, strings_.end()); - STLDeleteContainerPointers( - messages_.begin() + checkpoint.messages_before_checkpoint, - messages_.end()); - STLDeleteContainerPointers( - once_dynamics_.begin() + checkpoint.once_dynamics_before_checkpoint, - once_dynamics_.end()); - STLDeleteContainerPointers( - file_tables_.begin() + checkpoint.file_tables_before_checkpoint, - file_tables_.end()); - for (int i = checkpoint.allocations_before_checkpoint; - i < allocations_.size(); - i++) { - operator delete(allocations_[i]); - } - strings_.resize(checkpoint.strings_before_checkpoint); messages_.resize(checkpoint.messages_before_checkpoint); once_dynamics_.resize(checkpoint.once_dynamics_before_checkpoint); @@ -900,9 +884,9 @@ void DescriptorPool::Tables::RollbackToLastCheckpoint() { // ------------------------------------------------------------------- -inline Symbol DescriptorPool::Tables::FindSymbol(const string& key) const { - const Symbol* result = FindOrNull(symbols_by_name_, key.c_str()); - if (result == NULL) { +inline Symbol DescriptorPool::Tables::FindSymbol(StringPiece key) const { + const Symbol* result = FindOrNull(symbols_by_name_, key); + if (result == nullptr) { return kNullSymbol; } else { return *result; @@ -910,10 +894,10 @@ inline Symbol DescriptorPool::Tables::FindSymbol(const string& key) const { } inline Symbol FileDescriptorTables::FindNestedSymbol( - const void* parent, const string& name) const { + const void* parent, StringPiece name) const { const Symbol* result = - FindOrNull(symbols_by_parent_, PointerStringPair(parent, name.c_str())); - if (result == NULL) { + FindOrNull(symbols_by_parent_, PointerStringPair(parent, name)); + if (result == nullptr) { return kNullSymbol; } else { return *result; @@ -921,23 +905,32 @@ inline Symbol FileDescriptorTables::FindNestedSymbol( } inline Symbol FileDescriptorTables::FindNestedSymbolOfType( - const void* parent, const string& name, const Symbol::Type type) const { + const void* parent, StringPiece name, const Symbol::Type type) const { Symbol result = FindNestedSymbol(parent, name); if (result.type != type) return kNullSymbol; return result; } -Symbol DescriptorPool::Tables::FindByNameHelper( - const DescriptorPool* pool, const string& name) { +Symbol DescriptorPool::Tables::FindByNameHelper(const DescriptorPool* pool, + StringPiece name) { + if (pool->mutex_ != nullptr) { + // Fast path: the Symbol is already cached. This is just a hash lookup. + ReaderMutexLock lock(pool->mutex_); + if (known_bad_symbols_.empty() && known_bad_files_.empty()) { + Symbol result = FindSymbol(name); + if (!result.IsNull()) return result; + } + } MutexLockMaybe lock(pool->mutex_); - known_bad_symbols_.clear(); - known_bad_files_.clear(); + if (pool->fallback_database_ != nullptr) { + known_bad_symbols_.clear(); + known_bad_files_.clear(); + } Symbol result = FindSymbol(name); - if (result.IsNull() && pool->underlay_ != NULL) { + if (result.IsNull() && pool->underlay_ != nullptr) { // Symbol not found; check the underlay. - result = - pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name); + result = pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name); } if (result.IsNull()) { @@ -951,8 +944,8 @@ Symbol DescriptorPool::Tables::FindByNameHelper( } inline const FileDescriptor* DescriptorPool::Tables::FindFile( - const string& key) const { - return FindPtrOrNull(files_by_name_, key.c_str()); + StringPiece key) const { + return FindPtrOrNull(files_by_name_, key); } inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber( @@ -960,21 +953,71 @@ inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber( return FindPtrOrNull(fields_by_number_, std::make_pair(parent, number)); } +const void* FileDescriptorTables::FindParentForFieldsByMap( + const FieldDescriptor* field) const { + if (field->is_extension()) { + if (field->extension_scope() == nullptr) { + return field->file(); + } else { + return field->extension_scope(); + } + } else { + return field->containing_type(); + } +} + +void FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic( + const FileDescriptorTables* tables) { + tables->FieldsByLowercaseNamesLazyInitInternal(); +} + +void FileDescriptorTables::FieldsByLowercaseNamesLazyInitInternal() const { + for (FieldsByNumberMap::const_iterator it = fields_by_number_.begin(); + it != fields_by_number_.end(); it++) { + PointerStringPair lowercase_key(FindParentForFieldsByMap(it->second), + it->second->lowercase_name().c_str()); + InsertIfNotPresent(&fields_by_lowercase_name_, lowercase_key, + it->second); + } +} + inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName( - const void* parent, const string& lowercase_name) const { + const void* parent, StringPiece lowercase_name) const { + internal::call_once( + fields_by_lowercase_name_once_, + &FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic, this); return FindPtrOrNull(fields_by_lowercase_name_, - PointerStringPair(parent, lowercase_name.c_str())); + PointerStringPair(parent, lowercase_name)); +} + +void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic( + const FileDescriptorTables* tables) { + tables->FieldsByCamelcaseNamesLazyInitInternal(); +} + +void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitInternal() const { + for (FieldsByNumberMap::const_iterator it = fields_by_number_.begin(); + it != fields_by_number_.end(); it++) { + PointerStringPair camelcase_key(FindParentForFieldsByMap(it->second), + it->second->camelcase_name().c_str()); + InsertIfNotPresent(&fields_by_camelcase_name_, camelcase_key, + it->second); + } } inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName( - const void* parent, const string& camelcase_name) const { + const void* parent, StringPiece camelcase_name) const { + internal::call_once( + fields_by_camelcase_name_once_, + FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic, this); return FindPtrOrNull(fields_by_camelcase_name_, - PointerStringPair(parent, camelcase_name.c_str())); + PointerStringPair(parent, camelcase_name)); } inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber( const EnumDescriptor* parent, int number) const { - return FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number)); + return FindPtrOrNull(enum_values_by_number_, + std::make_pair(parent, number)); } inline const EnumValueDescriptor* @@ -982,9 +1025,9 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( const EnumDescriptor* parent, int number) const { // First try, with map of compiled-in values. { - const EnumValueDescriptor* desc = - FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number)); - if (desc != NULL) { + const EnumValueDescriptor* desc = FindPtrOrNull( + enum_values_by_number_, std::make_pair(parent, number)); + if (desc != nullptr) { return desc; } } @@ -993,7 +1036,7 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( ReaderMutexLock l(&unknown_enum_values_mu_); const EnumValueDescriptor* desc = FindPtrOrNull( unknown_enum_values_by_number_, std::make_pair(parent, number)); - if (desc != NULL) { + if (desc != nullptr) { return desc; } } @@ -1003,7 +1046,7 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( WriterMutexLock l(&unknown_enum_values_mu_); const EnumValueDescriptor* desc = FindPtrOrNull( unknown_enum_values_by_number_, std::make_pair(parent, number)); - if (desc != NULL) { + if (desc != nullptr) { return desc; } @@ -1011,27 +1054,25 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( // EnumDescriptor (it's not a part of the enum as originally defined), but // we do insert it into the table so that we can return the same pointer // later. - string enum_value_name = StringPrintf( - "UNKNOWN_ENUM_VALUE_%s_%d", parent->name().c_str(), number); - DescriptorPool::Tables* tables = - const_cast(DescriptorPool::generated_pool()-> - tables_.get()); + std::string enum_value_name = StringPrintf("UNKNOWN_ENUM_VALUE_%s_%d", + parent->name().c_str(), number); + DescriptorPool::Tables* tables = const_cast( + DescriptorPool::generated_pool()->tables_.get()); EnumValueDescriptor* result = tables->Allocate(); result->name_ = tables->AllocateString(enum_value_name); - result->full_name_ = tables->AllocateString(parent->full_name() + - "." + enum_value_name); + result->full_name_ = + tables->AllocateString(parent->full_name() + "." + enum_value_name); result->number_ = number; result->type_ = parent; result->options_ = &EnumValueOptions::default_instance(); InsertIfNotPresent(&unknown_enum_values_by_number_, - std::make_pair(parent, number), result); + std::make_pair(parent, number), result); return result; } } - inline const FieldDescriptor* DescriptorPool::Tables::FindExtension( - const Descriptor* extendee, int number) { + const Descriptor* extendee, int number) const { return FindPtrOrNull(extensions_, std::make_pair(extendee, number)); } @@ -1047,9 +1088,9 @@ inline void DescriptorPool::Tables::FindAllExtensions( // ------------------------------------------------------------------- -bool DescriptorPool::Tables::AddSymbol( - const string& full_name, Symbol symbol) { - if (InsertIfNotPresent(&symbols_by_name_, full_name.c_str(), symbol)) { +bool DescriptorPool::Tables::AddSymbol(const std::string& full_name, + Symbol symbol) { + if (InsertIfNotPresent(&symbols_by_name_, full_name, symbol)) { symbols_after_checkpoint_.push_back(full_name.c_str()); return true; } else { @@ -1057,14 +1098,15 @@ bool DescriptorPool::Tables::AddSymbol( } } -bool FileDescriptorTables::AddAliasUnderParent( - const void* parent, const string& name, Symbol symbol) { +bool FileDescriptorTables::AddAliasUnderParent(const void* parent, + const std::string& name, + Symbol symbol) { PointerStringPair by_parent_key(parent, name.c_str()); return InsertIfNotPresent(&symbols_by_parent_, by_parent_key, symbol); } bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) { - if (InsertIfNotPresent(&files_by_name_, file->name().c_str(), file)) { + if (InsertIfNotPresent(&files_by_name_, file->name(), file)) { files_after_checkpoint_.push_back(file->name().c_str()); return true; } else { @@ -1072,24 +1114,38 @@ bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) { } } +void FileDescriptorTables::FinalizeTables() { + // Clean up the temporary maps used by AddFieldByStylizedNames(). + fields_by_lowercase_name_tmp_ = nullptr; + fields_by_camelcase_name_tmp_ = nullptr; +} + void FileDescriptorTables::AddFieldByStylizedNames( const FieldDescriptor* field) { - const void* parent; - if (field->is_extension()) { - if (field->extension_scope() == NULL) { - parent = field->file(); - } else { - parent = field->extension_scope(); - } - } else { - parent = field->containing_type(); - } + const void* parent = FindParentForFieldsByMap(field); + + // We want fields_by_{lower,camel}case_name_ to be lazily built, but + // cross-link order determines which entry will be present in the case of a + // conflict. So we use the temporary maps that get destroyed after + // BuildFileImpl() to detect the conflicts, and only store the conflicts in + // the map that will persist. We will then lazily populate the rest of the + // entries from fields_by_number_. PointerStringPair lowercase_key(parent, field->lowercase_name().c_str()); - InsertIfNotPresent(&fields_by_lowercase_name_, lowercase_key, field); + if (!InsertIfNotPresent(fields_by_lowercase_name_tmp_.get(), + lowercase_key, field)) { + InsertIfNotPresent( + &fields_by_lowercase_name_, lowercase_key, + FindPtrOrNull(*fields_by_lowercase_name_tmp_, lowercase_key)); + } PointerStringPair camelcase_key(parent, field->camelcase_name().c_str()); - InsertIfNotPresent(&fields_by_camelcase_name_, camelcase_key, field); + if (!InsertIfNotPresent(fields_by_camelcase_name_tmp_.get(), + camelcase_key, field)) { + InsertIfNotPresent( + &fields_by_camelcase_name_, camelcase_key, + FindPtrOrNull(*fields_by_camelcase_name_tmp_, camelcase_key)); + } } bool FileDescriptorTables::AddFieldByNumber(const FieldDescriptor* field) { @@ -1115,38 +1171,44 @@ bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) { // ------------------------------------------------------------------- -template +template Type* DescriptorPool::Tables::Allocate() { return reinterpret_cast(AllocateBytes(sizeof(Type))); } -template +template Type* DescriptorPool::Tables::AllocateArray(int count) { return reinterpret_cast(AllocateBytes(sizeof(Type) * count)); } -string* DescriptorPool::Tables::AllocateString(const string& value) { - string* result = new string(value); - strings_.push_back(result); +std::string* DescriptorPool::Tables::AllocateString(StringPiece value) { + std::string* result = new std::string(value); + strings_.emplace_back(result); return result; } -GoogleOnceDynamic* DescriptorPool::Tables::AllocateOnceDynamic() { - GoogleOnceDynamic* result = new GoogleOnceDynamic(); - once_dynamics_.push_back(result); +std::string* DescriptorPool::Tables::AllocateEmptyString() { + std::string* result = new std::string(); + strings_.emplace_back(result); return result; } -template +internal::once_flag* DescriptorPool::Tables::AllocateOnceDynamic() { + internal::once_flag* result = new internal::once_flag(); + once_dynamics_.emplace_back(result); + return result; +} + +template Type* DescriptorPool::Tables::AllocateMessage(Type* /* dummy */) { Type* result = new Type; - messages_.push_back(result); + messages_.emplace_back(result); return result; } FileDescriptorTables* DescriptorPool::Tables::AllocateFileTables() { FileDescriptorTables* result = new FileDescriptorTables; - file_tables_.push_back(result); + file_tables_.emplace_back(result); return result; } @@ -1155,11 +1217,10 @@ void* DescriptorPool::Tables::AllocateBytes(int size) { // sophisticated way? Probably not for the open source release, but for // internal use we could easily plug in one of our existing memory pool // allocators... - if (size == 0) return NULL; + if (size == 0) return nullptr; - void* result = operator new(size); - allocations_.push_back(result); - return result; + allocations_.emplace_back(size); + return allocations_.back().data(); } void FileDescriptorTables::BuildLocationsByPath( @@ -1174,7 +1235,8 @@ const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation( const std::vector& path, const SourceCodeInfo* info) const { std::pair p( std::make_pair(this, info)); - locations_by_path_once_.Init(&FileDescriptorTables::BuildLocationsByPath, &p); + internal::call_once(locations_by_path_once_, + FileDescriptorTables::BuildLocationsByPath, &p); return FindPtrOrNull(locations_by_path_, Join(path, ",")); } @@ -1184,45 +1246,44 @@ const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation( DescriptorPool::ErrorCollector::~ErrorCollector() {} DescriptorPool::DescriptorPool() - : mutex_(NULL), - fallback_database_(NULL), - default_error_collector_(NULL), - underlay_(NULL), - tables_(new Tables), - enforce_dependencies_(true), - lazily_build_dependencies_(false), - allow_unknown_(false), - enforce_weak_(false), - disallow_enforce_utf8_(false) {} + : mutex_(nullptr), + fallback_database_(nullptr), + default_error_collector_(nullptr), + underlay_(nullptr), + tables_(new Tables), + enforce_dependencies_(true), + lazily_build_dependencies_(false), + allow_unknown_(false), + enforce_weak_(false), + disallow_enforce_utf8_(false) {} DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database, ErrorCollector* error_collector) - : mutex_(new Mutex), - fallback_database_(fallback_database), - default_error_collector_(error_collector), - underlay_(NULL), - tables_(new Tables), - enforce_dependencies_(true), - lazily_build_dependencies_(false), - allow_unknown_(false), - enforce_weak_(false), - disallow_enforce_utf8_(false) { -} + : mutex_(new internal::WrappedMutex), + fallback_database_(fallback_database), + default_error_collector_(error_collector), + underlay_(nullptr), + tables_(new Tables), + enforce_dependencies_(true), + lazily_build_dependencies_(false), + allow_unknown_(false), + enforce_weak_(false), + disallow_enforce_utf8_(false) {} DescriptorPool::DescriptorPool(const DescriptorPool* underlay) - : mutex_(NULL), - fallback_database_(NULL), - default_error_collector_(NULL), - underlay_(underlay), - tables_(new Tables), - enforce_dependencies_(true), - lazily_build_dependencies_(false), - allow_unknown_(false), - enforce_weak_(false), - disallow_enforce_utf8_(false) {} + : mutex_(nullptr), + fallback_database_(nullptr), + default_error_collector_(nullptr), + underlay_(underlay), + tables_(new Tables), + enforce_dependencies_(true), + lazily_build_dependencies_(false), + allow_unknown_(false), + enforce_weak_(false), + disallow_enforce_utf8_(false) {} DescriptorPool::~DescriptorPool() { - if (mutex_ != NULL) delete mutex_; + if (mutex_ != nullptr) delete mutex_; } // DescriptorPool::BuildFile() defined later. @@ -1232,17 +1293,18 @@ void DescriptorPool::InternalDontEnforceDependencies() { enforce_dependencies_ = false; } -void DescriptorPool::AddUnusedImportTrackFile(const string& file_name) { - unused_import_track_files_.insert(file_name); +void DescriptorPool::AddUnusedImportTrackFile(ConstStringParam file_name, + bool is_error) { + unused_import_track_files_[std::string(file_name)] = is_error; } void DescriptorPool::ClearUnusedImportTrackFiles() { unused_import_track_files_.clear(); } -bool DescriptorPool::InternalIsFileLoaded(const string& filename) const { +bool DescriptorPool::InternalIsFileLoaded(ConstStringParam filename) const { MutexLockMaybe lock(mutex_); - return tables_->FindFile(filename) != NULL; + return tables_->FindFile(filename) != nullptr; } // generated_pool ==================================================== @@ -1250,43 +1312,38 @@ bool DescriptorPool::InternalIsFileLoaded(const string& filename) const { namespace { -EncodedDescriptorDatabase* generated_database_ = NULL; -DescriptorPool* generated_pool_ = NULL; -GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_); +EncodedDescriptorDatabase* GeneratedDatabase() { + static auto generated_database = + internal::OnShutdownDelete(new EncodedDescriptorDatabase()); + return generated_database; +} -void DeleteGeneratedPool() { - delete generated_database_; - generated_database_ = NULL; - delete generated_pool_; - generated_pool_ = NULL; +DescriptorPool* NewGeneratedPool() { + auto generated_pool = new DescriptorPool(GeneratedDatabase()); + generated_pool->InternalSetLazilyBuildDependencies(); + return generated_pool; } -static void InitGeneratedPool() { - generated_database_ = new EncodedDescriptorDatabase; - generated_pool_ = new DescriptorPool(generated_database_); - generated_pool_->InternalSetLazilyBuildDependencies(); +} // anonymous namespace - internal::OnShutdown(&DeleteGeneratedPool); +DescriptorDatabase* DescriptorPool::internal_generated_database() { + return GeneratedDatabase(); } -inline void InitGeneratedPoolOnce() { - ::google::protobuf::GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool); +DescriptorPool* DescriptorPool::internal_generated_pool() { + static DescriptorPool* generated_pool = + internal::OnShutdownDelete(NewGeneratedPool()); + return generated_pool; } -} // anonymous namespace - const DescriptorPool* DescriptorPool::generated_pool() { - InitGeneratedPoolOnce(); - return generated_pool_; + const DescriptorPool* pool = internal_generated_pool(); + // Ensure that descriptor.proto has been registered in the generated pool. + DescriptorProto::descriptor(); + return pool; } - -DescriptorPool* DescriptorPool::internal_generated_pool() { - InitGeneratedPoolOnce(); - return generated_pool_; -} - void DescriptorPool::InternalAddGeneratedFile( const void* encoded_file_descriptor, int size) { // So, this function is called in the process of initializing the @@ -1311,8 +1368,7 @@ void DescriptorPool::InternalAddGeneratedFile( // Therefore, when we parse one, we have to be very careful to avoid using // any descriptor-based operations, since this might cause infinite recursion // or deadlock. - InitGeneratedPoolOnce(); - GOOGLE_CHECK(generated_database_->Add(encoded_file_descriptor, size)); + GOOGLE_CHECK(GeneratedDatabase()->Add(encoded_file_descriptor, size)); } @@ -1322,140 +1378,201 @@ void DescriptorPool::InternalAddGeneratedFile( // there's any good way to factor it out. Think about this some time when // there's nothing more important to do (read: never). -const FileDescriptor* DescriptorPool::FindFileByName(const string& name) const { +const FileDescriptor* DescriptorPool::FindFileByName( + ConstStringParam name) const { MutexLockMaybe lock(mutex_); - tables_->known_bad_symbols_.clear(); - tables_->known_bad_files_.clear(); + if (fallback_database_ != nullptr) { + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); + } const FileDescriptor* result = tables_->FindFile(name); - if (result != NULL) return result; - if (underlay_ != NULL) { + if (result != nullptr) return result; + if (underlay_ != nullptr) { result = underlay_->FindFileByName(name); - if (result != NULL) return result; + if (result != nullptr) return result; } if (TryFindFileInFallbackDatabase(name)) { result = tables_->FindFile(name); - if (result != NULL) return result; + if (result != nullptr) return result; } - return NULL; + return nullptr; } const FileDescriptor* DescriptorPool::FindFileContainingSymbol( - const string& symbol_name) const { + ConstStringParam symbol_name) const { MutexLockMaybe lock(mutex_); - tables_->known_bad_symbols_.clear(); - tables_->known_bad_files_.clear(); + if (fallback_database_ != nullptr) { + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); + } Symbol result = tables_->FindSymbol(symbol_name); if (!result.IsNull()) return result.GetFile(); - if (underlay_ != NULL) { + if (underlay_ != nullptr) { const FileDescriptor* file_result = - underlay_->FindFileContainingSymbol(symbol_name); - if (file_result != NULL) return file_result; + underlay_->FindFileContainingSymbol(symbol_name); + if (file_result != nullptr) return file_result; } if (TryFindSymbolInFallbackDatabase(symbol_name)) { result = tables_->FindSymbol(symbol_name); if (!result.IsNull()) return result.GetFile(); } - return NULL; + return nullptr; } const Descriptor* DescriptorPool::FindMessageTypeByName( - const string& name) const { + ConstStringParam name) const { Symbol result = tables_->FindByNameHelper(this, name); - return (result.type == Symbol::MESSAGE) ? result.descriptor : NULL; + return (result.type == Symbol::MESSAGE) ? result.descriptor : nullptr; } const FieldDescriptor* DescriptorPool::FindFieldByName( - const string& name) const { + ConstStringParam name) const { Symbol result = tables_->FindByNameHelper(this, name); if (result.type == Symbol::FIELD && !result.field_descriptor->is_extension()) { return result.field_descriptor; } else { - return NULL; + return nullptr; } } const FieldDescriptor* DescriptorPool::FindExtensionByName( - const string& name) const { + ConstStringParam name) const { Symbol result = tables_->FindByNameHelper(this, name); - if (result.type == Symbol::FIELD && - result.field_descriptor->is_extension()) { + if (result.type == Symbol::FIELD && result.field_descriptor->is_extension()) { return result.field_descriptor; } else { - return NULL; + return nullptr; } } const OneofDescriptor* DescriptorPool::FindOneofByName( - const string& name) const { + ConstStringParam name) const { Symbol result = tables_->FindByNameHelper(this, name); - return (result.type == Symbol::ONEOF) ? result.oneof_descriptor : NULL; + return (result.type == Symbol::ONEOF) ? result.oneof_descriptor : nullptr; } const EnumDescriptor* DescriptorPool::FindEnumTypeByName( - const string& name) const { + ConstStringParam name) const { Symbol result = tables_->FindByNameHelper(this, name); - return (result.type == Symbol::ENUM) ? result.enum_descriptor : NULL; + return (result.type == Symbol::ENUM) ? result.enum_descriptor : nullptr; } const EnumValueDescriptor* DescriptorPool::FindEnumValueByName( - const string& name) const { + ConstStringParam name) const { Symbol result = tables_->FindByNameHelper(this, name); - return (result.type == Symbol::ENUM_VALUE) ? - result.enum_value_descriptor : NULL; + return (result.type == Symbol::ENUM_VALUE) ? result.enum_value_descriptor + : nullptr; } const ServiceDescriptor* DescriptorPool::FindServiceByName( - const string& name) const { + ConstStringParam name) const { Symbol result = tables_->FindByNameHelper(this, name); - return (result.type == Symbol::SERVICE) ? result.service_descriptor : NULL; + return (result.type == Symbol::SERVICE) ? result.service_descriptor : nullptr; } const MethodDescriptor* DescriptorPool::FindMethodByName( - const string& name) const { + ConstStringParam name) const { Symbol result = tables_->FindByNameHelper(this, name); - return (result.type == Symbol::METHOD) ? result.method_descriptor : NULL; + return (result.type == Symbol::METHOD) ? result.method_descriptor : nullptr; } const FieldDescriptor* DescriptorPool::FindExtensionByNumber( const Descriptor* extendee, int number) const { + if (extendee->extension_range_count() == 0) return nullptr; + // A faster path to reduce lock contention in finding extensions, assuming + // most extensions will be cache hit. + if (mutex_ != nullptr) { + ReaderMutexLock lock(mutex_); + const FieldDescriptor* result = tables_->FindExtension(extendee, number); + if (result != nullptr) { + return result; + } + } MutexLockMaybe lock(mutex_); - tables_->known_bad_symbols_.clear(); - tables_->known_bad_files_.clear(); + if (fallback_database_ != nullptr) { + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); + } const FieldDescriptor* result = tables_->FindExtension(extendee, number); - if (result != NULL) { + if (result != nullptr) { return result; } - if (underlay_ != NULL) { + if (underlay_ != nullptr) { result = underlay_->FindExtensionByNumber(extendee, number); - if (result != NULL) return result; + if (result != nullptr) return result; } if (TryFindExtensionInFallbackDatabase(extendee, number)) { result = tables_->FindExtension(extendee, number); - if (result != NULL) { + if (result != nullptr) { return result; } } - return NULL; + return nullptr; +} + +const FieldDescriptor* DescriptorPool::InternalFindExtensionByNumberNoLock( + const Descriptor* extendee, int number) const { + if (extendee->extension_range_count() == 0) return nullptr; + + const FieldDescriptor* result = tables_->FindExtension(extendee, number); + if (result != nullptr) { + return result; + } + + if (underlay_ != nullptr) { + result = underlay_->InternalFindExtensionByNumberNoLock(extendee, number); + if (result != nullptr) return result; + } + + return nullptr; +} + +const FieldDescriptor* DescriptorPool::FindExtensionByPrintableName( + const Descriptor* extendee, ConstStringParam printable_name) const { + if (extendee->extension_range_count() == 0) return nullptr; + const FieldDescriptor* result = FindExtensionByName(printable_name); + if (result != nullptr && result->containing_type() == extendee) { + return result; + } + if (extendee->options().message_set_wire_format()) { + // MessageSet extensions may be identified by type name. + const Descriptor* type = FindMessageTypeByName(printable_name); + if (type != nullptr) { + // Look for a matching extension in the foreign type's scope. + const int type_extension_count = type->extension_count(); + for (int i = 0; i < type_extension_count; i++) { + const FieldDescriptor* extension = type->extension(i); + if (extension->containing_type() == extendee && + extension->type() == FieldDescriptor::TYPE_MESSAGE && + extension->is_optional() && extension->message_type() == type) { + // Found it. + return extension; + } + } + } + } + return nullptr; } void DescriptorPool::FindAllExtensions( const Descriptor* extendee, std::vector* out) const { MutexLockMaybe lock(mutex_); - tables_->known_bad_symbols_.clear(); - tables_->known_bad_files_.clear(); + if (fallback_database_ != nullptr) { + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); + } // Initialize tables_->extensions_ from the fallback database first // (but do this only once per descriptor). - if (fallback_database_ != NULL && + if (fallback_database_ != nullptr && tables_->extensions_loaded_from_db_.count(extendee) == 0) { std::vector numbers; if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(), &numbers)) { - for (int i = 0; i < numbers.size(); ++i) { - int number = numbers[i]; - if (tables_->FindExtension(extendee, number) == NULL) { + for (int number : numbers) { + if (tables_->FindExtension(extendee, number) == nullptr) { TryFindExtensionInFallbackDatabase(extendee, number); } } @@ -1464,7 +1581,7 @@ void DescriptorPool::FindAllExtensions( } tables_->FindAllExtensions(extendee, out); - if (underlay_ != NULL) { + if (underlay_ != nullptr) { underlay_->FindAllExtensions(extendee, out); } } @@ -1472,276 +1589,304 @@ void DescriptorPool::FindAllExtensions( // ------------------------------------------------------------------- -const FieldDescriptor* -Descriptor::FindFieldByNumber(int key) const { - const FieldDescriptor* result = - file()->tables_->FindFieldByNumber(this, key); - if (result == NULL || result->is_extension()) { - return NULL; +const FieldDescriptor* Descriptor::FindFieldByNumber(int key) const { + const FieldDescriptor* result = file()->tables_->FindFieldByNumber(this, key); + if (result == nullptr || result->is_extension()) { + return nullptr; } else { return result; } } -const FieldDescriptor* -Descriptor::FindFieldByLowercaseName(const string& key) const { +const FieldDescriptor* Descriptor::FindFieldByLowercaseName( + ConstStringParam key) const { const FieldDescriptor* result = - file()->tables_->FindFieldByLowercaseName(this, key); - if (result == NULL || result->is_extension()) { - return NULL; + file()->tables_->FindFieldByLowercaseName(this, key); + if (result == nullptr || result->is_extension()) { + return nullptr; } else { return result; } } -const FieldDescriptor* -Descriptor::FindFieldByCamelcaseName(const string& key) const { +const FieldDescriptor* Descriptor::FindFieldByCamelcaseName( + ConstStringParam key) const { const FieldDescriptor* result = - file()->tables_->FindFieldByCamelcaseName(this, key); - if (result == NULL || result->is_extension()) { - return NULL; + file()->tables_->FindFieldByCamelcaseName(this, key); + if (result == nullptr || result->is_extension()) { + return nullptr; } else { return result; } } -const FieldDescriptor* -Descriptor::FindFieldByName(const string& key) const { +const FieldDescriptor* Descriptor::FindFieldByName(ConstStringParam key) const { Symbol result = - file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD); + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD); if (!result.IsNull() && !result.field_descriptor->is_extension()) { return result.field_descriptor; } else { - return NULL; + return nullptr; } } -const OneofDescriptor* -Descriptor::FindOneofByName(const string& key) const { +const OneofDescriptor* Descriptor::FindOneofByName(ConstStringParam key) const { Symbol result = - file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ONEOF); + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ONEOF); if (!result.IsNull()) { return result.oneof_descriptor; } else { - return NULL; + return nullptr; } } -const FieldDescriptor* -Descriptor::FindExtensionByName(const string& key) const { +const FieldDescriptor* Descriptor::FindExtensionByName( + ConstStringParam key) const { Symbol result = - file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD); + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD); if (!result.IsNull() && result.field_descriptor->is_extension()) { return result.field_descriptor; } else { - return NULL; + return nullptr; } } -const FieldDescriptor* -Descriptor::FindExtensionByLowercaseName(const string& key) const { +const FieldDescriptor* Descriptor::FindExtensionByLowercaseName( + ConstStringParam key) const { const FieldDescriptor* result = - file()->tables_->FindFieldByLowercaseName(this, key); - if (result == NULL || !result->is_extension()) { - return NULL; + file()->tables_->FindFieldByLowercaseName(this, key); + if (result == nullptr || !result->is_extension()) { + return nullptr; } else { return result; } } -const FieldDescriptor* -Descriptor::FindExtensionByCamelcaseName(const string& key) const { +const FieldDescriptor* Descriptor::FindExtensionByCamelcaseName( + ConstStringParam key) const { const FieldDescriptor* result = - file()->tables_->FindFieldByCamelcaseName(this, key); - if (result == NULL || !result->is_extension()) { - return NULL; + file()->tables_->FindFieldByCamelcaseName(this, key); + if (result == nullptr || !result->is_extension()) { + return nullptr; } else { return result; } } -const Descriptor* -Descriptor::FindNestedTypeByName(const string& key) const { +const Descriptor* Descriptor::FindNestedTypeByName(ConstStringParam key) const { Symbol result = - file()->tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE); + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE); if (!result.IsNull()) { return result.descriptor; } else { - return NULL; + return nullptr; } } -const EnumDescriptor* -Descriptor::FindEnumTypeByName(const string& key) const { +const EnumDescriptor* Descriptor::FindEnumTypeByName( + ConstStringParam key) const { Symbol result = - file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM); + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM); if (!result.IsNull()) { return result.enum_descriptor; } else { - return NULL; + return nullptr; } } -const EnumValueDescriptor* -Descriptor::FindEnumValueByName(const string& key) const { +const EnumValueDescriptor* Descriptor::FindEnumValueByName( + ConstStringParam key) const { Symbol result = - file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE); + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE); if (!result.IsNull()) { return result.enum_value_descriptor; } else { - return NULL; + return nullptr; } } -const EnumValueDescriptor* -EnumDescriptor::FindValueByName(const string& key) const { +const FieldDescriptor* Descriptor::map_key() const { + if (!options().map_entry()) return nullptr; + GOOGLE_DCHECK_EQ(field_count(), 2); + return field(0); +} + +const FieldDescriptor* Descriptor::map_value() const { + if (!options().map_entry()) return nullptr; + GOOGLE_DCHECK_EQ(field_count(), 2); + return field(1); +} + +const EnumValueDescriptor* EnumDescriptor::FindValueByName( + ConstStringParam key) const { Symbol result = - file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE); + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE); if (!result.IsNull()) { return result.enum_value_descriptor; } else { - return NULL; + return nullptr; } } -const EnumValueDescriptor* -EnumDescriptor::FindValueByNumber(int key) const { +const EnumValueDescriptor* EnumDescriptor::FindValueByNumber(int key) const { return file()->tables_->FindEnumValueByNumber(this, key); } -const EnumValueDescriptor* -EnumDescriptor::FindValueByNumberCreatingIfUnknown(int key) const { +const EnumValueDescriptor* EnumDescriptor::FindValueByNumberCreatingIfUnknown( + int key) const { return file()->tables_->FindEnumValueByNumberCreatingIfUnknown(this, key); } -const MethodDescriptor* -ServiceDescriptor::FindMethodByName(const string& key) const { +const MethodDescriptor* ServiceDescriptor::FindMethodByName( + ConstStringParam key) const { Symbol result = - file()->tables_->FindNestedSymbolOfType(this, key, Symbol::METHOD); + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::METHOD); if (!result.IsNull()) { return result.method_descriptor; } else { - return NULL; + return nullptr; } } -const Descriptor* -FileDescriptor::FindMessageTypeByName(const string& key) const { +const Descriptor* FileDescriptor::FindMessageTypeByName( + ConstStringParam key) const { Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE); if (!result.IsNull()) { return result.descriptor; } else { - return NULL; + return nullptr; } } -const EnumDescriptor* -FileDescriptor::FindEnumTypeByName(const string& key) const { +const EnumDescriptor* FileDescriptor::FindEnumTypeByName( + ConstStringParam key) const { Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM); if (!result.IsNull()) { return result.enum_descriptor; } else { - return NULL; + return nullptr; } } -const EnumValueDescriptor* -FileDescriptor::FindEnumValueByName(const string& key) const { +const EnumValueDescriptor* FileDescriptor::FindEnumValueByName( + ConstStringParam key) const { Symbol result = - tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE); + tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE); if (!result.IsNull()) { return result.enum_value_descriptor; } else { - return NULL; + return nullptr; } } -const ServiceDescriptor* -FileDescriptor::FindServiceByName(const string& key) const { +const ServiceDescriptor* FileDescriptor::FindServiceByName( + ConstStringParam key) const { Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::SERVICE); if (!result.IsNull()) { return result.service_descriptor; } else { - return NULL; + return nullptr; } } -const FieldDescriptor* -FileDescriptor::FindExtensionByName(const string& key) const { +const FieldDescriptor* FileDescriptor::FindExtensionByName( + ConstStringParam key) const { Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD); if (!result.IsNull() && result.field_descriptor->is_extension()) { return result.field_descriptor; } else { - return NULL; + return nullptr; } } -const FieldDescriptor* -FileDescriptor::FindExtensionByLowercaseName(const string& key) const { +const FieldDescriptor* FileDescriptor::FindExtensionByLowercaseName( + ConstStringParam key) const { const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key); - if (result == NULL || !result->is_extension()) { - return NULL; + if (result == nullptr || !result->is_extension()) { + return nullptr; } else { return result; } } -const FieldDescriptor* -FileDescriptor::FindExtensionByCamelcaseName(const string& key) const { +const FieldDescriptor* FileDescriptor::FindExtensionByCamelcaseName( + ConstStringParam key) const { const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key); - if (result == NULL || !result->is_extension()) { - return NULL; + if (result == nullptr || !result->is_extension()) { + return nullptr; } else { return result; } } +void Descriptor::ExtensionRange::CopyTo( + DescriptorProto_ExtensionRange* proto) const { + proto->set_start(this->start); + proto->set_end(this->end); + if (options_ != &ExtensionRangeOptions::default_instance()) { + *proto->mutable_options() = *options_; + } +} + const Descriptor::ExtensionRange* Descriptor::FindExtensionRangeContainingNumber(int number) const { // Linear search should be fine because we don't expect a message to have // more than a couple extension ranges. for (int i = 0; i < extension_range_count(); i++) { if (number >= extension_range(i)->start && - number < extension_range(i)->end) { + number < extension_range(i)->end) { return extension_range(i); } } - return NULL; + return nullptr; +} + +const Descriptor::ReservedRange* Descriptor::FindReservedRangeContainingNumber( + int number) const { + // TODO(chrisn): Consider a non-linear search. + for (int i = 0; i < reserved_range_count(); i++) { + if (number >= reserved_range(i)->start && number < reserved_range(i)->end) { + return reserved_range(i); + } + } + return nullptr; } -const Descriptor::ReservedRange* -Descriptor::FindReservedRangeContainingNumber(int number) const { +const EnumDescriptor::ReservedRange* +EnumDescriptor::FindReservedRangeContainingNumber(int number) const { // TODO(chrisn): Consider a non-linear search. for (int i = 0; i < reserved_range_count(); i++) { if (number >= reserved_range(i)->start && - number < reserved_range(i)->end) { + number <= reserved_range(i)->end) { return reserved_range(i); } } - return NULL; + return nullptr; } // ------------------------------------------------------------------- -bool DescriptorPool::TryFindFileInFallbackDatabase(const string& name) const { - if (fallback_database_ == NULL) return false; +bool DescriptorPool::TryFindFileInFallbackDatabase( + StringPiece name) const { + if (fallback_database_ == nullptr) return false; - if (tables_->known_bad_files_.count(name) > 0) return false; + auto name_string = std::string(name); + if (tables_->known_bad_files_.count(name_string) > 0) return false; FileDescriptorProto file_proto; - if (!fallback_database_->FindFileByName(name, &file_proto) || - BuildFileFromDatabase(file_proto) == NULL) { - tables_->known_bad_files_.insert(name); + if (!fallback_database_->FindFileByName(name_string, &file_proto) || + BuildFileFromDatabase(file_proto) == nullptr) { + tables_->known_bad_files_.insert(std::move(name_string)); return false; } return true; } -bool DescriptorPool::IsSubSymbolOfBuiltType(const string& name) const { - string prefix = name; +bool DescriptorPool::IsSubSymbolOfBuiltType(StringPiece name) const { + auto prefix = std::string(name); for (;;) { - string::size_type dot_pos = prefix.find_last_of('.'); - if (dot_pos == string::npos) { + std::string::size_type dot_pos = prefix.find_last_of('.'); + if (dot_pos == std::string::npos) { break; } prefix = prefix.substr(0, dot_pos); @@ -1752,48 +1897,50 @@ bool DescriptorPool::IsSubSymbolOfBuiltType(const string& name) const { return true; } } - if (underlay_ != NULL) { + if (underlay_ != nullptr) { // Check to see if any prefix of this symbol exists in the underlay. return underlay_->IsSubSymbolOfBuiltType(name); } return false; } -bool DescriptorPool::TryFindSymbolInFallbackDatabase(const string& name) const { - if (fallback_database_ == NULL) return false; +bool DescriptorPool::TryFindSymbolInFallbackDatabase( + StringPiece name) const { + if (fallback_database_ == nullptr) return false; - if (tables_->known_bad_symbols_.count(name) > 0) return false; + auto name_string = std::string(name); + if (tables_->known_bad_symbols_.count(name_string) > 0) return false; FileDescriptorProto file_proto; - if (// We skip looking in the fallback database if the name is a sub-symbol - // of any descriptor that already exists in the descriptor pool (except - // for package descriptors). This is valid because all symbols except - // for packages are defined in a single file, so if the symbol exists - // then we should already have its definition. - // - // The other reason to do this is to support "overriding" type - // definitions by merging two databases that define the same type. (Yes, - // people do this.) The main difficulty with making this work is that - // FindFileContainingSymbol() is allowed to return both false positives - // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and false - // negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase). - // When two such databases are merged, looking up a non-existent - // sub-symbol of a type that already exists in the descriptor pool can - // result in an attempt to load multiple definitions of the same type. - // The check below avoids this. + if ( // We skip looking in the fallback database if the name is a sub-symbol + // of any descriptor that already exists in the descriptor pool (except + // for package descriptors). This is valid because all symbols except + // for packages are defined in a single file, so if the symbol exists + // then we should already have its definition. + // + // The other reason to do this is to support "overriding" type + // definitions by merging two databases that define the same type. (Yes, + // people do this.) The main difficulty with making this work is that + // FindFileContainingSymbol() is allowed to return both false positives + // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and + // false negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase). + // When two such databases are merged, looking up a non-existent + // sub-symbol of a type that already exists in the descriptor pool can + // result in an attempt to load multiple definitions of the same type. + // The check below avoids this. IsSubSymbolOfBuiltType(name) // Look up file containing this symbol in fallback database. - || !fallback_database_->FindFileContainingSymbol(name, &file_proto) + || !fallback_database_->FindFileContainingSymbol(name_string, &file_proto) // Check if we've already built this file. If so, it apparently doesn't // contain the symbol we're looking for. Some DescriptorDatabases // return false positives. - || tables_->FindFile(file_proto.name()) != NULL + || tables_->FindFile(file_proto.name()) != nullptr // Build the file. - || BuildFileFromDatabase(file_proto) == NULL) { - tables_->known_bad_symbols_.insert(name); + || BuildFileFromDatabase(file_proto) == nullptr) { + tables_->known_bad_symbols_.insert(std::move(name_string)); return false; } @@ -1802,22 +1949,22 @@ bool DescriptorPool::TryFindSymbolInFallbackDatabase(const string& name) const { bool DescriptorPool::TryFindExtensionInFallbackDatabase( const Descriptor* containing_type, int field_number) const { - if (fallback_database_ == NULL) return false; + if (fallback_database_ == nullptr) return false; FileDescriptorProto file_proto; if (!fallback_database_->FindFileContainingExtension( - containing_type->full_name(), field_number, &file_proto)) { + containing_type->full_name(), field_number, &file_proto)) { return false; } - if (tables_->FindFile(file_proto.name()) != NULL) { + if (tables_->FindFile(file_proto.name()) != nullptr) { // We've already loaded this file, and it apparently doesn't contain the // extension we're looking for. Some DescriptorDatabases return false // positives. return false; } - if (BuildFileFromDatabase(file_proto) == NULL) { + if (BuildFileFromDatabase(file_proto) == nullptr) { return false; } @@ -1826,24 +1973,25 @@ bool DescriptorPool::TryFindExtensionInFallbackDatabase( // =================================================================== -bool FieldDescriptor::is_map() const { - return type() == TYPE_MESSAGE && message_type()->options().map_entry(); +bool FieldDescriptor::is_map_message_type() const { + return message_type_->options().map_entry(); } -string FieldDescriptor::DefaultValueAsString(bool quote_string_type) const { +std::string FieldDescriptor::DefaultValueAsString( + bool quote_string_type) const { GOOGLE_CHECK(has_default_value()) << "No default value"; switch (cpp_type()) { case CPPTYPE_INT32: - return SimpleItoa(default_value_int32()); + return StrCat(default_value_int32()); break; case CPPTYPE_INT64: - return SimpleItoa(default_value_int64()); + return StrCat(default_value_int64()); break; case CPPTYPE_UINT32: - return SimpleItoa(default_value_uint32()); + return StrCat(default_value_uint32()); break; case CPPTYPE_UINT64: - return SimpleItoa(default_value_uint64()); + return StrCat(default_value_uint64()); break; case CPPTYPE_FLOAT: return SimpleFtoa(default_value_float()); @@ -1951,13 +2099,7 @@ void Descriptor::CopyTo(DescriptorProto* proto) const { enum_type(i)->CopyTo(proto->add_enum_type()); } for (int i = 0; i < extension_range_count(); i++) { - DescriptorProto::ExtensionRange* range = proto->add_extension_range(); - range->set_start(extension_range(i)->start); - range->set_end(extension_range(i)->end); - const ExtensionRangeOptions* options = extension_range(i)->options_; - if (options != &ExtensionRangeOptions::default_instance()) { - range->mutable_options()->CopyFrom(*options); - } + extension_range(i)->CopyTo(proto->add_extension_range()); } for (int i = 0; i < extension_count(); i++) { extension(i)->CopyTo(proto->add_extension()); @@ -2000,13 +2142,15 @@ void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const { if (has_json_name_) { proto->set_json_name(json_name()); } - + if (proto3_optional_) { + proto->set_proto3_optional(true); + } // Some compilers do not allow static_cast directly between two enum types, // so we must cast to int first. proto->set_label(static_cast( - implicit_cast(label()))); + implicit_cast(label()))); proto->set_type(static_cast( - implicit_cast(type()))); + implicit_cast(type()))); if (is_extension()) { if (!containing_type()->is_unqualified_placeholder_) { @@ -2037,7 +2181,7 @@ void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const { proto->set_default_value(DefaultValueAsString(false)); } - if (containing_oneof() != NULL && !is_extension()) { + if (containing_oneof() != nullptr && !is_extension()) { proto->set_oneof_index(containing_oneof()->index()); } @@ -2063,6 +2207,14 @@ void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const { for (int i = 0; i < value_count(); i++) { value(i)->CopyTo(proto->add_value()); } + for (int i = 0; i < reserved_range_count(); i++) { + EnumDescriptorProto::EnumReservedRange* range = proto->add_reserved_range(); + range->set_start(reserved_range(i)->start); + range->set_end(reserved_range(i)->end); + } + for (int i = 0; i < reserved_name_count(); i++) { + proto->add_reserved_name(reserved_name(i)); + } if (&options() != &EnumOptions::default_instance()) { proto->mutable_options()->CopyFrom(options()); @@ -2119,40 +2271,41 @@ void MethodDescriptor::CopyTo(MethodDescriptorProto* proto) const { namespace { -bool RetrieveOptionsAssumingRightPool(int depth, const Message& options, - std::vector* option_entries) { +bool RetrieveOptionsAssumingRightPool( + int depth, const Message& options, + std::vector* option_entries) { option_entries->clear(); const Reflection* reflection = options.GetReflection(); std::vector fields; reflection->ListFields(options, &fields); - for (int i = 0; i < fields.size(); i++) { + for (const FieldDescriptor* field : fields) { int count = 1; bool repeated = false; - if (fields[i]->is_repeated()) { - count = reflection->FieldSize(options, fields[i]); + if (field->is_repeated()) { + count = reflection->FieldSize(options, field); repeated = true; } for (int j = 0; j < count; j++) { - string fieldval; - if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - string tmp; + std::string fieldval; + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + std::string tmp; TextFormat::Printer printer; printer.SetInitialIndentLevel(depth + 1); - printer.PrintFieldValueToString(options, fields[i], - repeated ? j : -1, &tmp); + printer.PrintFieldValueToString(options, field, repeated ? j : -1, + &tmp); fieldval.append("{\n"); fieldval.append(tmp); fieldval.append(depth * 2, ' '); fieldval.append("}"); } else { - TextFormat::PrintFieldValueToString(options, fields[i], - repeated ? j : -1, &fieldval); + TextFormat::PrintFieldValueToString(options, field, repeated ? j : -1, + &fieldval); } - string name; - if (fields[i]->is_extension()) { - name = "(." + fields[i]->full_name() + ")"; + std::string name; + if (field->is_extension()) { + name = "(." + field->full_name() + ")"; } else { - name = fields[i]->name(); + name = field->name(); } option_entries->push_back(name + " = " + fieldval); } @@ -2163,7 +2316,7 @@ bool RetrieveOptionsAssumingRightPool(int depth, const Message& options, // Used by each of the option formatters. bool RetrieveOptions(int depth, const Message& options, const DescriptorPool* pool, - std::vector* option_entries) { + std::vector* option_entries) { // When printing custom options for a descriptor, we must use an options // message built on top of the same DescriptorPool where the descriptor // is coming from. This is to ensure we are interpreting custom options @@ -2173,14 +2326,13 @@ bool RetrieveOptions(int depth, const Message& options, } else { const Descriptor* option_descriptor = pool->FindMessageTypeByName(options.GetDescriptor()->full_name()); - if (option_descriptor == NULL) { - // google/protobuf/descriptor.proto is not in the pool. This means no - // custom options are used so we are safe to proceed with the compiled - // options message type. + if (option_descriptor == nullptr) { + // descriptor.proto is not in the pool. This means no custom options are + // used so we are safe to proceed with the compiled options message type. return RetrieveOptionsAssumingRightPool(depth, options, option_entries); } DynamicMessageFactory factory; - google::protobuf::scoped_ptr dynamic_options( + std::unique_ptr dynamic_options( factory.GetPrototype(option_descriptor)->New()); if (dynamic_options->ParseFromString(options.SerializeAsString())) { return RetrieveOptionsAssumingRightPool(depth, *dynamic_options, @@ -2196,8 +2348,8 @@ bool RetrieveOptions(int depth, const Message& options, // Formats options that all appear together in brackets. Does not include // brackets. bool FormatBracketedOptions(int depth, const Message& options, - const DescriptorPool* pool, string* output) { - std::vector all_options; + const DescriptorPool* pool, std::string* output) { + std::vector all_options; if (RetrieveOptions(depth, options, pool, &all_options)) { output->append(Join(all_options, ", ")); } @@ -2206,13 +2358,12 @@ bool FormatBracketedOptions(int depth, const Message& options, // Formats options one per line bool FormatLineOptions(int depth, const Message& options, - const DescriptorPool* pool, string* output) { - string prefix(depth * 2, ' '); - std::vector all_options; + const DescriptorPool* pool, std::string* output) { + std::string prefix(depth * 2, ' '); + std::vector all_options; if (RetrieveOptions(depth, options, pool, &all_options)) { - for (int i = 0; i < all_options.size(); i++) { - strings::SubstituteAndAppend(output, "$0option $1;\n", - prefix, all_options[i]); + for (const std::string& option : all_options) { + strings::SubstituteAndAppend(output, "$0option $1;\n", prefix, option); } } return !all_options.empty(); @@ -2220,31 +2371,31 @@ bool FormatLineOptions(int depth, const Message& options, class SourceLocationCommentPrinter { public: - template - SourceLocationCommentPrinter(const DescType* desc, - const string& prefix, + template + SourceLocationCommentPrinter(const DescType* desc, const std::string& prefix, const DebugStringOptions& options) : options_(options), prefix_(prefix) { // Perform the SourceLocation lookup only if we're including user comments, // because the lookup is fairly expensive. - have_source_loc_ = options.include_comments && - desc->GetSourceLocation(&source_loc_); + have_source_loc_ = + options.include_comments && desc->GetSourceLocation(&source_loc_); } SourceLocationCommentPrinter(const FileDescriptor* file, const std::vector& path, - const string& prefix, + const std::string& prefix, const DebugStringOptions& options) : options_(options), prefix_(prefix) { // Perform the SourceLocation lookup only if we're including user comments, // because the lookup is fairly expensive. - have_source_loc_ = options.include_comments && - file->GetSourceLocation(path, &source_loc_); + have_source_loc_ = + options.include_comments && file->GetSourceLocation(path, &source_loc_); } - void AddPreComment(string* output) { + void AddPreComment(std::string* output) { if (have_source_loc_) { // Detached leading comments. - for (int i = 0 ; i < source_loc_.leading_detached_comments.size(); ++i) { - *output += FormatComment(source_loc_.leading_detached_comments[i]); + for (const std::string& leading_detached_comment : + source_loc_.leading_detached_comments) { + *output += FormatComment(leading_detached_comment); *output += "\n"; } // Attached leading comments. @@ -2253,7 +2404,7 @@ class SourceLocationCommentPrinter { } } } - void AddPostComment(string* output) { + void AddPostComment(std::string* output) { if (have_source_loc_ && source_loc_.trailing_comments.size() > 0) { *output += FormatComment(source_loc_.trailing_comments); } @@ -2261,13 +2412,12 @@ class SourceLocationCommentPrinter { // Format comment such that each line becomes a full-line C++-style comment in // the DebugString() output. - string FormatComment(const string& comment_text) { - string stripped_comment = comment_text; + std::string FormatComment(const std::string& comment_text) { + std::string stripped_comment = comment_text; StripWhitespace(&stripped_comment); - std::vector lines = Split(stripped_comment, "\n"); - string output; - for (int i = 0; i < lines.size(); ++i) { - const string& line = lines[i]; + std::vector lines = Split(stripped_comment, "\n"); + std::string output; + for (const std::string& line : lines) { strings::SubstituteAndAppend(&output, "$0// $1\n", prefix_, line); } return output; @@ -2278,32 +2428,31 @@ class SourceLocationCommentPrinter { bool have_source_loc_; SourceLocation source_loc_; DebugStringOptions options_; - string prefix_; + std::string prefix_; }; } // anonymous namespace -string FileDescriptor::DebugString() const { +std::string FileDescriptor::DebugString() const { DebugStringOptions options; // default options return DebugStringWithOptions(options); } -string FileDescriptor::DebugStringWithOptions( +std::string FileDescriptor::DebugStringWithOptions( const DebugStringOptions& debug_string_options) const { - string contents; + std::string contents; { std::vector path; path.push_back(FileDescriptorProto::kSyntaxFieldNumber); - SourceLocationCommentPrinter syntax_comment( - this, path, "", debug_string_options); + SourceLocationCommentPrinter syntax_comment(this, path, "", + debug_string_options); syntax_comment.AddPreComment(&contents); strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n", - SyntaxName(syntax())); + SyntaxName(syntax())); syntax_comment.AddPostComment(&contents); } - SourceLocationCommentPrinter - comment_printer(this, "", debug_string_options); + SourceLocationCommentPrinter comment_printer(this, "", debug_string_options); comment_printer.AddPreComment(&contents); std::set public_dependencies; @@ -2316,21 +2465,21 @@ string FileDescriptor::DebugStringWithOptions( for (int i = 0; i < dependency_count(); i++) { if (public_dependencies.count(i) > 0) { strings::SubstituteAndAppend(&contents, "import public \"$0\";\n", - dependency(i)->name()); + dependency(i)->name()); } else if (weak_dependencies.count(i) > 0) { strings::SubstituteAndAppend(&contents, "import weak \"$0\";\n", - dependency(i)->name()); + dependency(i)->name()); } else { strings::SubstituteAndAppend(&contents, "import \"$0\";\n", - dependency(i)->name()); + dependency(i)->name()); } } if (!package().empty()) { std::vector path; path.push_back(FileDescriptorProto::kPackageFieldNumber); - SourceLocationCommentPrinter package_comment( - this, path, "", debug_string_options); + SourceLocationCommentPrinter package_comment(this, path, "", + debug_string_options); package_comment.AddPreComment(&contents); strings::SubstituteAndAppend(&contents, "package $0;\n\n", package()); package_comment.AddPostComment(&contents); @@ -2367,16 +2516,15 @@ string FileDescriptor::DebugStringWithOptions( contents.append("\n"); } - const Descriptor* containing_type = NULL; + const Descriptor* containing_type = nullptr; for (int i = 0; i < extension_count(); i++) { if (extension(i)->containing_type() != containing_type) { if (i > 0) contents.append("}\n\n"); containing_type = extension(i)->containing_type(); strings::SubstituteAndAppend(&contents, "extend .$0 {\n", - containing_type->full_name()); + containing_type->full_name()); } - extension(i)->DebugString(1, FieldDescriptor::PRINT_LABEL, &contents, - debug_string_options); + extension(i)->DebugString(1, &contents, debug_string_options); } if (extension_count() > 0) contents.append("}\n\n"); @@ -2385,31 +2533,30 @@ string FileDescriptor::DebugStringWithOptions( return contents; } -string Descriptor::DebugString() const { +std::string Descriptor::DebugString() const { DebugStringOptions options; // default options return DebugStringWithOptions(options); } -string Descriptor::DebugStringWithOptions( +std::string Descriptor::DebugStringWithOptions( const DebugStringOptions& options) const { - string contents; + std::string contents; DebugString(0, &contents, options, /* include_opening_clause */ true); return contents; } -void Descriptor::DebugString(int depth, string *contents, - const DebugStringOptions& - debug_string_options, +void Descriptor::DebugString(int depth, std::string* contents, + const DebugStringOptions& debug_string_options, bool include_opening_clause) const { if (options().map_entry()) { // Do not generate debug string for auto-generated map-entry type. return; } - string prefix(depth * 2, ' '); + std::string prefix(depth * 2, ' '); ++depth; - SourceLocationCommentPrinter - comment_printer(this, prefix, debug_string_options); + SourceLocationCommentPrinter comment_printer(this, prefix, + debug_string_options); comment_printer.AddPreComment(contents); if (include_opening_clause) { @@ -2444,9 +2591,8 @@ void Descriptor::DebugString(int depth, string *contents, enum_type(i)->DebugString(depth, contents, debug_string_options); } for (int i = 0; i < field_count(); i++) { - if (field(i)->containing_oneof() == NULL) { - field(i)->DebugString(depth, FieldDescriptor::PRINT_LABEL, contents, - debug_string_options); + if (field(i)->containing_oneof() == nullptr) { + field(i)->DebugString(depth, contents, debug_string_options); } else if (field(i)->containing_oneof()->field(0) == field(i)) { // This is the first field in this oneof, so print the whole oneof. field(i)->containing_oneof()->DebugString(depth, contents, @@ -2455,24 +2601,21 @@ void Descriptor::DebugString(int depth, string *contents, } for (int i = 0; i < extension_range_count(); i++) { - strings::SubstituteAndAppend(contents, "$0 extensions $1 to $2;\n", - prefix, - extension_range(i)->start, - extension_range(i)->end - 1); + strings::SubstituteAndAppend(contents, "$0 extensions $1 to $2;\n", prefix, + extension_range(i)->start, + extension_range(i)->end - 1); } // Group extensions by what they extend, so they can be printed out together. - const Descriptor* containing_type = NULL; + const Descriptor* containing_type = nullptr; for (int i = 0; i < extension_count(); i++) { if (extension(i)->containing_type() != containing_type) { if (i > 0) strings::SubstituteAndAppend(contents, "$0 }\n", prefix); containing_type = extension(i)->containing_type(); - strings::SubstituteAndAppend(contents, "$0 extend .$1 {\n", - prefix, containing_type->full_name()); + strings::SubstituteAndAppend(contents, "$0 extend .$1 {\n", prefix, + containing_type->full_name()); } - extension(i)->DebugString( - depth + 1, FieldDescriptor::PRINT_LABEL, contents, - debug_string_options); + extension(i)->DebugString(depth + 1, contents, debug_string_options); } if (extension_count() > 0) strings::SubstituteAndAppend(contents, "$0 }\n", prefix); @@ -2483,9 +2626,11 @@ void Descriptor::DebugString(int depth, string *contents, const Descriptor::ReservedRange* range = reserved_range(i); if (range->end == range->start + 1) { strings::SubstituteAndAppend(contents, "$0, ", range->start); + } else if (range->end > FieldDescriptor::kMaxNumber) { + strings::SubstituteAndAppend(contents, "$0 to max, ", range->start); } else { - strings::SubstituteAndAppend(contents, "$0 to $1, ", - range->start, range->end - 1); + strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start, + range->end - 1); } } contents->replace(contents->size() - 2, 2, ";\n"); @@ -2495,7 +2640,7 @@ void Descriptor::DebugString(int depth, string *contents, strings::SubstituteAndAppend(contents, "$0 reserved ", prefix); for (int i = 0; i < reserved_name_count(); i++) { strings::SubstituteAndAppend(contents, "\"$0\", ", - CEscape(reserved_name(i))); + CEscape(reserved_name(i))); } contents->replace(contents->size() - 2, 2, ";\n"); } @@ -2504,21 +2649,21 @@ void Descriptor::DebugString(int depth, string *contents, comment_printer.AddPostComment(contents); } -string FieldDescriptor::DebugString() const { +std::string FieldDescriptor::DebugString() const { DebugStringOptions options; // default options return DebugStringWithOptions(options); } -string FieldDescriptor::DebugStringWithOptions( +std::string FieldDescriptor::DebugStringWithOptions( const DebugStringOptions& debug_string_options) const { - string contents; + std::string contents; int depth = 0; if (is_extension()) { strings::SubstituteAndAppend(&contents, "extend .$0 {\n", - containing_type()->full_name()); + containing_type()->full_name()); depth = 1; } - DebugString(depth, PRINT_LABEL, &contents, debug_string_options); + DebugString(depth, &contents, debug_string_options); if (is_extension()) { contents.append("}\n"); } @@ -2526,8 +2671,8 @@ string FieldDescriptor::DebugStringWithOptions( } // The field type string used in FieldDescriptor::DebugString() -string FieldDescriptor::FieldTypeNameDebugString() const { - switch(type()) { +std::string FieldDescriptor::FieldTypeNameDebugString() const { + switch (type()) { case TYPE_MESSAGE: return "." + message_type()->full_name(); case TYPE_ENUM: @@ -2537,13 +2682,11 @@ string FieldDescriptor::FieldTypeNameDebugString() const { } } -void FieldDescriptor::DebugString(int depth, - PrintLabelFlag print_label_flag, - string *contents, - const DebugStringOptions& - debug_string_options) const { - string prefix(depth * 2, ' '); - string field_type; +void FieldDescriptor::DebugString( + int depth, std::string* contents, + const DebugStringOptions& debug_string_options) const { + std::string prefix(depth * 2, ' '); + std::string field_type; // Special case map fields. if (is_map()) { @@ -2555,44 +2698,32 @@ void FieldDescriptor::DebugString(int depth, field_type = FieldTypeNameDebugString(); } - bool print_label = true; - // Determine whether to omit label: - // 1. For an optional field, omit label if it's in oneof or in proto3. - // 2. For a repeated field, omit label if it's a map. - if (is_optional() && (print_label_flag == OMIT_LABEL || - file()->syntax() == FileDescriptor::SYNTAX_PROTO3)) { - print_label = false; - } else if (is_map()) { - print_label = false; - } - string label; - if (print_label) { - label = kLabelToName[this->label()]; - label.push_back(' '); + std::string label = StrCat(kLabelToName[this->label()], " "); + + // Label is omitted for maps, oneof, and plain proto3 fields. + if (is_map() || containing_oneof() || + (is_optional() && !has_optional_keyword())) { + label.clear(); } - SourceLocationCommentPrinter - comment_printer(this, prefix, debug_string_options); + SourceLocationCommentPrinter comment_printer(this, prefix, + debug_string_options); comment_printer.AddPreComment(contents); - strings::SubstituteAndAppend(contents, "$0$1$2 $3 = $4", - prefix, - label, - field_type, - type() == TYPE_GROUP ? message_type()->name() : - name(), - number()); + strings::SubstituteAndAppend( + contents, "$0$1$2 $3 = $4", prefix, label, field_type, + type() == TYPE_GROUP ? message_type()->name() : name(), number()); bool bracketed = false; if (has_default_value()) { bracketed = true; strings::SubstituteAndAppend(contents, " [default = $0", - DefaultValueAsString(true)); + DefaultValueAsString(true)); } if (has_json_name_) { if (!bracketed) { bracketed = true; - contents->append("["); + contents->append(" ["); } else { contents->append(", "); } @@ -2601,7 +2732,7 @@ void FieldDescriptor::DebugString(int depth, contents->append("\""); } - string formatted_options; + std::string formatted_options; if (FormatBracketedOptions(depth, options(), file()->pool(), &formatted_options)) { contents->append(bracketed ? ", " : " ["); @@ -2627,25 +2758,25 @@ void FieldDescriptor::DebugString(int depth, comment_printer.AddPostComment(contents); } -string OneofDescriptor::DebugString() const { +std::string OneofDescriptor::DebugString() const { DebugStringOptions options; // default values return DebugStringWithOptions(options); } -string OneofDescriptor::DebugStringWithOptions( +std::string OneofDescriptor::DebugStringWithOptions( const DebugStringOptions& options) const { - string contents; + std::string contents; DebugString(0, &contents, options); return contents; } -void OneofDescriptor::DebugString(int depth, string* contents, - const DebugStringOptions& - debug_string_options) const { - string prefix(depth * 2, ' '); +void OneofDescriptor::DebugString( + int depth, std::string* contents, + const DebugStringOptions& debug_string_options) const { + std::string prefix(depth * 2, ' '); ++depth; - SourceLocationCommentPrinter - comment_printer(this, prefix, debug_string_options); + SourceLocationCommentPrinter comment_printer(this, prefix, + debug_string_options); comment_printer.AddPreComment(contents); strings::SubstituteAndAppend(contents, "$0oneof $1 {", prefix, name()); @@ -2657,74 +2788,97 @@ void OneofDescriptor::DebugString(int depth, string* contents, } else { contents->append("\n"); for (int i = 0; i < field_count(); i++) { - field(i)->DebugString(depth, FieldDescriptor::OMIT_LABEL, contents, - debug_string_options); + field(i)->DebugString(depth, contents, debug_string_options); } strings::SubstituteAndAppend(contents, "$0}\n", prefix); } comment_printer.AddPostComment(contents); } -string EnumDescriptor::DebugString() const { +std::string EnumDescriptor::DebugString() const { DebugStringOptions options; // default values return DebugStringWithOptions(options); } -string EnumDescriptor::DebugStringWithOptions( +std::string EnumDescriptor::DebugStringWithOptions( const DebugStringOptions& options) const { - string contents; + std::string contents; DebugString(0, &contents, options); return contents; } -void EnumDescriptor::DebugString(int depth, string *contents, - const DebugStringOptions& - debug_string_options) const { - string prefix(depth * 2, ' '); +void EnumDescriptor::DebugString( + int depth, std::string* contents, + const DebugStringOptions& debug_string_options) const { + std::string prefix(depth * 2, ' '); ++depth; - SourceLocationCommentPrinter - comment_printer(this, prefix, debug_string_options); + SourceLocationCommentPrinter comment_printer(this, prefix, + debug_string_options); comment_printer.AddPreComment(contents); - strings::SubstituteAndAppend(contents, "$0enum $1 {\n", - prefix, name()); + strings::SubstituteAndAppend(contents, "$0enum $1 {\n", prefix, name()); FormatLineOptions(depth, options(), file()->pool(), contents); for (int i = 0; i < value_count(); i++) { value(i)->DebugString(depth, contents, debug_string_options); } + + if (reserved_range_count() > 0) { + strings::SubstituteAndAppend(contents, "$0 reserved ", prefix); + for (int i = 0; i < reserved_range_count(); i++) { + const EnumDescriptor::ReservedRange* range = reserved_range(i); + if (range->end == range->start) { + strings::SubstituteAndAppend(contents, "$0, ", range->start); + } else if (range->end == INT_MAX) { + strings::SubstituteAndAppend(contents, "$0 to max, ", range->start); + } else { + strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start, + range->end); + } + } + contents->replace(contents->size() - 2, 2, ";\n"); + } + + if (reserved_name_count() > 0) { + strings::SubstituteAndAppend(contents, "$0 reserved ", prefix); + for (int i = 0; i < reserved_name_count(); i++) { + strings::SubstituteAndAppend(contents, "\"$0\", ", + CEscape(reserved_name(i))); + } + contents->replace(contents->size() - 2, 2, ";\n"); + } + strings::SubstituteAndAppend(contents, "$0}\n", prefix); comment_printer.AddPostComment(contents); } -string EnumValueDescriptor::DebugString() const { +std::string EnumValueDescriptor::DebugString() const { DebugStringOptions options; // default values return DebugStringWithOptions(options); } -string EnumValueDescriptor::DebugStringWithOptions( +std::string EnumValueDescriptor::DebugStringWithOptions( const DebugStringOptions& options) const { - string contents; + std::string contents; DebugString(0, &contents, options); return contents; } -void EnumValueDescriptor::DebugString(int depth, string *contents, - const DebugStringOptions& - debug_string_options) const { - string prefix(depth * 2, ' '); +void EnumValueDescriptor::DebugString( + int depth, std::string* contents, + const DebugStringOptions& debug_string_options) const { + std::string prefix(depth * 2, ' '); - SourceLocationCommentPrinter - comment_printer(this, prefix, debug_string_options); + SourceLocationCommentPrinter comment_printer(this, prefix, + debug_string_options); comment_printer.AddPreComment(contents); - strings::SubstituteAndAppend(contents, "$0$1 = $2", - prefix, name(), number()); + strings::SubstituteAndAppend(contents, "$0$1 = $2", prefix, name(), number()); - string formatted_options; + std::string formatted_options; if (FormatBracketedOptions(depth, options(), type()->file()->pool(), &formatted_options)) { strings::SubstituteAndAppend(contents, " [$0]", formatted_options); @@ -2734,23 +2888,23 @@ void EnumValueDescriptor::DebugString(int depth, string *contents, comment_printer.AddPostComment(contents); } -string ServiceDescriptor::DebugString() const { +std::string ServiceDescriptor::DebugString() const { DebugStringOptions options; // default values return DebugStringWithOptions(options); } -string ServiceDescriptor::DebugStringWithOptions( +std::string ServiceDescriptor::DebugStringWithOptions( const DebugStringOptions& options) const { - string contents; + std::string contents; DebugString(&contents, options); return contents; } -void ServiceDescriptor::DebugString(string *contents, - const DebugStringOptions& - debug_string_options) const { - SourceLocationCommentPrinter - comment_printer(this, /* prefix */ "", debug_string_options); +void ServiceDescriptor::DebugString( + std::string* contents, + const DebugStringOptions& debug_string_options) const { + SourceLocationCommentPrinter comment_printer(this, /* prefix */ "", + debug_string_options); comment_printer.AddPreComment(contents); strings::SubstituteAndAppend(contents, "service $0 {\n", name()); @@ -2766,40 +2920,38 @@ void ServiceDescriptor::DebugString(string *contents, comment_printer.AddPostComment(contents); } -string MethodDescriptor::DebugString() const { +std::string MethodDescriptor::DebugString() const { DebugStringOptions options; // default values return DebugStringWithOptions(options); } -string MethodDescriptor::DebugStringWithOptions( +std::string MethodDescriptor::DebugStringWithOptions( const DebugStringOptions& options) const { - string contents; + std::string contents; DebugString(0, &contents, options); return contents; } -void MethodDescriptor::DebugString(int depth, string *contents, - const DebugStringOptions& - debug_string_options) const { - string prefix(depth * 2, ' '); +void MethodDescriptor::DebugString( + int depth, std::string* contents, + const DebugStringOptions& debug_string_options) const { + std::string prefix(depth * 2, ' '); ++depth; - SourceLocationCommentPrinter - comment_printer(this, prefix, debug_string_options); + SourceLocationCommentPrinter comment_printer(this, prefix, + debug_string_options); comment_printer.AddPreComment(contents); - strings::SubstituteAndAppend(contents, "$0rpc $1($4.$2) returns ($5.$3)", - prefix, name(), - input_type()->full_name(), - output_type()->full_name(), - client_streaming() ? "stream " : "", - server_streaming() ? "stream " : ""); + strings::SubstituteAndAppend( + contents, "$0rpc $1($4.$2) returns ($5.$3)", prefix, name(), + input_type()->full_name(), output_type()->full_name(), + client_streaming() ? "stream " : "", server_streaming() ? "stream " : ""); - string formatted_options; + std::string formatted_options; if (FormatLineOptions(depth, options(), service()->file()->pool(), &formatted_options)) { - strings::SubstituteAndAppend(contents, " {\n$0$1}\n", - formatted_options, prefix); + strings::SubstituteAndAppend(contents, " {\n$0$1}\n", formatted_options, + prefix); } else { contents->append(";\n"); } @@ -2812,16 +2964,16 @@ void MethodDescriptor::DebugString(int depth, string *contents, bool FileDescriptor::GetSourceLocation(const std::vector& path, SourceLocation* out_location) const { - GOOGLE_CHECK_NOTNULL(out_location); + GOOGLE_CHECK(out_location != nullptr); if (source_code_info_) { if (const SourceCodeInfo_Location* loc = - tables_->GetSourceLocation(path, source_code_info_)) { + tables_->GetSourceLocation(path, source_code_info_)) { const RepeatedField& span = loc->span(); if (span.size() == 3 || span.size() == 4) { - out_location->start_line = span.Get(0); + out_location->start_line = span.Get(0); out_location->start_column = span.Get(1); - out_location->end_line = span.Get(span.size() == 3 ? 0 : 2); - out_location->end_column = span.Get(span.size() - 1); + out_location->end_line = span.Get(span.size() == 3 ? 0 : 2); + out_location->end_column = span.Get(span.size() - 1); out_location->leading_comments = loc->leading_comments(); out_location->trailing_comments = loc->trailing_comments(); @@ -2843,9 +2995,9 @@ bool FileDescriptor::GetSourceLocation(SourceLocation* out_location) const { bool FieldDescriptor::is_packed() const { if (!is_packable()) return false; if (file_->syntax() == FileDescriptor::SYNTAX_PROTO2) { - return (options_ != NULL) && options_->packed(); + return (options_ != nullptr) && options_->packed(); } else { - return options_ == NULL || !options_->has_packed() || options_->packed(); + return options_ == nullptr || !options_->has_packed() || options_->packed(); } } @@ -2905,7 +3057,7 @@ void Descriptor::GetLocationPath(std::vector* output) const { void FieldDescriptor::GetLocationPath(std::vector* output) const { if (is_extension()) { - if (extension_scope() == NULL) { + if (extension_scope() == nullptr) { output->push_back(FileDescriptorProto::kExtensionFieldNumber); output->push_back(index()); } else { @@ -2964,17 +3116,17 @@ namespace { // pointers in the original options, not the mutable copy). The Message must be // one of the Options messages in descriptor.proto. struct OptionsToInterpret { - OptionsToInterpret(const string& ns, - const string& el, - const Message* orig_opt, + OptionsToInterpret(const std::string& ns, const std::string& el, + const std::vector& path, const Message* orig_opt, Message* opt) : name_scope(ns), element_name(el), + element_path(path), original_options(orig_opt), - options(opt) { - } - string name_scope; - string element_name; + options(opt) {} + std::string name_scope; + std::string element_name; + std::vector element_path; const Message* original_options; Message* options; }; @@ -2983,8 +3135,7 @@ struct OptionsToInterpret { class DescriptorBuilder { public: - DescriptorBuilder(const DescriptorPool* pool, - DescriptorPool::Tables* tables, + DescriptorBuilder(const DescriptorPool* pool, DescriptorPool::Tables* tables, DescriptorPool::ErrorCollector* error_collector); ~DescriptorBuilder(); @@ -2994,7 +3145,7 @@ class DescriptorBuilder { friend class OptionInterpreter; // Non-recursive part of BuildFile functionality. - const FileDescriptor* BuildFileImpl(const FileDescriptorProto& proto); + FileDescriptor* BuildFileImpl(const FileDescriptorProto& proto); const DescriptorPool* pool_; DescriptorPool::Tables* tables_; // for convenience @@ -3006,7 +3157,7 @@ class DescriptorBuilder { std::vector options_to_interpret_; bool had_errors_; - string filename_; + std::string filename_; FileDescriptor* file_; FileDescriptorTables* file_tables_; std::set dependencies_; @@ -3023,19 +3174,17 @@ class DescriptorBuilder { // actually found in possible_undeclared_dependency_, which may be a parent // of the symbol actually looked for. const FileDescriptor* possible_undeclared_dependency_; - string possible_undeclared_dependency_name_; + std::string possible_undeclared_dependency_name_; // If LookupSymbol() could resolve a symbol which is not defined, // record the resolved name. This is only used by AddNotDefinedError() // to report a more useful error message. - string undefine_resolved_name_; + std::string undefine_resolved_name_; - void AddError(const string& element_name, - const Message& descriptor, + void AddError(const std::string& element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, - const string& error); - void AddError(const string& element_name, - const Message& descriptor, + const std::string& error); + void AddError(const std::string& element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, const char* error); void AddRecursiveImportError(const FileDescriptorProto& proto, int from_here); @@ -3045,19 +3194,18 @@ class DescriptorBuilder { // Adds an error indicating that undefined_symbol was not defined. Must // only be called after LookupSymbol() fails. void AddNotDefinedError( - const string& element_name, - const Message& descriptor, - DescriptorPool::ErrorCollector::ErrorLocation location, - const string& undefined_symbol); + const std::string& element_name, const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const std::string& undefined_symbol); - void AddWarning(const string& element_name, const Message& descriptor, + void AddWarning(const std::string& element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, - const string& error); + const std::string& error); // Silly helper which determines if the given file is in the given package. // I.e., either file->package() == package_name or file->package() is a // nested package within package_name. - bool IsInPackage(const FileDescriptor* file, const string& package_name); + bool IsInPackage(const FileDescriptor* file, const std::string& package_name); // Helper function which finds all public dependencies of the given file, and // stores the them in the dependencies_ set in the builder. @@ -3067,15 +3215,16 @@ class DescriptorBuilder { // - Search the pool's underlay if not found in tables_. // - Insure that the resulting Symbol is from one of the file's declared // dependencies. - Symbol FindSymbol(const string& name, bool build_it = true); + Symbol FindSymbol(const std::string& name, bool build_it = true); // Like FindSymbol() but does not require that the symbol is in one of the // file's declared dependencies. - Symbol FindSymbolNotEnforcingDeps(const string& name, bool build_it = true); + Symbol FindSymbolNotEnforcingDeps(const std::string& name, + bool build_it = true); // This implements the body of FindSymbolNotEnforcingDeps(). Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool, - const string& name, + const std::string& name, bool build_it = true); // Like FindSymbol(), but looks up the name relative to some other symbol @@ -3092,10 +3241,8 @@ class DescriptorBuilder { // that LookupSymbol may still return a non-type symbol in LOOKUP_TYPES mode, // if it believes that's all it could refer to. The caller should always // check that it receives the type of symbol it was expecting. - enum ResolveMode { - LOOKUP_ALL, LOOKUP_TYPES - }; - Symbol LookupSymbol(const string& name, const string& relative_to, + enum ResolveMode { LOOKUP_ALL, LOOKUP_TYPES }; + Symbol LookupSymbol(const std::string& name, const std::string& relative_to, DescriptorPool::PlaceholderType placeholder_type = DescriptorPool::PLACEHOLDER_MESSAGE, ResolveMode resolve_mode = LOOKUP_ALL, @@ -3103,29 +3250,28 @@ class DescriptorBuilder { // Like LookupSymbol() but will not return a placeholder even if // AllowUnknownDependencies() has been used. - Symbol LookupSymbolNoPlaceholder(const string& name, - const string& relative_to, + Symbol LookupSymbolNoPlaceholder(const std::string& name, + const std::string& relative_to, ResolveMode resolve_mode = LOOKUP_ALL, bool build_it = true); // Calls tables_->AddSymbol() and records an error if it fails. Returns // true if successful or false if failed, though most callers can ignore // the return value since an error has already been recorded. - bool AddSymbol(const string& full_name, - const void* parent, const string& name, - const Message& proto, Symbol symbol); + bool AddSymbol(const std::string& full_name, const void* parent, + const std::string& name, const Message& proto, Symbol symbol); // Like AddSymbol(), but succeeds if the symbol is already defined as long // as the existing definition is also a package (because it's OK to define // the same package in two different files). Also adds all parents of the - // packgae to the symbol table (e.g. AddPackage("foo.bar", ...) will add + // package to the symbol table (e.g. AddPackage("foo.bar", ...) will add // "foo.bar" and "foo" to the table). - void AddPackage(const string& name, const Message& proto, + void AddPackage(const std::string& name, const Message& proto, const FileDescriptor* file); // Checks that the symbol name contains only alphanumeric characters and // underscores. Records an error otherwise. - void ValidateSymbolName(const string& name, const string& full_name, + void ValidateSymbolName(const std::string& name, const std::string& full_name, const Message& proto); // Used by BUILD_ARRAY macro (below) to avoid having to have the type @@ -3139,36 +3285,40 @@ class DescriptorBuilder { // descriptor. Remembers its uninterpreted options, to be interpreted // later. DescriptorT must be one of the Descriptor messages from // descriptor.proto. - template void AllocateOptions( - const typename DescriptorT::OptionsType& orig_options, - DescriptorT* descriptor); + template + void AllocateOptions(const typename DescriptorT::OptionsType& orig_options, + DescriptorT* descriptor, int options_field_tag, + const std::string& option_name); // Specialization for FileOptions. void AllocateOptions(const FileOptions& orig_options, FileDescriptor* descriptor); // Implementation for AllocateOptions(). Don't call this directly. - template void AllocateOptionsImpl( - const string& name_scope, - const string& element_name, + template + void AllocateOptionsImpl( + const std::string& name_scope, const std::string& element_name, const typename DescriptorT::OptionsType& orig_options, - DescriptorT* descriptor); + DescriptorT* descriptor, const std::vector& options_path, + const std::string& option_name); + + // Allocate string on the string pool and initialize it to full proto name. + // Full proto name is "scope.proto_name" if scope is non-empty and + // "proto_name" otherwise. + std::string* AllocateNameString(const std::string& scope, + const std::string& proto_name); // These methods all have the same signature for the sake of the BUILD_ARRAY // macro, below. - void BuildMessage(const DescriptorProto& proto, - const Descriptor* parent, + void BuildMessage(const DescriptorProto& proto, const Descriptor* parent, Descriptor* result); void BuildFieldOrExtension(const FieldDescriptorProto& proto, - const Descriptor* parent, - FieldDescriptor* result, + Descriptor* parent, FieldDescriptor* result, bool is_extension); - void BuildField(const FieldDescriptorProto& proto, - const Descriptor* parent, + void BuildField(const FieldDescriptorProto& proto, Descriptor* parent, FieldDescriptor* result) { BuildFieldOrExtension(proto, parent, result, false); } - void BuildExtension(const FieldDescriptorProto& proto, - const Descriptor* parent, + void BuildExtension(const FieldDescriptorProto& proto, Descriptor* parent, FieldDescriptor* result) { BuildFieldOrExtension(proto, parent, result, true); } @@ -3176,25 +3326,24 @@ class DescriptorBuilder { const Descriptor* parent, Descriptor::ExtensionRange* result); void BuildReservedRange(const DescriptorProto::ReservedRange& proto, - const Descriptor* parent, - Descriptor::ReservedRange* result); - void BuildOneof(const OneofDescriptorProto& proto, - Descriptor* parent, + const Descriptor* parent, + Descriptor::ReservedRange* result); + void BuildReservedRange(const EnumDescriptorProto::EnumReservedRange& proto, + const EnumDescriptor* parent, + EnumDescriptor::ReservedRange* result); + void BuildOneof(const OneofDescriptorProto& proto, Descriptor* parent, OneofDescriptor* result); void CheckEnumValueUniqueness(const EnumDescriptorProto& proto, const EnumDescriptor* result); - void BuildEnum(const EnumDescriptorProto& proto, - const Descriptor* parent, + void BuildEnum(const EnumDescriptorProto& proto, const Descriptor* parent, EnumDescriptor* result); void BuildEnumValue(const EnumValueDescriptorProto& proto, const EnumDescriptor* parent, EnumValueDescriptor* result); - void BuildService(const ServiceDescriptorProto& proto, - const void* dummy, + void BuildService(const ServiceDescriptorProto& proto, const void* dummy, ServiceDescriptor* result); void BuildMethod(const MethodDescriptorProto& proto, - const ServiceDescriptor* parent, - MethodDescriptor* result); + const ServiceDescriptor* parent, MethodDescriptor* result); void LogUnusedDependency(const FileDescriptorProto& proto, const FileDescriptor* result); @@ -3226,8 +3375,8 @@ class DescriptorBuilder { class OptionInterpreter { public: // Creates an interpreter that operates in the context of the pool of the - // specified builder, which must not be NULL. We don't take ownership of the - // builder. + // specified builder, which must not be nullptr. We don't take ownership of + // the builder. explicit OptionInterpreter(DescriptorBuilder* builder); ~OptionInterpreter(); @@ -3237,13 +3386,22 @@ class DescriptorBuilder { // Otherwise returns true. bool InterpretOptions(OptionsToInterpret* options_to_interpret); + // Updates the given source code info by re-writing uninterpreted option + // locations to refer to the corresponding interpreted option. + void UpdateSourceCodeInfo(SourceCodeInfo* info); + class AggregateOptionFinder; private: // Interprets uninterpreted_option_ on the specified message, which // must be the mutable copy of the original options message to which - // uninterpreted_option_ belongs. - bool InterpretSingleOption(Message* options); + // uninterpreted_option_ belongs. The given src_path is the source + // location path to the uninterpreted option, and options_path is the + // source location path to the options message. The location paths are + // recorded and then used in UpdateSourceCodeInfo. + bool InterpretSingleOption(Message* options, + const std::vector& src_path, + const std::vector& options_path); // Adds the uninterpreted_option to the given options message verbatim. // Used when AllowUnknownDependencies() is in effect and we can't find @@ -3259,7 +3417,8 @@ class DescriptorBuilder { intermediate_fields_iter, std::vector::const_iterator intermediate_fields_end, - const FieldDescriptor* innermost_field, const string& debug_msg_name, + const FieldDescriptor* innermost_field, + const std::string& debug_msg_name, const UnknownFieldSet& unknown_fields); // Validates the value for the option field of the currently interpreted @@ -3286,7 +3445,7 @@ class DescriptorBuilder { // A helper function that adds an error at the specified location of the // option we're currently interpreting, and returns false. bool AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location, - const string& msg) { + const std::string& msg) { builder_->AddError(options_to_interpret_->element_name, *uninterpreted_option_, location, msg); return false; @@ -3294,30 +3453,40 @@ class DescriptorBuilder { // A helper function that adds an error at the location of the option name // and returns false. - bool AddNameError(const string& msg) { + bool AddNameError(const std::string& msg) { return AddOptionError(DescriptorPool::ErrorCollector::OPTION_NAME, msg); } // A helper function that adds an error at the location of the option name // and returns false. - bool AddValueError(const string& msg) { + bool AddValueError(const std::string& msg) { return AddOptionError(DescriptorPool::ErrorCollector::OPTION_VALUE, msg); } - // We interpret against this builder's pool. Is never NULL. We don't own + // We interpret against this builder's pool. Is never nullptr. We don't own // this pointer. DescriptorBuilder* builder_; - // The options we're currently interpreting, or NULL if we're not in a call - // to InterpretOptions. + // The options we're currently interpreting, or nullptr if we're not in a + // call to InterpretOptions. const OptionsToInterpret* options_to_interpret_; // The option we're currently interpreting within options_to_interpret_, or - // NULL if we're not in a call to InterpretOptions(). This points to a + // nullptr if we're not in a call to InterpretOptions(). This points to a // submessage of the original option, not the mutable copy. Therefore we // can use it to find locations recorded by the parser. const UninterpretedOption* uninterpreted_option_; + // This maps the element path of uninterpreted options to the element path + // of the resulting interpreted option. This is used to modify a file's + // source code info to account for option interpretation. + std::map, std::vector> interpreted_paths_; + + // This maps the path to a repeated option field to the known number of + // elements the field contains. This is used to track the compute the + // index portion of the element path when interpreting a single option. + std::map, int> repeated_option_counts_; + // Factory used to create the dynamic messages we need to parse // any aggregate option values we encounter. DynamicMessageFactory dynamic_factory_; @@ -3342,10 +3511,10 @@ class DescriptorBuilder { return pool->enforce_weak_; } static inline bool get_is_placeholder(const Descriptor* descriptor) { - return descriptor->is_placeholder_; + return descriptor != nullptr && descriptor->is_placeholder_; } static inline void assert_mutex_held(const DescriptorPool* pool) { - if (pool->mutex_ != NULL) { + if (pool->mutex_ != nullptr) { pool->mutex_->AssertHeld(); } } @@ -3366,14 +3535,15 @@ class DescriptorBuilder { const EnumDescriptorProto& proto); void ValidateEnumValueOptions(EnumValueDescriptor* enum_value, const EnumValueDescriptorProto& proto); + void ValidateExtensionRangeOptions( + const std::string& full_name, Descriptor::ExtensionRange* extension_range, + const DescriptorProto_ExtensionRange& proto); void ValidateServiceOptions(ServiceDescriptor* service, const ServiceDescriptorProto& proto); void ValidateMethodOptions(MethodDescriptor* method, const MethodDescriptorProto& proto); - void ValidateProto3(FileDescriptor* file, - const FileDescriptorProto& proto); - void ValidateProto3Message(Descriptor* message, - const DescriptorProto& proto); + void ValidateProto3(FileDescriptor* file, const FileDescriptorProto& proto); + void ValidateProto3Message(Descriptor* message, const DescriptorProto& proto); void ValidateProto3Field(FieldDescriptor* field, const FieldDescriptorProto& proto); void ValidateProto3Enum(EnumDescriptor* enm, @@ -3395,119 +3565,116 @@ class DescriptorBuilder { const FileDescriptor* DescriptorPool::BuildFile( const FileDescriptorProto& proto) { - GOOGLE_CHECK(fallback_database_ == NULL) - << "Cannot call BuildFile on a DescriptorPool that uses a " - "DescriptorDatabase. You must instead find a way to get your file " - "into the underlying database."; - GOOGLE_CHECK(mutex_ == NULL); // Implied by the above GOOGLE_CHECK. + GOOGLE_CHECK(fallback_database_ == nullptr) + << "Cannot call BuildFile on a DescriptorPool that uses a " + "DescriptorDatabase. You must instead find a way to get your file " + "into the underlying database."; + GOOGLE_CHECK(mutex_ == nullptr); // Implied by the above GOOGLE_CHECK. tables_->known_bad_symbols_.clear(); tables_->known_bad_files_.clear(); - return DescriptorBuilder(this, tables_.get(), NULL).BuildFile(proto); + return DescriptorBuilder(this, tables_.get(), nullptr).BuildFile(proto); } const FileDescriptor* DescriptorPool::BuildFileCollectingErrors( - const FileDescriptorProto& proto, - ErrorCollector* error_collector) { - GOOGLE_CHECK(fallback_database_ == NULL) - << "Cannot call BuildFile on a DescriptorPool that uses a " - "DescriptorDatabase. You must instead find a way to get your file " - "into the underlying database."; - GOOGLE_CHECK(mutex_ == NULL); // Implied by the above GOOGLE_CHECK. + const FileDescriptorProto& proto, ErrorCollector* error_collector) { + GOOGLE_CHECK(fallback_database_ == nullptr) + << "Cannot call BuildFile on a DescriptorPool that uses a " + "DescriptorDatabase. You must instead find a way to get your file " + "into the underlying database."; + GOOGLE_CHECK(mutex_ == nullptr); // Implied by the above GOOGLE_CHECK. tables_->known_bad_symbols_.clear(); tables_->known_bad_files_.clear(); - return DescriptorBuilder(this, tables_.get(), - error_collector).BuildFile(proto); + return DescriptorBuilder(this, tables_.get(), error_collector) + .BuildFile(proto); } const FileDescriptor* DescriptorPool::BuildFileFromDatabase( const FileDescriptorProto& proto) const { mutex_->AssertHeld(); if (tables_->known_bad_files_.count(proto.name()) > 0) { - return NULL; + return nullptr; } const FileDescriptor* result = - DescriptorBuilder(this, tables_.get(), - default_error_collector_).BuildFile(proto); - if (result == NULL) { + DescriptorBuilder(this, tables_.get(), default_error_collector_) + .BuildFile(proto); + if (result == nullptr) { tables_->known_bad_files_.insert(proto.name()); } return result; } DescriptorBuilder::DescriptorBuilder( - const DescriptorPool* pool, - DescriptorPool::Tables* tables, + const DescriptorPool* pool, DescriptorPool::Tables* tables, DescriptorPool::ErrorCollector* error_collector) - : pool_(pool), - tables_(tables), - error_collector_(error_collector), - had_errors_(false), - possible_undeclared_dependency_(NULL), - undefine_resolved_name_("") {} + : pool_(pool), + tables_(tables), + error_collector_(error_collector), + had_errors_(false), + possible_undeclared_dependency_(nullptr), + undefine_resolved_name_("") {} DescriptorBuilder::~DescriptorBuilder() {} void DescriptorBuilder::AddError( - const string& element_name, - const Message& descriptor, + const std::string& element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, - const string& error) { - if (error_collector_ == NULL) { + const std::string& error) { + if (error_collector_ == nullptr) { if (!had_errors_) { GOOGLE_LOG(ERROR) << "Invalid proto descriptor for file \"" << filename_ << "\":"; } GOOGLE_LOG(ERROR) << " " << element_name << ": " << error; } else { - error_collector_->AddError(filename_, element_name, - &descriptor, location, error); + error_collector_->AddError(filename_, element_name, &descriptor, location, + error); } had_errors_ = true; } void DescriptorBuilder::AddError( - const string& element_name, - const Message& descriptor, - DescriptorPool::ErrorCollector::ErrorLocation location, - const char* error) { - AddError(element_name, descriptor, location, string(error)); + const std::string& element_name, const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, const char* error) { + AddError(element_name, descriptor, location, std::string(error)); } void DescriptorBuilder::AddNotDefinedError( - const string& element_name, - const Message& descriptor, + const std::string& element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, - const string& undefined_symbol) { - if (possible_undeclared_dependency_ == NULL && + const std::string& undefined_symbol) { + if (possible_undeclared_dependency_ == nullptr && undefine_resolved_name_.empty()) { AddError(element_name, descriptor, location, "\"" + undefined_symbol + "\" is not defined."); } else { - if (possible_undeclared_dependency_ != NULL) { + if (possible_undeclared_dependency_ != nullptr) { AddError(element_name, descriptor, location, "\"" + possible_undeclared_dependency_name_ + - "\" seems to be defined in \"" + - possible_undeclared_dependency_->name() + "\", which is not " - "imported by \"" + filename_ + "\". To use it here, please " - "add the necessary import."); + "\" seems to be defined in \"" + + possible_undeclared_dependency_->name() + + "\", which is not " + "imported by \"" + + filename_ + + "\". To use it here, please " + "add the necessary import."); } if (!undefine_resolved_name_.empty()) { AddError(element_name, descriptor, location, "\"" + undefined_symbol + "\" is resolved to \"" + - undefine_resolved_name_ + "\", which is not defined. " - "The innermost scope is searched first in name resolution. " - "Consider using a leading '.'(i.e., \"." - + undefined_symbol + - "\") to start from the outermost scope."); + undefine_resolved_name_ + + "\", which is not defined. " + "The innermost scope is searched first in name resolution. " + "Consider using a leading '.'(i.e., \"." + + undefined_symbol + "\") to start from the outermost scope."); } } } void DescriptorBuilder::AddWarning( - const string& element_name, const Message& descriptor, + const std::string& element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, - const string& error) { - if (error_collector_ == NULL) { + const std::string& error) { + if (error_collector_ == nullptr) { GOOGLE_LOG(WARNING) << filename_ << " " << element_name << ": " << error; } else { error_collector_->AddWarning(filename_, element_name, &descriptor, location, @@ -3516,27 +3683,27 @@ void DescriptorBuilder::AddWarning( } bool DescriptorBuilder::IsInPackage(const FileDescriptor* file, - const string& package_name) { + const std::string& package_name) { return HasPrefixString(file->package(), package_name) && (file->package().size() == package_name.size() || file->package()[package_name.size()] == '.'); } void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) { - if (file == NULL || !dependencies_.insert(file).second) return; - for (int i = 0; file != NULL && i < file->public_dependency_count(); i++) { + if (file == nullptr || !dependencies_.insert(file).second) return; + for (int i = 0; file != nullptr && i < file->public_dependency_count(); i++) { RecordPublicDependencies(file->public_dependency(i)); } } Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper( - const DescriptorPool* pool, const string& name, bool build_it) { + const DescriptorPool* pool, const std::string& name, bool build_it) { // If we are looking at an underlay, we must lock its mutex_, since we are // accessing the underlay's tables_ directly. - MutexLockMaybe lock((pool == pool_) ? NULL : pool->mutex_); + MutexLockMaybe lock((pool == pool_) ? nullptr : pool->mutex_); Symbol result = pool->tables_->FindSymbol(name); - if (result.IsNull() && pool->underlay_ != NULL) { + if (result.IsNull() && pool->underlay_ != nullptr) { // Symbol not found; check the underlay. result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name); } @@ -3557,12 +3724,19 @@ Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper( return result; } -Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const string& name, +Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const std::string& name, bool build_it) { - return FindSymbolNotEnforcingDepsHelper(pool_, name, build_it); + Symbol result = FindSymbolNotEnforcingDepsHelper(pool_, name, build_it); + // Only find symbols which were defined in this file or one of its + // dependencies. + const FileDescriptor* file = result.GetFile(); + if (file == file_ || dependencies_.count(file) > 0) { + unused_dependency_.erase(file); + } + return result; } -Symbol DescriptorBuilder::FindSymbol(const string& name, bool build_it) { +Symbol DescriptorBuilder::FindSymbol(const std::string& name, bool build_it) { Symbol result = FindSymbolNotEnforcingDeps(name, build_it); if (result.IsNull()) return result; @@ -3576,7 +3750,6 @@ Symbol DescriptorBuilder::FindSymbol(const string& name, bool build_it) { // dependencies. const FileDescriptor* file = result.GetFile(); if (file == file_ || dependencies_.count(file) > 0) { - unused_dependency_.erase(file); return result; } @@ -3592,8 +3765,8 @@ Symbol DescriptorBuilder::FindSymbol(const string& name, bool build_it) { for (std::set::const_iterator it = dependencies_.begin(); it != dependencies_.end(); ++it) { - // Note: A dependency may be NULL if it was not found or had errors. - if (*it != NULL && IsInPackage(*it, name)) return result; + // Note: A dependency may be nullptr if it was not found or had errors. + if (*it != nullptr && IsInPackage(*it, name)) return result; } } @@ -3602,11 +3775,10 @@ Symbol DescriptorBuilder::FindSymbol(const string& name, bool build_it) { return kNullSymbol; } -Symbol DescriptorBuilder::LookupSymbolNoPlaceholder(const string& name, - const string& relative_to, - ResolveMode resolve_mode, - bool build_it) { - possible_undeclared_dependency_ = NULL; +Symbol DescriptorBuilder::LookupSymbolNoPlaceholder( + const std::string& name, const std::string& relative_to, + ResolveMode resolve_mode, bool build_it) { + possible_undeclared_dependency_ = nullptr; undefine_resolved_name_.clear(); if (!name.empty() && name[0] == '.') { @@ -3625,27 +3797,27 @@ Symbol DescriptorBuilder::LookupSymbolNoPlaceholder(const string& name, // } // So, we look for just "Foo" first, then look for "Bar.baz" within it if // found. - string::size_type name_dot_pos = name.find_first_of('.'); - string first_part_of_name; - if (name_dot_pos == string::npos) { + std::string::size_type name_dot_pos = name.find_first_of('.'); + std::string first_part_of_name; + if (name_dot_pos == std::string::npos) { first_part_of_name = name; } else { first_part_of_name = name.substr(0, name_dot_pos); } - string scope_to_try(relative_to); + std::string scope_to_try(relative_to); while (true) { // Chop off the last component of the scope. - string::size_type dot_pos = scope_to_try.find_last_of('.'); - if (dot_pos == string::npos) { + std::string::size_type dot_pos = scope_to_try.find_last_of('.'); + if (dot_pos == std::string::npos) { return FindSymbol(name, build_it); } else { scope_to_try.erase(dot_pos); } // Append ".first_part_of_name" and try to find. - string::size_type old_size = scope_to_try.size(); + std::string::size_type old_size = scope_to_try.size(); scope_to_try.append(1, '.'); scope_to_try.append(first_part_of_name); Symbol result = FindSymbol(scope_to_try, build_it); @@ -3679,7 +3851,7 @@ Symbol DescriptorBuilder::LookupSymbolNoPlaceholder(const string& name, } Symbol DescriptorBuilder::LookupSymbol( - const string& name, const string& relative_to, + const std::string& name, const std::string& relative_to, DescriptorPool::PlaceholderType placeholder_type, ResolveMode resolve_mode, bool build_it) { Symbol result = @@ -3692,16 +3864,16 @@ Symbol DescriptorBuilder::LookupSymbol( return result; } -static bool ValidateQualifiedName(const string& name) { +static bool ValidateQualifiedName(StringPiece name) { bool last_was_period = false; - for (int i = 0; i < name.size(); i++) { + for (char character : name) { // I don't trust isalnum() due to locales. :( - if (('a' <= name[i] && name[i] <= 'z') || - ('A' <= name[i] && name[i] <= 'Z') || - ('0' <= name[i] && name[i] <= '9') || (name[i] == '_')) { + if (('a' <= character && character <= 'z') || + ('A' <= character && character <= 'Z') || + ('0' <= character && character <= '9') || (character == '_')) { last_was_period = false; - } else if (name[i] == '.') { + } else if (character == '.') { if (last_was_period) return false; last_was_period = true; } else { @@ -3712,21 +3884,21 @@ static bool ValidateQualifiedName(const string& name) { return !name.empty() && !last_was_period; } -Symbol DescriptorPool::NewPlaceholder(const string& name, +Symbol DescriptorPool::NewPlaceholder(StringPiece name, PlaceholderType placeholder_type) const { MutexLockMaybe lock(mutex_); return NewPlaceholderWithMutexHeld(name, placeholder_type); } Symbol DescriptorPool::NewPlaceholderWithMutexHeld( - const string& name, PlaceholderType placeholder_type) const { + StringPiece name, PlaceholderType placeholder_type) const { if (mutex_) { mutex_->AssertHeld(); } // Compute names. - const string* placeholder_full_name; - const string* placeholder_name; - const string* placeholder_package; + const std::string* placeholder_full_name; + const std::string* placeholder_name; + const std::string* placeholder_package; if (!ValidateQualifiedName(name)) return kNullSymbol; if (name[0] == '.') { @@ -3736,12 +3908,12 @@ Symbol DescriptorPool::NewPlaceholderWithMutexHeld( placeholder_full_name = tables_->AllocateString(name); } - string::size_type dotpos = placeholder_full_name->find_last_of('.'); - if (dotpos != string::npos) { - placeholder_package = tables_->AllocateString( - placeholder_full_name->substr(0, dotpos)); - placeholder_name = tables_->AllocateString( - placeholder_full_name->substr(dotpos + 1)); + std::string::size_type dotpos = placeholder_full_name->find_last_of('.'); + if (dotpos != std::string::npos) { + placeholder_package = + tables_->AllocateString(placeholder_full_name->substr(0, dotpos)); + placeholder_name = + tables_->AllocateString(placeholder_full_name->substr(dotpos + 1)); } else { placeholder_package = &internal::GetEmptyString(); placeholder_name = placeholder_full_name; @@ -3754,11 +3926,10 @@ Symbol DescriptorPool::NewPlaceholderWithMutexHeld( if (placeholder_type == PLACEHOLDER_ENUM) { placeholder_file->enum_type_count_ = 1; - placeholder_file->enum_types_ = - tables_->AllocateArray(1); + placeholder_file->enum_types_ = tables_->AllocateArray(1); EnumDescriptor* placeholder_enum = &placeholder_file->enum_types_[0]; - memset(placeholder_enum, 0, sizeof(*placeholder_enum)); + memset(static_cast(placeholder_enum), 0, sizeof(*placeholder_enum)); placeholder_enum->full_name_ = placeholder_full_name; placeholder_enum->name_ = placeholder_name; @@ -3772,13 +3943,16 @@ Symbol DescriptorPool::NewPlaceholderWithMutexHeld( placeholder_enum->values_ = tables_->AllocateArray(1); EnumValueDescriptor* placeholder_value = &placeholder_enum->values_[0]; - memset(placeholder_value, 0, sizeof(*placeholder_value)); + memset(static_cast(placeholder_value), 0, + sizeof(*placeholder_value)); placeholder_value->name_ = tables_->AllocateString("PLACEHOLDER_VALUE"); // Note that enum value names are siblings of their type, not children. placeholder_value->full_name_ = - placeholder_package->empty() ? placeholder_value->name_ : - tables_->AllocateString(*placeholder_package + ".PLACEHOLDER_VALUE"); + placeholder_package->empty() + ? placeholder_value->name_ + : tables_->AllocateString(*placeholder_package + + ".PLACEHOLDER_VALUE"); placeholder_value->number_ = 0; placeholder_value->type_ = placeholder_enum; @@ -3787,11 +3961,11 @@ Symbol DescriptorPool::NewPlaceholderWithMutexHeld( return Symbol(placeholder_enum); } else { placeholder_file->message_type_count_ = 1; - placeholder_file->message_types_ = - tables_->AllocateArray(1); + placeholder_file->message_types_ = tables_->AllocateArray(1); Descriptor* placeholder_message = &placeholder_file->message_types_[0]; - memset(placeholder_message, 0, sizeof(*placeholder_message)); + memset(static_cast(placeholder_message), 0, + sizeof(*placeholder_message)); placeholder_message->full_name_ = placeholder_full_name; placeholder_message->name_ = placeholder_name; @@ -3803,29 +3977,30 @@ Symbol DescriptorPool::NewPlaceholderWithMutexHeld( if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) { placeholder_message->extension_range_count_ = 1; placeholder_message->extension_ranges_ = - tables_->AllocateArray(1); + tables_->AllocateArray(1); placeholder_message->extension_ranges_->start = 1; // kMaxNumber + 1 because ExtensionRange::end is exclusive. placeholder_message->extension_ranges_->end = - FieldDescriptor::kMaxNumber + 1; + FieldDescriptor::kMaxNumber + 1; } return Symbol(placeholder_message); } } -FileDescriptor* DescriptorPool::NewPlaceholderFile(const string& name) const { +FileDescriptor* DescriptorPool::NewPlaceholderFile( + StringPiece name) const { MutexLockMaybe lock(mutex_); return NewPlaceholderFileWithMutexHeld(name); } FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld( - const string& name) const { + StringPiece name) const { if (mutex_) { mutex_->AssertHeld(); } FileDescriptor* placeholder = tables_->Allocate(); - memset(placeholder, 0, sizeof(*placeholder)); + memset(static_cast(placeholder), 0, sizeof(*placeholder)); placeholder->name_ = tables_->AllocateString(name); placeholder->package_ = &internal::GetEmptyString(); @@ -3834,26 +4009,32 @@ FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld( placeholder->tables_ = &FileDescriptorTables::GetEmptyInstance(); placeholder->source_code_info_ = &SourceCodeInfo::default_instance(); placeholder->is_placeholder_ = true; - placeholder->syntax_ = FileDescriptor::SYNTAX_PROTO2; + placeholder->syntax_ = FileDescriptor::SYNTAX_UNKNOWN; placeholder->finished_building_ = true; - // All other fields are zero or NULL. + // All other fields are zero or nullptr. return placeholder; } -bool DescriptorBuilder::AddSymbol( - const string& full_name, const void* parent, const string& name, - const Message& proto, Symbol symbol) { - // If the caller passed NULL for the parent, the symbol is at file scope. +bool DescriptorBuilder::AddSymbol(const std::string& full_name, + const void* parent, const std::string& name, + const Message& proto, Symbol symbol) { + // If the caller passed nullptr for the parent, the symbol is at file scope. // Use its file as the parent instead. - if (parent == NULL) parent = file_; + if (parent == nullptr) parent = file_; + if (full_name.find('\0') != std::string::npos) { + AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, + "\"" + full_name + "\" contains null character."); + return false; + } if (tables_->AddSymbol(full_name, symbol)) { if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) { // This is only possible if there was already an error adding something of // the same name. if (!had_errors_) { - GOOGLE_LOG(DFATAL) << "\"" << full_name << "\" not previously defined in " + GOOGLE_LOG(DFATAL) << "\"" << full_name + << "\" not previously defined in " "symbols_by_name_, but was defined in " "symbols_by_parent_; this shouldn't be possible."; } @@ -3863,37 +4044,45 @@ bool DescriptorBuilder::AddSymbol( } else { const FileDescriptor* other_file = tables_->FindSymbol(full_name).GetFile(); if (other_file == file_) { - string::size_type dot_pos = full_name.find_last_of('.'); - if (dot_pos == string::npos) { + std::string::size_type dot_pos = full_name.find_last_of('.'); + if (dot_pos == std::string::npos) { AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, "\"" + full_name + "\" is already defined."); } else { AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, "\"" + full_name.substr(dot_pos + 1) + - "\" is already defined in \"" + - full_name.substr(0, dot_pos) + "\"."); + "\" is already defined in \"" + + full_name.substr(0, dot_pos) + "\"."); } } else { // Symbol seems to have been defined in a different file. AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, "\"" + full_name + "\" is already defined in file \"" + - other_file->name() + "\"."); + (other_file == nullptr ? "null" : other_file->name()) + + "\"."); } return false; } } -void DescriptorBuilder::AddPackage( - const string& name, const Message& proto, const FileDescriptor* file) { +void DescriptorBuilder::AddPackage(const std::string& name, + const Message& proto, + const FileDescriptor* file) { + if (name.find('\0') != std::string::npos) { + AddError(name, proto, DescriptorPool::ErrorCollector::NAME, + "\"" + name + "\" contains null character."); + return; + } if (tables_->AddSymbol(name, Symbol(file))) { // Success. Also add parent package, if any. - string::size_type dot_pos = name.find_last_of('.'); - if (dot_pos == string::npos) { + std::string::size_type dot_pos = name.find_last_of('.'); + if (dot_pos == std::string::npos) { // No parents. ValidateSymbolName(name, name, proto); } else { // Has parent. - string* parent_name = tables_->AllocateString(name.substr(0, dot_pos)); + std::string* parent_name = + tables_->AllocateString(name.substr(0, dot_pos)); AddPackage(*parent_name, proto, file); ValidateSymbolName(name.substr(dot_pos + 1), name, proto); } @@ -3903,25 +4092,26 @@ void DescriptorBuilder::AddPackage( if (existing_symbol.type != Symbol::PACKAGE) { // Symbol seems to have been defined in a different file. AddError(name, proto, DescriptorPool::ErrorCollector::NAME, - "\"" + name + "\" is already defined (as something other than " - "a package) in file \"" + existing_symbol.GetFile()->name() + - "\"."); + "\"" + name + + "\" is already defined (as something other than " + "a package) in file \"" + + existing_symbol.GetFile()->name() + "\"."); } } } -void DescriptorBuilder::ValidateSymbolName( - const string& name, const string& full_name, const Message& proto) { +void DescriptorBuilder::ValidateSymbolName(const std::string& name, + const std::string& full_name, + const Message& proto) { if (name.empty()) { AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, "Missing name."); } else { - for (int i = 0; i < name.size(); i++) { + for (char character : name) { // I don't trust isalnum() due to locales. :( - if ((name[i] < 'a' || 'z' < name[i]) && - (name[i] < 'A' || 'Z' < name[i]) && - (name[i] < '0' || '9' < name[i]) && - (name[i] != '_')) { + if ((character < 'a' || 'z' < character) && + (character < 'A' || 'Z' < character) && + (character < '0' || '9' < character) && (character != '_')) { AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, "\"" + name + "\" is not a valid identifier."); } @@ -3933,32 +4123,49 @@ void DescriptorBuilder::ValidateSymbolName( // This generic implementation is good for all descriptors except // FileDescriptor. -template void DescriptorBuilder::AllocateOptions( +template +void DescriptorBuilder::AllocateOptions( const typename DescriptorT::OptionsType& orig_options, - DescriptorT* descriptor) { + DescriptorT* descriptor, int options_field_tag, + const std::string& option_name) { + std::vector options_path; + descriptor->GetLocationPath(&options_path); + options_path.push_back(options_field_tag); AllocateOptionsImpl(descriptor->full_name(), descriptor->full_name(), - orig_options, descriptor); + orig_options, descriptor, options_path, option_name); } // We specialize for FileDescriptor. void DescriptorBuilder::AllocateOptions(const FileOptions& orig_options, FileDescriptor* descriptor) { + std::vector options_path; + options_path.push_back(FileDescriptorProto::kOptionsFieldNumber); // We add the dummy token so that LookupSymbol does the right thing. AllocateOptionsImpl(descriptor->package() + ".dummy", descriptor->name(), - orig_options, descriptor); + orig_options, descriptor, options_path, + "google.protobuf.FileOptions"); } -template void DescriptorBuilder::AllocateOptionsImpl( - const string& name_scope, - const string& element_name, +template +void DescriptorBuilder::AllocateOptionsImpl( + const std::string& name_scope, const std::string& element_name, const typename DescriptorT::OptionsType& orig_options, - DescriptorT* descriptor) { + DescriptorT* descriptor, const std::vector& options_path, + const std::string& option_name) { // We need to use a dummy pointer to work around a bug in older versions of // GCC. Otherwise, the following two lines could be replaced with: // typename DescriptorT::OptionsType* options = // tables_->AllocateMessage(); - typename DescriptorT::OptionsType* const dummy = NULL; + typename DescriptorT::OptionsType* const dummy = nullptr; typename DescriptorT::OptionsType* options = tables_->AllocateMessage(dummy); + + if (!orig_options.IsInitialized()) { + AddError(name_scope + "." + element_name, orig_options, + DescriptorPool::ErrorCollector::OPTION_NAME, + "Uninterpreted option is missing name or value."); + return; + } + // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti // friendly. Without RTTI, MergeFrom() and CopyFrom() will fallback to the // reflection based method, which requires the Descriptor. However, we are in @@ -3974,51 +4181,75 @@ template void DescriptorBuilder::AllocateOptionsImpl( // OptionsType::GetDescriptor() to be called which may then deadlock since // we're still trying to build it. if (options->uninterpreted_option_size() > 0) { - options_to_interpret_.push_back( - OptionsToInterpret(name_scope, element_name, &orig_options, options)); + options_to_interpret_.push_back(OptionsToInterpret( + name_scope, element_name, options_path, &orig_options, options)); + } + + // If the custom option is in unknown fields, no need to interpret it. + // Remove the dependency file from unused_dependency. + const UnknownFieldSet& unknown_fields = orig_options.unknown_fields(); + if (!unknown_fields.empty()) { + // Can not use options->GetDescriptor() which may case deadlock. + Symbol msg_symbol = tables_->FindSymbol(option_name); + if (msg_symbol.type == Symbol::MESSAGE) { + for (int i = 0; i < unknown_fields.field_count(); ++i) { + assert_mutex_held(pool_); + const FieldDescriptor* field = + pool_->InternalFindExtensionByNumberNoLock( + msg_symbol.descriptor, unknown_fields.field(i).number()); + if (field) { + unused_dependency_.erase(field->file()); + } + } + } } } - // A common pattern: We want to convert a repeated field in the descriptor // to an array of values, calling some method to build each value. -#define BUILD_ARRAY(INPUT, OUTPUT, NAME, METHOD, PARENT) \ - OUTPUT->NAME##_count_ = INPUT.NAME##_size(); \ - AllocateArray(INPUT.NAME##_size(), &OUTPUT->NAME##s_); \ - for (int i = 0; i < INPUT.NAME##_size(); i++) { \ - METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i); \ +#define BUILD_ARRAY(INPUT, OUTPUT, NAME, METHOD, PARENT) \ + OUTPUT->NAME##_count_ = INPUT.NAME##_size(); \ + AllocateArray(INPUT.NAME##_size(), &OUTPUT->NAME##s_); \ + for (int i = 0; i < INPUT.NAME##_size(); i++) { \ + METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i); \ } void DescriptorBuilder::AddRecursiveImportError( const FileDescriptorProto& proto, int from_here) { - string error_message("File recursively imports itself: "); - for (int i = from_here; i < tables_->pending_files_.size(); i++) { + std::string error_message("File recursively imports itself: "); + for (size_t i = from_here; i < tables_->pending_files_.size(); i++) { error_message.append(tables_->pending_files_[i]); error_message.append(" -> "); } error_message.append(proto.name()); - AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, - error_message); + if (static_cast(from_here) < tables_->pending_files_.size() - 1) { + AddError(tables_->pending_files_[from_here + 1], proto, + DescriptorPool::ErrorCollector::IMPORT, error_message); + } else { + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::IMPORT, + error_message); + } } void DescriptorBuilder::AddTwiceListedError(const FileDescriptorProto& proto, int index) { - AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, + AddError(proto.dependency(index), proto, + DescriptorPool::ErrorCollector::IMPORT, "Import \"" + proto.dependency(index) + "\" was listed twice."); } void DescriptorBuilder::AddImportError(const FileDescriptorProto& proto, int index) { - string message; - if (pool_->fallback_database_ == NULL) { - message = "Import \"" + proto.dependency(index) + - "\" has not been loaded."; + std::string message; + if (pool_->fallback_database_ == nullptr) { + message = "Import \"" + proto.dependency(index) + "\" has not been loaded."; } else { message = "Import \"" + proto.dependency(index) + "\" was not found or had errors."; } - AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, message); + AddError(proto.dependency(index), proto, + DescriptorPool::ErrorCollector::IMPORT, message); } static bool ExistingFileMatchesProto(const FileDescriptor* existing_file, @@ -4046,7 +4277,7 @@ const FileDescriptor* DescriptorBuilder::BuildFile( // This is fine, because this idempotency "feature" really only exists to // accommodate one hack in the proto1->proto2 migration layer. const FileDescriptor* existing_file = tables_->FindFile(filename_); - if (existing_file != NULL) { + if (existing_file != nullptr) { // File already in pool. Compare the existing one to the input. if (ExistingFileMatchesProto(existing_file, proto)) { // They're identical. Return the existing descriptor. @@ -4065,10 +4296,10 @@ const FileDescriptor* DescriptorBuilder::BuildFile( // mid-file, but that's pretty ugly, and I'm pretty sure there are // some languages out there that do not allow recursive dependencies // at all. - for (int i = 0; i < tables_->pending_files_.size(); i++) { + for (size_t i = 0; i < tables_->pending_files_.size(); i++) { if (tables_->pending_files_[i] == proto.name()) { AddRecursiveImportError(proto, i); - return NULL; + return nullptr; } } @@ -4076,12 +4307,13 @@ const FileDescriptor* DescriptorBuilder::BuildFile( // attempt to load all dependencies now, before checkpointing tables_. This // avoids confusion with recursive checkpoints. if (!pool_->lazily_build_dependencies_) { - if (pool_->fallback_database_ != NULL) { + if (pool_->fallback_database_ != nullptr) { tables_->pending_files_.push_back(proto.name()); for (int i = 0; i < proto.dependency_size(); i++) { - if (tables_->FindFile(proto.dependency(i)) == NULL && - (pool_->underlay_ == NULL || - pool_->underlay_->FindFileByName(proto.dependency(i)) == NULL)) { + if (tables_->FindFile(proto.dependency(i)) == nullptr && + (pool_->underlay_ == nullptr || + pool_->underlay_->FindFileByName(proto.dependency(i)) == + nullptr)) { // We don't care what this returns since we'll find out below anyway. pool_->TryFindFileInFallbackDatabase(proto.dependency(i)); } @@ -4089,21 +4321,33 @@ const FileDescriptor* DescriptorBuilder::BuildFile( tables_->pending_files_.pop_back(); } } - return BuildFileImpl(proto); -} -const FileDescriptor* DescriptorBuilder::BuildFileImpl( - const FileDescriptorProto& proto) { // Checkpoint the tables so that we can roll back if something goes wrong. tables_->AddCheckpoint(); + FileDescriptor* result = BuildFileImpl(proto); + + file_tables_->FinalizeTables(); + if (result) { + tables_->ClearLastCheckpoint(); + result->finished_building_ = true; + } else { + tables_->RollbackToLastCheckpoint(); + } + + return result; +} + +FileDescriptor* DescriptorBuilder::BuildFileImpl( + const FileDescriptorProto& proto) { FileDescriptor* result = tables_->Allocate(); file_ = result; result->is_placeholder_ = false; result->finished_building_ = false; + SourceCodeInfo* info = nullptr; if (proto.has_source_code_info()) { - SourceCodeInfo *info = tables_->AllocateMessage(); + info = tables_->AllocateMessage(); info->CopyFrom(proto.source_code_info()); result->source_code_info_ = info; } else { @@ -4142,33 +4386,40 @@ const FileDescriptor* DescriptorBuilder::BuildFileImpl( } result->pool_ = pool_; + if (result->name().find('\0') != std::string::npos) { + AddError(result->name(), proto, DescriptorPool::ErrorCollector::NAME, + "\"" + result->name() + "\" contains null character."); + return nullptr; + } + // Add to tables. if (!tables_->AddFile(result)) { AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, "A file with this name is already in the pool."); // Bail out early so that if this is actually the exact same file, we // don't end up reporting that every single symbol is already defined. - tables_->RollbackToLastCheckpoint(); - return NULL; + return nullptr; } if (!result->package().empty()) { AddPackage(result->package(), proto, result); } // Make sure all dependencies are loaded. - std::set seen_dependencies; + std::set seen_dependencies; result->dependency_count_ = proto.dependency_size(); result->dependencies_ = tables_->AllocateArray(proto.dependency_size()); if (pool_->lazily_build_dependencies_) { result->dependencies_once_ = tables_->AllocateOnceDynamic(); result->dependencies_names_ = - tables_->AllocateArray(proto.dependency_size()); - memset(result->dependencies_names_, 0, - sizeof(*result->dependencies_names_) * proto.dependency_size()); + tables_->AllocateArray(proto.dependency_size()); + if (proto.dependency_size() > 0) { + memset(result->dependencies_names_, 0, + sizeof(*result->dependencies_names_) * proto.dependency_size()); + } } else { - result->dependencies_once_ = NULL; - result->dependencies_names_ = NULL; + result->dependencies_once_ = nullptr; + result->dependencies_names_ = nullptr; } unused_dependency_.clear(); std::set weak_deps; @@ -4181,7 +4432,7 @@ const FileDescriptor* DescriptorBuilder::BuildFileImpl( } const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i)); - if (dependency == NULL && pool_->underlay_ != NULL) { + if (dependency == nullptr && pool_->underlay_ != nullptr) { dependency = pool_->underlay_->FindFileByName(proto.dependency(i)); } @@ -4189,17 +4440,16 @@ const FileDescriptor* DescriptorBuilder::BuildFileImpl( // Recursive import. dependency/result is not fully initialized, and it's // dangerous to try to do anything with it. The recursive import error // will be detected and reported in DescriptorBuilder::BuildFile(). - tables_->RollbackToLastCheckpoint(); - return NULL; + return nullptr; } - if (dependency == NULL) { - if (pool_->allow_unknown_ || - (!pool_->enforce_weak_ && weak_deps.find(i) != weak_deps.end())) { - dependency = - pool_->NewPlaceholderFileWithMutexHeld(proto.dependency(i)); - } else { - if (!pool_->lazily_build_dependencies_) { + if (dependency == nullptr) { + if (!pool_->lazily_build_dependencies_) { + if (pool_->allow_unknown_ || + (!pool_->enforce_weak_ && weak_deps.find(i) != weak_deps.end())) { + dependency = + pool_->NewPlaceholderFileWithMutexHeld(proto.dependency(i)); + } else { AddImportError(proto, i); } } @@ -4223,8 +4473,8 @@ const FileDescriptor* DescriptorBuilder::BuildFileImpl( // Check public dependencies. int public_dependency_count = 0; - result->public_dependencies_ = tables_->AllocateArray( - proto.public_dependency_size()); + result->public_dependencies_ = + tables_->AllocateArray(proto.public_dependency_size()); for (int i = 0; i < proto.public_dependency_size(); i++) { // Only put valid public dependency indexes. int index = proto.public_dependency(i); @@ -4238,8 +4488,7 @@ const FileDescriptor* DescriptorBuilder::BuildFileImpl( unused_dependency_.erase(result->dependency(index)); } } else { - AddError(proto.name(), proto, - DescriptorPool::ErrorCollector::OTHER, + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, "Invalid public dependency index."); } } @@ -4258,30 +4507,28 @@ const FileDescriptor* DescriptorBuilder::BuildFileImpl( // Check weak dependencies. int weak_dependency_count = 0; - result->weak_dependencies_ = tables_->AllocateArray( - proto.weak_dependency_size()); + result->weak_dependencies_ = + tables_->AllocateArray(proto.weak_dependency_size()); for (int i = 0; i < proto.weak_dependency_size(); i++) { int index = proto.weak_dependency(i); if (index >= 0 && index < proto.dependency_size()) { result->weak_dependencies_[weak_dependency_count++] = index; } else { - AddError(proto.name(), proto, - DescriptorPool::ErrorCollector::OTHER, + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, "Invalid weak dependency index."); } } result->weak_dependency_count_ = weak_dependency_count; // Convert children. - BUILD_ARRAY(proto, result, message_type, BuildMessage , NULL); - BUILD_ARRAY(proto, result, enum_type , BuildEnum , NULL); - BUILD_ARRAY(proto, result, service , BuildService , NULL); - BUILD_ARRAY(proto, result, extension , BuildExtension, NULL); + BUILD_ARRAY(proto, result, message_type, BuildMessage, nullptr); + BUILD_ARRAY(proto, result, enum_type, BuildEnum, nullptr); + BUILD_ARRAY(proto, result, service, BuildService, nullptr); + BUILD_ARRAY(proto, result, extension, BuildExtension, nullptr); // Copy options. - if (!proto.has_options()) { - result->options_ = NULL; // Will set to default_instance later. - } else { + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { AllocateOptions(proto.options(), result); } @@ -4301,6 +4548,9 @@ const FileDescriptor* DescriptorBuilder::BuildFileImpl( option_interpreter.InterpretOptions(&(*iter)); } options_to_interpret_.clear(); + if (info != nullptr) { + option_interpreter.UpdateSourceCodeInfo(info); + } } // Validate options. See comments at InternalSetLazilyBuildDependencies about @@ -4319,67 +4569,82 @@ const FileDescriptor* DescriptorBuilder::BuildFileImpl( // Again, see comments at InternalSetLazilyBuildDependencies about error - // checking. - if (!unused_dependency_.empty() && !pool_->lazily_build_dependencies_) { + // checking. Also, don't log unused dependencies if there were previous + // errors, since the results might be inaccurate. + if (!had_errors_ && !unused_dependency_.empty() && + !pool_->lazily_build_dependencies_) { LogUnusedDependency(proto, result); } if (had_errors_) { - tables_->RollbackToLastCheckpoint(); - return NULL; + return nullptr; } else { - tables_->ClearLastCheckpoint(); - result->finished_building_ = true; return result; } } + +std::string* DescriptorBuilder::AllocateNameString( + const std::string& scope, const std::string& proto_name) { + std::string* full_name; + if (scope.empty()) { + full_name = tables_->AllocateString(proto_name); + } else { + full_name = tables_->AllocateEmptyString(); + *full_name = StrCat(scope, ".", proto_name); + } + return full_name; +} + void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, const Descriptor* parent, Descriptor* result) { - const string& scope = (parent == NULL) ? - file_->package() : parent->full_name(); - string* full_name = tables_->AllocateString(scope); - if (!full_name->empty()) full_name->append(1, '.'); - full_name->append(proto.name()); - + const std::string& scope = + (parent == nullptr) ? file_->package() : parent->full_name(); + std::string* full_name = AllocateNameString(scope, proto.name()); ValidateSymbolName(proto.name(), *full_name, proto); - result->name_ = tables_->AllocateString(proto.name()); - result->full_name_ = full_name; - result->file_ = file_; + result->name_ = tables_->AllocateString(proto.name()); + result->full_name_ = full_name; + result->file_ = file_; result->containing_type_ = parent; - result->is_placeholder_ = false; + result->is_placeholder_ = false; result->is_unqualified_placeholder_ = false; + result->well_known_type_ = Descriptor::WELLKNOWNTYPE_UNSPECIFIED; + + auto it = pool_->tables_->well_known_types_.find(*full_name); + if (it != pool_->tables_->well_known_types_.end()) { + result->well_known_type_ = it->second; + } // Build oneofs first so that fields and extension ranges can refer to them. - BUILD_ARRAY(proto, result, oneof_decl , BuildOneof , result); - BUILD_ARRAY(proto, result, field , BuildField , result); - BUILD_ARRAY(proto, result, nested_type , BuildMessage , result); - BUILD_ARRAY(proto, result, enum_type , BuildEnum , result); + BUILD_ARRAY(proto, result, oneof_decl, BuildOneof, result); + BUILD_ARRAY(proto, result, field, BuildField, result); + BUILD_ARRAY(proto, result, nested_type, BuildMessage, result); + BUILD_ARRAY(proto, result, enum_type, BuildEnum, result); BUILD_ARRAY(proto, result, extension_range, BuildExtensionRange, result); - BUILD_ARRAY(proto, result, extension , BuildExtension , result); - BUILD_ARRAY(proto, result, reserved_range , BuildReservedRange , result); + BUILD_ARRAY(proto, result, extension, BuildExtension, result); + BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result); // Copy reserved names. int reserved_name_count = proto.reserved_name_size(); result->reserved_name_count_ = reserved_name_count; result->reserved_names_ = - tables_->AllocateArray(reserved_name_count); + tables_->AllocateArray(reserved_name_count); for (int i = 0; i < reserved_name_count; ++i) { result->reserved_names_[i] = tables_->AllocateString(proto.reserved_name(i)); } // Copy options. - if (!proto.has_options()) { - result->options_ = NULL; // Will set to default_instance later. - } else { - AllocateOptions(proto.options(), result); + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { + AllocateOptions(proto.options(), result, + DescriptorProto::kOptionsFieldNumber, + "google.protobuf.MessageOptions"); } - AddSymbol(result->full_name(), parent, result->name(), - proto, Symbol(result)); + AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); for (int i = 0; i < proto.reserved_range_size(); i++) { const DescriptorProto_ReservedRange& range1 = proto.reserved_range(i); @@ -4389,37 +4654,37 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, AddError(result->full_name(), proto.reserved_range(i), DescriptorPool::ErrorCollector::NUMBER, strings::Substitute("Reserved range $0 to $1 overlaps with " - "already-defined range $2 to $3.", - range2.start(), range2.end() - 1, - range1.start(), range1.end() - 1)); + "already-defined range $2 to $3.", + range2.start(), range2.end() - 1, + range1.start(), range1.end() - 1)); } } } - hash_set reserved_name_set; + HASH_SET reserved_name_set; for (int i = 0; i < proto.reserved_name_size(); i++) { - const string& name = proto.reserved_name(i); + const std::string& name = proto.reserved_name(i); if (reserved_name_set.find(name) == reserved_name_set.end()) { reserved_name_set.insert(name); } else { AddError(name, proto, DescriptorPool::ErrorCollector::NAME, - strings::Substitute( - "Field name \"$0\" is reserved multiple times.", - name)); + strings::Substitute("Field name \"$0\" is reserved multiple times.", + name)); } } + for (int i = 0; i < result->field_count(); i++) { const FieldDescriptor* field = result->field(i); for (int j = 0; j < result->extension_range_count(); j++) { const Descriptor::ExtensionRange* range = result->extension_range(j); if (range->start <= field->number() && field->number() < range->end) { - AddError(field->full_name(), proto.extension_range(j), - DescriptorPool::ErrorCollector::NUMBER, - strings::Substitute( - "Extension range $0 to $1 includes field \"$2\" ($3).", - range->start, range->end - 1, - field->name(), field->number())); + AddError( + field->full_name(), proto.extension_range(j), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute( + "Extension range $0 to $1 includes field \"$2\" ($3).", + range->start, range->end - 1, field->name(), field->number())); } } for (int j = 0; j < result->reserved_range_count(); j++) { @@ -4427,21 +4692,21 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, if (range->start <= field->number() && field->number() < range->end) { AddError(field->full_name(), proto.reserved_range(j), DescriptorPool::ErrorCollector::NUMBER, - strings::Substitute( - "Field \"$0\" uses reserved number $1.", - field->name(), field->number())); + strings::Substitute("Field \"$0\" uses reserved number $1.", + field->name(), field->number())); } } if (reserved_name_set.find(field->name()) != reserved_name_set.end()) { - AddError(field->full_name(), proto.field(i), - DescriptorPool::ErrorCollector::NAME, - strings::Substitute( - "Field name \"$0\" is reserved.", field->name())); + AddError( + field->full_name(), proto.field(i), + DescriptorPool::ErrorCollector::NAME, + strings::Substitute("Field name \"$0\" is reserved.", field->name())); } + } // Check that extension ranges don't overlap and don't include - // reserved field numbers. + // reserved field numbers or names. for (int i = 0; i < result->extension_range_count(); i++) { const Descriptor::ExtensionRange* range1 = result->extension_range(i); for (int j = 0; j < result->reserved_range_count(); j++) { @@ -4450,9 +4715,9 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, AddError(result->full_name(), proto.extension_range(i), DescriptorPool::ErrorCollector::NUMBER, strings::Substitute("Extension range $0 to $1 overlaps with " - "reserved range $2 to $3.", - range1->start, range1->end - 1, - range2->start, range2->end - 1)); + "reserved range $2 to $3.", + range1->start, range1->end - 1, range2->start, + range2->end - 1)); } } for (int j = i + 1; j < result->extension_range_count(); j++) { @@ -4461,37 +4726,42 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, AddError(result->full_name(), proto.extension_range(i), DescriptorPool::ErrorCollector::NUMBER, strings::Substitute("Extension range $0 to $1 overlaps with " - "already-defined range $2 to $3.", - range2->start, range2->end - 1, - range1->start, range1->end - 1)); + "already-defined range $2 to $3.", + range2->start, range2->end - 1, range1->start, + range1->end - 1)); } } } } - void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, - const Descriptor* parent, + Descriptor* parent, FieldDescriptor* result, bool is_extension) { - const string& scope = (parent == NULL) ? - file_->package() : parent->full_name(); - string* full_name = tables_->AllocateString(scope); - if (!full_name->empty()) full_name->append(1, '.'); - full_name->append(proto.name()); - + const std::string& scope = + (parent == nullptr) ? file_->package() : parent->full_name(); + std::string* full_name = AllocateNameString(scope, proto.name()); ValidateSymbolName(proto.name(), *full_name, proto); - result->name_ = tables_->AllocateString(proto.name()); - result->full_name_ = full_name; - result->file_ = file_; - result->number_ = proto.number(); + result->name_ = tables_->AllocateString(proto.name()); + result->full_name_ = full_name; + result->file_ = file_; + result->number_ = proto.number(); result->is_extension_ = is_extension; + result->proto3_optional_ = proto.proto3_optional(); + + if (proto.proto3_optional() && + file_->syntax() != FileDescriptor::SYNTAX_PROTO3) { + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "The [proto3_optional=true] option may only be set on proto3" + "fields, not " + + result->full_name()); + } // If .proto files follow the style guide then the name should already be - // lower-cased. If that's the case we can just reuse the string we already - // allocated rather than allocate a new one. - string lowercase_name(proto.name()); + // lower-cased. If that's the case we can just reuse the string we + // already allocated rather than allocate a new one. + std::string lowercase_name(proto.name()); LowerString(&lowercase_name); if (lowercase_name == proto.name()) { result->lowercase_name_ = result->name_; @@ -4516,33 +4786,34 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, // Some compilers do not allow static_cast directly between two enum types, // so we must cast to int first. - result->type_ = static_cast( - implicit_cast(proto.type())); + result->type_ = static_cast( + implicit_cast(proto.type())); result->label_ = static_cast( - implicit_cast(proto.label())); + implicit_cast(proto.label())); - // An extension cannot have a required field (b/13365836). - if (result->is_extension_ && - result->label_ == FieldDescriptor::LABEL_REQUIRED) { - AddError(result->full_name(), proto, - // Error location `TYPE`: we would really like to indicate - // `LABEL`, but the `ErrorLocation` enum has no entry for this, and - // we don't necessarily know about all implementations of the - // `ErrorCollector` interface to extend them to handle the new - // error location type properly. - DescriptorPool::ErrorCollector::TYPE, - "Message extensions cannot have required fields."); + if (result->label_ == FieldDescriptor::LABEL_REQUIRED) { + // An extension cannot have a required field (b/13365836). + if (result->is_extension_) { + AddError(result->full_name(), proto, + // Error location `TYPE`: we would really like to indicate + // `LABEL`, but the `ErrorLocation` enum has no entry for this, + // and we don't necessarily know about all implementations of the + // `ErrorCollector` interface to extend them to handle the new + // error location type properly. + DescriptorPool::ErrorCollector::TYPE, + "The extension " + result->full_name() + " cannot be required."); + } } // Some of these may be filled in when cross-linking. - result->containing_type_ = NULL; - result->extension_scope_ = NULL; - result->message_type_ = NULL; - result->enum_type_ = NULL; - result->type_name_ = NULL; - result->type_once_ = NULL; - result->default_value_enum_ = NULL; - result->default_value_enum_name_ = NULL; + result->containing_type_ = nullptr; + result->extension_scope_ = nullptr; + result->message_type_ = nullptr; + result->enum_type_ = nullptr; + result->type_name_ = nullptr; + result->type_once_ = nullptr; + result->default_value_enum_ = nullptr; + result->default_value_enum_name_ = nullptr; result->has_default_value_ = proto.has_default_value(); if (proto.has_default_value() && result->is_repeated()) { @@ -4553,23 +4824,23 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, if (proto.has_type()) { if (proto.has_default_value()) { - char* end_pos = NULL; + char* end_pos = nullptr; switch (result->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: result->default_value_int32_ = - strtol(proto.default_value().c_str(), &end_pos, 0); + strtol(proto.default_value().c_str(), &end_pos, 0); break; case FieldDescriptor::CPPTYPE_INT64: result->default_value_int64_ = - strto64(proto.default_value().c_str(), &end_pos, 0); + strto64(proto.default_value().c_str(), &end_pos, 0); break; case FieldDescriptor::CPPTYPE_UINT32: result->default_value_uint32_ = - strtoul(proto.default_value().c_str(), &end_pos, 0); + strtoul(proto.default_value().c_str(), &end_pos, 0); break; case FieldDescriptor::CPPTYPE_UINT64: result->default_value_uint64_ = - strtou64(proto.default_value().c_str(), &end_pos, 0); + strtou64(proto.default_value().c_str(), &end_pos, 0); break; case FieldDescriptor::CPPTYPE_FLOAT: if (proto.default_value() == "inf") { @@ -4581,7 +4852,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, } else if (proto.default_value() == "nan") { result->default_value_float_ = std::numeric_limits::quiet_NaN(); - } else { + } else { result->default_value_float_ = io::SafeDoubleToFloat( io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos)); } @@ -4596,7 +4867,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, } else if (proto.default_value() == "nan") { result->default_value_double_ = std::numeric_limits::quiet_NaN(); - } else { + } else { result->default_value_double_ = io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos); } @@ -4614,12 +4885,12 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, break; case FieldDescriptor::CPPTYPE_ENUM: // This will be filled in when cross-linking. - result->default_value_enum_ = NULL; + result->default_value_enum_ = nullptr; break; case FieldDescriptor::CPPTYPE_STRING: if (result->type() == FieldDescriptor::TYPE_BYTES) { result->default_value_string_ = tables_->AllocateString( - UnescapeCEscapeString(proto.default_value())); + UnescapeCEscapeString(proto.default_value())); } else { result->default_value_string_ = tables_->AllocateString(proto.default_value()); @@ -4630,18 +4901,19 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, DescriptorPool::ErrorCollector::DEFAULT_VALUE, "Messages can't have default values."); result->has_default_value_ = false; + result->default_generated_instance_ = nullptr; break; } - if (end_pos != NULL) { - // end_pos is only set non-NULL by the parsers for numeric types, above. - // This checks that the default was non-empty and had no extra junk - // after the end of the number. + if (end_pos != nullptr) { + // end_pos is only set non-null by the parsers for numeric types, + // above. This checks that the default was non-empty and had no extra + // junk after the end of the number. if (proto.default_value().empty() || *end_pos != '\0') { AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::DEFAULT_VALUE, "Couldn't parse default value \"" + proto.default_value() + - "\"."); + "\"."); } } } else { @@ -4670,12 +4942,13 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, break; case FieldDescriptor::CPPTYPE_ENUM: // This will be filled in when cross-linking. - result->default_value_enum_ = NULL; + result->default_value_enum_ = nullptr; break; case FieldDescriptor::CPPTYPE_STRING: result->default_value_string_ = &internal::GetEmptyString(); break; case FieldDescriptor::CPPTYPE_MESSAGE: + result->default_generated_instance_ = nullptr; break; } } @@ -4695,15 +4968,15 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, // on extension numbers. AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, strings::Substitute("Field numbers cannot be greater than $0.", - FieldDescriptor::kMaxNumber)); + FieldDescriptor::kMaxNumber)); } else if (result->number() >= FieldDescriptor::kFirstReservedNumber && result->number() <= FieldDescriptor::kLastReservedNumber) { AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, strings::Substitute( - "Field numbers $0 through $1 are reserved for the protocol " - "buffer library implementation.", - FieldDescriptor::kFirstReservedNumber, - FieldDescriptor::kLastReservedNumber)); + "Field numbers $0 through $1 are reserved for the protocol " + "buffer library implementation.", + FieldDescriptor::kFirstReservedNumber, + FieldDescriptor::kLastReservedNumber)); } if (is_extension) { @@ -4716,14 +4989,13 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, result->extension_scope_ = parent; if (proto.has_oneof_index()) { - AddError(result->full_name(), proto, - DescriptorPool::ErrorCollector::OTHER, + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, "FieldDescriptorProto.oneof_index should not be set for " "extensions."); } // Fill in later (maybe). - result->containing_oneof_ = NULL; + result->containing_oneof_ = nullptr; } else { if (proto.has_extendee()) { AddError(result->full_name(), proto, @@ -4737,41 +5009,38 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, if (proto.oneof_index() < 0 || proto.oneof_index() >= parent->oneof_decl_count()) { AddError(result->full_name(), proto, - DescriptorPool::ErrorCollector::OTHER, + DescriptorPool::ErrorCollector::TYPE, strings::Substitute("FieldDescriptorProto.oneof_index $0 is " - "out of range for type \"$1\".", - proto.oneof_index(), - parent->name())); - result->containing_oneof_ = NULL; + "out of range for type \"$1\".", + proto.oneof_index(), parent->name())); + result->containing_oneof_ = nullptr; } else { result->containing_oneof_ = parent->oneof_decl(proto.oneof_index()); } } else { - result->containing_oneof_ = NULL; + result->containing_oneof_ = nullptr; } } // Copy options. - if (!proto.has_options()) { - result->options_ = NULL; // Will set to default_instance later. - } else { - AllocateOptions(proto.options(), result); + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { + AllocateOptions(proto.options(), result, + FieldDescriptorProto::kOptionsFieldNumber, + "google.protobuf.FieldOptions"); } - AddSymbol(result->full_name(), parent, result->name(), - proto, Symbol(result)); + AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); } void DescriptorBuilder::BuildExtensionRange( - const DescriptorProto::ExtensionRange& proto, - const Descriptor* parent, + const DescriptorProto::ExtensionRange& proto, const Descriptor* parent, Descriptor::ExtensionRange* result) { result->start = proto.start(); result->end = proto.end(); if (result->start <= 0) { - AddError(parent->full_name(), proto, - DescriptorPool::ErrorCollector::NUMBER, + AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, "Extension numbers must be positive integers."); } @@ -4781,39 +5050,55 @@ void DescriptorBuilder::BuildExtensionRange( // numbers are actually used as int32s in the message_set_wire_format. if (result->start >= result->end) { - AddError(parent->full_name(), proto, - DescriptorPool::ErrorCollector::NUMBER, + AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, "Extension range end number must be greater than start number."); } - if (!proto.has_options()) { - result->options_ = NULL; // Will set to default_instance later. - } else { + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { + std::vector options_path; + parent->GetLocationPath(&options_path); + options_path.push_back(DescriptorProto::kExtensionRangeFieldNumber); + // find index of this extension range in order to compute path + int index; + for (index = 0; parent->extension_ranges_ + index != result; index++) { + } + options_path.push_back(index); + options_path.push_back(DescriptorProto_ExtensionRange::kOptionsFieldNumber); AllocateOptionsImpl(parent->full_name(), parent->full_name(), - proto.options(), result); + proto.options(), result, options_path, + "google.protobuf.ExtensionRangeOptions"); } } void DescriptorBuilder::BuildReservedRange( - const DescriptorProto::ReservedRange& proto, - const Descriptor* parent, + const DescriptorProto::ReservedRange& proto, const Descriptor* parent, Descriptor::ReservedRange* result) { result->start = proto.start(); result->end = proto.end(); if (result->start <= 0) { - AddError(parent->full_name(), proto, - DescriptorPool::ErrorCollector::NUMBER, + AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, "Reserved numbers must be positive integers."); } } +void DescriptorBuilder::BuildReservedRange( + const EnumDescriptorProto::EnumReservedRange& proto, + const EnumDescriptor* parent, EnumDescriptor::ReservedRange* result) { + result->start = proto.start(); + result->end = proto.end(); + + if (result->start > result->end) { + AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, + "Reserved range end number must be greater than start number."); + } +} + void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto, Descriptor* parent, OneofDescriptor* result) { - string* full_name = tables_->AllocateString(parent->full_name()); - full_name->append(1, '.'); - full_name->append(proto.name()); - + std::string* full_name = + AllocateNameString(parent->full_name(), proto.name()); ValidateSymbolName(proto.name(), *full_name, proto); result->name_ = tables_->AllocateString(proto.name()); @@ -4823,17 +5108,17 @@ void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto, // We need to fill these in later. result->field_count_ = 0; - result->fields_ = NULL; + result->fields_ = nullptr; + result->options_ = nullptr; // Copy options. - if (!proto.has_options()) { - result->options_ = NULL; // Will set to default_instance later. - } else { - AllocateOptions(proto.options(), result); + if (proto.has_options()) { + AllocateOptions(proto.options(), result, + OneofDescriptorProto::kOptionsFieldNumber, + "google.protobuf.OneofOptions"); } - AddSymbol(result->full_name(), parent, result->name(), - proto, Symbol(result)); + AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); } void DescriptorBuilder::CheckEnumValueUniqueness( @@ -4865,13 +5150,12 @@ void DescriptorBuilder::CheckEnumValueUniqueness( // NAME_TYPE_LAST_NAME = 2, // } PrefixRemover remover(result->name()); - std::map values; + std::map values; for (int i = 0; i < result->value_count(); i++) { - const google::protobuf::EnumValueDescriptor* value = result->value(i); - string stripped = + const EnumValueDescriptor* value = result->value(i); + std::string stripped = EnumValueToPascalCase(remover.MaybeRemove(value->name())); - std::pair::iterator, - bool> + std::pair::iterator, bool> insert_result = values.insert(std::make_pair(stripped, value)); bool inserted = insert_result.second; @@ -4883,11 +5167,13 @@ void DescriptorBuilder::CheckEnumValueUniqueness( // stripping should de-dup the labels in this case). if (!inserted && insert_result.first->second->name() != value->name() && insert_result.first->second->number() != value->number()) { - string error_message = - "When enum name is stripped and label is PascalCased (" + stripped + - "), this value label conflicts with " + values[stripped]->name() + - ". This will make the proto fail to compile for some languages, such " - "as C#."; + std::string error_message = + "Enum name " + value->name() + " has the same name as " + + values[stripped]->name() + + " if you ignore case and strip out the enum name prefix (if any). " + "This is error-prone and can lead to undefined behavior. " + "Please avoid doing this. If you are using allow_alias, please " + "assign the same numeric value to both enums."; // There are proto2 enums out there with conflicting names, so to preserve // compatibility we issue only a warning for proto2. if (result->file()->syntax() == FileDescriptor::SYNTAX_PROTO2) { @@ -4904,87 +5190,145 @@ void DescriptorBuilder::CheckEnumValueUniqueness( void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto, const Descriptor* parent, EnumDescriptor* result) { - const string& scope = (parent == NULL) ? - file_->package() : parent->full_name(); - string* full_name = tables_->AllocateString(scope); - if (!full_name->empty()) full_name->append(1, '.'); - full_name->append(proto.name()); - + const std::string& scope = + (parent == nullptr) ? file_->package() : parent->full_name(); + std::string* full_name = AllocateNameString(scope, proto.name()); ValidateSymbolName(proto.name(), *full_name, proto); - result->name_ = tables_->AllocateString(proto.name()); - result->full_name_ = full_name; - result->file_ = file_; + result->name_ = tables_->AllocateString(proto.name()); + result->full_name_ = full_name; + result->file_ = file_; result->containing_type_ = parent; - result->is_placeholder_ = false; + result->is_placeholder_ = false; result->is_unqualified_placeholder_ = false; if (proto.value_size() == 0) { // We cannot allow enums with no values because this would mean there // would be no valid default value for fields of this type. - AddError(result->full_name(), proto, - DescriptorPool::ErrorCollector::NAME, + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NAME, "Enums must contain at least one value."); } BUILD_ARRAY(proto, result, value, BuildEnumValue, result); + BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result); + + // Copy reserved names. + int reserved_name_count = proto.reserved_name_size(); + result->reserved_name_count_ = reserved_name_count; + result->reserved_names_ = + tables_->AllocateArray(reserved_name_count); + for (int i = 0; i < reserved_name_count; ++i) { + result->reserved_names_[i] = + tables_->AllocateString(proto.reserved_name(i)); + } CheckEnumValueUniqueness(proto, result); // Copy options. - if (!proto.has_options()) { - result->options_ = NULL; // Will set to default_instance later. - } else { - AllocateOptions(proto.options(), result); + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { + AllocateOptions(proto.options(), result, + EnumDescriptorProto::kOptionsFieldNumber, + "google.protobuf.EnumOptions"); } - AddSymbol(result->full_name(), parent, result->name(), - proto, Symbol(result)); + AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); + + for (int i = 0; i < proto.reserved_range_size(); i++) { + const EnumDescriptorProto_EnumReservedRange& range1 = + proto.reserved_range(i); + for (int j = i + 1; j < proto.reserved_range_size(); j++) { + const EnumDescriptorProto_EnumReservedRange& range2 = + proto.reserved_range(j); + if (range1.end() >= range2.start() && range2.end() >= range1.start()) { + AddError(result->full_name(), proto.reserved_range(i), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Reserved range $0 to $1 overlaps with " + "already-defined range $2 to $3.", + range2.start(), range2.end(), range1.start(), + range1.end())); + } + } + } + + HASH_SET reserved_name_set; + for (int i = 0; i < proto.reserved_name_size(); i++) { + const std::string& name = proto.reserved_name(i); + if (reserved_name_set.find(name) == reserved_name_set.end()) { + reserved_name_set.insert(name); + } else { + AddError(name, proto, DescriptorPool::ErrorCollector::NAME, + strings::Substitute("Enum value \"$0\" is reserved multiple times.", + name)); + } + } + + for (int i = 0; i < result->value_count(); i++) { + const EnumValueDescriptor* value = result->value(i); + for (int j = 0; j < result->reserved_range_count(); j++) { + const EnumDescriptor::ReservedRange* range = result->reserved_range(j); + if (range->start <= value->number() && value->number() <= range->end) { + AddError(value->full_name(), proto.reserved_range(j), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Enum value \"$0\" uses reserved number $1.", + value->name(), value->number())); + } + } + if (reserved_name_set.find(value->name()) != reserved_name_set.end()) { + AddError( + value->full_name(), proto.value(i), + DescriptorPool::ErrorCollector::NAME, + strings::Substitute("Enum value \"$0\" is reserved.", value->name())); + } + } } void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto, const EnumDescriptor* parent, EnumValueDescriptor* result) { - result->name_ = tables_->AllocateString(proto.name()); + result->name_ = tables_->AllocateString(proto.name()); result->number_ = proto.number(); - result->type_ = parent; + result->type_ = parent; // Note: full_name for enum values is a sibling to the parent's name, not a // child of it. - string* full_name = tables_->AllocateString(*parent->full_name_); - full_name->resize(full_name->size() - parent->name_->size()); + std::string* full_name = tables_->AllocateEmptyString(); + size_t scope_len = parent->full_name_->size() - parent->name_->size(); + full_name->reserve(scope_len + result->name_->size()); + full_name->append(parent->full_name_->data(), scope_len); full_name->append(*result->name_); result->full_name_ = full_name; ValidateSymbolName(proto.name(), *full_name, proto); // Copy options. - if (!proto.has_options()) { - result->options_ = NULL; // Will set to default_instance later. - } else { - AllocateOptions(proto.options(), result); + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { + AllocateOptions(proto.options(), result, + EnumValueDescriptorProto::kOptionsFieldNumber, + "google.protobuf.EnumValueOptions"); } // Again, enum values are weird because we makes them appear as siblings // of the enum type instead of children of it. So, we use // parent->containing_type() as the value's parent. bool added_to_outer_scope = - AddSymbol(result->full_name(), parent->containing_type(), result->name(), - proto, Symbol(result)); + AddSymbol(result->full_name(), parent->containing_type(), result->name(), + proto, Symbol(result)); // However, we also want to be able to search for values within a single // enum type, so we add it as a child of the enum type itself, too. // Note: This could fail, but if it does, the error has already been // reported by the above AddSymbol() call, so we ignore the return code. bool added_to_inner_scope = - file_tables_->AddAliasUnderParent(parent, result->name(), Symbol(result)); + file_tables_->AddAliasUnderParent(parent, result->name(), Symbol(result)); if (added_to_inner_scope && !added_to_outer_scope) { // This value did not conflict with any values defined in the same enum, // but it did conflict with some other symbol defined in the enum type's // scope. Let's print an additional error to explain this. - string outer_scope; - if (parent->containing_type() == NULL) { + std::string outer_scope; + if (parent->containing_type() == nullptr) { outer_scope = file_->package(); } else { outer_scope = parent->containing_type()->full_name(); @@ -4996,12 +5340,12 @@ void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto, outer_scope = "\"" + outer_scope + "\""; } - AddError(result->full_name(), proto, - DescriptorPool::ErrorCollector::NAME, + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NAME, "Note that enum values use C++ scoping rules, meaning that " "enum values are siblings of their type, not children of it. " - "Therefore, \"" + result->name() + "\" must be unique within " - + outer_scope + ", not just within \"" + parent->name() + "\"."); + "Therefore, \"" + + result->name() + "\" must be unique within " + outer_scope + + ", not just within \"" + parent->name() + "\"."); } // An enum is allowed to define two numbers that refer to the same value. @@ -5013,38 +5357,35 @@ void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto, void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto, const void* /* dummy */, ServiceDescriptor* result) { - string* full_name = tables_->AllocateString(file_->package()); - if (!full_name->empty()) full_name->append(1, '.'); - full_name->append(proto.name()); - + std::string* full_name = AllocateNameString(file_->package(), proto.name()); ValidateSymbolName(proto.name(), *full_name, proto); - result->name_ = tables_->AllocateString(proto.name()); + result->name_ = tables_->AllocateString(proto.name()); result->full_name_ = full_name; - result->file_ = file_; + result->file_ = file_; BUILD_ARRAY(proto, result, method, BuildMethod, result); // Copy options. - if (!proto.has_options()) { - result->options_ = NULL; // Will set to default_instance later. - } else { - AllocateOptions(proto.options(), result); + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { + AllocateOptions(proto.options(), result, + ServiceDescriptorProto::kOptionsFieldNumber, + "google.protobuf.ServiceOptions"); } - AddSymbol(result->full_name(), NULL, result->name(), - proto, Symbol(result)); + AddSymbol(result->full_name(), nullptr, result->name(), proto, + Symbol(result)); } void DescriptorBuilder::BuildMethod(const MethodDescriptorProto& proto, const ServiceDescriptor* parent, MethodDescriptor* result) { - result->name_ = tables_->AllocateString(proto.name()); + result->name_ = tables_->AllocateString(proto.name()); result->service_ = parent; - string* full_name = tables_->AllocateString(parent->full_name()); - full_name->append(1, '.'); - full_name->append(*result->name_); + std::string* full_name = + AllocateNameString(parent->full_name(), *result->name_); result->full_name_ = full_name; ValidateSymbolName(proto.name(), *full_name, proto); @@ -5054,26 +5395,26 @@ void DescriptorBuilder::BuildMethod(const MethodDescriptorProto& proto, result->output_type_.Init(); // Copy options. - if (!proto.has_options()) { - result->options_ = NULL; // Will set to default_instance later. - } else { - AllocateOptions(proto.options(), result); + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { + AllocateOptions(proto.options(), result, + MethodDescriptorProto::kOptionsFieldNumber, + "google.protobuf.MethodOptions"); } result->client_streaming_ = proto.client_streaming(); result->server_streaming_ = proto.server_streaming(); - AddSymbol(result->full_name(), parent, result->name(), - proto, Symbol(result)); + AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); } #undef BUILD_ARRAY // ------------------------------------------------------------------- -void DescriptorBuilder::CrossLinkFile( - FileDescriptor* file, const FileDescriptorProto& proto) { - if (file->options_ == NULL) { +void DescriptorBuilder::CrossLinkFile(FileDescriptor* file, + const FileDescriptorProto& proto) { + if (file->options_ == nullptr) { file->options_ = &FileOptions::default_instance(); } @@ -5094,9 +5435,9 @@ void DescriptorBuilder::CrossLinkFile( } } -void DescriptorBuilder::CrossLinkMessage( - Descriptor* message, const DescriptorProto& proto) { - if (message->options_ == NULL) { +void DescriptorBuilder::CrossLinkMessage(Descriptor* message, + const DescriptorProto& proto) { + if (message->options_ == nullptr) { message->options_ = &MessageOptions::default_instance(); } @@ -5126,7 +5467,7 @@ void DescriptorBuilder::CrossLinkMessage( // First count the number of fields per oneof. for (int i = 0; i < message->field_count(); i++) { const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof(); - if (oneof_decl != NULL) { + if (oneof_decl != nullptr) { // Make sure fields belonging to the same oneof are defined consecutively. // This enables optimizations in codegens and reflection libraries to // skip fields in the oneof group, as only one of the field can be set. @@ -5135,14 +5476,13 @@ void DescriptorBuilder::CrossLinkMessage( // safe. if (oneof_decl->field_count() > 0 && message->field(i - 1)->containing_oneof() != oneof_decl) { - AddError( - message->full_name() + "." + message->field(i - 1)->name(), - proto.field(i - 1), DescriptorPool::ErrorCollector::OTHER, - strings::Substitute( - "Fields in the same oneof must be defined consecutively. " - "\"$0\" cannot be defined before the completion of the " - "\"$1\" oneof definition.", - message->field(i - 1)->name(), oneof_decl->name())); + AddError(message->full_name() + "." + message->field(i - 1)->name(), + proto.field(i - 1), DescriptorPool::ErrorCollector::TYPE, + strings::Substitute( + "Fields in the same oneof must be defined consecutively. " + "\"$0\" cannot be defined before the completion of the " + "\"$1\" oneof definition.", + message->field(i - 1)->name(), oneof_decl->name())); } // Must go through oneof_decls_ array to get a non-const version of the // OneofDescriptor. @@ -5156,16 +5496,15 @@ void DescriptorBuilder::CrossLinkMessage( if (oneof_decl->field_count() == 0) { AddError(message->full_name() + "." + oneof_decl->name(), - proto.oneof_decl(i), - DescriptorPool::ErrorCollector::NAME, + proto.oneof_decl(i), DescriptorPool::ErrorCollector::NAME, "Oneof must have at least one field."); } - oneof_decl->fields_ = - tables_->AllocateArray(oneof_decl->field_count_); + oneof_decl->fields_ = tables_->AllocateArray( + oneof_decl->field_count_); oneof_decl->field_count_ = 0; - if (oneof_decl->options_ == NULL) { + if (oneof_decl->options_ == nullptr) { oneof_decl->options_ = &OneofOptions::default_instance(); } } @@ -5173,7 +5512,7 @@ void DescriptorBuilder::CrossLinkMessage( // Then fill them in. for (int i = 0; i < message->field_count(); i++) { const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof(); - if (oneof_decl != NULL) { + if (oneof_decl != nullptr) { OneofDescriptor* mutable_oneof_decl = &message->oneof_decls_[oneof_decl->index()]; message->fields_[i].index_in_oneof_ = mutable_oneof_decl->field_count_; @@ -5181,19 +5520,55 @@ void DescriptorBuilder::CrossLinkMessage( message->field(i); } } + + for (int i = 0; i < message->field_count(); i++) { + const FieldDescriptor* field = message->field(i); + if (field->proto3_optional_) { + if (!field->containing_oneof() || + !field->containing_oneof()->is_synthetic()) { + AddError(message->full_name(), proto.field(i), + DescriptorPool::ErrorCollector::OTHER, + "Fields with proto3_optional set must be " + "a member of a one-field oneof"); + } + } + } + + // Synthetic oneofs must be last. + int first_synthetic = -1; + for (int i = 0; i < message->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = message->oneof_decl(i); + if (oneof->is_synthetic()) { + if (first_synthetic == -1) { + first_synthetic = i; + } + } else { + if (first_synthetic != -1) { + AddError(message->full_name(), proto.oneof_decl(i), + DescriptorPool::ErrorCollector::OTHER, + "Synthetic oneofs must be after all other oneofs"); + } + } + } + + if (first_synthetic == -1) { + message->real_oneof_decl_count_ = message->oneof_decl_count_; + } else { + message->real_oneof_decl_count_ = first_synthetic; + } } void DescriptorBuilder::CrossLinkExtensionRange( Descriptor::ExtensionRange* range, const DescriptorProto::ExtensionRange& proto) { - if (range->options_ == NULL) { + if (range->options_ == nullptr) { range->options_ = &ExtensionRangeOptions::default_instance(); } } -void DescriptorBuilder::CrossLinkField( - FieldDescriptor* field, const FieldDescriptorProto& proto) { - if (field->options_ == NULL) { +void DescriptorBuilder::CrossLinkField(FieldDescriptor* field, + const FieldDescriptorProto& proto) { + if (field->options_ == nullptr) { field->options_ = &FieldOptions::default_instance(); } @@ -5217,26 +5592,33 @@ void DescriptorBuilder::CrossLinkField( } field->containing_type_ = extendee.descriptor; - const Descriptor::ExtensionRange* extension_range = field->containing_type() - ->FindExtensionRangeContainingNumber(field->number()); - - if (extension_range == NULL) { - AddError(field->full_name(), proto, - DescriptorPool::ErrorCollector::NUMBER, - strings::Substitute("\"$0\" does not declare $1 as an " - "extension number.", - field->containing_type()->full_name(), - field->number())); + const Descriptor::ExtensionRange* extension_range = + field->containing_type()->FindExtensionRangeContainingNumber( + field->number()); + + if (extension_range == nullptr) { + // Set of valid extension numbers for MessageSet is different (< 2^32) + // from other extendees (< 2^29). If unknown deps are allowed, we may not + // have that information, and wrongly deem the extension as invalid. + auto skip_check = get_allow_unknown(pool_) && + proto.extendee() == "google.protobuf.bridge.MessageSet"; + if (!skip_check) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("\"$0\" does not declare $1 as an " + "extension number.", + field->containing_type()->full_name(), + field->number())); + } } } - if (field->containing_oneof() != NULL) { + if (field->containing_oneof() != nullptr) { if (field->label() != FieldDescriptor::LABEL_OPTIONAL) { // Note that this error will never happen when parsing .proto files. // It can only happen if you manually construct a FileDescriptorProto // that is incorrect. - AddError(field->full_name(), proto, - DescriptorPool::ErrorCollector::NAME, + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME, "Fields of oneofs must themselves have label LABEL_OPTIONAL."); } } @@ -5248,25 +5630,27 @@ void DescriptorBuilder::CrossLinkField( bool expecting_enum = (proto.type() == FieldDescriptorProto::TYPE_ENUM) || proto.has_default_value(); + // In case of weak fields we force building the dependency. We need to know + // if the type exist or not. If it doesn't exist we substitute Empty which + // should only be done if the type can't be found in the generated pool. + // TODO(gerbens) Ideally we should query the database directly to check + // if weak fields exist or not so that we don't need to force building + // weak dependencies. However the name lookup rules for symbols are + // somewhat complicated, so I defer it too another CL. + bool is_weak = !pool_->enforce_weak_ && proto.options().weak(); + bool is_lazy = pool_->lazily_build_dependencies_ && !is_weak; + Symbol type = LookupSymbol(proto.type_name(), field->full_name(), expecting_enum ? DescriptorPool::PLACEHOLDER_ENUM : DescriptorPool::PLACEHOLDER_MESSAGE, - LOOKUP_TYPES, !pool_->lazily_build_dependencies_); - - // If the type is a weak type, we change the type to a google.protobuf.Empty field. - if (type.IsNull() && !pool_->enforce_weak_ && proto.options().weak()) { - type = FindSymbol(kNonLinkedWeakMessageReplacementName); - } + LOOKUP_TYPES, !is_lazy); if (type.IsNull()) { - if (pool_->lazily_build_dependencies_) { + if (is_lazy) { // Save the symbol names for later for lookup, and allocate the once // object needed for the accessors. - string name = proto.type_name(); - if (!pool_->enforce_weak_ && proto.options().weak()) { - name = kNonLinkedWeakMessageReplacementName; - } + std::string name = proto.type_name(); field->type_once_ = tables_->AllocateOnceDynamic(); field->type_name_ = tables_->AllocateString(name); if (proto.has_default_value()) { @@ -5284,10 +5668,17 @@ void DescriptorBuilder::CrossLinkField( } return; } else { - AddNotDefinedError(field->full_name(), proto, - DescriptorPool::ErrorCollector::TYPE, - proto.type_name()); - return; + // If the type is a weak type, we change the type to a google.protobuf.Empty + // field. + if (is_weak) { + type = FindSymbol(kNonLinkedWeakMessageReplacementName); + } + if (type.IsNull()) { + AddNotDefinedError(field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + proto.type_name()); + return; + } } } @@ -5348,20 +5739,19 @@ void DescriptorBuilder::CrossLinkField( // We can't just use field->enum_type()->FindValueByName() here // because that locks the pool's mutex, which we have already locked // at this point. - Symbol default_value = - LookupSymbolNoPlaceholder(proto.default_value(), - field->enum_type()->full_name()); + Symbol default_value = LookupSymbolNoPlaceholder( + proto.default_value(), field->enum_type()->full_name()); if (default_value.type == Symbol::ENUM_VALUE && default_value.enum_value_descriptor->type() == - field->enum_type()) { + field->enum_type()) { field->default_value_enum_ = default_value.enum_value_descriptor; } else { AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::DEFAULT_VALUE, "Enum type \"" + field->enum_type()->full_name() + - "\" has no value named \"" + proto.default_value() + - "\"."); + "\" has no value named \"" + proto.default_value() + + "\"."); } } } else if (field->enum_type()->value_count() > 0) { @@ -5389,41 +5779,41 @@ void DescriptorBuilder::CrossLinkField( // risk to calling containing_type() or other accessors that will build // dependencies. if (!file_tables_->AddFieldByNumber(field)) { - const FieldDescriptor* conflicting_field = - file_tables_->FindFieldByNumber(field->containing_type(), - field->number()); - string containing_type_name = field->containing_type() == NULL - ? "unknown" - : field->containing_type()->full_name(); + const FieldDescriptor* conflicting_field = file_tables_->FindFieldByNumber( + field->containing_type(), field->number()); + std::string containing_type_name = + field->containing_type() == nullptr + ? "unknown" + : field->containing_type()->full_name(); if (field->is_extension()) { AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, strings::Substitute("Extension number $0 has already been used " - "in \"$1\" by extension \"$2\".", - field->number(), - containing_type_name, - conflicting_field->full_name())); + "in \"$1\" by extension \"$2\".", + field->number(), containing_type_name, + conflicting_field->full_name())); } else { AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, strings::Substitute("Field number $0 has already been used in " - "\"$1\" by field \"$2\".", - field->number(), - containing_type_name, - conflicting_field->name())); + "\"$1\" by field \"$2\".", + field->number(), containing_type_name, + conflicting_field->name())); } } else { if (field->is_extension()) { if (!tables_->AddExtension(field)) { const FieldDescriptor* conflicting_field = tables_->FindExtension(field->containing_type(), field->number()); - string error_msg = strings::Substitute( + std::string containing_type_name = + field->containing_type() == nullptr + ? "unknown" + : field->containing_type()->full_name(); + std::string error_msg = strings::Substitute( "Extension number $0 has already been used in \"$1\" by extension " "\"$2\" defined in $3.", - field->number(), - field->containing_type()->full_name(), - conflicting_field->full_name(), - conflicting_field->file()->name()); + field->number(), containing_type_name, + conflicting_field->full_name(), conflicting_field->file()->name()); // Conflicting extension numbers should be an error. However, before // turning this into an error we need to fix all existing broken // protos first. @@ -5435,9 +5825,9 @@ void DescriptorBuilder::CrossLinkField( } } -void DescriptorBuilder::CrossLinkEnum( - EnumDescriptor* enum_type, const EnumDescriptorProto& proto) { - if (enum_type->options_ == NULL) { +void DescriptorBuilder::CrossLinkEnum(EnumDescriptor* enum_type, + const EnumDescriptorProto& proto) { + if (enum_type->options_ == nullptr) { enum_type->options_ = &EnumOptions::default_instance(); } @@ -5449,14 +5839,14 @@ void DescriptorBuilder::CrossLinkEnum( void DescriptorBuilder::CrossLinkEnumValue( EnumValueDescriptor* enum_value, const EnumValueDescriptorProto& /* proto */) { - if (enum_value->options_ == NULL) { + if (enum_value->options_ == nullptr) { enum_value->options_ = &EnumValueOptions::default_instance(); } } -void DescriptorBuilder::CrossLinkService( - ServiceDescriptor* service, const ServiceDescriptorProto& proto) { - if (service->options_ == NULL) { +void DescriptorBuilder::CrossLinkService(ServiceDescriptor* service, + const ServiceDescriptorProto& proto) { + if (service->options_ == nullptr) { service->options_ = &ServiceOptions::default_instance(); } @@ -5465,9 +5855,9 @@ void DescriptorBuilder::CrossLinkService( } } -void DescriptorBuilder::CrossLinkMethod( - MethodDescriptor* method, const MethodDescriptorProto& proto) { - if (method->options_ == NULL) { +void DescriptorBuilder::CrossLinkMethod(MethodDescriptor* method, + const MethodDescriptorProto& proto) { + if (method->options_ == nullptr) { method->options_ = &MethodOptions::default_instance(); } @@ -5514,10 +5904,10 @@ void DescriptorBuilder::CrossLinkMethod( // ------------------------------------------------------------------- -#define VALIDATE_OPTIONS_FROM_ARRAY(descriptor, array_name, type) \ - for (int i = 0; i < descriptor->array_name##_count(); ++i) { \ - Validate##type##Options(descriptor->array_name##s_ + i, \ - proto.array_name(i)); \ +#define VALIDATE_OPTIONS_FROM_ARRAY(descriptor, array_name, type) \ + for (int i = 0; i < descriptor->array_name##_count(); ++i) { \ + Validate##type##Options(descriptor->array_name##s_ + i, \ + proto.array_name(i)); \ } // Determine if the file uses optimize_for = LITE_RUNTIME, being careful to @@ -5525,7 +5915,7 @@ void DescriptorBuilder::CrossLinkMethod( static bool IsLite(const FileDescriptor* file) { // TODO(kenton): I don't even remember how many of these conditions are // actually possible. I'm just being super-safe. - return file != NULL && + return file != nullptr && &file->options() != &FileOptions::default_instance() && file->options().optimize_for() == FileOptions::LITE_RUNTIME; } @@ -5542,11 +5932,12 @@ void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file, for (int i = 0; i < file->dependency_count(); i++) { if (IsLite(file->dependency(i))) { AddError( - file->name(), proto, - DescriptorPool::ErrorCollector::OTHER, - "Files that do not use optimize_for = LITE_RUNTIME cannot import " - "files which do use this option. This file is not lite, but it " - "imports \"" + file->dependency(i)->name() + "\" which is."); + file->dependency(i)->name(), proto, + DescriptorPool::ErrorCollector::IMPORT, + "Files that do not use optimize_for = LITE_RUNTIME cannot import " + "files which do use this option. This file is not lite, but it " + "imports \"" + + file->dependency(i)->name() + "\" which is."); break; } } @@ -5556,8 +5947,8 @@ void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file, } } -void DescriptorBuilder::ValidateProto3( - FileDescriptor* file, const FileDescriptorProto& proto) { +void DescriptorBuilder::ValidateProto3(FileDescriptor* file, + const FileDescriptorProto& proto) { for (int i = 0; i < file->extension_count(); ++i) { ValidateProto3Field(file->extensions_ + i, proto.extension(i)); } @@ -5569,111 +5960,106 @@ void DescriptorBuilder::ValidateProto3( } } -static string ToLowercaseWithoutUnderscores(const string& name) { - string result; - for (int i = 0; i < name.size(); ++i) { - if (name[i] != '_') { - if (name[i] >= 'A' && name[i] <= 'Z') { - result.push_back(name[i] - 'A' + 'a'); +static std::string ToLowercaseWithoutUnderscores(const std::string& name) { + std::string result; + for (char character : name) { + if (character != '_') { + if (character >= 'A' && character <= 'Z') { + result.push_back(character - 'A' + 'a'); } else { - result.push_back(name[i]); + result.push_back(character); } } } return result; } -void DescriptorBuilder::ValidateProto3Message( - Descriptor* message, const DescriptorProto& proto) { +void DescriptorBuilder::ValidateProto3Message(Descriptor* message, + const DescriptorProto& proto) { for (int i = 0; i < message->nested_type_count(); ++i) { - ValidateProto3Message(message->nested_types_ + i, - proto.nested_type(i)); + ValidateProto3Message(message->nested_types_ + i, proto.nested_type(i)); } for (int i = 0; i < message->enum_type_count(); ++i) { - ValidateProto3Enum(message->enum_types_ + i, - proto.enum_type(i)); + ValidateProto3Enum(message->enum_types_ + i, proto.enum_type(i)); } for (int i = 0; i < message->field_count(); ++i) { ValidateProto3Field(message->fields_ + i, proto.field(i)); } for (int i = 0; i < message->extension_count(); ++i) { - ValidateProto3Field(message->extensions_ +i, proto.extension(i)); + ValidateProto3Field(message->extensions_ + i, proto.extension(i)); } if (message->extension_range_count() > 0) { - AddError(message->full_name(), proto, - DescriptorPool::ErrorCollector::OTHER, + AddError(message->full_name(), proto.extension_range(0), + DescriptorPool::ErrorCollector::NUMBER, "Extension ranges are not allowed in proto3."); } if (message->options().message_set_wire_format()) { // Using MessageSet doesn't make sense since we disallow extensions. - AddError(message->full_name(), proto, - DescriptorPool::ErrorCollector::OTHER, + AddError(message->full_name(), proto, DescriptorPool::ErrorCollector::NAME, "MessageSet is not supported in proto3."); } // In proto3, we reject field names if they conflict in camelCase. // Note that we currently enforce a stricter rule: Field names must be // unique after being converted to lowercase with underscores removed. - std::map name_to_field; + std::map name_to_field; for (int i = 0; i < message->field_count(); ++i) { - string lowercase_name = ToLowercaseWithoutUnderscores( - message->field(i)->name()); + std::string lowercase_name = + ToLowercaseWithoutUnderscores(message->field(i)->name()); if (name_to_field.find(lowercase_name) != name_to_field.end()) { - AddError(message->full_name(), proto, - DescriptorPool::ErrorCollector::OTHER, + AddError(message->full_name(), proto.field(i), + DescriptorPool::ErrorCollector::NAME, "The JSON camel-case name of field \"" + - message->field(i)->name() + "\" conflicts with field \"" + - name_to_field[lowercase_name]->name() + "\". This is not " + - "allowed in proto3."); + message->field(i)->name() + "\" conflicts with field \"" + + name_to_field[lowercase_name]->name() + "\". This is not " + + "allowed in proto3."); } else { name_to_field[lowercase_name] = message->field(i); } } } -void DescriptorBuilder::ValidateProto3Field( - FieldDescriptor* field, const FieldDescriptorProto& proto) { +void DescriptorBuilder::ValidateProto3Field(FieldDescriptor* field, + const FieldDescriptorProto& proto) { if (field->is_extension() && !AllowedExtendeeInProto3(field->containing_type()->full_name())) { AddError(field->full_name(), proto, - DescriptorPool::ErrorCollector::OTHER, + DescriptorPool::ErrorCollector::EXTENDEE, "Extensions in proto3 are only allowed for defining options."); } if (field->is_required()) { - AddError(field->full_name(), proto, - DescriptorPool::ErrorCollector::OTHER, + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, "Required fields are not allowed in proto3."); } if (field->has_default_value()) { - AddError( - field->full_name(), proto, DescriptorPool::ErrorCollector::OTHER, - "Explicit default values are not allowed in proto3."); + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Explicit default values are not allowed in proto3."); } if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM && field->enum_type() && - field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_PROTO3) { + field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_PROTO3 && + field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_UNKNOWN) { // Proto3 messages can only use Proto3 enum types; otherwise we can't // guarantee that the default value is zero. - AddError(field->full_name(), proto, - DescriptorPool::ErrorCollector::TYPE, + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, "Enum type \"" + field->enum_type()->full_name() + - "\" is not a proto3 enum, but is used in \"" + - field->containing_type()->full_name() + - "\" which is a proto3 message type."); + "\" is not a proto3 enum, but is used in \"" + + field->containing_type()->full_name() + + "\" which is a proto3 message type."); } if (field->type() == FieldDescriptor::TYPE_GROUP) { - AddError(field->full_name(), proto, - DescriptorPool::ErrorCollector::TYPE, + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, "Groups are not supported in proto3 syntax."); } } -void DescriptorBuilder::ValidateProto3Enum( - EnumDescriptor* enm, const EnumDescriptorProto& proto) { +void DescriptorBuilder::ValidateProto3Enum(EnumDescriptor* enm, + const EnumDescriptorProto& proto) { if (enm->value_count() > 0 && enm->value(0)->number() != 0) { - AddError( - enm->full_name(), proto, DescriptorPool::ErrorCollector::OTHER, - "The first enum value must be zero in proto3."); + AddError(enm->full_name(), proto.value(0), + DescriptorPool::ErrorCollector::NUMBER, + "The first enum value must be zero in proto3."); } } @@ -5685,31 +6071,33 @@ void DescriptorBuilder::ValidateMessageOptions(Descriptor* message, VALIDATE_OPTIONS_FROM_ARRAY(message, extension, Field); const int64 max_extension_range = - static_cast(message->options().message_set_wire_format() ? - kint32max : - FieldDescriptor::kMaxNumber); + static_cast(message->options().message_set_wire_format() + ? kint32max + : FieldDescriptor::kMaxNumber); for (int i = 0; i < message->extension_range_count(); ++i) { if (message->extension_range(i)->end > max_extension_range + 1) { - AddError( - message->full_name(), proto.extension_range(i), - DescriptorPool::ErrorCollector::NUMBER, - strings::Substitute("Extension numbers cannot be greater than $0.", - max_extension_range)); + AddError(message->full_name(), proto.extension_range(i), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Extension numbers cannot be greater than $0.", + max_extension_range)); } + + ValidateExtensionRangeOptions(message->full_name(), + message->extension_ranges_ + i, + proto.extension_range(i)); } } -void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field, - const FieldDescriptorProto& proto) { +void DescriptorBuilder::ValidateFieldOptions( + FieldDescriptor* field, const FieldDescriptorProto& proto) { if (pool_->lazily_build_dependencies_ && (!field || !field->message_type())) { return; } // Only message type fields may be lazy. if (field->options().lazy()) { if (field->type() != FieldDescriptor::TYPE_MESSAGE) { - AddError(field->full_name(), proto, - DescriptorPool::ErrorCollector::TYPE, + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, "[lazy = true] can only be specified for submessage fields."); } } @@ -5717,16 +6105,15 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field, // Only repeated primitive fields may be packed. if (field->options().packed() && !field->is_packable()) { AddError( - field->full_name(), proto, - DescriptorPool::ErrorCollector::TYPE, - "[packed = true] can only be specified for repeated primitive fields."); + field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "[packed = true] can only be specified for repeated primitive fields."); } // Note: Default instance may not yet be initialized here, so we have to // avoid reading from it. - if (field->containing_type_ != NULL && + if (field->containing_type_ != nullptr && &field->containing_type()->options() != - &MessageOptions::default_instance() && + &MessageOptions::default_instance() && field->containing_type()->options().message_set_wire_format()) { if (field->is_extension()) { if (!field->is_optional() || @@ -5736,15 +6123,13 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field, "Extensions of MessageSets must be optional messages."); } } else { - AddError(field->full_name(), proto, - DescriptorPool::ErrorCollector::NAME, + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME, "MessageSets cannot have fields, only extensions."); } } // Lite extensions can only be of Lite types. - if (IsLite(field->file()) && - field->containing_type_ != NULL && + if (IsLite(field->file()) && field->containing_type_ != nullptr && !IsLite(field->containing_type()->file())) { AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::EXTENDEE, @@ -5756,8 +6141,7 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field, // Validate map types. if (field->is_map()) { if (!ValidateMapEntry(field, proto)) { - AddError(field->full_name(), proto, - DescriptorPool::ErrorCollector::OTHER, + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, "map_entry should not be set explicitly. Use map instead."); } @@ -5765,30 +6149,43 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field, ValidateJSType(field, proto); + // json_name option is not allowed on extension fields. Note that the + // json_name field in FieldDescriptorProto is always populated by protoc + // when it sends descriptor data to plugins (calculated from field name if + // the option is not explicitly set) so we can't rely on its presence to + // determine whether the json_name option is set on the field. Here we + // compare it against the default calculated json_name value and consider + // the option set if they are different. This won't catch the case when + // an user explicitly sets json_name to the default value, but should be + // good enough to catch common misuses. + if (field->is_extension() && + (field->has_json_name() && + field->json_name() != ToJsonName(field->name()))) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::OPTION_NAME, + "option json_name is not allowed on extension fields."); + } + } void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm, const EnumDescriptorProto& proto) { VALIDATE_OPTIONS_FROM_ARRAY(enm, value, EnumValue); if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) { - std::map used_values; + std::map used_values; for (int i = 0; i < enm->value_count(); ++i) { const EnumValueDescriptor* enum_value = enm->value(i); if (used_values.find(enum_value->number()) != used_values.end()) { - string error = + std::string error = "\"" + enum_value->full_name() + "\" uses the same enum value as \"" + - used_values[enum_value->number()] + "\". If this is intended, set " + used_values[enum_value->number()] + + "\". If this is intended, set " "'option allow_alias = true;' to the enum definition."; if (!enm->options().allow_alias()) { // Generate error if duplicated enum values are explicitly disallowed. - AddError(enm->full_name(), proto, - DescriptorPool::ErrorCollector::NUMBER, - error); - } else { - // Generate warning if duplicated values are found but the option - // isn't set. - GOOGLE_LOG(ERROR) << error; + AddError(enm->full_name(), proto.value(i), + DescriptorPool::ErrorCollector::NUMBER, error); } } else { used_values[enum_value->number()] = enum_value->full_name(); @@ -5802,31 +6199,36 @@ void DescriptorBuilder::ValidateEnumValueOptions( const EnumValueDescriptorProto& /* proto */) { // Nothing to do so far. } -void DescriptorBuilder::ValidateServiceOptions(ServiceDescriptor* service, - const ServiceDescriptorProto& proto) { + +void DescriptorBuilder::ValidateExtensionRangeOptions( + const std::string& full_name, Descriptor::ExtensionRange* extension_range, + const DescriptorProto_ExtensionRange& proto) { +} + +void DescriptorBuilder::ValidateServiceOptions( + ServiceDescriptor* service, const ServiceDescriptorProto& proto) { if (IsLite(service->file()) && (service->file()->options().cc_generic_services() || service->file()->options().java_generic_services())) { - AddError(service->full_name(), proto, - DescriptorPool::ErrorCollector::NAME, + AddError(service->full_name(), proto, DescriptorPool::ErrorCollector::NAME, "Files with optimize_for = LITE_RUNTIME cannot define services " "unless you set both options cc_generic_services and " - "java_generic_sevices to false."); + "java_generic_services to false."); } VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method); } -void DescriptorBuilder::ValidateMethodOptions(MethodDescriptor* /* method */, - const MethodDescriptorProto& /* proto */) { +void DescriptorBuilder::ValidateMethodOptions( + MethodDescriptor* /* method */, const MethodDescriptorProto& /* proto */) { // Nothing to do so far. } bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field, const FieldDescriptorProto& proto) { const Descriptor* message = field->message_type(); - if (// Must not contain extensions, extension range or nested message or - // enums + if ( // Must not contain extensions, extension range or nested message or + // enums message->extension_count() != 0 || field->label() != FieldDescriptor::LABEL_REPEATED || message->extension_range_count() != 0 || @@ -5840,8 +6242,8 @@ bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field, return false; } - const FieldDescriptor* key = message->field(0); - const FieldDescriptor* value = message->field(1); + const FieldDescriptor* key = message->map_key(); + const FieldDescriptor* value = message->map_value(); if (key->label() != FieldDescriptor::LABEL_OPTIONAL || key->number() != 1 || key->name() != "key") { return false; @@ -5854,9 +6256,8 @@ bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field, // Check key types are legal. switch (key->type()) { case FieldDescriptor::TYPE_ENUM: - AddError( - field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, - "Key in map fields cannot be enum types."); + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Key in map fields cannot be enum types."); break; case FieldDescriptor::TYPE_FLOAT: case FieldDescriptor::TYPE_DOUBLE: @@ -5881,15 +6282,14 @@ bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field, case FieldDescriptor::TYPE_SFIXED64: // Legal cases break; - // Do not add a default, so that the compiler will complain when new types - // are added. + // Do not add a default, so that the compiler will complain when new types + // are added. } if (value->type() == FieldDescriptor::TYPE_ENUM) { if (value->enum_type()->value(0)->number() != 0) { - AddError( - field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, - "Enum value in map must define 0 as the first value."); + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Enum value in map must define 0 as the first value."); } } @@ -5898,10 +6298,10 @@ bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field, void DescriptorBuilder::DetectMapConflicts(const Descriptor* message, const DescriptorProto& proto) { - std::map seen_types; + std::map seen_types; for (int i = 0; i < message->nested_type_count(); ++i) { const Descriptor* nested = message->nested_type(i); - std::pair::iterator, bool> result = + std::pair::iterator, bool> result = seen_types.insert(std::make_pair(nested->name(), nested)); if (!result.second) { if (result.first->second->options().map_entry() || @@ -5909,7 +6309,7 @@ void DescriptorBuilder::DetectMapConflicts(const Descriptor* message, AddError(message->full_name(), proto, DescriptorPool::ErrorCollector::NAME, "Expanded map entry type " + nested->name() + - " conflicts with an existing nested message type."); + " conflicts with an existing nested message type."); } } // Recursively test on the nested types. @@ -5918,37 +6318,37 @@ void DescriptorBuilder::DetectMapConflicts(const Descriptor* message, // Check for conflicted field names. for (int i = 0; i < message->field_count(); ++i) { const FieldDescriptor* field = message->field(i); - std::map::iterator iter = + std::map::iterator iter = seen_types.find(field->name()); if (iter != seen_types.end() && iter->second->options().map_entry()) { AddError(message->full_name(), proto, DescriptorPool::ErrorCollector::NAME, "Expanded map entry type " + iter->second->name() + - " conflicts with an existing field."); + " conflicts with an existing field."); } } // Check for conflicted enum names. for (int i = 0; i < message->enum_type_count(); ++i) { const EnumDescriptor* enum_desc = message->enum_type(i); - std::map::iterator iter = + std::map::iterator iter = seen_types.find(enum_desc->name()); if (iter != seen_types.end() && iter->second->options().map_entry()) { AddError(message->full_name(), proto, DescriptorPool::ErrorCollector::NAME, "Expanded map entry type " + iter->second->name() + - " conflicts with an existing enum type."); + " conflicts with an existing enum type."); } } // Check for conflicted oneof names. for (int i = 0; i < message->oneof_decl_count(); ++i) { const OneofDescriptor* oneof_desc = message->oneof_decl(i); - std::map::iterator iter = + std::map::iterator iter = seen_types.find(oneof_desc->name()); if (iter != seen_types.end() && iter->second->options().map_entry()) { AddError(message->full_name(), proto, DescriptorPool::ErrorCollector::NAME, "Expanded map entry type " + iter->second->name() + - " conflicts with an existing oneof type."); + " conflicts with an existing oneof type."); } } } @@ -5976,7 +6376,7 @@ void DescriptorBuilder::ValidateJSType(FieldDescriptor* field, AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, "Illegal jstype for int64, uint64, sint64, fixed64 " "or sfixed64 field: " + - FieldOptions_JSType_descriptor()->value(jstype)->name()); + FieldOptions_JSType_descriptor()->value(jstype)->name()); break; // No other types permit a jstype option. @@ -5993,12 +6393,12 @@ void DescriptorBuilder::ValidateJSType(FieldDescriptor* field, // ------------------------------------------------------------------- DescriptorBuilder::OptionInterpreter::OptionInterpreter( - DescriptorBuilder* builder) : builder_(builder) { + DescriptorBuilder* builder) + : builder_(builder) { GOOGLE_CHECK(builder_); } -DescriptorBuilder::OptionInterpreter::~OptionInterpreter() { -} +DescriptorBuilder::OptionInterpreter::~OptionInterpreter() {} bool DescriptorBuilder::OptionInterpreter::InterpretOptions( OptionsToInterpret* options_to_interpret) { @@ -6014,32 +6414,39 @@ bool DescriptorBuilder::OptionInterpreter::InterpretOptions( // and clear them, since we're about to interpret them. const FieldDescriptor* uninterpreted_options_field = options->GetDescriptor()->FindFieldByName("uninterpreted_option"); - GOOGLE_CHECK(uninterpreted_options_field != NULL) + GOOGLE_CHECK(uninterpreted_options_field != nullptr) << "No field named \"uninterpreted_option\" in the Options proto."; options->GetReflection()->ClearField(options, uninterpreted_options_field); + std::vector src_path = options_to_interpret->element_path; + src_path.push_back(uninterpreted_options_field->number()); + // Find the uninterpreted_option field in the original options. const FieldDescriptor* original_uninterpreted_options_field = - original_options->GetDescriptor()-> - FindFieldByName("uninterpreted_option"); - GOOGLE_CHECK(original_uninterpreted_options_field != NULL) + original_options->GetDescriptor()->FindFieldByName( + "uninterpreted_option"); + GOOGLE_CHECK(original_uninterpreted_options_field != nullptr) << "No field named \"uninterpreted_option\" in the Options proto."; - const int num_uninterpreted_options = original_options->GetReflection()-> - FieldSize(*original_options, original_uninterpreted_options_field); + const int num_uninterpreted_options = + original_options->GetReflection()->FieldSize( + *original_options, original_uninterpreted_options_field); for (int i = 0; i < num_uninterpreted_options; ++i) { + src_path.push_back(i); uninterpreted_option_ = down_cast( &original_options->GetReflection()->GetRepeatedMessage( *original_options, original_uninterpreted_options_field, i)); - if (!InterpretSingleOption(options)) { + if (!InterpretSingleOption(options, src_path, + options_to_interpret->element_path)) { // Error already added by InterpretSingleOption(). failed = true; break; } + src_path.pop_back(); } // Reset these, so we don't have any dangling pointers. - uninterpreted_option_ = NULL; - options_to_interpret_ = NULL; + uninterpreted_option_ = nullptr; + options_to_interpret_ = nullptr; if (!failed) { // InterpretSingleOption() added the interpreted options in the @@ -6050,25 +6457,35 @@ bool DescriptorBuilder::OptionInterpreter::InterpretOptions( // If they are not known, that's OK too. They will get reparsed into the // UnknownFieldSet and wait there until the message is parsed by something // that does know about the options. - string buf; - GOOGLE_CHECK(options->AppendPartialToString(&buf)) - << "Protocol message could not be serialized."; - GOOGLE_CHECK(options->ParsePartialFromString(buf)) - << "Protocol message serialized itself in invalid fashion."; - if (!options->IsInitialized()) { - builder_->AddWarning( + + // Keep the unparsed options around in case the reparsing fails. + std::unique_ptr unparsed_options(options->New()); + options->GetReflection()->Swap(unparsed_options.get(), options); + + std::string buf; + if (!unparsed_options->AppendToString(&buf) || + !options->ParseFromString(buf)) { + builder_->AddError( options_to_interpret->element_name, *original_options, DescriptorPool::ErrorCollector::OTHER, - "Options could not be fully parsed using the proto descriptors " - "compiled into this binary. Missing required fields: " + - options->InitializationErrorString()); + "Some options could not be correctly parsed using the proto " + "descriptors compiled into this binary.\n" + "Unparsed options: " + + unparsed_options->ShortDebugString() + + "\n" + "Parsing attempt: " + + options->ShortDebugString()); + // Restore the unparsed options. + options->GetReflection()->Swap(unparsed_options.get(), options); } } + return !failed; } bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( - Message* options) { + Message* options, const std::vector& src_path, + const std::vector& options_path) { // First do some basic validation. if (uninterpreted_option_->name_size() == 0) { // This should never happen unless the parser has gone seriously awry or @@ -6076,15 +6493,16 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( return AddNameError("Option must have a name."); } if (uninterpreted_option_->name(0).name_part() == "uninterpreted_option") { - return AddNameError("Option must not use reserved name " - "\"uninterpreted_option\"."); + return AddNameError( + "Option must not use reserved name " + "\"uninterpreted_option\"."); } - const Descriptor* options_descriptor = NULL; + const Descriptor* options_descriptor = nullptr; // Get the options message's descriptor from the builder's pool, so that we - // get the version that knows about any extension options declared in the - // file we're currently building. The descriptor should be there as long as - // the file we're building imported "google/protobuf/descriptors.proto". + // get the version that knows about any extension options declared in the file + // we're currently building. The descriptor should be there as long as the + // file we're building imported descriptor.proto. // Note that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not // DescriptorPool::FindMessageTypeByName() because we're already holding the @@ -6092,7 +6510,7 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( // FindSymbol() because files that use custom options only need to depend on // the file that defines the option, not descriptor.proto itself. Symbol symbol = builder_->FindSymbolNotEnforcingDeps( - options->GetDescriptor()->full_name()); + options->GetDescriptor()->full_name()); if (!symbol.IsNull() && symbol.type == Symbol::MESSAGE) { options_descriptor = symbol.descriptor; } else { @@ -6110,12 +6528,15 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( // through in |intermediate_fields|. As we go, we reconstruct the full option // name in |debug_msg_name|, for use in error messages. const Descriptor* descriptor = options_descriptor; - const FieldDescriptor* field = NULL; + const FieldDescriptor* field = nullptr; std::vector intermediate_fields; - string debug_msg_name = ""; + std::string debug_msg_name = ""; + + std::vector dest_path = options_path; for (int i = 0; i < uninterpreted_option_->name_size(); ++i) { - const string& name_part = uninterpreted_option_->name(i).name_part(); + builder_->undefine_resolved_name_.clear(); + const std::string& name_part = uninterpreted_option_->name(i).name_part(); if (debug_msg_name.size() > 0) { debug_msg_name += "."; } @@ -6126,8 +6547,8 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( // DescriptorPool::FindExtensionByName(), for two reasons: 1) It allows // relative lookups, and 2) because we're already holding the pool's // mutex, and the latter method locks it again. - symbol = builder_->LookupSymbol(name_part, - options_to_interpret_->name_scope); + symbol = + builder_->LookupSymbol(name_part, options_to_interpret_->name_scope); if (!symbol.IsNull() && symbol.type == Symbol::FIELD) { field = symbol.field_descriptor; } @@ -6141,7 +6562,7 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( field = descriptor->FindFieldByName(name_part); } - if (field == NULL) { + if (field == nullptr) { if (get_allow_unknown(builder_->pool_)) { // We can't find the option, but AllowUnknownDependencies() is enabled, // so we will just leave it as uninterpreted. @@ -6157,7 +6578,10 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( debug_msg_name.substr(1) + "\") to start from the outermost scope."); } else { - return AddNameError("Option \"" + debug_msg_name + "\" unknown."); + return AddNameError( + "Option \"" + debug_msg_name + + "\" unknown. Ensure that your proto" + + " definition file imports the proto which defines the option."); } } else if (field->containing_type() != descriptor) { if (get_is_placeholder(field->containing_type())) { @@ -6176,19 +6600,24 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( "\" is not a field or extension of message \"" + descriptor->name() + "\"."); } - } else if (i < uninterpreted_option_->name_size() - 1) { - if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { - return AddNameError("Option \"" + debug_msg_name + - "\" is an atomic type, not a message."); - } else if (field->is_repeated()) { - return AddNameError("Option field \"" + debug_msg_name + - "\" is a repeated message. Repeated message " - "options must be initialized using an " - "aggregate value."); - } else { - // Drill down into the submessage. - intermediate_fields.push_back(field); - descriptor = field->message_type(); + } else { + // accumulate field numbers to form path to interpreted option + dest_path.push_back(field->number()); + + if (i < uninterpreted_option_->name_size() - 1) { + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + return AddNameError("Option \"" + debug_msg_name + + "\" is an atomic type, not a message."); + } else if (field->is_repeated()) { + return AddNameError("Option field \"" + debug_msg_name + + "\" is a repeated message. Repeated message " + "options must be initialized using an " + "aggregate value."); + } else { + // Drill down into the submessage. + intermediate_fields.push_back(field); + descriptor = field->message_type(); + } } } } @@ -6201,18 +6630,17 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( // known will populate them correctly. // First see if the option is already set. - if (!field->is_repeated() && !ExamineIfOptionIsSet( - intermediate_fields.begin(), - intermediate_fields.end(), - field, debug_msg_name, + if (!field->is_repeated() && + !ExamineIfOptionIsSet( + intermediate_fields.begin(), intermediate_fields.end(), field, + debug_msg_name, options->GetReflection()->GetUnknownFields(*options))) { return false; // ExamineIfOptionIsSet() already added the error. } - // First set the value on the UnknownFieldSet corresponding to the // innermost message. - google::protobuf::scoped_ptr unknown_fields(new UnknownFieldSet()); + std::unique_ptr unknown_fields(new UnknownFieldSet()); if (!SetOptionValue(field, unknown_fields.get())) { return false; // SetOptionValue() already added the error. } @@ -6222,7 +6650,7 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( for (std::vector::reverse_iterator iter = intermediate_fields.rbegin(); iter != intermediate_fields.rend(); ++iter) { - google::protobuf::scoped_ptr parent_unknown_fields( + std::unique_ptr parent_unknown_fields( new UnknownFieldSet()); switch ((*iter)->type()) { case FieldDescriptor::TYPE_MESSAGE: { @@ -6237,8 +6665,8 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( } case FieldDescriptor::TYPE_GROUP: { - parent_unknown_fields->AddGroup((*iter)->number()) - ->MergeFrom(*unknown_fields); + parent_unknown_fields->AddGroup((*iter)->number()) + ->MergeFrom(*unknown_fields); break; } @@ -6255,24 +6683,125 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( options->GetReflection()->MutableUnknownFields(options)->MergeFrom( *unknown_fields); + // record the element path of the interpreted option + if (field->is_repeated()) { + int index = repeated_option_counts_[dest_path]++; + dest_path.push_back(index); + } + interpreted_paths_[src_path] = dest_path; + return true; } +void DescriptorBuilder::OptionInterpreter::UpdateSourceCodeInfo( + SourceCodeInfo* info) { + if (interpreted_paths_.empty()) { + // nothing to do! + return; + } + + // We find locations that match keys in interpreted_paths_ and + // 1) replace the path with the corresponding value in interpreted_paths_ + // 2) remove any subsequent sub-locations (sub-location is one whose path + // has the parent path as a prefix) + // + // To avoid quadratic behavior of removing interior rows as we go, + // we keep a copy. But we don't actually copy anything until we've + // found the first match (so if the source code info has no locations + // that need to be changed, there is zero copy overhead). + + RepeatedPtrField* locs = info->mutable_location(); + RepeatedPtrField new_locs; + bool copying = false; + + std::vector pathv; + bool matched = false; + + for (RepeatedPtrField::iterator loc = locs->begin(); + loc != locs->end(); loc++) { + if (matched) { + // see if this location is in the range to remove + bool loc_matches = true; + if (loc->path_size() < static_cast(pathv.size())) { + loc_matches = false; + } else { + for (size_t j = 0; j < pathv.size(); j++) { + if (loc->path(j) != pathv[j]) { + loc_matches = false; + break; + } + } + } + + if (loc_matches) { + // don't copy this row since it is a sub-location that we're removing + continue; + } + + matched = false; + } + + pathv.clear(); + for (int j = 0; j < loc->path_size(); j++) { + pathv.push_back(loc->path(j)); + } + + std::map, std::vector>::iterator entry = + interpreted_paths_.find(pathv); + + if (entry == interpreted_paths_.end()) { + // not a match + if (copying) { + *new_locs.Add() = *loc; + } + continue; + } + + matched = true; + + if (!copying) { + // initialize the copy we are building + copying = true; + new_locs.Reserve(locs->size()); + for (RepeatedPtrField::iterator it = + locs->begin(); + it != loc; it++) { + *new_locs.Add() = *it; + } + } + + // add replacement and update its path + SourceCodeInfo_Location* replacement = new_locs.Add(); + *replacement = *loc; + replacement->clear_path(); + for (std::vector::iterator rit = entry->second.begin(); + rit != entry->second.end(); rit++) { + replacement->add_path(*rit); + } + } + + // if we made a changed copy, put it in place + if (copying) { + *locs = new_locs; + } +} + void DescriptorBuilder::OptionInterpreter::AddWithoutInterpreting( const UninterpretedOption& uninterpreted_option, Message* options) { const FieldDescriptor* field = - options->GetDescriptor()->FindFieldByName("uninterpreted_option"); - GOOGLE_CHECK(field != NULL); + options->GetDescriptor()->FindFieldByName("uninterpreted_option"); + GOOGLE_CHECK(field != nullptr); - options->GetReflection()->AddMessage(options, field) - ->CopyFrom(uninterpreted_option); + options->GetReflection() + ->AddMessage(options, field) + ->CopyFrom(uninterpreted_option); } bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet( std::vector::const_iterator intermediate_fields_iter, std::vector::const_iterator intermediate_fields_end, - const FieldDescriptor* innermost_field, const string& debug_msg_name, + const FieldDescriptor* innermost_field, const std::string& debug_msg_name, const UnknownFieldSet& unknown_fields) { // We do linear searches of the UnknownFieldSet and its sub-groups. This // should be fine since it's unlikely that any one options structure will @@ -6302,8 +6831,8 @@ bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet( if (intermediate_unknown_fields.ParseFromString( unknown_field->length_delimited()) && !ExamineIfOptionIsSet(intermediate_fields_iter + 1, - intermediate_fields_end, - innermost_field, debug_msg_name, + intermediate_fields_end, innermost_field, + debug_msg_name, intermediate_unknown_fields)) { return false; // Error already added. } @@ -6313,9 +6842,8 @@ bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet( case FieldDescriptor::TYPE_GROUP: if (unknown_field->type() == UnknownField::TYPE_GROUP) { if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1, - intermediate_fields_end, - innermost_field, debug_msg_name, - unknown_field->group())) { + intermediate_fields_end, innermost_field, + debug_msg_name, unknown_field->group())) { return false; // Error already added. } } @@ -6331,11 +6859,9 @@ bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet( } bool DescriptorBuilder::OptionInterpreter::SetOptionValue( - const FieldDescriptor* option_field, - UnknownFieldSet* unknown_fields) { + const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) { // We switch on the CppType to validate. switch (option_field->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: if (uninterpreted_option_->has_positive_int_value()) { if (uninterpreted_option_->positive_int_value() > @@ -6395,8 +6921,10 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue( option_field->type(), unknown_fields); } } else { - return AddValueError("Value must be non-negative integer for uint32 " - "option \"" + option_field->full_name() + "\"."); + return AddValueError( + "Value must be non-negative integer for uint32 " + "option \"" + + option_field->full_name() + "\"."); } break; @@ -6406,8 +6934,10 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue( uninterpreted_option_->positive_int_value(), option_field->type(), unknown_fields); } else { - return AddValueError("Value must be non-negative integer for uint64 " - "option \"" + option_field->full_name() + "\"."); + return AddValueError( + "Value must be non-negative integer for uint64 " + "option \"" + + option_field->full_name() + "\"."); } break; @@ -6424,7 +6954,7 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue( option_field->full_name() + "\"."); } unknown_fields->AddFixed32(option_field->number(), - google::protobuf::internal::WireFormatLite::EncodeFloat(value)); + internal::WireFormatLite::EncodeFloat(value)); break; } @@ -6441,40 +6971,46 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue( option_field->full_name() + "\"."); } unknown_fields->AddFixed64(option_field->number(), - google::protobuf::internal::WireFormatLite::EncodeDouble(value)); + internal::WireFormatLite::EncodeDouble(value)); break; } case FieldDescriptor::CPPTYPE_BOOL: uint64 value; if (!uninterpreted_option_->has_identifier_value()) { - return AddValueError("Value must be identifier for boolean option " - "\"" + option_field->full_name() + "\"."); + return AddValueError( + "Value must be identifier for boolean option " + "\"" + + option_field->full_name() + "\"."); } if (uninterpreted_option_->identifier_value() == "true") { value = 1; } else if (uninterpreted_option_->identifier_value() == "false") { value = 0; } else { - return AddValueError("Value must be \"true\" or \"false\" for boolean " - "option \"" + option_field->full_name() + "\"."); + return AddValueError( + "Value must be \"true\" or \"false\" for boolean " + "option \"" + + option_field->full_name() + "\"."); } unknown_fields->AddVarint(option_field->number(), value); break; case FieldDescriptor::CPPTYPE_ENUM: { if (!uninterpreted_option_->has_identifier_value()) { - return AddValueError("Value must be identifier for enum-valued option " - "\"" + option_field->full_name() + "\"."); + return AddValueError( + "Value must be identifier for enum-valued option " + "\"" + + option_field->full_name() + "\"."); } const EnumDescriptor* enum_type = option_field->enum_type(); - const string& value_name = uninterpreted_option_->identifier_value(); - const EnumValueDescriptor* enum_value = NULL; + const std::string& value_name = uninterpreted_option_->identifier_value(); + const EnumValueDescriptor* enum_value = nullptr; if (enum_type->file()->pool() != DescriptorPool::generated_pool()) { // Note that the enum value's fully-qualified name is a sibling of the // enum's name, not a child of it. - string fully_qualified_name = enum_type->full_name(); + std::string fully_qualified_name = enum_type->full_name(); fully_qualified_name.resize(fully_qualified_name.size() - enum_type->name().size()); fully_qualified_name += value_name; @@ -6484,10 +7020,11 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue( // DescriptorPool::FindEnumValueByName() because we're already holding // the pool's mutex, and the latter method locks it again. Symbol symbol = - builder_->FindSymbolNotEnforcingDeps(fully_qualified_name); + builder_->FindSymbolNotEnforcingDeps(fully_qualified_name); if (!symbol.IsNull() && symbol.type == Symbol::ENUM_VALUE) { if (symbol.enum_value_descriptor->type() != enum_type) { - return AddValueError("Enum type \"" + enum_type->full_name() + + return AddValueError( + "Enum type \"" + enum_type->full_name() + "\" has no value named \"" + value_name + "\" for option \"" + option_field->full_name() + "\". This appears to be a value from a sibling type."); @@ -6501,28 +7038,33 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue( enum_value = enum_type->FindValueByName(value_name); } - if (enum_value == NULL) { + if (enum_value == nullptr) { return AddValueError("Enum type \"" + option_field->enum_type()->full_name() + - "\" has no value named \"" + value_name + "\" for " - "option \"" + option_field->full_name() + "\"."); + "\" has no value named \"" + value_name + + "\" for " + "option \"" + + option_field->full_name() + "\"."); } else { // Sign-extension is not a problem, since we cast directly from int32 to // uint64, without first going through uint32. - unknown_fields->AddVarint(option_field->number(), - static_cast(static_cast(enum_value->number()))); + unknown_fields->AddVarint( + option_field->number(), + static_cast(static_cast(enum_value->number()))); } break; } case FieldDescriptor::CPPTYPE_STRING: if (!uninterpreted_option_->has_string_value()) { - return AddValueError("Value must be quoted string for string option " - "\"" + option_field->full_name() + "\"."); + return AddValueError( + "Value must be quoted string for string option " + "\"" + + option_field->full_name() + "\"."); } // The string has already been unquoted and unescaped by the parser. unknown_fields->AddLengthDelimited(option_field->number(), - uninterpreted_option_->string_value()); + uninterpreted_option_->string_value()); break; case FieldDescriptor::CPPTYPE_MESSAGE: @@ -6540,12 +7082,24 @@ class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder public: DescriptorBuilder* builder_; - virtual const FieldDescriptor* FindExtension( - Message* message, const string& name) const { + const Descriptor* FindAnyType(const Message& message, + const std::string& prefix, + const std::string& name) const override { + if (prefix != internal::kTypeGoogleApisComPrefix && + prefix != internal::kTypeGoogleProdComPrefix) { + return nullptr; + } + assert_mutex_held(builder_->pool_); + Symbol result = builder_->FindSymbol(name); + return result.type == Symbol::MESSAGE ? result.descriptor : nullptr; + } + + const FieldDescriptor* FindExtension(Message* message, + const std::string& name) const override { assert_mutex_held(builder_->pool_); const Descriptor* descriptor = message->GetDescriptor(); - Symbol result = builder_->LookupSymbolNoPlaceholder( - name, descriptor->full_name()); + Symbol result = + builder_->LookupSymbolNoPlaceholder(name, descriptor->full_name()); if (result.type == Symbol::FIELD && result.field_descriptor->is_extension()) { return result.field_descriptor; @@ -6568,7 +7122,7 @@ class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder } } } - return NULL; + return nullptr; } }; @@ -6576,42 +7130,42 @@ class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder namespace { class AggregateErrorCollector : public io::ErrorCollector { public: - string error_; + std::string error_; - virtual void AddError(int /* line */, int /* column */, - const string& message) { + void AddError(int /* line */, int /* column */, + const std::string& message) override { if (!error_.empty()) { error_ += "; "; } error_ += message; } - virtual void AddWarning(int /* line */, int /* column */, - const string& /* message */) { + void AddWarning(int /* line */, int /* column */, + const std::string& /* message */) override { // Ignore warnings } }; -} +} // namespace // We construct a dynamic message of the type corresponding to // option_field, parse the supplied text-format string into this // message, and serialize the resulting message to produce the value. bool DescriptorBuilder::OptionInterpreter::SetAggregateOption( - const FieldDescriptor* option_field, - UnknownFieldSet* unknown_fields) { + const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) { if (!uninterpreted_option_->has_aggregate_value()) { return AddValueError("Option \"" + option_field->full_name() + "\" is a message. To set the entire message, use " - "syntax like \"" + option_field->name() + + "syntax like \"" + + option_field->name() + " = { }\". " "To set fields within it, use " - "syntax like \"" + option_field->name() + - ".foo = value\"."); + "syntax like \"" + + option_field->name() + ".foo = value\"."); } const Descriptor* type = option_field->message_type(); - google::protobuf::scoped_ptr dynamic(dynamic_factory_.GetPrototype(type)->New()); - GOOGLE_CHECK(dynamic.get() != NULL) + std::unique_ptr dynamic(dynamic_factory_.GetPrototype(type)->New()); + GOOGLE_CHECK(dynamic.get() != nullptr) << "Could not create an instance of " << option_field->DebugString(); AggregateErrorCollector collector; @@ -6626,12 +7180,12 @@ bool DescriptorBuilder::OptionInterpreter::SetAggregateOption( option_field->name() + "\": " + collector.error_); return false; } else { - string serial; + std::string serial; dynamic->SerializeToString(&serial); // Never fails if (option_field->type() == FieldDescriptor::TYPE_MESSAGE) { unknown_fields->AddLengthDelimited(option_field->number(), serial); } else { - GOOGLE_CHECK_EQ(option_field->type(), FieldDescriptor::TYPE_GROUP); + GOOGLE_CHECK_EQ(option_field->type(), FieldDescriptor::TYPE_GROUP); UnknownFieldSet* group = unknown_fields->AddGroup(option_field->number()); group->ParseFromString(serial); } @@ -6639,12 +7193,13 @@ bool DescriptorBuilder::OptionInterpreter::SetAggregateOption( } } -void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value, - FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) { +void DescriptorBuilder::OptionInterpreter::SetInt32( + int number, int32 value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields) { switch (type) { case FieldDescriptor::TYPE_INT32: unknown_fields->AddVarint(number, - static_cast(static_cast(value))); + static_cast(static_cast(value))); break; case FieldDescriptor::TYPE_SFIXED32: @@ -6652,8 +7207,8 @@ void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value, break; case FieldDescriptor::TYPE_SINT32: - unknown_fields->AddVarint(number, - google::protobuf::internal::WireFormatLite::ZigZagEncode32(value)); + unknown_fields->AddVarint( + number, internal::WireFormatLite::ZigZagEncode32(value)); break; default: @@ -6662,8 +7217,9 @@ void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value, } } -void DescriptorBuilder::OptionInterpreter::SetInt64(int number, int64 value, - FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) { +void DescriptorBuilder::OptionInterpreter::SetInt64( + int number, int64 value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields) { switch (type) { case FieldDescriptor::TYPE_INT64: unknown_fields->AddVarint(number, static_cast(value)); @@ -6674,8 +7230,8 @@ void DescriptorBuilder::OptionInterpreter::SetInt64(int number, int64 value, break; case FieldDescriptor::TYPE_SINT64: - unknown_fields->AddVarint(number, - google::protobuf::internal::WireFormatLite::ZigZagEncode64(value)); + unknown_fields->AddVarint( + number, internal::WireFormatLite::ZigZagEncode64(value)); break; default: @@ -6684,8 +7240,9 @@ void DescriptorBuilder::OptionInterpreter::SetInt64(int number, int64 value, } } -void DescriptorBuilder::OptionInterpreter::SetUInt32(int number, uint32 value, - FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) { +void DescriptorBuilder::OptionInterpreter::SetUInt32( + int number, uint32 value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields) { switch (type) { case FieldDescriptor::TYPE_UINT32: unknown_fields->AddVarint(number, static_cast(value)); @@ -6701,8 +7258,9 @@ void DescriptorBuilder::OptionInterpreter::SetUInt32(int number, uint32 value, } } -void DescriptorBuilder::OptionInterpreter::SetUInt64(int number, uint64 value, - FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) { +void DescriptorBuilder::OptionInterpreter::SetUInt64( + int number, uint64 value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields) { switch (type) { case FieldDescriptor::TYPE_UINT64: unknown_fields->AddVarint(number, value); @@ -6722,41 +7280,27 @@ void DescriptorBuilder::LogUnusedDependency(const FileDescriptorProto& proto, const FileDescriptor* result) { if (!unused_dependency_.empty()) { - std::set annotation_extensions; - annotation_extensions.insert("google.protobuf.MessageOptions"); - annotation_extensions.insert("google.protobuf.FileOptions"); - annotation_extensions.insert("google.protobuf.FieldOptions"); - annotation_extensions.insert("google.protobuf.EnumOptions"); - annotation_extensions.insert("google.protobuf.EnumValueOptions"); - annotation_extensions.insert("google.protobuf.EnumValueOptions"); - annotation_extensions.insert("google.protobuf.ServiceOptions"); - annotation_extensions.insert("google.protobuf.MethodOptions"); - annotation_extensions.insert("google.protobuf.StreamOptions"); - for (std::set::const_iterator - it = unused_dependency_.begin(); + auto itr = pool_->unused_import_track_files_.find(proto.name()); + bool is_error = + itr != pool_->unused_import_track_files_.end() && itr->second; + for (std::set::const_iterator it = + unused_dependency_.begin(); it != unused_dependency_.end(); ++it) { - // Do not log warnings for proto files which extend annotations. - int i; - for (i = 0 ; i < (*it)->extension_count(); ++i) { - if (annotation_extensions.find( - (*it)->extension(i)->containing_type()->full_name()) - != annotation_extensions.end()) { - break; - } - } - // Log warnings for unused imported files. - if (i == (*it)->extension_count()) { - string error_message = "Import " + (*it)->name() + " but not used."; - AddWarning((*it)->name(), proto, DescriptorPool::ErrorCollector::OTHER, + std::string error_message = "Import " + (*it)->name() + " is unused."; + if (is_error) { + AddError((*it)->name(), proto, DescriptorPool::ErrorCollector::IMPORT, + error_message); + } else { + AddWarning((*it)->name(), proto, DescriptorPool::ErrorCollector::IMPORT, error_message); } } } } -Symbol DescriptorPool::CrossLinkOnDemandHelper(const string& name, +Symbol DescriptorPool::CrossLinkOnDemandHelper(StringPiece name, bool expecting_enum) const { - string lookup_name = name; + auto lookup_name = std::string(name); if (!lookup_name.empty() && lookup_name[0] == '.') { lookup_name = lookup_name.substr(1); } @@ -6785,10 +7329,10 @@ void FieldDescriptor::InternalTypeOnceInit() const { if (default_value_enum_name_) { // Have to build the full name now instead of at CrossLink time, // because enum_type_ may not be known at the time. - string name = enum_type_->full_name(); + std::string name = enum_type_->full_name(); // Enum values reside in the same scope as the enum type. - string::size_type last_dot = name.find_last_of('.'); - if (last_dot != string::npos) { + std::string::size_type last_dot = name.find_last_of('.'); + if (last_dot != std::string::npos) { name = name.substr(0, last_dot) + "." + *default_value_enum_name_; } else { name = *default_value_enum_name_; @@ -6812,34 +7356,36 @@ void FieldDescriptor::TypeOnceInit(const FieldDescriptor* to_init) { } // message_type(), enum_type(), default_value_enum(), and type() -// all share the same GoogleOnceDynamic init path to do lazy +// all share the same internal::call_once init path to do lazy // import building and cross linking of a field of a message. const Descriptor* FieldDescriptor::message_type() const { if (type_once_) { - type_once_->Init(&FieldDescriptor::TypeOnceInit, this); + internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this); } return message_type_; } const EnumDescriptor* FieldDescriptor::enum_type() const { if (type_once_) { - type_once_->Init(&FieldDescriptor::TypeOnceInit, this); + internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this); } return enum_type_; } const EnumValueDescriptor* FieldDescriptor::default_value_enum() const { if (type_once_) { - type_once_->Init(&FieldDescriptor::TypeOnceInit, this); + internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this); } return default_value_enum_; } -FieldDescriptor::Type FieldDescriptor::type() const { - if (type_once_) { - type_once_->Init(&FieldDescriptor::TypeOnceInit, this); - } - return type_; +const std::string& FieldDescriptor::PrintableNameForExtension() const { + const bool is_message_set_extension = + is_extension() && + containing_type()->options().message_set_wire_format() && + type() == FieldDescriptor::TYPE_MESSAGE && is_optional() && + extension_scope() == message_type(); + return is_message_set_extension ? message_type()->full_name() : full_name(); } void FileDescriptor::InternalDependenciesOnceInit() const { @@ -6857,9 +7403,10 @@ void FileDescriptor::DependenciesOnceInit(const FileDescriptor* to_init) { const FileDescriptor* FileDescriptor::dependency(int index) const { if (dependencies_once_) { - // Do once init for all indicies, as it's unlikely only a single index would - // be called, and saves on GoogleOnceDynamic allocations. - dependencies_once_->Init(&FileDescriptor::DependenciesOnceInit, this); + // Do once init for all indices, as it's unlikely only a single index would + // be called, and saves on internal::call_once allocations. + internal::call_once(*dependencies_once_, + FileDescriptor::DependenciesOnceInit, this); } return dependencies_[index]; } @@ -6881,7 +7428,8 @@ void LazyDescriptor::Set(const Descriptor* descriptor) { descriptor_ = descriptor; } -void LazyDescriptor::SetLazy(const string& name, const FileDescriptor* file) { +void LazyDescriptor::SetLazy(StringPiece name, + const FileDescriptor* file) { // verify Init() has been called and Set hasn't been called yet. GOOGLE_CHECK(!descriptor_); GOOGLE_CHECK(!file_); @@ -6897,7 +7445,7 @@ void LazyDescriptor::SetLazy(const string& name, const FileDescriptor* file) { void LazyDescriptor::Once() { if (once_) { - once_->Init(&LazyDescriptor::OnceStatic, this); + internal::call_once(*once_, LazyDescriptor::OnceStatic, this); } } @@ -6916,3 +7464,5 @@ void LazyDescriptor::OnceInternal() { } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index 57128e6b0aadf..0625b5022156f 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -54,22 +54,29 @@ #ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H__ #define GOOGLE_PROTOBUF_DESCRIPTOR_H__ +#include +#include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include #include + #include #include #include +#include +#include // TYPE_BOOL is defined in the MacOS's ConditionalMacros.h. #ifdef TYPE_BOOL #undef TYPE_BOOL #endif // TYPE_BOOL +#ifdef SWIG +#define PROTOBUF_EXPORT +#endif + + namespace google { namespace protobuf { @@ -87,6 +94,7 @@ class DescriptorPool; // Defined in descriptor.proto class DescriptorProto; +class DescriptorProto_ExtensionRange; class FieldDescriptorProto; class OneofDescriptorProto; class EnumDescriptorProto; @@ -108,6 +116,7 @@ class SourceCodeInfo; // Defined in message.h class Message; +class Reflection; // Defined in descriptor.cc class DescriptorBuilder; @@ -117,14 +126,13 @@ struct Symbol; // Defined in unknown_field_set.h. class UnknownField; -// Defined in generated_message_reflection.h. -namespace internal { -class GeneratedMessageReflection; -} // namespace internal - // Defined in command_line_interface.cc namespace compiler { class CommandLineInterface; +namespace cpp { +// Defined in helpers.h +class Formatter; +} // namespace cpp } // namespace compiler namespace descriptor_unittest { @@ -145,9 +153,9 @@ struct SourceLocation { // Doc comments found at the source location. // See the comments in SourceCodeInfo.Location (descriptor.proto) for details. - string leading_comments; - string trailing_comments; - std::vector leading_detached_comments; + std::string leading_comments; + std::string trailing_comments; + std::vector leading_detached_comments; }; // Options when generating machine-parsable output from a descriptor with @@ -165,7 +173,8 @@ struct DebugStringOptions { DebugStringOptions() : include_comments(false), elide_group_body(false), - elide_oneof_body(false) {} + elide_oneof_body(false) { + } }; // A class to handle the simplest cases of a lazily linked descriptor @@ -173,15 +182,15 @@ struct DebugStringOptions { // which is needed when a pool has lazily_build_dependencies_ set. // Must be instantiated as mutable in a descriptor. namespace internal { -class LIBPROTOBUF_EXPORT LazyDescriptor { +class PROTOBUF_EXPORT LazyDescriptor { public: // Init function to be called at init time of a descriptor containing // a LazyDescriptor. void Init() { - descriptor_ = NULL; - name_ = NULL; - once_ = NULL; - file_ = NULL; + descriptor_ = nullptr; + name_ = nullptr; + once_ = nullptr; + file_ = nullptr; } // Sets the value of the descriptor if it is known during the descriptor @@ -195,7 +204,7 @@ class LIBPROTOBUF_EXPORT LazyDescriptor { // build time if the symbol wasn't found and building of the file containing // that type is delayed because lazily_build_dependencies_ is set on the pool. // Should not be called after Set() has been called. - void SetLazy(const string& name, const FileDescriptor* file); + void SetLazy(StringPiece name, const FileDescriptor* file); // Returns the current value of the descriptor, thread-safe. If SetLazy(...) // has been called, will do a one-time cross link of the type specified, @@ -211,8 +220,8 @@ class LIBPROTOBUF_EXPORT LazyDescriptor { void Once(); const Descriptor* descriptor_; - const string* name_; - GoogleOnceDynamic* once_; + const std::string* name_; + internal::once_flag* once_; const FileDescriptor* file_; }; } // namespace internal @@ -222,34 +231,35 @@ class LIBPROTOBUF_EXPORT LazyDescriptor { // Message::GetDescriptor(). Generated message classes also have a // static method called descriptor() which returns the type's descriptor. // Use DescriptorPool to construct your own descriptors. -class LIBPROTOBUF_EXPORT Descriptor { +class PROTOBUF_EXPORT Descriptor { public: + typedef DescriptorProto Proto; + // The name of the message type, not including its scope. - const string& name() const; + const std::string& name() const; // The fully-qualified name of the message type, scope delimited by // periods. For example, message type "Foo" which is declared in package // "bar" has full name "bar.Foo". If a type "Baz" is nested within // Foo, Baz's full_name is "bar.Foo.Baz". To get only the part that // comes after the last '.', use name(). - const string& full_name() const; + const std::string& full_name() const; // Index of this descriptor within the file or containing type's message // type array. int index() const; - // The .proto file in which this message type was defined. Never NULL. + // The .proto file in which this message type was defined. Never nullptr. const FileDescriptor* file() const; // If this Descriptor describes a nested type, this returns the type - // in which it is nested. Otherwise, returns NULL. + // in which it is nested. Otherwise, returns nullptr. const Descriptor* containing_type() const; // Get options for this message type. These are specified in the .proto file // by placing lines like "option foo = 1234;" in the message definition. - // Allowed options are defined by MessageOptions in - // google/protobuf/descriptor.proto, and any available extensions of that - // message. + // Allowed options are defined by MessageOptions in descriptor.proto, and any + // available extensions of that message. const MessageOptions& options() const; // Write the contents of this Descriptor into the given DescriptorProto. @@ -257,19 +267,49 @@ class LIBPROTOBUF_EXPORT Descriptor { // isn't, the result may be garbage. void CopyTo(DescriptorProto* proto) const; - // Write the contents of this decriptor in a human-readable form. Output + // Write the contents of this descriptor in a human-readable form. Output // will be suitable for re-parsing. - string DebugString() const; + std::string DebugString() const; // Similar to DebugString(), but additionally takes options (e.g., // include original user comments in output). - string DebugStringWithOptions(const DebugStringOptions& options) const; + std::string DebugStringWithOptions(const DebugStringOptions& options) const; // Returns true if this is a placeholder for an unknown type. This will // only be the case if this descriptor comes from a DescriptorPool // with AllowUnknownDependencies() set. bool is_placeholder() const; + enum WellKnownType { + WELLKNOWNTYPE_UNSPECIFIED, // Not a well-known type. + + // Wrapper types. + WELLKNOWNTYPE_DOUBLEVALUE, // google.protobuf.DoubleValue + WELLKNOWNTYPE_FLOATVALUE, // google.protobuf.FloatValue + WELLKNOWNTYPE_INT64VALUE, // google.protobuf.Int64Value + WELLKNOWNTYPE_UINT64VALUE, // google.protobuf.UInt64Value + WELLKNOWNTYPE_INT32VALUE, // google.protobuf.Int32Value + WELLKNOWNTYPE_UINT32VALUE, // google.protobuf.UInt32Value + WELLKNOWNTYPE_STRINGVALUE, // google.protobuf.StringValue + WELLKNOWNTYPE_BYTESVALUE, // google.protobuf.BytesValue + WELLKNOWNTYPE_BOOLVALUE, // google.protobuf.BoolValue + + // Other well known types. + WELLKNOWNTYPE_ANY, // google.protobuf.Any + WELLKNOWNTYPE_FIELDMASK, // google.protobuf.FieldMask + WELLKNOWNTYPE_DURATION, // google.protobuf.Duration + WELLKNOWNTYPE_TIMESTAMP, // google.protobuf.Timestamp + WELLKNOWNTYPE_VALUE, // google.protobuf.Value + WELLKNOWNTYPE_LISTVALUE, // google.protobuf.ListValue + WELLKNOWNTYPE_STRUCT, // google.protobuf.Struct + + // New well-known types may be added in the future. + // Please make sure any switch() statements have a 'default' case. + __WELLKNOWNTYPE__DO_NOT_USE__ADD_DEFAULT_INSTEAD__, + }; + + WellKnownType well_known_type() const; + // Field stuff ----------------------------------------------------- // The number of fields in this message type. @@ -278,33 +318,37 @@ class LIBPROTOBUF_EXPORT Descriptor { // These are returned in the order they were defined in the .proto file. const FieldDescriptor* field(int index) const; - // Looks up a field by declared tag number. Returns NULL if no such field + // Looks up a field by declared tag number. Returns nullptr if no such field // exists. const FieldDescriptor* FindFieldByNumber(int number) const; - // Looks up a field by name. Returns NULL if no such field exists. - const FieldDescriptor* FindFieldByName(const string& name) const; + // Looks up a field by name. Returns nullptr if no such field exists. + const FieldDescriptor* FindFieldByName(ConstStringParam name) const; // Looks up a field by lowercased name (as returned by lowercase_name()). // This lookup may be ambiguous if multiple field names differ only by case, // in which case the field returned is chosen arbitrarily from the matches. const FieldDescriptor* FindFieldByLowercaseName( - const string& lowercase_name) const; + ConstStringParam lowercase_name) const; // Looks up a field by camel-case name (as returned by camelcase_name()). // This lookup may be ambiguous if multiple field names differ in a way that // leads them to have identical camel-case names, in which case the field // returned is chosen arbitrarily from the matches. const FieldDescriptor* FindFieldByCamelcaseName( - const string& camelcase_name) const; + ConstStringParam camelcase_name) const; // The number of oneofs in this message type. int oneof_decl_count() const; + // The number of oneofs in this message type, excluding synthetic oneofs. + // Real oneofs always come first, so iterating up to real_oneof_decl_cout() + // will yield all real oneofs. + int real_oneof_decl_count() const; // Get a oneof by index, where 0 <= index < oneof_decl_count(). // These are returned in the order they were defined in the .proto file. const OneofDescriptor* oneof_decl(int index) const; - // Looks up a oneof by name. Returns NULL if no such oneof exists. - const OneofDescriptor* FindOneofByName(const string& name) const; + // Looks up a oneof by name. Returns nullptr if no such oneof exists. + const OneofDescriptor* FindOneofByName(ConstStringParam name) const; // Nested type stuff ----------------------------------------------- @@ -314,9 +358,9 @@ class LIBPROTOBUF_EXPORT Descriptor { // These are returned in the order they were defined in the .proto file. const Descriptor* nested_type(int index) const; - // Looks up a nested type by name. Returns NULL if no such nested type + // Looks up a nested type by name. Returns nullptr if no such nested type // exists. - const Descriptor* FindNestedTypeByName(const string& name) const; + const Descriptor* FindNestedTypeByName(ConstStringParam name) const; // Enum stuff ------------------------------------------------------ @@ -326,20 +370,26 @@ class LIBPROTOBUF_EXPORT Descriptor { // These are returned in the order they were defined in the .proto file. const EnumDescriptor* enum_type(int index) const; - // Looks up an enum type by name. Returns NULL if no such enum type exists. - const EnumDescriptor* FindEnumTypeByName(const string& name) const; + // Looks up an enum type by name. Returns nullptr if no such enum type + // exists. + const EnumDescriptor* FindEnumTypeByName(ConstStringParam name) const; // Looks up an enum value by name, among all enum types in this message. - // Returns NULL if no such value exists. - const EnumValueDescriptor* FindEnumValueByName(const string& name) const; + // Returns nullptr if no such value exists. + const EnumValueDescriptor* FindEnumValueByName(ConstStringParam name) const; // Extensions ------------------------------------------------------ // A range of field numbers which are designated for third-party // extensions. struct ExtensionRange { + typedef DescriptorProto_ExtensionRange Proto; + typedef ExtensionRangeOptions OptionsType; + // See Descriptor::CopyTo(). + void CopyTo(DescriptorProto_ExtensionRange* proto) const; + int start; // inclusive int end; // exclusive @@ -356,11 +406,33 @@ class LIBPROTOBUF_EXPORT Descriptor { // Returns true if the number is in one of the extension ranges. bool IsExtensionNumber(int number) const; - // Returns NULL if no extension range contains the given number. + // Returns nullptr if no extension range contains the given number. const ExtensionRange* FindExtensionRangeContainingNumber(int number) const; - // The number of extensions -- extending *other* messages -- that were - // defined nested within this message type's scope. + // The number of extensions defined nested within this message type's scope. + // See doc: + // https://developers.google.com/protocol-buffers/docs/proto#nested-extensions + // + // Note that the extensions may be extending *other* messages. + // + // For example: + // message M1 { + // extensions 1 to max; + // } + // + // message M2 { + // extend M1 { + // optional int32 foo = 1; + // } + // } + // + // In this case, + // DescriptorPool::generated_pool() + // ->FindMessageTypeByName("M2") + // ->extension(0) + // will return "foo", even though "foo" is an extension of M1. + // To find all known extensions of a given message, instead use + // DescriptorPool::FindAllExtensions. int extension_count() const; // Get an extension by index, where 0 <= index < extension_count(). // These are returned in the order they were defined in the .proto file. @@ -368,15 +440,17 @@ class LIBPROTOBUF_EXPORT Descriptor { // Looks up a named extension (which extends some *other* message type) // defined within this message type's scope. - const FieldDescriptor* FindExtensionByName(const string& name) const; + const FieldDescriptor* FindExtensionByName(ConstStringParam name) const; // Similar to FindFieldByLowercaseName(), but finds extensions defined within // this message type's scope. - const FieldDescriptor* FindExtensionByLowercaseName(const string& name) const; + const FieldDescriptor* FindExtensionByLowercaseName( + ConstStringParam name) const; // Similar to FindFieldByCamelcaseName(), but finds extensions defined within // this message type's scope. - const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const; + const FieldDescriptor* FindExtensionByCamelcaseName( + ConstStringParam name) const; // Reserved fields ------------------------------------------------- @@ -396,17 +470,17 @@ class LIBPROTOBUF_EXPORT Descriptor { // Returns true if the number is in one of the reserved ranges. bool IsReservedNumber(int number) const; - // Returns NULL if no reserved range contains the given number. + // Returns nullptr if no reserved range contains the given number. const ReservedRange* FindReservedRangeContainingNumber(int number) const; // The number of reserved field names in this message type. int reserved_name_count() const; // Gets a reserved name by index, where 0 <= index < reserved_name_count(). - const string& reserved_name(int index) const; + const std::string& reserved_name(int index) const; // Returns true if the field name is reserved. - bool IsReservedName(const string& name) const; + bool IsReservedName(ConstStringParam name) const; // Source Location --------------------------------------------------- @@ -415,14 +489,25 @@ class LIBPROTOBUF_EXPORT Descriptor { // |*out_location| unchanged iff location information was not available. bool GetSourceLocation(SourceLocation* out_location) const; + // Maps -------------------------------------------------------------- + + // Returns the FieldDescriptor for the "key" field. If this isn't a map entry + // field, returns nullptr. + const FieldDescriptor* map_key() const; + + // Returns the FieldDescriptor for the "value" field. If this isn't a map + // entry field, returns nullptr. + const FieldDescriptor* map_value() const; + private: typedef MessageOptions OptionsType; // Allows tests to test CopyTo(proto, true). - friend class ::google::protobuf::descriptor_unittest::DescriptorTest; + friend class descriptor_unittest::DescriptorTest; // Allows access to GetLocationPath for annotations. - friend class ::google::protobuf::io::Printer; + friend class io::Printer; + friend class compiler::cpp::Formatter; // Fill the json_name field of FieldDescriptorProto. void CopyJsonNameTo(DescriptorProto* proto) const; @@ -431,7 +516,7 @@ class LIBPROTOBUF_EXPORT Descriptor { // correct depth. Takes |options| to control debug-string options, and // |include_opening_clause| to indicate whether the "message ... " part of the // clause has already been generated (this varies depending on context). - void DebugString(int depth, string *contents, + void DebugString(int depth, std::string* contents, const DebugStringOptions& options, bool include_opening_clause) const; @@ -439,8 +524,8 @@ class LIBPROTOBUF_EXPORT Descriptor { // to this descriptor from the file root. void GetLocationPath(std::vector* output) const; - const string* name_; - const string* full_name_; + const std::string* name_; + const std::string* full_name_; const FileDescriptor* file_; const Descriptor* containing_type_; const MessageOptions* options_; @@ -453,10 +538,11 @@ class LIBPROTOBUF_EXPORT Descriptor { ExtensionRange* extension_ranges_; FieldDescriptor* extensions_; ReservedRange* reserved_ranges_; - const string** reserved_names_; + const std::string** reserved_names_; int field_count_; int oneof_decl_count_; + int real_oneof_decl_count_; int nested_type_count_; int enum_type_count_; int extension_range_count_; @@ -468,6 +554,8 @@ class LIBPROTOBUF_EXPORT Descriptor { bool is_placeholder_; // True if this is a placeholder and the type name wasn't fully-qualified. bool is_unqualified_placeholder_; + // Well known type. Stored as char to conserve space. + char well_known_type_; // IMPORTANT: If you add a new field, make sure to search for all instances // of Allocate() and AllocateArray() in descriptor.cc @@ -493,72 +581,72 @@ class LIBPROTOBUF_EXPORT Descriptor { // - Get the Descriptor or FileDescriptor for its containing scope, then // call Descriptor::FindExtensionByName() or // FileDescriptor::FindExtensionByName(). -// - Given a DescriptorPool, call DescriptorPool::FindExtensionByNumber(). -// - Given a Reflection for a message object, call -// Reflection::FindKnownExtensionByName() or -// Reflection::FindKnownExtensionByNumber(). +// - Given a DescriptorPool, call DescriptorPool::FindExtensionByNumber() or +// DescriptorPool::FindExtensionByPrintableName(). // Use DescriptorPool to construct your own descriptors. -class LIBPROTOBUF_EXPORT FieldDescriptor { +class PROTOBUF_EXPORT FieldDescriptor { public: + typedef FieldDescriptorProto Proto; + // Identifies a field type. 0 is reserved for errors. The order is weird // for historical reasons. Types 12 and up are new in proto2. enum Type { - TYPE_DOUBLE = 1, // double, exactly eight bytes on the wire. - TYPE_FLOAT = 2, // float, exactly four bytes on the wire. - TYPE_INT64 = 3, // int64, varint on the wire. Negative numbers - // take 10 bytes. Use TYPE_SINT64 if negative - // values are likely. - TYPE_UINT64 = 4, // uint64, varint on the wire. - TYPE_INT32 = 5, // int32, varint on the wire. Negative numbers - // take 10 bytes. Use TYPE_SINT32 if negative - // values are likely. - TYPE_FIXED64 = 6, // uint64, exactly eight bytes on the wire. - TYPE_FIXED32 = 7, // uint32, exactly four bytes on the wire. - TYPE_BOOL = 8, // bool, varint on the wire. - TYPE_STRING = 9, // UTF-8 text. - TYPE_GROUP = 10, // Tag-delimited message. Deprecated. - TYPE_MESSAGE = 11, // Length-delimited message. - - TYPE_BYTES = 12, // Arbitrary byte array. - TYPE_UINT32 = 13, // uint32, varint on the wire - TYPE_ENUM = 14, // Enum, varint on the wire - TYPE_SFIXED32 = 15, // int32, exactly four bytes on the wire - TYPE_SFIXED64 = 16, // int64, exactly eight bytes on the wire - TYPE_SINT32 = 17, // int32, ZigZag-encoded varint on the wire - TYPE_SINT64 = 18, // int64, ZigZag-encoded varint on the wire - - MAX_TYPE = 18, // Constant useful for defining lookup tables - // indexed by Type. + TYPE_DOUBLE = 1, // double, exactly eight bytes on the wire. + TYPE_FLOAT = 2, // float, exactly four bytes on the wire. + TYPE_INT64 = 3, // int64, varint on the wire. Negative numbers + // take 10 bytes. Use TYPE_SINT64 if negative + // values are likely. + TYPE_UINT64 = 4, // uint64, varint on the wire. + TYPE_INT32 = 5, // int32, varint on the wire. Negative numbers + // take 10 bytes. Use TYPE_SINT32 if negative + // values are likely. + TYPE_FIXED64 = 6, // uint64, exactly eight bytes on the wire. + TYPE_FIXED32 = 7, // uint32, exactly four bytes on the wire. + TYPE_BOOL = 8, // bool, varint on the wire. + TYPE_STRING = 9, // UTF-8 text. + TYPE_GROUP = 10, // Tag-delimited message. Deprecated. + TYPE_MESSAGE = 11, // Length-delimited message. + + TYPE_BYTES = 12, // Arbitrary byte array. + TYPE_UINT32 = 13, // uint32, varint on the wire + TYPE_ENUM = 14, // Enum, varint on the wire + TYPE_SFIXED32 = 15, // int32, exactly four bytes on the wire + TYPE_SFIXED64 = 16, // int64, exactly eight bytes on the wire + TYPE_SINT32 = 17, // int32, ZigZag-encoded varint on the wire + TYPE_SINT64 = 18, // int64, ZigZag-encoded varint on the wire + + MAX_TYPE = 18, // Constant useful for defining lookup tables + // indexed by Type. }; // Specifies the C++ data type used to represent the field. There is a // fixed mapping from Type to CppType where each Type maps to exactly one // CppType. 0 is reserved for errors. enum CppType { - CPPTYPE_INT32 = 1, // TYPE_INT32, TYPE_SINT32, TYPE_SFIXED32 - CPPTYPE_INT64 = 2, // TYPE_INT64, TYPE_SINT64, TYPE_SFIXED64 - CPPTYPE_UINT32 = 3, // TYPE_UINT32, TYPE_FIXED32 - CPPTYPE_UINT64 = 4, // TYPE_UINT64, TYPE_FIXED64 - CPPTYPE_DOUBLE = 5, // TYPE_DOUBLE - CPPTYPE_FLOAT = 6, // TYPE_FLOAT - CPPTYPE_BOOL = 7, // TYPE_BOOL - CPPTYPE_ENUM = 8, // TYPE_ENUM - CPPTYPE_STRING = 9, // TYPE_STRING, TYPE_BYTES - CPPTYPE_MESSAGE = 10, // TYPE_MESSAGE, TYPE_GROUP - - MAX_CPPTYPE = 10, // Constant useful for defining lookup tables - // indexed by CppType. + CPPTYPE_INT32 = 1, // TYPE_INT32, TYPE_SINT32, TYPE_SFIXED32 + CPPTYPE_INT64 = 2, // TYPE_INT64, TYPE_SINT64, TYPE_SFIXED64 + CPPTYPE_UINT32 = 3, // TYPE_UINT32, TYPE_FIXED32 + CPPTYPE_UINT64 = 4, // TYPE_UINT64, TYPE_FIXED64 + CPPTYPE_DOUBLE = 5, // TYPE_DOUBLE + CPPTYPE_FLOAT = 6, // TYPE_FLOAT + CPPTYPE_BOOL = 7, // TYPE_BOOL + CPPTYPE_ENUM = 8, // TYPE_ENUM + CPPTYPE_STRING = 9, // TYPE_STRING, TYPE_BYTES + CPPTYPE_MESSAGE = 10, // TYPE_MESSAGE, TYPE_GROUP + + MAX_CPPTYPE = 10, // Constant useful for defining lookup tables + // indexed by CppType. }; // Identifies whether the field is optional, required, or repeated. 0 is // reserved for errors. enum Label { - LABEL_OPTIONAL = 1, // optional - LABEL_REQUIRED = 2, // required - LABEL_REPEATED = 3, // repeated + LABEL_OPTIONAL = 1, // optional + LABEL_REQUIRED = 2, // required + LABEL_REPEATED = 3, // repeated - MAX_LABEL = 3, // Constant useful for defining lookup tables - // indexed by Label. + MAX_LABEL = 3, // Constant useful for defining lookup tables + // indexed by Label. }; // Valid field numbers are positive integers up to kMaxNumber. @@ -569,14 +657,14 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { static const int kFirstReservedNumber = 19000; // Last field number reserved for the protocol buffer library implementation. // Users may not declare fields that use reserved numbers. - static const int kLastReservedNumber = 19999; + static const int kLastReservedNumber = 19999; - const string& name() const; // Name of this field within the message. - const string& full_name() const; // Fully-qualified name of the field. - const string& json_name() const; // JSON name of this field. - const FileDescriptor* file() const;// File in which this field was defined. - bool is_extension() const; // Is this an extension field? - int number() const; // Declared tag number. + const std::string& name() const; // Name of this field within the message. + const std::string& full_name() const; // Fully-qualified name of the field. + const std::string& json_name() const; // JSON name of this field. + const FileDescriptor* file() const; // File in which this field was defined. + bool is_extension() const; // Is this an extension field? + int number() const; // Declared tag number. // Same as name() except converted to lower-case. This (and especially the // FindFieldByLowercaseName() method) can be useful when parsing formats @@ -584,7 +672,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { // field names should be lowercased anyway according to the protobuf style // guide, so this only makes a difference when dealing with old .proto files // which do not follow the guide.) - const string& lowercase_name() const; + const std::string& lowercase_name() const; // Same as name() except converted to camel-case. In this conversion, any // time an underscore appears in the name, it is removed and the next @@ -595,7 +683,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { // fooBar -> fooBar // This (and especially the FindFieldByCamelcaseName() method) can be useful // when parsing formats which prefer to use camel-case naming style. - const string& camelcase_name() const; + const std::string& camelcase_name() const; Type type() const; // Declared type of this field. const char* type_name() const; // Name of the declared type. @@ -603,15 +691,28 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { const char* cpp_type_name() const; // Name of the C++ type. Label label() const; // optional/required/repeated - bool is_required() const; // shorthand for label() == LABEL_REQUIRED - bool is_optional() const; // shorthand for label() == LABEL_OPTIONAL - bool is_repeated() const; // shorthand for label() == LABEL_REPEATED - bool is_packable() const; // shorthand for is_repeated() && - // IsTypePackable(type()) - bool is_packed() const; // shorthand for is_packable() && - // options().packed() - bool is_map() const; // shorthand for type() == TYPE_MESSAGE && - // message_type()->options().map_entry() + bool is_required() const; // shorthand for label() == LABEL_REQUIRED + bool is_optional() const; // shorthand for label() == LABEL_OPTIONAL + bool is_repeated() const; // shorthand for label() == LABEL_REPEATED + bool is_packable() const; // shorthand for is_repeated() && + // IsTypePackable(type()) + bool is_packed() const; // shorthand for is_packable() && + // options().packed() + bool is_map() const; // shorthand for type() == TYPE_MESSAGE && + // message_type()->options().map_entry() + + // Returns true if this field was syntactically written with "optional" in the + // .proto file. Excludes singular proto3 fields that do not have a label. + bool has_optional_keyword() const; + + // Returns true if this field tracks presence, ie. does the field + // distinguish between "unset" and "present with default value." + // This includes required, optional, and oneof fields. It excludes maps, + // repeated fields, and singular proto3 fields without "optional". + // + // For fields where has_presence() == true, the return value of + // Reflection::HasField() is semantically meaningful. + bool has_presence() const; // Index of this field within the message's field array, or the file or // extension scope's extensions array. @@ -648,26 +749,30 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { // Get the field default value if cpp_type() == CPPTYPE_ENUM. If no // explicit default was defined, the default is the first value defined // in the enum type (all enum types are required to have at least one value). - // This never returns NULL. + // This never returns nullptr. const EnumValueDescriptor* default_value_enum() const; // Get the field default value if cpp_type() == CPPTYPE_STRING. If no // explicit default was defined, the default is the empty string. - const string& default_value_string() const; + const std::string& default_value_string() const; // The Descriptor for the message of which this is a field. For extensions, - // this is the extended type. Never NULL. + // this is the extended type. Never nullptr. const Descriptor* containing_type() const; // If the field is a member of a oneof, this is the one, otherwise this is - // NULL. + // nullptr. const OneofDescriptor* containing_oneof() const; + // If the field is a member of a non-synthetic oneof, returns the descriptor + // for the oneof, otherwise returns nullptr. + const OneofDescriptor* real_containing_oneof() const; + // If the field is a member of a oneof, returns the index in that oneof. int index_in_oneof() const; // An extension may be declared within the scope of another message. If this // field is an extension (is_extension() is true), then extension_scope() - // returns that message, or NULL if the extension was declared at global + // returns that message, or nullptr if the extension was declared at global // scope. If this is not an extension, extension_scope() is undefined (may // assert-fail). const Descriptor* extension_scope() const; @@ -682,19 +787,18 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { // Get the FieldOptions for this field. This includes things listed in // square brackets after the field definition. E.g., the field: // optional string text = 1 [ctype=CORD]; - // has the "ctype" option set. Allowed options are defined by FieldOptions - // in google/protobuf/descriptor.proto, and any available extensions of that - // message. + // has the "ctype" option set. Allowed options are defined by FieldOptions in + // descriptor.proto, and any available extensions of that message. const FieldOptions& options() const; // See Descriptor::CopyTo(). void CopyTo(FieldDescriptorProto* proto) const; // See Descriptor::DebugString(). - string DebugString() const; + std::string DebugString() const; // See Descriptor::DebugStringWithOptions(). - string DebugStringWithOptions(const DebugStringOptions& options) const; + std::string DebugStringWithOptions(const DebugStringOptions& options) const; // Helper method to get the CppType for a particular Type. static CppType TypeToCppType(Type type); @@ -708,6 +812,21 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { // Return true iff [packed = true] is valid for fields of this type. static inline bool IsTypePackable(Type field_type); + // Returns full_name() except if the field is a MessageSet extension, + // in which case it returns the full_name() of the containing message type + // for backwards compatibility with proto1. + // + // A MessageSet extension is defined as an optional message extension + // whose containing type has the message_set_wire_format option set. + // This should be true of extensions of google.protobuf.bridge.MessageSet; + // by convention, such extensions are named "message_set_extension". + // + // The opposite operation (looking up an extension's FieldDescriptor given + // its printable name) can be accomplished with + // message->file()->pool()->FindExtensionByPrintableName(message, name) + // where the extension extends "message". + const std::string& PrintableNameForExtension() const; + // Source Location --------------------------------------------------- // Updates |*out_location| to the source location of the complete @@ -719,42 +838,47 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { typedef FieldOptions OptionsType; // Allows access to GetLocationPath for annotations. - friend class ::google::protobuf::io::Printer; + friend class io::Printer; + friend class compiler::cpp::Formatter; + friend class Reflection; // Fill the json_name field of FieldDescriptorProto. void CopyJsonNameTo(FieldDescriptorProto* proto) const; // See Descriptor::DebugString(). - enum PrintLabelFlag { PRINT_LABEL, OMIT_LABEL }; - void DebugString(int depth, PrintLabelFlag print_label_flag, - string* contents, const DebugStringOptions& options) const; + void DebugString(int depth, std::string* contents, + const DebugStringOptions& options) const; // formats the default value appropriately and returns it as a string. // Must have a default value to call this. If quote_string_type is true, then // types of CPPTYPE_STRING whill be surrounded by quotes and CEscaped. - string DefaultValueAsString(bool quote_string_type) const; + std::string DefaultValueAsString(bool quote_string_type) const; // Helper function that returns the field type name for DebugString. - string FieldTypeNameDebugString() const; + std::string FieldTypeNameDebugString() const; // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. void GetLocationPath(std::vector* output) const; - const string* name_; - const string* full_name_; - const string* lowercase_name_; - const string* camelcase_name_; + // Returns true if this is a map message type. + bool is_map_message_type() const; + + const std::string* name_; + const std::string* full_name_; + const std::string* lowercase_name_; + const std::string* camelcase_name_; // If has_json_name_ is true, it's the value specified by the user. // Otherwise, it has the same value as camelcase_name_. - const string* json_name_; + const std::string* json_name_; const FileDescriptor* file_; - GoogleOnceDynamic* type_once_; + internal::once_flag* type_once_; static void TypeOnceInit(const FieldDescriptor* to_init); void InternalTypeOnceInit() const; mutable Type type_; Label label_; bool has_default_value_; + bool proto3_optional_; // Whether the user has specified the json_name field option in the .proto // file. bool has_json_name_; @@ -767,32 +891,33 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { mutable const Descriptor* message_type_; mutable const EnumDescriptor* enum_type_; const FieldOptions* options_; - const string* type_name_; - const string* default_value_enum_name_; + const std::string* type_name_; + const std::string* default_value_enum_name_; // IMPORTANT: If you add a new field, make sure to search for all instances // of Allocate() and AllocateArray() in // descriptor.cc and update them to initialize the field. union { - int32 default_value_int32_; - int64 default_value_int64_; + int32 default_value_int32_; + int64 default_value_int64_; uint32 default_value_uint32_; uint64 default_value_uint64_; - float default_value_float_; + float default_value_float_; double default_value_double_; - bool default_value_bool_; + bool default_value_bool_; mutable const EnumValueDescriptor* default_value_enum_; - const string* default_value_string_; + const std::string* default_value_string_; + mutable std::atomic default_generated_instance_; }; static const CppType kTypeToCppTypeMap[MAX_TYPE + 1]; - static const char * const kTypeToName[MAX_TYPE + 1]; + static const char* const kTypeToName[MAX_TYPE + 1]; - static const char * const kCppTypeToName[MAX_CPPTYPE + 1]; + static const char* const kCppTypeToName[MAX_CPPTYPE + 1]; - static const char * const kLabelToName[MAX_LABEL + 1]; + static const char* const kLabelToName[MAX_LABEL + 1]; // Must be constructed using DescriptorPool. FieldDescriptor() {} @@ -805,15 +930,21 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { // Describes a oneof defined in a message type. -class LIBPROTOBUF_EXPORT OneofDescriptor { +class PROTOBUF_EXPORT OneofDescriptor { public: - const string& name() const; // Name of this oneof. - const string& full_name() const; // Fully-qualified name of the oneof. + typedef OneofDescriptorProto Proto; + + const std::string& name() const; // Name of this oneof. + const std::string& full_name() const; // Fully-qualified name of the oneof. // Index of this oneof within the message's oneof array. int index() const; - // The .proto file in which this oneof was defined. Never NULL. + // Returns whether this oneof was inserted by the compiler to wrap a proto3 + // optional field. If this returns true, code generators should *not* emit it. + bool is_synthetic() const; + + // The .proto file in which this oneof was defined. Never nullptr. const FileDescriptor* file() const; // The Descriptor for the message containing this oneof. const Descriptor* containing_type() const; @@ -830,10 +961,10 @@ class LIBPROTOBUF_EXPORT OneofDescriptor { void CopyTo(OneofDescriptorProto* proto) const; // See Descriptor::DebugString(). - string DebugString() const; + std::string DebugString() const; // See Descriptor::DebugStringWithOptions(). - string DebugStringWithOptions(const DebugStringOptions& options) const; + std::string DebugStringWithOptions(const DebugStringOptions& options) const; // Source Location --------------------------------------------------- @@ -846,20 +977,20 @@ class LIBPROTOBUF_EXPORT OneofDescriptor { typedef OneofOptions OptionsType; // Allows access to GetLocationPath for annotations. - friend class ::google::protobuf::io::Printer; + friend class io::Printer; + friend class compiler::cpp::Formatter; // See Descriptor::DebugString(). - void DebugString(int depth, string* contents, + void DebugString(int depth, std::string* contents, const DebugStringOptions& options) const; // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. void GetLocationPath(std::vector* output) const; - const string* name_; - const string* full_name_; + const std::string* name_; + const std::string* full_name_; const Descriptor* containing_type_; - bool is_extendable_; int field_count_; const FieldDescriptor** fields_; const OneofOptions* options_; @@ -878,18 +1009,20 @@ class LIBPROTOBUF_EXPORT OneofDescriptor { // Describes an enum type defined in a .proto file. To get the EnumDescriptor // for a generated enum type, call TypeName_descriptor(). Use DescriptorPool // to construct your own descriptors. -class LIBPROTOBUF_EXPORT EnumDescriptor { +class PROTOBUF_EXPORT EnumDescriptor { public: + typedef EnumDescriptorProto Proto; + // The name of this enum type in the containing scope. - const string& name() const; + const std::string& name() const; // The fully-qualified name of the enum type, scope delimited by periods. - const string& full_name() const; + const std::string& full_name() const; // Index of this enum within the file or containing message's enum array. int index() const; - // The .proto file in which this enum type was defined. Never NULL. + // The .proto file in which this enum type was defined. Never nullptr. const FileDescriptor* file() const; // The number of values for this EnumDescriptor. Guaranteed to be greater @@ -899,37 +1032,67 @@ class LIBPROTOBUF_EXPORT EnumDescriptor { // These are returned in the order they were defined in the .proto file. const EnumValueDescriptor* value(int index) const; - // Looks up a value by name. Returns NULL if no such value exists. - const EnumValueDescriptor* FindValueByName(const string& name) const; - // Looks up a value by number. Returns NULL if no such value exists. If + // Looks up a value by name. Returns nullptr if no such value exists. + const EnumValueDescriptor* FindValueByName(ConstStringParam name) const; + // Looks up a value by number. Returns nullptr if no such value exists. If // multiple values have this number, the first one defined is returned. const EnumValueDescriptor* FindValueByNumber(int number) const; // If this enum type is nested in a message type, this is that message type. - // Otherwise, NULL. + // Otherwise, nullptr. const Descriptor* containing_type() const; // Get options for this enum type. These are specified in the .proto file by // placing lines like "option foo = 1234;" in the enum definition. Allowed - // options are defined by EnumOptions in google/protobuf/descriptor.proto, - // and any available extensions of that message. + // options are defined by EnumOptions in descriptor.proto, and any available + // extensions of that message. const EnumOptions& options() const; // See Descriptor::CopyTo(). void CopyTo(EnumDescriptorProto* proto) const; // See Descriptor::DebugString(). - string DebugString() const; + std::string DebugString() const; // See Descriptor::DebugStringWithOptions(). - string DebugStringWithOptions(const DebugStringOptions& options) const; - + std::string DebugStringWithOptions(const DebugStringOptions& options) const; // Returns true if this is a placeholder for an unknown enum. This will // only be the case if this descriptor comes from a DescriptorPool // with AllowUnknownDependencies() set. bool is_placeholder() const; + // Reserved fields ------------------------------------------------- + + // A range of reserved field numbers. + struct ReservedRange { + int start; // inclusive + int end; // inclusive + }; + + // The number of reserved ranges in this message type. + int reserved_range_count() const; + // Gets an reserved range by index, where 0 <= index < + // reserved_range_count(). These are returned in the order they were defined + // in the .proto file. + const EnumDescriptor::ReservedRange* reserved_range(int index) const; + + // Returns true if the number is in one of the reserved ranges. + bool IsReservedNumber(int number) const; + + // Returns nullptr if no reserved range contains the given number. + const EnumDescriptor::ReservedRange* FindReservedRangeContainingNumber( + int number) const; + + // The number of reserved field names in this message type. + int reserved_name_count() const; + + // Gets a reserved name by index, where 0 <= index < reserved_name_count(). + const std::string& reserved_name(int index) const; + + // Returns true if the field name is reserved. + bool IsReservedName(ConstStringParam name) const; + // Source Location --------------------------------------------------- // Updates |*out_location| to the source location of the complete @@ -941,30 +1104,30 @@ class LIBPROTOBUF_EXPORT EnumDescriptor { typedef EnumOptions OptionsType; // Allows access to GetLocationPath for annotations. - friend class ::google::protobuf::io::Printer; + friend class io::Printer; + friend class compiler::cpp::Formatter; // Looks up a value by number. If the value does not exist, dynamically // creates a new EnumValueDescriptor for that value, assuming that it was // unknown. If a new descriptor is created, this is done in a thread-safe way, // and future calls will return the same value descriptor pointer. // - // This is private but is used by GeneratedMessageReflection (which is - // friended below) to return a valid EnumValueDescriptor from GetEnum() when - // this feature is enabled. - const EnumValueDescriptor* - FindValueByNumberCreatingIfUnknown(int number) const; - + // This is private but is used by Reflection (which is friended below) to + // return a valid EnumValueDescriptor from GetEnum() when this feature is + // enabled. + const EnumValueDescriptor* FindValueByNumberCreatingIfUnknown( + int number) const; // See Descriptor::DebugString(). - void DebugString(int depth, string *contents, + void DebugString(int depth, std::string* contents, const DebugStringOptions& options) const; // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. void GetLocationPath(std::vector* output) const; - const string* name_; - const string* full_name_; + const std::string* name_; + const std::string* full_name_; const FileDescriptor* file_; const Descriptor* containing_type_; const EnumOptions* options_; @@ -976,6 +1139,12 @@ class LIBPROTOBUF_EXPORT EnumDescriptor { int value_count_; EnumValueDescriptor* values_; + + int reserved_range_count_; + int reserved_name_count_; + EnumDescriptor::ReservedRange* reserved_ranges_; + const std::string** reserved_names_; + // IMPORTANT: If you add a new field, make sure to search for all instances // of Allocate() and AllocateArray() in // descriptor.cc and update them to initialize the field. @@ -988,7 +1157,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptor { friend class EnumValueDescriptor; friend class FileDescriptor; friend class DescriptorPool; - friend class internal::GeneratedMessageReflection; + friend class Reflection; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumDescriptor); }; @@ -997,40 +1166,40 @@ class LIBPROTOBUF_EXPORT EnumDescriptor { // for its type, then use EnumDescriptor::FindValueByName() or // EnumDescriptor::FindValueByNumber(). Use DescriptorPool to construct // your own descriptors. -class LIBPROTOBUF_EXPORT EnumValueDescriptor { +class PROTOBUF_EXPORT EnumValueDescriptor { public: - const string& name() const; // Name of this enum constant. - int index() const; // Index within the enums's Descriptor. - int number() const; // Numeric value of this enum constant. + typedef EnumValueDescriptorProto Proto; + + const std::string& name() const; // Name of this enum constant. + int index() const; // Index within the enums's Descriptor. + int number() const; // Numeric value of this enum constant. // The full_name of an enum value is a sibling symbol of the enum type. // e.g. the full name of FieldDescriptorProto::TYPE_INT32 is actually // "google.protobuf.FieldDescriptorProto.TYPE_INT32", NOT // "google.protobuf.FieldDescriptorProto.Type.TYPE_INT32". This is to conform // with C++ scoping rules for enums. - const string& full_name() const; + const std::string& full_name() const; - // The .proto file in which this value was defined. Never NULL. + // The .proto file in which this value was defined. Never nullptr. const FileDescriptor* file() const; - // The type of this value. Never NULL. + // The type of this value. Never nullptr. const EnumDescriptor* type() const; - // Get options for this enum value. These are specified in the .proto file - // by adding text like "[foo = 1234]" after an enum value definition. - // Allowed options are defined by EnumValueOptions in - // google/protobuf/descriptor.proto, and any available extensions of that - // message. + // Get options for this enum value. These are specified in the .proto file by + // adding text like "[foo = 1234]" after an enum value definition. Allowed + // options are defined by EnumValueOptions in descriptor.proto, and any + // available extensions of that message. const EnumValueOptions& options() const; // See Descriptor::CopyTo(). void CopyTo(EnumValueDescriptorProto* proto) const; // See Descriptor::DebugString(). - string DebugString() const; + std::string DebugString() const; // See Descriptor::DebugStringWithOptions(). - string DebugStringWithOptions(const DebugStringOptions& options) const; - + std::string DebugStringWithOptions(const DebugStringOptions& options) const; // Source Location --------------------------------------------------- @@ -1043,18 +1212,19 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptor { typedef EnumValueOptions OptionsType; // Allows access to GetLocationPath for annotations. - friend class ::google::protobuf::io::Printer; + friend class io::Printer; + friend class compiler::cpp::Formatter; // See Descriptor::DebugString(). - void DebugString(int depth, string *contents, + void DebugString(int depth, std::string* contents, const DebugStringOptions& options) const; // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. void GetLocationPath(std::vector* output) const; - const string* name_; - const string* full_name_; + const std::string* name_; + const std::string* full_name_; int number_; const EnumDescriptor* type_; const EnumValueOptions* options_; @@ -1068,30 +1238,30 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptor { friend class EnumDescriptor; friend class DescriptorPool; friend class FileDescriptorTables; + friend class Reflection; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumValueDescriptor); }; -// Describes an RPC service. To get the ServiceDescriptor for a service, -// call Service::GetDescriptor(). Generated service classes also have a -// static method called descriptor() which returns the type's -// ServiceDescriptor. Use DescriptorPool to construct your own descriptors. -class LIBPROTOBUF_EXPORT ServiceDescriptor { +// Describes an RPC service. Use DescriptorPool to construct your own +// descriptors. +class PROTOBUF_EXPORT ServiceDescriptor { public: + typedef ServiceDescriptorProto Proto; + // The name of the service, not including its containing scope. - const string& name() const; + const std::string& name() const; // The fully-qualified name of the service, scope delimited by periods. - const string& full_name() const; + const std::string& full_name() const; // Index of this service within the file's services array. int index() const; - // The .proto file in which this service was defined. Never NULL. + // The .proto file in which this service was defined. Never nullptr. const FileDescriptor* file() const; // Get options for this service type. These are specified in the .proto file // by placing lines like "option foo = 1234;" in the service definition. - // Allowed options are defined by ServiceOptions in - // google/protobuf/descriptor.proto, and any available extensions of that - // message. + // Allowed options are defined by ServiceOptions in descriptor.proto, and any + // available extensions of that message. const ServiceOptions& options() const; // The number of methods this service defines. @@ -1101,16 +1271,15 @@ class LIBPROTOBUF_EXPORT ServiceDescriptor { const MethodDescriptor* method(int index) const; // Look up a MethodDescriptor by name. - const MethodDescriptor* FindMethodByName(const string& name) const; + const MethodDescriptor* FindMethodByName(ConstStringParam name) const; // See Descriptor::CopyTo(). void CopyTo(ServiceDescriptorProto* proto) const; // See Descriptor::DebugString(). - string DebugString() const; + std::string DebugString() const; // See Descriptor::DebugStringWithOptions(). - string DebugStringWithOptions(const DebugStringOptions& options) const; - + std::string DebugStringWithOptions(const DebugStringOptions& options) const; // Source Location --------------------------------------------------- @@ -1123,17 +1292,19 @@ class LIBPROTOBUF_EXPORT ServiceDescriptor { typedef ServiceOptions OptionsType; // Allows access to GetLocationPath for annotations. - friend class ::google::protobuf::io::Printer; + friend class io::Printer; + friend class compiler::cpp::Formatter; // See Descriptor::DebugString(). - void DebugString(string *contents, const DebugStringOptions& options) const; + void DebugString(std::string* contents, + const DebugStringOptions& options) const; // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. void GetLocationPath(std::vector* output) const; - const string* name_; - const string* full_name_; + const std::string* name_; + const std::string* full_name_; const FileDescriptor* file_; const ServiceOptions* options_; MethodDescriptor* methods_; @@ -1155,18 +1326,20 @@ class LIBPROTOBUF_EXPORT ServiceDescriptor { // a service, first get its ServiceDescriptor, then call // ServiceDescriptor::FindMethodByName(). Use DescriptorPool to construct your // own descriptors. -class LIBPROTOBUF_EXPORT MethodDescriptor { +class PROTOBUF_EXPORT MethodDescriptor { public: + typedef MethodDescriptorProto Proto; + // Name of this method, not including containing scope. - const string& name() const; + const std::string& name() const; // The fully-qualified name of the method, scope delimited by periods. - const string& full_name() const; + const std::string& full_name() const; // Index within the service's Descriptor. int index() const; - // The .proto file in which this method was defined. Never NULL. + // The .proto file in which this method was defined. Never nullptr. const FileDescriptor* file() const; - // Gets the service to which this method belongs. Never NULL. + // Gets the service to which this method belongs. Never nullptr. const ServiceDescriptor* service() const; // Gets the type of protocol message which this method accepts as input. @@ -1182,19 +1355,17 @@ class LIBPROTOBUF_EXPORT MethodDescriptor { // Get options for this method. These are specified in the .proto file by // placing lines like "option foo = 1234;" in curly-braces after a method // declaration. Allowed options are defined by MethodOptions in - // google/protobuf/descriptor.proto, and any available extensions of that - // message. + // descriptor.proto, and any available extensions of that message. const MethodOptions& options() const; // See Descriptor::CopyTo(). void CopyTo(MethodDescriptorProto* proto) const; // See Descriptor::DebugString(). - string DebugString() const; + std::string DebugString() const; // See Descriptor::DebugStringWithOptions(). - string DebugStringWithOptions(const DebugStringOptions& options) const; - + std::string DebugStringWithOptions(const DebugStringOptions& options) const; // Source Location --------------------------------------------------- @@ -1207,18 +1378,19 @@ class LIBPROTOBUF_EXPORT MethodDescriptor { typedef MethodOptions OptionsType; // Allows access to GetLocationPath for annotations. - friend class ::google::protobuf::io::Printer; + friend class io::Printer; + friend class compiler::cpp::Formatter; // See Descriptor::DebugString(). - void DebugString(int depth, string *contents, + void DebugString(int depth, std::string* contents, const DebugStringOptions& options) const; // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. void GetLocationPath(std::vector* output) const; - const string* name_; - const string* full_name_; + const std::string* name_; + const std::string* full_name_; const ServiceDescriptor* service_; mutable internal::LazyDescriptor input_type_; mutable internal::LazyDescriptor output_type_; @@ -1240,17 +1412,19 @@ class LIBPROTOBUF_EXPORT MethodDescriptor { // Describes a whole .proto file. To get the FileDescriptor for a compiled-in // file, get the descriptor for something defined in that file and call // descriptor->file(). Use DescriptorPool to construct your own descriptors. -class LIBPROTOBUF_EXPORT FileDescriptor { +class PROTOBUF_EXPORT FileDescriptor { public: + typedef FileDescriptorProto Proto; + // The filename, relative to the source tree. - // e.g. "google/protobuf/descriptor.proto" - const string& name() const; + // e.g. "foo/bar/baz.proto" + const std::string& name() const; // The package, e.g. "google.protobuf.compiler". - const string& package() const; + const std::string& package() const; // The DescriptorPool in which this FileDescriptor and all its contents were - // allocated. Never NULL. + // allocated. Never nullptr. const DescriptorPool* pool() const; // The number of files imported by this one. @@ -1305,36 +1479,39 @@ class LIBPROTOBUF_EXPORT FileDescriptor { // Get options for this file. These are specified in the .proto file by // placing lines like "option foo = 1234;" at the top level, outside of any // other definitions. Allowed options are defined by FileOptions in - // google/protobuf/descriptor.proto, and any available extensions of that - // message. + // descriptor.proto, and any available extensions of that message. const FileOptions& options() const; // Syntax of this file. enum Syntax { SYNTAX_UNKNOWN = 0, - SYNTAX_PROTO2 = 2, - SYNTAX_PROTO3 = 3, + SYNTAX_PROTO2 = 2, + SYNTAX_PROTO3 = 3, }; Syntax syntax() const; static const char* SyntaxName(Syntax syntax); - // Find a top-level message type by name. Returns NULL if not found. - const Descriptor* FindMessageTypeByName(const string& name) const; - // Find a top-level enum type by name. Returns NULL if not found. - const EnumDescriptor* FindEnumTypeByName(const string& name) const; - // Find an enum value defined in any top-level enum by name. Returns NULL if + // Find a top-level message type by name (not full_name). Returns nullptr if // not found. - const EnumValueDescriptor* FindEnumValueByName(const string& name) const; - // Find a service definition by name. Returns NULL if not found. - const ServiceDescriptor* FindServiceByName(const string& name) const; - // Find a top-level extension definition by name. Returns NULL if not found. - const FieldDescriptor* FindExtensionByName(const string& name) const; + const Descriptor* FindMessageTypeByName(ConstStringParam name) const; + // Find a top-level enum type by name. Returns nullptr if not found. + const EnumDescriptor* FindEnumTypeByName(ConstStringParam name) const; + // Find an enum value defined in any top-level enum by name. Returns nullptr + // if not found. + const EnumValueDescriptor* FindEnumValueByName(ConstStringParam name) const; + // Find a service definition by name. Returns nullptr if not found. + const ServiceDescriptor* FindServiceByName(ConstStringParam name) const; + // Find a top-level extension definition by name. Returns nullptr if not + // found. + const FieldDescriptor* FindExtensionByName(ConstStringParam name) const; // Similar to FindExtensionByName(), but searches by lowercased-name. See // Descriptor::FindFieldByLowercaseName(). - const FieldDescriptor* FindExtensionByLowercaseName(const string& name) const; + const FieldDescriptor* FindExtensionByLowercaseName( + ConstStringParam name) const; // Similar to FindExtensionByName(), but searches by camelcased-name. See // Descriptor::FindFieldByCamelcaseName(). - const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const; + const FieldDescriptor* FindExtensionByCamelcaseName( + ConstStringParam name) const; // See Descriptor::CopyTo(). // Notes: @@ -1349,10 +1526,10 @@ class LIBPROTOBUF_EXPORT FileDescriptor { void CopyJsonNameTo(FileDescriptorProto* proto) const; // See Descriptor::DebugString(). - string DebugString() const; + std::string DebugString() const; // See Descriptor::DebugStringWithOptions(). - string DebugStringWithOptions(const DebugStringOptions& options) const; + std::string DebugStringWithOptions(const DebugStringOptions& options) const; // Returns true if this is a placeholder for an unknown file. This will // only be the case if this descriptor comes from a DescriptorPool @@ -1374,14 +1551,14 @@ class LIBPROTOBUF_EXPORT FileDescriptor { private: typedef FileOptions OptionsType; - const string* name_; - const string* package_; + const std::string* name_; + const std::string* package_; const DescriptorPool* pool_; - GoogleOnceDynamic* dependencies_once_; + internal::once_flag* dependencies_once_; static void DependenciesOnceInit(const FileDescriptor* to_init); void InternalDependenciesOnceInit() const; - // These are arranged to minimze padding on 64-bit. + // These are arranged to minimize padding on 64-bit. int dependency_count_; int public_dependency_count_; int weak_dependency_count_; @@ -1398,7 +1575,7 @@ class LIBPROTOBUF_EXPORT FileDescriptor { bool finished_building_; mutable const FileDescriptor** dependencies_; - const string** dependencies_names_; + const std::string** dependencies_names_; int* public_dependencies_; int* weak_dependencies_; Descriptor* message_types_; @@ -1455,7 +1632,7 @@ class LIBPROTOBUF_EXPORT FileDescriptor { // // You can also search for descriptors within a DescriptorPool by name, and // extensions by number. -class LIBPROTOBUF_EXPORT DescriptorPool { +class PROTOBUF_EXPORT DescriptorPool { public: // Create a normal, empty DescriptorPool. DescriptorPool(); @@ -1485,7 +1662,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // in subsequent lookups in the DescriptorPool. class ErrorCollector; explicit DescriptorPool(DescriptorDatabase* fallback_database, - ErrorCollector* error_collector = NULL); + ErrorCollector* error_collector = nullptr); ~DescriptorPool(); @@ -1495,36 +1672,44 @@ class LIBPROTOBUF_EXPORT DescriptorPool { static const DescriptorPool* generated_pool(); - // Find a FileDescriptor in the pool by file name. Returns NULL if not + // Find a FileDescriptor in the pool by file name. Returns nullptr if not // found. - const FileDescriptor* FindFileByName(const string& name) const; + const FileDescriptor* FindFileByName(ConstStringParam name) const; // Find the FileDescriptor in the pool which defines the given symbol. // If any of the Find*ByName() methods below would succeed, then this is // equivalent to calling that method and calling the result's file() method. - // Otherwise this returns NULL. + // Otherwise this returns nullptr. const FileDescriptor* FindFileContainingSymbol( - const string& symbol_name) const; + ConstStringParam symbol_name) const; // Looking up descriptors ------------------------------------------ // These find descriptors by fully-qualified name. These will find both - // top-level descriptors and nested descriptors. They return NULL if not + // top-level descriptors and nested descriptors. They return nullptr if not // found. - const Descriptor* FindMessageTypeByName(const string& name) const; - const FieldDescriptor* FindFieldByName(const string& name) const; - const FieldDescriptor* FindExtensionByName(const string& name) const; - const OneofDescriptor* FindOneofByName(const string& name) const; - const EnumDescriptor* FindEnumTypeByName(const string& name) const; - const EnumValueDescriptor* FindEnumValueByName(const string& name) const; - const ServiceDescriptor* FindServiceByName(const string& name) const; - const MethodDescriptor* FindMethodByName(const string& name) const; + const Descriptor* FindMessageTypeByName(ConstStringParam name) const; + const FieldDescriptor* FindFieldByName(ConstStringParam name) const; + const FieldDescriptor* FindExtensionByName(ConstStringParam name) const; + const OneofDescriptor* FindOneofByName(ConstStringParam name) const; + const EnumDescriptor* FindEnumTypeByName(ConstStringParam name) const; + const EnumValueDescriptor* FindEnumValueByName(ConstStringParam name) const; + const ServiceDescriptor* FindServiceByName(ConstStringParam name) const; + const MethodDescriptor* FindMethodByName(ConstStringParam name) const; // Finds an extension of the given type by number. The extendee must be // a member of this DescriptorPool or one of its underlays. const FieldDescriptor* FindExtensionByNumber(const Descriptor* extendee, int number) const; + // Finds an extension of the given type by its printable name. + // See comments above PrintableNameForExtension() for the definition of + // "printable name". The extendee must be a member of this DescriptorPool + // or one of its underlays. Returns nullptr if there is no known message + // extension with the given printable name. + const FieldDescriptor* FindExtensionByPrintableName( + const Descriptor* extendee, ConstStringParam printable_name) const; + // Finds extensions of extendee. The extensions will be appended to // out in an undefined order. Only extensions defined directly in // this DescriptorPool or one of its underlays are guaranteed to be @@ -1538,7 +1723,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // When converting a FileDescriptorProto to a FileDescriptor, various // errors might be detected in the input. The caller may handle these // programmatically by implementing an ErrorCollector. - class LIBPROTOBUF_EXPORT ErrorCollector { + class PROTOBUF_EXPORT ErrorCollector { public: inline ErrorCollector() {} virtual ~ErrorCollector(); @@ -1547,37 +1732,40 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // This is useful e.g. for mapping the error back to an exact location // in a .proto file. enum ErrorLocation { - NAME, // the symbol name, or the package name for files - NUMBER, // field or extension range number - TYPE, // field type - EXTENDEE, // field extendee - DEFAULT_VALUE, // field default value - INPUT_TYPE, // method input type - OUTPUT_TYPE, // method output type - OPTION_NAME, // name in assignment - OPTION_VALUE, // value in option assignment - OTHER // some other problem + NAME, // the symbol name, or the package name for files + NUMBER, // field or extension range number + TYPE, // field type + EXTENDEE, // field extendee + DEFAULT_VALUE, // field default value + INPUT_TYPE, // method input type + OUTPUT_TYPE, // method output type + OPTION_NAME, // name in assignment + OPTION_VALUE, // value in option assignment + IMPORT, // import error + OTHER // some other problem }; // Reports an error in the FileDescriptorProto. Use this function if the // problem occurred should interrupt building the FileDescriptorProto. virtual void AddError( - const string& filename, // File name in which the error occurred. - const string& element_name, // Full name of the erroneous element. - const Message* descriptor, // Descriptor of the erroneous element. - ErrorLocation location, // One of the location constants, above. - const string& message // Human-readable error message. - ) = 0; + const std::string& filename, // File name in which the error occurred. + const std::string& element_name, // Full name of the erroneous element. + const Message* descriptor, // Descriptor of the erroneous element. + ErrorLocation location, // One of the location constants, above. + const std::string& message // Human-readable error message. + ) = 0; // Reports a warning in the FileDescriptorProto. Use this function if the // problem occurred should NOT interrupt building the FileDescriptorProto. virtual void AddWarning( - const string& /*filename*/, // File name in which the error occurred. - const string& /*element_name*/, // Full name of the erroneous element. - const Message* /*descriptor*/, // Descriptor of the erroneous element. - ErrorLocation /*location*/, // One of the location constants, above. - const string& /*message*/ // Human-readable error message. - ) {} + const std::string& /*filename*/, // File name in which the error + // occurred. + const std::string& /*element_name*/, // Full name of the erroneous + // element. + const Message* /*descriptor*/, // Descriptor of the erroneous element. + ErrorLocation /*location*/, // One of the location constants, above. + const std::string& /*message*/ // Human-readable error message. + ) {} private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector); @@ -1585,15 +1773,14 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // Convert the FileDescriptorProto to real descriptors and place them in // this DescriptorPool. All dependencies of the file must already be in - // the pool. Returns the resulting FileDescriptor, or NULL if there were + // the pool. Returns the resulting FileDescriptor, or nullptr if there were // problems with the input (e.g. the message was invalid, or dependencies // were missing). Details about the errors are written to GOOGLE_LOG(ERROR). const FileDescriptor* BuildFile(const FileDescriptorProto& proto); // Same as BuildFile() except errors are sent to the given ErrorCollector. const FileDescriptor* BuildFileCollectingErrors( - const FileDescriptorProto& proto, - ErrorCollector* error_collector); + const FileDescriptorProto& proto, ErrorCollector* error_collector); // By default, it is an error if a FileDescriptorProto contains references // to types or other files that are not found in the DescriptorPool (or its @@ -1648,8 +1835,8 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // Called by generated classes at init time to add their descriptors to // generated_pool. Do NOT call this in your own code! filename must be a // permanent string (e.g. a string literal). - static void InternalAddGeneratedFile( - const void* encoded_file_descriptor, int size); + static void InternalAddGeneratedFile(const void* encoded_file_descriptor, + int size); // Disallow [enforce_utf8 = false] in .proto files. void DisallowEnforceUtf8() { disallow_enforce_utf8_ = true; } @@ -1661,6 +1848,11 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // the underlay takes precedence. static DescriptorPool* internal_generated_pool(); + // For internal use only: Gets a non-const pointer to the generated + // descriptor database. + // Only used for testing. + static DescriptorDatabase* internal_generated_database(); + // For internal use only: Changes the behavior of BuildFile() such that it // allows the file to make reference to message types declared in other files // which it did not officially declare as dependencies. @@ -1670,7 +1862,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // Delay the building of dependencies of a file descriptor until absolutely // necessary, like when message_type() is called on a field that is defined // in that dependency's file. This will cause functional issues if a proto - // or one of it's dependencies has errors. Should only be enabled for the + // or one of its dependencies has errors. Should only be enabled for the // generated_pool_ (because no descriptor build errors are guaranteed by // the compilation generation process), testing, or if a lack of descriptor // build errors can be guaranteed for a pool. @@ -1689,12 +1881,12 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // For internal (unit test) use only: Returns true if a FileDescriptor has // been constructed for the given file, false otherwise. Useful for testing // lazy descriptor initialization behavior. - bool InternalIsFileLoaded(const string& filename) const; - + bool InternalIsFileLoaded(ConstStringParam filename) const; // Add a file to unused_import_track_files_. DescriptorBuilder will log - // warnings for those files if there is any unused import. - void AddUnusedImportTrackFile(const string& file_name); + // warnings or errors for those files if there is any unused import. + void AddUnusedImportTrackFile(ConstStringParam file_name, + bool is_error = false); void ClearUnusedImportTrackFiles(); private: @@ -1712,33 +1904,40 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // Return true if the given name is a sub-symbol of any non-package // descriptor that already exists in the descriptor pool. (The full // definition of such types is already known.) - bool IsSubSymbolOfBuiltType(const string& name) const; + bool IsSubSymbolOfBuiltType(StringPiece name) const; // Tries to find something in the fallback database and link in the // corresponding proto file. Returns true if successful, in which case // the caller should search for the thing again. These are declared // const because they are called by (semantically) const methods. - bool TryFindFileInFallbackDatabase(const string& name) const; - bool TryFindSymbolInFallbackDatabase(const string& name) const; + bool TryFindFileInFallbackDatabase(StringPiece name) const; + bool TryFindSymbolInFallbackDatabase(StringPiece name) const; bool TryFindExtensionInFallbackDatabase(const Descriptor* containing_type, int field_number) const; + // This internal find extension method only check with its table and underlay + // descriptor_pool's table. It does not check with fallback DB and no + // additional proto file will be build in this method. + const FieldDescriptor* InternalFindExtensionByNumberNoLock( + const Descriptor* extendee, int number) const; + // Like BuildFile() but called internally when the file has been loaded from // fallback_database_. Declared const because it is called by (semantically) // const methods. const FileDescriptor* BuildFileFromDatabase( - const FileDescriptorProto& proto) const; + const FileDescriptorProto& proto) const; // Helper for when lazily_build_dependencies_ is set, can look up a symbol // after the file's descriptor is built, and can build the file where that // symbol is defined if necessary. Will create a placeholder if the type // doesn't exist in the fallback database, or the file doesn't build // successfully. - Symbol CrossLinkOnDemandHelper(const string& name, bool expecting_enum) const; + Symbol CrossLinkOnDemandHelper(StringPiece name, + bool expecting_enum) const; // Create a placeholder FileDescriptor of the specified name - FileDescriptor* NewPlaceholderFile(const string& name) const; - FileDescriptor* NewPlaceholderFileWithMutexHeld(const string& name) const; + FileDescriptor* NewPlaceholderFile(StringPiece name) const; + FileDescriptor* NewPlaceholderFileWithMutexHeld(StringPiece name) const; enum PlaceholderType { PLACEHOLDER_MESSAGE, @@ -1746,14 +1945,14 @@ class LIBPROTOBUF_EXPORT DescriptorPool { PLACEHOLDER_EXTENDABLE_MESSAGE }; // Create a placeholder Descriptor of the specified name - Symbol NewPlaceholder(const string& name, + Symbol NewPlaceholder(StringPiece name, PlaceholderType placeholder_type) const; - Symbol NewPlaceholderWithMutexHeld(const string& name, + Symbol NewPlaceholderWithMutexHeld(StringPiece name, PlaceholderType placeholder_type) const; - // If fallback_database_ is NULL, this is NULL. Otherwise, this is a mutex - // which must be locked while accessing tables_. - Mutex* mutex_; + // If fallback_database_ is nullptr, this is nullptr. Otherwise, this is a + // mutex which must be locked while accessing tables_. + internal::WrappedMutex* mutex_; // See constructor. DescriptorDatabase* fallback_database_; @@ -1763,14 +1962,17 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // This class contains a lot of hash maps with complicated types that // we'd like to keep out of the header. class Tables; - google::protobuf::scoped_ptr tables_; + std::unique_ptr tables_; bool enforce_dependencies_; bool lazily_build_dependencies_; bool allow_unknown_; bool enforce_weak_; bool disallow_enforce_utf8_; - std::set unused_import_track_files_; + + // Set of files to track for unused imports. The bool value when true means + // unused imports are treated as errors (and as warnings when false). + std::map unused_import_track_files_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPool); }; @@ -1784,7 +1986,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // Strings fields are stored as pointers but returned as const references. #define PROTOBUF_DEFINE_STRING_ACCESSOR(CLASS, FIELD) \ - inline const string& CLASS::FIELD() const { return *FIELD##_; } + inline const std::string& CLASS::FIELD() const { return *FIELD##_; } // Arrays take an index parameter, obviously. #define PROTOBUF_DEFINE_ARRAY_ACCESSOR(CLASS, FIELD, TYPE) \ @@ -1800,6 +2002,7 @@ PROTOBUF_DEFINE_ACCESSOR(Descriptor, containing_type, const Descriptor*) PROTOBUF_DEFINE_ACCESSOR(Descriptor, field_count, int) PROTOBUF_DEFINE_ACCESSOR(Descriptor, oneof_decl_count, int) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, real_oneof_decl_count, int) PROTOBUF_DEFINE_ACCESSOR(Descriptor, nested_type_count, int) PROTOBUF_DEFINE_ACCESSOR(Descriptor, enum_type_count, int) @@ -1812,8 +2015,7 @@ PROTOBUF_DEFINE_ACCESSOR(Descriptor, extension_range_count, int) PROTOBUF_DEFINE_ACCESSOR(Descriptor, extension_count, int) PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension_range, const Descriptor::ExtensionRange*) -PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension, - const FieldDescriptor*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension, const FieldDescriptor*) PROTOBUF_DEFINE_ACCESSOR(Descriptor, reserved_range_count, int) PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, reserved_range, @@ -1840,13 +2042,13 @@ PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, extension_scope, const Descriptor*) PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FieldDescriptor, FieldOptions) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, has_default_value, bool) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, has_json_name, bool) -PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int32 , int32 ) -PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int64 , int64 ) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int32, int32) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int64, int64) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_uint32, uint32) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_uint64, uint64) -PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_float , float ) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_float, float) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_double, double) -PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_bool , bool ) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_bool, bool) PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, default_value_string) PROTOBUF_DEFINE_STRING_ACCESSOR(OneofDescriptor, name) @@ -1864,6 +2066,10 @@ PROTOBUF_DEFINE_ARRAY_ACCESSOR(EnumDescriptor, value, const EnumValueDescriptor*) PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumDescriptor, EnumOptions) PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, is_placeholder, bool) +PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, reserved_range_count, int) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(EnumDescriptor, reserved_range, + const EnumDescriptor::ReservedRange*) +PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, reserved_name_count, int) PROTOBUF_DEFINE_STRING_ACCESSOR(EnumValueDescriptor, name) PROTOBUF_DEFINE_STRING_ACCESSOR(EnumValueDescriptor, full_name) @@ -1912,17 +2118,40 @@ PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, extension, // A few accessors differ from the macros... +inline Descriptor::WellKnownType Descriptor::well_known_type() const { + return static_cast(well_known_type_); +} + inline bool Descriptor::IsExtensionNumber(int number) const { - return FindExtensionRangeContainingNumber(number) != NULL; + return FindExtensionRangeContainingNumber(number) != nullptr; } inline bool Descriptor::IsReservedNumber(int number) const { - return FindReservedRangeContainingNumber(number) != NULL; + return FindReservedRangeContainingNumber(number) != nullptr; +} + +inline bool Descriptor::IsReservedName(ConstStringParam name) const { + for (int i = 0; i < reserved_name_count(); i++) { + if (name == static_cast(reserved_name(i))) { + return true; + } + } + return false; +} + +// Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because reserved_names_ is actually +// an array of pointers rather than the usual array of objects. +inline const std::string& Descriptor::reserved_name(int index) const { + return *reserved_names_[index]; +} + +inline bool EnumDescriptor::IsReservedNumber(int number) const { + return FindReservedRangeContainingNumber(number) != nullptr; } -inline bool Descriptor::IsReservedName(const string& name) const { +inline bool EnumDescriptor::IsReservedName(ConstStringParam name) const { for (int i = 0; i < reserved_name_count(); i++) { - if (name == reserved_name(i)) { + if (name == static_cast(reserved_name(i))) { return true; } } @@ -1931,10 +2160,17 @@ inline bool Descriptor::IsReservedName(const string& name) const { // Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because reserved_names_ is actually // an array of pointers rather than the usual array of objects. -inline const string& Descriptor::reserved_name(int index) const { +inline const std::string& EnumDescriptor::reserved_name(int index) const { return *reserved_names_[index]; } +inline FieldDescriptor::Type FieldDescriptor::type() const { + if (type_once_) { + internal::call_once(*type_once_, &FieldDescriptor::TypeOnceInit, this); + } + return type_; +} + inline bool FieldDescriptor::is_required() const { return label() == LABEL_REQUIRED; } @@ -1951,12 +2187,34 @@ inline bool FieldDescriptor::is_packable() const { return is_repeated() && IsTypePackable(type()); } +inline bool FieldDescriptor::is_map() const { + return type() == TYPE_MESSAGE && is_map_message_type(); +} + +inline bool FieldDescriptor::has_optional_keyword() const { + return proto3_optional_ || + (file()->syntax() == FileDescriptor::SYNTAX_PROTO2 && is_optional() && + !containing_oneof()); +} + +inline const OneofDescriptor* FieldDescriptor::real_containing_oneof() const { + return containing_oneof_ && !containing_oneof_->is_synthetic() + ? containing_oneof_ + : nullptr; +} + +inline bool FieldDescriptor::has_presence() const { + if (is_repeated()) return false; + return cpp_type() == CPPTYPE_MESSAGE || containing_oneof() || + file()->syntax() == FileDescriptor::SYNTAX_PROTO2; +} + // To save space, index() is computed by looking at the descriptor's position // in the parent's array of children. inline int FieldDescriptor::index() const { if (!is_extension_) { return static_cast(this - containing_type()->fields_); - } else if (extension_scope_ != NULL) { + } else if (extension_scope_ != nullptr) { return static_cast(this - extension_scope_->extensions_); } else { return static_cast(this - file_->extensions_); @@ -1964,7 +2222,7 @@ inline int FieldDescriptor::index() const { } inline int Descriptor::index() const { - if (containing_type_ == NULL) { + if (containing_type_ == nullptr) { return static_cast(this - file_->message_types_); } else { return static_cast(this - containing_type_->nested_types_); @@ -1979,8 +2237,12 @@ inline int OneofDescriptor::index() const { return static_cast(this - containing_type_->oneof_decls_); } +inline bool OneofDescriptor::is_synthetic() const { + return field_count() == 1 && field(0)->proto3_optional_; +} + inline int EnumDescriptor::index() const { - if (containing_type_ == NULL) { + if (containing_type_ == nullptr) { return static_cast(this - file_->enum_types_); } else { return static_cast(this - containing_type_->enum_types_); @@ -2043,14 +2305,11 @@ inline const FileDescriptor* FileDescriptor::public_dependency( return dependency(public_dependencies_[index]); } -inline const FileDescriptor* FileDescriptor::weak_dependency( - int index) const { +inline const FileDescriptor* FileDescriptor::weak_dependency(int index) const { return dependency(weak_dependencies_[index]); } -inline FileDescriptor::Syntax FileDescriptor::syntax() const { - return syntax_; -} +inline FileDescriptor::Syntax FileDescriptor::syntax() const { return syntax_; } // Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because fields_ is actually an array // of pointers rather than the usual array of objects. @@ -2059,6 +2318,8 @@ inline const FieldDescriptor* OneofDescriptor::field(int index) const { } } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_DESCRIPTOR_H__ diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 69c0ab0d3718d..8ceaa19718d37 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -1,229 +1,482 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/descriptor.proto -#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include #include -#include -#include -#include #include -#include +#include +#include #include #include #include #include // @@protoc_insertion_point(includes) - -namespace google { -namespace protobuf { -class FileDescriptorSetDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _FileDescriptorSet_default_instance_; -class FileDescriptorProtoDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _FileDescriptorProto_default_instance_; -class DescriptorProto_ExtensionRangeDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _DescriptorProto_ExtensionRange_default_instance_; -class DescriptorProto_ReservedRangeDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _DescriptorProto_ReservedRange_default_instance_; -class DescriptorProtoDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _DescriptorProto_default_instance_; -class ExtensionRangeOptionsDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _ExtensionRangeOptions_default_instance_; -class FieldDescriptorProtoDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _FieldDescriptorProto_default_instance_; -class OneofDescriptorProtoDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _OneofDescriptorProto_default_instance_; -class EnumDescriptorProtoDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _EnumDescriptorProto_default_instance_; -class EnumValueDescriptorProtoDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _EnumValueDescriptorProto_default_instance_; -class ServiceDescriptorProtoDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _ServiceDescriptorProto_default_instance_; -class MethodDescriptorProtoDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _MethodDescriptorProto_default_instance_; -class FileOptionsDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _FileOptions_default_instance_; -class MessageOptionsDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _MessageOptions_default_instance_; -class FieldOptionsDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _FieldOptions_default_instance_; -class OneofOptionsDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _OneofOptions_default_instance_; -class EnumOptionsDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _EnumOptions_default_instance_; -class EnumValueOptionsDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _EnumValueOptions_default_instance_; -class ServiceOptionsDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _ServiceOptions_default_instance_; -class MethodOptionsDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _MethodOptions_default_instance_; -class UninterpretedOption_NamePartDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _UninterpretedOption_NamePart_default_instance_; -class UninterpretedOptionDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _UninterpretedOption_default_instance_; -class SourceCodeInfo_LocationDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _SourceCodeInfo_Location_default_instance_; -class SourceCodeInfoDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _SourceCodeInfo_default_instance_; -class GeneratedCodeInfo_AnnotationDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _GeneratedCodeInfo_Annotation_default_instance_; -class GeneratedCodeInfoDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _GeneratedCodeInfo_default_instance_; - -namespace protobuf_google_2fprotobuf_2fdescriptor_2eproto { - - -namespace { - -::google::protobuf::Metadata file_level_metadata[26]; -const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors[6]; - -} // namespace - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField - const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0}, +#include + +PROTOBUF_PRAGMA_INIT_SEG +PROTOBUF_NAMESPACE_OPEN +constexpr FileDescriptorSet::FileDescriptorSet( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : file_(){} +struct FileDescriptorSetDefaultTypeInternal { + constexpr FileDescriptorSetDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~FileDescriptorSetDefaultTypeInternal() {} + union { + FileDescriptorSet _instance; + }; }; - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField - const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - ::google::protobuf::internal::AuxillaryParseTableField(), +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FileDescriptorSetDefaultTypeInternal _FileDescriptorSet_default_instance_; +constexpr FileDescriptorProto::FileDescriptorProto( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : dependency_() + , message_type_() + , enum_type_() + , service_() + , extension_() + , public_dependency_() + , weak_dependency_() + , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , package_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , syntax_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , options_(nullptr) + , source_code_info_(nullptr){} +struct FileDescriptorProtoDefaultTypeInternal { + constexpr FileDescriptorProtoDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~FileDescriptorProtoDefaultTypeInternal() {} + union { + FileDescriptorProto _instance; + }; }; -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const - TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FileDescriptorProtoDefaultTypeInternal _FileDescriptorProto_default_instance_; +constexpr DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : options_(nullptr) + , start_(0) + , end_(0){} +struct DescriptorProto_ExtensionRangeDefaultTypeInternal { + constexpr DescriptorProto_ExtensionRangeDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~DescriptorProto_ExtensionRangeDefaultTypeInternal() {} + union { + DescriptorProto_ExtensionRange _instance; + }; }; - -const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _internal_metadata_), +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT DescriptorProto_ExtensionRangeDefaultTypeInternal _DescriptorProto_ExtensionRange_default_instance_; +constexpr DescriptorProto_ReservedRange::DescriptorProto_ReservedRange( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : start_(0) + , end_(0){} +struct DescriptorProto_ReservedRangeDefaultTypeInternal { + constexpr DescriptorProto_ReservedRangeDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~DescriptorProto_ReservedRangeDefaultTypeInternal() {} + union { + DescriptorProto_ReservedRange _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT DescriptorProto_ReservedRangeDefaultTypeInternal _DescriptorProto_ReservedRange_default_instance_; +constexpr DescriptorProto::DescriptorProto( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : field_() + , nested_type_() + , enum_type_() + , extension_range_() + , extension_() + , oneof_decl_() + , reserved_range_() + , reserved_name_() + , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , options_(nullptr){} +struct DescriptorProtoDefaultTypeInternal { + constexpr DescriptorProtoDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~DescriptorProtoDefaultTypeInternal() {} + union { + DescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT DescriptorProtoDefaultTypeInternal _DescriptorProto_default_instance_; +constexpr ExtensionRangeOptions::ExtensionRangeOptions( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : uninterpreted_option_(){} +struct ExtensionRangeOptionsDefaultTypeInternal { + constexpr ExtensionRangeOptionsDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~ExtensionRangeOptionsDefaultTypeInternal() {} + union { + ExtensionRangeOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT ExtensionRangeOptionsDefaultTypeInternal _ExtensionRangeOptions_default_instance_; +constexpr FieldDescriptorProto::FieldDescriptorProto( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , extendee_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , type_name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , default_value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , json_name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , options_(nullptr) + , number_(0) + , oneof_index_(0) + , proto3_optional_(false) + , label_(1) + + , type_(1) +{} +struct FieldDescriptorProtoDefaultTypeInternal { + constexpr FieldDescriptorProtoDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~FieldDescriptorProtoDefaultTypeInternal() {} + union { + FieldDescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_; +constexpr OneofDescriptorProto::OneofDescriptorProto( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , options_(nullptr){} +struct OneofDescriptorProtoDefaultTypeInternal { + constexpr OneofDescriptorProtoDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~OneofDescriptorProtoDefaultTypeInternal() {} + union { + OneofDescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT OneofDescriptorProtoDefaultTypeInternal _OneofDescriptorProto_default_instance_; +constexpr EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : start_(0) + , end_(0){} +struct EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal { + constexpr EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal() {} + union { + EnumDescriptorProto_EnumReservedRange _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal _EnumDescriptorProto_EnumReservedRange_default_instance_; +constexpr EnumDescriptorProto::EnumDescriptorProto( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : value_() + , reserved_range_() + , reserved_name_() + , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , options_(nullptr){} +struct EnumDescriptorProtoDefaultTypeInternal { + constexpr EnumDescriptorProtoDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~EnumDescriptorProtoDefaultTypeInternal() {} + union { + EnumDescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EnumDescriptorProtoDefaultTypeInternal _EnumDescriptorProto_default_instance_; +constexpr EnumValueDescriptorProto::EnumValueDescriptorProto( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , options_(nullptr) + , number_(0){} +struct EnumValueDescriptorProtoDefaultTypeInternal { + constexpr EnumValueDescriptorProtoDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~EnumValueDescriptorProtoDefaultTypeInternal() {} + union { + EnumValueDescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EnumValueDescriptorProtoDefaultTypeInternal _EnumValueDescriptorProto_default_instance_; +constexpr ServiceDescriptorProto::ServiceDescriptorProto( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : method_() + , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , options_(nullptr){} +struct ServiceDescriptorProtoDefaultTypeInternal { + constexpr ServiceDescriptorProtoDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~ServiceDescriptorProtoDefaultTypeInternal() {} + union { + ServiceDescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT ServiceDescriptorProtoDefaultTypeInternal _ServiceDescriptorProto_default_instance_; +constexpr MethodDescriptorProto::MethodDescriptorProto( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , input_type_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , output_type_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , options_(nullptr) + , client_streaming_(false) + , server_streaming_(false){} +struct MethodDescriptorProtoDefaultTypeInternal { + constexpr MethodDescriptorProtoDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~MethodDescriptorProtoDefaultTypeInternal() {} + union { + MethodDescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT MethodDescriptorProtoDefaultTypeInternal _MethodDescriptorProto_default_instance_; +constexpr FileOptions::FileOptions( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : uninterpreted_option_() + , java_package_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , java_outer_classname_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , go_package_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , objc_class_prefix_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , csharp_namespace_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , swift_prefix_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , php_class_prefix_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , php_namespace_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , php_metadata_namespace_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , ruby_package_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , java_multiple_files_(false) + , java_generate_equals_and_hash_(false) + , java_string_check_utf8_(false) + , cc_generic_services_(false) + , java_generic_services_(false) + , py_generic_services_(false) + , php_generic_services_(false) + , deprecated_(false) + , optimize_for_(1) + + , cc_enable_arenas_(true){} +struct FileOptionsDefaultTypeInternal { + constexpr FileOptionsDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~FileOptionsDefaultTypeInternal() {} + union { + FileOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FileOptionsDefaultTypeInternal _FileOptions_default_instance_; +constexpr MessageOptions::MessageOptions( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : uninterpreted_option_() + , message_set_wire_format_(false) + , no_standard_descriptor_accessor_(false) + , deprecated_(false) + , map_entry_(false){} +struct MessageOptionsDefaultTypeInternal { + constexpr MessageOptionsDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~MessageOptionsDefaultTypeInternal() {} + union { + MessageOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT MessageOptionsDefaultTypeInternal _MessageOptions_default_instance_; +constexpr FieldOptions::FieldOptions( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : uninterpreted_option_() + , ctype_(0) + + , packed_(false) + , lazy_(false) + , deprecated_(false) + , weak_(false) + , jstype_(0) +{} +struct FieldOptionsDefaultTypeInternal { + constexpr FieldOptionsDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~FieldOptionsDefaultTypeInternal() {} + union { + FieldOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FieldOptionsDefaultTypeInternal _FieldOptions_default_instance_; +constexpr OneofOptions::OneofOptions( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : uninterpreted_option_(){} +struct OneofOptionsDefaultTypeInternal { + constexpr OneofOptionsDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~OneofOptionsDefaultTypeInternal() {} + union { + OneofOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT OneofOptionsDefaultTypeInternal _OneofOptions_default_instance_; +constexpr EnumOptions::EnumOptions( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : uninterpreted_option_() + , allow_alias_(false) + , deprecated_(false){} +struct EnumOptionsDefaultTypeInternal { + constexpr EnumOptionsDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~EnumOptionsDefaultTypeInternal() {} + union { + EnumOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EnumOptionsDefaultTypeInternal _EnumOptions_default_instance_; +constexpr EnumValueOptions::EnumValueOptions( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : uninterpreted_option_() + , deprecated_(false){} +struct EnumValueOptionsDefaultTypeInternal { + constexpr EnumValueOptionsDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~EnumValueOptionsDefaultTypeInternal() {} + union { + EnumValueOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_; +constexpr ServiceOptions::ServiceOptions( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : uninterpreted_option_() + , deprecated_(false){} +struct ServiceOptionsDefaultTypeInternal { + constexpr ServiceOptionsDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~ServiceOptionsDefaultTypeInternal() {} + union { + ServiceOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT ServiceOptionsDefaultTypeInternal _ServiceOptions_default_instance_; +constexpr MethodOptions::MethodOptions( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : uninterpreted_option_() + , deprecated_(false) + , idempotency_level_(0) +{} +struct MethodOptionsDefaultTypeInternal { + constexpr MethodOptionsDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~MethodOptionsDefaultTypeInternal() {} + union { + MethodOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT MethodOptionsDefaultTypeInternal _MethodOptions_default_instance_; +constexpr UninterpretedOption_NamePart::UninterpretedOption_NamePart( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : name_part_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , is_extension_(false){} +struct UninterpretedOption_NamePartDefaultTypeInternal { + constexpr UninterpretedOption_NamePartDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~UninterpretedOption_NamePartDefaultTypeInternal() {} + union { + UninterpretedOption_NamePart _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_; +constexpr UninterpretedOption::UninterpretedOption( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : name_() + , identifier_value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , string_value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , aggregate_value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , positive_int_value_(PROTOBUF_ULONGLONG(0)) + , negative_int_value_(PROTOBUF_LONGLONG(0)) + , double_value_(0){} +struct UninterpretedOptionDefaultTypeInternal { + constexpr UninterpretedOptionDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~UninterpretedOptionDefaultTypeInternal() {} + union { + UninterpretedOption _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT UninterpretedOptionDefaultTypeInternal _UninterpretedOption_default_instance_; +constexpr SourceCodeInfo_Location::SourceCodeInfo_Location( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : path_() + , _path_cached_byte_size_() + , span_() + , _span_cached_byte_size_() + , leading_detached_comments_() + , leading_comments_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , trailing_comments_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){} +struct SourceCodeInfo_LocationDefaultTypeInternal { + constexpr SourceCodeInfo_LocationDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~SourceCodeInfo_LocationDefaultTypeInternal() {} + union { + SourceCodeInfo_Location _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT SourceCodeInfo_LocationDefaultTypeInternal _SourceCodeInfo_Location_default_instance_; +constexpr SourceCodeInfo::SourceCodeInfo( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : location_(){} +struct SourceCodeInfoDefaultTypeInternal { + constexpr SourceCodeInfoDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~SourceCodeInfoDefaultTypeInternal() {} + union { + SourceCodeInfo _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT SourceCodeInfoDefaultTypeInternal _SourceCodeInfo_default_instance_; +constexpr GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : path_() + , _path_cached_byte_size_() + , source_file_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , begin_(0) + , end_(0){} +struct GeneratedCodeInfo_AnnotationDefaultTypeInternal { + constexpr GeneratedCodeInfo_AnnotationDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~GeneratedCodeInfo_AnnotationDefaultTypeInternal() {} + union { + GeneratedCodeInfo_Annotation _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT GeneratedCodeInfo_AnnotationDefaultTypeInternal _GeneratedCodeInfo_Annotation_default_instance_; +constexpr GeneratedCodeInfo::GeneratedCodeInfo( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : annotation_(){} +struct GeneratedCodeInfoDefaultTypeInternal { + constexpr GeneratedCodeInfoDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~GeneratedCodeInfoDefaultTypeInternal() {} + union { + GeneratedCodeInfo _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT GeneratedCodeInfoDefaultTypeInternal _GeneratedCodeInfo_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[27]; +static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[6]; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto = nullptr; + +const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorSet, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, file_), - ~0u, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorSet, file_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, package_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, dependency_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, public_dependency_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, weak_dependency_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, message_type_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, enum_type_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, service_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, extension_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, options_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, source_code_info_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, syntax_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, package_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, dependency_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, public_dependency_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, weak_dependency_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, message_type_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, enum_type_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, service_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, extension_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, options_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, source_code_info_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, syntax_), 0, 1, ~0u, @@ -236,41 +489,41 @@ const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION 3, 4, 2, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, start_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, end_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, options_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, start_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, end_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, options_), 1, 2, 0, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, start_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, end_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, start_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, end_), 0, 1, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, field_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, nested_type_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, enum_type_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_range_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, oneof_decl_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, options_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, reserved_range_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, reserved_name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto, name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto, field_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto, extension_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto, nested_type_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto, enum_type_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto, extension_range_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto, oneof_decl_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto, options_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto, reserved_range_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::DescriptorProto, reserved_name_), 0, ~0u, ~0u, @@ -281,167 +534,185 @@ const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION 1, ~0u, ~0u, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ExtensionRangeOptions, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ExtensionRangeOptions, _internal_metadata_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ExtensionRangeOptions, _extensions_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _extensions_), ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ExtensionRangeOptions, uninterpreted_option_), - ~0u, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, uninterpreted_option_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, number_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, label_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, type_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, type_name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, extendee_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, default_value_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, oneof_index_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, json_name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, options_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, number_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, label_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, type_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, type_name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, extendee_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, default_value_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, oneof_index_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, json_name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, options_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, proto3_optional_), 0, 6, - 8, 9, + 10, 2, 1, 3, 7, 4, 5, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, _internal_metadata_), + 8, + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, options_), + 0, + 1, + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, options_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, start_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, end_), 0, 1, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, value_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, options_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, value_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, options_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, reserved_range_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, reserved_name_), 0, ~0u, 1, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, _internal_metadata_), + ~0u, + ~0u, + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, number_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, options_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, number_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, options_), 0, 2, 1, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, method_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, options_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, method_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, options_), 0, ~0u, 1, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, input_type_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, output_type_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, options_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, client_streaming_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, server_streaming_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, input_type_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, output_type_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, options_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, client_streaming_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, server_streaming_), 0, 1, 2, 3, 4, 5, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _internal_metadata_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _extensions_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, _extensions_), ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generate_equals_and_hash_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_string_check_utf8_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, optimize_for_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, go_package_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_generic_services_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generic_services_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, php_generic_services_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, deprecated_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_enable_arenas_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, objc_class_prefix_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_namespace_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, swift_prefix_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, php_class_prefix_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, php_namespace_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, java_package_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, java_outer_classname_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, java_multiple_files_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, java_generate_equals_and_hash_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, java_string_check_utf8_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, optimize_for_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, go_package_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, cc_generic_services_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, java_generic_services_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, py_generic_services_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, php_generic_services_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, deprecated_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, cc_enable_arenas_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, objc_class_prefix_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, csharp_namespace_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, swift_prefix_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, php_class_prefix_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, php_namespace_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, php_metadata_namespace_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, ruby_package_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileOptions, uninterpreted_option_), 0, 1, - 8, - 9, 10, - 17, - 2, 11, 12, + 18, + 2, 13, 14, 15, 16, + 17, + 19, 3, 4, 5, 6, 7, + 8, + 9, ~0u, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _internal_metadata_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _extensions_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MessageOptions, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MessageOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MessageOptions, _extensions_), ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, message_set_wire_format_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, no_standard_descriptor_accessor_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, deprecated_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, map_entry_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, uninterpreted_option_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MessageOptions, message_set_wire_format_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MessageOptions, no_standard_descriptor_accessor_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MessageOptions, deprecated_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MessageOptions, map_entry_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MessageOptions, uninterpreted_option_), 0, 1, 2, 3, ~0u, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _internal_metadata_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _extensions_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldOptions, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldOptions, _extensions_), ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, packed_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, jstype_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, lazy_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, deprecated_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, weak_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, uninterpreted_option_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldOptions, ctype_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldOptions, packed_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldOptions, jstype_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldOptions, lazy_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldOptions, deprecated_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldOptions, weak_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldOptions, uninterpreted_option_), 0, 1, 5, @@ -449,74 +720,73 @@ const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION 3, 4, ~0u, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofOptions, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofOptions, _internal_metadata_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofOptions, _extensions_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, _extensions_), ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofOptions, uninterpreted_option_), - ~0u, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _internal_metadata_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _extensions_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, uninterpreted_option_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _extensions_), ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, allow_alias_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, deprecated_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, uninterpreted_option_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, allow_alias_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, deprecated_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, uninterpreted_option_), 0, 1, ~0u, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _internal_metadata_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _extensions_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumValueOptions, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumValueOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumValueOptions, _extensions_), ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, deprecated_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, uninterpreted_option_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumValueOptions, deprecated_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumValueOptions, uninterpreted_option_), 0, ~0u, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _internal_metadata_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _extensions_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ServiceOptions, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ServiceOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ServiceOptions, _extensions_), ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, deprecated_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, uninterpreted_option_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ServiceOptions, deprecated_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ServiceOptions, uninterpreted_option_), 0, ~0u, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _internal_metadata_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _extensions_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MethodOptions, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MethodOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MethodOptions, _extensions_), ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, deprecated_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, idempotency_level_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, uninterpreted_option_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MethodOptions, deprecated_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MethodOptions, idempotency_level_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::MethodOptions, uninterpreted_option_), 0, 1, ~0u, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, name_part_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, is_extension_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, name_part_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, is_extension_), 0, 1, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::UninterpretedOption, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::UninterpretedOption, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, identifier_value_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, positive_int_value_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, negative_int_value_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, double_value_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, string_value_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, aggregate_value_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::UninterpretedOption, name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::UninterpretedOption, identifier_value_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::UninterpretedOption, positive_int_value_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::UninterpretedOption, negative_int_value_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::UninterpretedOption, double_value_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::UninterpretedOption, string_value_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::UninterpretedOption, aggregate_value_), ~0u, 0, 3, @@ -524,385 +794,279 @@ const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION 5, 1, 2, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, span_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_comments_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, trailing_comments_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_detached_comments_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, path_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, span_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, leading_comments_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, trailing_comments_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, leading_detached_comments_), ~0u, ~0u, 0, 1, ~0u, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _internal_metadata_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, location_), - ~0u, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo, location_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, path_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, source_file_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, begin_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo_Annotation, end_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, path_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, source_file_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, begin_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, end_), ~0u, 0, 1, 2, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo, _internal_metadata_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo, annotation_), - ~0u, + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, annotation_), }; -static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { 0, 6, sizeof(FileDescriptorSet)}, - { 7, 24, sizeof(FileDescriptorProto)}, - { 36, 44, sizeof(DescriptorProto_ExtensionRange)}, - { 47, 54, sizeof(DescriptorProto_ReservedRange)}, - { 56, 71, sizeof(DescriptorProto)}, - { 81, 87, sizeof(ExtensionRangeOptions)}, - { 88, 103, sizeof(FieldDescriptorProto)}, - { 113, 120, sizeof(OneofDescriptorProto)}, - { 122, 130, sizeof(EnumDescriptorProto)}, - { 133, 141, sizeof(EnumValueDescriptorProto)}, - { 144, 152, sizeof(ServiceDescriptorProto)}, - { 155, 166, sizeof(MethodDescriptorProto)}, - { 172, 196, sizeof(FileOptions)}, - { 215, 225, sizeof(MessageOptions)}, - { 230, 242, sizeof(FieldOptions)}, - { 249, 255, sizeof(OneofOptions)}, - { 256, 264, sizeof(EnumOptions)}, - { 267, 274, sizeof(EnumValueOptions)}, - { 276, 283, sizeof(ServiceOptions)}, - { 285, 293, sizeof(MethodOptions)}, - { 296, 303, sizeof(UninterpretedOption_NamePart)}, - { 305, 317, sizeof(UninterpretedOption)}, - { 324, 334, sizeof(SourceCodeInfo_Location)}, - { 339, 345, sizeof(SourceCodeInfo)}, - { 346, 355, sizeof(GeneratedCodeInfo_Annotation)}, - { 359, 365, sizeof(GeneratedCodeInfo)}, +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, sizeof(PROTOBUF_NAMESPACE_ID::FileDescriptorSet)}, + { 6, 23, sizeof(PROTOBUF_NAMESPACE_ID::FileDescriptorProto)}, + { 35, 43, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange)}, + { 46, 53, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange)}, + { 55, 70, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto)}, + { 80, -1, sizeof(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions)}, + { 86, 102, sizeof(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto)}, + { 113, 120, sizeof(PROTOBUF_NAMESPACE_ID::OneofDescriptorProto)}, + { 122, 129, sizeof(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange)}, + { 131, 141, sizeof(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto)}, + { 146, 154, sizeof(PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto)}, + { 157, 165, sizeof(PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto)}, + { 168, 179, sizeof(PROTOBUF_NAMESPACE_ID::MethodDescriptorProto)}, + { 185, 211, sizeof(PROTOBUF_NAMESPACE_ID::FileOptions)}, + { 232, 242, sizeof(PROTOBUF_NAMESPACE_ID::MessageOptions)}, + { 247, 259, sizeof(PROTOBUF_NAMESPACE_ID::FieldOptions)}, + { 266, -1, sizeof(PROTOBUF_NAMESPACE_ID::OneofOptions)}, + { 272, 280, sizeof(PROTOBUF_NAMESPACE_ID::EnumOptions)}, + { 283, 290, sizeof(PROTOBUF_NAMESPACE_ID::EnumValueOptions)}, + { 292, 299, sizeof(PROTOBUF_NAMESPACE_ID::ServiceOptions)}, + { 301, 309, sizeof(PROTOBUF_NAMESPACE_ID::MethodOptions)}, + { 312, 319, sizeof(PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart)}, + { 321, 333, sizeof(PROTOBUF_NAMESPACE_ID::UninterpretedOption)}, + { 340, 350, sizeof(PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location)}, + { 355, -1, sizeof(PROTOBUF_NAMESPACE_ID::SourceCodeInfo)}, + { 361, 370, sizeof(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation)}, + { 374, -1, sizeof(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo)}, }; -static ::google::protobuf::Message const * const file_default_instances[] = { - reinterpret_cast(&_FileDescriptorSet_default_instance_), - reinterpret_cast(&_FileDescriptorProto_default_instance_), - reinterpret_cast(&_DescriptorProto_ExtensionRange_default_instance_), - reinterpret_cast(&_DescriptorProto_ReservedRange_default_instance_), - reinterpret_cast(&_DescriptorProto_default_instance_), - reinterpret_cast(&_ExtensionRangeOptions_default_instance_), - reinterpret_cast(&_FieldDescriptorProto_default_instance_), - reinterpret_cast(&_OneofDescriptorProto_default_instance_), - reinterpret_cast(&_EnumDescriptorProto_default_instance_), - reinterpret_cast(&_EnumValueDescriptorProto_default_instance_), - reinterpret_cast(&_ServiceDescriptorProto_default_instance_), - reinterpret_cast(&_MethodDescriptorProto_default_instance_), - reinterpret_cast(&_FileOptions_default_instance_), - reinterpret_cast(&_MessageOptions_default_instance_), - reinterpret_cast(&_FieldOptions_default_instance_), - reinterpret_cast(&_OneofOptions_default_instance_), - reinterpret_cast(&_EnumOptions_default_instance_), - reinterpret_cast(&_EnumValueOptions_default_instance_), - reinterpret_cast(&_ServiceOptions_default_instance_), - reinterpret_cast(&_MethodOptions_default_instance_), - reinterpret_cast(&_UninterpretedOption_NamePart_default_instance_), - reinterpret_cast(&_UninterpretedOption_default_instance_), - reinterpret_cast(&_SourceCodeInfo_Location_default_instance_), - reinterpret_cast(&_SourceCodeInfo_default_instance_), - reinterpret_cast(&_GeneratedCodeInfo_Annotation_default_instance_), - reinterpret_cast(&_GeneratedCodeInfo_default_instance_), +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_FileDescriptorSet_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_FileDescriptorProto_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_DescriptorProto_ExtensionRange_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_DescriptorProto_ReservedRange_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_DescriptorProto_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_ExtensionRangeOptions_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_FieldDescriptorProto_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_OneofDescriptorProto_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_EnumDescriptorProto_EnumReservedRange_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_EnumDescriptorProto_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_EnumValueDescriptorProto_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_ServiceDescriptorProto_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_MethodDescriptorProto_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_FileOptions_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_MessageOptions_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_FieldOptions_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_OneofOptions_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_EnumOptions_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_EnumValueOptions_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_ServiceOptions_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_MethodOptions_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_UninterpretedOption_NamePart_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_UninterpretedOption_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_Location_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_Annotation_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_default_instance_), }; -namespace { - -void protobuf_AssignDescriptors() { - AddDescriptors(); - ::google::protobuf::MessageFactory* factory = NULL; - AssignDescriptors( - "google/protobuf/descriptor.proto", schemas, file_default_instances, TableStruct::offsets, factory, - file_level_metadata, file_level_enum_descriptors, NULL); -} - -void protobuf_AssignDescriptorsOnce() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors); -} - -void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; -void protobuf_RegisterTypes(const ::std::string&) { - protobuf_AssignDescriptorsOnce(); - ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 26); -} - -} // namespace -void TableStruct::InitDefaultsImpl() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - ::google::protobuf::internal::InitProtobufDefaults(); - _FileDescriptorSet_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_FileDescriptorSet_default_instance_);_FileDescriptorProto_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_FileDescriptorProto_default_instance_);_DescriptorProto_ExtensionRange_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_DescriptorProto_ExtensionRange_default_instance_);_DescriptorProto_ReservedRange_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_DescriptorProto_ReservedRange_default_instance_);_DescriptorProto_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_DescriptorProto_default_instance_);_ExtensionRangeOptions_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_ExtensionRangeOptions_default_instance_);_FieldDescriptorProto_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_FieldDescriptorProto_default_instance_);_OneofDescriptorProto_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_OneofDescriptorProto_default_instance_);_EnumDescriptorProto_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_EnumDescriptorProto_default_instance_);_EnumValueDescriptorProto_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_EnumValueDescriptorProto_default_instance_);_ServiceDescriptorProto_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_ServiceDescriptorProto_default_instance_);_MethodDescriptorProto_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_MethodDescriptorProto_default_instance_);_FileOptions_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_FileOptions_default_instance_);_MessageOptions_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_MessageOptions_default_instance_);_FieldOptions_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_FieldOptions_default_instance_);_OneofOptions_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_OneofOptions_default_instance_);_EnumOptions_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_EnumOptions_default_instance_);_EnumValueOptions_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_EnumValueOptions_default_instance_);_ServiceOptions_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_ServiceOptions_default_instance_);_MethodOptions_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_MethodOptions_default_instance_);_UninterpretedOption_NamePart_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_UninterpretedOption_NamePart_default_instance_);_UninterpretedOption_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_UninterpretedOption_default_instance_);_SourceCodeInfo_Location_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_SourceCodeInfo_Location_default_instance_);_SourceCodeInfo_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_SourceCodeInfo_default_instance_);_GeneratedCodeInfo_Annotation_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_GeneratedCodeInfo_Annotation_default_instance_);_GeneratedCodeInfo_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_GeneratedCodeInfo_default_instance_);_FileDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::FileOptions*>( - ::google::protobuf::FileOptions::internal_default_instance()); - _FileDescriptorProto_default_instance_._instance.get_mutable()->source_code_info_ = const_cast< ::google::protobuf::SourceCodeInfo*>( - ::google::protobuf::SourceCodeInfo::internal_default_instance()); - _DescriptorProto_ExtensionRange_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::ExtensionRangeOptions*>( - ::google::protobuf::ExtensionRangeOptions::internal_default_instance()); - _DescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::MessageOptions*>( - ::google::protobuf::MessageOptions::internal_default_instance()); - _FieldDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::FieldOptions*>( - ::google::protobuf::FieldOptions::internal_default_instance()); - _OneofDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::OneofOptions*>( - ::google::protobuf::OneofOptions::internal_default_instance()); - _EnumDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::EnumOptions*>( - ::google::protobuf::EnumOptions::internal_default_instance()); - _EnumValueDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::EnumValueOptions*>( - ::google::protobuf::EnumValueOptions::internal_default_instance()); - _ServiceDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::ServiceOptions*>( - ::google::protobuf::ServiceOptions::internal_default_instance()); - _MethodDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::MethodOptions*>( - ::google::protobuf::MethodOptions::internal_default_instance()); -} - -void InitDefaults() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl); -} -namespace { -void AddDescriptorsImpl() { - InitDefaults(); - static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - "\n google/protobuf/descriptor.proto\022\017goog" - "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file" - "\030\001 \003(\0132$.google.protobuf.FileDescriptorP" - "roto\"\333\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001" - "(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022" - "\031\n\021public_dependency\030\n \003(\005\022\027\n\017weak_depen" - "dency\030\013 \003(\005\0226\n\014message_type\030\004 \003(\0132 .goog" - "le.protobuf.DescriptorProto\0227\n\tenum_type" - "\030\005 \003(\0132$.google.protobuf.EnumDescriptorP" - "roto\0228\n\007service\030\006 \003(\0132\'.google.protobuf." - "ServiceDescriptorProto\0228\n\textension\030\007 \003(" - "\0132%.google.protobuf.FieldDescriptorProto" - "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File" - "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog" - "le.protobuf.SourceCodeInfo\022\016\n\006syntax\030\014 \001" - "(\t\"\251\005\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005" - "field\030\002 \003(\0132%.google.protobuf.FieldDescr" - "iptorProto\0228\n\textension\030\006 \003(\0132%.google.p" - "rotobuf.FieldDescriptorProto\0225\n\013nested_t" - "ype\030\003 \003(\0132 .google.protobuf.DescriptorPr" - "oto\0227\n\tenum_type\030\004 \003(\0132$.google.protobuf" - ".EnumDescriptorProto\022H\n\017extension_range\030" - "\005 \003(\0132/.google.protobuf.DescriptorProto." - "ExtensionRange\0229\n\noneof_decl\030\010 \003(\0132%.goo" - "gle.protobuf.OneofDescriptorProto\0220\n\007opt" - "ions\030\007 \001(\0132\037.google.protobuf.MessageOpti" - "ons\022F\n\016reserved_range\030\t \003(\0132..google.pro" - "tobuf.DescriptorProto.ReservedRange\022\025\n\rr" - "eserved_name\030\n \003(\t\032e\n\016ExtensionRange\022\r\n\005" - "start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\0227\n\007options\030\003 \001(" - "\0132&.google.protobuf.ExtensionRangeOption" - "s\032+\n\rReservedRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end" - "\030\002 \001(\005\"g\n\025ExtensionRangeOptions\022C\n\024unint" - "erpreted_option\030\347\007 \003(\0132$.google.protobuf" - ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\274\005\n\024Fiel" - "dDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number" - "\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobuf." - "FieldDescriptorProto.Label\0228\n\004type\030\005 \001(\016" - "2*.google.protobuf.FieldDescriptorProto." - "Type\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001(" - "\t\022\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_index\030" - "\t \001(\005\022\021\n\tjson_name\030\n \001(\t\022.\n\007options\030\010 \001(" - "\0132\035.google.protobuf.FieldOptions\"\266\002\n\004Typ" - "e\022\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTY" - "PE_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT3" - "2\020\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022" - "\r\n\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_" - "GROUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020" - "\014\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYP" - "E_SFIXED32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_" - "SINT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016LA" - "BEL_OPTIONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LA" - "BEL_REPEATED\020\003\"T\n\024OneofDescriptorProto\022\014" - "\n\004name\030\001 \001(\t\022.\n\007options\030\002 \001(\0132\035.google.p" - "rotobuf.OneofOptions\"\214\001\n\023EnumDescriptorP" - "roto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002 \003(\0132).goog" - "le.protobuf.EnumValueDescriptorProto\022-\n\007" - "options\030\003 \001(\0132\034.google.protobuf.EnumOpti" - "ons\"l\n\030EnumValueDescriptorProto\022\014\n\004name\030" - "\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!" - ".google.protobuf.EnumValueOptions\"\220\001\n\026Se" - "rviceDescriptorProto\022\014\n\004name\030\001 \001(\t\0226\n\006me" - "thod\030\002 \003(\0132&.google.protobuf.MethodDescr" - "iptorProto\0220\n\007options\030\003 \001(\0132\037.google.pro" - "tobuf.ServiceOptions\"\301\001\n\025MethodDescripto" - "rProto\022\014\n\004name\030\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t" - "\022\023\n\013output_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036" - ".google.protobuf.MethodOptions\022\037\n\020client" - "_streaming\030\005 \001(\010:\005false\022\037\n\020server_stream" - "ing\030\006 \001(\010:\005false\"\360\005\n\013FileOptions\022\024\n\014java" - "_package\030\001 \001(\t\022\034\n\024java_outer_classname\030\010" - " \001(\t\022\"\n\023java_multiple_files\030\n \001(\010:\005false" - "\022)\n\035java_generate_equals_and_hash\030\024 \001(\010B" - "\002\030\001\022%\n\026java_string_check_utf8\030\033 \001(\010:\005fal" - "se\022F\n\014optimize_for\030\t \001(\0162).google.protob" - "uf.FileOptions.OptimizeMode:\005SPEED\022\022\n\ngo" - "_package\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 " - "\001(\010:\005false\022$\n\025java_generic_services\030\021 \001(" - "\010:\005false\022\"\n\023py_generic_services\030\022 \001(\010:\005f" - "alse\022#\n\024php_generic_services\030\023 \001(\010:\005fals" - "e\022\031\n\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enabl" - "e_arenas\030\037 \001(\010:\005false\022\031\n\021objc_class_pref" - "ix\030$ \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022\024\n\014sw" - "ift_prefix\030\' \001(\t\022\030\n\020php_class_prefix\030( \001" - "(\t\022\025\n\rphp_namespace\030) \001(\t\022C\n\024uninterpret" - "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint" - "erpretedOption\":\n\014OptimizeMode\022\t\n\005SPEED\020" - "\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020" - "\200\200\200\200\002J\004\010&\020\'\"\362\001\n\016MessageOptions\022&\n\027messag" - "e_set_wire_format\030\001 \001(\010:\005false\022.\n\037no_sta" - "ndard_descriptor_accessor\030\002 \001(\010:\005false\022\031" - "\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007" - " \001(\010\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go" - "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200" - "\200\200\200\002J\004\010\010\020\tJ\004\010\t\020\n\"\236\003\n\014FieldOptions\022:\n\005cty" - "pe\030\001 \001(\0162#.google.protobuf.FieldOptions." - "CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030" - "\006 \001(\0162$.google.protobuf.FieldOptions.JST" - "ype:\tJS_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\nd" - "eprecated\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005fa" - "lse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo" - "gle.protobuf.UninterpretedOption\"/\n\005CTyp" - "e\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020" - "\002\"5\n\006JSType\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020" - "\001\022\r\n\tJS_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005\"^\n\014One" - "ofOptions\022C\n\024uninterpreted_option\030\347\007 \003(\013" - "2$.google.protobuf.UninterpretedOption*\t" - "\010\350\007\020\200\200\200\200\002\"\223\001\n\013EnumOptions\022\023\n\013allow_alias" - "\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005false\022C\n\024uni" - "nterpreted_option\030\347\007 \003(\0132$.google.protob" - "uf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\005\020\006\"" - "}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 \001(\010:" - "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$." - "google.protobuf.UninterpretedOption*\t\010\350\007" - "\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecated\030!" - " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003" - "(\0132$.google.protobuf.UninterpretedOption" - "*\t\010\350\007\020\200\200\200\200\002\"\255\002\n\rMethodOptions\022\031\n\ndepreca" - "ted\030! \001(\010:\005false\022_\n\021idempotency_level\030\" " - "\001(\0162/.google.protobuf.MethodOptions.Idem" - "potencyLevel:\023IDEMPOTENCY_UNKNOWN\022C\n\024uni" - "nterpreted_option\030\347\007 \003(\0132$.google.protob" - "uf.UninterpretedOption\"P\n\020IdempotencyLev" - "el\022\027\n\023IDEMPOTENCY_UNKNOWN\020\000\022\023\n\017NO_SIDE_E" - "FFECTS\020\001\022\016\n\nIDEMPOTENT\020\002*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023" - "UninterpretedOption\022;\n\004name\030\002 \003(\0132-.goog" - "le.protobuf.UninterpretedOption.NamePart" - "\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022positive_i" - "nt_value\030\004 \001(\004\022\032\n\022negative_int_value\030\005 \001" - "(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_value" - "\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010NameP" - "art\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002" - " \002(\010\"\325\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003(" - "\0132(.google.protobuf.SourceCodeInfo.Locat" - "ion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004sp" - "an\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031" - "\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_det" - "ached_comments\030\006 \003(\t\"\247\001\n\021GeneratedCodeIn" - "fo\022A\n\nannotation\030\001 \003(\0132-.google.protobuf" - ".GeneratedCodeInfo.Annotation\032O\n\nAnnotat" - "ion\022\020\n\004path\030\001 \003(\005B\002\020\001\022\023\n\013source_file\030\002 \001" - "(\t\022\r\n\005begin\030\003 \001(\005\022\013\n\003end\030\004 \001(\005B\214\001\n\023com.g" - "oogle.protobufB\020DescriptorProtosH\001Z>gith" - "ub.com/golang/protobuf/protoc-gen-go/des" - "criptor;descriptor\242\002\003GPB\252\002\032Google.Protob" - "uf.Reflection" - }; - ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( - descriptor, 5813); - ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( - "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); -} -} // anonymous namespace - -void AddDescriptors() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl); +const char descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n google/protobuf/descriptor.proto\022\017goog" + "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file" + "\030\001 \003(\0132$.google.protobuf.FileDescriptorP" + "roto\"\333\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001" + "(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022" + "\031\n\021public_dependency\030\n \003(\005\022\027\n\017weak_depen" + "dency\030\013 \003(\005\0226\n\014message_type\030\004 \003(\0132 .goog" + "le.protobuf.DescriptorProto\0227\n\tenum_type" + "\030\005 \003(\0132$.google.protobuf.EnumDescriptorP" + "roto\0228\n\007service\030\006 \003(\0132\'.google.protobuf." + "ServiceDescriptorProto\0228\n\textension\030\007 \003(" + "\0132%.google.protobuf.FieldDescriptorProto" + "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File" + "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog" + "le.protobuf.SourceCodeInfo\022\016\n\006syntax\030\014 \001" + "(\t\"\251\005\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005" + "field\030\002 \003(\0132%.google.protobuf.FieldDescr" + "iptorProto\0228\n\textension\030\006 \003(\0132%.google.p" + "rotobuf.FieldDescriptorProto\0225\n\013nested_t" + "ype\030\003 \003(\0132 .google.protobuf.DescriptorPr" + "oto\0227\n\tenum_type\030\004 \003(\0132$.google.protobuf" + ".EnumDescriptorProto\022H\n\017extension_range\030" + "\005 \003(\0132/.google.protobuf.DescriptorProto." + "ExtensionRange\0229\n\noneof_decl\030\010 \003(\0132%.goo" + "gle.protobuf.OneofDescriptorProto\0220\n\007opt" + "ions\030\007 \001(\0132\037.google.protobuf.MessageOpti" + "ons\022F\n\016reserved_range\030\t \003(\0132..google.pro" + "tobuf.DescriptorProto.ReservedRange\022\025\n\rr" + "eserved_name\030\n \003(\t\032e\n\016ExtensionRange\022\r\n\005" + "start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\0227\n\007options\030\003 \001(" + "\0132&.google.protobuf.ExtensionRangeOption" + "s\032+\n\rReservedRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end" + "\030\002 \001(\005\"g\n\025ExtensionRangeOptions\022C\n\024unint" + "erpreted_option\030\347\007 \003(\0132$.google.protobuf" + ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\325\005\n\024Fiel" + "dDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number" + "\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobuf." + "FieldDescriptorProto.Label\0228\n\004type\030\005 \001(\016" + "2*.google.protobuf.FieldDescriptorProto." + "Type\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001(" + "\t\022\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_index\030" + "\t \001(\005\022\021\n\tjson_name\030\n \001(\t\022.\n\007options\030\010 \001(" + "\0132\035.google.protobuf.FieldOptions\022\027\n\017prot" + "o3_optional\030\021 \001(\010\"\266\002\n\004Type\022\017\n\013TYPE_DOUBL" + "E\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013T" + "YPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIX" + "ED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022" + "\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE" + "_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT3" + "2\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n" + "\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYP" + "E_SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022" + "\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"" + "T\n\024OneofDescriptorProto\022\014\n\004name\030\001 \001(\t\022.\n" + "\007options\030\002 \001(\0132\035.google.protobuf.OneofOp" + "tions\"\244\002\n\023EnumDescriptorProto\022\014\n\004name\030\001 " + "\001(\t\0228\n\005value\030\002 \003(\0132).google.protobuf.Enu" + "mValueDescriptorProto\022-\n\007options\030\003 \001(\0132\034" + ".google.protobuf.EnumOptions\022N\n\016reserved" + "_range\030\004 \003(\01326.google.protobuf.EnumDescr" + "iptorProto.EnumReservedRange\022\025\n\rreserved" + "_name\030\005 \003(\t\032/\n\021EnumReservedRange\022\r\n\005star" + "t\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"l\n\030EnumValueDescrip" + "torProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222" + "\n\007options\030\003 \001(\0132!.google.protobuf.EnumVa" + "lueOptions\"\220\001\n\026ServiceDescriptorProto\022\014\n" + "\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.pro" + "tobuf.MethodDescriptorProto\0220\n\007options\030\003" + " \001(\0132\037.google.protobuf.ServiceOptions\"\301\001" + "\n\025MethodDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n" + "\ninput_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/" + "\n\007options\030\004 \001(\0132\036.google.protobuf.Method" + "Options\022\037\n\020client_streaming\030\005 \001(\010:\005false" + "\022\037\n\020server_streaming\030\006 \001(\010:\005false\"\245\006\n\013Fi" + "leOptions\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java_" + "outer_classname\030\010 \001(\t\022\"\n\023java_multiple_f" + "iles\030\n \001(\010:\005false\022)\n\035java_generate_equal" + "s_and_hash\030\024 \001(\010B\002\030\001\022%\n\026java_string_chec" + "k_utf8\030\033 \001(\010:\005false\022F\n\014optimize_for\030\t \001(" + "\0162).google.protobuf.FileOptions.Optimize" + "Mode:\005SPEED\022\022\n\ngo_package\030\013 \001(\t\022\"\n\023cc_ge" + "neric_services\030\020 \001(\010:\005false\022$\n\025java_gene" + "ric_services\030\021 \001(\010:\005false\022\"\n\023py_generic_" + "services\030\022 \001(\010:\005false\022#\n\024php_generic_ser" + "vices\030* \001(\010:\005false\022\031\n\ndeprecated\030\027 \001(\010:\005" + "false\022\036\n\020cc_enable_arenas\030\037 \001(\010:\004true\022\031\n" + "\021objc_class_prefix\030$ \001(\t\022\030\n\020csharp_names" + "pace\030% \001(\t\022\024\n\014swift_prefix\030\' \001(\t\022\030\n\020php_" + "class_prefix\030( \001(\t\022\025\n\rphp_namespace\030) \001(" + "\t\022\036\n\026php_metadata_namespace\030, \001(\t\022\024\n\014rub" + "y_package\030- \001(\t\022C\n\024uninterpreted_option\030" + "\347\007 \003(\0132$.google.protobuf.UninterpretedOp" + "tion\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_" + "SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002J\004\010&\020" + "\'\"\362\001\n\016MessageOptions\022&\n\027message_set_wire" + "_format\030\001 \001(\010:\005false\022.\n\037no_standard_desc" + "riptor_accessor\030\002 \001(\010:\005false\022\031\n\ndeprecat" + "ed\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024un" + "interpreted_option\030\347\007 \003(\0132$.google.proto" + "buf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\010\020\t" + "J\004\010\t\020\n\"\236\003\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#" + ".google.protobuf.FieldOptions.CType:\006STR" + "ING\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$.go" + "ogle.protobuf.FieldOptions.JSType:\tJS_NO" + "RMAL\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecated\030" + "\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024uni" + "nterpreted_option\030\347\007 \003(\0132$.google.protob" + "uf.UninterpretedOption\"/\n\005CType\022\n\n\006STRIN" + "G\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002\"5\n\006JSTyp" + "e\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020\001\022\r\n\tJS_NU" + "MBER\020\002*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005\"^\n\014OneofOptions\022" + "C\n\024uninterpreted_option\030\347\007 \003(\0132$.google." + "protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"" + "\223\001\n\013EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\n" + "deprecated\030\003 \001(\010:\005false\022C\n\024uninterpreted" + "_option\030\347\007 \003(\0132$.google.protobuf.Uninter" + "pretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\005\020\006\"}\n\020EnumVal" + "ueOptions\022\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024" + "uninterpreted_option\030\347\007 \003(\0132$.google.pro" + "tobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016" + "ServiceOptions\022\031\n\ndeprecated\030! \001(\010:\005fals" + "e\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.googl" + "e.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200" + "\002\"\255\002\n\rMethodOptions\022\031\n\ndeprecated\030! \001(\010:" + "\005false\022_\n\021idempotency_level\030\" \001(\0162/.goog" + "le.protobuf.MethodOptions.IdempotencyLev" + "el:\023IDEMPOTENCY_UNKNOWN\022C\n\024uninterpreted" + "_option\030\347\007 \003(\0132$.google.protobuf.Uninter" + "pretedOption\"P\n\020IdempotencyLevel\022\027\n\023IDEM" + "POTENCY_UNKNOWN\020\000\022\023\n\017NO_SIDE_EFFECTS\020\001\022\016" + "\n\nIDEMPOTENT\020\002*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023Uninterpre" + "tedOption\022;\n\004name\030\002 \003(\0132-.google.protobu" + "f.UninterpretedOption.NamePart\022\030\n\020identi" + "fier_value\030\003 \001(\t\022\032\n\022positive_int_value\030\004" + " \001(\004\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014doub" + "le_value\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017" + "aggregate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tnam" + "e_part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\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\"\247\001\n\021GeneratedCodeInfo\022A\n\nanno" + "tation\030\001 \003(\0132-.google.protobuf.Generated" + "CodeInfo.Annotation\032O\n\nAnnotation\022\020\n\004pat" + "h\030\001 \003(\005B\002\020\001\022\023\n\013source_file\030\002 \001(\t\022\r\n\005begi" + "n\030\003 \001(\005\022\013\n\003end\030\004 \001(\005B~\n\023com.google.proto" + "bufB\020DescriptorProtosH\001Z-google.golang.o" + "rg/protobuf/types/descriptorpb\370\001\001\242\002\003GPB\252" + "\002\032Google.Protobuf.Reflection" + ; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto = { + false, false, 6028, descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto, "google/protobuf/descriptor.proto", + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, nullptr, 0, 27, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto, file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata +descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(int index) { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); + return descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[index]; } -// Force AddDescriptors() to be called at dynamic initialization time. -struct StaticDescriptorInitializer { - StaticDescriptorInitializer() { - AddDescriptors(); - } -} static_descriptor_initializer; -} // namespace protobuf_google_2fprotobuf_2fdescriptor_2eproto - -const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_enum_descriptors[0]; +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fdescriptor_2eproto(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); +PROTOBUF_NAMESPACE_OPEN +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldDescriptorProto_Type_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[0]; } bool FieldDescriptorProto_Type_IsValid(int value) { switch (value) { @@ -930,32 +1094,32 @@ bool FieldDescriptorProto_Type_IsValid(int value) { } } -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_DOUBLE; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FLOAT; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_INT64; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_UINT64; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_INT32; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FIXED64; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FIXED32; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_BOOL; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_STRING; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_GROUP; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_MESSAGE; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_BYTES; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_UINT32; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_ENUM; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SFIXED32; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SFIXED64; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT32; -const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT64; -const FieldDescriptorProto_Type FieldDescriptorProto::Type_MIN; -const FieldDescriptorProto_Type FieldDescriptorProto::Type_MAX; -const int FieldDescriptorProto::Type_ARRAYSIZE; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 -const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_enum_descriptors[1]; +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900) +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_DOUBLE; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FLOAT; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_INT64; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_UINT64; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_INT32; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FIXED64; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FIXED32; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_BOOL; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_STRING; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_GROUP; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_MESSAGE; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_BYTES; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_UINT32; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_ENUM; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SFIXED32; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SFIXED64; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT32; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT64; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::Type_MIN; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::Type_MAX; +constexpr int FieldDescriptorProto::Type_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900) +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldDescriptorProto_Label_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[1]; } bool FieldDescriptorProto_Label_IsValid(int value) { switch (value) { @@ -968,17 +1132,17 @@ bool FieldDescriptorProto_Label_IsValid(int value) { } } -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const FieldDescriptorProto_Label FieldDescriptorProto::LABEL_OPTIONAL; -const FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REQUIRED; -const FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REPEATED; -const FieldDescriptorProto_Label FieldDescriptorProto::Label_MIN; -const FieldDescriptorProto_Label FieldDescriptorProto::Label_MAX; -const int FieldDescriptorProto::Label_ARRAYSIZE; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 -const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_enum_descriptors[2]; +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900) +constexpr FieldDescriptorProto_Label FieldDescriptorProto::LABEL_OPTIONAL; +constexpr FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REQUIRED; +constexpr FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REPEATED; +constexpr FieldDescriptorProto_Label FieldDescriptorProto::Label_MIN; +constexpr FieldDescriptorProto_Label FieldDescriptorProto::Label_MAX; +constexpr int FieldDescriptorProto::Label_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900) +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FileOptions_OptimizeMode_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[2]; } bool FileOptions_OptimizeMode_IsValid(int value) { switch (value) { @@ -991,17 +1155,17 @@ bool FileOptions_OptimizeMode_IsValid(int value) { } } -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const FileOptions_OptimizeMode FileOptions::SPEED; -const FileOptions_OptimizeMode FileOptions::CODE_SIZE; -const FileOptions_OptimizeMode FileOptions::LITE_RUNTIME; -const FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN; -const FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX; -const int FileOptions::OptimizeMode_ARRAYSIZE; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 -const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_enum_descriptors[3]; +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900) +constexpr FileOptions_OptimizeMode FileOptions::SPEED; +constexpr FileOptions_OptimizeMode FileOptions::CODE_SIZE; +constexpr FileOptions_OptimizeMode FileOptions::LITE_RUNTIME; +constexpr FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN; +constexpr FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX; +constexpr int FileOptions::OptimizeMode_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900) +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldOptions_CType_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[3]; } bool FieldOptions_CType_IsValid(int value) { switch (value) { @@ -1014,17 +1178,17 @@ bool FieldOptions_CType_IsValid(int value) { } } -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const FieldOptions_CType FieldOptions::STRING; -const FieldOptions_CType FieldOptions::CORD; -const FieldOptions_CType FieldOptions::STRING_PIECE; -const FieldOptions_CType FieldOptions::CType_MIN; -const FieldOptions_CType FieldOptions::CType_MAX; -const int FieldOptions::CType_ARRAYSIZE; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 -const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_enum_descriptors[4]; +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900) +constexpr FieldOptions_CType FieldOptions::STRING; +constexpr FieldOptions_CType FieldOptions::CORD; +constexpr FieldOptions_CType FieldOptions::STRING_PIECE; +constexpr FieldOptions_CType FieldOptions::CType_MIN; +constexpr FieldOptions_CType FieldOptions::CType_MAX; +constexpr int FieldOptions::CType_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900) +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldOptions_JSType_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[4]; } bool FieldOptions_JSType_IsValid(int value) { switch (value) { @@ -1037,17 +1201,17 @@ bool FieldOptions_JSType_IsValid(int value) { } } -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const FieldOptions_JSType FieldOptions::JS_NORMAL; -const FieldOptions_JSType FieldOptions::JS_STRING; -const FieldOptions_JSType FieldOptions::JS_NUMBER; -const FieldOptions_JSType FieldOptions::JSType_MIN; -const FieldOptions_JSType FieldOptions::JSType_MAX; -const int FieldOptions::JSType_ARRAYSIZE; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 -const ::google::protobuf::EnumDescriptor* MethodOptions_IdempotencyLevel_descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_enum_descriptors[5]; +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900) +constexpr FieldOptions_JSType FieldOptions::JS_NORMAL; +constexpr FieldOptions_JSType FieldOptions::JS_STRING; +constexpr FieldOptions_JSType FieldOptions::JS_NUMBER; +constexpr FieldOptions_JSType FieldOptions::JSType_MIN; +constexpr FieldOptions_JSType FieldOptions::JSType_MAX; +constexpr int FieldOptions::JSType_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900) +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* MethodOptions_IdempotencyLevel_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[5]; } bool MethodOptions_IdempotencyLevel_IsValid(int value) { switch (value) { @@ -1060,165 +1224,126 @@ bool MethodOptions_IdempotencyLevel_IsValid(int value) { } } -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const MethodOptions_IdempotencyLevel MethodOptions::IDEMPOTENCY_UNKNOWN; -const MethodOptions_IdempotencyLevel MethodOptions::NO_SIDE_EFFECTS; -const MethodOptions_IdempotencyLevel MethodOptions::IDEMPOTENT; -const MethodOptions_IdempotencyLevel MethodOptions::IdempotencyLevel_MIN; -const MethodOptions_IdempotencyLevel MethodOptions::IdempotencyLevel_MAX; -const int MethodOptions::IdempotencyLevel_ARRAYSIZE; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900) +constexpr MethodOptions_IdempotencyLevel MethodOptions::IDEMPOTENCY_UNKNOWN; +constexpr MethodOptions_IdempotencyLevel MethodOptions::NO_SIDE_EFFECTS; +constexpr MethodOptions_IdempotencyLevel MethodOptions::IDEMPOTENT; +constexpr MethodOptions_IdempotencyLevel MethodOptions::IdempotencyLevel_MIN; +constexpr MethodOptions_IdempotencyLevel MethodOptions::IdempotencyLevel_MAX; +constexpr int MethodOptions::IdempotencyLevel_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900) // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int FileDescriptorSet::kFileFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +class FileDescriptorSet::_Internal { + public: +}; -FileDescriptorSet::FileDescriptorSet() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - } +FileDescriptorSet::FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + file_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorSet) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.FileDescriptorSet) } FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0), + : ::PROTOBUF_NAMESPACE_ID::Message(), file_(from.file_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorSet) } void FileDescriptorSet::SharedCtor() { - _cached_size_ = 0; } FileDescriptorSet::~FileDescriptorSet() { // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorSet) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void FileDescriptorSet::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); } -void FileDescriptorSet::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* FileDescriptorSet::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void FileDescriptorSet::ArenaDtor(void* object) { + FileDescriptorSet* _this = reinterpret_cast< FileDescriptorSet* >(object); + (void)_this; } - -const FileDescriptorSet& FileDescriptorSet::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void FileDescriptorSet::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -FileDescriptorSet* FileDescriptorSet::New(::google::protobuf::Arena* arena) const { - FileDescriptorSet* n = new FileDescriptorSet; - if (arena != NULL) { - arena->Own(n); - } - return n; +void FileDescriptorSet::SetCachedSize(int size) const { + _cached_size_.Set(size); } void FileDescriptorSet::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorSet) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; file_.Clear(); - _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool FileDescriptorSet::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.FileDescriptorSet) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // repeated .google.protobuf.FileDescriptorProto file = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_file())); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* FileDescriptorSet::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // repeated .google.protobuf.FileDescriptorProto file = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_file(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.FileDescriptorSet) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.FileDescriptorSet) - return false; -#undef DO_ -} - -void FileDescriptorSet::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.FileDescriptorSet) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // repeated .google.protobuf.FileDescriptorProto file = 1; - for (unsigned int i = 0, - n = static_cast(this->file_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 1, this->file(static_cast(i)), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.FileDescriptorSet) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* FileDescriptorSet::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* FileDescriptorSet::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorSet) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // repeated .google.protobuf.FileDescriptorProto file = 1; for (unsigned int i = 0, - n = static_cast(this->file_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 1, this->file(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_file_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(1, this->_internal_file(i), target, stream); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorSet) return target; @@ -1228,38 +1353,35 @@ size_t FileDescriptorSet::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorSet) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.FileDescriptorProto file = 1; - { - unsigned int count = static_cast(this->file_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->file(static_cast(i))); - } + total_size += 1UL * this->_internal_file_size(); + for (const auto& msg : this->file_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void FileDescriptorSet::MergeFrom(const ::google::protobuf::Message& from) { +void FileDescriptorSet::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileDescriptorSet) GOOGLE_DCHECK_NE(&from, this); const FileDescriptorSet* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileDescriptorSet) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileDescriptorSet) MergeFrom(*source); @@ -1269,14 +1391,14 @@ void FileDescriptorSet::MergeFrom(const ::google::protobuf::Message& from) { void FileDescriptorSet::MergeFrom(const FileDescriptorSet& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorSet) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; file_.MergeFrom(from.file_); } -void FileDescriptorSet::CopyFrom(const ::google::protobuf::Message& from) { +void FileDescriptorSet::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileDescriptorSet) if (&from == this) return; Clear(); @@ -1291,92 +1413,69 @@ void FileDescriptorSet::CopyFrom(const FileDescriptorSet& from) { } bool FileDescriptorSet::IsInitialized() const { - if (!::google::protobuf::internal::AllAreInitialized(this->file())) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(file_)) return false; return true; } -void FileDescriptorSet::Swap(FileDescriptorSet* other) { - if (other == this) return; - InternalSwap(other); -} void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); file_.InternalSwap(&other->file_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata FileDescriptorSet::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// FileDescriptorSet - -// repeated .google.protobuf.FileDescriptorProto file = 1; -int FileDescriptorSet::file_size() const { - return file_.size(); -} -void FileDescriptorSet::clear_file() { - file_.Clear(); -} -const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorSet.file) - return file_.Get(index); -} -::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorSet.file) - return file_.Mutable(index); -} -::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() { - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file) - return file_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* -FileDescriptorSet::mutable_file() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file) - return &file_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& -FileDescriptorSet::file() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file) - return file_; +::PROTOBUF_NAMESPACE_ID::Metadata FileDescriptorSet::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int FileDescriptorProto::kNameFieldNumber; -const int FileDescriptorProto::kPackageFieldNumber; -const int FileDescriptorProto::kDependencyFieldNumber; -const int FileDescriptorProto::kPublicDependencyFieldNumber; -const int FileDescriptorProto::kWeakDependencyFieldNumber; -const int FileDescriptorProto::kMessageTypeFieldNumber; -const int FileDescriptorProto::kEnumTypeFieldNumber; -const int FileDescriptorProto::kServiceFieldNumber; -const int FileDescriptorProto::kExtensionFieldNumber; -const int FileDescriptorProto::kOptionsFieldNumber; -const int FileDescriptorProto::kSourceCodeInfoFieldNumber; -const int FileDescriptorProto::kSyntaxFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -FileDescriptorProto::FileDescriptorProto() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class FileDescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_package(HasBits* has_bits) { + (*has_bits)[0] |= 2u; } + static const PROTOBUF_NAMESPACE_ID::FileOptions& options(const FileDescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } + static const PROTOBUF_NAMESPACE_ID::SourceCodeInfo& source_code_info(const FileDescriptorProto* msg); + static void set_has_source_code_info(HasBits* has_bits) { + (*has_bits)[0] |= 16u; + } + static void set_has_syntax(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } +}; + +const PROTOBUF_NAMESPACE_ID::FileOptions& +FileDescriptorProto::_Internal::options(const FileDescriptorProto* msg) { + return *msg->options_; +} +const PROTOBUF_NAMESPACE_ID::SourceCodeInfo& +FileDescriptorProto::_Internal::source_code_info(const FileDescriptorProto* msg) { + return *msg->source_code_info_; +} +FileDescriptorProto::FileDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + dependency_(arena), + message_type_(arena), + enum_type_(arena), + service_(arena), + extension_(arena), + public_dependency_(arena), + weak_dependency_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorProto) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.FileDescriptorProto) } FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), _has_bits_(from._has_bits_), - _cached_size_(0), dependency_(from.dependency_), message_type_(from.message_type_), enum_type_(from.enum_type_), @@ -1384,81 +1483,73 @@ FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from) extension_(from.extension_), public_dependency_(from.public_dependency_), weak_dependency_(from.weak_dependency_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_name()) { - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); - } - package_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_package()) { - package_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.package_); - } - syntax_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_syntax()) { - syntax_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.syntax_); - } - if (from.has_options()) { - options_ = new ::google::protobuf::FileOptions(*from.options_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_name()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArena()); + } + package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_package()) { + package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_package(), + GetArena()); + } + syntax_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_syntax()) { + syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_syntax(), + GetArena()); + } + if (from._internal_has_options()) { + options_ = new PROTOBUF_NAMESPACE_ID::FileOptions(*from.options_); } else { - options_ = NULL; + options_ = nullptr; } - if (from.has_source_code_info()) { - source_code_info_ = new ::google::protobuf::SourceCodeInfo(*from.source_code_info_); + if (from._internal_has_source_code_info()) { + source_code_info_ = new PROTOBUF_NAMESPACE_ID::SourceCodeInfo(*from.source_code_info_); } else { - source_code_info_ = NULL; + source_code_info_ = nullptr; } // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorProto) } void FileDescriptorProto::SharedCtor() { - _cached_size_ = 0; - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - package_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - syntax_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - ::memset(&options_, 0, static_cast( - reinterpret_cast(&source_code_info_) - - reinterpret_cast(&options_)) + sizeof(source_code_info_)); +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +syntax_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&options_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&source_code_info_) - + reinterpret_cast(&options_)) + sizeof(source_code_info_)); } FileDescriptorProto::~FileDescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorProto) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void FileDescriptorProto::SharedDtor() { - name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - syntax_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + package_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + syntax_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (this != internal_default_instance()) delete options_; if (this != internal_default_instance()) delete source_code_info_; } -void FileDescriptorProto::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* FileDescriptorProto::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void FileDescriptorProto::ArenaDtor(void* object) { + FileDescriptorProto* _this = reinterpret_cast< FileDescriptorProto* >(object); + (void)_this; } - -const FileDescriptorProto& FileDescriptorProto::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void FileDescriptorProto::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -FileDescriptorProto* FileDescriptorProto::New(::google::protobuf::Arena* arena) const { - FileDescriptorProto* n = new FileDescriptorProto; - if (arena != NULL) { - arena->Own(n); - } - return n; +void FileDescriptorProto::SetCachedSize(int size) const { + _cached_size_.Set(size); } void FileDescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; @@ -1470,588 +1561,434 @@ void FileDescriptorProto::Clear() { public_dependency_.Clear(); weak_dependency_.Clear(); cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 31u) { + if (cached_has_bits & 0x0000001fu) { if (cached_has_bits & 0x00000001u) { - GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*name_.UnsafeRawStringPointer())->clear(); + name_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000002u) { - GOOGLE_DCHECK(!package_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*package_.UnsafeRawStringPointer())->clear(); + package_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000004u) { - GOOGLE_DCHECK(!syntax_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*syntax_.UnsafeRawStringPointer())->clear(); + syntax_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000008u) { - GOOGLE_DCHECK(options_ != NULL); - options_->::google::protobuf::FileOptions::Clear(); + GOOGLE_DCHECK(options_ != nullptr); + options_->Clear(); } if (cached_has_bits & 0x00000010u) { - GOOGLE_DCHECK(source_code_info_ != NULL); - source_code_info_->::google::protobuf::SourceCodeInfo::Clear(); + GOOGLE_DCHECK(source_code_info_ != nullptr); + source_code_info_->Clear(); } } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool FileDescriptorProto::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.FileDescriptorProto) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional string name = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FileDescriptorProto.name"); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* FileDescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FileDescriptorProto.name"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string package = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_package())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->package().data(), static_cast(this->package().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FileDescriptorProto.package"); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + auto str = _internal_mutable_package(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FileDescriptorProto.package"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated string dependency = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->add_dependency())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->dependency(this->dependency_size() - 1).data(), - static_cast(this->dependency(this->dependency_size() - 1).length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FileDescriptorProto.dependency"); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + ptr -= 1; + do { + ptr += 1; + auto str = _internal_add_dependency(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FileDescriptorProto.dependency"); + #endif // !NDEBUG + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr)); + } else goto handle_unusual; + continue; // repeated .google.protobuf.DescriptorProto message_type = 4; - case 4: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_message_type())); - } else { - goto handle_unusual; - } - break; - } - + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_message_type(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<34>(ptr)); + } else goto handle_unusual; + continue; // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; - case 5: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(42u /* 42 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_enum_type())); - } else { - goto handle_unusual; - } - break; - } - + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 42)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_enum_type(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<42>(ptr)); + } else goto handle_unusual; + continue; // repeated .google.protobuf.ServiceDescriptorProto service = 6; - case 6: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_service())); - } else { - goto handle_unusual; - } - break; - } - + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 50)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_service(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr)); + } else goto handle_unusual; + continue; // repeated .google.protobuf.FieldDescriptorProto extension = 7; - case 7: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(58u /* 58 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_extension())); - } else { - goto handle_unusual; - } - break; - } - + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 58)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_extension(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<58>(ptr)); + } else goto handle_unusual; + continue; // optional .google.protobuf.FileOptions options = 8; - case 8: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(66u /* 66 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, mutable_options())); - } else { - goto handle_unusual; - } - break; - } - + case 8: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 66)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional .google.protobuf.SourceCodeInfo source_code_info = 9; - case 9: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(74u /* 74 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, mutable_source_code_info())); - } else { - goto handle_unusual; - } - break; - } - + case 9: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 74)) { + ptr = ctx->ParseMessage(_internal_mutable_source_code_info(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated int32 public_dependency = 10; - case 10: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(80u /* 80 & 0xFF */)) { - DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - 1, 80u, input, this->mutable_public_dependency()))); - } else if ( - static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(82u /* 82 & 0xFF */)) { - DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, this->mutable_public_dependency()))); - } else { - goto handle_unusual; - } - break; - } - + case 10: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 80)) { + ptr -= 1; + do { + ptr += 1; + _internal_add_public_dependency(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr)); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<80>(ptr)); + } else if (static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 82) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_public_dependency(), ptr, ctx); + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated int32 weak_dependency = 11; - case 11: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(88u /* 88 & 0xFF */)) { - DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - 1, 88u, input, this->mutable_weak_dependency()))); - } else if ( - static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(90u /* 90 & 0xFF */)) { - DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, this->mutable_weak_dependency()))); - } else { - goto handle_unusual; - } - break; - } - + case 11: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 88)) { + ptr -= 1; + do { + ptr += 1; + _internal_add_weak_dependency(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr)); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<88>(ptr)); + } else if (static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 90) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_weak_dependency(), ptr, ctx); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string syntax = 12; - case 12: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(98u /* 98 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_syntax())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->syntax().data(), static_cast(this->syntax().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FileDescriptorProto.syntax"); - } else { - goto handle_unusual; - } - break; - } - + case 12: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 98)) { + auto str = _internal_mutable_syntax(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FileDescriptorProto.syntax"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.FileDescriptorProto) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.FileDescriptorProto) - return false; -#undef DO_ + ptr = nullptr; + goto success; +#undef CHK_ } -void FileDescriptorProto::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.FileDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; +::PROTOBUF_NAMESPACE_ID::uint8* FileDescriptorProto::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorProto) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional string name = 1; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FileDescriptorProto.name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->name(), output); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); } // optional string package = 2; if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->package().data(), static_cast(this->package().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_package().data(), static_cast(this->_internal_package().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FileDescriptorProto.package"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 2, this->package(), output); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_package(), target); } // repeated string dependency = 3; - for (int i = 0, n = this->dependency_size(); i < n; i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->dependency(i).data(), static_cast(this->dependency(i).length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + for (int i = 0, n = this->_internal_dependency_size(); i < n; i++) { + const auto& s = this->_internal_dependency(i); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + s.data(), static_cast(s.length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FileDescriptorProto.dependency"); - ::google::protobuf::internal::WireFormatLite::WriteString( - 3, this->dependency(i), output); + target = stream->WriteString(3, s, target); } // repeated .google.protobuf.DescriptorProto message_type = 4; for (unsigned int i = 0, - n = static_cast(this->message_type_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 4, this->message_type(static_cast(i)), output); + n = static_cast(this->_internal_message_type_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(4, this->_internal_message_type(i), target, stream); } // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; for (unsigned int i = 0, - n = static_cast(this->enum_type_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 5, this->enum_type(static_cast(i)), output); + n = static_cast(this->_internal_enum_type_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(5, this->_internal_enum_type(i), target, stream); } // repeated .google.protobuf.ServiceDescriptorProto service = 6; for (unsigned int i = 0, - n = static_cast(this->service_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 6, this->service(static_cast(i)), output); + n = static_cast(this->_internal_service_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(6, this->_internal_service(i), target, stream); } // repeated .google.protobuf.FieldDescriptorProto extension = 7; for (unsigned int i = 0, - n = static_cast(this->extension_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 7, this->extension(static_cast(i)), output); + n = static_cast(this->_internal_extension_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(7, this->_internal_extension(i), target, stream); } // optional .google.protobuf.FileOptions options = 8; if (cached_has_bits & 0x00000008u) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 8, *this->options_, output); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 8, _Internal::options(this), target, stream); } // optional .google.protobuf.SourceCodeInfo source_code_info = 9; if (cached_has_bits & 0x00000010u) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 9, *this->source_code_info_, output); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 9, _Internal::source_code_info(this), target, stream); } // repeated int32 public_dependency = 10; - for (int i = 0, n = this->public_dependency_size(); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteInt32( - 10, this->public_dependency(i), output); + for (int i = 0, n = this->_internal_public_dependency_size(); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(10, this->_internal_public_dependency(i), target); } // repeated int32 weak_dependency = 11; - for (int i = 0, n = this->weak_dependency_size(); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteInt32( - 11, this->weak_dependency(i), output); + for (int i = 0, n = this->_internal_weak_dependency_size(); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(11, this->_internal_weak_dependency(i), target); } // optional string syntax = 12; if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->syntax().data(), static_cast(this->syntax().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_syntax().data(), static_cast(this->_internal_syntax().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FileDescriptorProto.syntax"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 12, this->syntax(), output); + target = stream->WriteStringMaybeAliased( + 12, this->_internal_syntax(), target); } - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } - // @@protoc_insertion_point(serialize_end:google.protobuf.FileDescriptorProto) + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorProto) + return target; } -::google::protobuf::uint8* FileDescriptorProto::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileDescriptorProto.name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->name(), target); - } +size_t FileDescriptorProto::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorProto) + size_t total_size = 0; - // optional string package = 2; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->package().data(), static_cast(this->package().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileDescriptorProto.package"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 2, this->package(), target); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; // repeated string dependency = 3; - for (int i = 0, n = this->dependency_size(); i < n; i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->dependency(i).data(), static_cast(this->dependency(i).length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileDescriptorProto.dependency"); - target = ::google::protobuf::internal::WireFormatLite:: - WriteStringToArray(3, this->dependency(i), target); + total_size += 1 * + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(dependency_.size()); + for (int i = 0, n = dependency_.size(); i < n; i++) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + dependency_.Get(i)); } // repeated .google.protobuf.DescriptorProto message_type = 4; - for (unsigned int i = 0, - n = static_cast(this->message_type_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 4, this->message_type(static_cast(i)), deterministic, target); + total_size += 1UL * this->_internal_message_type_size(); + for (const auto& msg : this->message_type_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; - for (unsigned int i = 0, - n = static_cast(this->enum_type_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 5, this->enum_type(static_cast(i)), deterministic, target); + total_size += 1UL * this->_internal_enum_type_size(); + for (const auto& msg : this->enum_type_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // repeated .google.protobuf.ServiceDescriptorProto service = 6; - for (unsigned int i = 0, - n = static_cast(this->service_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 6, this->service(static_cast(i)), deterministic, target); + total_size += 1UL * this->_internal_service_size(); + for (const auto& msg : this->service_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // repeated .google.protobuf.FieldDescriptorProto extension = 7; - for (unsigned int i = 0, - n = static_cast(this->extension_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 7, this->extension(static_cast(i)), deterministic, target); - } - - // optional .google.protobuf.FileOptions options = 8; - if (cached_has_bits & 0x00000008u) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 8, *this->options_, deterministic, target); - } - - // optional .google.protobuf.SourceCodeInfo source_code_info = 9; - if (cached_has_bits & 0x00000010u) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 9, *this->source_code_info_, deterministic, target); + total_size += 1UL * this->_internal_extension_size(); + for (const auto& msg : this->extension_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // repeated int32 public_dependency = 10; - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArray(10, this->public_dependency_, target); + { + size_t data_size = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + Int32Size(this->public_dependency_); + total_size += 1 * + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(this->_internal_public_dependency_size()); + total_size += data_size; + } // repeated int32 weak_dependency = 11; - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArray(11, this->weak_dependency_, target); - - // optional string syntax = 12; - if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->syntax().data(), static_cast(this->syntax().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileDescriptorProto.syntax"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 12, this->syntax(), target); + { + size_t data_size = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + Int32Size(this->weak_dependency_); + total_size += 1 * + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(this->_internal_weak_dependency_size()); + total_size += data_size; } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorProto) - return target; -} + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x0000001fu) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } -size_t FileDescriptorProto::ByteSizeLong() const { -// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorProto) - size_t total_size = 0; - - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } - // repeated string dependency = 3; - total_size += 1 * - ::google::protobuf::internal::FromIntSize(this->dependency_size()); - for (int i = 0, n = this->dependency_size(); i < n; i++) { - total_size += ::google::protobuf::internal::WireFormatLite::StringSize( - this->dependency(i)); - } - - // repeated .google.protobuf.DescriptorProto message_type = 4; - { - unsigned int count = static_cast(this->message_type_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->message_type(static_cast(i))); - } - } - - // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; - { - unsigned int count = static_cast(this->enum_type_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->enum_type(static_cast(i))); - } - } - - // repeated .google.protobuf.ServiceDescriptorProto service = 6; - { - unsigned int count = static_cast(this->service_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->service(static_cast(i))); - } - } - - // repeated .google.protobuf.FieldDescriptorProto extension = 7; - { - unsigned int count = static_cast(this->extension_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->extension(static_cast(i))); - } - } - - // repeated int32 public_dependency = 10; - { - size_t data_size = ::google::protobuf::internal::WireFormatLite:: - Int32Size(this->public_dependency_); - total_size += 1 * - ::google::protobuf::internal::FromIntSize(this->public_dependency_size()); - total_size += data_size; - } - - // repeated int32 weak_dependency = 11; - { - size_t data_size = ::google::protobuf::internal::WireFormatLite:: - Int32Size(this->weak_dependency_); - total_size += 1 * - ::google::protobuf::internal::FromIntSize(this->weak_dependency_size()); - total_size += data_size; - } - - if (_has_bits_[0 / 32] & 31u) { - // optional string name = 1; - if (has_name()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->name()); - } - - // optional string package = 2; - if (has_package()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->package()); - } + // optional string package = 2; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_package()); + } // optional string syntax = 12; - if (has_syntax()) { + if (cached_has_bits & 0x00000004u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->syntax()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_syntax()); } // optional .google.protobuf.FileOptions options = 8; - if (has_options()) { + if (cached_has_bits & 0x00000008u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - *this->options_); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *options_); } // optional .google.protobuf.SourceCodeInfo source_code_info = 9; - if (has_source_code_info()) { + if (cached_has_bits & 0x00000010u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - *this->source_code_info_); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *source_code_info_); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void FileDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +void FileDescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileDescriptorProto) GOOGLE_DCHECK_NE(&from, this); const FileDescriptorProto* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileDescriptorProto) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileDescriptorProto) MergeFrom(*source); @@ -2061,8 +1998,8 @@ void FileDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorProto) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; dependency_.MergeFrom(from.dependency_); @@ -2073,29 +2010,26 @@ void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) { public_dependency_.MergeFrom(from.public_dependency_); weak_dependency_.MergeFrom(from.weak_dependency_); cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 31u) { + if (cached_has_bits & 0x0000001fu) { if (cached_has_bits & 0x00000001u) { - set_has_name(); - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); + _internal_set_name(from._internal_name()); } if (cached_has_bits & 0x00000002u) { - set_has_package(); - package_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.package_); + _internal_set_package(from._internal_package()); } if (cached_has_bits & 0x00000004u) { - set_has_syntax(); - syntax_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.syntax_); + _internal_set_syntax(from._internal_syntax()); } if (cached_has_bits & 0x00000008u) { - mutable_options()->::google::protobuf::FileOptions::MergeFrom(from.options()); + _internal_mutable_options()->PROTOBUF_NAMESPACE_ID::FileOptions::MergeFrom(from._internal_options()); } if (cached_has_bits & 0x00000010u) { - mutable_source_code_info()->::google::protobuf::SourceCodeInfo::MergeFrom(from.source_code_info()); + _internal_mutable_source_code_info()->PROTOBUF_NAMESPACE_ID::SourceCodeInfo::MergeFrom(from._internal_source_code_info()); } } } -void FileDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +void FileDescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileDescriptorProto) if (&from == this) return; Clear(); @@ -2110,22 +2044,20 @@ void FileDescriptorProto::CopyFrom(const FileDescriptorProto& from) { } bool FileDescriptorProto::IsInitialized() const { - if (!::google::protobuf::internal::AllAreInitialized(this->message_type())) return false; - if (!::google::protobuf::internal::AllAreInitialized(this->enum_type())) return false; - if (!::google::protobuf::internal::AllAreInitialized(this->service())) return false; - if (!::google::protobuf::internal::AllAreInitialized(this->extension())) return false; - if (has_options()) { - if (!this->options_->IsInitialized()) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(message_type_)) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(enum_type_)) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(service_)) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(extension_)) return false; + if (_internal_has_options()) { + if (!options_->IsInitialized()) return false; } return true; } -void FileDescriptorProto::Swap(FileDescriptorProto* other) { - if (other == this) return; - InternalSwap(other); -} void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); dependency_.InternalSwap(&other->dependency_); message_type_.InternalSwap(&other->message_type_); enum_type_.InternalSwap(&other->enum_type_); @@ -2133,582 +2065,57 @@ void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) { extension_.InternalSwap(&other->extension_); public_dependency_.InternalSwap(&other->public_dependency_); weak_dependency_.InternalSwap(&other->weak_dependency_); - name_.Swap(&other->name_); - package_.Swap(&other->package_); - syntax_.Swap(&other->syntax_); - swap(options_, other->options_); - swap(source_code_info_, other->source_code_info_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata FileDescriptorProto::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// FileDescriptorProto - -// optional string name = 1; -bool FileDescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void FileDescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; -} -void FileDescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; -} -void FileDescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); -} -const ::std::string& FileDescriptorProto::name() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name) - return name_.GetNoArena(); -} -void FileDescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.name) -} -#if LANG_CXX11 -void FileDescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.name) -} -#endif -void FileDescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name) -} -void FileDescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name) -} -::std::string* FileDescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FileDescriptorProto::release_name() { - // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FileDescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); - } else { - clear_has_name(); - } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name) -} - -// optional string package = 2; -bool FileDescriptorProto::has_package() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void FileDescriptorProto::set_has_package() { - _has_bits_[0] |= 0x00000002u; -} -void FileDescriptorProto::clear_has_package() { - _has_bits_[0] &= ~0x00000002u; -} -void FileDescriptorProto::clear_package() { - package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_package(); -} -const ::std::string& FileDescriptorProto::package() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package) - return package_.GetNoArena(); -} -void FileDescriptorProto::set_package(const ::std::string& value) { - set_has_package(); - package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.package) -} -#if LANG_CXX11 -void FileDescriptorProto::set_package(::std::string&& value) { - set_has_package(); - package_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.package) -} -#endif -void FileDescriptorProto::set_package(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_package(); - package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package) -} -void FileDescriptorProto::set_package(const char* value, size_t size) { - set_has_package(); - package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package) -} -::std::string* FileDescriptorProto::mutable_package() { - set_has_package(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package) - return package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FileDescriptorProto::release_package() { - // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.package) - clear_has_package(); - return package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FileDescriptorProto::set_allocated_package(::std::string* package) { - if (package != NULL) { - set_has_package(); - } else { - clear_has_package(); - } - package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), package); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package) -} - -// repeated string dependency = 3; -int FileDescriptorProto::dependency_size() const { - return dependency_.size(); -} -void FileDescriptorProto::clear_dependency() { - dependency_.Clear(); -} -const ::std::string& FileDescriptorProto::dependency(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.dependency) - return dependency_.Get(index); -} -::std::string* FileDescriptorProto::mutable_dependency(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.dependency) - return dependency_.Mutable(index); -} -void FileDescriptorProto::set_dependency(int index, const ::std::string& value) { - // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency) - dependency_.Mutable(index)->assign(value); -} -#if LANG_CXX11 -void FileDescriptorProto::set_dependency(int index, ::std::string&& value) { - // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency) - dependency_.Mutable(index)->assign(std::move(value)); -} -#endif -void FileDescriptorProto::set_dependency(int index, const char* value) { - GOOGLE_DCHECK(value != NULL); - dependency_.Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.dependency) -} -void FileDescriptorProto::set_dependency(int index, const char* value, size_t size) { - dependency_.Mutable(index)->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency) -} -::std::string* FileDescriptorProto::add_dependency() { - // @@protoc_insertion_point(field_add_mutable:google.protobuf.FileDescriptorProto.dependency) - return dependency_.Add(); -} -void FileDescriptorProto::add_dependency(const ::std::string& value) { - dependency_.Add()->assign(value); - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency) -} -#if LANG_CXX11 -void FileDescriptorProto::add_dependency(::std::string&& value) { - dependency_.Add(std::move(value)); - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency) -} -#endif -void FileDescriptorProto::add_dependency(const char* value) { - GOOGLE_DCHECK(value != NULL); - dependency_.Add()->assign(value); - // @@protoc_insertion_point(field_add_char:google.protobuf.FileDescriptorProto.dependency) -} -void FileDescriptorProto::add_dependency(const char* value, size_t size) { - dependency_.Add()->assign(reinterpret_cast(value), size); - // @@protoc_insertion_point(field_add_pointer:google.protobuf.FileDescriptorProto.dependency) -} -const ::google::protobuf::RepeatedPtrField< ::std::string>& -FileDescriptorProto::dependency() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.dependency) - return dependency_; -} -::google::protobuf::RepeatedPtrField< ::std::string>* -FileDescriptorProto::mutable_dependency() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.dependency) - return &dependency_; -} - -// repeated int32 public_dependency = 10; -int FileDescriptorProto::public_dependency_size() const { - return public_dependency_.size(); -} -void FileDescriptorProto::clear_public_dependency() { - public_dependency_.Clear(); -} -::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.public_dependency) - return public_dependency_.Get(index); -} -void FileDescriptorProto::set_public_dependency(int index, ::google::protobuf::int32 value) { - public_dependency_.Set(index, value); - // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.public_dependency) -} -void FileDescriptorProto::add_public_dependency(::google::protobuf::int32 value) { - public_dependency_.Add(value); - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.public_dependency) -} -const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& -FileDescriptorProto::public_dependency() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.public_dependency) - return public_dependency_; -} -::google::protobuf::RepeatedField< ::google::protobuf::int32 >* -FileDescriptorProto::mutable_public_dependency() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.public_dependency) - return &public_dependency_; -} - -// repeated int32 weak_dependency = 11; -int FileDescriptorProto::weak_dependency_size() const { - return weak_dependency_.size(); -} -void FileDescriptorProto::clear_weak_dependency() { - weak_dependency_.Clear(); -} -::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.weak_dependency) - return weak_dependency_.Get(index); -} -void FileDescriptorProto::set_weak_dependency(int index, ::google::protobuf::int32 value) { - weak_dependency_.Set(index, value); - // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.weak_dependency) -} -void FileDescriptorProto::add_weak_dependency(::google::protobuf::int32 value) { - weak_dependency_.Add(value); - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.weak_dependency) -} -const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& -FileDescriptorProto::weak_dependency() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.weak_dependency) - return weak_dependency_; -} -::google::protobuf::RepeatedField< ::google::protobuf::int32 >* -FileDescriptorProto::mutable_weak_dependency() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.weak_dependency) - return &weak_dependency_; + name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + package_.Swap(&other->package_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + syntax_.Swap(&other->syntax_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(FileDescriptorProto, source_code_info_) + + sizeof(FileDescriptorProto::source_code_info_) + - PROTOBUF_FIELD_OFFSET(FileDescriptorProto, options_)>( + reinterpret_cast(&options_), + reinterpret_cast(&other->options_)); } -// repeated .google.protobuf.DescriptorProto message_type = 4; -int FileDescriptorProto::message_type_size() const { - return message_type_.size(); -} -void FileDescriptorProto::clear_message_type() { - message_type_.Clear(); -} -const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.message_type) - return message_type_.Get(index); -} -::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.message_type) - return message_type_.Mutable(index); -} -::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() { - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type) - return message_type_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* -FileDescriptorProto::mutable_message_type() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type) - return &message_type_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& -FileDescriptorProto::message_type() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type) - return message_type_; +::PROTOBUF_NAMESPACE_ID::Metadata FileDescriptorProto::GetMetadata() const { + return GetMetadataStatic(); } -// repeated .google.protobuf.EnumDescriptorProto enum_type = 5; -int FileDescriptorProto::enum_type_size() const { - return enum_type_.size(); -} -void FileDescriptorProto::clear_enum_type() { - enum_type_.Clear(); -} -const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.enum_type) - return enum_type_.Get(index); -} -::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.enum_type) - return enum_type_.Mutable(index); -} -::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() { - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type) - return enum_type_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* -FileDescriptorProto::mutable_enum_type() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type) - return &enum_type_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& -FileDescriptorProto::enum_type() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type) - return enum_type_; -} -// repeated .google.protobuf.ServiceDescriptorProto service = 6; -int FileDescriptorProto::service_size() const { - return service_.size(); -} -void FileDescriptorProto::clear_service() { - service_.Clear(); -} -const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.service) - return service_.Get(index); -} -::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.service) - return service_.Mutable(index); -} -::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() { - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service) - return service_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* -FileDescriptorProto::mutable_service() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service) - return &service_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& -FileDescriptorProto::service() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service) - return service_; -} +// =================================================================== -// repeated .google.protobuf.FieldDescriptorProto extension = 7; -int FileDescriptorProto::extension_size() const { - return extension_.size(); -} -void FileDescriptorProto::clear_extension() { - extension_.Clear(); -} -const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.extension) - return extension_.Get(index); -} -::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.extension) - return extension_.Mutable(index); -} -::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() { - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension) - return extension_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* -FileDescriptorProto::mutable_extension() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension) - return &extension_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& -FileDescriptorProto::extension() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension) - return extension_; -} - -// optional .google.protobuf.FileOptions options = 8; -bool FileDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000008u) != 0; -} -void FileDescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000008u; -} -void FileDescriptorProto::clear_has_options() { - _has_bits_[0] &= ~0x00000008u; -} -void FileDescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear(); - clear_has_options(); -} -const ::google::protobuf::FileOptions& FileDescriptorProto::options() const { - const ::google::protobuf::FileOptions* p = options_; - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_FileOptions_default_instance_); -} -::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::FileOptions; - } - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options) - return options_; -} -::google::protobuf::FileOptions* FileDescriptorProto::release_options() { - // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.options) - clear_has_options(); - ::google::protobuf::FileOptions* temp = options_; - options_ = NULL; - return temp; -} -void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) { - delete options_; - options_ = options; - if (options) { - set_has_options(); - } else { - clear_has_options(); +class DescriptorProto_ExtensionRange::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_start(HasBits* has_bits) { + (*has_bits)[0] |= 2u; } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options) -} - -// optional .google.protobuf.SourceCodeInfo source_code_info = 9; -bool FileDescriptorProto::has_source_code_info() const { - return (_has_bits_[0] & 0x00000010u) != 0; -} -void FileDescriptorProto::set_has_source_code_info() { - _has_bits_[0] |= 0x00000010u; -} -void FileDescriptorProto::clear_has_source_code_info() { - _has_bits_[0] &= ~0x00000010u; -} -void FileDescriptorProto::clear_source_code_info() { - if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear(); - clear_has_source_code_info(); -} -const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const { - const ::google::protobuf::SourceCodeInfo* p = source_code_info_; - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_SourceCodeInfo_default_instance_); -} -::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() { - set_has_source_code_info(); - if (source_code_info_ == NULL) { - source_code_info_ = new ::google::protobuf::SourceCodeInfo; + static void set_has_end(HasBits* has_bits) { + (*has_bits)[0] |= 4u; } - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info) - return source_code_info_; -} -::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() { - // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.source_code_info) - clear_has_source_code_info(); - ::google::protobuf::SourceCodeInfo* temp = source_code_info_; - source_code_info_ = NULL; - return temp; -} -void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) { - delete source_code_info_; - source_code_info_ = source_code_info; - if (source_code_info) { - set_has_source_code_info(); - } else { - clear_has_source_code_info(); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info) -} - -// optional string syntax = 12; -bool FileDescriptorProto::has_syntax() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -void FileDescriptorProto::set_has_syntax() { - _has_bits_[0] |= 0x00000004u; -} -void FileDescriptorProto::clear_has_syntax() { - _has_bits_[0] &= ~0x00000004u; -} -void FileDescriptorProto::clear_syntax() { - syntax_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_syntax(); -} -const ::std::string& FileDescriptorProto::syntax() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.syntax) - return syntax_.GetNoArena(); -} -void FileDescriptorProto::set_syntax(const ::std::string& value) { - set_has_syntax(); - syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.syntax) -} -#if LANG_CXX11 -void FileDescriptorProto::set_syntax(::std::string&& value) { - set_has_syntax(); - syntax_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.syntax) -} -#endif -void FileDescriptorProto::set_syntax(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_syntax(); - syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.syntax) -} -void FileDescriptorProto::set_syntax(const char* value, size_t size) { - set_has_syntax(); - syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.syntax) -} -::std::string* FileDescriptorProto::mutable_syntax() { - set_has_syntax(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.syntax) - return syntax_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FileDescriptorProto::release_syntax() { - // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.syntax) - clear_has_syntax(); - return syntax_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FileDescriptorProto::set_allocated_syntax(::std::string* syntax) { - if (syntax != NULL) { - set_has_syntax(); - } else { - clear_has_syntax(); + static const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& options(const DescriptorProto_ExtensionRange* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } - syntax_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), syntax); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax) -} - -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS - -// =================================================================== - -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int DescriptorProto_ExtensionRange::kStartFieldNumber; -const int DescriptorProto_ExtensionRange::kEndFieldNumber; -const int DescriptorProto_ExtensionRange::kOptionsFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +}; -DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - } +const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& +DescriptorProto_ExtensionRange::_Internal::options(const DescriptorProto_ExtensionRange* msg) { + return *msg->options_; +} +DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto.ExtensionRange) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto.ExtensionRange) } DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - if (from.has_options()) { - options_ = new ::google::protobuf::ExtensionRangeOptions(*from.options_); + : ::PROTOBUF_NAMESPACE_ID::Message(), + _has_bits_(from._has_bits_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + if (from._internal_has_options()) { + options_ = new PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions(*from.options_); } else { - options_ = NULL; + options_ = nullptr; } ::memcpy(&start_, &from.start_, static_cast(reinterpret_cast(&end_) - @@ -2717,192 +2124,137 @@ DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorP } void DescriptorProto_ExtensionRange::SharedCtor() { - _cached_size_ = 0; - ::memset(&options_, 0, static_cast( - reinterpret_cast(&end_) - - reinterpret_cast(&options_)) + sizeof(end_)); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&options_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&end_) - + reinterpret_cast(&options_)) + sizeof(end_)); } DescriptorProto_ExtensionRange::~DescriptorProto_ExtensionRange() { // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ExtensionRange) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void DescriptorProto_ExtensionRange::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); if (this != internal_default_instance()) delete options_; } -void DescriptorProto_ExtensionRange::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void DescriptorProto_ExtensionRange::ArenaDtor(void* object) { + DescriptorProto_ExtensionRange* _this = reinterpret_cast< DescriptorProto_ExtensionRange* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const DescriptorProto_ExtensionRange& DescriptorProto_ExtensionRange::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void DescriptorProto_ExtensionRange::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::New(::google::protobuf::Arena* arena) const { - DescriptorProto_ExtensionRange* n = new DescriptorProto_ExtensionRange; - if (arena != NULL) { - arena->Own(n); - } - return n; +void DescriptorProto_ExtensionRange::SetCachedSize(int size) const { + _cached_size_.Set(size); } void DescriptorProto_ExtensionRange::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ExtensionRange) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - if (has_options()) { - GOOGLE_DCHECK(options_ != NULL); - options_->::google::protobuf::ExtensionRangeOptions::Clear(); - } cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 6u) { + if (cached_has_bits & 0x00000001u) { + GOOGLE_DCHECK(options_ != nullptr); + options_->Clear(); + } + if (cached_has_bits & 0x00000006u) { ::memset(&start_, 0, static_cast( reinterpret_cast(&end_) - reinterpret_cast(&start_)) + sizeof(end_)); } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto.ExtensionRange) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional int32 start = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { - set_has_start(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, &start_))); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* DescriptorProto_ExtensionRange::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional int32 start = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + _Internal::set_has_start(&has_bits); + start_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional int32 end = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) { - set_has_end(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, &end_))); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + _Internal::set_has_end(&has_bits); + end_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional .google.protobuf.ExtensionRangeOptions options = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, mutable_options())); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.DescriptorProto.ExtensionRange) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.DescriptorProto.ExtensionRange) - return false; -#undef DO_ -} - -void DescriptorProto_ExtensionRange::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.DescriptorProto.ExtensionRange) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional int32 start = 1; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output); - } - - // optional int32 end = 2; - if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output); - } - - // optional .google.protobuf.ExtensionRangeOptions options = 3; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 3, *this->options_, output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto.ExtensionRange) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* DescriptorProto_ExtensionRange::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* DescriptorProto_ExtensionRange::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ExtensionRange) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional int32 start = 1; if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_start(), target); } // optional int32 end = 2; if (cached_has_bits & 0x00000004u) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_end(), target); } // optional .google.protobuf.ExtensionRangeOptions options = 3; if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 3, *this->options_, deterministic, target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 3, _Internal::options(this), target, stream); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ExtensionRange) return target; @@ -2912,50 +2264,52 @@ size_t DescriptorProto_ExtensionRange::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ExtensionRange) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } - if (_has_bits_[0 / 32] & 7u) { + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000007u) { // optional .google.protobuf.ExtensionRangeOptions options = 3; - if (has_options()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - *this->options_); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *options_); } // optional int32 start = 1; - if (has_start()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - this->start()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_start()); } // optional int32 end = 2; - if (has_end()) { + if (cached_has_bits & 0x00000004u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - this->end()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_end()); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message& from) { +void DescriptorProto_ExtensionRange::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange) GOOGLE_DCHECK_NE(&from, this); const DescriptorProto_ExtensionRange* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto.ExtensionRange) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto.ExtensionRange) MergeFrom(*source); @@ -2965,14 +2319,14 @@ void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRange& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 7u) { + if (cached_has_bits & 0x00000007u) { if (cached_has_bits & 0x00000001u) { - mutable_options()->::google::protobuf::ExtensionRangeOptions::MergeFrom(from.options()); + _internal_mutable_options()->PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions::MergeFrom(from._internal_options()); } if (cached_has_bits & 0x00000002u) { start_ = from.start_; @@ -2984,7 +2338,7 @@ void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRa } } -void DescriptorProto_ExtensionRange::CopyFrom(const ::google::protobuf::Message& from) { +void DescriptorProto_ExtensionRange::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto.ExtensionRange) if (&from == this) return; Clear(); @@ -2999,151 +2353,52 @@ void DescriptorProto_ExtensionRange::CopyFrom(const DescriptorProto_ExtensionRan } bool DescriptorProto_ExtensionRange::IsInitialized() const { - if (has_options()) { - if (!this->options_->IsInitialized()) return false; + if (_internal_has_options()) { + if (!options_->IsInitialized()) return false; } return true; } -void DescriptorProto_ExtensionRange::Swap(DescriptorProto_ExtensionRange* other) { - if (other == this) return; - InternalSwap(other); -} void DescriptorProto_ExtensionRange::InternalSwap(DescriptorProto_ExtensionRange* other) { using std::swap; - swap(options_, other->options_); - swap(start_, other->start_); - swap(end_, other->end_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(DescriptorProto_ExtensionRange, end_) + + sizeof(DescriptorProto_ExtensionRange::end_) + - PROTOBUF_FIELD_OFFSET(DescriptorProto_ExtensionRange, options_)>( + reinterpret_cast(&options_), + reinterpret_cast(&other->options_)); } -::google::protobuf::Metadata DescriptorProto_ExtensionRange::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; +::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto_ExtensionRange::GetMetadata() const { + return GetMetadataStatic(); } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// DescriptorProto_ExtensionRange - -// optional int32 start = 1; -bool DescriptorProto_ExtensionRange::has_start() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void DescriptorProto_ExtensionRange::set_has_start() { - _has_bits_[0] |= 0x00000002u; -} -void DescriptorProto_ExtensionRange::clear_has_start() { - _has_bits_[0] &= ~0x00000002u; -} -void DescriptorProto_ExtensionRange::clear_start() { - start_ = 0; - clear_has_start(); -} -::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.start) - return start_; -} -void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) { - set_has_start(); - start_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.start) -} -// optional int32 end = 2; -bool DescriptorProto_ExtensionRange::has_end() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -void DescriptorProto_ExtensionRange::set_has_end() { - _has_bits_[0] |= 0x00000004u; -} -void DescriptorProto_ExtensionRange::clear_has_end() { - _has_bits_[0] &= ~0x00000004u; -} -void DescriptorProto_ExtensionRange::clear_end() { - end_ = 0; - clear_has_end(); -} -::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.end) - return end_; -} -void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) { - set_has_end(); - end_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end) -} +// =================================================================== -// optional .google.protobuf.ExtensionRangeOptions options = 3; -bool DescriptorProto_ExtensionRange::has_options() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void DescriptorProto_ExtensionRange::set_has_options() { - _has_bits_[0] |= 0x00000001u; -} -void DescriptorProto_ExtensionRange::clear_has_options() { - _has_bits_[0] &= ~0x00000001u; -} -void DescriptorProto_ExtensionRange::clear_options() { - if (options_ != NULL) options_->::google::protobuf::ExtensionRangeOptions::Clear(); - clear_has_options(); -} -const ::google::protobuf::ExtensionRangeOptions& DescriptorProto_ExtensionRange::options() const { - const ::google::protobuf::ExtensionRangeOptions* p = options_; - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_ExtensionRangeOptions_default_instance_); -} -::google::protobuf::ExtensionRangeOptions* DescriptorProto_ExtensionRange::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::ExtensionRangeOptions; +class DescriptorProto_ReservedRange::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_start(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } - // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.ExtensionRange.options) - return options_; -} -::google::protobuf::ExtensionRangeOptions* DescriptorProto_ExtensionRange::release_options() { - // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.ExtensionRange.options) - clear_has_options(); - ::google::protobuf::ExtensionRangeOptions* temp = options_; - options_ = NULL; - return temp; -} -void DescriptorProto_ExtensionRange::set_allocated_options(::google::protobuf::ExtensionRangeOptions* options) { - delete options_; - options_ = options; - if (options) { - set_has_options(); - } else { - clear_has_options(); + static void set_has_end(HasBits* has_bits) { + (*has_bits)[0] |= 2u; } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.ExtensionRange.options) -} - -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS - -// =================================================================== - -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int DescriptorProto_ReservedRange::kStartFieldNumber; -const int DescriptorProto_ReservedRange::kEndFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +}; -DescriptorProto_ReservedRange::DescriptorProto_ReservedRange() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - } +DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto.ReservedRange) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto.ReservedRange) } DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + : ::PROTOBUF_NAMESPACE_ID::Message(), + _has_bits_(from._has_bits_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); ::memcpy(&start_, &from.start_, static_cast(reinterpret_cast(&end_) - reinterpret_cast(&start_)) + sizeof(end_)); @@ -3151,162 +2406,117 @@ DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(const DescriptorPro } void DescriptorProto_ReservedRange::SharedCtor() { - _cached_size_ = 0; - ::memset(&start_, 0, static_cast( - reinterpret_cast(&end_) - - reinterpret_cast(&start_)) + sizeof(end_)); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&start_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&end_) - + reinterpret_cast(&start_)) + sizeof(end_)); } DescriptorProto_ReservedRange::~DescriptorProto_ReservedRange() { // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ReservedRange) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void DescriptorProto_ReservedRange::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); } -void DescriptorProto_ReservedRange::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void DescriptorProto_ReservedRange::ArenaDtor(void* object) { + DescriptorProto_ReservedRange* _this = reinterpret_cast< DescriptorProto_ReservedRange* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* DescriptorProto_ReservedRange::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const DescriptorProto_ReservedRange& DescriptorProto_ReservedRange::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void DescriptorProto_ReservedRange::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -DescriptorProto_ReservedRange* DescriptorProto_ReservedRange::New(::google::protobuf::Arena* arena) const { - DescriptorProto_ReservedRange* n = new DescriptorProto_ReservedRange; - if (arena != NULL) { - arena->Own(n); - } - return n; +void DescriptorProto_ReservedRange::SetCachedSize(int size) const { + _cached_size_.Set(size); } void DescriptorProto_ReservedRange::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ReservedRange) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { ::memset(&start_, 0, static_cast( reinterpret_cast(&end_) - reinterpret_cast(&start_)) + sizeof(end_)); } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool DescriptorProto_ReservedRange::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto.ReservedRange) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional int32 start = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { - set_has_start(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, &start_))); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* DescriptorProto_ReservedRange::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional int32 start = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + _Internal::set_has_start(&has_bits); + start_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional int32 end = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) { - set_has_end(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, &end_))); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + _Internal::set_has_end(&has_bits); + end_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.DescriptorProto.ReservedRange) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.DescriptorProto.ReservedRange) - return false; -#undef DO_ -} - -void DescriptorProto_ReservedRange::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.DescriptorProto.ReservedRange) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional int32 start = 1; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output); - } - - // optional int32 end = 2; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto.ReservedRange) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* DescriptorProto_ReservedRange::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* DescriptorProto_ReservedRange::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ReservedRange) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional int32 start = 1; if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_start(), target); } // optional int32 end = 2; if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_end(), target); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ReservedRange) return target; @@ -3316,43 +2526,45 @@ size_t DescriptorProto_ReservedRange::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ReservedRange) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } - if (_has_bits_[0 / 32] & 3u) { + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000003u) { // optional int32 start = 1; - if (has_start()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - this->start()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_start()); } // optional int32 end = 2; - if (has_end()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - this->end()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_end()); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void DescriptorProto_ReservedRange::MergeFrom(const ::google::protobuf::Message& from) { +void DescriptorProto_ReservedRange::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto.ReservedRange) GOOGLE_DCHECK_NE(&from, this); const DescriptorProto_ReservedRange* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto.ReservedRange) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto.ReservedRange) MergeFrom(*source); @@ -3362,12 +2574,12 @@ void DescriptorProto_ReservedRange::MergeFrom(const ::google::protobuf::Message& void DescriptorProto_ReservedRange::MergeFrom(const DescriptorProto_ReservedRange& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ReservedRange) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { start_ = from.start_; } @@ -3378,7 +2590,7 @@ void DescriptorProto_ReservedRange::MergeFrom(const DescriptorProto_ReservedRang } } -void DescriptorProto_ReservedRange::CopyFrom(const ::google::protobuf::Message& from) { +void DescriptorProto_ReservedRange::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto.ReservedRange) if (&from == this) return; Clear(); @@ -3396,105 +2608,58 @@ bool DescriptorProto_ReservedRange::IsInitialized() const { return true; } -void DescriptorProto_ReservedRange::Swap(DescriptorProto_ReservedRange* other) { - if (other == this) return; - InternalSwap(other); -} void DescriptorProto_ReservedRange::InternalSwap(DescriptorProto_ReservedRange* other) { using std::swap; - swap(start_, other->start_); - swap(end_, other->end_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(DescriptorProto_ReservedRange, end_) + + sizeof(DescriptorProto_ReservedRange::end_) + - PROTOBUF_FIELD_OFFSET(DescriptorProto_ReservedRange, start_)>( + reinterpret_cast(&start_), + reinterpret_cast(&other->start_)); } -::google::protobuf::Metadata DescriptorProto_ReservedRange::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; +::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto_ReservedRange::GetMetadata() const { + return GetMetadataStatic(); } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// DescriptorProto_ReservedRange - -// optional int32 start = 1; -bool DescriptorProto_ReservedRange::has_start() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void DescriptorProto_ReservedRange::set_has_start() { - _has_bits_[0] |= 0x00000001u; -} -void DescriptorProto_ReservedRange::clear_has_start() { - _has_bits_[0] &= ~0x00000001u; -} -void DescriptorProto_ReservedRange::clear_start() { - start_ = 0; - clear_has_start(); -} -::google::protobuf::int32 DescriptorProto_ReservedRange::start() const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.start) - return start_; -} -void DescriptorProto_ReservedRange::set_start(::google::protobuf::int32 value) { - set_has_start(); - start_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.start) -} - -// optional int32 end = 2; -bool DescriptorProto_ReservedRange::has_end() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void DescriptorProto_ReservedRange::set_has_end() { - _has_bits_[0] |= 0x00000002u; -} -void DescriptorProto_ReservedRange::clear_has_end() { - _has_bits_[0] &= ~0x00000002u; -} -void DescriptorProto_ReservedRange::clear_end() { - end_ = 0; - clear_has_end(); -} -::google::protobuf::int32 DescriptorProto_ReservedRange::end() const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.end) - return end_; -} -void DescriptorProto_ReservedRange::set_end(::google::protobuf::int32 value) { - set_has_end(); - end_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.end) -} - -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int DescriptorProto::kNameFieldNumber; -const int DescriptorProto::kFieldFieldNumber; -const int DescriptorProto::kExtensionFieldNumber; -const int DescriptorProto::kNestedTypeFieldNumber; -const int DescriptorProto::kEnumTypeFieldNumber; -const int DescriptorProto::kExtensionRangeFieldNumber; -const int DescriptorProto::kOneofDeclFieldNumber; -const int DescriptorProto::kOptionsFieldNumber; -const int DescriptorProto::kReservedRangeFieldNumber; -const int DescriptorProto::kReservedNameFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -DescriptorProto::DescriptorProto() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class DescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static const PROTOBUF_NAMESPACE_ID::MessageOptions& options(const DescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 2u; } +}; + +const PROTOBUF_NAMESPACE_ID::MessageOptions& +DescriptorProto::_Internal::options(const DescriptorProto* msg) { + return *msg->options_; +} +DescriptorProto::DescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + field_(arena), + nested_type_(arena), + enum_type_(arena), + extension_range_(arena), + extension_(arena), + oneof_decl_(arena), + reserved_range_(arena), + reserved_name_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto) } DescriptorProto::DescriptorProto(const DescriptorProto& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), _has_bits_(from._has_bits_), - _cached_size_(0), field_(from.field_), nested_type_(from.nested_type_), enum_type_(from.enum_type_), @@ -3503,61 +2668,50 @@ DescriptorProto::DescriptorProto(const DescriptorProto& from) oneof_decl_(from.oneof_decl_), reserved_range_(from.reserved_range_), reserved_name_(from.reserved_name_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_name()) { - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); - } - if (from.has_options()) { - options_ = new ::google::protobuf::MessageOptions(*from.options_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_name()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArena()); + } + if (from._internal_has_options()) { + options_ = new PROTOBUF_NAMESPACE_ID::MessageOptions(*from.options_); } else { - options_ = NULL; + options_ = nullptr; } // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto) } void DescriptorProto::SharedCtor() { - _cached_size_ = 0; - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - options_ = NULL; +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +options_ = nullptr; } DescriptorProto::~DescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void DescriptorProto::SharedDtor() { - name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (this != internal_default_instance()) delete options_; } -void DescriptorProto::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void DescriptorProto::ArenaDtor(void* object) { + DescriptorProto* _this = reinterpret_cast< DescriptorProto* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* DescriptorProto::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const DescriptorProto& DescriptorProto::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void DescriptorProto::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -DescriptorProto* DescriptorProto::New(::google::protobuf::Arena* arena) const { - DescriptorProto* n = new DescriptorProto; - if (arena != NULL) { - arena->Own(n); - } - return n; +void DescriptorProto::SetCachedSize(int size) const { + _cached_size_.Set(size); } void DescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; @@ -3570,363 +2724,262 @@ void DescriptorProto::Clear() { reserved_range_.Clear(); reserved_name_.Clear(); cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*name_.UnsafeRawStringPointer())->clear(); + name_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000002u) { - GOOGLE_DCHECK(options_ != NULL); - options_->::google::protobuf::MessageOptions::Clear(); + GOOGLE_DCHECK(options_ != nullptr); + options_->Clear(); } } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool DescriptorProto::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional string name = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.DescriptorProto.name"); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* DescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.DescriptorProto.name"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated .google.protobuf.FieldDescriptorProto field = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_field())); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_field(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr)); + } else goto handle_unusual; + continue; // repeated .google.protobuf.DescriptorProto nested_type = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_nested_type())); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_nested_type(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr)); + } else goto handle_unusual; + continue; // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; - case 4: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_enum_type())); - } else { - goto handle_unusual; - } - break; - } - + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_enum_type(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<34>(ptr)); + } else goto handle_unusual; + continue; // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; - case 5: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(42u /* 42 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_extension_range())); - } else { - goto handle_unusual; - } - break; - } - + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 42)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_extension_range(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<42>(ptr)); + } else goto handle_unusual; + continue; // repeated .google.protobuf.FieldDescriptorProto extension = 6; - case 6: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_extension())); - } else { - goto handle_unusual; - } - break; - } - + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 50)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_extension(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr)); + } else goto handle_unusual; + continue; // optional .google.protobuf.MessageOptions options = 7; - case 7: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(58u /* 58 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, mutable_options())); - } else { - goto handle_unusual; - } - break; - } - + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 58)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; - case 8: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(66u /* 66 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_oneof_decl())); - } else { - goto handle_unusual; - } - break; - } - + case 8: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 66)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_oneof_decl(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<66>(ptr)); + } else goto handle_unusual; + continue; // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; - case 9: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(74u /* 74 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_reserved_range())); - } else { - goto handle_unusual; - } - break; - } - + case 9: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 74)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_reserved_range(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<74>(ptr)); + } else goto handle_unusual; + continue; // repeated string reserved_name = 10; - case 10: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(82u /* 82 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->add_reserved_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->reserved_name(this->reserved_name_size() - 1).data(), - static_cast(this->reserved_name(this->reserved_name_size() - 1).length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.DescriptorProto.reserved_name"); - } else { - goto handle_unusual; - } - break; - } - + case 10: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 82)) { + ptr -= 1; + do { + ptr += 1; + auto str = _internal_add_reserved_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.DescriptorProto.reserved_name"); + #endif // !NDEBUG + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<82>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.DescriptorProto) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.DescriptorProto) - return false; -#undef DO_ -} - -void DescriptorProto::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.DescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.DescriptorProto.name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->name(), output); - } - - // repeated .google.protobuf.FieldDescriptorProto field = 2; - for (unsigned int i = 0, - n = static_cast(this->field_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 2, this->field(static_cast(i)), output); - } - - // repeated .google.protobuf.DescriptorProto nested_type = 3; - for (unsigned int i = 0, - n = static_cast(this->nested_type_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 3, this->nested_type(static_cast(i)), output); - } - - // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; - for (unsigned int i = 0, - n = static_cast(this->enum_type_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 4, this->enum_type(static_cast(i)), output); - } - - // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; - for (unsigned int i = 0, - n = static_cast(this->extension_range_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 5, this->extension_range(static_cast(i)), output); - } - - // repeated .google.protobuf.FieldDescriptorProto extension = 6; - for (unsigned int i = 0, - n = static_cast(this->extension_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 6, this->extension(static_cast(i)), output); - } - - // optional .google.protobuf.MessageOptions options = 7; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 7, *this->options_, output); - } - - // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; - for (unsigned int i = 0, - n = static_cast(this->oneof_decl_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 8, this->oneof_decl(static_cast(i)), output); - } - - // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; - for (unsigned int i = 0, - n = static_cast(this->reserved_range_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 9, this->reserved_range(static_cast(i)), output); - } - - // repeated string reserved_name = 10; - for (int i = 0, n = this->reserved_name_size(); i < n; i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->reserved_name(i).data(), static_cast(this->reserved_name(i).length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.DescriptorProto.reserved_name"); - ::google::protobuf::internal::WireFormatLite::WriteString( - 10, this->reserved_name(i), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* DescriptorProto::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* DescriptorProto::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional string name = 1; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.DescriptorProto.name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->name(), target); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); } // repeated .google.protobuf.FieldDescriptorProto field = 2; for (unsigned int i = 0, - n = static_cast(this->field_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 2, this->field(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_field_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(2, this->_internal_field(i), target, stream); } // repeated .google.protobuf.DescriptorProto nested_type = 3; for (unsigned int i = 0, - n = static_cast(this->nested_type_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 3, this->nested_type(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_nested_type_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(3, this->_internal_nested_type(i), target, stream); } // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; for (unsigned int i = 0, - n = static_cast(this->enum_type_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 4, this->enum_type(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_enum_type_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(4, this->_internal_enum_type(i), target, stream); } // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; for (unsigned int i = 0, - n = static_cast(this->extension_range_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 5, this->extension_range(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_extension_range_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(5, this->_internal_extension_range(i), target, stream); } // repeated .google.protobuf.FieldDescriptorProto extension = 6; for (unsigned int i = 0, - n = static_cast(this->extension_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 6, this->extension(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_extension_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(6, this->_internal_extension(i), target, stream); } // optional .google.protobuf.MessageOptions options = 7; if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 7, *this->options_, deterministic, target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 7, _Internal::options(this), target, stream); } // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; for (unsigned int i = 0, - n = static_cast(this->oneof_decl_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 8, this->oneof_decl(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_oneof_decl_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(8, this->_internal_oneof_decl(i), target, stream); } // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; for (unsigned int i = 0, - n = static_cast(this->reserved_range_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 9, this->reserved_range(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_reserved_range_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(9, this->_internal_reserved_range(i), target, stream); } // repeated string reserved_name = 10; - for (int i = 0, n = this->reserved_name_size(); i < n; i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->reserved_name(i).data(), static_cast(this->reserved_name(i).length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + for (int i = 0, n = this->_internal_reserved_name_size(); i < n; i++) { + const auto& s = this->_internal_reserved_name(i); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + s.data(), static_cast(s.length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.DescriptorProto.reserved_name"); - target = ::google::protobuf::internal::WireFormatLite:: - WriteStringToArray(10, this->reserved_name(i), target); + target = stream->WriteString(10, s, target); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto) return target; @@ -3936,128 +2989,102 @@ size_t DescriptorProto::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.FieldDescriptorProto field = 2; - { - unsigned int count = static_cast(this->field_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->field(static_cast(i))); - } + total_size += 1UL * this->_internal_field_size(); + for (const auto& msg : this->field_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // repeated .google.protobuf.DescriptorProto nested_type = 3; - { - unsigned int count = static_cast(this->nested_type_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->nested_type(static_cast(i))); - } + total_size += 1UL * this->_internal_nested_type_size(); + for (const auto& msg : this->nested_type_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; - { - unsigned int count = static_cast(this->enum_type_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->enum_type(static_cast(i))); - } + total_size += 1UL * this->_internal_enum_type_size(); + for (const auto& msg : this->enum_type_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; - { - unsigned int count = static_cast(this->extension_range_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->extension_range(static_cast(i))); - } + total_size += 1UL * this->_internal_extension_range_size(); + for (const auto& msg : this->extension_range_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // repeated .google.protobuf.FieldDescriptorProto extension = 6; - { - unsigned int count = static_cast(this->extension_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->extension(static_cast(i))); - } + total_size += 1UL * this->_internal_extension_size(); + for (const auto& msg : this->extension_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; - { - unsigned int count = static_cast(this->oneof_decl_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->oneof_decl(static_cast(i))); - } + total_size += 1UL * this->_internal_oneof_decl_size(); + for (const auto& msg : this->oneof_decl_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; - { - unsigned int count = static_cast(this->reserved_range_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->reserved_range(static_cast(i))); - } + total_size += 1UL * this->_internal_reserved_range_size(); + for (const auto& msg : this->reserved_range_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // repeated string reserved_name = 10; total_size += 1 * - ::google::protobuf::internal::FromIntSize(this->reserved_name_size()); - for (int i = 0, n = this->reserved_name_size(); i < n; i++) { - total_size += ::google::protobuf::internal::WireFormatLite::StringSize( - this->reserved_name(i)); + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(reserved_name_.size()); + for (int i = 0, n = reserved_name_.size(); i < n; i++) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + reserved_name_.Get(i)); } - if (_has_bits_[0 / 32] & 3u) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000003u) { // optional string name = 1; - if (has_name()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->name()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); } // optional .google.protobuf.MessageOptions options = 7; - if (has_options()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - *this->options_); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *options_); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void DescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +void DescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto) GOOGLE_DCHECK_NE(&from, this); const DescriptorProto* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.DescriptorProto) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.DescriptorProto) MergeFrom(*source); @@ -4067,8 +3094,8 @@ void DescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void DescriptorProto::MergeFrom(const DescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; field_.MergeFrom(from.field_); @@ -4080,18 +3107,17 @@ void DescriptorProto::MergeFrom(const DescriptorProto& from) { reserved_range_.MergeFrom(from.reserved_range_); reserved_name_.MergeFrom(from.reserved_name_); cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - set_has_name(); - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); + _internal_set_name(from._internal_name()); } if (cached_has_bits & 0x00000002u) { - mutable_options()->::google::protobuf::MessageOptions::MergeFrom(from.options()); + _internal_mutable_options()->PROTOBUF_NAMESPACE_ID::MessageOptions::MergeFrom(from._internal_options()); } } } -void DescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +void DescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.DescriptorProto) if (&from == this) return; Clear(); @@ -4106,24 +3132,22 @@ void DescriptorProto::CopyFrom(const DescriptorProto& from) { } bool DescriptorProto::IsInitialized() const { - if (!::google::protobuf::internal::AllAreInitialized(this->field())) return false; - if (!::google::protobuf::internal::AllAreInitialized(this->nested_type())) return false; - if (!::google::protobuf::internal::AllAreInitialized(this->enum_type())) return false; - if (!::google::protobuf::internal::AllAreInitialized(this->extension_range())) return false; - if (!::google::protobuf::internal::AllAreInitialized(this->extension())) return false; - if (!::google::protobuf::internal::AllAreInitialized(this->oneof_decl())) return false; - if (has_options()) { - if (!this->options_->IsInitialized()) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(field_)) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(nested_type_)) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(enum_type_)) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(extension_range_)) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(extension_)) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(oneof_decl_)) return false; + if (_internal_has_options()) { + if (!options_->IsInitialized()) return false; } return true; } -void DescriptorProto::Swap(DescriptorProto* other) { - if (other == this) return; - InternalSwap(other); -} void DescriptorProto::InternalSwap(DescriptorProto* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); field_.InternalSwap(&other->field_); nested_type_.InternalSwap(&other->nested_type_); enum_type_.InternalSwap(&other->enum_type_); @@ -4132,577 +3156,139 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) { oneof_decl_.InternalSwap(&other->oneof_decl_); reserved_range_.InternalSwap(&other->reserved_range_); reserved_name_.InternalSwap(&other->reserved_name_); - name_.Swap(&other->name_); + name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); swap(options_, other->options_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata DescriptorProto::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// DescriptorProto - -// optional string name = 1; -bool DescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void DescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; -} -void DescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; -} -void DescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); -} -const ::std::string& DescriptorProto::name() const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name) - return name_.GetNoArena(); -} -void DescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.name) -} -#if LANG_CXX11 -void DescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.DescriptorProto.name) -} -#endif -void DescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name) -} -void DescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name) -} -::std::string* DescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* DescriptorProto::release_name() { - // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void DescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); - } else { - clear_has_name(); - } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name) -} - -// repeated .google.protobuf.FieldDescriptorProto field = 2; -int DescriptorProto::field_size() const { - return field_.size(); -} -void DescriptorProto::clear_field() { - field_.Clear(); -} -const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.field) - return field_.Get(index); -} -::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.field) - return field_.Mutable(index); -} -::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() { - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field) - return field_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* -DescriptorProto::mutable_field() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field) - return &field_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& -DescriptorProto::field() const { - // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field) - return field_; -} - -// repeated .google.protobuf.FieldDescriptorProto extension = 6; -int DescriptorProto::extension_size() const { - return extension_.size(); -} -void DescriptorProto::clear_extension() { - extension_.Clear(); -} -const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension) - return extension_.Get(index); -} -::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension) - return extension_.Mutable(index); -} -::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() { - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension) - return extension_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* -DescriptorProto::mutable_extension() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension) - return &extension_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& -DescriptorProto::extension() const { - // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension) - return extension_; -} - -// repeated .google.protobuf.DescriptorProto nested_type = 3; -int DescriptorProto::nested_type_size() const { - return nested_type_.size(); -} -void DescriptorProto::clear_nested_type() { - nested_type_.Clear(); -} -const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.nested_type) - return nested_type_.Get(index); -} -::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.nested_type) - return nested_type_.Mutable(index); -} -::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() { - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type) - return nested_type_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* -DescriptorProto::mutable_nested_type() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type) - return &nested_type_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& -DescriptorProto::nested_type() const { - // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type) - return nested_type_; -} - -// repeated .google.protobuf.EnumDescriptorProto enum_type = 4; -int DescriptorProto::enum_type_size() const { - return enum_type_.size(); -} -void DescriptorProto::clear_enum_type() { - enum_type_.Clear(); -} -const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.enum_type) - return enum_type_.Get(index); -} -::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.enum_type) - return enum_type_.Mutable(index); -} -::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() { - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type) - return enum_type_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* -DescriptorProto::mutable_enum_type() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type) - return &enum_type_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& -DescriptorProto::enum_type() const { - // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type) - return enum_type_; -} - -// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; -int DescriptorProto::extension_range_size() const { - return extension_range_.size(); -} -void DescriptorProto::clear_extension_range() { - extension_range_.Clear(); -} -const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension_range) - return extension_range_.Get(index); -} -::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension_range) - return extension_range_.Mutable(index); -} -::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() { - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range) - return extension_range_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* -DescriptorProto::mutable_extension_range() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range) - return &extension_range_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& -DescriptorProto::extension_range() const { - // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range) - return extension_range_; -} - -// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; -int DescriptorProto::oneof_decl_size() const { - return oneof_decl_.size(); -} -void DescriptorProto::clear_oneof_decl() { - oneof_decl_.Clear(); -} -const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.oneof_decl) - return oneof_decl_.Get(index); -} -::google::protobuf::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.oneof_decl) - return oneof_decl_.Mutable(index); -} -::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl() { - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl) - return oneof_decl_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* -DescriptorProto::mutable_oneof_decl() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl) - return &oneof_decl_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& -DescriptorProto::oneof_decl() const { - // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl) - return oneof_decl_; -} - -// optional .google.protobuf.MessageOptions options = 7; -bool DescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void DescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000002u; -} -void DescriptorProto::clear_has_options() { - _has_bits_[0] &= ~0x00000002u; -} -void DescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear(); - clear_has_options(); -} -const ::google::protobuf::MessageOptions& DescriptorProto::options() const { - const ::google::protobuf::MessageOptions* p = options_; - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_MessageOptions_default_instance_); -} -::google::protobuf::MessageOptions* DescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::MessageOptions; - } - // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options) - return options_; -} -::google::protobuf::MessageOptions* DescriptorProto::release_options() { - // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.options) - clear_has_options(); - ::google::protobuf::MessageOptions* temp = options_; - options_ = NULL; - return temp; -} -void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) { - delete options_; - options_ = options; - if (options) { - set_has_options(); - } else { - clear_has_options(); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options) -} - -// repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; -int DescriptorProto::reserved_range_size() const { - return reserved_range_.size(); -} -void DescriptorProto::clear_reserved_range() { - reserved_range_.Clear(); -} -const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_range) - return reserved_range_.Get(index); -} -::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_range) - return reserved_range_.Mutable(index); -} -::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() { - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range) - return reserved_range_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >* -DescriptorProto::mutable_reserved_range() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range) - return &reserved_range_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >& -DescriptorProto::reserved_range() const { - // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range) - return reserved_range_; } -// repeated string reserved_name = 10; -int DescriptorProto::reserved_name_size() const { - return reserved_name_.size(); -} -void DescriptorProto::clear_reserved_name() { - reserved_name_.Clear(); -} -const ::std::string& DescriptorProto::reserved_name(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_name) - return reserved_name_.Get(index); -} -::std::string* DescriptorProto::mutable_reserved_name(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_name) - return reserved_name_.Mutable(index); -} -void DescriptorProto::set_reserved_name(int index, const ::std::string& value) { - // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name) - reserved_name_.Mutable(index)->assign(value); -} -#if LANG_CXX11 -void DescriptorProto::set_reserved_name(int index, ::std::string&& value) { - // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name) - reserved_name_.Mutable(index)->assign(std::move(value)); -} -#endif -void DescriptorProto::set_reserved_name(int index, const char* value) { - GOOGLE_DCHECK(value != NULL); - reserved_name_.Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.reserved_name) -} -void DescriptorProto::set_reserved_name(int index, const char* value, size_t size) { - reserved_name_.Mutable(index)->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name) -} -::std::string* DescriptorProto::add_reserved_name() { - // @@protoc_insertion_point(field_add_mutable:google.protobuf.DescriptorProto.reserved_name) - return reserved_name_.Add(); -} -void DescriptorProto::add_reserved_name(const ::std::string& value) { - reserved_name_.Add()->assign(value); - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name) -} -#if LANG_CXX11 -void DescriptorProto::add_reserved_name(::std::string&& value) { - reserved_name_.Add(std::move(value)); - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name) -} -#endif -void DescriptorProto::add_reserved_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - reserved_name_.Add()->assign(value); - // @@protoc_insertion_point(field_add_char:google.protobuf.DescriptorProto.reserved_name) -} -void DescriptorProto::add_reserved_name(const char* value, size_t size) { - reserved_name_.Add()->assign(reinterpret_cast(value), size); - // @@protoc_insertion_point(field_add_pointer:google.protobuf.DescriptorProto.reserved_name) -} -const ::google::protobuf::RepeatedPtrField< ::std::string>& -DescriptorProto::reserved_name() const { - // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_name) - return reserved_name_; -} -::google::protobuf::RepeatedPtrField< ::std::string>* -DescriptorProto::mutable_reserved_name() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_name) - return &reserved_name_; +::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int ExtensionRangeOptions::kUninterpretedOptionFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +class ExtensionRangeOptions::_Internal { + public: +}; -ExtensionRangeOptions::ExtensionRangeOptions() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - } +ExtensionRangeOptions::ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + _extensions_(arena), + uninterpreted_option_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.ExtensionRangeOptions) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.ExtensionRangeOptions) } ExtensionRangeOptions::ExtensionRangeOptions(const ExtensionRangeOptions& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0), + : ::PROTOBUF_NAMESPACE_ID::Message(), uninterpreted_option_(from.uninterpreted_option_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _extensions_.MergeFrom(from._extensions_); // @@protoc_insertion_point(copy_constructor:google.protobuf.ExtensionRangeOptions) } void ExtensionRangeOptions::SharedCtor() { - _cached_size_ = 0; } ExtensionRangeOptions::~ExtensionRangeOptions() { // @@protoc_insertion_point(destructor:google.protobuf.ExtensionRangeOptions) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void ExtensionRangeOptions::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); } -void ExtensionRangeOptions::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void ExtensionRangeOptions::ArenaDtor(void* object) { + ExtensionRangeOptions* _this = reinterpret_cast< ExtensionRangeOptions* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* ExtensionRangeOptions::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void ExtensionRangeOptions::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -const ExtensionRangeOptions& ExtensionRangeOptions::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -ExtensionRangeOptions* ExtensionRangeOptions::New(::google::protobuf::Arena* arena) const { - ExtensionRangeOptions* n = new ExtensionRangeOptions; - if (arena != NULL) { - arena->Own(n); - } - return n; +void ExtensionRangeOptions::SetCachedSize(int size) const { + _cached_size_.Set(size); } void ExtensionRangeOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.ExtensionRangeOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; _extensions_.Clear(); uninterpreted_option_.Clear(); - _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool ExtensionRangeOptions::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.ExtensionRangeOptions) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(16383u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - case 999: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_uninterpreted_option())); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* ExtensionRangeOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - if ((8000u <= tag)) { - DO_(_extensions_.ParseField(tag, input, - internal_default_instance(), - _internal_metadata_.mutable_unknown_fields())); - continue; - } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + if ((8000u <= tag)) { + ptr = _extensions_.ParseField(tag, ptr, + internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.ExtensionRangeOptions) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.ExtensionRangeOptions) - return false; -#undef DO_ -} - -void ExtensionRangeOptions::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.ExtensionRangeOptions) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 999, this->uninterpreted_option(static_cast(i)), output); - } - - // Extension range [1000, 536870912) - _extensions_.SerializeWithCachedSizes( - 1000, 536870912, output); - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.ExtensionRangeOptions) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* ExtensionRangeOptions::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* ExtensionRangeOptions::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ExtensionRangeOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 999, this->uninterpreted_option(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_uninterpreted_option_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, this->_internal_uninterpreted_option(i), target, stream); } // Extension range [1000, 536870912) - target = _extensions_.InternalSerializeWithCachedSizesToArray( - 1000, 536870912, deterministic, target); + target = _extensions_._InternalSerialize( + 1000, 536870912, target, stream); - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ExtensionRangeOptions) return target; @@ -4714,38 +3300,35 @@ size_t ExtensionRangeOptions::ByteSizeLong() const { total_size += _extensions_.ByteSize(); - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - unsigned int count = static_cast(this->uninterpreted_option_size()); - total_size += 2UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->uninterpreted_option(static_cast(i))); - } + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void ExtensionRangeOptions::MergeFrom(const ::google::protobuf::Message& from) { +void ExtensionRangeOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ExtensionRangeOptions) GOOGLE_DCHECK_NE(&from, this); const ExtensionRangeOptions* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ExtensionRangeOptions) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ExtensionRangeOptions) MergeFrom(*source); @@ -4756,14 +3339,14 @@ void ExtensionRangeOptions::MergeFrom(const ExtensionRangeOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ExtensionRangeOptions) GOOGLE_DCHECK_NE(&from, this); _extensions_.MergeFrom(from._extensions_); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; uninterpreted_option_.MergeFrom(from.uninterpreted_option_); } -void ExtensionRangeOptions::CopyFrom(const ::google::protobuf::Message& from) { +void ExtensionRangeOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ExtensionRangeOptions) if (&from == this) return; Clear(); @@ -4782,116 +3365,106 @@ bool ExtensionRangeOptions::IsInitialized() const { return false; } - if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(uninterpreted_option_)) return false; return true; } -void ExtensionRangeOptions::Swap(ExtensionRangeOptions* other) { - if (other == this) return; - InternalSwap(other); -} void ExtensionRangeOptions::InternalSwap(ExtensionRangeOptions* other) { using std::swap; - uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); _extensions_.Swap(&other->_extensions_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); } -::google::protobuf::Metadata ExtensionRangeOptions::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; +::PROTOBUF_NAMESPACE_ID::Metadata ExtensionRangeOptions::GetMetadata() const { + return GetMetadataStatic(); } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// ExtensionRangeOptions - -// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -int ExtensionRangeOptions::uninterpreted_option_size() const { - return uninterpreted_option_.size(); -} -void ExtensionRangeOptions::clear_uninterpreted_option() { - uninterpreted_option_.Clear(); -} -const ::google::protobuf::UninterpretedOption& ExtensionRangeOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.ExtensionRangeOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -::google::protobuf::UninterpretedOption* ExtensionRangeOptions::mutable_uninterpreted_option(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.ExtensionRangeOptions.uninterpreted_option) - return uninterpreted_option_.Mutable(index); -} -::google::protobuf::UninterpretedOption* ExtensionRangeOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.ExtensionRangeOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* -ExtensionRangeOptions::mutable_uninterpreted_option() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.ExtensionRangeOptions.uninterpreted_option) - return &uninterpreted_option_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -ExtensionRangeOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.ExtensionRangeOptions.uninterpreted_option) - return uninterpreted_option_; -} - -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int FieldDescriptorProto::kNameFieldNumber; -const int FieldDescriptorProto::kNumberFieldNumber; -const int FieldDescriptorProto::kLabelFieldNumber; -const int FieldDescriptorProto::kTypeFieldNumber; -const int FieldDescriptorProto::kTypeNameFieldNumber; -const int FieldDescriptorProto::kExtendeeFieldNumber; -const int FieldDescriptorProto::kDefaultValueFieldNumber; -const int FieldDescriptorProto::kOneofIndexFieldNumber; -const int FieldDescriptorProto::kJsonNameFieldNumber; -const int FieldDescriptorProto::kOptionsFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -FieldDescriptorProto::FieldDescriptorProto() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class FieldDescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_number(HasBits* has_bits) { + (*has_bits)[0] |= 64u; + } + static void set_has_label(HasBits* has_bits) { + (*has_bits)[0] |= 512u; + } + static void set_has_type(HasBits* has_bits) { + (*has_bits)[0] |= 1024u; + } + static void set_has_type_name(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static void set_has_extendee(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_default_value(HasBits* has_bits) { + (*has_bits)[0] |= 8u; } + static void set_has_oneof_index(HasBits* has_bits) { + (*has_bits)[0] |= 128u; + } + static void set_has_json_name(HasBits* has_bits) { + (*has_bits)[0] |= 16u; + } + static const PROTOBUF_NAMESPACE_ID::FieldOptions& options(const FieldDescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 32u; + } + static void set_has_proto3_optional(HasBits* has_bits) { + (*has_bits)[0] |= 256u; + } +}; + +const PROTOBUF_NAMESPACE_ID::FieldOptions& +FieldDescriptorProto::_Internal::options(const FieldDescriptorProto* msg) { + return *msg->options_; +} +FieldDescriptorProto::FieldDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.FieldDescriptorProto) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldDescriptorProto) } FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_name()) { - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); - } - extendee_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_extendee()) { - extendee_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.extendee_); - } - type_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_type_name()) { - type_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_name_); - } - default_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_default_value()) { - default_value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.default_value_); - } - json_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_json_name()) { - json_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.json_name_); - } - if (from.has_options()) { - options_ = new ::google::protobuf::FieldOptions(*from.options_); + : ::PROTOBUF_NAMESPACE_ID::Message(), + _has_bits_(from._has_bits_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_name()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArena()); + } + extendee_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_extendee()) { + extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_extendee(), + GetArena()); + } + type_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_type_name()) { + type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_type_name(), + GetArena()); + } + default_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_default_value()) { + default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_default_value(), + GetArena()); + } + json_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_json_name()) { + json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_json_name(), + GetArena()); + } + if (from._internal_has_options()) { + options_ = new PROTOBUF_NAMESPACE_ID::FieldOptions(*from.options_); } else { - options_ = NULL; + options_ = nullptr; } ::memcpy(&number_, &from.number_, static_cast(reinterpret_cast(&type_) - @@ -4900,479 +3473,328 @@ FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from) } void FieldDescriptorProto::SharedCtor() { - _cached_size_ = 0; - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - extendee_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - type_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - default_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - json_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - ::memset(&options_, 0, static_cast( - reinterpret_cast(&oneof_index_) - - reinterpret_cast(&options_)) + sizeof(oneof_index_)); - label_ = 1; - type_ = 1; +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +extendee_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +type_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +default_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +json_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&options_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&proto3_optional_) - + reinterpret_cast(&options_)) + sizeof(proto3_optional_)); +label_ = 1; +type_ = 1; } FieldDescriptorProto::~FieldDescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.FieldDescriptorProto) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void FieldDescriptorProto::SharedDtor() { - name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - extendee_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - type_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - default_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - json_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + extendee_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + type_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + default_value_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + json_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (this != internal_default_instance()) delete options_; } -void FieldDescriptorProto::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* FieldDescriptorProto::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void FieldDescriptorProto::ArenaDtor(void* object) { + FieldDescriptorProto* _this = reinterpret_cast< FieldDescriptorProto* >(object); + (void)_this; } - -const FieldDescriptorProto& FieldDescriptorProto::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void FieldDescriptorProto::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -FieldDescriptorProto* FieldDescriptorProto::New(::google::protobuf::Arena* arena) const { - FieldDescriptorProto* n = new FieldDescriptorProto; - if (arena != NULL) { - arena->Own(n); - } - return n; +void FieldDescriptorProto::SetCachedSize(int size) const { + _cached_size_.Set(size); } void FieldDescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 63u) { + if (cached_has_bits & 0x0000003fu) { if (cached_has_bits & 0x00000001u) { - GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*name_.UnsafeRawStringPointer())->clear(); + name_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000002u) { - GOOGLE_DCHECK(!extendee_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*extendee_.UnsafeRawStringPointer())->clear(); + extendee_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000004u) { - GOOGLE_DCHECK(!type_name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*type_name_.UnsafeRawStringPointer())->clear(); + type_name_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000008u) { - GOOGLE_DCHECK(!default_value_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*default_value_.UnsafeRawStringPointer())->clear(); + default_value_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000010u) { - GOOGLE_DCHECK(!json_name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*json_name_.UnsafeRawStringPointer())->clear(); + json_name_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000020u) { - GOOGLE_DCHECK(options_ != NULL); - options_->::google::protobuf::FieldOptions::Clear(); + GOOGLE_DCHECK(options_ != nullptr); + options_->Clear(); } } - if (cached_has_bits & 192u) { + if (cached_has_bits & 0x000000c0u) { ::memset(&number_, 0, static_cast( reinterpret_cast(&oneof_index_) - reinterpret_cast(&number_)) + sizeof(oneof_index_)); } - if (cached_has_bits & 768u) { + if (cached_has_bits & 0x00000700u) { + proto3_optional_ = false; label_ = 1; type_ = 1; } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool FieldDescriptorProto::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.FieldDescriptorProto) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional string name = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FieldDescriptorProto.name"); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* FieldDescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.name"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string extendee = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_extendee())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->extendee().data(), static_cast(this->extendee().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FieldDescriptorProto.extendee"); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + auto str = _internal_mutable_extendee(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.extendee"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional int32 number = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) { - set_has_number(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, &number_))); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + _Internal::set_has_number(&has_bits); + number_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional .google.protobuf.FieldDescriptorProto.Label label = 4; - case 4: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(32u /* 32 & 0xFF */)) { - int value; - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( - input, &value))); - if (::google::protobuf::FieldDescriptorProto_Label_IsValid(value)) { - set_label(static_cast< ::google::protobuf::FieldDescriptorProto_Label >(value)); + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 32)) { + ::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + if (PROTOBUF_PREDICT_TRUE(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label_IsValid(val))) { + _internal_set_label(static_cast(val)); } else { - mutable_unknown_fields()->AddVarint( - 4, static_cast< ::google::protobuf::uint64>(value)); + ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(4, val, mutable_unknown_fields()); } - } else { - goto handle_unusual; - } - break; - } - + } else goto handle_unusual; + continue; // optional .google.protobuf.FieldDescriptorProto.Type type = 5; - case 5: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(40u /* 40 & 0xFF */)) { - int value; - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( - input, &value))); - if (::google::protobuf::FieldDescriptorProto_Type_IsValid(value)) { - set_type(static_cast< ::google::protobuf::FieldDescriptorProto_Type >(value)); + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 40)) { + ::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + if (PROTOBUF_PREDICT_TRUE(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type_IsValid(val))) { + _internal_set_type(static_cast(val)); } else { - mutable_unknown_fields()->AddVarint( - 5, static_cast< ::google::protobuf::uint64>(value)); + ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(5, val, mutable_unknown_fields()); } - } else { - goto handle_unusual; - } - break; - } - + } else goto handle_unusual; + continue; // optional string type_name = 6; - case 6: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_type_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->type_name().data(), static_cast(this->type_name().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FieldDescriptorProto.type_name"); - } else { - goto handle_unusual; - } - break; - } - + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 50)) { + auto str = _internal_mutable_type_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.type_name"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string default_value = 7; - case 7: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(58u /* 58 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_default_value())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->default_value().data(), static_cast(this->default_value().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FieldDescriptorProto.default_value"); - } else { - goto handle_unusual; - } - break; - } - + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 58)) { + auto str = _internal_mutable_default_value(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.default_value"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional .google.protobuf.FieldOptions options = 8; - case 8: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(66u /* 66 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, mutable_options())); - } else { - goto handle_unusual; - } - break; - } - + case 8: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 66)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional int32 oneof_index = 9; - case 9: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(72u /* 72 & 0xFF */)) { - set_has_oneof_index(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, &oneof_index_))); - } else { - goto handle_unusual; - } - break; - } - + case 9: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 72)) { + _Internal::set_has_oneof_index(&has_bits); + oneof_index_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string json_name = 10; - case 10: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(82u /* 82 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_json_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->json_name().data(), static_cast(this->json_name().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FieldDescriptorProto.json_name"); - } else { - goto handle_unusual; - } - break; - } - + case 10: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 82)) { + auto str = _internal_mutable_json_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.json_name"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; + // optional bool proto3_optional = 17; + case 17: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 136)) { + _Internal::set_has_proto3_optional(&has_bits); + proto3_optional_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.FieldDescriptorProto) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.FieldDescriptorProto) - return false; -#undef DO_ + ptr = nullptr; + goto success; +#undef CHK_ } -void FieldDescriptorProto::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.FieldDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; +::PROTOBUF_NAMESPACE_ID::uint8* FieldDescriptorProto::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldDescriptorProto) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional string name = 1; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FieldDescriptorProto.name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->name(), output); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); } // optional string extendee = 2; if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->extendee().data(), static_cast(this->extendee().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_extendee().data(), static_cast(this->_internal_extendee().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FieldDescriptorProto.extendee"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 2, this->extendee(), output); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_extendee(), target); } // optional int32 number = 3; if (cached_has_bits & 0x00000040u) { - ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->number(), output); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_number(), target); } // optional .google.protobuf.FieldDescriptorProto.Label label = 4; - if (cached_has_bits & 0x00000100u) { - ::google::protobuf::internal::WireFormatLite::WriteEnum( - 4, this->label(), output); + if (cached_has_bits & 0x00000200u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray( + 4, this->_internal_label(), target); } // optional .google.protobuf.FieldDescriptorProto.Type type = 5; - if (cached_has_bits & 0x00000200u) { - ::google::protobuf::internal::WireFormatLite::WriteEnum( - 5, this->type(), output); + if (cached_has_bits & 0x00000400u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray( + 5, this->_internal_type(), target); } // optional string type_name = 6; if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->type_name().data(), static_cast(this->type_name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_type_name().data(), static_cast(this->_internal_type_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FieldDescriptorProto.type_name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 6, this->type_name(), output); + target = stream->WriteStringMaybeAliased( + 6, this->_internal_type_name(), target); } // optional string default_value = 7; if (cached_has_bits & 0x00000008u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->default_value().data(), static_cast(this->default_value().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_default_value().data(), static_cast(this->_internal_default_value().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FieldDescriptorProto.default_value"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 7, this->default_value(), output); + target = stream->WriteStringMaybeAliased( + 7, this->_internal_default_value(), target); } // optional .google.protobuf.FieldOptions options = 8; if (cached_has_bits & 0x00000020u) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 8, *this->options_, output); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 8, _Internal::options(this), target, stream); } // optional int32 oneof_index = 9; if (cached_has_bits & 0x00000080u) { - ::google::protobuf::internal::WireFormatLite::WriteInt32(9, this->oneof_index(), output); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(9, this->_internal_oneof_index(), target); } // optional string json_name = 10; if (cached_has_bits & 0x00000010u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->json_name().data(), static_cast(this->json_name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_json_name().data(), static_cast(this->_internal_json_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FieldDescriptorProto.json_name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 10, this->json_name(), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.FieldDescriptorProto) -} - -::google::protobuf::uint8* FieldDescriptorProto::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FieldDescriptorProto.name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->name(), target); - } - - // optional string extendee = 2; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->extendee().data(), static_cast(this->extendee().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FieldDescriptorProto.extendee"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 2, this->extendee(), target); - } - - // optional int32 number = 3; - if (cached_has_bits & 0x00000040u) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->number(), target); + target = stream->WriteStringMaybeAliased( + 10, this->_internal_json_name(), target); } - // optional .google.protobuf.FieldDescriptorProto.Label label = 4; + // optional bool proto3_optional = 17; if (cached_has_bits & 0x00000100u) { - target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( - 4, this->label(), target); - } - - // optional .google.protobuf.FieldDescriptorProto.Type type = 5; - if (cached_has_bits & 0x00000200u) { - target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( - 5, this->type(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(17, this->_internal_proto3_optional(), target); } - // optional string type_name = 6; - if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->type_name().data(), static_cast(this->type_name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FieldDescriptorProto.type_name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 6, this->type_name(), target); - } - - // optional string default_value = 7; - if (cached_has_bits & 0x00000008u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->default_value().data(), static_cast(this->default_value().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FieldDescriptorProto.default_value"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 7, this->default_value(), target); - } - - // optional .google.protobuf.FieldOptions options = 8; - if (cached_has_bits & 0x00000020u) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 8, *this->options_, deterministic, target); - } - - // optional int32 oneof_index = 9; - if (cached_has_bits & 0x00000080u) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(9, this->oneof_index(), target); - } - - // optional string json_name = 10; - if (cached_has_bits & 0x00000010u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->json_name().data(), static_cast(this->json_name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FieldDescriptorProto.json_name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 10, this->json_name(), target); - } - - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldDescriptorProto) return target; @@ -5382,99 +3804,106 @@ size_t FieldDescriptorProto::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldDescriptorProto) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } - if (_has_bits_[0 / 32] & 255u) { + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x000000ffu) { // optional string name = 1; - if (has_name()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->name()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); } // optional string extendee = 2; - if (has_extendee()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->extendee()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_extendee()); } // optional string type_name = 6; - if (has_type_name()) { + if (cached_has_bits & 0x00000004u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->type_name()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_type_name()); } // optional string default_value = 7; - if (has_default_value()) { + if (cached_has_bits & 0x00000008u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->default_value()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_default_value()); } // optional string json_name = 10; - if (has_json_name()) { + if (cached_has_bits & 0x00000010u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->json_name()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_json_name()); } // optional .google.protobuf.FieldOptions options = 8; - if (has_options()) { + if (cached_has_bits & 0x00000020u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - *this->options_); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *options_); } // optional int32 number = 3; - if (has_number()) { + if (cached_has_bits & 0x00000040u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - this->number()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_number()); } // optional int32 oneof_index = 9; - if (has_oneof_index()) { + if (cached_has_bits & 0x00000080u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - this->oneof_index()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_oneof_index()); } } - if (_has_bits_[8 / 32] & 768u) { + if (cached_has_bits & 0x00000700u) { + // optional bool proto3_optional = 17; + if (cached_has_bits & 0x00000100u) { + total_size += 2 + 1; + } + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; - if (has_label()) { + if (cached_has_bits & 0x00000200u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::EnumSize(this->label()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_label()); } // optional .google.protobuf.FieldDescriptorProto.Type type = 5; - if (has_type()) { + if (cached_has_bits & 0x00000400u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::EnumSize(this->type()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_type()); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +void FieldDescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldDescriptorProto) GOOGLE_DCHECK_NE(&from, this); const FieldDescriptorProto* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldDescriptorProto) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldDescriptorProto) MergeFrom(*source); @@ -5484,34 +3913,29 @@ void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldDescriptorProto) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 255u) { + if (cached_has_bits & 0x000000ffu) { if (cached_has_bits & 0x00000001u) { - set_has_name(); - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); + _internal_set_name(from._internal_name()); } if (cached_has_bits & 0x00000002u) { - set_has_extendee(); - extendee_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.extendee_); + _internal_set_extendee(from._internal_extendee()); } if (cached_has_bits & 0x00000004u) { - set_has_type_name(); - type_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_name_); + _internal_set_type_name(from._internal_type_name()); } if (cached_has_bits & 0x00000008u) { - set_has_default_value(); - default_value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.default_value_); + _internal_set_default_value(from._internal_default_value()); } if (cached_has_bits & 0x00000010u) { - set_has_json_name(); - json_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.json_name_); + _internal_set_json_name(from._internal_json_name()); } if (cached_has_bits & 0x00000020u) { - mutable_options()->::google::protobuf::FieldOptions::MergeFrom(from.options()); + _internal_mutable_options()->PROTOBUF_NAMESPACE_ID::FieldOptions::MergeFrom(from._internal_options()); } if (cached_has_bits & 0x00000040u) { number_ = from.number_; @@ -5521,18 +3945,21 @@ void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) { } _has_bits_[0] |= cached_has_bits; } - if (cached_has_bits & 768u) { + if (cached_has_bits & 0x00000700u) { if (cached_has_bits & 0x00000100u) { - label_ = from.label_; + proto3_optional_ = from.proto3_optional_; } if (cached_has_bits & 0x00000200u) { + label_ = from.label_; + } + if (cached_has_bits & 0x00000400u) { type_ = from.type_; } _has_bits_[0] |= cached_has_bits; } } -void FieldDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +void FieldDescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldDescriptorProto) if (&from == this) return; Clear(); @@ -5547,712 +3974,201 @@ void FieldDescriptorProto::CopyFrom(const FieldDescriptorProto& from) { } bool FieldDescriptorProto::IsInitialized() const { - if (has_options()) { - if (!this->options_->IsInitialized()) return false; + if (_internal_has_options()) { + if (!options_->IsInitialized()) return false; } return true; } -void FieldDescriptorProto::Swap(FieldDescriptorProto* other) { - if (other == this) return; - InternalSwap(other); -} void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) { using std::swap; - name_.Swap(&other->name_); - extendee_.Swap(&other->extendee_); - type_name_.Swap(&other->type_name_); - default_value_.Swap(&other->default_value_); - json_name_.Swap(&other->json_name_); - swap(options_, other->options_); - swap(number_, other->number_); - swap(oneof_index_, other->oneof_index_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); + name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + extendee_.Swap(&other->extendee_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + type_name_.Swap(&other->type_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + default_value_.Swap(&other->default_value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + json_name_.Swap(&other->json_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, proto3_optional_) + + sizeof(FieldDescriptorProto::proto3_optional_) + - PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, options_)>( + reinterpret_cast(&options_), + reinterpret_cast(&other->options_)); swap(label_, other->label_); swap(type_, other->type_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata FieldDescriptorProto::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// FieldDescriptorProto - -// optional string name = 1; -bool FieldDescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void FieldDescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; -} -void FieldDescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; -} -void FieldDescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); -} -const ::std::string& FieldDescriptorProto::name() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name) - return name_.GetNoArena(); -} -void FieldDescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.name) -} -#if LANG_CXX11 -void FieldDescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.name) -} -#endif -void FieldDescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name) -} -void FieldDescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name) -} -::std::string* FieldDescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FieldDescriptorProto::release_name() { - // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FieldDescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); - } else { - clear_has_name(); - } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name) } -// optional int32 number = 3; -bool FieldDescriptorProto::has_number() const { - return (_has_bits_[0] & 0x00000040u) != 0; -} -void FieldDescriptorProto::set_has_number() { - _has_bits_[0] |= 0x00000040u; -} -void FieldDescriptorProto::clear_has_number() { - _has_bits_[0] &= ~0x00000040u; -} -void FieldDescriptorProto::clear_number() { - number_ = 0; - clear_has_number(); -} -::google::protobuf::int32 FieldDescriptorProto::number() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.number) - return number_; -} -void FieldDescriptorProto::set_number(::google::protobuf::int32 value) { - set_has_number(); - number_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.number) +::PROTOBUF_NAMESPACE_ID::Metadata FieldDescriptorProto::GetMetadata() const { + return GetMetadataStatic(); } -// optional .google.protobuf.FieldDescriptorProto.Label label = 4; -bool FieldDescriptorProto::has_label() const { - return (_has_bits_[0] & 0x00000100u) != 0; -} -void FieldDescriptorProto::set_has_label() { - _has_bits_[0] |= 0x00000100u; -} -void FieldDescriptorProto::clear_has_label() { - _has_bits_[0] &= ~0x00000100u; -} -void FieldDescriptorProto::clear_label() { - label_ = 1; - clear_has_label(); -} -::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.label) - return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_); -} -void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) { - assert(::google::protobuf::FieldDescriptorProto_Label_IsValid(value)); - set_has_label(); - label_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.label) -} -// optional .google.protobuf.FieldDescriptorProto.Type type = 5; -bool FieldDescriptorProto::has_type() const { - return (_has_bits_[0] & 0x00000200u) != 0; -} -void FieldDescriptorProto::set_has_type() { - _has_bits_[0] |= 0x00000200u; -} -void FieldDescriptorProto::clear_has_type() { - _has_bits_[0] &= ~0x00000200u; -} -void FieldDescriptorProto::clear_type() { - type_ = 1; - clear_has_type(); -} -::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type) - return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_); -} -void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) { - assert(::google::protobuf::FieldDescriptorProto_Type_IsValid(value)); - set_has_type(); - type_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type) -} +// =================================================================== -// optional string type_name = 6; -bool FieldDescriptorProto::has_type_name() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -void FieldDescriptorProto::set_has_type_name() { - _has_bits_[0] |= 0x00000004u; -} -void FieldDescriptorProto::clear_has_type_name() { - _has_bits_[0] &= ~0x00000004u; -} -void FieldDescriptorProto::clear_type_name() { - type_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_type_name(); -} -const ::std::string& FieldDescriptorProto::type_name() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type_name) - return type_name_.GetNoArena(); -} -void FieldDescriptorProto::set_type_name(const ::std::string& value) { - set_has_type_name(); - type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type_name) -} -#if LANG_CXX11 -void FieldDescriptorProto::set_type_name(::std::string&& value) { - set_has_type_name(); - type_name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.type_name) -} -#endif -void FieldDescriptorProto::set_type_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_type_name(); - type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name) -} -void FieldDescriptorProto::set_type_name(const char* value, size_t size) { - set_has_type_name(); - type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name) -} -::std::string* FieldDescriptorProto::mutable_type_name() { - set_has_type_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name) - return type_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FieldDescriptorProto::release_type_name() { - // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.type_name) - clear_has_type_name(); - return type_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) { - if (type_name != NULL) { - set_has_type_name(); - } else { - clear_has_type_name(); - } - type_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name) -} - -// optional string extendee = 2; -bool FieldDescriptorProto::has_extendee() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void FieldDescriptorProto::set_has_extendee() { - _has_bits_[0] |= 0x00000002u; -} -void FieldDescriptorProto::clear_has_extendee() { - _has_bits_[0] &= ~0x00000002u; -} -void FieldDescriptorProto::clear_extendee() { - extendee_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_extendee(); -} -const ::std::string& FieldDescriptorProto::extendee() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee) - return extendee_.GetNoArena(); -} -void FieldDescriptorProto::set_extendee(const ::std::string& value) { - set_has_extendee(); - extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.extendee) -} -#if LANG_CXX11 -void FieldDescriptorProto::set_extendee(::std::string&& value) { - set_has_extendee(); - extendee_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.extendee) -} -#endif -void FieldDescriptorProto::set_extendee(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_extendee(); - extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee) -} -void FieldDescriptorProto::set_extendee(const char* value, size_t size) { - set_has_extendee(); - extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee) -} -::std::string* FieldDescriptorProto::mutable_extendee() { - set_has_extendee(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee) - return extendee_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FieldDescriptorProto::release_extendee() { - // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.extendee) - clear_has_extendee(); - return extendee_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) { - if (extendee != NULL) { - set_has_extendee(); - } else { - clear_has_extendee(); - } - extendee_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), extendee); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee) -} - -// optional string default_value = 7; -bool FieldDescriptorProto::has_default_value() const { - return (_has_bits_[0] & 0x00000008u) != 0; -} -void FieldDescriptorProto::set_has_default_value() { - _has_bits_[0] |= 0x00000008u; -} -void FieldDescriptorProto::clear_has_default_value() { - _has_bits_[0] &= ~0x00000008u; -} -void FieldDescriptorProto::clear_default_value() { - default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_default_value(); -} -const ::std::string& FieldDescriptorProto::default_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.default_value) - return default_value_.GetNoArena(); -} -void FieldDescriptorProto::set_default_value(const ::std::string& value) { - set_has_default_value(); - default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.default_value) -} -#if LANG_CXX11 -void FieldDescriptorProto::set_default_value(::std::string&& value) { - set_has_default_value(); - default_value_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.default_value) -} -#endif -void FieldDescriptorProto::set_default_value(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_default_value(); - default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value) -} -void FieldDescriptorProto::set_default_value(const char* value, size_t size) { - set_has_default_value(); - default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value) -} -::std::string* FieldDescriptorProto::mutable_default_value() { - set_has_default_value(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value) - return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FieldDescriptorProto::release_default_value() { - // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.default_value) - clear_has_default_value(); - return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) { - if (default_value != NULL) { - set_has_default_value(); - } else { - clear_has_default_value(); +class OneofDescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } - default_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), default_value); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value) -} - -// optional int32 oneof_index = 9; -bool FieldDescriptorProto::has_oneof_index() const { - return (_has_bits_[0] & 0x00000080u) != 0; -} -void FieldDescriptorProto::set_has_oneof_index() { - _has_bits_[0] |= 0x00000080u; -} -void FieldDescriptorProto::clear_has_oneof_index() { - _has_bits_[0] &= ~0x00000080u; -} -void FieldDescriptorProto::clear_oneof_index() { - oneof_index_ = 0; - clear_has_oneof_index(); -} -::google::protobuf::int32 FieldDescriptorProto::oneof_index() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.oneof_index) - return oneof_index_; -} -void FieldDescriptorProto::set_oneof_index(::google::protobuf::int32 value) { - set_has_oneof_index(); - oneof_index_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index) -} - -// optional string json_name = 10; -bool FieldDescriptorProto::has_json_name() const { - return (_has_bits_[0] & 0x00000010u) != 0; -} -void FieldDescriptorProto::set_has_json_name() { - _has_bits_[0] |= 0x00000010u; -} -void FieldDescriptorProto::clear_has_json_name() { - _has_bits_[0] &= ~0x00000010u; -} -void FieldDescriptorProto::clear_json_name() { - json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_json_name(); -} -const ::std::string& FieldDescriptorProto::json_name() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.json_name) - return json_name_.GetNoArena(); -} -void FieldDescriptorProto::set_json_name(const ::std::string& value) { - set_has_json_name(); - json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.json_name) -} -#if LANG_CXX11 -void FieldDescriptorProto::set_json_name(::std::string&& value) { - set_has_json_name(); - json_name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.json_name) -} -#endif -void FieldDescriptorProto::set_json_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_json_name(); - json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.json_name) -} -void FieldDescriptorProto::set_json_name(const char* value, size_t size) { - set_has_json_name(); - json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.json_name) -} -::std::string* FieldDescriptorProto::mutable_json_name() { - set_has_json_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.json_name) - return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FieldDescriptorProto::release_json_name() { - // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.json_name) - clear_has_json_name(); - return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FieldDescriptorProto::set_allocated_json_name(::std::string* json_name) { - if (json_name != NULL) { - set_has_json_name(); - } else { - clear_has_json_name(); + static const PROTOBUF_NAMESPACE_ID::OneofOptions& options(const OneofDescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 2u; } - json_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), json_name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.json_name) -} +}; -// optional .google.protobuf.FieldOptions options = 8; -bool FieldDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000020u) != 0; -} -void FieldDescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000020u; -} -void FieldDescriptorProto::clear_has_options() { - _has_bits_[0] &= ~0x00000020u; -} -void FieldDescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); - clear_has_options(); +const PROTOBUF_NAMESPACE_ID::OneofOptions& +OneofDescriptorProto::_Internal::options(const OneofDescriptorProto* msg) { + return *msg->options_; } -const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const { - const ::google::protobuf::FieldOptions* p = options_; - // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_FieldOptions_default_instance_); -} -::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::FieldOptions; - } - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options) - return options_; -} -::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() { - // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.options) - clear_has_options(); - ::google::protobuf::FieldOptions* temp = options_; - options_ = NULL; - return temp; -} -void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) { - delete options_; - options_ = options; - if (options) { - set_has_options(); - } else { - clear_has_options(); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.options) -} - -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS - -// =================================================================== - -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int OneofDescriptorProto::kNameFieldNumber; -const int OneofDescriptorProto::kOptionsFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -OneofDescriptorProto::OneofDescriptorProto() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - } +OneofDescriptorProto::OneofDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.OneofDescriptorProto) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.OneofDescriptorProto) } OneofDescriptorProto::OneofDescriptorProto(const OneofDescriptorProto& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_name()) { - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); - } - if (from.has_options()) { - options_ = new ::google::protobuf::OneofOptions(*from.options_); + : ::PROTOBUF_NAMESPACE_ID::Message(), + _has_bits_(from._has_bits_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_name()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArena()); + } + if (from._internal_has_options()) { + options_ = new PROTOBUF_NAMESPACE_ID::OneofOptions(*from.options_); } else { - options_ = NULL; + options_ = nullptr; } // @@protoc_insertion_point(copy_constructor:google.protobuf.OneofDescriptorProto) } void OneofDescriptorProto::SharedCtor() { - _cached_size_ = 0; - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - options_ = NULL; +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +options_ = nullptr; } OneofDescriptorProto::~OneofDescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.OneofDescriptorProto) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void OneofDescriptorProto::SharedDtor() { - name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (this != internal_default_instance()) delete options_; } -void OneofDescriptorProto::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* OneofDescriptorProto::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void OneofDescriptorProto::ArenaDtor(void* object) { + OneofDescriptorProto* _this = reinterpret_cast< OneofDescriptorProto* >(object); + (void)_this; } - -const OneofDescriptorProto& OneofDescriptorProto::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void OneofDescriptorProto::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -OneofDescriptorProto* OneofDescriptorProto::New(::google::protobuf::Arena* arena) const { - OneofDescriptorProto* n = new OneofDescriptorProto; - if (arena != NULL) { - arena->Own(n); - } - return n; +void OneofDescriptorProto::SetCachedSize(int size) const { + _cached_size_.Set(size); } void OneofDescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.OneofDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*name_.UnsafeRawStringPointer())->clear(); + name_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000002u) { - GOOGLE_DCHECK(options_ != NULL); - options_->::google::protobuf::OneofOptions::Clear(); + GOOGLE_DCHECK(options_ != nullptr); + options_->Clear(); } } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool OneofDescriptorProto::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.OneofDescriptorProto) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional string name = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.OneofDescriptorProto.name"); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* OneofDescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.OneofDescriptorProto.name"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional .google.protobuf.OneofOptions options = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, mutable_options())); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.OneofDescriptorProto) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.OneofDescriptorProto) - return false; -#undef DO_ -} - -void OneofDescriptorProto::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.OneofDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.OneofDescriptorProto.name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->name(), output); - } - - // optional .google.protobuf.OneofOptions options = 2; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 2, *this->options_, output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.OneofDescriptorProto) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* OneofDescriptorProto::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* OneofDescriptorProto::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional string name = 1; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.OneofDescriptorProto.name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->name(), target); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); } // optional .google.protobuf.OneofOptions options = 2; if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 2, *this->options_, deterministic, target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 2, _Internal::options(this), target, stream); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.OneofDescriptorProto) return target; @@ -6262,43 +4178,45 @@ size_t OneofDescriptorProto::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.OneofDescriptorProto) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } - if (_has_bits_[0 / 32] & 3u) { + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000003u) { // optional string name = 1; - if (has_name()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->name()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); } // optional .google.protobuf.OneofOptions options = 2; - if (has_options()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - *this->options_); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *options_); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void OneofDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +void OneofDescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.OneofDescriptorProto) GOOGLE_DCHECK_NE(&from, this); const OneofDescriptorProto* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.OneofDescriptorProto) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.OneofDescriptorProto) MergeFrom(*source); @@ -6308,23 +4226,22 @@ void OneofDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void OneofDescriptorProto::MergeFrom(const OneofDescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofDescriptorProto) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - set_has_name(); - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); + _internal_set_name(from._internal_name()); } if (cached_has_bits & 0x00000002u) { - mutable_options()->::google::protobuf::OneofOptions::MergeFrom(from.options()); + _internal_mutable_options()->PROTOBUF_NAMESPACE_ID::OneofOptions::MergeFrom(from._internal_options()); } } } -void OneofDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +void OneofDescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.OneofDescriptorProto) if (&from == this) return; Clear(); @@ -6339,384 +4256,514 @@ void OneofDescriptorProto::CopyFrom(const OneofDescriptorProto& from) { } bool OneofDescriptorProto::IsInitialized() const { - if (has_options()) { - if (!this->options_->IsInitialized()) return false; + if (_internal_has_options()) { + if (!options_->IsInitialized()) return false; } return true; } -void OneofDescriptorProto::Swap(OneofDescriptorProto* other) { - if (other == this) return; - InternalSwap(other); -} void OneofDescriptorProto::InternalSwap(OneofDescriptorProto* other) { using std::swap; - name_.Swap(&other->name_); - swap(options_, other->options_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata OneofDescriptorProto::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// OneofDescriptorProto - -// optional string name = 1; -bool OneofDescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void OneofDescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; -} -void OneofDescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; -} -void OneofDescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); -} -const ::std::string& OneofDescriptorProto::name() const { - // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name) - return name_.GetNoArena(); -} -void OneofDescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.OneofDescriptorProto.name) -} -#if LANG_CXX11 -void OneofDescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.OneofDescriptorProto.name) -} -#endif -void OneofDescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name) -} -void OneofDescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.name) -} -::std::string* OneofDescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* OneofDescriptorProto::release_name() { - // @@protoc_insertion_point(field_release:google.protobuf.OneofDescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void OneofDescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); - } else { - clear_has_name(); + name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + swap(options_, other->options_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata OneofDescriptorProto::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +class EnumDescriptorProto_EnumReservedRange::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_start(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name) + static void set_has_end(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumDescriptorProto.EnumReservedRange) +} +EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange(const EnumDescriptorProto_EnumReservedRange& from) + : ::PROTOBUF_NAMESPACE_ID::Message(), + _has_bits_(from._has_bits_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&start_, &from.start_, + static_cast(reinterpret_cast(&end_) - + reinterpret_cast(&start_)) + sizeof(end_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumDescriptorProto.EnumReservedRange) +} + +void EnumDescriptorProto_EnumReservedRange::SharedCtor() { +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&start_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&end_) - + reinterpret_cast(&start_)) + sizeof(end_)); +} + +EnumDescriptorProto_EnumReservedRange::~EnumDescriptorProto_EnumReservedRange() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumDescriptorProto.EnumReservedRange) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } -// optional .google.protobuf.OneofOptions options = 2; -bool OneofDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000002u) != 0; +void EnumDescriptorProto_EnumReservedRange::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); } -void OneofDescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000002u; + +void EnumDescriptorProto_EnumReservedRange::ArenaDtor(void* object) { + EnumDescriptorProto_EnumReservedRange* _this = reinterpret_cast< EnumDescriptorProto_EnumReservedRange* >(object); + (void)_this; +} +void EnumDescriptorProto_EnumReservedRange::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } -void OneofDescriptorProto::clear_has_options() { - _has_bits_[0] &= ~0x00000002u; +void EnumDescriptorProto_EnumReservedRange::SetCachedSize(int size) const { + _cached_size_.Set(size); } -void OneofDescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::OneofOptions::Clear(); - clear_has_options(); + +void EnumDescriptorProto_EnumReservedRange::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + ::memset(&start_, 0, static_cast( + reinterpret_cast(&end_) - + reinterpret_cast(&start_)) + sizeof(end_)); + } + _has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } -const ::google::protobuf::OneofOptions& OneofDescriptorProto::options() const { - const ::google::protobuf::OneofOptions* p = options_; - // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_OneofOptions_default_instance_); + +const char* EnumDescriptorProto_EnumReservedRange::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional int32 start = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + _Internal::set_has_start(&has_bits); + start_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // optional int32 end = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + _Internal::set_has_end(&has_bits); + end_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + _has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::OneofOptions* OneofDescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::OneofOptions; + +::PROTOBUF_NAMESPACE_ID::uint8* EnumDescriptorProto_EnumReservedRange::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _has_bits_[0]; + // optional int32 start = 1; + if (cached_has_bits & 0x00000001u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_start(), target); + } + + // optional int32 end = 2; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_end(), target); } - // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.options) - return options_; + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumDescriptorProto.EnumReservedRange) + return target; } -::google::protobuf::OneofOptions* OneofDescriptorProto::release_options() { - // @@protoc_insertion_point(field_release:google.protobuf.OneofDescriptorProto.options) - clear_has_options(); - ::google::protobuf::OneofOptions* temp = options_; - options_ = NULL; - return temp; + +size_t EnumDescriptorProto_EnumReservedRange::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional int32 start = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_start()); + } + + // optional int32 end = 2; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_end()); + } + + } + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; } -void OneofDescriptorProto::set_allocated_options(::google::protobuf::OneofOptions* options) { - delete options_; - options_ = options; - if (options) { - set_has_options(); + +void EnumDescriptorProto_EnumReservedRange::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) + GOOGLE_DCHECK_NE(&from, this); + const EnumDescriptorProto_EnumReservedRange* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumDescriptorProto.EnumReservedRange) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { - clear_has_options(); + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumDescriptorProto.EnumReservedRange) + MergeFrom(*source); } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.options) } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS +void EnumDescriptorProto_EnumReservedRange::MergeFrom(const EnumDescriptorProto_EnumReservedRange& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + start_ = from.start_; + } + if (cached_has_bits & 0x00000002u) { + end_ = from.end_; + } + _has_bits_[0] |= cached_has_bits; + } +} + +void EnumDescriptorProto_EnumReservedRange::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void EnumDescriptorProto_EnumReservedRange::CopyFrom(const EnumDescriptorProto_EnumReservedRange& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool EnumDescriptorProto_EnumReservedRange::IsInitialized() const { + return true; +} + +void EnumDescriptorProto_EnumReservedRange::InternalSwap(EnumDescriptorProto_EnumReservedRange* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(EnumDescriptorProto_EnumReservedRange, end_) + + sizeof(EnumDescriptorProto_EnumReservedRange::end_) + - PROTOBUF_FIELD_OFFSET(EnumDescriptorProto_EnumReservedRange, start_)>( + reinterpret_cast(&start_), + reinterpret_cast(&other->start_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata EnumDescriptorProto_EnumReservedRange::GetMetadata() const { + return GetMetadataStatic(); +} -// =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int EnumDescriptorProto::kNameFieldNumber; -const int EnumDescriptorProto::kValueFieldNumber; -const int EnumDescriptorProto::kOptionsFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +// =================================================================== -EnumDescriptorProto::EnumDescriptorProto() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class EnumDescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static const PROTOBUF_NAMESPACE_ID::EnumOptions& options(const EnumDescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 2u; } +}; + +const PROTOBUF_NAMESPACE_ID::EnumOptions& +EnumDescriptorProto::_Internal::options(const EnumDescriptorProto* msg) { + return *msg->options_; +} +EnumDescriptorProto::EnumDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + value_(arena), + reserved_range_(arena), + reserved_name_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.EnumDescriptorProto) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumDescriptorProto) } EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), _has_bits_(from._has_bits_), - _cached_size_(0), - value_(from.value_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_name()) { - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); - } - if (from.has_options()) { - options_ = new ::google::protobuf::EnumOptions(*from.options_); + value_(from.value_), + reserved_range_(from.reserved_range_), + reserved_name_(from.reserved_name_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_name()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArena()); + } + if (from._internal_has_options()) { + options_ = new PROTOBUF_NAMESPACE_ID::EnumOptions(*from.options_); } else { - options_ = NULL; + options_ = nullptr; } // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumDescriptorProto) } void EnumDescriptorProto::SharedCtor() { - _cached_size_ = 0; - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - options_ = NULL; +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +options_ = nullptr; } EnumDescriptorProto::~EnumDescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.EnumDescriptorProto) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void EnumDescriptorProto::SharedDtor() { - name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (this != internal_default_instance()) delete options_; } -void EnumDescriptorProto::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void EnumDescriptorProto::ArenaDtor(void* object) { + EnumDescriptorProto* _this = reinterpret_cast< EnumDescriptorProto* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* EnumDescriptorProto::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void EnumDescriptorProto::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -const EnumDescriptorProto& EnumDescriptorProto::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -EnumDescriptorProto* EnumDescriptorProto::New(::google::protobuf::Arena* arena) const { - EnumDescriptorProto* n = new EnumDescriptorProto; - if (arena != NULL) { - arena->Own(n); - } - return n; +void EnumDescriptorProto::SetCachedSize(int size) const { + _cached_size_.Set(size); } void EnumDescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; value_.Clear(); + reserved_range_.Clear(); + reserved_name_.Clear(); cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*name_.UnsafeRawStringPointer())->clear(); + name_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000002u) { - GOOGLE_DCHECK(options_ != NULL); - options_->::google::protobuf::EnumOptions::Clear(); + GOOGLE_DCHECK(options_ != nullptr); + options_->Clear(); } } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool EnumDescriptorProto::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.EnumDescriptorProto) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional string name = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.EnumDescriptorProto.name"); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* EnumDescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.EnumDescriptorProto.name"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated .google.protobuf.EnumValueDescriptorProto value = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_value())); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_value(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr)); + } else goto handle_unusual; + continue; // optional .google.protobuf.EnumOptions options = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, mutable_options())); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_reserved_range(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<34>(ptr)); + } else goto handle_unusual; + continue; + // repeated string reserved_name = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 42)) { + ptr -= 1; + do { + ptr += 1; + auto str = _internal_add_reserved_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.EnumDescriptorProto.reserved_name"); + #endif // !NDEBUG + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<42>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.EnumDescriptorProto) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.EnumDescriptorProto) - return false; -#undef DO_ + ptr = nullptr; + goto success; +#undef CHK_ } -void EnumDescriptorProto::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.EnumDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; +::PROTOBUF_NAMESPACE_ID::uint8* EnumDescriptorProto::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional string name = 1; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.EnumDescriptorProto.name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->name(), output); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); } // repeated .google.protobuf.EnumValueDescriptorProto value = 2; for (unsigned int i = 0, - n = static_cast(this->value_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 2, this->value(static_cast(i)), output); + n = static_cast(this->_internal_value_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(2, this->_internal_value(i), target, stream); } // optional .google.protobuf.EnumOptions options = 3; if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 3, *this->options_, output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.EnumDescriptorProto) -} - -::google::protobuf::uint8* EnumDescriptorProto::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.EnumDescriptorProto.name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->name(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 3, _Internal::options(this), target, stream); } - // repeated .google.protobuf.EnumValueDescriptorProto value = 2; + // repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; for (unsigned int i = 0, - n = static_cast(this->value_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 2, this->value(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_reserved_range_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(4, this->_internal_reserved_range(i), target, stream); } - // optional .google.protobuf.EnumOptions options = 3; - if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 3, *this->options_, deterministic, target); + // repeated string reserved_name = 5; + for (int i = 0, n = this->_internal_reserved_name_size(); i < n; i++) { + const auto& s = this->_internal_reserved_name(i); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + s.data(), static_cast(s.length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.EnumDescriptorProto.reserved_name"); + target = stream->WriteString(5, s, target); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumDescriptorProto) return target; @@ -6726,54 +4773,67 @@ size_t EnumDescriptorProto::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; + total_size += 1UL * this->_internal_value_size(); + for (const auto& msg : this->value_) { total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - // repeated .google.protobuf.EnumValueDescriptorProto value = 2; - { - unsigned int count = static_cast(this->value_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->value(static_cast(i))); - } + + // repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; + total_size += 1UL * this->_internal_reserved_range_size(); + for (const auto& msg : this->reserved_range_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated string reserved_name = 5; + total_size += 1 * + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(reserved_name_.size()); + for (int i = 0, n = reserved_name_.size(); i < n; i++) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + reserved_name_.Get(i)); } - if (_has_bits_[0 / 32] & 3u) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000003u) { // optional string name = 1; - if (has_name()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->name()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); } // optional .google.protobuf.EnumOptions options = 3; - if (has_options()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - *this->options_); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *options_); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void EnumDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +void EnumDescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumDescriptorProto) GOOGLE_DCHECK_NE(&from, this); const EnumDescriptorProto* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumDescriptorProto) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumDescriptorProto) MergeFrom(*source); @@ -6783,24 +4843,25 @@ void EnumDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void EnumDescriptorProto::MergeFrom(const EnumDescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumDescriptorProto) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; value_.MergeFrom(from.value_); + reserved_range_.MergeFrom(from.reserved_range_); + reserved_name_.MergeFrom(from.reserved_name_); cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - set_has_name(); - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); + _internal_set_name(from._internal_name()); } if (cached_has_bits & 0x00000002u) { - mutable_options()->::google::protobuf::EnumOptions::MergeFrom(from.options()); + _internal_mutable_options()->PROTOBUF_NAMESPACE_ID::EnumOptions::MergeFrom(from._internal_options()); } } } -void EnumDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +void EnumDescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumDescriptorProto) if (&from == this) return; Clear(); @@ -6815,415 +4876,216 @@ void EnumDescriptorProto::CopyFrom(const EnumDescriptorProto& from) { } bool EnumDescriptorProto::IsInitialized() const { - if (!::google::protobuf::internal::AllAreInitialized(this->value())) return false; - if (has_options()) { - if (!this->options_->IsInitialized()) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(value_)) return false; + if (_internal_has_options()) { + if (!options_->IsInitialized()) return false; } return true; } -void EnumDescriptorProto::Swap(EnumDescriptorProto* other) { - if (other == this) return; - InternalSwap(other); -} void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); value_.InternalSwap(&other->value_); - name_.Swap(&other->name_); + reserved_range_.InternalSwap(&other->reserved_range_); + reserved_name_.InternalSwap(&other->reserved_name_); + name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); swap(options_, other->options_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata EnumDescriptorProto::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// EnumDescriptorProto - -// optional string name = 1; -bool EnumDescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void EnumDescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; -} -void EnumDescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; -} -void EnumDescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); -} -const ::std::string& EnumDescriptorProto::name() const { - // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name) - return name_.GetNoArena(); -} -void EnumDescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name) -} -#if LANG_CXX11 -void EnumDescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumDescriptorProto.name) -} -#endif -void EnumDescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name) -} -void EnumDescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name) -} -::std::string* EnumDescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* EnumDescriptorProto::release_name() { - // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void EnumDescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); - } else { - clear_has_name(); - } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name) } -// repeated .google.protobuf.EnumValueDescriptorProto value = 2; -int EnumDescriptorProto::value_size() const { - return value_.size(); -} -void EnumDescriptorProto::clear_value() { - value_.Clear(); -} -const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.value) - return value_.Get(index); -} -::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.value) - return value_.Mutable(index); -} -::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() { - // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value) - return value_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* -EnumDescriptorProto::mutable_value() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value) - return &value_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& -EnumDescriptorProto::value() const { - // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value) - return value_; -} - -// optional .google.protobuf.EnumOptions options = 3; -bool EnumDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void EnumDescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000002u; -} -void EnumDescriptorProto::clear_has_options() { - _has_bits_[0] &= ~0x00000002u; -} -void EnumDescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear(); - clear_has_options(); -} -const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const { - const ::google::protobuf::EnumOptions* p = options_; - // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_EnumOptions_default_instance_); -} -::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::EnumOptions; - } - // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options) - return options_; -} -::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() { - // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.options) - clear_has_options(); - ::google::protobuf::EnumOptions* temp = options_; - options_ = NULL; - return temp; -} -void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) { - delete options_; - options_ = options; - if (options) { - set_has_options(); - } else { - clear_has_options(); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options) +::PROTOBUF_NAMESPACE_ID::Metadata EnumDescriptorProto::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int EnumValueDescriptorProto::kNameFieldNumber; -const int EnumValueDescriptorProto::kNumberFieldNumber; -const int EnumValueDescriptorProto::kOptionsFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -EnumValueDescriptorProto::EnumValueDescriptorProto() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class EnumValueDescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } + static void set_has_number(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static const PROTOBUF_NAMESPACE_ID::EnumValueOptions& options(const EnumValueDescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +const PROTOBUF_NAMESPACE_ID::EnumValueOptions& +EnumValueDescriptorProto::_Internal::options(const EnumValueDescriptorProto* msg) { + return *msg->options_; +} +EnumValueDescriptorProto::EnumValueDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.EnumValueDescriptorProto) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumValueDescriptorProto) } EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProto& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_name()) { - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); - } - if (from.has_options()) { - options_ = new ::google::protobuf::EnumValueOptions(*from.options_); + : ::PROTOBUF_NAMESPACE_ID::Message(), + _has_bits_(from._has_bits_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_name()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArena()); + } + if (from._internal_has_options()) { + options_ = new PROTOBUF_NAMESPACE_ID::EnumValueOptions(*from.options_); } else { - options_ = NULL; + options_ = nullptr; } number_ = from.number_; // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueDescriptorProto) } void EnumValueDescriptorProto::SharedCtor() { - _cached_size_ = 0; - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - ::memset(&options_, 0, static_cast( - reinterpret_cast(&number_) - - reinterpret_cast(&options_)) + sizeof(number_)); +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&options_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&number_) - + reinterpret_cast(&options_)) + sizeof(number_)); } EnumValueDescriptorProto::~EnumValueDescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.EnumValueDescriptorProto) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void EnumValueDescriptorProto::SharedDtor() { - name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (this != internal_default_instance()) delete options_; } -void EnumValueDescriptorProto::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* EnumValueDescriptorProto::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void EnumValueDescriptorProto::ArenaDtor(void* object) { + EnumValueDescriptorProto* _this = reinterpret_cast< EnumValueDescriptorProto* >(object); + (void)_this; } - -const EnumValueDescriptorProto& EnumValueDescriptorProto::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void EnumValueDescriptorProto::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -EnumValueDescriptorProto* EnumValueDescriptorProto::New(::google::protobuf::Arena* arena) const { - EnumValueDescriptorProto* n = new EnumValueDescriptorProto; - if (arena != NULL) { - arena->Own(n); - } - return n; +void EnumValueDescriptorProto::SetCachedSize(int size) const { + _cached_size_.Set(size); } void EnumValueDescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*name_.UnsafeRawStringPointer())->clear(); + name_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000002u) { - GOOGLE_DCHECK(options_ != NULL); - options_->::google::protobuf::EnumValueOptions::Clear(); + GOOGLE_DCHECK(options_ != nullptr); + options_->Clear(); } } number_ = 0; _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool EnumValueDescriptorProto::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.EnumValueDescriptorProto) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional string name = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.EnumValueDescriptorProto.name"); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* EnumValueDescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.EnumValueDescriptorProto.name"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional int32 number = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) { - set_has_number(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, &number_))); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + _Internal::set_has_number(&has_bits); + number_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional .google.protobuf.EnumValueOptions options = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, mutable_options())); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.EnumValueDescriptorProto) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.EnumValueDescriptorProto) - return false; -#undef DO_ -} - -void EnumValueDescriptorProto::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.EnumValueDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.EnumValueDescriptorProto.name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->name(), output); - } - - // optional int32 number = 2; - if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->number(), output); - } - - // optional .google.protobuf.EnumValueOptions options = 3; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 3, *this->options_, output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.EnumValueDescriptorProto) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* EnumValueDescriptorProto::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* EnumValueDescriptorProto::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional string name = 1; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.EnumValueDescriptorProto.name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->name(), target); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); } // optional int32 number = 2; if (cached_has_bits & 0x00000004u) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->number(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_number(), target); } // optional .google.protobuf.EnumValueOptions options = 3; if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 3, *this->options_, deterministic, target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 3, _Internal::options(this), target, stream); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueDescriptorProto) return target; @@ -7233,50 +5095,52 @@ size_t EnumValueDescriptorProto::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueDescriptorProto) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } - if (_has_bits_[0 / 32] & 7u) { + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000007u) { // optional string name = 1; - if (has_name()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->name()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); } // optional .google.protobuf.EnumValueOptions options = 3; - if (has_options()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - *this->options_); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *options_); } // optional int32 number = 2; - if (has_number()) { + if (cached_has_bits & 0x00000004u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - this->number()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_number()); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +void EnumValueDescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValueDescriptorProto) GOOGLE_DCHECK_NE(&from, this); const EnumValueDescriptorProto* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumValueDescriptorProto) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumValueDescriptorProto) MergeFrom(*source); @@ -7286,18 +5150,17 @@ void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueDescriptorProto) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 7u) { + if (cached_has_bits & 0x00000007u) { if (cached_has_bits & 0x00000001u) { - set_has_name(); - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); + _internal_set_name(from._internal_name()); } if (cached_has_bits & 0x00000002u) { - mutable_options()->::google::protobuf::EnumValueOptions::MergeFrom(from.options()); + _internal_mutable_options()->PROTOBUF_NAMESPACE_ID::EnumValueOptions::MergeFrom(from._internal_options()); } if (cached_has_bits & 0x00000004u) { number_ = from.number_; @@ -7306,7 +5169,7 @@ void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) { } } -void EnumValueDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +void EnumValueDescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumValueDescriptorProto) if (&from == this) return; Clear(); @@ -7321,409 +5184,218 @@ void EnumValueDescriptorProto::CopyFrom(const EnumValueDescriptorProto& from) { } bool EnumValueDescriptorProto::IsInitialized() const { - if (has_options()) { - if (!this->options_->IsInitialized()) return false; + if (_internal_has_options()) { + if (!options_->IsInitialized()) return false; } return true; } -void EnumValueDescriptorProto::Swap(EnumValueDescriptorProto* other) { - if (other == this) return; - InternalSwap(other); -} void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) { using std::swap; - name_.Swap(&other->name_); - swap(options_, other->options_); - swap(number_, other->number_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata EnumValueDescriptorProto::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// EnumValueDescriptorProto - -// optional string name = 1; -bool EnumValueDescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void EnumValueDescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; -} -void EnumValueDescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; -} -void EnumValueDescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); -} -const ::std::string& EnumValueDescriptorProto::name() const { - // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name) - return name_.GetNoArena(); -} -void EnumValueDescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.name) -} -#if LANG_CXX11 -void EnumValueDescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumValueDescriptorProto.name) -} -#endif -void EnumValueDescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name) -} -void EnumValueDescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name) -} -::std::string* EnumValueDescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* EnumValueDescriptorProto::release_name() { - // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void EnumValueDescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); - } else { - clear_has_name(); - } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name) + name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(EnumValueDescriptorProto, number_) + + sizeof(EnumValueDescriptorProto::number_) + - PROTOBUF_FIELD_OFFSET(EnumValueDescriptorProto, options_)>( + reinterpret_cast(&options_), + reinterpret_cast(&other->options_)); } -// optional int32 number = 2; -bool EnumValueDescriptorProto::has_number() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -void EnumValueDescriptorProto::set_has_number() { - _has_bits_[0] |= 0x00000004u; -} -void EnumValueDescriptorProto::clear_has_number() { - _has_bits_[0] &= ~0x00000004u; -} -void EnumValueDescriptorProto::clear_number() { - number_ = 0; - clear_has_number(); -} -::google::protobuf::int32 EnumValueDescriptorProto::number() const { - // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.number) - return number_; -} -void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) { - set_has_number(); - number_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.number) -} - -// optional .google.protobuf.EnumValueOptions options = 3; -bool EnumValueDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void EnumValueDescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000002u; -} -void EnumValueDescriptorProto::clear_has_options() { - _has_bits_[0] &= ~0x00000002u; -} -void EnumValueDescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear(); - clear_has_options(); -} -const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const { - const ::google::protobuf::EnumValueOptions* p = options_; - // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_EnumValueOptions_default_instance_); -} -::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::EnumValueOptions; - } - // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options) - return options_; -} -::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() { - // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.options) - clear_has_options(); - ::google::protobuf::EnumValueOptions* temp = options_; - options_ = NULL; - return temp; -} -void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) { - delete options_; - options_ = options; - if (options) { - set_has_options(); - } else { - clear_has_options(); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.options) +::PROTOBUF_NAMESPACE_ID::Metadata EnumValueDescriptorProto::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int ServiceDescriptorProto::kNameFieldNumber; -const int ServiceDescriptorProto::kMethodFieldNumber; -const int ServiceDescriptorProto::kOptionsFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -ServiceDescriptorProto::ServiceDescriptorProto() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class ServiceDescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } + static const PROTOBUF_NAMESPACE_ID::ServiceOptions& options(const ServiceDescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +const PROTOBUF_NAMESPACE_ID::ServiceOptions& +ServiceDescriptorProto::_Internal::options(const ServiceDescriptorProto* msg) { + return *msg->options_; +} +ServiceDescriptorProto::ServiceDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + method_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.ServiceDescriptorProto) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.ServiceDescriptorProto) } ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), _has_bits_(from._has_bits_), - _cached_size_(0), method_(from.method_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_name()) { - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); - } - if (from.has_options()) { - options_ = new ::google::protobuf::ServiceOptions(*from.options_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_name()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArena()); + } + if (from._internal_has_options()) { + options_ = new PROTOBUF_NAMESPACE_ID::ServiceOptions(*from.options_); } else { - options_ = NULL; + options_ = nullptr; } // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceDescriptorProto) } void ServiceDescriptorProto::SharedCtor() { - _cached_size_ = 0; - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - options_ = NULL; +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +options_ = nullptr; } ServiceDescriptorProto::~ServiceDescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.ServiceDescriptorProto) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void ServiceDescriptorProto::SharedDtor() { - name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (this != internal_default_instance()) delete options_; } -void ServiceDescriptorProto::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void ServiceDescriptorProto::ArenaDtor(void* object) { + ServiceDescriptorProto* _this = reinterpret_cast< ServiceDescriptorProto* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* ServiceDescriptorProto::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void ServiceDescriptorProto::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -const ServiceDescriptorProto& ServiceDescriptorProto::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -ServiceDescriptorProto* ServiceDescriptorProto::New(::google::protobuf::Arena* arena) const { - ServiceDescriptorProto* n = new ServiceDescriptorProto; - if (arena != NULL) { - arena->Own(n); - } - return n; +void ServiceDescriptorProto::SetCachedSize(int size) const { + _cached_size_.Set(size); } void ServiceDescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; method_.Clear(); cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*name_.UnsafeRawStringPointer())->clear(); + name_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000002u) { - GOOGLE_DCHECK(options_ != NULL); - options_->::google::protobuf::ServiceOptions::Clear(); + GOOGLE_DCHECK(options_ != nullptr); + options_->Clear(); } } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool ServiceDescriptorProto::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.ServiceDescriptorProto) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional string name = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.ServiceDescriptorProto.name"); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* ServiceDescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.ServiceDescriptorProto.name"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated .google.protobuf.MethodDescriptorProto method = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_method())); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_method(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr)); + } else goto handle_unusual; + continue; // optional .google.protobuf.ServiceOptions options = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, mutable_options())); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.ServiceDescriptorProto) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.ServiceDescriptorProto) - return false; -#undef DO_ -} - -void ServiceDescriptorProto::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.ServiceDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.ServiceDescriptorProto.name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->name(), output); - } - - // repeated .google.protobuf.MethodDescriptorProto method = 2; - for (unsigned int i = 0, - n = static_cast(this->method_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 2, this->method(static_cast(i)), output); - } - - // optional .google.protobuf.ServiceOptions options = 3; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 3, *this->options_, output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.ServiceDescriptorProto) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* ServiceDescriptorProto::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* ServiceDescriptorProto::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional string name = 1; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.ServiceDescriptorProto.name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->name(), target); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); } // repeated .google.protobuf.MethodDescriptorProto method = 2; for (unsigned int i = 0, - n = static_cast(this->method_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 2, this->method(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_method_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(2, this->_internal_method(i), target, stream); } // optional .google.protobuf.ServiceOptions options = 3; if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 3, *this->options_, deterministic, target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 3, _Internal::options(this), target, stream); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceDescriptorProto) return target; @@ -7733,54 +5405,52 @@ size_t ServiceDescriptorProto::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceDescriptorProto) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.MethodDescriptorProto method = 2; - { - unsigned int count = static_cast(this->method_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->method(static_cast(i))); - } + total_size += 1UL * this->_internal_method_size(); + for (const auto& msg : this->method_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - if (_has_bits_[0 / 32] & 3u) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000003u) { // optional string name = 1; - if (has_name()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->name()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); } // optional .google.protobuf.ServiceOptions options = 3; - if (has_options()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - *this->options_); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *options_); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void ServiceDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +void ServiceDescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ServiceDescriptorProto) GOOGLE_DCHECK_NE(&from, this); const ServiceDescriptorProto* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ServiceDescriptorProto) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ServiceDescriptorProto) MergeFrom(*source); @@ -7790,24 +5460,23 @@ void ServiceDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) void ServiceDescriptorProto::MergeFrom(const ServiceDescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceDescriptorProto) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; method_.MergeFrom(from.method_); cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - set_has_name(); - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); + _internal_set_name(from._internal_name()); } if (cached_has_bits & 0x00000002u) { - mutable_options()->::google::protobuf::ServiceOptions::MergeFrom(from.options()); + _internal_mutable_options()->PROTOBUF_NAMESPACE_ID::ServiceOptions::MergeFrom(from._internal_options()); } } } -void ServiceDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +void ServiceDescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ServiceDescriptorProto) if (&from == this) return; Clear(); @@ -7822,217 +5491,86 @@ void ServiceDescriptorProto::CopyFrom(const ServiceDescriptorProto& from) { } bool ServiceDescriptorProto::IsInitialized() const { - if (!::google::protobuf::internal::AllAreInitialized(this->method())) return false; - if (has_options()) { - if (!this->options_->IsInitialized()) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(method_)) return false; + if (_internal_has_options()) { + if (!options_->IsInitialized()) return false; } return true; } -void ServiceDescriptorProto::Swap(ServiceDescriptorProto* other) { - if (other == this) return; - InternalSwap(other); -} void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); method_.InternalSwap(&other->method_); - name_.Swap(&other->name_); + name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); swap(options_, other->options_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata ServiceDescriptorProto::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// ServiceDescriptorProto - -// optional string name = 1; -bool ServiceDescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void ServiceDescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; -} -void ServiceDescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; -} -void ServiceDescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); -} -const ::std::string& ServiceDescriptorProto::name() const { - // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name) - return name_.GetNoArena(); -} -void ServiceDescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.ServiceDescriptorProto.name) -} -#if LANG_CXX11 -void ServiceDescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.ServiceDescriptorProto.name) -} -#endif -void ServiceDescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name) -} -void ServiceDescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name) -} -::std::string* ServiceDescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* ServiceDescriptorProto::release_name() { - // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void ServiceDescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); - } else { - clear_has_name(); - } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name) } -// repeated .google.protobuf.MethodDescriptorProto method = 2; -int ServiceDescriptorProto::method_size() const { - return method_.size(); -} -void ServiceDescriptorProto::clear_method() { - method_.Clear(); -} -const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.method) - return method_.Get(index); -} -::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.method) - return method_.Mutable(index); -} -::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() { - // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method) - return method_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* -ServiceDescriptorProto::mutable_method() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method) - return &method_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& -ServiceDescriptorProto::method() const { - // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method) - return method_; -} - -// optional .google.protobuf.ServiceOptions options = 3; -bool ServiceDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void ServiceDescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000002u; -} -void ServiceDescriptorProto::clear_has_options() { - _has_bits_[0] &= ~0x00000002u; -} -void ServiceDescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear(); - clear_has_options(); -} -const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const { - const ::google::protobuf::ServiceOptions* p = options_; - // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_ServiceOptions_default_instance_); -} -::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::ServiceOptions; - } - // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options) - return options_; -} -::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() { - // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.options) - clear_has_options(); - ::google::protobuf::ServiceOptions* temp = options_; - options_ = NULL; - return temp; -} -void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) { - delete options_; - options_ = options; - if (options) { - set_has_options(); - } else { - clear_has_options(); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.options) +::PROTOBUF_NAMESPACE_ID::Metadata ServiceDescriptorProto::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int MethodDescriptorProto::kNameFieldNumber; -const int MethodDescriptorProto::kInputTypeFieldNumber; -const int MethodDescriptorProto::kOutputTypeFieldNumber; -const int MethodDescriptorProto::kOptionsFieldNumber; -const int MethodDescriptorProto::kClientStreamingFieldNumber; -const int MethodDescriptorProto::kServerStreamingFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -MethodDescriptorProto::MethodDescriptorProto() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class MethodDescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_input_type(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_output_type(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static const PROTOBUF_NAMESPACE_ID::MethodOptions& options(const MethodDescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 8u; } + static void set_has_client_streaming(HasBits* has_bits) { + (*has_bits)[0] |= 16u; + } + static void set_has_server_streaming(HasBits* has_bits) { + (*has_bits)[0] |= 32u; + } +}; + +const PROTOBUF_NAMESPACE_ID::MethodOptions& +MethodDescriptorProto::_Internal::options(const MethodDescriptorProto* msg) { + return *msg->options_; +} +MethodDescriptorProto::MethodDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.MethodDescriptorProto) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.MethodDescriptorProto) } MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_name()) { - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); - } - input_type_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_input_type()) { - input_type_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.input_type_); - } - output_type_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_output_type()) { - output_type_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.output_type_); - } - if (from.has_options()) { - options_ = new ::google::protobuf::MethodOptions(*from.options_); + : ::PROTOBUF_NAMESPACE_ID::Message(), + _has_bits_(from._has_bits_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_name()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArena()); + } + input_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_input_type()) { + input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_input_type(), + GetArena()); + } + output_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_output_type()) { + output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_output_type(), + GetArena()); + } + if (from._internal_has_options()) { + options_ = new PROTOBUF_NAMESPACE_ID::MethodOptions(*from.options_); } else { - options_ = NULL; + options_ = nullptr; } ::memcpy(&client_streaming_, &from.client_streaming_, static_cast(reinterpret_cast(&server_streaming_) - @@ -8041,323 +5579,215 @@ MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from) } void MethodDescriptorProto::SharedCtor() { - _cached_size_ = 0; - name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - input_type_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - output_type_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - ::memset(&options_, 0, static_cast( - reinterpret_cast(&server_streaming_) - - reinterpret_cast(&options_)) + sizeof(server_streaming_)); +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +input_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +output_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&options_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&server_streaming_) - + reinterpret_cast(&options_)) + sizeof(server_streaming_)); } MethodDescriptorProto::~MethodDescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.MethodDescriptorProto) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void MethodDescriptorProto::SharedDtor() { - name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - input_type_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - output_type_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + input_type_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + output_type_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (this != internal_default_instance()) delete options_; } -void MethodDescriptorProto::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void MethodDescriptorProto::ArenaDtor(void* object) { + MethodDescriptorProto* _this = reinterpret_cast< MethodDescriptorProto* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* MethodDescriptorProto::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void MethodDescriptorProto::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -const MethodDescriptorProto& MethodDescriptorProto::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -MethodDescriptorProto* MethodDescriptorProto::New(::google::protobuf::Arena* arena) const { - MethodDescriptorProto* n = new MethodDescriptorProto; - if (arena != NULL) { - arena->Own(n); - } - return n; +void MethodDescriptorProto::SetCachedSize(int size) const { + _cached_size_.Set(size); } void MethodDescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.MethodDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 15u) { + if (cached_has_bits & 0x0000000fu) { if (cached_has_bits & 0x00000001u) { - GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*name_.UnsafeRawStringPointer())->clear(); + name_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000002u) { - GOOGLE_DCHECK(!input_type_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*input_type_.UnsafeRawStringPointer())->clear(); + input_type_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000004u) { - GOOGLE_DCHECK(!output_type_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*output_type_.UnsafeRawStringPointer())->clear(); + output_type_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000008u) { - GOOGLE_DCHECK(options_ != NULL); - options_->::google::protobuf::MethodOptions::Clear(); + GOOGLE_DCHECK(options_ != nullptr); + options_->Clear(); } } - if (cached_has_bits & 48u) { - ::memset(&client_streaming_, 0, static_cast( - reinterpret_cast(&server_streaming_) - - reinterpret_cast(&client_streaming_)) + sizeof(server_streaming_)); - } + ::memset(&client_streaming_, 0, static_cast( + reinterpret_cast(&server_streaming_) - + reinterpret_cast(&client_streaming_)) + sizeof(server_streaming_)); _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool MethodDescriptorProto::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.MethodDescriptorProto) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional string name = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.MethodDescriptorProto.name"); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* MethodDescriptorProto::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.MethodDescriptorProto.name"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string input_type = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_input_type())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->input_type().data(), static_cast(this->input_type().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.MethodDescriptorProto.input_type"); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + auto str = _internal_mutable_input_type(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.MethodDescriptorProto.input_type"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string output_type = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_output_type())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->output_type().data(), static_cast(this->output_type().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.MethodDescriptorProto.output_type"); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + auto str = _internal_mutable_output_type(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.MethodDescriptorProto.output_type"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional .google.protobuf.MethodOptions options = 4; - case 4: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, mutable_options())); - } else { - goto handle_unusual; - } - break; - } - + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional bool client_streaming = 5 [default = false]; - case 5: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(40u /* 40 & 0xFF */)) { - set_has_client_streaming(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &client_streaming_))); - } else { - goto handle_unusual; - } - break; - } - + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 40)) { + _Internal::set_has_client_streaming(&has_bits); + client_streaming_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional bool server_streaming = 6 [default = false]; - case 6: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(48u /* 48 & 0xFF */)) { - set_has_server_streaming(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &server_streaming_))); - } else { - goto handle_unusual; - } - break; - } - + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 48)) { + _Internal::set_has_server_streaming(&has_bits); + server_streaming_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.MethodDescriptorProto) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.MethodDescriptorProto) - return false; -#undef DO_ -} - -void MethodDescriptorProto::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.MethodDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.MethodDescriptorProto.name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->name(), output); - } - - // optional string input_type = 2; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->input_type().data(), static_cast(this->input_type().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.MethodDescriptorProto.input_type"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 2, this->input_type(), output); - } - - // optional string output_type = 3; - if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->output_type().data(), static_cast(this->output_type().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.MethodDescriptorProto.output_type"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 3, this->output_type(), output); - } - - // optional .google.protobuf.MethodOptions options = 4; - if (cached_has_bits & 0x00000008u) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 4, *this->options_, output); - } - - // optional bool client_streaming = 5 [default = false]; - if (cached_has_bits & 0x00000010u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(5, this->client_streaming(), output); - } - - // optional bool server_streaming = 6 [default = false]; - if (cached_has_bits & 0x00000020u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(6, this->server_streaming(), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.MethodDescriptorProto) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* MethodDescriptorProto::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* MethodDescriptorProto::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodDescriptorProto) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional string name = 1; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name().data(), static_cast(this->name().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.MethodDescriptorProto.name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->name(), target); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); } // optional string input_type = 2; if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->input_type().data(), static_cast(this->input_type().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_input_type().data(), static_cast(this->_internal_input_type().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.MethodDescriptorProto.input_type"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 2, this->input_type(), target); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_input_type(), target); } // optional string output_type = 3; if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->output_type().data(), static_cast(this->output_type().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_output_type().data(), static_cast(this->_internal_output_type().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.MethodDescriptorProto.output_type"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 3, this->output_type(), target); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_output_type(), target); } // optional .google.protobuf.MethodOptions options = 4; if (cached_has_bits & 0x00000008u) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 4, *this->options_, deterministic, target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 4, _Internal::options(this), target, stream); } // optional bool client_streaming = 5 [default = false]; if (cached_has_bits & 0x00000010u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->client_streaming(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(5, this->_internal_client_streaming(), target); } // optional bool server_streaming = 6 [default = false]; if (cached_has_bits & 0x00000020u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(6, this->server_streaming(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(6, this->_internal_server_streaming(), target); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodDescriptorProto) return target; @@ -8367,67 +5797,69 @@ size_t MethodDescriptorProto::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodDescriptorProto) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } - if (_has_bits_[0 / 32] & 63u) { + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { // optional string name = 1; - if (has_name()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->name()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); } // optional string input_type = 2; - if (has_input_type()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->input_type()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_input_type()); } // optional string output_type = 3; - if (has_output_type()) { + if (cached_has_bits & 0x00000004u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->output_type()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_output_type()); } // optional .google.protobuf.MethodOptions options = 4; - if (has_options()) { + if (cached_has_bits & 0x00000008u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - *this->options_); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *options_); } // optional bool client_streaming = 5 [default = false]; - if (has_client_streaming()) { + if (cached_has_bits & 0x00000010u) { total_size += 1 + 1; } // optional bool server_streaming = 6 [default = false]; - if (has_server_streaming()) { + if (cached_has_bits & 0x00000020u) { total_size += 1 + 1; } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { +void MethodDescriptorProto::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MethodDescriptorProto) GOOGLE_DCHECK_NE(&from, this); const MethodDescriptorProto* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MethodDescriptorProto) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MethodDescriptorProto) MergeFrom(*source); @@ -8437,26 +5869,23 @@ void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodDescriptorProto) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 63u) { + if (cached_has_bits & 0x0000003fu) { if (cached_has_bits & 0x00000001u) { - set_has_name(); - name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); + _internal_set_name(from._internal_name()); } if (cached_has_bits & 0x00000002u) { - set_has_input_type(); - input_type_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.input_type_); + _internal_set_input_type(from._internal_input_type()); } if (cached_has_bits & 0x00000004u) { - set_has_output_type(); - output_type_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.output_type_); + _internal_set_output_type(from._internal_output_type()); } if (cached_has_bits & 0x00000008u) { - mutable_options()->::google::protobuf::MethodOptions::MergeFrom(from.options()); + _internal_mutable_options()->PROTOBUF_NAMESPACE_ID::MethodOptions::MergeFrom(from._internal_options()); } if (cached_has_bits & 0x00000010u) { client_streaming_ = from.client_streaming_; @@ -8468,7 +5897,7 @@ void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) { } } -void MethodDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { +void MethodDescriptorProto::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MethodDescriptorProto) if (&from == this) return; Clear(); @@ -8483,1151 +5912,703 @@ void MethodDescriptorProto::CopyFrom(const MethodDescriptorProto& from) { } bool MethodDescriptorProto::IsInitialized() const { - if (has_options()) { - if (!this->options_->IsInitialized()) return false; + if (_internal_has_options()) { + if (!options_->IsInitialized()) return false; } return true; } -void MethodDescriptorProto::Swap(MethodDescriptorProto* other) { - if (other == this) return; - InternalSwap(other); -} void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) { using std::swap; - name_.Swap(&other->name_); - input_type_.Swap(&other->input_type_); - output_type_.Swap(&other->output_type_); - swap(options_, other->options_); - swap(client_streaming_, other->client_streaming_); - swap(server_streaming_, other->server_streaming_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata MethodDescriptorProto::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// MethodDescriptorProto - -// optional string name = 1; -bool MethodDescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void MethodDescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; -} -void MethodDescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; -} -void MethodDescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); -} -const ::std::string& MethodDescriptorProto::name() const { - // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name) - return name_.GetNoArena(); -} -void MethodDescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.name) -} -#if LANG_CXX11 -void MethodDescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.name) -} -#endif -void MethodDescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name) -} -void MethodDescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name) -} -::std::string* MethodDescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* MethodDescriptorProto::release_name() { - // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void MethodDescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); - } else { - clear_has_name(); - } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name) -} - -// optional string input_type = 2; -bool MethodDescriptorProto::has_input_type() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void MethodDescriptorProto::set_has_input_type() { - _has_bits_[0] |= 0x00000002u; -} -void MethodDescriptorProto::clear_has_input_type() { - _has_bits_[0] &= ~0x00000002u; -} -void MethodDescriptorProto::clear_input_type() { - input_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_input_type(); -} -const ::std::string& MethodDescriptorProto::input_type() const { - // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.input_type) - return input_type_.GetNoArena(); -} -void MethodDescriptorProto::set_input_type(const ::std::string& value) { - set_has_input_type(); - input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.input_type) -} -#if LANG_CXX11 -void MethodDescriptorProto::set_input_type(::std::string&& value) { - set_has_input_type(); - input_type_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.input_type) -} -#endif -void MethodDescriptorProto::set_input_type(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_input_type(); - input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type) -} -void MethodDescriptorProto::set_input_type(const char* value, size_t size) { - set_has_input_type(); - input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type) -} -::std::string* MethodDescriptorProto::mutable_input_type() { - set_has_input_type(); - // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type) - return input_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* MethodDescriptorProto::release_input_type() { - // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.input_type) - clear_has_input_type(); - return input_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) { - if (input_type != NULL) { - set_has_input_type(); - } else { - clear_has_input_type(); - } - input_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), input_type); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type) -} - -// optional string output_type = 3; -bool MethodDescriptorProto::has_output_type() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -void MethodDescriptorProto::set_has_output_type() { - _has_bits_[0] |= 0x00000004u; -} -void MethodDescriptorProto::clear_has_output_type() { - _has_bits_[0] &= ~0x00000004u; -} -void MethodDescriptorProto::clear_output_type() { - output_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_output_type(); -} -const ::std::string& MethodDescriptorProto::output_type() const { - // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.output_type) - return output_type_.GetNoArena(); -} -void MethodDescriptorProto::set_output_type(const ::std::string& value) { - set_has_output_type(); - output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.output_type) -} -#if LANG_CXX11 -void MethodDescriptorProto::set_output_type(::std::string&& value) { - set_has_output_type(); - output_type_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.output_type) -} -#endif -void MethodDescriptorProto::set_output_type(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_output_type(); - output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type) -} -void MethodDescriptorProto::set_output_type(const char* value, size_t size) { - set_has_output_type(); - output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type) -} -::std::string* MethodDescriptorProto::mutable_output_type() { - set_has_output_type(); - // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type) - return output_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* MethodDescriptorProto::release_output_type() { - // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.output_type) - clear_has_output_type(); - return output_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) { - if (output_type != NULL) { - set_has_output_type(); - } else { - clear_has_output_type(); - } - output_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), output_type); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type) -} - -// optional .google.protobuf.MethodOptions options = 4; -bool MethodDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000008u) != 0; -} -void MethodDescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000008u; -} -void MethodDescriptorProto::clear_has_options() { - _has_bits_[0] &= ~0x00000008u; -} -void MethodDescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear(); - clear_has_options(); -} -const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const { - const ::google::protobuf::MethodOptions* p = options_; - // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_MethodOptions_default_instance_); -} -::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::MethodOptions; - } - // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options) - return options_; -} -::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() { - // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.options) - clear_has_options(); - ::google::protobuf::MethodOptions* temp = options_; - options_ = NULL; - return temp; -} -void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) { - delete options_; - options_ = options; - if (options) { - set_has_options(); - } else { - clear_has_options(); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.options) -} - -// optional bool client_streaming = 5 [default = false]; -bool MethodDescriptorProto::has_client_streaming() const { - return (_has_bits_[0] & 0x00000010u) != 0; -} -void MethodDescriptorProto::set_has_client_streaming() { - _has_bits_[0] |= 0x00000010u; -} -void MethodDescriptorProto::clear_has_client_streaming() { - _has_bits_[0] &= ~0x00000010u; -} -void MethodDescriptorProto::clear_client_streaming() { - client_streaming_ = false; - clear_has_client_streaming(); -} -bool MethodDescriptorProto::client_streaming() const { - // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.client_streaming) - return client_streaming_; -} -void MethodDescriptorProto::set_client_streaming(bool value) { - set_has_client_streaming(); - client_streaming_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.client_streaming) + name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + input_type_.Swap(&other->input_type_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + output_type_.Swap(&other->output_type_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(MethodDescriptorProto, server_streaming_) + + sizeof(MethodDescriptorProto::server_streaming_) + - PROTOBUF_FIELD_OFFSET(MethodDescriptorProto, options_)>( + reinterpret_cast(&options_), + reinterpret_cast(&other->options_)); } -// optional bool server_streaming = 6 [default = false]; -bool MethodDescriptorProto::has_server_streaming() const { - return (_has_bits_[0] & 0x00000020u) != 0; -} -void MethodDescriptorProto::set_has_server_streaming() { - _has_bits_[0] |= 0x00000020u; -} -void MethodDescriptorProto::clear_has_server_streaming() { - _has_bits_[0] &= ~0x00000020u; -} -void MethodDescriptorProto::clear_server_streaming() { - server_streaming_ = false; - clear_has_server_streaming(); -} -bool MethodDescriptorProto::server_streaming() const { - // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.server_streaming) - return server_streaming_; -} -void MethodDescriptorProto::set_server_streaming(bool value) { - set_has_server_streaming(); - server_streaming_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.server_streaming) +::PROTOBUF_NAMESPACE_ID::Metadata MethodDescriptorProto::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int FileOptions::kJavaPackageFieldNumber; -const int FileOptions::kJavaOuterClassnameFieldNumber; -const int FileOptions::kJavaMultipleFilesFieldNumber; -const int FileOptions::kJavaGenerateEqualsAndHashFieldNumber; -const int FileOptions::kJavaStringCheckUtf8FieldNumber; -const int FileOptions::kOptimizeForFieldNumber; -const int FileOptions::kGoPackageFieldNumber; -const int FileOptions::kCcGenericServicesFieldNumber; -const int FileOptions::kJavaGenericServicesFieldNumber; -const int FileOptions::kPyGenericServicesFieldNumber; -const int FileOptions::kPhpGenericServicesFieldNumber; -const int FileOptions::kDeprecatedFieldNumber; -const int FileOptions::kCcEnableArenasFieldNumber; -const int FileOptions::kObjcClassPrefixFieldNumber; -const int FileOptions::kCsharpNamespaceFieldNumber; -const int FileOptions::kSwiftPrefixFieldNumber; -const int FileOptions::kPhpClassPrefixFieldNumber; -const int FileOptions::kPhpNamespaceFieldNumber; -const int FileOptions::kUninterpretedOptionFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -FileOptions::FileOptions() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class FileOptions::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_java_package(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } - SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.FileOptions) -} -FileOptions::FileOptions(const FileOptions& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0), - uninterpreted_option_(from.uninterpreted_option_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - _extensions_.MergeFrom(from._extensions_); - java_package_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_java_package()) { - java_package_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.java_package_); + static void set_has_java_outer_classname(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_java_multiple_files(HasBits* has_bits) { + (*has_bits)[0] |= 1024u; + } + static void set_has_java_generate_equals_and_hash(HasBits* has_bits) { + (*has_bits)[0] |= 2048u; + } + static void set_has_java_string_check_utf8(HasBits* has_bits) { + (*has_bits)[0] |= 4096u; + } + static void set_has_optimize_for(HasBits* has_bits) { + (*has_bits)[0] |= 262144u; + } + static void set_has_go_package(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static void set_has_cc_generic_services(HasBits* has_bits) { + (*has_bits)[0] |= 8192u; + } + static void set_has_java_generic_services(HasBits* has_bits) { + (*has_bits)[0] |= 16384u; + } + static void set_has_py_generic_services(HasBits* has_bits) { + (*has_bits)[0] |= 32768u; } - java_outer_classname_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_java_outer_classname()) { - java_outer_classname_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.java_outer_classname_); + static void set_has_php_generic_services(HasBits* has_bits) { + (*has_bits)[0] |= 65536u; } - go_package_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_go_package()) { - go_package_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.go_package_); + static void set_has_deprecated(HasBits* has_bits) { + (*has_bits)[0] |= 131072u; } - objc_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_objc_class_prefix()) { - objc_class_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.objc_class_prefix_); + static void set_has_cc_enable_arenas(HasBits* has_bits) { + (*has_bits)[0] |= 524288u; } - csharp_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_csharp_namespace()) { - csharp_namespace_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.csharp_namespace_); + static void set_has_objc_class_prefix(HasBits* has_bits) { + (*has_bits)[0] |= 8u; } - swift_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_swift_prefix()) { - swift_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.swift_prefix_); + static void set_has_csharp_namespace(HasBits* has_bits) { + (*has_bits)[0] |= 16u; } - php_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_php_class_prefix()) { - php_class_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.php_class_prefix_); + static void set_has_swift_prefix(HasBits* has_bits) { + (*has_bits)[0] |= 32u; } - php_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_php_namespace()) { - php_namespace_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.php_namespace_); + static void set_has_php_class_prefix(HasBits* has_bits) { + (*has_bits)[0] |= 64u; + } + static void set_has_php_namespace(HasBits* has_bits) { + (*has_bits)[0] |= 128u; + } + static void set_has_php_metadata_namespace(HasBits* has_bits) { + (*has_bits)[0] |= 256u; + } + static void set_has_ruby_package(HasBits* has_bits) { + (*has_bits)[0] |= 512u; + } +}; + +FileOptions::FileOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + _extensions_(arena), + uninterpreted_option_(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.FileOptions) +} +FileOptions::FileOptions(const FileOptions& from) + : ::PROTOBUF_NAMESPACE_ID::Message(), + _has_bits_(from._has_bits_), + uninterpreted_option_(from.uninterpreted_option_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _extensions_.MergeFrom(from._extensions_); + java_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_java_package()) { + java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_java_package(), + GetArena()); + } + java_outer_classname_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_java_outer_classname()) { + java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_java_outer_classname(), + GetArena()); + } + go_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_go_package()) { + go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_go_package(), + GetArena()); + } + objc_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_objc_class_prefix()) { + objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_objc_class_prefix(), + GetArena()); + } + csharp_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_csharp_namespace()) { + csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_csharp_namespace(), + GetArena()); + } + swift_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_swift_prefix()) { + swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_swift_prefix(), + GetArena()); + } + php_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_php_class_prefix()) { + php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_php_class_prefix(), + GetArena()); + } + php_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_php_namespace()) { + php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_php_namespace(), + GetArena()); + } + php_metadata_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_php_metadata_namespace()) { + php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_php_metadata_namespace(), + GetArena()); + } + ruby_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_ruby_package()) { + ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_ruby_package(), + GetArena()); } ::memcpy(&java_multiple_files_, &from.java_multiple_files_, - static_cast(reinterpret_cast(&optimize_for_) - - reinterpret_cast(&java_multiple_files_)) + sizeof(optimize_for_)); + static_cast(reinterpret_cast(&cc_enable_arenas_) - + reinterpret_cast(&java_multiple_files_)) + sizeof(cc_enable_arenas_)); // @@protoc_insertion_point(copy_constructor:google.protobuf.FileOptions) } void FileOptions::SharedCtor() { - _cached_size_ = 0; - java_package_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - java_outer_classname_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - go_package_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - objc_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - csharp_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - swift_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - php_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - php_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - ::memset(&java_multiple_files_, 0, static_cast( - reinterpret_cast(&cc_enable_arenas_) - - reinterpret_cast(&java_multiple_files_)) + sizeof(cc_enable_arenas_)); - optimize_for_ = 1; +java_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +java_outer_classname_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +go_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +objc_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +csharp_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +swift_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +php_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +php_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +php_metadata_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +ruby_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&java_multiple_files_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&deprecated_) - + reinterpret_cast(&java_multiple_files_)) + sizeof(deprecated_)); +optimize_for_ = 1; +cc_enable_arenas_ = true; } FileOptions::~FileOptions() { // @@protoc_insertion_point(destructor:google.protobuf.FileOptions) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void FileOptions::SharedDtor() { - java_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - java_outer_classname_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - go_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - objc_class_prefix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - csharp_namespace_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - swift_prefix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - php_class_prefix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - php_namespace_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + java_package_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + java_outer_classname_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + go_package_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + objc_class_prefix_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + csharp_namespace_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + swift_prefix_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + php_class_prefix_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + php_namespace_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + php_metadata_namespace_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + ruby_package_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } -void FileOptions::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* FileOptions::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void FileOptions::ArenaDtor(void* object) { + FileOptions* _this = reinterpret_cast< FileOptions* >(object); + (void)_this; } - -const FileOptions& FileOptions::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void FileOptions::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -FileOptions* FileOptions::New(::google::protobuf::Arena* arena) const { - FileOptions* n = new FileOptions; - if (arena != NULL) { - arena->Own(n); - } - return n; +void FileOptions::SetCachedSize(int size) const { + _cached_size_.Set(size); } void FileOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FileOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; _extensions_.Clear(); uninterpreted_option_.Clear(); cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 255u) { + if (cached_has_bits & 0x000000ffu) { if (cached_has_bits & 0x00000001u) { - GOOGLE_DCHECK(!java_package_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*java_package_.UnsafeRawStringPointer())->clear(); + java_package_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000002u) { - GOOGLE_DCHECK(!java_outer_classname_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*java_outer_classname_.UnsafeRawStringPointer())->clear(); + java_outer_classname_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000004u) { - GOOGLE_DCHECK(!go_package_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*go_package_.UnsafeRawStringPointer())->clear(); + go_package_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000008u) { - GOOGLE_DCHECK(!objc_class_prefix_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*objc_class_prefix_.UnsafeRawStringPointer())->clear(); + objc_class_prefix_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000010u) { - GOOGLE_DCHECK(!csharp_namespace_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*csharp_namespace_.UnsafeRawStringPointer())->clear(); + csharp_namespace_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000020u) { - GOOGLE_DCHECK(!swift_prefix_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*swift_prefix_.UnsafeRawStringPointer())->clear(); + swift_prefix_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000040u) { - GOOGLE_DCHECK(!php_class_prefix_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*php_class_prefix_.UnsafeRawStringPointer())->clear(); + php_class_prefix_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000080u) { - GOOGLE_DCHECK(!php_namespace_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*php_namespace_.UnsafeRawStringPointer())->clear(); + php_namespace_.ClearNonDefaultToEmpty(); + } + } + if (cached_has_bits & 0x00000300u) { + if (cached_has_bits & 0x00000100u) { + php_metadata_namespace_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000200u) { + ruby_package_.ClearNonDefaultToEmpty(); } } - if (cached_has_bits & 65280u) { + if (cached_has_bits & 0x0000fc00u) { ::memset(&java_multiple_files_, 0, static_cast( - reinterpret_cast(&deprecated_) - - reinterpret_cast(&java_multiple_files_)) + sizeof(deprecated_)); + reinterpret_cast(&py_generic_services_) - + reinterpret_cast(&java_multiple_files_)) + sizeof(py_generic_services_)); } - if (cached_has_bits & 196608u) { - cc_enable_arenas_ = false; + if (cached_has_bits & 0x000f0000u) { + ::memset(&php_generic_services_, 0, static_cast( + reinterpret_cast(&deprecated_) - + reinterpret_cast(&php_generic_services_)) + sizeof(deprecated_)); optimize_for_ = 1; + cc_enable_arenas_ = true; } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool FileOptions::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.FileOptions) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(16383u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional string java_package = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_java_package())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->java_package().data(), static_cast(this->java_package().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FileOptions.java_package"); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* FileOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional string java_package = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_java_package(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FileOptions.java_package"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string java_outer_classname = 8; - case 8: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(66u /* 66 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_java_outer_classname())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->java_outer_classname().data(), static_cast(this->java_outer_classname().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FileOptions.java_outer_classname"); - } else { - goto handle_unusual; - } - break; - } - + case 8: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 66)) { + auto str = _internal_mutable_java_outer_classname(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FileOptions.java_outer_classname"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; - case 9: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(72u /* 72 & 0xFF */)) { - int value; - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( - input, &value))); - if (::google::protobuf::FileOptions_OptimizeMode_IsValid(value)) { - set_optimize_for(static_cast< ::google::protobuf::FileOptions_OptimizeMode >(value)); + case 9: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 72)) { + ::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + if (PROTOBUF_PREDICT_TRUE(PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode_IsValid(val))) { + _internal_set_optimize_for(static_cast(val)); } else { - mutable_unknown_fields()->AddVarint( - 9, static_cast< ::google::protobuf::uint64>(value)); + ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(9, val, mutable_unknown_fields()); } - } else { - goto handle_unusual; - } - break; - } - + } else goto handle_unusual; + continue; // optional bool java_multiple_files = 10 [default = false]; - case 10: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(80u /* 80 & 0xFF */)) { - set_has_java_multiple_files(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &java_multiple_files_))); - } else { - goto handle_unusual; - } - break; - } - + case 10: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 80)) { + _Internal::set_has_java_multiple_files(&has_bits); + java_multiple_files_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string go_package = 11; - case 11: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(90u /* 90 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_go_package())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->go_package().data(), static_cast(this->go_package().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FileOptions.go_package"); - } else { - goto handle_unusual; - } - break; - } - + case 11: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 90)) { + auto str = _internal_mutable_go_package(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FileOptions.go_package"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional bool cc_generic_services = 16 [default = false]; - case 16: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(128u /* 128 & 0xFF */)) { - set_has_cc_generic_services(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &cc_generic_services_))); - } else { - goto handle_unusual; - } - break; - } - + case 16: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 128)) { + _Internal::set_has_cc_generic_services(&has_bits); + cc_generic_services_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional bool java_generic_services = 17 [default = false]; - case 17: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(136u /* 136 & 0xFF */)) { - set_has_java_generic_services(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &java_generic_services_))); - } else { - goto handle_unusual; - } - break; - } - + case 17: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 136)) { + _Internal::set_has_java_generic_services(&has_bits); + java_generic_services_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional bool py_generic_services = 18 [default = false]; - case 18: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(144u /* 144 & 0xFF */)) { - set_has_py_generic_services(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &py_generic_services_))); - } else { - goto handle_unusual; - } - break; - } - - // optional bool php_generic_services = 19 [default = false]; - case 19: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(152u /* 152 & 0xFF */)) { - set_has_php_generic_services(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &php_generic_services_))); - } else { - goto handle_unusual; - } - break; - } - + case 18: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 144)) { + _Internal::set_has_py_generic_services(&has_bits); + py_generic_services_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional bool java_generate_equals_and_hash = 20 [deprecated = true]; - case 20: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(160u /* 160 & 0xFF */)) { - set_has_java_generate_equals_and_hash(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &java_generate_equals_and_hash_))); - } else { - goto handle_unusual; - } - break; - } - + case 20: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 160)) { + _Internal::set_has_java_generate_equals_and_hash(&has_bits); + java_generate_equals_and_hash_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional bool deprecated = 23 [default = false]; - case 23: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(184u /* 184 & 0xFF */)) { - set_has_deprecated(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &deprecated_))); - } else { - goto handle_unusual; - } - break; - } - + case 23: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 184)) { + _Internal::set_has_deprecated(&has_bits); + deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional bool java_string_check_utf8 = 27 [default = false]; - case 27: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(216u /* 216 & 0xFF */)) { - set_has_java_string_check_utf8(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &java_string_check_utf8_))); - } else { - goto handle_unusual; - } - break; - } - - // optional bool cc_enable_arenas = 31 [default = false]; - case 31: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(248u /* 248 & 0xFF */)) { - set_has_cc_enable_arenas(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &cc_enable_arenas_))); - } else { - goto handle_unusual; - } - break; - } - + case 27: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 216)) { + _Internal::set_has_java_string_check_utf8(&has_bits); + java_string_check_utf8_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // optional bool cc_enable_arenas = 31 [default = true]; + case 31: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 248)) { + _Internal::set_has_cc_enable_arenas(&has_bits); + cc_enable_arenas_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string objc_class_prefix = 36; - case 36: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(34u /* 290 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_objc_class_prefix())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->objc_class_prefix().data(), static_cast(this->objc_class_prefix().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FileOptions.objc_class_prefix"); - } else { - goto handle_unusual; - } - break; - } - + case 36: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + auto str = _internal_mutable_objc_class_prefix(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FileOptions.objc_class_prefix"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string csharp_namespace = 37; - case 37: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(42u /* 298 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_csharp_namespace())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->csharp_namespace().data(), static_cast(this->csharp_namespace().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FileOptions.csharp_namespace"); - } else { - goto handle_unusual; - } - break; - } - + case 37: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 42)) { + auto str = _internal_mutable_csharp_namespace(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FileOptions.csharp_namespace"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string swift_prefix = 39; - case 39: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(58u /* 314 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_swift_prefix())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->swift_prefix().data(), static_cast(this->swift_prefix().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FileOptions.swift_prefix"); - } else { - goto handle_unusual; - } - break; - } - + case 39: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 58)) { + auto str = _internal_mutable_swift_prefix(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FileOptions.swift_prefix"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string php_class_prefix = 40; - case 40: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(66u /* 322 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_php_class_prefix())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->php_class_prefix().data(), static_cast(this->php_class_prefix().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FileOptions.php_class_prefix"); - } else { - goto handle_unusual; - } - break; - } - + case 40: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 66)) { + auto str = _internal_mutable_php_class_prefix(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FileOptions.php_class_prefix"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string php_namespace = 41; - case 41: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(74u /* 330 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_php_namespace())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->php_namespace().data(), static_cast(this->php_namespace().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FileOptions.php_namespace"); - } else { - goto handle_unusual; - } - break; - } - + case 41: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 74)) { + auto str = _internal_mutable_php_namespace(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FileOptions.php_namespace"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; + // optional bool php_generic_services = 42 [default = false]; + case 42: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 80)) { + _Internal::set_has_php_generic_services(&has_bits); + php_generic_services_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // optional string php_metadata_namespace = 44; + case 44: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 98)) { + auto str = _internal_mutable_php_metadata_namespace(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FileOptions.php_metadata_namespace"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; + // optional string ruby_package = 45; + case 45: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 106)) { + auto str = _internal_mutable_ruby_package(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FileOptions.ruby_package"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - case 999: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_uninterpreted_option())); - } else { - goto handle_unusual; - } - break; - } - + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - if ((8000u <= tag)) { - DO_(_extensions_.ParseField(tag, input, - internal_default_instance(), - _internal_metadata_.mutable_unknown_fields())); - continue; - } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + if ((8000u <= tag)) { + ptr = _extensions_.ParseField(tag, ptr, + internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.FileOptions) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.FileOptions) - return false; -#undef DO_ + ptr = nullptr; + goto success; +#undef CHK_ } -void FileOptions::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.FileOptions) - ::google::protobuf::uint32 cached_has_bits = 0; +::PROTOBUF_NAMESPACE_ID::uint8* FileOptions::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileOptions) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional string java_package = 1; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->java_package().data(), static_cast(this->java_package().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_java_package().data(), static_cast(this->_internal_java_package().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FileOptions.java_package"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->java_package(), output); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_java_package(), target); } // optional string java_outer_classname = 8; if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->java_outer_classname().data(), static_cast(this->java_outer_classname().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_java_outer_classname().data(), static_cast(this->_internal_java_outer_classname().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FileOptions.java_outer_classname"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 8, this->java_outer_classname(), output); + target = stream->WriteStringMaybeAliased( + 8, this->_internal_java_outer_classname(), target); } // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; - if (cached_has_bits & 0x00020000u) { - ::google::protobuf::internal::WireFormatLite::WriteEnum( - 9, this->optimize_for(), output); + if (cached_has_bits & 0x00040000u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray( + 9, this->_internal_optimize_for(), target); } // optional bool java_multiple_files = 10 [default = false]; - if (cached_has_bits & 0x00000100u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->java_multiple_files(), output); + if (cached_has_bits & 0x00000400u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(10, this->_internal_java_multiple_files(), target); } // optional string go_package = 11; if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->go_package().data(), static_cast(this->go_package().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_go_package().data(), static_cast(this->_internal_go_package().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FileOptions.go_package"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 11, this->go_package(), output); + target = stream->WriteStringMaybeAliased( + 11, this->_internal_go_package(), target); } // optional bool cc_generic_services = 16 [default = false]; - if (cached_has_bits & 0x00000800u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(16, this->cc_generic_services(), output); + if (cached_has_bits & 0x00002000u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(16, this->_internal_cc_generic_services(), target); } // optional bool java_generic_services = 17 [default = false]; - if (cached_has_bits & 0x00001000u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(17, this->java_generic_services(), output); + if (cached_has_bits & 0x00004000u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(17, this->_internal_java_generic_services(), target); } // optional bool py_generic_services = 18 [default = false]; - if (cached_has_bits & 0x00002000u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(18, this->py_generic_services(), output); - } - - // optional bool php_generic_services = 19 [default = false]; - if (cached_has_bits & 0x00004000u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(19, this->php_generic_services(), output); + if (cached_has_bits & 0x00008000u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(18, this->_internal_py_generic_services(), target); } // optional bool java_generate_equals_and_hash = 20 [deprecated = true]; - if (cached_has_bits & 0x00000200u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(20, this->java_generate_equals_and_hash(), output); + if (cached_has_bits & 0x00000800u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(20, this->_internal_java_generate_equals_and_hash(), target); } // optional bool deprecated = 23 [default = false]; - if (cached_has_bits & 0x00008000u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(23, this->deprecated(), output); + if (cached_has_bits & 0x00020000u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(23, this->_internal_deprecated(), target); } // optional bool java_string_check_utf8 = 27 [default = false]; - if (cached_has_bits & 0x00000400u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(27, this->java_string_check_utf8(), output); + if (cached_has_bits & 0x00001000u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(27, this->_internal_java_string_check_utf8(), target); } - // optional bool cc_enable_arenas = 31 [default = false]; - if (cached_has_bits & 0x00010000u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(31, this->cc_enable_arenas(), output); + // optional bool cc_enable_arenas = 31 [default = true]; + if (cached_has_bits & 0x00080000u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(31, this->_internal_cc_enable_arenas(), target); } // optional string objc_class_prefix = 36; if (cached_has_bits & 0x00000008u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->objc_class_prefix().data(), static_cast(this->objc_class_prefix().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_objc_class_prefix().data(), static_cast(this->_internal_objc_class_prefix().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FileOptions.objc_class_prefix"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 36, this->objc_class_prefix(), output); + target = stream->WriteStringMaybeAliased( + 36, this->_internal_objc_class_prefix(), target); } // optional string csharp_namespace = 37; if (cached_has_bits & 0x00000010u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->csharp_namespace().data(), static_cast(this->csharp_namespace().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_csharp_namespace().data(), static_cast(this->_internal_csharp_namespace().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FileOptions.csharp_namespace"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 37, this->csharp_namespace(), output); + target = stream->WriteStringMaybeAliased( + 37, this->_internal_csharp_namespace(), target); } // optional string swift_prefix = 39; if (cached_has_bits & 0x00000020u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->swift_prefix().data(), static_cast(this->swift_prefix().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_swift_prefix().data(), static_cast(this->_internal_swift_prefix().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FileOptions.swift_prefix"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 39, this->swift_prefix(), output); + target = stream->WriteStringMaybeAliased( + 39, this->_internal_swift_prefix(), target); } // optional string php_class_prefix = 40; if (cached_has_bits & 0x00000040u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->php_class_prefix().data(), static_cast(this->php_class_prefix().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_php_class_prefix().data(), static_cast(this->_internal_php_class_prefix().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FileOptions.php_class_prefix"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 40, this->php_class_prefix(), output); + target = stream->WriteStringMaybeAliased( + 40, this->_internal_php_class_prefix(), target); } // optional string php_namespace = 41; if (cached_has_bits & 0x00000080u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->php_namespace().data(), static_cast(this->php_namespace().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_php_namespace().data(), static_cast(this->_internal_php_namespace().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.FileOptions.php_namespace"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 41, this->php_namespace(), output); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 999, this->uninterpreted_option(static_cast(i)), output); - } - - // Extension range [1000, 536870912) - _extensions_.SerializeWithCachedSizes( - 1000, 536870912, output); - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.FileOptions) -} - -::google::protobuf::uint8* FileOptions::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileOptions) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional string java_package = 1; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->java_package().data(), static_cast(this->java_package().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.java_package"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->java_package(), target); - } - - // optional string java_outer_classname = 8; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->java_outer_classname().data(), static_cast(this->java_outer_classname().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.java_outer_classname"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 8, this->java_outer_classname(), target); + target = stream->WriteStringMaybeAliased( + 41, this->_internal_php_namespace(), target); } - // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; - if (cached_has_bits & 0x00020000u) { - target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( - 9, this->optimize_for(), target); + // optional bool php_generic_services = 42 [default = false]; + if (cached_has_bits & 0x00010000u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(42, this->_internal_php_generic_services(), target); } - // optional bool java_multiple_files = 10 [default = false]; + // optional string php_metadata_namespace = 44; if (cached_has_bits & 0x00000100u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->java_multiple_files(), target); - } - - // optional string go_package = 11; - if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->go_package().data(), static_cast(this->go_package().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.go_package"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 11, this->go_package(), target); - } - - // optional bool cc_generic_services = 16 [default = false]; - if (cached_has_bits & 0x00000800u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(16, this->cc_generic_services(), target); - } - - // optional bool java_generic_services = 17 [default = false]; - if (cached_has_bits & 0x00001000u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(17, this->java_generic_services(), target); - } - - // optional bool py_generic_services = 18 [default = false]; - if (cached_has_bits & 0x00002000u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(18, this->py_generic_services(), target); - } - - // optional bool php_generic_services = 19 [default = false]; - if (cached_has_bits & 0x00004000u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(19, this->php_generic_services(), target); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_php_metadata_namespace().data(), static_cast(this->_internal_php_metadata_namespace().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.php_metadata_namespace"); + target = stream->WriteStringMaybeAliased( + 44, this->_internal_php_metadata_namespace(), target); } - // optional bool java_generate_equals_and_hash = 20 [deprecated = true]; + // optional string ruby_package = 45; if (cached_has_bits & 0x00000200u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(20, this->java_generate_equals_and_hash(), target); - } - - // optional bool deprecated = 23 [default = false]; - if (cached_has_bits & 0x00008000u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(23, this->deprecated(), target); - } - - // optional bool java_string_check_utf8 = 27 [default = false]; - if (cached_has_bits & 0x00000400u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(27, this->java_string_check_utf8(), target); - } - - // optional bool cc_enable_arenas = 31 [default = false]; - if (cached_has_bits & 0x00010000u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(31, this->cc_enable_arenas(), target); - } - - // optional string objc_class_prefix = 36; - if (cached_has_bits & 0x00000008u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->objc_class_prefix().data(), static_cast(this->objc_class_prefix().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.objc_class_prefix"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 36, this->objc_class_prefix(), target); - } - - // optional string csharp_namespace = 37; - if (cached_has_bits & 0x00000010u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->csharp_namespace().data(), static_cast(this->csharp_namespace().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.csharp_namespace"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 37, this->csharp_namespace(), target); - } - - // optional string swift_prefix = 39; - if (cached_has_bits & 0x00000020u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->swift_prefix().data(), static_cast(this->swift_prefix().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.swift_prefix"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 39, this->swift_prefix(), target); - } - - // optional string php_class_prefix = 40; - if (cached_has_bits & 0x00000040u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->php_class_prefix().data(), static_cast(this->php_class_prefix().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.php_class_prefix"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 40, this->php_class_prefix(), target); - } - - // optional string php_namespace = 41; - if (cached_has_bits & 0x00000080u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->php_namespace().data(), static_cast(this->php_namespace().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.php_namespace"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 41, this->php_namespace(), target); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_ruby_package().data(), static_cast(this->_internal_ruby_package().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.ruby_package"); + target = stream->WriteStringMaybeAliased( + 45, this->_internal_ruby_package(), target); } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 999, this->uninterpreted_option(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_uninterpreted_option_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, this->_internal_uninterpreted_option(i), target, stream); } // Extension range [1000, 536870912) - target = _extensions_.InternalSerializeWithCachedSizesToArray( - 1000, 536870912, deterministic, target); + target = _extensions_._InternalSerialize( + 1000, 536870912, target, stream); - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileOptions) return target; @@ -9639,151 +6620,163 @@ size_t FileOptions::ByteSizeLong() const { total_size += _extensions_.ByteSize(); - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - unsigned int count = static_cast(this->uninterpreted_option_size()); - total_size += 2UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->uninterpreted_option(static_cast(i))); - } + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - if (_has_bits_[0 / 32] & 255u) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x000000ffu) { // optional string java_package = 1; - if (has_java_package()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->java_package()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_java_package()); } // optional string java_outer_classname = 8; - if (has_java_outer_classname()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->java_outer_classname()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_java_outer_classname()); } // optional string go_package = 11; - if (has_go_package()) { + if (cached_has_bits & 0x00000004u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->go_package()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_go_package()); } // optional string objc_class_prefix = 36; - if (has_objc_class_prefix()) { + if (cached_has_bits & 0x00000008u) { total_size += 2 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->objc_class_prefix()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_objc_class_prefix()); } // optional string csharp_namespace = 37; - if (has_csharp_namespace()) { + if (cached_has_bits & 0x00000010u) { total_size += 2 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->csharp_namespace()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_csharp_namespace()); } // optional string swift_prefix = 39; - if (has_swift_prefix()) { + if (cached_has_bits & 0x00000020u) { total_size += 2 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->swift_prefix()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_swift_prefix()); } // optional string php_class_prefix = 40; - if (has_php_class_prefix()) { + if (cached_has_bits & 0x00000040u) { total_size += 2 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->php_class_prefix()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_php_class_prefix()); } // optional string php_namespace = 41; - if (has_php_namespace()) { + if (cached_has_bits & 0x00000080u) { total_size += 2 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->php_namespace()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_php_namespace()); } } - if (_has_bits_[8 / 32] & 65280u) { + if (cached_has_bits & 0x0000ff00u) { + // optional string php_metadata_namespace = 44; + if (cached_has_bits & 0x00000100u) { + total_size += 2 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_php_metadata_namespace()); + } + + // optional string ruby_package = 45; + if (cached_has_bits & 0x00000200u) { + total_size += 2 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_ruby_package()); + } + // optional bool java_multiple_files = 10 [default = false]; - if (has_java_multiple_files()) { + if (cached_has_bits & 0x00000400u) { total_size += 1 + 1; } // optional bool java_generate_equals_and_hash = 20 [deprecated = true]; - if (has_java_generate_equals_and_hash()) { + if (cached_has_bits & 0x00000800u) { total_size += 2 + 1; } // optional bool java_string_check_utf8 = 27 [default = false]; - if (has_java_string_check_utf8()) { + if (cached_has_bits & 0x00001000u) { total_size += 2 + 1; } // optional bool cc_generic_services = 16 [default = false]; - if (has_cc_generic_services()) { + if (cached_has_bits & 0x00002000u) { total_size += 2 + 1; } // optional bool java_generic_services = 17 [default = false]; - if (has_java_generic_services()) { + if (cached_has_bits & 0x00004000u) { total_size += 2 + 1; } // optional bool py_generic_services = 18 [default = false]; - if (has_py_generic_services()) { + if (cached_has_bits & 0x00008000u) { total_size += 2 + 1; } - // optional bool php_generic_services = 19 [default = false]; - if (has_php_generic_services()) { + } + if (cached_has_bits & 0x000f0000u) { + // optional bool php_generic_services = 42 [default = false]; + if (cached_has_bits & 0x00010000u) { total_size += 2 + 1; } // optional bool deprecated = 23 [default = false]; - if (has_deprecated()) { - total_size += 2 + 1; - } - - } - if (_has_bits_[16 / 32] & 196608u) { - // optional bool cc_enable_arenas = 31 [default = false]; - if (has_cc_enable_arenas()) { + if (cached_has_bits & 0x00020000u) { total_size += 2 + 1; } // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; - if (has_optimize_for()) { + if (cached_has_bits & 0x00040000u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::EnumSize(this->optimize_for()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_optimize_for()); + } + + // optional bool cc_enable_arenas = 31 [default = true]; + if (cached_has_bits & 0x00080000u) { + total_size += 2 + 1; } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void FileOptions::MergeFrom(const ::google::protobuf::Message& from) { +void FileOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileOptions) GOOGLE_DCHECK_NE(&from, this); const FileOptions* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FileOptions) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FileOptions) MergeFrom(*source); @@ -9794,85 +6787,83 @@ void FileOptions::MergeFrom(const FileOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileOptions) GOOGLE_DCHECK_NE(&from, this); _extensions_.MergeFrom(from._extensions_); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; uninterpreted_option_.MergeFrom(from.uninterpreted_option_); cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 255u) { + if (cached_has_bits & 0x000000ffu) { if (cached_has_bits & 0x00000001u) { - set_has_java_package(); - java_package_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.java_package_); + _internal_set_java_package(from._internal_java_package()); } if (cached_has_bits & 0x00000002u) { - set_has_java_outer_classname(); - java_outer_classname_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.java_outer_classname_); + _internal_set_java_outer_classname(from._internal_java_outer_classname()); } if (cached_has_bits & 0x00000004u) { - set_has_go_package(); - go_package_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.go_package_); + _internal_set_go_package(from._internal_go_package()); } if (cached_has_bits & 0x00000008u) { - set_has_objc_class_prefix(); - objc_class_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.objc_class_prefix_); + _internal_set_objc_class_prefix(from._internal_objc_class_prefix()); } if (cached_has_bits & 0x00000010u) { - set_has_csharp_namespace(); - csharp_namespace_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.csharp_namespace_); + _internal_set_csharp_namespace(from._internal_csharp_namespace()); } if (cached_has_bits & 0x00000020u) { - set_has_swift_prefix(); - swift_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.swift_prefix_); + _internal_set_swift_prefix(from._internal_swift_prefix()); } if (cached_has_bits & 0x00000040u) { - set_has_php_class_prefix(); - php_class_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.php_class_prefix_); + _internal_set_php_class_prefix(from._internal_php_class_prefix()); } if (cached_has_bits & 0x00000080u) { - set_has_php_namespace(); - php_namespace_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.php_namespace_); + _internal_set_php_namespace(from._internal_php_namespace()); } } - if (cached_has_bits & 65280u) { + if (cached_has_bits & 0x0000ff00u) { if (cached_has_bits & 0x00000100u) { - java_multiple_files_ = from.java_multiple_files_; + _internal_set_php_metadata_namespace(from._internal_php_metadata_namespace()); } if (cached_has_bits & 0x00000200u) { - java_generate_equals_and_hash_ = from.java_generate_equals_and_hash_; + _internal_set_ruby_package(from._internal_ruby_package()); } if (cached_has_bits & 0x00000400u) { - java_string_check_utf8_ = from.java_string_check_utf8_; + java_multiple_files_ = from.java_multiple_files_; } if (cached_has_bits & 0x00000800u) { - cc_generic_services_ = from.cc_generic_services_; + java_generate_equals_and_hash_ = from.java_generate_equals_and_hash_; } if (cached_has_bits & 0x00001000u) { - java_generic_services_ = from.java_generic_services_; + java_string_check_utf8_ = from.java_string_check_utf8_; } if (cached_has_bits & 0x00002000u) { - py_generic_services_ = from.py_generic_services_; + cc_generic_services_ = from.cc_generic_services_; } if (cached_has_bits & 0x00004000u) { - php_generic_services_ = from.php_generic_services_; + java_generic_services_ = from.java_generic_services_; } if (cached_has_bits & 0x00008000u) { - deprecated_ = from.deprecated_; + py_generic_services_ = from.py_generic_services_; } _has_bits_[0] |= cached_has_bits; } - if (cached_has_bits & 196608u) { + if (cached_has_bits & 0x000f0000u) { if (cached_has_bits & 0x00010000u) { - cc_enable_arenas_ = from.cc_enable_arenas_; + php_generic_services_ = from.php_generic_services_; } if (cached_has_bits & 0x00020000u) { + deprecated_ = from.deprecated_; + } + if (cached_has_bits & 0x00040000u) { optimize_for_ = from.optimize_for_; } + if (cached_has_bits & 0x00080000u) { + cc_enable_arenas_ = from.cc_enable_arenas_; + } _has_bits_[0] |= cached_has_bits; } } -void FileOptions::CopyFrom(const ::google::protobuf::Message& from) { +void FileOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FileOptions) if (&from == this) return; Clear(); @@ -9891,1106 +6882,249 @@ bool FileOptions::IsInitialized() const { return false; } - if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(uninterpreted_option_)) return false; return true; } -void FileOptions::Swap(FileOptions* other) { - if (other == this) return; - InternalSwap(other); -} void FileOptions::InternalSwap(FileOptions* other) { using std::swap; + _extensions_.Swap(&other->_extensions_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); - java_package_.Swap(&other->java_package_); - java_outer_classname_.Swap(&other->java_outer_classname_); - go_package_.Swap(&other->go_package_); - objc_class_prefix_.Swap(&other->objc_class_prefix_); - csharp_namespace_.Swap(&other->csharp_namespace_); - swift_prefix_.Swap(&other->swift_prefix_); - php_class_prefix_.Swap(&other->php_class_prefix_); - php_namespace_.Swap(&other->php_namespace_); - swap(java_multiple_files_, other->java_multiple_files_); - swap(java_generate_equals_and_hash_, other->java_generate_equals_and_hash_); - swap(java_string_check_utf8_, other->java_string_check_utf8_); - swap(cc_generic_services_, other->cc_generic_services_); - swap(java_generic_services_, other->java_generic_services_); - swap(py_generic_services_, other->py_generic_services_); - swap(php_generic_services_, other->php_generic_services_); - swap(deprecated_, other->deprecated_); - swap(cc_enable_arenas_, other->cc_enable_arenas_); + java_package_.Swap(&other->java_package_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + java_outer_classname_.Swap(&other->java_outer_classname_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + go_package_.Swap(&other->go_package_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + objc_class_prefix_.Swap(&other->objc_class_prefix_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + csharp_namespace_.Swap(&other->csharp_namespace_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + swift_prefix_.Swap(&other->swift_prefix_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + php_class_prefix_.Swap(&other->php_class_prefix_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + php_namespace_.Swap(&other->php_namespace_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + php_metadata_namespace_.Swap(&other->php_metadata_namespace_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ruby_package_.Swap(&other->ruby_package_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(FileOptions, deprecated_) + + sizeof(FileOptions::deprecated_) + - PROTOBUF_FIELD_OFFSET(FileOptions, java_multiple_files_)>( + reinterpret_cast(&java_multiple_files_), + reinterpret_cast(&other->java_multiple_files_)); swap(optimize_for_, other->optimize_for_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); - _extensions_.Swap(&other->_extensions_); + swap(cc_enable_arenas_, other->cc_enable_arenas_); } -::google::protobuf::Metadata FileOptions::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; +::PROTOBUF_NAMESPACE_ID::Metadata FileOptions::GetMetadata() const { + return GetMetadataStatic(); } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// FileOptions -// optional string java_package = 1; -bool FileOptions::has_java_package() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void FileOptions::set_has_java_package() { - _has_bits_[0] |= 0x00000001u; -} -void FileOptions::clear_has_java_package() { - _has_bits_[0] &= ~0x00000001u; -} -void FileOptions::clear_java_package() { - java_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_java_package(); -} -const ::std::string& FileOptions::java_package() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_package) - return java_package_.GetNoArena(); -} -void FileOptions::set_java_package(const ::std::string& value) { - set_has_java_package(); - java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_package) -} -#if LANG_CXX11 -void FileOptions::set_java_package(::std::string&& value) { - set_has_java_package(); - java_package_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.java_package) -} -#endif -void FileOptions::set_java_package(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_java_package(); - java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package) -} -void FileOptions::set_java_package(const char* value, size_t size) { - set_has_java_package(); - java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package) -} -::std::string* FileOptions::mutable_java_package() { - set_has_java_package(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package) - return java_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FileOptions::release_java_package() { - // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_package) - clear_has_java_package(); - return java_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FileOptions::set_allocated_java_package(::std::string* java_package) { - if (java_package != NULL) { - set_has_java_package(); - } else { - clear_has_java_package(); - } - java_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_package); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package) -} - -// optional string java_outer_classname = 8; -bool FileOptions::has_java_outer_classname() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void FileOptions::set_has_java_outer_classname() { - _has_bits_[0] |= 0x00000002u; -} -void FileOptions::clear_has_java_outer_classname() { - _has_bits_[0] &= ~0x00000002u; -} -void FileOptions::clear_java_outer_classname() { - java_outer_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_java_outer_classname(); -} -const ::std::string& FileOptions::java_outer_classname() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_outer_classname) - return java_outer_classname_.GetNoArena(); -} -void FileOptions::set_java_outer_classname(const ::std::string& value) { - set_has_java_outer_classname(); - java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_outer_classname) -} -#if LANG_CXX11 -void FileOptions::set_java_outer_classname(::std::string&& value) { - set_has_java_outer_classname(); - java_outer_classname_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.java_outer_classname) -} -#endif -void FileOptions::set_java_outer_classname(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_java_outer_classname(); - java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_outer_classname) -} -void FileOptions::set_java_outer_classname(const char* value, size_t size) { - set_has_java_outer_classname(); - java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname) -} -::std::string* FileOptions::mutable_java_outer_classname() { - set_has_java_outer_classname(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname) - return java_outer_classname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FileOptions::release_java_outer_classname() { - // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_outer_classname) - clear_has_java_outer_classname(); - return java_outer_classname_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) { - if (java_outer_classname != NULL) { - set_has_java_outer_classname(); - } else { - clear_has_java_outer_classname(); +// =================================================================== + +class MessageOptions::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_message_set_wire_format(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } - java_outer_classname_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_outer_classname); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname) -} + static void set_has_no_standard_descriptor_accessor(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_deprecated(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static void set_has_map_entry(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } +}; -// optional bool java_multiple_files = 10 [default = false]; -bool FileOptions::has_java_multiple_files() const { - return (_has_bits_[0] & 0x00000100u) != 0; -} -void FileOptions::set_has_java_multiple_files() { - _has_bits_[0] |= 0x00000100u; -} -void FileOptions::clear_has_java_multiple_files() { - _has_bits_[0] &= ~0x00000100u; +MessageOptions::MessageOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + _extensions_(arena), + uninterpreted_option_(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.MessageOptions) } -void FileOptions::clear_java_multiple_files() { - java_multiple_files_ = false; - clear_has_java_multiple_files(); +MessageOptions::MessageOptions(const MessageOptions& from) + : ::PROTOBUF_NAMESPACE_ID::Message(), + _has_bits_(from._has_bits_), + uninterpreted_option_(from.uninterpreted_option_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _extensions_.MergeFrom(from._extensions_); + ::memcpy(&message_set_wire_format_, &from.message_set_wire_format_, + static_cast(reinterpret_cast(&map_entry_) - + reinterpret_cast(&message_set_wire_format_)) + sizeof(map_entry_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.MessageOptions) } -bool FileOptions::java_multiple_files() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_multiple_files) - return java_multiple_files_; + +void MessageOptions::SharedCtor() { +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&message_set_wire_format_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&map_entry_) - + reinterpret_cast(&message_set_wire_format_)) + sizeof(map_entry_)); } -void FileOptions::set_java_multiple_files(bool value) { - set_has_java_multiple_files(); - java_multiple_files_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_multiple_files) + +MessageOptions::~MessageOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.MessageOptions) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } -// optional bool java_generate_equals_and_hash = 20 [deprecated = true]; -bool FileOptions::has_java_generate_equals_and_hash() const { - return (_has_bits_[0] & 0x00000200u) != 0; +void MessageOptions::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); } -void FileOptions::set_has_java_generate_equals_and_hash() { - _has_bits_[0] |= 0x00000200u; + +void MessageOptions::ArenaDtor(void* object) { + MessageOptions* _this = reinterpret_cast< MessageOptions* >(object); + (void)_this; } -void FileOptions::clear_has_java_generate_equals_and_hash() { - _has_bits_[0] &= ~0x00000200u; +void MessageOptions::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } -void FileOptions::clear_java_generate_equals_and_hash() { - java_generate_equals_and_hash_ = false; - clear_has_java_generate_equals_and_hash(); -} -bool FileOptions::java_generate_equals_and_hash() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generate_equals_and_hash) - return java_generate_equals_and_hash_; -} -void FileOptions::set_java_generate_equals_and_hash(bool value) { - set_has_java_generate_equals_and_hash(); - java_generate_equals_and_hash_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generate_equals_and_hash) -} - -// optional bool java_string_check_utf8 = 27 [default = false]; -bool FileOptions::has_java_string_check_utf8() const { - return (_has_bits_[0] & 0x00000400u) != 0; -} -void FileOptions::set_has_java_string_check_utf8() { - _has_bits_[0] |= 0x00000400u; -} -void FileOptions::clear_has_java_string_check_utf8() { - _has_bits_[0] &= ~0x00000400u; -} -void FileOptions::clear_java_string_check_utf8() { - java_string_check_utf8_ = false; - clear_has_java_string_check_utf8(); -} -bool FileOptions::java_string_check_utf8() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_string_check_utf8) - return java_string_check_utf8_; -} -void FileOptions::set_java_string_check_utf8(bool value) { - set_has_java_string_check_utf8(); - java_string_check_utf8_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_string_check_utf8) -} - -// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; -bool FileOptions::has_optimize_for() const { - return (_has_bits_[0] & 0x00020000u) != 0; -} -void FileOptions::set_has_optimize_for() { - _has_bits_[0] |= 0x00020000u; -} -void FileOptions::clear_has_optimize_for() { - _has_bits_[0] &= ~0x00020000u; -} -void FileOptions::clear_optimize_for() { - optimize_for_ = 1; - clear_has_optimize_for(); -} -::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.optimize_for) - return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_); -} -void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) { - assert(::google::protobuf::FileOptions_OptimizeMode_IsValid(value)); - set_has_optimize_for(); - optimize_for_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.optimize_for) -} - -// optional string go_package = 11; -bool FileOptions::has_go_package() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -void FileOptions::set_has_go_package() { - _has_bits_[0] |= 0x00000004u; -} -void FileOptions::clear_has_go_package() { - _has_bits_[0] &= ~0x00000004u; -} -void FileOptions::clear_go_package() { - go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_go_package(); -} -const ::std::string& FileOptions::go_package() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.go_package) - return go_package_.GetNoArena(); -} -void FileOptions::set_go_package(const ::std::string& value) { - set_has_go_package(); - go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package) -} -#if LANG_CXX11 -void FileOptions::set_go_package(::std::string&& value) { - set_has_go_package(); - go_package_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.go_package) -} -#endif -void FileOptions::set_go_package(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_go_package(); - go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package) -} -void FileOptions::set_go_package(const char* value, size_t size) { - set_has_go_package(); - go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package) -} -::std::string* FileOptions::mutable_go_package() { - set_has_go_package(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package) - return go_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FileOptions::release_go_package() { - // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.go_package) - clear_has_go_package(); - return go_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FileOptions::set_allocated_go_package(::std::string* go_package) { - if (go_package != NULL) { - set_has_go_package(); - } else { - clear_has_go_package(); - } - go_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), go_package); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package) -} - -// optional bool cc_generic_services = 16 [default = false]; -bool FileOptions::has_cc_generic_services() const { - return (_has_bits_[0] & 0x00000800u) != 0; -} -void FileOptions::set_has_cc_generic_services() { - _has_bits_[0] |= 0x00000800u; -} -void FileOptions::clear_has_cc_generic_services() { - _has_bits_[0] &= ~0x00000800u; -} -void FileOptions::clear_cc_generic_services() { - cc_generic_services_ = false; - clear_has_cc_generic_services(); -} -bool FileOptions::cc_generic_services() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_generic_services) - return cc_generic_services_; -} -void FileOptions::set_cc_generic_services(bool value) { - set_has_cc_generic_services(); - cc_generic_services_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_generic_services) -} - -// optional bool java_generic_services = 17 [default = false]; -bool FileOptions::has_java_generic_services() const { - return (_has_bits_[0] & 0x00001000u) != 0; -} -void FileOptions::set_has_java_generic_services() { - _has_bits_[0] |= 0x00001000u; -} -void FileOptions::clear_has_java_generic_services() { - _has_bits_[0] &= ~0x00001000u; -} -void FileOptions::clear_java_generic_services() { - java_generic_services_ = false; - clear_has_java_generic_services(); -} -bool FileOptions::java_generic_services() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generic_services) - return java_generic_services_; -} -void FileOptions::set_java_generic_services(bool value) { - set_has_java_generic_services(); - java_generic_services_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generic_services) -} - -// optional bool py_generic_services = 18 [default = false]; -bool FileOptions::has_py_generic_services() const { - return (_has_bits_[0] & 0x00002000u) != 0; -} -void FileOptions::set_has_py_generic_services() { - _has_bits_[0] |= 0x00002000u; -} -void FileOptions::clear_has_py_generic_services() { - _has_bits_[0] &= ~0x00002000u; -} -void FileOptions::clear_py_generic_services() { - py_generic_services_ = false; - clear_has_py_generic_services(); -} -bool FileOptions::py_generic_services() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.py_generic_services) - return py_generic_services_; -} -void FileOptions::set_py_generic_services(bool value) { - set_has_py_generic_services(); - py_generic_services_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.py_generic_services) -} - -// optional bool php_generic_services = 19 [default = false]; -bool FileOptions::has_php_generic_services() const { - return (_has_bits_[0] & 0x00004000u) != 0; -} -void FileOptions::set_has_php_generic_services() { - _has_bits_[0] |= 0x00004000u; -} -void FileOptions::clear_has_php_generic_services() { - _has_bits_[0] &= ~0x00004000u; -} -void FileOptions::clear_php_generic_services() { - php_generic_services_ = false; - clear_has_php_generic_services(); -} -bool FileOptions::php_generic_services() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_generic_services) - return php_generic_services_; -} -void FileOptions::set_php_generic_services(bool value) { - set_has_php_generic_services(); - php_generic_services_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_generic_services) -} - -// optional bool deprecated = 23 [default = false]; -bool FileOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00008000u) != 0; -} -void FileOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00008000u; -} -void FileOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00008000u; -} -void FileOptions::clear_deprecated() { - deprecated_ = false; - clear_has_deprecated(); -} -bool FileOptions::deprecated() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.deprecated) - return deprecated_; -} -void FileOptions::set_deprecated(bool value) { - set_has_deprecated(); - deprecated_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.deprecated) -} - -// optional bool cc_enable_arenas = 31 [default = false]; -bool FileOptions::has_cc_enable_arenas() const { - return (_has_bits_[0] & 0x00010000u) != 0; -} -void FileOptions::set_has_cc_enable_arenas() { - _has_bits_[0] |= 0x00010000u; -} -void FileOptions::clear_has_cc_enable_arenas() { - _has_bits_[0] &= ~0x00010000u; -} -void FileOptions::clear_cc_enable_arenas() { - cc_enable_arenas_ = false; - clear_has_cc_enable_arenas(); -} -bool FileOptions::cc_enable_arenas() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_enable_arenas) - return cc_enable_arenas_; -} -void FileOptions::set_cc_enable_arenas(bool value) { - set_has_cc_enable_arenas(); - cc_enable_arenas_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas) -} - -// optional string objc_class_prefix = 36; -bool FileOptions::has_objc_class_prefix() const { - return (_has_bits_[0] & 0x00000008u) != 0; -} -void FileOptions::set_has_objc_class_prefix() { - _has_bits_[0] |= 0x00000008u; -} -void FileOptions::clear_has_objc_class_prefix() { - _has_bits_[0] &= ~0x00000008u; -} -void FileOptions::clear_objc_class_prefix() { - objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_objc_class_prefix(); -} -const ::std::string& FileOptions::objc_class_prefix() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix) - return objc_class_prefix_.GetNoArena(); -} -void FileOptions::set_objc_class_prefix(const ::std::string& value) { - set_has_objc_class_prefix(); - objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix) -} -#if LANG_CXX11 -void FileOptions::set_objc_class_prefix(::std::string&& value) { - set_has_objc_class_prefix(); - objc_class_prefix_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.objc_class_prefix) -} -#endif -void FileOptions::set_objc_class_prefix(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_objc_class_prefix(); - objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix) -} -void FileOptions::set_objc_class_prefix(const char* value, size_t size) { - set_has_objc_class_prefix(); - objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix) -} -::std::string* FileOptions::mutable_objc_class_prefix() { - set_has_objc_class_prefix(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix) - return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FileOptions::release_objc_class_prefix() { - // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.objc_class_prefix) - clear_has_objc_class_prefix(); - return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_class_prefix) { - if (objc_class_prefix != NULL) { - set_has_objc_class_prefix(); - } else { - clear_has_objc_class_prefix(); - } - objc_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), objc_class_prefix); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix) -} - -// optional string csharp_namespace = 37; -bool FileOptions::has_csharp_namespace() const { - return (_has_bits_[0] & 0x00000010u) != 0; -} -void FileOptions::set_has_csharp_namespace() { - _has_bits_[0] |= 0x00000010u; -} -void FileOptions::clear_has_csharp_namespace() { - _has_bits_[0] &= ~0x00000010u; -} -void FileOptions::clear_csharp_namespace() { - csharp_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_csharp_namespace(); -} -const ::std::string& FileOptions::csharp_namespace() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_namespace) - return csharp_namespace_.GetNoArena(); -} -void FileOptions::set_csharp_namespace(const ::std::string& value) { - set_has_csharp_namespace(); - csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_namespace) -} -#if LANG_CXX11 -void FileOptions::set_csharp_namespace(::std::string&& value) { - set_has_csharp_namespace(); - csharp_namespace_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.csharp_namespace) -} -#endif -void FileOptions::set_csharp_namespace(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_csharp_namespace(); - csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_namespace) -} -void FileOptions::set_csharp_namespace(const char* value, size_t size) { - set_has_csharp_namespace(); - csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_namespace) -} -::std::string* FileOptions::mutable_csharp_namespace() { - set_has_csharp_namespace(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_namespace) - return csharp_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FileOptions::release_csharp_namespace() { - // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.csharp_namespace) - clear_has_csharp_namespace(); - return csharp_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FileOptions::set_allocated_csharp_namespace(::std::string* csharp_namespace) { - if (csharp_namespace != NULL) { - set_has_csharp_namespace(); - } else { - clear_has_csharp_namespace(); - } - csharp_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_namespace); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace) -} - -// optional string swift_prefix = 39; -bool FileOptions::has_swift_prefix() const { - return (_has_bits_[0] & 0x00000020u) != 0; -} -void FileOptions::set_has_swift_prefix() { - _has_bits_[0] |= 0x00000020u; -} -void FileOptions::clear_has_swift_prefix() { - _has_bits_[0] &= ~0x00000020u; -} -void FileOptions::clear_swift_prefix() { - swift_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_swift_prefix(); -} -const ::std::string& FileOptions::swift_prefix() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.swift_prefix) - return swift_prefix_.GetNoArena(); -} -void FileOptions::set_swift_prefix(const ::std::string& value) { - set_has_swift_prefix(); - swift_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.swift_prefix) -} -#if LANG_CXX11 -void FileOptions::set_swift_prefix(::std::string&& value) { - set_has_swift_prefix(); - swift_prefix_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.swift_prefix) -} -#endif -void FileOptions::set_swift_prefix(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_swift_prefix(); - swift_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.swift_prefix) -} -void FileOptions::set_swift_prefix(const char* value, size_t size) { - set_has_swift_prefix(); - swift_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.swift_prefix) -} -::std::string* FileOptions::mutable_swift_prefix() { - set_has_swift_prefix(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.swift_prefix) - return swift_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FileOptions::release_swift_prefix() { - // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.swift_prefix) - clear_has_swift_prefix(); - return swift_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FileOptions::set_allocated_swift_prefix(::std::string* swift_prefix) { - if (swift_prefix != NULL) { - set_has_swift_prefix(); - } else { - clear_has_swift_prefix(); - } - swift_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), swift_prefix); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.swift_prefix) -} - -// optional string php_class_prefix = 40; -bool FileOptions::has_php_class_prefix() const { - return (_has_bits_[0] & 0x00000040u) != 0; -} -void FileOptions::set_has_php_class_prefix() { - _has_bits_[0] |= 0x00000040u; -} -void FileOptions::clear_has_php_class_prefix() { - _has_bits_[0] &= ~0x00000040u; -} -void FileOptions::clear_php_class_prefix() { - php_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_php_class_prefix(); -} -const ::std::string& FileOptions::php_class_prefix() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_class_prefix) - return php_class_prefix_.GetNoArena(); -} -void FileOptions::set_php_class_prefix(const ::std::string& value) { - set_has_php_class_prefix(); - php_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_class_prefix) -} -#if LANG_CXX11 -void FileOptions::set_php_class_prefix(::std::string&& value) { - set_has_php_class_prefix(); - php_class_prefix_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_class_prefix) -} -#endif -void FileOptions::set_php_class_prefix(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_php_class_prefix(); - php_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_class_prefix) -} -void FileOptions::set_php_class_prefix(const char* value, size_t size) { - set_has_php_class_prefix(); - php_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_class_prefix) -} -::std::string* FileOptions::mutable_php_class_prefix() { - set_has_php_class_prefix(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_class_prefix) - return php_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FileOptions::release_php_class_prefix() { - // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_class_prefix) - clear_has_php_class_prefix(); - return php_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FileOptions::set_allocated_php_class_prefix(::std::string* php_class_prefix) { - if (php_class_prefix != NULL) { - set_has_php_class_prefix(); - } else { - clear_has_php_class_prefix(); - } - php_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), php_class_prefix); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_class_prefix) -} - -// optional string php_namespace = 41; -bool FileOptions::has_php_namespace() const { - return (_has_bits_[0] & 0x00000080u) != 0; -} -void FileOptions::set_has_php_namespace() { - _has_bits_[0] |= 0x00000080u; -} -void FileOptions::clear_has_php_namespace() { - _has_bits_[0] &= ~0x00000080u; -} -void FileOptions::clear_php_namespace() { - php_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_php_namespace(); -} -const ::std::string& FileOptions::php_namespace() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_namespace) - return php_namespace_.GetNoArena(); -} -void FileOptions::set_php_namespace(const ::std::string& value) { - set_has_php_namespace(); - php_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_namespace) -} -#if LANG_CXX11 -void FileOptions::set_php_namespace(::std::string&& value) { - set_has_php_namespace(); - php_namespace_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_namespace) -} -#endif -void FileOptions::set_php_namespace(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_php_namespace(); - php_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_namespace) -} -void FileOptions::set_php_namespace(const char* value, size_t size) { - set_has_php_namespace(); - php_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_namespace) -} -::std::string* FileOptions::mutable_php_namespace() { - set_has_php_namespace(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_namespace) - return php_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* FileOptions::release_php_namespace() { - // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_namespace) - clear_has_php_namespace(); - return php_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void FileOptions::set_allocated_php_namespace(::std::string* php_namespace) { - if (php_namespace != NULL) { - set_has_php_namespace(); - } else { - clear_has_php_namespace(); - } - php_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), php_namespace); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_namespace) -} - -// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -int FileOptions::uninterpreted_option_size() const { - return uninterpreted_option_.size(); -} -void FileOptions::clear_uninterpreted_option() { - uninterpreted_option_.Clear(); -} -const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.uninterpreted_option) - return uninterpreted_option_.Mutable(index); -} -::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* -FileOptions::mutable_uninterpreted_option() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option) - return &uninterpreted_option_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -FileOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option) - return uninterpreted_option_; -} - -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS - -// =================================================================== - -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int MessageOptions::kMessageSetWireFormatFieldNumber; -const int MessageOptions::kNoStandardDescriptorAccessorFieldNumber; -const int MessageOptions::kDeprecatedFieldNumber; -const int MessageOptions::kMapEntryFieldNumber; -const int MessageOptions::kUninterpretedOptionFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -MessageOptions::MessageOptions() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - } - SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.MessageOptions) -} -MessageOptions::MessageOptions(const MessageOptions& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0), - uninterpreted_option_(from.uninterpreted_option_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - _extensions_.MergeFrom(from._extensions_); - ::memcpy(&message_set_wire_format_, &from.message_set_wire_format_, - static_cast(reinterpret_cast(&map_entry_) - - reinterpret_cast(&message_set_wire_format_)) + sizeof(map_entry_)); - // @@protoc_insertion_point(copy_constructor:google.protobuf.MessageOptions) -} - -void MessageOptions::SharedCtor() { - _cached_size_ = 0; - ::memset(&message_set_wire_format_, 0, static_cast( - reinterpret_cast(&map_entry_) - - reinterpret_cast(&message_set_wire_format_)) + sizeof(map_entry_)); -} - -MessageOptions::~MessageOptions() { - // @@protoc_insertion_point(destructor:google.protobuf.MessageOptions) - SharedDtor(); -} - -void MessageOptions::SharedDtor() { -} - -void MessageOptions::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* MessageOptions::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const MessageOptions& MessageOptions::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -MessageOptions* MessageOptions::New(::google::protobuf::Arena* arena) const { - MessageOptions* n = new MessageOptions; - if (arena != NULL) { - arena->Own(n); - } - return n; +void MessageOptions::SetCachedSize(int size) const { + _cached_size_.Set(size); } void MessageOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.MessageOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; _extensions_.Clear(); uninterpreted_option_.Clear(); - cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 15u) { - ::memset(&message_set_wire_format_, 0, static_cast( - reinterpret_cast(&map_entry_) - - reinterpret_cast(&message_set_wire_format_)) + sizeof(map_entry_)); - } + ::memset(&message_set_wire_format_, 0, static_cast( + reinterpret_cast(&map_entry_) - + reinterpret_cast(&message_set_wire_format_)) + sizeof(map_entry_)); _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool MessageOptions::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.MessageOptions) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(16383u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional bool message_set_wire_format = 1 [default = false]; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { - set_has_message_set_wire_format(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &message_set_wire_format_))); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* MessageOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional bool message_set_wire_format = 1 [default = false]; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + _Internal::set_has_message_set_wire_format(&has_bits); + message_set_wire_format_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional bool no_standard_descriptor_accessor = 2 [default = false]; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) { - set_has_no_standard_descriptor_accessor(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &no_standard_descriptor_accessor_))); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + _Internal::set_has_no_standard_descriptor_accessor(&has_bits); + no_standard_descriptor_accessor_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional bool deprecated = 3 [default = false]; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) { - set_has_deprecated(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &deprecated_))); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + _Internal::set_has_deprecated(&has_bits); + deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional bool map_entry = 7; - case 7: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(56u /* 56 & 0xFF */)) { - set_has_map_entry(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &map_entry_))); - } else { - goto handle_unusual; - } - break; - } - + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 56)) { + _Internal::set_has_map_entry(&has_bits); + map_entry_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - case 999: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_uninterpreted_option())); - } else { - goto handle_unusual; - } - break; - } - + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - if ((8000u <= tag)) { - DO_(_extensions_.ParseField(tag, input, - internal_default_instance(), - _internal_metadata_.mutable_unknown_fields())); - continue; - } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + if ((8000u <= tag)) { + ptr = _extensions_.ParseField(tag, ptr, + internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.MessageOptions) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.MessageOptions) - return false; -#undef DO_ + ptr = nullptr; + goto success; +#undef CHK_ } -void MessageOptions::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.MessageOptions) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional bool message_set_wire_format = 1 [default = false]; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output); - } - - // optional bool no_standard_descriptor_accessor = 2 [default = false]; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->no_standard_descriptor_accessor(), output); - } - - // optional bool deprecated = 3 [default = false]; - if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output); - } - - // optional bool map_entry = 7; - if (cached_has_bits & 0x00000008u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(7, this->map_entry(), output); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 999, this->uninterpreted_option(static_cast(i)), output); - } - - // Extension range [1000, 536870912) - _extensions_.SerializeWithCachedSizes( - 1000, 536870912, output); - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.MessageOptions) -} - -::google::protobuf::uint8* MessageOptions::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* MessageOptions::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MessageOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional bool message_set_wire_format = 1 [default = false]; if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->message_set_wire_format(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(1, this->_internal_message_set_wire_format(), target); } // optional bool no_standard_descriptor_accessor = 2 [default = false]; if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->no_standard_descriptor_accessor(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(2, this->_internal_no_standard_descriptor_accessor(), target); } // optional bool deprecated = 3 [default = false]; if (cached_has_bits & 0x00000004u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(3, this->_internal_deprecated(), target); } // optional bool map_entry = 7; if (cached_has_bits & 0x00000008u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(7, this->map_entry(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(7, this->_internal_map_entry(), target); } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 999, this->uninterpreted_option(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_uninterpreted_option_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, this->_internal_uninterpreted_option(i), target, stream); } // Extension range [1000, 536870912) - target = _extensions_.InternalSerializeWithCachedSizesToArray( - 1000, 536870912, deterministic, target); + target = _extensions_._InternalSerialize( + 1000, 536870912, target, stream); - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MessageOptions) return target; @@ -11002,60 +7136,58 @@ size_t MessageOptions::ByteSizeLong() const { total_size += _extensions_.ByteSize(); - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - unsigned int count = static_cast(this->uninterpreted_option_size()); - total_size += 2UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->uninterpreted_option(static_cast(i))); - } + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - if (_has_bits_[0 / 32] & 15u) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { // optional bool message_set_wire_format = 1 [default = false]; - if (has_message_set_wire_format()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + 1; } // optional bool no_standard_descriptor_accessor = 2 [default = false]; - if (has_no_standard_descriptor_accessor()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + 1; } // optional bool deprecated = 3 [default = false]; - if (has_deprecated()) { + if (cached_has_bits & 0x00000004u) { total_size += 1 + 1; } // optional bool map_entry = 7; - if (has_map_entry()) { + if (cached_has_bits & 0x00000008u) { total_size += 1 + 1; } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void MessageOptions::MergeFrom(const ::google::protobuf::Message& from) { +void MessageOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MessageOptions) GOOGLE_DCHECK_NE(&from, this); const MessageOptions* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MessageOptions) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MessageOptions) MergeFrom(*source); @@ -11066,13 +7198,13 @@ void MessageOptions::MergeFrom(const MessageOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MessageOptions) GOOGLE_DCHECK_NE(&from, this); _extensions_.MergeFrom(from._extensions_); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; uninterpreted_option_.MergeFrom(from.uninterpreted_option_); cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 15u) { + if (cached_has_bits & 0x0000000fu) { if (cached_has_bits & 0x00000001u) { message_set_wire_format_ = from.message_set_wire_format_; } @@ -11089,7 +7221,7 @@ void MessageOptions::MergeFrom(const MessageOptions& from) { } } -void MessageOptions::CopyFrom(const ::google::protobuf::Message& from) { +void MessageOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MessageOptions) if (&from == this) return; Clear(); @@ -11108,190 +7240,67 @@ bool MessageOptions::IsInitialized() const { return false; } - if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(uninterpreted_option_)) return false; return true; } -void MessageOptions::Swap(MessageOptions* other) { - if (other == this) return; - InternalSwap(other); -} void MessageOptions::InternalSwap(MessageOptions* other) { using std::swap; - uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); - swap(message_set_wire_format_, other->message_set_wire_format_); - swap(no_standard_descriptor_accessor_, other->no_standard_descriptor_accessor_); - swap(deprecated_, other->deprecated_); - swap(map_entry_, other->map_entry_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); _extensions_.Swap(&other->_extensions_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); + uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(MessageOptions, map_entry_) + + sizeof(MessageOptions::map_entry_) + - PROTOBUF_FIELD_OFFSET(MessageOptions, message_set_wire_format_)>( + reinterpret_cast(&message_set_wire_format_), + reinterpret_cast(&other->message_set_wire_format_)); } -::google::protobuf::Metadata MessageOptions::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// MessageOptions - -// optional bool message_set_wire_format = 1 [default = false]; -bool MessageOptions::has_message_set_wire_format() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void MessageOptions::set_has_message_set_wire_format() { - _has_bits_[0] |= 0x00000001u; -} -void MessageOptions::clear_has_message_set_wire_format() { - _has_bits_[0] &= ~0x00000001u; -} -void MessageOptions::clear_message_set_wire_format() { - message_set_wire_format_ = false; - clear_has_message_set_wire_format(); -} -bool MessageOptions::message_set_wire_format() const { - // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.message_set_wire_format) - return message_set_wire_format_; -} -void MessageOptions::set_message_set_wire_format(bool value) { - set_has_message_set_wire_format(); - message_set_wire_format_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.message_set_wire_format) -} - -// optional bool no_standard_descriptor_accessor = 2 [default = false]; -bool MessageOptions::has_no_standard_descriptor_accessor() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void MessageOptions::set_has_no_standard_descriptor_accessor() { - _has_bits_[0] |= 0x00000002u; -} -void MessageOptions::clear_has_no_standard_descriptor_accessor() { - _has_bits_[0] &= ~0x00000002u; -} -void MessageOptions::clear_no_standard_descriptor_accessor() { - no_standard_descriptor_accessor_ = false; - clear_has_no_standard_descriptor_accessor(); -} -bool MessageOptions::no_standard_descriptor_accessor() const { - // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.no_standard_descriptor_accessor) - return no_standard_descriptor_accessor_; -} -void MessageOptions::set_no_standard_descriptor_accessor(bool value) { - set_has_no_standard_descriptor_accessor(); - no_standard_descriptor_accessor_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.no_standard_descriptor_accessor) -} - -// optional bool deprecated = 3 [default = false]; -bool MessageOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -void MessageOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00000004u; -} -void MessageOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00000004u; -} -void MessageOptions::clear_deprecated() { - deprecated_ = false; - clear_has_deprecated(); -} -bool MessageOptions::deprecated() const { - // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.deprecated) - return deprecated_; -} -void MessageOptions::set_deprecated(bool value) { - set_has_deprecated(); - deprecated_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.deprecated) -} - -// optional bool map_entry = 7; -bool MessageOptions::has_map_entry() const { - return (_has_bits_[0] & 0x00000008u) != 0; -} -void MessageOptions::set_has_map_entry() { - _has_bits_[0] |= 0x00000008u; -} -void MessageOptions::clear_has_map_entry() { - _has_bits_[0] &= ~0x00000008u; -} -void MessageOptions::clear_map_entry() { - map_entry_ = false; - clear_has_map_entry(); -} -bool MessageOptions::map_entry() const { - // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.map_entry) - return map_entry_; -} -void MessageOptions::set_map_entry(bool value) { - set_has_map_entry(); - map_entry_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.map_entry) -} - -// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -int MessageOptions::uninterpreted_option_size() const { - return uninterpreted_option_.size(); -} -void MessageOptions::clear_uninterpreted_option() { - uninterpreted_option_.Clear(); -} -const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.MessageOptions.uninterpreted_option) - return uninterpreted_option_.Mutable(index); -} -::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* -MessageOptions::mutable_uninterpreted_option() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option) - return &uninterpreted_option_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -MessageOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option) - return uninterpreted_option_; +::PROTOBUF_NAMESPACE_ID::Metadata MessageOptions::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int FieldOptions::kCtypeFieldNumber; -const int FieldOptions::kPackedFieldNumber; -const int FieldOptions::kJstypeFieldNumber; -const int FieldOptions::kLazyFieldNumber; -const int FieldOptions::kDeprecatedFieldNumber; -const int FieldOptions::kWeakFieldNumber; -const int FieldOptions::kUninterpretedOptionFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -FieldOptions::FieldOptions() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class FieldOptions::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_ctype(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } + static void set_has_packed(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_jstype(HasBits* has_bits) { + (*has_bits)[0] |= 32u; + } + static void set_has_lazy(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static void set_has_deprecated(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } + static void set_has_weak(HasBits* has_bits) { + (*has_bits)[0] |= 16u; + } +}; + +FieldOptions::FieldOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + _extensions_(arena), + uninterpreted_option_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.FieldOptions) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldOptions) } FieldOptions::FieldOptions(const FieldOptions& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), _has_bits_(from._has_bits_), - _cached_size_(0), uninterpreted_option_(from.uninterpreted_option_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _extensions_.MergeFrom(from._extensions_); ::memcpy(&ctype_, &from.ctype_, static_cast(reinterpret_cast(&jstype_) - @@ -11300,317 +7309,215 @@ FieldOptions::FieldOptions(const FieldOptions& from) } void FieldOptions::SharedCtor() { - _cached_size_ = 0; - ::memset(&ctype_, 0, static_cast( - reinterpret_cast(&jstype_) - - reinterpret_cast(&ctype_)) + sizeof(jstype_)); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&ctype_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&jstype_) - + reinterpret_cast(&ctype_)) + sizeof(jstype_)); } FieldOptions::~FieldOptions() { // @@protoc_insertion_point(destructor:google.protobuf.FieldOptions) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void FieldOptions::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); } -void FieldOptions::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void FieldOptions::ArenaDtor(void* object) { + FieldOptions* _this = reinterpret_cast< FieldOptions* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* FieldOptions::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void FieldOptions::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -const FieldOptions& FieldOptions::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -FieldOptions* FieldOptions::New(::google::protobuf::Arena* arena) const { - FieldOptions* n = new FieldOptions; - if (arena != NULL) { - arena->Own(n); - } - return n; +void FieldOptions::SetCachedSize(int size) const { + _cached_size_.Set(size); } void FieldOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; _extensions_.Clear(); uninterpreted_option_.Clear(); cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 63u) { + if (cached_has_bits & 0x0000003fu) { ::memset(&ctype_, 0, static_cast( reinterpret_cast(&jstype_) - reinterpret_cast(&ctype_)) + sizeof(jstype_)); } - _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool FieldOptions::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.FieldOptions) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(16383u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { - int value; - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( - input, &value))); - if (::google::protobuf::FieldOptions_CType_IsValid(value)) { - set_ctype(static_cast< ::google::protobuf::FieldOptions_CType >(value)); - } else { - mutable_unknown_fields()->AddVarint( - 1, static_cast< ::google::protobuf::uint64>(value)); - } - } else { - goto handle_unusual; - } - break; - } - - // optional bool packed = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) { - set_has_packed(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &packed_))); - } else { - goto handle_unusual; - } - break; - } - - // optional bool deprecated = 3 [default = false]; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) { - set_has_deprecated(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &deprecated_))); - } else { - goto handle_unusual; - } - break; - } - - // optional bool lazy = 5 [default = false]; - case 5: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(40u /* 40 & 0xFF */)) { - set_has_lazy(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &lazy_))); - } else { - goto handle_unusual; - } - break; - } - - // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; - case 6: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(48u /* 48 & 0xFF */)) { - int value; - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( - input, &value))); - if (::google::protobuf::FieldOptions_JSType_IsValid(value)) { - set_jstype(static_cast< ::google::protobuf::FieldOptions_JSType >(value)); - } else { - mutable_unknown_fields()->AddVarint( - 6, static_cast< ::google::protobuf::uint64>(value)); - } - } else { - goto handle_unusual; - } - break; - } - - // optional bool weak = 10 [default = false]; - case 10: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(80u /* 80 & 0xFF */)) { - set_has_weak(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &weak_))); - } else { - goto handle_unusual; - } - break; - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - case 999: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_uninterpreted_option())); - } else { - goto handle_unusual; - } - break; - } - - default: { - handle_unusual: - if (tag == 0) { - goto success; - } - if ((8000u <= tag)) { - DO_(_extensions_.ParseField(tag, input, - internal_default_instance(), - _internal_metadata_.mutable_unknown_fields())); - continue; - } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; - } - } - } -success: - // @@protoc_insertion_point(parse_success:google.protobuf.FieldOptions) - return true; -failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.FieldOptions) - return false; -#undef DO_ -} - -void FieldOptions::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.FieldOptions) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormatLite::WriteEnum( - 1, this->ctype(), output); - } - - // optional bool packed = 2; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->packed(), output); - } - - // optional bool deprecated = 3 [default = false]; - if (cached_has_bits & 0x00000008u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output); - } - - // optional bool lazy = 5 [default = false]; - if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(5, this->lazy(), output); - } - - // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; - if (cached_has_bits & 0x00000020u) { - ::google::protobuf::internal::WireFormatLite::WriteEnum( - 6, this->jstype(), output); - } - - // optional bool weak = 10 [default = false]; - if (cached_has_bits & 0x00000010u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->weak(), output); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 999, this->uninterpreted_option(static_cast(i)), output); - } - - // Extension range [1000, 536870912) - _extensions_.SerializeWithCachedSizes( - 1000, 536870912, output); + _has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.FieldOptions) +const char* FieldOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + ::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + if (PROTOBUF_PREDICT_TRUE(PROTOBUF_NAMESPACE_ID::FieldOptions_CType_IsValid(val))) { + _internal_set_ctype(static_cast(val)); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(1, val, mutable_unknown_fields()); + } + } else goto handle_unusual; + continue; + // optional bool packed = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + _Internal::set_has_packed(&has_bits); + packed_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // optional bool deprecated = 3 [default = false]; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + _Internal::set_has_deprecated(&has_bits); + deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // optional bool lazy = 5 [default = false]; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 40)) { + _Internal::set_has_lazy(&has_bits); + lazy_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 48)) { + ::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + if (PROTOBUF_PREDICT_TRUE(PROTOBUF_NAMESPACE_ID::FieldOptions_JSType_IsValid(val))) { + _internal_set_jstype(static_cast(val)); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(6, val, mutable_unknown_fields()); + } + } else goto handle_unusual; + continue; + // optional bool weak = 10 [default = false]; + case 10: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 80)) { + _Internal::set_has_weak(&has_bits); + weak_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + if ((8000u <= tag)) { + ptr = _extensions_.ParseField(tag, ptr, + internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + _has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* FieldOptions::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* FieldOptions::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( - 1, this->ctype(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray( + 1, this->_internal_ctype(), target); } // optional bool packed = 2; if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->packed(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(2, this->_internal_packed(), target); } // optional bool deprecated = 3 [default = false]; if (cached_has_bits & 0x00000008u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(3, this->_internal_deprecated(), target); } // optional bool lazy = 5 [default = false]; if (cached_has_bits & 0x00000004u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->lazy(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(5, this->_internal_lazy(), target); } // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; if (cached_has_bits & 0x00000020u) { - target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( - 6, this->jstype(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray( + 6, this->_internal_jstype(), target); } // optional bool weak = 10 [default = false]; if (cached_has_bits & 0x00000010u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->weak(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(10, this->_internal_weak(), target); } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 999, this->uninterpreted_option(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_uninterpreted_option_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, this->_internal_uninterpreted_option(i), target, stream); } // Extension range [1000, 536870912) - target = _extensions_.InternalSerializeWithCachedSizesToArray( - 1000, 536870912, deterministic, target); + target = _extensions_._InternalSerialize( + 1000, 536870912, target, stream); - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldOptions) return target; @@ -11622,72 +7529,70 @@ size_t FieldOptions::ByteSizeLong() const { total_size += _extensions_.ByteSize(); - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - unsigned int count = static_cast(this->uninterpreted_option_size()); - total_size += 2UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->uninterpreted_option(static_cast(i))); - } + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - if (_has_bits_[0 / 32] & 63u) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; - if (has_ctype()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::EnumSize(this->ctype()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_ctype()); } // optional bool packed = 2; - if (has_packed()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + 1; } // optional bool lazy = 5 [default = false]; - if (has_lazy()) { + if (cached_has_bits & 0x00000004u) { total_size += 1 + 1; } // optional bool deprecated = 3 [default = false]; - if (has_deprecated()) { + if (cached_has_bits & 0x00000008u) { total_size += 1 + 1; } // optional bool weak = 10 [default = false]; - if (has_weak()) { + if (cached_has_bits & 0x00000010u) { total_size += 1 + 1; } // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; - if (has_jstype()) { + if (cached_has_bits & 0x00000020u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::EnumSize(this->jstype()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_jstype()); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void FieldOptions::MergeFrom(const ::google::protobuf::Message& from) { +void FieldOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldOptions) GOOGLE_DCHECK_NE(&from, this); const FieldOptions* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldOptions) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldOptions) MergeFrom(*source); @@ -11698,13 +7603,13 @@ void FieldOptions::MergeFrom(const FieldOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldOptions) GOOGLE_DCHECK_NE(&from, this); _extensions_.MergeFrom(from._extensions_); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; uninterpreted_option_.MergeFrom(from.uninterpreted_option_); cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 63u) { + if (cached_has_bits & 0x0000003fu) { if (cached_has_bits & 0x00000001u) { ctype_ = from.ctype_; } @@ -11727,7 +7632,7 @@ void FieldOptions::MergeFrom(const FieldOptions& from) { } } -void FieldOptions::CopyFrom(const ::google::protobuf::Message& from) { +void FieldOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldOptions) if (&from == this) return; Clear(); @@ -11746,381 +7651,153 @@ bool FieldOptions::IsInitialized() const { return false; } - if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(uninterpreted_option_)) return false; return true; } -void FieldOptions::Swap(FieldOptions* other) { - if (other == this) return; - InternalSwap(other); -} void FieldOptions::InternalSwap(FieldOptions* other) { using std::swap; - uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); - swap(ctype_, other->ctype_); - swap(packed_, other->packed_); - swap(lazy_, other->lazy_); - swap(deprecated_, other->deprecated_); - swap(weak_, other->weak_); - swap(jstype_, other->jstype_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); _extensions_.Swap(&other->_extensions_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); + uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(FieldOptions, jstype_) + + sizeof(FieldOptions::jstype_) + - PROTOBUF_FIELD_OFFSET(FieldOptions, ctype_)>( + reinterpret_cast(&ctype_), + reinterpret_cast(&other->ctype_)); } -::google::protobuf::Metadata FieldOptions::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// FieldOptions - -// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; -bool FieldOptions::has_ctype() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void FieldOptions::set_has_ctype() { - _has_bits_[0] |= 0x00000001u; -} -void FieldOptions::clear_has_ctype() { - _has_bits_[0] &= ~0x00000001u; -} -void FieldOptions::clear_ctype() { - ctype_ = 0; - clear_has_ctype(); -} -::google::protobuf::FieldOptions_CType FieldOptions::ctype() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.ctype) - return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_); -} -void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) { - assert(::google::protobuf::FieldOptions_CType_IsValid(value)); - set_has_ctype(); - ctype_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.ctype) -} - -// optional bool packed = 2; -bool FieldOptions::has_packed() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void FieldOptions::set_has_packed() { - _has_bits_[0] |= 0x00000002u; -} -void FieldOptions::clear_has_packed() { - _has_bits_[0] &= ~0x00000002u; -} -void FieldOptions::clear_packed() { - packed_ = false; - clear_has_packed(); -} -bool FieldOptions::packed() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.packed) - return packed_; -} -void FieldOptions::set_packed(bool value) { - set_has_packed(); - packed_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed) -} - -// optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; -bool FieldOptions::has_jstype() const { - return (_has_bits_[0] & 0x00000020u) != 0; -} -void FieldOptions::set_has_jstype() { - _has_bits_[0] |= 0x00000020u; -} -void FieldOptions::clear_has_jstype() { - _has_bits_[0] &= ~0x00000020u; -} -void FieldOptions::clear_jstype() { - jstype_ = 0; - clear_has_jstype(); -} -::google::protobuf::FieldOptions_JSType FieldOptions::jstype() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.jstype) - return static_cast< ::google::protobuf::FieldOptions_JSType >(jstype_); -} -void FieldOptions::set_jstype(::google::protobuf::FieldOptions_JSType value) { - assert(::google::protobuf::FieldOptions_JSType_IsValid(value)); - set_has_jstype(); - jstype_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.jstype) -} - -// optional bool lazy = 5 [default = false]; -bool FieldOptions::has_lazy() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -void FieldOptions::set_has_lazy() { - _has_bits_[0] |= 0x00000004u; -} -void FieldOptions::clear_has_lazy() { - _has_bits_[0] &= ~0x00000004u; -} -void FieldOptions::clear_lazy() { - lazy_ = false; - clear_has_lazy(); -} -bool FieldOptions::lazy() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.lazy) - return lazy_; -} -void FieldOptions::set_lazy(bool value) { - set_has_lazy(); - lazy_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.lazy) -} - -// optional bool deprecated = 3 [default = false]; -bool FieldOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00000008u) != 0; -} -void FieldOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00000008u; -} -void FieldOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00000008u; -} -void FieldOptions::clear_deprecated() { - deprecated_ = false; - clear_has_deprecated(); -} -bool FieldOptions::deprecated() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.deprecated) - return deprecated_; -} -void FieldOptions::set_deprecated(bool value) { - set_has_deprecated(); - deprecated_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.deprecated) -} - -// optional bool weak = 10 [default = false]; -bool FieldOptions::has_weak() const { - return (_has_bits_[0] & 0x00000010u) != 0; -} -void FieldOptions::set_has_weak() { - _has_bits_[0] |= 0x00000010u; -} -void FieldOptions::clear_has_weak() { - _has_bits_[0] &= ~0x00000010u; -} -void FieldOptions::clear_weak() { - weak_ = false; - clear_has_weak(); -} -bool FieldOptions::weak() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.weak) - return weak_; -} -void FieldOptions::set_weak(bool value) { - set_has_weak(); - weak_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak) -} - -// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -int FieldOptions::uninterpreted_option_size() const { - return uninterpreted_option_.size(); -} -void FieldOptions::clear_uninterpreted_option() { - uninterpreted_option_.Clear(); -} -const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.uninterpreted_option) - return uninterpreted_option_.Mutable(index); -} -::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* -FieldOptions::mutable_uninterpreted_option() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option) - return &uninterpreted_option_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -FieldOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option) - return uninterpreted_option_; +::PROTOBUF_NAMESPACE_ID::Metadata FieldOptions::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int OneofOptions::kUninterpretedOptionFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +class OneofOptions::_Internal { + public: +}; -OneofOptions::OneofOptions() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - } +OneofOptions::OneofOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + _extensions_(arena), + uninterpreted_option_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.OneofOptions) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.OneofOptions) } OneofOptions::OneofOptions(const OneofOptions& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0), + : ::PROTOBUF_NAMESPACE_ID::Message(), uninterpreted_option_(from.uninterpreted_option_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _extensions_.MergeFrom(from._extensions_); // @@protoc_insertion_point(copy_constructor:google.protobuf.OneofOptions) } void OneofOptions::SharedCtor() { - _cached_size_ = 0; } OneofOptions::~OneofOptions() { // @@protoc_insertion_point(destructor:google.protobuf.OneofOptions) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void OneofOptions::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); } -void OneofOptions::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* OneofOptions::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void OneofOptions::ArenaDtor(void* object) { + OneofOptions* _this = reinterpret_cast< OneofOptions* >(object); + (void)_this; } - -const OneofOptions& OneofOptions::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void OneofOptions::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -OneofOptions* OneofOptions::New(::google::protobuf::Arena* arena) const { - OneofOptions* n = new OneofOptions; - if (arena != NULL) { - arena->Own(n); - } - return n; +void OneofOptions::SetCachedSize(int size) const { + _cached_size_.Set(size); } void OneofOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.OneofOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; _extensions_.Clear(); uninterpreted_option_.Clear(); - _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool OneofOptions::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.OneofOptions) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(16383u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - case 999: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_uninterpreted_option())); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* OneofOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - if ((8000u <= tag)) { - DO_(_extensions_.ParseField(tag, input, - internal_default_instance(), - _internal_metadata_.mutable_unknown_fields())); - continue; - } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + if ((8000u <= tag)) { + ptr = _extensions_.ParseField(tag, ptr, + internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.OneofOptions) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.OneofOptions) - return false; -#undef DO_ -} - -void OneofOptions::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.OneofOptions) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 999, this->uninterpreted_option(static_cast(i)), output); - } - - // Extension range [1000, 536870912) - _extensions_.SerializeWithCachedSizes( - 1000, 536870912, output); - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.OneofOptions) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* OneofOptions::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* OneofOptions::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 999, this->uninterpreted_option(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_uninterpreted_option_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, this->_internal_uninterpreted_option(i), target, stream); } // Extension range [1000, 536870912) - target = _extensions_.InternalSerializeWithCachedSizesToArray( - 1000, 536870912, deterministic, target); + target = _extensions_._InternalSerialize( + 1000, 536870912, target, stream); - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.OneofOptions) return target; @@ -12132,38 +7809,35 @@ size_t OneofOptions::ByteSizeLong() const { total_size += _extensions_.ByteSize(); - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - unsigned int count = static_cast(this->uninterpreted_option_size()); - total_size += 2UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->uninterpreted_option(static_cast(i))); - } + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void OneofOptions::MergeFrom(const ::google::protobuf::Message& from) { +void OneofOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.OneofOptions) GOOGLE_DCHECK_NE(&from, this); const OneofOptions* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.OneofOptions) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.OneofOptions) MergeFrom(*source); @@ -12174,14 +7848,14 @@ void OneofOptions::MergeFrom(const OneofOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofOptions) GOOGLE_DCHECK_NE(&from, this); _extensions_.MergeFrom(from._extensions_); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; uninterpreted_option_.MergeFrom(from.uninterpreted_option_); } -void OneofOptions::CopyFrom(const ::google::protobuf::Message& from) { +void OneofOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.OneofOptions) if (&from == this) return; Clear(); @@ -12200,86 +7874,48 @@ bool OneofOptions::IsInitialized() const { return false; } - if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(uninterpreted_option_)) return false; return true; } -void OneofOptions::Swap(OneofOptions* other) { - if (other == this) return; - InternalSwap(other); -} void OneofOptions::InternalSwap(OneofOptions* other) { using std::swap; - uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); _extensions_.Swap(&other->_extensions_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); } -::google::protobuf::Metadata OneofOptions::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// OneofOptions - -// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -int OneofOptions::uninterpreted_option_size() const { - return uninterpreted_option_.size(); -} -void OneofOptions::clear_uninterpreted_option() { - uninterpreted_option_.Clear(); -} -const ::google::protobuf::UninterpretedOption& OneofOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.OneofOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -::google::protobuf::UninterpretedOption* OneofOptions::mutable_uninterpreted_option(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.OneofOptions.uninterpreted_option) - return uninterpreted_option_.Mutable(index); -} -::google::protobuf::UninterpretedOption* OneofOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.OneofOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* -OneofOptions::mutable_uninterpreted_option() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.OneofOptions.uninterpreted_option) - return &uninterpreted_option_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -OneofOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.OneofOptions.uninterpreted_option) - return uninterpreted_option_; +::PROTOBUF_NAMESPACE_ID::Metadata OneofOptions::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int EnumOptions::kAllowAliasFieldNumber; -const int EnumOptions::kDeprecatedFieldNumber; -const int EnumOptions::kUninterpretedOptionFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -EnumOptions::EnumOptions() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class EnumOptions::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_allow_alias(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } + static void set_has_deprecated(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +EnumOptions::EnumOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + _extensions_(arena), + uninterpreted_option_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.EnumOptions) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumOptions) } EnumOptions::EnumOptions(const EnumOptions& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), _has_bits_(from._has_bits_), - _cached_size_(0), uninterpreted_option_(from.uninterpreted_option_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _extensions_.MergeFrom(from._extensions_); ::memcpy(&allow_alias_, &from.allow_alias_, static_cast(reinterpret_cast(&deprecated_) - @@ -12288,205 +7924,146 @@ EnumOptions::EnumOptions(const EnumOptions& from) } void EnumOptions::SharedCtor() { - _cached_size_ = 0; - ::memset(&allow_alias_, 0, static_cast( - reinterpret_cast(&deprecated_) - - reinterpret_cast(&allow_alias_)) + sizeof(deprecated_)); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&allow_alias_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&deprecated_) - + reinterpret_cast(&allow_alias_)) + sizeof(deprecated_)); } EnumOptions::~EnumOptions() { // @@protoc_insertion_point(destructor:google.protobuf.EnumOptions) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void EnumOptions::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); } -void EnumOptions::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void EnumOptions::ArenaDtor(void* object) { + EnumOptions* _this = reinterpret_cast< EnumOptions* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* EnumOptions::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const EnumOptions& EnumOptions::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void EnumOptions::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -EnumOptions* EnumOptions::New(::google::protobuf::Arena* arena) const { - EnumOptions* n = new EnumOptions; - if (arena != NULL) { - arena->Own(n); - } - return n; +void EnumOptions::SetCachedSize(int size) const { + _cached_size_.Set(size); } void EnumOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; _extensions_.Clear(); uninterpreted_option_.Clear(); - cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 3u) { - ::memset(&allow_alias_, 0, static_cast( - reinterpret_cast(&deprecated_) - - reinterpret_cast(&allow_alias_)) + sizeof(deprecated_)); - } + ::memset(&allow_alias_, 0, static_cast( + reinterpret_cast(&deprecated_) - + reinterpret_cast(&allow_alias_)) + sizeof(deprecated_)); _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool EnumOptions::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.EnumOptions) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(16383u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional bool allow_alias = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) { - set_has_allow_alias(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &allow_alias_))); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* EnumOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional bool allow_alias = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + _Internal::set_has_allow_alias(&has_bits); + allow_alias_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional bool deprecated = 3 [default = false]; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) { - set_has_deprecated(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &deprecated_))); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + _Internal::set_has_deprecated(&has_bits); + deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - case 999: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_uninterpreted_option())); - } else { - goto handle_unusual; - } - break; - } - + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - if ((8000u <= tag)) { - DO_(_extensions_.ParseField(tag, input, - internal_default_instance(), - _internal_metadata_.mutable_unknown_fields())); - continue; - } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + if ((8000u <= tag)) { + ptr = _extensions_.ParseField(tag, ptr, + internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.EnumOptions) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.EnumOptions) - return false; -#undef DO_ -} - -void EnumOptions::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.EnumOptions) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional bool allow_alias = 2; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->allow_alias(), output); - } - - // optional bool deprecated = 3 [default = false]; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 999, this->uninterpreted_option(static_cast(i)), output); - } - - // Extension range [1000, 536870912) - _extensions_.SerializeWithCachedSizes( - 1000, 536870912, output); - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.EnumOptions) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* EnumOptions::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* EnumOptions::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional bool allow_alias = 2; if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->allow_alias(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(2, this->_internal_allow_alias(), target); } // optional bool deprecated = 3 [default = false]; if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(3, this->_internal_deprecated(), target); } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 999, this->uninterpreted_option(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_uninterpreted_option_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, this->_internal_uninterpreted_option(i), target, stream); } // Extension range [1000, 536870912) - target = _extensions_.InternalSerializeWithCachedSizesToArray( - 1000, 536870912, deterministic, target); + target = _extensions_._InternalSerialize( + 1000, 536870912, target, stream); - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumOptions) return target; @@ -12498,50 +8075,48 @@ size_t EnumOptions::ByteSizeLong() const { total_size += _extensions_.ByteSize(); - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - unsigned int count = static_cast(this->uninterpreted_option_size()); - total_size += 2UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->uninterpreted_option(static_cast(i))); - } + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - if (_has_bits_[0 / 32] & 3u) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000003u) { // optional bool allow_alias = 2; - if (has_allow_alias()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + 1; } // optional bool deprecated = 3 [default = false]; - if (has_deprecated()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + 1; } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void EnumOptions::MergeFrom(const ::google::protobuf::Message& from) { +void EnumOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumOptions) GOOGLE_DCHECK_NE(&from, this); const EnumOptions* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumOptions) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumOptions) MergeFrom(*source); @@ -12552,13 +8127,13 @@ void EnumOptions::MergeFrom(const EnumOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumOptions) GOOGLE_DCHECK_NE(&from, this); _extensions_.MergeFrom(from._extensions_); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; uninterpreted_option_.MergeFrom(from.uninterpreted_option_); cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { allow_alias_ = from.allow_alias_; } @@ -12569,7 +8144,7 @@ void EnumOptions::MergeFrom(const EnumOptions& from) { } } -void EnumOptions::CopyFrom(const ::google::protobuf::Message& from) { +void EnumOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumOptions) if (&from == this) return; Clear(); @@ -12583,184 +8158,89 @@ void EnumOptions::CopyFrom(const EnumOptions& from) { MergeFrom(from); } -bool EnumOptions::IsInitialized() const { - if (!_extensions_.IsInitialized()) { - return false; - } - - if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; - return true; -} - -void EnumOptions::Swap(EnumOptions* other) { - if (other == this) return; - InternalSwap(other); -} -void EnumOptions::InternalSwap(EnumOptions* other) { - using std::swap; - uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); - swap(allow_alias_, other->allow_alias_); - swap(deprecated_, other->deprecated_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); - _extensions_.Swap(&other->_extensions_); -} - -::google::protobuf::Metadata EnumOptions::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// EnumOptions - -// optional bool allow_alias = 2; -bool EnumOptions::has_allow_alias() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void EnumOptions::set_has_allow_alias() { - _has_bits_[0] |= 0x00000001u; -} -void EnumOptions::clear_has_allow_alias() { - _has_bits_[0] &= ~0x00000001u; -} -void EnumOptions::clear_allow_alias() { - allow_alias_ = false; - clear_has_allow_alias(); -} -bool EnumOptions::allow_alias() const { - // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.allow_alias) - return allow_alias_; -} -void EnumOptions::set_allow_alias(bool value) { - set_has_allow_alias(); - allow_alias_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.allow_alias) -} - -// optional bool deprecated = 3 [default = false]; -bool EnumOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void EnumOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00000002u; -} -void EnumOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00000002u; -} -void EnumOptions::clear_deprecated() { - deprecated_ = false; - clear_has_deprecated(); -} -bool EnumOptions::deprecated() const { - // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.deprecated) - return deprecated_; -} -void EnumOptions::set_deprecated(bool value) { - set_has_deprecated(); - deprecated_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.deprecated) -} - -// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -int EnumOptions::uninterpreted_option_size() const { - return uninterpreted_option_.size(); -} -void EnumOptions::clear_uninterpreted_option() { - uninterpreted_option_.Clear(); -} -const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.EnumOptions.uninterpreted_option) - return uninterpreted_option_.Mutable(index); -} -::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option) - return uninterpreted_option_.Add(); +bool EnumOptions::IsInitialized() const { + if (!_extensions_.IsInitialized()) { + return false; + } + + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(uninterpreted_option_)) return false; + return true; } -::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* -EnumOptions::mutable_uninterpreted_option() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option) - return &uninterpreted_option_; + +void EnumOptions::InternalSwap(EnumOptions* other) { + using std::swap; + _extensions_.Swap(&other->_extensions_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); + uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(EnumOptions, deprecated_) + + sizeof(EnumOptions::deprecated_) + - PROTOBUF_FIELD_OFFSET(EnumOptions, allow_alias_)>( + reinterpret_cast(&allow_alias_), + reinterpret_cast(&other->allow_alias_)); } -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -EnumOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option) - return uninterpreted_option_; + +::PROTOBUF_NAMESPACE_ID::Metadata EnumOptions::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int EnumValueOptions::kDeprecatedFieldNumber; -const int EnumValueOptions::kUninterpretedOptionFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -EnumValueOptions::EnumValueOptions() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class EnumValueOptions::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_deprecated(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } +}; + +EnumValueOptions::EnumValueOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + _extensions_(arena), + uninterpreted_option_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.EnumValueOptions) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumValueOptions) } EnumValueOptions::EnumValueOptions(const EnumValueOptions& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), _has_bits_(from._has_bits_), - _cached_size_(0), uninterpreted_option_(from.uninterpreted_option_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _extensions_.MergeFrom(from._extensions_); deprecated_ = from.deprecated_; // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueOptions) } void EnumValueOptions::SharedCtor() { - _cached_size_ = 0; - deprecated_ = false; +deprecated_ = false; } EnumValueOptions::~EnumValueOptions() { // @@protoc_insertion_point(destructor:google.protobuf.EnumValueOptions) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void EnumValueOptions::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); } -void EnumValueOptions::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* EnumValueOptions::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void EnumValueOptions::ArenaDtor(void* object) { + EnumValueOptions* _this = reinterpret_cast< EnumValueOptions* >(object); + (void)_this; } - -const EnumValueOptions& EnumValueOptions::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void EnumValueOptions::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -EnumValueOptions* EnumValueOptions::New(::google::protobuf::Arena* arena) const { - EnumValueOptions* n = new EnumValueOptions; - if (arena != NULL) { - arena->Own(n); - } - return n; +void EnumValueOptions::SetCachedSize(int size) const { + _cached_size_.Set(size); } void EnumValueOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; @@ -12768,129 +8248,94 @@ void EnumValueOptions::Clear() { uninterpreted_option_.Clear(); deprecated_ = false; _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool EnumValueOptions::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.EnumValueOptions) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(16383u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional bool deprecated = 1 [default = false]; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { - set_has_deprecated(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &deprecated_))); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* EnumValueOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional bool deprecated = 1 [default = false]; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + _Internal::set_has_deprecated(&has_bits); + deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - case 999: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_uninterpreted_option())); - } else { - goto handle_unusual; - } - break; - } - + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - if ((8000u <= tag)) { - DO_(_extensions_.ParseField(tag, input, - internal_default_instance(), - _internal_metadata_.mutable_unknown_fields())); - continue; - } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + if ((8000u <= tag)) { + ptr = _extensions_.ParseField(tag, ptr, + internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.EnumValueOptions) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.EnumValueOptions) - return false; -#undef DO_ -} - -void EnumValueOptions::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.EnumValueOptions) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional bool deprecated = 1 [default = false]; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->deprecated(), output); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 999, this->uninterpreted_option(static_cast(i)), output); - } - - // Extension range [1000, 536870912) - _extensions_.SerializeWithCachedSizes( - 1000, 536870912, output); - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.EnumValueOptions) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* EnumValueOptions::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* EnumValueOptions::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional bool deprecated = 1 [default = false]; if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->deprecated(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(1, this->_internal_deprecated(), target); } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 999, this->uninterpreted_option(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_uninterpreted_option_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, this->_internal_uninterpreted_option(i), target, stream); } // Extension range [1000, 536870912) - target = _extensions_.InternalSerializeWithCachedSizesToArray( - 1000, 536870912, deterministic, target); + target = _extensions_._InternalSerialize( + 1000, 536870912, target, stream); - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueOptions) return target; @@ -12902,43 +8347,41 @@ size_t EnumValueOptions::ByteSizeLong() const { total_size += _extensions_.ByteSize(); - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - unsigned int count = static_cast(this->uninterpreted_option_size()); - total_size += 2UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->uninterpreted_option(static_cast(i))); - } + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // optional bool deprecated = 1 [default = false]; - if (has_deprecated()) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000001u) { total_size += 1 + 1; } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void EnumValueOptions::MergeFrom(const ::google::protobuf::Message& from) { +void EnumValueOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValueOptions) GOOGLE_DCHECK_NE(&from, this); const EnumValueOptions* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.EnumValueOptions) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.EnumValueOptions) MergeFrom(*source); @@ -12949,17 +8392,17 @@ void EnumValueOptions::MergeFrom(const EnumValueOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueOptions) GOOGLE_DCHECK_NE(&from, this); _extensions_.MergeFrom(from._extensions_); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; uninterpreted_option_.MergeFrom(from.uninterpreted_option_); - if (from.has_deprecated()) { - set_deprecated(from.deprecated()); + if (from._internal_has_deprecated()) { + _internal_set_deprecated(from._internal_deprecated()); } } -void EnumValueOptions::CopyFrom(const ::google::protobuf::Message& from) { +void EnumValueOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.EnumValueOptions) if (&from == this) return; Clear(); @@ -12978,154 +8421,79 @@ bool EnumValueOptions::IsInitialized() const { return false; } - if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(uninterpreted_option_)) return false; return true; } -void EnumValueOptions::Swap(EnumValueOptions* other) { - if (other == this) return; - InternalSwap(other); -} void EnumValueOptions::InternalSwap(EnumValueOptions* other) { using std::swap; + _extensions_.Swap(&other->_extensions_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); swap(deprecated_, other->deprecated_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); - _extensions_.Swap(&other->_extensions_); -} - -::google::protobuf::Metadata EnumValueOptions::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// EnumValueOptions - -// optional bool deprecated = 1 [default = false]; -bool EnumValueOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void EnumValueOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00000001u; -} -void EnumValueOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00000001u; -} -void EnumValueOptions::clear_deprecated() { - deprecated_ = false; - clear_has_deprecated(); -} -bool EnumValueOptions::deprecated() const { - // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.deprecated) - return deprecated_; -} -void EnumValueOptions::set_deprecated(bool value) { - set_has_deprecated(); - deprecated_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.EnumValueOptions.deprecated) } -// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -int EnumValueOptions::uninterpreted_option_size() const { - return uninterpreted_option_.size(); -} -void EnumValueOptions::clear_uninterpreted_option() { - uninterpreted_option_.Clear(); -} -const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueOptions.uninterpreted_option) - return uninterpreted_option_.Mutable(index); -} -::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* -EnumValueOptions::mutable_uninterpreted_option() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option) - return &uninterpreted_option_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -EnumValueOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option) - return uninterpreted_option_; +::PROTOBUF_NAMESPACE_ID::Metadata EnumValueOptions::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int ServiceOptions::kDeprecatedFieldNumber; -const int ServiceOptions::kUninterpretedOptionFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -ServiceOptions::ServiceOptions() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class ServiceOptions::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_deprecated(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } +}; + +ServiceOptions::ServiceOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + _extensions_(arena), + uninterpreted_option_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.ServiceOptions) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.ServiceOptions) } ServiceOptions::ServiceOptions(const ServiceOptions& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), _has_bits_(from._has_bits_), - _cached_size_(0), uninterpreted_option_(from.uninterpreted_option_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _extensions_.MergeFrom(from._extensions_); deprecated_ = from.deprecated_; // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceOptions) } void ServiceOptions::SharedCtor() { - _cached_size_ = 0; - deprecated_ = false; +deprecated_ = false; } ServiceOptions::~ServiceOptions() { // @@protoc_insertion_point(destructor:google.protobuf.ServiceOptions) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void ServiceOptions::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); } -void ServiceOptions::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void ServiceOptions::ArenaDtor(void* object) { + ServiceOptions* _this = reinterpret_cast< ServiceOptions* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* ServiceOptions::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void ServiceOptions::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -const ServiceOptions& ServiceOptions::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -ServiceOptions* ServiceOptions::New(::google::protobuf::Arena* arena) const { - ServiceOptions* n = new ServiceOptions; - if (arena != NULL) { - arena->Own(n); - } - return n; +void ServiceOptions::SetCachedSize(int size) const { + _cached_size_.Set(size); } void ServiceOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; @@ -13133,129 +8501,94 @@ void ServiceOptions::Clear() { uninterpreted_option_.Clear(); deprecated_ = false; _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool ServiceOptions::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.ServiceOptions) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(16383u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional bool deprecated = 33 [default = false]; - case 33: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(8u /* 264 & 0xFF */)) { - set_has_deprecated(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &deprecated_))); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* ServiceOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional bool deprecated = 33 [default = false]; + case 33: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + _Internal::set_has_deprecated(&has_bits); + deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - case 999: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_uninterpreted_option())); - } else { - goto handle_unusual; - } - break; - } - + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - if ((8000u <= tag)) { - DO_(_extensions_.ParseField(tag, input, - internal_default_instance(), - _internal_metadata_.mutable_unknown_fields())); - continue; - } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + if ((8000u <= tag)) { + ptr = _extensions_.ParseField(tag, ptr, + internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.ServiceOptions) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.ServiceOptions) - return false; -#undef DO_ -} - -void ServiceOptions::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.ServiceOptions) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional bool deprecated = 33 [default = false]; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(33, this->deprecated(), output); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 999, this->uninterpreted_option(static_cast(i)), output); - } - - // Extension range [1000, 536870912) - _extensions_.SerializeWithCachedSizes( - 1000, 536870912, output); - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.ServiceOptions) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* ServiceOptions::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* ServiceOptions::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional bool deprecated = 33 [default = false]; if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(33, this->deprecated(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(33, this->_internal_deprecated(), target); } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 999, this->uninterpreted_option(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_uninterpreted_option_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, this->_internal_uninterpreted_option(i), target, stream); } // Extension range [1000, 536870912) - target = _extensions_.InternalSerializeWithCachedSizesToArray( - 1000, 536870912, deterministic, target); + target = _extensions_._InternalSerialize( + 1000, 536870912, target, stream); - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceOptions) return target; @@ -13267,43 +8600,41 @@ size_t ServiceOptions::ByteSizeLong() const { total_size += _extensions_.ByteSize(); - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - unsigned int count = static_cast(this->uninterpreted_option_size()); - total_size += 2UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->uninterpreted_option(static_cast(i))); - } + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } // optional bool deprecated = 33 [default = false]; - if (has_deprecated()) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000001u) { total_size += 2 + 1; } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void ServiceOptions::MergeFrom(const ::google::protobuf::Message& from) { +void ServiceOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ServiceOptions) GOOGLE_DCHECK_NE(&from, this); const ServiceOptions* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ServiceOptions) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ServiceOptions) MergeFrom(*source); @@ -13314,17 +8645,17 @@ void ServiceOptions::MergeFrom(const ServiceOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceOptions) GOOGLE_DCHECK_NE(&from, this); _extensions_.MergeFrom(from._extensions_); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; uninterpreted_option_.MergeFrom(from.uninterpreted_option_); - if (from.has_deprecated()) { - set_deprecated(from.deprecated()); + if (from._internal_has_deprecated()) { + _internal_set_deprecated(from._internal_deprecated()); } } -void ServiceOptions::CopyFrom(const ::google::protobuf::Message& from) { +void ServiceOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ServiceOptions) if (&from == this) return; Clear(); @@ -13343,111 +8674,50 @@ bool ServiceOptions::IsInitialized() const { return false; } - if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(uninterpreted_option_)) return false; return true; } -void ServiceOptions::Swap(ServiceOptions* other) { - if (other == this) return; - InternalSwap(other); -} void ServiceOptions::InternalSwap(ServiceOptions* other) { using std::swap; + _extensions_.Swap(&other->_extensions_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); swap(deprecated_, other->deprecated_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); - _extensions_.Swap(&other->_extensions_); -} - -::google::protobuf::Metadata ServiceOptions::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// ServiceOptions - -// optional bool deprecated = 33 [default = false]; -bool ServiceOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void ServiceOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00000001u; -} -void ServiceOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00000001u; -} -void ServiceOptions::clear_deprecated() { - deprecated_ = false; - clear_has_deprecated(); -} -bool ServiceOptions::deprecated() const { - // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.deprecated) - return deprecated_; -} -void ServiceOptions::set_deprecated(bool value) { - set_has_deprecated(); - deprecated_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.ServiceOptions.deprecated) } -// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -int ServiceOptions::uninterpreted_option_size() const { - return uninterpreted_option_.size(); -} -void ServiceOptions::clear_uninterpreted_option() { - uninterpreted_option_.Clear(); -} -const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceOptions.uninterpreted_option) - return uninterpreted_option_.Mutable(index); -} -::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* -ServiceOptions::mutable_uninterpreted_option() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option) - return &uninterpreted_option_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -ServiceOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option) - return uninterpreted_option_; +::PROTOBUF_NAMESPACE_ID::Metadata ServiceOptions::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int MethodOptions::kDeprecatedFieldNumber; -const int MethodOptions::kIdempotencyLevelFieldNumber; -const int MethodOptions::kUninterpretedOptionFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -MethodOptions::MethodOptions() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class MethodOptions::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_deprecated(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_idempotency_level(HasBits* has_bits) { + (*has_bits)[0] |= 2u; } +}; + +MethodOptions::MethodOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + _extensions_(arena), + uninterpreted_option_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.MethodOptions) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.MethodOptions) } MethodOptions::MethodOptions(const MethodOptions& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), _has_bits_(from._has_bits_), - _cached_size_(0), uninterpreted_option_(from.uninterpreted_option_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _extensions_.MergeFrom(from._extensions_); ::memcpy(&deprecated_, &from.deprecated_, static_cast(reinterpret_cast(&idempotency_level_) - @@ -13456,213 +8726,154 @@ MethodOptions::MethodOptions(const MethodOptions& from) } void MethodOptions::SharedCtor() { - _cached_size_ = 0; - ::memset(&deprecated_, 0, static_cast( - reinterpret_cast(&idempotency_level_) - - reinterpret_cast(&deprecated_)) + sizeof(idempotency_level_)); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&deprecated_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&idempotency_level_) - + reinterpret_cast(&deprecated_)) + sizeof(idempotency_level_)); } MethodOptions::~MethodOptions() { // @@protoc_insertion_point(destructor:google.protobuf.MethodOptions) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void MethodOptions::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); } -void MethodOptions::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void MethodOptions::ArenaDtor(void* object) { + MethodOptions* _this = reinterpret_cast< MethodOptions* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* MethodOptions::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const MethodOptions& MethodOptions::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void MethodOptions::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -MethodOptions* MethodOptions::New(::google::protobuf::Arena* arena) const { - MethodOptions* n = new MethodOptions; - if (arena != NULL) { - arena->Own(n); - } - return n; +void MethodOptions::SetCachedSize(int size) const { + _cached_size_.Set(size); } void MethodOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.MethodOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; _extensions_.Clear(); uninterpreted_option_.Clear(); cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { ::memset(&deprecated_, 0, static_cast( reinterpret_cast(&idempotency_level_) - reinterpret_cast(&deprecated_)) + sizeof(idempotency_level_)); } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool MethodOptions::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.MethodOptions) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(16383u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional bool deprecated = 33 [default = false]; - case 33: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(8u /* 264 & 0xFF */)) { - set_has_deprecated(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &deprecated_))); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* MethodOptions::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // optional bool deprecated = 33 [default = false]; + case 33: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + _Internal::set_has_deprecated(&has_bits); + deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; - case 34: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(16u /* 272 & 0xFF */)) { - int value; - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( - input, &value))); - if (::google::protobuf::MethodOptions_IdempotencyLevel_IsValid(value)) { - set_idempotency_level(static_cast< ::google::protobuf::MethodOptions_IdempotencyLevel >(value)); + case 34: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + ::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + if (PROTOBUF_PREDICT_TRUE(PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel_IsValid(val))) { + _internal_set_idempotency_level(static_cast(val)); } else { - mutable_unknown_fields()->AddVarint( - 34, static_cast< ::google::protobuf::uint64>(value)); + ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(34, val, mutable_unknown_fields()); } - } else { - goto handle_unusual; - } - break; - } - + } else goto handle_unusual; + continue; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - case 999: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_uninterpreted_option())); - } else { - goto handle_unusual; - } - break; - } - + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - if ((8000u <= tag)) { - DO_(_extensions_.ParseField(tag, input, - internal_default_instance(), - _internal_metadata_.mutable_unknown_fields())); - continue; - } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + if ((8000u <= tag)) { + ptr = _extensions_.ParseField(tag, ptr, + internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.MethodOptions) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.MethodOptions) - return false; -#undef DO_ -} - -void MethodOptions::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.MethodOptions) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional bool deprecated = 33 [default = false]; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(33, this->deprecated(), output); - } - - // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteEnum( - 34, this->idempotency_level(), output); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 999, this->uninterpreted_option(static_cast(i)), output); - } - - // Extension range [1000, 536870912) - _extensions_.SerializeWithCachedSizes( - 1000, 536870912, output); - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.MethodOptions) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* MethodOptions::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* MethodOptions::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodOptions) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // optional bool deprecated = 33 [default = false]; if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(33, this->deprecated(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(33, this->_internal_deprecated(), target); } // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( - 34, this->idempotency_level(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray( + 34, this->_internal_idempotency_level(), target); } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, - n = static_cast(this->uninterpreted_option_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 999, this->uninterpreted_option(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_uninterpreted_option_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, this->_internal_uninterpreted_option(i), target, stream); } // Extension range [1000, 536870912) - target = _extensions_.InternalSerializeWithCachedSizesToArray( - 1000, 536870912, deterministic, target); + target = _extensions_._InternalSerialize( + 1000, 536870912, target, stream); - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodOptions) return target; @@ -13674,51 +8885,49 @@ size_t MethodOptions::ByteSizeLong() const { total_size += _extensions_.ByteSize(); - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - unsigned int count = static_cast(this->uninterpreted_option_size()); - total_size += 2UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->uninterpreted_option(static_cast(i))); - } + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - if (_has_bits_[0 / 32] & 3u) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000003u) { // optional bool deprecated = 33 [default = false]; - if (has_deprecated()) { + if (cached_has_bits & 0x00000001u) { total_size += 2 + 1; } // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; - if (has_idempotency_level()) { + if (cached_has_bits & 0x00000002u) { total_size += 2 + - ::google::protobuf::internal::WireFormatLite::EnumSize(this->idempotency_level()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_idempotency_level()); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void MethodOptions::MergeFrom(const ::google::protobuf::Message& from) { +void MethodOptions::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MethodOptions) GOOGLE_DCHECK_NE(&from, this); const MethodOptions* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.MethodOptions) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.MethodOptions) MergeFrom(*source); @@ -13729,13 +8938,13 @@ void MethodOptions::MergeFrom(const MethodOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodOptions) GOOGLE_DCHECK_NE(&from, this); _extensions_.MergeFrom(from._extensions_); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; uninterpreted_option_.MergeFrom(from.uninterpreted_option_); cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { deprecated_ = from.deprecated_; } @@ -13746,7 +8955,7 @@ void MethodOptions::MergeFrom(const MethodOptions& from) { } } -void MethodOptions::CopyFrom(const ::google::protobuf::Message& from) { +void MethodOptions::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.MethodOptions) if (&from == this) return; Clear(); @@ -13765,312 +8974,181 @@ bool MethodOptions::IsInitialized() const { return false; } - if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(uninterpreted_option_)) return false; return true; } -void MethodOptions::Swap(MethodOptions* other) { - if (other == this) return; - InternalSwap(other); -} void MethodOptions::InternalSwap(MethodOptions* other) { using std::swap; - uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); - swap(deprecated_, other->deprecated_); - swap(idempotency_level_, other->idempotency_level_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); _extensions_.Swap(&other->_extensions_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); + uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(MethodOptions, idempotency_level_) + + sizeof(MethodOptions::idempotency_level_) + - PROTOBUF_FIELD_OFFSET(MethodOptions, deprecated_)>( + reinterpret_cast(&deprecated_), + reinterpret_cast(&other->deprecated_)); } -::google::protobuf::Metadata MethodOptions::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// MethodOptions - -// optional bool deprecated = 33 [default = false]; -bool MethodOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void MethodOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00000001u; -} -void MethodOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00000001u; -} -void MethodOptions::clear_deprecated() { - deprecated_ = false; - clear_has_deprecated(); -} -bool MethodOptions::deprecated() const { - // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.deprecated) - return deprecated_; -} -void MethodOptions::set_deprecated(bool value) { - set_has_deprecated(); - deprecated_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.deprecated) -} - -// optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; -bool MethodOptions::has_idempotency_level() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void MethodOptions::set_has_idempotency_level() { - _has_bits_[0] |= 0x00000002u; -} -void MethodOptions::clear_has_idempotency_level() { - _has_bits_[0] &= ~0x00000002u; -} -void MethodOptions::clear_idempotency_level() { - idempotency_level_ = 0; - clear_has_idempotency_level(); -} -::google::protobuf::MethodOptions_IdempotencyLevel MethodOptions::idempotency_level() const { - // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.idempotency_level) - return static_cast< ::google::protobuf::MethodOptions_IdempotencyLevel >(idempotency_level_); -} -void MethodOptions::set_idempotency_level(::google::protobuf::MethodOptions_IdempotencyLevel value) { - assert(::google::protobuf::MethodOptions_IdempotencyLevel_IsValid(value)); - set_has_idempotency_level(); - idempotency_level_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.idempotency_level) -} - -// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -int MethodOptions::uninterpreted_option_size() const { - return uninterpreted_option_.size(); -} -void MethodOptions::clear_uninterpreted_option() { - uninterpreted_option_.Clear(); -} -const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.MethodOptions.uninterpreted_option) - return uninterpreted_option_.Mutable(index); -} -::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* -MethodOptions::mutable_uninterpreted_option() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option) - return &uninterpreted_option_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& -MethodOptions::uninterpreted_option() const { - // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option) - return uninterpreted_option_; +::PROTOBUF_NAMESPACE_ID::Metadata MethodOptions::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int UninterpretedOption_NamePart::kNamePartFieldNumber; -const int UninterpretedOption_NamePart::kIsExtensionFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -UninterpretedOption_NamePart::UninterpretedOption_NamePart() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class UninterpretedOption_NamePart::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_name_part(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_is_extension(HasBits* has_bits) { + (*has_bits)[0] |= 2u; } + static bool MissingRequiredFields(const HasBits& has_bits) { + return ((has_bits[0] & 0x00000003) ^ 0x00000003) != 0; + } +}; + +UninterpretedOption_NamePart::UninterpretedOption_NamePart(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption.NamePart) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.UninterpretedOption.NamePart) } UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - name_part_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_name_part()) { - name_part_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_part_); + : ::PROTOBUF_NAMESPACE_ID::Message(), + _has_bits_(from._has_bits_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_part_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_name_part()) { + name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name_part(), + GetArena()); } is_extension_ = from.is_extension_; // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption.NamePart) } void UninterpretedOption_NamePart::SharedCtor() { - _cached_size_ = 0; - name_part_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - is_extension_ = false; +name_part_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +is_extension_ = false; } UninterpretedOption_NamePart::~UninterpretedOption_NamePart() { // @@protoc_insertion_point(destructor:google.protobuf.UninterpretedOption.NamePart) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void UninterpretedOption_NamePart::SharedDtor() { - name_part_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + name_part_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } -void UninterpretedOption_NamePart::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void UninterpretedOption_NamePart::ArenaDtor(void* object) { + UninterpretedOption_NamePart* _this = reinterpret_cast< UninterpretedOption_NamePart* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* UninterpretedOption_NamePart::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const UninterpretedOption_NamePart& UninterpretedOption_NamePart::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void UninterpretedOption_NamePart::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -UninterpretedOption_NamePart* UninterpretedOption_NamePart::New(::google::protobuf::Arena* arena) const { - UninterpretedOption_NamePart* n = new UninterpretedOption_NamePart; - if (arena != NULL) { - arena->Own(n); - } - return n; +void UninterpretedOption_NamePart::SetCachedSize(int size) const { + _cached_size_.Set(size); } void UninterpretedOption_NamePart::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption.NamePart) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - if (has_name_part()) { - GOOGLE_DCHECK(!name_part_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*name_part_.UnsafeRawStringPointer())->clear(); + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + name_part_.ClearNonDefaultToEmpty(); } is_extension_ = false; _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool UninterpretedOption_NamePart::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.UninterpretedOption.NamePart) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // required string name_part = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_name_part())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name_part().data(), static_cast(this->name_part().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.UninterpretedOption.NamePart.name_part"); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* UninterpretedOption_NamePart::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // required string name_part = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_name_part(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.UninterpretedOption.NamePart.name_part"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // required bool is_extension = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) { - set_has_is_extension(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &is_extension_))); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + _Internal::set_has_is_extension(&has_bits); + is_extension_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.UninterpretedOption.NamePart) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.UninterpretedOption.NamePart) - return false; -#undef DO_ -} - -void UninterpretedOption_NamePart::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.UninterpretedOption.NamePart) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // required string name_part = 1; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name_part().data(), static_cast(this->name_part().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.UninterpretedOption.NamePart.name_part"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->name_part(), output); - } - - // required bool is_extension = 2; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_extension(), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.UninterpretedOption.NamePart) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* UninterpretedOption_NamePart::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* UninterpretedOption_NamePart::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption.NamePart) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _has_bits_[0]; // required string name_part = 1; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->name_part().data(), static_cast(this->name_part().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name_part().data(), static_cast(this->_internal_name_part().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.UninterpretedOption.NamePart.name_part"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->name_part(), target); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name_part(), target); } // required bool is_extension = 2; if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_extension(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(2, this->_internal_is_extension(), target); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption.NamePart) return target; @@ -14080,14 +9158,14 @@ size_t UninterpretedOption_NamePart::RequiredFieldsByteSizeFallback() const { // @@protoc_insertion_point(required_fields_byte_size_fallback_start:google.protobuf.UninterpretedOption.NamePart) size_t total_size = 0; - if (has_name_part()) { + if (_internal_has_name_part()) { // required string name_part = 1; total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->name_part()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name_part()); } - if (has_is_extension()) { + if (_internal_has_is_extension()) { // required bool is_extension = 2; total_size += 1 + 1; } @@ -14098,16 +9176,11 @@ size_t UninterpretedOption_NamePart::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption.NamePart) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } if (((_has_bits_[0] & 0x00000003) ^ 0x00000003) == 0) { // All required fields are present. // required string name_part = 1; total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->name_part()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name_part()); // required bool is_extension = 2; total_size += 1 + 1; @@ -14115,22 +9188,28 @@ size_t UninterpretedOption_NamePart::ByteSizeLong() const { } else { total_size += RequiredFieldsByteSizeFallback(); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message& from) { +void UninterpretedOption_NamePart::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UninterpretedOption.NamePart) GOOGLE_DCHECK_NE(&from, this); const UninterpretedOption_NamePart* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UninterpretedOption.NamePart) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UninterpretedOption.NamePart) MergeFrom(*source); @@ -14140,15 +9219,14 @@ void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message& void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption.NamePart) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - set_has_name_part(); - name_part_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_part_); + _internal_set_name_part(from._internal_name_part()); } if (cached_has_bits & 0x00000002u) { is_extension_ = from.is_extension_; @@ -14157,7 +9235,7 @@ void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& } } -void UninterpretedOption_NamePart::CopyFrom(const ::google::protobuf::Message& from) { +void UninterpretedOption_NamePart::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UninterpretedOption.NamePart) if (&from == this) return; Clear(); @@ -14172,158 +9250,74 @@ void UninterpretedOption_NamePart::CopyFrom(const UninterpretedOption_NamePart& } bool UninterpretedOption_NamePart::IsInitialized() const { - if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + if (_Internal::MissingRequiredFields(_has_bits_)) return false; return true; } -void UninterpretedOption_NamePart::Swap(UninterpretedOption_NamePart* other) { - if (other == this) return; - InternalSwap(other); -} void UninterpretedOption_NamePart::InternalSwap(UninterpretedOption_NamePart* other) { using std::swap; - name_part_.Swap(&other->name_part_); - swap(is_extension_, other->is_extension_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata UninterpretedOption_NamePart::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// UninterpretedOption_NamePart - -// required string name_part = 1; -bool UninterpretedOption_NamePart::has_name_part() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void UninterpretedOption_NamePart::set_has_name_part() { - _has_bits_[0] |= 0x00000001u; -} -void UninterpretedOption_NamePart::clear_has_name_part() { - _has_bits_[0] &= ~0x00000001u; -} -void UninterpretedOption_NamePart::clear_name_part() { - name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name_part(); -} -const ::std::string& UninterpretedOption_NamePart::name_part() const { - // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.name_part) - return name_part_.GetNoArena(); -} -void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) { - set_has_name_part(); - name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.name_part) -} -#if LANG_CXX11 -void UninterpretedOption_NamePart::set_name_part(::std::string&& value) { - set_has_name_part(); - name_part_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.NamePart.name_part) -} -#endif -void UninterpretedOption_NamePart::set_name_part(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name_part(); - name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.NamePart.name_part) -} -void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) { - set_has_name_part(); - name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part) -} -::std::string* UninterpretedOption_NamePart::mutable_name_part() { - set_has_name_part(); - // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part) - return name_part_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* UninterpretedOption_NamePart::release_name_part() { - // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.NamePart.name_part) - clear_has_name_part(); - return name_part_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) { - if (name_part != NULL) { - set_has_name_part(); - } else { - clear_has_name_part(); - } - name_part_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name_part); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part) + name_part_.Swap(&other->name_part_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + swap(is_extension_, other->is_extension_); } -// required bool is_extension = 2; -bool UninterpretedOption_NamePart::has_is_extension() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void UninterpretedOption_NamePart::set_has_is_extension() { - _has_bits_[0] |= 0x00000002u; -} -void UninterpretedOption_NamePart::clear_has_is_extension() { - _has_bits_[0] &= ~0x00000002u; -} -void UninterpretedOption_NamePart::clear_is_extension() { - is_extension_ = false; - clear_has_is_extension(); -} -bool UninterpretedOption_NamePart::is_extension() const { - // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.is_extension) - return is_extension_; -} -void UninterpretedOption_NamePart::set_is_extension(bool value) { - set_has_is_extension(); - is_extension_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.is_extension) +::PROTOBUF_NAMESPACE_ID::Metadata UninterpretedOption_NamePart::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int UninterpretedOption::kNameFieldNumber; -const int UninterpretedOption::kIdentifierValueFieldNumber; -const int UninterpretedOption::kPositiveIntValueFieldNumber; -const int UninterpretedOption::kNegativeIntValueFieldNumber; -const int UninterpretedOption::kDoubleValueFieldNumber; -const int UninterpretedOption::kStringValueFieldNumber; -const int UninterpretedOption::kAggregateValueFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -UninterpretedOption::UninterpretedOption() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class UninterpretedOption::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_identifier_value(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } + static void set_has_positive_int_value(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } + static void set_has_negative_int_value(HasBits* has_bits) { + (*has_bits)[0] |= 16u; + } + static void set_has_double_value(HasBits* has_bits) { + (*has_bits)[0] |= 32u; + } + static void set_has_string_value(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_aggregate_value(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } +}; + +UninterpretedOption::UninterpretedOption(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + name_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.UninterpretedOption) } UninterpretedOption::UninterpretedOption(const UninterpretedOption& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), _has_bits_(from._has_bits_), - _cached_size_(0), name_(from.name_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - identifier_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_identifier_value()) { - identifier_value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.identifier_value_); - } - string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_string_value()) { - string_value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.string_value_); - } - aggregate_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_aggregate_value()) { - aggregate_value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.aggregate_value_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + identifier_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_identifier_value()) { + identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_identifier_value(), + GetArena()); + } + string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_string_value()) { + string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_string_value(), + GetArena()); + } + aggregate_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_aggregate_value()) { + aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_aggregate_value(), + GetArena()); } ::memcpy(&positive_int_value_, &from.positive_int_value_, static_cast(reinterpret_cast(&double_value_) - @@ -14332,333 +9326,225 @@ UninterpretedOption::UninterpretedOption(const UninterpretedOption& from) } void UninterpretedOption::SharedCtor() { - _cached_size_ = 0; - identifier_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - aggregate_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - ::memset(&positive_int_value_, 0, static_cast( - reinterpret_cast(&double_value_) - - reinterpret_cast(&positive_int_value_)) + sizeof(double_value_)); +identifier_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +aggregate_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&positive_int_value_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&double_value_) - + reinterpret_cast(&positive_int_value_)) + sizeof(double_value_)); } UninterpretedOption::~UninterpretedOption() { // @@protoc_insertion_point(destructor:google.protobuf.UninterpretedOption) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void UninterpretedOption::SharedDtor() { - identifier_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - string_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - aggregate_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + identifier_value_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + string_value_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + aggregate_value_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } -void UninterpretedOption::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* UninterpretedOption::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void UninterpretedOption::ArenaDtor(void* object) { + UninterpretedOption* _this = reinterpret_cast< UninterpretedOption* >(object); + (void)_this; } - -const UninterpretedOption& UninterpretedOption::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void UninterpretedOption::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -UninterpretedOption* UninterpretedOption::New(::google::protobuf::Arena* arena) const { - UninterpretedOption* n = new UninterpretedOption; - if (arena != NULL) { - arena->Own(n); - } - return n; +void UninterpretedOption::SetCachedSize(int size) const { + _cached_size_.Set(size); } void UninterpretedOption::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; name_.Clear(); cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 7u) { + if (cached_has_bits & 0x00000007u) { if (cached_has_bits & 0x00000001u) { - GOOGLE_DCHECK(!identifier_value_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*identifier_value_.UnsafeRawStringPointer())->clear(); + identifier_value_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000002u) { - GOOGLE_DCHECK(!string_value_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*string_value_.UnsafeRawStringPointer())->clear(); + string_value_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000004u) { - GOOGLE_DCHECK(!aggregate_value_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*aggregate_value_.UnsafeRawStringPointer())->clear(); + aggregate_value_.ClearNonDefaultToEmpty(); } } - if (cached_has_bits & 56u) { + if (cached_has_bits & 0x00000038u) { ::memset(&positive_int_value_, 0, static_cast( reinterpret_cast(&double_value_) - reinterpret_cast(&positive_int_value_)) + sizeof(double_value_)); } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool UninterpretedOption::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.UninterpretedOption) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_name())); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* UninterpretedOption::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_name(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr)); + } else goto handle_unusual; + continue; // optional string identifier_value = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_identifier_value())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->identifier_value().data(), static_cast(this->identifier_value().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.UninterpretedOption.identifier_value"); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + auto str = _internal_mutable_identifier_value(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.UninterpretedOption.identifier_value"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional uint64 positive_int_value = 4; - case 4: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(32u /* 32 & 0xFF */)) { - set_has_positive_int_value(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>( - input, &positive_int_value_))); - } else { - goto handle_unusual; - } - break; - } - + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 32)) { + _Internal::set_has_positive_int_value(&has_bits); + positive_int_value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional int64 negative_int_value = 5; - case 5: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(40u /* 40 & 0xFF */)) { - set_has_negative_int_value(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>( - input, &negative_int_value_))); - } else { - goto handle_unusual; - } - break; - } - + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 40)) { + _Internal::set_has_negative_int_value(&has_bits); + negative_int_value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional double double_value = 6; - case 6: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(49u /* 49 & 0xFF */)) { - set_has_double_value(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( - input, &double_value_))); - } else { - goto handle_unusual; - } - break; - } - + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 49)) { + _Internal::set_has_double_value(&has_bits); + double_value_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); + ptr += sizeof(double); + } else goto handle_unusual; + continue; // optional bytes string_value = 7; - case 7: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(58u /* 58 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadBytes( - input, this->mutable_string_value())); - } else { - goto handle_unusual; - } - break; - } - + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 58)) { + auto str = _internal_mutable_string_value(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string aggregate_value = 8; - case 8: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(66u /* 66 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_aggregate_value())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->aggregate_value().data(), static_cast(this->aggregate_value().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.UninterpretedOption.aggregate_value"); - } else { - goto handle_unusual; - } - break; - } - + case 8: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 66)) { + auto str = _internal_mutable_aggregate_value(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.UninterpretedOption.aggregate_value"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.UninterpretedOption) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.UninterpretedOption) - return false; -#undef DO_ -} - -void UninterpretedOption::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.UninterpretedOption) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; - for (unsigned int i = 0, - n = static_cast(this->name_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 2, this->name(static_cast(i)), output); - } - - cached_has_bits = _has_bits_[0]; - // optional string identifier_value = 3; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->identifier_value().data(), static_cast(this->identifier_value().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.UninterpretedOption.identifier_value"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 3, this->identifier_value(), output); - } - - // optional uint64 positive_int_value = 4; - if (cached_has_bits & 0x00000008u) { - ::google::protobuf::internal::WireFormatLite::WriteUInt64(4, this->positive_int_value(), output); - } - - // optional int64 negative_int_value = 5; - if (cached_has_bits & 0x00000010u) { - ::google::protobuf::internal::WireFormatLite::WriteInt64(5, this->negative_int_value(), output); - } - - // optional double double_value = 6; - if (cached_has_bits & 0x00000020u) { - ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->double_value(), output); - } - - // optional bytes string_value = 7; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased( - 7, this->string_value(), output); - } - - // optional string aggregate_value = 8; - if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->aggregate_value().data(), static_cast(this->aggregate_value().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.UninterpretedOption.aggregate_value"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 8, this->aggregate_value(), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.UninterpretedOption) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* UninterpretedOption::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* UninterpretedOption::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; for (unsigned int i = 0, - n = static_cast(this->name_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 2, this->name(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_name_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(2, this->_internal_name(i), target, stream); } cached_has_bits = _has_bits_[0]; // optional string identifier_value = 3; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->identifier_value().data(), static_cast(this->identifier_value().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_identifier_value().data(), static_cast(this->_internal_identifier_value().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.UninterpretedOption.identifier_value"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 3, this->identifier_value(), target); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_identifier_value(), target); } // optional uint64 positive_int_value = 4; if (cached_has_bits & 0x00000008u) { - target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(4, this->positive_int_value(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt64ToArray(4, this->_internal_positive_int_value(), target); } // optional int64 negative_int_value = 5; if (cached_has_bits & 0x00000010u) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(5, this->negative_int_value(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(5, this->_internal_negative_int_value(), target); } // optional double double_value = 6; if (cached_has_bits & 0x00000020u) { - target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->double_value(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteDoubleToArray(6, this->_internal_double_value(), target); } // optional bytes string_value = 7; if (cached_has_bits & 0x00000002u) { - target = - ::google::protobuf::internal::WireFormatLite::WriteBytesToArray( - 7, this->string_value(), target); + target = stream->WriteBytesMaybeAliased( + 7, this->_internal_string_value(), target); } // optional string aggregate_value = 8; if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->aggregate_value().data(), static_cast(this->aggregate_value().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_aggregate_value().data(), static_cast(this->_internal_aggregate_value().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.UninterpretedOption.aggregate_value"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 8, this->aggregate_value(), target); + target = stream->WriteStringMaybeAliased( + 8, this->_internal_aggregate_value(), target); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption) return target; @@ -14668,80 +9554,78 @@ size_t UninterpretedOption::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; - { - unsigned int count = static_cast(this->name_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->name(static_cast(i))); - } + total_size += 1UL * this->_internal_name_size(); + for (const auto& msg : this->name_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - if (_has_bits_[0 / 32] & 63u) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { // optional string identifier_value = 3; - if (has_identifier_value()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->identifier_value()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_identifier_value()); } // optional bytes string_value = 7; - if (has_string_value()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::BytesSize( - this->string_value()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize( + this->_internal_string_value()); } // optional string aggregate_value = 8; - if (has_aggregate_value()) { + if (cached_has_bits & 0x00000004u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->aggregate_value()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_aggregate_value()); } // optional uint64 positive_int_value = 4; - if (has_positive_int_value()) { + if (cached_has_bits & 0x00000008u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt64Size( - this->positive_int_value()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt64Size( + this->_internal_positive_int_value()); } // optional int64 negative_int_value = 5; - if (has_negative_int_value()) { + if (cached_has_bits & 0x00000010u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int64Size( - this->negative_int_value()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int64Size( + this->_internal_negative_int_value()); } // optional double double_value = 6; - if (has_double_value()) { + if (cached_has_bits & 0x00000020u) { total_size += 1 + 8; } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void UninterpretedOption::MergeFrom(const ::google::protobuf::Message& from) { +void UninterpretedOption::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UninterpretedOption) GOOGLE_DCHECK_NE(&from, this); const UninterpretedOption* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.UninterpretedOption) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.UninterpretedOption) MergeFrom(*source); @@ -14751,24 +9635,21 @@ void UninterpretedOption::MergeFrom(const ::google::protobuf::Message& from) { void UninterpretedOption::MergeFrom(const UninterpretedOption& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; name_.MergeFrom(from.name_); cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 63u) { + if (cached_has_bits & 0x0000003fu) { if (cached_has_bits & 0x00000001u) { - set_has_identifier_value(); - identifier_value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.identifier_value_); + _internal_set_identifier_value(from._internal_identifier_value()); } if (cached_has_bits & 0x00000002u) { - set_has_string_value(); - string_value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.string_value_); + _internal_set_string_value(from._internal_string_value()); } if (cached_has_bits & 0x00000004u) { - set_has_aggregate_value(); - aggregate_value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.aggregate_value_); + _internal_set_aggregate_value(from._internal_aggregate_value()); } if (cached_has_bits & 0x00000008u) { positive_int_value_ = from.positive_int_value_; @@ -14783,7 +9664,7 @@ void UninterpretedOption::MergeFrom(const UninterpretedOption& from) { } } -void UninterpretedOption::CopyFrom(const ::google::protobuf::Message& from) { +void UninterpretedOption::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.UninterpretedOption) if (&from == this) return; Clear(); @@ -14798,409 +9679,103 @@ void UninterpretedOption::CopyFrom(const UninterpretedOption& from) { } bool UninterpretedOption::IsInitialized() const { - if (!::google::protobuf::internal::AllAreInitialized(this->name())) return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(name_)) return false; return true; } -void UninterpretedOption::Swap(UninterpretedOption* other) { - if (other == this) return; - InternalSwap(other); -} void UninterpretedOption::InternalSwap(UninterpretedOption* other) { using std::swap; - name_.InternalSwap(&other->name_); - identifier_value_.Swap(&other->identifier_value_); - string_value_.Swap(&other->string_value_); - aggregate_value_.Swap(&other->aggregate_value_); - swap(positive_int_value_, other->positive_int_value_); - swap(negative_int_value_, other->negative_int_value_); - swap(double_value_, other->double_value_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata UninterpretedOption::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// UninterpretedOption - -// repeated .google.protobuf.UninterpretedOption.NamePart name = 2; -int UninterpretedOption::name_size() const { - return name_.size(); -} -void UninterpretedOption::clear_name() { - name_.Clear(); -} -const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.name) - return name_.Get(index); -} -::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.name) - return name_.Mutable(index); -} -::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() { - // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name) - return name_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* -UninterpretedOption::mutable_name() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name) - return &name_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& -UninterpretedOption::name() const { - // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name) - return name_; -} - -// optional string identifier_value = 3; -bool UninterpretedOption::has_identifier_value() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void UninterpretedOption::set_has_identifier_value() { - _has_bits_[0] |= 0x00000001u; -} -void UninterpretedOption::clear_has_identifier_value() { - _has_bits_[0] &= ~0x00000001u; -} -void UninterpretedOption::clear_identifier_value() { - identifier_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_identifier_value(); -} -const ::std::string& UninterpretedOption::identifier_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.identifier_value) - return identifier_value_.GetNoArena(); -} -void UninterpretedOption::set_identifier_value(const ::std::string& value) { - set_has_identifier_value(); - identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.identifier_value) -} -#if LANG_CXX11 -void UninterpretedOption::set_identifier_value(::std::string&& value) { - set_has_identifier_value(); - identifier_value_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.identifier_value) -} -#endif -void UninterpretedOption::set_identifier_value(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_identifier_value(); - identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value) -} -void UninterpretedOption::set_identifier_value(const char* value, size_t size) { - set_has_identifier_value(); - identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value) -} -::std::string* UninterpretedOption::mutable_identifier_value() { - set_has_identifier_value(); - // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value) - return identifier_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* UninterpretedOption::release_identifier_value() { - // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.identifier_value) - clear_has_identifier_value(); - return identifier_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) { - if (identifier_value != NULL) { - set_has_identifier_value(); - } else { - clear_has_identifier_value(); - } - identifier_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), identifier_value); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value) -} - -// optional uint64 positive_int_value = 4; -bool UninterpretedOption::has_positive_int_value() const { - return (_has_bits_[0] & 0x00000008u) != 0; -} -void UninterpretedOption::set_has_positive_int_value() { - _has_bits_[0] |= 0x00000008u; -} -void UninterpretedOption::clear_has_positive_int_value() { - _has_bits_[0] &= ~0x00000008u; -} -void UninterpretedOption::clear_positive_int_value() { - positive_int_value_ = GOOGLE_ULONGLONG(0); - clear_has_positive_int_value(); -} -::google::protobuf::uint64 UninterpretedOption::positive_int_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.positive_int_value) - return positive_int_value_; -} -void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) { - set_has_positive_int_value(); - positive_int_value_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.positive_int_value) -} - -// optional int64 negative_int_value = 5; -bool UninterpretedOption::has_negative_int_value() const { - return (_has_bits_[0] & 0x00000010u) != 0; -} -void UninterpretedOption::set_has_negative_int_value() { - _has_bits_[0] |= 0x00000010u; -} -void UninterpretedOption::clear_has_negative_int_value() { - _has_bits_[0] &= ~0x00000010u; -} -void UninterpretedOption::clear_negative_int_value() { - negative_int_value_ = GOOGLE_LONGLONG(0); - clear_has_negative_int_value(); -} -::google::protobuf::int64 UninterpretedOption::negative_int_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.negative_int_value) - return negative_int_value_; -} -void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) { - set_has_negative_int_value(); - negative_int_value_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.negative_int_value) -} - -// optional double double_value = 6; -bool UninterpretedOption::has_double_value() const { - return (_has_bits_[0] & 0x00000020u) != 0; -} -void UninterpretedOption::set_has_double_value() { - _has_bits_[0] |= 0x00000020u; -} -void UninterpretedOption::clear_has_double_value() { - _has_bits_[0] &= ~0x00000020u; -} -void UninterpretedOption::clear_double_value() { - double_value_ = 0; - clear_has_double_value(); -} -double UninterpretedOption::double_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.double_value) - return double_value_; -} -void UninterpretedOption::set_double_value(double value) { - set_has_double_value(); - double_value_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.double_value) + name_.InternalSwap(&other->name_); + identifier_value_.Swap(&other->identifier_value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + string_value_.Swap(&other->string_value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + aggregate_value_.Swap(&other->aggregate_value_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(UninterpretedOption, double_value_) + + sizeof(UninterpretedOption::double_value_) + - PROTOBUF_FIELD_OFFSET(UninterpretedOption, positive_int_value_)>( + reinterpret_cast(&positive_int_value_), + reinterpret_cast(&other->positive_int_value_)); } -// optional bytes string_value = 7; -bool UninterpretedOption::has_string_value() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void UninterpretedOption::set_has_string_value() { - _has_bits_[0] |= 0x00000002u; -} -void UninterpretedOption::clear_has_string_value() { - _has_bits_[0] &= ~0x00000002u; -} -void UninterpretedOption::clear_string_value() { - string_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_string_value(); -} -const ::std::string& UninterpretedOption::string_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.string_value) - return string_value_.GetNoArena(); -} -void UninterpretedOption::set_string_value(const ::std::string& value) { - set_has_string_value(); - string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.string_value) -} -#if LANG_CXX11 -void UninterpretedOption::set_string_value(::std::string&& value) { - set_has_string_value(); - string_value_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.string_value) -} -#endif -void UninterpretedOption::set_string_value(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_string_value(); - string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value) -} -void UninterpretedOption::set_string_value(const void* value, size_t size) { - set_has_string_value(); - string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value) -} -::std::string* UninterpretedOption::mutable_string_value() { - set_has_string_value(); - // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value) - return string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* UninterpretedOption::release_string_value() { - // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.string_value) - clear_has_string_value(); - return string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void UninterpretedOption::set_allocated_string_value(::std::string* string_value) { - if (string_value != NULL) { - set_has_string_value(); - } else { - clear_has_string_value(); - } - string_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value) -} - -// optional string aggregate_value = 8; -bool UninterpretedOption::has_aggregate_value() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -void UninterpretedOption::set_has_aggregate_value() { - _has_bits_[0] |= 0x00000004u; -} -void UninterpretedOption::clear_has_aggregate_value() { - _has_bits_[0] &= ~0x00000004u; -} -void UninterpretedOption::clear_aggregate_value() { - aggregate_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_aggregate_value(); -} -const ::std::string& UninterpretedOption::aggregate_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.aggregate_value) - return aggregate_value_.GetNoArena(); -} -void UninterpretedOption::set_aggregate_value(const ::std::string& value) { - set_has_aggregate_value(); - aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value) -} -#if LANG_CXX11 -void UninterpretedOption::set_aggregate_value(::std::string&& value) { - set_has_aggregate_value(); - aggregate_value_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.aggregate_value) -} -#endif -void UninterpretedOption::set_aggregate_value(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_aggregate_value(); - aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value) -} -void UninterpretedOption::set_aggregate_value(const char* value, size_t size) { - set_has_aggregate_value(); - aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value) -} -::std::string* UninterpretedOption::mutable_aggregate_value() { - set_has_aggregate_value(); - // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value) - return aggregate_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* UninterpretedOption::release_aggregate_value() { - // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.aggregate_value) - clear_has_aggregate_value(); - return aggregate_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) { - if (aggregate_value != NULL) { - set_has_aggregate_value(); - } else { - clear_has_aggregate_value(); - } - aggregate_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), aggregate_value); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value) +::PROTOBUF_NAMESPACE_ID::Metadata UninterpretedOption::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int SourceCodeInfo_Location::kPathFieldNumber; -const int SourceCodeInfo_Location::kSpanFieldNumber; -const int SourceCodeInfo_Location::kLeadingCommentsFieldNumber; -const int SourceCodeInfo_Location::kTrailingCommentsFieldNumber; -const int SourceCodeInfo_Location::kLeadingDetachedCommentsFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -SourceCodeInfo_Location::SourceCodeInfo_Location() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class SourceCodeInfo_Location::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_leading_comments(HasBits* has_bits) { + (*has_bits)[0] |= 1u; } + static void set_has_trailing_comments(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +SourceCodeInfo_Location::SourceCodeInfo_Location(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + path_(arena), + span_(arena), + leading_detached_comments_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo.Location) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.SourceCodeInfo.Location) } SourceCodeInfo_Location::SourceCodeInfo_Location(const SourceCodeInfo_Location& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), _has_bits_(from._has_bits_), - _cached_size_(0), path_(from.path_), span_(from.span_), leading_detached_comments_(from.leading_detached_comments_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - leading_comments_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_leading_comments()) { - leading_comments_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.leading_comments_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + leading_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_leading_comments()) { + leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_leading_comments(), + GetArena()); } - trailing_comments_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_trailing_comments()) { - trailing_comments_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.trailing_comments_); + trailing_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_trailing_comments()) { + trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_trailing_comments(), + GetArena()); } // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo.Location) } void SourceCodeInfo_Location::SharedCtor() { - _cached_size_ = 0; - leading_comments_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - trailing_comments_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +leading_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +trailing_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } SourceCodeInfo_Location::~SourceCodeInfo_Location() { // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo.Location) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void SourceCodeInfo_Location::SharedDtor() { - leading_comments_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - trailing_comments_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + leading_comments_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + trailing_comments_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } -void SourceCodeInfo_Location::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void SourceCodeInfo_Location::ArenaDtor(void* object) { + SourceCodeInfo_Location* _this = reinterpret_cast< SourceCodeInfo_Location* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* SourceCodeInfo_Location::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const SourceCodeInfo_Location& SourceCodeInfo_Location::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void SourceCodeInfo_Location::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -SourceCodeInfo_Location* SourceCodeInfo_Location::New(::google::protobuf::Arena* arena) const { - SourceCodeInfo_Location* n = new SourceCodeInfo_Location; - if (arena != NULL) { - arena->Own(n); - } - return n; +void SourceCodeInfo_Location::SetCachedSize(int size) const { + _cached_size_.Set(size); } void SourceCodeInfo_Location::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo.Location) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; @@ -15208,272 +9783,165 @@ void SourceCodeInfo_Location::Clear() { span_.Clear(); leading_detached_comments_.Clear(); cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - GOOGLE_DCHECK(!leading_comments_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*leading_comments_.UnsafeRawStringPointer())->clear(); + leading_comments_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000002u) { - GOOGLE_DCHECK(!trailing_comments_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*trailing_comments_.UnsafeRawStringPointer())->clear(); + trailing_comments_.ClearNonDefaultToEmpty(); } } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool SourceCodeInfo_Location::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.SourceCodeInfo.Location) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // repeated int32 path = 1 [packed = true]; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, this->mutable_path()))); - } else if ( - static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { - DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - 1, 10u, input, this->mutable_path()))); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* SourceCodeInfo_Location::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // repeated int32 path = 1 [packed = true]; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_path(), ptr, ctx); + CHK_(ptr); + } else if (static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8) { + _internal_add_path(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr)); + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated int32 span = 2 [packed = true]; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, this->mutable_span()))); - } else if ( - static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) { - DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - 1, 18u, input, this->mutable_span()))); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_span(), ptr, ctx); + CHK_(ptr); + } else if (static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16) { + _internal_add_span(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr)); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string leading_comments = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_leading_comments())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->leading_comments().data(), static_cast(this->leading_comments().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.SourceCodeInfo.Location.leading_comments"); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + auto str = _internal_mutable_leading_comments(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.SourceCodeInfo.Location.leading_comments"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string trailing_comments = 4; - case 4: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_trailing_comments())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->trailing_comments().data(), static_cast(this->trailing_comments().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.SourceCodeInfo.Location.trailing_comments"); - } else { - goto handle_unusual; - } - break; - } - + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + auto str = _internal_mutable_trailing_comments(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.SourceCodeInfo.Location.trailing_comments"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // repeated string leading_detached_comments = 6; - case 6: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->add_leading_detached_comments())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->leading_detached_comments(this->leading_detached_comments_size() - 1).data(), - static_cast(this->leading_detached_comments(this->leading_detached_comments_size() - 1).length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"); - } else { - goto handle_unusual; - } - break; - } - + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 50)) { + ptr -= 1; + do { + ptr += 1; + auto str = _internal_add_leading_detached_comments(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"); + #endif // !NDEBUG + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.SourceCodeInfo.Location) - return true; -failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.SourceCodeInfo.Location) - return false; -#undef DO_ -} - -void SourceCodeInfo_Location::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.SourceCodeInfo.Location) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // repeated int32 path = 1 [packed = true]; - if (this->path_size() > 0) { - ::google::protobuf::internal::WireFormatLite::WriteTag(1, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(static_cast< ::google::protobuf::uint32>( - _path_cached_byte_size_)); - } - for (int i = 0, n = this->path_size(); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag( - this->path(i), output); - } - - // repeated int32 span = 2 [packed = true]; - if (this->span_size() > 0) { - ::google::protobuf::internal::WireFormatLite::WriteTag(2, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(static_cast< ::google::protobuf::uint32>( - _span_cached_byte_size_)); - } - for (int i = 0, n = this->span_size(); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag( - this->span(i), output); - } - - cached_has_bits = _has_bits_[0]; - // optional string leading_comments = 3; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->leading_comments().data(), static_cast(this->leading_comments().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.SourceCodeInfo.Location.leading_comments"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 3, this->leading_comments(), output); - } - - // optional string trailing_comments = 4; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->trailing_comments().data(), static_cast(this->trailing_comments().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.SourceCodeInfo.Location.trailing_comments"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 4, this->trailing_comments(), output); - } - - // repeated string leading_detached_comments = 6; - for (int i = 0, n = this->leading_detached_comments_size(); i < n; i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->leading_detached_comments(i).data(), static_cast(this->leading_detached_comments(i).length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"); - ::google::protobuf::internal::WireFormatLite::WriteString( - 6, this->leading_detached_comments(i), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.SourceCodeInfo.Location) + _has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* SourceCodeInfo_Location::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* SourceCodeInfo_Location::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo.Location) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // repeated int32 path = 1 [packed = true]; - if (this->path_size() > 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( - 1, - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, - target); - target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( - static_cast< ::google::protobuf::uint32>( - _path_cached_byte_size_), target); - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32NoTagToArray(this->path_, target); + { + int byte_size = _path_cached_byte_size_.load(std::memory_order_relaxed); + if (byte_size > 0) { + target = stream->WriteInt32Packed( + 1, _internal_path(), byte_size, target); + } } // repeated int32 span = 2 [packed = true]; - if (this->span_size() > 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( - 2, - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, - target); - target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( - static_cast< ::google::protobuf::uint32>( - _span_cached_byte_size_), target); - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32NoTagToArray(this->span_, target); + { + int byte_size = _span_cached_byte_size_.load(std::memory_order_relaxed); + if (byte_size > 0) { + target = stream->WriteInt32Packed( + 2, _internal_span(), byte_size, target); + } } cached_has_bits = _has_bits_[0]; // optional string leading_comments = 3; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->leading_comments().data(), static_cast(this->leading_comments().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_leading_comments().data(), static_cast(this->_internal_leading_comments().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.SourceCodeInfo.Location.leading_comments"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 3, this->leading_comments(), target); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_leading_comments(), target); } // optional string trailing_comments = 4; if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->trailing_comments().data(), static_cast(this->trailing_comments().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_trailing_comments().data(), static_cast(this->_internal_trailing_comments().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.SourceCodeInfo.Location.trailing_comments"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 4, this->trailing_comments(), target); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_trailing_comments(), target); } // repeated string leading_detached_comments = 6; - for (int i = 0, n = this->leading_detached_comments_size(); i < n; i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->leading_detached_comments(i).data(), static_cast(this->leading_detached_comments(i).length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + for (int i = 0, n = this->_internal_leading_detached_comments_size(); i < n; i++) { + const auto& s = this->_internal_leading_detached_comments(i); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + s.data(), static_cast(s.length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"); - target = ::google::protobuf::internal::WireFormatLite:: - WriteStringToArray(6, this->leading_detached_comments(i), target); + target = stream->WriteString(6, s, target); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo.Location) return target; @@ -15483,83 +9951,83 @@ size_t SourceCodeInfo_Location::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo.Location) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated int32 path = 1 [packed = true]; { - size_t data_size = ::google::protobuf::internal::WireFormatLite:: + size_t data_size = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: Int32Size(this->path_); if (data_size > 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - static_cast< ::google::protobuf::int32>(data_size)); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + static_cast<::PROTOBUF_NAMESPACE_ID::int32>(data_size)); } - int cached_size = ::google::protobuf::internal::ToCachedSize(data_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _path_cached_byte_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(data_size); + _path_cached_byte_size_.store(cached_size, + std::memory_order_relaxed); total_size += data_size; } // repeated int32 span = 2 [packed = true]; { - size_t data_size = ::google::protobuf::internal::WireFormatLite:: + size_t data_size = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: Int32Size(this->span_); if (data_size > 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - static_cast< ::google::protobuf::int32>(data_size)); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + static_cast<::PROTOBUF_NAMESPACE_ID::int32>(data_size)); } - int cached_size = ::google::protobuf::internal::ToCachedSize(data_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _span_cached_byte_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(data_size); + _span_cached_byte_size_.store(cached_size, + std::memory_order_relaxed); total_size += data_size; } // repeated string leading_detached_comments = 6; total_size += 1 * - ::google::protobuf::internal::FromIntSize(this->leading_detached_comments_size()); - for (int i = 0, n = this->leading_detached_comments_size(); i < n; i++) { - total_size += ::google::protobuf::internal::WireFormatLite::StringSize( - this->leading_detached_comments(i)); + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(leading_detached_comments_.size()); + for (int i = 0, n = leading_detached_comments_.size(); i < n; i++) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + leading_detached_comments_.Get(i)); } - if (_has_bits_[0 / 32] & 3u) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000003u) { // optional string leading_comments = 3; - if (has_leading_comments()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->leading_comments()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_leading_comments()); } // optional string trailing_comments = 4; - if (has_trailing_comments()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->trailing_comments()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_trailing_comments()); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) { +void SourceCodeInfo_Location::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceCodeInfo.Location) GOOGLE_DCHECK_NE(&from, this); const SourceCodeInfo_Location* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceCodeInfo.Location) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceCodeInfo.Location) MergeFrom(*source); @@ -15569,27 +10037,25 @@ void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo.Location) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; path_.MergeFrom(from.path_); span_.MergeFrom(from.span_); leading_detached_comments_.MergeFrom(from.leading_detached_comments_); cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - set_has_leading_comments(); - leading_comments_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.leading_comments_); + _internal_set_leading_comments(from._internal_leading_comments()); } if (cached_has_bits & 0x00000002u) { - set_has_trailing_comments(); - trailing_comments_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.trailing_comments_); + _internal_set_trailing_comments(from._internal_trailing_comments()); } } } -void SourceCodeInfo_Location::CopyFrom(const ::google::protobuf::Message& from) { +void SourceCodeInfo_Location::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceCodeInfo.Location) if (&from == this) return; Clear(); @@ -15607,437 +10073,133 @@ bool SourceCodeInfo_Location::IsInitialized() const { return true; } -void SourceCodeInfo_Location::Swap(SourceCodeInfo_Location* other) { - if (other == this) return; - InternalSwap(other); -} void SourceCodeInfo_Location::InternalSwap(SourceCodeInfo_Location* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); path_.InternalSwap(&other->path_); span_.InternalSwap(&other->span_); leading_detached_comments_.InternalSwap(&other->leading_detached_comments_); - leading_comments_.Swap(&other->leading_comments_); - trailing_comments_.Swap(&other->trailing_comments_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata SourceCodeInfo_Location::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// SourceCodeInfo_Location - -// repeated int32 path = 1 [packed = true]; -int SourceCodeInfo_Location::path_size() const { - return path_.size(); -} -void SourceCodeInfo_Location::clear_path() { - path_.Clear(); -} -::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.path) - return path_.Get(index); -} -void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) { - path_.Set(index, value); - // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.path) -} -void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) { - path_.Add(value); - // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.path) -} -const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& -SourceCodeInfo_Location::path() const { - // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.path) - return path_; -} -::google::protobuf::RepeatedField< ::google::protobuf::int32 >* -SourceCodeInfo_Location::mutable_path() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.path) - return &path_; -} - -// repeated int32 span = 2 [packed = true]; -int SourceCodeInfo_Location::span_size() const { - return span_.size(); -} -void SourceCodeInfo_Location::clear_span() { - span_.Clear(); -} -::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.span) - return span_.Get(index); -} -void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) { - span_.Set(index, value); - // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.span) -} -void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) { - span_.Add(value); - // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.span) -} -const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& -SourceCodeInfo_Location::span() const { - // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.span) - return span_; -} -::google::protobuf::RepeatedField< ::google::protobuf::int32 >* -SourceCodeInfo_Location::mutable_span() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.span) - return &span_; -} - -// optional string leading_comments = 3; -bool SourceCodeInfo_Location::has_leading_comments() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void SourceCodeInfo_Location::set_has_leading_comments() { - _has_bits_[0] |= 0x00000001u; -} -void SourceCodeInfo_Location::clear_has_leading_comments() { - _has_bits_[0] &= ~0x00000001u; -} -void SourceCodeInfo_Location::clear_leading_comments() { - leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_leading_comments(); -} -const ::std::string& SourceCodeInfo_Location::leading_comments() const { - // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_comments) - return leading_comments_.GetNoArena(); -} -void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) { - set_has_leading_comments(); - leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments) -} -#if LANG_CXX11 -void SourceCodeInfo_Location::set_leading_comments(::std::string&& value) { - set_has_leading_comments(); - leading_comments_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceCodeInfo.Location.leading_comments) -} -#endif -void SourceCodeInfo_Location::set_leading_comments(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_leading_comments(); - leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_comments) -} -void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) { - set_has_leading_comments(); - leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments) -} -::std::string* SourceCodeInfo_Location::mutable_leading_comments() { - set_has_leading_comments(); - // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments) - return leading_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* SourceCodeInfo_Location::release_leading_comments() { - // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.leading_comments) - clear_has_leading_comments(); - return leading_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) { - if (leading_comments != NULL) { - set_has_leading_comments(); - } else { - clear_has_leading_comments(); - } - leading_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), leading_comments); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments) -} - -// optional string trailing_comments = 4; -bool SourceCodeInfo_Location::has_trailing_comments() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void SourceCodeInfo_Location::set_has_trailing_comments() { - _has_bits_[0] |= 0x00000002u; -} -void SourceCodeInfo_Location::clear_has_trailing_comments() { - _has_bits_[0] &= ~0x00000002u; -} -void SourceCodeInfo_Location::clear_trailing_comments() { - trailing_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_trailing_comments(); -} -const ::std::string& SourceCodeInfo_Location::trailing_comments() const { - // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.trailing_comments) - return trailing_comments_.GetNoArena(); -} -void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) { - set_has_trailing_comments(); - trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments) -} -#if LANG_CXX11 -void SourceCodeInfo_Location::set_trailing_comments(::std::string&& value) { - set_has_trailing_comments(); - trailing_comments_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceCodeInfo.Location.trailing_comments) -} -#endif -void SourceCodeInfo_Location::set_trailing_comments(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_trailing_comments(); - trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.trailing_comments) -} -void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) { - set_has_trailing_comments(); - trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments) -} -::std::string* SourceCodeInfo_Location::mutable_trailing_comments() { - set_has_trailing_comments(); - // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments) - return trailing_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* SourceCodeInfo_Location::release_trailing_comments() { - // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.trailing_comments) - clear_has_trailing_comments(); - return trailing_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) { - if (trailing_comments != NULL) { - set_has_trailing_comments(); - } else { - clear_has_trailing_comments(); - } - trailing_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), trailing_comments); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments) + leading_comments_.Swap(&other->leading_comments_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + trailing_comments_.Swap(&other->trailing_comments_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -// repeated string leading_detached_comments = 6; -int SourceCodeInfo_Location::leading_detached_comments_size() const { - return leading_detached_comments_.size(); -} -void SourceCodeInfo_Location::clear_leading_detached_comments() { - leading_detached_comments_.Clear(); -} -const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) - return leading_detached_comments_.Get(index); -} -::std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) - return leading_detached_comments_.Mutable(index); -} -void SourceCodeInfo_Location::set_leading_detached_comments(int index, const ::std::string& value) { - // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) - leading_detached_comments_.Mutable(index)->assign(value); -} -#if LANG_CXX11 -void SourceCodeInfo_Location::set_leading_detached_comments(int index, ::std::string&& value) { - // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) - leading_detached_comments_.Mutable(index)->assign(std::move(value)); -} -#endif -void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) { - GOOGLE_DCHECK(value != NULL); - leading_detached_comments_.Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) -} -void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) { - leading_detached_comments_.Mutable(index)->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) -} -::std::string* SourceCodeInfo_Location::add_leading_detached_comments() { - // @@protoc_insertion_point(field_add_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) - return leading_detached_comments_.Add(); -} -void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) { - leading_detached_comments_.Add()->assign(value); - // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) -} -#if LANG_CXX11 -void SourceCodeInfo_Location::add_leading_detached_comments(::std::string&& value) { - leading_detached_comments_.Add(std::move(value)); - // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) -} -#endif -void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) { - GOOGLE_DCHECK(value != NULL); - leading_detached_comments_.Add()->assign(value); - // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) -} -void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) { - leading_detached_comments_.Add()->assign(reinterpret_cast(value), size); - // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) -} -const ::google::protobuf::RepeatedPtrField< ::std::string>& -SourceCodeInfo_Location::leading_detached_comments() const { - // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) - return leading_detached_comments_; -} -::google::protobuf::RepeatedPtrField< ::std::string>* -SourceCodeInfo_Location::mutable_leading_detached_comments() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) - return &leading_detached_comments_; +::PROTOBUF_NAMESPACE_ID::Metadata SourceCodeInfo_Location::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int SourceCodeInfo::kLocationFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +class SourceCodeInfo::_Internal { + public: +}; -SourceCodeInfo::SourceCodeInfo() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - } +SourceCodeInfo::SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + location_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.SourceCodeInfo) } SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0), + : ::PROTOBUF_NAMESPACE_ID::Message(), location_(from.location_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo) } void SourceCodeInfo::SharedCtor() { - _cached_size_ = 0; } SourceCodeInfo::~SourceCodeInfo() { // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void SourceCodeInfo::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); } -void SourceCodeInfo::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void SourceCodeInfo::ArenaDtor(void* object) { + SourceCodeInfo* _this = reinterpret_cast< SourceCodeInfo* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* SourceCodeInfo::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void SourceCodeInfo::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -const SourceCodeInfo& SourceCodeInfo::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -SourceCodeInfo* SourceCodeInfo::New(::google::protobuf::Arena* arena) const { - SourceCodeInfo* n = new SourceCodeInfo; - if (arena != NULL) { - arena->Own(n); - } - return n; +void SourceCodeInfo::SetCachedSize(int size) const { + _cached_size_.Set(size); } void SourceCodeInfo::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; location_.Clear(); - _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool SourceCodeInfo::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.SourceCodeInfo) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // repeated .google.protobuf.SourceCodeInfo.Location location = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_location())); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* SourceCodeInfo::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_location(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.SourceCodeInfo) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.SourceCodeInfo) - return false; -#undef DO_ -} - -void SourceCodeInfo::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.SourceCodeInfo) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // repeated .google.protobuf.SourceCodeInfo.Location location = 1; - for (unsigned int i = 0, - n = static_cast(this->location_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 1, this->location(static_cast(i)), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.SourceCodeInfo) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* SourceCodeInfo::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* SourceCodeInfo::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // repeated .google.protobuf.SourceCodeInfo.Location location = 1; for (unsigned int i = 0, - n = static_cast(this->location_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 1, this->location(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_location_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(1, this->_internal_location(i), target, stream); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo) return target; @@ -16047,38 +10209,35 @@ size_t SourceCodeInfo::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; - { - unsigned int count = static_cast(this->location_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->location(static_cast(i))); - } + total_size += 1UL * this->_internal_location_size(); + for (const auto& msg : this->location_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) { +void SourceCodeInfo::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceCodeInfo) GOOGLE_DCHECK_NE(&from, this); const SourceCodeInfo* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceCodeInfo) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceCodeInfo) MergeFrom(*source); @@ -16088,14 +10247,14 @@ void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) { void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; location_.MergeFrom(from.location_); } -void SourceCodeInfo::CopyFrom(const ::google::protobuf::Message& from) { +void SourceCodeInfo::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceCodeInfo) if (&from == this) return; Clear(); @@ -16113,85 +10272,49 @@ bool SourceCodeInfo::IsInitialized() const { return true; } -void SourceCodeInfo::Swap(SourceCodeInfo* other) { - if (other == this) return; - InternalSwap(other); -} void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); location_.InternalSwap(&other->location_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata SourceCodeInfo::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// SourceCodeInfo - -// repeated .google.protobuf.SourceCodeInfo.Location location = 1; -int SourceCodeInfo::location_size() const { - return location_.size(); -} -void SourceCodeInfo::clear_location() { - location_.Clear(); -} -const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.location) - return location_.Get(index); -} -::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.location) - return location_.Mutable(index); -} -::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() { - // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location) - return location_.Add(); -} -::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* -SourceCodeInfo::mutable_location() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location) - return &location_; -} -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& -SourceCodeInfo::location() const { - // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location) - return location_; +::PROTOBUF_NAMESPACE_ID::Metadata SourceCodeInfo::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int GeneratedCodeInfo_Annotation::kPathFieldNumber; -const int GeneratedCodeInfo_Annotation::kSourceFileFieldNumber; -const int GeneratedCodeInfo_Annotation::kBeginFieldNumber; -const int GeneratedCodeInfo_Annotation::kEndFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); +class GeneratedCodeInfo_Annotation::_Internal { + public: + using HasBits = decltype(std::declval()._has_bits_); + static void set_has_source_file(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_begin(HasBits* has_bits) { + (*has_bits)[0] |= 2u; } + static void set_has_end(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } +}; + +GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + path_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.GeneratedCodeInfo.Annotation) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.GeneratedCodeInfo.Annotation) } GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(const GeneratedCodeInfo_Annotation& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), + : ::PROTOBUF_NAMESPACE_ID::Message(), _has_bits_(from._has_bits_), - _cached_size_(0), path_(from.path_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - source_file_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.has_source_file()) { - source_file_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.source_file_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + source_file_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (from._internal_has_source_file()) { + source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_source_file(), + GetArena()); } ::memcpy(&begin_, &from.begin_, static_cast(reinterpret_cast(&end_) - @@ -16200,249 +10323,163 @@ GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(const GeneratedCodeIn } void GeneratedCodeInfo_Annotation::SharedCtor() { - _cached_size_ = 0; - source_file_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - ::memset(&begin_, 0, static_cast( - reinterpret_cast(&end_) - - reinterpret_cast(&begin_)) + sizeof(end_)); +source_file_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&begin_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&end_) - + reinterpret_cast(&begin_)) + sizeof(end_)); } GeneratedCodeInfo_Annotation::~GeneratedCodeInfo_Annotation() { // @@protoc_insertion_point(destructor:google.protobuf.GeneratedCodeInfo.Annotation) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void GeneratedCodeInfo_Annotation::SharedDtor() { - source_file_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + source_file_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } -void GeneratedCodeInfo_Annotation::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* GeneratedCodeInfo_Annotation::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void GeneratedCodeInfo_Annotation::ArenaDtor(void* object) { + GeneratedCodeInfo_Annotation* _this = reinterpret_cast< GeneratedCodeInfo_Annotation* >(object); + (void)_this; } - -const GeneratedCodeInfo_Annotation& GeneratedCodeInfo_Annotation::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); +void GeneratedCodeInfo_Annotation::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -GeneratedCodeInfo_Annotation* GeneratedCodeInfo_Annotation::New(::google::protobuf::Arena* arena) const { - GeneratedCodeInfo_Annotation* n = new GeneratedCodeInfo_Annotation; - if (arena != NULL) { - arena->Own(n); - } - return n; +void GeneratedCodeInfo_Annotation::SetCachedSize(int size) const { + _cached_size_.Set(size); } void GeneratedCodeInfo_Annotation::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo.Annotation) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; path_.Clear(); - if (has_source_file()) { - GOOGLE_DCHECK(!source_file_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited())); - (*source_file_.UnsafeRawStringPointer())->clear(); - } cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 6u) { + if (cached_has_bits & 0x00000001u) { + source_file_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000006u) { ::memset(&begin_, 0, static_cast( reinterpret_cast(&end_) - reinterpret_cast(&begin_)) + sizeof(end_)); } _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool GeneratedCodeInfo_Annotation::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.GeneratedCodeInfo.Annotation) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // repeated int32 path = 1 [packed = true]; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, this->mutable_path()))); - } else if ( - static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { - DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - 1, 10u, input, this->mutable_path()))); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* GeneratedCodeInfo_Annotation::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // repeated int32 path = 1 [packed = true]; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_path(), ptr, ctx); + CHK_(ptr); + } else if (static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8) { + _internal_add_path(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr)); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional string source_file = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_source_file())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->source_file().data(), static_cast(this->source_file().length()), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.GeneratedCodeInfo.Annotation.source_file"); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + auto str = _internal_mutable_source_file(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + #ifndef NDEBUG + ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.GeneratedCodeInfo.Annotation.source_file"); + #endif // !NDEBUG + CHK_(ptr); + } else goto handle_unusual; + continue; // optional int32 begin = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) { - set_has_begin(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, &begin_))); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + _Internal::set_has_begin(&has_bits); + begin_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // optional int32 end = 4; - case 4: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(32u /* 32 & 0xFF */)) { - set_has_end(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, &end_))); - } else { - goto handle_unusual; - } - break; - } - + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 32)) { + _Internal::set_has_end(&has_bits); + end_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.GeneratedCodeInfo.Annotation) - return true; + _has_bits_.Or(has_bits); + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.GeneratedCodeInfo.Annotation) - return false; -#undef DO_ -} - -void GeneratedCodeInfo_Annotation::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.GeneratedCodeInfo.Annotation) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // repeated int32 path = 1 [packed = true]; - if (this->path_size() > 0) { - ::google::protobuf::internal::WireFormatLite::WriteTag(1, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(static_cast< ::google::protobuf::uint32>( - _path_cached_byte_size_)); - } - for (int i = 0, n = this->path_size(); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag( - this->path(i), output); - } - - cached_has_bits = _has_bits_[0]; - // optional string source_file = 2; - if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->source_file().data(), static_cast(this->source_file().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.GeneratedCodeInfo.Annotation.source_file"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 2, this->source_file(), output); - } - - // optional int32 begin = 3; - if (cached_has_bits & 0x00000002u) { - ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->begin(), output); - } - - // optional int32 end = 4; - if (cached_has_bits & 0x00000004u) { - ::google::protobuf::internal::WireFormatLite::WriteInt32(4, this->end(), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.GeneratedCodeInfo.Annotation) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* GeneratedCodeInfo_Annotation::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* GeneratedCodeInfo_Annotation::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo.Annotation) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // repeated int32 path = 1 [packed = true]; - if (this->path_size() > 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( - 1, - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, - target); - target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( - static_cast< ::google::protobuf::uint32>( - _path_cached_byte_size_), target); - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32NoTagToArray(this->path_, target); + { + int byte_size = _path_cached_byte_size_.load(std::memory_order_relaxed); + if (byte_size > 0) { + target = stream->WriteInt32Packed( + 1, _internal_path(), byte_size, target); + } } cached_has_bits = _has_bits_[0]; // optional string source_file = 2; if (cached_has_bits & 0x00000001u) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->source_file().data(), static_cast(this->source_file().length()), - ::google::protobuf::internal::WireFormat::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_source_file().data(), static_cast(this->_internal_source_file().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, "google.protobuf.GeneratedCodeInfo.Annotation.source_file"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 2, this->source_file(), target); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_source_file(), target); } // optional int32 begin = 3; if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->begin(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_begin(), target); } // optional int32 end = 4; if (cached_has_bits & 0x00000004u) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(4, this->end(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(4, this->_internal_end(), target); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.GeneratedCodeInfo.Annotation) return target; @@ -16452,66 +10489,67 @@ size_t GeneratedCodeInfo_Annotation::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo.Annotation) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated int32 path = 1 [packed = true]; { - size_t data_size = ::google::protobuf::internal::WireFormatLite:: + size_t data_size = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: Int32Size(this->path_); if (data_size > 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - static_cast< ::google::protobuf::int32>(data_size)); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + static_cast<::PROTOBUF_NAMESPACE_ID::int32>(data_size)); } - int cached_size = ::google::protobuf::internal::ToCachedSize(data_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _path_cached_byte_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(data_size); + _path_cached_byte_size_.store(cached_size, + std::memory_order_relaxed); total_size += data_size; } - if (_has_bits_[0 / 32] & 7u) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000007u) { // optional string source_file = 2; - if (has_source_file()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->source_file()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_source_file()); } // optional int32 begin = 3; - if (has_begin()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - this->begin()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_begin()); } // optional int32 end = 4; - if (has_end()) { + if (cached_has_bits & 0x00000004u) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - this->end()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_end()); } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void GeneratedCodeInfo_Annotation::MergeFrom(const ::google::protobuf::Message& from) { +void GeneratedCodeInfo_Annotation::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation) GOOGLE_DCHECK_NE(&from, this); const GeneratedCodeInfo_Annotation* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.GeneratedCodeInfo.Annotation) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.GeneratedCodeInfo.Annotation) MergeFrom(*source); @@ -16521,16 +10559,15 @@ void GeneratedCodeInfo_Annotation::MergeFrom(const ::google::protobuf::Message& void GeneratedCodeInfo_Annotation::MergeFrom(const GeneratedCodeInfo_Annotation& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; path_.MergeFrom(from.path_); cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 7u) { + if (cached_has_bits & 0x00000007u) { if (cached_has_bits & 0x00000001u) { - set_has_source_file(); - source_file_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.source_file_); + _internal_set_source_file(from._internal_source_file()); } if (cached_has_bits & 0x00000002u) { begin_ = from.begin_; @@ -16542,7 +10579,7 @@ void GeneratedCodeInfo_Annotation::MergeFrom(const GeneratedCodeInfo_Annotation& } } -void GeneratedCodeInfo_Annotation::CopyFrom(const ::google::protobuf::Message& from) { +void GeneratedCodeInfo_Annotation::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.GeneratedCodeInfo.Annotation) if (&from == this) return; Clear(); @@ -16560,322 +10597,136 @@ bool GeneratedCodeInfo_Annotation::IsInitialized() const { return true; } -void GeneratedCodeInfo_Annotation::Swap(GeneratedCodeInfo_Annotation* other) { - if (other == this) return; - InternalSwap(other); -} void GeneratedCodeInfo_Annotation::InternalSwap(GeneratedCodeInfo_Annotation* other) { using std::swap; - path_.InternalSwap(&other->path_); - source_file_.Swap(&other->source_file_); - swap(begin_, other->begin_); - swap(end_, other->end_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata GeneratedCodeInfo_Annotation::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// GeneratedCodeInfo_Annotation - -// repeated int32 path = 1 [packed = true]; -int GeneratedCodeInfo_Annotation::path_size() const { - return path_.size(); -} -void GeneratedCodeInfo_Annotation::clear_path() { - path_.Clear(); -} -::google::protobuf::int32 GeneratedCodeInfo_Annotation::path(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.path) - return path_.Get(index); -} -void GeneratedCodeInfo_Annotation::set_path(int index, ::google::protobuf::int32 value) { - path_.Set(index, value); - // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.path) -} -void GeneratedCodeInfo_Annotation::add_path(::google::protobuf::int32 value) { - path_.Add(value); - // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.Annotation.path) -} -const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& -GeneratedCodeInfo_Annotation::path() const { - // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.Annotation.path) - return path_; -} -::google::protobuf::RepeatedField< ::google::protobuf::int32 >* -GeneratedCodeInfo_Annotation::mutable_path() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.Annotation.path) - return &path_; -} - -// optional string source_file = 2; -bool GeneratedCodeInfo_Annotation::has_source_file() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -void GeneratedCodeInfo_Annotation::set_has_source_file() { - _has_bits_[0] |= 0x00000001u; -} -void GeneratedCodeInfo_Annotation::clear_has_source_file() { - _has_bits_[0] &= ~0x00000001u; -} -void GeneratedCodeInfo_Annotation::clear_source_file() { - source_file_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_source_file(); -} -const ::std::string& GeneratedCodeInfo_Annotation::source_file() const { - // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.source_file) - return source_file_.GetNoArena(); -} -void GeneratedCodeInfo_Annotation::set_source_file(const ::std::string& value) { - set_has_source_file(); - source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.source_file) -} -#if LANG_CXX11 -void GeneratedCodeInfo_Annotation::set_source_file(::std::string&& value) { - set_has_source_file(); - source_file_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.GeneratedCodeInfo.Annotation.source_file) -} -#endif -void GeneratedCodeInfo_Annotation::set_source_file(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_source_file(); - source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.GeneratedCodeInfo.Annotation.source_file) -} -void GeneratedCodeInfo_Annotation::set_source_file(const char* value, size_t size) { - set_has_source_file(); - source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.GeneratedCodeInfo.Annotation.source_file) -} -::std::string* GeneratedCodeInfo_Annotation::mutable_source_file() { - set_has_source_file(); - // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.Annotation.source_file) - return source_file_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* GeneratedCodeInfo_Annotation::release_source_file() { - // @@protoc_insertion_point(field_release:google.protobuf.GeneratedCodeInfo.Annotation.source_file) - clear_has_source_file(); - return source_file_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void GeneratedCodeInfo_Annotation::set_allocated_source_file(::std::string* source_file) { - if (source_file != NULL) { - set_has_source_file(); - } else { - clear_has_source_file(); - } - source_file_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), source_file); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.GeneratedCodeInfo.Annotation.source_file) -} - -// optional int32 begin = 3; -bool GeneratedCodeInfo_Annotation::has_begin() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -void GeneratedCodeInfo_Annotation::set_has_begin() { - _has_bits_[0] |= 0x00000002u; -} -void GeneratedCodeInfo_Annotation::clear_has_begin() { - _has_bits_[0] &= ~0x00000002u; -} -void GeneratedCodeInfo_Annotation::clear_begin() { - begin_ = 0; - clear_has_begin(); -} -::google::protobuf::int32 GeneratedCodeInfo_Annotation::begin() const { - // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.begin) - return begin_; -} -void GeneratedCodeInfo_Annotation::set_begin(::google::protobuf::int32 value) { - set_has_begin(); - begin_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.begin) + path_.InternalSwap(&other->path_); + source_file_.Swap(&other->source_file_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, end_) + + sizeof(GeneratedCodeInfo_Annotation::end_) + - PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, begin_)>( + reinterpret_cast(&begin_), + reinterpret_cast(&other->begin_)); } -// optional int32 end = 4; -bool GeneratedCodeInfo_Annotation::has_end() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -void GeneratedCodeInfo_Annotation::set_has_end() { - _has_bits_[0] |= 0x00000004u; -} -void GeneratedCodeInfo_Annotation::clear_has_end() { - _has_bits_[0] &= ~0x00000004u; -} -void GeneratedCodeInfo_Annotation::clear_end() { - end_ = 0; - clear_has_end(); -} -::google::protobuf::int32 GeneratedCodeInfo_Annotation::end() const { - // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.end) - return end_; -} -void GeneratedCodeInfo_Annotation::set_end(::google::protobuf::int32 value) { - set_has_end(); - end_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.end) +::PROTOBUF_NAMESPACE_ID::Metadata GeneratedCodeInfo_Annotation::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int GeneratedCodeInfo::kAnnotationFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +class GeneratedCodeInfo::_Internal { + public: +}; -GeneratedCodeInfo::GeneratedCodeInfo() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - } +GeneratedCodeInfo::GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + annotation_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.GeneratedCodeInfo) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.GeneratedCodeInfo) } GeneratedCodeInfo::GeneratedCodeInfo(const GeneratedCodeInfo& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _has_bits_(from._has_bits_), - _cached_size_(0), + : ::PROTOBUF_NAMESPACE_ID::Message(), annotation_(from.annotation_) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo) } void GeneratedCodeInfo::SharedCtor() { - _cached_size_ = 0; } GeneratedCodeInfo::~GeneratedCodeInfo() { // @@protoc_insertion_point(destructor:google.protobuf.GeneratedCodeInfo) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void GeneratedCodeInfo::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); } -void GeneratedCodeInfo::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void GeneratedCodeInfo::ArenaDtor(void* object) { + GeneratedCodeInfo* _this = reinterpret_cast< GeneratedCodeInfo* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* GeneratedCodeInfo::descriptor() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void GeneratedCodeInfo::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -const GeneratedCodeInfo& GeneratedCodeInfo::default_instance() { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -GeneratedCodeInfo* GeneratedCodeInfo::New(::google::protobuf::Arena* arena) const { - GeneratedCodeInfo* n = new GeneratedCodeInfo; - if (arena != NULL) { - arena->Own(n); - } - return n; +void GeneratedCodeInfo::SetCachedSize(int size) const { + _cached_size_.Set(size); } void GeneratedCodeInfo::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; annotation_.Clear(); - _has_bits_.Clear(); - _internal_metadata_.Clear(); -} - -bool GeneratedCodeInfo::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.GeneratedCodeInfo) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_annotation())); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* GeneratedCodeInfo::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_annotation(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.GeneratedCodeInfo) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.GeneratedCodeInfo) - return false; -#undef DO_ -} - -void GeneratedCodeInfo::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.GeneratedCodeInfo) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; - for (unsigned int i = 0, - n = static_cast(this->annotation_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 1, this->annotation(static_cast(i)), output); - } - - if (_internal_metadata_.have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - _internal_metadata_.unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.GeneratedCodeInfo) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* GeneratedCodeInfo::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* GeneratedCodeInfo::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; for (unsigned int i = 0, - n = static_cast(this->annotation_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 1, this->annotation(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_annotation_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(1, this->_internal_annotation(i), target, stream); } - if (_internal_metadata_.have_unknown_fields()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields(), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.GeneratedCodeInfo) return target; @@ -16885,38 +10736,35 @@ size_t GeneratedCodeInfo::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo) size_t total_size = 0; - if (_internal_metadata_.have_unknown_fields()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - _internal_metadata_.unknown_fields()); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; - { - unsigned int count = static_cast(this->annotation_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->annotation(static_cast(i))); - } + total_size += 1UL * this->_internal_annotation_size(); + for (const auto& msg : this->annotation_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void GeneratedCodeInfo::MergeFrom(const ::google::protobuf::Message& from) { +void GeneratedCodeInfo::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.GeneratedCodeInfo) GOOGLE_DCHECK_NE(&from, this); const GeneratedCodeInfo* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.GeneratedCodeInfo) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.GeneratedCodeInfo) MergeFrom(*source); @@ -16926,14 +10774,14 @@ void GeneratedCodeInfo::MergeFrom(const ::google::protobuf::Message& from) { void GeneratedCodeInfo::MergeFrom(const GeneratedCodeInfo& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; annotation_.MergeFrom(from.annotation_); } -void GeneratedCodeInfo::CopyFrom(const ::google::protobuf::Message& from) { +void GeneratedCodeInfo::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.GeneratedCodeInfo) if (&from == this) return; Clear(); @@ -16951,61 +10799,102 @@ bool GeneratedCodeInfo::IsInitialized() const { return true; } -void GeneratedCodeInfo::Swap(GeneratedCodeInfo* other) { - if (other == this) return; - InternalSwap(other); -} void GeneratedCodeInfo::InternalSwap(GeneratedCodeInfo* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); annotation_.InternalSwap(&other->annotation_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); } -::google::protobuf::Metadata GeneratedCodeInfo::GetMetadata() const { - protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages]; +::PROTOBUF_NAMESPACE_ID::Metadata GeneratedCodeInfo::GetMetadata() const { + return GetMetadataStatic(); } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// GeneratedCodeInfo -// repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; -int GeneratedCodeInfo::annotation_size() const { - return annotation_.size(); +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::FileDescriptorSet* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::FileDescriptorSet >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::FileDescriptorSet >(arena); } -void GeneratedCodeInfo::clear_annotation() { - annotation_.Clear(); +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::FileDescriptorProto* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >(arena); } -const ::google::protobuf::GeneratedCodeInfo_Annotation& GeneratedCodeInfo::annotation(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.annotation) - return annotation_.Get(index); +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange >(arena); } -::google::protobuf::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::mutable_annotation(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.annotation) - return annotation_.Mutable(index); +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange >(arena); } -::google::protobuf::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::add_annotation() { - // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.annotation) - return annotation_.Add(); +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::DescriptorProto* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::DescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::DescriptorProto >(arena); } -::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >* -GeneratedCodeInfo::mutable_annotation() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.annotation) - return &annotation_; +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions >(arena); } -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >& -GeneratedCodeInfo::annotation() const { - // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.annotation) - return annotation_; +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >(arena); } - -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS - -// @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::OneofDescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::OneofDescriptorProto >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::MethodDescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::MethodDescriptorProto >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::FileOptions* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::FileOptions >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::FileOptions >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::MessageOptions* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::MessageOptions >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::MessageOptions >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::FieldOptions* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::FieldOptions >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::FieldOptions >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::OneofOptions* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::OneofOptions >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::OneofOptions >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::EnumOptions* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::EnumOptions >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::EnumOptions >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::EnumValueOptions* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::EnumValueOptions >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::EnumValueOptions >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::ServiceOptions* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::ServiceOptions >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::ServiceOptions >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::MethodOptions* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::MethodOptions >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::MethodOptions >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::UninterpretedOption* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::UninterpretedOption >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::UninterpretedOption >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::SourceCodeInfo* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::SourceCodeInfo >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::SourceCodeInfo >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation >(arena); +} +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo >(arena); +} +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) +#include diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index 7ec516ab7d0ab..c9d47546c4995 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -1,138 +1,175 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/descriptor.proto -#ifndef PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED -#define PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto +#include #include -#include - -#if GOOGLE_PROTOBUF_VERSION < 3004000 +#include +#if PROTOBUF_VERSION < 3015000 #error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update +#error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 3015000 < PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please +#error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif +#include #include #include #include #include #include -#include +#include +#include #include #include // IWYU pragma: export #include // IWYU pragma: export #include #include // @@protoc_insertion_point(includes) -namespace google { -namespace protobuf { +#include +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fdescriptor_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[27] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; +}; +extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto; +PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(int index); +PROTOBUF_NAMESPACE_OPEN class DescriptorProto; -class DescriptorProtoDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern DescriptorProtoDefaultTypeInternal _DescriptorProto_default_instance_; +struct DescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern DescriptorProtoDefaultTypeInternal _DescriptorProto_default_instance_; class DescriptorProto_ExtensionRange; -class DescriptorProto_ExtensionRangeDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern DescriptorProto_ExtensionRangeDefaultTypeInternal _DescriptorProto_ExtensionRange_default_instance_; +struct DescriptorProto_ExtensionRangeDefaultTypeInternal; +PROTOBUF_EXPORT extern DescriptorProto_ExtensionRangeDefaultTypeInternal _DescriptorProto_ExtensionRange_default_instance_; class DescriptorProto_ReservedRange; -class DescriptorProto_ReservedRangeDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern DescriptorProto_ReservedRangeDefaultTypeInternal _DescriptorProto_ReservedRange_default_instance_; +struct DescriptorProto_ReservedRangeDefaultTypeInternal; +PROTOBUF_EXPORT extern DescriptorProto_ReservedRangeDefaultTypeInternal _DescriptorProto_ReservedRange_default_instance_; class EnumDescriptorProto; -class EnumDescriptorProtoDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern EnumDescriptorProtoDefaultTypeInternal _EnumDescriptorProto_default_instance_; +struct EnumDescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern EnumDescriptorProtoDefaultTypeInternal _EnumDescriptorProto_default_instance_; +class EnumDescriptorProto_EnumReservedRange; +struct EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal; +PROTOBUF_EXPORT extern EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal _EnumDescriptorProto_EnumReservedRange_default_instance_; class EnumOptions; -class EnumOptionsDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern EnumOptionsDefaultTypeInternal _EnumOptions_default_instance_; +struct EnumOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern EnumOptionsDefaultTypeInternal _EnumOptions_default_instance_; class EnumValueDescriptorProto; -class EnumValueDescriptorProtoDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern EnumValueDescriptorProtoDefaultTypeInternal _EnumValueDescriptorProto_default_instance_; +struct EnumValueDescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern EnumValueDescriptorProtoDefaultTypeInternal _EnumValueDescriptorProto_default_instance_; class EnumValueOptions; -class EnumValueOptionsDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_; +struct EnumValueOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_; class ExtensionRangeOptions; -class ExtensionRangeOptionsDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern ExtensionRangeOptionsDefaultTypeInternal _ExtensionRangeOptions_default_instance_; +struct ExtensionRangeOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern ExtensionRangeOptionsDefaultTypeInternal _ExtensionRangeOptions_default_instance_; class FieldDescriptorProto; -class FieldDescriptorProtoDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_; +struct FieldDescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_; class FieldOptions; -class FieldOptionsDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern FieldOptionsDefaultTypeInternal _FieldOptions_default_instance_; +struct FieldOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern FieldOptionsDefaultTypeInternal _FieldOptions_default_instance_; class FileDescriptorProto; -class FileDescriptorProtoDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern FileDescriptorProtoDefaultTypeInternal _FileDescriptorProto_default_instance_; +struct FileDescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern FileDescriptorProtoDefaultTypeInternal _FileDescriptorProto_default_instance_; class FileDescriptorSet; -class FileDescriptorSetDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern FileDescriptorSetDefaultTypeInternal _FileDescriptorSet_default_instance_; +struct FileDescriptorSetDefaultTypeInternal; +PROTOBUF_EXPORT extern FileDescriptorSetDefaultTypeInternal _FileDescriptorSet_default_instance_; class FileOptions; -class FileOptionsDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern FileOptionsDefaultTypeInternal _FileOptions_default_instance_; +struct FileOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern FileOptionsDefaultTypeInternal _FileOptions_default_instance_; class GeneratedCodeInfo; -class GeneratedCodeInfoDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern GeneratedCodeInfoDefaultTypeInternal _GeneratedCodeInfo_default_instance_; +struct GeneratedCodeInfoDefaultTypeInternal; +PROTOBUF_EXPORT extern GeneratedCodeInfoDefaultTypeInternal _GeneratedCodeInfo_default_instance_; class GeneratedCodeInfo_Annotation; -class GeneratedCodeInfo_AnnotationDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern GeneratedCodeInfo_AnnotationDefaultTypeInternal _GeneratedCodeInfo_Annotation_default_instance_; +struct GeneratedCodeInfo_AnnotationDefaultTypeInternal; +PROTOBUF_EXPORT extern GeneratedCodeInfo_AnnotationDefaultTypeInternal _GeneratedCodeInfo_Annotation_default_instance_; class MessageOptions; -class MessageOptionsDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern MessageOptionsDefaultTypeInternal _MessageOptions_default_instance_; +struct MessageOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern MessageOptionsDefaultTypeInternal _MessageOptions_default_instance_; class MethodDescriptorProto; -class MethodDescriptorProtoDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern MethodDescriptorProtoDefaultTypeInternal _MethodDescriptorProto_default_instance_; +struct MethodDescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern MethodDescriptorProtoDefaultTypeInternal _MethodDescriptorProto_default_instance_; class MethodOptions; -class MethodOptionsDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern MethodOptionsDefaultTypeInternal _MethodOptions_default_instance_; +struct MethodOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern MethodOptionsDefaultTypeInternal _MethodOptions_default_instance_; class OneofDescriptorProto; -class OneofDescriptorProtoDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern OneofDescriptorProtoDefaultTypeInternal _OneofDescriptorProto_default_instance_; +struct OneofDescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern OneofDescriptorProtoDefaultTypeInternal _OneofDescriptorProto_default_instance_; class OneofOptions; -class OneofOptionsDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern OneofOptionsDefaultTypeInternal _OneofOptions_default_instance_; +struct OneofOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern OneofOptionsDefaultTypeInternal _OneofOptions_default_instance_; class ServiceDescriptorProto; -class ServiceDescriptorProtoDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern ServiceDescriptorProtoDefaultTypeInternal _ServiceDescriptorProto_default_instance_; +struct ServiceDescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern ServiceDescriptorProtoDefaultTypeInternal _ServiceDescriptorProto_default_instance_; class ServiceOptions; -class ServiceOptionsDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern ServiceOptionsDefaultTypeInternal _ServiceOptions_default_instance_; +struct ServiceOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern ServiceOptionsDefaultTypeInternal _ServiceOptions_default_instance_; class SourceCodeInfo; -class SourceCodeInfoDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern SourceCodeInfoDefaultTypeInternal _SourceCodeInfo_default_instance_; +struct SourceCodeInfoDefaultTypeInternal; +PROTOBUF_EXPORT extern SourceCodeInfoDefaultTypeInternal _SourceCodeInfo_default_instance_; class SourceCodeInfo_Location; -class SourceCodeInfo_LocationDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern SourceCodeInfo_LocationDefaultTypeInternal _SourceCodeInfo_Location_default_instance_; +struct SourceCodeInfo_LocationDefaultTypeInternal; +PROTOBUF_EXPORT extern SourceCodeInfo_LocationDefaultTypeInternal _SourceCodeInfo_Location_default_instance_; class UninterpretedOption; -class UninterpretedOptionDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern UninterpretedOptionDefaultTypeInternal _UninterpretedOption_default_instance_; +struct UninterpretedOptionDefaultTypeInternal; +PROTOBUF_EXPORT extern UninterpretedOptionDefaultTypeInternal _UninterpretedOption_default_instance_; class UninterpretedOption_NamePart; -class UninterpretedOption_NamePartDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_; -} // namespace protobuf -} // namespace google - -namespace google { -namespace protobuf { - -namespace protobuf_google_2fprotobuf_2fdescriptor_2eproto { -// Internal implementation detail -- do not call these. -struct LIBPROTOBUF_EXPORT TableStruct { - static const ::google::protobuf::internal::ParseTableField entries[]; - static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; - static const ::google::protobuf::internal::ParseTable schema[]; - static const ::google::protobuf::uint32 offsets[]; - static const ::google::protobuf::internal::FieldMetadata field_metadata[]; - static const ::google::protobuf::internal::SerializationTable serialization_table[]; - static void InitDefaultsImpl(); -}; -void LIBPROTOBUF_EXPORT AddDescriptors(); -void LIBPROTOBUF_EXPORT InitDefaults(); -} // namespace protobuf_google_2fprotobuf_2fdescriptor_2eproto - -enum FieldDescriptorProto_Type { +struct UninterpretedOption_NamePartDefaultTypeInternal; +PROTOBUF_EXPORT extern UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::DescriptorProto* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::EnumOptions* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::EnumValueOptions* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::FieldOptions* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::FileDescriptorProto* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::FileDescriptorSet* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::FileOptions* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::MessageOptions* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::MethodOptions* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::OneofOptions* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::ServiceOptions* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::SourceCodeInfo* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::UninterpretedOption* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* Arena::CreateMaybeMessage(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN + +enum FieldDescriptorProto_Type : int { FieldDescriptorProto_Type_TYPE_DOUBLE = 1, FieldDescriptorProto_Type_TYPE_FLOAT = 2, FieldDescriptorProto_Type_TYPE_INT64 = 3, @@ -152,842 +189,1156 @@ enum FieldDescriptorProto_Type { FieldDescriptorProto_Type_TYPE_SINT32 = 17, FieldDescriptorProto_Type_TYPE_SINT64 = 18 }; -LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Type_IsValid(int value); -const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MIN = FieldDescriptorProto_Type_TYPE_DOUBLE; -const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MAX = FieldDescriptorProto_Type_TYPE_SINT64; -const int FieldDescriptorProto_Type_Type_ARRAYSIZE = FieldDescriptorProto_Type_Type_MAX + 1; - -LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor(); -inline const ::std::string& FieldDescriptorProto_Type_Name(FieldDescriptorProto_Type value) { - return ::google::protobuf::internal::NameOfEnum( - FieldDescriptorProto_Type_descriptor(), value); +PROTOBUF_EXPORT bool FieldDescriptorProto_Type_IsValid(int value); +constexpr FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MIN = FieldDescriptorProto_Type_TYPE_DOUBLE; +constexpr FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MAX = FieldDescriptorProto_Type_TYPE_SINT64; +constexpr int FieldDescriptorProto_Type_Type_ARRAYSIZE = FieldDescriptorProto_Type_Type_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldDescriptorProto_Type_descriptor(); +template +inline const std::string& FieldDescriptorProto_Type_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function FieldDescriptorProto_Type_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + FieldDescriptorProto_Type_descriptor(), enum_t_value); } inline bool FieldDescriptorProto_Type_Parse( - const ::std::string& name, FieldDescriptorProto_Type* value) { - return ::google::protobuf::internal::ParseNamedEnum( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldDescriptorProto_Type* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum( FieldDescriptorProto_Type_descriptor(), name, value); } -enum FieldDescriptorProto_Label { +enum FieldDescriptorProto_Label : int { FieldDescriptorProto_Label_LABEL_OPTIONAL = 1, FieldDescriptorProto_Label_LABEL_REQUIRED = 2, FieldDescriptorProto_Label_LABEL_REPEATED = 3 }; -LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Label_IsValid(int value); -const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MIN = FieldDescriptorProto_Label_LABEL_OPTIONAL; -const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MAX = FieldDescriptorProto_Label_LABEL_REPEATED; -const int FieldDescriptorProto_Label_Label_ARRAYSIZE = FieldDescriptorProto_Label_Label_MAX + 1; - -LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor(); -inline const ::std::string& FieldDescriptorProto_Label_Name(FieldDescriptorProto_Label value) { - return ::google::protobuf::internal::NameOfEnum( - FieldDescriptorProto_Label_descriptor(), value); +PROTOBUF_EXPORT bool FieldDescriptorProto_Label_IsValid(int value); +constexpr FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MIN = FieldDescriptorProto_Label_LABEL_OPTIONAL; +constexpr FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MAX = FieldDescriptorProto_Label_LABEL_REPEATED; +constexpr int FieldDescriptorProto_Label_Label_ARRAYSIZE = FieldDescriptorProto_Label_Label_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldDescriptorProto_Label_descriptor(); +template +inline const std::string& FieldDescriptorProto_Label_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function FieldDescriptorProto_Label_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + FieldDescriptorProto_Label_descriptor(), enum_t_value); } inline bool FieldDescriptorProto_Label_Parse( - const ::std::string& name, FieldDescriptorProto_Label* value) { - return ::google::protobuf::internal::ParseNamedEnum( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldDescriptorProto_Label* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum( FieldDescriptorProto_Label_descriptor(), name, value); } -enum FileOptions_OptimizeMode { +enum FileOptions_OptimizeMode : int { FileOptions_OptimizeMode_SPEED = 1, FileOptions_OptimizeMode_CODE_SIZE = 2, FileOptions_OptimizeMode_LITE_RUNTIME = 3 }; -LIBPROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value); -const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = FileOptions_OptimizeMode_SPEED; -const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = FileOptions_OptimizeMode_LITE_RUNTIME; -const int FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE = FileOptions_OptimizeMode_OptimizeMode_MAX + 1; - -LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor(); -inline const ::std::string& FileOptions_OptimizeMode_Name(FileOptions_OptimizeMode value) { - return ::google::protobuf::internal::NameOfEnum( - FileOptions_OptimizeMode_descriptor(), value); +PROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value); +constexpr FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = FileOptions_OptimizeMode_SPEED; +constexpr FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = FileOptions_OptimizeMode_LITE_RUNTIME; +constexpr int FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE = FileOptions_OptimizeMode_OptimizeMode_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FileOptions_OptimizeMode_descriptor(); +template +inline const std::string& FileOptions_OptimizeMode_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function FileOptions_OptimizeMode_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + FileOptions_OptimizeMode_descriptor(), enum_t_value); } inline bool FileOptions_OptimizeMode_Parse( - const ::std::string& name, FileOptions_OptimizeMode* value) { - return ::google::protobuf::internal::ParseNamedEnum( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FileOptions_OptimizeMode* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum( FileOptions_OptimizeMode_descriptor(), name, value); } -enum FieldOptions_CType { +enum FieldOptions_CType : int { FieldOptions_CType_STRING = 0, FieldOptions_CType_CORD = 1, FieldOptions_CType_STRING_PIECE = 2 }; -LIBPROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value); -const FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_STRING; -const FieldOptions_CType FieldOptions_CType_CType_MAX = FieldOptions_CType_STRING_PIECE; -const int FieldOptions_CType_CType_ARRAYSIZE = FieldOptions_CType_CType_MAX + 1; - -LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor(); -inline const ::std::string& FieldOptions_CType_Name(FieldOptions_CType value) { - return ::google::protobuf::internal::NameOfEnum( - FieldOptions_CType_descriptor(), value); +PROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value); +constexpr FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_STRING; +constexpr FieldOptions_CType FieldOptions_CType_CType_MAX = FieldOptions_CType_STRING_PIECE; +constexpr int FieldOptions_CType_CType_ARRAYSIZE = FieldOptions_CType_CType_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldOptions_CType_descriptor(); +template +inline const std::string& FieldOptions_CType_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function FieldOptions_CType_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + FieldOptions_CType_descriptor(), enum_t_value); } inline bool FieldOptions_CType_Parse( - const ::std::string& name, FieldOptions_CType* value) { - return ::google::protobuf::internal::ParseNamedEnum( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldOptions_CType* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum( FieldOptions_CType_descriptor(), name, value); } -enum FieldOptions_JSType { +enum FieldOptions_JSType : int { FieldOptions_JSType_JS_NORMAL = 0, FieldOptions_JSType_JS_STRING = 1, FieldOptions_JSType_JS_NUMBER = 2 }; -LIBPROTOBUF_EXPORT bool FieldOptions_JSType_IsValid(int value); -const FieldOptions_JSType FieldOptions_JSType_JSType_MIN = FieldOptions_JSType_JS_NORMAL; -const FieldOptions_JSType FieldOptions_JSType_JSType_MAX = FieldOptions_JSType_JS_NUMBER; -const int FieldOptions_JSType_JSType_ARRAYSIZE = FieldOptions_JSType_JSType_MAX + 1; - -LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor(); -inline const ::std::string& FieldOptions_JSType_Name(FieldOptions_JSType value) { - return ::google::protobuf::internal::NameOfEnum( - FieldOptions_JSType_descriptor(), value); +PROTOBUF_EXPORT bool FieldOptions_JSType_IsValid(int value); +constexpr FieldOptions_JSType FieldOptions_JSType_JSType_MIN = FieldOptions_JSType_JS_NORMAL; +constexpr FieldOptions_JSType FieldOptions_JSType_JSType_MAX = FieldOptions_JSType_JS_NUMBER; +constexpr int FieldOptions_JSType_JSType_ARRAYSIZE = FieldOptions_JSType_JSType_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldOptions_JSType_descriptor(); +template +inline const std::string& FieldOptions_JSType_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function FieldOptions_JSType_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + FieldOptions_JSType_descriptor(), enum_t_value); } inline bool FieldOptions_JSType_Parse( - const ::std::string& name, FieldOptions_JSType* value) { - return ::google::protobuf::internal::ParseNamedEnum( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldOptions_JSType* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum( FieldOptions_JSType_descriptor(), name, value); } -enum MethodOptions_IdempotencyLevel { +enum MethodOptions_IdempotencyLevel : int { MethodOptions_IdempotencyLevel_IDEMPOTENCY_UNKNOWN = 0, MethodOptions_IdempotencyLevel_NO_SIDE_EFFECTS = 1, MethodOptions_IdempotencyLevel_IDEMPOTENT = 2 }; -LIBPROTOBUF_EXPORT bool MethodOptions_IdempotencyLevel_IsValid(int value); -const MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel_IdempotencyLevel_MIN = MethodOptions_IdempotencyLevel_IDEMPOTENCY_UNKNOWN; -const MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX = MethodOptions_IdempotencyLevel_IDEMPOTENT; -const int MethodOptions_IdempotencyLevel_IdempotencyLevel_ARRAYSIZE = MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX + 1; - -LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* MethodOptions_IdempotencyLevel_descriptor(); -inline const ::std::string& MethodOptions_IdempotencyLevel_Name(MethodOptions_IdempotencyLevel value) { - return ::google::protobuf::internal::NameOfEnum( - MethodOptions_IdempotencyLevel_descriptor(), value); +PROTOBUF_EXPORT bool MethodOptions_IdempotencyLevel_IsValid(int value); +constexpr MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel_IdempotencyLevel_MIN = MethodOptions_IdempotencyLevel_IDEMPOTENCY_UNKNOWN; +constexpr MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX = MethodOptions_IdempotencyLevel_IDEMPOTENT; +constexpr int MethodOptions_IdempotencyLevel_IdempotencyLevel_ARRAYSIZE = MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* MethodOptions_IdempotencyLevel_descriptor(); +template +inline const std::string& MethodOptions_IdempotencyLevel_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function MethodOptions_IdempotencyLevel_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + MethodOptions_IdempotencyLevel_descriptor(), enum_t_value); } inline bool MethodOptions_IdempotencyLevel_Parse( - const ::std::string& name, MethodOptions_IdempotencyLevel* value) { - return ::google::protobuf::internal::ParseNamedEnum( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, MethodOptions_IdempotencyLevel* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum( MethodOptions_IdempotencyLevel_descriptor(), name, value); } // =================================================================== -class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileDescriptorSet) */ { +class PROTOBUF_EXPORT FileDescriptorSet PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileDescriptorSet) */ { public: - FileDescriptorSet(); + inline FileDescriptorSet() : FileDescriptorSet(nullptr) {} virtual ~FileDescriptorSet(); + explicit constexpr FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); FileDescriptorSet(const FileDescriptorSet& from); - - inline FileDescriptorSet& operator=(const FileDescriptorSet& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 FileDescriptorSet(FileDescriptorSet&& from) noexcept : FileDescriptorSet() { *this = ::std::move(from); } + inline FileDescriptorSet& operator=(const FileDescriptorSet& from) { + CopyFrom(from); + return *this; + } inline FileDescriptorSet& operator=(FileDescriptorSet&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const FileDescriptorSet& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const FileDescriptorSet& default_instance() { + return *internal_default_instance(); + } static inline const FileDescriptorSet* internal_default_instance() { return reinterpret_cast( &_FileDescriptorSet_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 0; - void Swap(FileDescriptorSet* other); friend void swap(FileDescriptorSet& a, FileDescriptorSet& b) { a.Swap(&b); } + inline void Swap(FileDescriptorSet* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FileDescriptorSet* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline FileDescriptorSet* New() const PROTOBUF_FINAL { return New(NULL); } + inline FileDescriptorSet* New() const final { + return CreateMaybeMessage(nullptr); + } - FileDescriptorSet* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + FileDescriptorSet* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const FileDescriptorSet& from); void MergeFrom(const FileDescriptorSet& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(FileDescriptorSet* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(FileDescriptorSet* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.FileDescriptorSet"; } + protected: + explicit FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kFileFieldNumber = 1, + }; // repeated .google.protobuf.FileDescriptorProto file = 1; int file_size() const; + private: + int _internal_file_size() const; + public: void clear_file(); - static const int kFileFieldNumber = 1; - const ::google::protobuf::FileDescriptorProto& file(int index) const; - ::google::protobuf::FileDescriptorProto* mutable_file(int index); - ::google::protobuf::FileDescriptorProto* add_file(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* + PROTOBUF_NAMESPACE_ID::FileDescriptorProto* mutable_file(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >* mutable_file(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& + private: + const PROTOBUF_NAMESPACE_ID::FileDescriptorProto& _internal_file(int index) const; + PROTOBUF_NAMESPACE_ID::FileDescriptorProto* _internal_add_file(); + public: + const PROTOBUF_NAMESPACE_ID::FileDescriptorProto& file(int index) const; + PROTOBUF_NAMESPACE_ID::FileDescriptorProto* add_file(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >& file() const; // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet) private: - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto > file_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileDescriptorProto) */ { +class PROTOBUF_EXPORT FileDescriptorProto PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileDescriptorProto) */ { public: - FileDescriptorProto(); + inline FileDescriptorProto() : FileDescriptorProto(nullptr) {} virtual ~FileDescriptorProto(); + explicit constexpr FileDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); FileDescriptorProto(const FileDescriptorProto& from); - - inline FileDescriptorProto& operator=(const FileDescriptorProto& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 FileDescriptorProto(FileDescriptorProto&& from) noexcept : FileDescriptorProto() { *this = ::std::move(from); } + inline FileDescriptorProto& operator=(const FileDescriptorProto& from) { + CopyFrom(from); + return *this; + } inline FileDescriptorProto& operator=(FileDescriptorProto&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const FileDescriptorProto& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const FileDescriptorProto& default_instance() { + return *internal_default_instance(); + } static inline const FileDescriptorProto* internal_default_instance() { return reinterpret_cast( &_FileDescriptorProto_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 1; - void Swap(FileDescriptorProto* other); friend void swap(FileDescriptorProto& a, FileDescriptorProto& b) { a.Swap(&b); } + inline void Swap(FileDescriptorProto* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FileDescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline FileDescriptorProto* New() const PROTOBUF_FINAL { return New(NULL); } + inline FileDescriptorProto* New() const final { + return CreateMaybeMessage(nullptr); + } - FileDescriptorProto* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + FileDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const FileDescriptorProto& from); void MergeFrom(const FileDescriptorProto& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(FileDescriptorProto* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(FileDescriptorProto* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.FileDescriptorProto"; } + protected: + explicit FileDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kDependencyFieldNumber = 3, + kMessageTypeFieldNumber = 4, + kEnumTypeFieldNumber = 5, + kServiceFieldNumber = 6, + kExtensionFieldNumber = 7, + kPublicDependencyFieldNumber = 10, + kWeakDependencyFieldNumber = 11, + kNameFieldNumber = 1, + kPackageFieldNumber = 2, + kSyntaxFieldNumber = 12, + kOptionsFieldNumber = 8, + kSourceCodeInfoFieldNumber = 9, + }; // repeated string dependency = 3; int dependency_size() const; + private: + int _internal_dependency_size() const; + public: void clear_dependency(); - static const int kDependencyFieldNumber = 3; - const ::std::string& dependency(int index) const; - ::std::string* mutable_dependency(int index); - void set_dependency(int index, const ::std::string& value); - #if LANG_CXX11 - void set_dependency(int index, ::std::string&& value); - #endif + const std::string& dependency(int index) const; + std::string* mutable_dependency(int index); + void set_dependency(int index, const std::string& value); + void set_dependency(int index, std::string&& value); void set_dependency(int index, const char* value); void set_dependency(int index, const char* value, size_t size); - ::std::string* add_dependency(); - void add_dependency(const ::std::string& value); - #if LANG_CXX11 - void add_dependency(::std::string&& value); - #endif + std::string* add_dependency(); + void add_dependency(const std::string& value); + void add_dependency(std::string&& value); void add_dependency(const char* value); void add_dependency(const char* value, size_t size); - const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const; - ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField& dependency() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField* mutable_dependency(); + private: + const std::string& _internal_dependency(int index) const; + std::string* _internal_add_dependency(); + public: // repeated .google.protobuf.DescriptorProto message_type = 4; int message_type_size() const; + private: + int _internal_message_type_size() const; + public: void clear_message_type(); - static const int kMessageTypeFieldNumber = 4; - const ::google::protobuf::DescriptorProto& message_type(int index) const; - ::google::protobuf::DescriptorProto* mutable_message_type(int index); - ::google::protobuf::DescriptorProto* add_message_type(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* + PROTOBUF_NAMESPACE_ID::DescriptorProto* mutable_message_type(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto >* mutable_message_type(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& + private: + const PROTOBUF_NAMESPACE_ID::DescriptorProto& _internal_message_type(int index) const; + PROTOBUF_NAMESPACE_ID::DescriptorProto* _internal_add_message_type(); + public: + const PROTOBUF_NAMESPACE_ID::DescriptorProto& message_type(int index) const; + PROTOBUF_NAMESPACE_ID::DescriptorProto* add_message_type(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto >& message_type() const; // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; int enum_type_size() const; + private: + int _internal_enum_type_size() const; + public: void clear_enum_type(); - static const int kEnumTypeFieldNumber = 5; - const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const; - ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index); - ::google::protobuf::EnumDescriptorProto* add_enum_type(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* + PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* mutable_enum_type(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >* mutable_enum_type(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& + private: + const PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& _internal_enum_type(int index) const; + PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* _internal_add_enum_type(); + public: + const PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& enum_type(int index) const; + PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* add_enum_type(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >& enum_type() const; // repeated .google.protobuf.ServiceDescriptorProto service = 6; int service_size() const; + private: + int _internal_service_size() const; + public: void clear_service(); - static const int kServiceFieldNumber = 6; - const ::google::protobuf::ServiceDescriptorProto& service(int index) const; - ::google::protobuf::ServiceDescriptorProto* mutable_service(int index); - ::google::protobuf::ServiceDescriptorProto* add_service(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* + PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* mutable_service(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto >* mutable_service(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& + private: + const PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto& _internal_service(int index) const; + PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* _internal_add_service(); + public: + const PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto& service(int index) const; + PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* add_service(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto >& service() const; // repeated .google.protobuf.FieldDescriptorProto extension = 7; int extension_size() const; + private: + int _internal_extension_size() const; + public: void clear_extension(); - static const int kExtensionFieldNumber = 7; - const ::google::protobuf::FieldDescriptorProto& extension(int index) const; - ::google::protobuf::FieldDescriptorProto* mutable_extension(int index); - ::google::protobuf::FieldDescriptorProto* add_extension(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* + PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* mutable_extension(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >* mutable_extension(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + private: + const PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& _internal_extension(int index) const; + PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* _internal_add_extension(); + public: + const PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& extension(int index) const; + PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* add_extension(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >& extension() const; // repeated int32 public_dependency = 10; int public_dependency_size() const; + private: + int _internal_public_dependency_size() const; + public: void clear_public_dependency(); - static const int kPublicDependencyFieldNumber = 10; - ::google::protobuf::int32 public_dependency(int index) const; - void set_public_dependency(int index, ::google::protobuf::int32 value); - void add_public_dependency(::google::protobuf::int32 value); - const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_public_dependency(int index) const; + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& + _internal_public_dependency() const; + void _internal_add_public_dependency(::PROTOBUF_NAMESPACE_ID::int32 value); + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* + _internal_mutable_public_dependency(); + public: + ::PROTOBUF_NAMESPACE_ID::int32 public_dependency(int index) const; + void set_public_dependency(int index, ::PROTOBUF_NAMESPACE_ID::int32 value); + void add_public_dependency(::PROTOBUF_NAMESPACE_ID::int32 value); + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& public_dependency() const; - ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* mutable_public_dependency(); // repeated int32 weak_dependency = 11; int weak_dependency_size() const; + private: + int _internal_weak_dependency_size() const; + public: void clear_weak_dependency(); - static const int kWeakDependencyFieldNumber = 11; - ::google::protobuf::int32 weak_dependency(int index) const; - void set_weak_dependency(int index, ::google::protobuf::int32 value); - void add_weak_dependency(::google::protobuf::int32 value); - const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_weak_dependency(int index) const; + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& + _internal_weak_dependency() const; + void _internal_add_weak_dependency(::PROTOBUF_NAMESPACE_ID::int32 value); + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* + _internal_mutable_weak_dependency(); + public: + ::PROTOBUF_NAMESPACE_ID::int32 weak_dependency(int index) const; + void set_weak_dependency(int index, ::PROTOBUF_NAMESPACE_ID::int32 value); + void add_weak_dependency(::PROTOBUF_NAMESPACE_ID::int32 value); + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& weak_dependency() const; - ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* mutable_weak_dependency(); // optional string name = 1; bool has_name() const; + private: + bool _internal_has_name() const; + public: void clear_name(); - static const int kNameFieldNumber = 1; - const ::std::string& name() const; - void set_name(const ::std::string& value); - #if LANG_CXX11 - void set_name(::std::string&& value); - #endif + const std::string& name() const; + void set_name(const std::string& value); + void set_name(std::string&& value); void set_name(const char* value); void set_name(const char* value, size_t size); - ::std::string* mutable_name(); - ::std::string* release_name(); - void set_allocated_name(::std::string* name); + std::string* mutable_name(); + std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: // optional string package = 2; bool has_package() const; + private: + bool _internal_has_package() const; + public: void clear_package(); - static const int kPackageFieldNumber = 2; - const ::std::string& package() const; - void set_package(const ::std::string& value); - #if LANG_CXX11 - void set_package(::std::string&& value); - #endif + const std::string& package() const; + void set_package(const std::string& value); + void set_package(std::string&& value); void set_package(const char* value); void set_package(const char* value, size_t size); - ::std::string* mutable_package(); - ::std::string* release_package(); - void set_allocated_package(::std::string* package); + std::string* mutable_package(); + std::string* release_package(); + void set_allocated_package(std::string* package); + private: + const std::string& _internal_package() const; + void _internal_set_package(const std::string& value); + std::string* _internal_mutable_package(); + public: // optional string syntax = 12; bool has_syntax() const; + private: + bool _internal_has_syntax() const; + public: void clear_syntax(); - static const int kSyntaxFieldNumber = 12; - const ::std::string& syntax() const; - void set_syntax(const ::std::string& value); - #if LANG_CXX11 - void set_syntax(::std::string&& value); - #endif + const std::string& syntax() const; + void set_syntax(const std::string& value); + void set_syntax(std::string&& value); void set_syntax(const char* value); void set_syntax(const char* value, size_t size); - ::std::string* mutable_syntax(); - ::std::string* release_syntax(); - void set_allocated_syntax(::std::string* syntax); + std::string* mutable_syntax(); + std::string* release_syntax(); + void set_allocated_syntax(std::string* syntax); + private: + const std::string& _internal_syntax() const; + void _internal_set_syntax(const std::string& value); + std::string* _internal_mutable_syntax(); + public: // optional .google.protobuf.FileOptions options = 8; bool has_options() const; + private: + bool _internal_has_options() const; + public: void clear_options(); - static const int kOptionsFieldNumber = 8; - const ::google::protobuf::FileOptions& options() const; - ::google::protobuf::FileOptions* mutable_options(); - ::google::protobuf::FileOptions* release_options(); - void set_allocated_options(::google::protobuf::FileOptions* options); + const PROTOBUF_NAMESPACE_ID::FileOptions& options() const; + PROTOBUF_NAMESPACE_ID::FileOptions* release_options(); + PROTOBUF_NAMESPACE_ID::FileOptions* mutable_options(); + void set_allocated_options(PROTOBUF_NAMESPACE_ID::FileOptions* options); + private: + const PROTOBUF_NAMESPACE_ID::FileOptions& _internal_options() const; + PROTOBUF_NAMESPACE_ID::FileOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::FileOptions* options); + PROTOBUF_NAMESPACE_ID::FileOptions* unsafe_arena_release_options(); // optional .google.protobuf.SourceCodeInfo source_code_info = 9; bool has_source_code_info() const; + private: + bool _internal_has_source_code_info() const; + public: void clear_source_code_info(); - static const int kSourceCodeInfoFieldNumber = 9; - const ::google::protobuf::SourceCodeInfo& source_code_info() const; - ::google::protobuf::SourceCodeInfo* mutable_source_code_info(); - ::google::protobuf::SourceCodeInfo* release_source_code_info(); - void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info); + const PROTOBUF_NAMESPACE_ID::SourceCodeInfo& source_code_info() const; + PROTOBUF_NAMESPACE_ID::SourceCodeInfo* release_source_code_info(); + PROTOBUF_NAMESPACE_ID::SourceCodeInfo* mutable_source_code_info(); + void set_allocated_source_code_info(PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info); + private: + const PROTOBUF_NAMESPACE_ID::SourceCodeInfo& _internal_source_code_info() const; + PROTOBUF_NAMESPACE_ID::SourceCodeInfo* _internal_mutable_source_code_info(); + public: + void unsafe_arena_set_allocated_source_code_info( + PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info); + PROTOBUF_NAMESPACE_ID::SourceCodeInfo* unsafe_arena_release_source_code_info(); // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto) private: - void set_has_name(); - void clear_has_name(); - void set_has_package(); - void clear_has_package(); - void set_has_options(); - void clear_has_options(); - void set_has_source_code_info(); - void clear_has_source_code_info(); - void set_has_syntax(); - void clear_has_syntax(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::std::string> dependency_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > message_type_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto > service_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_; - ::google::protobuf::RepeatedField< ::google::protobuf::int32 > public_dependency_; - ::google::protobuf::RepeatedField< ::google::protobuf::int32 > weak_dependency_; - ::google::protobuf::internal::ArenaStringPtr name_; - ::google::protobuf::internal::ArenaStringPtr package_; - ::google::protobuf::internal::ArenaStringPtr syntax_; - ::google::protobuf::FileOptions* options_; - ::google::protobuf::SourceCodeInfo* source_code_info_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField dependency_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto > message_type_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto > enum_type_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto > service_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto > extension_; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 > public_dependency_; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 > weak_dependency_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr package_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr syntax_; + PROTOBUF_NAMESPACE_ID::FileOptions* options_; + PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto.ExtensionRange) */ { +class PROTOBUF_EXPORT DescriptorProto_ExtensionRange PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto.ExtensionRange) */ { public: - DescriptorProto_ExtensionRange(); + inline DescriptorProto_ExtensionRange() : DescriptorProto_ExtensionRange(nullptr) {} virtual ~DescriptorProto_ExtensionRange(); + explicit constexpr DescriptorProto_ExtensionRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from); - - inline DescriptorProto_ExtensionRange& operator=(const DescriptorProto_ExtensionRange& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 DescriptorProto_ExtensionRange(DescriptorProto_ExtensionRange&& from) noexcept : DescriptorProto_ExtensionRange() { *this = ::std::move(from); } + inline DescriptorProto_ExtensionRange& operator=(const DescriptorProto_ExtensionRange& from) { + CopyFrom(from); + return *this; + } inline DescriptorProto_ExtensionRange& operator=(DescriptorProto_ExtensionRange&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const DescriptorProto_ExtensionRange& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const DescriptorProto_ExtensionRange& default_instance() { + return *internal_default_instance(); + } static inline const DescriptorProto_ExtensionRange* internal_default_instance() { return reinterpret_cast( &_DescriptorProto_ExtensionRange_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 2; - void Swap(DescriptorProto_ExtensionRange* other); friend void swap(DescriptorProto_ExtensionRange& a, DescriptorProto_ExtensionRange& b) { a.Swap(&b); } + inline void Swap(DescriptorProto_ExtensionRange* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(DescriptorProto_ExtensionRange* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline DescriptorProto_ExtensionRange* New() const PROTOBUF_FINAL { return New(NULL); } + inline DescriptorProto_ExtensionRange* New() const final { + return CreateMaybeMessage(nullptr); + } - DescriptorProto_ExtensionRange* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + DescriptorProto_ExtensionRange* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const DescriptorProto_ExtensionRange& from); void MergeFrom(const DescriptorProto_ExtensionRange& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(DescriptorProto_ExtensionRange* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(DescriptorProto_ExtensionRange* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.DescriptorProto.ExtensionRange"; } + protected: + explicit DescriptorProto_ExtensionRange(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kOptionsFieldNumber = 3, + kStartFieldNumber = 1, + kEndFieldNumber = 2, + }; // optional .google.protobuf.ExtensionRangeOptions options = 3; bool has_options() const; + private: + bool _internal_has_options() const; + public: void clear_options(); - static const int kOptionsFieldNumber = 3; - const ::google::protobuf::ExtensionRangeOptions& options() const; - ::google::protobuf::ExtensionRangeOptions* mutable_options(); - ::google::protobuf::ExtensionRangeOptions* release_options(); - void set_allocated_options(::google::protobuf::ExtensionRangeOptions* options); + const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& options() const; + PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* release_options(); + PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* mutable_options(); + void set_allocated_options(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options); + private: + const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& _internal_options() const; + PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options); + PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* unsafe_arena_release_options(); // optional int32 start = 1; bool has_start() const; + private: + bool _internal_has_start() const; + public: void clear_start(); - static const int kStartFieldNumber = 1; - ::google::protobuf::int32 start() const; - void set_start(::google::protobuf::int32 value); + ::PROTOBUF_NAMESPACE_ID::int32 start() const; + void set_start(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_start() const; + void _internal_set_start(::PROTOBUF_NAMESPACE_ID::int32 value); + public: // optional int32 end = 2; bool has_end() const; + private: + bool _internal_has_end() const; + public: void clear_end(); - static const int kEndFieldNumber = 2; - ::google::protobuf::int32 end() const; - void set_end(::google::protobuf::int32 value); + ::PROTOBUF_NAMESPACE_ID::int32 end() const; + void set_end(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_end() const; + void _internal_set_end(::PROTOBUF_NAMESPACE_ID::int32 value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange) private: - void set_has_start(); - void clear_has_start(); - void set_has_end(); - void clear_has_end(); - void set_has_options(); - void clear_has_options(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::ExtensionRangeOptions* options_; - ::google::protobuf::int32 start_; - ::google::protobuf::int32 end_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options_; + ::PROTOBUF_NAMESPACE_ID::int32 start_; + ::PROTOBUF_NAMESPACE_ID::int32 end_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT DescriptorProto_ReservedRange : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto.ReservedRange) */ { +class PROTOBUF_EXPORT DescriptorProto_ReservedRange PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto.ReservedRange) */ { public: - DescriptorProto_ReservedRange(); + inline DescriptorProto_ReservedRange() : DescriptorProto_ReservedRange(nullptr) {} virtual ~DescriptorProto_ReservedRange(); + explicit constexpr DescriptorProto_ReservedRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from); - - inline DescriptorProto_ReservedRange& operator=(const DescriptorProto_ReservedRange& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 DescriptorProto_ReservedRange(DescriptorProto_ReservedRange&& from) noexcept : DescriptorProto_ReservedRange() { *this = ::std::move(from); } + inline DescriptorProto_ReservedRange& operator=(const DescriptorProto_ReservedRange& from) { + CopyFrom(from); + return *this; + } inline DescriptorProto_ReservedRange& operator=(DescriptorProto_ReservedRange&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const DescriptorProto_ReservedRange& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const DescriptorProto_ReservedRange& default_instance() { + return *internal_default_instance(); + } static inline const DescriptorProto_ReservedRange* internal_default_instance() { return reinterpret_cast( &_DescriptorProto_ReservedRange_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 3; - void Swap(DescriptorProto_ReservedRange* other); friend void swap(DescriptorProto_ReservedRange& a, DescriptorProto_ReservedRange& b) { a.Swap(&b); } + inline void Swap(DescriptorProto_ReservedRange* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(DescriptorProto_ReservedRange* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline DescriptorProto_ReservedRange* New() const PROTOBUF_FINAL { return New(NULL); } + inline DescriptorProto_ReservedRange* New() const final { + return CreateMaybeMessage(nullptr); + } - DescriptorProto_ReservedRange* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + DescriptorProto_ReservedRange* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const DescriptorProto_ReservedRange& from); void MergeFrom(const DescriptorProto_ReservedRange& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(DescriptorProto_ReservedRange* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(DescriptorProto_ReservedRange* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.DescriptorProto.ReservedRange"; } + protected: + explicit DescriptorProto_ReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kStartFieldNumber = 1, + kEndFieldNumber = 2, + }; // optional int32 start = 1; bool has_start() const; + private: + bool _internal_has_start() const; + public: void clear_start(); - static const int kStartFieldNumber = 1; - ::google::protobuf::int32 start() const; - void set_start(::google::protobuf::int32 value); + ::PROTOBUF_NAMESPACE_ID::int32 start() const; + void set_start(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_start() const; + void _internal_set_start(::PROTOBUF_NAMESPACE_ID::int32 value); + public: // optional int32 end = 2; bool has_end() const; + private: + bool _internal_has_end() const; + public: void clear_end(); - static const int kEndFieldNumber = 2; - ::google::protobuf::int32 end() const; - void set_end(::google::protobuf::int32 value); + ::PROTOBUF_NAMESPACE_ID::int32 end() const; + void set_end(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_end() const; + void _internal_set_end(::PROTOBUF_NAMESPACE_ID::int32 value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ReservedRange) private: - void set_has_start(); - void clear_has_start(); - void set_has_end(); - void clear_has_end(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::int32 start_; - ::google::protobuf::int32 end_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::int32 start_; + ::PROTOBUF_NAMESPACE_ID::int32 end_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto) */ { +class PROTOBUF_EXPORT DescriptorProto PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto) */ { public: - DescriptorProto(); + inline DescriptorProto() : DescriptorProto(nullptr) {} virtual ~DescriptorProto(); + explicit constexpr DescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); DescriptorProto(const DescriptorProto& from); - - inline DescriptorProto& operator=(const DescriptorProto& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 DescriptorProto(DescriptorProto&& from) noexcept : DescriptorProto() { *this = ::std::move(from); } + inline DescriptorProto& operator=(const DescriptorProto& from) { + CopyFrom(from); + return *this; + } inline DescriptorProto& operator=(DescriptorProto&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const DescriptorProto& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const DescriptorProto& default_instance() { + return *internal_default_instance(); + } static inline const DescriptorProto* internal_default_instance() { return reinterpret_cast( &_DescriptorProto_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 4; - void Swap(DescriptorProto* other); friend void swap(DescriptorProto& a, DescriptorProto& b) { a.Swap(&b); } + inline void Swap(DescriptorProto* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(DescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline DescriptorProto* New() const PROTOBUF_FINAL { return New(NULL); } + inline DescriptorProto* New() const final { + return CreateMaybeMessage(nullptr); + } - DescriptorProto* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + DescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const DescriptorProto& from); void MergeFrom(const DescriptorProto& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(DescriptorProto* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(DescriptorProto* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.DescriptorProto"; } + protected: + explicit DescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- @@ -996,1704 +1347,2584 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message /* // accessors ------------------------------------------------------- + enum : int { + kFieldFieldNumber = 2, + kNestedTypeFieldNumber = 3, + kEnumTypeFieldNumber = 4, + kExtensionRangeFieldNumber = 5, + kExtensionFieldNumber = 6, + kOneofDeclFieldNumber = 8, + kReservedRangeFieldNumber = 9, + kReservedNameFieldNumber = 10, + kNameFieldNumber = 1, + kOptionsFieldNumber = 7, + }; // repeated .google.protobuf.FieldDescriptorProto field = 2; int field_size() const; + private: + int _internal_field_size() const; + public: void clear_field(); - static const int kFieldFieldNumber = 2; - const ::google::protobuf::FieldDescriptorProto& field(int index) const; - ::google::protobuf::FieldDescriptorProto* mutable_field(int index); - ::google::protobuf::FieldDescriptorProto* add_field(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* + PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* mutable_field(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >* mutable_field(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + private: + const PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& _internal_field(int index) const; + PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* _internal_add_field(); + public: + const PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& field(int index) const; + PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* add_field(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >& field() const; // repeated .google.protobuf.DescriptorProto nested_type = 3; int nested_type_size() const; + private: + int _internal_nested_type_size() const; + public: void clear_nested_type(); - static const int kNestedTypeFieldNumber = 3; - const ::google::protobuf::DescriptorProto& nested_type(int index) const; - ::google::protobuf::DescriptorProto* mutable_nested_type(int index); - ::google::protobuf::DescriptorProto* add_nested_type(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* + PROTOBUF_NAMESPACE_ID::DescriptorProto* mutable_nested_type(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto >* mutable_nested_type(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& + private: + const PROTOBUF_NAMESPACE_ID::DescriptorProto& _internal_nested_type(int index) const; + PROTOBUF_NAMESPACE_ID::DescriptorProto* _internal_add_nested_type(); + public: + const PROTOBUF_NAMESPACE_ID::DescriptorProto& nested_type(int index) const; + PROTOBUF_NAMESPACE_ID::DescriptorProto* add_nested_type(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto >& nested_type() const; // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; int enum_type_size() const; + private: + int _internal_enum_type_size() const; + public: void clear_enum_type(); - static const int kEnumTypeFieldNumber = 4; - const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const; - ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index); - ::google::protobuf::EnumDescriptorProto* add_enum_type(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* + PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* mutable_enum_type(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >* mutable_enum_type(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& + private: + const PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& _internal_enum_type(int index) const; + PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* _internal_add_enum_type(); + public: + const PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& enum_type(int index) const; + PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* add_enum_type(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >& enum_type() const; // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; int extension_range_size() const; + private: + int _internal_extension_range_size() const; + public: void clear_extension_range(); - static const int kExtensionRangeFieldNumber = 5; - const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const; - ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index); - ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* + PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* mutable_extension_range(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange >* mutable_extension_range(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& + private: + const PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange& _internal_extension_range(int index) const; + PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* _internal_add_extension_range(); + public: + const PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange& extension_range(int index) const; + PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* add_extension_range(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange >& extension_range() const; // repeated .google.protobuf.FieldDescriptorProto extension = 6; int extension_size() const; + private: + int _internal_extension_size() const; + public: void clear_extension(); - static const int kExtensionFieldNumber = 6; - const ::google::protobuf::FieldDescriptorProto& extension(int index) const; - ::google::protobuf::FieldDescriptorProto* mutable_extension(int index); - ::google::protobuf::FieldDescriptorProto* add_extension(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* + PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* mutable_extension(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >* mutable_extension(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + private: + const PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& _internal_extension(int index) const; + PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* _internal_add_extension(); + public: + const PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& extension(int index) const; + PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* add_extension(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >& extension() const; // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; int oneof_decl_size() const; + private: + int _internal_oneof_decl_size() const; + public: void clear_oneof_decl(); - static const int kOneofDeclFieldNumber = 8; - const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const; - ::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index); - ::google::protobuf::OneofDescriptorProto* add_oneof_decl(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* + PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* mutable_oneof_decl(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::OneofDescriptorProto >* mutable_oneof_decl(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& + private: + const PROTOBUF_NAMESPACE_ID::OneofDescriptorProto& _internal_oneof_decl(int index) const; + PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* _internal_add_oneof_decl(); + public: + const PROTOBUF_NAMESPACE_ID::OneofDescriptorProto& oneof_decl(int index) const; + PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* add_oneof_decl(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::OneofDescriptorProto >& oneof_decl() const; // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; int reserved_range_size() const; + private: + int _internal_reserved_range_size() const; + public: void clear_reserved_range(); - static const int kReservedRangeFieldNumber = 9; - const ::google::protobuf::DescriptorProto_ReservedRange& reserved_range(int index) const; - ::google::protobuf::DescriptorProto_ReservedRange* mutable_reserved_range(int index); - ::google::protobuf::DescriptorProto_ReservedRange* add_reserved_range(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >* + PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* mutable_reserved_range(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange >* mutable_reserved_range(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >& + private: + const PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange& _internal_reserved_range(int index) const; + PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* _internal_add_reserved_range(); + public: + const PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange& reserved_range(int index) const; + PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* add_reserved_range(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange >& reserved_range() const; // repeated string reserved_name = 10; int reserved_name_size() const; + private: + int _internal_reserved_name_size() const; + public: void clear_reserved_name(); - static const int kReservedNameFieldNumber = 10; - const ::std::string& reserved_name(int index) const; - ::std::string* mutable_reserved_name(int index); - void set_reserved_name(int index, const ::std::string& value); - #if LANG_CXX11 - void set_reserved_name(int index, ::std::string&& value); - #endif + const std::string& reserved_name(int index) const; + std::string* mutable_reserved_name(int index); + void set_reserved_name(int index, const std::string& value); + void set_reserved_name(int index, std::string&& value); void set_reserved_name(int index, const char* value); void set_reserved_name(int index, const char* value, size_t size); - ::std::string* add_reserved_name(); - void add_reserved_name(const ::std::string& value); - #if LANG_CXX11 - void add_reserved_name(::std::string&& value); - #endif + std::string* add_reserved_name(); + void add_reserved_name(const std::string& value); + void add_reserved_name(std::string&& value); void add_reserved_name(const char* value); void add_reserved_name(const char* value, size_t size); - const ::google::protobuf::RepeatedPtrField< ::std::string>& reserved_name() const; - ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_reserved_name(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField& reserved_name() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField* mutable_reserved_name(); + private: + const std::string& _internal_reserved_name(int index) const; + std::string* _internal_add_reserved_name(); + public: // optional string name = 1; bool has_name() const; + private: + bool _internal_has_name() const; + public: void clear_name(); - static const int kNameFieldNumber = 1; - const ::std::string& name() const; - void set_name(const ::std::string& value); - #if LANG_CXX11 - void set_name(::std::string&& value); - #endif + const std::string& name() const; + void set_name(const std::string& value); + void set_name(std::string&& value); void set_name(const char* value); void set_name(const char* value, size_t size); - ::std::string* mutable_name(); - ::std::string* release_name(); - void set_allocated_name(::std::string* name); + std::string* mutable_name(); + std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: // optional .google.protobuf.MessageOptions options = 7; bool has_options() const; + private: + bool _internal_has_options() const; + public: void clear_options(); - static const int kOptionsFieldNumber = 7; - const ::google::protobuf::MessageOptions& options() const; - ::google::protobuf::MessageOptions* mutable_options(); - ::google::protobuf::MessageOptions* release_options(); - void set_allocated_options(::google::protobuf::MessageOptions* options); + const PROTOBUF_NAMESPACE_ID::MessageOptions& options() const; + PROTOBUF_NAMESPACE_ID::MessageOptions* release_options(); + PROTOBUF_NAMESPACE_ID::MessageOptions* mutable_options(); + void set_allocated_options(PROTOBUF_NAMESPACE_ID::MessageOptions* options); + private: + const PROTOBUF_NAMESPACE_ID::MessageOptions& _internal_options() const; + PROTOBUF_NAMESPACE_ID::MessageOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::MessageOptions* options); + PROTOBUF_NAMESPACE_ID::MessageOptions* unsafe_arena_release_options(); // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto) private: - void set_has_name(); - void clear_has_name(); - void set_has_options(); - void clear_has_options(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > field_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > nested_type_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange > extension_range_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto > oneof_decl_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange > reserved_range_; - ::google::protobuf::RepeatedPtrField< ::std::string> reserved_name_; - ::google::protobuf::internal::ArenaStringPtr name_; - ::google::protobuf::MessageOptions* options_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto > field_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto > nested_type_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto > enum_type_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange > extension_range_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto > extension_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::OneofDescriptorProto > oneof_decl_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange > reserved_range_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField reserved_name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + PROTOBUF_NAMESPACE_ID::MessageOptions* options_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT ExtensionRangeOptions : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ExtensionRangeOptions) */ { +class PROTOBUF_EXPORT ExtensionRangeOptions PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ExtensionRangeOptions) */ { public: - ExtensionRangeOptions(); + inline ExtensionRangeOptions() : ExtensionRangeOptions(nullptr) {} virtual ~ExtensionRangeOptions(); + explicit constexpr ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); ExtensionRangeOptions(const ExtensionRangeOptions& from); - - inline ExtensionRangeOptions& operator=(const ExtensionRangeOptions& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 ExtensionRangeOptions(ExtensionRangeOptions&& from) noexcept : ExtensionRangeOptions() { *this = ::std::move(from); } + inline ExtensionRangeOptions& operator=(const ExtensionRangeOptions& from) { + CopyFrom(from); + return *this; + } inline ExtensionRangeOptions& operator=(ExtensionRangeOptions&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const ExtensionRangeOptions& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const ExtensionRangeOptions& default_instance() { + return *internal_default_instance(); + } static inline const ExtensionRangeOptions* internal_default_instance() { return reinterpret_cast( &_ExtensionRangeOptions_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 5; - void Swap(ExtensionRangeOptions* other); friend void swap(ExtensionRangeOptions& a, ExtensionRangeOptions& b) { a.Swap(&b); } + inline void Swap(ExtensionRangeOptions* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ExtensionRangeOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline ExtensionRangeOptions* New() const PROTOBUF_FINAL { return New(NULL); } + inline ExtensionRangeOptions* New() const final { + return CreateMaybeMessage(nullptr); + } - ExtensionRangeOptions* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + ExtensionRangeOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const ExtensionRangeOptions& from); void MergeFrom(const ExtensionRangeOptions& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(ExtensionRangeOptions* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(ExtensionRangeOptions* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.ExtensionRangeOptions"; } + protected: + explicit ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kUninterpretedOptionFieldNumber = 999, + }; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: void clear_uninterpreted_option(); - static const int kUninterpretedOptionFieldNumber = 999; - const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* mutable_uninterpreted_option(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + private: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& uninterpreted_option() const; GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ExtensionRangeOptions) // @@protoc_insertion_point(class_scope:google.protobuf.ExtensionRangeOptions) private: + class _Internal; - ::google::protobuf::internal::ExtensionSet _extensions_; + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldDescriptorProto) */ { +class PROTOBUF_EXPORT FieldDescriptorProto PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldDescriptorProto) */ { public: - FieldDescriptorProto(); + inline FieldDescriptorProto() : FieldDescriptorProto(nullptr) {} virtual ~FieldDescriptorProto(); + explicit constexpr FieldDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); FieldDescriptorProto(const FieldDescriptorProto& from); - - inline FieldDescriptorProto& operator=(const FieldDescriptorProto& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 FieldDescriptorProto(FieldDescriptorProto&& from) noexcept : FieldDescriptorProto() { *this = ::std::move(from); } + inline FieldDescriptorProto& operator=(const FieldDescriptorProto& from) { + CopyFrom(from); + return *this; + } inline FieldDescriptorProto& operator=(FieldDescriptorProto&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const FieldDescriptorProto& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const FieldDescriptorProto& default_instance() { + return *internal_default_instance(); + } static inline const FieldDescriptorProto* internal_default_instance() { return reinterpret_cast( &_FieldDescriptorProto_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 6; - void Swap(FieldDescriptorProto* other); friend void swap(FieldDescriptorProto& a, FieldDescriptorProto& b) { a.Swap(&b); } + inline void Swap(FieldDescriptorProto* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FieldDescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline FieldDescriptorProto* New() const PROTOBUF_FINAL { return New(NULL); } + inline FieldDescriptorProto* New() const final { + return CreateMaybeMessage(nullptr); + } - FieldDescriptorProto* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + FieldDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const FieldDescriptorProto& from); void MergeFrom(const FieldDescriptorProto& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(FieldDescriptorProto* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(FieldDescriptorProto* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.FieldDescriptorProto"; } + protected: + explicit FieldDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- typedef FieldDescriptorProto_Type Type; - static const Type TYPE_DOUBLE = + static constexpr Type TYPE_DOUBLE = FieldDescriptorProto_Type_TYPE_DOUBLE; - static const Type TYPE_FLOAT = + static constexpr Type TYPE_FLOAT = FieldDescriptorProto_Type_TYPE_FLOAT; - static const Type TYPE_INT64 = + static constexpr Type TYPE_INT64 = FieldDescriptorProto_Type_TYPE_INT64; - static const Type TYPE_UINT64 = + static constexpr Type TYPE_UINT64 = FieldDescriptorProto_Type_TYPE_UINT64; - static const Type TYPE_INT32 = + static constexpr Type TYPE_INT32 = FieldDescriptorProto_Type_TYPE_INT32; - static const Type TYPE_FIXED64 = + static constexpr Type TYPE_FIXED64 = FieldDescriptorProto_Type_TYPE_FIXED64; - static const Type TYPE_FIXED32 = + static constexpr Type TYPE_FIXED32 = FieldDescriptorProto_Type_TYPE_FIXED32; - static const Type TYPE_BOOL = + static constexpr Type TYPE_BOOL = FieldDescriptorProto_Type_TYPE_BOOL; - static const Type TYPE_STRING = + static constexpr Type TYPE_STRING = FieldDescriptorProto_Type_TYPE_STRING; - static const Type TYPE_GROUP = + static constexpr Type TYPE_GROUP = FieldDescriptorProto_Type_TYPE_GROUP; - static const Type TYPE_MESSAGE = + static constexpr Type TYPE_MESSAGE = FieldDescriptorProto_Type_TYPE_MESSAGE; - static const Type TYPE_BYTES = + static constexpr Type TYPE_BYTES = FieldDescriptorProto_Type_TYPE_BYTES; - static const Type TYPE_UINT32 = + static constexpr Type TYPE_UINT32 = FieldDescriptorProto_Type_TYPE_UINT32; - static const Type TYPE_ENUM = + static constexpr Type TYPE_ENUM = FieldDescriptorProto_Type_TYPE_ENUM; - static const Type TYPE_SFIXED32 = + static constexpr Type TYPE_SFIXED32 = FieldDescriptorProto_Type_TYPE_SFIXED32; - static const Type TYPE_SFIXED64 = + static constexpr Type TYPE_SFIXED64 = FieldDescriptorProto_Type_TYPE_SFIXED64; - static const Type TYPE_SINT32 = + static constexpr Type TYPE_SINT32 = FieldDescriptorProto_Type_TYPE_SINT32; - static const Type TYPE_SINT64 = + static constexpr Type TYPE_SINT64 = FieldDescriptorProto_Type_TYPE_SINT64; static inline bool Type_IsValid(int value) { return FieldDescriptorProto_Type_IsValid(value); } - static const Type Type_MIN = + static constexpr Type Type_MIN = FieldDescriptorProto_Type_Type_MIN; - static const Type Type_MAX = + static constexpr Type Type_MAX = FieldDescriptorProto_Type_Type_MAX; - static const int Type_ARRAYSIZE = + static constexpr int Type_ARRAYSIZE = FieldDescriptorProto_Type_Type_ARRAYSIZE; - static inline const ::google::protobuf::EnumDescriptor* + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Type_descriptor() { return FieldDescriptorProto_Type_descriptor(); } - static inline const ::std::string& Type_Name(Type value) { - return FieldDescriptorProto_Type_Name(value); + template + static inline const std::string& Type_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function Type_Name."); + return FieldDescriptorProto_Type_Name(enum_t_value); } - static inline bool Type_Parse(const ::std::string& name, + static inline bool Type_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, Type* value) { return FieldDescriptorProto_Type_Parse(name, value); } typedef FieldDescriptorProto_Label Label; - static const Label LABEL_OPTIONAL = + static constexpr Label LABEL_OPTIONAL = FieldDescriptorProto_Label_LABEL_OPTIONAL; - static const Label LABEL_REQUIRED = + static constexpr Label LABEL_REQUIRED = FieldDescriptorProto_Label_LABEL_REQUIRED; - static const Label LABEL_REPEATED = + static constexpr Label LABEL_REPEATED = FieldDescriptorProto_Label_LABEL_REPEATED; static inline bool Label_IsValid(int value) { return FieldDescriptorProto_Label_IsValid(value); } - static const Label Label_MIN = + static constexpr Label Label_MIN = FieldDescriptorProto_Label_Label_MIN; - static const Label Label_MAX = + static constexpr Label Label_MAX = FieldDescriptorProto_Label_Label_MAX; - static const int Label_ARRAYSIZE = + static constexpr int Label_ARRAYSIZE = FieldDescriptorProto_Label_Label_ARRAYSIZE; - static inline const ::google::protobuf::EnumDescriptor* + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Label_descriptor() { return FieldDescriptorProto_Label_descriptor(); } - static inline const ::std::string& Label_Name(Label value) { - return FieldDescriptorProto_Label_Name(value); + template + static inline const std::string& Label_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function Label_Name."); + return FieldDescriptorProto_Label_Name(enum_t_value); } - static inline bool Label_Parse(const ::std::string& name, + static inline bool Label_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, Label* value) { return FieldDescriptorProto_Label_Parse(name, value); } // accessors ------------------------------------------------------- + enum : int { + kNameFieldNumber = 1, + kExtendeeFieldNumber = 2, + kTypeNameFieldNumber = 6, + kDefaultValueFieldNumber = 7, + kJsonNameFieldNumber = 10, + kOptionsFieldNumber = 8, + kNumberFieldNumber = 3, + kOneofIndexFieldNumber = 9, + kProto3OptionalFieldNumber = 17, + kLabelFieldNumber = 4, + kTypeFieldNumber = 5, + }; // optional string name = 1; bool has_name() const; + private: + bool _internal_has_name() const; + public: void clear_name(); - static const int kNameFieldNumber = 1; - const ::std::string& name() const; - void set_name(const ::std::string& value); - #if LANG_CXX11 - void set_name(::std::string&& value); - #endif + const std::string& name() const; + void set_name(const std::string& value); + void set_name(std::string&& value); void set_name(const char* value); void set_name(const char* value, size_t size); - ::std::string* mutable_name(); - ::std::string* release_name(); - void set_allocated_name(::std::string* name); + std::string* mutable_name(); + std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: // optional string extendee = 2; bool has_extendee() const; + private: + bool _internal_has_extendee() const; + public: void clear_extendee(); - static const int kExtendeeFieldNumber = 2; - const ::std::string& extendee() const; - void set_extendee(const ::std::string& value); - #if LANG_CXX11 - void set_extendee(::std::string&& value); - #endif + const std::string& extendee() const; + void set_extendee(const std::string& value); + void set_extendee(std::string&& value); void set_extendee(const char* value); void set_extendee(const char* value, size_t size); - ::std::string* mutable_extendee(); - ::std::string* release_extendee(); - void set_allocated_extendee(::std::string* extendee); + std::string* mutable_extendee(); + std::string* release_extendee(); + void set_allocated_extendee(std::string* extendee); + private: + const std::string& _internal_extendee() const; + void _internal_set_extendee(const std::string& value); + std::string* _internal_mutable_extendee(); + public: // optional string type_name = 6; bool has_type_name() const; + private: + bool _internal_has_type_name() const; + public: void clear_type_name(); - static const int kTypeNameFieldNumber = 6; - const ::std::string& type_name() const; - void set_type_name(const ::std::string& value); - #if LANG_CXX11 - void set_type_name(::std::string&& value); - #endif + const std::string& type_name() const; + void set_type_name(const std::string& value); + void set_type_name(std::string&& value); void set_type_name(const char* value); void set_type_name(const char* value, size_t size); - ::std::string* mutable_type_name(); - ::std::string* release_type_name(); - void set_allocated_type_name(::std::string* type_name); + std::string* mutable_type_name(); + std::string* release_type_name(); + void set_allocated_type_name(std::string* type_name); + private: + const std::string& _internal_type_name() const; + void _internal_set_type_name(const std::string& value); + std::string* _internal_mutable_type_name(); + public: // optional string default_value = 7; bool has_default_value() const; + private: + bool _internal_has_default_value() const; + public: void clear_default_value(); - static const int kDefaultValueFieldNumber = 7; - const ::std::string& default_value() const; - void set_default_value(const ::std::string& value); - #if LANG_CXX11 - void set_default_value(::std::string&& value); - #endif + const std::string& default_value() const; + void set_default_value(const std::string& value); + void set_default_value(std::string&& value); void set_default_value(const char* value); void set_default_value(const char* value, size_t size); - ::std::string* mutable_default_value(); - ::std::string* release_default_value(); - void set_allocated_default_value(::std::string* default_value); + std::string* mutable_default_value(); + std::string* release_default_value(); + void set_allocated_default_value(std::string* default_value); + private: + const std::string& _internal_default_value() const; + void _internal_set_default_value(const std::string& value); + std::string* _internal_mutable_default_value(); + public: // optional string json_name = 10; bool has_json_name() const; + private: + bool _internal_has_json_name() const; + public: void clear_json_name(); - static const int kJsonNameFieldNumber = 10; - const ::std::string& json_name() const; - void set_json_name(const ::std::string& value); - #if LANG_CXX11 - void set_json_name(::std::string&& value); - #endif + const std::string& json_name() const; + void set_json_name(const std::string& value); + void set_json_name(std::string&& value); void set_json_name(const char* value); void set_json_name(const char* value, size_t size); - ::std::string* mutable_json_name(); - ::std::string* release_json_name(); - void set_allocated_json_name(::std::string* json_name); + std::string* mutable_json_name(); + std::string* release_json_name(); + void set_allocated_json_name(std::string* json_name); + private: + const std::string& _internal_json_name() const; + void _internal_set_json_name(const std::string& value); + std::string* _internal_mutable_json_name(); + public: // optional .google.protobuf.FieldOptions options = 8; bool has_options() const; + private: + bool _internal_has_options() const; + public: void clear_options(); - static const int kOptionsFieldNumber = 8; - const ::google::protobuf::FieldOptions& options() const; - ::google::protobuf::FieldOptions* mutable_options(); - ::google::protobuf::FieldOptions* release_options(); - void set_allocated_options(::google::protobuf::FieldOptions* options); + const PROTOBUF_NAMESPACE_ID::FieldOptions& options() const; + PROTOBUF_NAMESPACE_ID::FieldOptions* release_options(); + PROTOBUF_NAMESPACE_ID::FieldOptions* mutable_options(); + void set_allocated_options(PROTOBUF_NAMESPACE_ID::FieldOptions* options); + private: + const PROTOBUF_NAMESPACE_ID::FieldOptions& _internal_options() const; + PROTOBUF_NAMESPACE_ID::FieldOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::FieldOptions* options); + PROTOBUF_NAMESPACE_ID::FieldOptions* unsafe_arena_release_options(); // optional int32 number = 3; bool has_number() const; + private: + bool _internal_has_number() const; + public: void clear_number(); - static const int kNumberFieldNumber = 3; - ::google::protobuf::int32 number() const; - void set_number(::google::protobuf::int32 value); + ::PROTOBUF_NAMESPACE_ID::int32 number() const; + void set_number(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_number() const; + void _internal_set_number(::PROTOBUF_NAMESPACE_ID::int32 value); + public: // optional int32 oneof_index = 9; bool has_oneof_index() const; + private: + bool _internal_has_oneof_index() const; + public: void clear_oneof_index(); - static const int kOneofIndexFieldNumber = 9; - ::google::protobuf::int32 oneof_index() const; - void set_oneof_index(::google::protobuf::int32 value); + ::PROTOBUF_NAMESPACE_ID::int32 oneof_index() const; + void set_oneof_index(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_oneof_index() const; + void _internal_set_oneof_index(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // optional bool proto3_optional = 17; + bool has_proto3_optional() const; + private: + bool _internal_has_proto3_optional() const; + public: + void clear_proto3_optional(); + bool proto3_optional() const; + void set_proto3_optional(bool value); + private: + bool _internal_proto3_optional() const; + void _internal_set_proto3_optional(bool value); + public: // optional .google.protobuf.FieldDescriptorProto.Label label = 4; bool has_label() const; + private: + bool _internal_has_label() const; + public: void clear_label(); - static const int kLabelFieldNumber = 4; - ::google::protobuf::FieldDescriptorProto_Label label() const; - void set_label(::google::protobuf::FieldDescriptorProto_Label value); + PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label label() const; + void set_label(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label value); + private: + PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label _internal_label() const; + void _internal_set_label(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label value); + public: // optional .google.protobuf.FieldDescriptorProto.Type type = 5; bool has_type() const; + private: + bool _internal_has_type() const; + public: void clear_type(); - static const int kTypeFieldNumber = 5; - ::google::protobuf::FieldDescriptorProto_Type type() const; - void set_type(::google::protobuf::FieldDescriptorProto_Type value); + PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type type() const; + void set_type(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type value); + private: + PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type _internal_type() const; + void _internal_set_type(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto) private: - void set_has_name(); - void clear_has_name(); - void set_has_number(); - void clear_has_number(); - void set_has_label(); - void clear_has_label(); - void set_has_type(); - void clear_has_type(); - void set_has_type_name(); - void clear_has_type_name(); - void set_has_extendee(); - void clear_has_extendee(); - void set_has_default_value(); - void clear_has_default_value(); - void set_has_oneof_index(); - void clear_has_oneof_index(); - void set_has_json_name(); - void clear_has_json_name(); - void set_has_options(); - void clear_has_options(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::internal::ArenaStringPtr name_; - ::google::protobuf::internal::ArenaStringPtr extendee_; - ::google::protobuf::internal::ArenaStringPtr type_name_; - ::google::protobuf::internal::ArenaStringPtr default_value_; - ::google::protobuf::internal::ArenaStringPtr json_name_; - ::google::protobuf::FieldOptions* options_; - ::google::protobuf::int32 number_; - ::google::protobuf::int32 oneof_index_; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr extendee_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr type_name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr default_value_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr json_name_; + PROTOBUF_NAMESPACE_ID::FieldOptions* options_; + ::PROTOBUF_NAMESPACE_ID::int32 number_; + ::PROTOBUF_NAMESPACE_ID::int32 oneof_index_; + bool proto3_optional_; int label_; int type_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT OneofDescriptorProto : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.OneofDescriptorProto) */ { +class PROTOBUF_EXPORT OneofDescriptorProto PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.OneofDescriptorProto) */ { public: - OneofDescriptorProto(); + inline OneofDescriptorProto() : OneofDescriptorProto(nullptr) {} virtual ~OneofDescriptorProto(); + explicit constexpr OneofDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); OneofDescriptorProto(const OneofDescriptorProto& from); - - inline OneofDescriptorProto& operator=(const OneofDescriptorProto& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 OneofDescriptorProto(OneofDescriptorProto&& from) noexcept : OneofDescriptorProto() { *this = ::std::move(from); } + inline OneofDescriptorProto& operator=(const OneofDescriptorProto& from) { + CopyFrom(from); + return *this; + } inline OneofDescriptorProto& operator=(OneofDescriptorProto&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const OneofDescriptorProto& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const OneofDescriptorProto& default_instance() { + return *internal_default_instance(); + } static inline const OneofDescriptorProto* internal_default_instance() { return reinterpret_cast( &_OneofDescriptorProto_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 7; - void Swap(OneofDescriptorProto* other); friend void swap(OneofDescriptorProto& a, OneofDescriptorProto& b) { a.Swap(&b); } + inline void Swap(OneofDescriptorProto* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(OneofDescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline OneofDescriptorProto* New() const PROTOBUF_FINAL { return New(NULL); } + inline OneofDescriptorProto* New() const final { + return CreateMaybeMessage(nullptr); + } - OneofDescriptorProto* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + OneofDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const OneofDescriptorProto& from); void MergeFrom(const OneofDescriptorProto& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(OneofDescriptorProto* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(OneofDescriptorProto* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.OneofDescriptorProto"; } + protected: + explicit OneofDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kNameFieldNumber = 1, + kOptionsFieldNumber = 2, + }; // optional string name = 1; bool has_name() const; + private: + bool _internal_has_name() const; + public: void clear_name(); - static const int kNameFieldNumber = 1; - const ::std::string& name() const; - void set_name(const ::std::string& value); - #if LANG_CXX11 - void set_name(::std::string&& value); - #endif + const std::string& name() const; + void set_name(const std::string& value); + void set_name(std::string&& value); void set_name(const char* value); void set_name(const char* value, size_t size); - ::std::string* mutable_name(); - ::std::string* release_name(); - void set_allocated_name(::std::string* name); + std::string* mutable_name(); + std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: // optional .google.protobuf.OneofOptions options = 2; bool has_options() const; + private: + bool _internal_has_options() const; + public: void clear_options(); - static const int kOptionsFieldNumber = 2; - const ::google::protobuf::OneofOptions& options() const; - ::google::protobuf::OneofOptions* mutable_options(); - ::google::protobuf::OneofOptions* release_options(); - void set_allocated_options(::google::protobuf::OneofOptions* options); + const PROTOBUF_NAMESPACE_ID::OneofOptions& options() const; + PROTOBUF_NAMESPACE_ID::OneofOptions* release_options(); + PROTOBUF_NAMESPACE_ID::OneofOptions* mutable_options(); + void set_allocated_options(PROTOBUF_NAMESPACE_ID::OneofOptions* options); + private: + const PROTOBUF_NAMESPACE_ID::OneofOptions& _internal_options() const; + PROTOBUF_NAMESPACE_ID::OneofOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::OneofOptions* options); + PROTOBUF_NAMESPACE_ID::OneofOptions* unsafe_arena_release_options(); // @@protoc_insertion_point(class_scope:google.protobuf.OneofDescriptorProto) private: - void set_has_name(); - void clear_has_name(); - void set_has_options(); - void clear_has_options(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::internal::ArenaStringPtr name_; - ::google::protobuf::OneofOptions* options_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + PROTOBUF_NAMESPACE_ID::OneofOptions* options_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumDescriptorProto) */ { +class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumDescriptorProto.EnumReservedRange) */ { public: - EnumDescriptorProto(); - virtual ~EnumDescriptorProto(); + inline EnumDescriptorProto_EnumReservedRange() : EnumDescriptorProto_EnumReservedRange(nullptr) {} + virtual ~EnumDescriptorProto_EnumReservedRange(); + explicit constexpr EnumDescriptorProto_EnumReservedRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); - EnumDescriptorProto(const EnumDescriptorProto& from); + EnumDescriptorProto_EnumReservedRange(const EnumDescriptorProto_EnumReservedRange& from); + EnumDescriptorProto_EnumReservedRange(EnumDescriptorProto_EnumReservedRange&& from) noexcept + : EnumDescriptorProto_EnumReservedRange() { + *this = ::std::move(from); + } - inline EnumDescriptorProto& operator=(const EnumDescriptorProto& from) { + inline EnumDescriptorProto_EnumReservedRange& operator=(const EnumDescriptorProto_EnumReservedRange& from) { CopyFrom(from); return *this; } - #if LANG_CXX11 - EnumDescriptorProto(EnumDescriptorProto&& from) noexcept - : EnumDescriptorProto() { - *this = ::std::move(from); - } - - inline EnumDescriptorProto& operator=(EnumDescriptorProto&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + inline EnumDescriptorProto_EnumReservedRange& operator=(EnumDescriptorProto_EnumReservedRange&& from) noexcept { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const EnumDescriptorProto& default_instance(); - - static inline const EnumDescriptorProto* internal_default_instance() { - return reinterpret_cast( - &_EnumDescriptorProto_default_instance_); + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const EnumDescriptorProto_EnumReservedRange& default_instance() { + return *internal_default_instance(); + } + static inline const EnumDescriptorProto_EnumReservedRange* internal_default_instance() { + return reinterpret_cast( + &_EnumDescriptorProto_EnumReservedRange_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 8; - void Swap(EnumDescriptorProto* other); - friend void swap(EnumDescriptorProto& a, EnumDescriptorProto& b) { + friend void swap(EnumDescriptorProto_EnumReservedRange& a, EnumDescriptorProto_EnumReservedRange& b) { a.Swap(&b); } + inline void Swap(EnumDescriptorProto_EnumReservedRange* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(EnumDescriptorProto_EnumReservedRange* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline EnumDescriptorProto* New() const PROTOBUF_FINAL { return New(NULL); } - - EnumDescriptorProto* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void CopyFrom(const EnumDescriptorProto& from); - void MergeFrom(const EnumDescriptorProto& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(EnumDescriptorProto* other); - private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; + inline EnumDescriptorProto_EnumReservedRange* New() const final { + return CreateMaybeMessage(nullptr); } - inline void* MaybeArenaPtr() const { - return NULL; + + EnumDescriptorProto_EnumReservedRange* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const EnumDescriptorProto_EnumReservedRange& from); + void MergeFrom(const EnumDescriptorProto_EnumReservedRange& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(EnumDescriptorProto_EnumReservedRange* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.EnumDescriptorProto.EnumReservedRange"; + } + protected: + explicit EnumDescriptorProto_EnumReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- - // repeated .google.protobuf.EnumValueDescriptorProto value = 2; - int value_size() const; - void clear_value(); - static const int kValueFieldNumber = 2; - const ::google::protobuf::EnumValueDescriptorProto& value(int index) const; - ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index); - ::google::protobuf::EnumValueDescriptorProto* add_value(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* - mutable_value(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& - value() const; - - // optional string name = 1; - bool has_name() const; - void clear_name(); - static const int kNameFieldNumber = 1; - const ::std::string& name() const; - void set_name(const ::std::string& value); - #if LANG_CXX11 - void set_name(::std::string&& value); - #endif - void set_name(const char* value); - void set_name(const char* value, size_t size); - ::std::string* mutable_name(); - ::std::string* release_name(); - void set_allocated_name(::std::string* name); + enum : int { + kStartFieldNumber = 1, + kEndFieldNumber = 2, + }; + // optional int32 start = 1; + bool has_start() const; + private: + bool _internal_has_start() const; + public: + void clear_start(); + ::PROTOBUF_NAMESPACE_ID::int32 start() const; + void set_start(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_start() const; + void _internal_set_start(::PROTOBUF_NAMESPACE_ID::int32 value); + public: - // optional .google.protobuf.EnumOptions options = 3; - bool has_options() const; - void clear_options(); - static const int kOptionsFieldNumber = 3; - const ::google::protobuf::EnumOptions& options() const; - ::google::protobuf::EnumOptions* mutable_options(); - ::google::protobuf::EnumOptions* release_options(); - void set_allocated_options(::google::protobuf::EnumOptions* options); + // optional int32 end = 2; + bool has_end() const; + private: + bool _internal_has_end() const; + public: + void clear_end(); + ::PROTOBUF_NAMESPACE_ID::int32 end() const; + void set_end(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_end() const; + void _internal_set_end(::PROTOBUF_NAMESPACE_ID::int32 value); + public: - // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto) + // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto.EnumReservedRange) private: - void set_has_name(); - void clear_has_name(); - void set_has_options(); - void clear_has_options(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_; - ::google::protobuf::internal::ArenaStringPtr name_; - ::google::protobuf::EnumOptions* options_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::int32 start_; + ::PROTOBUF_NAMESPACE_ID::int32 end_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValueDescriptorProto) */ { +class PROTOBUF_EXPORT EnumDescriptorProto PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumDescriptorProto) */ { public: - EnumValueDescriptorProto(); - virtual ~EnumValueDescriptorProto(); + inline EnumDescriptorProto() : EnumDescriptorProto(nullptr) {} + virtual ~EnumDescriptorProto(); + explicit constexpr EnumDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); - EnumValueDescriptorProto(const EnumValueDescriptorProto& from); + EnumDescriptorProto(const EnumDescriptorProto& from); + EnumDescriptorProto(EnumDescriptorProto&& from) noexcept + : EnumDescriptorProto() { + *this = ::std::move(from); + } - inline EnumValueDescriptorProto& operator=(const EnumValueDescriptorProto& from) { + inline EnumDescriptorProto& operator=(const EnumDescriptorProto& from) { CopyFrom(from); return *this; } - #if LANG_CXX11 - EnumValueDescriptorProto(EnumValueDescriptorProto&& from) noexcept - : EnumValueDescriptorProto() { - *this = ::std::move(from); - } - - inline EnumValueDescriptorProto& operator=(EnumValueDescriptorProto&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + inline EnumDescriptorProto& operator=(EnumDescriptorProto&& from) noexcept { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const EnumDescriptorProto& default_instance() { + return *internal_default_instance(); + } + static inline const EnumDescriptorProto* internal_default_instance() { + return reinterpret_cast( + &_EnumDescriptorProto_default_instance_); + } + static constexpr int kIndexInFileMessages = + 9; + + friend void swap(EnumDescriptorProto& a, EnumDescriptorProto& b) { + a.Swap(&b); + } + inline void Swap(EnumDescriptorProto* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(EnumDescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline EnumDescriptorProto* New() const final { + return CreateMaybeMessage(nullptr); + } + + EnumDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const EnumDescriptorProto& from); + void MergeFrom(const EnumDescriptorProto& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(EnumDescriptorProto* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.EnumDescriptorProto"; + } + protected: + explicit EnumDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: + + // nested types ---------------------------------------------------- + + typedef EnumDescriptorProto_EnumReservedRange EnumReservedRange; + + // accessors ------------------------------------------------------- + + enum : int { + kValueFieldNumber = 2, + kReservedRangeFieldNumber = 4, + kReservedNameFieldNumber = 5, + kNameFieldNumber = 1, + kOptionsFieldNumber = 3, + }; + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; + int value_size() const; + private: + int _internal_value_size() const; + public: + void clear_value(); + PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* mutable_value(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto >* + mutable_value(); + private: + const PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto& _internal_value(int index) const; + PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* _internal_add_value(); + public: + const PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto& value(int index) const; + PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* add_value(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto >& + value() const; + + // repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; + int reserved_range_size() const; + private: + int _internal_reserved_range_size() const; + public: + void clear_reserved_range(); + PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* mutable_reserved_range(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange >* + mutable_reserved_range(); + private: + const PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange& _internal_reserved_range(int index) const; + PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* _internal_add_reserved_range(); + public: + const PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange& reserved_range(int index) const; + PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* add_reserved_range(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange >& + reserved_range() const; + + // repeated string reserved_name = 5; + int reserved_name_size() const; + private: + int _internal_reserved_name_size() const; + public: + void clear_reserved_name(); + const std::string& reserved_name(int index) const; + std::string* mutable_reserved_name(int index); + void set_reserved_name(int index, const std::string& value); + void set_reserved_name(int index, std::string&& value); + void set_reserved_name(int index, const char* value); + void set_reserved_name(int index, const char* value, size_t size); + std::string* add_reserved_name(); + void add_reserved_name(const std::string& value); + void add_reserved_name(std::string&& value); + void add_reserved_name(const char* value); + void add_reserved_name(const char* value, size_t size); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField& reserved_name() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField* mutable_reserved_name(); + private: + const std::string& _internal_reserved_name(int index) const; + std::string* _internal_add_reserved_name(); + public: + + // optional string name = 1; + bool has_name() const; + private: + bool _internal_has_name() const; + public: + void clear_name(); + const std::string& name() const; + void set_name(const std::string& value); + void set_name(std::string&& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + std::string* mutable_name(); + std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // optional .google.protobuf.EnumOptions options = 3; + bool has_options() const; + private: + bool _internal_has_options() const; + public: + void clear_options(); + const PROTOBUF_NAMESPACE_ID::EnumOptions& options() const; + PROTOBUF_NAMESPACE_ID::EnumOptions* release_options(); + PROTOBUF_NAMESPACE_ID::EnumOptions* mutable_options(); + void set_allocated_options(PROTOBUF_NAMESPACE_ID::EnumOptions* options); + private: + const PROTOBUF_NAMESPACE_ID::EnumOptions& _internal_options() const; + PROTOBUF_NAMESPACE_ID::EnumOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::EnumOptions* options); + PROTOBUF_NAMESPACE_ID::EnumOptions* unsafe_arena_release_options(); + + // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto > value_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange > reserved_range_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField reserved_name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + PROTOBUF_NAMESPACE_ID::EnumOptions* options_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT EnumValueDescriptorProto PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValueDescriptorProto) */ { + public: + inline EnumValueDescriptorProto() : EnumValueDescriptorProto(nullptr) {} + virtual ~EnumValueDescriptorProto(); + explicit constexpr EnumValueDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + EnumValueDescriptorProto(const EnumValueDescriptorProto& from); + EnumValueDescriptorProto(EnumValueDescriptorProto&& from) noexcept + : EnumValueDescriptorProto() { + *this = ::std::move(from); + } + + inline EnumValueDescriptorProto& operator=(const EnumValueDescriptorProto& from) { + CopyFrom(from); + return *this; } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline EnumValueDescriptorProto& operator=(EnumValueDescriptorProto&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; } - static const ::google::protobuf::Descriptor* descriptor(); - static const EnumValueDescriptorProto& default_instance(); + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const EnumValueDescriptorProto& default_instance() { + return *internal_default_instance(); + } static inline const EnumValueDescriptorProto* internal_default_instance() { return reinterpret_cast( &_EnumValueDescriptorProto_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 9; + static constexpr int kIndexInFileMessages = + 10; - void Swap(EnumValueDescriptorProto* other); friend void swap(EnumValueDescriptorProto& a, EnumValueDescriptorProto& b) { a.Swap(&b); } + inline void Swap(EnumValueDescriptorProto* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(EnumValueDescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline EnumValueDescriptorProto* New() const PROTOBUF_FINAL { return New(NULL); } + inline EnumValueDescriptorProto* New() const final { + return CreateMaybeMessage(nullptr); + } - EnumValueDescriptorProto* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + EnumValueDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const EnumValueDescriptorProto& from); void MergeFrom(const EnumValueDescriptorProto& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(EnumValueDescriptorProto* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(EnumValueDescriptorProto* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.EnumValueDescriptorProto"; } + protected: + explicit EnumValueDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kNameFieldNumber = 1, + kOptionsFieldNumber = 3, + kNumberFieldNumber = 2, + }; // optional string name = 1; bool has_name() const; + private: + bool _internal_has_name() const; + public: void clear_name(); - static const int kNameFieldNumber = 1; - const ::std::string& name() const; - void set_name(const ::std::string& value); - #if LANG_CXX11 - void set_name(::std::string&& value); - #endif + const std::string& name() const; + void set_name(const std::string& value); + void set_name(std::string&& value); void set_name(const char* value); void set_name(const char* value, size_t size); - ::std::string* mutable_name(); - ::std::string* release_name(); - void set_allocated_name(::std::string* name); + std::string* mutable_name(); + std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: // optional .google.protobuf.EnumValueOptions options = 3; bool has_options() const; + private: + bool _internal_has_options() const; + public: void clear_options(); - static const int kOptionsFieldNumber = 3; - const ::google::protobuf::EnumValueOptions& options() const; - ::google::protobuf::EnumValueOptions* mutable_options(); - ::google::protobuf::EnumValueOptions* release_options(); - void set_allocated_options(::google::protobuf::EnumValueOptions* options); + const PROTOBUF_NAMESPACE_ID::EnumValueOptions& options() const; + PROTOBUF_NAMESPACE_ID::EnumValueOptions* release_options(); + PROTOBUF_NAMESPACE_ID::EnumValueOptions* mutable_options(); + void set_allocated_options(PROTOBUF_NAMESPACE_ID::EnumValueOptions* options); + private: + const PROTOBUF_NAMESPACE_ID::EnumValueOptions& _internal_options() const; + PROTOBUF_NAMESPACE_ID::EnumValueOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::EnumValueOptions* options); + PROTOBUF_NAMESPACE_ID::EnumValueOptions* unsafe_arena_release_options(); // optional int32 number = 2; bool has_number() const; + private: + bool _internal_has_number() const; + public: void clear_number(); - static const int kNumberFieldNumber = 2; - ::google::protobuf::int32 number() const; - void set_number(::google::protobuf::int32 value); + ::PROTOBUF_NAMESPACE_ID::int32 number() const; + void set_number(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_number() const; + void _internal_set_number(::PROTOBUF_NAMESPACE_ID::int32 value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto) private: - void set_has_name(); - void clear_has_name(); - void set_has_number(); - void clear_has_number(); - void set_has_options(); - void clear_has_options(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::internal::ArenaStringPtr name_; - ::google::protobuf::EnumValueOptions* options_; - ::google::protobuf::int32 number_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + PROTOBUF_NAMESPACE_ID::EnumValueOptions* options_; + ::PROTOBUF_NAMESPACE_ID::int32 number_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ServiceDescriptorProto) */ { +class PROTOBUF_EXPORT ServiceDescriptorProto PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ServiceDescriptorProto) */ { public: - ServiceDescriptorProto(); + inline ServiceDescriptorProto() : ServiceDescriptorProto(nullptr) {} virtual ~ServiceDescriptorProto(); + explicit constexpr ServiceDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); ServiceDescriptorProto(const ServiceDescriptorProto& from); - - inline ServiceDescriptorProto& operator=(const ServiceDescriptorProto& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 ServiceDescriptorProto(ServiceDescriptorProto&& from) noexcept : ServiceDescriptorProto() { *this = ::std::move(from); } + inline ServiceDescriptorProto& operator=(const ServiceDescriptorProto& from) { + CopyFrom(from); + return *this; + } inline ServiceDescriptorProto& operator=(ServiceDescriptorProto&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const ServiceDescriptorProto& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const ServiceDescriptorProto& default_instance() { + return *internal_default_instance(); + } static inline const ServiceDescriptorProto* internal_default_instance() { return reinterpret_cast( &_ServiceDescriptorProto_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 10; + static constexpr int kIndexInFileMessages = + 11; - void Swap(ServiceDescriptorProto* other); friend void swap(ServiceDescriptorProto& a, ServiceDescriptorProto& b) { a.Swap(&b); } + inline void Swap(ServiceDescriptorProto* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ServiceDescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline ServiceDescriptorProto* New() const PROTOBUF_FINAL { return New(NULL); } + inline ServiceDescriptorProto* New() const final { + return CreateMaybeMessage(nullptr); + } - ServiceDescriptorProto* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + ServiceDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const ServiceDescriptorProto& from); void MergeFrom(const ServiceDescriptorProto& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(ServiceDescriptorProto* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(ServiceDescriptorProto* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.ServiceDescriptorProto"; } + protected: + explicit ServiceDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kMethodFieldNumber = 2, + kNameFieldNumber = 1, + kOptionsFieldNumber = 3, + }; // repeated .google.protobuf.MethodDescriptorProto method = 2; int method_size() const; + private: + int _internal_method_size() const; + public: void clear_method(); - static const int kMethodFieldNumber = 2; - const ::google::protobuf::MethodDescriptorProto& method(int index) const; - ::google::protobuf::MethodDescriptorProto* mutable_method(int index); - ::google::protobuf::MethodDescriptorProto* add_method(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* + PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* mutable_method(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::MethodDescriptorProto >* mutable_method(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& + private: + const PROTOBUF_NAMESPACE_ID::MethodDescriptorProto& _internal_method(int index) const; + PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* _internal_add_method(); + public: + const PROTOBUF_NAMESPACE_ID::MethodDescriptorProto& method(int index) const; + PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* add_method(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::MethodDescriptorProto >& method() const; // optional string name = 1; bool has_name() const; + private: + bool _internal_has_name() const; + public: void clear_name(); - static const int kNameFieldNumber = 1; - const ::std::string& name() const; - void set_name(const ::std::string& value); - #if LANG_CXX11 - void set_name(::std::string&& value); - #endif + const std::string& name() const; + void set_name(const std::string& value); + void set_name(std::string&& value); void set_name(const char* value); void set_name(const char* value, size_t size); - ::std::string* mutable_name(); - ::std::string* release_name(); - void set_allocated_name(::std::string* name); + std::string* mutable_name(); + std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: // optional .google.protobuf.ServiceOptions options = 3; bool has_options() const; + private: + bool _internal_has_options() const; + public: void clear_options(); - static const int kOptionsFieldNumber = 3; - const ::google::protobuf::ServiceOptions& options() const; - ::google::protobuf::ServiceOptions* mutable_options(); - ::google::protobuf::ServiceOptions* release_options(); - void set_allocated_options(::google::protobuf::ServiceOptions* options); + const PROTOBUF_NAMESPACE_ID::ServiceOptions& options() const; + PROTOBUF_NAMESPACE_ID::ServiceOptions* release_options(); + PROTOBUF_NAMESPACE_ID::ServiceOptions* mutable_options(); + void set_allocated_options(PROTOBUF_NAMESPACE_ID::ServiceOptions* options); + private: + const PROTOBUF_NAMESPACE_ID::ServiceOptions& _internal_options() const; + PROTOBUF_NAMESPACE_ID::ServiceOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::ServiceOptions* options); + PROTOBUF_NAMESPACE_ID::ServiceOptions* unsafe_arena_release_options(); // @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto) private: - void set_has_name(); - void clear_has_name(); - void set_has_options(); - void clear_has_options(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_; - ::google::protobuf::internal::ArenaStringPtr name_; - ::google::protobuf::ServiceOptions* options_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::MethodDescriptorProto > method_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + PROTOBUF_NAMESPACE_ID::ServiceOptions* options_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MethodDescriptorProto) */ { +class PROTOBUF_EXPORT MethodDescriptorProto PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MethodDescriptorProto) */ { public: - MethodDescriptorProto(); + inline MethodDescriptorProto() : MethodDescriptorProto(nullptr) {} virtual ~MethodDescriptorProto(); + explicit constexpr MethodDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); MethodDescriptorProto(const MethodDescriptorProto& from); - - inline MethodDescriptorProto& operator=(const MethodDescriptorProto& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 MethodDescriptorProto(MethodDescriptorProto&& from) noexcept : MethodDescriptorProto() { *this = ::std::move(from); } + inline MethodDescriptorProto& operator=(const MethodDescriptorProto& from) { + CopyFrom(from); + return *this; + } inline MethodDescriptorProto& operator=(MethodDescriptorProto&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const MethodDescriptorProto& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const MethodDescriptorProto& default_instance() { + return *internal_default_instance(); + } static inline const MethodDescriptorProto* internal_default_instance() { return reinterpret_cast( &_MethodDescriptorProto_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 11; + static constexpr int kIndexInFileMessages = + 12; - void Swap(MethodDescriptorProto* other); friend void swap(MethodDescriptorProto& a, MethodDescriptorProto& b) { a.Swap(&b); } + inline void Swap(MethodDescriptorProto* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(MethodDescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline MethodDescriptorProto* New() const PROTOBUF_FINAL { return New(NULL); } + inline MethodDescriptorProto* New() const final { + return CreateMaybeMessage(nullptr); + } - MethodDescriptorProto* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + MethodDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const MethodDescriptorProto& from); void MergeFrom(const MethodDescriptorProto& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(MethodDescriptorProto* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(MethodDescriptorProto* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.MethodDescriptorProto"; } + protected: + explicit MethodDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kNameFieldNumber = 1, + kInputTypeFieldNumber = 2, + kOutputTypeFieldNumber = 3, + kOptionsFieldNumber = 4, + kClientStreamingFieldNumber = 5, + kServerStreamingFieldNumber = 6, + }; // optional string name = 1; bool has_name() const; + private: + bool _internal_has_name() const; + public: void clear_name(); - static const int kNameFieldNumber = 1; - const ::std::string& name() const; - void set_name(const ::std::string& value); - #if LANG_CXX11 - void set_name(::std::string&& value); - #endif + const std::string& name() const; + void set_name(const std::string& value); + void set_name(std::string&& value); void set_name(const char* value); void set_name(const char* value, size_t size); - ::std::string* mutable_name(); - ::std::string* release_name(); - void set_allocated_name(::std::string* name); + std::string* mutable_name(); + std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: // optional string input_type = 2; bool has_input_type() const; + private: + bool _internal_has_input_type() const; + public: void clear_input_type(); - static const int kInputTypeFieldNumber = 2; - const ::std::string& input_type() const; - void set_input_type(const ::std::string& value); - #if LANG_CXX11 - void set_input_type(::std::string&& value); - #endif + const std::string& input_type() const; + void set_input_type(const std::string& value); + void set_input_type(std::string&& value); void set_input_type(const char* value); void set_input_type(const char* value, size_t size); - ::std::string* mutable_input_type(); - ::std::string* release_input_type(); - void set_allocated_input_type(::std::string* input_type); + std::string* mutable_input_type(); + std::string* release_input_type(); + void set_allocated_input_type(std::string* input_type); + private: + const std::string& _internal_input_type() const; + void _internal_set_input_type(const std::string& value); + std::string* _internal_mutable_input_type(); + public: // optional string output_type = 3; bool has_output_type() const; + private: + bool _internal_has_output_type() const; + public: void clear_output_type(); - static const int kOutputTypeFieldNumber = 3; - const ::std::string& output_type() const; - void set_output_type(const ::std::string& value); - #if LANG_CXX11 - void set_output_type(::std::string&& value); - #endif + const std::string& output_type() const; + void set_output_type(const std::string& value); + void set_output_type(std::string&& value); void set_output_type(const char* value); void set_output_type(const char* value, size_t size); - ::std::string* mutable_output_type(); - ::std::string* release_output_type(); - void set_allocated_output_type(::std::string* output_type); + std::string* mutable_output_type(); + std::string* release_output_type(); + void set_allocated_output_type(std::string* output_type); + private: + const std::string& _internal_output_type() const; + void _internal_set_output_type(const std::string& value); + std::string* _internal_mutable_output_type(); + public: // optional .google.protobuf.MethodOptions options = 4; bool has_options() const; + private: + bool _internal_has_options() const; + public: void clear_options(); - static const int kOptionsFieldNumber = 4; - const ::google::protobuf::MethodOptions& options() const; - ::google::protobuf::MethodOptions* mutable_options(); - ::google::protobuf::MethodOptions* release_options(); - void set_allocated_options(::google::protobuf::MethodOptions* options); + const PROTOBUF_NAMESPACE_ID::MethodOptions& options() const; + PROTOBUF_NAMESPACE_ID::MethodOptions* release_options(); + PROTOBUF_NAMESPACE_ID::MethodOptions* mutable_options(); + void set_allocated_options(PROTOBUF_NAMESPACE_ID::MethodOptions* options); + private: + const PROTOBUF_NAMESPACE_ID::MethodOptions& _internal_options() const; + PROTOBUF_NAMESPACE_ID::MethodOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::MethodOptions* options); + PROTOBUF_NAMESPACE_ID::MethodOptions* unsafe_arena_release_options(); // optional bool client_streaming = 5 [default = false]; bool has_client_streaming() const; + private: + bool _internal_has_client_streaming() const; + public: void clear_client_streaming(); - static const int kClientStreamingFieldNumber = 5; bool client_streaming() const; void set_client_streaming(bool value); + private: + bool _internal_client_streaming() const; + void _internal_set_client_streaming(bool value); + public: // optional bool server_streaming = 6 [default = false]; bool has_server_streaming() const; + private: + bool _internal_has_server_streaming() const; + public: void clear_server_streaming(); - static const int kServerStreamingFieldNumber = 6; bool server_streaming() const; void set_server_streaming(bool value); - + private: + bool _internal_server_streaming() const; + void _internal_set_server_streaming(bool value); + public: + // @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto) private: - void set_has_name(); - void clear_has_name(); - void set_has_input_type(); - void clear_has_input_type(); - void set_has_output_type(); - void clear_has_output_type(); - void set_has_options(); - void clear_has_options(); - void set_has_client_streaming(); - void clear_has_client_streaming(); - void set_has_server_streaming(); - void clear_has_server_streaming(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::internal::ArenaStringPtr name_; - ::google::protobuf::internal::ArenaStringPtr input_type_; - ::google::protobuf::internal::ArenaStringPtr output_type_; - ::google::protobuf::MethodOptions* options_; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr input_type_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr output_type_; + PROTOBUF_NAMESPACE_ID::MethodOptions* options_; bool client_streaming_; bool server_streaming_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileOptions) */ { +class PROTOBUF_EXPORT FileOptions PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileOptions) */ { public: - FileOptions(); + inline FileOptions() : FileOptions(nullptr) {} virtual ~FileOptions(); + explicit constexpr FileOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); FileOptions(const FileOptions& from); - - inline FileOptions& operator=(const FileOptions& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 FileOptions(FileOptions&& from) noexcept : FileOptions() { *this = ::std::move(from); } + inline FileOptions& operator=(const FileOptions& from) { + CopyFrom(from); + return *this; + } inline FileOptions& operator=(FileOptions&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const FileOptions& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const FileOptions& default_instance() { + return *internal_default_instance(); + } static inline const FileOptions* internal_default_instance() { return reinterpret_cast( &_FileOptions_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 12; + static constexpr int kIndexInFileMessages = + 13; - void Swap(FileOptions* other); friend void swap(FileOptions& a, FileOptions& b) { a.Swap(&b); } + inline void Swap(FileOptions* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FileOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline FileOptions* New() const PROTOBUF_FINAL { return New(NULL); } + inline FileOptions* New() const final { + return CreateMaybeMessage(nullptr); + } - FileOptions* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + FileOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const FileOptions& from); void MergeFrom(const FileOptions& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(FileOptions* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(FileOptions* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.FileOptions"; } + protected: + explicit FileOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- typedef FileOptions_OptimizeMode OptimizeMode; - static const OptimizeMode SPEED = + static constexpr OptimizeMode SPEED = FileOptions_OptimizeMode_SPEED; - static const OptimizeMode CODE_SIZE = + static constexpr OptimizeMode CODE_SIZE = FileOptions_OptimizeMode_CODE_SIZE; - static const OptimizeMode LITE_RUNTIME = + static constexpr OptimizeMode LITE_RUNTIME = FileOptions_OptimizeMode_LITE_RUNTIME; static inline bool OptimizeMode_IsValid(int value) { return FileOptions_OptimizeMode_IsValid(value); } - static const OptimizeMode OptimizeMode_MIN = + static constexpr OptimizeMode OptimizeMode_MIN = FileOptions_OptimizeMode_OptimizeMode_MIN; - static const OptimizeMode OptimizeMode_MAX = + static constexpr OptimizeMode OptimizeMode_MAX = FileOptions_OptimizeMode_OptimizeMode_MAX; - static const int OptimizeMode_ARRAYSIZE = + static constexpr int OptimizeMode_ARRAYSIZE = FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE; - static inline const ::google::protobuf::EnumDescriptor* + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* OptimizeMode_descriptor() { return FileOptions_OptimizeMode_descriptor(); } - static inline const ::std::string& OptimizeMode_Name(OptimizeMode value) { - return FileOptions_OptimizeMode_Name(value); + template + static inline const std::string& OptimizeMode_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function OptimizeMode_Name."); + return FileOptions_OptimizeMode_Name(enum_t_value); } - static inline bool OptimizeMode_Parse(const ::std::string& name, + static inline bool OptimizeMode_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, OptimizeMode* value) { return FileOptions_OptimizeMode_Parse(name, value); } // accessors ------------------------------------------------------- + enum : int { + kUninterpretedOptionFieldNumber = 999, + kJavaPackageFieldNumber = 1, + kJavaOuterClassnameFieldNumber = 8, + kGoPackageFieldNumber = 11, + kObjcClassPrefixFieldNumber = 36, + kCsharpNamespaceFieldNumber = 37, + kSwiftPrefixFieldNumber = 39, + kPhpClassPrefixFieldNumber = 40, + kPhpNamespaceFieldNumber = 41, + kPhpMetadataNamespaceFieldNumber = 44, + kRubyPackageFieldNumber = 45, + kJavaMultipleFilesFieldNumber = 10, + kJavaGenerateEqualsAndHashFieldNumber = 20, + kJavaStringCheckUtf8FieldNumber = 27, + kCcGenericServicesFieldNumber = 16, + kJavaGenericServicesFieldNumber = 17, + kPyGenericServicesFieldNumber = 18, + kPhpGenericServicesFieldNumber = 42, + kDeprecatedFieldNumber = 23, + kOptimizeForFieldNumber = 9, + kCcEnableArenasFieldNumber = 31, + }; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: void clear_uninterpreted_option(); - static const int kUninterpretedOptionFieldNumber = 999; - const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* mutable_uninterpreted_option(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + private: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& uninterpreted_option() const; // optional string java_package = 1; bool has_java_package() const; + private: + bool _internal_has_java_package() const; + public: void clear_java_package(); - static const int kJavaPackageFieldNumber = 1; - const ::std::string& java_package() const; - void set_java_package(const ::std::string& value); - #if LANG_CXX11 - void set_java_package(::std::string&& value); - #endif + const std::string& java_package() const; + void set_java_package(const std::string& value); + void set_java_package(std::string&& value); void set_java_package(const char* value); void set_java_package(const char* value, size_t size); - ::std::string* mutable_java_package(); - ::std::string* release_java_package(); - void set_allocated_java_package(::std::string* java_package); + std::string* mutable_java_package(); + std::string* release_java_package(); + void set_allocated_java_package(std::string* java_package); + private: + const std::string& _internal_java_package() const; + void _internal_set_java_package(const std::string& value); + std::string* _internal_mutable_java_package(); + public: // optional string java_outer_classname = 8; bool has_java_outer_classname() const; + private: + bool _internal_has_java_outer_classname() const; + public: void clear_java_outer_classname(); - static const int kJavaOuterClassnameFieldNumber = 8; - const ::std::string& java_outer_classname() const; - void set_java_outer_classname(const ::std::string& value); - #if LANG_CXX11 - void set_java_outer_classname(::std::string&& value); - #endif + const std::string& java_outer_classname() const; + void set_java_outer_classname(const std::string& value); + void set_java_outer_classname(std::string&& value); void set_java_outer_classname(const char* value); void set_java_outer_classname(const char* value, size_t size); - ::std::string* mutable_java_outer_classname(); - ::std::string* release_java_outer_classname(); - void set_allocated_java_outer_classname(::std::string* java_outer_classname); + std::string* mutable_java_outer_classname(); + std::string* release_java_outer_classname(); + void set_allocated_java_outer_classname(std::string* java_outer_classname); + private: + const std::string& _internal_java_outer_classname() const; + void _internal_set_java_outer_classname(const std::string& value); + std::string* _internal_mutable_java_outer_classname(); + public: // optional string go_package = 11; bool has_go_package() const; + private: + bool _internal_has_go_package() const; + public: void clear_go_package(); - static const int kGoPackageFieldNumber = 11; - const ::std::string& go_package() const; - void set_go_package(const ::std::string& value); - #if LANG_CXX11 - void set_go_package(::std::string&& value); - #endif + const std::string& go_package() const; + void set_go_package(const std::string& value); + void set_go_package(std::string&& value); void set_go_package(const char* value); void set_go_package(const char* value, size_t size); - ::std::string* mutable_go_package(); - ::std::string* release_go_package(); - void set_allocated_go_package(::std::string* go_package); + std::string* mutable_go_package(); + std::string* release_go_package(); + void set_allocated_go_package(std::string* go_package); + private: + const std::string& _internal_go_package() const; + void _internal_set_go_package(const std::string& value); + std::string* _internal_mutable_go_package(); + public: // optional string objc_class_prefix = 36; bool has_objc_class_prefix() const; + private: + bool _internal_has_objc_class_prefix() const; + public: void clear_objc_class_prefix(); - static const int kObjcClassPrefixFieldNumber = 36; - const ::std::string& objc_class_prefix() const; - void set_objc_class_prefix(const ::std::string& value); - #if LANG_CXX11 - void set_objc_class_prefix(::std::string&& value); - #endif + const std::string& objc_class_prefix() const; + void set_objc_class_prefix(const std::string& value); + void set_objc_class_prefix(std::string&& value); void set_objc_class_prefix(const char* value); void set_objc_class_prefix(const char* value, size_t size); - ::std::string* mutable_objc_class_prefix(); - ::std::string* release_objc_class_prefix(); - void set_allocated_objc_class_prefix(::std::string* objc_class_prefix); + std::string* mutable_objc_class_prefix(); + std::string* release_objc_class_prefix(); + void set_allocated_objc_class_prefix(std::string* objc_class_prefix); + private: + const std::string& _internal_objc_class_prefix() const; + void _internal_set_objc_class_prefix(const std::string& value); + std::string* _internal_mutable_objc_class_prefix(); + public: // optional string csharp_namespace = 37; bool has_csharp_namespace() const; + private: + bool _internal_has_csharp_namespace() const; + public: void clear_csharp_namespace(); - static const int kCsharpNamespaceFieldNumber = 37; - const ::std::string& csharp_namespace() const; - void set_csharp_namespace(const ::std::string& value); - #if LANG_CXX11 - void set_csharp_namespace(::std::string&& value); - #endif + const std::string& csharp_namespace() const; + void set_csharp_namespace(const std::string& value); + void set_csharp_namespace(std::string&& value); void set_csharp_namespace(const char* value); void set_csharp_namespace(const char* value, size_t size); - ::std::string* mutable_csharp_namespace(); - ::std::string* release_csharp_namespace(); - void set_allocated_csharp_namespace(::std::string* csharp_namespace); + std::string* mutable_csharp_namespace(); + std::string* release_csharp_namespace(); + void set_allocated_csharp_namespace(std::string* csharp_namespace); + private: + const std::string& _internal_csharp_namespace() const; + void _internal_set_csharp_namespace(const std::string& value); + std::string* _internal_mutable_csharp_namespace(); + public: // optional string swift_prefix = 39; bool has_swift_prefix() const; + private: + bool _internal_has_swift_prefix() const; + public: void clear_swift_prefix(); - static const int kSwiftPrefixFieldNumber = 39; - const ::std::string& swift_prefix() const; - void set_swift_prefix(const ::std::string& value); - #if LANG_CXX11 - void set_swift_prefix(::std::string&& value); - #endif + const std::string& swift_prefix() const; + void set_swift_prefix(const std::string& value); + void set_swift_prefix(std::string&& value); void set_swift_prefix(const char* value); void set_swift_prefix(const char* value, size_t size); - ::std::string* mutable_swift_prefix(); - ::std::string* release_swift_prefix(); - void set_allocated_swift_prefix(::std::string* swift_prefix); + std::string* mutable_swift_prefix(); + std::string* release_swift_prefix(); + void set_allocated_swift_prefix(std::string* swift_prefix); + private: + const std::string& _internal_swift_prefix() const; + void _internal_set_swift_prefix(const std::string& value); + std::string* _internal_mutable_swift_prefix(); + public: // optional string php_class_prefix = 40; bool has_php_class_prefix() const; + private: + bool _internal_has_php_class_prefix() const; + public: void clear_php_class_prefix(); - static const int kPhpClassPrefixFieldNumber = 40; - const ::std::string& php_class_prefix() const; - void set_php_class_prefix(const ::std::string& value); - #if LANG_CXX11 - void set_php_class_prefix(::std::string&& value); - #endif + const std::string& php_class_prefix() const; + void set_php_class_prefix(const std::string& value); + void set_php_class_prefix(std::string&& value); void set_php_class_prefix(const char* value); void set_php_class_prefix(const char* value, size_t size); - ::std::string* mutable_php_class_prefix(); - ::std::string* release_php_class_prefix(); - void set_allocated_php_class_prefix(::std::string* php_class_prefix); + std::string* mutable_php_class_prefix(); + std::string* release_php_class_prefix(); + void set_allocated_php_class_prefix(std::string* php_class_prefix); + private: + const std::string& _internal_php_class_prefix() const; + void _internal_set_php_class_prefix(const std::string& value); + std::string* _internal_mutable_php_class_prefix(); + public: // optional string php_namespace = 41; bool has_php_namespace() const; + private: + bool _internal_has_php_namespace() const; + public: void clear_php_namespace(); - static const int kPhpNamespaceFieldNumber = 41; - const ::std::string& php_namespace() const; - void set_php_namespace(const ::std::string& value); - #if LANG_CXX11 - void set_php_namespace(::std::string&& value); - #endif + const std::string& php_namespace() const; + void set_php_namespace(const std::string& value); + void set_php_namespace(std::string&& value); void set_php_namespace(const char* value); void set_php_namespace(const char* value, size_t size); - ::std::string* mutable_php_namespace(); - ::std::string* release_php_namespace(); - void set_allocated_php_namespace(::std::string* php_namespace); + std::string* mutable_php_namespace(); + std::string* release_php_namespace(); + void set_allocated_php_namespace(std::string* php_namespace); + private: + const std::string& _internal_php_namespace() const; + void _internal_set_php_namespace(const std::string& value); + std::string* _internal_mutable_php_namespace(); + public: + + // optional string php_metadata_namespace = 44; + bool has_php_metadata_namespace() const; + private: + bool _internal_has_php_metadata_namespace() const; + public: + void clear_php_metadata_namespace(); + const std::string& php_metadata_namespace() const; + void set_php_metadata_namespace(const std::string& value); + void set_php_metadata_namespace(std::string&& value); + void set_php_metadata_namespace(const char* value); + void set_php_metadata_namespace(const char* value, size_t size); + std::string* mutable_php_metadata_namespace(); + std::string* release_php_metadata_namespace(); + void set_allocated_php_metadata_namespace(std::string* php_metadata_namespace); + private: + const std::string& _internal_php_metadata_namespace() const; + void _internal_set_php_metadata_namespace(const std::string& value); + std::string* _internal_mutable_php_metadata_namespace(); + public: + + // optional string ruby_package = 45; + bool has_ruby_package() const; + private: + bool _internal_has_ruby_package() const; + public: + void clear_ruby_package(); + const std::string& ruby_package() const; + void set_ruby_package(const std::string& value); + void set_ruby_package(std::string&& value); + void set_ruby_package(const char* value); + void set_ruby_package(const char* value, size_t size); + std::string* mutable_ruby_package(); + std::string* release_ruby_package(); + void set_allocated_ruby_package(std::string* ruby_package); + private: + const std::string& _internal_ruby_package() const; + void _internal_set_ruby_package(const std::string& value); + std::string* _internal_mutable_ruby_package(); + public: // optional bool java_multiple_files = 10 [default = false]; bool has_java_multiple_files() const; + private: + bool _internal_has_java_multiple_files() const; + public: void clear_java_multiple_files(); - static const int kJavaMultipleFilesFieldNumber = 10; bool java_multiple_files() const; void set_java_multiple_files(bool value); + private: + bool _internal_java_multiple_files() const; + void _internal_set_java_multiple_files(bool value); + public: // optional bool java_generate_equals_and_hash = 20 [deprecated = true]; - GOOGLE_PROTOBUF_DEPRECATED_ATTR bool has_java_generate_equals_and_hash() const; - GOOGLE_PROTOBUF_DEPRECATED_ATTR void clear_java_generate_equals_and_hash(); - GOOGLE_PROTOBUF_DEPRECATED_ATTR static const int kJavaGenerateEqualsAndHashFieldNumber = 20; - GOOGLE_PROTOBUF_DEPRECATED_ATTR bool java_generate_equals_and_hash() const; - GOOGLE_PROTOBUF_DEPRECATED_ATTR void set_java_generate_equals_and_hash(bool value); + PROTOBUF_DEPRECATED bool has_java_generate_equals_and_hash() const; + private: + bool _internal_has_java_generate_equals_and_hash() const; + public: + PROTOBUF_DEPRECATED void clear_java_generate_equals_and_hash(); + PROTOBUF_DEPRECATED bool java_generate_equals_and_hash() const; + PROTOBUF_DEPRECATED void set_java_generate_equals_and_hash(bool value); + private: + bool _internal_java_generate_equals_and_hash() const; + void _internal_set_java_generate_equals_and_hash(bool value); + public: // optional bool java_string_check_utf8 = 27 [default = false]; bool has_java_string_check_utf8() const; + private: + bool _internal_has_java_string_check_utf8() const; + public: void clear_java_string_check_utf8(); - static const int kJavaStringCheckUtf8FieldNumber = 27; bool java_string_check_utf8() const; void set_java_string_check_utf8(bool value); + private: + bool _internal_java_string_check_utf8() const; + void _internal_set_java_string_check_utf8(bool value); + public: // optional bool cc_generic_services = 16 [default = false]; bool has_cc_generic_services() const; + private: + bool _internal_has_cc_generic_services() const; + public: void clear_cc_generic_services(); - static const int kCcGenericServicesFieldNumber = 16; bool cc_generic_services() const; void set_cc_generic_services(bool value); + private: + bool _internal_cc_generic_services() const; + void _internal_set_cc_generic_services(bool value); + public: // optional bool java_generic_services = 17 [default = false]; bool has_java_generic_services() const; + private: + bool _internal_has_java_generic_services() const; + public: void clear_java_generic_services(); - static const int kJavaGenericServicesFieldNumber = 17; bool java_generic_services() const; void set_java_generic_services(bool value); + private: + bool _internal_java_generic_services() const; + void _internal_set_java_generic_services(bool value); + public: // optional bool py_generic_services = 18 [default = false]; bool has_py_generic_services() const; + private: + bool _internal_has_py_generic_services() const; + public: void clear_py_generic_services(); - static const int kPyGenericServicesFieldNumber = 18; bool py_generic_services() const; void set_py_generic_services(bool value); + private: + bool _internal_py_generic_services() const; + void _internal_set_py_generic_services(bool value); + public: - // optional bool php_generic_services = 19 [default = false]; + // optional bool php_generic_services = 42 [default = false]; bool has_php_generic_services() const; + private: + bool _internal_has_php_generic_services() const; + public: void clear_php_generic_services(); - static const int kPhpGenericServicesFieldNumber = 19; bool php_generic_services() const; void set_php_generic_services(bool value); + private: + bool _internal_php_generic_services() const; + void _internal_set_php_generic_services(bool value); + public: // optional bool deprecated = 23 [default = false]; bool has_deprecated() const; + private: + bool _internal_has_deprecated() const; + public: void clear_deprecated(); - static const int kDeprecatedFieldNumber = 23; bool deprecated() const; void set_deprecated(bool value); + private: + bool _internal_deprecated() const; + void _internal_set_deprecated(bool value); + public: + + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + bool has_optimize_for() const; + private: + bool _internal_has_optimize_for() const; + public: + void clear_optimize_for(); + PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode optimize_for() const; + void set_optimize_for(PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode value); + private: + PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode _internal_optimize_for() const; + void _internal_set_optimize_for(PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode value); + public: - // optional bool cc_enable_arenas = 31 [default = false]; + // optional bool cc_enable_arenas = 31 [default = true]; bool has_cc_enable_arenas() const; + private: + bool _internal_has_cc_enable_arenas() const; + public: void clear_cc_enable_arenas(); - static const int kCcEnableArenasFieldNumber = 31; bool cc_enable_arenas() const; void set_cc_enable_arenas(bool value); - - // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; - bool has_optimize_for() const; - void clear_optimize_for(); - static const int kOptimizeForFieldNumber = 9; - ::google::protobuf::FileOptions_OptimizeMode optimize_for() const; - void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value); + private: + bool _internal_cc_enable_arenas() const; + void _internal_set_cc_enable_arenas(bool value); + public: GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions) // @@protoc_insertion_point(class_scope:google.protobuf.FileOptions) private: - void set_has_java_package(); - void clear_has_java_package(); - void set_has_java_outer_classname(); - void clear_has_java_outer_classname(); - void set_has_java_multiple_files(); - void clear_has_java_multiple_files(); - void set_has_java_generate_equals_and_hash(); - void clear_has_java_generate_equals_and_hash(); - void set_has_java_string_check_utf8(); - void clear_has_java_string_check_utf8(); - void set_has_optimize_for(); - void clear_has_optimize_for(); - void set_has_go_package(); - void clear_has_go_package(); - void set_has_cc_generic_services(); - void clear_has_cc_generic_services(); - void set_has_java_generic_services(); - void clear_has_java_generic_services(); - void set_has_py_generic_services(); - void clear_has_py_generic_services(); - void set_has_php_generic_services(); - void clear_has_php_generic_services(); - void set_has_deprecated(); - void clear_has_deprecated(); - void set_has_cc_enable_arenas(); - void clear_has_cc_enable_arenas(); - void set_has_objc_class_prefix(); - void clear_has_objc_class_prefix(); - void set_has_csharp_namespace(); - void clear_has_csharp_namespace(); - void set_has_swift_prefix(); - void clear_has_swift_prefix(); - void set_has_php_class_prefix(); - void clear_has_php_class_prefix(); - void set_has_php_namespace(); - void clear_has_php_namespace(); - - ::google::protobuf::internal::ExtensionSet _extensions_; - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; - ::google::protobuf::internal::ArenaStringPtr java_package_; - ::google::protobuf::internal::ArenaStringPtr java_outer_classname_; - ::google::protobuf::internal::ArenaStringPtr go_package_; - ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_; - ::google::protobuf::internal::ArenaStringPtr csharp_namespace_; - ::google::protobuf::internal::ArenaStringPtr swift_prefix_; - ::google::protobuf::internal::ArenaStringPtr php_class_prefix_; - ::google::protobuf::internal::ArenaStringPtr php_namespace_; + class _Internal; + + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr java_package_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr java_outer_classname_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr go_package_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr objc_class_prefix_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr csharp_namespace_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr swift_prefix_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr php_class_prefix_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr php_namespace_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr php_metadata_namespace_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr ruby_package_; bool java_multiple_files_; bool java_generate_equals_and_hash_; bool java_string_check_utf8_; @@ -2702,1266 +3933,1734 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message /* @@p bool py_generic_services_; bool php_generic_services_; bool deprecated_; - bool cc_enable_arenas_; int optimize_for_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + bool cc_enable_arenas_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MessageOptions) */ { +class PROTOBUF_EXPORT MessageOptions PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MessageOptions) */ { public: - MessageOptions(); + inline MessageOptions() : MessageOptions(nullptr) {} virtual ~MessageOptions(); + explicit constexpr MessageOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); MessageOptions(const MessageOptions& from); - - inline MessageOptions& operator=(const MessageOptions& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 MessageOptions(MessageOptions&& from) noexcept : MessageOptions() { *this = ::std::move(from); } + inline MessageOptions& operator=(const MessageOptions& from) { + CopyFrom(from); + return *this; + } inline MessageOptions& operator=(MessageOptions&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const MessageOptions& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const MessageOptions& default_instance() { + return *internal_default_instance(); + } static inline const MessageOptions* internal_default_instance() { return reinterpret_cast( &_MessageOptions_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 13; + static constexpr int kIndexInFileMessages = + 14; - void Swap(MessageOptions* other); friend void swap(MessageOptions& a, MessageOptions& b) { a.Swap(&b); } + inline void Swap(MessageOptions* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(MessageOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline MessageOptions* New() const PROTOBUF_FINAL { return New(NULL); } + inline MessageOptions* New() const final { + return CreateMaybeMessage(nullptr); + } - MessageOptions* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + MessageOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const MessageOptions& from); void MergeFrom(const MessageOptions& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(MessageOptions* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(MessageOptions* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.MessageOptions"; } + protected: + explicit MessageOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kUninterpretedOptionFieldNumber = 999, + kMessageSetWireFormatFieldNumber = 1, + kNoStandardDescriptorAccessorFieldNumber = 2, + kDeprecatedFieldNumber = 3, + kMapEntryFieldNumber = 7, + }; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: void clear_uninterpreted_option(); - static const int kUninterpretedOptionFieldNumber = 999; - const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* mutable_uninterpreted_option(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + private: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& uninterpreted_option() const; // optional bool message_set_wire_format = 1 [default = false]; bool has_message_set_wire_format() const; + private: + bool _internal_has_message_set_wire_format() const; + public: void clear_message_set_wire_format(); - static const int kMessageSetWireFormatFieldNumber = 1; bool message_set_wire_format() const; void set_message_set_wire_format(bool value); + private: + bool _internal_message_set_wire_format() const; + void _internal_set_message_set_wire_format(bool value); + public: // optional bool no_standard_descriptor_accessor = 2 [default = false]; bool has_no_standard_descriptor_accessor() const; + private: + bool _internal_has_no_standard_descriptor_accessor() const; + public: void clear_no_standard_descriptor_accessor(); - static const int kNoStandardDescriptorAccessorFieldNumber = 2; bool no_standard_descriptor_accessor() const; void set_no_standard_descriptor_accessor(bool value); + private: + bool _internal_no_standard_descriptor_accessor() const; + void _internal_set_no_standard_descriptor_accessor(bool value); + public: // optional bool deprecated = 3 [default = false]; bool has_deprecated() const; + private: + bool _internal_has_deprecated() const; + public: void clear_deprecated(); - static const int kDeprecatedFieldNumber = 3; bool deprecated() const; void set_deprecated(bool value); + private: + bool _internal_deprecated() const; + void _internal_set_deprecated(bool value); + public: // optional bool map_entry = 7; bool has_map_entry() const; + private: + bool _internal_has_map_entry() const; + public: void clear_map_entry(); - static const int kMapEntryFieldNumber = 7; bool map_entry() const; void set_map_entry(bool value); + private: + bool _internal_map_entry() const; + void _internal_set_map_entry(bool value); + public: GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions) // @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions) private: - void set_has_message_set_wire_format(); - void clear_has_message_set_wire_format(); - void set_has_no_standard_descriptor_accessor(); - void clear_has_no_standard_descriptor_accessor(); - void set_has_deprecated(); - void clear_has_deprecated(); - void set_has_map_entry(); - void clear_has_map_entry(); - - ::google::protobuf::internal::ExtensionSet _extensions_; - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + class _Internal; + + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; bool message_set_wire_format_; bool no_standard_descriptor_accessor_; bool deprecated_; bool map_entry_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldOptions) */ { +class PROTOBUF_EXPORT FieldOptions PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldOptions) */ { public: - FieldOptions(); + inline FieldOptions() : FieldOptions(nullptr) {} virtual ~FieldOptions(); + explicit constexpr FieldOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); FieldOptions(const FieldOptions& from); - - inline FieldOptions& operator=(const FieldOptions& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 FieldOptions(FieldOptions&& from) noexcept : FieldOptions() { *this = ::std::move(from); } + inline FieldOptions& operator=(const FieldOptions& from) { + CopyFrom(from); + return *this; + } inline FieldOptions& operator=(FieldOptions&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const FieldOptions& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const FieldOptions& default_instance() { + return *internal_default_instance(); + } static inline const FieldOptions* internal_default_instance() { return reinterpret_cast( &_FieldOptions_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 14; + static constexpr int kIndexInFileMessages = + 15; - void Swap(FieldOptions* other); friend void swap(FieldOptions& a, FieldOptions& b) { a.Swap(&b); } + inline void Swap(FieldOptions* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FieldOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline FieldOptions* New() const PROTOBUF_FINAL { return New(NULL); } + inline FieldOptions* New() const final { + return CreateMaybeMessage(nullptr); + } - FieldOptions* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + FieldOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const FieldOptions& from); void MergeFrom(const FieldOptions& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(FieldOptions* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(FieldOptions* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.FieldOptions"; } + protected: + explicit FieldOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- typedef FieldOptions_CType CType; - static const CType STRING = + static constexpr CType STRING = FieldOptions_CType_STRING; - static const CType CORD = + static constexpr CType CORD = FieldOptions_CType_CORD; - static const CType STRING_PIECE = + static constexpr CType STRING_PIECE = FieldOptions_CType_STRING_PIECE; static inline bool CType_IsValid(int value) { return FieldOptions_CType_IsValid(value); } - static const CType CType_MIN = + static constexpr CType CType_MIN = FieldOptions_CType_CType_MIN; - static const CType CType_MAX = + static constexpr CType CType_MAX = FieldOptions_CType_CType_MAX; - static const int CType_ARRAYSIZE = + static constexpr int CType_ARRAYSIZE = FieldOptions_CType_CType_ARRAYSIZE; - static inline const ::google::protobuf::EnumDescriptor* + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* CType_descriptor() { return FieldOptions_CType_descriptor(); } - static inline const ::std::string& CType_Name(CType value) { - return FieldOptions_CType_Name(value); + template + static inline const std::string& CType_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function CType_Name."); + return FieldOptions_CType_Name(enum_t_value); } - static inline bool CType_Parse(const ::std::string& name, + static inline bool CType_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, CType* value) { return FieldOptions_CType_Parse(name, value); } typedef FieldOptions_JSType JSType; - static const JSType JS_NORMAL = + static constexpr JSType JS_NORMAL = FieldOptions_JSType_JS_NORMAL; - static const JSType JS_STRING = + static constexpr JSType JS_STRING = FieldOptions_JSType_JS_STRING; - static const JSType JS_NUMBER = + static constexpr JSType JS_NUMBER = FieldOptions_JSType_JS_NUMBER; static inline bool JSType_IsValid(int value) { return FieldOptions_JSType_IsValid(value); } - static const JSType JSType_MIN = + static constexpr JSType JSType_MIN = FieldOptions_JSType_JSType_MIN; - static const JSType JSType_MAX = + static constexpr JSType JSType_MAX = FieldOptions_JSType_JSType_MAX; - static const int JSType_ARRAYSIZE = + static constexpr int JSType_ARRAYSIZE = FieldOptions_JSType_JSType_ARRAYSIZE; - static inline const ::google::protobuf::EnumDescriptor* + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* JSType_descriptor() { return FieldOptions_JSType_descriptor(); } - static inline const ::std::string& JSType_Name(JSType value) { - return FieldOptions_JSType_Name(value); + template + static inline const std::string& JSType_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function JSType_Name."); + return FieldOptions_JSType_Name(enum_t_value); } - static inline bool JSType_Parse(const ::std::string& name, + static inline bool JSType_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, JSType* value) { return FieldOptions_JSType_Parse(name, value); } // accessors ------------------------------------------------------- + enum : int { + kUninterpretedOptionFieldNumber = 999, + kCtypeFieldNumber = 1, + kPackedFieldNumber = 2, + kLazyFieldNumber = 5, + kDeprecatedFieldNumber = 3, + kWeakFieldNumber = 10, + kJstypeFieldNumber = 6, + }; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: void clear_uninterpreted_option(); - static const int kUninterpretedOptionFieldNumber = 999; - const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* mutable_uninterpreted_option(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + private: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& uninterpreted_option() const; // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; bool has_ctype() const; + private: + bool _internal_has_ctype() const; + public: void clear_ctype(); - static const int kCtypeFieldNumber = 1; - ::google::protobuf::FieldOptions_CType ctype() const; - void set_ctype(::google::protobuf::FieldOptions_CType value); + PROTOBUF_NAMESPACE_ID::FieldOptions_CType ctype() const; + void set_ctype(PROTOBUF_NAMESPACE_ID::FieldOptions_CType value); + private: + PROTOBUF_NAMESPACE_ID::FieldOptions_CType _internal_ctype() const; + void _internal_set_ctype(PROTOBUF_NAMESPACE_ID::FieldOptions_CType value); + public: // optional bool packed = 2; bool has_packed() const; + private: + bool _internal_has_packed() const; + public: void clear_packed(); - static const int kPackedFieldNumber = 2; bool packed() const; void set_packed(bool value); + private: + bool _internal_packed() const; + void _internal_set_packed(bool value); + public: // optional bool lazy = 5 [default = false]; bool has_lazy() const; + private: + bool _internal_has_lazy() const; + public: void clear_lazy(); - static const int kLazyFieldNumber = 5; bool lazy() const; void set_lazy(bool value); + private: + bool _internal_lazy() const; + void _internal_set_lazy(bool value); + public: // optional bool deprecated = 3 [default = false]; bool has_deprecated() const; + private: + bool _internal_has_deprecated() const; + public: void clear_deprecated(); - static const int kDeprecatedFieldNumber = 3; bool deprecated() const; void set_deprecated(bool value); + private: + bool _internal_deprecated() const; + void _internal_set_deprecated(bool value); + public: // optional bool weak = 10 [default = false]; bool has_weak() const; + private: + bool _internal_has_weak() const; + public: void clear_weak(); - static const int kWeakFieldNumber = 10; bool weak() const; void set_weak(bool value); + private: + bool _internal_weak() const; + void _internal_set_weak(bool value); + public: // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; bool has_jstype() const; + private: + bool _internal_has_jstype() const; + public: void clear_jstype(); - static const int kJstypeFieldNumber = 6; - ::google::protobuf::FieldOptions_JSType jstype() const; - void set_jstype(::google::protobuf::FieldOptions_JSType value); + PROTOBUF_NAMESPACE_ID::FieldOptions_JSType jstype() const; + void set_jstype(PROTOBUF_NAMESPACE_ID::FieldOptions_JSType value); + private: + PROTOBUF_NAMESPACE_ID::FieldOptions_JSType _internal_jstype() const; + void _internal_set_jstype(PROTOBUF_NAMESPACE_ID::FieldOptions_JSType value); + public: GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions) // @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions) private: - void set_has_ctype(); - void clear_has_ctype(); - void set_has_packed(); - void clear_has_packed(); - void set_has_jstype(); - void clear_has_jstype(); - void set_has_lazy(); - void clear_has_lazy(); - void set_has_deprecated(); - void clear_has_deprecated(); - void set_has_weak(); - void clear_has_weak(); - - ::google::protobuf::internal::ExtensionSet _extensions_; - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + class _Internal; + + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; int ctype_; bool packed_; bool lazy_; bool deprecated_; bool weak_; int jstype_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT OneofOptions : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.OneofOptions) */ { +class PROTOBUF_EXPORT OneofOptions PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.OneofOptions) */ { public: - OneofOptions(); + inline OneofOptions() : OneofOptions(nullptr) {} virtual ~OneofOptions(); + explicit constexpr OneofOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); OneofOptions(const OneofOptions& from); - - inline OneofOptions& operator=(const OneofOptions& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 OneofOptions(OneofOptions&& from) noexcept : OneofOptions() { *this = ::std::move(from); } - inline OneofOptions& operator=(OneofOptions&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + inline OneofOptions& operator=(const OneofOptions& from) { + CopyFrom(from); + return *this; + } + inline OneofOptions& operator=(OneofOptions&& from) noexcept { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const OneofOptions& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const OneofOptions& default_instance() { + return *internal_default_instance(); + } static inline const OneofOptions* internal_default_instance() { return reinterpret_cast( &_OneofOptions_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 15; + static constexpr int kIndexInFileMessages = + 16; - void Swap(OneofOptions* other); friend void swap(OneofOptions& a, OneofOptions& b) { a.Swap(&b); } + inline void Swap(OneofOptions* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(OneofOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline OneofOptions* New() const PROTOBUF_FINAL { return New(NULL); } + inline OneofOptions* New() const final { + return CreateMaybeMessage(nullptr); + } - OneofOptions* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + OneofOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const OneofOptions& from); void MergeFrom(const OneofOptions& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(OneofOptions* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(OneofOptions* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.OneofOptions"; } + protected: + explicit OneofOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kUninterpretedOptionFieldNumber = 999, + }; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: void clear_uninterpreted_option(); - static const int kUninterpretedOptionFieldNumber = 999; - const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* mutable_uninterpreted_option(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + private: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& uninterpreted_option() const; GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(OneofOptions) // @@protoc_insertion_point(class_scope:google.protobuf.OneofOptions) private: + class _Internal; - ::google::protobuf::internal::ExtensionSet _extensions_; + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumOptions) */ { +class PROTOBUF_EXPORT EnumOptions PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumOptions) */ { public: - EnumOptions(); + inline EnumOptions() : EnumOptions(nullptr) {} virtual ~EnumOptions(); + explicit constexpr EnumOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); EnumOptions(const EnumOptions& from); - - inline EnumOptions& operator=(const EnumOptions& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 EnumOptions(EnumOptions&& from) noexcept : EnumOptions() { *this = ::std::move(from); } + inline EnumOptions& operator=(const EnumOptions& from) { + CopyFrom(from); + return *this; + } inline EnumOptions& operator=(EnumOptions&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const EnumOptions& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const EnumOptions& default_instance() { + return *internal_default_instance(); + } static inline const EnumOptions* internal_default_instance() { return reinterpret_cast( &_EnumOptions_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 16; + static constexpr int kIndexInFileMessages = + 17; - void Swap(EnumOptions* other); friend void swap(EnumOptions& a, EnumOptions& b) { a.Swap(&b); } + inline void Swap(EnumOptions* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(EnumOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline EnumOptions* New() const PROTOBUF_FINAL { return New(NULL); } + inline EnumOptions* New() const final { + return CreateMaybeMessage(nullptr); + } - EnumOptions* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + EnumOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const EnumOptions& from); void MergeFrom(const EnumOptions& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(EnumOptions* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(EnumOptions* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.EnumOptions"; } + protected: + explicit EnumOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kUninterpretedOptionFieldNumber = 999, + kAllowAliasFieldNumber = 2, + kDeprecatedFieldNumber = 3, + }; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: void clear_uninterpreted_option(); - static const int kUninterpretedOptionFieldNumber = 999; - const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* mutable_uninterpreted_option(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + private: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& uninterpreted_option() const; // optional bool allow_alias = 2; bool has_allow_alias() const; + private: + bool _internal_has_allow_alias() const; + public: void clear_allow_alias(); - static const int kAllowAliasFieldNumber = 2; bool allow_alias() const; void set_allow_alias(bool value); + private: + bool _internal_allow_alias() const; + void _internal_set_allow_alias(bool value); + public: // optional bool deprecated = 3 [default = false]; bool has_deprecated() const; + private: + bool _internal_has_deprecated() const; + public: void clear_deprecated(); - static const int kDeprecatedFieldNumber = 3; bool deprecated() const; void set_deprecated(bool value); + private: + bool _internal_deprecated() const; + void _internal_set_deprecated(bool value); + public: GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions) // @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions) private: - void set_has_allow_alias(); - void clear_has_allow_alias(); - void set_has_deprecated(); - void clear_has_deprecated(); + class _Internal; - ::google::protobuf::internal::ExtensionSet _extensions_; + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; bool allow_alias_; bool deprecated_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValueOptions) */ { +class PROTOBUF_EXPORT EnumValueOptions PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValueOptions) */ { public: - EnumValueOptions(); + inline EnumValueOptions() : EnumValueOptions(nullptr) {} virtual ~EnumValueOptions(); + explicit constexpr EnumValueOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); EnumValueOptions(const EnumValueOptions& from); - - inline EnumValueOptions& operator=(const EnumValueOptions& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 EnumValueOptions(EnumValueOptions&& from) noexcept : EnumValueOptions() { *this = ::std::move(from); } + inline EnumValueOptions& operator=(const EnumValueOptions& from) { + CopyFrom(from); + return *this; + } inline EnumValueOptions& operator=(EnumValueOptions&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const EnumValueOptions& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const EnumValueOptions& default_instance() { + return *internal_default_instance(); + } static inline const EnumValueOptions* internal_default_instance() { return reinterpret_cast( &_EnumValueOptions_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 17; + static constexpr int kIndexInFileMessages = + 18; - void Swap(EnumValueOptions* other); friend void swap(EnumValueOptions& a, EnumValueOptions& b) { a.Swap(&b); } + inline void Swap(EnumValueOptions* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(EnumValueOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline EnumValueOptions* New() const PROTOBUF_FINAL { return New(NULL); } + inline EnumValueOptions* New() const final { + return CreateMaybeMessage(nullptr); + } - EnumValueOptions* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + EnumValueOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const EnumValueOptions& from); void MergeFrom(const EnumValueOptions& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(EnumValueOptions* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(EnumValueOptions* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.EnumValueOptions"; } + protected: + explicit EnumValueOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kUninterpretedOptionFieldNumber = 999, + kDeprecatedFieldNumber = 1, + }; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: void clear_uninterpreted_option(); - static const int kUninterpretedOptionFieldNumber = 999; - const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* mutable_uninterpreted_option(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + private: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& uninterpreted_option() const; // optional bool deprecated = 1 [default = false]; bool has_deprecated() const; + private: + bool _internal_has_deprecated() const; + public: void clear_deprecated(); - static const int kDeprecatedFieldNumber = 1; bool deprecated() const; void set_deprecated(bool value); + private: + bool _internal_deprecated() const; + void _internal_set_deprecated(bool value); + public: GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions) // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions) private: - void set_has_deprecated(); - void clear_has_deprecated(); + class _Internal; - ::google::protobuf::internal::ExtensionSet _extensions_; + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; bool deprecated_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ServiceOptions) */ { +class PROTOBUF_EXPORT ServiceOptions PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ServiceOptions) */ { public: - ServiceOptions(); + inline ServiceOptions() : ServiceOptions(nullptr) {} virtual ~ServiceOptions(); + explicit constexpr ServiceOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); ServiceOptions(const ServiceOptions& from); - - inline ServiceOptions& operator=(const ServiceOptions& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 ServiceOptions(ServiceOptions&& from) noexcept : ServiceOptions() { *this = ::std::move(from); } + inline ServiceOptions& operator=(const ServiceOptions& from) { + CopyFrom(from); + return *this; + } inline ServiceOptions& operator=(ServiceOptions&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const ServiceOptions& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const ServiceOptions& default_instance() { + return *internal_default_instance(); + } static inline const ServiceOptions* internal_default_instance() { return reinterpret_cast( &_ServiceOptions_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 18; + static constexpr int kIndexInFileMessages = + 19; - void Swap(ServiceOptions* other); friend void swap(ServiceOptions& a, ServiceOptions& b) { a.Swap(&b); } + inline void Swap(ServiceOptions* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ServiceOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline ServiceOptions* New() const PROTOBUF_FINAL { return New(NULL); } + inline ServiceOptions* New() const final { + return CreateMaybeMessage(nullptr); + } - ServiceOptions* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + ServiceOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const ServiceOptions& from); void MergeFrom(const ServiceOptions& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(ServiceOptions* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(ServiceOptions* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.ServiceOptions"; } + protected: + explicit ServiceOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kUninterpretedOptionFieldNumber = 999, + kDeprecatedFieldNumber = 33, + }; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: void clear_uninterpreted_option(); - static const int kUninterpretedOptionFieldNumber = 999; - const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* mutable_uninterpreted_option(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + private: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& uninterpreted_option() const; // optional bool deprecated = 33 [default = false]; bool has_deprecated() const; + private: + bool _internal_has_deprecated() const; + public: void clear_deprecated(); - static const int kDeprecatedFieldNumber = 33; bool deprecated() const; void set_deprecated(bool value); + private: + bool _internal_deprecated() const; + void _internal_set_deprecated(bool value); + public: GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions) // @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions) private: - void set_has_deprecated(); - void clear_has_deprecated(); + class _Internal; - ::google::protobuf::internal::ExtensionSet _extensions_; + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; bool deprecated_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MethodOptions) */ { +class PROTOBUF_EXPORT MethodOptions PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MethodOptions) */ { public: - MethodOptions(); + inline MethodOptions() : MethodOptions(nullptr) {} virtual ~MethodOptions(); + explicit constexpr MethodOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); MethodOptions(const MethodOptions& from); - - inline MethodOptions& operator=(const MethodOptions& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 MethodOptions(MethodOptions&& from) noexcept : MethodOptions() { *this = ::std::move(from); } + inline MethodOptions& operator=(const MethodOptions& from) { + CopyFrom(from); + return *this; + } inline MethodOptions& operator=(MethodOptions&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const MethodOptions& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const MethodOptions& default_instance() { + return *internal_default_instance(); + } static inline const MethodOptions* internal_default_instance() { return reinterpret_cast( &_MethodOptions_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 19; + static constexpr int kIndexInFileMessages = + 20; - void Swap(MethodOptions* other); friend void swap(MethodOptions& a, MethodOptions& b) { a.Swap(&b); } + inline void Swap(MethodOptions* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(MethodOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline MethodOptions* New() const PROTOBUF_FINAL { return New(NULL); } + inline MethodOptions* New() const final { + return CreateMaybeMessage(nullptr); + } - MethodOptions* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + MethodOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const MethodOptions& from); void MergeFrom(const MethodOptions& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(MethodOptions* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(MethodOptions* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.MethodOptions"; } + protected: + explicit MethodOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- typedef MethodOptions_IdempotencyLevel IdempotencyLevel; - static const IdempotencyLevel IDEMPOTENCY_UNKNOWN = + static constexpr IdempotencyLevel IDEMPOTENCY_UNKNOWN = MethodOptions_IdempotencyLevel_IDEMPOTENCY_UNKNOWN; - static const IdempotencyLevel NO_SIDE_EFFECTS = + static constexpr IdempotencyLevel NO_SIDE_EFFECTS = MethodOptions_IdempotencyLevel_NO_SIDE_EFFECTS; - static const IdempotencyLevel IDEMPOTENT = + static constexpr IdempotencyLevel IDEMPOTENT = MethodOptions_IdempotencyLevel_IDEMPOTENT; static inline bool IdempotencyLevel_IsValid(int value) { return MethodOptions_IdempotencyLevel_IsValid(value); } - static const IdempotencyLevel IdempotencyLevel_MIN = + static constexpr IdempotencyLevel IdempotencyLevel_MIN = MethodOptions_IdempotencyLevel_IdempotencyLevel_MIN; - static const IdempotencyLevel IdempotencyLevel_MAX = + static constexpr IdempotencyLevel IdempotencyLevel_MAX = MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX; - static const int IdempotencyLevel_ARRAYSIZE = + static constexpr int IdempotencyLevel_ARRAYSIZE = MethodOptions_IdempotencyLevel_IdempotencyLevel_ARRAYSIZE; - static inline const ::google::protobuf::EnumDescriptor* + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* IdempotencyLevel_descriptor() { return MethodOptions_IdempotencyLevel_descriptor(); } - static inline const ::std::string& IdempotencyLevel_Name(IdempotencyLevel value) { - return MethodOptions_IdempotencyLevel_Name(value); + template + static inline const std::string& IdempotencyLevel_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function IdempotencyLevel_Name."); + return MethodOptions_IdempotencyLevel_Name(enum_t_value); } - static inline bool IdempotencyLevel_Parse(const ::std::string& name, + static inline bool IdempotencyLevel_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, IdempotencyLevel* value) { return MethodOptions_IdempotencyLevel_Parse(name, value); } // accessors ------------------------------------------------------- + enum : int { + kUninterpretedOptionFieldNumber = 999, + kDeprecatedFieldNumber = 33, + kIdempotencyLevelFieldNumber = 34, + }; // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: void clear_uninterpreted_option(); - static const int kUninterpretedOptionFieldNumber = 999; - const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* mutable_uninterpreted_option(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + private: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& uninterpreted_option() const; // optional bool deprecated = 33 [default = false]; bool has_deprecated() const; + private: + bool _internal_has_deprecated() const; + public: void clear_deprecated(); - static const int kDeprecatedFieldNumber = 33; bool deprecated() const; void set_deprecated(bool value); + private: + bool _internal_deprecated() const; + void _internal_set_deprecated(bool value); + public: // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; bool has_idempotency_level() const; + private: + bool _internal_has_idempotency_level() const; + public: void clear_idempotency_level(); - static const int kIdempotencyLevelFieldNumber = 34; - ::google::protobuf::MethodOptions_IdempotencyLevel idempotency_level() const; - void set_idempotency_level(::google::protobuf::MethodOptions_IdempotencyLevel value); + PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel idempotency_level() const; + void set_idempotency_level(PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel value); + private: + PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel _internal_idempotency_level() const; + void _internal_set_idempotency_level(PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel value); + public: GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions) // @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions) private: - void set_has_deprecated(); - void clear_has_deprecated(); - void set_has_idempotency_level(); - void clear_has_idempotency_level(); + class _Internal; - ::google::protobuf::internal::ExtensionSet _extensions_; + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; bool deprecated_; int idempotency_level_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UninterpretedOption.NamePart) */ { +class PROTOBUF_EXPORT UninterpretedOption_NamePart PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UninterpretedOption.NamePart) */ { public: - UninterpretedOption_NamePart(); + inline UninterpretedOption_NamePart() : UninterpretedOption_NamePart(nullptr) {} virtual ~UninterpretedOption_NamePart(); + explicit constexpr UninterpretedOption_NamePart(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from); - - inline UninterpretedOption_NamePart& operator=(const UninterpretedOption_NamePart& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 UninterpretedOption_NamePart(UninterpretedOption_NamePart&& from) noexcept : UninterpretedOption_NamePart() { *this = ::std::move(from); } + inline UninterpretedOption_NamePart& operator=(const UninterpretedOption_NamePart& from) { + CopyFrom(from); + return *this; + } inline UninterpretedOption_NamePart& operator=(UninterpretedOption_NamePart&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const UninterpretedOption_NamePart& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const UninterpretedOption_NamePart& default_instance() { + return *internal_default_instance(); + } static inline const UninterpretedOption_NamePart* internal_default_instance() { return reinterpret_cast( &_UninterpretedOption_NamePart_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 20; + static constexpr int kIndexInFileMessages = + 21; - void Swap(UninterpretedOption_NamePart* other); friend void swap(UninterpretedOption_NamePart& a, UninterpretedOption_NamePart& b) { a.Swap(&b); } + inline void Swap(UninterpretedOption_NamePart* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(UninterpretedOption_NamePart* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline UninterpretedOption_NamePart* New() const PROTOBUF_FINAL { return New(NULL); } + inline UninterpretedOption_NamePart* New() const final { + return CreateMaybeMessage(nullptr); + } - UninterpretedOption_NamePart* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + UninterpretedOption_NamePart* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const UninterpretedOption_NamePart& from); void MergeFrom(const UninterpretedOption_NamePart& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(UninterpretedOption_NamePart* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(UninterpretedOption_NamePart* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.UninterpretedOption.NamePart"; } + protected: + explicit UninterpretedOption_NamePart(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kNamePartFieldNumber = 1, + kIsExtensionFieldNumber = 2, + }; // required string name_part = 1; bool has_name_part() const; + private: + bool _internal_has_name_part() const; + public: void clear_name_part(); - static const int kNamePartFieldNumber = 1; - const ::std::string& name_part() const; - void set_name_part(const ::std::string& value); - #if LANG_CXX11 - void set_name_part(::std::string&& value); - #endif + const std::string& name_part() const; + void set_name_part(const std::string& value); + void set_name_part(std::string&& value); void set_name_part(const char* value); void set_name_part(const char* value, size_t size); - ::std::string* mutable_name_part(); - ::std::string* release_name_part(); - void set_allocated_name_part(::std::string* name_part); + std::string* mutable_name_part(); + std::string* release_name_part(); + void set_allocated_name_part(std::string* name_part); + private: + const std::string& _internal_name_part() const; + void _internal_set_name_part(const std::string& value); + std::string* _internal_mutable_name_part(); + public: // required bool is_extension = 2; bool has_is_extension() const; + private: + bool _internal_has_is_extension() const; + public: void clear_is_extension(); - static const int kIsExtensionFieldNumber = 2; bool is_extension() const; void set_is_extension(bool value); + private: + bool _internal_is_extension() const; + void _internal_set_is_extension(bool value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart) private: - void set_has_name_part(); - void clear_has_name_part(); - void set_has_is_extension(); - void clear_has_is_extension(); + class _Internal; // helper for ByteSizeLong() size_t RequiredFieldsByteSizeFallback() const; - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::internal::ArenaStringPtr name_part_; + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_part_; bool is_extension_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UninterpretedOption) */ { +class PROTOBUF_EXPORT UninterpretedOption PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UninterpretedOption) */ { public: - UninterpretedOption(); + inline UninterpretedOption() : UninterpretedOption(nullptr) {} virtual ~UninterpretedOption(); + explicit constexpr UninterpretedOption(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); UninterpretedOption(const UninterpretedOption& from); - - inline UninterpretedOption& operator=(const UninterpretedOption& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 UninterpretedOption(UninterpretedOption&& from) noexcept : UninterpretedOption() { *this = ::std::move(from); } + inline UninterpretedOption& operator=(const UninterpretedOption& from) { + CopyFrom(from); + return *this; + } inline UninterpretedOption& operator=(UninterpretedOption&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const UninterpretedOption& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const UninterpretedOption& default_instance() { + return *internal_default_instance(); + } static inline const UninterpretedOption* internal_default_instance() { return reinterpret_cast( &_UninterpretedOption_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 21; + static constexpr int kIndexInFileMessages = + 22; - void Swap(UninterpretedOption* other); friend void swap(UninterpretedOption& a, UninterpretedOption& b) { a.Swap(&b); } + inline void Swap(UninterpretedOption* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(UninterpretedOption* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline UninterpretedOption* New() const PROTOBUF_FINAL { return New(NULL); } + inline UninterpretedOption* New() const final { + return CreateMaybeMessage(nullptr); + } - UninterpretedOption* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + UninterpretedOption* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const UninterpretedOption& from); void MergeFrom(const UninterpretedOption& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(UninterpretedOption* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(UninterpretedOption* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.UninterpretedOption"; } + protected: + explicit UninterpretedOption(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- @@ -3969,381 +5668,520 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag // accessors ------------------------------------------------------- + enum : int { + kNameFieldNumber = 2, + kIdentifierValueFieldNumber = 3, + kStringValueFieldNumber = 7, + kAggregateValueFieldNumber = 8, + kPositiveIntValueFieldNumber = 4, + kNegativeIntValueFieldNumber = 5, + kDoubleValueFieldNumber = 6, + }; // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; int name_size() const; + private: + int _internal_name_size() const; + public: void clear_name(); - static const int kNameFieldNumber = 2; - const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const; - ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index); - ::google::protobuf::UninterpretedOption_NamePart* add_name(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* + PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* mutable_name(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart >* mutable_name(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& + private: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart& _internal_name(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* _internal_add_name(); + public: + const PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart& name(int index) const; + PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* add_name(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart >& name() const; // optional string identifier_value = 3; bool has_identifier_value() const; + private: + bool _internal_has_identifier_value() const; + public: void clear_identifier_value(); - static const int kIdentifierValueFieldNumber = 3; - const ::std::string& identifier_value() const; - void set_identifier_value(const ::std::string& value); - #if LANG_CXX11 - void set_identifier_value(::std::string&& value); - #endif + const std::string& identifier_value() const; + void set_identifier_value(const std::string& value); + void set_identifier_value(std::string&& value); void set_identifier_value(const char* value); void set_identifier_value(const char* value, size_t size); - ::std::string* mutable_identifier_value(); - ::std::string* release_identifier_value(); - void set_allocated_identifier_value(::std::string* identifier_value); + std::string* mutable_identifier_value(); + std::string* release_identifier_value(); + void set_allocated_identifier_value(std::string* identifier_value); + private: + const std::string& _internal_identifier_value() const; + void _internal_set_identifier_value(const std::string& value); + std::string* _internal_mutable_identifier_value(); + public: // optional bytes string_value = 7; bool has_string_value() const; + private: + bool _internal_has_string_value() const; + public: void clear_string_value(); - static const int kStringValueFieldNumber = 7; - const ::std::string& string_value() const; - void set_string_value(const ::std::string& value); - #if LANG_CXX11 - void set_string_value(::std::string&& value); - #endif + const std::string& string_value() const; + void set_string_value(const std::string& value); + void set_string_value(std::string&& value); void set_string_value(const char* value); void set_string_value(const void* value, size_t size); - ::std::string* mutable_string_value(); - ::std::string* release_string_value(); - void set_allocated_string_value(::std::string* string_value); + std::string* mutable_string_value(); + std::string* release_string_value(); + void set_allocated_string_value(std::string* string_value); + private: + const std::string& _internal_string_value() const; + void _internal_set_string_value(const std::string& value); + std::string* _internal_mutable_string_value(); + public: // optional string aggregate_value = 8; bool has_aggregate_value() const; + private: + bool _internal_has_aggregate_value() const; + public: void clear_aggregate_value(); - static const int kAggregateValueFieldNumber = 8; - const ::std::string& aggregate_value() const; - void set_aggregate_value(const ::std::string& value); - #if LANG_CXX11 - void set_aggregate_value(::std::string&& value); - #endif + const std::string& aggregate_value() const; + void set_aggregate_value(const std::string& value); + void set_aggregate_value(std::string&& value); void set_aggregate_value(const char* value); void set_aggregate_value(const char* value, size_t size); - ::std::string* mutable_aggregate_value(); - ::std::string* release_aggregate_value(); - void set_allocated_aggregate_value(::std::string* aggregate_value); + std::string* mutable_aggregate_value(); + std::string* release_aggregate_value(); + void set_allocated_aggregate_value(std::string* aggregate_value); + private: + const std::string& _internal_aggregate_value() const; + void _internal_set_aggregate_value(const std::string& value); + std::string* _internal_mutable_aggregate_value(); + public: // optional uint64 positive_int_value = 4; bool has_positive_int_value() const; + private: + bool _internal_has_positive_int_value() const; + public: void clear_positive_int_value(); - static const int kPositiveIntValueFieldNumber = 4; - ::google::protobuf::uint64 positive_int_value() const; - void set_positive_int_value(::google::protobuf::uint64 value); + ::PROTOBUF_NAMESPACE_ID::uint64 positive_int_value() const; + void set_positive_int_value(::PROTOBUF_NAMESPACE_ID::uint64 value); + private: + ::PROTOBUF_NAMESPACE_ID::uint64 _internal_positive_int_value() const; + void _internal_set_positive_int_value(::PROTOBUF_NAMESPACE_ID::uint64 value); + public: // optional int64 negative_int_value = 5; bool has_negative_int_value() const; + private: + bool _internal_has_negative_int_value() const; + public: void clear_negative_int_value(); - static const int kNegativeIntValueFieldNumber = 5; - ::google::protobuf::int64 negative_int_value() const; - void set_negative_int_value(::google::protobuf::int64 value); + ::PROTOBUF_NAMESPACE_ID::int64 negative_int_value() const; + void set_negative_int_value(::PROTOBUF_NAMESPACE_ID::int64 value); + private: + ::PROTOBUF_NAMESPACE_ID::int64 _internal_negative_int_value() const; + void _internal_set_negative_int_value(::PROTOBUF_NAMESPACE_ID::int64 value); + public: // optional double double_value = 6; bool has_double_value() const; + private: + bool _internal_has_double_value() const; + public: void clear_double_value(); - static const int kDoubleValueFieldNumber = 6; double double_value() const; void set_double_value(double value); + private: + double _internal_double_value() const; + void _internal_set_double_value(double value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption) private: - void set_has_identifier_value(); - void clear_has_identifier_value(); - void set_has_positive_int_value(); - void clear_has_positive_int_value(); - void set_has_negative_int_value(); - void clear_has_negative_int_value(); - void set_has_double_value(); - void clear_has_double_value(); - void set_has_string_value(); - void clear_has_string_value(); - void set_has_aggregate_value(); - void clear_has_aggregate_value(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart > name_; - ::google::protobuf::internal::ArenaStringPtr identifier_value_; - ::google::protobuf::internal::ArenaStringPtr string_value_; - ::google::protobuf::internal::ArenaStringPtr aggregate_value_; - ::google::protobuf::uint64 positive_int_value_; - ::google::protobuf::int64 negative_int_value_; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart > name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr identifier_value_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr string_value_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr aggregate_value_; + ::PROTOBUF_NAMESPACE_ID::uint64 positive_int_value_; + ::PROTOBUF_NAMESPACE_ID::int64 negative_int_value_; double double_value_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceCodeInfo.Location) */ { +class PROTOBUF_EXPORT SourceCodeInfo_Location PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceCodeInfo.Location) */ { public: - SourceCodeInfo_Location(); + inline SourceCodeInfo_Location() : SourceCodeInfo_Location(nullptr) {} virtual ~SourceCodeInfo_Location(); + explicit constexpr SourceCodeInfo_Location(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); SourceCodeInfo_Location(const SourceCodeInfo_Location& from); - - inline SourceCodeInfo_Location& operator=(const SourceCodeInfo_Location& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 SourceCodeInfo_Location(SourceCodeInfo_Location&& from) noexcept : SourceCodeInfo_Location() { *this = ::std::move(from); } + inline SourceCodeInfo_Location& operator=(const SourceCodeInfo_Location& from) { + CopyFrom(from); + return *this; + } inline SourceCodeInfo_Location& operator=(SourceCodeInfo_Location&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const SourceCodeInfo_Location& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const SourceCodeInfo_Location& default_instance() { + return *internal_default_instance(); + } static inline const SourceCodeInfo_Location* internal_default_instance() { return reinterpret_cast( &_SourceCodeInfo_Location_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 22; + static constexpr int kIndexInFileMessages = + 23; - void Swap(SourceCodeInfo_Location* other); friend void swap(SourceCodeInfo_Location& a, SourceCodeInfo_Location& b) { a.Swap(&b); } + inline void Swap(SourceCodeInfo_Location* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SourceCodeInfo_Location* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline SourceCodeInfo_Location* New() const PROTOBUF_FINAL { return New(NULL); } + inline SourceCodeInfo_Location* New() const final { + return CreateMaybeMessage(nullptr); + } - SourceCodeInfo_Location* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + SourceCodeInfo_Location* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const SourceCodeInfo_Location& from); void MergeFrom(const SourceCodeInfo_Location& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(SourceCodeInfo_Location* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(SourceCodeInfo_Location* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.SourceCodeInfo.Location"; } + protected: + explicit SourceCodeInfo_Location(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kPathFieldNumber = 1, + kSpanFieldNumber = 2, + kLeadingDetachedCommentsFieldNumber = 6, + kLeadingCommentsFieldNumber = 3, + kTrailingCommentsFieldNumber = 4, + }; // repeated int32 path = 1 [packed = true]; int path_size() const; + private: + int _internal_path_size() const; + public: void clear_path(); - static const int kPathFieldNumber = 1; - ::google::protobuf::int32 path(int index) const; - void set_path(int index, ::google::protobuf::int32 value); - void add_path(::google::protobuf::int32 value); - const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_path(int index) const; + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& + _internal_path() const; + void _internal_add_path(::PROTOBUF_NAMESPACE_ID::int32 value); + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* + _internal_mutable_path(); + public: + ::PROTOBUF_NAMESPACE_ID::int32 path(int index) const; + void set_path(int index, ::PROTOBUF_NAMESPACE_ID::int32 value); + void add_path(::PROTOBUF_NAMESPACE_ID::int32 value); + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& path() const; - ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* mutable_path(); // repeated int32 span = 2 [packed = true]; int span_size() const; + private: + int _internal_span_size() const; + public: void clear_span(); - static const int kSpanFieldNumber = 2; - ::google::protobuf::int32 span(int index) const; - void set_span(int index, ::google::protobuf::int32 value); - void add_span(::google::protobuf::int32 value); - const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_span(int index) const; + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& + _internal_span() const; + void _internal_add_span(::PROTOBUF_NAMESPACE_ID::int32 value); + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* + _internal_mutable_span(); + public: + ::PROTOBUF_NAMESPACE_ID::int32 span(int index) const; + void set_span(int index, ::PROTOBUF_NAMESPACE_ID::int32 value); + void add_span(::PROTOBUF_NAMESPACE_ID::int32 value); + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& span() const; - ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* mutable_span(); // repeated string leading_detached_comments = 6; int leading_detached_comments_size() const; + private: + int _internal_leading_detached_comments_size() const; + public: void clear_leading_detached_comments(); - static const int kLeadingDetachedCommentsFieldNumber = 6; - const ::std::string& leading_detached_comments(int index) const; - ::std::string* mutable_leading_detached_comments(int index); - void set_leading_detached_comments(int index, const ::std::string& value); - #if LANG_CXX11 - void set_leading_detached_comments(int index, ::std::string&& value); - #endif + const std::string& leading_detached_comments(int index) const; + std::string* mutable_leading_detached_comments(int index); + void set_leading_detached_comments(int index, const std::string& value); + void set_leading_detached_comments(int index, std::string&& value); void set_leading_detached_comments(int index, const char* value); void set_leading_detached_comments(int index, const char* value, size_t size); - ::std::string* add_leading_detached_comments(); - void add_leading_detached_comments(const ::std::string& value); - #if LANG_CXX11 - void add_leading_detached_comments(::std::string&& value); - #endif + std::string* add_leading_detached_comments(); + void add_leading_detached_comments(const std::string& value); + void add_leading_detached_comments(std::string&& value); void add_leading_detached_comments(const char* value); void add_leading_detached_comments(const char* value, size_t size); - const ::google::protobuf::RepeatedPtrField< ::std::string>& leading_detached_comments() const; - ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_leading_detached_comments(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField& leading_detached_comments() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField* mutable_leading_detached_comments(); + private: + const std::string& _internal_leading_detached_comments(int index) const; + std::string* _internal_add_leading_detached_comments(); + public: // optional string leading_comments = 3; bool has_leading_comments() const; + private: + bool _internal_has_leading_comments() const; + public: void clear_leading_comments(); - static const int kLeadingCommentsFieldNumber = 3; - const ::std::string& leading_comments() const; - void set_leading_comments(const ::std::string& value); - #if LANG_CXX11 - void set_leading_comments(::std::string&& value); - #endif + const std::string& leading_comments() const; + void set_leading_comments(const std::string& value); + void set_leading_comments(std::string&& value); void set_leading_comments(const char* value); void set_leading_comments(const char* value, size_t size); - ::std::string* mutable_leading_comments(); - ::std::string* release_leading_comments(); - void set_allocated_leading_comments(::std::string* leading_comments); + std::string* mutable_leading_comments(); + std::string* release_leading_comments(); + void set_allocated_leading_comments(std::string* leading_comments); + private: + const std::string& _internal_leading_comments() const; + void _internal_set_leading_comments(const std::string& value); + std::string* _internal_mutable_leading_comments(); + public: // optional string trailing_comments = 4; bool has_trailing_comments() const; + private: + bool _internal_has_trailing_comments() const; + public: void clear_trailing_comments(); - static const int kTrailingCommentsFieldNumber = 4; - const ::std::string& trailing_comments() const; - void set_trailing_comments(const ::std::string& value); - #if LANG_CXX11 - void set_trailing_comments(::std::string&& value); - #endif + const std::string& trailing_comments() const; + void set_trailing_comments(const std::string& value); + void set_trailing_comments(std::string&& value); void set_trailing_comments(const char* value); void set_trailing_comments(const char* value, size_t size); - ::std::string* mutable_trailing_comments(); - ::std::string* release_trailing_comments(); - void set_allocated_trailing_comments(::std::string* trailing_comments); + std::string* mutable_trailing_comments(); + std::string* release_trailing_comments(); + void set_allocated_trailing_comments(std::string* trailing_comments); + private: + const std::string& _internal_trailing_comments() const; + void _internal_set_trailing_comments(const std::string& value); + std::string* _internal_mutable_trailing_comments(); + public: // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location) private: - void set_has_leading_comments(); - void clear_has_leading_comments(); - void set_has_trailing_comments(); - void clear_has_trailing_comments(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedField< ::google::protobuf::int32 > path_; - mutable int _path_cached_byte_size_; - ::google::protobuf::RepeatedField< ::google::protobuf::int32 > span_; - mutable int _span_cached_byte_size_; - ::google::protobuf::RepeatedPtrField< ::std::string> leading_detached_comments_; - ::google::protobuf::internal::ArenaStringPtr leading_comments_; - ::google::protobuf::internal::ArenaStringPtr trailing_comments_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 > path_; + mutable std::atomic _path_cached_byte_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 > span_; + mutable std::atomic _span_cached_byte_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField leading_detached_comments_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr leading_comments_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr trailing_comments_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceCodeInfo) */ { +class PROTOBUF_EXPORT SourceCodeInfo PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceCodeInfo) */ { public: - SourceCodeInfo(); + inline SourceCodeInfo() : SourceCodeInfo(nullptr) {} virtual ~SourceCodeInfo(); + explicit constexpr SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); SourceCodeInfo(const SourceCodeInfo& from); - - inline SourceCodeInfo& operator=(const SourceCodeInfo& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 SourceCodeInfo(SourceCodeInfo&& from) noexcept : SourceCodeInfo() { *this = ::std::move(from); } + inline SourceCodeInfo& operator=(const SourceCodeInfo& from) { + CopyFrom(from); + return *this; + } inline SourceCodeInfo& operator=(SourceCodeInfo&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const SourceCodeInfo& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const SourceCodeInfo& default_instance() { + return *internal_default_instance(); + } static inline const SourceCodeInfo* internal_default_instance() { return reinterpret_cast( &_SourceCodeInfo_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 23; + static constexpr int kIndexInFileMessages = + 24; - void Swap(SourceCodeInfo* other); friend void swap(SourceCodeInfo& a, SourceCodeInfo& b) { a.Swap(&b); } + inline void Swap(SourceCodeInfo* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SourceCodeInfo* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline SourceCodeInfo* New() const PROTOBUF_FINAL { return New(NULL); } + inline SourceCodeInfo* New() const final { + return CreateMaybeMessage(nullptr); + } - SourceCodeInfo* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + SourceCodeInfo* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const SourceCodeInfo& from); void MergeFrom(const SourceCodeInfo& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(SourceCodeInfo* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(SourceCodeInfo* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.SourceCodeInfo"; } + protected: + explicit SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- @@ -4351,262 +6189,365 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message /* // accessors ------------------------------------------------------- + enum : int { + kLocationFieldNumber = 1, + }; // repeated .google.protobuf.SourceCodeInfo.Location location = 1; int location_size() const; + private: + int _internal_location_size() const; + public: void clear_location(); - static const int kLocationFieldNumber = 1; - const ::google::protobuf::SourceCodeInfo_Location& location(int index) const; - ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index); - ::google::protobuf::SourceCodeInfo_Location* add_location(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* + PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* mutable_location(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location >* mutable_location(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& + private: + const PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location& _internal_location(int index) const; + PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* _internal_add_location(); + public: + const PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location& location(int index) const; + PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* add_location(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location >& location() const; // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo) private: - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location > location_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT GeneratedCodeInfo_Annotation : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.GeneratedCodeInfo.Annotation) */ { +class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.GeneratedCodeInfo.Annotation) */ { public: - GeneratedCodeInfo_Annotation(); + inline GeneratedCodeInfo_Annotation() : GeneratedCodeInfo_Annotation(nullptr) {} virtual ~GeneratedCodeInfo_Annotation(); + explicit constexpr GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); GeneratedCodeInfo_Annotation(const GeneratedCodeInfo_Annotation& from); - - inline GeneratedCodeInfo_Annotation& operator=(const GeneratedCodeInfo_Annotation& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 GeneratedCodeInfo_Annotation(GeneratedCodeInfo_Annotation&& from) noexcept : GeneratedCodeInfo_Annotation() { *this = ::std::move(from); } + inline GeneratedCodeInfo_Annotation& operator=(const GeneratedCodeInfo_Annotation& from) { + CopyFrom(from); + return *this; + } inline GeneratedCodeInfo_Annotation& operator=(GeneratedCodeInfo_Annotation&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const GeneratedCodeInfo_Annotation& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const GeneratedCodeInfo_Annotation& default_instance() { + return *internal_default_instance(); + } static inline const GeneratedCodeInfo_Annotation* internal_default_instance() { return reinterpret_cast( &_GeneratedCodeInfo_Annotation_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 24; + static constexpr int kIndexInFileMessages = + 25; - void Swap(GeneratedCodeInfo_Annotation* other); friend void swap(GeneratedCodeInfo_Annotation& a, GeneratedCodeInfo_Annotation& b) { a.Swap(&b); } + inline void Swap(GeneratedCodeInfo_Annotation* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(GeneratedCodeInfo_Annotation* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline GeneratedCodeInfo_Annotation* New() const PROTOBUF_FINAL { return New(NULL); } + inline GeneratedCodeInfo_Annotation* New() const final { + return CreateMaybeMessage(nullptr); + } - GeneratedCodeInfo_Annotation* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + GeneratedCodeInfo_Annotation* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const GeneratedCodeInfo_Annotation& from); void MergeFrom(const GeneratedCodeInfo_Annotation& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(GeneratedCodeInfo_Annotation* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(GeneratedCodeInfo_Annotation* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.GeneratedCodeInfo.Annotation"; } + protected: + explicit GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kPathFieldNumber = 1, + kSourceFileFieldNumber = 2, + kBeginFieldNumber = 3, + kEndFieldNumber = 4, + }; // repeated int32 path = 1 [packed = true]; int path_size() const; + private: + int _internal_path_size() const; + public: void clear_path(); - static const int kPathFieldNumber = 1; - ::google::protobuf::int32 path(int index) const; - void set_path(int index, ::google::protobuf::int32 value); - void add_path(::google::protobuf::int32 value); - const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_path(int index) const; + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& + _internal_path() const; + void _internal_add_path(::PROTOBUF_NAMESPACE_ID::int32 value); + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* + _internal_mutable_path(); + public: + ::PROTOBUF_NAMESPACE_ID::int32 path(int index) const; + void set_path(int index, ::PROTOBUF_NAMESPACE_ID::int32 value); + void add_path(::PROTOBUF_NAMESPACE_ID::int32 value); + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& path() const; - ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* mutable_path(); // optional string source_file = 2; bool has_source_file() const; + private: + bool _internal_has_source_file() const; + public: void clear_source_file(); - static const int kSourceFileFieldNumber = 2; - const ::std::string& source_file() const; - void set_source_file(const ::std::string& value); - #if LANG_CXX11 - void set_source_file(::std::string&& value); - #endif + const std::string& source_file() const; + void set_source_file(const std::string& value); + void set_source_file(std::string&& value); void set_source_file(const char* value); void set_source_file(const char* value, size_t size); - ::std::string* mutable_source_file(); - ::std::string* release_source_file(); - void set_allocated_source_file(::std::string* source_file); + std::string* mutable_source_file(); + std::string* release_source_file(); + void set_allocated_source_file(std::string* source_file); + private: + const std::string& _internal_source_file() const; + void _internal_set_source_file(const std::string& value); + std::string* _internal_mutable_source_file(); + public: // optional int32 begin = 3; bool has_begin() const; + private: + bool _internal_has_begin() const; + public: void clear_begin(); - static const int kBeginFieldNumber = 3; - ::google::protobuf::int32 begin() const; - void set_begin(::google::protobuf::int32 value); + ::PROTOBUF_NAMESPACE_ID::int32 begin() const; + void set_begin(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_begin() const; + void _internal_set_begin(::PROTOBUF_NAMESPACE_ID::int32 value); + public: // optional int32 end = 4; bool has_end() const; + private: + bool _internal_has_end() const; + public: void clear_end(); - static const int kEndFieldNumber = 4; - ::google::protobuf::int32 end() const; - void set_end(::google::protobuf::int32 value); + ::PROTOBUF_NAMESPACE_ID::int32 end() const; + void set_end(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_end() const; + void _internal_set_end(::PROTOBUF_NAMESPACE_ID::int32 value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo.Annotation) private: - void set_has_source_file(); - void clear_has_source_file(); - void set_has_begin(); - void clear_has_begin(); - void set_has_end(); - void clear_has_end(); - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedField< ::google::protobuf::int32 > path_; - mutable int _path_cached_byte_size_; - ::google::protobuf::internal::ArenaStringPtr source_file_; - ::google::protobuf::int32 begin_; - ::google::protobuf::int32 end_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 > path_; + mutable std::atomic _path_cached_byte_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr source_file_; + ::PROTOBUF_NAMESPACE_ID::int32 begin_; + ::PROTOBUF_NAMESPACE_ID::int32 end_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT GeneratedCodeInfo : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.GeneratedCodeInfo) */ { +class PROTOBUF_EXPORT GeneratedCodeInfo PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.GeneratedCodeInfo) */ { public: - GeneratedCodeInfo(); + inline GeneratedCodeInfo() : GeneratedCodeInfo(nullptr) {} virtual ~GeneratedCodeInfo(); + explicit constexpr GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); GeneratedCodeInfo(const GeneratedCodeInfo& from); - - inline GeneratedCodeInfo& operator=(const GeneratedCodeInfo& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 GeneratedCodeInfo(GeneratedCodeInfo&& from) noexcept : GeneratedCodeInfo() { *this = ::std::move(from); } + inline GeneratedCodeInfo& operator=(const GeneratedCodeInfo& from) { + CopyFrom(from); + return *this; + } inline GeneratedCodeInfo& operator=(GeneratedCodeInfo&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields(); + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); } - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields(); + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const GeneratedCodeInfo& default_instance(); - + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const GeneratedCodeInfo& default_instance() { + return *internal_default_instance(); + } static inline const GeneratedCodeInfo* internal_default_instance() { return reinterpret_cast( &_GeneratedCodeInfo_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = - 25; + static constexpr int kIndexInFileMessages = + 26; - void Swap(GeneratedCodeInfo* other); friend void swap(GeneratedCodeInfo& a, GeneratedCodeInfo& b) { a.Swap(&b); } + inline void Swap(GeneratedCodeInfo* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(GeneratedCodeInfo* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline GeneratedCodeInfo* New() const PROTOBUF_FINAL { return New(NULL); } + inline GeneratedCodeInfo* New() const final { + return CreateMaybeMessage(nullptr); + } - GeneratedCodeInfo* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + GeneratedCodeInfo* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const GeneratedCodeInfo& from); void MergeFrom(const GeneratedCodeInfo& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; - void InternalSwap(GeneratedCodeInfo* other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(GeneratedCodeInfo* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.GeneratedCodeInfo"; } + protected: + explicit GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- @@ -4614,33 +6555,43 @@ class LIBPROTOBUF_EXPORT GeneratedCodeInfo : public ::google::protobuf::Message // accessors ------------------------------------------------------- + enum : int { + kAnnotationFieldNumber = 1, + }; // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; int annotation_size() const; + private: + int _internal_annotation_size() const; + public: void clear_annotation(); - static const int kAnnotationFieldNumber = 1; - const ::google::protobuf::GeneratedCodeInfo_Annotation& annotation(int index) const; - ::google::protobuf::GeneratedCodeInfo_Annotation* mutable_annotation(int index); - ::google::protobuf::GeneratedCodeInfo_Annotation* add_annotation(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >* + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* mutable_annotation(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation >* mutable_annotation(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >& + private: + const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation& _internal_annotation(int index) const; + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* _internal_add_annotation(); + public: + const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation& annotation(int index) const; + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* add_annotation(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation >& annotation() const; // @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo) private: - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable int _cached_size_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation > annotation_; - friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation > annotation_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; // =================================================================== // =================================================================== -#if !PROTOBUF_INLINE_NOT_IN_HEADERS #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" @@ -4648,30 +6599,39 @@ class LIBPROTOBUF_EXPORT GeneratedCodeInfo : public ::google::protobuf::Message // FileDescriptorSet // repeated .google.protobuf.FileDescriptorProto file = 1; -inline int FileDescriptorSet::file_size() const { +inline int FileDescriptorSet::_internal_file_size() const { return file_.size(); } +inline int FileDescriptorSet::file_size() const { + return _internal_file_size(); +} inline void FileDescriptorSet::clear_file() { file_.Clear(); } -inline const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorSet.file) - return file_.Get(index); -} -inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) { +inline PROTOBUF_NAMESPACE_ID::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorSet.file) return file_.Mutable(index); } -inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() { - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file) - return file_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >* FileDescriptorSet::mutable_file() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file) return &file_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& +inline const PROTOBUF_NAMESPACE_ID::FileDescriptorProto& FileDescriptorSet::_internal_file(int index) const { + return file_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::FileDescriptorProto& FileDescriptorSet::file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorSet.file) + return _internal_file(index); +} +inline PROTOBUF_NAMESPACE_ID::FileDescriptorProto* FileDescriptorSet::_internal_add_file() { + return file_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::FileDescriptorProto* FileDescriptorSet::add_file() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file) + return _internal_add_file(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto >& FileDescriptorSet::file() const { // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file) return file_; @@ -4682,158 +6642,186 @@ FileDescriptorSet::file() const { // FileDescriptorProto // optional string name = 1; -inline bool FileDescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void FileDescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; +inline bool FileDescriptorProto::_internal_has_name() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void FileDescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; +inline bool FileDescriptorProto::has_name() const { + return _internal_has_name(); } inline void FileDescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); + name_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& FileDescriptorProto::name() const { +inline const std::string& FileDescriptorProto::name() const { // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name) - return name_.GetNoArena(); + return _internal_name(); } -inline void FileDescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FileDescriptorProto::set_name(const std::string& value) { + _internal_set_name(value); // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.name) } -#if LANG_CXX11 -inline void FileDescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.name) +inline std::string* FileDescriptorProto::mutable_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name) + return _internal_mutable_name(); } -#endif -inline void FileDescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name) +inline const std::string& FileDescriptorProto::_internal_name() const { + return name_.Get(); } -inline void FileDescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FileDescriptorProto::_internal_set_name(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FileDescriptorProto::set_name(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.name) +} +inline void FileDescriptorProto::set_name(const char* value) { + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name) +} +inline void FileDescriptorProto::set_name(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name) } -inline ::std::string* FileDescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FileDescriptorProto::_internal_mutable_name() { + _has_bits_[0] |= 0x00000001u; + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FileDescriptorProto::release_name() { +inline std::string* FileDescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_name()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FileDescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); +inline void FileDescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_name(); + _has_bits_[0] &= ~0x00000001u; } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name) } // optional string package = 2; -inline bool FileDescriptorProto::has_package() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -inline void FileDescriptorProto::set_has_package() { - _has_bits_[0] |= 0x00000002u; +inline bool FileDescriptorProto::_internal_has_package() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void FileDescriptorProto::clear_has_package() { - _has_bits_[0] &= ~0x00000002u; +inline bool FileDescriptorProto::has_package() const { + return _internal_has_package(); } inline void FileDescriptorProto::clear_package() { - package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_package(); + package_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000002u; } -inline const ::std::string& FileDescriptorProto::package() const { +inline const std::string& FileDescriptorProto::package() const { // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package) - return package_.GetNoArena(); + return _internal_package(); } -inline void FileDescriptorProto::set_package(const ::std::string& value) { - set_has_package(); - package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FileDescriptorProto::set_package(const std::string& value) { + _internal_set_package(value); // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.package) } -#if LANG_CXX11 -inline void FileDescriptorProto::set_package(::std::string&& value) { - set_has_package(); - package_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FileDescriptorProto::mutable_package() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package) + return _internal_mutable_package(); +} +inline const std::string& FileDescriptorProto::_internal_package() const { + return package_.Get(); +} +inline void FileDescriptorProto::_internal_set_package(const std::string& value) { + _has_bits_[0] |= 0x00000002u; + package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FileDescriptorProto::set_package(std::string&& value) { + _has_bits_[0] |= 0x00000002u; + package_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.package) } -#endif inline void FileDescriptorProto::set_package(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_package(); - package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000002u; + package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package) } -inline void FileDescriptorProto::set_package(const char* value, size_t size) { - set_has_package(); - package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FileDescriptorProto::set_package(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000002u; + package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package) } -inline ::std::string* FileDescriptorProto::mutable_package() { - set_has_package(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package) - return package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FileDescriptorProto::_internal_mutable_package() { + _has_bits_[0] |= 0x00000002u; + return package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FileDescriptorProto::release_package() { +inline std::string* FileDescriptorProto::release_package() { // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.package) - clear_has_package(); - return package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_package()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000002u; + return package_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FileDescriptorProto::set_allocated_package(::std::string* package) { - if (package != NULL) { - set_has_package(); +inline void FileDescriptorProto::set_allocated_package(std::string* package) { + if (package != nullptr) { + _has_bits_[0] |= 0x00000002u; } else { - clear_has_package(); + _has_bits_[0] &= ~0x00000002u; } - package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), package); + package_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), package, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package) } // repeated string dependency = 3; -inline int FileDescriptorProto::dependency_size() const { +inline int FileDescriptorProto::_internal_dependency_size() const { return dependency_.size(); } +inline int FileDescriptorProto::dependency_size() const { + return _internal_dependency_size(); +} inline void FileDescriptorProto::clear_dependency() { dependency_.Clear(); } -inline const ::std::string& FileDescriptorProto::dependency(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.dependency) +inline std::string* FileDescriptorProto::add_dependency() { + // @@protoc_insertion_point(field_add_mutable:google.protobuf.FileDescriptorProto.dependency) + return _internal_add_dependency(); +} +inline const std::string& FileDescriptorProto::_internal_dependency(int index) const { return dependency_.Get(index); } -inline ::std::string* FileDescriptorProto::mutable_dependency(int index) { +inline const std::string& FileDescriptorProto::dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.dependency) + return _internal_dependency(index); +} +inline std::string* FileDescriptorProto::mutable_dependency(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.dependency) return dependency_.Mutable(index); } -inline void FileDescriptorProto::set_dependency(int index, const ::std::string& value) { +inline void FileDescriptorProto::set_dependency(int index, const std::string& value) { // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency) dependency_.Mutable(index)->assign(value); } -#if LANG_CXX11 -inline void FileDescriptorProto::set_dependency(int index, ::std::string&& value) { +inline void FileDescriptorProto::set_dependency(int index, std::string&& value) { // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency) dependency_.Mutable(index)->assign(std::move(value)); } -#endif inline void FileDescriptorProto::set_dependency(int index, const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); dependency_.Mutable(index)->assign(value); // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.dependency) } @@ -4842,22 +6830,19 @@ inline void FileDescriptorProto::set_dependency(int index, const char* value, si reinterpret_cast(value), size); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency) } -inline ::std::string* FileDescriptorProto::add_dependency() { - // @@protoc_insertion_point(field_add_mutable:google.protobuf.FileDescriptorProto.dependency) +inline std::string* FileDescriptorProto::_internal_add_dependency() { return dependency_.Add(); } -inline void FileDescriptorProto::add_dependency(const ::std::string& value) { +inline void FileDescriptorProto::add_dependency(const std::string& value) { dependency_.Add()->assign(value); // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency) } -#if LANG_CXX11 -inline void FileDescriptorProto::add_dependency(::std::string&& value) { +inline void FileDescriptorProto::add_dependency(std::string&& value) { dependency_.Add(std::move(value)); // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency) } -#endif inline void FileDescriptorProto::add_dependency(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); dependency_.Add()->assign(value); // @@protoc_insertion_point(field_add_char:google.protobuf.FileDescriptorProto.dependency) } @@ -4865,349 +6850,503 @@ inline void FileDescriptorProto::add_dependency(const char* value, size_t size) dependency_.Add()->assign(reinterpret_cast(value), size); // @@protoc_insertion_point(field_add_pointer:google.protobuf.FileDescriptorProto.dependency) } -inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField& FileDescriptorProto::dependency() const { // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.dependency) return dependency_; } -inline ::google::protobuf::RepeatedPtrField< ::std::string>* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField* FileDescriptorProto::mutable_dependency() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.dependency) return &dependency_; } // repeated int32 public_dependency = 10; -inline int FileDescriptorProto::public_dependency_size() const { +inline int FileDescriptorProto::_internal_public_dependency_size() const { return public_dependency_.size(); } +inline int FileDescriptorProto::public_dependency_size() const { + return _internal_public_dependency_size(); +} inline void FileDescriptorProto::clear_public_dependency() { public_dependency_.Clear(); } -inline ::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.public_dependency) +inline ::PROTOBUF_NAMESPACE_ID::int32 FileDescriptorProto::_internal_public_dependency(int index) const { return public_dependency_.Get(index); } -inline void FileDescriptorProto::set_public_dependency(int index, ::google::protobuf::int32 value) { +inline ::PROTOBUF_NAMESPACE_ID::int32 FileDescriptorProto::public_dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.public_dependency) + return _internal_public_dependency(index); +} +inline void FileDescriptorProto::set_public_dependency(int index, ::PROTOBUF_NAMESPACE_ID::int32 value) { public_dependency_.Set(index, value); // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.public_dependency) } -inline void FileDescriptorProto::add_public_dependency(::google::protobuf::int32 value) { +inline void FileDescriptorProto::_internal_add_public_dependency(::PROTOBUF_NAMESPACE_ID::int32 value) { public_dependency_.Add(value); +} +inline void FileDescriptorProto::add_public_dependency(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_add_public_dependency(value); // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.public_dependency) } -inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& +FileDescriptorProto::_internal_public_dependency() const { + return public_dependency_; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& FileDescriptorProto::public_dependency() const { // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.public_dependency) - return public_dependency_; + return _internal_public_dependency(); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* +FileDescriptorProto::_internal_mutable_public_dependency() { + return &public_dependency_; } -inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* FileDescriptorProto::mutable_public_dependency() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.public_dependency) - return &public_dependency_; + return _internal_mutable_public_dependency(); } // repeated int32 weak_dependency = 11; -inline int FileDescriptorProto::weak_dependency_size() const { +inline int FileDescriptorProto::_internal_weak_dependency_size() const { return weak_dependency_.size(); } +inline int FileDescriptorProto::weak_dependency_size() const { + return _internal_weak_dependency_size(); +} inline void FileDescriptorProto::clear_weak_dependency() { weak_dependency_.Clear(); } -inline ::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.weak_dependency) +inline ::PROTOBUF_NAMESPACE_ID::int32 FileDescriptorProto::_internal_weak_dependency(int index) const { return weak_dependency_.Get(index); } -inline void FileDescriptorProto::set_weak_dependency(int index, ::google::protobuf::int32 value) { +inline ::PROTOBUF_NAMESPACE_ID::int32 FileDescriptorProto::weak_dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.weak_dependency) + return _internal_weak_dependency(index); +} +inline void FileDescriptorProto::set_weak_dependency(int index, ::PROTOBUF_NAMESPACE_ID::int32 value) { weak_dependency_.Set(index, value); // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.weak_dependency) } -inline void FileDescriptorProto::add_weak_dependency(::google::protobuf::int32 value) { +inline void FileDescriptorProto::_internal_add_weak_dependency(::PROTOBUF_NAMESPACE_ID::int32 value) { weak_dependency_.Add(value); +} +inline void FileDescriptorProto::add_weak_dependency(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_add_weak_dependency(value); // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.weak_dependency) } -inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& +FileDescriptorProto::_internal_weak_dependency() const { + return weak_dependency_; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& FileDescriptorProto::weak_dependency() const { // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.weak_dependency) - return weak_dependency_; + return _internal_weak_dependency(); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* +FileDescriptorProto::_internal_mutable_weak_dependency() { + return &weak_dependency_; } -inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* FileDescriptorProto::mutable_weak_dependency() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.weak_dependency) - return &weak_dependency_; + return _internal_mutable_weak_dependency(); } // repeated .google.protobuf.DescriptorProto message_type = 4; -inline int FileDescriptorProto::message_type_size() const { +inline int FileDescriptorProto::_internal_message_type_size() const { return message_type_.size(); } +inline int FileDescriptorProto::message_type_size() const { + return _internal_message_type_size(); +} inline void FileDescriptorProto::clear_message_type() { message_type_.Clear(); } -inline const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.message_type) - return message_type_.Get(index); -} -inline ::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) { +inline PROTOBUF_NAMESPACE_ID::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.message_type) return message_type_.Mutable(index); } -inline ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() { - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type) - return message_type_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto >* FileDescriptorProto::mutable_message_type() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type) return &message_type_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& +inline const PROTOBUF_NAMESPACE_ID::DescriptorProto& FileDescriptorProto::_internal_message_type(int index) const { + return message_type_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::DescriptorProto& FileDescriptorProto::message_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.message_type) + return _internal_message_type(index); +} +inline PROTOBUF_NAMESPACE_ID::DescriptorProto* FileDescriptorProto::_internal_add_message_type() { + return message_type_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::DescriptorProto* FileDescriptorProto::add_message_type() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type) + return _internal_add_message_type(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto >& FileDescriptorProto::message_type() const { // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type) return message_type_; } // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; -inline int FileDescriptorProto::enum_type_size() const { +inline int FileDescriptorProto::_internal_enum_type_size() const { return enum_type_.size(); } +inline int FileDescriptorProto::enum_type_size() const { + return _internal_enum_type_size(); +} inline void FileDescriptorProto::clear_enum_type() { enum_type_.Clear(); } -inline const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.enum_type) - return enum_type_.Get(index); -} -inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) { +inline PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.enum_type) return enum_type_.Mutable(index); } -inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() { - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type) - return enum_type_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >* FileDescriptorProto::mutable_enum_type() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type) return &enum_type_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& +inline const PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& FileDescriptorProto::_internal_enum_type(int index) const { + return enum_type_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.enum_type) + return _internal_enum_type(index); +} +inline PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* FileDescriptorProto::_internal_add_enum_type() { + return enum_type_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* FileDescriptorProto::add_enum_type() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type) + return _internal_add_enum_type(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >& FileDescriptorProto::enum_type() const { // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type) return enum_type_; } // repeated .google.protobuf.ServiceDescriptorProto service = 6; -inline int FileDescriptorProto::service_size() const { +inline int FileDescriptorProto::_internal_service_size() const { return service_.size(); } +inline int FileDescriptorProto::service_size() const { + return _internal_service_size(); +} inline void FileDescriptorProto::clear_service() { service_.Clear(); } -inline const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.service) - return service_.Get(index); -} -inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) { +inline PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.service) return service_.Mutable(index); } -inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() { - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service) - return service_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto >* FileDescriptorProto::mutable_service() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service) return &service_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& +inline const PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto& FileDescriptorProto::_internal_service(int index) const { + return service_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto& FileDescriptorProto::service(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.service) + return _internal_service(index); +} +inline PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* FileDescriptorProto::_internal_add_service() { + return service_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* FileDescriptorProto::add_service() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service) + return _internal_add_service(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto >& FileDescriptorProto::service() const { // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service) return service_; } // repeated .google.protobuf.FieldDescriptorProto extension = 7; -inline int FileDescriptorProto::extension_size() const { +inline int FileDescriptorProto::_internal_extension_size() const { return extension_.size(); } +inline int FileDescriptorProto::extension_size() const { + return _internal_extension_size(); +} inline void FileDescriptorProto::clear_extension() { extension_.Clear(); } -inline const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.extension) - return extension_.Get(index); -} -inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) { +inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.extension) return extension_.Mutable(index); } -inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() { - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension) - return extension_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >* FileDescriptorProto::mutable_extension() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension) return &extension_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +inline const PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& FileDescriptorProto::_internal_extension(int index) const { + return extension_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& FileDescriptorProto::extension(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.extension) + return _internal_extension(index); +} +inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* FileDescriptorProto::_internal_add_extension() { + return extension_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* FileDescriptorProto::add_extension() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension) + return _internal_add_extension(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >& FileDescriptorProto::extension() const { // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension) return extension_; } // optional .google.protobuf.FileOptions options = 8; -inline bool FileDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000008u) != 0; +inline bool FileDescriptorProto::_internal_has_options() const { + bool value = (_has_bits_[0] & 0x00000008u) != 0; + PROTOBUF_ASSUME(!value || options_ != nullptr); + return value; } -inline void FileDescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000008u; +inline bool FileDescriptorProto::has_options() const { + return _internal_has_options(); } -inline void FileDescriptorProto::clear_has_options() { +inline void FileDescriptorProto::clear_options() { + if (options_ != nullptr) options_->Clear(); _has_bits_[0] &= ~0x00000008u; } -inline void FileDescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear(); - clear_has_options(); +inline const PROTOBUF_NAMESPACE_ID::FileOptions& FileDescriptorProto::_internal_options() const { + const PROTOBUF_NAMESPACE_ID::FileOptions* p = options_; + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_FileOptions_default_instance_); } -inline const ::google::protobuf::FileOptions& FileDescriptorProto::options() const { - const ::google::protobuf::FileOptions* p = options_; +inline const PROTOBUF_NAMESPACE_ID::FileOptions& FileDescriptorProto::options() const { // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_FileOptions_default_instance_); + return _internal_options(); } -inline ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::FileOptions; +inline void FileDescriptorProto::unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::FileOptions* options) { + if (GetArena() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_); } - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options) - return options_; + options_ = options; + if (options) { + _has_bits_[0] |= 0x00000008u; + } else { + _has_bits_[0] &= ~0x00000008u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.options) +} +inline PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::release_options() { + _has_bits_[0] &= ~0x00000008u; + PROTOBUF_NAMESPACE_ID::FileOptions* temp = options_; + options_ = nullptr; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + return temp; } -inline ::google::protobuf::FileOptions* FileDescriptorProto::release_options() { +inline PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::unsafe_arena_release_options() { // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.options) - clear_has_options(); - ::google::protobuf::FileOptions* temp = options_; - options_ = NULL; + _has_bits_[0] &= ~0x00000008u; + PROTOBUF_NAMESPACE_ID::FileOptions* temp = options_; + options_ = nullptr; return temp; } -inline void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) { - delete options_; - options_ = options; +inline PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::_internal_mutable_options() { + _has_bits_[0] |= 0x00000008u; + if (options_ == nullptr) { + auto* p = CreateMaybeMessage(GetArena()); + options_ = p; + } + return options_; +} +inline PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::mutable_options() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options) + return _internal_mutable_options(); +} +inline void FileDescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::FileOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + if (message_arena == nullptr) { + delete options_; + } if (options) { - set_has_options(); + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _has_bits_[0] |= 0x00000008u; } else { - clear_has_options(); + _has_bits_[0] &= ~0x00000008u; } + options_ = options; // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options) } // optional .google.protobuf.SourceCodeInfo source_code_info = 9; -inline bool FileDescriptorProto::has_source_code_info() const { - return (_has_bits_[0] & 0x00000010u) != 0; +inline bool FileDescriptorProto::_internal_has_source_code_info() const { + bool value = (_has_bits_[0] & 0x00000010u) != 0; + PROTOBUF_ASSUME(!value || source_code_info_ != nullptr); + return value; } -inline void FileDescriptorProto::set_has_source_code_info() { - _has_bits_[0] |= 0x00000010u; +inline bool FileDescriptorProto::has_source_code_info() const { + return _internal_has_source_code_info(); } -inline void FileDescriptorProto::clear_has_source_code_info() { +inline void FileDescriptorProto::clear_source_code_info() { + if (source_code_info_ != nullptr) source_code_info_->Clear(); _has_bits_[0] &= ~0x00000010u; } -inline void FileDescriptorProto::clear_source_code_info() { - if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear(); - clear_has_source_code_info(); +inline const PROTOBUF_NAMESPACE_ID::SourceCodeInfo& FileDescriptorProto::_internal_source_code_info() const { + const PROTOBUF_NAMESPACE_ID::SourceCodeInfo* p = source_code_info_; + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_default_instance_); } -inline const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const { - const ::google::protobuf::SourceCodeInfo* p = source_code_info_; +inline const PROTOBUF_NAMESPACE_ID::SourceCodeInfo& FileDescriptorProto::source_code_info() const { // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_SourceCodeInfo_default_instance_); + return _internal_source_code_info(); } -inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() { - set_has_source_code_info(); - if (source_code_info_ == NULL) { - source_code_info_ = new ::google::protobuf::SourceCodeInfo; +inline void FileDescriptorProto::unsafe_arena_set_allocated_source_code_info( + PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info) { + if (GetArena() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_code_info_); } - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info) - return source_code_info_; + source_code_info_ = source_code_info; + if (source_code_info) { + _has_bits_[0] |= 0x00000010u; + } else { + _has_bits_[0] &= ~0x00000010u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.source_code_info) +} +inline PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::release_source_code_info() { + _has_bits_[0] &= ~0x00000010u; + PROTOBUF_NAMESPACE_ID::SourceCodeInfo* temp = source_code_info_; + source_code_info_ = nullptr; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + return temp; } -inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() { +inline PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::unsafe_arena_release_source_code_info() { // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.source_code_info) - clear_has_source_code_info(); - ::google::protobuf::SourceCodeInfo* temp = source_code_info_; - source_code_info_ = NULL; + _has_bits_[0] &= ~0x00000010u; + PROTOBUF_NAMESPACE_ID::SourceCodeInfo* temp = source_code_info_; + source_code_info_ = nullptr; return temp; } -inline void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) { - delete source_code_info_; - source_code_info_ = source_code_info; +inline PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::_internal_mutable_source_code_info() { + _has_bits_[0] |= 0x00000010u; + if (source_code_info_ == nullptr) { + auto* p = CreateMaybeMessage(GetArena()); + source_code_info_ = p; + } + return source_code_info_; +} +inline PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info) + return _internal_mutable_source_code_info(); +} +inline void FileDescriptorProto::set_allocated_source_code_info(PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + if (message_arena == nullptr) { + delete source_code_info_; + } if (source_code_info) { - set_has_source_code_info(); + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(source_code_info); + if (message_arena != submessage_arena) { + source_code_info = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, source_code_info, submessage_arena); + } + _has_bits_[0] |= 0x00000010u; } else { - clear_has_source_code_info(); + _has_bits_[0] &= ~0x00000010u; } + source_code_info_ = source_code_info; // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info) } // optional string syntax = 12; -inline bool FileDescriptorProto::has_syntax() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -inline void FileDescriptorProto::set_has_syntax() { - _has_bits_[0] |= 0x00000004u; +inline bool FileDescriptorProto::_internal_has_syntax() const { + bool value = (_has_bits_[0] & 0x00000004u) != 0; + return value; } -inline void FileDescriptorProto::clear_has_syntax() { - _has_bits_[0] &= ~0x00000004u; +inline bool FileDescriptorProto::has_syntax() const { + return _internal_has_syntax(); } inline void FileDescriptorProto::clear_syntax() { - syntax_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_syntax(); + syntax_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000004u; } -inline const ::std::string& FileDescriptorProto::syntax() const { +inline const std::string& FileDescriptorProto::syntax() const { // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.syntax) - return syntax_.GetNoArena(); + return _internal_syntax(); } -inline void FileDescriptorProto::set_syntax(const ::std::string& value) { - set_has_syntax(); - syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FileDescriptorProto::set_syntax(const std::string& value) { + _internal_set_syntax(value); // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.syntax) } -#if LANG_CXX11 -inline void FileDescriptorProto::set_syntax(::std::string&& value) { - set_has_syntax(); - syntax_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FileDescriptorProto::mutable_syntax() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.syntax) + return _internal_mutable_syntax(); +} +inline const std::string& FileDescriptorProto::_internal_syntax() const { + return syntax_.Get(); +} +inline void FileDescriptorProto::_internal_set_syntax(const std::string& value) { + _has_bits_[0] |= 0x00000004u; + syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FileDescriptorProto::set_syntax(std::string&& value) { + _has_bits_[0] |= 0x00000004u; + syntax_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.syntax) } -#endif inline void FileDescriptorProto::set_syntax(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_syntax(); - syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000004u; + syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.syntax) } -inline void FileDescriptorProto::set_syntax(const char* value, size_t size) { - set_has_syntax(); - syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FileDescriptorProto::set_syntax(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000004u; + syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.syntax) } -inline ::std::string* FileDescriptorProto::mutable_syntax() { - set_has_syntax(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.syntax) - return syntax_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FileDescriptorProto::_internal_mutable_syntax() { + _has_bits_[0] |= 0x00000004u; + return syntax_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FileDescriptorProto::release_syntax() { +inline std::string* FileDescriptorProto::release_syntax() { // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.syntax) - clear_has_syntax(); - return syntax_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_syntax()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000004u; + return syntax_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FileDescriptorProto::set_allocated_syntax(::std::string* syntax) { - if (syntax != NULL) { - set_has_syntax(); +inline void FileDescriptorProto::set_allocated_syntax(std::string* syntax) { + if (syntax != nullptr) { + _has_bits_[0] |= 0x00000004u; } else { - clear_has_syntax(); + _has_bits_[0] &= ~0x00000004u; } - syntax_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), syntax); + syntax_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), syntax, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax) } @@ -5216,148 +7355,201 @@ inline void FileDescriptorProto::set_allocated_syntax(::std::string* syntax) { // DescriptorProto_ExtensionRange // optional int32 start = 1; -inline bool DescriptorProto_ExtensionRange::has_start() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -inline void DescriptorProto_ExtensionRange::set_has_start() { - _has_bits_[0] |= 0x00000002u; +inline bool DescriptorProto_ExtensionRange::_internal_has_start() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void DescriptorProto_ExtensionRange::clear_has_start() { - _has_bits_[0] &= ~0x00000002u; +inline bool DescriptorProto_ExtensionRange::has_start() const { + return _internal_has_start(); } inline void DescriptorProto_ExtensionRange::clear_start() { start_ = 0; - clear_has_start(); + _has_bits_[0] &= ~0x00000002u; } -inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.start) +inline ::PROTOBUF_NAMESPACE_ID::int32 DescriptorProto_ExtensionRange::_internal_start() const { return start_; } -inline void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) { - set_has_start(); +inline ::PROTOBUF_NAMESPACE_ID::int32 DescriptorProto_ExtensionRange::start() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.start) + return _internal_start(); +} +inline void DescriptorProto_ExtensionRange::_internal_set_start(::PROTOBUF_NAMESPACE_ID::int32 value) { + _has_bits_[0] |= 0x00000002u; start_ = value; +} +inline void DescriptorProto_ExtensionRange::set_start(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_start(value); // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.start) } // optional int32 end = 2; -inline bool DescriptorProto_ExtensionRange::has_end() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -inline void DescriptorProto_ExtensionRange::set_has_end() { - _has_bits_[0] |= 0x00000004u; +inline bool DescriptorProto_ExtensionRange::_internal_has_end() const { + bool value = (_has_bits_[0] & 0x00000004u) != 0; + return value; } -inline void DescriptorProto_ExtensionRange::clear_has_end() { - _has_bits_[0] &= ~0x00000004u; +inline bool DescriptorProto_ExtensionRange::has_end() const { + return _internal_has_end(); } inline void DescriptorProto_ExtensionRange::clear_end() { end_ = 0; - clear_has_end(); + _has_bits_[0] &= ~0x00000004u; } -inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.end) +inline ::PROTOBUF_NAMESPACE_ID::int32 DescriptorProto_ExtensionRange::_internal_end() const { return end_; } -inline void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) { - set_has_end(); +inline ::PROTOBUF_NAMESPACE_ID::int32 DescriptorProto_ExtensionRange::end() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.end) + return _internal_end(); +} +inline void DescriptorProto_ExtensionRange::_internal_set_end(::PROTOBUF_NAMESPACE_ID::int32 value) { + _has_bits_[0] |= 0x00000004u; end_ = value; +} +inline void DescriptorProto_ExtensionRange::set_end(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_end(value); // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end) } // optional .google.protobuf.ExtensionRangeOptions options = 3; -inline bool DescriptorProto_ExtensionRange::has_options() const { - return (_has_bits_[0] & 0x00000001u) != 0; +inline bool DescriptorProto_ExtensionRange::_internal_has_options() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + PROTOBUF_ASSUME(!value || options_ != nullptr); + return value; } -inline void DescriptorProto_ExtensionRange::set_has_options() { - _has_bits_[0] |= 0x00000001u; +inline bool DescriptorProto_ExtensionRange::has_options() const { + return _internal_has_options(); } -inline void DescriptorProto_ExtensionRange::clear_has_options() { +inline void DescriptorProto_ExtensionRange::clear_options() { + if (options_ != nullptr) options_->Clear(); _has_bits_[0] &= ~0x00000001u; } -inline void DescriptorProto_ExtensionRange::clear_options() { - if (options_ != NULL) options_->::google::protobuf::ExtensionRangeOptions::Clear(); - clear_has_options(); +inline const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& DescriptorProto_ExtensionRange::_internal_options() const { + const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* p = options_; + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_ExtensionRangeOptions_default_instance_); } -inline const ::google::protobuf::ExtensionRangeOptions& DescriptorProto_ExtensionRange::options() const { - const ::google::protobuf::ExtensionRangeOptions* p = options_; +inline const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& DescriptorProto_ExtensionRange::options() const { // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_ExtensionRangeOptions_default_instance_); + return _internal_options(); } -inline ::google::protobuf::ExtensionRangeOptions* DescriptorProto_ExtensionRange::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::ExtensionRangeOptions; +inline void DescriptorProto_ExtensionRange::unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options) { + if (GetArena() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_); } - // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.ExtensionRange.options) - return options_; -} -inline ::google::protobuf::ExtensionRangeOptions* DescriptorProto_ExtensionRange::release_options() { - // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.ExtensionRange.options) - clear_has_options(); - ::google::protobuf::ExtensionRangeOptions* temp = options_; - options_ = NULL; - return temp; -} -inline void DescriptorProto_ExtensionRange::set_allocated_options(::google::protobuf::ExtensionRangeOptions* options) { - delete options_; options_ = options; if (options) { - set_has_options(); + _has_bits_[0] |= 0x00000001u; } else { - clear_has_options(); + _has_bits_[0] &= ~0x00000001u; } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.ExtensionRange.options) -} - -// ------------------------------------------------------------------- - -// DescriptorProto_ReservedRange - -// optional int32 start = 1; -inline bool DescriptorProto_ReservedRange::has_start() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void DescriptorProto_ReservedRange::set_has_start() { - _has_bits_[0] |= 0x00000001u; + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.DescriptorProto.ExtensionRange.options) } -inline void DescriptorProto_ReservedRange::clear_has_start() { +inline PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* DescriptorProto_ExtensionRange::release_options() { _has_bits_[0] &= ~0x00000001u; + PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* temp = options_; + options_ = nullptr; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + return temp; } -inline void DescriptorProto_ReservedRange::clear_start() { +inline PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* DescriptorProto_ExtensionRange::unsafe_arena_release_options() { + // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.ExtensionRange.options) + _has_bits_[0] &= ~0x00000001u; + PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* temp = options_; + options_ = nullptr; + return temp; +} +inline PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* DescriptorProto_ExtensionRange::_internal_mutable_options() { + _has_bits_[0] |= 0x00000001u; + if (options_ == nullptr) { + auto* p = CreateMaybeMessage(GetArena()); + options_ = p; + } + return options_; +} +inline PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* DescriptorProto_ExtensionRange::mutable_options() { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.ExtensionRange.options) + return _internal_mutable_options(); +} +inline void DescriptorProto_ExtensionRange::set_allocated_options(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + if (message_arena == nullptr) { + delete options_; + } + if (options) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _has_bits_[0] |= 0x00000001u; + } else { + _has_bits_[0] &= ~0x00000001u; + } + options_ = options; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.ExtensionRange.options) +} + +// ------------------------------------------------------------------- + +// DescriptorProto_ReservedRange + +// optional int32 start = 1; +inline bool DescriptorProto_ReservedRange::_internal_has_start() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool DescriptorProto_ReservedRange::has_start() const { + return _internal_has_start(); +} +inline void DescriptorProto_ReservedRange::clear_start() { start_ = 0; - clear_has_start(); + _has_bits_[0] &= ~0x00000001u; } -inline ::google::protobuf::int32 DescriptorProto_ReservedRange::start() const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.start) +inline ::PROTOBUF_NAMESPACE_ID::int32 DescriptorProto_ReservedRange::_internal_start() const { return start_; } -inline void DescriptorProto_ReservedRange::set_start(::google::protobuf::int32 value) { - set_has_start(); +inline ::PROTOBUF_NAMESPACE_ID::int32 DescriptorProto_ReservedRange::start() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.start) + return _internal_start(); +} +inline void DescriptorProto_ReservedRange::_internal_set_start(::PROTOBUF_NAMESPACE_ID::int32 value) { + _has_bits_[0] |= 0x00000001u; start_ = value; +} +inline void DescriptorProto_ReservedRange::set_start(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_start(value); // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.start) } // optional int32 end = 2; -inline bool DescriptorProto_ReservedRange::has_end() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -inline void DescriptorProto_ReservedRange::set_has_end() { - _has_bits_[0] |= 0x00000002u; +inline bool DescriptorProto_ReservedRange::_internal_has_end() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void DescriptorProto_ReservedRange::clear_has_end() { - _has_bits_[0] &= ~0x00000002u; +inline bool DescriptorProto_ReservedRange::has_end() const { + return _internal_has_end(); } inline void DescriptorProto_ReservedRange::clear_end() { end_ = 0; - clear_has_end(); + _has_bits_[0] &= ~0x00000002u; } -inline ::google::protobuf::int32 DescriptorProto_ReservedRange::end() const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.end) +inline ::PROTOBUF_NAMESPACE_ID::int32 DescriptorProto_ReservedRange::_internal_end() const { return end_; } -inline void DescriptorProto_ReservedRange::set_end(::google::protobuf::int32 value) { - set_has_end(); +inline ::PROTOBUF_NAMESPACE_ID::int32 DescriptorProto_ReservedRange::end() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.end) + return _internal_end(); +} +inline void DescriptorProto_ReservedRange::_internal_set_end(::PROTOBUF_NAMESPACE_ID::int32 value) { + _has_bits_[0] |= 0x00000002u; end_ = value; +} +inline void DescriptorProto_ReservedRange::set_end(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_end(value); // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.end) } @@ -5366,351 +7558,469 @@ inline void DescriptorProto_ReservedRange::set_end(::google::protobuf::int32 val // DescriptorProto // optional string name = 1; -inline bool DescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void DescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; +inline bool DescriptorProto::_internal_has_name() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void DescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; +inline bool DescriptorProto::has_name() const { + return _internal_has_name(); } inline void DescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); + name_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& DescriptorProto::name() const { +inline const std::string& DescriptorProto::name() const { // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name) - return name_.GetNoArena(); + return _internal_name(); } -inline void DescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void DescriptorProto::set_name(const std::string& value) { + _internal_set_name(value); // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.name) } -#if LANG_CXX11 -inline void DescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* DescriptorProto::mutable_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name) + return _internal_mutable_name(); +} +inline const std::string& DescriptorProto::_internal_name() const { + return name_.Get(); +} +inline void DescriptorProto::_internal_set_name(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void DescriptorProto::set_name(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.DescriptorProto.name) } -#endif inline void DescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name) } -inline void DescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void DescriptorProto::set_name(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name) } -inline ::std::string* DescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* DescriptorProto::_internal_mutable_name() { + _has_bits_[0] |= 0x00000001u; + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* DescriptorProto::release_name() { +inline std::string* DescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_name()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void DescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); +inline void DescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_name(); + _has_bits_[0] &= ~0x00000001u; } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name) } // repeated .google.protobuf.FieldDescriptorProto field = 2; -inline int DescriptorProto::field_size() const { +inline int DescriptorProto::_internal_field_size() const { return field_.size(); } +inline int DescriptorProto::field_size() const { + return _internal_field_size(); +} inline void DescriptorProto::clear_field() { field_.Clear(); } -inline const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.field) - return field_.Get(index); -} -inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(int index) { +inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* DescriptorProto::mutable_field(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.field) return field_.Mutable(index); } -inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() { - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field) - return field_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >* DescriptorProto::mutable_field() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field) return &field_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +inline const PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& DescriptorProto::_internal_field(int index) const { + return field_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& DescriptorProto::field(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.field) + return _internal_field(index); +} +inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* DescriptorProto::_internal_add_field() { + return field_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* DescriptorProto::add_field() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field) + return _internal_add_field(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >& DescriptorProto::field() const { // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field) return field_; } // repeated .google.protobuf.FieldDescriptorProto extension = 6; -inline int DescriptorProto::extension_size() const { +inline int DescriptorProto::_internal_extension_size() const { return extension_.size(); } +inline int DescriptorProto::extension_size() const { + return _internal_extension_size(); +} inline void DescriptorProto::clear_extension() { extension_.Clear(); } -inline const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension) - return extension_.Get(index); -} -inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) { +inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension) return extension_.Mutable(index); } -inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() { - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension) - return extension_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >* DescriptorProto::mutable_extension() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension) return &extension_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +inline const PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& DescriptorProto::_internal_extension(int index) const { + return extension_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& DescriptorProto::extension(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension) + return _internal_extension(index); +} +inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* DescriptorProto::_internal_add_extension() { + return extension_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* DescriptorProto::add_extension() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension) + return _internal_add_extension(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >& DescriptorProto::extension() const { // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension) return extension_; } // repeated .google.protobuf.DescriptorProto nested_type = 3; -inline int DescriptorProto::nested_type_size() const { +inline int DescriptorProto::_internal_nested_type_size() const { return nested_type_.size(); } +inline int DescriptorProto::nested_type_size() const { + return _internal_nested_type_size(); +} inline void DescriptorProto::clear_nested_type() { nested_type_.Clear(); } -inline const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.nested_type) - return nested_type_.Get(index); -} -inline ::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type(int index) { +inline PROTOBUF_NAMESPACE_ID::DescriptorProto* DescriptorProto::mutable_nested_type(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.nested_type) return nested_type_.Mutable(index); } -inline ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() { - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type) - return nested_type_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto >* DescriptorProto::mutable_nested_type() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type) return &nested_type_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& +inline const PROTOBUF_NAMESPACE_ID::DescriptorProto& DescriptorProto::_internal_nested_type(int index) const { + return nested_type_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::DescriptorProto& DescriptorProto::nested_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.nested_type) + return _internal_nested_type(index); +} +inline PROTOBUF_NAMESPACE_ID::DescriptorProto* DescriptorProto::_internal_add_nested_type() { + return nested_type_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::DescriptorProto* DescriptorProto::add_nested_type() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type) + return _internal_add_nested_type(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto >& DescriptorProto::nested_type() const { // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type) return nested_type_; } // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; -inline int DescriptorProto::enum_type_size() const { +inline int DescriptorProto::_internal_enum_type_size() const { return enum_type_.size(); } +inline int DescriptorProto::enum_type_size() const { + return _internal_enum_type_size(); +} inline void DescriptorProto::clear_enum_type() { enum_type_.Clear(); } -inline const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.enum_type) - return enum_type_.Get(index); -} -inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) { +inline PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.enum_type) return enum_type_.Mutable(index); } -inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() { - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type) - return enum_type_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >* DescriptorProto::mutable_enum_type() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type) return &enum_type_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& +inline const PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& DescriptorProto::_internal_enum_type(int index) const { + return enum_type_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& DescriptorProto::enum_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.enum_type) + return _internal_enum_type(index); +} +inline PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* DescriptorProto::_internal_add_enum_type() { + return enum_type_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* DescriptorProto::add_enum_type() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type) + return _internal_add_enum_type(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >& DescriptorProto::enum_type() const { // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type) return enum_type_; } // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; -inline int DescriptorProto::extension_range_size() const { +inline int DescriptorProto::_internal_extension_range_size() const { return extension_range_.size(); } +inline int DescriptorProto::extension_range_size() const { + return _internal_extension_range_size(); +} inline void DescriptorProto::clear_extension_range() { extension_range_.Clear(); } -inline const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension_range) - return extension_range_.Get(index); -} -inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) { +inline PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension_range) return extension_range_.Mutable(index); } -inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() { - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range) - return extension_range_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange >* DescriptorProto::mutable_extension_range() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range) return &extension_range_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& +inline const PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange& DescriptorProto::_internal_extension_range(int index) const { + return extension_range_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension_range) + return _internal_extension_range(index); +} +inline PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* DescriptorProto::_internal_add_extension_range() { + return extension_range_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range) + return _internal_add_extension_range(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange >& DescriptorProto::extension_range() const { // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range) return extension_range_; } // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; -inline int DescriptorProto::oneof_decl_size() const { +inline int DescriptorProto::_internal_oneof_decl_size() const { return oneof_decl_.size(); } +inline int DescriptorProto::oneof_decl_size() const { + return _internal_oneof_decl_size(); +} inline void DescriptorProto::clear_oneof_decl() { oneof_decl_.Clear(); } -inline const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.oneof_decl) - return oneof_decl_.Get(index); -} -inline ::google::protobuf::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) { +inline PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.oneof_decl) return oneof_decl_.Mutable(index); } -inline ::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl() { - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl) - return oneof_decl_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::OneofDescriptorProto >* DescriptorProto::mutable_oneof_decl() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl) return &oneof_decl_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& +inline const PROTOBUF_NAMESPACE_ID::OneofDescriptorProto& DescriptorProto::_internal_oneof_decl(int index) const { + return oneof_decl_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.oneof_decl) + return _internal_oneof_decl(index); +} +inline PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* DescriptorProto::_internal_add_oneof_decl() { + return oneof_decl_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* DescriptorProto::add_oneof_decl() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl) + return _internal_add_oneof_decl(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::OneofDescriptorProto >& DescriptorProto::oneof_decl() const { // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl) return oneof_decl_; } // optional .google.protobuf.MessageOptions options = 7; -inline bool DescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000002u) != 0; +inline bool DescriptorProto::_internal_has_options() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + PROTOBUF_ASSUME(!value || options_ != nullptr); + return value; } -inline void DescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000002u; +inline bool DescriptorProto::has_options() const { + return _internal_has_options(); } -inline void DescriptorProto::clear_has_options() { +inline void DescriptorProto::clear_options() { + if (options_ != nullptr) options_->Clear(); _has_bits_[0] &= ~0x00000002u; } -inline void DescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear(); - clear_has_options(); +inline const PROTOBUF_NAMESPACE_ID::MessageOptions& DescriptorProto::_internal_options() const { + const PROTOBUF_NAMESPACE_ID::MessageOptions* p = options_; + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_MessageOptions_default_instance_); } -inline const ::google::protobuf::MessageOptions& DescriptorProto::options() const { - const ::google::protobuf::MessageOptions* p = options_; +inline const PROTOBUF_NAMESPACE_ID::MessageOptions& DescriptorProto::options() const { // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_MessageOptions_default_instance_); + return _internal_options(); } -inline ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::MessageOptions; +inline void DescriptorProto::unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::MessageOptions* options) { + if (GetArena() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_); } - // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options) - return options_; + options_ = options; + if (options) { + _has_bits_[0] |= 0x00000002u; + } else { + _has_bits_[0] &= ~0x00000002u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.DescriptorProto.options) +} +inline PROTOBUF_NAMESPACE_ID::MessageOptions* DescriptorProto::release_options() { + _has_bits_[0] &= ~0x00000002u; + PROTOBUF_NAMESPACE_ID::MessageOptions* temp = options_; + options_ = nullptr; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + return temp; } -inline ::google::protobuf::MessageOptions* DescriptorProto::release_options() { +inline PROTOBUF_NAMESPACE_ID::MessageOptions* DescriptorProto::unsafe_arena_release_options() { // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.options) - clear_has_options(); - ::google::protobuf::MessageOptions* temp = options_; - options_ = NULL; + _has_bits_[0] &= ~0x00000002u; + PROTOBUF_NAMESPACE_ID::MessageOptions* temp = options_; + options_ = nullptr; return temp; } -inline void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) { - delete options_; - options_ = options; +inline PROTOBUF_NAMESPACE_ID::MessageOptions* DescriptorProto::_internal_mutable_options() { + _has_bits_[0] |= 0x00000002u; + if (options_ == nullptr) { + auto* p = CreateMaybeMessage(GetArena()); + options_ = p; + } + return options_; +} +inline PROTOBUF_NAMESPACE_ID::MessageOptions* DescriptorProto::mutable_options() { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options) + return _internal_mutable_options(); +} +inline void DescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::MessageOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + if (message_arena == nullptr) { + delete options_; + } if (options) { - set_has_options(); + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _has_bits_[0] |= 0x00000002u; } else { - clear_has_options(); + _has_bits_[0] &= ~0x00000002u; } + options_ = options; // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options) } // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; -inline int DescriptorProto::reserved_range_size() const { +inline int DescriptorProto::_internal_reserved_range_size() const { return reserved_range_.size(); } +inline int DescriptorProto::reserved_range_size() const { + return _internal_reserved_range_size(); +} inline void DescriptorProto::clear_reserved_range() { reserved_range_.Clear(); } -inline const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_range) - return reserved_range_.Get(index); -} -inline ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) { +inline PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_range) return reserved_range_.Mutable(index); } -inline ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() { - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range) - return reserved_range_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange >* DescriptorProto::mutable_reserved_range() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range) return &reserved_range_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >& +inline const PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange& DescriptorProto::_internal_reserved_range(int index) const { + return reserved_range_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_range) + return _internal_reserved_range(index); +} +inline PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* DescriptorProto::_internal_add_reserved_range() { + return reserved_range_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range) + return _internal_add_reserved_range(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange >& DescriptorProto::reserved_range() const { // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range) return reserved_range_; } // repeated string reserved_name = 10; -inline int DescriptorProto::reserved_name_size() const { +inline int DescriptorProto::_internal_reserved_name_size() const { return reserved_name_.size(); } +inline int DescriptorProto::reserved_name_size() const { + return _internal_reserved_name_size(); +} inline void DescriptorProto::clear_reserved_name() { reserved_name_.Clear(); } -inline const ::std::string& DescriptorProto::reserved_name(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_name) +inline std::string* DescriptorProto::add_reserved_name() { + // @@protoc_insertion_point(field_add_mutable:google.protobuf.DescriptorProto.reserved_name) + return _internal_add_reserved_name(); +} +inline const std::string& DescriptorProto::_internal_reserved_name(int index) const { return reserved_name_.Get(index); } -inline ::std::string* DescriptorProto::mutable_reserved_name(int index) { +inline const std::string& DescriptorProto::reserved_name(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_name) + return _internal_reserved_name(index); +} +inline std::string* DescriptorProto::mutable_reserved_name(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_name) return reserved_name_.Mutable(index); } -inline void DescriptorProto::set_reserved_name(int index, const ::std::string& value) { +inline void DescriptorProto::set_reserved_name(int index, const std::string& value) { // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name) reserved_name_.Mutable(index)->assign(value); } -#if LANG_CXX11 -inline void DescriptorProto::set_reserved_name(int index, ::std::string&& value) { +inline void DescriptorProto::set_reserved_name(int index, std::string&& value) { // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name) reserved_name_.Mutable(index)->assign(std::move(value)); } -#endif inline void DescriptorProto::set_reserved_name(int index, const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); reserved_name_.Mutable(index)->assign(value); // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.reserved_name) } @@ -5719,22 +8029,19 @@ inline void DescriptorProto::set_reserved_name(int index, const char* value, siz reinterpret_cast(value), size); // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name) } -inline ::std::string* DescriptorProto::add_reserved_name() { - // @@protoc_insertion_point(field_add_mutable:google.protobuf.DescriptorProto.reserved_name) +inline std::string* DescriptorProto::_internal_add_reserved_name() { return reserved_name_.Add(); } -inline void DescriptorProto::add_reserved_name(const ::std::string& value) { +inline void DescriptorProto::add_reserved_name(const std::string& value) { reserved_name_.Add()->assign(value); // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name) } -#if LANG_CXX11 -inline void DescriptorProto::add_reserved_name(::std::string&& value) { +inline void DescriptorProto::add_reserved_name(std::string&& value) { reserved_name_.Add(std::move(value)); // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name) } -#endif inline void DescriptorProto::add_reserved_name(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); reserved_name_.Add()->assign(value); // @@protoc_insertion_point(field_add_char:google.protobuf.DescriptorProto.reserved_name) } @@ -5742,12 +8049,12 @@ inline void DescriptorProto::add_reserved_name(const char* value, size_t size) { reserved_name_.Add()->assign(reinterpret_cast(value), size); // @@protoc_insertion_point(field_add_pointer:google.protobuf.DescriptorProto.reserved_name) } -inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField& DescriptorProto::reserved_name() const { // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_name) return reserved_name_; } -inline ::google::protobuf::RepeatedPtrField< ::std::string>* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField* DescriptorProto::mutable_reserved_name() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_name) return &reserved_name_; @@ -5758,30 +8065,39 @@ DescriptorProto::mutable_reserved_name() { // ExtensionRangeOptions // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -inline int ExtensionRangeOptions::uninterpreted_option_size() const { +inline int ExtensionRangeOptions::_internal_uninterpreted_option_size() const { return uninterpreted_option_.size(); } +inline int ExtensionRangeOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} inline void ExtensionRangeOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } -inline const ::google::protobuf::UninterpretedOption& ExtensionRangeOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.ExtensionRangeOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -inline ::google::protobuf::UninterpretedOption* ExtensionRangeOptions::mutable_uninterpreted_option(int index) { +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* ExtensionRangeOptions::mutable_uninterpreted_option(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.ExtensionRangeOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } -inline ::google::protobuf::UninterpretedOption* ExtensionRangeOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.ExtensionRangeOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* ExtensionRangeOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.ExtensionRangeOptions.uninterpreted_option) return &uninterpreted_option_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& ExtensionRangeOptions::_internal_uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& ExtensionRangeOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ExtensionRangeOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* ExtensionRangeOptions::_internal_add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* ExtensionRangeOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.ExtensionRangeOptions.uninterpreted_option) + return _internal_add_uninterpreted_option(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& ExtensionRangeOptions::uninterpreted_option() const { // @@protoc_insertion_point(field_list:google.protobuf.ExtensionRangeOptions.uninterpreted_option) return uninterpreted_option_; @@ -5792,718 +8108,1125 @@ ExtensionRangeOptions::uninterpreted_option() const { // FieldDescriptorProto // optional string name = 1; -inline bool FieldDescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void FieldDescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; +inline bool FieldDescriptorProto::_internal_has_name() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void FieldDescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; +inline bool FieldDescriptorProto::has_name() const { + return _internal_has_name(); } inline void FieldDescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); + name_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& FieldDescriptorProto::name() const { +inline const std::string& FieldDescriptorProto::name() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name) - return name_.GetNoArena(); + return _internal_name(); } -inline void FieldDescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FieldDescriptorProto::set_name(const std::string& value) { + _internal_set_name(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.name) } -#if LANG_CXX11 -inline void FieldDescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FieldDescriptorProto::mutable_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name) + return _internal_mutable_name(); +} +inline const std::string& FieldDescriptorProto::_internal_name() const { + return name_.Get(); +} +inline void FieldDescriptorProto::_internal_set_name(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FieldDescriptorProto::set_name(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.name) } -#endif inline void FieldDescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name) } -inline void FieldDescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FieldDescriptorProto::set_name(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name) } -inline ::std::string* FieldDescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FieldDescriptorProto::_internal_mutable_name() { + _has_bits_[0] |= 0x00000001u; + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FieldDescriptorProto::release_name() { +inline std::string* FieldDescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_name()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FieldDescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); +inline void FieldDescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_name(); + _has_bits_[0] &= ~0x00000001u; } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name) } // optional int32 number = 3; -inline bool FieldDescriptorProto::has_number() const { - return (_has_bits_[0] & 0x00000040u) != 0; -} -inline void FieldDescriptorProto::set_has_number() { - _has_bits_[0] |= 0x00000040u; +inline bool FieldDescriptorProto::_internal_has_number() const { + bool value = (_has_bits_[0] & 0x00000040u) != 0; + return value; } -inline void FieldDescriptorProto::clear_has_number() { - _has_bits_[0] &= ~0x00000040u; +inline bool FieldDescriptorProto::has_number() const { + return _internal_has_number(); } inline void FieldDescriptorProto::clear_number() { number_ = 0; - clear_has_number(); + _has_bits_[0] &= ~0x00000040u; } -inline ::google::protobuf::int32 FieldDescriptorProto::number() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.number) +inline ::PROTOBUF_NAMESPACE_ID::int32 FieldDescriptorProto::_internal_number() const { return number_; } -inline void FieldDescriptorProto::set_number(::google::protobuf::int32 value) { - set_has_number(); +inline ::PROTOBUF_NAMESPACE_ID::int32 FieldDescriptorProto::number() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.number) + return _internal_number(); +} +inline void FieldDescriptorProto::_internal_set_number(::PROTOBUF_NAMESPACE_ID::int32 value) { + _has_bits_[0] |= 0x00000040u; number_ = value; +} +inline void FieldDescriptorProto::set_number(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_number(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.number) } // optional .google.protobuf.FieldDescriptorProto.Label label = 4; -inline bool FieldDescriptorProto::has_label() const { - return (_has_bits_[0] & 0x00000100u) != 0; -} -inline void FieldDescriptorProto::set_has_label() { - _has_bits_[0] |= 0x00000100u; +inline bool FieldDescriptorProto::_internal_has_label() const { + bool value = (_has_bits_[0] & 0x00000200u) != 0; + return value; } -inline void FieldDescriptorProto::clear_has_label() { - _has_bits_[0] &= ~0x00000100u; +inline bool FieldDescriptorProto::has_label() const { + return _internal_has_label(); } inline void FieldDescriptorProto::clear_label() { label_ = 1; - clear_has_label(); + _has_bits_[0] &= ~0x00000200u; +} +inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label FieldDescriptorProto::_internal_label() const { + return static_cast< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label >(label_); } -inline ::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const { +inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label FieldDescriptorProto::label() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.label) - return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_); + return _internal_label(); } -inline void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) { - assert(::google::protobuf::FieldDescriptorProto_Label_IsValid(value)); - set_has_label(); +inline void FieldDescriptorProto::_internal_set_label(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label value) { + assert(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label_IsValid(value)); + _has_bits_[0] |= 0x00000200u; label_ = value; +} +inline void FieldDescriptorProto::set_label(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label value) { + _internal_set_label(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.label) } // optional .google.protobuf.FieldDescriptorProto.Type type = 5; -inline bool FieldDescriptorProto::has_type() const { - return (_has_bits_[0] & 0x00000200u) != 0; +inline bool FieldDescriptorProto::_internal_has_type() const { + bool value = (_has_bits_[0] & 0x00000400u) != 0; + return value; } -inline void FieldDescriptorProto::set_has_type() { - _has_bits_[0] |= 0x00000200u; -} -inline void FieldDescriptorProto::clear_has_type() { - _has_bits_[0] &= ~0x00000200u; +inline bool FieldDescriptorProto::has_type() const { + return _internal_has_type(); } inline void FieldDescriptorProto::clear_type() { type_ = 1; - clear_has_type(); + _has_bits_[0] &= ~0x00000400u; } -inline ::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const { +inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type FieldDescriptorProto::_internal_type() const { + return static_cast< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type >(type_); +} +inline PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type FieldDescriptorProto::type() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type) - return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_); + return _internal_type(); } -inline void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) { - assert(::google::protobuf::FieldDescriptorProto_Type_IsValid(value)); - set_has_type(); +inline void FieldDescriptorProto::_internal_set_type(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type value) { + assert(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type_IsValid(value)); + _has_bits_[0] |= 0x00000400u; type_ = value; +} +inline void FieldDescriptorProto::set_type(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type value) { + _internal_set_type(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type) } // optional string type_name = 6; -inline bool FieldDescriptorProto::has_type_name() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -inline void FieldDescriptorProto::set_has_type_name() { - _has_bits_[0] |= 0x00000004u; +inline bool FieldDescriptorProto::_internal_has_type_name() const { + bool value = (_has_bits_[0] & 0x00000004u) != 0; + return value; } -inline void FieldDescriptorProto::clear_has_type_name() { - _has_bits_[0] &= ~0x00000004u; +inline bool FieldDescriptorProto::has_type_name() const { + return _internal_has_type_name(); } inline void FieldDescriptorProto::clear_type_name() { - type_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_type_name(); + type_name_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000004u; } -inline const ::std::string& FieldDescriptorProto::type_name() const { +inline const std::string& FieldDescriptorProto::type_name() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type_name) - return type_name_.GetNoArena(); + return _internal_type_name(); } -inline void FieldDescriptorProto::set_type_name(const ::std::string& value) { - set_has_type_name(); - type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FieldDescriptorProto::set_type_name(const std::string& value) { + _internal_set_type_name(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type_name) } -#if LANG_CXX11 -inline void FieldDescriptorProto::set_type_name(::std::string&& value) { - set_has_type_name(); - type_name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FieldDescriptorProto::mutable_type_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name) + return _internal_mutable_type_name(); +} +inline const std::string& FieldDescriptorProto::_internal_type_name() const { + return type_name_.Get(); +} +inline void FieldDescriptorProto::_internal_set_type_name(const std::string& value) { + _has_bits_[0] |= 0x00000004u; + type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FieldDescriptorProto::set_type_name(std::string&& value) { + _has_bits_[0] |= 0x00000004u; + type_name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.type_name) } -#endif inline void FieldDescriptorProto::set_type_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_type_name(); - type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000004u; + type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name) } -inline void FieldDescriptorProto::set_type_name(const char* value, size_t size) { - set_has_type_name(); - type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FieldDescriptorProto::set_type_name(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000004u; + type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name) } -inline ::std::string* FieldDescriptorProto::mutable_type_name() { - set_has_type_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name) - return type_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FieldDescriptorProto::_internal_mutable_type_name() { + _has_bits_[0] |= 0x00000004u; + return type_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FieldDescriptorProto::release_type_name() { +inline std::string* FieldDescriptorProto::release_type_name() { // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.type_name) - clear_has_type_name(); - return type_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_type_name()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000004u; + return type_name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) { - if (type_name != NULL) { - set_has_type_name(); +inline void FieldDescriptorProto::set_allocated_type_name(std::string* type_name) { + if (type_name != nullptr) { + _has_bits_[0] |= 0x00000004u; } else { - clear_has_type_name(); + _has_bits_[0] &= ~0x00000004u; } - type_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_name); + type_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), type_name, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name) } // optional string extendee = 2; -inline bool FieldDescriptorProto::has_extendee() const { - return (_has_bits_[0] & 0x00000002u) != 0; +inline bool FieldDescriptorProto::_internal_has_extendee() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void FieldDescriptorProto::set_has_extendee() { - _has_bits_[0] |= 0x00000002u; -} -inline void FieldDescriptorProto::clear_has_extendee() { - _has_bits_[0] &= ~0x00000002u; +inline bool FieldDescriptorProto::has_extendee() const { + return _internal_has_extendee(); } inline void FieldDescriptorProto::clear_extendee() { - extendee_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_extendee(); + extendee_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000002u; } -inline const ::std::string& FieldDescriptorProto::extendee() const { +inline const std::string& FieldDescriptorProto::extendee() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee) - return extendee_.GetNoArena(); + return _internal_extendee(); } -inline void FieldDescriptorProto::set_extendee(const ::std::string& value) { - set_has_extendee(); - extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FieldDescriptorProto::set_extendee(const std::string& value) { + _internal_set_extendee(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.extendee) } -#if LANG_CXX11 -inline void FieldDescriptorProto::set_extendee(::std::string&& value) { - set_has_extendee(); - extendee_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FieldDescriptorProto::mutable_extendee() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee) + return _internal_mutable_extendee(); +} +inline const std::string& FieldDescriptorProto::_internal_extendee() const { + return extendee_.Get(); +} +inline void FieldDescriptorProto::_internal_set_extendee(const std::string& value) { + _has_bits_[0] |= 0x00000002u; + extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FieldDescriptorProto::set_extendee(std::string&& value) { + _has_bits_[0] |= 0x00000002u; + extendee_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.extendee) } -#endif inline void FieldDescriptorProto::set_extendee(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_extendee(); - extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000002u; + extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee) } -inline void FieldDescriptorProto::set_extendee(const char* value, size_t size) { - set_has_extendee(); - extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FieldDescriptorProto::set_extendee(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000002u; + extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee) } -inline ::std::string* FieldDescriptorProto::mutable_extendee() { - set_has_extendee(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee) - return extendee_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FieldDescriptorProto::_internal_mutable_extendee() { + _has_bits_[0] |= 0x00000002u; + return extendee_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FieldDescriptorProto::release_extendee() { +inline std::string* FieldDescriptorProto::release_extendee() { // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.extendee) - clear_has_extendee(); - return extendee_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_extendee()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000002u; + return extendee_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) { - if (extendee != NULL) { - set_has_extendee(); +inline void FieldDescriptorProto::set_allocated_extendee(std::string* extendee) { + if (extendee != nullptr) { + _has_bits_[0] |= 0x00000002u; } else { - clear_has_extendee(); + _has_bits_[0] &= ~0x00000002u; } - extendee_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), extendee); + extendee_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), extendee, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee) } // optional string default_value = 7; -inline bool FieldDescriptorProto::has_default_value() const { - return (_has_bits_[0] & 0x00000008u) != 0; -} -inline void FieldDescriptorProto::set_has_default_value() { - _has_bits_[0] |= 0x00000008u; +inline bool FieldDescriptorProto::_internal_has_default_value() const { + bool value = (_has_bits_[0] & 0x00000008u) != 0; + return value; } -inline void FieldDescriptorProto::clear_has_default_value() { - _has_bits_[0] &= ~0x00000008u; +inline bool FieldDescriptorProto::has_default_value() const { + return _internal_has_default_value(); } inline void FieldDescriptorProto::clear_default_value() { - default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_default_value(); + default_value_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000008u; } -inline const ::std::string& FieldDescriptorProto::default_value() const { +inline const std::string& FieldDescriptorProto::default_value() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.default_value) - return default_value_.GetNoArena(); + return _internal_default_value(); } -inline void FieldDescriptorProto::set_default_value(const ::std::string& value) { - set_has_default_value(); - default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FieldDescriptorProto::set_default_value(const std::string& value) { + _internal_set_default_value(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.default_value) } -#if LANG_CXX11 -inline void FieldDescriptorProto::set_default_value(::std::string&& value) { - set_has_default_value(); - default_value_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FieldDescriptorProto::mutable_default_value() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value) + return _internal_mutable_default_value(); +} +inline const std::string& FieldDescriptorProto::_internal_default_value() const { + return default_value_.Get(); +} +inline void FieldDescriptorProto::_internal_set_default_value(const std::string& value) { + _has_bits_[0] |= 0x00000008u; + default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FieldDescriptorProto::set_default_value(std::string&& value) { + _has_bits_[0] |= 0x00000008u; + default_value_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.default_value) } -#endif inline void FieldDescriptorProto::set_default_value(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_default_value(); - default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000008u; + default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value) } -inline void FieldDescriptorProto::set_default_value(const char* value, size_t size) { - set_has_default_value(); - default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FieldDescriptorProto::set_default_value(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000008u; + default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value) } -inline ::std::string* FieldDescriptorProto::mutable_default_value() { - set_has_default_value(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value) - return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FieldDescriptorProto::_internal_mutable_default_value() { + _has_bits_[0] |= 0x00000008u; + return default_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FieldDescriptorProto::release_default_value() { +inline std::string* FieldDescriptorProto::release_default_value() { // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.default_value) - clear_has_default_value(); - return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_default_value()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000008u; + return default_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) { - if (default_value != NULL) { - set_has_default_value(); +inline void FieldDescriptorProto::set_allocated_default_value(std::string* default_value) { + if (default_value != nullptr) { + _has_bits_[0] |= 0x00000008u; } else { - clear_has_default_value(); + _has_bits_[0] &= ~0x00000008u; } - default_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), default_value); + default_value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), default_value, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value) } // optional int32 oneof_index = 9; -inline bool FieldDescriptorProto::has_oneof_index() const { - return (_has_bits_[0] & 0x00000080u) != 0; +inline bool FieldDescriptorProto::_internal_has_oneof_index() const { + bool value = (_has_bits_[0] & 0x00000080u) != 0; + return value; } -inline void FieldDescriptorProto::set_has_oneof_index() { - _has_bits_[0] |= 0x00000080u; -} -inline void FieldDescriptorProto::clear_has_oneof_index() { - _has_bits_[0] &= ~0x00000080u; +inline bool FieldDescriptorProto::has_oneof_index() const { + return _internal_has_oneof_index(); } inline void FieldDescriptorProto::clear_oneof_index() { oneof_index_ = 0; - clear_has_oneof_index(); + _has_bits_[0] &= ~0x00000080u; } -inline ::google::protobuf::int32 FieldDescriptorProto::oneof_index() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.oneof_index) +inline ::PROTOBUF_NAMESPACE_ID::int32 FieldDescriptorProto::_internal_oneof_index() const { return oneof_index_; } -inline void FieldDescriptorProto::set_oneof_index(::google::protobuf::int32 value) { - set_has_oneof_index(); +inline ::PROTOBUF_NAMESPACE_ID::int32 FieldDescriptorProto::oneof_index() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.oneof_index) + return _internal_oneof_index(); +} +inline void FieldDescriptorProto::_internal_set_oneof_index(::PROTOBUF_NAMESPACE_ID::int32 value) { + _has_bits_[0] |= 0x00000080u; oneof_index_ = value; +} +inline void FieldDescriptorProto::set_oneof_index(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_oneof_index(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index) } // optional string json_name = 10; -inline bool FieldDescriptorProto::has_json_name() const { - return (_has_bits_[0] & 0x00000010u) != 0; +inline bool FieldDescriptorProto::_internal_has_json_name() const { + bool value = (_has_bits_[0] & 0x00000010u) != 0; + return value; } -inline void FieldDescriptorProto::set_has_json_name() { - _has_bits_[0] |= 0x00000010u; -} -inline void FieldDescriptorProto::clear_has_json_name() { - _has_bits_[0] &= ~0x00000010u; +inline bool FieldDescriptorProto::has_json_name() const { + return _internal_has_json_name(); } inline void FieldDescriptorProto::clear_json_name() { - json_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_json_name(); + json_name_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000010u; } -inline const ::std::string& FieldDescriptorProto::json_name() const { +inline const std::string& FieldDescriptorProto::json_name() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.json_name) - return json_name_.GetNoArena(); + return _internal_json_name(); } -inline void FieldDescriptorProto::set_json_name(const ::std::string& value) { - set_has_json_name(); - json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FieldDescriptorProto::set_json_name(const std::string& value) { + _internal_set_json_name(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.json_name) } -#if LANG_CXX11 -inline void FieldDescriptorProto::set_json_name(::std::string&& value) { - set_has_json_name(); - json_name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FieldDescriptorProto::mutable_json_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.json_name) + return _internal_mutable_json_name(); +} +inline const std::string& FieldDescriptorProto::_internal_json_name() const { + return json_name_.Get(); +} +inline void FieldDescriptorProto::_internal_set_json_name(const std::string& value) { + _has_bits_[0] |= 0x00000010u; + json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FieldDescriptorProto::set_json_name(std::string&& value) { + _has_bits_[0] |= 0x00000010u; + json_name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.json_name) } -#endif inline void FieldDescriptorProto::set_json_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_json_name(); - json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000010u; + json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.json_name) } -inline void FieldDescriptorProto::set_json_name(const char* value, size_t size) { - set_has_json_name(); - json_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FieldDescriptorProto::set_json_name(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000010u; + json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.json_name) } -inline ::std::string* FieldDescriptorProto::mutable_json_name() { - set_has_json_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.json_name) - return json_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FieldDescriptorProto::_internal_mutable_json_name() { + _has_bits_[0] |= 0x00000010u; + return json_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FieldDescriptorProto::release_json_name() { +inline std::string* FieldDescriptorProto::release_json_name() { // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.json_name) - clear_has_json_name(); - return json_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_json_name()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000010u; + return json_name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FieldDescriptorProto::set_allocated_json_name(::std::string* json_name) { - if (json_name != NULL) { - set_has_json_name(); +inline void FieldDescriptorProto::set_allocated_json_name(std::string* json_name) { + if (json_name != nullptr) { + _has_bits_[0] |= 0x00000010u; } else { - clear_has_json_name(); + _has_bits_[0] &= ~0x00000010u; } - json_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), json_name); + json_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), json_name, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.json_name) } // optional .google.protobuf.FieldOptions options = 8; -inline bool FieldDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000020u) != 0; +inline bool FieldDescriptorProto::_internal_has_options() const { + bool value = (_has_bits_[0] & 0x00000020u) != 0; + PROTOBUF_ASSUME(!value || options_ != nullptr); + return value; } -inline void FieldDescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000020u; +inline bool FieldDescriptorProto::has_options() const { + return _internal_has_options(); } -inline void FieldDescriptorProto::clear_has_options() { +inline void FieldDescriptorProto::clear_options() { + if (options_ != nullptr) options_->Clear(); _has_bits_[0] &= ~0x00000020u; } -inline void FieldDescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); - clear_has_options(); +inline const PROTOBUF_NAMESPACE_ID::FieldOptions& FieldDescriptorProto::_internal_options() const { + const PROTOBUF_NAMESPACE_ID::FieldOptions* p = options_; + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_FieldOptions_default_instance_); } -inline const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const { - const ::google::protobuf::FieldOptions* p = options_; +inline const PROTOBUF_NAMESPACE_ID::FieldOptions& FieldDescriptorProto::options() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_FieldOptions_default_instance_); + return _internal_options(); } -inline ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::FieldOptions; +inline void FieldDescriptorProto::unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::FieldOptions* options) { + if (GetArena() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_); } - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options) - return options_; + options_ = options; + if (options) { + _has_bits_[0] |= 0x00000020u; + } else { + _has_bits_[0] &= ~0x00000020u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FieldDescriptorProto.options) +} +inline PROTOBUF_NAMESPACE_ID::FieldOptions* FieldDescriptorProto::release_options() { + _has_bits_[0] &= ~0x00000020u; + PROTOBUF_NAMESPACE_ID::FieldOptions* temp = options_; + options_ = nullptr; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + return temp; } -inline ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() { +inline PROTOBUF_NAMESPACE_ID::FieldOptions* FieldDescriptorProto::unsafe_arena_release_options() { // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.options) - clear_has_options(); - ::google::protobuf::FieldOptions* temp = options_; - options_ = NULL; + _has_bits_[0] &= ~0x00000020u; + PROTOBUF_NAMESPACE_ID::FieldOptions* temp = options_; + options_ = nullptr; return temp; } -inline void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) { - delete options_; - options_ = options; +inline PROTOBUF_NAMESPACE_ID::FieldOptions* FieldDescriptorProto::_internal_mutable_options() { + _has_bits_[0] |= 0x00000020u; + if (options_ == nullptr) { + auto* p = CreateMaybeMessage(GetArena()); + options_ = p; + } + return options_; +} +inline PROTOBUF_NAMESPACE_ID::FieldOptions* FieldDescriptorProto::mutable_options() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options) + return _internal_mutable_options(); +} +inline void FieldDescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::FieldOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + if (message_arena == nullptr) { + delete options_; + } if (options) { - set_has_options(); + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _has_bits_[0] |= 0x00000020u; } else { - clear_has_options(); + _has_bits_[0] &= ~0x00000020u; } + options_ = options; // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.options) } +// optional bool proto3_optional = 17; +inline bool FieldDescriptorProto::_internal_has_proto3_optional() const { + bool value = (_has_bits_[0] & 0x00000100u) != 0; + return value; +} +inline bool FieldDescriptorProto::has_proto3_optional() const { + return _internal_has_proto3_optional(); +} +inline void FieldDescriptorProto::clear_proto3_optional() { + proto3_optional_ = false; + _has_bits_[0] &= ~0x00000100u; +} +inline bool FieldDescriptorProto::_internal_proto3_optional() const { + return proto3_optional_; +} +inline bool FieldDescriptorProto::proto3_optional() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.proto3_optional) + return _internal_proto3_optional(); +} +inline void FieldDescriptorProto::_internal_set_proto3_optional(bool value) { + _has_bits_[0] |= 0x00000100u; + proto3_optional_ = value; +} +inline void FieldDescriptorProto::set_proto3_optional(bool value) { + _internal_set_proto3_optional(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.proto3_optional) +} + // ------------------------------------------------------------------- // OneofDescriptorProto // optional string name = 1; -inline bool OneofDescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; +inline bool OneofDescriptorProto::_internal_has_name() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void OneofDescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; -} -inline void OneofDescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; +inline bool OneofDescriptorProto::has_name() const { + return _internal_has_name(); } inline void OneofDescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); + name_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& OneofDescriptorProto::name() const { +inline const std::string& OneofDescriptorProto::name() const { // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name) - return name_.GetNoArena(); + return _internal_name(); } -inline void OneofDescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void OneofDescriptorProto::set_name(const std::string& value) { + _internal_set_name(value); // @@protoc_insertion_point(field_set:google.protobuf.OneofDescriptorProto.name) } -#if LANG_CXX11 -inline void OneofDescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* OneofDescriptorProto::mutable_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.name) + return _internal_mutable_name(); +} +inline const std::string& OneofDescriptorProto::_internal_name() const { + return name_.Get(); +} +inline void OneofDescriptorProto::_internal_set_name(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void OneofDescriptorProto::set_name(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.OneofDescriptorProto.name) } -#endif inline void OneofDescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name) } -inline void OneofDescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void OneofDescriptorProto::set_name(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.name) } -inline ::std::string* OneofDescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* OneofDescriptorProto::_internal_mutable_name() { + _has_bits_[0] |= 0x00000001u; + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* OneofDescriptorProto::release_name() { +inline std::string* OneofDescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.OneofDescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_name()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void OneofDescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); +inline void OneofDescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_name(); + _has_bits_[0] &= ~0x00000001u; } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name) } // optional .google.protobuf.OneofOptions options = 2; +inline bool OneofDescriptorProto::_internal_has_options() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + PROTOBUF_ASSUME(!value || options_ != nullptr); + return value; +} inline bool OneofDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000002u) != 0; + return _internal_has_options(); +} +inline void OneofDescriptorProto::clear_options() { + if (options_ != nullptr) options_->Clear(); + _has_bits_[0] &= ~0x00000002u; +} +inline const PROTOBUF_NAMESPACE_ID::OneofOptions& OneofDescriptorProto::_internal_options() const { + const PROTOBUF_NAMESPACE_ID::OneofOptions* p = options_; + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_OneofOptions_default_instance_); +} +inline const PROTOBUF_NAMESPACE_ID::OneofOptions& OneofDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.options) + return _internal_options(); +} +inline void OneofDescriptorProto::unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::OneofOptions* options) { + if (GetArena() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_); + } + options_ = options; + if (options) { + _has_bits_[0] |= 0x00000002u; + } else { + _has_bits_[0] &= ~0x00000002u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.OneofDescriptorProto.options) } -inline void OneofDescriptorProto::set_has_options() { +inline PROTOBUF_NAMESPACE_ID::OneofOptions* OneofDescriptorProto::release_options() { + _has_bits_[0] &= ~0x00000002u; + PROTOBUF_NAMESPACE_ID::OneofOptions* temp = options_; + options_ = nullptr; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + return temp; +} +inline PROTOBUF_NAMESPACE_ID::OneofOptions* OneofDescriptorProto::unsafe_arena_release_options() { + // @@protoc_insertion_point(field_release:google.protobuf.OneofDescriptorProto.options) + _has_bits_[0] &= ~0x00000002u; + PROTOBUF_NAMESPACE_ID::OneofOptions* temp = options_; + options_ = nullptr; + return temp; +} +inline PROTOBUF_NAMESPACE_ID::OneofOptions* OneofDescriptorProto::_internal_mutable_options() { _has_bits_[0] |= 0x00000002u; + if (options_ == nullptr) { + auto* p = CreateMaybeMessage(GetArena()); + options_ = p; + } + return options_; +} +inline PROTOBUF_NAMESPACE_ID::OneofOptions* OneofDescriptorProto::mutable_options() { + // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.options) + return _internal_mutable_options(); +} +inline void OneofDescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::OneofOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + if (message_arena == nullptr) { + delete options_; + } + if (options) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _has_bits_[0] |= 0x00000002u; + } else { + _has_bits_[0] &= ~0x00000002u; + } + options_ = options; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.options) } -inline void OneofDescriptorProto::clear_has_options() { + +// ------------------------------------------------------------------- + +// EnumDescriptorProto_EnumReservedRange + +// optional int32 start = 1; +inline bool EnumDescriptorProto_EnumReservedRange::_internal_has_start() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool EnumDescriptorProto_EnumReservedRange::has_start() const { + return _internal_has_start(); +} +inline void EnumDescriptorProto_EnumReservedRange::clear_start() { + start_ = 0; + _has_bits_[0] &= ~0x00000001u; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 EnumDescriptorProto_EnumReservedRange::_internal_start() const { + return start_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 EnumDescriptorProto_EnumReservedRange::start() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.EnumReservedRange.start) + return _internal_start(); +} +inline void EnumDescriptorProto_EnumReservedRange::_internal_set_start(::PROTOBUF_NAMESPACE_ID::int32 value) { + _has_bits_[0] |= 0x00000001u; + start_ = value; +} +inline void EnumDescriptorProto_EnumReservedRange::set_start(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_start(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.EnumReservedRange.start) +} + +// optional int32 end = 2; +inline bool EnumDescriptorProto_EnumReservedRange::_internal_has_end() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool EnumDescriptorProto_EnumReservedRange::has_end() const { + return _internal_has_end(); +} +inline void EnumDescriptorProto_EnumReservedRange::clear_end() { + end_ = 0; _has_bits_[0] &= ~0x00000002u; } -inline void OneofDescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::OneofOptions::Clear(); - clear_has_options(); +inline ::PROTOBUF_NAMESPACE_ID::int32 EnumDescriptorProto_EnumReservedRange::_internal_end() const { + return end_; } -inline const ::google::protobuf::OneofOptions& OneofDescriptorProto::options() const { - const ::google::protobuf::OneofOptions* p = options_; - // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_OneofOptions_default_instance_); +inline ::PROTOBUF_NAMESPACE_ID::int32 EnumDescriptorProto_EnumReservedRange::end() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.EnumReservedRange.end) + return _internal_end(); +} +inline void EnumDescriptorProto_EnumReservedRange::_internal_set_end(::PROTOBUF_NAMESPACE_ID::int32 value) { + _has_bits_[0] |= 0x00000002u; + end_ = value; +} +inline void EnumDescriptorProto_EnumReservedRange::set_end(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_end(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.EnumReservedRange.end) +} + +// ------------------------------------------------------------------- + +// EnumDescriptorProto + +// optional string name = 1; +inline bool EnumDescriptorProto::_internal_has_name() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool EnumDescriptorProto::has_name() const { + return _internal_has_name(); +} +inline void EnumDescriptorProto::clear_name() { + name_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; +} +inline const std::string& EnumDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name) + return _internal_name(); +} +inline void EnumDescriptorProto::set_name(const std::string& value) { + _internal_set_name(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name) +} +inline std::string* EnumDescriptorProto::mutable_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name) + return _internal_mutable_name(); +} +inline const std::string& EnumDescriptorProto::_internal_name() const { + return name_.Get(); +} +inline void EnumDescriptorProto::_internal_set_name(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void EnumDescriptorProto::set_name(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumDescriptorProto.name) +} +inline void EnumDescriptorProto::set_name(const char* value) { + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); + // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name) +} +inline void EnumDescriptorProto::set_name(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name) +} +inline std::string* EnumDescriptorProto::_internal_mutable_name() { + _has_bits_[0] |= 0x00000001u; + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); +} +inline std::string* EnumDescriptorProto::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.name) + if (!_internal_has_name()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void EnumDescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _has_bits_[0] |= 0x00000001u; + } else { + _has_bits_[0] &= ~0x00000001u; + } + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name) +} + +// repeated .google.protobuf.EnumValueDescriptorProto value = 2; +inline int EnumDescriptorProto::_internal_value_size() const { + return value_.size(); +} +inline int EnumDescriptorProto::value_size() const { + return _internal_value_size(); +} +inline void EnumDescriptorProto::clear_value() { + value_.Clear(); +} +inline PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.value) + return value_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto >* +EnumDescriptorProto::mutable_value() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value) + return &value_; +} +inline const PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto& EnumDescriptorProto::_internal_value(int index) const { + return value_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.value) + return _internal_value(index); +} +inline PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* EnumDescriptorProto::_internal_add_value() { + return value_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* EnumDescriptorProto::add_value() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value) + return _internal_add_value(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto >& +EnumDescriptorProto::value() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value) + return value_; +} + +// optional .google.protobuf.EnumOptions options = 3; +inline bool EnumDescriptorProto::_internal_has_options() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + PROTOBUF_ASSUME(!value || options_ != nullptr); + return value; +} +inline bool EnumDescriptorProto::has_options() const { + return _internal_has_options(); +} +inline void EnumDescriptorProto::clear_options() { + if (options_ != nullptr) options_->Clear(); + _has_bits_[0] &= ~0x00000002u; +} +inline const PROTOBUF_NAMESPACE_ID::EnumOptions& EnumDescriptorProto::_internal_options() const { + const PROTOBUF_NAMESPACE_ID::EnumOptions* p = options_; + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_EnumOptions_default_instance_); +} +inline const PROTOBUF_NAMESPACE_ID::EnumOptions& EnumDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options) + return _internal_options(); +} +inline void EnumDescriptorProto::unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::EnumOptions* options) { + if (GetArena() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_); + } + options_ = options; + if (options) { + _has_bits_[0] |= 0x00000002u; + } else { + _has_bits_[0] &= ~0x00000002u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.EnumDescriptorProto.options) +} +inline PROTOBUF_NAMESPACE_ID::EnumOptions* EnumDescriptorProto::release_options() { + _has_bits_[0] &= ~0x00000002u; + PROTOBUF_NAMESPACE_ID::EnumOptions* temp = options_; + options_ = nullptr; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + return temp; +} +inline PROTOBUF_NAMESPACE_ID::EnumOptions* EnumDescriptorProto::unsafe_arena_release_options() { + // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.options) + _has_bits_[0] &= ~0x00000002u; + PROTOBUF_NAMESPACE_ID::EnumOptions* temp = options_; + options_ = nullptr; + return temp; } -inline ::google::protobuf::OneofOptions* OneofDescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::OneofOptions; +inline PROTOBUF_NAMESPACE_ID::EnumOptions* EnumDescriptorProto::_internal_mutable_options() { + _has_bits_[0] |= 0x00000002u; + if (options_ == nullptr) { + auto* p = CreateMaybeMessage(GetArena()); + options_ = p; } - // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.options) return options_; } -inline ::google::protobuf::OneofOptions* OneofDescriptorProto::release_options() { - // @@protoc_insertion_point(field_release:google.protobuf.OneofDescriptorProto.options) - clear_has_options(); - ::google::protobuf::OneofOptions* temp = options_; - options_ = NULL; - return temp; +inline PROTOBUF_NAMESPACE_ID::EnumOptions* EnumDescriptorProto::mutable_options() { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options) + return _internal_mutable_options(); } -inline void OneofDescriptorProto::set_allocated_options(::google::protobuf::OneofOptions* options) { - delete options_; - options_ = options; +inline void EnumDescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::EnumOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + if (message_arena == nullptr) { + delete options_; + } if (options) { - set_has_options(); + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _has_bits_[0] |= 0x00000002u; } else { - clear_has_options(); + _has_bits_[0] &= ~0x00000002u; } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.options) + options_ = options; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options) } -// ------------------------------------------------------------------- - -// EnumDescriptorProto - -// optional string name = 1; -inline bool EnumDescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; +// repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; +inline int EnumDescriptorProto::_internal_reserved_range_size() const { + return reserved_range_.size(); } -inline void EnumDescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; +inline int EnumDescriptorProto::reserved_range_size() const { + return _internal_reserved_range_size(); } -inline void EnumDescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; +inline void EnumDescriptorProto::clear_reserved_range() { + reserved_range_.Clear(); } -inline void EnumDescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); +inline PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* EnumDescriptorProto::mutable_reserved_range(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.reserved_range) + return reserved_range_.Mutable(index); } -inline const ::std::string& EnumDescriptorProto::name() const { - // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name) - return name_.GetNoArena(); +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange >* +EnumDescriptorProto::mutable_reserved_range() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.reserved_range) + return &reserved_range_; } -inline void EnumDescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name) +inline const PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange& EnumDescriptorProto::_internal_reserved_range(int index) const { + return reserved_range_.Get(index); } -#if LANG_CXX11 -inline void EnumDescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumDescriptorProto.name) +inline const PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange& EnumDescriptorProto::reserved_range(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.reserved_range) + return _internal_reserved_range(index); } -#endif -inline void EnumDescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name) +inline PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* EnumDescriptorProto::_internal_add_reserved_range() { + return reserved_range_.Add(); } -inline void EnumDescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name) +inline PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* EnumDescriptorProto::add_reserved_range() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.reserved_range) + return _internal_add_reserved_range(); } -inline ::std::string* EnumDescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange >& +EnumDescriptorProto::reserved_range() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.reserved_range) + return reserved_range_; } -inline ::std::string* EnumDescriptorProto::release_name() { - // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + +// repeated string reserved_name = 5; +inline int EnumDescriptorProto::_internal_reserved_name_size() const { + return reserved_name_.size(); } -inline void EnumDescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); - } else { - clear_has_name(); - } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name) +inline int EnumDescriptorProto::reserved_name_size() const { + return _internal_reserved_name_size(); } - -// repeated .google.protobuf.EnumValueDescriptorProto value = 2; -inline int EnumDescriptorProto::value_size() const { - return value_.size(); +inline void EnumDescriptorProto::clear_reserved_name() { + reserved_name_.Clear(); } -inline void EnumDescriptorProto::clear_value() { - value_.Clear(); +inline std::string* EnumDescriptorProto::add_reserved_name() { + // @@protoc_insertion_point(field_add_mutable:google.protobuf.EnumDescriptorProto.reserved_name) + return _internal_add_reserved_name(); } -inline const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.value) - return value_.Get(index); +inline const std::string& EnumDescriptorProto::_internal_reserved_name(int index) const { + return reserved_name_.Get(index); } -inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.value) - return value_.Mutable(index); +inline const std::string& EnumDescriptorProto::reserved_name(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.reserved_name) + return _internal_reserved_name(index); } -inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() { - // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value) - return value_.Add(); +inline std::string* EnumDescriptorProto::mutable_reserved_name(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.reserved_name) + return reserved_name_.Mutable(index); } -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* -EnumDescriptorProto::mutable_value() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value) - return &value_; +inline void EnumDescriptorProto::set_reserved_name(int index, const std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.reserved_name) + reserved_name_.Mutable(index)->assign(value); } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& -EnumDescriptorProto::value() const { - // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value) - return value_; +inline void EnumDescriptorProto::set_reserved_name(int index, std::string&& value) { + // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.reserved_name) + reserved_name_.Mutable(index)->assign(std::move(value)); } - -// optional .google.protobuf.EnumOptions options = 3; -inline bool EnumDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000002u) != 0; +inline void EnumDescriptorProto::set_reserved_name(int index, const char* value) { + GOOGLE_DCHECK(value != nullptr); + reserved_name_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.reserved_name) } -inline void EnumDescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000002u; +inline void EnumDescriptorProto::set_reserved_name(int index, const char* value, size_t size) { + reserved_name_.Mutable(index)->assign( + reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.reserved_name) } -inline void EnumDescriptorProto::clear_has_options() { - _has_bits_[0] &= ~0x00000002u; +inline std::string* EnumDescriptorProto::_internal_add_reserved_name() { + return reserved_name_.Add(); } -inline void EnumDescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear(); - clear_has_options(); +inline void EnumDescriptorProto::add_reserved_name(const std::string& value) { + reserved_name_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.reserved_name) } -inline const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const { - const ::google::protobuf::EnumOptions* p = options_; - // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_EnumOptions_default_instance_); +inline void EnumDescriptorProto::add_reserved_name(std::string&& value) { + reserved_name_.Add(std::move(value)); + // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.reserved_name) } -inline ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::EnumOptions; - } - // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options) - return options_; +inline void EnumDescriptorProto::add_reserved_name(const char* value) { + GOOGLE_DCHECK(value != nullptr); + reserved_name_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.EnumDescriptorProto.reserved_name) } -inline ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() { - // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.options) - clear_has_options(); - ::google::protobuf::EnumOptions* temp = options_; - options_ = NULL; - return temp; +inline void EnumDescriptorProto::add_reserved_name(const char* value, size_t size) { + reserved_name_.Add()->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.EnumDescriptorProto.reserved_name) } -inline void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) { - delete options_; - options_ = options; - if (options) { - set_has_options(); - } else { - clear_has_options(); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options) +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField& +EnumDescriptorProto::reserved_name() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.reserved_name) + return reserved_name_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField* +EnumDescriptorProto::mutable_reserved_name() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.reserved_name) + return &reserved_name_; } // ------------------------------------------------------------------- @@ -6511,135 +9234,186 @@ inline void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumO // EnumValueDescriptorProto // optional string name = 1; -inline bool EnumValueDescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void EnumValueDescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; +inline bool EnumValueDescriptorProto::_internal_has_name() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void EnumValueDescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; +inline bool EnumValueDescriptorProto::has_name() const { + return _internal_has_name(); } inline void EnumValueDescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); + name_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& EnumValueDescriptorProto::name() const { +inline const std::string& EnumValueDescriptorProto::name() const { // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name) - return name_.GetNoArena(); + return _internal_name(); } -inline void EnumValueDescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void EnumValueDescriptorProto::set_name(const std::string& value) { + _internal_set_name(value); // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.name) } -#if LANG_CXX11 -inline void EnumValueDescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* EnumValueDescriptorProto::mutable_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name) + return _internal_mutable_name(); +} +inline const std::string& EnumValueDescriptorProto::_internal_name() const { + return name_.Get(); +} +inline void EnumValueDescriptorProto::_internal_set_name(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void EnumValueDescriptorProto::set_name(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumValueDescriptorProto.name) } -#endif inline void EnumValueDescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name) } -inline void EnumValueDescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void EnumValueDescriptorProto::set_name(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name) } -inline ::std::string* EnumValueDescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* EnumValueDescriptorProto::_internal_mutable_name() { + _has_bits_[0] |= 0x00000001u; + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* EnumValueDescriptorProto::release_name() { +inline std::string* EnumValueDescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_name()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void EnumValueDescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); +inline void EnumValueDescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_name(); + _has_bits_[0] &= ~0x00000001u; } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name) } // optional int32 number = 2; -inline bool EnumValueDescriptorProto::has_number() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -inline void EnumValueDescriptorProto::set_has_number() { - _has_bits_[0] |= 0x00000004u; +inline bool EnumValueDescriptorProto::_internal_has_number() const { + bool value = (_has_bits_[0] & 0x00000004u) != 0; + return value; } -inline void EnumValueDescriptorProto::clear_has_number() { - _has_bits_[0] &= ~0x00000004u; +inline bool EnumValueDescriptorProto::has_number() const { + return _internal_has_number(); } inline void EnumValueDescriptorProto::clear_number() { number_ = 0; - clear_has_number(); + _has_bits_[0] &= ~0x00000004u; } -inline ::google::protobuf::int32 EnumValueDescriptorProto::number() const { - // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.number) +inline ::PROTOBUF_NAMESPACE_ID::int32 EnumValueDescriptorProto::_internal_number() const { return number_; } -inline void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) { - set_has_number(); +inline ::PROTOBUF_NAMESPACE_ID::int32 EnumValueDescriptorProto::number() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.number) + return _internal_number(); +} +inline void EnumValueDescriptorProto::_internal_set_number(::PROTOBUF_NAMESPACE_ID::int32 value) { + _has_bits_[0] |= 0x00000004u; number_ = value; +} +inline void EnumValueDescriptorProto::set_number(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_number(value); // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.number) } // optional .google.protobuf.EnumValueOptions options = 3; -inline bool EnumValueDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000002u) != 0; +inline bool EnumValueDescriptorProto::_internal_has_options() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + PROTOBUF_ASSUME(!value || options_ != nullptr); + return value; } -inline void EnumValueDescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000002u; +inline bool EnumValueDescriptorProto::has_options() const { + return _internal_has_options(); } -inline void EnumValueDescriptorProto::clear_has_options() { +inline void EnumValueDescriptorProto::clear_options() { + if (options_ != nullptr) options_->Clear(); _has_bits_[0] &= ~0x00000002u; } -inline void EnumValueDescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear(); - clear_has_options(); +inline const PROTOBUF_NAMESPACE_ID::EnumValueOptions& EnumValueDescriptorProto::_internal_options() const { + const PROTOBUF_NAMESPACE_ID::EnumValueOptions* p = options_; + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_EnumValueOptions_default_instance_); } -inline const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const { - const ::google::protobuf::EnumValueOptions* p = options_; +inline const PROTOBUF_NAMESPACE_ID::EnumValueOptions& EnumValueDescriptorProto::options() const { // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_EnumValueOptions_default_instance_); + return _internal_options(); } -inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::EnumValueOptions; +inline void EnumValueDescriptorProto::unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::EnumValueOptions* options) { + if (GetArena() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_); } - // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options) - return options_; + options_ = options; + if (options) { + _has_bits_[0] |= 0x00000002u; + } else { + _has_bits_[0] &= ~0x00000002u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.EnumValueDescriptorProto.options) +} +inline PROTOBUF_NAMESPACE_ID::EnumValueOptions* EnumValueDescriptorProto::release_options() { + _has_bits_[0] &= ~0x00000002u; + PROTOBUF_NAMESPACE_ID::EnumValueOptions* temp = options_; + options_ = nullptr; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + return temp; } -inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() { +inline PROTOBUF_NAMESPACE_ID::EnumValueOptions* EnumValueDescriptorProto::unsafe_arena_release_options() { // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.options) - clear_has_options(); - ::google::protobuf::EnumValueOptions* temp = options_; - options_ = NULL; + _has_bits_[0] &= ~0x00000002u; + PROTOBUF_NAMESPACE_ID::EnumValueOptions* temp = options_; + options_ = nullptr; return temp; } -inline void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) { - delete options_; - options_ = options; +inline PROTOBUF_NAMESPACE_ID::EnumValueOptions* EnumValueDescriptorProto::_internal_mutable_options() { + _has_bits_[0] |= 0x00000002u; + if (options_ == nullptr) { + auto* p = CreateMaybeMessage(GetArena()); + options_ = p; + } + return options_; +} +inline PROTOBUF_NAMESPACE_ID::EnumValueOptions* EnumValueDescriptorProto::mutable_options() { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options) + return _internal_mutable_options(); +} +inline void EnumValueDescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::EnumValueOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + if (message_arena == nullptr) { + delete options_; + } if (options) { - set_has_options(); + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _has_bits_[0] |= 0x00000002u; } else { - clear_has_options(); + _has_bits_[0] &= ~0x00000002u; } + options_ = options; // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.options) } @@ -6648,141 +9422,197 @@ inline void EnumValueDescriptorProto::set_allocated_options(::google::protobuf:: // ServiceDescriptorProto // optional string name = 1; -inline bool ServiceDescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void ServiceDescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; +inline bool ServiceDescriptorProto::_internal_has_name() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void ServiceDescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; +inline bool ServiceDescriptorProto::has_name() const { + return _internal_has_name(); } inline void ServiceDescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); + name_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& ServiceDescriptorProto::name() const { +inline const std::string& ServiceDescriptorProto::name() const { // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name) - return name_.GetNoArena(); + return _internal_name(); } -inline void ServiceDescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void ServiceDescriptorProto::set_name(const std::string& value) { + _internal_set_name(value); // @@protoc_insertion_point(field_set:google.protobuf.ServiceDescriptorProto.name) } -#if LANG_CXX11 -inline void ServiceDescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* ServiceDescriptorProto::mutable_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name) + return _internal_mutable_name(); +} +inline const std::string& ServiceDescriptorProto::_internal_name() const { + return name_.Get(); +} +inline void ServiceDescriptorProto::_internal_set_name(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void ServiceDescriptorProto::set_name(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.ServiceDescriptorProto.name) } -#endif inline void ServiceDescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name) } -inline void ServiceDescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void ServiceDescriptorProto::set_name(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name) } -inline ::std::string* ServiceDescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* ServiceDescriptorProto::_internal_mutable_name() { + _has_bits_[0] |= 0x00000001u; + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* ServiceDescriptorProto::release_name() { +inline std::string* ServiceDescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_name()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void ServiceDescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); +inline void ServiceDescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_name(); + _has_bits_[0] &= ~0x00000001u; } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name) } // repeated .google.protobuf.MethodDescriptorProto method = 2; -inline int ServiceDescriptorProto::method_size() const { +inline int ServiceDescriptorProto::_internal_method_size() const { return method_.size(); } +inline int ServiceDescriptorProto::method_size() const { + return _internal_method_size(); +} inline void ServiceDescriptorProto::clear_method() { method_.Clear(); } -inline const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.method) - return method_.Get(index); -} -inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) { +inline PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.method) return method_.Mutable(index); } -inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() { - // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method) - return method_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::MethodDescriptorProto >* ServiceDescriptorProto::mutable_method() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method) return &method_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& +inline const PROTOBUF_NAMESPACE_ID::MethodDescriptorProto& ServiceDescriptorProto::_internal_method(int index) const { + return method_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.method) + return _internal_method(index); +} +inline PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* ServiceDescriptorProto::_internal_add_method() { + return method_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* ServiceDescriptorProto::add_method() { + // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method) + return _internal_add_method(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::MethodDescriptorProto >& ServiceDescriptorProto::method() const { // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method) return method_; } // optional .google.protobuf.ServiceOptions options = 3; -inline bool ServiceDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000002u) != 0; +inline bool ServiceDescriptorProto::_internal_has_options() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + PROTOBUF_ASSUME(!value || options_ != nullptr); + return value; } -inline void ServiceDescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000002u; +inline bool ServiceDescriptorProto::has_options() const { + return _internal_has_options(); } -inline void ServiceDescriptorProto::clear_has_options() { +inline void ServiceDescriptorProto::clear_options() { + if (options_ != nullptr) options_->Clear(); _has_bits_[0] &= ~0x00000002u; } -inline void ServiceDescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear(); - clear_has_options(); +inline const PROTOBUF_NAMESPACE_ID::ServiceOptions& ServiceDescriptorProto::_internal_options() const { + const PROTOBUF_NAMESPACE_ID::ServiceOptions* p = options_; + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_ServiceOptions_default_instance_); } -inline const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const { - const ::google::protobuf::ServiceOptions* p = options_; +inline const PROTOBUF_NAMESPACE_ID::ServiceOptions& ServiceDescriptorProto::options() const { // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_ServiceOptions_default_instance_); + return _internal_options(); } -inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::ServiceOptions; +inline void ServiceDescriptorProto::unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::ServiceOptions* options) { + if (GetArena() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_); } - // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options) - return options_; + options_ = options; + if (options) { + _has_bits_[0] |= 0x00000002u; + } else { + _has_bits_[0] &= ~0x00000002u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.ServiceDescriptorProto.options) +} +inline PROTOBUF_NAMESPACE_ID::ServiceOptions* ServiceDescriptorProto::release_options() { + _has_bits_[0] &= ~0x00000002u; + PROTOBUF_NAMESPACE_ID::ServiceOptions* temp = options_; + options_ = nullptr; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + return temp; } -inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() { +inline PROTOBUF_NAMESPACE_ID::ServiceOptions* ServiceDescriptorProto::unsafe_arena_release_options() { // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.options) - clear_has_options(); - ::google::protobuf::ServiceOptions* temp = options_; - options_ = NULL; + _has_bits_[0] &= ~0x00000002u; + PROTOBUF_NAMESPACE_ID::ServiceOptions* temp = options_; + options_ = nullptr; return temp; } -inline void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) { - delete options_; - options_ = options; +inline PROTOBUF_NAMESPACE_ID::ServiceOptions* ServiceDescriptorProto::_internal_mutable_options() { + _has_bits_[0] |= 0x00000002u; + if (options_ == nullptr) { + auto* p = CreateMaybeMessage(GetArena()); + options_ = p; + } + return options_; +} +inline PROTOBUF_NAMESPACE_ID::ServiceOptions* ServiceDescriptorProto::mutable_options() { + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options) + return _internal_mutable_options(); +} +inline void ServiceDescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::ServiceOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + if (message_arena == nullptr) { + delete options_; + } if (options) { - set_has_options(); + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _has_bits_[0] |= 0x00000002u; } else { - clear_has_options(); + _has_bits_[0] &= ~0x00000002u; } + options_ = options; // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.options) } @@ -6791,285 +9621,360 @@ inline void ServiceDescriptorProto::set_allocated_options(::google::protobuf::Se // MethodDescriptorProto // optional string name = 1; -inline bool MethodDescriptorProto::has_name() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void MethodDescriptorProto::set_has_name() { - _has_bits_[0] |= 0x00000001u; +inline bool MethodDescriptorProto::_internal_has_name() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void MethodDescriptorProto::clear_has_name() { - _has_bits_[0] &= ~0x00000001u; +inline bool MethodDescriptorProto::has_name() const { + return _internal_has_name(); } inline void MethodDescriptorProto::clear_name() { - name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); + name_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& MethodDescriptorProto::name() const { +inline const std::string& MethodDescriptorProto::name() const { // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name) - return name_.GetNoArena(); + return _internal_name(); } -inline void MethodDescriptorProto::set_name(const ::std::string& value) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void MethodDescriptorProto::set_name(const std::string& value) { + _internal_set_name(value); // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.name) } -#if LANG_CXX11 -inline void MethodDescriptorProto::set_name(::std::string&& value) { - set_has_name(); - name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* MethodDescriptorProto::mutable_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name) + return _internal_mutable_name(); +} +inline const std::string& MethodDescriptorProto::_internal_name() const { + return name_.Get(); +} +inline void MethodDescriptorProto::_internal_set_name(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void MethodDescriptorProto::set_name(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.name) } -#endif inline void MethodDescriptorProto::set_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name) } -inline void MethodDescriptorProto::set_name(const char* value, size_t size) { - set_has_name(); - name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void MethodDescriptorProto::set_name(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name) } -inline ::std::string* MethodDescriptorProto::mutable_name() { - set_has_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name) - return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* MethodDescriptorProto::_internal_mutable_name() { + _has_bits_[0] |= 0x00000001u; + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* MethodDescriptorProto::release_name() { +inline std::string* MethodDescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.name) - clear_has_name(); - return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_name()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void MethodDescriptorProto::set_allocated_name(::std::string* name) { - if (name != NULL) { - set_has_name(); +inline void MethodDescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_name(); + _has_bits_[0] &= ~0x00000001u; } - name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name) } // optional string input_type = 2; -inline bool MethodDescriptorProto::has_input_type() const { - return (_has_bits_[0] & 0x00000002u) != 0; +inline bool MethodDescriptorProto::_internal_has_input_type() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void MethodDescriptorProto::set_has_input_type() { - _has_bits_[0] |= 0x00000002u; -} -inline void MethodDescriptorProto::clear_has_input_type() { - _has_bits_[0] &= ~0x00000002u; +inline bool MethodDescriptorProto::has_input_type() const { + return _internal_has_input_type(); } inline void MethodDescriptorProto::clear_input_type() { - input_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_input_type(); + input_type_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000002u; } -inline const ::std::string& MethodDescriptorProto::input_type() const { +inline const std::string& MethodDescriptorProto::input_type() const { // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.input_type) - return input_type_.GetNoArena(); + return _internal_input_type(); } -inline void MethodDescriptorProto::set_input_type(const ::std::string& value) { - set_has_input_type(); - input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void MethodDescriptorProto::set_input_type(const std::string& value) { + _internal_set_input_type(value); // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.input_type) } -#if LANG_CXX11 -inline void MethodDescriptorProto::set_input_type(::std::string&& value) { - set_has_input_type(); - input_type_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* MethodDescriptorProto::mutable_input_type() { + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type) + return _internal_mutable_input_type(); +} +inline const std::string& MethodDescriptorProto::_internal_input_type() const { + return input_type_.Get(); +} +inline void MethodDescriptorProto::_internal_set_input_type(const std::string& value) { + _has_bits_[0] |= 0x00000002u; + input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void MethodDescriptorProto::set_input_type(std::string&& value) { + _has_bits_[0] |= 0x00000002u; + input_type_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.input_type) } -#endif inline void MethodDescriptorProto::set_input_type(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_input_type(); - input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000002u; + input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type) } -inline void MethodDescriptorProto::set_input_type(const char* value, size_t size) { - set_has_input_type(); - input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void MethodDescriptorProto::set_input_type(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000002u; + input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type) } -inline ::std::string* MethodDescriptorProto::mutable_input_type() { - set_has_input_type(); - // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type) - return input_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* MethodDescriptorProto::_internal_mutable_input_type() { + _has_bits_[0] |= 0x00000002u; + return input_type_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* MethodDescriptorProto::release_input_type() { +inline std::string* MethodDescriptorProto::release_input_type() { // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.input_type) - clear_has_input_type(); - return input_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_input_type()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000002u; + return input_type_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) { - if (input_type != NULL) { - set_has_input_type(); +inline void MethodDescriptorProto::set_allocated_input_type(std::string* input_type) { + if (input_type != nullptr) { + _has_bits_[0] |= 0x00000002u; } else { - clear_has_input_type(); + _has_bits_[0] &= ~0x00000002u; } - input_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), input_type); + input_type_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), input_type, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type) } // optional string output_type = 3; -inline bool MethodDescriptorProto::has_output_type() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -inline void MethodDescriptorProto::set_has_output_type() { - _has_bits_[0] |= 0x00000004u; +inline bool MethodDescriptorProto::_internal_has_output_type() const { + bool value = (_has_bits_[0] & 0x00000004u) != 0; + return value; } -inline void MethodDescriptorProto::clear_has_output_type() { - _has_bits_[0] &= ~0x00000004u; +inline bool MethodDescriptorProto::has_output_type() const { + return _internal_has_output_type(); } inline void MethodDescriptorProto::clear_output_type() { - output_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_output_type(); + output_type_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000004u; } -inline const ::std::string& MethodDescriptorProto::output_type() const { +inline const std::string& MethodDescriptorProto::output_type() const { // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.output_type) - return output_type_.GetNoArena(); + return _internal_output_type(); } -inline void MethodDescriptorProto::set_output_type(const ::std::string& value) { - set_has_output_type(); - output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void MethodDescriptorProto::set_output_type(const std::string& value) { + _internal_set_output_type(value); // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.output_type) } -#if LANG_CXX11 -inline void MethodDescriptorProto::set_output_type(::std::string&& value) { - set_has_output_type(); - output_type_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* MethodDescriptorProto::mutable_output_type() { + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type) + return _internal_mutable_output_type(); +} +inline const std::string& MethodDescriptorProto::_internal_output_type() const { + return output_type_.Get(); +} +inline void MethodDescriptorProto::_internal_set_output_type(const std::string& value) { + _has_bits_[0] |= 0x00000004u; + output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void MethodDescriptorProto::set_output_type(std::string&& value) { + _has_bits_[0] |= 0x00000004u; + output_type_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.output_type) } -#endif inline void MethodDescriptorProto::set_output_type(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_output_type(); - output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000004u; + output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type) } -inline void MethodDescriptorProto::set_output_type(const char* value, size_t size) { - set_has_output_type(); - output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void MethodDescriptorProto::set_output_type(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000004u; + output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type) } -inline ::std::string* MethodDescriptorProto::mutable_output_type() { - set_has_output_type(); - // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type) - return output_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* MethodDescriptorProto::_internal_mutable_output_type() { + _has_bits_[0] |= 0x00000004u; + return output_type_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* MethodDescriptorProto::release_output_type() { +inline std::string* MethodDescriptorProto::release_output_type() { // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.output_type) - clear_has_output_type(); - return output_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_output_type()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000004u; + return output_type_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) { - if (output_type != NULL) { - set_has_output_type(); +inline void MethodDescriptorProto::set_allocated_output_type(std::string* output_type) { + if (output_type != nullptr) { + _has_bits_[0] |= 0x00000004u; } else { - clear_has_output_type(); + _has_bits_[0] &= ~0x00000004u; } - output_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), output_type); + output_type_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), output_type, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type) } // optional .google.protobuf.MethodOptions options = 4; -inline bool MethodDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000008u) != 0; +inline bool MethodDescriptorProto::_internal_has_options() const { + bool value = (_has_bits_[0] & 0x00000008u) != 0; + PROTOBUF_ASSUME(!value || options_ != nullptr); + return value; } -inline void MethodDescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000008u; +inline bool MethodDescriptorProto::has_options() const { + return _internal_has_options(); } -inline void MethodDescriptorProto::clear_has_options() { +inline void MethodDescriptorProto::clear_options() { + if (options_ != nullptr) options_->Clear(); _has_bits_[0] &= ~0x00000008u; } -inline void MethodDescriptorProto::clear_options() { - if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear(); - clear_has_options(); +inline const PROTOBUF_NAMESPACE_ID::MethodOptions& MethodDescriptorProto::_internal_options() const { + const PROTOBUF_NAMESPACE_ID::MethodOptions* p = options_; + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_MethodOptions_default_instance_); } -inline const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const { - const ::google::protobuf::MethodOptions* p = options_; +inline const PROTOBUF_NAMESPACE_ID::MethodOptions& MethodDescriptorProto::options() const { // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options) - return p != NULL ? *p : *reinterpret_cast( - &::google::protobuf::_MethodOptions_default_instance_); + return _internal_options(); } -inline ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() { - set_has_options(); - if (options_ == NULL) { - options_ = new ::google::protobuf::MethodOptions; +inline void MethodDescriptorProto::unsafe_arena_set_allocated_options( + PROTOBUF_NAMESPACE_ID::MethodOptions* options) { + if (GetArena() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(options_); } - // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options) - return options_; + options_ = options; + if (options) { + _has_bits_[0] |= 0x00000008u; + } else { + _has_bits_[0] &= ~0x00000008u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.MethodDescriptorProto.options) } -inline ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() { +inline PROTOBUF_NAMESPACE_ID::MethodOptions* MethodDescriptorProto::release_options() { + _has_bits_[0] &= ~0x00000008u; + PROTOBUF_NAMESPACE_ID::MethodOptions* temp = options_; + options_ = nullptr; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + return temp; +} +inline PROTOBUF_NAMESPACE_ID::MethodOptions* MethodDescriptorProto::unsafe_arena_release_options() { // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.options) - clear_has_options(); - ::google::protobuf::MethodOptions* temp = options_; - options_ = NULL; + _has_bits_[0] &= ~0x00000008u; + PROTOBUF_NAMESPACE_ID::MethodOptions* temp = options_; + options_ = nullptr; return temp; } -inline void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) { - delete options_; - options_ = options; +inline PROTOBUF_NAMESPACE_ID::MethodOptions* MethodDescriptorProto::_internal_mutable_options() { + _has_bits_[0] |= 0x00000008u; + if (options_ == nullptr) { + auto* p = CreateMaybeMessage(GetArena()); + options_ = p; + } + return options_; +} +inline PROTOBUF_NAMESPACE_ID::MethodOptions* MethodDescriptorProto::mutable_options() { + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options) + return _internal_mutable_options(); +} +inline void MethodDescriptorProto::set_allocated_options(PROTOBUF_NAMESPACE_ID::MethodOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + if (message_arena == nullptr) { + delete options_; + } if (options) { - set_has_options(); + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _has_bits_[0] |= 0x00000008u; } else { - clear_has_options(); + _has_bits_[0] &= ~0x00000008u; } + options_ = options; // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.options) } // optional bool client_streaming = 5 [default = false]; -inline bool MethodDescriptorProto::has_client_streaming() const { - return (_has_bits_[0] & 0x00000010u) != 0; +inline bool MethodDescriptorProto::_internal_has_client_streaming() const { + bool value = (_has_bits_[0] & 0x00000010u) != 0; + return value; } -inline void MethodDescriptorProto::set_has_client_streaming() { - _has_bits_[0] |= 0x00000010u; -} -inline void MethodDescriptorProto::clear_has_client_streaming() { - _has_bits_[0] &= ~0x00000010u; +inline bool MethodDescriptorProto::has_client_streaming() const { + return _internal_has_client_streaming(); } inline void MethodDescriptorProto::clear_client_streaming() { client_streaming_ = false; - clear_has_client_streaming(); + _has_bits_[0] &= ~0x00000010u; +} +inline bool MethodDescriptorProto::_internal_client_streaming() const { + return client_streaming_; } inline bool MethodDescriptorProto::client_streaming() const { // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.client_streaming) - return client_streaming_; + return _internal_client_streaming(); } -inline void MethodDescriptorProto::set_client_streaming(bool value) { - set_has_client_streaming(); +inline void MethodDescriptorProto::_internal_set_client_streaming(bool value) { + _has_bits_[0] |= 0x00000010u; client_streaming_ = value; +} +inline void MethodDescriptorProto::set_client_streaming(bool value) { + _internal_set_client_streaming(value); // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.client_streaming) } // optional bool server_streaming = 6 [default = false]; -inline bool MethodDescriptorProto::has_server_streaming() const { - return (_has_bits_[0] & 0x00000020u) != 0; -} -inline void MethodDescriptorProto::set_has_server_streaming() { - _has_bits_[0] |= 0x00000020u; +inline bool MethodDescriptorProto::_internal_has_server_streaming() const { + bool value = (_has_bits_[0] & 0x00000020u) != 0; + return value; } -inline void MethodDescriptorProto::clear_has_server_streaming() { - _has_bits_[0] &= ~0x00000020u; +inline bool MethodDescriptorProto::has_server_streaming() const { + return _internal_has_server_streaming(); } inline void MethodDescriptorProto::clear_server_streaming() { server_streaming_ = false; - clear_has_server_streaming(); + _has_bits_[0] &= ~0x00000020u; +} +inline bool MethodDescriptorProto::_internal_server_streaming() const { + return server_streaming_; } inline bool MethodDescriptorProto::server_streaming() const { // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.server_streaming) - return server_streaming_; + return _internal_server_streaming(); } -inline void MethodDescriptorProto::set_server_streaming(bool value) { - set_has_server_streaming(); +inline void MethodDescriptorProto::_internal_set_server_streaming(bool value) { + _has_bits_[0] |= 0x00000020u; server_streaming_ = value; +} +inline void MethodDescriptorProto::set_server_streaming(bool value) { + _internal_set_server_streaming(value); // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.server_streaming) } @@ -7078,775 +9983,1050 @@ inline void MethodDescriptorProto::set_server_streaming(bool value) { // FileOptions // optional string java_package = 1; -inline bool FileOptions::has_java_package() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void FileOptions::set_has_java_package() { - _has_bits_[0] |= 0x00000001u; +inline bool FileOptions::_internal_has_java_package() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void FileOptions::clear_has_java_package() { - _has_bits_[0] &= ~0x00000001u; +inline bool FileOptions::has_java_package() const { + return _internal_has_java_package(); } inline void FileOptions::clear_java_package() { - java_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_java_package(); + java_package_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& FileOptions::java_package() const { +inline const std::string& FileOptions::java_package() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_package) - return java_package_.GetNoArena(); + return _internal_java_package(); } -inline void FileOptions::set_java_package(const ::std::string& value) { - set_has_java_package(); - java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FileOptions::set_java_package(const std::string& value) { + _internal_set_java_package(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_package) } -#if LANG_CXX11 -inline void FileOptions::set_java_package(::std::string&& value) { - set_has_java_package(); - java_package_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FileOptions::mutable_java_package() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package) + return _internal_mutable_java_package(); +} +inline const std::string& FileOptions::_internal_java_package() const { + return java_package_.Get(); +} +inline void FileOptions::_internal_set_java_package(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FileOptions::set_java_package(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + java_package_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.java_package) } -#endif inline void FileOptions::set_java_package(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_java_package(); - java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package) } -inline void FileOptions::set_java_package(const char* value, size_t size) { - set_has_java_package(); - java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FileOptions::set_java_package(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package) } -inline ::std::string* FileOptions::mutable_java_package() { - set_has_java_package(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package) - return java_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FileOptions::_internal_mutable_java_package() { + _has_bits_[0] |= 0x00000001u; + return java_package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FileOptions::release_java_package() { +inline std::string* FileOptions::release_java_package() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_package) - clear_has_java_package(); - return java_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_java_package()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return java_package_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FileOptions::set_allocated_java_package(::std::string* java_package) { - if (java_package != NULL) { - set_has_java_package(); +inline void FileOptions::set_allocated_java_package(std::string* java_package) { + if (java_package != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_java_package(); + _has_bits_[0] &= ~0x00000001u; } - java_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_package); + java_package_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), java_package, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package) } // optional string java_outer_classname = 8; -inline bool FileOptions::has_java_outer_classname() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -inline void FileOptions::set_has_java_outer_classname() { - _has_bits_[0] |= 0x00000002u; +inline bool FileOptions::_internal_has_java_outer_classname() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void FileOptions::clear_has_java_outer_classname() { - _has_bits_[0] &= ~0x00000002u; +inline bool FileOptions::has_java_outer_classname() const { + return _internal_has_java_outer_classname(); } inline void FileOptions::clear_java_outer_classname() { - java_outer_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_java_outer_classname(); + java_outer_classname_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000002u; } -inline const ::std::string& FileOptions::java_outer_classname() const { +inline const std::string& FileOptions::java_outer_classname() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_outer_classname) - return java_outer_classname_.GetNoArena(); + return _internal_java_outer_classname(); } -inline void FileOptions::set_java_outer_classname(const ::std::string& value) { - set_has_java_outer_classname(); - java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FileOptions::set_java_outer_classname(const std::string& value) { + _internal_set_java_outer_classname(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_outer_classname) } -#if LANG_CXX11 -inline void FileOptions::set_java_outer_classname(::std::string&& value) { - set_has_java_outer_classname(); - java_outer_classname_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FileOptions::mutable_java_outer_classname() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname) + return _internal_mutable_java_outer_classname(); +} +inline const std::string& FileOptions::_internal_java_outer_classname() const { + return java_outer_classname_.Get(); +} +inline void FileOptions::_internal_set_java_outer_classname(const std::string& value) { + _has_bits_[0] |= 0x00000002u; + java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FileOptions::set_java_outer_classname(std::string&& value) { + _has_bits_[0] |= 0x00000002u; + java_outer_classname_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.java_outer_classname) } -#endif inline void FileOptions::set_java_outer_classname(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_java_outer_classname(); - java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000002u; + java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_outer_classname) } -inline void FileOptions::set_java_outer_classname(const char* value, size_t size) { - set_has_java_outer_classname(); - java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FileOptions::set_java_outer_classname(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000002u; + java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname) } -inline ::std::string* FileOptions::mutable_java_outer_classname() { - set_has_java_outer_classname(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname) - return java_outer_classname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FileOptions::_internal_mutable_java_outer_classname() { + _has_bits_[0] |= 0x00000002u; + return java_outer_classname_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FileOptions::release_java_outer_classname() { +inline std::string* FileOptions::release_java_outer_classname() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_outer_classname) - clear_has_java_outer_classname(); - return java_outer_classname_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_java_outer_classname()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000002u; + return java_outer_classname_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) { - if (java_outer_classname != NULL) { - set_has_java_outer_classname(); +inline void FileOptions::set_allocated_java_outer_classname(std::string* java_outer_classname) { + if (java_outer_classname != nullptr) { + _has_bits_[0] |= 0x00000002u; } else { - clear_has_java_outer_classname(); + _has_bits_[0] &= ~0x00000002u; } - java_outer_classname_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_outer_classname); + java_outer_classname_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), java_outer_classname, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname) } // optional bool java_multiple_files = 10 [default = false]; -inline bool FileOptions::has_java_multiple_files() const { - return (_has_bits_[0] & 0x00000100u) != 0; +inline bool FileOptions::_internal_has_java_multiple_files() const { + bool value = (_has_bits_[0] & 0x00000400u) != 0; + return value; } -inline void FileOptions::set_has_java_multiple_files() { - _has_bits_[0] |= 0x00000100u; -} -inline void FileOptions::clear_has_java_multiple_files() { - _has_bits_[0] &= ~0x00000100u; +inline bool FileOptions::has_java_multiple_files() const { + return _internal_has_java_multiple_files(); } inline void FileOptions::clear_java_multiple_files() { java_multiple_files_ = false; - clear_has_java_multiple_files(); + _has_bits_[0] &= ~0x00000400u; +} +inline bool FileOptions::_internal_java_multiple_files() const { + return java_multiple_files_; } inline bool FileOptions::java_multiple_files() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_multiple_files) - return java_multiple_files_; + return _internal_java_multiple_files(); } -inline void FileOptions::set_java_multiple_files(bool value) { - set_has_java_multiple_files(); +inline void FileOptions::_internal_set_java_multiple_files(bool value) { + _has_bits_[0] |= 0x00000400u; java_multiple_files_ = value; +} +inline void FileOptions::set_java_multiple_files(bool value) { + _internal_set_java_multiple_files(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_multiple_files) } // optional bool java_generate_equals_and_hash = 20 [deprecated = true]; -inline bool FileOptions::has_java_generate_equals_and_hash() const { - return (_has_bits_[0] & 0x00000200u) != 0; -} -inline void FileOptions::set_has_java_generate_equals_and_hash() { - _has_bits_[0] |= 0x00000200u; +inline bool FileOptions::_internal_has_java_generate_equals_and_hash() const { + bool value = (_has_bits_[0] & 0x00000800u) != 0; + return value; } -inline void FileOptions::clear_has_java_generate_equals_and_hash() { - _has_bits_[0] &= ~0x00000200u; +inline bool FileOptions::has_java_generate_equals_and_hash() const { + return _internal_has_java_generate_equals_and_hash(); } inline void FileOptions::clear_java_generate_equals_and_hash() { java_generate_equals_and_hash_ = false; - clear_has_java_generate_equals_and_hash(); + _has_bits_[0] &= ~0x00000800u; +} +inline bool FileOptions::_internal_java_generate_equals_and_hash() const { + return java_generate_equals_and_hash_; } inline bool FileOptions::java_generate_equals_and_hash() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generate_equals_and_hash) - return java_generate_equals_and_hash_; + return _internal_java_generate_equals_and_hash(); } -inline void FileOptions::set_java_generate_equals_and_hash(bool value) { - set_has_java_generate_equals_and_hash(); +inline void FileOptions::_internal_set_java_generate_equals_and_hash(bool value) { + _has_bits_[0] |= 0x00000800u; java_generate_equals_and_hash_ = value; +} +inline void FileOptions::set_java_generate_equals_and_hash(bool value) { + _internal_set_java_generate_equals_and_hash(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generate_equals_and_hash) } // optional bool java_string_check_utf8 = 27 [default = false]; -inline bool FileOptions::has_java_string_check_utf8() const { - return (_has_bits_[0] & 0x00000400u) != 0; -} -inline void FileOptions::set_has_java_string_check_utf8() { - _has_bits_[0] |= 0x00000400u; +inline bool FileOptions::_internal_has_java_string_check_utf8() const { + bool value = (_has_bits_[0] & 0x00001000u) != 0; + return value; } -inline void FileOptions::clear_has_java_string_check_utf8() { - _has_bits_[0] &= ~0x00000400u; +inline bool FileOptions::has_java_string_check_utf8() const { + return _internal_has_java_string_check_utf8(); } inline void FileOptions::clear_java_string_check_utf8() { java_string_check_utf8_ = false; - clear_has_java_string_check_utf8(); + _has_bits_[0] &= ~0x00001000u; +} +inline bool FileOptions::_internal_java_string_check_utf8() const { + return java_string_check_utf8_; } inline bool FileOptions::java_string_check_utf8() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_string_check_utf8) - return java_string_check_utf8_; + return _internal_java_string_check_utf8(); } -inline void FileOptions::set_java_string_check_utf8(bool value) { - set_has_java_string_check_utf8(); +inline void FileOptions::_internal_set_java_string_check_utf8(bool value) { + _has_bits_[0] |= 0x00001000u; java_string_check_utf8_ = value; +} +inline void FileOptions::set_java_string_check_utf8(bool value) { + _internal_set_java_string_check_utf8(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_string_check_utf8) } // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; -inline bool FileOptions::has_optimize_for() const { - return (_has_bits_[0] & 0x00020000u) != 0; -} -inline void FileOptions::set_has_optimize_for() { - _has_bits_[0] |= 0x00020000u; +inline bool FileOptions::_internal_has_optimize_for() const { + bool value = (_has_bits_[0] & 0x00040000u) != 0; + return value; } -inline void FileOptions::clear_has_optimize_for() { - _has_bits_[0] &= ~0x00020000u; +inline bool FileOptions::has_optimize_for() const { + return _internal_has_optimize_for(); } inline void FileOptions::clear_optimize_for() { optimize_for_ = 1; - clear_has_optimize_for(); + _has_bits_[0] &= ~0x00040000u; +} +inline PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode FileOptions::_internal_optimize_for() const { + return static_cast< PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode >(optimize_for_); } -inline ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const { +inline PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode FileOptions::optimize_for() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.optimize_for) - return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_); + return _internal_optimize_for(); } -inline void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) { - assert(::google::protobuf::FileOptions_OptimizeMode_IsValid(value)); - set_has_optimize_for(); +inline void FileOptions::_internal_set_optimize_for(PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode value) { + assert(PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode_IsValid(value)); + _has_bits_[0] |= 0x00040000u; optimize_for_ = value; +} +inline void FileOptions::set_optimize_for(PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode value) { + _internal_set_optimize_for(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.optimize_for) } // optional string go_package = 11; -inline bool FileOptions::has_go_package() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -inline void FileOptions::set_has_go_package() { - _has_bits_[0] |= 0x00000004u; +inline bool FileOptions::_internal_has_go_package() const { + bool value = (_has_bits_[0] & 0x00000004u) != 0; + return value; } -inline void FileOptions::clear_has_go_package() { - _has_bits_[0] &= ~0x00000004u; +inline bool FileOptions::has_go_package() const { + return _internal_has_go_package(); } inline void FileOptions::clear_go_package() { - go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_go_package(); + go_package_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000004u; } -inline const ::std::string& FileOptions::go_package() const { +inline const std::string& FileOptions::go_package() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.go_package) - return go_package_.GetNoArena(); + return _internal_go_package(); } -inline void FileOptions::set_go_package(const ::std::string& value) { - set_has_go_package(); - go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FileOptions::set_go_package(const std::string& value) { + _internal_set_go_package(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package) } -#if LANG_CXX11 -inline void FileOptions::set_go_package(::std::string&& value) { - set_has_go_package(); - go_package_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FileOptions::mutable_go_package() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package) + return _internal_mutable_go_package(); +} +inline const std::string& FileOptions::_internal_go_package() const { + return go_package_.Get(); +} +inline void FileOptions::_internal_set_go_package(const std::string& value) { + _has_bits_[0] |= 0x00000004u; + go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FileOptions::set_go_package(std::string&& value) { + _has_bits_[0] |= 0x00000004u; + go_package_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.go_package) } -#endif inline void FileOptions::set_go_package(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_go_package(); - go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000004u; + go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package) } -inline void FileOptions::set_go_package(const char* value, size_t size) { - set_has_go_package(); - go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FileOptions::set_go_package(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000004u; + go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package) } -inline ::std::string* FileOptions::mutable_go_package() { - set_has_go_package(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package) - return go_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FileOptions::_internal_mutable_go_package() { + _has_bits_[0] |= 0x00000004u; + return go_package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FileOptions::release_go_package() { +inline std::string* FileOptions::release_go_package() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.go_package) - clear_has_go_package(); - return go_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_go_package()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000004u; + return go_package_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FileOptions::set_allocated_go_package(::std::string* go_package) { - if (go_package != NULL) { - set_has_go_package(); +inline void FileOptions::set_allocated_go_package(std::string* go_package) { + if (go_package != nullptr) { + _has_bits_[0] |= 0x00000004u; } else { - clear_has_go_package(); + _has_bits_[0] &= ~0x00000004u; } - go_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), go_package); + go_package_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), go_package, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package) } // optional bool cc_generic_services = 16 [default = false]; -inline bool FileOptions::has_cc_generic_services() const { - return (_has_bits_[0] & 0x00000800u) != 0; -} -inline void FileOptions::set_has_cc_generic_services() { - _has_bits_[0] |= 0x00000800u; +inline bool FileOptions::_internal_has_cc_generic_services() const { + bool value = (_has_bits_[0] & 0x00002000u) != 0; + return value; } -inline void FileOptions::clear_has_cc_generic_services() { - _has_bits_[0] &= ~0x00000800u; +inline bool FileOptions::has_cc_generic_services() const { + return _internal_has_cc_generic_services(); } inline void FileOptions::clear_cc_generic_services() { cc_generic_services_ = false; - clear_has_cc_generic_services(); + _has_bits_[0] &= ~0x00002000u; +} +inline bool FileOptions::_internal_cc_generic_services() const { + return cc_generic_services_; } inline bool FileOptions::cc_generic_services() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_generic_services) - return cc_generic_services_; + return _internal_cc_generic_services(); } -inline void FileOptions::set_cc_generic_services(bool value) { - set_has_cc_generic_services(); +inline void FileOptions::_internal_set_cc_generic_services(bool value) { + _has_bits_[0] |= 0x00002000u; cc_generic_services_ = value; +} +inline void FileOptions::set_cc_generic_services(bool value) { + _internal_set_cc_generic_services(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_generic_services) } // optional bool java_generic_services = 17 [default = false]; -inline bool FileOptions::has_java_generic_services() const { - return (_has_bits_[0] & 0x00001000u) != 0; -} -inline void FileOptions::set_has_java_generic_services() { - _has_bits_[0] |= 0x00001000u; +inline bool FileOptions::_internal_has_java_generic_services() const { + bool value = (_has_bits_[0] & 0x00004000u) != 0; + return value; } -inline void FileOptions::clear_has_java_generic_services() { - _has_bits_[0] &= ~0x00001000u; +inline bool FileOptions::has_java_generic_services() const { + return _internal_has_java_generic_services(); } inline void FileOptions::clear_java_generic_services() { java_generic_services_ = false; - clear_has_java_generic_services(); + _has_bits_[0] &= ~0x00004000u; +} +inline bool FileOptions::_internal_java_generic_services() const { + return java_generic_services_; } inline bool FileOptions::java_generic_services() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generic_services) - return java_generic_services_; + return _internal_java_generic_services(); } -inline void FileOptions::set_java_generic_services(bool value) { - set_has_java_generic_services(); +inline void FileOptions::_internal_set_java_generic_services(bool value) { + _has_bits_[0] |= 0x00004000u; java_generic_services_ = value; +} +inline void FileOptions::set_java_generic_services(bool value) { + _internal_set_java_generic_services(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generic_services) } // optional bool py_generic_services = 18 [default = false]; -inline bool FileOptions::has_py_generic_services() const { - return (_has_bits_[0] & 0x00002000u) != 0; -} -inline void FileOptions::set_has_py_generic_services() { - _has_bits_[0] |= 0x00002000u; +inline bool FileOptions::_internal_has_py_generic_services() const { + bool value = (_has_bits_[0] & 0x00008000u) != 0; + return value; } -inline void FileOptions::clear_has_py_generic_services() { - _has_bits_[0] &= ~0x00002000u; +inline bool FileOptions::has_py_generic_services() const { + return _internal_has_py_generic_services(); } inline void FileOptions::clear_py_generic_services() { py_generic_services_ = false; - clear_has_py_generic_services(); + _has_bits_[0] &= ~0x00008000u; +} +inline bool FileOptions::_internal_py_generic_services() const { + return py_generic_services_; } inline bool FileOptions::py_generic_services() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.py_generic_services) - return py_generic_services_; + return _internal_py_generic_services(); } -inline void FileOptions::set_py_generic_services(bool value) { - set_has_py_generic_services(); +inline void FileOptions::_internal_set_py_generic_services(bool value) { + _has_bits_[0] |= 0x00008000u; py_generic_services_ = value; +} +inline void FileOptions::set_py_generic_services(bool value) { + _internal_set_py_generic_services(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.py_generic_services) } -// optional bool php_generic_services = 19 [default = false]; -inline bool FileOptions::has_php_generic_services() const { - return (_has_bits_[0] & 0x00004000u) != 0; +// optional bool php_generic_services = 42 [default = false]; +inline bool FileOptions::_internal_has_php_generic_services() const { + bool value = (_has_bits_[0] & 0x00010000u) != 0; + return value; } -inline void FileOptions::set_has_php_generic_services() { - _has_bits_[0] |= 0x00004000u; -} -inline void FileOptions::clear_has_php_generic_services() { - _has_bits_[0] &= ~0x00004000u; +inline bool FileOptions::has_php_generic_services() const { + return _internal_has_php_generic_services(); } inline void FileOptions::clear_php_generic_services() { php_generic_services_ = false; - clear_has_php_generic_services(); + _has_bits_[0] &= ~0x00010000u; +} +inline bool FileOptions::_internal_php_generic_services() const { + return php_generic_services_; } inline bool FileOptions::php_generic_services() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_generic_services) - return php_generic_services_; + return _internal_php_generic_services(); } -inline void FileOptions::set_php_generic_services(bool value) { - set_has_php_generic_services(); +inline void FileOptions::_internal_set_php_generic_services(bool value) { + _has_bits_[0] |= 0x00010000u; php_generic_services_ = value; +} +inline void FileOptions::set_php_generic_services(bool value) { + _internal_set_php_generic_services(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_generic_services) } // optional bool deprecated = 23 [default = false]; -inline bool FileOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00008000u) != 0; -} -inline void FileOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00008000u; +inline bool FileOptions::_internal_has_deprecated() const { + bool value = (_has_bits_[0] & 0x00020000u) != 0; + return value; } -inline void FileOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00008000u; +inline bool FileOptions::has_deprecated() const { + return _internal_has_deprecated(); } inline void FileOptions::clear_deprecated() { deprecated_ = false; - clear_has_deprecated(); + _has_bits_[0] &= ~0x00020000u; +} +inline bool FileOptions::_internal_deprecated() const { + return deprecated_; } inline bool FileOptions::deprecated() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.deprecated) - return deprecated_; + return _internal_deprecated(); } -inline void FileOptions::set_deprecated(bool value) { - set_has_deprecated(); +inline void FileOptions::_internal_set_deprecated(bool value) { + _has_bits_[0] |= 0x00020000u; deprecated_ = value; +} +inline void FileOptions::set_deprecated(bool value) { + _internal_set_deprecated(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.deprecated) } -// optional bool cc_enable_arenas = 31 [default = false]; -inline bool FileOptions::has_cc_enable_arenas() const { - return (_has_bits_[0] & 0x00010000u) != 0; -} -inline void FileOptions::set_has_cc_enable_arenas() { - _has_bits_[0] |= 0x00010000u; +// optional bool cc_enable_arenas = 31 [default = true]; +inline bool FileOptions::_internal_has_cc_enable_arenas() const { + bool value = (_has_bits_[0] & 0x00080000u) != 0; + return value; } -inline void FileOptions::clear_has_cc_enable_arenas() { - _has_bits_[0] &= ~0x00010000u; +inline bool FileOptions::has_cc_enable_arenas() const { + return _internal_has_cc_enable_arenas(); } inline void FileOptions::clear_cc_enable_arenas() { - cc_enable_arenas_ = false; - clear_has_cc_enable_arenas(); + cc_enable_arenas_ = true; + _has_bits_[0] &= ~0x00080000u; +} +inline bool FileOptions::_internal_cc_enable_arenas() const { + return cc_enable_arenas_; } inline bool FileOptions::cc_enable_arenas() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_enable_arenas) - return cc_enable_arenas_; + return _internal_cc_enable_arenas(); } -inline void FileOptions::set_cc_enable_arenas(bool value) { - set_has_cc_enable_arenas(); +inline void FileOptions::_internal_set_cc_enable_arenas(bool value) { + _has_bits_[0] |= 0x00080000u; cc_enable_arenas_ = value; +} +inline void FileOptions::set_cc_enable_arenas(bool value) { + _internal_set_cc_enable_arenas(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas) } // optional string objc_class_prefix = 36; -inline bool FileOptions::has_objc_class_prefix() const { - return (_has_bits_[0] & 0x00000008u) != 0; -} -inline void FileOptions::set_has_objc_class_prefix() { - _has_bits_[0] |= 0x00000008u; +inline bool FileOptions::_internal_has_objc_class_prefix() const { + bool value = (_has_bits_[0] & 0x00000008u) != 0; + return value; } -inline void FileOptions::clear_has_objc_class_prefix() { - _has_bits_[0] &= ~0x00000008u; +inline bool FileOptions::has_objc_class_prefix() const { + return _internal_has_objc_class_prefix(); } inline void FileOptions::clear_objc_class_prefix() { - objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_objc_class_prefix(); + objc_class_prefix_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000008u; } -inline const ::std::string& FileOptions::objc_class_prefix() const { +inline const std::string& FileOptions::objc_class_prefix() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix) - return objc_class_prefix_.GetNoArena(); + return _internal_objc_class_prefix(); } -inline void FileOptions::set_objc_class_prefix(const ::std::string& value) { - set_has_objc_class_prefix(); - objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FileOptions::set_objc_class_prefix(const std::string& value) { + _internal_set_objc_class_prefix(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix) } -#if LANG_CXX11 -inline void FileOptions::set_objc_class_prefix(::std::string&& value) { - set_has_objc_class_prefix(); - objc_class_prefix_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FileOptions::mutable_objc_class_prefix() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix) + return _internal_mutable_objc_class_prefix(); +} +inline const std::string& FileOptions::_internal_objc_class_prefix() const { + return objc_class_prefix_.Get(); +} +inline void FileOptions::_internal_set_objc_class_prefix(const std::string& value) { + _has_bits_[0] |= 0x00000008u; + objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FileOptions::set_objc_class_prefix(std::string&& value) { + _has_bits_[0] |= 0x00000008u; + objc_class_prefix_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.objc_class_prefix) } -#endif inline void FileOptions::set_objc_class_prefix(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_objc_class_prefix(); - objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000008u; + objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix) } -inline void FileOptions::set_objc_class_prefix(const char* value, size_t size) { - set_has_objc_class_prefix(); - objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FileOptions::set_objc_class_prefix(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000008u; + objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix) } -inline ::std::string* FileOptions::mutable_objc_class_prefix() { - set_has_objc_class_prefix(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix) - return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FileOptions::_internal_mutable_objc_class_prefix() { + _has_bits_[0] |= 0x00000008u; + return objc_class_prefix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FileOptions::release_objc_class_prefix() { +inline std::string* FileOptions::release_objc_class_prefix() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.objc_class_prefix) - clear_has_objc_class_prefix(); - return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_objc_class_prefix()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000008u; + return objc_class_prefix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_class_prefix) { - if (objc_class_prefix != NULL) { - set_has_objc_class_prefix(); +inline void FileOptions::set_allocated_objc_class_prefix(std::string* objc_class_prefix) { + if (objc_class_prefix != nullptr) { + _has_bits_[0] |= 0x00000008u; } else { - clear_has_objc_class_prefix(); + _has_bits_[0] &= ~0x00000008u; } - objc_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), objc_class_prefix); + objc_class_prefix_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), objc_class_prefix, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix) } // optional string csharp_namespace = 37; -inline bool FileOptions::has_csharp_namespace() const { - return (_has_bits_[0] & 0x00000010u) != 0; +inline bool FileOptions::_internal_has_csharp_namespace() const { + bool value = (_has_bits_[0] & 0x00000010u) != 0; + return value; } -inline void FileOptions::set_has_csharp_namespace() { - _has_bits_[0] |= 0x00000010u; -} -inline void FileOptions::clear_has_csharp_namespace() { - _has_bits_[0] &= ~0x00000010u; +inline bool FileOptions::has_csharp_namespace() const { + return _internal_has_csharp_namespace(); } inline void FileOptions::clear_csharp_namespace() { - csharp_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_csharp_namespace(); + csharp_namespace_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000010u; } -inline const ::std::string& FileOptions::csharp_namespace() const { +inline const std::string& FileOptions::csharp_namespace() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_namespace) - return csharp_namespace_.GetNoArena(); + return _internal_csharp_namespace(); } -inline void FileOptions::set_csharp_namespace(const ::std::string& value) { - set_has_csharp_namespace(); - csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FileOptions::set_csharp_namespace(const std::string& value) { + _internal_set_csharp_namespace(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_namespace) } -#if LANG_CXX11 -inline void FileOptions::set_csharp_namespace(::std::string&& value) { - set_has_csharp_namespace(); - csharp_namespace_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FileOptions::mutable_csharp_namespace() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_namespace) + return _internal_mutable_csharp_namespace(); +} +inline const std::string& FileOptions::_internal_csharp_namespace() const { + return csharp_namespace_.Get(); +} +inline void FileOptions::_internal_set_csharp_namespace(const std::string& value) { + _has_bits_[0] |= 0x00000010u; + csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FileOptions::set_csharp_namespace(std::string&& value) { + _has_bits_[0] |= 0x00000010u; + csharp_namespace_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.csharp_namespace) } -#endif inline void FileOptions::set_csharp_namespace(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_csharp_namespace(); - csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000010u; + csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_namespace) } -inline void FileOptions::set_csharp_namespace(const char* value, size_t size) { - set_has_csharp_namespace(); - csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FileOptions::set_csharp_namespace(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000010u; + csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_namespace) } -inline ::std::string* FileOptions::mutable_csharp_namespace() { - set_has_csharp_namespace(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_namespace) - return csharp_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FileOptions::_internal_mutable_csharp_namespace() { + _has_bits_[0] |= 0x00000010u; + return csharp_namespace_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FileOptions::release_csharp_namespace() { +inline std::string* FileOptions::release_csharp_namespace() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.csharp_namespace) - clear_has_csharp_namespace(); - return csharp_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_csharp_namespace()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000010u; + return csharp_namespace_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FileOptions::set_allocated_csharp_namespace(::std::string* csharp_namespace) { - if (csharp_namespace != NULL) { - set_has_csharp_namespace(); +inline void FileOptions::set_allocated_csharp_namespace(std::string* csharp_namespace) { + if (csharp_namespace != nullptr) { + _has_bits_[0] |= 0x00000010u; } else { - clear_has_csharp_namespace(); + _has_bits_[0] &= ~0x00000010u; } - csharp_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_namespace); + csharp_namespace_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), csharp_namespace, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace) } // optional string swift_prefix = 39; -inline bool FileOptions::has_swift_prefix() const { - return (_has_bits_[0] & 0x00000020u) != 0; -} -inline void FileOptions::set_has_swift_prefix() { - _has_bits_[0] |= 0x00000020u; +inline bool FileOptions::_internal_has_swift_prefix() const { + bool value = (_has_bits_[0] & 0x00000020u) != 0; + return value; } -inline void FileOptions::clear_has_swift_prefix() { - _has_bits_[0] &= ~0x00000020u; +inline bool FileOptions::has_swift_prefix() const { + return _internal_has_swift_prefix(); } inline void FileOptions::clear_swift_prefix() { - swift_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_swift_prefix(); + swift_prefix_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000020u; } -inline const ::std::string& FileOptions::swift_prefix() const { +inline const std::string& FileOptions::swift_prefix() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.swift_prefix) - return swift_prefix_.GetNoArena(); + return _internal_swift_prefix(); } -inline void FileOptions::set_swift_prefix(const ::std::string& value) { - set_has_swift_prefix(); - swift_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FileOptions::set_swift_prefix(const std::string& value) { + _internal_set_swift_prefix(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.swift_prefix) } -#if LANG_CXX11 -inline void FileOptions::set_swift_prefix(::std::string&& value) { - set_has_swift_prefix(); - swift_prefix_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FileOptions::mutable_swift_prefix() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.swift_prefix) + return _internal_mutable_swift_prefix(); +} +inline const std::string& FileOptions::_internal_swift_prefix() const { + return swift_prefix_.Get(); +} +inline void FileOptions::_internal_set_swift_prefix(const std::string& value) { + _has_bits_[0] |= 0x00000020u; + swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FileOptions::set_swift_prefix(std::string&& value) { + _has_bits_[0] |= 0x00000020u; + swift_prefix_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.swift_prefix) } -#endif inline void FileOptions::set_swift_prefix(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_swift_prefix(); - swift_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000020u; + swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.swift_prefix) } -inline void FileOptions::set_swift_prefix(const char* value, size_t size) { - set_has_swift_prefix(); - swift_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FileOptions::set_swift_prefix(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000020u; + swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.swift_prefix) } -inline ::std::string* FileOptions::mutable_swift_prefix() { - set_has_swift_prefix(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.swift_prefix) - return swift_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FileOptions::_internal_mutable_swift_prefix() { + _has_bits_[0] |= 0x00000020u; + return swift_prefix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FileOptions::release_swift_prefix() { +inline std::string* FileOptions::release_swift_prefix() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.swift_prefix) - clear_has_swift_prefix(); - return swift_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_swift_prefix()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000020u; + return swift_prefix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FileOptions::set_allocated_swift_prefix(::std::string* swift_prefix) { - if (swift_prefix != NULL) { - set_has_swift_prefix(); +inline void FileOptions::set_allocated_swift_prefix(std::string* swift_prefix) { + if (swift_prefix != nullptr) { + _has_bits_[0] |= 0x00000020u; } else { - clear_has_swift_prefix(); + _has_bits_[0] &= ~0x00000020u; } - swift_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), swift_prefix); + swift_prefix_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), swift_prefix, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.swift_prefix) } // optional string php_class_prefix = 40; -inline bool FileOptions::has_php_class_prefix() const { - return (_has_bits_[0] & 0x00000040u) != 0; -} -inline void FileOptions::set_has_php_class_prefix() { - _has_bits_[0] |= 0x00000040u; +inline bool FileOptions::_internal_has_php_class_prefix() const { + bool value = (_has_bits_[0] & 0x00000040u) != 0; + return value; } -inline void FileOptions::clear_has_php_class_prefix() { - _has_bits_[0] &= ~0x00000040u; +inline bool FileOptions::has_php_class_prefix() const { + return _internal_has_php_class_prefix(); } inline void FileOptions::clear_php_class_prefix() { - php_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_php_class_prefix(); + php_class_prefix_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000040u; } -inline const ::std::string& FileOptions::php_class_prefix() const { +inline const std::string& FileOptions::php_class_prefix() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_class_prefix) - return php_class_prefix_.GetNoArena(); + return _internal_php_class_prefix(); } -inline void FileOptions::set_php_class_prefix(const ::std::string& value) { - set_has_php_class_prefix(); - php_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FileOptions::set_php_class_prefix(const std::string& value) { + _internal_set_php_class_prefix(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_class_prefix) } -#if LANG_CXX11 -inline void FileOptions::set_php_class_prefix(::std::string&& value) { - set_has_php_class_prefix(); - php_class_prefix_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FileOptions::mutable_php_class_prefix() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_class_prefix) + return _internal_mutable_php_class_prefix(); +} +inline const std::string& FileOptions::_internal_php_class_prefix() const { + return php_class_prefix_.Get(); +} +inline void FileOptions::_internal_set_php_class_prefix(const std::string& value) { + _has_bits_[0] |= 0x00000040u; + php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FileOptions::set_php_class_prefix(std::string&& value) { + _has_bits_[0] |= 0x00000040u; + php_class_prefix_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_class_prefix) } -#endif inline void FileOptions::set_php_class_prefix(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_php_class_prefix(); - php_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000040u; + php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_class_prefix) } -inline void FileOptions::set_php_class_prefix(const char* value, size_t size) { - set_has_php_class_prefix(); - php_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FileOptions::set_php_class_prefix(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000040u; + php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_class_prefix) } -inline ::std::string* FileOptions::mutable_php_class_prefix() { - set_has_php_class_prefix(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_class_prefix) - return php_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FileOptions::_internal_mutable_php_class_prefix() { + _has_bits_[0] |= 0x00000040u; + return php_class_prefix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FileOptions::release_php_class_prefix() { +inline std::string* FileOptions::release_php_class_prefix() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_class_prefix) - clear_has_php_class_prefix(); - return php_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_php_class_prefix()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000040u; + return php_class_prefix_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FileOptions::set_allocated_php_class_prefix(::std::string* php_class_prefix) { - if (php_class_prefix != NULL) { - set_has_php_class_prefix(); +inline void FileOptions::set_allocated_php_class_prefix(std::string* php_class_prefix) { + if (php_class_prefix != nullptr) { + _has_bits_[0] |= 0x00000040u; } else { - clear_has_php_class_prefix(); + _has_bits_[0] &= ~0x00000040u; } - php_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), php_class_prefix); + php_class_prefix_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), php_class_prefix, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_class_prefix) } // optional string php_namespace = 41; -inline bool FileOptions::has_php_namespace() const { - return (_has_bits_[0] & 0x00000080u) != 0; -} -inline void FileOptions::set_has_php_namespace() { - _has_bits_[0] |= 0x00000080u; +inline bool FileOptions::_internal_has_php_namespace() const { + bool value = (_has_bits_[0] & 0x00000080u) != 0; + return value; } -inline void FileOptions::clear_has_php_namespace() { - _has_bits_[0] &= ~0x00000080u; +inline bool FileOptions::has_php_namespace() const { + return _internal_has_php_namespace(); } inline void FileOptions::clear_php_namespace() { - php_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_php_namespace(); + php_namespace_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000080u; } -inline const ::std::string& FileOptions::php_namespace() const { +inline const std::string& FileOptions::php_namespace() const { // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_namespace) - return php_namespace_.GetNoArena(); + return _internal_php_namespace(); } -inline void FileOptions::set_php_namespace(const ::std::string& value) { - set_has_php_namespace(); - php_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void FileOptions::set_php_namespace(const std::string& value) { + _internal_set_php_namespace(value); // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_namespace) } -#if LANG_CXX11 -inline void FileOptions::set_php_namespace(::std::string&& value) { - set_has_php_namespace(); - php_namespace_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* FileOptions::mutable_php_namespace() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_namespace) + return _internal_mutable_php_namespace(); +} +inline const std::string& FileOptions::_internal_php_namespace() const { + return php_namespace_.Get(); +} +inline void FileOptions::_internal_set_php_namespace(const std::string& value) { + _has_bits_[0] |= 0x00000080u; + php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FileOptions::set_php_namespace(std::string&& value) { + _has_bits_[0] |= 0x00000080u; + php_namespace_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_namespace) } -#endif inline void FileOptions::set_php_namespace(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_php_namespace(); - php_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000080u; + php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_namespace) } -inline void FileOptions::set_php_namespace(const char* value, size_t size) { - set_has_php_namespace(); - php_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void FileOptions::set_php_namespace(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000080u; + php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_namespace) } -inline ::std::string* FileOptions::mutable_php_namespace() { - set_has_php_namespace(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_namespace) - return php_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* FileOptions::_internal_mutable_php_namespace() { + _has_bits_[0] |= 0x00000080u; + return php_namespace_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* FileOptions::release_php_namespace() { +inline std::string* FileOptions::release_php_namespace() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_namespace) - clear_has_php_namespace(); - return php_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_php_namespace()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000080u; + return php_namespace_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void FileOptions::set_allocated_php_namespace(::std::string* php_namespace) { - if (php_namespace != NULL) { - set_has_php_namespace(); +inline void FileOptions::set_allocated_php_namespace(std::string* php_namespace) { + if (php_namespace != nullptr) { + _has_bits_[0] |= 0x00000080u; } else { - clear_has_php_namespace(); + _has_bits_[0] &= ~0x00000080u; } - php_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), php_namespace); + php_namespace_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), php_namespace, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_namespace) } +// optional string php_metadata_namespace = 44; +inline bool FileOptions::_internal_has_php_metadata_namespace() const { + bool value = (_has_bits_[0] & 0x00000100u) != 0; + return value; +} +inline bool FileOptions::has_php_metadata_namespace() const { + return _internal_has_php_metadata_namespace(); +} +inline void FileOptions::clear_php_metadata_namespace() { + php_metadata_namespace_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000100u; +} +inline const std::string& FileOptions::php_metadata_namespace() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_metadata_namespace) + return _internal_php_metadata_namespace(); +} +inline void FileOptions::set_php_metadata_namespace(const std::string& value) { + _internal_set_php_metadata_namespace(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_metadata_namespace) +} +inline std::string* FileOptions::mutable_php_metadata_namespace() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_metadata_namespace) + return _internal_mutable_php_metadata_namespace(); +} +inline const std::string& FileOptions::_internal_php_metadata_namespace() const { + return php_metadata_namespace_.Get(); +} +inline void FileOptions::_internal_set_php_metadata_namespace(const std::string& value) { + _has_bits_[0] |= 0x00000100u; + php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FileOptions::set_php_metadata_namespace(std::string&& value) { + _has_bits_[0] |= 0x00000100u; + php_metadata_namespace_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_metadata_namespace) +} +inline void FileOptions::set_php_metadata_namespace(const char* value) { + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000100u; + php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_metadata_namespace) +} +inline void FileOptions::set_php_metadata_namespace(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000100u; + php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_metadata_namespace) +} +inline std::string* FileOptions::_internal_mutable_php_metadata_namespace() { + _has_bits_[0] |= 0x00000100u; + return php_metadata_namespace_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); +} +inline std::string* FileOptions::release_php_metadata_namespace() { + // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_metadata_namespace) + if (!_internal_has_php_metadata_namespace()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000100u; + return php_metadata_namespace_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void FileOptions::set_allocated_php_metadata_namespace(std::string* php_metadata_namespace) { + if (php_metadata_namespace != nullptr) { + _has_bits_[0] |= 0x00000100u; + } else { + _has_bits_[0] &= ~0x00000100u; + } + php_metadata_namespace_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), php_metadata_namespace, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_metadata_namespace) +} + +// optional string ruby_package = 45; +inline bool FileOptions::_internal_has_ruby_package() const { + bool value = (_has_bits_[0] & 0x00000200u) != 0; + return value; +} +inline bool FileOptions::has_ruby_package() const { + return _internal_has_ruby_package(); +} +inline void FileOptions::clear_ruby_package() { + ruby_package_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000200u; +} +inline const std::string& FileOptions::ruby_package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.ruby_package) + return _internal_ruby_package(); +} +inline void FileOptions::set_ruby_package(const std::string& value) { + _internal_set_ruby_package(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.ruby_package) +} +inline std::string* FileOptions::mutable_ruby_package() { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.ruby_package) + return _internal_mutable_ruby_package(); +} +inline const std::string& FileOptions::_internal_ruby_package() const { + return ruby_package_.Get(); +} +inline void FileOptions::_internal_set_ruby_package(const std::string& value) { + _has_bits_[0] |= 0x00000200u; + ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void FileOptions::set_ruby_package(std::string&& value) { + _has_bits_[0] |= 0x00000200u; + ruby_package_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.ruby_package) +} +inline void FileOptions::set_ruby_package(const char* value) { + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000200u; + ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.ruby_package) +} +inline void FileOptions::set_ruby_package(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000200u; + ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.ruby_package) +} +inline std::string* FileOptions::_internal_mutable_ruby_package() { + _has_bits_[0] |= 0x00000200u; + return ruby_package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); +} +inline std::string* FileOptions::release_ruby_package() { + // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.ruby_package) + if (!_internal_has_ruby_package()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000200u; + return ruby_package_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void FileOptions::set_allocated_ruby_package(std::string* ruby_package) { + if (ruby_package != nullptr) { + _has_bits_[0] |= 0x00000200u; + } else { + _has_bits_[0] &= ~0x00000200u; + } + ruby_package_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ruby_package, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.ruby_package) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -inline int FileOptions::uninterpreted_option_size() const { +inline int FileOptions::_internal_uninterpreted_option_size() const { return uninterpreted_option_.size(); } +inline int FileOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} inline void FileOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } -inline const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -inline ::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) { +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } -inline ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* FileOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option) return &uninterpreted_option_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& FileOptions::_internal_uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& FileOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* FileOptions::_internal_add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* FileOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option) + return _internal_add_uninterpreted_option(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& FileOptions::uninterpreted_option() const { // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option) return uninterpreted_option_; @@ -7857,126 +11037,151 @@ FileOptions::uninterpreted_option() const { // MessageOptions // optional bool message_set_wire_format = 1 [default = false]; -inline bool MessageOptions::has_message_set_wire_format() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void MessageOptions::set_has_message_set_wire_format() { - _has_bits_[0] |= 0x00000001u; +inline bool MessageOptions::_internal_has_message_set_wire_format() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void MessageOptions::clear_has_message_set_wire_format() { - _has_bits_[0] &= ~0x00000001u; +inline bool MessageOptions::has_message_set_wire_format() const { + return _internal_has_message_set_wire_format(); } inline void MessageOptions::clear_message_set_wire_format() { message_set_wire_format_ = false; - clear_has_message_set_wire_format(); + _has_bits_[0] &= ~0x00000001u; +} +inline bool MessageOptions::_internal_message_set_wire_format() const { + return message_set_wire_format_; } inline bool MessageOptions::message_set_wire_format() const { // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.message_set_wire_format) - return message_set_wire_format_; + return _internal_message_set_wire_format(); } -inline void MessageOptions::set_message_set_wire_format(bool value) { - set_has_message_set_wire_format(); +inline void MessageOptions::_internal_set_message_set_wire_format(bool value) { + _has_bits_[0] |= 0x00000001u; message_set_wire_format_ = value; +} +inline void MessageOptions::set_message_set_wire_format(bool value) { + _internal_set_message_set_wire_format(value); // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.message_set_wire_format) } // optional bool no_standard_descriptor_accessor = 2 [default = false]; -inline bool MessageOptions::has_no_standard_descriptor_accessor() const { - return (_has_bits_[0] & 0x00000002u) != 0; +inline bool MessageOptions::_internal_has_no_standard_descriptor_accessor() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void MessageOptions::set_has_no_standard_descriptor_accessor() { - _has_bits_[0] |= 0x00000002u; -} -inline void MessageOptions::clear_has_no_standard_descriptor_accessor() { - _has_bits_[0] &= ~0x00000002u; +inline bool MessageOptions::has_no_standard_descriptor_accessor() const { + return _internal_has_no_standard_descriptor_accessor(); } inline void MessageOptions::clear_no_standard_descriptor_accessor() { no_standard_descriptor_accessor_ = false; - clear_has_no_standard_descriptor_accessor(); + _has_bits_[0] &= ~0x00000002u; +} +inline bool MessageOptions::_internal_no_standard_descriptor_accessor() const { + return no_standard_descriptor_accessor_; } inline bool MessageOptions::no_standard_descriptor_accessor() const { // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.no_standard_descriptor_accessor) - return no_standard_descriptor_accessor_; + return _internal_no_standard_descriptor_accessor(); } -inline void MessageOptions::set_no_standard_descriptor_accessor(bool value) { - set_has_no_standard_descriptor_accessor(); +inline void MessageOptions::_internal_set_no_standard_descriptor_accessor(bool value) { + _has_bits_[0] |= 0x00000002u; no_standard_descriptor_accessor_ = value; +} +inline void MessageOptions::set_no_standard_descriptor_accessor(bool value) { + _internal_set_no_standard_descriptor_accessor(value); // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.no_standard_descriptor_accessor) } // optional bool deprecated = 3 [default = false]; -inline bool MessageOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -inline void MessageOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00000004u; +inline bool MessageOptions::_internal_has_deprecated() const { + bool value = (_has_bits_[0] & 0x00000004u) != 0; + return value; } -inline void MessageOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00000004u; +inline bool MessageOptions::has_deprecated() const { + return _internal_has_deprecated(); } inline void MessageOptions::clear_deprecated() { deprecated_ = false; - clear_has_deprecated(); + _has_bits_[0] &= ~0x00000004u; +} +inline bool MessageOptions::_internal_deprecated() const { + return deprecated_; } inline bool MessageOptions::deprecated() const { // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.deprecated) - return deprecated_; + return _internal_deprecated(); } -inline void MessageOptions::set_deprecated(bool value) { - set_has_deprecated(); +inline void MessageOptions::_internal_set_deprecated(bool value) { + _has_bits_[0] |= 0x00000004u; deprecated_ = value; +} +inline void MessageOptions::set_deprecated(bool value) { + _internal_set_deprecated(value); // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.deprecated) } // optional bool map_entry = 7; -inline bool MessageOptions::has_map_entry() const { - return (_has_bits_[0] & 0x00000008u) != 0; -} -inline void MessageOptions::set_has_map_entry() { - _has_bits_[0] |= 0x00000008u; +inline bool MessageOptions::_internal_has_map_entry() const { + bool value = (_has_bits_[0] & 0x00000008u) != 0; + return value; } -inline void MessageOptions::clear_has_map_entry() { - _has_bits_[0] &= ~0x00000008u; +inline bool MessageOptions::has_map_entry() const { + return _internal_has_map_entry(); } inline void MessageOptions::clear_map_entry() { map_entry_ = false; - clear_has_map_entry(); + _has_bits_[0] &= ~0x00000008u; +} +inline bool MessageOptions::_internal_map_entry() const { + return map_entry_; } inline bool MessageOptions::map_entry() const { // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.map_entry) - return map_entry_; + return _internal_map_entry(); } -inline void MessageOptions::set_map_entry(bool value) { - set_has_map_entry(); +inline void MessageOptions::_internal_set_map_entry(bool value) { + _has_bits_[0] |= 0x00000008u; map_entry_ = value; +} +inline void MessageOptions::set_map_entry(bool value) { + _internal_set_map_entry(value); // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.map_entry) } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -inline int MessageOptions::uninterpreted_option_size() const { +inline int MessageOptions::_internal_uninterpreted_option_size() const { return uninterpreted_option_.size(); } +inline int MessageOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} inline void MessageOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } -inline const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -inline ::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) { +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.MessageOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } -inline ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* MessageOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option) return &uninterpreted_option_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& MessageOptions::_internal_uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* MessageOptions::_internal_add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* MessageOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option) + return _internal_add_uninterpreted_option(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& MessageOptions::uninterpreted_option() const { // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option) return uninterpreted_option_; @@ -7987,176 +11192,209 @@ MessageOptions::uninterpreted_option() const { // FieldOptions // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; -inline bool FieldOptions::has_ctype() const { - return (_has_bits_[0] & 0x00000001u) != 0; +inline bool FieldOptions::_internal_has_ctype() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void FieldOptions::set_has_ctype() { - _has_bits_[0] |= 0x00000001u; -} -inline void FieldOptions::clear_has_ctype() { - _has_bits_[0] &= ~0x00000001u; +inline bool FieldOptions::has_ctype() const { + return _internal_has_ctype(); } inline void FieldOptions::clear_ctype() { ctype_ = 0; - clear_has_ctype(); + _has_bits_[0] &= ~0x00000001u; +} +inline PROTOBUF_NAMESPACE_ID::FieldOptions_CType FieldOptions::_internal_ctype() const { + return static_cast< PROTOBUF_NAMESPACE_ID::FieldOptions_CType >(ctype_); } -inline ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const { +inline PROTOBUF_NAMESPACE_ID::FieldOptions_CType FieldOptions::ctype() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.ctype) - return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_); + return _internal_ctype(); } -inline void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) { - assert(::google::protobuf::FieldOptions_CType_IsValid(value)); - set_has_ctype(); +inline void FieldOptions::_internal_set_ctype(PROTOBUF_NAMESPACE_ID::FieldOptions_CType value) { + assert(PROTOBUF_NAMESPACE_ID::FieldOptions_CType_IsValid(value)); + _has_bits_[0] |= 0x00000001u; ctype_ = value; +} +inline void FieldOptions::set_ctype(PROTOBUF_NAMESPACE_ID::FieldOptions_CType value) { + _internal_set_ctype(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.ctype) } // optional bool packed = 2; -inline bool FieldOptions::has_packed() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -inline void FieldOptions::set_has_packed() { - _has_bits_[0] |= 0x00000002u; +inline bool FieldOptions::_internal_has_packed() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void FieldOptions::clear_has_packed() { - _has_bits_[0] &= ~0x00000002u; +inline bool FieldOptions::has_packed() const { + return _internal_has_packed(); } inline void FieldOptions::clear_packed() { packed_ = false; - clear_has_packed(); + _has_bits_[0] &= ~0x00000002u; +} +inline bool FieldOptions::_internal_packed() const { + return packed_; } inline bool FieldOptions::packed() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.packed) - return packed_; + return _internal_packed(); } -inline void FieldOptions::set_packed(bool value) { - set_has_packed(); +inline void FieldOptions::_internal_set_packed(bool value) { + _has_bits_[0] |= 0x00000002u; packed_ = value; +} +inline void FieldOptions::set_packed(bool value) { + _internal_set_packed(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed) } // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; -inline bool FieldOptions::has_jstype() const { - return (_has_bits_[0] & 0x00000020u) != 0; -} -inline void FieldOptions::set_has_jstype() { - _has_bits_[0] |= 0x00000020u; +inline bool FieldOptions::_internal_has_jstype() const { + bool value = (_has_bits_[0] & 0x00000020u) != 0; + return value; } -inline void FieldOptions::clear_has_jstype() { - _has_bits_[0] &= ~0x00000020u; +inline bool FieldOptions::has_jstype() const { + return _internal_has_jstype(); } inline void FieldOptions::clear_jstype() { jstype_ = 0; - clear_has_jstype(); + _has_bits_[0] &= ~0x00000020u; +} +inline PROTOBUF_NAMESPACE_ID::FieldOptions_JSType FieldOptions::_internal_jstype() const { + return static_cast< PROTOBUF_NAMESPACE_ID::FieldOptions_JSType >(jstype_); } -inline ::google::protobuf::FieldOptions_JSType FieldOptions::jstype() const { +inline PROTOBUF_NAMESPACE_ID::FieldOptions_JSType FieldOptions::jstype() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.jstype) - return static_cast< ::google::protobuf::FieldOptions_JSType >(jstype_); + return _internal_jstype(); } -inline void FieldOptions::set_jstype(::google::protobuf::FieldOptions_JSType value) { - assert(::google::protobuf::FieldOptions_JSType_IsValid(value)); - set_has_jstype(); +inline void FieldOptions::_internal_set_jstype(PROTOBUF_NAMESPACE_ID::FieldOptions_JSType value) { + assert(PROTOBUF_NAMESPACE_ID::FieldOptions_JSType_IsValid(value)); + _has_bits_[0] |= 0x00000020u; jstype_ = value; +} +inline void FieldOptions::set_jstype(PROTOBUF_NAMESPACE_ID::FieldOptions_JSType value) { + _internal_set_jstype(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.jstype) } // optional bool lazy = 5 [default = false]; -inline bool FieldOptions::has_lazy() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -inline void FieldOptions::set_has_lazy() { - _has_bits_[0] |= 0x00000004u; +inline bool FieldOptions::_internal_has_lazy() const { + bool value = (_has_bits_[0] & 0x00000004u) != 0; + return value; } -inline void FieldOptions::clear_has_lazy() { - _has_bits_[0] &= ~0x00000004u; +inline bool FieldOptions::has_lazy() const { + return _internal_has_lazy(); } inline void FieldOptions::clear_lazy() { lazy_ = false; - clear_has_lazy(); + _has_bits_[0] &= ~0x00000004u; +} +inline bool FieldOptions::_internal_lazy() const { + return lazy_; } inline bool FieldOptions::lazy() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.lazy) - return lazy_; + return _internal_lazy(); } -inline void FieldOptions::set_lazy(bool value) { - set_has_lazy(); +inline void FieldOptions::_internal_set_lazy(bool value) { + _has_bits_[0] |= 0x00000004u; lazy_ = value; +} +inline void FieldOptions::set_lazy(bool value) { + _internal_set_lazy(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.lazy) } // optional bool deprecated = 3 [default = false]; -inline bool FieldOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00000008u) != 0; +inline bool FieldOptions::_internal_has_deprecated() const { + bool value = (_has_bits_[0] & 0x00000008u) != 0; + return value; } -inline void FieldOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00000008u; -} -inline void FieldOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00000008u; +inline bool FieldOptions::has_deprecated() const { + return _internal_has_deprecated(); } inline void FieldOptions::clear_deprecated() { deprecated_ = false; - clear_has_deprecated(); + _has_bits_[0] &= ~0x00000008u; +} +inline bool FieldOptions::_internal_deprecated() const { + return deprecated_; } inline bool FieldOptions::deprecated() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.deprecated) - return deprecated_; + return _internal_deprecated(); } -inline void FieldOptions::set_deprecated(bool value) { - set_has_deprecated(); +inline void FieldOptions::_internal_set_deprecated(bool value) { + _has_bits_[0] |= 0x00000008u; deprecated_ = value; +} +inline void FieldOptions::set_deprecated(bool value) { + _internal_set_deprecated(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.deprecated) } // optional bool weak = 10 [default = false]; -inline bool FieldOptions::has_weak() const { - return (_has_bits_[0] & 0x00000010u) != 0; -} -inline void FieldOptions::set_has_weak() { - _has_bits_[0] |= 0x00000010u; +inline bool FieldOptions::_internal_has_weak() const { + bool value = (_has_bits_[0] & 0x00000010u) != 0; + return value; } -inline void FieldOptions::clear_has_weak() { - _has_bits_[0] &= ~0x00000010u; +inline bool FieldOptions::has_weak() const { + return _internal_has_weak(); } inline void FieldOptions::clear_weak() { weak_ = false; - clear_has_weak(); + _has_bits_[0] &= ~0x00000010u; +} +inline bool FieldOptions::_internal_weak() const { + return weak_; } inline bool FieldOptions::weak() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.weak) - return weak_; + return _internal_weak(); } -inline void FieldOptions::set_weak(bool value) { - set_has_weak(); +inline void FieldOptions::_internal_set_weak(bool value) { + _has_bits_[0] |= 0x00000010u; weak_ = value; +} +inline void FieldOptions::set_weak(bool value) { + _internal_set_weak(value); // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak) } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -inline int FieldOptions::uninterpreted_option_size() const { +inline int FieldOptions::_internal_uninterpreted_option_size() const { return uninterpreted_option_.size(); } +inline int FieldOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} inline void FieldOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } -inline const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -inline ::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) { +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } -inline ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* FieldOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option) return &uninterpreted_option_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& FieldOptions::_internal_uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* FieldOptions::_internal_add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* FieldOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option) + return _internal_add_uninterpreted_option(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& FieldOptions::uninterpreted_option() const { // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option) return uninterpreted_option_; @@ -8167,30 +11405,39 @@ FieldOptions::uninterpreted_option() const { // OneofOptions // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -inline int OneofOptions::uninterpreted_option_size() const { +inline int OneofOptions::_internal_uninterpreted_option_size() const { return uninterpreted_option_.size(); } +inline int OneofOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} inline void OneofOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } -inline const ::google::protobuf::UninterpretedOption& OneofOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.OneofOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -inline ::google::protobuf::UninterpretedOption* OneofOptions::mutable_uninterpreted_option(int index) { +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* OneofOptions::mutable_uninterpreted_option(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.OneofOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } -inline ::google::protobuf::UninterpretedOption* OneofOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.OneofOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* OneofOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.OneofOptions.uninterpreted_option) return &uninterpreted_option_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& OneofOptions::_internal_uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& OneofOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.OneofOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* OneofOptions::_internal_add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* OneofOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.OneofOptions.uninterpreted_option) + return _internal_add_uninterpreted_option(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& OneofOptions::uninterpreted_option() const { // @@protoc_insertion_point(field_list:google.protobuf.OneofOptions.uninterpreted_option) return uninterpreted_option_; @@ -8201,78 +11448,95 @@ OneofOptions::uninterpreted_option() const { // EnumOptions // optional bool allow_alias = 2; -inline bool EnumOptions::has_allow_alias() const { - return (_has_bits_[0] & 0x00000001u) != 0; +inline bool EnumOptions::_internal_has_allow_alias() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void EnumOptions::set_has_allow_alias() { - _has_bits_[0] |= 0x00000001u; -} -inline void EnumOptions::clear_has_allow_alias() { - _has_bits_[0] &= ~0x00000001u; +inline bool EnumOptions::has_allow_alias() const { + return _internal_has_allow_alias(); } inline void EnumOptions::clear_allow_alias() { allow_alias_ = false; - clear_has_allow_alias(); + _has_bits_[0] &= ~0x00000001u; +} +inline bool EnumOptions::_internal_allow_alias() const { + return allow_alias_; } inline bool EnumOptions::allow_alias() const { // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.allow_alias) - return allow_alias_; + return _internal_allow_alias(); } -inline void EnumOptions::set_allow_alias(bool value) { - set_has_allow_alias(); +inline void EnumOptions::_internal_set_allow_alias(bool value) { + _has_bits_[0] |= 0x00000001u; allow_alias_ = value; +} +inline void EnumOptions::set_allow_alias(bool value) { + _internal_set_allow_alias(value); // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.allow_alias) } // optional bool deprecated = 3 [default = false]; -inline bool EnumOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -inline void EnumOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00000002u; +inline bool EnumOptions::_internal_has_deprecated() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void EnumOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00000002u; +inline bool EnumOptions::has_deprecated() const { + return _internal_has_deprecated(); } inline void EnumOptions::clear_deprecated() { deprecated_ = false; - clear_has_deprecated(); + _has_bits_[0] &= ~0x00000002u; +} +inline bool EnumOptions::_internal_deprecated() const { + return deprecated_; } inline bool EnumOptions::deprecated() const { // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.deprecated) - return deprecated_; + return _internal_deprecated(); } -inline void EnumOptions::set_deprecated(bool value) { - set_has_deprecated(); +inline void EnumOptions::_internal_set_deprecated(bool value) { + _has_bits_[0] |= 0x00000002u; deprecated_ = value; +} +inline void EnumOptions::set_deprecated(bool value) { + _internal_set_deprecated(value); // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.deprecated) } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -inline int EnumOptions::uninterpreted_option_size() const { +inline int EnumOptions::_internal_uninterpreted_option_size() const { return uninterpreted_option_.size(); } +inline int EnumOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} inline void EnumOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } -inline const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -inline ::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) { +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.EnumOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } -inline ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* EnumOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option) return &uninterpreted_option_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& EnumOptions::_internal_uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* EnumOptions::_internal_add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* EnumOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option) + return _internal_add_uninterpreted_option(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& EnumOptions::uninterpreted_option() const { // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option) return uninterpreted_option_; @@ -8283,54 +11547,67 @@ EnumOptions::uninterpreted_option() const { // EnumValueOptions // optional bool deprecated = 1 [default = false]; -inline bool EnumValueOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void EnumValueOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00000001u; +inline bool EnumValueOptions::_internal_has_deprecated() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void EnumValueOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00000001u; +inline bool EnumValueOptions::has_deprecated() const { + return _internal_has_deprecated(); } inline void EnumValueOptions::clear_deprecated() { deprecated_ = false; - clear_has_deprecated(); + _has_bits_[0] &= ~0x00000001u; +} +inline bool EnumValueOptions::_internal_deprecated() const { + return deprecated_; } inline bool EnumValueOptions::deprecated() const { // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.deprecated) - return deprecated_; + return _internal_deprecated(); } -inline void EnumValueOptions::set_deprecated(bool value) { - set_has_deprecated(); +inline void EnumValueOptions::_internal_set_deprecated(bool value) { + _has_bits_[0] |= 0x00000001u; deprecated_ = value; +} +inline void EnumValueOptions::set_deprecated(bool value) { + _internal_set_deprecated(value); // @@protoc_insertion_point(field_set:google.protobuf.EnumValueOptions.deprecated) } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -inline int EnumValueOptions::uninterpreted_option_size() const { +inline int EnumValueOptions::_internal_uninterpreted_option_size() const { return uninterpreted_option_.size(); } +inline int EnumValueOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} inline void EnumValueOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } -inline const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -inline ::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) { +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } -inline ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* EnumValueOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option) return &uninterpreted_option_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& EnumValueOptions::_internal_uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* EnumValueOptions::_internal_add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option) + return _internal_add_uninterpreted_option(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& EnumValueOptions::uninterpreted_option() const { // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option) return uninterpreted_option_; @@ -8341,54 +11618,67 @@ EnumValueOptions::uninterpreted_option() const { // ServiceOptions // optional bool deprecated = 33 [default = false]; -inline bool ServiceOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void ServiceOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00000001u; +inline bool ServiceOptions::_internal_has_deprecated() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void ServiceOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00000001u; +inline bool ServiceOptions::has_deprecated() const { + return _internal_has_deprecated(); } inline void ServiceOptions::clear_deprecated() { deprecated_ = false; - clear_has_deprecated(); + _has_bits_[0] &= ~0x00000001u; +} +inline bool ServiceOptions::_internal_deprecated() const { + return deprecated_; } inline bool ServiceOptions::deprecated() const { // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.deprecated) - return deprecated_; + return _internal_deprecated(); } -inline void ServiceOptions::set_deprecated(bool value) { - set_has_deprecated(); +inline void ServiceOptions::_internal_set_deprecated(bool value) { + _has_bits_[0] |= 0x00000001u; deprecated_ = value; +} +inline void ServiceOptions::set_deprecated(bool value) { + _internal_set_deprecated(value); // @@protoc_insertion_point(field_set:google.protobuf.ServiceOptions.deprecated) } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -inline int ServiceOptions::uninterpreted_option_size() const { +inline int ServiceOptions::_internal_uninterpreted_option_size() const { return uninterpreted_option_.size(); } +inline int ServiceOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} inline void ServiceOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } -inline const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -inline ::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) { +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } -inline ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* ServiceOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option) return &uninterpreted_option_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& ServiceOptions::_internal_uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* ServiceOptions::_internal_add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* ServiceOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option) + return _internal_add_uninterpreted_option(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& ServiceOptions::uninterpreted_option() const { // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option) return uninterpreted_option_; @@ -8399,79 +11689,96 @@ ServiceOptions::uninterpreted_option() const { // MethodOptions // optional bool deprecated = 33 [default = false]; -inline bool MethodOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void MethodOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00000001u; +inline bool MethodOptions::_internal_has_deprecated() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void MethodOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00000001u; +inline bool MethodOptions::has_deprecated() const { + return _internal_has_deprecated(); } inline void MethodOptions::clear_deprecated() { deprecated_ = false; - clear_has_deprecated(); + _has_bits_[0] &= ~0x00000001u; +} +inline bool MethodOptions::_internal_deprecated() const { + return deprecated_; } inline bool MethodOptions::deprecated() const { // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.deprecated) - return deprecated_; + return _internal_deprecated(); } -inline void MethodOptions::set_deprecated(bool value) { - set_has_deprecated(); +inline void MethodOptions::_internal_set_deprecated(bool value) { + _has_bits_[0] |= 0x00000001u; deprecated_ = value; +} +inline void MethodOptions::set_deprecated(bool value) { + _internal_set_deprecated(value); // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.deprecated) } // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; -inline bool MethodOptions::has_idempotency_level() const { - return (_has_bits_[0] & 0x00000002u) != 0; +inline bool MethodOptions::_internal_has_idempotency_level() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void MethodOptions::set_has_idempotency_level() { - _has_bits_[0] |= 0x00000002u; -} -inline void MethodOptions::clear_has_idempotency_level() { - _has_bits_[0] &= ~0x00000002u; +inline bool MethodOptions::has_idempotency_level() const { + return _internal_has_idempotency_level(); } inline void MethodOptions::clear_idempotency_level() { idempotency_level_ = 0; - clear_has_idempotency_level(); + _has_bits_[0] &= ~0x00000002u; +} +inline PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel MethodOptions::_internal_idempotency_level() const { + return static_cast< PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel >(idempotency_level_); } -inline ::google::protobuf::MethodOptions_IdempotencyLevel MethodOptions::idempotency_level() const { +inline PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel MethodOptions::idempotency_level() const { // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.idempotency_level) - return static_cast< ::google::protobuf::MethodOptions_IdempotencyLevel >(idempotency_level_); + return _internal_idempotency_level(); } -inline void MethodOptions::set_idempotency_level(::google::protobuf::MethodOptions_IdempotencyLevel value) { - assert(::google::protobuf::MethodOptions_IdempotencyLevel_IsValid(value)); - set_has_idempotency_level(); +inline void MethodOptions::_internal_set_idempotency_level(PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel value) { + assert(PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel_IsValid(value)); + _has_bits_[0] |= 0x00000002u; idempotency_level_ = value; +} +inline void MethodOptions::set_idempotency_level(PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel value) { + _internal_set_idempotency_level(value); // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.idempotency_level) } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; -inline int MethodOptions::uninterpreted_option_size() const { +inline int MethodOptions::_internal_uninterpreted_option_size() const { return uninterpreted_option_.size(); } +inline int MethodOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} inline void MethodOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } -inline const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.uninterpreted_option) - return uninterpreted_option_.Get(index); -} -inline ::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) { +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.MethodOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } -inline ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() { - // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option) - return uninterpreted_option_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >* MethodOptions::mutable_uninterpreted_option() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option) return &uninterpreted_option_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& MethodOptions::_internal_uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* MethodOptions::_internal_add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption* MethodOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option) + return _internal_add_uninterpreted_option(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption >& MethodOptions::uninterpreted_option() const { // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option) return uninterpreted_option_; @@ -8482,89 +11789,103 @@ MethodOptions::uninterpreted_option() const { // UninterpretedOption_NamePart // required string name_part = 1; -inline bool UninterpretedOption_NamePart::has_name_part() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void UninterpretedOption_NamePart::set_has_name_part() { - _has_bits_[0] |= 0x00000001u; +inline bool UninterpretedOption_NamePart::_internal_has_name_part() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void UninterpretedOption_NamePart::clear_has_name_part() { - _has_bits_[0] &= ~0x00000001u; +inline bool UninterpretedOption_NamePart::has_name_part() const { + return _internal_has_name_part(); } inline void UninterpretedOption_NamePart::clear_name_part() { - name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name_part(); + name_part_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& UninterpretedOption_NamePart::name_part() const { +inline const std::string& UninterpretedOption_NamePart::name_part() const { // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.name_part) - return name_part_.GetNoArena(); + return _internal_name_part(); } -inline void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) { - set_has_name_part(); - name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void UninterpretedOption_NamePart::set_name_part(const std::string& value) { + _internal_set_name_part(value); // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.name_part) } -#if LANG_CXX11 -inline void UninterpretedOption_NamePart::set_name_part(::std::string&& value) { - set_has_name_part(); - name_part_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* UninterpretedOption_NamePart::mutable_name_part() { + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part) + return _internal_mutable_name_part(); +} +inline const std::string& UninterpretedOption_NamePart::_internal_name_part() const { + return name_part_.Get(); +} +inline void UninterpretedOption_NamePart::_internal_set_name_part(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void UninterpretedOption_NamePart::set_name_part(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + name_part_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.NamePart.name_part) } -#endif inline void UninterpretedOption_NamePart::set_name_part(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_name_part(); - name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.NamePart.name_part) } -inline void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) { - set_has_name_part(); - name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void UninterpretedOption_NamePart::set_name_part(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part) } -inline ::std::string* UninterpretedOption_NamePart::mutable_name_part() { - set_has_name_part(); - // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part) - return name_part_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* UninterpretedOption_NamePart::_internal_mutable_name_part() { + _has_bits_[0] |= 0x00000001u; + return name_part_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* UninterpretedOption_NamePart::release_name_part() { +inline std::string* UninterpretedOption_NamePart::release_name_part() { // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.NamePart.name_part) - clear_has_name_part(); - return name_part_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_name_part()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return name_part_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) { - if (name_part != NULL) { - set_has_name_part(); +inline void UninterpretedOption_NamePart::set_allocated_name_part(std::string* name_part) { + if (name_part != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_name_part(); + _has_bits_[0] &= ~0x00000001u; } - name_part_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name_part); + name_part_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name_part, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part) } // required bool is_extension = 2; -inline bool UninterpretedOption_NamePart::has_is_extension() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -inline void UninterpretedOption_NamePart::set_has_is_extension() { - _has_bits_[0] |= 0x00000002u; +inline bool UninterpretedOption_NamePart::_internal_has_is_extension() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void UninterpretedOption_NamePart::clear_has_is_extension() { - _has_bits_[0] &= ~0x00000002u; +inline bool UninterpretedOption_NamePart::has_is_extension() const { + return _internal_has_is_extension(); } inline void UninterpretedOption_NamePart::clear_is_extension() { is_extension_ = false; - clear_has_is_extension(); + _has_bits_[0] &= ~0x00000002u; +} +inline bool UninterpretedOption_NamePart::_internal_is_extension() const { + return is_extension_; } inline bool UninterpretedOption_NamePart::is_extension() const { // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.is_extension) - return is_extension_; + return _internal_is_extension(); } -inline void UninterpretedOption_NamePart::set_is_extension(bool value) { - set_has_is_extension(); +inline void UninterpretedOption_NamePart::_internal_set_is_extension(bool value) { + _has_bits_[0] |= 0x00000002u; is_extension_ = value; +} +inline void UninterpretedOption_NamePart::set_is_extension(bool value) { + _internal_set_is_extension(value); // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.is_extension) } @@ -8573,293 +11894,344 @@ inline void UninterpretedOption_NamePart::set_is_extension(bool value) { // UninterpretedOption // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; -inline int UninterpretedOption::name_size() const { +inline int UninterpretedOption::_internal_name_size() const { return name_.size(); } +inline int UninterpretedOption::name_size() const { + return _internal_name_size(); +} inline void UninterpretedOption::clear_name() { name_.Clear(); } -inline const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.name) - return name_.Get(index); -} -inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) { +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.name) return name_.Mutable(index); } -inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() { - // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name) - return name_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart >* UninterpretedOption::mutable_name() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name) return &name_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart& UninterpretedOption::_internal_name(int index) const { + return name_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.name) + return _internal_name(index); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* UninterpretedOption::_internal_add_name() { + return name_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* UninterpretedOption::add_name() { + // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name) + return _internal_add_name(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart >& UninterpretedOption::name() const { // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name) return name_; } // optional string identifier_value = 3; -inline bool UninterpretedOption::has_identifier_value() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void UninterpretedOption::set_has_identifier_value() { - _has_bits_[0] |= 0x00000001u; +inline bool UninterpretedOption::_internal_has_identifier_value() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void UninterpretedOption::clear_has_identifier_value() { - _has_bits_[0] &= ~0x00000001u; +inline bool UninterpretedOption::has_identifier_value() const { + return _internal_has_identifier_value(); } inline void UninterpretedOption::clear_identifier_value() { - identifier_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_identifier_value(); + identifier_value_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& UninterpretedOption::identifier_value() const { +inline const std::string& UninterpretedOption::identifier_value() const { // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.identifier_value) - return identifier_value_.GetNoArena(); + return _internal_identifier_value(); } -inline void UninterpretedOption::set_identifier_value(const ::std::string& value) { - set_has_identifier_value(); - identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void UninterpretedOption::set_identifier_value(const std::string& value) { + _internal_set_identifier_value(value); // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.identifier_value) } -#if LANG_CXX11 -inline void UninterpretedOption::set_identifier_value(::std::string&& value) { - set_has_identifier_value(); - identifier_value_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* UninterpretedOption::mutable_identifier_value() { + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value) + return _internal_mutable_identifier_value(); +} +inline const std::string& UninterpretedOption::_internal_identifier_value() const { + return identifier_value_.Get(); +} +inline void UninterpretedOption::_internal_set_identifier_value(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void UninterpretedOption::set_identifier_value(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + identifier_value_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.identifier_value) } -#endif inline void UninterpretedOption::set_identifier_value(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_identifier_value(); - identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value) } -inline void UninterpretedOption::set_identifier_value(const char* value, size_t size) { - set_has_identifier_value(); - identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void UninterpretedOption::set_identifier_value(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value) } -inline ::std::string* UninterpretedOption::mutable_identifier_value() { - set_has_identifier_value(); - // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value) - return identifier_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* UninterpretedOption::_internal_mutable_identifier_value() { + _has_bits_[0] |= 0x00000001u; + return identifier_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* UninterpretedOption::release_identifier_value() { +inline std::string* UninterpretedOption::release_identifier_value() { // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.identifier_value) - clear_has_identifier_value(); - return identifier_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_identifier_value()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return identifier_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) { - if (identifier_value != NULL) { - set_has_identifier_value(); +inline void UninterpretedOption::set_allocated_identifier_value(std::string* identifier_value) { + if (identifier_value != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_identifier_value(); + _has_bits_[0] &= ~0x00000001u; } - identifier_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), identifier_value); + identifier_value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), identifier_value, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value) } // optional uint64 positive_int_value = 4; -inline bool UninterpretedOption::has_positive_int_value() const { - return (_has_bits_[0] & 0x00000008u) != 0; +inline bool UninterpretedOption::_internal_has_positive_int_value() const { + bool value = (_has_bits_[0] & 0x00000008u) != 0; + return value; } -inline void UninterpretedOption::set_has_positive_int_value() { - _has_bits_[0] |= 0x00000008u; +inline bool UninterpretedOption::has_positive_int_value() const { + return _internal_has_positive_int_value(); } -inline void UninterpretedOption::clear_has_positive_int_value() { +inline void UninterpretedOption::clear_positive_int_value() { + positive_int_value_ = PROTOBUF_ULONGLONG(0); _has_bits_[0] &= ~0x00000008u; } -inline void UninterpretedOption::clear_positive_int_value() { - positive_int_value_ = GOOGLE_ULONGLONG(0); - clear_has_positive_int_value(); +inline ::PROTOBUF_NAMESPACE_ID::uint64 UninterpretedOption::_internal_positive_int_value() const { + return positive_int_value_; } -inline ::google::protobuf::uint64 UninterpretedOption::positive_int_value() const { +inline ::PROTOBUF_NAMESPACE_ID::uint64 UninterpretedOption::positive_int_value() const { // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.positive_int_value) - return positive_int_value_; + return _internal_positive_int_value(); } -inline void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) { - set_has_positive_int_value(); +inline void UninterpretedOption::_internal_set_positive_int_value(::PROTOBUF_NAMESPACE_ID::uint64 value) { + _has_bits_[0] |= 0x00000008u; positive_int_value_ = value; +} +inline void UninterpretedOption::set_positive_int_value(::PROTOBUF_NAMESPACE_ID::uint64 value) { + _internal_set_positive_int_value(value); // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.positive_int_value) } // optional int64 negative_int_value = 5; -inline bool UninterpretedOption::has_negative_int_value() const { - return (_has_bits_[0] & 0x00000010u) != 0; +inline bool UninterpretedOption::_internal_has_negative_int_value() const { + bool value = (_has_bits_[0] & 0x00000010u) != 0; + return value; } -inline void UninterpretedOption::set_has_negative_int_value() { - _has_bits_[0] |= 0x00000010u; +inline bool UninterpretedOption::has_negative_int_value() const { + return _internal_has_negative_int_value(); } -inline void UninterpretedOption::clear_has_negative_int_value() { +inline void UninterpretedOption::clear_negative_int_value() { + negative_int_value_ = PROTOBUF_LONGLONG(0); _has_bits_[0] &= ~0x00000010u; } -inline void UninterpretedOption::clear_negative_int_value() { - negative_int_value_ = GOOGLE_LONGLONG(0); - clear_has_negative_int_value(); +inline ::PROTOBUF_NAMESPACE_ID::int64 UninterpretedOption::_internal_negative_int_value() const { + return negative_int_value_; } -inline ::google::protobuf::int64 UninterpretedOption::negative_int_value() const { +inline ::PROTOBUF_NAMESPACE_ID::int64 UninterpretedOption::negative_int_value() const { // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.negative_int_value) - return negative_int_value_; + return _internal_negative_int_value(); } -inline void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) { - set_has_negative_int_value(); +inline void UninterpretedOption::_internal_set_negative_int_value(::PROTOBUF_NAMESPACE_ID::int64 value) { + _has_bits_[0] |= 0x00000010u; negative_int_value_ = value; +} +inline void UninterpretedOption::set_negative_int_value(::PROTOBUF_NAMESPACE_ID::int64 value) { + _internal_set_negative_int_value(value); // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.negative_int_value) } // optional double double_value = 6; -inline bool UninterpretedOption::has_double_value() const { - return (_has_bits_[0] & 0x00000020u) != 0; +inline bool UninterpretedOption::_internal_has_double_value() const { + bool value = (_has_bits_[0] & 0x00000020u) != 0; + return value; } -inline void UninterpretedOption::set_has_double_value() { - _has_bits_[0] |= 0x00000020u; -} -inline void UninterpretedOption::clear_has_double_value() { - _has_bits_[0] &= ~0x00000020u; +inline bool UninterpretedOption::has_double_value() const { + return _internal_has_double_value(); } inline void UninterpretedOption::clear_double_value() { double_value_ = 0; - clear_has_double_value(); + _has_bits_[0] &= ~0x00000020u; +} +inline double UninterpretedOption::_internal_double_value() const { + return double_value_; } inline double UninterpretedOption::double_value() const { // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.double_value) - return double_value_; + return _internal_double_value(); } -inline void UninterpretedOption::set_double_value(double value) { - set_has_double_value(); +inline void UninterpretedOption::_internal_set_double_value(double value) { + _has_bits_[0] |= 0x00000020u; double_value_ = value; +} +inline void UninterpretedOption::set_double_value(double value) { + _internal_set_double_value(value); // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.double_value) } // optional bytes string_value = 7; -inline bool UninterpretedOption::has_string_value() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -inline void UninterpretedOption::set_has_string_value() { - _has_bits_[0] |= 0x00000002u; +inline bool UninterpretedOption::_internal_has_string_value() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void UninterpretedOption::clear_has_string_value() { - _has_bits_[0] &= ~0x00000002u; +inline bool UninterpretedOption::has_string_value() const { + return _internal_has_string_value(); } inline void UninterpretedOption::clear_string_value() { - string_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_string_value(); + string_value_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000002u; } -inline const ::std::string& UninterpretedOption::string_value() const { +inline const std::string& UninterpretedOption::string_value() const { // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.string_value) - return string_value_.GetNoArena(); + return _internal_string_value(); } -inline void UninterpretedOption::set_string_value(const ::std::string& value) { - set_has_string_value(); - string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void UninterpretedOption::set_string_value(const std::string& value) { + _internal_set_string_value(value); // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.string_value) } -#if LANG_CXX11 -inline void UninterpretedOption::set_string_value(::std::string&& value) { - set_has_string_value(); - string_value_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* UninterpretedOption::mutable_string_value() { + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value) + return _internal_mutable_string_value(); +} +inline const std::string& UninterpretedOption::_internal_string_value() const { + return string_value_.Get(); +} +inline void UninterpretedOption::_internal_set_string_value(const std::string& value) { + _has_bits_[0] |= 0x00000002u; + string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void UninterpretedOption::set_string_value(std::string&& value) { + _has_bits_[0] |= 0x00000002u; + string_value_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.string_value) } -#endif inline void UninterpretedOption::set_string_value(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_string_value(); - string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000002u; + string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value) } -inline void UninterpretedOption::set_string_value(const void* value, size_t size) { - set_has_string_value(); - string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void UninterpretedOption::set_string_value(const void* value, + size_t size) { + _has_bits_[0] |= 0x00000002u; + string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value) } -inline ::std::string* UninterpretedOption::mutable_string_value() { - set_has_string_value(); - // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value) - return string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* UninterpretedOption::_internal_mutable_string_value() { + _has_bits_[0] |= 0x00000002u; + return string_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* UninterpretedOption::release_string_value() { +inline std::string* UninterpretedOption::release_string_value() { // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.string_value) - clear_has_string_value(); - return string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_string_value()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000002u; + return string_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void UninterpretedOption::set_allocated_string_value(::std::string* string_value) { - if (string_value != NULL) { - set_has_string_value(); +inline void UninterpretedOption::set_allocated_string_value(std::string* string_value) { + if (string_value != nullptr) { + _has_bits_[0] |= 0x00000002u; } else { - clear_has_string_value(); + _has_bits_[0] &= ~0x00000002u; } - string_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value); + string_value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), string_value, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value) } // optional string aggregate_value = 8; -inline bool UninterpretedOption::has_aggregate_value() const { - return (_has_bits_[0] & 0x00000004u) != 0; +inline bool UninterpretedOption::_internal_has_aggregate_value() const { + bool value = (_has_bits_[0] & 0x00000004u) != 0; + return value; } -inline void UninterpretedOption::set_has_aggregate_value() { - _has_bits_[0] |= 0x00000004u; -} -inline void UninterpretedOption::clear_has_aggregate_value() { - _has_bits_[0] &= ~0x00000004u; +inline bool UninterpretedOption::has_aggregate_value() const { + return _internal_has_aggregate_value(); } inline void UninterpretedOption::clear_aggregate_value() { - aggregate_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_aggregate_value(); + aggregate_value_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000004u; } -inline const ::std::string& UninterpretedOption::aggregate_value() const { +inline const std::string& UninterpretedOption::aggregate_value() const { // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.aggregate_value) - return aggregate_value_.GetNoArena(); + return _internal_aggregate_value(); } -inline void UninterpretedOption::set_aggregate_value(const ::std::string& value) { - set_has_aggregate_value(); - aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void UninterpretedOption::set_aggregate_value(const std::string& value) { + _internal_set_aggregate_value(value); // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value) } -#if LANG_CXX11 -inline void UninterpretedOption::set_aggregate_value(::std::string&& value) { - set_has_aggregate_value(); - aggregate_value_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* UninterpretedOption::mutable_aggregate_value() { + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value) + return _internal_mutable_aggregate_value(); +} +inline const std::string& UninterpretedOption::_internal_aggregate_value() const { + return aggregate_value_.Get(); +} +inline void UninterpretedOption::_internal_set_aggregate_value(const std::string& value) { + _has_bits_[0] |= 0x00000004u; + aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void UninterpretedOption::set_aggregate_value(std::string&& value) { + _has_bits_[0] |= 0x00000004u; + aggregate_value_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.aggregate_value) } -#endif inline void UninterpretedOption::set_aggregate_value(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_aggregate_value(); - aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000004u; + aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value) } -inline void UninterpretedOption::set_aggregate_value(const char* value, size_t size) { - set_has_aggregate_value(); - aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void UninterpretedOption::set_aggregate_value(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000004u; + aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value) } -inline ::std::string* UninterpretedOption::mutable_aggregate_value() { - set_has_aggregate_value(); - // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value) - return aggregate_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* UninterpretedOption::_internal_mutable_aggregate_value() { + _has_bits_[0] |= 0x00000004u; + return aggregate_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* UninterpretedOption::release_aggregate_value() { +inline std::string* UninterpretedOption::release_aggregate_value() { // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.aggregate_value) - clear_has_aggregate_value(); - return aggregate_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_aggregate_value()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000004u; + return aggregate_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) { - if (aggregate_value != NULL) { - set_has_aggregate_value(); +inline void UninterpretedOption::set_allocated_aggregate_value(std::string* aggregate_value) { + if (aggregate_value != nullptr) { + _has_bits_[0] |= 0x00000004u; } else { - clear_has_aggregate_value(); + _has_bits_[0] &= ~0x00000004u; } - aggregate_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), aggregate_value); + aggregate_value_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), aggregate_value, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value) } @@ -8868,218 +12240,280 @@ inline void UninterpretedOption::set_allocated_aggregate_value(::std::string* ag // SourceCodeInfo_Location // repeated int32 path = 1 [packed = true]; -inline int SourceCodeInfo_Location::path_size() const { +inline int SourceCodeInfo_Location::_internal_path_size() const { return path_.size(); } +inline int SourceCodeInfo_Location::path_size() const { + return _internal_path_size(); +} inline void SourceCodeInfo_Location::clear_path() { path_.Clear(); } -inline ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.path) +inline ::PROTOBUF_NAMESPACE_ID::int32 SourceCodeInfo_Location::_internal_path(int index) const { return path_.Get(index); } -inline void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) { +inline ::PROTOBUF_NAMESPACE_ID::int32 SourceCodeInfo_Location::path(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.path) + return _internal_path(index); +} +inline void SourceCodeInfo_Location::set_path(int index, ::PROTOBUF_NAMESPACE_ID::int32 value) { path_.Set(index, value); // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.path) } -inline void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) { +inline void SourceCodeInfo_Location::_internal_add_path(::PROTOBUF_NAMESPACE_ID::int32 value) { path_.Add(value); +} +inline void SourceCodeInfo_Location::add_path(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_add_path(value); // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.path) } -inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& +SourceCodeInfo_Location::_internal_path() const { + return path_; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& SourceCodeInfo_Location::path() const { // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.path) - return path_; + return _internal_path(); } -inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* +SourceCodeInfo_Location::_internal_mutable_path() { + return &path_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* SourceCodeInfo_Location::mutable_path() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.path) - return &path_; + return _internal_mutable_path(); } // repeated int32 span = 2 [packed = true]; -inline int SourceCodeInfo_Location::span_size() const { +inline int SourceCodeInfo_Location::_internal_span_size() const { return span_.size(); } +inline int SourceCodeInfo_Location::span_size() const { + return _internal_span_size(); +} inline void SourceCodeInfo_Location::clear_span() { span_.Clear(); } -inline ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.span) +inline ::PROTOBUF_NAMESPACE_ID::int32 SourceCodeInfo_Location::_internal_span(int index) const { return span_.Get(index); } -inline void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) { +inline ::PROTOBUF_NAMESPACE_ID::int32 SourceCodeInfo_Location::span(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.span) + return _internal_span(index); +} +inline void SourceCodeInfo_Location::set_span(int index, ::PROTOBUF_NAMESPACE_ID::int32 value) { span_.Set(index, value); // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.span) } -inline void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) { +inline void SourceCodeInfo_Location::_internal_add_span(::PROTOBUF_NAMESPACE_ID::int32 value) { span_.Add(value); +} +inline void SourceCodeInfo_Location::add_span(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_add_span(value); // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.span) } -inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& +SourceCodeInfo_Location::_internal_span() const { + return span_; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& SourceCodeInfo_Location::span() const { // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.span) - return span_; + return _internal_span(); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* +SourceCodeInfo_Location::_internal_mutable_span() { + return &span_; } -inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* SourceCodeInfo_Location::mutable_span() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.span) - return &span_; + return _internal_mutable_span(); } // optional string leading_comments = 3; -inline bool SourceCodeInfo_Location::has_leading_comments() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void SourceCodeInfo_Location::set_has_leading_comments() { - _has_bits_[0] |= 0x00000001u; +inline bool SourceCodeInfo_Location::_internal_has_leading_comments() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void SourceCodeInfo_Location::clear_has_leading_comments() { - _has_bits_[0] &= ~0x00000001u; +inline bool SourceCodeInfo_Location::has_leading_comments() const { + return _internal_has_leading_comments(); } inline void SourceCodeInfo_Location::clear_leading_comments() { - leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_leading_comments(); + leading_comments_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& SourceCodeInfo_Location::leading_comments() const { +inline const std::string& SourceCodeInfo_Location::leading_comments() const { // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_comments) - return leading_comments_.GetNoArena(); + return _internal_leading_comments(); } -inline void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) { - set_has_leading_comments(); - leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void SourceCodeInfo_Location::set_leading_comments(const std::string& value) { + _internal_set_leading_comments(value); // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments) } -#if LANG_CXX11 -inline void SourceCodeInfo_Location::set_leading_comments(::std::string&& value) { - set_has_leading_comments(); - leading_comments_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* SourceCodeInfo_Location::mutable_leading_comments() { + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments) + return _internal_mutable_leading_comments(); +} +inline const std::string& SourceCodeInfo_Location::_internal_leading_comments() const { + return leading_comments_.Get(); +} +inline void SourceCodeInfo_Location::_internal_set_leading_comments(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void SourceCodeInfo_Location::set_leading_comments(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + leading_comments_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceCodeInfo.Location.leading_comments) } -#endif inline void SourceCodeInfo_Location::set_leading_comments(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_leading_comments(); - leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_comments) } -inline void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) { - set_has_leading_comments(); - leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void SourceCodeInfo_Location::set_leading_comments(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments) } -inline ::std::string* SourceCodeInfo_Location::mutable_leading_comments() { - set_has_leading_comments(); - // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments) - return leading_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* SourceCodeInfo_Location::_internal_mutable_leading_comments() { + _has_bits_[0] |= 0x00000001u; + return leading_comments_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* SourceCodeInfo_Location::release_leading_comments() { +inline std::string* SourceCodeInfo_Location::release_leading_comments() { // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.leading_comments) - clear_has_leading_comments(); - return leading_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_leading_comments()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return leading_comments_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) { - if (leading_comments != NULL) { - set_has_leading_comments(); +inline void SourceCodeInfo_Location::set_allocated_leading_comments(std::string* leading_comments) { + if (leading_comments != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_leading_comments(); + _has_bits_[0] &= ~0x00000001u; } - leading_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), leading_comments); + leading_comments_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), leading_comments, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments) } // optional string trailing_comments = 4; -inline bool SourceCodeInfo_Location::has_trailing_comments() const { - return (_has_bits_[0] & 0x00000002u) != 0; +inline bool SourceCodeInfo_Location::_internal_has_trailing_comments() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void SourceCodeInfo_Location::set_has_trailing_comments() { - _has_bits_[0] |= 0x00000002u; -} -inline void SourceCodeInfo_Location::clear_has_trailing_comments() { - _has_bits_[0] &= ~0x00000002u; +inline bool SourceCodeInfo_Location::has_trailing_comments() const { + return _internal_has_trailing_comments(); } inline void SourceCodeInfo_Location::clear_trailing_comments() { - trailing_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_trailing_comments(); + trailing_comments_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000002u; } -inline const ::std::string& SourceCodeInfo_Location::trailing_comments() const { +inline const std::string& SourceCodeInfo_Location::trailing_comments() const { // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.trailing_comments) - return trailing_comments_.GetNoArena(); + return _internal_trailing_comments(); } -inline void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) { - set_has_trailing_comments(); - trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void SourceCodeInfo_Location::set_trailing_comments(const std::string& value) { + _internal_set_trailing_comments(value); // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments) } -#if LANG_CXX11 -inline void SourceCodeInfo_Location::set_trailing_comments(::std::string&& value) { - set_has_trailing_comments(); - trailing_comments_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* SourceCodeInfo_Location::mutable_trailing_comments() { + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments) + return _internal_mutable_trailing_comments(); +} +inline const std::string& SourceCodeInfo_Location::_internal_trailing_comments() const { + return trailing_comments_.Get(); +} +inline void SourceCodeInfo_Location::_internal_set_trailing_comments(const std::string& value) { + _has_bits_[0] |= 0x00000002u; + trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void SourceCodeInfo_Location::set_trailing_comments(std::string&& value) { + _has_bits_[0] |= 0x00000002u; + trailing_comments_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceCodeInfo.Location.trailing_comments) } -#endif inline void SourceCodeInfo_Location::set_trailing_comments(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_trailing_comments(); - trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000002u; + trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.trailing_comments) } -inline void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) { - set_has_trailing_comments(); - trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void SourceCodeInfo_Location::set_trailing_comments(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000002u; + trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments) } -inline ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() { - set_has_trailing_comments(); - // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments) - return trailing_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* SourceCodeInfo_Location::_internal_mutable_trailing_comments() { + _has_bits_[0] |= 0x00000002u; + return trailing_comments_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* SourceCodeInfo_Location::release_trailing_comments() { +inline std::string* SourceCodeInfo_Location::release_trailing_comments() { // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.trailing_comments) - clear_has_trailing_comments(); - return trailing_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_trailing_comments()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000002u; + return trailing_comments_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) { - if (trailing_comments != NULL) { - set_has_trailing_comments(); +inline void SourceCodeInfo_Location::set_allocated_trailing_comments(std::string* trailing_comments) { + if (trailing_comments != nullptr) { + _has_bits_[0] |= 0x00000002u; } else { - clear_has_trailing_comments(); + _has_bits_[0] &= ~0x00000002u; } - trailing_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), trailing_comments); + trailing_comments_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), trailing_comments, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments) } // repeated string leading_detached_comments = 6; -inline int SourceCodeInfo_Location::leading_detached_comments_size() const { +inline int SourceCodeInfo_Location::_internal_leading_detached_comments_size() const { return leading_detached_comments_.size(); } +inline int SourceCodeInfo_Location::leading_detached_comments_size() const { + return _internal_leading_detached_comments_size(); +} inline void SourceCodeInfo_Location::clear_leading_detached_comments() { leading_detached_comments_.Clear(); } -inline const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +inline std::string* SourceCodeInfo_Location::add_leading_detached_comments() { + // @@protoc_insertion_point(field_add_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return _internal_add_leading_detached_comments(); +} +inline const std::string& SourceCodeInfo_Location::_internal_leading_detached_comments(int index) const { return leading_detached_comments_.Get(index); } -inline ::std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) { +inline const std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return _internal_leading_detached_comments(index); +} +inline std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) return leading_detached_comments_.Mutable(index); } -inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const ::std::string& value) { +inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const std::string& value) { // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) leading_detached_comments_.Mutable(index)->assign(value); } -#if LANG_CXX11 -inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, ::std::string&& value) { +inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, std::string&& value) { // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) leading_detached_comments_.Mutable(index)->assign(std::move(value)); } -#endif inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); leading_detached_comments_.Mutable(index)->assign(value); // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) } @@ -9088,22 +12522,19 @@ inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, co reinterpret_cast(value), size); // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) } -inline ::std::string* SourceCodeInfo_Location::add_leading_detached_comments() { - // @@protoc_insertion_point(field_add_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +inline std::string* SourceCodeInfo_Location::_internal_add_leading_detached_comments() { return leading_detached_comments_.Add(); } -inline void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) { +inline void SourceCodeInfo_Location::add_leading_detached_comments(const std::string& value) { leading_detached_comments_.Add()->assign(value); // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) } -#if LANG_CXX11 -inline void SourceCodeInfo_Location::add_leading_detached_comments(::std::string&& value) { +inline void SourceCodeInfo_Location::add_leading_detached_comments(std::string&& value) { leading_detached_comments_.Add(std::move(value)); // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) } -#endif inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); leading_detached_comments_.Add()->assign(value); // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) } @@ -9111,12 +12542,12 @@ inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* v leading_detached_comments_.Add()->assign(reinterpret_cast(value), size); // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) } -inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField& SourceCodeInfo_Location::leading_detached_comments() const { // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) return leading_detached_comments_; } -inline ::google::protobuf::RepeatedPtrField< ::std::string>* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField* SourceCodeInfo_Location::mutable_leading_detached_comments() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) return &leading_detached_comments_; @@ -9127,30 +12558,39 @@ SourceCodeInfo_Location::mutable_leading_detached_comments() { // SourceCodeInfo // repeated .google.protobuf.SourceCodeInfo.Location location = 1; -inline int SourceCodeInfo::location_size() const { +inline int SourceCodeInfo::_internal_location_size() const { return location_.size(); } +inline int SourceCodeInfo::location_size() const { + return _internal_location_size(); +} inline void SourceCodeInfo::clear_location() { location_.Clear(); } -inline const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.location) - return location_.Get(index); -} -inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) { +inline PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.location) return location_.Mutable(index); } -inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() { - // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location) - return location_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location >* SourceCodeInfo::mutable_location() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location) return &location_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& +inline const PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location& SourceCodeInfo::_internal_location(int index) const { + return location_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.location) + return _internal_location(index); +} +inline PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* SourceCodeInfo::_internal_add_location() { + return location_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* SourceCodeInfo::add_location() { + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location) + return _internal_add_location(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location >& SourceCodeInfo::location() const { // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location) return location_; @@ -9161,143 +12601,178 @@ SourceCodeInfo::location() const { // GeneratedCodeInfo_Annotation // repeated int32 path = 1 [packed = true]; -inline int GeneratedCodeInfo_Annotation::path_size() const { +inline int GeneratedCodeInfo_Annotation::_internal_path_size() const { return path_.size(); } +inline int GeneratedCodeInfo_Annotation::path_size() const { + return _internal_path_size(); +} inline void GeneratedCodeInfo_Annotation::clear_path() { path_.Clear(); } -inline ::google::protobuf::int32 GeneratedCodeInfo_Annotation::path(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.path) +inline ::PROTOBUF_NAMESPACE_ID::int32 GeneratedCodeInfo_Annotation::_internal_path(int index) const { return path_.Get(index); } -inline void GeneratedCodeInfo_Annotation::set_path(int index, ::google::protobuf::int32 value) { +inline ::PROTOBUF_NAMESPACE_ID::int32 GeneratedCodeInfo_Annotation::path(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.path) + return _internal_path(index); +} +inline void GeneratedCodeInfo_Annotation::set_path(int index, ::PROTOBUF_NAMESPACE_ID::int32 value) { path_.Set(index, value); // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.path) } -inline void GeneratedCodeInfo_Annotation::add_path(::google::protobuf::int32 value) { +inline void GeneratedCodeInfo_Annotation::_internal_add_path(::PROTOBUF_NAMESPACE_ID::int32 value) { path_.Add(value); +} +inline void GeneratedCodeInfo_Annotation::add_path(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_add_path(value); // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.Annotation.path) } -inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& +GeneratedCodeInfo_Annotation::_internal_path() const { + return path_; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >& GeneratedCodeInfo_Annotation::path() const { // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.Annotation.path) - return path_; + return _internal_path(); } -inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* +GeneratedCodeInfo_Annotation::_internal_mutable_path() { + return &path_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >* GeneratedCodeInfo_Annotation::mutable_path() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.Annotation.path) - return &path_; + return _internal_mutable_path(); } // optional string source_file = 2; -inline bool GeneratedCodeInfo_Annotation::has_source_file() const { - return (_has_bits_[0] & 0x00000001u) != 0; +inline bool GeneratedCodeInfo_Annotation::_internal_has_source_file() const { + bool value = (_has_bits_[0] & 0x00000001u) != 0; + return value; } -inline void GeneratedCodeInfo_Annotation::set_has_source_file() { - _has_bits_[0] |= 0x00000001u; -} -inline void GeneratedCodeInfo_Annotation::clear_has_source_file() { - _has_bits_[0] &= ~0x00000001u; +inline bool GeneratedCodeInfo_Annotation::has_source_file() const { + return _internal_has_source_file(); } inline void GeneratedCodeInfo_Annotation::clear_source_file() { - source_file_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_source_file(); + source_file_.ClearToEmpty(); + _has_bits_[0] &= ~0x00000001u; } -inline const ::std::string& GeneratedCodeInfo_Annotation::source_file() const { +inline const std::string& GeneratedCodeInfo_Annotation::source_file() const { // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.source_file) - return source_file_.GetNoArena(); + return _internal_source_file(); } -inline void GeneratedCodeInfo_Annotation::set_source_file(const ::std::string& value) { - set_has_source_file(); - source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void GeneratedCodeInfo_Annotation::set_source_file(const std::string& value) { + _internal_set_source_file(value); // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.source_file) } -#if LANG_CXX11 -inline void GeneratedCodeInfo_Annotation::set_source_file(::std::string&& value) { - set_has_source_file(); - source_file_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); +inline std::string* GeneratedCodeInfo_Annotation::mutable_source_file() { + // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.Annotation.source_file) + return _internal_mutable_source_file(); +} +inline const std::string& GeneratedCodeInfo_Annotation::_internal_source_file() const { + return source_file_.Get(); +} +inline void GeneratedCodeInfo_Annotation::_internal_set_source_file(const std::string& value) { + _has_bits_[0] |= 0x00000001u; + source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void GeneratedCodeInfo_Annotation::set_source_file(std::string&& value) { + _has_bits_[0] |= 0x00000001u; + source_file_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.GeneratedCodeInfo.Annotation.source_file) } -#endif inline void GeneratedCodeInfo_Annotation::set_source_file(const char* value) { - GOOGLE_DCHECK(value != NULL); - set_has_source_file(); - source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + GOOGLE_DCHECK(value != nullptr); + _has_bits_[0] |= 0x00000001u; + source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.GeneratedCodeInfo.Annotation.source_file) } -inline void GeneratedCodeInfo_Annotation::set_source_file(const char* value, size_t size) { - set_has_source_file(); - source_file_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); +inline void GeneratedCodeInfo_Annotation::set_source_file(const char* value, + size_t size) { + _has_bits_[0] |= 0x00000001u; + source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.GeneratedCodeInfo.Annotation.source_file) } -inline ::std::string* GeneratedCodeInfo_Annotation::mutable_source_file() { - set_has_source_file(); - // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.Annotation.source_file) - return source_file_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline std::string* GeneratedCodeInfo_Annotation::_internal_mutable_source_file() { + _has_bits_[0] |= 0x00000001u; + return source_file_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* GeneratedCodeInfo_Annotation::release_source_file() { +inline std::string* GeneratedCodeInfo_Annotation::release_source_file() { // @@protoc_insertion_point(field_release:google.protobuf.GeneratedCodeInfo.Annotation.source_file) - clear_has_source_file(); - return source_file_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (!_internal_has_source_file()) { + return nullptr; + } + _has_bits_[0] &= ~0x00000001u; + return source_file_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void GeneratedCodeInfo_Annotation::set_allocated_source_file(::std::string* source_file) { - if (source_file != NULL) { - set_has_source_file(); +inline void GeneratedCodeInfo_Annotation::set_allocated_source_file(std::string* source_file) { + if (source_file != nullptr) { + _has_bits_[0] |= 0x00000001u; } else { - clear_has_source_file(); + _has_bits_[0] &= ~0x00000001u; } - source_file_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), source_file); + source_file_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), source_file, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.GeneratedCodeInfo.Annotation.source_file) } // optional int32 begin = 3; -inline bool GeneratedCodeInfo_Annotation::has_begin() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -inline void GeneratedCodeInfo_Annotation::set_has_begin() { - _has_bits_[0] |= 0x00000002u; +inline bool GeneratedCodeInfo_Annotation::_internal_has_begin() const { + bool value = (_has_bits_[0] & 0x00000002u) != 0; + return value; } -inline void GeneratedCodeInfo_Annotation::clear_has_begin() { - _has_bits_[0] &= ~0x00000002u; +inline bool GeneratedCodeInfo_Annotation::has_begin() const { + return _internal_has_begin(); } inline void GeneratedCodeInfo_Annotation::clear_begin() { begin_ = 0; - clear_has_begin(); + _has_bits_[0] &= ~0x00000002u; } -inline ::google::protobuf::int32 GeneratedCodeInfo_Annotation::begin() const { - // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.begin) +inline ::PROTOBUF_NAMESPACE_ID::int32 GeneratedCodeInfo_Annotation::_internal_begin() const { return begin_; } -inline void GeneratedCodeInfo_Annotation::set_begin(::google::protobuf::int32 value) { - set_has_begin(); +inline ::PROTOBUF_NAMESPACE_ID::int32 GeneratedCodeInfo_Annotation::begin() const { + // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.begin) + return _internal_begin(); +} +inline void GeneratedCodeInfo_Annotation::_internal_set_begin(::PROTOBUF_NAMESPACE_ID::int32 value) { + _has_bits_[0] |= 0x00000002u; begin_ = value; +} +inline void GeneratedCodeInfo_Annotation::set_begin(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_begin(value); // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.begin) } // optional int32 end = 4; -inline bool GeneratedCodeInfo_Annotation::has_end() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -inline void GeneratedCodeInfo_Annotation::set_has_end() { - _has_bits_[0] |= 0x00000004u; +inline bool GeneratedCodeInfo_Annotation::_internal_has_end() const { + bool value = (_has_bits_[0] & 0x00000004u) != 0; + return value; } -inline void GeneratedCodeInfo_Annotation::clear_has_end() { - _has_bits_[0] &= ~0x00000004u; +inline bool GeneratedCodeInfo_Annotation::has_end() const { + return _internal_has_end(); } inline void GeneratedCodeInfo_Annotation::clear_end() { end_ = 0; - clear_has_end(); + _has_bits_[0] &= ~0x00000004u; } -inline ::google::protobuf::int32 GeneratedCodeInfo_Annotation::end() const { - // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.end) +inline ::PROTOBUF_NAMESPACE_ID::int32 GeneratedCodeInfo_Annotation::_internal_end() const { return end_; } -inline void GeneratedCodeInfo_Annotation::set_end(::google::protobuf::int32 value) { - set_has_end(); +inline ::PROTOBUF_NAMESPACE_ID::int32 GeneratedCodeInfo_Annotation::end() const { + // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.end) + return _internal_end(); +} +inline void GeneratedCodeInfo_Annotation::_internal_set_end(::PROTOBUF_NAMESPACE_ID::int32 value) { + _has_bits_[0] |= 0x00000004u; end_ = value; +} +inline void GeneratedCodeInfo_Annotation::set_end(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_end(value); // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.end) } @@ -9306,30 +12781,39 @@ inline void GeneratedCodeInfo_Annotation::set_end(::google::protobuf::int32 valu // GeneratedCodeInfo // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; -inline int GeneratedCodeInfo::annotation_size() const { +inline int GeneratedCodeInfo::_internal_annotation_size() const { return annotation_.size(); } +inline int GeneratedCodeInfo::annotation_size() const { + return _internal_annotation_size(); +} inline void GeneratedCodeInfo::clear_annotation() { annotation_.Clear(); } -inline const ::google::protobuf::GeneratedCodeInfo_Annotation& GeneratedCodeInfo::annotation(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.annotation) - return annotation_.Get(index); -} -inline ::google::protobuf::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::mutable_annotation(int index) { +inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::mutable_annotation(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.annotation) return annotation_.Mutable(index); } -inline ::google::protobuf::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::add_annotation() { - // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.annotation) - return annotation_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation >* GeneratedCodeInfo::mutable_annotation() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.annotation) return &annotation_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation >& +inline const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation& GeneratedCodeInfo::_internal_annotation(int index) const { + return annotation_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation& GeneratedCodeInfo::annotation(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.annotation) + return _internal_annotation(index); +} +inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::_internal_add_annotation() { + return annotation_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::add_annotation() { + // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.annotation) + return _internal_add_annotation(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation >& GeneratedCodeInfo::annotation() const { // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.annotation) return annotation_; @@ -9338,7 +12822,8 @@ GeneratedCodeInfo::annotation() const { #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ -#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS +// ------------------------------------------------------------------- + // ------------------------------------------------------------------- // ------------------------------------------------------------------- @@ -9392,47 +12877,44 @@ GeneratedCodeInfo::annotation() const { // @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE -} // namespace protobuf -} // namespace google - -namespace google { -namespace protobuf { +PROTOBUF_NAMESPACE_OPEN -template <> struct is_proto_enum< ::google::protobuf::FieldDescriptorProto_Type> : ::google::protobuf::internal::true_type {}; +template <> struct is_proto_enum< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type> : ::std::true_type {}; template <> -inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Type>() { - return ::google::protobuf::FieldDescriptorProto_Type_descriptor(); +inline const EnumDescriptor* GetEnumDescriptor< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type>() { + return PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type_descriptor(); } -template <> struct is_proto_enum< ::google::protobuf::FieldDescriptorProto_Label> : ::google::protobuf::internal::true_type {}; +template <> struct is_proto_enum< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label> : ::std::true_type {}; template <> -inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Label>() { - return ::google::protobuf::FieldDescriptorProto_Label_descriptor(); +inline const EnumDescriptor* GetEnumDescriptor< PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label>() { + return PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label_descriptor(); } -template <> struct is_proto_enum< ::google::protobuf::FileOptions_OptimizeMode> : ::google::protobuf::internal::true_type {}; +template <> struct is_proto_enum< PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode> : ::std::true_type {}; template <> -inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FileOptions_OptimizeMode>() { - return ::google::protobuf::FileOptions_OptimizeMode_descriptor(); +inline const EnumDescriptor* GetEnumDescriptor< PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode>() { + return PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode_descriptor(); } -template <> struct is_proto_enum< ::google::protobuf::FieldOptions_CType> : ::google::protobuf::internal::true_type {}; +template <> struct is_proto_enum< PROTOBUF_NAMESPACE_ID::FieldOptions_CType> : ::std::true_type {}; template <> -inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_CType>() { - return ::google::protobuf::FieldOptions_CType_descriptor(); +inline const EnumDescriptor* GetEnumDescriptor< PROTOBUF_NAMESPACE_ID::FieldOptions_CType>() { + return PROTOBUF_NAMESPACE_ID::FieldOptions_CType_descriptor(); } -template <> struct is_proto_enum< ::google::protobuf::FieldOptions_JSType> : ::google::protobuf::internal::true_type {}; +template <> struct is_proto_enum< PROTOBUF_NAMESPACE_ID::FieldOptions_JSType> : ::std::true_type {}; template <> -inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_JSType>() { - return ::google::protobuf::FieldOptions_JSType_descriptor(); +inline const EnumDescriptor* GetEnumDescriptor< PROTOBUF_NAMESPACE_ID::FieldOptions_JSType>() { + return PROTOBUF_NAMESPACE_ID::FieldOptions_JSType_descriptor(); } -template <> struct is_proto_enum< ::google::protobuf::MethodOptions_IdempotencyLevel> : ::google::protobuf::internal::true_type {}; +template <> struct is_proto_enum< PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel> : ::std::true_type {}; template <> -inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::MethodOptions_IdempotencyLevel>() { - return ::google::protobuf::MethodOptions_IdempotencyLevel_descriptor(); +inline const EnumDescriptor* GetEnumDescriptor< PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel>() { + return PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel_descriptor(); } -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) -#endif // PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index f1ec5735da438..9f0ce6cde0719 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -40,11 +40,13 @@ syntax = "proto2"; package google.protobuf; -option go_package = "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor"; + +option go_package = "google.golang.org/protobuf/types/descriptorpb"; option java_package = "com.google.protobuf"; option java_outer_classname = "DescriptorProtos"; option csharp_namespace = "Google.Protobuf.Reflection"; option objc_class_prefix = "GPB"; +option cc_enable_arenas = true; // descriptor.proto must be optimized for speed because reflection-based // algorithms don't work during bootstrapping. @@ -58,8 +60,8 @@ message FileDescriptorSet { // Describes a complete .proto file. message FileDescriptorProto { - optional string name = 1; // file name, relative to root of source tree - optional string package = 2; // e.g. "foo", "foo.bar", etc. + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. // Names of files imported by this file. repeated string dependency = 3; @@ -99,8 +101,8 @@ message DescriptorProto { repeated EnumDescriptorProto enum_type = 4; message ExtensionRange { - optional int32 start = 1; - optional int32 end = 2; + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. optional ExtensionRangeOptions options = 3; } @@ -114,8 +116,8 @@ message DescriptorProto { // fields or extension ranges in the same message. Reserved ranges may // not overlap. message ReservedRange { - optional int32 start = 1; // Inclusive. - optional int32 end = 2; // Exclusive. + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. } repeated ReservedRange reserved_range = 9; // Reserved field names, which may not be used by fields in the same message. @@ -127,6 +129,7 @@ message ExtensionRangeOptions { // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; + // Clients can define custom options in extensions of this message. See above. extensions 1000 to max; } @@ -136,42 +139,42 @@ message FieldDescriptorProto { enum Type { // 0 is reserved for errors. // Order is weird for historical reasons. - TYPE_DOUBLE = 1; - TYPE_FLOAT = 2; + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if // negative values are likely. - TYPE_INT64 = 3; - TYPE_UINT64 = 4; + TYPE_INT64 = 3; + TYPE_UINT64 = 4; // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if // negative values are likely. - TYPE_INT32 = 5; - TYPE_FIXED64 = 6; - TYPE_FIXED32 = 7; - TYPE_BOOL = 8; - TYPE_STRING = 9; + TYPE_INT32 = 5; + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; // Tag-delimited aggregate. // Group type is deprecated and not supported in proto3. However, Proto3 // implementations should still be able to parse the group wire format and // treat group fields as unknown fields. - TYPE_GROUP = 10; - TYPE_MESSAGE = 11; // Length-delimited aggregate. + TYPE_GROUP = 10; + TYPE_MESSAGE = 11; // Length-delimited aggregate. // New in version 2. - TYPE_BYTES = 12; - TYPE_UINT32 = 13; - TYPE_ENUM = 14; - TYPE_SFIXED32 = 15; - TYPE_SFIXED64 = 16; - TYPE_SINT32 = 17; // Uses ZigZag encoding. - TYPE_SINT64 = 18; // Uses ZigZag encoding. - }; + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + } enum Label { // 0 is reserved for errors - LABEL_OPTIONAL = 1; - LABEL_REQUIRED = 2; - LABEL_REPEATED = 3; - }; + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + } optional string name = 1; optional int32 number = 3; @@ -210,6 +213,29 @@ message FieldDescriptorProto { optional string json_name = 10; optional FieldOptions options = 8; + + // If true, this is a proto3 "optional". When a proto3 field is optional, it + // tracks presence regardless of field type. + // + // When proto3_optional is true, this field must be belong to a oneof to + // signal to old proto3 clients that presence is tracked for this field. This + // oneof is known as a "synthetic" oneof, and this field must be its sole + // member (each proto3 optional field gets its own synthetic oneof). Synthetic + // oneofs exist in the descriptor only, and do not generate any API. Synthetic + // oneofs must be ordered after all "real" oneofs. + // + // For message fields, proto3_optional doesn't create any semantic change, + // since non-repeated message fields always track presence. However it still + // indicates the semantic detail of whether the user wrote "optional" or not. + // This can be useful for round-tripping the .proto file. For consistency we + // give message fields a synthetic oneof also, even though it is not required + // to track presence. This is especially important because the parser can't + // tell if a field is a message or an enum, so it must always create a + // synthetic oneof. + // + // Proto2 optional fields do not set this flag, because they already indicate + // optional with `LABEL_OPTIONAL`. + optional bool proto3_optional = 17; } // Describes a oneof. @@ -225,6 +251,26 @@ message EnumDescriptorProto { repeated EnumValueDescriptorProto value = 2; optional EnumOptions options = 3; + + // Range of reserved numeric values. Reserved values may not be used by + // entries in the same enum. Reserved ranges may not overlap. + // + // Note that this is distinct from DescriptorProto.ReservedRange in that it + // is inclusive such that it can appropriately represent the entire int32 + // domain. + message EnumReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Inclusive. + } + + // Range of reserved numeric values. Reserved numeric values may not be used + // by enum values in the same enum declaration. Reserved ranges may not + // overlap. + repeated EnumReservedRange reserved_range = 4; + + // Reserved enum value names, which may not be reused. A given name may only + // be reserved once. + repeated string reserved_name = 5; } // Describes a value within an enum. @@ -255,9 +301,9 @@ message MethodDescriptorProto { optional MethodOptions options = 4; // Identifies if client streams multiple client messages - optional bool client_streaming = 5 [default=false]; + optional bool client_streaming = 5 [default = false]; // Identifies if server streams multiple server messages - optional bool server_streaming = 6 [default=false]; + optional bool server_streaming = 6 [default = false]; } @@ -293,7 +339,6 @@ message MethodDescriptorProto { // If this turns out to be popular, a web service will be set up // to automatically assign option numbers. - message FileOptions { // Sets the Java package where classes generated from this .proto will be @@ -316,7 +361,7 @@ message FileOptions { // named by java_outer_classname. However, the outer class will still be // generated to contain the file's getDescriptor() method as well as any // top-level extensions defined in the file. - optional bool java_multiple_files = 10 [default=false]; + optional bool java_multiple_files = 10 [default = false]; // This option does nothing. optional bool java_generate_equals_and_hash = 20 [deprecated=true]; @@ -327,17 +372,17 @@ message FileOptions { // Message reflection will do the same. // However, an extension field still accepts non-UTF-8 byte sequences. // This option has no effect on when used with the lite runtime. - optional bool java_string_check_utf8 = 27 [default=false]; + optional bool java_string_check_utf8 = 27 [default = false]; // Generated classes can be optimized for speed or code size. enum OptimizeMode { - SPEED = 1; // Generate complete code for parsing, serialization, - // etc. - CODE_SIZE = 2; // Use ReflectionOps to implement these methods. - LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. } - optional OptimizeMode optimize_for = 9 [default=SPEED]; + optional OptimizeMode optimize_for = 9 [default = SPEED]; // Sets the Go package where structs generated from this .proto will be // placed. If omitted, the Go package will be derived from the following: @@ -348,6 +393,7 @@ message FileOptions { + // Should generic services be generated in each language? "Generic" services // are not specific to any particular RPC system. They are generated by the // main code generators in each language (without additional plugins). @@ -358,20 +404,20 @@ message FileOptions { // that generate code specific to your particular RPC system. Therefore, // these default to false. Old code which depends on generic services should // explicitly set them to true. - optional bool cc_generic_services = 16 [default=false]; - optional bool java_generic_services = 17 [default=false]; - optional bool py_generic_services = 18 [default=false]; - optional bool php_generic_services = 19 [default=false]; + optional bool cc_generic_services = 16 [default = false]; + optional bool java_generic_services = 17 [default = false]; + optional bool py_generic_services = 18 [default = false]; + optional bool php_generic_services = 42 [default = false]; // Is this file deprecated? // Depending on the target platform, this can emit Deprecated annotations // for everything in the file, or it will be completely ignored; in the very // least, this is a formalization for deprecating files. - optional bool deprecated = 23 [default=false]; + optional bool deprecated = 23 [default = false]; // Enables the use of arenas for the proto messages in this file. This applies // only to generated classes for C++. - optional bool cc_enable_arenas = 31 [default=false]; + optional bool cc_enable_arenas = 31 [default = true]; // Sets the objective c class prefix which is prepended to all objective c @@ -396,10 +442,23 @@ message FileOptions { // determining the namespace. optional string php_namespace = 41; - // The parser stores options it doesn't recognize here. See above. + // Use this option to change the namespace of php generated metadata classes. + // Default is empty. When this option is empty, the proto file name will be + // used for determining the namespace. + optional string php_metadata_namespace = 44; + + // Use this option to change the package of ruby generated classes. Default + // is empty. When this option is not set, the package name will be used for + // determining the ruby package. + optional string ruby_package = 45; + + + // The parser stores options it doesn't recognize here. + // See the documentation for the "Options" section above. repeated UninterpretedOption uninterpreted_option = 999; - // Clients can define custom options in extensions of this message. See above. + // Clients can define custom options in extensions of this message. + // See the documentation for the "Options" section above. extensions 1000 to max; reserved 38; @@ -424,18 +483,18 @@ message MessageOptions { // // Because this is an option, the above two restrictions are not enforced by // the protocol compiler. - optional bool message_set_wire_format = 1 [default=false]; + optional bool message_set_wire_format = 1 [default = false]; // Disables the generation of the standard "descriptor()" accessor, which can // conflict with a field of the same name. This is meant to make migration // from proto1 easier; new code should avoid fields named "descriptor". - optional bool no_standard_descriptor_accessor = 2 [default=false]; + optional bool no_standard_descriptor_accessor = 2 [default = false]; // Is this message deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the message, or it will be completely ignored; in the very least, // this is a formalization for deprecating messages. - optional bool deprecated = 3 [default=false]; + optional bool deprecated = 3 [default = false]; // Whether the message is an automatically generated map entry type for the // maps field. @@ -452,7 +511,7 @@ message MessageOptions { // // Implementations may choose not to generate the map_entry=true message, but // use a native map in the target language to hold the keys and values. - // The reflection APIs in such implementions still need to work as + // The reflection APIs in such implementations still need to work as // if the field is a repeated message field. // // NOTE: Do not set the option in .proto files. Always use the maps syntax @@ -463,6 +522,7 @@ message MessageOptions { reserved 8; // javalite_serializable reserved 9; // javanano_as_lite + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -542,16 +602,16 @@ message FieldOptions { // implementation must either *always* check its required fields, or *never* // check its required fields, regardless of whether or not the message has // been parsed. - optional bool lazy = 5 [default=false]; + optional bool lazy = 5 [default = false]; // Is this field deprecated? // Depending on the target platform, this can emit Deprecated annotations // for accessors, or it will be completely ignored; in the very least, this // is a formalization for deprecating fields. - optional bool deprecated = 3 [default=false]; + optional bool deprecated = 3 [default = false]; // For Google-internal migration only. Do not use. - optional bool weak = 10 [default=false]; + optional bool weak = 10 [default = false]; // The parser stores options it doesn't recognize here. See above. @@ -581,7 +641,7 @@ message EnumOptions { // Depending on the target platform, this can emit Deprecated annotations // for the enum, or it will be completely ignored; in the very least, this // is a formalization for deprecating enums. - optional bool deprecated = 3 [default=false]; + optional bool deprecated = 3 [default = false]; reserved 5; // javanano_as_lite @@ -597,7 +657,7 @@ message EnumValueOptions { // Depending on the target platform, this can emit Deprecated annotations // for the enum value, or it will be completely ignored; in the very least, // this is a formalization for deprecating enum values. - optional bool deprecated = 1 [default=false]; + optional bool deprecated = 1 [default = false]; // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -617,7 +677,7 @@ message ServiceOptions { // Depending on the target platform, this can emit Deprecated annotations // for the service, or it will be completely ignored; in the very least, // this is a formalization for deprecating services. - optional bool deprecated = 33 [default=false]; + optional bool deprecated = 33 [default = false]; // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -637,18 +697,18 @@ message MethodOptions { // Depending on the target platform, this can emit Deprecated annotations // for the method, or it will be completely ignored; in the very least, // this is a formalization for deprecating methods. - optional bool deprecated = 33 [default=false]; + optional bool deprecated = 33 [default = false]; // Is this method side-effect-free (or safe in HTTP parlance), or idempotent, // or neither? HTTP based RPC implementation may choose GET verb for safe // methods, and PUT verb for idempotent methods instead of the default POST. enum IdempotencyLevel { IDEMPOTENCY_UNKNOWN = 0; - NO_SIDE_EFFECTS = 1; // implies idempotent - IDEMPOTENT = 2; // idempotent, but may have side effects + NO_SIDE_EFFECTS = 1; // implies idempotent + IDEMPOTENT = 2; // idempotent, but may have side effects } - optional IdempotencyLevel idempotency_level = - 34 [default=IDEMPOTENCY_UNKNOWN]; + optional IdempotencyLevel idempotency_level = 34 + [default = IDEMPOTENCY_UNKNOWN]; // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -729,7 +789,7 @@ message SourceCodeInfo { // beginning of the "extend" block and is shared by all extensions within // the block. // - Just because a location's span is a subset of some other location's span - // does not mean that it is a descendent. For example, a "group" defines + // does not mean that it is a descendant. For example, a "group" defines // both a type and a field in a single declaration. Thus, the locations // corresponding to the type and field and their components will overlap. // - Code which tries to interpret locations should probably be designed to @@ -760,14 +820,14 @@ message SourceCodeInfo { // [ 4, 3, 2, 7 ] // this path refers to the whole field declaration (from the beginning // of the label to the terminating semicolon). - repeated int32 path = 1 [packed=true]; + repeated int32 path = 1 [packed = true]; // Always has exactly three or four elements: start line, start column, // end line (optional, otherwise assumed same as start line), end column. // These are packed into a single field for efficiency. Note that line // and column numbers are zero-based -- typically you will want to add // 1 to each before displaying to a user. - repeated int32 span = 2 [packed=true]; + repeated int32 span = 2 [packed = true]; // If this SourceCodeInfo represents a complete declaration, these are any // comments appearing before and after the declaration which appear to be @@ -832,7 +892,7 @@ message GeneratedCodeInfo { message Annotation { // Identifies the element in the original source .proto file. This field // is formatted the same as SourceCodeInfo.Location.path. - repeated int32 path = 1 [packed=true]; + repeated int32 path = 1 [packed = true]; // Identifies the filesystem path to the original source .proto. optional string source_file = 2; diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc index ba85ef13aa922..5f53cd138185a 100644 --- a/src/google/protobuf/descriptor_database.cc +++ b/src/google/protobuf/descriptor_database.cc @@ -37,23 +37,85 @@ #include #include -#include -#include - #include #include + namespace google { namespace protobuf { +namespace { +void RecordMessageNames(const DescriptorProto& desc_proto, + const std::string& prefix, + std::set* output) { + GOOGLE_CHECK(desc_proto.has_name()); + std::string full_name = prefix.empty() + ? desc_proto.name() + : StrCat(prefix, ".", desc_proto.name()); + output->insert(full_name); + + for (const auto& d : desc_proto.nested_type()) { + RecordMessageNames(d, full_name, output); + } +} + +void RecordMessageNames(const FileDescriptorProto& file_proto, + std::set* output) { + for (const auto& d : file_proto.message_type()) { + RecordMessageNames(d, file_proto.package(), output); + } +} + +template +bool ForAllFileProtos(DescriptorDatabase* db, Fn callback, + std::vector* output) { + std::vector file_names; + if (!db->FindAllFileNames(&file_names)) { + return false; + } + std::set set; + FileDescriptorProto file_proto; + for (const auto& f : file_names) { + file_proto.Clear(); + if (!db->FindFileByName(f, &file_proto)) { + GOOGLE_LOG(ERROR) << "File not found in database (unexpected): " << f; + return false; + } + callback(file_proto, &set); + } + output->insert(output->end(), set.begin(), set.end()); + return true; +} +} // namespace + DescriptorDatabase::~DescriptorDatabase() {} +bool DescriptorDatabase::FindAllPackageNames(std::vector* output) { + return ForAllFileProtos( + this, + [](const FileDescriptorProto& file_proto, std::set* set) { + set->insert(file_proto.package()); + }, + output); +} + +bool DescriptorDatabase::FindAllMessageNames(std::vector* output) { + return ForAllFileProtos( + this, + [](const FileDescriptorProto& file_proto, std::set* set) { + RecordMessageNames(file_proto, set); + }, + output); +} + // =================================================================== +SimpleDescriptorDatabase::SimpleDescriptorDatabase() {} +SimpleDescriptorDatabase::~SimpleDescriptorDatabase() {} + template bool SimpleDescriptorDatabase::DescriptorIndex::AddFile( - const FileDescriptorProto& file, - Value value) { + const FileDescriptorProto& file, Value value) { if (!InsertIfNotPresent(&by_name_, file.name(), value)) { GOOGLE_LOG(ERROR) << "File already exists in database: " << file.name(); return false; @@ -62,19 +124,20 @@ bool SimpleDescriptorDatabase::DescriptorIndex::AddFile( // We must be careful here -- calling file.package() if file.has_package() is // false could access an uninitialized static-storage variable if we are being // run at startup time. - string path = file.has_package() ? file.package() : string(); + std::string path = file.has_package() ? file.package() : std::string(); if (!path.empty()) path += '.'; for (int i = 0; i < file.message_type_size(); i++) { if (!AddSymbol(path + file.message_type(i).name(), value)) return false; - if (!AddNestedExtensions(file.message_type(i), value)) return false; + if (!AddNestedExtensions(file.name(), file.message_type(i), value)) + return false; } for (int i = 0; i < file.enum_type_size(); i++) { if (!AddSymbol(path + file.enum_type(i).name(), value)) return false; } for (int i = 0; i < file.extension_size(); i++) { if (!AddSymbol(path + file.extension(i).name(), value)) return false; - if (!AddExtension(file.extension(i), value)) return false; + if (!AddExtension(file.name(), file.extension(i), value)) return false; } for (int i = 0; i < file.service_size(); i++) { if (!AddSymbol(path + file.service(i).name(), value)) return false; @@ -83,9 +146,55 @@ bool SimpleDescriptorDatabase::DescriptorIndex::AddFile( return true; } +namespace { + +// Returns true if and only if all characters in the name are alphanumerics, +// underscores, or periods. +bool ValidateSymbolName(StringPiece name) { + for (char c : name) { + // I don't trust ctype.h due to locales. :( + if (c != '.' && c != '_' && (c < '0' || c > '9') && (c < 'A' || c > 'Z') && + (c < 'a' || c > 'z')) { + return false; + } + } + return true; +} + +// Find the last key in the container which sorts less than or equal to the +// symbol name. Since upper_bound() returns the *first* key that sorts +// *greater* than the input, we want the element immediately before that. +template +typename Container::const_iterator FindLastLessOrEqual( + const Container* container, const Key& key) { + auto iter = container->upper_bound(key); + if (iter != container->begin()) --iter; + return iter; +} + +// As above, but using std::upper_bound instead. +template +typename Container::const_iterator FindLastLessOrEqual( + const Container* container, const Key& key, const Cmp& cmp) { + auto iter = std::upper_bound(container->begin(), container->end(), key, cmp); + if (iter != container->begin()) --iter; + return iter; +} + +// True if either the arguments are equal or super_symbol identifies a +// parent symbol of sub_symbol (e.g. "foo.bar" is a parent of +// "foo.bar.baz", but not a parent of "foo.barbaz"). +bool IsSubSymbol(StringPiece sub_symbol, StringPiece super_symbol) { + return sub_symbol == super_symbol || + (HasPrefixString(super_symbol, sub_symbol) && + super_symbol[sub_symbol.size()] == '.'); +} + +} // namespace + template bool SimpleDescriptorDatabase::DescriptorIndex::AddSymbol( - const string& name, Value value) { + const std::string& name, Value value) { // We need to make sure not to violate our map invariant. // If the symbol name is invalid it could break our lookup algorithm (which @@ -98,18 +207,20 @@ bool SimpleDescriptorDatabase::DescriptorIndex::AddSymbol( // Try to look up the symbol to make sure a super-symbol doesn't already // exist. - typename std::map::iterator iter = FindLastLessOrEqual(name); + auto iter = FindLastLessOrEqual(&by_symbol_, name); if (iter == by_symbol_.end()) { // Apparently the map is currently empty. Just insert and be done with it. by_symbol_.insert( - typename std::map::value_type(name, value)); + typename std::map::value_type(name, value)); return true; } if (IsSubSymbol(iter->first, name)) { - GOOGLE_LOG(ERROR) << "Symbol name \"" << name << "\" conflicts with the existing " - "symbol \"" << iter->first << "\"."; + GOOGLE_LOG(ERROR) << "Symbol name \"" << name + << "\" conflicts with the existing " + "symbol \"" + << iter->first << "\"."; return false; } @@ -121,8 +232,10 @@ bool SimpleDescriptorDatabase::DescriptorIndex::AddSymbol( ++iter; if (iter != by_symbol_.end() && IsSubSymbol(name, iter->first)) { - GOOGLE_LOG(ERROR) << "Symbol name \"" << name << "\" conflicts with the existing " - "symbol \"" << iter->first << "\"."; + GOOGLE_LOG(ERROR) << "Symbol name \"" << name + << "\" conflicts with the existing " + "symbol \"" + << iter->first << "\"."; return false; } @@ -130,28 +243,29 @@ bool SimpleDescriptorDatabase::DescriptorIndex::AddSymbol( // Insert the new symbol using the iterator as a hint, the new entry will // appear immediately before the one the iterator is pointing at. - by_symbol_.insert(iter, - typename std::map::value_type(name, value)); + by_symbol_.insert( + iter, typename std::map::value_type(name, value)); return true; } template bool SimpleDescriptorDatabase::DescriptorIndex::AddNestedExtensions( - const DescriptorProto& message_type, + const std::string& filename, const DescriptorProto& message_type, Value value) { for (int i = 0; i < message_type.nested_type_size(); i++) { - if (!AddNestedExtensions(message_type.nested_type(i), value)) return false; + if (!AddNestedExtensions(filename, message_type.nested_type(i), value)) + return false; } for (int i = 0; i < message_type.extension_size(); i++) { - if (!AddExtension(message_type.extension(i), value)) return false; + if (!AddExtension(filename, message_type.extension(i), value)) return false; } return true; } template bool SimpleDescriptorDatabase::DescriptorIndex::AddExtension( - const FieldDescriptorProto& field, + const std::string& filename, const FieldDescriptorProto& field, Value value) { if (!field.extendee().empty() && field.extendee()[0] == '.') { // The extension is fully-qualified. We can use it as a lookup key in @@ -161,8 +275,9 @@ bool SimpleDescriptorDatabase::DescriptorIndex::AddExtension( std::make_pair(field.extendee().substr(1), field.number()), value)) { GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: " - "extend " << field.extendee() << " { " - << field.name() << " = " << field.number() << " }"; + "extend " + << field.extendee() << " { " << field.name() << " = " + << field.number() << " } from:" << filename; return false; } } else { @@ -175,32 +290,31 @@ bool SimpleDescriptorDatabase::DescriptorIndex::AddExtension( template Value SimpleDescriptorDatabase::DescriptorIndex::FindFile( - const string& filename) { + const std::string& filename) { return FindWithDefault(by_name_, filename, Value()); } template Value SimpleDescriptorDatabase::DescriptorIndex::FindSymbol( - const string& name) { - typename std::map::iterator iter = FindLastLessOrEqual(name); + const std::string& name) { + auto iter = FindLastLessOrEqual(&by_symbol_, name); - return (iter != by_symbol_.end() && IsSubSymbol(iter->first, name)) ? - iter->second : Value(); + return (iter != by_symbol_.end() && IsSubSymbol(iter->first, name)) + ? iter->second + : Value(); } template Value SimpleDescriptorDatabase::DescriptorIndex::FindExtension( - const string& containing_type, - int field_number) { + const std::string& containing_type, int field_number) { return FindWithDefault( by_extension_, std::make_pair(containing_type, field_number), Value()); } template bool SimpleDescriptorDatabase::DescriptorIndex::FindAllExtensionNumbers( - const string& containing_type, - std::vector* output) { - typename std::map, Value>::const_iterator it = + const std::string& containing_type, std::vector* output) { + typename std::map, Value>::const_iterator it = by_extension_.lower_bound(std::make_pair(containing_type, 0)); bool success = false; @@ -214,48 +328,18 @@ bool SimpleDescriptorDatabase::DescriptorIndex::FindAllExtensionNumbers( } template -typename std::map::iterator -SimpleDescriptorDatabase::DescriptorIndex::FindLastLessOrEqual( - const string& name) { - // Find the last key in the map which sorts less than or equal to the - // symbol name. Since upper_bound() returns the *first* key that sorts - // *greater* than the input, we want the element immediately before that. - typename std::map::iterator iter = - by_symbol_.upper_bound(name); - if (iter != by_symbol_.begin()) --iter; - return iter; -} - -template -bool SimpleDescriptorDatabase::DescriptorIndex::IsSubSymbol( - const string& sub_symbol, const string& super_symbol) { - return sub_symbol == super_symbol || - (HasPrefixString(super_symbol, sub_symbol) && - super_symbol[sub_symbol.size()] == '.'); -} - -template -bool SimpleDescriptorDatabase::DescriptorIndex::ValidateSymbolName( - const string& name) { - for (int i = 0; i < name.size(); i++) { - // I don't trust ctype.h due to locales. :( - if (name[i] != '.' && name[i] != '_' && - (name[i] < '0' || name[i] > '9') && - (name[i] < 'A' || name[i] > 'Z') && - (name[i] < 'a' || name[i] > 'z')) { - return false; - } +void SimpleDescriptorDatabase::DescriptorIndex::FindAllFileNames( + std::vector* output) { + output->resize(by_name_.size()); + int i = 0; + for (const auto& kv : by_name_) { + (*output)[i] = kv.first; + i++; } - return true; } // ------------------------------------------------------------------- -SimpleDescriptorDatabase::SimpleDescriptorDatabase() {} -SimpleDescriptorDatabase::~SimpleDescriptorDatabase() { - STLDeleteElements(&files_to_delete_); -} - bool SimpleDescriptorDatabase::Add(const FileDescriptorProto& file) { FileDescriptorProto* new_file = new FileDescriptorProto; new_file->CopyFrom(file); @@ -263,36 +347,38 @@ bool SimpleDescriptorDatabase::Add(const FileDescriptorProto& file) { } bool SimpleDescriptorDatabase::AddAndOwn(const FileDescriptorProto* file) { - files_to_delete_.push_back(file); + files_to_delete_.emplace_back(file); return index_.AddFile(*file, file); } -bool SimpleDescriptorDatabase::FindFileByName( - const string& filename, - FileDescriptorProto* output) { +bool SimpleDescriptorDatabase::FindFileByName(const std::string& filename, + FileDescriptorProto* output) { return MaybeCopy(index_.FindFile(filename), output); } bool SimpleDescriptorDatabase::FindFileContainingSymbol( - const string& symbol_name, - FileDescriptorProto* output) { + const std::string& symbol_name, FileDescriptorProto* output) { return MaybeCopy(index_.FindSymbol(symbol_name), output); } bool SimpleDescriptorDatabase::FindFileContainingExtension( - const string& containing_type, - int field_number, + const std::string& containing_type, int field_number, FileDescriptorProto* output) { return MaybeCopy(index_.FindExtension(containing_type, field_number), output); } bool SimpleDescriptorDatabase::FindAllExtensionNumbers( - const string& extendee_type, - std::vector* output) { + const std::string& extendee_type, std::vector* output) { return index_.FindAllExtensionNumbers(extendee_type, output); } +bool SimpleDescriptorDatabase::FindAllFileNames( + std::vector* output) { + index_.FindAllFileNames(output); + return true; +} + bool SimpleDescriptorDatabase::MaybeCopy(const FileDescriptorProto* file, FileDescriptorProto* output) { if (file == NULL) return false; @@ -302,18 +388,173 @@ bool SimpleDescriptorDatabase::MaybeCopy(const FileDescriptorProto* file, // ------------------------------------------------------------------- -EncodedDescriptorDatabase::EncodedDescriptorDatabase() {} -EncodedDescriptorDatabase::~EncodedDescriptorDatabase() { - for (int i = 0; i < files_to_delete_.size(); i++) { - operator delete(files_to_delete_[i]); - } -} +class EncodedDescriptorDatabase::DescriptorIndex { + public: + using Value = std::pair; + // Helpers to recursively add particular descriptors and all their contents + // to the index. + template + bool AddFile(const FileProto& file, Value value); + + Value FindFile(StringPiece filename); + Value FindSymbol(StringPiece name); + Value FindSymbolOnlyFlat(StringPiece name) const; + Value FindExtension(StringPiece containing_type, int field_number); + bool FindAllExtensionNumbers(StringPiece containing_type, + std::vector* output); + void FindAllFileNames(std::vector* output) const; + + private: + friend class EncodedDescriptorDatabase; + + bool AddSymbol(StringPiece symbol); + + template + bool AddNestedExtensions(StringPiece filename, + const DescProto& message_type); + template + bool AddExtension(StringPiece filename, const FieldProto& field); + + // All the maps below have two representations: + // - a std::set<> where we insert initially. + // - a std::vector<> where we flatten the structure on demand. + // The initial tree helps avoid O(N) behavior of inserting into a sorted + // vector, while the vector reduces the heap requirements of the data + // structure. + + void EnsureFlat(); + + using String = std::string; + + String EncodeString(StringPiece str) const { return String(str); } + StringPiece DecodeString(const String& str, int) const { return str; } + + struct EncodedEntry { + // Do not use `Value` here to avoid the padding of that object. + const void* data; + int size; + // Keep the package here instead of each SymbolEntry to save space. + String encoded_package; + + Value value() const { return {data, size}; } + }; + std::vector all_values_; + + struct FileEntry { + int data_offset; + String encoded_name; + + StringPiece name(const DescriptorIndex& index) const { + return index.DecodeString(encoded_name, data_offset); + } + }; + struct FileCompare { + const DescriptorIndex& index; + + bool operator()(const FileEntry& a, const FileEntry& b) const { + return a.name(index) < b.name(index); + } + bool operator()(const FileEntry& a, StringPiece b) const { + return a.name(index) < b; + } + bool operator()(StringPiece a, const FileEntry& b) const { + return a < b.name(index); + } + }; + std::set by_name_{FileCompare{*this}}; + std::vector by_name_flat_; + + struct SymbolEntry { + int data_offset; + String encoded_symbol; + + StringPiece package(const DescriptorIndex& index) const { + return index.DecodeString(index.all_values_[data_offset].encoded_package, + data_offset); + } + StringPiece symbol(const DescriptorIndex& index) const { + return index.DecodeString(encoded_symbol, data_offset); + } + + std::string AsString(const DescriptorIndex& index) const { + auto p = package(index); + return StrCat(p, p.empty() ? "" : ".", symbol(index)); + } + }; + + struct SymbolCompare { + const DescriptorIndex& index; -bool EncodedDescriptorDatabase::Add( - const void* encoded_file_descriptor, int size) { + std::string AsString(const SymbolEntry& entry) const { + return entry.AsString(index); + } + static StringPiece AsString(StringPiece str) { return str; } + + std::pair GetParts( + const SymbolEntry& entry) const { + auto package = entry.package(index); + if (package.empty()) return {entry.symbol(index), StringPiece{}}; + return {package, entry.symbol(index)}; + } + std::pair GetParts( + StringPiece str) const { + return {str, {}}; + } + + template + bool operator()(const T& lhs, const U& rhs) const { + auto lhs_parts = GetParts(lhs); + auto rhs_parts = GetParts(rhs); + + // Fast path to avoid making the whole string for common cases. + if (int res = + lhs_parts.first.substr(0, rhs_parts.first.size()) + .compare(rhs_parts.first.substr(0, lhs_parts.first.size()))) { + // If the packages already differ, exit early. + return res < 0; + } else if (lhs_parts.first.size() == rhs_parts.first.size()) { + return lhs_parts.second < rhs_parts.second; + } + return AsString(lhs) < AsString(rhs); + } + }; + std::set by_symbol_{SymbolCompare{*this}}; + std::vector by_symbol_flat_; + + struct ExtensionEntry { + int data_offset; + String encoded_extendee; + StringPiece extendee(const DescriptorIndex& index) const { + return index.DecodeString(encoded_extendee, data_offset).substr(1); + } + int extension_number; + }; + struct ExtensionCompare { + const DescriptorIndex& index; + + bool operator()(const ExtensionEntry& a, const ExtensionEntry& b) const { + return std::make_tuple(a.extendee(index), a.extension_number) < + std::make_tuple(b.extendee(index), b.extension_number); + } + bool operator()(const ExtensionEntry& a, + std::tuple b) const { + return std::make_tuple(a.extendee(index), a.extension_number) < b; + } + bool operator()(std::tuple a, + const ExtensionEntry& b) const { + return a < std::make_tuple(b.extendee(index), b.extension_number); + } + }; + std::set by_extension_{ + ExtensionCompare{*this}}; + std::vector by_extension_flat_; +}; + +bool EncodedDescriptorDatabase::Add(const void* encoded_file_descriptor, + int size) { FileDescriptorProto file; if (file.ParseFromArray(encoded_file_descriptor, size)) { - return index_.AddFile(file, std::make_pair(encoded_file_descriptor, size)); + return index_->AddFile(file, std::make_pair(encoded_file_descriptor, size)); } else { GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to " "EncodedDescriptorDatabase::Add()."; @@ -321,35 +562,32 @@ bool EncodedDescriptorDatabase::Add( } } -bool EncodedDescriptorDatabase::AddCopy( - const void* encoded_file_descriptor, int size) { +bool EncodedDescriptorDatabase::AddCopy(const void* encoded_file_descriptor, + int size) { void* copy = operator new(size); memcpy(copy, encoded_file_descriptor, size); files_to_delete_.push_back(copy); return Add(copy, size); } -bool EncodedDescriptorDatabase::FindFileByName( - const string& filename, - FileDescriptorProto* output) { - return MaybeParse(index_.FindFile(filename), output); +bool EncodedDescriptorDatabase::FindFileByName(const std::string& filename, + FileDescriptorProto* output) { + return MaybeParse(index_->FindFile(filename), output); } bool EncodedDescriptorDatabase::FindFileContainingSymbol( - const string& symbol_name, - FileDescriptorProto* output) { - return MaybeParse(index_.FindSymbol(symbol_name), output); + const std::string& symbol_name, FileDescriptorProto* output) { + return MaybeParse(index_->FindSymbol(symbol_name), output); } bool EncodedDescriptorDatabase::FindNameOfFileContainingSymbol( - const string& symbol_name, - string* output) { - std::pair encoded_file = index_.FindSymbol(symbol_name); + const std::string& symbol_name, std::string* output) { + auto encoded_file = index_->FindSymbol(symbol_name); if (encoded_file.first == NULL) return false; // Optimization: The name should be the first field in the encoded message. // Try to just read it directly. - io::CodedInputStream input(reinterpret_cast(encoded_file.first), + io::CodedInputStream input(static_cast(encoded_file.first), encoded_file.second); const uint32 kNameTag = internal::WireFormatLite::MakeTag( @@ -371,35 +609,289 @@ bool EncodedDescriptorDatabase::FindNameOfFileContainingSymbol( } bool EncodedDescriptorDatabase::FindFileContainingExtension( - const string& containing_type, - int field_number, + const std::string& containing_type, int field_number, FileDescriptorProto* output) { - return MaybeParse(index_.FindExtension(containing_type, field_number), + return MaybeParse(index_->FindExtension(containing_type, field_number), output); } bool EncodedDescriptorDatabase::FindAllExtensionNumbers( - const string& extendee_type, - std::vector* output) { - return index_.FindAllExtensionNumbers(extendee_type, output); + const std::string& extendee_type, std::vector* output) { + return index_->FindAllExtensionNumbers(extendee_type, output); +} + +template +bool EncodedDescriptorDatabase::DescriptorIndex::AddFile(const FileProto& file, + Value value) { + // We push `value` into the array first. This is important because the AddXXX + // functions below will expect it to be there. + all_values_.push_back({value.first, value.second, {}}); + + if (!ValidateSymbolName(file.package())) { + GOOGLE_LOG(ERROR) << "Invalid package name: " << file.package(); + return false; + } + all_values_.back().encoded_package = EncodeString(file.package()); + + if (!InsertIfNotPresent( + &by_name_, FileEntry{static_cast(all_values_.size() - 1), + EncodeString(file.name())}) || + std::binary_search(by_name_flat_.begin(), by_name_flat_.end(), + file.name(), by_name_.key_comp())) { + GOOGLE_LOG(ERROR) << "File already exists in database: " << file.name(); + return false; + } + + for (const auto& message_type : file.message_type()) { + if (!AddSymbol(message_type.name())) return false; + if (!AddNestedExtensions(file.name(), message_type)) return false; + } + for (const auto& enum_type : file.enum_type()) { + if (!AddSymbol(enum_type.name())) return false; + } + for (const auto& extension : file.extension()) { + if (!AddSymbol(extension.name())) return false; + if (!AddExtension(file.name(), extension)) return false; + } + for (const auto& service : file.service()) { + if (!AddSymbol(service.name())) return false; + } + + return true; +} + +template +static bool CheckForMutualSubsymbols(StringPiece symbol_name, Iter* iter, + Iter2 end, const Index& index) { + if (*iter != end) { + if (IsSubSymbol((*iter)->AsString(index), symbol_name)) { + GOOGLE_LOG(ERROR) << "Symbol name \"" << symbol_name + << "\" conflicts with the existing symbol \"" + << (*iter)->AsString(index) << "\"."; + return false; + } + + // OK, that worked. Now we have to make sure that no symbol in the map is + // a sub-symbol of the one we are inserting. The only symbol which could + // be so is the first symbol that is greater than the new symbol. Since + // |iter| points at the last symbol that is less than or equal, we just have + // to increment it. + ++*iter; + + if (*iter != end && IsSubSymbol(symbol_name, (*iter)->AsString(index))) { + GOOGLE_LOG(ERROR) << "Symbol name \"" << symbol_name + << "\" conflicts with the existing symbol \"" + << (*iter)->AsString(index) << "\"."; + return false; + } + } + return true; +} + +bool EncodedDescriptorDatabase::DescriptorIndex::AddSymbol( + StringPiece symbol) { + SymbolEntry entry = {static_cast(all_values_.size() - 1), + EncodeString(symbol)}; + std::string entry_as_string = entry.AsString(*this); + + // We need to make sure not to violate our map invariant. + + // If the symbol name is invalid it could break our lookup algorithm (which + // relies on the fact that '.' sorts before all other characters that are + // valid in symbol names). + if (!ValidateSymbolName(symbol)) { + GOOGLE_LOG(ERROR) << "Invalid symbol name: " << entry_as_string; + return false; + } + + auto iter = FindLastLessOrEqual(&by_symbol_, entry); + if (!CheckForMutualSubsymbols(entry_as_string, &iter, by_symbol_.end(), + *this)) { + return false; + } + + // Same, but on by_symbol_flat_ + auto flat_iter = + FindLastLessOrEqual(&by_symbol_flat_, entry, by_symbol_.key_comp()); + if (!CheckForMutualSubsymbols(entry_as_string, &flat_iter, + by_symbol_flat_.end(), *this)) { + return false; + } + + // OK, no conflicts. + + // Insert the new symbol using the iterator as a hint, the new entry will + // appear immediately before the one the iterator is pointing at. + by_symbol_.insert(iter, entry); + + return true; +} + +template +bool EncodedDescriptorDatabase::DescriptorIndex::AddNestedExtensions( + StringPiece filename, const DescProto& message_type) { + for (const auto& nested_type : message_type.nested_type()) { + if (!AddNestedExtensions(filename, nested_type)) return false; + } + for (const auto& extension : message_type.extension()) { + if (!AddExtension(filename, extension)) return false; + } + return true; +} + +template +bool EncodedDescriptorDatabase::DescriptorIndex::AddExtension( + StringPiece filename, const FieldProto& field) { + if (!field.extendee().empty() && field.extendee()[0] == '.') { + // The extension is fully-qualified. We can use it as a lookup key in + // the by_symbol_ table. + if (!InsertIfNotPresent( + &by_extension_, + ExtensionEntry{static_cast(all_values_.size() - 1), + EncodeString(field.extendee()), field.number()}) || + std::binary_search( + by_extension_flat_.begin(), by_extension_flat_.end(), + std::make_pair(field.extendee().substr(1), field.number()), + by_extension_.key_comp())) { + GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: " + "extend " + << field.extendee() << " { " << field.name() << " = " + << field.number() << " } from:" << filename; + return false; + } + } else { + // Not fully-qualified. We can't really do anything here, unfortunately. + // We don't consider this an error, though, because the descriptor is + // valid. + } + return true; +} + +std::pair +EncodedDescriptorDatabase::DescriptorIndex::FindSymbol(StringPiece name) { + EnsureFlat(); + return FindSymbolOnlyFlat(name); +} + +std::pair +EncodedDescriptorDatabase::DescriptorIndex::FindSymbolOnlyFlat( + StringPiece name) const { + auto iter = + FindLastLessOrEqual(&by_symbol_flat_, name, by_symbol_.key_comp()); + + return iter != by_symbol_flat_.end() && + IsSubSymbol(iter->AsString(*this), name) + ? all_values_[iter->data_offset].value() + : Value(); +} + +std::pair +EncodedDescriptorDatabase::DescriptorIndex::FindExtension( + StringPiece containing_type, int field_number) { + EnsureFlat(); + + auto it = std::lower_bound( + by_extension_flat_.begin(), by_extension_flat_.end(), + std::make_tuple(containing_type, field_number), by_extension_.key_comp()); + return it == by_extension_flat_.end() || + it->extendee(*this) != containing_type || + it->extension_number != field_number + ? std::make_pair(nullptr, 0) + : all_values_[it->data_offset].value(); +} + +template +static void MergeIntoFlat(std::set* s, std::vector* flat) { + if (s->empty()) return; + std::vector new_flat(s->size() + flat->size()); + std::merge(s->begin(), s->end(), flat->begin(), flat->end(), &new_flat[0], + s->key_comp()); + *flat = std::move(new_flat); + s->clear(); +} + +void EncodedDescriptorDatabase::DescriptorIndex::EnsureFlat() { + all_values_.shrink_to_fit(); + // Merge each of the sets into their flat counterpart. + MergeIntoFlat(&by_name_, &by_name_flat_); + MergeIntoFlat(&by_symbol_, &by_symbol_flat_); + MergeIntoFlat(&by_extension_, &by_extension_flat_); +} + +bool EncodedDescriptorDatabase::DescriptorIndex::FindAllExtensionNumbers( + StringPiece containing_type, std::vector* output) { + EnsureFlat(); + + bool success = false; + auto it = std::lower_bound( + by_extension_flat_.begin(), by_extension_flat_.end(), + std::make_tuple(containing_type, 0), by_extension_.key_comp()); + for (; + it != by_extension_flat_.end() && it->extendee(*this) == containing_type; + ++it) { + output->push_back(it->extension_number); + success = true; + } + + return success; +} + +void EncodedDescriptorDatabase::DescriptorIndex::FindAllFileNames( + std::vector* output) const { + output->resize(by_name_.size() + by_name_flat_.size()); + int i = 0; + for (const auto& entry : by_name_) { + (*output)[i] = std::string(entry.name(*this)); + i++; + } + for (const auto& entry : by_name_flat_) { + (*output)[i] = std::string(entry.name(*this)); + i++; + } +} + +std::pair +EncodedDescriptorDatabase::DescriptorIndex::FindFile( + StringPiece filename) { + EnsureFlat(); + + auto it = std::lower_bound(by_name_flat_.begin(), by_name_flat_.end(), + filename, by_name_.key_comp()); + return it == by_name_flat_.end() || it->name(*this) != filename + ? std::make_pair(nullptr, 0) + : all_values_[it->data_offset].value(); +} + + +bool EncodedDescriptorDatabase::FindAllFileNames( + std::vector* output) { + index_->FindAllFileNames(output); + return true; } bool EncodedDescriptorDatabase::MaybeParse( - std::pair encoded_file, - FileDescriptorProto* output) { + std::pair encoded_file, FileDescriptorProto* output) { if (encoded_file.first == NULL) return false; return output->ParseFromArray(encoded_file.first, encoded_file.second); } +EncodedDescriptorDatabase::EncodedDescriptorDatabase() + : index_(new DescriptorIndex()) {} + +EncodedDescriptorDatabase::~EncodedDescriptorDatabase() { + for (void* p : files_to_delete_) { + operator delete(p); + } +} + // =================================================================== DescriptorPoolDatabase::DescriptorPoolDatabase(const DescriptorPool& pool) - : pool_(pool) {} + : pool_(pool) {} DescriptorPoolDatabase::~DescriptorPoolDatabase() {} -bool DescriptorPoolDatabase::FindFileByName( - const string& filename, - FileDescriptorProto* output) { +bool DescriptorPoolDatabase::FindFileByName(const std::string& filename, + FileDescriptorProto* output) { const FileDescriptor* file = pool_.FindFileByName(filename); if (file == NULL) return false; output->Clear(); @@ -408,8 +900,7 @@ bool DescriptorPoolDatabase::FindFileByName( } bool DescriptorPoolDatabase::FindFileContainingSymbol( - const string& symbol_name, - FileDescriptorProto* output) { + const std::string& symbol_name, FileDescriptorProto* output) { const FileDescriptor* file = pool_.FindFileContainingSymbol(symbol_name); if (file == NULL) return false; output->Clear(); @@ -418,14 +909,13 @@ bool DescriptorPoolDatabase::FindFileContainingSymbol( } bool DescriptorPoolDatabase::FindFileContainingExtension( - const string& containing_type, - int field_number, + const std::string& containing_type, int field_number, FileDescriptorProto* output) { const Descriptor* extendee = pool_.FindMessageTypeByName(containing_type); if (extendee == NULL) return false; const FieldDescriptor* extension = - pool_.FindExtensionByNumber(extendee, field_number); + pool_.FindExtensionByNumber(extendee, field_number); if (extension == NULL) return false; output->Clear(); @@ -434,16 +924,15 @@ bool DescriptorPoolDatabase::FindFileContainingExtension( } bool DescriptorPoolDatabase::FindAllExtensionNumbers( - const string& extendee_type, - std::vector* output) { + const std::string& extendee_type, std::vector* output) { const Descriptor* extendee = pool_.FindMessageTypeByName(extendee_type); if (extendee == NULL) return false; std::vector extensions; pool_.FindAllExtensions(extendee, &extensions); - for (int i = 0; i < extensions.size(); ++i) { - output->push_back(extensions[i]->number()); + for (const FieldDescriptor* extension : extensions) { + output->push_back(extension->number()); } return true; @@ -452,21 +941,19 @@ bool DescriptorPoolDatabase::FindAllExtensionNumbers( // =================================================================== MergedDescriptorDatabase::MergedDescriptorDatabase( - DescriptorDatabase* source1, - DescriptorDatabase* source2) { + DescriptorDatabase* source1, DescriptorDatabase* source2) { sources_.push_back(source1); sources_.push_back(source2); } MergedDescriptorDatabase::MergedDescriptorDatabase( const std::vector& sources) - : sources_(sources) {} + : sources_(sources) {} MergedDescriptorDatabase::~MergedDescriptorDatabase() {} -bool MergedDescriptorDatabase::FindFileByName( - const string& filename, - FileDescriptorProto* output) { - for (int i = 0; i < sources_.size(); i++) { - if (sources_[i]->FindFileByName(filename, output)) { +bool MergedDescriptorDatabase::FindFileByName(const std::string& filename, + FileDescriptorProto* output) { + for (DescriptorDatabase* source : sources_) { + if (source->FindFileByName(filename, output)) { return true; } } @@ -474,16 +961,15 @@ bool MergedDescriptorDatabase::FindFileByName( } bool MergedDescriptorDatabase::FindFileContainingSymbol( - const string& symbol_name, - FileDescriptorProto* output) { - for (int i = 0; i < sources_.size(); i++) { + const std::string& symbol_name, FileDescriptorProto* output) { + for (size_t i = 0; i < sources_.size(); i++) { if (sources_[i]->FindFileContainingSymbol(symbol_name, output)) { // The symbol was found in source i. However, if one of the previous // sources defines a file with the same name (which presumably doesn't // contain the symbol, since it wasn't found in that source), then we // must hide it from the caller. FileDescriptorProto temp; - for (int j = 0; j < i; j++) { + for (size_t j = 0; j < i; j++) { if (sources_[j]->FindFileByName(output->name(), &temp)) { // Found conflicting file in a previous source. return false; @@ -496,18 +982,17 @@ bool MergedDescriptorDatabase::FindFileContainingSymbol( } bool MergedDescriptorDatabase::FindFileContainingExtension( - const string& containing_type, - int field_number, + const std::string& containing_type, int field_number, FileDescriptorProto* output) { - for (int i = 0; i < sources_.size(); i++) { - if (sources_[i]->FindFileContainingExtension( - containing_type, field_number, output)) { + for (size_t i = 0; i < sources_.size(); i++) { + if (sources_[i]->FindFileContainingExtension(containing_type, field_number, + output)) { // The symbol was found in source i. However, if one of the previous // sources defines a file with the same name (which presumably doesn't // contain the symbol, since it wasn't found in that source), then we // must hide it from the caller. FileDescriptorProto temp; - for (int j = 0; j < i; j++) { + for (size_t j = 0; j < i; j++) { if (sources_[j]->FindFileByName(output->name(), &temp)) { // Found conflicting file in a previous source. return false; @@ -520,14 +1005,13 @@ bool MergedDescriptorDatabase::FindFileContainingExtension( } bool MergedDescriptorDatabase::FindAllExtensionNumbers( - const string& extendee_type, - std::vector* output) { + const std::string& extendee_type, std::vector* output) { std::set merged_results; std::vector results; bool success = false; - for (int i = 0; i < sources_.size(); i++) { - if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) { + for (DescriptorDatabase* source : sources_) { + if (source->FindAllExtensionNumbers(extendee_type, &results)) { std::copy(results.begin(), results.end(), std::insert_iterator >(merged_results, merged_results.begin())); diff --git a/src/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h index 28f8af7a2da00..5fb593efc65c2 100644 --- a/src/google/protobuf/descriptor_database.h +++ b/src/google/protobuf/descriptor_database.h @@ -44,6 +44,12 @@ #include #include +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + namespace google { namespace protobuf { @@ -62,27 +68,27 @@ class MergedDescriptorDatabase; // calling DescriptorPool::BuildFile() for each one. Instead, a DescriptorPool // can be created which wraps a DescriptorDatabase and only builds particular // descriptors when they are needed. -class LIBPROTOBUF_EXPORT DescriptorDatabase { +class PROTOBUF_EXPORT DescriptorDatabase { public: inline DescriptorDatabase() {} virtual ~DescriptorDatabase(); // Find a file by file name. Fills in in *output and returns true if found. // Otherwise, returns false, leaving the contents of *output undefined. - virtual bool FindFileByName(const string& filename, + virtual bool FindFileByName(const std::string& filename, FileDescriptorProto* output) = 0; // Find the file that declares the given fully-qualified symbol name. // If found, fills in *output and returns true, otherwise returns false // and leaves *output undefined. - virtual bool FindFileContainingSymbol(const string& symbol_name, + virtual bool FindFileContainingSymbol(const std::string& symbol_name, FileDescriptorProto* output) = 0; // Find the file which defines an extension extending the given message type // with the given field number. If found, fills in *output and returns true, // otherwise returns false and leaves *output undefined. containing_type // must be a fully-qualified type name. - virtual bool FindFileContainingExtension(const string& containing_type, + virtual bool FindFileContainingExtension(const std::string& containing_type, int field_number, FileDescriptorProto* output) = 0; @@ -96,7 +102,7 @@ class LIBPROTOBUF_EXPORT DescriptorDatabase { // // This method has a default implementation that always returns // false. - virtual bool FindAllExtensionNumbers(const string& /* extendee_type */, + virtual bool FindAllExtensionNumbers(const std::string& /* extendee_type */, std::vector* /* output */) { return false; } @@ -110,10 +116,24 @@ class LIBPROTOBUF_EXPORT DescriptorDatabase { // // This method has a default implementation that always returns // false. - virtual bool FindAllFileNames(std::vector* output) { + virtual bool FindAllFileNames(std::vector* /*output*/) { return false; } + // Finds the package names and appends them to the output in an + // undefined order. This method is best-effort: it's not guaranteed that the + // database will find all packages. Returns true if the database supports + // searching all package names, otherwise returns false and leaves output + // unchanged. + bool FindAllPackageNames(std::vector* output); + + // Finds the message names and appends them to the output in an + // undefined order. This method is best-effort: it's not guaranteed that the + // database will find all messages. Returns true if the database supports + // searching all message names, otherwise returns false and leaves output + // unchanged. + bool FindAllMessageNames(std::vector* output); + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorDatabase); }; @@ -139,10 +159,10 @@ class LIBPROTOBUF_EXPORT DescriptorDatabase { // FileDescriptor::CopyTo()) will always use fully-qualified names for all // types. You only need to worry if you are constructing FileDescriptorProtos // yourself, or are calling compiler::Parser directly. -class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase { +class PROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase { public: SimpleDescriptorDatabase(); - ~SimpleDescriptorDatabase(); + ~SimpleDescriptorDatabase() override; // Adds the FileDescriptorProto to the database, making a copy. The object // can be deleted after Add() returns. Returns false if the file conflicted @@ -154,20 +174,19 @@ class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase { bool AddAndOwn(const FileDescriptorProto* file); // implements DescriptorDatabase ----------------------------------- - bool FindFileByName(const string& filename, - FileDescriptorProto* output); - bool FindFileContainingSymbol(const string& symbol_name, - FileDescriptorProto* output); - bool FindFileContainingExtension(const string& containing_type, + bool FindFileByName(const std::string& filename, + FileDescriptorProto* output) override; + bool FindFileContainingSymbol(const std::string& symbol_name, + FileDescriptorProto* output) override; + bool FindFileContainingExtension(const std::string& containing_type, int field_number, - FileDescriptorProto* output); - bool FindAllExtensionNumbers(const string& extendee_type, - std::vector* output); + FileDescriptorProto* output) override; + bool FindAllExtensionNumbers(const std::string& extendee_type, + std::vector* output) override; - private: - // So that it can use DescriptorIndex. - friend class EncodedDescriptorDatabase; + bool FindAllFileNames(std::vector* output) override; + private: // An index mapping file names, symbol names, and extension numbers to // some sort of values. template @@ -175,24 +194,24 @@ class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase { public: // Helpers to recursively add particular descriptors and all their contents // to the index. - bool AddFile(const FileDescriptorProto& file, - Value value); - bool AddSymbol(const string& name, Value value); - bool AddNestedExtensions(const DescriptorProto& message_type, - Value value); - bool AddExtension(const FieldDescriptorProto& field, - Value value); - - Value FindFile(const string& filename); - Value FindSymbol(const string& name); - Value FindExtension(const string& containing_type, int field_number); - bool FindAllExtensionNumbers(const string& containing_type, + bool AddFile(const FileDescriptorProto& file, Value value); + bool AddSymbol(const std::string& name, Value value); + bool AddNestedExtensions(const std::string& filename, + const DescriptorProto& message_type, Value value); + bool AddExtension(const std::string& filename, + const FieldDescriptorProto& field, Value value); + + Value FindFile(const std::string& filename); + Value FindSymbol(const std::string& name); + Value FindExtension(const std::string& containing_type, int field_number); + bool FindAllExtensionNumbers(const std::string& containing_type, std::vector* output); + void FindAllFileNames(std::vector* output); private: - std::map by_name_; - std::map by_symbol_; - std::map, Value> by_extension_; + std::map by_name_; + std::map by_symbol_; + std::map, Value> by_extension_; // Invariant: The by_symbol_ map does not contain any symbols which are // prefixes of other symbols in the map. For example, "foo.bar" is a @@ -214,7 +233,7 @@ class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase { // will find it. Proof: // 1) Define the "search key" to be the key we are looking for, the "found // key" to be the key found in step (1), and the "match key" to be the - // key which actually matches the serach key (i.e. the key we're trying + // key which actually matches the search key (i.e. the key we're trying // to find). // 2) The found key must be less than or equal to the search key by // definition. @@ -244,30 +263,14 @@ class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase { // That symbol cannot be a super-symbol of the search key since if it were, // then it would be a match, and we're assuming the match key doesn't exist. // Therefore, step 2 will correctly return no match. - - // Find the last entry in the by_symbol_ map whose key is less than or - // equal to the given name. - typename std::map::iterator FindLastLessOrEqual( - const string& name); - - // True if either the arguments are equal or super_symbol identifies a - // parent symbol of sub_symbol (e.g. "foo.bar" is a parent of - // "foo.bar.baz", but not a parent of "foo.barbaz"). - bool IsSubSymbol(const string& sub_symbol, const string& super_symbol); - - // Returns true if and only if all characters in the name are alphanumerics, - // underscores, or periods. - bool ValidateSymbolName(const string& name); }; - DescriptorIndex index_; - std::vector files_to_delete_; + std::vector> files_to_delete_; // If file is non-NULL, copy it into *output and return true, otherwise // return false. - bool MaybeCopy(const FileDescriptorProto* file, - FileDescriptorProto* output); + bool MaybeCopy(const FileDescriptorProto* file, FileDescriptorProto* output); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleDescriptorDatabase); }; @@ -277,10 +280,10 @@ class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase { // // The same caveats regarding FindFileContainingExtension() apply as with // SimpleDescriptorDatabase. -class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase { +class PROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase { public: EncodedDescriptorDatabase(); - ~EncodedDescriptorDatabase(); + ~EncodedDescriptorDatabase() override; // Adds the FileDescriptorProto to the database. The descriptor is provided // in encoded form. The database does not make a copy of the bytes, nor @@ -295,23 +298,26 @@ class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase { bool AddCopy(const void* encoded_file_descriptor, int size); // Like FindFileContainingSymbol but returns only the name of the file. - bool FindNameOfFileContainingSymbol(const string& symbol_name, - string* output); + bool FindNameOfFileContainingSymbol(const std::string& symbol_name, + std::string* output); // implements DescriptorDatabase ----------------------------------- - bool FindFileByName(const string& filename, - FileDescriptorProto* output); - bool FindFileContainingSymbol(const string& symbol_name, - FileDescriptorProto* output); - bool FindFileContainingExtension(const string& containing_type, + bool FindFileByName(const std::string& filename, + FileDescriptorProto* output) override; + bool FindFileContainingSymbol(const std::string& symbol_name, + FileDescriptorProto* output) override; + bool FindFileContainingExtension(const std::string& containing_type, int field_number, - FileDescriptorProto* output); - bool FindAllExtensionNumbers(const string& extendee_type, - std::vector* output); + FileDescriptorProto* output) override; + bool FindAllExtensionNumbers(const std::string& extendee_type, + std::vector* output) override; + bool FindAllFileNames(std::vector* output) override; private: - SimpleDescriptorDatabase::DescriptorIndex > - index_; + class DescriptorIndex; + // Keep DescriptorIndex by pointer to hide the implementation to keep a + // cleaner header. + std::unique_ptr index_; std::vector files_to_delete_; // If encoded_file.first is non-NULL, parse the data into *output and return @@ -323,21 +329,21 @@ class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase { }; // A DescriptorDatabase that fetches files from a given pool. -class LIBPROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase { +class PROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase { public: explicit DescriptorPoolDatabase(const DescriptorPool& pool); - ~DescriptorPoolDatabase(); + ~DescriptorPoolDatabase() override; // implements DescriptorDatabase ----------------------------------- - bool FindFileByName(const string& filename, - FileDescriptorProto* output); - bool FindFileContainingSymbol(const string& symbol_name, - FileDescriptorProto* output); - bool FindFileContainingExtension(const string& containing_type, + bool FindFileByName(const std::string& filename, + FileDescriptorProto* output) override; + bool FindFileContainingSymbol(const std::string& symbol_name, + FileDescriptorProto* output) override; + bool FindFileContainingExtension(const std::string& containing_type, int field_number, - FileDescriptorProto* output); - bool FindAllExtensionNumbers(const string& extendee_type, - std::vector* output); + FileDescriptorProto* output) override; + bool FindAllExtensionNumbers(const std::string& extendee_type, + std::vector* output) override; private: const DescriptorPool& pool_; @@ -346,7 +352,7 @@ class LIBPROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase { // A DescriptorDatabase that wraps two or more others. It first searches the // first database and, if that fails, tries the second, and so on. -class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase { +class PROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase { public: // Merge just two databases. The sources remain property of the caller. MergedDescriptorDatabase(DescriptorDatabase* source1, @@ -356,20 +362,20 @@ class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase { // DescriptorDatabases need to stick around. explicit MergedDescriptorDatabase( const std::vector& sources); - ~MergedDescriptorDatabase(); + ~MergedDescriptorDatabase() override; // implements DescriptorDatabase ----------------------------------- - bool FindFileByName(const string& filename, - FileDescriptorProto* output); - bool FindFileContainingSymbol(const string& symbol_name, - FileDescriptorProto* output); - bool FindFileContainingExtension(const string& containing_type, + bool FindFileByName(const std::string& filename, + FileDescriptorProto* output) override; + bool FindFileContainingSymbol(const std::string& symbol_name, + FileDescriptorProto* output) override; + bool FindFileContainingExtension(const std::string& containing_type, int field_number, - FileDescriptorProto* output); + FileDescriptorProto* output) override; // Merges the results of calling all databases. Returns true iff any // of the databases returned true. - bool FindAllExtensionNumbers(const string& extendee_type, - std::vector* output); + bool FindAllExtensionNumbers(const std::string& extendee_type, + std::vector* output) override; private: @@ -378,6 +384,8 @@ class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase { }; } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__ diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc index 7e81d70af236e..fba0b95a84dbe 100644 --- a/src/google/protobuf/descriptor_database_unittest.cc +++ b/src/google/protobuf/descriptor_database_unittest.cc @@ -34,22 +34,21 @@ // // This file makes extensive use of RFC 3092. :) +#include + #include #include -#ifndef _SHARED_PTR_H -#include -#endif - -#include -#include -#include -#include #include #include +#include +#include +#include +#include #include #include + namespace google { namespace protobuf { namespace { @@ -62,12 +61,11 @@ static void AddToDatabase(SimpleDescriptorDatabase* database, } static void ExpectContainsType(const FileDescriptorProto& proto, - const string& type_name) { + const std::string& type_name) { for (int i = 0; i < proto.message_type_size(); i++) { if (proto.message_type(i).name() == type_name) return; } - ADD_FAILURE() << "\"" << proto.name() - << "\" did not contain expected type \"" + ADD_FAILURE() << "\"" << proto.name() << "\" did not contain expected type \"" << type_name << "\"."; } @@ -80,7 +78,7 @@ static void ExpectContainsType(const FileDescriptorProto& proto, // three nearly-identical sets of tests, we use parameterized tests to apply // the same code to all three. -// The parameterized test runs against a DescriptarDatabaseTestCase. We have +// The parameterized test runs against a DescriptorDatabaseTestCase. We have // implementations for each of the three classes we want to test. class DescriptorDatabaseTestCase { public: @@ -102,9 +100,7 @@ class SimpleDescriptorDatabaseTestCase : public DescriptorDatabaseTestCase { virtual ~SimpleDescriptorDatabaseTestCase() {} - virtual DescriptorDatabase* GetDatabase() { - return &database_; - } + virtual DescriptorDatabase* GetDatabase() { return &database_; } virtual bool AddToDatabase(const FileDescriptorProto& file) { return database_.Add(file); } @@ -122,11 +118,9 @@ class EncodedDescriptorDatabaseTestCase : public DescriptorDatabaseTestCase { virtual ~EncodedDescriptorDatabaseTestCase() {} - virtual DescriptorDatabase* GetDatabase() { - return &database_; - } + virtual DescriptorDatabase* GetDatabase() { return &database_; } virtual bool AddToDatabase(const FileDescriptorProto& file) { - string data; + std::string data; file.SerializeToString(&data); return database_.AddCopy(data.data(), data.size()); } @@ -145,9 +139,7 @@ class DescriptorPoolDatabaseTestCase : public DescriptorDatabaseTestCase { DescriptorPoolDatabaseTestCase() : database_(pool_) {} virtual ~DescriptorPoolDatabaseTestCase() {} - virtual DescriptorDatabase* GetDatabase() { - return &database_; - } + virtual DescriptorDatabase* GetDatabase() { return &database_; } virtual bool AddToDatabase(const FileDescriptorProto& file) { return pool_.BuildFile(file); } @@ -179,17 +171,17 @@ class DescriptorDatabaseTest EXPECT_FALSE(test_case_->AddToDatabase(file_proto)); } - google::protobuf::scoped_ptr test_case_; + std::unique_ptr test_case_; DescriptorDatabase* database_; }; TEST_P(DescriptorDatabaseTest, FindFileByName) { AddToDatabase( - "name: \"foo.proto\" " - "message_type { name:\"Foo\" }"); + "name: \"foo.proto\" " + "message_type { name:\"Foo\" }"); AddToDatabase( - "name: \"bar.proto\" " - "message_type { name:\"Bar\" }"); + "name: \"bar.proto\" " + "message_type { name:\"Bar\" }"); { FileDescriptorProto file; @@ -214,27 +206,26 @@ TEST_P(DescriptorDatabaseTest, FindFileByName) { TEST_P(DescriptorDatabaseTest, FindFileContainingSymbol) { AddToDatabase( - "name: \"foo.proto\" " - "message_type { " - " name: \"Foo\" " - " field { name:\"qux\" }" - " nested_type { name: \"Grault\" } " - " enum_type { name: \"Garply\" } " - "} " - "enum_type { " - " name: \"Waldo\" " - " value { name:\"FRED\" } " - "} " - "extension { name: \"plugh\" } " - "service { " - " name: \"Xyzzy\" " - " method { name: \"Thud\" } " - "}" - ); + "name: \"foo.proto\" " + "message_type { " + " name: \"Foo\" " + " field { name:\"qux\" }" + " nested_type { name: \"Grault\" } " + " enum_type { name: \"Garply\" } " + "} " + "enum_type { " + " name: \"Waldo\" " + " value { name:\"FRED\" } " + "} " + "extension { name: \"plugh\" } " + "service { " + " name: \"Xyzzy\" " + " method { name: \"Thud\" } " + "}"); AddToDatabase( - "name: \"bar.proto\" " - "package: \"corge\" " - "message_type { name: \"Bar\" }"); + "name: \"bar.proto\" " + "package: \"corge\" " + "message_type { name: \"Bar\" }"); { FileDescriptorProto file; @@ -247,6 +238,10 @@ TEST_P(DescriptorDatabaseTest, FindFileContainingSymbol) { FileDescriptorProto file; EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.qux", &file)); EXPECT_EQ("foo.proto", file.name()); + // Non-existent field under a valid top level symbol can also be + // found. + EXPECT_TRUE( + database_->FindFileContainingSymbol("Foo.none_field.none", &file)); } { @@ -320,24 +315,25 @@ TEST_P(DescriptorDatabaseTest, FindFileContainingSymbol) { TEST_P(DescriptorDatabaseTest, FindFileContainingExtension) { AddToDatabase( - "name: \"foo.proto\" " - "message_type { " - " name: \"Foo\" " - " extension_range { start: 1 end: 1000 } " - " extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 " - " extendee: \".Foo\" }" - "}"); + "name: \"foo.proto\" " + "message_type { " + " name: \"Foo\" " + " extension_range { start: 1 end: 1000 } " + " extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 " + "number:5 " + " extendee: \".Foo\" }" + "}"); AddToDatabase( - "name: \"bar.proto\" " - "package: \"corge\" " - "dependency: \"foo.proto\" " - "message_type { " - " name: \"Bar\" " - " extension_range { start: 1 end: 1000 } " - "} " - "extension { name:\"grault\" extendee: \".Foo\" number:32 } " - "extension { name:\"garply\" extendee: \".corge.Bar\" number:70 } " - "extension { name:\"waldo\" extendee: \"Bar\" number:56 } "); + "name: \"bar.proto\" " + "package: \"corge\" " + "dependency: \"foo.proto\" " + "message_type { " + " name: \"Bar\" " + " extension_range { start: 1 end: 1000 } " + "} " + "extension { name:\"grault\" extendee: \".Foo\" number:32 } " + "extension { name:\"garply\" extendee: \".corge.Bar\" number:70 } " + "extension { name:\"waldo\" extendee: \"Bar\" number:56 } "); { FileDescriptorProto file; @@ -389,24 +385,25 @@ TEST_P(DescriptorDatabaseTest, FindFileContainingExtension) { TEST_P(DescriptorDatabaseTest, FindAllExtensionNumbers) { AddToDatabase( - "name: \"foo.proto\" " - "message_type { " - " name: \"Foo\" " - " extension_range { start: 1 end: 1000 } " - " extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 " - " extendee: \".Foo\" }" - "}"); + "name: \"foo.proto\" " + "message_type { " + " name: \"Foo\" " + " extension_range { start: 1 end: 1000 } " + " extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 " + "number:5 " + " extendee: \".Foo\" }" + "}"); AddToDatabase( - "name: \"bar.proto\" " - "package: \"corge\" " - "dependency: \"foo.proto\" " - "message_type { " - " name: \"Bar\" " - " extension_range { start: 1 end: 1000 } " - "} " - "extension { name:\"grault\" extendee: \".Foo\" number:32 } " - "extension { name:\"garply\" extendee: \".corge.Bar\" number:70 } " - "extension { name:\"waldo\" extendee: \"Bar\" number:56 } "); + "name: \"bar.proto\" " + "package: \"corge\" " + "dependency: \"foo.proto\" " + "message_type { " + " name: \"Bar\" " + " extension_range { start: 1 end: 1000 } " + "} " + "extension { name:\"grault\" extendee: \".Foo\" number:32 } " + "extension { name:\"garply\" extendee: \".corge.Bar\" number:70 } " + "extension { name:\"waldo\" extendee: \"Bar\" number:56 } "); { std::vector numbers; @@ -440,47 +437,49 @@ TEST_P(DescriptorDatabaseTest, FindAllExtensionNumbers) { TEST_P(DescriptorDatabaseTest, ConflictingFileError) { AddToDatabase( - "name: \"foo.proto\" " - "message_type { " - " name: \"Foo\" " - "}"); + "name: \"foo.proto\" " + "message_type { " + " name: \"Foo\" " + "}"); AddToDatabaseWithError( - "name: \"foo.proto\" " - "message_type { " - " name: \"Bar\" " - "}"); + "name: \"foo.proto\" " + "message_type { " + " name: \"Bar\" " + "}"); } TEST_P(DescriptorDatabaseTest, ConflictingTypeError) { AddToDatabase( - "name: \"foo.proto\" " - "message_type { " - " name: \"Foo\" " - "}"); + "name: \"foo.proto\" " + "message_type { " + " name: \"Foo\" " + "}"); AddToDatabaseWithError( - "name: \"bar.proto\" " - "message_type { " - " name: \"Foo\" " - "}"); + "name: \"bar.proto\" " + "message_type { " + " name: \"Foo\" " + "}"); } TEST_P(DescriptorDatabaseTest, ConflictingExtensionError) { AddToDatabase( - "name: \"foo.proto\" " - "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 " - " extendee: \".Foo\" }"); + "name: \"foo.proto\" " + "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 " + " extendee: \".Foo\" }"); AddToDatabaseWithError( - "name: \"bar.proto\" " - "extension { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 " - " extendee: \".Foo\" }"); + "name: \"bar.proto\" " + "extension { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 " + " extendee: \".Foo\" }"); } -INSTANTIATE_TEST_CASE_P(Simple, DescriptorDatabaseTest, +INSTANTIATE_TEST_CASE_P( + Simple, DescriptorDatabaseTest, testing::Values(&SimpleDescriptorDatabaseTestCase::New)); -INSTANTIATE_TEST_CASE_P(MemoryConserving, DescriptorDatabaseTest, +INSTANTIATE_TEST_CASE_P( + MemoryConserving, DescriptorDatabaseTest, testing::Values(&EncodedDescriptorDatabaseTestCase::New)); INSTANTIATE_TEST_CASE_P(Pool, DescriptorDatabaseTest, - testing::Values(&DescriptorPoolDatabaseTestCase::New)); + testing::Values(&DescriptorPoolDatabaseTestCase::New)); #endif // GTEST_HAS_PARAM_TEST @@ -495,10 +494,10 @@ TEST(EncodedDescriptorDatabaseExtraTest, FindNameOfFileContainingSymbol) { file2b.add_message_type()->set_name("Bar"); // Normal serialization allows our optimization to kick in. - string data1 = file1.SerializeAsString(); + std::string data1 = file1.SerializeAsString(); // Force out-of-order serialization to test slow path. - string data2 = file2b.SerializeAsString() + file2a.SerializeAsString(); + std::string data2 = file2b.SerializeAsString() + file2a.SerializeAsString(); // Create EncodedDescriptorDatabase containing both files. EncodedDescriptorDatabase db; @@ -506,7 +505,7 @@ TEST(EncodedDescriptorDatabaseExtraTest, FindNameOfFileContainingSymbol) { db.Add(data2.data(), data2.size()); // Test! - string filename; + std::string filename; EXPECT_TRUE(db.FindNameOfFileContainingSymbol("foo.Foo", &filename)); EXPECT_EQ("foo.proto", filename); EXPECT_TRUE(db.FindNameOfFileContainingSymbol("foo.Foo.Blah", &filename)); @@ -518,41 +517,100 @@ TEST(EncodedDescriptorDatabaseExtraTest, FindNameOfFileContainingSymbol) { EXPECT_FALSE(db.FindNameOfFileContainingSymbol("baz.Baz", &filename)); } +TEST(SimpleDescriptorDatabaseExtraTest, FindAllFileNames) { + FileDescriptorProto f; + f.set_name("foo.proto"); + f.set_package("foo"); + f.add_message_type()->set_name("Foo"); + + SimpleDescriptorDatabase db; + db.Add(f); + + // Test! + std::vector all_files; + db.FindAllFileNames(&all_files); + EXPECT_THAT(all_files, testing::ElementsAre("foo.proto")); +} + +TEST(SimpleDescriptorDatabaseExtraTest, FindAllPackageNames) { + FileDescriptorProto f; + f.set_name("foo.proto"); + f.set_package("foo"); + f.add_message_type()->set_name("Foo"); + + FileDescriptorProto b; + b.set_name("bar.proto"); + b.set_package(""); + b.add_message_type()->set_name("Bar"); + + SimpleDescriptorDatabase db; + db.Add(f); + db.Add(b); + + std::vector packages; + EXPECT_TRUE(db.FindAllPackageNames(&packages)); + EXPECT_THAT(packages, ::testing::UnorderedElementsAre("foo", "")); +} + +TEST(SimpleDescriptorDatabaseExtraTest, FindAllMessageNames) { + FileDescriptorProto f; + f.set_name("foo.proto"); + f.set_package("foo"); + f.add_message_type()->set_name("Foo"); + + FileDescriptorProto b; + b.set_name("bar.proto"); + b.set_package(""); + b.add_message_type()->set_name("Bar"); + + SimpleDescriptorDatabase db; + db.Add(f); + db.Add(b); + + std::vector messages; + EXPECT_TRUE(db.FindAllMessageNames(&messages)); + EXPECT_THAT(messages, ::testing::UnorderedElementsAre("foo.Foo", "Bar")); +} + // =================================================================== class MergedDescriptorDatabaseTest : public testing::Test { protected: MergedDescriptorDatabaseTest() - : forward_merged_(&database1_, &database2_), - reverse_merged_(&database2_, &database1_) {} + : forward_merged_(&database1_, &database2_), + reverse_merged_(&database2_, &database1_) {} virtual void SetUp() { - AddToDatabase(&database1_, - "name: \"foo.proto\" " - "message_type { name:\"Foo\" extension_range { start: 1 end: 100 } } " - "extension { name:\"foo_ext\" extendee: \".Foo\" number:3 " - " label:LABEL_OPTIONAL type:TYPE_INT32 } "); - AddToDatabase(&database2_, - "name: \"bar.proto\" " - "message_type { name:\"Bar\" extension_range { start: 1 end: 100 } } " - "extension { name:\"bar_ext\" extendee: \".Bar\" number:5 " - " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + AddToDatabase( + &database1_, + "name: \"foo.proto\" " + "message_type { name:\"Foo\" extension_range { start: 1 end: 100 } } " + "extension { name:\"foo_ext\" extendee: \".Foo\" number:3 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + AddToDatabase( + &database2_, + "name: \"bar.proto\" " + "message_type { name:\"Bar\" extension_range { start: 1 end: 100 } } " + "extension { name:\"bar_ext\" extendee: \".Bar\" number:5 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } "); // baz.proto exists in both pools, with different definitions. - AddToDatabase(&database1_, - "name: \"baz.proto\" " - "message_type { name:\"Baz\" extension_range { start: 1 end: 100 } } " - "message_type { name:\"FromPool1\" } " - "extension { name:\"baz_ext\" extendee: \".Baz\" number:12 " - " label:LABEL_OPTIONAL type:TYPE_INT32 } " - "extension { name:\"database1_only_ext\" extendee: \".Baz\" number:13 " - " label:LABEL_OPTIONAL type:TYPE_INT32 } "); - AddToDatabase(&database2_, - "name: \"baz.proto\" " - "message_type { name:\"Baz\" extension_range { start: 1 end: 100 } } " - "message_type { name:\"FromPool2\" } " - "extension { name:\"baz_ext\" extendee: \".Baz\" number:12 " - " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + AddToDatabase( + &database1_, + "name: \"baz.proto\" " + "message_type { name:\"Baz\" extension_range { start: 1 end: 100 } } " + "message_type { name:\"FromPool1\" } " + "extension { name:\"baz_ext\" extendee: \".Baz\" number:12 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } " + "extension { name:\"database1_only_ext\" extendee: \".Baz\" number:13 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + AddToDatabase( + &database2_, + "name: \"baz.proto\" " + "message_type { name:\"Baz\" extension_range { start: 1 end: 100 } } " + "message_type { name:\"FromPool2\" } " + "extension { name:\"baz_ext\" extendee: \".Baz\" number:12 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } "); } SimpleDescriptorDatabase database1_; @@ -646,8 +704,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindFileContainingSymbol) { { // Can't find non-existent symbol. FileDescriptorProto file; - EXPECT_FALSE( - forward_merged_.FindFileContainingSymbol("NoSuchType", &file)); + EXPECT_FALSE(forward_merged_.FindFileContainingSymbol("NoSuchType", &file)); } } @@ -655,8 +712,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindFileContainingExtension) { { // Can find file that is only in database1_. FileDescriptorProto file; - EXPECT_TRUE( - forward_merged_.FindFileContainingExtension("Foo", 3, &file)); + EXPECT_TRUE(forward_merged_.FindFileContainingExtension("Foo", 3, &file)); EXPECT_EQ("foo.proto", file.name()); ExpectContainsType(file, "Foo"); } @@ -664,8 +720,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindFileContainingExtension) { { // Can find file that is only in database2_. FileDescriptorProto file; - EXPECT_TRUE( - forward_merged_.FindFileContainingExtension("Bar", 5, &file)); + EXPECT_TRUE(forward_merged_.FindFileContainingExtension("Bar", 5, &file)); EXPECT_EQ("bar.proto", file.name()); ExpectContainsType(file, "Bar"); } @@ -673,8 +728,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindFileContainingExtension) { { // In forward_merged_, database1_'s baz.proto takes precedence. FileDescriptorProto file; - EXPECT_TRUE( - forward_merged_.FindFileContainingExtension("Baz", 12, &file)); + EXPECT_TRUE(forward_merged_.FindFileContainingExtension("Baz", 12, &file)); EXPECT_EQ("baz.proto", file.name()); ExpectContainsType(file, "FromPool1"); } @@ -682,8 +736,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindFileContainingExtension) { { // In reverse_merged_, database2_'s baz.proto takes precedence. FileDescriptorProto file; - EXPECT_TRUE( - reverse_merged_.FindFileContainingExtension("Baz", 12, &file)); + EXPECT_TRUE(reverse_merged_.FindFileContainingExtension("Baz", 12, &file)); EXPECT_EQ("baz.proto", file.name()); ExpectContainsType(file, "FromPool2"); } @@ -699,8 +752,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindFileContainingExtension) { { // Can't find non-existent extension. FileDescriptorProto file; - EXPECT_FALSE( - forward_merged_.FindFileContainingExtension("Foo", 6, &file)); + EXPECT_FALSE(forward_merged_.FindFileContainingExtension("Foo", 6, &file)); } } @@ -747,6 +799,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindAllExtensionNumbers) { } } + } // anonymous namespace } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index 7523893117741..b454ed5ad1c17 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -34,16 +34,18 @@ // // This file makes extensive use of RFC 3092. :) +#include #include -#ifndef _SHARED_PTR_H -#include -#endif #include +#include #include #include #include #include +#include +#include +#include #include #include #include @@ -53,14 +55,14 @@ #include #include #include -#include - -#include -#include -#include -#include +#include #include #include +#include +#include + + +#include namespace google { namespace protobuf { @@ -69,41 +71,43 @@ namespace protobuf { namespace descriptor_unittest { // Some helpers to make assembling descriptors faster. -DescriptorProto* AddMessage(FileDescriptorProto* file, const string& name) { +DescriptorProto* AddMessage(FileDescriptorProto* file, + const std::string& name) { DescriptorProto* result = file->add_message_type(); result->set_name(name); return result; } -DescriptorProto* AddNestedMessage(DescriptorProto* parent, const string& name) { +DescriptorProto* AddNestedMessage(DescriptorProto* parent, + const std::string& name) { DescriptorProto* result = parent->add_nested_type(); result->set_name(name); return result; } -EnumDescriptorProto* AddEnum(FileDescriptorProto* file, const string& name) { +EnumDescriptorProto* AddEnum(FileDescriptorProto* file, + const std::string& name) { EnumDescriptorProto* result = file->add_enum_type(); result->set_name(name); return result; } EnumDescriptorProto* AddNestedEnum(DescriptorProto* parent, - const string& name) { + const std::string& name) { EnumDescriptorProto* result = parent->add_enum_type(); result->set_name(name); return result; } ServiceDescriptorProto* AddService(FileDescriptorProto* file, - const string& name) { + const std::string& name) { ServiceDescriptorProto* result = file->add_service(); result->set_name(name); return result; } -FieldDescriptorProto* AddField(DescriptorProto* parent, - const string& name, int number, - FieldDescriptorProto::Label label, +FieldDescriptorProto* AddField(DescriptorProto* parent, const std::string& name, + int number, FieldDescriptorProto::Label label, FieldDescriptorProto::Type type) { FieldDescriptorProto* result = parent->add_field(); result->set_name(name); @@ -114,8 +118,8 @@ FieldDescriptorProto* AddField(DescriptorProto* parent, } FieldDescriptorProto* AddExtension(FileDescriptorProto* file, - const string& extendee, - const string& name, int number, + const std::string& extendee, + const std::string& name, int number, FieldDescriptorProto::Label label, FieldDescriptorProto::Type type) { FieldDescriptorProto* result = file->add_extension(); @@ -128,8 +132,8 @@ FieldDescriptorProto* AddExtension(FileDescriptorProto* file, } FieldDescriptorProto* AddNestedExtension(DescriptorProto* parent, - const string& extendee, - const string& name, int number, + const std::string& extendee, + const std::string& name, int number, FieldDescriptorProto::Label label, FieldDescriptorProto::Type type) { FieldDescriptorProto* result = parent->add_extension(); @@ -157,8 +161,16 @@ DescriptorProto::ReservedRange* AddReservedRange(DescriptorProto* parent, return result; } +EnumDescriptorProto::EnumReservedRange* AddReservedRange( + EnumDescriptorProto* parent, int start, int end) { + EnumDescriptorProto::EnumReservedRange* result = parent->add_reserved_range(); + result->set_start(start); + result->set_end(end); + return result; +} + EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto, - const string& name, int number) { + const std::string& name, int number) { EnumValueDescriptorProto* result = enum_proto->add_value(); result->set_name(name); result->set_number(number); @@ -166,9 +178,9 @@ EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto, } MethodDescriptorProto* AddMethod(ServiceDescriptorProto* service, - const string& name, - const string& input_type, - const string& output_type) { + const std::string& name, + const std::string& input_type, + const std::string& output_type) { MethodDescriptorProto* result = service->add_method(); result->set_name(name); result->set_input_type(input_type); @@ -178,7 +190,7 @@ MethodDescriptorProto* AddMethod(ServiceDescriptorProto* service, // Empty enums technically aren't allowed. We need to insert a dummy value // into them. -void AddEmptyEnum(FileDescriptorProto* file, const string& name) { +void AddEmptyEnum(FileDescriptorProto* file, const std::string& name) { AddEnumValue(AddEnum(file, name), name + "_DUMMY", 1); } @@ -187,53 +199,97 @@ class MockErrorCollector : public DescriptorPool::ErrorCollector { MockErrorCollector() {} ~MockErrorCollector() {} - string text_; - string warning_text_; + std::string text_; + std::string warning_text_; // implements ErrorCollector --------------------------------------- - void AddError(const string& filename, - const string& element_name, const Message* descriptor, - ErrorLocation location, const string& message) { - const char* location_name = NULL; + void AddError(const std::string& filename, const std::string& element_name, + const Message* descriptor, ErrorLocation location, + const std::string& message) { + const char* location_name = nullptr; switch (location) { - case NAME : location_name = "NAME" ; break; - case NUMBER : location_name = "NUMBER" ; break; - case TYPE : location_name = "TYPE" ; break; - case EXTENDEE : location_name = "EXTENDEE" ; break; - case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break; - case OPTION_NAME : location_name = "OPTION_NAME" ; break; - case OPTION_VALUE : location_name = "OPTION_VALUE" ; break; - case INPUT_TYPE : location_name = "INPUT_TYPE" ; break; - case OUTPUT_TYPE : location_name = "OUTPUT_TYPE" ; break; - case OTHER : location_name = "OTHER" ; break; + case NAME: + location_name = "NAME"; + break; + case NUMBER: + location_name = "NUMBER"; + break; + case TYPE: + location_name = "TYPE"; + break; + case EXTENDEE: + location_name = "EXTENDEE"; + break; + case DEFAULT_VALUE: + location_name = "DEFAULT_VALUE"; + break; + case OPTION_NAME: + location_name = "OPTION_NAME"; + break; + case OPTION_VALUE: + location_name = "OPTION_VALUE"; + break; + case INPUT_TYPE: + location_name = "INPUT_TYPE"; + break; + case OUTPUT_TYPE: + location_name = "OUTPUT_TYPE"; + break; + case IMPORT: + location_name = "IMPORT"; + break; + case OTHER: + location_name = "OTHER"; + break; } - strings::SubstituteAndAppend( - &text_, "$0: $1: $2: $3\n", - filename, element_name, location_name, message); + strings::SubstituteAndAppend(&text_, "$0: $1: $2: $3\n", filename, + element_name, location_name, message); } // implements ErrorCollector --------------------------------------- - void AddWarning(const string& filename, const string& element_name, + void AddWarning(const std::string& filename, const std::string& element_name, const Message* descriptor, ErrorLocation location, - const string& message) { - const char* location_name = NULL; + const std::string& message) { + const char* location_name = nullptr; switch (location) { - case NAME : location_name = "NAME" ; break; - case NUMBER : location_name = "NUMBER" ; break; - case TYPE : location_name = "TYPE" ; break; - case EXTENDEE : location_name = "EXTENDEE" ; break; - case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break; - case OPTION_NAME : location_name = "OPTION_NAME" ; break; - case OPTION_VALUE : location_name = "OPTION_VALUE" ; break; - case INPUT_TYPE : location_name = "INPUT_TYPE" ; break; - case OUTPUT_TYPE : location_name = "OUTPUT_TYPE" ; break; - case OTHER : location_name = "OTHER" ; break; + case NAME: + location_name = "NAME"; + break; + case NUMBER: + location_name = "NUMBER"; + break; + case TYPE: + location_name = "TYPE"; + break; + case EXTENDEE: + location_name = "EXTENDEE"; + break; + case DEFAULT_VALUE: + location_name = "DEFAULT_VALUE"; + break; + case OPTION_NAME: + location_name = "OPTION_NAME"; + break; + case OPTION_VALUE: + location_name = "OPTION_VALUE"; + break; + case INPUT_TYPE: + location_name = "INPUT_TYPE"; + break; + case OUTPUT_TYPE: + location_name = "OUTPUT_TYPE"; + break; + case IMPORT: + location_name = "IMPORT"; + break; + case OTHER: + location_name = "OTHER"; + break; } - strings::SubstituteAndAppend( - &warning_text_, "$0: $1: $2: $3\n", - filename, element_name, location_name, message); + strings::SubstituteAndAppend(&warning_text_, "$0: $1: $2: $3\n", filename, + element_name, location_name, message); } }; @@ -287,13 +343,13 @@ class FileDescriptorTest : public testing::Test { // Build the descriptors and get the pointers. foo_file_ = pool_.BuildFile(foo_file); - ASSERT_TRUE(foo_file_ != NULL); + ASSERT_TRUE(foo_file_ != nullptr); bar_file_ = pool_.BuildFile(bar_file); - ASSERT_TRUE(bar_file_ != NULL); + ASSERT_TRUE(bar_file_ != nullptr); baz_file_ = pool_.BuildFile(baz_file); - ASSERT_TRUE(baz_file_ != NULL); + ASSERT_TRUE(baz_file_ != nullptr); ASSERT_EQ(1, foo_file_->message_type_count()); foo_message_ = foo_file_->message_type(0); @@ -324,17 +380,17 @@ class FileDescriptorTest : public testing::Test { const FileDescriptor* bar_file_; const FileDescriptor* baz_file_; - const Descriptor* foo_message_; - const EnumDescriptor* foo_enum_; + const Descriptor* foo_message_; + const EnumDescriptor* foo_enum_; const EnumValueDescriptor* foo_enum_value_; - const ServiceDescriptor* foo_service_; - const FieldDescriptor* foo_extension_; + const ServiceDescriptor* foo_service_; + const FieldDescriptor* foo_extension_; - const Descriptor* bar_message_; - const EnumDescriptor* bar_enum_; + const Descriptor* bar_message_; + const EnumDescriptor* bar_enum_; const EnumValueDescriptor* bar_enum_value_; - const ServiceDescriptor* bar_service_; - const FieldDescriptor* bar_extension_; + const ServiceDescriptor* bar_service_; + const FieldDescriptor* bar_extension_; }; TEST_F(FileDescriptorTest, Name) { @@ -358,71 +414,72 @@ TEST_F(FileDescriptorTest, FindMessageTypeByName) { EXPECT_EQ(foo_message_, foo_file_->FindMessageTypeByName("FooMessage")); EXPECT_EQ(bar_message_, bar_file_->FindMessageTypeByName("BarMessage")); - EXPECT_TRUE(foo_file_->FindMessageTypeByName("BarMessage") == NULL); - EXPECT_TRUE(bar_file_->FindMessageTypeByName("FooMessage") == NULL); - EXPECT_TRUE(baz_file_->FindMessageTypeByName("FooMessage") == NULL); + EXPECT_TRUE(foo_file_->FindMessageTypeByName("BarMessage") == nullptr); + EXPECT_TRUE(bar_file_->FindMessageTypeByName("FooMessage") == nullptr); + EXPECT_TRUE(baz_file_->FindMessageTypeByName("FooMessage") == nullptr); - EXPECT_TRUE(foo_file_->FindMessageTypeByName("NoSuchMessage") == NULL); - EXPECT_TRUE(foo_file_->FindMessageTypeByName("FooEnum") == NULL); + EXPECT_TRUE(foo_file_->FindMessageTypeByName("NoSuchMessage") == nullptr); + EXPECT_TRUE(foo_file_->FindMessageTypeByName("FooEnum") == nullptr); } TEST_F(FileDescriptorTest, FindEnumTypeByName) { EXPECT_EQ(foo_enum_, foo_file_->FindEnumTypeByName("FooEnum")); EXPECT_EQ(bar_enum_, bar_file_->FindEnumTypeByName("BarEnum")); - EXPECT_TRUE(foo_file_->FindEnumTypeByName("BarEnum") == NULL); - EXPECT_TRUE(bar_file_->FindEnumTypeByName("FooEnum") == NULL); - EXPECT_TRUE(baz_file_->FindEnumTypeByName("FooEnum") == NULL); + EXPECT_TRUE(foo_file_->FindEnumTypeByName("BarEnum") == nullptr); + EXPECT_TRUE(bar_file_->FindEnumTypeByName("FooEnum") == nullptr); + EXPECT_TRUE(baz_file_->FindEnumTypeByName("FooEnum") == nullptr); - EXPECT_TRUE(foo_file_->FindEnumTypeByName("NoSuchEnum") == NULL); - EXPECT_TRUE(foo_file_->FindEnumTypeByName("FooMessage") == NULL); + EXPECT_TRUE(foo_file_->FindEnumTypeByName("NoSuchEnum") == nullptr); + EXPECT_TRUE(foo_file_->FindEnumTypeByName("FooMessage") == nullptr); } TEST_F(FileDescriptorTest, FindEnumValueByName) { EXPECT_EQ(foo_enum_value_, foo_file_->FindEnumValueByName("FOO_ENUM_VALUE")); EXPECT_EQ(bar_enum_value_, bar_file_->FindEnumValueByName("BAR_ENUM_VALUE")); - EXPECT_TRUE(foo_file_->FindEnumValueByName("BAR_ENUM_VALUE") == NULL); - EXPECT_TRUE(bar_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL); - EXPECT_TRUE(baz_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL); + EXPECT_TRUE(foo_file_->FindEnumValueByName("BAR_ENUM_VALUE") == nullptr); + EXPECT_TRUE(bar_file_->FindEnumValueByName("FOO_ENUM_VALUE") == nullptr); + EXPECT_TRUE(baz_file_->FindEnumValueByName("FOO_ENUM_VALUE") == nullptr); - EXPECT_TRUE(foo_file_->FindEnumValueByName("NO_SUCH_VALUE") == NULL); - EXPECT_TRUE(foo_file_->FindEnumValueByName("FooMessage") == NULL); + EXPECT_TRUE(foo_file_->FindEnumValueByName("NO_SUCH_VALUE") == nullptr); + EXPECT_TRUE(foo_file_->FindEnumValueByName("FooMessage") == nullptr); } TEST_F(FileDescriptorTest, FindServiceByName) { EXPECT_EQ(foo_service_, foo_file_->FindServiceByName("FooService")); EXPECT_EQ(bar_service_, bar_file_->FindServiceByName("BarService")); - EXPECT_TRUE(foo_file_->FindServiceByName("BarService") == NULL); - EXPECT_TRUE(bar_file_->FindServiceByName("FooService") == NULL); - EXPECT_TRUE(baz_file_->FindServiceByName("FooService") == NULL); + EXPECT_TRUE(foo_file_->FindServiceByName("BarService") == nullptr); + EXPECT_TRUE(bar_file_->FindServiceByName("FooService") == nullptr); + EXPECT_TRUE(baz_file_->FindServiceByName("FooService") == nullptr); - EXPECT_TRUE(foo_file_->FindServiceByName("NoSuchService") == NULL); - EXPECT_TRUE(foo_file_->FindServiceByName("FooMessage") == NULL); + EXPECT_TRUE(foo_file_->FindServiceByName("NoSuchService") == nullptr); + EXPECT_TRUE(foo_file_->FindServiceByName("FooMessage") == nullptr); } TEST_F(FileDescriptorTest, FindExtensionByName) { EXPECT_EQ(foo_extension_, foo_file_->FindExtensionByName("foo_extension")); EXPECT_EQ(bar_extension_, bar_file_->FindExtensionByName("bar_extension")); - EXPECT_TRUE(foo_file_->FindExtensionByName("bar_extension") == NULL); - EXPECT_TRUE(bar_file_->FindExtensionByName("foo_extension") == NULL); - EXPECT_TRUE(baz_file_->FindExtensionByName("foo_extension") == NULL); + EXPECT_TRUE(foo_file_->FindExtensionByName("bar_extension") == nullptr); + EXPECT_TRUE(bar_file_->FindExtensionByName("foo_extension") == nullptr); + EXPECT_TRUE(baz_file_->FindExtensionByName("foo_extension") == nullptr); - EXPECT_TRUE(foo_file_->FindExtensionByName("no_such_extension") == NULL); - EXPECT_TRUE(foo_file_->FindExtensionByName("FooMessage") == NULL); + EXPECT_TRUE(foo_file_->FindExtensionByName("no_such_extension") == nullptr); + EXPECT_TRUE(foo_file_->FindExtensionByName("FooMessage") == nullptr); } TEST_F(FileDescriptorTest, FindExtensionByNumber) { EXPECT_EQ(foo_extension_, pool_.FindExtensionByNumber(foo_message_, 1)); EXPECT_EQ(bar_extension_, pool_.FindExtensionByNumber(bar_message_, 1)); - EXPECT_TRUE(pool_.FindExtensionByNumber(foo_message_, 2) == NULL); + EXPECT_TRUE(pool_.FindExtensionByNumber(foo_message_, 2) == nullptr); } + TEST_F(FileDescriptorTest, BuildAgain) { - // Test that if te call BuildFile again on the same input we get the same + // Test that if we call BuildFile again on the same input we get the same // FileDescriptor back. FileDescriptorProto file; foo_file_->CopyTo(&file); @@ -430,18 +487,18 @@ TEST_F(FileDescriptorTest, BuildAgain) { // But if we change the file then it won't work. file.set_package("some.other.package"); - EXPECT_TRUE(pool_.BuildFile(file) == NULL); + EXPECT_TRUE(pool_.BuildFile(file) == nullptr); } TEST_F(FileDescriptorTest, BuildAgainWithSyntax) { - // Test that if te call BuildFile again on the same input we get the same + // Test that if we call BuildFile again on the same input we get the same // FileDescriptor back even if syntax param is specified. FileDescriptorProto proto_syntax2; proto_syntax2.set_name("foo_syntax2"); proto_syntax2.set_syntax("proto2"); const FileDescriptor* proto2_descriptor = pool_.BuildFile(proto_syntax2); - EXPECT_TRUE(proto2_descriptor != NULL); + EXPECT_TRUE(proto2_descriptor != nullptr); EXPECT_EQ(proto2_descriptor, pool_.BuildFile(proto_syntax2)); FileDescriptorProto implicit_proto2; @@ -449,7 +506,7 @@ TEST_F(FileDescriptorTest, BuildAgainWithSyntax) { const FileDescriptor* implicit_proto2_descriptor = pool_.BuildFile(implicit_proto2); - EXPECT_TRUE(implicit_proto2_descriptor != NULL); + EXPECT_TRUE(implicit_proto2_descriptor != nullptr); // We get the same FileDescriptor back if syntax param is explicitly // specified. implicit_proto2.set_syntax("proto2"); @@ -460,7 +517,7 @@ TEST_F(FileDescriptorTest, BuildAgainWithSyntax) { proto_syntax3.set_syntax("proto3"); const FileDescriptor* proto3_descriptor = pool_.BuildFile(proto_syntax3); - EXPECT_TRUE(proto3_descriptor != NULL); + EXPECT_TRUE(proto3_descriptor != nullptr); EXPECT_EQ(proto3_descriptor, pool_.BuildFile(proto_syntax3)); } @@ -473,7 +530,7 @@ TEST_F(FileDescriptorTest, Syntax) { proto.set_syntax("proto2"); DescriptorPool pool; const FileDescriptor* file = pool.BuildFile(proto); - EXPECT_TRUE(file != NULL); + EXPECT_TRUE(file != nullptr); EXPECT_EQ(FileDescriptor::SYNTAX_PROTO2, file->syntax()); FileDescriptorProto other; file->CopyTo(&other); @@ -484,7 +541,7 @@ TEST_F(FileDescriptorTest, Syntax) { proto.set_syntax("proto3"); DescriptorPool pool; const FileDescriptor* file = pool.BuildFile(proto); - EXPECT_TRUE(file != NULL); + EXPECT_TRUE(file != nullptr); EXPECT_EQ(FileDescriptor::SYNTAX_PROTO3, file->syntax()); FileDescriptorProto other; file->CopyTo(&other); @@ -493,8 +550,8 @@ TEST_F(FileDescriptorTest, Syntax) { } void ExtractDebugString( - const FileDescriptor* file, std::set* visited, - std::vector >* debug_strings) { + const FileDescriptor* file, std::set* visited, + std::vector>* debug_strings) { if (!visited->insert(file->name()).second) { return; } @@ -504,23 +561,23 @@ void ExtractDebugString( debug_strings->push_back(std::make_pair(file->name(), file->DebugString())); } -class SimpleErrorCollector : public google::protobuf::io::ErrorCollector { +class SimpleErrorCollector : public io::ErrorCollector { public: // implements ErrorCollector --------------------------------------- - void AddError(int line, int column, const string& message) { + void AddError(int line, int column, const std::string& message) { last_error_ = StringPrintf("%d:%d:", line, column) + message; } - const string& last_error() { return last_error_; } + const std::string& last_error() { return last_error_; } private: - string last_error_; + std::string last_error_; }; // Test that the result of FileDescriptor::DebugString() can be used to create // the original descriptors. TEST_F(FileDescriptorTest, DebugStringRoundTrip) { - std::set visited; - std::vector > debug_strings; + std::set visited; + std::vector> debug_strings; ExtractDebugString(protobuf_unittest::TestAllTypes::descriptor()->file(), &visited, &debug_strings); ExtractDebugString( @@ -532,12 +589,12 @@ TEST_F(FileDescriptorTest, DebugStringRoundTrip) { DescriptorPool pool; for (int i = 0; i < debug_strings.size(); ++i) { - const string& name = debug_strings[i].first; - const string& content = debug_strings[i].second; - google::protobuf::io::ArrayInputStream input_stream(content.data(), content.size()); + const std::string& name = debug_strings[i].first; + const std::string& content = debug_strings[i].second; + io::ArrayInputStream input_stream(content.data(), content.size()); SimpleErrorCollector error_collector; - google::protobuf::io::Tokenizer tokenizer(&input_stream, &error_collector); - google::protobuf::compiler::Parser parser; + io::Tokenizer tokenizer(&input_stream, &error_collector); + compiler::Parser parser; parser.RecordErrorsTo(&error_collector); FileDescriptorProto proto; ASSERT_TRUE(parser.Parse(&tokenizer, &proto)) @@ -546,7 +603,7 @@ TEST_F(FileDescriptorTest, DebugStringRoundTrip) { ASSERT_EQ("", error_collector.last_error()); proto.set_name(name); const FileDescriptor* descriptor = pool.BuildFile(proto); - ASSERT_TRUE(descriptor != NULL) << proto.DebugString(); + ASSERT_TRUE(descriptor != nullptr) << proto.DebugString(); EXPECT_EQ(content, descriptor->DebugString()); } } @@ -609,35 +666,28 @@ class DescriptorTest : public testing::Test { AddEmptyEnum(&foo_file, "TestEnum"); DescriptorProto* message = AddMessage(&foo_file, "TestMessage"); - AddField(message, "foo", 1, - FieldDescriptorProto::LABEL_REQUIRED, + AddField(message, "foo", 1, FieldDescriptorProto::LABEL_REQUIRED, FieldDescriptorProto::TYPE_STRING); - AddField(message, "bar", 6, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(message, "bar", 6, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_ENUM) - ->set_type_name("TestEnum"); - AddField(message, "baz", 500000000, - FieldDescriptorProto::LABEL_REPEATED, + ->set_type_name("TestEnum"); + AddField(message, "baz", 500000000, FieldDescriptorProto::LABEL_REPEATED, FieldDescriptorProto::TYPE_MESSAGE) - ->set_type_name("TestForeign"); - AddField(message, "qux", 15, - FieldDescriptorProto::LABEL_OPTIONAL, + ->set_type_name("TestForeign"); + AddField(message, "qux", 15, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_GROUP) - ->set_type_name("TestForeign"); + ->set_type_name("TestForeign"); FileDescriptorProto bar_file; bar_file.set_name("bar.proto"); bar_file.set_package("corge.grault"); DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2"); - AddField(message2, "foo", 1, - FieldDescriptorProto::LABEL_REQUIRED, + AddField(message2, "foo", 1, FieldDescriptorProto::LABEL_REQUIRED, FieldDescriptorProto::TYPE_STRING); - AddField(message2, "bar", 2, - FieldDescriptorProto::LABEL_REQUIRED, + AddField(message2, "bar", 2, FieldDescriptorProto::LABEL_REQUIRED, FieldDescriptorProto::TYPE_STRING); - AddField(message2, "quux", 6, - FieldDescriptorProto::LABEL_REQUIRED, + AddField(message2, "quux", 6, FieldDescriptorProto::LABEL_REQUIRED, FieldDescriptorProto::TYPE_STRING); FileDescriptorProto map_file; @@ -645,11 +695,9 @@ class DescriptorTest : public testing::Test { DescriptorProto* message3 = AddMessage(&map_file, "TestMessage3"); DescriptorProto* entry = AddNestedMessage(message3, "MapInt32Int32Entry"); - AddField(entry, "key", 1, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(entry, "key", 1, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32); - AddField(entry, "value", 2, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(entry, "value", 2, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32); entry->mutable_options()->set_map_entry(true); @@ -662,38 +710,32 @@ class DescriptorTest : public testing::Test { json_file.set_name("json.proto"); json_file.set_syntax("proto3"); DescriptorProto* message4 = AddMessage(&json_file, "TestMessage4"); - AddField(message4, "field_name1", 1, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(message4, "field_name1", 1, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32); - AddField(message4, "fieldName2", 2, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(message4, "fieldName2", 2, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32); - AddField(message4, "FieldName3", 3, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(message4, "FieldName3", 3, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32); - AddField(message4, "_field_name4", 4, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(message4, "_field_name4", 4, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32); - AddField(message4, "FIELD_NAME5", 5, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(message4, "FIELD_NAME5", 5, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32); - AddField(message4, "field_name6", 6, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(message4, "field_name6", 6, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32) ->set_json_name("@type"); // Build the descriptors and get the pointers. foo_file_ = pool_.BuildFile(foo_file); - ASSERT_TRUE(foo_file_ != NULL); + ASSERT_TRUE(foo_file_ != nullptr); bar_file_ = pool_.BuildFile(bar_file); - ASSERT_TRUE(bar_file_ != NULL); + ASSERT_TRUE(bar_file_ != nullptr); map_file_ = pool_.BuildFile(map_file); - ASSERT_TRUE(map_file_ != NULL); + ASSERT_TRUE(map_file_ != nullptr); json_file_ = pool_.BuildFile(json_file); - ASSERT_TRUE(json_file_ != NULL); + ASSERT_TRUE(json_file_ != nullptr); ASSERT_EQ(1, foo_file_->enum_type_count()); enum_ = foo_file_->enum_type(0); @@ -712,15 +754,15 @@ class DescriptorTest : public testing::Test { message2_ = bar_file_->message_type(0); ASSERT_EQ(3, message2_->field_count()); - foo2_ = message2_->field(0); - bar2_ = message2_->field(1); + foo2_ = message2_->field(0); + bar2_ = message2_->field(1); quux2_ = message2_->field(2); ASSERT_EQ(1, map_file_->message_type_count()); message3_ = map_file_->message_type(0); ASSERT_EQ(1, message3_->field_count()); - map_ = message3_->field(0); + map_ = message3_->field(0); ASSERT_EQ(1, json_file_->message_type_count()); message4_ = json_file_->message_type(0); @@ -768,8 +810,8 @@ TEST_F(DescriptorTest, Name) { } TEST_F(DescriptorTest, ContainingType) { - EXPECT_TRUE(message_->containing_type() == NULL); - EXPECT_TRUE(message2_->containing_type() == NULL); + EXPECT_TRUE(message_->containing_type() == nullptr); + EXPECT_TRUE(message2_->containing_type() == nullptr); } TEST_F(DescriptorTest, FieldsByIndex) { @@ -790,14 +832,14 @@ TEST_F(DescriptorTest, FindFieldByName) { EXPECT_EQ(bar_, message_->FindFieldByName("bar")); EXPECT_EQ(baz_, message_->FindFieldByName("baz")); EXPECT_EQ(qux_, message_->FindFieldByName("qux")); - EXPECT_TRUE(message_->FindFieldByName("no_such_field") == NULL); - EXPECT_TRUE(message_->FindFieldByName("quux") == NULL); + EXPECT_TRUE(message_->FindFieldByName("no_such_field") == nullptr); + EXPECT_TRUE(message_->FindFieldByName("quux") == nullptr); - EXPECT_EQ(foo2_ , message2_->FindFieldByName("foo" )); - EXPECT_EQ(bar2_ , message2_->FindFieldByName("bar" )); + EXPECT_EQ(foo2_, message2_->FindFieldByName("foo")); + EXPECT_EQ(bar2_, message2_->FindFieldByName("bar")); EXPECT_EQ(quux2_, message2_->FindFieldByName("quux")); - EXPECT_TRUE(message2_->FindFieldByName("baz") == NULL); - EXPECT_TRUE(message2_->FindFieldByName("qux") == NULL); + EXPECT_TRUE(message2_->FindFieldByName("baz") == nullptr); + EXPECT_TRUE(message2_->FindFieldByName("qux") == nullptr); } TEST_F(DescriptorTest, FindFieldByNumber) { @@ -805,14 +847,14 @@ TEST_F(DescriptorTest, FindFieldByNumber) { EXPECT_EQ(bar_, message_->FindFieldByNumber(6)); EXPECT_EQ(baz_, message_->FindFieldByNumber(500000000)); EXPECT_EQ(qux_, message_->FindFieldByNumber(15)); - EXPECT_TRUE(message_->FindFieldByNumber(837592) == NULL); - EXPECT_TRUE(message_->FindFieldByNumber(2) == NULL); + EXPECT_TRUE(message_->FindFieldByNumber(837592) == nullptr); + EXPECT_TRUE(message_->FindFieldByNumber(2) == nullptr); - EXPECT_EQ(foo2_ , message2_->FindFieldByNumber(1)); - EXPECT_EQ(bar2_ , message2_->FindFieldByNumber(2)); + EXPECT_EQ(foo2_, message2_->FindFieldByNumber(1)); + EXPECT_EQ(bar2_, message2_->FindFieldByNumber(2)); EXPECT_EQ(quux2_, message2_->FindFieldByNumber(6)); - EXPECT_TRUE(message2_->FindFieldByNumber(15) == NULL); - EXPECT_TRUE(message2_->FindFieldByNumber(500000000) == NULL); + EXPECT_TRUE(message2_->FindFieldByNumber(15) == nullptr); + EXPECT_TRUE(message2_->FindFieldByNumber(500000000) == nullptr); } TEST_F(DescriptorTest, FieldName) { @@ -833,6 +875,34 @@ TEST_F(DescriptorTest, FieldFullName) { EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name()); } +TEST_F(DescriptorTest, PrintableNameIsFullNameForNonExtensionFields) { + EXPECT_EQ("TestMessage.foo", foo_->PrintableNameForExtension()); + EXPECT_EQ("TestMessage.bar", bar_->PrintableNameForExtension()); + EXPECT_EQ("TestMessage.baz", baz_->PrintableNameForExtension()); + EXPECT_EQ("TestMessage.qux", qux_->PrintableNameForExtension()); + + EXPECT_EQ("corge.grault.TestMessage2.foo", + foo2_->PrintableNameForExtension()); + EXPECT_EQ("corge.grault.TestMessage2.bar", + bar2_->PrintableNameForExtension()); + EXPECT_EQ("corge.grault.TestMessage2.quux", + quux2_->PrintableNameForExtension()); +} + +TEST_F(DescriptorTest, PrintableNameIsFullNameForNonMessageSetExtension) { + EXPECT_EQ("protobuf_unittest.Aggregate.nested", + protobuf_unittest::Aggregate::descriptor() + ->FindExtensionByName("nested") + ->PrintableNameForExtension()); +} + +TEST_F(DescriptorTest, PrintableNameIsExtendingTypeForMessageSetExtension) { + EXPECT_EQ("protobuf_unittest.AggregateMessageSetElement", + protobuf_unittest::AggregateMessageSetElement::descriptor() + ->FindExtensionByName("message_set_extension") + ->PrintableNameForExtension()); +} + TEST_F(DescriptorTest, FieldJsonName) { EXPECT_EQ("fieldName1", message4_->field(0)->json_name()); EXPECT_EQ("fieldName2", message4_->field(1)->json_name()); @@ -891,17 +961,17 @@ TEST_F(DescriptorTest, FieldIndex) { } TEST_F(DescriptorTest, FieldNumber) { - EXPECT_EQ( 1, foo_->number()); - EXPECT_EQ( 6, bar_->number()); + EXPECT_EQ(1, foo_->number()); + EXPECT_EQ(6, bar_->number()); EXPECT_EQ(500000000, baz_->number()); - EXPECT_EQ( 15, qux_->number()); + EXPECT_EQ(15, qux_->number()); } TEST_F(DescriptorTest, FieldType) { - EXPECT_EQ(FieldDescriptor::TYPE_STRING , foo_->type()); - EXPECT_EQ(FieldDescriptor::TYPE_ENUM , bar_->type()); + EXPECT_EQ(FieldDescriptor::TYPE_STRING, foo_->type()); + EXPECT_EQ(FieldDescriptor::TYPE_ENUM, bar_->type()); EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_->type()); - EXPECT_EQ(FieldDescriptor::TYPE_GROUP , qux_->type()); + EXPECT_EQ(FieldDescriptor::TYPE_GROUP, qux_->type()); } TEST_F(DescriptorTest, FieldLabel) { @@ -910,17 +980,17 @@ TEST_F(DescriptorTest, FieldLabel) { EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, baz_->label()); EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, qux_->label()); - EXPECT_TRUE (foo_->is_required()); + EXPECT_TRUE(foo_->is_required()); EXPECT_FALSE(foo_->is_optional()); EXPECT_FALSE(foo_->is_repeated()); EXPECT_FALSE(bar_->is_required()); - EXPECT_TRUE (bar_->is_optional()); + EXPECT_TRUE(bar_->is_optional()); EXPECT_FALSE(bar_->is_repeated()); EXPECT_FALSE(baz_->is_required()); EXPECT_FALSE(baz_->is_optional()); - EXPECT_TRUE (baz_->is_repeated()); + EXPECT_TRUE(baz_->is_repeated()); } TEST_F(DescriptorTest, IsMap) { @@ -929,6 +999,22 @@ TEST_F(DescriptorTest, IsMap) { EXPECT_TRUE(map_->message_type()->options().map_entry()); } +TEST_F(DescriptorTest, GetMap) { + const Descriptor* map_desc = map_->message_type(); + const FieldDescriptor* map_key = map_desc->map_key(); + ASSERT_TRUE(map_key != nullptr); + EXPECT_EQ(map_key->name(), "key"); + EXPECT_EQ(map_key->number(), 1); + + const FieldDescriptor* map_value = map_desc->map_value(); + ASSERT_TRUE(map_value != nullptr); + EXPECT_EQ(map_value->name(), "value"); + EXPECT_EQ(map_value->number(), 2); + + EXPECT_EQ(message_->map_key(), nullptr); + EXPECT_EQ(message_->map_value(), nullptr); +} + TEST_F(DescriptorTest, FieldHasDefault) { EXPECT_FALSE(foo_->has_default_value()); EXPECT_FALSE(bar_->has_default_value()); @@ -942,27 +1028,28 @@ TEST_F(DescriptorTest, FieldContainingType) { EXPECT_EQ(message_, baz_->containing_type()); EXPECT_EQ(message_, qux_->containing_type()); - EXPECT_EQ(message2_, foo2_ ->containing_type()); - EXPECT_EQ(message2_, bar2_ ->containing_type()); + EXPECT_EQ(message2_, foo2_->containing_type()); + EXPECT_EQ(message2_, bar2_->containing_type()); EXPECT_EQ(message2_, quux2_->containing_type()); } TEST_F(DescriptorTest, FieldMessageType) { - EXPECT_TRUE(foo_->message_type() == NULL); - EXPECT_TRUE(bar_->message_type() == NULL); + EXPECT_TRUE(foo_->message_type() == nullptr); + EXPECT_TRUE(bar_->message_type() == nullptr); EXPECT_EQ(foreign_, baz_->message_type()); EXPECT_EQ(foreign_, qux_->message_type()); } TEST_F(DescriptorTest, FieldEnumType) { - EXPECT_TRUE(foo_->enum_type() == NULL); - EXPECT_TRUE(baz_->enum_type() == NULL); - EXPECT_TRUE(qux_->enum_type() == NULL); + EXPECT_TRUE(foo_->enum_type() == nullptr); + EXPECT_TRUE(baz_->enum_type() == nullptr); + EXPECT_TRUE(qux_->enum_type() == nullptr); EXPECT_EQ(enum_, bar_->enum_type()); } + // =================================================================== // Test simple flat messages and fields. @@ -991,27 +1078,23 @@ class OneofDescriptorTest : public testing::Test { oneof_message->add_oneof_decl()->set_name("foo"); oneof_message->add_oneof_decl()->set_name("bar"); - AddField(oneof_message, "a", 1, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(oneof_message, "a", 1, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32); - AddField(oneof_message, "b", 2, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(oneof_message, "b", 2, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_STRING); oneof_message->mutable_field(1)->set_oneof_index(0); - AddField(oneof_message, "c", 3, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(oneof_message, "c", 3, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_MESSAGE); oneof_message->mutable_field(2)->set_oneof_index(0); oneof_message->mutable_field(2)->set_type_name("TestOneof"); - AddField(oneof_message, "d", 4, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(oneof_message, "d", 4, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_FLOAT); oneof_message->mutable_field(3)->set_oneof_index(1); // Build the descriptors and get the pointers. baz_file_ = pool_.BuildFile(baz_file); - ASSERT_TRUE(baz_file_ != NULL); + ASSERT_TRUE(baz_file_ != nullptr); ASSERT_EQ(1, baz_file_->message_type_count()); oneof_message_ = baz_file_->message_type(0); @@ -1039,8 +1122,6 @@ class OneofDescriptorTest : public testing::Test { const FieldDescriptor* b_; const FieldDescriptor* c_; const FieldDescriptor* d_; - const FieldDescriptor* e_; - const FieldDescriptor* f_; }; TEST_F(OneofDescriptorTest, Normal) { @@ -1050,7 +1131,7 @@ TEST_F(OneofDescriptorTest, Normal) { ASSERT_EQ(2, oneof_->field_count()); EXPECT_EQ(b_, oneof_->field(0)); EXPECT_EQ(c_, oneof_->field(1)); - EXPECT_TRUE(a_->containing_oneof() == NULL); + EXPECT_TRUE(a_->containing_oneof() == nullptr); EXPECT_EQ(oneof_, b_->containing_oneof()); EXPECT_EQ(oneof_, c_->containing_oneof()); } @@ -1058,7 +1139,7 @@ TEST_F(OneofDescriptorTest, Normal) { TEST_F(OneofDescriptorTest, FindByName) { EXPECT_EQ(oneof_, oneof_message_->FindOneofByName("foo")); EXPECT_EQ(oneof2_, oneof_message_->FindOneofByName("bar")); - EXPECT_TRUE(oneof_message_->FindOneofByName("no_such_oneof") == NULL); + EXPECT_TRUE(oneof_message_->FindOneofByName("no_such_oneof") == nullptr); } // =================================================================== @@ -1072,14 +1153,11 @@ class StylizedFieldNamesTest : public testing::Test { AddExtensionRange(AddMessage(&file, "ExtendableMessage"), 1, 1000); DescriptorProto* message = AddMessage(&file, "TestMessage"); - AddField(message, "foo_foo", 1, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(message, "foo_foo", 1, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32); - AddField(message, "FooBar", 2, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(message, "FooBar", 2, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32); - AddField(message, "fooBaz", 3, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(message, "fooBaz", 3, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32); AddField(message, "fooFoo", 4, // Camel-case conflict with foo_foo. FieldDescriptorProto::LABEL_OPTIONAL, @@ -1121,7 +1199,7 @@ class StylizedFieldNamesTest : public testing::Test { FieldDescriptorProto::TYPE_INT32); file_ = pool_.BuildFile(file); - ASSERT_TRUE(file_ != NULL); + ASSERT_TRUE(file_ != nullptr); ASSERT_EQ(2, file_->message_type_count()); message_ = file_->message_type(1); ASSERT_EQ("TestMessage", message_->name()); @@ -1137,22 +1215,22 @@ class StylizedFieldNamesTest : public testing::Test { TEST_F(StylizedFieldNamesTest, LowercaseName) { EXPECT_EQ("foo_foo", message_->field(0)->lowercase_name()); - EXPECT_EQ("foobar" , message_->field(1)->lowercase_name()); - EXPECT_EQ("foobaz" , message_->field(2)->lowercase_name()); - EXPECT_EQ("foofoo" , message_->field(3)->lowercase_name()); - EXPECT_EQ("foobar" , message_->field(4)->lowercase_name()); + EXPECT_EQ("foobar", message_->field(1)->lowercase_name()); + EXPECT_EQ("foobaz", message_->field(2)->lowercase_name()); + EXPECT_EQ("foofoo", message_->field(3)->lowercase_name()); + EXPECT_EQ("foobar", message_->field(4)->lowercase_name()); EXPECT_EQ("bar_foo", message_->extension(0)->lowercase_name()); - EXPECT_EQ("barbar" , message_->extension(1)->lowercase_name()); - EXPECT_EQ("barbaz" , message_->extension(2)->lowercase_name()); - EXPECT_EQ("barfoo" , message_->extension(3)->lowercase_name()); - EXPECT_EQ("barbar" , message_->extension(4)->lowercase_name()); + EXPECT_EQ("barbar", message_->extension(1)->lowercase_name()); + EXPECT_EQ("barbaz", message_->extension(2)->lowercase_name()); + EXPECT_EQ("barfoo", message_->extension(3)->lowercase_name()); + EXPECT_EQ("barbar", message_->extension(4)->lowercase_name()); EXPECT_EQ("baz_foo", file_->extension(0)->lowercase_name()); - EXPECT_EQ("bazbar" , file_->extension(1)->lowercase_name()); - EXPECT_EQ("bazbaz" , file_->extension(2)->lowercase_name()); - EXPECT_EQ("bazfoo" , file_->extension(3)->lowercase_name()); - EXPECT_EQ("bazbar" , file_->extension(4)->lowercase_name()); + EXPECT_EQ("bazbar", file_->extension(1)->lowercase_name()); + EXPECT_EQ("bazbaz", file_->extension(2)->lowercase_name()); + EXPECT_EQ("bazfoo", file_->extension(3)->lowercase_name()); + EXPECT_EQ("bazbar", file_->extension(4)->lowercase_name()); } TEST_F(StylizedFieldNamesTest, CamelcaseName) { @@ -1176,16 +1254,13 @@ TEST_F(StylizedFieldNamesTest, CamelcaseName) { } TEST_F(StylizedFieldNamesTest, FindByLowercaseName) { - EXPECT_EQ(message_->field(0), - message_->FindFieldByLowercaseName("foo_foo")); - EXPECT_EQ(message_->field(1), - message_->FindFieldByLowercaseName("foobar")); - EXPECT_EQ(message_->field(2), - message_->FindFieldByLowercaseName("foobaz")); - EXPECT_TRUE(message_->FindFieldByLowercaseName("FooBar") == NULL); - EXPECT_TRUE(message_->FindFieldByLowercaseName("fooBaz") == NULL); - EXPECT_TRUE(message_->FindFieldByLowercaseName("bar_foo") == NULL); - EXPECT_TRUE(message_->FindFieldByLowercaseName("nosuchfield") == NULL); + EXPECT_EQ(message_->field(0), message_->FindFieldByLowercaseName("foo_foo")); + EXPECT_EQ(message_->field(1), message_->FindFieldByLowercaseName("foobar")); + EXPECT_EQ(message_->field(2), message_->FindFieldByLowercaseName("foobaz")); + EXPECT_TRUE(message_->FindFieldByLowercaseName("FooBar") == nullptr); + EXPECT_TRUE(message_->FindFieldByLowercaseName("fooBaz") == nullptr); + EXPECT_TRUE(message_->FindFieldByLowercaseName("bar_foo") == nullptr); + EXPECT_TRUE(message_->FindFieldByLowercaseName("nosuchfield") == nullptr); EXPECT_EQ(message_->extension(0), message_->FindExtensionByLowercaseName("bar_foo")); @@ -1193,33 +1268,28 @@ TEST_F(StylizedFieldNamesTest, FindByLowercaseName) { message_->FindExtensionByLowercaseName("barbar")); EXPECT_EQ(message_->extension(2), message_->FindExtensionByLowercaseName("barbaz")); - EXPECT_TRUE(message_->FindExtensionByLowercaseName("BarBar") == NULL); - EXPECT_TRUE(message_->FindExtensionByLowercaseName("barBaz") == NULL); - EXPECT_TRUE(message_->FindExtensionByLowercaseName("foo_foo") == NULL); - EXPECT_TRUE(message_->FindExtensionByLowercaseName("nosuchfield") == NULL); + EXPECT_TRUE(message_->FindExtensionByLowercaseName("BarBar") == nullptr); + EXPECT_TRUE(message_->FindExtensionByLowercaseName("barBaz") == nullptr); + EXPECT_TRUE(message_->FindExtensionByLowercaseName("foo_foo") == nullptr); + EXPECT_TRUE(message_->FindExtensionByLowercaseName("nosuchfield") == nullptr); EXPECT_EQ(file_->extension(0), file_->FindExtensionByLowercaseName("baz_foo")); - EXPECT_EQ(file_->extension(1), - file_->FindExtensionByLowercaseName("bazbar")); - EXPECT_EQ(file_->extension(2), - file_->FindExtensionByLowercaseName("bazbaz")); - EXPECT_TRUE(file_->FindExtensionByLowercaseName("BazBar") == NULL); - EXPECT_TRUE(file_->FindExtensionByLowercaseName("bazBaz") == NULL); - EXPECT_TRUE(file_->FindExtensionByLowercaseName("nosuchfield") == NULL); + EXPECT_EQ(file_->extension(1), file_->FindExtensionByLowercaseName("bazbar")); + EXPECT_EQ(file_->extension(2), file_->FindExtensionByLowercaseName("bazbaz")); + EXPECT_TRUE(file_->FindExtensionByLowercaseName("BazBar") == nullptr); + EXPECT_TRUE(file_->FindExtensionByLowercaseName("bazBaz") == nullptr); + EXPECT_TRUE(file_->FindExtensionByLowercaseName("nosuchfield") == nullptr); } TEST_F(StylizedFieldNamesTest, FindByCamelcaseName) { - EXPECT_EQ(message_->field(0), - message_->FindFieldByCamelcaseName("fooFoo")); - EXPECT_EQ(message_->field(1), - message_->FindFieldByCamelcaseName("fooBar")); - EXPECT_EQ(message_->field(2), - message_->FindFieldByCamelcaseName("fooBaz")); - EXPECT_TRUE(message_->FindFieldByCamelcaseName("foo_foo") == NULL); - EXPECT_TRUE(message_->FindFieldByCamelcaseName("FooBar") == NULL); - EXPECT_TRUE(message_->FindFieldByCamelcaseName("barFoo") == NULL); - EXPECT_TRUE(message_->FindFieldByCamelcaseName("nosuchfield") == NULL); + EXPECT_EQ(message_->field(0), message_->FindFieldByCamelcaseName("fooFoo")); + EXPECT_EQ(message_->field(1), message_->FindFieldByCamelcaseName("fooBar")); + EXPECT_EQ(message_->field(2), message_->FindFieldByCamelcaseName("fooBaz")); + EXPECT_TRUE(message_->FindFieldByCamelcaseName("foo_foo") == nullptr); + EXPECT_TRUE(message_->FindFieldByCamelcaseName("FooBar") == nullptr); + EXPECT_TRUE(message_->FindFieldByCamelcaseName("barFoo") == nullptr); + EXPECT_TRUE(message_->FindFieldByCamelcaseName("nosuchfield") == nullptr); EXPECT_EQ(message_->extension(0), message_->FindExtensionByCamelcaseName("barFoo")); @@ -1227,20 +1297,17 @@ TEST_F(StylizedFieldNamesTest, FindByCamelcaseName) { message_->FindExtensionByCamelcaseName("barBar")); EXPECT_EQ(message_->extension(2), message_->FindExtensionByCamelcaseName("barBaz")); - EXPECT_TRUE(message_->FindExtensionByCamelcaseName("bar_foo") == NULL); - EXPECT_TRUE(message_->FindExtensionByCamelcaseName("BarBar") == NULL); - EXPECT_TRUE(message_->FindExtensionByCamelcaseName("fooFoo") == NULL); - EXPECT_TRUE(message_->FindExtensionByCamelcaseName("nosuchfield") == NULL); + EXPECT_TRUE(message_->FindExtensionByCamelcaseName("bar_foo") == nullptr); + EXPECT_TRUE(message_->FindExtensionByCamelcaseName("BarBar") == nullptr); + EXPECT_TRUE(message_->FindExtensionByCamelcaseName("fooFoo") == nullptr); + EXPECT_TRUE(message_->FindExtensionByCamelcaseName("nosuchfield") == nullptr); - EXPECT_EQ(file_->extension(0), - file_->FindExtensionByCamelcaseName("bazFoo")); - EXPECT_EQ(file_->extension(1), - file_->FindExtensionByCamelcaseName("bazBar")); - EXPECT_EQ(file_->extension(2), - file_->FindExtensionByCamelcaseName("bazBaz")); - EXPECT_TRUE(file_->FindExtensionByCamelcaseName("baz_foo") == NULL); - EXPECT_TRUE(file_->FindExtensionByCamelcaseName("BazBar") == NULL); - EXPECT_TRUE(file_->FindExtensionByCamelcaseName("nosuchfield") == NULL); + EXPECT_EQ(file_->extension(0), file_->FindExtensionByCamelcaseName("bazFoo")); + EXPECT_EQ(file_->extension(1), file_->FindExtensionByCamelcaseName("bazBar")); + EXPECT_EQ(file_->extension(2), file_->FindExtensionByCamelcaseName("bazBaz")); + EXPECT_TRUE(file_->FindExtensionByCamelcaseName("baz_foo") == nullptr); + EXPECT_TRUE(file_->FindExtensionByCamelcaseName("BazBar") == nullptr); + EXPECT_TRUE(file_->FindExtensionByCamelcaseName("nosuchfield") == nullptr); } // =================================================================== @@ -1287,10 +1354,10 @@ class EnumDescriptorTest : public testing::Test { // Build the descriptors and get the pointers. foo_file_ = pool_.BuildFile(foo_file); - ASSERT_TRUE(foo_file_ != NULL); + ASSERT_TRUE(foo_file_ != nullptr); bar_file_ = pool_.BuildFile(bar_file); - ASSERT_TRUE(bar_file_ != NULL); + ASSERT_TRUE(bar_file_ != nullptr); ASSERT_EQ(1, foo_file_->enum_type_count()); enum_ = foo_file_->enum_type(0); @@ -1333,8 +1400,8 @@ TEST_F(EnumDescriptorTest, Name) { } TEST_F(EnumDescriptorTest, ContainingType) { - EXPECT_TRUE(enum_->containing_type() == NULL); - EXPECT_TRUE(enum2_->containing_type() == NULL); + EXPECT_TRUE(enum_->containing_type() == nullptr); + EXPECT_TRUE(enum2_->containing_type() == nullptr); } TEST_F(EnumDescriptorTest, ValuesByIndex) { @@ -1344,25 +1411,25 @@ TEST_F(EnumDescriptorTest, ValuesByIndex) { } TEST_F(EnumDescriptorTest, FindValueByName) { - EXPECT_EQ(foo_ , enum_ ->FindValueByName("FOO")); - EXPECT_EQ(bar_ , enum_ ->FindValueByName("BAR")); + EXPECT_EQ(foo_, enum_->FindValueByName("FOO")); + EXPECT_EQ(bar_, enum_->FindValueByName("BAR")); EXPECT_EQ(foo2_, enum2_->FindValueByName("FOO")); EXPECT_EQ(baz2_, enum2_->FindValueByName("BAZ")); - EXPECT_TRUE(enum_ ->FindValueByName("NO_SUCH_VALUE") == NULL); - EXPECT_TRUE(enum_ ->FindValueByName("BAZ" ) == NULL); - EXPECT_TRUE(enum2_->FindValueByName("BAR" ) == NULL); + EXPECT_TRUE(enum_->FindValueByName("NO_SUCH_VALUE") == nullptr); + EXPECT_TRUE(enum_->FindValueByName("BAZ") == nullptr); + EXPECT_TRUE(enum2_->FindValueByName("BAR") == nullptr); } TEST_F(EnumDescriptorTest, FindValueByNumber) { - EXPECT_EQ(foo_ , enum_ ->FindValueByNumber(1)); - EXPECT_EQ(bar_ , enum_ ->FindValueByNumber(2)); + EXPECT_EQ(foo_, enum_->FindValueByNumber(1)); + EXPECT_EQ(bar_, enum_->FindValueByNumber(2)); EXPECT_EQ(foo2_, enum2_->FindValueByNumber(1)); EXPECT_EQ(baz2_, enum2_->FindValueByNumber(3)); - EXPECT_TRUE(enum_ ->FindValueByNumber(416) == NULL); - EXPECT_TRUE(enum_ ->FindValueByNumber(3) == NULL); - EXPECT_TRUE(enum2_->FindValueByNumber(2) == NULL); + EXPECT_TRUE(enum_->FindValueByNumber(416) == nullptr); + EXPECT_TRUE(enum_->FindValueByNumber(3) == nullptr); + EXPECT_TRUE(enum2_->FindValueByNumber(2) == nullptr); } TEST_F(EnumDescriptorTest, ValueName) { @@ -1388,8 +1455,8 @@ TEST_F(EnumDescriptorTest, ValueNumber) { } TEST_F(EnumDescriptorTest, ValueType) { - EXPECT_EQ(enum_ , foo_ ->type()); - EXPECT_EQ(enum_ , bar_ ->type()); + EXPECT_EQ(enum_, foo_->type()); + EXPECT_EQ(enum_, bar_->type()); EXPECT_EQ(enum2_, foo2_->type()); EXPECT_EQ(enum2_, baz2_->type()); } @@ -1446,17 +1513,17 @@ class ServiceDescriptorTest : public testing::Test { // Build the descriptors and get the pointers. foo_file_ = pool_.BuildFile(foo_file); - ASSERT_TRUE(foo_file_ != NULL); + ASSERT_TRUE(foo_file_ != nullptr); bar_file_ = pool_.BuildFile(bar_file); - ASSERT_TRUE(bar_file_ != NULL); + ASSERT_TRUE(bar_file_ != nullptr); ASSERT_EQ(6, foo_file_->message_type_count()); - foo_request_ = foo_file_->message_type(0); + foo_request_ = foo_file_->message_type(0); foo_response_ = foo_file_->message_type(1); - bar_request_ = foo_file_->message_type(2); + bar_request_ = foo_file_->message_type(2); bar_response_ = foo_file_->message_type(3); - baz_request_ = foo_file_->message_type(4); + baz_request_ = foo_file_->message_type(4); baz_response_ = foo_file_->message_type(5); ASSERT_EQ(1, foo_file_->service_count()); @@ -1513,14 +1580,14 @@ TEST_F(ServiceDescriptorTest, MethodsByIndex) { } TEST_F(ServiceDescriptorTest, FindMethodByName) { - EXPECT_EQ(foo_ , service_ ->FindMethodByName("Foo")); - EXPECT_EQ(bar_ , service_ ->FindMethodByName("Bar")); + EXPECT_EQ(foo_, service_->FindMethodByName("Foo")); + EXPECT_EQ(bar_, service_->FindMethodByName("Bar")); EXPECT_EQ(foo2_, service2_->FindMethodByName("Foo")); EXPECT_EQ(baz2_, service2_->FindMethodByName("Baz")); - EXPECT_TRUE(service_ ->FindMethodByName("NoSuchMethod") == NULL); - EXPECT_TRUE(service_ ->FindMethodByName("Baz" ) == NULL); - EXPECT_TRUE(service2_->FindMethodByName("Bar" ) == NULL); + EXPECT_TRUE(service_->FindMethodByName("NoSuchMethod") == nullptr); + EXPECT_TRUE(service_->FindMethodByName("Baz") == nullptr); + EXPECT_TRUE(service2_->FindMethodByName("Bar") == nullptr); } TEST_F(ServiceDescriptorTest, MethodName) { @@ -1612,10 +1679,10 @@ class NestedDescriptorTest : public testing::Test { // Build the descriptors and get the pointers. foo_file_ = pool_.BuildFile(foo_file); - ASSERT_TRUE(foo_file_ != NULL); + ASSERT_TRUE(foo_file_ != nullptr); bar_file_ = pool_.BuildFile(bar_file); - ASSERT_TRUE(bar_file_ != NULL); + ASSERT_TRUE(bar_file_ != nullptr); ASSERT_EQ(1, foo_file_->message_type_count()); message_ = foo_file_->message_type(0); @@ -1674,8 +1741,8 @@ class NestedDescriptorTest : public testing::Test { }; TEST_F(NestedDescriptorTest, MessageName) { - EXPECT_EQ("Foo", foo_ ->name()); - EXPECT_EQ("Bar", bar_ ->name()); + EXPECT_EQ("Foo", foo_->name()); + EXPECT_EQ("Bar", bar_->name()); EXPECT_EQ("Foo", foo2_->name()); EXPECT_EQ("Baz", baz2_->name()); @@ -1686,8 +1753,8 @@ TEST_F(NestedDescriptorTest, MessageName) { } TEST_F(NestedDescriptorTest, MessageContainingType) { - EXPECT_EQ(message_ , foo_ ->containing_type()); - EXPECT_EQ(message_ , bar_ ->containing_type()); + EXPECT_EQ(message_, foo_->containing_type()); + EXPECT_EQ(message_, bar_->containing_type()); EXPECT_EQ(message2_, foo2_->containing_type()); EXPECT_EQ(message2_, baz2_->containing_type()); } @@ -1699,41 +1766,41 @@ TEST_F(NestedDescriptorTest, NestedMessagesByIndex) { } TEST_F(NestedDescriptorTest, FindFieldByNameDoesntFindNestedTypes) { - EXPECT_TRUE(message_->FindFieldByName("Foo") == NULL); - EXPECT_TRUE(message_->FindFieldByName("Qux") == NULL); - EXPECT_TRUE(message_->FindExtensionByName("Foo") == NULL); - EXPECT_TRUE(message_->FindExtensionByName("Qux") == NULL); + EXPECT_TRUE(message_->FindFieldByName("Foo") == nullptr); + EXPECT_TRUE(message_->FindFieldByName("Qux") == nullptr); + EXPECT_TRUE(message_->FindExtensionByName("Foo") == nullptr); + EXPECT_TRUE(message_->FindExtensionByName("Qux") == nullptr); } TEST_F(NestedDescriptorTest, FindNestedTypeByName) { - EXPECT_EQ(foo_ , message_ ->FindNestedTypeByName("Foo")); - EXPECT_EQ(bar_ , message_ ->FindNestedTypeByName("Bar")); + EXPECT_EQ(foo_, message_->FindNestedTypeByName("Foo")); + EXPECT_EQ(bar_, message_->FindNestedTypeByName("Bar")); EXPECT_EQ(foo2_, message2_->FindNestedTypeByName("Foo")); EXPECT_EQ(baz2_, message2_->FindNestedTypeByName("Baz")); - EXPECT_TRUE(message_ ->FindNestedTypeByName("NoSuchType") == NULL); - EXPECT_TRUE(message_ ->FindNestedTypeByName("Baz" ) == NULL); - EXPECT_TRUE(message2_->FindNestedTypeByName("Bar" ) == NULL); + EXPECT_TRUE(message_->FindNestedTypeByName("NoSuchType") == nullptr); + EXPECT_TRUE(message_->FindNestedTypeByName("Baz") == nullptr); + EXPECT_TRUE(message2_->FindNestedTypeByName("Bar") == nullptr); - EXPECT_TRUE(message_->FindNestedTypeByName("Qux") == NULL); + EXPECT_TRUE(message_->FindNestedTypeByName("Qux") == nullptr); } TEST_F(NestedDescriptorTest, EnumName) { - EXPECT_EQ("Baz" , baz_ ->name()); - EXPECT_EQ("Qux" , qux_ ->name()); - EXPECT_EQ("Qux" , qux2_->name()); + EXPECT_EQ("Baz", baz_->name()); + EXPECT_EQ("Qux", qux_->name()); + EXPECT_EQ("Qux", qux2_->name()); EXPECT_EQ("Quux", quux2_->name()); EXPECT_EQ("TestMessage.Baz", baz_->full_name()); EXPECT_EQ("TestMessage.Qux", qux_->full_name()); - EXPECT_EQ("corge.grault.TestMessage2.Qux" , qux2_ ->full_name()); + EXPECT_EQ("corge.grault.TestMessage2.Qux", qux2_->full_name()); EXPECT_EQ("corge.grault.TestMessage2.Quux", quux2_->full_name()); } TEST_F(NestedDescriptorTest, EnumContainingType) { - EXPECT_EQ(message_ , baz_ ->containing_type()); - EXPECT_EQ(message_ , qux_ ->containing_type()); - EXPECT_EQ(message2_, qux2_ ->containing_type()); + EXPECT_EQ(message_, baz_->containing_type()); + EXPECT_EQ(message_, qux_->containing_type()); + EXPECT_EQ(message2_, qux2_->containing_type()); EXPECT_EQ(message2_, quux2_->containing_type()); } @@ -1744,29 +1811,29 @@ TEST_F(NestedDescriptorTest, NestedEnumsByIndex) { } TEST_F(NestedDescriptorTest, FindEnumTypeByName) { - EXPECT_EQ(baz_ , message_ ->FindEnumTypeByName("Baz" )); - EXPECT_EQ(qux_ , message_ ->FindEnumTypeByName("Qux" )); - EXPECT_EQ(qux2_ , message2_->FindEnumTypeByName("Qux" )); + EXPECT_EQ(baz_, message_->FindEnumTypeByName("Baz")); + EXPECT_EQ(qux_, message_->FindEnumTypeByName("Qux")); + EXPECT_EQ(qux2_, message2_->FindEnumTypeByName("Qux")); EXPECT_EQ(quux2_, message2_->FindEnumTypeByName("Quux")); - EXPECT_TRUE(message_ ->FindEnumTypeByName("NoSuchType") == NULL); - EXPECT_TRUE(message_ ->FindEnumTypeByName("Quux" ) == NULL); - EXPECT_TRUE(message2_->FindEnumTypeByName("Baz" ) == NULL); + EXPECT_TRUE(message_->FindEnumTypeByName("NoSuchType") == nullptr); + EXPECT_TRUE(message_->FindEnumTypeByName("Quux") == nullptr); + EXPECT_TRUE(message2_->FindEnumTypeByName("Baz") == nullptr); - EXPECT_TRUE(message_->FindEnumTypeByName("Foo") == NULL); + EXPECT_TRUE(message_->FindEnumTypeByName("Foo") == nullptr); } TEST_F(NestedDescriptorTest, FindEnumValueByName) { - EXPECT_EQ(a_ , message_ ->FindEnumValueByName("A")); - EXPECT_EQ(b_ , message_ ->FindEnumValueByName("B")); + EXPECT_EQ(a_, message_->FindEnumValueByName("A")); + EXPECT_EQ(b_, message_->FindEnumValueByName("B")); EXPECT_EQ(a2_, message2_->FindEnumValueByName("A")); EXPECT_EQ(c2_, message2_->FindEnumValueByName("C")); - EXPECT_TRUE(message_ ->FindEnumValueByName("NO_SUCH_VALUE") == NULL); - EXPECT_TRUE(message_ ->FindEnumValueByName("C" ) == NULL); - EXPECT_TRUE(message2_->FindEnumValueByName("B" ) == NULL); + EXPECT_TRUE(message_->FindEnumValueByName("NO_SUCH_VALUE") == nullptr); + EXPECT_TRUE(message_->FindEnumValueByName("C") == nullptr); + EXPECT_TRUE(message2_->FindEnumValueByName("B") == nullptr); - EXPECT_TRUE(message_->FindEnumValueByName("Foo") == NULL); + EXPECT_TRUE(message_->FindEnumValueByName("Foo") == nullptr); } // =================================================================== @@ -1784,12 +1851,17 @@ class ExtensionDescriptorTest : public testing::Test { // extensions 10 to 19; // extensions 30 to 39; // } - // extends Foo with optional int32 foo_int32 = 10; - // extends Foo with repeated TestEnum foo_enum = 19; + // extend Foo { + // optional int32 foo_int32 = 10; + // } + // extend Foo { + // repeated TestEnum foo_enum = 19; + // } // message Bar { - // extends Foo with optional Qux foo_message = 30; - // // (using Qux as the group type) - // extends Foo with repeated group foo_group = 39; + // extend Foo { + // optional Qux foo_message = 30; + // repeated Qux foo_group = 39; // (but internally set to TYPE_GROUP) + // } // } FileDescriptorProto foo_file; @@ -1808,21 +1880,21 @@ class ExtensionDescriptorTest : public testing::Test { AddExtension(&foo_file, "Foo", "foo_enum", 19, FieldDescriptorProto::LABEL_REPEATED, FieldDescriptorProto::TYPE_ENUM) - ->set_type_name("Baz"); + ->set_type_name("Baz"); DescriptorProto* bar = AddMessage(&foo_file, "Bar"); AddNestedExtension(bar, "Foo", "foo_message", 30, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_MESSAGE) - ->set_type_name("Qux"); + ->set_type_name("Qux"); AddNestedExtension(bar, "Foo", "foo_group", 39, FieldDescriptorProto::LABEL_REPEATED, FieldDescriptorProto::TYPE_GROUP) - ->set_type_name("Qux"); + ->set_type_name("Qux"); // Build the descriptors and get the pointers. foo_file_ = pool_.BuildFile(foo_file); - ASSERT_TRUE(foo_file_ != NULL); + ASSERT_TRUE(foo_file_ != nullptr); ASSERT_EQ(1, foo_file_->enum_type_count()); baz_ = foo_file_->enum_type(0); @@ -1852,7 +1924,7 @@ TEST_F(ExtensionDescriptorTest, ExtensionRanges) { EXPECT_EQ(20, foo_->extension_range(0)->end); EXPECT_EQ(40, foo_->extension_range(1)->end); -}; +} TEST_F(ExtensionDescriptorTest, Extensions) { EXPECT_EQ(0, foo_->extension_count()); @@ -1864,20 +1936,20 @@ TEST_F(ExtensionDescriptorTest, Extensions) { EXPECT_TRUE(bar_->extension(0)->is_extension()); EXPECT_TRUE(bar_->extension(1)->is_extension()); - EXPECT_EQ("foo_int32" , foo_file_->extension(0)->name()); - EXPECT_EQ("foo_enum" , foo_file_->extension(1)->name()); + EXPECT_EQ("foo_int32", foo_file_->extension(0)->name()); + EXPECT_EQ("foo_enum", foo_file_->extension(1)->name()); EXPECT_EQ("foo_message", bar_->extension(0)->name()); - EXPECT_EQ("foo_group" , bar_->extension(1)->name()); + EXPECT_EQ("foo_group", bar_->extension(1)->name()); EXPECT_EQ(10, foo_file_->extension(0)->number()); EXPECT_EQ(19, foo_file_->extension(1)->number()); EXPECT_EQ(30, bar_->extension(0)->number()); EXPECT_EQ(39, bar_->extension(1)->number()); - EXPECT_EQ(FieldDescriptor::TYPE_INT32 , foo_file_->extension(0)->type()); - EXPECT_EQ(FieldDescriptor::TYPE_ENUM , foo_file_->extension(1)->type()); + EXPECT_EQ(FieldDescriptor::TYPE_INT32, foo_file_->extension(0)->type()); + EXPECT_EQ(FieldDescriptor::TYPE_ENUM, foo_file_->extension(1)->type()); EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_->extension(0)->type()); - EXPECT_EQ(FieldDescriptor::TYPE_GROUP , bar_->extension(1)->type()); + EXPECT_EQ(FieldDescriptor::TYPE_GROUP, bar_->extension(1)->type()); EXPECT_EQ(baz_, foo_file_->extension(1)->enum_type()); EXPECT_EQ(qux_, bar_->extension(0)->message_type()); @@ -1893,20 +1965,20 @@ TEST_F(ExtensionDescriptorTest, Extensions) { EXPECT_EQ(foo_, bar_->extension(0)->containing_type()); EXPECT_EQ(foo_, bar_->extension(1)->containing_type()); - EXPECT_TRUE(foo_file_->extension(0)->extension_scope() == NULL); - EXPECT_TRUE(foo_file_->extension(1)->extension_scope() == NULL); + EXPECT_TRUE(foo_file_->extension(0)->extension_scope() == nullptr); + EXPECT_TRUE(foo_file_->extension(1)->extension_scope() == nullptr); EXPECT_EQ(bar_, bar_->extension(0)->extension_scope()); EXPECT_EQ(bar_, bar_->extension(1)->extension_scope()); -}; +} TEST_F(ExtensionDescriptorTest, IsExtensionNumber) { - EXPECT_FALSE(foo_->IsExtensionNumber( 9)); - EXPECT_TRUE (foo_->IsExtensionNumber(10)); - EXPECT_TRUE (foo_->IsExtensionNumber(19)); + EXPECT_FALSE(foo_->IsExtensionNumber(9)); + EXPECT_TRUE(foo_->IsExtensionNumber(10)); + EXPECT_TRUE(foo_->IsExtensionNumber(19)); EXPECT_FALSE(foo_->IsExtensionNumber(20)); EXPECT_FALSE(foo_->IsExtensionNumber(29)); - EXPECT_TRUE (foo_->IsExtensionNumber(30)); - EXPECT_TRUE (foo_->IsExtensionNumber(39)); + EXPECT_TRUE(foo_->IsExtensionNumber(30)); + EXPECT_TRUE(foo_->IsExtensionNumber(39)); EXPECT_FALSE(foo_->IsExtensionNumber(40)); } @@ -1916,11 +1988,40 @@ TEST_F(ExtensionDescriptorTest, FindExtensionByName) { ASSERT_EQ(2, bar_->extension_count()); EXPECT_EQ(bar_->extension(0), bar_->FindExtensionByName("foo_message")); - EXPECT_EQ(bar_->extension(1), bar_->FindExtensionByName("foo_group" )); - - EXPECT_TRUE(bar_->FindExtensionByName("no_such_extension") == NULL); - EXPECT_TRUE(foo_->FindExtensionByName("foo_int32") == NULL); - EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == NULL); + EXPECT_EQ(bar_->extension(1), bar_->FindExtensionByName("foo_group")); + + EXPECT_TRUE(bar_->FindExtensionByName("no_such_extension") == nullptr); + EXPECT_TRUE(foo_->FindExtensionByName("foo_int32") == nullptr); + EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == nullptr); +} + +TEST_F(ExtensionDescriptorTest, FindExtensionByPrintableName) { + EXPECT_TRUE(pool_.FindExtensionByPrintableName(foo_, "no_such_extension") == + nullptr); + EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "no_such_extension") == + nullptr); + + ASSERT_FALSE(pool_.FindExtensionByPrintableName(foo_, "Bar.foo_message") == + nullptr); + ASSERT_FALSE(pool_.FindExtensionByPrintableName(foo_, "Bar.foo_group") == + nullptr); + EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "foo_message") == + nullptr); + EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "foo_group") == nullptr); + EXPECT_EQ(bar_->FindExtensionByName("foo_message"), + pool_.FindExtensionByPrintableName(foo_, "Bar.foo_message")); + EXPECT_EQ(bar_->FindExtensionByName("foo_group"), + pool_.FindExtensionByPrintableName(foo_, "Bar.foo_group")); + + ASSERT_FALSE(pool_.FindExtensionByPrintableName(foo_, "foo_int32") == + nullptr); + ASSERT_FALSE(pool_.FindExtensionByPrintableName(foo_, "foo_enum") == nullptr); + EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "foo_int32") == nullptr); + EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "foo_enum") == nullptr); + EXPECT_EQ(foo_file_->FindExtensionByName("foo_int32"), + pool_.FindExtensionByPrintableName(foo_, "foo_int32")); + EXPECT_EQ(foo_file_->FindExtensionByName("foo_enum"), + pool_.FindExtensionByPrintableName(foo_, "foo_enum")); } TEST_F(ExtensionDescriptorTest, FindAllExtensions) { @@ -1933,12 +2034,13 @@ TEST_F(ExtensionDescriptorTest, FindAllExtensions) { EXPECT_EQ(39, extensions[3]->number()); } + TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) { DescriptorPool pool; FileDescriptorProto file_proto; // Add "google/protobuf/descriptor.proto". FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); // Add "foo.proto": // import "google/protobuf/descriptor.proto"; // extend google.protobuf.FieldOptions { @@ -1950,7 +2052,7 @@ TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) { AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); // Add "bar.proto": // import "google/protobuf/descriptor.proto"; // extend google.protobuf.FieldOptions { @@ -1964,7 +2066,7 @@ TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) { FieldDescriptorProto::TYPE_INT32); // Currently we only generate a warning for conflicting extension numbers. // TODO(xiaofeng): Change it to an error. - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); } // =================================================================== @@ -1993,7 +2095,7 @@ class ReservedDescriptorTest : public testing::Test { // Build the descriptors and get the pointers. foo_file_ = pool_.BuildFile(foo_file); - ASSERT_TRUE(foo_file_ != NULL); + ASSERT_TRUE(foo_file_ != nullptr); ASSERT_EQ(1, foo_file_->message_type_count()); foo_ = foo_file_->message_type(0); @@ -2015,36 +2117,167 @@ TEST_F(ReservedDescriptorTest, ReservedRanges) { EXPECT_EQ(15, foo_->reserved_range(2)->start); EXPECT_EQ(16, foo_->reserved_range(2)->end); -}; +} TEST_F(ReservedDescriptorTest, IsReservedNumber) { EXPECT_FALSE(foo_->IsReservedNumber(1)); - EXPECT_TRUE (foo_->IsReservedNumber(2)); + EXPECT_TRUE(foo_->IsReservedNumber(2)); EXPECT_FALSE(foo_->IsReservedNumber(3)); EXPECT_FALSE(foo_->IsReservedNumber(8)); - EXPECT_TRUE (foo_->IsReservedNumber(9)); - EXPECT_TRUE (foo_->IsReservedNumber(10)); - EXPECT_TRUE (foo_->IsReservedNumber(11)); + EXPECT_TRUE(foo_->IsReservedNumber(9)); + EXPECT_TRUE(foo_->IsReservedNumber(10)); + EXPECT_TRUE(foo_->IsReservedNumber(11)); EXPECT_FALSE(foo_->IsReservedNumber(12)); EXPECT_FALSE(foo_->IsReservedNumber(13)); EXPECT_FALSE(foo_->IsReservedNumber(14)); - EXPECT_TRUE (foo_->IsReservedNumber(15)); + EXPECT_TRUE(foo_->IsReservedNumber(15)); EXPECT_FALSE(foo_->IsReservedNumber(16)); -}; +} TEST_F(ReservedDescriptorTest, ReservedNames) { ASSERT_EQ(2, foo_->reserved_name_count()); EXPECT_EQ("foo", foo_->reserved_name(0)); EXPECT_EQ("bar", foo_->reserved_name(1)); -}; +} TEST_F(ReservedDescriptorTest, IsReservedName) { - EXPECT_TRUE (foo_->IsReservedName("foo")); - EXPECT_TRUE (foo_->IsReservedName("bar")); + EXPECT_TRUE(foo_->IsReservedName("foo")); + EXPECT_TRUE(foo_->IsReservedName("bar")); EXPECT_FALSE(foo_->IsReservedName("baz")); +} + +// =================================================================== + +// Test reserved enum fields. +class ReservedEnumDescriptorTest : public testing::Test { + protected: + virtual void SetUp() { + // Build descriptors for the following definitions: + // + // enum Foo { + // BAR = 1; + // reserved 2, 9 to 11, 15; + // reserved "foo", "bar"; + // } + + FileDescriptorProto foo_file; + foo_file.set_name("foo.proto"); + + EnumDescriptorProto* foo = AddEnum(&foo_file, "Foo"); + EnumDescriptorProto* edge1 = AddEnum(&foo_file, "Edge1"); + EnumDescriptorProto* edge2 = AddEnum(&foo_file, "Edge2"); + + AddEnumValue(foo, "BAR", 4); + AddReservedRange(foo, -5, -3); + AddReservedRange(foo, -2, 1); + AddReservedRange(foo, 2, 3); + AddReservedRange(foo, 9, 12); + AddReservedRange(foo, 15, 16); + + foo->add_reserved_name("foo"); + foo->add_reserved_name("bar"); + + // Some additional edge cases that cover most or all of the range of enum + // values + + // Note: We use INT_MAX as the maximum reserved range upper bound, + // inclusive. + AddEnumValue(edge1, "EDGE1", 1); + AddReservedRange(edge1, 10, INT_MAX); + AddEnumValue(edge2, "EDGE2", 15); + AddReservedRange(edge2, INT_MIN, 10); + + // Build the descriptors and get the pointers. + foo_file_ = pool_.BuildFile(foo_file); + ASSERT_TRUE(foo_file_ != nullptr); + + ASSERT_EQ(3, foo_file_->enum_type_count()); + foo_ = foo_file_->enum_type(0); + edge1_ = foo_file_->enum_type(1); + edge2_ = foo_file_->enum_type(2); + } + + DescriptorPool pool_; + const FileDescriptor* foo_file_; + const EnumDescriptor* foo_; + const EnumDescriptor* edge1_; + const EnumDescriptor* edge2_; }; +TEST_F(ReservedEnumDescriptorTest, ReservedRanges) { + ASSERT_EQ(5, foo_->reserved_range_count()); + + EXPECT_EQ(-5, foo_->reserved_range(0)->start); + EXPECT_EQ(-3, foo_->reserved_range(0)->end); + + EXPECT_EQ(-2, foo_->reserved_range(1)->start); + EXPECT_EQ(1, foo_->reserved_range(1)->end); + + EXPECT_EQ(2, foo_->reserved_range(2)->start); + EXPECT_EQ(3, foo_->reserved_range(2)->end); + + EXPECT_EQ(9, foo_->reserved_range(3)->start); + EXPECT_EQ(12, foo_->reserved_range(3)->end); + + EXPECT_EQ(15, foo_->reserved_range(4)->start); + EXPECT_EQ(16, foo_->reserved_range(4)->end); + + ASSERT_EQ(1, edge1_->reserved_range_count()); + EXPECT_EQ(10, edge1_->reserved_range(0)->start); + EXPECT_EQ(INT_MAX, edge1_->reserved_range(0)->end); + + ASSERT_EQ(1, edge2_->reserved_range_count()); + EXPECT_EQ(INT_MIN, edge2_->reserved_range(0)->start); + EXPECT_EQ(10, edge2_->reserved_range(0)->end); +} + +TEST_F(ReservedEnumDescriptorTest, IsReservedNumber) { + EXPECT_TRUE(foo_->IsReservedNumber(-5)); + EXPECT_TRUE(foo_->IsReservedNumber(-4)); + EXPECT_TRUE(foo_->IsReservedNumber(-3)); + EXPECT_TRUE(foo_->IsReservedNumber(-2)); + EXPECT_TRUE(foo_->IsReservedNumber(-1)); + EXPECT_TRUE(foo_->IsReservedNumber(0)); + EXPECT_TRUE(foo_->IsReservedNumber(1)); + EXPECT_TRUE(foo_->IsReservedNumber(2)); + EXPECT_TRUE(foo_->IsReservedNumber(3)); + EXPECT_FALSE(foo_->IsReservedNumber(8)); + EXPECT_TRUE(foo_->IsReservedNumber(9)); + EXPECT_TRUE(foo_->IsReservedNumber(10)); + EXPECT_TRUE(foo_->IsReservedNumber(11)); + EXPECT_TRUE(foo_->IsReservedNumber(12)); + EXPECT_FALSE(foo_->IsReservedNumber(13)); + EXPECT_FALSE(foo_->IsReservedNumber(13)); + EXPECT_FALSE(foo_->IsReservedNumber(14)); + EXPECT_TRUE(foo_->IsReservedNumber(15)); + EXPECT_TRUE(foo_->IsReservedNumber(16)); + EXPECT_FALSE(foo_->IsReservedNumber(17)); + + EXPECT_FALSE(edge1_->IsReservedNumber(9)); + EXPECT_TRUE(edge1_->IsReservedNumber(10)); + EXPECT_TRUE(edge1_->IsReservedNumber(INT_MAX - 1)); + EXPECT_TRUE(edge1_->IsReservedNumber(INT_MAX)); + + EXPECT_TRUE(edge2_->IsReservedNumber(INT_MIN)); + EXPECT_TRUE(edge2_->IsReservedNumber(9)); + EXPECT_TRUE(edge2_->IsReservedNumber(10)); + EXPECT_FALSE(edge2_->IsReservedNumber(11)); +} + +TEST_F(ReservedEnumDescriptorTest, ReservedNames) { + ASSERT_EQ(2, foo_->reserved_name_count()); + + EXPECT_EQ("foo", foo_->reserved_name(0)); + EXPECT_EQ("bar", foo_->reserved_name(1)); +} + +TEST_F(ReservedEnumDescriptorTest, IsReservedName) { + EXPECT_TRUE(foo_->IsReservedName("foo")); + EXPECT_TRUE(foo_->IsReservedName("bar")); + EXPECT_FALSE(foo_->IsReservedName("baz")); +} + // =================================================================== class MiscTest : public testing::Test { @@ -2056,9 +2289,9 @@ class MiscTest : public testing::Test { AddEmptyEnum(&file_proto, "DummyEnum"); DescriptorProto* message = AddMessage(&file_proto, "TestMessage"); - FieldDescriptorProto* field = - AddField(message, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL, - static_cast(static_cast(type))); + FieldDescriptorProto* field = AddField( + message, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL, + static_cast(static_cast(type))); if (type == FieldDescriptor::TYPE_MESSAGE || type == FieldDescriptor::TYPE_GROUP) { @@ -2071,44 +2304,43 @@ class MiscTest : public testing::Test { pool_.reset(new DescriptorPool()); const FileDescriptor* file = pool_->BuildFile(file_proto); - if (file != NULL && - file->message_type_count() == 1 && + if (file != nullptr && file->message_type_count() == 1 && file->message_type(0)->field_count() == 1) { return file->message_type(0)->field(0); } else { - return NULL; + return nullptr; } } const char* GetTypeNameForFieldType(FieldDescriptor::Type type) { const FieldDescriptor* field = GetFieldDescriptorOfType(type); - return field != NULL ? field->type_name() : ""; + return field != nullptr ? field->type_name() : ""; } FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) { const FieldDescriptor* field = GetFieldDescriptorOfType(type); - return field != NULL ? field->cpp_type() : - static_cast(0); + return field != nullptr ? field->cpp_type() + : static_cast(0); } const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) { const FieldDescriptor* field = GetFieldDescriptorOfType(type); - return field != NULL ? field->cpp_type_name() : ""; + return field != nullptr ? field->cpp_type_name() : ""; } const Descriptor* GetMessageDescriptorForFieldType( FieldDescriptor::Type type) { const FieldDescriptor* field = GetFieldDescriptorOfType(type); - return field != NULL ? field->message_type() : NULL; + return field != nullptr ? field->message_type() : nullptr; } const EnumDescriptor* GetEnumDescriptorForFieldType( - FieldDescriptor::Type type) { + FieldDescriptor::Type type) { const FieldDescriptor* field = GetFieldDescriptorOfType(type); - return field != NULL ? field->enum_type() : NULL; + return field != nullptr ? field->enum_type() : nullptr; } - google::protobuf::scoped_ptr pool_; + std::unique_ptr pool_; }; TEST_F(MiscTest, TypeNames) { @@ -2116,24 +2348,24 @@ TEST_F(MiscTest, TypeNames) { typedef FieldDescriptor FD; // avoid ugly line wrapping - EXPECT_STREQ("double" , GetTypeNameForFieldType(FD::TYPE_DOUBLE )); - EXPECT_STREQ("float" , GetTypeNameForFieldType(FD::TYPE_FLOAT )); - EXPECT_STREQ("int64" , GetTypeNameForFieldType(FD::TYPE_INT64 )); - EXPECT_STREQ("uint64" , GetTypeNameForFieldType(FD::TYPE_UINT64 )); - EXPECT_STREQ("int32" , GetTypeNameForFieldType(FD::TYPE_INT32 )); - EXPECT_STREQ("fixed64" , GetTypeNameForFieldType(FD::TYPE_FIXED64 )); - EXPECT_STREQ("fixed32" , GetTypeNameForFieldType(FD::TYPE_FIXED32 )); - EXPECT_STREQ("bool" , GetTypeNameForFieldType(FD::TYPE_BOOL )); - EXPECT_STREQ("string" , GetTypeNameForFieldType(FD::TYPE_STRING )); - EXPECT_STREQ("group" , GetTypeNameForFieldType(FD::TYPE_GROUP )); - EXPECT_STREQ("message" , GetTypeNameForFieldType(FD::TYPE_MESSAGE )); - EXPECT_STREQ("bytes" , GetTypeNameForFieldType(FD::TYPE_BYTES )); - EXPECT_STREQ("uint32" , GetTypeNameForFieldType(FD::TYPE_UINT32 )); - EXPECT_STREQ("enum" , GetTypeNameForFieldType(FD::TYPE_ENUM )); + EXPECT_STREQ("double", GetTypeNameForFieldType(FD::TYPE_DOUBLE)); + EXPECT_STREQ("float", GetTypeNameForFieldType(FD::TYPE_FLOAT)); + EXPECT_STREQ("int64", GetTypeNameForFieldType(FD::TYPE_INT64)); + EXPECT_STREQ("uint64", GetTypeNameForFieldType(FD::TYPE_UINT64)); + EXPECT_STREQ("int32", GetTypeNameForFieldType(FD::TYPE_INT32)); + EXPECT_STREQ("fixed64", GetTypeNameForFieldType(FD::TYPE_FIXED64)); + EXPECT_STREQ("fixed32", GetTypeNameForFieldType(FD::TYPE_FIXED32)); + EXPECT_STREQ("bool", GetTypeNameForFieldType(FD::TYPE_BOOL)); + EXPECT_STREQ("string", GetTypeNameForFieldType(FD::TYPE_STRING)); + EXPECT_STREQ("group", GetTypeNameForFieldType(FD::TYPE_GROUP)); + EXPECT_STREQ("message", GetTypeNameForFieldType(FD::TYPE_MESSAGE)); + EXPECT_STREQ("bytes", GetTypeNameForFieldType(FD::TYPE_BYTES)); + EXPECT_STREQ("uint32", GetTypeNameForFieldType(FD::TYPE_UINT32)); + EXPECT_STREQ("enum", GetTypeNameForFieldType(FD::TYPE_ENUM)); EXPECT_STREQ("sfixed32", GetTypeNameForFieldType(FD::TYPE_SFIXED32)); EXPECT_STREQ("sfixed64", GetTypeNameForFieldType(FD::TYPE_SFIXED64)); - EXPECT_STREQ("sint32" , GetTypeNameForFieldType(FD::TYPE_SINT32 )); - EXPECT_STREQ("sint64" , GetTypeNameForFieldType(FD::TYPE_SINT64 )); + EXPECT_STREQ("sint32", GetTypeNameForFieldType(FD::TYPE_SINT32)); + EXPECT_STREQ("sint64", GetTypeNameForFieldType(FD::TYPE_SINT64)); } TEST_F(MiscTest, StaticTypeNames) { @@ -2141,24 +2373,24 @@ TEST_F(MiscTest, StaticTypeNames) { typedef FieldDescriptor FD; // avoid ugly line wrapping - EXPECT_STREQ("double" , FD::TypeName(FD::TYPE_DOUBLE )); - EXPECT_STREQ("float" , FD::TypeName(FD::TYPE_FLOAT )); - EXPECT_STREQ("int64" , FD::TypeName(FD::TYPE_INT64 )); - EXPECT_STREQ("uint64" , FD::TypeName(FD::TYPE_UINT64 )); - EXPECT_STREQ("int32" , FD::TypeName(FD::TYPE_INT32 )); - EXPECT_STREQ("fixed64" , FD::TypeName(FD::TYPE_FIXED64 )); - EXPECT_STREQ("fixed32" , FD::TypeName(FD::TYPE_FIXED32 )); - EXPECT_STREQ("bool" , FD::TypeName(FD::TYPE_BOOL )); - EXPECT_STREQ("string" , FD::TypeName(FD::TYPE_STRING )); - EXPECT_STREQ("group" , FD::TypeName(FD::TYPE_GROUP )); - EXPECT_STREQ("message" , FD::TypeName(FD::TYPE_MESSAGE )); - EXPECT_STREQ("bytes" , FD::TypeName(FD::TYPE_BYTES )); - EXPECT_STREQ("uint32" , FD::TypeName(FD::TYPE_UINT32 )); - EXPECT_STREQ("enum" , FD::TypeName(FD::TYPE_ENUM )); + EXPECT_STREQ("double", FD::TypeName(FD::TYPE_DOUBLE)); + EXPECT_STREQ("float", FD::TypeName(FD::TYPE_FLOAT)); + EXPECT_STREQ("int64", FD::TypeName(FD::TYPE_INT64)); + EXPECT_STREQ("uint64", FD::TypeName(FD::TYPE_UINT64)); + EXPECT_STREQ("int32", FD::TypeName(FD::TYPE_INT32)); + EXPECT_STREQ("fixed64", FD::TypeName(FD::TYPE_FIXED64)); + EXPECT_STREQ("fixed32", FD::TypeName(FD::TYPE_FIXED32)); + EXPECT_STREQ("bool", FD::TypeName(FD::TYPE_BOOL)); + EXPECT_STREQ("string", FD::TypeName(FD::TYPE_STRING)); + EXPECT_STREQ("group", FD::TypeName(FD::TYPE_GROUP)); + EXPECT_STREQ("message", FD::TypeName(FD::TYPE_MESSAGE)); + EXPECT_STREQ("bytes", FD::TypeName(FD::TYPE_BYTES)); + EXPECT_STREQ("uint32", FD::TypeName(FD::TYPE_UINT32)); + EXPECT_STREQ("enum", FD::TypeName(FD::TYPE_ENUM)); EXPECT_STREQ("sfixed32", FD::TypeName(FD::TYPE_SFIXED32)); EXPECT_STREQ("sfixed64", FD::TypeName(FD::TYPE_SFIXED64)); - EXPECT_STREQ("sint32" , FD::TypeName(FD::TYPE_SINT32 )); - EXPECT_STREQ("sint64" , FD::TypeName(FD::TYPE_SINT64 )); + EXPECT_STREQ("sint32", FD::TypeName(FD::TYPE_SINT32)); + EXPECT_STREQ("sint64", FD::TypeName(FD::TYPE_SINT64)); } TEST_F(MiscTest, CppTypes) { @@ -2166,24 +2398,24 @@ TEST_F(MiscTest, CppTypes) { typedef FieldDescriptor FD; // avoid ugly line wrapping - EXPECT_EQ(FD::CPPTYPE_DOUBLE , GetCppTypeForFieldType(FD::TYPE_DOUBLE )); - EXPECT_EQ(FD::CPPTYPE_FLOAT , GetCppTypeForFieldType(FD::TYPE_FLOAT )); - EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_INT64 )); - EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_UINT64 )); - EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_INT32 )); - EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_FIXED64 )); - EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_FIXED32 )); - EXPECT_EQ(FD::CPPTYPE_BOOL , GetCppTypeForFieldType(FD::TYPE_BOOL )); - EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_STRING )); - EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_GROUP )); - EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_MESSAGE )); - EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_BYTES )); - EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_UINT32 )); - EXPECT_EQ(FD::CPPTYPE_ENUM , GetCppTypeForFieldType(FD::TYPE_ENUM )); - EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_SFIXED32)); - EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_SFIXED64)); - EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_SINT32 )); - EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_SINT64 )); + EXPECT_EQ(FD::CPPTYPE_DOUBLE, GetCppTypeForFieldType(FD::TYPE_DOUBLE)); + EXPECT_EQ(FD::CPPTYPE_FLOAT, GetCppTypeForFieldType(FD::TYPE_FLOAT)); + EXPECT_EQ(FD::CPPTYPE_INT64, GetCppTypeForFieldType(FD::TYPE_INT64)); + EXPECT_EQ(FD::CPPTYPE_UINT64, GetCppTypeForFieldType(FD::TYPE_UINT64)); + EXPECT_EQ(FD::CPPTYPE_INT32, GetCppTypeForFieldType(FD::TYPE_INT32)); + EXPECT_EQ(FD::CPPTYPE_UINT64, GetCppTypeForFieldType(FD::TYPE_FIXED64)); + EXPECT_EQ(FD::CPPTYPE_UINT32, GetCppTypeForFieldType(FD::TYPE_FIXED32)); + EXPECT_EQ(FD::CPPTYPE_BOOL, GetCppTypeForFieldType(FD::TYPE_BOOL)); + EXPECT_EQ(FD::CPPTYPE_STRING, GetCppTypeForFieldType(FD::TYPE_STRING)); + EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_GROUP)); + EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_MESSAGE)); + EXPECT_EQ(FD::CPPTYPE_STRING, GetCppTypeForFieldType(FD::TYPE_BYTES)); + EXPECT_EQ(FD::CPPTYPE_UINT32, GetCppTypeForFieldType(FD::TYPE_UINT32)); + EXPECT_EQ(FD::CPPTYPE_ENUM, GetCppTypeForFieldType(FD::TYPE_ENUM)); + EXPECT_EQ(FD::CPPTYPE_INT32, GetCppTypeForFieldType(FD::TYPE_SFIXED32)); + EXPECT_EQ(FD::CPPTYPE_INT64, GetCppTypeForFieldType(FD::TYPE_SFIXED64)); + EXPECT_EQ(FD::CPPTYPE_INT32, GetCppTypeForFieldType(FD::TYPE_SINT32)); + EXPECT_EQ(FD::CPPTYPE_INT64, GetCppTypeForFieldType(FD::TYPE_SINT64)); } TEST_F(MiscTest, CppTypeNames) { @@ -2191,24 +2423,24 @@ TEST_F(MiscTest, CppTypeNames) { typedef FieldDescriptor FD; // avoid ugly line wrapping - EXPECT_STREQ("double" , GetCppTypeNameForFieldType(FD::TYPE_DOUBLE )); - EXPECT_STREQ("float" , GetCppTypeNameForFieldType(FD::TYPE_FLOAT )); - EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_INT64 )); - EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_UINT64 )); - EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_INT32 )); - EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_FIXED64 )); - EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_FIXED32 )); - EXPECT_STREQ("bool" , GetCppTypeNameForFieldType(FD::TYPE_BOOL )); - EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_STRING )); - EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_GROUP )); - EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE )); - EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_BYTES )); - EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_UINT32 )); - EXPECT_STREQ("enum" , GetCppTypeNameForFieldType(FD::TYPE_ENUM )); - EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED32)); - EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED64)); - EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SINT32 )); - EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SINT64 )); + EXPECT_STREQ("double", GetCppTypeNameForFieldType(FD::TYPE_DOUBLE)); + EXPECT_STREQ("float", GetCppTypeNameForFieldType(FD::TYPE_FLOAT)); + EXPECT_STREQ("int64", GetCppTypeNameForFieldType(FD::TYPE_INT64)); + EXPECT_STREQ("uint64", GetCppTypeNameForFieldType(FD::TYPE_UINT64)); + EXPECT_STREQ("int32", GetCppTypeNameForFieldType(FD::TYPE_INT32)); + EXPECT_STREQ("uint64", GetCppTypeNameForFieldType(FD::TYPE_FIXED64)); + EXPECT_STREQ("uint32", GetCppTypeNameForFieldType(FD::TYPE_FIXED32)); + EXPECT_STREQ("bool", GetCppTypeNameForFieldType(FD::TYPE_BOOL)); + EXPECT_STREQ("string", GetCppTypeNameForFieldType(FD::TYPE_STRING)); + EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_GROUP)); + EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE)); + EXPECT_STREQ("string", GetCppTypeNameForFieldType(FD::TYPE_BYTES)); + EXPECT_STREQ("uint32", GetCppTypeNameForFieldType(FD::TYPE_UINT32)); + EXPECT_STREQ("enum", GetCppTypeNameForFieldType(FD::TYPE_ENUM)); + EXPECT_STREQ("int32", GetCppTypeNameForFieldType(FD::TYPE_SFIXED32)); + EXPECT_STREQ("int64", GetCppTypeNameForFieldType(FD::TYPE_SFIXED64)); + EXPECT_STREQ("int32", GetCppTypeNameForFieldType(FD::TYPE_SINT32)); + EXPECT_STREQ("int64", GetCppTypeNameForFieldType(FD::TYPE_SINT64)); } TEST_F(MiscTest, StaticCppTypeNames) { @@ -2216,69 +2448,68 @@ TEST_F(MiscTest, StaticCppTypeNames) { typedef FieldDescriptor FD; // avoid ugly line wrapping - EXPECT_STREQ("int32" , FD::CppTypeName(FD::CPPTYPE_INT32 )); - EXPECT_STREQ("int64" , FD::CppTypeName(FD::CPPTYPE_INT64 )); - EXPECT_STREQ("uint32" , FD::CppTypeName(FD::CPPTYPE_UINT32 )); - EXPECT_STREQ("uint64" , FD::CppTypeName(FD::CPPTYPE_UINT64 )); - EXPECT_STREQ("double" , FD::CppTypeName(FD::CPPTYPE_DOUBLE )); - EXPECT_STREQ("float" , FD::CppTypeName(FD::CPPTYPE_FLOAT )); - EXPECT_STREQ("bool" , FD::CppTypeName(FD::CPPTYPE_BOOL )); - EXPECT_STREQ("enum" , FD::CppTypeName(FD::CPPTYPE_ENUM )); - EXPECT_STREQ("string" , FD::CppTypeName(FD::CPPTYPE_STRING )); + EXPECT_STREQ("int32", FD::CppTypeName(FD::CPPTYPE_INT32)); + EXPECT_STREQ("int64", FD::CppTypeName(FD::CPPTYPE_INT64)); + EXPECT_STREQ("uint32", FD::CppTypeName(FD::CPPTYPE_UINT32)); + EXPECT_STREQ("uint64", FD::CppTypeName(FD::CPPTYPE_UINT64)); + EXPECT_STREQ("double", FD::CppTypeName(FD::CPPTYPE_DOUBLE)); + EXPECT_STREQ("float", FD::CppTypeName(FD::CPPTYPE_FLOAT)); + EXPECT_STREQ("bool", FD::CppTypeName(FD::CPPTYPE_BOOL)); + EXPECT_STREQ("enum", FD::CppTypeName(FD::CPPTYPE_ENUM)); + EXPECT_STREQ("string", FD::CppTypeName(FD::CPPTYPE_STRING)); EXPECT_STREQ("message", FD::CppTypeName(FD::CPPTYPE_MESSAGE)); } TEST_F(MiscTest, MessageType) { - // Test that message_type() is NULL for non-aggregate fields + // Test that message_type() is nullptr for non-aggregate fields typedef FieldDescriptor FD; // avoid ugly line wrapping - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_DOUBLE )); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FLOAT )); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT64 )); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT64 )); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT32 )); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED64 )); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED32 )); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BOOL )); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_STRING )); - EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_GROUP )); - EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_MESSAGE )); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BYTES )); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT32 )); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_ENUM )); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED32)); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED64)); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT32 )); - EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT64 )); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_DOUBLE)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_FLOAT)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_INT64)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_UINT64)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_INT32)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_FIXED64)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_FIXED32)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_BOOL)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_STRING)); + EXPECT_TRUE(nullptr != GetMessageDescriptorForFieldType(FD::TYPE_GROUP)); + EXPECT_TRUE(nullptr != GetMessageDescriptorForFieldType(FD::TYPE_MESSAGE)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_BYTES)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_UINT32)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_ENUM)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED32)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED64)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_SINT32)); + EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_SINT64)); } TEST_F(MiscTest, EnumType) { - // Test that enum_type() is NULL for non-enum fields + // Test that enum_type() is nullptr for non-enum fields typedef FieldDescriptor FD; // avoid ugly line wrapping - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_DOUBLE )); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FLOAT )); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT64 )); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT64 )); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT32 )); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED64 )); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED32 )); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BOOL )); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_STRING )); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_GROUP )); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_MESSAGE )); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BYTES )); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT32 )); - EXPECT_TRUE(NULL != GetEnumDescriptorForFieldType(FD::TYPE_ENUM )); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED32)); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED64)); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT32 )); - EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT64 )); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_DOUBLE)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_FLOAT)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_INT64)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_UINT64)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_INT32)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_FIXED64)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_FIXED32)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_BOOL)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_STRING)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_GROUP)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_MESSAGE)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_BYTES)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_UINT32)); + EXPECT_TRUE(nullptr != GetEnumDescriptorForFieldType(FD::TYPE_ENUM)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED32)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED64)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_SINT32)); + EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_SINT64)); } - TEST_F(MiscTest, DefaultValues) { // Test that setting default values works. FileDescriptorProto file_proto; @@ -2294,52 +2525,52 @@ TEST_F(MiscTest, DefaultValues) { const FD::Label label = FD::LABEL_OPTIONAL; // Create fields of every CPP type with default values. - AddField(message_proto, "int32" , 1, label, FD::TYPE_INT32 ) - ->set_default_value("-1"); - AddField(message_proto, "int64" , 2, label, FD::TYPE_INT64 ) - ->set_default_value("-1000000000000"); + AddField(message_proto, "int32", 1, label, FD::TYPE_INT32) + ->set_default_value("-1"); + AddField(message_proto, "int64", 2, label, FD::TYPE_INT64) + ->set_default_value("-1000000000000"); AddField(message_proto, "uint32", 3, label, FD::TYPE_UINT32) - ->set_default_value("42"); + ->set_default_value("42"); AddField(message_proto, "uint64", 4, label, FD::TYPE_UINT64) - ->set_default_value("2000000000000"); - AddField(message_proto, "float" , 5, label, FD::TYPE_FLOAT ) - ->set_default_value("4.5"); + ->set_default_value("2000000000000"); + AddField(message_proto, "float", 5, label, FD::TYPE_FLOAT) + ->set_default_value("4.5"); AddField(message_proto, "double", 6, label, FD::TYPE_DOUBLE) - ->set_default_value("10e100"); - AddField(message_proto, "bool" , 7, label, FD::TYPE_BOOL ) - ->set_default_value("true"); + ->set_default_value("10e100"); + AddField(message_proto, "bool", 7, label, FD::TYPE_BOOL) + ->set_default_value("true"); AddField(message_proto, "string", 8, label, FD::TYPE_STRING) - ->set_default_value("hello"); - AddField(message_proto, "data" , 9, label, FD::TYPE_BYTES ) - ->set_default_value("\\001\\002\\003"); + ->set_default_value("hello"); + AddField(message_proto, "data", 9, label, FD::TYPE_BYTES) + ->set_default_value("\\001\\002\\003"); FieldDescriptorProto* enum_field = - AddField(message_proto, "enum", 10, label, FD::TYPE_ENUM); + AddField(message_proto, "enum", 10, label, FD::TYPE_ENUM); enum_field->set_type_name("DummyEnum"); enum_field->set_default_value("B"); // Strings are allowed to have empty defaults. (At one point, due to // a bug, empty defaults for strings were rejected. Oops.) AddField(message_proto, "empty_string", 11, label, FD::TYPE_STRING) - ->set_default_value(""); + ->set_default_value(""); - // Add a second set of fields with implicit defalut values. - AddField(message_proto, "implicit_int32" , 21, label, FD::TYPE_INT32 ); - AddField(message_proto, "implicit_int64" , 22, label, FD::TYPE_INT64 ); + // Add a second set of fields with implicit default values. + AddField(message_proto, "implicit_int32", 21, label, FD::TYPE_INT32); + AddField(message_proto, "implicit_int64", 22, label, FD::TYPE_INT64); AddField(message_proto, "implicit_uint32", 23, label, FD::TYPE_UINT32); AddField(message_proto, "implicit_uint64", 24, label, FD::TYPE_UINT64); - AddField(message_proto, "implicit_float" , 25, label, FD::TYPE_FLOAT ); + AddField(message_proto, "implicit_float", 25, label, FD::TYPE_FLOAT); AddField(message_proto, "implicit_double", 26, label, FD::TYPE_DOUBLE); - AddField(message_proto, "implicit_bool" , 27, label, FD::TYPE_BOOL ); + AddField(message_proto, "implicit_bool", 27, label, FD::TYPE_BOOL); AddField(message_proto, "implicit_string", 28, label, FD::TYPE_STRING); - AddField(message_proto, "implicit_data" , 29, label, FD::TYPE_BYTES ); - AddField(message_proto, "implicit_enum" , 30, label, FD::TYPE_ENUM) - ->set_type_name("DummyEnum"); + AddField(message_proto, "implicit_data", 29, label, FD::TYPE_BYTES); + AddField(message_proto, "implicit_enum", 30, label, FD::TYPE_ENUM) + ->set_type_name("DummyEnum"); // Build it. DescriptorPool pool; const FileDescriptor* file = pool.BuildFile(file_proto); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); ASSERT_EQ(1, file->enum_type_count()); const EnumDescriptor* enum_type = file->enum_type(0); @@ -2365,19 +2596,17 @@ TEST_F(MiscTest, DefaultValues) { ASSERT_TRUE(message->field(9)->has_default_value()); ASSERT_TRUE(message->field(10)->has_default_value()); - EXPECT_EQ(-1 , message->field(0)->default_value_int32 ()); - EXPECT_EQ(-GOOGLE_ULONGLONG(1000000000000), - message->field(1)->default_value_int64 ()); - EXPECT_EQ(42 , message->field(2)->default_value_uint32()); - EXPECT_EQ(GOOGLE_ULONGLONG(2000000000000), - message->field(3)->default_value_uint64()); - EXPECT_EQ(4.5 , message->field(4)->default_value_float ()); - EXPECT_EQ(10e100 , message->field(5)->default_value_double()); - EXPECT_TRUE( message->field(6)->default_value_bool ()); - EXPECT_EQ("hello" , message->field(7)->default_value_string()); - EXPECT_EQ("\001\002\003" , message->field(8)->default_value_string()); - EXPECT_EQ(enum_value_b , message->field(9)->default_value_enum ()); - EXPECT_EQ("" , message->field(10)->default_value_string()); + EXPECT_EQ(-1, message->field(0)->default_value_int32()); + EXPECT_EQ(int64{-1000000000000}, message->field(1)->default_value_int64()); + EXPECT_EQ(42, message->field(2)->default_value_uint32()); + EXPECT_EQ(uint64{2000000000000}, message->field(3)->default_value_uint64()); + EXPECT_EQ(4.5, message->field(4)->default_value_float()); + EXPECT_EQ(10e100, message->field(5)->default_value_double()); + EXPECT_TRUE(message->field(6)->default_value_bool()); + EXPECT_EQ("hello", message->field(7)->default_value_string()); + EXPECT_EQ("\001\002\003", message->field(8)->default_value_string()); + EXPECT_EQ(enum_value_b, message->field(9)->default_value_enum()); + EXPECT_EQ("", message->field(10)->default_value_string()); ASSERT_FALSE(message->field(11)->has_default_value()); ASSERT_FALSE(message->field(12)->has_default_value()); @@ -2390,15 +2619,15 @@ TEST_F(MiscTest, DefaultValues) { ASSERT_FALSE(message->field(19)->has_default_value()); ASSERT_FALSE(message->field(20)->has_default_value()); - EXPECT_EQ(0 , message->field(11)->default_value_int32 ()); - EXPECT_EQ(0 , message->field(12)->default_value_int64 ()); - EXPECT_EQ(0 , message->field(13)->default_value_uint32()); - EXPECT_EQ(0 , message->field(14)->default_value_uint64()); - EXPECT_EQ(0.0f , message->field(15)->default_value_float ()); - EXPECT_EQ(0.0 , message->field(16)->default_value_double()); - EXPECT_FALSE( message->field(17)->default_value_bool ()); - EXPECT_EQ("" , message->field(18)->default_value_string()); - EXPECT_EQ("" , message->field(19)->default_value_string()); + EXPECT_EQ(0, message->field(11)->default_value_int32()); + EXPECT_EQ(0, message->field(12)->default_value_int64()); + EXPECT_EQ(0, message->field(13)->default_value_uint32()); + EXPECT_EQ(0, message->field(14)->default_value_uint64()); + EXPECT_EQ(0.0f, message->field(15)->default_value_float()); + EXPECT_EQ(0.0, message->field(16)->default_value_double()); + EXPECT_FALSE(message->field(17)->default_value_bool()); + EXPECT_EQ("", message->field(18)->default_value_string()); + EXPECT_EQ("", message->field(19)->default_value_string()); EXPECT_EQ(enum_value_a, message->field(20)->default_value_enum()); } @@ -2409,13 +2638,11 @@ TEST_F(MiscTest, FieldOptions) { file_proto.set_name("foo.proto"); DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage"); - AddField(message_proto, "foo", 1, - FieldDescriptorProto::LABEL_OPTIONAL, + AddField(message_proto, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32); FieldDescriptorProto* bar_proto = - AddField(message_proto, "bar", 2, - FieldDescriptorProto::LABEL_OPTIONAL, - FieldDescriptorProto::TYPE_INT32); + AddField(message_proto, "bar", 2, FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); FieldOptions* options = bar_proto->mutable_options(); options->set_ctype(FieldOptions::CORD); @@ -2423,7 +2650,7 @@ TEST_F(MiscTest, FieldOptions) { // Build the descriptors and get the pointers. DescriptorPool pool; const FileDescriptor* file = pool.BuildFile(file_proto); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); ASSERT_EQ(1, file->message_type_count()); const Descriptor* message = file->message_type(0); @@ -2442,17 +2669,14 @@ TEST_F(MiscTest, FieldOptions) { } // =================================================================== -enum DescriptorPoolMode { - NO_DATABASE, - FALLBACK_DATABASE -}; +enum DescriptorPoolMode { NO_DATABASE, FALLBACK_DATABASE }; class AllowUnknownDependenciesTest - : public testing::TestWithParam { + : public testing::TestWithParam< + std::tuple> { protected: - DescriptorPoolMode mode() { - return GetParam(); - } + DescriptorPoolMode mode() { return std::get<0>(GetParam()); } + const char* syntax() { return std::get<1>(GetParam()); } virtual void SetUp() { FileDescriptorProto foo_proto, bar_proto; @@ -2469,42 +2693,45 @@ class AllowUnknownDependenciesTest pool_->AllowUnknownDependencies(); ASSERT_TRUE(TextFormat::ParseFromString( - "name: 'foo.proto'" - "dependency: 'bar.proto'" - "dependency: 'baz.proto'" - "message_type {" - " name: 'Foo'" - " field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'Bar' }" - " field { name:'baz' number:2 label:LABEL_OPTIONAL type_name:'Baz' }" - " field { name:'qux' number:3 label:LABEL_OPTIONAL" - " type_name: '.corge.Qux'" - " type: TYPE_ENUM" - " options {" - " uninterpreted_option {" - " name {" - " name_part: 'grault'" - " is_extension: true" - " }" - " positive_int_value: 1234" - " }" - " }" - " }" - "}", - &foo_proto)); - ASSERT_TRUE(TextFormat::ParseFromString( - "name: 'bar.proto'" - "message_type { name: 'Bar' }", - &bar_proto)); + "name: 'foo.proto'" + "dependency: 'bar.proto'" + "dependency: 'baz.proto'" + "message_type {" + " name: 'Foo'" + " field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'Bar' }" + " field { name:'baz' number:2 label:LABEL_OPTIONAL type_name:'Baz' }" + " field { name:'qux' number:3 label:LABEL_OPTIONAL" + " type_name: '.corge.Qux'" + " type: TYPE_ENUM" + " options {" + " uninterpreted_option {" + " name {" + " name_part: 'grault'" + " is_extension: true" + " }" + " positive_int_value: 1234" + " }" + " }" + " }" + "}", + &foo_proto)); + foo_proto.set_syntax(syntax()); + + ASSERT_TRUE( + TextFormat::ParseFromString("name: 'bar.proto'" + "message_type { name: 'Bar' }", + &bar_proto)); + bar_proto.set_syntax(syntax()); // Collect pointers to stuff. bar_file_ = BuildFile(bar_proto); - ASSERT_TRUE(bar_file_ != NULL); + ASSERT_TRUE(bar_file_ != nullptr); ASSERT_EQ(1, bar_file_->message_type_count()); bar_type_ = bar_file_->message_type(0); foo_file_ = BuildFile(foo_proto); - ASSERT_TRUE(foo_file_ != NULL); + ASSERT_TRUE(foo_file_ != nullptr); ASSERT_EQ(1, foo_file_->message_type_count()); foo_type_ = foo_file_->message_type(0); @@ -2526,7 +2753,7 @@ class AllowUnknownDependenciesTest } } GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; + return nullptr; } const FileDescriptor* bar_file_; @@ -2537,8 +2764,8 @@ class AllowUnknownDependenciesTest const FieldDescriptor* baz_field_; const FieldDescriptor* qux_field_; - SimpleDescriptorDatabase db_; // used if in FALLBACK_DATABASE mode. - google::protobuf::scoped_ptr pool_; + SimpleDescriptorDatabase db_; // used if in FALLBACK_DATABASE mode. + std::unique_ptr pool_; }; TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) { @@ -2553,7 +2780,7 @@ TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) { // Placeholder files should not be findable. EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name())); - EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL); + EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == nullptr); // Copy*To should not crash for placeholder files. FileDescriptorProto baz_file_proto; @@ -2582,8 +2809,8 @@ TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) { // Placeholder types should not be findable. EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name())); - EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == NULL); - EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == NULL); + EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == nullptr); + EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == nullptr); } TEST_P(AllowUnknownDependenciesTest, CopyTo) { @@ -2613,7 +2840,7 @@ TEST_P(AllowUnknownDependenciesTest, CustomOptions) { // Qux should still have the uninterpreted option attached. ASSERT_EQ(1, qux_field_->options().uninterpreted_option_size()); const UninterpretedOption& option = - qux_field_->options().uninterpreted_option(0); + qux_field_->options().uninterpreted_option(0); ASSERT_EQ(1, option.name_size()); EXPECT_EQ("grault", option.name(0).name_part()); } @@ -2625,13 +2852,13 @@ TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) { FileDescriptorProto extension_proto; ASSERT_TRUE(TextFormat::ParseFromString( - "name: 'extension.proto'" - "extension { extendee: 'UnknownType' name:'some_extension' number:123" - " label:LABEL_OPTIONAL type:TYPE_INT32 }", - &extension_proto)); + "name: 'extension.proto'" + "extension { extendee: 'UnknownType' name:'some_extension' number:123" + " label:LABEL_OPTIONAL type:TYPE_INT32 }", + &extension_proto)); const FileDescriptor* file = BuildFile(extension_proto); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); ASSERT_EQ(1, file->extension_count()); const Descriptor* extendee = file->extension(0)->containing_type(); @@ -2649,42 +2876,42 @@ TEST_P(AllowUnknownDependenciesTest, CustomOption) { FileDescriptorProto option_proto; ASSERT_TRUE(TextFormat::ParseFromString( - "name: \"unknown_custom_options.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "extension { " - " extendee: \"google.protobuf.FileOptions\" " - " name: \"some_option\" " - " number: 123456 " - " label: LABEL_OPTIONAL " - " type: TYPE_INT32 " - "} " - "options { " - " uninterpreted_option { " - " name { " - " name_part: \"some_option\" " - " is_extension: true " - " } " - " positive_int_value: 1234 " - " } " - " uninterpreted_option { " - " name { " - " name_part: \"unknown_option\" " - " is_extension: true " - " } " - " positive_int_value: 1234 " - " } " - " uninterpreted_option { " - " name { " - " name_part: \"optimize_for\" " - " is_extension: false " - " } " - " identifier_value: \"SPEED\" " - " } " - "}", - &option_proto)); + "name: \"unknown_custom_options.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { " + " extendee: \"google.protobuf.FileOptions\" " + " name: \"some_option\" " + " number: 123456 " + " label: LABEL_OPTIONAL " + " type: TYPE_INT32 " + "} " + "options { " + " uninterpreted_option { " + " name { " + " name_part: \"some_option\" " + " is_extension: true " + " } " + " positive_int_value: 1234 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"unknown_option\" " + " is_extension: true " + " } " + " positive_int_value: 1234 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"optimize_for\" " + " is_extension: false " + " } " + " identifier_value: \"SPEED\" " + " } " + "}", + &option_proto)); const FileDescriptor* file = BuildFile(option_proto); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); // Verify that no extension options were set, but they were left as // uninterpreted_options. @@ -2708,25 +2935,25 @@ TEST_P(AllowUnknownDependenciesTest, FileDescriptorProto undeclared_dep_proto; // We make this file fail to build by giving it two fields with tag 1. ASSERT_TRUE(TextFormat::ParseFromString( - "name: \"invalid_file_as_undeclared_dep.proto\" " - "package: \"undeclared\" " - "message_type: { " - " name: \"Quux\" " - " field { " - " name:'qux' number:1 label:LABEL_OPTIONAL type: TYPE_INT32 " - " }" - " field { " - " name:'quux' number:1 label:LABEL_OPTIONAL type: TYPE_INT64 " - " }" - "}", - &undeclared_dep_proto)); + "name: \"invalid_file_as_undeclared_dep.proto\" " + "package: \"undeclared\" " + "message_type: { " + " name: \"Quux\" " + " field { " + " name:'qux' number:1 label:LABEL_OPTIONAL type: TYPE_INT32 " + " }" + " field { " + " name:'quux' number:1 label:LABEL_OPTIONAL type: TYPE_INT64 " + " }" + "}", + &undeclared_dep_proto)); // We can't use the BuildFile() helper because we don't actually want to build // it into the descriptor pool in the fallback database case: it just needs to // be sitting in the database so that it gets built during the building of // test.proto below. switch (mode()) { case NO_DATABASE: { - ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == NULL); + ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == nullptr); break; } case FALLBACK_DATABASE: { @@ -2736,18 +2963,18 @@ TEST_P(AllowUnknownDependenciesTest, FileDescriptorProto test_proto; ASSERT_TRUE(TextFormat::ParseFromString( - "name: \"test.proto\" " - "message_type: { " - " name: \"Corge\" " - " field { " - " name:'quux' number:1 label: LABEL_OPTIONAL " - " type_name:'undeclared.Quux' type: TYPE_MESSAGE " - " }" - "}", - &test_proto)); + "name: \"test.proto\" " + "message_type: { " + " name: \"Corge\" " + " field { " + " name:'quux' number:1 label: LABEL_OPTIONAL " + " type_name:'undeclared.Quux' type: TYPE_MESSAGE " + " }" + "}", + &test_proto)); const FileDescriptor* file = BuildFile(test_proto); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); GOOGLE_LOG(INFO) << file->DebugString(); EXPECT_EQ(0, file->dependency_count()); @@ -2763,12 +2990,13 @@ TEST_P(AllowUnknownDependenciesTest, ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name()); EXPECT_TRUE(quux_field->message_type()->is_placeholder()); // The place holder type should not be findable. - ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL); + ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == nullptr); } -INSTANTIATE_TEST_CASE_P(DatabaseSource, - AllowUnknownDependenciesTest, - testing::Values(NO_DATABASE, FALLBACK_DATABASE)); +INSTANTIATE_TEST_SUITE_P(DatabaseSource, AllowUnknownDependenciesTest, + testing::Combine(testing::Values(NO_DATABASE, + FALLBACK_DATABASE), + testing::Values("proto2", "proto3"))); // =================================================================== @@ -2784,22 +3012,19 @@ TEST(CustomOptions, OptionLocations) { file->FindServiceByName("TestServiceWithCustomOptions"); const MethodDescriptor* method = service->FindMethodByName("Foo"); - EXPECT_EQ(GOOGLE_LONGLONG(9876543210), + EXPECT_EQ(int64{9876543210}, file->options().GetExtension(protobuf_unittest::file_opt1)); EXPECT_EQ(-56, message->options().GetExtension(protobuf_unittest::message_opt1)); - EXPECT_EQ(GOOGLE_LONGLONG(8765432109), + EXPECT_EQ(int64{8765432109}, field->options().GetExtension(protobuf_unittest::field_opt1)); EXPECT_EQ(42, // Check that we get the default for an option we don't set. field->options().GetExtension(protobuf_unittest::field_opt2)); - EXPECT_EQ(-99, - oneof->options().GetExtension(protobuf_unittest::oneof_opt1)); - EXPECT_EQ(-789, - enm->options().GetExtension(protobuf_unittest::enum_opt1)); - EXPECT_EQ(123, - enm->value(1)->options().GetExtension( - protobuf_unittest::enum_value_opt1)); - EXPECT_EQ(GOOGLE_LONGLONG(-9876543210), + EXPECT_EQ(-99, oneof->options().GetExtension(protobuf_unittest::oneof_opt1)); + EXPECT_EQ(-789, enm->options().GetExtension(protobuf_unittest::enum_opt1)); + EXPECT_EQ(123, enm->value(1)->options().GetExtension( + protobuf_unittest::enum_value_opt1)); + EXPECT_EQ(int64{-9876543210}, service->options().GetExtension(protobuf_unittest::service_opt1)); EXPECT_EQ(protobuf_unittest::METHODOPT1_VAL2, method->options().GetExtension(protobuf_unittest::method_opt1)); @@ -2810,38 +3035,37 @@ TEST(CustomOptions, OptionLocations) { } TEST(CustomOptions, OptionTypes) { - const MessageOptions* options = NULL; + const MessageOptions* options = nullptr; options = &protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options(); - EXPECT_EQ(false , options->GetExtension(protobuf_unittest::bool_opt)); + EXPECT_EQ(false, options->GetExtension(protobuf_unittest::bool_opt)); EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::int32_opt)); EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::int64_opt)); - EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint32_opt)); - EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint64_opt)); + EXPECT_EQ(0, options->GetExtension(protobuf_unittest::uint32_opt)); + EXPECT_EQ(0, options->GetExtension(protobuf_unittest::uint64_opt)); EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sint32_opt)); EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sint64_opt)); - EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::fixed32_opt)); - EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::fixed64_opt)); + EXPECT_EQ(0, options->GetExtension(protobuf_unittest::fixed32_opt)); + EXPECT_EQ(0, options->GetExtension(protobuf_unittest::fixed64_opt)); EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sfixed32_opt)); EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sfixed64_opt)); options = &protobuf_unittest::CustomOptionMaxIntegerValues::descriptor()->options(); - EXPECT_EQ(true , options->GetExtension(protobuf_unittest::bool_opt)); - EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::int32_opt)); - EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::int64_opt)); + EXPECT_EQ(true, options->GetExtension(protobuf_unittest::bool_opt)); + EXPECT_EQ(kint32max, options->GetExtension(protobuf_unittest::int32_opt)); + EXPECT_EQ(kint64max, options->GetExtension(protobuf_unittest::int64_opt)); EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::uint32_opt)); EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::uint64_opt)); - EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sint32_opt)); - EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sint64_opt)); + EXPECT_EQ(kint32max, options->GetExtension(protobuf_unittest::sint32_opt)); + EXPECT_EQ(kint64max, options->GetExtension(protobuf_unittest::sint64_opt)); EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::fixed32_opt)); EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::fixed64_opt)); - EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sfixed32_opt)); - EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sfixed64_opt)); + EXPECT_EQ(kint32max, options->GetExtension(protobuf_unittest::sfixed32_opt)); + EXPECT_EQ(kint64max, options->GetExtension(protobuf_unittest::sfixed64_opt)); - options = - &protobuf_unittest::CustomOptionOtherValues::descriptor()->options(); + options = &protobuf_unittest::CustomOptionOtherValues::descriptor()->options(); EXPECT_EQ(-100, options->GetExtension(protobuf_unittest::int32_opt)); EXPECT_FLOAT_EQ(12.3456789, options->GetExtension(protobuf_unittest::float_opt)); @@ -2850,7 +3074,7 @@ TEST(CustomOptions, OptionTypes) { EXPECT_EQ("Hello, \"World\"", options->GetExtension(protobuf_unittest::string_opt)); - EXPECT_EQ(string("Hello\0World", 11), + EXPECT_EQ(std::string("Hello\0World", 11), options->GetExtension(protobuf_unittest::bytes_opt)); EXPECT_EQ(protobuf_unittest::DummyMessageContainingEnum::TEST_OPTION_ENUM_TYPE2, @@ -2871,35 +3095,52 @@ TEST(CustomOptions, ComplexExtensionOptions) { const MessageOptions* options = &protobuf_unittest::VariousComplexOptions::descriptor()->options(); EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).foo(), 42); - EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1). - GetExtension(protobuf_unittest::quux), 324); - EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1). - GetExtension(protobuf_unittest::corge).qux(), 876); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1) + .GetExtension(protobuf_unittest::quux), + 324); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1) + .GetExtension(protobuf_unittest::corge) + .qux(), + 876); EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).baz(), 987); - EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2). - GetExtension(protobuf_unittest::grault), 654); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2) + .GetExtension(protobuf_unittest::grault), + 654); EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().foo(), 743); - EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar(). - GetExtension(protobuf_unittest::quux), 1999); - EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar(). - GetExtension(protobuf_unittest::corge).qux(), 2008); - EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2). - GetExtension(protobuf_unittest::garply).foo(), 741); - EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2). - GetExtension(protobuf_unittest::garply). - GetExtension(protobuf_unittest::quux), 1998); - EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2). - GetExtension(protobuf_unittest::garply). - GetExtension(protobuf_unittest::corge).qux(), 2121); - EXPECT_EQ(options->GetExtension( - protobuf_unittest::ComplexOptionType2::ComplexOptionType4::complex_opt4). - waldo(), 1971); - EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2). - fred().waldo(), 321); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2) + .bar() + .GetExtension(protobuf_unittest::quux), + 1999); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2) + .bar() + .GetExtension(protobuf_unittest::corge) + .qux(), + 2008); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2) + .GetExtension(protobuf_unittest::garply) + .foo(), + 741); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2) + .GetExtension(protobuf_unittest::garply) + .GetExtension(protobuf_unittest::quux), + 1998); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2) + .GetExtension(protobuf_unittest::garply) + .GetExtension(protobuf_unittest::corge) + .qux(), + 2121); + EXPECT_EQ(options + ->GetExtension(protobuf_unittest::ComplexOptionType2:: + ComplexOptionType4::complex_opt4) + .waldo(), + 1971); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).fred().waldo(), + 321); EXPECT_EQ(9, options->GetExtension(protobuf_unittest::complex_opt3).qux()); - EXPECT_EQ(22, options->GetExtension(protobuf_unittest::complex_opt3). - complexoptiontype5().plugh()); + EXPECT_EQ(22, options->GetExtension(protobuf_unittest::complex_opt3) + .complexoptiontype5() + .plugh()); EXPECT_EQ(24, options->GetExtension(protobuf_unittest::complexopt6).xyzzy()); } @@ -2910,48 +3151,52 @@ TEST(CustomOptions, OptionsFromOtherFile) { FileDescriptorProto file_proto; FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); + + // We have to import the Any dependency. + FileDescriptorProto any_proto; + google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto); + ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr); - protobuf_unittest::TestMessageWithCustomOptions::descriptor() - ->file()->CopyTo(&file_proto); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo( + &file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); ASSERT_TRUE(TextFormat::ParseFromString( - "name: \"custom_options_import.proto\" " - "package: \"protobuf_unittest\" " - "dependency: \"google/protobuf/unittest_custom_options.proto\" " - "options { " - " uninterpreted_option { " - " name { " - " name_part: \"file_opt1\" " - " is_extension: true " - " } " - " positive_int_value: 1234 " - " } " - // Test a non-extension option too. (At one point this failed due to a - // bug.) - " uninterpreted_option { " - " name { " - " name_part: \"java_package\" " - " is_extension: false " - " } " - " string_value: \"foo\" " - " } " - // Test that enum-typed options still work too. (At one point this also - // failed due to a bug.) - " uninterpreted_option { " - " name { " - " name_part: \"optimize_for\" " - " is_extension: false " - " } " - " identifier_value: \"SPEED\" " - " } " - "}" - , - &file_proto)); + "name: \"custom_options_import.proto\" " + "package: \"protobuf_unittest\" " + "dependency: \"google/protobuf/unittest_custom_options.proto\" " + "options { " + " uninterpreted_option { " + " name { " + " name_part: \"file_opt1\" " + " is_extension: true " + " } " + " positive_int_value: 1234 " + " } " + // Test a non-extension option too. (At one point this failed due to a + // bug.) + " uninterpreted_option { " + " name { " + " name_part: \"java_package\" " + " is_extension: false " + " } " + " string_value: \"foo\" " + " } " + // Test that enum-typed options still work too. (At one point this also + // failed due to a bug.) + " uninterpreted_option { " + " name { " + " name_part: \"optimize_for\" " + " is_extension: false " + " } " + " identifier_value: \"SPEED\" " + " } " + "}", + &file_proto)); const FileDescriptor* file = pool.BuildFile(file_proto); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); EXPECT_EQ(1234, file->options().GetExtension(protobuf_unittest::file_opt1)); EXPECT_TRUE(file->options().has_java_package()); EXPECT_EQ("foo", file->options().java_package()); @@ -2969,11 +3214,15 @@ TEST(CustomOptions, MessageOptionThreeFieldsSet) { FileDescriptorProto file_proto; FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); + + FileDescriptorProto any_proto; + google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto); + ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr); - protobuf_unittest::TestMessageWithCustomOptions::descriptor() - ->file()->CopyTo(&file_proto); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo( + &file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); // The following represents the definition: // @@ -2985,51 +3234,51 @@ TEST(CustomOptions, MessageOptionThreeFieldsSet) { // option (complex_opt1).foo3 = 1234; // } ASSERT_TRUE(TextFormat::ParseFromString( - "name: \"custom_options_import.proto\" " - "package: \"protobuf_unittest\" " - "dependency: \"google/protobuf/unittest_custom_options.proto\" " - "message_type { " - " name: \"Foo\" " - " options { " - " uninterpreted_option { " - " name { " - " name_part: \"complex_opt1\" " - " is_extension: true " - " } " - " name { " - " name_part: \"foo\" " - " is_extension: false " - " } " - " positive_int_value: 1234 " - " } " - " uninterpreted_option { " - " name { " - " name_part: \"complex_opt1\" " - " is_extension: true " - " } " - " name { " - " name_part: \"foo2\" " - " is_extension: false " - " } " - " positive_int_value: 1234 " - " } " - " uninterpreted_option { " - " name { " - " name_part: \"complex_opt1\" " - " is_extension: true " - " } " - " name { " - " name_part: \"foo3\" " - " is_extension: false " - " } " - " positive_int_value: 1234 " - " } " - " } " - "}", - &file_proto)); + "name: \"custom_options_import.proto\" " + "package: \"protobuf_unittest\" " + "dependency: \"google/protobuf/unittest_custom_options.proto\" " + "message_type { " + " name: \"Foo\" " + " options { " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo\" " + " is_extension: false " + " } " + " positive_int_value: 1234 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo2\" " + " is_extension: false " + " } " + " positive_int_value: 1234 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo3\" " + " is_extension: false " + " } " + " positive_int_value: 1234 " + " } " + " } " + "}", + &file_proto)); const FileDescriptor* file = pool.BuildFile(file_proto); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); ASSERT_EQ(1, file->message_type_count()); const MessageOptions& options = file->message_type(0)->options(); @@ -3046,11 +3295,15 @@ TEST(CustomOptions, MessageOptionRepeatedLeafFieldSet) { FileDescriptorProto file_proto; FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); - protobuf_unittest::TestMessageWithCustomOptions::descriptor() - ->file()->CopyTo(&file_proto); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + FileDescriptorProto any_proto; + google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto); + ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr); + + protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo( + &file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); // The following represents the definition: // @@ -3062,51 +3315,51 @@ TEST(CustomOptions, MessageOptionRepeatedLeafFieldSet) { // option (complex_opt1).foo4 = 56; // } ASSERT_TRUE(TextFormat::ParseFromString( - "name: \"custom_options_import.proto\" " - "package: \"protobuf_unittest\" " - "dependency: \"google/protobuf/unittest_custom_options.proto\" " - "message_type { " - " name: \"Foo\" " - " options { " - " uninterpreted_option { " - " name { " - " name_part: \"complex_opt1\" " - " is_extension: true " - " } " - " name { " - " name_part: \"foo4\" " - " is_extension: false " - " } " - " positive_int_value: 12 " - " } " - " uninterpreted_option { " - " name { " - " name_part: \"complex_opt1\" " - " is_extension: true " - " } " - " name { " - " name_part: \"foo4\" " - " is_extension: false " - " } " - " positive_int_value: 34 " - " } " - " uninterpreted_option { " - " name { " - " name_part: \"complex_opt1\" " - " is_extension: true " - " } " - " name { " - " name_part: \"foo4\" " - " is_extension: false " - " } " - " positive_int_value: 56 " - " } " - " } " - "}", - &file_proto)); + "name: \"custom_options_import.proto\" " + "package: \"protobuf_unittest\" " + "dependency: \"google/protobuf/unittest_custom_options.proto\" " + "message_type { " + " name: \"Foo\" " + " options { " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo4\" " + " is_extension: false " + " } " + " positive_int_value: 12 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo4\" " + " is_extension: false " + " } " + " positive_int_value: 34 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo4\" " + " is_extension: false " + " } " + " positive_int_value: 56 " + " } " + " } " + "}", + &file_proto)); const FileDescriptor* file = pool.BuildFile(file_proto); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); ASSERT_EQ(1, file->message_type_count()); const MessageOptions& options = file->message_type(0)->options(); @@ -3126,11 +3379,15 @@ TEST(CustomOptions, MessageOptionRepeatedMsgFieldSet) { FileDescriptorProto file_proto; FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); + + FileDescriptorProto any_proto; + google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto); + ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr); - protobuf_unittest::TestMessageWithCustomOptions::descriptor() - ->file()->CopyTo(&file_proto); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo( + &file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); // The following represents the definition: // @@ -3142,62 +3399,64 @@ TEST(CustomOptions, MessageOptionRepeatedMsgFieldSet) { // option (complex_opt2).barney = {waldo: 100}; // } ASSERT_TRUE(TextFormat::ParseFromString( - "name: \"custom_options_import.proto\" " - "package: \"protobuf_unittest\" " - "dependency: \"google/protobuf/unittest_custom_options.proto\" " - "message_type { " - " name: \"Foo\" " - " options { " - " uninterpreted_option { " - " name { " - " name_part: \"complex_opt2\" " - " is_extension: true " - " } " - " name { " - " name_part: \"barney\" " - " is_extension: false " - " } " - " aggregate_value: \"waldo: 1\" " - " } " - " uninterpreted_option { " - " name { " - " name_part: \"complex_opt2\" " - " is_extension: true " - " } " - " name { " - " name_part: \"barney\" " - " is_extension: false " - " } " - " aggregate_value: \"waldo: 10\" " - " } " - " uninterpreted_option { " - " name { " - " name_part: \"complex_opt2\" " - " is_extension: true " - " } " - " name { " - " name_part: \"barney\" " - " is_extension: false " - " } " - " aggregate_value: \"waldo: 100\" " - " } " - " } " - "}", - &file_proto)); + "name: \"custom_options_import.proto\" " + "package: \"protobuf_unittest\" " + "dependency: \"google/protobuf/unittest_custom_options.proto\" " + "message_type { " + " name: \"Foo\" " + " options { " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt2\" " + " is_extension: true " + " } " + " name { " + " name_part: \"barney\" " + " is_extension: false " + " } " + " aggregate_value: \"waldo: 1\" " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt2\" " + " is_extension: true " + " } " + " name { " + " name_part: \"barney\" " + " is_extension: false " + " } " + " aggregate_value: \"waldo: 10\" " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt2\" " + " is_extension: true " + " } " + " name { " + " name_part: \"barney\" " + " is_extension: false " + " } " + " aggregate_value: \"waldo: 100\" " + " } " + " } " + "}", + &file_proto)); const FileDescriptor* file = pool.BuildFile(file_proto); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); ASSERT_EQ(1, file->message_type_count()); const MessageOptions& options = file->message_type(0)->options(); - EXPECT_EQ(3, options.GetExtension( - protobuf_unittest::complex_opt2).barney_size()); - EXPECT_EQ(1,options.GetExtension( - protobuf_unittest::complex_opt2).barney(0).waldo()); - EXPECT_EQ(10, options.GetExtension( - protobuf_unittest::complex_opt2).barney(1).waldo()); - EXPECT_EQ(100, options.GetExtension( - protobuf_unittest::complex_opt2).barney(2).waldo()); + EXPECT_EQ(3, + options.GetExtension(protobuf_unittest::complex_opt2).barney_size()); + EXPECT_EQ( + 1, options.GetExtension(protobuf_unittest::complex_opt2).barney(0).waldo()); + EXPECT_EQ( + 10, + options.GetExtension(protobuf_unittest::complex_opt2).barney(1).waldo()); + EXPECT_EQ( + 100, + options.GetExtension(protobuf_unittest::complex_opt2).barney(2).waldo()); } // Check that aggregate options were parsed and saved correctly in @@ -3208,8 +3467,8 @@ TEST(CustomOptions, AggregateOptions) { const FieldDescriptor* field = msg->FindFieldByName("fieldname"); const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum"); const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE"); - const ServiceDescriptor* service = file->FindServiceByName( - "AggregateService"); + const ServiceDescriptor* service = + file->FindServiceByName("AggregateService"); const MethodDescriptor* method = service->FindMethodByName("Method"); // Tests for the different types of data embedded in fileopt @@ -3221,9 +3480,14 @@ TEST(CustomOptions, AggregateOptions) { EXPECT_EQ("FileExtensionAnnotation", file_options.file().GetExtension(protobuf_unittest::fileopt).s()); EXPECT_EQ("EmbeddedMessageSetElement", - file_options.mset().GetExtension( - protobuf_unittest::AggregateMessageSetElement - ::message_set_extension).s()); + file_options.mset() + .GetExtension(protobuf_unittest::AggregateMessageSetElement :: + message_set_extension) + .s()); + + protobuf_unittest::AggregateMessageSetElement any_payload; + ASSERT_TRUE(file_options.any().UnpackTo(&any_payload)); + EXPECT_EQ("EmbeddedMessageSetElement", any_payload.s()); // Simple tests for all the other types of annotations EXPECT_EQ("MessageAnnotation", @@ -3240,38 +3504,46 @@ TEST(CustomOptions, AggregateOptions) { method->options().GetExtension(protobuf_unittest::methodopt).s()); } -TEST(CustomOptions, UnusedImportWarning) { +TEST(CustomOptions, UnusedImportError) { DescriptorPool pool; FileDescriptorProto file_proto; FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); + + FileDescriptorProto any_proto; + google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto); + ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr); - protobuf_unittest::TestMessageWithCustomOptions::descriptor() - ->file()->CopyTo(&file_proto); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo( + &file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); - pool.AddUnusedImportTrackFile("custom_options_import.proto"); + pool.AddUnusedImportTrackFile("custom_options_import.proto", true); ASSERT_TRUE(TextFormat::ParseFromString( - "name: \"custom_options_import.proto\" " - "package: \"protobuf_unittest\" " - "dependency: \"google/protobuf/unittest_custom_options.proto\" ", - &file_proto)); + "name: \"custom_options_import.proto\" " + "package: \"protobuf_unittest\" " + "dependency: \"google/protobuf/unittest_custom_options.proto\" ", + &file_proto)); MockErrorCollector error_collector; - EXPECT_TRUE(pool.BuildFileCollectingErrors(file_proto, &error_collector)); - EXPECT_EQ("", error_collector.warning_text_); + EXPECT_FALSE(pool.BuildFileCollectingErrors(file_proto, &error_collector)); + EXPECT_EQ( + "custom_options_import.proto: " + "google/protobuf/unittest_custom_options.proto: IMPORT: Import " + "google/protobuf/unittest_custom_options.proto is unused.\n", + error_collector.text_); } // Verifies that proto files can correctly be parsed, even if the // custom options defined in the file are incompatible with those // compiled in the binary. See http://b/19276250. -TEST(CustomOptions, OptionsWithRequiredEnums) { +TEST(CustomOptions, OptionsWithIncompatibleDescriptors) { DescriptorPool pool; FileDescriptorProto file_proto; MessageOptions::descriptor()->file()->CopyTo(&file_proto); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); // Create a new file descriptor proto containing a subset of the // messages defined in google/protobuf/unittest_custom_options.proto. @@ -3282,61 +3554,36 @@ TEST(CustomOptions, OptionsWithRequiredEnums) { // Add the "required_enum_opt" extension. FieldDescriptorProto* extension = file_proto.add_extension(); - protobuf_unittest::OldOptionType::descriptor()->file() - ->FindExtensionByName("required_enum_opt")->CopyTo(extension); + protobuf_unittest::OldOptionType::descriptor() + ->file() + ->FindExtensionByName("required_enum_opt") + ->CopyTo(extension); // Add a test message that uses the "required_enum_opt" option. DescriptorProto* test_message_type = file_proto.add_message_type(); - protobuf_unittest::TestMessageWithRequiredEnumOption::descriptor() - ->CopyTo(test_message_type); + protobuf_unittest::TestMessageWithRequiredEnumOption::descriptor()->CopyTo( + test_message_type); // Instruct the extension to use NewOptionType instead of // OldOptionType, and add the descriptor of NewOptionType. extension->set_type_name(".protobuf_unittest.NewOptionType"); DescriptorProto* new_option_type = file_proto.add_message_type(); - protobuf_unittest::NewOptionType::descriptor() - ->CopyTo(new_option_type); + protobuf_unittest::NewOptionType::descriptor()->CopyTo(new_option_type); // Replace the value of the "required_enum_opt" option used in the // test message with an enum value that only exists in NewOptionType. - ASSERT_TRUE(TextFormat::ParseFromString( - "uninterpreted_option { " - " name { " - " name_part: 'required_enum_opt' " - " is_extension: true " - " } " - " aggregate_value: 'value: NEW_VALUE' " - "}", - test_message_type->mutable_options())); - - // Add the file descriptor to the pool. - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); - - // Find the test message. - const Descriptor* test_message = pool.FindMessageTypeByName( - "protobuf_unittest.TestMessageWithRequiredEnumOption"); - ASSERT_TRUE(test_message != NULL); - - const MessageOptions& options = test_message->options(); - // Extract the "required_enum_opt" option. Since the binary does not - // know that the extension was updated, this will still return an - // OldOptionType message. ASSERT_TRUE( - options.HasExtension(protobuf_unittest::required_enum_opt)); - const protobuf_unittest::OldOptionType& old_enum_opt = - options.GetExtension(protobuf_unittest::required_enum_opt); - - // Confirm that the required enum field is missing. - EXPECT_FALSE(old_enum_opt.IsInitialized()); - EXPECT_FALSE(old_enum_opt.has_value()); + TextFormat::ParseFromString("uninterpreted_option { " + " name { " + " name_part: 'required_enum_opt' " + " is_extension: true " + " } " + " aggregate_value: 'value: NEW_VALUE'" + "}", + test_message_type->mutable_options())); - string buf; - // Verify that the required enum field does show up when the option - // is re-parsed as a NewOptionType message; - protobuf_unittest::NewOptionType new_enum_opt; - EXPECT_TRUE(old_enum_opt.AppendPartialToString(&buf)); - EXPECT_TRUE(new_enum_opt.ParseFromString(buf)); - EXPECT_EQ(protobuf_unittest::NewOptionType::NEW_VALUE, new_enum_opt.value()); + // Adding the file descriptor to the pool should fail. + EXPECT_TRUE(pool.BuildFile(file_proto) == nullptr); } // Test that FileDescriptor::DebugString() formats custom options correctly. @@ -3345,7 +3592,7 @@ TEST(CustomOptions, DebugString) { FileDescriptorProto file_proto; MessageOptions::descriptor()->file()->CopyTo(&file_proto); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); // Add "foo.proto": // import "google/protobuf/descriptor.proto"; @@ -3397,7 +3644,7 @@ TEST(CustomOptions, DebugString) { "}", &file_proto)); const FileDescriptor* descriptor = pool.BuildFile(file_proto); - ASSERT_TRUE(descriptor != NULL); + ASSERT_TRUE(descriptor != nullptr); EXPECT_EQ(2, descriptor->extension_count()); @@ -3424,7 +3671,7 @@ class ValidationErrorTest : public testing::Test { protected: // Parse file_text as a FileDescriptorProto in text format and add it // to the DescriptorPool. Expect no errors. - const FileDescriptor* BuildFile(const string& file_text) { + const FileDescriptor* BuildFile(const std::string& file_text) { FileDescriptorProto file_proto; EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); return GOOGLE_CHECK_NOTNULL(pool_.BuildFile(file_proto)); @@ -3433,22 +3680,22 @@ class ValidationErrorTest : public testing::Test { // Parse file_text as a FileDescriptorProto in text format and add it // to the DescriptorPool. Expect errors to be produced which match the // given error text. - void BuildFileWithErrors(const string& file_text, - const string& expected_errors) { + void BuildFileWithErrors(const std::string& file_text, + const std::string& expected_errors) { FileDescriptorProto file_proto; ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); MockErrorCollector error_collector; - EXPECT_TRUE( - pool_.BuildFileCollectingErrors(file_proto, &error_collector) == NULL); + EXPECT_TRUE(pool_.BuildFileCollectingErrors(file_proto, &error_collector) == + nullptr); EXPECT_EQ(expected_errors, error_collector.text_); } // Parse file_text as a FileDescriptorProto in text format and add it // to the DescriptorPool. Expect errors to be produced which match the // given warning text. - void BuildFileWithWarnings(const string& file_text, - const string& expected_warnings) { + void BuildFileWithWarnings(const std::string& file_text, + const std::string& expected_warnings) { FileDescriptorProto file_proto; ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); @@ -3461,7 +3708,7 @@ class ValidationErrorTest : public testing::Test { void BuildFileInTestPool(const FileDescriptor* file) { FileDescriptorProto file_proto; file->CopyTo(&file_proto); - ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL); + ASSERT_TRUE(pool_.BuildFile(file_proto) != nullptr); } // Build descriptor.proto in our test pool. This allows us to extend it in @@ -3475,57 +3722,57 @@ class ValidationErrorTest : public testing::Test { TEST_F(ValidationErrorTest, AlreadyDefined) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type { name: \"Foo\" }" - "message_type { name: \"Foo\" }", + "name: \"foo.proto\" " + "message_type { name: \"Foo\" }" + "message_type { name: \"Foo\" }", - "foo.proto: Foo: NAME: \"Foo\" is already defined.\n"); + "foo.proto: Foo: NAME: \"Foo\" is already defined.\n"); } TEST_F(ValidationErrorTest, AlreadyDefinedInPackage) { BuildFileWithErrors( - "name: \"foo.proto\" " - "package: \"foo.bar\" " - "message_type { name: \"Foo\" }" - "message_type { name: \"Foo\" }", + "name: \"foo.proto\" " + "package: \"foo.bar\" " + "message_type { name: \"Foo\" }" + "message_type { name: \"Foo\" }", - "foo.proto: foo.bar.Foo: NAME: \"Foo\" is already defined in " + "foo.proto: foo.bar.Foo: NAME: \"Foo\" is already defined in " "\"foo.bar\".\n"); } TEST_F(ValidationErrorTest, AlreadyDefinedInOtherFile) { BuildFile( - "name: \"foo.proto\" " - "message_type { name: \"Foo\" }"); + "name: \"foo.proto\" " + "message_type { name: \"Foo\" }"); BuildFileWithErrors( - "name: \"bar.proto\" " - "message_type { name: \"Foo\" }", + "name: \"bar.proto\" " + "message_type { name: \"Foo\" }", - "bar.proto: Foo: NAME: \"Foo\" is already defined in file " + "bar.proto: Foo: NAME: \"Foo\" is already defined in file " "\"foo.proto\".\n"); } TEST_F(ValidationErrorTest, PackageAlreadyDefined) { BuildFile( - "name: \"foo.proto\" " - "message_type { name: \"foo\" }"); + "name: \"foo.proto\" " + "message_type { name: \"foo\" }"); BuildFileWithErrors( - "name: \"bar.proto\" " - "package: \"foo.bar\"", + "name: \"bar.proto\" " + "package: \"foo.bar\"", - "bar.proto: foo: NAME: \"foo\" is already defined (as something other " + "bar.proto: foo: NAME: \"foo\" is already defined (as something other " "than a package) in file \"foo.proto\".\n"); } TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParent) { BuildFileWithErrors( - "name: \"foo.proto\" " - "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } " - "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ", + "name: \"foo.proto\" " + "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } " + "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ", - "foo.proto: FOO: NAME: \"FOO\" is already defined.\n" - "foo.proto: FOO: NAME: Note that enum values use C++ scoping rules, " + "foo.proto: FOO: NAME: \"FOO\" is already defined.\n" + "foo.proto: FOO: NAME: Note that enum values use C++ scoping rules, " "meaning that enum values are siblings of their type, not children of " "it. Therefore, \"FOO\" must be unique within the global scope, not " "just within \"Bar\".\n"); @@ -3533,13 +3780,13 @@ TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParent) { TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParentNonGlobal) { BuildFileWithErrors( - "name: \"foo.proto\" " - "package: \"pkg\" " - "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } " - "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ", + "name: \"foo.proto\" " + "package: \"pkg\" " + "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } " + "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ", - "foo.proto: pkg.FOO: NAME: \"FOO\" is already defined in \"pkg\".\n" - "foo.proto: pkg.FOO: NAME: Note that enum values use C++ scoping rules, " + "foo.proto: pkg.FOO: NAME: \"FOO\" is already defined in \"pkg\".\n" + "foo.proto: pkg.FOO: NAME: Note that enum values use C++ scoping rules, " "meaning that enum values are siblings of their type, not children of " "it. Therefore, \"FOO\" must be unique within \"pkg\", not just within " "\"Bar\".\n"); @@ -3547,60 +3794,99 @@ TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParentNonGlobal) { TEST_F(ValidationErrorTest, MissingName) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type { }", + "name: \"foo.proto\" " + "message_type { }", - "foo.proto: : NAME: Missing name.\n"); + "foo.proto: : NAME: Missing name.\n"); } TEST_F(ValidationErrorTest, InvalidName) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type { name: \"$\" }", + "name: \"foo.proto\" " + "message_type { name: \"$\" }", - "foo.proto: $: NAME: \"$\" is not a valid identifier.\n"); + "foo.proto: $: NAME: \"$\" is not a valid identifier.\n"); } TEST_F(ValidationErrorTest, InvalidPackageName) { BuildFileWithErrors( - "name: \"foo.proto\" " - "package: \"foo.$\"", + "name: \"foo.proto\" " + "package: \"foo.$\"", - "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n"); + "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n"); } -TEST_F(ValidationErrorTest, MissingFileName) { +// 'str' is a static C-style string that may contain '\0' +#define STATIC_STR(str) std::string((str), sizeof(str) - 1) + +TEST_F(ValidationErrorTest, NullCharSymbolName) { + BuildFileWithErrors( + "name: \"bar.proto\" " + "package: \"foo\"" + "message_type { " + " name: '\\000\\001\\013.Bar' " + " field { name: \"foo\" number: 9 label:LABEL_OPTIONAL type:TYPE_INT32 " + "} " + "}", + STATIC_STR("bar.proto: foo.\0\x1\v.Bar: NAME: \"\0\x1\v.Bar\" is not a " + "valid identifier.\nbar.proto: foo.\0\x1\v.Bar: NAME: " + "\"\0\x1\v.Bar\" is not a valid identifier.\nbar.proto: " + "foo.\0\x1\v.Bar: NAME: \"\0\x1\v.Bar\" is not a valid " + "identifier.\nbar.proto: foo.\0\x1\v.Bar: NAME: " + "\"\0\x1\v.Bar\" is not a valid identifier.\nbar.proto: " + "foo.\0\x1\v.Bar.foo: NAME: \"foo.\0\x1\v.Bar.foo\" contains " + "null character.\nbar.proto: foo.\0\x1\v.Bar: NAME: " + "\"foo.\0\x1\v.Bar\" contains null character.\n")); +} + +TEST_F(ValidationErrorTest, NullCharFileName) { + BuildFileWithErrors( + "name: \"bar\\000\\001\\013.proto\" " + "package: \"outer.foo\"", + STATIC_STR("bar\0\x1\v.proto: bar\0\x1\v.proto: NAME: " + "\"bar\0\x1\v.proto\" contains null character.\n")); +} + +TEST_F(ValidationErrorTest, NullCharPackageName) { BuildFileWithErrors( - "", + "name: \"bar.proto\" " + "package: \"\\000\\001\\013.\"", + STATIC_STR("bar.proto: \0\x1\v.: NAME: \"\0\x1\v.\" contains null " + "character.\n")); +} + +TEST_F(ValidationErrorTest, MissingFileName) { + BuildFileWithErrors("", - ": : OTHER: Missing field: FileDescriptorProto.name.\n"); + ": : OTHER: Missing field: FileDescriptorProto.name.\n"); } TEST_F(ValidationErrorTest, DupeDependency) { BuildFile("name: \"foo.proto\""); BuildFileWithErrors( - "name: \"bar.proto\" " - "dependency: \"foo.proto\" " - "dependency: \"foo.proto\" ", + "name: \"bar.proto\" " + "dependency: \"foo.proto\" " + "dependency: \"foo.proto\" ", - "bar.proto: bar.proto: OTHER: Import \"foo.proto\" was listed twice.\n"); + "bar.proto: foo.proto: IMPORT: Import \"foo.proto\" was listed twice.\n"); } TEST_F(ValidationErrorTest, UnknownDependency) { BuildFileWithErrors( - "name: \"bar.proto\" " - "dependency: \"foo.proto\" ", + "name: \"bar.proto\" " + "dependency: \"foo.proto\" ", - "bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n"); + "bar.proto: foo.proto: IMPORT: Import \"foo.proto\" has not been " + "loaded.\n"); } TEST_F(ValidationErrorTest, InvalidPublicDependencyIndex) { BuildFile("name: \"foo.proto\""); BuildFileWithErrors( - "name: \"bar.proto\" " - "dependency: \"foo.proto\" " - "public_dependency: 1", - "bar.proto: bar.proto: OTHER: Invalid public dependency index.\n"); + "name: \"bar.proto\" " + "dependency: \"foo.proto\" " + "public_dependency: 1", + "bar.proto: bar.proto: OTHER: Invalid public dependency index.\n"); } TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) { @@ -3610,315 +3896,520 @@ TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) { // include that parent package in the name (i.e. we do a relative lookup)... // Yes, really. BuildFile( - "name: 'foo.proto' " - "package: 'outer.foo' "); - BuildFileWithErrors( - "name: 'bar.proto' " - "dependency: 'baz.proto' " - "package: 'outer.bar' " - "message_type { " - " name: 'Bar' " - " field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }" - "}", - - "bar.proto: bar.proto: OTHER: Import \"baz.proto\" has not been loaded.\n" - "bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined in " + "name: 'foo.proto' " + "package: 'outer.foo' "); + BuildFileWithErrors( + "name: 'bar.proto' " + "dependency: 'baz.proto' " + "package: 'outer.bar' " + "message_type { " + " name: 'Bar' " + " field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }" + "}", + + "bar.proto: baz.proto: IMPORT: Import \"baz.proto\" has not been " + "loaded.\n" + "bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined " + "in " "\"foo.proto\", which is not imported by \"bar.proto\". To use it here, " "please add the necessary import.\n"); } TEST_F(ValidationErrorTest, DupeFile) { BuildFile( - "name: \"foo.proto\" " - "message_type { name: \"Foo\" }"); + "name: \"foo.proto\" " + "message_type { name: \"Foo\" }"); // Note: We should *not* get redundant errors about "Foo" already being // defined. BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type { name: \"Foo\" } " - // Add another type so that the files aren't identical (in which case there - // would be no error). - "enum_type { name: \"Bar\" }", + "name: \"foo.proto\" " + "message_type { name: \"Foo\" } " + // Add another type so that the files aren't identical (in which case + // there would be no error). + "enum_type { name: \"Bar\" }", - "foo.proto: foo.proto: OTHER: A file with this name is already in the " + "foo.proto: foo.proto: OTHER: A file with this name is already in the " "pool.\n"); } TEST_F(ValidationErrorTest, FieldInExtensionRange) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name: \"foo\" number: 9 label:LABEL_OPTIONAL type:TYPE_INT32 }" - " field { name: \"bar\" number: 10 label:LABEL_OPTIONAL type:TYPE_INT32 }" - " field { name: \"baz\" number: 19 label:LABEL_OPTIONAL type:TYPE_INT32 }" - " field { name: \"qux\" number: 20 label:LABEL_OPTIONAL type:TYPE_INT32 }" - " extension_range { start: 10 end: 20 }" - "}", - - "foo.proto: Foo.bar: NUMBER: Extension range 10 to 19 includes field " + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name: \"foo\" number: 9 label:LABEL_OPTIONAL type:TYPE_INT32 " + "}" + " field { name: \"bar\" number: 10 label:LABEL_OPTIONAL type:TYPE_INT32 " + "}" + " field { name: \"baz\" number: 19 label:LABEL_OPTIONAL type:TYPE_INT32 " + "}" + " field { name: \"qux\" number: 20 label:LABEL_OPTIONAL type:TYPE_INT32 " + "}" + " extension_range { start: 10 end: 20 }" + "}", + + "foo.proto: Foo.bar: NUMBER: Extension range 10 to 19 includes field " "\"bar\" (10).\n" - "foo.proto: Foo.baz: NUMBER: Extension range 10 to 19 includes field " + "foo.proto: Foo.baz: NUMBER: Extension range 10 to 19 includes field " "\"baz\" (19).\n"); } TEST_F(ValidationErrorTest, OverlappingExtensionRanges) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " extension_range { start: 10 end: 20 }" - " extension_range { start: 20 end: 30 }" - " extension_range { start: 19 end: 21 }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension_range { start: 10 end: 20 }" + " extension_range { start: 20 end: 30 }" + " extension_range { start: 19 end: 21 }" + "}", - "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with " + "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with " "already-defined range 10 to 19.\n" - "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with " + "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with " "already-defined range 20 to 29.\n"); } TEST_F(ValidationErrorTest, ReservedFieldError) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 }" - " reserved_range { start: 10 end: 20 }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 " + "}" + " reserved_range { start: 10 end: 20 }" + "}", - "foo.proto: Foo.foo: NUMBER: Field \"foo\" uses reserved number 15.\n"); + "foo.proto: Foo.foo: NUMBER: Field \"foo\" uses reserved number 15.\n"); } TEST_F(ValidationErrorTest, ReservedExtensionRangeError) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " extension_range { start: 10 end: 20 }" - " reserved_range { start: 5 end: 15 }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension_range { start: 10 end: 20 }" + " reserved_range { start: 5 end: 15 }" + "}", - "foo.proto: Foo: NUMBER: Extension range 10 to 19" - " overlaps with reserved range 5 to 14.\n"); + "foo.proto: Foo: NUMBER: Extension range 10 to 19" + " overlaps with reserved range 5 to 14.\n"); } TEST_F(ValidationErrorTest, ReservedExtensionRangeAdjacent) { BuildFile( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " extension_range { start: 10 end: 20 }" - " reserved_range { start: 5 end: 10 }" - "}"); + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension_range { start: 10 end: 20 }" + " reserved_range { start: 5 end: 10 }" + "}"); } TEST_F(ValidationErrorTest, ReservedRangeOverlap) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " reserved_range { start: 10 end: 20 }" - " reserved_range { start: 5 end: 15 }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " reserved_range { start: 10 end: 20 }" + " reserved_range { start: 5 end: 15 }" + "}", - "foo.proto: Foo: NUMBER: Reserved range 5 to 14" - " overlaps with already-defined range 10 to 19.\n"); + "foo.proto: Foo: NUMBER: Reserved range 5 to 14" + " overlaps with already-defined range 10 to 19.\n"); } TEST_F(ValidationErrorTest, ReservedNameError) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 }" - " field { name: \"bar\" number: 16 label:LABEL_OPTIONAL type:TYPE_INT32 }" - " field { name: \"baz\" number: 17 label:LABEL_OPTIONAL type:TYPE_INT32 }" - " reserved_name: \"foo\"" - " reserved_name: \"bar\"" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 " + "}" + " field { name: \"bar\" number: 16 label:LABEL_OPTIONAL type:TYPE_INT32 " + "}" + " field { name: \"baz\" number: 17 label:LABEL_OPTIONAL type:TYPE_INT32 " + "}" + " reserved_name: \"foo\"" + " reserved_name: \"bar\"" + "}", - "foo.proto: Foo.foo: NAME: Field name \"foo\" is reserved.\n" - "foo.proto: Foo.bar: NAME: Field name \"bar\" is reserved.\n"); + "foo.proto: Foo.foo: NAME: Field name \"foo\" is reserved.\n" + "foo.proto: Foo.bar: NAME: Field name \"bar\" is reserved.\n"); } TEST_F(ValidationErrorTest, ReservedNameRedundant) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " reserved_name: \"foo\"" - " reserved_name: \"foo\"" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " reserved_name: \"foo\"" + " reserved_name: \"foo\"" + "}", - "foo.proto: foo: NAME: Field name \"foo\" is reserved multiple times.\n"); + "foo.proto: foo: NAME: Field name \"foo\" is reserved multiple times.\n"); } TEST_F(ValidationErrorTest, ReservedFieldsDebugString) { const FileDescriptor* file = BuildFile( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " reserved_name: \"foo\"" - " reserved_name: \"bar\"" - " reserved_range { start: 5 end: 6 }" - " reserved_range { start: 10 end: 20 }" - "}"); + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " reserved_name: \"foo\"" + " reserved_name: \"bar\"" + " reserved_range { start: 5 end: 6 }" + " reserved_range { start: 10 end: 20 }" + "}"); ASSERT_EQ( - "syntax = \"proto2\";\n\n" - "message Foo {\n" - " reserved 5, 10 to 19;\n" - " reserved \"foo\", \"bar\";\n" - "}\n\n", - file->DebugString()); + "syntax = \"proto2\";\n\n" + "message Foo {\n" + " reserved 5, 10 to 19;\n" + " reserved \"foo\", \"bar\";\n" + "}\n\n", + file->DebugString()); +} + +TEST_F(ValidationErrorTest, DebugStringReservedRangeMax) { + const FileDescriptor* file = BuildFile(strings::Substitute( + "name: \"foo.proto\" " + "enum_type { " + " name: \"Bar\"" + " value { name:\"BAR\" number:1 }" + " reserved_range { start: 5 end: $0 }" + "}" + "message_type {" + " name: \"Foo\"" + " reserved_range { start: 5 end: $1 }" + "}", + std::numeric_limits::max(), FieldDescriptor::kMaxNumber + 1)); + + ASSERT_EQ( + "syntax = \"proto2\";\n\n" + "enum Bar {\n" + " BAR = 1;\n" + " reserved 5 to max;\n" + "}\n\n" + "message Foo {\n" + " reserved 5 to max;\n" + "}\n\n", + file->DebugString()); +} + +TEST_F(ValidationErrorTest, EnumReservedFieldError) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Foo\"" + " value { name:\"BAR\" number:15 }" + " reserved_range { start: 10 end: 20 }" + "}", + + "foo.proto: BAR: NUMBER: Enum value \"BAR\" uses reserved number 15.\n"); +} + +TEST_F(ValidationErrorTest, EnumNegativeReservedFieldError) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Foo\"" + " value { name:\"BAR\" number:-15 }" + " reserved_range { start: -20 end: -10 }" + "}", + + "foo.proto: BAR: NUMBER: Enum value \"BAR\" uses reserved number -15.\n"); +} + +TEST_F(ValidationErrorTest, EnumReservedRangeOverlap) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Foo\"" + " value { name:\"BAR\" number:0 }" + " reserved_range { start: 10 end: 20 }" + " reserved_range { start: 5 end: 15 }" + "}", + + "foo.proto: Foo: NUMBER: Reserved range 5 to 15" + " overlaps with already-defined range 10 to 20.\n"); +} + +TEST_F(ValidationErrorTest, EnumReservedRangeOverlapByOne) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Foo\"" + " value { name:\"BAR\" number:0 }" + " reserved_range { start: 10 end: 20 }" + " reserved_range { start: 5 end: 10 }" + "}", + + "foo.proto: Foo: NUMBER: Reserved range 5 to 10" + " overlaps with already-defined range 10 to 20.\n"); +} + +TEST_F(ValidationErrorTest, EnumNegativeReservedRangeOverlap) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Foo\"" + " value { name:\"BAR\" number:0 }" + " reserved_range { start: -20 end: -10 }" + " reserved_range { start: -15 end: -5 }" + "}", + + "foo.proto: Foo: NUMBER: Reserved range -15 to -5" + " overlaps with already-defined range -20 to -10.\n"); +} + +TEST_F(ValidationErrorTest, EnumMixedReservedRangeOverlap) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Foo\"" + " value { name:\"BAR\" number:20 }" + " reserved_range { start: -20 end: 10 }" + " reserved_range { start: -15 end: 5 }" + "}", + + "foo.proto: Foo: NUMBER: Reserved range -15 to 5" + " overlaps with already-defined range -20 to 10.\n"); +} + +TEST_F(ValidationErrorTest, EnumMixedReservedRangeOverlap2) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Foo\"" + " value { name:\"BAR\" number:20 }" + " reserved_range { start: -20 end: 10 }" + " reserved_range { start: 10 end: 10 }" + "}", + + "foo.proto: Foo: NUMBER: Reserved range 10 to 10" + " overlaps with already-defined range -20 to 10.\n"); +} + +TEST_F(ValidationErrorTest, EnumReservedRangeStartGreaterThanEnd) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Foo\"" + " value { name:\"BAR\" number:20 }" + " reserved_range { start: 11 end: 10 }" + "}", + + "foo.proto: Foo: NUMBER: Reserved range end number must be greater" + " than start number.\n"); +} + +TEST_F(ValidationErrorTest, EnumReservedNameError) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Foo\"" + " value { name:\"FOO\" number:15 }" + " value { name:\"BAR\" number:15 }" + " reserved_name: \"FOO\"" + " reserved_name: \"BAR\"" + "}", + + "foo.proto: FOO: NAME: Enum value \"FOO\" is reserved.\n" + "foo.proto: BAR: NAME: Enum value \"BAR\" is reserved.\n"); +} + +TEST_F(ValidationErrorTest, EnumReservedNameRedundant) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Foo\"" + " value { name:\"FOO\" number:15 }" + " reserved_name: \"foo\"" + " reserved_name: \"foo\"" + "}", + + "foo.proto: foo: NAME: Enum value \"foo\" is reserved multiple times.\n"); +} + +TEST_F(ValidationErrorTest, EnumReservedFieldsDebugString) { + const FileDescriptor* file = BuildFile( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Foo\"" + " value { name:\"FOO\" number:3 }" + " reserved_name: \"foo\"" + " reserved_name: \"bar\"" + " reserved_range { start: -6 end: -6 }" + " reserved_range { start: -5 end: -4 }" + " reserved_range { start: -1 end: 1 }" + " reserved_range { start: 5 end: 5 }" + " reserved_range { start: 10 end: 19 }" + "}"); + + ASSERT_EQ( + "syntax = \"proto2\";\n\n" + "enum Foo {\n" + " FOO = 3;\n" + " reserved -6, -5 to -4, -1 to 1, 5, 10 to 19;\n" + " reserved \"foo\", \"bar\";\n" + "}\n\n", + file->DebugString()); } TEST_F(ValidationErrorTest, InvalidDefaults) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" - // Invalid number. - " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32" - " default_value: \"abc\" }" + // Invalid number. + " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32" + " default_value: \"abc\" }" - // Empty default value. - " field { name: \"bar\" number: 2 label: LABEL_OPTIONAL type: TYPE_INT32" - " default_value: \"\" }" + // Empty default value. + " field { name: \"bar\" number: 2 label: LABEL_OPTIONAL type: TYPE_INT32" + " default_value: \"\" }" - // Invalid boolean. - " field { name: \"baz\" number: 3 label: LABEL_OPTIONAL type: TYPE_BOOL" - " default_value: \"abc\" }" + // Invalid boolean. + " field { name: \"baz\" number: 3 label: LABEL_OPTIONAL type: TYPE_BOOL" + " default_value: \"abc\" }" - // Messages can't have defaults. - " field { name: \"qux\" number: 4 label: LABEL_OPTIONAL type: TYPE_MESSAGE" - " default_value: \"abc\" type_name: \"Foo\" }" + // Messages can't have defaults. + " field { name: \"qux\" number: 4 label: LABEL_OPTIONAL type: " + "TYPE_MESSAGE" + " default_value: \"abc\" type_name: \"Foo\" }" - // Same thing, but we don't know that this field has message type until - // we look up the type name. - " field { name: \"quux\" number: 5 label: LABEL_OPTIONAL" - " default_value: \"abc\" type_name: \"Foo\" }" + // Same thing, but we don't know that this field has message type until + // we look up the type name. + " field { name: \"quux\" number: 5 label: LABEL_OPTIONAL" + " default_value: \"abc\" type_name: \"Foo\" }" - // Repeateds can't have defaults. - " field { name: \"corge\" number: 6 label: LABEL_REPEATED type: TYPE_INT32" - " default_value: \"1\" }" - "}", + // Repeateds can't have defaults. + " field { name: \"corge\" number: 6 label: LABEL_REPEATED type: " + "TYPE_INT32" + " default_value: \"1\" }" + "}", - "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value \"abc\".\n" - "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value \"\".\n" - "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or " + "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value " + "\"abc\".\n" + "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value \"\".\n" + "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or " "false.\n" - "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n" - "foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default " + "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n" + "foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default " "values.\n" - // This ends up being reported later because the error is detected at - // cross-linking time. - "foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default " + // This ends up being reported later because the error is detected at + // cross-linking time. + "foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default " "values.\n"); } TEST_F(ValidationErrorTest, NegativeFieldNumber) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name: \"foo\" number: -1 label:LABEL_OPTIONAL type:TYPE_INT32 }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name: \"foo\" number: -1 label:LABEL_OPTIONAL type:TYPE_INT32 " + "}" + "}", - "foo.proto: Foo.foo: NUMBER: Field numbers must be positive integers.\n"); + "foo.proto: Foo.foo: NUMBER: Field numbers must be positive integers.\n"); } TEST_F(ValidationErrorTest, HugeFieldNumber) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name: \"foo\" number: 0x70000000 " - " label:LABEL_OPTIONAL type:TYPE_INT32 }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name: \"foo\" number: 0x70000000 " + " label:LABEL_OPTIONAL type:TYPE_INT32 }" + "}", - "foo.proto: Foo.foo: NUMBER: Field numbers cannot be greater than " + "foo.proto: Foo.foo: NUMBER: Field numbers cannot be greater than " "536870911.\n"); } TEST_F(ValidationErrorTest, ReservedFieldNumber) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field {name:\"foo\" number: 18999 label:LABEL_OPTIONAL type:TYPE_INT32 }" - " field {name:\"bar\" number: 19000 label:LABEL_OPTIONAL type:TYPE_INT32 }" - " field {name:\"baz\" number: 19999 label:LABEL_OPTIONAL type:TYPE_INT32 }" - " field {name:\"qux\" number: 20000 label:LABEL_OPTIONAL type:TYPE_INT32 }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field {name:\"foo\" number: 18999 label:LABEL_OPTIONAL " + "type:TYPE_INT32 }" + " field {name:\"bar\" number: 19000 label:LABEL_OPTIONAL " + "type:TYPE_INT32 }" + " field {name:\"baz\" number: 19999 label:LABEL_OPTIONAL " + "type:TYPE_INT32 }" + " field {name:\"qux\" number: 20000 label:LABEL_OPTIONAL " + "type:TYPE_INT32 }" + "}", - "foo.proto: Foo.bar: NUMBER: Field numbers 19000 through 19999 are " + "foo.proto: Foo.bar: NUMBER: Field numbers 19000 through 19999 are " "reserved for the protocol buffer library implementation.\n" - "foo.proto: Foo.baz: NUMBER: Field numbers 19000 through 19999 are " + "foo.proto: Foo.baz: NUMBER: Field numbers 19000 through 19999 are " "reserved for the protocol buffer library implementation.\n"); } TEST_F(ValidationErrorTest, ExtensionMissingExtendee) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " extension { name: \"foo\" number: 1 label: LABEL_OPTIONAL" - " type_name: \"Foo\" }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension { name: \"foo\" number: 1 label: LABEL_OPTIONAL" + " type_name: \"Foo\" }" + "}", - "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee not set for " + "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee not set for " "extension field.\n"); } TEST_F(ValidationErrorTest, NonExtensionWithExtendee) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Bar\"" - " extension_range { start: 1 end: 2 }" - "}" - "message_type {" - " name: \"Foo\"" - " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL" - " type_name: \"Foo\" extendee: \"Bar\" }" - "}", - - "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for " + "name: \"foo.proto\" " + "message_type {" + " name: \"Bar\"" + " extension_range { start: 1 end: 2 }" + "}" + "message_type {" + " name: \"Foo\"" + " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL" + " type_name: \"Foo\" extendee: \"Bar\" }" + "}", + + "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for " "non-extension field.\n"); } TEST_F(ValidationErrorTest, FieldOneofIndexTooLarge) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 " - " oneof_index: 1 }" - " field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 " - " oneof_index: 0 }" - " oneof_decl { name:\"bar\" }" - "}", - - "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index 1 is out of " + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 1 }" + " field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 0 }" + " oneof_decl { name:\"bar\" }" + "}", + + "foo.proto: Foo.foo: TYPE: FieldDescriptorProto.oneof_index 1 is out of " "range for type \"Foo\".\n"); } TEST_F(ValidationErrorTest, FieldOneofIndexNegative) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 " - " oneof_index: -1 }" - " field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 " - " oneof_index: 0 }" - " oneof_decl { name:\"bar\" }" - "}", - - "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index -1 is out of " + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: -1 }" + " field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 0 }" + " oneof_decl { name:\"bar\" }" + "}", + + "foo.proto: Foo.foo: TYPE: FieldDescriptorProto.oneof_index -1 is out " + "of " "range for type \"Foo\".\n"); } @@ -3936,7 +4427,7 @@ TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) { " oneof_decl { name:\"foos\" }" "}", - "foo.proto: Foo.bar: OTHER: Fields in the same oneof must be defined " + "foo.proto: Foo.bar: TYPE: Fields in the same oneof must be defined " "consecutively. \"bar\" cannot be defined before the completion of the " "\"foos\" oneof definition.\n"); @@ -3956,10 +4447,10 @@ TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) { " oneof_decl { name:\"foos\" }" " oneof_decl { name:\"bars\" }" "}", - "foo2.proto: Foo2.bar1: OTHER: Fields in the same oneof must be defined " + "foo2.proto: Foo2.bar1: TYPE: Fields in the same oneof must be defined " "consecutively. \"bar1\" cannot be defined before the completion of the " "\"foos\" oneof definition.\n" - "foo2.proto: Foo2.foo2: OTHER: Fields in the same oneof must be defined " + "foo2.proto: Foo2.foo2: TYPE: Fields in the same oneof must be defined " "consecutively. \"foo2\" cannot be defined before the completion of the " "\"bars\" oneof definition.\n"); @@ -3978,202 +4469,204 @@ TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) { " oneof_decl { name:\"foos\" }" " oneof_decl { name:\"bars\" }" "}", - "foo3.proto: Foo3.baz: OTHER: Fields in the same oneof must be defined " + "foo3.proto: Foo3.baz: TYPE: Fields in the same oneof must be defined " "consecutively. \"baz\" cannot be defined before the completion of the " "\"foos\" oneof definition.\n"); } TEST_F(ValidationErrorTest, FieldNumberConflict) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }" - " field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }" + "}", - "foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in " + "foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in " "\"Foo\" by field \"foo\".\n"); } TEST_F(ValidationErrorTest, BadMessageSetExtensionType) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"MessageSet\"" - " options { message_set_wire_format: true }" - " extension_range { start: 4 end: 5 }" - "}" - "message_type {" - " name: \"Foo\"" - " extension { name:\"foo\" number:4 label:LABEL_OPTIONAL type:TYPE_INT32" - " extendee: \"MessageSet\" }" - "}", - - "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional " + "name: \"foo.proto\" " + "message_type {" + " name: \"MessageSet\"" + " options { message_set_wire_format: true }" + " extension_range { start: 4 end: 5 }" + "}" + "message_type {" + " name: \"Foo\"" + " extension { name:\"foo\" number:4 label:LABEL_OPTIONAL type:TYPE_INT32" + " extendee: \"MessageSet\" }" + "}", + + "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional " "messages.\n"); } TEST_F(ValidationErrorTest, BadMessageSetExtensionLabel) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"MessageSet\"" - " options { message_set_wire_format: true }" - " extension_range { start: 4 end: 5 }" - "}" - "message_type {" - " name: \"Foo\"" - " extension { name:\"foo\" number:4 label:LABEL_REPEATED type:TYPE_MESSAGE" - " type_name: \"Foo\" extendee: \"MessageSet\" }" - "}", - - "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional " + "name: \"foo.proto\" " + "message_type {" + " name: \"MessageSet\"" + " options { message_set_wire_format: true }" + " extension_range { start: 4 end: 5 }" + "}" + "message_type {" + " name: \"Foo\"" + " extension { name:\"foo\" number:4 label:LABEL_REPEATED " + "type:TYPE_MESSAGE" + " type_name: \"Foo\" extendee: \"MessageSet\" }" + "}", + + "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional " "messages.\n"); } TEST_F(ValidationErrorTest, FieldInMessageSet) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " options { message_set_wire_format: true }" - " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " options { message_set_wire_format: true }" + " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }" + "}", - "foo.proto: Foo.foo: NAME: MessageSets cannot have fields, only " + "foo.proto: Foo.foo: NAME: MessageSets cannot have fields, only " "extensions.\n"); } TEST_F(ValidationErrorTest, NegativeExtensionRangeNumber) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " extension_range { start: -10 end: -1 }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension_range { start: -10 end: -1 }" + "}", - "foo.proto: Foo: NUMBER: Extension numbers must be positive integers.\n"); + "foo.proto: Foo: NUMBER: Extension numbers must be positive integers.\n"); } TEST_F(ValidationErrorTest, HugeExtensionRangeNumber) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " extension_range { start: 1 end: 0x70000000 }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension_range { start: 1 end: 0x70000000 }" + "}", - "foo.proto: Foo: NUMBER: Extension numbers cannot be greater than " + "foo.proto: Foo: NUMBER: Extension numbers cannot be greater than " "536870911.\n"); } TEST_F(ValidationErrorTest, ExtensionRangeEndBeforeStart) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " extension_range { start: 10 end: 10 }" - " extension_range { start: 10 end: 5 }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension_range { start: 10 end: 10 }" + " extension_range { start: 10 end: 5 }" + "}", - "foo.proto: Foo: NUMBER: Extension range end number must be greater than " + "foo.proto: Foo: NUMBER: Extension range end number must be greater than " "start number.\n" - "foo.proto: Foo: NUMBER: Extension range end number must be greater than " + "foo.proto: Foo: NUMBER: Extension range end number must be greater than " "start number.\n"); } TEST_F(ValidationErrorTest, EmptyEnum) { BuildFileWithErrors( - "name: \"foo.proto\" " - "enum_type { name: \"Foo\" }" - // Also use the empty enum in a message to make sure there are no crashes - // during validation (possible if the code attempts to derive a default - // value for the field). - "message_type {" - " name: \"Bar\"" - " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type_name:\"Foo\" }" - " field { name: \"bar\" number: 2 label:LABEL_OPTIONAL type_name:\"Foo\" " - " default_value: \"NO_SUCH_VALUE\" }" - "}", - - "foo.proto: Foo: NAME: Enums must contain at least one value.\n" - "foo.proto: Bar.bar: DEFAULT_VALUE: Enum type \"Foo\" has no value named " + "name: \"foo.proto\" " + "enum_type { name: \"Foo\" }" + // Also use the empty enum in a message to make sure there are no crashes + // during validation (possible if the code attempts to derive a default + // value for the field). + "message_type {" + " name: \"Bar\"" + " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL " + "type_name:\"Foo\" }" + " field { name: \"bar\" number: 2 label:LABEL_OPTIONAL " + "type_name:\"Foo\" " + " default_value: \"NO_SUCH_VALUE\" }" + "}", + + "foo.proto: Foo: NAME: Enums must contain at least one value.\n" + "foo.proto: Bar.bar: DEFAULT_VALUE: Enum type \"Foo\" has no value named " "\"NO_SUCH_VALUE\".\n"); } TEST_F(ValidationErrorTest, UndefinedExtendee) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" - " extendee: \"Bar\" }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" + " extendee: \"Bar\" }" + "}", - "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not defined.\n"); + "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not defined.\n"); } TEST_F(ValidationErrorTest, NonMessageExtendee) { BuildFileWithErrors( - "name: \"foo.proto\" " - "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } }" - "message_type {" - " name: \"Foo\"" - " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" - " extendee: \"Bar\" }" - "}", + "name: \"foo.proto\" " + "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } }" + "message_type {" + " name: \"Foo\"" + " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" + " extendee: \"Bar\" }" + "}", - "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not a message type.\n"); + "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not a message type.\n"); } TEST_F(ValidationErrorTest, NotAnExtensionNumber) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Bar\"" - "}" - "message_type {" - " name: \"Foo\"" - " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" - " extendee: \"Bar\" }" - "}", - - "foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension " + "name: \"foo.proto\" " + "message_type {" + " name: \"Bar\"" + "}" + "message_type {" + " name: \"Foo\"" + " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" + " extendee: \"Bar\" }" + "}", + + "foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension " "number.\n"); } TEST_F(ValidationErrorTest, RequiredExtension) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Bar\"" - " extension_range { start: 1000 end: 10000 }" - "}" - "message_type {" - " name: \"Foo\"" - " extension {" - " name:\"foo\"" - " number:1000" - " label:LABEL_REQUIRED" - " type:TYPE_INT32" - " extendee: \"Bar\"" - " }" - "}", - - "foo.proto: Foo.foo: TYPE: Message extensions cannot have required " - "fields.\n"); + "name: \"foo.proto\" " + "message_type {" + " name: \"Bar\"" + " extension_range { start: 1000 end: 10000 }" + "}" + "message_type {" + " name: \"Foo\"" + " extension {" + " name:\"foo\"" + " number:1000" + " label:LABEL_REQUIRED" + " type:TYPE_INT32" + " extendee: \"Bar\"" + " }" + "}", + + "foo.proto: Foo.foo: TYPE: The extension Foo.foo cannot be required.\n"); } TEST_F(ValidationErrorTest, UndefinedFieldType) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}", - "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n"); + "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n"); } TEST_F(ValidationErrorTest, UndefinedFieldTypeWithDefault) { @@ -4182,42 +4675,42 @@ TEST_F(ValidationErrorTest, UndefinedFieldTypeWithDefault) { // error message. We want this input to yield a validation error instead, // since the unknown type is the primary problem. BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"int\" " - " default_value:\"1\" }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"int\" " + " default_value:\"1\" }" + "}", - "foo.proto: Foo.foo: TYPE: \"int\" is not defined.\n"); + "foo.proto: Foo.foo: TYPE: \"int\" is not defined.\n"); } TEST_F(ValidationErrorTest, UndefinedNestedFieldType) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " nested_type { name:\"Baz\" }" - " field { name:\"foo\" number:1" - " label:LABEL_OPTIONAL" - " type_name:\"Foo.Baz.Bar\" }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " nested_type { name:\"Baz\" }" + " field { name:\"foo\" number:1" + " label:LABEL_OPTIONAL" + " type_name:\"Foo.Baz.Bar\" }" + "}", - "foo.proto: Foo.foo: TYPE: \"Foo.Baz.Bar\" is not defined.\n"); + "foo.proto: Foo.foo: TYPE: \"Foo.Baz.Bar\" is not defined.\n"); } TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) { BuildFile( - "name: \"bar.proto\" " - "message_type { name: \"Bar\" } "); + "name: \"bar.proto\" " + "message_type { name: \"Bar\" } "); BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" - "}", - "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", " + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}", + "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", " "which is not imported by \"foo.proto\". To use it here, please add the " "necessary import.\n"); } @@ -4238,21 +4731,21 @@ TEST_F(ValidationErrorTest, FieldTypeDefinedInIndirectDependency) { // } // BuildFile( - "name: \"bar.proto\" " - "message_type { name: \"Bar\" }"); + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); BuildFile( - "name: \"forward.proto\"" - "dependency: \"bar.proto\""); + "name: \"forward.proto\"" + "dependency: \"bar.proto\""); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"forward.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" - "}", - "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", " + "name: \"foo.proto\" " + "dependency: \"forward.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}", + "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", " "which is not imported by \"foo.proto\". To use it here, please add the " "necessary import.\n"); } @@ -4275,21 +4768,21 @@ TEST_F(ValidationErrorTest, FieldTypeDefinedInPublicDependency) { // } // BuildFile( - "name: \"bar.proto\" " - "message_type { name: \"Bar\" }"); + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); BuildFile( - "name: \"forward.proto\"" - "dependency: \"bar.proto\" " - "public_dependency: 0"); + "name: \"forward.proto\"" + "dependency: \"bar.proto\" " + "public_dependency: 0"); BuildFile( - "name: \"foo.proto\" " - "dependency: \"forward.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" - "}"); + "name: \"foo.proto\" " + "dependency: \"forward.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}"); } TEST_F(ValidationErrorTest, FieldTypeDefinedInTransitivePublicDependency) { @@ -4311,26 +4804,26 @@ TEST_F(ValidationErrorTest, FieldTypeDefinedInTransitivePublicDependency) { // } // BuildFile( - "name: \"bar.proto\" " - "message_type { name: \"Bar\" }"); + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); BuildFile( - "name: \"forward.proto\"" - "dependency: \"bar.proto\" " - "public_dependency: 0"); + "name: \"forward.proto\"" + "dependency: \"bar.proto\" " + "public_dependency: 0"); BuildFile( - "name: \"forward2.proto\"" - "dependency: \"forward.proto\" " - "public_dependency: 0"); + "name: \"forward2.proto\"" + "dependency: \"forward.proto\" " + "public_dependency: 0"); BuildFile( - "name: \"foo.proto\" " - "dependency: \"forward2.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" - "}"); + "name: \"foo.proto\" " + "dependency: \"forward2.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}"); } TEST_F(ValidationErrorTest, @@ -4355,26 +4848,26 @@ TEST_F(ValidationErrorTest, // } // BuildFile( - "name: \"bar.proto\" " - "message_type { name: \"Bar\" }"); + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); BuildFile( - "name: \"forward.proto\"" - "dependency: \"bar.proto\""); + "name: \"forward.proto\"" + "dependency: \"bar.proto\""); BuildFile( - "name: \"forward2.proto\"" - "dependency: \"forward.proto\" " - "public_dependency: 0"); - - BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"forward2.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" - "}", - "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", " + "name: \"forward2.proto\"" + "dependency: \"forward.proto\" " + "public_dependency: 0"); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"forward2.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}", + "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", " "which is not imported by \"foo.proto\". To use it here, please add the " "necessary import.\n"); } @@ -4396,22 +4889,22 @@ TEST_F(ValidationErrorTest, SearchMostLocalFirst) { // fail, and ten try "Bar.Baz" and succeed, even though "Bar" should actually // refer to the inner Bar, not the outer one. BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Bar\"" - " nested_type { name: \"Baz\" }" - "}" - "message_type {" - " name: \"Foo\"" - " nested_type { name: \"Bar\" }" - " field { name:\"baz\" number:1 label:LABEL_OPTIONAL" - " type_name:\"Bar.Baz\" }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Bar\"" + " nested_type { name: \"Baz\" }" + "}" + "message_type {" + " name: \"Foo\"" + " nested_type { name: \"Bar\" }" + " field { name:\"baz\" number:1 label:LABEL_OPTIONAL" + " type_name:\"Bar.Baz\" }" + "}", - "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is resolved to \"Foo.Bar.Baz\"," - " which is not defined. The innermost scope is searched first in name " - "resolution. Consider using a leading '.'(i.e., \".Bar.Baz\") to start " - "from the outermost scope.\n"); + "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is resolved to \"Foo.Bar.Baz\"," + " which is not defined. The innermost scope is searched first in name " + "resolution. Consider using a leading '.'(i.e., \".Bar.Baz\") to start " + "from the outermost scope.\n"); } TEST_F(ValidationErrorTest, SearchMostLocalFirst2) { @@ -4419,17 +4912,17 @@ TEST_F(ValidationErrorTest, SearchMostLocalFirst2) { // proceeds to find the outer one because the inner one's not an // aggregate. BuildFile( - "name: \"foo.proto\" " - "message_type {" - " name: \"Bar\"" - " nested_type { name: \"Baz\" }" - "}" - "message_type {" - " name: \"Foo\"" - " field { name: \"Bar\" number:1 type:TYPE_BYTES } " - " field { name:\"baz\" number:2 label:LABEL_OPTIONAL" - " type_name:\"Bar.Baz\" }" - "}"); + "name: \"foo.proto\" " + "message_type {" + " name: \"Bar\"" + " nested_type { name: \"Baz\" }" + "}" + "message_type {" + " name: \"Foo\"" + " field { name: \"Bar\" number:1 type:TYPE_BYTES } " + " field { name:\"baz\" number:2 label:LABEL_OPTIONAL" + " type_name:\"Bar.Baz\" }" + "}"); } TEST_F(ValidationErrorTest, PackageOriginallyDeclaredInTransitiveDependent) { @@ -4455,353 +4948,352 @@ TEST_F(ValidationErrorTest, PackageOriginallyDeclaredInTransitiveDependent) { // prevent it from finding "foo.bar". BuildFile( - "name: \"foo.proto\" " - "package: \"foo.bar\" "); + "name: \"foo.proto\" " + "package: \"foo.bar\" "); BuildFile( - "name: \"bar.proto\" " - "package: \"foo.bar\" " - "dependency: \"foo.proto\" " - "message_type { name: \"Bar\" }"); + "name: \"bar.proto\" " + "package: \"foo.bar\" " + "dependency: \"foo.proto\" " + "message_type { name: \"Bar\" }"); BuildFile( - "name: \"baz.proto\" " - "package: \"foo\" " - "dependency: \"bar.proto\" " - "message_type { " - " name: \"Baz\" " - " field { name:\"qux\" number:1 label:LABEL_OPTIONAL " - " type_name:\"bar.Bar\" }" - "}"); + "name: \"baz.proto\" " + "package: \"foo\" " + "dependency: \"bar.proto\" " + "message_type { " + " name: \"Baz\" " + " field { name:\"qux\" number:1 label:LABEL_OPTIONAL " + " type_name:\"bar.Bar\" }" + "}"); } TEST_F(ValidationErrorTest, FieldTypeNotAType) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL " - " type_name:\".Foo.bar\" }" - " field { name:\"bar\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL " + " type_name:\".Foo.bar\" }" + " field { name:\"bar\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }" + "}", - "foo.proto: Foo.foo: TYPE: \".Foo.bar\" is not a type.\n"); + "foo.proto: Foo.foo: TYPE: \".Foo.bar\" is not a type.\n"); } TEST_F(ValidationErrorTest, RelativeFieldTypeNotAType) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " nested_type {" - " name: \"Bar\"" - " field { name:\"Baz\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }" - " }" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL " - " type_name:\"Bar.Baz\" }" - "}", - "foo.proto: Foo.foo: TYPE: \"Bar.Baz\" is not a type.\n"); + "name: \"foo.proto\" " + "message_type {" + " nested_type {" + " name: \"Bar\"" + " field { name:\"Baz\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " }" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL " + " type_name:\"Bar.Baz\" }" + "}", + "foo.proto: Foo.foo: TYPE: \"Bar.Baz\" is not a type.\n"); } TEST_F(ValidationErrorTest, FieldTypeMayBeItsName) { BuildFile( - "name: \"foo.proto\" " - "message_type {" - " name: \"Bar\"" - "}" - "message_type {" - " name: \"Foo\"" - " field { name:\"Bar\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" - "}"); + "name: \"foo.proto\" " + "message_type {" + " name: \"Bar\"" + "}" + "message_type {" + " name: \"Foo\"" + " field { name:\"Bar\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}"); } TEST_F(ValidationErrorTest, EnumFieldTypeIsMessage) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type { name: \"Bar\" } " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_ENUM" - " type_name:\"Bar\" }" - "}", + "name: \"foo.proto\" " + "message_type { name: \"Bar\" } " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_ENUM" + " type_name:\"Bar\" }" + "}", - "foo.proto: Foo.foo: TYPE: \"Bar\" is not an enum type.\n"); + "foo.proto: Foo.foo: TYPE: \"Bar\" is not an enum type.\n"); } TEST_F(ValidationErrorTest, MessageFieldTypeIsEnum) { BuildFileWithErrors( - "name: \"foo.proto\" " - "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE" - " type_name:\"Bar\" }" - "}", + "name: \"foo.proto\" " + "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE" + " type_name:\"Bar\" }" + "}", - "foo.proto: Foo.foo: TYPE: \"Bar\" is not a message type.\n"); + "foo.proto: Foo.foo: TYPE: \"Bar\" is not a message type.\n"); } TEST_F(ValidationErrorTest, BadEnumDefaultValue) { BuildFileWithErrors( - "name: \"foo.proto\" " - "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\"" - " default_value:\"NO_SUCH_VALUE\" }" - "}", + "name: \"foo.proto\" " + "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\"" + " default_value:\"NO_SUCH_VALUE\" }" + "}", - "foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named " + "foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named " "\"NO_SUCH_VALUE\".\n"); } TEST_F(ValidationErrorTest, EnumDefaultValueIsInteger) { BuildFileWithErrors( - "name: \"foo.proto\" " - "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\"" - " default_value:\"0\" }" - "}", + "name: \"foo.proto\" " + "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\"" + " default_value:\"0\" }" + "}", - "foo.proto: Foo.foo: DEFAULT_VALUE: Default value for an enum field must " - "be an identifier.\n"); + "foo.proto: Foo.foo: DEFAULT_VALUE: Default value for an enum field must " + "be an identifier.\n"); } TEST_F(ValidationErrorTest, PrimitiveWithTypeName) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" - " type_name:\"Foo\" }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" + " type_name:\"Foo\" }" + "}", - "foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n"); + "foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n"); } TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }" + "}", - "foo.proto: Foo.foo: TYPE: Field with message or enum type missing " + "foo.proto: Foo.foo: TYPE: Field with message or enum type missing " "type_name.\n"); } TEST_F(ValidationErrorTest, OneofWithNoFields) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " oneof_decl { name:\"bar\" }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " oneof_decl { name:\"bar\" }" + "}", - "foo.proto: Foo.bar: NAME: Oneof must have at least one field.\n"); + "foo.proto: Foo.bar: NAME: Oneof must have at least one field.\n"); } TEST_F(ValidationErrorTest, OneofLabelMismatch) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"Foo\"" - " field { name:\"foo\" number:1 label:LABEL_REPEATED type:TYPE_INT32 " - " oneof_index:0 }" - " oneof_decl { name:\"bar\" }" - "}", + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_REPEATED type:TYPE_INT32 " + " oneof_index:0 }" + " oneof_decl { name:\"bar\" }" + "}", - "foo.proto: Foo.foo: NAME: Fields of oneofs must themselves have label " + "foo.proto: Foo.foo: NAME: Fields of oneofs must themselves have label " "LABEL_OPTIONAL.\n"); } TEST_F(ValidationErrorTest, InputTypeNotDefined) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type { name: \"Foo\" } " - "service {" - " name: \"TestService\"" - " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }" - "}", + "name: \"foo.proto\" " + "message_type { name: \"Foo\" } " + "service {" + " name: \"TestService\"" + " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }" + "}", - "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n" - ); + "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n" + ); } TEST_F(ValidationErrorTest, InputTypeNotAMessage) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type { name: \"Foo\" } " - "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " - "service {" - " name: \"TestService\"" - " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }" - "}", + "name: \"foo.proto\" " + "message_type { name: \"Foo\" } " + "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " + "service {" + " name: \"TestService\"" + " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }" + "}", - "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n" - ); + "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n" + ); } TEST_F(ValidationErrorTest, OutputTypeNotDefined) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type { name: \"Foo\" } " - "service {" - " name: \"TestService\"" - " method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }" - "}", + "name: \"foo.proto\" " + "message_type { name: \"Foo\" } " + "service {" + " name: \"TestService\"" + " method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }" + "}", - "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n" - ); + "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n" + ); } TEST_F(ValidationErrorTest, OutputTypeNotAMessage) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type { name: \"Foo\" } " - "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " - "service {" - " name: \"TestService\"" - " method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }" - "}", + "name: \"foo.proto\" " + "message_type { name: \"Foo\" } " + "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " + "service {" + " name: \"TestService\"" + " method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }" + "}", - "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n" - ); + "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n" + ); } TEST_F(ValidationErrorTest, IllegalPackedField) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {\n" - " name: \"Foo\"" - " field { name:\"packed_string\" number:1 label:LABEL_REPEATED " - " type:TYPE_STRING " - " options { uninterpreted_option {" - " name { name_part: \"packed\" is_extension: false }" - " identifier_value: \"true\" }}}\n" - " field { name:\"packed_message\" number:3 label:LABEL_REPEATED " - " type_name: \"Foo\"" - " options { uninterpreted_option {" - " name { name_part: \"packed\" is_extension: false }" - " identifier_value: \"true\" }}}\n" - " field { name:\"optional_int32\" number: 4 label: LABEL_OPTIONAL " - " type:TYPE_INT32 " - " options { uninterpreted_option {" - " name { name_part: \"packed\" is_extension: false }" - " identifier_value: \"true\" }}}\n" - "}", - - "foo.proto: Foo.packed_string: TYPE: [packed = true] can only be " - "specified for repeated primitive fields.\n" - "foo.proto: Foo.packed_message: TYPE: [packed = true] can only be " - "specified for repeated primitive fields.\n" - "foo.proto: Foo.optional_int32: TYPE: [packed = true] can only be " - "specified for repeated primitive fields.\n" - ); + "name: \"foo.proto\" " + "message_type {\n" + " name: \"Foo\"" + " field { name:\"packed_string\" number:1 label:LABEL_REPEATED " + " type:TYPE_STRING " + " options { uninterpreted_option {" + " name { name_part: \"packed\" is_extension: false }" + " identifier_value: \"true\" }}}\n" + " field { name:\"packed_message\" number:3 label:LABEL_REPEATED " + " type_name: \"Foo\"" + " options { uninterpreted_option {" + " name { name_part: \"packed\" is_extension: false }" + " identifier_value: \"true\" }}}\n" + " field { name:\"optional_int32\" number: 4 label: LABEL_OPTIONAL " + " type:TYPE_INT32 " + " options { uninterpreted_option {" + " name { name_part: \"packed\" is_extension: false }" + " identifier_value: \"true\" }}}\n" + "}", + + "foo.proto: Foo.packed_string: TYPE: [packed = true] can only be " + "specified for repeated primitive fields.\n" + "foo.proto: Foo.packed_message: TYPE: [packed = true] can only be " + "specified for repeated primitive fields.\n" + "foo.proto: Foo.optional_int32: TYPE: [packed = true] can only be " + "specified for repeated primitive fields.\n"); } TEST_F(ValidationErrorTest, OptionWrongType) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type { " - " name: \"TestMessage\" " - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING " - " options { uninterpreted_option { name { name_part: \"ctype\" " - " is_extension: false }" - " positive_int_value: 1 }" - " }" - " }" - "}\n", + "name: \"foo.proto\" " + "message_type { " + " name: \"TestMessage\" " + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING " + " options { uninterpreted_option { name { name_part: \"ctype\" " + " is_extension: false }" + " positive_int_value: 1 }" + " }" + " }" + "}\n", - "foo.proto: TestMessage.foo: OPTION_VALUE: Value must be identifier for " - "enum-valued option \"google.protobuf.FieldOptions.ctype\".\n"); + "foo.proto: TestMessage.foo: OPTION_VALUE: Value must be identifier for " + "enum-valued option \"google.protobuf.FieldOptions.ctype\".\n"); } TEST_F(ValidationErrorTest, OptionExtendsAtomicType) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type { " - " name: \"TestMessage\" " - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING " - " options { uninterpreted_option { name { name_part: \"ctype\" " - " is_extension: false }" - " name { name_part: \"foo\" " - " is_extension: true }" - " positive_int_value: 1 }" - " }" - " }" - "}\n", + "name: \"foo.proto\" " + "message_type { " + " name: \"TestMessage\" " + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING " + " options { uninterpreted_option { name { name_part: \"ctype\" " + " is_extension: false }" + " name { name_part: \"foo\" " + " is_extension: true }" + " positive_int_value: 1 }" + " }" + " }" + "}\n", - "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" is an " - "atomic type, not a message.\n"); + "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" is an " + "atomic type, not a message.\n"); } TEST_F(ValidationErrorTest, DupOption) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type { " - " name: \"TestMessage\" " - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_UINT32 " - " options { uninterpreted_option { name { name_part: \"ctype\" " - " is_extension: false }" - " identifier_value: \"CORD\" }" - " uninterpreted_option { name { name_part: \"ctype\" " - " is_extension: false }" - " identifier_value: \"CORD\" }" - " }" - " }" - "}\n", + "name: \"foo.proto\" " + "message_type { " + " name: \"TestMessage\" " + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_UINT32 " + " options { uninterpreted_option { name { name_part: \"ctype\" " + " is_extension: false }" + " identifier_value: \"CORD\" }" + " uninterpreted_option { name { name_part: \"ctype\" " + " is_extension: false }" + " identifier_value: \"CORD\" }" + " }" + " }" + "}\n", - "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" was " - "already set.\n"); + "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" was " + "already set.\n"); } TEST_F(ValidationErrorTest, InvalidOptionName) { BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type { " - " name: \"TestMessage\" " - " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_BOOL " - " options { uninterpreted_option { " - " name { name_part: \"uninterpreted_option\" " - " is_extension: false }" - " positive_int_value: 1 " - " }" - " }" - " }" - "}\n", + "name: \"foo.proto\" " + "message_type { " + " name: \"TestMessage\" " + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_BOOL " + " options { uninterpreted_option { " + " name { name_part: \"uninterpreted_option\" " + " is_extension: false }" + " positive_int_value: 1 " + " }" + " }" + " }" + "}\n", - "foo.proto: TestMessage.foo: OPTION_NAME: Option must not use " - "reserved name \"uninterpreted_option\".\n"); + "foo.proto: TestMessage.foo: OPTION_NAME: Option must not use " + "reserved name \"uninterpreted_option\".\n"); } TEST_F(ValidationErrorTest, RepeatedMessageOption) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "message_type: { name: \"Bar\" field: { " - " name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } " - "} " - "extension { name: \"bar\" number: 7672757 label: LABEL_REPEATED " - " type: TYPE_MESSAGE type_name: \"Bar\" " - " extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"bar\" " - " is_extension: true } " - " name { name_part: \"foo\" " - " is_extension: false } " - " positive_int_value: 1 } }", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "message_type: { name: \"Bar\" field: { " + " name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } " + "} " + "extension { name: \"bar\" number: 7672757 label: LABEL_REPEATED " + " type: TYPE_MESSAGE type_name: \"Bar\" " + " extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"bar\" " + " is_extension: true } " + " name { name_part: \"foo\" " + " is_extension: false } " + " positive_int_value: 1 } }", - "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" is a " - "repeated message. Repeated message options must be initialized " - "using an aggregate value.\n"); + "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" is a " + "repeated message. Repeated message options must be initialized " + "using an aggregate value.\n"); } TEST_F(ValidationErrorTest, ResolveUndefinedOption) { - // The following should produce an eror that baz.bar is resolved but not + // The following should produce an error that baz.bar is resolved but not // defined. // foo.proto: // package baz @@ -4819,313 +5311,338 @@ TEST_F(ValidationErrorTest, ResolveUndefinedOption) { BuildDescriptorMessagesInTestPool(); BuildFile( - "name: \"foo.proto\" " - "package: \"baz\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "message_type: { name: \"Bar\" field: { " - " name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } " - "} " - "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_MESSAGE type_name: \"Bar\" " - " extendee: \"google.protobuf.FileOptions\" }"); - - BuildFileWithErrors( - "name: \"qux.proto\" " - "package: \"qux.baz\" " - "options { uninterpreted_option { name { name_part: \"baz.bar\" " - " is_extension: true } " - " name { name_part: \"foo\" " - " is_extension: false } " - " positive_int_value: 1 } }", - - "qux.proto: qux.proto: OPTION_NAME: Option \"(baz.bar)\" is resolved to " - "\"(qux.baz.bar)\"," - " which is not defined. The innermost scope is searched first in name " - "resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\") to start " - "from the outermost scope.\n"); + "name: \"foo.proto\" " + "package: \"baz\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "message_type: { name: \"Bar\" field: { " + " name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } " + "} " + "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_MESSAGE type_name: \"Bar\" " + " extendee: \"google.protobuf.FileOptions\" }"); + + BuildFileWithErrors( + "name: \"qux.proto\" " + "package: \"qux.baz\" " + "options { uninterpreted_option { name { name_part: \"baz.bar\" " + " is_extension: true } " + " name { name_part: \"foo\" " + " is_extension: false } " + " positive_int_value: 1 } }", + + "qux.proto: qux.proto: OPTION_NAME: Option \"(baz.bar)\" is resolved to " + "\"(qux.baz.bar)\"," + " which is not defined. The innermost scope is searched first in name " + "resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\") to start " + "from the outermost scope.\n"); } TEST_F(ValidationErrorTest, UnknownOption) { BuildFileWithErrors( - "name: \"qux.proto\" " - "package: \"qux.baz\" " - "options { uninterpreted_option { name { name_part: \"baaz.bar\" " - " is_extension: true } " - " name { name_part: \"foo\" " - " is_extension: false } " - " positive_int_value: 1 } }", + "name: \"qux.proto\" " + "package: \"qux.baz\" " + "options { uninterpreted_option { name { name_part: \"baaz.bar\" " + " is_extension: true } " + " name { name_part: \"foo\" " + " is_extension: false } " + " positive_int_value: 1 } }", - "qux.proto: qux.proto: OPTION_NAME: Option \"(baaz.bar)\" unknown.\n"); + "qux.proto: qux.proto: OPTION_NAME: Option \"(baaz.bar)\" unknown. " + "Ensure " + "that your proto definition file imports the proto which defines the " + "option.\n"); } TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo1\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }" - "extension { name: \"foo2\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo1\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }" + "extension { name: \"foo2\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }", - "foo.proto: foo2: NUMBER: Extension number 7672757 has already been used " - "in \"google.protobuf.FieldOptions\" by extension \"foo1\".\n"); + "foo.proto: foo2: NUMBER: Extension number 7672757 has already been used " + "in \"google.protobuf.FieldOptions\" by extension \"foo1\".\n"); } TEST_F(ValidationErrorTest, Int32OptionValueOutOfPositiveRange) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " positive_int_value: 0x80000000 } " - "}", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " positive_int_value: 0x80000000 } " + "}", - "foo.proto: foo.proto: OPTION_VALUE: Value out of range " - "for int32 option \"foo\".\n"); + "foo.proto: foo.proto: OPTION_VALUE: Value out of range " + "for int32 option \"foo\".\n"); } TEST_F(ValidationErrorTest, Int32OptionValueOutOfNegativeRange) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " negative_int_value: -0x80000001 } " - "}", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " negative_int_value: -0x80000001 } " + "}", - "foo.proto: foo.proto: OPTION_VALUE: Value out of range " - "for int32 option \"foo\".\n"); + "foo.proto: foo.proto: OPTION_VALUE: Value out of range " + "for int32 option \"foo\".\n"); } TEST_F(ValidationErrorTest, Int32OptionValueIsNotPositiveInt) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " string_value: \"5\" } }", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " string_value: \"5\" } }", - "foo.proto: foo.proto: OPTION_VALUE: Value must be integer " - "for int32 option \"foo\".\n"); + "foo.proto: foo.proto: OPTION_VALUE: Value must be integer " + "for int32 option \"foo\".\n"); } TEST_F(ValidationErrorTest, Int64OptionValueOutOfRange) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " positive_int_value: 0x8000000000000000 } " - "}", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " positive_int_value: 0x8000000000000000 " + "} " + "}", - "foo.proto: foo.proto: OPTION_VALUE: Value out of range " - "for int64 option \"foo\".\n"); + "foo.proto: foo.proto: OPTION_VALUE: Value out of range " + "for int64 option \"foo\".\n"); } TEST_F(ValidationErrorTest, Int64OptionValueIsNotPositiveInt) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " identifier_value: \"5\" } }", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " identifier_value: \"5\" } }", - "foo.proto: foo.proto: OPTION_VALUE: Value must be integer " - "for int64 option \"foo\".\n"); + "foo.proto: foo.proto: OPTION_VALUE: Value must be integer " + "for int64 option \"foo\".\n"); } TEST_F(ValidationErrorTest, UInt32OptionValueOutOfRange) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " positive_int_value: 0x100000000 } }", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " positive_int_value: 0x100000000 } }", - "foo.proto: foo.proto: OPTION_VALUE: Value out of range " - "for uint32 option \"foo\".\n"); + "foo.proto: foo.proto: OPTION_VALUE: Value out of range " + "for uint32 option \"foo\".\n"); } TEST_F(ValidationErrorTest, UInt32OptionValueIsNotPositiveInt) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " double_value: -5.6 } }", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " double_value: -5.6 } }", - "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer " - "for uint32 option \"foo\".\n"); + "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer " + "for uint32 option \"foo\".\n"); } TEST_F(ValidationErrorTest, UInt64OptionValueIsNotPositiveInt) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_UINT64 extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " negative_int_value: -5 } }", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_UINT64 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " negative_int_value: -5 } }", - "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer " - "for uint64 option \"foo\".\n"); + "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer " + "for uint64 option \"foo\".\n"); } TEST_F(ValidationErrorTest, FloatOptionValueIsNotNumber) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " string_value: \"bar\" } }", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " string_value: \"bar\" } }", - "foo.proto: foo.proto: OPTION_VALUE: Value must be number " - "for float option \"foo\".\n"); + "foo.proto: foo.proto: OPTION_VALUE: Value must be number " + "for float option \"foo\".\n"); } TEST_F(ValidationErrorTest, DoubleOptionValueIsNotNumber) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_DOUBLE extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " string_value: \"bar\" } }", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_DOUBLE extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " string_value: \"bar\" } }", - "foo.proto: foo.proto: OPTION_VALUE: Value must be number " - "for double option \"foo\".\n"); + "foo.proto: foo.proto: OPTION_VALUE: Value must be number " + "for double option \"foo\".\n"); } TEST_F(ValidationErrorTest, BoolOptionValueIsNotTrueOrFalse) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_BOOL extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " identifier_value: \"bar\" } }", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_BOOL extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " identifier_value: \"bar\" } }", - "foo.proto: foo.proto: OPTION_VALUE: Value must be \"true\" or \"false\" " - "for boolean option \"foo\".\n"); + "foo.proto: foo.proto: OPTION_VALUE: Value must be \"true\" or \"false\" " + "for boolean option \"foo\".\n"); } TEST_F(ValidationErrorTest, EnumOptionValueIsNotIdentifier) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } " - " value { name: \"BAZ\" number: 2 } }" - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_ENUM type_name: \"FooEnum\" " - " extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " string_value: \"QUUX\" } }", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } " + " value { name: \"BAZ\" number: 2 } }" + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_ENUM type_name: \"FooEnum\" " + " extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " string_value: \"QUUX\" } }", - "foo.proto: foo.proto: OPTION_VALUE: Value must be identifier for " - "enum-valued option \"foo\".\n"); + "foo.proto: foo.proto: OPTION_VALUE: Value must be identifier for " + "enum-valued option \"foo\".\n"); } TEST_F(ValidationErrorTest, EnumOptionValueIsNotEnumValueName) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } " - " value { name: \"BAZ\" number: 2 } }" - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_ENUM type_name: \"FooEnum\" " - " extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " identifier_value: \"QUUX\" } }", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } " + " value { name: \"BAZ\" number: 2 } }" + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_ENUM type_name: \"FooEnum\" " + " extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " identifier_value: \"QUUX\" } }", - "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum\" has no value " - "named \"QUUX\" for option \"foo\".\n"); + "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum\" has no value " + "named \"QUUX\" for option \"foo\".\n"); } TEST_F(ValidationErrorTest, EnumOptionValueIsSiblingEnumValueName) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "enum_type { name: \"FooEnum1\" value { name: \"BAR\" number: 1 } " - " value { name: \"BAZ\" number: 2 } }" - "enum_type { name: \"FooEnum2\" value { name: \"QUX\" number: 1 } " - " value { name: \"QUUX\" number: 2 } }" - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_ENUM type_name: \"FooEnum1\" " - " extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " identifier_value: \"QUUX\" } }", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "enum_type { name: \"FooEnum1\" value { name: \"BAR\" number: 1 } " + " value { name: \"BAZ\" number: 2 } }" + "enum_type { name: \"FooEnum2\" value { name: \"QUX\" number: 1 } " + " value { name: \"QUUX\" number: 2 } }" + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_ENUM type_name: \"FooEnum1\" " + " extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " identifier_value: \"QUUX\" } }", - "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum1\" has no value " - "named \"QUUX\" for option \"foo\". This appears to be a value from a " - "sibling type.\n"); + "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum1\" has no value " + "named \"QUUX\" for option \"foo\". This appears to be a value from a " + "sibling type.\n"); } TEST_F(ValidationErrorTest, StringOptionValueIsNotString) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_STRING extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " - " is_extension: true } " - " identifier_value: \"QUUX\" } }", + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_STRING extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " identifier_value: \"QUUX\" } }", - "foo.proto: foo.proto: OPTION_VALUE: Value must be quoted string for " - "string option \"foo\".\n"); + "foo.proto: foo.proto: OPTION_VALUE: Value must be quoted string " + "for " + "string option \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, JsonNameOptionOnExtensions) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "package: \"foo\" " + "message_type {" + " name: \"Foo\"" + " extension_range { start: 10 end: 20 }" + "}" + "extension {" + " name: \"value\"" + " number: 10" + " label: LABEL_OPTIONAL" + " type: TYPE_INT32" + " extendee: \"foo.Foo\"" + " json_name: \"myName\"" + "}", + "foo.proto: foo.value: OPTION_NAME: option json_name is not allowed on " + "extension fields.\n"); } TEST_F(ValidationErrorTest, DuplicateExtensionFieldNumber) { @@ -5150,7 +5667,7 @@ TEST_F(ValidationErrorTest, DuplicateExtensionFieldNumber) { // Helper function for tests that check for aggregate value parsing // errors. The "value" argument is embedded inside the // "uninterpreted_option" portion of the result. -static string EmbedAggregateValue(const char* value) { +static std::string EmbedAggregateValue(const char* value) { return strings::Substitute( "name: \"foo.proto\" " "dependency: \"google/protobuf/descriptor.proto\" " @@ -5195,60 +5712,60 @@ TEST_F(ValidationErrorTest, AggregateValueUnknownFields) { TEST_F(ValidationErrorTest, NotLiteImportsLite) { BuildFile( - "name: \"bar.proto\" " - "options { optimize_for: LITE_RUNTIME } "); + "name: \"bar.proto\" " + "options { optimize_for: LITE_RUNTIME } "); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"bar.proto\" ", + "name: \"foo.proto\" " + "dependency: \"bar.proto\" ", - "foo.proto: foo.proto: OTHER: Files that do not use optimize_for = " + "foo.proto: bar.proto: IMPORT: Files that do not use optimize_for = " "LITE_RUNTIME cannot import files which do use this option. This file " "is not lite, but it imports \"bar.proto\" which is.\n"); } TEST_F(ValidationErrorTest, LiteExtendsNotLite) { BuildFile( - "name: \"bar.proto\" " - "message_type: {" - " name: \"Bar\"" - " extension_range { start: 1 end: 1000 }" - "}"); + "name: \"bar.proto\" " + "message_type: {" + " name: \"Bar\"" + " extension_range { start: 1 end: 1000 }" + "}"); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"bar.proto\" " - "options { optimize_for: LITE_RUNTIME } " - "extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL " - " type: TYPE_INT32 extendee: \"Bar\" }", + "name: \"foo.proto\" " + "dependency: \"bar.proto\" " + "options { optimize_for: LITE_RUNTIME } " + "extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"Bar\" }", - "foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be " + "foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be " "declared in non-lite files. Note that you cannot extend a non-lite " "type to contain a lite type, but the reverse is allowed.\n"); } TEST_F(ValidationErrorTest, NoLiteServices) { BuildFileWithErrors( - "name: \"foo.proto\" " - "options {" - " optimize_for: LITE_RUNTIME" - " cc_generic_services: true" - " java_generic_services: true" - "} " - "service { name: \"Foo\" }", + "name: \"foo.proto\" " + "options {" + " optimize_for: LITE_RUNTIME" + " cc_generic_services: true" + " java_generic_services: true" + "} " + "service { name: \"Foo\" }", - "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot " - "define services unless you set both options cc_generic_services and " - "java_generic_sevices to false.\n"); + "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot " + "define services unless you set both options cc_generic_services and " + "java_generic_services to false.\n"); BuildFile( - "name: \"bar.proto\" " - "options {" - " optimize_for: LITE_RUNTIME" - " cc_generic_services: false" - " java_generic_services: false" - "} " - "service { name: \"Bar\" }"); + "name: \"bar.proto\" " + "options {" + " optimize_for: LITE_RUNTIME" + " cc_generic_services: false" + " java_generic_services: false" + "} " + "service { name: \"Bar\" }"); } TEST_F(ValidationErrorTest, RollbackAfterError) { @@ -5257,47 +5774,47 @@ TEST_F(ValidationErrorTest, RollbackAfterError) { // before the undefined type error is noticed. The DescriptorPool will then // have to roll everything back. BuildFileWithErrors( - "name: \"foo.proto\" " - "message_type {" - " name: \"TestMessage\"" - " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }" - "} " - "enum_type {" - " name: \"TestEnum\"" - " value { name:\"BAR\" number:1 }" - "} " - "service {" - " name: \"TestService\"" - " method {" - " name: \"Baz\"" - " input_type: \"NoSuchType\"" // error - " output_type: \"TestMessage\"" - " }" - "}", - - "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n" - ); + "name: \"foo.proto\" " + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }" + "} " + "enum_type {" + " name: \"TestEnum\"" + " value { name:\"BAR\" number:1 }" + "} " + "service {" + " name: \"TestService\"" + " method {" + " name: \"Baz\"" + " input_type: \"NoSuchType\"" // error + " output_type: \"TestMessage\"" + " }" + "}", + + "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n" + ); // Make sure that if we build the same file again with the error fixed, // it works. If the above rollback was incomplete, then some symbols will // be left defined, and this second attempt will fail since it tries to // re-define the same symbols. BuildFile( - "name: \"foo.proto\" " - "message_type {" - " name: \"TestMessage\"" - " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }" - "} " - "enum_type {" - " name: \"TestEnum\"" - " value { name:\"BAR\" number:1 }" - "} " - "service {" - " name: \"TestService\"" - " method { name:\"Baz\"" - " input_type:\"TestMessage\"" - " output_type:\"TestMessage\" }" - "}"); + "name: \"foo.proto\" " + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }" + "} " + "enum_type {" + " name: \"TestEnum\"" + " value { name:\"BAR\" number:1 }" + "} " + "service {" + " name: \"TestService\"" + " method { name:\"Baz\"" + " input_type:\"TestMessage\"" + " output_type:\"TestMessage\" }" + "}"); } TEST_F(ValidationErrorTest, ErrorsReportedToLogError) { @@ -5305,17 +5822,17 @@ TEST_F(ValidationErrorTest, ErrorsReportedToLogError) { // provided. FileDescriptorProto file_proto; - ASSERT_TRUE(TextFormat::ParseFromString( - "name: \"foo.proto\" " - "message_type { name: \"Foo\" } " - "message_type { name: \"Foo\" } ", - &file_proto)); + ASSERT_TRUE( + TextFormat::ParseFromString("name: \"foo.proto\" " + "message_type { name: \"Foo\" } " + "message_type { name: \"Foo\" } ", + &file_proto)); - std::vector errors; + std::vector errors; { ScopedMemoryLog log; - EXPECT_TRUE(pool_.BuildFile(file_proto) == NULL); + EXPECT_TRUE(pool_.BuildFile(file_proto) == nullptr); errors = log.GetMessages(ERROR); } @@ -5327,50 +5844,50 @@ TEST_F(ValidationErrorTest, ErrorsReportedToLogError) { TEST_F(ValidationErrorTest, DisallowEnumAlias) { BuildFileWithErrors( - "name: \"foo.proto\" " - "enum_type {" - " name: \"Bar\"" - " value { name:\"ENUM_A\" number:0 }" - " value { name:\"ENUM_B\" number:0 }" - "}", - "foo.proto: Bar: NUMBER: " - "\"ENUM_B\" uses the same enum value as \"ENUM_A\". " - "If this is intended, set 'option allow_alias = true;' to the enum " - "definition.\n"); + "name: \"foo.proto\" " + "enum_type {" + " name: \"Bar\"" + " value { name:\"ENUM_A\" number:0 }" + " value { name:\"ENUM_B\" number:0 }" + "}", + "foo.proto: Bar: NUMBER: " + "\"ENUM_B\" uses the same enum value as \"ENUM_A\". " + "If this is intended, set 'option allow_alias = true;' to the enum " + "definition.\n"); } TEST_F(ValidationErrorTest, AllowEnumAlias) { BuildFile( - "name: \"foo.proto\" " - "enum_type {" - " name: \"Bar\"" - " value { name:\"ENUM_A\" number:0 }" - " value { name:\"ENUM_B\" number:0 }" - " options { allow_alias: true }" - "}"); + "name: \"foo.proto\" " + "enum_type {" + " name: \"Bar\"" + " value { name:\"ENUM_A\" number:0 }" + " value { name:\"ENUM_B\" number:0 }" + " options { allow_alias: true }" + "}"); } TEST_F(ValidationErrorTest, UnusedImportWarning) { pool_.AddUnusedImportTrackFile("bar.proto"); BuildFile( - "name: \"bar.proto\" " - "message_type { name: \"Bar\" }"); + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); pool_.AddUnusedImportTrackFile("base.proto"); BuildFile( - "name: \"base.proto\" " - "message_type { name: \"Base\" }"); + "name: \"base.proto\" " + "message_type { name: \"Base\" }"); pool_.AddUnusedImportTrackFile("baz.proto"); BuildFile( - "name: \"baz.proto\" " - "message_type { name: \"Baz\" }"); + "name: \"baz.proto\" " + "message_type { name: \"Baz\" }"); pool_.AddUnusedImportTrackFile("public.proto"); BuildFile( - "name: \"public.proto\" " - "dependency: \"bar.proto\"" - "public_dependency: 0"); + "name: \"public.proto\" " + "dependency: \"bar.proto\"" + "public_dependency: 0"); // // forward.proto // import "base.proto" // No warning: Base message is used. @@ -5383,17 +5900,18 @@ TEST_F(ValidationErrorTest, UnusedImportWarning) { // pool_.AddUnusedImportTrackFile("forward.proto"); BuildFileWithWarnings( - "name: \"forward.proto\"" - "dependency: \"base.proto\"" - "dependency: \"bar.proto\"" - "dependency: \"baz.proto\"" - "dependency: \"public.proto\"" - "public_dependency: 2 " - "message_type {" - " name: \"Forward\"" - " field { name:\"base\" number:1 label:LABEL_OPTIONAL type_name:\"Base\" }" - "}", - "forward.proto: bar.proto: OTHER: Import bar.proto but not used.\n"); + "name: \"forward.proto\"" + "dependency: \"base.proto\"" + "dependency: \"bar.proto\"" + "dependency: \"baz.proto\"" + "dependency: \"public.proto\"" + "public_dependency: 2 " + "message_type {" + " name: \"Forward\"" + " field { name:\"base\" number:1 label:LABEL_OPTIONAL " + "type_name:\"Base\" }" + "}", + "forward.proto: bar.proto: IMPORT: Import bar.proto is unused.\n"); } namespace { @@ -5424,7 +5942,7 @@ void FillValidMapEntry(FileDescriptorProto* file_proto) { file_proto)); } static const char* kMapEntryErrorMessage = - "foo.proto: Foo.foo_map: OTHER: map_entry should not be set explicitly. " + "foo.proto: Foo.foo_map: TYPE: map_entry should not be set explicitly. " "Use map instead.\n"; static const char* kMapEntryKeyTypeErrorMessage = "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot be float/double, " @@ -5528,9 +6046,9 @@ TEST_F(ValidationErrorTest, MapEntryDifferentContainingType) { TEST_F(ValidationErrorTest, MapEntryKeyName) { FileDescriptorProto file_proto; FillValidMapEntry(&file_proto); - FieldDescriptorProto* key = file_proto.mutable_message_type(0) - ->mutable_nested_type(0) - ->mutable_field(0); + FieldDescriptorProto* key = + file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field( + 0); key->set_name("Key"); BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); } @@ -5538,9 +6056,9 @@ TEST_F(ValidationErrorTest, MapEntryKeyName) { TEST_F(ValidationErrorTest, MapEntryKeyLabel) { FileDescriptorProto file_proto; FillValidMapEntry(&file_proto); - FieldDescriptorProto* key = file_proto.mutable_message_type(0) - ->mutable_nested_type(0) - ->mutable_field(0); + FieldDescriptorProto* key = + file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field( + 0); key->set_label(FieldDescriptorProto::LABEL_REQUIRED); BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); } @@ -5548,9 +6066,9 @@ TEST_F(ValidationErrorTest, MapEntryKeyLabel) { TEST_F(ValidationErrorTest, MapEntryKeyNumber) { FileDescriptorProto file_proto; FillValidMapEntry(&file_proto); - FieldDescriptorProto* key = file_proto.mutable_message_type(0) - ->mutable_nested_type(0) - ->mutable_field(0); + FieldDescriptorProto* key = + file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field( + 0); key->set_number(3); BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); } @@ -5558,9 +6076,9 @@ TEST_F(ValidationErrorTest, MapEntryKeyNumber) { TEST_F(ValidationErrorTest, MapEntryValueName) { FileDescriptorProto file_proto; FillValidMapEntry(&file_proto); - FieldDescriptorProto* value = file_proto.mutable_message_type(0) - ->mutable_nested_type(0) - ->mutable_field(1); + FieldDescriptorProto* value = + file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field( + 1); value->set_name("Value"); BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); } @@ -5568,9 +6086,9 @@ TEST_F(ValidationErrorTest, MapEntryValueName) { TEST_F(ValidationErrorTest, MapEntryValueLabel) { FileDescriptorProto file_proto; FillValidMapEntry(&file_proto); - FieldDescriptorProto* value = file_proto.mutable_message_type(0) - ->mutable_nested_type(0) - ->mutable_field(1); + FieldDescriptorProto* value = + file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field( + 1); value->set_label(FieldDescriptorProto::LABEL_REQUIRED); BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); } @@ -5578,9 +6096,9 @@ TEST_F(ValidationErrorTest, MapEntryValueLabel) { TEST_F(ValidationErrorTest, MapEntryValueNumber) { FileDescriptorProto file_proto; FillValidMapEntry(&file_proto); - FieldDescriptorProto* value = file_proto.mutable_message_type(0) - ->mutable_nested_type(0) - ->mutable_field(1); + FieldDescriptorProto* value = + file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field( + 1); value->set_number(3); BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); } @@ -5588,9 +6106,9 @@ TEST_F(ValidationErrorTest, MapEntryValueNumber) { TEST_F(ValidationErrorTest, MapEntryKeyTypeFloat) { FileDescriptorProto file_proto; FillValidMapEntry(&file_proto); - FieldDescriptorProto* key = file_proto.mutable_message_type(0) - ->mutable_nested_type(0) - ->mutable_field(0); + FieldDescriptorProto* key = + file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field( + 0); key->set_type(FieldDescriptorProto::TYPE_FLOAT); BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage); } @@ -5598,9 +6116,9 @@ TEST_F(ValidationErrorTest, MapEntryKeyTypeFloat) { TEST_F(ValidationErrorTest, MapEntryKeyTypeDouble) { FileDescriptorProto file_proto; FillValidMapEntry(&file_proto); - FieldDescriptorProto* key = file_proto.mutable_message_type(0) - ->mutable_nested_type(0) - ->mutable_field(0); + FieldDescriptorProto* key = + file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field( + 0); key->set_type(FieldDescriptorProto::TYPE_DOUBLE); BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage); } @@ -5608,9 +6126,9 @@ TEST_F(ValidationErrorTest, MapEntryKeyTypeDouble) { TEST_F(ValidationErrorTest, MapEntryKeyTypeBytes) { FileDescriptorProto file_proto; FillValidMapEntry(&file_proto); - FieldDescriptorProto* key = file_proto.mutable_message_type(0) - ->mutable_nested_type(0) - ->mutable_field(0); + FieldDescriptorProto* key = + file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field( + 0); key->set_type(FieldDescriptorProto::TYPE_BYTES); BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage); } @@ -5618,9 +6136,9 @@ TEST_F(ValidationErrorTest, MapEntryKeyTypeBytes) { TEST_F(ValidationErrorTest, MapEntryKeyTypeEnum) { FileDescriptorProto file_proto; FillValidMapEntry(&file_proto); - FieldDescriptorProto* key = file_proto.mutable_message_type(0) - ->mutable_nested_type(0) - ->mutable_field(0); + FieldDescriptorProto* key = + file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field( + 0); key->clear_type(); key->set_type_name("BarEnum"); EnumDescriptorProto* enum_proto = file_proto.add_enum_type(); @@ -5640,13 +6158,12 @@ TEST_F(ValidationErrorTest, MapEntryKeyTypeEnum) { "be enum types.\n"); } - TEST_F(ValidationErrorTest, MapEntryKeyTypeMessage) { FileDescriptorProto file_proto; FillValidMapEntry(&file_proto); - FieldDescriptorProto* key = file_proto.mutable_message_type(0) - ->mutable_nested_type(0) - ->mutable_field(0); + FieldDescriptorProto* key = + file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field( + 0); key->clear_type(); key->set_type_name(".Bar"); BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage); @@ -5705,6 +6222,34 @@ TEST_F(ValidationErrorTest, MapEntryConflictsWithEnum) { "with an existing enum type.\n"); } +TEST_F(ValidationErrorTest, EnumValuesConflictWithDifferentCasing) { + BuildFileWithErrors( + "syntax: 'proto3'" + "name: 'foo.proto' " + "enum_type {" + " name: 'FooEnum' " + " value { name: 'BAR' number: 0 }" + " value { name: 'bar' number: 1 }" + "}", + "foo.proto: bar: NAME: Enum name bar has the same name as BAR " + "if you ignore case and strip out the enum name prefix (if any). " + "This is error-prone and can lead to undefined behavior. " + "Please avoid doing this. If you are using allow_alias, please assign " + "the same numeric value to both enums.\n"); + + // Not an error because both enums are mapped to the same value. + BuildFile( + "syntax: 'proto3'" + "name: 'foo.proto' " + "enum_type {" + " name: 'FooEnum' " + " options { allow_alias: true }" + " value { name: 'UNKNOWN' number: 0 }" + " value { name: 'BAR' number: 1 }" + " value { name: 'bar' number: 1 }" + "}"); +} + TEST_F(ValidationErrorTest, EnumValuesConflictWhenPrefixesStripped) { BuildFileWithErrors( "syntax: 'proto3'" @@ -5714,9 +6259,11 @@ TEST_F(ValidationErrorTest, EnumValuesConflictWhenPrefixesStripped) { " value { name: 'FOO_ENUM_BAZ' number: 0 }" " value { name: 'BAZ' number: 1 }" "}", - "foo.proto: BAZ: NAME: When enum name is stripped and label is " - "PascalCased (Baz), this value label conflicts with FOO_ENUM_BAZ. This " - "will make the proto fail to compile for some languages, such as C#.\n"); + "foo.proto: BAZ: NAME: Enum name BAZ has the same name as FOO_ENUM_BAZ " + "if you ignore case and strip out the enum name prefix (if any). " + "This is error-prone and can lead to undefined behavior. " + "Please avoid doing this. If you are using allow_alias, please assign " + "the same numeric value to both enums.\n"); BuildFileWithErrors( "syntax: 'proto3'" @@ -5726,9 +6273,11 @@ TEST_F(ValidationErrorTest, EnumValuesConflictWhenPrefixesStripped) { " value { name: 'FOOENUM_BAZ' number: 0 }" " value { name: 'BAZ' number: 1 }" "}", - "foo.proto: BAZ: NAME: When enum name is stripped and label is " - "PascalCased (Baz), this value label conflicts with FOOENUM_BAZ. This " - "will make the proto fail to compile for some languages, such as C#.\n"); + "foo.proto: BAZ: NAME: Enum name BAZ has the same name as FOOENUM_BAZ " + "if you ignore case and strip out the enum name prefix (if any). " + "This is error-prone and can lead to undefined behavior. " + "Please avoid doing this. If you are using allow_alias, please assign " + "the same numeric value to both enums.\n"); BuildFileWithErrors( "syntax: 'proto3'" @@ -5738,10 +6287,11 @@ TEST_F(ValidationErrorTest, EnumValuesConflictWhenPrefixesStripped) { " value { name: 'FOO_ENUM_BAR_BAZ' number: 0 }" " value { name: 'BAR__BAZ' number: 1 }" "}", - "foo.proto: BAR__BAZ: NAME: When enum name is stripped and label is " - "PascalCased (BarBaz), this value label conflicts with " - "FOO_ENUM_BAR_BAZ. This will make the proto fail to compile for some " - "languages, such as C#.\n"); + "foo.proto: BAR__BAZ: NAME: Enum name BAR__BAZ has the same name as " + "FOO_ENUM_BAR_BAZ if you ignore case and strip out the enum name prefix " + "(if any). This is error-prone and can lead to undefined behavior. " + "Please avoid doing this. If you are using allow_alias, please assign " + "the same numeric value to both enums.\n"); BuildFileWithErrors( "syntax: 'proto3'" @@ -5751,10 +6301,11 @@ TEST_F(ValidationErrorTest, EnumValuesConflictWhenPrefixesStripped) { " value { name: 'FOO_ENUM__BAR_BAZ' number: 0 }" " value { name: 'BAR_BAZ' number: 1 }" "}", - "foo.proto: BAR_BAZ: NAME: When enum name is stripped and label is " - "PascalCased (BarBaz), this value label conflicts with " - "FOO_ENUM__BAR_BAZ. This will make the proto fail to compile for some " - "languages, such as C#.\n"); + "foo.proto: BAR_BAZ: NAME: Enum name BAR_BAZ has the same name as " + "FOO_ENUM__BAR_BAZ if you ignore case and strip out the enum name prefix " + "(if any). This is error-prone and can lead to undefined behavior. " + "Please avoid doing this. If you are using allow_alias, please assign " + "the same numeric value to both enums.\n"); // This isn't an error because the underscore will cause the PascalCase to // differ by case (BarBaz vs. Barbaz). @@ -5794,31 +6345,31 @@ TEST_F(ValidationErrorTest, MapEntryConflictsWithOneof) { TEST_F(ValidationErrorTest, MapEntryUsesNoneZeroEnumDefaultValue) { BuildFileWithErrors( - "name: \"foo.proto\" " - "enum_type {" - " name: \"Bar\"" - " value { name:\"ENUM_A\" number:1 }" - " value { name:\"ENUM_B\" number:2 }" - "}" - "message_type {" - " name: 'Foo' " - " field { " - " name: 'foo_map' number: 1 label:LABEL_REPEATED " - " type_name: 'FooMapEntry' " - " } " - " nested_type { " - " name: 'FooMapEntry' " - " options { map_entry: true } " - " field { " - " name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL " - " } " - " field { " - " name: 'value' number: 2 type_name:\"Bar\" label:LABEL_OPTIONAL " - " } " - " } " - "}", - "foo.proto: Foo.foo_map: " - "TYPE: Enum value in map must define 0 as the first value.\n"); + "name: \"foo.proto\" " + "enum_type {" + " name: \"Bar\"" + " value { name:\"ENUM_A\" number:1 }" + " value { name:\"ENUM_B\" number:2 }" + "}" + "message_type {" + " name: 'Foo' " + " field { " + " name: 'foo_map' number: 1 label:LABEL_REPEATED " + " type_name: 'FooMapEntry' " + " } " + " nested_type { " + " name: 'FooMapEntry' " + " options { map_entry: true } " + " field { " + " name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL " + " } " + " field { " + " name: 'value' number: 2 type_name:\"Bar\" label:LABEL_OPTIONAL " + " } " + " } " + "}", + "foo.proto: Foo.foo_map: " + "TYPE: Enum value in map must define 0 as the first value.\n"); } TEST_F(ValidationErrorTest, Proto3RequiredFields) { @@ -5829,7 +6380,7 @@ TEST_F(ValidationErrorTest, Proto3RequiredFields) { " name: 'Foo' " " field { name:'foo' number:1 label:LABEL_REQUIRED type:TYPE_INT32 } " "}", - "foo.proto: Foo.foo: OTHER: Required fields are not allowed in " + "foo.proto: Foo.foo: TYPE: Required fields are not allowed in " "proto3.\n"); // applied to nested types as well. @@ -5843,7 +6394,7 @@ TEST_F(ValidationErrorTest, Proto3RequiredFields) { " field { name:'bar' number:1 label:LABEL_REQUIRED type:TYPE_INT32 } " " } " "}", - "foo.proto: Foo.Bar.bar: OTHER: Required fields are not allowed in " + "foo.proto: Foo.Bar.bar: TYPE: Required fields are not allowed in " "proto3.\n"); // optional and repeated fields are OK. @@ -5866,8 +6417,8 @@ TEST_F(ValidationErrorTest, ValidateProto3DefaultValue) { " field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 " " default_value: '1' }" "}", - "foo.proto: Foo.foo: OTHER: Explicit default values are not allowed in " - "proto3.\n"); + "foo.proto: Foo.foo: DEFAULT_VALUE: Explicit default values are not " + "allowed in proto3.\n"); BuildFileWithErrors( "name: 'foo.proto' " @@ -5880,8 +6431,8 @@ TEST_F(ValidationErrorTest, ValidateProto3DefaultValue) { " default_value: '1' }" " } " "}", - "foo.proto: Foo.Bar.bar: OTHER: Explicit default values are not allowed " - "in proto3.\n"); + "foo.proto: Foo.Bar.bar: DEFAULT_VALUE: Explicit default values are not " + "allowed in proto3.\n"); } TEST_F(ValidationErrorTest, ValidateProto3ExtensionRange) { @@ -5893,7 +6444,7 @@ TEST_F(ValidationErrorTest, ValidateProto3ExtensionRange) { " field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } " " extension_range { start:10 end:100 } " "}", - "foo.proto: Foo: OTHER: Extension ranges are not allowed in " + "foo.proto: Foo: NUMBER: Extension ranges are not allowed in " "proto3.\n"); BuildFileWithErrors( @@ -5907,7 +6458,7 @@ TEST_F(ValidationErrorTest, ValidateProto3ExtensionRange) { " extension_range { start:10 end:100 } " " } " "}", - "foo.proto: Foo.Bar: OTHER: Extension ranges are not allowed in " + "foo.proto: Foo.Bar: NUMBER: Extension ranges are not allowed in " "proto3.\n"); } @@ -5919,7 +6470,7 @@ TEST_F(ValidationErrorTest, ValidateProto3MessageSetWireFormat) { " name: 'Foo' " " options { message_set_wire_format: true } " "}", - "foo.proto: Foo: OTHER: MessageSet is not supported " + "foo.proto: Foo: NAME: MessageSet is not supported " "in proto3.\n"); } @@ -5931,7 +6482,7 @@ TEST_F(ValidationErrorTest, ValidateProto3Enum) { " name: 'FooEnum' " " value { name: 'FOO_FOO' number:1 } " "}", - "foo.proto: FooEnum: OTHER: The first enum value must be " + "foo.proto: FooEnum: NUMBER: The first enum value must be " "zero in proto3.\n"); BuildFileWithErrors( @@ -5944,7 +6495,7 @@ TEST_F(ValidationErrorTest, ValidateProto3Enum) { " value { name: 'FOO_FOO' number:1 } " " } " "}", - "foo.proto: Foo.FooEnum: OTHER: The first enum value must be " + "foo.proto: Foo.FooEnum: NUMBER: The first enum value must be " "zero in proto3.\n"); // valid case. @@ -6006,7 +6557,7 @@ TEST_F(ValidationErrorTest, ValidateProto3Extension) { FileDescriptorProto file_proto; // Add "google/protobuf/descriptor.proto". FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); // Add "foo.proto": // import "google/protobuf/descriptor.proto"; // extend google.protobuf.FieldOptions { @@ -6019,7 +6570,7 @@ TEST_F(ValidationErrorTest, ValidateProto3Extension) { AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000, FieldDescriptorProto::LABEL_OPTIONAL, FieldDescriptorProto::TYPE_INT32); - ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); // Copy and change the package of the descriptor.proto BuildFile( @@ -6036,7 +6587,7 @@ TEST_F(ValidationErrorTest, ValidateProto3Extension) { " name: 'bar' number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 " " extendee: 'Container' " "}", - "bar.proto: bar: OTHER: Extensions in proto3 are only allowed for " + "bar.proto: bar: EXTENDEE: Extensions in proto3 are only allowed for " "defining options.\n"); } @@ -6051,7 +6602,7 @@ TEST_F(ValidationErrorTest, ValidateProto3JsonName) { " field { name:'name' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }" " field { name:'Name' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }" "}", - "foo.proto: Foo: OTHER: The JSON camel-case name of field \"Name\" " + "foo.proto: Foo: NAME: The JSON camel-case name of field \"Name\" " "conflicts with field \"name\". This is not allowed in proto3.\n"); // Underscores are ignored. BuildFileWithErrors( @@ -6062,11 +6613,33 @@ TEST_F(ValidationErrorTest, ValidateProto3JsonName) { " field { name:'ab' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }" " field { name:'_a__b_' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }" "}", - "foo.proto: Foo: OTHER: The JSON camel-case name of field \"_a__b_\" " + "foo.proto: Foo: NAME: The JSON camel-case name of field \"_a__b_\" " "conflicts with field \"ab\". This is not allowed in proto3.\n"); } +TEST_F(ValidationErrorTest, UnusedImportWithOtherError) { + BuildFile( + "name: 'bar.proto' " + "message_type {" + " name: 'Bar'" + "}"); + + pool_.AddUnusedImportTrackFile("foo.proto", true); + BuildFileWithErrors( + "name: 'foo.proto' " + "dependency: 'bar.proto' " + "message_type {" + " name: 'Foo'" + " extension { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32" + " extendee: 'Baz' }" + "}", + + // Should not also contain unused import error. + "foo.proto: Foo.foo: EXTENDEE: \"Baz\" is not defined.\n"); +} + + // =================================================================== // DescriptorDatabase @@ -6084,24 +6657,26 @@ class DatabaseBackedPoolTest : public testing::Test { SimpleDescriptorDatabase database_; virtual void SetUp() { + AddToDatabase( + &database_, + "name: 'foo.proto' " + "message_type { name:'Foo' extension_range { start: 1 end: 100 } } " + "enum_type { name:'TestEnum' value { name:'DUMMY' number:0 } } " + "service { name:'TestService' } "); AddToDatabase(&database_, - "name: 'foo.proto' " - "message_type { name:'Foo' extension_range { start: 1 end: 100 } } " - "enum_type { name:'TestEnum' value { name:'DUMMY' number:0 } } " - "service { name:'TestService' } "); - AddToDatabase(&database_, - "name: 'bar.proto' " - "dependency: 'foo.proto' " - "message_type { name:'Bar' } " - "extension { name:'foo_ext' extendee: '.Foo' number:5 " - " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + "name: 'bar.proto' " + "dependency: 'foo.proto' " + "message_type { name:'Bar' } " + "extension { name:'foo_ext' extendee: '.Foo' number:5 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } "); // Baz has an undeclared dependency on Foo. - AddToDatabase(&database_, - "name: 'baz.proto' " - "message_type { " - " name:'Baz' " - " field { name:'foo' number:1 label:LABEL_OPTIONAL type_name:'Foo' } " - "}"); + AddToDatabase( + &database_, + "name: 'baz.proto' " + "message_type { " + " name:'Baz' " + " field { name:'foo' number:1 label:LABEL_OPTIONAL type_name:'Foo' } " + "}"); } // We can't inject a file containing errors into a DescriptorPool, so we @@ -6112,7 +6687,7 @@ class DatabaseBackedPoolTest : public testing::Test { ~ErrorDescriptorDatabase() {} // implements DescriptorDatabase --------------------------------- - bool FindFileByName(const string& filename, + bool FindFileByName(const std::string& filename, FileDescriptorProto* output) { // error.proto and error2.proto cyclically import each other. if (filename == "error.proto") { @@ -6129,11 +6704,11 @@ class DatabaseBackedPoolTest : public testing::Test { return false; } } - bool FindFileContainingSymbol(const string& symbol_name, + bool FindFileContainingSymbol(const std::string& symbol_name, FileDescriptorProto* output) { return false; } - bool FindFileContainingExtension(const string& containing_type, + bool FindFileContainingExtension(const std::string& containing_type, int field_number, FileDescriptorProto* output) { return false; @@ -6145,7 +6720,7 @@ class DatabaseBackedPoolTest : public testing::Test { class CallCountingDatabase : public DescriptorDatabase { public: CallCountingDatabase(DescriptorDatabase* wrapped_db) - : wrapped_db_(wrapped_db) { + : wrapped_db_(wrapped_db) { Clear(); } ~CallCountingDatabase() {} @@ -6154,27 +6729,25 @@ class DatabaseBackedPoolTest : public testing::Test { int call_count_; - void Clear() { - call_count_ = 0; - } + void Clear() { call_count_ = 0; } // implements DescriptorDatabase --------------------------------- - bool FindFileByName(const string& filename, + bool FindFileByName(const std::string& filename, FileDescriptorProto* output) { ++call_count_; return wrapped_db_->FindFileByName(filename, output); } - bool FindFileContainingSymbol(const string& symbol_name, + bool FindFileContainingSymbol(const std::string& symbol_name, FileDescriptorProto* output) { ++call_count_; return wrapped_db_->FindFileContainingSymbol(symbol_name, output); } - bool FindFileContainingExtension(const string& containing_type, + bool FindFileContainingExtension(const std::string& containing_type, int field_number, FileDescriptorProto* output) { ++call_count_; - return wrapped_db_->FindFileContainingExtension( - containing_type, field_number, output); + return wrapped_db_->FindFileContainingExtension(containing_type, + field_number, output); } }; @@ -6184,21 +6757,21 @@ class DatabaseBackedPoolTest : public testing::Test { class FalsePositiveDatabase : public DescriptorDatabase { public: FalsePositiveDatabase(DescriptorDatabase* wrapped_db) - : wrapped_db_(wrapped_db) {} + : wrapped_db_(wrapped_db) {} ~FalsePositiveDatabase() {} DescriptorDatabase* wrapped_db_; // implements DescriptorDatabase --------------------------------- - bool FindFileByName(const string& filename, + bool FindFileByName(const std::string& filename, FileDescriptorProto* output) { return wrapped_db_->FindFileByName(filename, output); } - bool FindFileContainingSymbol(const string& symbol_name, + bool FindFileContainingSymbol(const std::string& symbol_name, FileDescriptorProto* output) { return FindFileByName("foo.proto", output); } - bool FindFileContainingExtension(const string& containing_type, + bool FindFileContainingExtension(const std::string& containing_type, int field_number, FileDescriptorProto* output) { return FindFileByName("foo.proto", output); @@ -6210,27 +6783,27 @@ TEST_F(DatabaseBackedPoolTest, FindFileByName) { DescriptorPool pool(&database_); const FileDescriptor* foo = pool.FindFileByName("foo.proto"); - ASSERT_TRUE(foo != NULL); + ASSERT_TRUE(foo != nullptr); EXPECT_EQ("foo.proto", foo->name()); ASSERT_EQ(1, foo->message_type_count()); EXPECT_EQ("Foo", foo->message_type(0)->name()); EXPECT_EQ(foo, pool.FindFileByName("foo.proto")); - EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == NULL); + EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == nullptr); } TEST_F(DatabaseBackedPoolTest, FindDependencyBeforeDependent) { DescriptorPool pool(&database_); const FileDescriptor* foo = pool.FindFileByName("foo.proto"); - ASSERT_TRUE(foo != NULL); + ASSERT_TRUE(foo != nullptr); EXPECT_EQ("foo.proto", foo->name()); ASSERT_EQ(1, foo->message_type_count()); EXPECT_EQ("Foo", foo->message_type(0)->name()); const FileDescriptor* bar = pool.FindFileByName("bar.proto"); - ASSERT_TRUE(bar != NULL); + ASSERT_TRUE(bar != nullptr); EXPECT_EQ("bar.proto", bar->name()); ASSERT_EQ(1, bar->message_type_count()); EXPECT_EQ("Bar", bar->message_type(0)->name()); @@ -6243,13 +6816,13 @@ TEST_F(DatabaseBackedPoolTest, FindDependentBeforeDependency) { DescriptorPool pool(&database_); const FileDescriptor* bar = pool.FindFileByName("bar.proto"); - ASSERT_TRUE(bar != NULL); + ASSERT_TRUE(bar != nullptr); EXPECT_EQ("bar.proto", bar->name()); ASSERT_EQ(1, bar->message_type_count()); ASSERT_EQ("Bar", bar->message_type(0)->name()); const FileDescriptor* foo = pool.FindFileByName("foo.proto"); - ASSERT_TRUE(foo != NULL); + ASSERT_TRUE(foo != nullptr); EXPECT_EQ("foo.proto", foo->name()); ASSERT_EQ(1, foo->message_type_count()); ASSERT_EQ("Foo", foo->message_type(0)->name()); @@ -6262,36 +6835,36 @@ TEST_F(DatabaseBackedPoolTest, FindFileContainingSymbol) { DescriptorPool pool(&database_); const FileDescriptor* file = pool.FindFileContainingSymbol("Foo"); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); EXPECT_EQ("foo.proto", file->name()); EXPECT_EQ(file, pool.FindFileByName("foo.proto")); - EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == NULL); + EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == nullptr); } TEST_F(DatabaseBackedPoolTest, FindMessageTypeByName) { DescriptorPool pool(&database_); const Descriptor* type = pool.FindMessageTypeByName("Foo"); - ASSERT_TRUE(type != NULL); + ASSERT_TRUE(type != nullptr); EXPECT_EQ("Foo", type->name()); EXPECT_EQ(type->file(), pool.FindFileByName("foo.proto")); - EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == NULL); + EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == nullptr); } TEST_F(DatabaseBackedPoolTest, FindExtensionByNumber) { DescriptorPool pool(&database_); const Descriptor* foo = pool.FindMessageTypeByName("Foo"); - ASSERT_TRUE(foo != NULL); + ASSERT_TRUE(foo != nullptr); const FieldDescriptor* extension = pool.FindExtensionByNumber(foo, 5); - ASSERT_TRUE(extension != NULL); + ASSERT_TRUE(extension != nullptr); EXPECT_EQ("foo_ext", extension->name()); EXPECT_EQ(extension->file(), pool.FindFileByName("bar.proto")); - EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == NULL); + EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == nullptr); } TEST_F(DatabaseBackedPoolTest, FindAllExtensions) { @@ -6313,11 +6886,11 @@ TEST_F(DatabaseBackedPoolTest, ErrorWithoutErrorCollector) { ErrorDescriptorDatabase error_database; DescriptorPool pool(&error_database); - std::vector errors; + std::vector errors; { ScopedMemoryLog log; - EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL); + EXPECT_TRUE(pool.FindFileByName("error.proto") == nullptr); errors = log.GetMessages(ERROR); } @@ -6329,15 +6902,15 @@ TEST_F(DatabaseBackedPoolTest, ErrorWithErrorCollector) { MockErrorCollector error_collector; DescriptorPool pool(&error_database, &error_collector); - EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL); + EXPECT_TRUE(pool.FindFileByName("error.proto") == nullptr); EXPECT_EQ( - "error.proto: error.proto: OTHER: File recursively imports itself: " + "error.proto: error2.proto: IMPORT: File recursively imports itself: " "error.proto -> error2.proto -> error.proto\n" - "error2.proto: error2.proto: OTHER: Import \"error.proto\" was not " + "error2.proto: error.proto: IMPORT: Import \"error.proto\" was not " "found or had errors.\n" - "error.proto: error.proto: OTHER: Import \"error2.proto\" was not " + "error.proto: error2.proto: IMPORT: Import \"error2.proto\" was not " "found or had errors.\n", - error_collector.text_); + error_collector.text_); } TEST_F(DatabaseBackedPoolTest, UndeclaredDependencyOnUnbuiltType) { @@ -6345,12 +6918,12 @@ TEST_F(DatabaseBackedPoolTest, UndeclaredDependencyOnUnbuiltType) { // in the descriptor database but that have not not been built yet. MockErrorCollector error_collector; DescriptorPool pool(&database_, &error_collector); - EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL); + EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == nullptr); EXPECT_EQ( - "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", " - "which is not imported by \"baz.proto\". To use it here, please add " - "the necessary import.\n", - error_collector.text_); + "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", " + "which is not imported by \"baz.proto\". To use it here, please add " + "the necessary import.\n", + error_collector.text_); } TEST_F(DatabaseBackedPoolTest, RollbackAfterError) { @@ -6361,25 +6934,25 @@ TEST_F(DatabaseBackedPoolTest, RollbackAfterError) { // Baz is defined in the database, but the file is invalid because it is // missing a necessary import. DescriptorPool pool(&database_); - EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL); + EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == nullptr); // Make sure that searching again for the file or the type fails. - EXPECT_TRUE(pool.FindFileByName("baz.proto") == NULL); - EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL); + EXPECT_TRUE(pool.FindFileByName("baz.proto") == nullptr); + EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == nullptr); } TEST_F(DatabaseBackedPoolTest, UnittestProto) { // Try to load all of unittest.proto from a DescriptorDatabase. This should // thoroughly test all paths through DescriptorBuilder to insure that there - // are no deadlocking problems when pool_->mutex_ is non-NULL. + // are no deadlocking problems when pool_->mutex_ is non-null. const FileDescriptor* original_file = - protobuf_unittest::TestAllTypes::descriptor()->file(); + protobuf_unittest::TestAllTypes::descriptor()->file(); DescriptorPoolDatabase database(*DescriptorPool::generated_pool()); DescriptorPool pool(&database); const FileDescriptor* file_from_database = - pool.FindFileByName(original_file->name()); + pool.FindFileByName(original_file->name()); - ASSERT_TRUE(file_from_database != NULL); + ASSERT_TRUE(file_from_database != nullptr); FileDescriptorProto original_file_proto; original_file->CopyTo(&original_file_proto); @@ -6391,8 +6964,7 @@ TEST_F(DatabaseBackedPoolTest, UnittestProto) { file_from_database_proto.DebugString()); // Also verify that CopyTo() did not omit any information. - EXPECT_EQ(original_file->DebugString(), - file_from_database->DebugString()); + EXPECT_EQ(original_file->DebugString(), file_from_database->DebugString()); } TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) { @@ -6403,39 +6975,39 @@ TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) { DescriptorPool pool(&call_counter); const FileDescriptor* file = pool.FindFileByName("foo.proto"); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); const Descriptor* foo = pool.FindMessageTypeByName("Foo"); - ASSERT_TRUE(foo != NULL); + ASSERT_TRUE(foo != nullptr); const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum"); - ASSERT_TRUE(test_enum != NULL); + ASSERT_TRUE(test_enum != nullptr); const ServiceDescriptor* test_service = pool.FindServiceByName("TestService"); - ASSERT_TRUE(test_service != NULL); + ASSERT_TRUE(test_service != nullptr); EXPECT_NE(0, call_counter.call_count_); call_counter.Clear(); - EXPECT_TRUE(foo->FindFieldByName("no_such_field") == NULL); - EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == NULL); - EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == NULL); - EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == NULL); - EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == NULL); - EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == NULL); - EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == NULL); - - EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == NULL); - EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == NULL); - EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == NULL); - EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == NULL); - EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == NULL); - - EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == NULL); - EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == NULL); - EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == NULL); - EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == NULL); - EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == NULL); - EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == NULL); - EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == NULL); - EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == NULL); + EXPECT_TRUE(foo->FindFieldByName("no_such_field") == nullptr); + EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == nullptr); + EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == nullptr); + EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == nullptr); + EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == nullptr); + EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == nullptr); + EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == nullptr); + + EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == nullptr); + EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == nullptr); + EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == nullptr); + EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == nullptr); + EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == nullptr); + + EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == nullptr); + EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == nullptr); + EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == nullptr); + EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == nullptr); + EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == nullptr); + EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == nullptr); + EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == nullptr); + EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == nullptr); EXPECT_EQ(0, call_counter.call_count_); } @@ -6450,11 +7022,11 @@ TEST_F(DatabaseBackedPoolTest, DoesntReloadFilesUncesessarily) { // First make sure foo.proto is loaded. const Descriptor* foo = pool.FindMessageTypeByName("Foo"); - ASSERT_TRUE(foo != NULL); + ASSERT_TRUE(foo != nullptr); // Try inducing false positives. - EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == NULL); - EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == NULL); + EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == nullptr); + EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == nullptr); // No errors should have been reported. (If foo.proto was incorrectly // loaded multiple times, errors would have been reported.) @@ -6476,7 +7048,7 @@ class ExponentialErrorDatabase : public DescriptorDatabase { ~ExponentialErrorDatabase() {} // implements DescriptorDatabase --------------------------------- - bool FindFileByName(const string& filename, + bool FindFileByName(const std::string& filename, FileDescriptorProto* output) { int file_num = -1; FullMatch(filename, "file", ".proto", &file_num); @@ -6486,7 +7058,7 @@ class ExponentialErrorDatabase : public DescriptorDatabase { return false; } } - bool FindFileContainingSymbol(const string& symbol_name, + bool FindFileContainingSymbol(const std::string& symbol_name, FileDescriptorProto* output) { int file_num = -1; FullMatch(symbol_name, "Message", "", &file_num); @@ -6496,44 +7068,41 @@ class ExponentialErrorDatabase : public DescriptorDatabase { return false; } } - bool FindFileContainingExtension(const string& containing_type, + bool FindFileContainingExtension(const std::string& containing_type, int field_number, FileDescriptorProto* output) { return false; } private: - void FullMatch(const string& name, - const string& begin_with, - const string& end_with, - int* file_num) { + void FullMatch(const std::string& name, const std::string& begin_with, + const std::string& end_with, int* file_num) { int begin_size = begin_with.size(); int end_size = end_with.size(); if (name.substr(0, begin_size) != begin_with || - name.substr(name.size()- end_size, end_size) != end_with) { + name.substr(name.size() - end_size, end_size) != end_with) { return; } - safe_strto32(name.substr(begin_size, name.size() - end_size - begin_size), - file_num); + safe_strto32( + name.substr(begin_size, name.size() - end_size - begin_size), file_num); } bool PopulateFile(int file_num, FileDescriptorProto* output) { - using strings::Substitute; GOOGLE_CHECK_GE(file_num, 0); output->Clear(); - output->set_name(Substitute("file$0.proto", file_num)); + output->set_name(strings::Substitute("file$0.proto", file_num)); // file0.proto doesn't define Message0 if (file_num > 0) { DescriptorProto* message = output->add_message_type(); - message->set_name(Substitute("Message$0", file_num)); + message->set_name(strings::Substitute("Message$0", file_num)); for (int i = 0; i < file_num; ++i) { - output->add_dependency(Substitute("file$0.proto", i)); + output->add_dependency(strings::Substitute("file$0.proto", i)); FieldDescriptorProto* field = message->add_field(); - field->set_name(Substitute("field$0", i)); + field->set_name(strings::Substitute("field$0", i)); field->set_number(i); field->set_label(FieldDescriptorProto::LABEL_OPTIONAL); field->set_type(FieldDescriptorProto::TYPE_MESSAGE); - field->set_type_name(Substitute("Message$0", i)); + field->set_type_name(strings::Substitute("Message$0", i)); } } return true; @@ -6546,8 +7115,8 @@ TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) { GOOGLE_LOG(INFO) << "A timeout in this test probably indicates a real bug."; - EXPECT_TRUE(pool.FindFileByName("file40.proto") == NULL); - EXPECT_TRUE(pool.FindMessageTypeByName("Message40") == NULL); + EXPECT_TRUE(pool.FindFileByName("file40.proto") == nullptr); + EXPECT_TRUE(pool.FindMessageTypeByName("Message40") == nullptr); } TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) { @@ -6558,22 +7127,22 @@ TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) { DescriptorPool pool(&call_counter); const FileDescriptor* file = pool.FindFileByName("foo.proto"); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); const Descriptor* foo = pool.FindMessageTypeByName("Foo"); - ASSERT_TRUE(foo != NULL); + ASSERT_TRUE(foo != nullptr); const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum"); - ASSERT_TRUE(test_enum != NULL); + ASSERT_TRUE(test_enum != nullptr); EXPECT_NE(0, call_counter.call_count_); call_counter.Clear(); - EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == NULL); - EXPECT_TRUE(pool.FindFieldByName("Foo") == NULL); - EXPECT_TRUE(pool.FindExtensionByName("Foo") == NULL); - EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == NULL); - EXPECT_TRUE(pool.FindEnumValueByName("Foo") == NULL); - EXPECT_TRUE(pool.FindServiceByName("Foo") == NULL); - EXPECT_TRUE(pool.FindMethodByName("Foo") == NULL); + EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == nullptr); + EXPECT_TRUE(pool.FindFieldByName("Foo") == nullptr); + EXPECT_TRUE(pool.FindExtensionByName("Foo") == nullptr); + EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == nullptr); + EXPECT_TRUE(pool.FindEnumValueByName("Foo") == nullptr); + EXPECT_TRUE(pool.FindServiceByName("Foo") == nullptr); + EXPECT_TRUE(pool.FindMethodByName("Foo") == nullptr); EXPECT_EQ(0, call_counter.call_count_); } @@ -6584,15 +7153,14 @@ class AbortingErrorCollector : public DescriptorPool::ErrorCollector { public: AbortingErrorCollector() {} - virtual void AddError( - const string &filename, - const string &element_name, - const Message *message, - ErrorLocation location, - const string &error_message) { + virtual void AddError(const std::string& filename, + const std::string& element_name, const Message* message, + ErrorLocation location, + const std::string& error_message) { GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << " [" << element_name << "]: " << error_message; } + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector); }; @@ -6600,73 +7168,134 @@ class AbortingErrorCollector : public DescriptorPool::ErrorCollector { // A source tree containing only one file. class SingletonSourceTree : public compiler::SourceTree { public: - SingletonSourceTree(const string& filename, const string& contents) + SingletonSourceTree(const std::string& filename, const std::string& contents) : filename_(filename), contents_(contents) {} - virtual io::ZeroCopyInputStream* Open(const string& filename) { - return filename == filename_ ? - new io::ArrayInputStream(contents_.data(), contents_.size()) : NULL; + virtual io::ZeroCopyInputStream* Open(const std::string& filename) { + return filename == filename_ + ? new io::ArrayInputStream(contents_.data(), contents_.size()) + : nullptr; } private: - const string filename_; - const string contents_; + const std::string filename_; + const std::string contents_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree); }; -const char *const kSourceLocationTestInput = - "syntax = \"proto2\";\n" - "message A {\n" - " optional int32 a = 1;\n" - " message B {\n" - " required double b = 1;\n" - " }\n" - "}\n" - "enum Indecision {\n" - " YES = 1;\n" - " NO = 2;\n" - " MAYBE = 3;\n" - "}\n" - "service S {\n" - " rpc Method(A) returns (A.B);\n" - // Put an empty line here to make the source location range match. - "\n" - "}\n" - "message MessageWithExtensions {\n" - " extensions 1000 to max;\n" - "}\n" - "extend MessageWithExtensions {\n" - " optional int32 int32_extension = 1001;\n" - "}\n" - "message C {\n" - " extend MessageWithExtensions {\n" - " optional C message_extension = 1002;\n" - " }\n" - "}\n"; +const char* const kSourceLocationTestInput = + "syntax = \"proto2\";\n" + "option java_package = \"com.foo.bar\";\n" + "option (test_file_opt) = \"foobar\";\n" + "message A {\n" + " option (test_msg_opt) = \"foobar\";\n" + " optional int32 a = 1 [deprecated = true];\n" + " message B {\n" + " required double b = 1 [(test_field_opt) = \"foobar\"];\n" + " }\n" + " oneof c {\n" + " option (test_oneof_opt) = \"foobar\";\n" + " string d = 2;\n" + " string e = 3;\n" + " string f = 4;\n" + " }\n" + "}\n" + "enum Indecision {\n" + " option (test_enum_opt) = 21;\n" + " option (test_enum_opt) = 42;\n" + " option (test_enum_opt) = 63;\n" + " YES = 1 [(test_enumval_opt).a = 100];\n" + " NO = 2 [(test_enumval_opt) = {a:200}];\n" + " MAYBE = 3;\n" + "}\n" + "service S {\n" + " option (test_svc_opt) = {a:100};\n" + " option (test_svc_opt) = {a:200};\n" + " option (test_svc_opt) = {a:300};\n" + " rpc Method(A) returns (A.B);\n" + // Put an empty line here to make the source location range match. + "\n" + " rpc OtherMethod(A) returns (A) {\n" + " option deprecated = true;\n" + " option (test_method_opt) = \"foobar\";\n" + " }\n" + "}\n" + "message MessageWithExtensions {\n" + " extensions 1000 to 2000, 2001 to max [(test_ext_opt) = \"foobar\"];\n" + "}\n" + "extend MessageWithExtensions {\n" + " repeated int32 int32_extension = 1001 [packed=true];\n" + "}\n" + "message C {\n" + " extend MessageWithExtensions {\n" + " optional C message_extension = 1002;\n" + " }\n" + "}\n" + "import \"google/protobuf/descriptor.proto\";\n" + "extend google.protobuf.FileOptions {\n" + " optional string test_file_opt = 10101;\n" + "}\n" + "extend google.protobuf.MessageOptions {\n" + " optional string test_msg_opt = 10101;\n" + "}\n" + "extend google.protobuf.FieldOptions {\n" + " optional string test_field_opt = 10101;\n" + "}\n" + "extend google.protobuf.EnumOptions {\n" + " repeated int32 test_enum_opt = 10101;\n" + "}\n" + "extend google.protobuf.EnumValueOptions {\n" + " optional A test_enumval_opt = 10101;\n" + "}\n" + "extend google.protobuf.ServiceOptions {\n" + " repeated A test_svc_opt = 10101;\n" + "}\n" + "extend google.protobuf.MethodOptions {\n" + " optional string test_method_opt = 10101;\n" + "}\n" + "extend google.protobuf.OneofOptions {\n" + " optional string test_oneof_opt = 10101;\n" + "}\n" + "extend google.protobuf.ExtensionRangeOptions {\n" + " optional string test_ext_opt = 10101;\n" + "}\n"; class SourceLocationTest : public testing::Test { public: SourceLocationTest() : source_tree_("/test/test.proto", kSourceLocationTestInput), - db_(&source_tree_), - pool_(&db_, &collector_) {} + simple_db_(), + source_tree_db_(&source_tree_), + merged_db_(&simple_db_, &source_tree_db_), + pool_(&merged_db_, &collector_) { + // we need descriptor.proto to be accessible by the pool + // since our test file imports it + FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto_); + simple_db_.Add(file_proto_); + } - static string PrintSourceLocation(const SourceLocation &loc) { - return strings::Substitute("$0:$1-$2:$3", - 1 + loc.start_line, - 1 + loc.start_column, - 1 + loc.end_line, - 1 + loc.end_column); + static std::string PrintSourceLocation(const SourceLocation& loc) { + return strings::Substitute("$0:$1-$2:$3", 1 + loc.start_line, + 1 + loc.start_column, 1 + loc.end_line, + 1 + loc.end_column); } private: + FileDescriptorProto file_proto_; AbortingErrorCollector collector_; SingletonSourceTree source_tree_; - compiler::SourceTreeDescriptorDatabase db_; + SimpleDescriptorDatabase simple_db_; // contains descriptor.proto + compiler::SourceTreeDescriptorDatabase source_tree_db_; // loads test.proto + MergedDescriptorDatabase merged_db_; // combines above two dbs protected: DescriptorPool pool_; + + // tag number of all custom options in above test file + static constexpr int kCustomOptionFieldNumber = 10101; + // tag number of field "a" in message type "A" in above test file + static constexpr int kAFieldNumber = 1; }; // TODO(adonovan): implement support for option fields and for @@ -6675,61 +7304,429 @@ class SourceLocationTest : public testing::Test { TEST_F(SourceLocationTest, GetSourceLocation) { SourceLocation loc; - const FileDescriptor *file_desc = + const FileDescriptor* file_desc = GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); - const Descriptor *a_desc = file_desc->FindMessageTypeByName("A"); + const Descriptor* a_desc = file_desc->FindMessageTypeByName("A"); EXPECT_TRUE(a_desc->GetSourceLocation(&loc)); - EXPECT_EQ("2:1-7:2", PrintSourceLocation(loc)); + EXPECT_EQ("4:1-16:2", PrintSourceLocation(loc)); - const Descriptor *a_b_desc = a_desc->FindNestedTypeByName("B"); + const Descriptor* a_b_desc = a_desc->FindNestedTypeByName("B"); EXPECT_TRUE(a_b_desc->GetSourceLocation(&loc)); - EXPECT_EQ("4:3-6:4", PrintSourceLocation(loc)); + EXPECT_EQ("7:3-9:4", PrintSourceLocation(loc)); - const EnumDescriptor *e_desc = file_desc->FindEnumTypeByName("Indecision"); + const EnumDescriptor* e_desc = file_desc->FindEnumTypeByName("Indecision"); EXPECT_TRUE(e_desc->GetSourceLocation(&loc)); - EXPECT_EQ("8:1-12:2", PrintSourceLocation(loc)); + EXPECT_EQ("17:1-24:2", PrintSourceLocation(loc)); - const EnumValueDescriptor *yes_desc = e_desc->FindValueByName("YES"); + const EnumValueDescriptor* yes_desc = e_desc->FindValueByName("YES"); EXPECT_TRUE(yes_desc->GetSourceLocation(&loc)); - EXPECT_EQ("9:3-9:13", PrintSourceLocation(loc)); + EXPECT_EQ("21:3-21:42", PrintSourceLocation(loc)); - const ServiceDescriptor *s_desc = file_desc->FindServiceByName("S"); + const ServiceDescriptor* s_desc = file_desc->FindServiceByName("S"); EXPECT_TRUE(s_desc->GetSourceLocation(&loc)); - EXPECT_EQ("13:1-16:2", PrintSourceLocation(loc)); + EXPECT_EQ("25:1-35:2", PrintSourceLocation(loc)); - const MethodDescriptor *m_desc = s_desc->FindMethodByName("Method"); + const MethodDescriptor* m_desc = s_desc->FindMethodByName("Method"); EXPECT_TRUE(m_desc->GetSourceLocation(&loc)); - EXPECT_EQ("14:3-14:31", PrintSourceLocation(loc)); + EXPECT_EQ("29:3-29:31", PrintSourceLocation(loc)); } TEST_F(SourceLocationTest, ExtensionSourceLocation) { SourceLocation loc; - const FileDescriptor *file_desc = + const FileDescriptor* file_desc = GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); - const FieldDescriptor *int32_extension_desc = + const FieldDescriptor* int32_extension_desc = file_desc->FindExtensionByName("int32_extension"); EXPECT_TRUE(int32_extension_desc->GetSourceLocation(&loc)); - EXPECT_EQ("21:3-21:41", PrintSourceLocation(loc)); + EXPECT_EQ("40:3-40:55", PrintSourceLocation(loc)); - const Descriptor *c_desc = file_desc->FindMessageTypeByName("C"); + const Descriptor* c_desc = file_desc->FindMessageTypeByName("C"); EXPECT_TRUE(c_desc->GetSourceLocation(&loc)); - EXPECT_EQ("23:1-27:2", PrintSourceLocation(loc)); + EXPECT_EQ("42:1-46:2", PrintSourceLocation(loc)); - const FieldDescriptor *message_extension_desc = + const FieldDescriptor* message_extension_desc = c_desc->FindExtensionByName("message_extension"); EXPECT_TRUE(message_extension_desc->GetSourceLocation(&loc)); - EXPECT_EQ("25:5-25:41", PrintSourceLocation(loc)); + EXPECT_EQ("44:5-44:41", PrintSourceLocation(loc)); +} +TEST_F(SourceLocationTest, InterpretedOptionSourceLocation) { + // This one's a doozy. It checks every kind of option, including + // extension range options. + + // We are verifying that the file's source info contains correct + // info for interpreted options and that it does *not* contain + // any info for corresponding uninterpreted option path. + + SourceLocation loc; + + const FileDescriptor* file_desc = + GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); + + // File options + { + int path[] = {FileDescriptorProto::kOptionsFieldNumber, + FileOptions::kJavaPackageFieldNumber}; + int unint[] = {FileDescriptorProto::kOptionsFieldNumber, + FileOptions::kUninterpretedOptionFieldNumber, 0}; + + std::vector vpath(path, path + 2); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("2:1-2:37", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 3); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + { + int path[] = {FileDescriptorProto::kOptionsFieldNumber, + kCustomOptionFieldNumber}; + int unint[] = {FileDescriptorProto::kOptionsFieldNumber, + FileOptions::kUninterpretedOptionFieldNumber, 1}; + std::vector vpath(path, path + 2); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("3:1-3:35", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 3); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + + // Message option + { + int path[] = {FileDescriptorProto::kMessageTypeFieldNumber, 0, + DescriptorProto::kOptionsFieldNumber, + kCustomOptionFieldNumber}; + int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber, 0, + DescriptorProto::kOptionsFieldNumber, + MessageOptions::kUninterpretedOptionFieldNumber, 0}; + std::vector vpath(path, path + 4); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("5:3-5:36", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 5); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + + // Field option + { + int path[] = {FileDescriptorProto::kMessageTypeFieldNumber, + 0, + DescriptorProto::kFieldFieldNumber, + 0, + FieldDescriptorProto::kOptionsFieldNumber, + FieldOptions::kDeprecatedFieldNumber}; + int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber, + 0, + DescriptorProto::kFieldFieldNumber, + 0, + FieldDescriptorProto::kOptionsFieldNumber, + FieldOptions::kUninterpretedOptionFieldNumber, + 0}; + std::vector vpath(path, path + 6); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("6:25-6:42", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 7); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + + // Nested message option + { + int path[] = { + FileDescriptorProto::kMessageTypeFieldNumber, 0, + DescriptorProto::kNestedTypeFieldNumber, 0, + DescriptorProto::kFieldFieldNumber, 0, + FieldDescriptorProto::kOptionsFieldNumber, kCustomOptionFieldNumber}; + int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber, + 0, + DescriptorProto::kNestedTypeFieldNumber, + 0, + DescriptorProto::kFieldFieldNumber, + 0, + FieldDescriptorProto::kOptionsFieldNumber, + FieldOptions::kUninterpretedOptionFieldNumber, + 0}; + std::vector vpath(path, path + 8); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("8:28-8:55", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 9); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + + // One-of option + { + int path[] = { + FileDescriptorProto::kMessageTypeFieldNumber, 0, + DescriptorProto::kOneofDeclFieldNumber, 0, + OneofDescriptorProto::kOptionsFieldNumber, kCustomOptionFieldNumber}; + int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber, + 0, + DescriptorProto::kOneofDeclFieldNumber, + 0, + OneofDescriptorProto::kOptionsFieldNumber, + OneofOptions::kUninterpretedOptionFieldNumber, + 0}; + std::vector vpath(path, path + 6); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("11:5-11:40", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 7); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + + // Enum option, repeated options + { + int path[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0, + EnumDescriptorProto::kOptionsFieldNumber, + kCustomOptionFieldNumber, 0}; + int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0, + EnumDescriptorProto::kOptionsFieldNumber, + EnumOptions::kUninterpretedOptionFieldNumber, 0}; + std::vector vpath(path, path + 5); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("18:3-18:31", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 5); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + { + int path[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0, + EnumDescriptorProto::kOptionsFieldNumber, + kCustomOptionFieldNumber, 1}; + int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0, + EnumDescriptorProto::kOptionsFieldNumber, + EnumOptions::kUninterpretedOptionFieldNumber, 1}; + std::vector vpath(path, path + 5); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("19:3-19:31", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 5); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + { + int path[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0, + EnumDescriptorProto::kOptionsFieldNumber, + kCustomOptionFieldNumber, 2}; + int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0, + EnumDescriptorProto::kOptionsFieldNumber, + OneofOptions::kUninterpretedOptionFieldNumber, 2}; + std::vector vpath(path, path + 5); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("20:3-20:31", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 5); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + + // Enum value options + { + // option w/ message type that directly sets field + int path[] = {FileDescriptorProto::kEnumTypeFieldNumber, + 0, + EnumDescriptorProto::kValueFieldNumber, + 0, + EnumValueDescriptorProto::kOptionsFieldNumber, + kCustomOptionFieldNumber, + kAFieldNumber}; + int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber, + 0, + EnumDescriptorProto::kValueFieldNumber, + 0, + EnumValueDescriptorProto::kOptionsFieldNumber, + EnumValueOptions::kUninterpretedOptionFieldNumber, + 0}; + std::vector vpath(path, path + 7); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("21:14-21:40", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 7); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + { + int path[] = {FileDescriptorProto::kEnumTypeFieldNumber, + 0, + EnumDescriptorProto::kValueFieldNumber, + 1, + EnumValueDescriptorProto::kOptionsFieldNumber, + kCustomOptionFieldNumber}; + int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber, + 0, + EnumDescriptorProto::kValueFieldNumber, + 1, + EnumValueDescriptorProto::kOptionsFieldNumber, + EnumValueOptions::kUninterpretedOptionFieldNumber, + 0}; + std::vector vpath(path, path + 6); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("22:14-22:42", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 7); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + + // Service option, repeated options + { + int path[] = {FileDescriptorProto::kServiceFieldNumber, 0, + ServiceDescriptorProto::kOptionsFieldNumber, + kCustomOptionFieldNumber, 0}; + int unint[] = {FileDescriptorProto::kServiceFieldNumber, 0, + ServiceDescriptorProto::kOptionsFieldNumber, + ServiceOptions::kUninterpretedOptionFieldNumber, 0}; + std::vector vpath(path, path + 5); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("26:3-26:35", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 5); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + { + int path[] = {FileDescriptorProto::kServiceFieldNumber, 0, + ServiceDescriptorProto::kOptionsFieldNumber, + kCustomOptionFieldNumber, 1}; + int unint[] = {FileDescriptorProto::kServiceFieldNumber, 0, + ServiceDescriptorProto::kOptionsFieldNumber, + ServiceOptions::kUninterpretedOptionFieldNumber, 1}; + std::vector vpath(path, path + 5); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("27:3-27:35", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 5); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + { + int path[] = {FileDescriptorProto::kServiceFieldNumber, 0, + ServiceDescriptorProto::kOptionsFieldNumber, + kCustomOptionFieldNumber, 2}; + int unint[] = {FileDescriptorProto::kServiceFieldNumber, 0, + ServiceDescriptorProto::kOptionsFieldNumber, + ServiceOptions::kUninterpretedOptionFieldNumber, 2}; + std::vector vpath(path, path + 5); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("28:3-28:35", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 5); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + + // Method options + { + int path[] = {FileDescriptorProto::kServiceFieldNumber, + 0, + ServiceDescriptorProto::kMethodFieldNumber, + 1, + MethodDescriptorProto::kOptionsFieldNumber, + MethodOptions::kDeprecatedFieldNumber}; + int unint[] = {FileDescriptorProto::kServiceFieldNumber, + 0, + ServiceDescriptorProto::kMethodFieldNumber, + 1, + MethodDescriptorProto::kOptionsFieldNumber, + MethodOptions::kUninterpretedOptionFieldNumber, + 0}; + std::vector vpath(path, path + 6); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("32:5-32:30", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 7); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + { + int path[] = { + FileDescriptorProto::kServiceFieldNumber, 0, + ServiceDescriptorProto::kMethodFieldNumber, 1, + MethodDescriptorProto::kOptionsFieldNumber, kCustomOptionFieldNumber}; + int unint[] = {FileDescriptorProto::kServiceFieldNumber, + 0, + ServiceDescriptorProto::kMethodFieldNumber, + 1, + MethodDescriptorProto::kOptionsFieldNumber, + MethodOptions::kUninterpretedOptionFieldNumber, + 1}; + std::vector vpath(path, path + 6); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("33:5-33:41", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 7); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + + // Extension range options + { + int path[] = {FileDescriptorProto::kMessageTypeFieldNumber, 1, + DescriptorProto::kExtensionRangeFieldNumber, 0, + DescriptorProto_ExtensionRange::kOptionsFieldNumber}; + std::vector vpath(path, path + 5); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("37:40-37:67", PrintSourceLocation(loc)); + } + { + int path[] = {FileDescriptorProto::kMessageTypeFieldNumber, + 1, + DescriptorProto::kExtensionRangeFieldNumber, + 0, + DescriptorProto_ExtensionRange::kOptionsFieldNumber, + kCustomOptionFieldNumber}; + int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber, + 1, + DescriptorProto::kExtensionRangeFieldNumber, + 0, + DescriptorProto_ExtensionRange::kOptionsFieldNumber, + ExtensionRangeOptions::kUninterpretedOptionFieldNumber, + 0}; + std::vector vpath(path, path + 6); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("37:41-37:66", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 7); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + { + int path[] = {FileDescriptorProto::kMessageTypeFieldNumber, + 1, + DescriptorProto::kExtensionRangeFieldNumber, + 1, + DescriptorProto_ExtensionRange::kOptionsFieldNumber, + kCustomOptionFieldNumber}; + int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber, + 1, + DescriptorProto::kExtensionRangeFieldNumber, + 1, + DescriptorProto_ExtensionRange::kOptionsFieldNumber, + ExtensionRangeOptions::kUninterpretedOptionFieldNumber, + 0}; + std::vector vpath(path, path + 6); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("37:41-37:66", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 7); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } + + // Field option on extension + { + int path[] = {FileDescriptorProto::kExtensionFieldNumber, 0, + FieldDescriptorProto::kOptionsFieldNumber, + FieldOptions::kPackedFieldNumber}; + int unint[] = {FileDescriptorProto::kExtensionFieldNumber, 0, + FieldDescriptorProto::kOptionsFieldNumber, + FieldOptions::kUninterpretedOptionFieldNumber, 0}; + std::vector vpath(path, path + 4); + EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc)); + EXPECT_EQ("40:42-40:53", PrintSourceLocation(loc)); + + std::vector vunint(unint, unint + 5); + EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc)); + } } // Missing SourceCodeInfo doesn't cause crash: TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) { SourceLocation loc; - const FileDescriptor *file_desc = + const FileDescriptor* file_desc = GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); FileDescriptorProto proto; @@ -6739,7 +7736,7 @@ TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) { DescriptorPool bad1_pool(&pool_); const FileDescriptor* bad1_file_desc = GOOGLE_CHECK_NOTNULL(bad1_pool.BuildFile(proto)); - const Descriptor *bad1_a_desc = bad1_file_desc->FindMessageTypeByName("A"); + const Descriptor* bad1_a_desc = bad1_file_desc->FindMessageTypeByName("A"); EXPECT_FALSE(bad1_a_desc->GetSourceLocation(&loc)); } @@ -6747,13 +7744,13 @@ TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) { TEST_F(SourceLocationTest, GetSourceLocation_BogusSourceCodeInfo) { SourceLocation loc; - const FileDescriptor *file_desc = + const FileDescriptor* file_desc = GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); FileDescriptorProto proto; file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo. EXPECT_FALSE(proto.has_source_code_info()); - SourceCodeInfo_Location *loc_msg = + SourceCodeInfo_Location* loc_msg = proto.mutable_source_code_info()->add_location(); loc_msg->add_path(1); loc_msg->add_path(2); @@ -6765,15 +7762,15 @@ TEST_F(SourceLocationTest, GetSourceLocation_BogusSourceCodeInfo) { DescriptorPool bad2_pool(&pool_); const FileDescriptor* bad2_file_desc = GOOGLE_CHECK_NOTNULL(bad2_pool.BuildFile(proto)); - const Descriptor *bad2_a_desc = bad2_file_desc->FindMessageTypeByName("A"); + const Descriptor* bad2_a_desc = bad2_file_desc->FindMessageTypeByName("A"); EXPECT_FALSE(bad2_a_desc->GetSourceLocation(&loc)); } // =================================================================== const char* const kCopySourceCodeInfoToTestInput = - "syntax = \"proto2\";\n" - "message Foo {}\n"; + "syntax = \"proto2\";\n" + "message Foo {}\n"; // Required since source code information is not preserved by // FileDescriptorTest. @@ -6827,7 +7824,7 @@ TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) { class LazilyBuildDependenciesTest : public testing::Test { public: - LazilyBuildDependenciesTest() : pool_(&db_, NULL) { + LazilyBuildDependenciesTest() : pool_(&db_, nullptr) { pool_.InternalSetLazilyBuildDependencies(); } @@ -6837,7 +7834,7 @@ class LazilyBuildDependenciesTest : public testing::Test { db_.Add(tmp); } - void ParseProtoAndAddToDb(const string& proto) { + void ParseProtoAndAddToDb(const std::string& proto) { FileDescriptorProto tmp; ASSERT_TRUE(TextFormat::ParseFromString(proto, &tmp)); db_.Add(tmp); @@ -6845,12 +7842,12 @@ class LazilyBuildDependenciesTest : public testing::Test { void AddSimpleMessageProtoFileToDb(const char* file_name, const char* message_name) { - ParseProtoAndAddToDb("name: '" + string(file_name) + + ParseProtoAndAddToDb("name: '" + std::string(file_name) + ".proto' " "package: \"protobuf_unittest\" " "message_type { " " name:'" + - string(message_name) + + std::string(message_name) + "' " " field { name:'a' number:1 " " label:LABEL_OPTIONAL " @@ -6860,15 +7857,15 @@ class LazilyBuildDependenciesTest : public testing::Test { void AddSimpleEnumProtoFileToDb(const char* file_name, const char* enum_name, const char* enum_value_name) { - ParseProtoAndAddToDb("name: '" + string(file_name) + + ParseProtoAndAddToDb("name: '" + std::string(file_name) + ".proto' " "package: 'protobuf_unittest' " "enum_type { " " name:'" + - string(enum_name) + + std::string(enum_name) + "' " " value { name:'" + - string(enum_value_name) + + std::string(enum_value_name) + "' number:1 } " "}"); } @@ -6897,7 +7894,7 @@ TEST_F(LazilyBuildDependenciesTest, Message) { const FileDescriptor* file = pool_.FindFileByName("foo.proto"); // Verify only foo gets built when asking for foo.proto - EXPECT_TRUE(file != NULL); + EXPECT_TRUE(file != nullptr); EXPECT_TRUE(pool_.InternalIsFileLoaded("foo.proto")); EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto")); @@ -6906,15 +7903,15 @@ TEST_F(LazilyBuildDependenciesTest, Message) { // the field's type is defined in, as well. const Descriptor* desc = file->FindMessageTypeByName("Foo"); const FieldDescriptor* field = desc->FindFieldByName("bar"); - EXPECT_TRUE(field != NULL); + EXPECT_TRUE(field != nullptr); EXPECT_EQ(field, desc->FindFieldByNumber(1)); EXPECT_EQ(field, desc->FindFieldByLowercaseName("bar")); EXPECT_EQ(field, desc->FindFieldByCamelcaseName("bar")); EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto")); // Finally, verify that if we call message_type() on the field, we will - // buid the file where the message is defined, and get a valid descriptor - EXPECT_TRUE(field->message_type() != NULL); + // build the file where the message is defined, and get a valid descriptor + EXPECT_TRUE(field->message_type() != nullptr); EXPECT_TRUE(pool_.InternalIsFileLoaded("bar.proto")); } @@ -6940,18 +7937,18 @@ TEST_F(LazilyBuildDependenciesTest, Enum) { // yet built will build the file and return a descriptor. EXPECT_FALSE(pool_.InternalIsFileLoaded("enum1.proto")); const Descriptor* desc = file->FindMessageTypeByName("Lazy"); - EXPECT_TRUE(desc != NULL); + EXPECT_TRUE(desc != nullptr); const FieldDescriptor* field = desc->FindFieldByName("enum1"); - EXPECT_TRUE(field != NULL); - EXPECT_TRUE(field->enum_type() != NULL); + EXPECT_TRUE(field != nullptr); + EXPECT_TRUE(field->enum_type() != nullptr); EXPECT_TRUE(pool_.InternalIsFileLoaded("enum1.proto")); // Verify calling default_value_enum() on a field whose definition is not // yet built will build the file and return a descriptor to the value. EXPECT_FALSE(pool_.InternalIsFileLoaded("enum2.proto")); field = desc->FindFieldByName("enum2"); - EXPECT_TRUE(field != NULL); - EXPECT_TRUE(field->default_value_enum() != NULL); + EXPECT_TRUE(field != nullptr); + EXPECT_TRUE(field->default_value_enum() != nullptr); EXPECT_TRUE(pool_.InternalIsFileLoaded("enum2.proto")); } @@ -6985,9 +7982,9 @@ TEST_F(LazilyBuildDependenciesTest, Type) { // build the type defined in another file. EXPECT_FALSE(pool_.InternalIsFileLoaded("message1.proto")); const Descriptor* desc = file->FindMessageTypeByName("Lazy"); - EXPECT_TRUE(desc != NULL); + EXPECT_TRUE(desc != nullptr); const FieldDescriptor* field = desc->FindFieldByName("message1"); - EXPECT_TRUE(field != NULL); + EXPECT_TRUE(field != nullptr); EXPECT_EQ(field->type(), FieldDescriptor::TYPE_MESSAGE); EXPECT_TRUE(pool_.InternalIsFileLoaded("message1.proto")); @@ -6995,7 +7992,7 @@ TEST_F(LazilyBuildDependenciesTest, Type) { // build the type defined in another file. EXPECT_FALSE(pool_.InternalIsFileLoaded("message2.proto")); field = desc->FindFieldByName("message2"); - EXPECT_TRUE(field != NULL); + EXPECT_TRUE(field != nullptr); EXPECT_EQ(field->cpp_type(), FieldDescriptor::CPPTYPE_MESSAGE); EXPECT_TRUE(pool_.InternalIsFileLoaded("message2.proto")); @@ -7003,7 +8000,7 @@ TEST_F(LazilyBuildDependenciesTest, Type) { // build the type defined in another file. EXPECT_FALSE(pool_.InternalIsFileLoaded("enum1.proto")); field = desc->FindFieldByName("enum1"); - EXPECT_TRUE(field != NULL); + EXPECT_TRUE(field != nullptr); EXPECT_EQ(field->type(), FieldDescriptor::TYPE_ENUM); EXPECT_TRUE(pool_.InternalIsFileLoaded("enum1.proto")); @@ -7011,7 +8008,7 @@ TEST_F(LazilyBuildDependenciesTest, Type) { // build the type defined in another file. EXPECT_FALSE(pool_.InternalIsFileLoaded("enum2.proto")); field = desc->FindFieldByName("enum2"); - EXPECT_TRUE(field != NULL); + EXPECT_TRUE(field != nullptr); EXPECT_EQ(field->cpp_type(), FieldDescriptor::CPPTYPE_ENUM); EXPECT_TRUE(pool_.InternalIsFileLoaded("enum2.proto")); } @@ -7042,7 +8039,7 @@ TEST_F(LazilyBuildDependenciesTest, Extension) { // Verify foo.bar gets loaded, and bar.proto gets loaded // to register the extension. baz.proto should not get loaded. - EXPECT_TRUE(file != NULL); + EXPECT_TRUE(file != nullptr); EXPECT_TRUE(pool_.InternalIsFileLoaded("foo.proto")); EXPECT_TRUE(pool_.InternalIsFileLoaded("bar.proto")); EXPECT_FALSE(pool_.InternalIsFileLoaded("baz.proto")); @@ -7072,15 +8069,15 @@ TEST_F(LazilyBuildDependenciesTest, Service) { // files defining the input and output type, and input_type() and // output_type() does indeed build the appropriate files. const ServiceDescriptor* service = file->FindServiceByName("LazyService"); - EXPECT_TRUE(service != NULL); + EXPECT_TRUE(service != nullptr); const MethodDescriptor* method = service->FindMethodByName("A"); EXPECT_FALSE(pool_.InternalIsFileLoaded("message1.proto")); EXPECT_FALSE(pool_.InternalIsFileLoaded("message2.proto")); - EXPECT_TRUE(method != NULL); - EXPECT_TRUE(method->input_type() != NULL); + EXPECT_TRUE(method != nullptr); + EXPECT_TRUE(method->input_type() != nullptr); EXPECT_TRUE(pool_.InternalIsFileLoaded("message1.proto")); EXPECT_FALSE(pool_.InternalIsFileLoaded("message2.proto")); - EXPECT_TRUE(method->output_type() != NULL); + EXPECT_TRUE(method->output_type() != nullptr); EXPECT_TRUE(pool_.InternalIsFileLoaded("message2.proto")); } @@ -7105,7 +8102,7 @@ TEST_F(LazilyBuildDependenciesTest, GeneratedFile) { // the generated function "descriptor()" doesn't somehow subvert the laziness // by manually loading the dependencies or something. EXPECT_TRUE(protobuf_unittest::lazy_imports::ImportedMessage::descriptor() != - NULL); + nullptr); EXPECT_TRUE(DescriptorPool::generated_pool()->InternalIsFileLoaded( "google/protobuf/unittest_lazy_dependencies.proto")); EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded( @@ -7116,7 +8113,7 @@ TEST_F(LazilyBuildDependenciesTest, GeneratedFile) { // Verify custom options work when defined in an import that isn't loaded, // and that a non-default value of a custom option doesn't load the file // where that enum is defined. - const google::protobuf::MessageOptions& options = + const MessageOptions& options = protobuf_unittest::lazy_imports::MessageCustomOption::descriptor() ->options(); protobuf_unittest::lazy_imports::LazyEnum custom_option_value = @@ -7128,7 +8125,7 @@ TEST_F(LazilyBuildDependenciesTest, GeneratedFile) { "google/protobuf/unittest_lazy_dependencies_enum.proto")); EXPECT_EQ(custom_option_value, protobuf_unittest::lazy_imports::LAZY_ENUM_1); - const google::protobuf::MessageOptions& options2 = + const MessageOptions& options2 = protobuf_unittest::lazy_imports::MessageCustomOption2::descriptor() ->options(); custom_option_value = @@ -7163,7 +8160,7 @@ TEST_F(LazilyBuildDependenciesTest, Dependency) { AddSimpleMessageProtoFileToDb("baz", "Baz"); const FileDescriptor* foo_file = pool_.FindFileByName("foo.proto"); - EXPECT_TRUE(foo_file != NULL); + EXPECT_TRUE(foo_file != nullptr); // As expected, requesting foo.proto shouldn't build it's dependencies EXPECT_TRUE(pool_.InternalIsFileLoaded("foo.proto")); EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto")); @@ -7172,7 +8169,7 @@ TEST_F(LazilyBuildDependenciesTest, Dependency) { // Verify calling dependency(N) will build the dependency, but // not that file's dependencies. const FileDescriptor* bar_file = foo_file->dependency(0); - EXPECT_TRUE(bar_file != NULL); + EXPECT_TRUE(bar_file != nullptr); EXPECT_TRUE(pool_.InternalIsFileLoaded("bar.proto")); EXPECT_FALSE(pool_.InternalIsFileLoaded("baz.proto")); } @@ -7183,3 +8180,5 @@ TEST_F(LazilyBuildDependenciesTest, Dependency) { } // namespace descriptor_unittest } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/drop_unknown_fields_test.cc b/src/google/protobuf/drop_unknown_fields_test.cc index f2f2f749e0723..55b9ecd38c94a 100644 --- a/src/google/protobuf/drop_unknown_fields_test.cc +++ b/src/google/protobuf/drop_unknown_fields_test.cc @@ -29,44 +29,19 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include #include #include -namespace google { using unittest_drop_unknown_fields::Foo; using unittest_drop_unknown_fields::FooWithExtraFields; +namespace google { namespace protobuf { -TEST(DropUnknownFieldsTest, GeneratedMessageDefaultDrop) { - ::google::protobuf::internal::SetProto3PreserveUnknownsDefault(false); - FooWithExtraFields foo_with_extra_fields; - foo_with_extra_fields.set_int32_value(1); - foo_with_extra_fields.set_enum_value(FooWithExtraFields::QUX); - foo_with_extra_fields.set_extra_int32_value(2); - - Foo foo; - ASSERT_TRUE(foo.ParseFromString(foo_with_extra_fields.SerializeAsString())); - EXPECT_EQ(1, foo.int32_value()); - EXPECT_EQ(static_cast(FooWithExtraFields::QUX), - static_cast(foo.enum_value())); - EXPECT_TRUE(foo.GetReflection()->GetUnknownFields(foo).empty()); - - ASSERT_TRUE(foo_with_extra_fields.ParseFromString(foo.SerializeAsString())); - EXPECT_EQ(1, foo_with_extra_fields.int32_value()); - EXPECT_EQ(FooWithExtraFields::QUX, foo_with_extra_fields.enum_value()); - // The "extra_int32_value" field should be lost. - EXPECT_EQ(0, foo_with_extra_fields.extra_int32_value()); -} - -TEST(DropUnknownFieldsTest, GeneratedMessageDefaultPreserve) { - ::google::protobuf::internal::SetProto3PreserveUnknownsDefault(true); +TEST(DropUnknownFieldsTest, GeneratedMessage) { FooWithExtraFields foo_with_extra_fields; foo_with_extra_fields.set_int32_value(1); foo_with_extra_fields.set_enum_value(FooWithExtraFields::QUX); @@ -86,36 +61,14 @@ TEST(DropUnknownFieldsTest, GeneratedMessageDefaultPreserve) { EXPECT_EQ(2, foo_with_extra_fields.extra_int32_value()); } -TEST(DropUnknownFieldsTest, DynamicMessageDefaultDrop) { - internal::SetProto3PreserveUnknownsDefault(false); - FooWithExtraFields foo_with_extra_fields; - foo_with_extra_fields.set_int32_value(1); - foo_with_extra_fields.set_enum_value(FooWithExtraFields::QUX); - foo_with_extra_fields.set_extra_int32_value(2); - - google::protobuf::DynamicMessageFactory factory; - google::protobuf::scoped_ptr foo( - factory.GetPrototype(Foo::descriptor())->New()); - ASSERT_TRUE(foo->ParseFromString(foo_with_extra_fields.SerializeAsString())); - EXPECT_TRUE(foo->GetReflection()->GetUnknownFields(*foo).empty()); - - ASSERT_TRUE(foo_with_extra_fields.ParseFromString(foo->SerializeAsString())); - EXPECT_EQ(1, foo_with_extra_fields.int32_value()); - EXPECT_EQ(FooWithExtraFields::QUX, foo_with_extra_fields.enum_value()); - // The "extra_int32_value" field should be lost. - EXPECT_EQ(0, foo_with_extra_fields.extra_int32_value()); -} - -TEST(DropUnknownFieldsTest, DynamicMessageDefaultPreserve) { - internal::SetProto3PreserveUnknownsDefault(true); +TEST(DropUnknownFieldsTest, DynamicMessage) { FooWithExtraFields foo_with_extra_fields; foo_with_extra_fields.set_int32_value(1); foo_with_extra_fields.set_enum_value(FooWithExtraFields::QUX); foo_with_extra_fields.set_extra_int32_value(2); - google::protobuf::DynamicMessageFactory factory; - google::protobuf::scoped_ptr foo( - factory.GetPrototype(Foo::descriptor())->New()); + DynamicMessageFactory factory; + std::unique_ptr foo(factory.GetPrototype(Foo::descriptor())->New()); ASSERT_TRUE(foo->ParseFromString(foo_with_extra_fields.SerializeAsString())); EXPECT_FALSE(foo->GetReflection()->GetUnknownFields(*foo).empty()); diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index ad0eeb45da3aa..d04e32b0afc4d 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -1,164 +1,97 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/duration.proto -#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include #include -#include -#include -#include #include -#include +#include +#include #include #include #include #include // @@protoc_insertion_point(includes) - -namespace google { -namespace protobuf { -class DurationDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _Duration_default_instance_; - -namespace protobuf_google_2fprotobuf_2fduration_2eproto { - - -namespace { - -::google::protobuf::Metadata file_level_metadata[1]; - -} // namespace - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField - const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0}, -}; - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField - const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - ::google::protobuf::internal::AuxillaryParseTableField(), -}; -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const - TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, +#include + +PROTOBUF_PRAGMA_INIT_SEG +PROTOBUF_NAMESPACE_OPEN +constexpr Duration::Duration( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : seconds_(PROTOBUF_LONGLONG(0)) + , nanos_(0){} +struct DurationDefaultTypeInternal { + constexpr DurationDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~DurationDefaultTypeInternal() {} + union { + Duration _instance; + }; }; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT DurationDefaultTypeInternal _Duration_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fduration_2eproto[1]; +static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr; -const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { +const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fduration_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { ~0u, // no _has_bits_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Duration, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Duration, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Duration, seconds_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Duration, nanos_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Duration, seconds_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Duration, nanos_), }; -static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { 0, -1, sizeof(Duration)}, +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, sizeof(PROTOBUF_NAMESPACE_ID::Duration)}, }; -static ::google::protobuf::Message const * const file_default_instances[] = { - reinterpret_cast(&_Duration_default_instance_), +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_Duration_default_instance_), }; -namespace { - -void protobuf_AssignDescriptors() { - AddDescriptors(); - ::google::protobuf::MessageFactory* factory = NULL; - AssignDescriptors( - "google/protobuf/duration.proto", schemas, file_default_instances, TableStruct::offsets, factory, - file_level_metadata, NULL, NULL); -} - -void protobuf_AssignDescriptorsOnce() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors); -} - -void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; -void protobuf_RegisterTypes(const ::std::string&) { - protobuf_AssignDescriptorsOnce(); - ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1); -} - -} // namespace -void TableStruct::InitDefaultsImpl() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - ::google::protobuf::internal::InitProtobufDefaults(); - _Duration_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_Duration_default_instance_);} - -void InitDefaults() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl); -} -namespace { -void AddDescriptorsImpl() { - InitDefaults(); - static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - "\n\036google/protobuf/duration.proto\022\017google" - ".protobuf\"*\n\010Duration\022\017\n\007seconds\030\001 \001(\003\022\r" - "\n\005nanos\030\002 \001(\005B|\n\023com.google.protobufB\rDu" - "rationProtoP\001Z*github.com/golang/protobu" - "f/ptypes/duration\370\001\001\242\002\003GPB\252\002\036Google.Prot" - "obuf.WellKnownTypesb\006proto3" - }; - ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( - descriptor, 227); - ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( - "google/protobuf/duration.proto", &protobuf_RegisterTypes); -} -} // anonymous namespace - -void AddDescriptors() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl); +const char descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\036google/protobuf/duration.proto\022\017google" + ".protobuf\"*\n\010Duration\022\017\n\007seconds\030\001 \001(\003\022\r" + "\n\005nanos\030\002 \001(\005B\203\001\n\023com.google.protobufB\rD" + "urationProtoP\001Z1google.golang.org/protob" + "uf/types/known/durationpb\370\001\001\242\002\003GPB\252\002\036Goo" + "gle.Protobuf.WellKnownTypesb\006proto3" + ; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fduration_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto = { + false, false, 235, descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto, "google/protobuf/duration.proto", + &descriptor_table_google_2fprotobuf_2fduration_2eproto_once, nullptr, 0, 1, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fduration_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fduration_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto, file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata +descriptor_table_google_2fprotobuf_2fduration_2eproto_metadata_getter(int index) { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fduration_2eproto); + return descriptor_table_google_2fprotobuf_2fduration_2eproto.file_level_metadata[index]; } -// Force AddDescriptors() to be called at dynamic initialization time. -struct StaticDescriptorInitializer { - StaticDescriptorInitializer() { - AddDescriptors(); - } -} static_descriptor_initializer; - -} // namespace protobuf_google_2fprotobuf_2fduration_2eproto +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fduration_2eproto(&descriptor_table_google_2fprotobuf_2fduration_2eproto); +PROTOBUF_NAMESPACE_OPEN // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int Duration::kSecondsFieldNumber; -const int Duration::kNanosFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +class Duration::_Internal { + public: +}; -Duration::Duration() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fduration_2eproto::InitDefaults(); - } - SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.Duration) -} -Duration::Duration(::google::protobuf::Arena* arena) - : ::google::protobuf::Message(), - _internal_metadata_(arena) { - protobuf_google_2fprotobuf_2fduration_2eproto::InitDefaults(); +Duration::Duration(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); RegisterArenaDtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Duration) } Duration::Duration(const Duration& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); ::memcpy(&seconds_, &from.seconds_, static_cast(reinterpret_cast(&nanos_) - reinterpret_cast(&seconds_)) + sizeof(nanos_)); @@ -166,164 +99,108 @@ Duration::Duration(const Duration& from) } void Duration::SharedCtor() { - ::memset(&seconds_, 0, static_cast( - reinterpret_cast(&nanos_) - - reinterpret_cast(&seconds_)) + sizeof(nanos_)); - _cached_size_ = 0; +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&seconds_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&nanos_) - + reinterpret_cast(&seconds_)) + sizeof(nanos_)); } Duration::~Duration() { // @@protoc_insertion_point(destructor:google.protobuf.Duration) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void Duration::SharedDtor() { - ::google::protobuf::Arena* arena = GetArenaNoVirtual(); - GOOGLE_DCHECK(arena == NULL); - if (arena != NULL) { - return; - } - + GOOGLE_DCHECK(GetArena() == nullptr); } void Duration::ArenaDtor(void* object) { Duration* _this = reinterpret_cast< Duration* >(object); (void)_this; } -void Duration::RegisterArenaDtor(::google::protobuf::Arena* arena) { +void Duration::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } void Duration::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* Duration::descriptor() { - protobuf_google_2fprotobuf_2fduration_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fduration_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const Duration& Duration::default_instance() { - protobuf_google_2fprotobuf_2fduration_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -Duration* Duration::New(::google::protobuf::Arena* arena) const { - return ::google::protobuf::Arena::CreateMessage(arena); + _cached_size_.Set(size); } void Duration::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Duration) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; ::memset(&seconds_, 0, static_cast( reinterpret_cast(&nanos_) - reinterpret_cast(&seconds_)) + sizeof(nanos_)); - _internal_metadata_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } -bool Duration::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.Duration) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { +const char* Duration::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { // int64 seconds = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { - - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>( - input, &seconds_))); - } else { - goto handle_unusual; - } - break; - } - + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + seconds_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // int32 nanos = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) { - - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, &nanos_))); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + nanos_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.Duration) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.Duration) - return false; -#undef DO_ -} - -void Duration::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.Duration) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // int64 seconds = 1; - if (this->seconds() != 0) { - ::google::protobuf::internal::WireFormatLite::WriteInt64(1, this->seconds(), output); - } - - // int32 nanos = 2; - if (this->nanos() != 0) { - ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->nanos(), output); - } - - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.Duration) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* Duration::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* Duration::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Duration) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // int64 seconds = 1; if (this->seconds() != 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(1, this->seconds(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(1, this->_internal_seconds(), target); } // int32 nanos = 2; if (this->nanos() != 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->nanos(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_nanos(), target); } - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Duration) return target; @@ -333,41 +210,42 @@ size_t Duration::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Duration) size_t total_size = 0; - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // int64 seconds = 1; if (this->seconds() != 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int64Size( - this->seconds()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int64Size( + this->_internal_seconds()); } // int32 nanos = 2; if (this->nanos() != 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - this->nanos()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_nanos()); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void Duration::MergeFrom(const ::google::protobuf::Message& from) { +void Duration::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Duration) GOOGLE_DCHECK_NE(&from, this); const Duration* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Duration) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Duration) MergeFrom(*source); @@ -377,19 +255,19 @@ void Duration::MergeFrom(const ::google::protobuf::Message& from) { void Duration::MergeFrom(const Duration& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Duration) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; if (from.seconds() != 0) { - set_seconds(from.seconds()); + _internal_set_seconds(from._internal_seconds()); } if (from.nanos() != 0) { - set_nanos(from.nanos()); + _internal_set_nanos(from._internal_nanos()); } } -void Duration::CopyFrom(const ::google::protobuf::Message& from) { +void Duration::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Duration) if (&from == this) return; Clear(); @@ -407,74 +285,29 @@ bool Duration::IsInitialized() const { return true; } -void Duration::Swap(Duration* other) { - if (other == this) return; - if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { - InternalSwap(other); - } else { - Duration* temp = New(GetArenaNoVirtual()); - temp->MergeFrom(*other); - other->CopyFrom(*this); - InternalSwap(temp); - if (GetArenaNoVirtual() == NULL) { - delete temp; - } - } -} -void Duration::UnsafeArenaSwap(Duration* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); - InternalSwap(other); -} void Duration::InternalSwap(Duration* other) { using std::swap; - swap(seconds_, other->seconds_); - swap(nanos_, other->nanos_); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata Duration::GetMetadata() const { - protobuf_google_2fprotobuf_2fduration_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fduration_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// Duration - -// int64 seconds = 1; -void Duration::clear_seconds() { - seconds_ = GOOGLE_LONGLONG(0); -} -::google::protobuf::int64 Duration::seconds() const { - // @@protoc_insertion_point(field_get:google.protobuf.Duration.seconds) - return seconds_; -} -void Duration::set_seconds(::google::protobuf::int64 value) { - - seconds_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.Duration.seconds) + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(Duration, nanos_) + + sizeof(Duration::nanos_) + - PROTOBUF_FIELD_OFFSET(Duration, seconds_)>( + reinterpret_cast(&seconds_), + reinterpret_cast(&other->seconds_)); } -// int32 nanos = 2; -void Duration::clear_nanos() { - nanos_ = 0; -} -::google::protobuf::int32 Duration::nanos() const { - // @@protoc_insertion_point(field_get:google.protobuf.Duration.nanos) - return nanos_; -} -void Duration::set_nanos(::google::protobuf::int32 value) { - - nanos_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.Duration.nanos) +::PROTOBUF_NAMESPACE_ID::Metadata Duration::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::Duration* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::Duration >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::Duration >(arena); +} +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) +#include diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h index bed112b507c53..65c5d264a3467 100644 --- a/src/google/protobuf/duration.pb.h +++ b/src/google/protobuf/duration.pb.h @@ -1,186 +1,222 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/duration.proto -#ifndef PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED -#define PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto +#include #include -#include - -#if GOOGLE_PROTOBUF_VERSION < 3004000 +#include +#if PROTOBUF_VERSION < 3015000 #error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update +#error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 3015000 < PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please +#error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif +#include #include #include #include #include #include -#include +#include +#include #include #include // IWYU pragma: export #include // IWYU pragma: export #include // @@protoc_insertion_point(includes) -namespace google { -namespace protobuf { -class Duration; -class DurationDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern DurationDefaultTypeInternal _Duration_default_instance_; -} // namespace protobuf -} // namespace google - -namespace google { -namespace protobuf { - -namespace protobuf_google_2fprotobuf_2fduration_2eproto { -// Internal implementation detail -- do not call these. -struct LIBPROTOBUF_EXPORT TableStruct { - static const ::google::protobuf::internal::ParseTableField entries[]; - static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; - static const ::google::protobuf::internal::ParseTable schema[]; - static const ::google::protobuf::uint32 offsets[]; - static const ::google::protobuf::internal::FieldMetadata field_metadata[]; - static const ::google::protobuf::internal::SerializationTable serialization_table[]; - static void InitDefaultsImpl(); +#include +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fduration_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fduration_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; }; -void LIBPROTOBUF_EXPORT AddDescriptors(); -void LIBPROTOBUF_EXPORT InitDefaults(); -} // namespace protobuf_google_2fprotobuf_2fduration_2eproto +extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto; +PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fduration_2eproto_metadata_getter(int index); +PROTOBUF_NAMESPACE_OPEN +class Duration; +struct DurationDefaultTypeInternal; +PROTOBUF_EXPORT extern DurationDefaultTypeInternal _Duration_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::Duration* Arena::CreateMaybeMessage(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN // =================================================================== -class LIBPROTOBUF_EXPORT Duration : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Duration) */ { +class PROTOBUF_EXPORT Duration PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Duration) */ { public: - Duration(); + inline Duration() : Duration(nullptr) {} virtual ~Duration(); + explicit constexpr Duration(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); Duration(const Duration& from); - - inline Duration& operator=(const Duration& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 Duration(Duration&& from) noexcept : Duration() { *this = ::std::move(from); } + inline Duration& operator=(const Duration& from) { + CopyFrom(from); + return *this; + } inline Duration& operator=(Duration&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL { - return GetArenaNoVirtual(); + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); } - inline void* GetMaybeArenaPointer() const PROTOBUF_FINAL { - return MaybeArenaPtr(); + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const Duration& default_instance() { + return *internal_default_instance(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const Duration& default_instance(); - static inline const Duration* internal_default_instance() { return reinterpret_cast( &_Duration_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 0; - void UnsafeArenaSwap(Duration* other); - void Swap(Duration* other); friend void swap(Duration& a, Duration& b) { a.Swap(&b); } + inline void Swap(Duration* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Duration* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline Duration* New() const PROTOBUF_FINAL { return New(NULL); } + inline Duration* New() const final { + return CreateMaybeMessage(nullptr); + } - Duration* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + Duration* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const Duration& from); void MergeFrom(const Duration& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(Duration* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Duration"; + } protected: - explicit Duration(::google::protobuf::Arena* arena); + explicit Duration(::PROTOBUF_NAMESPACE_ID::Arena* arena); private: static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::google::protobuf::Arena* arena); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return _internal_metadata_.arena(); - } - inline void* MaybeArenaPtr() const { - return _internal_metadata_.raw_arena_ptr(); + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fduration_2eproto_metadata_getter(kIndexInFileMessages); } - public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kSecondsFieldNumber = 1, + kNanosFieldNumber = 2, + }; // int64 seconds = 1; void clear_seconds(); - static const int kSecondsFieldNumber = 1; - ::google::protobuf::int64 seconds() const; - void set_seconds(::google::protobuf::int64 value); + ::PROTOBUF_NAMESPACE_ID::int64 seconds() const; + void set_seconds(::PROTOBUF_NAMESPACE_ID::int64 value); + private: + ::PROTOBUF_NAMESPACE_ID::int64 _internal_seconds() const; + void _internal_set_seconds(::PROTOBUF_NAMESPACE_ID::int64 value); + public: // int32 nanos = 2; void clear_nanos(); - static const int kNanosFieldNumber = 2; - ::google::protobuf::int32 nanos() const; - void set_nanos(::google::protobuf::int32 value); + ::PROTOBUF_NAMESPACE_ID::int32 nanos() const; + void set_nanos(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_nanos() const; + void _internal_set_nanos(::PROTOBUF_NAMESPACE_ID::int32 value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.Duration) private: + class _Internal; - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - template friend class ::google::protobuf::Arena::InternalHelper; + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; - ::google::protobuf::int64 seconds_; - ::google::protobuf::int32 nanos_; - mutable int _cached_size_; - friend struct protobuf_google_2fprotobuf_2fduration_2eproto::TableStruct; + ::PROTOBUF_NAMESPACE_ID::int64 seconds_; + ::PROTOBUF_NAMESPACE_ID::int32 nanos_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2fduration_2eproto; }; // =================================================================== // =================================================================== -#if !PROTOBUF_INLINE_NOT_IN_HEADERS #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" @@ -189,15 +225,21 @@ class LIBPROTOBUF_EXPORT Duration : public ::google::protobuf::Message /* @@prot // int64 seconds = 1; inline void Duration::clear_seconds() { - seconds_ = GOOGLE_LONGLONG(0); + seconds_ = PROTOBUF_LONGLONG(0); } -inline ::google::protobuf::int64 Duration::seconds() const { - // @@protoc_insertion_point(field_get:google.protobuf.Duration.seconds) +inline ::PROTOBUF_NAMESPACE_ID::int64 Duration::_internal_seconds() const { return seconds_; } -inline void Duration::set_seconds(::google::protobuf::int64 value) { +inline ::PROTOBUF_NAMESPACE_ID::int64 Duration::seconds() const { + // @@protoc_insertion_point(field_get:google.protobuf.Duration.seconds) + return _internal_seconds(); +} +inline void Duration::_internal_set_seconds(::PROTOBUF_NAMESPACE_ID::int64 value) { seconds_ = value; +} +inline void Duration::set_seconds(::PROTOBUF_NAMESPACE_ID::int64 value) { + _internal_set_seconds(value); // @@protoc_insertion_point(field_set:google.protobuf.Duration.seconds) } @@ -205,27 +247,31 @@ inline void Duration::set_seconds(::google::protobuf::int64 value) { inline void Duration::clear_nanos() { nanos_ = 0; } -inline ::google::protobuf::int32 Duration::nanos() const { - // @@protoc_insertion_point(field_get:google.protobuf.Duration.nanos) +inline ::PROTOBUF_NAMESPACE_ID::int32 Duration::_internal_nanos() const { return nanos_; } -inline void Duration::set_nanos(::google::protobuf::int32 value) { +inline ::PROTOBUF_NAMESPACE_ID::int32 Duration::nanos() const { + // @@protoc_insertion_point(field_get:google.protobuf.Duration.nanos) + return _internal_nanos(); +} +inline void Duration::_internal_set_nanos(::PROTOBUF_NAMESPACE_ID::int32 value) { nanos_ = value; +} +inline void Duration::set_nanos(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_nanos(value); // @@protoc_insertion_point(field_set:google.protobuf.Duration.nanos) } #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ -#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) -#endif // PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto diff --git a/src/google/protobuf/duration.proto b/src/google/protobuf/duration.proto index 975fce41aae05..81c3e369fd130 100644 --- a/src/google/protobuf/duration.proto +++ b/src/google/protobuf/duration.proto @@ -34,7 +34,7 @@ package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/duration"; +option go_package = "google.golang.org/protobuf/types/known/durationpb"; option java_package = "com.google.protobuf"; option java_outer_classname = "DurationProto"; option java_multiple_files = true; @@ -61,7 +61,7 @@ option objc_class_prefix = "GPB"; // if (duration.seconds < 0 && duration.nanos > 0) { // duration.seconds += 1; // duration.nanos -= 1000000000; -// } else if (durations.seconds > 0 && duration.nanos < 0) { +// } else if (duration.seconds > 0 && duration.nanos < 0) { // duration.seconds -= 1; // duration.nanos += 1000000000; // } @@ -101,7 +101,6 @@ option objc_class_prefix = "GPB"; // // message Duration { - // Signed seconds of the span of time. Must be from -315,576,000,000 // to +315,576,000,000 inclusive. Note: these bounds are computed from: // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc index cdd4324362a5d..ef7e1f2e7a58d 100644 --- a/src/google/protobuf/dynamic_message.cc +++ b/src/google/protobuf/dynamic_message.cc @@ -34,10 +34,10 @@ // // DynamicMessage is implemented by constructing a data structure which // has roughly the same memory layout as a generated message would have. -// Then, we use GeneratedMessageReflection to implement our reflection -// interface. All the other operations we need to implement (e.g. -// parsing, copying, etc.) are already implemented in terms of -// Reflection, so the rest is easy. +// Then, we use Reflection to implement our reflection interface. All +// the other operations we need to implement (e.g. parsing, copying, +// etc.) are already implemented in terms of Reflection, so the rest is +// easy. // // The up side of this strategy is that it's very efficient. We don't // need to use hash_maps or generic representations of fields. The @@ -62,20 +62,20 @@ // Item 8 of "More Effective C++" discusses this in more detail, though // I don't have the book on me right now so I'm not sure. +#include + #include -#include +#include #include -#ifndef _SHARED_PTR_H -#include -#endif - -#include +#include +#include -#include -#include #include -#include +#include #include +#include +#include +#include #include #include #include @@ -85,14 +85,13 @@ #include #include +#include // NOLINT namespace google { namespace protobuf { using internal::DynamicMapField; using internal::ExtensionSet; -using internal::GeneratedMessageReflection; -using internal::InternalMetadataWithArena; using internal::MapField; @@ -103,8 +102,28 @@ using internal::ArenaStringPtr; namespace { -bool IsMapFieldInApi(const FieldDescriptor* field) { - return field->is_map(); +bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); } + +// Sync with helpers.h. +inline bool HasHasbit(const FieldDescriptor* field) { + // This predicate includes proto3 message fields only if they have "optional". + // Foo submsg1 = 1; // HasHasbit() == false + // optional Foo submsg2 = 2; // HasHasbit() == true + // This is slightly odd, as adding "optional" to a singular proto3 field does + // not change the semantics or API. However whenever any field in a message + // has a hasbit, it forces reflection to include hasbit offsets for *all* + // fields, even if almost all of them are set to -1 (no hasbit). So to avoid + // causing a sudden size regression for ~all proto3 messages, we give proto3 + // message fields a hasbit only if "optional" is present. If the user is + // explicitly writing "optional", it is likely they are writing it on + // primitive fields also. + return (field->has_optional_keyword() || field->is_required()) && + !field->options().weak(); +} + +inline bool InRealOneof(const FieldDescriptor* field) { + return field->containing_oneof() && + !field->containing_oneof()->is_synthetic(); } // Compute the byte size of the in-memory representation of the field. @@ -112,14 +131,22 @@ int FieldSpaceUsed(const FieldDescriptor* field) { typedef FieldDescriptor FD; // avoid line wrapping if (field->label() == FD::LABEL_REPEATED) { switch (field->cpp_type()) { - case FD::CPPTYPE_INT32 : return sizeof(RepeatedField); - case FD::CPPTYPE_INT64 : return sizeof(RepeatedField); - case FD::CPPTYPE_UINT32 : return sizeof(RepeatedField); - case FD::CPPTYPE_UINT64 : return sizeof(RepeatedField); - case FD::CPPTYPE_DOUBLE : return sizeof(RepeatedField); - case FD::CPPTYPE_FLOAT : return sizeof(RepeatedField); - case FD::CPPTYPE_BOOL : return sizeof(RepeatedField); - case FD::CPPTYPE_ENUM : return sizeof(RepeatedField); + case FD::CPPTYPE_INT32: + return sizeof(RepeatedField); + case FD::CPPTYPE_INT64: + return sizeof(RepeatedField); + case FD::CPPTYPE_UINT32: + return sizeof(RepeatedField); + case FD::CPPTYPE_UINT64: + return sizeof(RepeatedField); + case FD::CPPTYPE_DOUBLE: + return sizeof(RepeatedField); + case FD::CPPTYPE_FLOAT: + return sizeof(RepeatedField); + case FD::CPPTYPE_BOOL: + return sizeof(RepeatedField); + case FD::CPPTYPE_ENUM: + return sizeof(RepeatedField); case FD::CPPTYPE_MESSAGE: if (IsMapFieldInApi(field)) { return sizeof(DynamicMapField); @@ -131,20 +158,28 @@ int FieldSpaceUsed(const FieldDescriptor* field) { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: - return sizeof(RepeatedPtrField); + return sizeof(RepeatedPtrField); } break; } } else { switch (field->cpp_type()) { - case FD::CPPTYPE_INT32 : return sizeof(int32 ); - case FD::CPPTYPE_INT64 : return sizeof(int64 ); - case FD::CPPTYPE_UINT32 : return sizeof(uint32 ); - case FD::CPPTYPE_UINT64 : return sizeof(uint64 ); - case FD::CPPTYPE_DOUBLE : return sizeof(double ); - case FD::CPPTYPE_FLOAT : return sizeof(float ); - case FD::CPPTYPE_BOOL : return sizeof(bool ); - case FD::CPPTYPE_ENUM : return sizeof(int ); + case FD::CPPTYPE_INT32: + return sizeof(int32); + case FD::CPPTYPE_INT64: + return sizeof(int64); + case FD::CPPTYPE_UINT32: + return sizeof(uint32); + case FD::CPPTYPE_UINT64: + return sizeof(uint64); + case FD::CPPTYPE_DOUBLE: + return sizeof(double); + case FD::CPPTYPE_FLOAT: + return sizeof(float); + case FD::CPPTYPE_BOOL: + return sizeof(bool); + case FD::CPPTYPE_ENUM: + return sizeof(int); case FD::CPPTYPE_MESSAGE: return sizeof(Message*); @@ -163,39 +198,7 @@ int FieldSpaceUsed(const FieldDescriptor* field) { return 0; } -// Compute the byte size of in-memory representation of the oneof fields -// in default oneof instance. -int OneofFieldSpaceUsed(const FieldDescriptor* field) { - typedef FieldDescriptor FD; // avoid line wrapping - switch (field->cpp_type()) { - case FD::CPPTYPE_INT32 : return sizeof(int32 ); - case FD::CPPTYPE_INT64 : return sizeof(int64 ); - case FD::CPPTYPE_UINT32 : return sizeof(uint32 ); - case FD::CPPTYPE_UINT64 : return sizeof(uint64 ); - case FD::CPPTYPE_DOUBLE : return sizeof(double ); - case FD::CPPTYPE_FLOAT : return sizeof(float ); - case FD::CPPTYPE_BOOL : return sizeof(bool ); - case FD::CPPTYPE_ENUM : return sizeof(int ); - - case FD::CPPTYPE_MESSAGE: - return sizeof(Message*); - - case FD::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: - case FieldOptions::STRING: - return sizeof(ArenaStringPtr); - } - break; - } - - GOOGLE_LOG(DFATAL) << "Can't get here."; - return 0; -} - -inline int DivideRoundingUp(int i, int j) { - return (i + (j - 1)) / j; -} +inline int DivideRoundingUp(int i, int j) { return (i + (j - 1)) / j; } static const int kSafeAlignment = sizeof(uint64); static const int kMaxOneofUnionSize = sizeof(uint64); @@ -206,9 +209,7 @@ inline int AlignTo(int offset, int alignment) { // Rounds the given byte offset up to the next offset aligned such that any // type may be stored at it. -inline int AlignOffset(int offset) { - return AlignTo(offset, kSafeAlignment); -} +inline int AlignOffset(int offset) { return AlignTo(offset, kSafeAlignment); } #define bitsizeof(T) (sizeof(T) * 8) @@ -218,81 +219,56 @@ inline int AlignOffset(int offset) { class DynamicMessage : public Message { public: - struct TypeInfo { - int size; - int has_bits_offset; - int oneof_case_offset; - int internal_metadata_offset; - int extensions_offset; - - // Not owned by the TypeInfo. - DynamicMessageFactory* factory; // The factory that created this object. - const DescriptorPool* pool; // The factory's DescriptorPool. - const Descriptor* type; // Type of this DynamicMessage. - - // Warning: The order in which the following pointers are defined is - // important (the prototype must be deleted *before* the offsets). - google::protobuf::scoped_array offsets; - google::protobuf::scoped_array has_bits_indices; - google::protobuf::scoped_ptr reflection; - // Don't use a scoped_ptr to hold the prototype: the destructor for - // DynamicMessage needs to know whether it is the prototype, and does so by - // looking back at this field. This would assume details about the - // implementation of scoped_ptr. - const DynamicMessage* prototype; - int weak_field_map_offset; // The offset for the weak_field_map; - - TypeInfo() : prototype(NULL) {} - - ~TypeInfo() { - delete prototype; - } - }; - - DynamicMessage(const TypeInfo* type_info); + explicit DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info); // This should only be used by GetPrototypeNoLock() to avoid dead lock. - DynamicMessage(const TypeInfo* type_info, bool lock_factory); + DynamicMessage(DynamicMessageFactory::TypeInfo* type_info, bool lock_factory); ~DynamicMessage(); // Called on the prototype after construction to initialize message fields. + // Cross linking the default instances allows for fast reflection access of + // unset message fields. Without it we would have to go to the MessageFactory + // to get the prototype, which is a much more expensive operation. + // + // Generated messages do not cross-link to avoid dynamic initialization of the + // global instances. + // Instead, they keep the default instances in the FieldDescriptor objects. void CrossLinkPrototypes(); // implements Message ---------------------------------------------- - Message* New() const; - Message* New(::google::protobuf::Arena* arena) const; - ::google::protobuf::Arena* GetArena() const { return NULL; }; + Message* New() const override; + Message* New(Arena* arena) const override; - int GetCachedSize() const; - void SetCachedSize(int size) const; + int GetCachedSize() const override; + void SetCachedSize(int size) const override; - Metadata GetMetadata() const; + Metadata GetMetadata() const override; +#if defined(__cpp_lib_destroying_delete) && defined(__cpp_sized_deallocation) + static void operator delete(DynamicMessage* msg, std::destroying_delete_t); +#else // We actually allocate more memory than sizeof(*this) when this // class's memory is allocated via the global operator new. Thus, we need to // manually call the global operator delete. Calling the destructor is taken // care of for us. This makes DynamicMessage compatible with -fsized-delete. // It doesn't work for MSVC though. #ifndef _MSC_VER - static void operator delete(void* ptr) { - ::operator delete(ptr); - } + static void operator delete(void* ptr) { ::operator delete(ptr); } #endif // !_MSC_VER +#endif private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage); - DynamicMessage(const TypeInfo* type_info, ::google::protobuf::Arena* arena); + DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info, + Arena* arena); void SharedCtor(bool lock_factory); - inline bool is_prototype() const { - return type_info_->prototype == this || - // If type_info_->prototype is NULL, then we must be constructing - // the prototype now, which means we must be the prototype. - type_info_->prototype == NULL; - } + // Needed to get the offset of the internal metadata member. + friend class DynamicMessageFactory; + + bool is_prototype() const; inline void* OffsetToPointer(int offset) { return reinterpret_cast(this) + offset; @@ -301,26 +277,60 @@ class DynamicMessage : public Message { return reinterpret_cast(this) + offset; } - const TypeInfo* type_info_; - // TODO(kenton): Make this an atomic when C++ supports it. - mutable int cached_byte_size_; + const DynamicMessageFactory::TypeInfo* type_info_; + mutable std::atomic cached_byte_size_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage); +}; + +struct DynamicMessageFactory::TypeInfo { + int size; + int has_bits_offset; + int oneof_case_offset; + int extensions_offset; + + // Not owned by the TypeInfo. + DynamicMessageFactory* factory; // The factory that created this object. + const DescriptorPool* pool; // The factory's DescriptorPool. + const Descriptor* type; // Type of this DynamicMessage. + + // Warning: The order in which the following pointers are defined is + // important (the prototype must be deleted *before* the offsets). + std::unique_ptr offsets; + std::unique_ptr has_bits_indices; + std::unique_ptr reflection; + // Don't use a unique_ptr to hold the prototype: the destructor for + // DynamicMessage needs to know whether it is the prototype, and does so by + // looking back at this field. This would assume details about the + // implementation of unique_ptr. + const DynamicMessage* prototype; + int weak_field_map_offset; // The offset for the weak_field_map; + + TypeInfo() : prototype(nullptr) {} + + ~TypeInfo() { delete prototype; } }; -DynamicMessage::DynamicMessage(const TypeInfo* type_info) - : type_info_(type_info), - cached_byte_size_(0) { +DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info) + : type_info_(type_info), cached_byte_size_(0) { SharedCtor(true); } -DynamicMessage::DynamicMessage(const TypeInfo* type_info, - ::google::protobuf::Arena* arena) - : type_info_(type_info), - cached_byte_size_(0) { +DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info, + Arena* arena) + : Message(arena), type_info_(type_info), cached_byte_size_(0) { SharedCtor(true); } -DynamicMessage::DynamicMessage(const TypeInfo* type_info, bool lock_factory) +DynamicMessage::DynamicMessage(DynamicMessageFactory::TypeInfo* type_info, + bool lock_factory) : type_info_(type_info), cached_byte_size_(0) { + // The prototype in type_info has to be set before creating the prototype + // instance on memory. e.g., message Foo { map a = 1; }. When + // creating prototype for Foo, prototype of the map entry will also be + // created, which needs the address of the prototype of Foo (the value in + // map). To break the cyclic dependency, we have to assign the address of + // prototype into type_info first. + type_info->prototype = this; SharedCtor(lock_factory); } @@ -336,47 +346,47 @@ void DynamicMessage::SharedCtor(bool lock_factory) { const Descriptor* descriptor = type_info_->type; // Initialize oneof cases. - for (int i = 0 ; i < descriptor->oneof_decl_count(); ++i) { - new (OffsetToPointer(type_info_->oneof_case_offset + sizeof(uint32) * i)) - uint32(0); + int oneof_count = 0; + for (int i = 0; i < descriptor->oneof_decl_count(); ++i) { + if (descriptor->oneof_decl(i)->is_synthetic()) continue; + new (OffsetToPointer(type_info_->oneof_case_offset + + sizeof(uint32) * oneof_count++)) uint32(0); } - new (OffsetToPointer(type_info_->internal_metadata_offset)) - InternalMetadataWithArena; - if (type_info_->extensions_offset != -1) { - new (OffsetToPointer(type_info_->extensions_offset)) ExtensionSet; + new (OffsetToPointer(type_info_->extensions_offset)) + ExtensionSet(GetArena()); } for (int i = 0; i < descriptor->field_count(); i++) { const FieldDescriptor* field = descriptor->field(i); void* field_ptr = OffsetToPointer(type_info_->offsets[i]); - if (field->containing_oneof()) { + if (InRealOneof(field)) { continue; } switch (field->cpp_type()) { -#define HANDLE_TYPE(CPPTYPE, TYPE) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - if (!field->is_repeated()) { \ - new(field_ptr) TYPE(field->default_value_##TYPE()); \ - } else { \ - new(field_ptr) RepeatedField(); \ - } \ - break; - - HANDLE_TYPE(INT32 , int32 ); - HANDLE_TYPE(INT64 , int64 ); +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + if (!field->is_repeated()) { \ + new (field_ptr) TYPE(field->default_value_##TYPE()); \ + } else { \ + new (field_ptr) RepeatedField(GetArena()); \ + } \ + break; + + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); HANDLE_TYPE(UINT32, uint32); HANDLE_TYPE(UINT64, uint64); HANDLE_TYPE(DOUBLE, double); - HANDLE_TYPE(FLOAT , float ); - HANDLE_TYPE(BOOL , bool ); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_ENUM: if (!field->is_repeated()) { - new(field_ptr) int(field->default_value_enum()->number()); + new (field_ptr) int(field->default_value_enum()->number()); } else { - new(field_ptr) RepeatedField(); + new (field_ptr) RepeatedField(GetArena()); } break; @@ -385,19 +395,14 @@ void DynamicMessage::SharedCtor(bool lock_factory) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: if (!field->is_repeated()) { - const string* default_value; - if (is_prototype()) { - default_value = &field->default_value_string(); - } else { - default_value = &(reinterpret_cast( - type_info_->prototype->OffsetToPointer( - type_info_->offsets[i])) - ->Get()); - } - ArenaStringPtr* asp = new(field_ptr) ArenaStringPtr(); + const std::string* default_value = + field->default_value_string().empty() + ? &internal::GetEmptyStringAlreadyInited() + : nullptr; + ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr(); asp->UnsafeSetDefault(default_value); } else { - new(field_ptr) RepeatedPtrField(); + new (field_ptr) RepeatedPtrField(GetArena()); } break; } @@ -405,22 +410,35 @@ void DynamicMessage::SharedCtor(bool lock_factory) { case FieldDescriptor::CPPTYPE_MESSAGE: { if (!field->is_repeated()) { - new(field_ptr) Message*(NULL); + new (field_ptr) Message*(NULL); } else { if (IsMapFieldInApi(field)) { // We need to lock in most cases to avoid data racing. Only not lock // when the constructor is called inside GetPrototype(), in which // case we have already locked the factory. if (lock_factory) { - new (field_ptr) DynamicMapField( - type_info_->factory->GetPrototype(field->message_type())); + if (GetArena() != nullptr) { + new (field_ptr) DynamicMapField( + type_info_->factory->GetPrototype(field->message_type()), + GetArena()); + } else { + new (field_ptr) DynamicMapField( + type_info_->factory->GetPrototype(field->message_type())); + } } else { - new (field_ptr) - DynamicMapField(type_info_->factory->GetPrototypeNoLock( - field->message_type())); + if (GetArena() != nullptr) { + new (field_ptr) + DynamicMapField(type_info_->factory->GetPrototypeNoLock( + field->message_type()), + GetArena()); + } else { + new (field_ptr) + DynamicMapField(type_info_->factory->GetPrototypeNoLock( + field->message_type())); + } } } else { - new (field_ptr) RepeatedPtrField(); + new (field_ptr) RepeatedPtrField(GetArena()); } } break; @@ -429,16 +447,31 @@ void DynamicMessage::SharedCtor(bool lock_factory) { } } +bool DynamicMessage::is_prototype() const { + return type_info_->prototype == this || + // If type_info_->prototype is NULL, then we must be constructing + // the prototype now, which means we must be the prototype. + type_info_->prototype == nullptr; +} + +#if defined(__cpp_lib_destroying_delete) && defined(__cpp_sized_deallocation) +void DynamicMessage::operator delete(DynamicMessage* msg, + std::destroying_delete_t) { + const size_t size = msg->type_info_->size; + msg->~DynamicMessage(); + ::operator delete(msg, size); +} +#endif + DynamicMessage::~DynamicMessage() { const Descriptor* descriptor = type_info_->type; - reinterpret_cast( - OffsetToPointer(type_info_->internal_metadata_offset)) - ->~InternalMetadataWithArena(); + _internal_metadata_.Delete(); if (type_info_->extensions_offset != -1) { reinterpret_cast( - OffsetToPointer(type_info_->extensions_offset))->~ExtensionSet(); + OffsetToPointer(type_info_->extensions_offset)) + ->~ExtensionSet(); } // We need to manually run the destructors for repeated fields and strings, @@ -451,24 +484,23 @@ DynamicMessage::~DynamicMessage() { // be touched. for (int i = 0; i < descriptor->field_count(); i++) { const FieldDescriptor* field = descriptor->field(i); - if (field->containing_oneof()) { - void* field_ptr = OffsetToPointer( - type_info_->oneof_case_offset - + sizeof(uint32) * field->containing_oneof()->index()); - if (*(reinterpret_cast(field_ptr)) == - field->number()) { - field_ptr = OffsetToPointer(type_info_->offsets[ - descriptor->field_count() + field->containing_oneof()->index()]); + if (InRealOneof(field)) { + void* field_ptr = + OffsetToPointer(type_info_->oneof_case_offset + + sizeof(uint32) * field->containing_oneof()->index()); + if (*(reinterpret_cast(field_ptr)) == field->number()) { + field_ptr = OffsetToPointer( + type_info_->offsets[descriptor->field_count() + + field->containing_oneof()->index()]); if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { switch (field->options().ctype()) { default: case FieldOptions::STRING: { - const ::std::string* default_value = - &(reinterpret_cast( - reinterpret_cast( - type_info_->prototype) + - type_info_->offsets[i]) - ->Get()); + // Oneof string fields are never set as a default instance. + // We just need to pass some arbitrary default string to make it + // work. This allows us to not have the real default accessible + // from reflection. + const std::string* default_value = nullptr; reinterpret_cast(field_ptr)->Destroy( default_value, NULL); break; @@ -484,28 +516,28 @@ DynamicMessage::~DynamicMessage() { if (field->is_repeated()) { switch (field->cpp_type()) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case FieldDescriptor::CPPTYPE_##UPPERCASE : \ - reinterpret_cast*>(field_ptr) \ - ->~RepeatedField(); \ - break - - HANDLE_TYPE( INT32, int32); - HANDLE_TYPE( INT64, int64); +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + reinterpret_cast*>(field_ptr) \ + ->~RepeatedField(); \ + break + + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); HANDLE_TYPE(UINT32, uint32); HANDLE_TYPE(UINT64, uint64); HANDLE_TYPE(DOUBLE, double); - HANDLE_TYPE( FLOAT, float); - HANDLE_TYPE( BOOL, bool); - HANDLE_TYPE( ENUM, int); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, int); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: - reinterpret_cast*>(field_ptr) - ->~RepeatedPtrField(); + reinterpret_cast*>(field_ptr) + ->~RepeatedPtrField(); break; } break; @@ -524,18 +556,18 @@ DynamicMessage::~DynamicMessage() { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { - const ::std::string* default_value = - &(reinterpret_cast( - type_info_->prototype->OffsetToPointer( - type_info_->offsets[i])) - ->Get()); - reinterpret_cast(field_ptr)->Destroy( - default_value, NULL); + const std::string* default_value = + reinterpret_cast( + type_info_->prototype->OffsetToPointer( + type_info_->offsets[i])) + ->GetPointer(); + reinterpret_cast(field_ptr)->Destroy(default_value, + NULL); break; } } } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - if (!is_prototype()) { + if (!is_prototype()) { Message* message = *reinterpret_cast(field_ptr); if (message != NULL) { delete message; @@ -557,44 +589,38 @@ void DynamicMessage::CrossLinkPrototypes() { const FieldDescriptor* field = descriptor->field(i); void* field_ptr = OffsetToPointer(type_info_->offsets[i]); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !field->options().weak() && !InRealOneof(field) && !field->is_repeated()) { // For fields with message types, we need to cross-link with the // prototype for the field's type. // For singular fields, the field is just a pointer which should // point to the prototype. *reinterpret_cast(field_ptr) = - factory->GetPrototypeNoLock(field->message_type()); + factory->GetPrototypeNoLock(field->message_type()); } } } -Message* DynamicMessage::New() const { - void* new_base = operator new(type_info_->size); - memset(new_base, 0, type_info_->size); - return new(new_base) DynamicMessage(type_info_); -} +Message* DynamicMessage::New() const { return New(NULL); } -Message* DynamicMessage::New(::google::protobuf::Arena* arena) const { +Message* DynamicMessage::New(Arena* arena) const { if (arena != NULL) { - Message* message = New(); - arena->Own(message); - return message; + void* new_base = Arena::CreateArray(arena, type_info_->size); + memset(new_base, 0, type_info_->size); + return new (new_base) DynamicMessage(type_info_, arena); } else { - return New(); + void* new_base = operator new(type_info_->size); + memset(new_base, 0, type_info_->size); + return new (new_base) DynamicMessage(type_info_); } } int DynamicMessage::GetCachedSize() const { - return cached_byte_size_; + return cached_byte_size_.load(std::memory_order_relaxed); } void DynamicMessage::SetCachedSize(int size) const { - // This is theoretically not thread-compatible, but in practice it works - // because if multiple threads write this simultaneously, they will be - // writing the exact same value. - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - cached_byte_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + cached_byte_size_.store(size, std::memory_order_relaxed); } Metadata DynamicMessage::GetMetadata() const { @@ -606,27 +632,14 @@ Metadata DynamicMessage::GetMetadata() const { // =================================================================== -struct DynamicMessageFactory::PrototypeMap { - typedef hash_map Map; - Map map_; -}; - DynamicMessageFactory::DynamicMessageFactory() - : pool_(NULL), delegate_to_generated_factory_(false), - prototypes_(new PrototypeMap) { -} + : pool_(nullptr), delegate_to_generated_factory_(false) {} DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool) - : pool_(pool), delegate_to_generated_factory_(false), - prototypes_(new PrototypeMap) { -} + : pool_(pool), delegate_to_generated_factory_(false) {} DynamicMessageFactory::~DynamicMessageFactory() { - for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin(); - iter != prototypes_->map_.end(); ++iter) { - DeleteDefaultOneofInstance(iter->second->type, - iter->second->offsets.get(), - iter->second->prototype); + for (auto iter = prototypes_.begin(); iter != prototypes_.end(); ++iter) { delete iter->second; } } @@ -643,30 +656,35 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( return MessageFactory::generated_factory()->GetPrototype(type); } - const DynamicMessage::TypeInfo** target = &prototypes_->map_[type]; + const TypeInfo** target = &prototypes_[type]; if (*target != NULL) { // Already exists. return (*target)->prototype; } - DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo; + TypeInfo* type_info = new TypeInfo; *target = type_info; type_info->type = type; type_info->pool = (pool_ == NULL) ? type->file()->pool() : pool_; type_info->factory = this; - // We need to construct all the structures passed to - // GeneratedMessageReflection's constructor. This includes: + // We need to construct all the structures passed to Reflection's constructor. + // This includes: // - A block of memory that contains space for all the message's fields. // - An array of integers indicating the byte offset of each field within // this block. // - A big bitfield containing a bit for each field indicating whether // or not that field is set. + int real_oneof_count = 0; + for (int i = 0; i < type->oneof_decl_count(); i++) { + if (!type->oneof_decl(i)->is_synthetic()) { + real_oneof_count++; + } + } // Compute size and offsets. - uint32* offsets = - new uint32[type->field_count() + type->oneof_decl_count()]; + uint32* offsets = new uint32[type->field_count() + real_oneof_count]; type_info->offsets.reset(offsets); // Decide all field offsets by packing in order. @@ -676,26 +694,35 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( size = AlignOffset(size); // Next the has_bits, which is an array of uint32s. - if (type->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { - type_info->has_bits_offset = -1; - } else { - type_info->has_bits_offset = size; - int has_bits_array_size = - DivideRoundingUp(type->field_count(), bitsizeof(uint32)); + type_info->has_bits_offset = -1; + int max_hasbit = 0; + for (int i = 0; i < type->field_count(); i++) { + if (HasHasbit(type->field(i))) { + if (type_info->has_bits_offset == -1) { + // At least one field in the message requires a hasbit, so allocate + // hasbits. + type_info->has_bits_offset = size; + uint32* has_bits_indices = new uint32[type->field_count()]; + for (int i = 0; i < type->field_count(); i++) { + // Initialize to -1, fields that need a hasbit will overwrite. + has_bits_indices[i] = static_cast(-1); + } + type_info->has_bits_indices.reset(has_bits_indices); + } + type_info->has_bits_indices[i] = max_hasbit++; + } + } + + if (max_hasbit > 0) { + int has_bits_array_size = DivideRoundingUp(max_hasbit, bitsizeof(uint32)); size += has_bits_array_size * sizeof(uint32); size = AlignOffset(size); - - uint32* has_bits_indices = new uint32[type->field_count()]; - for (int i = 0; i < type->field_count(); i++) { - has_bits_indices[i] = i; - } - type_info->has_bits_indices.reset(has_bits_indices); } // The oneof_case, if any. It is an array of uint32s. - if (type->oneof_decl_count() > 0) { + if (real_oneof_count > 0) { type_info->oneof_case_offset = size; - size += type->oneof_decl_count() * sizeof(uint32); + size += real_oneof_count * sizeof(uint32); size = AlignOffset(size); } @@ -712,11 +739,10 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( // All the fields. // // TODO(b/31226269): Optimize the order of fields to minimize padding. - int num_weak_fields = 0; for (int i = 0; i < type->field_count(); i++) { // Make sure field is aligned to avoid bus errors. // Oneof fields do not use any space. - if (!type->field(i)->containing_oneof()) { + if (!InRealOneof(type->field(i))) { int field_size = FieldSpaceUsed(type->field(i)); size = AlignTo(size, std::min(kSafeAlignment, field_size)); offsets[i] = size; @@ -726,75 +752,57 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( // The oneofs. for (int i = 0; i < type->oneof_decl_count(); i++) { - size = AlignTo(size, kSafeAlignment); - offsets[type->field_count() + i] = size; - size += kMaxOneofUnionSize; + if (!type->oneof_decl(i)->is_synthetic()) { + size = AlignTo(size, kSafeAlignment); + offsets[type->field_count() + i] = size; + size += kMaxOneofUnionSize; + } } - // Add the InternalMetadataWithArena to the end. - size = AlignOffset(size); - type_info->internal_metadata_offset = size; - size += sizeof(InternalMetadataWithArena); - type_info->weak_field_map_offset = -1; // Align the final size to make sure no clever allocators think that // alignment is not necessary. type_info->size = size; - // Construct the reflection object. - if (type->oneof_decl_count() > 0) { - // Compute the size of default oneof instance and offsets of default - // oneof fields. - for (int i = 0; i < type->oneof_decl_count(); i++) { - for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = type->oneof_decl(i)->field(j); - int field_size = OneofFieldSpaceUsed(field); - size = AlignTo(size, std::min(kSafeAlignment, field_size)); - offsets[field->index()] = size; - size += field_size; - } + // Compute the size of default oneof instance and offsets of default + // oneof fields. + for (int i = 0; i < type->oneof_decl_count(); i++) { + if (type->oneof_decl(i)->is_synthetic()) continue; + for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = type->oneof_decl(i)->field(j); + // oneof fields are not accessed through offsets, but we still have the + // entry from a legacy implementation. This should be removed at some + // point. + // Mark the field to prevent unintentional access through reflection. + // Don't use the top bit because that is for unused fields. + offsets[field->index()] = internal::kInvalidFieldOffsetTag; } } - size = AlignOffset(size); - // Allocate the prototype + oneof fields. + + // Allocate the prototype fields. void* base = operator new(size); memset(base, 0, size); - // The prototype in type_info has to be set before creating the prototype - // instance on memory. e.g., message Foo { map a = 1; }. When - // creating prototype for Foo, prototype of the map entry will also be - // created, which needs the address of the prototype of Foo (the value in - // map). To break the cyclic dependency, we have to assgin the address of - // prototype into type_info first. - type_info->prototype = static_cast(base); - // We have already locked the factory so we should not lock in the constructor // of dynamic message to avoid dead lock. DynamicMessage* prototype = new (base) DynamicMessage(type_info, false); - if (type->oneof_decl_count() > 0 || num_weak_fields > 0) { - // Construct default oneof instance. - ConstructDefaultOneofInstance(type_info->type, - type_info->offsets.get(), - prototype); - } - internal::ReflectionSchema schema = { type_info->prototype, type_info->offsets.get(), type_info->has_bits_indices.get(), type_info->has_bits_offset, - type_info->internal_metadata_offset, + PROTOBUF_FIELD_OFFSET(DynamicMessage, _internal_metadata_), type_info->extensions_offset, type_info->oneof_case_offset, type_info->size, type_info->weak_field_map_offset}; - type_info->reflection.reset(new GeneratedMessageReflection( - type_info->type, schema, type_info->pool, this)); + type_info->reflection.reset( + new Reflection(type_info->type, schema, type_info->pool, this)); // Cross link prototypes. prototype->CrossLinkPrototypes(); @@ -802,69 +810,7 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( return prototype; } -void DynamicMessageFactory::ConstructDefaultOneofInstance( - const Descriptor* type, - const uint32 offsets[], - void* default_oneof_or_weak_instance) { - for (int i = 0; i < type->oneof_decl_count(); i++) { - for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = type->oneof_decl(i)->field(j); - void* field_ptr = reinterpret_cast( - default_oneof_or_weak_instance) + offsets[field->index()]; - switch (field->cpp_type()) { -#define HANDLE_TYPE(CPPTYPE, TYPE) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - new(field_ptr) TYPE(field->default_value_##TYPE()); \ - break; - - HANDLE_TYPE(INT32 , int32 ); - HANDLE_TYPE(INT64 , int64 ); - HANDLE_TYPE(UINT32, uint32); - HANDLE_TYPE(UINT64, uint64); - HANDLE_TYPE(DOUBLE, double); - HANDLE_TYPE(FLOAT , float ); - HANDLE_TYPE(BOOL , bool ); -#undef HANDLE_TYPE - - case FieldDescriptor::CPPTYPE_ENUM: - new(field_ptr) int(field->default_value_enum()->number()); - break; - case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: - case FieldOptions::STRING: - ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr(); - asp->UnsafeSetDefault(&field->default_value_string()); - break; - } - break; - - case FieldDescriptor::CPPTYPE_MESSAGE: { - new(field_ptr) Message*(NULL); - break; - } - } - } - } -} - -void DynamicMessageFactory::DeleteDefaultOneofInstance( - const Descriptor* type, - const uint32 offsets[], - const void* default_oneof_instance) { - for (int i = 0; i < type->oneof_decl_count(); i++) { - for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = type->oneof_decl(i)->field(j); - if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { - switch (field->options().ctype()) { - default: - case FieldOptions::STRING: - break; - } - } - } - } -} - } // namespace protobuf } // namespace google + +#include // NOLINT diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h index e29b148d6a6b1..b85e00f3e8a18 100644 --- a/src/google/protobuf/dynamic_message.h +++ b/src/google/protobuf/dynamic_message.h @@ -40,22 +40,27 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif +#include #include -#include -#include #include +#include #include +#include +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +#include namespace google { namespace protobuf { // Defined in other files. -class Descriptor; // descriptor.h -class DescriptorPool; // descriptor.h +class Descriptor; // descriptor.h +class DescriptorPool; // descriptor.h // Constructs implementations of Message which can emulate types which are not // known at compile-time. @@ -74,7 +79,7 @@ class DescriptorPool; // descriptor.h // encapsulates this "cache". All DynamicMessages of the same type created // from the same factory will share the same support data. Any Descriptors // used with a particular factory must outlive the factory. -class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory { +class PROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory { public: // Construct a DynamicMessageFactory that will search for extensions in // the DescriptorPool in which the extendee is defined. @@ -118,62 +123,44 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory { // outlive the DynamicMessageFactory. // // The method is thread-safe. - const Message* GetPrototype(const Descriptor* type); + const Message* GetPrototype(const Descriptor* type) override; private: const DescriptorPool* pool_; bool delegate_to_generated_factory_; - // This struct just contains a hash_map. We can't #include from - // this header due to hacks needed for hash_map portability in the open source - // release. Namely, stubs/hash.h, which defines hash_map portably, is not a - // public header (for good reason), but dynamic_message.h is, and public - // headers may only #include other public headers. - struct PrototypeMap; - google::protobuf::scoped_ptr prototypes_; - mutable Mutex prototypes_mutex_; + struct TypeInfo; + std::unordered_map prototypes_; + mutable internal::WrappedMutex prototypes_mutex_; friend class DynamicMessage; const Message* GetPrototypeNoLock(const Descriptor* type); - // Construct default oneof instance for reflection usage if oneof - // is defined. - static void ConstructDefaultOneofInstance(const Descriptor* type, - const uint32 offsets[], - void* default_oneof_instance); - // Delete default oneof instance. Called by ~DynamicMessageFactory. - static void DeleteDefaultOneofInstance(const Descriptor* type, - const uint32 offsets[], - const void* default_oneof_instance); - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory); }; // Helper for computing a sorted list of map entries via reflection. -class LIBPROTOBUF_EXPORT DynamicMapSorter { +class PROTOBUF_EXPORT DynamicMapSorter { public: - static std::vector Sort(const Message& message, - int map_size, + static std::vector Sort(const Message& message, int map_size, const Reflection* reflection, const FieldDescriptor* field) { - std::vector result(static_cast(map_size)); - const RepeatedPtrField& map_field = - reflection->GetRepeatedPtrField(message, field); - size_t i = 0; - for (RepeatedPtrField::const_pointer_iterator it = - map_field.pointer_begin(); it != map_field.pointer_end(); ) { - result[i++] = *it++; + std::vector result; + result.reserve(map_size); + RepeatedFieldRef map_field = + reflection->GetRepeatedFieldRef(message, field); + for (auto it = map_field.begin(); it != map_field.end(); ++it) { + result.push_back(&*it); } - GOOGLE_DCHECK_EQ(result.size(), i); MapEntryMessageComparator comparator(field->message_type()); std::stable_sort(result.begin(), result.end(), comparator); // Complain if the keys aren't in ascending order. #ifndef NDEBUG for (size_t j = 1; j < static_cast(map_size); j++) { if (!comparator(result[j - 1], result[j])) { - GOOGLE_LOG(ERROR) << (comparator(result[j], result[j - 1]) ? - "internal error in map key sorting" : - "map keys are not unique"); + GOOGLE_LOG(ERROR) << (comparator(result[j], result[j - 1]) + ? "internal error in map key sorting" + : "map keys are not unique"); } } #endif @@ -181,7 +168,7 @@ class LIBPROTOBUF_EXPORT DynamicMapSorter { } private: - class LIBPROTOBUF_EXPORT MapEntryMessageComparator { + class PROTOBUF_EXPORT MapEntryMessageComparator { public: explicit MapEntryMessageComparator(const Descriptor* descriptor) : field_(descriptor->field(0)) {} @@ -215,8 +202,8 @@ class LIBPROTOBUF_EXPORT DynamicMapSorter { return first < second; } case FieldDescriptor::CPPTYPE_STRING: { - string first = reflection->GetString(*a, field_); - string second = reflection->GetString(*b, field_); + std::string first = reflection->GetString(*a, field_); + std::string second = reflection->GetString(*b, field_); return first < second; } default: @@ -231,6 +218,8 @@ class LIBPROTOBUF_EXPORT DynamicMapSorter { }; } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ diff --git a/src/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc index fe51d8cfdc37e..37f9574b0b0b5 100644 --- a/src/google/protobuf/dynamic_message_unittest.cc +++ b/src/google/protobuf/dynamic_message_unittest.cc @@ -41,16 +41,13 @@ // DynamicMessage. #include -#ifndef _SHARED_PTR_H -#include -#endif -#include -#include -#include #include #include #include +#include +#include +#include #include #include @@ -60,7 +57,7 @@ namespace google { namespace protobuf { -class DynamicMessageTest : public testing::Test { +class DynamicMessageTest : public ::testing::TestWithParam { protected: DescriptorPool pool_; DynamicMessageFactory factory_; @@ -75,7 +72,7 @@ class DynamicMessageTest : public testing::Test { const Descriptor* proto3_descriptor_; const Message* proto3_prototype_; - DynamicMessageTest(): factory_(&pool_) {} + DynamicMessageTest() : factory_(&pool_) {} virtual void SetUp() { // We want to make sure that DynamicMessage works (particularly with @@ -89,11 +86,11 @@ class DynamicMessageTest : public testing::Test { unittest::TestAllTypes::descriptor()->file()->CopyTo(&unittest_file); unittest_import::ImportMessage::descriptor()->file()->CopyTo( - &unittest_import_file); + &unittest_import_file); unittest_import::PublicImportMessage::descriptor()->file()->CopyTo( - &unittest_import_public_file); - proto2_nofieldpresence_unittest::TestAllTypes::descriptor()-> - file()->CopyTo(&unittest_no_field_presence_file); + &unittest_import_public_file); + proto2_nofieldpresence_unittest::TestAllTypes::descriptor()->file()->CopyTo( + &unittest_no_field_presence_file); ASSERT_TRUE(pool_.BuildFile(unittest_import_public_file) != NULL); ASSERT_TRUE(pool_.BuildFile(unittest_import_file) != NULL); @@ -105,23 +102,22 @@ class DynamicMessageTest : public testing::Test { prototype_ = factory_.GetPrototype(descriptor_); extensions_descriptor_ = - pool_.FindMessageTypeByName("protobuf_unittest.TestAllExtensions"); + pool_.FindMessageTypeByName("protobuf_unittest.TestAllExtensions"); ASSERT_TRUE(extensions_descriptor_ != NULL); extensions_prototype_ = factory_.GetPrototype(extensions_descriptor_); packed_descriptor_ = - pool_.FindMessageTypeByName("protobuf_unittest.TestPackedTypes"); + pool_.FindMessageTypeByName("protobuf_unittest.TestPackedTypes"); ASSERT_TRUE(packed_descriptor_ != NULL); packed_prototype_ = factory_.GetPrototype(packed_descriptor_); oneof_descriptor_ = - pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2"); + pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2"); ASSERT_TRUE(oneof_descriptor_ != NULL); oneof_prototype_ = factory_.GetPrototype(oneof_descriptor_); - proto3_descriptor_ = - pool_.FindMessageTypeByName( - "proto2_nofieldpresence_unittest.TestAllTypes"); + proto3_descriptor_ = pool_.FindMessageTypeByName( + "proto2_nofieldpresence_unittest.TestAllTypes"); ASSERT_TRUE(proto3_descriptor_ != NULL); proto3_prototype_ = factory_.GetPrototype(proto3_descriptor_); } @@ -144,54 +140,72 @@ TEST_F(DynamicMessageTest, Defaults) { reflection_tester.ExpectClearViaReflection(*prototype_); } -TEST_F(DynamicMessageTest, IndependentOffsets) { +TEST_P(DynamicMessageTest, IndependentOffsets) { // Check that all fields have independent offsets by setting each // one to a unique value then checking that they all still have those // unique values (i.e. they don't stomp each other). - google::protobuf::scoped_ptr message(prototype_->New()); + Arena arena; + Message* message = prototype_->New(GetParam() ? &arena : NULL); TestUtil::ReflectionTester reflection_tester(descriptor_); - reflection_tester.SetAllFieldsViaReflection(message.get()); + reflection_tester.SetAllFieldsViaReflection(message); reflection_tester.ExpectAllFieldsSetViaReflection(*message); + + if (!GetParam()) { + delete message; + } } -TEST_F(DynamicMessageTest, Extensions) { +TEST_P(DynamicMessageTest, Extensions) { // Check that extensions work. - google::protobuf::scoped_ptr message(extensions_prototype_->New()); + Arena arena; + Message* message = extensions_prototype_->New(GetParam() ? &arena : NULL); TestUtil::ReflectionTester reflection_tester(extensions_descriptor_); - reflection_tester.SetAllFieldsViaReflection(message.get()); + reflection_tester.SetAllFieldsViaReflection(message); reflection_tester.ExpectAllFieldsSetViaReflection(*message); + + if (!GetParam()) { + delete message; + } } -TEST_F(DynamicMessageTest, PackedFields) { +TEST_P(DynamicMessageTest, PackedFields) { // Check that packed fields work properly. - google::protobuf::scoped_ptr message(packed_prototype_->New()); + Arena arena; + Message* message = packed_prototype_->New(GetParam() ? &arena : NULL); TestUtil::ReflectionTester reflection_tester(packed_descriptor_); - reflection_tester.SetPackedFieldsViaReflection(message.get()); + reflection_tester.SetPackedFieldsViaReflection(message); reflection_tester.ExpectPackedFieldsSetViaReflection(*message); + + if (!GetParam()) { + delete message; + } } -TEST_F(DynamicMessageTest, Oneof) { +TEST_P(DynamicMessageTest, Oneof) { // Check that oneof fields work properly. - google::protobuf::scoped_ptr message(oneof_prototype_->New()); + Arena arena; + Message* message = oneof_prototype_->New(GetParam() ? &arena : NULL); // Check default values. const Descriptor* descriptor = message->GetDescriptor(); const Reflection* reflection = message->GetReflection(); - EXPECT_EQ(0, reflection->GetInt32( - *message, descriptor->FindFieldByName("foo_int"))); - EXPECT_EQ("", reflection->GetString( - *message, descriptor->FindFieldByName("foo_string"))); + EXPECT_EQ(0, reflection->GetInt32(*message, + descriptor->FindFieldByName("foo_int"))); EXPECT_EQ("", reflection->GetString( - *message, descriptor->FindFieldByName("foo_cord"))); + *message, descriptor->FindFieldByName("foo_string"))); + EXPECT_EQ("", reflection->GetString(*message, + descriptor->FindFieldByName("foo_cord"))); EXPECT_EQ("", reflection->GetString( - *message, descriptor->FindFieldByName("foo_string_piece"))); + *message, descriptor->FindFieldByName("foo_string_piece"))); EXPECT_EQ("", reflection->GetString( - *message, descriptor->FindFieldByName("foo_bytes"))); - EXPECT_EQ(unittest::TestOneof2::FOO, reflection->GetEnum( - *message, descriptor->FindFieldByName("foo_enum"))->number()); + *message, descriptor->FindFieldByName("foo_bytes"))); + EXPECT_EQ( + unittest::TestOneof2::FOO, + reflection->GetEnum(*message, descriptor->FindFieldByName("foo_enum")) + ->number()); const Descriptor* nested_descriptor; const Message* nested_prototype; nested_descriptor = @@ -206,49 +220,69 @@ TEST_F(DynamicMessageTest, Oneof) { pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2.FooGroup"); foogroup_prototype = factory_.GetPrototype(foogroup_descriptor); EXPECT_EQ(foogroup_prototype, - &reflection->GetMessage( - *message, descriptor->FindFieldByName("foogroup"))); + &reflection->GetMessage(*message, + descriptor->FindFieldByName("foogroup"))); EXPECT_NE(foogroup_prototype, &reflection->GetMessage( *message, descriptor->FindFieldByName("foo_lazy_message"))); - EXPECT_EQ(5, reflection->GetInt32( - *message, descriptor->FindFieldByName("bar_int"))); + EXPECT_EQ(5, reflection->GetInt32(*message, + descriptor->FindFieldByName("bar_int"))); EXPECT_EQ("STRING", reflection->GetString( - *message, descriptor->FindFieldByName("bar_string"))); + *message, descriptor->FindFieldByName("bar_string"))); EXPECT_EQ("CORD", reflection->GetString( - *message, descriptor->FindFieldByName("bar_cord"))); - EXPECT_EQ("SPIECE", reflection->GetString( - *message, descriptor->FindFieldByName("bar_string_piece"))); + *message, descriptor->FindFieldByName("bar_cord"))); + EXPECT_EQ("SPIECE", + reflection->GetString( + *message, descriptor->FindFieldByName("bar_string_piece"))); EXPECT_EQ("BYTES", reflection->GetString( - *message, descriptor->FindFieldByName("bar_bytes"))); - EXPECT_EQ(unittest::TestOneof2::BAR, reflection->GetEnum( - *message, descriptor->FindFieldByName("bar_enum"))->number()); + *message, descriptor->FindFieldByName("bar_bytes"))); + EXPECT_EQ( + unittest::TestOneof2::BAR, + reflection->GetEnum(*message, descriptor->FindFieldByName("bar_enum")) + ->number()); // Check set functions. TestUtil::ReflectionTester reflection_tester(oneof_descriptor_); - reflection_tester.SetOneofViaReflection(message.get()); + reflection_tester.SetOneofViaReflection(message); reflection_tester.ExpectOneofSetViaReflection(*message); + + if (!GetParam()) { + delete message; + } } -TEST_F(DynamicMessageTest, SpaceUsed) { - // Test that SpaceUsed() works properly +TEST_P(DynamicMessageTest, SpaceUsed) { + // Test that SpaceUsedLong() works properly // Since we share the implementation with generated messages, we don't need // to test very much here. Just make sure it appears to be working. - google::protobuf::scoped_ptr message(prototype_->New()); + Arena arena; + Message* message = prototype_->New(GetParam() ? &arena : NULL); TestUtil::ReflectionTester reflection_tester(descriptor_); - int initial_space_used = message->SpaceUsed(); + size_t initial_space_used = message->SpaceUsedLong(); - reflection_tester.SetAllFieldsViaReflection(message.get()); - EXPECT_LT(initial_space_used, message->SpaceUsed()); + reflection_tester.SetAllFieldsViaReflection(message); + EXPECT_LT(initial_space_used, message->SpaceUsedLong()); + + if (!GetParam()) { + delete message; + } } TEST_F(DynamicMessageTest, Arena) { Arena arena; Message* message = prototype_->New(&arena); - (void)message; // avoid unused-variable error. + Message* extension_message = extensions_prototype_->New(&arena); + Message* packed_message = packed_prototype_->New(&arena); + Message* oneof_message = oneof_prototype_->New(&arena); + + // avoid unused-variable error. + (void)message; + (void)extension_message; + (void)packed_message; + (void)oneof_message; // Return without freeing: should not leak. } @@ -257,7 +291,7 @@ TEST_F(DynamicMessageTest, Proto3) { const Reflection* refl = message->GetReflection(); const Descriptor* desc = message->GetDescriptor(); - // Just test a single primtive and single message field here to make sure we + // Just test a single primitive and single message field here to make sure we // are getting the no-field-presence semantics elsewhere. DynamicMessage uses // GeneratedMessageReflection under the hood, so the rest should be fine as // long as GMR recognizes that we're using a proto3 message. @@ -286,6 +320,7 @@ TEST_F(DynamicMessageTest, Proto3) { delete message; } +INSTANTIATE_TEST_SUITE_P(UseArena, DynamicMessageTest, ::testing::Bool()); } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc index 6d2ea338aadde..42d7f3be06c0f 100644 --- a/src/google/protobuf/empty.pb.cc +++ b/src/google/protobuf/empty.pb.cc @@ -1,262 +1,160 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/empty.proto -#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include #include -#include -#include -#include #include -#include +#include +#include #include #include #include #include // @@protoc_insertion_point(includes) - -namespace google { -namespace protobuf { -class EmptyDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _Empty_default_instance_; - -namespace protobuf_google_2fprotobuf_2fempty_2eproto { - - -namespace { - -::google::protobuf::Metadata file_level_metadata[1]; - -} // namespace - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField - const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0}, -}; - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField - const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - ::google::protobuf::internal::AuxillaryParseTableField(), -}; -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const - TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, +#include + +PROTOBUF_PRAGMA_INIT_SEG +PROTOBUF_NAMESPACE_OPEN +constexpr Empty::Empty( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized){} +struct EmptyDefaultTypeInternal { + constexpr EmptyDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~EmptyDefaultTypeInternal() {} + union { + Empty _instance; + }; }; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EmptyDefaultTypeInternal _Empty_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fempty_2eproto[1]; +static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr; -const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { +const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fempty_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { ~0u, // no _has_bits_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Empty, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Empty, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ }; -static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { 0, -1, sizeof(Empty)}, +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, sizeof(PROTOBUF_NAMESPACE_ID::Empty)}, }; -static ::google::protobuf::Message const * const file_default_instances[] = { - reinterpret_cast(&_Empty_default_instance_), +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_Empty_default_instance_), }; -namespace { - -void protobuf_AssignDescriptors() { - AddDescriptors(); - ::google::protobuf::MessageFactory* factory = NULL; - AssignDescriptors( - "google/protobuf/empty.proto", schemas, file_default_instances, TableStruct::offsets, factory, - file_level_metadata, NULL, NULL); -} - -void protobuf_AssignDescriptorsOnce() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors); -} - -void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; -void protobuf_RegisterTypes(const ::std::string&) { - protobuf_AssignDescriptorsOnce(); - ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1); -} - -} // namespace -void TableStruct::InitDefaultsImpl() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - ::google::protobuf::internal::InitProtobufDefaults(); - _Empty_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_Empty_default_instance_);} - -void InitDefaults() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl); -} -namespace { -void AddDescriptorsImpl() { - InitDefaults(); - static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - "\n\033google/protobuf/empty.proto\022\017google.pr" - "otobuf\"\007\n\005EmptyBv\n\023com.google.protobufB\n" - "EmptyProtoP\001Z\'github.com/golang/protobuf" - "/ptypes/empty\370\001\001\242\002\003GPB\252\002\036Google.Protobuf" - ".WellKnownTypesb\006proto3" - }; - ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( - descriptor, 183); - ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( - "google/protobuf/empty.proto", &protobuf_RegisterTypes); -} -} // anonymous namespace - -void AddDescriptors() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl); +const char descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\033google/protobuf/empty.proto\022\017google.pr" + "otobuf\"\007\n\005EmptyB}\n\023com.google.protobufB\n" + "EmptyProtoP\001Z.google.golang.org/protobuf" + "/types/known/emptypb\370\001\001\242\002\003GPB\252\002\036Google.P" + "rotobuf.WellKnownTypesb\006proto3" + ; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fempty_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto = { + false, false, 190, descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto, "google/protobuf/empty.proto", + &descriptor_table_google_2fprotobuf_2fempty_2eproto_once, nullptr, 0, 1, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fempty_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fempty_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto, file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata +descriptor_table_google_2fprotobuf_2fempty_2eproto_metadata_getter(int index) { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fempty_2eproto); + return descriptor_table_google_2fprotobuf_2fempty_2eproto.file_level_metadata[index]; } -// Force AddDescriptors() to be called at dynamic initialization time. -struct StaticDescriptorInitializer { - StaticDescriptorInitializer() { - AddDescriptors(); - } -} static_descriptor_initializer; - -} // namespace protobuf_google_2fprotobuf_2fempty_2eproto +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fempty_2eproto(&descriptor_table_google_2fprotobuf_2fempty_2eproto); +PROTOBUF_NAMESPACE_OPEN // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +class Empty::_Internal { + public: +}; -Empty::Empty() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fempty_2eproto::InitDefaults(); - } - SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.Empty) -} -Empty::Empty(::google::protobuf::Arena* arena) - : ::google::protobuf::Message(), - _internal_metadata_(arena) { - protobuf_google_2fprotobuf_2fempty_2eproto::InitDefaults(); +Empty::Empty(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); RegisterArenaDtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Empty) } Empty::Empty(const Empty& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); // @@protoc_insertion_point(copy_constructor:google.protobuf.Empty) } void Empty::SharedCtor() { - _cached_size_ = 0; } Empty::~Empty() { // @@protoc_insertion_point(destructor:google.protobuf.Empty) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void Empty::SharedDtor() { - ::google::protobuf::Arena* arena = GetArenaNoVirtual(); - GOOGLE_DCHECK(arena == NULL); - if (arena != NULL) { - return; - } - + GOOGLE_DCHECK(GetArena() == nullptr); } void Empty::ArenaDtor(void* object) { Empty* _this = reinterpret_cast< Empty* >(object); (void)_this; } -void Empty::RegisterArenaDtor(::google::protobuf::Arena* arena) { +void Empty::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } void Empty::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* Empty::descriptor() { - protobuf_google_2fprotobuf_2fempty_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fempty_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const Empty& Empty::default_instance() { - protobuf_google_2fprotobuf_2fempty_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -Empty* Empty::New(::google::protobuf::Arena* arena) const { - return ::google::protobuf::Arena::CreateMessage(arena); + _cached_size_.Set(size); } void Empty::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Empty) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - _internal_metadata_.Clear(); -} - -bool Empty::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.Empty) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - handle_unusual: - if (tag == 0) { - goto success; - } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Empty::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.Empty) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.Empty) - return false; -#undef DO_ -} - -void Empty::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.Empty) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.Empty) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* Empty::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* Empty::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Empty) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Empty) return target; @@ -266,27 +164,28 @@ size_t Empty::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Empty) size_t total_size = 0; - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void Empty::MergeFrom(const ::google::protobuf::Message& from) { +void Empty::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Empty) GOOGLE_DCHECK_NE(&from, this); const Empty* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Empty) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Empty) MergeFrom(*source); @@ -296,13 +195,13 @@ void Empty::MergeFrom(const ::google::protobuf::Message& from) { void Empty::MergeFrom(const Empty& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Empty) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; } -void Empty::CopyFrom(const ::google::protobuf::Message& from) { +void Empty::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Empty) if (&from == this) return; Clear(); @@ -320,44 +219,23 @@ bool Empty::IsInitialized() const { return true; } -void Empty::Swap(Empty* other) { - if (other == this) return; - if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { - InternalSwap(other); - } else { - Empty* temp = New(GetArenaNoVirtual()); - temp->MergeFrom(*other); - other->CopyFrom(*this); - InternalSwap(temp); - if (GetArenaNoVirtual() == NULL) { - delete temp; - } - } -} -void Empty::UnsafeArenaSwap(Empty* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); - InternalSwap(other); -} void Empty::InternalSwap(Empty* other) { using std::swap; - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); } -::google::protobuf::Metadata Empty::GetMetadata() const { - protobuf_google_2fprotobuf_2fempty_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fempty_2eproto::file_level_metadata[kIndexInFileMessages]; +::PROTOBUF_NAMESPACE_ID::Metadata Empty::GetMetadata() const { + return GetMetadataStatic(); } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// Empty - -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::Empty* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::Empty >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::Empty >(arena); +} +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) +#include diff --git a/src/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h index 1c6e53e6d4511..8de6f1c0f45a7 100644 --- a/src/google/protobuf/empty.pb.h +++ b/src/google/protobuf/empty.pb.h @@ -1,151 +1,178 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/empty.proto -#ifndef PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED -#define PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto +#include #include -#include - -#if GOOGLE_PROTOBUF_VERSION < 3004000 +#include +#if PROTOBUF_VERSION < 3015000 #error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update +#error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 3015000 < PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please +#error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif +#include #include #include #include #include #include -#include +#include +#include #include #include // IWYU pragma: export #include // IWYU pragma: export #include // @@protoc_insertion_point(includes) -namespace google { -namespace protobuf { -class Empty; -class EmptyDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern EmptyDefaultTypeInternal _Empty_default_instance_; -} // namespace protobuf -} // namespace google - -namespace google { -namespace protobuf { - -namespace protobuf_google_2fprotobuf_2fempty_2eproto { -// Internal implementation detail -- do not call these. -struct LIBPROTOBUF_EXPORT TableStruct { - static const ::google::protobuf::internal::ParseTableField entries[]; - static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; - static const ::google::protobuf::internal::ParseTable schema[]; - static const ::google::protobuf::uint32 offsets[]; - static const ::google::protobuf::internal::FieldMetadata field_metadata[]; - static const ::google::protobuf::internal::SerializationTable serialization_table[]; - static void InitDefaultsImpl(); +#include +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fempty_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fempty_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; }; -void LIBPROTOBUF_EXPORT AddDescriptors(); -void LIBPROTOBUF_EXPORT InitDefaults(); -} // namespace protobuf_google_2fprotobuf_2fempty_2eproto +extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto; +PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fempty_2eproto_metadata_getter(int index); +PROTOBUF_NAMESPACE_OPEN +class Empty; +struct EmptyDefaultTypeInternal; +PROTOBUF_EXPORT extern EmptyDefaultTypeInternal _Empty_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::Empty* Arena::CreateMaybeMessage(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN // =================================================================== -class LIBPROTOBUF_EXPORT Empty : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Empty) */ { +class PROTOBUF_EXPORT Empty PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Empty) */ { public: - Empty(); + inline Empty() : Empty(nullptr) {} virtual ~Empty(); + explicit constexpr Empty(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); Empty(const Empty& from); - - inline Empty& operator=(const Empty& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 Empty(Empty&& from) noexcept : Empty() { *this = ::std::move(from); } + inline Empty& operator=(const Empty& from) { + CopyFrom(from); + return *this; + } inline Empty& operator=(Empty&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL { - return GetArenaNoVirtual(); + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); } - inline void* GetMaybeArenaPointer() const PROTOBUF_FINAL { - return MaybeArenaPtr(); + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const Empty& default_instance() { + return *internal_default_instance(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const Empty& default_instance(); - static inline const Empty* internal_default_instance() { return reinterpret_cast( &_Empty_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 0; - void UnsafeArenaSwap(Empty* other); - void Swap(Empty* other); friend void swap(Empty& a, Empty& b) { a.Swap(&b); } + inline void Swap(Empty* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Empty* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline Empty* New() const PROTOBUF_FINAL { return New(NULL); } + inline Empty* New() const final { + return CreateMaybeMessage(nullptr); + } - Empty* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + Empty* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const Empty& from); void MergeFrom(const Empty& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(Empty* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Empty"; + } protected: - explicit Empty(::google::protobuf::Arena* arena); + explicit Empty(::PROTOBUF_NAMESPACE_ID::Arena* arena); private: static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::google::protobuf::Arena* arena); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return _internal_metadata_.arena(); - } - inline void* MaybeArenaPtr() const { - return _internal_metadata_.raw_arena_ptr(); + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fempty_2eproto_metadata_getter(kIndexInFileMessages); } - public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + public: // nested types ---------------------------------------------------- @@ -153,20 +180,19 @@ class LIBPROTOBUF_EXPORT Empty : public ::google::protobuf::Message /* @@protoc_ // @@protoc_insertion_point(class_scope:google.protobuf.Empty) private: + class _Internal; - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - template friend class ::google::protobuf::Arena::InternalHelper; + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; - mutable int _cached_size_; - friend struct protobuf_google_2fprotobuf_2fempty_2eproto::TableStruct; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2fempty_2eproto; }; // =================================================================== // =================================================================== -#if !PROTOBUF_INLINE_NOT_IN_HEADERS #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" @@ -176,14 +202,12 @@ class LIBPROTOBUF_EXPORT Empty : public ::google::protobuf::Message /* @@protoc_ #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ -#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) -#endif // PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto diff --git a/src/google/protobuf/empty.proto b/src/google/protobuf/empty.proto index 03cacd233088d..5f992de94ab46 100644 --- a/src/google/protobuf/empty.proto +++ b/src/google/protobuf/empty.proto @@ -33,7 +33,7 @@ syntax = "proto3"; package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option go_package = "github.com/golang/protobuf/ptypes/empty"; +option go_package = "google.golang.org/protobuf/types/known/emptypb"; option java_package = "com.google.protobuf"; option java_outer_classname = "EmptyProto"; option java_multiple_files = true; diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 955c079bddcd9..bc53480794756 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -32,15 +32,23 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include -#include -#include #include -#include + +#include +#include +#include +#include +#include +#include #include -#include +#include +#include +#include #include #include +#include + +#include namespace google { namespace protobuf { @@ -68,48 +76,47 @@ inline bool is_packable(WireFormatLite::WireType type) { case WireFormatLite::WIRETYPE_END_GROUP: return false; - // Do not add a default statement. Let the compiler complain when someone - // adds a new wire type. + // Do not add a default statement. Let the compiler complain when someone + // adds a new wire type. } GOOGLE_LOG(FATAL) << "can't reach here."; return false; } // Registry stuff. -typedef hash_map, - ExtensionInfo> ExtensionRegistry; -ExtensionRegistry* registry_ = NULL; -GOOGLE_PROTOBUF_DECLARE_ONCE(registry_init_); +struct ExtensionHasher { + std::size_t operator()(const std::pair& p) const { + return std::hash{}(p.first) ^ + std::hash{}(p.second); + } +}; -void DeleteRegistry() { - delete registry_; - registry_ = NULL; -} +typedef std::unordered_map, ExtensionInfo, + ExtensionHasher> + ExtensionRegistry; -void InitRegistry() { - registry_ = new ExtensionRegistry; - OnShutdown(&DeleteRegistry); -} +static const ExtensionRegistry* global_registry = nullptr; // This function is only called at startup, so there is no need for thread- // safety. -void Register(const MessageLite* containing_type, - int number, ExtensionInfo info) { - ::google::protobuf::GoogleOnceInit(®istry_init_, &InitRegistry); - - if (!InsertIfNotPresent(registry_, std::make_pair(containing_type, number), - info)) { +void Register(const MessageLite* containing_type, int number, + ExtensionInfo info) { + static auto local_static_registry = OnShutdownDelete(new ExtensionRegistry); + global_registry = local_static_registry; + if (!InsertIfNotPresent(local_static_registry, + std::make_pair(containing_type, number), info)) { GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \"" - << containing_type->GetTypeName() - << "\", field number " << number << "."; + << containing_type->GetTypeName() << "\", field number " + << number << "."; } } -const ExtensionInfo* FindRegisteredExtension( - const MessageLite* containing_type, int number) { - return (registry_ == NULL) - ? NULL - : FindOrNull(*registry_, std::make_pair(containing_type, number)); +const ExtensionInfo* FindRegisteredExtension(const MessageLite* containing_type, + int number) { + return global_registry == nullptr + ? nullptr + : FindOrNull(*global_registry, + std::make_pair(containing_type, number)); } } // namespace @@ -169,78 +176,92 @@ void ExtensionSet::RegisterMessageExtension(const MessageLite* containing_type, GOOGLE_CHECK(type == WireFormatLite::TYPE_MESSAGE || type == WireFormatLite::TYPE_GROUP); ExtensionInfo info(type, is_repeated, is_packed); - info.message_prototype = prototype; + info.message_info = {prototype}; Register(containing_type, number, info); } - // =================================================================== // Constructors and basic methods. -ExtensionSet::ExtensionSet(::google::protobuf::Arena* arena) - : arena_(arena) { - if (arena_ != NULL) { - arena_->OwnDestructor(&extensions_); - } -} - -ExtensionSet::ExtensionSet() : arena_(NULL) {} +ExtensionSet::ExtensionSet(Arena* arena) + : arena_(arena), + flat_capacity_(0), + flat_size_(0), + map_{flat_capacity_ == 0 + ? NULL + : Arena::CreateArray(arena_, flat_capacity_)} {} ExtensionSet::~ExtensionSet() { // Deletes all allocated extensions. if (arena_ == NULL) { - for (ExtensionMap::iterator iter = extensions_.begin(); - iter != extensions_.end(); ++iter) { - iter->second.Free(); + ForEach([](int /* number */, Extension& ext) { ext.Free(); }); + if (PROTOBUF_PREDICT_FALSE(is_large())) { + delete map_.large; + } else { + DeleteFlatMap(map_.flat, flat_capacity_); } } } +void ExtensionSet::DeleteFlatMap(const ExtensionSet::KeyValue* flat, + uint16 flat_capacity) { +#ifdef __cpp_sized_deallocation + // Arena::CreateArray already requires a trivially destructible type, but + // ensure this constraint is not violated in the future. + static_assert(std::is_trivially_destructible::value, + "CreateArray requires a trivially destructible type"); + // A const-cast is needed, but this is safe as we are about to deallocate the + // array. + ::operator delete[](const_cast(flat), + sizeof(*flat) * flat_capacity); +#else // !__cpp_sized_deallocation + delete[] flat; +#endif // !__cpp_sized_deallocation +} + // Defined in extension_set_heavy.cc. // void ExtensionSet::AppendToList(const Descriptor* containing_type, // const DescriptorPool* pool, // vector* output) const bool ExtensionSet::Has(int number) const { - ExtensionMap::const_iterator iter = extensions_.find(number); - if (iter == extensions_.end()) return false; - GOOGLE_DCHECK(!iter->second.is_repeated); - return !iter->second.is_cleared; + const Extension* ext = FindOrNull(number); + if (ext == NULL) return false; + GOOGLE_DCHECK(!ext->is_repeated); + return !ext->is_cleared; } int ExtensionSet::NumExtensions() const { int result = 0; - for (ExtensionMap::const_iterator iter = extensions_.begin(); - iter != extensions_.end(); ++iter) { - if (!iter->second.is_cleared) { + ForEach([&result](int /* number */, const Extension& ext) { + if (!ext.is_cleared) { ++result; } - } + }); return result; } int ExtensionSet::ExtensionSize(int number) const { - ExtensionMap::const_iterator iter = extensions_.find(number); - if (iter == extensions_.end()) return false; - return iter->second.GetSize(); + const Extension* ext = FindOrNull(number); + return ext == NULL ? 0 : ext->GetSize(); } FieldType ExtensionSet::ExtensionType(int number) const { - ExtensionMap::const_iterator iter = extensions_.find(number); - if (iter == extensions_.end()) { + const Extension* ext = FindOrNull(number); + if (ext == NULL) { GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (1). "; return 0; } - if (iter->second.is_cleared) { + if (ext->is_cleared) { GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (2). "; } - return iter->second.type; + return ext->type; } void ExtensionSet::ClearExtension(int number) { - ExtensionMap::iterator iter = extensions_.find(number); - if (iter == extensions_.end()) return; - iter->second.Clear(); + Extension* ext = FindOrNull(number); + if (ext == NULL) return; + ext->Clear(); } // =================================================================== @@ -248,100 +269,100 @@ void ExtensionSet::ClearExtension(int number) { namespace { -enum Cardinality { - REPEATED, - OPTIONAL -}; +enum { REPEATED_FIELD, OPTIONAL_FIELD }; } // namespace -#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \ - GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? REPEATED : OPTIONAL, LABEL); \ +#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \ + GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? REPEATED_FIELD : OPTIONAL_FIELD, LABEL); \ GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), WireFormatLite::CPPTYPE_##CPPTYPE) // ------------------------------------------------------------------- // Primitives -#define PRIMITIVE_ACCESSORS(UPPERCASE, LOWERCASE, CAMELCASE) \ - \ -LOWERCASE ExtensionSet::Get##CAMELCASE(int number, \ - LOWERCASE default_value) const { \ - ExtensionMap::const_iterator iter = extensions_.find(number); \ - if (iter == extensions_.end() || iter->second.is_cleared) { \ - return default_value; \ - } else { \ - GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, UPPERCASE); \ - return iter->second.LOWERCASE##_value; \ - } \ -} \ - \ -void ExtensionSet::Set##CAMELCASE(int number, FieldType type, \ - LOWERCASE value, \ - const FieldDescriptor* descriptor) { \ - Extension* extension; \ - if (MaybeNewExtension(number, descriptor, &extension)) { \ - extension->type = type; \ - GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \ - extension->is_repeated = false; \ - } else { \ - GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, UPPERCASE); \ - } \ - extension->is_cleared = false; \ - extension->LOWERCASE##_value = value; \ -} \ - \ -LOWERCASE ExtensionSet::GetRepeated##CAMELCASE(int number, int index) const { \ - ExtensionMap::const_iterator iter = extensions_.find(number); \ - GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; \ - GOOGLE_DCHECK_TYPE(iter->second, REPEATED, UPPERCASE); \ - return iter->second.repeated_##LOWERCASE##_value->Get(index); \ -} \ - \ -void ExtensionSet::SetRepeated##CAMELCASE( \ - int number, int index, LOWERCASE value) { \ - ExtensionMap::iterator iter = extensions_.find(number); \ - GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; \ - GOOGLE_DCHECK_TYPE(iter->second, REPEATED, UPPERCASE); \ - iter->second.repeated_##LOWERCASE##_value->Set(index, value); \ -} \ - \ -void ExtensionSet::Add##CAMELCASE(int number, FieldType type, \ - bool packed, LOWERCASE value, \ - const FieldDescriptor* descriptor) { \ - Extension* extension; \ - if (MaybeNewExtension(number, descriptor, &extension)) { \ - extension->type = type; \ - GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \ - extension->is_repeated = true; \ - extension->is_packed = packed; \ - extension->repeated_##LOWERCASE##_value = \ - Arena::CreateMessage >(arena_); \ - } else { \ - GOOGLE_DCHECK_TYPE(*extension, REPEATED, UPPERCASE); \ - GOOGLE_DCHECK_EQ(extension->is_packed, packed); \ - } \ - extension->repeated_##LOWERCASE##_value->Add(value); \ -} - -PRIMITIVE_ACCESSORS( INT32, int32, Int32) -PRIMITIVE_ACCESSORS( INT64, int64, Int64) +#define PRIMITIVE_ACCESSORS(UPPERCASE, LOWERCASE, CAMELCASE) \ + \ + LOWERCASE ExtensionSet::Get##CAMELCASE(int number, LOWERCASE default_value) \ + const { \ + const Extension* extension = FindOrNull(number); \ + if (extension == NULL || extension->is_cleared) { \ + return default_value; \ + } else { \ + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, UPPERCASE); \ + return extension->LOWERCASE##_value; \ + } \ + } \ + \ + void ExtensionSet::Set##CAMELCASE(int number, FieldType type, \ + LOWERCASE value, \ + const FieldDescriptor* descriptor) { \ + Extension* extension; \ + if (MaybeNewExtension(number, descriptor, &extension)) { \ + extension->type = type; \ + GOOGLE_DCHECK_EQ(cpp_type(extension->type), \ + WireFormatLite::CPPTYPE_##UPPERCASE); \ + extension->is_repeated = false; \ + } else { \ + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, UPPERCASE); \ + } \ + extension->is_cleared = false; \ + extension->LOWERCASE##_value = value; \ + } \ + \ + LOWERCASE ExtensionSet::GetRepeated##CAMELCASE(int number, int index) \ + const { \ + const Extension* extension = FindOrNull(number); \ + GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; \ + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \ + return extension->repeated_##LOWERCASE##_value->Get(index); \ + } \ + \ + void ExtensionSet::SetRepeated##CAMELCASE(int number, int index, \ + LOWERCASE value) { \ + Extension* extension = FindOrNull(number); \ + GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; \ + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \ + extension->repeated_##LOWERCASE##_value->Set(index, value); \ + } \ + \ + void ExtensionSet::Add##CAMELCASE(int number, FieldType type, bool packed, \ + LOWERCASE value, \ + const FieldDescriptor* descriptor) { \ + Extension* extension; \ + if (MaybeNewExtension(number, descriptor, &extension)) { \ + extension->type = type; \ + GOOGLE_DCHECK_EQ(cpp_type(extension->type), \ + WireFormatLite::CPPTYPE_##UPPERCASE); \ + extension->is_repeated = true; \ + extension->is_packed = packed; \ + extension->repeated_##LOWERCASE##_value = \ + Arena::CreateMessage>(arena_); \ + } else { \ + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \ + GOOGLE_DCHECK_EQ(extension->is_packed, packed); \ + } \ + extension->repeated_##LOWERCASE##_value->Add(value); \ + } + +PRIMITIVE_ACCESSORS(INT32, int32, Int32) +PRIMITIVE_ACCESSORS(INT64, int64, Int64) PRIMITIVE_ACCESSORS(UINT32, uint32, UInt32) PRIMITIVE_ACCESSORS(UINT64, uint64, UInt64) -PRIMITIVE_ACCESSORS( FLOAT, float, Float) +PRIMITIVE_ACCESSORS(FLOAT, float, Float) PRIMITIVE_ACCESSORS(DOUBLE, double, Double) -PRIMITIVE_ACCESSORS( BOOL, bool, Bool) +PRIMITIVE_ACCESSORS(BOOL, bool, Bool) #undef PRIMITIVE_ACCESSORS const void* ExtensionSet::GetRawRepeatedField(int number, const void* default_value) const { - ExtensionMap::const_iterator iter = extensions_.find(number); - if (iter == extensions_.end()) { + const Extension* extension = FindOrNull(number); + if (extension == NULL) { return default_value; } // We assume that all the RepeatedField<>* pointers have the same // size and alignment within the anonymous union in Extension. - return iter->second.repeated_int32_value; + return extension->repeated_int32_value; } void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type, @@ -360,43 +381,43 @@ void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type, static_cast(field_type))) { case WireFormatLite::CPPTYPE_INT32: extension->repeated_int32_value = - Arena::CreateMessage >(arena_); + Arena::CreateMessage>(arena_); break; case WireFormatLite::CPPTYPE_INT64: extension->repeated_int64_value = - Arena::CreateMessage >(arena_); + Arena::CreateMessage>(arena_); break; case WireFormatLite::CPPTYPE_UINT32: extension->repeated_uint32_value = - Arena::CreateMessage >(arena_); + Arena::CreateMessage>(arena_); break; case WireFormatLite::CPPTYPE_UINT64: extension->repeated_uint64_value = - Arena::CreateMessage >(arena_); + Arena::CreateMessage>(arena_); break; case WireFormatLite::CPPTYPE_DOUBLE: extension->repeated_double_value = - Arena::CreateMessage >(arena_); + Arena::CreateMessage>(arena_); break; case WireFormatLite::CPPTYPE_FLOAT: extension->repeated_float_value = - Arena::CreateMessage >(arena_); + Arena::CreateMessage>(arena_); break; case WireFormatLite::CPPTYPE_BOOL: extension->repeated_bool_value = - Arena::CreateMessage >(arena_); + Arena::CreateMessage>(arena_); break; case WireFormatLite::CPPTYPE_ENUM: extension->repeated_enum_value = - Arena::CreateMessage >(arena_); + Arena::CreateMessage>(arena_); break; case WireFormatLite::CPPTYPE_STRING: extension->repeated_string_value = - Arena::CreateMessage >(arena_); + Arena::CreateMessage>(arena_); break; case WireFormatLite::CPPTYPE_MESSAGE: extension->repeated_message_value = - Arena::CreateMessage >(arena_); + Arena::CreateMessage>(arena_); break; } } @@ -409,25 +430,24 @@ void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type, // Compatible version using old call signature. Does not create extensions when // the don't already exist; instead, just GOOGLE_CHECK-fails. void* ExtensionSet::MutableRawRepeatedField(int number) { - ExtensionMap::iterator iter = extensions_.find(number); - GOOGLE_CHECK(iter == extensions_.end()) << "Extension not found."; + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != NULL) << "Extension not found."; // We assume that all the RepeatedField<>* pointers have the same // size and alignment within the anonymous union in Extension. - return iter->second.repeated_int32_value; + return extension->repeated_int32_value; } - // ------------------------------------------------------------------- // Enums int ExtensionSet::GetEnum(int number, int default_value) const { - ExtensionMap::const_iterator iter = extensions_.find(number); - if (iter == extensions_.end() || iter->second.is_cleared) { + const Extension* extension = FindOrNull(number); + if (extension == NULL || extension->is_cleared) { // Not present. Return the default value. return default_value; } else { - GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, ENUM); - return iter->second.enum_value; + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, ENUM); + return extension->enum_value; } } @@ -439,28 +459,27 @@ void ExtensionSet::SetEnum(int number, FieldType type, int value, GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM); extension->is_repeated = false; } else { - GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, ENUM); + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, ENUM); } extension->is_cleared = false; extension->enum_value = value; } int ExtensionSet::GetRepeatedEnum(int number, int index) const { - ExtensionMap::const_iterator iter = extensions_.find(number); - GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; - GOOGLE_DCHECK_TYPE(iter->second, REPEATED, ENUM); - return iter->second.repeated_enum_value->Get(index); + const Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM); + return extension->repeated_enum_value->Get(index); } void ExtensionSet::SetRepeatedEnum(int number, int index, int value) { - ExtensionMap::iterator iter = extensions_.find(number); - GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; - GOOGLE_DCHECK_TYPE(iter->second, REPEATED, ENUM); - iter->second.repeated_enum_value->Set(index, value); + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM); + extension->repeated_enum_value->Set(index, value); } -void ExtensionSet::AddEnum(int number, FieldType type, - bool packed, int value, +void ExtensionSet::AddEnum(int number, FieldType type, bool packed, int value, const FieldDescriptor* descriptor) { Extension* extension; if (MaybeNewExtension(number, descriptor, &extension)) { @@ -469,9 +488,9 @@ void ExtensionSet::AddEnum(int number, FieldType type, extension->is_repeated = true; extension->is_packed = packed; extension->repeated_enum_value = - Arena::CreateMessage >(arena_); + Arena::CreateMessage>(arena_); } else { - GOOGLE_DCHECK_TYPE(*extension, REPEATED, ENUM); + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM); GOOGLE_DCHECK_EQ(extension->is_packed, packed); } extension->repeated_enum_value->Add(value); @@ -480,49 +499,50 @@ void ExtensionSet::AddEnum(int number, FieldType type, // ------------------------------------------------------------------- // Strings -const string& ExtensionSet::GetString(int number, - const string& default_value) const { - ExtensionMap::const_iterator iter = extensions_.find(number); - if (iter == extensions_.end() || iter->second.is_cleared) { +const std::string& ExtensionSet::GetString( + int number, const std::string& default_value) const { + const Extension* extension = FindOrNull(number); + if (extension == NULL || extension->is_cleared) { // Not present. Return the default value. return default_value; } else { - GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, STRING); - return *iter->second.string_value; + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, STRING); + return *extension->string_value; } } -string* ExtensionSet::MutableString(int number, FieldType type, - const FieldDescriptor* descriptor) { +std::string* ExtensionSet::MutableString(int number, FieldType type, + const FieldDescriptor* descriptor) { Extension* extension; if (MaybeNewExtension(number, descriptor, &extension)) { extension->type = type; GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING); extension->is_repeated = false; - extension->string_value = Arena::Create(arena_); + extension->string_value = Arena::Create(arena_); } else { - GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, STRING); + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, STRING); } extension->is_cleared = false; return extension->string_value; } -const string& ExtensionSet::GetRepeatedString(int number, int index) const { - ExtensionMap::const_iterator iter = extensions_.find(number); - GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; - GOOGLE_DCHECK_TYPE(iter->second, REPEATED, STRING); - return iter->second.repeated_string_value->Get(index); +const std::string& ExtensionSet::GetRepeatedString(int number, + int index) const { + const Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING); + return extension->repeated_string_value->Get(index); } -string* ExtensionSet::MutableRepeatedString(int number, int index) { - ExtensionMap::iterator iter = extensions_.find(number); - GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; - GOOGLE_DCHECK_TYPE(iter->second, REPEATED, STRING); - return iter->second.repeated_string_value->Mutable(index); +std::string* ExtensionSet::MutableRepeatedString(int number, int index) { + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING); + return extension->repeated_string_value->Mutable(index); } -string* ExtensionSet::AddString(int number, FieldType type, - const FieldDescriptor* descriptor) { +std::string* ExtensionSet::AddString(int number, FieldType type, + const FieldDescriptor* descriptor) { Extension* extension; if (MaybeNewExtension(number, descriptor, &extension)) { extension->type = type; @@ -530,9 +550,9 @@ string* ExtensionSet::AddString(int number, FieldType type, extension->is_repeated = true; extension->is_packed = false; extension->repeated_string_value = - Arena::CreateMessage >(arena_); + Arena::CreateMessage>(arena_); } else { - GOOGLE_DCHECK_TYPE(*extension, REPEATED, STRING); + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING); } return extension->repeated_string_value->Add(); } @@ -542,16 +562,16 @@ string* ExtensionSet::AddString(int number, FieldType type, const MessageLite& ExtensionSet::GetMessage( int number, const MessageLite& default_value) const { - ExtensionMap::const_iterator iter = extensions_.find(number); - if (iter == extensions_.end()) { + const Extension* extension = FindOrNull(number); + if (extension == NULL) { // Not present. Return the default value. return default_value; } else { - GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); - if (iter->second.is_lazy) { - return iter->second.lazymessage_value->GetMessage(default_value); + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); + if (extension->is_lazy) { + return extension->lazymessage_value->GetMessage(default_value); } else { - return *iter->second.message_value; + return *extension->message_value; } } } @@ -574,7 +594,7 @@ MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, extension->is_cleared = false; return extension->message_value; } else { - GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); extension->is_cleared = false; if (extension->is_lazy) { return extension->lazymessage_value->MutableMessage(prototype); @@ -596,7 +616,7 @@ void ExtensionSet::SetAllocatedMessage(int number, FieldType type, ClearExtension(number); return; } - ::google::protobuf::Arena* message_arena = message->GetArena(); + Arena* message_arena = message->GetArena(); Extension* extension; if (MaybeNewExtension(number, descriptor, &extension)) { extension->type = type; @@ -613,7 +633,7 @@ void ExtensionSet::SetAllocatedMessage(int number, FieldType type, extension->message_value->CheckTypeAndMergeFrom(*message); } } else { - GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); if (extension->is_lazy) { extension->lazymessage_value->SetAllocatedMessage(message); } else { @@ -649,7 +669,7 @@ void ExtensionSet::UnsafeArenaSetAllocatedMessage( extension->is_lazy = false; extension->message_value = message; } else { - GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); if (extension->is_lazy) { extension->lazymessage_value->UnsafeArenaSetAllocatedMessage(message); } else { @@ -662,55 +682,53 @@ void ExtensionSet::UnsafeArenaSetAllocatedMessage( extension->is_cleared = false; } - MessageLite* ExtensionSet::ReleaseMessage(int number, const MessageLite& prototype) { - ExtensionMap::iterator iter = extensions_.find(number); - if (iter == extensions_.end()) { + Extension* extension = FindOrNull(number); + if (extension == NULL) { // Not present. Return NULL. return NULL; } else { - GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); MessageLite* ret = NULL; - if (iter->second.is_lazy) { - ret = iter->second.lazymessage_value->ReleaseMessage(prototype); + if (extension->is_lazy) { + ret = extension->lazymessage_value->ReleaseMessage(prototype); if (arena_ == NULL) { - delete iter->second.lazymessage_value; + delete extension->lazymessage_value; } } else { if (arena_ == NULL) { - ret = iter->second.message_value; + ret = extension->message_value; } else { // ReleaseMessage() always returns a heap-allocated message, and we are // on an arena, so we need to make a copy of this message to return. - ret = (iter->second.message_value)->New(); - ret->CheckTypeAndMergeFrom(*iter->second.message_value); + ret = extension->message_value->New(); + ret->CheckTypeAndMergeFrom(*extension->message_value); } } - extensions_.erase(number); + Erase(number); return ret; } } MessageLite* ExtensionSet::UnsafeArenaReleaseMessage( int number, const MessageLite& prototype) { - ExtensionMap::iterator iter = extensions_.find(number); - if (iter == extensions_.end()) { + Extension* extension = FindOrNull(number); + if (extension == NULL) { // Not present. Return NULL. return NULL; } else { - GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); MessageLite* ret = NULL; - if (iter->second.is_lazy) { - ret = - iter->second.lazymessage_value->UnsafeArenaReleaseMessage(prototype); + if (extension->is_lazy) { + ret = extension->lazymessage_value->UnsafeArenaReleaseMessage(prototype); if (arena_ == NULL) { - delete iter->second.lazymessage_value; + delete extension->lazymessage_value; } } else { - ret = iter->second.message_value; + ret = extension->message_value; } - extensions_.erase(number); + Erase(number); return ret; } } @@ -719,19 +737,19 @@ MessageLite* ExtensionSet::UnsafeArenaReleaseMessage( // MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor, // MessageFactory* factory); -const MessageLite& ExtensionSet::GetRepeatedMessage( - int number, int index) const { - ExtensionMap::const_iterator iter = extensions_.find(number); - GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; - GOOGLE_DCHECK_TYPE(iter->second, REPEATED, MESSAGE); - return iter->second.repeated_message_value->Get(index); +const MessageLite& ExtensionSet::GetRepeatedMessage(int number, + int index) const { + const Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE); + return extension->repeated_message_value->Get(index); } MessageLite* ExtensionSet::MutableRepeatedMessage(int number, int index) { - ExtensionMap::iterator iter = extensions_.find(number); - GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; - GOOGLE_DCHECK_TYPE(iter->second, REPEATED, MESSAGE); - return iter->second.repeated_message_value->Mutable(index); + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE); + return extension->repeated_message_value->Mutable(index); } MessageLite* ExtensionSet::AddMessage(int number, FieldType type, @@ -743,15 +761,16 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type, GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); extension->is_repeated = true; extension->repeated_message_value = - Arena::CreateMessage >(arena_); + Arena::CreateMessage>(arena_); } else { - GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE); + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE); } // RepeatedPtrField does not know how to Add() since it cannot // allocate an abstract object, so we have to be tricky. - MessageLite* result = extension->repeated_message_value - ->AddFromCleared >(); + MessageLite* result = reinterpret_cast( + extension->repeated_message_value) + ->AddFromCleared>(); if (result == NULL) { result = prototype.New(arena_); extension->repeated_message_value->AddAllocated(result); @@ -767,13 +786,11 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type, #undef GOOGLE_DCHECK_TYPE void ExtensionSet::RemoveLast(int number) { - ExtensionMap::iterator iter = extensions_.find(number); - GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; - - Extension* extension = &iter->second; + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; GOOGLE_DCHECK(extension->is_repeated); - switch(cpp_type(extension->type)) { + switch (cpp_type(extension->type)) { case WireFormatLite::CPPTYPE_INT32: extension->repeated_int32_value->RemoveLast(); break; @@ -808,23 +825,19 @@ void ExtensionSet::RemoveLast(int number) { } MessageLite* ExtensionSet::ReleaseLast(int number) { - ExtensionMap::iterator iter = extensions_.find(number); - GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; - - Extension* extension = &iter->second; + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; GOOGLE_DCHECK(extension->is_repeated); GOOGLE_DCHECK(cpp_type(extension->type) == WireFormatLite::CPPTYPE_MESSAGE); return extension->repeated_message_value->ReleaseLast(); } void ExtensionSet::SwapElements(int number, int index1, int index2) { - ExtensionMap::iterator iter = extensions_.find(number); - GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; - - Extension* extension = &iter->second; + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; GOOGLE_DCHECK(extension->is_repeated); - switch(cpp_type(extension->type)) { + switch (cpp_type(extension->type)) { case WireFormatLite::CPPTYPE_INT32: extension->repeated_int32_value->SwapElements(index1, index2); break; @@ -861,26 +874,53 @@ void ExtensionSet::SwapElements(int number, int index1, int index2) { // =================================================================== void ExtensionSet::Clear() { - for (ExtensionMap::iterator iter = extensions_.begin(); - iter != extensions_.end(); ++iter) { - iter->second.Clear(); + ForEach([](int /* number */, Extension& ext) { ext.Clear(); }); +} + +namespace { +// Computes the size of a std::set_union without constructing the union. +template +size_t SizeOfUnion(ItX it_xs, ItX end_xs, ItY it_ys, ItY end_ys) { + size_t result = 0; + while (it_xs != end_xs && it_ys != end_ys) { + ++result; + if (it_xs->first < it_ys->first) { + ++it_xs; + } else if (it_xs->first == it_ys->first) { + ++it_xs; + ++it_ys; + } else { + ++it_ys; + } } + result += std::distance(it_xs, end_xs); + result += std::distance(it_ys, end_ys); + return result; } +} // namespace void ExtensionSet::MergeFrom(const ExtensionSet& other) { - for (ExtensionMap::const_iterator iter = other.extensions_.begin(); - iter != other.extensions_.end(); ++iter) { - const Extension& other_extension = iter->second; - InternalExtensionMergeFrom(iter->first, other_extension); + if (PROTOBUF_PREDICT_TRUE(!is_large())) { + if (PROTOBUF_PREDICT_TRUE(!other.is_large())) { + GrowCapacity(SizeOfUnion(flat_begin(), flat_end(), other.flat_begin(), + other.flat_end())); + } else { + GrowCapacity(SizeOfUnion(flat_begin(), flat_end(), + other.map_.large->begin(), + other.map_.large->end())); + } } + other.ForEach([this](int number, const Extension& ext) { + this->InternalExtensionMergeFrom(number, ext); + }); } void ExtensionSet::InternalExtensionMergeFrom( - int number, const Extension& other_extension) { + int number, const Extension& other_extension) { if (other_extension.is_repeated) { Extension* extension; - bool is_new = MaybeNewExtension(number, other_extension.descriptor, - &extension); + bool is_new = + MaybeNewExtension(number, other_extension.descriptor, &extension); if (is_new) { // Extension did not already exist in set. extension->type = other_extension.type; @@ -893,31 +933,31 @@ void ExtensionSet::InternalExtensionMergeFrom( } switch (cpp_type(other_extension.type)) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \ - case WireFormatLite::CPPTYPE_##UPPERCASE: \ - if (is_new) { \ - extension->repeated_##LOWERCASE##_value = \ - Arena::CreateMessage(arena_); \ - } \ - extension->repeated_##LOWERCASE##_value->MergeFrom( \ - *other_extension.repeated_##LOWERCASE##_value); \ - break; - - HANDLE_TYPE( INT32, int32, RepeatedField < int32>); - HANDLE_TYPE( INT64, int64, RepeatedField < int64>); - HANDLE_TYPE( UINT32, uint32, RepeatedField < uint32>); - HANDLE_TYPE( UINT64, uint64, RepeatedField < uint64>); - HANDLE_TYPE( FLOAT, float, RepeatedField < float>); - HANDLE_TYPE( DOUBLE, double, RepeatedField < double>); - HANDLE_TYPE( BOOL, bool, RepeatedField < bool>); - HANDLE_TYPE( ENUM, enum, RepeatedField < int>); - HANDLE_TYPE( STRING, string, RepeatedPtrField< string>); +#define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + if (is_new) { \ + extension->repeated_##LOWERCASE##_value = \ + Arena::CreateMessage(arena_); \ + } \ + extension->repeated_##LOWERCASE##_value->MergeFrom( \ + *other_extension.repeated_##LOWERCASE##_value); \ + break; + + HANDLE_TYPE(INT32, int32, RepeatedField); + HANDLE_TYPE(INT64, int64, RepeatedField); + HANDLE_TYPE(UINT32, uint32, RepeatedField); + HANDLE_TYPE(UINT64, uint64, RepeatedField); + HANDLE_TYPE(FLOAT, float, RepeatedField); + HANDLE_TYPE(DOUBLE, double, RepeatedField); + HANDLE_TYPE(BOOL, bool, RepeatedField); + HANDLE_TYPE(ENUM, enum, RepeatedField); + HANDLE_TYPE(STRING, string, RepeatedPtrField); #undef HANDLE_TYPE case WireFormatLite::CPPTYPE_MESSAGE: if (is_new) { extension->repeated_message_value = - Arena::CreateMessage >(arena_); + Arena::CreateMessage>(arena_); } // We can't call RepeatedPtrField::MergeFrom() because // it would attempt to allocate new objects. @@ -925,8 +965,10 @@ void ExtensionSet::InternalExtensionMergeFrom( other_extension.repeated_message_value; for (int i = 0; i < other_repeated_message->size(); i++) { const MessageLite& other_message = other_repeated_message->Get(i); - MessageLite* target = extension->repeated_message_value - ->AddFromCleared >(); + MessageLite* target = + reinterpret_cast( + extension->repeated_message_value) + ->AddFromCleared>(); if (target == NULL) { target = other_message.New(arena_); extension->repeated_message_value->AddAllocated(target); @@ -938,32 +980,30 @@ void ExtensionSet::InternalExtensionMergeFrom( } else { if (!other_extension.is_cleared) { switch (cpp_type(other_extension.type)) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \ - case WireFormatLite::CPPTYPE_##UPPERCASE: \ - Set##CAMELCASE(number, other_extension.type, \ - other_extension.LOWERCASE##_value, \ - other_extension.descriptor); \ - break; - - HANDLE_TYPE( INT32, int32, Int32); - HANDLE_TYPE( INT64, int64, Int64); +#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + Set##CAMELCASE(number, other_extension.type, \ + other_extension.LOWERCASE##_value, \ + other_extension.descriptor); \ + break; + + HANDLE_TYPE(INT32, int32, Int32); + HANDLE_TYPE(INT64, int64, Int64); HANDLE_TYPE(UINT32, uint32, UInt32); HANDLE_TYPE(UINT64, uint64, UInt64); - HANDLE_TYPE( FLOAT, float, Float); + HANDLE_TYPE(FLOAT, float, Float); HANDLE_TYPE(DOUBLE, double, Double); - HANDLE_TYPE( BOOL, bool, Bool); - HANDLE_TYPE( ENUM, enum, Enum); + HANDLE_TYPE(BOOL, bool, Bool); + HANDLE_TYPE(ENUM, enum, Enum); #undef HANDLE_TYPE case WireFormatLite::CPPTYPE_STRING: - SetString(number, other_extension.type, - *other_extension.string_value, + SetString(number, other_extension.type, *other_extension.string_value, other_extension.descriptor); break; case WireFormatLite::CPPTYPE_MESSAGE: { Extension* extension; - bool is_new = MaybeNewExtension(number, - other_extension.descriptor, - &extension); + bool is_new = + MaybeNewExtension(number, other_extension.descriptor, &extension); if (is_new) { extension->type = other_extension.type; extension->is_packed = other_extension.is_packed; @@ -983,7 +1023,7 @@ void ExtensionSet::InternalExtensionMergeFrom( } } else { GOOGLE_DCHECK_EQ(extension->type, other_extension.type); - GOOGLE_DCHECK_EQ(extension->is_packed,other_extension.is_packed); + GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed); GOOGLE_DCHECK(!extension->is_repeated); if (other_extension.is_lazy) { if (extension->is_lazy) { @@ -996,9 +1036,9 @@ void ExtensionSet::InternalExtensionMergeFrom( } } else { if (extension->is_lazy) { - extension->lazymessage_value->MutableMessage( - *other_extension.message_value)->CheckTypeAndMergeFrom( - *other_extension.message_value); + extension->lazymessage_value + ->MutableMessage(*other_extension.message_value) + ->CheckTypeAndMergeFrom(*other_extension.message_value); } else { extension->message_value->CheckTypeAndMergeFrom( *other_extension.message_value); @@ -1014,8 +1054,11 @@ void ExtensionSet::InternalExtensionMergeFrom( } void ExtensionSet::Swap(ExtensionSet* x) { - if (GetArenaNoVirtual() == x->GetArenaNoVirtual()) { - extensions_.swap(x->extensions_); + if (GetArena() == x->GetArena()) { + using std::swap; + swap(flat_capacity_, x->flat_capacity_); + swap(flat_size_, x->flat_size_); + swap(map_, x->map_); } else { // TODO(cfallin, rohananil): We maybe able to optimize a case where we are // swapping from heap to arena-allocated extension set, by just Own()'ing @@ -1029,22 +1072,19 @@ void ExtensionSet::Swap(ExtensionSet* x) { } } -void ExtensionSet::SwapExtension(ExtensionSet* other, - int number) { +void ExtensionSet::SwapExtension(ExtensionSet* other, int number) { if (this == other) return; - ExtensionMap::iterator this_iter = extensions_.find(number); - ExtensionMap::iterator other_iter = other->extensions_.find(number); + Extension* this_ext = FindOrNull(number); + Extension* other_ext = other->FindOrNull(number); - if (this_iter == extensions_.end() && - other_iter == other->extensions_.end()) { + if (this_ext == NULL && other_ext == NULL) { return; } - if (this_iter != extensions_.end() && - other_iter != other->extensions_.end()) { - if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { + if (this_ext != NULL && other_ext != NULL) { + if (GetArena() == other->GetArena()) { using std::swap; - swap(this_iter->second, other_iter->second); + swap(*this_ext, *other_ext); } else { // TODO(cfallin, rohananil): We could further optimize these cases, // especially avoid creation of ExtensionSet, and move MergeFrom logic @@ -1052,33 +1092,33 @@ void ExtensionSet::SwapExtension(ExtensionSet* other, // We do it this way to reuse the copy-across-arenas logic already // implemented in ExtensionSet's MergeFrom. ExtensionSet temp; - temp.InternalExtensionMergeFrom(number, other_iter->second); - ExtensionMap::iterator temp_iter = temp.extensions_.find(number); - other_iter->second.Clear(); - other->InternalExtensionMergeFrom(number, this_iter->second); - this_iter->second.Clear(); - InternalExtensionMergeFrom(number, temp_iter->second); + temp.InternalExtensionMergeFrom(number, *other_ext); + Extension* temp_ext = temp.FindOrNull(number); + other_ext->Clear(); + other->InternalExtensionMergeFrom(number, *this_ext); + this_ext->Clear(); + InternalExtensionMergeFrom(number, *temp_ext); } return; } - if (this_iter == extensions_.end()) { - if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { - extensions_.insert(std::make_pair(number, other_iter->second)); + if (this_ext == NULL) { + if (GetArena() == other->GetArena()) { + *Insert(number).first = *other_ext; } else { - InternalExtensionMergeFrom(number, other_iter->second); + InternalExtensionMergeFrom(number, *other_ext); } - other->extensions_.erase(number); + other->Erase(number); return; } - if (other_iter == other->extensions_.end()) { - if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { - other->extensions_.insert(std::make_pair(number, this_iter->second)); + if (other_ext == NULL) { + if (GetArena() == other->GetArena()) { + *other->Insert(number).first = *this_ext; } else { - other->InternalExtensionMergeFrom(number, this_iter->second); + other->InternalExtensionMergeFrom(number, *this_ext); } - extensions_.erase(number); + Erase(number); return; } } @@ -1086,34 +1126,23 @@ void ExtensionSet::SwapExtension(ExtensionSet* other, bool ExtensionSet::IsInitialized() const { // Extensions are never required. However, we need to check that all // embedded messages are initialized. - for (ExtensionMap::const_iterator iter = extensions_.begin(); - iter != extensions_.end(); ++iter) { - const Extension& extension = iter->second; - if (cpp_type(extension.type) == WireFormatLite::CPPTYPE_MESSAGE) { - if (extension.is_repeated) { - for (int i = 0; i < extension.repeated_message_value->size(); i++) { - if (!extension.repeated_message_value->Get(i).IsInitialized()) { - return false; - } - } - } else { - if (!extension.is_cleared) { - if (extension.is_lazy) { - if (!extension.lazymessage_value->IsInitialized()) return false; - } else { - if (!extension.message_value->IsInitialized()) return false; - } - } - } + if (PROTOBUF_PREDICT_FALSE(is_large())) { + for (const auto& kv : *map_.large) { + if (!kv.second.IsInitialized()) return false; } + return true; + } + for (const KeyValue* it = flat_begin(); it != flat_end(); ++it) { + if (!it->second.IsInitialized()) return false; } - return true; } -bool ExtensionSet::FindExtensionInfoFromTag( - uint32 tag, ExtensionFinder* extension_finder, int* field_number, - ExtensionInfo* extension, bool* was_packed_on_wire) { +bool ExtensionSet::FindExtensionInfoFromTag(uint32 tag, + ExtensionFinder* extension_finder, + int* field_number, + ExtensionInfo* extension, + bool* was_packed_on_wire) { *field_number = WireFormatLite::GetTagFieldNumber(tag); WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); return FindExtensionInfoFromFieldNumber(wire_type, *field_number, @@ -1149,19 +1178,44 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, int number; bool was_packed_on_wire; ExtensionInfo extension; - if (!FindExtensionInfoFromTag( - tag, extension_finder, &number, &extension, &was_packed_on_wire)) { + if (!FindExtensionInfoFromTag(tag, extension_finder, &number, &extension, + &was_packed_on_wire)) { return field_skipper->SkipField(input, tag); } else { - return ParseFieldWithExtensionInfo( - number, was_packed_on_wire, extension, input, field_skipper); + return ParseFieldWithExtensionInfo(number, was_packed_on_wire, extension, + input, field_skipper); } } -bool ExtensionSet::ParseFieldWithExtensionInfo( - int number, bool was_packed_on_wire, const ExtensionInfo& extension, - io::CodedInputStream* input, - FieldSkipper* field_skipper) { +const char* ExtensionSet::ParseField(uint64 tag, const char* ptr, + const MessageLite* containing_type, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx) { + GeneratedExtensionFinder finder(containing_type); + int number = tag >> 3; + bool was_packed_on_wire; + ExtensionInfo extension; + if (!FindExtensionInfoFromFieldNumber(tag & 7, number, &finder, &extension, + &was_packed_on_wire)) { + return UnknownFieldParse( + tag, metadata->mutable_unknown_fields(), ptr, ctx); + } + return ParseFieldWithExtensionInfo( + number, was_packed_on_wire, extension, metadata, ptr, ctx); +} + +const char* ExtensionSet::ParseMessageSetItem( + const char* ptr, const MessageLite* containing_type, + internal::InternalMetadata* metadata, internal::ParseContext* ctx) { + return ParseMessageSetItemTmpl(ptr, containing_type, + metadata, ctx); +} + +bool ExtensionSet::ParseFieldWithExtensionInfo(int number, + bool was_packed_on_wire, + const ExtensionInfo& extension, + io::CodedInputStream* input, + FieldSkipper* field_skipper) { // Explicitly not read extension.is_packed, instead check whether the field // was encoded in packed form on the wire. if (was_packed_on_wire) { @@ -1170,39 +1224,40 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( io::CodedInputStream::Limit limit = input->PushLimit(size); switch (extension.type) { -#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE, CPP_LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - while (input->BytesUntilLimit() > 0) { \ - CPP_LOWERCASE value; \ - if (!WireFormatLite::ReadPrimitive< \ - CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \ - input, &value)) return false; \ - Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ - extension.is_packed, value, \ - extension.descriptor); \ - } \ - break - - HANDLE_TYPE( INT32, Int32, int32); - HANDLE_TYPE( INT64, Int64, int64); - HANDLE_TYPE( UINT32, UInt32, uint32); - HANDLE_TYPE( UINT64, UInt64, uint64); - HANDLE_TYPE( SINT32, Int32, int32); - HANDLE_TYPE( SINT64, Int64, int64); - HANDLE_TYPE( FIXED32, UInt32, uint32); - HANDLE_TYPE( FIXED64, UInt64, uint64); - HANDLE_TYPE(SFIXED32, Int32, int32); - HANDLE_TYPE(SFIXED64, Int64, int64); - HANDLE_TYPE( FLOAT, Float, float); - HANDLE_TYPE( DOUBLE, Double, double); - HANDLE_TYPE( BOOL, Bool, bool); +#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE, CPP_LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + while (input->BytesUntilLimit() > 0) { \ + CPP_LOWERCASE value; \ + if (!WireFormatLite::ReadPrimitive( \ + input, &value)) \ + return false; \ + Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ + extension.is_packed, value, extension.descriptor); \ + } \ + break + + HANDLE_TYPE(INT32, Int32, int32); + HANDLE_TYPE(INT64, Int64, int64); + HANDLE_TYPE(UINT32, UInt32, uint32); + HANDLE_TYPE(UINT64, UInt64, uint64); + HANDLE_TYPE(SINT32, Int32, int32); + HANDLE_TYPE(SINT64, Int64, int64); + HANDLE_TYPE(FIXED32, UInt32, uint32); + HANDLE_TYPE(FIXED64, UInt64, uint64); + HANDLE_TYPE(SFIXED32, Int32, int32); + HANDLE_TYPE(SFIXED64, Int64, int64); + HANDLE_TYPE(FLOAT, Float, float); + HANDLE_TYPE(DOUBLE, Double, double); + HANDLE_TYPE(BOOL, Bool, bool); #undef HANDLE_TYPE case WireFormatLite::TYPE_ENUM: while (input->BytesUntilLimit() > 0) { int value; if (!WireFormatLite::ReadPrimitive( - input, &value)) return false; + input, &value)) + return false; if (extension.enum_validity_check.func( extension.enum_validity_check.arg, value)) { AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, @@ -1225,41 +1280,42 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( input->PopLimit(limit); } else { switch (extension.type) { -#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE, CPP_LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: { \ - CPP_LOWERCASE value; \ - if (!WireFormatLite::ReadPrimitive< \ - CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \ - input, &value)) return false; \ - if (extension.is_repeated) { \ - Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ - extension.is_packed, value, \ - extension.descriptor); \ - } else { \ - Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \ - extension.descriptor); \ - } \ - } break - - HANDLE_TYPE( INT32, Int32, int32); - HANDLE_TYPE( INT64, Int64, int64); - HANDLE_TYPE( UINT32, UInt32, uint32); - HANDLE_TYPE( UINT64, UInt64, uint64); - HANDLE_TYPE( SINT32, Int32, int32); - HANDLE_TYPE( SINT64, Int64, int64); - HANDLE_TYPE( FIXED32, UInt32, uint32); - HANDLE_TYPE( FIXED64, UInt64, uint64); - HANDLE_TYPE(SFIXED32, Int32, int32); - HANDLE_TYPE(SFIXED64, Int64, int64); - HANDLE_TYPE( FLOAT, Float, float); - HANDLE_TYPE( DOUBLE, Double, double); - HANDLE_TYPE( BOOL, Bool, bool); +#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE, CPP_LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: { \ + CPP_LOWERCASE value; \ + if (!WireFormatLite::ReadPrimitive( \ + input, &value)) \ + return false; \ + if (extension.is_repeated) { \ + Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ + extension.is_packed, value, extension.descriptor); \ + } else { \ + Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \ + extension.descriptor); \ + } \ + } break + + HANDLE_TYPE(INT32, Int32, int32); + HANDLE_TYPE(INT64, Int64, int64); + HANDLE_TYPE(UINT32, UInt32, uint32); + HANDLE_TYPE(UINT64, UInt64, uint64); + HANDLE_TYPE(SINT32, Int32, int32); + HANDLE_TYPE(SINT64, Int64, int64); + HANDLE_TYPE(FIXED32, UInt32, uint32); + HANDLE_TYPE(FIXED64, UInt64, uint64); + HANDLE_TYPE(SFIXED32, Int32, int32); + HANDLE_TYPE(SFIXED64, Int64, int64); + HANDLE_TYPE(FLOAT, Float, float); + HANDLE_TYPE(DOUBLE, Double, double); + HANDLE_TYPE(BOOL, Bool, bool); #undef HANDLE_TYPE case WireFormatLite::TYPE_ENUM: { int value; if (!WireFormatLite::ReadPrimitive( - input, &value)) return false; + input, &value)) + return false; if (!extension.enum_validity_check.func( extension.enum_validity_check.arg, value)) { @@ -1275,40 +1331,50 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( break; } - case WireFormatLite::TYPE_STRING: { - string* value = extension.is_repeated ? - AddString(number, WireFormatLite::TYPE_STRING, extension.descriptor) : - MutableString(number, WireFormatLite::TYPE_STRING, - extension.descriptor); + case WireFormatLite::TYPE_STRING: { + std::string* value = + extension.is_repeated + ? AddString(number, WireFormatLite::TYPE_STRING, + extension.descriptor) + : MutableString(number, WireFormatLite::TYPE_STRING, + extension.descriptor); if (!WireFormatLite::ReadString(input, value)) return false; break; } - case WireFormatLite::TYPE_BYTES: { - string* value = extension.is_repeated ? - AddString(number, WireFormatLite::TYPE_BYTES, extension.descriptor) : - MutableString(number, WireFormatLite::TYPE_BYTES, - extension.descriptor); + case WireFormatLite::TYPE_BYTES: { + std::string* value = + extension.is_repeated + ? AddString(number, WireFormatLite::TYPE_BYTES, + extension.descriptor) + : MutableString(number, WireFormatLite::TYPE_BYTES, + extension.descriptor); if (!WireFormatLite::ReadBytes(input, value)) return false; break; } case WireFormatLite::TYPE_GROUP: { - MessageLite* value = extension.is_repeated ? - AddMessage(number, WireFormatLite::TYPE_GROUP, - *extension.message_prototype, extension.descriptor) : - MutableMessage(number, WireFormatLite::TYPE_GROUP, - *extension.message_prototype, extension.descriptor); + MessageLite* value = + extension.is_repeated + ? AddMessage(number, WireFormatLite::TYPE_GROUP, + *extension.message_info.prototype, + extension.descriptor) + : MutableMessage(number, WireFormatLite::TYPE_GROUP, + *extension.message_info.prototype, + extension.descriptor); if (!WireFormatLite::ReadGroup(number, input, value)) return false; break; } case WireFormatLite::TYPE_MESSAGE: { - MessageLite* value = extension.is_repeated ? - AddMessage(number, WireFormatLite::TYPE_MESSAGE, - *extension.message_prototype, extension.descriptor) : - MutableMessage(number, WireFormatLite::TYPE_MESSAGE, - *extension.message_prototype, extension.descriptor); + MessageLite* value = + extension.is_repeated + ? AddMessage(number, WireFormatLite::TYPE_MESSAGE, + *extension.message_info.prototype, + extension.descriptor) + : MutableMessage(number, WireFormatLite::TYPE_MESSAGE, + *extension.message_info.prototype, + extension.descriptor); if (!WireFormatLite::ReadMessage(input, value)) return false; break; } @@ -1333,35 +1399,97 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, return ParseField(tag, input, &finder, &skipper); } -// Defined in extension_set_heavy.cc. -// bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, -// const MessageLite* containing_type, -// UnknownFieldSet* unknown_fields) +bool ExtensionSet::ParseMessageSetLite(io::CodedInputStream* input, + ExtensionFinder* extension_finder, + FieldSkipper* field_skipper) { + while (true) { + const uint32 tag = input->ReadTag(); + switch (tag) { + case 0: + return true; + case WireFormatLite::kMessageSetItemStartTag: + if (!ParseMessageSetItemLite(input, extension_finder, field_skipper)) { + return false; + } + break; + default: + if (!ParseField(tag, input, extension_finder, field_skipper)) { + return false; + } + break; + } + } +} -// Defined in extension_set_heavy.cc. -// bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, -// const MessageLite* containing_type, -// UnknownFieldSet* unknown_fields); +bool ExtensionSet::ParseMessageSetItemLite(io::CodedInputStream* input, + ExtensionFinder* extension_finder, + FieldSkipper* field_skipper) { + struct MSLite { + bool ParseField(int type_id, io::CodedInputStream* input) { + return me->ParseField( + WireFormatLite::WIRETYPE_LENGTH_DELIMITED + 8 * type_id, input, + extension_finder, field_skipper); + } + + bool SkipField(uint32 tag, io::CodedInputStream* input) { + return field_skipper->SkipField(input, tag); + } + + ExtensionSet* me; + ExtensionFinder* extension_finder; + FieldSkipper* field_skipper; + }; -void ExtensionSet::SerializeWithCachedSizes( - int start_field_number, int end_field_number, - io::CodedOutputStream* output) const { - ExtensionMap::const_iterator iter; - for (iter = extensions_.lower_bound(start_field_number); - iter != extensions_.end() && iter->first < end_field_number; - ++iter) { - iter->second.SerializeFieldWithCachedSizes(iter->first, output); + return ParseMessageSetItemImpl(input, + MSLite{this, extension_finder, field_skipper}); +} + +bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, + const MessageLite* containing_type, + std::string* unknown_fields) { + io::StringOutputStream zcis(unknown_fields); + io::CodedOutputStream output(&zcis); + CodedOutputStreamFieldSkipper skipper(&output); + GeneratedExtensionFinder finder(containing_type); + return ParseMessageSetLite(input, &finder, &skipper); +} + +uint8* ExtensionSet::_InternalSerializeImpl( + int start_field_number, int end_field_number, uint8* target, + io::EpsCopyOutputStream* stream) const { + if (PROTOBUF_PREDICT_FALSE(is_large())) { + const auto& end = map_.large->end(); + for (auto it = map_.large->lower_bound(start_field_number); + it != end && it->first < end_field_number; ++it) { + target = it->second.InternalSerializeFieldWithCachedSizesToArray( + it->first, target, stream); + } + return target; } + const KeyValue* end = flat_end(); + for (const KeyValue* it = std::lower_bound( + flat_begin(), end, start_field_number, KeyValue::FirstComparator()); + it != end && it->first < end_field_number; ++it) { + target = it->second.InternalSerializeFieldWithCachedSizesToArray( + it->first, target, stream); + } + return target; +} + +uint8* ExtensionSet::InternalSerializeMessageSetWithCachedSizesToArray( + uint8* target, io::EpsCopyOutputStream* stream) const { + ForEach([&target, stream](int number, const Extension& ext) { + target = ext.InternalSerializeMessageSetItemWithCachedSizesToArray( + number, target, stream); + }); + return target; } size_t ExtensionSet::ByteSize() const { size_t total_size = 0; - - for (ExtensionMap::const_iterator iter = extensions_.begin(); - iter != extensions_.end(); ++iter) { - total_size += iter->second.ByteSize(iter->first); - } - + ForEach([&total_size](int number, const Extension& ext) { + total_size += ext.ByteSize(number); + }); return total_size; } @@ -1371,11 +1499,10 @@ size_t ExtensionSet::ByteSize() const { bool ExtensionSet::MaybeNewExtension(int number, const FieldDescriptor* descriptor, Extension** result) { - std::pair insert_result = - extensions_.insert(std::make_pair(number, Extension())); - *result = &insert_result.first->second; + bool extension_is_new = false; + std::tie(*result, extension_is_new) = Insert(number); (*result)->descriptor = descriptor; - return insert_result.second; + return extension_is_new; } // =================================================================== @@ -1384,20 +1511,20 @@ bool ExtensionSet::MaybeNewExtension(int number, void ExtensionSet::Extension::Clear() { if (is_repeated) { switch (cpp_type(type)) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case WireFormatLite::CPPTYPE_##UPPERCASE: \ - repeated_##LOWERCASE##_value->Clear(); \ - break - - HANDLE_TYPE( INT32, int32); - HANDLE_TYPE( INT64, int64); - HANDLE_TYPE( UINT32, uint32); - HANDLE_TYPE( UINT64, uint64); - HANDLE_TYPE( FLOAT, float); - HANDLE_TYPE( DOUBLE, double); - HANDLE_TYPE( BOOL, bool); - HANDLE_TYPE( ENUM, enum); - HANDLE_TYPE( STRING, string); +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + repeated_##LOWERCASE##_value->Clear(); \ + break + + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, enum); + HANDLE_TYPE(STRING, string); HANDLE_TYPE(MESSAGE, message); #undef HANDLE_TYPE } @@ -1426,152 +1553,42 @@ void ExtensionSet::Extension::Clear() { } } -void ExtensionSet::Extension::SerializeFieldWithCachedSizes( - int number, - io::CodedOutputStream* output) const { - if (is_repeated) { - if (is_packed) { - if (cached_size == 0) return; - - WireFormatLite::WriteTag(number, - WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(cached_size); - - switch (real_type(type)) { -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - WireFormatLite::Write##CAMELCASE##NoTag( \ - repeated_##LOWERCASE##_value->Get(i), output); \ - } \ - break - - HANDLE_TYPE( INT32, Int32, int32); - HANDLE_TYPE( INT64, Int64, int64); - HANDLE_TYPE( UINT32, UInt32, uint32); - HANDLE_TYPE( UINT64, UInt64, uint64); - HANDLE_TYPE( SINT32, SInt32, int32); - HANDLE_TYPE( SINT64, SInt64, int64); - HANDLE_TYPE( FIXED32, Fixed32, uint32); - HANDLE_TYPE( FIXED64, Fixed64, uint64); - HANDLE_TYPE(SFIXED32, SFixed32, int32); - HANDLE_TYPE(SFIXED64, SFixed64, int64); - HANDLE_TYPE( FLOAT, Float, float); - HANDLE_TYPE( DOUBLE, Double, double); - HANDLE_TYPE( BOOL, Bool, bool); - HANDLE_TYPE( ENUM, Enum, enum); -#undef HANDLE_TYPE - - case WireFormatLite::TYPE_STRING: - case WireFormatLite::TYPE_BYTES: - case WireFormatLite::TYPE_GROUP: - case WireFormatLite::TYPE_MESSAGE: - GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; - break; - } - } else { - switch (real_type(type)) { -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - WireFormatLite::Write##CAMELCASE(number, \ - repeated_##LOWERCASE##_value->Get(i), output); \ - } \ - break - - HANDLE_TYPE( INT32, Int32, int32); - HANDLE_TYPE( INT64, Int64, int64); - HANDLE_TYPE( UINT32, UInt32, uint32); - HANDLE_TYPE( UINT64, UInt64, uint64); - HANDLE_TYPE( SINT32, SInt32, int32); - HANDLE_TYPE( SINT64, SInt64, int64); - HANDLE_TYPE( FIXED32, Fixed32, uint32); - HANDLE_TYPE( FIXED64, Fixed64, uint64); - HANDLE_TYPE(SFIXED32, SFixed32, int32); - HANDLE_TYPE(SFIXED64, SFixed64, int64); - HANDLE_TYPE( FLOAT, Float, float); - HANDLE_TYPE( DOUBLE, Double, double); - HANDLE_TYPE( BOOL, Bool, bool); - HANDLE_TYPE( STRING, String, string); - HANDLE_TYPE( BYTES, Bytes, string); - HANDLE_TYPE( ENUM, Enum, enum); - HANDLE_TYPE( GROUP, Group, message); - HANDLE_TYPE( MESSAGE, Message, message); -#undef HANDLE_TYPE - } - } - } else if (!is_cleared) { - switch (real_type(type)) { -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - WireFormatLite::Write##CAMELCASE(number, VALUE, output); \ - break - - HANDLE_TYPE( INT32, Int32, int32_value); - HANDLE_TYPE( INT64, Int64, int64_value); - HANDLE_TYPE( UINT32, UInt32, uint32_value); - HANDLE_TYPE( UINT64, UInt64, uint64_value); - HANDLE_TYPE( SINT32, SInt32, int32_value); - HANDLE_TYPE( SINT64, SInt64, int64_value); - HANDLE_TYPE( FIXED32, Fixed32, uint32_value); - HANDLE_TYPE( FIXED64, Fixed64, uint64_value); - HANDLE_TYPE(SFIXED32, SFixed32, int32_value); - HANDLE_TYPE(SFIXED64, SFixed64, int64_value); - HANDLE_TYPE( FLOAT, Float, float_value); - HANDLE_TYPE( DOUBLE, Double, double_value); - HANDLE_TYPE( BOOL, Bool, bool_value); - HANDLE_TYPE( STRING, String, *string_value); - HANDLE_TYPE( BYTES, Bytes, *string_value); - HANDLE_TYPE( ENUM, Enum, enum_value); - HANDLE_TYPE( GROUP, Group, *message_value); -#undef HANDLE_TYPE - case WireFormatLite::TYPE_MESSAGE: - if (is_lazy) { - lazymessage_value->WriteMessage(number, output); - } else { - WireFormatLite::WriteMessage(number, *message_value, output); - } - break; - } - } -} - size_t ExtensionSet::Extension::ByteSize(int number) const { size_t result = 0; if (is_repeated) { if (is_packed) { switch (real_type(type)) { -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - result += WireFormatLite::CAMELCASE##Size( \ - repeated_##LOWERCASE##_value->Get(i)); \ - } \ - break - - HANDLE_TYPE( INT32, Int32, int32); - HANDLE_TYPE( INT64, Int64, int64); - HANDLE_TYPE( UINT32, UInt32, uint32); - HANDLE_TYPE( UINT64, UInt64, uint64); - HANDLE_TYPE( SINT32, SInt32, int32); - HANDLE_TYPE( SINT64, SInt64, int64); - HANDLE_TYPE( ENUM, Enum, enum); +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + result += WireFormatLite::CAMELCASE##Size( \ + repeated_##LOWERCASE##_value->Get(i)); \ + } \ + break + + HANDLE_TYPE(INT32, Int32, int32); + HANDLE_TYPE(INT64, Int64, int64); + HANDLE_TYPE(UINT32, UInt32, uint32); + HANDLE_TYPE(UINT64, UInt64, uint64); + HANDLE_TYPE(SINT32, SInt32, int32); + HANDLE_TYPE(SINT64, SInt64, int64); + HANDLE_TYPE(ENUM, Enum, enum); #undef HANDLE_TYPE // Stuff with fixed size. -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - result += WireFormatLite::k##CAMELCASE##Size * \ - FromIntSize(repeated_##LOWERCASE##_value->size()); \ - break - HANDLE_TYPE( FIXED32, Fixed32, uint32); - HANDLE_TYPE( FIXED64, Fixed64, uint64); - HANDLE_TYPE(SFIXED32, SFixed32, int32); - HANDLE_TYPE(SFIXED64, SFixed64, int64); - HANDLE_TYPE( FLOAT, Float, float); - HANDLE_TYPE( DOUBLE, Double, double); - HANDLE_TYPE( BOOL, Bool, bool); +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += WireFormatLite::k##CAMELCASE##Size * \ + FromIntSize(repeated_##LOWERCASE##_value->size()); \ + break + HANDLE_TYPE(FIXED32, Fixed32, uint32); + HANDLE_TYPE(FIXED64, Fixed64, uint64); + HANDLE_TYPE(SFIXED32, SFixed32, int32); + HANDLE_TYPE(SFIXED64, SFixed64, int64); + HANDLE_TYPE(FLOAT, Float, float); + HANDLE_TYPE(DOUBLE, Double, double); + HANDLE_TYPE(BOOL, Bool, bool); #undef HANDLE_TYPE case WireFormatLite::TYPE_STRING: @@ -1585,75 +1602,73 @@ size_t ExtensionSet::Extension::ByteSize(int number) const { cached_size = ToCachedSize(result); if (result > 0) { result += io::CodedOutputStream::VarintSize32(result); - result += io::CodedOutputStream::VarintSize32( - WireFormatLite::MakeTag(number, - WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); + result += io::CodedOutputStream::VarintSize32(WireFormatLite::MakeTag( + number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); } } else { size_t tag_size = WireFormatLite::TagSize(number, real_type(type)); switch (real_type(type)) { #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - result += tag_size * \ - FromIntSize(repeated_##LOWERCASE##_value->size()); \ - for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - result += WireFormatLite::CAMELCASE##Size( \ - repeated_##LOWERCASE##_value->Get(i)); \ - } \ - break - - HANDLE_TYPE( INT32, Int32, int32); - HANDLE_TYPE( INT64, Int64, int64); - HANDLE_TYPE( UINT32, UInt32, uint32); - HANDLE_TYPE( UINT64, UInt64, uint64); - HANDLE_TYPE( SINT32, SInt32, int32); - HANDLE_TYPE( SINT64, SInt64, int64); - HANDLE_TYPE( STRING, String, string); - HANDLE_TYPE( BYTES, Bytes, string); - HANDLE_TYPE( ENUM, Enum, enum); - HANDLE_TYPE( GROUP, Group, message); - HANDLE_TYPE( MESSAGE, Message, message); + case WireFormatLite::TYPE_##UPPERCASE: \ + result += tag_size * FromIntSize(repeated_##LOWERCASE##_value->size()); \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + result += WireFormatLite::CAMELCASE##Size( \ + repeated_##LOWERCASE##_value->Get(i)); \ + } \ + break + + HANDLE_TYPE(INT32, Int32, int32); + HANDLE_TYPE(INT64, Int64, int64); + HANDLE_TYPE(UINT32, UInt32, uint32); + HANDLE_TYPE(UINT64, UInt64, uint64); + HANDLE_TYPE(SINT32, SInt32, int32); + HANDLE_TYPE(SINT64, SInt64, int64); + HANDLE_TYPE(STRING, String, string); + HANDLE_TYPE(BYTES, Bytes, string); + HANDLE_TYPE(ENUM, Enum, enum); + HANDLE_TYPE(GROUP, Group, message); + HANDLE_TYPE(MESSAGE, Message, message); #undef HANDLE_TYPE // Stuff with fixed size. -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - result += (tag_size + WireFormatLite::k##CAMELCASE##Size) * \ - FromIntSize(repeated_##LOWERCASE##_value->size()); \ - break - HANDLE_TYPE( FIXED32, Fixed32, uint32); - HANDLE_TYPE( FIXED64, Fixed64, uint64); - HANDLE_TYPE(SFIXED32, SFixed32, int32); - HANDLE_TYPE(SFIXED64, SFixed64, int64); - HANDLE_TYPE( FLOAT, Float, float); - HANDLE_TYPE( DOUBLE, Double, double); - HANDLE_TYPE( BOOL, Bool, bool); +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += (tag_size + WireFormatLite::k##CAMELCASE##Size) * \ + FromIntSize(repeated_##LOWERCASE##_value->size()); \ + break + HANDLE_TYPE(FIXED32, Fixed32, uint32); + HANDLE_TYPE(FIXED64, Fixed64, uint64); + HANDLE_TYPE(SFIXED32, SFixed32, int32); + HANDLE_TYPE(SFIXED64, SFixed64, int64); + HANDLE_TYPE(FLOAT, Float, float); + HANDLE_TYPE(DOUBLE, Double, double); + HANDLE_TYPE(BOOL, Bool, bool); #undef HANDLE_TYPE } } } else if (!is_cleared) { result += WireFormatLite::TagSize(number, real_type(type)); switch (real_type(type)) { -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - result += WireFormatLite::CAMELCASE##Size(LOWERCASE); \ - break - - HANDLE_TYPE( INT32, Int32, int32_value); - HANDLE_TYPE( INT64, Int64, int64_value); - HANDLE_TYPE( UINT32, UInt32, uint32_value); - HANDLE_TYPE( UINT64, UInt64, uint64_value); - HANDLE_TYPE( SINT32, SInt32, int32_value); - HANDLE_TYPE( SINT64, SInt64, int64_value); - HANDLE_TYPE( STRING, String, *string_value); - HANDLE_TYPE( BYTES, Bytes, *string_value); - HANDLE_TYPE( ENUM, Enum, enum_value); - HANDLE_TYPE( GROUP, Group, *message_value); +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += WireFormatLite::CAMELCASE##Size(LOWERCASE); \ + break + + HANDLE_TYPE(INT32, Int32, int32_value); + HANDLE_TYPE(INT64, Int64, int64_value); + HANDLE_TYPE(UINT32, UInt32, uint32_value); + HANDLE_TYPE(UINT64, UInt64, uint64_value); + HANDLE_TYPE(SINT32, SInt32, int32_value); + HANDLE_TYPE(SINT64, SInt64, int64_value); + HANDLE_TYPE(STRING, String, *string_value); + HANDLE_TYPE(BYTES, Bytes, *string_value); + HANDLE_TYPE(ENUM, Enum, enum_value); + HANDLE_TYPE(GROUP, Group, *message_value); #undef HANDLE_TYPE case WireFormatLite::TYPE_MESSAGE: { if (is_lazy) { - size_t size = lazymessage_value->ByteSize(); + size_t size = lazymessage_value->ByteSizeLong(); result += io::CodedOutputStream::VarintSize32(size) + size; } else { result += WireFormatLite::MessageSize(*message_value); @@ -1662,17 +1677,17 @@ size_t ExtensionSet::Extension::ByteSize(int number) const { } // Stuff with fixed size. -#define HANDLE_TYPE(UPPERCASE, CAMELCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - result += WireFormatLite::k##CAMELCASE##Size; \ - break - HANDLE_TYPE( FIXED32, Fixed32); - HANDLE_TYPE( FIXED64, Fixed64); - HANDLE_TYPE(SFIXED32, SFixed32); - HANDLE_TYPE(SFIXED64, SFixed64); - HANDLE_TYPE( FLOAT, Float); - HANDLE_TYPE( DOUBLE, Double); - HANDLE_TYPE( BOOL, Bool); +#define HANDLE_TYPE(UPPERCASE, CAMELCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += WireFormatLite::k##CAMELCASE##Size; \ + break + HANDLE_TYPE(FIXED32, Fixed32); + HANDLE_TYPE(FIXED64, Fixed64); + HANDLE_TYPE(SFIXED32, SFixed32); + HANDLE_TYPE(SFIXED64, SFixed64); + HANDLE_TYPE(FLOAT, Float); + HANDLE_TYPE(DOUBLE, Double); + HANDLE_TYPE(BOOL, Bool); #undef HANDLE_TYPE } } @@ -1683,19 +1698,19 @@ size_t ExtensionSet::Extension::ByteSize(int number) const { int ExtensionSet::Extension::GetSize() const { GOOGLE_DCHECK(is_repeated); switch (cpp_type(type)) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case WireFormatLite::CPPTYPE_##UPPERCASE: \ - return repeated_##LOWERCASE##_value->size() - - HANDLE_TYPE( INT32, int32); - HANDLE_TYPE( INT64, int64); - HANDLE_TYPE( UINT32, uint32); - HANDLE_TYPE( UINT64, uint64); - HANDLE_TYPE( FLOAT, float); - HANDLE_TYPE( DOUBLE, double); - HANDLE_TYPE( BOOL, bool); - HANDLE_TYPE( ENUM, enum); - HANDLE_TYPE( STRING, string); +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + return repeated_##LOWERCASE##_value->size() + + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, enum); + HANDLE_TYPE(STRING, string); HANDLE_TYPE(MESSAGE, message); #undef HANDLE_TYPE } @@ -1709,20 +1724,20 @@ int ExtensionSet::Extension::GetSize() const { void ExtensionSet::Extension::Free() { if (is_repeated) { switch (cpp_type(type)) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case WireFormatLite::CPPTYPE_##UPPERCASE: \ - delete repeated_##LOWERCASE##_value; \ - break - - HANDLE_TYPE( INT32, int32); - HANDLE_TYPE( INT64, int64); - HANDLE_TYPE( UINT32, uint32); - HANDLE_TYPE( UINT64, uint64); - HANDLE_TYPE( FLOAT, float); - HANDLE_TYPE( DOUBLE, double); - HANDLE_TYPE( BOOL, bool); - HANDLE_TYPE( ENUM, enum); - HANDLE_TYPE( STRING, string); +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + delete repeated_##LOWERCASE##_value; \ + break + + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, enum); + HANDLE_TYPE(STRING, string); HANDLE_TYPE(MESSAGE, message); #undef HANDLE_TYPE } @@ -1747,71 +1762,380 @@ void ExtensionSet::Extension::Free() { // Defined in extension_set_heavy.cc. // int ExtensionSet::Extension::SpaceUsedExcludingSelf() const -// ================================================================== -// Default repeated field instances for iterator-compatible accessors +bool ExtensionSet::Extension::IsInitialized() const { + if (cpp_type(type) == WireFormatLite::CPPTYPE_MESSAGE) { + if (is_repeated) { + for (int i = 0; i < repeated_message_value->size(); i++) { + if (!repeated_message_value->Get(i).IsInitialized()) { + return false; + } + } + } else { + if (!is_cleared) { + if (is_lazy) { + if (!lazymessage_value->IsInitialized()) return false; + } else { + if (!message_value->IsInitialized()) return false; + } + } + } + } + return true; +} -GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_primitive_generic_type_traits_once_init_); -GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_string_type_traits_once_init_); -GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_message_generic_type_traits_once_init_); +// Dummy key method to avoid weak vtable. +void ExtensionSet::LazyMessageExtension::UnusedKeyMethod() {} -void RepeatedPrimitiveGenericTypeTraits::InitializeDefaultRepeatedFields() { - default_repeated_field_int32_ = new RepeatedField; - default_repeated_field_int64_ = new RepeatedField; - default_repeated_field_uint32_ = new RepeatedField; - default_repeated_field_uint64_ = new RepeatedField; - default_repeated_field_double_ = new RepeatedField; - default_repeated_field_float_ = new RepeatedField; - default_repeated_field_bool_ = new RepeatedField; - OnShutdown(&DestroyDefaultRepeatedFields); +const ExtensionSet::Extension* ExtensionSet::FindOrNull(int key) const { + if (PROTOBUF_PREDICT_FALSE(is_large())) { + return FindOrNullInLargeMap(key); + } + const KeyValue* end = flat_end(); + const KeyValue* it = + std::lower_bound(flat_begin(), end, key, KeyValue::FirstComparator()); + if (it != end && it->first == key) { + return &it->second; + } + return NULL; } -void RepeatedPrimitiveGenericTypeTraits::DestroyDefaultRepeatedFields() { - delete default_repeated_field_int32_; - delete default_repeated_field_int64_; - delete default_repeated_field_uint32_; - delete default_repeated_field_uint64_; - delete default_repeated_field_double_; - delete default_repeated_field_float_; - delete default_repeated_field_bool_; +const ExtensionSet::Extension* ExtensionSet::FindOrNullInLargeMap( + int key) const { + assert(is_large()); + LargeMap::const_iterator it = map_.large->find(key); + if (it != map_.large->end()) { + return &it->second; + } + return NULL; } -void RepeatedStringTypeTraits::InitializeDefaultRepeatedFields() { - default_repeated_field_ = new RepeatedFieldType; - OnShutdown(&DestroyDefaultRepeatedFields); +ExtensionSet::Extension* ExtensionSet::FindOrNull(int key) { + if (PROTOBUF_PREDICT_FALSE(is_large())) { + return FindOrNullInLargeMap(key); + } + KeyValue* end = flat_end(); + KeyValue* it = + std::lower_bound(flat_begin(), end, key, KeyValue::FirstComparator()); + if (it != end && it->first == key) { + return &it->second; + } + return NULL; } -void RepeatedStringTypeTraits::DestroyDefaultRepeatedFields() { - delete default_repeated_field_; +ExtensionSet::Extension* ExtensionSet::FindOrNullInLargeMap(int key) { + assert(is_large()); + LargeMap::iterator it = map_.large->find(key); + if (it != map_.large->end()) { + return &it->second; + } + return NULL; } -void RepeatedMessageGenericTypeTraits::InitializeDefaultRepeatedFields() { - default_repeated_field_ = new RepeatedFieldType; - OnShutdown(&DestroyDefaultRepeatedFields); +std::pair ExtensionSet::Insert(int key) { + if (PROTOBUF_PREDICT_FALSE(is_large())) { + auto maybe = map_.large->insert({key, Extension()}); + return {&maybe.first->second, maybe.second}; + } + KeyValue* end = flat_end(); + KeyValue* it = + std::lower_bound(flat_begin(), end, key, KeyValue::FirstComparator()); + if (it != end && it->first == key) { + return {&it->second, false}; + } + if (flat_size_ < flat_capacity_) { + std::copy_backward(it, end, end + 1); + ++flat_size_; + it->first = key; + it->second = Extension(); + return {&it->second, true}; + } + GrowCapacity(flat_size_ + 1); + return Insert(key); } -void RepeatedMessageGenericTypeTraits::DestroyDefaultRepeatedFields() { - delete default_repeated_field_; +void ExtensionSet::GrowCapacity(size_t minimum_new_capacity) { + if (PROTOBUF_PREDICT_FALSE(is_large())) { + return; // LargeMap does not have a "reserve" method. + } + if (flat_capacity_ >= minimum_new_capacity) { + return; + } + + auto new_flat_capacity = flat_capacity_; + do { + new_flat_capacity = new_flat_capacity == 0 ? 1 : new_flat_capacity * 4; + } while (new_flat_capacity < minimum_new_capacity); + + const KeyValue* begin = flat_begin(); + const KeyValue* end = flat_end(); + AllocatedData new_map; + if (new_flat_capacity > kMaximumFlatCapacity) { + new_map.large = Arena::Create(arena_); + LargeMap::iterator hint = new_map.large->begin(); + for (const KeyValue* it = begin; it != end; ++it) { + hint = new_map.large->insert(hint, {it->first, it->second}); + } + } else { + new_map.flat = Arena::CreateArray(arena_, new_flat_capacity); + std::copy(begin, end, new_map.flat); + } + + if (arena_ == nullptr) { + DeleteFlatMap(begin, flat_capacity_); + } + flat_capacity_ = new_flat_capacity; + map_ = new_map; +} + +// static +constexpr uint16 ExtensionSet::kMaximumFlatCapacity; + +void ExtensionSet::Erase(int key) { + if (PROTOBUF_PREDICT_FALSE(is_large())) { + map_.large->erase(key); + return; + } + KeyValue* end = flat_end(); + KeyValue* it = + std::lower_bound(flat_begin(), end, key, KeyValue::FirstComparator()); + if (it != end && it->first == key) { + std::copy(it + 1, end, it); + --flat_size_; + } +} + +// ================================================================== +// Default repeated field instances for iterator-compatible accessors + +const RepeatedPrimitiveDefaults* RepeatedPrimitiveDefaults::default_instance() { + static auto instance = OnShutdownDelete(new RepeatedPrimitiveDefaults); + return instance; } -const RepeatedField* -RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int32_ = NULL; -const RepeatedField* -RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int64_ = NULL; -const RepeatedField* -RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint32_ = NULL; -const RepeatedField* -RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint64_ = NULL; -const RepeatedField* -RepeatedPrimitiveGenericTypeTraits::default_repeated_field_double_ = NULL; -const RepeatedField* -RepeatedPrimitiveGenericTypeTraits::default_repeated_field_float_ = NULL; -const RepeatedField* -RepeatedPrimitiveGenericTypeTraits::default_repeated_field_bool_ = NULL; const RepeatedStringTypeTraits::RepeatedFieldType* -RepeatedStringTypeTraits::default_repeated_field_ = NULL; -const RepeatedMessageGenericTypeTraits::RepeatedFieldType* -RepeatedMessageGenericTypeTraits::default_repeated_field_ = NULL; +RepeatedStringTypeTraits::GetDefaultRepeatedField() { + static auto instance = OnShutdownDelete(new RepeatedFieldType); + return instance; +} + +uint8* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray( + int number, uint8* target, io::EpsCopyOutputStream* stream) const { + if (is_repeated) { + if (is_packed) { + if (cached_size == 0) return target; + + target = stream->EnsureSpace(target); + target = WireFormatLite::WriteTagToArray( + number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target); + target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target); + + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + target = stream->EnsureSpace(target); \ + target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \ + repeated_##LOWERCASE##_value->Get(i), target); \ + } \ + break + + HANDLE_TYPE(INT32, Int32, int32); + HANDLE_TYPE(INT64, Int64, int64); + HANDLE_TYPE(UINT32, UInt32, uint32); + HANDLE_TYPE(UINT64, UInt64, uint64); + HANDLE_TYPE(SINT32, SInt32, int32); + HANDLE_TYPE(SINT64, SInt64, int64); + HANDLE_TYPE(FIXED32, Fixed32, uint32); + HANDLE_TYPE(FIXED64, Fixed64, uint64); + HANDLE_TYPE(SFIXED32, SFixed32, int32); + HANDLE_TYPE(SFIXED64, SFixed64, int64); + HANDLE_TYPE(FLOAT, Float, float); + HANDLE_TYPE(DOUBLE, Double, double); + HANDLE_TYPE(BOOL, Bool, bool); + HANDLE_TYPE(ENUM, Enum, enum); +#undef HANDLE_TYPE + + case WireFormatLite::TYPE_STRING: + case WireFormatLite::TYPE_BYTES: + case WireFormatLite::TYPE_GROUP: + case WireFormatLite::TYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; + break; + } + } else { + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + target = stream->EnsureSpace(target); \ + target = WireFormatLite::Write##CAMELCASE##ToArray( \ + number, repeated_##LOWERCASE##_value->Get(i), target); \ + } \ + break + + HANDLE_TYPE(INT32, Int32, int32); + HANDLE_TYPE(INT64, Int64, int64); + HANDLE_TYPE(UINT32, UInt32, uint32); + HANDLE_TYPE(UINT64, UInt64, uint64); + HANDLE_TYPE(SINT32, SInt32, int32); + HANDLE_TYPE(SINT64, SInt64, int64); + HANDLE_TYPE(FIXED32, Fixed32, uint32); + HANDLE_TYPE(FIXED64, Fixed64, uint64); + HANDLE_TYPE(SFIXED32, SFixed32, int32); + HANDLE_TYPE(SFIXED64, SFixed64, int64); + HANDLE_TYPE(FLOAT, Float, float); + HANDLE_TYPE(DOUBLE, Double, double); + HANDLE_TYPE(BOOL, Bool, bool); + HANDLE_TYPE(ENUM, Enum, enum); +#undef HANDLE_TYPE +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + target = stream->EnsureSpace(target); \ + target = stream->WriteString( \ + number, repeated_##LOWERCASE##_value->Get(i), target); \ + } \ + break + HANDLE_TYPE(STRING, String, string); + HANDLE_TYPE(BYTES, Bytes, string); +#undef HANDLE_TYPE +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + target = stream->EnsureSpace(target); \ + target = WireFormatLite::InternalWrite##CAMELCASE( \ + number, repeated_##LOWERCASE##_value->Get(i), target, stream); \ + } \ + break + + HANDLE_TYPE(GROUP, Group, message); + HANDLE_TYPE(MESSAGE, Message, message); +#undef HANDLE_TYPE + } + } + } else if (!is_cleared) { + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + target = stream->EnsureSpace(target); \ + target = WireFormatLite::Write##CAMELCASE##ToArray(number, VALUE, target); \ + break + + HANDLE_TYPE(INT32, Int32, int32_value); + HANDLE_TYPE(INT64, Int64, int64_value); + HANDLE_TYPE(UINT32, UInt32, uint32_value); + HANDLE_TYPE(UINT64, UInt64, uint64_value); + HANDLE_TYPE(SINT32, SInt32, int32_value); + HANDLE_TYPE(SINT64, SInt64, int64_value); + HANDLE_TYPE(FIXED32, Fixed32, uint32_value); + HANDLE_TYPE(FIXED64, Fixed64, uint64_value); + HANDLE_TYPE(SFIXED32, SFixed32, int32_value); + HANDLE_TYPE(SFIXED64, SFixed64, int64_value); + HANDLE_TYPE(FLOAT, Float, float_value); + HANDLE_TYPE(DOUBLE, Double, double_value); + HANDLE_TYPE(BOOL, Bool, bool_value); + HANDLE_TYPE(ENUM, Enum, enum_value); +#undef HANDLE_TYPE +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + target = stream->EnsureSpace(target); \ + target = stream->WriteString(number, VALUE, target); \ + break + HANDLE_TYPE(STRING, String, *string_value); + HANDLE_TYPE(BYTES, Bytes, *string_value); +#undef HANDLE_TYPE + case WireFormatLite::TYPE_GROUP: + target = stream->EnsureSpace(target); + target = WireFormatLite::InternalWriteGroup(number, *message_value, + target, stream); + break; + case WireFormatLite::TYPE_MESSAGE: + if (is_lazy) { + target = + lazymessage_value->WriteMessageToArray(number, target, stream); + } else { + target = stream->EnsureSpace(target); + target = WireFormatLite::InternalWriteMessage(number, *message_value, + target, stream); + } + break; + } + } + return target; +} + +uint8* +ExtensionSet::Extension::InternalSerializeMessageSetItemWithCachedSizesToArray( + int number, uint8* target, io::EpsCopyOutputStream* stream) const { + if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { + // Not a valid MessageSet extension, but serialize it the normal way. + GOOGLE_LOG(WARNING) << "Invalid message set extension."; + return InternalSerializeFieldWithCachedSizesToArray(number, target, stream); + } + + if (is_cleared) return target; + + target = stream->EnsureSpace(target); + // Start group. + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetItemStartTag, target); + // Write type ID. + target = WireFormatLite::WriteUInt32ToArray( + WireFormatLite::kMessageSetTypeIdNumber, number, target); + // Write message. + if (is_lazy) { + target = lazymessage_value->WriteMessageToArray( + WireFormatLite::kMessageSetMessageNumber, target, stream); + } else { + target = WireFormatLite::InternalWriteMessage( + WireFormatLite::kMessageSetMessageNumber, *message_value, target, + stream); + } + // End group. + target = stream->EnsureSpace(target); + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetItemEndTag, target); + return target; +} + +size_t ExtensionSet::Extension::MessageSetItemByteSize(int number) const { + if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { + // Not a valid MessageSet extension, but compute the byte size for it the + // normal way. + return ByteSize(number); + } + + if (is_cleared) return 0; + + size_t our_size = WireFormatLite::kMessageSetItemTagsSize; + + // type_id + our_size += io::CodedOutputStream::VarintSize32(number); + + // message + size_t message_size = 0; + if (is_lazy) { + message_size = lazymessage_value->ByteSizeLong(); + } else { + message_size = message_value->ByteSizeLong(); + } + + our_size += io::CodedOutputStream::VarintSize32(message_size); + our_size += message_size; + + return our_size; +} + +size_t ExtensionSet::MessageSetByteSize() const { + size_t total_size = 0; + ForEach([&total_size](int number, const Extension& ext) { + total_size += ext.MessageSetItemByteSize(number); + }); + return total_size; +} } // namespace internal } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h index 6f47c4a678832..c4b845a8ee5e7 100644 --- a/src/google/protobuf/extension_set.h +++ b/src/google/protobuf/extension_set.h @@ -38,41 +38,49 @@ #ifndef GOOGLE_PROTOBUF_EXTENSION_SET_H__ #define GOOGLE_PROTOBUF_EXTENSION_SET_H__ -#include +#include +#include #include -#include #include - +#include +#include #include #include -#include - +#include +#include +#include #include +#include -namespace google { +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif +namespace google { namespace protobuf { - class Arena; - class Descriptor; // descriptor.h - class FieldDescriptor; // descriptor.h - class DescriptorPool; // descriptor.h - class MessageLite; // message_lite.h - class Message; // message.h - class MessageFactory; // message.h - class UnknownFieldSet; // unknown_field_set.h - namespace io { - class CodedInputStream; // coded_stream.h - class CodedOutputStream; // coded_stream.h - } - namespace internal { - class FieldSkipper; // wire_format_lite.h - } -} +class Arena; +class Descriptor; // descriptor.h +class FieldDescriptor; // descriptor.h +class DescriptorPool; // descriptor.h +class MessageLite; // message_lite.h +class Message; // message.h +class MessageFactory; // message.h +class UnknownFieldSet; // unknown_field_set.h +namespace internal { +class FieldSkipper; // wire_format_lite.h +} // namespace internal +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace internal { +class InternalMetadata; + // Used to store values of type WireFormatLite::FieldType without having to // #include wire_format_lite.h. Also, ensures that we use only one byte to // store these values, which is important to keep the layout of @@ -92,7 +100,9 @@ typedef bool EnumValidityFuncWithArg(const void* arg, int number); struct ExtensionInfo { inline ExtensionInfo() {} inline ExtensionInfo(FieldType type_param, bool isrepeated, bool ispacked) - : type(type_param), is_repeated(isrepeated), is_packed(ispacked), + : type(type_param), + is_repeated(isrepeated), + is_packed(ispacked), descriptor(NULL) {} FieldType type; @@ -104,9 +114,13 @@ struct ExtensionInfo { const void* arg; }; + struct MessageInfo { + const MessageLite* prototype; + }; + union { EnumValidityCheck enum_validity_check; - const MessageLite* message_prototype; + MessageInfo message_info; }; // The descriptor for this extension, if one exists and is known. May be @@ -117,7 +131,7 @@ struct ExtensionInfo { // Abstract interface for an object which looks up extension definitions. Used // when parsing. -class LIBPROTOBUF_EXPORT ExtensionFinder { +class PROTOBUF_EXPORT ExtensionFinder { public: virtual ~ExtensionFinder(); @@ -127,14 +141,14 @@ class LIBPROTOBUF_EXPORT ExtensionFinder { // Implementation of ExtensionFinder which finds extensions defined in .proto // files which have been compiled into the binary. -class LIBPROTOBUF_EXPORT GeneratedExtensionFinder : public ExtensionFinder { +class PROTOBUF_EXPORT GeneratedExtensionFinder : public ExtensionFinder { public: GeneratedExtensionFinder(const MessageLite* containing_type) : containing_type_(containing_type) {} - virtual ~GeneratedExtensionFinder() {} + ~GeneratedExtensionFinder() override {} // Returns true and fills in *output if found, otherwise returns false. - virtual bool Find(int number, ExtensionInfo* output); + bool Find(int number, ExtensionInfo* output) override; private: const MessageLite* containing_type_; @@ -157,10 +171,10 @@ class MessageSetFieldSkipper; // ExtensionSet. When parsing, if a tag number is encountered which is // inside one of the message type's extension ranges, the tag is passed // off to the ExtensionSet for parsing. Etc. -class LIBPROTOBUF_EXPORT ExtensionSet { +class PROTOBUF_EXPORT ExtensionSet { public: - ExtensionSet(); - explicit ExtensionSet(::google::protobuf::Arena* arena); + constexpr ExtensionSet(); + explicit ExtensionSet(Arena* arena); ~ExtensionSet(); // These are called at startup by protocol-compiler-generated code to @@ -168,9 +182,9 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // to look up extensions for parsed field numbers. Note that dynamic parsing // does not use ParseField(); only protocol-compiler-generated parsing // methods do. - static void RegisterExtension(const MessageLite* containing_type, - int number, FieldType type, - bool is_repeated, bool is_packed); + static void RegisterExtension(const MessageLite* containing_type, int number, + FieldType type, bool is_repeated, + bool is_packed); static void RegisterEnumExtension(const MessageLite* containing_type, int number, FieldType type, bool is_repeated, bool is_packed, @@ -219,22 +233,23 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // - Strings provide Mutable() in addition to Set() accessors. bool Has(int number) const; - int ExtensionSize(int number) const; // Size of a repeated extension. - int NumExtensions() const; // The number of extensions + int ExtensionSize(int number) const; // Size of a repeated extension. + int NumExtensions() const; // The number of extensions FieldType ExtensionType(int number) const; void ClearExtension(int number); // singular fields ------------------------------------------------- - int32 GetInt32 (int number, int32 default_value) const; - int64 GetInt64 (int number, int64 default_value) const; + int32 GetInt32(int number, int32 default_value) const; + int64 GetInt64(int number, int64 default_value) const; uint32 GetUInt32(int number, uint32 default_value) const; uint64 GetUInt64(int number, uint64 default_value) const; - float GetFloat (int number, float default_value) const; + float GetFloat(int number, float default_value) const; double GetDouble(int number, double default_value) const; - bool GetBool (int number, bool default_value) const; - int GetEnum (int number, int default_value) const; - const string & GetString (int number, const string& default_value) const; + bool GetBool(int number, bool default_value) const; + int GetEnum(int number, int default_value) const; + const std::string& GetString(int number, + const std::string& default_value) const; const MessageLite& GetMessage(int number, const MessageLite& default_value) const; const MessageLite& GetMessage(int number, const Descriptor* message_type, @@ -244,19 +259,19 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // the extension lives in the same pool as the descriptor for the containing // type. #define desc const FieldDescriptor* descriptor // avoid line wrapping - void SetInt32 (int number, FieldType type, int32 value, desc); - void SetInt64 (int number, FieldType type, int64 value, desc); + void SetInt32(int number, FieldType type, int32 value, desc); + void SetInt64(int number, FieldType type, int64 value, desc); void SetUInt32(int number, FieldType type, uint32 value, desc); void SetUInt64(int number, FieldType type, uint64 value, desc); - void SetFloat (int number, FieldType type, float value, desc); + void SetFloat(int number, FieldType type, float value, desc); void SetDouble(int number, FieldType type, double value, desc); - void SetBool (int number, FieldType type, bool value, desc); - void SetEnum (int number, FieldType type, int value, desc); - void SetString(int number, FieldType type, const string& value, desc); - string * MutableString (int number, FieldType type, desc); + void SetBool(int number, FieldType type, bool value, desc); + void SetEnum(int number, FieldType type, int value, desc); + void SetString(int number, FieldType type, std::string value, desc); + std::string* MutableString(int number, FieldType type, desc); MessageLite* MutableMessage(int number, FieldType type, const MessageLite& prototype, desc); - MessageLite* MutableMessage(const FieldDescriptor* decsriptor, + MessageLite* MutableMessage(const FieldDescriptor* descriptor, MessageFactory* factory); // Adds the given message to the ExtensionSet, taking ownership of the // message object. Existing message with the same number will be deleted. @@ -268,15 +283,15 @@ class LIBPROTOBUF_EXPORT ExtensionSet { const FieldDescriptor* descriptor, MessageLite* message); MessageLite* ReleaseMessage(int number, const MessageLite& prototype); - MessageLite* UnsafeArenaReleaseMessage( - int number, const MessageLite& prototype); + MessageLite* UnsafeArenaReleaseMessage(int number, + const MessageLite& prototype); MessageLite* ReleaseMessage(const FieldDescriptor* descriptor, MessageFactory* factory); MessageLite* UnsafeArenaReleaseMessage(const FieldDescriptor* descriptor, MessageFactory* factory); #undef desc - ::google::protobuf::Arena* GetArenaNoVirtual() const { return arena_; } + Arena* GetArena() const { return arena_; } // repeated fields ------------------------------------------------- @@ -287,8 +302,8 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // Fetches a mutable version of a RepeatedField extension by number, // instantiating one if none exists. Similar to above, user should not use // this directly; it underlies MutableRepeatedExtension(). - void* MutableRawRepeatedField(int number, FieldType field_type, - bool packed, const FieldDescriptor* desc); + void* MutableRawRepeatedField(int number, FieldType field_type, bool packed, + const FieldDescriptor* desc); // This is an overload of MutableRawRepeatedField to maintain compatibility // with old code using a previous API. This version of @@ -296,40 +311,40 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // (E.g.: borg/clients/internal/proto1/proto2_reflection.cc.) void* MutableRawRepeatedField(int number); - int32 GetRepeatedInt32 (int number, int index) const; - int64 GetRepeatedInt64 (int number, int index) const; + int32 GetRepeatedInt32(int number, int index) const; + int64 GetRepeatedInt64(int number, int index) const; uint32 GetRepeatedUInt32(int number, int index) const; uint64 GetRepeatedUInt64(int number, int index) const; - float GetRepeatedFloat (int number, int index) const; + float GetRepeatedFloat(int number, int index) const; double GetRepeatedDouble(int number, int index) const; - bool GetRepeatedBool (int number, int index) const; - int GetRepeatedEnum (int number, int index) const; - const string & GetRepeatedString (int number, int index) const; + bool GetRepeatedBool(int number, int index) const; + int GetRepeatedEnum(int number, int index) const; + const std::string& GetRepeatedString(int number, int index) const; const MessageLite& GetRepeatedMessage(int number, int index) const; - void SetRepeatedInt32 (int number, int index, int32 value); - void SetRepeatedInt64 (int number, int index, int64 value); + void SetRepeatedInt32(int number, int index, int32 value); + void SetRepeatedInt64(int number, int index, int64 value); void SetRepeatedUInt32(int number, int index, uint32 value); void SetRepeatedUInt64(int number, int index, uint64 value); - void SetRepeatedFloat (int number, int index, float value); + void SetRepeatedFloat(int number, int index, float value); void SetRepeatedDouble(int number, int index, double value); - void SetRepeatedBool (int number, int index, bool value); - void SetRepeatedEnum (int number, int index, int value); - void SetRepeatedString(int number, int index, const string& value); - string * MutableRepeatedString (int number, int index); + void SetRepeatedBool(int number, int index, bool value); + void SetRepeatedEnum(int number, int index, int value); + void SetRepeatedString(int number, int index, std::string value); + std::string* MutableRepeatedString(int number, int index); MessageLite* MutableRepeatedMessage(int number, int index); #define desc const FieldDescriptor* descriptor // avoid line wrapping - void AddInt32 (int number, FieldType type, bool packed, int32 value, desc); - void AddInt64 (int number, FieldType type, bool packed, int64 value, desc); + void AddInt32(int number, FieldType type, bool packed, int32 value, desc); + void AddInt64(int number, FieldType type, bool packed, int64 value, desc); void AddUInt32(int number, FieldType type, bool packed, uint32 value, desc); void AddUInt64(int number, FieldType type, bool packed, uint64 value, desc); - void AddFloat (int number, FieldType type, bool packed, float value, desc); + void AddFloat(int number, FieldType type, bool packed, float value, desc); void AddDouble(int number, FieldType type, bool packed, double value, desc); - void AddBool (int number, FieldType type, bool packed, bool value, desc); - void AddEnum (int number, FieldType type, bool packed, int value, desc); - void AddString(int number, FieldType type, const string& value, desc); - string * AddString (int number, FieldType type, desc); + void AddBool(int number, FieldType type, bool packed, bool value, desc); + void AddEnum(int number, FieldType type, bool packed, int value, desc); + void AddString(int number, FieldType type, std::string value, desc); + std::string* AddString(int number, FieldType type, desc); MessageLite* AddMessage(int number, FieldType type, const MessageLite& prototype, desc); MessageLite* AddMessage(const FieldDescriptor* descriptor, @@ -378,8 +393,52 @@ class LIBPROTOBUF_EXPORT ExtensionSet { const MessageLite* containing_type, io::CodedOutputStream* unknown_fields); + // Lite parser + const char* ParseField(uint64 tag, const char* ptr, + const MessageLite* containing_type, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx); + // Full parser + const char* ParseField(uint64 tag, const char* ptr, + const Message* containing_type, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx); + template + const char* ParseMessageSet(const char* ptr, const Msg* containing_type, + InternalMetadata* metadata, + internal::ParseContext* ctx) { + struct MessageSetItem { + const char* _InternalParse(const char* ptr, ParseContext* ctx) { + return me->ParseMessageSetItem(ptr, containing_type, metadata, ctx); + } + ExtensionSet* me; + const Msg* containing_type; + InternalMetadata* metadata; + } item{this, containing_type, metadata}; + while (!ctx->Done(&ptr)) { + uint32 tag; + ptr = ReadTag(ptr, &tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + if (tag == WireFormatLite::kMessageSetItemStartTag) { + ptr = ctx->ParseGroup(&item, ptr, tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + } else { + if (tag == 0 || (tag & 7) == 4) { + ctx->SetLastTag(tag); + return ptr; + } + ptr = ParseField(tag, ptr, containing_type, metadata, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + } + } + return ptr; + } + // Parse an entire message in MessageSet format. Such messages have no // fields, only extensions. + bool ParseMessageSetLite(io::CodedInputStream* input, + ExtensionFinder* extension_finder, + FieldSkipper* field_skipper); bool ParseMessageSet(io::CodedInputStream* input, ExtensionFinder* extension_finder, MessageSetFieldSkipper* field_skipper); @@ -387,7 +446,8 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // Specific versions for lite or full messages (constructs the appropriate // FieldSkipper automatically). bool ParseMessageSet(io::CodedInputStream* input, - const MessageLite* containing_type); + const MessageLite* containing_type, + std::string* unknown_fields); bool ParseMessageSet(io::CodedInputStream* input, const Message* containing_type, UnknownFieldSet* unknown_fields); @@ -396,24 +456,35 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // [start_field_number, end_field_number) // to the output stream, using the cached sizes computed when ByteSize() was // last called. Note that the range bounds are inclusive-exclusive. - void SerializeWithCachedSizes(int start_field_number, - int end_field_number, - io::CodedOutputStream* output) const; + void SerializeWithCachedSizes(int start_field_number, int end_field_number, + io::CodedOutputStream* output) const { + output->SetCur(_InternalSerialize(start_field_number, end_field_number, + output->Cur(), output->EpsCopy())); + } // Same as SerializeWithCachedSizes, but without any bounds checking. // The caller must ensure that target has sufficient capacity for the // serialized extensions. // // Returns a pointer past the last written byte. - uint8* InternalSerializeWithCachedSizesToArray(int start_field_number, - int end_field_number, - bool deterministic, - uint8* target) const; + uint8* _InternalSerialize(int start_field_number, int end_field_number, + uint8* target, + io::EpsCopyOutputStream* stream) const { + if (flat_size_ == 0) { + assert(!is_large()); + return target; + } + return _InternalSerializeImpl(start_field_number, end_field_number, target, + stream); + } // Like above but serializes in MessageSet format. - void SerializeMessageSetWithCachedSizes(io::CodedOutputStream* output) const; - uint8* InternalSerializeMessageSetWithCachedSizesToArray(bool deterministic, - uint8* target) const; + void SerializeMessageSetWithCachedSizes(io::CodedOutputStream* output) const { + output->SetCur(InternalSerializeMessageSetWithCachedSizesToArray( + output->Cur(), output->EpsCopy())); + } + uint8* InternalSerializeMessageSetWithCachedSizesToArray( + uint8* target, io::EpsCopyOutputStream* stream) const; // For backward-compatibility, versions of two of the above methods that // serialize deterministically iff SetDefaultSerializationDeterministic() @@ -446,25 +517,31 @@ class LIBPROTOBUF_EXPORT ExtensionSet { int SpaceUsedExcludingSelf() const; private: - + // Implementation of _InternalSerialize for non-empty map_. + uint8* _InternalSerializeImpl(int start_field_number, int end_field_number, + uint8* target, + io::EpsCopyOutputStream* stream) const; // Interface of a lazily parsed singular message extension. - class LIBPROTOBUF_EXPORT LazyMessageExtension { + class PROTOBUF_EXPORT LazyMessageExtension { public: LazyMessageExtension() {} virtual ~LazyMessageExtension() {} - virtual LazyMessageExtension* New(::google::protobuf::Arena* arena) const = 0; + virtual LazyMessageExtension* New(Arena* arena) const = 0; virtual const MessageLite& GetMessage( const MessageLite& prototype) const = 0; virtual MessageLite* MutableMessage(const MessageLite& prototype) = 0; - virtual void SetAllocatedMessage(MessageLite *message) = 0; - virtual void UnsafeArenaSetAllocatedMessage(MessageLite *message) = 0; + virtual void SetAllocatedMessage(MessageLite* message) = 0; + virtual void UnsafeArenaSetAllocatedMessage(MessageLite* message) = 0; virtual MessageLite* ReleaseMessage(const MessageLite& prototype) = 0; virtual MessageLite* UnsafeArenaReleaseMessage( const MessageLite& prototype) = 0; virtual bool IsInitialized() const = 0; - virtual int ByteSize() const = 0; + + PROTOBUF_DEPRECATED_MSG("Please use ByteSizeLong() instead") + virtual int ByteSize() const { return internal::ToIntSize(ByteSizeLong()); } + virtual size_t ByteSizeLong() const = 0; virtual size_t SpaceUsedLong() const = 0; virtual void MergeFrom(const LazyMessageExtension& other) = 0; @@ -472,44 +549,40 @@ class LIBPROTOBUF_EXPORT ExtensionSet { virtual bool ReadMessage(const MessageLite& prototype, io::CodedInputStream* input) = 0; - virtual void WriteMessage(int number, - io::CodedOutputStream* output) const = 0; - virtual uint8* WriteMessageToArray(int number, uint8* target) const = 0; - virtual uint8* InternalWriteMessageToArray(int number, bool, - uint8* target) const { - // TODO(gpike): make this pure virtual. This is a placeholder because we - // need to update third_party/upb, for example. - return WriteMessageToArray(number, target); - } + virtual const char* _InternalParse(const char* ptr, ParseContext* ctx) = 0; + virtual uint8* WriteMessageToArray( + int number, uint8* target, io::EpsCopyOutputStream* stream) const = 0; private: + virtual void UnusedKeyMethod(); // Dummy key method to avoid weak vtable. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyMessageExtension); }; struct Extension { // The order of these fields packs Extension into 24 bytes when using 8 // byte alignment. Consider this when adding or removing fields here. union { - int32 int32_value; - int64 int64_value; - uint32 uint32_value; - uint64 uint64_value; - float float_value; - double double_value; - bool bool_value; - int enum_value; - string* string_value; - MessageLite* message_value; + int32 int32_value; + int64 int64_value; + uint32 uint32_value; + uint64 uint64_value; + float float_value; + double double_value; + bool bool_value; + int enum_value; + std::string* string_value; + MessageLite* message_value; LazyMessageExtension* lazymessage_value; - RepeatedField * repeated_int32_value; - RepeatedField * repeated_int64_value; - RepeatedField * repeated_uint32_value; - RepeatedField * repeated_uint64_value; - RepeatedField * repeated_float_value; - RepeatedField * repeated_double_value; - RepeatedField * repeated_bool_value; - RepeatedField * repeated_enum_value; - RepeatedPtrField* repeated_string_value; + RepeatedField* repeated_int32_value; + RepeatedField* repeated_int64_value; + RepeatedField* repeated_uint32_value; + RepeatedField* repeated_uint64_value; + RepeatedField* repeated_float_value; + RepeatedField* repeated_double_value; + RepeatedField* repeated_bool_value; + RepeatedField* repeated_enum_value; + RepeatedPtrField* repeated_string_value; RepeatedPtrField* repeated_message_value; }; @@ -545,29 +618,99 @@ class LIBPROTOBUF_EXPORT ExtensionSet { const FieldDescriptor* descriptor; // Some helper methods for operations on a single Extension. - void SerializeFieldWithCachedSizes( - int number, - io::CodedOutputStream* output) const; uint8* InternalSerializeFieldWithCachedSizesToArray( - int number, - bool deterministic, - uint8* target) const; - void SerializeMessageSetItemWithCachedSizes( - int number, - io::CodedOutputStream* output) const; + int number, uint8* target, io::EpsCopyOutputStream* stream) const; uint8* InternalSerializeMessageSetItemWithCachedSizesToArray( - int number, - bool deterministic, - uint8* target) const; + int number, uint8* target, io::EpsCopyOutputStream* stream) const; size_t ByteSize(int number) const; size_t MessageSetItemByteSize(int number) const; void Clear(); int GetSize() const; void Free(); size_t SpaceUsedExcludingSelfLong() const; + bool IsInitialized() const; }; - typedef std::map ExtensionMap; + // The Extension struct is small enough to be passed by value, so we use it + // directly as the value type in mappings rather than use pointers. We use + // sorted maps rather than hash-maps because we expect most ExtensionSets will + // only contain a small number of extension. Also, we want AppendToList and + // deterministic serialization to order fields by field number. + + struct KeyValue { + int first; + Extension second; + + struct FirstComparator { + bool operator()(const KeyValue& lhs, const KeyValue& rhs) const { + return lhs.first < rhs.first; + } + bool operator()(const KeyValue& lhs, int key) const { + return lhs.first < key; + } + bool operator()(int key, const KeyValue& rhs) const { + return key < rhs.first; + } + }; + }; + + typedef std::map LargeMap; + + // Wrapper API that switches between flat-map and LargeMap. + + // Finds a key (if present) in the ExtensionSet. + const Extension* FindOrNull(int key) const; + Extension* FindOrNull(int key); + + // Helper-functions that only inspect the LargeMap. + const Extension* FindOrNullInLargeMap(int key) const; + Extension* FindOrNullInLargeMap(int key); + + // Inserts a new (key, Extension) into the ExtensionSet (and returns true), or + // finds the already-existing Extension for that key (returns false). + // The Extension* will point to the new-or-found Extension. + std::pair Insert(int key); + + // Grows the flat_capacity_. + // If flat_capacity_ > kMaximumFlatCapacity, converts to LargeMap. + void GrowCapacity(size_t minimum_new_capacity); + static constexpr uint16 kMaximumFlatCapacity = 256; + bool is_large() const { return flat_capacity_ > kMaximumFlatCapacity; } + + // Removes a key from the ExtensionSet. + void Erase(int key); + + size_t Size() const { + return PROTOBUF_PREDICT_FALSE(is_large()) ? map_.large->size() : flat_size_; + } + + // Similar to std::for_each. + // Each Iterator is decomposed into ->first and ->second fields, so + // that the KeyValueFunctor can be agnostic vis-a-vis KeyValue-vs-std::pair. + template + static KeyValueFunctor ForEach(Iterator begin, Iterator end, + KeyValueFunctor func) { + for (Iterator it = begin; it != end; ++it) func(it->first, it->second); + return std::move(func); + } + + // Applies a functor to the pairs in sorted order. + template + KeyValueFunctor ForEach(KeyValueFunctor func) { + if (PROTOBUF_PREDICT_FALSE(is_large())) { + return ForEach(map_.large->begin(), map_.large->end(), std::move(func)); + } + return ForEach(flat_begin(), flat_end(), std::move(func)); + } + + // Applies a functor to the pairs in sorted order. + template + KeyValueFunctor ForEach(KeyValueFunctor func) const { + if (PROTOBUF_PREDICT_FALSE(is_large())) { + return ForEach(map_.large->begin(), map_.large->end(), std::move(func)); + } + return ForEach(flat_begin(), flat_end(), std::move(func)); + } // Merges existing Extension from other_extension void InternalExtensionMergeFrom(int number, const Extension& other_extension); @@ -593,8 +736,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // positioned immediately after the wire tag. This method is called in // ParseField() after field number and was_packed_on_wire is extracted from // the wire tag and ExtensionInfo is found by the field number. - bool ParseFieldWithExtensionInfo(int field_number, - bool was_packed_on_wire, + bool ParseFieldWithExtensionInfo(int field_number, bool was_packed_on_wire, const ExtensionInfo& extension, io::CodedInputStream* input, FieldSkipper* field_skipper); @@ -615,12 +757,63 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // it does not exist. Extension* MaybeNewRepeatedExtension(const FieldDescriptor* descriptor); + // Parse a single MessageSet item -- called just after the item group start + // tag has been read. + bool ParseMessageSetItemLite(io::CodedInputStream* input, + ExtensionFinder* extension_finder, + FieldSkipper* field_skipper); // Parse a single MessageSet item -- called just after the item group start // tag has been read. bool ParseMessageSetItem(io::CodedInputStream* input, ExtensionFinder* extension_finder, MessageSetFieldSkipper* field_skipper); + bool FindExtension(int wire_type, uint32 field, + const MessageLite* containing_type, + const internal::ParseContext* /*ctx*/, + ExtensionInfo* extension, bool* was_packed_on_wire) { + GeneratedExtensionFinder finder(containing_type); + return FindExtensionInfoFromFieldNumber(wire_type, field, &finder, + extension, was_packed_on_wire); + } + inline bool FindExtension(int wire_type, uint32 field, + const Message* containing_type, + const internal::ParseContext* ctx, + ExtensionInfo* extension, bool* was_packed_on_wire); + // Used for MessageSet only + const char* ParseFieldMaybeLazily(uint64 tag, const char* ptr, + const MessageLite* containing_type, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx) { + // Lite MessageSet doesn't implement lazy. + return ParseField(tag, ptr, containing_type, metadata, ctx); + } + const char* ParseFieldMaybeLazily(uint64 tag, const char* ptr, + const Message* containing_type, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx); + const char* ParseMessageSetItem(const char* ptr, + const MessageLite* containing_type, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx); + const char* ParseMessageSetItem(const char* ptr, + const Message* containing_type, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx); + + // Implemented in extension_set_inl.h to keep code out of the header file. + template + const char* ParseFieldWithExtensionInfo(int number, bool was_packed_on_wire, + const ExtensionInfo& info, + internal::InternalMetadata* metadata, + const char* ptr, + internal::ParseContext* ctx); + template + const char* ParseMessageSetItemTmpl(const char* ptr, + const Msg* containing_type, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx); + // Hack: RepeatedPtrFieldBase declares ExtensionSet as a friend. This // friendship should automatically extend to ExtensionSet::Extension, but // unfortunately some older compilers (e.g. GCC 3.4.4) do not implement this @@ -631,33 +824,61 @@ class LIBPROTOBUF_EXPORT ExtensionSet { static inline size_t RepeatedMessage_SpaceUsedExcludingSelfLong( RepeatedPtrFieldBase* field); - // The Extension struct is small enough to be passed by value, so we use it - // directly as the value type in the map rather than use pointers. We use - // a map rather than hash_map here because we expect most ExtensionSets will - // only contain a small number of extensions whereas hash_map is optimized - // for 100 elements or more. Also, we want AppendToList() to order fields - // by field number. - ExtensionMap extensions_; - ::google::protobuf::Arena* arena_; + KeyValue* flat_begin() { + assert(!is_large()); + return map_.flat; + } + const KeyValue* flat_begin() const { + assert(!is_large()); + return map_.flat; + } + KeyValue* flat_end() { + assert(!is_large()); + return map_.flat + flat_size_; + } + const KeyValue* flat_end() const { + assert(!is_large()); + return map_.flat + flat_size_; + } + + Arena* arena_; + + // Manual memory-management: + // map_.flat is an allocated array of flat_capacity_ elements. + // [map_.flat, map_.flat + flat_size_) is the currently-in-use prefix. + uint16 flat_capacity_; + uint16 flat_size_; + union AllocatedData { + KeyValue* flat; + + // If flat_capacity_ > kMaximumFlatCapacity, switch to LargeMap, + // which guarantees O(n lg n) CPU but larger constant factors. + LargeMap* large; + } map_; + + static void DeleteFlatMap(const KeyValue* flat, uint16 flat_capacity); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet); }; +constexpr ExtensionSet::ExtensionSet() + : arena_(nullptr), flat_capacity_(0), flat_size_(0), map_{nullptr} {} + // These are just for convenience... inline void ExtensionSet::SetString(int number, FieldType type, - const string& value, + std::string value, const FieldDescriptor* descriptor) { - MutableString(number, type, descriptor)->assign(value); + MutableString(number, type, descriptor)->assign(std::move(value)); } inline void ExtensionSet::SetRepeatedString(int number, int index, - const string& value) { - MutableRepeatedString(number, index)->assign(value); + std::string value) { + MutableRepeatedString(number, index)->assign(std::move(value)); } inline void ExtensionSet::AddString(int number, FieldType type, - const string& value, + std::string value, const FieldDescriptor* descriptor) { - AddString(number, type, descriptor)->assign(value); + AddString(number, type, descriptor)->assign(std::move(value)); } - // =================================================================== // Glue for generated extension accessors @@ -697,6 +918,10 @@ inline void ExtensionSet::AddString(int number, FieldType type, // ExtensionSet* set); // static inline void Add(int number, ConstType value, ExtensionSet* set); // static inline MutableType Add(int number, ExtensionSet* set); +// This is used by the ExtensionIdentifier constructor to register +// the extension at dynamic initialization. +// template +// static void Register(int number, FieldType type, bool is_packed); // }; // // Not all of these methods make sense for all field types. For example, the @@ -726,8 +951,13 @@ class PrimitiveTypeTraits { static inline ConstType Get(int number, const ExtensionSet& set, ConstType default_value); - static inline void Set(int number, FieldType field_type, - ConstType value, ExtensionSet* set); + static inline void Set(int number, FieldType field_type, ConstType value, + ExtensionSet* set); + template + static void Register(int number, FieldType type, bool is_packed) { + ExtensionSet::RegisterExtension(&ExtendeeT::default_instance(), number, + type, false, is_packed); + } }; template @@ -741,88 +971,94 @@ class RepeatedPrimitiveTypeTraits { static inline Type Get(int number, const ExtensionSet& set, int index); static inline void Set(int number, int index, Type value, ExtensionSet* set); - static inline void Add(int number, FieldType field_type, - bool is_packed, Type value, ExtensionSet* set); + static inline void Add(int number, FieldType field_type, bool is_packed, + Type value, ExtensionSet* set); - static inline const RepeatedField& - GetRepeated(int number, const ExtensionSet& set); - static inline RepeatedField* - MutableRepeated(int number, FieldType field_type, - bool is_packed, ExtensionSet* set); + static inline const RepeatedField& GetRepeated( + int number, const ExtensionSet& set); + static inline RepeatedField* MutableRepeated(int number, + FieldType field_type, + bool is_packed, + ExtensionSet* set); static const RepeatedFieldType* GetDefaultRepeatedField(); + template + static void Register(int number, FieldType type, bool is_packed) { + ExtensionSet::RegisterExtension(&ExtendeeT::default_instance(), number, + type, true, is_packed); + } }; -LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_primitive_generic_type_traits_once_init_; - -class LIBPROTOBUF_EXPORT RepeatedPrimitiveGenericTypeTraits { +class PROTOBUF_EXPORT RepeatedPrimitiveDefaults { private: - template friend class RepeatedPrimitiveTypeTraits; - static void InitializeDefaultRepeatedFields(); - static void DestroyDefaultRepeatedFields(); - static const RepeatedField* default_repeated_field_int32_; - static const RepeatedField* default_repeated_field_int64_; - static const RepeatedField* default_repeated_field_uint32_; - static const RepeatedField* default_repeated_field_uint64_; - static const RepeatedField* default_repeated_field_double_; - static const RepeatedField* default_repeated_field_float_; - static const RepeatedField* default_repeated_field_bool_; + template + friend class RepeatedPrimitiveTypeTraits; + static const RepeatedPrimitiveDefaults* default_instance(); + RepeatedField default_repeated_field_int32_; + RepeatedField default_repeated_field_int64_; + RepeatedField default_repeated_field_uint32_; + RepeatedField default_repeated_field_uint64_; + RepeatedField default_repeated_field_double_; + RepeatedField default_repeated_field_float_; + RepeatedField default_repeated_field_bool_; }; -#define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD) \ -template<> inline TYPE PrimitiveTypeTraits::Get( \ - int number, const ExtensionSet& set, TYPE default_value) { \ - return set.Get##METHOD(number, default_value); \ -} \ -template<> inline void PrimitiveTypeTraits::Set( \ - int number, FieldType field_type, TYPE value, ExtensionSet* set) { \ - set->Set##METHOD(number, field_type, value, NULL); \ -} \ - \ -template<> inline TYPE RepeatedPrimitiveTypeTraits::Get( \ - int number, const ExtensionSet& set, int index) { \ - return set.GetRepeated##METHOD(number, index); \ -} \ -template<> inline void RepeatedPrimitiveTypeTraits::Set( \ - int number, int index, TYPE value, ExtensionSet* set) { \ - set->SetRepeated##METHOD(number, index, value); \ -} \ -template<> inline void RepeatedPrimitiveTypeTraits::Add( \ - int number, FieldType field_type, bool is_packed, \ - TYPE value, ExtensionSet* set) { \ - set->Add##METHOD(number, field_type, is_packed, value, NULL); \ -} \ -template<> inline const RepeatedField* \ - RepeatedPrimitiveTypeTraits::GetDefaultRepeatedField() { \ - ::google::protobuf::GoogleOnceInit( \ - &repeated_primitive_generic_type_traits_once_init_, \ - &RepeatedPrimitiveGenericTypeTraits::InitializeDefaultRepeatedFields); \ - return RepeatedPrimitiveGenericTypeTraits:: \ - default_repeated_field_##TYPE##_; \ -} \ -template<> inline const RepeatedField& \ - RepeatedPrimitiveTypeTraits::GetRepeated(int number, \ - const ExtensionSet& set) { \ - return *reinterpret_cast*>( \ - set.GetRawRepeatedField( \ - number, GetDefaultRepeatedField())); \ -} \ -template<> inline RepeatedField* \ - RepeatedPrimitiveTypeTraits::MutableRepeated(int number, \ - FieldType field_type, \ - bool is_packed, \ - ExtensionSet* set) { \ - return reinterpret_cast*>( \ - set->MutableRawRepeatedField(number, field_type, is_packed, NULL)); \ -} +#define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD) \ + template <> \ + inline TYPE PrimitiveTypeTraits::Get( \ + int number, const ExtensionSet& set, TYPE default_value) { \ + return set.Get##METHOD(number, default_value); \ + } \ + template <> \ + inline void PrimitiveTypeTraits::Set(int number, FieldType field_type, \ + TYPE value, ExtensionSet* set) { \ + set->Set##METHOD(number, field_type, value, NULL); \ + } \ + \ + template <> \ + inline TYPE RepeatedPrimitiveTypeTraits::Get( \ + int number, const ExtensionSet& set, int index) { \ + return set.GetRepeated##METHOD(number, index); \ + } \ + template <> \ + inline void RepeatedPrimitiveTypeTraits::Set( \ + int number, int index, TYPE value, ExtensionSet* set) { \ + set->SetRepeated##METHOD(number, index, value); \ + } \ + template <> \ + inline void RepeatedPrimitiveTypeTraits::Add( \ + int number, FieldType field_type, bool is_packed, TYPE value, \ + ExtensionSet* set) { \ + set->Add##METHOD(number, field_type, is_packed, value, NULL); \ + } \ + template <> \ + inline const RepeatedField* \ + RepeatedPrimitiveTypeTraits::GetDefaultRepeatedField() { \ + return &RepeatedPrimitiveDefaults::default_instance() \ + ->default_repeated_field_##TYPE##_; \ + } \ + template <> \ + inline const RepeatedField& \ + RepeatedPrimitiveTypeTraits::GetRepeated(int number, \ + const ExtensionSet& set) { \ + return *reinterpret_cast*>( \ + set.GetRawRepeatedField(number, GetDefaultRepeatedField())); \ + } \ + template <> \ + inline RepeatedField* \ + RepeatedPrimitiveTypeTraits::MutableRepeated( \ + int number, FieldType field_type, bool is_packed, ExtensionSet* set) { \ + return reinterpret_cast*>( \ + set->MutableRawRepeatedField(number, field_type, is_packed, NULL)); \ + } -PROTOBUF_DEFINE_PRIMITIVE_TYPE( int32, Int32) -PROTOBUF_DEFINE_PRIMITIVE_TYPE( int64, Int64) +PROTOBUF_DEFINE_PRIMITIVE_TYPE(int32, Int32) +PROTOBUF_DEFINE_PRIMITIVE_TYPE(int64, Int64) PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint32, UInt32) PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint64, UInt64) -PROTOBUF_DEFINE_PRIMITIVE_TYPE( float, Float) +PROTOBUF_DEFINE_PRIMITIVE_TYPE(float, Float) PROTOBUF_DEFINE_PRIMITIVE_TYPE(double, Double) -PROTOBUF_DEFINE_PRIMITIVE_TYPE( bool, Bool) +PROTOBUF_DEFINE_PRIMITIVE_TYPE(bool, Bool) #undef PROTOBUF_DEFINE_PRIMITIVE_TYPE @@ -830,80 +1066,81 @@ PROTOBUF_DEFINE_PRIMITIVE_TYPE( bool, Bool) // StringTypeTraits // Strings support both Set() and Mutable(). -class LIBPROTOBUF_EXPORT StringTypeTraits { +class PROTOBUF_EXPORT StringTypeTraits { public: - typedef const string& ConstType; - typedef string* MutableType; + typedef const std::string& ConstType; + typedef std::string* MutableType; typedef StringTypeTraits Singular; - static inline const string& Get(int number, const ExtensionSet& set, - ConstType default_value) { + static inline const std::string& Get(int number, const ExtensionSet& set, + ConstType default_value) { return set.GetString(number, default_value); } static inline void Set(int number, FieldType field_type, - const string& value, ExtensionSet* set) { + const std::string& value, ExtensionSet* set) { set->SetString(number, field_type, value, NULL); } - static inline string* Mutable(int number, FieldType field_type, - ExtensionSet* set) { + static inline std::string* Mutable(int number, FieldType field_type, + ExtensionSet* set) { return set->MutableString(number, field_type, NULL); } + template + static void Register(int number, FieldType type, bool is_packed) { + ExtensionSet::RegisterExtension(&ExtendeeT::default_instance(), number, + type, false, is_packed); + } }; -LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_string_type_traits_once_init_; - -class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits { +class PROTOBUF_EXPORT RepeatedStringTypeTraits { public: - typedef const string& ConstType; - typedef string* MutableType; + typedef const std::string& ConstType; + typedef std::string* MutableType; typedef RepeatedStringTypeTraits Repeated; - typedef RepeatedPtrField RepeatedFieldType; + typedef RepeatedPtrField RepeatedFieldType; - static inline const string& Get(int number, const ExtensionSet& set, - int index) { + static inline const std::string& Get(int number, const ExtensionSet& set, + int index) { return set.GetRepeatedString(number, index); } - static inline void Set(int number, int index, - const string& value, ExtensionSet* set) { + static inline void Set(int number, int index, const std::string& value, + ExtensionSet* set) { set->SetRepeatedString(number, index, value); } - static inline string* Mutable(int number, int index, ExtensionSet* set) { + static inline std::string* Mutable(int number, int index, ExtensionSet* set) { return set->MutableRepeatedString(number, index); } - static inline void Add(int number, FieldType field_type, - bool /*is_packed*/, const string& value, - ExtensionSet* set) { + static inline void Add(int number, FieldType field_type, bool /*is_packed*/, + const std::string& value, ExtensionSet* set) { set->AddString(number, field_type, value, NULL); } - static inline string* Add(int number, FieldType field_type, - ExtensionSet* set) { + static inline std::string* Add(int number, FieldType field_type, + ExtensionSet* set) { return set->AddString(number, field_type, NULL); } - static inline const RepeatedPtrField& - GetRepeated(int number, const ExtensionSet& set) { - return *reinterpret_cast*>( + static inline const RepeatedPtrField& GetRepeated( + int number, const ExtensionSet& set) { + return *reinterpret_cast*>( set.GetRawRepeatedField(number, GetDefaultRepeatedField())); } - static inline RepeatedPtrField* - MutableRepeated(int number, FieldType field_type, - bool is_packed, ExtensionSet* set) { - return reinterpret_cast*>( - set->MutableRawRepeatedField(number, field_type, - is_packed, NULL)); + static inline RepeatedPtrField* MutableRepeated( + int number, FieldType field_type, bool is_packed, ExtensionSet* set) { + return reinterpret_cast*>( + set->MutableRawRepeatedField(number, field_type, is_packed, NULL)); } - static const RepeatedFieldType* GetDefaultRepeatedField() { - ::google::protobuf::GoogleOnceInit(&repeated_string_type_traits_once_init_, - &InitializeDefaultRepeatedFields); - return default_repeated_field_; + static const RepeatedFieldType* GetDefaultRepeatedField(); + + template + static void Register(int number, FieldType type, bool is_packed) { + ExtensionSet::RegisterExtension(&ExtendeeT::default_instance(), number, + type, true, is_packed); } private: static void InitializeDefaultRepeatedFields(); static void DestroyDefaultRepeatedFields(); - static const RepeatedFieldType *default_repeated_field_; }; // ------------------------------------------------------------------- @@ -922,11 +1159,16 @@ class EnumTypeTraits { ConstType default_value) { return static_cast(set.GetEnum(number, default_value)); } - static inline void Set(int number, FieldType field_type, - ConstType value, ExtensionSet* set) { + static inline void Set(int number, FieldType field_type, ConstType value, + ExtensionSet* set) { GOOGLE_DCHECK(IsValid(value)); set->SetEnum(number, field_type, value, NULL); } + template + static void Register(int number, FieldType type, bool is_packed) { + ExtensionSet::RegisterEnumExtension(&ExtendeeT::default_instance(), number, + type, false, is_packed, IsValid); + } }; template @@ -941,19 +1183,18 @@ class RepeatedEnumTypeTraits { static inline ConstType Get(int number, const ExtensionSet& set, int index) { return static_cast(set.GetRepeatedEnum(number, index)); } - static inline void Set(int number, int index, - ConstType value, ExtensionSet* set) { + static inline void Set(int number, int index, ConstType value, + ExtensionSet* set) { GOOGLE_DCHECK(IsValid(value)); set->SetRepeatedEnum(number, index, value); } - static inline void Add(int number, FieldType field_type, - bool is_packed, ConstType value, ExtensionSet* set) { + static inline void Add(int number, FieldType field_type, bool is_packed, + ConstType value, ExtensionSet* set) { GOOGLE_DCHECK(IsValid(value)); set->AddEnum(number, field_type, is_packed, value, NULL); } - static inline const RepeatedField& GetRepeated(int number, - const ExtensionSet& - set) { + static inline const RepeatedField& GetRepeated( + int number, const ExtensionSet& set) { // Hack: the `Extension` struct stores a RepeatedField for enums. // RepeatedField cannot implicitly convert to RepeatedField // so we need to do some casting magic. See message.h for similar @@ -980,6 +1221,11 @@ class RepeatedEnumTypeTraits { return reinterpret_cast*>( RepeatedPrimitiveTypeTraits::GetDefaultRepeatedField()); } + template + static void Register(int number, FieldType type, bool is_packed) { + ExtensionSet::RegisterEnumExtension(&ExtendeeT::default_instance(), number, + type, true, is_packed, IsValid); + } }; // ------------------------------------------------------------------- @@ -997,13 +1243,12 @@ class MessageTypeTraits { static inline ConstType Get(int number, const ExtensionSet& set, ConstType default_value) { - return static_cast( - set.GetMessage(number, default_value)); + return static_cast(set.GetMessage(number, default_value)); } static inline MutableType Mutable(int number, FieldType field_type, ExtensionSet* set) { - return static_cast( - set->MutableMessage(number, field_type, Type::default_instance(), NULL)); + return static_cast(set->MutableMessage( + number, field_type, Type::default_instance(), NULL)); } static inline void SetAllocated(int number, FieldType field_type, MutableType message, ExtensionSet* set) { @@ -1016,14 +1261,20 @@ class MessageTypeTraits { } static inline MutableType Release(int number, FieldType /* field_type */, ExtensionSet* set) { - return static_cast(set->ReleaseMessage( - number, Type::default_instance())); + return static_cast( + set->ReleaseMessage(number, Type::default_instance())); } static inline MutableType UnsafeArenaRelease(int number, FieldType /* field_type */, ExtensionSet* set) { - return static_cast(set->UnsafeArenaReleaseMessage( - number, Type::default_instance())); + return static_cast( + set->UnsafeArenaReleaseMessage(number, Type::default_instance())); + } + template + static void Register(int number, FieldType type, bool is_packed) { + ExtensionSet::RegisterMessageExtension(&ExtendeeT::default_instance(), + number, type, false, is_packed, + &Type::default_instance()); } }; @@ -1050,9 +1301,8 @@ class RepeatedMessageTypeTraits { return static_cast( set->AddMessage(number, field_type, Type::default_instance(), NULL)); } - static inline const RepeatedPtrField& GetRepeated(int number, - const ExtensionSet& - set) { + static inline const RepeatedPtrField& GetRepeated( + int number, const ExtensionSet& set) { // See notes above in RepeatedEnumTypeTraits::GetRepeated(): same // casting hack applies here, because a RepeatedPtrField // cannot naturally become a RepeatedPtrType even though Type is @@ -1070,63 +1320,60 @@ class RepeatedMessageTypeTraits { } static const RepeatedFieldType* GetDefaultRepeatedField(); + template + static void Register(int number, FieldType type, bool is_packed) { + ExtensionSet::RegisterMessageExtension(&ExtendeeT::default_instance(), + number, type, true, is_packed, + &Type::default_instance()); + } }; -LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_message_generic_type_traits_once_init_; - -// This class exists only to hold a generic default empty repeated field for all -// message-type repeated field extensions. -class LIBPROTOBUF_EXPORT RepeatedMessageGenericTypeTraits { - public: - typedef RepeatedPtrField< ::google::protobuf::MessageLite*> RepeatedFieldType; - private: - template friend class RepeatedMessageTypeTraits; - static void InitializeDefaultRepeatedFields(); - static void DestroyDefaultRepeatedFields(); - static const RepeatedFieldType* default_repeated_field_; -}; - -template inline - const typename RepeatedMessageTypeTraits::RepeatedFieldType* - RepeatedMessageTypeTraits::GetDefaultRepeatedField() { - ::google::protobuf::GoogleOnceInit( - &repeated_message_generic_type_traits_once_init_, - &RepeatedMessageGenericTypeTraits::InitializeDefaultRepeatedFields); - return reinterpret_cast( - RepeatedMessageGenericTypeTraits::default_repeated_field_); +template +inline const typename RepeatedMessageTypeTraits::RepeatedFieldType* +RepeatedMessageTypeTraits::GetDefaultRepeatedField() { + static auto instance = OnShutdownDelete(new RepeatedFieldType); + return instance; } // ------------------------------------------------------------------- // ExtensionIdentifier // This is the type of actual extension objects. E.g. if you have: -// extends Foo with optional int32 bar = 1234; +// extend Foo { +// optional int32 bar = 1234; +// } // then "bar" will be defined in C++ as: -// ExtensionIdentifier, 1, false> bar(1234); +// ExtensionIdentifier, 5, false> bar(1234); // // Note that we could, in theory, supply the field number as a template // parameter, and thus make an instance of ExtensionIdentifier have no -// actual contents. However, if we did that, then using at extension +// actual contents. However, if we did that, then using an extension // identifier would not necessarily cause the compiler to output any sort // of reference to any symbol defined in the extension's .pb.o file. Some // linkers will actually drop object files that are not explicitly referenced, // but that would be bad because it would cause this extension to not be // registered at static initialization, and therefore using it would crash. -template +template class ExtensionIdentifier { public: typedef TypeTraitsType TypeTraits; typedef ExtendeeType Extendee; ExtensionIdentifier(int number, typename TypeTraits::ConstType default_value) - : number_(number), default_value_(default_value) {} + : number_(number), default_value_(default_value) { + Register(number); + } inline int number() const { return number_; } typename TypeTraits::ConstType default_value() const { return default_value_; } + static void Register(int number) { + TypeTraits::template Register(number, field_type, is_packed); + } + private: const int number_; typename TypeTraits::ConstType default_value_; @@ -1145,182 +1392,213 @@ class ExtensionIdentifier { // // For similar reason, we use "_field_type" and "_is_packed" as parameter names // below, so that "field_type" and "is_packed" can be used as field names. -#define GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(CLASSNAME) \ +#define GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(CLASSNAME) \ /* Has, Size, Clear */ \ template \ inline bool HasExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \ return _extensions_.Has(id.number()); \ } \ \ template \ inline void ClearExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ _extensions_.ClearExtension(id.number()); \ } \ \ template \ inline int ExtensionSize( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \ return _extensions_.ExtensionSize(id.number()); \ } \ \ /* Singular accessors */ \ template \ inline typename _proto_TypeTraits::Singular::ConstType GetExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \ return _proto_TypeTraits::Get(id.number(), _extensions_, \ id.default_value()); \ } \ \ template \ inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ return _proto_TypeTraits::Mutable(id.number(), _field_type, \ &_extensions_); \ } \ \ template \ inline void SetExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ typename _proto_TypeTraits::Singular::ConstType value) { \ _proto_TypeTraits::Set(id.number(), _field_type, value, &_extensions_); \ } \ \ template \ inline void SetAllocatedExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ typename _proto_TypeTraits::Singular::MutableType value) { \ - _proto_TypeTraits::SetAllocated(id.number(), _field_type, \ - value, &_extensions_); \ + _proto_TypeTraits::SetAllocated(id.number(), _field_type, value, \ + &_extensions_); \ } \ template \ inline void UnsafeArenaSetAllocatedExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ typename _proto_TypeTraits::Singular::MutableType value) { \ _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type, \ value, &_extensions_); \ } \ template \ inline typename _proto_TypeTraits::Singular::MutableType ReleaseExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ return _proto_TypeTraits::Release(id.number(), _field_type, \ &_extensions_); \ } \ template \ inline typename _proto_TypeTraits::Singular::MutableType \ - UnsafeArenaReleaseExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ + UnsafeArenaReleaseExtension( \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type, \ &_extensions_); \ } \ \ /* Repeated accessors */ \ template \ inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ int index) const { \ return _proto_TypeTraits::Get(id.number(), _extensions_, index); \ } \ \ template \ inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ int index) { \ return _proto_TypeTraits::Mutable(id.number(), index, &_extensions_); \ } \ \ template \ inline void SetExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ int index, typename _proto_TypeTraits::Repeated::ConstType value) { \ _proto_TypeTraits::Set(id.number(), index, value, &_extensions_); \ } \ \ template \ inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ return _proto_TypeTraits::Add(id.number(), _field_type, &_extensions_); \ } \ \ template \ inline void AddExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ typename _proto_TypeTraits::Repeated::ConstType value) { \ - _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, \ - value, &_extensions_); \ + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value, \ + &_extensions_); \ } \ \ template \ inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& \ - GetRepeatedExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, \ - _is_packed>& id) const { \ + GetRepeatedExtension( \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \ return _proto_TypeTraits::GetRepeated(id.number(), _extensions_); \ } \ \ template \ inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* \ - MutableRepeatedExtension( \ - const ::google::protobuf::internal::ExtensionIdentifier< \ - CLASSNAME, _proto_TypeTraits, _field_type, \ - _is_packed>& id) { \ + MutableRepeatedExtension( \ + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, \ _is_packed, &_extensions_); \ } } // namespace internal -} // namespace protobuf +// Call this function to ensure that this extensions's reflection is linked into +// the binary: +// +// google::protobuf::LinkExtensionReflection(Foo::my_extension); +// +// This will ensure that the following lookup will succeed: +// +// DescriptorPool::generated_pool()->FindExtensionByName("Foo.my_extension"); +// +// This is often relevant for parsing extensions in text mode. +// +// As a side-effect, it will also guarantee that anything else from the same +// .proto file will also be available for lookup in the generated pool. +// +// This function does not actually register the extension, so it does not need +// to be called before the lookup. However it does need to occur in a function +// that cannot be stripped from the binary (ie. it must be reachable from main). +// +// Best practice is to call this function as close as possible to where the +// reflection is actually needed. This function is very cheap to call, so you +// should not need to worry about its runtime overhead except in tight loops (on +// x86-64 it compiles into two "mov" instructions). +template +void LinkExtensionReflection( + const google::protobuf::internal::ExtensionIdentifier< + ExtendeeType, TypeTraitsType, field_type, is_packed>& extension) { + internal::StrongReference(extension); +} + +} // namespace protobuf } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_EXTENSION_SET_H__ diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc index f545fe30f95b6..76ac0766f6d4b 100644 --- a/src/google/protobuf/extension_set_heavy.cc +++ b/src/google/protobuf/extension_set_heavy.cc @@ -35,23 +35,30 @@ // Contains methods defined in extension_set.h which cannot be part of the // lite library because they use descriptors or reflection. +#include + +#include +#include +#include +#include #include #include #include -#include #include #include +#include #include -#include +#include -namespace google { +#include + +namespace google { namespace protobuf { namespace internal { // A FieldSkipper used to store unknown MessageSet fields into UnknownFieldSet. -class MessageSetFieldSkipper - : public UnknownFieldSetFieldSkipper { +class MessageSetFieldSkipper : public UnknownFieldSetFieldSkipper { public: explicit MessageSetFieldSkipper(UnknownFieldSet* unknown_fields) : UnknownFieldSetFieldSkipper(unknown_fields) {} @@ -60,15 +67,15 @@ class MessageSetFieldSkipper virtual bool SkipMessageSetField(io::CodedInputStream* input, int field_number); }; -bool MessageSetFieldSkipper::SkipMessageSetField( - io::CodedInputStream* input, int field_number) { +bool MessageSetFieldSkipper::SkipMessageSetField(io::CodedInputStream* input, + int field_number) { uint32 length; if (!input->ReadVarint32(&length)) return false; if (unknown_fields_ == NULL) { return input->Skip(length); } else { - return input->ReadString( - unknown_fields_->AddLengthDelimited(field_number), length); + return input->ReadString(unknown_fields_->AddLengthDelimited(field_number), + length); } } @@ -82,9 +89,9 @@ class DescriptorPoolExtensionFinder : public ExtensionFinder { MessageFactory* factory, const Descriptor* containing_type) : pool_(pool), factory_(factory), containing_type_(containing_type) {} - virtual ~DescriptorPoolExtensionFinder() {} + ~DescriptorPoolExtensionFinder() override {} - virtual bool Find(int number, ExtensionInfo* output); + bool Find(int number, ExtensionInfo* output) override; private: const DescriptorPool* pool_; @@ -93,16 +100,14 @@ class DescriptorPoolExtensionFinder : public ExtensionFinder { }; void ExtensionSet::AppendToList( - const Descriptor* containing_type, - const DescriptorPool* pool, + const Descriptor* containing_type, const DescriptorPool* pool, std::vector* output) const { - for (ExtensionMap::const_iterator iter = extensions_.begin(); - iter != extensions_.end(); ++iter) { + ForEach([containing_type, pool, &output](int number, const Extension& ext) { bool has = false; - if (iter->second.is_repeated) { - has = iter->second.GetSize() > 0; + if (ext.is_repeated) { + has = ext.GetSize() > 0; } else { - has = !iter->second.is_cleared; + has = !ext.is_cleared; } if (has) { @@ -111,14 +116,13 @@ void ExtensionSet::AppendToList( // initialized, so they might not even be constructed until // AppendToList() is called. - if (iter->second.descriptor == NULL) { - output->push_back(pool->FindExtensionByNumber( - containing_type, iter->first)); + if (ext.descriptor == NULL) { + output->push_back(pool->FindExtensionByNumber(containing_type, number)); } else { - output->push_back(iter->second.descriptor); + output->push_back(ext.descriptor); } } - } + }); } inline FieldDescriptor::Type real_type(FieldType type) { @@ -136,26 +140,26 @@ inline WireFormatLite::FieldType field_type(FieldType type) { return static_cast(type); } -#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \ - GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \ - : FieldDescriptor::LABEL_OPTIONAL, \ - FieldDescriptor::LABEL_##LABEL); \ +#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \ + GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \ + : FieldDescriptor::LABEL_OPTIONAL, \ + FieldDescriptor::LABEL_##LABEL); \ GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE) const MessageLite& ExtensionSet::GetMessage(int number, const Descriptor* message_type, MessageFactory* factory) const { - ExtensionMap::const_iterator iter = extensions_.find(number); - if (iter == extensions_.end() || iter->second.is_cleared) { + const Extension* extension = FindOrNull(number); + if (extension == NULL || extension->is_cleared) { // Not present. Return the default value. return *factory->GetPrototype(message_type); } else { - GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); - if (iter->second.is_lazy) { - return iter->second.lazymessage_value->GetMessage( + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + if (extension->is_lazy) { + return extension->lazymessage_value->GetMessage( *factory->GetPrototype(message_type)); } else { - return *iter->second.message_value; + return *extension->message_value; } } } @@ -188,63 +192,64 @@ MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor, MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor, MessageFactory* factory) { - ExtensionMap::iterator iter = extensions_.find(descriptor->number()); - if (iter == extensions_.end()) { + Extension* extension = FindOrNull(descriptor->number()); + if (extension == NULL) { // Not present. Return NULL. return NULL; } else { - GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); MessageLite* ret = NULL; - if (iter->second.is_lazy) { - ret = iter->second.lazymessage_value->ReleaseMessage( + if (extension->is_lazy) { + ret = extension->lazymessage_value->ReleaseMessage( *factory->GetPrototype(descriptor->message_type())); if (arena_ == NULL) { - delete iter->second.lazymessage_value; + delete extension->lazymessage_value; } } else { if (arena_ != NULL) { - ret = (iter->second.message_value)->New(); - ret->CheckTypeAndMergeFrom(*(iter->second.message_value)); + ret = extension->message_value->New(); + ret->CheckTypeAndMergeFrom(*extension->message_value); } else { - ret = iter->second.message_value; + ret = extension->message_value; } } - extensions_.erase(descriptor->number()); + Erase(descriptor->number()); return ret; } } MessageLite* ExtensionSet::UnsafeArenaReleaseMessage( const FieldDescriptor* descriptor, MessageFactory* factory) { - ExtensionMap::iterator iter = extensions_.find(descriptor->number()); - if (iter == extensions_.end()) { + Extension* extension = FindOrNull(descriptor->number()); + if (extension == NULL) { // Not present. Return NULL. return NULL; } else { - GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); MessageLite* ret = NULL; - if (iter->second.is_lazy) { - ret = iter->second.lazymessage_value->UnsafeArenaReleaseMessage( + if (extension->is_lazy) { + ret = extension->lazymessage_value->UnsafeArenaReleaseMessage( *factory->GetPrototype(descriptor->message_type())); if (arena_ == NULL) { - delete iter->second.lazymessage_value; + delete extension->lazymessage_value; } } else { - ret = iter->second.message_value; + ret = extension->message_value; } - extensions_.erase(descriptor->number()); + Erase(descriptor->number()); return ret; } } -ExtensionSet::Extension* ExtensionSet::MaybeNewRepeatedExtension(const FieldDescriptor* descriptor) { +ExtensionSet::Extension* ExtensionSet::MaybeNewRepeatedExtension( + const FieldDescriptor* descriptor) { Extension* extension; if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) { extension->type = descriptor->type(); GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE); extension->is_repeated = true; extension->repeated_message_value = - ::google::protobuf::Arena::CreateMessage >(arena_); + Arena::CreateMessage >(arena_); } else { GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE); } @@ -257,8 +262,10 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor, // RepeatedPtrField does not know how to Add() since it cannot // allocate an abstract object, so we have to be tricky. - MessageLite* result = extension->repeated_message_value - ->AddFromCleared >(); + MessageLite* result = + reinterpret_cast( + extension->repeated_message_value) + ->AddFromCleared >(); if (result == NULL) { const MessageLite* prototype; if (extension->repeated_message_value->size() == 0) { @@ -281,8 +288,8 @@ void ExtensionSet::AddAllocatedMessage(const FieldDescriptor* descriptor, } static bool ValidateEnumUsingDescriptor(const void* arg, int number) { - return reinterpret_cast(arg) - ->FindValueByNumber(number) != NULL; + return reinterpret_cast(arg)->FindValueByNumber( + number) != NULL; } bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) { @@ -296,9 +303,9 @@ bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) { output->is_packed = extension->options().packed(); output->descriptor = extension; if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - output->message_prototype = + output->message_info.prototype = factory_->GetPrototype(extension->message_type()); - GOOGLE_CHECK(output->message_prototype != NULL) + GOOGLE_CHECK(output->message_info.prototype != nullptr) << "Extension factory's GetPrototype() returned NULL for extension: " << extension->full_name(); } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { @@ -310,6 +317,58 @@ bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) { } } + +bool ExtensionSet::FindExtension(int wire_type, uint32 field, + const Message* containing_type, + const internal::ParseContext* ctx, + ExtensionInfo* extension, + bool* was_packed_on_wire) { + if (ctx->data().pool == nullptr) { + GeneratedExtensionFinder finder(containing_type); + if (!FindExtensionInfoFromFieldNumber(wire_type, field, &finder, extension, + was_packed_on_wire)) { + return false; + } + } else { + DescriptorPoolExtensionFinder finder(ctx->data().pool, ctx->data().factory, + containing_type->GetDescriptor()); + if (!FindExtensionInfoFromFieldNumber(wire_type, field, &finder, extension, + was_packed_on_wire)) { + return false; + } + } + return true; +} + +const char* ExtensionSet::ParseField(uint64 tag, const char* ptr, + const Message* containing_type, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx) { + int number = tag >> 3; + bool was_packed_on_wire; + ExtensionInfo extension; + if (!FindExtension(tag & 7, number, containing_type, ctx, &extension, + &was_packed_on_wire)) { + return UnknownFieldParse( + tag, metadata->mutable_unknown_fields(), ptr, ctx); + } + return ParseFieldWithExtensionInfo( + number, was_packed_on_wire, extension, metadata, ptr, ctx); +} + +const char* ExtensionSet::ParseFieldMaybeLazily( + uint64 tag, const char* ptr, const Message* containing_type, + internal::InternalMetadata* metadata, internal::ParseContext* ctx) { + return ParseField(tag, ptr, containing_type, metadata, ctx); +} + +const char* ExtensionSet::ParseMessageSetItem( + const char* ptr, const Message* containing_type, + internal::InternalMetadata* metadata, internal::ParseContext* ctx) { + return ParseMessageSetItemTmpl(ptr, containing_type, + metadata, ctx); +} + bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, const Message* containing_type, UnknownFieldSet* unknown_fields) { @@ -345,14 +404,10 @@ int ExtensionSet::SpaceUsedExcludingSelf() const { } size_t ExtensionSet::SpaceUsedExcludingSelfLong() const { - size_t total_size = - extensions_.size() * sizeof(ExtensionMap::value_type); - for (ExtensionMap::const_iterator iter = extensions_.begin(), - end = extensions_.end(); - iter != end; - ++iter) { - total_size += iter->second.SpaceUsedExcludingSelfLong(); - } + size_t total_size = Size() * sizeof(KeyValue); + ForEach([&total_size](int /* number */, const Extension& ext) { + total_size += ext.SpaceUsedExcludingSelfLong(); + }); return total_size; } @@ -371,15 +426,15 @@ size_t ExtensionSet::Extension::SpaceUsedExcludingSelfLong() const { repeated_##LOWERCASE##_value->SpaceUsedExcludingSelfLong(); \ break - HANDLE_TYPE( INT32, int32); - HANDLE_TYPE( INT64, int64); - HANDLE_TYPE( UINT32, uint32); - HANDLE_TYPE( UINT64, uint64); - HANDLE_TYPE( FLOAT, float); - HANDLE_TYPE( DOUBLE, double); - HANDLE_TYPE( BOOL, bool); - HANDLE_TYPE( ENUM, enum); - HANDLE_TYPE( STRING, string); + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, enum); + HANDLE_TYPE(STRING, string); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_MESSAGE: @@ -387,9 +442,10 @@ size_t ExtensionSet::Extension::SpaceUsedExcludingSelfLong() const { // but MessageLite has no SpaceUsedLong(), so we must directly call // RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong() with a different // type handler. - total_size += - sizeof(*repeated_message_value) + - RepeatedMessage_SpaceUsedExcludingSelfLong(repeated_message_value); + total_size += sizeof(*repeated_message_value) + + RepeatedMessage_SpaceUsedExcludingSelfLong( + reinterpret_cast( + repeated_message_value)); break; } } else { @@ -413,211 +469,21 @@ size_t ExtensionSet::Extension::SpaceUsedExcludingSelfLong() const { return total_size; } -// The Serialize*ToArray methods are only needed in the heavy library, as -// the lite library only generates SerializeWithCachedSizes. -uint8* ExtensionSet::SerializeWithCachedSizesToArray(int start_field_number, - int end_field_number, - uint8* target) const { - return InternalSerializeWithCachedSizesToArray( - start_field_number, end_field_number, - google::protobuf::io::CodedOutputStream::IsDefaultSerializationDeterministic(), - target); -} - uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray( uint8* target) const { - return InternalSerializeMessageSetWithCachedSizesToArray( - google::protobuf::io::CodedOutputStream::IsDefaultSerializationDeterministic(), - target); -} - -uint8* ExtensionSet::InternalSerializeWithCachedSizesToArray( - int start_field_number, int end_field_number, - bool deterministic, uint8* target) const { - ExtensionMap::const_iterator iter; - for (iter = extensions_.lower_bound(start_field_number); - iter != extensions_.end() && iter->first < end_field_number; - ++iter) { - target = iter->second.InternalSerializeFieldWithCachedSizesToArray( - iter->first, deterministic, target); - } - return target; -} - -uint8* ExtensionSet::InternalSerializeMessageSetWithCachedSizesToArray( - bool deterministic, uint8* target) const { - ExtensionMap::const_iterator iter; - for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) { - target = iter->second.InternalSerializeMessageSetItemWithCachedSizesToArray( - iter->first, deterministic, target); - } - return target; -} - -uint8* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray( - int number, bool deterministic, uint8* target) const { - if (is_repeated) { - if (is_packed) { - if (cached_size == 0) return target; - - target = WireFormatLite::WriteTagToArray(number, - WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target); - target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target); - - switch (real_type(type)) { -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case FieldDescriptor::TYPE_##UPPERCASE: \ - for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \ - repeated_##LOWERCASE##_value->Get(i), target); \ - } \ - break - - HANDLE_TYPE( INT32, Int32, int32); - HANDLE_TYPE( INT64, Int64, int64); - HANDLE_TYPE( UINT32, UInt32, uint32); - HANDLE_TYPE( UINT64, UInt64, uint64); - HANDLE_TYPE( SINT32, SInt32, int32); - HANDLE_TYPE( SINT64, SInt64, int64); - HANDLE_TYPE( FIXED32, Fixed32, uint32); - HANDLE_TYPE( FIXED64, Fixed64, uint64); - HANDLE_TYPE(SFIXED32, SFixed32, int32); - HANDLE_TYPE(SFIXED64, SFixed64, int64); - HANDLE_TYPE( FLOAT, Float, float); - HANDLE_TYPE( DOUBLE, Double, double); - HANDLE_TYPE( BOOL, Bool, bool); - HANDLE_TYPE( ENUM, Enum, enum); -#undef HANDLE_TYPE - - case WireFormatLite::TYPE_STRING: - case WireFormatLite::TYPE_BYTES: - case WireFormatLite::TYPE_GROUP: - case WireFormatLite::TYPE_MESSAGE: - GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; - break; - } - } else { - switch (real_type(type)) { -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case FieldDescriptor::TYPE_##UPPERCASE: \ - for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - target = WireFormatLite::Write##CAMELCASE##ToArray(number, \ - repeated_##LOWERCASE##_value->Get(i), target); \ - } \ - break - - HANDLE_TYPE( INT32, Int32, int32); - HANDLE_TYPE( INT64, Int64, int64); - HANDLE_TYPE( UINT32, UInt32, uint32); - HANDLE_TYPE( UINT64, UInt64, uint64); - HANDLE_TYPE( SINT32, SInt32, int32); - HANDLE_TYPE( SINT64, SInt64, int64); - HANDLE_TYPE( FIXED32, Fixed32, uint32); - HANDLE_TYPE( FIXED64, Fixed64, uint64); - HANDLE_TYPE(SFIXED32, SFixed32, int32); - HANDLE_TYPE(SFIXED64, SFixed64, int64); - HANDLE_TYPE( FLOAT, Float, float); - HANDLE_TYPE( DOUBLE, Double, double); - HANDLE_TYPE( BOOL, Bool, bool); - HANDLE_TYPE( STRING, String, string); - HANDLE_TYPE( BYTES, Bytes, string); - HANDLE_TYPE( ENUM, Enum, enum); -#undef HANDLE_TYPE -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case FieldDescriptor::TYPE_##UPPERCASE: \ - for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - target = WireFormatLite::InternalWrite##CAMELCASE##ToArray( \ - number, repeated_##LOWERCASE##_value->Get(i), \ - deterministic, target); \ - } \ - break - - HANDLE_TYPE( GROUP, Group, message); - HANDLE_TYPE( MESSAGE, Message, message); -#undef HANDLE_TYPE - } - } - } else if (!is_cleared) { - switch (real_type(type)) { -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \ - case FieldDescriptor::TYPE_##UPPERCASE: \ - target = WireFormatLite::Write##CAMELCASE##ToArray( \ - number, VALUE, target); \ - break - - HANDLE_TYPE( INT32, Int32, int32_value); - HANDLE_TYPE( INT64, Int64, int64_value); - HANDLE_TYPE( UINT32, UInt32, uint32_value); - HANDLE_TYPE( UINT64, UInt64, uint64_value); - HANDLE_TYPE( SINT32, SInt32, int32_value); - HANDLE_TYPE( SINT64, SInt64, int64_value); - HANDLE_TYPE( FIXED32, Fixed32, uint32_value); - HANDLE_TYPE( FIXED64, Fixed64, uint64_value); - HANDLE_TYPE(SFIXED32, SFixed32, int32_value); - HANDLE_TYPE(SFIXED64, SFixed64, int64_value); - HANDLE_TYPE( FLOAT, Float, float_value); - HANDLE_TYPE( DOUBLE, Double, double_value); - HANDLE_TYPE( BOOL, Bool, bool_value); - HANDLE_TYPE( STRING, String, *string_value); - HANDLE_TYPE( BYTES, Bytes, *string_value); - HANDLE_TYPE( ENUM, Enum, enum_value); - HANDLE_TYPE( GROUP, Group, *message_value); -#undef HANDLE_TYPE - case FieldDescriptor::TYPE_MESSAGE: - if (is_lazy) { - target = lazymessage_value->InternalWriteMessageToArray( - number, deterministic, target); - } else { - target = WireFormatLite::InternalWriteMessageToArray( - number, *message_value, deterministic, target); - } - break; - } - } - return target; -} - -uint8* -ExtensionSet::Extension::InternalSerializeMessageSetItemWithCachedSizesToArray( - int number, bool deterministic, uint8* target) const { - if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { - // Not a valid MessageSet extension, but serialize it the normal way. - GOOGLE_LOG(WARNING) << "Invalid message set extension."; - return InternalSerializeFieldWithCachedSizesToArray(number, deterministic, - target); - } - - if (is_cleared) return target; - - // Start group. - target = io::CodedOutputStream::WriteTagToArray( - WireFormatLite::kMessageSetItemStartTag, target); - // Write type ID. - target = WireFormatLite::WriteUInt32ToArray( - WireFormatLite::kMessageSetTypeIdNumber, number, target); - // Write message. - if (is_lazy) { - target = lazymessage_value->InternalWriteMessageToArray( - WireFormatLite::kMessageSetMessageNumber, deterministic, target); - } else { - target = WireFormatLite::InternalWriteMessageToArray( - WireFormatLite::kMessageSetMessageNumber, *message_value, deterministic, - target); - } - // End group. - target = io::CodedOutputStream::WriteTagToArray( - WireFormatLite::kMessageSetItemEndTag, target); - return target; + io::EpsCopyOutputStream stream( + target, MessageSetByteSize(), + io::CodedOutputStream::IsDefaultSerializationDeterministic()); + return InternalSerializeMessageSetWithCachedSizesToArray(target, &stream); } - bool ExtensionSet::ParseFieldMaybeLazily( int wire_type, int field_number, io::CodedInputStream* input, - ExtensionFinder* extension_finder, - MessageSetFieldSkipper* field_skipper) { - return ParseField(WireFormatLite::MakeTag( - field_number, static_cast(wire_type)), - input, extension_finder, field_skipper); + ExtensionFinder* extension_finder, MessageSetFieldSkipper* field_skipper) { + return ParseField( + WireFormatLite::MakeTag(field_number, + static_cast(wire_type)), + input, extension_finder, field_skipper); } bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, @@ -642,171 +508,31 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, } } -bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, - const MessageLite* containing_type) { - MessageSetFieldSkipper skipper(NULL); - GeneratedExtensionFinder finder(containing_type); - return ParseMessageSet(input, &finder, &skipper); -} - bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input, ExtensionFinder* extension_finder, MessageSetFieldSkipper* field_skipper) { - // TODO(kenton): It would be nice to share code between this and - // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the - // differences would be hard to factor out. - - // This method parses a group which should contain two fields: - // required int32 type_id = 2; - // required data message = 3; - - uint32 last_type_id = 0; - - // If we see message data before the type_id, we'll append it to this so - // we can parse it later. - string message_data; - - while (true) { - const uint32 tag = input->ReadTagNoLastTag(); - if (tag == 0) return false; - - switch (tag) { - case WireFormatLite::kMessageSetTypeIdTag: { - uint32 type_id; - if (!input->ReadVarint32(&type_id)) return false; - last_type_id = type_id; - - if (!message_data.empty()) { - // We saw some message data before the type_id. Have to parse it - // now. - io::CodedInputStream sub_input( - reinterpret_cast(message_data.data()), - message_data.size()); - if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED, - last_type_id, &sub_input, - extension_finder, field_skipper)) { - return false; - } - message_data.clear(); - } - - break; - } - - case WireFormatLite::kMessageSetMessageTag: { - if (last_type_id == 0) { - // We haven't seen a type_id yet. Append this data to message_data. - string temp; - uint32 length; - if (!input->ReadVarint32(&length)) return false; - if (!input->ReadString(&temp, length)) return false; - io::StringOutputStream output_stream(&message_data); - io::CodedOutputStream coded_output(&output_stream); - coded_output.WriteVarint32(length); - coded_output.WriteString(temp); - } else { - // Already saw type_id, so we can parse this directly. - if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED, - last_type_id, input, - extension_finder, field_skipper)) { - return false; - } - } - - break; - } - - case WireFormatLite::kMessageSetItemEndTag: { - return true; - } - - default: { - if (!field_skipper->SkipField(input, tag)) return false; - } + struct MSFull { + bool ParseField(int type_id, io::CodedInputStream* input) { + return me->ParseFieldMaybeLazily( + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, type_id, input, + extension_finder, field_skipper); } - } -} - -void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes( - int number, - io::CodedOutputStream* output) const { - if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { - // Not a valid MessageSet extension, but serialize it the normal way. - SerializeFieldWithCachedSizes(number, output); - return; - } - - if (is_cleared) return; - - // Start group. - output->WriteTag(WireFormatLite::kMessageSetItemStartTag); - - // Write type ID. - WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber, - number, - output); - // Write message. - if (is_lazy) { - lazymessage_value->WriteMessage( - WireFormatLite::kMessageSetMessageNumber, output); - } else { - WireFormatLite::WriteMessageMaybeToArray( - WireFormatLite::kMessageSetMessageNumber, - *message_value, - output); - } - - // End group. - output->WriteTag(WireFormatLite::kMessageSetItemEndTag); -} - -size_t ExtensionSet::Extension::MessageSetItemByteSize(int number) const { - if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { - // Not a valid MessageSet extension, but compute the byte size for it the - // normal way. - return ByteSize(number); - } - - if (is_cleared) return 0; - - size_t our_size = WireFormatLite::kMessageSetItemTagsSize; - - // type_id - our_size += io::CodedOutputStream::VarintSize32(number); - // message - size_t message_size = 0; - if (is_lazy) { - message_size = lazymessage_value->ByteSize(); - } else { - message_size = message_value->ByteSize(); - } - - our_size += io::CodedOutputStream::VarintSize32(message_size); - our_size += message_size; - - return our_size; -} - -void ExtensionSet::SerializeMessageSetWithCachedSizes( - io::CodedOutputStream* output) const { - for (ExtensionMap::const_iterator iter = extensions_.begin(); - iter != extensions_.end(); ++iter) { - iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output); - } -} + bool SkipField(uint32 tag, io::CodedInputStream* input) { + return field_skipper->SkipField(input, tag); + } -size_t ExtensionSet::MessageSetByteSize() const { - size_t total_size = 0; + ExtensionSet* me; + ExtensionFinder* extension_finder; + MessageSetFieldSkipper* field_skipper; + }; - for (ExtensionMap::const_iterator iter = extensions_.begin(); - iter != extensions_.end(); ++iter) { - total_size += iter->second.MessageSetItemByteSize(iter->first); - } - - return total_size; + return ParseMessageSetItemImpl(input, + MSFull{this, extension_finder, field_skipper}); } } // namespace internal } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/extension_set_inl.h b/src/google/protobuf/extension_set_inl.h new file mode 100644 index 0000000000000..074784b96d502 --- /dev/null +++ b/src/google/protobuf/extension_set_inl.h @@ -0,0 +1,276 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__ +#define GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +template +const char* ExtensionSet::ParseFieldWithExtensionInfo( + int number, bool was_packed_on_wire, const ExtensionInfo& extension, + InternalMetadata* metadata, const char* ptr, internal::ParseContext* ctx) { + if (was_packed_on_wire) { + switch (extension.type) { +#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + return internal::Packed##CPP_CAMELCASE##Parser( \ + MutableRawRepeatedField(number, extension.type, extension.is_packed, \ + extension.descriptor), \ + ptr, ctx); + HANDLE_TYPE(INT32, Int32); + HANDLE_TYPE(INT64, Int64); + HANDLE_TYPE(UINT32, UInt32); + HANDLE_TYPE(UINT64, UInt64); + HANDLE_TYPE(SINT32, SInt32); + HANDLE_TYPE(SINT64, SInt64); + HANDLE_TYPE(FIXED32, Fixed32); + HANDLE_TYPE(FIXED64, Fixed64); + HANDLE_TYPE(SFIXED32, SFixed32); + HANDLE_TYPE(SFIXED64, SFixed64); + HANDLE_TYPE(FLOAT, Float); + HANDLE_TYPE(DOUBLE, Double); + HANDLE_TYPE(BOOL, Bool); +#undef HANDLE_TYPE + + case WireFormatLite::TYPE_ENUM: + return internal::PackedEnumParserArg( + MutableRawRepeatedField(number, extension.type, extension.is_packed, + extension.descriptor), + ptr, ctx, extension.enum_validity_check.func, + extension.enum_validity_check.arg, metadata, number); + case WireFormatLite::TYPE_STRING: + case WireFormatLite::TYPE_BYTES: + case WireFormatLite::TYPE_GROUP: + case WireFormatLite::TYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; + break; + } + } else { + switch (extension.type) { +#define HANDLE_VARINT_TYPE(UPPERCASE, CPP_CAMELCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: { \ + uint64 value; \ + ptr = VarintParse(ptr, &value); \ + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); \ + if (extension.is_repeated) { \ + Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ + extension.is_packed, value, extension.descriptor); \ + } else { \ + Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \ + extension.descriptor); \ + } \ + } break + + HANDLE_VARINT_TYPE(INT32, Int32); + HANDLE_VARINT_TYPE(INT64, Int64); + HANDLE_VARINT_TYPE(UINT32, UInt32); + HANDLE_VARINT_TYPE(UINT64, UInt64); + HANDLE_VARINT_TYPE(BOOL, Bool); +#undef HANDLE_VARINT_TYPE +#define HANDLE_SVARINT_TYPE(UPPERCASE, CPP_CAMELCASE, SIZE) \ + case WireFormatLite::TYPE_##UPPERCASE: { \ + uint64 val; \ + ptr = VarintParse(ptr, &val); \ + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); \ + auto value = WireFormatLite::ZigZagDecode##SIZE(val); \ + if (extension.is_repeated) { \ + Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ + extension.is_packed, value, extension.descriptor); \ + } else { \ + Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \ + extension.descriptor); \ + } \ + } break + + HANDLE_SVARINT_TYPE(SINT32, Int32, 32); + HANDLE_SVARINT_TYPE(SINT64, Int64, 64); +#undef HANDLE_SVARINT_TYPE +#define HANDLE_FIXED_TYPE(UPPERCASE, CPP_CAMELCASE, CPPTYPE) \ + case WireFormatLite::TYPE_##UPPERCASE: { \ + auto value = UnalignedLoad(ptr); \ + ptr += sizeof(CPPTYPE); \ + if (extension.is_repeated) { \ + Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ + extension.is_packed, value, extension.descriptor); \ + } else { \ + Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \ + extension.descriptor); \ + } \ + } break + + HANDLE_FIXED_TYPE(FIXED32, UInt32, uint32); + HANDLE_FIXED_TYPE(FIXED64, UInt64, uint64); + HANDLE_FIXED_TYPE(SFIXED32, Int32, int32); + HANDLE_FIXED_TYPE(SFIXED64, Int64, int64); + HANDLE_FIXED_TYPE(FLOAT, Float, float); + HANDLE_FIXED_TYPE(DOUBLE, Double, double); +#undef HANDLE_FIXED_TYPE + + case WireFormatLite::TYPE_ENUM: { + uint64 val; + ptr = VarintParse(ptr, &val); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + int value = val; + + if (!extension.enum_validity_check.func( + extension.enum_validity_check.arg, value)) { + WriteVarint(number, val, metadata->mutable_unknown_fields()); + } else if (extension.is_repeated) { + AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value, + extension.descriptor); + } else { + SetEnum(number, WireFormatLite::TYPE_ENUM, value, + extension.descriptor); + } + break; + } + + case WireFormatLite::TYPE_BYTES: + case WireFormatLite::TYPE_STRING: { + std::string* value = + extension.is_repeated + ? AddString(number, WireFormatLite::TYPE_STRING, + extension.descriptor) + : MutableString(number, WireFormatLite::TYPE_STRING, + extension.descriptor); + int size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + return ctx->ReadString(ptr, size, value); + } + + case WireFormatLite::TYPE_GROUP: { + MessageLite* value = + extension.is_repeated + ? AddMessage(number, WireFormatLite::TYPE_GROUP, + *extension.message_info.prototype, + extension.descriptor) + : MutableMessage(number, WireFormatLite::TYPE_GROUP, + *extension.message_info.prototype, + extension.descriptor); + uint32 tag = (number << 3) + WireFormatLite::WIRETYPE_START_GROUP; + return ctx->ParseGroup(value, ptr, tag); + } + + case WireFormatLite::TYPE_MESSAGE: { + MessageLite* value = + extension.is_repeated + ? AddMessage(number, WireFormatLite::TYPE_MESSAGE, + *extension.message_info.prototype, + extension.descriptor) + : MutableMessage(number, WireFormatLite::TYPE_MESSAGE, + *extension.message_info.prototype, + extension.descriptor); + return ctx->ParseMessage(value, ptr); + } + } + } + return ptr; +} + +template +const char* ExtensionSet::ParseMessageSetItemTmpl( + const char* ptr, const Msg* containing_type, + internal::InternalMetadata* metadata, internal::ParseContext* ctx) { + std::string payload; + uint32 type_id = 0; + bool payload_read = false; + while (!ctx->Done(&ptr)) { + uint32 tag = static_cast(*ptr++); + if (tag == WireFormatLite::kMessageSetTypeIdTag) { + uint64 tmp; + ptr = ParseBigVarint(ptr, &tmp); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + type_id = tmp; + if (payload_read) { + ExtensionInfo extension; + bool was_packed_on_wire; + if (!FindExtension(2, type_id, containing_type, ctx, &extension, + &was_packed_on_wire)) { + WriteLengthDelimited(type_id, payload, + metadata->mutable_unknown_fields()); + } else { + MessageLite* value = + extension.is_repeated + ? AddMessage(type_id, WireFormatLite::TYPE_MESSAGE, + *extension.message_info.prototype, + extension.descriptor) + : MutableMessage(type_id, WireFormatLite::TYPE_MESSAGE, + *extension.message_info.prototype, + extension.descriptor); + + const char* p; + // We can't use regular parse from string as we have to track + // proper recursion depth and descriptor pools. + ParseContext tmp_ctx(ctx->depth(), false, &p, payload); + tmp_ctx.data().pool = ctx->data().pool; + tmp_ctx.data().factory = ctx->data().factory; + GOOGLE_PROTOBUF_PARSER_ASSERT(value->_InternalParse(p, &tmp_ctx) && + tmp_ctx.EndedAtLimit()); + } + type_id = 0; + } + } else if (tag == WireFormatLite::kMessageSetMessageTag) { + if (type_id != 0) { + ptr = ParseFieldMaybeLazily(static_cast(type_id) * 8 + 2, ptr, + containing_type, metadata, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr); + type_id = 0; + } else { + int32 size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ptr = ctx->ReadString(ptr, size, &payload); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + payload_read = true; + } + } else { + ptr = ReadTag(ptr - 1, &tag); + if (tag == 0 || (tag & 7) == 4) { + ctx->SetLastTag(tag); + return ptr; + } + ptr = ParseField(tag, ptr, containing_type, metadata, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + } + } + return ptr; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__ diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc index 3e71b253b26d6..6a6fc25b3cd5d 100644 --- a/src/google/protobuf/extension_set_unittest.cc +++ b/src/google/protobuf/extension_set_unittest.cc @@ -32,33 +32,38 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. - +#include #include -#include +#include +#include #include #include -#include +#include +#include #include #include #include #include +#include #include -#include -#include - #include #include #include #include #include -namespace google { +// Must be included last. +#include + +namespace google { namespace protobuf { namespace internal { namespace { -// This test closely mirrors google/protobuf/compiler/cpp/unittest.cc +using TestUtil::EqualsToSerialized; + +// This test closely mirrors net/proto2/compiler/cpp/internal/unittest.cc // except that it uses extensions rather than regular fields. TEST(ExtensionSetTest, Defaults) { @@ -74,9 +79,9 @@ TEST(ExtensionSetTest, Defaults) { &message.GetExtension(unittest::optionalgroup_extension)); EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(), &message.GetExtension(unittest::optional_nested_message_extension)); - EXPECT_EQ(&unittest::ForeignMessage::default_instance(), - &message.GetExtension( - unittest::optional_foreign_message_extension)); + EXPECT_EQ( + &unittest::ForeignMessage::default_instance(), + &message.GetExtension(unittest::optional_foreign_message_extension)); EXPECT_EQ(&unittest_import::ImportMessage::default_instance(), &message.GetExtension(unittest::optional_import_message_extension)); } @@ -110,9 +115,9 @@ TEST(ExtensionSetTest, Clear) { &message.GetExtension(unittest::optionalgroup_extension)); EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(), &message.GetExtension(unittest::optional_nested_message_extension)); - EXPECT_NE(&unittest::ForeignMessage::default_instance(), - &message.GetExtension( - unittest::optional_foreign_message_extension)); + EXPECT_NE( + &unittest::ForeignMessage::default_instance(), + &message.GetExtension(unittest::optional_foreign_message_extension)); EXPECT_NE(&unittest_import::ImportMessage::default_instance(), &message.GetExtension(unittest::optional_import_message_extension)); @@ -129,7 +134,7 @@ TEST(ExtensionSetTest, ClearOneField) { TestUtil::SetAllExtensions(&message); int64 original_value = - message.GetExtension(unittest::optional_int64_extension); + message.GetExtension(unittest::optional_int64_extension); // Clear the field and make sure it shows up as cleared. message.ClearExtension(unittest::optional_int64_extension); @@ -147,20 +152,18 @@ TEST(ExtensionSetTest, ClearOneField) { TEST(ExtensionSetTest, SetAllocatedExtension) { unittest::TestAllExtensions message; - EXPECT_FALSE(message.HasExtension( - unittest::optional_foreign_message_extension)); + EXPECT_FALSE( + message.HasExtension(unittest::optional_foreign_message_extension)); // Add a extension using SetAllocatedExtension unittest::ForeignMessage* foreign_message = new unittest::ForeignMessage(); message.SetAllocatedExtension(unittest::optional_foreign_message_extension, foreign_message); - EXPECT_TRUE(message.HasExtension( - unittest::optional_foreign_message_extension)); - EXPECT_EQ(foreign_message, - message.MutableExtension( - unittest::optional_foreign_message_extension)); - EXPECT_EQ(foreign_message, - &message.GetExtension( - unittest::optional_foreign_message_extension)); + EXPECT_TRUE( + message.HasExtension(unittest::optional_foreign_message_extension)); + EXPECT_EQ(foreign_message, message.MutableExtension( + unittest::optional_foreign_message_extension)); + EXPECT_EQ(foreign_message, &message.GetExtension( + unittest::optional_foreign_message_extension)); // SetAllocatedExtension should delete the previously existing extension. // (We reply on unittest to check memory leaks for this case) @@ -170,8 +173,8 @@ TEST(ExtensionSetTest, SetAllocatedExtension) { // SetAllocatedExtension with a NULL parameter is equivalent to ClearExtenion. message.SetAllocatedExtension(unittest::optional_foreign_message_extension, NULL); - EXPECT_FALSE(message.HasExtension( - unittest::optional_foreign_message_extension)); + EXPECT_FALSE( + message.HasExtension(unittest::optional_foreign_message_extension)); } TEST(ExtensionSetTest, ReleaseExtension) { @@ -182,8 +185,7 @@ TEST(ExtensionSetTest, ReleaseExtension) { unittest::TestMessageSetExtension1* extension = new unittest::TestMessageSetExtension1(); message.SetAllocatedExtension( - unittest::TestMessageSetExtension1::message_set_extension, - extension); + unittest::TestMessageSetExtension1::message_set_extension, extension); EXPECT_TRUE(message.HasExtension( unittest::TestMessageSetExtension1::message_set_extension)); // Release the extension using ReleaseExtension @@ -196,8 +198,7 @@ TEST(ExtensionSetTest, ReleaseExtension) { // ReleaseExtension will return the underlying object even after // ClearExtension is called. message.SetAllocatedExtension( - unittest::TestMessageSetExtension1::message_set_extension, - extension); + unittest::TestMessageSetExtension1::message_set_extension, extension); message.ClearExtension( unittest::TestMessageSetExtension1::message_set_extension); released_extension = message.ReleaseExtension( @@ -207,13 +208,12 @@ TEST(ExtensionSetTest, ReleaseExtension) { } TEST(ExtensionSetTest, ArenaUnsafeArenaSetAllocatedAndRelease) { - ::google::protobuf::Arena arena; + Arena arena; unittest::TestAllExtensions* message = - ::google::protobuf::Arena::CreateMessage(&arena); + Arena::CreateMessage(&arena); unittest::ForeignMessage extension; message->UnsafeArenaSetAllocatedExtension( - unittest::optional_foreign_message_extension, - &extension); + unittest::optional_foreign_message_extension, &extension); // No copy when set. unittest::ForeignMessage* mutable_extension = message->MutableExtension(unittest::optional_foreign_message_extension); @@ -223,21 +223,19 @@ TEST(ExtensionSetTest, ArenaUnsafeArenaSetAllocatedAndRelease) { message->UnsafeArenaReleaseExtension( unittest::optional_foreign_message_extension); EXPECT_EQ(&extension, released_extension); - EXPECT_FALSE(message->HasExtension( - unittest::optional_foreign_message_extension)); + EXPECT_FALSE( + message->HasExtension(unittest::optional_foreign_message_extension)); // Set the ownership back and let the destructors run. It should not take // ownership, so this should not crash. message->UnsafeArenaSetAllocatedExtension( - unittest::optional_foreign_message_extension, - &extension); + unittest::optional_foreign_message_extension, &extension); } TEST(ExtensionSetTest, UnsafeArenaSetAllocatedAndRelease) { unittest::TestAllExtensions message; unittest::ForeignMessage* extension = new unittest::ForeignMessage(); message.UnsafeArenaSetAllocatedExtension( - unittest::optional_foreign_message_extension, - extension); + unittest::optional_foreign_message_extension, extension); // No copy when set. unittest::ForeignMessage* mutable_extension = message.MutableExtension(unittest::optional_foreign_message_extension); @@ -247,31 +245,29 @@ TEST(ExtensionSetTest, UnsafeArenaSetAllocatedAndRelease) { message.UnsafeArenaReleaseExtension( unittest::optional_foreign_message_extension); EXPECT_EQ(extension, released_extension); - EXPECT_FALSE(message.HasExtension( - unittest::optional_foreign_message_extension)); + EXPECT_FALSE( + message.HasExtension(unittest::optional_foreign_message_extension)); // Set the ownership back and let the destructors run. It should take // ownership, so this should not leak. message.UnsafeArenaSetAllocatedExtension( - unittest::optional_foreign_message_extension, - extension); + unittest::optional_foreign_message_extension, extension); } TEST(ExtensionSetTest, ArenaUnsafeArenaReleaseOfHeapAlloc) { - ::google::protobuf::Arena arena; + Arena arena; unittest::TestAllExtensions* message = - ::google::protobuf::Arena::CreateMessage(&arena); + Arena::CreateMessage(&arena); unittest::ForeignMessage* extension = new unittest::ForeignMessage; - message->SetAllocatedExtension( - unittest::optional_foreign_message_extension, - extension); + message->SetAllocatedExtension(unittest::optional_foreign_message_extension, + extension); // The arena should maintain ownership of the heap allocated proto because we // used UnsafeArenaReleaseExtension. The leak checker will ensure this. unittest::ForeignMessage* released_extension = message->UnsafeArenaReleaseExtension( unittest::optional_foreign_message_extension); EXPECT_EQ(extension, released_extension); - EXPECT_FALSE(message->HasExtension( - unittest::optional_foreign_message_extension)); + EXPECT_FALSE( + message->HasExtension(unittest::optional_foreign_message_extension)); } @@ -285,7 +281,7 @@ TEST(ExtensionSetTest, CopyFrom) { TestUtil::ExpectAllExtensionsSet(message2); } -TEST(ExtensioSetTest, CopyFromPacked) { +TEST(ExtensionSetTest, CopyFromPacked) { unittest::TestPackedExtensions message1, message2; TestUtil::SetPackedExtensions(&message1); @@ -341,10 +337,8 @@ TEST(ExtensionSetTest, SwapExtension) { TestUtil::ExpectExtensionsClear(message2); // Swap two extensions. - fields.push_back( - reflection->FindKnownExtensionByNumber(12)); - fields.push_back( - reflection->FindKnownExtensionByNumber(25)); + fields.push_back(reflection->FindKnownExtensionByNumber(12)); + fields.push_back(reflection->FindKnownExtensionByNumber(25)); reflection->SwapFields(&message1, &message2, fields); EXPECT_TRUE(message1.HasExtension(unittest::optional_int32_extension)); @@ -391,17 +385,17 @@ TEST(ExtensionSetTest, SwapExtensionBothFull) { } TEST(ExtensionSetTest, ArenaSetAllExtension) { - ::google::protobuf::Arena arena1; + Arena arena1; unittest::TestAllExtensions* message1 = - ::google::protobuf::Arena::CreateMessage(&arena1); + Arena::CreateMessage(&arena1); TestUtil::SetAllExtensions(message1); TestUtil::ExpectAllExtensionsSet(*message1); } TEST(ExtensionSetTest, ArenaCopyConstructor) { - ::google::protobuf::Arena arena1; + Arena arena1; unittest::TestAllExtensions* message1 = - ::google::protobuf::Arena::CreateMessage(&arena1); + Arena::CreateMessage(&arena1); TestUtil::SetAllExtensions(message1); unittest::TestAllExtensions message2(*message1); arena1.Reset(); @@ -409,9 +403,9 @@ TEST(ExtensionSetTest, ArenaCopyConstructor) { } TEST(ExtensionSetTest, ArenaMergeFrom) { - ::google::protobuf::Arena arena1; + Arena arena1; unittest::TestAllExtensions* message1 = - ::google::protobuf::Arena::CreateMessage(&arena1); + Arena::CreateMessage(&arena1); TestUtil::SetAllExtensions(message1); unittest::TestAllExtensions message2; message2.MergeFrom(*message1); @@ -420,31 +414,30 @@ TEST(ExtensionSetTest, ArenaMergeFrom) { } TEST(ExtensionSetTest, ArenaSetAllocatedMessageAndRelease) { - ::google::protobuf::Arena arena; + Arena arena; unittest::TestAllExtensions* message = - ::google::protobuf::Arena::CreateMessage(&arena); - EXPECT_FALSE(message->HasExtension( - unittest::optional_foreign_message_extension)); + Arena::CreateMessage(&arena); + EXPECT_FALSE( + message->HasExtension(unittest::optional_foreign_message_extension)); // Add a extension using SetAllocatedExtension unittest::ForeignMessage* foreign_message = new unittest::ForeignMessage(); message->SetAllocatedExtension(unittest::optional_foreign_message_extension, foreign_message); // foreign_message is now owned by the arena. - EXPECT_EQ(foreign_message, - message->MutableExtension( - unittest::optional_foreign_message_extension)); + EXPECT_EQ(foreign_message, message->MutableExtension( + unittest::optional_foreign_message_extension)); // Underlying message is copied, and returned. - unittest::ForeignMessage* released_message = message->ReleaseExtension( - unittest::optional_foreign_message_extension); + unittest::ForeignMessage* released_message = + message->ReleaseExtension(unittest::optional_foreign_message_extension); delete released_message; - EXPECT_FALSE(message->HasExtension( - unittest::optional_foreign_message_extension)); + EXPECT_FALSE( + message->HasExtension(unittest::optional_foreign_message_extension)); } TEST(ExtensionSetTest, SwapExtensionBothFullWithArena) { - ::google::protobuf::Arena arena1; - google::protobuf::scoped_ptr arena2(new ::google::protobuf::Arena()); + Arena arena1; + std::unique_ptr arena2(new Arena()); unittest::TestAllExtensions* message1 = Arena::CreateMessage(&arena1); @@ -466,7 +459,7 @@ TEST(ExtensionSetTest, SwapExtensionBothFullWithArena) { arena2.reset(NULL); TestUtil::ExpectAllExtensionsSet(*message1); // Test corner cases, when one is empty and other is not. - ::google::protobuf::Arena arena3, arena4; + Arena arena3, arena4; unittest::TestAllExtensions* message3 = Arena::CreateMessage(&arena3); @@ -479,8 +472,8 @@ TEST(ExtensionSetTest, SwapExtensionBothFullWithArena) { } TEST(ExtensionSetTest, SwapFieldsOfExtensionBothFullWithArena) { - google::protobuf::Arena arena1; - google::protobuf::Arena* arena2 = new ::google::protobuf::Arena(); + Arena arena1; + Arena* arena2 = new Arena(); unittest::TestAllExtensions* message1 = Arena::CreateMessage(&arena1); @@ -523,10 +516,10 @@ TEST(ExtensionSetTest, SerializationToArray) { unittest::TestAllExtensions source; unittest::TestAllTypes destination; TestUtil::SetAllExtensions(&source); - int size = source.ByteSize(); - string data; + size_t size = source.ByteSizeLong(); + std::string data; data.resize(size); - uint8* target = reinterpret_cast(string_as_array(&data)); + uint8* target = reinterpret_cast(::google::protobuf::string_as_array(&data)); uint8* end = source.SerializeWithCachedSizesToArray(target); EXPECT_EQ(size, end - target); EXPECT_TRUE(destination.ParseFromString(data)); @@ -544,11 +537,11 @@ TEST(ExtensionSetTest, SerializationToStream) { unittest::TestAllExtensions source; unittest::TestAllTypes destination; TestUtil::SetAllExtensions(&source); - int size = source.ByteSize(); - string data; + size_t size = source.ByteSizeLong(); + std::string data; data.resize(size); { - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); io::CodedOutputStream output_stream(&array_stream); source.SerializeWithCachedSizes(&output_stream); ASSERT_FALSE(output_stream.HadError()); @@ -567,10 +560,10 @@ TEST(ExtensionSetTest, PackedSerializationToArray) { unittest::TestPackedExtensions source; unittest::TestPackedTypes destination; TestUtil::SetPackedExtensions(&source); - int size = source.ByteSize(); - string data; + size_t size = source.ByteSizeLong(); + std::string data; data.resize(size); - uint8* target = reinterpret_cast(string_as_array(&data)); + uint8* target = reinterpret_cast(::google::protobuf::string_as_array(&data)); uint8* end = source.SerializeWithCachedSizesToArray(target); EXPECT_EQ(size, end - target); EXPECT_TRUE(destination.ParseFromString(data)); @@ -588,11 +581,11 @@ TEST(ExtensionSetTest, PackedSerializationToStream) { unittest::TestPackedExtensions source; unittest::TestPackedTypes destination; TestUtil::SetPackedExtensions(&source); - int size = source.ByteSize(); - string data; + size_t size = source.ByteSizeLong(); + std::string data; data.resize(size); { - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); io::CodedOutputStream output_stream(&array_stream); source.SerializeWithCachedSizes(&output_stream); ASSERT_FALSE(output_stream.HadError()); @@ -601,11 +594,37 @@ TEST(ExtensionSetTest, PackedSerializationToStream) { TestUtil::ExpectPackedFieldsSet(destination); } +TEST(ExtensionSetTest, NestedExtensionGroup) { + // Serialize as TestGroup and parse as TestGroupExtension. + unittest::TestGroup source; + unittest::TestGroupExtension destination; + std::string data; + + source.mutable_optionalgroup()->set_a(117); + source.set_optional_foreign_enum(unittest::FOREIGN_BAZ); + source.SerializeToString(&data); + EXPECT_TRUE(destination.ParseFromString(data)); + EXPECT_TRUE( + destination + .GetExtension(unittest::TestNestedExtension::optionalgroup_extension) + .has_a()); + EXPECT_EQ(117, destination + .GetExtension( + unittest::TestNestedExtension::optionalgroup_extension) + .a()); + EXPECT_TRUE(destination.HasExtension( + unittest::TestNestedExtension::optional_foreign_enum_extension)); + EXPECT_EQ( + unittest::FOREIGN_BAZ, + destination.GetExtension( + unittest::TestNestedExtension::optional_foreign_enum_extension)); +} + TEST(ExtensionSetTest, Parsing) { // Serialize as TestAllTypes and parse as TestAllExtensions. unittest::TestAllTypes source; unittest::TestAllExtensions destination; - string data; + std::string data; TestUtil::SetAllFields(&source); source.SerializeToString(&data); @@ -618,7 +637,7 @@ TEST(ExtensionSetTest, PackedParsing) { // Serialize as TestPackedTypes and parse as TestPackedExtensions. unittest::TestPackedTypes source; unittest::TestPackedExtensions destination; - string data; + std::string data; TestUtil::SetPackedFields(&source); source.SerializeToString(&data); @@ -629,7 +648,7 @@ TEST(ExtensionSetTest, PackedParsing) { TEST(ExtensionSetTest, PackedToUnpackedParsing) { unittest::TestPackedTypes source; unittest::TestUnpackedExtensions destination; - string data; + std::string data; TestUtil::SetPackedFields(&source); source.SerializeToString(&data); @@ -639,7 +658,10 @@ TEST(ExtensionSetTest, PackedToUnpackedParsing) { // Reserialize unittest::TestUnpackedTypes unpacked; TestUtil::SetUnpackedFields(&unpacked); - EXPECT_TRUE(unpacked.SerializeAsString() == destination.SerializeAsString()); + // Serialized proto has to be the same size and parsed to the same message. + EXPECT_EQ(unpacked.SerializeAsString().size(), + destination.SerializeAsString().size()); + EXPECT_TRUE(EqualsToSerialized(unpacked, destination.SerializeAsString())); // Make sure we can add extensions. destination.AddExtension(unittest::unpacked_int32_extension, 1); @@ -650,7 +672,7 @@ TEST(ExtensionSetTest, PackedToUnpackedParsing) { TEST(ExtensionSetTest, UnpackedToPackedParsing) { unittest::TestUnpackedTypes source; unittest::TestPackedExtensions destination; - string data; + std::string data; TestUtil::SetUnpackedFields(&source); source.SerializeToString(&data); @@ -660,7 +682,10 @@ TEST(ExtensionSetTest, UnpackedToPackedParsing) { // Reserialize unittest::TestPackedTypes packed; TestUtil::SetPackedFields(&packed); - EXPECT_TRUE(packed.SerializeAsString() == destination.SerializeAsString()); + // Serialized proto has to be the same size and parsed to the same message. + EXPECT_EQ(packed.SerializeAsString().size(), + destination.SerializeAsString().size()); + EXPECT_TRUE(EqualsToSerialized(packed, destination.SerializeAsString())); // Make sure we can add extensions. destination.AddExtension(unittest::packed_int32_extension, 1); @@ -713,60 +738,63 @@ TEST(ExtensionSetTest, MutableString) { TEST(ExtensionSetTest, SpaceUsedExcludingSelf) { // Scalar primitive extensions should increase the extension set size by a // minimum of the size of the primitive type. -#define TEST_SCALAR_EXTENSIONS_SPACE_USED(type, value) \ - do { \ - unittest::TestAllExtensions message; \ - const int base_size = message.SpaceUsed(); \ - message.SetExtension(unittest::optional_##type##_extension, value); \ - int min_expected_size = base_size + \ - sizeof(message.GetExtension(unittest::optional_##type##_extension)); \ - EXPECT_LE(min_expected_size, message.SpaceUsed()); \ +#define TEST_SCALAR_EXTENSIONS_SPACE_USED(type, value) \ + do { \ + unittest::TestAllExtensions message; \ + const int base_size = message.SpaceUsedLong(); \ + message.SetExtension(unittest::optional_##type##_extension, value); \ + int min_expected_size = \ + base_size + \ + sizeof(message.GetExtension(unittest::optional_##type##_extension)); \ + EXPECT_LE(min_expected_size, message.SpaceUsedLong()); \ } while (0) - TEST_SCALAR_EXTENSIONS_SPACE_USED(int32 , 101); - TEST_SCALAR_EXTENSIONS_SPACE_USED(int64 , 102); - TEST_SCALAR_EXTENSIONS_SPACE_USED(uint32 , 103); - TEST_SCALAR_EXTENSIONS_SPACE_USED(uint64 , 104); - TEST_SCALAR_EXTENSIONS_SPACE_USED(sint32 , 105); - TEST_SCALAR_EXTENSIONS_SPACE_USED(sint64 , 106); - TEST_SCALAR_EXTENSIONS_SPACE_USED(fixed32 , 107); - TEST_SCALAR_EXTENSIONS_SPACE_USED(fixed64 , 108); + TEST_SCALAR_EXTENSIONS_SPACE_USED(int32, 101); + TEST_SCALAR_EXTENSIONS_SPACE_USED(int64, 102); + TEST_SCALAR_EXTENSIONS_SPACE_USED(uint32, 103); + TEST_SCALAR_EXTENSIONS_SPACE_USED(uint64, 104); + TEST_SCALAR_EXTENSIONS_SPACE_USED(sint32, 105); + TEST_SCALAR_EXTENSIONS_SPACE_USED(sint64, 106); + TEST_SCALAR_EXTENSIONS_SPACE_USED(fixed32, 107); + TEST_SCALAR_EXTENSIONS_SPACE_USED(fixed64, 108); TEST_SCALAR_EXTENSIONS_SPACE_USED(sfixed32, 109); TEST_SCALAR_EXTENSIONS_SPACE_USED(sfixed64, 110); - TEST_SCALAR_EXTENSIONS_SPACE_USED(float , 111); - TEST_SCALAR_EXTENSIONS_SPACE_USED(double , 112); - TEST_SCALAR_EXTENSIONS_SPACE_USED(bool , true); + TEST_SCALAR_EXTENSIONS_SPACE_USED(float, 111); + TEST_SCALAR_EXTENSIONS_SPACE_USED(double, 112); + TEST_SCALAR_EXTENSIONS_SPACE_USED(bool, true); #undef TEST_SCALAR_EXTENSIONS_SPACE_USED { unittest::TestAllExtensions message; - const int base_size = message.SpaceUsed(); + const int base_size = message.SpaceUsedLong(); message.SetExtension(unittest::optional_nested_enum_extension, unittest::TestAllTypes::FOO); - int min_expected_size = base_size + + int min_expected_size = + base_size + sizeof(message.GetExtension(unittest::optional_nested_enum_extension)); - EXPECT_LE(min_expected_size, message.SpaceUsed()); + EXPECT_LE(min_expected_size, message.SpaceUsedLong()); } { // Strings may cause extra allocations depending on their length; ensure // that gets included as well. unittest::TestAllExtensions message; - const int base_size = message.SpaceUsed(); - const string s("this is a fairly large string that will cause some " - "allocation in order to store it in the extension"); + const int base_size = message.SpaceUsedLong(); + const std::string s( + "this is a fairly large string that will cause some " + "allocation in order to store it in the extension"); message.SetExtension(unittest::optional_string_extension, s); int min_expected_size = base_size + s.length(); - EXPECT_LE(min_expected_size, message.SpaceUsed()); + EXPECT_LE(min_expected_size, message.SpaceUsedLong()); } { // Messages also have additional allocation that need to be counted. unittest::TestAllExtensions message; - const int base_size = message.SpaceUsed(); + const int base_size = message.SpaceUsedLong(); unittest::ForeignMessage foreign; foreign.set_c(42); - message.MutableExtension(unittest::optional_foreign_message_extension)-> - CopyFrom(foreign); - int min_expected_size = base_size + foreign.SpaceUsed(); - EXPECT_LE(min_expected_size, message.SpaceUsed()); + message.MutableExtension(unittest::optional_foreign_message_extension) + ->CopyFrom(foreign); + int min_expected_size = base_size + foreign.SpaceUsedLong(); + EXPECT_LE(min_expected_size, message.SpaceUsedLong()); } // Repeated primitive extensions will increase space used by at least a @@ -776,82 +804,92 @@ TEST(ExtensionSetTest, SpaceUsedExcludingSelf) { // - Adds a value to the repeated extension, then clears it, establishing // the base size. // - Adds a small number of values, testing that it doesn't increase the - // SpaceUsed() + // SpaceUsedLong() // - Adds a large number of values (requiring allocation in the repeated - // field), and ensures that that allocation is included in SpaceUsed() -#define TEST_REPEATED_EXTENSIONS_SPACE_USED(type, cpptype, value) \ - do { \ - unittest::TestAllExtensions message; \ - const int base_size = message.SpaceUsed(); \ - int min_expected_size = sizeof(RepeatedField) + base_size; \ - message.AddExtension(unittest::repeated_##type##_extension, value); \ - message.ClearExtension(unittest::repeated_##type##_extension); \ - const int empty_repeated_field_size = message.SpaceUsed(); \ - EXPECT_LE(min_expected_size, empty_repeated_field_size) << #type; \ - message.AddExtension(unittest::repeated_##type##_extension, value); \ - message.AddExtension(unittest::repeated_##type##_extension, value); \ - EXPECT_EQ(empty_repeated_field_size, message.SpaceUsed()) << #type; \ - message.ClearExtension(unittest::repeated_##type##_extension); \ - for (int i = 0; i < 16; ++i) { \ - message.AddExtension(unittest::repeated_##type##_extension, value); \ - } \ - int expected_size = sizeof(cpptype) * (16 - \ - kMinRepeatedFieldAllocationSize) + empty_repeated_field_size; \ - EXPECT_LE(expected_size, message.SpaceUsed()) << #type; \ + // field), and ensures that that allocation is included in SpaceUsedLong() +#define TEST_REPEATED_EXTENSIONS_SPACE_USED(type, cpptype, value) \ + do { \ + unittest::TestAllExtensions message; \ + const size_t base_size = message.SpaceUsedLong(); \ + size_t min_expected_size = sizeof(RepeatedField) + base_size; \ + message.AddExtension(unittest::repeated_##type##_extension, value); \ + message.ClearExtension(unittest::repeated_##type##_extension); \ + const size_t empty_repeated_field_size = message.SpaceUsedLong(); \ + EXPECT_LE(min_expected_size, empty_repeated_field_size) << #type; \ + message.AddExtension(unittest::repeated_##type##_extension, value); \ + message.AddExtension(unittest::repeated_##type##_extension, value); \ + EXPECT_EQ(empty_repeated_field_size, message.SpaceUsedLong()) << #type; \ + message.ClearExtension(unittest::repeated_##type##_extension); \ + const size_t old_capacity = \ + message.GetRepeatedExtension(unittest::repeated_##type##_extension) \ + .Capacity(); \ + EXPECT_GE(old_capacity, kRepeatedFieldLowerClampLimit); \ + for (int i = 0; i < 16; ++i) { \ + message.AddExtension(unittest::repeated_##type##_extension, value); \ + } \ + int expected_size = \ + sizeof(cpptype) * \ + (message \ + .GetRepeatedExtension(unittest::repeated_##type##_extension) \ + .Capacity() - \ + old_capacity) + \ + empty_repeated_field_size; \ + EXPECT_LE(expected_size, message.SpaceUsedLong()) << #type; \ } while (0) - TEST_REPEATED_EXTENSIONS_SPACE_USED(int32 , int32 , 101); - TEST_REPEATED_EXTENSIONS_SPACE_USED(int64 , int64 , 102); - TEST_REPEATED_EXTENSIONS_SPACE_USED(uint32 , uint32, 103); - TEST_REPEATED_EXTENSIONS_SPACE_USED(uint64 , uint64, 104); - TEST_REPEATED_EXTENSIONS_SPACE_USED(sint32 , int32 , 105); - TEST_REPEATED_EXTENSIONS_SPACE_USED(sint64 , int64 , 106); - TEST_REPEATED_EXTENSIONS_SPACE_USED(fixed32 , uint32, 107); - TEST_REPEATED_EXTENSIONS_SPACE_USED(fixed64 , uint64, 108); - TEST_REPEATED_EXTENSIONS_SPACE_USED(sfixed32, int32 , 109); - TEST_REPEATED_EXTENSIONS_SPACE_USED(sfixed64, int64 , 110); - TEST_REPEATED_EXTENSIONS_SPACE_USED(float , float , 111); - TEST_REPEATED_EXTENSIONS_SPACE_USED(double , double, 112); - TEST_REPEATED_EXTENSIONS_SPACE_USED(bool , bool , true); + TEST_REPEATED_EXTENSIONS_SPACE_USED(int32, int32, 101); + TEST_REPEATED_EXTENSIONS_SPACE_USED(int64, int64, 102); + TEST_REPEATED_EXTENSIONS_SPACE_USED(uint32, uint32, 103); + TEST_REPEATED_EXTENSIONS_SPACE_USED(uint64, uint64, 104); + TEST_REPEATED_EXTENSIONS_SPACE_USED(sint32, int32, 105); + TEST_REPEATED_EXTENSIONS_SPACE_USED(sint64, int64, 106); + TEST_REPEATED_EXTENSIONS_SPACE_USED(fixed32, uint32, 107); + TEST_REPEATED_EXTENSIONS_SPACE_USED(fixed64, uint64, 108); + TEST_REPEATED_EXTENSIONS_SPACE_USED(sfixed32, int32, 109); + TEST_REPEATED_EXTENSIONS_SPACE_USED(sfixed64, int64, 110); + TEST_REPEATED_EXTENSIONS_SPACE_USED(float, float, 111); + TEST_REPEATED_EXTENSIONS_SPACE_USED(double, double, 112); + TEST_REPEATED_EXTENSIONS_SPACE_USED(bool, bool, true); TEST_REPEATED_EXTENSIONS_SPACE_USED(nested_enum, int, unittest::TestAllTypes::FOO); #undef TEST_REPEATED_EXTENSIONS_SPACE_USED // Repeated strings { unittest::TestAllExtensions message; - const int base_size = message.SpaceUsed(); - int min_expected_size = sizeof(RepeatedPtrField) + base_size; - const string value(256, 'x'); + const size_t base_size = message.SpaceUsedLong(); + size_t min_expected_size = + sizeof(RepeatedPtrField) + base_size; + const std::string value(256, 'x'); // Once items are allocated, they may stick around even when cleared so // without the hardcore memory management accessors there isn't a notion of // the empty repeated field memory usage as there is with primitive types. for (int i = 0; i < 16; ++i) { message.AddExtension(unittest::repeated_string_extension, value); } - min_expected_size += (sizeof(value) + value.size()) * - (16 - kMinRepeatedFieldAllocationSize); - EXPECT_LE(min_expected_size, message.SpaceUsed()); + min_expected_size += + (sizeof(value) + value.size()) * (16 - kRepeatedFieldLowerClampLimit); + EXPECT_LE(min_expected_size, message.SpaceUsedLong()); } // Repeated messages { unittest::TestAllExtensions message; - const int base_size = message.SpaceUsed(); - int min_expected_size = sizeof(RepeatedPtrField) + - base_size; + const size_t base_size = message.SpaceUsedLong(); + size_t min_expected_size = + sizeof(RepeatedPtrField) + base_size; unittest::ForeignMessage prototype; prototype.set_c(2); for (int i = 0; i < 16; ++i) { - message.AddExtension(unittest::repeated_foreign_message_extension)-> - CopyFrom(prototype); + message.AddExtension(unittest::repeated_foreign_message_extension) + ->CopyFrom(prototype); } min_expected_size += - (16 - kMinRepeatedFieldAllocationSize) * prototype.SpaceUsed(); - EXPECT_LE(min_expected_size, message.SpaceUsed()); + (16 - kRepeatedFieldLowerClampLimit) * prototype.SpaceUsedLong(); + EXPECT_LE(min_expected_size, message.SpaceUsedLong()); } } // N.B.: We do not test range-based for here because we remain C++03 compatible. -template +template inline T SumAllExtensions(const M& message, ID extension, T zero) { T sum = zero; typename RepeatedField::const_iterator iter = @@ -864,12 +902,11 @@ inline T SumAllExtensions(const M& message, ID extension, T zero) { return sum; } -template -inline void IncAllExtensions(M* message, ID extension, - T val) { +template +inline void IncAllExtensions(M* message, ID extension, T val) { typename RepeatedField::iterator iter = message->MutableRepeatedExtension(extension)->begin(); - typename RepeatedField::iterator end = + typename RepeatedField::iterator end = message->MutableRepeatedExtension(extension)->end(); for (; iter != end; ++iter) { *iter += val; @@ -880,14 +917,19 @@ TEST(ExtensionSetTest, RepeatedFields) { unittest::TestAllExtensions message; // Test empty repeated-field case (b/12926163) - ASSERT_EQ(0, message.GetRepeatedExtension( - unittest::repeated_int32_extension).size()); - ASSERT_EQ(0, message.GetRepeatedExtension( - unittest::repeated_nested_enum_extension).size()); - ASSERT_EQ(0, message.GetRepeatedExtension( - unittest::repeated_string_extension).size()); - ASSERT_EQ(0, message.GetRepeatedExtension( - unittest::repeated_nested_message_extension).size()); + ASSERT_EQ( + 0, + message.GetRepeatedExtension(unittest::repeated_int32_extension).size()); + ASSERT_EQ( + 0, message.GetRepeatedExtension(unittest::repeated_nested_enum_extension) + .size()); + ASSERT_EQ( + 0, + message.GetRepeatedExtension(unittest::repeated_string_extension).size()); + ASSERT_EQ( + 0, + message.GetRepeatedExtension(unittest::repeated_nested_message_extension) + .size()); unittest::TestAllTypes::NestedMessage nested_message; nested_message.set_bb(42); @@ -910,114 +952,113 @@ TEST(ExtensionSetTest, RepeatedFields) { message.AddExtension(unittest::repeated_bool_extension, true); message.AddExtension(unittest::repeated_nested_enum_extension, nested_enum); message.AddExtension(unittest::repeated_string_extension, - ::std::string("test")); + std::string("test")); message.AddExtension(unittest::repeated_bytes_extension, - ::std::string("test\xFF")); - message.AddExtension( - unittest::repeated_nested_message_extension)->CopyFrom(nested_message); - message.AddExtension(unittest::repeated_nested_enum_extension, - nested_enum); + std::string("test\xFF")); + message.AddExtension(unittest::repeated_nested_message_extension) + ->CopyFrom(nested_message); + message.AddExtension(unittest::repeated_nested_enum_extension, nested_enum); } - ASSERT_EQ(10, SumAllExtensions( - message, unittest::repeated_int32_extension, 0)); - IncAllExtensions( - &message, unittest::repeated_int32_extension, 1); - ASSERT_EQ(20, SumAllExtensions( - message, unittest::repeated_int32_extension, 0)); + ASSERT_EQ(10, SumAllExtensions(message, + unittest::repeated_int32_extension, 0)); + IncAllExtensions(&message, unittest::repeated_int32_extension, 1); + ASSERT_EQ(20, SumAllExtensions(message, + unittest::repeated_int32_extension, 0)); - ASSERT_EQ(20, SumAllExtensions( - message, unittest::repeated_int64_extension, 0)); - IncAllExtensions( - &message, unittest::repeated_int64_extension, 1); - ASSERT_EQ(30, SumAllExtensions( - message, unittest::repeated_int64_extension, 0)); + ASSERT_EQ(20, SumAllExtensions(message, + unittest::repeated_int64_extension, 0)); + IncAllExtensions(&message, unittest::repeated_int64_extension, 1); + ASSERT_EQ(30, SumAllExtensions(message, + unittest::repeated_int64_extension, 0)); ASSERT_EQ(30, SumAllExtensions( - message, unittest::repeated_uint32_extension, 0)); - IncAllExtensions( - &message, unittest::repeated_uint32_extension, 1); + message, unittest::repeated_uint32_extension, 0)); + IncAllExtensions(&message, unittest::repeated_uint32_extension, 1); ASSERT_EQ(40, SumAllExtensions( - message, unittest::repeated_uint32_extension, 0)); + message, unittest::repeated_uint32_extension, 0)); ASSERT_EQ(40, SumAllExtensions( - message, unittest::repeated_uint64_extension, 0)); - IncAllExtensions( - &message, unittest::repeated_uint64_extension, 1); + message, unittest::repeated_uint64_extension, 0)); + IncAllExtensions(&message, unittest::repeated_uint64_extension, 1); ASSERT_EQ(50, SumAllExtensions( - message, unittest::repeated_uint64_extension, 0)); + message, unittest::repeated_uint64_extension, 0)); ASSERT_EQ(50, SumAllExtensions( - message, unittest::repeated_sint32_extension, 0)); - IncAllExtensions( - &message, unittest::repeated_sint32_extension, 1); + message, unittest::repeated_sint32_extension, 0)); + IncAllExtensions(&message, unittest::repeated_sint32_extension, 1); ASSERT_EQ(60, SumAllExtensions( - message, unittest::repeated_sint32_extension, 0)); + message, unittest::repeated_sint32_extension, 0)); ASSERT_EQ(60, SumAllExtensions( - message, unittest::repeated_sint64_extension, 0)); - IncAllExtensions( - &message, unittest::repeated_sint64_extension, 1); + message, unittest::repeated_sint64_extension, 0)); + IncAllExtensions(&message, unittest::repeated_sint64_extension, 1); ASSERT_EQ(70, SumAllExtensions( - message, unittest::repeated_sint64_extension, 0)); + message, unittest::repeated_sint64_extension, 0)); ASSERT_EQ(70, SumAllExtensions( - message, unittest::repeated_fixed32_extension, 0)); - IncAllExtensions( - &message, unittest::repeated_fixed32_extension, 1); + message, unittest::repeated_fixed32_extension, 0)); + IncAllExtensions(&message, unittest::repeated_fixed32_extension, 1); ASSERT_EQ(80, SumAllExtensions( - message, unittest::repeated_fixed32_extension, 0)); + message, unittest::repeated_fixed32_extension, 0)); ASSERT_EQ(80, SumAllExtensions( - message, unittest::repeated_fixed64_extension, 0)); - IncAllExtensions( - &message, unittest::repeated_fixed64_extension, 1); + message, unittest::repeated_fixed64_extension, 0)); + IncAllExtensions(&message, unittest::repeated_fixed64_extension, 1); ASSERT_EQ(90, SumAllExtensions( - message, unittest::repeated_fixed64_extension, 0)); + message, unittest::repeated_fixed64_extension, 0)); // Usually, floating-point arithmetic cannot be trusted to be exact, so it is // a Bad Idea to assert equality in a test like this. However, we're dealing // with integers with a small number of significant mantissa bits, so we // should actually have exact precision here. - ASSERT_EQ(90, SumAllExtensions( - message, unittest::repeated_float_extension, 0)); - IncAllExtensions( - &message, unittest::repeated_float_extension, 1); + ASSERT_EQ(90, SumAllExtensions(message, + unittest::repeated_float_extension, 0)); + IncAllExtensions(&message, unittest::repeated_float_extension, 1); ASSERT_EQ(100, SumAllExtensions( - message, unittest::repeated_float_extension, 0)); + message, unittest::repeated_float_extension, 0)); ASSERT_EQ(100, SumAllExtensions( - message, unittest::repeated_double_extension, 0)); - IncAllExtensions( - &message, unittest::repeated_double_extension, 1); + message, unittest::repeated_double_extension, 0)); + IncAllExtensions(&message, unittest::repeated_double_extension, 1); ASSERT_EQ(110, SumAllExtensions( - message, unittest::repeated_double_extension, 0)); - - RepeatedPtrField< ::std::string>::iterator string_iter; - RepeatedPtrField< ::std::string>::iterator string_end; - for (string_iter = message.MutableRepeatedExtension( - unittest::repeated_string_extension)->begin(), - string_end = message.MutableRepeatedExtension( - unittest::repeated_string_extension)->end(); + message, unittest::repeated_double_extension, 0)); + + RepeatedPtrField::iterator string_iter; + RepeatedPtrField::iterator string_end; + for (string_iter = + message + .MutableRepeatedExtension(unittest::repeated_string_extension) + ->begin(), + string_end = + message + .MutableRepeatedExtension(unittest::repeated_string_extension) + ->end(); string_iter != string_end; ++string_iter) { *string_iter += "test"; } - RepeatedPtrField< ::std::string>::const_iterator string_const_iter; - RepeatedPtrField< ::std::string>::const_iterator string_const_end; - for (string_const_iter = message.GetRepeatedExtension( - unittest::repeated_string_extension).begin(), - string_const_end = message.GetRepeatedExtension( - unittest::repeated_string_extension).end(); + RepeatedPtrField::const_iterator string_const_iter; + RepeatedPtrField::const_iterator string_const_end; + for (string_const_iter = + message.GetRepeatedExtension(unittest::repeated_string_extension) + .begin(), + string_const_end = + message.GetRepeatedExtension(unittest::repeated_string_extension) + .end(); string_iter != string_end; ++string_iter) { ASSERT_TRUE(*string_iter == "testtest"); } RepeatedField::iterator enum_iter; RepeatedField::iterator enum_end; - for (enum_iter = message.MutableRepeatedExtension( - unittest::repeated_nested_enum_extension)->begin(), - enum_end = message.MutableRepeatedExtension( - unittest::repeated_nested_enum_extension)->end(); + for (enum_iter = message + .MutableRepeatedExtension( + unittest::repeated_nested_enum_extension) + ->begin(), + enum_end = message + .MutableRepeatedExtension( + unittest::repeated_nested_enum_extension) + ->end(); enum_iter != enum_end; ++enum_iter) { *enum_iter = unittest::TestAllTypes::NestedEnum_MAX; } @@ -1025,79 +1066,87 @@ TEST(ExtensionSetTest, RepeatedFields) { enum_const_iter; RepeatedField::const_iterator enum_const_end; - for (enum_const_iter = message.GetRepeatedExtension( - unittest::repeated_nested_enum_extension).begin(), - enum_const_end = message.GetRepeatedExtension( - unittest::repeated_nested_enum_extension).end(); - enum_iter != enum_end; ++enum_iter) { + for (enum_const_iter = + message + .GetRepeatedExtension(unittest::repeated_nested_enum_extension) + .begin(), + enum_const_end = + message + .GetRepeatedExtension(unittest::repeated_nested_enum_extension) + .end(); + enum_const_iter != enum_const_end; ++enum_const_iter) { ASSERT_EQ(*enum_const_iter, unittest::TestAllTypes::NestedEnum_MAX); } - RepeatedPtrField::iterator - msg_iter; - RepeatedPtrField::iterator - msg_end; - for (msg_iter = message.MutableRepeatedExtension( - unittest::repeated_nested_message_extension)->begin(), - msg_end = message.MutableRepeatedExtension( - unittest::repeated_nested_message_extension)->end(); + RepeatedPtrField::iterator msg_iter; + RepeatedPtrField::iterator msg_end; + for (msg_iter = message + .MutableRepeatedExtension( + unittest::repeated_nested_message_extension) + ->begin(), + msg_end = message + .MutableRepeatedExtension( + unittest::repeated_nested_message_extension) + ->end(); msg_iter != msg_end; ++msg_iter) { msg_iter->set_bb(1234); } - RepeatedPtrField:: - const_iterator msg_const_iter; - RepeatedPtrField:: - const_iterator msg_const_end; - for (msg_const_iter = message.GetRepeatedExtension( - unittest::repeated_nested_message_extension).begin(), - msg_const_end = message.GetRepeatedExtension( - unittest::repeated_nested_message_extension).end(); + RepeatedPtrField::const_iterator + msg_const_iter; + RepeatedPtrField::const_iterator + msg_const_end; + for (msg_const_iter = message + .GetRepeatedExtension( + unittest::repeated_nested_message_extension) + .begin(), + msg_const_end = message + .GetRepeatedExtension( + unittest::repeated_nested_message_extension) + .end(); msg_const_iter != msg_const_end; ++msg_const_iter) { ASSERT_EQ(msg_const_iter->bb(), 1234); } - // Test range-based for as well, but only if compiled as C++11. -#if __cplusplus >= 201103L // Test one primitive field. - for (auto& x : *message.MutableRepeatedExtension( - unittest::repeated_int32_extension)) { + for (auto& x : + *message.MutableRepeatedExtension(unittest::repeated_int32_extension)) { x = 4321; } - for (const auto& x : message.GetRepeatedExtension( - unittest::repeated_int32_extension)) { + for (const auto& x : + message.GetRepeatedExtension(unittest::repeated_int32_extension)) { ASSERT_EQ(x, 4321); } // Test one string field. - for (auto& x : *message.MutableRepeatedExtension( - unittest::repeated_string_extension)) { + for (auto& x : + *message.MutableRepeatedExtension(unittest::repeated_string_extension)) { x = "test_range_based_for"; } - for (const auto& x : message.GetRepeatedExtension( - unittest::repeated_string_extension)) { + for (const auto& x : + message.GetRepeatedExtension(unittest::repeated_string_extension)) { ASSERT_TRUE(x == "test_range_based_for"); } // Test one message field. for (auto& x : *message.MutableRepeatedExtension( - unittest::repeated_nested_message_extension)) { + unittest::repeated_nested_message_extension)) { x.set_bb(4321); } for (const auto& x : *message.MutableRepeatedExtension( - unittest::repeated_nested_message_extension)) { + unittest::repeated_nested_message_extension)) { ASSERT_EQ(x.bb(), 4321); } -#endif } // From b/12926163 TEST(ExtensionSetTest, AbsentExtension) { unittest::TestAllExtensions message; message.MutableRepeatedExtension(unittest::repeated_nested_message_extension) - ->Add()->set_bb(123); - ASSERT_EQ(1, message.ExtensionSize( - unittest::repeated_nested_message_extension)); - EXPECT_EQ( - 123, message.GetExtension( - unittest::repeated_nested_message_extension, 0).bb()); + ->Add() + ->set_bb(123); + ASSERT_EQ(1, + message.ExtensionSize(unittest::repeated_nested_message_extension)); + EXPECT_EQ(123, + message.GetExtension(unittest::repeated_nested_message_extension, 0) + .bb()); } #ifdef PROTOBUF_HAS_DEATH_TEST @@ -1105,9 +1154,9 @@ TEST(ExtensionSetTest, AbsentExtension) { TEST(ExtensionSetTest, InvalidEnumDeath) { unittest::TestAllExtensions message; EXPECT_DEBUG_DEATH( - message.SetExtension(unittest::optional_foreign_enum_extension, - static_cast(53)), - "IsValid"); + message.SetExtension(unittest::optional_foreign_enum_extension, + static_cast(53)), + "IsValid"); } #endif // PROTOBUF_HAS_DEATH_TEST @@ -1143,9 +1192,9 @@ TEST(ExtensionSetTest, DynamicExtensions) { // If the field refers to one of the types nested in TestDynamicExtensions, // make it refer to the type in our dynamic proto instead. - string prefix = "." + template_descriptor->full_name() + "."; + std::string prefix = "." + template_descriptor->full_name() + "."; if (extension->has_type_name()) { - string* type_name = extension->mutable_type_name(); + std::string* type_name = extension->mutable_type_name(); if (HasPrefixString(*type_name, prefix)) { type_name->replace(0, prefix.size(), ".dynamic_extensions."); } @@ -1162,7 +1211,8 @@ TEST(ExtensionSetTest, DynamicExtensions) { // Construct a message that we can parse with the extensions we defined. // Since the extensions were based off of the fields of TestDynamicExtensions, // we can use that message to create this test message. - string data; + std::string data; + unittest::TestDynamicExtensions dynamic_extension; { unittest::TestDynamicExtensions message; message.set_scalar_extension(123); @@ -1182,12 +1232,13 @@ TEST(ExtensionSetTest, DynamicExtensions) { // An unknown enum value (for a known field). message.mutable_unknown_fields()->AddVarint( - unittest::TestDynamicExtensions::kDynamicEnumExtensionFieldNumber, - 12345); + unittest::TestDynamicExtensions::kDynamicEnumExtensionFieldNumber, + 12345); // A regular unknown field. message.mutable_unknown_fields()->AddLengthDelimited(54321, "unknown"); message.SerializeToString(&data); + dynamic_extension = message; } // Now we can parse this using our dynamic extension definitions... @@ -1202,29 +1253,28 @@ TEST(ExtensionSetTest, DynamicExtensions) { // Can we print it? EXPECT_EQ( - "[dynamic_extensions.scalar_extension]: 123\n" - "[dynamic_extensions.enum_extension]: FOREIGN_BAR\n" - "[dynamic_extensions.dynamic_enum_extension]: DYNAMIC_BAZ\n" - "[dynamic_extensions.message_extension] {\n" - " c: 456\n" - "}\n" - "[dynamic_extensions.dynamic_message_extension] {\n" - " dynamic_field: 789\n" - "}\n" - "[dynamic_extensions.repeated_extension]: \"foo\"\n" - "[dynamic_extensions.repeated_extension]: \"bar\"\n" - "[dynamic_extensions.packed_extension]: 12\n" - "[dynamic_extensions.packed_extension]: -34\n" - "[dynamic_extensions.packed_extension]: 56\n" - "[dynamic_extensions.packed_extension]: -78\n" - "2002: 12345\n" - "54321: \"unknown\"\n", - message.DebugString()); + "[dynamic_extensions.scalar_extension]: 123\n" + "[dynamic_extensions.enum_extension]: FOREIGN_BAR\n" + "[dynamic_extensions.dynamic_enum_extension]: DYNAMIC_BAZ\n" + "[dynamic_extensions.message_extension] {\n" + " c: 456\n" + "}\n" + "[dynamic_extensions.dynamic_message_extension] {\n" + " dynamic_field: 789\n" + "}\n" + "[dynamic_extensions.repeated_extension]: \"foo\"\n" + "[dynamic_extensions.repeated_extension]: \"bar\"\n" + "[dynamic_extensions.packed_extension]: 12\n" + "[dynamic_extensions.packed_extension]: -34\n" + "[dynamic_extensions.packed_extension]: 56\n" + "[dynamic_extensions.packed_extension]: -78\n" + "2002: 12345\n" + "54321: \"unknown\"\n", + message.DebugString()); // Can we serialize it? - // (Don't use EXPECT_EQ because we don't want to dump raw binary data to the - // terminal on failure.) - EXPECT_TRUE(message.SerializeAsString() == data); + EXPECT_TRUE( + EqualsToSerialized(dynamic_extension, message.SerializeAsString())); // What if we parse using the reflection-based parser? { @@ -1245,10 +1295,10 @@ TEST(ExtensionSetTest, DynamicExtensions) { const Message& sub_message = message.GetReflection()->GetMessage(message, message_extension); const unittest::ForeignMessage* typed_sub_message = -#ifdef GOOGLE_PROTOBUF_NO_RTTI - static_cast(&sub_message); -#else +#if PROTOBUF_RTTI dynamic_cast(&sub_message); +#else + static_cast(&sub_message); #endif ASSERT_TRUE(typed_sub_message != NULL); EXPECT_EQ(456, typed_sub_message->c()); @@ -1261,16 +1311,29 @@ TEST(ExtensionSetTest, DynamicExtensions) { file->FindExtensionByName("dynamic_message_extension"); ASSERT_TRUE(dynamic_message_extension != NULL); const Message& parent = unittest::TestAllExtensions::default_instance(); - const Message& sub_message = - parent.GetReflection()->GetMessage(parent, dynamic_message_extension, - &dynamic_factory); + const Message& sub_message = parent.GetReflection()->GetMessage( + parent, dynamic_message_extension, &dynamic_factory); const Message* prototype = dynamic_factory.GetPrototype(dynamic_message_extension->message_type()); EXPECT_EQ(prototype, &sub_message); } } +TEST(ExtensionSetTest, BoolExtension) { + unittest::TestAllExtensions msg; + uint8 wire_bytes[2] = {13 * 8, 42 /* out of bounds payload for bool */}; + EXPECT_TRUE(msg.ParseFromArray(wire_bytes, 2)); + EXPECT_TRUE(msg.GetExtension(protobuf_unittest::optional_bool_extension)); +} + +TEST(ExtensionSetTest, ConstInit) { + PROTOBUF_CONSTINIT static ExtensionSet set{}; + EXPECT_EQ(set.NumExtensions(), 0); +} + } // namespace } // namespace internal } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc index afc3db56e7f5b..5a23fc7f2b44f 100644 --- a/src/google/protobuf/field_mask.pb.cc +++ b/src/google/protobuf/field_mask.pb.cc @@ -1,293 +1,195 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/field_mask.proto -#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include #include -#include -#include -#include #include -#include +#include +#include #include #include #include #include // @@protoc_insertion_point(includes) - -namespace google { -namespace protobuf { -class FieldMaskDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _FieldMask_default_instance_; - -namespace protobuf_google_2fprotobuf_2ffield_5fmask_2eproto { - - -namespace { - -::google::protobuf::Metadata file_level_metadata[1]; - -} // namespace - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField - const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0}, -}; - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField - const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - ::google::protobuf::internal::AuxillaryParseTableField(), -}; -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const - TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, +#include + +PROTOBUF_PRAGMA_INIT_SEG +PROTOBUF_NAMESPACE_OPEN +constexpr FieldMask::FieldMask( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : paths_(){} +struct FieldMaskDefaultTypeInternal { + constexpr FieldMaskDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~FieldMaskDefaultTypeInternal() {} + union { + FieldMask _instance; + }; }; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FieldMaskDefaultTypeInternal _FieldMask_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto[1]; +static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr; -const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { +const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { ~0u, // no _has_bits_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldMask, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldMask, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldMask, paths_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldMask, paths_), }; -static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { 0, -1, sizeof(FieldMask)}, +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, sizeof(PROTOBUF_NAMESPACE_ID::FieldMask)}, }; -static ::google::protobuf::Message const * const file_default_instances[] = { - reinterpret_cast(&_FieldMask_default_instance_), +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_FieldMask_default_instance_), }; -namespace { - -void protobuf_AssignDescriptors() { - AddDescriptors(); - ::google::protobuf::MessageFactory* factory = NULL; - AssignDescriptors( - "google/protobuf/field_mask.proto", schemas, file_default_instances, TableStruct::offsets, factory, - file_level_metadata, NULL, NULL); -} - -void protobuf_AssignDescriptorsOnce() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors); -} - -void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; -void protobuf_RegisterTypes(const ::std::string&) { - protobuf_AssignDescriptorsOnce(); - ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1); -} - -} // namespace -void TableStruct::InitDefaultsImpl() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - ::google::protobuf::internal::InitProtobufDefaults(); - _FieldMask_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_FieldMask_default_instance_);} - -void InitDefaults() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl); -} -namespace { -void AddDescriptorsImpl() { - InitDefaults(); - static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - "\n google/protobuf/field_mask.proto\022\017goog" - "le.protobuf\"\032\n\tFieldMask\022\r\n\005paths\030\001 \003(\tB" - "\211\001\n\023com.google.protobufB\016FieldMaskProtoP" - "\001Z9google.golang.org/genproto/protobuf/f" - "ield_mask;field_mask\242\002\003GPB\252\002\036Google.Prot" - "obuf.WellKnownTypesb\006proto3" - }; - ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( - descriptor, 227); - ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( - "google/protobuf/field_mask.proto", &protobuf_RegisterTypes); -} -} // anonymous namespace - -void AddDescriptors() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl); +const char descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n google/protobuf/field_mask.proto\022\017goog" + "le.protobuf\"\032\n\tFieldMask\022\r\n\005paths\030\001 \003(\tB" + "\205\001\n\023com.google.protobufB\016FieldMaskProtoP" + "\001Z2google.golang.org/protobuf/types/know" + "n/fieldmaskpb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf" + ".WellKnownTypesb\006proto3" + ; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto = { + false, false, 223, descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto, "google/protobuf/field_mask.proto", + &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once, nullptr, 0, 1, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto, file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata +descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_metadata_getter(int index) { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto); + return descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto.file_level_metadata[index]; } -// Force AddDescriptors() to be called at dynamic initialization time. -struct StaticDescriptorInitializer { - StaticDescriptorInitializer() { - AddDescriptors(); - } -} static_descriptor_initializer; - -} // namespace protobuf_google_2fprotobuf_2ffield_5fmask_2eproto +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ffield_5fmask_2eproto(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto); +PROTOBUF_NAMESPACE_OPEN // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int FieldMask::kPathsFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +class FieldMask::_Internal { + public: +}; -FieldMask::FieldMask() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::InitDefaults(); - } +FieldMask::FieldMask(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + paths_(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.FieldMask) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldMask) } FieldMask::FieldMask(const FieldMask& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - paths_(from.paths_), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + : ::PROTOBUF_NAMESPACE_ID::Message(), + paths_(from.paths_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldMask) } void FieldMask::SharedCtor() { - _cached_size_ = 0; } FieldMask::~FieldMask() { // @@protoc_insertion_point(destructor:google.protobuf.FieldMask) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void FieldMask::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); } -void FieldMask::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* FieldMask::descriptor() { - protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +void FieldMask::ArenaDtor(void* object) { + FieldMask* _this = reinterpret_cast< FieldMask* >(object); + (void)_this; } - -const FieldMask& FieldMask::default_instance() { - protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::InitDefaults(); - return *internal_default_instance(); +void FieldMask::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -FieldMask* FieldMask::New(::google::protobuf::Arena* arena) const { - FieldMask* n = new FieldMask; - if (arena != NULL) { - arena->Own(n); - } - return n; +void FieldMask::SetCachedSize(int size) const { + _cached_size_.Set(size); } void FieldMask::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldMask) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; paths_.Clear(); - _internal_metadata_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } -bool FieldMask::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.FieldMask) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { +const char* FieldMask::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { // repeated string paths = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->add_paths())); - DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->paths(this->paths_size() - 1).data(), - static_cast(this->paths(this->paths_size() - 1).length()), - ::google::protobuf::internal::WireFormatLite::PARSE, - "google.protobuf.FieldMask.paths")); - } else { - goto handle_unusual; - } - break; - } - + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + ptr -= 1; + do { + ptr += 1; + auto str = _internal_add_paths(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.FieldMask.paths")); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.FieldMask) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.FieldMask) - return false; -#undef DO_ + ptr = nullptr; + goto success; +#undef CHK_ } -void FieldMask::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.FieldMask) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // repeated string paths = 1; - for (int i = 0, n = this->paths_size(); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->paths(i).data(), static_cast(this->paths(i).length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, - "google.protobuf.FieldMask.paths"); - ::google::protobuf::internal::WireFormatLite::WriteString( - 1, this->paths(i), output); - } - - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.FieldMask) -} - -::google::protobuf::uint8* FieldMask::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* FieldMask::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldMask) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // repeated string paths = 1; - for (int i = 0, n = this->paths_size(); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->paths(i).data(), static_cast(this->paths(i).length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, + for (int i = 0, n = this->_internal_paths_size(); i < n; i++) { + const auto& s = this->_internal_paths(i); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + s.data(), static_cast(s.length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "google.protobuf.FieldMask.paths"); - target = ::google::protobuf::internal::WireFormatLite:: - WriteStringToArray(1, this->paths(i), target); + target = stream->WriteString(1, s, target); } - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldMask) return target; @@ -297,35 +199,36 @@ size_t FieldMask::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldMask) size_t total_size = 0; - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated string paths = 1; total_size += 1 * - ::google::protobuf::internal::FromIntSize(this->paths_size()); - for (int i = 0, n = this->paths_size(); i < n; i++) { - total_size += ::google::protobuf::internal::WireFormatLite::StringSize( - this->paths(i)); + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(paths_.size()); + for (int i = 0, n = paths_.size(); i < n; i++) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + paths_.Get(i)); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void FieldMask::MergeFrom(const ::google::protobuf::Message& from) { +void FieldMask::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldMask) GOOGLE_DCHECK_NE(&from, this); const FieldMask* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.FieldMask) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.FieldMask) MergeFrom(*source); @@ -335,14 +238,14 @@ void FieldMask::MergeFrom(const ::google::protobuf::Message& from) { void FieldMask::MergeFrom(const FieldMask& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldMask) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; paths_.MergeFrom(from.paths_); } -void FieldMask::CopyFrom(const ::google::protobuf::Message& from) { +void FieldMask::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.FieldMask) if (&from == this) return; Clear(); @@ -360,99 +263,24 @@ bool FieldMask::IsInitialized() const { return true; } -void FieldMask::Swap(FieldMask* other) { - if (other == this) return; - InternalSwap(other); -} void FieldMask::InternalSwap(FieldMask* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); paths_.InternalSwap(&other->paths_); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); } -::google::protobuf::Metadata FieldMask::GetMetadata() const { - protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::file_level_metadata[kIndexInFileMessages]; +::PROTOBUF_NAMESPACE_ID::Metadata FieldMask::GetMetadata() const { + return GetMetadataStatic(); } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// FieldMask - -// repeated string paths = 1; -int FieldMask::paths_size() const { - return paths_.size(); -} -void FieldMask::clear_paths() { - paths_.Clear(); -} -const ::std::string& FieldMask::paths(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldMask.paths) - return paths_.Get(index); -} -::std::string* FieldMask::mutable_paths(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldMask.paths) - return paths_.Mutable(index); -} -void FieldMask::set_paths(int index, const ::std::string& value) { - // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths) - paths_.Mutable(index)->assign(value); -} -#if LANG_CXX11 -void FieldMask::set_paths(int index, ::std::string&& value) { - // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths) - paths_.Mutable(index)->assign(std::move(value)); -} -#endif -void FieldMask::set_paths(int index, const char* value) { - GOOGLE_DCHECK(value != NULL); - paths_.Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.FieldMask.paths) -} -void FieldMask::set_paths(int index, const char* value, size_t size) { - paths_.Mutable(index)->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldMask.paths) -} -::std::string* FieldMask::add_paths() { - // @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths) - return paths_.Add(); -} -void FieldMask::add_paths(const ::std::string& value) { - paths_.Add()->assign(value); - // @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths) -} -#if LANG_CXX11 -void FieldMask::add_paths(::std::string&& value) { - paths_.Add(std::move(value)); - // @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths) -} -#endif -void FieldMask::add_paths(const char* value) { - GOOGLE_DCHECK(value != NULL); - paths_.Add()->assign(value); - // @@protoc_insertion_point(field_add_char:google.protobuf.FieldMask.paths) -} -void FieldMask::add_paths(const char* value, size_t size) { - paths_.Add()->assign(reinterpret_cast(value), size); - // @@protoc_insertion_point(field_add_pointer:google.protobuf.FieldMask.paths) -} -const ::google::protobuf::RepeatedPtrField< ::std::string>& -FieldMask::paths() const { - // @@protoc_insertion_point(field_list:google.protobuf.FieldMask.paths) - return paths_; -} -::google::protobuf::RepeatedPtrField< ::std::string>* -FieldMask::mutable_paths() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldMask.paths) - return &paths_; -} - -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::FieldMask* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::FieldMask >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::FieldMask >(arena); +} +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) +#include diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h index b8f10389d3f0a..af25a03cab039 100644 --- a/src/google/protobuf/field_mask.pb.h +++ b/src/google/protobuf/field_mask.pb.h @@ -1,180 +1,226 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/field_mask.proto -#ifndef PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED -#define PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto +#include #include -#include - -#if GOOGLE_PROTOBUF_VERSION < 3004000 +#include +#if PROTOBUF_VERSION < 3015000 #error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update +#error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 3015000 < PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please +#error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif +#include #include #include #include #include #include -#include +#include +#include #include #include // IWYU pragma: export #include // IWYU pragma: export #include // @@protoc_insertion_point(includes) -namespace google { -namespace protobuf { -class FieldMask; -class FieldMaskDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern FieldMaskDefaultTypeInternal _FieldMask_default_instance_; -} // namespace protobuf -} // namespace google - -namespace google { -namespace protobuf { - -namespace protobuf_google_2fprotobuf_2ffield_5fmask_2eproto { -// Internal implementation detail -- do not call these. -struct LIBPROTOBUF_EXPORT TableStruct { - static const ::google::protobuf::internal::ParseTableField entries[]; - static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; - static const ::google::protobuf::internal::ParseTable schema[]; - static const ::google::protobuf::uint32 offsets[]; - static const ::google::protobuf::internal::FieldMetadata field_metadata[]; - static const ::google::protobuf::internal::SerializationTable serialization_table[]; - static void InitDefaultsImpl(); +#include +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ffield_5fmask_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; }; -void LIBPROTOBUF_EXPORT AddDescriptors(); -void LIBPROTOBUF_EXPORT InitDefaults(); -} // namespace protobuf_google_2fprotobuf_2ffield_5fmask_2eproto +extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto; +PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_metadata_getter(int index); +PROTOBUF_NAMESPACE_OPEN +class FieldMask; +struct FieldMaskDefaultTypeInternal; +PROTOBUF_EXPORT extern FieldMaskDefaultTypeInternal _FieldMask_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::FieldMask* Arena::CreateMaybeMessage(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN // =================================================================== -class LIBPROTOBUF_EXPORT FieldMask : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldMask) */ { +class PROTOBUF_EXPORT FieldMask PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldMask) */ { public: - FieldMask(); + inline FieldMask() : FieldMask(nullptr) {} virtual ~FieldMask(); + explicit constexpr FieldMask(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); FieldMask(const FieldMask& from); - - inline FieldMask& operator=(const FieldMask& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 FieldMask(FieldMask&& from) noexcept : FieldMask() { *this = ::std::move(from); } + inline FieldMask& operator=(const FieldMask& from) { + CopyFrom(from); + return *this; + } inline FieldMask& operator=(FieldMask&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - static const ::google::protobuf::Descriptor* descriptor(); - static const FieldMask& default_instance(); + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const FieldMask& default_instance() { + return *internal_default_instance(); + } static inline const FieldMask* internal_default_instance() { return reinterpret_cast( &_FieldMask_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 0; - void Swap(FieldMask* other); friend void swap(FieldMask& a, FieldMask& b) { a.Swap(&b); } + inline void Swap(FieldMask* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FieldMask* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline FieldMask* New() const PROTOBUF_FINAL { return New(NULL); } + inline FieldMask* New() const final { + return CreateMaybeMessage(nullptr); + } - FieldMask* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + FieldMask* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const FieldMask& from); void MergeFrom(const FieldMask& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(FieldMask* other); - private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.FieldMask"; } + protected: + explicit FieldMask(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kPathsFieldNumber = 1, + }; // repeated string paths = 1; int paths_size() const; + private: + int _internal_paths_size() const; + public: void clear_paths(); - static const int kPathsFieldNumber = 1; - const ::std::string& paths(int index) const; - ::std::string* mutable_paths(int index); - void set_paths(int index, const ::std::string& value); - #if LANG_CXX11 - void set_paths(int index, ::std::string&& value); - #endif + const std::string& paths(int index) const; + std::string* mutable_paths(int index); + void set_paths(int index, const std::string& value); + void set_paths(int index, std::string&& value); void set_paths(int index, const char* value); void set_paths(int index, const char* value, size_t size); - ::std::string* add_paths(); - void add_paths(const ::std::string& value); - #if LANG_CXX11 - void add_paths(::std::string&& value); - #endif + std::string* add_paths(); + void add_paths(const std::string& value); + void add_paths(std::string&& value); void add_paths(const char* value); void add_paths(const char* value, size_t size); - const ::google::protobuf::RepeatedPtrField< ::std::string>& paths() const; - ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_paths(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField& paths() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField* mutable_paths(); + private: + const std::string& _internal_paths(int index) const; + std::string* _internal_add_paths(); + public: // @@protoc_insertion_point(class_scope:google.protobuf.FieldMask) private: - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::RepeatedPtrField< ::std::string> paths_; - mutable int _cached_size_; - friend struct protobuf_google_2fprotobuf_2ffield_5fmask_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField paths_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto; }; // =================================================================== // =================================================================== -#if !PROTOBUF_INLINE_NOT_IN_HEADERS #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" @@ -182,32 +228,40 @@ class LIBPROTOBUF_EXPORT FieldMask : public ::google::protobuf::Message /* @@pro // FieldMask // repeated string paths = 1; -inline int FieldMask::paths_size() const { +inline int FieldMask::_internal_paths_size() const { return paths_.size(); } +inline int FieldMask::paths_size() const { + return _internal_paths_size(); +} inline void FieldMask::clear_paths() { paths_.Clear(); } -inline const ::std::string& FieldMask::paths(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldMask.paths) +inline std::string* FieldMask::add_paths() { + // @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths) + return _internal_add_paths(); +} +inline const std::string& FieldMask::_internal_paths(int index) const { return paths_.Get(index); } -inline ::std::string* FieldMask::mutable_paths(int index) { +inline const std::string& FieldMask::paths(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldMask.paths) + return _internal_paths(index); +} +inline std::string* FieldMask::mutable_paths(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.FieldMask.paths) return paths_.Mutable(index); } -inline void FieldMask::set_paths(int index, const ::std::string& value) { +inline void FieldMask::set_paths(int index, const std::string& value) { // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths) paths_.Mutable(index)->assign(value); } -#if LANG_CXX11 -inline void FieldMask::set_paths(int index, ::std::string&& value) { +inline void FieldMask::set_paths(int index, std::string&& value) { // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths) paths_.Mutable(index)->assign(std::move(value)); } -#endif inline void FieldMask::set_paths(int index, const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); paths_.Mutable(index)->assign(value); // @@protoc_insertion_point(field_set_char:google.protobuf.FieldMask.paths) } @@ -216,22 +270,19 @@ inline void FieldMask::set_paths(int index, const char* value, size_t size) { reinterpret_cast(value), size); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldMask.paths) } -inline ::std::string* FieldMask::add_paths() { - // @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths) +inline std::string* FieldMask::_internal_add_paths() { return paths_.Add(); } -inline void FieldMask::add_paths(const ::std::string& value) { +inline void FieldMask::add_paths(const std::string& value) { paths_.Add()->assign(value); // @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths) } -#if LANG_CXX11 -inline void FieldMask::add_paths(::std::string&& value) { +inline void FieldMask::add_paths(std::string&& value) { paths_.Add(std::move(value)); // @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths) } -#endif inline void FieldMask::add_paths(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); paths_.Add()->assign(value); // @@protoc_insertion_point(field_add_char:google.protobuf.FieldMask.paths) } @@ -239,12 +290,12 @@ inline void FieldMask::add_paths(const char* value, size_t size) { paths_.Add()->assign(reinterpret_cast(value), size); // @@protoc_insertion_point(field_add_pointer:google.protobuf.FieldMask.paths) } -inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField& FieldMask::paths() const { // @@protoc_insertion_point(field_list:google.protobuf.FieldMask.paths) return paths_; } -inline ::google::protobuf::RepeatedPtrField< ::std::string>* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField* FieldMask::mutable_paths() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldMask.paths) return &paths_; @@ -253,14 +304,12 @@ FieldMask::mutable_paths() { #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ -#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) -#endif // PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto index c68d247c8a478..6b5104f188aa7 100644 --- a/src/google/protobuf/field_mask.proto +++ b/src/google/protobuf/field_mask.proto @@ -37,7 +37,8 @@ option java_package = "com.google.protobuf"; option java_outer_classname = "FieldMaskProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; -option go_package = "google.golang.org/genproto/protobuf/field_mask;field_mask"; +option go_package = "google.golang.org/protobuf/types/known/fieldmaskpb"; +option cc_enable_arenas = true; // `FieldMask` represents a set of symbolic field paths, for example: // @@ -107,57 +108,49 @@ option go_package = "google.golang.org/genproto/protobuf/field_mask;field_mask"; // describe the updated values, the API ignores the values of all // fields not covered by the mask. // -// If a repeated field is specified for an update operation, the existing -// repeated values in the target resource will be overwritten by the new values. -// Note that a repeated field is only allowed in the last position of a `paths` -// string. +// If a repeated field is specified for an update operation, new values will +// be appended to the existing repeated field in the target resource. Note that +// a repeated field is only allowed in the last position of a `paths` string. // // If a sub-message is specified in the last position of the field mask for an -// update operation, then the existing sub-message in the target resource is -// overwritten. Given the target message: +// update operation, then new value will be merged into the existing sub-message +// in the target resource. +// +// For example, given the target message: // // f { // b { -// d : 1 -// x : 2 +// d: 1 +// x: 2 // } -// c : 1 +// c: [1] // } // // And an update message: // // f { // b { -// d : 10 +// d: 10 // } +// c: [2] // } // // then if the field mask is: // -// paths: "f.b" +// paths: ["f.b", "f.c"] // // then the result will be: // // f { // b { -// d : 10 +// d: 10 +// x: 2 // } -// c : 1 +// c: [1, 2] // } // -// However, if the update mask was: -// -// paths: "f.b.d" -// -// then the result would be: -// -// f { -// b { -// d : 10 -// x : 2 -// } -// c : 1 -// } +// An implementation may provide options to override this default behavior for +// repeated and message fields. // // In order to reset a field's value to the default, the field must // be in the mask and set to the default value in the provided resource. @@ -240,6 +233,12 @@ option go_package = "google.golang.org/genproto/protobuf/field_mask;field_mask"; // // Note that oneof type names ("test_oneof" in this case) cannot be used in // paths. +// +// ## Field Mask Verification +// +// The implementation of any API method which has a FieldMask type field in the +// request should verify the included field paths, and return an +// `INVALID_ARGUMENT` error if any path is unmappable. message FieldMask { // The set of field mask paths. repeated string paths = 1; diff --git a/src/google/protobuf/generated_enum_reflection.h b/src/google/protobuf/generated_enum_reflection.h index fdcdc277909ee..5debc0a2564e8 100644 --- a/src/google/protobuf/generated_enum_reflection.h +++ b/src/google/protobuf/generated_enum_reflection.h @@ -41,14 +41,23 @@ #include -#include #include +#include +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +#include namespace google { namespace protobuf { - class EnumDescriptor; +class EnumDescriptor; } // namespace protobuf +} // namespace google +namespace google { namespace protobuf { // Returns the EnumDescriptor for enum type E, which must be a @@ -59,16 +68,14 @@ const EnumDescriptor* GetEnumDescriptor(); namespace internal { -// Helper for EnumType_Parse functions: try to parse the string 'name' as an -// enum name of the given type, returning true and filling in value on success, -// or returning false and leaving value unchanged on failure. -LIBPROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor, - const string& name, - int* value); +// Helper for EnumType_Parse functions: try to parse the string 'name' as +// an enum name of the given type, returning true and filling in value on +// success, or returning false and leaving value unchanged on failure. +PROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor, + ConstStringParam name, int* value); -template -bool ParseNamedEnum(const EnumDescriptor* descriptor, - const string& name, +template +bool ParseNamedEnum(const EnumDescriptor* descriptor, ConstStringParam name, EnumType* value) { int tmp; if (!ParseNamedEnum(descriptor, name, &tmp)) return false; @@ -79,10 +86,13 @@ bool ParseNamedEnum(const EnumDescriptor* descriptor, // Just a wrapper around printing the name of a value. The main point of this // function is not to be inlined, so that you can do this without including // descriptor.h. -LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value); +PROTOBUF_EXPORT const std::string& NameOfEnum(const EnumDescriptor* descriptor, + int value); } // namespace internal } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__ diff --git a/src/google/protobuf/generated_enum_util.cc b/src/google/protobuf/generated_enum_util.cc new file mode 100644 index 0000000000000..df7583e999845 --- /dev/null +++ b/src/google/protobuf/generated_enum_util.cc @@ -0,0 +1,95 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + +#include + +namespace google { +namespace protobuf { +namespace internal { +namespace { + +bool EnumCompareByName(const EnumEntry& a, const EnumEntry& b) { + return StringPiece(a.name) < StringPiece(b.name); +} + +// Gets the numeric value of the EnumEntry at the given index, but returns a +// special value for the index -1. This gives a way to use std::lower_bound on a +// sorted array of indices while searching for value that we associate with -1. +int GetValue(const EnumEntry* enums, int i, int target) { + if (i == -1) { + return target; + } else { + return enums[i].value; + } +} + +} // namespace + +bool LookUpEnumValue(const EnumEntry* enums, size_t size, + StringPiece name, int* value) { + EnumEntry target{name, 0}; + auto it = std::lower_bound(enums, enums + size, target, EnumCompareByName); + if (it != enums + size && it->name == name) { + *value = it->value; + return true; + } + return false; +} + +int LookUpEnumName(const EnumEntry* enums, const int* sorted_indices, + size_t size, int value) { + auto comparator = [enums, value](int a, int b) { + return GetValue(enums, a, value) < GetValue(enums, b, value); + }; + auto it = + std::lower_bound(sorted_indices, sorted_indices + size, -1, comparator); + if (it != sorted_indices + size && enums[*it].value == value) { + return it - sorted_indices; + } + return -1; +} + +bool InitializeEnumStrings( + const EnumEntry* enums, const int* sorted_indices, size_t size, + internal::ExplicitlyConstructed* enum_strings) { + for (size_t i = 0; i < size; ++i) { + enum_strings[i].Construct(enums[sorted_indices[i]].name); + internal::OnShutdownDestroyString(enum_strings[i].get_mutable()); + } + return true; +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/generated_enum_util.h b/src/google/protobuf/generated_enum_util.h index e4242055e991a..f1002e2d14396 100644 --- a/src/google/protobuf/generated_enum_util.h +++ b/src/google/protobuf/generated_enum_util.h @@ -31,16 +31,53 @@ #ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__ #define GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__ -#include +#include + +#include +#include + +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif namespace google { namespace protobuf { // This type trait can be used to cause templates to only match proto2 enum // types. -template struct is_proto_enum : ::google::protobuf::internal::false_type {}; +template +struct is_proto_enum : ::std::false_type {}; -} // namespace protobuf +namespace internal { + +// The table entry format for storing enum name-to-value mapping used with lite +// protos. This struct and the following related functions should only be used +// by protobuf generated code. +struct EnumEntry { + StringPiece name; + int value; +}; + +// Looks up a numeric enum value given the string name. +PROTOBUF_EXPORT bool LookUpEnumValue(const EnumEntry* enums, size_t size, + StringPiece name, int* value); +// Looks up an enum name given the numeric value. +PROTOBUF_EXPORT int LookUpEnumName(const EnumEntry* enums, + const int* sorted_indices, size_t size, + int value); + +// Initializes the list of enum names in std::string form. +PROTOBUF_EXPORT bool InitializeEnumStrings( + const EnumEntry* enums, const int* sorted_indices, size_t size, + internal::ExplicitlyConstructed* enum_strings); + +} // namespace internal +} // namespace protobuf } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__ diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 263d52ab0c1c4..b2ffe1fa8a36b 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -32,6 +32,8 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include + #include #include @@ -40,182 +42,200 @@ #include #include #include -#include #include #include +#include +#include #include +#include #include +#include + +#include #define GOOGLE_PROTOBUF_HAS_ONEOF +using google::protobuf::internal::ArenaStringPtr; +using google::protobuf::internal::DescriptorTable; +using google::protobuf::internal::ExtensionSet; +using google::protobuf::internal::GenericTypeHandler; +using google::protobuf::internal::GetEmptyString; +using google::protobuf::internal::InternalMetadata; +using google::protobuf::internal::LazyField; +using google::protobuf::internal::MapFieldBase; +using google::protobuf::internal::MigrationSchema; +using google::protobuf::internal::OnShutdownDelete; +using google::protobuf::internal::ReflectionSchema; +using google::protobuf::internal::RepeatedPtrFieldBase; +using google::protobuf::internal::StringSpaceUsedExcludingSelfLong; +using google::protobuf::internal::WrappedMutex; + namespace google { namespace protobuf { -namespace internal { namespace { -bool IsMapFieldInApi(const FieldDescriptor* field) { - return field->is_map(); -} +bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); } } // anonymous namespace -bool ParseNamedEnum(const EnumDescriptor* descriptor, - const string& name, +namespace internal { + +bool ParseNamedEnum(const EnumDescriptor* descriptor, ConstStringParam name, int* value) { const EnumValueDescriptor* d = descriptor->FindValueByName(name); - if (d == NULL) return false; + if (d == nullptr) return false; *value = d->number(); return true; } -const string& NameOfEnum(const EnumDescriptor* descriptor, int value) { +const std::string& NameOfEnum(const EnumDescriptor* descriptor, int value) { const EnumValueDescriptor* d = descriptor->FindValueByNumber(value); - return (d == NULL ? GetEmptyString() : d->name()); + return (d == nullptr ? GetEmptyString() : d->name()); } +} // namespace internal + // =================================================================== // Helpers for reporting usage errors (e.g. trying to use GetInt32() on // a string field). namespace { -template -To* GetPointerAtOffset(Message* message, uint32 offset) { - return reinterpret_cast(reinterpret_cast(message) + offset); -} - -template -const To* GetConstPointerAtOffset(const Message* message, uint32 offset) { - return reinterpret_cast(reinterpret_cast(message) + - offset); -} - -template -const To& GetConstRefAtOffset(const Message& message, uint32 offset) { - return *GetConstPointerAtOffset(&message, offset); -} - -void ReportReflectionUsageError( - const Descriptor* descriptor, const FieldDescriptor* field, - const char* method, const char* description) { - GOOGLE_LOG(FATAL) - << "Protocol Buffer reflection usage error:\n" - " Method : google::protobuf::Reflection::" << method << "\n" - " Message type: " << descriptor->full_name() << "\n" - " Field : " << field->full_name() << "\n" - " Problem : " << description; +using internal::GetConstPointerAtOffset; +using internal::GetConstRefAtOffset; +using internal::GetPointerAtOffset; + +void ReportReflectionUsageError(const Descriptor* descriptor, + const FieldDescriptor* field, + const char* method, const char* description) { + GOOGLE_LOG(FATAL) << "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::" + << method + << "\n" + " Message type: " + << descriptor->full_name() + << "\n" + " Field : " + << field->full_name() + << "\n" + " Problem : " + << description; } const char* cpptype_names_[FieldDescriptor::MAX_CPPTYPE + 1] = { - "INVALID_CPPTYPE", - "CPPTYPE_INT32", - "CPPTYPE_INT64", - "CPPTYPE_UINT32", - "CPPTYPE_UINT64", - "CPPTYPE_DOUBLE", - "CPPTYPE_FLOAT", - "CPPTYPE_BOOL", - "CPPTYPE_ENUM", - "CPPTYPE_STRING", - "CPPTYPE_MESSAGE" -}; + "INVALID_CPPTYPE", "CPPTYPE_INT32", "CPPTYPE_INT64", "CPPTYPE_UINT32", + "CPPTYPE_UINT64", "CPPTYPE_DOUBLE", "CPPTYPE_FLOAT", "CPPTYPE_BOOL", + "CPPTYPE_ENUM", "CPPTYPE_STRING", "CPPTYPE_MESSAGE"}; static void ReportReflectionUsageTypeError( const Descriptor* descriptor, const FieldDescriptor* field, - const char* method, - FieldDescriptor::CppType expected_type) { + const char* method, FieldDescriptor::CppType expected_type) { GOOGLE_LOG(FATAL) - << "Protocol Buffer reflection usage error:\n" - " Method : google::protobuf::Reflection::" << method << "\n" - " Message type: " << descriptor->full_name() << "\n" - " Field : " << field->full_name() << "\n" - " Problem : Field is not the right type for this message:\n" - " Expected : " << cpptype_names_[expected_type] << "\n" - " Field type: " << cpptype_names_[field->cpp_type()]; + << "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::" + << method + << "\n" + " Message type: " + << descriptor->full_name() + << "\n" + " Field : " + << field->full_name() + << "\n" + " Problem : Field is not the right type for this message:\n" + " Expected : " + << cpptype_names_[expected_type] + << "\n" + " Field type: " + << cpptype_names_[field->cpp_type()]; } static void ReportReflectionUsageEnumTypeError( const Descriptor* descriptor, const FieldDescriptor* field, const char* method, const EnumValueDescriptor* value) { - GOOGLE_LOG(FATAL) - << "Protocol Buffer reflection usage error:\n" - " Method : google::protobuf::Reflection::" << method << "\n" - " Message type: " << descriptor->full_name() << "\n" - " Field : " << field->full_name() << "\n" - " Problem : Enum value did not match field type:\n" - " Expected : " << field->enum_type()->full_name() << "\n" - " Actual : " << value->full_name(); -} - -#define USAGE_CHECK(CONDITION, METHOD, ERROR_DESCRIPTION) \ - if (!(CONDITION)) \ - ReportReflectionUsageError(descriptor_, field, #METHOD, ERROR_DESCRIPTION) -#define USAGE_CHECK_EQ(A, B, METHOD, ERROR_DESCRIPTION) \ + GOOGLE_LOG(FATAL) << "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::" + << method + << "\n" + " Message type: " + << descriptor->full_name() + << "\n" + " Field : " + << field->full_name() + << "\n" + " Problem : Enum value did not match field type:\n" + " Expected : " + << field->enum_type()->full_name() + << "\n" + " Actual : " + << value->full_name(); +} + +inline void CheckInvalidAccess(const internal::ReflectionSchema& schema, + const FieldDescriptor* field) { + GOOGLE_CHECK(!schema.IsFieldStripped(field)) + << "invalid access to a stripped field " << field->full_name(); +} + +#define USAGE_CHECK(CONDITION, METHOD, ERROR_DESCRIPTION) \ + if (!(CONDITION)) \ + ReportReflectionUsageError(descriptor_, field, #METHOD, ERROR_DESCRIPTION) +#define USAGE_CHECK_EQ(A, B, METHOD, ERROR_DESCRIPTION) \ USAGE_CHECK((A) == (B), METHOD, ERROR_DESCRIPTION) -#define USAGE_CHECK_NE(A, B, METHOD, ERROR_DESCRIPTION) \ +#define USAGE_CHECK_NE(A, B, METHOD, ERROR_DESCRIPTION) \ USAGE_CHECK((A) != (B), METHOD, ERROR_DESCRIPTION) -#define USAGE_CHECK_TYPE(METHOD, CPPTYPE) \ - if (field->cpp_type() != FieldDescriptor::CPPTYPE_##CPPTYPE) \ - ReportReflectionUsageTypeError(descriptor_, field, #METHOD, \ - FieldDescriptor::CPPTYPE_##CPPTYPE) +#define USAGE_CHECK_TYPE(METHOD, CPPTYPE) \ + if (field->cpp_type() != FieldDescriptor::CPPTYPE_##CPPTYPE) \ + ReportReflectionUsageTypeError(descriptor_, field, #METHOD, \ + FieldDescriptor::CPPTYPE_##CPPTYPE) -#define USAGE_CHECK_ENUM_VALUE(METHOD) \ - if (value->type() != field->enum_type()) \ - ReportReflectionUsageEnumTypeError(descriptor_, field, #METHOD, value) +#define USAGE_CHECK_ENUM_VALUE(METHOD) \ + if (value->type() != field->enum_type()) \ + ReportReflectionUsageEnumTypeError(descriptor_, field, #METHOD, value) -#define USAGE_CHECK_MESSAGE_TYPE(METHOD) \ - USAGE_CHECK_EQ(field->containing_type(), descriptor_, \ - METHOD, "Field does not match message type."); -#define USAGE_CHECK_SINGULAR(METHOD) \ - USAGE_CHECK_NE(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \ +#define USAGE_CHECK_MESSAGE_TYPE(METHOD) \ + USAGE_CHECK_EQ(field->containing_type(), descriptor_, METHOD, \ + "Field does not match message type."); +#define USAGE_CHECK_SINGULAR(METHOD) \ + USAGE_CHECK_NE(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \ "Field is repeated; the method requires a singular field.") -#define USAGE_CHECK_REPEATED(METHOD) \ - USAGE_CHECK_EQ(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \ +#define USAGE_CHECK_REPEATED(METHOD) \ + USAGE_CHECK_EQ(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \ "Field is singular; the method requires a repeated field.") -#define USAGE_CHECK_ALL(METHOD, LABEL, CPPTYPE) \ - USAGE_CHECK_MESSAGE_TYPE(METHOD); \ - USAGE_CHECK_##LABEL(METHOD); \ - USAGE_CHECK_TYPE(METHOD, CPPTYPE) +#define USAGE_CHECK_ALL(METHOD, LABEL, CPPTYPE) \ + USAGE_CHECK_MESSAGE_TYPE(METHOD); \ + USAGE_CHECK_##LABEL(METHOD); \ + USAGE_CHECK_TYPE(METHOD, CPPTYPE) } // namespace // =================================================================== -GeneratedMessageReflection::GeneratedMessageReflection( - const Descriptor* descriptor, const ReflectionSchema& schema, - const DescriptorPool* pool, MessageFactory* factory) +Reflection::Reflection(const Descriptor* descriptor, + const internal::ReflectionSchema& schema, + const DescriptorPool* pool, MessageFactory* factory) : descriptor_(descriptor), schema_(schema), - descriptor_pool_((pool == NULL) ? DescriptorPool::generated_pool() - : pool), + descriptor_pool_( + (pool == nullptr) ? DescriptorPool::internal_generated_pool() : pool), message_factory_(factory), last_non_weak_field_index_(-1) { last_non_weak_field_index_ = descriptor_->field_count() - 1; } -GeneratedMessageReflection::~GeneratedMessageReflection() {} - -const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields( +const UnknownFieldSet& Reflection::GetUnknownFields( const Message& message) const { - if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 && - !GetProto3PreserveUnknownsDefault()) { - // We have to ensure that any mutations made to the return value of - // MutableUnknownFields() are not reflected here when Proto3 defaults to - // discard unknowns. - return *UnknownFieldSet::default_instance(); - } else { - return GetInternalMetadataWithArena(message).unknown_fields(); - } + return GetInternalMetadata(message).unknown_fields( + UnknownFieldSet::default_instance); } -UnknownFieldSet* GeneratedMessageReflection::MutableUnknownFields( - Message* message) const { - return MutableInternalMetadataWithArena(message)->mutable_unknown_fields(); +UnknownFieldSet* Reflection::MutableUnknownFields(Message* message) const { + return MutableInternalMetadata(message) + ->mutable_unknown_fields(); } -size_t GeneratedMessageReflection::SpaceUsedLong(const Message& message) const { +size_t Reflection::SpaceUsedLong(const Message& message) const { // object_size_ already includes the in-memory representation of each field // in the message, so we only need to account for additional memory used by // the fields. @@ -230,35 +250,36 @@ size_t GeneratedMessageReflection::SpaceUsedLong(const Message& message) const { const FieldDescriptor* field = descriptor_->field(i); if (field->is_repeated()) { switch (field->cpp_type()) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case FieldDescriptor::CPPTYPE_##UPPERCASE : \ - total_size += GetRaw >(message, field) \ - .SpaceUsedExcludingSelfLong(); \ - break - - HANDLE_TYPE( INT32, int32); - HANDLE_TYPE( INT64, int64); +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + total_size += GetRaw >(message, field) \ + .SpaceUsedExcludingSelfLong(); \ + break + + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); HANDLE_TYPE(UINT32, uint32); HANDLE_TYPE(UINT64, uint64); HANDLE_TYPE(DOUBLE, double); - HANDLE_TYPE( FLOAT, float); - HANDLE_TYPE( BOOL, bool); - HANDLE_TYPE( ENUM, int); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, int); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: - total_size += GetRaw >(message, field) - .SpaceUsedExcludingSelfLong(); + total_size += + GetRaw >(message, field) + .SpaceUsedExcludingSelfLong(); break; } break; case FieldDescriptor::CPPTYPE_MESSAGE: if (IsMapFieldInApi(field)) { - total_size += GetRaw(message, field) + total_size += GetRaw(message, field) .SpaceUsedExcludingSelfLong(); } else { // We don't know which subclass of RepeatedPtrFieldBase the type is, @@ -271,18 +292,18 @@ size_t GeneratedMessageReflection::SpaceUsedLong(const Message& message) const { break; } } else { - if (field->containing_oneof() && !HasOneofField(message, field)) { + if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { continue; } switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32 : - case FieldDescriptor::CPPTYPE_INT64 : + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_INT64: case FieldDescriptor::CPPTYPE_UINT32: case FieldDescriptor::CPPTYPE_UINT64: case FieldDescriptor::CPPTYPE_DOUBLE: - case FieldDescriptor::CPPTYPE_FLOAT : - case FieldDescriptor::CPPTYPE_BOOL : - case FieldDescriptor::CPPTYPE_ENUM : + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_BOOL: + case FieldDescriptor::CPPTYPE_ENUM: // Field is inline, so we've already counted it. break; @@ -290,15 +311,16 @@ size_t GeneratedMessageReflection::SpaceUsedLong(const Message& message) const { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { - // Initially, the string points to the default value stored in - // the prototype. Only count the string if it has been changed - // from the default value. - const string* default_ptr = - &DefaultRaw(field).Get(); - const string* ptr = - &GetField(message, field).Get(); - - if (ptr != default_ptr) { + const std::string* ptr = + GetField(message, field).GetPointer(); + + // Initially, the string points to the default value stored + // in the prototype. Only count the string if it has been + // changed from the default value. + // Except oneof fields, those never point to a default instance, + // and there is no default instance to point to. + if (schema_.InRealOneof(field) || + ptr != DefaultRaw(field).GetPointer()) { // string fields are represented by just a pointer, so also // include sizeof(string) as well. total_size += @@ -316,7 +338,7 @@ size_t GeneratedMessageReflection::SpaceUsedLong(const Message& message) const { // external type's prototype, so there is no extra memory usage. } else { const Message* sub_message = GetRaw(message, field); - if (sub_message != NULL) { + if (sub_message != nullptr) { total_size += sub_message->SpaceUsedLong(); } } @@ -327,49 +349,44 @@ size_t GeneratedMessageReflection::SpaceUsedLong(const Message& message) const { return total_size; } -void GeneratedMessageReflection::SwapField( - Message* message1, - Message* message2, - const FieldDescriptor* field) const { +void Reflection::SwapField(Message* message1, Message* message2, + const FieldDescriptor* field) const { if (field->is_repeated()) { switch (field->cpp_type()) { -#define SWAP_ARRAYS(CPPTYPE, TYPE) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - MutableRaw >(message1, field)->Swap( \ - MutableRaw >(message2, field)); \ - break; - - SWAP_ARRAYS(INT32 , int32 ); - SWAP_ARRAYS(INT64 , int64 ); +#define SWAP_ARRAYS(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + MutableRaw >(message1, field) \ + ->Swap(MutableRaw >(message2, field)); \ + break; + + SWAP_ARRAYS(INT32, int32); + SWAP_ARRAYS(INT64, int64); SWAP_ARRAYS(UINT32, uint32); SWAP_ARRAYS(UINT64, uint64); - SWAP_ARRAYS(FLOAT , float ); + SWAP_ARRAYS(FLOAT, float); SWAP_ARRAYS(DOUBLE, double); - SWAP_ARRAYS(BOOL , bool ); - SWAP_ARRAYS(ENUM , int ); + SWAP_ARRAYS(BOOL, bool); + SWAP_ARRAYS(ENUM, int); #undef SWAP_ARRAYS case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: - MutableRaw(message1, field)-> - Swap >( + MutableRaw(message1, field) + ->Swap >( MutableRaw(message2, field)); break; } break; case FieldDescriptor::CPPTYPE_MESSAGE: if (IsMapFieldInApi(field)) { - MutableRaw(message1, field)-> - MutableRepeatedField()-> - Swap >( - MutableRaw(message2, field)-> - MutableRepeatedField()); + MutableRaw(message1, field) + ->Swap(MutableRaw(message2, field)); } else { - MutableRaw(message1, field)-> - Swap >( - MutableRaw(message2, field)); + MutableRaw(message1, field) + ->Swap >( + MutableRaw(message2, field)); } break; @@ -378,20 +395,20 @@ void GeneratedMessageReflection::SwapField( } } else { switch (field->cpp_type()) { -#define SWAP_VALUES(CPPTYPE, TYPE) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - std::swap(*MutableRaw(message1, field), \ - *MutableRaw(message2, field)); \ - break; - - SWAP_VALUES(INT32 , int32 ); - SWAP_VALUES(INT64 , int64 ); +#define SWAP_VALUES(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + std::swap(*MutableRaw(message1, field), \ + *MutableRaw(message2, field)); \ + break; + + SWAP_VALUES(INT32, int32); + SWAP_VALUES(INT64, int64); SWAP_VALUES(UINT32, uint32); SWAP_VALUES(UINT64, uint64); - SWAP_VALUES(FLOAT , float ); + SWAP_VALUES(FLOAT, float); SWAP_VALUES(DOUBLE, double); - SWAP_VALUES(BOOL , bool ); - SWAP_VALUES(ENUM , int ); + SWAP_VALUES(BOOL, bool); + SWAP_VALUES(ENUM, int); #undef SWAP_VALUES case FieldDescriptor::CPPTYPE_MESSAGE: if (GetArena(message1) == GetArena(message2)) { @@ -400,12 +417,12 @@ void GeneratedMessageReflection::SwapField( } else { Message** sub_msg1 = MutableRaw(message1, field); Message** sub_msg2 = MutableRaw(message2, field); - if (*sub_msg1 == NULL && *sub_msg2 == NULL) break; + if (*sub_msg1 == nullptr && *sub_msg2 == nullptr) break; if (*sub_msg1 && *sub_msg2) { (*sub_msg1)->GetReflection()->Swap(*sub_msg1, *sub_msg2); break; } - if (*sub_msg1 == NULL) { + if (*sub_msg1 == nullptr) { *sub_msg1 = (*sub_msg2)->New(message1->GetArena()); (*sub_msg1)->CopyFrom(**sub_msg2); ClearField(message2, field); @@ -420,25 +437,33 @@ void GeneratedMessageReflection::SwapField( case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. - case FieldOptions::STRING: - { - Arena* arena1 = GetArena(message1); - Arena* arena2 = GetArena(message2); - ArenaStringPtr* string1 = - MutableRaw(message1, field); - ArenaStringPtr* string2 = - MutableRaw(message2, field); - if (arena1 == arena2) { - string1->Swap(string2); - } else { - const string* default_ptr = - &DefaultRaw(field).Get(); - const string temp = string1->Get(); - string1->Set(default_ptr, string2->Get(), arena1); - string2->Set(default_ptr, temp, arena2); - } + case FieldOptions::STRING: { + Arena* arena1 = GetArena(message1); + Arena* arena2 = GetArena(message2); + + ArenaStringPtr* string1 = + MutableRaw(message1, field); + ArenaStringPtr* string2 = + MutableRaw(message2, field); + const std::string* default_ptr = + DefaultRaw(field).GetPointer(); + if (arena1 == arena2) { + string1->Swap(string2, default_ptr, arena1); + } else if (string1->IsDefault(default_ptr) && + string2->IsDefault(default_ptr)) { + // Nothing to do. + } else if (string1->IsDefault(default_ptr)) { + string1->Set(default_ptr, string2->Get(), arena1); + string2->UnsafeSetDefault(default_ptr); + } else if (string2->IsDefault(default_ptr)) { + string2->Set(default_ptr, string1->Get(), arena2); + string1->UnsafeSetDefault(default_ptr); + } else { + std::string temp = string1->Get(); + string1->Set(default_ptr, string2->Get(), arena1); + string2->Set(default_ptr, std::move(temp), arena2); } - break; + } break; } break; @@ -448,10 +473,9 @@ void GeneratedMessageReflection::SwapField( } } -void GeneratedMessageReflection::SwapOneofField( - Message* message1, - Message* message2, - const OneofDescriptor* oneof_descriptor) const { +void Reflection::SwapOneofField(Message* message1, Message* message2, + const OneofDescriptor* oneof_descriptor) const { + GOOGLE_DCHECK(!oneof_descriptor->is_synthetic()); uint32 oneof_case1 = GetOneofCase(*message1, oneof_descriptor); uint32 oneof_case2 = GetOneofCase(*message2, oneof_descriptor); @@ -463,28 +487,28 @@ void GeneratedMessageReflection::SwapOneofField( double temp_double; bool temp_bool; int temp_int; - Message* temp_message = NULL; - string temp_string; + Message* temp_message = nullptr; + std::string temp_string; // Stores message1's oneof field to a temp variable. - const FieldDescriptor* field1 = NULL; + const FieldDescriptor* field1 = nullptr; if (oneof_case1 > 0) { field1 = descriptor_->FindFieldByNumber(oneof_case1); - //oneof_descriptor->field(oneof_case1); + // oneof_descriptor->field(oneof_case1); switch (field1->cpp_type()) { -#define GET_TEMP_VALUE(CPPTYPE, TYPE) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - temp_##TYPE = GetField(*message1, field1); \ - break; +#define GET_TEMP_VALUE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + temp_##TYPE = GetField(*message1, field1); \ + break; - GET_TEMP_VALUE(INT32 , int32 ); - GET_TEMP_VALUE(INT64 , int64 ); + GET_TEMP_VALUE(INT32, int32); + GET_TEMP_VALUE(INT64, int64); GET_TEMP_VALUE(UINT32, uint32); GET_TEMP_VALUE(UINT64, uint64); - GET_TEMP_VALUE(FLOAT , float ); + GET_TEMP_VALUE(FLOAT, float); GET_TEMP_VALUE(DOUBLE, double); - GET_TEMP_VALUE(BOOL , bool ); - GET_TEMP_VALUE(ENUM , int ); + GET_TEMP_VALUE(BOOL, bool); + GET_TEMP_VALUE(ENUM, int); #undef GET_TEMP_VALUE case FieldDescriptor::CPPTYPE_MESSAGE: temp_message = ReleaseMessage(message1, field1); @@ -501,27 +525,24 @@ void GeneratedMessageReflection::SwapOneofField( // Sets message1's oneof field from the message2's oneof field. if (oneof_case2 > 0) { - const FieldDescriptor* field2 = - descriptor_->FindFieldByNumber(oneof_case2); + const FieldDescriptor* field2 = descriptor_->FindFieldByNumber(oneof_case2); switch (field2->cpp_type()) { -#define SET_ONEOF_VALUE1(CPPTYPE, TYPE) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - SetField(message1, field2, GetField(*message2, field2)); \ - break; +#define SET_ONEOF_VALUE1(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + SetField(message1, field2, GetField(*message2, field2)); \ + break; - SET_ONEOF_VALUE1(INT32 , int32 ); - SET_ONEOF_VALUE1(INT64 , int64 ); + SET_ONEOF_VALUE1(INT32, int32); + SET_ONEOF_VALUE1(INT64, int64); SET_ONEOF_VALUE1(UINT32, uint32); SET_ONEOF_VALUE1(UINT64, uint64); - SET_ONEOF_VALUE1(FLOAT , float ); + SET_ONEOF_VALUE1(FLOAT, float); SET_ONEOF_VALUE1(DOUBLE, double); - SET_ONEOF_VALUE1(BOOL , bool ); - SET_ONEOF_VALUE1(ENUM , int ); + SET_ONEOF_VALUE1(BOOL, bool); + SET_ONEOF_VALUE1(ENUM, int); #undef SET_ONEOF_VALUE1 case FieldDescriptor::CPPTYPE_MESSAGE: - SetAllocatedMessage(message1, - ReleaseMessage(message2, field2), - field2); + SetAllocatedMessage(message1, ReleaseMessage(message2, field2), field2); break; case FieldDescriptor::CPPTYPE_STRING: @@ -538,19 +559,19 @@ void GeneratedMessageReflection::SwapOneofField( // Sets message2's oneof field from the temp variable. if (oneof_case1 > 0) { switch (field1->cpp_type()) { -#define SET_ONEOF_VALUE2(CPPTYPE, TYPE) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - SetField(message2, field1, temp_##TYPE); \ - break; +#define SET_ONEOF_VALUE2(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + SetField(message2, field1, temp_##TYPE); \ + break; - SET_ONEOF_VALUE2(INT32 , int32 ); - SET_ONEOF_VALUE2(INT64 , int64 ); + SET_ONEOF_VALUE2(INT32, int32); + SET_ONEOF_VALUE2(INT64, int64); SET_ONEOF_VALUE2(UINT32, uint32); SET_ONEOF_VALUE2(UINT64, uint64); - SET_ONEOF_VALUE2(FLOAT , float ); + SET_ONEOF_VALUE2(FLOAT, float); SET_ONEOF_VALUE2(DOUBLE, double); - SET_ONEOF_VALUE2(BOOL , bool ); - SET_ONEOF_VALUE2(ENUM , int ); + SET_ONEOF_VALUE2(BOOL, bool); + SET_ONEOF_VALUE2(ENUM, int); #undef SET_ONEOF_VALUE2 case FieldDescriptor::CPPTYPE_MESSAGE: SetAllocatedMessage(message2, temp_message, field1); @@ -568,26 +589,26 @@ void GeneratedMessageReflection::SwapOneofField( } } -void GeneratedMessageReflection::Swap( - Message* message1, - Message* message2) const { +void Reflection::Swap(Message* message1, Message* message2) const { if (message1 == message2) return; // TODO(kenton): Other Reflection methods should probably check this too. GOOGLE_CHECK_EQ(message1->GetReflection(), this) - << "First argument to Swap() (of type \"" - << message1->GetDescriptor()->full_name() - << "\") is not compatible with this reflection object (which is for type \"" - << descriptor_->full_name() - << "\"). Note that the exact same class is required; not just the same " - "descriptor."; + << "First argument to Swap() (of type \"" + << message1->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type " + "\"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; GOOGLE_CHECK_EQ(message2->GetReflection(), this) - << "Second argument to Swap() (of type \"" - << message2->GetDescriptor()->full_name() - << "\") is not compatible with this reflection object (which is for type \"" - << descriptor_->full_name() - << "\"). Note that the exact same class is required; not just the same " - "descriptor."; + << "Second argument to Swap() (of type \"" + << message2->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type " + "\"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; // Check that both messages are in the same arena (or both on the heap). We // need to copy all data if not, due to ownership semantics. @@ -598,7 +619,7 @@ void GeneratedMessageReflection::Swap( temp->MergeFrom(*message2); message2->CopyFrom(*message1); Swap(message1, temp); - if (GetArena(message1) == NULL) { + if (GetArena(message1) == nullptr) { delete temp; } return; @@ -611,7 +632,7 @@ void GeneratedMessageReflection::Swap( int fields_with_has_bits = 0; for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (field->is_repeated() || field->containing_oneof()) { + if (field->is_repeated() || schema_.InRealOneof(field)) { continue; } fields_with_has_bits++; @@ -626,12 +647,16 @@ void GeneratedMessageReflection::Swap( for (int i = 0; i <= last_non_weak_field_index_; i++) { const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof()) continue; + if (schema_.InRealOneof(field)) continue; + if (schema_.IsFieldStripped(field)) continue; SwapField(message1, message2, field); } const int oneof_decl_count = descriptor_->oneof_decl_count(); for (int i = 0; i < oneof_decl_count; i++) { - SwapOneofField(message1, message2, descriptor_->oneof_decl(i)); + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + if (!oneof->is_synthetic()) { + SwapOneofField(message1, message2, oneof); + } } if (schema_.HasExtensionSet()) { @@ -641,39 +666,40 @@ void GeneratedMessageReflection::Swap( MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2)); } -void GeneratedMessageReflection::SwapFields( - Message* message1, - Message* message2, +void Reflection::SwapFields( + Message* message1, Message* message2, const std::vector& fields) const { if (message1 == message2) return; // TODO(kenton): Other Reflection methods should probably check this too. GOOGLE_CHECK_EQ(message1->GetReflection(), this) - << "First argument to SwapFields() (of type \"" - << message1->GetDescriptor()->full_name() - << "\") is not compatible with this reflection object (which is for type \"" - << descriptor_->full_name() - << "\"). Note that the exact same class is required; not just the same " - "descriptor."; + << "First argument to SwapFields() (of type \"" + << message1->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type " + "\"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; GOOGLE_CHECK_EQ(message2->GetReflection(), this) - << "Second argument to SwapFields() (of type \"" - << message2->GetDescriptor()->full_name() - << "\") is not compatible with this reflection object (which is for type \"" - << descriptor_->full_name() - << "\"). Note that the exact same class is required; not just the same " - "descriptor."; + << "Second argument to SwapFields() (of type \"" + << message2->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type " + "\"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; std::set swapped_oneof; const int fields_size = static_cast(fields.size()); for (int i = 0; i < fields_size; i++) { const FieldDescriptor* field = fields[i]; + CheckInvalidAccess(schema_, field); if (field->is_extension()) { MutableExtensionSet(message1)->SwapExtension( - MutableExtensionSet(message2), - field->number()); + MutableExtensionSet(message2), field->number()); } else { - if (field->containing_oneof()) { + if (schema_.InRealOneof(field)) { int oneof_index = field->containing_oneof()->index(); // Only swap the oneof field once. if (swapped_oneof.find(oneof_index) != swapped_oneof.end()) { @@ -696,15 +722,16 @@ void GeneratedMessageReflection::SwapFields( // ------------------------------------------------------------------- -bool GeneratedMessageReflection::HasField(const Message& message, - const FieldDescriptor* field) const { +bool Reflection::HasField(const Message& message, + const FieldDescriptor* field) const { USAGE_CHECK_MESSAGE_TYPE(HasField); USAGE_CHECK_SINGULAR(HasField); + CheckInvalidAccess(schema_, field); if (field->is_extension()) { return GetExtensionSet(message).Has(field->number()); } else { - if (field->containing_oneof()) { + if (schema_.InRealOneof(field)) { return HasOneofField(message, field); } else { return HasBit(message, field); @@ -712,33 +739,42 @@ bool GeneratedMessageReflection::HasField(const Message& message, } } -int GeneratedMessageReflection::FieldSize(const Message& message, - const FieldDescriptor* field) const { +int Reflection::FieldSize(const Message& message, + const FieldDescriptor* field) const { USAGE_CHECK_MESSAGE_TYPE(FieldSize); USAGE_CHECK_REPEATED(FieldSize); + CheckInvalidAccess(schema_, field); if (field->is_extension()) { return GetExtensionSet(message).ExtensionSize(field->number()); } else { switch (field->cpp_type()) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case FieldDescriptor::CPPTYPE_##UPPERCASE : \ - return GetRaw >(message, field).size() +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + return GetRaw >(message, field).size() - HANDLE_TYPE( INT32, int32); - HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); HANDLE_TYPE(UINT32, uint32); HANDLE_TYPE(UINT64, uint64); HANDLE_TYPE(DOUBLE, double); - HANDLE_TYPE( FLOAT, float); - HANDLE_TYPE( BOOL, bool); - HANDLE_TYPE( ENUM, int); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, int); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: case FieldDescriptor::CPPTYPE_MESSAGE: if (IsMapFieldInApi(field)) { - return GetRaw(message, field).GetRepeatedField().size(); + const internal::MapFieldBase& map = + GetRaw(message, field); + if (map.IsRepeatedFieldValid()) { + return map.GetRepeatedField().size(); + } else { + // No need to materialize the repeated field if it is out of sync: + // its size will be the same as the map's size. + return map.size(); + } } else { return GetRaw(message, field).size(); } @@ -749,14 +785,15 @@ int GeneratedMessageReflection::FieldSize(const Message& message, } } -void GeneratedMessageReflection::ClearField( - Message* message, const FieldDescriptor* field) const { +void Reflection::ClearField(Message* message, + const FieldDescriptor* field) const { USAGE_CHECK_MESSAGE_TYPE(ClearField); + CheckInvalidAccess(schema_, field); if (field->is_extension()) { MutableExtensionSet(message)->ClearExtension(field->number()); } else if (!field->is_repeated()) { - if (field->containing_oneof()) { + if (schema_.InRealOneof(field)) { ClearOneofField(message, field); return; } @@ -765,34 +802,33 @@ void GeneratedMessageReflection::ClearField( // We need to set the field back to its default value. switch (field->cpp_type()) { -#define CLEAR_TYPE(CPPTYPE, TYPE) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - *MutableRaw(message, field) = \ - field->default_value_##TYPE(); \ - break; +#define CLEAR_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + *MutableRaw(message, field) = field->default_value_##TYPE(); \ + break; - CLEAR_TYPE(INT32 , int32 ); - CLEAR_TYPE(INT64 , int64 ); + CLEAR_TYPE(INT32, int32); + CLEAR_TYPE(INT64, int64); CLEAR_TYPE(UINT32, uint32); CLEAR_TYPE(UINT64, uint64); - CLEAR_TYPE(FLOAT , float ); + CLEAR_TYPE(FLOAT, float); CLEAR_TYPE(DOUBLE, double); - CLEAR_TYPE(BOOL , bool ); + CLEAR_TYPE(BOOL, bool); #undef CLEAR_TYPE case FieldDescriptor::CPPTYPE_ENUM: *MutableRaw(message, field) = - field->default_value_enum()->number(); + field->default_value_enum()->number(); break; case FieldDescriptor::CPPTYPE_STRING: { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { - const string* default_ptr = - &DefaultRaw(field).Get(); - MutableRaw(message, field)->SetAllocated( - default_ptr, NULL, GetArena(message)); + const std::string* default_ptr = + DefaultRaw(field).GetPointer(); + MutableRaw(message, field) + ->SetAllocated(default_ptr, nullptr, GetArena(message)); break; } } @@ -800,13 +836,13 @@ void GeneratedMessageReflection::ClearField( } case FieldDescriptor::CPPTYPE_MESSAGE: - if (!schema_.HasHasbits()) { + if (schema_.HasBitIndex(field) == static_cast(-1)) { // Proto3 does not have has-bits and we need to set a message field - // to NULL in order to indicate its un-presence. - if (GetArena(message) == NULL) { + // to nullptr in order to indicate its un-presence. + if (GetArena(message) == nullptr) { delete *MutableRaw(message, field); } - *MutableRaw(message, field) = NULL; + *MutableRaw(message, field) = nullptr; } else { (*MutableRaw(message, field))->Clear(); } @@ -815,26 +851,26 @@ void GeneratedMessageReflection::ClearField( } } else { switch (field->cpp_type()) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case FieldDescriptor::CPPTYPE_##UPPERCASE : \ - MutableRaw >(message, field)->Clear(); \ - break +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + MutableRaw >(message, field)->Clear(); \ + break - HANDLE_TYPE( INT32, int32); - HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); HANDLE_TYPE(UINT32, uint32); HANDLE_TYPE(UINT64, uint64); HANDLE_TYPE(DOUBLE, double); - HANDLE_TYPE( FLOAT, float); - HANDLE_TYPE( BOOL, bool); - HANDLE_TYPE( ENUM, int); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, int); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: - MutableRaw >(message, field)->Clear(); + MutableRaw >(message, field)->Clear(); break; } break; @@ -842,9 +878,7 @@ void GeneratedMessageReflection::ClearField( case FieldDescriptor::CPPTYPE_MESSAGE: { if (IsMapFieldInApi(field)) { - MutableRaw(message, field) - ->MutableRepeatedField() - ->Clear >(); + MutableRaw(message, field)->Clear(); } else { // We don't know which subclass of RepeatedPtrFieldBase the type is, // so we use RepeatedPtrFieldBase directly. @@ -857,36 +891,37 @@ void GeneratedMessageReflection::ClearField( } } -void GeneratedMessageReflection::RemoveLast( - Message* message, - const FieldDescriptor* field) const { +void Reflection::RemoveLast(Message* message, + const FieldDescriptor* field) const { USAGE_CHECK_MESSAGE_TYPE(RemoveLast); USAGE_CHECK_REPEATED(RemoveLast); + CheckInvalidAccess(schema_, field); if (field->is_extension()) { MutableExtensionSet(message)->RemoveLast(field->number()); } else { switch (field->cpp_type()) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case FieldDescriptor::CPPTYPE_##UPPERCASE : \ - MutableRaw >(message, field)->RemoveLast(); \ - break +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + MutableRaw >(message, field)->RemoveLast(); \ + break - HANDLE_TYPE( INT32, int32); - HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); HANDLE_TYPE(UINT32, uint32); HANDLE_TYPE(UINT64, uint64); HANDLE_TYPE(DOUBLE, double); - HANDLE_TYPE( FLOAT, float); - HANDLE_TYPE( BOOL, bool); - HANDLE_TYPE( ENUM, int); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, int); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: - MutableRaw >(message, field)->RemoveLast(); + MutableRaw >(message, field) + ->RemoveLast(); break; } break; @@ -898,17 +933,17 @@ void GeneratedMessageReflection::RemoveLast( ->RemoveLast >(); } else { MutableRaw(message, field) - ->RemoveLast >(); + ->RemoveLast >(); } break; } } } -Message* GeneratedMessageReflection::ReleaseLast( - Message* message, - const FieldDescriptor* field) const { +Message* Reflection::ReleaseLast(Message* message, + const FieldDescriptor* field) const { USAGE_CHECK_ALL(ReleaseLast, REPEATED, MESSAGE); + CheckInvalidAccess(schema_, field); if (field->is_extension()) { return static_cast( @@ -920,37 +955,35 @@ Message* GeneratedMessageReflection::ReleaseLast( ->ReleaseLast >(); } else { return MutableRaw(message, field) - ->ReleaseLast >(); + ->ReleaseLast >(); } } } -void GeneratedMessageReflection::SwapElements( - Message* message, - const FieldDescriptor* field, - int index1, - int index2) const { +void Reflection::SwapElements(Message* message, const FieldDescriptor* field, + int index1, int index2) const { USAGE_CHECK_MESSAGE_TYPE(Swap); USAGE_CHECK_REPEATED(Swap); + CheckInvalidAccess(schema_, field); if (field->is_extension()) { MutableExtensionSet(message)->SwapElements(field->number(), index1, index2); } else { switch (field->cpp_type()) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case FieldDescriptor::CPPTYPE_##UPPERCASE : \ - MutableRaw >(message, field) \ - ->SwapElements(index1, index2); \ - break - - HANDLE_TYPE( INT32, int32); - HANDLE_TYPE( INT64, int64); +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + MutableRaw >(message, field) \ + ->SwapElements(index1, index2); \ + break + + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); HANDLE_TYPE(UINT32, uint32); HANDLE_TYPE(UINT64, uint64); HANDLE_TYPE(DOUBLE, double); - HANDLE_TYPE( FLOAT, float); - HANDLE_TYPE( BOOL, bool); - HANDLE_TYPE( ENUM, int); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, int); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: @@ -961,7 +994,7 @@ void GeneratedMessageReflection::SwapElements( ->SwapElements(index1, index2); } else { MutableRaw(message, field) - ->SwapElements(index1, index2); + ->SwapElements(index1, index2); } break; } @@ -977,16 +1010,27 @@ struct FieldNumberSorter { } }; -inline bool IsIndexInHasBitSet( - const uint32* has_bit_set, uint32 has_bit_index) { +bool IsIndexInHasBitSet(const uint32* has_bit_set, uint32 has_bit_index) { GOOGLE_DCHECK_NE(has_bit_index, ~0u); return ((has_bit_set[has_bit_index / 32] >> (has_bit_index % 32)) & static_cast(1)) != 0; } + +bool CreateUnknownEnumValues(const FileDescriptor* file) { + return file->syntax() == FileDescriptor::SYNTAX_PROTO3; +} } // namespace -void GeneratedMessageReflection::ListFields( - const Message& message, +namespace internal { +bool CreateUnknownEnumValues(const FieldDescriptor* field) { + bool open_enum = false; + return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 || open_enum; +} +} // namespace internal +using internal::CreateUnknownEnumValues; + +void Reflection::ListFieldsMayFailOnStripped( + const Message& message, bool should_fail, std::vector* output) const { output->clear(); @@ -995,29 +1039,35 @@ void GeneratedMessageReflection::ListFields( // Optimization: Avoid calling GetHasBits() and HasOneofField() many times // within the field loop. We allow this violation of ReflectionSchema - // encapsulation because this function takes a noticable about of CPU + // encapsulation because this function takes a noticeable about of CPU // fleetwide and properly allowing this optimization through public interfaces // seems more trouble than it is worth. const uint32* const has_bits = - schema_.HasHasbits() ? GetHasBits(message) : NULL; + schema_.HasHasbits() ? GetHasBits(message) : nullptr; const uint32* const has_bits_indices = schema_.has_bit_indices_; - const uint32* const oneof_case_array = - GetConstPointerAtOffset(&message, schema_.oneof_case_offset_); output->reserve(descriptor_->field_count()); - for (int i = 0; i <= last_non_weak_field_index_; i++) { + const int last_non_weak_field_index = last_non_weak_field_index_; + for (int i = 0; i <= last_non_weak_field_index; i++) { const FieldDescriptor* field = descriptor_->field(i); + if (!should_fail && schema_.IsFieldStripped(field)) { + continue; + } if (field->is_repeated()) { if (FieldSize(message, field) > 0) { output->push_back(field); } } else { const OneofDescriptor* containing_oneof = field->containing_oneof(); - if (containing_oneof) { + if (schema_.InRealOneof(field)) { + const uint32* const oneof_case_array = GetConstPointerAtOffset( + &message, schema_.oneof_case_offset_); // Equivalent to: HasOneofField(message, field) - if (oneof_case_array[containing_oneof->index()] == field->number()) { + if (static_cast(oneof_case_array[containing_oneof->index()]) == + field->number()) { output->push_back(field); } - } else if (has_bits) { + } else if (has_bits && has_bits_indices[i] != static_cast(-1)) { + CheckInvalidAccess(schema_, field); // Equivalent to: HasBit(message, field) if (IsIndexInHasBitSet(has_bits, has_bits_indices[i])) { output->push_back(field); @@ -1036,140 +1086,163 @@ void GeneratedMessageReflection::ListFields( std::sort(output->begin(), output->end(), FieldNumberSorter()); } +void Reflection::ListFields(const Message& message, + std::vector* output) const { + ListFieldsMayFailOnStripped(message, true, output); +} + +void Reflection::ListFieldsOmitStripped( + const Message& message, std::vector* output) const { + ListFieldsMayFailOnStripped(message, false, output); +} + // ------------------------------------------------------------------- #undef DEFINE_PRIMITIVE_ACCESSORS -#define DEFINE_PRIMITIVE_ACCESSORS(TYPENAME, TYPE, PASSTYPE, CPPTYPE) \ - PASSTYPE GeneratedMessageReflection::Get##TYPENAME( \ - const Message& message, const FieldDescriptor* field) const { \ - USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE); \ - if (field->is_extension()) { \ - return GetExtensionSet(message).Get##TYPENAME( \ - field->number(), field->default_value_##PASSTYPE()); \ - } else { \ - return GetField(message, field); \ - } \ - } \ - \ - void GeneratedMessageReflection::Set##TYPENAME( \ - Message* message, const FieldDescriptor* field, \ - PASSTYPE value) const { \ - USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \ - if (field->is_extension()) { \ - return MutableExtensionSet(message)->Set##TYPENAME( \ - field->number(), field->type(), value, field); \ - } else { \ - SetField(message, field, value); \ - } \ - } \ - \ - PASSTYPE GeneratedMessageReflection::GetRepeated##TYPENAME( \ - const Message& message, \ - const FieldDescriptor* field, int index) const { \ - USAGE_CHECK_ALL(GetRepeated##TYPENAME, REPEATED, CPPTYPE); \ - if (field->is_extension()) { \ - return GetExtensionSet(message).GetRepeated##TYPENAME( \ - field->number(), index); \ - } else { \ - return GetRepeatedField(message, field, index); \ - } \ - } \ - \ - void GeneratedMessageReflection::SetRepeated##TYPENAME( \ - Message* message, const FieldDescriptor* field, \ - int index, PASSTYPE value) const { \ - USAGE_CHECK_ALL(SetRepeated##TYPENAME, REPEATED, CPPTYPE); \ - if (field->is_extension()) { \ - MutableExtensionSet(message)->SetRepeated##TYPENAME( \ - field->number(), index, value); \ - } else { \ - SetRepeatedField(message, field, index, value); \ - } \ - } \ - \ - void GeneratedMessageReflection::Add##TYPENAME( \ - Message* message, const FieldDescriptor* field, \ - PASSTYPE value) const { \ - USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \ - if (field->is_extension()) { \ - MutableExtensionSet(message)->Add##TYPENAME( \ - field->number(), field->type(), field->options().packed(), value, \ - field); \ - } else { \ - AddField(message, field, value); \ - } \ - } - -DEFINE_PRIMITIVE_ACCESSORS(Int32 , int32 , int32 , INT32 ) -DEFINE_PRIMITIVE_ACCESSORS(Int64 , int64 , int64 , INT64 ) +#define DEFINE_PRIMITIVE_ACCESSORS(TYPENAME, TYPE, PASSTYPE, CPPTYPE) \ + PASSTYPE Reflection::Get##TYPENAME(const Message& message, \ + const FieldDescriptor* field) const { \ + USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE); \ + if (field->is_extension()) { \ + return GetExtensionSet(message).Get##TYPENAME( \ + field->number(), field->default_value_##PASSTYPE()); \ + } else if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { \ + return field->default_value_##PASSTYPE(); \ + } else { \ + return GetField(message, field); \ + } \ + } \ + \ + void Reflection::Set##TYPENAME( \ + Message* message, const FieldDescriptor* field, PASSTYPE value) const { \ + USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \ + if (field->is_extension()) { \ + return MutableExtensionSet(message)->Set##TYPENAME( \ + field->number(), field->type(), value, field); \ + } else { \ + SetField(message, field, value); \ + } \ + } \ + \ + PASSTYPE Reflection::GetRepeated##TYPENAME( \ + const Message& message, const FieldDescriptor* field, int index) const { \ + USAGE_CHECK_ALL(GetRepeated##TYPENAME, REPEATED, CPPTYPE); \ + if (field->is_extension()) { \ + return GetExtensionSet(message).GetRepeated##TYPENAME(field->number(), \ + index); \ + } else { \ + return GetRepeatedField(message, field, index); \ + } \ + } \ + \ + void Reflection::SetRepeated##TYPENAME(Message* message, \ + const FieldDescriptor* field, \ + int index, PASSTYPE value) const { \ + USAGE_CHECK_ALL(SetRepeated##TYPENAME, REPEATED, CPPTYPE); \ + if (field->is_extension()) { \ + MutableExtensionSet(message)->SetRepeated##TYPENAME(field->number(), \ + index, value); \ + } else { \ + SetRepeatedField(message, field, index, value); \ + } \ + } \ + \ + void Reflection::Add##TYPENAME( \ + Message* message, const FieldDescriptor* field, PASSTYPE value) const { \ + USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \ + if (field->is_extension()) { \ + MutableExtensionSet(message)->Add##TYPENAME( \ + field->number(), field->type(), field->options().packed(), value, \ + field); \ + } else { \ + AddField(message, field, value); \ + } \ + } + +DEFINE_PRIMITIVE_ACCESSORS(Int32, int32, int32, INT32) +DEFINE_PRIMITIVE_ACCESSORS(Int64, int64, int64, INT64) DEFINE_PRIMITIVE_ACCESSORS(UInt32, uint32, uint32, UINT32) DEFINE_PRIMITIVE_ACCESSORS(UInt64, uint64, uint64, UINT64) -DEFINE_PRIMITIVE_ACCESSORS(Float , float , float , FLOAT ) +DEFINE_PRIMITIVE_ACCESSORS(Float, float, float, FLOAT) DEFINE_PRIMITIVE_ACCESSORS(Double, double, double, DOUBLE) -DEFINE_PRIMITIVE_ACCESSORS(Bool , bool , bool , BOOL ) +DEFINE_PRIMITIVE_ACCESSORS(Bool, bool, bool, BOOL) #undef DEFINE_PRIMITIVE_ACCESSORS // ------------------------------------------------------------------- -string GeneratedMessageReflection::GetString( - const Message& message, const FieldDescriptor* field) const { +std::string Reflection::GetString(const Message& message, + const FieldDescriptor* field) const { USAGE_CHECK_ALL(GetString, SINGULAR, STRING); if (field->is_extension()) { return GetExtensionSet(message).GetString(field->number(), field->default_value_string()); } else { + if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { + return field->default_value_string(); + } switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { - return GetField(message, field).Get(); + if (auto* value = + GetField(message, field).GetPointer()) { + return *value; + } + return field->default_value_string(); } } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return GetEmptyString(); // Make compiler happy. } } -const string& GeneratedMessageReflection::GetStringReference( - const Message& message, - const FieldDescriptor* field, string* scratch) const { +const std::string& Reflection::GetStringReference(const Message& message, + const FieldDescriptor* field, + std::string* scratch) const { USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING); if (field->is_extension()) { return GetExtensionSet(message).GetString(field->number(), field->default_value_string()); } else { + if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { + return field->default_value_string(); + } switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { - return GetField(message, field).Get(); + if (auto* value = + GetField(message, field).GetPointer()) { + return *value; + } + return field->default_value_string(); } } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return GetEmptyString(); // Make compiler happy. } } -void GeneratedMessageReflection::SetString( - Message* message, const FieldDescriptor* field, - const string& value) const { +void Reflection::SetString(Message* message, const FieldDescriptor* field, + std::string value) const { USAGE_CHECK_ALL(SetString, SINGULAR, STRING); if (field->is_extension()) { - return MutableExtensionSet(message)->SetString(field->number(), - field->type(), value, field); + return MutableExtensionSet(message)->SetString( + field->number(), field->type(), std::move(value), field); } else { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { - const string* default_ptr = &DefaultRaw(field).Get(); - if (field->containing_oneof() && !HasOneofField(*message, field)) { + // Oneof string fields are never set as a default instance. + // We just need to pass some arbitrary default string to make it work. + // This allows us to not have the real default accessible from + // reflection. + const std::string* default_ptr = + schema_.InRealOneof(field) + ? nullptr + : DefaultRaw(field).GetPointer(); + if (schema_.InRealOneof(field) && !HasOneofField(*message, field)) { ClearOneof(message, field->containing_oneof()); - MutableField(message, field)->UnsafeSetDefault( - default_ptr); + MutableField(message, field) + ->UnsafeSetDefault(default_ptr); } - MutableField(message, field)->Set(default_ptr, - value, GetArena(message)); + MutableField(message, field) + ->Set(default_ptr, std::move(value), GetArena(message)); break; } } @@ -1177,8 +1250,9 @@ void GeneratedMessageReflection::SetString( } -string GeneratedMessageReflection::GetRepeatedString( - const Message& message, const FieldDescriptor* field, int index) const { +std::string Reflection::GetRepeatedString(const Message& message, + const FieldDescriptor* field, + int index) const { USAGE_CHECK_ALL(GetRepeatedString, REPEATED, STRING); if (field->is_extension()) { return GetExtensionSet(message).GetRepeatedString(field->number(), index); @@ -1186,17 +1260,14 @@ string GeneratedMessageReflection::GetRepeatedString( switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: - return GetRepeatedPtrField(message, field, index); + return GetRepeatedPtrField(message, field, index); } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return GetEmptyString(); // Make compiler happy. } } -const string& GeneratedMessageReflection::GetRepeatedStringReference( - const Message& message, const FieldDescriptor* field, - int index, string* scratch) const { +const std::string& Reflection::GetRepeatedStringReference( + const Message& message, const FieldDescriptor* field, int index, + std::string* scratch) const { USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING); if (field->is_extension()) { return GetExtensionSet(message).GetRepeatedString(field->number(), index); @@ -1204,45 +1275,42 @@ const string& GeneratedMessageReflection::GetRepeatedStringReference( switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: - return GetRepeatedPtrField(message, field, index); + return GetRepeatedPtrField(message, field, index); } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return GetEmptyString(); // Make compiler happy. } } -void GeneratedMessageReflection::SetRepeatedString( - Message* message, const FieldDescriptor* field, - int index, const string& value) const { +void Reflection::SetRepeatedString(Message* message, + const FieldDescriptor* field, int index, + std::string value) const { USAGE_CHECK_ALL(SetRepeatedString, REPEATED, STRING); if (field->is_extension()) { - MutableExtensionSet(message)->SetRepeatedString( - field->number(), index, value); + MutableExtensionSet(message)->SetRepeatedString(field->number(), index, + std::move(value)); } else { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: - *MutableRepeatedField(message, field, index) = value; + MutableRepeatedField(message, field, index) + ->assign(std::move(value)); break; } } } -void GeneratedMessageReflection::AddString( - Message* message, const FieldDescriptor* field, - const string& value) const { +void Reflection::AddString(Message* message, const FieldDescriptor* field, + std::string value) const { USAGE_CHECK_ALL(AddString, REPEATED, STRING); if (field->is_extension()) { - MutableExtensionSet(message)->AddString(field->number(), - field->type(), value, field); + MutableExtensionSet(message)->AddString(field->number(), field->type(), + std::move(value), field); } else { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: - *AddField(message, field) = value; + AddField(message, field)->assign(std::move(value)); break; } } @@ -1251,79 +1319,73 @@ void GeneratedMessageReflection::AddString( // ------------------------------------------------------------------- -inline bool CreateUnknownEnumValues(const FileDescriptor* file) { - return file->syntax() == FileDescriptor::SYNTAX_PROTO3; -} - -const EnumValueDescriptor* GeneratedMessageReflection::GetEnum( +const EnumValueDescriptor* Reflection::GetEnum( const Message& message, const FieldDescriptor* field) const { // Usage checked by GetEnumValue. int value = GetEnumValue(message, field); return field->enum_type()->FindValueByNumberCreatingIfUnknown(value); } -int GeneratedMessageReflection::GetEnumValue( - const Message& message, const FieldDescriptor* field) const { +int Reflection::GetEnumValue(const Message& message, + const FieldDescriptor* field) const { USAGE_CHECK_ALL(GetEnumValue, SINGULAR, ENUM); int32 value; if (field->is_extension()) { value = GetExtensionSet(message).GetEnum( - field->number(), field->default_value_enum()->number()); + field->number(), field->default_value_enum()->number()); + } else if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { + value = field->default_value_enum()->number(); } else { value = GetField(message, field); } return value; } -void GeneratedMessageReflection::SetEnum( - Message* message, const FieldDescriptor* field, - const EnumValueDescriptor* value) const { +void Reflection::SetEnum(Message* message, const FieldDescriptor* field, + const EnumValueDescriptor* value) const { // Usage checked by SetEnumValue. USAGE_CHECK_ENUM_VALUE(SetEnum); SetEnumValueInternal(message, field, value->number()); } -void GeneratedMessageReflection::SetEnumValue( - Message* message, const FieldDescriptor* field, - int value) const { +void Reflection::SetEnumValue(Message* message, const FieldDescriptor* field, + int value) const { USAGE_CHECK_ALL(SetEnumValue, SINGULAR, ENUM); - if (!CreateUnknownEnumValues(descriptor_->file())) { + if (!CreateUnknownEnumValues(field)) { // Check that the value is valid if we don't support direct storage of // unknown enum values. const EnumValueDescriptor* value_desc = field->enum_type()->FindValueByNumber(value); - if (value_desc == NULL) { - GOOGLE_LOG(DFATAL) << "SetEnumValue accepts only valid integer values: value " - << value << " unexpected for field " << field->full_name(); - // In production builds, DFATAL will not terminate the program, so we have - // to do something reasonable: just set the default value. - value = field->default_value_enum()->number(); + if (value_desc == nullptr) { + MutableUnknownFields(message)->AddVarint(field->number(), value); + return; } } SetEnumValueInternal(message, field, value); } -void GeneratedMessageReflection::SetEnumValueInternal( - Message* message, const FieldDescriptor* field, - int value) const { +void Reflection::SetEnumValueInternal(Message* message, + const FieldDescriptor* field, + int value) const { if (field->is_extension()) { - MutableExtensionSet(message)->SetEnum(field->number(), field->type(), - value, field); + MutableExtensionSet(message)->SetEnum(field->number(), field->type(), value, + field); } else { SetField(message, field, value); } } -const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum( +const EnumValueDescriptor* Reflection::GetRepeatedEnum( const Message& message, const FieldDescriptor* field, int index) const { // Usage checked by GetRepeatedEnumValue. int value = GetRepeatedEnumValue(message, field, index); return field->enum_type()->FindValueByNumberCreatingIfUnknown(value); } -int GeneratedMessageReflection::GetRepeatedEnumValue( - const Message& message, const FieldDescriptor* field, int index) const { +int Reflection::GetRepeatedEnumValue(const Message& message, + const FieldDescriptor* field, + int index) const { USAGE_CHECK_ALL(GetRepeatedEnumValue, REPEATED, ENUM); int value; @@ -1335,84 +1397,72 @@ int GeneratedMessageReflection::GetRepeatedEnumValue( return value; } -void GeneratedMessageReflection::SetRepeatedEnum( - Message* message, - const FieldDescriptor* field, int index, - const EnumValueDescriptor* value) const { +void Reflection::SetRepeatedEnum(Message* message, const FieldDescriptor* field, + int index, + const EnumValueDescriptor* value) const { // Usage checked by SetRepeatedEnumValue. USAGE_CHECK_ENUM_VALUE(SetRepeatedEnum); SetRepeatedEnumValueInternal(message, field, index, value->number()); } -void GeneratedMessageReflection::SetRepeatedEnumValue( - Message* message, - const FieldDescriptor* field, int index, - int value) const { +void Reflection::SetRepeatedEnumValue(Message* message, + const FieldDescriptor* field, int index, + int value) const { USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM); - if (!CreateUnknownEnumValues(descriptor_->file())) { + if (!CreateUnknownEnumValues(field)) { // Check that the value is valid if we don't support direct storage of // unknown enum values. const EnumValueDescriptor* value_desc = field->enum_type()->FindValueByNumber(value); - if (value_desc == NULL) { - GOOGLE_LOG(DFATAL) << "SetRepeatedEnumValue accepts only valid integer values: " - << "value " << value << " unexpected for field " - << field->full_name(); - // In production builds, DFATAL will not terminate the program, so we have - // to do something reasonable: just set the default value. - value = field->default_value_enum()->number(); + if (value_desc == nullptr) { + MutableUnknownFields(message)->AddVarint(field->number(), value); + return; } } SetRepeatedEnumValueInternal(message, field, index, value); } -void GeneratedMessageReflection::SetRepeatedEnumValueInternal( - Message* message, - const FieldDescriptor* field, int index, - int value) const { +void Reflection::SetRepeatedEnumValueInternal(Message* message, + const FieldDescriptor* field, + int index, int value) const { if (field->is_extension()) { - MutableExtensionSet(message)->SetRepeatedEnum( - field->number(), index, value); + MutableExtensionSet(message)->SetRepeatedEnum(field->number(), index, + value); } else { SetRepeatedField(message, field, index, value); } } -void GeneratedMessageReflection::AddEnum( - Message* message, const FieldDescriptor* field, - const EnumValueDescriptor* value) const { +void Reflection::AddEnum(Message* message, const FieldDescriptor* field, + const EnumValueDescriptor* value) const { // Usage checked by AddEnumValue. USAGE_CHECK_ENUM_VALUE(AddEnum); AddEnumValueInternal(message, field, value->number()); } -void GeneratedMessageReflection::AddEnumValue( - Message* message, const FieldDescriptor* field, - int value) const { +void Reflection::AddEnumValue(Message* message, const FieldDescriptor* field, + int value) const { USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM); - if (!CreateUnknownEnumValues(descriptor_->file())) { + if (!CreateUnknownEnumValues(field)) { // Check that the value is valid if we don't support direct storage of // unknown enum values. const EnumValueDescriptor* value_desc = field->enum_type()->FindValueByNumber(value); - if (value_desc == NULL) { - GOOGLE_LOG(DFATAL) << "AddEnumValue accepts only valid integer values: value " - << value << " unexpected for field " << field->full_name(); - // In production builds, DFATAL will not terminate the program, so we have - // to do something reasonable: just set the default value. - value = field->default_value_enum()->number(); + if (value_desc == nullptr) { + MutableUnknownFields(message)->AddVarint(field->number(), value); + return; } } AddEnumValueInternal(message, field, value); } -void GeneratedMessageReflection::AddEnumValueInternal( - Message* message, const FieldDescriptor* field, - int value) const { +void Reflection::AddEnumValueInternal(Message* message, + const FieldDescriptor* field, + int value) const { if (field->is_extension()) { MutableExtensionSet(message)->AddEnum(field->number(), field->type(), - field->options().packed(), - value, field); + field->options().packed(), value, + field); } else { AddField(message, field, value); } @@ -1420,32 +1470,70 @@ void GeneratedMessageReflection::AddEnumValueInternal( // ------------------------------------------------------------------- -const Message& GeneratedMessageReflection::GetMessage( - const Message& message, const FieldDescriptor* field, - MessageFactory* factory) const { +const Message* Reflection::GetDefaultMessageInstance( + const FieldDescriptor* field) const { + // If we are using the generated factory, we cache the prototype in the field + // descriptor for faster access. + // The default instances of generated messages are not cross-linked, which + // means they contain null pointers on their message fields and can't be used + // to get the default of submessages. + if (message_factory_ == MessageFactory::generated_factory()) { + auto& ptr = field->default_generated_instance_; + auto* res = ptr.load(std::memory_order_acquire); + if (res == nullptr) { + // First time asking for this field's default. Load it and cache it. + res = message_factory_->GetPrototype(field->message_type()); + ptr.store(res, std::memory_order_release); + } + return res; + } + + // For other factories, we try the default's object field. + // In particular, the DynamicMessageFactory will cross link the default + // instances to allow for this. But only do this for real fields. + // This is an optimization to avoid going to GetPrototype() below, as that + // requires a lock and a map lookup. + if (!field->is_extension() && !field->options().weak() && + !field->options().lazy() && !schema_.InRealOneof(field)) { + auto* res = DefaultRaw(field); + if (res != nullptr) { + return res; + } + } + // Otherwise, just go to the factory. + return message_factory_->GetPrototype(field->message_type()); +} + +const Message& Reflection::GetMessage(const Message& message, + const FieldDescriptor* field, + MessageFactory* factory) const { USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE); + CheckInvalidAccess(schema_, field); - if (factory == NULL) factory = message_factory_; + if (factory == nullptr) factory = message_factory_; if (field->is_extension()) { - return static_cast( - GetExtensionSet(message).GetMessage( - field->number(), field->message_type(), factory)); + return static_cast(GetExtensionSet(message).GetMessage( + field->number(), field->message_type(), factory)); } else { + if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { + return *GetDefaultMessageInstance(field); + } const Message* result = GetRaw(message, field); - if (result == NULL) { - result = DefaultRaw(field); + if (result == nullptr) { + result = GetDefaultMessageInstance(field); } return *result; } } -Message* GeneratedMessageReflection::MutableMessage( - Message* message, const FieldDescriptor* field, - MessageFactory* factory) const { +Message* Reflection::MutableMessage(Message* message, + const FieldDescriptor* field, + MessageFactory* factory) const { USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE); + CheckInvalidAccess(schema_, field); - if (factory == NULL) factory = message_factory_; + if (factory == nullptr) factory = message_factory_; if (field->is_extension()) { return static_cast( @@ -1455,19 +1543,19 @@ Message* GeneratedMessageReflection::MutableMessage( Message** result_holder = MutableRaw(message, field); - if (field->containing_oneof()) { + if (schema_.InRealOneof(field)) { if (!HasOneofField(*message, field)) { ClearOneof(message, field->containing_oneof()); result_holder = MutableField(message, field); - const Message* default_message = DefaultRaw(field); + const Message* default_message = GetDefaultMessageInstance(field); *result_holder = default_message->New(message->GetArena()); } } else { SetBit(message, field); } - if (*result_holder == NULL) { - const Message* default_message = DefaultRaw(field); + if (*result_holder == nullptr) { + const Message* default_message = GetDefaultMessageInstance(field); *result_holder = default_message->New(message->GetArena()); } result = *result_holder; @@ -1475,18 +1563,18 @@ Message* GeneratedMessageReflection::MutableMessage( } } -void GeneratedMessageReflection::UnsafeArenaSetAllocatedMessage( - Message* message, - Message* sub_message, +void Reflection::UnsafeArenaSetAllocatedMessage( + Message* message, Message* sub_message, const FieldDescriptor* field) const { USAGE_CHECK_ALL(SetAllocatedMessage, SINGULAR, MESSAGE); + CheckInvalidAccess(schema_, field); if (field->is_extension()) { MutableExtensionSet(message)->UnsafeArenaSetAllocatedMessage( field->number(), field->type(), field, sub_message); } else { - if (field->containing_oneof()) { - if (sub_message == NULL) { + if (schema_.InRealOneof(field)) { + if (sub_message == nullptr) { ClearOneof(message, field->containing_oneof()); return; } @@ -1496,29 +1584,29 @@ void GeneratedMessageReflection::UnsafeArenaSetAllocatedMessage( return; } - if (sub_message == NULL) { + if (sub_message == nullptr) { ClearBit(message, field); } else { SetBit(message, field); } Message** sub_message_holder = MutableRaw(message, field); - if (GetArena(message) == NULL) { + if (GetArena(message) == nullptr) { delete *sub_message_holder; } *sub_message_holder = sub_message; } } -void GeneratedMessageReflection::SetAllocatedMessage( - Message* message, - Message* sub_message, - const FieldDescriptor* field) const { +void Reflection::SetAllocatedMessage(Message* message, Message* sub_message, + const FieldDescriptor* field) const { + CheckInvalidAccess(schema_, field); + // If message and sub-message are in different memory ownership domains // (different arenas, or one is on heap and one is not), then we may need to // do a copy. - if (sub_message != NULL && + if (sub_message != nullptr && sub_message->GetArena() != message->GetArena()) { - if (sub_message->GetArena() == NULL && message->GetArena() != NULL) { + if (sub_message->GetArena() == nullptr && message->GetArena() != nullptr) { // Case 1: parent is on an arena and child is heap-allocated. We can add // the child to the arena's Own() list to free on arena destruction, then // set our pointer. @@ -1537,42 +1625,43 @@ void GeneratedMessageReflection::SetAllocatedMessage( } } -Message* GeneratedMessageReflection::UnsafeArenaReleaseMessage( - Message* message, - const FieldDescriptor* field, - MessageFactory* factory) const { +Message* Reflection::UnsafeArenaReleaseMessage(Message* message, + const FieldDescriptor* field, + MessageFactory* factory) const { USAGE_CHECK_ALL(ReleaseMessage, SINGULAR, MESSAGE); + CheckInvalidAccess(schema_, field); - if (factory == NULL) factory = message_factory_; + if (factory == nullptr) factory = message_factory_; if (field->is_extension()) { return static_cast( MutableExtensionSet(message)->UnsafeArenaReleaseMessage(field, factory)); } else { - if (!(field->is_repeated() || field->containing_oneof())) { + if (!(field->is_repeated() || schema_.InRealOneof(field))) { ClearBit(message, field); } - if (field->containing_oneof()) { + if (schema_.InRealOneof(field)) { if (HasOneofField(*message, field)) { *MutableOneofCase(message, field->containing_oneof()) = 0; } else { - return NULL; + return nullptr; } } Message** result = MutableRaw(message, field); Message* ret = *result; - *result = NULL; + *result = nullptr; return ret; } } -Message* GeneratedMessageReflection::ReleaseMessage( - Message* message, - const FieldDescriptor* field, - MessageFactory* factory) const { +Message* Reflection::ReleaseMessage(Message* message, + const FieldDescriptor* field, + MessageFactory* factory) const { + CheckInvalidAccess(schema_, field); + Message* released = UnsafeArenaReleaseMessage(message, field, factory); - if (GetArena(message) != NULL && released != NULL) { + if (GetArena(message) != nullptr && released != nullptr) { Message* copy_from_arena = released->New(); copy_from_arena->CopyFrom(*released); released = copy_from_arena; @@ -1580,9 +1669,11 @@ Message* GeneratedMessageReflection::ReleaseMessage( return released; } -const Message& GeneratedMessageReflection::GetRepeatedMessage( - const Message& message, const FieldDescriptor* field, int index) const { +const Message& Reflection::GetRepeatedMessage(const Message& message, + const FieldDescriptor* field, + int index) const { USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE); + CheckInvalidAccess(schema_, field); if (field->is_extension()) { return static_cast( @@ -1599,14 +1690,16 @@ const Message& GeneratedMessageReflection::GetRepeatedMessage( } } -Message* GeneratedMessageReflection::MutableRepeatedMessage( - Message* message, const FieldDescriptor* field, int index) const { +Message* Reflection::MutableRepeatedMessage(Message* message, + const FieldDescriptor* field, + int index) const { USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE); + CheckInvalidAccess(schema_, field); if (field->is_extension()) { return static_cast( - MutableExtensionSet(message)->MutableRepeatedMessage( - field->number(), index)); + MutableExtensionSet(message)->MutableRepeatedMessage(field->number(), + index)); } else { if (IsMapFieldInApi(field)) { return MutableRaw(message, field) @@ -1614,27 +1707,27 @@ Message* GeneratedMessageReflection::MutableRepeatedMessage( ->Mutable >(index); } else { return MutableRaw(message, field) - ->Mutable >(index); + ->Mutable >(index); } } } -Message* GeneratedMessageReflection::AddMessage( - Message* message, const FieldDescriptor* field, - MessageFactory* factory) const { +Message* Reflection::AddMessage(Message* message, const FieldDescriptor* field, + MessageFactory* factory) const { USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE); + CheckInvalidAccess(schema_, field); - if (factory == NULL) factory = message_factory_; + if (factory == nullptr) factory = message_factory_; if (field->is_extension()) { return static_cast( MutableExtensionSet(message)->AddMessage(field, factory)); } else { - Message* result = NULL; + Message* result = nullptr; // We can't use AddField() because RepeatedPtrFieldBase doesn't // know how to allocate one. - RepeatedPtrFieldBase* repeated = NULL; + RepeatedPtrFieldBase* repeated = nullptr; if (IsMapFieldInApi(field)) { repeated = MutableRaw(message, field)->MutableRepeatedField(); @@ -1642,7 +1735,7 @@ Message* GeneratedMessageReflection::AddMessage( repeated = MutableRaw(message, field); } result = repeated->AddFromCleared >(); - if (result == NULL) { + if (result == nullptr) { // We must allocate a new object. const Message* prototype; if (repeated->size() == 0) { @@ -1661,15 +1754,16 @@ Message* GeneratedMessageReflection::AddMessage( } } -void GeneratedMessageReflection::AddAllocatedMessage( - Message* message, const FieldDescriptor* field, - Message* new_entry) const { +void Reflection::AddAllocatedMessage(Message* message, + const FieldDescriptor* field, + Message* new_entry) const { USAGE_CHECK_ALL(AddAllocatedMessage, REPEATED, MESSAGE); + CheckInvalidAccess(schema_, field); if (field->is_extension()) { MutableExtensionSet(message)->AddAllocatedMessage(field, new_entry); } else { - RepeatedPtrFieldBase* repeated = NULL; + RepeatedPtrFieldBase* repeated = nullptr; if (IsMapFieldInApi(field)) { repeated = MutableRaw(message, field)->MutableRepeatedField(); @@ -1680,17 +1774,20 @@ void GeneratedMessageReflection::AddAllocatedMessage( } } -void* GeneratedMessageReflection::MutableRawRepeatedField( - Message* message, const FieldDescriptor* field, - FieldDescriptor::CppType cpptype, - int ctype, const Descriptor* desc) const { +void* Reflection::MutableRawRepeatedField(Message* message, + const FieldDescriptor* field, + FieldDescriptor::CppType cpptype, + int ctype, + const Descriptor* desc) const { USAGE_CHECK_REPEATED("MutableRawRepeatedField"); - if (field->cpp_type() != cpptype) - ReportReflectionUsageTypeError(descriptor_, - field, "MutableRawRepeatedField", cpptype); - if (ctype >= 0) - GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch"; - if (desc != NULL) + CheckInvalidAccess(schema_, field); + + if (field->cpp_type() != cpptype && + (field->cpp_type() != FieldDescriptor::CPPTYPE_ENUM || + cpptype != FieldDescriptor::CPPTYPE_INT32)) + ReportReflectionUsageTypeError(descriptor_, field, + "MutableRawRepeatedField", cpptype); + if (desc != nullptr) GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type"; if (field->is_extension()) { return MutableExtensionSet(message)->MutableRawRepeatedField( @@ -1705,17 +1802,18 @@ void* GeneratedMessageReflection::MutableRawRepeatedField( } } -const void* GeneratedMessageReflection::GetRawRepeatedField( - const Message& message, const FieldDescriptor* field, - FieldDescriptor::CppType cpptype, - int ctype, const Descriptor* desc) const { +const void* Reflection::GetRawRepeatedField(const Message& message, + const FieldDescriptor* field, + FieldDescriptor::CppType cpptype, + int ctype, + const Descriptor* desc) const { USAGE_CHECK_REPEATED("GetRawRepeatedField"); if (field->cpp_type() != cpptype) - ReportReflectionUsageTypeError(descriptor_, - field, "GetRawRepeatedField", cpptype); + ReportReflectionUsageTypeError(descriptor_, field, "GetRawRepeatedField", + cpptype); if (ctype >= 0) GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch"; - if (desc != NULL) + if (desc != nullptr) GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type"; if (field->is_extension()) { // Should use extension_set::GetRawRepeatedField. However, the required @@ -1723,8 +1821,8 @@ const void* GeneratedMessageReflection::GetRawRepeatedField( // Map is not supported in extensions, it is acceptable to use // extension_set::MutableRawRepeatedField which does not change the message. return MutableExtensionSet(const_cast(&message)) - ->MutableRawRepeatedField( - field->number(), field->type(), field->is_packed(), field); + ->MutableRawRepeatedField(field->number(), field->type(), + field->is_packed(), field); } else { // Trigger transform for MapField if (IsMapFieldInApi(field)) { @@ -1734,120 +1832,91 @@ const void* GeneratedMessageReflection::GetRawRepeatedField( } } -const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor( - const Message& message, - const OneofDescriptor* oneof_descriptor) const { +const FieldDescriptor* Reflection::GetOneofFieldDescriptor( + const Message& message, const OneofDescriptor* oneof_descriptor) const { + if (oneof_descriptor->is_synthetic()) { + const FieldDescriptor* field = oneof_descriptor->field(0); + return HasField(message, field) ? field : nullptr; + } uint32 field_number = GetOneofCase(message, oneof_descriptor); if (field_number == 0) { - return NULL; + return nullptr; } return descriptor_->FindFieldByNumber(field_number); } -bool GeneratedMessageReflection::ContainsMapKey( - const Message& message, - const FieldDescriptor* field, - const MapKey& key) const { - USAGE_CHECK(IsMapFieldInApi(field), - "LookupMapValue", +bool Reflection::ContainsMapKey(const Message& message, + const FieldDescriptor* field, + const MapKey& key) const { + USAGE_CHECK(IsMapFieldInApi(field), "LookupMapValue", "Field is not a map field."); return GetRaw(message, field).ContainsMapKey(key); } -bool GeneratedMessageReflection::InsertOrLookupMapValue( - Message* message, - const FieldDescriptor* field, - const MapKey& key, - MapValueRef* val) const { - USAGE_CHECK(IsMapFieldInApi(field), - "InsertOrLookupMapValue", +bool Reflection::InsertOrLookupMapValue(Message* message, + const FieldDescriptor* field, + const MapKey& key, + MapValueRef* val) const { + USAGE_CHECK(IsMapFieldInApi(field), "InsertOrLookupMapValue", "Field is not a map field."); val->SetType(field->message_type()->FindFieldByName("value")->cpp_type()); - return MutableRaw(message, field)->InsertOrLookupMapValue( - key, val); + return MutableRaw(message, field) + ->InsertOrLookupMapValue(key, val); } -bool GeneratedMessageReflection::DeleteMapValue( - Message* message, - const FieldDescriptor* field, - const MapKey& key) const { - USAGE_CHECK(IsMapFieldInApi(field), - "DeleteMapValue", +bool Reflection::LookupMapValue(const Message& message, + const FieldDescriptor* field, const MapKey& key, + MapValueConstRef* val) const { + USAGE_CHECK(IsMapFieldInApi(field), "LookupMapValue", "Field is not a map field."); - return MutableRaw(message, field)->DeleteMapValue(key); + val->SetType(field->message_type()->FindFieldByName("value")->cpp_type()); + return GetRaw(message, field).LookupMapValue(key, val); } -MapIterator GeneratedMessageReflection::MapBegin( - Message* message, - const FieldDescriptor* field) const { - USAGE_CHECK(IsMapFieldInApi(field), - "MapBegin", +bool Reflection::DeleteMapValue(Message* message, const FieldDescriptor* field, + const MapKey& key) const { + USAGE_CHECK(IsMapFieldInApi(field), "DeleteMapValue", "Field is not a map field."); + return MutableRaw(message, field)->DeleteMapValue(key); +} + +MapIterator Reflection::MapBegin(Message* message, + const FieldDescriptor* field) const { + USAGE_CHECK(IsMapFieldInApi(field), "MapBegin", "Field is not a map field."); MapIterator iter(message, field); GetRaw(*message, field).MapBegin(&iter); return iter; } -MapIterator GeneratedMessageReflection::MapEnd( - Message* message, - const FieldDescriptor* field) const { - USAGE_CHECK(IsMapFieldInApi(field), - "MapEnd", - "Field is not a map field."); +MapIterator Reflection::MapEnd(Message* message, + const FieldDescriptor* field) const { + USAGE_CHECK(IsMapFieldInApi(field), "MapEnd", "Field is not a map field."); MapIterator iter(message, field); GetRaw(*message, field).MapEnd(&iter); return iter; } -int GeneratedMessageReflection::MapSize( - const Message& message, - const FieldDescriptor* field) const { - USAGE_CHECK(IsMapFieldInApi(field), - "MapSize", - "Field is not a map field."); +int Reflection::MapSize(const Message& message, + const FieldDescriptor* field) const { + USAGE_CHECK(IsMapFieldInApi(field), "MapSize", "Field is not a map field."); return GetRaw(message, field).size(); } // ----------------------------------------------------------------------------- -const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName( - const string& name) const { - if (!schema_.HasExtensionSet()) return NULL; - - const FieldDescriptor* result = descriptor_pool_->FindExtensionByName(name); - if (result != NULL && result->containing_type() == descriptor_) { - return result; - } - - if (descriptor_->options().message_set_wire_format()) { - // MessageSet extensions may be identified by type name. - const Descriptor* type = descriptor_pool_->FindMessageTypeByName(name); - if (type != NULL) { - // Look for a matching extension in the foreign type's scope. - const int type_extension_count = type->extension_count(); - for (int i = 0; i < type_extension_count; i++) { - const FieldDescriptor* extension = type->extension(i); - if (extension->containing_type() == descriptor_ && - extension->type() == FieldDescriptor::TYPE_MESSAGE && - extension->is_optional() && - extension->message_type() == type) { - // Found it. - return extension; - } - } - } - } - - return NULL; +const FieldDescriptor* Reflection::FindKnownExtensionByName( + const std::string& name) const { + if (!schema_.HasExtensionSet()) return nullptr; + return descriptor_pool_->FindExtensionByPrintableName(descriptor_, name); } -const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber( +const FieldDescriptor* Reflection::FindKnownExtensionByNumber( int number) const { - if (!schema_.HasExtensionSet()) return NULL; + if (!schema_.HasExtensionSet()) return nullptr; return descriptor_pool_->FindExtensionByNumber(descriptor_, number); } -bool GeneratedMessageReflection::SupportsUnknownEnumValues() const { +bool Reflection::SupportsUnknownEnumValues() const { return CreateUnknownEnumValues(descriptor_->file()); } @@ -1858,115 +1927,105 @@ bool GeneratedMessageReflection::SupportsUnknownEnumValues() const { // the given field. template -const Type& GeneratedMessageReflection::GetRawNonOneof( - const Message& message, const FieldDescriptor* field) const { +const Type& Reflection::GetRawNonOneof(const Message& message, + const FieldDescriptor* field) const { return GetConstRefAtOffset(message, schema_.GetFieldOffsetNonOneof(field)); } template -Type* GeneratedMessageReflection::MutableRawNonOneof( - Message* message, const FieldDescriptor* field) const { +Type* Reflection::MutableRawNonOneof(Message* message, + const FieldDescriptor* field) const { return GetPointerAtOffset(message, schema_.GetFieldOffsetNonOneof(field)); } template -const Type& GeneratedMessageReflection::GetRaw( - const Message& message, const FieldDescriptor* field) const { - if (field->containing_oneof() && !HasOneofField(message, field)) { - return DefaultRaw(field); - } +const Type& Reflection::GetRaw(const Message& message, + const FieldDescriptor* field) const { + GOOGLE_DCHECK(!schema_.InRealOneof(field) || HasOneofField(message, field)) + << "Field = " << field->full_name(); return GetConstRefAtOffset(message, schema_.GetFieldOffset(field)); } template -Type* GeneratedMessageReflection::MutableRaw(Message* message, - const FieldDescriptor* field) const { +Type* Reflection::MutableRaw(Message* message, + const FieldDescriptor* field) const { return GetPointerAtOffset(message, schema_.GetFieldOffset(field)); } - -inline const uint32* GeneratedMessageReflection::GetHasBits( - const Message& message) const { +const uint32* Reflection::GetHasBits(const Message& message) const { GOOGLE_DCHECK(schema_.HasHasbits()); return &GetConstRefAtOffset(message, schema_.HasBitsOffset()); } -inline uint32* GeneratedMessageReflection::MutableHasBits( - Message* message) const { +uint32* Reflection::MutableHasBits(Message* message) const { GOOGLE_DCHECK(schema_.HasHasbits()); return GetPointerAtOffset(message, schema_.HasBitsOffset()); } -inline uint32 GeneratedMessageReflection::GetOneofCase( - const Message& message, const OneofDescriptor* oneof_descriptor) const { +uint32 Reflection::GetOneofCase(const Message& message, + const OneofDescriptor* oneof_descriptor) const { + GOOGLE_DCHECK(!oneof_descriptor->is_synthetic()); return GetConstRefAtOffset( message, schema_.GetOneofCaseOffset(oneof_descriptor)); } -inline uint32* GeneratedMessageReflection::MutableOneofCase( +uint32* Reflection::MutableOneofCase( Message* message, const OneofDescriptor* oneof_descriptor) const { + GOOGLE_DCHECK(!oneof_descriptor->is_synthetic()); return GetPointerAtOffset( message, schema_.GetOneofCaseOffset(oneof_descriptor)); } -inline const ExtensionSet& GeneratedMessageReflection::GetExtensionSet( - const Message& message) const { +const ExtensionSet& Reflection::GetExtensionSet(const Message& message) const { return GetConstRefAtOffset(message, schema_.GetExtensionSetOffset()); } -inline ExtensionSet* GeneratedMessageReflection::MutableExtensionSet( - Message* message) const { +ExtensionSet* Reflection::MutableExtensionSet(Message* message) const { return GetPointerAtOffset(message, schema_.GetExtensionSetOffset()); } -inline Arena* GeneratedMessageReflection::GetArena(Message* message) const { - return GetInternalMetadataWithArena(*message).arena(); +Arena* Reflection::GetArena(Message* message) const { + return GetInternalMetadata(*message).arena(); } -inline const InternalMetadataWithArena& -GeneratedMessageReflection::GetInternalMetadataWithArena( +const InternalMetadata& Reflection::GetInternalMetadata( const Message& message) const { - return GetConstRefAtOffset( - message, schema_.GetMetadataOffset()); + return GetConstRefAtOffset(message, + schema_.GetMetadataOffset()); } -inline InternalMetadataWithArena* -GeneratedMessageReflection::MutableInternalMetadataWithArena( - Message* message) const { - return GetPointerAtOffset( - message, schema_.GetMetadataOffset()); -} - -template -inline const Type& GeneratedMessageReflection::DefaultRaw( - const FieldDescriptor* field) const { - return *reinterpret_cast(schema_.GetFieldDefault(field)); +InternalMetadata* Reflection::MutableInternalMetadata(Message* message) const { + return GetPointerAtOffset(message, + schema_.GetMetadataOffset()); } // Simple accessors for manipulating has_bits_. -inline bool GeneratedMessageReflection::HasBit( - const Message& message, const FieldDescriptor* field) const { +bool Reflection::HasBit(const Message& message, + const FieldDescriptor* field) const { GOOGLE_DCHECK(!field->options().weak()); - if (schema_.HasHasbits()) { + if (schema_.HasBitIndex(field) != static_cast(-1)) { return IsIndexInHasBitSet(GetHasBits(message), schema_.HasBitIndex(field)); } + // Intentionally check here because HasBitIndex(field) != -1 means valid. + CheckInvalidAccess(schema_, field); + // proto3: no has-bits. All fields present except messages, which are - // present only if their message-field pointer is non-NULL. + // present only if their message-field pointer is non-null. if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { return !schema_.IsDefaultInstance(message) && - GetRaw(message, field) != NULL; + GetRaw(message, field) != nullptr; } else { // Non-message field (and non-oneof, since that was handled in HasField() // before calling us), and singular (again, checked in HasField). So, this // field must be a scalar. // Scalar primitive (numeric or string/bytes) fields are present if - // their value is non-zero (numeric) or non-empty (string/bytes). N.B.: + // their value is non-zero (numeric) or non-empty (string/bytes). N.B.: // we must use this definition here, rather than the "scalar fields // always present" in the proto3 docs, because MergeFrom() semantics // require presence as "present on wire", and reflection-based merge @@ -2004,30 +2063,25 @@ inline bool GeneratedMessageReflection::HasBit( } } -inline void GeneratedMessageReflection::SetBit( - Message* message, const FieldDescriptor* field) const { +void Reflection::SetBit(Message* message, const FieldDescriptor* field) const { GOOGLE_DCHECK(!field->options().weak()); - if (!schema_.HasHasbits()) { - return; - } const uint32 index = schema_.HasBitIndex(field); + if (index == static_cast(-1)) return; MutableHasBits(message)[index / 32] |= (static_cast(1) << (index % 32)); } -inline void GeneratedMessageReflection::ClearBit( - Message* message, const FieldDescriptor* field) const { +void Reflection::ClearBit(Message* message, + const FieldDescriptor* field) const { GOOGLE_DCHECK(!field->options().weak()); - if (!schema_.HasHasbits()) { - return; - } const uint32 index = schema_.HasBitIndex(field); + if (index == static_cast(-1)) return; MutableHasBits(message)[index / 32] &= ~(static_cast(1) << (index % 32)); } -inline void GeneratedMessageReflection::SwapBit( - Message* message1, Message* message2, const FieldDescriptor* field) const { +void Reflection::SwapBit(Message* message1, Message* message2, + const FieldDescriptor* field) const { GOOGLE_DCHECK(!field->options().weak()); if (!schema_.HasHasbits()) { return; @@ -2045,46 +2099,56 @@ inline void GeneratedMessageReflection::SwapBit( } } -inline bool GeneratedMessageReflection::HasOneof( - const Message& message, const OneofDescriptor* oneof_descriptor) const { +bool Reflection::HasOneof(const Message& message, + const OneofDescriptor* oneof_descriptor) const { + if (oneof_descriptor->is_synthetic()) { + return HasField(message, oneof_descriptor->field(0)); + } return (GetOneofCase(message, oneof_descriptor) > 0); } -inline bool GeneratedMessageReflection::HasOneofField( - const Message& message, const FieldDescriptor* field) const { - return (GetOneofCase(message, field->containing_oneof()) == field->number()); +bool Reflection::HasOneofField(const Message& message, + const FieldDescriptor* field) const { + return (GetOneofCase(message, field->containing_oneof()) == + static_cast(field->number())); } -inline void GeneratedMessageReflection::SetOneofCase( - Message* message, const FieldDescriptor* field) const { +void Reflection::SetOneofCase(Message* message, + const FieldDescriptor* field) const { *MutableOneofCase(message, field->containing_oneof()) = field->number(); } -inline void GeneratedMessageReflection::ClearOneofField( - Message* message, const FieldDescriptor* field) const { +void Reflection::ClearOneofField(Message* message, + const FieldDescriptor* field) const { if (HasOneofField(*message, field)) { ClearOneof(message, field->containing_oneof()); } } -inline void GeneratedMessageReflection::ClearOneof( - Message* message, const OneofDescriptor* oneof_descriptor) const { +void Reflection::ClearOneof(Message* message, + const OneofDescriptor* oneof_descriptor) const { + if (oneof_descriptor->is_synthetic()) { + ClearField(message, oneof_descriptor->field(0)); + return; + } // TODO(jieluo): Consider to cache the unused object instead of deleting // it. It will be much faster if an application switches a lot from // a few oneof fields. Time/space tradeoff uint32 oneof_case = GetOneofCase(*message, oneof_descriptor); if (oneof_case > 0) { const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case); - if (GetArena(message) == NULL) { + if (GetArena(message) == nullptr) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_STRING: { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { - const string* default_ptr = - &DefaultRaw(field).Get(); - MutableField(message, field)-> - Destroy(default_ptr, GetArena(message)); + // Oneof string fields are never set as a default instance. + // We just need to pass some arbitrary default string to make it + // work. This allows us to not have the real default accessible + // from reflection. + MutableField(message, field) + ->Destroy(nullptr, GetArena(message)); break; } } @@ -2103,83 +2167,120 @@ inline void GeneratedMessageReflection::ClearOneof( } } +#define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE) \ + template <> \ + const RepeatedField& Reflection::GetRepeatedFieldInternal( \ + const Message& message, const FieldDescriptor* field) const { \ + return *static_cast*>(MutableRawRepeatedField( \ + const_cast(&message), field, CPPTYPE, CTYPE, NULL)); \ + } \ + \ + template <> \ + RepeatedField* Reflection::MutableRepeatedFieldInternal( \ + Message * message, const FieldDescriptor* field) const { \ + return static_cast*>( \ + MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, NULL)); \ + } + +HANDLE_TYPE(int32, FieldDescriptor::CPPTYPE_INT32, -1); +HANDLE_TYPE(int64, FieldDescriptor::CPPTYPE_INT64, -1); +HANDLE_TYPE(uint32, FieldDescriptor::CPPTYPE_UINT32, -1); +HANDLE_TYPE(uint64, FieldDescriptor::CPPTYPE_UINT64, -1); +HANDLE_TYPE(float, FieldDescriptor::CPPTYPE_FLOAT, -1); +HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1); +HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1); + + +#undef HANDLE_TYPE + +void* Reflection::MutableRawRepeatedString(Message* message, + const FieldDescriptor* field, + bool is_string) const { + return MutableRawRepeatedField(message, field, + FieldDescriptor::CPPTYPE_STRING, + FieldOptions::STRING, NULL); +} + // Template implementations of basic accessors. Inline because each // template instance is only called from one location. These are // used for all types except messages. template -inline const Type& GeneratedMessageReflection::GetField( - const Message& message, const FieldDescriptor* field) const { +const Type& Reflection::GetField(const Message& message, + const FieldDescriptor* field) const { return GetRaw(message, field); } template -inline void GeneratedMessageReflection::SetField( - Message* message, const FieldDescriptor* field, const Type& value) const { - if (field->containing_oneof() && !HasOneofField(*message, field)) { +void Reflection::SetField(Message* message, const FieldDescriptor* field, + const Type& value) const { + bool real_oneof = schema_.InRealOneof(field); + if (real_oneof && !HasOneofField(*message, field)) { ClearOneof(message, field->containing_oneof()); } *MutableRaw(message, field) = value; - field->containing_oneof() ? - SetOneofCase(message, field) : SetBit(message, field); + real_oneof ? SetOneofCase(message, field) : SetBit(message, field); } template -inline Type* GeneratedMessageReflection::MutableField( - Message* message, const FieldDescriptor* field) const { - field->containing_oneof() ? - SetOneofCase(message, field) : SetBit(message, field); +Type* Reflection::MutableField(Message* message, + const FieldDescriptor* field) const { + schema_.InRealOneof(field) ? SetOneofCase(message, field) + : SetBit(message, field); return MutableRaw(message, field); } template -inline const Type& GeneratedMessageReflection::GetRepeatedField( - const Message& message, const FieldDescriptor* field, int index) const { +const Type& Reflection::GetRepeatedField(const Message& message, + const FieldDescriptor* field, + int index) const { return GetRaw >(message, field).Get(index); } template -inline const Type& GeneratedMessageReflection::GetRepeatedPtrField( - const Message& message, const FieldDescriptor* field, int index) const { +const Type& Reflection::GetRepeatedPtrField(const Message& message, + const FieldDescriptor* field, + int index) const { return GetRaw >(message, field).Get(index); } template -inline void GeneratedMessageReflection::SetRepeatedField( - Message* message, const FieldDescriptor* field, - int index, Type value) const { +void Reflection::SetRepeatedField(Message* message, + const FieldDescriptor* field, int index, + Type value) const { MutableRaw >(message, field)->Set(index, value); } template -inline Type* GeneratedMessageReflection::MutableRepeatedField( - Message* message, const FieldDescriptor* field, int index) const { +Type* Reflection::MutableRepeatedField(Message* message, + const FieldDescriptor* field, + int index) const { RepeatedPtrField* repeated = - MutableRaw >(message, field); + MutableRaw >(message, field); return repeated->Mutable(index); } template -inline void GeneratedMessageReflection::AddField( - Message* message, const FieldDescriptor* field, const Type& value) const { +void Reflection::AddField(Message* message, const FieldDescriptor* field, + const Type& value) const { MutableRaw >(message, field)->Add(value); } template -inline Type* GeneratedMessageReflection::AddField( - Message* message, const FieldDescriptor* field) const { +Type* Reflection::AddField(Message* message, + const FieldDescriptor* field) const { RepeatedPtrField* repeated = - MutableRaw >(message, field); + MutableRaw >(message, field); return repeated->Add(); } -MessageFactory* GeneratedMessageReflection::GetMessageFactory() const { +MessageFactory* Reflection::GetMessageFactory() const { return message_factory_; } -void* GeneratedMessageReflection::RepeatedFieldData( - Message* message, const FieldDescriptor* field, - FieldDescriptor::CppType cpp_type, - const Descriptor* message_type) const { +void* Reflection::RepeatedFieldData(Message* message, + const FieldDescriptor* field, + FieldDescriptor::CppType cpp_type, + const Descriptor* message_type) const { GOOGLE_CHECK(field->is_repeated()); GOOGLE_CHECK(field->cpp_type() == cpp_type || (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM && @@ -2187,7 +2288,7 @@ void* GeneratedMessageReflection::RepeatedFieldData( << "The type parameter T in RepeatedFieldRef API doesn't match " << "the actual field type (for enums T should be the generated enum " << "type or int32)."; - if (message_type != NULL) { + if (message_type != nullptr) { GOOGLE_CHECK_EQ(message_type, field->message_type()); } if (field->is_extension()) { @@ -2198,14 +2299,20 @@ void* GeneratedMessageReflection::RepeatedFieldData( } } -MapFieldBase* GeneratedMessageReflection::MapData( - Message* message, const FieldDescriptor* field) const { - USAGE_CHECK(IsMapFieldInApi(field), - "GetMapData", +MapFieldBase* Reflection::MutableMapData(Message* message, + const FieldDescriptor* field) const { + USAGE_CHECK(IsMapFieldInApi(field), "GetMapData", "Field is not a map field."); return MutableRaw(message, field); } +const MapFieldBase* Reflection::GetMapData(const Message& message, + const FieldDescriptor* field) const { + USAGE_CHECK(IsMapFieldInApi(field), "GetMapData", + "Field is not a map field."); + return &(GetRaw(message, field)); +} + namespace { // Helper function to transform migration schema into reflection schema. @@ -2227,13 +2334,14 @@ ReflectionSchema MigrationToReflectionSchema( return result; } -template +} // namespace + class AssignDescriptorsHelper { public: AssignDescriptorsHelper(MessageFactory* factory, Metadata* file_level_metadata, const EnumDescriptor** file_level_enum_descriptors, - const Schema* schemas, + const MigrationSchema* schemas, const Message* const* default_instance_data, const uint32* offsets) : factory_(factory), @@ -2250,17 +2358,15 @@ class AssignDescriptorsHelper { file_level_metadata_->descriptor = descriptor; - if (!descriptor->options().map_entry()) { - // Only set reflection for non map types. - file_level_metadata_->reflection = new GeneratedMessageReflection( - descriptor, MigrationToReflectionSchema(default_instance_data_, - offsets_, *schemas_), - ::google::protobuf::DescriptorPool::generated_pool(), factory_); - for (int i = 0; i < descriptor->enum_type_count(); i++) { - AssignEnumDescriptor(descriptor->enum_type(i)); - } - schemas_++; + file_level_metadata_->reflection = + new Reflection(descriptor, + MigrationToReflectionSchema(default_instance_data_, + offsets_, *schemas_), + DescriptorPool::internal_generated_pool(), factory_); + for (int i = 0; i < descriptor->enum_type_count(); i++) { + AssignEnumDescriptor(descriptor->enum_type(i)); } + schemas_++; default_instance_data_++; file_level_metadata_++; } @@ -2276,65 +2382,85 @@ class AssignDescriptorsHelper { MessageFactory* factory_; Metadata* file_level_metadata_; const EnumDescriptor** file_level_enum_descriptors_; - const Schema* schemas_; - const Message* const * default_instance_data_; + const MigrationSchema* schemas_; + const Message* const* default_instance_data_; const uint32* offsets_; }; +namespace { + // We have the routines that assign descriptors and build reflection // automatically delete the allocated reflection. MetadataOwner owns // all the allocated reflection instances. struct MetadataOwner { + ~MetadataOwner() { + for (auto range : metadata_arrays_) { + for (const Metadata* m = range.first; m < range.second; m++) { + delete m->reflection; + } + } + } + void AddArray(const Metadata* begin, const Metadata* end) { - MutexLock lock(&mu_); + mu_.Lock(); metadata_arrays_.push_back(std::make_pair(begin, end)); + mu_.Unlock(); } static MetadataOwner* Instance() { - static MetadataOwner* res = new MetadataOwner; + static MetadataOwner* res = OnShutdownDelete(new MetadataOwner); return res; } private: - // Use the constructor to register the shutdown code. Because c++ makes sure - // this called only once. - MetadataOwner() { OnShutdown(&DeleteMetadata); } - ~MetadataOwner() { - for (int i = 0; i < metadata_arrays_.size(); i++) { - for (const Metadata* m = metadata_arrays_[i].first; - m < metadata_arrays_[i].second; m++) { - delete m->reflection; - } - } - } + MetadataOwner() = default; // private because singleton - static void DeleteMetadata() { - delete Instance(); - } - - Mutex mu_; + WrappedMutex mu_; std::vector > metadata_arrays_; }; -} // namespace +void AddDescriptors(const DescriptorTable* table); + +void AssignDescriptorsImpl(const DescriptorTable* table, bool eager) { + // Ensure the file descriptor is added to the pool. + { + // This only happens once per proto file. So a global mutex to serialize + // calls to AddDescriptors. + static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED}; + mu.Lock(); + AddDescriptors(table); + mu.Unlock(); + } + if (eager) { + // Normally we do not want to eagerly build descriptors of our deps. + // However if this proto is optimized for code size (ie using reflection) + // and it has a message extending a custom option of a descriptor with that + // message being optimized for code size as well. Building the descriptors + // in this file requires parsing the serialized file descriptor, which now + // requires parsing the message extension, which potentially requires + // building the descriptor of the message extending one of the options. + // However we are already updating descriptor pool under a lock. To prevent + // this the compiler statically looks for this case and we just make sure we + // first build the descriptors of all our dependencies, preventing the + // deadlock. + int num_deps = table->num_deps; + for (int i = 0; i < num_deps; i++) { + // In case of weak fields deps[i] could be null. + if (table->deps[i]) AssignDescriptors(table->deps[i], true); + } + } -void AssignDescriptors( - const string& filename, const MigrationSchema* schemas, - const Message* const* default_instances_, const uint32* offsets, - MessageFactory* factory, - // update the following descriptor arrays. - Metadata* file_level_metadata, - const EnumDescriptor** file_level_enum_descriptors, - const ServiceDescriptor** file_level_service_descriptors) { - const ::google::protobuf::FileDescriptor* file = - ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(filename); - GOOGLE_CHECK(file != NULL); + // Fill the arrays with pointers to descriptors and reflection classes. + const FileDescriptor* file = + DescriptorPool::internal_generated_pool()->FindFileByName( + table->filename); + GOOGLE_CHECK(file != nullptr); - if (!factory) factory = MessageFactory::generated_factory(); + MessageFactory* factory = MessageFactory::generated_factory(); - AssignDescriptorsHelper helper(factory, file_level_metadata, - file_level_enum_descriptors, schemas, - default_instances_, offsets); + AssignDescriptorsHelper helper( + factory, table->file_level_metadata, table->file_level_enum_descriptors, + table->schemas, table->default_instances, table->offsets); for (int i = 0; i < file->message_type_count(); i++) { helper.AssignMessageDescriptor(file->message_type(i)); @@ -2345,43 +2471,84 @@ void AssignDescriptors( } if (file->options().cc_generic_services()) { for (int i = 0; i < file->service_count(); i++) { - file_level_service_descriptors[i] = file->service(i); + table->file_level_service_descriptors[i] = file->service(i); } } - MetadataOwner::Instance()->AddArray( - file_level_metadata, helper.GetCurrentMetadataPtr()); + MetadataOwner::Instance()->AddArray(table->file_level_metadata, + helper.GetCurrentMetadataPtr()); +} + +void AddDescriptorsImpl(const DescriptorTable* table) { + // Reflection refers to the default fields so make sure they are initialized. + internal::InitProtobufDefaults(); + + // Ensure all dependent descriptors are registered to the generated descriptor + // pool and message factory. + int num_deps = table->num_deps; + for (int i = 0; i < num_deps; i++) { + // In case of weak fields deps[i] could be null. + if (table->deps[i]) AddDescriptors(table->deps[i]); + } + + // Register the descriptor of this file. + DescriptorPool::InternalAddGeneratedFile(table->descriptor, table->size); + MessageFactory::InternalRegisterGeneratedFile(table); } +void AddDescriptors(const DescriptorTable* table) { + // AddDescriptors is not thread safe. Callers need to ensure calls are + // properly serialized. This function is only called pre-main by global + // descriptors and we can assume single threaded access or it's called + // by AssignDescriptorImpl which uses a mutex to sequence calls. + if (table->is_initialized) return; + table->is_initialized = true; + AddDescriptorsImpl(table); +} + +} // namespace + +// Separate function because it needs to be a friend of +// Reflection void RegisterAllTypesInternal(const Metadata* file_level_metadata, int size) { for (int i = 0; i < size; i++) { - const GeneratedMessageReflection* reflection = - static_cast( - file_level_metadata[i].reflection); - if (reflection) { - // It's not a map type - ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( - file_level_metadata[i].descriptor, - reflection->schema_.default_instance_); - } + const Reflection* reflection = file_level_metadata[i].reflection; + MessageFactory::InternalRegisterGeneratedMessage( + file_level_metadata[i].descriptor, + reflection->schema_.default_instance_); } } -void RegisterAllTypes(const Metadata* file_level_metadata, int size) { - RegisterAllTypesInternal(file_level_metadata, size); +namespace internal { + +void AssignDescriptors(const DescriptorTable* table, bool eager) { + if (!eager) eager = table->is_eager; + call_once(*table->once, AssignDescriptorsImpl, table, eager); +} + +AddDescriptorsRunner::AddDescriptorsRunner(const DescriptorTable* table) { + AddDescriptors(table); +} + +void RegisterFileLevelMetadata(const DescriptorTable* table) { + AssignDescriptors(table); + RegisterAllTypesInternal(table->file_level_metadata, table->num_messages); } void UnknownFieldSetSerializer(const uint8* base, uint32 offset, uint32 tag, uint32 has_offset, - ::google::protobuf::io::CodedOutputStream* output) { + io::CodedOutputStream* output) { const void* ptr = base + offset; - const InternalMetadataWithArena* metadata = - static_cast(ptr); + const InternalMetadata* metadata = static_cast(ptr); if (metadata->have_unknown_fields()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - metadata->unknown_fields(), output); + internal::WireFormat::SerializeUnknownFields( + metadata->unknown_fields( + UnknownFieldSet::default_instance), + output); } } } // namespace internal } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h index f6ce16a7a7128..5916cb7b5dba4 100644 --- a/src/google/protobuf/generated_message_reflection.h +++ b/src/google/protobuf/generated_message_reflection.h @@ -42,46 +42,36 @@ #include #include #include -// TODO(jasonh): Remove this once the compiler change to directly include this -// is released to components. +#include #include -#include -#include -#include +#include +#include #include -namespace google { -namespace upb { -namespace google_opensource { -class GMR_Handlers; -} // namespace google_opensource -} // namespace upb +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif +namespace google { namespace protobuf { -class DescriptorPool; class MapKey; class MapValueRef; +class MessageLayoutInspector; +class Message; +struct Metadata; } // namespace protobuf +} // namespace google - -namespace protobuf { -namespace flat { -class MetadataBuilder; -} // namespace flat -} // namespace protobuf - - +namespace google { namespace protobuf { namespace internal { class DefaultEmptyOneof; - -// Defined in this file. -class GeneratedMessageReflection; - // Defined in other files. -class ExtensionSet; // extension_set.h -class WeakFieldMap; // weak_field_map.h +class ExtensionSet; // extension_set.h +class WeakFieldMap; // weak_field_map.h // This struct describes the internal layout of the message, hence this is // used to act on the message reflectively. @@ -89,17 +79,17 @@ class WeakFieldMap; // weak_field_map.h // used to obtain pointers to default instances of embedded // messages, which GetMessage() will return if the particular // sub-message has not been initialized yet. (Thus, all -// embedded message fields *must* have non-NULL pointers +// embedded message fields *must* have non-null pointers // in the default instance.) // offsets: An array of ints giving the byte offsets. // For each oneof or weak field, the offset is relative to the // default_instance. These can be computed at compile time // using the -// GOOGLE_PROTOBUF_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET() +// PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET() // macro. For each none oneof field, the offset is related to // the start of the message object. These can be computed at // compile time using the -// GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET() macro. +// PROTO2_GENERATED_MESSAGE_FIELD_OFFSET() macro. // Besides offsets for all fields, this array also contains // offsets for oneof unions. The offset of the i-th oneof union // is offsets[descriptor->field_count() + i]. @@ -131,20 +121,25 @@ struct ReflectionSchema { // Size of a google::protobuf::Message object of this type. uint32 GetObjectSize() const { return static_cast(object_size_); } + bool InRealOneof(const FieldDescriptor* field) const { + return field->containing_oneof() && + !field->containing_oneof()->is_synthetic(); + } + // Offset of a non-oneof field. Getting a field offset is slightly more // efficient when we know statically that it is not a oneof field. uint32 GetFieldOffsetNonOneof(const FieldDescriptor* field) const { - GOOGLE_DCHECK(!field->containing_oneof()); - return offsets_[field->index()]; + GOOGLE_DCHECK(!InRealOneof(field)); + return OffsetValue(offsets_[field->index()], field->type()); } // Offset of any field. uint32 GetFieldOffset(const FieldDescriptor* field) const { - if (field->containing_oneof()) { + if (InRealOneof(field)) { size_t offset = static_cast(field->containing_type()->field_count() + - field->containing_oneof()->index()); - return offsets_[offset]; + field->containing_oneof()->index()); + return OffsetValue(offsets_[offset], field->type()); } else { return GetFieldOffsetNonOneof(field); } @@ -152,14 +147,15 @@ struct ReflectionSchema { uint32 GetOneofCaseOffset(const OneofDescriptor* oneof_descriptor) const { return static_cast(oneof_case_offset_) + - static_cast( - static_cast(oneof_descriptor->index()) * sizeof(uint32)); + static_cast(static_cast(oneof_descriptor->index()) * + sizeof(uint32)); } bool HasHasbits() const { return has_bits_offset_ != -1; } // Bit index within the bit array of hasbits. Bit order is low-to-high. uint32 HasBitIndex(const FieldDescriptor* field) const { + if (has_bits_offset_ == -1) return static_cast(-1); GOOGLE_DCHECK(HasHasbits()); return has_bit_indices_[field->index()]; } @@ -197,9 +193,26 @@ struct ReflectionSchema { // Returns a pointer to the default value for this field. The size and type // of the underlying data depends on the field's type. - const void *GetFieldDefault(const FieldDescriptor* field) const { + const void* GetFieldDefault(const FieldDescriptor* field) const { return reinterpret_cast(default_instance_) + - offsets_[field->index()]; + OffsetValue(offsets_[field->index()], field->type()); + } + + // Returns true if the field's accessor is called by any external code (aka, + // non proto library code). + bool IsFieldUsed(const FieldDescriptor* field) const { + (void)field; + return true; + } + + bool IsFieldStripped(const FieldDescriptor* field) const { + (void)field; + return false; + } + + bool IsMessageStripped(const Descriptor* descriptor) const { + (void)descriptor; + return false; } @@ -210,7 +223,7 @@ struct ReflectionSchema { // them, ie. // // ReflectionSchema schema = {a, b, c, d, e, ...}; - // private: + // private: const Message* default_instance_; const uint32* offsets_; const uint32* has_bit_indices_; @@ -220,6 +233,12 @@ struct ReflectionSchema { int oneof_case_offset_; int object_size_; int weak_field_map_offset_; + + // We tag offset values to provide additional data about fields (such as + // "unused"). + static uint32 OffsetValue(uint32 v, FieldDescriptor::Type /* type */) { + return v & 0x7FFFFFFFu; + } }; // Structs that the code generator emits directly to describe a message. @@ -234,496 +253,56 @@ struct MigrationSchema { int object_size; }; -// THIS CLASS IS NOT INTENDED FOR DIRECT USE. It is intended for use -// by generated code. This class is just a big hack that reduces code -// size. -// -// A GeneratedMessageReflection is an implementation of Reflection -// which expects all fields to be backed by simple variables located in -// memory. The locations are given using a base pointer and a set of -// offsets. -// -// It is required that the user represents fields of each type in a standard -// way, so that GeneratedMessageReflection can cast the void* pointer to -// the appropriate type. For primitive fields and string fields, each field -// should be represented using the obvious C++ primitive type. Enums and -// Messages are different: -// - Singular Message fields are stored as a pointer to a Message. These -// should start out NULL, except for in the default instance where they -// should start out pointing to other default instances. -// - Enum fields are stored as an int. This int must always contain -// a valid value, such that EnumDescriptor::FindValueByNumber() would -// not return NULL. -// - Repeated fields are stored as RepeatedFields or RepeatedPtrFields -// of whatever type the individual field would be. Strings and -// Messages use RepeatedPtrFields while everything else uses -// RepeatedFields. -class LIBPROTOBUF_EXPORT GeneratedMessageReflection PROTOBUF_FINAL : public Reflection { - public: - // Constructs a GeneratedMessageReflection. - // Parameters: - // descriptor: The descriptor for the message type being implemented. - // schema: The description of the internal guts of the message. - // pool: DescriptorPool to search for extension definitions. Only - // used by FindKnownExtensionByName() and - // FindKnownExtensionByNumber(). - // factory: MessageFactory to use to construct extension messages. - GeneratedMessageReflection(const Descriptor* descriptor, - const ReflectionSchema& schema, - const DescriptorPool* pool, - MessageFactory* factory); - - ~GeneratedMessageReflection(); - - // implements Reflection ------------------------------------------- - - const UnknownFieldSet& GetUnknownFields(const Message& message) const; - UnknownFieldSet* MutableUnknownFields(Message* message) const; - - size_t SpaceUsedLong(const Message& message) const; - - bool HasField(const Message& message, const FieldDescriptor* field) const; - int FieldSize(const Message& message, const FieldDescriptor* field) const; - void ClearField(Message* message, const FieldDescriptor* field) const; - bool HasOneof(const Message& message, - const OneofDescriptor* oneof_descriptor) const; - void ClearOneof(Message* message, const OneofDescriptor* field) const; - void RemoveLast(Message* message, const FieldDescriptor* field) const; - Message* ReleaseLast(Message* message, const FieldDescriptor* field) const; - void Swap(Message* message1, Message* message2) const; - void SwapFields(Message* message1, Message* message2, - const std::vector& fields) const; - void SwapElements(Message* message, const FieldDescriptor* field, - int index1, int index2) const; - void ListFields(const Message& message, - std::vector* output) const; - - int32 GetInt32 (const Message& message, - const FieldDescriptor* field) const; - int64 GetInt64 (const Message& message, - const FieldDescriptor* field) const; - uint32 GetUInt32(const Message& message, - const FieldDescriptor* field) const; - uint64 GetUInt64(const Message& message, - const FieldDescriptor* field) const; - float GetFloat (const Message& message, - const FieldDescriptor* field) const; - double GetDouble(const Message& message, - const FieldDescriptor* field) const; - bool GetBool (const Message& message, - const FieldDescriptor* field) const; - string GetString(const Message& message, - const FieldDescriptor* field) const; - const string& GetStringReference(const Message& message, - const FieldDescriptor* field, - string* scratch) const; - const EnumValueDescriptor* GetEnum(const Message& message, - const FieldDescriptor* field) const; - int GetEnumValue(const Message& message, - const FieldDescriptor* field) const; - const Message& GetMessage(const Message& message, - const FieldDescriptor* field, - MessageFactory* factory = NULL) const; - - const FieldDescriptor* GetOneofFieldDescriptor( - const Message& message, - const OneofDescriptor* oneof_descriptor) const; - - private: - bool ContainsMapKey(const Message& message, - const FieldDescriptor* field, - const MapKey& key) const; - bool InsertOrLookupMapValue(Message* message, - const FieldDescriptor* field, - const MapKey& key, - MapValueRef* val) const; - bool DeleteMapValue(Message* message, - const FieldDescriptor* field, - const MapKey& key) const; - MapIterator MapBegin( - Message* message, - const FieldDescriptor* field) const; - MapIterator MapEnd( - Message* message, - const FieldDescriptor* field) const; - int MapSize(const Message& message, const FieldDescriptor* field) const; - - public: - void SetInt32 (Message* message, - const FieldDescriptor* field, int32 value) const; - void SetInt64 (Message* message, - const FieldDescriptor* field, int64 value) const; - void SetUInt32(Message* message, - const FieldDescriptor* field, uint32 value) const; - void SetUInt64(Message* message, - const FieldDescriptor* field, uint64 value) const; - void SetFloat (Message* message, - const FieldDescriptor* field, float value) const; - void SetDouble(Message* message, - const FieldDescriptor* field, double value) const; - void SetBool (Message* message, - const FieldDescriptor* field, bool value) const; - void SetString(Message* message, - const FieldDescriptor* field, - const string& value) const; - void SetEnum (Message* message, const FieldDescriptor* field, - const EnumValueDescriptor* value) const; - void SetEnumValue(Message* message, const FieldDescriptor* field, - int value) const; - Message* MutableMessage(Message* message, const FieldDescriptor* field, - MessageFactory* factory = NULL) const; - void SetAllocatedMessage(Message* message, - Message* sub_message, - const FieldDescriptor* field) const; - Message* ReleaseMessage(Message* message, const FieldDescriptor* field, - MessageFactory* factory = NULL) const; - - int32 GetRepeatedInt32 (const Message& message, - const FieldDescriptor* field, int index) const; - int64 GetRepeatedInt64 (const Message& message, - const FieldDescriptor* field, int index) const; - uint32 GetRepeatedUInt32(const Message& message, - const FieldDescriptor* field, int index) const; - uint64 GetRepeatedUInt64(const Message& message, - const FieldDescriptor* field, int index) const; - float GetRepeatedFloat (const Message& message, - const FieldDescriptor* field, int index) const; - double GetRepeatedDouble(const Message& message, - const FieldDescriptor* field, int index) const; - bool GetRepeatedBool (const Message& message, - const FieldDescriptor* field, int index) const; - string GetRepeatedString(const Message& message, - const FieldDescriptor* field, int index) const; - const string& GetRepeatedStringReference(const Message& message, - const FieldDescriptor* field, - int index, string* scratch) const; - const EnumValueDescriptor* GetRepeatedEnum(const Message& message, - const FieldDescriptor* field, - int index) const; - int GetRepeatedEnumValue(const Message& message, - const FieldDescriptor* field, - int index) const; - const Message& GetRepeatedMessage(const Message& message, - const FieldDescriptor* field, - int index) const; - - // Set the value of a field. - void SetRepeatedInt32 (Message* message, - const FieldDescriptor* field, int index, int32 value) const; - void SetRepeatedInt64 (Message* message, - const FieldDescriptor* field, int index, int64 value) const; - void SetRepeatedUInt32(Message* message, - const FieldDescriptor* field, int index, uint32 value) const; - void SetRepeatedUInt64(Message* message, - const FieldDescriptor* field, int index, uint64 value) const; - void SetRepeatedFloat (Message* message, - const FieldDescriptor* field, int index, float value) const; - void SetRepeatedDouble(Message* message, - const FieldDescriptor* field, int index, double value) const; - void SetRepeatedBool (Message* message, - const FieldDescriptor* field, int index, bool value) const; - void SetRepeatedString(Message* message, - const FieldDescriptor* field, int index, - const string& value) const; - void SetRepeatedEnum(Message* message, const FieldDescriptor* field, - int index, const EnumValueDescriptor* value) const; - void SetRepeatedEnumValue(Message* message, const FieldDescriptor* field, - int index, int value) const; - // Get a mutable pointer to a field with a message type. - Message* MutableRepeatedMessage(Message* message, - const FieldDescriptor* field, - int index) const; - - void AddInt32 (Message* message, - const FieldDescriptor* field, int32 value) const; - void AddInt64 (Message* message, - const FieldDescriptor* field, int64 value) const; - void AddUInt32(Message* message, - const FieldDescriptor* field, uint32 value) const; - void AddUInt64(Message* message, - const FieldDescriptor* field, uint64 value) const; - void AddFloat (Message* message, - const FieldDescriptor* field, float value) const; - void AddDouble(Message* message, - const FieldDescriptor* field, double value) const; - void AddBool (Message* message, - const FieldDescriptor* field, bool value) const; - void AddString(Message* message, - const FieldDescriptor* field, const string& value) const; - void AddEnum(Message* message, - const FieldDescriptor* field, - const EnumValueDescriptor* value) const; - void AddEnumValue(Message* message, - const FieldDescriptor* field, - int value) const; - Message* AddMessage(Message* message, const FieldDescriptor* field, - MessageFactory* factory = NULL) const; - void AddAllocatedMessage( - Message* message, const FieldDescriptor* field, - Message* new_entry) const; - - const FieldDescriptor* FindKnownExtensionByName(const string& name) const; - const FieldDescriptor* FindKnownExtensionByNumber(int number) const; - - bool SupportsUnknownEnumValues() const; - - // This value for arena_offset_ indicates that there is no arena pointer in - // this message (e.g., old generated code). - static const int kNoArenaPointer = -1; - - // This value for unknown_field_offset_ indicates that there is no - // UnknownFieldSet in this message, and that instead, we are using the - // Zero-Overhead Arena Pointer trick. When this is the case, arena_offset_ - // actually indexes to an InternalMetadataWithArena instance, which can return - // either an arena pointer or an UnknownFieldSet or both. It is never the case - // that unknown_field_offset_ == kUnknownFieldSetInMetadata && arena_offset_ - // == kNoArenaPointer. - static const int kUnknownFieldSetInMetadata = -1; - - protected: - void* MutableRawRepeatedField( - Message* message, const FieldDescriptor* field, FieldDescriptor::CppType, - int ctype, const Descriptor* desc) const; - - const void* GetRawRepeatedField( - const Message& message, const FieldDescriptor* field, - FieldDescriptor::CppType, int ctype, - const Descriptor* desc) const; - - virtual MessageFactory* GetMessageFactory() const; - - virtual void* RepeatedFieldData( - Message* message, const FieldDescriptor* field, - FieldDescriptor::CppType cpp_type, - const Descriptor* message_type) const; - - private: - friend class google::protobuf::flat::MetadataBuilder; - friend class upb::google_opensource::GMR_Handlers; - - const Descriptor* const descriptor_; - const ReflectionSchema schema_; - const DescriptorPool* const descriptor_pool_; - MessageFactory* const message_factory_; - - // Last non weak field index. This is an optimization when most weak fields - // are at the end of the containing message. If a message proto doesn't - // contain weak fields, then this field equals descriptor_->field_count(). - int last_non_weak_field_index_; - - template - const T& GetRawNonOneof(const Message& message, - const FieldDescriptor* field) const; - template - T* MutableRawNonOneof(Message* message, const FieldDescriptor* field) const; - - template - const Type& GetRaw(const Message& message, - const FieldDescriptor* field) const; - template - inline Type* MutableRaw(Message* message, - const FieldDescriptor* field) const; - template - inline const Type& DefaultRaw(const FieldDescriptor* field) const; - - inline const uint32* GetHasBits(const Message& message) const; - inline uint32* MutableHasBits(Message* message) const; - inline uint32 GetOneofCase( - const Message& message, - const OneofDescriptor* oneof_descriptor) const; - inline uint32* MutableOneofCase( - Message* message, - const OneofDescriptor* oneof_descriptor) const; - inline const ExtensionSet& GetExtensionSet(const Message& message) const; - inline ExtensionSet* MutableExtensionSet(Message* message) const; - inline Arena* GetArena(Message* message) const; - - inline const InternalMetadataWithArena& GetInternalMetadataWithArena( - const Message& message) const; - - inline InternalMetadataWithArena* - MutableInternalMetadataWithArena(Message* message) const; - - inline bool HasBit(const Message& message, - const FieldDescriptor* field) const; - inline void SetBit(Message* message, - const FieldDescriptor* field) const; - inline void ClearBit(Message* message, - const FieldDescriptor* field) const; - inline void SwapBit(Message* message1, - Message* message2, - const FieldDescriptor* field) const; - - // This function only swaps the field. Should swap corresponding has_bit - // before or after using this function. - void SwapField(Message* message1, - Message* message2, - const FieldDescriptor* field) const; - - void SwapOneofField(Message* message1, - Message* message2, - const OneofDescriptor* oneof_descriptor) const; - - inline bool HasOneofField(const Message& message, - const FieldDescriptor* field) const; - inline void SetOneofCase(Message* message, - const FieldDescriptor* field) const; - inline void ClearOneofField(Message* message, - const FieldDescriptor* field) const; - - template - inline const Type& GetField(const Message& message, - const FieldDescriptor* field) const; - template - inline void SetField(Message* message, - const FieldDescriptor* field, const Type& value) const; - template - inline Type* MutableField(Message* message, - const FieldDescriptor* field) const; - template - inline const Type& GetRepeatedField(const Message& message, - const FieldDescriptor* field, - int index) const; - template - inline const Type& GetRepeatedPtrField(const Message& message, - const FieldDescriptor* field, - int index) const; - template - inline void SetRepeatedField(Message* message, - const FieldDescriptor* field, int index, - Type value) const; - template - inline Type* MutableRepeatedField(Message* message, - const FieldDescriptor* field, - int index) const; - template - inline void AddField(Message* message, - const FieldDescriptor* field, const Type& value) const; - template - inline Type* AddField(Message* message, - const FieldDescriptor* field) const; - - int GetExtensionNumberOrDie(const Descriptor* type) const; - - // Internal versions of EnumValue API perform no checking. Called after checks - // by public methods. - void SetEnumValueInternal(Message* message, - const FieldDescriptor* field, - int value) const; - void SetRepeatedEnumValueInternal(Message* message, - const FieldDescriptor* field, - int index, - int value) const; - void AddEnumValueInternal(Message* message, - const FieldDescriptor* field, - int value) const; - - - Message* UnsafeArenaReleaseMessage(Message* message, - const FieldDescriptor* field, - MessageFactory* factory = NULL) const; - - void UnsafeArenaSetAllocatedMessage(Message* message, - Message* sub_message, - const FieldDescriptor* field) const; - - internal::MapFieldBase* MapData( - Message* message, const FieldDescriptor* field) const; - - friend inline // inline so nobody can call this function. - void - RegisterAllTypesInternal(const Metadata* file_level_metadata, int size); - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratedMessageReflection); +// This struct tries to reduce unnecessary padding. +// The num_xxx might not be close to their respective pointer, but this saves +// padding. +struct PROTOBUF_EXPORT DescriptorTable { + mutable bool is_initialized; + bool is_eager; + int size; // of serialized descriptor + const char* descriptor; + const char* filename; + once_flag* once; + const DescriptorTable* const* deps; + int num_deps; + int num_messages; + const MigrationSchema* schemas; + const Message* const* default_instances; + const uint32* offsets; + // update the following descriptor arrays. + Metadata* file_level_metadata; + const EnumDescriptor** file_level_enum_descriptors; + const ServiceDescriptor** file_level_service_descriptors; }; -// There are some places in proto2 where dynamic_cast would be useful as an -// optimization. For example, take Message::MergeFrom(const Message& other). -// For a given generated message FooMessage, we generate these two methods: -// void MergeFrom(const FooMessage& other); -// void MergeFrom(const Message& other); -// The former method can be implemented directly in terms of FooMessage's -// inline accessors, but the latter method must work with the reflection -// interface. However, if the parameter to the latter method is actually of -// type FooMessage, then we'd like to be able to just call the other method -// as an optimization. So, we use dynamic_cast to check this. -// -// That said, dynamic_cast requires RTTI, which many people like to disable -// for performance and code size reasons. When RTTI is not available, we -// still need to produce correct results. So, in this case we have to fall -// back to using reflection, which is what we would have done anyway if the -// objects were not of the exact same class. -// -// dynamic_cast_if_available() implements this logic. If RTTI is -// enabled, it does a dynamic_cast. If RTTI is disabled, it just returns -// NULL. -// -// If you need to compile without RTTI, simply #define GOOGLE_PROTOBUF_NO_RTTI. -// On MSVC, this should be detected automatically. -template -inline To dynamic_cast_if_available(From from) { -#if defined(GOOGLE_PROTOBUF_NO_RTTI) || (defined(_MSC_VER)&&!defined(_CPPRTTI)) - // Avoid the compiler warning about unused variables. - (void)from; - return NULL; -#else - return dynamic_cast(from); -#endif -} - -// Tries to downcast this message to a generated message type. -// Returns NULL if this class is not an instance of T. -// -// This is like dynamic_cast_if_available, except it works even when -// dynamic_cast is not available by using Reflection. However it only works -// with Message objects. -// -// TODO(haberman): can we remove dynamic_cast_if_available in favor of this? -template -T* DynamicCastToGenerated(const Message* from) { - // Compile-time assert that T is a generated type that has a - // default_instance() accessor, but avoid actually calling it. - const T&(*get_default_instance)() = &T::default_instance; - (void)get_default_instance; - - // Compile-time assert that T is a subclass of google::protobuf::Message. - const Message* unused = static_cast(NULL); - (void)unused; - -#if defined(GOOGLE_PROTOBUF_NO_RTTI) || \ - (defined(_MSC_VER) && !defined(_CPPRTTI)) - bool ok = &T::default_instance() == - from->GetReflection()->GetMessageFactory()->GetPrototype( - from->GetDescriptor()); - return ok ? down_cast(from) : NULL; -#else - return dynamic_cast(from); -#endif -} - -template -T* DynamicCastToGenerated(Message* from) { - const Message* message_const = from; - return const_cast(DynamicCastToGenerated(message_const)); -} - -LIBPROTOBUF_EXPORT void AssignDescriptors( - const string& filename, const MigrationSchema* schemas, - const Message* const* default_instances_, const uint32* offsets, - MessageFactory* factory, - // update the following descriptor arrays. - Metadata* file_level_metadata, - const EnumDescriptor** file_level_enum_descriptors, - const ServiceDescriptor** file_level_service_descriptors); +enum { + // Tag used on offsets for fields that don't have a real offset. + // For example, weak message fields go into the WeakFieldMap and not in an + // actual field. + kInvalidFieldOffsetTag = 0x40000000u, +}; -LIBPROTOBUF_EXPORT void RegisterAllTypes(const Metadata* file_level_metadata, int size); +// AssignDescriptors() pulls the compiled FileDescriptor from the DescriptorPool +// and uses it to populate all of the global variables which store pointers to +// the descriptor objects. It also constructs the reflection objects. It is +// called the first time anyone calls descriptor() or GetReflection() on one of +// the types defined in the file. AssignDescriptors() is thread-safe. +void PROTOBUF_EXPORT AssignDescriptors(const DescriptorTable* table, + bool eager = false); // These cannot be in lite so we put them in the reflection. -LIBPROTOBUF_EXPORT void UnknownFieldSetSerializer(const uint8* base, uint32 offset, uint32 tag, - uint32 has_offset, - ::google::protobuf::io::CodedOutputStream* output); +PROTOBUF_EXPORT void UnknownFieldSetSerializer(const uint8* base, uint32 offset, + uint32 tag, uint32 has_offset, + io::CodedOutputStream* output); + +struct PROTOBUF_EXPORT AddDescriptorsRunner { + explicit AddDescriptorsRunner(const DescriptorTable* table); +}; } // namespace internal } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__ diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc index 242cc4a1b7be3..7234f5f9321bc 100644 --- a/src/google/protobuf/generated_message_reflection_unittest.cc +++ b/src/google/protobuf/generated_message_reflection_unittest.cc @@ -43,18 +43,15 @@ // rather than generated accessors. #include + #include -#ifndef _SHARED_PTR_H -#include -#endif +#include +#include #include #include #include #include - -#include -#include #include #include @@ -64,9 +61,9 @@ namespace protobuf { namespace { // Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes. -const FieldDescriptor* F(const string& name) { +const FieldDescriptor* F(const std::string& name) { const FieldDescriptor* result = - unittest::TestAllTypes::descriptor()->FindFieldByName(name); + unittest::TestAllTypes::descriptor()->FindFieldByName(name); GOOGLE_CHECK(result != NULL); return result; } @@ -75,7 +72,7 @@ TEST(GeneratedMessageReflectionTest, Defaults) { // Check that all default values are set correctly in the initial message. unittest::TestAllTypes message; TestUtil::ReflectionTester reflection_tester( - unittest::TestAllTypes::descriptor()); + unittest::TestAllTypes::descriptor()); reflection_tester.ExpectClearViaReflection(message); @@ -99,7 +96,7 @@ TEST(GeneratedMessageReflectionTest, Accessors) { // values. unittest::TestAllTypes message; TestUtil::ReflectionTester reflection_tester( - unittest::TestAllTypes::descriptor()); + unittest::TestAllTypes::descriptor()); reflection_tester.SetAllFieldsViaReflection(&message); TestUtil::ExpectAllFieldsSet(message); @@ -110,24 +107,26 @@ TEST(GeneratedMessageReflectionTest, Accessors) { } TEST(GeneratedMessageReflectionTest, GetStringReference) { - // Test that GetStringReference() returns the underlying string when it is - // a normal string field. + // Test that GetStringReference() returns the underlying string when it + // is a normal string field. unittest::TestAllTypes message; message.set_optional_string("foo"); message.add_repeated_string("foo"); const Reflection* reflection = message.GetReflection(); - string scratch; + std::string scratch; - EXPECT_EQ(&message.optional_string(), + EXPECT_EQ( + &message.optional_string(), &reflection->GetStringReference(message, F("optional_string"), &scratch)) - << "For simple string fields, GetStringReference() should return a " - "reference to the underlying string."; + << "For simple string fields, GetStringReference() should return a " + "reference to the underlying string."; EXPECT_EQ(&message.repeated_string(0), - &reflection->GetRepeatedStringReference(message, F("repeated_string"), - 0, &scratch)) - << "For simple string fields, GetRepeatedStringReference() should return " - "a reference to the underlying string."; + &reflection->GetRepeatedStringReference( + message, F("repeated_string"), 0, &scratch)) + << "For simple string fields, GetRepeatedStringReference() should " + "return " + "a reference to the underlying string."; } @@ -136,7 +135,7 @@ TEST(GeneratedMessageReflectionTest, DefaultsAfterClear) { // embedded message does NOT return the default instance. unittest::TestAllTypes message; TestUtil::ReflectionTester reflection_tester( - unittest::TestAllTypes::descriptor()); + unittest::TestAllTypes::descriptor()); TestUtil::SetAllFields(&message); message.Clear(); @@ -153,7 +152,6 @@ TEST(GeneratedMessageReflectionTest, DefaultsAfterClear) { &reflection->GetMessage(message, F("optional_import_message"))); } - TEST(GeneratedMessageReflectionTest, Swap) { unittest::TestAllTypes message1; unittest::TestAllTypes message2; @@ -322,7 +320,7 @@ TEST(GeneratedMessageReflectionTest, SwapFieldsOneof) { TEST(GeneratedMessageReflectionTest, RemoveLast) { unittest::TestAllTypes message; TestUtil::ReflectionTester reflection_tester( - unittest::TestAllTypes::descriptor()); + unittest::TestAllTypes::descriptor()); TestUtil::SetAllFields(&message); @@ -334,7 +332,7 @@ TEST(GeneratedMessageReflectionTest, RemoveLast) { TEST(GeneratedMessageReflectionTest, RemoveLastExtensions) { unittest::TestAllExtensions message; TestUtil::ReflectionTester reflection_tester( - unittest::TestAllExtensions::descriptor()); + unittest::TestAllExtensions::descriptor()); TestUtil::SetAllExtensions(&message); @@ -360,7 +358,7 @@ TEST(GeneratedMessageReflectionTest, ReleaseLast) { ASSERT_EQ(2, message.repeated_foreign_message_size()); const protobuf_unittest::ForeignMessage* expected = message.mutable_repeated_foreign_message(1); - google::protobuf::scoped_ptr released(message.GetReflection()->ReleaseLast( + std::unique_ptr released(message.GetReflection()->ReleaseLast( &message, descriptor->FindFieldByName("repeated_foreign_message"))); EXPECT_EQ(expected, released.get()); } @@ -379,21 +377,20 @@ TEST(GeneratedMessageReflectionTest, ReleaseLastExtensions) { // Now test that we actually release the right message. message.Clear(); TestUtil::SetAllExtensions(&message); - ASSERT_EQ(2, message.ExtensionSize( - unittest::repeated_foreign_message_extension)); - const protobuf_unittest::ForeignMessage* expected = message.MutableExtension( - unittest::repeated_foreign_message_extension, 1); - google::protobuf::scoped_ptr released(message.GetReflection()->ReleaseLast( + ASSERT_EQ( + 2, message.ExtensionSize(unittest::repeated_foreign_message_extension)); + const protobuf_unittest::ForeignMessage* expected = + message.MutableExtension(unittest::repeated_foreign_message_extension, 1); + std::unique_ptr released(message.GetReflection()->ReleaseLast( &message, descriptor->file()->FindExtensionByName( "repeated_foreign_message_extension"))); EXPECT_EQ(expected, released.get()); - } TEST(GeneratedMessageReflectionTest, SwapRepeatedElements) { unittest::TestAllTypes message; TestUtil::ReflectionTester reflection_tester( - unittest::TestAllTypes::descriptor()); + unittest::TestAllTypes::descriptor()); TestUtil::SetAllFields(&message); @@ -409,7 +406,7 @@ TEST(GeneratedMessageReflectionTest, SwapRepeatedElements) { TEST(GeneratedMessageReflectionTest, SwapRepeatedElementsExtension) { unittest::TestAllExtensions message; TestUtil::ReflectionTester reflection_tester( - unittest::TestAllExtensions::descriptor()); + unittest::TestAllExtensions::descriptor()); TestUtil::SetAllExtensions(&message); @@ -427,7 +424,7 @@ TEST(GeneratedMessageReflectionTest, Extensions) { // values. unittest::TestAllExtensions message; TestUtil::ReflectionTester reflection_tester( - unittest::TestAllExtensions::descriptor()); + unittest::TestAllExtensions::descriptor()); reflection_tester.SetAllFieldsViaReflection(&message); TestUtil::ExpectAllExtensionsSet(message); @@ -439,14 +436,14 @@ TEST(GeneratedMessageReflectionTest, Extensions) { TEST(GeneratedMessageReflectionTest, FindExtensionTypeByNumber) { const Reflection* reflection = - unittest::TestAllExtensions::default_instance().GetReflection(); + unittest::TestAllExtensions::default_instance().GetReflection(); const FieldDescriptor* extension1 = - unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName( - "optional_int32_extension"); + unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName( + "optional_int32_extension"); const FieldDescriptor* extension2 = - unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName( - "repeated_string_extension"); + unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName( + "repeated_string_extension"); EXPECT_EQ(extension1, reflection->FindKnownExtensionByNumber(extension1->number())); @@ -458,20 +455,21 @@ TEST(GeneratedMessageReflectionTest, FindExtensionTypeByNumber) { // Extensions of TestAllExtensions should not show up as extensions of // other types. - EXPECT_TRUE(unittest::TestAllTypes::default_instance().GetReflection()-> - FindKnownExtensionByNumber(extension1->number()) == NULL); + EXPECT_TRUE(unittest::TestAllTypes::default_instance() + .GetReflection() + ->FindKnownExtensionByNumber(extension1->number()) == NULL); } TEST(GeneratedMessageReflectionTest, FindKnownExtensionByName) { const Reflection* reflection = - unittest::TestAllExtensions::default_instance().GetReflection(); + unittest::TestAllExtensions::default_instance().GetReflection(); const FieldDescriptor* extension1 = - unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName( - "optional_int32_extension"); + unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName( + "optional_int32_extension"); const FieldDescriptor* extension2 = - unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName( - "repeated_string_extension"); + unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName( + "repeated_string_extension"); EXPECT_EQ(extension1, reflection->FindKnownExtensionByName(extension1->full_name())); @@ -483,16 +481,18 @@ TEST(GeneratedMessageReflectionTest, FindKnownExtensionByName) { // Extensions of TestAllExtensions should not show up as extensions of // other types. - EXPECT_TRUE(unittest::TestAllTypes::default_instance().GetReflection()-> - FindKnownExtensionByName(extension1->full_name()) == NULL); + EXPECT_TRUE(unittest::TestAllTypes::default_instance() + .GetReflection() + ->FindKnownExtensionByName(extension1->full_name()) == NULL); } + TEST(GeneratedMessageReflectionTest, SetAllocatedMessageTest) { unittest::TestAllTypes from_message1; unittest::TestAllTypes from_message2; unittest::TestAllTypes to_message; TestUtil::ReflectionTester reflection_tester( - unittest::TestAllTypes::descriptor()); + unittest::TestAllTypes::descriptor()); reflection_tester.SetAllFieldsViaReflection(&from_message1); reflection_tester.SetAllFieldsViaReflection(&from_message2); @@ -523,11 +523,11 @@ TEST(GeneratedMessageReflectionTest, SetAllocatedMessageTest) { TEST(GeneratedMessageReflectionTest, SetAllocatedMessageOnArenaTest) { unittest::TestAllTypes from_message1; unittest::TestAllTypes from_message2; - ::google::protobuf::Arena arena; + Arena arena; unittest::TestAllTypes* to_message = - ::google::protobuf::Arena::CreateMessage(&arena); + Arena::CreateMessage(&arena); TestUtil::ReflectionTester reflection_tester( - unittest::TestAllTypes::descriptor()); + unittest::TestAllTypes::descriptor()); reflection_tester.SetAllFieldsViaReflection(&from_message1); reflection_tester.SetAllFieldsViaReflection(&from_message2); @@ -560,7 +560,7 @@ TEST(GeneratedMessageReflectionTest, SetAllocatedExtensionMessageTest) { unittest::TestAllExtensions from_message2; unittest::TestAllExtensions to_message; TestUtil::ReflectionTester reflection_tester( - unittest::TestAllExtensions::descriptor()); + unittest::TestAllExtensions::descriptor()); reflection_tester.SetAllFieldsViaReflection(&from_message1); reflection_tester.SetAllFieldsViaReflection(&from_message2); @@ -589,13 +589,13 @@ TEST(GeneratedMessageReflectionTest, SetAllocatedExtensionMessageTest) { } TEST(GeneratedMessageReflectionTest, SetAllocatedExtensionMessageOnArenaTest) { - ::google::protobuf::Arena arena; + Arena arena; unittest::TestAllExtensions* to_message = - ::google::protobuf::Arena::CreateMessage(&arena); + Arena::CreateMessage(&arena); unittest::TestAllExtensions from_message1; unittest::TestAllExtensions from_message2; TestUtil::ReflectionTester reflection_tester( - unittest::TestAllExtensions::descriptor()); + unittest::TestAllExtensions::descriptor()); reflection_tester.SetAllFieldsViaReflection(&from_message1); reflection_tester.SetAllFieldsViaReflection(&from_message2); @@ -634,8 +634,8 @@ TEST(GeneratedMessageReflectionTest, AddRepeatedMessage) { unittest::TestAllTypes::NestedMessage::descriptor()->FindFieldByName( "bb"); - Message* nested = reflection->AddMessage( - &message, F("repeated_nested_message")); + Message* nested = + reflection->AddMessage(&message, F("repeated_nested_message")); nested_reflection->SetInt32(nested, nested_bb, 11); EXPECT_EQ(11, message.repeated_nested_message(0).bb()); @@ -669,7 +669,8 @@ TEST(GeneratedMessageReflectionTest, AddAllocatedMessage) { unittest::TestAllTypes::NestedMessage* nested = new unittest::TestAllTypes::NestedMessage(); nested->set_bb(11); - reflection->AddAllocatedMessage(&message, F("repeated_nested_message"), nested); + reflection->AddAllocatedMessage(&message, F("repeated_nested_message"), + nested); EXPECT_EQ(1, message.repeated_nested_message_size()); EXPECT_EQ(11, message.repeated_nested_message(0).bb()); } @@ -690,62 +691,72 @@ TEST(GeneratedMessageReflectionTest, Oneof) { const Reflection* reflection = message.GetReflection(); // Check default values. - EXPECT_EQ(0, reflection->GetInt32( - message, descriptor->FindFieldByName("foo_int"))); - EXPECT_EQ("", reflection->GetString( - message, descriptor->FindFieldByName("foo_string"))); + EXPECT_EQ( + 0, reflection->GetInt32(message, descriptor->FindFieldByName("foo_int"))); EXPECT_EQ("", reflection->GetString( - message, descriptor->FindFieldByName("foo_cord"))); + message, descriptor->FindFieldByName("foo_string"))); + EXPECT_EQ("", reflection->GetString(message, + descriptor->FindFieldByName("foo_cord"))); EXPECT_EQ("", reflection->GetString( - message, descriptor->FindFieldByName("foo_string_piece"))); + message, descriptor->FindFieldByName("foo_string_piece"))); EXPECT_EQ("", reflection->GetString( - message, descriptor->FindFieldByName("foo_bytes"))); - EXPECT_EQ(unittest::TestOneof2::FOO, reflection->GetEnum( - message, descriptor->FindFieldByName("foo_enum"))->number()); + message, descriptor->FindFieldByName("foo_bytes"))); + EXPECT_EQ( + unittest::TestOneof2::FOO, + reflection->GetEnum(message, descriptor->FindFieldByName("foo_enum")) + ->number()); EXPECT_EQ(&unittest::TestOneof2::NestedMessage::default_instance(), &reflection->GetMessage( message, descriptor->FindFieldByName("foo_message"))); EXPECT_EQ(&unittest::TestOneof2::FooGroup::default_instance(), - &reflection->GetMessage( - message, descriptor->FindFieldByName("foogroup"))); + &reflection->GetMessage(message, + descriptor->FindFieldByName("foogroup"))); EXPECT_NE(&unittest::TestOneof2::FooGroup::default_instance(), &reflection->GetMessage( message, descriptor->FindFieldByName("foo_lazy_message"))); - EXPECT_EQ(5, reflection->GetInt32( - message, descriptor->FindFieldByName("bar_int"))); + EXPECT_EQ( + 5, reflection->GetInt32(message, descriptor->FindFieldByName("bar_int"))); EXPECT_EQ("STRING", reflection->GetString( - message, descriptor->FindFieldByName("bar_string"))); + message, descriptor->FindFieldByName("bar_string"))); EXPECT_EQ("CORD", reflection->GetString( - message, descriptor->FindFieldByName("bar_cord"))); - EXPECT_EQ("SPIECE", reflection->GetString( - message, descriptor->FindFieldByName("bar_string_piece"))); + message, descriptor->FindFieldByName("bar_cord"))); + EXPECT_EQ("SPIECE", + reflection->GetString( + message, descriptor->FindFieldByName("bar_string_piece"))); EXPECT_EQ("BYTES", reflection->GetString( - message, descriptor->FindFieldByName("bar_bytes"))); - EXPECT_EQ(unittest::TestOneof2::BAR, reflection->GetEnum( - message, descriptor->FindFieldByName("bar_enum"))->number()); + message, descriptor->FindFieldByName("bar_bytes"))); + EXPECT_EQ( + unittest::TestOneof2::BAR, + reflection->GetEnum(message, descriptor->FindFieldByName("bar_enum")) + ->number()); // Check Set functions. - reflection->SetInt32( - &message, descriptor->FindFieldByName("foo_int"), 123); - EXPECT_EQ(123, reflection->GetInt32( - message, descriptor->FindFieldByName("foo_int"))); - reflection->SetString( - &message, descriptor->FindFieldByName("foo_string"), "abc"); + reflection->SetInt32(&message, descriptor->FindFieldByName("foo_int"), 123); + EXPECT_EQ(123, reflection->GetInt32(message, + descriptor->FindFieldByName("foo_int"))); + reflection->SetString(&message, descriptor->FindFieldByName("foo_string"), + "abc"); EXPECT_EQ("abc", reflection->GetString( - message, descriptor->FindFieldByName("foo_string"))); - reflection->SetString( - &message, descriptor->FindFieldByName("foo_bytes"), "bytes"); + message, descriptor->FindFieldByName("foo_string"))); + reflection->SetString(&message, descriptor->FindFieldByName("foo_bytes"), + "bytes"); EXPECT_EQ("bytes", reflection->GetString( - message, descriptor->FindFieldByName("foo_bytes"))); - reflection->SetString( - &message, descriptor->FindFieldByName("bar_cord"), "change_cord"); - EXPECT_EQ("change_cord", reflection->GetString( - message, descriptor->FindFieldByName("bar_cord"))); - reflection->SetString( - &message, descriptor->FindFieldByName("bar_string_piece"), - "change_spiece"); - EXPECT_EQ("change_spiece", reflection->GetString( - message, descriptor->FindFieldByName("bar_string_piece"))); + message, descriptor->FindFieldByName("foo_bytes"))); + reflection->SetString(&message, descriptor->FindFieldByName("bar_cord"), + "change_cord"); + EXPECT_EQ( + "change_cord", + reflection->GetString(message, descriptor->FindFieldByName("bar_cord"))); + reflection->SetString(&message, + descriptor->FindFieldByName("bar_string_piece"), + "change_spiece"); + EXPECT_EQ("change_spiece", + reflection->GetString( + message, descriptor->FindFieldByName("bar_string_piece"))); + + message.clear_foo(); + message.clear_bar(); + TestUtil::ExpectOneofClear(message); } TEST(GeneratedMessageReflectionTest, SetAllocatedOneofMessageTest) { @@ -766,8 +777,8 @@ TEST(GeneratedMessageReflectionTest, SetAllocatedOneofMessageTest) { TestUtil::ReflectionTester::ExpectOneofSetViaReflection(from_message1); TestUtil::ReflectionTester:: - SetAllocatedOptionalMessageFieldsToMessageViaReflection( - &from_message1, &to_message); + SetAllocatedOptionalMessageFieldsToMessageViaReflection(&from_message1, + &to_message); const Message& sub_message = reflection->GetMessage( to_message, descriptor->FindFieldByName("foo_lazy_message")); released = reflection->ReleaseMessage( @@ -778,12 +789,12 @@ TEST(GeneratedMessageReflectionTest, SetAllocatedOneofMessageTest) { TestUtil::ReflectionTester::SetOneofViaReflection(&from_message2); - reflection->MutableMessage( - &from_message2, descriptor->FindFieldByName("foo_message")); + reflection->MutableMessage(&from_message2, + descriptor->FindFieldByName("foo_message")); TestUtil::ReflectionTester:: - SetAllocatedOptionalMessageFieldsToMessageViaReflection( - &from_message2, &to_message); + SetAllocatedOptionalMessageFieldsToMessageViaReflection(&from_message2, + &to_message); const Message& sub_message2 = reflection->GetMessage( to_message, descriptor->FindFieldByName("foo_message")); @@ -797,9 +808,9 @@ TEST(GeneratedMessageReflectionTest, SetAllocatedOneofMessageTest) { TEST(GeneratedMessageReflectionTest, SetAllocatedOneofMessageOnArenaTest) { unittest::TestOneof2 from_message1; unittest::TestOneof2 from_message2; - ::google::protobuf::Arena arena; + Arena arena; unittest::TestOneof2* to_message = - ::google::protobuf::Arena::CreateMessage(&arena); + Arena::CreateMessage(&arena); const Descriptor* descriptor = unittest::TestOneof2::descriptor(); const Reflection* reflection = to_message->GetReflection(); @@ -814,8 +825,8 @@ TEST(GeneratedMessageReflectionTest, SetAllocatedOneofMessageOnArenaTest) { TestUtil::ReflectionTester::ExpectOneofSetViaReflection(from_message1); TestUtil::ReflectionTester:: - SetAllocatedOptionalMessageFieldsToMessageViaReflection( - &from_message1, to_message); + SetAllocatedOptionalMessageFieldsToMessageViaReflection(&from_message1, + to_message); const Message& sub_message = reflection->GetMessage( *to_message, descriptor->FindFieldByName("foo_lazy_message")); released = reflection->ReleaseMessage( @@ -828,12 +839,12 @@ TEST(GeneratedMessageReflectionTest, SetAllocatedOneofMessageOnArenaTest) { TestUtil::ReflectionTester::SetOneofViaReflection(&from_message2); - reflection->MutableMessage( - &from_message2, descriptor->FindFieldByName("foo_message")); + reflection->MutableMessage(&from_message2, + descriptor->FindFieldByName("foo_message")); TestUtil::ReflectionTester:: - SetAllocatedOptionalMessageFieldsToMessageViaReflection( - &from_message2, to_message); + SetAllocatedOptionalMessageFieldsToMessageViaReflection(&from_message2, + to_message); const Message& sub_message2 = reflection->GetMessage( *to_message, descriptor->FindFieldByName("foo_message")); @@ -846,11 +857,10 @@ TEST(GeneratedMessageReflectionTest, SetAllocatedOneofMessageOnArenaTest) { delete released; } - TEST(GeneratedMessageReflectionTest, ReleaseMessageTest) { unittest::TestAllTypes message; TestUtil::ReflectionTester reflection_tester( - unittest::TestAllTypes::descriptor()); + unittest::TestAllTypes::descriptor()); // When nothing is set, we expect all released messages to be NULL. reflection_tester.ExpectMessagesReleasedViaReflection( @@ -876,7 +886,7 @@ TEST(GeneratedMessageReflectionTest, ReleaseMessageTest) { TEST(GeneratedMessageReflectionTest, ReleaseExtensionMessageTest) { unittest::TestAllExtensions message; TestUtil::ReflectionTester reflection_tester( - unittest::TestAllExtensions::descriptor()); + unittest::TestAllExtensions::descriptor()); // When nothing is set, we expect all released messages to be NULL. reflection_tester.ExpectMessagesReleasedViaReflection( @@ -920,9 +930,9 @@ TEST(GeneratedMessageReflectionTest, ReleaseOneofMessageTest) { } TEST(GeneratedMessageReflectionTest, ArenaReleaseMessageTest) { - ::google::protobuf::Arena arena; + Arena arena; unittest::TestAllTypes* message = - ::google::protobuf::Arena::CreateMessage(&arena); + Arena::CreateMessage(&arena); TestUtil::ReflectionTester reflection_tester( unittest::TestAllTypes::descriptor()); @@ -944,9 +954,9 @@ TEST(GeneratedMessageReflectionTest, ArenaReleaseMessageTest) { } TEST(GeneratedMessageReflectionTest, ArenaReleaseExtensionMessageTest) { - ::google::protobuf::Arena arena; + Arena arena; unittest::TestAllExtensions* message = - ::google::protobuf::Arena::CreateMessage(&arena); + Arena::CreateMessage(&arena); TestUtil::ReflectionTester reflection_tester( unittest::TestAllExtensions::descriptor()); @@ -968,9 +978,9 @@ TEST(GeneratedMessageReflectionTest, ArenaReleaseExtensionMessageTest) { } TEST(GeneratedMessageReflectionTest, ArenaReleaseOneofMessageTest) { - ::google::protobuf::Arena arena; + Arena arena; unittest::TestOneof2* message = - ::google::protobuf::Arena::CreateMessage(&arena); + Arena::CreateMessage(&arena); TestUtil::ReflectionTester::SetOneofViaReflection(message); const Descriptor* descriptor = unittest::TestOneof2::descriptor(); @@ -998,39 +1008,41 @@ TEST(GeneratedMessageReflectionTest, UsageErrors) { // Testing every single failure mode would be too much work. Let's just // check a few. EXPECT_DEATH( - reflection->GetInt32( - message, descriptor->FindFieldByName("optional_int64")), - "Protocol Buffer reflection usage error:\n" - " Method : google::protobuf::Reflection::GetInt32\n" - " Message type: protobuf_unittest\\.TestAllTypes\n" - " Field : protobuf_unittest\\.TestAllTypes\\.optional_int64\n" - " Problem : Field is not the right type for this message:\n" - " Expected : CPPTYPE_INT32\n" - " Field type: CPPTYPE_INT64"); - EXPECT_DEATH( - reflection->GetInt32( - message, descriptor->FindFieldByName("repeated_int32")), - "Protocol Buffer reflection usage error:\n" - " Method : google::protobuf::Reflection::GetInt32\n" - " Message type: protobuf_unittest.TestAllTypes\n" - " Field : protobuf_unittest.TestAllTypes.repeated_int32\n" - " Problem : Field is repeated; the method requires a singular field."); + reflection->GetInt32(message, + descriptor->FindFieldByName("optional_int64")), + "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::GetInt32\n" + " Message type: protobuf_unittest\\.TestAllTypes\n" + " Field : protobuf_unittest\\.TestAllTypes\\.optional_int64\n" + " Problem : Field is not the right type for this message:\n" + " Expected : CPPTYPE_INT32\n" + " Field type: CPPTYPE_INT64"); + EXPECT_DEATH(reflection->GetInt32( + message, descriptor->FindFieldByName("repeated_int32")), + "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::GetInt32\n" + " Message type: protobuf_unittest.TestAllTypes\n" + " Field : protobuf_unittest.TestAllTypes.repeated_int32\n" + " Problem : Field is repeated; the method requires a " + "singular field."); EXPECT_DEATH( - reflection->GetInt32( - message, unittest::ForeignMessage::descriptor()->FindFieldByName("c")), - "Protocol Buffer reflection usage error:\n" - " Method : google::protobuf::Reflection::GetInt32\n" - " Message type: protobuf_unittest.TestAllTypes\n" - " Field : protobuf_unittest.ForeignMessage.c\n" - " Problem : Field does not match message type."); + reflection->GetInt32( + message, + unittest::ForeignMessage::descriptor()->FindFieldByName("c")), + "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::GetInt32\n" + " Message type: protobuf_unittest.TestAllTypes\n" + " Field : protobuf_unittest.ForeignMessage.c\n" + " Problem : Field does not match message type."); EXPECT_DEATH( - reflection->HasField( - message, unittest::ForeignMessage::descriptor()->FindFieldByName("c")), - "Protocol Buffer reflection usage error:\n" - " Method : google::protobuf::Reflection::HasField\n" - " Message type: protobuf_unittest.TestAllTypes\n" - " Field : protobuf_unittest.ForeignMessage.c\n" - " Problem : Field does not match message type."); + reflection->HasField( + message, + unittest::ForeignMessage::descriptor()->FindFieldByName("c")), + "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::HasField\n" + " Message type: protobuf_unittest.TestAllTypes\n" + " Field : protobuf_unittest.ForeignMessage.c\n" + " Problem : Field does not match message type."); #undef f } diff --git a/src/google/protobuf/generated_message_table_driven.cc b/src/google/protobuf/generated_message_table_driven.cc index 29af1ef692adc..56f1a6af841ef 100644 --- a/src/google/protobuf/generated_message_table_driven.cc +++ b/src/google/protobuf/generated_message_table_driven.cc @@ -30,15 +30,14 @@ #include -#include +#include +#include #include #include -#include #include #include #include -#include namespace google { namespace protobuf { @@ -47,38 +46,40 @@ namespace internal { namespace { UnknownFieldSet* MutableUnknownFields(MessageLite* msg, int64 arena_offset) { - return Raw(msg, arena_offset) - ->mutable_unknown_fields(); + return Raw(msg, arena_offset) + ->mutable_unknown_fields(); } struct UnknownFieldHandler { + // TODO(mvels): consider renaming UnknownFieldHandler to (TableDrivenTraits?), + // and conflating InternalMetaData into it, simplifying the template. + static constexpr bool IsLite() { return false; } + static bool Skip(MessageLite* msg, const ParseTable& table, - io::CodedInputStream* input, - int tag) { + io::CodedInputStream* input, int tag) { GOOGLE_DCHECK(table.unknown_field_set); return WireFormat::SkipField(input, tag, - MutableUnknownFields(msg, table.arena_offset)); + MutableUnknownFields(msg, table.arena_offset)); } - static void Varint(MessageLite* msg, const ParseTable& table, - int tag, int value) { + static void Varint(MessageLite* msg, const ParseTable& table, int tag, + int value) { GOOGLE_DCHECK(table.unknown_field_set); - MutableUnknownFields(msg, table.arena_offset)->AddVarint( - WireFormatLite::GetTagFieldNumber(tag), value); + MutableUnknownFields(msg, table.arena_offset) + ->AddVarint(WireFormatLite::GetTagFieldNumber(tag), value); } - static bool ParseExtension( - MessageLite* msg, const ParseTable& table, - io::CodedInputStream* input, int tag) { + static bool ParseExtension(MessageLite* msg, const ParseTable& table, + io::CodedInputStream* input, int tag) { ExtensionSet* extensions = GetExtensionSet(msg, table.extension_offset); if (extensions == NULL) { return false; } - const Message* prototype = down_cast( - table.default_instance()); + const Message* prototype = + down_cast(table.default_instance()); GOOGLE_DCHECK(prototype != NULL); GOOGLE_DCHECK(table.unknown_field_set); @@ -91,11 +92,10 @@ struct UnknownFieldHandler { } // namespace -bool MergePartialFromCodedStream( - MessageLite* msg, const ParseTable& table, io::CodedInputStream* input) { - return MergePartialFromCodedStreamImpl(msg, table, - input); +bool MergePartialFromCodedStream(MessageLite* msg, const ParseTable& table, + io::CodedInputStream* input) { + return MergePartialFromCodedStreamImpl(msg, table, + input); } } // namespace internal diff --git a/src/google/protobuf/generated_message_table_driven.h b/src/google/protobuf/generated_message_table_driven.h index 5eb63dbd27b04..0f6309ae988fd 100644 --- a/src/google/protobuf/generated_message_table_driven.h +++ b/src/google/protobuf/generated_message_table_driven.h @@ -33,41 +33,40 @@ #include #include +#include #include #include -#include - -#if LANG_CXX11 -#define PROTOBUF_CONSTEXPR constexpr // We require C++11 and Clang to use constexpr for variables, as GCC 4.8 // requires constexpr to be consistent between declarations of variables // unnecessarily (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58541). -#ifdef __clang__ +// VS 2017 Update 3 also supports this usage of constexpr. +#if defined(__clang__) || (defined(_MSC_VER) && _MSC_VER >= 1911) #define PROTOBUF_CONSTEXPR_VAR constexpr #else // !__clang__ #define PROTOBUF_CONSTEXPR_VAR #endif // !_clang -#else -#define PROTOBUF_CONSTEXPR -#define PROTOBUF_CONSTEXPR_VAR +#ifdef SWIG +#error "You cannot SWIG proto headers" #endif +#include + namespace google { namespace protobuf { namespace internal { // Processing-type masks. -static PROTOBUF_CONSTEXPR const unsigned char kOneofMask = 0x40; -static PROTOBUF_CONSTEXPR const unsigned char kRepeatedMask = 0x20; +static constexpr const unsigned char kOneofMask = 0x40; +static constexpr const unsigned char kRepeatedMask = 0x20; // Mask for the raw type: either a WireFormatLite::FieldType or one of the // ProcessingTypes below, without the oneof or repeated flag. -static PROTOBUF_CONSTEXPR const unsigned char kTypeMask = 0x1f; +static constexpr const unsigned char kTypeMask = 0x1f; // Wire type masks. -static PROTOBUF_CONSTEXPR const unsigned char kNotPackedMask = 0x10; -static PROTOBUF_CONSTEXPR const unsigned char kInvalidMask = 0x20; +static constexpr const unsigned char kNotPackedMask = 0x10; +static constexpr const unsigned char kInvalidMask = 0x20; enum ProcessingTypes { TYPE_STRING_CORD = 19, @@ -77,9 +76,40 @@ enum ProcessingTypes { TYPE_MAP = 23, }; -#if LANG_CXX11 static_assert(TYPE_MAP < kRepeatedMask, "Invalid enum"); -#endif + +struct PROTOBUF_EXPORT FieldMetadata { + uint32 offset; // offset of this field in the struct + uint32 tag; // field * 8 + wire_type + // byte offset * 8 + bit_offset; + // if the high bit is set then this is the byte offset of the oneof_case + // for this field. + uint32 has_offset; + uint32 type; // the type of this field. + const void* ptr; // auxiliary data + + // From the serializer point of view each fundamental type can occur in + // 4 different ways. For simplicity we treat all combinations as a cartesion + // product although not all combinations are allowed. + enum FieldTypeClass { + kPresence, + kNoPresence, + kRepeated, + kPacked, + kOneOf, + kNumTypeClasses // must be last enum + }; + // C++ protobuf has 20 fundamental types, were we added Cord and StringPiece + // and also distinguish the same types if they have different wire format. + enum { + kCordType = 19, + kStringPieceType = 20, + kNumTypes = 20, + kSpecial = kNumTypes * kNumTypeClasses, + }; + + static int CalculateType(int fundamental_type, FieldTypeClass type_class); +}; // TODO(ckennelly): Add a static assertion to ensure that these masks do not // conflict with wiretypes. @@ -87,7 +117,7 @@ static_assert(TYPE_MAP < kRepeatedMask, "Invalid enum"); // ParseTableField is kept small to help simplify instructions for computing // offsets, as we will always need this information to parse a field. // Additional data, needed for some types, is stored in -// AuxillaryParseTableField. +// AuxiliaryParseTableField. struct ParseTableField { uint32 offset; // The presence_index ordinarily represents a has_bit index, but for fields @@ -105,7 +135,7 @@ struct ParseTableField { struct ParseTable; -union AuxillaryParseTableField { +union AuxiliaryParseTableField { typedef bool (*EnumValidator)(int); // Enums @@ -122,7 +152,6 @@ union AuxillaryParseTableField { const MessageLite* default_message() const { return static_cast(default_message_void); } - const ParseTable* parse_table; }; message_aux messages; // Strings @@ -137,25 +166,20 @@ union AuxillaryParseTableField { }; map_aux maps; -#if LANG_CXX11 - AuxillaryParseTableField() = default; -#else - AuxillaryParseTableField() { } -#endif - PROTOBUF_CONSTEXPR AuxillaryParseTableField( - AuxillaryParseTableField::enum_aux e) : enums(e) {} - PROTOBUF_CONSTEXPR AuxillaryParseTableField( - AuxillaryParseTableField::message_aux m) : messages(m) {} - PROTOBUF_CONSTEXPR AuxillaryParseTableField( - AuxillaryParseTableField::string_aux s) : strings(s) {} - PROTOBUF_CONSTEXPR AuxillaryParseTableField( - AuxillaryParseTableField::map_aux m) + AuxiliaryParseTableField() = default; + constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::enum_aux e) + : enums(e) {} + constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::message_aux m) + : messages(m) {} + constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::string_aux s) + : strings(s) {} + constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::map_aux m) : maps(m) {} }; struct ParseTable { const ParseTableField* fields; - const AuxillaryParseTableField* aux; + const AuxiliaryParseTableField* aux; int max_field_number; // TODO(ckennelly): Do something with this padding. @@ -176,56 +200,147 @@ struct ParseTable { bool unknown_field_set; }; -// TODO(jhen): Remove the __NVCC__ check when we get a version of nvcc that -// supports these checks. -#if LANG_CXX11 && !defined(__NVCC__) static_assert(sizeof(ParseTableField) <= 16, "ParseTableField is too large"); // The tables must be composed of POD components to ensure link-time // initialization. -static_assert(std::is_pod::value, ""); -static_assert(std::is_pod::value, ""); -static_assert(std::is_pod::value, ""); -static_assert(std::is_pod::value, ""); -static_assert(std::is_pod::value, ""); -static_assert(std::is_pod::value, ""); -#endif +static_assert(std::is_standard_layout::value, ""); +static_assert(std::is_trivial::value, ""); +static_assert(std::is_standard_layout::value, ""); +static_assert(std::is_trivial::value, ""); +static_assert( + std::is_standard_layout::value, ""); +static_assert(std::is_trivial::value, ""); +static_assert( + std::is_standard_layout::value, ""); +static_assert(std::is_trivial::value, + ""); +static_assert( + std::is_standard_layout::value, ""); +static_assert(std::is_trivial::value, ""); +static_assert(std::is_standard_layout::value, ""); +static_assert(std::is_trivial::value, ""); // TODO(ckennelly): Consolidate these implementations into a single one, using // dynamic dispatch to the appropriate unknown field handler. bool MergePartialFromCodedStream(MessageLite* msg, const ParseTable& table, io::CodedInputStream* input); bool MergePartialFromCodedStreamLite(MessageLite* msg, const ParseTable& table, - io::CodedInputStream* input); - -template -struct MapEntryToMapField; - -template -struct MapEntryToMapField > { - typedef MapFieldLite, - Key, Value, kKeyFieldType, kValueFieldType, - default_enum_value> - MapFieldType; -}; + io::CodedInputStream* input); template bool ParseMap(io::CodedInputStream* input, void* map_field) { typedef typename MapEntryToMapField::MapFieldType MapFieldType; - typedef google::protobuf::Map + typedef Map MapType; typedef typename Entry::template Parser ParserType; ParserType parser(static_cast(map_field)); - return ::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(input, - &parser); + return WireFormatLite::ReadMessageNoVirtual(input, &parser); +} + +struct SerializationTable { + int num_fields; + const FieldMetadata* field_table; +}; + +PROTOBUF_EXPORT void SerializeInternal(const uint8* base, + const FieldMetadata* table, + int32 num_fields, + io::CodedOutputStream* output); + +inline void TableSerialize(const MessageLite& msg, + const SerializationTable* table, + io::CodedOutputStream* output) { + const FieldMetadata* field_table = table->field_table; + int num_fields = table->num_fields - 1; + const uint8* base = reinterpret_cast(&msg); + // TODO(gerbens) This skips the first test if we could use the fast + // array serialization path, we should make this + // int cached_size = + // *reinterpret_cast(base + field_table->offset); + // SerializeWithCachedSize(msg, field_table + 1, num_fields, cached_size, ...) + // But we keep conformance with the old way for now. + SerializeInternal(base, field_table + 1, num_fields, output); +} + +uint8* SerializeInternalToArray(const uint8* base, const FieldMetadata* table, + int32 num_fields, bool is_deterministic, + uint8* buffer); + +inline uint8* TableSerializeToArray(const MessageLite& msg, + const SerializationTable* table, + bool is_deterministic, uint8* buffer) { + const uint8* base = reinterpret_cast(&msg); + const FieldMetadata* field_table = table->field_table + 1; + int num_fields = table->num_fields - 1; + return SerializeInternalToArray(base, field_table, num_fields, + is_deterministic, buffer); +} + +template +struct CompareHelper { + bool operator()(const T& a, const T& b) const { return a < b; } +}; + +template <> +struct CompareHelper { + bool operator()(const ArenaStringPtr& a, const ArenaStringPtr& b) const { + return a.Get() < b.Get(); + } +}; + +struct CompareMapKey { + template + bool operator()(const MapEntryHelper& a, + const MapEntryHelper& b) const { + return Compare(a.key_, b.key_); + } + template + bool Compare(const T& a, const T& b) const { + return CompareHelper()(a, b); + } +}; + +template +void MapFieldSerializer(const uint8* base, uint32 offset, uint32 tag, + uint32 has_offset, io::CodedOutputStream* output) { + typedef MapEntryHelper Entry; + typedef typename MapFieldType::MapType::const_iterator Iter; + + const MapFieldType& map_field = + *reinterpret_cast(base + offset); + const SerializationTable* t = + table + + has_offset; // has_offset is overloaded for maps to mean table offset + if (!output->IsSerializationDeterministic()) { + for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end(); + ++it) { + Entry map_entry(*it); + output->WriteVarint32(tag); + output->WriteVarint32(map_entry._cached_size_); + SerializeInternal(reinterpret_cast(&map_entry), + t->field_table, t->num_fields, output); + } + } else { + std::vector v; + for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end(); + ++it) { + v.push_back(Entry(*it)); + } + std::sort(v.begin(), v.end(), CompareMapKey()); + for (int i = 0; i < v.size(); i++) { + output->WriteVarint32(tag); + output->WriteVarint32(v[i]._cached_size_); + SerializeInternal(reinterpret_cast(&v[i]), t->field_table, + t->num_fields, output); + } + } } } // namespace internal } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_H__ diff --git a/src/google/protobuf/generated_message_table_driven_lite.cc b/src/google/protobuf/generated_message_table_driven_lite.cc index 90a5050553b74..02e6dacee6d6a 100644 --- a/src/google/protobuf/generated_message_table_driven_lite.cc +++ b/src/google/protobuf/generated_message_table_driven_lite.cc @@ -30,13 +30,12 @@ #include -#include +#include #include #include #include #include -#include namespace google { namespace protobuf { @@ -44,40 +43,40 @@ namespace internal { namespace { -string* MutableUnknownFields(MessageLite* msg, int64 arena_offset) { - return Raw(msg, arena_offset) - ->mutable_unknown_fields(); +std::string* MutableUnknownFields(MessageLite* msg, int64 arena_offset) { + return Raw(msg, arena_offset) + ->mutable_unknown_fields(); } struct UnknownFieldHandlerLite { + // TODO(mvels): consider renaming UnknownFieldHandler to (TableDrivenTraits?), + // and conflating InternalMetaData into it, simplifying the template. + static constexpr bool IsLite() { return true; } + static bool Skip(MessageLite* msg, const ParseTable& table, - io::CodedInputStream* input, - int tag) { + io::CodedInputStream* input, int tag) { GOOGLE_DCHECK(!table.unknown_field_set); - ::google::protobuf::io::StringOutputStream unknown_fields_string( + io::StringOutputStream unknown_fields_string( MutableUnknownFields(msg, table.arena_offset)); - ::google::protobuf::io::CodedOutputStream unknown_fields_stream( - &unknown_fields_string, false); + io::CodedOutputStream unknown_fields_stream(&unknown_fields_string, false); - return ::google::protobuf::internal::WireFormatLite::SkipField( - input, tag, &unknown_fields_stream); + return internal::WireFormatLite::SkipField(input, tag, + &unknown_fields_stream); } - static void Varint(MessageLite* msg, const ParseTable& table, - int tag, int value) { + static void Varint(MessageLite* msg, const ParseTable& table, int tag, + int value) { GOOGLE_DCHECK(!table.unknown_field_set); - ::google::protobuf::io::StringOutputStream unknown_fields_string( + io::StringOutputStream unknown_fields_string( MutableUnknownFields(msg, table.arena_offset)); - ::google::protobuf::io::CodedOutputStream unknown_fields_stream( - &unknown_fields_string, false); + io::CodedOutputStream unknown_fields_stream(&unknown_fields_string, false); unknown_fields_stream.WriteVarint32(tag); unknown_fields_stream.WriteVarint32(value); } - static bool ParseExtension( - MessageLite* msg, const ParseTable& table, - io::CodedInputStream* input, int tag) { + static bool ParseExtension(MessageLite* msg, const ParseTable& table, + io::CodedInputStream* input, int tag) { ExtensionSet* extensions = GetExtensionSet(msg, table.extension_offset); if (extensions == NULL) { return false; @@ -86,22 +85,20 @@ struct UnknownFieldHandlerLite { const MessageLite* prototype = table.default_instance(); GOOGLE_DCHECK(!table.unknown_field_set); - ::google::protobuf::io::StringOutputStream unknown_fields_string( + io::StringOutputStream unknown_fields_string( MutableUnknownFields(msg, table.arena_offset)); - ::google::protobuf::io::CodedOutputStream unknown_fields_stream( - &unknown_fields_string, false); - return extensions->ParseField( - tag, input, prototype, &unknown_fields_stream); + io::CodedOutputStream unknown_fields_stream(&unknown_fields_string, false); + return extensions->ParseField(tag, input, prototype, + &unknown_fields_stream); } }; } // namespace -bool MergePartialFromCodedStreamLite( - MessageLite* msg, const ParseTable& table, io::CodedInputStream* input) { - return MergePartialFromCodedStreamImpl( - msg, table, input); +bool MergePartialFromCodedStreamLite(MessageLite* msg, const ParseTable& table, + io::CodedInputStream* input) { + return MergePartialFromCodedStreamImpl(msg, table, + input); } } // namespace internal diff --git a/src/google/protobuf/generated_message_table_driven_lite.h b/src/google/protobuf/generated_message_table_driven_lite.h index 20b4da218aeb9..32cc16e8624e9 100644 --- a/src/google/protobuf/generated_message_table_driven_lite.h +++ b/src/google/protobuf/generated_message_table_driven_lite.h @@ -31,17 +31,16 @@ #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_LITE_H__ #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_LITE_H__ -#include - -#include - #include #include -#include +#include +#include #include #include -#include +#include + +#include namespace google { namespace protobuf { @@ -50,8 +49,6 @@ namespace internal { enum StringType { StringType_STRING = 0, - StringType_CORD = 1, - StringType_STRING_PIECE = 2 }; // Logically a superset of StringType, consisting of all field types that @@ -60,7 +57,7 @@ enum ProcessingType { ProcessingType_STRING = 0, ProcessingType_CORD = 1, ProcessingType_STRING_PIECE = 2, - ProcessingType_MESSAGE = 3 + ProcessingType_MESSAGE = 3, }; enum Cardinality { @@ -80,15 +77,6 @@ inline const Type* Raw(const MessageLite* msg, int64 offset) { offset); } -template -inline Arena* GetArena(MessageLite* msg, int64 arena_offset) { - if (GOOGLE_PREDICT_FALSE(arena_offset == -1)) { - return NULL; - } - - return Raw(msg, arena_offset)->arena(); -} - inline ExtensionSet* GetExtensionSet(MessageLite* msg, int64 extension_offset) { if (extension_offset == -1) { return NULL; @@ -99,35 +87,28 @@ inline ExtensionSet* GetExtensionSet(MessageLite* msg, int64 extension_offset) { template inline Type* AddField(MessageLite* msg, int64 offset) { -#if LANG_CXX11 - static_assert(has_trivial_copy::value, - "Do not assign"); -#endif + static_assert(std::is_trivial::value, "Do not assign"); - google::protobuf::RepeatedField* repeated = - Raw >(msg, offset); + RepeatedField* repeated = Raw>(msg, offset); return repeated->Add(); } template <> -inline string* AddField(MessageLite* msg, int64 offset) { - google::protobuf::RepeatedPtrField* repeated = - Raw >(msg, offset); +inline std::string* AddField(MessageLite* msg, int64 offset) { + RepeatedPtrField* repeated = + Raw>(msg, offset); return repeated->Add(); } template inline void AddField(MessageLite* msg, int64 offset, Type value) { -#if LANG_CXX11 - static_assert(has_trivial_copy::value, - "Do not assign"); -#endif + static_assert(std::is_trivial::value, "Do not assign"); *AddField(msg, offset) = value; } inline void SetBit(uint32* has_bits, uint32 has_bit_index) { - GOOGLE_DCHECK(has_bits != NULL); + GOOGLE_DCHECK(has_bits != nullptr); uint32 mask = static_cast(1u) << (has_bit_index % 32); has_bits[has_bit_index / 32u] |= mask; @@ -143,10 +124,7 @@ inline Type* MutableField(MessageLite* msg, uint32* has_bits, template inline void SetField(MessageLite* msg, uint32* has_bits, uint32 has_bit_index, int64 offset, Type value) { -#if LANG_CXX11 - static_assert(has_trivial_copy::value, - "Do not assign"); -#endif + static_assert(std::is_trivial::value, "Do not assign"); *MutableField(msg, has_bits, has_bit_index, offset) = value; } @@ -161,7 +139,7 @@ inline void SetOneofField(MessageLite* msg, uint32* oneof_case, // Clears a oneof field. The field argument should correspond to the particular // field that is currently set in the oneof. inline void ClearOneofField(const ParseTableField& field, Arena* arena, - MessageLite* msg) { + MessageLite* msg) { switch (field.processing_type & kTypeMask) { case WireFormatLite::TYPE_MESSAGE: if (arena == NULL) { @@ -172,7 +150,7 @@ inline void ClearOneofField(const ParseTableField& field, Arena* arena, case WireFormatLite::TYPE_STRING: case WireFormatLite::TYPE_BYTES: Raw(msg, field.offset) - ->Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), arena); + ->Destroy(ArenaStringPtr::EmptyDefault{}, arena); break; default: @@ -191,7 +169,7 @@ template inline void ResetOneofField(const ParseTable& table, int field_number, Arena* arena, MessageLite* msg, uint32* oneof_case, int64 offset, const void* default_ptr) { - if (*oneof_case == field_number) { + if (static_cast(*oneof_case) == field_number) { // The oneof is already set to the right type, so there is no need to clear // it. return; @@ -205,7 +183,7 @@ inline void ResetOneofField(const ParseTable& table, int field_number, switch (field_type) { case ProcessingType_STRING: Raw(msg, offset) - ->UnsafeSetDefault(static_cast(default_ptr)); + ->UnsafeSetDefault(static_cast(default_ptr)); break; case ProcessingType_MESSAGE: MessageLite** submessage = Raw(msg, offset); @@ -216,70 +194,85 @@ inline void ResetOneofField(const ParseTable& table, int field_number, } } -template +template static inline bool HandleString(io::CodedInputStream* input, MessageLite* msg, Arena* arena, uint32* has_bits, uint32 has_bit_index, int64 offset, const void* default_ptr, const char* field_name) { + StringPiece utf8_string_data; #ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED - const char* sdata; - size_t size; -#endif - - string* value; - switch (cardinality) { - case Cardinality_SINGULAR: - // TODO(ckennelly): Is this optimal? - value = - MutableField(msg, has_bits, has_bit_index, offset) - ->Mutable(static_cast(default_ptr), arena); - break; - case Cardinality_REPEATED: - value = AddField(msg, offset); - break; - case Cardinality_ONEOF: - value = Raw(msg, offset) - ->Mutable(static_cast(default_ptr), arena); - break; - } - GOOGLE_DCHECK(value != NULL); - - if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadString(input, value))) { - return false; + constexpr bool kValidateUtf8 = is_string_type; +#else + constexpr bool kValidateUtf8 = false; +#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + + switch (ctype) { + case StringType_STRING: { + switch (cardinality) { + case Cardinality_SINGULAR: { + ArenaStringPtr* field = MutableField( + msg, has_bits, has_bit_index, offset); + std::string* value = field->MutableNoCopy( + static_cast(default_ptr), arena); + if (PROTOBUF_PREDICT_FALSE( + !WireFormatLite::ReadString(input, value))) { + return false; + } + utf8_string_data = field->Get(); + } break; + case Cardinality_REPEATED: { + std::string* value = AddField(msg, offset); + if (PROTOBUF_PREDICT_FALSE( + !WireFormatLite::ReadString(input, value))) { + return false; + } + utf8_string_data = *value; + } break; + case Cardinality_ONEOF: { + ArenaStringPtr* field = Raw(msg, offset); + std::string* value = field->MutableNoCopy( + static_cast(default_ptr), arena); + if (PROTOBUF_PREDICT_FALSE( + !WireFormatLite::ReadString(input, value))) { + return false; + } + utf8_string_data = field->Get(); + } break; + default: + PROTOBUF_ASSUME(false); + } + break; } - -#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED - sdata = value->data(); - size = value->size(); -#endif - -#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED - if (validate) { - WireFormatLite::VerifyUtf8String(sdata, size, WireFormatLite::PARSE, - field_name); + default: + PROTOBUF_ASSUME(false); } -#endif + if (kValidateUtf8) { + // TODO(b/118759213): fail if proto3 + WireFormatLite::VerifyUtf8String(utf8_string_data.data(), + utf8_string_data.length(), + WireFormatLite::PARSE, field_name); + } return true; } -template +template inline bool HandleEnum(const ParseTable& table, io::CodedInputStream* input, MessageLite* msg, uint32* presence, uint32 presence_index, int64 offset, uint32 tag, int field_number) { int value; - if (GOOGLE_PREDICT_FALSE( + if (PROTOBUF_PREDICT_FALSE( (!WireFormatLite::ReadPrimitive( input, &value)))) { return false; } - AuxillaryParseTableField::EnumValidator validator = + AuxiliaryParseTableField::EnumValidator validator = table.aux[field_number].enums.validator; - if (validator(value)) { + if (validator == nullptr || validator(value)) { switch (cardinality) { case Cardinality_SINGULAR: SetField(msg, presence, presence_index, offset, value); @@ -288,12 +281,13 @@ inline bool HandleEnum(const ParseTable& table, io::CodedInputStream* input, AddField(msg, offset, value); break; case Cardinality_ONEOF: - ClearOneofField(table.fields[presence[presence_index]], - GetArena(msg, table.arena_offset), + ClearOneofField(table.fields[presence[presence_index]], msg->GetArena(), msg); SetOneofField(msg, presence, presence_index, offset, field_number, value); break; + default: + PROTOBUF_ASSUME(false); } } else { UnknownFieldHandler::Varint(msg, table, tag, value); @@ -307,6 +301,7 @@ inline bool HandleEnum(const ParseTable& table, io::CodedInputStream* input, class RepeatedMessageTypeHandler { public: typedef MessageLite Type; + typedef MessageLite WeakType; static Arena* GetArena(Type* t) { return t->GetArena(); } static void* GetMaybeArenaPointer(Type* t) { return t->GetMaybeArenaPointer(); @@ -322,44 +317,6 @@ class RepeatedMessageTypeHandler { } }; -inline bool ReadGroup(int field_number, io::CodedInputStream* input, - MessageLite* value) { - if (GOOGLE_PREDICT_FALSE(!input->IncrementRecursionDepth())) { - return false; - } - - if (GOOGLE_PREDICT_FALSE(!value->MergePartialFromCodedStream(input))) { - return false; - } - - input->DecrementRecursionDepth(); - // Make sure the last thing read was an end tag for this group. - if (GOOGLE_PREDICT_FALSE(!input->LastTagWas(WireFormatLite::MakeTag( - field_number, WireFormatLite::WIRETYPE_END_GROUP)))) { - return false; - } - - return true; -} - -inline bool ReadMessage(io::CodedInputStream* input, MessageLite* value) { - int length; - if (GOOGLE_PREDICT_FALSE(!input->ReadVarintSizeAsInt(&length))) { - return false; - } - - std::pair p = - input->IncrementRecursionDepthAndPushLimit(length); - if (GOOGLE_PREDICT_FALSE(p.second < 0 || - !value->MergePartialFromCodedStream(input))) { - return false; - } - - // Make sure that parsing stopped when the limit was hit, not at an endgroup - // tag. - return input->DecrementRecursionDepthAndPopLimit(p.first); -} - class MergePartialFromCodedStreamHelper { public: static MessageLite* Add(RepeatedPtrFieldBase* field, @@ -369,9 +326,10 @@ class MergePartialFromCodedStreamHelper { } }; -template -bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, - io::CodedInputStream* input) { +template +bool MergePartialFromCodedStreamInlined(MessageLite* msg, + const ParseTable& table, + io::CodedInputStream* input) { // We require that has_bits are present, as to avoid having to check for them // for every field. // @@ -381,20 +339,20 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, GOOGLE_DCHECK(has_bits != NULL); while (true) { - uint32 tag = input->ReadTag(); - + uint32 tag = input->ReadTagWithCutoffNoLastTag(kMaxTag).first; const WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); const int field_number = WireFormatLite::GetTagFieldNumber(tag); - if (field_number > table.max_field_number) { + if (PROTOBUF_PREDICT_FALSE(field_number > table.max_field_number)) { // check for possible extensions if (UnknownFieldHandler::ParseExtension(msg, table, input, tag)) { // successfully parsed continue; } - if (GOOGLE_PREDICT_FALSE(!UnknownFieldHandler::Skip(msg, table, input, tag))) { + if (PROTOBUF_PREDICT_FALSE( + !UnknownFieldHandler::Skip(msg, table, input, tag))) { return false; } @@ -414,14 +372,11 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, const unsigned char processing_type = data->processing_type; if (data->normal_wiretype == static_cast(wire_type)) { - // TODO(ckennelly): Use a computed goto on GCC/LLVM or otherwise eliminate - // the bounds check on processing_type. - switch (processing_type) { #define HANDLE_TYPE(TYPE, CPPTYPE) \ case (WireFormatLite::TYPE_##TYPE): { \ CPPTYPE value; \ - if (GOOGLE_PREDICT_FALSE( \ + if (PROTOBUF_PREDICT_FALSE( \ (!WireFormatLite::ReadPrimitive< \ CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)))) { \ return false; \ @@ -430,10 +385,9 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, break; \ } \ case (WireFormatLite::TYPE_##TYPE) | kRepeatedMask: { \ - google::protobuf::RepeatedField* values = \ - Raw >(msg, offset); \ - if (GOOGLE_PREDICT_FALSE((!WireFormatLite::ReadRepeatedPrimitive< \ - CPPTYPE, WireFormatLite::TYPE_##TYPE>( \ + RepeatedField* values = Raw>(msg, offset); \ + if (PROTOBUF_PREDICT_FALSE((!WireFormatLite::ReadRepeatedPrimitive< \ + CPPTYPE, WireFormatLite::TYPE_##TYPE>( \ data->tag_size, tag, input, values)))) { \ return false; \ } \ @@ -442,13 +396,13 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, case (WireFormatLite::TYPE_##TYPE) | kOneofMask: { \ uint32* oneof_case = Raw(msg, table.oneof_case_offset); \ CPPTYPE value; \ - if (GOOGLE_PREDICT_FALSE( \ + if (PROTOBUF_PREDICT_FALSE( \ (!WireFormatLite::ReadPrimitive< \ CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)))) { \ return false; \ } \ - ClearOneofField(table.fields[oneof_case[presence_index]], \ - GetArena(msg, table.arena_offset), msg); \ + ClearOneofField(table.fields[oneof_case[presence_index]], msg->GetArena(), \ + msg); \ SetOneofField(msg, oneof_case, presence_index, offset, field_number, \ value); \ break; \ @@ -474,16 +428,16 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, case WireFormatLite::TYPE_BYTES: #ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED case WireFormatLite::TYPE_STRING: -#endif +#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED { - Arena* const arena = - GetArena(msg, table.arena_offset); + Arena* const arena = msg->GetArena(); const void* default_ptr = table.aux[field_number].strings.default_ptr; - if (GOOGLE_PREDICT_FALSE(( - !HandleString( + if (PROTOBUF_PREDICT_FALSE( + (!HandleString( input, msg, arena, has_bits, presence_index, offset, - default_ptr, NULL)))) { + default_ptr, nullptr)))) { return false; } break; @@ -491,10 +445,9 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, case WireFormatLite::TYPE_BYTES | kOneofMask: #ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED case WireFormatLite::TYPE_STRING | kOneofMask: -#endif +#endif // !GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED { - Arena* const arena = - GetArena(msg, table.arena_offset); + Arena* const arena = msg->GetArena(); uint32* oneof_case = Raw(msg, table.oneof_case_offset); const void* default_ptr = table.aux[field_number].strings.default_ptr; @@ -502,10 +455,11 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, table, field_number, arena, msg, oneof_case + presence_index, offset, default_ptr); - if (GOOGLE_PREDICT_FALSE( - (!HandleString( - input, msg, arena, has_bits, presence_index, offset, - default_ptr, NULL)))) { + if (PROTOBUF_PREDICT_FALSE( + (!HandleString(input, msg, arena, has_bits, + presence_index, offset, + default_ptr, nullptr)))) { return false; } break; @@ -513,30 +467,29 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, case (WireFormatLite::TYPE_BYTES) | kRepeatedMask: #ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED case (WireFormatLite::TYPE_STRING) | kRepeatedMask: -#endif +#endif // !GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED { - Arena* const arena = - GetArena(msg, table.arena_offset); - const void* default_ptr = - table.aux[field_number].strings.default_ptr; + Arena* const arena = msg->GetArena(); + const void* default_ptr = table.aux[field_number].strings.default_ptr; - if (GOOGLE_PREDICT_FALSE(( - !HandleString( + if (PROTOBUF_PREDICT_FALSE( + (!HandleString( input, msg, arena, has_bits, presence_index, offset, - default_ptr, NULL)))) { + default_ptr, nullptr)))) { return false; } break; } #ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED case (WireFormatLite::TYPE_STRING): { - Arena* const arena = - GetArena(msg, table.arena_offset); + Arena* const arena = msg->GetArena(); const void* default_ptr = table.aux[field_number].strings.default_ptr; const char* field_name = table.aux[field_number].strings.field_name; - if (GOOGLE_PREDICT_FALSE( - (!HandleString( + if (PROTOBUF_PREDICT_FALSE( + (!HandleString( input, msg, arena, has_bits, presence_index, offset, default_ptr, field_name)))) { return false; @@ -544,13 +497,13 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, break; } case (WireFormatLite::TYPE_STRING) | kRepeatedMask: { - Arena* const arena = - GetArena(msg, table.arena_offset); + Arena* const arena = msg->GetArena(); const void* default_ptr = table.aux[field_number].strings.default_ptr; const char* field_name = table.aux[field_number].strings.field_name; - if (GOOGLE_PREDICT_FALSE( - (!HandleString( + if (PROTOBUF_PREDICT_FALSE( + (!HandleString( input, msg, arena, has_bits, presence_index, offset, default_ptr, field_name)))) { return false; @@ -558,8 +511,7 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, break; } case (WireFormatLite::TYPE_STRING) | kOneofMask: { - Arena* const arena = - GetArena(msg, table.arena_offset); + Arena* const arena = msg->GetArena(); uint32* oneof_case = Raw(msg, table.oneof_case_offset); const void* default_ptr = table.aux[field_number].strings.default_ptr; const char* field_name = table.aux[field_number].strings.field_name; @@ -568,39 +520,40 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, table, field_number, arena, msg, oneof_case + presence_index, offset, default_ptr); - if (GOOGLE_PREDICT_FALSE( - (!HandleString( + if (PROTOBUF_PREDICT_FALSE( + (!HandleString( input, msg, arena, has_bits, presence_index, offset, default_ptr, field_name)))) { return false; } break; } -#endif +#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED case WireFormatLite::TYPE_ENUM: { - if (GOOGLE_PREDICT_FALSE((!HandleEnum( - table, input, msg, has_bits, presence_index, offset, tag, - field_number)))) { + if (PROTOBUF_PREDICT_FALSE( + (!HandleEnum( + table, input, msg, has_bits, presence_index, offset, tag, + field_number)))) { return false; } break; } case WireFormatLite::TYPE_ENUM | kRepeatedMask: { - if (GOOGLE_PREDICT_FALSE((!HandleEnum( - table, input, msg, has_bits, presence_index, offset, tag, - field_number)))) { + if (PROTOBUF_PREDICT_FALSE( + (!HandleEnum( + table, input, msg, has_bits, presence_index, offset, tag, + field_number)))) { return false; } break; } case WireFormatLite::TYPE_ENUM | kOneofMask: { uint32* oneof_case = Raw(msg, table.oneof_case_offset); - if (GOOGLE_PREDICT_FALSE((!HandleEnum( - table, input, msg, oneof_case, presence_index, offset, tag, - field_number)))) { + if (PROTOBUF_PREDICT_FALSE( + (!HandleEnum( + table, input, msg, oneof_case, presence_index, offset, + tag, field_number)))) { return false; } break; @@ -611,16 +564,15 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, MessageLite* submsg = *submsg_holder; if (submsg == NULL) { - Arena* const arena = - GetArena(msg, table.arena_offset); + Arena* const arena = msg->GetArena(); const MessageLite* prototype = table.aux[field_number].messages.default_message(); submsg = prototype->New(arena); *submsg_holder = submsg; } - if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadGroup( - field_number, input, submsg))) { + if (PROTOBUF_PREDICT_FALSE( + !WireFormatLite::ReadGroup(field_number, input, submsg))) { return false; } @@ -635,8 +587,8 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, MessageLite* submsg = MergePartialFromCodedStreamHelper::Add(field, prototype); - if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadGroup( - field_number, input, submsg))) { + if (PROTOBUF_PREDICT_FALSE( + !WireFormatLite::ReadGroup(field_number, input, submsg))) { return false; } @@ -648,15 +600,18 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, MessageLite* submsg = *submsg_holder; if (submsg == NULL) { - Arena* const arena = - GetArena(msg, table.arena_offset); + Arena* const arena = msg->GetArena(); const MessageLite* prototype = table.aux[field_number].messages.default_message(); + if (prototype == NULL) { + prototype = ImplicitWeakMessage::default_instance(); + } submsg = prototype->New(arena); *submsg_holder = submsg; } - if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadMessage(input, submsg))) { + if (PROTOBUF_PREDICT_FALSE( + !WireFormatLite::ReadMessage(input, submsg))) { return false; } @@ -668,20 +623,22 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, RepeatedPtrFieldBase* field = Raw(msg, offset); const MessageLite* prototype = table.aux[field_number].messages.default_message(); - GOOGLE_DCHECK(prototype != NULL); + if (prototype == NULL) { + prototype = ImplicitWeakMessage::default_instance(); + } MessageLite* submsg = MergePartialFromCodedStreamHelper::Add(field, prototype); - if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadMessage(input, submsg))) { + if (PROTOBUF_PREDICT_FALSE( + !WireFormatLite::ReadMessage(input, submsg))) { return false; } break; } case WireFormatLite::TYPE_MESSAGE | kOneofMask: { - Arena* const arena = - GetArena(msg, table.arena_offset); + Arena* const arena = msg->GetArena(); uint32* oneof_case = Raw(msg, table.oneof_case_offset); MessageLite** submsg_holder = Raw(msg, offset); ResetOneofField( @@ -689,14 +646,15 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, offset, NULL); MessageLite* submsg = *submsg_holder; - if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadMessage(input, submsg))) { + if (PROTOBUF_PREDICT_FALSE( + !WireFormatLite::ReadMessage(input, submsg))) { return false; } break; } case TYPE_MAP: { - if (GOOGLE_PREDICT_FALSE(!(*table.aux[field_number].maps.parse_map)( + if (PROTOBUF_PREDICT_FALSE(!(*table.aux[field_number].maps.parse_map)( input, Raw(msg, offset)))) { return false; } @@ -704,10 +662,11 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, } case 0: { // Done. + input->SetLastTag(tag); return true; } default: - break; + PROTOBUF_ASSUME(false); } } else if (data->packed_wiretype == static_cast(wire_type)) { // Non-packable fields have their packed_wiretype masked with @@ -717,22 +676,18 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, GOOGLE_DCHECK_EQ(0, processing_type & kOneofMask); - - // TODO(ckennelly): Use a computed goto on GCC/LLVM. - // // Mask out kRepeatedMask bit, allowing the jump table to be smaller. - switch (static_cast( - processing_type ^ kRepeatedMask)) { -#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \ - case WireFormatLite::TYPE_##TYPE: { \ - google::protobuf::RepeatedField* values = \ - Raw >(msg, offset); \ - if (GOOGLE_PREDICT_FALSE( \ - (!WireFormatLite::ReadPackedPrimitive< \ - CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, values)))) { \ - return false; \ - } \ - break; \ + switch (static_cast(processing_type ^ + kRepeatedMask)) { +#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \ + case WireFormatLite::TYPE_##TYPE: { \ + RepeatedField* values = Raw>(msg, offset); \ + if (PROTOBUF_PREDICT_FALSE( \ + (!WireFormatLite::ReadPackedPrimitive< \ + CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, values)))) { \ + return false; \ + } \ + break; \ } HANDLE_PACKED_TYPE(INT32, int32, Int32) @@ -754,29 +709,28 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, #undef HANDLE_PACKED_TYPE case WireFormatLite::TYPE_ENUM: { // To avoid unnecessarily calling MutableUnknownFields (which mutates - // InternalMetadataWithArena) when all inputs in the repeated series + // InternalMetadata) when all inputs in the repeated series // are valid, we implement our own parser rather than call // WireFormat::ReadPackedEnumPreserveUnknowns. uint32 length; - if (GOOGLE_PREDICT_FALSE(!input->ReadVarint32(&length))) { + if (PROTOBUF_PREDICT_FALSE(!input->ReadVarint32(&length))) { return false; } - AuxillaryParseTableField::EnumValidator validator = + AuxiliaryParseTableField::EnumValidator validator = table.aux[field_number].enums.validator; - google::protobuf::RepeatedField* values = - Raw >(msg, offset); + RepeatedField* values = Raw>(msg, offset); io::CodedInputStream::Limit limit = input->PushLimit(length); while (input->BytesUntilLimit() > 0) { int value; - if (GOOGLE_PREDICT_FALSE( - (!google::protobuf::internal::WireFormatLite::ReadPrimitive< + if (PROTOBUF_PREDICT_FALSE( + (!WireFormatLite::ReadPrimitive< int, WireFormatLite::TYPE_ENUM>(input, &value)))) { return false; } - if (validator(value)) { + if (validator == nullptr || validator(value)) { values->Add(value); } else { // TODO(ckennelly): Consider caching here. @@ -794,11 +748,12 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, GOOGLE_DCHECK(false); return false; default: - break; + PROTOBUF_ASSUME(false); } } else { if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) { // Must be the end of the message. + input->SetLastTag(tag); return true; } @@ -809,15 +764,36 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, } // process unknown field. - if (GOOGLE_PREDICT_FALSE(!UnknownFieldHandler::Skip(msg, table, input, tag))) { + if (PROTOBUF_PREDICT_FALSE( + !UnknownFieldHandler::Skip(msg, table, input, tag))) { return false; } } } +} // NOLINT(readability/fn_size) + +template +bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, + io::CodedInputStream* input) { + // The main beneficial cutoff values are 1 and 2 byte tags. + // Instantiate calls with the appropriate upper tag range + if (table.max_field_number <= (0x7F >> 3)) { + return MergePartialFromCodedStreamInlined( + msg, table, input); + } else if (table.max_field_number <= (0x3FFF >> 3)) { + return MergePartialFromCodedStreamInlined( + msg, table, input); + } else { + return MergePartialFromCodedStreamInlined< + UnknownFieldHandler, std::numeric_limits::max()>(msg, table, + input); + } } } // namespace internal } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_LITE_H__ diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc index c9dfe61ade32d..bc7936591b496 100644 --- a/src/google/protobuf/generated_message_util.cc +++ b/src/google/protobuf/generated_message_util.cc @@ -34,41 +34,63 @@ #include +#include #include #include -#include #include +#include #include #include +#include #include #include #include #include -#include + +// Must be included last +#include + +PROTOBUF_PRAGMA_INIT_SEG + namespace google { namespace protobuf { namespace internal { -double Infinity() { - return std::numeric_limits::infinity(); +void DestroyMessage(const void* message) { + static_cast(message)->~MessageLite(); } -double NaN() { - return std::numeric_limits::quiet_NaN(); +void DestroyString(const void* s) { + static_cast(s)->~basic_string(); } -ExplicitlyConstructed< ::std::string> fixed_address_empty_string; -GOOGLE_PROTOBUF_DECLARE_ONCE(empty_string_once_init_); +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY ExplicitlyConstructed + fixed_address_empty_string{}; // NOLINT -void DeleteEmptyString() { fixed_address_empty_string.Destruct(); } -void InitEmptyString() { +PROTOBUF_CONSTINIT std::atomic init_protobuf_defaults_state{false}; +static bool InitProtobufDefaultsImpl() { fixed_address_empty_string.DefaultConstruct(); - OnShutdown(&DeleteEmptyString); + OnShutdownDestroyString(fixed_address_empty_string.get_mutable()); + + + init_protobuf_defaults_state.store(true, std::memory_order_release); + return true; +} + +void InitProtobufDefaultsSlow() { + static bool is_inited = InitProtobufDefaultsImpl(); + (void)is_inited; } +// Force the initialization of the empty string. +// Normally, registration would do it, but we don't have any guarantee that +// there is any object with reflection. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static std::true_type init_empty_string = + (InitProtobufDefaultsSlow(), std::true_type{}); -size_t StringSpaceUsedExcludingSelfLong(const string& str) { +size_t StringSpaceUsedExcludingSelfLong(const std::string& str) { const void* start = &str; const void* end = &str + 1; if (start <= str.data() && str.data() < end) { @@ -79,12 +101,6 @@ size_t StringSpaceUsedExcludingSelfLong(const string& str) { } } - - -void InitProtobufDefaults() { - GetEmptyString(); -} - template const T& Get(const void* ptr) { return *static_cast(ptr); @@ -100,8 +116,7 @@ struct PrimitiveTypeHelper; template <> struct PrimitiveTypeHelper { typedef bool Type; - static void Serialize(const void* ptr, - ::google::protobuf::io::CodedOutputStream* output) { + static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteBoolNoTag(Get(ptr), output); } static uint8* SerializeToArray(const void* ptr, uint8* buffer) { @@ -112,8 +127,7 @@ struct PrimitiveTypeHelper { template <> struct PrimitiveTypeHelper { typedef int32 Type; - static void Serialize(const void* ptr, - ::google::protobuf::io::CodedOutputStream* output) { + static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteInt32NoTag(Get(ptr), output); } static uint8* SerializeToArray(const void* ptr, uint8* buffer) { @@ -124,8 +138,7 @@ struct PrimitiveTypeHelper { template <> struct PrimitiveTypeHelper { typedef int32 Type; - static void Serialize(const void* ptr, - ::google::protobuf::io::CodedOutputStream* output) { + static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteSInt32NoTag(Get(ptr), output); } static uint8* SerializeToArray(const void* ptr, uint8* buffer) { @@ -136,8 +149,7 @@ struct PrimitiveTypeHelper { template <> struct PrimitiveTypeHelper { typedef uint32 Type; - static void Serialize(const void* ptr, - ::google::protobuf::io::CodedOutputStream* output) { + static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteUInt32NoTag(Get(ptr), output); } static uint8* SerializeToArray(const void* ptr, uint8* buffer) { @@ -147,8 +159,7 @@ struct PrimitiveTypeHelper { template <> struct PrimitiveTypeHelper { typedef int64 Type; - static void Serialize(const void* ptr, - ::google::protobuf::io::CodedOutputStream* output) { + static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteInt64NoTag(Get(ptr), output); } static uint8* SerializeToArray(const void* ptr, uint8* buffer) { @@ -159,8 +170,7 @@ struct PrimitiveTypeHelper { template <> struct PrimitiveTypeHelper { typedef int64 Type; - static void Serialize(const void* ptr, - ::google::protobuf::io::CodedOutputStream* output) { + static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteSInt64NoTag(Get(ptr), output); } static uint8* SerializeToArray(const void* ptr, uint8* buffer) { @@ -170,8 +180,7 @@ struct PrimitiveTypeHelper { template <> struct PrimitiveTypeHelper { typedef uint64 Type; - static void Serialize(const void* ptr, - ::google::protobuf::io::CodedOutputStream* output) { + static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteUInt64NoTag(Get(ptr), output); } static uint8* SerializeToArray(const void* ptr, uint8* buffer) { @@ -182,8 +191,7 @@ struct PrimitiveTypeHelper { template <> struct PrimitiveTypeHelper { typedef uint32 Type; - static void Serialize(const void* ptr, - ::google::protobuf::io::CodedOutputStream* output) { + static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteFixed32NoTag(Get(ptr), output); } static uint8* SerializeToArray(const void* ptr, uint8* buffer) { @@ -194,8 +202,7 @@ struct PrimitiveTypeHelper { template <> struct PrimitiveTypeHelper { typedef uint64 Type; - static void Serialize(const void* ptr, - ::google::protobuf::io::CodedOutputStream* output) { + static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteFixed64NoTag(Get(ptr), output); } static uint8* SerializeToArray(const void* ptr, uint8* buffer) { @@ -230,9 +237,8 @@ struct PrimitiveTypeHelper template <> struct PrimitiveTypeHelper { - typedef string Type; - static void Serialize(const void* ptr, - ::google::protobuf::io::CodedOutputStream* output) { + typedef std::string Type; + static void Serialize(const void* ptr, io::CodedOutputStream* output) { const Type& value = *static_cast(ptr); output->WriteVarint32(value.size()); output->WriteRawMaybeAliased(value.data(), value.size()); @@ -271,9 +277,8 @@ void WriteLengthTo(uint32 length, O* output) { // Specialization for coded output stream template -struct OutputHelper< ::google::protobuf::io::CodedOutputStream, type> { - static void Serialize(const void* ptr, - ::google::protobuf::io::CodedOutputStream* output) { +struct OutputHelper { + static void Serialize(const void* ptr, io::CodedOutputStream* output) { PrimitiveTypeHelper::Serialize(ptr, output); } }; @@ -292,35 +297,29 @@ struct OutputHelper { }; void SerializeMessageNoTable(const MessageLite* msg, - ::google::protobuf::io::CodedOutputStream* output) { + io::CodedOutputStream* output) { msg->SerializeWithCachedSizes(output); } void SerializeMessageNoTable(const MessageLite* msg, ArrayOutput* output) { - output->ptr = msg->InternalSerializeWithCachedSizesToArray( - output->is_deterministic, output->ptr); + io::ArrayOutputStream array_stream(output->ptr, INT_MAX); + io::CodedOutputStream o(&array_stream); + o.SetSerializationDeterministic(output->is_deterministic); + msg->SerializeWithCachedSizes(&o); + output->ptr += o.ByteCount(); } // Helper to branch to fast path if possible -void SerializeMessageDispatch(const ::google::protobuf::MessageLite& msg, +void SerializeMessageDispatch(const MessageLite& msg, const FieldMetadata* field_table, int num_fields, int32 cached_size, - ::google::protobuf::io::CodedOutputStream* output) { + io::CodedOutputStream* output) { const uint8* base = reinterpret_cast(&msg); - // Try the fast path - uint8* ptr = output->GetDirectBufferForNBytesAndAdvance(cached_size); - if (ptr) { - // We use virtual dispatch to enable dedicated generated code for the - // fast path. - msg.InternalSerializeWithCachedSizesToArray( - output->IsSerializationDeterministic(), ptr); - return; - } SerializeInternal(base, field_table, num_fields, output); } // Helper to branch to fast path if possible -void SerializeMessageDispatch(const ::google::protobuf::MessageLite& msg, +void SerializeMessageDispatch(const MessageLite& msg, const FieldMetadata* field_table, int num_fields, int32 cached_size, ArrayOutput* output) { const uint8* base = reinterpret_cast(&msg); @@ -478,8 +477,8 @@ struct RepeatedFieldHelper { for (int i = 0; i < AccessorHelper::Size(array); i++) { WriteTagTo(md.tag, output); SerializeMessageTo( - static_cast(AccessorHelper::Get(array, i)), md.ptr, - output); + static_cast(AccessorHelper::Get(array, i)), + md.ptr, output); } } }; @@ -593,8 +592,8 @@ bool IsNull(const void* ptr) { void SerializeInternal(const uint8* base, const FieldMetadata* field_metadata_table, - int32 num_fields, - ::google::protobuf::io::CodedOutputStream* output) { + int32 num_fields, io::CodedOutputStream* output) { + SpecialSerializer func = nullptr; for (int i = 0; i < num_fields; i++) { const FieldMetadata& field_metadata = field_metadata_table[i]; const uint8* ptr = base + field_metadata.offset; @@ -620,10 +619,10 @@ void SerializeInternal(const uint8* base, // Special cases case FieldMetadata::kSpecial: - reinterpret_cast( - const_cast(field_metadata.ptr))( - base, field_metadata.offset, field_metadata.tag, - field_metadata.has_offset, output); + func = reinterpret_cast( + const_cast(field_metadata.ptr)); + func(base, field_metadata.offset, field_metadata.tag, + field_metadata.has_offset, output); break; default: // __builtin_unreachable() @@ -638,6 +637,7 @@ uint8* SerializeInternalToArray(const uint8* base, uint8* buffer) { ArrayOutput array_output = {buffer, is_deterministic}; ArrayOutput* output = &array_output; + SpecialSerializer func = nullptr; for (int i = 0; i < num_fields; i++) { const FieldMetadata& field_metadata = field_metadata_table[i]; const uint8* ptr = base + field_metadata.offset; @@ -665,10 +665,10 @@ uint8* SerializeInternalToArray(const uint8* base, io::ArrayOutputStream array_stream(array_output.ptr, INT_MAX); io::CodedOutputStream output(&array_stream); output.SetSerializationDeterministic(is_deterministic); - reinterpret_cast( - const_cast(field_metadata.ptr))( - base, field_metadata.offset, field_metadata.tag, - field_metadata.has_offset, &output); + func = reinterpret_cast( + const_cast(field_metadata.ptr)); + func(base, field_metadata.offset, field_metadata.tag, + field_metadata.has_offset, &output); array_output.ptr += output.ByteCount(); } break; default: @@ -681,20 +681,57 @@ uint8* SerializeInternalToArray(const uint8* base, #undef SERIALIZERS_FOR_TYPE void ExtensionSerializer(const uint8* ptr, uint32 offset, uint32 tag, - uint32 has_offset, - ::google::protobuf::io::CodedOutputStream* output) { + uint32 has_offset, io::CodedOutputStream* output) { reinterpret_cast(ptr + offset) ->SerializeWithCachedSizes(tag, has_offset, output); } void UnknownFieldSerializerLite(const uint8* ptr, uint32 offset, uint32 tag, uint32 has_offset, - ::google::protobuf::io::CodedOutputStream* output) { + io::CodedOutputStream* output) { output->WriteString( - reinterpret_cast(ptr + offset) - ->unknown_fields()); + reinterpret_cast(ptr + offset) + ->unknown_fields(&internal::GetEmptyString)); +} + +MessageLite* DuplicateIfNonNullInternal(MessageLite* message) { + if (message) { + MessageLite* ret = message->New(); + ret->CheckTypeAndMergeFrom(*message); + return ret; + } else { + return NULL; + } +} + +void GenericSwap(MessageLite* m1, MessageLite* m2) { + std::unique_ptr tmp(m1->New()); + tmp->CheckTypeAndMergeFrom(*m1); + m1->Clear(); + m1->CheckTypeAndMergeFrom(*m2); + m2->Clear(); + m2->CheckTypeAndMergeFrom(*tmp); +} + +// Returns a message owned by this Arena. This may require Own()ing or +// duplicating the message. +MessageLite* GetOwnedMessageInternal(Arena* message_arena, + MessageLite* submessage, + Arena* submessage_arena) { + GOOGLE_DCHECK(submessage->GetArena() == submessage_arena); + GOOGLE_DCHECK(message_arena != submessage_arena); + if (message_arena != NULL && submessage_arena == NULL) { + message_arena->Own(submessage); + return submessage; + } else { + MessageLite* ret = submessage->New(message_arena); + ret->CheckTypeAndMergeFrom(*submessage); + return ret; + } } } // namespace internal } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h index 096a84cd8cf72..94c6c294b2eb0 100644 --- a/src/google/protobuf/generated_message_util.h +++ b/src/google/protobuf/generated_message_util.h @@ -39,73 +39,69 @@ #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ #include + +#include #include #include #include -#include #include -#include +#include #include -#include +#include #include +#include // Add direct dep on port for pb.cc +#include +#include #include +#include +#include -namespace google { +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif +namespace google { namespace protobuf { class Arena; +class Message; -namespace io { class CodedInputStream; } +namespace io { +class CodedInputStream; +} namespace internal { - -// Annotation for the compiler to emit a deprecation message if a field marked -// with option 'deprecated=true' is used in the code, or for other things in -// generated code which are deprecated. -// -// For internal use in the pb.cc files, deprecation warnings are suppressed -// there. -#undef DEPRECATED_PROTOBUF_FIELD -#define PROTOBUF_DEPRECATED - -#define GOOGLE_PROTOBUF_DEPRECATED_ATTR +template +inline To DownCast(From* f) { + return PROTOBUF_NAMESPACE_ID::internal::down_cast(f); +} +template +inline To DownCast(From& f) { + return PROTOBUF_NAMESPACE_ID::internal::down_cast(f); +} -// Returns the offset of the given field within the given aggregate type. -// This is equivalent to the ANSI C offsetof() macro. However, according -// to the C++ standard, offsetof() only works on POD types, and GCC -// enforces this requirement with a warning. In practice, this rule is -// unnecessarily strict; there is probably no compiler or platform on -// which the offsets of the direct fields of a class are non-constant. -// Fields inherited from superclasses *can* have non-constant offsets, -// but that's not what this macro will be used for. -#if defined(__clang__) -// For Clang we use __builtin_offsetof() and suppress the warning, -// to avoid Control Flow Integrity and UBSan vptr sanitizers from -// crashing while trying to validate the invalid reinterpet_casts. -#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD) \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ - __builtin_offsetof(TYPE, FIELD) \ - _Pragma("clang diagnostic pop") -#else -// Note that we calculate relative to the pointer value 16 here since if we -// just use zero, GCC complains about dereferencing a NULL pointer. We -// choose 16 rather than some other number just in case the compiler would -// be confused by an unaligned pointer. -#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD) \ - static_cast< ::google::protobuf::uint32>( \ - reinterpret_cast( \ - &reinterpret_cast(16)->FIELD) - \ - reinterpret_cast(16)) -#endif +// This fastpath inlines a single branch instead of having to make the +// InitProtobufDefaults function call. +// It also generates less inlined code than a function-scope static initializer. +PROTOBUF_EXPORT extern std::atomic init_protobuf_defaults_state; +PROTOBUF_EXPORT void InitProtobufDefaultsSlow(); +PROTOBUF_EXPORT inline void InitProtobufDefaults() { + if (PROTOBUF_PREDICT_FALSE( + !init_protobuf_defaults_state.load(std::memory_order_acquire))) { + InitProtobufDefaultsSlow(); + } +} -// Constants for special floating point values. -LIBPROTOBUF_EXPORT double Infinity(); -LIBPROTOBUF_EXPORT double NaN(); +// This used by proto1 +PROTOBUF_EXPORT inline const std::string& GetEmptyString() { + InitProtobufDefaults(); + return GetEmptyStringAlreadyInited(); +} // True if IsInitialized() is true for all elements of t. Type is expected @@ -113,51 +109,32 @@ LIBPROTOBUF_EXPORT double NaN(); // helper here to keep the protobuf compiler from ever having to emit loops in // IsInitialized() methods. We want the C++ compiler to inline this or not // as it sees fit. -template bool AllAreInitialized(const Type& t) { - for (int i = t.size(); --i >= 0; ) { +template +bool AllAreInitialized(const RepeatedPtrField& t) { + for (int i = t.size(); --i >= 0;) { if (!t.Get(i).IsInitialized()) return false; } return true; } -LIBPROTOBUF_EXPORT void InitProtobufDefaults(); - -struct LIBPROTOBUF_EXPORT FieldMetadata { - uint32 offset; // offset of this field in the struct - uint32 tag; // field * 8 + wire_type - // byte offset * 8 + bit_offset; - // if the high bit is set then this is the byte offset of the oneof_case - // for this field. - uint32 has_offset; - uint32 type; // the type of this field. - const void* ptr; // auxiliary data - - // From the serializer point of view each fundamental type can occur in - // 4 different ways. For simplicity we treat all combinations as a cartesion - // product although not all combinations are allowed. - enum FieldTypeClass { - kPresence, - kNoPresence, - kRepeated, - kPacked, - kOneOf, - kNumTypeClasses // must be last enum - }; - // C++ protobuf has 20 fundamental types, were we added Cord and StringPiece - // and also distinquish the same types if they have different wire format. - enum { - kCordType = 19, - kStringPieceType = 20, - kNumTypes = 20, - kSpecial = kNumTypes * kNumTypeClasses, - }; - - static int CalculateType(int fundamental_type, FieldTypeClass type_class); -}; +// "Weak" variant of AllAreInitialized, used to implement implicit weak fields. +// This version operates on MessageLite to avoid introducing a dependency on the +// concrete message type. +template +bool AllAreInitializedWeak(const RepeatedPtrField& t) { + for (int i = t.size(); --i >= 0;) { + if (!reinterpret_cast(t) + .Get >(i) + .IsInitialized()) { + return false; + } + } + return true; +} inline bool IsPresent(const void* base, uint32 hasbit) { const uint32* has_bits_array = static_cast(base); - return has_bits_array[hasbit / 32] & (1u << (hasbit & 31)); + return (has_bits_array[hasbit / 32] & (1u << (hasbit & 31))) != 0; } inline bool IsOneofPresent(const void* base, uint32 offset, uint32 tag) { @@ -168,114 +145,68 @@ inline bool IsOneofPresent(const void* base, uint32 offset, uint32 tag) { typedef void (*SpecialSerializer)(const uint8* base, uint32 offset, uint32 tag, uint32 has_offset, - ::google::protobuf::io::CodedOutputStream* output); + io::CodedOutputStream* output); + +PROTOBUF_EXPORT void ExtensionSerializer(const uint8* base, uint32 offset, + uint32 tag, uint32 has_offset, + io::CodedOutputStream* output); +PROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8* base, + uint32 offset, uint32 tag, + uint32 has_offset, + io::CodedOutputStream* output); + +PROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message); +PROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena, + MessageLite* submessage, + Arena* submessage_arena); +PROTOBUF_EXPORT void GenericSwap(MessageLite* m1, MessageLite* m2); +// We specialize GenericSwap for non-lite messages to benefit from reflection. +PROTOBUF_EXPORT void GenericSwap(Message* m1, Message* m2); -LIBPROTOBUF_EXPORT void ExtensionSerializer(const uint8* base, uint32 offset, uint32 tag, - uint32 has_offset, - ::google::protobuf::io::CodedOutputStream* output); -LIBPROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8* base, uint32 offset, uint32 tag, - uint32 has_offset, - ::google::protobuf::io::CodedOutputStream* output); - -struct SerializationTable { - int num_fields; - const FieldMetadata* field_table; -}; - -LIBPROTOBUF_EXPORT void SerializeInternal(const uint8* base, const FieldMetadata* table, - int num_fields, ::google::protobuf::io::CodedOutputStream* output); - -inline void TableSerialize(const ::google::protobuf::MessageLite& msg, - const SerializationTable* table, - ::google::protobuf::io::CodedOutputStream* output) { - const FieldMetadata* field_table = table->field_table; - int num_fields = table->num_fields - 1; - const uint8* base = reinterpret_cast(&msg); - // TODO(gerbens) This skips the first test if we could use the fast - // array serialization path, we should make this - // int cached_size = - // *reinterpret_cast(base + field_table->offset); - // SerializeWithCachedSize(msg, field_table + 1, num_fields, cached_size, ...) - // But we keep conformance with the old way for now. - SerializeInternal(base, field_table + 1, num_fields, output); +template +T* DuplicateIfNonNull(T* message) { + // The casts must be reinterpret_cast<> because T might be a forward-declared + // type that the compiler doesn't know is related to MessageLite. + return reinterpret_cast( + DuplicateIfNonNullInternal(reinterpret_cast(message))); } -uint8* SerializeInternalToArray(const uint8* base, const FieldMetadata* table, - int num_fields, bool is_deterministic, - uint8* buffer); - -inline uint8* TableSerializeToArray(const ::google::protobuf::MessageLite& msg, - const SerializationTable* table, - bool is_deterministic, uint8* buffer) { - const uint8* base = reinterpret_cast(&msg); - const FieldMetadata* field_table = table->field_table + 1; - int num_fields = table->num_fields - 1; - return SerializeInternalToArray(base, field_table, num_fields, - is_deterministic, buffer); +template +T* GetOwnedMessage(Arena* message_arena, T* submessage, + Arena* submessage_arena) { + // The casts must be reinterpret_cast<> because T might be a forward-declared + // type that the compiler doesn't know is related to MessageLite. + return reinterpret_cast(GetOwnedMessageInternal( + message_arena, reinterpret_cast(submessage), + submessage_arena)); } -template -struct CompareHelper { - bool operator()(const T& a, const T& b) { return a < b; } -}; +// Hide atomic from the public header and allow easy change to regular int +// on platforms where the atomic might have a perf impact. +class PROTOBUF_EXPORT CachedSize { + public: + int Get() const { return size_.load(std::memory_order_relaxed); } + void Set(int size) { size_.store(size, std::memory_order_relaxed); } -template <> -struct CompareHelper { - bool operator()(const ArenaStringPtr& a, const ArenaStringPtr& b) { - return a.Get() < b.Get(); - } + private: + std::atomic size_{0}; }; -struct CompareMapKey { - template - bool operator()(const MapEntryHelper& a, const MapEntryHelper& b) { - return Compare(a.key_, b.key_); - } - template - bool Compare(const T& a, const T& b) { - return CompareHelper()(a, b); - } -}; - -template -void MapFieldSerializer(const uint8* base, uint32 offset, uint32 tag, - uint32 has_offset, - ::google::protobuf::io::CodedOutputStream* output) { - typedef MapEntryHelper Entry; - typedef typename MapFieldType::MapType::const_iterator Iter; - - const MapFieldType& map_field = - *reinterpret_cast(base + offset); - const SerializationTable* t = - table + - has_offset; // has_offset is overloaded for maps to mean table offset - if (!output->IsSerializationDeterministic()) { - for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end(); - ++it) { - Entry map_entry(*it); - output->WriteVarint32(tag); - output->WriteVarint32(map_entry._cached_size_); - SerializeInternal(reinterpret_cast(&map_entry), - t->field_table, t->num_fields, output); - } - } else { - std::vector v; - for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end(); - ++it) { - v.push_back(Entry(*it)); - } - std::sort(v.begin(), v.end(), CompareMapKey()); - for (int i = 0; i < v.size(); i++) { - output->WriteVarint32(tag); - output->WriteVarint32(v[i]._cached_size_); - SerializeInternal(reinterpret_cast(&v[i]), t->field_table, - t->num_fields, output); - } - } +PROTOBUF_EXPORT void DestroyMessage(const void* message); +PROTOBUF_EXPORT void DestroyString(const void* s); +// Destroy (not delete) the message +inline void OnShutdownDestroyMessage(const void* ptr) { + OnShutdownRun(DestroyMessage, ptr); +} +// Destroy the string (call std::string destructor) +inline void OnShutdownDestroyString(const std::string* ptr) { + OnShutdownRun(DestroyString, ptr); } } // namespace internal } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ diff --git a/src/google/protobuf/has_bits.h b/src/google/protobuf/has_bits.h index cb1d7cccb68fc..7fd92343c7af1 100644 --- a/src/google/protobuf/has_bits.h +++ b/src/google/protobuf/has_bits.h @@ -32,25 +32,32 @@ #define GOOGLE_PROTOBUF_HAS_BITS_H__ #include +#include + +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif namespace google { namespace protobuf { namespace internal { -template +template class HasBits { public: - HasBits() GOOGLE_ATTRIBUTE_ALWAYS_INLINE { Clear(); } + constexpr HasBits() PROTOBUF_NDEBUG_INLINE : has_bits_{} {} - void Clear() GOOGLE_ATTRIBUTE_ALWAYS_INLINE { + void Clear() PROTOBUF_NDEBUG_INLINE { memset(has_bits_, 0, sizeof(has_bits_)); } - ::google::protobuf::uint32& operator[](int index) GOOGLE_ATTRIBUTE_ALWAYS_INLINE { + uint32& operator[](int index) PROTOBUF_NDEBUG_INLINE { return has_bits_[index]; } - const ::google::protobuf::uint32& operator[](int index) const GOOGLE_ATTRIBUTE_ALWAYS_INLINE { + const uint32& operator[](int index) const PROTOBUF_NDEBUG_INLINE { return has_bits_[index]; } @@ -62,10 +69,14 @@ class HasBits { return !(*this == rhs); } + void Or(const HasBits& rhs) { + for (size_t i = 0; i < doublewords; i++) has_bits_[i] |= rhs[i]; + } + bool empty() const; private: - ::google::protobuf::uint32 has_bits_[doublewords]; + uint32 has_bits_[doublewords]; }; template <> @@ -98,6 +109,8 @@ inline bool HasBits::empty() const { } // namespace internal } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_HAS_BITS_H__ diff --git a/src/google/protobuf/implicit_weak_message.cc b/src/google/protobuf/implicit_weak_message.cc new file mode 100644 index 0000000000000..528cf95d41084 --- /dev/null +++ b/src/google/protobuf/implicit_weak_message.cc @@ -0,0 +1,67 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include +#include +#include +#include + +#include + +namespace google { +namespace protobuf { +namespace internal { + +const char* ImplicitWeakMessage::_InternalParse(const char* ptr, + ParseContext* ctx) { + return ctx->AppendString(ptr, &data_); +} + +ExplicitlyConstructed + implicit_weak_message_default_instance; +internal::once_flag implicit_weak_message_once_init_; + +void InitImplicitWeakMessageDefaultInstance() { + implicit_weak_message_default_instance.DefaultConstruct(); +} + +const ImplicitWeakMessage* ImplicitWeakMessage::default_instance() { + internal::call_once(implicit_weak_message_once_init_, + InitImplicitWeakMessageDefaultInstance); + return &implicit_weak_message_default_instance.get(); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include diff --git a/src/google/protobuf/implicit_weak_message.h b/src/google/protobuf/implicit_weak_message.h new file mode 100644 index 0000000000000..bfa6a813b3a6a --- /dev/null +++ b/src/google/protobuf/implicit_weak_message.h @@ -0,0 +1,190 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__ +#define GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__ + +#include + +#include +#include +#include +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +#include + +// This file is logically internal-only and should only be used by protobuf +// generated code. + +namespace google { +namespace protobuf { +namespace internal { + +// An implementation of MessageLite that treats all data as unknown. This type +// acts as a placeholder for an implicit weak field in the case where the true +// message type does not get linked into the binary. +class PROTOBUF_EXPORT ImplicitWeakMessage : public MessageLite { + public: + ImplicitWeakMessage() {} + explicit ImplicitWeakMessage(Arena* arena) : MessageLite(arena) {} + + static const ImplicitWeakMessage* default_instance(); + + std::string GetTypeName() const override { return ""; } + + MessageLite* New() const override { return new ImplicitWeakMessage; } + MessageLite* New(Arena* arena) const override { + return Arena::CreateMessage(arena); + } + + void Clear() override { data_.clear(); } + + bool IsInitialized() const override { return true; } + + void CheckTypeAndMergeFrom(const MessageLite& other) override { + data_.append(static_cast(other).data_); + } + + const char* _InternalParse(const char* ptr, ParseContext* ctx) final; + + size_t ByteSizeLong() const override { return data_.size(); } + + uint8* _InternalSerialize(uint8* target, + io::EpsCopyOutputStream* stream) const final { + return stream->WriteRaw(data_.data(), static_cast(data_.size()), + target); + } + + int GetCachedSize() const override { return static_cast(data_.size()); } + + typedef void InternalArenaConstructable_; + + private: + std::string data_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImplicitWeakMessage); +}; + +// A type handler for use with implicit weak repeated message fields. +template +class ImplicitWeakTypeHandler { + public: + typedef MessageLite Type; + static constexpr bool Moveable = false; + + static inline MessageLite* NewFromPrototype(const MessageLite* prototype, + Arena* arena = NULL) { + return prototype->New(arena); + } + + static inline void Delete(MessageLite* value, Arena* arena) { + if (arena == NULL) { + delete value; + } + } + static inline Arena* GetArena(MessageLite* value) { + return value->GetArena(); + } + static inline void* GetMaybeArenaPointer(MessageLite* value) { + return value->GetArena(); + } + static inline void Clear(MessageLite* value) { value->Clear(); } + static void Merge(const MessageLite& from, MessageLite* to) { + to->CheckTypeAndMergeFrom(from); + } +}; + +} // namespace internal + +template +struct WeakRepeatedPtrField { + using TypeHandler = internal::ImplicitWeakTypeHandler; + constexpr WeakRepeatedPtrField() : weak() {} + explicit WeakRepeatedPtrField(Arena* arena) : weak(arena) {} + ~WeakRepeatedPtrField() { weak.template Destroy(); } + + typedef internal::RepeatedPtrIterator iterator; + typedef internal::RepeatedPtrIterator const_iterator; + typedef internal::RepeatedPtrOverPtrsIterator + pointer_iterator; + typedef internal::RepeatedPtrOverPtrsIterator + const_pointer_iterator; + + iterator begin() { return iterator(base().raw_data()); } + const_iterator begin() const { return iterator(base().raw_data()); } + const_iterator cbegin() const { return begin(); } + iterator end() { return begin() + base().size(); } + const_iterator end() const { return begin() + base().size(); } + const_iterator cend() const { return end(); } + pointer_iterator pointer_begin() { + return pointer_iterator(base().raw_mutable_data()); + } + const_pointer_iterator pointer_begin() const { + return const_pointer_iterator(base().raw_mutable_data()); + } + pointer_iterator pointer_end() { + return pointer_iterator(base().raw_mutable_data() + base().size()); + } + const_pointer_iterator pointer_end() const { + return const_pointer_iterator(base().raw_mutable_data() + base().size()); + } + + MessageLite* AddWeak(const MessageLite* prototype) { + return base().AddWeak(prototype); + } + T* Add() { return weak.Add(); } + void Clear() { base().template Clear(); } + void MergeFrom(const WeakRepeatedPtrField& other) { + base().template MergeFrom(other.base()); + } + void InternalSwap(WeakRepeatedPtrField* other) { + base().InternalSwap(&other->base()); + } + + const internal::RepeatedPtrFieldBase& base() const { return weak; } + internal::RepeatedPtrFieldBase& base() { return weak; } + // Union disables running the destructor. Which would create a strong link. + // Instead we explicitly destroy the underlying base through the virtual + // destructor. + union { + RepeatedPtrField weak; + }; +}; + +} // namespace protobuf +} // namespace google + +#include + +#endif // GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__ diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc index 17eb0ffa2e9a0..2b20e0a5ce6e8 100644 --- a/src/google/protobuf/io/coded_stream.cc +++ b/src/google/protobuf/io/coded_stream.cc @@ -38,17 +38,24 @@ // will not cross the end of the buffer, since we can avoid a lot // of branching in this case. -#include +#include + +#include + #include +#include #include -#include -#include -#include + #include #include +#include +#include +#include #include +#include + namespace google { namespace protobuf { namespace io { @@ -59,8 +66,8 @@ static const int kMaxVarintBytes = 10; static const int kMaxVarint32Bytes = 5; -inline bool NextNonEmpty(ZeroCopyInputStream* input, - const void** data, int* size) { +inline bool NextNonEmpty(ZeroCopyInputStream* input, const void** data, + int* size) { bool success; do { success = input->Next(data, size); @@ -82,10 +89,6 @@ CodedInputStream::~CodedInputStream() { int CodedInputStream::default_recursion_limit_ = 100; -void CodedOutputStream::EnableAliasing(bool enabled) { - aliasing_enabled_ = enabled && output_->AllowsAliasing(); -} - void CodedInputStream::BackUpInputToCurrentPosition() { int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_; if (backup_bytes > 0) { @@ -121,9 +124,9 @@ CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) { // security: byte_limit is possibly evil, so check for negative values // and overflow. Also check that the new requested limit is before the // previous limit; otherwise we continue to enforce the previous limit. - if GOOGLE_PREDICT_TRUE(byte_limit >= 0 && - byte_limit <= INT_MAX - current_position && - byte_limit < current_limit_ - current_position) { + if (PROTOBUF_PREDICT_TRUE(byte_limit >= 0 && + byte_limit <= INT_MAX - current_position && + byte_limit < current_limit_ - current_position)) { current_limit_ = current_position + byte_limit; RecomputeBufferLimits(); } @@ -173,10 +176,7 @@ int CodedInputStream::BytesUntilLimit() const { return current_limit_ - current_position; } -void CodedInputStream::SetTotalBytesLimit( - int total_bytes_limit, int warning_threshold) { - (void) warning_threshold; - +void CodedInputStream::SetTotalBytesLimit(int total_bytes_limit) { // Make sure the limit isn't already past, since this could confuse other // code. int current_position = CurrentPosition(); @@ -190,11 +190,13 @@ int CodedInputStream::BytesUntilTotalBytesLimit() const { } void CodedInputStream::PrintTotalBytesLimitError() { - GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too " - "big (more than " << total_bytes_limit_ - << " bytes). To increase the limit (or to disable these " - "warnings), see CodedInputStream::SetTotalBytesLimit() " - "in google/protobuf/io/coded_stream.h."; + GOOGLE_LOG(ERROR) + << "A protocol message was rejected because it was too " + "big (more than " + << total_bytes_limit_ + << " bytes). To increase the limit (or to disable these " + "warnings), see CodedInputStream::SetTotalBytesLimit() " + "in third_party/protobuf/src/google/protobuf/io/coded_stream.h."; } bool CodedInputStream::SkipFallback(int count, int original_buffer_size) { @@ -220,8 +222,12 @@ bool CodedInputStream::SkipFallback(int count, int original_buffer_size) { return false; } + if (!input_->Skip(count)) { + total_bytes_read_ = input_->ByteCount(); + return false; + } total_bytes_read_ += count; - return input_->Skip(count); + return true; } bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) { @@ -233,15 +239,42 @@ bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) { } bool CodedInputStream::ReadRaw(void* buffer, int size) { - return InternalReadRawInline(buffer, size); + int current_buffer_size; + while ((current_buffer_size = BufferSize()) < size) { + // Reading past end of buffer. Copy what we have, then refresh. + memcpy(buffer, buffer_, current_buffer_size); + buffer = reinterpret_cast(buffer) + current_buffer_size; + size -= current_buffer_size; + Advance(current_buffer_size); + if (!Refresh()) return false; + } + + memcpy(buffer, buffer_, size); + Advance(size); + + return true; } -bool CodedInputStream::ReadString(string* buffer, int size) { +bool CodedInputStream::ReadString(std::string* buffer, int size) { if (size < 0) return false; // security: size is often user-supplied - return InternalReadStringInline(buffer, size); + + if (BufferSize() >= size) { + STLStringResizeUninitialized(buffer, size); + std::pair z = as_string_data(buffer); + if (z.second) { + // Oddly enough, memcpy() requires its first two args to be non-NULL even + // if we copy 0 bytes. So, we have ensured that z.first is non-NULL here. + GOOGLE_DCHECK(z.first != NULL); + memcpy(z.first, buffer_, size); + Advance(size); + } + return true; + } + + return ReadStringFallback(buffer, size); } -bool CodedInputStream::ReadStringFallback(string* buffer, int size) { +bool CodedInputStream::ReadStringFallback(std::string* buffer, int size) { if (!buffer->empty()) { buffer->clear(); } @@ -279,7 +312,7 @@ bool CodedInputStream::ReadLittleEndian32Fallback(uint32* value) { uint8 bytes[sizeof(*value)]; const uint8* ptr; - if (BufferSize() >= sizeof(*value)) { + if (BufferSize() >= static_cast(sizeof(*value))) { // Fast path: Enough bytes in the buffer to read directly. ptr = buffer_; Advance(sizeof(*value)); @@ -296,7 +329,7 @@ bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) { uint8 bytes[sizeof(*value)]; const uint8* ptr; - if (BufferSize() >= sizeof(*value)) { + if (BufferSize() >= static_cast(sizeof(*value))) { // Fast path: Enough bytes in the buffer to read directly. ptr = buffer_; Advance(sizeof(*value)); @@ -311,13 +344,28 @@ bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) { namespace { +// Decodes varint64 with known size, N, and returns next pointer. Knowing N at +// compile time, compiler can generate optimal code. For example, instead of +// subtracting 0x80 at each iteration, it subtracts properly shifted mask once. +template +const uint8* DecodeVarint64KnownSize(const uint8* buffer, uint64* value) { + GOOGLE_DCHECK_GT(N, 0); + uint64 result = static_cast(buffer[N - 1]) << (7 * (N - 1)); + for (size_t i = 0, offset = 0; i < N - 1; i++, offset += 7) { + result += static_cast(buffer[i] - 0x80) << offset; + } + *value = result; + return buffer + N; +} + // Read a varint from the given buffer, write it to *value, and return a pair. // The first part of the pair is true iff the read was successful. The second // part is buffer + (number of bytes read). This function is always inlined, // so returning a pair is costless. -GOOGLE_ATTRIBUTE_ALWAYS_INLINE ::std::pair ReadVarint32FromArray( - uint32 first_byte, const uint8* buffer, - uint32* value); +PROTOBUF_ALWAYS_INLINE +::std::pair ReadVarint32FromArray(uint32 first_byte, + const uint8* buffer, + uint32* value); inline ::std::pair ReadVarint32FromArray( uint32 first_byte, const uint8* buffer, uint32* value) { // Fast path: We have enough bytes left in the buffer to guarantee that @@ -328,71 +376,72 @@ inline ::std::pair ReadVarint32FromArray( uint32 b; uint32 result = first_byte - 0x80; ++ptr; // We just processed the first byte. Move on to the second. - b = *(ptr++); result += b << 7; if (!(b & 0x80)) goto done; + b = *(ptr++); + result += b << 7; + if (!(b & 0x80)) goto done; result -= 0x80 << 7; - b = *(ptr++); result += b << 14; if (!(b & 0x80)) goto done; + b = *(ptr++); + result += b << 14; + if (!(b & 0x80)) goto done; result -= 0x80 << 14; - b = *(ptr++); result += b << 21; if (!(b & 0x80)) goto done; + b = *(ptr++); + result += b << 21; + if (!(b & 0x80)) goto done; result -= 0x80 << 21; - b = *(ptr++); result += b << 28; if (!(b & 0x80)) goto done; + b = *(ptr++); + result += b << 28; + if (!(b & 0x80)) goto done; // "result -= 0x80 << 28" is irrevelant. // If the input is larger than 32 bits, we still need to read it all // and discard the high-order bits. for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) { - b = *(ptr++); if (!(b & 0x80)) goto done; + b = *(ptr++); + if (!(b & 0x80)) goto done; } // We have overrun the maximum size of a varint (10 bytes). Assume // the data is corrupt. return std::make_pair(false, ptr); - done: +done: *value = result; return std::make_pair(true, ptr); } -GOOGLE_ATTRIBUTE_ALWAYS_INLINE::std::pair ReadVarint64FromArray( +PROTOBUF_ALWAYS_INLINE::std::pair ReadVarint64FromArray( const uint8* buffer, uint64* value); inline ::std::pair ReadVarint64FromArray( const uint8* buffer, uint64* value) { - const uint8* ptr = buffer; - uint32 b; - - // Splitting into 32-bit pieces gives better performance on 32-bit - // processors. - uint32 part0 = 0, part1 = 0, part2 = 0; - - b = *(ptr++); part0 = b ; if (!(b & 0x80)) goto done; - part0 -= 0x80; - b = *(ptr++); part0 += b << 7; if (!(b & 0x80)) goto done; - part0 -= 0x80 << 7; - b = *(ptr++); part0 += b << 14; if (!(b & 0x80)) goto done; - part0 -= 0x80 << 14; - b = *(ptr++); part0 += b << 21; if (!(b & 0x80)) goto done; - part0 -= 0x80 << 21; - b = *(ptr++); part1 = b ; if (!(b & 0x80)) goto done; - part1 -= 0x80; - b = *(ptr++); part1 += b << 7; if (!(b & 0x80)) goto done; - part1 -= 0x80 << 7; - b = *(ptr++); part1 += b << 14; if (!(b & 0x80)) goto done; - part1 -= 0x80 << 14; - b = *(ptr++); part1 += b << 21; if (!(b & 0x80)) goto done; - part1 -= 0x80 << 21; - b = *(ptr++); part2 = b ; if (!(b & 0x80)) goto done; - part2 -= 0x80; - b = *(ptr++); part2 += b << 7; if (!(b & 0x80)) goto done; - // "part2 -= 0x80 << 7" is irrelevant because (0x80 << 7) << 56 is 0. - - // We have overrun the maximum size of a varint (10 bytes). Assume - // the data is corrupt. - return std::make_pair(false, ptr); + // Assumes varint64 is at least 2 bytes. + GOOGLE_DCHECK_GE(buffer[0], 128); + + const uint8* next; + if (buffer[1] < 128) { + next = DecodeVarint64KnownSize<2>(buffer, value); + } else if (buffer[2] < 128) { + next = DecodeVarint64KnownSize<3>(buffer, value); + } else if (buffer[3] < 128) { + next = DecodeVarint64KnownSize<4>(buffer, value); + } else if (buffer[4] < 128) { + next = DecodeVarint64KnownSize<5>(buffer, value); + } else if (buffer[5] < 128) { + next = DecodeVarint64KnownSize<6>(buffer, value); + } else if (buffer[6] < 128) { + next = DecodeVarint64KnownSize<7>(buffer, value); + } else if (buffer[7] < 128) { + next = DecodeVarint64KnownSize<8>(buffer, value); + } else if (buffer[8] < 128) { + next = DecodeVarint64KnownSize<9>(buffer, value); + } else if (buffer[9] < 128) { + next = DecodeVarint64KnownSize<10>(buffer, value); + } else { + // We have overrun the maximum size of a varint (10 bytes). Assume + // the data is corrupt. + return std::make_pair(false, buffer + 11); + } - done: - *value = (static_cast(part0)) | - (static_cast(part1) << 28) | - (static_cast(part2) << 56); - return std::make_pair(true, ptr); + return std::make_pair(true, next); } } // namespace @@ -414,7 +463,7 @@ int64 CodedInputStream::ReadVarint32Fallback(uint32 first_byte_or_zero) { << "Caller should provide us with *buffer_ when buffer is non-empty"; uint32 temp; ::std::pair p = - ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp); + ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp); if (!p.first) return -1; buffer_ = p.second; return temp; @@ -617,168 +666,285 @@ bool CodedInputStream::Refresh() { // CodedOutputStream ================================================= -google::protobuf::internal::AtomicWord CodedOutputStream::default_serialization_deterministic_ = 0; - -CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output) - : output_(output), - buffer_(NULL), - buffer_size_(0), - total_bytes_(0), - had_error_(false), - aliasing_enabled_(false), - serialization_deterministic_is_overridden_(false) { - // Eagerly Refresh() so buffer space is immediately available. - Refresh(); - // The Refresh() may have failed. If the client doesn't write any data, - // though, don't consider this an error. If the client does write data, then - // another Refresh() will be attempted and it will set the error once again. - had_error_ = false; -} - -CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output, - bool do_eager_refresh) - : output_(output), - buffer_(NULL), - buffer_size_(0), - total_bytes_(0), - had_error_(false), - aliasing_enabled_(false), - serialization_deterministic_is_overridden_(false) { - if (do_eager_refresh) { - // Eagerly Refresh() so buffer space is immediately available. - Refresh(); - // The Refresh() may have failed. If the client doesn't write any data, - // though, don't consider this an error. If the client does write data, then - // another Refresh() will be attempted and it will set the error once again. - had_error_ = false; - } +void EpsCopyOutputStream::EnableAliasing(bool enabled) { + aliasing_enabled_ = enabled && stream_->AllowsAliasing(); } -CodedOutputStream::~CodedOutputStream() { - Trim(); +int64 EpsCopyOutputStream::ByteCount(uint8* ptr) const { + // Calculate the current offset relative to the end of the stream buffer. + int delta = (end_ - ptr) + (buffer_end_ ? 0 : kSlopBytes); + return stream_->ByteCount() - delta; } -void CodedOutputStream::Trim() { - if (buffer_size_ > 0) { - output_->BackUp(buffer_size_); - total_bytes_ -= buffer_size_; - buffer_size_ = 0; - buffer_ = NULL; +// Flushes what's written out to the underlying ZeroCopyOutputStream buffers. +// Returns the size remaining in the buffer and sets buffer_end_ to the start +// of the remaining buffer, ie. [buffer_end_, buffer_end_ + return value) +int EpsCopyOutputStream::Flush(uint8* ptr) { + while (buffer_end_ && ptr > end_) { + int overrun = ptr - end_; + GOOGLE_DCHECK(!had_error_); + GOOGLE_DCHECK(overrun <= kSlopBytes); // NOLINT + ptr = Next() + overrun; + if (had_error_) return 0; + } + int s; + if (buffer_end_) { + std::memcpy(buffer_end_, buffer_, ptr - buffer_); + buffer_end_ += ptr - buffer_; + s = end_ - ptr; + } else { + // The stream is writing directly in the ZeroCopyOutputStream buffer. + s = end_ + kSlopBytes - ptr; + buffer_end_ = ptr; } + GOOGLE_DCHECK(s >= 0); // NOLINT + return s; } -bool CodedOutputStream::Skip(int count) { - if (count < 0) return false; +uint8* EpsCopyOutputStream::Trim(uint8* ptr) { + if (had_error_) return ptr; + int s = Flush(ptr); + if (s) stream_->BackUp(s); + // Reset to initial state (expecting new buffer) + buffer_end_ = end_ = buffer_; + return buffer_; +} - while (count > buffer_size_) { - count -= buffer_size_; - if (!Refresh()) return false; - } - Advance(count); - return true; +uint8* EpsCopyOutputStream::FlushAndResetBuffer(uint8* ptr) { + if (had_error_) return buffer_; + int s = Flush(ptr); + if (had_error_) return buffer_; + return SetInitialBuffer(buffer_end_, s); } -bool CodedOutputStream::GetDirectBufferPointer(void** data, int* size) { - if (buffer_size_ == 0 && !Refresh()) return false; - - *data = buffer_; - *size = buffer_size_; +bool EpsCopyOutputStream::Skip(int count, uint8** pp) { + if (count < 0) return false; + if (had_error_) { + *pp = buffer_; + return false; + } + int size = Flush(*pp); + if (had_error_) { + *pp = buffer_; + return false; + } + void* data = buffer_end_; + while (count > size) { + count -= size; + if (!stream_->Next(&data, &size)) { + *pp = Error(); + return false; + } + } + *pp = SetInitialBuffer(static_cast(data) + count, size - count); return true; } -void CodedOutputStream::WriteRaw(const void* data, int size) { - while (buffer_size_ < size) { - memcpy(buffer_, data, buffer_size_); - size -= buffer_size_; - data = reinterpret_cast(data) + buffer_size_; - if (!Refresh()) return; +bool EpsCopyOutputStream::GetDirectBufferPointer(void** data, int* size, + uint8** pp) { + if (had_error_) { + *pp = buffer_; + return false; } - - memcpy(buffer_, data, size); - Advance(size); + *size = Flush(*pp); + if (had_error_) { + *pp = buffer_; + return false; + } + *data = buffer_end_; + while (*size == 0) { + if (!stream_->Next(data, size)) { + *pp = Error(); + return false; + } + } + *pp = SetInitialBuffer(*data, *size); + return true; } -uint8* CodedOutputStream::WriteRawToArray( - const void* data, int size, uint8* target) { - memcpy(target, data, size); - return target + size; +uint8* EpsCopyOutputStream::GetDirectBufferForNBytesAndAdvance(int size, + uint8** pp) { + if (had_error_) { + *pp = buffer_; + return nullptr; + } + int s = Flush(*pp); + if (had_error_) { + *pp = buffer_; + return nullptr; + } + if (s >= size) { + auto res = buffer_end_; + *pp = SetInitialBuffer(buffer_end_ + size, s - size); + return res; + } else { + *pp = SetInitialBuffer(buffer_end_, s); + return nullptr; + } } - -void CodedOutputStream::WriteAliasedRaw(const void* data, int size) { - if (size < buffer_size_ - ) { - WriteRaw(data, size); +uint8* EpsCopyOutputStream::Next() { + GOOGLE_DCHECK(!had_error_); // NOLINT + if (PROTOBUF_PREDICT_FALSE(stream_ == nullptr)) return Error(); + if (buffer_end_) { + // We're in the patch buffer and need to fill up the previous buffer. + std::memcpy(buffer_end_, buffer_, end_ - buffer_); + uint8* ptr; + int size; + do { + void* data; + if (PROTOBUF_PREDICT_FALSE(!stream_->Next(&data, &size))) { + // Stream has an error, we use the patch buffer to continue to be + // able to write. + return Error(); + } + ptr = static_cast(data); + } while (size == 0); + if (PROTOBUF_PREDICT_TRUE(size > kSlopBytes)) { + std::memcpy(ptr, end_, kSlopBytes); + end_ = ptr + size - kSlopBytes; + buffer_end_ = nullptr; + return ptr; + } else { + GOOGLE_DCHECK(size > 0); // NOLINT + // Buffer to small + std::memmove(buffer_, end_, kSlopBytes); + buffer_end_ = ptr; + end_ = buffer_ + size; + return buffer_; + } } else { - Trim(); - - total_bytes_ += size; - had_error_ |= !output_->WriteAliasedRaw(data, size); + std::memcpy(buffer_, end_, kSlopBytes); + buffer_end_ = end_; + end_ = buffer_ + kSlopBytes; + return buffer_; } } -void CodedOutputStream::WriteLittleEndian32(uint32 value) { - uint8 bytes[sizeof(value)]; - - bool use_fast = buffer_size_ >= sizeof(value); - uint8* ptr = use_fast ? buffer_ : bytes; - - WriteLittleEndian32ToArray(value, ptr); +uint8* EpsCopyOutputStream::EnsureSpaceFallback(uint8* ptr) { + do { + if (PROTOBUF_PREDICT_FALSE(had_error_)) return buffer_; + int overrun = ptr - end_; + GOOGLE_DCHECK(overrun >= 0); // NOLINT + GOOGLE_DCHECK(overrun <= kSlopBytes); // NOLINT + ptr = Next() + overrun; + } while (ptr >= end_); + GOOGLE_DCHECK(ptr < end_); // NOLINT + return ptr; +} + +uint8* EpsCopyOutputStream::WriteRawFallback(const void* data, int size, + uint8* ptr) { + int s = GetSize(ptr); + while (s < size) { + std::memcpy(ptr, data, s); + size -= s; + data = static_cast(data) + s; + ptr = EnsureSpaceFallback(ptr + s); + s = GetSize(ptr); + } + std::memcpy(ptr, data, size); + return ptr + size; +} - if (use_fast) { - Advance(sizeof(value)); +uint8* EpsCopyOutputStream::WriteAliasedRaw(const void* data, int size, + uint8* ptr) { + if (size < GetSize(ptr) + ) { + return WriteRaw(data, size, ptr); } else { - WriteRaw(bytes, sizeof(value)); + ptr = Trim(ptr); + if (stream_->WriteAliasedRaw(data, size)) return ptr; + return Error(); } } -void CodedOutputStream::WriteLittleEndian64(uint64 value) { - uint8 bytes[sizeof(value)]; - - bool use_fast = buffer_size_ >= sizeof(value); - uint8* ptr = use_fast ? buffer_ : bytes; - - WriteLittleEndian64ToArray(value, ptr); - - if (use_fast) { - Advance(sizeof(value)); - } else { - WriteRaw(bytes, sizeof(value)); +#ifndef PROTOBUF_LITTLE_ENDIAN +uint8* EpsCopyOutputStream::WriteRawLittleEndian32(const void* data, int size, + uint8* ptr) { + auto p = static_cast(data); + auto end = p + size; + while (end - p >= kSlopBytes) { + ptr = EnsureSpace(ptr); + uint32 buffer[4]; + static_assert(sizeof(buffer) == kSlopBytes, "Buffer must be kSlopBytes"); + std::memcpy(buffer, p, kSlopBytes); + p += kSlopBytes; + for (auto x : buffer) + ptr = CodedOutputStream::WriteLittleEndian32ToArray(x, ptr); + } + while (p < end) { + ptr = EnsureSpace(ptr); + uint32 buffer; + std::memcpy(&buffer, p, 4); + p += 4; + ptr = CodedOutputStream::WriteLittleEndian32ToArray(buffer, ptr); } + return ptr; +} + +uint8* EpsCopyOutputStream::WriteRawLittleEndian64(const void* data, int size, + uint8* ptr) { + auto p = static_cast(data); + auto end = p + size; + while (end - p >= kSlopBytes) { + ptr = EnsureSpace(ptr); + uint64 buffer[2]; + static_assert(sizeof(buffer) == kSlopBytes, "Buffer must be kSlopBytes"); + std::memcpy(buffer, p, kSlopBytes); + p += kSlopBytes; + for (auto x : buffer) + ptr = CodedOutputStream::WriteLittleEndian64ToArray(x, ptr); + } + while (p < end) { + ptr = EnsureSpace(ptr); + uint64 buffer; + std::memcpy(&buffer, p, 8); + p += 8; + ptr = CodedOutputStream::WriteLittleEndian64ToArray(buffer, ptr); + } + return ptr; } +#endif -void CodedOutputStream::WriteVarint32SlowPath(uint32 value) { - uint8 bytes[kMaxVarint32Bytes]; - uint8* target = &bytes[0]; - uint8* end = WriteVarint32ToArray(value, target); - int size = end - target; - WriteRaw(bytes, size); + +uint8* EpsCopyOutputStream::WriteStringMaybeAliasedOutline(uint32 num, + const std::string& s, + uint8* ptr) { + ptr = EnsureSpace(ptr); + uint32 size = s.size(); + ptr = WriteLengthDelim(num, size, ptr); + return WriteRawMaybeAliased(s.data(), size, ptr); } -void CodedOutputStream::WriteVarint64SlowPath(uint64 value) { - uint8 bytes[kMaxVarintBytes]; - uint8* target = &bytes[0]; - uint8* end = WriteVarint64ToArray(value, target); - int size = end - target; - WriteRaw(bytes, size); +uint8* EpsCopyOutputStream::WriteStringOutline(uint32 num, const std::string& s, + uint8* ptr) { + ptr = EnsureSpace(ptr); + uint32 size = s.size(); + ptr = WriteLengthDelim(num, size, ptr); + return WriteRaw(s.data(), size, ptr); } -bool CodedOutputStream::Refresh() { - void* void_buffer; - if (output_->Next(&void_buffer, &buffer_size_)) { - buffer_ = reinterpret_cast(void_buffer); - total_bytes_ += buffer_size_; - return true; - } else { - buffer_ = NULL; - buffer_size_ = 0; - had_error_ = true; - return false; +std::atomic CodedOutputStream::default_serialization_deterministic_{ + false}; + +CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* stream, + bool do_eager_refresh) + : impl_(stream, IsDefaultSerializationDeterministic(), &cur_), + start_count_(stream->ByteCount()) { + if (do_eager_refresh) { + void* data; + int size; + if (!stream->Next(&data, &size) || size == 0) return; + cur_ = impl_.SetInitialBuffer(data, size); } } -uint8* CodedOutputStream::WriteStringWithSizeToArray(const string& str, +CodedOutputStream::~CodedOutputStream() { Trim(); } + + +uint8* CodedOutputStream::WriteStringWithSizeToArray(const std::string& str, uint8* target) { GOOGLE_DCHECK_LE(str.size(), kuint32max); target = WriteVarint32ToArray(str.size(), target); @@ -788,3 +954,5 @@ uint8* CodedOutputStream::WriteStringWithSizeToArray(const string& str, } // namespace io } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index 6d2599fba00c5..df8c4499ad7f2 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -67,7 +67,7 @@ // // Read a file created by the above code. // int fd = open("myfile", O_RDONLY); // ZeroCopyInputStream* raw_input = new FileInputStream(fd); -// CodedInputStream coded_input = new CodedInputStream(raw_input); +// CodedInputStream* coded_input = new CodedInputStream(raw_input); // // coded_input->ReadLittleEndian32(&magic_number); // if (magic_number != 1234) { @@ -109,40 +109,59 @@ #ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ #define GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ + #include + +#include #include +#include +#include #include +#include #include -#ifdef _MSC_VER - // Assuming windows is always little-endian. - #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) - #define PROTOBUF_LITTLE_ENDIAN 1 - #endif - #if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) - // If MSVC has "/RTCc" set, it will complain about truncating casts at - // runtime. This file contains some intentional truncating casts. - #pragma runtime_checks("c", off) - #endif + +#ifdef _WIN32 +// Assuming windows is always little-endian. +#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) +#define PROTOBUF_LITTLE_ENDIAN 1 +#endif +#if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) +// If MSVC has "/RTCc" set, it will complain about truncating casts at +// runtime. This file contains some intentional truncating casts. +#pragma runtime_checks("c", off) +#endif +#else +#ifdef __APPLE__ +#include // __BYTE_ORDER #else - #include // __BYTE_ORDER - #if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ - (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN)) && \ - !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) - #define PROTOBUF_LITTLE_ENDIAN 1 - #endif +#include // __BYTE_ORDER +#endif +#if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ + (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN)) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) +#define PROTOBUF_LITTLE_ENDIAN 1 +#endif #endif -#include #include +#include +#include +#include #include -namespace google { +#include + +namespace google { namespace protobuf { class DescriptorPool; class MessageFactory; +class ZeroCopyCodedInputStream; -namespace internal { void MapTestForceDeterministic(); } +namespace internal { +void MapTestForceDeterministic(); +class EpsCopyByteStream; +} // namespace internal namespace io { @@ -151,8 +170,8 @@ class CodedInputStream; class CodedOutputStream; // Defined in other files. -class ZeroCopyInputStream; // zero_copy_stream.h -class ZeroCopyOutputStream; // zero_copy_stream.h +class ZeroCopyInputStream; // zero_copy_stream.h +class ZeroCopyOutputStream; // zero_copy_stream.h // Class which reads and decodes binary data which is composed of varint- // encoded integers and fixed-width pieces. Wraps a ZeroCopyInputStream. @@ -161,7 +180,9 @@ class ZeroCopyOutputStream; // zero_copy_stream.h // Most methods of CodedInputStream that return a bool return false if an // underlying I/O error occurs or if the data is malformed. Once such a // failure occurs, the CodedInputStream is broken and is no longer useful. -class LIBPROTOBUF_EXPORT CodedInputStream { +// After a failure, callers also should assume writes to "out" args may have +// occurred, though nothing useful can be determined from those writes. +class PROTOBUF_EXPORT CodedInputStream { public: // Create a CodedInputStream that reads from the given ZeroCopyInputStream. explicit CodedInputStream(ZeroCopyInputStream* input); @@ -197,28 +218,14 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Like GetDirectBufferPointer, but this method is inlined, and does not // attempt to Refresh() if the buffer is currently empty. - GOOGLE_ATTRIBUTE_ALWAYS_INLINE void GetDirectBufferPointerInline(const void** data, - int* size); + PROTOBUF_ALWAYS_INLINE + void GetDirectBufferPointerInline(const void** data, int* size); // Read raw bytes, copying them into the given buffer. bool ReadRaw(void* buffer, int size); - // Like the above, with inlined optimizations. This should only be used - // by the protobuf implementation. - GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InternalReadRawInline(void* buffer, int size); - // Like ReadRaw, but reads into a string. - // - // Implementation Note: ReadString() grows the string gradually as it - // reads in the data, rather than allocating the entire requested size - // upfront. This prevents denial-of-service attacks in which a client - // could claim that a string is going to be MAX_INT bytes long in order to - // crash the server because it can't allocate this much space at once. - bool ReadString(string* buffer, int size); - // Like the above, with inlined optimizations. This should only be used - // by the protobuf implementation. - GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InternalReadStringInline(string* buffer, - int size); + bool ReadString(std::string* buffer, int size); // Read a 32-bit little-endian integer. @@ -230,10 +237,10 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // responsible for ensuring that the buffer has sufficient space. // Read a 32-bit little-endian integer. static const uint8* ReadLittleEndian32FromArray(const uint8* buffer, - uint32* value); + uint32* value); // Read a 64-bit little-endian integer. static const uint8* ReadLittleEndian64FromArray(const uint8* buffer, - uint64* value); + uint64* value); // Read an unsigned integer with Varint encoding, truncating to 32 bits. // Reading a 32-bit value is equivalent to reading a 64-bit one and casting @@ -261,12 +268,11 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Always inline because this is only called in one place per parse loop // but it is called for every iteration of said loop, so it should be fast. // GCC doesn't want to inline this by default. - GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTag() { + PROTOBUF_ALWAYS_INLINE uint32 ReadTag() { return last_tag_ = ReadTagNoLastTag(); } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTagNoLastTag(); - + PROTOBUF_ALWAYS_INLINE uint32 ReadTagNoLastTag(); // This usually a faster alternative to ReadTag() when cutoff is a manifest // constant. It does particularly well for cutoff >= 127. The first part @@ -276,15 +282,15 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // above cutoff or is 0. (There's intentional wiggle room when tag is 0, // because that can arise in several ways, and for best performance we want // to avoid an extra "is tag == 0?" check here.) - GOOGLE_ATTRIBUTE_ALWAYS_INLINE std::pair ReadTagWithCutoff( - uint32 cutoff) { + PROTOBUF_ALWAYS_INLINE + std::pair ReadTagWithCutoff(uint32 cutoff) { std::pair result = ReadTagWithCutoffNoLastTag(cutoff); last_tag_ = result.first; return result; } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE std::pair ReadTagWithCutoffNoLastTag( - uint32 cutoff); + PROTOBUF_ALWAYS_INLINE + std::pair ReadTagWithCutoffNoLastTag(uint32 cutoff); // Usually returns true if calling ReadVarint32() now would produce the given // value. Will always return false if ReadVarint32() would not return the @@ -293,7 +299,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // parameter. // Always inline because this collapses to a small number of instructions // when given a constant parameter, but GCC doesn't want to inline by default. - GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool ExpectTag(uint32 expected); + PROTOBUF_ALWAYS_INLINE bool ExpectTag(uint32 expected); // Like above, except this reads from the specified buffer. The caller is // responsible for ensuring that the buffer is large enough to read a varint @@ -302,9 +308,8 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // // Returns a pointer beyond the expected tag if it was found, or NULL if it // was not. - GOOGLE_ATTRIBUTE_ALWAYS_INLINE static const uint8* ExpectTagFromArray( - const uint8* buffer, - uint32 expected); + PROTOBUF_ALWAYS_INLINE + static const uint8* ExpectTagFromArray(const uint8* buffer, uint32 expected); // Usually returns true if no more bytes can be read. Always returns false // if more bytes can be read. If ExpectAtEnd() returns true, a subsequent @@ -333,6 +338,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // It also checks for some cases where, due to optimizations, // MergeFromCodedStream() can incorrectly return true. bool ConsumedEntireMessage(); + void SetConsumed() { legitimate_message_end_ = true; } // Limits ---------------------------------------------------------- // Limits are used when parsing length-delimited embedded messages. @@ -372,42 +378,32 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Total Bytes Limit ----------------------------------------------- // To prevent malicious users from sending excessively large messages - // and causing integer overflows or memory exhaustion, CodedInputStream - // imposes a hard limit on the total number of bytes it will read. + // and causing memory exhaustion, CodedInputStream imposes a hard limit on + // the total number of bytes it will read. // Sets the maximum number of bytes that this CodedInputStream will read - // before refusing to continue. To prevent integer overflows in the - // protocol buffers implementation, as well as to prevent servers from - // allocating enormous amounts of memory to hold parsed messages, the - // maximum message length should be limited to the shortest length that - // will not harm usability. The theoretical shortest message that could - // cause integer overflows is 512MB. The default limit is 64MB. Apps - // should set shorter limits if possible. For backwards compatibility all - // negative values get squashed to -1, as other negative values might have - // special internal meanings. An error will always be printed to stderr if - // the limit is reached. + // before refusing to continue. To prevent servers from allocating enormous + // amounts of memory to hold parsed messages, the maximum message length + // should be limited to the shortest length that will not harm usability. + // The default limit is INT_MAX (~2GB) and apps should set shorter limits + // if possible. An error will always be printed to stderr if the limit is + // reached. // - // This is unrelated to PushLimit()/PopLimit(). + // Note: setting a limit less than the current read position is interpreted + // as a limit on the current position. // - // Hint: If you are reading this because your program is printing a - // warning about dangerously large protocol messages, you may be - // confused about what to do next. The best option is to change your - // design such that excessively large messages are not necessary. - // For example, try to design file formats to consist of many small - // messages rather than a single large one. If this is infeasible, - // you will need to increase the limit. Chances are, though, that - // your code never constructs a CodedInputStream on which the limit - // can be set. You probably parse messages by calling things like - // Message::ParseFromString(). In this case, you will need to change - // your code to instead construct some sort of ZeroCopyInputStream - // (e.g. an ArrayInputStream), construct a CodedInputStream around - // that, then call Message::ParseFromCodedStream() instead. Then - // you can adjust the limit. Yes, it's more work, but you're doing - // something unusual. - void SetTotalBytesLimit(int total_bytes_limit, int warning_threshold); - - // The Total Bytes Limit minus the Current Position, or -1 if there - // is no Total Bytes Limit. + // This is unrelated to PushLimit()/PopLimit(). + void SetTotalBytesLimit(int total_bytes_limit); + + PROTOBUF_DEPRECATED_MSG( + "Please use the single parameter version of SetTotalBytesLimit(). The " + "second parameter is ignored.") + void SetTotalBytesLimit(int total_bytes_limit, int) { + SetTotalBytesLimit(total_bytes_limit); + } + + // The Total Bytes Limit minus the Current Position, or -1 if the total bytes + // limit is INT_MAX. int BytesUntilTotalBytesLimit() const; // Recursion Limit ------------------------------------------------- @@ -418,7 +414,9 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Sets the maximum recursion depth. The default is 100. void SetRecursionLimit(int limit); + int RecursionBudget() { return recursion_budget_; } + static int GetDefaultRecursionLimit() { return default_recursion_limit_; } // Increments the current recursion depth. Returns true if the depth is // under the limit, false if it has gone over. @@ -542,7 +540,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedInputStream); const uint8* buffer_; - const uint8* buffer_end_; // pointer to the end of the buffer. + const uint8* buffer_end_; // pointer to the end of the buffer. ZeroCopyInputStream* input_; int total_bytes_read_; // total bytes read from input_, including // the current buffer @@ -552,7 +550,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { int overflow_bytes_; // LastTagWas() stuff. - uint32 last_tag_; // result of last ReadTag() or ReadTagWithCutoff(). + uint32 last_tag_; // result of last ReadTag() or ReadTagWithCutoff(). // This is set true by ReadTag{Fallback/Slow}() if it is called when exactly // at EOF, or by ExpectAtEnd() when it returns true. This happens when we @@ -563,7 +561,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { bool aliasing_enabled_; // Limits - Limit current_limit_; // if position = -1, no limit is applied + Limit current_limit_; // if position = -1, no limit is applied // For simplicity, if the current buffer crosses a limit (either a normal // limit created by PushLimit() or the total bytes limit), buffer_size_ @@ -585,8 +583,6 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Recursion depth limit, set by SetRecursionLimit(). int recursion_limit_; - bool disable_strict_correctness_enforcement_; - // See SetExtensionRegistry(). const DescriptorPool* extension_pool_; MessageFactory* extension_factory_; @@ -638,7 +634,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // stream. uint32 ReadTagFallback(uint32 first_byte_or_zero); uint32 ReadTagSlow(); - bool ReadStringFallback(string* buffer, int size); + bool ReadStringFallback(std::string* buffer, int size); // Return the size of the buffer. int BufferSize() const; @@ -646,8 +642,365 @@ class LIBPROTOBUF_EXPORT CodedInputStream { static const int kDefaultTotalBytesLimit = INT_MAX; static int default_recursion_limit_; // 100 by default. + + friend class google::protobuf::ZeroCopyCodedInputStream; + friend class google::protobuf::internal::EpsCopyByteStream; +}; + +// EpsCopyOutputStream wraps a ZeroCopyOutputStream and exposes a new stream, +// which has the property you can write kSlopBytes (16 bytes) from the current +// position without bounds checks. The cursor into the stream is managed by +// the user of the class and is an explicit parameter in the methods. Careful +// use of this class, ie. keep ptr a local variable, eliminates the need to +// for the compiler to sync the ptr value between register and memory. +class PROTOBUF_EXPORT EpsCopyOutputStream { + public: + enum { kSlopBytes = 16 }; + + // Initialize from a stream. + EpsCopyOutputStream(ZeroCopyOutputStream* stream, bool deterministic, + uint8** pp) + : end_(buffer_), + stream_(stream), + is_serialization_deterministic_(deterministic) { + *pp = buffer_; + } + + // Only for array serialization. No overflow protection, end_ will be the + // pointed to the end of the array. When using this the total size is already + // known, so no need to maintain the slop region. + EpsCopyOutputStream(void* data, int size, bool deterministic) + : end_(static_cast(data) + size), + buffer_end_(nullptr), + stream_(nullptr), + is_serialization_deterministic_(deterministic) {} + + // Initialize from stream but with the first buffer already given (eager). + EpsCopyOutputStream(void* data, int size, ZeroCopyOutputStream* stream, + bool deterministic, uint8** pp) + : stream_(stream), is_serialization_deterministic_(deterministic) { + *pp = SetInitialBuffer(data, size); + } + + // Flush everything that's written into the underlying ZeroCopyOutputStream + // and trims the underlying stream to the location of ptr. + uint8* Trim(uint8* ptr); + + // After this it's guaranteed you can safely write kSlopBytes to ptr. This + // will never fail! The underlying stream can produce an error. Use HadError + // to check for errors. + PROTOBUF_MUST_USE_RESULT uint8* EnsureSpace(uint8* ptr) { + if (PROTOBUF_PREDICT_FALSE(ptr >= end_)) { + return EnsureSpaceFallback(ptr); + } + return ptr; + } + + uint8* WriteRaw(const void* data, int size, uint8* ptr) { + if (PROTOBUF_PREDICT_FALSE(end_ - ptr < size)) { + return WriteRawFallback(data, size, ptr); + } + std::memcpy(ptr, data, size); + return ptr + size; + } + // Writes the buffer specified by data, size to the stream. Possibly by + // aliasing the buffer (ie. not copying the data). The caller is responsible + // to make sure the buffer is alive for the duration of the + // ZeroCopyOutputStream. + uint8* WriteRawMaybeAliased(const void* data, int size, uint8* ptr) { + if (aliasing_enabled_) { + return WriteAliasedRaw(data, size, ptr); + } else { + return WriteRaw(data, size, ptr); + } + } + + + uint8* WriteStringMaybeAliased(uint32 num, const std::string& s, uint8* ptr) { + std::ptrdiff_t size = s.size(); + if (PROTOBUF_PREDICT_FALSE( + size >= 128 || end_ - ptr + 16 - TagSize(num << 3) - 1 < size)) { + return WriteStringMaybeAliasedOutline(num, s, ptr); + } + ptr = UnsafeVarint((num << 3) | 2, ptr); + *ptr++ = static_cast(size); + std::memcpy(ptr, s.data(), size); + return ptr + size; + } + uint8* WriteBytesMaybeAliased(uint32 num, const std::string& s, uint8* ptr) { + return WriteStringMaybeAliased(num, s, ptr); + } + + template + PROTOBUF_ALWAYS_INLINE uint8* WriteString(uint32 num, const T& s, + uint8* ptr) { + std::ptrdiff_t size = s.size(); + if (PROTOBUF_PREDICT_FALSE( + size >= 128 || end_ - ptr + 16 - TagSize(num << 3) - 1 < size)) { + return WriteStringOutline(num, s, ptr); + } + ptr = UnsafeVarint((num << 3) | 2, ptr); + *ptr++ = static_cast(size); + std::memcpy(ptr, s.data(), size); + return ptr + size; + } + template + uint8* WriteBytes(uint32 num, const T& s, uint8* ptr) { + return WriteString(num, s, ptr); + } + + template + PROTOBUF_ALWAYS_INLINE uint8* WriteInt32Packed(int num, const T& r, int size, + uint8* ptr) { + return WriteVarintPacked(num, r, size, ptr, Encode64); + } + template + PROTOBUF_ALWAYS_INLINE uint8* WriteUInt32Packed(int num, const T& r, int size, + uint8* ptr) { + return WriteVarintPacked(num, r, size, ptr, Encode32); + } + template + PROTOBUF_ALWAYS_INLINE uint8* WriteSInt32Packed(int num, const T& r, int size, + uint8* ptr) { + return WriteVarintPacked(num, r, size, ptr, ZigZagEncode32); + } + template + PROTOBUF_ALWAYS_INLINE uint8* WriteInt64Packed(int num, const T& r, int size, + uint8* ptr) { + return WriteVarintPacked(num, r, size, ptr, Encode64); + } + template + PROTOBUF_ALWAYS_INLINE uint8* WriteUInt64Packed(int num, const T& r, int size, + uint8* ptr) { + return WriteVarintPacked(num, r, size, ptr, Encode64); + } + template + PROTOBUF_ALWAYS_INLINE uint8* WriteSInt64Packed(int num, const T& r, int size, + uint8* ptr) { + return WriteVarintPacked(num, r, size, ptr, ZigZagEncode64); + } + template + PROTOBUF_ALWAYS_INLINE uint8* WriteEnumPacked(int num, const T& r, int size, + uint8* ptr) { + return WriteVarintPacked(num, r, size, ptr, Encode64); + } + + template + PROTOBUF_ALWAYS_INLINE uint8* WriteFixedPacked(int num, const T& r, + uint8* ptr) { + ptr = EnsureSpace(ptr); + constexpr auto element_size = sizeof(typename T::value_type); + auto size = r.size() * element_size; + ptr = WriteLengthDelim(num, size, ptr); + return WriteRawLittleEndian(r.data(), static_cast(size), + ptr); + } + + // Returns true if there was an underlying I/O error since this object was + // created. + bool HadError() const { return had_error_; } + + // Instructs the EpsCopyOutputStream to allow the underlying + // ZeroCopyOutputStream to hold pointers to the original structure instead of + // copying, if it supports it (i.e. output->AllowsAliasing() is true). If the + // underlying stream does not support aliasing, then enabling it has no + // affect. For now, this only affects the behavior of + // WriteRawMaybeAliased(). + // + // NOTE: It is caller's responsibility to ensure that the chunk of memory + // remains live until all of the data has been consumed from the stream. + void EnableAliasing(bool enabled); + + // See documentation on CodedOutputStream::SetSerializationDeterministic. + void SetSerializationDeterministic(bool value) { + is_serialization_deterministic_ = value; + } + + // See documentation on CodedOutputStream::IsSerializationDeterministic. + bool IsSerializationDeterministic() const { + return is_serialization_deterministic_; + } + + // The number of bytes written to the stream at position ptr, relative to the + // stream's overall position. + int64 ByteCount(uint8* ptr) const; + + + private: + uint8* end_; + uint8* buffer_end_ = buffer_; + uint8 buffer_[2 * kSlopBytes]; + ZeroCopyOutputStream* stream_; + bool had_error_ = false; + bool aliasing_enabled_ = false; // See EnableAliasing(). + bool is_serialization_deterministic_; + + uint8* EnsureSpaceFallback(uint8* ptr); + inline uint8* Next(); + int Flush(uint8* ptr); + std::ptrdiff_t GetSize(uint8* ptr) const { + GOOGLE_DCHECK(ptr <= end_ + kSlopBytes); // NOLINT + return end_ + kSlopBytes - ptr; + } + + uint8* Error() { + had_error_ = true; + // We use the patch buffer to always guarantee space to write to. + end_ = buffer_ + kSlopBytes; + return buffer_; + } + + static constexpr int TagSize(uint32 tag) { + return (tag < (1 << 7)) + ? 1 + : (tag < (1 << 14)) + ? 2 + : (tag < (1 << 21)) ? 3 : (tag < (1 << 28)) ? 4 : 5; + } + + PROTOBUF_ALWAYS_INLINE uint8* WriteTag(uint32 num, uint32 wt, uint8* ptr) { + GOOGLE_DCHECK(ptr < end_); // NOLINT + return UnsafeVarint((num << 3) | wt, ptr); + } + + PROTOBUF_ALWAYS_INLINE uint8* WriteLengthDelim(int num, uint32 size, + uint8* ptr) { + ptr = WriteTag(num, 2, ptr); + return UnsafeWriteSize(size, ptr); + } + + uint8* WriteRawFallback(const void* data, int size, uint8* ptr); + + uint8* WriteAliasedRaw(const void* data, int size, uint8* ptr); + + uint8* WriteStringMaybeAliasedOutline(uint32 num, const std::string& s, + uint8* ptr); + uint8* WriteStringOutline(uint32 num, const std::string& s, uint8* ptr); + + template + PROTOBUF_ALWAYS_INLINE uint8* WriteVarintPacked(int num, const T& r, int size, + uint8* ptr, const E& encode) { + ptr = EnsureSpace(ptr); + ptr = WriteLengthDelim(num, size, ptr); + auto it = r.data(); + auto end = it + r.size(); + do { + ptr = EnsureSpace(ptr); + ptr = UnsafeVarint(encode(*it++), ptr); + } while (it < end); + return ptr; + } + + static uint32 Encode32(uint32 v) { return v; } + static uint64 Encode64(uint64 v) { return v; } + static uint32 ZigZagEncode32(int32 v) { + return (static_cast(v) << 1) ^ static_cast(v >> 31); + } + static uint64 ZigZagEncode64(int64 v) { + return (static_cast(v) << 1) ^ static_cast(v >> 63); + } + + template + PROTOBUF_ALWAYS_INLINE static uint8* UnsafeVarint(T value, uint8* ptr) { + static_assert(std::is_unsigned::value, + "Varint serialization must be unsigned"); + if (value < 0x80) { + ptr[0] = static_cast(value); + return ptr + 1; + } + ptr[0] = static_cast(value | 0x80); + value >>= 7; + if (value < 0x80) { + ptr[1] = static_cast(value); + return ptr + 2; + } + ptr++; + do { + *ptr = static_cast(value | 0x80); + value >>= 7; + ++ptr; + } while (PROTOBUF_PREDICT_FALSE(value >= 0x80)); + *ptr++ = static_cast(value); + return ptr; + } + + PROTOBUF_ALWAYS_INLINE static uint8* UnsafeWriteSize(uint32 value, + uint8* ptr) { + while (PROTOBUF_PREDICT_FALSE(value >= 0x80)) { + *ptr = static_cast(value | 0x80); + value >>= 7; + ++ptr; + } + *ptr++ = static_cast(value); + return ptr; + } + + template + uint8* WriteRawLittleEndian(const void* data, int size, uint8* ptr); +#ifndef PROTOBUF_LITTLE_ENDIAN + uint8* WriteRawLittleEndian32(const void* data, int size, uint8* ptr); + uint8* WriteRawLittleEndian64(const void* data, int size, uint8* ptr); +#endif + + // These methods are for CodedOutputStream. Ideally they should be private + // but to match current behavior of CodedOutputStream as close as possible + // we allow it some functionality. + public: + uint8* SetInitialBuffer(void* data, int size) { + auto ptr = static_cast(data); + if (size > kSlopBytes) { + end_ = ptr + size - kSlopBytes; + buffer_end_ = nullptr; + return ptr; + } else { + end_ = buffer_ + size; + buffer_end_ = ptr; + return buffer_; + } + } + + private: + // Needed by CodedOutputStream HadError. HadError needs to flush the patch + // buffers to ensure there is no error as of yet. + uint8* FlushAndResetBuffer(uint8*); + + // The following functions mimic the old CodedOutputStream behavior as close + // as possible. They flush the current state to the stream, behave as + // the old CodedOutputStream and then return to normal operation. + bool Skip(int count, uint8** pp); + bool GetDirectBufferPointer(void** data, int* size, uint8** pp); + uint8* GetDirectBufferForNBytesAndAdvance(int size, uint8** pp); + + friend class CodedOutputStream; }; +template <> +inline uint8* EpsCopyOutputStream::WriteRawLittleEndian<1>(const void* data, + int size, + uint8* ptr) { + return WriteRaw(data, size, ptr); +} +template <> +inline uint8* EpsCopyOutputStream::WriteRawLittleEndian<4>(const void* data, + int size, + uint8* ptr) { +#ifdef PROTOBUF_LITTLE_ENDIAN + return WriteRaw(data, size, ptr); +#else + return WriteRawLittleEndian32(data, size, ptr); +#endif +} +template <> +inline uint8* EpsCopyOutputStream::WriteRawLittleEndian<8>(const void* data, + int size, + uint8* ptr) { +#ifdef PROTOBUF_LITTLE_ENDIAN + return WriteRaw(data, size, ptr); +#else + return WriteRawLittleEndian64(data, size, ptr); +#endif +} + // Class which encodes and writes binary data which is composed of varint- // encoded integers and fixed-width pieces. Wraps a ZeroCopyOutputStream. // Most users will not need to deal with CodedOutputStream. @@ -668,7 +1021,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // individual value. // i.e., in the example above: // -// CodedOutputStream coded_output = new CodedOutputStream(raw_output); +// CodedOutputStream* coded_output = new CodedOutputStream(raw_output); // int magic_number = 1234; // char text[] = "Hello world!"; // @@ -678,7 +1031,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // // uint8* buffer = // coded_output->GetDirectBufferForNBytesAndAdvance(coded_size); -// if (buffer != NULL) { +// if (buffer != nullptr) { // // The output stream has enough space in the buffer: write directly to // // the array. // buffer = CodedOutputStream::WriteLittleEndian32ToArray(magic_number, @@ -694,27 +1047,40 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // } // // delete coded_output; -class LIBPROTOBUF_EXPORT CodedOutputStream { +class PROTOBUF_EXPORT CodedOutputStream { public: // Create an CodedOutputStream that writes to the given ZeroCopyOutputStream. - explicit CodedOutputStream(ZeroCopyOutputStream* output); - CodedOutputStream(ZeroCopyOutputStream* output, bool do_eager_refresh); + explicit CodedOutputStream(ZeroCopyOutputStream* stream) + : CodedOutputStream(stream, true) {} + CodedOutputStream(ZeroCopyOutputStream* stream, bool do_eager_refresh); // Destroy the CodedOutputStream and position the underlying // ZeroCopyOutputStream immediately after the last byte written. ~CodedOutputStream(); + // Returns true if there was an underlying I/O error since this object was + // created. On should call Trim before this function in order to catch all + // errors. + bool HadError() { + cur_ = impl_.FlushAndResetBuffer(cur_); + GOOGLE_DCHECK(cur_); + return impl_.HadError(); + } + // Trims any unused space in the underlying buffer so that its size matches // the number of bytes written by this stream. The underlying buffer will // automatically be trimmed when this stream is destroyed; this call is only // necessary if the underlying buffer is accessed *before* the stream is // destroyed. - void Trim(); + void Trim() { cur_ = impl_.Trim(cur_); } // Skips a number of bytes, leaving the bytes unmodified in the underlying // buffer. Returns false if an underlying write error occurs. This is // mainly useful with GetDirectBufferPointer(). - bool Skip(int count); + // Note of caution, the skipped bytes may contain uninitialized data. The + // caller must make sure that the skipped bytes are properly initialized, + // otherwise you might leak bytes from your heap. + bool Skip(int count) { return impl_.Skip(count, &cur_); } // Sets *data to point directly at the unwritten part of the // CodedOutputStream's underlying buffer, and *size to the size of that @@ -724,7 +1090,9 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // the consumed bytes. This may be useful for implementing external fast // serialization routines for types of data not covered by the // CodedOutputStream interface. - bool GetDirectBufferPointer(void** data, int* size); + bool GetDirectBufferPointer(void** data, int* size) { + return impl_.GetDirectBufferPointer(data, size, &cur_); + } // If there are at least "size" bytes available in the current buffer, // returns a pointer directly into the buffer and advances over these bytes. @@ -733,10 +1101,14 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // there are not enough bytes available, returns NULL. The return pointer is // invalidated as soon as any other non-const method of CodedOutputStream // is called. - inline uint8* GetDirectBufferForNBytesAndAdvance(int size); + inline uint8* GetDirectBufferForNBytesAndAdvance(int size) { + return impl_.GetDirectBufferForNBytesAndAdvance(size, &cur_); + } // Write raw bytes, copying them from the given buffer. - void WriteRaw(const void* buffer, int size); + void WriteRaw(const void* buffer, int size) { + cur_ = impl_.WriteRaw(buffer, size, cur_); + } // Like WriteRaw() but will try to write aliased data if aliasing is // turned on. void WriteRawMaybeAliased(const void* data, int size); @@ -748,30 +1120,26 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { static uint8* WriteRawToArray(const void* buffer, int size, uint8* target); // Equivalent to WriteRaw(str.data(), str.size()). - void WriteString(const string& str); + void WriteString(const std::string& str); // Like WriteString() but writing directly to the target array. - static uint8* WriteStringToArray(const string& str, uint8* target); + static uint8* WriteStringToArray(const std::string& str, uint8* target); // Write the varint-encoded size of str followed by str. - static uint8* WriteStringWithSizeToArray(const string& str, uint8* target); + static uint8* WriteStringWithSizeToArray(const std::string& str, + uint8* target); - // Instructs the CodedOutputStream to allow the underlying - // ZeroCopyOutputStream to hold pointers to the original structure instead of - // copying, if it supports it (i.e. output->AllowsAliasing() is true). If the - // underlying stream does not support aliasing, then enabling it has no - // affect. For now, this only affects the behavior of - // WriteRawMaybeAliased(). - // - // NOTE: It is caller's responsibility to ensure that the chunk of memory - // remains live until all of the data has been consumed from the stream. - void EnableAliasing(bool enabled); - // Write a 32-bit little-endian integer. - void WriteLittleEndian32(uint32 value); + void WriteLittleEndian32(uint32 value) { + cur_ = impl_.EnsureSpace(cur_); + SetCur(WriteLittleEndian32ToArray(value, Cur())); + } // Like WriteLittleEndian32() but writing directly to the target array. static uint8* WriteLittleEndian32ToArray(uint32 value, uint8* target); // Write a 64-bit little-endian integer. - void WriteLittleEndian64(uint64 value); + void WriteLittleEndian64(uint64 value) { + cur_ = impl_.EnsureSpace(cur_); + SetCur(WriteLittleEndian64ToArray(value, Cur())); + } // Like WriteLittleEndian64() but writing directly to the target array. static uint8* WriteLittleEndian64ToArray(uint64 value, uint8* target); @@ -795,19 +1163,19 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // This is identical to WriteVarint32(), but optimized for writing tags. // In particular, if the input is a compile-time constant, this method // compiles down to a couple instructions. - // Always inline because otherwise the aformentioned optimization can't work, + // Always inline because otherwise the aforementioned optimization can't work, // but GCC by default doesn't want to inline this. void WriteTag(uint32 value); // Like WriteTag() but writing directly to the target array. - GOOGLE_ATTRIBUTE_ALWAYS_INLINE static uint8* WriteTagToArray(uint32 value, - uint8* target); + PROTOBUF_ALWAYS_INLINE + static uint8* WriteTagToArray(uint32 value, uint8* target); // Returns the number of bytes needed to encode the given value as a varint. static size_t VarintSize32(uint32 value); // Returns the number of bytes needed to encode the given value as a varint. static size_t VarintSize64(uint64 value); - // If negative, 10 bytes. Otheriwse, same as VarintSize32(). + // If negative, 10 bytes. Otherwise, same as VarintSize32(). static size_t VarintSize32SignExtended(int32 value); // Compile-time equivalent of VarintSize32(). @@ -817,93 +1185,73 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { (Value < (1 << 7)) ? 1 : (Value < (1 << 14)) - ? 2 - : (Value < (1 << 21)) - ? 3 - : (Value < (1 << 28)) - ? 4 - : 5; + ? 2 + : (Value < (1 << 21)) ? 3 : (Value < (1 << 28)) ? 4 : 5; }; // Returns the total number of bytes written since this object was created. - inline int ByteCount() const; + int ByteCount() const { + return static_cast(impl_.ByteCount(cur_) - start_count_); + } - // Returns true if there was an underlying I/O error since this object was - // created. - bool HadError() const { return had_error_; } + // Instructs the CodedOutputStream to allow the underlying + // ZeroCopyOutputStream to hold pointers to the original structure instead of + // copying, if it supports it (i.e. output->AllowsAliasing() is true). If the + // underlying stream does not support aliasing, then enabling it has no + // affect. For now, this only affects the behavior of + // WriteRawMaybeAliased(). + // + // NOTE: It is caller's responsibility to ensure that the chunk of memory + // remains live until all of the data has been consumed from the stream. + void EnableAliasing(bool enabled) { impl_.EnableAliasing(enabled); } - // Deterministic serialization, if requested, guarantees that for a given - // binary, equal messages will always be serialized to the same bytes. This - // implies: - // . repeated serialization of a message will return the same bytes - // . different processes of the same binary (which may be executing on - // different machines) will serialize equal messages to the same bytes. + // Indicate to the serializer whether the user wants derministic + // serialization. The default when this is not called comes from the global + // default, controlled by SetDefaultSerializationDeterministic. // - // Note the deterministic serialization is NOT canonical across languages; it - // is also unstable across different builds with schema changes due to unknown - // fields. Users who need canonical serialization, e.g., persistent storage in - // a canonical form, fingerprinting, etc., should define their own - // canonicalization specification and implement the serializer using - // reflection APIs rather than relying on this API. + // What deterministic serialization means is entirely up to the driver of the + // serialization process (i.e. the caller of methods like WriteVarint32). In + // the case of serializing a proto buffer message using one of the methods of + // MessageLite, this means that for a given binary equal messages will always + // be serialized to the same bytes. This implies: + // + // * Repeated serialization of a message will return the same bytes. // - // If determinisitc serialization is requested, the serializer will - // sort map entries by keys in lexicographical order or numerical order. - // (This is an implementation detail and may subject to change.) + // * Different processes running the same binary (including on different + // machines) will serialize equal messages to the same bytes. // - // There are two ways to determine whether serialization should be - // deterministic for this CodedOutputStream. If SetSerializationDeterministic - // has not yet been called, then the default comes from the global default, - // which is false, until SetDefaultSerializationDeterministic has been called. - // Otherwise, SetSerializationDeterministic has been called, and the last - // value passed to it is all that matters. + // Note that this is *not* canonical across languages. It is also unstable + // across different builds with intervening message definition changes, due to + // unknown fields. Users who need canonical serialization (e.g. persistent + // storage in a canonical form, fingerprinting) should define their own + // canonicalization specification and implement the serializer using + // reflection APIs rather than relying on this API. void SetSerializationDeterministic(bool value) { - serialization_deterministic_is_overridden_ = true; - serialization_deterministic_override_ = value; + impl_.SetSerializationDeterministic(value); } - // See above. Also, note that users of this CodedOutputStream may need to - // call IsSerializationDeterministic() to serialize in the intended way. This - // CodedOutputStream cannot enforce a desire for deterministic serialization - // by itself. + + // Return whether the user wants deterministic serialization. See above. bool IsSerializationDeterministic() const { - return serialization_deterministic_is_overridden_ ? - serialization_deterministic_override_ : - default_serialization_deterministic_; + return impl_.IsSerializationDeterministic(); } static bool IsDefaultSerializationDeterministic() { - return google::protobuf::internal::Acquire_Load(&default_serialization_deterministic_); + return default_serialization_deterministic_.load( + std::memory_order_relaxed) != 0; } - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedOutputStream); - - ZeroCopyOutputStream* output_; - uint8* buffer_; - int buffer_size_; - int total_bytes_; // Sum of sizes of all buffers seen so far. - bool had_error_; // Whether an error occurred during output. - bool aliasing_enabled_; // See EnableAliasing(). - // See SetSerializationDeterministic() regarding these three fields. - bool serialization_deterministic_is_overridden_; - bool serialization_deterministic_override_; - // Conceptually, default_serialization_deterministic_ is an atomic bool. - static google::protobuf::internal::AtomicWord default_serialization_deterministic_; - - // Advance the buffer by a given number of bytes. - void Advance(int amount); - - // Called when the buffer runs out to request more data. Implies an - // Advance(buffer_size_). - bool Refresh(); + template + void Serialize(const Func& func); - // Like WriteRaw() but may avoid copying if the underlying - // ZeroCopyOutputStream supports it. - void WriteAliasedRaw(const void* buffer, int size); + uint8* Cur() const { return cur_; } + void SetCur(uint8* ptr) { cur_ = ptr; } + EpsCopyOutputStream* EpsCopy() { return &impl_; } - // If this write might cross the end of the buffer, we compose the bytes first - // then use WriteRaw(). - void WriteVarint32SlowPath(uint32 value); - void WriteVarint64SlowPath(uint64 value); + private: + EpsCopyOutputStream impl_; + uint8* cur_; + int64 start_count_; + static std::atomic default_serialization_deterministic_; // See above. Other projects may use "friend" to allow them to call this. // After SetDefaultSerializationDeterministic() completes, all protocol @@ -912,10 +1260,11 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // that wants deterministic serialization by default needs to call // SetDefaultSerializationDeterministic() or ensure on its own that another // thread has done so. - friend void ::google::protobuf::internal::MapTestForceDeterministic(); + friend void internal::MapTestForceDeterministic(); static void SetDefaultSerializationDeterministic() { - google::protobuf::internal::Release_Store(&default_serialization_deterministic_, 1); + default_serialization_deterministic_.store(true, std::memory_order_relaxed); } + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedOutputStream); }; // inline methods ==================================================== @@ -924,7 +1273,7 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { inline bool CodedInputStream::ReadVarint32(uint32* value) { uint32 v = 0; - if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) { + if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) { v = *buffer_; if (v < 0x80) { *value = v; @@ -938,7 +1287,7 @@ inline bool CodedInputStream::ReadVarint32(uint32* value) { } inline bool CodedInputStream::ReadVarint64(uint64* value) { - if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) { + if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) { *value = *buffer_; Advance(1); return true; @@ -949,7 +1298,7 @@ inline bool CodedInputStream::ReadVarint64(uint64* value) { } inline bool CodedInputStream::ReadVarintSizeAsInt(int* value) { - if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) { + if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) { int v = *buffer_; if (v < 0x80) { *value = v; @@ -963,14 +1312,13 @@ inline bool CodedInputStream::ReadVarintSizeAsInt(int* value) { // static inline const uint8* CodedInputStream::ReadLittleEndian32FromArray( - const uint8* buffer, - uint32* value) { + const uint8* buffer, uint32* value) { #if defined(PROTOBUF_LITTLE_ENDIAN) memcpy(value, buffer, sizeof(*value)); return buffer + sizeof(*value); #else - *value = (static_cast(buffer[0]) ) | - (static_cast(buffer[1]) << 8) | + *value = (static_cast(buffer[0])) | + (static_cast(buffer[1]) << 8) | (static_cast(buffer[2]) << 16) | (static_cast(buffer[3]) << 24); return buffer + sizeof(*value); @@ -978,29 +1326,27 @@ inline const uint8* CodedInputStream::ReadLittleEndian32FromArray( } // static inline const uint8* CodedInputStream::ReadLittleEndian64FromArray( - const uint8* buffer, - uint64* value) { + const uint8* buffer, uint64* value) { #if defined(PROTOBUF_LITTLE_ENDIAN) memcpy(value, buffer, sizeof(*value)); return buffer + sizeof(*value); #else - uint32 part0 = (static_cast(buffer[0]) ) | - (static_cast(buffer[1]) << 8) | + uint32 part0 = (static_cast(buffer[0])) | + (static_cast(buffer[1]) << 8) | (static_cast(buffer[2]) << 16) | (static_cast(buffer[3]) << 24); - uint32 part1 = (static_cast(buffer[4]) ) | - (static_cast(buffer[5]) << 8) | + uint32 part1 = (static_cast(buffer[4])) | + (static_cast(buffer[5]) << 8) | (static_cast(buffer[6]) << 16) | (static_cast(buffer[7]) << 24); - *value = static_cast(part0) | - (static_cast(part1) << 32); + *value = static_cast(part0) | (static_cast(part1) << 32); return buffer + sizeof(*value); #endif } inline bool CodedInputStream::ReadLittleEndian32(uint32* value) { #if defined(PROTOBUF_LITTLE_ENDIAN) - if (GOOGLE_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { + if (PROTOBUF_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { buffer_ = ReadLittleEndian32FromArray(buffer_, value); return true; } else { @@ -1013,7 +1359,7 @@ inline bool CodedInputStream::ReadLittleEndian32(uint32* value) { inline bool CodedInputStream::ReadLittleEndian64(uint64* value) { #if defined(PROTOBUF_LITTLE_ENDIAN) - if (GOOGLE_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { + if (PROTOBUF_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { buffer_ = ReadLittleEndian64FromArray(buffer_, value); return true; } else { @@ -1026,7 +1372,7 @@ inline bool CodedInputStream::ReadLittleEndian64(uint64* value) { inline uint32 CodedInputStream::ReadTagNoLastTag() { uint32 v = 0; - if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) { + if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) { v = *buffer_; if (v < 0x80) { Advance(1); @@ -1043,7 +1389,7 @@ inline std::pair CodedInputStream::ReadTagWithCutoffNoLastTag( // constant, and things like "cutoff >= kMax1ByteVarint" to be evaluated at // compile time. uint32 first_byte_or_zero = 0; - if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) { + if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) { // Hot case: buffer_ non_empty, buffer_[0] in [1, 128). // TODO(gpike): Is it worth rearranging this? E.g., if the number of fields // is large enough then is it better to check for the two-byte case first? @@ -1057,9 +1403,8 @@ inline std::pair CodedInputStream::ReadTagWithCutoffNoLastTag( // Other hot case: cutoff >= 0x80, buffer_ has at least two bytes available, // and tag is two bytes. The latter is tested by bitwise-and-not of the // first byte and the second byte. - if (cutoff >= 0x80 && - GOOGLE_PREDICT_TRUE(buffer_ + 1 < buffer_end_) && - GOOGLE_PREDICT_TRUE((buffer_[0] & ~buffer_[1]) >= 0x80)) { + if (cutoff >= 0x80 && PROTOBUF_PREDICT_TRUE(buffer_ + 1 < buffer_end_) && + PROTOBUF_PREDICT_TRUE((buffer_[0] & ~buffer_[1]) >= 0x80)) { const uint32 kMax2ByteVarint = (0x7f << 7) + 0x7f; uint32 tag = (1u << 7) * buffer_[1] + (buffer_[0] - 0x80); Advance(2); @@ -1088,14 +1433,15 @@ inline bool CodedInputStream::ConsumedEntireMessage() { inline bool CodedInputStream::ExpectTag(uint32 expected) { if (expected < (1 << 7)) { - if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && buffer_[0] == expected) { + if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_) && + buffer_[0] == expected) { Advance(1); return true; } else { return false; } } else if (expected < (1 << 14)) { - if (GOOGLE_PREDICT_TRUE(BufferSize() >= 2) && + if (PROTOBUF_PREDICT_TRUE(BufferSize() >= 2) && buffer_[0] == static_cast(expected | 0x80) && buffer_[1] == static_cast(expected >> 7)) { Advance(2); @@ -1109,8 +1455,8 @@ inline bool CodedInputStream::ExpectTag(uint32 expected) { } } -inline const uint8* CodedInputStream::ExpectTagFromArray( - const uint8* buffer, uint32 expected) { +inline const uint8* CodedInputStream::ExpectTagFromArray(const uint8* buffer, + uint32 expected) { if (expected < (1 << 7)) { if (buffer[0] == expected) { return buffer + 1; @@ -1121,7 +1467,7 @@ inline const uint8* CodedInputStream::ExpectTagFromArray( return buffer + 2; } } - return NULL; + return nullptr; } inline void CodedInputStream::GetDirectBufferPointerInline(const void** data, @@ -1134,9 +1480,8 @@ inline bool CodedInputStream::ExpectAtEnd() { // If we are at a limit we know no more bytes can be read. Otherwise, it's // hard to say without calling Refresh(), and we'd rather not do that. - if (buffer_ == buffer_end_ && - ((buffer_size_after_limit_ != 0) || - (total_bytes_read_ == current_limit_))) { + if (buffer_ == buffer_end_ && ((buffer_size_after_limit_ != 0) || + (total_bytes_read_ == current_limit_))) { last_tag_ = 0; // Pretend we called ReadTag()... legitimate_message_end_ = true; // ... and it hit EOF. return true; @@ -1149,36 +1494,109 @@ inline int CodedInputStream::CurrentPosition() const { return total_bytes_read_ - (BufferSize() + buffer_size_after_limit_); } -inline uint8* CodedOutputStream::GetDirectBufferForNBytesAndAdvance(int size) { - if (buffer_size_ < size) { - return NULL; - } else { - uint8* result = buffer_; - Advance(size); - return result; +inline void CodedInputStream::Advance(int amount) { buffer_ += amount; } + +inline void CodedInputStream::SetRecursionLimit(int limit) { + recursion_budget_ += limit - recursion_limit_; + recursion_limit_ = limit; +} + +inline bool CodedInputStream::IncrementRecursionDepth() { + --recursion_budget_; + return recursion_budget_ >= 0; +} + +inline void CodedInputStream::DecrementRecursionDepth() { + if (recursion_budget_ < recursion_limit_) ++recursion_budget_; +} + +inline void CodedInputStream::UnsafeDecrementRecursionDepth() { + assert(recursion_budget_ < recursion_limit_); + ++recursion_budget_; +} + +inline void CodedInputStream::SetExtensionRegistry(const DescriptorPool* pool, + MessageFactory* factory) { + extension_pool_ = pool; + extension_factory_ = factory; +} + +inline const DescriptorPool* CodedInputStream::GetExtensionPool() { + return extension_pool_; +} + +inline MessageFactory* CodedInputStream::GetExtensionFactory() { + return extension_factory_; +} + +inline int CodedInputStream::BufferSize() const { + return static_cast(buffer_end_ - buffer_); +} + +inline CodedInputStream::CodedInputStream(ZeroCopyInputStream* input) + : buffer_(nullptr), + buffer_end_(nullptr), + input_(input), + total_bytes_read_(0), + overflow_bytes_(0), + last_tag_(0), + legitimate_message_end_(false), + aliasing_enabled_(false), + current_limit_(kint32max), + buffer_size_after_limit_(0), + total_bytes_limit_(kDefaultTotalBytesLimit), + recursion_budget_(default_recursion_limit_), + recursion_limit_(default_recursion_limit_), + extension_pool_(nullptr), + extension_factory_(nullptr) { + // Eagerly Refresh() so buffer space is immediately available. + Refresh(); +} + +inline CodedInputStream::CodedInputStream(const uint8* buffer, int size) + : buffer_(buffer), + buffer_end_(buffer + size), + input_(nullptr), + total_bytes_read_(size), + overflow_bytes_(0), + last_tag_(0), + legitimate_message_end_(false), + aliasing_enabled_(false), + current_limit_(size), + buffer_size_after_limit_(0), + total_bytes_limit_(kDefaultTotalBytesLimit), + recursion_budget_(default_recursion_limit_), + recursion_limit_(default_recursion_limit_), + extension_pool_(nullptr), + extension_factory_(nullptr) { + // Note that setting current_limit_ == size is important to prevent some + // code paths from trying to access input_ and segfaulting. +} + +inline bool CodedInputStream::IsFlat() const { return input_ == nullptr; } + +inline bool CodedInputStream::Skip(int count) { + if (count < 0) return false; // security: count is often user-supplied + + const int original_buffer_size = BufferSize(); + + if (count <= original_buffer_size) { + // Just skipping within the current buffer. Easy. + Advance(count); + return true; } + + return SkipFallback(count, original_buffer_size); } inline uint8* CodedOutputStream::WriteVarint32ToArray(uint32 value, uint8* target) { - while (value >= 0x80) { - *target = static_cast(value | 0x80); - value >>= 7; - ++target; - } - *target = static_cast(value); - return target + 1; + return EpsCopyOutputStream::UnsafeVarint(value, target); } inline uint8* CodedOutputStream::WriteVarint64ToArray(uint64 value, uint8* target) { - while (value >= 0x80) { - *target = static_cast(value | 0x80); - value >>= 7; - ++target; - } - *target = static_cast(value); - return target + 1; + return EpsCopyOutputStream::UnsafeVarint(value, target); } inline void CodedOutputStream::WriteVarint32SignExtended(int32 value) { @@ -1196,7 +1614,7 @@ inline uint8* CodedOutputStream::WriteLittleEndian32ToArray(uint32 value, memcpy(target, &value, sizeof(value)); #else target[0] = static_cast(value); - target[1] = static_cast(value >> 8); + target[1] = static_cast(value >> 8); target[2] = static_cast(value >> 16); target[3] = static_cast(value >> 24); #endif @@ -1212,11 +1630,11 @@ inline uint8* CodedOutputStream::WriteLittleEndian64ToArray(uint64 value, uint32 part1 = static_cast(value >> 32); target[0] = static_cast(part0); - target[1] = static_cast(part0 >> 8); + target[1] = static_cast(part0 >> 8); target[2] = static_cast(part0 >> 16); target[3] = static_cast(part0 >> 24); target[4] = static_cast(part1); - target[5] = static_cast(part1 >> 8); + target[5] = static_cast(part1 >> 8); target[6] = static_cast(part1 >> 16); target[7] = static_cast(part1 >> 24); #endif @@ -1224,37 +1642,18 @@ inline uint8* CodedOutputStream::WriteLittleEndian64ToArray(uint64 value, } inline void CodedOutputStream::WriteVarint32(uint32 value) { - if (buffer_size_ >= 5) { - // Fast path: We have enough bytes left in the buffer to guarantee that - // this write won't cross the end, so we can skip the checks. - uint8* target = buffer_; - uint8* end = WriteVarint32ToArray(value, target); - int size = static_cast(end - target); - Advance(size); - } else { - WriteVarint32SlowPath(value); - } + cur_ = impl_.EnsureSpace(cur_); + SetCur(WriteVarint32ToArray(value, Cur())); } inline void CodedOutputStream::WriteVarint64(uint64 value) { - if (buffer_size_ >= 10) { - // Fast path: We have enough bytes left in the buffer to guarantee that - // this write won't cross the end, so we can skip the checks. - uint8* target = buffer_; - uint8* end = WriteVarint64ToArray(value, target); - int size = static_cast(end - target); - Advance(size); - } else { - WriteVarint64SlowPath(value); - } + cur_ = impl_.EnsureSpace(cur_); + SetCur(WriteVarint64ToArray(value, Cur())); } -inline void CodedOutputStream::WriteTag(uint32 value) { - WriteVarint32(value); -} +inline void CodedOutputStream::WriteTag(uint32 value) { WriteVarint32(value); } -inline uint8* CodedOutputStream::WriteTagToArray( - uint32 value, uint8* target) { +inline uint8* CodedOutputStream::WriteTagToArray(uint32 value, uint8* target) { return WriteVarint32ToArray(value, target); } @@ -1280,147 +1679,40 @@ inline size_t CodedOutputStream::VarintSize64(uint64 value) { inline size_t CodedOutputStream::VarintSize32SignExtended(int32 value) { if (value < 0) { - return 10; // TODO(kenton): Make this a symbolic constant. + return 10; // TODO(kenton): Make this a symbolic constant. } else { return VarintSize32(static_cast(value)); } } -inline void CodedOutputStream::WriteString(const string& str) { +inline void CodedOutputStream::WriteString(const std::string& str) { WriteRaw(str.data(), static_cast(str.size())); } -inline void CodedOutputStream::WriteRawMaybeAliased( - const void* data, int size) { - if (aliasing_enabled_) { - WriteAliasedRaw(data, size); - } else { - WriteRaw(data, size); - } -} - -inline uint8* CodedOutputStream::WriteStringToArray( - const string& str, uint8* target) { - return WriteRawToArray(str.data(), static_cast(str.size()), target); -} - -inline int CodedOutputStream::ByteCount() const { - return total_bytes_ - buffer_size_; -} - -inline void CodedInputStream::Advance(int amount) { - buffer_ += amount; -} - -inline void CodedOutputStream::Advance(int amount) { - buffer_ += amount; - buffer_size_ -= amount; -} - -inline void CodedInputStream::SetRecursionLimit(int limit) { - recursion_budget_ += limit - recursion_limit_; - recursion_limit_ = limit; -} - -inline bool CodedInputStream::IncrementRecursionDepth() { - --recursion_budget_; - return recursion_budget_ >= 0; -} - -inline void CodedInputStream::DecrementRecursionDepth() { - if (recursion_budget_ < recursion_limit_) ++recursion_budget_; -} - -inline void CodedInputStream::UnsafeDecrementRecursionDepth() { - assert(recursion_budget_ < recursion_limit_); - ++recursion_budget_; +inline void CodedOutputStream::WriteRawMaybeAliased(const void* data, + int size) { + cur_ = impl_.WriteRawMaybeAliased(data, size, cur_); } -inline void CodedInputStream::SetExtensionRegistry(const DescriptorPool* pool, - MessageFactory* factory) { - extension_pool_ = pool; - extension_factory_ = factory; +inline uint8* CodedOutputStream::WriteRawToArray(const void* data, int size, + uint8* target) { + memcpy(target, data, size); + return target + size; } -inline const DescriptorPool* CodedInputStream::GetExtensionPool() { - return extension_pool_; -} - -inline MessageFactory* CodedInputStream::GetExtensionFactory() { - return extension_factory_; -} - -inline int CodedInputStream::BufferSize() const { - return static_cast(buffer_end_ - buffer_); -} - -inline CodedInputStream::CodedInputStream(ZeroCopyInputStream* input) - : buffer_(NULL), - buffer_end_(NULL), - input_(input), - total_bytes_read_(0), - overflow_bytes_(0), - last_tag_(0), - legitimate_message_end_(false), - aliasing_enabled_(false), - current_limit_(kint32max), - buffer_size_after_limit_(0), - total_bytes_limit_(kDefaultTotalBytesLimit), - recursion_budget_(default_recursion_limit_), - recursion_limit_(default_recursion_limit_), - disable_strict_correctness_enforcement_(true), - extension_pool_(NULL), - extension_factory_(NULL) { - // Eagerly Refresh() so buffer space is immediately available. - Refresh(); -} - -inline CodedInputStream::CodedInputStream(const uint8* buffer, int size) - : buffer_(buffer), - buffer_end_(buffer + size), - input_(NULL), - total_bytes_read_(size), - overflow_bytes_(0), - last_tag_(0), - legitimate_message_end_(false), - aliasing_enabled_(false), - current_limit_(size), - buffer_size_after_limit_(0), - total_bytes_limit_(kDefaultTotalBytesLimit), - recursion_budget_(default_recursion_limit_), - recursion_limit_(default_recursion_limit_), - disable_strict_correctness_enforcement_(true), - extension_pool_(NULL), - extension_factory_(NULL) { - // Note that setting current_limit_ == size is important to prevent some - // code paths from trying to access input_ and segfaulting. -} - -inline bool CodedInputStream::IsFlat() const { - return input_ == NULL; -} - -inline bool CodedInputStream::Skip(int count) { - if (count < 0) return false; // security: count is often user-supplied - - const int original_buffer_size = BufferSize(); - - if (count <= original_buffer_size) { - // Just skipping within the current buffer. Easy. - Advance(count); - return true; - } - - return SkipFallback(count, original_buffer_size); +inline uint8* CodedOutputStream::WriteStringToArray(const std::string& str, + uint8* target) { + return WriteRawToArray(str.data(), static_cast(str.size()), target); } } // namespace io } // namespace protobuf - +} // namespace google #if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) - #pragma runtime_checks("c", restore) +#pragma runtime_checks("c", restore) #endif // _MSC_VER && !defined(__INTEL_COMPILER) -} // namespace google +#include + #endif // GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ diff --git a/src/google/protobuf/io/coded_stream_inl.h b/src/google/protobuf/io/coded_stream_inl.h deleted file mode 100644 index d95b06e04e531..0000000000000 --- a/src/google/protobuf/io/coded_stream_inl.h +++ /dev/null @@ -1,90 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: jasonh@google.com (Jason Hsueh) -// -// Implements methods of coded_stream.h that need to be inlined for performance -// reasons, but should not be defined in a public header. - -#ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__ -#define GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__ - -#include -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace io { - -inline bool CodedInputStream::InternalReadStringInline(string* buffer, - int size) { - if (size < 0) return false; // security: size is often user-supplied - - if (BufferSize() >= size) { - STLStringResizeUninitialized(buffer, size); - std::pair z = as_string_data(buffer); - if (z.second) { - // Oddly enough, memcpy() requires its first two args to be non-NULL even - // if we copy 0 bytes. So, we have ensured that z.first is non-NULL here. - GOOGLE_DCHECK(z.first != NULL); - memcpy(z.first, buffer_, size); - Advance(size); - } - return true; - } - - return ReadStringFallback(buffer, size); -} - -inline bool CodedInputStream::InternalReadRawInline(void* buffer, int size) { - int current_buffer_size; - while ((current_buffer_size = BufferSize()) < size) { - // Reading past end of buffer. Copy what we have, then refresh. - memcpy(buffer, buffer_, current_buffer_size); - buffer = reinterpret_cast(buffer) + current_buffer_size; - size -= current_buffer_size; - Advance(current_buffer_size); - if (!Refresh()) return false; - } - - memcpy(buffer, buffer_, size); - Advance(size); - - return true; -} - -} // namespace io -} // namespace protobuf -} // namespace google -#endif // GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__ diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc index 96f91ae91c2d3..d2f8959c7b7a6 100644 --- a/src/google/protobuf/io/coded_stream_unittest.cc +++ b/src/google/protobuf/io/coded_stream_unittest.cc @@ -34,31 +34,30 @@ // // This file contains tests and benchmarks. -#include -#ifndef _SHARED_PTR_H -#include -#endif -#include - #include #include +#include +#include + #include #include #include +#include #include #include -#include +#include +#include // This declares an unsigned long long integer literal in a portable way. // (The original macro is way too big and ruins my formatting.) #undef ULL -#define ULL(x) GOOGLE_ULONGLONG(x) +#define ULL(x) PROTOBUF_ULONGLONG(x) -namespace google { +namespace google { namespace protobuf { namespace io { namespace { @@ -87,59 +86,53 @@ namespace { // TODO(kenton): gTest now supports "parameterized tests" which would be // a better way to accomplish this. Rewrite when time permits. -#define TEST_1D(FIXTURE, NAME, CASES) \ - class FIXTURE##_##NAME##_DD : public FIXTURE { \ - protected: \ - template \ - void DoSingleCase(const CaseType& CASES##_case); \ - }; \ - \ - TEST_F(FIXTURE##_##NAME##_DD, NAME) { \ - for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES); i++) { \ - SCOPED_TRACE(testing::Message() \ - << #CASES " case #" << i << ": " << CASES[i]); \ - DoSingleCase(CASES[i]); \ - } \ - } \ - \ - template \ +#define TEST_1D(FIXTURE, NAME, CASES) \ + class FIXTURE##_##NAME##_DD : public FIXTURE { \ + protected: \ + template \ + void DoSingleCase(const CaseType& CASES##_case); \ + }; \ + \ + TEST_F(FIXTURE##_##NAME##_DD, NAME) { \ + for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES); i++) { \ + SCOPED_TRACE(testing::Message() \ + << #CASES " case #" << i << ": " << CASES[i]); \ + DoSingleCase(CASES[i]); \ + } \ + } \ + \ + template \ void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType& CASES##_case) -#define TEST_2D(FIXTURE, NAME, CASES1, CASES2) \ - class FIXTURE##_##NAME##_DD : public FIXTURE { \ - protected: \ - template \ - void DoSingleCase(const CaseType1& CASES1##_case, \ - const CaseType2& CASES2##_case); \ - }; \ - \ - TEST_F(FIXTURE##_##NAME##_DD, NAME) { \ - for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES1); i++) { \ - for (int j = 0; j < GOOGLE_ARRAYSIZE(CASES2); j++) { \ - SCOPED_TRACE(testing::Message() \ - << #CASES1 " case #" << i << ": " << CASES1[i] << ", " \ - << #CASES2 " case #" << j << ": " << CASES2[j]); \ - DoSingleCase(CASES1[i], CASES2[j]); \ - } \ - } \ - } \ - \ - template \ - void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType1& CASES1##_case, \ +#define TEST_2D(FIXTURE, NAME, CASES1, CASES2) \ + class FIXTURE##_##NAME##_DD : public FIXTURE { \ + protected: \ + template \ + void DoSingleCase(const CaseType1& CASES1##_case, \ + const CaseType2& CASES2##_case); \ + }; \ + \ + TEST_F(FIXTURE##_##NAME##_DD, NAME) { \ + for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES1); i++) { \ + for (int j = 0; j < GOOGLE_ARRAYSIZE(CASES2); j++) { \ + SCOPED_TRACE(testing::Message() \ + << #CASES1 " case #" << i << ": " << CASES1[i] << ", " \ + << #CASES2 " case #" << j << ": " << CASES2[j]); \ + DoSingleCase(CASES1[i], CASES2[j]); \ + } \ + } \ + } \ + \ + template \ + void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType1& CASES1##_case, \ const CaseType2& CASES2##_case) // =================================================================== class CodedStreamTest : public testing::Test { protected: - // Helper method used by tests for bytes warning. See implementation comment - // for further information. - static void SetupTotalBytesLimitWarningTest( - int total_bytes_limit, int warning_threshold, - std::vector* out_errors, std::vector* out_warnings); - // Buffer used during most of the tests. This assumes tests run sequentially. - static const int kBufferSize = 1024 * 64; + static constexpr int kBufferSize = 1024 * 64; static uint8 buffer_[kBufferSize]; }; @@ -157,9 +150,9 @@ const int kBlockSizes[] = {1, 2, 3, 5, 7, 13, 32, 1024}; // Varint tests. struct VarintCase { - uint8 bytes[10]; // Encoded bytes. - int size; // Encoded size, in bytes. - uint64 value; // Parsed value. + uint8 bytes[10]; // Encoded bytes. + int size; // Encoded size, in bytes. + uint64 value; // Parsed value. }; inline std::ostream& operator<<(std::ostream& os, const VarintCase& c) { @@ -167,28 +160,32 @@ inline std::ostream& operator<<(std::ostream& os, const VarintCase& c) { } VarintCase kVarintCases[] = { - // 32-bit values - {{0x00} , 1, 0}, - {{0x01} , 1, 1}, - {{0x7f} , 1, 127}, - {{0xa2, 0x74}, 2, (0x22 << 0) | (0x74 << 7)}, // 14882 - {{0xbe, 0xf7, 0x92, 0x84, 0x0b}, 5, // 2961488830 - (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | - (ULL(0x0b) << 28)}, - - // 64-bit - {{0xbe, 0xf7, 0x92, 0x84, 0x1b}, 5, // 7256456126 - (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | - (ULL(0x1b) << 28)}, - {{0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49}, 8, // 41256202580718336 - (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) | - (ULL(0x43) << 28) | (ULL(0x49) << 35) | (ULL(0x24) << 42) | - (ULL(0x49) << 49)}, - // 11964378330978735131 - {{0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01}, 10, - (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) | - (ULL(0x3b) << 28) | (ULL(0x56) << 35) | (ULL(0x00) << 42) | - (ULL(0x05) << 49) | (ULL(0x26) << 56) | (ULL(0x01) << 63)}, + // 32-bit values + {{0x00}, 1, 0}, + {{0x01}, 1, 1}, + {{0x7f}, 1, 127}, + {{0xa2, 0x74}, 2, (0x22 << 0) | (0x74 << 7)}, // 14882 + {{0xbe, 0xf7, 0x92, 0x84, 0x0b}, + 5, // 2961488830 + (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | + (ULL(0x0b) << 28)}, + + // 64-bit + {{0xbe, 0xf7, 0x92, 0x84, 0x1b}, + 5, // 7256456126 + (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | + (ULL(0x1b) << 28)}, + {{0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49}, + 8, // 41256202580718336 + (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) | + (ULL(0x43) << 28) | (ULL(0x49) << 35) | (ULL(0x24) << 42) | + (ULL(0x49) << 49)}, + // 11964378330978735131 + {{0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01}, + 10, + (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) | + (ULL(0x3b) << 28) | (ULL(0x56) << 35) | (ULL(0x00) << 42) | + (ULL(0x05) << 49) | (ULL(0x26) << 56) | (ULL(0x01) << 63)}, }; TEST_2D(CodedStreamTest, ReadVarint32, kVarintCases, kBlockSizes) { @@ -229,20 +226,19 @@ TEST_F(CodedStreamTest, EmptyInputBeforeEos) { class In : public ZeroCopyInputStream { public: In() : count_(0) {} + private: - virtual bool Next(const void** data, int* size) { + bool Next(const void** data, int* size) override { *data = NULL; *size = 0; return count_++ < 2; } - virtual void BackUp(int count) { - GOOGLE_LOG(FATAL) << "Tests never call this."; - } - virtual bool Skip(int count) { + void BackUp(int count) override { GOOGLE_LOG(FATAL) << "Tests never call this."; } + bool Skip(int count) override { GOOGLE_LOG(FATAL) << "Tests never call this."; return false; } - virtual int64 ByteCount() const { return 0; } + int64_t ByteCount() const override { return 0; } int count_; } in; CodedInputStream input(&in); @@ -291,9 +287,8 @@ TEST_1D(CodedStreamTest, ExpectTagFromArray, kVarintCases) { // If the expectation succeeds, it should return a pointer past the tag. if (kVarintCases_case.size <= 2) { - EXPECT_TRUE(NULL == - CodedInputStream::ExpectTagFromArray(buffer_, - expected_value + 1)); + EXPECT_TRUE(NULL == CodedInputStream::ExpectTagFromArray( + buffer_, expected_value + 1)); EXPECT_TRUE(buffer_ + kVarintCases_case.size == CodedInputStream::ExpectTagFromArray(buffer_, expected_value)); } else { @@ -336,7 +331,7 @@ TEST_2D(CodedStreamTest, WriteVarint32, kVarintCases, kBlockSizes) { EXPECT_EQ(kVarintCases_case.size, output.ByteCount()); EXPECT_EQ(0, - memcmp(buffer_, kVarintCases_case.bytes, kVarintCases_case.size)); + memcmp(buffer_, kVarintCases_case.bytes, kVarintCases_case.size)); } TEST_2D(CodedStreamTest, WriteVarint64, kVarintCases, kBlockSizes) { @@ -353,19 +348,17 @@ TEST_2D(CodedStreamTest, WriteVarint64, kVarintCases, kBlockSizes) { EXPECT_EQ(kVarintCases_case.size, output.ByteCount()); EXPECT_EQ(0, - memcmp(buffer_, kVarintCases_case.bytes, kVarintCases_case.size)); + memcmp(buffer_, kVarintCases_case.bytes, kVarintCases_case.size)); } // This test causes gcc 3.3.5 (and earlier?) to give the cryptic error: // "sorry, unimplemented: `method_call_expr' not supported by dump_expr" #if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3) -int32 kSignExtendedVarintCases[] = { - 0, 1, -1, 1237894, -37895138 -}; +int32 kSignExtendedVarintCases[] = {0, 1, -1, 1237894, -37895138}; -TEST_2D(CodedStreamTest, WriteVarint32SignExtended, - kSignExtendedVarintCases, kBlockSizes) { +TEST_2D(CodedStreamTest, WriteVarint32SignExtended, kSignExtendedVarintCases, + kBlockSizes) { ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case); { @@ -419,22 +412,23 @@ inline std::ostream& operator<<(std::ostream& os, const VarintErrorCase& c) { } const VarintErrorCase kVarintErrorCases[] = { - // Control case. (Insures that there isn't something else wrong that - // makes parsing always fail.) - {{0x00}, 1, true}, + // Control case. (Insures that there isn't something else wrong that + // makes parsing always fail.) + {{0x00}, 1, true}, - // No input data. - {{}, 0, false}, + // No input data. + {{}, 0, false}, - // Input ends unexpectedly. - {{0xf0, 0xab}, 2, false}, + // Input ends unexpectedly. + {{0xf0, 0xab}, 2, false}, - // Input ends unexpectedly after 32 bits. - {{0xf0, 0xab, 0xc9, 0x9a, 0xf8, 0xb2}, 6, false}, + // Input ends unexpectedly after 32 bits. + {{0xf0, 0xab, 0xc9, 0x9a, 0xf8, 0xb2}, 6, false}, - // Longer than 10 bytes. - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}, - 11, false}, + // Longer than 10 bytes. + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}, + 11, + false}, }; TEST_2D(CodedStreamTest, ReadVarint32Error, kVarintErrorCases, kBlockSizes) { @@ -500,14 +494,14 @@ inline std::ostream& operator<<(std::ostream& os, const VarintSizeCase& c) { } VarintSizeCase kVarintSizeCases[] = { - {0u, 1}, - {1u, 1}, - {127u, 1}, - {128u, 2}, - {758923u, 3}, - {4000000000u, 5}, - {ULL(41256202580718336), 8}, - {ULL(11964378330978735131), 10}, + {0u, 1}, + {1u, 1}, + {127u, 1}, + {128u, 2}, + {758923u, 3}, + {4000000000u, 5}, + {ULL(41256202580718336), 8}, + {ULL(11964378330978735131), 10}, }; TEST_1D(CodedStreamTest, VarintSize32, kVarintSizeCases) { @@ -517,13 +511,13 @@ TEST_1D(CodedStreamTest, VarintSize32, kVarintSizeCases) { } EXPECT_EQ(kVarintSizeCases_case.size, - CodedOutputStream::VarintSize32( - static_cast(kVarintSizeCases_case.value))); + CodedOutputStream::VarintSize32( + static_cast(kVarintSizeCases_case.value))); } TEST_1D(CodedStreamTest, VarintSize64, kVarintSizeCases) { EXPECT_EQ(kVarintSizeCases_case.size, - CodedOutputStream::VarintSize64(kVarintSizeCases_case.value)); + CodedOutputStream::VarintSize64(kVarintSizeCases_case.value)); } TEST_F(CodedStreamTest, VarintSize32PowersOfTwo) { @@ -552,13 +546,13 @@ TEST_F(CodedStreamTest, VarintSize64PowersOfTwo) { // Fixed-size int tests struct Fixed32Case { - uint8 bytes[sizeof(uint32)]; // Encoded bytes. - uint32 value; // Parsed value. + uint8 bytes[sizeof(uint32)]; // Encoded bytes. + uint32 value; // Parsed value. }; struct Fixed64Case { - uint8 bytes[sizeof(uint64)]; // Encoded bytes. - uint64 value; // Parsed value. + uint8 bytes[sizeof(uint64)]; // Encoded bytes. + uint64 value; // Parsed value. }; inline std::ostream& operator<<(std::ostream& os, const Fixed32Case& c) { @@ -570,13 +564,13 @@ inline std::ostream& operator<<(std::ostream& os, const Fixed64Case& c) { } Fixed32Case kFixed32Cases[] = { - {{0xef, 0xcd, 0xab, 0x90}, 0x90abcdefu}, - {{0x12, 0x34, 0x56, 0x78}, 0x78563412u}, + {{0xef, 0xcd, 0xab, 0x90}, 0x90abcdefu}, + {{0x12, 0x34, 0x56, 0x78}, 0x78563412u}, }; Fixed64Case kFixed64Cases[] = { - {{0xef, 0xcd, 0xab, 0x90, 0x12, 0x34, 0x56, 0x78}, ULL(0x7856341290abcdef)}, - {{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, ULL(0x8877665544332211)}, + {{0xef, 0xcd, 0xab, 0x90, 0x12, 0x34, 0x56, 0x78}, ULL(0x7856341290abcdef)}, + {{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, ULL(0x8877665544332211)}, }; TEST_2D(CodedStreamTest, ReadLittleEndian32, kFixed32Cases, kBlockSizes) { @@ -647,8 +641,8 @@ TEST_1D(CodedStreamTest, ReadLittleEndian32FromArray, kFixed32Cases) { memcpy(buffer_, kFixed32Cases_case.bytes, sizeof(kFixed32Cases_case.bytes)); uint32 value; - const uint8* end = CodedInputStream::ReadLittleEndian32FromArray( - buffer_, &value); + const uint8* end = + CodedInputStream::ReadLittleEndian32FromArray(buffer_, &value); EXPECT_EQ(kFixed32Cases_case.value, value); EXPECT_TRUE(end == buffer_ + sizeof(value)); } @@ -657,8 +651,8 @@ TEST_1D(CodedStreamTest, ReadLittleEndian64FromArray, kFixed64Cases) { memcpy(buffer_, kFixed64Cases_case.bytes, sizeof(kFixed64Cases_case.bytes)); uint64 value; - const uint8* end = CodedInputStream::ReadLittleEndian64FromArray( - buffer_, &value); + const uint8* end = + CodedInputStream::ReadLittleEndian64FromArray(buffer_, &value); EXPECT_EQ(kFixed64Cases_case.value, value); EXPECT_TRUE(end == buffer_ + sizeof(value)); } @@ -706,7 +700,7 @@ TEST_1D(CodedStreamTest, ReadString, kBlockSizes) { { CodedInputStream coded_input(&input); - string str; + std::string str; EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes))); EXPECT_EQ(kRawBytes, str); } @@ -721,7 +715,7 @@ TEST_1D(CodedStreamTest, ReadStringImpossiblyLarge, kBlockSizes) { { CodedInputStream coded_input(&input); - string str; + std::string str; // Try to read a gigabyte. EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30)); } @@ -732,14 +726,14 @@ TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnStack) { // crashes while the above did not. uint8 buffer[8]; CodedInputStream coded_input(buffer, 8); - string str; + std::string str; EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30)); } TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnHeap) { - google::protobuf::scoped_array buffer(new uint8[8]); + std::unique_ptr buffer(new uint8[8]); CodedInputStream coded_input(buffer.get(), 8); - string str; + std::string str; EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30)); } @@ -752,7 +746,7 @@ TEST_1D(CodedStreamTest, ReadStringReservesMemoryOnTotalLimit, kBlockSizes) { coded_input.SetTotalBytesLimit(sizeof(kRawBytes), sizeof(kRawBytes)); EXPECT_EQ(sizeof(kRawBytes), coded_input.BytesUntilTotalBytesLimit()); - string str; + std::string str; EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes))); EXPECT_EQ(sizeof(kRawBytes) - strlen(kRawBytes), coded_input.BytesUntilTotalBytesLimit()); @@ -772,7 +766,7 @@ TEST_1D(CodedStreamTest, ReadStringReservesMemoryOnPushedLimit, kBlockSizes) { CodedInputStream coded_input(&input); coded_input.PushLimit(sizeof(buffer_)); - string str; + std::string str; EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes))); EXPECT_EQ(kRawBytes, str); // TODO(liujisi): Replace with a more meaningful test (see cl/60966023). @@ -792,7 +786,7 @@ TEST_F(CodedStreamTest, ReadStringNoReservationIfLimitsNotSet) { { CodedInputStream coded_input(&input); - string str; + std::string str; EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes))); EXPECT_EQ(kRawBytes, str); // Note: this check depends on string class implementation. It @@ -817,12 +811,12 @@ TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsNegative) { CodedInputStream coded_input(&input); coded_input.PushLimit(sizeof(buffer_)); - string str; + std::string str; EXPECT_FALSE(coded_input.ReadString(&str, -1)); // Note: this check depends on string class implementation. It // expects that string will always allocate the same amount of // memory for an empty string. - EXPECT_EQ(string().capacity(), str.capacity()); + EXPECT_EQ(std::string().capacity(), str.capacity()); } } @@ -837,7 +831,7 @@ TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsLarge) { CodedInputStream coded_input(&input); coded_input.PushLimit(sizeof(buffer_)); - string str; + std::string str; EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30)); EXPECT_GT(1 << 30, str.capacity()); } @@ -854,7 +848,7 @@ TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsOverTheLimit) { CodedInputStream coded_input(&input); coded_input.PushLimit(16); - string str; + std::string str; EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes))); // Note: this check depends on string class implementation. It // expects that string will allocate less than strlen(kRawBytes) @@ -874,7 +868,7 @@ TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsOverTheTotalBytesLimit) { CodedInputStream coded_input(&input); coded_input.SetTotalBytesLimit(16, 16); - string str; + std::string str; EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes))); // Note: this check depends on string class implementation. It // expects that string will allocate less than strlen(kRawBytes) @@ -896,7 +890,7 @@ TEST_F(CodedStreamTest, coded_input.PushLimit(sizeof(buffer_)); coded_input.SetTotalBytesLimit(16, 16); - string str; + std::string str; EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes))); // Note: this check depends on string class implementation. It // expects that string will allocate less than strlen(kRawBytes) @@ -919,7 +913,7 @@ TEST_F(CodedStreamTest, coded_input.SetTotalBytesLimit(sizeof(buffer_), sizeof(buffer_)); EXPECT_EQ(sizeof(buffer_), coded_input.BytesUntilTotalBytesLimit()); - string str; + std::string str; EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes))); // Note: this check depends on string class implementation. It // expects that string will allocate less than strlen(kRawBytes) @@ -933,7 +927,7 @@ TEST_F(CodedStreamTest, // Skip const char kSkipTestBytes[] = - ""; + ""; TEST_1D(CodedStreamTest, SkipInput, kBlockSizes) { memcpy(buffer_, kSkipTestBytes, sizeof(kSkipTestBytes)); @@ -942,7 +936,7 @@ TEST_1D(CodedStreamTest, SkipInput, kBlockSizes) { { CodedInputStream coded_input(&input); - string str; + std::string str; EXPECT_TRUE(coded_input.ReadString(&str, strlen(""))); EXPECT_EQ("", str); EXPECT_TRUE(coded_input.Skip(strlen(""))); @@ -1015,41 +1009,6 @@ TEST_F(CodedStreamTest, GetDirectBufferPointerInlineInput) { EXPECT_EQ(0, size); } -TEST_F(CodedStreamTest, GetDirectBufferPointerOutput) { - ArrayOutputStream output(buffer_, sizeof(buffer_), 8); - CodedOutputStream coded_output(&output); - - void* ptr; - int size; - - EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size)); - EXPECT_EQ(buffer_, ptr); - EXPECT_EQ(8, size); - - // Peeking again should return the same pointer. - EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size)); - EXPECT_EQ(buffer_, ptr); - EXPECT_EQ(8, size); - - // Skip forward in the same buffer then peek again. - EXPECT_TRUE(coded_output.Skip(3)); - EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size)); - EXPECT_EQ(buffer_ + 3, ptr); - EXPECT_EQ(5, size); - - // Skip to end of buffer and peek -- should get next buffer. - EXPECT_TRUE(coded_output.Skip(5)); - EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size)); - EXPECT_EQ(buffer_ + 8, ptr); - EXPECT_EQ(8, size); - - // Skip over multiple buffers. - EXPECT_TRUE(coded_output.Skip(22)); - EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size)); - EXPECT_EQ(buffer_ + 30, ptr); - EXPECT_EQ(2, size); -} - // ------------------------------------------------------------------- // Limits @@ -1226,11 +1185,11 @@ TEST_F(CodedStreamTest, TotalBytesLimit) { coded_input.SetTotalBytesLimit(16, -1); EXPECT_EQ(16, coded_input.BytesUntilTotalBytesLimit()); - string str; + std::string str; EXPECT_TRUE(coded_input.ReadString(&str, 16)); EXPECT_EQ(0, coded_input.BytesUntilTotalBytesLimit()); - std::vector errors; + std::vector errors; { ScopedMemoryLog error_log; @@ -1240,7 +1199,8 @@ TEST_F(CodedStreamTest, TotalBytesLimit) { ASSERT_EQ(1, errors.size()); EXPECT_PRED_FORMAT2(testing::IsSubstring, - "A protocol message was rejected because it was too big", errors[0]); + "A protocol message was rejected because it was too big", + errors[0]); coded_input.SetTotalBytesLimit(32, -1); EXPECT_EQ(16, coded_input.BytesUntilTotalBytesLimit()); @@ -1259,7 +1219,7 @@ TEST_F(CodedStreamTest, TotalBytesLimitNotValidMessageEnd) { CodedInputStream::Limit limit = coded_input.PushLimit(16); // Read 16 bytes. - string str; + std::string str; EXPECT_TRUE(coded_input.ReadString(&str, 16)); // Read a tag. Should fail, but report being a valid endpoint since it's @@ -1276,62 +1236,41 @@ TEST_F(CodedStreamTest, TotalBytesLimitNotValidMessageEnd) { EXPECT_FALSE(coded_input.ConsumedEntireMessage()); } -// This method is used by the tests below. -// It constructs a CodedInputStream with the given limits and tries to read 2KiB -// of data from it. Then it returns the logged errors and warnings in the given -// vectors. -void CodedStreamTest::SetupTotalBytesLimitWarningTest( - int total_bytes_limit, int warning_threshold, - std::vector* out_errors, std::vector* out_warnings) { - ArrayInputStream raw_input(buffer_, sizeof(buffer_), 128); - - ScopedMemoryLog scoped_log; - { - CodedInputStream input(&raw_input); - input.SetTotalBytesLimit(total_bytes_limit, warning_threshold); - string str; - EXPECT_TRUE(input.ReadString(&str, 2048)); - } - - *out_errors = scoped_log.GetMessages(ERROR); - *out_warnings = scoped_log.GetMessages(WARNING); -} - TEST_F(CodedStreamTest, RecursionLimit) { ArrayInputStream input(buffer_, sizeof(buffer_)); CodedInputStream coded_input(&input); coded_input.SetRecursionLimit(4); // This is way too much testing for a counter. - EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 1 - EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 2 - EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 3 - EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 4 - EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 5 - EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 6 - coded_input.DecrementRecursionDepth(); // 5 - EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 6 - coded_input.DecrementRecursionDepth(); // 5 - coded_input.DecrementRecursionDepth(); // 4 - coded_input.DecrementRecursionDepth(); // 3 - EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 4 - EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 5 - coded_input.DecrementRecursionDepth(); // 4 - coded_input.DecrementRecursionDepth(); // 3 - coded_input.DecrementRecursionDepth(); // 2 - coded_input.DecrementRecursionDepth(); // 1 - coded_input.DecrementRecursionDepth(); // 0 - coded_input.DecrementRecursionDepth(); // 0 - coded_input.DecrementRecursionDepth(); // 0 - EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 1 - EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 2 - EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 3 - EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 4 - EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 5 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 1 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 2 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 3 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 4 + EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 5 + EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 6 + coded_input.DecrementRecursionDepth(); // 5 + EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 6 + coded_input.DecrementRecursionDepth(); // 5 + coded_input.DecrementRecursionDepth(); // 4 + coded_input.DecrementRecursionDepth(); // 3 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 4 + EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 5 + coded_input.DecrementRecursionDepth(); // 4 + coded_input.DecrementRecursionDepth(); // 3 + coded_input.DecrementRecursionDepth(); // 2 + coded_input.DecrementRecursionDepth(); // 1 + coded_input.DecrementRecursionDepth(); // 0 + coded_input.DecrementRecursionDepth(); // 0 + coded_input.DecrementRecursionDepth(); // 0 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 1 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 2 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 3 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 4 + EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 5 coded_input.SetRecursionLimit(6); - EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 6 - EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 7 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 6 + EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 7 } @@ -1341,7 +1280,7 @@ class ReallyBigInputStream : public ZeroCopyInputStream { ~ReallyBigInputStream() {} // implements ZeroCopyInputStream ---------------------------------- - bool Next(const void** data, int* size) { + bool Next(const void** data, int* size) override { // We only expect BackUp() to be called at the end. EXPECT_EQ(0, backup_amount_); @@ -1363,12 +1302,16 @@ class ReallyBigInputStream : public ZeroCopyInputStream { } } - void BackUp(int count) { - backup_amount_ = count; - } + void BackUp(int count) override { backup_amount_ = count; } - bool Skip(int count) { GOOGLE_LOG(FATAL) << "Not implemented."; return false; } - int64 ByteCount() const { GOOGLE_LOG(FATAL) << "Not implemented."; return 0; } + bool Skip(int count) override { + GOOGLE_LOG(FATAL) << "Not implemented."; + return false; + } + int64_t ByteCount() const override { + GOOGLE_LOG(FATAL) << "Not implemented."; + return 0; + } int backup_amount_; @@ -1382,12 +1325,12 @@ TEST_F(CodedStreamTest, InputOver2G) { // input.BackUp() with the correct number of bytes on destruction. ReallyBigInputStream input; - std::vector errors; + std::vector errors; { ScopedMemoryLog error_log; CodedInputStream coded_input(&input); - string str; + std::string str; EXPECT_TRUE(coded_input.ReadString(&str, 512)); EXPECT_TRUE(coded_input.ReadString(&str, 1024)); errors = error_log.GetMessages(ERROR); @@ -1401,3 +1344,5 @@ TEST_F(CodedStreamTest, InputOver2G) { } // namespace io } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc index a569eff0a7a90..ad6bb5f1c4225 100644 --- a/src/google/protobuf/io/gzip_stream.cc +++ b/src/google/protobuf/io/gzip_stream.cc @@ -46,8 +46,8 @@ namespace io { static const int kDefaultBufferSize = 65536; -GzipInputStream::GzipInputStream( - ZeroCopyInputStream* sub_stream, Format format, int buffer_size) +GzipInputStream::GzipInputStream(ZeroCopyInputStream* sub_stream, Format format, + int buffer_size) : format_(format), sub_stream_(sub_stream), zerror_(Z_OK), byte_count_(0) { zcontext_.state = Z_NULL; zcontext_.zalloc = Z_NULL; @@ -74,15 +74,21 @@ GzipInputStream::~GzipInputStream() { zerror_ = inflateEnd(&zcontext_); } -static inline int internalInflateInit2( - z_stream* zcontext, GzipInputStream::Format format) { +static inline int internalInflateInit2(z_stream* zcontext, + GzipInputStream::Format format) { int windowBitsFormat = 0; switch (format) { - case GzipInputStream::GZIP: windowBitsFormat = 16; break; - case GzipInputStream::AUTO: windowBitsFormat = 32; break; - case GzipInputStream::ZLIB: windowBitsFormat = 0; break; + case GzipInputStream::GZIP: + windowBitsFormat = 16; + break; + case GzipInputStream::AUTO: + windowBitsFormat = 32; + break; + case GzipInputStream::ZLIB: + windowBitsFormat = 0; + break; } - return inflateInit2(zcontext, /* windowBits */15 | windowBitsFormat); + return inflateInit2(zcontext, /* windowBits */ 15 | windowBitsFormat); } int GzipInputStream::Inflate(int flush) { @@ -122,8 +128,8 @@ void GzipInputStream::DoNextOutput(const void** data, int* size) { // implements ZeroCopyInputStream ---------------------------------- bool GzipInputStream::Next(const void** data, int* size) { - bool ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END) - || (zerror_ == Z_BUF_ERROR); + bool ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END) || + (zerror_ == Z_BUF_ERROR); if ((!ok) || (zcontext_.next_out == NULL)) { return false; } @@ -154,8 +160,8 @@ bool GzipInputStream::Next(const void** data, int* size) { // The underlying stream's Next returned false inside Inflate. return false; } - ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END) - || (zerror_ == Z_BUF_ERROR); + ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END) || + (zerror_ == Z_BUF_ERROR); if (!ok) { return false; } @@ -179,7 +185,7 @@ bool GzipInputStream::Skip(int count) { } return ok; } -int64 GzipInputStream::ByteCount() const { +int64_t GzipInputStream::ByteCount() const { int64 ret = byte_count_ + zcontext_.total_out; if (zcontext_.next_out != NULL && output_position_ != NULL) { ret += reinterpret_cast(zcontext_.next_out) - @@ -230,13 +236,10 @@ void GzipOutputStream::Init(ZeroCopyOutputStream* sub_stream, if (options.format == ZLIB) { windowBitsFormat = 0; } - zerror_ = deflateInit2( - &zcontext_, - options.compression_level, - Z_DEFLATED, - /* windowBits */15 | windowBitsFormat, - /* memLevel (default) */8, - options.compression_strategy); + zerror_ = + deflateInit2(&zcontext_, options.compression_level, Z_DEFLATED, + /* windowBits */ 15 | windowBitsFormat, + /* memLevel (default) */ 8, options.compression_strategy); } GzipOutputStream::~GzipOutputStream() { @@ -295,19 +298,19 @@ bool GzipOutputStream::Next(void** data, int* size) { return true; } void GzipOutputStream::BackUp(int count) { - GOOGLE_CHECK_GE(zcontext_.avail_in, count); + GOOGLE_CHECK_GE(zcontext_.avail_in, static_cast(count)); zcontext_.avail_in -= count; } -int64 GzipOutputStream::ByteCount() const { +int64_t GzipOutputStream::ByteCount() const { return zcontext_.total_in + zcontext_.avail_in; } bool GzipOutputStream::Flush() { zerror_ = Deflate(Z_FULL_FLUSH); // Return true if the flush succeeded or if it was a no-op. - return (zerror_ == Z_OK) || - (zerror_ == Z_BUF_ERROR && zcontext_.avail_in == 0 && - zcontext_.avail_out != 0); + return (zerror_ == Z_OK) || + (zerror_ == Z_BUF_ERROR && zcontext_.avail_in == 0 && + zcontext_.avail_out != 0); } bool GzipOutputStream::Close() { diff --git a/src/google/protobuf/io/gzip_stream.h b/src/google/protobuf/io/gzip_stream.h index 15b02fe3d7dc7..b1ce1d36c652d 100644 --- a/src/google/protobuf/io/gzip_stream.h +++ b/src/google/protobuf/io/gzip_stream.h @@ -43,16 +43,20 @@ #ifndef GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__ #define GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__ + #include #include +#include #include +#include + namespace google { namespace protobuf { namespace io { // A ZeroCopyInputStream that reads compressed data through zlib -class LIBPROTOBUF_EXPORT GzipInputStream : public ZeroCopyInputStream { +class PROTOBUF_EXPORT GzipInputStream : public ZeroCopyInputStream { public: // Format key for constructor enum Format { @@ -67,25 +71,19 @@ class LIBPROTOBUF_EXPORT GzipInputStream : public ZeroCopyInputStream { }; // buffer_size and format may be -1 for default of 64kB and GZIP format - explicit GzipInputStream( - ZeroCopyInputStream* sub_stream, - Format format = AUTO, - int buffer_size = -1); + explicit GzipInputStream(ZeroCopyInputStream* sub_stream, + Format format = AUTO, int buffer_size = -1); virtual ~GzipInputStream(); // Return last error message or NULL if no error. - inline const char* ZlibErrorMessage() const { - return zcontext_.msg; - } - inline int ZlibErrorCode() const { - return zerror_; - } + inline const char* ZlibErrorMessage() const { return zcontext_.msg; } + inline int ZlibErrorCode() const { return zerror_; } // implements ZeroCopyInputStream ---------------------------------- bool Next(const void** data, int* size); void BackUp(int count); bool Skip(int count); - int64 ByteCount() const; + int64_t ByteCount() const; private: Format format_; @@ -106,8 +104,7 @@ class LIBPROTOBUF_EXPORT GzipInputStream : public ZeroCopyInputStream { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipInputStream); }; - -class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream { +class PROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream { public: // Format key for constructor enum Format { @@ -118,7 +115,7 @@ class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream { ZLIB = 2, }; - struct Options { + struct PROTOBUF_EXPORT Options { // Defaults to GZIP. Format format; @@ -141,19 +138,13 @@ class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream { explicit GzipOutputStream(ZeroCopyOutputStream* sub_stream); // Create a GzipOutputStream with the given options. - GzipOutputStream( - ZeroCopyOutputStream* sub_stream, - const Options& options); + GzipOutputStream(ZeroCopyOutputStream* sub_stream, const Options& options); virtual ~GzipOutputStream(); // Return last error message or NULL if no error. - inline const char* ZlibErrorMessage() const { - return zcontext_.msg; - } - inline int ZlibErrorCode() const { - return zerror_; - } + inline const char* ZlibErrorMessage() const { return zcontext_.msg; } + inline int ZlibErrorCode() const { return zerror_; } // Flushes data written so far to zipped data in the underlying stream. // It is the caller's responsibility to flush the underlying stream if @@ -178,7 +169,7 @@ class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream { // implements ZeroCopyOutputStream --------------------------------- bool Next(void** data, int* size); void BackUp(int count); - int64 ByteCount() const; + int64_t ByteCount() const; private: ZeroCopyOutputStream* sub_stream_; @@ -204,6 +195,8 @@ class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream { } // namespace io } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__ diff --git a/src/google/protobuf/io/io_win32.cc b/src/google/protobuf/io/io_win32.cc new file mode 100644 index 0000000000000..d22ceac77372e --- /dev/null +++ b/src/google/protobuf/io/io_win32.cc @@ -0,0 +1,470 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: laszlocsomor@google.com (Laszlo Csomor) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +// Implementation for long-path-aware open/mkdir/access/etc. on Windows, as well +// as for the supporting utility functions. +// +// These functions convert the input path to an absolute Windows path +// with "\\?\" prefix, then pass that to _wopen/_wmkdir/_waccess/etc. +// (declared in ) respectively. This allows working with files/directories +// whose paths are longer than MAX_PATH (260 chars). +// +// This file is only used on Windows, it's empty on other platforms. + +#if defined(_WIN32) && !defined(_XBOX_ONE) + +// Comment this out to fall back to using the ANSI versions (open, mkdir, ...) +// instead of the Unicode ones (_wopen, _wmkdir, ...). Doing so can be useful to +// debug failing tests if that's caused by the long path support. +#define SUPPORT_LONGPATHS + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif + +#include + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace io { +namespace win32 { +namespace { + +using std::string; +using std::wstring; + +template +struct CharTraits { + static bool is_alpha(char_type ch); +}; + +template <> +struct CharTraits { + static bool is_alpha(char ch) { return isalpha(ch); } +}; + +template <> +struct CharTraits { + static bool is_alpha(wchar_t ch) { return iswalpha(ch); } +}; + +template +bool null_or_empty(const char_type* s) { + return s == nullptr || *s == 0; +} + +// Returns true if the path starts with a drive letter, e.g. "c:". +// Note that this won't check for the "\" after the drive letter, so this also +// returns true for "c:foo" (which is "c:\${PWD}\foo"). +// This check requires that a path not have a longpath prefix ("\\?\"). +template +bool has_drive_letter(const char_type* ch) { + return CharTraits::is_alpha(ch[0]) && ch[1] == ':'; +} + +// Returns true if the path starts with a longpath prefix ("\\?\"). +template +bool has_longpath_prefix(const char_type* path) { + return path[0] == '\\' && path[1] == '\\' && path[2] == '?' && + path[3] == '\\'; +} + +template +bool is_separator(char_type c) { + return c == '/' || c == '\\'; +} + +// Returns true if the path starts with a drive specifier (e.g. "c:\"). +template +bool is_path_absolute(const char_type* path) { + return has_drive_letter(path) && is_separator(path[2]); +} + +template +bool is_drive_relative(const char_type* path) { + return has_drive_letter(path) && (path[2] == 0 || !is_separator(path[2])); +} + +wstring join_paths(const wstring& path1, const wstring& path2) { + if (path1.empty() || is_path_absolute(path2.c_str()) || + has_longpath_prefix(path2.c_str())) { + return path2; + } + if (path2.empty()) { + return path1; + } + + if (is_separator(path1[path1.size() - 1])) { + return is_separator(path2[0]) ? (path1 + path2.substr(1)) + : (path1 + path2); + } else { + return is_separator(path2[0]) ? (path1 + path2) + : (path1 + L'\\' + path2); + } +} + +wstring normalize(wstring path) { + if (has_longpath_prefix(path.c_str())) { + path = path.substr(4); + } + + static const wstring dot(L"."); + static const wstring dotdot(L".."); + const WCHAR* p = path.c_str(); + + std::vector segments; + int segment_start = -1; + // Find the path segments in `path` (separated by "/"). + for (int i = 0;; ++i) { + if (!is_separator(p[i]) && p[i] != L'\0') { + // The current character does not end a segment, so start one unless it's + // already started. + if (segment_start < 0) { + segment_start = i; + } + } else if (segment_start >= 0 && i > segment_start) { + // The current character is "/" or "\0", so this ends a segment. + // Add that to `segments` if there's anything to add; handle "." and "..". + wstring segment(p, segment_start, i - segment_start); + segment_start = -1; + if (segment == dotdot) { + if (!segments.empty() && + (!has_drive_letter(segments[0].c_str()) || segments.size() > 1)) { + segments.pop_back(); + } + } else if (segment != dot && !segment.empty()) { + segments.push_back(segment); + } + } + if (p[i] == L'\0') { + break; + } + } + + // Handle the case when `path` is just a drive specifier (or some degenerate + // form of it, e.g. "c:\.."). + if (segments.size() == 1 && segments[0].size() == 2 && + has_drive_letter(segments[0].c_str())) { + return segments[0] + L'\\'; + } + + // Join all segments. + bool first = true; + std::wstringstream result; + for (int i = 0; i < segments.size(); ++i) { + if (!first) { + result << L'\\'; + } + first = false; + result << segments[i]; + } + // Preserve trailing separator if the input contained it. + if (!path.empty() && is_separator(p[path.size() - 1])) { + result << L'\\'; + } + return result.str(); +} + +bool as_windows_path(const char* path, wstring* result) { + if (null_or_empty(path)) { + result->clear(); + return true; + } + wstring wpath; + if (!strings::utf8_to_wcs(path, &wpath)) { + return false; + } + if (has_longpath_prefix(wpath.c_str())) { + *result = wpath; + return true; + } + if (is_separator(path[0]) || is_drive_relative(path)) { + return false; + } + + + if (!is_path_absolute(wpath.c_str())) { + int size = ::GetCurrentDirectoryW(0, nullptr); + if (size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + return false; + } + std::unique_ptr wcwd(new WCHAR[size]); + ::GetCurrentDirectoryW(size, wcwd.get()); + wpath = join_paths(wcwd.get(), wpath); + } + wpath = normalize(wpath); + if (!has_longpath_prefix(wpath.c_str())) { + // Add the "\\?\" prefix unconditionally. This way we prevent the Win32 API + // from processing the path and "helpfully" removing trailing dots from the + // path, for example. + // See https://github.com/bazelbuild/bazel/issues/2935 + wpath = wstring(L"\\\\?\\") + wpath; + } + *result = wpath; + return true; +} + +} // namespace + +int open(const char* path, int flags, int mode) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_wopen(wpath.c_str(), flags, mode); +#else + return ::_open(path, flags, mode); +#endif +} + +int mkdir(const char* path, int _mode) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_wmkdir(wpath.c_str()); +#else // not SUPPORT_LONGPATHS + return ::_mkdir(path); +#endif // not SUPPORT_LONGPATHS +} + +int access(const char* path, int mode) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_waccess(wpath.c_str(), mode); +#else + return ::_access(path, mode); +#endif +} + +int chdir(const char* path) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_wchdir(wpath.c_str()); +#else + return ::_chdir(path); +#endif +} + +int stat(const char* path, struct _stat* buffer) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_wstat(wpath.c_str(), buffer); +#else // not SUPPORT_LONGPATHS + return ::_stat(path, buffer); +#endif // not SUPPORT_LONGPATHS +} + +FILE* fopen(const char* path, const char* mode) { +#ifdef SUPPORT_LONGPATHS + if (null_or_empty(path)) { + errno = EINVAL; + return nullptr; + } + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return nullptr; + } + wstring wmode; + if (!strings::utf8_to_wcs(mode, &wmode)) { + errno = EINVAL; + return nullptr; + } + return ::_wfopen(wpath.c_str(), wmode.c_str()); +#else + return ::fopen(path, mode); +#endif +} + +int close(int fd) { return ::_close(fd); } + +int dup(int fd) { return ::_dup(fd); } + +int dup2(int fd1, int fd2) { return ::_dup2(fd1, fd2); } + +int read(int fd, void* buffer, size_t size) { + return ::_read(fd, buffer, size); +} + +int setmode(int fd, int mode) { return ::_setmode(fd, mode); } + +int write(int fd, const void* buffer, size_t size) { + return ::_write(fd, buffer, size); +} + +wstring testonly_utf8_to_winpath(const char* path) { + wstring wpath; + return as_windows_path(path, &wpath) ? wpath : wstring(); +} + +ExpandWildcardsResult ExpandWildcards( + const string& path, std::function consume) { + if (path.find_first_of("*?") == string::npos) { + // There are no wildcards in the path, we don't need to expand it. + consume(path); + return ExpandWildcardsResult::kSuccess; + } + + wstring wpath; + if (!as_windows_path(path.c_str(), &wpath)) { + return ExpandWildcardsResult::kErrorInputPathConversion; + } + + static const wstring kDot = L"."; + static const wstring kDotDot = L".."; + WIN32_FIND_DATAW metadata; + HANDLE handle = ::FindFirstFileW(wpath.c_str(), &metadata); + if (handle == INVALID_HANDLE_VALUE) { + // The pattern does not match any files (or directories). + return ExpandWildcardsResult::kErrorNoMatchingFile; + } + + string::size_type pos = path.find_last_of("\\/"); + string dirname; + if (pos != string::npos) { + dirname = path.substr(0, pos + 1); + } + + ExpandWildcardsResult matched = ExpandWildcardsResult::kErrorNoMatchingFile; + do { + // Ignore ".", "..", and directories. + if ((metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 && + kDot != metadata.cFileName && kDotDot != metadata.cFileName) { + matched = ExpandWildcardsResult::kSuccess; + string filename; + if (!strings::wcs_to_utf8(metadata.cFileName, &filename)) { + return ExpandWildcardsResult::kErrorOutputPathConversion; + } + + if (dirname.empty()) { + consume(filename); + } else { + consume(dirname + filename); + } + } + } while (::FindNextFileW(handle, &metadata)); + FindClose(handle); + return matched; +} + +namespace strings { + +bool wcs_to_mbs(const WCHAR* s, string* out, bool outUtf8) { + if (null_or_empty(s)) { + out->clear(); + return true; + } + BOOL usedDefaultChar = FALSE; + SetLastError(0); + int size = WideCharToMultiByte( + outUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, nullptr, 0, nullptr, + outUtf8 ? nullptr : &usedDefaultChar); + if ((size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + || usedDefaultChar) { + return false; + } + std::unique_ptr astr(new CHAR[size]); + WideCharToMultiByte( + outUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, astr.get(), size, nullptr, nullptr); + out->assign(astr.get()); + return true; +} + +bool mbs_to_wcs(const char* s, wstring* out, bool inUtf8) { + if (null_or_empty(s)) { + out->clear(); + return true; + } + + SetLastError(0); + int size = + MultiByteToWideChar(inUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, nullptr, 0); + if (size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + return false; + } + std::unique_ptr wstr(new WCHAR[size]); + MultiByteToWideChar( + inUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, wstr.get(), size + 1); + out->assign(wstr.get()); + return true; +} + +bool utf8_to_wcs(const char* input, wstring* out) { + return mbs_to_wcs(input, out, true); +} + +bool wcs_to_utf8(const wchar_t* input, string* out) { + return wcs_to_mbs(input, out, true); +} + +} // namespace strings +} // namespace win32 +} // namespace io +} // namespace protobuf +} // namespace google + +#endif // defined(_WIN32) diff --git a/src/google/protobuf/io/io_win32.h b/src/google/protobuf/io/io_win32.h new file mode 100644 index 0000000000000..7d11dc2b3151a --- /dev/null +++ b/src/google/protobuf/io/io_win32.h @@ -0,0 +1,139 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: laszlocsomor@google.com (Laszlo Csomor) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +// This file contains the declarations for Windows implementations of +// commonly used POSIX functions such as open(2) and access(2), as well +// as macro definitions for flags of these functions. +// +// By including this file you'll redefine open/access/etc. to +// ::google::protobuf::io::win32::{open/access/etc.}. +// Make sure you don't include a header that attempts to redeclare or +// redefine these functions, that'll lead to confusing compilation +// errors. It's best to #include this file as the last one to ensure that. +// +// This file is only used on Windows, it's empty on other platforms. + +#ifndef GOOGLE_PROTOBUF_IO_IO_WIN32_H__ +#define GOOGLE_PROTOBUF_IO_IO_WIN32_H__ + +#if defined(_WIN32) + +#include +#include + +#include +#include + +// Compilers on Windows other than MSVC (e.g. Cygwin, MinGW32) define the +// following functions already, except for mkdir. +namespace google { +namespace protobuf { +namespace io { +namespace win32 { + +PROTOBUF_EXPORT FILE* fopen(const char* path, const char* mode); +PROTOBUF_EXPORT int access(const char* path, int mode); +PROTOBUF_EXPORT int chdir(const char* path); +PROTOBUF_EXPORT int close(int fd); +PROTOBUF_EXPORT int dup(int fd); +PROTOBUF_EXPORT int dup2(int fd1, int fd2); +PROTOBUF_EXPORT int mkdir(const char* path, int _mode); +PROTOBUF_EXPORT int open(const char* path, int flags, int mode = 0); +PROTOBUF_EXPORT int read(int fd, void* buffer, size_t size); +PROTOBUF_EXPORT int setmode(int fd, int mode); +PROTOBUF_EXPORT int stat(const char* path, struct _stat* buffer); +PROTOBUF_EXPORT int write(int fd, const void* buffer, size_t size); +PROTOBUF_EXPORT std::wstring testonly_utf8_to_winpath(const char* path); + +enum class ExpandWildcardsResult { + kSuccess = 0, + kErrorNoMatchingFile = 1, + kErrorInputPathConversion = 2, + kErrorOutputPathConversion = 3, +}; + +// Expand wildcards in a path pattern, feed the result to a consumer function. +// +// `path` must be a valid, Windows-style path. It may be absolute, or relative +// to the current working directory, and it may contain wildcards ("*" and "?") +// in the last path segment. This function passes all matching file names to +// `consume`. The resulting paths may not be absolute nor normalized. +// +// The function returns a value from `ExpandWildcardsResult`. +PROTOBUF_EXPORT ExpandWildcardsResult ExpandWildcards( + const std::string& path, std::function consume); + +namespace strings { + +// Convert from UTF-16 to Active-Code-Page-encoded or to UTF-8-encoded text. +PROTOBUF_EXPORT bool wcs_to_mbs(const wchar_t* s, std::string* out, + bool outUtf8); + +// Convert from Active-Code-Page-encoded or UTF-8-encoded text to UTF-16. +PROTOBUF_EXPORT bool mbs_to_wcs(const char* s, std::wstring* out, bool inUtf8); + +// Convert from UTF-8-encoded text to UTF-16. +PROTOBUF_EXPORT bool utf8_to_wcs(const char* input, std::wstring* out); + +// Convert from UTF-16-encoded text to UTF-8. +PROTOBUF_EXPORT bool wcs_to_utf8(const wchar_t* input, std::string* out); + +} // namespace strings + +} // namespace win32 +} // namespace io +} // namespace protobuf +} // namespace google + +#ifndef W_OK +#define W_OK 02 // not defined by MSVC for whatever reason +#endif + +#ifndef F_OK +#define F_OK 00 // not defined by MSVC for whatever reason +#endif + +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif + +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif + +#include + +#endif // defined(_WIN32) + +#endif // GOOGLE_PROTOBUF_IO_IO_WIN32_H__ diff --git a/src/google/protobuf/io/io_win32_unittest.cc b/src/google/protobuf/io/io_win32_unittest.cc new file mode 100644 index 0000000000000..c50f68d6a92f0 --- /dev/null +++ b/src/google/protobuf/io/io_win32_unittest.cc @@ -0,0 +1,631 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: laszlocsomor@google.com (Laszlo Csomor) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +// Unit tests for long-path-aware open/mkdir/access/etc. on Windows, as well as +// for the supporting utility functions. +// +// This file is only used on Windows, it's empty on other platforms. + +#if defined(_WIN32) + +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace google { +namespace protobuf { +namespace io { +namespace win32 { +namespace { + +const char kUtf8Text[] = { + 'h', 'i', ' ', + // utf-8: 11010000 10011111, utf-16: 100 0001 1111 = 0x041F + static_cast(0xd0), static_cast(0x9f), + // utf-8: 11010001 10000000, utf-16: 100 0100 0000 = 0x0440 + static_cast(0xd1), static_cast(0x80), + // utf-8: 11010000 10111000, utf-16: 100 0011 1000 = 0x0438 + static_cast(0xd0), static_cast(0xb8), + // utf-8: 11010000 10110010, utf-16: 100 0011 0010 = 0x0432 + static_cast(0xd0), static_cast(0xb2), + // utf-8: 11010000 10110101, utf-16: 100 0011 0101 = 0x0435 + static_cast(0xd0), static_cast(0xb5), + // utf-8: 11010001 10000010, utf-16: 100 0100 0010 = 0x0442 + static_cast(0xd1), static_cast(0x82), 0 +}; + +const wchar_t kUtf16Text[] = { + L'h', L'i', L' ', + L'\x41f', L'\x440', L'\x438', L'\x432', L'\x435', L'\x442', 0 +}; + +using std::string; +using std::vector; +using std::wstring; + +class IoWin32Test : public ::testing::Test { + public: + void SetUp(); + void TearDown(); + + protected: + bool CreateAllUnder(wstring path); + bool DeleteAllUnder(wstring path); + + WCHAR working_directory[MAX_PATH]; + string test_tmpdir; + wstring wtest_tmpdir; +}; + +#define ASSERT_INITIALIZED \ + { \ + EXPECT_FALSE(test_tmpdir.empty()); \ + EXPECT_FALSE(wtest_tmpdir.empty()); \ + } + +namespace { +void StripTrailingSlashes(string* str) { + int i = str->size() - 1; + for (; i >= 0 && ((*str)[i] == '/' || (*str)[i] == '\\'); --i) {} + str->resize(i+1); +} + +bool GetEnvVarAsUtf8(const WCHAR* name, string* result) { + DWORD size = ::GetEnvironmentVariableW(name, nullptr, 0); + if (size > 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND) { + std::unique_ptr wcs(new WCHAR[size]); + ::GetEnvironmentVariableW(name, wcs.get(), size); + // GetEnvironmentVariableA retrieves an Active-Code-Page-encoded text which + // we'd first need to convert to UTF-16 then to UTF-8, because there seems + // to be no API function to do that conversion directly. + // GetEnvironmentVariableW retrieves an UTF-16-encoded text, which we need + // to convert to UTF-8. + return strings::wcs_to_utf8(wcs.get(), result); + } else { + return false; + } +} + +bool GetCwdAsUtf8(string* result) { + DWORD size = ::GetCurrentDirectoryW(0, nullptr); + if (size > 0) { + std::unique_ptr wcs(new WCHAR[size]); + ::GetCurrentDirectoryW(size, wcs.get()); + // GetCurrentDirectoryA retrieves an Active-Code-Page-encoded text which + // we'd first need to convert to UTF-16 then to UTF-8, because there seems + // to be no API function to do that conversion directly. + // GetCurrentDirectoryW retrieves an UTF-16-encoded text, which we need + // to convert to UTF-8. + return strings::wcs_to_utf8(wcs.get(), result); + } else { + return false; + } +} + +bool CreateEmptyFile(const wstring& path) { + HANDLE h = CreateFileW(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) { + return false; + } + CloseHandle(h); + return true; +} + +} // namespace + +void IoWin32Test::SetUp() { + test_tmpdir.clear(); + wtest_tmpdir.clear(); + DWORD size = ::GetCurrentDirectoryW(MAX_PATH, working_directory); + EXPECT_GT(size, 0); + EXPECT_LT(size, MAX_PATH); + + string tmp; + bool ok = false; + if (!ok) { + // Bazel sets this environment variable when it runs tests. + ok = GetEnvVarAsUtf8(L"TEST_TMPDIR", &tmp); + } + if (!ok) { + // Bazel 0.8.0 sets this environment for every build and test action. + ok = GetEnvVarAsUtf8(L"TEMP", &tmp); + } + if (!ok) { + // Bazel 0.8.0 sets this environment for every build and test action. + ok = GetEnvVarAsUtf8(L"TMP", &tmp); + } + if (!ok) { + // Fall back to using the current directory. + ok = GetCwdAsUtf8(&tmp); + } + if (!ok || tmp.empty()) { + FAIL() << "Cannot find a temp directory."; + } + + StripTrailingSlashes(&tmp); + std::stringstream result; + // Deleting files and directories is asynchronous on Windows, and if TearDown + // just deleted the previous temp directory, sometimes we cannot recreate the + // same directory. + // Use a counter so every test method gets its own temp directory. + static unsigned int counter = 0; + result << tmp << "\\w32tst" << counter++ << ".tmp"; + test_tmpdir = result.str(); + wtest_tmpdir = testonly_utf8_to_winpath(test_tmpdir.c_str()); + ASSERT_FALSE(wtest_tmpdir.empty()); + ASSERT_TRUE(DeleteAllUnder(wtest_tmpdir)); + ASSERT_TRUE(CreateAllUnder(wtest_tmpdir)); +} + +void IoWin32Test::TearDown() { + if (!wtest_tmpdir.empty()) { + DeleteAllUnder(wtest_tmpdir); + } + ::SetCurrentDirectoryW(working_directory); +} + +bool IoWin32Test::CreateAllUnder(wstring path) { + // Prepend UNC prefix if the path doesn't have it already. Don't bother + // checking if the path is shorter than MAX_PATH, let's just do it + // unconditionally. + if (path.find(L"\\\\?\\") != 0) { + path = wstring(L"\\\\?\\") + path; + } + if (::CreateDirectoryW(path.c_str(), nullptr) || + GetLastError() == ERROR_ALREADY_EXISTS || + GetLastError() == ERROR_ACCESS_DENIED) { + return true; + } + if (GetLastError() == ERROR_PATH_NOT_FOUND) { + size_t pos = path.find_last_of(L'\\'); + if (pos != wstring::npos) { + wstring parent(path, 0, pos); + if (CreateAllUnder(parent) && CreateDirectoryW(path.c_str(), nullptr)) { + return true; + } + } + } + return false; +} + +bool IoWin32Test::DeleteAllUnder(wstring path) { + static const wstring kDot(L"."); + static const wstring kDotDot(L".."); + + // Prepend UNC prefix if the path doesn't have it already. Don't bother + // checking if the path is shorter than MAX_PATH, let's just do it + // unconditionally. + if (path.find(L"\\\\?\\") != 0) { + path = wstring(L"\\\\?\\") + path; + } + // Append "\" if necessary. + if (path[path.size() - 1] != L'\\') { + path.push_back(L'\\'); + } + + WIN32_FIND_DATAW metadata; + HANDLE handle = ::FindFirstFileW((path + L"*").c_str(), &metadata); + if (handle == INVALID_HANDLE_VALUE) { + return true; // directory doesn't exist + } + + bool result = true; + do { + wstring childname = metadata.cFileName; + if (kDot != childname && kDotDot != childname) { + wstring childpath = path + childname; + if ((metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { + // If this is not a junction, delete its contents recursively. + // Finally delete this directory/junction too. + if (((metadata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0 && + !DeleteAllUnder(childpath)) || + !::RemoveDirectoryW(childpath.c_str())) { + result = false; + break; + } + } else { + if (!::DeleteFileW(childpath.c_str())) { + result = false; + break; + } + } + } + } while (::FindNextFileW(handle, &metadata)); + ::FindClose(handle); + return result; +} + +TEST_F(IoWin32Test, AccessTest) { + ASSERT_INITIALIZED; + + string path = test_tmpdir; + while (path.size() < MAX_PATH - 30) { + path += "\\accesstest"; + EXPECT_EQ(mkdir(path.c_str(), 0644), 0); + } + string file = path + "\\file.txt"; + int fd = open(file.c_str(), O_CREAT | O_WRONLY, 0644); + if (fd > 0) { + EXPECT_EQ(close(fd), 0); + } else { + EXPECT_TRUE(false); + } + + EXPECT_EQ(access(test_tmpdir.c_str(), F_OK), 0); + EXPECT_EQ(access(path.c_str(), F_OK), 0); + EXPECT_EQ(access(path.c_str(), W_OK), 0); + EXPECT_EQ(access(file.c_str(), F_OK | W_OK), 0); + EXPECT_NE(access((file + ".blah").c_str(), F_OK), 0); + EXPECT_NE(access((file + ".blah").c_str(), W_OK), 0); + + EXPECT_EQ(access(".", F_OK), 0); + EXPECT_EQ(access(".", W_OK), 0); + EXPECT_EQ(access((test_tmpdir + "/accesstest").c_str(), F_OK | W_OK), 0); + ASSERT_EQ(access((test_tmpdir + "/./normalize_me/.././accesstest").c_str(), + F_OK | W_OK), + 0); + EXPECT_NE(access("io_win32_unittest.AccessTest.nonexistent", F_OK), 0); + EXPECT_NE(access("io_win32_unittest.AccessTest.nonexistent", W_OK), 0); + + ASSERT_EQ(access("c:bad", F_OK), -1); + ASSERT_EQ(errno, ENOENT); + ASSERT_EQ(access("/tmp/bad", F_OK), -1); + ASSERT_EQ(errno, ENOENT); + ASSERT_EQ(access("\\bad", F_OK), -1); + ASSERT_EQ(errno, ENOENT); +} + +TEST_F(IoWin32Test, OpenTest) { + ASSERT_INITIALIZED; + + string path = test_tmpdir; + while (path.size() < MAX_PATH) { + path += "\\opentest"; + EXPECT_EQ(mkdir(path.c_str(), 0644), 0); + } + string file = path + "\\file.txt"; + int fd = open(file.c_str(), O_CREAT | O_WRONLY, 0644); + if (fd > 0) { + EXPECT_EQ(write(fd, "hello", 5), 5); + EXPECT_EQ(close(fd), 0); + } else { + EXPECT_TRUE(false); + } + + ASSERT_EQ(open("c:bad.txt", O_CREAT | O_WRONLY, 0644), -1); + ASSERT_EQ(errno, ENOENT); + ASSERT_EQ(open("/tmp/bad.txt", O_CREAT | O_WRONLY, 0644), -1); + ASSERT_EQ(errno, ENOENT); + ASSERT_EQ(open("\\bad.txt", O_CREAT | O_WRONLY, 0644), -1); + ASSERT_EQ(errno, ENOENT); +} + +TEST_F(IoWin32Test, MkdirTest) { + ASSERT_INITIALIZED; + + string path = test_tmpdir; + do { + path += "\\mkdirtest"; + ASSERT_EQ(mkdir(path.c_str(), 0644), 0); + } while (path.size() <= MAX_PATH); + + ASSERT_EQ(mkdir("c:bad", 0644), -1); + ASSERT_EQ(errno, ENOENT); + ASSERT_EQ(mkdir("/tmp/bad", 0644), -1); + ASSERT_EQ(errno, ENOENT); + ASSERT_EQ(mkdir("\\bad", 0644), -1); + ASSERT_EQ(errno, ENOENT); +} + +TEST_F(IoWin32Test, MkdirTestNonAscii) { + ASSERT_INITIALIZED; + + // Create a non-ASCII path. + // Ensure that we can create the directory using CreateDirectoryW. + EXPECT_TRUE(CreateDirectoryW((wtest_tmpdir + L"\\1").c_str(), nullptr)); + EXPECT_TRUE(CreateDirectoryW((wtest_tmpdir + L"\\1\\" + kUtf16Text).c_str(), nullptr)); + // Ensure that we can create a very similarly named directory using mkdir. + // We don't attempt to delete and recreate the same directory, because on + // Windows, deleting files and directories seems to be asynchronous. + EXPECT_EQ(mkdir((test_tmpdir + "\\2").c_str(), 0644), 0); + EXPECT_EQ(mkdir((test_tmpdir + "\\2\\" + kUtf8Text).c_str(), 0644), 0); +} + +TEST_F(IoWin32Test, ChdirTest) { + string path("C:\\"); + EXPECT_EQ(access(path.c_str(), F_OK), 0); + ASSERT_EQ(chdir(path.c_str()), 0); + + // Do not try to chdir into the test_tmpdir, it may already contain directory + // names with trailing dots. + // Instead test here with an obviously dot-trailed path. If the win32_chdir + // function would not convert the path to absolute and prefix with "\\?\" then + // the Win32 API would ignore the trailing dot, but because of the prefixing + // there'll be no path processing done, so we'll actually attempt to chdir + // into "C:\some\path\foo." + path = test_tmpdir + "/foo."; + EXPECT_EQ(mkdir(path.c_str(), 644), 0); + EXPECT_EQ(access(path.c_str(), F_OK), 0); + ASSERT_NE(chdir(path.c_str()), 0); +} + +TEST_F(IoWin32Test, ChdirTestNonAscii) { + ASSERT_INITIALIZED; + + // Create a directory with a non-ASCII path and ensure we can cd into it. + wstring wNonAscii(wtest_tmpdir + L"\\" + kUtf16Text); + string nonAscii; + EXPECT_TRUE(strings::wcs_to_utf8(wNonAscii.c_str(), &nonAscii)); + EXPECT_TRUE(CreateDirectoryW(wNonAscii.c_str(), nullptr)); + WCHAR cwd[MAX_PATH]; + EXPECT_TRUE(GetCurrentDirectoryW(MAX_PATH, cwd)); + // Ensure that we can cd into the path using SetCurrentDirectoryW. + EXPECT_TRUE(SetCurrentDirectoryW(wNonAscii.c_str())); + EXPECT_TRUE(SetCurrentDirectoryW(cwd)); + // Ensure that we can cd into the path using chdir. + ASSERT_EQ(chdir(nonAscii.c_str()), 0); + // Ensure that the GetCurrentDirectoryW returns the desired path. + EXPECT_TRUE(GetCurrentDirectoryW(MAX_PATH, cwd)); + ASSERT_EQ(wNonAscii, cwd); +} + +TEST_F(IoWin32Test, ExpandWildcardsInRelativePathTest) { + wstring wNonAscii(wtest_tmpdir + L"\\" + kUtf16Text); + EXPECT_TRUE(CreateDirectoryW(wNonAscii.c_str(), nullptr)); + // Create mock files we will test pattern matching on. + EXPECT_TRUE(CreateEmptyFile(wNonAscii + L"\\foo_a.proto")); + EXPECT_TRUE(CreateEmptyFile(wNonAscii + L"\\foo_b.proto")); + EXPECT_TRUE(CreateEmptyFile(wNonAscii + L"\\bar.proto")); + // `cd` into `wtest_tmpdir`. + EXPECT_TRUE(SetCurrentDirectoryW(wtest_tmpdir.c_str())); + + int found_a = 0; + int found_b = 0; + vector found_bad; + // Assert matching a relative path pattern. Results should also be relative. + ExpandWildcardsResult result = + ExpandWildcards(string(kUtf8Text) + "\\foo*.proto", + [&found_a, &found_b, &found_bad](const string& p) { + if (p == string(kUtf8Text) + "\\foo_a.proto") { + found_a++; + } else if (p == string(kUtf8Text) + "\\foo_b.proto") { + found_b++; + } else { + found_bad.push_back(p); + } + }); + EXPECT_EQ(result, ExpandWildcardsResult::kSuccess); + EXPECT_EQ(found_a, 1); + EXPECT_EQ(found_b, 1); + if (!found_bad.empty()) { + FAIL() << found_bad[0]; + } + + // Assert matching the exact filename. + found_a = 0; + found_bad.clear(); + result = ExpandWildcards(string(kUtf8Text) + "\\foo_a.proto", + [&found_a, &found_bad](const string& p) { + if (p == string(kUtf8Text) + "\\foo_a.proto") { + found_a++; + } else { + found_bad.push_back(p); + } + }); + EXPECT_EQ(result, ExpandWildcardsResult::kSuccess); + EXPECT_EQ(found_a, 1); + if (!found_bad.empty()) { + FAIL() << found_bad[0]; + } +} + +TEST_F(IoWin32Test, ExpandWildcardsInAbsolutePathTest) { + wstring wNonAscii(wtest_tmpdir + L"\\" + kUtf16Text); + EXPECT_TRUE(CreateDirectoryW(wNonAscii.c_str(), nullptr)); + // Create mock files we will test pattern matching on. + EXPECT_TRUE(CreateEmptyFile(wNonAscii + L"\\foo_a.proto")); + EXPECT_TRUE(CreateEmptyFile(wNonAscii + L"\\foo_b.proto")); + EXPECT_TRUE(CreateEmptyFile(wNonAscii + L"\\bar.proto")); + + int found_a = 0; + int found_b = 0; + vector found_bad; + // Assert matching an absolute path. The results should also use absolute + // path. + ExpandWildcardsResult result = + ExpandWildcards(string(test_tmpdir) + "\\" + kUtf8Text + "\\foo*.proto", + [this, &found_a, &found_b, &found_bad](const string& p) { + if (p == string(this->test_tmpdir) + "\\" + kUtf8Text + + "\\foo_a.proto") { + found_a++; + } else if (p == string(this->test_tmpdir) + "\\" + + kUtf8Text + "\\foo_b.proto") { + found_b++; + } else { + found_bad.push_back(p); + } + }); + EXPECT_EQ(result, ExpandWildcardsResult::kSuccess); + EXPECT_EQ(found_a, 1); + EXPECT_EQ(found_b, 1); + if (!found_bad.empty()) { + FAIL() << found_bad[0]; + } + + // Assert matching the exact filename. + found_a = 0; + found_bad.clear(); + result = + ExpandWildcards(string(test_tmpdir) + "\\" + kUtf8Text + "\\foo_a.proto", + [this, &found_a, &found_bad](const string& p) { + if (p == string(this->test_tmpdir) + "\\" + kUtf8Text + + "\\foo_a.proto") { + found_a++; + } else { + found_bad.push_back(p); + } + }); + EXPECT_EQ(result, ExpandWildcardsResult::kSuccess); + EXPECT_EQ(found_a, 1); + if (!found_bad.empty()) { + FAIL() << found_bad[0]; + } +} + +TEST_F(IoWin32Test, ExpandWildcardsIgnoresDirectoriesTest) { + wstring wNonAscii(wtest_tmpdir + L"\\" + kUtf16Text); + EXPECT_TRUE(CreateDirectoryW(wNonAscii.c_str(), nullptr)); + // Create mock files we will test pattern matching on. + EXPECT_TRUE(CreateEmptyFile(wNonAscii + L"\\foo_a.proto")); + EXPECT_TRUE( + CreateDirectoryW((wNonAscii + L"\\foo_b.proto").c_str(), nullptr)); + EXPECT_TRUE(CreateEmptyFile(wNonAscii + L"\\foo_c.proto")); + // `cd` into `wtest_tmpdir`. + EXPECT_TRUE(SetCurrentDirectoryW(wtest_tmpdir.c_str())); + + int found_a = 0; + int found_c = 0; + vector found_bad; + // Assert that the pattern matches exactly the expected files, and using the + // absolute path as did the input pattern. + ExpandWildcardsResult result = + ExpandWildcards(string(kUtf8Text) + "\\foo*.proto", + [&found_a, &found_c, &found_bad](const string& p) { + if (p == string(kUtf8Text) + "\\foo_a.proto") { + found_a++; + } else if (p == string(kUtf8Text) + "\\foo_c.proto") { + found_c++; + } else { + found_bad.push_back(p); + } + }); + EXPECT_EQ(result, ExpandWildcardsResult::kSuccess); + EXPECT_EQ(found_a, 1); + EXPECT_EQ(found_c, 1); + if (!found_bad.empty()) { + FAIL() << found_bad[0]; + } +} + +TEST_F(IoWin32Test, ExpandWildcardsFailsIfNoFileMatchesTest) { + wstring wNonAscii(wtest_tmpdir + L"\\" + kUtf16Text); + EXPECT_TRUE(CreateDirectoryW(wNonAscii.c_str(), nullptr)); + // Create mock files we will test pattern matching on. + EXPECT_TRUE(CreateEmptyFile(wNonAscii + L"\\foo_a.proto")); + // `cd` into `wtest_tmpdir`. + EXPECT_TRUE(SetCurrentDirectoryW(wtest_tmpdir.c_str())); + + // Control test: should match foo*.proto + ExpandWildcardsResult result = + ExpandWildcards(string(kUtf8Text) + "\\foo*.proto", [](const string&) {}); + EXPECT_EQ(result, ExpandWildcardsResult::kSuccess); + + // Control test: should match foo_a.proto + result = ExpandWildcards(string(kUtf8Text) + "\\foo_a.proto", + [](const string&) {}); + EXPECT_EQ(result, ExpandWildcardsResult::kSuccess); + + // Actual test: should not match anything. + result = + ExpandWildcards(string(kUtf8Text) + "\\bar*.proto", [](const string&) {}); + ASSERT_EQ(result, ExpandWildcardsResult::kErrorNoMatchingFile); +} + +TEST_F(IoWin32Test, AsWindowsPathTest) { + DWORD size = GetCurrentDirectoryW(0, nullptr); + std::unique_ptr cwd_str(new wchar_t[size]); + EXPECT_GT(GetCurrentDirectoryW(size, cwd_str.get()), 0); + wstring cwd = wstring(L"\\\\?\\") + cwd_str.get(); + + ASSERT_EQ(testonly_utf8_to_winpath("relative_mkdirtest"), + cwd + L"\\relative_mkdirtest"); + ASSERT_EQ(testonly_utf8_to_winpath("preserve//\\trailing///"), + cwd + L"\\preserve\\trailing\\"); + ASSERT_EQ(testonly_utf8_to_winpath("./normalize_me\\/../blah"), + cwd + L"\\blah"); + std::ostringstream relpath; + for (wchar_t* p = cwd_str.get(); *p; ++p) { + if (*p == '/' || *p == '\\') { + relpath << "../"; + } + } + relpath << ".\\/../\\./beyond-toplevel"; + ASSERT_EQ(testonly_utf8_to_winpath(relpath.str().c_str()), + wstring(L"\\\\?\\") + cwd_str.get()[0] + L":\\beyond-toplevel"); + + // Absolute unix paths lack drive letters, driveless absolute windows paths + // do too. Neither can be converted to a drive-specifying absolute Windows + // path. + ASSERT_EQ(testonly_utf8_to_winpath("/absolute/unix/path"), L""); + // Though valid on Windows, we also don't support UNC paths (\\UNC\\blah). + ASSERT_EQ(testonly_utf8_to_winpath("\\driveless\\absolute"), L""); + // Though valid in cmd.exe, drive-relative paths are not supported. + ASSERT_EQ(testonly_utf8_to_winpath("c:foo"), L""); + ASSERT_EQ(testonly_utf8_to_winpath("c:/foo"), L"\\\\?\\c:\\foo"); + ASSERT_EQ(testonly_utf8_to_winpath("\\\\?\\C:\\foo"), L"\\\\?\\C:\\foo"); +} + +TEST_F(IoWin32Test, Utf8Utf16ConversionTest) { + string mbs; + wstring wcs; + ASSERT_TRUE(strings::utf8_to_wcs(kUtf8Text, &wcs)); + ASSERT_TRUE(strings::wcs_to_utf8(kUtf16Text, &mbs)); + ASSERT_EQ(wcs, kUtf16Text); + ASSERT_EQ(mbs, kUtf8Text); +} + +} // namespace +} // namespace win32 +} // namespace io +} // namespace protobuf +} // namespace google + +#endif // defined(_WIN32) + diff --git a/src/google/protobuf/io/package_info.h b/src/google/protobuf/io/package_info.h index dc1fc91e5b4eb..46c3dac9173de 100644 --- a/src/google/protobuf/io/package_info.h +++ b/src/google/protobuf/io/package_info.h @@ -37,7 +37,6 @@ // documentation generator. namespace google { - namespace protobuf { // Auxiliary classes used for I/O. diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc index 8493268dadd1e..230960c908ad8 100644 --- a/src/google/protobuf/io/printer.cc +++ b/src/google/protobuf/io/printer.cc @@ -33,9 +33,12 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include -#include + +#include + #include #include +#include namespace google { namespace protobuf { @@ -71,7 +74,7 @@ Printer::~Printer() { bool Printer::GetSubstitutionRange(const char* varname, std::pair* range) { - std::map >::const_iterator iter = + std::map >::const_iterator iter = substitutions_.find(varname); if (iter == substitutions_.end()) { GOOGLE_LOG(DFATAL) << " Undefined variable in annotation: " << varname; @@ -87,7 +90,8 @@ bool Printer::GetSubstitutionRange(const char* varname, } void Printer::Annotate(const char* begin_varname, const char* end_varname, - const string& file_path, const std::vector& path) { + const std::string& file_path, + const std::vector& path) { if (annotation_collector_ == NULL) { // Can't generate signatures with this Printer. return; @@ -106,7 +110,7 @@ void Printer::Annotate(const char* begin_varname, const char* end_varname, } } -void Printer::Print(const std::map& variables, +void Printer::Print(const std::map& variables, const char* text) { int size = strlen(text); int pos = 0; // The number of bytes we've written so far. @@ -140,13 +144,14 @@ void Printer::Print(const std::map& variables, } int endpos = end - text; - string varname(text + pos, endpos - pos); + std::string varname(text + pos, endpos - pos); if (varname.empty()) { // Two delimiters in a row reduce to a literal delimiter character. WriteRaw(&variable_delimiter_, 1); } else { // Replace with the variable's value. - std::map::const_iterator iter = variables.find(varname); + std::map::const_iterator iter = + variables.find(varname); if (iter == variables.end()) { GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname; } else { @@ -154,7 +159,7 @@ void Printer::Print(const std::map& variables, line_start_variables_.push_back(varname); } WriteRaw(iter->second.data(), iter->second.size()); - std::pair >::iterator, + std::pair >::iterator, bool> inserted = substitutions_.insert(std::make_pair( varname, @@ -178,126 +183,7 @@ void Printer::Print(const std::map& variables, WriteRaw(text + pos, size - pos); } -void Printer::Print(const char* text) { - static std::map empty; - Print(empty, text); -} - -void Printer::Print(const char* text, - const char* variable, const string& value) { - std::map vars; - vars[variable] = value; - Print(vars, text); -} - -void Printer::Print(const char* text, - const char* variable1, const string& value1, - const char* variable2, const string& value2) { - std::map vars; - vars[variable1] = value1; - vars[variable2] = value2; - Print(vars, text); -} - -void Printer::Print(const char* text, - const char* variable1, const string& value1, - const char* variable2, const string& value2, - const char* variable3, const string& value3) { - std::map vars; - vars[variable1] = value1; - vars[variable2] = value2; - vars[variable3] = value3; - Print(vars, text); -} - -void Printer::Print(const char* text, - const char* variable1, const string& value1, - const char* variable2, const string& value2, - const char* variable3, const string& value3, - const char* variable4, const string& value4) { - std::map vars; - vars[variable1] = value1; - vars[variable2] = value2; - vars[variable3] = value3; - vars[variable4] = value4; - Print(vars, text); -} - -void Printer::Print(const char* text, - const char* variable1, const string& value1, - const char* variable2, const string& value2, - const char* variable3, const string& value3, - const char* variable4, const string& value4, - const char* variable5, const string& value5) { - std::map vars; - vars[variable1] = value1; - vars[variable2] = value2; - vars[variable3] = value3; - vars[variable4] = value4; - vars[variable5] = value5; - Print(vars, text); -} - -void Printer::Print(const char* text, - const char* variable1, const string& value1, - const char* variable2, const string& value2, - const char* variable3, const string& value3, - const char* variable4, const string& value4, - const char* variable5, const string& value5, - const char* variable6, const string& value6) { - std::map vars; - vars[variable1] = value1; - vars[variable2] = value2; - vars[variable3] = value3; - vars[variable4] = value4; - vars[variable5] = value5; - vars[variable6] = value6; - Print(vars, text); -} - -void Printer::Print(const char* text, - const char* variable1, const string& value1, - const char* variable2, const string& value2, - const char* variable3, const string& value3, - const char* variable4, const string& value4, - const char* variable5, const string& value5, - const char* variable6, const string& value6, - const char* variable7, const string& value7) { - std::map vars; - vars[variable1] = value1; - vars[variable2] = value2; - vars[variable3] = value3; - vars[variable4] = value4; - vars[variable5] = value5; - vars[variable6] = value6; - vars[variable7] = value7; - Print(vars, text); -} - -void Printer::Print(const char* text, - const char* variable1, const string& value1, - const char* variable2, const string& value2, - const char* variable3, const string& value3, - const char* variable4, const string& value4, - const char* variable5, const string& value5, - const char* variable6, const string& value6, - const char* variable7, const string& value7, - const char* variable8, const string& value8) { - std::map vars; - vars[variable1] = value1; - vars[variable2] = value2; - vars[variable3] = value3; - vars[variable4] = value4; - vars[variable5] = value5; - vars[variable6] = value6; - vars[variable7] = value7; - vars[variable8] = value8; - Print(vars, text); -} - -void Printer::Indent() { - indent_ += " "; -} +void Printer::Indent() { indent_ += " "; } void Printer::Outdent() { if (indent_.empty()) { @@ -308,7 +194,7 @@ void Printer::Outdent() { indent_.resize(indent_.size() - 2); } -void Printer::PrintRaw(const string& data) { +void Printer::PrintRaw(const std::string& data) { WriteRaw(data.data(), data.size()); } @@ -328,7 +214,7 @@ void Printer::WriteRaw(const char* data, int size) { if (failed_) return; // Fix up empty variables (e.g., "{") that should be annotated as // coming after the indent. - for (std::vector::iterator i = line_start_variables_.begin(); + for (std::vector::iterator i = line_start_variables_.begin(); i != line_start_variables_.end(); ++i) { substitutions_[*i].first += indent_.size(); substitutions_[*i].second += indent_.size(); @@ -343,6 +229,18 @@ void Printer::WriteRaw(const char* data, int size) { CopyToBuffer(data, size); } +bool Printer::Next() { + do { + void* void_buffer; + if (!output_->Next(&void_buffer, &buffer_size_)) { + failed_ = true; + return false; + } + buffer_ = reinterpret_cast(void_buffer); + } while (buffer_size_ == 0); + return true; +} + void Printer::CopyToBuffer(const char* data, int size) { if (failed_) return; if (size == 0) return; @@ -350,10 +248,12 @@ void Printer::CopyToBuffer(const char* data, int size) { while (size > buffer_size_) { // Data exceeds space in the buffer. Copy what we can and request a // new buffer. - memcpy(buffer_, data, buffer_size_); - offset_ += buffer_size_; - data += buffer_size_; - size -= buffer_size_; + if (buffer_size_ > 0) { + memcpy(buffer_, data, buffer_size_); + offset_ += buffer_size_; + data += buffer_size_; + size -= buffer_size_; + } void* void_buffer; failed_ = !output_->Next(&void_buffer, &buffer_size_); if (failed_) return; @@ -367,6 +267,134 @@ void Printer::CopyToBuffer(const char* data, int size) { offset_ += size; } +void Printer::IndentIfAtStart() { + if (at_start_of_line_) { + CopyToBuffer(indent_.data(), indent_.size()); + at_start_of_line_ = false; + } +} + +void Printer::FormatInternal(const std::vector& args, + const std::map& vars, + const char* format) { + auto save = format; + int arg_index = 0; + std::vector annotations; + while (*format) { + char c = *format++; + switch (c) { + case '$': + format = WriteVariable(args, vars, format, &arg_index, &annotations); + continue; + case '\n': + at_start_of_line_ = true; + line_start_variables_.clear(); + break; + default: + IndentIfAtStart(); + break; + } + push_back(c); + } + if (arg_index != static_cast(args.size())) { + GOOGLE_LOG(FATAL) << " Unused arguments. " << save; + } + if (!annotations.empty()) { + GOOGLE_LOG(FATAL) << " Annotation range is not-closed, expect $}$. " << save; + } +} + +const char* Printer::WriteVariable( + const std::vector& args, + const std::map& vars, const char* format, + int* arg_index, std::vector* annotations) { + auto start = format; + auto end = strchr(format, '$'); + if (!end) { + GOOGLE_LOG(FATAL) << " Unclosed variable name."; + } + format = end + 1; + if (end == start) { + // "$$" is an escape for just '$' + IndentIfAtStart(); + push_back('$'); + return format; + } + if (*start == '{') { + GOOGLE_CHECK(std::isdigit(start[1])); + GOOGLE_CHECK_EQ(end - start, 2); + int idx = start[1] - '1'; + if (idx < 0 || static_cast(idx) >= args.size()) { + GOOGLE_LOG(FATAL) << "Annotation ${" << idx + 1 << "$ is out of bounds."; + } + if (idx > *arg_index) { + GOOGLE_LOG(FATAL) << "Annotation arg must be in correct order as given. Expected" + << " ${" << (*arg_index) + 1 << "$ got ${" << idx + 1 << "$."; + } else if (idx == *arg_index) { + (*arg_index)++; + } + IndentIfAtStart(); + annotations->push_back({{offset_, 0}, args[idx]}); + return format; + } else if (*start == '}') { + GOOGLE_CHECK(annotations); + if (annotations->empty()) { + GOOGLE_LOG(FATAL) << "Unexpected end of annotation found."; + } + auto& a = annotations->back(); + a.first.second = offset_; + if (annotation_collector_) annotation_collector_->AddAnnotationNew(a); + annotations->pop_back(); + return format; + } + auto start_var = start; + while (start_var < end && *start_var == ' ') start_var++; + if (start_var == end) { + GOOGLE_LOG(FATAL) << " Empty variable."; + } + auto end_var = end; + while (start_var < end_var && *(end_var - 1) == ' ') end_var--; + std::string var_name{ + start_var, static_cast(end_var - start_var)}; + std::string sub; + if (std::isdigit(var_name[0])) { + GOOGLE_CHECK_EQ(var_name.size(), 1U); // No need for multi-digits + int idx = var_name[0] - '1'; // Start counting at 1 + GOOGLE_CHECK_GE(idx, 0); + if (static_cast(idx) >= args.size()) { + GOOGLE_LOG(FATAL) << "Argument $" << idx + 1 << "$ is out of bounds."; + } + if (idx > *arg_index) { + GOOGLE_LOG(FATAL) << "Arguments must be used in same order as given. Expected $" + << (*arg_index) + 1 << "$ got $" << idx + 1 << "$."; + } else if (idx == *arg_index) { + (*arg_index)++; + } + sub = args[idx]; + } else { + auto it = vars.find(var_name); + if (it == vars.end()) { + GOOGLE_LOG(FATAL) << " Unknown variable: " << var_name << "."; + } + sub = it->second; + } + + // By returning here in case of empty we also skip possible spaces inside + // the $...$, i.e. "void$ dllexpor$ f();" -> "void f();" in the empty case. + if (sub.empty()) return format; + + // We're going to write something non-empty so we need a possible indent. + IndentIfAtStart(); + + // Write the possible spaces in front. + CopyToBuffer(start, start_var - start); + // Write a non-empty substituted variable. + CopyToBuffer(sub.c_str(), sub.size()); + // Finish off with writing possible trailing spaces. + CopyToBuffer(end_var, end - end_var); + return format; +} + } // namespace io } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h index d11745ce97ae1..64336ebcefed1 100644 --- a/src/google/protobuf/io/printer.h +++ b/src/google/protobuf/io/printer.h @@ -37,26 +37,36 @@ #ifndef GOOGLE_PROTOBUF_IO_PRINTER_H__ #define GOOGLE_PROTOBUF_IO_PRINTER_H__ -#include + #include +#include #include + #include +#include namespace google { namespace protobuf { namespace io { -class ZeroCopyOutputStream; // zero_copy_stream.h +class ZeroCopyOutputStream; // zero_copy_stream.h // Records annotations about a Printer's output. -class LIBPROTOBUF_EXPORT AnnotationCollector { +class PROTOBUF_EXPORT AnnotationCollector { public: + // Annotation is a offset range and a payload pair. + typedef std::pair, std::string> Annotation; + // Records that the bytes in file_path beginning with begin_offset and ending // before end_offset are associated with the SourceCodeInfo-style path. virtual void AddAnnotation(size_t begin_offset, size_t end_offset, - const string& file_path, + const std::string& file_path, const std::vector& path) = 0; + // TODO(gerbens) I don't see why we need virtuals here. Just a vector of + // range, payload pairs stored in a context should suffice. + virtual void AddAnnotationNew(Annotation& a) {} + virtual ~AnnotationCollector() {} }; @@ -73,7 +83,7 @@ class AnnotationProtoCollector : public AnnotationCollector { // Override for AnnotationCollector::AddAnnotation. virtual void AddAnnotation(size_t begin_offset, size_t end_offset, - const string& file_path, + const std::string& file_path, const std::vector& path) { typename AnnotationProto::Annotation* annotation = annotation_proto_->add_annotation(); @@ -84,6 +94,13 @@ class AnnotationProtoCollector : public AnnotationCollector { annotation->set_begin(begin_offset); annotation->set_end(end_offset); } + // Override for AnnotationCollector::AddAnnotation. + virtual void AddAnnotationNew(Annotation& a) { + auto* annotation = annotation_proto_->add_annotation(); + annotation->ParseFromString(a.second); + annotation->set_begin(a.first.first); + annotation->set_end(a.first.second); + } private: // The protocol buffer to which new annotations should be added. @@ -162,7 +179,7 @@ class AnnotationProtoCollector : public AnnotationCollector { // This code associates the span covering "call(bar,bar)" in the output with the // call_ descriptor. -class LIBPROTOBUF_EXPORT Printer { +class PROTOBUF_EXPORT Printer { public: // Create a printer that writes text to the given output stream. Use the // given character as the delimiter for variables. @@ -177,8 +194,8 @@ class LIBPROTOBUF_EXPORT Printer { ~Printer(); - // Link a subsitution variable emitted by the last call to Print to the object - // described by descriptor. + // Link a substitution variable emitted by the last call to Print to the + // object described by descriptor. template void Annotate(const char* varname, const SomeDescriptor* descriptor) { Annotate(varname, varname, descriptor); @@ -201,9 +218,9 @@ class LIBPROTOBUF_EXPORT Printer { Annotate(begin_varname, end_varname, descriptor->file()->name(), path); } - // Link a subsitution variable emitted by the last call to Print to the file + // Link a substitution variable emitted by the last call to Print to the file // with path file_name. - void Annotate(const char* varname, const string& file_name) { + void Annotate(const char* varname, const std::string& file_name) { Annotate(varname, varname, file_name); } @@ -212,7 +229,7 @@ class LIBPROTOBUF_EXPORT Printer { // at begin_varname's value and ends after the last character of the value // substituted for end_varname. void Annotate(const char* begin_varname, const char* end_varname, - const string& file_name) { + const std::string& file_name) { if (annotation_collector_ == NULL) { // Annotations aren't turned on for this Printer. return; @@ -226,54 +243,15 @@ class LIBPROTOBUF_EXPORT Printer { // substituted are identified by their names surrounded by delimiter // characters (as given to the constructor). The variable bindings are // defined by the given map. - void Print(const std::map& variables, const char* text); + void Print(const std::map& variables, + const char* text); // Like the first Print(), except the substitutions are given as parameters. - void Print(const char* text); - // Like the first Print(), except the substitutions are given as parameters. - void Print(const char* text, const char* variable, const string& value); - // Like the first Print(), except the substitutions are given as parameters. - void Print(const char* text, const char* variable1, const string& value1, - const char* variable2, const string& value2); - // Like the first Print(), except the substitutions are given as parameters. - void Print(const char* text, const char* variable1, const string& value1, - const char* variable2, const string& value2, - const char* variable3, const string& value3); - // Like the first Print(), except the substitutions are given as parameters. - void Print(const char* text, const char* variable1, const string& value1, - const char* variable2, const string& value2, - const char* variable3, const string& value3, - const char* variable4, const string& value4); - // Like the first Print(), except the substitutions are given as parameters. - void Print(const char* text, const char* variable1, const string& value1, - const char* variable2, const string& value2, - const char* variable3, const string& value3, - const char* variable4, const string& value4, - const char* variable5, const string& value5); - // Like the first Print(), except the substitutions are given as parameters. - void Print(const char* text, const char* variable1, const string& value1, - const char* variable2, const string& value2, - const char* variable3, const string& value3, - const char* variable4, const string& value4, - const char* variable5, const string& value5, - const char* variable6, const string& value6); - // Like the first Print(), except the substitutions are given as parameters. - void Print(const char* text, const char* variable1, const string& value1, - const char* variable2, const string& value2, - const char* variable3, const string& value3, - const char* variable4, const string& value4, - const char* variable5, const string& value5, - const char* variable6, const string& value6, - const char* variable7, const string& value7); - // Like the first Print(), except the substitutions are given as parameters. - void Print(const char* text, const char* variable1, const string& value1, - const char* variable2, const string& value2, - const char* variable3, const string& value3, - const char* variable4, const string& value4, - const char* variable5, const string& value5, - const char* variable6, const string& value6, - const char* variable7, const string& value7, - const char* variable8, const string& value8); + template + void Print(const char* text, const Args&... args) { + std::map vars; + PrintInternal(&vars, text, args...); + } // Indent text by two spaces. After calling Indent(), two spaces will be // inserted at the beginning of each line of text. Indent() may be called @@ -286,7 +264,7 @@ class LIBPROTOBUF_EXPORT Printer { // Write a string to the output buffer. // This method does not look for newlines to add indentation. - void PrintRaw(const string& data); + void PrintRaw(const std::string& data); // Write a zero-delimited string to output buffer. // This method does not look for newlines to add indentation. @@ -296,6 +274,15 @@ class LIBPROTOBUF_EXPORT Printer { // This method does not look for newlines to add indentation. void WriteRaw(const char* data, int size); + // FormatInternal is a helper function not meant to use directly, use + // compiler::cpp::Formatter instead. This function is meant to support + // formatting text using named variables (eq. "$foo$) from a lookup map (vars) + // and variables directly supplied by arguments (eq "$1$" meaning first + // argument which is the zero index element of args). + void FormatInternal(const std::vector& args, + const std::map& vars, + const char* format); + // True if any write to the underlying stream failed. (We don't just // crash in this case because this is an I/O failure, not a programming // error.) @@ -309,11 +296,44 @@ class LIBPROTOBUF_EXPORT Printer { // substituted for end_varname. Note that begin_varname and end_varname // may refer to the same variable. void Annotate(const char* begin_varname, const char* end_varname, - const string& file_path, const std::vector& path); + const std::string& file_path, const std::vector& path); + + // Base case + void PrintInternal(std::map* vars, + const char* text) { + Print(*vars, text); + } + + template + void PrintInternal(std::map* vars, const char* text, + const char* key, const std::string& value, + const Args&... args) { + (*vars)[key] = value; + PrintInternal(vars, text, args...); + } // Copy size worth of bytes from data to buffer_. void CopyToBuffer(const char* data, int size); + void push_back(char c) { + if (failed_) return; + if (buffer_size_ == 0) { + if (!Next()) return; + } + *buffer_++ = c; + buffer_size_--; + offset_++; + } + + bool Next(); + + inline void IndentIfAtStart(); + const char* WriteVariable( + const std::vector& args, + const std::map& vars, const char* format, + int* arg_index, + std::vector* annotations); + const char variable_delimiter_; ZeroCopyOutputStream* const output_; @@ -324,7 +344,7 @@ class LIBPROTOBUF_EXPORT Printer { // used to calculate annotation ranges in the substitutions_ map below. size_t offset_; - string indent_; + std::string indent_; bool at_start_of_line_; bool failed_; @@ -335,12 +355,12 @@ class LIBPROTOBUF_EXPORT Printer { // start offset is the beginning of the substitution; the end offset is the // last byte of the substitution plus one (such that (end - start) is the // length of the substituted string). - std::map > substitutions_; + std::map > substitutions_; // Keeps track of the keys in substitutions_ that need to be updated when // indents are inserted. These are keys that refer to the beginning of the // current line. - std::vector line_start_variables_; + std::vector line_start_variables_; // Returns true and sets range to the substitution range in the output for // varname if varname was used once in the last call to Print. If varname @@ -358,6 +378,8 @@ class LIBPROTOBUF_EXPORT Printer { } // namespace io } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_IO_PRINTER_H__ diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc index d0a0ebeea238a..ed54d1dd1d063 100644 --- a/src/google/protobuf/io/printer_unittest.cc +++ b/src/google/protobuf/io/printer_unittest.cc @@ -32,21 +32,20 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include - #include -#include -#include + +#include #include #include +#include #include #include +#include namespace google { namespace protobuf { namespace io { -namespace { // Each test repeats over several block sizes in order to test both cases // where particular writes cross a buffer boundary and cases where they do @@ -78,10 +77,11 @@ TEST(Printer, BasicPrinting) { buffer[output.ByteCount()] = '\0'; - EXPECT_STREQ("Hello World! This is the same line.\n" - "But this is a new one.\n" - "And this is another one.", - buffer); + EXPECT_STREQ( + "Hello World! This is the same line.\n" + "But this is a new one.\n" + "And this is another one.", + buffer); } } @@ -92,7 +92,7 @@ TEST(Printer, WriteRaw) { ArrayOutputStream output(buffer, sizeof(buffer), block_size); { - string string_obj = "From an object\n"; + std::string string_obj = "From an object\n"; Printer printer(&output, '$'); printer.WriteRaw("Hello World!", 12); printer.PrintRaw(" This is the same line.\n"); @@ -104,12 +104,13 @@ TEST(Printer, WriteRaw) { buffer[output.ByteCount()] = '\0'; - EXPECT_STREQ("Hello World! This is the same line.\n" - "But this is a new one.\n" - "And this is another one." - "\n" - "From an object\n", - buffer); + EXPECT_STREQ( + "Hello World! This is the same line.\n" + "But this is a new one.\n" + "And this is another one." + "\n" + "From an object\n", + buffer); } } @@ -121,7 +122,7 @@ TEST(Printer, VariableSubstitution) { { Printer printer(&output, '$'); - std::map vars; + std::map vars; vars["foo"] = "World"; vars["bar"] = "$foo$"; @@ -139,13 +140,14 @@ TEST(Printer, VariableSubstitution) { buffer[output.ByteCount()] = '\0'; - EXPECT_STREQ("Hello World!\n" - "bar = $foo$\n" - "RawBit\n" - "1234\n" - "A literal dollar sign: $\n" - "Now foo = blah.", - buffer); + EXPECT_STREQ( + "Hello World!\n" + "bar = $foo$\n" + "RawBit\n" + "1234\n" + "A literal dollar sign: $\n" + "Now foo = blah.", + buffer); } } @@ -164,30 +166,31 @@ TEST(Printer, InlineVariableSubstitution) { buffer[output.ByteCount()] = '\0'; - EXPECT_STREQ("Hello World!\n" - "RawBit\n" - "one two\n", - buffer); + EXPECT_STREQ( + "Hello World!\n" + "RawBit\n" + "one two\n", + buffer); } // MockDescriptorFile defines only those members that Printer uses to write out // annotations. class MockDescriptorFile { public: - explicit MockDescriptorFile(const string& file) : file_(file) {} + explicit MockDescriptorFile(const std::string& file) : file_(file) {} // The mock filename for this file. - const string& name() const { return file_; } + const std::string& name() const { return file_; } private: - string file_; + std::string file_; }; // MockDescriptor defines only those members that Printer uses to write out // annotations. class MockDescriptor { public: - MockDescriptor(const string& file, const std::vector& path) + MockDescriptor(const std::string& file, const std::vector& path) : file_(file), path_(path) {} // The mock file in which this descriptor was defined. @@ -195,7 +198,7 @@ class MockDescriptor { private: // Allows access to GetLocationPath. - friend class ::google::protobuf::io::Printer; + friend class Printer; // Copies the pre-stored path to output. void GetLocationPath(std::vector* output) const { *output = path_; } @@ -211,7 +214,7 @@ TEST(Printer, AnnotateMap) { AnnotationProtoCollector info_collector(&info); { Printer printer(&output, '$', &info_collector); - std::map vars; + std::map vars; vars["foo"] = "3"; vars["bar"] = "5"; printer.Print(vars, "012$foo$4$bar$\n"); @@ -436,7 +439,6 @@ TEST(Printer, AnnotateIndentNewline) { EXPECT_EQ(4, ab->end()); } - TEST(Printer, Indenting) { char buffer[8192]; @@ -445,7 +447,7 @@ TEST(Printer, Indenting) { { Printer printer(&output, '$'); - std::map vars; + std::map vars; vars["newline"] = "\n"; @@ -455,11 +457,13 @@ TEST(Printer, Indenting) { printer.Outdent(); printer.Print("But this is not."); printer.Indent(); - printer.Print(" And this is still the same line.\n" - "But this is indented.\n"); + printer.Print( + " And this is still the same line.\n" + "But this is indented.\n"); printer.PrintRaw("RawBit has indent at start\n"); printer.PrintRaw("but not after a raw newline\n"); - printer.Print(vars, "Note that a newline in a variable will break " + printer.Print(vars, + "Note that a newline in a variable will break " "indenting, as we see$newline$here.\n"); printer.Indent(); printer.Print("And this"); @@ -473,18 +477,18 @@ TEST(Printer, Indenting) { buffer[output.ByteCount()] = '\0'; EXPECT_STREQ( - "This is not indented.\n" - " This is indented\n" - " And so is this\n" - "But this is not. And this is still the same line.\n" - " But this is indented.\n" - " RawBit has indent at start\n" - "but not after a raw newline\n" - "Note that a newline in a variable will break indenting, as we see\n" - "here.\n" - " And this is double-indented\n" - "Back to normal.", - buffer); + "This is not indented.\n" + " This is indented\n" + " And so is this\n" + "But this is not. And this is still the same line.\n" + " But this is indented.\n" + " RawBit has indent at start\n" + "but not after a raw newline\n" + "Note that a newline in a variable will break indenting, as we see\n" + "here.\n" + " And this is double-indented\n" + "Back to normal.", + buffer); } } @@ -569,7 +573,7 @@ TEST(Printer, WriteFailurePartial) { EXPECT_TRUE(printer.failed()); // Buffer should contain the first 17 bytes written. - EXPECT_EQ("0123456789abcdef<", string(buffer, sizeof(buffer))); + EXPECT_EQ("0123456789abcdef<", std::string(buffer, sizeof(buffer))); } TEST(Printer, WriteFailureExact) { @@ -591,10 +595,141 @@ TEST(Printer, WriteFailureExact) { EXPECT_TRUE(printer.failed()); // Buffer should contain the first 16 bytes written. - EXPECT_EQ("0123456789abcdef", string(buffer, sizeof(buffer))); + EXPECT_EQ("0123456789abcdef", std::string(buffer, sizeof(buffer))); +} + +TEST(Printer, FormatInternal) { + std::vector args{"arg1", "arg2"}; + std::map vars{ + {"foo", "bar"}, {"baz", "bla"}, {"empty", ""}}; + // Substitution tests + { + // Direct arg substitution + std::string s; + { + StringOutputStream output(&s); + Printer printer(&output, '$'); + printer.FormatInternal(args, vars, "$1$ $2$"); + } + EXPECT_EQ("arg1 arg2", s); + } + { + // Variable substitution including spaces left + std::string s; + { + StringOutputStream output(&s); + Printer printer(&output, '$'); + printer.FormatInternal({}, vars, "$foo$$ baz$$ empty$"); + } + EXPECT_EQ("bar bla", s); + } + { + // Variable substitution including spaces right + std::string s; + { + StringOutputStream output(&s); + Printer printer(&output, '$'); + printer.FormatInternal({}, vars, "$empty $$foo $$baz$"); + } + EXPECT_EQ("bar bla", s); + } + { + // Mixed variable substitution + std::string s; + { + StringOutputStream output(&s); + Printer printer(&output, '$'); + printer.FormatInternal(args, vars, "$empty $$1$ $foo $$2$ $baz$"); + } + EXPECT_EQ("arg1 bar arg2 bla", s); + } + + // Indentation tests + { + // Empty lines shouldn't indent. + std::string s; + { + StringOutputStream output(&s); + Printer printer(&output, '$'); + printer.Indent(); + printer.FormatInternal(args, vars, "$empty $\n\n$1$ $foo $$2$\n$baz$"); + printer.Outdent(); + } + EXPECT_EQ("\n\n arg1 bar arg2\n bla", s); + } + { + // Annotations should respect indentation. + std::string s; + GeneratedCodeInfo info; + { + StringOutputStream output(&s); + AnnotationProtoCollector info_collector(&info); + Printer printer(&output, '$', &info_collector); + printer.Indent(); + GeneratedCodeInfo::Annotation annotation; + annotation.set_source_file("file.proto"); + annotation.add_path(33); + std::vector args{annotation.SerializeAsString(), "arg1", + "arg2"}; + printer.FormatInternal(args, vars, "$empty $\n\n${1$$2$$}$ $3$\n$baz$"); + printer.Outdent(); + } + EXPECT_EQ("\n\n arg1 arg2\n bla", s); + ASSERT_EQ(1, info.annotation_size()); + const GeneratedCodeInfo::Annotation* arg1 = &info.annotation(0); + ASSERT_EQ(1, arg1->path_size()); + EXPECT_EQ(33, arg1->path(0)); + EXPECT_EQ("file.proto", arg1->source_file()); + EXPECT_EQ(4, arg1->begin()); + EXPECT_EQ(8, arg1->end()); + } +#ifdef PROTOBUF_HAS_DEATH_TEST + // Death tests in case of illegal format strings. + { + // Unused arguments + std::string s; + StringOutputStream output(&s); + Printer printer(&output, '$'); + EXPECT_DEATH(printer.FormatInternal(args, vars, "$empty $$1$"), "Unused"); + } + { + // Wrong order arguments + std::string s; + StringOutputStream output(&s); + Printer printer(&output, '$'); + EXPECT_DEATH(printer.FormatInternal(args, vars, "$2$ $1$"), "order"); + } + { + // Zero is illegal argument + std::string s; + StringOutputStream output(&s); + Printer printer(&output, '$'); + EXPECT_DEATH(printer.FormatInternal(args, vars, "$0$"), "failed"); + } + { + // Argument out of bounds + std::string s; + StringOutputStream output(&s); + Printer printer(&output, '$'); + EXPECT_DEATH(printer.FormatInternal(args, vars, "$1$ $2$ $3$"), "bounds"); + } + { + // Unknown variable + std::string s; + StringOutputStream output(&s); + Printer printer(&output, '$'); + EXPECT_DEATH(printer.FormatInternal(args, vars, "$huh$ $1$$2$"), "Unknown"); + } + { + // Illegal variable + std::string s; + StringOutputStream output(&s); + Printer printer(&output, '$'); + EXPECT_DEATH(printer.FormatInternal({}, vars, "$ $"), "Empty"); + } +#endif // PROTOBUF_HAS_DEATH_TEST } -} // namespace } // namespace io } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/io/strtod.cc b/src/google/protobuf/io/strtod.cc index a90bb9a31eff3..03acb5b294afb 100644 --- a/src/google/protobuf/io/strtod.cc +++ b/src/google/protobuf/io/strtod.cc @@ -38,88 +38,45 @@ #include #include +#include + namespace google { namespace protobuf { namespace io { -// ---------------------------------------------------------------------- -// NoLocaleStrtod() -// This code will make you cry. -// ---------------------------------------------------------------------- - -namespace { - -// Returns a string identical to *input except that the character pointed to -// by radix_pos (which should be '.') is replaced with the locale-specific -// radix character. -string LocalizeRadix(const char* input, const char* radix_pos) { - // Determine the locale-specific radix character by calling sprintf() to - // print the number 1.5, then stripping off the digits. As far as I can - // tell, this is the only portable, thread-safe way to get the C library - // to divuldge the locale's radix character. No, localeconv() is NOT - // thread-safe. - char temp[16]; - int size = sprintf(temp, "%.1f", 1.5); - GOOGLE_CHECK_EQ(temp[0], '1'); - GOOGLE_CHECK_EQ(temp[size-1], '5'); - GOOGLE_CHECK_LE(size, 6); - - // Now replace the '.' in the input with it. - string result; - result.reserve(strlen(input) + size - 3); - result.append(input, radix_pos); - result.append(temp + 1, size - 2); - result.append(radix_pos + 1); - return result; -} - -} // namespace - -double NoLocaleStrtod(const char* text, char** original_endptr) { - // We cannot simply set the locale to "C" temporarily with setlocale() - // as this is not thread-safe. Instead, we try to parse in the current - // locale first. If parsing stops at a '.' character, then this is a - // pretty good hint that we're actually in some other locale in which - // '.' is not the radix character. - - char* temp_endptr; - double result = strtod(text, &temp_endptr); - if (original_endptr != NULL) *original_endptr = temp_endptr; - if (*temp_endptr != '.') return result; - - // Parsing halted on a '.'. Perhaps we're in a different locale? Let's - // try to replace the '.' with a locale-specific radix character and - // try again. - string localized = LocalizeRadix(text, temp_endptr); - const char* localized_cstr = localized.c_str(); - char* localized_endptr; - result = strtod(localized_cstr, &localized_endptr); - if ((localized_endptr - localized_cstr) > - (temp_endptr - text)) { - // This attempt got further, so replacing the decimal must have helped. - // Update original_endptr to point at the right location. - if (original_endptr != NULL) { - // size_diff is non-zero if the localized radix has multiple bytes. - int size_diff = localized.size() - strlen(text); - // const_cast is necessary to match the strtod() interface. - *original_endptr = const_cast( - text + (localized_endptr - localized_cstr - size_diff)); - } - } - - return result; -} +// This approximately 0x1.ffffffp127, but we don't use 0x1.ffffffp127 because +// it won't compile in MSVC. +const double MAX_FLOAT_AS_DOUBLE_ROUNDED = 3.4028235677973366e+38; float SafeDoubleToFloat(double value) { + // static_cast on a number larger than float can result in illegal + // instruction error, so we need to manually convert it to infinity or max. if (value > std::numeric_limits::max()) { + // Max float value is about 3.4028234664E38 when represented as a double. + // However, when printing float as text, it will be rounded as + // 3.4028235e+38. If we parse the value of 3.4028235e+38 from text and + // compare it to 3.4028234664E38, we may think that it is larger, but + // actually, any number between these two numbers could only be represented + // as the same max float number in float, so we should treat them the same + // as max float. + if (value <= MAX_FLOAT_AS_DOUBLE_ROUNDED) { + return std::numeric_limits::max(); + } return std::numeric_limits::infinity(); } else if (value < -std::numeric_limits::max()) { + if (value >= -MAX_FLOAT_AS_DOUBLE_ROUNDED) { + return -std::numeric_limits::max(); + } return -std::numeric_limits::infinity(); } else { return static_cast(value); } } +double NoLocaleStrtod(const char* str, char** endptr) { + return google::protobuf::internal::NoLocaleStrtod(str, endptr); +} + } // namespace io } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/io/strtod.h b/src/google/protobuf/io/strtod.h index f56e41c840308..38f544af34c80 100644 --- a/src/google/protobuf/io/strtod.h +++ b/src/google/protobuf/io/strtod.h @@ -50,6 +50,6 @@ float SafeDoubleToFloat(double value); } // namespace io } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_IO_STRTOD_H__ diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc index 916d1606b767d..129b4889e53db 100644 --- a/src/google/protobuf/io/tokenizer.cc +++ b/src/google/protobuf/io/tokenizer.cc @@ -89,12 +89,13 @@ // exactly pretty. #include + #include #include #include +#include #include #include -#include #include namespace google { @@ -113,39 +114,34 @@ namespace { // Note: No class is allowed to contain '\0', since this is used to mark end- // of-input and is handled specially. -#define CHARACTER_CLASS(NAME, EXPRESSION) \ - class NAME { \ - public: \ - static inline bool InClass(char c) { \ - return EXPRESSION; \ - } \ +#define CHARACTER_CLASS(NAME, EXPRESSION) \ + class NAME { \ + public: \ + static inline bool InClass(char c) { return EXPRESSION; } \ } -CHARACTER_CLASS(Whitespace, c == ' ' || c == '\n' || c == '\t' || - c == '\r' || c == '\v' || c == '\f'); -CHARACTER_CLASS(WhitespaceNoNewline, c == ' ' || c == '\t' || - c == '\r' || c == '\v' || c == '\f'); +CHARACTER_CLASS(Whitespace, c == ' ' || c == '\n' || c == '\t' || c == '\r' || + c == '\v' || c == '\f'); +CHARACTER_CLASS(WhitespaceNoNewline, + c == ' ' || c == '\t' || c == '\r' || c == '\v' || c == '\f'); -CHARACTER_CLASS(Unprintable, c < ' ' && c > '\0'); +CHARACTER_CLASS(Unprintable, c<' ' && c> '\0'); CHARACTER_CLASS(Digit, '0' <= c && c <= '9'); CHARACTER_CLASS(OctalDigit, '0' <= c && c <= '7'); -CHARACTER_CLASS(HexDigit, ('0' <= c && c <= '9') || - ('a' <= c && c <= 'f') || - ('A' <= c && c <= 'F')); +CHARACTER_CLASS(HexDigit, ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || + ('A' <= c && c <= 'F')); -CHARACTER_CLASS(Letter, ('a' <= c && c <= 'z') || - ('A' <= c && c <= 'Z') || - (c == '_')); +CHARACTER_CLASS(Letter, + ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '_')); CHARACTER_CLASS(Alphanumeric, ('a' <= c && c <= 'z') || - ('A' <= c && c <= 'Z') || - ('0' <= c && c <= '9') || - (c == '_')); + ('A' <= c && c <= 'Z') || + ('0' <= c && c <= '9') || (c == '_')); CHARACTER_CLASS(Escape, c == 'a' || c == 'b' || c == 'f' || c == 'n' || - c == 'r' || c == 't' || c == 'v' || c == '\\' || - c == '?' || c == '\'' || c == '\"'); + c == 'r' || c == 't' || c == 'v' || c == '\\' || + c == '?' || c == '\'' || c == '\"'); #undef CHARACTER_CLASS @@ -161,20 +157,32 @@ inline int DigitValue(char digit) { // Inline because it's only used in one place. inline char TranslateEscape(char c) { switch (c) { - case 'a': return '\a'; - case 'b': return '\b'; - case 'f': return '\f'; - case 'n': return '\n'; - case 'r': return '\r'; - case 't': return '\t'; - case 'v': return '\v'; - case '\\': return '\\'; - case '?': return '\?'; // Trigraphs = :( - case '\'': return '\''; - case '"': return '\"'; + case 'a': + return '\a'; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + case 'v': + return '\v'; + case '\\': + return '\\'; + case '?': + return '\?'; // Trigraphs = :( + case '\'': + return '\''; + case '"': + return '\"'; // We expect escape sequences to have been validated separately. - default: return '?'; + default: + return '?'; } } @@ -186,21 +194,20 @@ ErrorCollector::~ErrorCollector() {} Tokenizer::Tokenizer(ZeroCopyInputStream* input, ErrorCollector* error_collector) - : input_(input), - error_collector_(error_collector), - buffer_(NULL), - buffer_size_(0), - buffer_pos_(0), - read_error_(false), - line_(0), - column_(0), - record_target_(NULL), - record_start_(-1), - allow_f_after_float_(false), - comment_style_(CPP_COMMENT_STYLE), - require_space_after_number_(true), - allow_multiline_strings_(false) { - + : input_(input), + error_collector_(error_collector), + buffer_(NULL), + buffer_size_(0), + buffer_pos_(0), + read_error_(false), + line_(0), + column_(0), + record_target_(NULL), + record_start_(-1), + allow_f_after_float_(false), + comment_style_(CPP_COMMENT_STYLE), + require_space_after_number_(true), + allow_multiline_strings_(false) { current_.line = 0; current_.column = 0; current_.end_column = 0; @@ -249,7 +256,8 @@ void Tokenizer::Refresh() { // If we're in a token, append the rest of the buffer to it. if (record_target_ != NULL && record_start_ < buffer_size_) { - record_target_->append(buffer_ + record_start_, buffer_size_ - record_start_); + record_target_->append(buffer_ + record_start_, + buffer_size_ - record_start_); record_start_ = 0; } @@ -271,7 +279,7 @@ void Tokenizer::Refresh() { current_char_ = buffer_[0]; } -inline void Tokenizer::RecordTo(string* target) { +inline void Tokenizer::RecordTo(std::string* target) { record_target_ = target; record_start_ = buffer_pos_; } @@ -282,14 +290,15 @@ inline void Tokenizer::StopRecording() { // be helpful by detecting the NULL pointer, even though there's nothing // wrong with reading zero bytes from NULL. if (buffer_pos_ != record_start_) { - record_target_->append(buffer_ + record_start_, buffer_pos_ - record_start_); + record_target_->append(buffer_ + record_start_, + buffer_pos_ - record_start_); } record_target_ = NULL; record_start_ = -1; } inline void Tokenizer::StartToken() { - current_.type = TYPE_START; // Just for the sake of initializing it. + current_.type = TYPE_START; // Just for the sake of initializing it. current_.text.clear(); current_.line = line_; current_.column = column_; @@ -304,12 +313,12 @@ inline void Tokenizer::EndToken() { // ------------------------------------------------------------------- // Helper methods that consume characters. -template +template inline bool Tokenizer::LookingAt() { return CharacterClass::InClass(current_char_); } -template +template inline bool Tokenizer::TryConsumeOne() { if (CharacterClass::InClass(current_char_)) { NextChar(); @@ -328,14 +337,14 @@ inline bool Tokenizer::TryConsume(char c) { } } -template +template inline void Tokenizer::ConsumeZeroOrMore() { while (CharacterClass::InClass(current_char_)) { NextChar(); } } -template +template inline void Tokenizer::ConsumeOneOrMore(const char* error) { if (!CharacterClass::InClass(current_char_)) { AddError(error); @@ -381,25 +390,21 @@ void Tokenizer::ConsumeString(char delimiter) { } // Possibly followed by another hex digit, but again we don't care. } else if (TryConsume('u')) { - if (!TryConsumeOne() || - !TryConsumeOne() || - !TryConsumeOne() || - !TryConsumeOne()) { + if (!TryConsumeOne() || !TryConsumeOne() || + !TryConsumeOne() || !TryConsumeOne()) { AddError("Expected four hex digits for \\u escape sequence."); } } else if (TryConsume('U')) { // We expect 8 hex digits; but only the range up to 0x10ffff is // legal. - if (!TryConsume('0') || - !TryConsume('0') || + if (!TryConsume('0') || !TryConsume('0') || !(TryConsume('0') || TryConsume('1')) || - !TryConsumeOne() || - !TryConsumeOne() || - !TryConsumeOne() || - !TryConsumeOne() || + !TryConsumeOne() || !TryConsumeOne() || + !TryConsumeOne() || !TryConsumeOne() || !TryConsumeOne()) { - AddError("Expected eight hex digits up to 10ffff for \\U escape " - "sequence"); + AddError( + "Expected eight hex digits up to 10ffff for \\U escape " + "sequence"); } } else { AddError("Invalid escape sequence in string literal."); @@ -465,7 +470,7 @@ Tokenizer::TokenType Tokenizer::ConsumeNumber(bool started_with_zero, } else if (current_char_ == '.') { if (is_float) { AddError( - "Already saw decimal point or exponent; can't have another one."); + "Already saw decimal point or exponent; can't have another one."); } else { AddError("Hex and octal numbers must be integers."); } @@ -474,7 +479,7 @@ Tokenizer::TokenType Tokenizer::ConsumeNumber(bool started_with_zero, return is_float ? TYPE_FLOAT : TYPE_INTEGER; } -void Tokenizer::ConsumeLineComment(string* content) { +void Tokenizer::ConsumeLineComment(std::string* content) { if (content != NULL) RecordTo(content); while (current_char_ != '\0' && current_char_ != '\n') { @@ -485,17 +490,15 @@ void Tokenizer::ConsumeLineComment(string* content) { if (content != NULL) StopRecording(); } -void Tokenizer::ConsumeBlockComment(string* content) { +void Tokenizer::ConsumeBlockComment(std::string* content) { int start_line = line_; int start_column = column_ - 2; if (content != NULL) RecordTo(content); while (true) { - while (current_char_ != '\0' && - current_char_ != '*' && - current_char_ != '/' && - current_char_ != '\n') { + while (current_char_ != '\0' && current_char_ != '*' && + current_char_ != '/' && current_char_ != '\n') { NextChar(); } @@ -524,11 +527,11 @@ void Tokenizer::ConsumeBlockComment(string* content) { // Note: We didn't consume the '*' because if there is a '/' after it // we want to interpret that as the end of the comment. AddError( - "\"/*\" inside block comment. Block comments cannot be nested."); + "\"/*\" inside block comment. Block comments cannot be nested."); } else if (current_char_ == '\0') { AddError("End-of-file inside block comment."); - error_collector_->AddError( - start_line, start_column, " Comment started here."); + error_collector_->AddError(start_line, start_column, + " Comment started here."); if (content != NULL) StopRecording(); break; } @@ -613,8 +616,9 @@ bool Tokenizer::Next() { current_.line == previous_.line && current_.column == previous_.end_column) { // We don't accept syntax like "blah.123". - error_collector_->AddError(line_, column_ - 2, - "Need space between identifier and decimal point."); + error_collector_->AddError( + line_, column_ - 2, + "Need space between identifier and decimal point."); } current_.type = ConsumeNumber(false, true); } else { @@ -631,7 +635,8 @@ bool Tokenizer::Next() { } else { // Check if the high order bit is set. if (current_char_ & 0x80) { - error_collector_->AddError(line_, column_, + error_collector_->AddError( + line_, column_, StringPrintf("Interpreting non ascii codepoint %d.", static_cast(current_char_))); } @@ -664,9 +669,9 @@ namespace { // next_leading_comments. class CommentCollector { public: - CommentCollector(string* prev_trailing_comments, - std::vector* detached_comments, - string* next_leading_comments) + CommentCollector(std::string* prev_trailing_comments, + std::vector* detached_comments, + std::string* next_leading_comments) : prev_trailing_comments_(prev_trailing_comments), detached_comments_(detached_comments), next_leading_comments_(next_leading_comments), @@ -687,7 +692,7 @@ class CommentCollector { // About to read a line comment. Get the comment buffer pointer in order to // read into it. - string* GetBufferForLineComment() { + std::string* GetBufferForLineComment() { // We want to combine with previous line comments, but not block comments. if (has_comment_ && !is_line_comment_) { Flush(); @@ -699,7 +704,7 @@ class CommentCollector { // About to read a block comment. Get the comment buffer pointer in order to // read into it. - string* GetBufferForBlockComment() { + std::string* GetBufferForBlockComment() { if (has_comment_) { Flush(); } @@ -731,16 +736,14 @@ class CommentCollector { } } - void DetachFromPrev() { - can_attach_to_prev_ = false; - } + void DetachFromPrev() { can_attach_to_prev_ = false; } private: - string* prev_trailing_comments_; - std::vector* detached_comments_; - string* next_leading_comments_; + std::string* prev_trailing_comments_; + std::vector* detached_comments_; + std::string* next_leading_comments_; - string comment_buffer_; + std::string comment_buffer_; // True if any comments were read into comment_buffer_. This can be true even // if comment_buffer_ is empty, namely if the comment was "/**/". @@ -754,11 +757,11 @@ class CommentCollector { bool can_attach_to_prev_; }; -} // namespace +} // namespace -bool Tokenizer::NextWithComments(string* prev_trailing_comments, - std::vector* detached_comments, - string* next_leading_comments) { +bool Tokenizer::NextWithComments(std::string* prev_trailing_comments, + std::vector* detached_comments, + std::string* next_leading_comments) { CommentCollector collector(prev_trailing_comments, detached_comments, next_leading_comments); @@ -767,8 +770,9 @@ bool Tokenizer::NextWithComments(string* prev_trailing_comments, // beginning. Only UTF-8 BOM (0xEF 0xBB 0xBF) is accepted. if (TryConsume((char)0xEF)) { if (!TryConsume((char)0xBB) || !TryConsume((char)0xBF)) { - AddError("Proto file starts with 0xEF but not UTF-8 BOM. " - "Only UTF-8 is accepted for proto file."); + AddError( + "Proto file starts with 0xEF but not UTF-8 BOM. " + "Only UTF-8 is accepted for proto file."); return false; } } @@ -836,9 +840,7 @@ bool Tokenizer::NextWithComments(string* prev_trailing_comments, collector.DetachFromPrev(); } else { bool result = Next(); - if (!result || - current_.text == "}" || - current_.text == "]" || + if (!result || current_.text == "}" || current_.text == "]" || current_.text == ")") { // It looks like we're at the end of a scope. In this case it // makes no sense to attach a comment to the following token. @@ -858,12 +860,12 @@ bool Tokenizer::NextWithComments(string* prev_trailing_comments, // are given is text that the tokenizer actually parsed as a token // of the given type. -bool Tokenizer::ParseInteger(const string& text, uint64 max_value, +bool Tokenizer::ParseInteger(const std::string& text, uint64 max_value, uint64* output) { // Sadly, we can't just use strtoul() since it is only 32-bit and strtoull() // is non-standard. I hate the C standard library. :( -// return strtoull(text.c_str(), NULL, 0); + // return strtoull(text.c_str(), NULL, 0); const char* ptr = text.c_str(); int base = 10; @@ -886,7 +888,8 @@ bool Tokenizer::ParseInteger(const string& text, uint64 max_value, // token, but Tokenizer still think it's integer. return false; } - if (digit > max_value || result > (max_value - digit) / base) { + if (static_cast(digit) > max_value || + result > (max_value - digit) / base) { // Overflow. return false; } @@ -897,7 +900,7 @@ bool Tokenizer::ParseInteger(const string& text, uint64 max_value, return true; } -double Tokenizer::ParseFloat(const string& text) { +double Tokenizer::ParseFloat(const std::string& text) { const char* start = text.c_str(); char* end; double result = NoLocaleStrtod(start, &end); @@ -916,41 +919,38 @@ double Tokenizer::ParseFloat(const string& text) { ++end; } - GOOGLE_LOG_IF(DFATAL, end - start != text.size() || *start == '-') - << " Tokenizer::ParseFloat() passed text that could not have been" - " tokenized as a float: " << CEscape(text); + GOOGLE_LOG_IF(DFATAL, + static_cast(end - start) != text.size() || *start == '-') + << " Tokenizer::ParseFloat() passed text that could not have been" + " tokenized as a float: " + << CEscape(text); return result; } // Helper to append a Unicode code point to a string as UTF8, without bringing // in any external dependencies. -static void AppendUTF8(uint32 code_point, string* output) { +static void AppendUTF8(uint32 code_point, std::string* output) { uint32 tmp = 0; int len = 0; if (code_point <= 0x7f) { tmp = code_point; len = 1; } else if (code_point <= 0x07ff) { - tmp = 0x0000c080 | - ((code_point & 0x07c0) << 2) | - (code_point & 0x003f); + tmp = 0x0000c080 | ((code_point & 0x07c0) << 2) | (code_point & 0x003f); len = 2; } else if (code_point <= 0xffff) { - tmp = 0x00e08080 | - ((code_point & 0xf000) << 4) | - ((code_point & 0x0fc0) << 2) | - (code_point & 0x003f); + tmp = 0x00e08080 | ((code_point & 0xf000) << 4) | + ((code_point & 0x0fc0) << 2) | (code_point & 0x003f); len = 3; - } else if (code_point <= 0x1fffff) { - tmp = 0xf0808080 | - ((code_point & 0x1c0000) << 6) | - ((code_point & 0x03f000) << 4) | - ((code_point & 0x000fc0) << 2) | - (code_point & 0x003f); + } else if (code_point <= 0x10ffff) { + tmp = 0xf0808080 | ((code_point & 0x1c0000) << 6) | + ((code_point & 0x03f000) << 4) | ((code_point & 0x000fc0) << 2) | + (code_point & 0x003f); len = 4; } else { - // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is - // normally only defined up to there as well. + // Unicode code points end at 0x10FFFF, so this is out-of-range. + // ConsumeString permits hex values up to 0x1FFFFF, and FetchUnicodePoint + // doesn't perform a range check. StringAppendF(output, "\\U%08x", code_point); return; } @@ -986,7 +986,7 @@ static inline bool IsHeadSurrogate(uint32 code_point) { static inline bool IsTrailSurrogate(uint32 code_point) { return (code_point >= kMinTrailSurrogate) && - (code_point < kMaxTrailSurrogate); + (code_point < kMaxTrailSurrogate); } // Combine a head and trail surrogate into a single Unicode code point. @@ -994,7 +994,7 @@ static uint32 AssembleUTF16(uint32 head_surrogate, uint32 trail_surrogate) { GOOGLE_DCHECK(IsHeadSurrogate(head_surrogate)); GOOGLE_DCHECK(IsTrailSurrogate(trail_surrogate)); return 0x10000 + (((head_surrogate - kMinHeadSurrogate) << 10) | - (trail_surrogate - kMinTrailSurrogate)); + (trail_surrogate - kMinTrailSurrogate)); } // Convert the escape sequence parameter to a number of expected hex digits. @@ -1012,8 +1012,7 @@ static const char* FetchUnicodePoint(const char* ptr, uint32* code_point) { const char* p = ptr; // Fetch the code point. const int len = UnicodeLength(*p++); - if (!ReadHexDigits(p, len, code_point)) - return ptr; + if (!ReadHexDigits(p, len, code_point)) return ptr; p += len; // Check if the code point we read is a "head surrogate." If so, then we @@ -1036,14 +1035,15 @@ static const char* FetchUnicodePoint(const char* ptr, uint32* code_point) { // The text string must begin and end with single or double quote // characters. -void Tokenizer::ParseStringAppend(const string& text, string* output) { +void Tokenizer::ParseStringAppend(const std::string& text, + std::string* output) { // Reminder: text[0] is always a quote character. (If text is // empty, it's invalid, so we'll just return). const size_t text_size = text.size(); if (text_size == 0) { - GOOGLE_LOG(DFATAL) - << " Tokenizer::ParseStringAppend() passed text that could not" - " have been tokenized as a string: " << CEscape(text); + GOOGLE_LOG(DFATAL) << " Tokenizer::ParseStringAppend() passed text that could not" + " have been tokenized as a string: " + << CEscape(text); return; } @@ -1114,23 +1114,19 @@ void Tokenizer::ParseStringAppend(const string& text, string* output) { } } -template -static bool AllInClass(const string& s) { - for (int i = 0; i < s.size(); ++i) { - if (!CharacterClass::InClass(s[i])) - return false; +template +static bool AllInClass(const std::string& s) { + for (const char character : s) { + if (!CharacterClass::InClass(character)) return false; } return true; } -bool Tokenizer::IsIdentifier(const string& text) { +bool Tokenizer::IsIdentifier(const std::string& text) { // Mirrors IDENTIFIER definition in Tokenizer::Next() above. - if (text.size() == 0) - return false; - if (!Letter::InClass(text.at(0))) - return false; - if (!AllInClass(text.substr(1))) - return false; + if (text.size() == 0) return false; + if (!Letter::InClass(text.at(0))) return false; + if (!AllInClass(text.substr(1))) return false; return true; } diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h index e80d564cd5e8f..551516ea39705 100644 --- a/src/google/protobuf/io/tokenizer.h +++ b/src/google/protobuf/io/tokenizer.h @@ -37,16 +37,19 @@ #ifndef GOOGLE_PROTOBUF_IO_TOKENIZER_H__ #define GOOGLE_PROTOBUF_IO_TOKENIZER_H__ + #include #include + #include #include +#include namespace google { namespace protobuf { namespace io { -class ZeroCopyInputStream; // zero_copy_stream.h +class ZeroCopyInputStream; // zero_copy_stream.h // Defined in this file. class ErrorCollector; @@ -61,7 +64,7 @@ typedef int ColumnNumber; // Abstract interface for an object which collects the errors that occur // during parsing. A typical implementation might simply print the errors // to stdout. -class LIBPROTOBUF_EXPORT ErrorCollector { +class PROTOBUF_EXPORT ErrorCollector { public: inline ErrorCollector() {} virtual ~ErrorCollector(); @@ -70,13 +73,13 @@ class LIBPROTOBUF_EXPORT ErrorCollector { // column numbers. The numbers are zero-based, so you may want to add // 1 to each before printing them. virtual void AddError(int line, ColumnNumber column, - const string& message) = 0; + const std::string& message) = 0; // Indicates that there was a warning in the input at the given line and // column numbers. The numbers are zero-based, so you may want to add // 1 to each before printing them. virtual void AddWarning(int line, ColumnNumber column, - const string& message) { } + const std::string& message) {} private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector); @@ -88,7 +91,7 @@ class LIBPROTOBUF_EXPORT ErrorCollector { // precise descriptions. Whitespace and comments are skipped. By default, // C- and C++-style comments are recognized, but other styles can be used by // calling set_comment_style(). -class LIBPROTOBUF_EXPORT Tokenizer { +class PROTOBUF_EXPORT Tokenizer { public: // Construct a Tokenizer that reads and tokenizes text from the given // input stream and writes errors to the given error_collector. @@ -97,8 +100,8 @@ class LIBPROTOBUF_EXPORT Tokenizer { ~Tokenizer(); enum TokenType { - TYPE_START, // Next() has not yet been called. - TYPE_END, // End of input reached. "text" is empty. + TYPE_START, // Next() has not yet been called. + TYPE_END, // End of input reached. "text" is empty. TYPE_IDENTIFIER, // A sequence of letters, digits, and underscores, not // starting with a digit. It is an error for a number @@ -124,7 +127,7 @@ class LIBPROTOBUF_EXPORT Tokenizer { // Structure representing a token read from the token stream. struct Token { TokenType type; - string text; // The exact text of the token as it appeared in + std::string text; // The exact text of the token as it appeared in // the input. e.g. tokens of TYPE_STRING will still // be escaped and in quotes. @@ -190,31 +193,31 @@ class LIBPROTOBUF_EXPORT Tokenizer { // /* Block comment attached to // * grault. */ // optional int32 grault = 6; - bool NextWithComments(string* prev_trailing_comments, - std::vector* detached_comments, - string* next_leading_comments); + bool NextWithComments(std::string* prev_trailing_comments, + std::vector* detached_comments, + std::string* next_leading_comments); // Parse helpers --------------------------------------------------- // Parses a TYPE_FLOAT token. This never fails, so long as the text actually // comes from a TYPE_FLOAT token parsed by Tokenizer. If it doesn't, the // result is undefined (possibly an assert failure). - static double ParseFloat(const string& text); + static double ParseFloat(const std::string& text); // Parses a TYPE_STRING token. This never fails, so long as the text actually // comes from a TYPE_STRING token parsed by Tokenizer. If it doesn't, the // result is undefined (possibly an assert failure). - static void ParseString(const string& text, string* output); + static void ParseString(const std::string& text, std::string* output); // Identical to ParseString, but appends to output. - static void ParseStringAppend(const string& text, string* output); + static void ParseStringAppend(const std::string& text, std::string* output); // Parses a TYPE_INTEGER token. Returns false if the result would be // greater than max_value. Otherwise, returns true and sets *output to the // result. If the text is not from a Token of type TYPE_INTEGER originally // parsed by a Tokenizer, the result is undefined (possibly an assert // failure). - static bool ParseInteger(const string& text, uint64 max_value, + static bool ParseInteger(const std::string& text, uint64 max_value, uint64* output); // Options --------------------------------------------------------- @@ -250,23 +253,23 @@ class LIBPROTOBUF_EXPORT Tokenizer { } // External helper: validate an identifier. - static bool IsIdentifier(const string& text); + static bool IsIdentifier(const std::string& text); // ----------------------------------------------------------------- private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer); - Token current_; // Returned by current(). - Token previous_; // Returned by previous(). + Token current_; // Returned by current(). + Token previous_; // Returned by previous(). ZeroCopyInputStream* input_; ErrorCollector* error_collector_; - char current_char_; // == buffer_[buffer_pos_], updated by NextChar(). - const char* buffer_; // Current buffer returned from input_. - int buffer_size_; // Size of buffer_. - int buffer_pos_; // Current position within the buffer. - bool read_error_; // Did we previously encounter a read error? + char current_char_; // == buffer_[buffer_pos_], updated by NextChar(). + const char* buffer_; // Current buffer returned from input_. + int buffer_size_; // Size of buffer_. + int buffer_pos_; // Current position within the buffer. + bool read_error_; // Did we previously encounter a read error? // Line and column number of current_char_ within the whole input stream. int line_; @@ -276,7 +279,7 @@ class LIBPROTOBUF_EXPORT Tokenizer { // Call RecordTo(&str) to start recording and StopRecording() to stop. // E.g. StartToken() calls RecordTo(¤t_.text). record_start_ is the // position within the current buffer where recording started. - string* record_target_; + std::string* record_target_; int record_start_; // Options. @@ -299,7 +302,7 @@ class LIBPROTOBUF_EXPORT Tokenizer { // Read a new buffer from the input. void Refresh(); - inline void RecordTo(string* target); + inline void RecordTo(std::string* target); inline void StopRecording(); // Called when the current character is the first character of a new @@ -311,7 +314,7 @@ class LIBPROTOBUF_EXPORT Tokenizer { inline void EndToken(); // Convenience method to add an error at the current line and column. - void AddError(const string& message) { + void AddError(const std::string& message) { error_collector_->AddError(line_, column_, message); } @@ -334,9 +337,9 @@ class LIBPROTOBUF_EXPORT Tokenizer { TokenType ConsumeNumber(bool started_with_zero, bool started_with_dot); // Consume the rest of a line. - void ConsumeLineComment(string* content); + void ConsumeLineComment(std::string* content); // Consume until "*/". - void ConsumeBlockComment(string* content); + void ConsumeBlockComment(std::string* content); enum NextCommentStatus { // Started a line comment. @@ -367,45 +370,44 @@ class LIBPROTOBUF_EXPORT Tokenizer { // Returns true if the current character is of the given character // class, but does not consume anything. - template + template inline bool LookingAt(); // If the current character is in the given class, consume it and return // true. Otherwise return false. // e.g. TryConsumeOne() - template + template inline bool TryConsumeOne(); // Like above, but try to consume the specific character indicated. inline bool TryConsume(char c); // Consume zero or more of the given character class. - template + template inline void ConsumeZeroOrMore(); // Consume one or more of the given character class or log the given // error message. // e.g. ConsumeOneOrMore("Expected digits."); - template + template inline void ConsumeOneOrMore(const char* error); }; // inline methods ==================================================== -inline const Tokenizer::Token& Tokenizer::current() { - return current_; -} +inline const Tokenizer::Token& Tokenizer::current() { return current_; } -inline const Tokenizer::Token& Tokenizer::previous() { - return previous_; -} +inline const Tokenizer::Token& Tokenizer::previous() { return previous_; } -inline void Tokenizer::ParseString(const string& text, string* output) { +inline void Tokenizer::ParseString(const std::string& text, + std::string* output) { output->clear(); ParseStringAppend(text, output); } } // namespace io } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_IO_TOKENIZER_H__ diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc index e55288e2ff018..91c440cebfa3e 100644 --- a/src/google/protobuf/io/tokenizer_unittest.cc +++ b/src/google/protobuf/io/tokenizer_unittest.cc @@ -32,18 +32,18 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include + #include #include #include -#include -#include - #include #include #include #include +#include #include #include @@ -56,7 +56,7 @@ namespace { // Data-Driven Test Infrastructure // TODO(kenton): This is copied from coded_stream_unittest. This is -// temporary until these fetaures are integrated into gTest itself. +// temporary until these features are integrated into gTest itself. // TEST_1D and TEST_2D are macros I'd eventually like to see added to // gTest. These macros can be used to declare tests which should be @@ -75,45 +75,45 @@ namespace { // which failed will be printed. The case type must be printable using // ostream::operator<<. -#define TEST_1D(FIXTURE, NAME, CASES) \ - class FIXTURE##_##NAME##_DD : public FIXTURE { \ - protected: \ - template \ - void DoSingleCase(const CaseType& CASES##_case); \ - }; \ - \ - TEST_F(FIXTURE##_##NAME##_DD, NAME) { \ - for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES); i++) { \ - SCOPED_TRACE(testing::Message() \ - << #CASES " case #" << i << ": " << CASES[i]); \ - DoSingleCase(CASES[i]); \ - } \ - } \ - \ - template \ +#define TEST_1D(FIXTURE, NAME, CASES) \ + class FIXTURE##_##NAME##_DD : public FIXTURE { \ + protected: \ + template \ + void DoSingleCase(const CaseType& CASES##_case); \ + }; \ + \ + TEST_F(FIXTURE##_##NAME##_DD, NAME) { \ + for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES); i++) { \ + SCOPED_TRACE(testing::Message() \ + << #CASES " case #" << i << ": " << CASES[i]); \ + DoSingleCase(CASES[i]); \ + } \ + } \ + \ + template \ void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType& CASES##_case) -#define TEST_2D(FIXTURE, NAME, CASES1, CASES2) \ - class FIXTURE##_##NAME##_DD : public FIXTURE { \ - protected: \ - template \ - void DoSingleCase(const CaseType1& CASES1##_case, \ - const CaseType2& CASES2##_case); \ - }; \ - \ - TEST_F(FIXTURE##_##NAME##_DD, NAME) { \ - for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES1); i++) { \ - for (int j = 0; j < GOOGLE_ARRAYSIZE(CASES2); j++) { \ - SCOPED_TRACE(testing::Message() \ - << #CASES1 " case #" << i << ": " << CASES1[i] << ", " \ - << #CASES2 " case #" << j << ": " << CASES2[j]); \ - DoSingleCase(CASES1[i], CASES2[j]); \ - } \ - } \ - } \ - \ - template \ - void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType1& CASES1##_case, \ +#define TEST_2D(FIXTURE, NAME, CASES1, CASES2) \ + class FIXTURE##_##NAME##_DD : public FIXTURE { \ + protected: \ + template \ + void DoSingleCase(const CaseType1& CASES1##_case, \ + const CaseType2& CASES2##_case); \ + }; \ + \ + TEST_F(FIXTURE##_##NAME##_DD, NAME) { \ + for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES1); i++) { \ + for (int j = 0; j < GOOGLE_ARRAYSIZE(CASES2); j++) { \ + SCOPED_TRACE(testing::Message() \ + << #CASES1 " case #" << i << ": " << CASES1[i] << ", " \ + << #CASES2 " case #" << j << ": " << CASES2[j]); \ + DoSingleCase(CASES1[i], CASES2[j]); \ + } \ + } \ + } \ + \ + template \ + void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType1& CASES1##_case, \ const CaseType2& CASES2##_case) // ------------------------------------------------------------------- @@ -123,11 +123,11 @@ namespace { class TestInputStream : public ZeroCopyInputStream { public: TestInputStream(const void* data, int size, int block_size) - : array_stream_(data, size, block_size), counter_(0) {} + : array_stream_(data, size, block_size), counter_(0) {} ~TestInputStream() {} // implements ZeroCopyInputStream ---------------------------------- - bool Next(const void** data, int* size) { + bool Next(const void** data, int* size) override { // We'll return empty buffers starting with the first buffer, and every // 3 and 5 buffers after that. if (counter_ % 3 == 0 || counter_ % 5 == 0) { @@ -141,9 +141,9 @@ class TestInputStream : public ZeroCopyInputStream { } } - void BackUp(int count) { return array_stream_.BackUp(count); } - bool Skip(int count) { return array_stream_.Skip(count); } - int64 ByteCount() const { return array_stream_.ByteCount(); } + void BackUp(int count) override { return array_stream_.BackUp(count); } + bool Skip(int count) override { return array_stream_.Skip(count); } + int64_t ByteCount() const override { return array_stream_.ByteCount(); } private: ArrayInputStream array_stream_; @@ -159,12 +159,11 @@ class TestErrorCollector : public ErrorCollector { TestErrorCollector() {} ~TestErrorCollector() {} - string text_; + std::string text_; // implements ErrorCollector --------------------------------------- - void AddError(int line, int column, const string& message) { - strings::SubstituteAndAppend(&text_, "$0:$1: $2\n", - line, column, message); + void AddError(int line, int column, const std::string& message) { + strings::SubstituteAndAppend(&text_, "$0:$1: $2\n", line, column, message); } }; @@ -179,7 +178,7 @@ const int kBlockSizes[] = {1, 2, 3, 5, 7, 13, 32, 1024}; class TokenizerTest : public testing::Test { protected: // For easy testing. - uint64 ParseInteger(const string& text) { + uint64 ParseInteger(const std::string& text) { uint64 result; EXPECT_TRUE(Tokenizer::ParseInteger(text, kuint64max, &result)); return result; @@ -195,7 +194,7 @@ class TokenizerTest : public testing::Test { // In each test case, the entire input text should parse as a single token // of the given type. struct SimpleTokenCase { - string input; + std::string input; Tokenizer::TokenType type; }; @@ -205,52 +204,51 @@ inline std::ostream& operator<<(std::ostream& out, } SimpleTokenCase kSimpleTokenCases[] = { - // Test identifiers. - { "hello", Tokenizer::TYPE_IDENTIFIER }, - - // Test integers. - { "123", Tokenizer::TYPE_INTEGER }, - { "0xab6", Tokenizer::TYPE_INTEGER }, - { "0XAB6", Tokenizer::TYPE_INTEGER }, - { "0X1234567", Tokenizer::TYPE_INTEGER }, - { "0x89abcdef", Tokenizer::TYPE_INTEGER }, - { "0x89ABCDEF", Tokenizer::TYPE_INTEGER }, - { "01234567", Tokenizer::TYPE_INTEGER }, - - // Test floats. - { "123.45", Tokenizer::TYPE_FLOAT }, - { "1.", Tokenizer::TYPE_FLOAT }, - { "1e3", Tokenizer::TYPE_FLOAT }, - { "1E3", Tokenizer::TYPE_FLOAT }, - { "1e-3", Tokenizer::TYPE_FLOAT }, - { "1e+3", Tokenizer::TYPE_FLOAT }, - { "1.e3", Tokenizer::TYPE_FLOAT }, - { "1.2e3", Tokenizer::TYPE_FLOAT }, - { ".1", Tokenizer::TYPE_FLOAT }, - { ".1e3", Tokenizer::TYPE_FLOAT }, - { ".1e-3", Tokenizer::TYPE_FLOAT }, - { ".1e+3", Tokenizer::TYPE_FLOAT }, - - // Test strings. - { "'hello'", Tokenizer::TYPE_STRING }, - { "\"foo\"", Tokenizer::TYPE_STRING }, - { "'a\"b'", Tokenizer::TYPE_STRING }, - { "\"a'b\"", Tokenizer::TYPE_STRING }, - { "'a\\'b'", Tokenizer::TYPE_STRING }, - { "\"a\\\"b\"", Tokenizer::TYPE_STRING }, - { "'\\xf'", Tokenizer::TYPE_STRING }, - { "'\\0'", Tokenizer::TYPE_STRING }, - - // Test symbols. - { "+", Tokenizer::TYPE_SYMBOL }, - { ".", Tokenizer::TYPE_SYMBOL }, + // Test identifiers. + {"hello", Tokenizer::TYPE_IDENTIFIER}, + + // Test integers. + {"123", Tokenizer::TYPE_INTEGER}, + {"0xab6", Tokenizer::TYPE_INTEGER}, + {"0XAB6", Tokenizer::TYPE_INTEGER}, + {"0X1234567", Tokenizer::TYPE_INTEGER}, + {"0x89abcdef", Tokenizer::TYPE_INTEGER}, + {"0x89ABCDEF", Tokenizer::TYPE_INTEGER}, + {"01234567", Tokenizer::TYPE_INTEGER}, + + // Test floats. + {"123.45", Tokenizer::TYPE_FLOAT}, + {"1.", Tokenizer::TYPE_FLOAT}, + {"1e3", Tokenizer::TYPE_FLOAT}, + {"1E3", Tokenizer::TYPE_FLOAT}, + {"1e-3", Tokenizer::TYPE_FLOAT}, + {"1e+3", Tokenizer::TYPE_FLOAT}, + {"1.e3", Tokenizer::TYPE_FLOAT}, + {"1.2e3", Tokenizer::TYPE_FLOAT}, + {".1", Tokenizer::TYPE_FLOAT}, + {".1e3", Tokenizer::TYPE_FLOAT}, + {".1e-3", Tokenizer::TYPE_FLOAT}, + {".1e+3", Tokenizer::TYPE_FLOAT}, + + // Test strings. + {"'hello'", Tokenizer::TYPE_STRING}, + {"\"foo\"", Tokenizer::TYPE_STRING}, + {"'a\"b'", Tokenizer::TYPE_STRING}, + {"\"a'b\"", Tokenizer::TYPE_STRING}, + {"'a\\'b'", Tokenizer::TYPE_STRING}, + {"\"a\\\"b\"", Tokenizer::TYPE_STRING}, + {"'\\xf'", Tokenizer::TYPE_STRING}, + {"'\\0'", Tokenizer::TYPE_STRING}, + + // Test symbols. + {"+", Tokenizer::TYPE_SYMBOL}, + {".", Tokenizer::TYPE_SYMBOL}, }; TEST_2D(TokenizerTest, SimpleTokens, kSimpleTokenCases, kBlockSizes) { // Set up the tokenizer. TestInputStream input(kSimpleTokenCases_case.input.data(), - kSimpleTokenCases_case.input.size(), - kBlockSizes_case); + kSimpleTokenCases_case.input.size(), kBlockSizes_case); TestErrorCollector error_collector; Tokenizer tokenizer(&input, &error_collector); @@ -326,7 +324,7 @@ TEST_1D(TokenizerTest, FloatSuffix, kBlockSizes) { // In each case, the input is parsed to produce a list of tokens. The // last token in "output" must have type TYPE_END. struct MultiTokenCase { - string input; + std::string input; Tokenizer::Token output[10]; // The compiler wants a constant array // size for initialization to work. There // is no reason this can't be increased if @@ -339,92 +337,101 @@ inline std::ostream& operator<<(std::ostream& out, } MultiTokenCase kMultiTokenCases[] = { - // Test empty input. - { "", { - { Tokenizer::TYPE_END , "" , 0, 0, 0 }, - }}, - - // Test all token types at the same time. - { "foo 1 1.2 + 'bar'", { - { Tokenizer::TYPE_IDENTIFIER, "foo" , 0, 0, 3 }, - { Tokenizer::TYPE_INTEGER , "1" , 0, 4, 5 }, - { Tokenizer::TYPE_FLOAT , "1.2" , 0, 6, 9 }, - { Tokenizer::TYPE_SYMBOL , "+" , 0, 10, 11 }, - { Tokenizer::TYPE_STRING , "'bar'", 0, 12, 17 }, - { Tokenizer::TYPE_END , "" , 0, 17, 17 }, - }}, - - // Test that consecutive symbols are parsed as separate tokens. - { "!@+%", { - { Tokenizer::TYPE_SYMBOL , "!" , 0, 0, 1 }, - { Tokenizer::TYPE_SYMBOL , "@" , 0, 1, 2 }, - { Tokenizer::TYPE_SYMBOL , "+" , 0, 2, 3 }, - { Tokenizer::TYPE_SYMBOL , "%" , 0, 3, 4 }, - { Tokenizer::TYPE_END , "" , 0, 4, 4 }, - }}, - - // Test that newlines affect line numbers correctly. - { "foo bar\nrab oof", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 4, 7 }, - { Tokenizer::TYPE_IDENTIFIER, "rab", 1, 0, 3 }, - { Tokenizer::TYPE_IDENTIFIER, "oof", 1, 4, 7 }, - { Tokenizer::TYPE_END , "" , 1, 7, 7 }, - }}, - - // Test that tabs affect column numbers correctly. - { "foo\tbar \tbaz", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 8, 11 }, - { Tokenizer::TYPE_IDENTIFIER, "baz", 0, 16, 19 }, - { Tokenizer::TYPE_END , "" , 0, 19, 19 }, - }}, - - // Test that tabs in string literals affect column numbers correctly. - { "\"foo\tbar\" baz", { - { Tokenizer::TYPE_STRING , "\"foo\tbar\"", 0, 0, 12 }, - { Tokenizer::TYPE_IDENTIFIER, "baz" , 0, 13, 16 }, - { Tokenizer::TYPE_END , "" , 0, 16, 16 }, - }}, - - // Test that line comments are ignored. - { "foo // This is a comment\n" - "bar // This is another comment", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 0, 3 }, - { Tokenizer::TYPE_END , "" , 1, 30, 30 }, - }}, - - // Test that block comments are ignored. - { "foo /* This is a block comment */ bar", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 34, 37 }, - { Tokenizer::TYPE_END , "" , 0, 37, 37 }, - }}, - - // Test that sh-style comments are not ignored by default. - { "foo # bar\n" - "baz", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, - { Tokenizer::TYPE_SYMBOL , "#" , 0, 4, 5 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 6, 9 }, - { Tokenizer::TYPE_IDENTIFIER, "baz", 1, 0, 3 }, - { Tokenizer::TYPE_END , "" , 1, 3, 3 }, - }}, - - // Test all whitespace chars - { "foo\n\t\r\v\fbar", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 11, 14 }, - { Tokenizer::TYPE_END , "" , 1, 14, 14 }, - }}, + // Test empty input. + {"", + { + {Tokenizer::TYPE_END, "", 0, 0, 0}, + }}, + + // Test all token types at the same time. + {"foo 1 1.2 + 'bar'", + { + {Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3}, + {Tokenizer::TYPE_INTEGER, "1", 0, 4, 5}, + {Tokenizer::TYPE_FLOAT, "1.2", 0, 6, 9}, + {Tokenizer::TYPE_SYMBOL, "+", 0, 10, 11}, + {Tokenizer::TYPE_STRING, "'bar'", 0, 12, 17}, + {Tokenizer::TYPE_END, "", 0, 17, 17}, + }}, + + // Test that consecutive symbols are parsed as separate tokens. + {"!@+%", + { + {Tokenizer::TYPE_SYMBOL, "!", 0, 0, 1}, + {Tokenizer::TYPE_SYMBOL, "@", 0, 1, 2}, + {Tokenizer::TYPE_SYMBOL, "+", 0, 2, 3}, + {Tokenizer::TYPE_SYMBOL, "%", 0, 3, 4}, + {Tokenizer::TYPE_END, "", 0, 4, 4}, + }}, + + // Test that newlines affect line numbers correctly. + {"foo bar\nrab oof", + { + {Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3}, + {Tokenizer::TYPE_IDENTIFIER, "bar", 0, 4, 7}, + {Tokenizer::TYPE_IDENTIFIER, "rab", 1, 0, 3}, + {Tokenizer::TYPE_IDENTIFIER, "oof", 1, 4, 7}, + {Tokenizer::TYPE_END, "", 1, 7, 7}, + }}, + + // Test that tabs affect column numbers correctly. + {"foo\tbar \tbaz", + { + {Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3}, + {Tokenizer::TYPE_IDENTIFIER, "bar", 0, 8, 11}, + {Tokenizer::TYPE_IDENTIFIER, "baz", 0, 16, 19}, + {Tokenizer::TYPE_END, "", 0, 19, 19}, + }}, + + // Test that tabs in string literals affect column numbers correctly. + {"\"foo\tbar\" baz", + { + {Tokenizer::TYPE_STRING, "\"foo\tbar\"", 0, 0, 12}, + {Tokenizer::TYPE_IDENTIFIER, "baz", 0, 13, 16}, + {Tokenizer::TYPE_END, "", 0, 16, 16}, + }}, + + // Test that line comments are ignored. + {"foo // This is a comment\n" + "bar // This is another comment", + { + {Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3}, + {Tokenizer::TYPE_IDENTIFIER, "bar", 1, 0, 3}, + {Tokenizer::TYPE_END, "", 1, 30, 30}, + }}, + + // Test that block comments are ignored. + {"foo /* This is a block comment */ bar", + { + {Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3}, + {Tokenizer::TYPE_IDENTIFIER, "bar", 0, 34, 37}, + {Tokenizer::TYPE_END, "", 0, 37, 37}, + }}, + + // Test that sh-style comments are not ignored by default. + {"foo # bar\n" + "baz", + { + {Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3}, + {Tokenizer::TYPE_SYMBOL, "#", 0, 4, 5}, + {Tokenizer::TYPE_IDENTIFIER, "bar", 0, 6, 9}, + {Tokenizer::TYPE_IDENTIFIER, "baz", 1, 0, 3}, + {Tokenizer::TYPE_END, "", 1, 3, 3}, + }}, + + // Test all whitespace chars + {"foo\n\t\r\v\fbar", + { + {Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3}, + {Tokenizer::TYPE_IDENTIFIER, "bar", 1, 11, 14}, + {Tokenizer::TYPE_END, "", 1, 14, 14}, + }}, }; TEST_2D(TokenizerTest, MultipleTokens, kMultiTokenCases, kBlockSizes) { // Set up the tokenizer. TestInputStream input(kMultiTokenCases_case.input.data(), - kMultiTokenCases_case.input.size(), - kBlockSizes_case); + kMultiTokenCases_case.input.size(), kBlockSizes_case); TestErrorCollector error_collector; Tokenizer tokenizer(&input, &error_collector); @@ -479,14 +486,14 @@ TEST_2D(TokenizerTest, MultipleTokens, kMultiTokenCases, kBlockSizes) { TEST_1D(TokenizerTest, ShCommentStyle, kBlockSizes) { // Test the "comment_style" option. - const char* text = "foo # bar\n" - "baz // qux\n" - "corge /* grault */\n" - "garply"; + const char* text = + "foo # bar\n" + "baz // qux\n" + "corge /* grault */\n" + "garply"; const char* const kTokens[] = {"foo", // "# bar" is ignored - "baz", "/", "/", "qux", - "corge", "/", "*", "grault", "*", "/", - "garply"}; + "baz", "/", "/", "qux", "corge", "/", + "*", "grault", "*", "/", "garply"}; // Set up the tokenizer. TestInputStream input(text, strlen(text), kBlockSizes_case); @@ -513,7 +520,7 @@ TEST_1D(TokenizerTest, ShCommentStyle, kBlockSizes) { // In each case, the input is expected to have two tokens named "prev" and // "next" with comments in between. struct DocCommentCase { - string input; + std::string input; const char* prev_trailing_comments; const char* detached_comments[10]; @@ -526,164 +533,136 @@ inline std::ostream& operator<<(std::ostream& out, } DocCommentCase kDocCommentCases[] = { - { - "prev next", - - "", - {}, - "" - }, - - { - "prev /* ignored */ next", - - "", - {}, - "" - }, - - { - "prev // trailing comment\n" - "next", - - " trailing comment\n", - {}, - "" - }, - - { - "prev\n" - "// leading comment\n" - "// line 2\n" - "next", - - "", - {}, - " leading comment\n" - " line 2\n" - }, - - { - "prev\n" - "// trailing comment\n" - "// line 2\n" - "\n" - "next", - - " trailing comment\n" - " line 2\n", - {}, - "" - }, - - { - "prev // trailing comment\n" - "// leading comment\n" - "// line 2\n" - "next", - - " trailing comment\n", - {}, - " leading comment\n" - " line 2\n" - }, - - { - "prev /* trailing block comment */\n" - "/* leading block comment\n" - " * line 2\n" - " * line 3 */" - "next", - - " trailing block comment ", - {}, - " leading block comment\n" - " line 2\n" - " line 3 " - }, - - { - "prev\n" - "/* trailing block comment\n" - " * line 2\n" - " * line 3\n" - " */\n" - "/* leading block comment\n" - " * line 2\n" - " * line 3 */" - "next", - - " trailing block comment\n" - " line 2\n" - " line 3\n", - {}, - " leading block comment\n" - " line 2\n" - " line 3 " - }, - - { - "prev\n" - "// trailing comment\n" - "\n" - "// detached comment\n" - "// line 2\n" - "\n" - "// second detached comment\n" - "/* third detached comment\n" - " * line 2 */\n" - "// leading comment\n" - "next", - - " trailing comment\n", - { - " detached comment\n" - " line 2\n", - " second detached comment\n", - " third detached comment\n" - " line 2 " - }, - " leading comment\n" - }, - - { - "prev /**/\n" - "\n" - "// detached comment\n" - "\n" - "// leading comment\n" - "next", - - "", - { - " detached comment\n" - }, - " leading comment\n" - }, - - { - "prev /**/\n" - "// leading comment\n" - "next", - - "", - {}, - " leading comment\n" - }, - }; + {"prev next", + + "", + {}, + ""}, + + {"prev /* ignored */ next", + + "", + {}, + ""}, + + {"prev // trailing comment\n" + "next", + + " trailing comment\n", + {}, + ""}, + + {"prev\n" + "// leading comment\n" + "// line 2\n" + "next", + + "", + {}, + " leading comment\n" + " line 2\n"}, + + {"prev\n" + "// trailing comment\n" + "// line 2\n" + "\n" + "next", + + " trailing comment\n" + " line 2\n", + {}, + ""}, + + {"prev // trailing comment\n" + "// leading comment\n" + "// line 2\n" + "next", + + " trailing comment\n", + {}, + " leading comment\n" + " line 2\n"}, + + {"prev /* trailing block comment */\n" + "/* leading block comment\n" + " * line 2\n" + " * line 3 */" + "next", + + " trailing block comment ", + {}, + " leading block comment\n" + " line 2\n" + " line 3 "}, + + {"prev\n" + "/* trailing block comment\n" + " * line 2\n" + " * line 3\n" + " */\n" + "/* leading block comment\n" + " * line 2\n" + " * line 3 */" + "next", + + " trailing block comment\n" + " line 2\n" + " line 3\n", + {}, + " leading block comment\n" + " line 2\n" + " line 3 "}, + + {"prev\n" + "// trailing comment\n" + "\n" + "// detached comment\n" + "// line 2\n" + "\n" + "// second detached comment\n" + "/* third detached comment\n" + " * line 2 */\n" + "// leading comment\n" + "next", + + " trailing comment\n", + {" detached comment\n" + " line 2\n", + " second detached comment\n", + " third detached comment\n" + " line 2 "}, + " leading comment\n"}, + + {"prev /**/\n" + "\n" + "// detached comment\n" + "\n" + "// leading comment\n" + "next", + + "", + {" detached comment\n"}, + " leading comment\n"}, + + {"prev /**/\n" + "// leading comment\n" + "next", + + "", + {}, + " leading comment\n"}, +}; TEST_2D(TokenizerTest, DocComments, kDocCommentCases, kBlockSizes) { // Set up the tokenizer. TestInputStream input(kDocCommentCases_case.input.data(), - kDocCommentCases_case.input.size(), - kBlockSizes_case); + kDocCommentCases_case.input.size(), kBlockSizes_case); TestErrorCollector error_collector; Tokenizer tokenizer(&input, &error_collector); // Set up a second tokenizer where we'll pass all NULLs to NextWithComments(). TestInputStream input2(kDocCommentCases_case.input.data(), - kDocCommentCases_case.input.size(), - kBlockSizes_case); + kDocCommentCases_case.input.size(), kBlockSizes_case); Tokenizer tokenizer2(&input2, &error_collector); tokenizer.Next(); @@ -692,9 +671,9 @@ TEST_2D(TokenizerTest, DocComments, kDocCommentCases, kBlockSizes) { EXPECT_EQ("prev", tokenizer.current().text); EXPECT_EQ("prev", tokenizer2.current().text); - string prev_trailing_comments; - std::vector detached_comments; - string next_leading_comments; + std::string prev_trailing_comments; + std::vector detached_comments; + std::string next_leading_comments; tokenizer.NextWithComments(&prev_trailing_comments, &detached_comments, &next_leading_comments); tokenizer2.NextWithComments(NULL, NULL, NULL); @@ -707,16 +686,14 @@ TEST_2D(TokenizerTest, DocComments, kDocCommentCases, kBlockSizes) { for (int i = 0; i < detached_comments.size(); i++) { ASSERT_LT(i, GOOGLE_ARRAYSIZE(kDocCommentCases)); ASSERT_TRUE(kDocCommentCases_case.detached_comments[i] != NULL); - EXPECT_EQ(kDocCommentCases_case.detached_comments[i], - detached_comments[i]); + EXPECT_EQ(kDocCommentCases_case.detached_comments[i], detached_comments[i]); } // Verify that we matched all the detached comments. EXPECT_EQ(NULL, - kDocCommentCases_case.detached_comments[detached_comments.size()]); + kDocCommentCases_case.detached_comments[detached_comments.size()]); - EXPECT_EQ(kDocCommentCases_case.next_leading_comments, - next_leading_comments); + EXPECT_EQ(kDocCommentCases_case.next_leading_comments, next_leading_comments); } // ------------------------------------------------------------------- @@ -745,30 +722,30 @@ TEST_F(TokenizerTest, ParseInteger) { EXPECT_FALSE(Tokenizer::ParseInteger("-1", kuint64max, &i)); // Test overflows. - EXPECT_TRUE (Tokenizer::ParseInteger("0", 0, &i)); + EXPECT_TRUE(Tokenizer::ParseInteger("0", 0, &i)); EXPECT_FALSE(Tokenizer::ParseInteger("1", 0, &i)); - EXPECT_TRUE (Tokenizer::ParseInteger("1", 1, &i)); - EXPECT_TRUE (Tokenizer::ParseInteger("12345", 12345, &i)); + EXPECT_TRUE(Tokenizer::ParseInteger("1", 1, &i)); + EXPECT_TRUE(Tokenizer::ParseInteger("12345", 12345, &i)); EXPECT_FALSE(Tokenizer::ParseInteger("12346", 12345, &i)); - EXPECT_TRUE (Tokenizer::ParseInteger("0xFFFFFFFFFFFFFFFF" , kuint64max, &i)); + EXPECT_TRUE(Tokenizer::ParseInteger("0xFFFFFFFFFFFFFFFF", kuint64max, &i)); EXPECT_FALSE(Tokenizer::ParseInteger("0x10000000000000000", kuint64max, &i)); } TEST_F(TokenizerTest, ParseFloat) { - EXPECT_DOUBLE_EQ(1 , Tokenizer::ParseFloat("1.")); - EXPECT_DOUBLE_EQ(1e3 , Tokenizer::ParseFloat("1e3")); - EXPECT_DOUBLE_EQ(1e3 , Tokenizer::ParseFloat("1E3")); + EXPECT_DOUBLE_EQ(1, Tokenizer::ParseFloat("1.")); + EXPECT_DOUBLE_EQ(1e3, Tokenizer::ParseFloat("1e3")); + EXPECT_DOUBLE_EQ(1e3, Tokenizer::ParseFloat("1E3")); EXPECT_DOUBLE_EQ(1.5e3, Tokenizer::ParseFloat("1.5e3")); - EXPECT_DOUBLE_EQ(.1 , Tokenizer::ParseFloat(".1")); - EXPECT_DOUBLE_EQ(.25 , Tokenizer::ParseFloat(".25")); - EXPECT_DOUBLE_EQ(.1e3 , Tokenizer::ParseFloat(".1e3")); + EXPECT_DOUBLE_EQ(.1, Tokenizer::ParseFloat(".1")); + EXPECT_DOUBLE_EQ(.25, Tokenizer::ParseFloat(".25")); + EXPECT_DOUBLE_EQ(.1e3, Tokenizer::ParseFloat(".1e3")); EXPECT_DOUBLE_EQ(.25e3, Tokenizer::ParseFloat(".25e3")); EXPECT_DOUBLE_EQ(.1e+3, Tokenizer::ParseFloat(".1e+3")); EXPECT_DOUBLE_EQ(.1e-3, Tokenizer::ParseFloat(".1e-3")); - EXPECT_DOUBLE_EQ(5 , Tokenizer::ParseFloat("5")); + EXPECT_DOUBLE_EQ(5, Tokenizer::ParseFloat("5")); EXPECT_DOUBLE_EQ(6e-12, Tokenizer::ParseFloat("6e-12")); - EXPECT_DOUBLE_EQ(1.2 , Tokenizer::ParseFloat("1.2")); - EXPECT_DOUBLE_EQ(1.e2 , Tokenizer::ParseFloat("1.e2")); + EXPECT_DOUBLE_EQ(1.2, Tokenizer::ParseFloat("1.2")); + EXPECT_DOUBLE_EQ(1.e2, Tokenizer::ParseFloat("1.e2")); // Test invalid integers that may still be tokenized as integers. EXPECT_DOUBLE_EQ(1, Tokenizer::ParseFloat("1e")); @@ -782,22 +759,25 @@ TEST_F(TokenizerTest, ParseFloat) { // These should parse successfully even though they are out of range. // Overflows become infinity and underflows become zero. - EXPECT_EQ( 0.0, Tokenizer::ParseFloat("1e-9999999999999999999999999999")); + EXPECT_EQ(0.0, Tokenizer::ParseFloat("1e-9999999999999999999999999999")); EXPECT_EQ(HUGE_VAL, Tokenizer::ParseFloat("1e+9999999999999999999999999999")); #ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet // Test invalid integers that will never be tokenized as integers. - EXPECT_DEBUG_DEATH(Tokenizer::ParseFloat("zxy"), - "passed text that could not have been tokenized as a float"); - EXPECT_DEBUG_DEATH(Tokenizer::ParseFloat("1-e0"), - "passed text that could not have been tokenized as a float"); - EXPECT_DEBUG_DEATH(Tokenizer::ParseFloat("-1.0"), - "passed text that could not have been tokenized as a float"); + EXPECT_DEBUG_DEATH( + Tokenizer::ParseFloat("zxy"), + "passed text that could not have been tokenized as a float"); + EXPECT_DEBUG_DEATH( + Tokenizer::ParseFloat("1-e0"), + "passed text that could not have been tokenized as a float"); + EXPECT_DEBUG_DEATH( + Tokenizer::ParseFloat("-1.0"), + "passed text that could not have been tokenized as a float"); #endif // PROTOBUF_HAS_DEATH_TEST } TEST_F(TokenizerTest, ParseString) { - string output; + std::string output; Tokenizer::ParseString("'hello'", &output); EXPECT_EQ("hello", output); Tokenizer::ParseString("\"blah\\nblah2\"", &output); @@ -828,19 +808,23 @@ TEST_F(TokenizerTest, ParseString) { Tokenizer::ParseString("'\\ud852XX'", &output); EXPECT_EQ("\xed\xa1\x92XX", output); // Malformed escape: Demons may fly out of the nose. - Tokenizer::ParseString("\\u0", &output); + Tokenizer::ParseString("'\\u0'", &output); EXPECT_EQ("u0", output); + // Beyond the range of valid UTF-32 code units. + Tokenizer::ParseString("'\\U00110000\\U00200000\\UFFFFFFFF'", &output); + EXPECT_EQ("\\U00110000\\U00200000\\Uffffffff", output); // Test invalid strings that will never be tokenized as strings. #ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet - EXPECT_DEBUG_DEATH(Tokenizer::ParseString("", &output), - "passed text that could not have been tokenized as a string"); + EXPECT_DEBUG_DEATH( + Tokenizer::ParseString("", &output), + "passed text that could not have been tokenized as a string"); #endif // PROTOBUF_HAS_DEATH_TEST } TEST_F(TokenizerTest, ParseStringAppend) { // Check that ParseString and ParseStringAppend differ. - string output("stuff+"); + std::string output("stuff+"); Tokenizer::ParseStringAppend("'hello'", &output); EXPECT_EQ("stuff+hello", output); Tokenizer::ParseString("'hello'", &output); @@ -852,7 +836,7 @@ TEST_F(TokenizerTest, ParseStringAppend) { // Each case parses some input text, ignoring the tokens produced, and // checks that the error output matches what is expected. struct ErrorCase { - string input; + std::string input; bool recoverable; // True if the tokenizer should be able to recover and // parse more tokens after seeing this error. Cases // for which this is true must end with "foo" as @@ -865,93 +849,76 @@ inline std::ostream& operator<<(std::ostream& out, const ErrorCase& test_case) { } ErrorCase kErrorCases[] = { - // String errors. - { "'\\l' foo", true, - "0:2: Invalid escape sequence in string literal.\n" }, - { "'\\X' foo", true, - "0:2: Invalid escape sequence in string literal.\n" }, - { "'\\x' foo", true, - "0:3: Expected hex digits for escape sequence.\n" }, - { "'foo", false, - "0:4: Unexpected end of string.\n" }, - { "'bar\nfoo", true, - "0:4: String literals cannot cross line boundaries.\n" }, - { "'\\u01' foo", true, - "0:5: Expected four hex digits for \\u escape sequence.\n" }, - { "'\\u01' foo", true, - "0:5: Expected four hex digits for \\u escape sequence.\n" }, - { "'\\uXYZ' foo", true, - "0:3: Expected four hex digits for \\u escape sequence.\n" }, - - // Integer errors. - { "123foo", true, - "0:3: Need space between number and identifier.\n" }, - - // Hex/octal errors. - { "0x foo", true, - "0:2: \"0x\" must be followed by hex digits.\n" }, - { "0541823 foo", true, - "0:4: Numbers starting with leading zero must be in octal.\n" }, - { "0x123z foo", true, - "0:5: Need space between number and identifier.\n" }, - { "0x123.4 foo", true, - "0:5: Hex and octal numbers must be integers.\n" }, - { "0123.4 foo", true, - "0:4: Hex and octal numbers must be integers.\n" }, - - // Float errors. - { "1e foo", true, - "0:2: \"e\" must be followed by exponent.\n" }, - { "1e- foo", true, - "0:3: \"e\" must be followed by exponent.\n" }, - { "1.2.3 foo", true, - "0:3: Already saw decimal point or exponent; can't have another one.\n" }, - { "1e2.3 foo", true, - "0:3: Already saw decimal point or exponent; can't have another one.\n" }, - { "a.1 foo", true, - "0:1: Need space between identifier and decimal point.\n" }, - // allow_f_after_float not enabled, so this should be an error. - { "1.0f foo", true, - "0:3: Need space between number and identifier.\n" }, - - // Block comment errors. - { "/*", false, - "0:2: End-of-file inside block comment.\n" - "0:0: Comment started here.\n"}, - { "/*/*/ foo", true, - "0:3: \"/*\" inside block comment. Block comments cannot be nested.\n"}, - - // Control characters. Multiple consecutive control characters should only - // produce one error. - { "\b foo", true, - "0:0: Invalid control characters encountered in text.\n" }, - { "\b\b foo", true, - "0:0: Invalid control characters encountered in text.\n" }, - - // Check that control characters at end of input don't result in an - // infinite loop. - { "\b", false, - "0:0: Invalid control characters encountered in text.\n" }, - - // Check recovery from '\0'. We have to explicitly specify the length of - // these strings because otherwise the string constructor will just call - // strlen() which will see the first '\0' and think that is the end of the - // string. - { string("\0foo", 4), true, - "0:0: Invalid control characters encountered in text.\n" }, - { string("\0\0foo", 5), true, - "0:0: Invalid control characters encountered in text.\n" }, - - // Check error from high order bits set - { "\300foo", true, - "0:0: Interpreting non ascii codepoint 192.\n" }, + // String errors. + {"'\\l' foo", true, "0:2: Invalid escape sequence in string literal.\n"}, + {"'\\X' foo", true, "0:2: Invalid escape sequence in string literal.\n"}, + {"'\\x' foo", true, "0:3: Expected hex digits for escape sequence.\n"}, + {"'foo", false, "0:4: Unexpected end of string.\n"}, + {"'bar\nfoo", true, "0:4: String literals cannot cross line boundaries.\n"}, + {"'\\u01' foo", true, + "0:5: Expected four hex digits for \\u escape sequence.\n"}, + {"'\\u01' foo", true, + "0:5: Expected four hex digits for \\u escape sequence.\n"}, + {"'\\uXYZ' foo", true, + "0:3: Expected four hex digits for \\u escape sequence.\n"}, + + // Integer errors. + {"123foo", true, "0:3: Need space between number and identifier.\n"}, + + // Hex/octal errors. + {"0x foo", true, "0:2: \"0x\" must be followed by hex digits.\n"}, + {"0541823 foo", true, + "0:4: Numbers starting with leading zero must be in octal.\n"}, + {"0x123z foo", true, "0:5: Need space between number and identifier.\n"}, + {"0x123.4 foo", true, "0:5: Hex and octal numbers must be integers.\n"}, + {"0123.4 foo", true, "0:4: Hex and octal numbers must be integers.\n"}, + + // Float errors. + {"1e foo", true, "0:2: \"e\" must be followed by exponent.\n"}, + {"1e- foo", true, "0:3: \"e\" must be followed by exponent.\n"}, + {"1.2.3 foo", true, + "0:3: Already saw decimal point or exponent; can't have another one.\n"}, + {"1e2.3 foo", true, + "0:3: Already saw decimal point or exponent; can't have another one.\n"}, + {"a.1 foo", true, + "0:1: Need space between identifier and decimal point.\n"}, + // allow_f_after_float not enabled, so this should be an error. + {"1.0f foo", true, "0:3: Need space between number and identifier.\n"}, + + // Block comment errors. + {"/*", false, + "0:2: End-of-file inside block comment.\n" + "0:0: Comment started here.\n"}, + {"/*/*/ foo", true, + "0:3: \"/*\" inside block comment. Block comments cannot be nested.\n"}, + + // Control characters. Multiple consecutive control characters should only + // produce one error. + {"\b foo", true, "0:0: Invalid control characters encountered in text.\n"}, + {"\b\b foo", true, + "0:0: Invalid control characters encountered in text.\n"}, + + // Check that control characters at end of input don't result in an + // infinite loop. + {"\b", false, "0:0: Invalid control characters encountered in text.\n"}, + + // Check recovery from '\0'. We have to explicitly specify the length of + // these strings because otherwise the string constructor will just call + // strlen() which will see the first '\0' and think that is the end of the + // string. + {std::string("\0foo", 4), true, + "0:0: Invalid control characters encountered in text.\n"}, + {std::string("\0\0foo", 5), true, + "0:0: Invalid control characters encountered in text.\n"}, + + // Check error from high order bits set + {"\300foo", true, "0:0: Interpreting non ascii codepoint 192.\n"}, }; TEST_2D(TokenizerTest, Errors, kErrorCases, kBlockSizes) { // Set up the tokenizer. TestInputStream input(kErrorCases_case.input.data(), - kErrorCases_case.input.size(), - kBlockSizes_case); + kErrorCases_case.input.size(), kBlockSizes_case); TestErrorCollector error_collector; Tokenizer tokenizer(&input, &error_collector); @@ -973,7 +940,7 @@ TEST_2D(TokenizerTest, Errors, kErrorCases, kBlockSizes) { // ------------------------------------------------------------------- TEST_1D(TokenizerTest, BackUpOnDestruction, kBlockSizes) { - string text = "foo bar"; + std::string text = "foo bar"; TestInputStream input(text.data(), text.size(), kBlockSizes_case); // Create a tokenizer, read one token, then destroy it. diff --git a/src/google/protobuf/io/zero_copy_stream.h b/src/google/protobuf/io/zero_copy_stream.h index 62ace7ae33f30..d3bd6daed38b7 100644 --- a/src/google/protobuf/io/zero_copy_stream.h +++ b/src/google/protobuf/io/zero_copy_stream.h @@ -107,11 +107,14 @@ #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ + #include + #include +#include -namespace google { +namespace google { namespace protobuf { namespace io { @@ -121,7 +124,7 @@ class ZeroCopyOutputStream; // Abstract interface similar to an input stream but designed to minimize // copying. -class LIBPROTOBUF_EXPORT ZeroCopyInputStream { +class PROTOBUF_EXPORT ZeroCopyInputStream { public: ZeroCopyInputStream() {} virtual ~ZeroCopyInputStream() {} @@ -169,7 +172,7 @@ class LIBPROTOBUF_EXPORT ZeroCopyInputStream { virtual bool Skip(int count) = 0; // Returns the total number of bytes read since this object was created. - virtual int64 ByteCount() const = 0; + virtual int64_t ByteCount() const = 0; private: @@ -178,7 +181,7 @@ class LIBPROTOBUF_EXPORT ZeroCopyInputStream { // Abstract interface similar to an output stream but designed to minimize // copying. -class LIBPROTOBUF_EXPORT ZeroCopyOutputStream { +class PROTOBUF_EXPORT ZeroCopyOutputStream { public: ZeroCopyOutputStream() {} virtual ~ZeroCopyOutputStream() {} @@ -224,7 +227,7 @@ class LIBPROTOBUF_EXPORT ZeroCopyOutputStream { virtual void BackUp(int count) = 0; // Returns the total number of bytes written since this object was created. - virtual int64 ByteCount() const = 0; + virtual int64_t ByteCount() const = 0; // Write a given chunk of data to the output. Some output streams may // implement this in a way that avoids copying. Check AllowsAliasing() before @@ -243,6 +246,8 @@ class LIBPROTOBUF_EXPORT ZeroCopyOutputStream { } // namespace io } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ diff --git a/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc index 81fb50335b67c..52617e9efec9b 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl.cc @@ -33,18 +33,20 @@ // Sanjay Ghemawat, Jeff Dean, and others. #ifndef _MSC_VER -#include -#include -#include #include +#include +#include +#include #endif #include -#include + #include -#include +#include + #include -#include #include +#include +#include #include @@ -56,16 +58,13 @@ namespace io { // Win32 lseek is broken: If invoked on a non-seekable file descriptor, its // return value is undefined. We re-define it to always produce an error. #define lseek(fd, offset, origin) ((off_t)-1) -#endif - -#ifdef _MSC_VER // DO NOT include , instead create functions in io_win32.{h,cc} and import // them like we do below. -using google::protobuf::internal::win32::access; -using google::protobuf::internal::win32::close; -using google::protobuf::internal::win32::open; -using google::protobuf::internal::win32::read; -using google::protobuf::internal::win32::write; +using google::protobuf::io::win32::access; +using google::protobuf::io::win32::close; +using google::protobuf::io::win32::open; +using google::protobuf::io::win32::read; +using google::protobuf::io::win32::write; #endif namespace { @@ -81,42 +80,30 @@ int close_no_eintr(int fd) { } // namespace - // =================================================================== FileInputStream::FileInputStream(int file_descriptor, int block_size) - : copying_input_(file_descriptor), - impl_(©ing_input_, block_size) { -} + : copying_input_(file_descriptor), impl_(©ing_input_, block_size) {} -bool FileInputStream::Close() { - return copying_input_.Close(); -} +bool FileInputStream::Close() { return copying_input_.Close(); } bool FileInputStream::Next(const void** data, int* size) { return impl_.Next(data, size); } -void FileInputStream::BackUp(int count) { - impl_.BackUp(count); -} +void FileInputStream::BackUp(int count) { impl_.BackUp(count); } -bool FileInputStream::Skip(int count) { - return impl_.Skip(count); -} +bool FileInputStream::Skip(int count) { return impl_.Skip(count); } -int64 FileInputStream::ByteCount() const { - return impl_.ByteCount(); -} +int64_t FileInputStream::ByteCount() const { return impl_.ByteCount(); } FileInputStream::CopyingFileInputStream::CopyingFileInputStream( int file_descriptor) - : file_(file_descriptor), - close_on_delete_(false), - is_closed_(false), - errno_(0), - previous_seek_failed_(false) { -} + : file_(file_descriptor), + close_on_delete_(false), + is_closed_(false), + errno_(0), + previous_seek_failed_(false) {} FileInputStream::CopyingFileInputStream::~CopyingFileInputStream() { if (close_on_delete_) { @@ -160,8 +147,7 @@ int FileInputStream::CopyingFileInputStream::Read(void* buffer, int size) { int FileInputStream::CopyingFileInputStream::Skip(int count) { GOOGLE_CHECK(!is_closed_); - if (!previous_seek_failed_ && - lseek(file_, count, SEEK_CUR) != (off_t)-1) { + if (!previous_seek_failed_ && lseek(file_, count, SEEK_CUR) != (off_t)-1) { // Seek succeeded. return count; } else { @@ -179,42 +165,22 @@ int FileInputStream::CopyingFileInputStream::Skip(int count) { // =================================================================== FileOutputStream::FileOutputStream(int file_descriptor, int block_size) - : copying_output_(file_descriptor), - impl_(©ing_output_, block_size) { -} - -FileOutputStream::~FileOutputStream() { - impl_.Flush(); -} + : CopyingOutputStreamAdaptor(©ing_output_), + copying_output_(file_descriptor) {} bool FileOutputStream::Close() { - bool flush_succeeded = impl_.Flush(); + bool flush_succeeded = Flush(); return copying_output_.Close() && flush_succeeded; } -bool FileOutputStream::Flush() { - return impl_.Flush(); -} - -bool FileOutputStream::Next(void** data, int* size) { - return impl_.Next(data, size); -} - -void FileOutputStream::BackUp(int count) { - impl_.BackUp(count); -} - -int64 FileOutputStream::ByteCount() const { - return impl_.ByteCount(); -} - FileOutputStream::CopyingFileOutputStream::CopyingFileOutputStream( int file_descriptor) - : file_(file_descriptor), - close_on_delete_(false), - is_closed_(false), - errno_(0) { -} + : file_(file_descriptor), + close_on_delete_(false), + is_closed_(false), + errno_(0) {} + +FileOutputStream::~FileOutputStream() { Flush(); } FileOutputStream::CopyingFileOutputStream::~CopyingFileOutputStream() { if (close_on_delete_) { @@ -239,8 +205,8 @@ bool FileOutputStream::CopyingFileOutputStream::Close() { return true; } -bool FileOutputStream::CopyingFileOutputStream::Write( - const void* buffer, int size) { +bool FileOutputStream::CopyingFileOutputStream::Write(const void* buffer, + int size) { GOOGLE_CHECK(!is_closed_); int total_written = 0; @@ -283,17 +249,11 @@ bool IstreamInputStream::Next(const void** data, int* size) { return impl_.Next(data, size); } -void IstreamInputStream::BackUp(int count) { - impl_.BackUp(count); -} +void IstreamInputStream::BackUp(int count) { impl_.BackUp(count); } -bool IstreamInputStream::Skip(int count) { - return impl_.Skip(count); -} +bool IstreamInputStream::Skip(int count) { return impl_.Skip(count); } -int64 IstreamInputStream::ByteCount() const { - return impl_.ByteCount(); -} +int64_t IstreamInputStream::ByteCount() const { return impl_.ByteCount(); } IstreamInputStream::CopyingIstreamInputStream::CopyingIstreamInputStream( std::istream* input) @@ -301,8 +261,8 @@ IstreamInputStream::CopyingIstreamInputStream::CopyingIstreamInputStream( IstreamInputStream::CopyingIstreamInputStream::~CopyingIstreamInputStream() {} -int IstreamInputStream::CopyingIstreamInputStream::Read( - void* buffer, int size) { +int IstreamInputStream::CopyingIstreamInputStream::Read(void* buffer, + int size) { input_->read(reinterpret_cast(buffer), size); int result = input_->gcount(); if (result == 0 && input_->fail() && !input_->eof()) { @@ -316,21 +276,15 @@ int IstreamInputStream::CopyingIstreamInputStream::Read( OstreamOutputStream::OstreamOutputStream(std::ostream* output, int block_size) : copying_output_(output), impl_(©ing_output_, block_size) {} -OstreamOutputStream::~OstreamOutputStream() { - impl_.Flush(); -} +OstreamOutputStream::~OstreamOutputStream() { impl_.Flush(); } bool OstreamOutputStream::Next(void** data, int* size) { return impl_.Next(data, size); } -void OstreamOutputStream::BackUp(int count) { - impl_.BackUp(count); -} +void OstreamOutputStream::BackUp(int count) { impl_.BackUp(count); } -int64 OstreamOutputStream::ByteCount() const { - return impl_.ByteCount(); -} +int64_t OstreamOutputStream::ByteCount() const { return impl_.ByteCount(); } OstreamOutputStream::CopyingOstreamOutputStream::CopyingOstreamOutputStream( std::ostream* output) @@ -339,8 +293,8 @@ OstreamOutputStream::CopyingOstreamOutputStream::CopyingOstreamOutputStream( OstreamOutputStream::CopyingOstreamOutputStream::~CopyingOstreamOutputStream() { } -bool OstreamOutputStream::CopyingOstreamOutputStream::Write( - const void* buffer, int size) { +bool OstreamOutputStream::CopyingOstreamOutputStream::Write(const void* buffer, + int size) { output_->write(reinterpret_cast(buffer), size); return output_->good(); } @@ -349,7 +303,7 @@ bool OstreamOutputStream::CopyingOstreamOutputStream::Write( ConcatenatingInputStream::ConcatenatingInputStream( ZeroCopyInputStream* const streams[], int count) - : streams_(streams), stream_count_(count), bytes_retired_(0) { + : streams_(streams), stream_count_(count), bytes_retired_(0) { } bool ConcatenatingInputStream::Next(const void** data, int* size) { @@ -396,7 +350,7 @@ bool ConcatenatingInputStream::Skip(int count) { return false; } -int64 ConcatenatingInputStream::ByteCount() const { +int64_t ConcatenatingInputStream::ByteCount() const { if (stream_count_ == 0) { return bytes_retired_; } else { @@ -405,63 +359,6 @@ int64 ConcatenatingInputStream::ByteCount() const { } -// =================================================================== - -LimitingInputStream::LimitingInputStream(ZeroCopyInputStream* input, - int64 limit) - : input_(input), limit_(limit) { - prior_bytes_read_ = input_->ByteCount(); -} - -LimitingInputStream::~LimitingInputStream() { - // If we overshot the limit, back up. - if (limit_ < 0) input_->BackUp(-limit_); -} - -bool LimitingInputStream::Next(const void** data, int* size) { - if (limit_ <= 0) return false; - if (!input_->Next(data, size)) return false; - - limit_ -= *size; - if (limit_ < 0) { - // We overshot the limit. Reduce *size to hide the rest of the buffer. - *size += limit_; - } - return true; -} - -void LimitingInputStream::BackUp(int count) { - if (limit_ < 0) { - input_->BackUp(count - limit_); - limit_ = count; - } else { - input_->BackUp(count); - limit_ += count; - } -} - -bool LimitingInputStream::Skip(int count) { - if (count > limit_) { - if (limit_ < 0) return false; - input_->Skip(limit_); - limit_ = 0; - return false; - } else { - if (!input_->Skip(count)) return false; - limit_ -= count; - return true; - } -} - -int64 LimitingInputStream::ByteCount() const { - if (limit_ < 0) { - return input_->ByteCount() + limit_ - prior_bytes_read_; - } else { - return input_->ByteCount() - prior_bytes_read_; - } -} - - // =================================================================== } // namespace io diff --git a/src/google/protobuf/io/zero_copy_stream_impl.h b/src/google/protobuf/io/zero_copy_stream_impl.h index ea978bfbb7086..0206e3887eb7e 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl.h +++ b/src/google/protobuf/io/zero_copy_stream_impl.h @@ -40,18 +40,20 @@ #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__ #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__ -#include + #include +#include + +#include #include #include -#include +#include namespace google { namespace protobuf { namespace io { - // =================================================================== // A ZeroCopyInputStream which reads from a file descriptor. @@ -60,7 +62,7 @@ namespace io { // The latter will introduce an extra layer of buffering, harming performance. // Also, it's conceivable that FileInputStream could someday be enhanced // to use zero-copy file descriptors on OSs which support them. -class LIBPROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream { +class PROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream { public: // Creates a stream that reads from the given Unix file descriptor. // If a block_size is given, it specifies the number of bytes that @@ -84,27 +86,27 @@ class LIBPROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream { // errno from that error. Otherwise, this is zero. Once an error // occurs, the stream is broken and all subsequent operations will // fail. - int GetErrno() { return copying_input_.GetErrno(); } + int GetErrno() const { return copying_input_.GetErrno(); } // implements ZeroCopyInputStream ---------------------------------- - bool Next(const void** data, int* size); - void BackUp(int count); - bool Skip(int count); - int64 ByteCount() const; + bool Next(const void** data, int* size) override; + void BackUp(int count) override; + bool Skip(int count) override; + int64_t ByteCount() const override; private: - class LIBPROTOBUF_EXPORT CopyingFileInputStream : public CopyingInputStream { + class PROTOBUF_EXPORT CopyingFileInputStream : public CopyingInputStream { public: CopyingFileInputStream(int file_descriptor); - ~CopyingFileInputStream(); + ~CopyingFileInputStream() override; bool Close(); void SetCloseOnDelete(bool value) { close_on_delete_ = value; } - int GetErrno() { return errno_; } + int GetErrno() const { return errno_; } // implements CopyingInputStream --------------------------------- - int Read(void* buffer, int size); - int Skip(int count); + int Read(void* buffer, int size) override; + int Skip(int count) override; private: // The file descriptor. @@ -137,25 +139,21 @@ class LIBPROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream { // harming performance. Also, it's conceivable that FileOutputStream could // someday be enhanced to use zero-copy file descriptors on OSs which // support them. -class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream { +class PROTOBUF_EXPORT FileOutputStream : public CopyingOutputStreamAdaptor { public: // Creates a stream that writes to the given Unix file descriptor. // If a block_size is given, it specifies the size of the buffers // that should be returned by Next(). Otherwise, a reasonable default // is used. explicit FileOutputStream(int file_descriptor, int block_size = -1); - ~FileOutputStream(); + + ~FileOutputStream() override; // Flushes any buffers and closes the underlying file. Returns false if // an error occurs during the process; use GetErrno() to examine the error. // Even if an error occurs, the file descriptor is closed when this returns. bool Close(); - // Flushes FileOutputStream's buffers but does not close the - // underlying file. No special measures are taken to ensure that - // underlying operating system file object is synchronized to disk. - bool Flush(); - // By default, the file descriptor is not closed when the stream is // destroyed. Call SetCloseOnDelete(true) to change that. WARNING: // This leaves no way for the caller to detect if close() fails. If @@ -167,25 +165,20 @@ class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream { // errno from that error. Otherwise, this is zero. Once an error // occurs, the stream is broken and all subsequent operations will // fail. - int GetErrno() { return copying_output_.GetErrno(); } - - // implements ZeroCopyOutputStream --------------------------------- - bool Next(void** data, int* size); - void BackUp(int count); - int64 ByteCount() const; + int GetErrno() const { return copying_output_.GetErrno(); } private: - class LIBPROTOBUF_EXPORT CopyingFileOutputStream : public CopyingOutputStream { + class PROTOBUF_EXPORT CopyingFileOutputStream : public CopyingOutputStream { public: CopyingFileOutputStream(int file_descriptor); - ~CopyingFileOutputStream(); + ~CopyingFileOutputStream() override; bool Close(); void SetCloseOnDelete(bool value) { close_on_delete_ = value; } - int GetErrno() { return errno_; } + int GetErrno() const { return errno_; } // implements CopyingOutputStream -------------------------------- - bool Write(const void* buffer, int size); + bool Write(const void* buffer, int size) override; private: // The file descriptor. @@ -200,7 +193,6 @@ class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream { }; CopyingFileOutputStream copying_output_; - CopyingOutputStreamAdaptor impl_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileOutputStream); }; @@ -211,7 +203,7 @@ class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream { // // Note that for reading files (or anything represented by a file descriptor), // FileInputStream is more efficient. -class LIBPROTOBUF_EXPORT IstreamInputStream : public ZeroCopyInputStream { +class PROTOBUF_EXPORT IstreamInputStream : public ZeroCopyInputStream { public: // Creates a stream that reads from the given C++ istream. // If a block_size is given, it specifies the number of bytes that @@ -220,19 +212,19 @@ class LIBPROTOBUF_EXPORT IstreamInputStream : public ZeroCopyInputStream { explicit IstreamInputStream(std::istream* stream, int block_size = -1); // implements ZeroCopyInputStream ---------------------------------- - bool Next(const void** data, int* size); - void BackUp(int count); - bool Skip(int count); - int64 ByteCount() const; + bool Next(const void** data, int* size) override; + void BackUp(int count) override; + bool Skip(int count) override; + int64_t ByteCount() const override; private: - class LIBPROTOBUF_EXPORT CopyingIstreamInputStream : public CopyingInputStream { + class PROTOBUF_EXPORT CopyingIstreamInputStream : public CopyingInputStream { public: CopyingIstreamInputStream(std::istream* input); - ~CopyingIstreamInputStream(); + ~CopyingIstreamInputStream() override; // implements CopyingInputStream --------------------------------- - int Read(void* buffer, int size); + int Read(void* buffer, int size) override; // (We use the default implementation of Skip().) private: @@ -254,28 +246,29 @@ class LIBPROTOBUF_EXPORT IstreamInputStream : public ZeroCopyInputStream { // // Note that for writing files (or anything represented by a file descriptor), // FileOutputStream is more efficient. -class LIBPROTOBUF_EXPORT OstreamOutputStream : public ZeroCopyOutputStream { +class PROTOBUF_EXPORT OstreamOutputStream : public ZeroCopyOutputStream { public: // Creates a stream that writes to the given C++ ostream. // If a block_size is given, it specifies the size of the buffers // that should be returned by Next(). Otherwise, a reasonable default // is used. explicit OstreamOutputStream(std::ostream* stream, int block_size = -1); - ~OstreamOutputStream(); + ~OstreamOutputStream() override; // implements ZeroCopyOutputStream --------------------------------- - bool Next(void** data, int* size); - void BackUp(int count); - int64 ByteCount() const; + bool Next(void** data, int* size) override; + void BackUp(int count) override; + int64_t ByteCount() const override; private: - class LIBPROTOBUF_EXPORT CopyingOstreamOutputStream : public CopyingOutputStream { + class PROTOBUF_EXPORT CopyingOstreamOutputStream + : public CopyingOutputStream { public: CopyingOstreamOutputStream(std::ostream* output); - ~CopyingOstreamOutputStream(); + ~CopyingOstreamOutputStream() override; // implements CopyingOutputStream -------------------------------- - bool Write(const void* buffer, int size); + bool Write(const void* buffer, int size) override; private: // The stream. @@ -299,17 +292,18 @@ class LIBPROTOBUF_EXPORT OstreamOutputStream : public ZeroCopyOutputStream { // ConcatenatingInputStream may do odd things. It is suggested that you do // not use ConcatenatingInputStream on streams that might produce read errors // other than end-of-stream. -class LIBPROTOBUF_EXPORT ConcatenatingInputStream : public ZeroCopyInputStream { +class PROTOBUF_EXPORT ConcatenatingInputStream : public ZeroCopyInputStream { public: // All streams passed in as well as the array itself must remain valid // until the ConcatenatingInputStream is destroyed. ConcatenatingInputStream(ZeroCopyInputStream* const streams[], int count); + ~ConcatenatingInputStream() override = default; // implements ZeroCopyInputStream ---------------------------------- - bool Next(const void** data, int* size); - void BackUp(int count); - bool Skip(int count); - int64 ByteCount() const; + bool Next(const void** data, int* size) override; + void BackUp(int count) override; + bool Skip(int count) override; + int64_t ByteCount() const override; private: @@ -324,32 +318,10 @@ class LIBPROTOBUF_EXPORT ConcatenatingInputStream : public ZeroCopyInputStream { // =================================================================== -// A ZeroCopyInputStream which wraps some other stream and limits it to -// a particular byte count. -class LIBPROTOBUF_EXPORT LimitingInputStream : public ZeroCopyInputStream { - public: - LimitingInputStream(ZeroCopyInputStream* input, int64 limit); - ~LimitingInputStream(); - - // implements ZeroCopyInputStream ---------------------------------- - bool Next(const void** data, int* size); - void BackUp(int count); - bool Skip(int count); - int64 ByteCount() const; - - - private: - ZeroCopyInputStream* input_; - int64 limit_; // Decreases as we go, becomes negative if we overshoot. - int64 prior_bytes_read_; // Bytes read on underlying stream at construction - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream); -}; - -// =================================================================== - } // namespace io } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__ diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc index 60c71c8027571..0eeeb0e760abb 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc @@ -37,9 +37,9 @@ #include #include -#include #include #include +#include #include namespace google { @@ -55,14 +55,12 @@ static const int kDefaultBlockSize = 8192; // =================================================================== -ArrayInputStream::ArrayInputStream(const void* data, int size, - int block_size) - : data_(reinterpret_cast(data)), - size_(size), - block_size_(block_size > 0 ? block_size : size), - position_(0), - last_returned_size_(0) { -} +ArrayInputStream::ArrayInputStream(const void* data, int size, int block_size) + : data_(reinterpret_cast(data)), + size_(size), + block_size_(block_size > 0 ? block_size : size), + position_(0), + last_returned_size_(0) {} bool ArrayInputStream::Next(const void** data, int* size) { if (position_ < size_) { @@ -73,7 +71,7 @@ bool ArrayInputStream::Next(const void** data, int* size) { return true; } else { // We're at the end of the array. - last_returned_size_ = 0; // Don't let caller back up. + last_returned_size_ = 0; // Don't let caller back up. return false; } } @@ -89,7 +87,7 @@ void ArrayInputStream::BackUp(int count) { bool ArrayInputStream::Skip(int count) { GOOGLE_CHECK_GE(count, 0); - last_returned_size_ = 0; // Don't let caller back up. + last_returned_size_ = 0; // Don't let caller back up. if (count > size_ - position_) { position_ = size_; return false; @@ -99,20 +97,17 @@ bool ArrayInputStream::Skip(int count) { } } -int64 ArrayInputStream::ByteCount() const { - return position_; -} +int64_t ArrayInputStream::ByteCount() const { return position_; } // =================================================================== ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size) - : data_(reinterpret_cast(data)), - size_(size), - block_size_(block_size > 0 ? block_size : size), - position_(0), - last_returned_size_(0) { -} + : data_(reinterpret_cast(data)), + size_(size), + block_size_(block_size > 0 ? block_size : size), + position_(0), + last_returned_size_(0) {} bool ArrayOutputStream::Next(void** data, int* size) { if (position_ < size_) { @@ -123,7 +118,7 @@ bool ArrayOutputStream::Next(void** data, int* size) { return true; } else { // We're at the end of the array. - last_returned_size_ = 0; // Don't let caller back up. + last_returned_size_ = 0; // Don't let caller back up. return false; } } @@ -137,41 +132,33 @@ void ArrayOutputStream::BackUp(int count) { last_returned_size_ = 0; // Don't let caller back up further. } -int64 ArrayOutputStream::ByteCount() const { - return position_; -} +int64_t ArrayOutputStream::ByteCount() const { return position_; } // =================================================================== -StringOutputStream::StringOutputStream(string* target) - : target_(target) { -} +StringOutputStream::StringOutputStream(std::string* target) : target_(target) {} bool StringOutputStream::Next(void** data, int* size) { GOOGLE_CHECK(target_ != NULL); - int old_size = target_->size(); + size_t old_size = target_->size(); // Grow the string. + size_t new_size; if (old_size < target_->capacity()) { // Resize the string to match its capacity, since we can get away // without a memory allocation this way. - STLStringResizeUninitialized(target_, target_->capacity()); + new_size = target_->capacity(); } else { - // Size has reached capacity, try to double the size. - if (old_size > std::numeric_limits::max() / 2) { - // Can not double the size otherwise it is going to cause integer - // overflow in the expression below: old_size * 2 "; - GOOGLE_LOG(ERROR) << "Cannot allocate buffer larger than kint32max for " - << "StringOutputStream."; - return false; - } - // Double the size, also make sure that the new size is at least - // kMinimumSize. - STLStringResizeUninitialized( - target_, - std::max(old_size * 2, - kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness. + // Size has reached capacity, try to double it. + new_size = old_size * 2; } + // Avoid integer overflow in returned '*size'. + new_size = std::min(new_size, old_size + std::numeric_limits::max()); + // Increase the size, also make sure that it is at least kMinimumSize. + STLStringResizeUninitialized( + target_, + std::max(new_size, + kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness. *data = mutable_string_data(target_) + old_size; *size = target_->size() - old_size; @@ -181,48 +168,23 @@ bool StringOutputStream::Next(void** data, int* size) { void StringOutputStream::BackUp(int count) { GOOGLE_CHECK_GE(count, 0); GOOGLE_CHECK(target_ != NULL); - GOOGLE_CHECK_LE(count, target_->size()); + GOOGLE_CHECK_LE(static_cast(count), target_->size()); target_->resize(target_->size() - count); } -int64 StringOutputStream::ByteCount() const { +int64_t StringOutputStream::ByteCount() const { GOOGLE_CHECK(target_ != NULL); return target_->size(); } -void StringOutputStream::SetString(string* target) { - target_ = target; -} - -// =================================================================== - -LazyStringOutputStream::LazyStringOutputStream( - ResultCallback* callback) - : StringOutputStream(NULL), - callback_(GOOGLE_CHECK_NOTNULL(callback)), - string_is_set_(false) { -} - -bool LazyStringOutputStream::Next(void** data, int* size) { - if (!string_is_set_) { - SetString(callback_->Run()); - string_is_set_ = true; - } - return StringOutputStream::Next(data, size); -} - -int64 LazyStringOutputStream::ByteCount() const { - return string_is_set_ ? StringOutputStream::ByteCount() : 0; -} - // =================================================================== int CopyingInputStream::Skip(int count) { char junk[4096]; int skipped = 0; while (skipped < count) { - int bytes = - Read(junk, std::min(count - skipped, implicit_cast(sizeof(junk)))); + int bytes = Read(junk, std::min(count - skipped, + implicit_cast(sizeof(junk)))); if (bytes <= 0) { // EOF or read error. return skipped; @@ -234,14 +196,13 @@ int CopyingInputStream::Skip(int count) { CopyingInputStreamAdaptor::CopyingInputStreamAdaptor( CopyingInputStream* copying_stream, int block_size) - : copying_stream_(copying_stream), - owns_copying_stream_(false), - failed_(false), - position_(0), - buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize), - buffer_used_(0), - backup_bytes_(0) { -} + : copying_stream_(copying_stream), + owns_copying_stream_(false), + failed_(false), + position_(0), + buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize), + buffer_used_(0), + backup_bytes_(0) {} CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() { if (owns_copying_stream_) { @@ -285,12 +246,11 @@ bool CopyingInputStreamAdaptor::Next(const void** data, int* size) { void CopyingInputStreamAdaptor::BackUp(int count) { GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL) - << " BackUp() can only be called after Next()."; + << " BackUp() can only be called after Next()."; GOOGLE_CHECK_LE(count, buffer_used_) - << " Can't back up over more bytes than were returned by the last call" - " to Next()."; - GOOGLE_CHECK_GE(count, 0) - << " Parameter to BackUp() can't be negative."; + << " Can't back up over more bytes than were returned by the last call" + " to Next()."; + GOOGLE_CHECK_GE(count, 0) << " Parameter to BackUp() can't be negative."; backup_bytes_ = count; } @@ -318,7 +278,7 @@ bool CopyingInputStreamAdaptor::Skip(int count) { return skipped == count; } -int64 CopyingInputStreamAdaptor::ByteCount() const { +int64_t CopyingInputStreamAdaptor::ByteCount() const { return position_ - backup_bytes_; } @@ -338,13 +298,12 @@ void CopyingInputStreamAdaptor::FreeBuffer() { CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor( CopyingOutputStream* copying_stream, int block_size) - : copying_stream_(copying_stream), - owns_copying_stream_(false), - failed_(false), - position_(0), - buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize), - buffer_used_(0) { -} + : copying_stream_(copying_stream), + owns_copying_stream_(false), + failed_(false), + position_(0), + buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize), + buffer_used_(0) {} CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() { WriteBuffer(); @@ -353,9 +312,7 @@ CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() { } } -bool CopyingOutputStreamAdaptor::Flush() { - return WriteBuffer(); -} +bool CopyingOutputStreamAdaptor::Flush() { return WriteBuffer(); } bool CopyingOutputStreamAdaptor::Next(void** data, int* size) { if (buffer_used_ == buffer_size_) { @@ -373,18 +330,49 @@ bool CopyingOutputStreamAdaptor::Next(void** data, int* size) { void CopyingOutputStreamAdaptor::BackUp(int count) { GOOGLE_CHECK_GE(count, 0); GOOGLE_CHECK_EQ(buffer_used_, buffer_size_) - << " BackUp() can only be called after Next()."; + << " BackUp() can only be called after Next()."; GOOGLE_CHECK_LE(count, buffer_used_) - << " Can't back up over more bytes than were returned by the last call" - " to Next()."; + << " Can't back up over more bytes than were returned by the last call" + " to Next()."; buffer_used_ -= count; } -int64 CopyingOutputStreamAdaptor::ByteCount() const { +int64_t CopyingOutputStreamAdaptor::ByteCount() const { return position_ + buffer_used_; } +bool CopyingOutputStreamAdaptor::WriteAliasedRaw(const void* data, int size) { + if (size >= buffer_size_) { + if (!Flush() || !copying_stream_->Write(data, size)) { + return false; + } + GOOGLE_DCHECK_EQ(buffer_used_, 0); + position_ += size; + return true; + } + + void* out; + int out_size; + while (true) { + if (!Next(&out, &out_size)) { + return false; + } + + if (size <= out_size) { + std::memcpy(out, data, size); + BackUp(out_size - size); + return true; + } + + std::memcpy(out, data, out_size); + data = static_cast(data) + out_size; + size -= out_size; + } + return true; +} + + bool CopyingOutputStreamAdaptor::WriteBuffer() { if (failed_) { // Already failed on a previous write. @@ -415,6 +403,63 @@ void CopyingOutputStreamAdaptor::FreeBuffer() { buffer_.reset(); } +// =================================================================== + +LimitingInputStream::LimitingInputStream(ZeroCopyInputStream* input, + int64 limit) + : input_(input), limit_(limit) { + prior_bytes_read_ = input_->ByteCount(); +} + +LimitingInputStream::~LimitingInputStream() { + // If we overshot the limit, back up. + if (limit_ < 0) input_->BackUp(-limit_); +} + +bool LimitingInputStream::Next(const void** data, int* size) { + if (limit_ <= 0) return false; + if (!input_->Next(data, size)) return false; + + limit_ -= *size; + if (limit_ < 0) { + // We overshot the limit. Reduce *size to hide the rest of the buffer. + *size += limit_; + } + return true; +} + +void LimitingInputStream::BackUp(int count) { + if (limit_ < 0) { + input_->BackUp(count - limit_); + limit_ = count; + } else { + input_->BackUp(count); + limit_ += count; + } +} + +bool LimitingInputStream::Skip(int count) { + if (count > limit_) { + if (limit_ < 0) return false; + input_->Skip(limit_); + limit_ = 0; + return false; + } else { + if (!input_->Skip(count)) return false; + limit_ -= count; + return true; + } +} + +int64_t LimitingInputStream::ByteCount() const { + if (limit_ < 0) { + return input_->ByteCount() + limit_ - prior_bytes_read_; + } else { + return input_->ByteCount() - prior_bytes_read_; + } +} + + // =================================================================== } // namespace io diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h index a7bbc625ff3ab..cfe81d2cc1f4c 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h @@ -44,18 +44,19 @@ #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ + +#include #include -#ifndef _SHARED_PTR_H -#include -#endif #include -#include -#include + #include #include +#include #include +#include + namespace google { namespace protobuf { namespace io { @@ -63,7 +64,7 @@ namespace io { // =================================================================== // A ZeroCopyInputStream backed by an in-memory array of bytes. -class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream { +class PROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream { public: // Create an InputStream that returns the bytes pointed to by "data". // "data" remains the property of the caller but must remain valid until @@ -73,12 +74,13 @@ class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream { // useful for testing; in production you would probably never want to set // it. ArrayInputStream(const void* data, int size, int block_size = -1); + ~ArrayInputStream() override = default; // implements ZeroCopyInputStream ---------------------------------- - bool Next(const void** data, int* size); - void BackUp(int count); - bool Skip(int count); - int64 ByteCount() const; + bool Next(const void** data, int* size) override; + void BackUp(int count) override; + bool Skip(int count) override; + int64_t ByteCount() const override; private: @@ -87,8 +89,8 @@ class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream { const int block_size_; // How many bytes to return at a time. int position_; - int last_returned_size_; // How many bytes we returned last time Next() - // was called (used for error checking only). + int last_returned_size_; // How many bytes we returned last time Next() + // was called (used for error checking only). GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream); }; @@ -96,7 +98,7 @@ class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream { // =================================================================== // A ZeroCopyOutputStream backed by an in-memory array of bytes. -class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream { +class PROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream { public: // Create an OutputStream that writes to the bytes pointed to by "data". // "data" remains the property of the caller but must remain valid until @@ -106,20 +108,21 @@ class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream { // useful for testing; in production you would probably never want to set // it. ArrayOutputStream(void* data, int size, int block_size = -1); + ~ArrayOutputStream() override = default; // implements ZeroCopyOutputStream --------------------------------- - bool Next(void** data, int* size); - void BackUp(int count); - int64 ByteCount() const; + bool Next(void** data, int* size) override; + void BackUp(int count) override; + int64_t ByteCount() const override; private: - uint8* const data_; // The byte array. - const int size_; // Total size of the array. - const int block_size_; // How many bytes to return at a time. + uint8* const data_; // The byte array. + const int size_; // Total size of the array. + const int block_size_; // How many bytes to return at a time. int position_; - int last_returned_size_; // How many bytes we returned last time Next() - // was called (used for error checking only). + int last_returned_size_; // How many bytes we returned last time Next() + // was called (used for error checking only). GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream); }; @@ -127,7 +130,7 @@ class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream { // =================================================================== // A ZeroCopyOutputStream which appends bytes to a string. -class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream { +class PROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream { public: // Create a StringOutputStream which appends bytes to the given string. // The string remains property of the caller, but it is mutated in arbitrary @@ -138,44 +141,22 @@ class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream { // Hint: If you call target->reserve(n) before creating the stream, // the first call to Next() will return at least n bytes of buffer // space. - explicit StringOutputStream(string* target); + explicit StringOutputStream(std::string* target); + ~StringOutputStream() override = default; // implements ZeroCopyOutputStream --------------------------------- - bool Next(void** data, int* size); - void BackUp(int count); - int64 ByteCount() const; - - protected: - void SetString(string* target); + bool Next(void** data, int* size) override; + void BackUp(int count) override; + int64_t ByteCount() const override; private: - static const int kMinimumSize = 16; + static constexpr size_t kMinimumSize = 16; - string* target_; + std::string* target_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream); }; -// LazyStringOutputStream is a StringOutputStream with lazy acquisition of -// the output string from a callback. The string is owned externally, and not -// deleted in the stream destructor. -class LIBPROTOBUF_EXPORT LazyStringOutputStream : public StringOutputStream { - public: - // Callback should be permanent (non-self-deleting). Ownership is transferred - // to the LazyStringOutputStream. - explicit LazyStringOutputStream(ResultCallback* callback); - - // implements ZeroCopyOutputStream, overriding StringOutputStream ----------- - bool Next(void** data, int* size); - int64 ByteCount() const; - - private: - const google::protobuf::scoped_ptr > callback_; - bool string_is_set_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyStringOutputStream); -}; - // Note: There is no StringInputStream. Instead, just create an // ArrayInputStream as follows: // ArrayInputStream input(str.data(), str.size()); @@ -193,7 +174,7 @@ class LIBPROTOBUF_EXPORT LazyStringOutputStream : public StringOutputStream { // CopyingInputStream implementations should avoid buffering if possible. // CopyingInputStreamAdaptor does its own buffering and will read data // in large blocks. -class LIBPROTOBUF_EXPORT CopyingInputStream { +class PROTOBUF_EXPORT CopyingInputStream { public: virtual ~CopyingInputStream() {} @@ -219,7 +200,7 @@ class LIBPROTOBUF_EXPORT CopyingInputStream { // If you want to read from file descriptors or C++ istreams, this is // already implemented for you: use FileInputStream or IstreamInputStream // respectively. -class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream { +class PROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream { public: // Creates a stream that reads from the given CopyingInputStream. // If a block_size is given, it specifies the number of bytes that @@ -228,17 +209,17 @@ class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream // copying_stream unless SetOwnsCopyingStream(true) is called. explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream, int block_size = -1); - ~CopyingInputStreamAdaptor(); + ~CopyingInputStreamAdaptor() override; // Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to // delete the underlying CopyingInputStream when it is destroyed. void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; } // implements ZeroCopyInputStream ---------------------------------- - bool Next(const void** data, int* size); - void BackUp(int count); - bool Skip(int count); - int64 ByteCount() const; + bool Next(const void** data, int* size) override; + void BackUp(int count) override; + bool Skip(int count) override; + int64_t ByteCount() const override; private: // Insures that buffer_ is not NULL. @@ -250,7 +231,7 @@ class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream CopyingInputStream* copying_stream_; bool owns_copying_stream_; - // True if we have seen a permenant error from the underlying stream. + // True if we have seen a permanent error from the underlying stream. bool failed_; // The current position of copying_stream_, relative to the point where @@ -259,7 +240,7 @@ class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream // Data is read into this buffer. It may be NULL if no buffer is currently // in use. Otherwise, it points to an array of size buffer_size_. - google::protobuf::scoped_array buffer_; + std::unique_ptr buffer_; const int buffer_size_; // Number of valid bytes currently in the buffer (i.e. the size last @@ -287,7 +268,7 @@ class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream // CopyingOutputStream implementations should avoid buffering if possible. // CopyingOutputStreamAdaptor does its own buffering and will write data // in large blocks. -class LIBPROTOBUF_EXPORT CopyingOutputStream { +class PROTOBUF_EXPORT CopyingOutputStream { public: virtual ~CopyingOutputStream() {} @@ -303,7 +284,7 @@ class LIBPROTOBUF_EXPORT CopyingOutputStream { // If you want to write to file descriptors or C++ ostreams, this is // already implemented for you: use FileOutputStream or OstreamOutputStream // respectively. -class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream { +class PROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream { public: // Creates a stream that writes to the given Unix file descriptor. // If a block_size is given, it specifies the size of the buffers @@ -311,7 +292,7 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea // is used. explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream, int block_size = -1); - ~CopyingOutputStreamAdaptor(); + ~CopyingOutputStreamAdaptor() override; // Writes all pending data to the underlying stream. Returns false if a // write error occurred on the underlying stream. (The underlying @@ -323,9 +304,11 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; } // implements ZeroCopyOutputStream --------------------------------- - bool Next(void** data, int* size); - void BackUp(int count); - int64 ByteCount() const; + bool Next(void** data, int* size) override; + void BackUp(int count) override; + int64_t ByteCount() const override; + bool WriteAliasedRaw(const void* data, int size) override; + bool AllowsAliasing() const override { return true; } private: // Write the current buffer, if it is present. @@ -339,7 +322,7 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea CopyingOutputStream* copying_stream_; bool owns_copying_stream_; - // True if we have seen a permenant error from the underlying stream. + // True if we have seen a permanent error from the underlying stream. bool failed_; // The current position of copying_stream_, relative to the point where @@ -348,7 +331,7 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea // Data is written from this buffer. It may be NULL if no buffer is // currently in use. Otherwise, it points to an array of size buffer_size_. - google::protobuf::scoped_array buffer_; + std::unique_ptr buffer_; const int buffer_size_; // Number of valid bytes currently in the buffer (i.e. the size last @@ -359,6 +342,31 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor); }; +// =================================================================== + +// A ZeroCopyInputStream which wraps some other stream and limits it to +// a particular byte count. +class PROTOBUF_EXPORT LimitingInputStream : public ZeroCopyInputStream { + public: + LimitingInputStream(ZeroCopyInputStream* input, int64 limit); + ~LimitingInputStream() override; + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size) override; + void BackUp(int count) override; + bool Skip(int count) override; + int64_t ByteCount() const override; + + + private: + ZeroCopyInputStream* input_; + int64 limit_; // Decreases as we go, becomes negative if we overshoot. + int64 prior_bytes_read_; // Bytes read on underlying stream at construction + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream); +}; + + // =================================================================== // mutable_string_data() and as_string_data() are workarounds to improve @@ -376,31 +384,25 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea // Return a pointer to mutable characters underlying the given string. The // return value is valid until the next time the string is resized. We // trust the caller to treat the return value as an array of length s->size(). -inline char* mutable_string_data(string* s) { -#ifdef LANG_CXX11 +inline char* mutable_string_data(std::string* s) { // This should be simpler & faster than string_as_array() because the latter // is guaranteed to return NULL when *s is empty, so it has to check for that. return &(*s)[0]; -#else - return string_as_array(s); -#endif } // as_string_data(s) is equivalent to // ({ char* p = mutable_string_data(s); make_pair(p, p != NULL); }) // Sometimes it's faster: in some scenarios p cannot be NULL, and then the // code can avoid that check. -inline std::pair as_string_data(string* s) { - char *p = mutable_string_data(s); -#ifdef LANG_CXX11 +inline std::pair as_string_data(std::string* s) { + char* p = mutable_string_data(s); return std::make_pair(p, true); -#else - return std::make_pair(p, p != NULL); -#endif } } // namespace io } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc index 2bca6a9088670..cc53949fce581 100644 --- a/src/google/protobuf/io/zero_copy_stream_unittest.cc +++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc @@ -50,19 +50,19 @@ #ifndef _MSC_VER #include #endif +#include +#include #include -#include #include -#include -#include +#include + #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include +#include #include +#include #include #if HAVE_ZLIB @@ -70,10 +70,9 @@ #endif #include -#include #include -#include #include +#include #include namespace google { @@ -83,22 +82,19 @@ namespace { #ifdef _WIN32 #define pipe(fds) _pipe(fds, 4096, O_BINARY) -#endif - -#ifdef _MSC_VER // DO NOT include , instead create functions in io_win32.{h,cc} and import // them like we do below. -using google::protobuf::internal::win32::access; -using google::protobuf::internal::win32::mkdir; -using google::protobuf::internal::win32::open; -using google::protobuf::internal::win32::close; +using google::protobuf::io::win32::access; +using google::protobuf::io::win32::close; +using google::protobuf::io::win32::mkdir; +using google::protobuf::io::win32::open; #endif #ifndef O_BINARY #ifdef _O_BINARY #define O_BINARY _O_BINARY #else -#define O_BINARY 0 // If this isn't defined, the platform doesn't need it. +#define O_BINARY 0 // If this isn't defined, the platform doesn't need it. #endif #endif @@ -111,12 +107,12 @@ class IoTest : public testing::Test { // Helper to read a fixed-length array of data from an input stream. int ReadFromInput(ZeroCopyInputStream* input, void* data, int size); // Write a string to the output stream. - void WriteString(ZeroCopyOutputStream* output, const string& str); + void WriteString(ZeroCopyOutputStream* output, const std::string& str); // Read a number of bytes equal to the size of the given string and checks // that it matches the string. - void ReadString(ZeroCopyInputStream* input, const string& str); + void ReadString(ZeroCopyInputStream* input, const std::string& str); // Writes some text to the output stream in a particular order. Returns - // the number of bytes written, incase the caller needs that to set up an + // the number of bytes written, in case the caller needs that to set up an // input stream. int WriteStuff(ZeroCopyOutputStream* output); // Reads text from an input stream and expects it to match what @@ -130,8 +126,9 @@ class IoTest : public testing::Test { void ReadStuffLarge(ZeroCopyInputStream* input); #if HAVE_ZLIB - string Compress(const string& data, const GzipOutputStream::Options& options); - string Uncompress(const string& data); + std::string Compress(const std::string& data, + const GzipOutputStream::Options& options); + std::string Uncompress(const std::string& data); #endif static const int kBlockSizes[]; @@ -141,8 +138,8 @@ class IoTest : public testing::Test { const int IoTest::kBlockSizes[] = {-1, 1, 2, 5, 7, 10, 23, 64}; const int IoTest::kBlockSizeCount = GOOGLE_ARRAYSIZE(IoTest::kBlockSizes); -bool IoTest::WriteToOutput(ZeroCopyOutputStream* output, - const void* data, int size) { +bool IoTest::WriteToOutput(ZeroCopyOutputStream* output, const void* data, + int size) { const uint8* in = reinterpret_cast(data); int in_size = size; @@ -204,12 +201,12 @@ int IoTest::ReadFromInput(ZeroCopyInputStream* input, void* data, int size) { } } -void IoTest::WriteString(ZeroCopyOutputStream* output, const string& str) { +void IoTest::WriteString(ZeroCopyOutputStream* output, const std::string& str) { EXPECT_TRUE(WriteToOutput(output, str.c_str(), str.size())); } -void IoTest::ReadString(ZeroCopyInputStream* input, const string& str) { - google::protobuf::scoped_array buffer(new char[str.size() + 1]); +void IoTest::ReadString(ZeroCopyInputStream* input, const std::string& str) { + std::unique_ptr buffer(new char[str.size() + 1]); buffer[str.size()] = '\0'; EXPECT_EQ(ReadFromInput(input, buffer.get(), str.size()), str.size()); EXPECT_STREQ(str.c_str(), buffer.get()); @@ -251,8 +248,8 @@ int IoTest::WriteStuffLarge(ZeroCopyOutputStream* output) { WriteString(output, "Hello world!\n"); WriteString(output, "Some te"); WriteString(output, "xt. Blah blah."); - WriteString(output, string(100000, 'x')); // A very long string - WriteString(output, string(100000, 'y')); // A very long string + WriteString(output, std::string(100000, 'x')); // A very long string + WriteString(output, std::string(100000, 'y')); // A very long string WriteString(output, "01234567890123456789"); EXPECT_EQ(output->ByteCount(), 200055); @@ -268,7 +265,7 @@ void IoTest::ReadStuffLarge(ZeroCopyInputStream* input) { EXPECT_TRUE(input->Skip(5)); ReadString(input, "blah."); EXPECT_TRUE(input->Skip(100000 - 10)); - ReadString(input, string(10, 'x') + string(100000 - 20000, 'y')); + ReadString(input, std::string(10, 'x') + std::string(100000 - 20000, 'y')); EXPECT_TRUE(input->Skip(20000 - 10)); ReadString(input, "yyyyyyyyyy01234567890123456789"); @@ -304,7 +301,7 @@ TEST_F(IoTest, TwoSessionWrite) { static const char* strA = "0123456789"; static const char* strB = "WhirledPeas"; - const int kBufferSize = 2*1024; + const int kBufferSize = 2 * 1024; uint8* buffer = new uint8[kBufferSize]; char* temp_buffer = new char[40]; @@ -318,8 +315,8 @@ TEST_F(IoTest, TwoSessionWrite) { delete coded_output; // flush int64 pos = output->ByteCount(); delete output; - output = new ArrayOutputStream( - buffer + pos, kBufferSize - pos, kBlockSizes[i]); + output = new ArrayOutputStream(buffer + pos, kBufferSize - pos, + kBlockSizes[i]); coded_output = new CodedOutputStream(output); coded_output->WriteVarint32(strlen(strB)); coded_output->WriteRaw(strB, strlen(strB)); @@ -346,13 +343,13 @@ TEST_F(IoTest, TwoSessionWrite) { } } - delete [] temp_buffer; - delete [] buffer; + delete[] temp_buffer; + delete[] buffer; } #if HAVE_ZLIB TEST_F(IoTest, GzipIo) { - const int kBufferSize = 2*1024; + const int kBufferSize = 2 * 1024; uint8* buffer = new uint8[kBufferSize]; for (int i = 0; i < kBlockSizeCount; i++) { for (int j = 0; j < kBlockSizeCount; j++) { @@ -373,18 +370,17 @@ TEST_F(IoTest, GzipIo) { } { ArrayInputStream input(buffer, size, kBlockSizes[j]); - GzipInputStream gzin( - &input, GzipInputStream::GZIP, gzip_buffer_size); + GzipInputStream gzin(&input, GzipInputStream::GZIP, gzip_buffer_size); ReadStuff(&gzin); } } } } - delete [] buffer; + delete[] buffer; } TEST_F(IoTest, GzipIoWithFlush) { - const int kBufferSize = 2*1024; + const int kBufferSize = 2 * 1024; uint8* buffer = new uint8[kBufferSize]; // We start with i = 4 as we want a block size > 6. With block size <= 6 // Flush() fills up the entire 2K buffer with flush markers and the test @@ -409,18 +405,17 @@ TEST_F(IoTest, GzipIoWithFlush) { } { ArrayInputStream input(buffer, size, kBlockSizes[j]); - GzipInputStream gzin( - &input, GzipInputStream::GZIP, gzip_buffer_size); + GzipInputStream gzin(&input, GzipInputStream::GZIP, gzip_buffer_size); ReadStuff(&gzin); } } } } - delete [] buffer; + delete[] buffer; } TEST_F(IoTest, GzipIoContiguousFlushes) { - const int kBufferSize = 2*1024; + const int kBufferSize = 2 * 1024; uint8* buffer = new uint8[kBufferSize]; int block_size = kBlockSizes[4]; @@ -441,15 +436,14 @@ TEST_F(IoTest, GzipIoContiguousFlushes) { size = output.ByteCount(); ArrayInputStream input(buffer, size, block_size); - GzipInputStream gzin( - &input, GzipInputStream::GZIP, gzip_buffer_size); + GzipInputStream gzin(&input, GzipInputStream::GZIP, gzip_buffer_size); ReadStuff(&gzin); - delete [] buffer; + delete[] buffer; } TEST_F(IoTest, GzipIoReadAfterFlush) { - const int kBufferSize = 2*1024; + const int kBufferSize = 2 * 1024; uint8* buffer = new uint8[kBufferSize]; int block_size = kBlockSizes[4]; @@ -468,17 +462,16 @@ TEST_F(IoTest, GzipIoReadAfterFlush) { size = output.ByteCount(); ArrayInputStream input(buffer, size, block_size); - GzipInputStream gzin( - &input, GzipInputStream::GZIP, gzip_buffer_size); + GzipInputStream gzin(&input, GzipInputStream::GZIP, gzip_buffer_size); ReadStuff(&gzin); gzout.Close(); - delete [] buffer; + delete[] buffer; } TEST_F(IoTest, ZlibIo) { - const int kBufferSize = 2*1024; + const int kBufferSize = 2 * 1024; uint8* buffer = new uint8[kBufferSize]; for (int i = 0; i < kBlockSizeCount; i++) { for (int j = 0; j < kBlockSizeCount; j++) { @@ -499,18 +492,17 @@ TEST_F(IoTest, ZlibIo) { } { ArrayInputStream input(buffer, size, kBlockSizes[j]); - GzipInputStream gzin( - &input, GzipInputStream::ZLIB, gzip_buffer_size); + GzipInputStream gzin(&input, GzipInputStream::ZLIB, gzip_buffer_size); ReadStuff(&gzin); } } } } - delete [] buffer; + delete[] buffer; } TEST_F(IoTest, ZlibIoInputAutodetect) { - const int kBufferSize = 2*1024; + const int kBufferSize = 2 * 1024; uint8* buffer = new uint8[kBufferSize]; int size; { @@ -541,12 +533,12 @@ TEST_F(IoTest, ZlibIoInputAutodetect) { GzipInputStream gzin(&input, GzipInputStream::AUTO); ReadStuff(&gzin); } - delete [] buffer; + delete[] buffer; } -string IoTest::Compress(const string& data, - const GzipOutputStream::Options& options) { - string result; +std::string IoTest::Compress(const std::string& data, + const GzipOutputStream::Options& options) { + std::string result; { StringOutputStream output(&result); GzipOutputStream gzout(&output, options); @@ -555,8 +547,8 @@ string IoTest::Compress(const string& data, return result; } -string IoTest::Uncompress(const string& data) { - string result; +std::string IoTest::Uncompress(const std::string& data) { + std::string result; { ArrayInputStream input(data.data(), data.size()); GzipInputStream gzin(&input); @@ -572,22 +564,21 @@ string IoTest::Uncompress(const string& data) { TEST_F(IoTest, CompressionOptions) { // Some ad-hoc testing of compression options. - string golden; - GOOGLE_CHECK_OK(File::GetContents( - TestSourceDir() + - "/google/protobuf/testdata/golden_message", - &golden, true)); + std::string golden_filename = + TestUtil::GetTestDataPath("net/proto2/internal/testdata/golden_message"); + std::string golden; + GOOGLE_CHECK_OK(File::GetContents(golden_filename, &golden, true)); GzipOutputStream::Options options; - string gzip_compressed = Compress(golden, options); + std::string gzip_compressed = Compress(golden, options); options.compression_level = 0; - string not_compressed = Compress(golden, options); + std::string not_compressed = Compress(golden, options); // Try zlib compression for fun. options = GzipOutputStream::Options(); options.format = GzipOutputStream::ZLIB; - string zlib_compressed = Compress(golden, options); + std::string zlib_compressed = Compress(golden, options); // Uncompressed should be bigger than the original since it should have some // sort of header. @@ -610,7 +601,7 @@ TEST_F(IoTest, TwoSessionWriteGzip) { static const char* strA = "0123456789"; static const char* strB = "QuickBrownFox"; - const int kBufferSize = 2*1024; + const int kBufferSize = 2 * 1024; uint8* buffer = new uint8[kBufferSize]; char* temp_buffer = new char[40]; @@ -624,18 +615,18 @@ TEST_F(IoTest, TwoSessionWriteGzip) { coded_output->WriteVarint32(outlen); coded_output->WriteRaw(strA, outlen); delete coded_output; // flush - delete gzout; // flush + delete gzout; // flush int64 pos = output->ByteCount(); delete output; - output = new ArrayOutputStream( - buffer + pos, kBufferSize - pos, kBlockSizes[i]); + output = new ArrayOutputStream(buffer + pos, kBufferSize - pos, + kBlockSizes[i]); gzout = new GzipOutputStream(output); coded_output = new CodedOutputStream(gzout); outlen = strlen(strB) + 1; coded_output->WriteVarint32(outlen); coded_output->WriteRaw(strB, outlen); delete coded_output; // flush - delete gzout; // flush + delete gzout; // flush int64 size = pos + output->ByteCount(); delete output; @@ -655,10 +646,8 @@ TEST_F(IoTest, TwoSessionWriteGzip) { EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize)); EXPECT_EQ(0, memcmp(temp_buffer, strB, insize)) << " out_block_size=" << kBlockSizes[i] - << " in_block_size=" << kBlockSizes[j] - << " pos=" << pos - << " size=" << size - << " strB=" << strB << " in=" << temp_buffer; + << " in_block_size=" << kBlockSizes[j] << " pos=" << pos + << " size=" << size << " strB=" << strB << " in=" << temp_buffer; delete coded_input; delete gzin; @@ -666,13 +655,13 @@ TEST_F(IoTest, TwoSessionWriteGzip) { } } - delete [] temp_buffer; - delete [] buffer; + delete[] temp_buffer; + delete[] buffer; } TEST_F(IoTest, GzipInputByteCountAfterClosed) { - string golden = "abcdefghijklmnopqrstuvwxyz"; - string compressed = Compress(golden, GzipOutputStream::Options()); + std::string golden = "abcdefghijklmnopqrstuvwxyz"; + std::string compressed = Compress(golden, GzipOutputStream::Options()); for (int i = 0; i < kBlockSizeCount; i++) { ArrayInputStream arr_input(compressed.data(), compressed.size(), @@ -688,11 +677,11 @@ TEST_F(IoTest, GzipInputByteCountAfterClosed) { } TEST_F(IoTest, GzipInputByteCountAfterClosedConcatenatedStreams) { - string golden1 = "abcdefghijklmnopqrstuvwxyz"; - string golden2 = "the quick brown fox jumps over the lazy dog"; + std::string golden1 = "abcdefghijklmnopqrstuvwxyz"; + std::string golden2 = "the quick brown fox jumps over the lazy dog"; const size_t total_size = golden1.size() + golden2.size(); - string compressed = Compress(golden1, GzipOutputStream::Options()) + - Compress(golden2, GzipOutputStream::Options()); + std::string compressed = Compress(golden1, GzipOutputStream::Options()) + + Compress(golden2, GzipOutputStream::Options()); for (int i = 0; i < kBlockSizeCount; i++) { ArrayInputStream arr_input(compressed.data(), compressed.size(), @@ -712,7 +701,7 @@ TEST_F(IoTest, GzipInputByteCountAfterClosedConcatenatedStreams) { // explicit block sizes. So, we'll only run one test and we'll use // ArrayInput to read back the results. TEST_F(IoTest, StringIo) { - string str; + std::string str; { StringOutputStream output(&str); WriteStuff(&output); @@ -723,16 +712,31 @@ TEST_F(IoTest, StringIo) { } } +// Verifies that outputs up to kint32max can be created. +TEST_F(IoTest, LargeOutput) { + std::string str; + StringOutputStream output(&str); + void* unused_data; + int size; + // Repeatedly calling Next should eventually grow the buffer to kint32max. + do { + EXPECT_TRUE(output.Next(&unused_data, &size)); + } while (str.size() < std::numeric_limits::max()); + // Further increases should be possible. + output.Next(&unused_data, &size); + EXPECT_GT(size, 0); +} + // To test files, we create a temporary file, write, read, truncate, repeat. TEST_F(IoTest, FileIo) { - string filename = TestTempDir() + "/zero_copy_stream_test_file"; + std::string filename = TestTempDir() + "/zero_copy_stream_test_file"; for (int i = 0; i < kBlockSizeCount; i++) { for (int j = 0; j < kBlockSizeCount; j++) { // Make a temporary file. int file = - open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0777); + open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0777); ASSERT_GE(file, 0); { @@ -757,13 +761,13 @@ TEST_F(IoTest, FileIo) { #if HAVE_ZLIB TEST_F(IoTest, GzipFileIo) { - string filename = TestTempDir() + "/zero_copy_stream_test_file"; + std::string filename = TestTempDir() + "/zero_copy_stream_test_file"; for (int i = 0; i < kBlockSizeCount; i++) { for (int j = 0; j < kBlockSizeCount; j++) { // Make a temporary file. int file = - open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0777); + open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0777); ASSERT_GE(file, 0); { FileOutputStream output(file, kBlockSizes[i]); @@ -805,10 +809,8 @@ class MsvcDebugDisabler { old_mode_ = _CrtSetReportMode(_CRT_ASSERT, old_mode_); } - static void MyHandler(const wchar_t *expr, - const wchar_t *func, - const wchar_t *file, - unsigned int line, + static void MyHandler(const wchar_t* expr, const wchar_t* func, + const wchar_t* file, unsigned int line, uintptr_t pReserved) { // do nothing } @@ -936,19 +938,19 @@ TEST_F(IoTest, ConcatenatingInputStream) { // Now split it up into multiple streams of varying sizes. ASSERT_EQ(68, output.ByteCount()); // Test depends on this. - ArrayInputStream input1(buffer , 12); - ArrayInputStream input2(buffer + 12, 7); - ArrayInputStream input3(buffer + 19, 6); + ArrayInputStream input1(buffer, 12); + ArrayInputStream input2(buffer + 12, 7); + ArrayInputStream input3(buffer + 19, 6); ArrayInputStream input4(buffer + 25, 15); - ArrayInputStream input5(buffer + 40, 0); + ArrayInputStream input5(buffer + 40, 0); // Note: We want to make sure we have a stream boundary somewhere between // bytes 42 and 62, which is the range that it Skip()ed by ReadStuff(). This // tests that a bug that existed in the original code for Skip() is fixed. ArrayInputStream input6(buffer + 40, 10); ArrayInputStream input7(buffer + 50, 18); // Total = 68 bytes. - ZeroCopyInputStream* streams[] = - {&input1, &input2, &input3, &input4, &input5, &input6, &input7}; + ZeroCopyInputStream* streams[] = {&input1, &input2, &input3, &input4, + &input5, &input6, &input7}; // Create the concatenating stream and read. ConcatenatingInputStream input(streams, GOOGLE_ARRAYSIZE(streams)); @@ -991,7 +993,7 @@ TEST_F(IoTest, LimitingInputStreamByteCount) { LimitingInputStream input(&array_input, kHalfBufferSize - 1); EXPECT_EQ(0, input.ByteCount()); EXPECT_TRUE(input.Next(&data, &size)); - EXPECT_EQ(kHalfBufferSize - 1 , input.ByteCount()); + EXPECT_EQ(kHalfBufferSize - 1, input.ByteCount()); } // Check that a zero-size array doesn't confuse the code. diff --git a/src/google/protobuf/lite_arena_unittest.cc b/src/google/protobuf/lite_arena_unittest.cc index f0bee880aa669..d68c6c9bbe38b 100644 --- a/src/google/protobuf/lite_arena_unittest.cc +++ b/src/google/protobuf/lite_arena_unittest.cc @@ -30,46 +30,53 @@ #include #include -#include #include namespace google { namespace protobuf { namespace { -TEST(LiteArenaTest, MapNoHeapAllocation) { - // Allocate a large initial block to avoid mallocs during hooked test. - std::vector arena_block(128 * 1024); - google::protobuf::ArenaOptions options; - options.initial_block = &arena_block[0]; - options.initial_block_size = arena_block.size(); - google::protobuf::Arena arena(options); - string data; +class LiteArenaTest : public testing::Test { + protected: + LiteArenaTest() { + ArenaOptions options; + options.start_block_size = 128 * 1024; + options.max_block_size = 128 * 1024; + arena_.reset(new Arena(options)); + // Trigger the allocation of the first arena block, so that further use of + // the arena will not require any heap allocations. + Arena::CreateArray(arena_.get(), 1); + } + + std::unique_ptr arena_; +}; + +TEST_F(LiteArenaTest, MapNoHeapAllocation) { + std::string data; data.reserve(128 * 1024); { // TODO(teboring): Enable no heap check when ArenaStringPtr is used in // Map. - // google::protobuf::internal::NoHeapChecker no_heap; + // internal::NoHeapChecker no_heap; protobuf_unittest::TestArenaMapLite* from = - google::protobuf::Arena::CreateMessage(&arena); - google::protobuf::MapLiteTestUtil::SetArenaMapFields(from); + Arena::CreateMessage(arena_.get()); + MapLiteTestUtil::SetArenaMapFields(from); from->SerializeToString(&data); protobuf_unittest::TestArenaMapLite* to = - google::protobuf::Arena::CreateMessage(&arena); + Arena::CreateMessage(arena_.get()); to->ParseFromString(data); - google::protobuf::MapLiteTestUtil::ExpectArenaMapFieldsSet(*to); + MapLiteTestUtil::ExpectArenaMapFieldsSet(*to); } } -TEST(LiteArenaTest, UnknownFieldMemLeak) { - google::protobuf::Arena arena; +TEST_F(LiteArenaTest, UnknownFieldMemLeak) { protobuf_unittest::ForeignMessageArenaLite* message = - google::protobuf::Arena::CreateMessage( - &arena); - string data = "\012\000"; + Arena::CreateMessage( + arena_.get()); + std::string data = "\012\000"; int original_capacity = data.capacity(); while (data.capacity() <= original_capacity) { data.append("a"); diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc index 6cf166291971c..deb5f06b83359 100644 --- a/src/google/protobuf/lite_unittest.cc +++ b/src/google/protobuf/lite_unittest.cc @@ -30,8 +30,8 @@ // Author: kenton@google.com (Kenton Varda) -#include #include +#include #include #include @@ -41,27 +41,26 @@ #include #include #include +#include +#include #include #include -#include #include - #include -using std::string; +namespace google { +namespace protobuf { -namespace { // Helper methods to test parsing merge behavior. -void ExpectMessageMerged(const google::protobuf::unittest::TestAllTypesLite& message) { +void ExpectMessageMerged(const unittest::TestAllTypesLite& message) { EXPECT_EQ(message.optional_int32(), 3); EXPECT_EQ(message.optional_int64(), 2); EXPECT_EQ(message.optional_string(), "hello"); } -void AssignParsingMergeMessages( - google::protobuf::unittest::TestAllTypesLite* msg1, - google::protobuf::unittest::TestAllTypesLite* msg2, - google::protobuf::unittest::TestAllTypesLite* msg3) { +void AssignParsingMergeMessages(unittest::TestAllTypesLite* msg1, + unittest::TestAllTypesLite* msg2, + unittest::TestAllTypesLite* msg3) { msg1->set_optional_int32(1); msg2->set_optional_int64(2); msg3->set_optional_int32(3); @@ -69,119 +68,117 @@ void AssignParsingMergeMessages( } void SetAllTypesInEmptyMessageUnknownFields( - google::protobuf::unittest::TestEmptyMessageLite* empty_message) { + unittest::TestEmptyMessageLite* empty_message) { protobuf_unittest::TestAllTypesLite message; - google::protobuf::TestUtilLite::ExpectClear(message); - google::protobuf::TestUtilLite::SetAllFields(&message); - string data = message.SerializeAsString(); + TestUtilLite::ExpectClear(message); + TestUtilLite::SetAllFields(&message); + std::string data = message.SerializeAsString(); empty_message->ParseFromString(data); } void SetSomeTypesInEmptyMessageUnknownFields( - google::protobuf::unittest::TestEmptyMessageLite* empty_message) { + unittest::TestEmptyMessageLite* empty_message) { protobuf_unittest::TestAllTypesLite message; - google::protobuf::TestUtilLite::ExpectClear(message); + TestUtilLite::ExpectClear(message); message.set_optional_int32(101); message.set_optional_int64(102); message.set_optional_uint32(103); message.set_optional_uint64(104); - string data = message.SerializeAsString(); + std::string data = message.SerializeAsString(); empty_message->ParseFromString(data); } -} // namespace - TEST(Lite, AllLite1) { - string data; + std::string data; { protobuf_unittest::TestAllTypesLite message, message2, message3; - google::protobuf::TestUtilLite::ExpectClear(message); - google::protobuf::TestUtilLite::SetAllFields(&message); + TestUtilLite::ExpectClear(message); + TestUtilLite::SetAllFields(&message); message2.CopyFrom(message); data = message.SerializeAsString(); message3.ParseFromString(data); - google::protobuf::TestUtilLite::ExpectAllFieldsSet(message); - google::protobuf::TestUtilLite::ExpectAllFieldsSet(message2); - google::protobuf::TestUtilLite::ExpectAllFieldsSet(message3); - google::protobuf::TestUtilLite::ModifyRepeatedFields(&message); - google::protobuf::TestUtilLite::ExpectRepeatedFieldsModified(message); + TestUtilLite::ExpectAllFieldsSet(message); + TestUtilLite::ExpectAllFieldsSet(message2); + TestUtilLite::ExpectAllFieldsSet(message3); + TestUtilLite::ModifyRepeatedFields(&message); + TestUtilLite::ExpectRepeatedFieldsModified(message); message.Clear(); - google::protobuf::TestUtilLite::ExpectClear(message); + TestUtilLite::ExpectClear(message); } } TEST(Lite, AllLite2) { - string data; + std::string data; { protobuf_unittest::TestAllExtensionsLite message, message2, message3; - google::protobuf::TestUtilLite::ExpectExtensionsClear(message); - google::protobuf::TestUtilLite::SetAllExtensions(&message); + TestUtilLite::ExpectExtensionsClear(message); + TestUtilLite::SetAllExtensions(&message); message2.CopyFrom(message); - string extensions_data = message.SerializeAsString(); + std::string extensions_data = message.SerializeAsString(); message3.ParseFromString(extensions_data); - google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message); - google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message2); - google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message3); - google::protobuf::TestUtilLite::ModifyRepeatedExtensions(&message); - google::protobuf::TestUtilLite::ExpectRepeatedExtensionsModified(message); + TestUtilLite::ExpectAllExtensionsSet(message); + TestUtilLite::ExpectAllExtensionsSet(message2); + TestUtilLite::ExpectAllExtensionsSet(message3); + TestUtilLite::ModifyRepeatedExtensions(&message); + TestUtilLite::ExpectRepeatedExtensionsModified(message); message.Clear(); - google::protobuf::TestUtilLite::ExpectExtensionsClear(message); + TestUtilLite::ExpectExtensionsClear(message); } } TEST(Lite, AllLite3) { - string data, packed_data; + std::string data, packed_data; { protobuf_unittest::TestPackedTypesLite message, message2, message3; - google::protobuf::TestUtilLite::ExpectPackedClear(message); - google::protobuf::TestUtilLite::SetPackedFields(&message); + TestUtilLite::ExpectPackedClear(message); + TestUtilLite::SetPackedFields(&message); message2.CopyFrom(message); packed_data = message.SerializeAsString(); message3.ParseFromString(packed_data); - google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message); - google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message2); - google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message3); - google::protobuf::TestUtilLite::ModifyPackedFields(&message); - google::protobuf::TestUtilLite::ExpectPackedFieldsModified(message); + TestUtilLite::ExpectPackedFieldsSet(message); + TestUtilLite::ExpectPackedFieldsSet(message2); + TestUtilLite::ExpectPackedFieldsSet(message3); + TestUtilLite::ModifyPackedFields(&message); + TestUtilLite::ExpectPackedFieldsModified(message); message.Clear(); - google::protobuf::TestUtilLite::ExpectPackedClear(message); + TestUtilLite::ExpectPackedClear(message); } { protobuf_unittest::TestPackedExtensionsLite message, message2, message3; - google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message); - google::protobuf::TestUtilLite::SetPackedExtensions(&message); + TestUtilLite::ExpectPackedExtensionsClear(message); + TestUtilLite::SetPackedExtensions(&message); message2.CopyFrom(message); - string packed_extensions_data = message.SerializeAsString(); + std::string packed_extensions_data = message.SerializeAsString(); EXPECT_EQ(packed_extensions_data, packed_data); message3.ParseFromString(packed_extensions_data); - google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message); - google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message2); - google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message3); - google::protobuf::TestUtilLite::ModifyPackedExtensions(&message); - google::protobuf::TestUtilLite::ExpectPackedExtensionsModified(message); + TestUtilLite::ExpectPackedExtensionsSet(message); + TestUtilLite::ExpectPackedExtensionsSet(message2); + TestUtilLite::ExpectPackedExtensionsSet(message3); + TestUtilLite::ModifyPackedExtensions(&message); + TestUtilLite::ExpectPackedExtensionsModified(message); message.Clear(); - google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message); + TestUtilLite::ExpectPackedExtensionsClear(message); } } TEST(Lite, AllLite5) { - string data; + std::string data; { // Test that if an optional or required message/group field appears multiple // times in the input, they need to be merged. - google::protobuf::unittest::TestParsingMergeLite::RepeatedFieldsGenerator generator; - google::protobuf::unittest::TestAllTypesLite* msg1; - google::protobuf::unittest::TestAllTypesLite* msg2; - google::protobuf::unittest::TestAllTypesLite* msg3; - -#define ASSIGN_REPEATED_FIELD(FIELD) \ - msg1 = generator.add_##FIELD(); \ - msg2 = generator.add_##FIELD(); \ - msg3 = generator.add_##FIELD(); \ + unittest::TestParsingMergeLite::RepeatedFieldsGenerator generator; + unittest::TestAllTypesLite* msg1; + unittest::TestAllTypesLite* msg2; + unittest::TestAllTypesLite* msg3; + +#define ASSIGN_REPEATED_FIELD(FIELD) \ + msg1 = generator.add_##FIELD(); \ + msg2 = generator.add_##FIELD(); \ + msg3 = generator.add_##FIELD(); \ AssignParsingMergeMessages(msg1, msg2, msg3) ASSIGN_REPEATED_FIELD(field1); @@ -202,9 +199,9 @@ TEST(Lite, AllLite5) { #undef ASSIGN_REPEATED_GROUP - string buffer; + std::string buffer; generator.SerializeToString(&buffer); - google::protobuf::unittest::TestParsingMergeLite parsing_merge; + unittest::TestParsingMergeLite parsing_merge; parsing_merge.ParseFromString(buffer); // Required and optional fields should be merged. @@ -213,100 +210,100 @@ TEST(Lite, AllLite5) { ExpectMessageMerged( parsing_merge.optionalgroup().optional_group_all_types()); ExpectMessageMerged(parsing_merge.GetExtension( - google::protobuf::unittest::TestParsingMergeLite::optional_ext)); + unittest::TestParsingMergeLite::optional_ext)); // Repeated fields should not be merged. EXPECT_EQ(parsing_merge.repeated_all_types_size(), 3); EXPECT_EQ(parsing_merge.repeatedgroup_size(), 3); EXPECT_EQ(parsing_merge.ExtensionSize( - google::protobuf::unittest::TestParsingMergeLite::repeated_ext), + unittest::TestParsingMergeLite::repeated_ext), 3); } } TEST(Lite, AllLite6) { - string data; + std::string data; // Test unknown fields support for lite messages. { protobuf_unittest::TestAllTypesLite message, message2; protobuf_unittest::TestEmptyMessageLite empty_message; - google::protobuf::TestUtilLite::ExpectClear(message); - google::protobuf::TestUtilLite::SetAllFields(&message); + TestUtilLite::ExpectClear(message); + TestUtilLite::SetAllFields(&message); data = message.SerializeAsString(); - empty_message.ParseFromString(data); + ASSERT_TRUE(empty_message.ParseFromString(data)); data.clear(); data = empty_message.SerializeAsString(); - message2.ParseFromString(data); + EXPECT_TRUE(message2.ParseFromString(data)); data = message2.SerializeAsString(); - google::protobuf::TestUtilLite::ExpectAllFieldsSet(message2); + TestUtilLite::ExpectAllFieldsSet(message2); message.Clear(); - google::protobuf::TestUtilLite::ExpectClear(message); + TestUtilLite::ExpectClear(message); } } TEST(Lite, AllLite7) { - string data; + std::string data; { protobuf_unittest::TestAllExtensionsLite message, message2; protobuf_unittest::TestEmptyMessageLite empty_message; - google::protobuf::TestUtilLite::ExpectExtensionsClear(message); - google::protobuf::TestUtilLite::SetAllExtensions(&message); + TestUtilLite::ExpectExtensionsClear(message); + TestUtilLite::SetAllExtensions(&message); data = message.SerializeAsString(); empty_message.ParseFromString(data); data.clear(); data = empty_message.SerializeAsString(); message2.ParseFromString(data); data = message2.SerializeAsString(); - google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message2); + TestUtilLite::ExpectAllExtensionsSet(message2); message.Clear(); - google::protobuf::TestUtilLite::ExpectExtensionsClear(message); + TestUtilLite::ExpectExtensionsClear(message); } } TEST(Lite, AllLite8) { - string data; + std::string data; { protobuf_unittest::TestPackedTypesLite message, message2; protobuf_unittest::TestEmptyMessageLite empty_message; - google::protobuf::TestUtilLite::ExpectPackedClear(message); - google::protobuf::TestUtilLite::SetPackedFields(&message); + TestUtilLite::ExpectPackedClear(message); + TestUtilLite::SetPackedFields(&message); data = message.SerializeAsString(); empty_message.ParseFromString(data); data.clear(); data = empty_message.SerializeAsString(); message2.ParseFromString(data); data = message2.SerializeAsString(); - google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message2); + TestUtilLite::ExpectPackedFieldsSet(message2); message.Clear(); - google::protobuf::TestUtilLite::ExpectPackedClear(message); + TestUtilLite::ExpectPackedClear(message); } } TEST(Lite, AllLite9) { - string data; + std::string data; { protobuf_unittest::TestPackedExtensionsLite message, message2; protobuf_unittest::TestEmptyMessageLite empty_message; - google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message); - google::protobuf::TestUtilLite::SetPackedExtensions(&message); + TestUtilLite::ExpectPackedExtensionsClear(message); + TestUtilLite::SetPackedExtensions(&message); data = message.SerializeAsString(); empty_message.ParseFromString(data); data.clear(); data = empty_message.SerializeAsString(); message2.ParseFromString(data); data = message2.SerializeAsString(); - google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message2); + TestUtilLite::ExpectPackedExtensionsSet(message2); message.Clear(); - google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message); + TestUtilLite::ExpectPackedExtensionsClear(message); } } TEST(Lite, AllLite10) { - string data; + std::string data; { // Test Unknown fields swap @@ -314,7 +311,7 @@ TEST(Lite, AllLite10) { SetAllTypesInEmptyMessageUnknownFields(&empty_message); SetSomeTypesInEmptyMessageUnknownFields(&empty_message2); data = empty_message.SerializeAsString(); - string data2 = empty_message2.SerializeAsString(); + std::string data2 = empty_message2.SerializeAsString(); empty_message.Swap(&empty_message2); EXPECT_EQ(data, empty_message2.SerializeAsString()); EXPECT_EQ(data2, empty_message.SerializeAsString()); @@ -322,7 +319,7 @@ TEST(Lite, AllLite10) { } TEST(Lite, AllLite11) { - string data; + std::string data; { // Test unknown fields swap with self @@ -335,7 +332,7 @@ TEST(Lite, AllLite11) { } TEST(Lite, AllLite12) { - string data; + std::string data; { // Test MergeFrom with unknown fields @@ -343,10 +340,10 @@ TEST(Lite, AllLite12) { protobuf_unittest::TestEmptyMessageLite empty_message, empty_message2; message.set_optional_int32(101); message.add_repeated_int32(201); - message.set_optional_nested_enum(google::protobuf::unittest::TestAllTypesLite::BAZ); + message.set_optional_nested_enum(unittest::TestAllTypesLite::BAZ); message2.set_optional_int64(102); message2.add_repeated_int64(202); - message2.set_optional_foreign_enum(google::protobuf::unittest::FOREIGN_LITE_BAZ); + message2.set_optional_foreign_enum(unittest::FOREIGN_LITE_BAZ); data = message.SerializeAsString(); empty_message.ParseFromString(data); @@ -365,22 +362,22 @@ TEST(Lite, AllLite12) { } TEST(Lite, AllLite13) { - string data; + std::string data; { // Test unknown enum value protobuf_unittest::TestAllTypesLite message; - string buffer; + std::string buffer; { - google::protobuf::io::StringOutputStream output_stream(&buffer); - google::protobuf::io::CodedOutputStream coded_output(&output_stream); - google::protobuf::internal::WireFormatLite::WriteTag( + io::StringOutputStream output_stream(&buffer); + io::CodedOutputStream coded_output(&output_stream); + internal::WireFormatLite::WriteTag( protobuf_unittest::TestAllTypesLite::kOptionalNestedEnumFieldNumber, - google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT, &coded_output); + internal::WireFormatLite::WIRETYPE_VARINT, &coded_output); coded_output.WriteVarint32(10); - google::protobuf::internal::WireFormatLite::WriteTag( + internal::WireFormatLite::WriteTag( protobuf_unittest::TestAllTypesLite::kRepeatedNestedEnumFieldNumber, - google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT, &coded_output); + internal::WireFormatLite::WIRETYPE_VARINT, &coded_output); coded_output.WriteVarint32(20); } message.ParseFromString(buffer); @@ -390,7 +387,7 @@ TEST(Lite, AllLite13) { } TEST(Lite, AllLite14) { - string data; + std::string data; { // Test Clear with unknown fields @@ -404,77 +401,76 @@ TEST(Lite, AllLite14) { // Tests for map lite ============================================= TEST(Lite, AllLite15) { - string data; + std::string data; { // Accessors protobuf_unittest::TestMapLite message; - google::protobuf::MapLiteTestUtil::SetMapFields(&message); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message); + MapLiteTestUtil::SetMapFields(&message); + MapLiteTestUtil::ExpectMapFieldsSet(message); - google::protobuf::MapLiteTestUtil::ModifyMapFields(&message); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsModified(message); + MapLiteTestUtil::ModifyMapFields(&message); + MapLiteTestUtil::ExpectMapFieldsModified(message); } } TEST(Lite, AllLite16) { - string data; + std::string data; { // SetMapFieldsInitialized protobuf_unittest::TestMapLite message; - google::protobuf::MapLiteTestUtil::SetMapFieldsInitialized(&message); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSetInitialized(message); + MapLiteTestUtil::SetMapFieldsInitialized(&message); + MapLiteTestUtil::ExpectMapFieldsSetInitialized(message); } } TEST(Lite, AllLite17) { - string data; + std::string data; { // Clear protobuf_unittest::TestMapLite message; - google::protobuf::MapLiteTestUtil::SetMapFields(&message); + MapLiteTestUtil::SetMapFields(&message); message.Clear(); - google::protobuf::MapLiteTestUtil::ExpectClear(message); + MapLiteTestUtil::ExpectClear(message); } } TEST(Lite, AllLite18) { - string data; + std::string data; { // ClearMessageMap protobuf_unittest::TestMessageMapLite message; // Creates a TestAllTypes with default value - google::protobuf::TestUtilLite::ExpectClear( - (*message.mutable_map_int32_message())[0]); + TestUtilLite::ExpectClear((*message.mutable_map_int32_message())[0]); } } TEST(Lite, AllLite19) { - string data; + std::string data; { // CopyFrom protobuf_unittest::TestMapLite message1, message2; - google::protobuf::MapLiteTestUtil::SetMapFields(&message1); + MapLiteTestUtil::SetMapFields(&message1); message2.CopyFrom(message1); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + MapLiteTestUtil::ExpectMapFieldsSet(message2); // Copying from self should be a no-op. message2.CopyFrom(message2); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + MapLiteTestUtil::ExpectMapFieldsSet(message2); } } TEST(Lite, AllLite20) { - string data; + std::string data; { // CopyFromMessageMap @@ -492,93 +488,93 @@ TEST(Lite, AllLite20) { } TEST(Lite, AllLite21) { - string data; + std::string data; { // SwapWithEmpty protobuf_unittest::TestMapLite message1, message2; - google::protobuf::MapLiteTestUtil::SetMapFields(&message1); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message1); - google::protobuf::MapLiteTestUtil::ExpectClear(message2); + MapLiteTestUtil::SetMapFields(&message1); + MapLiteTestUtil::ExpectMapFieldsSet(message1); + MapLiteTestUtil::ExpectClear(message2); message1.Swap(&message2); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); - google::protobuf::MapLiteTestUtil::ExpectClear(message1); + MapLiteTestUtil::ExpectMapFieldsSet(message2); + MapLiteTestUtil::ExpectClear(message1); } } TEST(Lite, AllLite22) { - string data; + std::string data; { // SwapWithSelf protobuf_unittest::TestMapLite message; - google::protobuf::MapLiteTestUtil::SetMapFields(&message); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message); + MapLiteTestUtil::SetMapFields(&message); + MapLiteTestUtil::ExpectMapFieldsSet(message); message.Swap(&message); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message); + MapLiteTestUtil::ExpectMapFieldsSet(message); } } TEST(Lite, AllLite23) { - string data; + std::string data; { // SwapWithOther protobuf_unittest::TestMapLite message1, message2; - google::protobuf::MapLiteTestUtil::SetMapFields(&message1); - google::protobuf::MapLiteTestUtil::SetMapFields(&message2); - google::protobuf::MapLiteTestUtil::ModifyMapFields(&message2); + MapLiteTestUtil::SetMapFields(&message1); + MapLiteTestUtil::SetMapFields(&message2); + MapLiteTestUtil::ModifyMapFields(&message2); message1.Swap(&message2); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsModified(message1); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + MapLiteTestUtil::ExpectMapFieldsModified(message1); + MapLiteTestUtil::ExpectMapFieldsSet(message2); } } TEST(Lite, AllLite24) { - string data; + std::string data; { // CopyConstructor protobuf_unittest::TestMapLite message1; - google::protobuf::MapLiteTestUtil::SetMapFields(&message1); + MapLiteTestUtil::SetMapFields(&message1); protobuf_unittest::TestMapLite message2(message1); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + MapLiteTestUtil::ExpectMapFieldsSet(message2); } } TEST(Lite, AllLite25) { - string data; + std::string data; { // CopyAssignmentOperator protobuf_unittest::TestMapLite message1; - google::protobuf::MapLiteTestUtil::SetMapFields(&message1); + MapLiteTestUtil::SetMapFields(&message1); protobuf_unittest::TestMapLite message2; message2 = message1; - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + MapLiteTestUtil::ExpectMapFieldsSet(message2); // Make sure that self-assignment does something sane. message2.operator=(message2); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + MapLiteTestUtil::ExpectMapFieldsSet(message2); } } TEST(Lite, AllLite26) { - string data; + std::string data; { // NonEmptyMergeFrom protobuf_unittest::TestMapLite message1, message2; - google::protobuf::MapLiteTestUtil::SetMapFields(&message1); + MapLiteTestUtil::SetMapFields(&message1); // This field will test merging into an empty spot. (*message2.mutable_map_int32_int32())[1] = 1; @@ -589,12 +585,12 @@ TEST(Lite, AllLite26) { (*message1.mutable_map_int32_double())[1] = 2; message1.MergeFrom(message2); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message1); + MapLiteTestUtil::ExpectMapFieldsSet(message1); } } TEST(Lite, AllLite27) { - string data; + std::string data; { // MergeFromMessageMap @@ -612,50 +608,49 @@ TEST(Lite, AllLite27) { } TEST(Lite, AllLite28) { - string data; + std::string data; { // Test the generated SerializeWithCachedSizesToArray() protobuf_unittest::TestMapLite message1, message2; - string data; - google::protobuf::MapLiteTestUtil::SetMapFields(&message1); - int size = message1.ByteSize(); + std::string data; + MapLiteTestUtil::SetMapFields(&message1); + size_t size = message1.ByteSizeLong(); data.resize(size); - ::google::protobuf::uint8* start = reinterpret_cast< ::google::protobuf::uint8*>(::google::protobuf::string_as_array(&data)); + ::google::protobuf::uint8* start = reinterpret_cast<::google::protobuf::uint8*>(::google::protobuf::string_as_array(&data)); ::google::protobuf::uint8* end = message1.SerializeWithCachedSizesToArray(start); EXPECT_EQ(size, end - start); EXPECT_TRUE(message2.ParseFromString(data)); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + MapLiteTestUtil::ExpectMapFieldsSet(message2); } } TEST(Lite, AllLite29) { - string data; + std::string data; { // Test the generated SerializeWithCachedSizes() protobuf_unittest::TestMapLite message1, message2; - google::protobuf::MapLiteTestUtil::SetMapFields(&message1); - int size = message1.ByteSize(); - string data; + MapLiteTestUtil::SetMapFields(&message1); + size_t size = message1.ByteSizeLong(); + std::string data; data.resize(size); { // Allow the output stream to buffer only one byte at a time. - google::protobuf::io::ArrayOutputStream array_stream( - ::google::protobuf::string_as_array(&data), size, 1); - google::protobuf::io::CodedOutputStream output_stream(&array_stream); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); message1.SerializeWithCachedSizes(&output_stream); EXPECT_FALSE(output_stream.HadError()); EXPECT_EQ(size, output_stream.ByteCount()); } EXPECT_TRUE(message2.ParseFromString(data)); - google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + MapLiteTestUtil::ExpectMapFieldsSet(message2); } } TEST(Lite, AllLite32) { - string data; + std::string data; { // Proto2UnknownEnum @@ -664,14 +659,14 @@ TEST(Lite, AllLite32) { protobuf_unittest::E_PROTO2_MAP_ENUM_FOO_LITE; (*from.mutable_unknown_map_field())[0] = protobuf_unittest::E_PROTO2_MAP_ENUM_EXTRA_LITE; - string data; + std::string data; from.SerializeToString(&data); protobuf_unittest::TestEnumMapLite to; EXPECT_TRUE(to.ParseFromString(data)); EXPECT_EQ(0, to.unknown_map_field().size()); EXPECT_FALSE(to.mutable_unknown_fields()->empty()); - EXPECT_EQ(1, to.known_map_field().size()); + ASSERT_EQ(1, to.known_map_field().size()); EXPECT_EQ(protobuf_unittest::PROTO2_MAP_ENUM_FOO_LITE, to.known_map_field().at(0)); @@ -679,141 +674,147 @@ TEST(Lite, AllLite32) { from.Clear(); to.SerializeToString(&data); EXPECT_TRUE(from.ParseFromString(data)); - EXPECT_EQ(1, from.known_map_field().size()); + ASSERT_EQ(1, from.known_map_field().size()); EXPECT_EQ(protobuf_unittest::E_PROTO2_MAP_ENUM_FOO_LITE, from.known_map_field().at(0)); - EXPECT_EQ(1, from.unknown_map_field().size()); + ASSERT_EQ(1, from.unknown_map_field().size()); EXPECT_EQ(protobuf_unittest::E_PROTO2_MAP_ENUM_EXTRA_LITE, from.unknown_map_field().at(0)); } } TEST(Lite, AllLite33) { - string data; + std::string data; { // StandardWireFormat protobuf_unittest::TestMapLite message; - string data = "\x0A\x04\x08\x01\x10\x01"; + std::string data = "\x0A\x04\x08\x01\x10\x01"; EXPECT_TRUE(message.ParseFromString(data)); - EXPECT_EQ(1, message.map_int32_int32().size()); + ASSERT_EQ(1, message.map_int32_int32().size()); EXPECT_EQ(1, message.map_int32_int32().at(1)); } } TEST(Lite, AllLite34) { - string data; + std::string data; { // UnorderedWireFormat protobuf_unittest::TestMapLite message; // put value before key in wire format - string data = "\x0A\x04\x10\x01\x08\x02"; + std::string data = "\x0A\x04\x10\x01\x08\x02"; EXPECT_TRUE(message.ParseFromString(data)); - EXPECT_EQ(1, message.map_int32_int32().size()); + ASSERT_EQ(1, message.map_int32_int32().size()); + ASSERT_NE(message.map_int32_int32().find(2), + message.map_int32_int32().end()); EXPECT_EQ(1, message.map_int32_int32().at(2)); } } TEST(Lite, AllLite35) { - string data; + std::string data; { // DuplicatedKeyWireFormat protobuf_unittest::TestMapLite message; // Two key fields in wire format - string data = "\x0A\x06\x08\x01\x08\x02\x10\x01"; + std::string data = "\x0A\x06\x08\x01\x08\x02\x10\x01"; EXPECT_TRUE(message.ParseFromString(data)); - EXPECT_EQ(1, message.map_int32_int32().size()); + ASSERT_EQ(1, message.map_int32_int32().size()); EXPECT_EQ(1, message.map_int32_int32().at(2)); } } TEST(Lite, AllLite36) { - string data; + std::string data; { // DuplicatedValueWireFormat protobuf_unittest::TestMapLite message; // Two value fields in wire format - string data = "\x0A\x06\x08\x01\x10\x01\x10\x02"; + std::string data = "\x0A\x06\x08\x01\x10\x01\x10\x02"; EXPECT_TRUE(message.ParseFromString(data)); - EXPECT_EQ(1, message.map_int32_int32().size()); + ASSERT_EQ(1, message.map_int32_int32().size()); EXPECT_EQ(2, message.map_int32_int32().at(1)); } } TEST(Lite, AllLite37) { - string data; + std::string data; { // MissedKeyWireFormat protobuf_unittest::TestMapLite message; // No key field in wire format - string data = "\x0A\x02\x10\x01"; + std::string data = "\x0A\x02\x10\x01"; EXPECT_TRUE(message.ParseFromString(data)); - EXPECT_EQ(1, message.map_int32_int32().size()); + ASSERT_EQ(1, message.map_int32_int32().size()); + ASSERT_NE(message.map_int32_int32().find(0), + message.map_int32_int32().end()); EXPECT_EQ(1, message.map_int32_int32().at(0)); } } TEST(Lite, AllLite38) { - string data; + std::string data; { // MissedValueWireFormat protobuf_unittest::TestMapLite message; // No value field in wire format - string data = "\x0A\x02\x08\x01"; + std::string data = "\x0A\x02\x08\x01"; EXPECT_TRUE(message.ParseFromString(data)); - EXPECT_EQ(1, message.map_int32_int32().size()); + ASSERT_EQ(1, message.map_int32_int32().size()); + ASSERT_NE(message.map_int32_int32().find(1), + message.map_int32_int32().end()); EXPECT_EQ(0, message.map_int32_int32().at(1)); } } TEST(Lite, AllLite39) { - string data; + std::string data; { // UnknownFieldWireFormat protobuf_unittest::TestMapLite message; // Unknown field in wire format - string data = "\x0A\x06\x08\x02\x10\x03\x18\x01"; + std::string data = "\x0A\x06\x08\x02\x10\x03\x18\x01"; EXPECT_TRUE(message.ParseFromString(data)); - EXPECT_EQ(1, message.map_int32_int32().size()); + ASSERT_EQ(1, message.map_int32_int32().size()); EXPECT_EQ(3, message.map_int32_int32().at(2)); } } TEST(Lite, AllLite40) { - string data; + std::string data; { // CorruptedWireFormat protobuf_unittest::TestMapLite message; // corrupted data in wire format - string data = "\x0A\x06\x08\x02\x11\x03"; + std::string data = "\x0A\x06\x08\x02\x11\x03"; EXPECT_FALSE(message.ParseFromString(data)); } } TEST(Lite, AllLite41) { - string data; + std::string data; { // IsInitialized @@ -832,33 +833,33 @@ TEST(Lite, AllLite41) { } TEST(Lite, AllLite42) { - string data; + std::string data; { - // Check that adding more values to enum does not corrupt message - // when passed through an old client. - protobuf_unittest::V2MessageLite v2_message; - v2_message.set_int_field(800); - // Set enum field to the value not understood by the old client. - v2_message.set_enum_field(protobuf_unittest::V2_SECOND); - string v2_bytes = v2_message.SerializeAsString(); - - protobuf_unittest::V1MessageLite v1_message; - v1_message.ParseFromString(v2_bytes); - EXPECT_TRUE(v1_message.IsInitialized()); - EXPECT_EQ(v1_message.int_field(), v2_message.int_field()); - // V1 client does not understand V2_SECOND value, so it discards it and - // uses default value instead. - EXPECT_EQ(v1_message.enum_field(), protobuf_unittest::V1_FIRST); - - // However, when re-serialized, it should preserve enum value. - string v1_bytes = v1_message.SerializeAsString(); - - protobuf_unittest::V2MessageLite same_v2_message; - same_v2_message.ParseFromString(v1_bytes); - - EXPECT_EQ(v2_message.int_field(), same_v2_message.int_field()); - EXPECT_EQ(v2_message.enum_field(), same_v2_message.enum_field()); + // Check that adding more values to enum does not corrupt message + // when passed through an old client. + protobuf_unittest::V2MessageLite v2_message; + v2_message.set_int_field(800); + // Set enum field to the value not understood by the old client. + v2_message.set_enum_field(protobuf_unittest::V2_SECOND); + std::string v2_bytes = v2_message.SerializeAsString(); + + protobuf_unittest::V1MessageLite v1_message; + v1_message.ParseFromString(v2_bytes); + EXPECT_TRUE(v1_message.IsInitialized()); + EXPECT_EQ(v1_message.int_field(), v2_message.int_field()); + // V1 client does not understand V2_SECOND value, so it discards it and + // uses default value instead. + EXPECT_EQ(v1_message.enum_field(), protobuf_unittest::V1_FIRST); + + // However, when re-serialized, it should preserve enum value. + std::string v1_bytes = v1_message.SerializeAsString(); + + protobuf_unittest::V2MessageLite same_v2_message; + same_v2_message.ParseFromString(v1_bytes); + + EXPECT_EQ(v2_message.int_field(), same_v2_message.int_field()); + EXPECT_EQ(v2_message.enum_field(), same_v2_message.enum_field()); } } @@ -868,14 +869,14 @@ TEST(Lite, AllLite43) { protobuf_unittest::TestOneofParsingLite message1; message1.set_oneof_int32(17); - string serialized; + std::string serialized; EXPECT_TRUE(message1.SerializeToString(&serialized)); // Submessage { protobuf_unittest::TestOneofParsingLite message2; message2.mutable_oneof_submessage(); - google::protobuf::io::CodedInputStream input_stream( + io::CodedInputStream input_stream( reinterpret_cast(serialized.data()), serialized.size()); EXPECT_TRUE(message2.MergeFromCodedStream(&input_stream)); EXPECT_EQ(17, message2.oneof_int32()); @@ -885,7 +886,7 @@ TEST(Lite, AllLite43) { { protobuf_unittest::TestOneofParsingLite message2; message2.set_oneof_string("string"); - google::protobuf::io::CodedInputStream input_stream( + io::CodedInputStream input_stream( reinterpret_cast(serialized.data()), serialized.size()); EXPECT_TRUE(message2.MergeFromCodedStream(&input_stream)); EXPECT_EQ(17, message2.oneof_int32()); @@ -895,7 +896,7 @@ TEST(Lite, AllLite43) { { protobuf_unittest::TestOneofParsingLite message2; message2.set_oneof_bytes("bytes"); - google::protobuf::io::CodedInputStream input_stream( + io::CodedInputStream input_stream( reinterpret_cast(serialized.data()), serialized.size()); EXPECT_TRUE(message2.MergeFromCodedStream(&input_stream)); EXPECT_EQ(17, message2.oneof_int32()); @@ -910,11 +911,11 @@ TEST(Lite, AllLite44) { { protobuf_unittest::TestOneofParsingLite original; original.set_oneof_int32(17); - string serialized; + std::string serialized; EXPECT_TRUE(original.SerializeToString(&serialized)); protobuf_unittest::TestOneofParsingLite parsed; for (int i = 0; i < 2; ++i) { - google::protobuf::io::CodedInputStream input_stream( + io::CodedInputStream input_stream( reinterpret_cast(serialized.data()), serialized.size()); EXPECT_TRUE(parsed.MergeFromCodedStream(&input_stream)); @@ -926,11 +927,11 @@ TEST(Lite, AllLite44) { { protobuf_unittest::TestOneofParsingLite original; original.mutable_oneof_submessage()->set_optional_int32(5); - string serialized; + std::string serialized; EXPECT_TRUE(original.SerializeToString(&serialized)); protobuf_unittest::TestOneofParsingLite parsed; for (int i = 0; i < 2; ++i) { - google::protobuf::io::CodedInputStream input_stream( + io::CodedInputStream input_stream( reinterpret_cast(serialized.data()), serialized.size()); EXPECT_TRUE(parsed.MergeFromCodedStream(&input_stream)); @@ -942,11 +943,11 @@ TEST(Lite, AllLite44) { { protobuf_unittest::TestOneofParsingLite original; original.set_oneof_string("string"); - string serialized; + std::string serialized; EXPECT_TRUE(original.SerializeToString(&serialized)); protobuf_unittest::TestOneofParsingLite parsed; for (int i = 0; i < 2; ++i) { - google::protobuf::io::CodedInputStream input_stream( + io::CodedInputStream input_stream( reinterpret_cast(serialized.data()), serialized.size()); EXPECT_TRUE(parsed.MergeFromCodedStream(&input_stream)); @@ -958,11 +959,11 @@ TEST(Lite, AllLite44) { { protobuf_unittest::TestOneofParsingLite original; original.set_oneof_bytes("bytes"); - string serialized; + std::string serialized; EXPECT_TRUE(original.SerializeToString(&serialized)); protobuf_unittest::TestOneofParsingLite parsed; for (int i = 0; i < 2; ++i) { - google::protobuf::io::CodedInputStream input_stream( + io::CodedInputStream input_stream( reinterpret_cast(serialized.data()), serialized.size()); EXPECT_TRUE(parsed.MergeFromCodedStream(&input_stream)); @@ -974,11 +975,11 @@ TEST(Lite, AllLite44) { { protobuf_unittest::TestOneofParsingLite original; original.set_oneof_enum(protobuf_unittest::V2_SECOND); - string serialized; + std::string serialized; EXPECT_TRUE(original.SerializeToString(&serialized)); protobuf_unittest::TestOneofParsingLite parsed; for (int i = 0; i < 2; ++i) { - google::protobuf::io::CodedInputStream input_stream( + io::CodedInputStream input_stream( reinterpret_cast(serialized.data()), serialized.size()); EXPECT_TRUE(parsed.MergeFromCodedStream(&input_stream)); @@ -988,3 +989,284 @@ TEST(Lite, AllLite44) { std::cout << "PASS" << std::endl; } + +TEST(Lite, AllLite45) { + // Test unknown fields are not discarded upon parsing. + std::string data = "\20\1"; // varint 1 with field number 2 + + protobuf_unittest::ForeignMessageLite a; + EXPECT_TRUE(a.ParseFromString(data)); + io::CodedInputStream input_stream( + reinterpret_cast(data.data()), data.size()); + EXPECT_TRUE(a.MergePartialFromCodedStream(&input_stream)); + + std::string serialized = a.SerializeAsString(); + EXPECT_EQ(serialized.substr(0, 2), data); + EXPECT_EQ(serialized.substr(2), data); +} + +// The following two tests check for wire compatibility between packed and +// unpacked repeated fields. There used to be a bug in the generated parsing +// code that caused us to calculate the highest possible tag number without +// taking into account that a repeated field might not be in the packed (or +// unpacked) state we expect. These tests specifically check for that issue by +// making sure we can parse repeated fields when the tag is higher than we would +// expect. +TEST(Lite, AllLite46) { + protobuf_unittest::PackedInt32 packed; + packed.add_repeated_int32(42); + std::string serialized; + ASSERT_TRUE(packed.SerializeToString(&serialized)); + + protobuf_unittest::NonPackedInt32 non_packed; + ASSERT_TRUE(non_packed.ParseFromString(serialized)); + ASSERT_EQ(1, non_packed.repeated_int32_size()); + EXPECT_EQ(42, non_packed.repeated_int32(0)); +} + +TEST(Lite, AllLite47) { + protobuf_unittest::NonPackedFixed32 non_packed; + non_packed.add_repeated_fixed32(42); + std::string serialized; + ASSERT_TRUE(non_packed.SerializeToString(&serialized)); + + protobuf_unittest::PackedFixed32 packed; + ASSERT_TRUE(packed.ParseFromString(serialized)); + ASSERT_EQ(1, packed.repeated_fixed32_size()); + EXPECT_EQ(42, packed.repeated_fixed32(0)); +} + +TEST(Lite, MapCrash) { + // See b/113635730 + Arena arena; + auto msg = Arena::CreateMessage(&arena); + // Payload for the map with a enum varint that's longer > + // 10 bytes. This causes a parse fail and a subsequent delete. field 16 + // (map) tag = 128+2 = \202 \1 + // 13 long \15 + // int32 key = 1 (\10 \1) + // MapEnumLite value = too long varint (parse error) + EXPECT_FALSE(msg->ParseFromString( + "\202\1\15\10\1\200\200\200\200\200\200\200\200\200\200\1")); +} + +TEST(Lite, CorrectEnding) { + protobuf_unittest::TestAllTypesLite msg; + { + // All proto wireformat parsers should act the same on parsing data in as + // much as it concerns the parsing, ie. not the interpretation of the data. + // TestAllTypesLite is not a group inside another message. So in practice + // will not encounter an end-group tag. However the parser should behave + // like any wire format parser should. + static const char kWireFormat[] = "\204\1"; + io::CodedInputStream cis(reinterpret_cast(kWireFormat), 2); + // The old CodedInputStream parser got an optimization (ReadTagNoLastTag) + // for non-group messages (like TestAllTypesLite) which made it not accept + // end-group. This is not a real big deal, but I think going forward its + // good to have all parse loops behave 'exactly' the same. + EXPECT_TRUE(msg.MergePartialFromCodedStream(&cis)); + EXPECT_FALSE(cis.ConsumedEntireMessage()); + EXPECT_TRUE(cis.LastTagWas(132)); + } + { + // This is an incomplete end-group tag. This should be a genuine parse + // failure. + static const char kWireFormat[] = "\214"; + io::CodedInputStream cis(reinterpret_cast(kWireFormat), 1); + // Unfortunately the old parser detects a parse error in ReadTag and returns + // 0 (as it states 0 is an invalid tag). However 0 is not an invalid tag + // as it can be used to terminate the stream, so this returns true. + EXPECT_FALSE(msg.MergePartialFromCodedStream(&cis)); + } +} + +TEST(Lite, DebugString) { + protobuf_unittest::TestAllTypesLite message1, message2; + EXPECT_TRUE(HasPrefixString(message1.DebugString(), "MessageLite at 0x")); + EXPECT_TRUE(HasPrefixString(message2.DebugString(), "MessageLite at 0x")); + + // DebugString() and ShortDebugString() are the same for now. + EXPECT_EQ(message1.DebugString(), message1.ShortDebugString()); + + // Even identical lite protos should have different DebugString() output. Part + // of the reason for including the memory address is so that we get some + // non-determinism, which should make it easier for us to change the output + // later without breaking any code. + EXPECT_NE(message1.DebugString(), message2.DebugString()); +} + +TEST(Lite, EnumValueToName) { + EXPECT_EQ("FOREIGN_LITE_FOO", protobuf_unittest::ForeignEnumLite_Name( + protobuf_unittest::FOREIGN_LITE_FOO)); + EXPECT_EQ("FOREIGN_LITE_BAR", protobuf_unittest::ForeignEnumLite_Name( + protobuf_unittest::FOREIGN_LITE_BAR)); + EXPECT_EQ("FOREIGN_LITE_BAZ", protobuf_unittest::ForeignEnumLite_Name( + protobuf_unittest::FOREIGN_LITE_BAZ)); + EXPECT_EQ("", protobuf_unittest::ForeignEnumLite_Name(0)); + EXPECT_EQ("", protobuf_unittest::ForeignEnumLite_Name(999)); +} + +TEST(Lite, NestedEnumValueToName) { + EXPECT_EQ("FOO", protobuf_unittest::TestAllTypesLite::NestedEnum_Name( + protobuf_unittest::TestAllTypesLite::FOO)); + EXPECT_EQ("BAR", protobuf_unittest::TestAllTypesLite::NestedEnum_Name( + protobuf_unittest::TestAllTypesLite::BAR)); + EXPECT_EQ("BAZ", protobuf_unittest::TestAllTypesLite::NestedEnum_Name( + protobuf_unittest::TestAllTypesLite::BAZ)); + EXPECT_EQ("", protobuf_unittest::TestAllTypesLite::NestedEnum_Name(0)); + EXPECT_EQ("", protobuf_unittest::TestAllTypesLite::NestedEnum_Name(999)); +} + +TEST(Lite, EnumNameToValue) { + protobuf_unittest::ForeignEnumLite value; + + ASSERT_TRUE( + protobuf_unittest::ForeignEnumLite_Parse("FOREIGN_LITE_FOO", &value)); + EXPECT_EQ(protobuf_unittest::FOREIGN_LITE_FOO, value); + + ASSERT_TRUE( + protobuf_unittest::ForeignEnumLite_Parse("FOREIGN_LITE_BAR", &value)); + EXPECT_EQ(protobuf_unittest::FOREIGN_LITE_BAR, value); + + ASSERT_TRUE( + protobuf_unittest::ForeignEnumLite_Parse("FOREIGN_LITE_BAZ", &value)); + EXPECT_EQ(protobuf_unittest::FOREIGN_LITE_BAZ, value); + + // Non-existent values + EXPECT_FALSE(protobuf_unittest::ForeignEnumLite_Parse("E", &value)); + EXPECT_FALSE( + protobuf_unittest::ForeignEnumLite_Parse("FOREIGN_LITE_C", &value)); + EXPECT_FALSE(protobuf_unittest::ForeignEnumLite_Parse("G", &value)); +} + +TEST(Lite, NestedEnumNameToValue) { + protobuf_unittest::TestAllTypesLite::NestedEnum value; + + ASSERT_TRUE( + protobuf_unittest::TestAllTypesLite::NestedEnum_Parse("FOO", &value)); + EXPECT_EQ(protobuf_unittest::TestAllTypesLite::FOO, value); + + ASSERT_TRUE( + protobuf_unittest::TestAllTypesLite::NestedEnum_Parse("BAR", &value)); + EXPECT_EQ(protobuf_unittest::TestAllTypesLite::BAR, value); + + ASSERT_TRUE( + protobuf_unittest::TestAllTypesLite::NestedEnum_Parse("BAZ", &value)); + EXPECT_EQ(protobuf_unittest::TestAllTypesLite::BAZ, value); + + // Non-existent values + EXPECT_FALSE( + protobuf_unittest::TestAllTypesLite::NestedEnum_Parse("A", &value)); + EXPECT_FALSE( + protobuf_unittest::TestAllTypesLite::NestedEnum_Parse("C", &value)); + EXPECT_FALSE( + protobuf_unittest::TestAllTypesLite::NestedEnum_Parse("G", &value)); +} + +TEST(Lite, AliasedEnum) { + // Enums with allow_alias = true can have multiple entries with the same + // value. + EXPECT_EQ("FOO1", protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Name( + protobuf_unittest::DupEnum::FOO1)); + EXPECT_EQ("FOO1", protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Name( + protobuf_unittest::DupEnum::FOO2)); + EXPECT_EQ("BAR1", protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Name( + protobuf_unittest::DupEnum::BAR1)); + EXPECT_EQ("BAR1", protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Name( + protobuf_unittest::DupEnum::BAR2)); + EXPECT_EQ("BAZ", protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Name( + protobuf_unittest::DupEnum::BAZ)); + EXPECT_EQ("", protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Name(999)); + + protobuf_unittest::DupEnum::TestEnumWithDupValueLite value; + ASSERT_TRUE( + protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Parse("FOO1", &value)); + EXPECT_EQ(protobuf_unittest::DupEnum::FOO1, value); + + value = static_cast(0); + ASSERT_TRUE( + protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Parse("FOO2", &value)); + EXPECT_EQ(protobuf_unittest::DupEnum::FOO2, value); +} + + +TEST(Lite, CodedInputStreamRollback) { + { + protobuf_unittest::TestAllTypesLite m; + m.set_optional_bytes(std::string(30, 'a')); + std::string serialized = m.SerializeAsString(); + serialized += '\014'; + serialized += std::string(3, ' '); + io::ArrayInputStream is(serialized.data(), serialized.size(), + serialized.size() - 6); + { + io::CodedInputStream cis(&is); + m.Clear(); + m.MergePartialFromCodedStream(&cis); + EXPECT_TRUE(cis.LastTagWas(12)); + EXPECT_FALSE(cis.ConsumedEntireMessage()); + // Should leave is with 3 spaces; + } + const void* data; + int size; + ASSERT_TRUE(is.Next(&data, &size)); + ASSERT_EQ(size, 3); + EXPECT_EQ(memcmp(data, " ", 3), 0); + } + { + protobuf_unittest::TestPackedTypesLite m; + constexpr int kCount = 30; + for (int i = 0; i < kCount; i++) m.add_packed_fixed32(i); + std::string serialized = m.SerializeAsString(); + serialized += '\014'; + serialized += std::string(3, ' '); + // Buffer breaks in middle of a fixed32. + io::ArrayInputStream is(serialized.data(), serialized.size(), + serialized.size() - 7); + { + io::CodedInputStream cis(&is); + m.Clear(); + m.MergePartialFromCodedStream(&cis); + EXPECT_TRUE(cis.LastTagWas(12)); + EXPECT_FALSE(cis.ConsumedEntireMessage()); + // Should leave is with 3 spaces; + } + ASSERT_EQ(m.packed_fixed32_size(), kCount); + for (int i = 0; i < kCount; i++) EXPECT_EQ(m.packed_fixed32(i), i); + const void* data; + int size; + ASSERT_TRUE(is.Next(&data, &size)); + ASSERT_EQ(size, 3); + EXPECT_EQ(memcmp(data, " ", 3), 0); + } + { + protobuf_unittest::TestPackedTypesLite m; + constexpr int kCount = 30; + // Make sure we output 2 byte varints + for (int i = 0; i < kCount; i++) m.add_packed_fixed32(128 + i); + std::string serialized = m.SerializeAsString(); + serialized += '\014'; + serialized += std::string(3, ' '); + // Buffer breaks in middle of a 2 byte varint. + io::ArrayInputStream is(serialized.data(), serialized.size(), + serialized.size() - 5); + { + io::CodedInputStream cis(&is); + m.Clear(); + m.MergePartialFromCodedStream(&cis); + EXPECT_TRUE(cis.LastTagWas(12)); + EXPECT_FALSE(cis.ConsumedEntireMessage()); + // Should leave is with 3 spaces; + } + ASSERT_EQ(m.packed_fixed32_size(), kCount); + for (int i = 0; i < kCount; i++) EXPECT_EQ(m.packed_fixed32(i), i + 128); + const void* data; + int size; + ASSERT_TRUE(is.Next(&data, &size)); + ASSERT_EQ(size, 3); + EXPECT_EQ(memcmp(data, " ", 3), 0); + } +} + +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/map.cc b/src/google/protobuf/map.cc new file mode 100644 index 0000000000000..d60a9a285cc8b --- /dev/null +++ b/src/google/protobuf/map.cc @@ -0,0 +1,41 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +namespace google { +namespace protobuf { +namespace internal { + +void* const kGlobalEmptyTable[kGlobalEmptyTableSize] = {nullptr}; + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index 6514a0cc6d3eb..7efee12526a95 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -37,17 +37,31 @@ #ifndef GOOGLE_PROTOBUF_MAP_H__ #define GOOGLE_PROTOBUF_MAP_H__ +#include +#include #include #include // To support Visual Studio 2008 -#include +#include +#include +#include #include +#if defined(__cpp_lib_string_view) +#include +#endif // defined(__cpp_lib_string_view) + #include #include #include #include #include +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +#include + namespace google { namespace protobuf { @@ -56,17 +70,18 @@ class Map; class MapIterator; -template struct is_proto_enum; +template +struct is_proto_enum; namespace internal { template + WireFormatLite::FieldType value_wire_type> class MapFieldLite; template + WireFormatLite::FieldType value_wire_type> class MapField; template @@ -75,28 +90,262 @@ class TypeDefinedMapFieldBase; class DynamicMapField; class GeneratedMessageReflection; + +// re-implement std::allocator to use arena allocator for memory allocation. +// Used for Map implementation. Users should not use this class +// directly. +template +class MapAllocator { + public: + using value_type = U; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = size_t; + using difference_type = ptrdiff_t; + + constexpr MapAllocator() : arena_(nullptr) {} + explicit constexpr MapAllocator(Arena* arena) : arena_(arena) {} + template + MapAllocator(const MapAllocator& allocator) // NOLINT(runtime/explicit) + : arena_(allocator.arena()) {} + + pointer allocate(size_type n, const void* /* hint */ = nullptr) { + // If arena is not given, malloc needs to be called which doesn't + // construct element object. + if (arena_ == nullptr) { + return static_cast(::operator new(n * sizeof(value_type))); + } else { + return reinterpret_cast( + Arena::CreateArray(arena_, n * sizeof(value_type))); + } + } + + void deallocate(pointer p, size_type n) { + if (arena_ == nullptr) { +#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) + ::operator delete(p, n * sizeof(value_type)); +#else + (void)n; + ::operator delete(p); +#endif + } + } + +#if !defined(GOOGLE_PROTOBUF_OS_APPLE) && !defined(GOOGLE_PROTOBUF_OS_NACL) && \ + !defined(GOOGLE_PROTOBUF_OS_EMSCRIPTEN) + template + void construct(NodeType* p, Args&&... args) { + // Clang 3.6 doesn't compile static casting to void* directly. (Issue + // #1266) According C++ standard 5.2.9/1: "The static_cast operator shall + // not cast away constness". So first the maybe const pointer is casted to + // const void* and after the const void* is const casted. + new (const_cast(static_cast(p))) + NodeType(std::forward(args)...); + } + + template + void destroy(NodeType* p) { + p->~NodeType(); + } +#else + void construct(pointer p, const_reference t) { new (p) value_type(t); } + + void destroy(pointer p) { p->~value_type(); } +#endif + + template + struct rebind { + using other = MapAllocator; + }; + + template + bool operator==(const MapAllocator& other) const { + return arena_ == other.arena_; + } + + template + bool operator!=(const MapAllocator& other) const { + return arena_ != other.arena_; + } + + // To support Visual Studio 2008 + size_type max_size() const { + // parentheses around (std::...:max) prevents macro warning of max() + return (std::numeric_limits::max)(); + } + + // To support gcc-4.4, which does not properly + // support templated friend classes + Arena* arena() const { return arena_; } + + private: + using DestructorSkippable_ = void; + Arena* arena_; +}; + +template +using KeyForTree = + typename std::conditional::value, T, + std::reference_wrapper>::type; + +// Default case: Not transparent. +// We use std::hash/std::less and all the lookup functions +// only accept `key_type`. +template +struct TransparentSupport { + using hash = std::hash; + using less = std::less; + + static bool Equals(const key_type& a, const key_type& b) { return a == b; } + + template + using key_arg = key_type; +}; + +#if defined(__cpp_lib_string_view) +// If std::string_view is available, we add transparent support for std::string +// keys. We use std::hash as it supports the input types we +// care about. The lookup functions accept arbitrary `K`. This will include any +// key type that is convertible to std::string_view. +template <> +struct TransparentSupport { + static std::string_view ImplicitConvert(std::string_view str) { return str; } + // If the element is not convertible to std::string_view, try to convert to + // std::string first. + // The template makes this overload lose resolution when both have the same + // rank otherwise. + template + static std::string_view ImplicitConvert(const std::string& str) { + return str; + } + + struct hash : private std::hash { + using is_transparent = void; + + template + size_t operator()(const T& str) const { + return base()(ImplicitConvert(str)); + } + + private: + const std::hash& base() const { return *this; } + }; + struct less { + using is_transparent = void; + + template + bool operator()(const T& t, const U& u) const { + return ImplicitConvert(t) < ImplicitConvert(u); + } + }; + + template + static bool Equals(const T& t, const U& u) { + return ImplicitConvert(t) == ImplicitConvert(u); + } + + template + using key_arg = K; +}; +#endif // defined(__cpp_lib_string_view) + +template +using TreeForMap = + std::map, void*, typename TransparentSupport::less, + MapAllocator, void*>>>; + +inline bool TableEntryIsEmpty(void* const* table, size_t b) { + return table[b] == nullptr; +} +inline bool TableEntryIsNonEmptyList(void* const* table, size_t b) { + return table[b] != nullptr && table[b] != table[b ^ 1]; +} +inline bool TableEntryIsTree(void* const* table, size_t b) { + return !TableEntryIsEmpty(table, b) && !TableEntryIsNonEmptyList(table, b); +} +inline bool TableEntryIsList(void* const* table, size_t b) { + return !TableEntryIsTree(table, b); +} + +// This captures all numeric types. +inline size_t MapValueSpaceUsedExcludingSelfLong(bool) { return 0; } +inline size_t MapValueSpaceUsedExcludingSelfLong(const std::string& str) { + return StringSpaceUsedExcludingSelfLong(str); +} +template ().SpaceUsedLong())> +size_t MapValueSpaceUsedExcludingSelfLong(const T& message) { + return message.SpaceUsedLong() - sizeof(T); +} + +constexpr size_t kGlobalEmptyTableSize = 1; +PROTOBUF_EXPORT extern void* const kGlobalEmptyTable[kGlobalEmptyTableSize]; + +// Space used for the table, trees, and nodes. +// Does not include the indirect space used. Eg the data of a std::string. +template +PROTOBUF_NOINLINE size_t SpaceUsedInTable(void** table, size_t num_buckets, + size_t num_elements, + size_t sizeof_node) { + size_t size = 0; + // The size of the table. + size += sizeof(void*) * num_buckets; + // All the nodes. + size += sizeof_node * num_elements; + // For each tree, count the overhead of the those nodes. + // Two buckets at a time because we only care about trees. + for (size_t b = 0; b < num_buckets; b += 2) { + if (internal::TableEntryIsTree(table, b)) { + using Tree = TreeForMap; + Tree* tree = static_cast(table[b]); + // Estimated cost of the red-black tree nodes, 3 pointers plus a + // bool (plus alignment, so 4 pointers). + size += tree->size() * + (sizeof(typename Tree::value_type) + sizeof(void*) * 4); + } + } + return size; +} + +template ::value || + !std::is_scalar::value>::type> +size_t SpaceUsedInValues(const Map* map) { + size_t size = 0; + for (const auto& v : *map) { + size += internal::MapValueSpaceUsedExcludingSelfLong(v.first) + + internal::MapValueSpaceUsedExcludingSelfLong(v.second); + } + return size; +} + +inline size_t SpaceUsedInValues(const void*) { return 0; } + } // namespace internal -// This is the class for google::protobuf::Map's internal value_type. Instead of using +// This is the class for Map's internal value_type. Instead of using // std::pair as value_type, we use this class which provides us more control of // its process of construction and destruction. template -class MapPair { - public: - typedef const Key first_type; - typedef T second_type; +struct MapPair { + using first_type = const Key; + using second_type = T; MapPair(const Key& other_first, const T& other_second) : first(other_first), second(other_second) {} explicit MapPair(const Key& other_first) : first(other_first), second() {} - MapPair(const MapPair& other) - : first(other.first), second(other.second) {} + explicit MapPair(Key&& other_first) + : first(std::move(other_first)), second() {} + MapPair(const MapPair& other) : first(other.first), second(other.second) {} ~MapPair() {} // Implicitly convertible to std::pair of compatible types. template - operator std::pair() const { + operator std::pair() const { // NOLINT(runtime/explicit) return std::pair(first, second); } @@ -104,11 +353,11 @@ class MapPair { T second; private: - friend class ::google::protobuf::Arena; + friend class Arena; friend class Map; }; -// google::protobuf::Map is an associative container type used to store protobuf map +// Map is an associative container type used to store protobuf map // fields. Each Map instance may or may not use a different hash function, a // different iteration order, and so on. E.g., please don't examine // implementation details to decide if the following would work: @@ -121,161 +370,51 @@ class MapPair { template class Map { public: - typedef Key key_type; - typedef T mapped_type; - typedef MapPair value_type; + using key_type = Key; + using mapped_type = T; + using value_type = MapPair; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; - typedef size_t size_type; - typedef hash hasher; + using size_type = size_t; + using hasher = typename internal::TransparentSupport::hash; - Map() : arena_(NULL), default_enum_value_(0) { Init(); } - explicit Map(Arena* arena) : arena_(arena), default_enum_value_(0) { Init(); } + constexpr Map() : elements_(nullptr) {} + explicit Map(Arena* arena) : elements_(arena) {} - Map(const Map& other) - : arena_(NULL), default_enum_value_(other.default_enum_value_) { - Init(); - insert(other.begin(), other.end()); - } + Map(const Map& other) : Map() { insert(other.begin(), other.end()); } - template - Map(const InputIt& first, const InputIt& last) - : arena_(NULL), default_enum_value_(0) { - Init(); - insert(first, last); - } - - ~Map() { - clear(); - if (arena_ == NULL) { - delete elements_; + Map(Map&& other) noexcept : Map() { + if (other.arena() != nullptr) { + *this = other; + } else { + swap(other); } } - private: - void Init() { - elements_ = Arena::Create(arena_, 0u, hasher(), Allocator(arena_)); - } - - // re-implement std::allocator to use arena allocator for memory allocation. - // Used for google::protobuf::Map implementation. Users should not use this class - // directly. - template - class MapAllocator { - public: - typedef U value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - - MapAllocator() : arena_(NULL) {} - explicit MapAllocator(Arena* arena) : arena_(arena) {} - template - MapAllocator(const MapAllocator& allocator) - : arena_(allocator.arena()) {} - - pointer allocate(size_type n, const void* hint = 0) { - // If arena is not given, malloc needs to be called which doesn't - // construct element object. - if (arena_ == NULL) { - return static_cast(::operator new(n * sizeof(value_type))); + Map& operator=(Map&& other) noexcept { + if (this != &other) { + if (arena() != other.arena()) { + *this = other; } else { - return reinterpret_cast( - Arena::CreateArray(arena_, n * sizeof(value_type))); - } - } - - void deallocate(pointer p, size_type n) { - if (arena_ == NULL) { -#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) - ::operator delete(p, n * sizeof(value_type)); -#else - ::operator delete(p); -#endif + swap(other); } } + return *this; + } -#if __cplusplus >= 201103L && !defined(GOOGLE_PROTOBUF_OS_APPLE) && \ - !defined(GOOGLE_PROTOBUF_OS_NACL) && \ - !defined(GOOGLE_PROTOBUF_OS_EMSCRIPTEN) - template - void construct(NodeType* p, Args&&... args) { - // Clang 3.6 doesn't compile static casting to void* directly. (Issue - // #1266) According C++ standard 5.2.9/1: "The static_cast operator shall - // not cast away constness". So first the maybe const pointer is casted to - // const void* and after the const void* is const casted. - new (const_cast(static_cast(p))) - NodeType(std::forward(args)...); - } - - template - void destroy(NodeType* p) { - p->~NodeType(); - } -#else - void construct(pointer p, const_reference t) { new (p) value_type(t); } - - void destroy(pointer p) { p->~value_type(); } -#endif - - template - struct rebind { - typedef MapAllocator other; - }; - - template - bool operator==(const MapAllocator& other) const { - return arena_ == other.arena_; - } - - template - bool operator!=(const MapAllocator& other) const { - return arena_ != other.arena_; - } - - // To support Visual Studio 2008 - size_type max_size() const { - // parentheses around (std::...:max) prevents macro warning of max() - return (std::numeric_limits::max)(); - } - - // To support gcc-4.4, which does not properly - // support templated friend classes - Arena* arena() const { - return arena_; - } - - private: - typedef void DestructorSkippable_; - Arena* const arena_; - }; - - // InnerMap's key type is Key and its value type is value_type*. We use a - // custom class here and for Node, below, to ensure that k_ is at offset 0, - // allowing safe conversion from pointer to Node to pointer to Key, and vice - // versa when appropriate. - class KeyValuePair { - public: - KeyValuePair(const Key& k, value_type* v) : k_(k), v_(v) {} - - const Key& key() const { return k_; } - Key& key() { return k_; } - value_type* value() const { return v_; } - value_type*& value() { return v_; } + template + Map(const InputIt& first, const InputIt& last) : Map() { + insert(first, last); + } - private: - Key k_; - value_type* v_; - }; + ~Map() {} - typedef MapAllocator Allocator; + private: + using Allocator = internal::MapAllocator; // InnerMap is a generic hash-based map. It doesn't contain any // protocol-buffer-specific logic. It is a chaining hash map with the @@ -292,7 +431,7 @@ class Map { // 2. The number of buckets is a power of two. // 3. Buckets are converted to trees in pairs: if we convert bucket b then // buckets b and b^1 will share a tree. Invariant: buckets b and b^1 have - // the same non-NULL value iff they are sharing a tree. (An alternative + // the same non-null value iff they are sharing a tree. (An alternative // implementation strategy would be to have a tag bit per bucket.) // 4. As is typical for hash_map and such, the Keys and Values are always // stored in linked list nodes. Pointers to elements are never invalidated @@ -302,27 +441,27 @@ class Map { // 6. Once we've tree-converted a bucket, it is never converted back. However, // the items a tree contains may wind up assigned to trees or lists upon a // rehash. - // 7. The code requires no C++ features from C++11 or later. + // 7. The code requires no C++ features from C++14 or later. // 8. Mutations to a map do not invalidate the map's iterators, pointers to // elements, or references to elements. // 9. Except for erase(iterator), any non-const method can reorder iterators. + // 10. InnerMap uses KeyForTree when using the Tree representation, which + // is either `Key`, if Key is a scalar, or `reference_wrapper` + // otherwise. This avoids unnecessary copies of string keys, for example. class InnerMap : private hasher { public: - typedef value_type* Value; - - InnerMap(size_type n, hasher h, Allocator alloc) - : hasher(h), + explicit constexpr InnerMap(Arena* arena) + : hasher(), num_elements_(0), - seed_(Seed()), - table_(NULL), - alloc_(alloc) { - n = TableSize(n); - table_ = CreateEmptyTable(n); - num_buckets_ = index_of_first_non_null_ = n; - } + num_buckets_(internal::kGlobalEmptyTableSize), + seed_(0), + index_of_first_non_null_(internal::kGlobalEmptyTableSize), + table_(const_cast(internal::kGlobalEmptyTable)), + alloc_(arena) {} ~InnerMap() { - if (table_ != NULL) { + if (alloc_.arena() == nullptr && + num_buckets_ != internal::kGlobalEmptyTableSize) { clear(); Dealloc(table_, num_buckets_); } @@ -333,42 +472,37 @@ class Map { // Linked-list nodes, as one would expect for a chaining hash table. struct Node { - KeyValuePair kv; + value_type kv; Node* next; }; - // This is safe only if the given pointer is known to point to a Key that is - // part of a Node. - static Node* NodePtrFromKeyPtr(Key* k) { - return reinterpret_cast(k); - } - - static Key* KeyPtrFromNodePtr(Node* node) { return &node->kv.key(); } + // Trees. The payload type is a copy of Key, so that we can query the tree + // with Keys that are not in any particular data structure. + // The value is a void* pointing to Node. We use void* instead of Node* to + // avoid code bloat. That way there is only one instantiation of the tree + // class per key type. + using Tree = internal::TreeForMap; + using TreeIterator = typename Tree::iterator; - // Trees. The payload type is pointer to Key, so that we can query the tree - // with Keys that are not in any particular data structure. When we insert, - // though, the pointer is always pointing to a Key that is inside a Node. - struct KeyCompare { - bool operator()(const Key* n0, const Key* n1) const { return *n0 < *n1; } - }; - typedef typename Allocator::template rebind::other KeyPtrAllocator; - typedef std::set Tree; - typedef typename Tree::iterator TreeIterator; + static Node* NodeFromTreeIterator(TreeIterator it) { + return static_cast(it->second); + } // iterator and const_iterator are instantiations of iterator_base. template - struct iterator_base { - typedef KeyValueType& reference; - typedef KeyValueType* pointer; + class iterator_base { + public: + using reference = KeyValueType&; + using pointer = KeyValueType*; // Invariants: // node_ is always correct. This is handy because the most common // operations are operator* and operator-> and they only use node_. - // When node_ is set to a non-NULL value, all the other non-const fields + // When node_ is set to a non-null value, all the other non-const fields // are updated to be correct also, but those fields can become stale // if the underlying map is modified. When those fields are needed they // are rechecked, and updated if necessary. - iterator_base() : node_(NULL), m_(NULL), bucket_index_(0) {} + iterator_base() : node_(nullptr), m_(nullptr), bucket_index_(0) {} explicit iterator_base(const InnerMap* m) : m_(m) { SearchFrom(m->index_of_first_non_null_); @@ -385,18 +519,18 @@ class Map { : node_(n), m_(m), bucket_index_(index) {} iterator_base(TreeIterator tree_it, const InnerMap* m, size_type index) - : node_(NodePtrFromKeyPtr(*tree_it)), m_(m), bucket_index_(index) { + : node_(NodeFromTreeIterator(tree_it)), m_(m), bucket_index_(index) { // Invariant: iterators that use buckets with trees have an even // bucket_index_. - GOOGLE_DCHECK_EQ(bucket_index_ % 2, 0); + GOOGLE_DCHECK_EQ(bucket_index_ % 2, 0u); } // Advance through buckets, looking for the first that isn't empty. - // If nothing non-empty is found then leave node_ == NULL. + // If nothing non-empty is found then leave node_ == nullptr. void SearchFrom(size_type start_bucket) { GOOGLE_DCHECK(m_->index_of_first_non_null_ == m_->num_buckets_ || - m_->table_[m_->index_of_first_non_null_] != NULL); - node_ = NULL; + m_->table_[m_->index_of_first_non_null_] != nullptr); + node_ = nullptr; for (bucket_index_ = start_bucket; bucket_index_ < m_->num_buckets_; bucket_index_++) { if (m_->TableEntryIsNonEmptyList(bucket_index_)) { @@ -405,7 +539,7 @@ class Map { } else if (m_->TableEntryIsTree(bucket_index_)) { Tree* tree = static_cast(m_->table_[bucket_index_]); GOOGLE_DCHECK(!tree->empty()); - node_ = NodePtrFromKeyPtr(*tree->begin()); + node_ = NodeFromTreeIterator(tree->begin()); break; } } @@ -422,18 +556,18 @@ class Map { } iterator_base& operator++() { - if (node_->next == NULL) { + if (node_->next == nullptr) { TreeIterator tree_it; const bool is_list = revalidate_if_necessary(&tree_it); if (is_list) { SearchFrom(bucket_index_ + 1); } else { - GOOGLE_DCHECK_EQ(bucket_index_ & 1, 0); + GOOGLE_DCHECK_EQ(bucket_index_ & 1, 0u); Tree* tree = static_cast(m_->table_[bucket_index_]); if (++tree_it == tree->end()) { SearchFrom(bucket_index_ + 2); } else { - node_ = NodePtrFromKeyPtr(*tree_it); + node_ = NodeFromTreeIterator(tree_it); } } } else { @@ -448,22 +582,21 @@ class Map { return tmp; } - // Assumes node_ and m_ are correct and non-NULL, but other fields may be + // Assumes node_ and m_ are correct and non-null, but other fields may be // stale. Fix them as needed. Then return true iff node_ points to a // Node in a list. If false is returned then *it is modified to be // a valid iterator for node_. bool revalidate_if_necessary(TreeIterator* it) { - GOOGLE_DCHECK(node_ != NULL && m_ != NULL); + GOOGLE_DCHECK(node_ != nullptr && m_ != nullptr); // Force bucket_index_ to be in range. bucket_index_ &= (m_->num_buckets_ - 1); // Common case: the bucket we think is relevant points to node_. - if (m_->table_[bucket_index_] == static_cast(node_)) - return true; + if (m_->table_[bucket_index_] == static_cast(node_)) return true; // Less common: the bucket is a linked list with node_ somewhere in it, // but not at the head. if (m_->TableEntryIsNonEmptyList(bucket_index_)) { Node* l = static_cast(m_->table_[bucket_index_]); - while ((l = l->next) != NULL) { + while ((l = l->next) != nullptr) { if (l == node_) { return true; } @@ -472,8 +605,8 @@ class Map { // Well, bucket_index_ still might be correct, but probably // not. Revalidate just to be sure. This case is rare enough that we // don't worry about potential optimizations, such as having a custom - // find-like method that compares Node* instead of const Key&. - iterator_base i(m_->find(*KeyPtrFromNodePtr(node_), it)); + // find-like method that compares Node* instead of the key. + iterator_base i(m_->find(node_->kv.first, it)); bucket_index_ = i.bucket_index_; return m_->TableEntryIsList(bucket_index_); } @@ -484,8 +617,19 @@ class Map { }; public: - typedef iterator_base iterator; - typedef iterator_base const_iterator; + using iterator = iterator_base; + using const_iterator = iterator_base; + + Arena* arena() const { return alloc_.arena(); } + + void Swap(InnerMap* other) { + std::swap(num_elements_, other->num_elements_); + std::swap(num_buckets_, other->num_buckets_); + std::swap(seed_, other->seed_); + std::swap(index_of_first_non_null_, other->index_of_first_non_null_); + std::swap(table_, other->table_); + std::swap(alloc_, other->alloc_); + } iterator begin() { return iterator(this); } iterator end() { return iterator(); } @@ -496,19 +640,19 @@ class Map { for (size_type b = 0; b < num_buckets_; b++) { if (TableEntryIsNonEmptyList(b)) { Node* node = static_cast(table_[b]); - table_[b] = NULL; + table_[b] = nullptr; do { Node* next = node->next; DestroyNode(node); node = next; - } while (node != NULL); + } while (node != nullptr); } else if (TableEntryIsTree(b)) { Tree* tree = static_cast(table_[b]); GOOGLE_DCHECK(table_[b] == table_[b + 1] && (b & 1) == 0); - table_[b] = table_[b + 1] = NULL; + table_[b] = table_[b + 1] = nullptr; typename Tree::iterator tree_it = tree->begin(); do { - Node* node = NodePtrFromKeyPtr(*tree_it); + Node* node = NodeFromTreeIterator(tree_it); typename Tree::iterator next = tree_it; ++next; tree->erase(tree_it); @@ -531,50 +675,53 @@ class Map { size_type size() const { return num_elements_; } bool empty() const { return size() == 0; } - iterator find(const Key& k) { return iterator(FindHelper(k).first); } - const_iterator find(const Key& k) const { return find(k, NULL); } + template + iterator find(const K& k) { + return iterator(FindHelper(k).first); + } - // In traditional C++ style, this performs "insert if not present." - std::pair insert(const KeyValuePair& kv) { - std::pair p = FindHelper(kv.key()); - // Case 1: key was already present. - if (p.first.node_ != NULL) - return std::make_pair(iterator(p.first), false); - // Case 2: insert. - if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) { - p = FindHelper(kv.key()); - } - const size_type b = p.second; // bucket number - Node* node = Alloc(1); - alloc_.construct(&node->kv, kv); - iterator result = InsertUnique(b, node); - ++num_elements_; - return std::make_pair(result, true); + template + const_iterator find(const K& k) const { + return FindHelper(k).first; } - // The same, but if an insertion is necessary then the value portion of the - // inserted key-value pair is left uninitialized. - std::pair insert(const Key& k) { + // Insert the key into the map, if not present. In that case, the value will + // be value initialized. + template + std::pair insert(K&& k) { std::pair p = FindHelper(k); // Case 1: key was already present. - if (p.first.node_ != NULL) + if (p.first.node_ != nullptr) return std::make_pair(iterator(p.first), false); // Case 2: insert. if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) { p = FindHelper(k); } const size_type b = p.second; // bucket number - Node* node = Alloc(1); - typedef typename Allocator::template rebind::other KeyAllocator; - KeyAllocator(alloc_).construct(&node->kv.key(), k); + Node* node; + // If K is not key_type, make the conversion to key_type explicit. + using TypeToInit = typename std::conditional< + std::is_same::type, key_type>::value, K&&, + key_type>::type; + if (alloc_.arena() == nullptr) { + node = new Node{value_type(static_cast(std::forward(k))), + nullptr}; + } else { + node = Alloc(1); + Arena::CreateInArenaStorage( + const_cast(&node->kv.first), alloc_.arena(), + static_cast(std::forward(k))); + Arena::CreateInArenaStorage(&node->kv.second, alloc_.arena()); + } + iterator result = InsertUnique(b, node); ++num_elements_; return std::make_pair(result, true); } - Value& operator[](const Key& k) { - KeyValuePair kv(k, Value()); - return insert(kv).first->value(); + template + value_type& operator[](K&& k) { + return *insert(std::forward(k)).first; } void erase(iterator it) { @@ -591,52 +738,58 @@ class Map { } else { GOOGLE_DCHECK(TableEntryIsTree(b)); Tree* tree = static_cast(table_[b]); - tree->erase(*tree_it); + tree->erase(tree_it); if (tree->empty()) { // Force b to be the minimum of b and b ^ 1. This is important // only because we want index_of_first_non_null_ to be correct. b &= ~static_cast(1); DestroyTree(tree); - table_[b] = table_[b + 1] = NULL; + table_[b] = table_[b + 1] = nullptr; } } DestroyNode(item); --num_elements_; - if (GOOGLE_PREDICT_FALSE(b == index_of_first_non_null_)) { + if (PROTOBUF_PREDICT_FALSE(b == index_of_first_non_null_)) { while (index_of_first_non_null_ < num_buckets_ && - table_[index_of_first_non_null_] == NULL) { + table_[index_of_first_non_null_] == nullptr) { ++index_of_first_non_null_; } } } + size_t SpaceUsedInternal() const { + return internal::SpaceUsedInTable(table_, num_buckets_, + num_elements_, sizeof(Node)); + } + private: const_iterator find(const Key& k, TreeIterator* it) const { return FindHelper(k, it).first; } - std::pair FindHelper(const Key& k) const { - return FindHelper(k, NULL); + template + std::pair FindHelper(const K& k) const { + return FindHelper(k, nullptr); } - std::pair FindHelper(const Key& k, + template + std::pair FindHelper(const K& k, TreeIterator* it) const { size_type b = BucketNumber(k); if (TableEntryIsNonEmptyList(b)) { Node* node = static_cast(table_[b]); do { - if (IsMatch(*KeyPtrFromNodePtr(node), k)) { + if (internal::TransparentSupport::Equals(node->kv.first, k)) { return std::make_pair(const_iterator(node, this, b), b); } else { node = node->next; } - } while (node != NULL); + } while (node != nullptr); } else if (TableEntryIsTree(b)) { GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]); b &= ~static_cast(1); Tree* tree = static_cast(table_[b]); - Key* key = const_cast(&k); - typename Tree::iterator tree_it = tree->find(key); + auto tree_it = tree->find(k); if (tree_it != tree->end()) { - if (it != NULL) *it = tree_it; + if (it != nullptr) *it = tree_it; return std::make_pair(const_iterator(tree_it, this, b), b); } } @@ -649,17 +802,17 @@ class Map { // bucket. num_elements_ is not modified. iterator InsertUnique(size_type b, Node* node) { GOOGLE_DCHECK(index_of_first_non_null_ == num_buckets_ || - table_[index_of_first_non_null_] != NULL); + table_[index_of_first_non_null_] != nullptr); // In practice, the code that led to this point may have already // determined whether we are inserting into an empty list, a short list, // or whatever. But it's probably cheap enough to recompute that here; // it's likely that we're inserting into an empty or short list. iterator result; - GOOGLE_DCHECK(find(*KeyPtrFromNodePtr(node)) == end()); + GOOGLE_DCHECK(find(node->kv.first) == end()); if (TableEntryIsEmpty(b)) { result = InsertUniqueInList(b, node); } else if (TableEntryIsNonEmptyList(b)) { - if (GOOGLE_PREDICT_FALSE(TableEntryIsTooLong(b))) { + if (PROTOBUF_PREDICT_FALSE(TableEntryIsTooLong(b))) { TreeConvert(b); result = InsertUniqueInTree(b, node); GOOGLE_DCHECK_EQ(result.bucket_index_, b & ~static_cast(1)); @@ -679,9 +832,30 @@ class Map { return result; } + // Returns whether we should insert after the head of the list. For + // non-optimized builds, we randomly decide whether to insert right at the + // head of the list or just after the head. This helps add a little bit of + // non-determinism to the map ordering. + bool ShouldInsertAfterHead(void* node) { +#ifdef NDEBUG + (void)node; + return false; +#else + // Doing modulo with a prime mixes the bits more. + return (reinterpret_cast(node) ^ seed_) % 13 > 6; +#endif + } + // Helper for InsertUnique. Handles the case where bucket b is a // not-too-long linked list. iterator InsertUniqueInList(size_type b, Node* node) { + if (table_[b] != nullptr && ShouldInsertAfterHead(node)) { + Node* first = static_cast(table_[b]); + node->next = first->next; + first->next = node; + return iterator(node, this, b); + } + node->next = static_cast(table_[b]); table_[b] = static_cast(node); return iterator(node, this, b); @@ -691,12 +865,11 @@ class Map { // Tree. iterator InsertUniqueInTree(size_type b, Node* node) { GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]); - // Maintain the invariant that node->next is NULL for all Nodes in Trees. - node->next = NULL; - return iterator(static_cast(table_[b]) - ->insert(KeyPtrFromNodePtr(node)) - .first, - this, b & ~static_cast(1)); + // Maintain the invariant that node->next is null for all Nodes in Trees. + node->next = nullptr; + return iterator( + static_cast(table_[b])->insert({node->kv.first, node}).first, + this, b & ~static_cast(1)); } // Returns whether it did resize. Currently this is only used when @@ -714,13 +887,13 @@ class Map { // We don't care how many elements are in trees. If a lot are, // we may resize even though there are many empty buckets. In // practice, this seems fine. - if (GOOGLE_PREDICT_FALSE(new_size >= hi_cutoff)) { + if (PROTOBUF_PREDICT_FALSE(new_size >= hi_cutoff)) { if (num_buckets_ <= max_size() / 2) { Resize(num_buckets_ * 2); return true; } - } else if (GOOGLE_PREDICT_FALSE(new_size <= lo_cutoff && - num_buckets_ > kMinTableSize)) { + } else if (PROTOBUF_PREDICT_FALSE(new_size <= lo_cutoff && + num_buckets_ > kMinTableSize)) { size_type lg2_of_size_reduction_factor = 1; // It's possible we want to shrink a lot here... size() could even be 0. // So, estimate how much to shrink by making sure we don't shrink so @@ -742,6 +915,15 @@ class Map { // Resize to the given number of buckets. void Resize(size_t new_num_buckets) { + if (num_buckets_ == internal::kGlobalEmptyTableSize) { + // This is the global empty array. + // Just overwrite with a new one. No need to transfer or free anything. + num_buckets_ = index_of_first_non_null_ = kMinTableSize; + table_ = CreateEmptyTable(num_buckets_); + seed_ = Seed(); + return; + } + GOOGLE_DCHECK_GE(new_num_buckets, kMinTableSize); void** const old_table = table_; const size_type old_table_size = num_buckets_; @@ -750,9 +932,9 @@ class Map { const size_type start = index_of_first_non_null_; index_of_first_non_null_ = num_buckets_; for (size_type i = start; i < old_table_size; i++) { - if (TableEntryIsNonEmptyList(old_table, i)) { + if (internal::TableEntryIsNonEmptyList(old_table, i)) { TransferList(old_table, i); - } else if (TableEntryIsTree(old_table, i)) { + } else if (internal::TableEntryIsTree(old_table, i)) { TransferTree(old_table, i++); } } @@ -763,17 +945,17 @@ class Map { Node* node = static_cast(table[index]); do { Node* next = node->next; - InsertUnique(BucketNumber(*KeyPtrFromNodePtr(node)), node); + InsertUnique(BucketNumber(node->kv.first), node); node = next; - } while (node != NULL); + } while (node != nullptr); } void TransferTree(void* const* table, size_type index) { Tree* tree = static_cast(table[index]); typename Tree::iterator tree_it = tree->begin(); do { - Node* node = NodePtrFromKeyPtr(*tree_it); - InsertUnique(BucketNumber(**tree_it), node); + InsertUnique(BucketNumber(std::cref(tree_it->first).get()), + NodeFromTreeIterator(tree_it)); } while (++tree_it != tree->end()); DestroyTree(tree); } @@ -788,42 +970,23 @@ class Map { } bool TableEntryIsEmpty(size_type b) const { - return TableEntryIsEmpty(table_, b); + return internal::TableEntryIsEmpty(table_, b); } bool TableEntryIsNonEmptyList(size_type b) const { - return TableEntryIsNonEmptyList(table_, b); + return internal::TableEntryIsNonEmptyList(table_, b); } bool TableEntryIsTree(size_type b) const { - return TableEntryIsTree(table_, b); + return internal::TableEntryIsTree(table_, b); } bool TableEntryIsList(size_type b) const { - return TableEntryIsList(table_, b); - } - static bool TableEntryIsEmpty(void* const* table, size_type b) { - return table[b] == NULL; - } - static bool TableEntryIsNonEmptyList(void* const* table, size_type b) { - return table[b] != NULL && table[b] != table[b ^ 1]; - } - static bool TableEntryIsTree(void* const* table, size_type b) { - return !TableEntryIsEmpty(table, b) && - !TableEntryIsNonEmptyList(table, b); - } - static bool TableEntryIsList(void* const* table, size_type b) { - return !TableEntryIsTree(table, b); + return internal::TableEntryIsList(table_, b); } void TreeConvert(size_type b) { GOOGLE_DCHECK(!TableEntryIsTree(b) && !TableEntryIsTree(b ^ 1)); - typename Allocator::template rebind::other tree_allocator(alloc_); - Tree* tree = tree_allocator.allocate(1); - // We want to use the three-arg form of construct, if it exists, but we - // create a temporary and use the two-arg construct that's known to exist. - // It's clunky, but the compiler should be able to generate more-or-less - // the same code. - tree_allocator.construct(tree, - Tree(KeyCompare(), KeyPtrAllocator(alloc_))); - // Now the tree is ready to use. + Tree* tree = + Arena::Create(alloc_.arena(), typename Tree::key_compare(), + typename Tree::allocator_type(alloc_)); size_type count = CopyListToTree(b, tree) + CopyListToTree(b ^ 1, tree); GOOGLE_DCHECK_EQ(count, tree->size()); table_[b] = table_[b ^ 1] = static_cast(tree); @@ -834,11 +997,11 @@ class Map { size_type CopyListToTree(size_type b, Tree* tree) { size_type count = 0; Node* node = static_cast(table_[b]); - while (node != NULL) { - tree->insert(KeyPtrFromNodePtr(node)); + while (node != nullptr) { + tree->insert({node->kv.first, node}); ++count; Node* next = node->next; - node->next = NULL; + node->next = nullptr; node = next; } return count; @@ -853,20 +1016,23 @@ class Map { do { ++count; node = node->next; - } while (node != NULL); + } while (node != nullptr); // Invariant: no linked list ever is more than kMaxLength in length. GOOGLE_DCHECK_LE(count, kMaxLength); return count >= kMaxLength; } - size_type BucketNumber(const Key& k) const { - // We inherit from hasher, so one-arg operator() provides a hash function. - size_type h = (*const_cast(this))(k); - return (h + seed_) & (num_buckets_ - 1); - } + template + size_type BucketNumber(const K& k) const { + // We xor the hash value against the random seed so that we effectively + // have a random hash function. + uint64 h = hash_function()(k) ^ seed_; - bool IsMatch(const Key& k0, const Key& k1) const { - return std::equal_to()(k0, k1); + // We use the multiplication method to determine the bucket number from + // the hash value. The constant kPhi (suggested by Knuth) is roughly + // (sqrt(5) - 1) / 2 * 2^64. + constexpr uint64 kPhi = uint64{0x9e3779b97f4a7c15}; + return ((kPhi * h) >> 32) & (num_buckets_ - 1); } // Return a power of two no less than max(kMinTableSize, n). @@ -880,26 +1046,27 @@ class Map { // Use alloc_ to allocate an array of n objects of type U. template U* Alloc(size_type n) { - typedef typename Allocator::template rebind::other alloc_type; + using alloc_type = typename Allocator::template rebind::other; return alloc_type(alloc_).allocate(n); } // Use alloc_ to deallocate an array of n objects of type U. template void Dealloc(U* t, size_type n) { - typedef typename Allocator::template rebind::other alloc_type; + using alloc_type = typename Allocator::template rebind::other; alloc_type(alloc_).deallocate(t, n); } void DestroyNode(Node* node) { - alloc_.destroy(&node->kv); - Dealloc(node, 1); + if (alloc_.arena() == nullptr) { + delete node; + } } void DestroyTree(Tree* tree) { - typename Allocator::template rebind::other tree_allocator(alloc_); - tree_allocator.destroy(tree); - tree_allocator.deallocate(tree, 1); + if (alloc_.arena() == nullptr) { + delete tree; + } } void** CreateEmptyTable(size_type n) { @@ -912,15 +1079,23 @@ class Map { // Return a randomish value. size_type Seed() const { - size_type s = static_cast(reinterpret_cast(this)); -#if defined(__x86_64__) && defined(__GNUC__) + // We get a little bit of randomness from the address of the map. The + // lower bits are not very random, due to alignment, so we discard them + // and shift the higher bits into their place. + size_type s = reinterpret_cast(this) >> 12; +#if defined(__x86_64__) && defined(__GNUC__) && \ + !defined(GOOGLE_PROTOBUF_NO_RDTSC) uint32 hi, lo; - asm("rdtsc" : "=a" (lo), "=d" (hi)); + asm volatile("rdtsc" : "=a"(lo), "=d"(hi)); s += ((static_cast(hi) << 32) | lo); #endif return s; } + friend class Arena; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + size_type num_elements_; size_type num_buckets_; size_type seed_; @@ -930,24 +1105,26 @@ class Map { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(InnerMap); }; // end of class InnerMap + template + using key_arg = typename internal::TransparentSupport< + key_type>::template key_arg; + public: // Iterators class const_iterator { - typedef typename InnerMap::const_iterator InnerIt; + using InnerIt = typename InnerMap::const_iterator; public: - typedef std::forward_iterator_tag iterator_category; - typedef typename Map::value_type value_type; - typedef ptrdiff_t difference_type; - typedef const value_type* pointer; - typedef const value_type& reference; + using iterator_category = std::forward_iterator_tag; + using value_type = typename Map::value_type; + using difference_type = ptrdiff_t; + using pointer = const value_type*; + using reference = const value_type&; const_iterator() {} explicit const_iterator(const InnerIt& it) : it_(it) {} - const_reference operator*() const { - return *it_->value(); - } + const_reference operator*() const { return *it_; } const_pointer operator->() const { return &(operator*()); } const_iterator& operator++() { @@ -968,19 +1145,19 @@ class Map { }; class iterator { - typedef typename InnerMap::iterator InnerIt; + using InnerIt = typename InnerMap::iterator; public: - typedef std::forward_iterator_tag iterator_category; - typedef typename Map::value_type value_type; - typedef ptrdiff_t difference_type; - typedef value_type* pointer; - typedef value_type& reference; + using iterator_category = std::forward_iterator_tag; + using value_type = typename Map::value_type; + using difference_type = ptrdiff_t; + using pointer = value_type*; + using reference = value_type&; iterator() {} explicit iterator(const InnerIt& it) : it_(it) {} - reference operator*() const { return *it_->value(); } + reference operator*() const { return *it_; } pointer operator->() const { return &(operator*()); } iterator& operator++() { @@ -990,7 +1167,7 @@ class Map { iterator operator++(int) { return iterator(it_++); } // Allow implicit conversion to const_iterator. - operator const_iterator() const { + operator const_iterator() const { // NOLINT(runtime/explicit) return const_iterator(typename InnerMap::const_iterator(it_)); } @@ -1007,55 +1184,67 @@ class Map { InnerIt it_; }; - iterator begin() { return iterator(elements_->begin()); } - iterator end() { return iterator(elements_->end()); } - const_iterator begin() const { - return const_iterator(iterator(elements_->begin())); - } - const_iterator end() const { - return const_iterator(iterator(elements_->end())); - } + iterator begin() { return iterator(elements_.begin()); } + iterator end() { return iterator(elements_.end()); } + const_iterator begin() const { return const_iterator(elements_.begin()); } + const_iterator end() const { return const_iterator(elements_.end()); } const_iterator cbegin() const { return begin(); } const_iterator cend() const { return end(); } // Capacity - size_type size() const { return elements_->size(); } + size_type size() const { return elements_.size(); } bool empty() const { return size() == 0; } // Element access - T& operator[](const key_type& key) { - value_type** value = &(*elements_)[key]; - if (*value == NULL) { - *value = CreateValueTypeInternal(key); - internal::MapValueInitializer::value, - T>::Initialize((*value)->second, - default_enum_value_); - } - return (*value)->second; + template + T& operator[](const key_arg& key) { + return elements_[key].second; + } + template < + typename K = key_type, + // Disable for integral types to reduce code bloat. + typename = typename std::enable_if::value>::type> + T& operator[](key_arg&& key) { + return elements_[std::forward(key)].second; } - const T& at(const key_type& key) const { + + template + const T& at(const key_arg& key) const { const_iterator it = find(key); - GOOGLE_CHECK(it != end()); + GOOGLE_CHECK(it != end()) << "key not found: " << static_cast(key); return it->second; } - T& at(const key_type& key) { + + template + T& at(const key_arg& key) { iterator it = find(key); - GOOGLE_CHECK(it != end()); + GOOGLE_CHECK(it != end()) << "key not found: " << static_cast(key); return it->second; } // Lookup - size_type count(const key_type& key) const { - const_iterator it = find(key); - GOOGLE_DCHECK(it == end() || key == it->first); - return it == end() ? 0 : 1; + template + size_type count(const key_arg& key) const { + return find(key) == end() ? 0 : 1; + } + + template + const_iterator find(const key_arg& key) const { + return const_iterator(elements_.find(key)); } - const_iterator find(const key_type& key) const { - return const_iterator(iterator(elements_->find(key))); + template + iterator find(const key_arg& key) { + return iterator(elements_.find(key)); } - iterator find(const key_type& key) { return iterator(elements_->find(key)); } + + template + bool contains(const key_arg& key) const { + return find(key) != end(); + } + + template std::pair equal_range( - const key_type& key) const { + const key_arg& key) const { const_iterator it = find(key); if (it == end()) { return std::pair(it, it); @@ -1064,7 +1253,9 @@ class Map { return std::pair(begin, it); } } - std::pair equal_range(const key_type& key) { + + template + std::pair equal_range(const key_arg& key) { iterator it = find(key); if (it == end()) { return std::pair(it, it); @@ -1077,9 +1268,9 @@ class Map { // insert std::pair insert(const value_type& value) { std::pair p = - elements_->insert(value.first); + elements_.insert(value.first); if (p.second) { - p.first->value() = CreateValueTypeInternal(value); + p.first->second = value.second; } return std::pair(iterator(p.first), p.second); } @@ -1092,9 +1283,13 @@ class Map { } } } + void insert(std::initializer_list values) { + insert(values.begin(), values.end()); + } // Erase and clear - size_type erase(const key_type& key) { + template + size_type erase(const key_arg& key) { iterator it = find(key); if (it == end()) { return 0; @@ -1104,9 +1299,8 @@ class Map { } } iterator erase(iterator pos) { - if (arena_ == NULL) delete pos.operator->(); iterator i = pos++; - elements_->erase(i.it_); + elements_.erase(i.it_); return pos; } void erase(iterator first, iterator last) { @@ -1114,7 +1308,7 @@ class Map { first = erase(first); } } - void clear() { erase(begin(), end()); } + void clear() { elements_.clear(); } // Assign Map& operator=(const Map& other) { @@ -1126,9 +1320,8 @@ class Map { } void swap(Map& other) { - if (arena_ == other.arena_) { - std::swap(default_enum_value_, other.default_enum_value_); - std::swap(elements_, other.elements_); + if (arena() == other.arena()) { + elements_.Swap(&other.elements_); } else { // TODO(zuguang): optimize this. The temporary copy can be allocated // in the same arena as the other message, and the "other = copy" can @@ -1141,58 +1334,29 @@ class Map { // Access to hasher. Currently this returns a copy, but it may // be modified to return a const reference in the future. - hasher hash_function() const { - return elements_->hash_function(); - } + hasher hash_function() const { return elements_.hash_function(); } - private: - // Set default enum value only for proto2 map field whose value is enum type. - void SetDefaultEnumValue(int default_enum_value) { - default_enum_value_ = default_enum_value; + size_t SpaceUsedExcludingSelfLong() const { + if (empty()) return 0; + return elements_.SpaceUsedInternal() + internal::SpaceUsedInValues(this); } - value_type* CreateValueTypeInternal(const Key& key) { - if (arena_ == NULL) { - return new value_type(key); - } else { - value_type* value = reinterpret_cast( - Arena::CreateArray(arena_, sizeof(value_type))); - Arena::CreateInArenaStorage(const_cast(&value->first), arena_); - Arena::CreateInArenaStorage(&value->second, arena_); - const_cast(value->first) = key; - return value; - } - } - - value_type* CreateValueTypeInternal(const value_type& value) { - if (arena_ == NULL) { - return new value_type(value); - } else { - value_type* p = reinterpret_cast( - Arena::CreateArray(arena_, sizeof(value_type))); - Arena::CreateInArenaStorage(const_cast(&p->first), arena_); - Arena::CreateInArenaStorage(&p->second, arena_); - const_cast(p->first) = value.first; - p->second = value.second; - return p; - } - } - - Arena* arena_; - int default_enum_value_; - InnerMap* elements_; + private: + Arena* arena() const { return elements_.arena(); } + InnerMap elements_; - friend class ::google::protobuf::Arena; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; + friend class Arena; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; template + internal::WireFormatLite::FieldType value_wire_type> friend class internal::MapFieldLite; }; } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_MAP_H__ diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h index afe809b28ac4a..9e35795f9b531 100644 --- a/src/google/protobuf/map_entry.h +++ b/src/google/protobuf/map_entry.h @@ -34,10 +34,16 @@ #include #include #include -#include +#include #include #include -#include +#include + +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif namespace google { namespace protobuf { @@ -45,11 +51,13 @@ class Arena; namespace internal { template + WireFormatLite::FieldType kValueFieldType> class MapField; } -} +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace internal { @@ -78,102 +86,75 @@ namespace internal { // // The in-memory types of primitive types can be inferred from its proto type, // while we need to explicitly specify the cpp type if proto type is -// TYPE_MESSAGE to infer the in-memory type. Moreover, default_enum_value is -// used to initialize enum field in proto2. +// TYPE_MESSAGE to infer the in-memory type. template -class MapEntry - : public MapEntryImpl { + WireFormatLite::FieldType kValueFieldType> +class MapEntry : public MapEntryImpl { public: - // Create default MapEntry instance for given descriptor. Descriptor has to be - // given when creating default MapEntry instance because different map field - // may have the same type and MapEntry class. The given descriptor is needed - // to distinguish instances of the same MapEntry class. - static const Reflection* CreateReflection(const Descriptor* descriptor, - const Derived* entry) { - ReflectionSchema schema = { - entry, - offsets_, - has_bits_, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _internal_metadata_), - -1, - -1, - sizeof(MapEntry), - -1, - }; - const Reflection* reflection = new GeneratedMessageReflection( - descriptor, schema, DescriptorPool::generated_pool(), - MessageFactory::generated_factory()); - return reflection; - } - - MapEntry() : _internal_metadata_(NULL) {} + constexpr MapEntry() : _internal_metadata_() {} explicit MapEntry(Arena* arena) : MapEntryImpl(arena), + kValueFieldType>(arena), _internal_metadata_(arena) {} + ~MapEntry() { + Message::_internal_metadata_.Delete(); + _internal_metadata_.Delete(); + } typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; - private: - static uint32 offsets_[2]; - static uint32 has_bits_[2]; - InternalMetadataWithArena _internal_metadata_; + typedef typename MapEntryImpl::KeyTypeHandler KeyTypeHandler; + typedef + typename MapEntryImpl::ValueTypeHandler ValueTypeHandler; + size_t SpaceUsedLong() const override { + size_t size = sizeof(Derived); + size += KeyTypeHandler::SpaceUsedInMapEntryLong(this->key_); + size += ValueTypeHandler::SpaceUsedInMapEntryLong(this->value_); + return size; + } + + InternalMetadata _internal_metadata_; - friend class ::google::protobuf::Arena; + private: + friend class ::PROTOBUF_NAMESPACE_ID::Arena; template + WireFormatLite::FieldType k_wire_type, WireFormatLite::FieldType> friend class internal::MapField; - friend class internal::GeneratedMessageReflection; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry); }; -template -uint32 MapEntry::offsets_[2] = { - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, key_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, value_), -}; - -template -uint32 MapEntry::has_bits_[2] = {0, 1}; - // Specialization for the full runtime template -struct MapEntryHelper > - : MapEntryHelper > { + WireFormatLite::FieldType kValueFieldType> +struct MapEntryHelper< + MapEntry > + : MapEntryHelper< + MapEntryLite > { explicit MapEntryHelper(const MapPair& map_pair) - : MapEntryHelper >(map_pair) {} + : MapEntryHelper< + MapEntryLite >( + map_pair) {} }; template -struct DeconstructMapEntry > { + WireFormatLite::FieldType key, WireFormatLite::FieldType value> +struct DeconstructMapEntry > { typedef K Key; typedef V Value; - static const WireFormatLite::FieldType kKeyFieldType = key; - static const WireFormatLite::FieldType kValueFieldType = value; - static const int default_enum_value = default_enum; + static constexpr WireFormatLite::FieldType kKeyFieldType = key; + static constexpr WireFormatLite::FieldType kValueFieldType = value; }; } // namespace internal } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_MAP_ENTRY_H__ diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h index 0bccf4d2fd911..1caf59dfedc52 100644 --- a/src/google/protobuf/map_entry_lite.h +++ b/src/google/protobuf/map_entry_lite.h @@ -32,26 +32,40 @@ #define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ #include +#include +#include +#include +#include #include +#include +#include #include #include -#include +#include +#include + +#include +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif namespace google { namespace protobuf { namespace internal { template + WireFormatLite::FieldType kValueFieldType> class MapEntry; template + WireFormatLite::FieldType kValueFieldType> class MapFieldLite; } // namespace internal } // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace internal { @@ -79,11 +93,45 @@ struct MoveHelper { // messages template struct MoveHelper { // strings and similar static void Move(T* src, T* dest) { -#if __cplusplus >= 201103L *dest = std::move(*src); -#else - dest->swap(*src); -#endif + } +}; + +// Functions for operating on a map entry. Does not contain any representation +// (this class is not intended to be instantiated). +template +struct MapEntryFuncs { + typedef MapTypeHandler KeyTypeHandler; + typedef MapTypeHandler ValueTypeHandler; + static const int kKeyFieldNumber = 1; + static const int kValueFieldNumber = 2; + + static uint8* InternalSerialize(int field_number, const Key& key, + const Value& value, uint8* ptr, + io::EpsCopyOutputStream* stream) { + ptr = stream->EnsureSpace(ptr); + ptr = WireFormatLite::WriteTagToArray( + field_number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, ptr); + ptr = io::CodedOutputStream::WriteVarint32ToArray(GetCachedSize(key, value), + ptr); + + ptr = KeyTypeHandler::Write(kKeyFieldNumber, key, ptr, stream); + return ValueTypeHandler::Write(kValueFieldNumber, value, ptr, stream); + } + + static size_t ByteSizeLong(const Key& key, const Value& value) { + // Tags for key and value will both be one byte (field numbers 1 and 2). + size_t inner_length = + 2 + KeyTypeHandler::ByteSize(key) + ValueTypeHandler::ByteSize(value); + return inner_length + io::CodedOutputStream::VarintSize32( + static_cast(inner_length)); + } + + static int GetCachedSize(const Key& key, const Value& value) { + // Tags for key and value will both be one byte (field numbers 1 and 2). + return 2 + KeyTypeHandler::GetCachedSize(key) + + ValueTypeHandler::GetCachedSize(value); } }; @@ -92,8 +140,11 @@ struct MoveHelper { // strings and similar // the eventual code to the template code. template + WireFormatLite::FieldType kValueFieldType> class MapEntryImpl : public Base { + public: + typedef MapEntryFuncs Funcs; + protected: // Provide utilities to parse/serialize key/value. Provide utilities to // manipulate internal stored type. @@ -108,16 +159,16 @@ class MapEntryImpl : public Base { // Enum type cannot be used for MapTypeHandler::Read. Define a type // which will replace Enum with int. typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType; - typedef typename ValueTypeHandler::MapEntryAccessorType - ValueMapEntryAccessorType; + typedef + typename ValueTypeHandler::MapEntryAccessorType ValueMapEntryAccessorType; // Constants for field number. static const int kKeyFieldNumber = 1; static const int kValueFieldNumber = 2; // Constants for field tag. - static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( - kKeyFieldNumber, KeyTypeHandler::kWireType); + static const uint8 kKeyTag = + GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kKeyFieldNumber, KeyTypeHandler::kWireType); static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( kValueFieldNumber, ValueTypeHandler::kWireType); static const size_t kTagSize = 1; @@ -130,28 +181,22 @@ class MapEntryImpl : public Base { typedef Value EntryValueType; static const WireFormatLite::FieldType kEntryKeyFieldType = kKeyFieldType; static const WireFormatLite::FieldType kEntryValueFieldType = kValueFieldType; - static const int kEntryDefaultEnumValue = default_enum_value; - MapEntryImpl() : default_instance_(NULL), arena_(NULL) { - KeyTypeHandler::Initialize(&key_, NULL); - ValueTypeHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value, - NULL); - _has_bits_[0] = 0; - } + constexpr MapEntryImpl() + : key_(KeyTypeHandler::Constinit()), + value_(ValueTypeHandler::Constinit()), + _has_bits_{} {} - explicit MapEntryImpl(Arena* arena) : default_instance_(NULL), arena_(arena) { - KeyTypeHandler::Initialize(&key_, arena); - ValueTypeHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value, - arena); - _has_bits_[0] = 0; - } + explicit MapEntryImpl(Arena* arena) + : Base(arena), + key_(KeyTypeHandler::Constinit()), + value_(ValueTypeHandler::Constinit()), + _has_bits_{} {} ~MapEntryImpl() { - if (this != default_instance_) { - if (GetArenaNoVirtual() != NULL) return; - KeyTypeHandler::DeleteNoArena(key_); - ValueTypeHandler::DeleteNoArena(value_); - } + if (Base::GetArena() != NULL) return; + KeyTypeHandler::DeleteNoArena(key_); + ValueTypeHandler::DeleteNoArena(value_); } // accessors ====================================================== @@ -160,193 +205,136 @@ class MapEntryImpl : public Base { return KeyTypeHandler::GetExternalReference(key_); } virtual inline const ValueMapEntryAccessorType& value() const { - GOOGLE_CHECK(default_instance_ != NULL); - return ValueTypeHandler::DefaultIfNotInitialized(value_, - default_instance_->value_); + return ValueTypeHandler::DefaultIfNotInitialized(value_); } inline KeyMapEntryAccessorType* mutable_key() { set_has_key(); - return KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual()); + return KeyTypeHandler::EnsureMutable(&key_, Base::GetArena()); } inline ValueMapEntryAccessorType* mutable_value() { set_has_value(); - return ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual()); + return ValueTypeHandler::EnsureMutable(&value_, Base::GetArena()); } // implements MessageLite ========================================= // MapEntryImpl is for implementation only and this function isn't called // anywhere. Just provide a fake implementation here for MessageLite. - string GetTypeName() const { return ""; } + std::string GetTypeName() const override { return ""; } - void CheckTypeAndMergeFrom(const MessageLite& other) { - MergeFromInternal(*::google::protobuf::down_cast(&other)); + void CheckTypeAndMergeFrom(const MessageLite& other) override { + MergeFromInternal(*::google::protobuf::internal::DownCast(&other)); } - bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) { - uint32 tag; - - for (;;) { - // 1) corrupted data: return false; - // 2) unknown field: skip without putting into unknown field set; - // 3) unknown enum value: keep it in parsing. In proto2, caller should - // check the value and put this entry into containing message's unknown - // field set if the value is an unknown enum. In proto3, caller doesn't - // need to care whether the value is unknown enum; - // 4) missing key/value: missed key/value will have default value. caller - // should take this entry as if key/value is set to default value. - tag = input->ReadTagNoLastTag(); - switch (tag) { - case kKeyTag: - if (!KeyTypeHandler::Read(input, mutable_key())) { - return false; - } - set_has_key(); - if (!input->ExpectTag(kValueTag)) break; - GOOGLE_FALLTHROUGH_INTENDED; - - case kValueTag: - if (!ValueTypeHandler::Read(input, mutable_value())) { - return false; - } - set_has_value(); - if (input->ExpectAtEnd()) return true; - break; - - default: - if (tag == 0 || - WireFormatLite::GetTagWireType(tag) == - WireFormatLite::WIRETYPE_END_GROUP) { - return true; - } - if (!WireFormatLite::SkipField(input, tag)) return false; - break; + const char* _InternalParse(const char* ptr, ParseContext* ctx) final { + while (!ctx->Done(&ptr)) { + uint32 tag; + ptr = ReadTag(ptr, &tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + if (tag == kKeyTag) { + set_has_key(); + KeyMapEntryAccessorType* key = mutable_key(); + ptr = KeyTypeHandler::Read(ptr, ctx, key); + if (!Derived::ValidateKey(key)) return nullptr; + } else if (tag == kValueTag) { + set_has_value(); + ValueMapEntryAccessorType* value = mutable_value(); + ptr = ValueTypeHandler::Read(ptr, ctx, value); + if (!Derived::ValidateValue(value)) return nullptr; + } else { + if (tag == 0 || WireFormatLite::GetTagWireType(tag) == + WireFormatLite::WIRETYPE_END_GROUP) { + ctx->SetLastTag(tag); + return ptr; + } + ptr = UnknownFieldParse(tag, static_cast(nullptr), ptr, + ctx); } + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); } + return ptr; } - size_t ByteSizeLong() const { + size_t ByteSizeLong() const override { size_t size = 0; - size += has_key() ? - kTagSize + static_cast(KeyTypeHandler::ByteSize(key())) : 0; - size += has_value() ? - kTagSize + static_cast(ValueTypeHandler::ByteSize(value())) : 0; + size += kTagSize + static_cast(KeyTypeHandler::ByteSize(key())); + size += kTagSize + static_cast(ValueTypeHandler::ByteSize(value())); return size; } - void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const { - KeyTypeHandler::Write(kKeyFieldNumber, key(), output); - ValueTypeHandler::Write(kValueFieldNumber, value(), output); - } - - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(bool deterministic, - ::google::protobuf::uint8* output) const { - output = KeyTypeHandler::InternalWriteToArray(kKeyFieldNumber, key(), - deterministic, output); - output = ValueTypeHandler::InternalWriteToArray(kValueFieldNumber, value(), - deterministic, output); - return output; + ::google::protobuf::uint8* _InternalSerialize(::google::protobuf::uint8* ptr, + io::EpsCopyOutputStream* stream) const override { + ptr = KeyTypeHandler::Write(kKeyFieldNumber, key(), ptr, stream); + return ValueTypeHandler::Write(kValueFieldNumber, value(), ptr, stream); } // Don't override SerializeWithCachedSizesToArray. Use MessageLite's. - int GetCachedSize() const { + int GetCachedSize() const override { int size = 0; - size += has_key() - ? static_cast(kTagSize) + KeyTypeHandler::GetCachedSize(key()) - : 0; - size += has_value() - ? static_cast(kTagSize) + ValueTypeHandler::GetCachedSize(value()) - : 0; + size += has_key() ? static_cast(kTagSize) + + KeyTypeHandler::GetCachedSize(key()) + : 0; + size += has_value() ? static_cast(kTagSize) + + ValueTypeHandler::GetCachedSize(value()) + : 0; return size; } - bool IsInitialized() const { return ValueTypeHandler::IsInitialized(value_); } + bool IsInitialized() const override { + return ValueTypeHandler::IsInitialized(value_); + } - Base* New() const { + Base* New() const override { Derived* entry = new Derived; - entry->default_instance_ = default_instance_; return entry; } - Base* New(Arena* arena) const { + Base* New(Arena* arena) const override { Derived* entry = Arena::CreateMessage(arena); - entry->default_instance_ = default_instance_; return entry; } - size_t SpaceUsedLong() const { - size_t size = sizeof(Derived); - size += KeyTypeHandler::SpaceUsedInMapEntryLong(key_); - size += ValueTypeHandler::SpaceUsedInMapEntryLong(value_); - return size; - } - protected: // We can't declare this function directly here as it would hide the other // overload (const Message&). void MergeFromInternal(const MapEntryImpl& from) { if (from._has_bits_[0]) { if (from.has_key()) { - KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual()); - KeyTypeHandler::Merge(from.key(), &key_, GetArenaNoVirtual()); + KeyTypeHandler::EnsureMutable(&key_, Base::GetArena()); + KeyTypeHandler::Merge(from.key(), &key_, Base::GetArena()); set_has_key(); } if (from.has_value()) { - ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual()); - ValueTypeHandler::Merge(from.value(), &value_, GetArenaNoVirtual()); + ValueTypeHandler::EnsureMutable(&value_, Base::GetArena()); + ValueTypeHandler::Merge(from.value(), &value_, Base::GetArena()); set_has_value(); } } } public: - void Clear() { - KeyTypeHandler::Clear(&key_, GetArenaNoVirtual()); - ValueTypeHandler::ClearMaybeByDefaultEnum( - &value_, GetArenaNoVirtual(), default_enum_value); + void Clear() override { + KeyTypeHandler::Clear(&key_, Base::GetArena()); + ValueTypeHandler::Clear(&value_, Base::GetArena()); clear_has_key(); clear_has_value(); } - void set_default_instance(MapEntryImpl* default_instance) { - default_instance_ = default_instance; - } - - void InitAsDefaultInstance() { - KeyTypeHandler::AssignDefaultValue(&key_); - ValueTypeHandler::AssignDefaultValue(&value_); - } - - Arena* GetArena() const { - return GetArenaNoVirtual(); - } - - // Create a MapEntryImpl for given key and value from google::protobuf::Map in - // serialization. This function is only called when value is enum. Enum is - // treated differently because its type in MapEntry is int and its type in - // google::protobuf::Map is enum. We cannot create a reference to int from an enum. - static Derived* EnumWrap(const Key& key, const Value value, Arena* arena) { - return Arena::CreateMessage(arena, key, value); - } - - // Like above, but for all the other types. This avoids value copy to create - // MapEntryImpl from google::protobuf::Map in serialization. - static Derived* Wrap(const Key& key, const Value& value, Arena* arena) { - return Arena::CreateMessage(arena, key, value); - } - // Parsing using MergePartialFromCodedStream, above, is not as // efficient as it could be. This helper class provides a speedier way. template class Parser { public: explicit Parser(MapField* mf) : mf_(mf), map_(mf->MutableMap()) {} + ~Parser() { + if (entry_ != nullptr && entry_->GetArena() == nullptr) delete entry_; + } // This does what the typical MergePartialFromCodedStream() is expected to // do, with the additional side-effect that if successful (i.e., if true is // going to be its return value) it inserts the key-value pair into map_. - bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) { + bool MergePartialFromCodedStream(io::CodedInputStream* input) { // Look for the expected thing: a key and then a value. If it fails, // invoke the enclosing class's MergePartialFromCodedStream, or return // false if that would be pointless. @@ -359,11 +347,11 @@ class MapEntryImpl : public Base { int size; input->GetDirectBufferPointerInline(&data, &size); // We could use memcmp here, but we don't bother. The tag is one byte. - GOOGLE_COMPILE_ASSERT(kTagSize == 1, tag_size_error); + static_assert(kTagSize == 1, "tag size must be 1"); if (size > 0 && *reinterpret_cast(data) == kValueTag) { - typename Map::size_type size = map_->size(); + typename Map::size_type map_size = map_->size(); value_ptr_ = &(*map_)[key_]; - if (GOOGLE_PREDICT_TRUE(size != map_->size())) { + if (PROTOBUF_PREDICT_TRUE(map_size != map_->size())) { // We created a new key-value pair. Fill in the value. typedef typename MapIf::type T; @@ -381,64 +369,118 @@ class MapEntryImpl : public Base { key_ = Key(); } - entry_.reset(mf_->NewEntry()); + NewEntry(); *entry_->mutable_key() = key_; const bool result = entry_->MergePartialFromCodedStream(input); if (result) UseKeyAndValueFromEntry(); - if (entry_->GetArena() != NULL) entry_.release(); return result; } + const char* _InternalParse(const char* ptr, ParseContext* ctx) { + if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kKeyTag)) { + ptr = KeyTypeHandler::Read(ptr + 1, ctx, &key_); + if (PROTOBUF_PREDICT_FALSE(!ptr || !Derived::ValidateKey(&key_))) { + return nullptr; + } + if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kValueTag)) { + typename Map::size_type map_size = map_->size(); + value_ptr_ = &(*map_)[key_]; + if (PROTOBUF_PREDICT_TRUE(map_size != map_->size())) { + using T = + typename MapIf::type; + ptr = ValueTypeHandler::Read(ptr + 1, ctx, + reinterpret_cast(value_ptr_)); + if (PROTOBUF_PREDICT_FALSE(!ptr || + !Derived::ValidateValue(value_ptr_))) { + map_->erase(key_); // Failure! Undo insertion. + return nullptr; + } + if (PROTOBUF_PREDICT_TRUE(ctx->Done(&ptr))) return ptr; + if (!ptr) return nullptr; + NewEntry(); + ValueMover::Move(value_ptr_, entry_->mutable_value()); + map_->erase(key_); + goto move_key; + } + } else { + if (!ptr) return nullptr; + } + NewEntry(); + move_key: + KeyMover::Move(&key_, entry_->mutable_key()); + } else { + if (!ptr) return nullptr; + NewEntry(); + } + ptr = entry_->_InternalParse(ptr, ctx); + if (ptr) UseKeyAndValueFromEntry(); + return ptr; + } + + template + const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx, + bool (*is_valid)(int), uint32 field_num, + InternalMetadata* metadata) { + auto entry = NewEntry(); + ptr = entry->_InternalParse(ptr, ctx); + if (!ptr) return nullptr; + if (is_valid(entry->value())) { + UseKeyAndValueFromEntry(); + } else { + WriteLengthDelimited(field_num, entry->SerializeAsString(), + metadata->mutable_unknown_fields()); + } + return ptr; + } + + MapEntryImpl* NewEntry() { return entry_ = mf_->NewEntry(); } + const Key& key() const { return key_; } const Value& value() const { return *value_ptr_; } + const Key& entry_key() const { return entry_->key(); } + const Value& entry_value() const { return entry_->value(); } + private: - void UseKeyAndValueFromEntry() GOOGLE_ATTRIBUTE_COLD { + void UseKeyAndValueFromEntry() { // Update key_ in case we need it later (because key() is called). // This is potentially inefficient, especially if the key is // expensive to copy (e.g., a long string), but this is a cold // path, so it's not a big deal. key_ = entry_->key(); value_ptr_ = &(*map_)[key_]; - MoveHelper::Move(entry_->mutable_value(), value_ptr_); + ValueMover::Move(entry_->mutable_value(), value_ptr_); } // After reading a key and value successfully, and inserting that data // into map_, we are not at the end of the input. This is unusual, but // allowed by the spec. - bool ReadBeyondKeyValuePair(::google::protobuf::io::CodedInputStream* input) - GOOGLE_ATTRIBUTE_COLD { - typedef MoveHelper KeyMover; - typedef MoveHelper ValueMover; - entry_.reset(mf_->NewEntry()); + bool ReadBeyondKeyValuePair(io::CodedInputStream* input) PROTOBUF_COLD { + NewEntry(); ValueMover::Move(value_ptr_, entry_->mutable_value()); map_->erase(key_); KeyMover::Move(&key_, entry_->mutable_key()); const bool result = entry_->MergePartialFromCodedStream(input); if (result) UseKeyAndValueFromEntry(); - if (entry_->GetArena() != NULL) entry_.release(); return result; } + typedef MoveHelper + KeyMover; + typedef MoveHelper + ValueMover; + MapField* const mf_; Map* const map_; Key key_; Value* value_ptr_; - // On the fast path entry_ is not used. And, when entry_ is used, it's set - // to mf_->NewEntry(), so in the arena case we must call entry_.release. - google::protobuf::scoped_ptr entry_; + MapEntryImpl* entry_ = nullptr; }; protected: @@ -449,111 +491,42 @@ class MapEntryImpl : public Base { bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; } void clear_has_value() { _has_bits_[0] &= ~0x00000002u; } - private: - // Serializing a generated message containing map field involves serializing - // key-value pairs from google::protobuf::Map. The wire format of each key-value pair - // after serialization should be the same as that of a MapEntry message - // containing the same key and value inside it. However, google::protobuf::Map doesn't - // store key and value as MapEntry message, which disables us to use existing - // code to serialize message. In order to use existing code to serialize - // message, we need to construct a MapEntry from key-value pair. But it - // involves copy of key and value to construct a MapEntry. In order to avoid - // this copy in constructing a MapEntry, we need the following class which - // only takes references of given key and value. - class MapEntryWrapper : public Derived { - typedef Derived BaseClass; - typedef typename BaseClass::KeyMapEntryAccessorType KeyMapEntryAccessorType; - typedef - typename BaseClass::ValueMapEntryAccessorType ValueMapEntryAccessorType; - - public: - MapEntryWrapper(Arena* arena, const Key& key, const Value& value) - : Derived(arena), key_(key), value_(value) { - BaseClass::set_has_key(); - BaseClass::set_has_value(); - } - inline const KeyMapEntryAccessorType& key() const { return key_; } - inline const ValueMapEntryAccessorType& value() const { return value_; } - - private: - const Key& key_; - const Value& value_; - - friend class ::google::protobuf::Arena; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; - }; - - // Like above, but for enum value only, which stores value instead of - // reference of value field inside. This is needed because the type of value - // field in constructor is an enum, while we need to store it as an int. If we - // initialize a reference to int with a reference to enum, compiler will - // generate a temporary int from enum and initialize the reference to int with - // the temporary. - class MapEnumEntryWrapper : public Derived { - typedef Derived BaseClass; - typedef typename BaseClass::KeyMapEntryAccessorType KeyMapEntryAccessorType; - typedef - typename BaseClass::ValueMapEntryAccessorType ValueMapEntryAccessorType; - - public: - MapEnumEntryWrapper(Arena* arena, const Key& key, const Value& value) - : Derived(arena), key_(key), value_(value) { - BaseClass::set_has_key(); - BaseClass::set_has_value(); - } - inline const KeyMapEntryAccessorType& key() const { return key_; } - inline const ValueMapEntryAccessorType& value() const { return value_; } - - private: - const KeyMapEntryAccessorType& key_; - const ValueMapEntryAccessorType value_; - - friend class google::protobuf::Arena; - typedef void DestructorSkippable_; - }; - - inline Arena* GetArenaNoVirtual() const { - return arena_; - } - - MapEntryImpl* default_instance_; + public: + inline Arena* GetArena() const { return Base::GetArena(); } + public: // Needed for constructing tables KeyOnMemory key_; ValueOnMemory value_; - Arena* arena_; uint32 _has_bits_[1]; - friend class ::google::protobuf::Arena; + private: + friend class ::PROTOBUF_NAMESPACE_ID::Arena; typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; template + WireFormatLite::FieldType> friend class internal::MapEntry; template + WireFormatLite::FieldType> friend class internal::MapFieldLite; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryImpl); }; -template -class MapEntryLite - : public MapEntryImpl, - MessageLite, Key, Value, kKeyFieldType, - kValueFieldType, default_enum_value> { +template +class MapEntryLite : public MapEntryImpl { public: - typedef MapEntryImpl + typedef MapEntryImpl SuperType; - MapEntryLite() {} + constexpr MapEntryLite() {} explicit MapEntryLite(Arena* arena) : SuperType(arena) {} - void MergeFrom(const MapEntryLite& other) { - MergeFromInternal(other); - } + ~MapEntryLite() { MessageLite::_internal_metadata_.Delete(); } + void MergeFrom(const MapEntryLite& other) { MergeFromInternal(other); } + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite); }; @@ -563,14 +536,13 @@ class MapEntryLite template struct DeconstructMapEntry; -template -struct DeconstructMapEntry > { +template +struct DeconstructMapEntry > { typedef K Key; typedef V Value; static const WireFormatLite::FieldType kKeyFieldType = key; static const WireFormatLite::FieldType kValueFieldType = value; - static const int default_enum_value = default_enum; }; // Helpers for deterministic serialization ============================= @@ -579,7 +551,8 @@ struct DeconstructMapEntry > { // type is relatively small and easy to copy then copying Keys into an // array of SortItems can be beneficial. Then all the data the sorting // algorithm needs to touch is in that one array. -template struct SortItem { +template +struct SortItem { SortItem() {} explicit SortItem(PtrToKeyValuePair p) : first(p->first), second(p) {} @@ -587,16 +560,14 @@ template struct SortItem { PtrToKeyValuePair second; }; -template struct CompareByFirstField { - bool operator()(const T& a, const T& b) const { - return a.first < b.first; - } +template +struct CompareByFirstField { + bool operator()(const T& a, const T& b) const { return a.first < b.first; } }; -template struct CompareByDerefFirst { - bool operator()(const T& a, const T& b) const { - return a->first < b->first; - } +template +struct CompareByDerefFirst { + bool operator()(const T& a, const T& b) const { return a->first < b->first; } }; // Helper for table driven serialization @@ -611,17 +582,21 @@ struct FromHelper { template <> struct FromHelper { - static ArenaStringPtr From(const string& x) { + static ArenaStringPtr From(const std::string& x) { ArenaStringPtr res; - res.UnsafeArenaSetAllocated(NULL, const_cast(&x), NULL); + TaggedPtr ptr; + ptr.Set(const_cast(&x)); + res.UnsafeSetTaggedPointer(ptr); return res; } }; template <> struct FromHelper { - static ArenaStringPtr From(const string& x) { + static ArenaStringPtr From(const std::string& x) { ArenaStringPtr res; - res.UnsafeArenaSetAllocated(NULL, const_cast(&x), NULL); + TaggedPtr ptr; + ptr.Set(const_cast(&x)); + res.UnsafeSetTaggedPointer(ptr); return res; } }; @@ -636,10 +611,11 @@ struct FromHelper { template struct MapEntryHelper; -template -struct MapEntryHelper > { +template +struct MapEntryHelper< + MapEntryLite > { // Provide utilities to parse/serialize key/value. Provide utilities to // manipulate internal stored type. typedef MapTypeHandler KeyTypeHandler; @@ -657,7 +633,7 @@ struct MapEntryHelper::From(map_pair.first)), value_(FromHelper::From(map_pair.second)) {} - // Purposely not folowing the style guide naming. These are the names + // Purposely not following the style guide naming. These are the names // the proto compiler would generate given the map entry descriptor. // The proto compiler generates the offsets in this struct as if this was // a regular message. This way the table driven code barely notices it's @@ -670,6 +646,8 @@ struct MapEntryHelper + #endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc index 64dcc990ff06e..542a1f8335b38 100644 --- a/src/google/protobuf/map_field.cc +++ b/src/google/protobuf/map_field.cc @@ -33,6 +33,8 @@ #include +#include + namespace google { namespace protobuf { namespace internal { @@ -42,20 +44,24 @@ MapFieldBase::~MapFieldBase() { } const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const { + ConstAccess(); SyncRepeatedFieldWithMap(); - return *repeated_field_; + return *reinterpret_cast(repeated_field_); } RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() { + MutableAccess(); SyncRepeatedFieldWithMap(); SetRepeatedDirty(); - return repeated_field_; + return reinterpret_cast(repeated_field_); } size_t MapFieldBase::SpaceUsedExcludingSelfLong() const { + ConstAccess(); mutex_.Lock(); size_t size = SpaceUsedExcludingSelfNoLock(); mutex_.Unlock(); + ConstAccess(); return size; } @@ -68,33 +74,68 @@ size_t MapFieldBase::SpaceUsedExcludingSelfNoLock() const { } bool MapFieldBase::IsMapValid() const { + ConstAccess(); // "Acquire" insures the operation after SyncRepeatedFieldWithMap won't get // executed before state_ is checked. - Atomic32 state = google::protobuf::internal::Acquire_Load(&state_); + int state = state_.load(std::memory_order_acquire); return state != STATE_MODIFIED_REPEATED; } -void MapFieldBase::SetMapDirty() { state_ = STATE_MODIFIED_MAP; } +bool MapFieldBase::IsRepeatedFieldValid() const { + ConstAccess(); + int state = state_.load(std::memory_order_acquire); + return state != STATE_MODIFIED_MAP; +} -void MapFieldBase::SetRepeatedDirty() { state_ = STATE_MODIFIED_REPEATED; } +void MapFieldBase::SetMapDirty() { + MutableAccess(); + // These are called by (non-const) mutator functions. So by our API it's the + // callers responsibility to have these calls properly ordered. + state_.store(STATE_MODIFIED_MAP, std::memory_order_relaxed); +} -void* MapFieldBase::MutableRepeatedPtrField() const { return repeated_field_; } +void MapFieldBase::SetRepeatedDirty() { + MutableAccess(); + // These are called by (non-const) mutator functions. So by our API it's the + // callers responsibility to have these calls properly ordered. + state_.store(STATE_MODIFIED_REPEATED, std::memory_order_relaxed); +} void MapFieldBase::SyncRepeatedFieldWithMap() const { - // "Acquire" insures the operation after SyncRepeatedFieldWithMap won't get - // executed before state_ is checked. - Atomic32 state = google::protobuf::internal::Acquire_Load(&state_); - if (state == STATE_MODIFIED_MAP) { - mutex_.Lock(); - // Double check state, because another thread may have seen the same state - // and done the synchronization before the current thread. - if (state_ == STATE_MODIFIED_MAP) { - SyncRepeatedFieldWithMapNoLock(); - // "Release" insures state_ can only be changed "after" - // SyncRepeatedFieldWithMapNoLock is finished. - google::protobuf::internal::Release_Store(&state_, CLEAN); - } - mutex_.Unlock(); + ConstAccess(); + // acquire here matches with release below to ensure that we can only see a + // value of CLEAN after all previous changes have been synced. + switch (state_.load(std::memory_order_acquire)) { + case STATE_MODIFIED_MAP: + mutex_.Lock(); + // Double check state, because another thread may have seen the same + // state and done the synchronization before the current thread. + if (state_.load(std::memory_order_relaxed) == STATE_MODIFIED_MAP) { + SyncRepeatedFieldWithMapNoLock(); + state_.store(CLEAN, std::memory_order_release); + } + mutex_.Unlock(); + ConstAccess(); + break; + case CLEAN: + mutex_.Lock(); + // Double check state + if (state_.load(std::memory_order_relaxed) == CLEAN) { + if (repeated_field_ == nullptr) { + if (arena_ == nullptr) { + repeated_field_ = new RepeatedPtrField(); + } else { + repeated_field_ = + Arena::CreateMessage >(arena_); + } + } + state_.store(CLEAN, std::memory_order_release); + } + mutex_.Unlock(); + ConstAccess(); + break; + default: + break; } } @@ -105,33 +146,30 @@ void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const { } void MapFieldBase::SyncMapWithRepeatedField() const { - // "Acquire" insures the operation after SyncMapWithRepeatedField won't get - // executed before state_ is checked. - Atomic32 state = google::protobuf::internal::Acquire_Load(&state_); - if (state == STATE_MODIFIED_REPEATED) { + ConstAccess(); + // acquire here matches with release below to ensure that we can only see a + // value of CLEAN after all previous changes have been synced. + if (state_.load(std::memory_order_acquire) == STATE_MODIFIED_REPEATED) { mutex_.Lock(); // Double check state, because another thread may have seen the same state // and done the synchronization before the current thread. - if (state_ == STATE_MODIFIED_REPEATED) { + if (state_.load(std::memory_order_relaxed) == STATE_MODIFIED_REPEATED) { SyncMapWithRepeatedFieldNoLock(); - // "Release" insures state_ can only be changed "after" - // SyncRepeatedFieldWithMapNoLock is finished. - google::protobuf::internal::Release_Store(&state_, CLEAN); + state_.store(CLEAN, std::memory_order_release); } mutex_.Unlock(); + ConstAccess(); } } // ------------------DynamicMapField------------------ DynamicMapField::DynamicMapField(const Message* default_entry) - : default_entry_(default_entry) { -} + : default_entry_(default_entry) {} -DynamicMapField::DynamicMapField(const Message* default_entry, - Arena* arena) +DynamicMapField::DynamicMapField(const Message* default_entry, Arena* arena) : TypeDefinedMapFieldBase(arena), - default_entry_(default_entry) { -} + map_(arena), + default_entry_(default_entry) {} DynamicMapField::~DynamicMapField() { // DynamicMapField owns map values. Need to delete them before clearing @@ -143,56 +181,74 @@ DynamicMapField::~DynamicMapField() { map_.clear(); } -int DynamicMapField::size() const { - return GetMap().size(); +int DynamicMapField::size() const { return GetMap().size(); } + +void DynamicMapField::Clear() { + Map* map = &const_cast(this)->map_; + if (MapFieldBase::arena_ == nullptr) { + for (Map::iterator iter = map->begin(); + iter != map->end(); ++iter) { + iter->second.DeleteData(); + } + } + + map->clear(); + + if (MapFieldBase::repeated_field_ != nullptr) { + MapFieldBase::repeated_field_->Clear(); + } + // Data in map and repeated field are both empty, but we can't set status + // CLEAN which will invalidate previous reference to map. + MapFieldBase::SetMapDirty(); } -bool DynamicMapField::ContainsMapKey( - const MapKey& map_key) const { +bool DynamicMapField::ContainsMapKey(const MapKey& map_key) const { const Map& map = GetMap(); Map::const_iterator iter = map.find(map_key); return iter != map.end(); } -bool DynamicMapField::InsertOrLookupMapValue( - const MapKey& map_key, MapValueRef* val) { +void DynamicMapField::AllocateMapValue(MapValueRef* map_val) { + const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value(); + map_val->SetType(val_des->cpp_type()); + // Allocate memory for the MapValueRef, and initialize to + // default value. + switch (val_des->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + TYPE* value = Arena::Create(MapFieldBase::arena_); \ + map_val->SetValue(value); \ + break; \ + } + HANDLE_TYPE(INT32, int32); + HANDLE_TYPE(INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(STRING, std::string); + HANDLE_TYPE(ENUM, int32); +#undef HANDLE_TYPE + case FieldDescriptor::CPPTYPE_MESSAGE: { + const Message& message = + default_entry_->GetReflection()->GetMessage(*default_entry_, val_des); + Message* value = message.New(MapFieldBase::arena_); + map_val->SetValue(value); + break; + } + } +} + +bool DynamicMapField::InsertOrLookupMapValue(const MapKey& map_key, + MapValueRef* val) { // Always use mutable map because users may change the map value by // MapValueRef. Map* map = MutableMap(); Map::iterator iter = map->find(map_key); if (iter == map->end()) { - // Insert - MapValueRef& map_val = (*map)[map_key]; - const FieldDescriptor* val_des = - default_entry_->GetDescriptor()->FindFieldByName("value"); - map_val.SetType(val_des->cpp_type()); - // Allocate memory for the inserted MapValueRef, and initialize to - // default value. - switch (val_des->cpp_type()) { -#define HANDLE_TYPE(CPPTYPE, TYPE) \ - case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \ - TYPE * value = new TYPE(); \ - map_val.SetValue(value); \ - break; \ - } - HANDLE_TYPE(INT32, int32); - HANDLE_TYPE(INT64, int64); - HANDLE_TYPE(UINT32, uint32); - HANDLE_TYPE(UINT64, uint64); - HANDLE_TYPE(DOUBLE, double); - HANDLE_TYPE(FLOAT, float); - HANDLE_TYPE(BOOL, bool); - HANDLE_TYPE(STRING, string); - HANDLE_TYPE(ENUM, int32); -#undef HANDLE_TYPE - case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { - const Message& message = default_entry_->GetReflection()->GetMessage( - *default_entry_, val_des); - Message* value = message.New(); - map_val.SetValue(value); - break; - } - } + MapValueRef& map_val = map_[map_key]; + AllocateMapValue(&map_val); val->CopyFrom(map_val); return true; } @@ -202,6 +258,19 @@ bool DynamicMapField::InsertOrLookupMapValue( return false; } +bool DynamicMapField::LookupMapValue(const MapKey& map_key, + MapValueConstRef* val) const { + const Map& map = GetMap(); + Map::const_iterator iter = map.find(map_key); + if (iter == map.end()) { + return false; + } + // map_key is already in the map. Make sure (*map)[map_key] is not called. + // [] may reorder the map and iterators. + val->CopyFrom(iter->second); + return true; +} + bool DynamicMapField::DeleteMapValue(const MapKey& map_key) { MapFieldBase::SyncMapWithRepeatedField(); Map::iterator iter = map_.find(map_key); @@ -210,7 +279,9 @@ bool DynamicMapField::DeleteMapValue(const MapKey& map_key) { } // Set map dirty only if the delete is successful. MapFieldBase::SetMapDirty(); - iter->second.DeleteData(); + if (MapFieldBase::arena_ == nullptr) { + iter->second.DeleteData(); + } map_.erase(iter); return true; } @@ -235,12 +306,87 @@ void DynamicMapField::SetMapIteratorValue(MapIterator* map_iter) const { map_iter->value_.CopyFrom(iter->second); } +void DynamicMapField::MergeFrom(const MapFieldBase& other) { + GOOGLE_DCHECK(IsMapValid() && other.IsMapValid()); + Map* map = MutableMap(); + const DynamicMapField& other_field = + reinterpret_cast(other); + for (Map::const_iterator other_it = + other_field.map_.begin(); + other_it != other_field.map_.end(); ++other_it) { + Map::iterator iter = map->find(other_it->first); + MapValueRef* map_val; + if (iter == map->end()) { + map_val = &map_[other_it->first]; + AllocateMapValue(map_val); + } else { + map_val = &iter->second; + } + + // Copy map value + const FieldDescriptor* field_descriptor = + default_entry_->GetDescriptor()->map_value(); + switch (field_descriptor->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: { + map_val->SetInt32Value(other_it->second.GetInt32Value()); + break; + } + case FieldDescriptor::CPPTYPE_INT64: { + map_val->SetInt64Value(other_it->second.GetInt64Value()); + break; + } + case FieldDescriptor::CPPTYPE_UINT32: { + map_val->SetUInt32Value(other_it->second.GetUInt32Value()); + break; + } + case FieldDescriptor::CPPTYPE_UINT64: { + map_val->SetUInt64Value(other_it->second.GetUInt64Value()); + break; + } + case FieldDescriptor::CPPTYPE_FLOAT: { + map_val->SetFloatValue(other_it->second.GetFloatValue()); + break; + } + case FieldDescriptor::CPPTYPE_DOUBLE: { + map_val->SetDoubleValue(other_it->second.GetDoubleValue()); + break; + } + case FieldDescriptor::CPPTYPE_BOOL: { + map_val->SetBoolValue(other_it->second.GetBoolValue()); + break; + } + case FieldDescriptor::CPPTYPE_STRING: { + map_val->SetStringValue(other_it->second.GetStringValue()); + break; + } + case FieldDescriptor::CPPTYPE_ENUM: { + map_val->SetEnumValue(other_it->second.GetEnumValue()); + break; + } + case FieldDescriptor::CPPTYPE_MESSAGE: { + map_val->MutableMessageValue()->CopyFrom( + other_it->second.GetMessageValue()); + break; + } + } + } +} + +void DynamicMapField::Swap(MapFieldBase* other) { + DynamicMapField* other_field = down_cast(other); + std::swap(this->MapFieldBase::repeated_field_, other_field->repeated_field_); + map_.swap(other_field->map_); + // a relaxed swap of the atomic + auto other_state = other_field->state_.load(std::memory_order_relaxed); + auto this_state = this->MapFieldBase::state_.load(std::memory_order_relaxed); + other_field->state_.store(this_state, std::memory_order_relaxed); + this->MapFieldBase::state_.store(other_state, std::memory_order_relaxed); +} + void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const { const Reflection* reflection = default_entry_->GetReflection(); - const FieldDescriptor* key_des = - default_entry_->GetDescriptor()->FindFieldByName("key"); - const FieldDescriptor* val_des = - default_entry_->GetDescriptor()->FindFieldByName("value"); + const FieldDescriptor* key_des = default_entry_->GetDescriptor()->map_key(); + const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value(); if (MapFieldBase::repeated_field_ == NULL) { if (MapFieldBase::arena_ == NULL) { MapFieldBase::repeated_field_ = new RepeatedPtrField(); @@ -255,65 +401,65 @@ void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const { for (Map::const_iterator it = map_.begin(); it != map_.end(); ++it) { - Message* new_entry = default_entry_->New(); + Message* new_entry = default_entry_->New(MapFieldBase::arena_); MapFieldBase::repeated_field_->AddAllocated(new_entry); const MapKey& map_key = it->first; switch (key_des->cpp_type()) { - case google::protobuf::FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_STRING: reflection->SetString(new_entry, key_des, map_key.GetStringValue()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_INT64: reflection->SetInt64(new_entry, key_des, map_key.GetInt64Value()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_INT32: reflection->SetInt32(new_entry, key_des, map_key.GetInt32Value()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_UINT64: reflection->SetUInt64(new_entry, key_des, map_key.GetUInt64Value()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_UINT32: reflection->SetUInt32(new_entry, key_des, map_key.GetUInt32Value()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: + case FieldDescriptor::CPPTYPE_BOOL: reflection->SetBool(new_entry, key_des, map_key.GetBoolValue()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: - case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: - case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: - case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: GOOGLE_LOG(FATAL) << "Can't get here."; break; } const MapValueRef& map_val = it->second; switch (val_des->cpp_type()) { - case google::protobuf::FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_STRING: reflection->SetString(new_entry, val_des, map_val.GetStringValue()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_INT64: reflection->SetInt64(new_entry, val_des, map_val.GetInt64Value()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_INT32: reflection->SetInt32(new_entry, val_des, map_val.GetInt32Value()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_UINT64: reflection->SetUInt64(new_entry, val_des, map_val.GetUInt64Value()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_UINT32: reflection->SetUInt32(new_entry, val_des, map_val.GetUInt32Value()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: + case FieldDescriptor::CPPTYPE_BOOL: reflection->SetBool(new_entry, val_des, map_val.GetBoolValue()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_DOUBLE: reflection->SetDouble(new_entry, val_des, map_val.GetDoubleValue()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_FLOAT: reflection->SetFloat(new_entry, val_des, map_val.GetFloatValue()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_ENUM: reflection->SetEnumValue(new_entry, val_des, map_val.GetEnumValue()); break; - case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { + case FieldDescriptor::CPPTYPE_MESSAGE: { const Message& message = map_val.GetMessageValue(); reflection->MutableMessage(new_entry, val_des)->CopyFrom(message); break; @@ -325,64 +471,67 @@ void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const { void DynamicMapField::SyncMapWithRepeatedFieldNoLock() const { Map* map = &const_cast(this)->map_; const Reflection* reflection = default_entry_->GetReflection(); - const FieldDescriptor* key_des = - default_entry_->GetDescriptor()->FindFieldByName("key"); - const FieldDescriptor* val_des = - default_entry_->GetDescriptor()->FindFieldByName("value"); + const FieldDescriptor* key_des = default_entry_->GetDescriptor()->map_key(); + const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value(); // DynamicMapField owns map values. Need to delete them before clearing // the map. - for (Map::iterator iter = map->begin(); - iter != map->end(); ++iter) { - iter->second.DeleteData(); + if (MapFieldBase::arena_ == nullptr) { + for (Map::iterator iter = map->begin(); + iter != map->end(); ++iter) { + iter->second.DeleteData(); + } } map->clear(); for (RepeatedPtrField::iterator it = MapFieldBase::repeated_field_->begin(); it != MapFieldBase::repeated_field_->end(); ++it) { + // MapKey type will be set later. MapKey map_key; switch (key_des->cpp_type()) { - case google::protobuf::FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_STRING: map_key.SetStringValue(reflection->GetString(*it, key_des)); break; - case google::protobuf::FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_INT64: map_key.SetInt64Value(reflection->GetInt64(*it, key_des)); break; - case google::protobuf::FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_INT32: map_key.SetInt32Value(reflection->GetInt32(*it, key_des)); break; - case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_UINT64: map_key.SetUInt64Value(reflection->GetUInt64(*it, key_des)); break; - case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_UINT32: map_key.SetUInt32Value(reflection->GetUInt32(*it, key_des)); break; - case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: + case FieldDescriptor::CPPTYPE_BOOL: map_key.SetBoolValue(reflection->GetBool(*it, key_des)); break; - case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: - case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: - case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: - case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: GOOGLE_LOG(FATAL) << "Can't get here."; break; } - // Remove existing map value with same key. - Map::iterator iter = map->find(map_key); - if (iter != map->end()) { - iter->second.DeleteData(); + if (MapFieldBase::arena_ == nullptr) { + // Remove existing map value with same key. + Map::iterator iter = map->find(map_key); + if (iter != map->end()) { + iter->second.DeleteData(); + } } MapValueRef& map_val = (*map)[map_key]; map_val.SetType(val_des->cpp_type()); switch (val_des->cpp_type()) { -#define HANDLE_TYPE(CPPTYPE, TYPE, METHOD) \ - case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \ - TYPE * value = new TYPE; \ - *value = reflection->Get##METHOD(*it, val_des); \ - map_val.SetValue(value); \ - break; \ - } +#define HANDLE_TYPE(CPPTYPE, TYPE, METHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + TYPE* value = Arena::Create(MapFieldBase::arena_); \ + *value = reflection->Get##METHOD(*it, val_des); \ + map_val.SetValue(value); \ + break; \ + } HANDLE_TYPE(INT32, int32, Int32); HANDLE_TYPE(INT64, int64, Int64); HANDLE_TYPE(UINT32, uint32, UInt32); @@ -390,12 +539,12 @@ void DynamicMapField::SyncMapWithRepeatedFieldNoLock() const { HANDLE_TYPE(DOUBLE, double, Double); HANDLE_TYPE(FLOAT, float, Float); HANDLE_TYPE(BOOL, bool, Bool); - HANDLE_TYPE(STRING, string, String); + HANDLE_TYPE(STRING, std::string, String); HANDLE_TYPE(ENUM, int32, EnumValue); #undef HANDLE_TYPE - case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { + case FieldDescriptor::CPPTYPE_MESSAGE: { const Message& message = reflection->GetMessage(*it, val_des); - Message* value = message.New(); + Message* value = message.New(MapFieldBase::arena_); value->CopyFrom(message); map_val.SetValue(value); break; @@ -416,16 +565,16 @@ size_t DynamicMapField::SpaceUsedExcludingSelfNoLock() const { size += sizeof(it->first) * map_size; size += sizeof(it->second) * map_size; // If key is string, add the allocated space. - if (it->first.type() == google::protobuf::FieldDescriptor::CPPTYPE_STRING) { - size += sizeof(string) * map_size; + if (it->first.type() == FieldDescriptor::CPPTYPE_STRING) { + size += sizeof(std::string) * map_size; } // Add the allocated space in MapValueRef. switch (it->second.type()) { -#define HANDLE_TYPE(CPPTYPE, TYPE) \ - case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \ - size += sizeof(TYPE) * map_size; \ - break; \ - } +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + size += sizeof(TYPE) * map_size; \ + break; \ + } HANDLE_TYPE(INT32, int32); HANDLE_TYPE(INT64, int64); HANDLE_TYPE(UINT32, uint32); @@ -433,10 +582,10 @@ size_t DynamicMapField::SpaceUsedExcludingSelfNoLock() const { HANDLE_TYPE(DOUBLE, double); HANDLE_TYPE(FLOAT, float); HANDLE_TYPE(BOOL, bool); - HANDLE_TYPE(STRING, string); + HANDLE_TYPE(STRING, std::string); HANDLE_TYPE(ENUM, int32); #undef HANDLE_TYPE - case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { + case FieldDescriptor::CPPTYPE_MESSAGE: { while (it != map_.end()) { const Message& message = it->second.GetMessageValue(); size += message.GetReflection()->SpaceUsedLong(message); @@ -452,3 +601,5 @@ size_t DynamicMapField::SpaceUsedExcludingSelfNoLock() const { } // namespace internal } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h index bd47890166473..e05d3ee04da26 100644 --- a/src/google/protobuf/map_field.h +++ b/src/google/protobuf/map_field.h @@ -31,24 +31,287 @@ #ifndef GOOGLE_PROTOBUF_MAP_FIELD_H__ #define GOOGLE_PROTOBUF_MAP_FIELD_H__ -#include -#include -#include -#include +#include +#include + #include #include +#include +#include #include #include #include #include +#include +#include #include #include +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + namespace google { namespace protobuf { class DynamicMessage; -class MapKey; +class MapIterator; + +#define TYPE_CHECK(EXPECTEDTYPE, METHOD) \ + if (type() != EXPECTEDTYPE) { \ + GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n" \ + << METHOD << " type does not match\n" \ + << " Expected : " \ + << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \ + << " Actual : " << FieldDescriptor::CppTypeName(type()); \ + } + +// MapKey is an union type for representing any possible +// map key. +class PROTOBUF_EXPORT MapKey { + public: + MapKey() : type_() {} + MapKey(const MapKey& other) : type_() { CopyFrom(other); } + + MapKey& operator=(const MapKey& other) { + CopyFrom(other); + return *this; + } + + ~MapKey() { + if (type_ == FieldDescriptor::CPPTYPE_STRING) { + val_.string_value_.Destruct(); + } + } + + FieldDescriptor::CppType type() const { + if (type_ == FieldDescriptor::CppType()) { + GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n" + << "MapKey::type MapKey is not initialized. " + << "Call set methods to initialize MapKey."; + } + return type_; + } + + void SetInt64Value(int64 value) { + SetType(FieldDescriptor::CPPTYPE_INT64); + val_.int64_value_ = value; + } + void SetUInt64Value(uint64 value) { + SetType(FieldDescriptor::CPPTYPE_UINT64); + val_.uint64_value_ = value; + } + void SetInt32Value(int32 value) { + SetType(FieldDescriptor::CPPTYPE_INT32); + val_.int32_value_ = value; + } + void SetUInt32Value(uint32 value) { + SetType(FieldDescriptor::CPPTYPE_UINT32); + val_.uint32_value_ = value; + } + void SetBoolValue(bool value) { + SetType(FieldDescriptor::CPPTYPE_BOOL); + val_.bool_value_ = value; + } + void SetStringValue(std::string val) { + SetType(FieldDescriptor::CPPTYPE_STRING); + *val_.string_value_.get_mutable() = std::move(val); + } + + int64 GetInt64Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapKey::GetInt64Value"); + return val_.int64_value_; + } + uint64 GetUInt64Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapKey::GetUInt64Value"); + return val_.uint64_value_; + } + int32 GetInt32Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapKey::GetInt32Value"); + return val_.int32_value_; + } + uint32 GetUInt32Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapKey::GetUInt32Value"); + return val_.uint32_value_; + } + bool GetBoolValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapKey::GetBoolValue"); + return val_.bool_value_; + } + const std::string& GetStringValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapKey::GetStringValue"); + return val_.string_value_.get(); + } + + bool operator<(const MapKey& other) const { + if (type_ != other.type_) { + // We could define a total order that handles this case, but + // there currently no need. So, for now, fail. + GOOGLE_LOG(FATAL) << "Unsupported: type mismatch"; + } + switch (type()) { + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Unsupported"; + return false; + case FieldDescriptor::CPPTYPE_STRING: + return val_.string_value_.get() < other.val_.string_value_.get(); + case FieldDescriptor::CPPTYPE_INT64: + return val_.int64_value_ < other.val_.int64_value_; + case FieldDescriptor::CPPTYPE_INT32: + return val_.int32_value_ < other.val_.int32_value_; + case FieldDescriptor::CPPTYPE_UINT64: + return val_.uint64_value_ < other.val_.uint64_value_; + case FieldDescriptor::CPPTYPE_UINT32: + return val_.uint32_value_ < other.val_.uint32_value_; + case FieldDescriptor::CPPTYPE_BOOL: + return val_.bool_value_ < other.val_.bool_value_; + } + return false; + } + + bool operator==(const MapKey& other) const { + if (type_ != other.type_) { + // To be consistent with operator<, we don't allow this either. + GOOGLE_LOG(FATAL) << "Unsupported: type mismatch"; + } + switch (type()) { + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Unsupported"; + break; + case FieldDescriptor::CPPTYPE_STRING: + return val_.string_value_.get() == other.val_.string_value_.get(); + case FieldDescriptor::CPPTYPE_INT64: + return val_.int64_value_ == other.val_.int64_value_; + case FieldDescriptor::CPPTYPE_INT32: + return val_.int32_value_ == other.val_.int32_value_; + case FieldDescriptor::CPPTYPE_UINT64: + return val_.uint64_value_ == other.val_.uint64_value_; + case FieldDescriptor::CPPTYPE_UINT32: + return val_.uint32_value_ == other.val_.uint32_value_; + case FieldDescriptor::CPPTYPE_BOOL: + return val_.bool_value_ == other.val_.bool_value_; + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return false; + } + + void CopyFrom(const MapKey& other) { + SetType(other.type()); + switch (type_) { + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Unsupported"; + break; + case FieldDescriptor::CPPTYPE_STRING: + *val_.string_value_.get_mutable() = other.val_.string_value_.get(); + break; + case FieldDescriptor::CPPTYPE_INT64: + val_.int64_value_ = other.val_.int64_value_; + break; + case FieldDescriptor::CPPTYPE_INT32: + val_.int32_value_ = other.val_.int32_value_; + break; + case FieldDescriptor::CPPTYPE_UINT64: + val_.uint64_value_ = other.val_.uint64_value_; + break; + case FieldDescriptor::CPPTYPE_UINT32: + val_.uint32_value_ = other.val_.uint32_value_; + break; + case FieldDescriptor::CPPTYPE_BOOL: + val_.bool_value_ = other.val_.bool_value_; + break; + } + } + + private: + template + friend class internal::TypeDefinedMapFieldBase; + friend class ::PROTOBUF_NAMESPACE_ID::MapIterator; + friend class internal::DynamicMapField; + + union KeyValue { + KeyValue() {} + internal::ExplicitlyConstructed string_value_; + int64 int64_value_; + int32 int32_value_; + uint64 uint64_value_; + uint32 uint32_value_; + bool bool_value_; + } val_; + + void SetType(FieldDescriptor::CppType type) { + if (type_ == type) return; + if (type_ == FieldDescriptor::CPPTYPE_STRING) { + val_.string_value_.Destruct(); + } + type_ = type; + if (type_ == FieldDescriptor::CPPTYPE_STRING) { + val_.string_value_.DefaultConstruct(); + } + } + + // type_ is 0 or a valid FieldDescriptor::CppType. + // Use "CppType()" to indicate zero. + FieldDescriptor::CppType type_; +}; + +} // namespace protobuf +} // namespace google +namespace std { +template <> +struct hash<::PROTOBUF_NAMESPACE_ID::MapKey> { + size_t operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key) const { + switch (map_key.type()) { + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_DOUBLE: + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_FLOAT: + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_ENUM: + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Unsupported"; + break; + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_STRING: + return hash()(map_key.GetStringValue()); + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT64: { + auto value = map_key.GetInt64Value(); + return hash()(value); + } + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT32: { + auto value = map_key.GetInt32Value(); + return hash()(map_key.GetInt32Value()); + } + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT64: { + auto value = map_key.GetUInt64Value(); + return hash()(map_key.GetUInt64Value()); + } + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT32: { + auto value = map_key.GetUInt32Value(); + return hash()(map_key.GetUInt32Value()); + } + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_BOOL: { + return hash()(map_key.GetBoolValue()); + } + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return 0; + } + bool operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key1, + const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key2) const { + return map_key1 < map_key2; + } +}; +} // namespace std + +namespace google { +namespace protobuf { namespace internal { class ContendedMapCleanTest; @@ -57,25 +320,33 @@ class MapFieldAccessor; // This class provides access to map field using reflection, which is the same // as those provided for RepeatedPtrField. It is used for internal -// reflection implentation only. Users should never use this directly. -class LIBPROTOBUF_EXPORT MapFieldBase { +// reflection implementation only. Users should never use this directly. +class PROTOBUF_EXPORT MapFieldBase { public: MapFieldBase() - : arena_(NULL), - repeated_field_(NULL), + : arena_(NULL), repeated_field_(NULL), state_(STATE_MODIFIED_MAP) {} + + // This constructor is for constant initialized global instances. + // It uses a linker initialized mutex, so it is not compatible with regular + // runtime instances. + // Except in MSVC, where we can't have a constinit mutex. + explicit constexpr MapFieldBase(ConstantInitialized) + : arena_(nullptr), + repeated_field_(nullptr), + mutex_(GOOGLE_PROTOBUF_LINKER_INITIALIZED), state_(STATE_MODIFIED_MAP) {} explicit MapFieldBase(Arena* arena) - : arena_(arena), - repeated_field_(NULL), - state_(STATE_MODIFIED_MAP) { + : arena_(arena), repeated_field_(NULL), state_(STATE_MODIFIED_MAP) { // Mutex's destructor needs to be called explicitly to release resources // acquired in its constructor. - arena->OwnDestructor(&mutex_); + if (arena) { + arena->OwnDestructor(&mutex_); + } } virtual ~MapFieldBase(); // Returns reference to internal repeated field. Data written using - // google::protobuf::Map's api prior to calling this function is guarantted to be + // Map's api prior to calling this function is guarantted to be // included in repeated field. const RepeatedPtrFieldBase& GetRepeatedField() const; @@ -84,8 +355,14 @@ class LIBPROTOBUF_EXPORT MapFieldBase { // Pure virtual map APIs for Map Reflection. virtual bool ContainsMapKey(const MapKey& map_key) const = 0; - virtual bool InsertOrLookupMapValue( - const MapKey& map_key, MapValueRef* val) = 0; + virtual bool InsertOrLookupMapValue(const MapKey& map_key, + MapValueRef* val) = 0; + virtual bool LookupMapValue(const MapKey& map_key, + MapValueConstRef* val) const = 0; + bool LookupMapValue(const MapKey&, MapValueRef*) const = delete; + + // Returns whether changes to the map are reflected in the repeated field. + bool IsRepeatedFieldValid() const; // Insures operations after won't get executed before calling this. bool IsMapValid() const; virtual bool DeleteMapValue(const MapKey& map_key) = 0; @@ -93,8 +370,11 @@ class LIBPROTOBUF_EXPORT MapFieldBase { const MapIterator& b) const = 0; virtual void MapBegin(MapIterator* map_iter) const = 0; virtual void MapEnd(MapIterator* map_iter) const = 0; + virtual void MergeFrom(const MapFieldBase& other) = 0; + virtual void Swap(MapFieldBase* other) = 0; // Sync Map with repeated field and returns the size of map. virtual int size() const = 0; + virtual void Clear() = 0; // Returns the number of bytes used by the repeated field, excluding // sizeof(*this) @@ -121,40 +401,58 @@ class LIBPROTOBUF_EXPORT MapFieldBase { // Tells MapFieldBase that there is new change to Map. void SetMapDirty(); - // Tells MapFieldBase that there is new change to RepeatedPTrField. + // Tells MapFieldBase that there is new change to RepeatedPtrField. void SetRepeatedDirty(); // Provides derived class the access to repeated field. void* MutableRepeatedPtrField() const; + // Support thread sanitizer (tsan) by making const / mutable races + // more apparent. If one thread calls MutableAccess() while another + // thread calls either ConstAccess() or MutableAccess(), on the same + // MapFieldBase-derived object, and there is no synchronization going + // on between them, tsan will alert. +#if defined(__SANITIZE_THREAD__) || defined(THREAD_SANITIZER) + void ConstAccess() const { GOOGLE_CHECK_EQ(seq1_, seq2_); } + void MutableAccess() { + if (seq1_ & 1) { + seq2_ = ++seq1_; + } else { + seq1_ = ++seq2_; + } + } + unsigned int seq1_ = 0, seq2_ = 0; +#else + void ConstAccess() const {} + void MutableAccess() {} +#endif enum State { STATE_MODIFIED_MAP = 0, // map has newly added data that has not been // synchronized to repeated field STATE_MODIFIED_REPEATED = 1, // repeated field has newly added data that // has not been synchronized to map - CLEAN = 2, // data in map and repeated field are same + CLEAN = 2, // data in map and repeated field are same }; Arena* arena_; mutable RepeatedPtrField* repeated_field_; - mutable Mutex mutex_; // The thread to synchronize map and repeated field - // needs to get lock first; - mutable volatile Atomic32 state_; // 0: STATE_MODIFIED_MAP - // 1: STATE_MODIFIED_REPEATED - // 2: CLEAN + mutable internal::WrappedMutex + mutex_; // The thread to synchronize map and repeated field + // needs to get lock first; + mutable std::atomic state_; private: friend class ContendedMapCleanTest; friend class GeneratedMessageReflection; friend class MapFieldAccessor; - friend class ::google::protobuf::DynamicMessage; + friend class ::PROTOBUF_NAMESPACE_ID::DynamicMessage; // Virtual helper methods for MapIterator. MapIterator doesn't have the // type helper for key and value. Call these help methods to deal with // different types. Real helper methods are implemented in // TypeDefinedMapFieldBase. - friend class ::google::protobuf::MapIterator; + friend class ::PROTOBUF_NAMESPACE_ID::MapIterator; // Allocate map<...>::iterator for MapIterator. virtual void InitializeIterator(MapIterator* map_iter) const = 0; @@ -175,15 +473,21 @@ class LIBPROTOBUF_EXPORT MapFieldBase { // This class provides common Map Reflection implementations for generated // message and dynamic message. -template +template class TypeDefinedMapFieldBase : public MapFieldBase { public: TypeDefinedMapFieldBase() {} + + // This constructor is for constant initialized global instances. + // It uses a linker initialized mutex, so it is not compatible with regular + // runtime instances. + explicit constexpr TypeDefinedMapFieldBase(ConstantInitialized tag) + : MapFieldBase(tag) {} explicit TypeDefinedMapFieldBase(Arena* arena) : MapFieldBase(arena) {} - ~TypeDefinedMapFieldBase() {} - void MapBegin(MapIterator* map_iter) const; - void MapEnd(MapIterator* map_iter) const; - bool EqualIterator(const MapIterator& a, const MapIterator& b) const; + ~TypeDefinedMapFieldBase() override {} + void MapBegin(MapIterator* map_iter) const override; + void MapEnd(MapIterator* map_iter) const override; + bool EqualIterator(const MapIterator& a, const MapIterator& b) const override; virtual const Map& GetMap() const = 0; virtual Map* MutableMap() = 0; @@ -193,22 +497,22 @@ class TypeDefinedMapFieldBase : public MapFieldBase { const MapIterator* map_iter) const; private: - void InitializeIterator(MapIterator* map_iter) const; - void DeleteIterator(MapIterator* map_iter) const; + void InitializeIterator(MapIterator* map_iter) const override; + void DeleteIterator(MapIterator* map_iter) const override; void CopyIterator(MapIterator* this_iteratorm, - const MapIterator& that_iterator) const; - void IncreaseIterator(MapIterator* map_iter) const; + const MapIterator& that_iterator) const override; + void IncreaseIterator(MapIterator* map_iter) const override; virtual void SetMapIteratorValue(MapIterator* map_iter) const = 0; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeDefinedMapFieldBase); }; // This class provides access to map field using generated api. It is used for -// internal generated message implentation only. Users should never use this +// internal generated message implementation only. Users should never use this // directly. template + WireFormatLite::FieldType kValueFieldType> class MapField : public TypeDefinedMapFieldBase { // Provide utilities to parse/serialize key/value. Provide utilities to // manipulate internal stored type. @@ -217,19 +521,16 @@ class MapField : public TypeDefinedMapFieldBase { // Define message type for internal repeated field. typedef Derived EntryType; - typedef MapEntryLite EntryLiteType; // Define abbreviation for parent MapFieldLite - typedef MapFieldLite + typedef MapFieldLite MapFieldLiteType; // Enum needs to be handled differently from other types because it has - // different exposed type in google::protobuf::Map's api and repeated field's api. For + // different exposed type in Map's api and repeated field's api. For // details see the comment in the implementation of // SyncMapWithRepeatedFieldNoLock. - static const bool kIsValueEnum = ValueTypeHandler::kIsEnum; + static constexpr bool kIsValueEnum = ValueTypeHandler::kIsEnum; typedef typename MapIf::type CastValueType; public: @@ -237,31 +538,39 @@ class MapField : public TypeDefinedMapFieldBase { typedef Map MapType; MapField() {} + + // This constructor is for constant initialized global instances. + // It uses a linker initialized mutex, so it is not compatible with regular + // runtime instances. + explicit constexpr MapField(ConstantInitialized tag) + : TypeDefinedMapFieldBase(tag), impl_() {} explicit MapField(Arena* arena) : TypeDefinedMapFieldBase(arena), impl_(arena) {} // Implement MapFieldBase - bool ContainsMapKey(const MapKey& map_key) const; - bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val); - bool DeleteMapValue(const MapKey& map_key); - - const Map& GetMap() const { + bool ContainsMapKey(const MapKey& map_key) const override; + bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) override; + bool LookupMapValue(const MapKey& map_key, + MapValueConstRef* val) const override; + bool LookupMapValue(const MapKey&, MapValueRef*) const = delete; + bool DeleteMapValue(const MapKey& map_key) override; + + const Map& GetMap() const override { MapFieldBase::SyncMapWithRepeatedField(); return impl_.GetMap(); } - Map* MutableMap() { + Map* MutableMap() override { MapFieldBase::SyncMapWithRepeatedField(); Map* result = impl_.MutableMap(); MapFieldBase::SetMapDirty(); return result; } - // Convenient methods for generated message implementation. - int size() const; - void Clear(); - void MergeFrom(const MapField& other); - void Swap(MapField* other); + int size() const override; + void Clear() override; + void MergeFrom(const MapFieldBase& other) override; + void Swap(MapFieldBase* other) override; // Used in the implementation of parsing. Caller should take the ownership iff // arena_ is NULL. @@ -277,6 +586,17 @@ class MapField : public TypeDefinedMapFieldBase { return impl_.NewEntryWrapper(key, t); } + const char* _InternalParse(const char* ptr, ParseContext* ctx) { + return impl_._InternalParse(ptr, ctx); + } + template + const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx, + bool (*is_valid)(int), uint32 field_num, + InternalMetadata* metadata) { + return impl_.template ParseWithEnumValidation( + ptr, ctx, is_valid, field_num, metadata); + } + private: MapFieldLiteType impl_; @@ -284,375 +604,213 @@ class MapField : public TypeDefinedMapFieldBase { typedef void DestructorSkippable_; // Implements MapFieldBase - void SyncRepeatedFieldWithMapNoLock() const; - void SyncMapWithRepeatedFieldNoLock() const; - size_t SpaceUsedExcludingSelfNoLock() const; + void SyncRepeatedFieldWithMapNoLock() const override; + void SyncMapWithRepeatedFieldNoLock() const override; + size_t SpaceUsedExcludingSelfNoLock() const override; - void SetMapIteratorValue(MapIterator* map_iter) const; + void SetMapIteratorValue(MapIterator* map_iter) const override; - friend class ::google::protobuf::Arena; + friend class ::PROTOBUF_NAMESPACE_ID::Arena; friend class MapFieldStateTest; // For testing, it needs raw access to impl_ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapField); }; -template -struct MapEntryToMapField { - typedef DeconstructMapEntry T; - typedef MapField - MapFieldType; +template +bool AllAreInitialized( + const MapField& field) { + const auto& t = field.GetMap(); + for (typename Map::const_iterator it = t.begin(); it != t.end(); + ++it) { + if (!it->second.IsInitialized()) return false; + } + return true; +} + +template +struct MapEntryToMapField< + MapEntry> { + typedef MapField MapFieldType; }; -class LIBPROTOBUF_EXPORT DynamicMapField: public TypeDefinedMapFieldBase { +class PROTOBUF_EXPORT DynamicMapField + : public TypeDefinedMapFieldBase { public: explicit DynamicMapField(const Message* default_entry); DynamicMapField(const Message* default_entry, Arena* arena); - ~DynamicMapField(); + ~DynamicMapField() override; // Implement MapFieldBase - bool ContainsMapKey(const MapKey& map_key) const; - bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val); - bool DeleteMapValue(const MapKey& map_key); + bool ContainsMapKey(const MapKey& map_key) const override; + bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) override; + bool LookupMapValue(const MapKey& map_key, + MapValueConstRef* val) const override; + bool LookupMapValue(const MapKey&, MapValueRef*) const = delete; + bool DeleteMapValue(const MapKey& map_key) override; + void MergeFrom(const MapFieldBase& other) override; + void Swap(MapFieldBase* other) override; - const Map& GetMap() const; - Map* MutableMap(); + const Map& GetMap() const override; + Map* MutableMap() override; - int size() const; + int size() const override; + void Clear() override; private: Map map_; const Message* default_entry_; + void AllocateMapValue(MapValueRef* map_val); + // Implements MapFieldBase - void SyncRepeatedFieldWithMapNoLock() const; - void SyncMapWithRepeatedFieldNoLock() const; - size_t SpaceUsedExcludingSelfNoLock() const; - void SetMapIteratorValue(MapIterator* map_iter) const; + void SyncRepeatedFieldWithMapNoLock() const override; + void SyncMapWithRepeatedFieldNoLock() const override; + size_t SpaceUsedExcludingSelfNoLock() const override; + void SetMapIteratorValue(MapIterator* map_iter) const override; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMapField); }; } // namespace internal -#define TYPE_CHECK(EXPECTEDTYPE, METHOD) \ - if (type() != EXPECTEDTYPE) { \ - GOOGLE_LOG(FATAL) \ - << "Protocol Buffer map usage error:\n" \ - << METHOD << " type does not match\n" \ - << " Expected : " \ - << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \ - << " Actual : " \ - << FieldDescriptor::CppTypeName(type()); \ - } - -// MapKey is an union type for representing any possible -// map key. -class LIBPROTOBUF_EXPORT MapKey { +// MapValueConstRef points to a map value. Users can NOT modify +// the map value. +class PROTOBUF_EXPORT MapValueConstRef { public: - MapKey() : type_(0) { - } - MapKey(const MapKey& other) : type_(0) { - CopyFrom(other); - } - MapKey& operator=(const MapKey& other) { - CopyFrom(other); - return *this; - } - - ~MapKey() { - if (type_ == FieldDescriptor::CPPTYPE_STRING) { - delete val_.string_value_; - } - } - - FieldDescriptor::CppType type() const { - if (type_ == 0) { - GOOGLE_LOG(FATAL) - << "Protocol Buffer map usage error:\n" - << "MapKey::type MapKey is not initialized. " - << "Call set methods to initialize MapKey."; - } - return (FieldDescriptor::CppType)type_; - } - - void SetInt64Value(int64 value) { - SetType(FieldDescriptor::CPPTYPE_INT64); - val_.int64_value_ = value; - } - void SetUInt64Value(uint64 value) { - SetType(FieldDescriptor::CPPTYPE_UINT64); - val_.uint64_value_ = value; - } - void SetInt32Value(int32 value) { - SetType(FieldDescriptor::CPPTYPE_INT32); - val_.int32_value_ = value; - } - void SetUInt32Value(uint32 value) { - SetType(FieldDescriptor::CPPTYPE_UINT32); - val_.uint32_value_ = value; - } - void SetBoolValue(bool value) { - SetType(FieldDescriptor::CPPTYPE_BOOL); - val_.bool_value_ = value; - } - void SetStringValue(const string& val) { - SetType(FieldDescriptor::CPPTYPE_STRING); - *val_.string_value_ = val; - } + MapValueConstRef() : data_(nullptr), type_() {} int64 GetInt64Value() const { TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, - "MapKey::GetInt64Value"); - return val_.int64_value_; + "MapValueConstRef::GetInt64Value"); + return *reinterpret_cast(data_); } uint64 GetUInt64Value() const { TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, - "MapKey::GetUInt64Value"); - return val_.uint64_value_; + "MapValueConstRef::GetUInt64Value"); + return *reinterpret_cast(data_); } int32 GetInt32Value() const { TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, - "MapKey::GetInt32Value"); - return val_.int32_value_; + "MapValueConstRef::GetInt32Value"); + return *reinterpret_cast(data_); } uint32 GetUInt32Value() const { TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, - "MapKey::GetUInt32Value"); - return val_.uint32_value_; + "MapValueConstRef::GetUInt32Value"); + return *reinterpret_cast(data_); } bool GetBoolValue() const { - TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, - "MapKey::GetBoolValue"); - return val_.bool_value_; + TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapValueConstRef::GetBoolValue"); + return *reinterpret_cast(data_); + } + int GetEnumValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueConstRef::GetEnumValue"); + return *reinterpret_cast(data_); } - const string& GetStringValue() const { + const std::string& GetStringValue() const { TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, - "MapKey::GetStringValue"); - return *val_.string_value_; + "MapValueConstRef::GetStringValue"); + return *reinterpret_cast(data_); } - - bool operator<(const MapKey& other) const { - if (type_ != other.type_) { - // We could define a total order that handles this case, but - // there currently no need. So, for now, fail. - GOOGLE_LOG(FATAL) << "Unsupported: type mismatch"; - } - switch (type()) { - case FieldDescriptor::CPPTYPE_DOUBLE: - case FieldDescriptor::CPPTYPE_FLOAT: - case FieldDescriptor::CPPTYPE_ENUM: - case FieldDescriptor::CPPTYPE_MESSAGE: - GOOGLE_LOG(FATAL) << "Unsupported"; - return false; - case FieldDescriptor::CPPTYPE_STRING: - return *val_.string_value_ < *other.val_.string_value_; - case FieldDescriptor::CPPTYPE_INT64: - return val_.int64_value_ < other.val_.int64_value_; - case FieldDescriptor::CPPTYPE_INT32: - return val_.int32_value_ < other.val_.int32_value_; - case FieldDescriptor::CPPTYPE_UINT64: - return val_.uint64_value_ < other.val_.uint64_value_; - case FieldDescriptor::CPPTYPE_UINT32: - return val_.uint32_value_ < other.val_.uint32_value_; - case FieldDescriptor::CPPTYPE_BOOL: - return val_.bool_value_ < other.val_.bool_value_; - } - return false; + float GetFloatValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, + "MapValueConstRef::GetFloatValue"); + return *reinterpret_cast(data_); + } + double GetDoubleValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, + "MapValueConstRef::GetDoubleValue"); + return *reinterpret_cast(data_); } - bool operator==(const MapKey& other) const { - if (type_ != other.type_) { - // To be consistent with operator<, we don't allow this either. - GOOGLE_LOG(FATAL) << "Unsupported: type mismatch"; - } - switch (type()) { - case FieldDescriptor::CPPTYPE_DOUBLE: - case FieldDescriptor::CPPTYPE_FLOAT: - case FieldDescriptor::CPPTYPE_ENUM: - case FieldDescriptor::CPPTYPE_MESSAGE: - GOOGLE_LOG(FATAL) << "Unsupported"; - break; - case FieldDescriptor::CPPTYPE_STRING: - return *val_.string_value_ == *other.val_.string_value_; - case FieldDescriptor::CPPTYPE_INT64: - return val_.int64_value_ == other.val_.int64_value_; - case FieldDescriptor::CPPTYPE_INT32: - return val_.int32_value_ == other.val_.int32_value_; - case FieldDescriptor::CPPTYPE_UINT64: - return val_.uint64_value_ == other.val_.uint64_value_; - case FieldDescriptor::CPPTYPE_UINT32: - return val_.uint32_value_ == other.val_.uint32_value_; - case FieldDescriptor::CPPTYPE_BOOL: - return val_.bool_value_ == other.val_.bool_value_; - } - GOOGLE_LOG(FATAL) << "Can't get here."; - return false; + const Message& GetMessageValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE, + "MapValueConstRef::GetMessageValue"); + return *reinterpret_cast(data_); } - void CopyFrom(const MapKey& other) { - SetType(other.type()); - switch (type_) { - case FieldDescriptor::CPPTYPE_DOUBLE: - case FieldDescriptor::CPPTYPE_FLOAT: - case FieldDescriptor::CPPTYPE_ENUM: - case FieldDescriptor::CPPTYPE_MESSAGE: - GOOGLE_LOG(FATAL) << "Unsupported"; - break; - case FieldDescriptor::CPPTYPE_STRING: - *val_.string_value_ = *other.val_.string_value_; - break; - case FieldDescriptor::CPPTYPE_INT64: - val_.int64_value_ = other.val_.int64_value_; - break; - case FieldDescriptor::CPPTYPE_INT32: - val_.int32_value_ = other.val_.int32_value_; - break; - case FieldDescriptor::CPPTYPE_UINT64: - val_.uint64_value_ = other.val_.uint64_value_; - break; - case FieldDescriptor::CPPTYPE_UINT32: - val_.uint32_value_ = other.val_.uint32_value_; - break; - case FieldDescriptor::CPPTYPE_BOOL: - val_.bool_value_ = other.val_.bool_value_; - break; + protected: + // data_ point to a map value. MapValueConstRef does not + // own this value. + void* data_; + // type_ is 0 or a valid FieldDescriptor::CppType. + // Use "CppType()" to indicate zero. + FieldDescriptor::CppType type_; + + FieldDescriptor::CppType type() const { + if (type_ == FieldDescriptor::CppType() || data_ == nullptr) { + GOOGLE_LOG(FATAL) + << "Protocol Buffer map usage error:\n" + << "MapValueConstRef::type MapValueConstRef is not initialized."; } + return type_; } private: + template + friend class internal::MapField; template friend class internal::TypeDefinedMapFieldBase; - friend class MapIterator; + friend class ::PROTOBUF_NAMESPACE_ID::MapIterator; + friend class Reflection; friend class internal::DynamicMapField; - union KeyValue { - KeyValue() {} - string* string_value_; - int64 int64_value_; - int32 int32_value_; - uint64 uint64_value_; - uint32 uint32_value_; - bool bool_value_; - } val_; - - void SetType(FieldDescriptor::CppType type) { - if (type_ == type) return; - if (type_ == FieldDescriptor::CPPTYPE_STRING) { - delete val_.string_value_; - } - type_ = type; - if (type_ == FieldDescriptor::CPPTYPE_STRING) { - val_.string_value_ = new string; - } + void SetType(FieldDescriptor::CppType type) { type_ = type; } + void SetValue(const void* val) { data_ = const_cast(val); } + void CopyFrom(const MapValueConstRef& other) { + type_ = other.type_; + data_ = other.data_; } - - // type_ is 0 or a valid FieldDescriptor::CppType. - int type_; }; -// MapValueRef points to a map value. -class LIBPROTOBUF_EXPORT MapValueRef { +// MapValueRef points to a map value. Users are able to modify +// the map value. +class PROTOBUF_EXPORT MapValueRef final : public MapValueConstRef { public: - MapValueRef() : data_(NULL), type_(0) {} + MapValueRef() {} void SetInt64Value(int64 value) { - TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, - "MapValueRef::SetInt64Value"); + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapValueRef::SetInt64Value"); *reinterpret_cast(data_) = value; } void SetUInt64Value(uint64 value) { - TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, - "MapValueRef::SetUInt64Value"); + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapValueRef::SetUInt64Value"); *reinterpret_cast(data_) = value; } void SetInt32Value(int32 value) { - TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, - "MapValueRef::SetInt32Value"); + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapValueRef::SetInt32Value"); *reinterpret_cast(data_) = value; } void SetUInt32Value(uint32 value) { - TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, - "MapValueRef::SetUInt32Value"); + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapValueRef::SetUInt32Value"); *reinterpret_cast(data_) = value; } void SetBoolValue(bool value) { - TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, - "MapValueRef::SetBoolValue"); + TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapValueRef::SetBoolValue"); *reinterpret_cast(data_) = value; } // TODO(jieluo) - Checks that enum is member. void SetEnumValue(int value) { - TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, - "MapValueRef::SetEnumValue"); + TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueRef::SetEnumValue"); *reinterpret_cast(data_) = value; } - void SetStringValue(const string& value) { - TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, - "MapValueRef::SetStringValue"); - *reinterpret_cast(data_) = value; + void SetStringValue(const std::string& value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapValueRef::SetStringValue"); + *reinterpret_cast(data_) = value; } void SetFloatValue(float value) { - TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, - "MapValueRef::SetFloatValue"); + TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, "MapValueRef::SetFloatValue"); *reinterpret_cast(data_) = value; } void SetDoubleValue(double value) { - TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, - "MapValueRef::SetDoubleValue"); + TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, "MapValueRef::SetDoubleValue"); *reinterpret_cast(data_) = value; } - int64 GetInt64Value() const { - TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, - "MapValueRef::GetInt64Value"); - return *reinterpret_cast(data_); - } - uint64 GetUInt64Value() const { - TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, - "MapValueRef::GetUInt64Value"); - return *reinterpret_cast(data_); - } - int32 GetInt32Value() const { - TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, - "MapValueRef::GetInt32Value"); - return *reinterpret_cast(data_); - } - uint32 GetUInt32Value() const { - TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, - "MapValueRef::GetUInt32Value"); - return *reinterpret_cast(data_); - } - bool GetBoolValue() const { - TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, - "MapValueRef::GetBoolValue"); - return *reinterpret_cast(data_); - } - int GetEnumValue() const { - TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, - "MapValueRef::GetEnumValue"); - return *reinterpret_cast(data_); - } - const string& GetStringValue() const { - TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, - "MapValueRef::GetStringValue"); - return *reinterpret_cast(data_); - } - float GetFloatValue() const { - TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, - "MapValueRef::GetFloatValue"); - return *reinterpret_cast(data_); - } - double GetDoubleValue() const { - TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, - "MapValueRef::GetDoubleValue"); - return *reinterpret_cast(data_); - } - - const Message& GetMessageValue() const { - TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE, - "MapValueRef::GetMessageValue"); - return *reinterpret_cast(data_); - } - Message* MutableMessageValue() { TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE, "MapValueRef::MutableMessageValue"); @@ -660,44 +818,16 @@ class LIBPROTOBUF_EXPORT MapValueRef { } private: - template - friend class internal::MapField; - template - friend class internal::TypeDefinedMapFieldBase; - friend class MapIterator; - friend class internal::GeneratedMessageReflection; friend class internal::DynamicMapField; - void SetType(FieldDescriptor::CppType type) { - type_ = type; - } - - FieldDescriptor::CppType type() const { - if (type_ == 0 || data_ == NULL) { - GOOGLE_LOG(FATAL) - << "Protocol Buffer map usage error:\n" - << "MapValueRef::type MapValueRef is not initialized."; - } - return (FieldDescriptor::CppType)type_; - } - void SetValue(const void* val) { - data_ = const_cast(val); - } - void CopyFrom(const MapValueRef& other) { - type_ = other.type_; - data_ = other.data_; - } // Only used in DynamicMapField void DeleteData() { switch (type_) { -#define HANDLE_TYPE(CPPTYPE, TYPE) \ - case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \ - delete reinterpret_cast(data_); \ - break; \ - } +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + delete reinterpret_cast(data_); \ + break; \ + } HANDLE_TYPE(INT32, int32); HANDLE_TYPE(INT64, int64); HANDLE_TYPE(UINT32, uint32); @@ -705,27 +835,21 @@ class LIBPROTOBUF_EXPORT MapValueRef { HANDLE_TYPE(DOUBLE, double); HANDLE_TYPE(FLOAT, float); HANDLE_TYPE(BOOL, bool); - HANDLE_TYPE(STRING, string); + HANDLE_TYPE(STRING, std::string); HANDLE_TYPE(ENUM, int32); HANDLE_TYPE(MESSAGE, Message); #undef HANDLE_TYPE } } - // data_ point to a map value. MapValueRef does not - // own this value. - void* data_; - // type_ is 0 or a valid FieldDescriptor::CppType. - int type_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapValueRef); }; #undef TYPE_CHECK -class LIBPROTOBUF_EXPORT MapIterator { +class PROTOBUF_EXPORT MapIterator { public: MapIterator(Message* message, const FieldDescriptor* field) { const Reflection* reflection = message->GetReflection(); - map_ = reflection->MapData(message, field); + map_ = reflection->MutableMapData(message, field); key_.SetType(field->message_type()->FindFieldByName("key")->cpp_type()); value_.SetType(field->message_type()->FindFieldByName("value")->cpp_type()); map_->InitializeIterator(this); @@ -735,9 +859,7 @@ class LIBPROTOBUF_EXPORT MapIterator { map_->InitializeIterator(this); map_->CopyIterator(this, other); } - ~MapIterator() { - map_->DeleteIterator(this); - } + ~MapIterator() { map_->DeleteIterator(this); } MapIterator& operator=(const MapIterator& other) { map_ = other.map_; map_->CopyIterator(this, other); @@ -760,12 +882,8 @@ class LIBPROTOBUF_EXPORT MapIterator { map_->IncreaseIterator(this); return *this; } - const MapKey& GetKey() { - return key_; - } - const MapValueRef& GetValueRef() { - return value_; - } + const MapKey& GetKey() { return key_; } + const MapValueRef& GetValueRef() { return value_; } MapValueRef* MutableValueRef() { map_->SetMapDirty(); return &value_; @@ -777,8 +895,7 @@ class LIBPROTOBUF_EXPORT MapIterator { friend class internal::DynamicMapField; template + internal::WireFormatLite::FieldType kValueFieldType> friend class internal::MapField; // reinterpret_cast from heap-allocated Map<...>::iterator*. MapIterator owns @@ -796,40 +913,6 @@ class LIBPROTOBUF_EXPORT MapIterator { } // namespace protobuf } // namespace google -GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START -template<> -struct hash { - size_t - operator()(const google::protobuf::MapKey& map_key) const { - switch (map_key.type()) { - case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: - case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: - case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: - case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: - GOOGLE_LOG(FATAL) << "Unsupported"; - break; - case google::protobuf::FieldDescriptor::CPPTYPE_STRING: - return hash()(map_key.GetStringValue()); - case google::protobuf::FieldDescriptor::CPPTYPE_INT64: - return hash< ::google::protobuf::int64>()(map_key.GetInt64Value()); - case google::protobuf::FieldDescriptor::CPPTYPE_INT32: - return hash< ::google::protobuf::int32>()(map_key.GetInt32Value()); - case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: - return hash< ::google::protobuf::uint64>()(map_key.GetUInt64Value()); - case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: - return hash< ::google::protobuf::uint32>()(map_key.GetUInt32Value()); - case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: - return hash()(map_key.GetBoolValue()); - } - GOOGLE_LOG(FATAL) << "Can't get here."; - return 0; - } - bool - operator()(const google::protobuf::MapKey& map_key1, - const google::protobuf::MapKey& map_key2) const { - return map_key1 < map_key2; - } -}; -GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END +#include #endif // GOOGLE_PROTOBUF_MAP_FIELD_H__ diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h index e317b5ed428ac..8e921708de8f6 100644 --- a/src/google/protobuf/map_field_inl.h +++ b/src/google/protobuf/map_field_inl.h @@ -32,70 +32,72 @@ #define GOOGLE_PROTOBUF_MAP_FIELD_INL_H__ #include -#ifndef _SHARED_PTR_H -#include -#endif +#include #include #include #include +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + namespace google { namespace protobuf { namespace internal { // UnwrapMapKey template -template +template T UnwrapMapKey(const MapKey& map_key); -template<> +template <> inline int32 UnwrapMapKey(const MapKey& map_key) { return map_key.GetInt32Value(); } -template<> +template <> inline uint32 UnwrapMapKey(const MapKey& map_key) { return map_key.GetUInt32Value(); } -template<> +template <> inline int64 UnwrapMapKey(const MapKey& map_key) { return map_key.GetInt64Value(); } -template<> +template <> inline uint64 UnwrapMapKey(const MapKey& map_key) { return map_key.GetUInt64Value(); } -template<> +template <> inline bool UnwrapMapKey(const MapKey& map_key) { return map_key.GetBoolValue(); } -template<> -inline string UnwrapMapKey(const MapKey& map_key) { +template <> +inline std::string UnwrapMapKey(const MapKey& map_key) { return map_key.GetStringValue(); } // SetMapKey template -template +template inline void SetMapKey(MapKey* map_key, const T& value); -template<> +template <> inline void SetMapKey(MapKey* map_key, const int32& value) { map_key->SetInt32Value(value); } -template<> +template <> inline void SetMapKey(MapKey* map_key, const uint32& value) { map_key->SetUInt32Value(value); } -template<> +template <> inline void SetMapKey(MapKey* map_key, const int64& value) { map_key->SetInt64Value(value); } -template<> +template <> inline void SetMapKey(MapKey* map_key, const uint64& value) { map_key->SetUInt64Value(value); } -template<> +template <> inline void SetMapKey(MapKey* map_key, const bool& value) { map_key->SetBoolValue(value); } -template<> -inline void SetMapKey(MapKey* map_key, const string& value) { +template <> +inline void SetMapKey(MapKey* map_key, const std::string& value) { map_key->SetStringValue(value); } @@ -104,7 +106,7 @@ template typename Map::const_iterator& TypeDefinedMapFieldBase::InternalGetIterator( const MapIterator* map_iter) const { - return *reinterpret_cast::const_iterator *>( + return *reinterpret_cast::const_iterator*>( map_iter->iter_); } @@ -120,15 +122,14 @@ void TypeDefinedMapFieldBase::MapEnd(MapIterator* map_iter) const { } template -bool TypeDefinedMapFieldBase::EqualIterator(const MapIterator& a, - const MapIterator& b) - const { +bool TypeDefinedMapFieldBase::EqualIterator( + const MapIterator& a, const MapIterator& b) const { return InternalGetIterator(&a) == InternalGetIterator(&b); } template -void TypeDefinedMapFieldBase::IncreaseIterator(MapIterator* map_iter) - const { +void TypeDefinedMapFieldBase::IncreaseIterator( + MapIterator* map_iter) const { ++InternalGetIterator(map_iter); SetMapIteratorValue(map_iter); } @@ -141,16 +142,15 @@ void TypeDefinedMapFieldBase::InitializeIterator( } template -void TypeDefinedMapFieldBase::DeleteIterator(MapIterator* map_iter) - const { - delete reinterpret_cast::const_iterator *>( +void TypeDefinedMapFieldBase::DeleteIterator( + MapIterator* map_iter) const { + delete reinterpret_cast::const_iterator*>( map_iter->iter_); } template void TypeDefinedMapFieldBase::CopyIterator( - MapIterator* this_iter, - const MapIterator& that_iter) const { + MapIterator* this_iter, const MapIterator& that_iter) const { InternalGetIterator(this_iter) = InternalGetIterator(&that_iter); this_iter->key_.SetType(that_iter.key_.type()); // MapValueRef::type() fails when containing data is null. However, if @@ -164,28 +164,35 @@ void TypeDefinedMapFieldBase::CopyIterator( template -int MapField::size() const { + WireFormatLite::FieldType kValueFieldType> +int MapField::size() const { MapFieldBase::SyncMapWithRepeatedField(); return static_cast(impl_.GetMap().size()); } template -void MapField::Clear() { - MapFieldBase::SyncMapWithRepeatedField(); + WireFormatLite::FieldType kValueFieldType> +void MapField::Clear() { + if (this->MapFieldBase::repeated_field_ != nullptr) { + RepeatedPtrField* repeated_field = + reinterpret_cast*>( + this->MapFieldBase::repeated_field_); + repeated_field->Clear(); + } + impl_.MutableMap()->clear(); + // Data in map and repeated field are both empty, but we can't set status + // CLEAN. Because clear is a generated API, we cannot invalidate previous + // reference to map. MapFieldBase::SetMapDirty(); } template -void MapField::SetMapIteratorValue(MapIterator* map_iter) + WireFormatLite::FieldType kValueFieldType> +void MapField::SetMapIteratorValue(MapIterator* map_iter) const { const Map& map = impl_.GetMap(); typename Map::const_iterator iter = @@ -197,9 +204,9 @@ void MapField -bool MapField::ContainsMapKey(const MapKey& map_key) const { + WireFormatLite::FieldType kValueFieldType> +bool MapField::ContainsMapKey( + const MapKey& map_key) const { const Map& map = impl_.GetMap(); const Key& key = UnwrapMapKey(map_key); typename Map::const_iterator iter = map.find(key); @@ -208,10 +215,10 @@ bool MapField -bool MapField::InsertOrLookupMapValue(const MapKey& map_key, - MapValueRef* val) { + WireFormatLite::FieldType kValueFieldType> +bool MapField::InsertOrLookupMapValue(const MapKey& map_key, + MapValueRef* val) { // Always use mutable map because users may change the map value by // MapValueRef. Map* map = MutableMap(); @@ -229,39 +236,62 @@ bool MapField -bool MapField::DeleteMapValue(const MapKey& map_key) { + WireFormatLite::FieldType kValueFieldType> +bool MapField::LookupMapValue( + const MapKey& map_key, MapValueConstRef* val) const { + const Map& map = GetMap(); + const Key& key = UnwrapMapKey(map_key); + typename Map::const_iterator iter = map.find(key); + if (map.end() == iter) { + return false; + } + // Key is already in the map. Make sure (*map)[key] is not called. + // [] may reorder the map and iterators. + val->SetValue(&(iter->second)); + return true; +} + +template +bool MapField::DeleteMapValue( + const MapKey& map_key) { const Key& key = UnwrapMapKey(map_key); return MutableMap()->erase(key); } template -void MapField::MergeFrom(const MapField& other) { + WireFormatLite::FieldType kValueFieldType> +void MapField::MergeFrom( + const MapFieldBase& other) { MapFieldBase::SyncMapWithRepeatedField(); - other.SyncMapWithRepeatedField(); - impl_.MergeFrom(other.impl_); + const MapField& other_field = static_cast(other); + other_field.SyncMapWithRepeatedField(); + impl_.MergeFrom(other_field.impl_); MapFieldBase::SetMapDirty(); } template -void MapField::Swap(MapField* other) { - std::swap(this->MapFieldBase::repeated_field_, other->repeated_field_); - impl_.Swap(&other->impl_); - std::swap(this->MapFieldBase::state_, other->state_); + WireFormatLite::FieldType kValueFieldType> +void MapField::Swap( + MapFieldBase* other) { + MapField* other_field = down_cast(other); + std::swap(this->MapFieldBase::repeated_field_, other_field->repeated_field_); + impl_.Swap(&other_field->impl_); + // a relaxed swap of the atomic + auto other_state = other_field->state_.load(std::memory_order_relaxed); + auto this_state = this->MapFieldBase::state_.load(std::memory_order_relaxed); + other_field->state_.store(this_state, std::memory_order_relaxed); + this->MapFieldBase::state_.store(other_state, std::memory_order_relaxed); } template -void MapField::SyncRepeatedFieldWithMapNoLock() const { + WireFormatLite::FieldType kValueFieldType> +void MapField::SyncRepeatedFieldWithMapNoLock() const { if (this->MapFieldBase::repeated_field_ == NULL) { if (this->MapFieldBase::arena_ == NULL) { this->MapFieldBase::repeated_field_ = new RepeatedPtrField(); @@ -284,8 +314,8 @@ void MapField::const_iterator it = map.begin(); - it != map.end(); ++it) { + for (typename Map::const_iterator it = map.begin(); it != map.end(); + ++it) { EntryType* new_entry = down_cast(default_entry->New(this->MapFieldBase::arena_)); repeated_field->AddAllocated(new_entry); @@ -296,9 +326,9 @@ void MapField -void MapField::SyncMapWithRepeatedFieldNoLock() const { + WireFormatLite::FieldType kValueFieldType> +void MapField::SyncMapWithRepeatedFieldNoLock() const { Map* map = const_cast(this)->impl_.MutableMap(); RepeatedPtrField* repeated_field = reinterpret_cast*>( @@ -306,7 +336,8 @@ void MapFieldMapFieldBase::repeated_field_ != NULL); map->clear(); for (typename RepeatedPtrField::iterator it = - repeated_field->begin(); it != repeated_field->end(); ++it) { + repeated_field->begin(); + it != repeated_field->end(); ++it) { // Cast is needed because Map's api and internal storage is different when // value is enum. For enum, we cannot cast an int to enum. Thus, we have to // copy value. For other types, they have same exposed api type and internal @@ -318,24 +349,19 @@ void MapField -size_t MapField::SpaceUsedExcludingSelfNoLock() const { + WireFormatLite::FieldType kValueFieldType> +size_t MapField::SpaceUsedExcludingSelfNoLock() const { size_t size = 0; if (this->MapFieldBase::repeated_field_ != NULL) { size += this->MapFieldBase::repeated_field_->SpaceUsedExcludingSelfLong(); } - Map* map = const_cast(this)->impl_.MutableMap(); - size += sizeof(*map); - for (typename Map::iterator it = map->begin(); it != map->end(); - ++it) { - size += KeyTypeHandler::SpaceUsedInMapLong(it->first); - size += ValueTypeHandler::SpaceUsedInMapLong(it->second); - } + size += impl_.GetMap().SpaceUsedExcludingSelfLong(); + return size; } } // namespace internal } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_MAP_FIELD_INL_H__ diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h index 12d4e6bae11c3..665cb0eebe871 100644 --- a/src/google/protobuf/map_field_lite.h +++ b/src/google/protobuf/map_field_lite.h @@ -31,20 +31,30 @@ #ifndef GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ #define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ +#include +#include +#include #include #include +#include #include +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + namespace google { namespace protobuf { namespace internal { // This class provides access to map field using generated api. It is used for -// internal generated message implentation only. Users should never use this +// internal generated message implementation only. Users should never use this // directly. template + WireFormatLite::FieldType value_wire_type> class MapFieldLite { // Define message type for internal repeated field. typedef Derived EntryType; @@ -53,11 +63,9 @@ class MapFieldLite { typedef Map MapType; typedef EntryType EntryTypeTrait; - MapFieldLite() : arena_(NULL) { SetDefaultEnumValue(); } + constexpr MapFieldLite() {} - explicit MapFieldLite(Arena* arena) : arena_(arena), map_(arena) { - SetDefaultEnumValue(); - } + explicit MapFieldLite(Arena* arena) : map_(arena) {} // Accessors const Map& GetMap() const { return map_; } @@ -74,46 +82,77 @@ class MapFieldLite { } void Swap(MapFieldLite* other) { map_.swap(other->map_); } - // Set default enum value only for proto2 map field whose value is enum type. - void SetDefaultEnumValue() { - MutableMap()->SetDefaultEnumValue(default_enum_value); - } - // Used in the implementation of parsing. Caller should take the ownership iff // arena_ is NULL. EntryType* NewEntry() const { - if (arena_ == NULL) { - return new EntryType(); - } else { - return Arena::CreateMessage(arena_); - } + return Arena::CreateMessage(map_.arena()); } // Used in the implementation of serializing enum value type. Caller should // take the ownership iff arena_ is NULL. EntryType* NewEnumEntryWrapper(const Key& key, const T t) const { - return EntryType::EnumWrap(key, t, arena_); + return EntryType::EnumWrap(key, t, map_.arena_); } // Used in the implementation of serializing other value types. Caller should // take the ownership iff arena_ is NULL. EntryType* NewEntryWrapper(const Key& key, const T& t) const { - return EntryType::Wrap(key, t, arena_); + return EntryType::Wrap(key, t, map_.arena_); + } + + const char* _InternalParse(const char* ptr, ParseContext* ctx) { + typename Derived::template Parser> parser(this); + return parser._InternalParse(ptr, ctx); + } + + template + const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx, + bool (*is_valid)(int), uint32 field_num, + InternalMetadata* metadata) { + typename Derived::template Parser> parser(this); + return parser.template ParseWithEnumValidation( + ptr, ctx, is_valid, field_num, metadata); } private: typedef void DestructorSkippable_; - Arena* arena_; Map map_; - friend class ::google::protobuf::Arena; + friend class ::PROTOBUF_NAMESPACE_ID::Arena; +}; + +template +struct EnumParseWrapper { + const char* _InternalParse(const char* ptr, ParseContext* ctx) { + return map_field->template ParseWithEnumValidation( + ptr, ctx, is_valid, field_num, metadata); + } + T* map_field; + bool (*is_valid)(int); + uint32 field_num; + InternalMetadata* metadata; }; +// Helper function because the typenames of maps are horrendous to print. This +// leverages compiler type deduction, to keep all type data out of the +// generated code +template +EnumParseWrapper InitEnumParseWrapper( + T* map_field, bool (*is_valid)(int), uint32 field_num, + InternalMetadata* metadata) { + return EnumParseWrapper{map_field, is_valid, field_num, + metadata}; +} + // True if IsInitialized() is true for value field in all elements of t. T is // expected to be message. It's useful to have this helper here to keep the // protobuf compiler from ever having to emit loops in IsInitialized() methods. // We want the C++ compiler to inline this or not as it sees fit. -template -bool AllAreInitialized(const Map& t) { +template +bool AllAreInitialized(const MapFieldLite& field) { + const auto& t = field.GetMap(); for (typename Map::const_iterator it = t.begin(); it != t.end(); ++it) { if (!it->second.IsInitialized()) return false; @@ -121,8 +160,24 @@ bool AllAreInitialized(const Map& t) { return true; } +template +struct MapEntryToMapField : MapEntryToMapField {}; + +template +struct MapEntryToMapField< + MapEntryLite> { + typedef MapFieldLite< + MapEntryLite, Key, Value, + kKeyFieldType, kValueFieldType> + MapFieldType; +}; + } // namespace internal } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc index 8617a366af30c..dd70e989d0e14 100644 --- a/src/google/protobuf/map_field_test.cc +++ b/src/google/protobuf/map_field_test.cc @@ -30,25 +30,25 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif +#include #include #include -#include -#include #include -#include #include +#include #include +#include +#include #include #include #include -#include #include -namespace google { +// Must be included last. +#include + +namespace google { namespace protobuf { namespace internal { @@ -61,49 +61,52 @@ class MapFieldBaseStub : public MapFieldBase { typedef void DestructorSkippable_; MapFieldBaseStub() {} explicit MapFieldBaseStub(Arena* arena) : MapFieldBase(arena) {} - void SyncRepeatedFieldWithMap() const { - MapFieldBase::SyncRepeatedFieldWithMap(); + // Get underlined repeated field without synchronizing map. + RepeatedPtrField* InternalRepeatedField() { return repeated_field_; } + bool IsMapClean() { + return state_.load(std::memory_order_relaxed) != STATE_MODIFIED_MAP; } - void SyncMapWithRepeatedField() const { - MapFieldBase::SyncMapWithRepeatedField(); + bool IsRepeatedClean() { + return state_.load(std::memory_order_relaxed) != STATE_MODIFIED_REPEATED; } - // Get underlined repeated field without synchronizing map. - RepeatedPtrField* InternalRepeatedField() { - return repeated_field_; + void SetMapDirty() { + state_.store(STATE_MODIFIED_MAP, std::memory_order_relaxed); } - bool IsMapClean() { return state_ != 0; } - bool IsRepeatedClean() { return state_ != 1; } - void SetMapDirty() { state_ = 0; } - void SetRepeatedDirty() { state_ = 1; } - bool ContainsMapKey(const MapKey& map_key) const { - return false; + void SetRepeatedDirty() { + state_.store(STATE_MODIFIED_REPEATED, std::memory_order_relaxed); } - bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) { + bool ContainsMapKey(const MapKey& map_key) const override { return false; } + bool InsertOrLookupMapValue(const MapKey& map_key, + MapValueRef* val) override { return false; } - bool DeleteMapValue(const MapKey& map_key) { + bool LookupMapValue(const MapKey& map_key, + MapValueConstRef* val) const override { return false; } - bool EqualIterator(const MapIterator& a, const MapIterator& b) const { + bool DeleteMapValue(const MapKey& map_key) override { return false; } + bool EqualIterator(const MapIterator& a, + const MapIterator& b) const override { return false; } - int size() const { return 0; } - void MapBegin(MapIterator* map_iter) const {} - void MapEnd(MapIterator* map_iter) const {} - void InitializeIterator(MapIterator* map_iter) const {} - void DeleteIterator(MapIterator* map_iter) const {} + int size() const override { return 0; } + void Clear() override {} + void MapBegin(MapIterator* map_iter) const override {} + void MapEnd(MapIterator* map_iter) const override {} + void MergeFrom(const MapFieldBase& other) override {} + void Swap(MapFieldBase* other) override {} + void InitializeIterator(MapIterator* map_iter) const override {} + void DeleteIterator(MapIterator* map_iter) const override {} void CopyIterator(MapIterator* this_iterator, - const MapIterator& other_iterator) const {} - void IncreaseIterator(MapIterator* map_iter) const {} - void SetDefaultMessageEntry(const Message* message) const {} - const Message* GetDefaultMessageEntry() const { return NULL; } + const MapIterator& other_iterator) const override {} + void IncreaseIterator(MapIterator* map_iter) const override {} }; class MapFieldBasePrimitiveTest : public ::testing::Test { protected: - typedef unittest::TestMap::TestMap_MapInt32Int32Entry EntryType; + typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType; typedef MapField + WireFormatLite::TYPE_INT32> MapFieldType; MapFieldBasePrimitiveTest() { @@ -111,8 +114,8 @@ class MapFieldBasePrimitiveTest : public ::testing::Test { map_descriptor_ = unittest::TestMap::descriptor() ->FindFieldByName("map_int32_int32") ->message_type(); - key_descriptor_ = map_descriptor_->FindFieldByName("key"); - value_descriptor_ = map_descriptor_->FindFieldByName("value"); + key_descriptor_ = map_descriptor_->map_key(); + value_descriptor_ = map_descriptor_->map_value(); // Build map field map_field_.reset(new MapFieldType); @@ -124,7 +127,7 @@ class MapFieldBasePrimitiveTest : public ::testing::Test { EXPECT_EQ(2, map_->size()); } - google::protobuf::scoped_ptr map_field_; + std::unique_ptr map_field_; MapFieldBase* map_field_base_; Map* map_; const Descriptor* map_descriptor_; @@ -202,13 +205,12 @@ namespace { enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY }; } // anonymous namespace -class MapFieldStateTest - : public testing::TestWithParam { +class MapFieldStateTest : public testing::TestWithParam { public: protected: - typedef unittest::TestMap::TestMap_MapInt32Int32Entry EntryType; + typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType; typedef MapField + WireFormatLite::TYPE_INT32> MapFieldType; MapFieldStateTest() : state_(GetParam()) { // Build map field @@ -287,17 +289,21 @@ class MapFieldStateTest if (is_repeated_null) { EXPECT_TRUE(repeated_field == NULL); } else { - EXPECT_EQ(repeated_size, repeated_field->size()); + if (repeated_field == nullptr) { + EXPECT_EQ(repeated_size, 0); + } else { + EXPECT_EQ(repeated_size, repeated_field->size()); + } } } - google::protobuf::scoped_ptr map_field_; + std::unique_ptr map_field_; MapFieldBase* map_field_base_; State state_; }; -INSTANTIATE_TEST_CASE_P(MapFieldStateTestInstance, MapFieldStateTest, - ::testing::Values(CLEAN, MAP_DIRTY, REPEATED_DIRTY)); +INSTANTIATE_TEST_SUITE_P(MapFieldStateTestInstance, MapFieldStateTest, + ::testing::Values(CLEAN, MAP_DIRTY, REPEATED_DIRTY)); TEST_P(MapFieldStateTest, GetMap) { map_field_->GetMap(); @@ -434,11 +440,7 @@ TEST_P(MapFieldStateTest, SwapRepeatedDirty) { TEST_P(MapFieldStateTest, Clear) { map_field_->Clear(); - if (state_ != MAP_DIRTY) { - Expect(map_field_.get(), MAP_DIRTY, 0, 1, false); - } else { - Expect(map_field_.get(), MAP_DIRTY, 0, 0, true); - } + Expect(map_field_.get(), MAP_DIRTY, 0, 0, false); } TEST_P(MapFieldStateTest, SpaceUsedExcludingSelf) { @@ -479,7 +481,25 @@ TEST_P(MapFieldStateTest, MutableMapField) { } } +class MyMapField + : public MapField { + public: + constexpr MyMapField() + : MyMapField::MapField(internal::ConstantInitialized{}) {} +}; + +TEST(MapFieldTest, ConstInit) { + // This tests that `MapField` and all its base classes can be constant + // initialized. + PROTOBUF_CONSTINIT static MyMapField field; // NOLINT + EXPECT_EQ(field.size(), 0); +} + } // namespace internal } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/map_lite_test_util.h b/src/google/protobuf/map_lite_test_util.h index 66dedde5db36a..573de7b2854ed 100644 --- a/src/google/protobuf/map_lite_test_util.h +++ b/src/google/protobuf/map_lite_test_util.h @@ -75,6 +75,6 @@ class MapLiteTestUtil { }; } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__ diff --git a/src/google/protobuf/map_lite_unittest.proto b/src/google/protobuf/map_lite_unittest.proto index 0135fff305434..cc00deec25d18 100644 --- a/src/google/protobuf/map_lite_unittest.proto +++ b/src/google/protobuf/map_lite_unittest.proto @@ -30,55 +30,52 @@ syntax = "proto2"; -option cc_enable_arenas = true; -option optimize_for = LITE_RUNTIME; +package protobuf_unittest; import "google/protobuf/unittest_lite.proto"; -import "google/protobuf/unittest_no_arena_lite.proto"; -package protobuf_unittest; +option cc_enable_arenas = true; +option optimize_for = LITE_RUNTIME; message TestMapLite { - map map_int32_int32 = 1; - map map_int64_int64 = 2; - map map_uint32_uint32 = 3; - map map_uint64_uint64 = 4; - map map_sint32_sint32 = 5; - map map_sint64_sint64 = 6; - map map_fixed32_fixed32 = 7; - map map_fixed64_fixed64 = 8; + map map_int32_int32 = 1; + map map_int64_int64 = 2; + map map_uint32_uint32 = 3; + map map_uint64_uint64 = 4; + map map_sint32_sint32 = 5; + map map_sint64_sint64 = 6; + map map_fixed32_fixed32 = 7; + map map_fixed64_fixed64 = 8; map map_sfixed32_sfixed32 = 9; map map_sfixed64_sfixed64 = 10; - map map_int32_float = 11; - map map_int32_double = 12; - map map_bool_bool = 13; - map map_string_string = 14; - map map_int32_bytes = 15; - map map_int32_enum = 16; - map map_int32_foreign_message = 17; + map map_int32_float = 11; + map map_int32_double = 12; + map map_bool_bool = 13; + map map_string_string = 14; + map map_int32_bytes = 15; + map map_int32_enum = 16; + map map_int32_foreign_message = 17; map teboring = 18; } message TestArenaMapLite { - map map_int32_int32 = 1; - map map_int64_int64 = 2; - map map_uint32_uint32 = 3; - map map_uint64_uint64 = 4; - map map_sint32_sint32 = 5; - map map_sint64_sint64 = 6; - map map_fixed32_fixed32 = 7; - map map_fixed64_fixed64 = 8; + map map_int32_int32 = 1; + map map_int64_int64 = 2; + map map_uint32_uint32 = 3; + map map_uint64_uint64 = 4; + map map_sint32_sint32 = 5; + map map_sint64_sint64 = 6; + map map_fixed32_fixed32 = 7; + map map_fixed64_fixed64 = 8; map map_sfixed32_sfixed32 = 9; map map_sfixed64_sfixed64 = 10; - map map_int32_float = 11; - map map_int32_double = 12; - map map_bool_bool = 13; - map map_string_string = 14; - map map_int32_bytes = 15; - map map_int32_enum = 16; - map map_int32_foreign_message = 17; - map - map_int32_foreign_message_no_arena = 18; + map map_int32_float = 11; + map map_int32_double = 12; + map map_bool_bool = 13; + map map_string_string = 14; + map map_int32_bytes = 15; + map map_int32_enum = 16; + map map_int32_foreign_message = 17; } // Test embedded message with required fields @@ -107,9 +104,9 @@ enum Proto2MapEnumLite { } enum Proto2MapEnumPlusExtraLite { - E_PROTO2_MAP_ENUM_FOO_LITE = 0; - E_PROTO2_MAP_ENUM_BAR_LITE = 1; - E_PROTO2_MAP_ENUM_BAZ_LITE = 2; + E_PROTO2_MAP_ENUM_FOO_LITE = 0; + E_PROTO2_MAP_ENUM_BAR_LITE = 1; + E_PROTO2_MAP_ENUM_BAZ_LITE = 2; E_PROTO2_MAP_ENUM_EXTRA_LITE = 3; } diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc index 960589ce4f521..768858f76638e 100644 --- a/src/google/protobuf/map_test.cc +++ b/src/google/protobuf/map_test.cc @@ -37,17 +37,15 @@ #endif // _WIN32 #include -#include #include #include -#ifndef _SHARED_PTR_H -#include -#endif +#include #include #include +#include +#include #include -#include #include #include #include @@ -57,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -72,28 +71,34 @@ #include #include #include -#include #include #include -#include #include #include #include +#include +#include -namespace google { -using google::protobuf::unittest::ForeignMessage; -using google::protobuf::unittest::TestAllTypes; -using google::protobuf::unittest::TestMap; -using google::protobuf::unittest::TestRecursiveMapMessage; +// Must be included last. +#include +namespace google { namespace protobuf { + +using unittest::ForeignMessage; +using unittest::TestAllTypes; +using unittest::TestMap; +using unittest::TestRecursiveMapMessage; + namespace internal { void MapTestForceDeterministic() { - ::google::protobuf::io::CodedOutputStream::SetDefaultSerializationDeterministic(); + io::CodedOutputStream::SetDefaultSerializationDeterministic(); } +namespace { + // Map API Test ===================================================== class MapImplTest : public ::testing::Test { @@ -125,15 +130,16 @@ class MapImplTest : public ::testing::Test { // Test map size is correct. EXPECT_EQ(value, map_[key]); EXPECT_EQ(1, map_.count(key)); + EXPECT_TRUE(map_.contains(key)); // Check mutable at and find work correctly. EXPECT_EQ(value, map_.at(key)); Map::iterator it = map_.find(key); - // interator dereferenceable - EXPECT_EQ(key, (*it).first); + // iterator dereferenceable + EXPECT_EQ(key, (*it).first); EXPECT_EQ(value, (*it).second); - EXPECT_EQ(key, it->first); + EXPECT_EQ(key, it->first); EXPECT_EQ(value, it->second); // iterator mutable @@ -158,7 +164,7 @@ class MapImplTest : public ::testing::Test { EXPECT_EQ(value, const_map_.at(key)); Map::const_iterator const_it = const_map_.find(key); - // interator dereferenceable + // iterator dereferenceable EXPECT_EQ(key, (*const_it).first); EXPECT_EQ(value, (*const_it).second); EXPECT_EQ(key, const_it->first); @@ -170,7 +176,7 @@ class MapImplTest : public ::testing::Test { EXPECT_EQ(value, const_it_copy->second); } - google::protobuf::scoped_ptr > map_ptr_; + std::unique_ptr > map_ptr_; Map& map_; const Map& const_map_; }; @@ -189,6 +195,62 @@ TEST_F(MapImplTest, OperatorBracket) { ExpectSingleElement(key, value2); } +struct MoveTestKey { + MoveTestKey(int data, int* copies) : data(data), copies(copies) {} + + MoveTestKey(const MoveTestKey& other) + : data(other.data), copies(other.copies) { + ++*copies; + } + + MoveTestKey(MoveTestKey&& other) noexcept + : data(other.data), copies(other.copies) {} + + friend bool operator==(const MoveTestKey& lhs, const MoveTestKey& rhs) { + return lhs.data == rhs.data; + } + friend bool operator<(const MoveTestKey& lhs, const MoveTestKey& rhs) { + return lhs.data < rhs.data; + } + + int data; + int* copies; +}; + +} // namespace +} // namespace internal +} // namespace protobuf +} // namespace google + +namespace std { + +template <> // NOLINT +struct hash { + size_t operator()(const google::protobuf::internal::MoveTestKey& key) const { + return hash{}(key.data); + } +}; +} // namespace std + +namespace google { +namespace protobuf { +namespace internal { +namespace { + +TEST_F(MapImplTest, OperatorBracketRValue) { + Arena arena; + for (Arena* arena_to_use : {&arena, static_cast(nullptr)}) { + int copies = 0; + Map map(arena_to_use); + MoveTestKey key1(1, &copies); + EXPECT_EQ(copies, 0); + map[key1] = 0; + EXPECT_EQ(copies, 1); + map[MoveTestKey(2, &copies)] = 2; + EXPECT_EQ(copies, 1); + } +} + TEST_F(MapImplTest, OperatorBracketNonExist) { int32 key = 0; int32 default_value = 0; @@ -229,9 +291,10 @@ TEST_F(MapImplTest, UsageErrors) { " Actual : int64"); MapValueRef value; - EXPECT_DEATH(value.SetFloatValue(0.1), - "Protocol Buffer map usage error:\n" - "MapValueRef::type MapValueRef is not initialized."); + EXPECT_DEATH( + value.SetFloatValue(0.1), + "Protocol Buffer map usage error:\n" + "MapValue[Const]*Ref::type MapValue[Const]*Ref is not initialized."); } #endif // PROTOBUF_HAS_DEATH_TEST @@ -243,8 +306,12 @@ TEST_F(MapImplTest, MapKeyAssignment) { EXPECT_EQ("abc", to.GetStringValue()); } -TEST_F(MapImplTest, CountNonExist) { - EXPECT_EQ(0, map_.count(0)); +TEST_F(MapImplTest, CountNonExist) { EXPECT_EQ(0, map_.count(0)); } + +TEST_F(MapImplTest, ContainNotExist) { EXPECT_FALSE(map_.contains(0)); } + +TEST_F(MapImplTest, ImmutableContainNotExist) { + EXPECT_FALSE(const_map_.contains(0)); } TEST_F(MapImplTest, MutableFindNonExist) { @@ -312,8 +379,8 @@ static int64 median(Iterator i0, Iterator i1) { } static int64 Now() { - return google::protobuf::util::TimeUtil::TimestampToNanoseconds( - google::protobuf::util::TimeUtil::GetCurrentTime()); + return util::TimeUtil::TimestampToNanoseconds( + util::TimeUtil::GetCurrentTime()); } // Arbitrary odd integers for creating test data. @@ -424,8 +491,7 @@ TEST_F(MapImplTest, CopyIteratorStressTest) { } template -static void TestValidityForAllKeysExcept(int key_to_avoid, - const T& check_map, +static void TestValidityForAllKeysExcept(int key_to_avoid, const T& check_map, const U& map) { typedef typename U::value_type value_type; // a key-value pair for (typename U::const_iterator it = map.begin(); it != map.end(); ++it) { @@ -457,7 +523,8 @@ template static void TestOldVersusNewIterator(int skip, Map* m) { const int initial_size = m->size(); IteratorType it = m->begin(); - for (int i = 0; i < skip && it != m->end(); it++, i++) {} + for (int i = 0; i < skip && it != m->end(); it++, i++) { + } if (it == m->end()) return; const IteratorType old = it; GOOGLE_LOG(INFO) << "skip=" << skip << ", old->first=" << old->first; @@ -508,8 +575,8 @@ static void StressTestIterators(int n) { ASSERT_EQ(n, m.size()); // Create maps of pointers and iterators. // These should remain valid even if we modify m. - hash_map::value_type*> mp(n); - hash_map::iterator> mi(n); + std::unordered_map::value_type*> mp(n); + std::unordered_map::iterator> mi(n); for (Map::iterator it = m.begin(); it != m.end(); ++it) { mp[it->first] = &*it; mi[it->first] = it; @@ -558,7 +625,7 @@ TEST_F(MapImplTest, IteratorInvalidation) { #endif std::set s; int n = kMaxSizeToTest; - int frog = k1 + n; + unsigned int frog = k1 + n; while (n > 1 && s.size() < 25) { s.insert(n); n = static_cast(n * 100 / (101.0 + (frog & 63))); @@ -616,16 +683,13 @@ TEST_F(MapImplTest, IteratorConstness) { } bool IsForwardIteratorHelper(std::forward_iterator_tag /*tag*/) { return true; } -template -bool IsForwardIteratorHelper(T /*t*/) { - return false; -} TEST_F(MapImplTest, IteratorCategory) { EXPECT_TRUE(IsForwardIteratorHelper( std::iterator_traits::iterator>::iterator_category())); - EXPECT_TRUE(IsForwardIteratorHelper(std::iterator_traits< - Map::const_iterator>::iterator_category())); + EXPECT_TRUE(IsForwardIteratorHelper( + std::iterator_traits< + Map::const_iterator>::iterator_category())); } TEST_F(MapImplTest, InsertSingle) { @@ -676,6 +740,14 @@ TEST_F(MapImplTest, InsertByIterator) { ExpectElements(map1); } +TEST_F(MapImplTest, InsertByInitializerList) { + map_.insert({{1, 100}, {2, 200}}); + ExpectElements({{1, 100}, {2, 200}}); + + map_.insert({{2, 201}, {3, 301}}); + ExpectElements({{1, 100}, {2, 200}, {3, 301}}); +} + TEST_F(MapImplTest, EraseSingleByKey) { int32 key = 0; int32 value = 100; @@ -863,7 +935,7 @@ TEST_F(MapImplTest, Assigner) { EXPECT_TRUE(other.find(key_other) == other.end()); // Self assign - other = other; + other = *&other; // Avoid -Wself-assign. EXPECT_EQ(2, other.size()); EXPECT_EQ(value1, other.at(key1)); EXPECT_EQ(value2, other.at(key2)); @@ -890,8 +962,8 @@ TEST_F(MapImplTest, EqualRange) { int key = 100, key_missing = 101; map_[key] = 100; - std::pair::iterator, - google::protobuf::Map::iterator> range = map_.equal_range(key); + std::pair::iterator, Map::iterator> range = + map_.equal_range(key); EXPECT_TRUE(map_.find(key) == range.first); EXPECT_TRUE(++map_.find(key) == range.second); @@ -899,9 +971,9 @@ TEST_F(MapImplTest, EqualRange) { EXPECT_TRUE(map_.end() == range.first); EXPECT_TRUE(map_.end() == range.second); - std::pair::const_iterator, - google::protobuf::Map::const_iterator> const_range = - const_map_.equal_range(key); + std::pair::const_iterator, + Map::const_iterator> + const_range = const_map_.equal_range(key); EXPECT_TRUE(const_map_.find(key) == const_range.first); EXPECT_TRUE(++const_map_.find(key) == const_range.second); @@ -931,11 +1003,10 @@ TEST_F(MapImplTest, SwapBasic) { another[9398] = 41999; another[8070] = 42056; another.swap(map_); - EXPECT_THAT(another, testing::UnorderedElementsAre( - testing::Pair(9398, 41999))); - EXPECT_THAT(map_, testing::UnorderedElementsAre( - testing::Pair(8070, 42056), - testing::Pair(9398, 41999))); + EXPECT_THAT(another, + testing::UnorderedElementsAre(testing::Pair(9398, 41999))); + EXPECT_THAT(map_, testing::UnorderedElementsAre(testing::Pair(8070, 42056), + testing::Pair(9398, 41999))); } TEST_F(MapImplTest, SwapArena) { @@ -948,23 +1019,18 @@ TEST_F(MapImplTest, SwapArena) { m2[10244] = 10247; m2[8070] = 42056; m1.swap(map_); - EXPECT_THAT(m1, testing::UnorderedElementsAre( - testing::Pair(9398, 41999))); - EXPECT_THAT(map_, testing::UnorderedElementsAre( - testing::Pair(8070, 42056), - testing::Pair(9398, 41999))); + EXPECT_THAT(m1, testing::UnorderedElementsAre(testing::Pair(9398, 41999))); + EXPECT_THAT(map_, testing::UnorderedElementsAre(testing::Pair(8070, 42056), + testing::Pair(9398, 41999))); m2.swap(m1); - EXPECT_THAT(m1, testing::UnorderedElementsAre( - testing::Pair(8070, 42056), - testing::Pair(10244, 10247))); - EXPECT_THAT(m2, testing::UnorderedElementsAre( - testing::Pair(9398, 41999))); + EXPECT_THAT(m1, testing::UnorderedElementsAre(testing::Pair(8070, 42056), + testing::Pair(10244, 10247))); + EXPECT_THAT(m2, testing::UnorderedElementsAre(testing::Pair(9398, 41999))); } TEST_F(MapImplTest, CopyAssignMapIterator) { TestMap message; - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); reflection_tester.SetMapFieldsViaMapReflection(&message); MapIterator it1 = reflection_tester.MapBegin(&message, "map_int32_int32"); MapIterator it2 = reflection_tester.MapEnd(&message, "map_int32_int32"); @@ -972,24 +1038,169 @@ TEST_F(MapImplTest, CopyAssignMapIterator) { EXPECT_EQ(it1.GetKey().GetInt32Value(), it2.GetKey().GetInt32Value()); } -// Map Field Reflection Test ======================================== +TEST_F(MapImplTest, SpaceUsed) { + constexpr size_t kMinCap = 8; + + Map m; + // An newly constructed map should have no space used. + EXPECT_EQ(m.SpaceUsedExcludingSelfLong(), 0); + + size_t capacity = kMinCap; + for (int i = 0; i < 100; ++i) { + m[i]; + static constexpr double kMaxLoadFactor = .75; + if (m.size() >= capacity * kMaxLoadFactor) { + capacity *= 2; + } + EXPECT_EQ(m.SpaceUsedExcludingSelfLong(), + sizeof(void*) * capacity + + m.size() * sizeof(std::pair, void*>)); + } + + // Test string, and non-scalar keys. + Map m2; + std::string str = "Some arbitrarily large string"; + m2[str] = 1; + EXPECT_EQ(m2.SpaceUsedExcludingSelfLong(), + sizeof(void*) * kMinCap + + sizeof(std::pair, void*>) + + internal::StringSpaceUsedExcludingSelfLong(str)); + + // Test messages, and non-scalar values. + Map m3; + m3[0].set_optional_string(str); + EXPECT_EQ(m3.SpaceUsedExcludingSelfLong(), + sizeof(void*) * kMinCap + + sizeof(std::pair, void*>) + + m3[0].SpaceUsedLong() - sizeof(m3[0])); +} + +// Attempts to verify that a map with keys a and b has a random ordering. This +// function returns true if it succeeds in observing both possible orderings. +bool MapOrderingIsRandom(int a, int b) { + bool saw_a_first = false; + bool saw_b_first = false; + + for (int i = 0; i < 50; ++i) { + Map m; + m[a] = 0; + m[b] = 0; + int32 first_element = m.begin()->first; + if (first_element == a) saw_a_first = true; + if (first_element == b) saw_b_first = true; + if (saw_a_first && saw_b_first) { + return true; + } + } -static int Func(int i, int j) { - return i * j; + return false; } -static string StrFunc(int i, int j) { - string str; - SStringPrintf(&str, "%d", Func(i, j)); - return str; +// This test verifies that the iteration order is reasonably random even for +// small maps. Currently we only have sufficient randomness for debug builds and +// builds where we can use the RDTSC instruction, so we only test for those +// builds. +#if defined(__x86_64__) && defined(__GNUC__) && \ + !defined(GOOGLE_PROTOBUF_NO_RDTSC) +TEST_F(MapImplTest, RandomOrdering) { + for (int i = 0; i < 10; ++i) { + for (int j = i + 1; j < 10; ++j) { + EXPECT_TRUE(MapOrderingIsRandom(i, j)) + << "Map with keys " << i << " and " << j + << " has deterministic ordering"; + } + } } +#endif + +template +void TestTransparent(const Key& key, const Key& miss_key) { + Map m; + const auto& cm = m; + + m.insert({"ABC", 1}); + + const auto abc_it = m.begin(); + + m.insert({"DEF", 2}); + + using testing::Pair; + using testing::UnorderedElementsAre; + + EXPECT_EQ(m.at(key), 1); + EXPECT_EQ(cm.at(key), 1); + +#ifdef PROTOBUF_HAS_DEATH_TEST + EXPECT_DEATH(m.at(miss_key), ""); + EXPECT_DEATH(cm.at(miss_key), ""); +#endif // PROTOBUF_HAS_DEATH_TEST + + EXPECT_EQ(m.count(key), 1); + EXPECT_EQ(cm.count(key), 1); + EXPECT_EQ(m.count(miss_key), 0); + EXPECT_EQ(cm.count(miss_key), 0); + + EXPECT_EQ(m.find(key), abc_it); + EXPECT_EQ(cm.find(key), abc_it); + EXPECT_EQ(m.find(miss_key), m.end()); + EXPECT_EQ(cm.find(miss_key), cm.end()); + + EXPECT_TRUE(m.contains(key)); + EXPECT_TRUE(cm.contains(key)); + EXPECT_FALSE(m.contains(miss_key)); + EXPECT_FALSE(cm.contains(miss_key)); + + EXPECT_THAT(m.equal_range(key), Pair(abc_it, std::next(abc_it))); + EXPECT_THAT(cm.equal_range(key), Pair(abc_it, std::next(abc_it))); + EXPECT_THAT(m.equal_range(miss_key), Pair(m.end(), m.end())); + EXPECT_THAT(cm.equal_range(miss_key), Pair(m.end(), m.end())); + + EXPECT_THAT(m, UnorderedElementsAre(Pair("ABC", 1), Pair("DEF", 2))); + EXPECT_EQ(m.erase(key), 1); + EXPECT_THAT(m, UnorderedElementsAre(Pair("DEF", 2))); + EXPECT_EQ(m.erase(key), 0); + EXPECT_EQ(m.erase(miss_key), 0); + EXPECT_THAT(m, UnorderedElementsAre(Pair("DEF", 2))); + + m[key]; + EXPECT_THAT(m, UnorderedElementsAre(Pair("ABC", 0), Pair("DEF", 2))); + m[key] = 1; + EXPECT_THAT(m, UnorderedElementsAre(Pair("ABC", 1), Pair("DEF", 2))); +} + +TEST_F(MapImplTest, TransparentLookupForString) { + TestTransparent("ABC", "LKJ"); + TestTransparent(std::string("ABC"), std::string("LKJ")); +#if defined(__cpp_lib_string_view) + TestTransparent(std::string_view("ABC"), std::string_view("LKJ")); +#endif // defined(__cpp_lib_string_view) -static int Int(const string& value) { + // std::reference_wrapper + std::string abc = "ABC", lkj = "LKJ"; + TestTransparent(std::ref(abc), std::ref(lkj)); + TestTransparent(std::cref(abc), std::cref(lkj)); +} + +TEST_F(MapImplTest, ConstInit) { + PROTOBUF_CONSTINIT static Map map; // NOLINT + EXPECT_TRUE(map.empty()); +} + +// Map Field Reflection Test ======================================== + +static int Func(int i, int j) { return i * j; } + +static std::string StrFunc(int i, int j) { return StrCat(Func(i, j)); } + +static int Int(const std::string& value) { int result = 0; std::istringstream(value) >> result; return result; } +} // namespace + +// This class is a friend, so no anonymous namespace. class MapFieldReflectionTest : public testing::Test { protected: typedef FieldDescriptor FD; @@ -1000,6 +1211,8 @@ class MapFieldReflectionTest : public testing::Test { } }; +namespace { + TEST_F(MapFieldReflectionTest, RegularFields) { TestMap message; const Reflection* refl = message.GetReflection(); @@ -1007,7 +1220,8 @@ TEST_F(MapFieldReflectionTest, RegularFields) { Map* map_int32_int32 = message.mutable_map_int32_int32(); Map* map_int32_double = message.mutable_map_int32_double(); - Map* map_string_string = message.mutable_map_string_string(); + Map* map_string_string = + message.mutable_map_string_string(); Map* map_int32_foreign_message = message.mutable_map_int32_foreign_message(); @@ -1052,10 +1266,8 @@ TEST_F(MapFieldReflectionTest, RegularFields) { refl->GetRepeatedPtrField(message, fd_map_int32_double); const RepeatedPtrField& mf_string_string = refl->GetRepeatedPtrField(message, fd_map_string_string); - const RepeatedPtrField& - mf_int32_foreign_message = - refl->GetRepeatedPtrField( - message, fd_map_int32_foreign_message); + const RepeatedPtrField& mf_int32_foreign_message = + refl->GetRepeatedPtrField(message, fd_map_int32_foreign_message); // Get mutable RepeatedPtrField objects for all fields of interest. RepeatedPtrField* mmf_int32_int32 = @@ -1065,8 +1277,8 @@ TEST_F(MapFieldReflectionTest, RegularFields) { RepeatedPtrField* mmf_string_string = refl->MutableRepeatedPtrField(&message, fd_map_string_string); RepeatedPtrField* mmf_int32_foreign_message = - refl->MutableRepeatedPtrField( - &message, fd_map_int32_foreign_message); + refl->MutableRepeatedPtrField(&message, + fd_map_int32_foreign_message); // Make sure we can do gets through the RepeatedPtrField objects. for (int i = 0; i < 10; ++i) { @@ -1088,10 +1300,10 @@ TEST_F(MapFieldReflectionTest, RegularFields) { EXPECT_EQ(value_int32_double, Func(key_int32_double, 2)); const Message& message_string_string = mf_string_string.Get(i); - string key_string_string = + std::string key_string_string = message_string_string.GetReflection()->GetString( message_string_string, fd_map_string_string_key); - string value_string_string = + std::string value_string_string = message_string_string.GetReflection()->GetString( message_string_string, fd_map_string_string_value); EXPECT_EQ(value_string_string, StrFunc(Int(key_string_string), 5)); @@ -1101,9 +1313,8 @@ TEST_F(MapFieldReflectionTest, RegularFields) { message_int32_message, fd_map_int32_foreign_message_key); const ForeignMessage& value_int32_message = down_cast( - message_int32_message.GetReflection() - ->GetMessage(message_int32_message, - fd_map_int32_foreign_message_value)); + message_int32_message.GetReflection()->GetMessage( + message_int32_message, fd_map_int32_foreign_message_value)); EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6)); } @@ -1125,10 +1336,10 @@ TEST_F(MapFieldReflectionTest, RegularFields) { EXPECT_EQ(value_int32_double, Func(key_int32_double, 2)); const Message& message_string_string = mmf_string_string->Get(i); - string key_string_string = + std::string key_string_string = message_string_string.GetReflection()->GetString( message_string_string, fd_map_string_string_key); - string value_string_string = + std::string value_string_string = message_string_string.GetReflection()->GetString( message_string_string, fd_map_string_string_value); EXPECT_EQ(value_string_string, StrFunc(Int(key_string_string), 5)); @@ -1138,9 +1349,8 @@ TEST_F(MapFieldReflectionTest, RegularFields) { message_int32_message, fd_map_int32_foreign_message_key); const ForeignMessage& value_int32_message = down_cast( - message_int32_message.GetReflection() - ->GetMessage(message_int32_message, - fd_map_int32_foreign_message_value)); + message_int32_message.GetReflection()->GetMessage( + message_int32_message, fd_map_int32_foreign_message_value)); EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6)); } } @@ -1163,7 +1373,7 @@ TEST_F(MapFieldReflectionTest, RegularFields) { Func(key_int32_double, -2)); Message* message_string_string = mmf_string_string->Mutable(i); - string key_string_string = + std::string key_string_string = message_string_string->GetReflection()->GetString( *message_string_string, fd_map_string_string_key); message_string_string->GetReflection()->SetString( @@ -1175,9 +1385,8 @@ TEST_F(MapFieldReflectionTest, RegularFields) { message_int32_message->GetReflection()->GetInt32( *message_int32_message, fd_map_int32_foreign_message_key); ForeignMessage* value_int32_message = down_cast( - message_int32_message->GetReflection() - ->MutableMessage(message_int32_message, - fd_map_int32_foreign_message_value)); + message_int32_message->GetReflection()->MutableMessage( + message_int32_message, fd_map_int32_foreign_message_value)); value_int32_message->set_c(Func(key_int32_message, -6)); } } @@ -1198,7 +1407,8 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { Map* map_int32_int32 = message.mutable_map_int32_int32(); Map* map_int32_double = message.mutable_map_int32_double(); - Map* map_string_string = message.mutable_map_string_string(); + Map* map_string_string = + message.mutable_map_string_string(); Map* map_int32_foreign_message = message.mutable_map_int32_foreign_message(); @@ -1253,25 +1463,24 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { refl->GetMutableRepeatedFieldRef(&message, fd_map_int32_double); const MutableRepeatedFieldRef mmf_string_string = refl->GetMutableRepeatedFieldRef(&message, fd_map_string_string); - const MutableRepeatedFieldRef - mmf_int32_foreign_message = - refl->GetMutableRepeatedFieldRef( - &message, fd_map_int32_foreign_message); + const MutableRepeatedFieldRef mmf_int32_foreign_message = + refl->GetMutableRepeatedFieldRef(&message, + fd_map_int32_foreign_message); // Get entry default instances - google::protobuf::scoped_ptr entry_int32_int32( + std::unique_ptr entry_int32_int32( MessageFactory::generated_factory() ->GetPrototype(fd_map_int32_int32->message_type()) ->New()); - google::protobuf::scoped_ptr entry_int32_double( + std::unique_ptr entry_int32_double( MessageFactory::generated_factory() ->GetPrototype(fd_map_int32_double->message_type()) ->New()); - google::protobuf::scoped_ptr entry_string_string( + std::unique_ptr entry_string_string( MessageFactory::generated_factory() ->GetPrototype(fd_map_string_string->message_type()) ->New()); - google::protobuf::scoped_ptr entry_int32_foreign_message( + std::unique_ptr entry_int32_foreign_message( MessageFactory::generated_factory() ->GetPrototype(fd_map_int32_foreign_message->message_type()) ->New()); @@ -1317,10 +1526,10 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { const Message& message_string_string = mf_string_string.Get(i, entry_string_string.get()); - string key_string_string = + std::string key_string_string = message_string_string.GetReflection()->GetString( message_string_string, fd_map_string_string_key); - string value_string_string = + std::string value_string_string = message_string_string.GetReflection()->GetString( message_string_string, fd_map_string_string_value); EXPECT_EQ(value_string_string, StrFunc(Int(key_string_string), 5)); @@ -1331,9 +1540,8 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { message_int32_message, fd_map_int32_foreign_message_key); const ForeignMessage& value_int32_message = down_cast( - message_int32_message.GetReflection() - ->GetMessage(message_int32_message, - fd_map_int32_foreign_message_value)); + message_int32_message.GetReflection()->GetMessage( + message_int32_message, fd_map_int32_foreign_message_value)); EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6)); } @@ -1358,10 +1566,10 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { const Message& message_string_string = mmf_string_string.Get(i, entry_string_string.get()); - string key_string_string = + std::string key_string_string = message_string_string.GetReflection()->GetString( message_string_string, fd_map_string_string_key); - string value_string_string = + std::string value_string_string = message_string_string.GetReflection()->GetString( message_string_string, fd_map_string_string_value); EXPECT_EQ(value_string_string, StrFunc(Int(key_string_string), 5)); @@ -1372,9 +1580,8 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { message_int32_message, fd_map_int32_foreign_message_key); const ForeignMessage& value_int32_message = down_cast( - message_int32_message.GetReflection() - ->GetMessage(message_int32_message, - fd_map_int32_foreign_message_value)); + message_int32_message.GetReflection()->GetMessage( + message_int32_message, fd_map_int32_foreign_message_value)); EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6)); } } @@ -1431,7 +1638,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { // Test iterators. { int index = 0; - hash_map result; + std::unordered_map result; for (RepeatedFieldRef::iterator it = mf_int32_int32.begin(); it != mf_int32_int32.end(); ++it) { const Message& message = *it; @@ -1443,7 +1650,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { ++index; } EXPECT_EQ(10, index); - for (hash_map::const_iterator it = result.begin(); + for (std::unordered_map::const_iterator it = result.begin(); it != result.end(); ++it) { EXPECT_EQ(message.map_int32_int32().at(it->first), it->second); } @@ -1451,7 +1658,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { { int index = 0; - hash_map result; + std::unordered_map result; for (RepeatedFieldRef::iterator it = mf_int32_double.begin(); it != mf_int32_double.end(); ++it) { const Message& message = *it; @@ -1463,7 +1670,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { ++index; } EXPECT_EQ(10, index); - for (hash_map::const_iterator it = result.begin(); + for (std::unordered_map::const_iterator it = result.begin(); it != result.end(); ++it) { EXPECT_EQ(message.map_int32_double().at(it->first), it->second); } @@ -1471,19 +1678,20 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { { int index = 0; - hash_map result; + std::unordered_map result; for (RepeatedFieldRef::iterator it = mf_string_string.begin(); it != mf_string_string.end(); ++it) { const Message& message = *it; - string key = + std::string key = message.GetReflection()->GetString(message, fd_map_string_string_key); - string value = message.GetReflection()->GetString( + std::string value = message.GetReflection()->GetString( message, fd_map_string_string_value); result[key] = value; ++index; } EXPECT_EQ(10, index); - for (hash_map::const_iterator it = result.begin(); + for (std::unordered_map::const_iterator it = + result.begin(); it != result.end(); ++it) { EXPECT_EQ(message.map_string_string().at(it->first), it->second); } @@ -1498,9 +1706,9 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { const Message& message = *it; int32 key = message.GetReflection()->GetInt32( message, fd_map_int32_foreign_message_key); - const ForeignMessage& sub_message = down_cast( - message.GetReflection() - ->GetMessage(message, fd_map_int32_foreign_message_value)); + const ForeignMessage& sub_message = + down_cast(message.GetReflection()->GetMessage( + message, fd_map_int32_foreign_message_value)); result[key].MergeFrom(sub_message); ++index; } @@ -1532,8 +1740,8 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { EXPECT_EQ(1234.0, message.map_int32_double().at(4321)); entry_string_string->GetReflection()->SetString( - entry_string_string.get(), - fd_map_string_string->message_type()->field(0), "4321"); + entry_string_string.get(), fd_map_string_string->message_type()->field(0), + "4321"); entry_string_string->GetReflection()->SetString( entry_string_string.get(), fd_map_string_string->message_type()->field(1), "1234"); @@ -1555,12 +1763,13 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { EXPECT_EQ(1234, message.map_int32_foreign_message().at(4321).c()); // Test Reflection::AddAllocatedMessage - Message* free_entry_string_string = MessageFactory::generated_factory() - ->GetPrototype(fd_map_string_string->message_type()) - ->New(); + Message* free_entry_string_string = + MessageFactory::generated_factory() + ->GetPrototype(fd_map_string_string->message_type()) + ->New(); entry_string_string->GetReflection()->SetString( - free_entry_string_string, - fd_map_string_string->message_type()->field(0), "4321"); + free_entry_string_string, fd_map_string_string->message_type()->field(0), + "4321"); entry_string_string->GetReflection()->SetString( free_entry_string_string, fd_map_string_string->message_type()->field(1), "1234"); @@ -1627,22 +1836,22 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { { const Message& message0a = mmf_string_string.Get(0, entry_string_string.get()); - string string_value0a = message0a.GetReflection()->GetString( + std::string string_value0a = message0a.GetReflection()->GetString( message0a, fd_map_string_string_value); const Message& message9a = mmf_string_string.Get(9, entry_string_string.get()); - string string_value9a = message9a.GetReflection()->GetString( + std::string string_value9a = message9a.GetReflection()->GetString( message9a, fd_map_string_string_value); mmf_string_string.SwapElements(0, 9); const Message& message0b = mmf_string_string.Get(0, entry_string_string.get()); - string string_value0b = message0b.GetReflection()->GetString( + std::string string_value0b = message0b.GetReflection()->GetString( message0b, fd_map_string_string_value); const Message& message9b = mmf_string_string.Get(9, entry_string_string.get()); - string string_value9b = message9b.GetReflection()->GetString( + std::string string_value9b = message9b.GetReflection()->GetString( message9b, fd_map_string_string_value); EXPECT_EQ(string_value9a, string_value0b); @@ -1652,30 +1861,30 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { { const Message& message0a = mmf_int32_foreign_message.Get(0, entry_int32_foreign_message.get()); - const ForeignMessage& sub_message0a = down_cast( - message0a.GetReflection() - ->GetMessage(message0a, fd_map_int32_foreign_message_value)); + const ForeignMessage& sub_message0a = + down_cast(message0a.GetReflection()->GetMessage( + message0a, fd_map_int32_foreign_message_value)); int32 int32_value0a = sub_message0a.c(); const Message& message9a = mmf_int32_foreign_message.Get(9, entry_int32_foreign_message.get()); - const ForeignMessage& sub_message9a = down_cast( - message9a.GetReflection() - ->GetMessage(message9a, fd_map_int32_foreign_message_value)); + const ForeignMessage& sub_message9a = + down_cast(message9a.GetReflection()->GetMessage( + message9a, fd_map_int32_foreign_message_value)); int32 int32_value9a = sub_message9a.c(); mmf_int32_foreign_message.SwapElements(0, 9); const Message& message0b = mmf_int32_foreign_message.Get(0, entry_int32_foreign_message.get()); - const ForeignMessage& sub_message0b = down_cast( - message0b.GetReflection() - ->GetMessage(message0b, fd_map_int32_foreign_message_value)); + const ForeignMessage& sub_message0b = + down_cast(message0b.GetReflection()->GetMessage( + message0b, fd_map_int32_foreign_message_value)); int32 int32_value0b = sub_message0b.c(); const Message& message9b = mmf_int32_foreign_message.Get(9, entry_int32_foreign_message.get()); - const ForeignMessage& sub_message9b = down_cast( - message9b.GetReflection() - ->GetMessage(message9b, fd_map_int32_foreign_message_value)); + const ForeignMessage& sub_message9b = + down_cast(message9b.GetReflection()->GetMessage( + message9b, fd_map_int32_foreign_message_value)); int32 int32_value9b = sub_message9b.c(); EXPECT_EQ(int32_value9a, int32_value0b); @@ -1714,34 +1923,26 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefMergeFromAndSwap) { const FieldDescriptor* fd_map_int32_foreign_message = desc->FindFieldByName("map_int32_foreign_message"); - // Get MutableRepeatedFieldRef objects for all fields of interest. + // Get MutableRepeatedFieldRef objects for all fields of interest. const MutableRepeatedFieldRef mmf_int32_int32 = - refl->GetMutableRepeatedFieldRef( - &m0, fd_map_int32_int32); + refl->GetMutableRepeatedFieldRef(&m0, fd_map_int32_int32); const MutableRepeatedFieldRef mmf_int32_double = - refl->GetMutableRepeatedFieldRef( - &m0, fd_map_int32_double); + refl->GetMutableRepeatedFieldRef(&m0, fd_map_int32_double); const MutableRepeatedFieldRef mmf_string_string = - refl->GetMutableRepeatedFieldRef( - &m0, fd_map_string_string); - const MutableRepeatedFieldRef - mmf_int32_foreign_message = - refl->GetMutableRepeatedFieldRef( - &m0, fd_map_int32_foreign_message); + refl->GetMutableRepeatedFieldRef(&m0, fd_map_string_string); + const MutableRepeatedFieldRef mmf_int32_foreign_message = + refl->GetMutableRepeatedFieldRef(&m0, + fd_map_int32_foreign_message); // Test MutableRepeatedRef::CopyFrom mmf_int32_int32.CopyFrom( - refl->GetRepeatedFieldRef( - m1, fd_map_int32_int32)); + refl->GetRepeatedFieldRef(m1, fd_map_int32_int32)); mmf_int32_double.CopyFrom( - refl->GetRepeatedFieldRef( - m1, fd_map_int32_double)); + refl->GetRepeatedFieldRef(m1, fd_map_int32_double)); mmf_string_string.CopyFrom( - refl->GetRepeatedFieldRef( - m1, fd_map_string_string)); + refl->GetRepeatedFieldRef(m1, fd_map_string_string)); mmf_int32_foreign_message.CopyFrom( - refl->GetRepeatedFieldRef( - m1, fd_map_int32_foreign_message)); + refl->GetRepeatedFieldRef(m1, fd_map_int32_foreign_message)); for (int i = 0; i < 10; ++i) { EXPECT_EQ(Func(i, 11), m0.map_int32_int32().at(i + 10)); @@ -1752,17 +1953,13 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefMergeFromAndSwap) { // Test MutableRepeatedRef::MergeFrom mmf_int32_int32.MergeFrom( - refl->GetRepeatedFieldRef( - m2, fd_map_int32_int32)); + refl->GetRepeatedFieldRef(m2, fd_map_int32_int32)); mmf_int32_double.MergeFrom( - refl->GetRepeatedFieldRef( - m2, fd_map_int32_double)); + refl->GetRepeatedFieldRef(m2, fd_map_int32_double)); mmf_string_string.MergeFrom( - refl->GetRepeatedFieldRef( - m2, fd_map_string_string)); + refl->GetRepeatedFieldRef(m2, fd_map_string_string)); mmf_int32_foreign_message.MergeFrom( - refl->GetRepeatedFieldRef( - m2, fd_map_int32_foreign_message)); + refl->GetRepeatedFieldRef(m2, fd_map_int32_foreign_message)); for (int i = 0; i < 10; ++i) { EXPECT_EQ(Func(i, 21), m0.map_int32_int32().at(i + 20)); EXPECT_EQ(Func(i, 22), m0.map_int32_double().at(i + 20)); @@ -1773,17 +1970,13 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefMergeFromAndSwap) { // Test MutableRepeatedRef::Swap // Swap between m0 and m2. mmf_int32_int32.Swap( - refl->GetMutableRepeatedFieldRef( - &m2, fd_map_int32_int32)); + refl->GetMutableRepeatedFieldRef(&m2, fd_map_int32_int32)); mmf_int32_double.Swap( - refl->GetMutableRepeatedFieldRef( - &m2, fd_map_int32_double)); + refl->GetMutableRepeatedFieldRef(&m2, fd_map_int32_double)); mmf_string_string.Swap( - refl->GetMutableRepeatedFieldRef( - &m2, fd_map_string_string)); - mmf_int32_foreign_message.Swap( - refl->GetMutableRepeatedFieldRef( - &m2, fd_map_int32_foreign_message)); + refl->GetMutableRepeatedFieldRef(&m2, fd_map_string_string)); + mmf_int32_foreign_message.Swap(refl->GetMutableRepeatedFieldRef( + &m2, fd_map_int32_foreign_message)); for (int i = 0; i < 10; ++i) { // Check the content of m0. EXPECT_EQ(Func(i, 21), m0.map_int32_int32().at(i + 20)); @@ -1809,7 +2002,7 @@ TEST_F(MapFieldReflectionTest, MapSizeWithDuplicatedKey) { // Dynamic Message { DynamicMessageFactory factory; - google::protobuf::scoped_ptr message( + std::unique_ptr message( factory.GetPrototype(unittest::TestMap::descriptor())->New()); const Reflection* reflection = message->GetReflection(); const FieldDescriptor* field = @@ -1826,6 +2019,7 @@ TEST_F(MapFieldReflectionTest, MapSizeWithDuplicatedKey) { EXPECT_EQ(2, reflection->FieldSize(*message, field)); EXPECT_EQ(1, MapSize(reflection, field, *message)); + EXPECT_EQ(2, reflection->FieldSize(*message, field)); } // Generated Message @@ -1849,6 +2043,49 @@ TEST_F(MapFieldReflectionTest, MapSizeWithDuplicatedKey) { } } +TEST_F(MapFieldReflectionTest, UninitializedEntry) { + unittest::TestRequiredMessageMap message; + const Reflection* reflection = message.GetReflection(); + const FieldDescriptor* field = + message.GetDescriptor()->FindFieldByName("map_field"); + auto entry = reflection->AddMessage(&message, field); + EXPECT_FALSE(entry->IsInitialized()); + EXPECT_FALSE(message.IsInitialized()); +} + +class MyMapEntry + : public internal::MapEntry { + public: + constexpr MyMapEntry() {} + MyMapEntry(Arena*) { std::abort(); } + Metadata GetMetadata() const override { std::abort(); } + static bool ValidateKey(void*) { return true; } + static bool ValidateValue(void*) { return true; } +}; + +class MyMapEntryLite + : public internal::MapEntryLite { + public: + constexpr MyMapEntryLite() {} + explicit MyMapEntryLite(Arena*) { std::abort(); } + static bool ValidateKey(void*) { return true; } + static bool ValidateValue(void*) { return true; } +}; + +TEST(MapEntryTest, ConstInit) { + // This verifies that `MapEntry`, `MapEntryLite` and `MapEntryImpl` can be + // constant initialized. + PROTOBUF_CONSTINIT static MyMapEntry entry{}; + EXPECT_NE(entry.SpaceUsed(), 0); + + PROTOBUF_CONSTINIT static MyMapEntryLite entry_lite{}; // NOLINT + EXPECT_TRUE(entry_lite.IsInitialized()); +} + // Generated Message Test =========================================== TEST(GeneratedMapFieldTest, Accessors) { @@ -1969,8 +2206,7 @@ TEST(GeneratedMapFieldTest, CopyAssignmentOperator) { MapTestUtil::ExpectMapFieldsSet(message2); } -#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \ - !defined(GOOGLE_PROTOBUF_NO_RTTI) +#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || PROTOBUF_RTTI TEST(GeneratedMapFieldTest, UpcastCopyFrom) { // Test the CopyFrom method that takes in the generic const Message& // parameter. @@ -1994,11 +2230,9 @@ TEST(GeneratedMapFieldTest, CopyFromDynamicMessage) { // Construct a new version of the dynamic message via the factory. DynamicMessageFactory factory; - google::protobuf::scoped_ptr message1; - message1.reset( - factory.GetPrototype(unittest::TestMap::descriptor())->New()); - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + std::unique_ptr message1; + message1.reset(factory.GetPrototype(unittest::TestMap::descriptor())->New()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); reflection_tester.SetMapFieldsViaReflection(message1.get()); reflection_tester.ExpectMapFieldsSetViaReflection(*message1); reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get()); @@ -2011,11 +2245,9 @@ TEST(GeneratedMapFieldTest, CopyFromDynamicMessageMapReflection) { // Construct a new version of the dynamic message via the factory. DynamicMessageFactory factory; - google::protobuf::scoped_ptr message1; - message1.reset( - factory.GetPrototype(unittest::TestMap::descriptor())->New()); - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + std::unique_ptr message1; + message1.reset(factory.GetPrototype(unittest::TestMap::descriptor())->New()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); reflection_tester.SetMapFieldsViaMapReflection(message1.get()); reflection_tester.ExpectMapFieldsSetViaReflection(*message1); reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get()); @@ -2023,6 +2255,38 @@ TEST(GeneratedMapFieldTest, CopyFromDynamicMessageMapReflection) { MapTestUtil::ExpectMapFieldsSet(message2); } +TEST(GeneratedMapFieldTest, DynamicMessageMergeFromDynamicMessage) { + // Construct two dynamic message and sets via map reflection. + DynamicMessageFactory factory; + std::unique_ptr message1; + message1.reset(factory.GetPrototype(unittest::TestMap::descriptor())->New()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); + reflection_tester.SetMapFieldsViaMapReflection(message1.get()); + + // message2 is created by same factory. + std::unique_ptr message2; + message2.reset(factory.GetPrototype(unittest::TestMap::descriptor())->New()); + reflection_tester.SetMapFieldsViaMapReflection(message2.get()); + + // message3 is created by different factory. + DynamicMessageFactory factory3; + std::unique_ptr message3; + message3.reset(factory3.GetPrototype(unittest::TestMap::descriptor())->New()); + reflection_tester.SetMapFieldsViaMapReflection(message3.get()); + + message2->MergeFrom(*message1); + message3->MergeFrom(*message1); + + // Test MergeFrom does not sync to repeated fields and + // there is no duplicate keys in text format. + std::string output1, output2, output3; + TextFormat::PrintToString(*message1, &output1); + TextFormat::PrintToString(*message2, &output2); + TextFormat::PrintToString(*message3, &output3); + EXPECT_EQ(output1, output2); + EXPECT_EQ(output1, output3); +} + TEST(GeneratedMapFieldTest, DynamicMessageCopyFrom) { // Test copying to a DynamicMessage, which must fall back to using reflection. unittest::TestMap message2; @@ -2030,28 +2294,24 @@ TEST(GeneratedMapFieldTest, DynamicMessageCopyFrom) { // Construct a new version of the dynamic message via the factory. DynamicMessageFactory factory; - google::protobuf::scoped_ptr message1; - message1.reset( - factory.GetPrototype(unittest::TestMap::descriptor())->New()); + std::unique_ptr message1; + message1.reset(factory.GetPrototype(unittest::TestMap::descriptor())->New()); - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); message1->MergeFrom(message2); reflection_tester.ExpectMapFieldsSetViaReflection(*message1); reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get()); } TEST(GeneratedMapFieldTest, DynamicMessageCopyFromMapReflection) { - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); unittest::TestMap message2; reflection_tester.SetMapFieldsViaMapReflection(&message2); // Construct a dynamic message via the factory. DynamicMessageFactory factory; - google::protobuf::scoped_ptr message1; - message1.reset( - factory.GetPrototype(unittest::TestMap::descriptor())->New()); + std::unique_ptr message1; + message1.reset(factory.GetPrototype(unittest::TestMap::descriptor())->New()); message1->MergeFrom(message2); reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get()); @@ -2060,12 +2320,10 @@ TEST(GeneratedMapFieldTest, DynamicMessageCopyFromMapReflection) { TEST(GeneratedMapFieldTest, SyncDynamicMapWithRepeatedField) { // Construct a dynamic message via the factory. - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); DynamicMessageFactory factory; - google::protobuf::scoped_ptr message; - message.reset( - factory.GetPrototype(unittest::TestMap::descriptor())->New()); + std::unique_ptr message; + message.reset(factory.GetPrototype(unittest::TestMap::descriptor())->New()); reflection_tester.SetMapFieldsViaReflection(message.get()); reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message.get()); reflection_tester.ExpectMapFieldsSetViaReflection(*message); @@ -2088,6 +2346,18 @@ TEST(GeneratedMapFieldTest, NonEmptyMergeFrom) { message1.MergeFrom(message2); MapTestUtil::ExpectMapFieldsSet(message1); + + // Test reflection MergeFrom does not sync to repeated field + // and there is no duplicated keys. + MapTestUtil::SetMapFields(&message1); + MapTestUtil::SetMapFields(&message2); + + message2.MergeFrom(message1); + + std::string output1, output2; + TextFormat::PrintToString(message1, &output1); + TextFormat::PrintToString(message2, &output2); + EXPECT_EQ(output1, output2); } TEST(GeneratedMapFieldTest, MergeFromMessageMap) { @@ -2106,11 +2376,11 @@ TEST(GeneratedMapFieldTest, MergeFromMessageMap) { // Test the generated SerializeWithCachedSizesToArray() TEST(GeneratedMapFieldTest, SerializationToArray) { unittest::TestMap message1, message2; - string data; + std::string data; MapTestUtil::SetMapFields(&message1); - int size = message1.ByteSize(); + size_t size = message1.ByteSizeLong(); data.resize(size); - uint8* start = reinterpret_cast(string_as_array(&data)); + uint8* start = reinterpret_cast(::google::protobuf::string_as_array(&data)); uint8* end = message1.SerializeWithCachedSizesToArray(start); EXPECT_EQ(size, end - start); EXPECT_TRUE(message2.ParseFromString(data)); @@ -2121,12 +2391,12 @@ TEST(GeneratedMapFieldTest, SerializationToArray) { TEST(GeneratedMapFieldTest, SerializationToStream) { unittest::TestMap message1, message2; MapTestUtil::SetMapFields(&message1); - int size = message1.ByteSize(); - string data; + size_t size = message1.ByteSizeLong(); + std::string data; data.resize(size); { // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); io::CodedOutputStream output_stream(&array_stream); message1.SerializeWithCachedSizes(&output_stream); EXPECT_FALSE(output_stream.HadError()); @@ -2158,7 +2428,7 @@ TEST(GeneratedMapFieldTest, Proto2UnknownEnum) { unittest::TestEnumMapPlusExtra from; (*from.mutable_known_map_field())[0] = unittest::E_PROTO2_MAP_ENUM_FOO; (*from.mutable_unknown_map_field())[0] = unittest::E_PROTO2_MAP_ENUM_EXTRA; - string data; + std::string data; from.SerializeToString(&data); unittest::TestEnumMap to; @@ -2183,7 +2453,7 @@ TEST(GeneratedMapFieldTest, Proto2UnknownEnum) { TEST(GeneratedMapFieldTest, StandardWireFormat) { unittest::TestMap message; - string data = "\x0A\x04\x08\x01\x10\x01"; + std::string data = "\x0A\x04\x08\x01\x10\x01"; EXPECT_TRUE(message.ParseFromString(data)); EXPECT_EQ(1, message.map_int32_int32().size()); @@ -2194,10 +2464,11 @@ TEST(GeneratedMapFieldTest, UnorderedWireFormat) { unittest::TestMap message; // put value before key in wire format - string data = "\x0A\x04\x10\x01\x08\x02"; + std::string data = "\x0A\x04\x10\x01\x08\x02"; EXPECT_TRUE(message.ParseFromString(data)); EXPECT_EQ(1, message.map_int32_int32().size()); + ASSERT_NE(message.map_int32_int32().find(2), message.map_int32_int32().end()); EXPECT_EQ(1, message.map_int32_int32().at(2)); } @@ -2205,7 +2476,7 @@ TEST(GeneratedMapFieldTest, DuplicatedKeyWireFormat) { unittest::TestMap message; // Two key fields in wire format - string data = "\x0A\x06\x08\x01\x08\x02\x10\x01"; + std::string data = "\x0A\x06\x08\x01\x08\x02\x10\x01"; EXPECT_TRUE(message.ParseFromString(data)); EXPECT_EQ(1, message.map_int32_int32().size()); @@ -2222,14 +2493,14 @@ TEST(GeneratedMapFieldTest, DuplicatedKeyWireFormat) { with_dummy4.set_c(0); with_dummy4.set_dummy4(11); (*map_message.mutable_map_field())[key] = with_dummy4; - string s = map_message.SerializeAsString(); + std::string s = map_message.SerializeAsString(); unittest::TestRequired with_dummy5; with_dummy5.set_a(0); with_dummy5.set_b(0); with_dummy5.set_c(0); with_dummy5.set_dummy5(12); (*map_message.mutable_map_field())[key] = with_dummy5; - string both = s + map_message.SerializeAsString(); + std::string both = s + map_message.SerializeAsString(); // We don't expect a merge now. The "second one wins." ASSERT_TRUE(map_message.ParseFromString(both)); ASSERT_EQ(1, map_message.map_field().size()); @@ -2253,7 +2524,7 @@ TEST(GeneratedMapFieldTest, KeysValuesUnknownsWireFormat) { const char kValueTag = 0x10; const char kJunkTag = 0x20; for (int items = 0; items <= kMaxNumKeysAndValuesAndJunk; items++) { - string data = "\x0A"; + std::string data = "\x0A"; // Encode length of what will follow. data.push_back(items * 2); static const int kBitsOfIPerItem = 4; @@ -2261,22 +2532,31 @@ TEST(GeneratedMapFieldTest, KeysValuesUnknownsWireFormat) { // Each iteration of the following is a test. It uses i as bit vector // encoding the keys and values to put in the wire format. for (int i = 0; i < (1 << (items * kBitsOfIPerItem)); i++) { - string wire_format = data; + std::string wire_format = data; int expected_key = 0; int expected_value = 0; for (int k = i, j = 0; j < items; j++, k >>= kBitsOfIPerItem) { bool is_key = k & 0x1; bool is_value = !is_key && (k & 0x2); - wire_format.push_back(is_key ? kKeyTag : - is_value ? kValueTag : kJunkTag); + wire_format.push_back(is_key ? kKeyTag + : is_value ? kValueTag : kJunkTag); char c = static_cast(k & mask) >> 2; // One char after the tag. wire_format.push_back(c); if (is_key) expected_key = static_cast(c); if (is_value) expected_value = static_cast(c); - ASSERT_TRUE(message.ParseFromString(wire_format)); - ASSERT_EQ(1, message.map_int32_int32().size()); - ASSERT_EQ(expected_key, message.map_int32_int32().begin()->first); - ASSERT_EQ(expected_value, message.map_int32_int32().begin()->second); + bool res = message.ParseFromString(wire_format); + bool expect_success = true; + // Unfortunately the old map parser accepts malformed input, the new + // parser accepts only correct input. + if (j != items - 1) expect_success = false; + if (expect_success) { + ASSERT_TRUE(res); + ASSERT_EQ(1, message.map_int32_int32().size()); + ASSERT_EQ(expected_key, message.map_int32_int32().begin()->first); + ASSERT_EQ(expected_value, message.map_int32_int32().begin()->second); + } else { + ASSERT_FALSE(res); + } } } } @@ -2286,7 +2566,7 @@ TEST(GeneratedMapFieldTest, DuplicatedValueWireFormat) { unittest::TestMap message; // Two value fields in wire format - string data = "\x0A\x06\x08\x01\x10\x01\x10\x02"; + std::string data = "\x0A\x06\x08\x01\x10\x01\x10\x02"; EXPECT_TRUE(message.ParseFromString(data)); EXPECT_EQ(1, message.map_int32_int32().size()); @@ -2297,10 +2577,11 @@ TEST(GeneratedMapFieldTest, MissedKeyWireFormat) { unittest::TestMap message; // No key field in wire format - string data = "\x0A\x02\x10\x01"; + std::string data = "\x0A\x02\x10\x01"; EXPECT_TRUE(message.ParseFromString(data)); EXPECT_EQ(1, message.map_int32_int32().size()); + ASSERT_NE(message.map_int32_int32().find(0), message.map_int32_int32().end()); EXPECT_EQ(1, message.map_int32_int32().at(0)); } @@ -2308,10 +2589,11 @@ TEST(GeneratedMapFieldTest, MissedValueWireFormat) { unittest::TestMap message; // No value field in wire format - string data = "\x0A\x02\x08\x01"; + std::string data = "\x0A\x02\x08\x01"; EXPECT_TRUE(message.ParseFromString(data)); EXPECT_EQ(1, message.map_int32_int32().size()); + ASSERT_NE(message.map_int32_int32().find(1), message.map_int32_int32().end()); EXPECT_EQ(0, message.map_int32_int32().at(1)); } @@ -2319,21 +2601,21 @@ TEST(GeneratedMapFieldTest, MissedValueTextFormat) { unittest::TestMap message; // No value field in text format - string text = + std::string text = "map_int32_foreign_message {\n" " key: 1234567890\n" "}"; - EXPECT_TRUE(google::protobuf::TextFormat::ParseFromString(text, &message)); + EXPECT_TRUE(TextFormat::ParseFromString(text, &message)); EXPECT_EQ(1, message.map_int32_foreign_message().size()); - EXPECT_EQ(11, message.ByteSize()); + EXPECT_EQ(11, message.ByteSizeLong()); } TEST(GeneratedMapFieldTest, UnknownFieldWireFormat) { unittest::TestMap message; // Unknown field in wire format - string data = "\x0A\x06\x08\x02\x10\x03\x18\x01"; + std::string data = "\x0A\x06\x08\x02\x10\x03\x18\x01"; EXPECT_TRUE(message.ParseFromString(data)); EXPECT_EQ(1, message.map_int32_int32().size()); @@ -2344,7 +2626,7 @@ TEST(GeneratedMapFieldTest, CorruptedWireFormat) { unittest::TestMap message; // corrupted data in wire format - string data = "\x0A\x06\x08\x02\x11\x03"; + std::string data = "\x0A\x06\x08\x02\x11\x03"; EXPECT_FALSE(message.ParseFromString(data)); } @@ -2363,47 +2645,68 @@ TEST(GeneratedMapFieldTest, IsInitialized) { EXPECT_TRUE(map_message.IsInitialized()); } +TEST(GeneratedMapFieldTest, SpaceUsed) { + unittest::TestRequiredMessageMap map_message; + const size_t initial = map_message.SpaceUsed(); + const size_t space_used_message = unittest::TestRequired().SpaceUsed(); + + auto& m = *map_message.mutable_map_field(); + constexpr int kNumValues = 100; + for (int i = 0; i < kNumValues; ++i) { + m[i]; + } + + // The exact value will depend on internal state, like collisions, + // so we can't predict it. But we can predict a lower bound. + size_t lower_bound = + initial + kNumValues * (space_used_message + sizeof(int32) + + /* Node::next */ sizeof(void*) + + /* table entry */ sizeof(void*)); + + EXPECT_LE(lower_bound, map_message.SpaceUsed()); +} + TEST(GeneratedMapFieldTest, MessagesMustMerge) { unittest::TestRequiredMessageMap map_message; + unittest::TestRequired with_dummy4; with_dummy4.set_a(97); - with_dummy4.set_b(0); - with_dummy4.set_c(0); + with_dummy4.set_b(91); with_dummy4.set_dummy4(98); - - EXPECT_TRUE(with_dummy4.IsInitialized()); + EXPECT_FALSE(with_dummy4.IsInitialized()); (*map_message.mutable_map_field())[0] = with_dummy4; - EXPECT_TRUE(map_message.IsInitialized()); - string s = map_message.SerializeAsString(); - - // Modify s so that there are two values in the entry for key 0. - // The first will have no value for c. The second will have no value for a. - // Those are required fields. Also, make some other little changes, to - // ensure we are merging the two values (because they're messages). - ASSERT_EQ(s.size() - 2, s[1]); // encoding of the length of what follows - string encoded_val(s.data() + 4, s.data() + s.size()); - // In s, change the encoding of c to an encoding of dummy32. - s[s.size() - 3] -= 8; - // Make encoded_val slightly different from what's in s. - encoded_val[encoded_val.size() - 1] += 33; // Encode c = 33. - for (int i = 0; i < encoded_val.size(); i++) { - if (encoded_val[i] == 97) { - // Encode b = 91 instead of a = 97. But this won't matter, because - // we also encode b = 0 right after this. The point is to leave out - // a required field, and make sure the parser doesn't complain, because - // every required field is set after the merge of the two values. - encoded_val[i - 1] += 16; - encoded_val[i] = 91; - } else if (encoded_val[i] == 98) { - // Encode dummy5 = 99 instead of dummy4 = 98. - encoded_val[i - 1] += 8; // The tag for dummy5 is 8 more. - encoded_val[i]++; - break; - } - } + EXPECT_FALSE(map_message.IsInitialized()); - s += encoded_val; // Add the second message. - s[1] += encoded_val.size(); // Adjust encoded size. + unittest::TestRequired with_dummy5; + with_dummy5.set_b(0); + with_dummy5.set_c(33); + with_dummy5.set_dummy5(99); + EXPECT_FALSE(with_dummy5.IsInitialized()); + (*map_message.mutable_map_field())[0] = with_dummy5; + EXPECT_FALSE(map_message.IsInitialized()); + + // The wire format of MapEntry is straightforward (*) and can be manually + // constructed to force merging of two uninitialized messages that would + // result in an initialized message. + // + // (*) http://google3/net/proto2/internal/map_test.cc?l=2433&rcl=310012028 + std::string dummy4_s = with_dummy4.SerializePartialAsString(); + std::string dummy5_s = with_dummy5.SerializePartialAsString(); + int payload_size = dummy4_s.size() + dummy5_s.size(); + // Makes sure the payload size fits into one byte. + ASSERT_LT(payload_size, 128); + + std::string s(6, 0); + char* p = &s[0]; + *p++ = WireFormatLite::MakeTag(1, WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + // Length: 2B for key tag & val and 2B for val tag and length of the following + // payload. + *p++ = 4 + payload_size; + *p++ = WireFormatLite::MakeTag(1, WireFormatLite::WIRETYPE_VARINT); + *p++ = 0; + *p++ = WireFormatLite::MakeTag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + *p++ = payload_size; + StrAppend(&s, dummy4_s, dummy5_s); // Test key then value then value. int key = 0; @@ -2417,10 +2720,10 @@ TEST(GeneratedMapFieldTest, MessagesMustMerge) { EXPECT_EQ(99, map_message.map_field().find(key)->second.dummy5()); // Test key then value then value then key. - s.push_back(s[2]); // Copy the key's tag. + s.push_back(s[2]); // Copy the key's tag. key = 19; - s.push_back(key); // Second key is 19 instead of 0. - s[1] += 2; // Adjust encoded size. + s.push_back(key); // Second key is 19 instead of 0. + s[1] += 2; // Adjust encoded size. ASSERT_TRUE(map_message.ParseFromString(s)); ASSERT_EQ(1, map_message.map_field().size()); ASSERT_EQ(1, map_message.map_field().count(key)); @@ -2435,19 +2738,17 @@ TEST(GeneratedMapFieldTest, MessagesMustMerge) { TEST(GeneratedMapFieldReflectionTest, SpaceUsed) { unittest::TestMap message; - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); reflection_tester.SetMapFieldsViaReflection(&message); - EXPECT_LT(0, message.GetReflection()->SpaceUsed(message)); + EXPECT_LT(0, message.GetReflection()->SpaceUsedLong(message)); } TEST(GeneratedMapFieldReflectionTest, Accessors) { // Set every field to a unique value then go back and check all those // values. unittest::TestMap message; - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); reflection_tester.SetMapFieldsViaReflection(&message); MapTestUtil::ExpectMapFieldsSet(message); reflection_tester.ExpectMapFieldsSetViaReflection(message); @@ -2505,8 +2806,7 @@ TEST(GeneratedMapFieldReflectionTest, ClearField) { MapTestUtil::SetMapFields(&message); MapTestUtil::ExpectMapFieldsSet(message); - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); reflection_tester.ClearMapFieldsViaReflection(&message); reflection_tester.ExpectClearViaReflection(message); reflection_tester.ExpectClearViaReflectionIterator(&message); @@ -2514,8 +2814,7 @@ TEST(GeneratedMapFieldReflectionTest, ClearField) { TEST(GeneratedMapFieldReflectionTest, RemoveLast) { unittest::TestMap message; - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); MapTestUtil::SetMapFields(&message); MapTestUtil::ExpectMapsSize(message, 2); @@ -2562,8 +2861,7 @@ TEST(GeneratedMapFieldReflectionTest, ReleaseLast) { TEST(GeneratedMapFieldReflectionTest, SwapElements) { unittest::TestMap message; - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); MapTestUtil::SetMapFields(&message); @@ -2602,8 +2900,7 @@ TEST(GeneratedMapFieldReflectionTest, SwapElements) { TEST(GeneratedMapFieldReflectionTest, MutableUnknownFields) { unittest::TestMap message; - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); reflection_tester.MutableUnknownFieldsOfMapFieldsViaReflection(&message); } @@ -2658,8 +2955,7 @@ TEST(GeneratedMapFieldReflectionTest, MergeFromClearMapEntry) { TEST(GeneratedMapFieldReflectionTest, MapEntryClear) { unittest::TestMap message; - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); reflection_tester.MutableUnknownFieldsOfMapFieldsViaReflection(&message); } @@ -2680,8 +2976,7 @@ TEST(GeneratedMapFieldReflectionTest, Proto2MapEntryClear) { TEST(GeneratedMapFieldReflectionTest, SetViaMapReflection) { unittest::TestMap message; - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); reflection_tester.SetMapFieldsViaMapReflection(&message); reflection_tester.ExpectMapFieldsSetViaReflection(message); reflection_tester.ExpectMapFieldsSetViaReflectionIterator(&message); @@ -2701,8 +2996,7 @@ class MapFieldInDynamicMessageTest : public testing::Test { : pool_(DescriptorPool::generated_pool()), factory_(pool_) {} virtual void SetUp() { - map_descriptor_ = - pool_->FindMessageTypeByName("protobuf_unittest.TestMap"); + map_descriptor_ = pool_->FindMessageTypeByName("protobuf_unittest.TestMap"); recursive_map_descriptor_ = pool_->FindMessageTypeByName("protobuf_unittest.TestRecursiveMapMessage"); ASSERT_TRUE(map_descriptor_ != NULL); @@ -2715,7 +3009,7 @@ TEST_F(MapFieldInDynamicMessageTest, MapIndependentOffsets) { // Check that all fields have independent offsets by setting each // one to a unique value then checking that they all still have those // unique values (i.e. they don't stomp each other). - google::protobuf::scoped_ptr message(map_prototype_->New()); + std::unique_ptr message(map_prototype_->New()); MapReflectionTester reflection_tester(map_descriptor_); reflection_tester.SetMapFieldsViaReflection(message.get()); @@ -2724,7 +3018,7 @@ TEST_F(MapFieldInDynamicMessageTest, MapIndependentOffsets) { TEST_F(MapFieldInDynamicMessageTest, DynamicMapReflection) { // Check that map fields work properly. - google::protobuf::scoped_ptr message(map_prototype_->New()); + std::unique_ptr message(map_prototype_->New()); // Check set functions. MapReflectionTester reflection_tester(map_descriptor_); @@ -2733,31 +3027,31 @@ TEST_F(MapFieldInDynamicMessageTest, DynamicMapReflection) { } TEST_F(MapFieldInDynamicMessageTest, MapSpaceUsed) { - // Test that SpaceUsed() works properly + // Test that SpaceUsedLong() works properly // Since we share the implementation with generated messages, we don't need // to test very much here. Just make sure it appears to be working. - google::protobuf::scoped_ptr message(map_prototype_->New()); + std::unique_ptr message(map_prototype_->New()); MapReflectionTester reflection_tester(map_descriptor_); - int initial_space_used = message->SpaceUsed(); + int initial_space_used = message->SpaceUsedLong(); reflection_tester.SetMapFieldsViaReflection(message.get()); - EXPECT_LT(initial_space_used, message->SpaceUsed()); + EXPECT_LT(initial_space_used, message->SpaceUsedLong()); } TEST_F(MapFieldInDynamicMessageTest, RecursiveMap) { TestRecursiveMapMessage from; (*from.mutable_a())[""]; - string data = from.SerializeAsString(); - google::protobuf::scoped_ptr to( + std::string data = from.SerializeAsString(); + std::unique_ptr to( factory_.GetPrototype(recursive_map_descriptor_)->New()); ASSERT_TRUE(to->ParseFromString(data)); } TEST_F(MapFieldInDynamicMessageTest, MapValueReferernceValidAfterSerialize) { - google::protobuf::scoped_ptr message(map_prototype_->New()); + std::unique_ptr message(map_prototype_->New()); MapReflectionTester reflection_tester(map_descriptor_); reflection_tester.SetMapFieldsViaMapReflection(message.get()); @@ -2773,7 +3067,7 @@ TEST_F(MapFieldInDynamicMessageTest, MapValueReferernceValidAfterSerialize) { // In previous implementation, calling SerializeToString will cause syncing // from map to repeated field, which will invalidate the submsg we previously // got. - string data; + std::string data; message->SerializeToString(&data); const Reflection* submsg_reflection = submsg->GetReflection(); @@ -2788,7 +3082,7 @@ TEST_F(MapFieldInDynamicMessageTest, MapValueReferernceValidAfterSerialize) { } TEST_F(MapFieldInDynamicMessageTest, MapEntryReferernceValidAfterSerialize) { - google::protobuf::scoped_ptr message(map_prototype_->New()); + std::unique_ptr message(map_prototype_->New()); MapReflectionTester reflection_tester(map_descriptor_); reflection_tester.SetMapFieldsViaReflection(message.get()); @@ -2805,7 +3099,7 @@ TEST_F(MapFieldInDynamicMessageTest, MapEntryReferernceValidAfterSerialize) { // In previous implementation, calling SerializeToString will cause syncing // from repeated field to map, which will invalidate the map_entry we // previously got. - string data; + std::string data; message->SerializeToString(&data); const Reflection* submsg_reflection = submsg->GetReflection(); @@ -2870,15 +3164,15 @@ TEST(ReflectionOpsForMapFieldTest, MapDiscardUnknownFields) { MapTestUtil::SetMapFields(&message); // Set some unknown fields in message. - message.GetReflection()->MutableUnknownFields(&message)-> - AddVarint(123456, 654321); + message.GetReflection()->MutableUnknownFields(&message)->AddVarint(123456, + 654321); // Discard them. ReflectionOps::DiscardUnknownFields(&message); MapTestUtil::ExpectMapFieldsSet(message); - EXPECT_EQ(0, message.GetReflection()-> - GetUnknownFields(message).field_count()); + EXPECT_EQ(0, + message.GetReflection()->GetUnknownFields(message).field_count()); } TEST(ReflectionOpsForMapFieldTest, IsInitialized) { @@ -2899,7 +3193,7 @@ TEST(ReflectionOpsForMapFieldTest, IsInitialized) { TEST(WireFormatForMapFieldTest, ParseMap) { unittest::TestMap source, dest; - string data; + std::string data; // Serialize using the generated code. MapTestUtil::SetMapFields(&source); @@ -2918,22 +3212,22 @@ TEST(WireFormatForMapFieldTest, MapByteSize) { unittest::TestMap message; MapTestUtil::SetMapFields(&message); - EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message)); + EXPECT_EQ(message.ByteSizeLong(), WireFormat::ByteSize(message)); message.Clear(); - EXPECT_EQ(0, message.ByteSize()); + EXPECT_EQ(0, message.ByteSizeLong()); EXPECT_EQ(0, WireFormat::ByteSize(message)); } TEST(WireFormatForMapFieldTest, SerializeMap) { unittest::TestMap message; - string generated_data; - string dynamic_data; + std::string generated_data; + std::string dynamic_data; MapTestUtil::SetMapFields(&message); // Serialize using the generated code. { - message.ByteSize(); + message.ByteSizeLong(); io::StringOutputStream raw_output(&generated_data); io::CodedOutputStream output(&raw_output); message.SerializeWithCachedSizes(&output); @@ -2944,24 +3238,22 @@ TEST(WireFormatForMapFieldTest, SerializeMap) { { io::StringOutputStream raw_output(&dynamic_data); io::CodedOutputStream output(&raw_output); - int size = WireFormat::ByteSize(message); + size_t size = WireFormat::ByteSize(message); WireFormat::SerializeWithCachedSizes(message, size, &output); ASSERT_FALSE(output.HadError()); } - // Should be the same. - // Don't use EXPECT_EQ here because we're comparing raw binary data and - // we really don't want it dumped to stdout on failure. - EXPECT_TRUE(dynamic_data == generated_data); + // Should parse to the same message. + EXPECT_TRUE(TestUtil::EqualsToSerialized(message, generated_data)); + EXPECT_TRUE(TestUtil::EqualsToSerialized(message, dynamic_data)); } TEST(WireFormatForMapFieldTest, SerializeMapDynamicMessage) { DynamicMessageFactory factory; - google::protobuf::scoped_ptr dynamic_message; + std::unique_ptr dynamic_message; dynamic_message.reset( factory.GetPrototype(unittest::TestMap::descriptor())->New()); - MapReflectionTester reflection_tester( - unittest::TestMap::descriptor()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); reflection_tester.SetMapFieldsViaReflection(dynamic_message.get()); reflection_tester.ExpectMapFieldsSetViaReflection(*dynamic_message); @@ -2969,8 +3261,8 @@ TEST(WireFormatForMapFieldTest, SerializeMapDynamicMessage) { MapTestUtil::SetMapFields(&generated_message); MapTestUtil::ExpectMapFieldsSet(generated_message); - string generated_data; - string dynamic_data; + std::string generated_data; + std::string dynamic_data; // Serialize. generated_message.SerializeToString(&generated_data); @@ -2982,8 +3274,60 @@ TEST(WireFormatForMapFieldTest, SerializeMapDynamicMessage) { EXPECT_TRUE(dynamic_data.size() == generated_data.size()); } +TEST(WireFormatForMapFieldTest, MapByteSizeDynamicMessage) { + DynamicMessageFactory factory; + std::unique_ptr dynamic_message; + dynamic_message.reset( + factory.GetPrototype(unittest::TestMap::descriptor())->New()); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); + reflection_tester.SetMapFieldsViaReflection(dynamic_message.get()); + reflection_tester.ExpectMapFieldsSetViaReflection(*dynamic_message); + std::string expected_serialized_data; + dynamic_message->SerializeToString(&expected_serialized_data); + int expected_size = expected_serialized_data.size(); + EXPECT_EQ(dynamic_message->ByteSizeLong(), expected_size); + + std::unique_ptr message2; + message2.reset(factory.GetPrototype(unittest::TestMap::descriptor())->New()); + reflection_tester.SetMapFieldsViaMapReflection(message2.get()); + + const FieldDescriptor* field = + unittest::TestMap::descriptor()->FindFieldByName("map_int32_int32"); + const Reflection* reflection = dynamic_message->GetReflection(); + + // Force the map field to mark with STATE_MODIFIED_REPEATED + reflection->RemoveLast(dynamic_message.get(), field); + dynamic_message->MergeFrom(*message2); + dynamic_message->MergeFrom(*message2); + // The map field is marked as STATE_MODIFIED_REPEATED, ByteSizeLong() will use + // repeated field which have duplicate keys to calculate. + size_t duplicate_size = dynamic_message->ByteSizeLong(); + EXPECT_TRUE(duplicate_size > expected_size); + std::string duplicate_serialized_data; + dynamic_message->SerializeToString(&duplicate_serialized_data); + EXPECT_EQ(dynamic_message->ByteSizeLong(), duplicate_serialized_data.size()); + + // Force the map field to mark with map CLEAN + EXPECT_EQ(reflection_tester.MapSize(*dynamic_message, "map_int32_int32"), 2); + // The map field is marked as CLEAN, ByteSizeLong() will use map which do not + // have duplicate keys to calculate. + int size = dynamic_message->ByteSizeLong(); + EXPECT_EQ(expected_size, size); + + // Protobuf used to have a bug for serialize when map it marked CLEAN. It used + // repeated field to calculate ByteSizeLong but use map to serialize the real + // data, thus the ByteSizeLong may bigger than real serialized size. A crash + // might be happen at SerializeToString(). Or an "unexpected end group" + // warning was raised at parse back if user use SerializeWithCachedSizes() + // which avoids size check at serialize. + std::string serialized_data; + dynamic_message->SerializeToString(&serialized_data); + EXPECT_EQ(serialized_data, expected_serialized_data); + dynamic_message->ParseFromString(serialized_data); +} + TEST(WireFormatForMapFieldTest, MapParseHelpers) { - string data; + std::string data; { // Set up. @@ -3010,7 +3354,7 @@ TEST(WireFormatForMapFieldTest, MapParseHelpers) { { // Test ParseFromBoundedZeroCopyStream. - string data_with_junk(data); + std::string data_with_junk(data); data_with_junk.append("some junk on the end"); io::ArrayInputStream stream(data_with_junk.data(), data_with_junk.size()); protobuf_unittest::TestMap message; @@ -3024,18 +3368,18 @@ TEST(WireFormatForMapFieldTest, MapParseHelpers) { io::ArrayInputStream stream(data.data(), data.size()); protobuf_unittest::TestAllTypes message; EXPECT_FALSE( - message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1)); + message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1)); } } // Deterministic Serialization Test ========================================== template -static string DeterministicSerializationWithSerializePartialToCodedStream( +static std::string DeterministicSerializationWithSerializePartialToCodedStream( const T& t) { - const int size = t.ByteSize(); - string result(size, '\0'); - io::ArrayOutputStream array_stream(string_as_array(&result), size); + const size_t size = t.ByteSizeLong(); + std::string result(size, '\0'); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&result), size); io::CodedOutputStream output_stream(&array_stream); output_stream.SetSerializationDeterministic(true); t.SerializePartialToCodedStream(&output_stream); @@ -3045,10 +3389,11 @@ static string DeterministicSerializationWithSerializePartialToCodedStream( } template -static string DeterministicSerializationWithSerializeToCodedStream(const T& t) { - const int size = t.ByteSize(); - string result(size, '\0'); - io::ArrayOutputStream array_stream(string_as_array(&result), size); +static std::string DeterministicSerializationWithSerializeToCodedStream( + const T& t) { + const size_t size = t.ByteSizeLong(); + std::string result(size, '\0'); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&result), size); io::CodedOutputStream output_stream(&array_stream); output_stream.SetSerializationDeterministic(true); t.SerializeToCodedStream(&output_stream); @@ -3058,38 +3403,26 @@ static string DeterministicSerializationWithSerializeToCodedStream(const T& t) { } template -static string DeterministicSerialization(const T& t) { - const int size = t.ByteSize(); - string result(size, '\0'); - io::ArrayOutputStream array_stream(string_as_array(&result), size); - io::CodedOutputStream output_stream(&array_stream); - output_stream.SetSerializationDeterministic(true); - t.SerializeWithCachedSizes(&output_stream); - EXPECT_FALSE(output_stream.HadError()); - EXPECT_EQ(size, output_stream.ByteCount()); +static std::string DeterministicSerialization(const T& t) { + const size_t size = t.ByteSizeLong(); + std::string result(size, '\0'); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&result), size); + { + io::CodedOutputStream output_stream(&array_stream); + output_stream.SetSerializationDeterministic(true); + t.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } EXPECT_EQ(result, DeterministicSerializationWithSerializeToCodedStream(t)); EXPECT_EQ(result, DeterministicSerializationWithSerializePartialToCodedStream(t)); return result; } -// Helper to test the serialization of the first arg against a golden file. -static void TestDeterministicSerialization(const protobuf_unittest::TestMaps& t, - const string& filename) { - string expected; - GOOGLE_CHECK_OK(File::GetContents( - TestSourceDir() + "/google/protobuf/testdata/" + filename, - &expected, true)); - const string actual = DeterministicSerialization(t); - EXPECT_EQ(expected, actual); - protobuf_unittest::TestMaps u; - EXPECT_TRUE(u.ParseFromString(actual)); - EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(u, t)); -} - // Helper for MapSerializationTest. Return a 7-bit ASCII string. -static string ConstructKey(uint64 n) { - string s(n % static_cast(9), '\0'); +static std::string ConstructKey(uint64 n) { + std::string s(n % static_cast(9), '\0'); if (s.empty()) { return StrCat(n); } else { @@ -3115,7 +3448,7 @@ TEST(MapSerializationTest, Deterministic) { const int64 i64 = static_cast(frog); const uint64 u64 = frog * static_cast(187321); const bool b = i32 > 0; - const string s = ConstructKey(frog); + const std::string s = ConstructKey(frog); (*inner.mutable_m())[i] = i32; (*t.mutable_m_int32())[i32] = (*t.mutable_m_sint32())[i32] = (*t.mutable_m_sfixed32())[i32] = inner; @@ -3125,26 +3458,36 @@ TEST(MapSerializationTest, Deterministic) { (*t.mutable_m_uint64())[u64] = (*t.mutable_m_fixed64())[u64] = inner; (*t.mutable_m_bool())[b] = inner; (*t.mutable_m_string())[s] = inner; - (*t.mutable_m_string())[s + string(1 << (u32 % static_cast(9)), - b)] = inner; + (*t.mutable_m_string())[s + std::string(1 << (u32 % static_cast(9)), + b)] = inner; inner.mutable_m()->erase(i); frog = frog * multiplier + i; frog ^= (frog >> 41); } - TestDeterministicSerialization(t, "golden_message_maps"); + + // Verifies if two consecutive calls to deterministic serialization produce + // the same bytes. Deterministic serialization means the same serialization + // bytes in the same binary. + const std::string s1 = DeterministicSerialization(t); + const std::string s2 = DeterministicSerialization(t); + EXPECT_EQ(s1, s2); + + protobuf_unittest::TestMaps u; + EXPECT_TRUE(u.ParseFromString(s1)); + EXPECT_TRUE(util::MessageDifferencer::Equals(u, t)); } TEST(MapSerializationTest, DeterministicSubmessage) { protobuf_unittest::TestSubmessageMaps p; protobuf_unittest::TestMaps t; - const string filename = "golden_message_maps"; - string golden; + const std::string filename = "golden_message_maps"; + std::string golden; GOOGLE_CHECK_OK(File::GetContents( - TestSourceDir() + "/google/protobuf/testdata/" + filename, + TestUtil::GetTestDataPath("net/proto2/internal/testdata/" + filename), &golden, true)); t.ParseFromString(golden); *(p.mutable_m()) = t; - std::vector v; + std::vector v; // Use multiple attempts to increase the chance of a failure if something is // buggy. For example, each separate copy of a map might use a different // randomly-chosen hash function. @@ -3161,7 +3504,7 @@ TEST(TextFormatMapTest, SerializeAndParse) { unittest::TestMap source; unittest::TestMap dest; MapTestUtil::SetMapFields(&source); - string output; + std::string output; // Test compact ASCII TextFormat::Printer printer; @@ -3171,18 +3514,36 @@ TEST(TextFormatMapTest, SerializeAndParse) { MapTestUtil::ExpectMapFieldsSet(dest); } +TEST(TextFormatMapTest, DynamicMessage) { + TestMap prototype; + DynamicMessageFactory factory; + std::unique_ptr message( + factory.GetPrototype(prototype.GetDescriptor())->New()); + MapReflectionTester tester(message->GetDescriptor()); + tester.SetMapFieldsViaReflection(message.get()); + + std::string expected_text; + GOOGLE_CHECK_OK( + File::GetContents(TestUtil::GetTestDataPath("net/proto2/internal/" + "testdata/map_test_data.txt"), + &expected_text, true)); + + CleanStringLineEndings(&expected_text, false); + EXPECT_EQ(message->DebugString(), expected_text); +} + TEST(TextFormatMapTest, Sorted) { unittest::TestMap message; MapReflectionTester tester(message.GetDescriptor()); tester.SetMapFieldsViaReflection(&message); - string expected_text; - GOOGLE_CHECK_OK(File::GetContents( - TestSourceDir() + - "/google/protobuf/" - "testdata/map_test_data.txt", - &expected_text, true)); + std::string expected_text; + GOOGLE_CHECK_OK( + File::GetContents(TestUtil::GetTestDataPath("net/proto2/internal/" + "testdata/map_test_data.txt"), + &expected_text, true)); + CleanStringLineEndings(&expected_text, false); EXPECT_EQ(message.DebugString(), expected_text); // Test again on the reverse order. @@ -3193,17 +3554,88 @@ TEST(TextFormatMapTest, Sorted) { } TEST(TextFormatMapTest, ParseCorruptedString) { - string serialized_message; - GOOGLE_CHECK_OK(File::GetContents( - TestSourceDir() + - "/google/protobuf/testdata/golden_message_maps", - &serialized_message, true)); + std::string serialized_message; + GOOGLE_CHECK_OK( + File::GetContents(TestUtil::GetTestDataPath( + "net/proto2/internal/testdata/golden_message_maps"), + &serialized_message, true)); protobuf_unittest::TestMaps message; GOOGLE_CHECK(message.ParseFromString(serialized_message)); TestParseCorruptedString(message); TestParseCorruptedString(message); } +// Previously, serializing to text format will disable iterator from generated +// API. Now, the iterator can be still used even after serializing to text +// format. +TEST(TextFormatMapTest, NoDisableIterator) { + unittest::TestMap source; + (*source.mutable_map_int32_int32())[1] = 1; + + // Get iterator. + Map::iterator iter = source.mutable_map_int32_int32()->find(1); + + // Serialize message to text format, which will invalidate the previous + // iterator previously. + std::string output; + TextFormat::Printer printer; + printer.PrintToString(source, &output); + + // Modify map via the iterator (invalidated in previous implementation.). + iter->second = 2; + + // In previous implementation, the new change won't be reflected in text + // format, because the previous iterator has been invalidated. + output.clear(); + printer.PrintToString(source, &output); + std::string expected = + "map_int32_int32 {\n" + " key: 1\n" + " value: 2\n" + "}\n"; + EXPECT_EQ(output, expected); +} + +// Previously, serializing to text format will disable iterator from reflection +// API. +TEST(TextFormatMapTest, NoDisableReflectionIterator) { + unittest::TestMap source; + (*source.mutable_map_int32_int32())[1] = 1; + + // Get iterator. This will also sync internal repeated field with map inside + // of MapField. + const Reflection* reflection = source.GetReflection(); + const FieldDescriptor* field_desc = + source.GetDescriptor()->FindFieldByName("map_int32_int32"); + RepeatedPtrField* map_field = + reflection->MutableRepeatedPtrField(&source, field_desc); + RepeatedPtrField::iterator iter = map_field->begin(); + + // Serialize message to text format, which will invalidate the previous + // iterator previously. + std::string output; + TextFormat::Printer printer; + printer.PrintToString(source, &output); + + // Modify map via the iterator (invalidated in previous implementation.). + const Reflection* map_entry_reflection = iter->GetReflection(); + const FieldDescriptor* value_field_desc = + iter->GetDescriptor()->FindFieldByName("value"); + map_entry_reflection->SetInt32(&(*iter), value_field_desc, 2); + GOOGLE_LOG(INFO) << iter->DebugString(); + + // In previous implementation, the new change won't be reflected in text + // format, because the previous iterator has been invalidated. + output.clear(); + printer.PrintToString(source, &output); + std::string expected = + "map_int32_int32 {\n" + " key: 1\n" + " value: 2\n" + "}\n"; + EXPECT_EQ(output, expected); +} + // arena support ================================================= TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) { @@ -3213,7 +3645,7 @@ TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) { options.initial_block = &arena_block[0]; options.initial_block_size = arena_block.size(); Arena arena(options); - string data; + std::string data; data.reserve(128 * 1024); { @@ -3235,7 +3667,7 @@ TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) { // Use text format parsing and serializing to test reflection api. TEST(ArenaTest, ReflectionInTextFormat) { Arena arena; - string data; + std::string data; TextFormat::Printer printer; TextFormat::Parser parser; @@ -3257,7 +3689,7 @@ TEST(ArenaTest, StringMapNoLeak) { Arena arena; unittest::TestArenaMap* message = Arena::CreateMessage(&arena); - string data; + std::string data; // String with length less than 16 will not be allocated from heap. int original_capacity = data.capacity(); while (data.capacity() <= original_capacity) { @@ -3283,6 +3715,61 @@ TEST(ArenaTest, IsInitialized) { EXPECT_EQ(0, (*message->mutable_map_int32_int32())[0]); } +TEST(ArenaTest, DynamicMapFieldOnArena) { + Arena arena; + unittest::TestMap message2; + + DynamicMessageFactory factory; + Message* message1 = + factory.GetPrototype(unittest::TestMap::descriptor())->New(&arena); + MapReflectionTester reflection_tester(unittest::TestMap::descriptor()); + reflection_tester.SetMapFieldsViaReflection(message1); + reflection_tester.ExpectMapFieldsSetViaReflection(*message1); + reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1); + message2.CopyFrom(*message1); + MapTestUtil::ExpectMapFieldsSet(message2); +} + +TEST(MoveTest, MoveConstructorWorks) { + Map original_map; + original_map[42].mutable_optional_nested_message()->set_bb(42); + original_map[43].mutable_optional_nested_message()->set_bb(43); + const auto* nested_msg42_ptr = &original_map[42].optional_nested_message(); + const auto* nested_msg43_ptr = &original_map[43].optional_nested_message(); + + Map moved_to_map(std::move(original_map)); + EXPECT_TRUE(original_map.empty()); + EXPECT_EQ(2, moved_to_map.size()); + EXPECT_EQ(42, moved_to_map[42].optional_nested_message().bb()); + EXPECT_EQ(43, moved_to_map[43].optional_nested_message().bb()); + // This test takes advantage of the fact that pointers are swapped, so there + // should be pointer stability. + EXPECT_EQ(nested_msg42_ptr, &moved_to_map[42].optional_nested_message()); + EXPECT_EQ(nested_msg43_ptr, &moved_to_map[43].optional_nested_message()); +} + +TEST(MoveTest, MoveAssignmentWorks) { + Map original_map; + original_map[42].mutable_optional_nested_message()->set_bb(42); + original_map[43].mutable_optional_nested_message()->set_bb(43); + const auto* nested_msg42_ptr = &original_map[42].optional_nested_message(); + const auto* nested_msg43_ptr = &original_map[43].optional_nested_message(); + + Map moved_to_map = std::move(original_map); + EXPECT_TRUE(original_map.empty()); + EXPECT_EQ(2, moved_to_map.size()); + EXPECT_EQ(42, moved_to_map[42].optional_nested_message().bb()); + EXPECT_EQ(43, moved_to_map[43].optional_nested_message().bb()); + // This test takes advantage of the fact that pointers are swapped, so there + // should be pointer stability. + EXPECT_EQ(nested_msg42_ptr, &moved_to_map[42].optional_nested_message()); + EXPECT_EQ(nested_msg43_ptr, &moved_to_map[43].optional_nested_message()); +} + + +} // namespace } // namespace internal } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/map_test_util.cc b/src/google/protobuf/map_test_util.cc deleted file mode 100644 index 31ac173633069..0000000000000 --- a/src/google/protobuf/map_test_util.cc +++ /dev/null @@ -1,1829 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include -#include -#include -#include - -namespace google { -namespace protobuf { - -void MapTestUtil::SetMapFields(unittest::TestMap* message) { - MapTestUtilImpl::SetMapFields(message); -} - -void MapTestUtil::SetArenaMapFields(unittest::TestArenaMap* message) { - MapTestUtilImpl::SetArenaMapFields(message); -} - -void MapTestUtil::SetMapFieldsInitialized(unittest::TestMap* message) { - MapTestUtilImpl::SetMapFieldsInitialized(message); -} - -void MapTestUtil::ModifyMapFields(unittest::TestMap* message) { - MapTestUtilImpl::ModifyMapFields( - message); -} - -void MapTestUtil::ExpectClear(const unittest::TestMap& message) { - MapTestUtilImpl::ExpectClear(message); -} - -void MapTestUtil::ExpectMapFieldsSet(const unittest::TestMap& message) { - MapTestUtilImpl::ExpectMapFieldsSet(message); -} - -void MapTestUtil::ExpectArenaMapFieldsSet( - const unittest::TestArenaMap& message) { - MapTestUtilImpl::ExpectArenaMapFieldsSet< - unittest::MapEnum, unittest::MAP_ENUM_BAR, unittest::MAP_ENUM_BAZ>( - message); -} - -void MapTestUtil::ExpectMapFieldsSetInitialized( - const unittest::TestMap& message) { - MapTestUtilImpl::ExpectMapFieldsSetInitialized( - message); -} - -void MapTestUtil::ExpectMapFieldsModified( - const unittest::TestMap& message) { - MapTestUtilImpl::ExpectMapFieldsModified< - unittest::MapEnum, unittest::MAP_ENUM_BAR, unittest::MAP_ENUM_FOO>( - message); -} - -void MapTestUtil::ExpectMapsSize( - const unittest::TestMap& message, int size) { - const Descriptor* descriptor = message.GetDescriptor(); - - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_int32_int32"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_int64_int64"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_uint32_uint32"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_uint64_uint64"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_sint32_sint32"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_sint64_sint64"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_fixed32_fixed32"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_fixed64_fixed64"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_sfixed32_sfixed32"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_sfixed64_sfixed64"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_int32_float"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_int32_double"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_bool_bool"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_string_string"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_int32_bytes"))); - EXPECT_EQ(size, message.GetReflection()->FieldSize( - message, descriptor->FindFieldByName("map_int32_foreign_message"))); -} - -std::vector MapTestUtil::GetMapEntries( - const unittest::TestMap& message, int index) { - const Descriptor* descriptor = message.GetDescriptor(); - std::vector result; - - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_int32_int32"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_int64_int64"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_uint32_uint32"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_uint64_uint64"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_sint32_sint32"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_sint64_sint64"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_fixed32_fixed32"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_fixed64_fixed64"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_sfixed32_sfixed32"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_sfixed64_sfixed64"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_int32_float"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_int32_double"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_bool_bool"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_string_string"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_int32_bytes"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_int32_enum"), index)); - result.push_back(&message.GetReflection()->GetRepeatedMessage( - message, descriptor->FindFieldByName("map_int32_foreign_message"), index)); - - return result; -} - -std::vector MapTestUtil::GetMapEntriesFromRelease( - unittest::TestMap* message) { - const Descriptor* descriptor = message->GetDescriptor(); - std::vector result; - - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_int32_int32"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_int64_int64"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_uint32_uint32"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_uint64_uint64"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_sint32_sint32"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_sint64_sint64"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_fixed32_fixed32"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_fixed64_fixed64"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_sfixed32_sfixed32"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_sfixed64_sfixed64"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_int32_float"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_int32_double"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_bool_bool"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_string_string"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_int32_bytes"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_int32_enum"))); - result.push_back(message->GetReflection()->ReleaseLast( - message, descriptor->FindFieldByName("map_int32_foreign_message"))); - - return result; -} - -MapReflectionTester::MapReflectionTester( - const Descriptor* base_descriptor) - : base_descriptor_(base_descriptor) { - const DescriptorPool* pool = base_descriptor->file()->pool(); - - map_enum_foo_ = pool->FindEnumValueByName("protobuf_unittest.MAP_ENUM_FOO"); - map_enum_bar_ = pool->FindEnumValueByName("protobuf_unittest.MAP_ENUM_BAR"); - map_enum_baz_ = pool->FindEnumValueByName("protobuf_unittest.MAP_ENUM_BAZ"); - - foreign_c_ = pool->FindFieldByName( - "protobuf_unittest.ForeignMessage.c"); - map_int32_int32_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapInt32Int32Entry.key"); - map_int32_int32_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapInt32Int32Entry.value"); - map_int64_int64_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapInt64Int64Entry.key"); - map_int64_int64_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapInt64Int64Entry.value"); - map_uint32_uint32_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapUint32Uint32Entry.key"); - map_uint32_uint32_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapUint32Uint32Entry.value"); - map_uint64_uint64_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapUint64Uint64Entry.key"); - map_uint64_uint64_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapUint64Uint64Entry.value"); - map_sint32_sint32_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapSint32Sint32Entry.key"); - map_sint32_sint32_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapSint32Sint32Entry.value"); - map_sint64_sint64_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapSint64Sint64Entry.key"); - map_sint64_sint64_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapSint64Sint64Entry.value"); - map_fixed32_fixed32_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapFixed32Fixed32Entry.key"); - map_fixed32_fixed32_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapFixed32Fixed32Entry.value"); - map_fixed64_fixed64_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapFixed64Fixed64Entry.key"); - map_fixed64_fixed64_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapFixed64Fixed64Entry.value"); - map_sfixed32_sfixed32_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry.key"); - map_sfixed32_sfixed32_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry.value"); - map_sfixed64_sfixed64_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry.key"); - map_sfixed64_sfixed64_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry.value"); - map_int32_float_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapInt32FloatEntry.key"); - map_int32_float_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapInt32FloatEntry.value"); - map_int32_double_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapInt32DoubleEntry.key"); - map_int32_double_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapInt32DoubleEntry.value"); - map_bool_bool_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapBoolBoolEntry.key"); - map_bool_bool_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapBoolBoolEntry.value"); - map_string_string_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapStringStringEntry.key"); - map_string_string_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapStringStringEntry.value"); - map_int32_bytes_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapInt32BytesEntry.key"); - map_int32_bytes_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapInt32BytesEntry.value"); - map_int32_enum_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapInt32EnumEntry.key"); - map_int32_enum_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapInt32EnumEntry.value"); - map_int32_foreign_message_key_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapInt32ForeignMessageEntry.key"); - map_int32_foreign_message_val_ = pool->FindFieldByName( - "protobuf_unittest.TestMap.MapInt32ForeignMessageEntry.value"); - - EXPECT_FALSE(map_enum_foo_ == NULL); - EXPECT_FALSE(map_enum_bar_ == NULL); - EXPECT_FALSE(map_enum_baz_ == NULL); - EXPECT_FALSE(map_int32_int32_key_ == NULL); - EXPECT_FALSE(map_int32_int32_val_ == NULL); - EXPECT_FALSE(map_int64_int64_key_ == NULL); - EXPECT_FALSE(map_int64_int64_val_ == NULL); - EXPECT_FALSE(map_uint32_uint32_key_ == NULL); - EXPECT_FALSE(map_uint32_uint32_val_ == NULL); - EXPECT_FALSE(map_uint64_uint64_key_ == NULL); - EXPECT_FALSE(map_uint64_uint64_val_ == NULL); - EXPECT_FALSE(map_sint32_sint32_key_ == NULL); - EXPECT_FALSE(map_sint32_sint32_val_ == NULL); - EXPECT_FALSE(map_sint64_sint64_key_ == NULL); - EXPECT_FALSE(map_sint64_sint64_val_ == NULL); - EXPECT_FALSE(map_fixed32_fixed32_key_ == NULL); - EXPECT_FALSE(map_fixed32_fixed32_val_ == NULL); - EXPECT_FALSE(map_fixed64_fixed64_key_ == NULL); - EXPECT_FALSE(map_fixed64_fixed64_val_ == NULL); - EXPECT_FALSE(map_sfixed32_sfixed32_key_ == NULL); - EXPECT_FALSE(map_sfixed32_sfixed32_val_ == NULL); - EXPECT_FALSE(map_sfixed64_sfixed64_key_ == NULL); - EXPECT_FALSE(map_sfixed64_sfixed64_val_ == NULL); - EXPECT_FALSE(map_int32_float_key_ == NULL); - EXPECT_FALSE(map_int32_float_val_ == NULL); - EXPECT_FALSE(map_int32_double_key_ == NULL); - EXPECT_FALSE(map_int32_double_val_ == NULL); - EXPECT_FALSE(map_bool_bool_key_ == NULL); - EXPECT_FALSE(map_bool_bool_val_ == NULL); - EXPECT_FALSE(map_string_string_key_ == NULL); - EXPECT_FALSE(map_string_string_val_ == NULL); - EXPECT_FALSE(map_int32_bytes_key_ == NULL); - EXPECT_FALSE(map_int32_bytes_val_ == NULL); - EXPECT_FALSE(map_int32_enum_key_ == NULL); - EXPECT_FALSE(map_int32_enum_val_ == NULL); - EXPECT_FALSE(map_int32_foreign_message_key_ == NULL); - EXPECT_FALSE(map_int32_foreign_message_val_ == NULL); -} - -// Shorthand to get a FieldDescriptor for a field of unittest::TestMap. -const FieldDescriptor* MapReflectionTester::F(const string& name) { - const FieldDescriptor* result = NULL; - result = base_descriptor_->FindFieldByName(name); - GOOGLE_CHECK(result != NULL); - return result; -} - -void MapReflectionTester::SetMapFieldsViaReflection( - Message* message) { - const Reflection* reflection = message->GetReflection(); - Message* sub_message = NULL; - Message* sub_foreign_message = NULL; - - // Add first element. - sub_message = reflection->AddMessage(message, F("map_int32_int32")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_int32_key_, 0); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_int32_val_, 0); - - sub_message = reflection->AddMessage(message, F("map_int64_int64")); - sub_message->GetReflection() - ->SetInt64(sub_message, map_int64_int64_key_, 0); - sub_message->GetReflection() - ->SetInt64(sub_message, map_int64_int64_val_, 0); - - sub_message = reflection->AddMessage(message, F("map_uint32_uint32")); - sub_message->GetReflection() - ->SetUInt32(sub_message, map_uint32_uint32_key_, 0); - sub_message->GetReflection() - ->SetUInt32(sub_message, map_uint32_uint32_val_, 0); - - sub_message = reflection->AddMessage(message, F("map_uint64_uint64")); - sub_message->GetReflection() - ->SetUInt64(sub_message, map_uint64_uint64_key_, 0); - sub_message->GetReflection() - ->SetUInt64(sub_message, map_uint64_uint64_val_, 0); - - sub_message = reflection->AddMessage(message, F("map_sint32_sint32")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_sint32_sint32_key_, 0); - sub_message->GetReflection() - ->SetInt32(sub_message, map_sint32_sint32_val_, 0); - - sub_message = reflection->AddMessage(message, F("map_sint64_sint64")); - sub_message->GetReflection() - ->SetInt64(sub_message, map_sint64_sint64_key_, 0); - sub_message->GetReflection() - ->SetInt64(sub_message, map_sint64_sint64_val_, 0); - - sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32")); - sub_message->GetReflection() - ->SetUInt32(sub_message, map_fixed32_fixed32_key_, 0); - sub_message->GetReflection() - ->SetUInt32(sub_message, map_fixed32_fixed32_val_, 0); - - sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64")); - sub_message->GetReflection() - ->SetUInt64(sub_message, map_fixed64_fixed64_key_, 0); - sub_message->GetReflection() - ->SetUInt64(sub_message, map_fixed64_fixed64_val_, 0); - - sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_sfixed32_sfixed32_key_, 0); - sub_message->GetReflection() - ->SetInt32(sub_message, map_sfixed32_sfixed32_val_, 0); - - sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64")); - sub_message->GetReflection() - ->SetInt64(sub_message, map_sfixed64_sfixed64_key_, 0); - sub_message->GetReflection() - ->SetInt64(sub_message, map_sfixed64_sfixed64_val_, 0); - - sub_message = reflection->AddMessage(message, F("map_int32_float")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_float_key_, 0); - sub_message->GetReflection() - ->SetFloat(sub_message, map_int32_float_val_, 0.0); - - sub_message = reflection->AddMessage(message, F("map_int32_double")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_double_key_, 0); - sub_message->GetReflection() - ->SetDouble(sub_message, map_int32_double_val_, 0.0); - - sub_message = reflection->AddMessage(message, F("map_bool_bool")); - sub_message->GetReflection() - ->SetBool(sub_message, map_bool_bool_key_, false); - sub_message->GetReflection() - ->SetBool(sub_message, map_bool_bool_val_, false); - - sub_message = reflection->AddMessage(message, F("map_string_string")); - sub_message->GetReflection() - ->SetString(sub_message, map_string_string_key_, "0"); - sub_message->GetReflection() - ->SetString(sub_message, map_string_string_val_, "0"); - - sub_message = reflection->AddMessage(message, F("map_int32_bytes")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_bytes_key_, 0); - sub_message->GetReflection() - ->SetString(sub_message, map_int32_bytes_val_, "0"); - - sub_message = reflection->AddMessage(message, F("map_int32_enum")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_enum_key_, 0); - sub_message->GetReflection() - ->SetEnum(sub_message, map_int32_enum_val_, map_enum_bar_); - - sub_message = reflection - ->AddMessage(message, F("map_int32_foreign_message")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_foreign_message_key_, 0); - sub_foreign_message = sub_message->GetReflection()-> - MutableMessage(sub_message, map_int32_foreign_message_val_, NULL); - sub_foreign_message->GetReflection()-> - SetInt32(sub_foreign_message, foreign_c_, 0); - - // Add second element - sub_message = reflection->AddMessage(message, F("map_int32_int32")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_int32_key_, 1); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_int32_val_, 1); - - sub_message = reflection->AddMessage(message, F("map_int64_int64")); - sub_message->GetReflection() - ->SetInt64(sub_message, map_int64_int64_key_, 1); - sub_message->GetReflection() - ->SetInt64(sub_message, map_int64_int64_val_, 1); - - sub_message = reflection->AddMessage(message, F("map_uint32_uint32")); - sub_message->GetReflection() - ->SetUInt32(sub_message, map_uint32_uint32_key_, 1); - sub_message->GetReflection() - ->SetUInt32(sub_message, map_uint32_uint32_val_, 1); - - sub_message = reflection->AddMessage(message, F("map_uint64_uint64")); - sub_message->GetReflection() - ->SetUInt64(sub_message, map_uint64_uint64_key_, 1); - sub_message->GetReflection() - ->SetUInt64(sub_message, map_uint64_uint64_val_, 1); - - sub_message = reflection->AddMessage(message, F("map_sint32_sint32")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_sint32_sint32_key_, 1); - sub_message->GetReflection() - ->SetInt32(sub_message, map_sint32_sint32_val_, 1); - - sub_message = reflection->AddMessage(message, F("map_sint64_sint64")); - sub_message->GetReflection() - ->SetInt64(sub_message, map_sint64_sint64_key_, 1); - sub_message->GetReflection() - ->SetInt64(sub_message, map_sint64_sint64_val_, 1); - - sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32")); - sub_message->GetReflection() - ->SetUInt32(sub_message, map_fixed32_fixed32_key_, 1); - sub_message->GetReflection() - ->SetUInt32(sub_message, map_fixed32_fixed32_val_, 1); - - sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64")); - sub_message->GetReflection() - ->SetUInt64(sub_message, map_fixed64_fixed64_key_, 1); - sub_message->GetReflection() - ->SetUInt64(sub_message, map_fixed64_fixed64_val_, 1); - - sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_sfixed32_sfixed32_key_, 1); - sub_message->GetReflection() - ->SetInt32(sub_message, map_sfixed32_sfixed32_val_, 1); - - sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64")); - sub_message->GetReflection() - ->SetInt64(sub_message, map_sfixed64_sfixed64_key_, 1); - sub_message->GetReflection() - ->SetInt64(sub_message, map_sfixed64_sfixed64_val_, 1); - - sub_message = reflection->AddMessage(message, F("map_int32_float")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_float_key_, 1); - sub_message->GetReflection() - ->SetFloat(sub_message, map_int32_float_val_, 1.0); - - sub_message = reflection->AddMessage(message, F("map_int32_double")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_double_key_, 1); - sub_message->GetReflection() - ->SetDouble(sub_message, map_int32_double_val_, 1.0); - - sub_message = reflection->AddMessage(message, F("map_bool_bool")); - sub_message->GetReflection() - ->SetBool(sub_message, map_bool_bool_key_, true); - sub_message->GetReflection() - ->SetBool(sub_message, map_bool_bool_val_, true); - - sub_message = reflection->AddMessage(message, F("map_string_string")); - sub_message->GetReflection() - ->SetString(sub_message, map_string_string_key_, "1"); - sub_message->GetReflection() - ->SetString(sub_message, map_string_string_val_, "1"); - - sub_message = reflection->AddMessage(message, F("map_int32_bytes")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_bytes_key_, 1); - sub_message->GetReflection() - ->SetString(sub_message, map_int32_bytes_val_, "1"); - - sub_message = reflection->AddMessage(message, F("map_int32_enum")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_enum_key_, 1); - sub_message->GetReflection() - ->SetEnum(sub_message, map_int32_enum_val_, map_enum_baz_); - - sub_message = reflection - ->AddMessage(message, F("map_int32_foreign_message")); - sub_message->GetReflection() - ->SetInt32(sub_message, map_int32_foreign_message_key_, 1); - sub_foreign_message = sub_message->GetReflection()-> - MutableMessage(sub_message, map_int32_foreign_message_val_, NULL); - sub_foreign_message->GetReflection()-> - SetInt32(sub_foreign_message, foreign_c_, 1); -} - -void MapReflectionTester::SetMapFieldsViaMapReflection( - Message* message) { - const Reflection* reflection = message->GetReflection(); - - Message* sub_foreign_message = NULL; - MapValueRef map_val; - - // Add first element. - MapKey map_key; - map_key.SetInt32Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_int32_int32"), map_key, &map_val)); - map_val.SetInt32Value(0); - - map_key.SetInt64Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_int64_int64"), map_key, &map_val)); - map_val.SetInt64Value(0); - - map_key.SetUInt32Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_uint32_uint32"), map_key, &map_val)); - map_val.SetUInt32Value(0); - - map_key.SetUInt64Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_uint64_uint64"), map_key, &map_val)); - map_val.SetUInt64Value(0); - - map_key.SetInt32Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_sint32_sint32"), map_key, &map_val)); - map_val.SetInt32Value(0); - - map_key.SetInt64Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_sint64_sint64"), map_key, &map_val)); - map_val.SetInt64Value(0); - - map_key.SetUInt32Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_fixed32_fixed32"), map_key, &map_val)); - map_val.SetUInt32Value(0); - - map_key.SetUInt64Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_fixed64_fixed64"), map_key, &map_val)); - map_val.SetUInt64Value(0); - - map_key.SetInt32Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_sfixed32_sfixed32"), map_key, &map_val)); - map_val.SetInt32Value(0); - - map_key.SetInt64Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_sfixed64_sfixed64"), map_key, &map_val)); - map_val.SetInt64Value(0); - - map_key.SetInt32Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_int32_float"), map_key, &map_val)); - map_val.SetFloatValue(0.0); - - map_key.SetInt32Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_int32_double"), map_key, &map_val)); - map_val.SetDoubleValue(0.0); - - map_key.SetBoolValue(false); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_bool_bool"), map_key, &map_val)); - map_val.SetBoolValue(false); - - map_key.SetStringValue("0"); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_string_string"), map_key, &map_val)); - map_val.SetStringValue("0"); - - map_key.SetInt32Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_int32_bytes"), map_key, &map_val)); - map_val.SetStringValue("0"); - - map_key.SetInt32Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_int32_enum"), map_key, &map_val)); - map_val.SetEnumValue(map_enum_bar_->number()); - - map_key.SetInt32Value(0); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_int32_foreign_message"), map_key, &map_val)); - sub_foreign_message = map_val.MutableMessageValue(); - sub_foreign_message->GetReflection()->SetInt32( - sub_foreign_message, foreign_c_, 0); - - // Add second element - map_key.SetInt32Value(1); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_int32_int32"), map_key, &map_val)); - map_val.SetInt32Value(1); - EXPECT_FALSE(reflection->InsertOrLookupMapValue( - message, F("map_int32_int32"), map_key, &map_val)); - - map_key.SetInt64Value(1); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_int64_int64"), map_key, &map_val)); - map_val.SetInt64Value(1); - EXPECT_FALSE(reflection->InsertOrLookupMapValue( - message, F("map_int64_int64"), map_key, &map_val)); - - map_key.SetUInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_uint32_uint32"), map_key, &map_val); - map_val.SetUInt32Value(1); - - map_key.SetUInt64Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_uint64_uint64"), map_key, &map_val); - map_val.SetUInt64Value(1); - - map_key.SetInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_sint32_sint32"), map_key, &map_val); - map_val.SetInt32Value(1); - - map_key.SetInt64Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_sint64_sint64"), map_key, &map_val); - map_val.SetInt64Value(1); - - map_key.SetUInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_fixed32_fixed32"), map_key, &map_val); - map_val.SetUInt32Value(1); - - map_key.SetUInt64Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_fixed64_fixed64"), map_key, &map_val); - map_val.SetUInt64Value(1); - - map_key.SetInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_sfixed32_sfixed32"), map_key, &map_val); - map_val.SetInt32Value(1); - - map_key.SetInt64Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_sfixed64_sfixed64"), map_key, &map_val); - map_val.SetInt64Value(1); - - map_key.SetInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_int32_float"), map_key, &map_val); - map_val.SetFloatValue(1.0); - - map_key.SetInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_int32_double"), map_key, &map_val); - map_val.SetDoubleValue(1.0); - - map_key.SetBoolValue(true); - reflection->InsertOrLookupMapValue( - message, F("map_bool_bool"), map_key, &map_val); - map_val.SetBoolValue(true); - - map_key.SetStringValue("1"); - reflection->InsertOrLookupMapValue( - message, F("map_string_string"), map_key, &map_val); - map_val.SetStringValue("1"); - - map_key.SetInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_int32_bytes"), map_key, &map_val); - map_val.SetStringValue("1"); - - map_key.SetInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_int32_enum"), map_key, &map_val); - map_val.SetEnumValue(map_enum_baz_->number()); - - map_key.SetInt32Value(1); - EXPECT_TRUE(reflection->InsertOrLookupMapValue( - message, F("map_int32_foreign_message"), map_key, &map_val)); - sub_foreign_message = map_val.MutableMessageValue(); - sub_foreign_message->GetReflection()->SetInt32( - sub_foreign_message, foreign_c_, 1); -} - -void MapReflectionTester::GetMapValueViaMapReflection(Message* message, - const string& field_name, - const MapKey& map_key, - MapValueRef* map_val) { - const Reflection* reflection = message->GetReflection(); - EXPECT_FALSE(reflection->InsertOrLookupMapValue(message, F(field_name), - map_key, map_val)); -} - -Message* MapReflectionTester::GetMapEntryViaReflection(Message* message, - const string& field_name, - int index) { - const Reflection* reflection = message->GetReflection(); - return reflection->MutableRepeatedMessage(message, F(field_name), index); -} - -MapIterator MapReflectionTester::MapBegin(Message* message, - const string& field_name) { - const Reflection* reflection = message->GetReflection(); - return reflection->MapBegin(message, F(field_name)); -} - -MapIterator MapReflectionTester::MapEnd(Message* message, - const string& field_name) { - const Reflection* reflection = message->GetReflection(); - return reflection->MapEnd(message, F(field_name)); -} - -void MapReflectionTester::ClearMapFieldsViaReflection( - Message* message) { - const Reflection* reflection = message->GetReflection(); - - reflection->ClearField(message, F("map_int32_int32")); - reflection->ClearField(message, F("map_int64_int64")); - reflection->ClearField(message, F("map_uint32_uint32")); - reflection->ClearField(message, F("map_uint64_uint64")); - reflection->ClearField(message, F("map_sint32_sint32")); - reflection->ClearField(message, F("map_sint64_sint64")); - reflection->ClearField(message, F("map_fixed32_fixed32")); - reflection->ClearField(message, F("map_fixed64_fixed64")); - reflection->ClearField(message, F("map_sfixed32_sfixed32")); - reflection->ClearField(message, F("map_sfixed64_sfixed64")); - reflection->ClearField(message, F("map_int32_float")); - reflection->ClearField(message, F("map_int32_double")); - reflection->ClearField(message, F("map_bool_bool")); - reflection->ClearField(message, F("map_string_string")); - reflection->ClearField(message, F("map_int32_bytes")); - reflection->ClearField(message, F("map_int32_enum")); - reflection->ClearField(message, F("map_int32_foreign_message")); -} - -void MapReflectionTester::ModifyMapFieldsViaReflection( - Message* message) { - const Reflection* reflection = message->GetReflection(); - MapValueRef map_val; - Message* sub_foreign_message; - - // Modify the second element - MapKey map_key; - map_key.SetInt32Value(1); - EXPECT_FALSE(reflection->InsertOrLookupMapValue( - message, F("map_int32_int32"), map_key, &map_val)); - map_val.SetInt32Value(2); - - map_key.SetInt64Value(1); - EXPECT_FALSE(reflection->InsertOrLookupMapValue( - message, F("map_int64_int64"), map_key, &map_val)); - map_val.SetInt64Value(2); - - map_key.SetUInt32Value(1); - EXPECT_FALSE(reflection->InsertOrLookupMapValue( - message, F("map_uint32_uint32"), map_key, &map_val)); - map_val.SetUInt32Value(2); - - map_key.SetUInt64Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_uint64_uint64"), map_key, &map_val); - map_val.SetUInt64Value(2); - - map_key.SetInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_sint32_sint32"), map_key, &map_val); - map_val.SetInt32Value(2); - - map_key.SetInt64Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_sint64_sint64"), map_key, &map_val); - map_val.SetInt64Value(2); - - map_key.SetUInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_fixed32_fixed32"), map_key, &map_val); - map_val.SetUInt32Value(2); - - map_key.SetUInt64Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_fixed64_fixed64"), map_key, &map_val); - map_val.SetUInt64Value(2); - - map_key.SetInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_sfixed32_sfixed32"), map_key, &map_val); - map_val.SetInt32Value(2); - - map_key.SetInt64Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_sfixed64_sfixed64"), map_key, &map_val); - map_val.SetInt64Value(2); - - map_key.SetInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_int32_float"), map_key, &map_val); - map_val.SetFloatValue(2.0); - - map_key.SetInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_int32_double"), map_key, &map_val); - map_val.SetDoubleValue(2.0); - - map_key.SetBoolValue(true); - reflection->InsertOrLookupMapValue( - message, F("map_bool_bool"), map_key, &map_val); - map_val.SetBoolValue(false); - - map_key.SetStringValue("1"); - reflection->InsertOrLookupMapValue( - message, F("map_string_string"), map_key, &map_val); - map_val.SetStringValue("2"); - - map_key.SetInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_int32_bytes"), map_key, &map_val); - map_val.SetStringValue("2"); - - map_key.SetInt32Value(1); - reflection->InsertOrLookupMapValue( - message, F("map_int32_enum"), map_key, &map_val); - map_val.SetEnumValue(map_enum_foo_->number()); - - map_key.SetInt32Value(1); - EXPECT_FALSE(reflection->InsertOrLookupMapValue( - message, F("map_int32_foreign_message"), map_key, &map_val)); - sub_foreign_message = map_val.MutableMessageValue(); - sub_foreign_message->GetReflection()->SetInt32( - sub_foreign_message, foreign_c_, 2); -} - -void MapReflectionTester::RemoveLastMapsViaReflection( - Message* message) { - const Reflection* reflection = message->GetReflection(); - - std::vector output; - reflection->ListFields(*message, &output); - for (int i = 0; i < output.size(); ++i) { - const FieldDescriptor* field = output[i]; - if (!field->is_repeated()) continue; - reflection->RemoveLast(message, field); - } -} - -void MapReflectionTester::ReleaseLastMapsViaReflection( - Message* message) { - const Reflection* reflection = message->GetReflection(); - - std::vector output; - reflection->ListFields(*message, &output); - for (int i = 0; i < output.size(); ++i) { - const FieldDescriptor* field = output[i]; - if (!field->is_repeated()) continue; - if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; - - Message* released = reflection->ReleaseLast(message, field); - ASSERT_TRUE(released != NULL) << "ReleaseLast returned NULL for: " - << field->name(); - delete released; - } -} - -void MapReflectionTester::SwapMapsViaReflection(Message* message) { - const Reflection* reflection = message->GetReflection(); - std::vector output; - reflection->ListFields(*message, &output); - for (int i = 0; i < output.size(); ++i) { - const FieldDescriptor* field = output[i]; - if (!field->is_repeated()) continue; - reflection->SwapElements(message, field, 0, 1); - } -} - -void MapReflectionTester:: - MutableUnknownFieldsOfMapFieldsViaReflection(Message* message) { - const Reflection* reflection = message->GetReflection(); - Message* sub_message = NULL; - - sub_message = reflection->AddMessage(message, F("map_int32_int32")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_int64_int64")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_uint32_uint32")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_uint64_uint64")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_sint32_sint32")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_sint64_sint64")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_int32_float")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_int32_double")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_bool_bool")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_string_string")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_int32_bytes")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_int32_enum")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); - sub_message = reflection->AddMessage(message, F("map_int32_foreign_message")); - EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != - NULL); -} - -void MapReflectionTester::ExpectMapFieldsSetViaReflection( - const Message& message) { - string scratch; - const Reflection* reflection = message.GetReflection(); - const Message* sub_message; - MapKey map_key; - - // ----------------------------------------------------------------- - - ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_int32"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_int64_int64"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_uint32_uint32"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_uint64_uint64"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_sint32_sint32"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_sint64_sint64"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_fixed32_fixed32"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_fixed64_fixed64"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_sfixed32_sfixed32"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_sfixed64_sfixed64"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_float"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_double"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_bool_bool"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_string_string"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_bytes"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_enum"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_foreign_message"))); - - { - std::map map; - map[0] = 0; - map[1] = 1; - for (int i = 0; i < 2; i++) { - // Check with RepeatedField Reflection - sub_message = - &reflection->GetRepeatedMessage(message, F("map_int32_int32"), i); - int32 key = sub_message->GetReflection()->GetInt32( - *sub_message, map_int32_int32_key_); - int32 val = sub_message->GetReflection()->GetInt32( - *sub_message, map_int32_int32_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetInt32Value(key); - EXPECT_TRUE(reflection->ContainsMapKey( - message, F("map_int32_int32"), map_key)); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (int i = 0; i < 2; i++) { - // Check with RepeatedField Reflection - sub_message = - &reflection->GetRepeatedMessage(message, F("map_int64_int64"), i); - int64 key = sub_message->GetReflection()->GetInt64( - *sub_message, map_int64_int64_key_); - int64 val = sub_message->GetReflection()->GetInt64( - *sub_message, map_int64_int64_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetInt64Value(key); - EXPECT_TRUE(reflection->ContainsMapKey( - message, F("map_int64_int64"), map_key)); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (int i = 0; i < 2; i++) { - // Check with RepeatedField Reflection - sub_message = - &reflection->GetRepeatedMessage(message, F("map_uint32_uint32"), i); - uint32 key = sub_message->GetReflection()->GetUInt32( - *sub_message, map_uint32_uint32_key_); - uint32 val = sub_message->GetReflection()->GetUInt32( - *sub_message, map_uint32_uint32_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetUInt32Value(key); - EXPECT_TRUE(reflection->ContainsMapKey( - message, F("map_uint32_uint32"), map_key)); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (int i = 0; i < 2; i++) { - sub_message = - &reflection->GetRepeatedMessage(message, F("map_uint64_uint64"), i); - uint64 key = sub_message->GetReflection()->GetUInt64( - *sub_message, map_uint64_uint64_key_); - uint64 val = sub_message->GetReflection()->GetUInt64( - *sub_message, map_uint64_uint64_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetUInt64Value(key); - EXPECT_TRUE(reflection->ContainsMapKey( - message, F("map_uint64_uint64"), map_key)); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (int i = 0; i < 2; i++) { - sub_message = - &reflection->GetRepeatedMessage(message, F("map_sint32_sint32"), i); - int32 key = sub_message->GetReflection()->GetInt32( - *sub_message, map_sint32_sint32_key_); - int32 val = sub_message->GetReflection()->GetInt32( - *sub_message, map_sint32_sint32_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetInt32Value(key); - EXPECT_EQ(true, reflection->ContainsMapKey( - message, F("map_sint32_sint32"), map_key)); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (int i = 0; i < 2; i++) { - sub_message = - &reflection->GetRepeatedMessage(message, F("map_sint64_sint64"), i); - int64 key = sub_message->GetReflection()->GetInt64( - *sub_message, map_sint64_sint64_key_); - int64 val = sub_message->GetReflection()->GetInt64( - *sub_message, map_sint64_sint64_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetInt64Value(key); - EXPECT_EQ(true, reflection->ContainsMapKey( - message, F("map_sint64_sint64"), map_key)); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (int i = 0; i < 2; i++) { - sub_message = - &reflection->GetRepeatedMessage(message, F("map_fixed32_fixed32"), i); - uint32 key = sub_message->GetReflection()->GetUInt32( - *sub_message, map_fixed32_fixed32_key_); - uint32 val = sub_message->GetReflection()->GetUInt32( - *sub_message, map_fixed32_fixed32_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetUInt32Value(key); - EXPECT_EQ(true, reflection->ContainsMapKey( - message, F("map_fixed32_fixed32"), map_key)); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (int i = 0; i < 2; i++) { - sub_message = - &reflection->GetRepeatedMessage(message, F("map_fixed64_fixed64"), i); - uint64 key = sub_message->GetReflection()->GetUInt64( - *sub_message, map_fixed64_fixed64_key_); - uint64 val = sub_message->GetReflection()->GetUInt64( - *sub_message, map_fixed64_fixed64_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetUInt64Value(key); - EXPECT_EQ(true, reflection->ContainsMapKey( - message, F("map_fixed64_fixed64"), map_key)); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (int i = 0; i < 2; i++) { - sub_message = &reflection->GetRepeatedMessage( - message, F("map_sfixed32_sfixed32"), i); - int32 key = sub_message->GetReflection()->GetInt32( - *sub_message, map_sfixed32_sfixed32_key_); - int32 val = sub_message->GetReflection()->GetInt32( - *sub_message, map_sfixed32_sfixed32_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetInt32Value(key); - EXPECT_EQ(true, reflection->ContainsMapKey( - message, F("map_sfixed32_sfixed32"), map_key)); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (int i = 0; i < 2; i++) { - sub_message = &reflection->GetRepeatedMessage( - message, F("map_sfixed64_sfixed64"), i); - int64 key = sub_message->GetReflection()->GetInt64( - *sub_message, map_sfixed64_sfixed64_key_); - int64 val = sub_message->GetReflection()->GetInt64( - *sub_message, map_sfixed64_sfixed64_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetInt64Value(key); - EXPECT_EQ(true, reflection->ContainsMapKey( - message, F("map_sfixed64_sfixed64"), map_key)); - } - } - { - std::map map; - map[0] = 0.0; - map[1] = 1.0; - for (int i = 0; i < 2; i++) { - sub_message = - &reflection->GetRepeatedMessage(message, F("map_int32_float"), i); - int32 key = sub_message->GetReflection()->GetInt32( - *sub_message, map_int32_float_key_); - float val = sub_message->GetReflection()->GetFloat( - *sub_message, map_int32_float_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetInt32Value(key); - EXPECT_EQ(true, reflection->ContainsMapKey( - message, F("map_int32_float"), map_key)); - } - } - { - std::map map; - map[0] = 0.0; - map[1] = 1.0; - for (int i = 0; i < 2; i++) { - sub_message = - &reflection->GetRepeatedMessage(message, F("map_int32_double"), i); - int32 key = sub_message->GetReflection()->GetInt32( - *sub_message, map_int32_double_key_); - double val = sub_message->GetReflection()->GetDouble( - *sub_message, map_int32_double_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetInt32Value(key); - EXPECT_EQ(true, reflection->ContainsMapKey( - message, F("map_int32_double"), map_key)); - } - } - { - std::map map; - map[false] = false; - map[true] = true; - for (int i = 0; i < 2; i++) { - sub_message = - &reflection->GetRepeatedMessage(message, F("map_bool_bool"), i); - bool key = sub_message->GetReflection()->GetBool( - *sub_message, map_bool_bool_key_); - bool val = sub_message->GetReflection()->GetBool( - *sub_message, map_bool_bool_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetBoolValue(key); - EXPECT_EQ(true, reflection->ContainsMapKey( - message, F("map_bool_bool"), map_key)); - } - } - { - std::map map; - map["0"] = "0"; - map["1"] = "1"; - for (int i = 0; i < 2; i++) { - sub_message = - &reflection->GetRepeatedMessage(message, F("map_string_string"), i); - string key = sub_message->GetReflection()->GetString( - *sub_message, map_string_string_key_); - string val = sub_message->GetReflection()->GetString( - *sub_message, map_string_string_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetStringValue(key); - EXPECT_EQ(true, reflection->ContainsMapKey( - message, F("map_string_string"), map_key)); - } - } - { - std::map map; - map[0] = "0"; - map[1] = "1"; - for (int i = 0; i < 2; i++) { - sub_message = - &reflection->GetRepeatedMessage(message, F("map_int32_bytes"), i); - int32 key = sub_message->GetReflection()->GetInt32( - *sub_message, map_int32_bytes_key_); - string val = sub_message->GetReflection()->GetString( - *sub_message, map_int32_bytes_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetInt32Value(key); - EXPECT_EQ(true, reflection->ContainsMapKey( - message, F("map_int32_bytes"), map_key)); - } - } - { - std::map map; - map[0] = map_enum_bar_; - map[1] = map_enum_baz_; - for (int i = 0; i < 2; i++) { - sub_message = &reflection->GetRepeatedMessage( - message, F("map_int32_enum"), i); - int32 key = sub_message->GetReflection()->GetInt32( - *sub_message, map_int32_enum_key_); - const EnumValueDescriptor* val = sub_message->GetReflection()->GetEnum( - *sub_message, map_int32_enum_val_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetInt32Value(key); - EXPECT_EQ(true, reflection->ContainsMapKey( - message, F("map_int32_enum"), map_key)); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (int i = 0; i < 2; i++) { - sub_message = &reflection->GetRepeatedMessage( - message, F("map_int32_foreign_message"), i); - int32 key = sub_message->GetReflection()->GetInt32( - *sub_message, map_int32_foreign_message_key_); - const Message& foreign_message = sub_message->GetReflection()->GetMessage( - *sub_message, map_int32_foreign_message_val_); - int32 val = foreign_message.GetReflection()->GetInt32( - foreign_message, foreign_c_); - EXPECT_EQ(map[key], val); - // Check with Map Reflection - map_key.SetInt32Value(key); - EXPECT_EQ(true, reflection->ContainsMapKey( - message, F("map_int32_foreign_message"), map_key)); - } - } -} - -void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( - Message* message) { - string scratch; - string serialized; - const Reflection* reflection = message->GetReflection(); - - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_int32"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int64_int64"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_uint32_uint32"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_uint64_uint64"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sint32_sint32"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sint64_sint64"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_fixed32_fixed32"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_fixed64_fixed64"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sfixed32_sfixed32"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sfixed64_sfixed64"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_float"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_double"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_bool_bool"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_string_string"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_bytes"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_enum"))); - ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_foreign_message"))); - - { - std::map map; - map[0] = 0; - map[1] = 1; - int size = 0; - for (MapIterator iter = reflection->MapBegin(message, F("map_int32_int32")); - iter != reflection->MapEnd(message, F("map_int32_int32")); - ++iter, ++size) { - // Check const methods do not invalidate map. - message->DebugString(); - message->ShortDebugString(); - message->SerializeToString(&serialized); - message->SpaceUsed(); - message->ByteSize(); - EXPECT_EQ(map[iter.GetKey().GetInt32Value()], - iter.GetValueRef().GetInt32Value()); - } - EXPECT_EQ(size, 2); - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (MapIterator iter = reflection->MapBegin(message, F("map_int64_int64")); - iter != reflection->MapEnd(message, F("map_int64_int64")); ++iter) { - EXPECT_EQ(map[iter.GetKey().GetInt64Value()], - iter.GetValueRef().GetInt64Value()); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (MapIterator iter = reflection->MapBegin( - message, F("map_uint32_uint32")); - iter != reflection->MapEnd(message, F("map_uint32_uint32")); - ++iter) { - EXPECT_EQ(map[iter.GetKey().GetUInt32Value()], - iter.GetValueRef().GetUInt32Value()); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (MapIterator iter = reflection->MapBegin( - message, F("map_uint64_uint64")); - iter != reflection->MapEnd(message, F("map_uint64_uint64")); - ++iter) { - EXPECT_EQ(map[iter.GetKey().GetUInt64Value()], - iter.GetValueRef().GetUInt64Value()); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (MapIterator iter = reflection->MapBegin( - message, F("map_sint32_sint32")); - iter != reflection->MapEnd(message, F("map_sint32_sint32")); - ++iter) { - EXPECT_EQ(map[iter.GetKey().GetInt32Value()], - iter.GetValueRef().GetInt32Value()); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (MapIterator iter = reflection->MapBegin( - message, F("map_sint64_sint64")); - iter != reflection->MapEnd(message, F("map_sint64_sint64")); ++iter) { - EXPECT_EQ(map[iter.GetKey().GetInt64Value()], - iter.GetValueRef().GetInt64Value()); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (MapIterator iter = reflection->MapBegin( - message, F("map_fixed32_fixed32")); - iter != reflection->MapEnd(message, F("map_fixed32_fixed32")); - ++iter) { - EXPECT_EQ(map[iter.GetKey().GetUInt32Value()], - iter.GetValueRef().GetUInt32Value()); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (MapIterator iter = reflection->MapBegin( - message, F("map_fixed64_fixed64")); - iter != reflection->MapEnd(message, F("map_fixed64_fixed64")); - ++iter) { - EXPECT_EQ(map[iter.GetKey().GetUInt64Value()], - iter.GetValueRef().GetUInt64Value()); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - for (MapIterator iter = reflection->MapBegin( - message, F("map_sfixed32_sfixed32")); - iter != reflection->MapEnd(message, F("map_sfixed32_sfixed32")); - ++iter) { - EXPECT_EQ(map[iter.GetKey().GetInt32Value()], - iter.GetValueRef().GetInt32Value()); - } - } - { - std::map map; - map[0] = 0.0; - map[1] = 1.0; - for (MapIterator iter = reflection->MapBegin(message, F("map_int32_float")); - iter != reflection->MapEnd(message, F("map_int32_float")); ++iter) { - EXPECT_EQ(map[iter.GetKey().GetInt32Value()], - iter.GetValueRef().GetFloatValue()); - } - } - { - std::map map; - map[0] = 0.0; - map[1] = 1.0; - for (MapIterator iter = reflection->MapBegin( - message, F("map_int32_double")); - iter != reflection->MapEnd(message, F("map_int32_double")); ++iter) { - EXPECT_EQ(map[iter.GetKey().GetInt32Value()], - iter.GetValueRef().GetDoubleValue()); - } - } - { - std::map map; - map[false] = false; - map[true] = true; - for (MapIterator iter = reflection->MapBegin(message, F("map_bool_bool")); - iter != reflection->MapEnd(message, F("map_bool_bool")); ++iter) { - EXPECT_EQ(map[iter.GetKey().GetBoolValue()], - iter.GetValueRef().GetBoolValue()); - } - } - { - std::map map; - map["0"] = "0"; - map["1"] = "1"; - int size = 0; - for (MapIterator iter = reflection->MapBegin( - message, F("map_string_string")); - iter != reflection->MapEnd(message, F("map_string_string")); - ++iter, ++size) { - // Check const methods do not invalidate map. - message->DebugString(); - message->ShortDebugString(); - message->SerializeToString(&serialized); - message->SpaceUsed(); - message->ByteSize(); - EXPECT_EQ(map[iter.GetKey().GetStringValue()], - iter.GetValueRef().GetStringValue()); - } - EXPECT_EQ(size, 2); - } - { - std::map map; - map[0] = "0"; - map[1] = "1"; - for (MapIterator iter = reflection->MapBegin(message, F("map_int32_bytes")); - iter != reflection->MapEnd(message, F("map_int32_bytes")); ++iter) { - EXPECT_EQ(map[iter.GetKey().GetInt32Value()], - iter.GetValueRef().GetStringValue()); - } - } - { - std::map map; - map[0] = map_enum_bar_; - map[1] = map_enum_baz_; - for (MapIterator iter = reflection->MapBegin(message, F("map_int32_enum")); - iter != reflection->MapEnd(message, F("map_int32_enum")); ++iter) { - EXPECT_EQ(map[iter.GetKey().GetInt32Value()]->number(), - iter.GetValueRef().GetEnumValue()); - } - } - { - std::map map; - map[0] = 0; - map[1] = 1; - int size = 0; - for (MapIterator iter = reflection->MapBegin( - message, F("map_int32_foreign_message")); - iter != reflection->MapEnd(message, F("map_int32_foreign_message")); - ++iter, ++size) { - // Check const methods do not invalidate map. - message->DebugString(); - message->ShortDebugString(); - message->SerializeToString(&serialized); - message->SpaceUsed(); - message->ByteSize(); - const Message& sub_message = iter.GetValueRef().GetMessageValue(); - EXPECT_EQ(map[iter.GetKey().GetInt32Value()], - sub_message.GetReflection()->GetInt32(sub_message, foreign_c_)); - } - EXPECT_EQ(size, 2); - } -} - -void MapReflectionTester::ExpectClearViaReflection( - const Message& message) { - const Reflection* reflection = message.GetReflection(); - // Map fields are empty. - EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_int32"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_int64_int64"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_uint32_uint32"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_uint64_uint64"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_sint32_sint32"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_sint64_sint64"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_fixed32_fixed32"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_fixed64_fixed64"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_sfixed32_sfixed32"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_sfixed64_sfixed64"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_float"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_double"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_bool_bool"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_string_string"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_bytes"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_enum"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_foreign_message"))); -} - -void MapReflectionTester::ExpectClearViaReflectionIterator( - Message* message) { - const Reflection* reflection = message->GetReflection(); - EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_int32")) == - reflection->MapEnd(message, F("map_int32_int32"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_int64_int64")) == - reflection->MapEnd(message, F("map_int64_int64"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_uint32_uint32")) == - reflection->MapEnd(message, F("map_uint32_uint32"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_uint64_uint64")) == - reflection->MapEnd(message, F("map_uint64_uint64"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_sint32_sint32")) == - reflection->MapEnd(message, F("map_sint32_sint32"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_sint64_sint64")) == - reflection->MapEnd(message, F("map_sint64_sint64"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_fixed32_fixed32")) == - reflection->MapEnd(message, F("map_fixed32_fixed32"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_fixed64_fixed64")) == - reflection->MapEnd(message, F("map_fixed64_fixed64"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_sfixed32_sfixed32")) == - reflection->MapEnd(message, F("map_sfixed32_sfixed32"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_sfixed64_sfixed64")) == - reflection->MapEnd(message, F("map_sfixed64_sfixed64"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_float")) == - reflection->MapEnd(message, F("map_int32_float"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_double")) == - reflection->MapEnd(message, F("map_int32_double"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_bool_bool")) == - reflection->MapEnd(message, F("map_bool_bool"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_string_string")) == - reflection->MapEnd(message, F("map_string_string"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_bytes")) == - reflection->MapEnd(message, F("map_int32_bytes"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_enum")) == - reflection->MapEnd(message, F("map_int32_enum"))); - EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_foreign_message")) == - reflection->MapEnd(message, F("map_int32_foreign_message"))); -} - -void MapReflectionTester::ExpectMapEntryClearViaReflection( - Message* message) { - const Reflection* reflection = message->GetReflection(); - const Message* sub_message; - - { - const FieldDescriptor* descriptor = F("map_int32_int32"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_int32_int32")); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, - key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_int64_int64"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_int64_int64")); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message, - key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_uint32_uint32"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_uint32_uint32")); - EXPECT_EQ(0, sub_message->GetReflection()->GetUInt32(*sub_message, - key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection()->GetUInt32(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_uint64_uint64"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_uint64_uint64")); - EXPECT_EQ(0, sub_message->GetReflection()->GetUInt64(*sub_message, - key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection()->GetUInt64(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_sint32_sint32"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_sint32_sint32")); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, - key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_sint64_sint64"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_sint64_sint64")); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message, - key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_fixed32_fixed32"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32")); - EXPECT_EQ(0, sub_message->GetReflection()->GetUInt32(*sub_message, - key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection()->GetUInt32(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_fixed64_fixed64"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64")); - EXPECT_EQ(0, sub_message->GetReflection()->GetUInt64(*sub_message, - key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection()->GetUInt64(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_sfixed32_sfixed32"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32")); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, - key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_sfixed64_sfixed64"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64")); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message, - key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt64(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_int32_float"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_int32_float")); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, - key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection()->GetFloat(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_int32_double"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_int32_double")); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, - key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection()->GetDouble(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_bool_bool"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_bool_bool")); - EXPECT_EQ(false, sub_message->GetReflection()->GetBool(*sub_message, - key_descriptor)); - EXPECT_EQ(false, sub_message->GetReflection()->GetBool(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_string_string"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_string_string")); - EXPECT_EQ("", sub_message->GetReflection()->GetString(*sub_message, - key_descriptor)); - EXPECT_EQ("", sub_message->GetReflection()->GetString(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_int32_bytes"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_int32_bytes")); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, - key_descriptor)); - EXPECT_EQ("", sub_message->GetReflection()->GetString(*sub_message, - value_descriptor)); - } - { - const FieldDescriptor* descriptor = F("map_int32_enum"); - const FieldDescriptor* key_descriptor = - descriptor->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_descriptor = - descriptor->message_type()->FindFieldByName("value"); - sub_message = reflection->AddMessage(message, F("map_int32_enum")); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, - key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection() - ->GetEnum(*sub_message, value_descriptor) - ->number()); - } - // Map using message as value has been tested in other place. Thus, we don't - // test it here. -} - -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/map_test_util.h b/src/google/protobuf/map_test_util.h index dd397619bab66..c3b84d1eddd8d 100644 --- a/src/google/protobuf/map_test_util.h +++ b/src/google/protobuf/map_test_util.h @@ -33,57 +33,18 @@ #include +#define UNITTEST ::protobuf_unittest +// Must define UNITTEST before including map_test_util.inc. +#include +#undef UNITTEST + +#include + namespace google { namespace protobuf { namespace unittest = ::protobuf_unittest; -class MapTestUtil { - public: - // Set every field in the TestMap message to a unique value. - static void SetMapFields(unittest::TestMap* message); - - // Set every field in the TestArenaMap message to a unique value. - static void SetArenaMapFields(unittest::TestArenaMap* message); - - // Set every field in the message to a default value. - static void SetMapFieldsInitialized(unittest::TestMap* message); - - // Modify all the map fields of the message (which should already have been - // initialized with SetMapFields()). - static void ModifyMapFields(unittest::TestMap* message); - - // Check that all fields have the values that they should have after - // SetMapFields() is called. - static void ExpectMapFieldsSet(const unittest::TestMap& message); - - // Check that all fields have the values that they should have after - // SetMapFields() is called for TestArenaMap. - static void ExpectArenaMapFieldsSet(const unittest::TestArenaMap& message); - - // Check that all fields have the values that they should have after - // SetMapFieldsInitialized() is called. - static void ExpectMapFieldsSetInitialized( - const unittest::TestMap& message); - - // Expect that the message is modified as would be expected from - // ModifyMapFields(). - static void ExpectMapFieldsModified(const unittest::TestMap& message); - - // Check that all fields are empty. - static void ExpectClear(const unittest::TestMap& message); - - // Check that all map fields have the given size. - static void ExpectMapsSize(const unittest::TestMap& message, int size); - - // Get pointers of map entries at given index. - static std::vector GetMapEntries( - const unittest::TestMap& message, int index); - - // Get pointers of map entries from release. - static std::vector GetMapEntriesFromRelease( - unittest::TestMap* message); -}; // Like above, but use the reflection interface. class MapReflectionTester { @@ -105,17 +66,17 @@ class MapReflectionTester { void ExpectMapFieldsSetViaReflectionIterator(Message* message); void ExpectClearViaReflection(const Message& message); void ExpectClearViaReflectionIterator(Message* message); - void ExpectMapEntryClearViaReflection(Message* message); void GetMapValueViaMapReflection(Message* message, - const string& field_name, + const std::string& field_name, const MapKey& map_key, MapValueRef* map_val); - Message* GetMapEntryViaReflection(Message* message, const string& field_name, - int index); - MapIterator MapBegin(Message* message, const string& field_name); - MapIterator MapEnd(Message* message, const string& field_name); + Message* GetMapEntryViaReflection(Message* message, + const std::string& field_name, int index); + MapIterator MapBegin(Message* message, const std::string& field_name); + MapIterator MapEnd(Message* message, const std::string& field_name); + int MapSize(const Message& message, const std::string& field_name); private: - const FieldDescriptor* F(const string& name); + const FieldDescriptor* F(const std::string& name); const Descriptor* base_descriptor_; @@ -160,7 +121,1518 @@ class MapReflectionTester { const FieldDescriptor* map_int32_foreign_message_val_; }; -} // namespace protobuf +inline MapReflectionTester::MapReflectionTester( + const Descriptor* base_descriptor) + : base_descriptor_(base_descriptor) { + const DescriptorPool* pool = base_descriptor->file()->pool(); + std::string package = base_descriptor->file()->package(); + + map_enum_foo_ = pool->FindEnumValueByName(package + ".MAP_ENUM_FOO"); + map_enum_bar_ = pool->FindEnumValueByName(package + ".MAP_ENUM_BAR"); + map_enum_baz_ = pool->FindEnumValueByName(package + ".MAP_ENUM_BAZ"); + + foreign_c_ = pool->FindFieldByName(package + ".ForeignMessage.c"); + map_int32_int32_key_ = + pool->FindFieldByName(package + ".TestMap.MapInt32Int32Entry.key"); + map_int32_int32_val_ = + pool->FindFieldByName(package + ".TestMap.MapInt32Int32Entry.value"); + map_int64_int64_key_ = + pool->FindFieldByName(package + ".TestMap.MapInt64Int64Entry.key"); + map_int64_int64_val_ = + pool->FindFieldByName(package + ".TestMap.MapInt64Int64Entry.value"); + map_uint32_uint32_key_ = + pool->FindFieldByName(package + ".TestMap.MapUint32Uint32Entry.key"); + map_uint32_uint32_val_ = + pool->FindFieldByName(package + ".TestMap.MapUint32Uint32Entry.value"); + map_uint64_uint64_key_ = + pool->FindFieldByName(package + ".TestMap.MapUint64Uint64Entry.key"); + map_uint64_uint64_val_ = + pool->FindFieldByName(package + ".TestMap.MapUint64Uint64Entry.value"); + map_sint32_sint32_key_ = + pool->FindFieldByName(package + ".TestMap.MapSint32Sint32Entry.key"); + map_sint32_sint32_val_ = + pool->FindFieldByName(package + ".TestMap.MapSint32Sint32Entry.value"); + map_sint64_sint64_key_ = + pool->FindFieldByName(package + ".TestMap.MapSint64Sint64Entry.key"); + map_sint64_sint64_val_ = + pool->FindFieldByName(package + ".TestMap.MapSint64Sint64Entry.value"); + map_fixed32_fixed32_key_ = + pool->FindFieldByName(package + ".TestMap.MapFixed32Fixed32Entry.key"); + map_fixed32_fixed32_val_ = + pool->FindFieldByName(package + ".TestMap.MapFixed32Fixed32Entry.value"); + map_fixed64_fixed64_key_ = + pool->FindFieldByName(package + ".TestMap.MapFixed64Fixed64Entry.key"); + map_fixed64_fixed64_val_ = + pool->FindFieldByName(package + ".TestMap.MapFixed64Fixed64Entry.value"); + map_sfixed32_sfixed32_key_ = + pool->FindFieldByName(package + ".TestMap.MapSfixed32Sfixed32Entry.key"); + map_sfixed32_sfixed32_val_ = pool->FindFieldByName( + package + ".TestMap.MapSfixed32Sfixed32Entry.value"); + map_sfixed64_sfixed64_key_ = + pool->FindFieldByName(package + ".TestMap.MapSfixed64Sfixed64Entry.key"); + map_sfixed64_sfixed64_val_ = pool->FindFieldByName( + package + ".TestMap.MapSfixed64Sfixed64Entry.value"); + map_int32_float_key_ = + pool->FindFieldByName(package + ".TestMap.MapInt32FloatEntry.key"); + map_int32_float_val_ = + pool->FindFieldByName(package + ".TestMap.MapInt32FloatEntry.value"); + map_int32_double_key_ = + pool->FindFieldByName(package + ".TestMap.MapInt32DoubleEntry.key"); + map_int32_double_val_ = + pool->FindFieldByName(package + ".TestMap.MapInt32DoubleEntry.value"); + map_bool_bool_key_ = + pool->FindFieldByName(package + ".TestMap.MapBoolBoolEntry.key"); + map_bool_bool_val_ = + pool->FindFieldByName(package + ".TestMap.MapBoolBoolEntry.value"); + map_string_string_key_ = + pool->FindFieldByName(package + ".TestMap.MapStringStringEntry.key"); + map_string_string_val_ = + pool->FindFieldByName(package + ".TestMap.MapStringStringEntry.value"); + map_int32_bytes_key_ = + pool->FindFieldByName(package + ".TestMap.MapInt32BytesEntry.key"); + map_int32_bytes_val_ = + pool->FindFieldByName(package + ".TestMap.MapInt32BytesEntry.value"); + map_int32_enum_key_ = + pool->FindFieldByName(package + ".TestMap.MapInt32EnumEntry.key"); + map_int32_enum_val_ = + pool->FindFieldByName(package + ".TestMap.MapInt32EnumEntry.value"); + map_int32_foreign_message_key_ = pool->FindFieldByName( + package + ".TestMap.MapInt32ForeignMessageEntry.key"); + map_int32_foreign_message_val_ = pool->FindFieldByName( + package + ".TestMap.MapInt32ForeignMessageEntry.value"); + + EXPECT_FALSE(map_enum_foo_ == nullptr); + EXPECT_FALSE(map_enum_bar_ == nullptr); + EXPECT_FALSE(map_enum_baz_ == nullptr); + EXPECT_FALSE(map_int32_int32_key_ == nullptr); + EXPECT_FALSE(map_int32_int32_val_ == nullptr); + EXPECT_FALSE(map_int64_int64_key_ == nullptr); + EXPECT_FALSE(map_int64_int64_val_ == nullptr); + EXPECT_FALSE(map_uint32_uint32_key_ == nullptr); + EXPECT_FALSE(map_uint32_uint32_val_ == nullptr); + EXPECT_FALSE(map_uint64_uint64_key_ == nullptr); + EXPECT_FALSE(map_uint64_uint64_val_ == nullptr); + EXPECT_FALSE(map_sint32_sint32_key_ == nullptr); + EXPECT_FALSE(map_sint32_sint32_val_ == nullptr); + EXPECT_FALSE(map_sint64_sint64_key_ == nullptr); + EXPECT_FALSE(map_sint64_sint64_val_ == nullptr); + EXPECT_FALSE(map_fixed32_fixed32_key_ == nullptr); + EXPECT_FALSE(map_fixed32_fixed32_val_ == nullptr); + EXPECT_FALSE(map_fixed64_fixed64_key_ == nullptr); + EXPECT_FALSE(map_fixed64_fixed64_val_ == nullptr); + EXPECT_FALSE(map_sfixed32_sfixed32_key_ == nullptr); + EXPECT_FALSE(map_sfixed32_sfixed32_val_ == nullptr); + EXPECT_FALSE(map_sfixed64_sfixed64_key_ == nullptr); + EXPECT_FALSE(map_sfixed64_sfixed64_val_ == nullptr); + EXPECT_FALSE(map_int32_float_key_ == nullptr); + EXPECT_FALSE(map_int32_float_val_ == nullptr); + EXPECT_FALSE(map_int32_double_key_ == nullptr); + EXPECT_FALSE(map_int32_double_val_ == nullptr); + EXPECT_FALSE(map_bool_bool_key_ == nullptr); + EXPECT_FALSE(map_bool_bool_val_ == nullptr); + EXPECT_FALSE(map_string_string_key_ == nullptr); + EXPECT_FALSE(map_string_string_val_ == nullptr); + EXPECT_FALSE(map_int32_bytes_key_ == nullptr); + EXPECT_FALSE(map_int32_bytes_val_ == nullptr); + EXPECT_FALSE(map_int32_enum_key_ == nullptr); + EXPECT_FALSE(map_int32_enum_val_ == nullptr); + EXPECT_FALSE(map_int32_foreign_message_key_ == nullptr); + EXPECT_FALSE(map_int32_foreign_message_val_ == nullptr); + + std::vector all_map_descriptors = { + map_int32_int32_key_, + map_int32_int32_val_, + map_int64_int64_key_, + map_int64_int64_val_, + map_uint32_uint32_key_, + map_uint32_uint32_val_, + map_uint64_uint64_key_, + map_uint64_uint64_val_, + map_sint32_sint32_key_, + map_sint32_sint32_val_, + map_sint64_sint64_key_, + map_sint64_sint64_val_, + map_fixed32_fixed32_key_, + map_fixed32_fixed32_val_, + map_fixed64_fixed64_key_, + map_fixed64_fixed64_val_, + map_sfixed32_sfixed32_key_, + map_sfixed32_sfixed32_val_, + map_sfixed64_sfixed64_key_, + map_sfixed64_sfixed64_val_, + map_int32_float_key_, + map_int32_float_val_, + map_int32_double_key_, + map_int32_double_val_, + map_bool_bool_key_, + map_bool_bool_val_, + map_string_string_key_, + map_string_string_val_, + map_int32_bytes_key_, + map_int32_bytes_val_, + map_int32_enum_key_, + map_int32_enum_val_, + map_int32_foreign_message_key_, + map_int32_foreign_message_val_}; + for (const FieldDescriptor* fdesc : all_map_descriptors) { + GOOGLE_CHECK(fdesc->containing_type() != nullptr) << fdesc->name(); + if (fdesc->name() == "key") { + EXPECT_EQ(fdesc->containing_type()->map_key(), fdesc); + } else { + EXPECT_EQ(fdesc->name(), "value"); + EXPECT_EQ(fdesc->containing_type()->map_value(), fdesc); + } + } +} + +// Shorthand to get a FieldDescriptor for a field of unittest::TestMap. +inline const FieldDescriptor* MapReflectionTester::F(const std::string& name) { + const FieldDescriptor* result = nullptr; + result = base_descriptor_->FindFieldByName(name); + GOOGLE_CHECK(result != nullptr); + return result; +} + +inline void MapReflectionTester::SetMapFieldsViaReflection(Message* message) { + const Reflection* reflection = message->GetReflection(); + Message* sub_message = nullptr; + Message* sub_foreign_message = nullptr; + + // Add first element. + sub_message = reflection->AddMessage(message, F("map_int32_int32")); + sub_message->GetReflection()->SetInt32(sub_message, map_int32_int32_key_, 0); + sub_message->GetReflection()->SetInt32(sub_message, map_int32_int32_val_, 0); + + sub_message = reflection->AddMessage(message, F("map_int64_int64")); + sub_message->GetReflection()->SetInt64(sub_message, map_int64_int64_key_, 0); + sub_message->GetReflection()->SetInt64(sub_message, map_int64_int64_val_, 0); + + sub_message = reflection->AddMessage(message, F("map_uint32_uint32")); + sub_message->GetReflection()->SetUInt32(sub_message, map_uint32_uint32_key_, + 0); + sub_message->GetReflection()->SetUInt32(sub_message, map_uint32_uint32_val_, + 0); + + sub_message = reflection->AddMessage(message, F("map_uint64_uint64")); + sub_message->GetReflection()->SetUInt64(sub_message, map_uint64_uint64_key_, + 0); + sub_message->GetReflection()->SetUInt64(sub_message, map_uint64_uint64_val_, + 0); + + sub_message = reflection->AddMessage(message, F("map_sint32_sint32")); + sub_message->GetReflection()->SetInt32(sub_message, map_sint32_sint32_key_, + 0); + sub_message->GetReflection()->SetInt32(sub_message, map_sint32_sint32_val_, + 0); + + sub_message = reflection->AddMessage(message, F("map_sint64_sint64")); + sub_message->GetReflection()->SetInt64(sub_message, map_sint64_sint64_key_, + 0); + sub_message->GetReflection()->SetInt64(sub_message, map_sint64_sint64_val_, + 0); + + sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32")); + sub_message->GetReflection()->SetUInt32(sub_message, map_fixed32_fixed32_key_, + 0); + sub_message->GetReflection()->SetUInt32(sub_message, map_fixed32_fixed32_val_, + 0); + + sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64")); + sub_message->GetReflection()->SetUInt64(sub_message, map_fixed64_fixed64_key_, + 0); + sub_message->GetReflection()->SetUInt64(sub_message, map_fixed64_fixed64_val_, + 0); + + sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32")); + sub_message->GetReflection()->SetInt32(sub_message, + map_sfixed32_sfixed32_key_, 0); + sub_message->GetReflection()->SetInt32(sub_message, + map_sfixed32_sfixed32_val_, 0); + + sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64")); + sub_message->GetReflection()->SetInt64(sub_message, + map_sfixed64_sfixed64_key_, 0); + sub_message->GetReflection()->SetInt64(sub_message, + map_sfixed64_sfixed64_val_, 0); + + sub_message = reflection->AddMessage(message, F("map_int32_float")); + sub_message->GetReflection()->SetInt32(sub_message, map_int32_float_key_, 0); + sub_message->GetReflection()->SetFloat(sub_message, map_int32_float_val_, + 0.0); + + sub_message = reflection->AddMessage(message, F("map_int32_double")); + sub_message->GetReflection()->SetInt32(sub_message, map_int32_double_key_, 0); + sub_message->GetReflection()->SetDouble(sub_message, map_int32_double_val_, + 0.0); + + sub_message = reflection->AddMessage(message, F("map_bool_bool")); + sub_message->GetReflection()->SetBool(sub_message, map_bool_bool_key_, false); + sub_message->GetReflection()->SetBool(sub_message, map_bool_bool_val_, false); + + sub_message = reflection->AddMessage(message, F("map_string_string")); + sub_message->GetReflection()->SetString(sub_message, map_string_string_key_, + "0"); + sub_message->GetReflection()->SetString(sub_message, map_string_string_val_, + "0"); + + sub_message = reflection->AddMessage(message, F("map_int32_bytes")); + sub_message->GetReflection()->SetInt32(sub_message, map_int32_bytes_key_, 0); + sub_message->GetReflection()->SetString(sub_message, map_int32_bytes_val_, + "0"); + + sub_message = reflection->AddMessage(message, F("map_int32_enum")); + sub_message->GetReflection()->SetInt32(sub_message, map_int32_enum_key_, 0); + sub_message->GetReflection()->SetEnum(sub_message, map_int32_enum_val_, + map_enum_bar_); + + sub_message = reflection->AddMessage(message, F("map_int32_foreign_message")); + sub_message->GetReflection()->SetInt32(sub_message, + map_int32_foreign_message_key_, 0); + sub_foreign_message = sub_message->GetReflection()->MutableMessage( + sub_message, map_int32_foreign_message_val_, nullptr); + sub_foreign_message->GetReflection()->SetInt32(sub_foreign_message, + foreign_c_, 0); + + // Add second element + sub_message = reflection->AddMessage(message, F("map_int32_int32")); + sub_message->GetReflection()->SetInt32(sub_message, map_int32_int32_key_, 1); + sub_message->GetReflection()->SetInt32(sub_message, map_int32_int32_val_, 1); + + sub_message = reflection->AddMessage(message, F("map_int64_int64")); + sub_message->GetReflection()->SetInt64(sub_message, map_int64_int64_key_, 1); + sub_message->GetReflection()->SetInt64(sub_message, map_int64_int64_val_, 1); + + sub_message = reflection->AddMessage(message, F("map_uint32_uint32")); + sub_message->GetReflection()->SetUInt32(sub_message, map_uint32_uint32_key_, + 1); + sub_message->GetReflection()->SetUInt32(sub_message, map_uint32_uint32_val_, + 1); + + sub_message = reflection->AddMessage(message, F("map_uint64_uint64")); + sub_message->GetReflection()->SetUInt64(sub_message, map_uint64_uint64_key_, + 1); + sub_message->GetReflection()->SetUInt64(sub_message, map_uint64_uint64_val_, + 1); + + sub_message = reflection->AddMessage(message, F("map_sint32_sint32")); + sub_message->GetReflection()->SetInt32(sub_message, map_sint32_sint32_key_, + 1); + sub_message->GetReflection()->SetInt32(sub_message, map_sint32_sint32_val_, + 1); + + sub_message = reflection->AddMessage(message, F("map_sint64_sint64")); + sub_message->GetReflection()->SetInt64(sub_message, map_sint64_sint64_key_, + 1); + sub_message->GetReflection()->SetInt64(sub_message, map_sint64_sint64_val_, + 1); + + sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32")); + sub_message->GetReflection()->SetUInt32(sub_message, map_fixed32_fixed32_key_, + 1); + sub_message->GetReflection()->SetUInt32(sub_message, map_fixed32_fixed32_val_, + 1); + + sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64")); + sub_message->GetReflection()->SetUInt64(sub_message, map_fixed64_fixed64_key_, + 1); + sub_message->GetReflection()->SetUInt64(sub_message, map_fixed64_fixed64_val_, + 1); + + sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32")); + sub_message->GetReflection()->SetInt32(sub_message, + map_sfixed32_sfixed32_key_, 1); + sub_message->GetReflection()->SetInt32(sub_message, + map_sfixed32_sfixed32_val_, 1); + + sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64")); + sub_message->GetReflection()->SetInt64(sub_message, + map_sfixed64_sfixed64_key_, 1); + sub_message->GetReflection()->SetInt64(sub_message, + map_sfixed64_sfixed64_val_, 1); + + sub_message = reflection->AddMessage(message, F("map_int32_float")); + sub_message->GetReflection()->SetInt32(sub_message, map_int32_float_key_, 1); + sub_message->GetReflection()->SetFloat(sub_message, map_int32_float_val_, + 1.0); + + sub_message = reflection->AddMessage(message, F("map_int32_double")); + sub_message->GetReflection()->SetInt32(sub_message, map_int32_double_key_, 1); + sub_message->GetReflection()->SetDouble(sub_message, map_int32_double_val_, + 1.0); + + sub_message = reflection->AddMessage(message, F("map_bool_bool")); + sub_message->GetReflection()->SetBool(sub_message, map_bool_bool_key_, true); + sub_message->GetReflection()->SetBool(sub_message, map_bool_bool_val_, true); + + sub_message = reflection->AddMessage(message, F("map_string_string")); + sub_message->GetReflection()->SetString(sub_message, map_string_string_key_, + "1"); + sub_message->GetReflection()->SetString(sub_message, map_string_string_val_, + "1"); + + sub_message = reflection->AddMessage(message, F("map_int32_bytes")); + sub_message->GetReflection()->SetInt32(sub_message, map_int32_bytes_key_, 1); + sub_message->GetReflection()->SetString(sub_message, map_int32_bytes_val_, + "1"); + + sub_message = reflection->AddMessage(message, F("map_int32_enum")); + sub_message->GetReflection()->SetInt32(sub_message, map_int32_enum_key_, 1); + sub_message->GetReflection()->SetEnum(sub_message, map_int32_enum_val_, + map_enum_baz_); + + sub_message = reflection->AddMessage(message, F("map_int32_foreign_message")); + sub_message->GetReflection()->SetInt32(sub_message, + map_int32_foreign_message_key_, 1); + sub_foreign_message = sub_message->GetReflection()->MutableMessage( + sub_message, map_int32_foreign_message_val_, nullptr); + sub_foreign_message->GetReflection()->SetInt32(sub_foreign_message, + foreign_c_, 1); +} + +inline void MapReflectionTester::SetMapFieldsViaMapReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + + Message* sub_foreign_message = nullptr; + MapValueRef map_val; + MapValueConstRef map_val_const; + + // Add first element. + MapKey map_key; + map_key.SetInt32Value(0); + EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_int32_int32"), + map_key, &map_val_const)); + EXPECT_TRUE(reflection->InsertOrLookupMapValue(message, F("map_int32_int32"), + map_key, &map_val)); + map_val.SetInt32Value(0); + + map_key.SetInt64Value(0); + EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_int64_int64"), + map_key, &map_val_const)); + EXPECT_TRUE(reflection->InsertOrLookupMapValue(message, F("map_int64_int64"), + map_key, &map_val)); + map_val.SetInt64Value(0); + + map_key.SetUInt32Value(0); + EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_uint32_uint32"), + map_key, &map_val_const)); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_uint32_uint32"), map_key, &map_val)); + map_val.SetUInt32Value(0); + + map_key.SetUInt64Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_uint64_uint64"), map_key, &map_val)); + map_val.SetUInt64Value(0); + + map_key.SetInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_sint32_sint32"), map_key, &map_val)); + map_val.SetInt32Value(0); + + map_key.SetInt64Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_sint64_sint64"), map_key, &map_val)); + map_val.SetInt64Value(0); + + map_key.SetUInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_fixed32_fixed32"), map_key, &map_val)); + map_val.SetUInt32Value(0); + + map_key.SetUInt64Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_fixed64_fixed64"), map_key, &map_val)); + map_val.SetUInt64Value(0); + + map_key.SetInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_sfixed32_sfixed32"), map_key, &map_val)); + map_val.SetInt32Value(0); + + map_key.SetInt64Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_sfixed64_sfixed64"), map_key, &map_val)); + map_val.SetInt64Value(0); + + map_key.SetInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue(message, F("map_int32_float"), + map_key, &map_val)); + map_val.SetFloatValue(0.0); + map_key.SetInt32Value(0); + EXPECT_TRUE(reflection->InsertOrLookupMapValue(message, F("map_int32_double"), + map_key, &map_val)); + map_val.SetDoubleValue(0.0); + + map_key.SetBoolValue(false); + EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_bool_bool"), map_key, + &map_val_const)); + EXPECT_TRUE(reflection->InsertOrLookupMapValue(message, F("map_bool_bool"), + map_key, &map_val)); + map_val.SetBoolValue(false); + + map_key.SetStringValue("0"); + EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_string_string"), + map_key, &map_val_const)); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_string_string"), map_key, &map_val)); + map_val.SetStringValue("0"); + + map_key.SetInt32Value(0); + EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_int32_bytes"), + map_key, &map_val_const)); + EXPECT_TRUE(reflection->InsertOrLookupMapValue(message, F("map_int32_bytes"), + map_key, &map_val)); + map_val.SetStringValue("0"); + + map_key.SetInt32Value(0); + EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_int32_enum"), + map_key, &map_val_const)); + EXPECT_TRUE(reflection->InsertOrLookupMapValue(message, F("map_int32_enum"), + map_key, &map_val)); + map_val.SetEnumValue(map_enum_bar_->number()); + + map_key.SetInt32Value(0); + EXPECT_FALSE(reflection->LookupMapValue( + *message, F("map_int32_foreign_message"), map_key, &map_val_const)); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_int32_foreign_message"), map_key, &map_val)); + sub_foreign_message = map_val.MutableMessageValue(); + sub_foreign_message->GetReflection()->SetInt32(sub_foreign_message, + foreign_c_, 0); + + // Add second element + map_key.SetInt32Value(1); + EXPECT_TRUE(reflection->InsertOrLookupMapValue(message, F("map_int32_int32"), + map_key, &map_val)); + map_val.SetInt32Value(1); + EXPECT_FALSE(reflection->InsertOrLookupMapValue(message, F("map_int32_int32"), + map_key, &map_val)); + + map_key.SetInt64Value(1); + EXPECT_TRUE(reflection->InsertOrLookupMapValue(message, F("map_int64_int64"), + map_key, &map_val)); + map_val.SetInt64Value(1); + EXPECT_FALSE(reflection->InsertOrLookupMapValue(message, F("map_int64_int64"), + map_key, &map_val)); + + map_key.SetUInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_uint32_uint32"), map_key, + &map_val); + map_val.SetUInt32Value(1); + + map_key.SetUInt64Value(1); + reflection->InsertOrLookupMapValue(message, F("map_uint64_uint64"), map_key, + &map_val); + map_val.SetUInt64Value(1); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_sint32_sint32"), map_key, + &map_val); + map_val.SetInt32Value(1); + + map_key.SetInt64Value(1); + reflection->InsertOrLookupMapValue(message, F("map_sint64_sint64"), map_key, + &map_val); + map_val.SetInt64Value(1); + + map_key.SetUInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_fixed32_fixed32"), map_key, + &map_val); + map_val.SetUInt32Value(1); + + map_key.SetUInt64Value(1); + reflection->InsertOrLookupMapValue(message, F("map_fixed64_fixed64"), map_key, + &map_val); + map_val.SetUInt64Value(1); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_sfixed32_sfixed32"), + map_key, &map_val); + map_val.SetInt32Value(1); + + map_key.SetInt64Value(1); + reflection->InsertOrLookupMapValue(message, F("map_sfixed64_sfixed64"), + map_key, &map_val); + map_val.SetInt64Value(1); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_int32_float"), map_key, + &map_val); + map_val.SetFloatValue(1.0); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_int32_double"), map_key, + &map_val); + map_val.SetDoubleValue(1.0); + + map_key.SetBoolValue(true); + reflection->InsertOrLookupMapValue(message, F("map_bool_bool"), map_key, + &map_val); + map_val.SetBoolValue(true); + + map_key.SetStringValue("1"); + reflection->InsertOrLookupMapValue(message, F("map_string_string"), map_key, + &map_val); + map_val.SetStringValue("1"); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_int32_bytes"), map_key, + &map_val); + map_val.SetStringValue("1"); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_int32_enum"), map_key, + &map_val); + map_val.SetEnumValue(map_enum_baz_->number()); + + map_key.SetInt32Value(1); + EXPECT_TRUE(reflection->InsertOrLookupMapValue( + message, F("map_int32_foreign_message"), map_key, &map_val)); + sub_foreign_message = map_val.MutableMessageValue(); + sub_foreign_message->GetReflection()->SetInt32(sub_foreign_message, + foreign_c_, 1); +} + +inline void MapReflectionTester::GetMapValueViaMapReflection( + Message* message, const std::string& field_name, const MapKey& map_key, + MapValueRef* map_val) { + const Reflection* reflection = message->GetReflection(); + EXPECT_FALSE(reflection->InsertOrLookupMapValue(message, F(field_name), + map_key, map_val)); +} + +inline Message* MapReflectionTester::GetMapEntryViaReflection( + Message* message, const std::string& field_name, int index) { + const Reflection* reflection = message->GetReflection(); + return reflection->MutableRepeatedMessage(message, F(field_name), index); +} + +inline MapIterator MapReflectionTester::MapBegin( + Message* message, const std::string& field_name) { + const Reflection* reflection = message->GetReflection(); + return reflection->MapBegin(message, F(field_name)); +} + +inline MapIterator MapReflectionTester::MapEnd(Message* message, + const std::string& field_name) { + const Reflection* reflection = message->GetReflection(); + return reflection->MapEnd(message, F(field_name)); +} + +inline int MapReflectionTester::MapSize(const Message& message, + const std::string& field_name) { + const Reflection* reflection = message.GetReflection(); + return reflection->MapSize(message, F(field_name)); +} + +inline void MapReflectionTester::ClearMapFieldsViaReflection(Message* message) { + const Reflection* reflection = message->GetReflection(); + + reflection->ClearField(message, F("map_int32_int32")); + reflection->ClearField(message, F("map_int64_int64")); + reflection->ClearField(message, F("map_uint32_uint32")); + reflection->ClearField(message, F("map_uint64_uint64")); + reflection->ClearField(message, F("map_sint32_sint32")); + reflection->ClearField(message, F("map_sint64_sint64")); + reflection->ClearField(message, F("map_fixed32_fixed32")); + reflection->ClearField(message, F("map_fixed64_fixed64")); + reflection->ClearField(message, F("map_sfixed32_sfixed32")); + reflection->ClearField(message, F("map_sfixed64_sfixed64")); + reflection->ClearField(message, F("map_int32_float")); + reflection->ClearField(message, F("map_int32_double")); + reflection->ClearField(message, F("map_bool_bool")); + reflection->ClearField(message, F("map_string_string")); + reflection->ClearField(message, F("map_int32_bytes")); + reflection->ClearField(message, F("map_int32_enum")); + reflection->ClearField(message, F("map_int32_foreign_message")); +} + +inline void MapReflectionTester::ModifyMapFieldsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + MapValueRef map_val; + Message* sub_foreign_message; + + // Modify the second element + MapKey map_key; + map_key.SetInt32Value(1); + EXPECT_FALSE(reflection->InsertOrLookupMapValue(message, F("map_int32_int32"), + map_key, &map_val)); + map_val.SetInt32Value(2); + + map_key.SetInt64Value(1); + EXPECT_FALSE(reflection->InsertOrLookupMapValue(message, F("map_int64_int64"), + map_key, &map_val)); + map_val.SetInt64Value(2); + + map_key.SetUInt32Value(1); + EXPECT_FALSE(reflection->InsertOrLookupMapValue( + message, F("map_uint32_uint32"), map_key, &map_val)); + map_val.SetUInt32Value(2); + + map_key.SetUInt64Value(1); + reflection->InsertOrLookupMapValue(message, F("map_uint64_uint64"), map_key, + &map_val); + map_val.SetUInt64Value(2); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_sint32_sint32"), map_key, + &map_val); + map_val.SetInt32Value(2); + + map_key.SetInt64Value(1); + reflection->InsertOrLookupMapValue(message, F("map_sint64_sint64"), map_key, + &map_val); + map_val.SetInt64Value(2); + + map_key.SetUInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_fixed32_fixed32"), map_key, + &map_val); + map_val.SetUInt32Value(2); + + map_key.SetUInt64Value(1); + reflection->InsertOrLookupMapValue(message, F("map_fixed64_fixed64"), map_key, + &map_val); + map_val.SetUInt64Value(2); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_sfixed32_sfixed32"), + map_key, &map_val); + map_val.SetInt32Value(2); + + map_key.SetInt64Value(1); + reflection->InsertOrLookupMapValue(message, F("map_sfixed64_sfixed64"), + map_key, &map_val); + map_val.SetInt64Value(2); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_int32_float"), map_key, + &map_val); + map_val.SetFloatValue(2.0); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_int32_double"), map_key, + &map_val); + map_val.SetDoubleValue(2.0); + + map_key.SetBoolValue(true); + reflection->InsertOrLookupMapValue(message, F("map_bool_bool"), map_key, + &map_val); + map_val.SetBoolValue(false); + + map_key.SetStringValue("1"); + reflection->InsertOrLookupMapValue(message, F("map_string_string"), map_key, + &map_val); + map_val.SetStringValue("2"); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_int32_bytes"), map_key, + &map_val); + map_val.SetStringValue("2"); + + map_key.SetInt32Value(1); + reflection->InsertOrLookupMapValue(message, F("map_int32_enum"), map_key, + &map_val); + map_val.SetEnumValue(map_enum_foo_->number()); + + map_key.SetInt32Value(1); + EXPECT_FALSE(reflection->InsertOrLookupMapValue( + message, F("map_int32_foreign_message"), map_key, &map_val)); + sub_foreign_message = map_val.MutableMessageValue(); + sub_foreign_message->GetReflection()->SetInt32(sub_foreign_message, + foreign_c_, 2); +} + +inline void MapReflectionTester::RemoveLastMapsViaReflection(Message* message) { + const Reflection* reflection = message->GetReflection(); + + std::vector output; + reflection->ListFields(*message, &output); + for (int i = 0; i < output.size(); ++i) { + const FieldDescriptor* field = output[i]; + if (!field->is_repeated()) continue; + reflection->RemoveLast(message, field); + } +} + +inline void MapReflectionTester::ReleaseLastMapsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + + std::vector output; + reflection->ListFields(*message, &output); + for (int i = 0; i < output.size(); ++i) { + const FieldDescriptor* field = output[i]; + if (!field->is_repeated()) continue; + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; + + Message* released = reflection->ReleaseLast(message, field); + ASSERT_TRUE(released != nullptr) + << "ReleaseLast returned nullptr for: " << field->name(); + delete released; + } +} + +inline void MapReflectionTester::SwapMapsViaReflection(Message* message) { + const Reflection* reflection = message->GetReflection(); + std::vector output; + reflection->ListFields(*message, &output); + for (int i = 0; i < output.size(); ++i) { + const FieldDescriptor* field = output[i]; + if (!field->is_repeated()) continue; + reflection->SwapElements(message, field, 0, 1); + } +} + +inline void MapReflectionTester::MutableUnknownFieldsOfMapFieldsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + Message* sub_message = nullptr; + + sub_message = reflection->AddMessage(message, F("map_int32_int32")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_int64_int64")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_uint32_uint32")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_uint64_uint64")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_sint32_sint32")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_sint64_sint64")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_fixed32_fixed32")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_fixed64_fixed64")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_sfixed32_sfixed32")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_sfixed64_sfixed64")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_int32_float")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_int32_double")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_bool_bool")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_string_string")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_int32_bytes")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_int32_enum")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); + sub_message = reflection->AddMessage(message, F("map_int32_foreign_message")); + EXPECT_TRUE(sub_message->GetReflection()->MutableUnknownFields(sub_message) != + nullptr); +} + +inline void MapReflectionTester::ExpectMapFieldsSetViaReflection( + const Message& message) { + std::string scratch; + const Reflection* reflection = message.GetReflection(); + const Message* sub_message; + MapKey map_key; + MapValueConstRef map_value_const_ref; + + // ----------------------------------------------------------------- + + ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_int32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_int64_int64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_uint32_uint32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_uint64_uint64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_sint32_sint32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_sint64_sint64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_fixed32_fixed32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_fixed64_fixed64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_sfixed32_sfixed32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_sfixed64_sfixed64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_float"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_double"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_bool_bool"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_string_string"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_bytes"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_enum"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_foreign_message"))); + + { + std::map map; + map[0] = 0; + map[1] = 1; + for (int i = 0; i < 2; i++) { + // Check with RepeatedField Reflection + sub_message = + &reflection->GetRepeatedMessage(message, F("map_int32_int32"), i); + int32 key = sub_message->GetReflection()->GetInt32(*sub_message, + map_int32_int32_key_); + int32 val = sub_message->GetReflection()->GetInt32(*sub_message, + map_int32_int32_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_TRUE( + reflection->ContainsMapKey(message, F("map_int32_int32"), map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, F("map_int32_int32"), + map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetInt32Value(), val); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (int i = 0; i < 2; i++) { + // Check with RepeatedField Reflection + sub_message = + &reflection->GetRepeatedMessage(message, F("map_int64_int64"), i); + int64 key = sub_message->GetReflection()->GetInt64(*sub_message, + map_int64_int64_key_); + int64 val = sub_message->GetReflection()->GetInt64(*sub_message, + map_int64_int64_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt64Value(key); + EXPECT_TRUE( + reflection->ContainsMapKey(message, F("map_int64_int64"), map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, F("map_int64_int64"), + map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetInt64Value(), val); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (int i = 0; i < 2; i++) { + // Check with RepeatedField Reflection + sub_message = + &reflection->GetRepeatedMessage(message, F("map_uint32_uint32"), i); + uint32 key = sub_message->GetReflection()->GetUInt32( + *sub_message, map_uint32_uint32_key_); + uint32 val = sub_message->GetReflection()->GetUInt32( + *sub_message, map_uint32_uint32_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetUInt32Value(key); + EXPECT_TRUE( + reflection->ContainsMapKey(message, F("map_uint32_uint32"), map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, F("map_uint32_uint32"), + map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetUInt32Value(), val); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (int i = 0; i < 2; i++) { + sub_message = + &reflection->GetRepeatedMessage(message, F("map_uint64_uint64"), i); + uint64 key = sub_message->GetReflection()->GetUInt64( + *sub_message, map_uint64_uint64_key_); + uint64 val = sub_message->GetReflection()->GetUInt64( + *sub_message, map_uint64_uint64_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetUInt64Value(key); + EXPECT_TRUE( + reflection->ContainsMapKey(message, F("map_uint64_uint64"), map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, F("map_uint64_uint64"), + map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetUInt64Value(), val); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (int i = 0; i < 2; i++) { + sub_message = + &reflection->GetRepeatedMessage(message, F("map_sint32_sint32"), i); + int32 key = sub_message->GetReflection()->GetInt32( + *sub_message, map_sint32_sint32_key_); + int32 val = sub_message->GetReflection()->GetInt32( + *sub_message, map_sint32_sint32_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_sint32_sint32"), map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, F("map_sint32_sint32"), + map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetInt32Value(), val); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (int i = 0; i < 2; i++) { + sub_message = + &reflection->GetRepeatedMessage(message, F("map_sint64_sint64"), i); + int64 key = sub_message->GetReflection()->GetInt64( + *sub_message, map_sint64_sint64_key_); + int64 val = sub_message->GetReflection()->GetInt64( + *sub_message, map_sint64_sint64_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt64Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_sint64_sint64"), map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, F("map_sint64_sint64"), + map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetInt64Value(), val); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (int i = 0; i < 2; i++) { + sub_message = + &reflection->GetRepeatedMessage(message, F("map_fixed32_fixed32"), i); + uint32 key = sub_message->GetReflection()->GetUInt32( + *sub_message, map_fixed32_fixed32_key_); + uint32 val = sub_message->GetReflection()->GetUInt32( + *sub_message, map_fixed32_fixed32_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetUInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_fixed32_fixed32"), map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, F("map_fixed32_fixed32"), + map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetUInt32Value(), val); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (int i = 0; i < 2; i++) { + sub_message = + &reflection->GetRepeatedMessage(message, F("map_fixed64_fixed64"), i); + uint64 key = sub_message->GetReflection()->GetUInt64( + *sub_message, map_fixed64_fixed64_key_); + uint64 val = sub_message->GetReflection()->GetUInt64( + *sub_message, map_fixed64_fixed64_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetUInt64Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_fixed64_fixed64"), map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, F("map_fixed64_fixed64"), + map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetUInt64Value(), val); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (int i = 0; i < 2; i++) { + sub_message = &reflection->GetRepeatedMessage( + message, F("map_sfixed32_sfixed32"), i); + int32 key = sub_message->GetReflection()->GetInt32( + *sub_message, map_sfixed32_sfixed32_key_); + int32 val = sub_message->GetReflection()->GetInt32( + *sub_message, map_sfixed32_sfixed32_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_sfixed32_sfixed32"), map_key)); + EXPECT_TRUE(reflection->LookupMapValue( + message, F("map_sfixed32_sfixed32"), map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetInt32Value(), val); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (int i = 0; i < 2; i++) { + sub_message = &reflection->GetRepeatedMessage( + message, F("map_sfixed64_sfixed64"), i); + int64 key = sub_message->GetReflection()->GetInt64( + *sub_message, map_sfixed64_sfixed64_key_); + int64 val = sub_message->GetReflection()->GetInt64( + *sub_message, map_sfixed64_sfixed64_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt64Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_sfixed64_sfixed64"), map_key)); + EXPECT_TRUE(reflection->LookupMapValue( + message, F("map_sfixed64_sfixed64"), map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetInt64Value(), val); + } + } + { + std::map map; + map[0] = 0.0; + map[1] = 1.0; + for (int i = 0; i < 2; i++) { + sub_message = + &reflection->GetRepeatedMessage(message, F("map_int32_float"), i); + int32 key = sub_message->GetReflection()->GetInt32(*sub_message, + map_int32_float_key_); + float val = sub_message->GetReflection()->GetFloat(*sub_message, + map_int32_float_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey(message, F("map_int32_float"), + map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, F("map_int32_float"), + map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetFloatValue(), val); + } + } + { + std::map map; + map[0] = 0.0; + map[1] = 1.0; + for (int i = 0; i < 2; i++) { + sub_message = + &reflection->GetRepeatedMessage(message, F("map_int32_double"), i); + int32 key = sub_message->GetReflection()->GetInt32(*sub_message, + map_int32_double_key_); + double val = sub_message->GetReflection()->GetDouble( + *sub_message, map_int32_double_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey(message, F("map_int32_double"), + map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, F("map_int32_double"), + map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetDoubleValue(), val); + } + } + { + std::map map; + map[false] = false; + map[true] = true; + for (int i = 0; i < 2; i++) { + sub_message = + &reflection->GetRepeatedMessage(message, F("map_bool_bool"), i); + bool key = sub_message->GetReflection()->GetBool(*sub_message, + map_bool_bool_key_); + bool val = sub_message->GetReflection()->GetBool(*sub_message, + map_bool_bool_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetBoolValue(key); + EXPECT_EQ(true, reflection->ContainsMapKey(message, F("map_bool_bool"), + map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, F("map_bool_bool"), + map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetBoolValue(), val); + } + } + { + std::map map; + map["0"] = "0"; + map["1"] = "1"; + for (int i = 0; i < 2; i++) { + sub_message = + &reflection->GetRepeatedMessage(message, F("map_string_string"), i); + std::string key = sub_message->GetReflection()->GetString( + *sub_message, map_string_string_key_); + std::string val = sub_message->GetReflection()->GetString( + *sub_message, map_string_string_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetStringValue(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_string_string"), map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, F("map_string_string"), + map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetStringValue(), val); + } + } + { + std::map map; + map[0] = "0"; + map[1] = "1"; + for (int i = 0; i < 2; i++) { + sub_message = + &reflection->GetRepeatedMessage(message, F("map_int32_bytes"), i); + int32 key = sub_message->GetReflection()->GetInt32(*sub_message, + map_int32_bytes_key_); + std::string val = sub_message->GetReflection()->GetString( + *sub_message, map_int32_bytes_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey(message, F("map_int32_bytes"), + map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, F("map_int32_bytes"), + map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetStringValue(), val); + } + } + { + std::map map; + map[0] = map_enum_bar_; + map[1] = map_enum_baz_; + for (int i = 0; i < 2; i++) { + sub_message = + &reflection->GetRepeatedMessage(message, F("map_int32_enum"), i); + int32 key = sub_message->GetReflection()->GetInt32(*sub_message, + map_int32_enum_key_); + const EnumValueDescriptor* val = sub_message->GetReflection()->GetEnum( + *sub_message, map_int32_enum_val_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey(message, F("map_int32_enum"), + map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, F("map_int32_enum"), + map_key, &map_value_const_ref)); + EXPECT_EQ(map_value_const_ref.GetEnumValue(), val->number()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (int i = 0; i < 2; i++) { + sub_message = &reflection->GetRepeatedMessage( + message, F("map_int32_foreign_message"), i); + int32 key = sub_message->GetReflection()->GetInt32( + *sub_message, map_int32_foreign_message_key_); + const Message& foreign_message = sub_message->GetReflection()->GetMessage( + *sub_message, map_int32_foreign_message_val_); + int32 val = foreign_message.GetReflection()->GetInt32(foreign_message, + foreign_c_); + EXPECT_EQ(map[key], val); + // Check with Map Reflection + map_key.SetInt32Value(key); + EXPECT_EQ(true, reflection->ContainsMapKey( + message, F("map_int32_foreign_message"), map_key)); + EXPECT_TRUE(reflection->LookupMapValue(message, + F("map_int32_foreign_message"), + map_key, &map_value_const_ref)); + EXPECT_EQ(foreign_message.GetReflection()->GetInt32( + map_value_const_ref.GetMessageValue(), foreign_c_), + val); + } + } +} + +inline void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( + Message* message) { + std::string scratch; + std::string serialized; + const Reflection* reflection = message->GetReflection(); + + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_int32"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int64_int64"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_uint32_uint32"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_uint64_uint64"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sint32_sint32"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sint64_sint64"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_fixed32_fixed32"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_fixed64_fixed64"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sfixed32_sfixed32"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sfixed64_sfixed64"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_float"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_double"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_bool_bool"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_string_string"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_bytes"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_enum"))); + ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_foreign_message"))); + + { + std::map map; + map[0] = 0; + map[1] = 1; + int size = 0; + for (MapIterator iter = reflection->MapBegin(message, F("map_int32_int32")); + iter != reflection->MapEnd(message, F("map_int32_int32")); + ++iter, ++size) { + // Check const methods do not invalidate map. + message->DebugString(); + message->ShortDebugString(); + message->SerializeToString(&serialized); + message->SpaceUsedLong(); + message->ByteSizeLong(); + EXPECT_EQ(map[iter.GetKey().GetInt32Value()], + iter.GetValueRef().GetInt32Value()); + } + EXPECT_EQ(size, 2); + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = reflection->MapBegin(message, F("map_int64_int64")); + iter != reflection->MapEnd(message, F("map_int64_int64")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt64Value()], + iter.GetValueRef().GetInt64Value()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = + reflection->MapBegin(message, F("map_uint32_uint32")); + iter != reflection->MapEnd(message, F("map_uint32_uint32")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetUInt32Value()], + iter.GetValueRef().GetUInt32Value()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = + reflection->MapBegin(message, F("map_uint64_uint64")); + iter != reflection->MapEnd(message, F("map_uint64_uint64")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetUInt64Value()], + iter.GetValueRef().GetUInt64Value()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = + reflection->MapBegin(message, F("map_sint32_sint32")); + iter != reflection->MapEnd(message, F("map_sint32_sint32")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt32Value()], + iter.GetValueRef().GetInt32Value()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = + reflection->MapBegin(message, F("map_sint64_sint64")); + iter != reflection->MapEnd(message, F("map_sint64_sint64")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt64Value()], + iter.GetValueRef().GetInt64Value()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = + reflection->MapBegin(message, F("map_fixed32_fixed32")); + iter != reflection->MapEnd(message, F("map_fixed32_fixed32")); + ++iter) { + EXPECT_EQ(map[iter.GetKey().GetUInt32Value()], + iter.GetValueRef().GetUInt32Value()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = + reflection->MapBegin(message, F("map_fixed64_fixed64")); + iter != reflection->MapEnd(message, F("map_fixed64_fixed64")); + ++iter) { + EXPECT_EQ(map[iter.GetKey().GetUInt64Value()], + iter.GetValueRef().GetUInt64Value()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + for (MapIterator iter = + reflection->MapBegin(message, F("map_sfixed32_sfixed32")); + iter != reflection->MapEnd(message, F("map_sfixed32_sfixed32")); + ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt32Value()], + iter.GetValueRef().GetInt32Value()); + } + } + { + std::map map; + map[0] = 0.0; + map[1] = 1.0; + for (MapIterator iter = reflection->MapBegin(message, F("map_int32_float")); + iter != reflection->MapEnd(message, F("map_int32_float")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt32Value()], + iter.GetValueRef().GetFloatValue()); + } + } + { + std::map map; + map[0] = 0.0; + map[1] = 1.0; + for (MapIterator iter = + reflection->MapBegin(message, F("map_int32_double")); + iter != reflection->MapEnd(message, F("map_int32_double")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt32Value()], + iter.GetValueRef().GetDoubleValue()); + } + } + { + std::map map; + map[false] = false; + map[true] = true; + for (MapIterator iter = reflection->MapBegin(message, F("map_bool_bool")); + iter != reflection->MapEnd(message, F("map_bool_bool")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetBoolValue()], + iter.GetValueRef().GetBoolValue()); + } + } + { + std::map map; + map["0"] = "0"; + map["1"] = "1"; + int size = 0; + for (MapIterator iter = + reflection->MapBegin(message, F("map_string_string")); + iter != reflection->MapEnd(message, F("map_string_string")); + ++iter, ++size) { + // Check const methods do not invalidate map. + message->DebugString(); + message->ShortDebugString(); + message->SerializeToString(&serialized); + message->SpaceUsedLong(); + message->ByteSizeLong(); + EXPECT_EQ(map[iter.GetKey().GetStringValue()], + iter.GetValueRef().GetStringValue()); + } + EXPECT_EQ(size, 2); + } + { + std::map map; + map[0] = "0"; + map[1] = "1"; + for (MapIterator iter = reflection->MapBegin(message, F("map_int32_bytes")); + iter != reflection->MapEnd(message, F("map_int32_bytes")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt32Value()], + iter.GetValueRef().GetStringValue()); + } + } + { + std::map map; + map[0] = map_enum_bar_; + map[1] = map_enum_baz_; + for (MapIterator iter = reflection->MapBegin(message, F("map_int32_enum")); + iter != reflection->MapEnd(message, F("map_int32_enum")); ++iter) { + EXPECT_EQ(map[iter.GetKey().GetInt32Value()]->number(), + iter.GetValueRef().GetEnumValue()); + } + } + { + std::map map; + map[0] = 0; + map[1] = 1; + int size = 0; + for (MapIterator iter = + reflection->MapBegin(message, F("map_int32_foreign_message")); + iter != reflection->MapEnd(message, F("map_int32_foreign_message")); + ++iter, ++size) { + // Check const methods do not invalidate map. + message->DebugString(); + message->ShortDebugString(); + message->SerializeToString(&serialized); + message->SpaceUsedLong(); + message->ByteSizeLong(); + const Message& sub_message = iter.GetValueRef().GetMessageValue(); + EXPECT_EQ(map[iter.GetKey().GetInt32Value()], + sub_message.GetReflection()->GetInt32(sub_message, foreign_c_)); + } + EXPECT_EQ(size, 2); + } +} + +inline void MapReflectionTester::ExpectClearViaReflection( + const Message& message) { + const Reflection* reflection = message.GetReflection(); + // Map fields are empty. + EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_int32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_int64_int64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_uint32_uint32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_uint64_uint64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_sint32_sint32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_sint64_sint64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_fixed32_fixed32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_fixed64_fixed64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_sfixed32_sfixed32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_sfixed64_sfixed64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_float"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_double"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_bool_bool"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_string_string"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_bytes"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_enum"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_foreign_message"))); + EXPECT_TRUE(reflection->GetMapData(message, F("map_int32_foreign_message")) + ->IsMapValid()); +} + +inline void MapReflectionTester::ExpectClearViaReflectionIterator( + Message* message) { + const Reflection* reflection = message->GetReflection(); + EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_int32")) == + reflection->MapEnd(message, F("map_int32_int32"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_int64_int64")) == + reflection->MapEnd(message, F("map_int64_int64"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_uint32_uint32")) == + reflection->MapEnd(message, F("map_uint32_uint32"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_uint64_uint64")) == + reflection->MapEnd(message, F("map_uint64_uint64"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_sint32_sint32")) == + reflection->MapEnd(message, F("map_sint32_sint32"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_sint64_sint64")) == + reflection->MapEnd(message, F("map_sint64_sint64"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_fixed32_fixed32")) == + reflection->MapEnd(message, F("map_fixed32_fixed32"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_fixed64_fixed64")) == + reflection->MapEnd(message, F("map_fixed64_fixed64"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_sfixed32_sfixed32")) == + reflection->MapEnd(message, F("map_sfixed32_sfixed32"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_sfixed64_sfixed64")) == + reflection->MapEnd(message, F("map_sfixed64_sfixed64"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_float")) == + reflection->MapEnd(message, F("map_int32_float"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_double")) == + reflection->MapEnd(message, F("map_int32_double"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_bool_bool")) == + reflection->MapEnd(message, F("map_bool_bool"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_string_string")) == + reflection->MapEnd(message, F("map_string_string"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_bytes")) == + reflection->MapEnd(message, F("map_int32_bytes"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_enum")) == + reflection->MapEnd(message, F("map_int32_enum"))); + EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_foreign_message")) == + reflection->MapEnd(message, F("map_int32_foreign_message"))); +} + +} // namespace protobuf } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_MAP_TEST_UTIL_H__ diff --git a/src/google/protobuf/map_test_util.inc b/src/google/protobuf/map_test_util.inc new file mode 100644 index 0000000000000..600fdc36a025e --- /dev/null +++ b/src/google/protobuf/map_test_util.inc @@ -0,0 +1,271 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include + +namespace google { +namespace protobuf { + +class MapTestUtil { + public: + // Set every field in the TestMap message to a unique value. + static void SetMapFields(UNITTEST::TestMap* message); + + // Set every field in the TestArenaMap message to a unique value. + static void SetArenaMapFields(UNITTEST::TestArenaMap* message); + + // Set every field in the message to a default value. + static void SetMapFieldsInitialized(UNITTEST::TestMap* message); + + // Modify all the map fields of the message (which should already have been + // initialized with SetMapFields()). + static void ModifyMapFields(UNITTEST::TestMap* message); + + // Check that all fields have the values that they should have after + // SetMapFields() is called. + static void ExpectMapFieldsSet(const UNITTEST::TestMap& message); + + // Check that all fields have the values that they should have after + // SetMapFields() is called for TestArenaMap. + static void ExpectArenaMapFieldsSet(const UNITTEST::TestArenaMap& message); + + // Check that all fields have the values that they should have after + // SetMapFieldsInitialized() is called. + static void ExpectMapFieldsSetInitialized(const UNITTEST::TestMap& message); + + // Expect that the message is modified as would be expected from + // ModifyMapFields(). + static void ExpectMapFieldsModified(const UNITTEST::TestMap& message); + + // Check that all fields are empty. + static void ExpectClear(const UNITTEST::TestMap& message); + + // Check that all map fields have the given size. + static void ExpectMapsSize(const UNITTEST::TestMap& message, int size); + + // Get pointers of map entries at given index. + static std::vector GetMapEntries( + const UNITTEST::TestMap& message, int index); + + // Get pointers of map entries from release. + static std::vector GetMapEntriesFromRelease( + UNITTEST::TestMap* message); +}; + +inline void MapTestUtil::SetMapFields(UNITTEST::TestMap* message) { + MapTestUtilImpl::SetMapFields(message); +} + +inline void MapTestUtil::SetArenaMapFields(UNITTEST::TestArenaMap* message) { + MapTestUtilImpl::SetArenaMapFields(message); +} + +inline void MapTestUtil::SetMapFieldsInitialized(UNITTEST::TestMap* message) { + MapTestUtilImpl::SetMapFieldsInitialized(message); +} + +inline void MapTestUtil::ModifyMapFields(UNITTEST::TestMap* message) { + MapTestUtilImpl::ModifyMapFields( + message); +} + +inline void MapTestUtil::ExpectClear(const UNITTEST::TestMap& message) { + MapTestUtilImpl::ExpectClear(message); +} + +inline void MapTestUtil::ExpectMapFieldsSet(const UNITTEST::TestMap& message) { + MapTestUtilImpl::ExpectMapFieldsSet(message); +} + +inline void MapTestUtil::ExpectArenaMapFieldsSet( + const UNITTEST::TestArenaMap& message) { + MapTestUtilImpl::ExpectArenaMapFieldsSet< + UNITTEST::MapEnum, UNITTEST::MAP_ENUM_BAR, UNITTEST::MAP_ENUM_BAZ>( + message); +} + +inline void MapTestUtil::ExpectMapFieldsSetInitialized( + const UNITTEST::TestMap& message) { + MapTestUtilImpl::ExpectMapFieldsSetInitialized( + message); +} + +inline void MapTestUtil::ExpectMapFieldsModified( + const UNITTEST::TestMap& message) { + MapTestUtilImpl::ExpectMapFieldsModified< + UNITTEST::MapEnum, UNITTEST::MAP_ENUM_BAR, UNITTEST::MAP_ENUM_FOO>( + message); +} + +inline void MapTestUtil::ExpectMapsSize(const UNITTEST::TestMap& message, + int size) { + const Descriptor* descriptor = message.GetDescriptor(); + + EXPECT_EQ(size, message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_int32_int32"))); + EXPECT_EQ(size, message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_int64_int64"))); + EXPECT_EQ(size, + message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_uint32_uint32"))); + EXPECT_EQ(size, + message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_uint64_uint64"))); + EXPECT_EQ(size, + message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_sint32_sint32"))); + EXPECT_EQ(size, + message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_sint64_sint64"))); + EXPECT_EQ(size, + message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_fixed32_fixed32"))); + EXPECT_EQ(size, + message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_fixed64_fixed64"))); + EXPECT_EQ(size, + message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_sfixed32_sfixed32"))); + EXPECT_EQ(size, + message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_sfixed64_sfixed64"))); + EXPECT_EQ(size, message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_int32_float"))); + EXPECT_EQ(size, + message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_int32_double"))); + EXPECT_EQ(size, message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_bool_bool"))); + EXPECT_EQ(size, + message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_string_string"))); + EXPECT_EQ(size, message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_int32_bytes"))); + EXPECT_EQ( + size, + message.GetReflection()->FieldSize( + message, descriptor->FindFieldByName("map_int32_foreign_message"))); +} + +inline std::vector MapTestUtil::GetMapEntries( + const UNITTEST::TestMap& message, int index) { + const Descriptor* descriptor = message.GetDescriptor(); + std::vector result; + + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_int32_int32"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_int64_int64"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_uint32_uint32"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_uint64_uint64"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_sint32_sint32"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_sint64_sint64"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_fixed32_fixed32"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_fixed64_fixed64"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_sfixed32_sfixed32"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_sfixed64_sfixed64"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_int32_float"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_int32_double"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_bool_bool"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_string_string"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_int32_bytes"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_int32_enum"), index)); + result.push_back(&message.GetReflection()->GetRepeatedMessage( + message, descriptor->FindFieldByName("map_int32_foreign_message"), + index)); + + return result; +} + +inline std::vector MapTestUtil::GetMapEntriesFromRelease( + UNITTEST::TestMap* message) { + const Descriptor* descriptor = message->GetDescriptor(); + std::vector result; + + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_int32_int32"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_int64_int64"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_uint32_uint32"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_uint64_uint64"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_sint32_sint32"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_sint64_sint64"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_fixed32_fixed32"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_fixed64_fixed64"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_sfixed32_sfixed32"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_sfixed64_sfixed64"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_int32_float"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_int32_double"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_bool_bool"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_string_string"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_int32_bytes"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_int32_enum"))); + result.push_back(message->GetReflection()->ReleaseLast( + message, descriptor->FindFieldByName("map_int32_foreign_message"))); + + return result; +} + +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/map_test_util_impl.h b/src/google/protobuf/map_test_util_impl.h index ad4d1a3dd3691..655aec8384d48 100644 --- a/src/google/protobuf/map_test_util_impl.h +++ b/src/google/protobuf/map_test_util_impl.h @@ -36,9 +36,9 @@ #include -namespace google { -namespace protobuf_unittest {} // forward declaration +namespace protobuf_unittest {} // namespace protobuf_unittest +namespace google { namespace protobuf { namespace unittest = ::protobuf_unittest; @@ -46,13 +46,13 @@ namespace unittest = ::protobuf_unittest; class MapTestUtilImpl { public: // Set every field in the TestMap message to a unique value. - template + template static void SetMapFields(MapMessage* message); // Set every field in the TestArenaMap message to a unique value. - template + template static void SetArenaMapFields(MapMessage* message); // Set every field in the message to a default value. @@ -66,14 +66,14 @@ class MapTestUtilImpl { // Check that all fields have the values that they should have after // SetMapFields() is called. - template + template static void ExpectMapFieldsSet(const MapMessage& message); // Check that all fields have the values that they should have after // SetMapFields() is called for TestArenaMap. - template + template static void ExpectArenaMapFieldsSet(const MapMessage& message); // Check that all fields have the values that they should have after @@ -83,8 +83,8 @@ class MapTestUtilImpl { // Expect that the message is modified as would be expected from // ModifyMapFields(). - template + template static void ExpectMapFieldsModified(const MapMessage& message); // Check that all fields are empty. @@ -104,8 +104,8 @@ class MapTestUtilImpl { // MapMessage* message); }; -template +template void MapTestUtilImpl::SetMapFields(MapMessage* message) { // Add first element. (*message->mutable_map_int32_int32())[0] = 0; @@ -146,8 +146,8 @@ void MapTestUtilImpl::SetMapFields(MapMessage* message) { (*message->mutable_map_int32_foreign_message())[1].set_c(1); } -template +template void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) { // Add first element. (*message->mutable_map_int32_int32())[0] = 0; @@ -167,7 +167,6 @@ void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) { (*message->mutable_map_int32_bytes())[0] = "0"; (*message->mutable_map_int32_enum())[0] = enum_value0; (*message->mutable_map_int32_foreign_message())[0].set_c(0); - (*message->mutable_map_int32_foreign_message_no_arena())[0].set_c(0); // Add second element (*message->mutable_map_int32_int32())[1] = 1; @@ -187,7 +186,6 @@ void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) { (*message->mutable_map_int32_bytes())[1] = "1"; (*message->mutable_map_int32_enum())[1] = enum_value1; (*message->mutable_map_int32_foreign_message())[1].set_c(1); - (*message->mutable_map_int32_foreign_message_no_arena())[1].set_c(1); } template @@ -255,10 +253,8 @@ void MapTestUtilImpl::ExpectClear(const MapMessage& message) { EXPECT_EQ(0, message.map_int32_foreign_message().size()); } - - -template +template void MapTestUtilImpl::ExpectMapFieldsSet(const MapMessage& message) { ASSERT_EQ(2, message.map_int32_int32().size()); ASSERT_EQ(2, message.map_int64_int64().size()); @@ -315,8 +311,8 @@ void MapTestUtilImpl::ExpectMapFieldsSet(const MapMessage& message) { EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c()); } -template +template void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) { EXPECT_EQ(2, message.map_int32_int32().size()); EXPECT_EQ(2, message.map_int64_int64().size()); @@ -335,7 +331,6 @@ void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) { EXPECT_EQ(2, message.map_int32_bytes().size()); EXPECT_EQ(2, message.map_int32_enum().size()); EXPECT_EQ(2, message.map_int32_foreign_message().size()); - EXPECT_EQ(2, message.map_int32_foreign_message_no_arena().size()); EXPECT_EQ(0, message.map_int32_int32().at(0)); EXPECT_EQ(0, message.map_int64_int64().at(0)); @@ -354,7 +349,6 @@ void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) { EXPECT_EQ("0", message.map_int32_bytes().at(0)); EXPECT_EQ(enum_value0, message.map_int32_enum().at(0)); EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c()); - EXPECT_EQ(0, message.map_int32_foreign_message_no_arena().at(0).c()); EXPECT_EQ(1, message.map_int32_int32().at(1)); EXPECT_EQ(1, message.map_int64_int64().at(1)); @@ -373,12 +367,10 @@ void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) { EXPECT_EQ("1", message.map_int32_bytes().at(1)); EXPECT_EQ(enum_value1, message.map_int32_enum().at(1)); EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c()); - EXPECT_EQ(1, message.map_int32_foreign_message_no_arena().at(1).c()); } template -void MapTestUtilImpl::ExpectMapFieldsSetInitialized( - const MapMessage& message) { +void MapTestUtilImpl::ExpectMapFieldsSetInitialized(const MapMessage& message) { EXPECT_EQ(1, message.map_int32_int32().size()); EXPECT_EQ(1, message.map_int64_int64().size()); EXPECT_EQ(1, message.map_uint32_uint32().size()); @@ -413,13 +405,12 @@ void MapTestUtilImpl::ExpectMapFieldsSetInitialized( EXPECT_EQ("", message.map_string_string().at("0")); EXPECT_EQ("", message.map_int32_bytes().at(0)); EXPECT_EQ(enum_value, message.map_int32_enum().at(0)); - EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSize()); + EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSizeLong()); } -template -void MapTestUtilImpl::ExpectMapFieldsModified( - const MapMessage& message) { +template +void MapTestUtilImpl::ExpectMapFieldsModified(const MapMessage& message) { // ModifyMapFields only sets the second element of each field. In addition to // verifying this, we also verify that the first element and size were *not* // modified. @@ -480,6 +471,6 @@ void MapTestUtilImpl::ExpectMapFieldsModified( } } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__ diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h index 423c98f127ec0..e718790ef49fe 100644 --- a/src/google/protobuf/map_type_handler.h +++ b/src/google/protobuf/map_type_handler.h @@ -31,8 +31,14 @@ #ifndef GOOGLE_PROTOBUF_TYPE_HANDLER_H__ #define GOOGLE_PROTOBUF_TYPE_HANDLER_H__ +#include +#include #include -#include +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif namespace google { namespace protobuf { @@ -40,41 +46,19 @@ namespace internal { // Used for compile time type selection. MapIf::type will be TrueType if Flag is // true and FalseType otherwise. -template +template struct MapIf; -template +template struct MapIf { typedef TrueType type; }; -template +template struct MapIf { typedef FalseType type; }; -// In proto2 Map, enum needs to be initialized to given default value, while -// other types' default value can be inferred from the type. -template -class MapValueInitializer { - public: - static inline void Initialize(Type& type, int default_enum_value); -}; - -template -class MapValueInitializer { - public: - static inline void Initialize(Type& value, int default_enum_value) { - value = static_cast(default_enum_value); - } -}; - -template -class MapValueInitializer { - public: - static inline void Initialize(Type& value, int default_enum_value) {} -}; - template class MapArenaMessageCreator { public: @@ -113,23 +97,23 @@ class MapWireFieldTypeTraits {}; WireFormatLite::WIRETYPE_##WireFormatType; \ }; -TYPE_TRAITS(MESSAGE , Type, LENGTH_DELIMITED, true, false) -TYPE_TRAITS(STRING , ArenaStringPtr, LENGTH_DELIMITED, false, false) -TYPE_TRAITS(BYTES , ArenaStringPtr , LENGTH_DELIMITED, false, false) -TYPE_TRAITS(INT64 , int64 , VARINT , false, false) -TYPE_TRAITS(UINT64 , uint64 , VARINT , false, false) -TYPE_TRAITS(INT32 , int32 , VARINT , false, false) -TYPE_TRAITS(UINT32 , uint32 , VARINT , false, false) -TYPE_TRAITS(SINT64 , int64 , VARINT , false, false) -TYPE_TRAITS(SINT32 , int32 , VARINT , false, false) -TYPE_TRAITS(ENUM , int , VARINT , false, true ) -TYPE_TRAITS(DOUBLE , double , FIXED64, false, false) -TYPE_TRAITS(FLOAT , float , FIXED32, false, false) -TYPE_TRAITS(FIXED64 , uint64 , FIXED64, false, false) -TYPE_TRAITS(FIXED32 , uint32 , FIXED32, false, false) -TYPE_TRAITS(SFIXED64, int64 , FIXED64, false, false) -TYPE_TRAITS(SFIXED32, int32 , FIXED32, false, false) -TYPE_TRAITS(BOOL , bool , VARINT , false, false) +TYPE_TRAITS(MESSAGE, Type, LENGTH_DELIMITED, true, false) +TYPE_TRAITS(STRING, ArenaStringPtr, LENGTH_DELIMITED, false, false) +TYPE_TRAITS(BYTES, ArenaStringPtr, LENGTH_DELIMITED, false, false) +TYPE_TRAITS(INT64, int64, VARINT, false, false) +TYPE_TRAITS(UINT64, uint64, VARINT, false, false) +TYPE_TRAITS(INT32, int32, VARINT, false, false) +TYPE_TRAITS(UINT32, uint32, VARINT, false, false) +TYPE_TRAITS(SINT64, int64, VARINT, false, false) +TYPE_TRAITS(SINT32, int32, VARINT, false, false) +TYPE_TRAITS(ENUM, int, VARINT, false, true) +TYPE_TRAITS(DOUBLE, double, FIXED64, false, false) +TYPE_TRAITS(FLOAT, float, FIXED32, false, false) +TYPE_TRAITS(FIXED64, uint64, FIXED64, false, false) +TYPE_TRAITS(FIXED32, uint32, FIXED32, false, false) +TYPE_TRAITS(SFIXED64, int64, FIXED64, false, false) +TYPE_TRAITS(SFIXED32, int32, FIXED32, false, false) +TYPE_TRAITS(BOOL, bool, VARINT, false, false) #undef TYPE_TRAITS @@ -142,18 +126,19 @@ class MapTypeHandler { // Enum type cannot be used for MapTypeHandler::Read. Define a type which will // replace Enum with int. typedef typename MapWireFieldTypeTraits::MapEntryAccessorType MapEntryAccessorType; + Type>::MapEntryAccessorType + MapEntryAccessorType; // Internal stored type in MapEntryLite for given wire field type. typedef typename MapWireFieldTypeTraits::TypeOnMemory TypeOnMemory; // Corresponding wire type for field type. - static const WireFormatLite::WireType kWireType = + static constexpr WireFormatLite::WireType kWireType = MapWireFieldTypeTraits::kWireType; // Whether wire type is for message. - static const bool kIsMessage = + static constexpr bool kIsMessage = MapWireFieldTypeTraits::kIsMessage; // Whether wire type is for enum. - static const bool kIsEnum = + static constexpr bool kIsEnum = MapWireFieldTypeTraits::kIsEnum; // Functions used in parsing and serialization. =================== @@ -161,39 +146,26 @@ class MapTypeHandler { static inline int GetCachedSize(const MapEntryAccessorType& value); static inline bool Read(io::CodedInputStream* input, MapEntryAccessorType* value); - static inline void Write(int field, const MapEntryAccessorType& value, - io::CodedOutputStream* output); - static inline uint8* InternalWriteToArray(int field, - const MapEntryAccessorType& value, - bool deterministic, uint8* target); - static inline uint8* WriteToArray(int field, - const MapEntryAccessorType& value, - uint8* target); + static inline const char* Read(const char* ptr, ParseContext* ctx, + MapEntryAccessorType* value); + + static inline uint8* Write(int field, const MapEntryAccessorType& value, + uint8* ptr, io::EpsCopyOutputStream* stream); // Functions to manipulate data on memory. ======================== static inline const Type& GetExternalReference(const Type* value); static inline void DeleteNoArena(const Type* x); static inline void Merge(const Type& from, Type** to, Arena* arena); static inline void Clear(Type** value, Arena* arena); - static inline void ClearMaybeByDefaultEnum(Type** value, Arena* arena, - int default_enum_value); - static inline void Initialize(Type** x, Arena* arena); + static constexpr TypeOnMemory Constinit(); - static inline void InitializeMaybeByDefaultEnum(Type** x, - int default_enum_value, - Arena* arena); static inline Type* EnsureMutable(Type** value, Arena* arena); // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding // those already calculate in sizeof(MapField). static inline size_t SpaceUsedInMapEntryLong(const Type* value); - // Return bytes used by value in Map. - static inline size_t SpaceUsedInMapLong(const Type& value); - // Assign default value to given instance. - static inline void AssignDefaultValue(Type** value); // Return default instance if value is not initialized when calling const // reference accessor. - static inline const Type& DefaultIfNotInitialized( - const Type* value, const Type* default_value); + static inline const Type& DefaultIfNotInitialized(const Type* value); // Check if all required fields have values set. static inline bool IsInitialized(Type* value); }; @@ -220,37 +192,22 @@ class MapTypeHandler { static inline int GetCachedSize(const MapEntryAccessorType& value); \ static inline bool Read(io::CodedInputStream* input, \ MapEntryAccessorType* value); \ - static inline void Write(int field, const MapEntryAccessorType& value, \ - io::CodedOutputStream* output); \ - static inline uint8* InternalWriteToArray( \ - int field, const MapEntryAccessorType& value, bool deterministic, \ - uint8* target); \ - static inline uint8* WriteToArray(int field, \ - const MapEntryAccessorType& value, \ - uint8* target) { \ - return InternalWriteToArray(field, value, false, target); \ - } \ + static inline const char* Read(const char* begin, ParseContext* ctx, \ + MapEntryAccessorType* value); \ + static inline uint8* Write(int field, const MapEntryAccessorType& value, \ + uint8* ptr, io::EpsCopyOutputStream* stream); \ static inline const MapEntryAccessorType& GetExternalReference( \ const TypeOnMemory& value); \ static inline void DeleteNoArena(const TypeOnMemory& x); \ static inline void Merge(const MapEntryAccessorType& from, \ TypeOnMemory* to, Arena* arena); \ static inline void Clear(TypeOnMemory* value, Arena* arena); \ - static inline void ClearMaybeByDefaultEnum(TypeOnMemory* value, \ - Arena* arena, \ - int default_enum); \ static inline size_t SpaceUsedInMapEntryLong(const TypeOnMemory& value); \ - static inline size_t SpaceUsedInMapLong(const TypeOnMemory& value); \ - static inline size_t SpaceUsedInMapLong(const string& value); \ - static inline void AssignDefaultValue(TypeOnMemory* value); \ static inline const MapEntryAccessorType& DefaultIfNotInitialized( \ - const TypeOnMemory& value, const TypeOnMemory& default_value); \ + const TypeOnMemory& value); \ static inline bool IsInitialized(const TypeOnMemory& value); \ static void DeleteNoArena(TypeOnMemory& value); \ - static inline void Initialize(TypeOnMemory* value, Arena* arena); \ - static inline void InitializeMaybeByDefaultEnum(TypeOnMemory* value, \ - int default_enum_value, \ - Arena* arena); \ + static constexpr TypeOnMemory Constinit(); \ static inline MapEntryAccessorType* EnsureMutable(TypeOnMemory* value, \ Arena* arena); \ }; @@ -273,8 +230,7 @@ MAP_HANDLER(BOOL) #undef MAP_HANDLER template -inline size_t -MapTypeHandler::ByteSize( +inline size_t MapTypeHandler::ByteSize( const MapEntryAccessorType& value) { return WireFormatLite::MessageSizeNoVirtual(value); } @@ -287,41 +243,39 @@ MapTypeHandler::ByteSize( } GOOGLE_PROTOBUF_BYTE_SIZE(STRING, String) -GOOGLE_PROTOBUF_BYTE_SIZE(BYTES , Bytes) -GOOGLE_PROTOBUF_BYTE_SIZE(INT64 , Int64) +GOOGLE_PROTOBUF_BYTE_SIZE(BYTES, Bytes) +GOOGLE_PROTOBUF_BYTE_SIZE(INT64, Int64) GOOGLE_PROTOBUF_BYTE_SIZE(UINT64, UInt64) -GOOGLE_PROTOBUF_BYTE_SIZE(INT32 , Int32) +GOOGLE_PROTOBUF_BYTE_SIZE(INT32, Int32) GOOGLE_PROTOBUF_BYTE_SIZE(UINT32, UInt32) GOOGLE_PROTOBUF_BYTE_SIZE(SINT64, SInt64) GOOGLE_PROTOBUF_BYTE_SIZE(SINT32, SInt32) -GOOGLE_PROTOBUF_BYTE_SIZE(ENUM , Enum) +GOOGLE_PROTOBUF_BYTE_SIZE(ENUM, Enum) #undef GOOGLE_PROTOBUF_BYTE_SIZE #define FIXED_BYTE_SIZE(FieldType, DeclaredType) \ template \ inline int MapTypeHandler::ByteSize( \ - const MapEntryAccessorType& value) { \ + const MapEntryAccessorType& /* value */) { \ return WireFormatLite::k##DeclaredType##Size; \ } -FIXED_BYTE_SIZE(DOUBLE , Double) -FIXED_BYTE_SIZE(FLOAT , Float) -FIXED_BYTE_SIZE(FIXED64 , Fixed64) -FIXED_BYTE_SIZE(FIXED32 , Fixed32) +FIXED_BYTE_SIZE(DOUBLE, Double) +FIXED_BYTE_SIZE(FLOAT, Float) +FIXED_BYTE_SIZE(FIXED64, Fixed64) +FIXED_BYTE_SIZE(FIXED32, Fixed32) FIXED_BYTE_SIZE(SFIXED64, SFixed64) FIXED_BYTE_SIZE(SFIXED32, SFixed32) -FIXED_BYTE_SIZE(BOOL , Bool) +FIXED_BYTE_SIZE(BOOL, Bool) #undef FIXED_BYTE_SIZE template -inline int -MapTypeHandler::GetCachedSize( +inline int MapTypeHandler::GetCachedSize( const MapEntryAccessorType& value) { - return static_cast( - WireFormatLite::LengthDelimitedSize( - static_cast(value.GetCachedSize()))); + return static_cast(WireFormatLite::LengthDelimitedSize( + static_cast(value.GetCachedSize()))); } #define GET_CACHED_SIZE(FieldType, DeclaredType) \ @@ -333,14 +287,14 @@ MapTypeHandler::GetCachedSize( } GET_CACHED_SIZE(STRING, String) -GET_CACHED_SIZE(BYTES , Bytes) -GET_CACHED_SIZE(INT64 , Int64) +GET_CACHED_SIZE(BYTES, Bytes) +GET_CACHED_SIZE(INT64, Int64) GET_CACHED_SIZE(UINT64, UInt64) -GET_CACHED_SIZE(INT32 , Int32) +GET_CACHED_SIZE(INT32, Int32) GET_CACHED_SIZE(UINT32, UInt32) GET_CACHED_SIZE(SINT64, SInt64) GET_CACHED_SIZE(SINT32, SInt32) -GET_CACHED_SIZE(ENUM , Enum) +GET_CACHED_SIZE(ENUM, Enum) #undef GET_CACHED_SIZE @@ -348,67 +302,64 @@ GET_CACHED_SIZE(ENUM , Enum) template \ inline int \ MapTypeHandler::GetCachedSize( \ - const MapEntryAccessorType& value) { \ + const MapEntryAccessorType& /* value */) { \ return WireFormatLite::k##DeclaredType##Size; \ } -GET_FIXED_CACHED_SIZE(DOUBLE , Double) -GET_FIXED_CACHED_SIZE(FLOAT , Float) -GET_FIXED_CACHED_SIZE(FIXED64 , Fixed64) -GET_FIXED_CACHED_SIZE(FIXED32 , Fixed32) +GET_FIXED_CACHED_SIZE(DOUBLE, Double) +GET_FIXED_CACHED_SIZE(FLOAT, Float) +GET_FIXED_CACHED_SIZE(FIXED64, Fixed64) +GET_FIXED_CACHED_SIZE(FIXED32, Fixed32) GET_FIXED_CACHED_SIZE(SFIXED64, SFixed64) GET_FIXED_CACHED_SIZE(SFIXED32, SFixed32) -GET_FIXED_CACHED_SIZE(BOOL , Bool) +GET_FIXED_CACHED_SIZE(BOOL, Bool) #undef GET_FIXED_CACHED_SIZE template -inline void MapTypeHandler::Write( - int field, const MapEntryAccessorType& value, - io::CodedOutputStream* output) { - WireFormatLite::WriteMessageMaybeToArray(field, value, output); -} - -template -inline uint8* -MapTypeHandler::InternalWriteToArray( - int field, const MapEntryAccessorType& value, bool deterministic, - uint8* target) { - return WireFormatLite::InternalWriteMessageToArray(field, value, - deterministic, target); +inline uint8* MapTypeHandler::Write( + int field, const MapEntryAccessorType& value, uint8* ptr, + io::EpsCopyOutputStream* stream) { + ptr = stream->EnsureSpace(ptr); + return WireFormatLite::InternalWriteMessage(field, value, ptr, stream); } #define WRITE_METHOD(FieldType, DeclaredType) \ template \ - inline void MapTypeHandler::Write( \ - int field, const MapEntryAccessorType& value, \ - io::CodedOutputStream* output) { \ - return WireFormatLite::Write##DeclaredType(field, value, output); \ - } \ + inline uint8* MapTypeHandler::Write( \ + int field, const MapEntryAccessorType& value, uint8* ptr, \ + io::EpsCopyOutputStream* stream) { \ + ptr = stream->EnsureSpace(ptr); \ + return stream->Write##DeclaredType(field, value, ptr); \ + } + +WRITE_METHOD(STRING, String) +WRITE_METHOD(BYTES, Bytes) + +#undef WRITE_METHOD +#define WRITE_METHOD(FieldType, DeclaredType) \ template \ - inline uint8* \ - MapTypeHandler::InternalWriteToArray( \ - int field, const MapEntryAccessorType& value, bool, uint8* target) { \ - return WireFormatLite::Write##DeclaredType##ToArray(field, value, target); \ + inline uint8* MapTypeHandler::Write( \ + int field, const MapEntryAccessorType& value, uint8* ptr, \ + io::EpsCopyOutputStream* stream) { \ + ptr = stream->EnsureSpace(ptr); \ + return WireFormatLite::Write##DeclaredType##ToArray(field, value, ptr); \ } -WRITE_METHOD(STRING , String) -WRITE_METHOD(BYTES , Bytes) -WRITE_METHOD(INT64 , Int64) -WRITE_METHOD(UINT64 , UInt64) -WRITE_METHOD(INT32 , Int32) -WRITE_METHOD(UINT32 , UInt32) -WRITE_METHOD(SINT64 , SInt64) -WRITE_METHOD(SINT32 , SInt32) -WRITE_METHOD(ENUM , Enum) -WRITE_METHOD(DOUBLE , Double) -WRITE_METHOD(FLOAT , Float) -WRITE_METHOD(FIXED64 , Fixed64) -WRITE_METHOD(FIXED32 , Fixed32) +WRITE_METHOD(INT64, Int64) +WRITE_METHOD(UINT64, UInt64) +WRITE_METHOD(INT32, Int32) +WRITE_METHOD(UINT32, UInt32) +WRITE_METHOD(SINT64, SInt64) +WRITE_METHOD(SINT32, SInt32) +WRITE_METHOD(ENUM, Enum) +WRITE_METHOD(DOUBLE, Double) +WRITE_METHOD(FLOAT, Float) +WRITE_METHOD(FIXED64, Fixed64) +WRITE_METHOD(FIXED32, Fixed32) WRITE_METHOD(SFIXED64, SFixed64) WRITE_METHOD(SFIXED32, SFixed32) -WRITE_METHOD(BOOL , Bool) +WRITE_METHOD(BOOL, Bool) #undef WRITE_METHOD @@ -430,6 +381,82 @@ inline bool MapTypeHandler::Read( return WireFormatLite::ReadBytes(input, value); } +template +const char* MapTypeHandler::Read( + const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) { + return ctx->ParseMessage(value, ptr); +} + +template +const char* MapTypeHandler::Read( + const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) { + int size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + return ctx->ReadString(ptr, size, value); +} + +template +const char* MapTypeHandler::Read( + const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) { + int size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + return ctx->ReadString(ptr, size, value); +} + +inline const char* ReadINT64(const char* ptr, int64* value) { + return VarintParse(ptr, reinterpret_cast(value)); +} +inline const char* ReadUINT64(const char* ptr, uint64* value) { + return VarintParse(ptr, value); +} +inline const char* ReadINT32(const char* ptr, int32* value) { + return VarintParse(ptr, reinterpret_cast(value)); +} +inline const char* ReadUINT32(const char* ptr, uint32* value) { + return VarintParse(ptr, value); +} +inline const char* ReadSINT64(const char* ptr, int64* value) { + *value = ReadVarintZigZag64(&ptr); + return ptr; +} +inline const char* ReadSINT32(const char* ptr, int32* value) { + *value = ReadVarintZigZag32(&ptr); + return ptr; +} +template +inline const char* ReadENUM(const char* ptr, E* value) { + *value = static_cast(ReadVarint32(&ptr)); + return ptr; +} +inline const char* ReadBOOL(const char* ptr, bool* value) { + *value = static_cast(ReadVarint32(&ptr)); + return ptr; +} + +template +inline const char* ReadUnaligned(const char* ptr, F* value) { + *value = UnalignedLoad(ptr); + return ptr + sizeof(F); +} +inline const char* ReadFLOAT(const char* ptr, float* value) { + return ReadUnaligned(ptr, value); +} +inline const char* ReadDOUBLE(const char* ptr, double* value) { + return ReadUnaligned(ptr, value); +} +inline const char* ReadFIXED64(const char* ptr, uint64* value) { + return ReadUnaligned(ptr, value); +} +inline const char* ReadFIXED32(const char* ptr, uint32* value) { + return ReadUnaligned(ptr, value); +} +inline const char* ReadSFIXED64(const char* ptr, int64* value) { + return ReadUnaligned(ptr, value); +} +inline const char* ReadSFIXED32(const char* ptr, int32* value) { + return ReadUnaligned(ptr, value); +} + #define READ_METHOD(FieldType) \ template \ inline bool MapTypeHandler::Read( \ @@ -437,6 +464,12 @@ inline bool MapTypeHandler::Read( return WireFormatLite::ReadPrimitive( \ input, value); \ + } \ + template \ + const char* MapTypeHandler::Read( \ + const char* begin, ParseContext* ctx, MapEntryAccessorType* value) { \ + (void)ctx; \ + return Read##FieldType(begin, value); \ } READ_METHOD(INT64) @@ -460,8 +493,8 @@ READ_METHOD(BOOL) template inline const Type& -MapTypeHandler::GetExternalReference(const Type* value) { +MapTypeHandler::GetExternalReference( + const Type* value) { return *value; } @@ -471,28 +504,14 @@ inline size_t MapTypeHandlerSpaceUsedLong(); } -template -size_t MapTypeHandler::SpaceUsedInMapLong( - const Type& value) { - return value.SpaceUsedLong(); -} - template inline void MapTypeHandler::Clear( - Type** value, Arena* arena) { - if (*value != NULL) (*value)->Clear(); -} -template -inline void -MapTypeHandler::ClearMaybeByDefaultEnum(Type** value, - Arena* arena, - int default_enum_value) { + Type** value, Arena* /* arena */) { if (*value != NULL) (*value)->Clear(); } template inline void MapTypeHandler::Merge( - const Type& from, Type** to, Arena* arena) { + const Type& from, Type** to, Arena* /* arena */) { (*to)->MergeFrom(from); } @@ -503,215 +522,148 @@ void MapTypeHandler::DeleteNoArena( } template -inline void MapTypeHandler::AssignDefaultValue(Type** value) { - *value = const_cast(Type::internal_default_instance()); +constexpr auto MapTypeHandler::Constinit() + -> TypeOnMemory { + return nullptr; } template -inline void MapTypeHandler::Initialize(Type** x, - Arena* arena) { - *x = NULL; -} - -template -inline void MapTypeHandler:: - InitializeMaybeByDefaultEnum(Type** x, int default_enum_value, - Arena* arena) { - *x = NULL; -} - -template -inline Type* MapTypeHandler::EnsureMutable(Type** value, - Arena* arena) { +inline Type* MapTypeHandler::EnsureMutable( + Type** value, Arena* arena) { if (*value == NULL) { - *value = - MapArenaMessageCreator:: - type::value>::CreateMessage(arena); + *value = MapArenaMessageCreator< + Type, + Arena::is_arena_constructable::type::value>::CreateMessage(arena); } return *value; } template -inline const Type& MapTypeHandler:: - DefaultIfNotInitialized(const Type* value, const Type* default_value) { - return value != NULL ? *value : *default_value; +inline const Type& +MapTypeHandler::DefaultIfNotInitialized( + const Type* value) { + return value != NULL ? *value : *Type::internal_default_instance(); } template -inline bool MapTypeHandler::IsInitialized(Type* value) { - return value->IsInitialized(); +inline bool MapTypeHandler::IsInitialized( + Type* value) { + return value ? value->IsInitialized() : false; } // Definition for string/bytes handler -#define STRING_OR_BYTES_HANDLER_FUNCTIONS(FieldType) \ - template \ - inline const typename MapTypeHandler::MapEntryAccessorType& \ - MapTypeHandler::GetExternalReference(const TypeOnMemory& value) { \ - return value.Get(); \ - } \ - template \ - inline size_t \ - MapTypeHandler::SpaceUsedInMapEntryLong(const TypeOnMemory& value) { \ - return sizeof(value); \ - } \ - template \ - inline size_t \ - MapTypeHandler::SpaceUsedInMapLong( \ - const TypeOnMemory& value) { \ - return sizeof(value); \ - } \ - template \ - inline size_t \ - MapTypeHandler::SpaceUsedInMapLong( \ - const string& value) { \ - return sizeof(value); \ - } \ - template \ - inline void MapTypeHandler::Clear( \ - TypeOnMemory* value, Arena* arena) { \ - value->ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), \ - arena); \ - } \ - template \ - inline void MapTypeHandler:: \ - ClearMaybeByDefaultEnum(TypeOnMemory* value, Arena* arena, \ - int default_enum) { \ - Clear(value, arena); \ - } \ - template \ - inline void MapTypeHandler::Merge( \ - const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \ - to->Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from, arena); \ - } \ - template \ - void MapTypeHandler::DeleteNoArena( \ - TypeOnMemory& value) { \ - value.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); \ - } \ - template \ - inline void MapTypeHandler::AssignDefaultValue(TypeOnMemory* value) {} \ - template \ - inline void \ - MapTypeHandler::Initialize( \ - TypeOnMemory* value, Arena* arena) { \ - value->UnsafeSetDefault( \ - &::google::protobuf::internal::GetEmptyStringAlreadyInited()); \ - } \ - template \ - inline void MapTypeHandler:: \ - InitializeMaybeByDefaultEnum(TypeOnMemory* value, \ - int default_enum_value, Arena* arena) { \ - Initialize(value, arena); \ - } \ - template \ - inline typename MapTypeHandler::MapEntryAccessorType* \ - MapTypeHandler::EnsureMutable( \ - TypeOnMemory* value, Arena* arena) { \ - return value->Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), \ - arena); \ - } \ - template \ - inline const typename MapTypeHandler::MapEntryAccessorType& \ - MapTypeHandler::DefaultIfNotInitialized(const TypeOnMemory& value, \ - const TypeOnMemory& \ - default_value) { \ - return value.Get(); \ - } \ - template \ - inline bool MapTypeHandler::IsInitialized(const TypeOnMemory& value) { \ - return true; \ +#define STRING_OR_BYTES_HANDLER_FUNCTIONS(FieldType) \ + template \ + inline const typename MapTypeHandler::MapEntryAccessorType& \ + MapTypeHandler::GetExternalReference(const TypeOnMemory& value) { \ + return value.Get(); \ + } \ + template \ + inline size_t \ + MapTypeHandler::SpaceUsedInMapEntryLong(const TypeOnMemory& value) { \ + return sizeof(value); \ + } \ + template \ + inline void MapTypeHandler::Clear( \ + TypeOnMemory* value, Arena* /* arena */) { \ + value->ClearToEmpty(); \ + } \ + template \ + inline void MapTypeHandler::Merge( \ + const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \ + to->Set(&internal::GetEmptyStringAlreadyInited(), from, arena); \ + } \ + template \ + void MapTypeHandler::DeleteNoArena( \ + TypeOnMemory& value) { \ + value.DestroyNoArena(&internal::GetEmptyStringAlreadyInited()); \ + } \ + template \ + constexpr auto \ + MapTypeHandler::Constinit() \ + ->TypeOnMemory { \ + return TypeOnMemory(&internal::fixed_address_empty_string); \ + } \ + template \ + inline typename MapTypeHandler::MapEntryAccessorType* \ + MapTypeHandler::EnsureMutable( \ + TypeOnMemory* value, Arena* arena) { \ + return value->Mutable(ArenaStringPtr::EmptyDefault{}, arena); \ + } \ + template \ + inline const typename MapTypeHandler::MapEntryAccessorType& \ + MapTypeHandler::DefaultIfNotInitialized(const TypeOnMemory& value) { \ + return value.Get(); \ + } \ + template \ + inline bool \ + MapTypeHandler::IsInitialized( \ + const TypeOnMemory& /* value */) { \ + return true; \ } STRING_OR_BYTES_HANDLER_FUNCTIONS(STRING) STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES) #undef STRING_OR_BYTES_HANDLER_FUNCTIONS -#define PRIMITIVE_HANDLER_FUNCTIONS(FieldType) \ - template \ - inline const typename MapTypeHandler::MapEntryAccessorType& \ - MapTypeHandler::GetExternalReference(const TypeOnMemory& value) { \ - return value; \ - } \ - template \ - inline size_t \ - MapTypeHandler::SpaceUsedInMapEntryLong(const TypeOnMemory& value) { \ - return 0; \ - } \ - template \ - inline size_t \ - MapTypeHandler::SpaceUsedInMapLong( \ - const TypeOnMemory& value) { \ - return sizeof(Type); \ - } \ - template \ - inline void MapTypeHandler::Clear( \ - TypeOnMemory* value, Arena* arena) { \ - *value = 0; \ - } \ - template \ - inline void MapTypeHandler:: \ - ClearMaybeByDefaultEnum(TypeOnMemory* value, Arena* arena, \ - int default_enum_value) { \ - *value = static_cast(default_enum_value); \ - } \ - template \ - inline void MapTypeHandler::Merge( \ - const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \ - *to = from; \ - } \ - template \ - inline void MapTypeHandler::DeleteNoArena(TypeOnMemory& x) {} \ - template \ - inline void MapTypeHandler::AssignDefaultValue(TypeOnMemory* value) {} \ - template \ - inline void \ - MapTypeHandler::Initialize( \ - TypeOnMemory* value, Arena* arena) { \ - *value = 0; \ - } \ - template \ - inline void MapTypeHandler:: \ - InitializeMaybeByDefaultEnum(TypeOnMemory* value, \ - int default_enum_value, Arena* arena) { \ - *value = static_cast(default_enum_value); \ - } \ - template \ - inline typename MapTypeHandler::MapEntryAccessorType* \ - MapTypeHandler::EnsureMutable( \ - TypeOnMemory* value, Arena* arena) { \ - return value; \ - } \ - template \ - inline const typename MapTypeHandler::MapEntryAccessorType& \ - MapTypeHandler::DefaultIfNotInitialized(const TypeOnMemory& value, \ - const TypeOnMemory& \ - default_value) { \ - return value; \ - } \ - template \ - inline bool MapTypeHandler::IsInitialized(const TypeOnMemory& value) { \ - return true; \ +#define PRIMITIVE_HANDLER_FUNCTIONS(FieldType) \ + template \ + inline const typename MapTypeHandler::MapEntryAccessorType& \ + MapTypeHandler::GetExternalReference(const TypeOnMemory& value) { \ + return value; \ + } \ + template \ + inline size_t MapTypeHandler:: \ + SpaceUsedInMapEntryLong(const TypeOnMemory& /* value */) { \ + return 0; \ + } \ + template \ + inline void MapTypeHandler::Clear( \ + TypeOnMemory* value, Arena* /* arena */) { \ + *value = 0; \ + } \ + template \ + inline void MapTypeHandler::Merge( \ + const MapEntryAccessorType& from, TypeOnMemory* to, \ + Arena* /* arena */) { \ + *to = from; \ + } \ + template \ + inline void MapTypeHandler::DeleteNoArena(TypeOnMemory& /* x */) {} \ + template \ + constexpr auto \ + MapTypeHandler::Constinit() \ + ->TypeOnMemory { \ + return 0; \ + } \ + template \ + inline typename MapTypeHandler::MapEntryAccessorType* \ + MapTypeHandler::EnsureMutable( \ + TypeOnMemory* value, Arena* /* arena */) { \ + return value; \ + } \ + template \ + inline const typename MapTypeHandler::MapEntryAccessorType& \ + MapTypeHandler::DefaultIfNotInitialized(const TypeOnMemory& value) { \ + return value; \ + } \ + template \ + inline bool \ + MapTypeHandler::IsInitialized( \ + const TypeOnMemory& /* value */) { \ + return true; \ } PRIMITIVE_HANDLER_FUNCTIONS(INT64) PRIMITIVE_HANDLER_FUNCTIONS(UINT64) @@ -731,6 +683,6 @@ PRIMITIVE_HANDLER_FUNCTIONS(BOOL) } // namespace internal } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_TYPE_HANDLER_H__ diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto index 836dc10b374b3..263ef61f806ad 100644 --- a/src/google/protobuf/map_unittest.proto +++ b/src/google/protobuf/map_unittest.proto @@ -33,7 +33,6 @@ syntax = "proto3"; option cc_enable_arenas = true; import "google/protobuf/unittest.proto"; -import "google/protobuf/unittest_no_arena.proto"; // We don't put this in a package within proto2 because we need to make sure // that the generated code doesn't depend on being in the proto2 namespace. @@ -42,25 +41,25 @@ package protobuf_unittest; // Tests maps. message TestMap { - map map_int32_int32 = 1; - map map_int64_int64 = 2; - map map_uint32_uint32 = 3; - map map_uint64_uint64 = 4; - map map_sint32_sint32 = 5; - map map_sint64_sint64 = 6; - map map_fixed32_fixed32 = 7; - map map_fixed64_fixed64 = 8; + map map_int32_int32 = 1; + map map_int64_int64 = 2; + map map_uint32_uint32 = 3; + map map_uint64_uint64 = 4; + map map_sint32_sint32 = 5; + map map_sint64_sint64 = 6; + map map_fixed32_fixed32 = 7; + map map_fixed64_fixed64 = 8; map map_sfixed32_sfixed32 = 9; map map_sfixed64_sfixed64 = 10; - map map_int32_float = 11; - map map_int32_double = 12; - map map_bool_bool = 13; - map map_string_string = 14; - map map_int32_bytes = 15; - map map_int32_enum = 16; - map map_int32_foreign_message = 17; - map map_string_foreign_message = 18; - map map_int32_all_types = 19; + map map_int32_float = 11; + map map_int32_double = 12; + map map_bool_bool = 13; + map map_string_string = 14; + map map_int32_bytes = 15; + map map_int32_enum = 16; + map map_int32_foreign_message = 17; + map map_string_foreign_message = 18; + map map_int32_all_types = 19; } message TestMapSubmessage { @@ -90,33 +89,29 @@ message TestRequiredMessageMap { } message TestArenaMap { - map map_int32_int32 = 1; - map map_int64_int64 = 2; - map map_uint32_uint32 = 3; - map map_uint64_uint64 = 4; - map map_sint32_sint32 = 5; - map map_sint64_sint64 = 6; - map map_fixed32_fixed32 = 7; - map map_fixed64_fixed64 = 8; + map map_int32_int32 = 1; + map map_int64_int64 = 2; + map map_uint32_uint32 = 3; + map map_uint64_uint64 = 4; + map map_sint32_sint32 = 5; + map map_sint64_sint64 = 6; + map map_fixed32_fixed32 = 7; + map map_fixed64_fixed64 = 8; map map_sfixed32_sfixed32 = 9; map map_sfixed64_sfixed64 = 10; - map map_int32_float = 11; - map map_int32_double = 12; - map map_bool_bool = 13; - map map_string_string = 14; - map map_int32_bytes = 15; - map map_int32_enum = 16; - map map_int32_foreign_message = 17; - map - map_int32_foreign_message_no_arena = 18; + map map_int32_float = 11; + map map_int32_double = 12; + map map_bool_bool = 13; + map map_string_string = 14; + map map_int32_bytes = 15; + map map_int32_enum = 16; + map map_int32_foreign_message = 17; } // Previously, message containing enum called Type cannot be used as value of // map field. message MessageContainingEnumCalledType { - enum Type { - TYPE_FOO = 0; - } + enum Type { TYPE_FOO = 0; } map type = 1; } diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index c01d1974b01c9..1a5c77560e65e 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -32,42 +32,61 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include + #include #include -#include - -#include +#include +#include #include #include -#include -#include +#include +#include #include #include #include -#include #include +#include #include #include +#include #include +#include #include +#include #include #include -#include #include +#include + +#include namespace google { namespace protobuf { -using internal::WireFormat; +namespace internal { + +// TODO(gerbens) make this factorized better. This should not have to hop +// to reflection. Currently uses GeneratedMessageReflection and thus is +// defined in generated_message_reflection.cc +void RegisterFileLevelMetadata(const DescriptorTable* descriptor_table); + +} // namespace internal + using internal::ReflectionOps; +using internal::WireFormat; +using internal::WireFormatLite; void Message::MergeFrom(const Message& from) { const Descriptor* descriptor = GetDescriptor(); GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor) - << ": Tried to merge from a message with a different type. " - "to: " << descriptor->full_name() << ", " - "from: " << from.GetDescriptor()->full_name(); + << ": Tried to merge from a message with a different type. " + "to: " + << descriptor->full_name() + << ", " + "from: " + << from.GetDescriptor()->full_name(); ReflectionOps::Merge(from, this); } @@ -78,78 +97,53 @@ void Message::CheckTypeAndMergeFrom(const MessageLite& other) { void Message::CopyFrom(const Message& from) { const Descriptor* descriptor = GetDescriptor(); GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor) - << ": Tried to copy from a message with a different type. " - "to: " << descriptor->full_name() << ", " - "from: " << from.GetDescriptor()->full_name(); + << ": Tried to copy from a message with a different type. " + "to: " + << descriptor->full_name() + << ", " + "from: " + << from.GetDescriptor()->full_name(); ReflectionOps::Copy(from, this); } -string Message::GetTypeName() const { +std::string Message::GetTypeName() const { return GetDescriptor()->full_name(); } -void Message::Clear() { - ReflectionOps::Clear(this); -} +void Message::Clear() { ReflectionOps::Clear(this); } bool Message::IsInitialized() const { return ReflectionOps::IsInitialized(*this); } -void Message::FindInitializationErrors(std::vector* errors) const { +void Message::FindInitializationErrors(std::vector* errors) const { return ReflectionOps::FindInitializationErrors(*this, "", errors); } -string Message::InitializationErrorString() const { - std::vector errors; +std::string Message::InitializationErrorString() const { + std::vector errors; FindInitializationErrors(&errors); return Join(errors, ", "); } void Message::CheckInitialized() const { - GOOGLE_CHECK(IsInitialized()) - << "Message of type \"" << GetDescriptor()->full_name() - << "\" is missing required fields: " << InitializationErrorString(); + GOOGLE_CHECK(IsInitialized()) << "Message of type \"" << GetDescriptor()->full_name() + << "\" is missing required fields: " + << InitializationErrorString(); } void Message::DiscardUnknownFields() { return ReflectionOps::DiscardUnknownFields(this); } -bool Message::MergePartialFromCodedStream(io::CodedInputStream* input) { - return WireFormat::ParseAndMergePartial(input, this); -} - -bool Message::ParseFromFileDescriptor(int file_descriptor) { - io::FileInputStream input(file_descriptor); - return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0; -} - -bool Message::ParsePartialFromFileDescriptor(int file_descriptor) { - io::FileInputStream input(file_descriptor); - return ParsePartialFromZeroCopyStream(&input) && input.GetErrno() == 0; +const char* Message::_InternalParse(const char* ptr, + internal::ParseContext* ctx) { + return WireFormat::_InternalParse(this, ptr, ctx); } -bool Message::ParseFromIstream(std::istream* input) { - io::IstreamInputStream zero_copy_input(input); - return ParseFromZeroCopyStream(&zero_copy_input) && input->eof(); -} - -bool Message::ParsePartialFromIstream(std::istream* input) { - io::IstreamInputStream zero_copy_input(input); - return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof(); -} - - -void Message::SerializeWithCachedSizes( - io::CodedOutputStream* output) const { - const internal::SerializationTable* table = - static_cast(InternalGetTable()); - if (table == 0) { - WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output); - } else { - internal::TableSerialize(*this, table, output); - } +uint8* Message::_InternalSerialize(uint8* target, + io::EpsCopyOutputStream* stream) const { + return WireFormat::_InternalSerialize(*this, target, stream); } size_t Message::ByteSizeLong() const { @@ -168,87 +162,8 @@ size_t Message::SpaceUsedLong() const { return GetReflection()->SpaceUsedLong(*this); } -bool Message::SerializeToFileDescriptor(int file_descriptor) const { - io::FileOutputStream output(file_descriptor); - return SerializeToZeroCopyStream(&output); -} - -bool Message::SerializePartialToFileDescriptor(int file_descriptor) const { - io::FileOutputStream output(file_descriptor); - return SerializePartialToZeroCopyStream(&output); -} - -bool Message::SerializeToOstream(std::ostream* output) const { - { - io::OstreamOutputStream zero_copy_output(output); - if (!SerializeToZeroCopyStream(&zero_copy_output)) return false; - } - return output->good(); -} - -bool Message::SerializePartialToOstream(std::ostream* output) const { - io::OstreamOutputStream zero_copy_output(output); - return SerializePartialToZeroCopyStream(&zero_copy_output); -} - - -// ============================================================================= -// Reflection and associated Template Specializations - -Reflection::~Reflection() {} - -void Reflection::AddAllocatedMessage(Message* /* message */, - const FieldDescriptor* /*field */, - Message* /* new_entry */) const {} - -#define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE) \ -template<> \ -const RepeatedField& Reflection::GetRepeatedField( \ - const Message& message, const FieldDescriptor* field) const { \ - return *static_cast* >( \ - MutableRawRepeatedField(const_cast(&message), \ - field, CPPTYPE, CTYPE, NULL)); \ -} \ - \ -template<> \ -RepeatedField* Reflection::MutableRepeatedField( \ - Message* message, const FieldDescriptor* field) const { \ - return static_cast* >( \ - MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, NULL)); \ -} - -HANDLE_TYPE(int32, FieldDescriptor::CPPTYPE_INT32, -1); -HANDLE_TYPE(int64, FieldDescriptor::CPPTYPE_INT64, -1); -HANDLE_TYPE(uint32, FieldDescriptor::CPPTYPE_UINT32, -1); -HANDLE_TYPE(uint64, FieldDescriptor::CPPTYPE_UINT64, -1); -HANDLE_TYPE(float, FieldDescriptor::CPPTYPE_FLOAT, -1); -HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1); -HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1); - - -#undef HANDLE_TYPE - -void* Reflection::MutableRawRepeatedString( - Message* message, const FieldDescriptor* field, bool is_string) const { - return MutableRawRepeatedField(message, field, - FieldDescriptor::CPPTYPE_STRING, FieldOptions::STRING, NULL); -} - - -MapIterator Reflection::MapBegin( - Message* message, - const FieldDescriptor* field) const { - GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API."; - MapIterator iter(message, field); - return iter; -} - -MapIterator Reflection::MapEnd( - Message* message, - const FieldDescriptor* field) const { - GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API."; - MapIterator iter(message, field); - return iter; +uint64 Message::GetInvariantPerBuild(uint64 salt) { + return salt; } // ============================================================================= @@ -258,63 +173,50 @@ MessageFactory::~MessageFactory() {} namespace { -class GeneratedMessageFactory : public MessageFactory { - public: - GeneratedMessageFactory(); - ~GeneratedMessageFactory(); +#define HASH_MAP std::unordered_map +#define STR_HASH_FXN hash<::google::protobuf::StringPiece> + + +class GeneratedMessageFactory final : public MessageFactory { + public: static GeneratedMessageFactory* singleton(); - typedef void RegistrationFunc(const string&); - void RegisterFile(const char* file, RegistrationFunc* registration_func); + void RegisterFile(const google::protobuf::internal::DescriptorTable* table); void RegisterType(const Descriptor* descriptor, const Message* prototype); // implements MessageFactory --------------------------------------- - const Message* GetPrototype(const Descriptor* type); + const Message* GetPrototype(const Descriptor* type) override; private: // Only written at static init time, so does not require locking. - hash_map, streq> file_map_; + HASH_MAP + file_map_; - Mutex mutex_; + internal::WrappedMutex mutex_; // Initialized lazily, so requires locking. - hash_map type_map_; + std::unordered_map type_map_; }; -GeneratedMessageFactory* generated_message_factory_ = NULL; -GOOGLE_PROTOBUF_DECLARE_ONCE(generated_message_factory_once_init_); - -void ShutdownGeneratedMessageFactory() { - delete generated_message_factory_; -} - -void InitGeneratedMessageFactory() { - generated_message_factory_ = new GeneratedMessageFactory; - internal::OnShutdown(&ShutdownGeneratedMessageFactory); -} - -GeneratedMessageFactory::GeneratedMessageFactory() {} -GeneratedMessageFactory::~GeneratedMessageFactory() {} - GeneratedMessageFactory* GeneratedMessageFactory::singleton() { - ::google::protobuf::GoogleOnceInit(&generated_message_factory_once_init_, - &InitGeneratedMessageFactory); - return generated_message_factory_; + static auto instance = + internal::OnShutdownDelete(new GeneratedMessageFactory); + return instance; } void GeneratedMessageFactory::RegisterFile( - const char* file, RegistrationFunc* registration_func) { - if (!InsertIfNotPresent(&file_map_, file, registration_func)) { - GOOGLE_LOG(FATAL) << "File is already registered: " << file; + const google::protobuf::internal::DescriptorTable* table) { + if (!InsertIfNotPresent(&file_map_, table->filename, table)) { + GOOGLE_LOG(FATAL) << "File is already registered: " << table->filename; } } void GeneratedMessageFactory::RegisterType(const Descriptor* descriptor, const Message* prototype) { GOOGLE_DCHECK_EQ(descriptor->file()->pool(), DescriptorPool::generated_pool()) - << "Tried to register a non-generated type with the generated " - "type registry."; + << "Tried to register a non-generated type with the generated " + "type registry."; // This should only be called as a result of calling a file registration // function during GetPrototype(), in which case we already have locked @@ -338,11 +240,12 @@ const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) { if (type->file()->pool() != DescriptorPool::generated_pool()) return NULL; // Apparently the file hasn't been registered yet. Let's do that now. - RegistrationFunc* registration_func = + const internal::DescriptorTable* registration_data = FindPtrOrNull(file_map_, type->file()->name().c_str()); - if (registration_func == NULL) { + if (registration_data == NULL) { GOOGLE_LOG(DFATAL) << "File appears to be in generated pool but wasn't " - "registered: " << type->file()->name(); + "registered: " + << type->file()->name(); return NULL; } @@ -352,7 +255,7 @@ const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) { const Message* result = FindPtrOrNull(type_map_, type); if (result == NULL) { // Nope. OK, register everything. - registration_func(type->file()->name()); + internal::RegisterFileLevelMetadata(registration_data); // Should be here now. result = FindPtrOrNull(type_map_, type); } @@ -372,9 +275,8 @@ MessageFactory* MessageFactory::generated_factory() { } void MessageFactory::InternalRegisterGeneratedFile( - const char* filename, void (*register_messages)(const string&)) { - GeneratedMessageFactory::singleton()->RegisterFile(filename, - register_messages); + const google::protobuf::internal::DescriptorTable* table) { + GeneratedMessageFactory::singleton()->RegisterFile(table); } void MessageFactory::InternalRegisterGeneratedMessage( @@ -383,31 +285,21 @@ void MessageFactory::InternalRegisterGeneratedMessage( } -MessageFactory* Reflection::GetMessageFactory() const { - GOOGLE_LOG(FATAL) << "Not implemented."; - return NULL; -} - -void* Reflection::RepeatedFieldData( - Message* message, const FieldDescriptor* field, - FieldDescriptor::CppType cpp_type, - const Descriptor* message_type) const { - GOOGLE_LOG(FATAL) << "Not implemented."; - return NULL; -} - -namespace internal { -RepeatedFieldAccessor::~RepeatedFieldAccessor() { +namespace { +template +T* GetSingleton() { + static T singleton; + return &singleton; } -} // namespace internal +} // namespace const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor( const FieldDescriptor* field) const { GOOGLE_CHECK(field->is_repeated()); switch (field->cpp_type()) { #define HANDLE_PRIMITIVE_TYPE(TYPE, type) \ - case FieldDescriptor::CPPTYPE_ ## TYPE: \ - return internal::Singleton >::get(); + case FieldDescriptor::CPPTYPE_##TYPE: \ + return GetSingleton >(); HANDLE_PRIMITIVE_TYPE(INT32, int32) HANDLE_PRIMITIVE_TYPE(UINT32, uint32) HANDLE_PRIMITIVE_TYPE(INT64, int64) @@ -421,14 +313,14 @@ const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor( switch (field->options().ctype()) { default: case FieldOptions::STRING: - return internal::Singleton::get(); + return GetSingleton(); } break; case FieldDescriptor::CPPTYPE_MESSAGE: if (field->is_map()) { - return internal::Singleton::get(); + return GetSingleton(); } else { - return internal::Singleton::get(); + return GetSingleton(); } } GOOGLE_LOG(FATAL) << "Should not reach here."; @@ -436,58 +328,40 @@ const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor( } namespace internal { -namespace { -void ShutdownRepeatedFieldAccessor() { - internal::Singleton >::ShutDown(); - internal::Singleton >::ShutDown(); - internal::Singleton >::ShutDown(); - internal::Singleton >::ShutDown(); - internal::Singleton >::ShutDown(); - internal::Singleton >::ShutDown(); - internal::Singleton >::ShutDown(); - internal::Singleton::ShutDown(); - internal::Singleton::ShutDown(); - internal::Singleton::ShutDown(); -} - -struct ShutdownRepeatedFieldRegister { - ShutdownRepeatedFieldRegister() { - OnShutdown(&ShutdownRepeatedFieldAccessor); - } -} shutdown_; - -} // namespace -} // namespace internal - -namespace internal { -template<> +template <> #if defined(_MSC_VER) && (_MSC_VER >= 1800) -// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue #240 -GOOGLE_ATTRIBUTE_NOINLINE +// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue +// #240 +PROTOBUF_NOINLINE #endif -Message* GenericTypeHandler::NewFromPrototype( - const Message* prototype, google::protobuf::Arena* arena) { + Message* + GenericTypeHandler::NewFromPrototype(const Message* prototype, + Arena* arena) { return prototype->New(arena); } -template<> +template <> #if defined(_MSC_VER) && (_MSC_VER >= 1800) -// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue #240 -GOOGLE_ATTRIBUTE_NOINLINE +// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue +// #240 +PROTOBUF_NOINLINE #endif -google::protobuf::Arena* GenericTypeHandler::GetArena( - Message* value) { + Arena* + GenericTypeHandler::GetArena(Message* value) { return value->GetArena(); } -template<> +template <> #if defined(_MSC_VER) && (_MSC_VER >= 1800) -// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue #240 -GOOGLE_ATTRIBUTE_NOINLINE +// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue +// #240 +PROTOBUF_NOINLINE #endif -void* GenericTypeHandler::GetMaybeArenaPointer( - Message* value) { + void* + GenericTypeHandler::GetMaybeArenaPointer(Message* value) { return value->GetMaybeArenaPointer(); } } // namespace internal } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index 44fe0fdef035a..52e6a1db19bd1 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -49,7 +49,7 @@ // Then, if you used the protocol compiler to generate a class from the above // definition, you could use it like so: // -// string data; // Will store a serialized version of the message. +// std::string data; // Will store a serialized version of the message. // // { // // Create a message and serialize it. @@ -84,12 +84,12 @@ // // Get the descriptors for the fields we're interested in and verify // // their types. // const FieldDescriptor* text_field = descriptor->FindFieldByName("text"); -// assert(text_field != NULL); +// assert(text_field != nullptr); // assert(text_field->type() == FieldDescriptor::TYPE_STRING); // assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL); // const FieldDescriptor* numbers_field = descriptor-> // FindFieldByName("numbers"); -// assert(numbers_field != NULL); +// assert(numbers_field != nullptr); // assert(numbers_field->type() == FieldDescriptor::TYPE_INT32); // assert(numbers_field->label() == FieldDescriptor::LABEL_REPEATED); // @@ -112,19 +112,27 @@ #include #include -#include +#include #include -#include -#include - +#include #include +#include #include +#include +#include +#include #define GOOGLE_PROTOBUF_HAS_ONEOF #define GOOGLE_PROTOBUF_HAS_ARENAS +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + namespace google { namespace protobuf { @@ -134,37 +142,52 @@ class Reflection; class MessageFactory; // Defined in other files. +class AssignDescriptorsHelper; +class DynamicMessageFactory; class MapKey; +class MapValueConstRef; class MapValueRef; class MapIterator; class MapReflectionTester; namespace internal { +struct DescriptorTable; class MapFieldBase; } -class UnknownFieldSet; // unknown_field_set.h +class UnknownFieldSet; // unknown_field_set.h namespace io { -class ZeroCopyInputStream; // zero_copy_stream.h -class ZeroCopyOutputStream; // zero_copy_stream.h -class CodedInputStream; // coded_stream.h -class CodedOutputStream; // coded_stream.h -} +class ZeroCopyInputStream; // zero_copy_stream.h +class ZeroCopyOutputStream; // zero_copy_stream.h +class CodedInputStream; // coded_stream.h +class CodedOutputStream; // coded_stream.h +} // namespace io namespace python { -class MapReflectionFriend; // scalar_map_container.h +class MapReflectionFriend; // scalar_map_container.h +} +namespace expr { +class CelMapReflectionFriend; // field_backed_map_impl.cc +} + +namespace internal { +class MapFieldPrinterHelper; // text_format.cc +} +namespace util { +class MessageDifferencer; } namespace internal { -class ReflectionOps; // reflection_ops.h -class MapKeySorter; // wire_format.cc -class WireFormat; // wire_format.h +class ReflectionAccessor; // message.cc +class ReflectionOps; // reflection_ops.h +class MapKeySorter; // wire_format.cc +class WireFormat; // wire_format.h class MapFieldReflectionTest; // map_test.cc -} +} // namespace internal -template -class RepeatedField; // repeated_field.h +template +class RepeatedField; // repeated_field.h -template +template class RepeatedPtrField; // repeated_field.h // A container to hold message metadata. @@ -173,6 +196,26 @@ struct Metadata { const Reflection* reflection; }; +namespace internal { +template +inline To* GetPointerAtOffset(Message* message, uint32 offset) { + return reinterpret_cast(reinterpret_cast(message) + offset); +} + +template +const To* GetConstPointerAtOffset(const Message* message, uint32 offset) { + return reinterpret_cast(reinterpret_cast(message) + + offset); +} + +template +const To& GetConstRefAtOffset(const Message& message, uint32 offset) { + return *GetConstPointerAtOffset(&message, offset); +} + +bool CreateUnknownEnumValues(const FieldDescriptor* field); +} // namespace internal + // Abstract interface for protocol messages. // // See also MessageLite, which contains most every-day operations. Message @@ -183,24 +226,26 @@ struct Metadata { // optimized for speed will want to override these with faster implementations, // but classes optimized for code size may be happy with keeping them. See // the optimize_for option in descriptor.proto. -class LIBPROTOBUF_EXPORT Message : public MessageLite { +// +// Users must not derive from this class. Only the protocol compiler and +// the internal library are allowed to create subclasses. +class PROTOBUF_EXPORT Message : public MessageLite { public: - inline Message() {} - virtual ~Message() {} + constexpr Message() {} // Basic Operations ------------------------------------------------ // Construct a new instance of the same type. Ownership is passed to the // caller. (This is also defined in MessageLite, but is defined again here // for return-type covariance.) - virtual Message* New() const = 0; + Message* New() const override = 0; // Construct a new instance on the arena. Ownership is passed to the caller - // if arena is a NULL. Default implementation allows for API compatibility + // if arena is a nullptr. Default implementation allows for API compatibility // during the Arena transition. - virtual Message* New(::google::protobuf::Arena* arena) const { + Message* New(Arena* arena) const override { Message* message = New(); - if (arena != NULL) { + if (arena != nullptr) { arena->Own(message); } return message; @@ -226,11 +271,11 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite { // This is much, much slower than IsInitialized() as it is implemented // purely via reflection. Generally, you should not call this unless you // have already determined that an error exists by calling IsInitialized(). - void FindInitializationErrors(std::vector* errors) const; + void FindInitializationErrors(std::vector* errors) const; // Like FindInitializationErrors, but joins all the strings, delimited by // commas, and returns them. - string InitializationErrorString() const; + std::string InitializationErrorString() const override; // Clears all unknown fields from this message and all embedded messages. // Normally, if unknown tag numbers are encountered when parsing a message, @@ -254,61 +299,39 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite { // fields defined for the proto. virtual size_t SpaceUsedLong() const; - PROTOBUF_RUNTIME_DEPRECATED("Please use SpaceUsedLong() instead") + PROTOBUF_DEPRECATED_MSG("Please use SpaceUsedLong() instead") int SpaceUsed() const { return internal::ToIntSize(SpaceUsedLong()); } // Debugging & Testing---------------------------------------------- // Generates a human readable form of this message, useful for debugging // and other purposes. - string DebugString() const; + std::string DebugString() const; // Like DebugString(), but with less whitespace. - string ShortDebugString() const; + std::string ShortDebugString() const; // Like DebugString(), but do not escape UTF-8 byte sequences. - string Utf8DebugString() const; + std::string Utf8DebugString() const; // Convenience function useful in GDB. Prints DebugString() to stdout. void PrintDebugString() const; - // Heavy I/O ------------------------------------------------------- - // Additional parsing and serialization methods not implemented by - // MessageLite because they are not supported by the lite library. - - // Parse a protocol buffer from a file descriptor. If successful, the entire - // input will be consumed. - bool ParseFromFileDescriptor(int file_descriptor); - // Like ParseFromFileDescriptor(), but accepts messages that are missing - // required fields. - bool ParsePartialFromFileDescriptor(int file_descriptor); - // Parse a protocol buffer from a C++ istream. If successful, the entire - // input will be consumed. - bool ParseFromIstream(std::istream* input); - // Like ParseFromIstream(), but accepts messages that are missing - // required fields. - bool ParsePartialFromIstream(std::istream* input); - - // Serialize the message and write it to the given file descriptor. All - // required fields must be set. - bool SerializeToFileDescriptor(int file_descriptor) const; - // Like SerializeToFileDescriptor(), but allows missing required fields. - bool SerializePartialToFileDescriptor(int file_descriptor) const; - // Serialize the message and write it to the given C++ ostream. All - // required fields must be set. - bool SerializeToOstream(std::ostream* output) const; - // Like SerializeToOstream(), but allows missing required fields. - bool SerializePartialToOstream(std::ostream* output) const; - - // Reflection-based methods ---------------------------------------- // These methods are pure-virtual in MessageLite, but Message provides // reflection-based default implementations. - virtual string GetTypeName() const; - virtual void Clear(); - virtual bool IsInitialized() const; - virtual void CheckTypeAndMergeFrom(const MessageLite& other); - virtual bool MergePartialFromCodedStream(io::CodedInputStream* input); - virtual size_t ByteSizeLong() const; - virtual void SerializeWithCachedSizes(io::CodedOutputStream* output) const; + std::string GetTypeName() const override; + void Clear() override; + + // Returns whether all required fields have been set. Note that required + // fields no longer exist starting in proto3. + bool IsInitialized() const override; + + void CheckTypeAndMergeFrom(const MessageLite& other) override; + // Reflective parser + const char* _InternalParse(const char* ptr, + internal::ParseContext* ctx) override; + size_t ByteSizeLong() const override; + uint8* _InternalSerialize(uint8* target, + io::EpsCopyOutputStream* stream) const override; private: // This is called only by the default implementation of ByteSize(), to @@ -321,33 +344,30 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite { virtual void SetCachedSize(int size) const; public: - // Introspection --------------------------------------------------- - // Typedef for backwards-compatibility. - typedef google::protobuf::Reflection Reflection; - // Get a Descriptor for this message's type. This describes what - // fields the message contains, the types of those fields, etc. + // Get a non-owning pointer to a Descriptor for this message's type. This + // describes what fields the message contains, the types of those fields, etc. + // This object remains property of the Message. const Descriptor* GetDescriptor() const { return GetMetadata().descriptor; } - // Get the Reflection interface for this Message, which can be used to - // read and modify the fields of the Message dynamically (in other words, - // without knowing the message type at compile time). This object remains - // property of the Message. - // - // This method remains virtual in case a subclass does not implement - // reflection and wants to override the default behavior. - virtual const Reflection* GetReflection() const { - return GetMetadata().reflection; - } + // Get a non-owning pointer to the Reflection interface for this Message, + // which can be used to read and modify the fields of the Message dynamically + // (in other words, without knowing the message type at compile time). This + // object remains property of the Message. + const Reflection* GetReflection() const { return GetMetadata().reflection; } protected: - // Get a struct containing the metadata for the Message. Most subclasses only - // need to implement this method, rather than the GetDescriptor() and - // GetReflection() wrappers. - virtual Metadata GetMetadata() const = 0; + // Get a struct containing the metadata for the Message, which is used in turn + // to implement GetDescriptor() and GetReflection() above. + virtual Metadata GetMetadata() const = 0; + + inline explicit Message(Arena* arena) : MessageLite(arena) {} + + protected: + static uint64 GetInvariantPerBuild(uint64 salt); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message); @@ -361,10 +381,10 @@ class RepeatedFieldAccessor; // Forward-declare RepeatedFieldRef templates. The second type parameter is // used for SFINAE tricks. Users should ignore it. -template +template class RepeatedFieldRef; -template +template class MutableRepeatedFieldRef; // This interface contains methods that can be used to dynamically access @@ -405,67 +425,46 @@ class MutableRepeatedFieldRef; // double the message's memory footprint, probably worse. Allocating the // objects on-demand, on the other hand, would be expensive and prone to // memory leaks. So, instead we ended up with this flat interface. -// -// TODO(kenton): Create a utility class which callers can use to read and -// write fields from a Reflection without paying attention to the type. -class LIBPROTOBUF_EXPORT Reflection { +class PROTOBUF_EXPORT Reflection final { public: - inline Reflection() {} - virtual ~Reflection(); - // Get the UnknownFieldSet for the message. This contains fields which // were seen when the Message was parsed but were not recognized according - // to the Message's definition. For proto3 protos, this method will always - // return an empty UnknownFieldSet. - virtual const UnknownFieldSet& GetUnknownFields( - const Message& message) const = 0; + // to the Message's definition. + const UnknownFieldSet& GetUnknownFields(const Message& message) const; // Get a mutable pointer to the UnknownFieldSet for the message. This // contains fields which were seen when the Message was parsed but were not - // recognized according to the Message's definition. For proto3 protos, this - // method will return a valid mutable UnknownFieldSet pointer but modifying - // it won't affect the serialized bytes of the message. - virtual UnknownFieldSet* MutableUnknownFields(Message* message) const = 0; + // recognized according to the Message's definition. + UnknownFieldSet* MutableUnknownFields(Message* message) const; // Estimate the amount of memory used by the message object. - virtual size_t SpaceUsedLong(const Message& message) const = 0; + size_t SpaceUsedLong(const Message& message) const; - PROTOBUF_RUNTIME_DEPRECATED("Please use SpaceUsedLong() instead") + PROTOBUF_DEPRECATED_MSG("Please use SpaceUsedLong() instead") int SpaceUsed(const Message& message) const { return internal::ToIntSize(SpaceUsedLong(message)); } // Check if the given non-repeated field is set. - virtual bool HasField(const Message& message, - const FieldDescriptor* field) const = 0; + bool HasField(const Message& message, const FieldDescriptor* field) const; // Get the number of elements of a repeated field. - virtual int FieldSize(const Message& message, - const FieldDescriptor* field) const = 0; + int FieldSize(const Message& message, const FieldDescriptor* field) const; // Clear the value of a field, so that HasField() returns false or // FieldSize() returns zero. - virtual void ClearField(Message* message, - const FieldDescriptor* field) const = 0; + void ClearField(Message* message, const FieldDescriptor* field) const; // Check if the oneof is set. Returns true if any field in oneof // is set, false otherwise. - // TODO(jieluo) - make it pure virtual after updating all - // the subclasses. - virtual bool HasOneof(const Message& /*message*/, - const OneofDescriptor* /*oneof_descriptor*/) const { - return false; - } + bool HasOneof(const Message& message, + const OneofDescriptor* oneof_descriptor) const; - virtual void ClearOneof(Message* /*message*/, - const OneofDescriptor* /*oneof_descriptor*/) const {} + void ClearOneof(Message* message, + const OneofDescriptor* oneof_descriptor) const; - // Returns the field descriptor if the oneof is set. NULL otherwise. - // TODO(jieluo) - make it pure virtual. - virtual const FieldDescriptor* GetOneofFieldDescriptor( - const Message& /*message*/, - const OneofDescriptor* /*oneof_descriptor*/) const { - return NULL; - } + // Returns the field descriptor if the oneof is set. nullptr otherwise. + const FieldDescriptor* GetOneofFieldDescriptor( + const Message& message, const OneofDescriptor* oneof_descriptor) const; // Removes the last element of a repeated field. // We don't provide a way to remove any element other than the last @@ -474,123 +473,111 @@ class LIBPROTOBUF_EXPORT Reflection { // than the last, the best way to do it is to re-arrange the elements // (using Swap()) so that the one you want removed is at the end, then // call RemoveLast(). - virtual void RemoveLast(Message* message, - const FieldDescriptor* field) const = 0; + void RemoveLast(Message* message, const FieldDescriptor* field) const; // Removes the last element of a repeated message field, and returns the // pointer to the caller. Caller takes ownership of the returned pointer. - virtual Message* ReleaseLast(Message* message, - const FieldDescriptor* field) const = 0; + Message* ReleaseLast(Message* message, const FieldDescriptor* field) const; // Swap the complete contents of two messages. - virtual void Swap(Message* message1, Message* message2) const = 0; + void Swap(Message* message1, Message* message2) const; // Swap fields listed in fields vector of two messages. - virtual void SwapFields(Message* message1, - Message* message2, - const std::vector& fields) - const = 0; + void SwapFields(Message* message1, Message* message2, + const std::vector& fields) const; // Swap two elements of a repeated field. - virtual void SwapElements(Message* message, - const FieldDescriptor* field, - int index1, - int index2) const = 0; - - // List all fields of the message which are currently set. This includes - // extensions. Singular fields will only be listed if HasField(field) would - // return true and repeated fields will only be listed if FieldSize(field) - // would return non-zero. Fields (both normal fields and extension fields) - // will be listed ordered by field number. - virtual void ListFields( - const Message& message, - std::vector* output) const = 0; + void SwapElements(Message* message, const FieldDescriptor* field, int index1, + int index2) const; + + // List all fields of the message which are currently set, except for unknown + // fields, but including extension known to the parser (i.e. compiled in). + // Singular fields will only be listed if HasField(field) would return true + // and repeated fields will only be listed if FieldSize(field) would return + // non-zero. Fields (both normal fields and extension fields) will be listed + // ordered by field number. + // Use Reflection::GetUnknownFields() or message.unknown_fields() to also get + // access to fields/extensions unknown to the parser. + void ListFields(const Message& message, + std::vector* output) const; // Singular field getters ------------------------------------------ // These get the value of a non-repeated field. They return the default // value for fields that aren't set. - virtual int32 GetInt32 (const Message& message, - const FieldDescriptor* field) const = 0; - virtual int64 GetInt64 (const Message& message, - const FieldDescriptor* field) const = 0; - virtual uint32 GetUInt32(const Message& message, - const FieldDescriptor* field) const = 0; - virtual uint64 GetUInt64(const Message& message, - const FieldDescriptor* field) const = 0; - virtual float GetFloat (const Message& message, - const FieldDescriptor* field) const = 0; - virtual double GetDouble(const Message& message, - const FieldDescriptor* field) const = 0; - virtual bool GetBool (const Message& message, - const FieldDescriptor* field) const = 0; - virtual string GetString(const Message& message, - const FieldDescriptor* field) const = 0; - virtual const EnumValueDescriptor* GetEnum( - const Message& message, const FieldDescriptor* field) const = 0; + int32 GetInt32(const Message& message, const FieldDescriptor* field) const; + int64 GetInt64(const Message& message, const FieldDescriptor* field) const; + uint32 GetUInt32(const Message& message, const FieldDescriptor* field) const; + uint64 GetUInt64(const Message& message, const FieldDescriptor* field) const; + float GetFloat(const Message& message, const FieldDescriptor* field) const; + double GetDouble(const Message& message, const FieldDescriptor* field) const; + bool GetBool(const Message& message, const FieldDescriptor* field) const; + std::string GetString(const Message& message, + const FieldDescriptor* field) const; + const EnumValueDescriptor* GetEnum(const Message& message, + const FieldDescriptor* field) const; // GetEnumValue() returns an enum field's value as an integer rather than // an EnumValueDescriptor*. If the integer value does not correspond to a // known value descriptor, a new value descriptor is created. (Such a value // will only be present when the new unknown-enum-value semantics are enabled // for a message.) - virtual int GetEnumValue( - const Message& message, const FieldDescriptor* field) const = 0; + int GetEnumValue(const Message& message, const FieldDescriptor* field) const; // See MutableMessage() for the meaning of the "factory" parameter. - virtual const Message& GetMessage(const Message& message, - const FieldDescriptor* field, - MessageFactory* factory = NULL) const = 0; + const Message& GetMessage(const Message& message, + const FieldDescriptor* field, + MessageFactory* factory = nullptr) const; // Get a string value without copying, if possible. // // GetString() necessarily returns a copy of the string. This can be - // inefficient when the string is already stored in a string object in the - // underlying message. GetStringReference() will return a reference to the - // underlying string in this case. Otherwise, it will copy the string into - // *scratch and return that. + // inefficient when the std::string is already stored in a std::string object + // in the underlying message. GetStringReference() will return a reference to + // the underlying std::string in this case. Otherwise, it will copy the + // string into *scratch and return that. // // Note: It is perfectly reasonable and useful to write code like: - // str = reflection->GetStringReference(field, &str); + // str = reflection->GetStringReference(message, field, &str); // This line would ensure that only one copy of the string is made // regardless of the field's underlying representation. When initializing - // a newly-constructed string, though, it's just as fast and more readable - // to use code like: - // string str = reflection->GetString(message, field); - virtual const string& GetStringReference(const Message& message, - const FieldDescriptor* field, - string* scratch) const = 0; + // a newly-constructed string, though, it's just as fast and more + // readable to use code like: + // std::string str = reflection->GetString(message, field); + const std::string& GetStringReference(const Message& message, + const FieldDescriptor* field, + std::string* scratch) const; // Singular field mutators ----------------------------------------- // These mutate the value of a non-repeated field. - virtual void SetInt32 (Message* message, - const FieldDescriptor* field, int32 value) const = 0; - virtual void SetInt64 (Message* message, - const FieldDescriptor* field, int64 value) const = 0; - virtual void SetUInt32(Message* message, - const FieldDescriptor* field, uint32 value) const = 0; - virtual void SetUInt64(Message* message, - const FieldDescriptor* field, uint64 value) const = 0; - virtual void SetFloat (Message* message, - const FieldDescriptor* field, float value) const = 0; - virtual void SetDouble(Message* message, - const FieldDescriptor* field, double value) const = 0; - virtual void SetBool (Message* message, - const FieldDescriptor* field, bool value) const = 0; - virtual void SetString(Message* message, - const FieldDescriptor* field, - const string& value) const = 0; - virtual void SetEnum (Message* message, - const FieldDescriptor* field, - const EnumValueDescriptor* value) const = 0; + void SetInt32(Message* message, const FieldDescriptor* field, + int32 value) const; + void SetInt64(Message* message, const FieldDescriptor* field, + int64 value) const; + void SetUInt32(Message* message, const FieldDescriptor* field, + uint32 value) const; + void SetUInt64(Message* message, const FieldDescriptor* field, + uint64 value) const; + void SetFloat(Message* message, const FieldDescriptor* field, + float value) const; + void SetDouble(Message* message, const FieldDescriptor* field, + double value) const; + void SetBool(Message* message, const FieldDescriptor* field, + bool value) const; + void SetString(Message* message, const FieldDescriptor* field, + std::string value) const; + void SetEnum(Message* message, const FieldDescriptor* field, + const EnumValueDescriptor* value) const; // Set an enum field's value with an integer rather than EnumValueDescriptor. - // If the value does not correspond to a known enum value, either behavior is - // undefined (for proto2 messages), or the value is accepted silently for - // messages with new unknown-enum-value semantics. - virtual void SetEnumValue(Message* message, - const FieldDescriptor* field, - int value) const = 0; + // For proto3 this is just setting the enum field to the value specified, for + // proto2 it's more complicated. If value is a known enum value the field is + // set as usual. If the value is unknown then it is added to the unknown field + // set. Note this matches the behavior of parsing unknown enum values. + // If multiple calls with unknown values happen than they are all added to the + // unknown field set in order of the calls. + void SetEnumValue(Message* message, const FieldDescriptor* field, + int value) const; // Get a mutable pointer to a field with a message type. If a MessageFactory // is provided, it will be used to construct instances of the sub-message; @@ -602,161 +589,140 @@ class LIBPROTOBUF_EXPORT Reflection { // FieldDescriptor is for a compiled-in extension, then // factory->GetPrototype(field->message_type()) MUST return an instance of // the compiled-in class for this type, NOT DynamicMessage. - virtual Message* MutableMessage(Message* message, - const FieldDescriptor* field, - MessageFactory* factory = NULL) const = 0; + Message* MutableMessage(Message* message, const FieldDescriptor* field, + MessageFactory* factory = nullptr) const; // Replaces the message specified by 'field' with the already-allocated object // sub_message, passing ownership to the message. If the field contained a - // message, that message is deleted. If sub_message is NULL, the field is + // message, that message is deleted. If sub_message is nullptr, the field is // cleared. - virtual void SetAllocatedMessage(Message* message, - Message* sub_message, - const FieldDescriptor* field) const = 0; + void SetAllocatedMessage(Message* message, Message* sub_message, + const FieldDescriptor* field) const; // Releases the message specified by 'field' and returns the pointer, // ReleaseMessage() will return the message the message object if it exists. - // Otherwise, it may or may not return NULL. In any case, if the return value - // is non-NULL, the caller takes ownership of the pointer. + // Otherwise, it may or may not return nullptr. In any case, if the return + // value is non-null, the caller takes ownership of the pointer. // If the field existed (HasField() is true), then the returned pointer will // be the same as the pointer returned by MutableMessage(). // This function has the same effect as ClearField(). - virtual Message* ReleaseMessage(Message* message, - const FieldDescriptor* field, - MessageFactory* factory = NULL) const = 0; + Message* ReleaseMessage(Message* message, const FieldDescriptor* field, + MessageFactory* factory = nullptr) const; // Repeated field getters ------------------------------------------ // These get the value of one element of a repeated field. - virtual int32 GetRepeatedInt32 (const Message& message, - const FieldDescriptor* field, - int index) const = 0; - virtual int64 GetRepeatedInt64 (const Message& message, - const FieldDescriptor* field, - int index) const = 0; - virtual uint32 GetRepeatedUInt32(const Message& message, - const FieldDescriptor* field, - int index) const = 0; - virtual uint64 GetRepeatedUInt64(const Message& message, - const FieldDescriptor* field, - int index) const = 0; - virtual float GetRepeatedFloat (const Message& message, - const FieldDescriptor* field, - int index) const = 0; - virtual double GetRepeatedDouble(const Message& message, - const FieldDescriptor* field, - int index) const = 0; - virtual bool GetRepeatedBool (const Message& message, - const FieldDescriptor* field, - int index) const = 0; - virtual string GetRepeatedString(const Message& message, - const FieldDescriptor* field, - int index) const = 0; - virtual const EnumValueDescriptor* GetRepeatedEnum( - const Message& message, - const FieldDescriptor* field, int index) const = 0; + int32 GetRepeatedInt32(const Message& message, const FieldDescriptor* field, + int index) const; + int64 GetRepeatedInt64(const Message& message, const FieldDescriptor* field, + int index) const; + uint32 GetRepeatedUInt32(const Message& message, const FieldDescriptor* field, + int index) const; + uint64 GetRepeatedUInt64(const Message& message, const FieldDescriptor* field, + int index) const; + float GetRepeatedFloat(const Message& message, const FieldDescriptor* field, + int index) const; + double GetRepeatedDouble(const Message& message, const FieldDescriptor* field, + int index) const; + bool GetRepeatedBool(const Message& message, const FieldDescriptor* field, + int index) const; + std::string GetRepeatedString(const Message& message, + const FieldDescriptor* field, int index) const; + const EnumValueDescriptor* GetRepeatedEnum(const Message& message, + const FieldDescriptor* field, + int index) const; // GetRepeatedEnumValue() returns an enum field's value as an integer rather // than an EnumValueDescriptor*. If the integer value does not correspond to a // known value descriptor, a new value descriptor is created. (Such a value // will only be present when the new unknown-enum-value semantics are enabled // for a message.) - virtual int GetRepeatedEnumValue( - const Message& message, - const FieldDescriptor* field, int index) const = 0; - virtual const Message& GetRepeatedMessage( - const Message& message, - const FieldDescriptor* field, int index) const = 0; + int GetRepeatedEnumValue(const Message& message, const FieldDescriptor* field, + int index) const; + const Message& GetRepeatedMessage(const Message& message, + const FieldDescriptor* field, + int index) const; // See GetStringReference(), above. - virtual const string& GetRepeatedStringReference( - const Message& message, const FieldDescriptor* field, - int index, string* scratch) const = 0; + const std::string& GetRepeatedStringReference(const Message& message, + const FieldDescriptor* field, + int index, + std::string* scratch) const; // Repeated field mutators ----------------------------------------- // These mutate the value of one element of a repeated field. - virtual void SetRepeatedInt32 (Message* message, - const FieldDescriptor* field, - int index, int32 value) const = 0; - virtual void SetRepeatedInt64 (Message* message, - const FieldDescriptor* field, - int index, int64 value) const = 0; - virtual void SetRepeatedUInt32(Message* message, - const FieldDescriptor* field, - int index, uint32 value) const = 0; - virtual void SetRepeatedUInt64(Message* message, - const FieldDescriptor* field, - int index, uint64 value) const = 0; - virtual void SetRepeatedFloat (Message* message, - const FieldDescriptor* field, - int index, float value) const = 0; - virtual void SetRepeatedDouble(Message* message, - const FieldDescriptor* field, - int index, double value) const = 0; - virtual void SetRepeatedBool (Message* message, - const FieldDescriptor* field, - int index, bool value) const = 0; - virtual void SetRepeatedString(Message* message, - const FieldDescriptor* field, - int index, const string& value) const = 0; - virtual void SetRepeatedEnum(Message* message, - const FieldDescriptor* field, int index, - const EnumValueDescriptor* value) const = 0; + void SetRepeatedInt32(Message* message, const FieldDescriptor* field, + int index, int32 value) const; + void SetRepeatedInt64(Message* message, const FieldDescriptor* field, + int index, int64 value) const; + void SetRepeatedUInt32(Message* message, const FieldDescriptor* field, + int index, uint32 value) const; + void SetRepeatedUInt64(Message* message, const FieldDescriptor* field, + int index, uint64 value) const; + void SetRepeatedFloat(Message* message, const FieldDescriptor* field, + int index, float value) const; + void SetRepeatedDouble(Message* message, const FieldDescriptor* field, + int index, double value) const; + void SetRepeatedBool(Message* message, const FieldDescriptor* field, + int index, bool value) const; + void SetRepeatedString(Message* message, const FieldDescriptor* field, + int index, std::string value) const; + void SetRepeatedEnum(Message* message, const FieldDescriptor* field, + int index, const EnumValueDescriptor* value) const; // Set an enum field's value with an integer rather than EnumValueDescriptor. - // If the value does not correspond to a known enum value, either behavior is - // undefined (for proto2 messages), or the value is accepted silently for - // messages with new unknown-enum-value semantics. - virtual void SetRepeatedEnumValue(Message* message, - const FieldDescriptor* field, int index, - int value) const = 0; + // For proto3 this is just setting the enum field to the value specified, for + // proto2 it's more complicated. If value is a known enum value the field is + // set as usual. If the value is unknown then it is added to the unknown field + // set. Note this matches the behavior of parsing unknown enum values. + // If multiple calls with unknown values happen than they are all added to the + // unknown field set in order of the calls. + void SetRepeatedEnumValue(Message* message, const FieldDescriptor* field, + int index, int value) const; // Get a mutable pointer to an element of a repeated field with a message // type. - virtual Message* MutableRepeatedMessage( - Message* message, const FieldDescriptor* field, int index) const = 0; + Message* MutableRepeatedMessage(Message* message, + const FieldDescriptor* field, + int index) const; // Repeated field adders ------------------------------------------- // These add an element to a repeated field. - virtual void AddInt32 (Message* message, - const FieldDescriptor* field, int32 value) const = 0; - virtual void AddInt64 (Message* message, - const FieldDescriptor* field, int64 value) const = 0; - virtual void AddUInt32(Message* message, - const FieldDescriptor* field, uint32 value) const = 0; - virtual void AddUInt64(Message* message, - const FieldDescriptor* field, uint64 value) const = 0; - virtual void AddFloat (Message* message, - const FieldDescriptor* field, float value) const = 0; - virtual void AddDouble(Message* message, - const FieldDescriptor* field, double value) const = 0; - virtual void AddBool (Message* message, - const FieldDescriptor* field, bool value) const = 0; - virtual void AddString(Message* message, - const FieldDescriptor* field, - const string& value) const = 0; - virtual void AddEnum (Message* message, - const FieldDescriptor* field, - const EnumValueDescriptor* value) const = 0; - // Set an enum field's value with an integer rather than EnumValueDescriptor. - // If the value does not correspond to a known enum value, either behavior is - // undefined (for proto2 messages), or the value is accepted silently for - // messages with new unknown-enum-value semantics. - virtual void AddEnumValue(Message* message, - const FieldDescriptor* field, - int value) const = 0; + void AddInt32(Message* message, const FieldDescriptor* field, + int32 value) const; + void AddInt64(Message* message, const FieldDescriptor* field, + int64 value) const; + void AddUInt32(Message* message, const FieldDescriptor* field, + uint32 value) const; + void AddUInt64(Message* message, const FieldDescriptor* field, + uint64 value) const; + void AddFloat(Message* message, const FieldDescriptor* field, + float value) const; + void AddDouble(Message* message, const FieldDescriptor* field, + double value) const; + void AddBool(Message* message, const FieldDescriptor* field, + bool value) const; + void AddString(Message* message, const FieldDescriptor* field, + std::string value) const; + void AddEnum(Message* message, const FieldDescriptor* field, + const EnumValueDescriptor* value) const; + // Add an integer value to a repeated enum field rather than + // EnumValueDescriptor. For proto3 this is just setting the enum field to the + // value specified, for proto2 it's more complicated. If value is a known enum + // value the field is set as usual. If the value is unknown then it is added + // to the unknown field set. Note this matches the behavior of parsing unknown + // enum values. If multiple calls with unknown values happen than they are all + // added to the unknown field set in order of the calls. + void AddEnumValue(Message* message, const FieldDescriptor* field, + int value) const; // See MutableMessage() for comments on the "factory" parameter. - virtual Message* AddMessage(Message* message, - const FieldDescriptor* field, - MessageFactory* factory = NULL) const = 0; + Message* AddMessage(Message* message, const FieldDescriptor* field, + MessageFactory* factory = nullptr) const; // Appends an already-allocated object 'new_entry' to the repeated field - // specifyed by 'field' passing ownership to the message. - // TODO(tmarek): Make virtual after all subclasses have been - // updated. - virtual void AddAllocatedMessage(Message* message, - const FieldDescriptor* field, - Message* new_entry) const; + // specified by 'field' passing ownership to the message. + void AddAllocatedMessage(Message* message, const FieldDescriptor* field, + Message* new_entry) const; // Get a RepeatedFieldRef object that can be used to read the underlying @@ -773,7 +739,7 @@ class LIBPROTOBUF_EXPORT Reflection { // CPPTYPE_FLOAT float // CPPTYPE_BOOL bool // CPPTYPE_ENUM generated enum type or int32 - // CPPTYPE_STRING string + // CPPTYPE_STRING std::string // CPPTYPE_MESSAGE generated message type or google::protobuf::Message // // A RepeatedFieldRef object can be copied and the resulted object will point @@ -781,20 +747,19 @@ class LIBPROTOBUF_EXPORT Reflection { // long as the message is not destroyed. // // Note that to use this method users need to include the header file - // "google/protobuf/reflection.h" (which defines the RepeatedFieldRef - // class templates). - template - RepeatedFieldRef GetRepeatedFieldRef( - const Message& message, const FieldDescriptor* field) const; + // "reflection.h" (which defines the RepeatedFieldRef class templates). + template + RepeatedFieldRef GetRepeatedFieldRef(const Message& message, + const FieldDescriptor* field) const; // Like GetRepeatedFieldRef() but return an object that can also be used // manipulate the underlying repeated field. - template + template MutableRepeatedFieldRef GetMutableRepeatedFieldRef( Message* message, const FieldDescriptor* field) const; // DEPRECATED. Please use Get(Mutable)RepeatedFieldRef() for repeated field - // access. The following repeated field accesors will be removed in the + // access. The following repeated field accessors will be removed in the // future. // // Repeated field accessors ------------------------------------------------- @@ -810,44 +775,55 @@ class LIBPROTOBUF_EXPORT Reflection { // DEPRECATED. Please use GetRepeatedFieldRef(). // // for T = Cord and all protobuf scalar types except enums. - template - const RepeatedField& GetRepeatedField( - const Message&, const FieldDescriptor*) const; + template + PROTOBUF_DEPRECATED_MSG("Please use GetRepeatedFieldRef() instead") + const RepeatedField& GetRepeatedField(const Message& msg, + const FieldDescriptor* d) const { + return GetRepeatedFieldInternal(msg, d); + } // DEPRECATED. Please use GetMutableRepeatedFieldRef(). // // for T = Cord and all protobuf scalar types except enums. - template - RepeatedField* MutableRepeatedField( - Message*, const FieldDescriptor*) const; + template + PROTOBUF_DEPRECATED_MSG("Please use GetMutableRepeatedFieldRef() instead") + RepeatedField* MutableRepeatedField(Message* msg, + const FieldDescriptor* d) const { + return MutableRepeatedFieldInternal(msg, d); + } // DEPRECATED. Please use GetRepeatedFieldRef(). // - // for T = string, google::protobuf::internal::StringPieceField + // for T = std::string, google::protobuf::internal::StringPieceField // google::protobuf::Message & descendants. - template + template + PROTOBUF_DEPRECATED_MSG("Please use GetRepeatedFieldRef() instead") const RepeatedPtrField& GetRepeatedPtrField( - const Message&, const FieldDescriptor*) const; + const Message& msg, const FieldDescriptor* d) const { + return GetRepeatedPtrFieldInternal(msg, d); + } // DEPRECATED. Please use GetMutableRepeatedFieldRef(). // - // for T = string, google::protobuf::internal::StringPieceField + // for T = std::string, google::protobuf::internal::StringPieceField // google::protobuf::Message & descendants. - template - RepeatedPtrField* MutableRepeatedPtrField( - Message*, const FieldDescriptor*) const; + template + PROTOBUF_DEPRECATED_MSG("Please use GetMutableRepeatedFieldRef() instead") + RepeatedPtrField* MutableRepeatedPtrField(Message* msg, + const FieldDescriptor* d) const { + return MutableRepeatedPtrFieldInternal(msg, d); + } // Extensions ---------------------------------------------------------------- // Try to find an extension of this message type by fully-qualified field - // name. Returns NULL if no extension is known for this name or number. - virtual const FieldDescriptor* FindKnownExtensionByName( - const string& name) const = 0; + // name. Returns nullptr if no extension is known for this name or number. + const FieldDescriptor* FindKnownExtensionByName( + const std::string& name) const; // Try to find an extension of this message type by field number. - // Returns NULL if no extension is known for this name or number. - virtual const FieldDescriptor* FindKnownExtensionByNumber( - int number) const = 0; + // Returns nullptr if no extension is known for this name or number. + const FieldDescriptor* FindKnownExtensionByNumber(int number) const; // Feature Flags ------------------------------------------------------------- @@ -868,7 +844,7 @@ class LIBPROTOBUF_EXPORT Reflection { // reflection->SetEnumValue(message, field, new_value); // } else { // if (field_descriptor->enum_type()-> - // FindValueByNumber(new_value) != NULL) { + // FindValueByNumber(new_value) != nullptr) { // reflection->SetEnumValue(message, field, new_value); // } else if (emit_unknown_enum_values) { // reflection->MutableUnknownFields(message)->AddVarint( @@ -879,7 +855,7 @@ class LIBPROTOBUF_EXPORT Reflection { // reflection->SetEnumValue(message, field, new_value); // } // } - virtual bool SupportsUnknownEnumValues() const { return false; } + bool SupportsUnknownEnumValues() const; // Returns the MessageFactory associated with this message. This can be // useful for determining if a message is a generated message or not, for @@ -890,136 +866,288 @@ class LIBPROTOBUF_EXPORT Reflection { // } // It can also be used to create more messages of this type, though // Message::New() is an easier way to accomplish this. - virtual MessageFactory* GetMessageFactory() const; - - // --------------------------------------------------------------------------- + MessageFactory* GetMessageFactory() const; - protected: + private: + template + const RepeatedField& GetRepeatedFieldInternal( + const Message& message, const FieldDescriptor* field) const; + template + RepeatedField* MutableRepeatedFieldInternal( + Message* message, const FieldDescriptor* field) const; + template + const RepeatedPtrField& GetRepeatedPtrFieldInternal( + const Message& message, const FieldDescriptor* field) const; + template + RepeatedPtrField* MutableRepeatedPtrFieldInternal( + Message* message, const FieldDescriptor* field) const; // Obtain a pointer to a Repeated Field Structure and do some type checking: // on field->cpp_type(), // on field->field_option().ctype() (if ctype >= 0) - // of field->message_type() (if message_type != NULL). + // of field->message_type() (if message_type != nullptr). // We use 2 routine rather than 4 (const vs mutable) x (scalar vs pointer). - virtual void* MutableRawRepeatedField( - Message* message, const FieldDescriptor* field, FieldDescriptor::CppType, - int ctype, const Descriptor* message_type) const = 0; - - // TODO(jieluo) - make it pure virtual after updating all the subclasses. - virtual const void* GetRawRepeatedField( - const Message& message, const FieldDescriptor* field, - FieldDescriptor::CppType cpptype, int ctype, - const Descriptor* message_type) const { - return MutableRawRepeatedField( - const_cast(&message), field, cpptype, ctype, message_type); - } + void* MutableRawRepeatedField(Message* message, const FieldDescriptor* field, + FieldDescriptor::CppType, int ctype, + const Descriptor* message_type) const; + + const void* GetRawRepeatedField(const Message& message, + const FieldDescriptor* field, + FieldDescriptor::CppType cpptype, int ctype, + const Descriptor* message_type) const; // The following methods are used to implement (Mutable)RepeatedFieldRef. // A Ref object will store a raw pointer to the repeated field data (obtained // from RepeatedFieldData()) and a pointer to a Accessor (obtained from // RepeatedFieldAccessor) which will be used to access the raw data. - // - // TODO(xiaofeng): Make these methods pure-virtual. // Returns a raw pointer to the repeated field // - // "cpp_type" and "message_type" are decuded from the type parameter T passed + // "cpp_type" and "message_type" are deduced from the type parameter T passed // to Get(Mutable)RepeatedFieldRef. If T is a generated message type, // "message_type" should be set to its descriptor. Otherwise "message_type" - // should be set to NULL. Implementations of this method should check whether - // "cpp_type"/"message_type" is consistent with the actual type of the field. - // We use 1 routine rather than 2 (const vs mutable) because it is protected - // and it doesn't change the message. - virtual void* RepeatedFieldData( - Message* message, const FieldDescriptor* field, - FieldDescriptor::CppType cpp_type, - const Descriptor* message_type) const; + // should be set to nullptr. Implementations of this method should check + // whether "cpp_type"/"message_type" is consistent with the actual type of the + // field. We use 1 routine rather than 2 (const vs mutable) because it is + // protected and it doesn't change the message. + void* RepeatedFieldData(Message* message, const FieldDescriptor* field, + FieldDescriptor::CppType cpp_type, + const Descriptor* message_type) const; // The returned pointer should point to a singleton instance which implements // the RepeatedFieldAccessor interface. - virtual const internal::RepeatedFieldAccessor* RepeatedFieldAccessor( + const internal::RepeatedFieldAccessor* RepeatedFieldAccessor( const FieldDescriptor* field) const; - private: - template + // Lists all fields of the message which are currently set, except for unknown + // fields and stripped fields. See ListFields for details. + void ListFieldsOmitStripped( + const Message& message, + std::vector* output) const; + + bool IsMessageStripped(const Descriptor* descriptor) const { + return schema_.IsMessageStripped(descriptor); + } + + friend class TextFormat; + + void ListFieldsMayFailOnStripped( + const Message& message, bool should_fail, + std::vector* output) const; + + const Descriptor* const descriptor_; + const internal::ReflectionSchema schema_; + const DescriptorPool* const descriptor_pool_; + MessageFactory* const message_factory_; + + // Last non weak field index. This is an optimization when most weak fields + // are at the end of the containing message. If a message proto doesn't + // contain weak fields, then this field equals descriptor_->field_count(). + int last_non_weak_field_index_; + + template friend class RepeatedFieldRef; - template + template friend class MutableRepeatedFieldRef; - friend class ::google::protobuf::python::MapReflectionFriend; + friend class ::PROTOBUF_NAMESPACE_ID::MessageLayoutInspector; + friend class ::PROTOBUF_NAMESPACE_ID::AssignDescriptorsHelper; + friend class DynamicMessageFactory; + friend class python::MapReflectionFriend; + friend class util::MessageDifferencer; +#define GOOGLE_PROTOBUF_HAS_CEL_MAP_REFLECTION_FRIEND + friend class expr::CelMapReflectionFriend; friend class internal::MapFieldReflectionTest; friend class internal::MapKeySorter; friend class internal::WireFormat; friend class internal::ReflectionOps; + // Needed for implementing text format for map. + friend class internal::MapFieldPrinterHelper; + + Reflection(const Descriptor* descriptor, + const internal::ReflectionSchema& schema, + const DescriptorPool* pool, MessageFactory* factory); - // Special version for specialized implementations of string. We can't call - // MutableRawRepeatedField directly here because we don't have access to + // Special version for specialized implementations of string. We can't + // call MutableRawRepeatedField directly here because we don't have access to // FieldOptions::* which are defined in descriptor.pb.h. Including that // file here is not possible because it would cause a circular include cycle. // We use 1 routine rather than 2 (const vs mutable) because it is private // and mutable a repeated string field doesn't change the message. - void* MutableRawRepeatedString( - Message* message, const FieldDescriptor* field, bool is_string) const; + void* MutableRawRepeatedString(Message* message, const FieldDescriptor* field, + bool is_string) const; friend class MapReflectionTester; - // TODO(jieluo) - make the map APIs pure virtual after updating - // all the subclasses. // Returns true if key is in map. Returns false if key is not in map field. - virtual bool ContainsMapKey(const Message& /* message */, - const FieldDescriptor* /* field */, - const MapKey& /* key */) const { - return false; - } + bool ContainsMapKey(const Message& message, const FieldDescriptor* field, + const MapKey& key) const; // If key is in map field: Saves the value pointer to val and returns // false. If key in not in map field: Insert the key into map, saves - // value pointer to val and retuns true. - virtual bool InsertOrLookupMapValue(Message* /* message */, - const FieldDescriptor* /* field */, - const MapKey& /* key */, - MapValueRef* /* val */) const { - return false; - } + // value pointer to val and returns true. Users are able to modify the + // map value by MapValueRef. + bool InsertOrLookupMapValue(Message* message, const FieldDescriptor* field, + const MapKey& key, MapValueRef* val) const; + + // If key is in map field: Saves the value pointer to val and returns true. + // Returns false if key is not in map field. Users are NOT able to modify + // the value by MapValueConstRef. + bool LookupMapValue(const Message& message, const FieldDescriptor* field, + const MapKey& key, MapValueConstRef* val) const; + bool LookupMapValue(const Message&, const FieldDescriptor*, const MapKey&, + MapValueRef*) const = delete; // Delete and returns true if key is in the map field. Returns false // otherwise. - virtual bool DeleteMapValue(Message* /* message */, - const FieldDescriptor* /* field */, - const MapKey& /* key */) const { - return false; - } + bool DeleteMapValue(Message* message, const FieldDescriptor* field, + const MapKey& key) const; // Returns a MapIterator referring to the first element in the map field. // If the map field is empty, this function returns the same as // reflection::MapEnd. Mutation to the field may invalidate the iterator. - virtual MapIterator MapBegin( - Message* message, - const FieldDescriptor* field) const; + MapIterator MapBegin(Message* message, const FieldDescriptor* field) const; // Returns a MapIterator referring to the theoretical element that would // follow the last element in the map field. It does not point to any // real element. Mutation to the field may invalidate the iterator. - virtual MapIterator MapEnd( - Message* message, - const FieldDescriptor* field) const; + MapIterator MapEnd(Message* message, const FieldDescriptor* field) const; // Get the number of pair of a map field. The result may be // different from FieldSize which can have duplicate keys. - virtual int MapSize(const Message& /* message */, - const FieldDescriptor* /* field */) const { - return 0; - } + int MapSize(const Message& message, const FieldDescriptor* field) const; // Help method for MapIterator. friend class MapIterator; - virtual internal::MapFieldBase* MapData( - Message* /* message */, const FieldDescriptor* /* field */) const { - return NULL; + friend class WireFormatForMapFieldTest; + internal::MapFieldBase* MutableMapData(Message* message, + const FieldDescriptor* field) const; + + const internal::MapFieldBase* GetMapData(const Message& message, + const FieldDescriptor* field) const; + + template + const T& GetRawNonOneof(const Message& message, + const FieldDescriptor* field) const; + template + T* MutableRawNonOneof(Message* message, const FieldDescriptor* field) const; + + template + const Type& GetRaw(const Message& message, + const FieldDescriptor* field) const; + template + inline Type* MutableRaw(Message* message, const FieldDescriptor* field) const; + template + const Type& DefaultRaw(const FieldDescriptor* field) const; + + const Message* GetDefaultMessageInstance(const FieldDescriptor* field) const; + + inline const uint32* GetHasBits(const Message& message) const; + inline uint32* MutableHasBits(Message* message) const; + inline uint32 GetOneofCase(const Message& message, + const OneofDescriptor* oneof_descriptor) const; + inline uint32* MutableOneofCase( + Message* message, const OneofDescriptor* oneof_descriptor) const; + inline bool HasExtensionSet(const Message& /* message */) const { + return schema_.HasExtensionSet(); } + const internal::ExtensionSet& GetExtensionSet(const Message& message) const; + internal::ExtensionSet* MutableExtensionSet(Message* message) const; + inline Arena* GetArena(Message* message) const; + + inline const internal::InternalMetadata& GetInternalMetadata( + const Message& message) const; + + internal::InternalMetadata* MutableInternalMetadata(Message* message) const; + + inline bool HasBit(const Message& message, + const FieldDescriptor* field) const; + inline void SetBit(Message* message, const FieldDescriptor* field) const; + inline void ClearBit(Message* message, const FieldDescriptor* field) const; + inline void SwapBit(Message* message1, Message* message2, + const FieldDescriptor* field) const; + + // This function only swaps the field. Should swap corresponding has_bit + // before or after using this function. + void SwapField(Message* message1, Message* message2, + const FieldDescriptor* field) const; + + void SwapOneofField(Message* message1, Message* message2, + const OneofDescriptor* oneof_descriptor) const; + + inline bool HasOneofField(const Message& message, + const FieldDescriptor* field) const; + inline void SetOneofCase(Message* message, + const FieldDescriptor* field) const; + inline void ClearOneofField(Message* message, + const FieldDescriptor* field) const; + + template + inline const Type& GetField(const Message& message, + const FieldDescriptor* field) const; + template + inline void SetField(Message* message, const FieldDescriptor* field, + const Type& value) const; + template + inline Type* MutableField(Message* message, + const FieldDescriptor* field) const; + template + inline const Type& GetRepeatedField(const Message& message, + const FieldDescriptor* field, + int index) const; + template + inline const Type& GetRepeatedPtrField(const Message& message, + const FieldDescriptor* field, + int index) const; + template + inline void SetRepeatedField(Message* message, const FieldDescriptor* field, + int index, Type value) const; + template + inline Type* MutableRepeatedField(Message* message, + const FieldDescriptor* field, + int index) const; + template + inline void AddField(Message* message, const FieldDescriptor* field, + const Type& value) const; + template + inline Type* AddField(Message* message, const FieldDescriptor* field) const; + + int GetExtensionNumberOrDie(const Descriptor* type) const; + + // Internal versions of EnumValue API perform no checking. Called after checks + // by public methods. + void SetEnumValueInternal(Message* message, const FieldDescriptor* field, + int value) const; + void SetRepeatedEnumValueInternal(Message* message, + const FieldDescriptor* field, int index, + int value) const; + void AddEnumValueInternal(Message* message, const FieldDescriptor* field, + int value) const; + + Message* UnsafeArenaReleaseMessage(Message* message, + const FieldDescriptor* field, + MessageFactory* factory = nullptr) const; + + void UnsafeArenaSetAllocatedMessage(Message* message, Message* sub_message, + const FieldDescriptor* field) const; + + friend inline // inline so nobody can call this function. + void + RegisterAllTypesInternal(const Metadata* file_level_metadata, int size); + friend inline const char* ParseLenDelim(int field_number, + const FieldDescriptor* field, + Message* msg, + const Reflection* reflection, + const char* ptr, + internal::ParseContext* ctx); + friend inline const char* ParsePackedField(const FieldDescriptor* field, + Message* msg, + const Reflection* reflection, + const char* ptr, + internal::ParseContext* ctx); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection); }; // Abstract interface for a factory for message objects. -class LIBPROTOBUF_EXPORT MessageFactory { +class PROTOBUF_EXPORT MessageFactory { public: inline MessageFactory() {} virtual ~MessageFactory(); @@ -1038,7 +1166,7 @@ class LIBPROTOBUF_EXPORT MessageFactory { // outlive the MessageFactory. // // Some implementations do not support all types. GetPrototype() will - // return NULL if the descriptor passed in is not supported. + // return nullptr if the descriptor passed in is not supported. // // This method may or may not be thread-safe depending on the implementation. // Each implementation should document its own degree thread-safety. @@ -1050,7 +1178,7 @@ class LIBPROTOBUF_EXPORT MessageFactory { // FooMessage::descriptor()) == FooMessage::default_instance() // This factory supports all types which are found in // DescriptorPool::generated_pool(). If given a descriptor from any other - // pool, GetPrototype() will return NULL. (You can also check if a + // pool, GetPrototype() will return nullptr. (You can also check if a // descriptor is for a generated message by checking if // descriptor->file()->pool() == DescriptorPool::generated_pool().) // @@ -1069,7 +1197,7 @@ class LIBPROTOBUF_EXPORT MessageFactory { // built lazily, so we can't register types by their descriptor until we // know that the descriptor exists. |filename| must be a permanent string. static void InternalRegisterGeneratedFile( - const char* filename, void (*register_messages)(const string&)); + const google::protobuf::internal::DescriptorTable* table); // For internal use only: Registers a message type. Called only by the // functions which are registered with InternalRegisterGeneratedFile(), @@ -1082,16 +1210,16 @@ class LIBPROTOBUF_EXPORT MessageFactory { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFactory); }; -#define DECLARE_GET_REPEATED_FIELD(TYPE) \ -template<> \ -LIBPROTOBUF_EXPORT \ -const RepeatedField& Reflection::GetRepeatedField( \ - const Message& message, const FieldDescriptor* field) const; \ - \ -template<> \ -LIBPROTOBUF_EXPORT \ -RepeatedField* Reflection::MutableRepeatedField( \ - Message* message, const FieldDescriptor* field) const; +#define DECLARE_GET_REPEATED_FIELD(TYPE) \ + template <> \ + PROTOBUF_EXPORT const RepeatedField& \ + Reflection::GetRepeatedFieldInternal( \ + const Message& message, const FieldDescriptor* field) const; \ + \ + template <> \ + PROTOBUF_EXPORT RepeatedField* \ + Reflection::MutableRepeatedFieldInternal( \ + Message * message, const FieldDescriptor* field) const; DECLARE_GET_REPEATED_FIELD(int32) DECLARE_GET_REPEATED_FIELD(int64) @@ -1103,64 +1231,127 @@ DECLARE_GET_REPEATED_FIELD(bool) #undef DECLARE_GET_REPEATED_FIELD +// Tries to downcast this message to a generated message type. Returns nullptr +// if this class is not an instance of T. This works even if RTTI is disabled. +// +// This also has the effect of creating a strong reference to T that will +// prevent the linker from stripping it out at link time. This can be important +// if you are using a DynamicMessageFactory that delegates to the generated +// factory. +template +const T* DynamicCastToGenerated(const Message* from) { + // Compile-time assert that T is a generated type that has a + // default_instance() accessor, but avoid actually calling it. + const T& (*get_default_instance)() = &T::default_instance; + (void)get_default_instance; + + // Compile-time assert that T is a subclass of google::protobuf::Message. + const Message* unused = static_cast(nullptr); + (void)unused; + +#if PROTOBUF_RTTI + return dynamic_cast(from); +#else + bool ok = from != nullptr && + T::default_instance().GetReflection() == from->GetReflection(); + return ok ? down_cast(from) : nullptr; +#endif +} + +template +T* DynamicCastToGenerated(Message* from) { + const Message* message_const = from; + return const_cast(DynamicCastToGenerated(message_const)); +} + +// Call this function to ensure that this message's reflection is linked into +// the binary: +// +// google::protobuf::LinkMessageReflection(); +// +// This will ensure that the following lookup will succeed: +// +// DescriptorPool::generated_pool()->FindMessageTypeByName("FooMessage"); +// +// As a side-effect, it will also guarantee that anything else from the same +// .proto file will also be available for lookup in the generated pool. +// +// This function does not actually register the message, so it does not need +// to be called before the lookup. However it does need to occur in a function +// that cannot be stripped from the binary (ie. it must be reachable from main). +// +// Best practice is to call this function as close as possible to where the +// reflection is actually needed. This function is very cheap to call, so you +// should not need to worry about its runtime overhead except in the tightest +// of loops (on x86-64 it compiles into two "mov" instructions). +template +void LinkMessageReflection() { + internal::StrongReference(T::default_instance); +} + // ============================================================================= // Implementation details for {Get,Mutable}RawRepeatedPtrField. We provide -// specializations for , and and handle -// everything else with the default template which will match any type having -// a method with signature "static const google::protobuf::Descriptor* descriptor()". -// Such a type presumably is a descendant of google::protobuf::Message. - -template<> -inline const RepeatedPtrField& Reflection::GetRepeatedPtrField( +// specializations for , and and +// handle everything else with the default template which will match any type +// having a method with signature "static const google::protobuf::Descriptor* +// descriptor()". Such a type presumably is a descendant of google::protobuf::Message. + +template <> +inline const RepeatedPtrField& +Reflection::GetRepeatedPtrFieldInternal( const Message& message, const FieldDescriptor* field) const { - return *static_cast* >( + return *static_cast*>( MutableRawRepeatedString(const_cast(&message), field, true)); } -template<> -inline RepeatedPtrField* Reflection::MutableRepeatedPtrField( +template <> +inline RepeatedPtrField* +Reflection::MutableRepeatedPtrFieldInternal( Message* message, const FieldDescriptor* field) const { - return static_cast* >( + return static_cast*>( MutableRawRepeatedString(message, field, true)); } // ----- -template<> -inline const RepeatedPtrField& Reflection::GetRepeatedPtrField( +template <> +inline const RepeatedPtrField& Reflection::GetRepeatedPtrFieldInternal( const Message& message, const FieldDescriptor* field) const { - return *static_cast* >( - GetRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_MESSAGE, - -1, NULL)); + return *static_cast*>(GetRawRepeatedField( + message, field, FieldDescriptor::CPPTYPE_MESSAGE, -1, nullptr)); } -template<> -inline RepeatedPtrField* Reflection::MutableRepeatedPtrField( +template <> +inline RepeatedPtrField* Reflection::MutableRepeatedPtrFieldInternal( Message* message, const FieldDescriptor* field) const { - return static_cast* >( - MutableRawRepeatedField(message, field, - FieldDescriptor::CPPTYPE_MESSAGE, -1, - NULL)); + return static_cast*>(MutableRawRepeatedField( + message, field, FieldDescriptor::CPPTYPE_MESSAGE, -1, nullptr)); } -template -inline const RepeatedPtrField& Reflection::GetRepeatedPtrField( +template +inline const RepeatedPtrField& Reflection::GetRepeatedPtrFieldInternal( const Message& message, const FieldDescriptor* field) const { - return *static_cast* >( - GetRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_MESSAGE, - -1, PB::default_instance().GetDescriptor())); + return *static_cast*>( + GetRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_MESSAGE, -1, + PB::default_instance().GetDescriptor())); } -template -inline RepeatedPtrField* Reflection::MutableRepeatedPtrField( +template +inline RepeatedPtrField* Reflection::MutableRepeatedPtrFieldInternal( Message* message, const FieldDescriptor* field) const { - return static_cast* >( - MutableRawRepeatedField(message, field, - FieldDescriptor::CPPTYPE_MESSAGE, -1, - PB::default_instance().GetDescriptor())); + return static_cast*>( + MutableRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_MESSAGE, + -1, PB::default_instance().GetDescriptor())); } -} // namespace protobuf +template +const Type& Reflection::DefaultRaw(const FieldDescriptor* field) const { + return *reinterpret_cast(schema_.GetFieldDefault(field)); +} +} // namespace protobuf } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_MESSAGE_H__ diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index 83a92d5a082c4..f137675beb173 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -33,26 +33,42 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include - -#include -#include #include -#include + +#include +#include #include + #include #include +#include +#include #include +#include +#include #include +#include +#include +#include +#include +#include #include +#include + +#include namespace google { namespace protobuf { -string MessageLite::InitializationErrorString() const { +std::string MessageLite::InitializationErrorString() const { return "(cannot determine missing fields for lite message)"; } +std::string MessageLite::DebugString() const { + std::uintptr_t address = reinterpret_cast(this); + return StrCat("MessageLite at 0x", strings::Hex(address)); +} + namespace { // When serializing, we first compute the byte size, then serialize the message. @@ -71,12 +87,13 @@ void ByteSizeConsistencyError(size_t byte_size_before_serialization, GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization) << "Byte size calculation and serialization were inconsistent. This " "may indicate a bug in protocol buffers or it may be caused by " - "concurrent modification of " << message.GetTypeName() << "."; + "concurrent modification of " + << message.GetTypeName() << "."; GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal."; } -string InitializationErrorMessage(const char* action, - const MessageLite& message) { +std::string InitializationErrorMessage(const char* action, + const MessageLite& message) { // Note: We want to avoid depending on strutil in the lite library, otherwise // we'd use: // @@ -86,7 +103,7 @@ string InitializationErrorMessage(const char* action, // action, message.GetTypeName(), // message.InitializationErrorString()); - string result; + std::string result; result += "Can't "; result += action; result += " message of type \""; @@ -96,64 +113,89 @@ string InitializationErrorMessage(const char* action, return result; } -// Several of the Parse methods below just do one thing and then call another -// method. In a naive implementation, we might have ParseFromString() call -// ParseFromArray() which would call ParseFromZeroCopyStream() which would call -// ParseFromCodedStream() which would call MergeFromCodedStream() which would -// call MergePartialFromCodedStream(). However, when parsing very small -// messages, every function call introduces significant overhead. To avoid -// this without reproducing code, we use these forced-inline helpers. -GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineMergeFromCodedStream( - io::CodedInputStream* input, MessageLite* message); -GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromCodedStream( - io::CodedInputStream* input, MessageLite* message); -GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromCodedStream( - io::CodedInputStream* input, MessageLite* message); -GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromArray( - const void* data, int size, MessageLite* message); -GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromArray( - const void* data, int size, MessageLite* message); - -inline bool InlineMergeFromCodedStream(io::CodedInputStream* input, - MessageLite* message) { - if (!message->MergePartialFromCodedStream(input)) return false; - if (!message->IsInitialized()) { - GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message); - return false; - } - return true; +inline StringPiece as_string_view(const void* data, int size) { + return StringPiece(static_cast(data), size); } -inline bool InlineParseFromCodedStream(io::CodedInputStream* input, - MessageLite* message) { - message->Clear(); - return InlineMergeFromCodedStream(input, message); +// Returns true of all required fields are present / have values. +inline bool CheckFieldPresence(const internal::ParseContext& ctx, + const MessageLite& msg, + MessageLite::ParseFlags parse_flags) { + if (PROTOBUF_PREDICT_FALSE((parse_flags & MessageLite::kMergePartial) != 0)) { + return true; + } + return msg.IsInitializedWithErrors(); } -inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input, - MessageLite* message) { - message->Clear(); - return message->MergePartialFromCodedStream(input); -} +} // namespace -inline bool InlineParseFromArray( - const void* data, int size, MessageLite* message) { - io::CodedInputStream input(reinterpret_cast(data), size); - return InlineParseFromCodedStream(&input, message) && - input.ConsumedEntireMessage(); +void MessageLite::LogInitializationErrorMessage() const { + GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *this); } -inline bool InlineParsePartialFromArray( - const void* data, int size, MessageLite* message) { - io::CodedInputStream input(reinterpret_cast(data), size); - return InlineParsePartialFromCodedStream(&input, message) && - input.ConsumedEntireMessage(); -} +namespace internal { -} // namespace +template +bool MergeFromImpl(StringPiece input, MessageLite* msg, + MessageLite::ParseFlags parse_flags) { + const char* ptr; + internal::ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(), + aliasing, &ptr, input); + ptr = msg->_InternalParse(ptr, &ctx); + // ctx has an explicit limit set (length of string_view). + if (PROTOBUF_PREDICT_TRUE(ptr && ctx.EndedAtLimit())) { + return CheckFieldPresence(ctx, *msg, parse_flags); + } + return false; +} + +template +bool MergeFromImpl(io::ZeroCopyInputStream* input, MessageLite* msg, + MessageLite::ParseFlags parse_flags) { + const char* ptr; + internal::ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(), + aliasing, &ptr, input); + ptr = msg->_InternalParse(ptr, &ctx); + // ctx has no explicit limit (hence we end on end of stream) + if (PROTOBUF_PREDICT_TRUE(ptr && ctx.EndedAtEndOfStream())) { + return CheckFieldPresence(ctx, *msg, parse_flags); + } + return false; +} + +template +bool MergeFromImpl(BoundedZCIS input, MessageLite* msg, + MessageLite::ParseFlags parse_flags) { + const char* ptr; + internal::ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(), + aliasing, &ptr, input.zcis, input.limit); + ptr = msg->_InternalParse(ptr, &ctx); + if (PROTOBUF_PREDICT_FALSE(!ptr)) return false; + ctx.BackUp(ptr); + if (PROTOBUF_PREDICT_TRUE(ctx.EndedAtLimit())) { + return CheckFieldPresence(ctx, *msg, parse_flags); + } + return false; +} + +template bool MergeFromImpl(StringPiece input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +template bool MergeFromImpl(StringPiece input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +template bool MergeFromImpl(io::ZeroCopyInputStream* input, + MessageLite* msg, + MessageLite::ParseFlags parse_flags); +template bool MergeFromImpl(io::ZeroCopyInputStream* input, + MessageLite* msg, + MessageLite::ParseFlags parse_flags); +template bool MergeFromImpl(BoundedZCIS input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +template bool MergeFromImpl(BoundedZCIS input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +} // namespace internal -MessageLite* MessageLite::New(::google::protobuf::Arena* arena) const { +MessageLite* MessageLite::New(Arena* arena) const { MessageLite* message = New(); if (arena != NULL) { arena->Own(message); @@ -161,70 +203,169 @@ MessageLite* MessageLite::New(::google::protobuf::Arena* arena) const { return message; } +class ZeroCopyCodedInputStream : public io::ZeroCopyInputStream { + public: + ZeroCopyCodedInputStream(io::CodedInputStream* cis) : cis_(cis) {} + bool Next(const void** data, int* size) final { + if (!cis_->GetDirectBufferPointer(data, size)) return false; + cis_->Skip(*size); + return true; + } + void BackUp(int count) final { cis_->Advance(-count); } + bool Skip(int count) final { return cis_->Skip(count); } + int64_t ByteCount() const final { return 0; } + + bool aliasing_enabled() { return cis_->aliasing_enabled_; } + + private: + io::CodedInputStream* cis_; +}; + +bool MessageLite::MergeFromImpl(io::CodedInputStream* input, + MessageLite::ParseFlags parse_flags) { + ZeroCopyCodedInputStream zcis(input); + const char* ptr; + internal::ParseContext ctx(input->RecursionBudget(), zcis.aliasing_enabled(), + &ptr, &zcis); + // MergePartialFromCodedStream allows terminating the wireformat by 0 or + // end-group tag. Leaving it up to the caller to verify correct ending by + // calling LastTagWas on input. We need to maintain this behavior. + ctx.TrackCorrectEnding(); + ctx.data().pool = input->GetExtensionPool(); + ctx.data().factory = input->GetExtensionFactory(); + ptr = _InternalParse(ptr, &ctx); + if (PROTOBUF_PREDICT_FALSE(!ptr)) return false; + ctx.BackUp(ptr); + if (!ctx.EndedAtEndOfStream()) { + GOOGLE_DCHECK(ctx.LastTag() != 1); // We can't end on a pushed limit. + if (ctx.IsExceedingLimit(ptr)) return false; + input->SetLastTag(ctx.LastTag()); + } else { + input->SetConsumed(); + } + return CheckFieldPresence(ctx, *this, parse_flags); +} + +bool MessageLite::MergePartialFromCodedStream(io::CodedInputStream* input) { + return MergeFromImpl(input, kMergePartial); +} + bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) { - return InlineMergeFromCodedStream(input, this); + return MergeFromImpl(input, kMerge); } bool MessageLite::ParseFromCodedStream(io::CodedInputStream* input) { - return InlineParseFromCodedStream(input, this); + Clear(); + return MergeFromImpl(input, kParse); } bool MessageLite::ParsePartialFromCodedStream(io::CodedInputStream* input) { - return InlineParsePartialFromCodedStream(input, this); + Clear(); + return MergeFromImpl(input, kParsePartial); } bool MessageLite::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) { - io::CodedInputStream decoder(input); - return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage(); + return ParseFrom(input); } bool MessageLite::ParsePartialFromZeroCopyStream( io::ZeroCopyInputStream* input) { - io::CodedInputStream decoder(input); - return ParsePartialFromCodedStream(&decoder) && - decoder.ConsumedEntireMessage(); + return ParseFrom(input); +} + +bool MessageLite::ParseFromFileDescriptor(int file_descriptor) { + io::FileInputStream input(file_descriptor); + return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0; } -bool MessageLite::ParseFromBoundedZeroCopyStream( +bool MessageLite::ParsePartialFromFileDescriptor(int file_descriptor) { + io::FileInputStream input(file_descriptor); + return ParsePartialFromZeroCopyStream(&input) && input.GetErrno() == 0; +} + +bool MessageLite::ParseFromIstream(std::istream* input) { + io::IstreamInputStream zero_copy_input(input); + return ParseFromZeroCopyStream(&zero_copy_input) && input->eof(); +} + +bool MessageLite::ParsePartialFromIstream(std::istream* input) { + io::IstreamInputStream zero_copy_input(input); + return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof(); +} + +bool MessageLite::MergePartialFromBoundedZeroCopyStream( io::ZeroCopyInputStream* input, int size) { - io::CodedInputStream decoder(input); - decoder.PushLimit(size); - return ParseFromCodedStream(&decoder) && - decoder.ConsumedEntireMessage() && - decoder.BytesUntilLimit() == 0; + return ParseFrom(internal::BoundedZCIS{input, size}); +} + +bool MessageLite::MergeFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, + int size) { + return ParseFrom(internal::BoundedZCIS{input, size}); +} + +bool MessageLite::ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, + int size) { + return ParseFrom(internal::BoundedZCIS{input, size}); } bool MessageLite::ParsePartialFromBoundedZeroCopyStream( io::ZeroCopyInputStream* input, int size) { - io::CodedInputStream decoder(input); - decoder.PushLimit(size); - return ParsePartialFromCodedStream(&decoder) && - decoder.ConsumedEntireMessage() && - decoder.BytesUntilLimit() == 0; + return ParseFrom(internal::BoundedZCIS{input, size}); } -bool MessageLite::ParseFromString(const string& data) { - return InlineParseFromArray(data.data(), data.size(), this); +bool MessageLite::ParseFromString(ConstStringParam data) { + return ParseFrom(data); } -bool MessageLite::ParsePartialFromString(const string& data) { - return InlineParsePartialFromArray(data.data(), data.size(), this); +bool MessageLite::ParsePartialFromString(ConstStringParam data) { + return ParseFrom(data); } bool MessageLite::ParseFromArray(const void* data, int size) { - return InlineParseFromArray(data, size, this); + return ParseFrom(as_string_view(data, size)); } bool MessageLite::ParsePartialFromArray(const void* data, int size) { - return InlineParsePartialFromArray(data, size, this); + return ParseFrom(as_string_view(data, size)); +} + +bool MessageLite::MergeFromString(ConstStringParam data) { + return ParseFrom(data); } // =================================================================== +inline uint8* SerializeToArrayImpl(const MessageLite& msg, uint8* target, + int size) { + constexpr bool debug = false; + if (debug) { + // Force serialization to a stream with a block size of 1, which forces + // all writes to the stream to cross buffers triggering all fallback paths + // in the unittests when serializing to string / array. + io::ArrayOutputStream stream(target, size, 1); + uint8* ptr; + io::EpsCopyOutputStream out( + &stream, io::CodedOutputStream::IsDefaultSerializationDeterministic(), + &ptr); + ptr = msg._InternalSerialize(ptr, &out); + out.Trim(ptr); + GOOGLE_DCHECK(!out.HadError() && stream.ByteCount() == size); + return target + size; + } else { + io::EpsCopyOutputStream out( + target, size, + io::CodedOutputStream::IsDefaultSerializationDeterministic()); + auto res = msg._InternalSerialize(target, &out); + GOOGLE_DCHECK(target + size == res); + return res; + } +} + uint8* MessageLite::SerializeWithCachedSizesToArray(uint8* target) const { - return InternalSerializeWithCachedSizesToArray( - io::CodedOutputStream::IsDefaultSerializationDeterministic(), target); + // We only optimize this when using optimize_for = SPEED. In other cases + // we just use the CodedOutputStream path. + return SerializeToArrayImpl(*this, target, GetCachedSize()); } bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const { @@ -236,76 +377,101 @@ bool MessageLite::SerializePartialToCodedStream( io::CodedOutputStream* output) const { const size_t size = ByteSizeLong(); // Force size to be cached. if (size > INT_MAX) { - GOOGLE_LOG(ERROR) << "Exceeded maximum protobuf size of 2GB: " << size; + GOOGLE_LOG(ERROR) << GetTypeName() + << " exceeded maximum protobuf size of 2GB: " << size; return false; } - uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size); - if (buffer != NULL) { - uint8* end = InternalSerializeWithCachedSizesToArray( - output->IsSerializationDeterministic(), buffer); - if (end - buffer != size) { - ByteSizeConsistencyError(size, ByteSizeLong(), end - buffer, *this); - } - return true; - } else { - int original_byte_count = output->ByteCount(); - SerializeWithCachedSizes(output); - if (output->HadError()) { - return false; - } - int final_byte_count = output->ByteCount(); - - if (final_byte_count - original_byte_count != size) { - ByteSizeConsistencyError(size, ByteSizeLong(), - final_byte_count - original_byte_count, *this); - } + int original_byte_count = output->ByteCount(); + SerializeWithCachedSizes(output); + if (output->HadError()) { + return false; + } + int final_byte_count = output->ByteCount(); - return true; + if (final_byte_count - original_byte_count != static_cast(size)) { + ByteSizeConsistencyError(size, ByteSizeLong(), + final_byte_count - original_byte_count, *this); } + + return true; } bool MessageLite::SerializeToZeroCopyStream( io::ZeroCopyOutputStream* output) const { - io::CodedOutputStream encoder(output); - return SerializeToCodedStream(&encoder); + GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); + return SerializePartialToZeroCopyStream(output); } bool MessageLite::SerializePartialToZeroCopyStream( io::ZeroCopyOutputStream* output) const { - io::CodedOutputStream encoder(output); - return SerializePartialToCodedStream(&encoder); + const size_t size = ByteSizeLong(); // Force size to be cached. + if (size > INT_MAX) { + GOOGLE_LOG(ERROR) << GetTypeName() + << " exceeded maximum protobuf size of 2GB: " << size; + return false; + } + + uint8* target; + io::EpsCopyOutputStream stream( + output, io::CodedOutputStream::IsDefaultSerializationDeterministic(), + &target); + target = _InternalSerialize(target, &stream); + stream.Trim(target); + if (stream.HadError()) return false; + return true; +} + +bool MessageLite::SerializeToFileDescriptor(int file_descriptor) const { + io::FileOutputStream output(file_descriptor); + return SerializeToZeroCopyStream(&output) && output.Flush(); +} + +bool MessageLite::SerializePartialToFileDescriptor(int file_descriptor) const { + io::FileOutputStream output(file_descriptor); + return SerializePartialToZeroCopyStream(&output) && output.Flush(); +} + +bool MessageLite::SerializeToOstream(std::ostream* output) const { + { + io::OstreamOutputStream zero_copy_output(output); + if (!SerializeToZeroCopyStream(&zero_copy_output)) return false; + } + return output->good(); } -bool MessageLite::AppendToString(string* output) const { +bool MessageLite::SerializePartialToOstream(std::ostream* output) const { + io::OstreamOutputStream zero_copy_output(output); + return SerializePartialToZeroCopyStream(&zero_copy_output); +} + +bool MessageLite::AppendToString(std::string* output) const { GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); return AppendPartialToString(output); } -bool MessageLite::AppendPartialToString(string* output) const { +bool MessageLite::AppendPartialToString(std::string* output) const { size_t old_size = output->size(); size_t byte_size = ByteSizeLong(); if (byte_size > INT_MAX) { - GOOGLE_LOG(ERROR) << "Exceeded maximum protobuf size of 2GB: " << byte_size; + GOOGLE_LOG(ERROR) << GetTypeName() + << " exceeded maximum protobuf size of 2GB: " << byte_size; return false; } STLStringResizeUninitialized(output, old_size + byte_size); uint8* start = reinterpret_cast(io::mutable_string_data(output) + old_size); - uint8* end = SerializeWithCachedSizesToArray(start); - if (end - start != byte_size) { - ByteSizeConsistencyError(byte_size, ByteSizeLong(), end - start, *this); - } + SerializeToArrayImpl(*this, start, byte_size); return true; } -bool MessageLite::SerializeToString(string* output) const { +bool MessageLite::SerializeToString(std::string* output) const { output->clear(); return AppendToString(output); } -bool MessageLite::SerializePartialToString(string* output) const { +bool MessageLite::SerializePartialToString(std::string* output) const { output->clear(); return AppendPartialToString(output); } @@ -316,68 +482,40 @@ bool MessageLite::SerializeToArray(void* data, int size) const { } bool MessageLite::SerializePartialToArray(void* data, int size) const { - int byte_size = ByteSizeLong(); - if (size < byte_size) return false; - uint8* start = reinterpret_cast(data); - uint8* end = SerializeWithCachedSizesToArray(start); - if (end - start != byte_size) { - ByteSizeConsistencyError(byte_size, ByteSizeLong(), end - start, *this); + const size_t byte_size = ByteSizeLong(); + if (byte_size > INT_MAX) { + GOOGLE_LOG(ERROR) << GetTypeName() + << " exceeded maximum protobuf size of 2GB: " << byte_size; + return false; } + if (size < static_cast(byte_size)) return false; + uint8* start = reinterpret_cast(data); + SerializeToArrayImpl(*this, start, byte_size); return true; } -string MessageLite::SerializeAsString() const { +std::string MessageLite::SerializeAsString() const { // If the compiler implements the (Named) Return Value Optimization, // the local variable 'output' will not actually reside on the stack // of this function, but will be overlaid with the object that the // caller supplied for the return value to be constructed in. - string output; - if (!AppendToString(&output)) - output.clear(); + std::string output; + if (!AppendToString(&output)) output.clear(); return output; } -string MessageLite::SerializePartialAsString() const { - string output; - if (!AppendPartialToString(&output)) - output.clear(); +std::string MessageLite::SerializePartialAsString() const { + std::string output; + if (!AppendPartialToString(&output)) output.clear(); return output; } -void MessageLite::SerializeWithCachedSizes(io::CodedOutputStream* output) const - { - GOOGLE_DCHECK(InternalGetTable()); - internal::TableSerialize(*this, static_cast(InternalGetTable()), output); -} - -// The table driven code optimizes the case that the CodedOutputStream buffer -// is large enough to serialize into it directly. -// If the proto is optimized for speed, this method will be overridden by -// generated code for maximum speed. If the proto is optimized for size or -// is lite, then we need to specialize this to avoid infinite recursion. -uint8* MessageLite::InternalSerializeWithCachedSizesToArray(bool deterministic, - uint8* target) const { - const internal::SerializationTable* table = - static_cast(InternalGetTable()); - if (table == NULL) { - // We only optimize this when using optimize_for = SPEED. In other cases - // we just use the CodedOutputStream path. - int size = GetCachedSize(); - io::ArrayOutputStream out(target, size); - io::CodedOutputStream coded_out(&out); - coded_out.SetSerializationDeterministic(deterministic); - SerializeWithCachedSizes(&coded_out); - GOOGLE_CHECK(!coded_out.HadError()); - return target + size; - } else { - return internal::TableSerializeToArray(*this, table, deterministic, target); - } -} namespace internal { -template<> + +template <> MessageLite* GenericTypeHandler::NewFromPrototype( - const MessageLite* prototype, google::protobuf::Arena* arena) { + const MessageLite* prototype, Arena* arena) { return prototype->New(arena); } template <> @@ -385,19 +523,80 @@ void GenericTypeHandler::Merge(const MessageLite& from, MessageLite* to) { to->CheckTypeAndMergeFrom(from); } -template<> -void GenericTypeHandler::Merge(const string& from, - string* to) { +template <> +void GenericTypeHandler::Merge(const std::string& from, + std::string* to) { *to = from; } -bool proto3_preserve_unknown_ = false; -void SetProto3PreserveUnknownsDefault(bool preserve) { - proto3_preserve_unknown_ = preserve; +// Non-inline variants of std::string specializations for +// various InternalMetadata routines. +template <> +void InternalMetadata::DoClear() { + mutable_unknown_fields()->clear(); +} + +template <> +void InternalMetadata::DoMergeFrom(const std::string& other) { + mutable_unknown_fields()->append(other); +} + +template <> +void InternalMetadata::DoSwap(std::string* other) { + mutable_unknown_fields()->swap(*other); +} + +} // namespace internal + + +// =================================================================== +// Shutdown support. + +namespace internal { + +struct ShutdownData { + ~ShutdownData() { + std::reverse(functions.begin(), functions.end()); + for (auto pair : functions) pair.first(pair.second); + } + + static ShutdownData* get() { + static auto* data = new ShutdownData; + return data; + } + + std::vector> functions; + Mutex mutex; +}; + +static void RunZeroArgFunc(const void* arg) { + void (*func)() = reinterpret_cast(const_cast(arg)); + func(); +} + +void OnShutdown(void (*func)()) { + OnShutdownRun(RunZeroArgFunc, reinterpret_cast(func)); } +void OnShutdownRun(void (*f)(const void*), const void* arg) { + auto shutdown_data = ShutdownData::get(); + MutexLock lock(&shutdown_data->mutex); + shutdown_data->functions.push_back(std::make_pair(f, arg)); +} } // namespace internal +void ShutdownProtobufLibrary() { + // This function should be called only once, but accepts multiple calls. + static bool is_shutdown = false; + if (!is_shutdown) { + delete internal::ShutdownData::get(); + is_shutdown = true; + } +} + + } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index 2075f4b6524fe..8a9b79dfb1cc1 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -40,43 +40,54 @@ #define GOOGLE_PROTOBUF_MESSAGE_LITE_H__ #include +#include + #include #include +#include +#include +#include #include +#include +#include -#if LANG_CXX11 && !defined(__NVCC__) -#define PROTOBUF_CXX11 1 -#else -#define PROTOBUF_CXX11 0 -#endif +#include -#if PROTOBUF_CXX11 -#define PROTOBUF_FINAL final -#else -#define PROTOBUF_FINAL +#ifdef SWIG +#error "You cannot SWIG proto headers" #endif -#ifndef LIBPROTOBUF_EXPORT -#define LIBPROTOBUF_EXPORT -#endif - -#define PROTOBUF_RUNTIME_DEPRECATED(message) - namespace google { namespace protobuf { -class Arena; + +template +class RepeatedPtrField; + namespace io { + class CodedInputStream; class CodedOutputStream; class ZeroCopyInputStream; class ZeroCopyOutputStream; -} + +} // namespace io namespace internal { +// Tag type used to invoke the constinit constructor overload of some classes. +// Such constructors are internal implementation details of the library. +struct ConstantInitialized { + explicit ConstantInitialized() = default; +}; + +// See parse_context.h for explanation +class ParseContext; + +class Proto3ArenaTestHelper; +class RepeatedPtrFieldBase; class WireFormatLite; +class WeakFieldMap; -#ifndef SWIG // We compute sizes as size_t but cache them as int. This function converts a // computed size to a cached size. Since we don't proceed with serialization // if the total size was > INT_MAX, it is not important what this function @@ -112,35 +123,30 @@ inline int ToIntSize(size_t size) { // // Pay special attention to the initialization state of the object. // 1. The object is "uninitialized" to begin with. -// 2. Call DefaultConstruct() only if the object is uninitialized. -// After the call, the object becomes "initialized". +// 2. Call Construct() or DefaultConstruct() only if the object is +// uninitialized. After the call, the object becomes "initialized". // 3. Call get() and get_mutable() only if the object is initialized. // 4. Call Destruct() only if the object is initialized. // After the call, the object becomes uninitialized. template class ExplicitlyConstructed { public: - void DefaultConstruct() { - new (&union_) T(); - } + void DefaultConstruct() { new (&union_) T(); } - void Destruct() { - get_mutable()->~T(); + template + void Construct(Args&&... args) { + new (&union_) T(std::forward(args)...); } -#if LANG_CXX11 - constexpr -#endif - const T& - get() const { - return reinterpret_cast(union_); - } + void Destruct() { get_mutable()->~T(); } + + constexpr const T& get() const { return reinterpret_cast(union_); } T* get_mutable() { return reinterpret_cast(&union_); } private: // Prefer c++14 aligned_storage, but for compatibility this will do. union AlignedUnion { - char space[sizeof(T)]; + alignas(T) char space[sizeof(T)]; int64 align_to_int64; void* align_to_ptr; } union_; @@ -148,22 +154,16 @@ class ExplicitlyConstructed { // Default empty string object. Don't use this directly. Instead, call // GetEmptyString() to get the reference. -extern ExplicitlyConstructed< ::std::string> fixed_address_empty_string; -LIBPROTOBUF_EXPORT extern ProtobufOnceType empty_string_once_init_; -LIBPROTOBUF_EXPORT void InitEmptyString(); +PROTOBUF_EXPORT extern ExplicitlyConstructed + fixed_address_empty_string; -LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyStringAlreadyInited() { +PROTOBUF_EXPORT constexpr const std::string& GetEmptyStringAlreadyInited() { return fixed_address_empty_string.get(); } -LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyString() { - ::google::protobuf::GoogleOnceInit(&empty_string_once_init_, &InitEmptyString); - return GetEmptyStringAlreadyInited(); -} +PROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const std::string& str); -LIBPROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const string& str); -#endif // SWIG } // namespace internal // Interface to light weight protocol messages. @@ -189,15 +189,18 @@ LIBPROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const string& str); // is best when you only have a small number of message types linked // into your binary, in which case the size of the protocol buffers // runtime itself is the biggest problem. -class LIBPROTOBUF_EXPORT MessageLite { +// +// Users must not derive from this class. Only the protocol compiler and +// the internal library are allowed to create subclasses. +class PROTOBUF_EXPORT MessageLite { public: - inline MessageLite() {} - virtual ~MessageLite() {} + constexpr MessageLite() {} + virtual ~MessageLite() = default; // Basic Operations ------------------------------------------------ // Get the name of this message type, e.g. "foo.bar.BazProto". - virtual string GetTypeName() const = 0; + virtual std::string GetTypeName() const = 0; // Construct a new instance of the same type. Ownership is passed to the // caller. @@ -205,14 +208,14 @@ class LIBPROTOBUF_EXPORT MessageLite { // Construct a new instance on the arena. Ownership is passed to the caller // if arena is a NULL. Default implementation for backwards compatibility. - virtual MessageLite* New(::google::protobuf::Arena* arena) const; + virtual MessageLite* New(Arena* arena) const; - // Get the arena, if any, associated with this message. Virtual method - // required for generic operations but most arena-related operations should - // use the GetArenaNoVirtual() generated-code method. Default implementation - // to reduce code size by avoiding the need for per-type implementations - // when types do not implement arena support. - virtual ::google::protobuf::Arena* GetArena() const { return NULL; } + // Get the arena for allocating submessages, if any, associated with this + // message. Virtual method required for generic operations but most + // arena-related operations should use the GetArena() generated-code method. + // Default implementation to reduce code size by avoiding the need for + // per-type implementations when types do not implement arena support. + Arena* GetArena() const { return _internal_metadata_.arena(); } // Get a pointer that may be equal to this message's arena, or may not be. // If the value returned by this method is equal to some arena pointer, then @@ -223,7 +226,9 @@ class LIBPROTOBUF_EXPORT MessageLite { // store the arena pointer directly, and sometimes in a more indirect way, // and allow a fastpath comparison against the arena pointer when it's easy // to obtain. - virtual void* GetMaybeArenaPointer() const { return GetArena(); } + void* GetMaybeArenaPointer() const { + return _internal_metadata_.raw_arena_ptr(); + } // Clear all fields of the message and set them to their default values. // Clear() avoids freeing memory, assuming that any memory allocated @@ -238,12 +243,27 @@ class LIBPROTOBUF_EXPORT MessageLite { // This is not implemented for Lite messages -- it just returns "(cannot // determine missing fields for lite message)". However, it is implemented // for full messages. See message.h. - virtual string InitializationErrorString() const; + virtual std::string InitializationErrorString() const; // If |other| is the exact same class as this, calls MergeFrom(). Otherwise, // results are undefined (probably crash). virtual void CheckTypeAndMergeFrom(const MessageLite& other) = 0; + // These methods return a human-readable summary of the message. Note that + // since the MessageLite interface does not support reflection, there is very + // little information that these methods can provide. They are shadowed by + // methods of the same name on the Message interface which provide much more + // information. The methods here are intended primarily to facilitate code + // reuse for logic that needs to interoperate with both full and lite protos. + // + // The format of the returned string is subject to change, so please do not + // assume it will remain stable over time. + std::string DebugString() const; + std::string ShortDebugString() const { return DebugString(); } + // MessageLite::DebugString is already Utf8 Safe. This is to add compatibility + // with Message. + std::string Utf8DebugString() const { return DebugString(); } + // Parsing --------------------------------------------------------- // Methods for parsing in protocol buffer format. Most of these are // just simple wrappers around MergeFromCodedStream(). Clear() will be @@ -254,42 +274,70 @@ class LIBPROTOBUF_EXPORT MessageLite { // format. A successful return does not indicate the entire input is // consumed, ensure you call ConsumedEntireMessage() to check that if // applicable. - bool ParseFromCodedStream(io::CodedInputStream* input); + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromCodedStream( + io::CodedInputStream* input); // Like ParseFromCodedStream(), but accepts messages that are missing // required fields. - bool ParsePartialFromCodedStream(io::CodedInputStream* input); + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromCodedStream( + io::CodedInputStream* input); // Read a protocol buffer from the given zero-copy input stream. If // successful, the entire input will be consumed. - bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input); + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromZeroCopyStream( + io::ZeroCopyInputStream* input); // Like ParseFromZeroCopyStream(), but accepts messages that are missing // required fields. - bool ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input); + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromZeroCopyStream( + io::ZeroCopyInputStream* input); + // Parse a protocol buffer from a file descriptor. If successful, the entire + // input will be consumed. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromFileDescriptor( + int file_descriptor); + // Like ParseFromFileDescriptor(), but accepts messages that are missing + // required fields. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromFileDescriptor( + int file_descriptor); + // Parse a protocol buffer from a C++ istream. If successful, the entire + // input will be consumed. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromIstream(std::istream* input); + // Like ParseFromIstream(), but accepts messages that are missing + // required fields. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromIstream( + std::istream* input); // Read a protocol buffer from the given zero-copy input stream, expecting // the message to be exactly "size" bytes long. If successful, exactly // this many bytes will have been consumed from the input. - bool ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size); + bool MergePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, + int size); // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are // missing required fields. - bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, - int size); + bool MergeFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size); + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromBoundedZeroCopyStream( + io::ZeroCopyInputStream* input, int size); + // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are + // missing required fields. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromBoundedZeroCopyStream( + io::ZeroCopyInputStream* input, int size); // Parses a protocol buffer contained in a string. Returns true on success. // This function takes a string in the (non-human-readable) binary wire // format, matching the encoding output by MessageLite::SerializeToString(). // If you'd like to convert a human-readable string into a protocol buffer // object, see google::protobuf::TextFormat::ParseFromString(). - bool ParseFromString(const string& data); + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromString(ConstStringParam data); // Like ParseFromString(), but accepts messages that are missing // required fields. - bool ParsePartialFromString(const string& data); + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromString( + ConstStringParam data); // Parse a protocol buffer contained in an array of bytes. - bool ParseFromArray(const void* data, int size); + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromArray(const void* data, + int size); // Like ParseFromArray(), but accepts messages that are missing // required fields. - bool ParsePartialFromArray(const void* data, int size); + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromArray(const void* data, + int size); // Reads a protocol buffer from the stream and merges it into this - // Message. Singular fields read from the input overwrite what is + // Message. Singular fields read from the what is // already in the Message and repeated fields are appended to those // already present. // @@ -297,7 +345,7 @@ class LIBPROTOBUF_EXPORT MessageLite { // (for groups) or input->ConsumedEntireMessage() (for non-groups) after // this returns to verify that the message's end was delimited correctly. // - // ParsefromCodedStream() is implemented as Clear() followed by + // ParseFromCodedStream() is implemented as Clear() followed by // MergeFromCodedStream(). bool MergeFromCodedStream(io::CodedInputStream* input); @@ -306,7 +354,10 @@ class LIBPROTOBUF_EXPORT MessageLite { // // MergeFromCodedStream() is just implemented as MergePartialFromCodedStream() // followed by IsInitialized(). - virtual bool MergePartialFromCodedStream(io::CodedInputStream* input) = 0; + bool MergePartialFromCodedStream(io::CodedInputStream* input); + + // Merge a protocol buffer contained in a string. + bool MergeFromString(ConstStringParam data); // Serialization --------------------------------------------------- @@ -326,9 +377,9 @@ class LIBPROTOBUF_EXPORT MessageLite { bool SerializePartialToZeroCopyStream(io::ZeroCopyOutputStream* output) const; // Serialize the message and store it in the given string. All required // fields must be set. - bool SerializeToString(string* output) const; + bool SerializeToString(std::string* output) const; // Like SerializeToString(), but allows missing required fields. - bool SerializePartialToString(string* output) const; + bool SerializePartialToString(std::string* output) const; // Serialize the message and store it in the given byte array. All required // fields must be set. bool SerializeToArray(void* data, int size) const; @@ -341,15 +392,27 @@ class LIBPROTOBUF_EXPORT MessageLite { // Note: If you intend to generate many such strings, you may // reduce heap fragmentation by instead re-using the same string // object with calls to SerializeToString(). - string SerializeAsString() const; + std::string SerializeAsString() const; // Like SerializeAsString(), but allows missing required fields. - string SerializePartialAsString() const; - - // Like SerializeToString(), but appends to the data to the string's existing - // contents. All required fields must be set. - bool AppendToString(string* output) const; + std::string SerializePartialAsString() const; + + // Serialize the message and write it to the given file descriptor. All + // required fields must be set. + bool SerializeToFileDescriptor(int file_descriptor) const; + // Like SerializeToFileDescriptor(), but allows missing required fields. + bool SerializePartialToFileDescriptor(int file_descriptor) const; + // Serialize the message and write it to the given C++ ostream. All + // required fields must be set. + bool SerializeToOstream(std::ostream* output) const; + // Like SerializeToOstream(), but allows missing required fields. + bool SerializePartialToOstream(std::ostream* output) const; + + // Like SerializeToString(), but appends to the data to the string's + // existing contents. All required fields must be set. + bool AppendToString(std::string* output) const; // Like AppendToString(), but allows missing required fields. - bool AppendPartialToString(string* output) const; + bool AppendPartialToString(std::string* output) const; + // Computes the serialized size of the message. This recursively calls // ByteSizeLong() on all embedded messages. @@ -359,16 +422,15 @@ class LIBPROTOBUF_EXPORT MessageLite { virtual size_t ByteSizeLong() const = 0; // Legacy ByteSize() API. - PROTOBUF_RUNTIME_DEPRECATED("Please use ByteSizeLong() instead") - int ByteSize() const { - return internal::ToIntSize(ByteSizeLong()); - } + PROTOBUF_DEPRECATED_MSG("Please use ByteSizeLong() instead") + int ByteSize() const { return internal::ToIntSize(ByteSizeLong()); } // Serializes the message without recomputing the size. The message must not // have changed since the last call to ByteSize(), and the value returned by // ByteSize must be non-negative. Otherwise the results are undefined. - virtual void SerializeWithCachedSizes( - io::CodedOutputStream* output) const; + void SerializeWithCachedSizes(io::CodedOutputStream* output) const { + output->SetCur(_InternalSerialize(output->Cur(), output->EpsCopy())); + } // Functions below here are not part of the public interface. It isn't // enforced, but they should be treated as private, and will be private @@ -380,7 +442,7 @@ class LIBPROTOBUF_EXPORT MessageLite { // must point at a byte array of at least ByteSize() bytes. Whether to use // deterministic serialization, e.g., maps in sorted order, is determined by // CodedOutputStream::IsDefaultSerializationDeterministic(). - virtual uint8* SerializeWithCachedSizesToArray(uint8* target) const; + uint8* SerializeWithCachedSizesToArray(uint8* target) const; // Returns the result of the last call to ByteSize(). An embedded message's // size is needed both to serialize it (because embedded messages are @@ -395,36 +457,163 @@ class LIBPROTOBUF_EXPORT MessageLite { // method.) virtual int GetCachedSize() const = 0; - virtual uint8* InternalSerializeWithCachedSizesToArray(bool deterministic, - uint8* target) const; + virtual const char* _InternalParse(const char* /*ptr*/, + internal::ParseContext* /*ctx*/) { + return nullptr; + } + + protected: + template + static T* CreateMaybeMessage(Arena* arena) { + return Arena::CreateMaybeMessage(arena); + } + + inline explicit MessageLite(Arena* arena) : _internal_metadata_(arena) {} + + internal::InternalMetadata _internal_metadata_; + + public: + enum ParseFlags { + kMerge = 0, + kParse = 1, + kMergePartial = 2, + kParsePartial = 3, + kMergeWithAliasing = 4, + kParseWithAliasing = 5, + kMergePartialWithAliasing = 6, + kParsePartialWithAliasing = 7 + }; + + template + bool ParseFrom(const T& input); + + // Fast path when conditions match (ie. non-deterministic) + // uint8* _InternalSerialize(uint8* ptr) const; + virtual uint8* _InternalSerialize(uint8* ptr, + io::EpsCopyOutputStream* stream) const = 0; + + // Identical to IsInitialized() except that it logs an error message. + bool IsInitializedWithErrors() const { + if (IsInitialized()) return true; + LogInitializationErrorMessage(); + return false; + } private: // TODO(gerbens) make this a pure abstract function virtual const void* InternalGetTable() const { return NULL; } + // Get the arena that owns this message. + Arena* GetOwningArena() const { return _internal_metadata_.GetOwningArena(); } + + // Set the owning arena to the given one. + void SetOwningArena(Arena* arena) { + _internal_metadata_.SetOwningArena(arena); + } + + friend class Arena; friend class internal::WireFormatLite; friend class Message; + friend class internal::Proto3ArenaTestHelper; + friend class internal::WeakFieldMap; + + void LogInitializationErrorMessage() const; + + bool MergeFromImpl(io::CodedInputStream* input, ParseFlags parse_flags); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageLite); }; namespace internal { -extern bool LIBPROTOBUF_EXPORT proto3_preserve_unknown_; +template +bool MergeFromImpl(StringPiece input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +extern template bool MergeFromImpl(StringPiece input, + MessageLite* msg, + MessageLite::ParseFlags parse_flags); +extern template bool MergeFromImpl(StringPiece input, + MessageLite* msg, + MessageLite::ParseFlags parse_flags); + +template +bool MergeFromImpl(io::ZeroCopyInputStream* input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +extern template bool MergeFromImpl(io::ZeroCopyInputStream* input, + MessageLite* msg, + MessageLite::ParseFlags parse_flags); +extern template bool MergeFromImpl(io::ZeroCopyInputStream* input, + MessageLite* msg, + MessageLite::ParseFlags parse_flags); + +struct BoundedZCIS { + io::ZeroCopyInputStream* zcis; + int limit; +}; + +template +bool MergeFromImpl(BoundedZCIS input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +extern template bool MergeFromImpl(BoundedZCIS input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +extern template bool MergeFromImpl(BoundedZCIS input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); + +template +struct SourceWrapper; -// DO NOT USE: For migration only. Will be removed when Proto3 defaults to -// preserve unknowns. -inline bool GetProto3PreserveUnknownsDefault() { - return proto3_preserve_unknown_; +template +bool MergeFromImpl(const SourceWrapper& input, MessageLite* msg, + MessageLite::ParseFlags parse_flags) { + return input.template MergeInto(msg, parse_flags); } -// DO NOT USE: For migration only. Will be removed when Proto3 defaults to -// preserve unknowns. -void LIBPROTOBUF_EXPORT SetProto3PreserveUnknownsDefault(bool preserve); } // namespace internal +template +bool MessageLite::ParseFrom(const T& input) { + if (flags & kParse) Clear(); + constexpr bool alias = (flags & kMergeWithAliasing) != 0; + return internal::MergeFromImpl(input, this, flags); +} -} // namespace protobuf +// =================================================================== +// Shutdown support. + + +// Shut down the entire protocol buffers library, deleting all static-duration +// objects allocated by the library or by generated .pb.cc files. +// +// There are two reasons you might want to call this: +// * You use a draconian definition of "memory leak" in which you expect +// every single malloc() to have a corresponding free(), even for objects +// which live until program exit. +// * You are writing a dynamically-loaded library which needs to clean up +// after itself when the library is unloaded. +// +// It is safe to call this multiple times. However, it is not safe to use +// any other part of the protocol buffers library after +// ShutdownProtobufLibrary() has been called. Furthermore this call is not +// thread safe, user needs to synchronize multiple calls. +PROTOBUF_EXPORT void ShutdownProtobufLibrary(); + +namespace internal { +// Register a function to be called when ShutdownProtocolBuffers() is called. +PROTOBUF_EXPORT void OnShutdown(void (*func)()); +// Run an arbitrary function on an arg +PROTOBUF_EXPORT void OnShutdownRun(void (*f)(const void*), const void* arg); + +template +T* OnShutdownDelete(T* p) { + OnShutdownRun([](const void* pp) { delete static_cast(pp); }, p); + return p; +} + +} // namespace internal +} // namespace protobuf } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_MESSAGE_LITE_H__ diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc index fe4566779b0c4..0840e7bf2a333 100644 --- a/src/google/protobuf/message_unittest.cc +++ b/src/google/protobuf/message_unittest.cc @@ -32,579 +32,14 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include - -#include -#include -#include -#ifndef _MSC_VER -#include -#endif -#include -#include - -#include #include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { - -#if defined(_MSC_VER) -// DO NOT include , instead create functions in io_win32.{h,cc} and import -// them like we do below. -using google::protobuf::internal::win32::close; -using google::protobuf::internal::win32::open; -#endif - -#ifndef O_BINARY -#ifdef _O_BINARY -#define O_BINARY _O_BINARY -#else -#define O_BINARY 0 // If this isn't defined, the platform doesn't need it. -#endif -#endif - -TEST(MessageTest, SerializeHelpers) { - // TODO(kenton): Test more helpers? They're all two-liners so it seems - // like a waste of time. - - protobuf_unittest::TestAllTypes message; - TestUtil::SetAllFields(&message); - std::stringstream stream; - - string str1("foo"); - string str2("bar"); - - EXPECT_TRUE(message.SerializeToString(&str1)); - EXPECT_TRUE(message.AppendToString(&str2)); - EXPECT_TRUE(message.SerializeToOstream(&stream)); - - EXPECT_EQ(str1.size() + 3, str2.size()); - EXPECT_EQ("bar", str2.substr(0, 3)); - // Don't use EXPECT_EQ because we don't want to dump raw binary data to - // stdout. - EXPECT_TRUE(str2.substr(3) == str1); - - // GCC gives some sort of error if we try to just do stream.str() == str1. - string temp = stream.str(); - EXPECT_TRUE(temp == str1); - - EXPECT_TRUE(message.SerializeAsString() == str1); - -} - -TEST(MessageTest, SerializeToBrokenOstream) { - std::ofstream out; - protobuf_unittest::TestAllTypes message; - message.set_optional_int32(123); - - EXPECT_FALSE(message.SerializeToOstream(&out)); -} - -TEST(MessageTest, ParseFromFileDescriptor) { - string filename = TestSourceDir() + - "/google/protobuf/testdata/golden_message"; - int file = open(filename.c_str(), O_RDONLY | O_BINARY); - ASSERT_GE(file, 0); - - protobuf_unittest::TestAllTypes message; - EXPECT_TRUE(message.ParseFromFileDescriptor(file)); - TestUtil::ExpectAllFieldsSet(message); - - EXPECT_GE(close(file), 0); -} - -TEST(MessageTest, ParsePackedFromFileDescriptor) { - string filename = - TestSourceDir() + - "/google/protobuf/testdata/golden_packed_fields_message"; - int file = open(filename.c_str(), O_RDONLY | O_BINARY); - ASSERT_GE(file, 0); - - protobuf_unittest::TestPackedTypes message; - EXPECT_TRUE(message.ParseFromFileDescriptor(file)); - TestUtil::ExpectPackedFieldsSet(message); - - EXPECT_GE(close(file), 0); -} - -TEST(MessageTest, ParseHelpers) { - // TODO(kenton): Test more helpers? They're all two-liners so it seems - // like a waste of time. - string data; - - { - // Set up. - protobuf_unittest::TestAllTypes message; - TestUtil::SetAllFields(&message); - message.SerializeToString(&data); - } - - { - // Test ParseFromString. - protobuf_unittest::TestAllTypes message; - EXPECT_TRUE(message.ParseFromString(data)); - TestUtil::ExpectAllFieldsSet(message); - } - - { - // Test ParseFromIstream. - protobuf_unittest::TestAllTypes message; - std::stringstream stream(data); - EXPECT_TRUE(message.ParseFromIstream(&stream)); - EXPECT_TRUE(stream.eof()); - TestUtil::ExpectAllFieldsSet(message); - } - - { - // Test ParseFromBoundedZeroCopyStream. - string data_with_junk(data); - data_with_junk.append("some junk on the end"); - io::ArrayInputStream stream(data_with_junk.data(), data_with_junk.size()); - protobuf_unittest::TestAllTypes message; - EXPECT_TRUE(message.ParseFromBoundedZeroCopyStream(&stream, data.size())); - TestUtil::ExpectAllFieldsSet(message); - } - - { - // Test that ParseFromBoundedZeroCopyStream fails (but doesn't crash) if - // EOF is reached before the expected number of bytes. - io::ArrayInputStream stream(data.data(), data.size()); - protobuf_unittest::TestAllTypes message; - EXPECT_FALSE( - message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1)); - } -} - -TEST(MessageTest, ParseFailsIfNotInitialized) { - unittest::TestRequired message; - std::vector errors; - - { - ScopedMemoryLog log; - EXPECT_FALSE(message.ParseFromString("")); - errors = log.GetMessages(ERROR); - } - - ASSERT_EQ(1, errors.size()); - EXPECT_EQ("Can't parse message of type \"protobuf_unittest.TestRequired\" " - "because it is missing required fields: a, b, c", - errors[0]); -} - -TEST(MessageTest, BypassInitializationCheckOnParse) { - unittest::TestRequired message; - io::ArrayInputStream raw_input(NULL, 0); - io::CodedInputStream input(&raw_input); - EXPECT_TRUE(message.MergePartialFromCodedStream(&input)); -} - -TEST(MessageTest, InitializationErrorString) { - unittest::TestRequired message; - EXPECT_EQ("a, b, c", message.InitializationErrorString()); -} - -TEST(MessageTest, DynamicCastToGenerated) { - unittest::TestAllTypes test_all_types; - - google::protobuf::Message* test_all_types_pointer = &test_all_types; - EXPECT_EQ(&test_all_types, - google::protobuf::internal::DynamicCastToGenerated( - test_all_types_pointer)); - EXPECT_EQ(NULL, - google::protobuf::internal::DynamicCastToGenerated( - test_all_types_pointer)); - - const google::protobuf::Message* test_all_types_pointer_const = &test_all_types; - EXPECT_EQ( - &test_all_types, - google::protobuf::internal::DynamicCastToGenerated( - test_all_types_pointer_const)); - EXPECT_EQ( - NULL, - google::protobuf::internal::DynamicCastToGenerated( - test_all_types_pointer_const)); -} - -#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet. - -TEST(MessageTest, SerializeFailsIfNotInitialized) { - unittest::TestRequired message; - string data; - EXPECT_DEBUG_DEATH(EXPECT_TRUE(message.SerializeToString(&data)), - "Can't serialize message of type \"protobuf_unittest.TestRequired\" because " - "it is missing required fields: a, b, c"); -} - -TEST(MessageTest, CheckInitialized) { - unittest::TestRequired message; - EXPECT_DEATH(message.CheckInitialized(), - "Message of type \"protobuf_unittest.TestRequired\" is missing required " - "fields: a, b, c"); -} - -TEST(MessageTest, CheckOverflow) { - unittest::TestAllTypes message; - // Create a message with size just over 2GB. This triggers integer overflow - // when computing message size. - const string data(1024, 'x'); - Cord one_megabyte; - for (int i = 0; i < 1024; i++) { - one_megabyte.Append(data); - } - - for (int i = 0; i < 2 * 1024 + 1; ++i) { - message.add_repeated_cord()->CopyFrom(one_megabyte); - } - - Cord serialized; - EXPECT_FALSE(message.AppendToCord(&serialized)); -} - -TEST(MessageTest, CheckBigOverflow) { - // Checking for 4GB buffers on 32 bit systems is problematic. - if (sizeof(void*) < 8) return; - unittest::TestAllTypes message; - // Create a message with size just over 4GB. We should be able to detect this - // too, even though it will make a plain "int" wrap back to a positive number. - const string data(1024, 'x'); - Cord one_megabyte; - for (int i = 0; i < 1024; i++) { - one_megabyte.Append(data); - } - - for (int i = 0; i < 4 * 1024 + 1; ++i) { - message.add_repeated_cord()->CopyFrom(one_megabyte); - } - - Cord serialized; - EXPECT_FALSE(message.AppendToCord(&serialized)); -} - -#endif // PROTOBUF_HAS_DEATH_TEST - -namespace { -// An input stream that repeats a string's content for a number of times. It -// helps us create a really large input without consuming too much memory. Used -// to test the parsing behavior when the input size exceeds 2G or close to it. -class RepeatedInputStream : public io::ZeroCopyInputStream { - public: - RepeatedInputStream(const string& data, size_t count) - : data_(data), count_(count), position_(0), total_byte_count_(0) {} - - virtual bool Next(const void** data, int* size) { - if (position_ == data_.size()) { - if (--count_ == 0) { - return false; - } - position_ = 0; - } - *data = &data_[position_]; - *size = static_cast(data_.size() - position_); - position_ = data_.size(); - total_byte_count_ += *size; - return true; - } - - virtual void BackUp(int count) { - position_ -= static_cast(count); - total_byte_count_ -= count; - } - - virtual bool Skip(int count) { - while (count > 0) { - const void* data; - int size; - if (!Next(&data, &size)) { - break; - } - if (size >= count) { - BackUp(size - count); - return true; - } else { - count -= size; - } - } - return false; - } - - virtual int64 ByteCount() const { return total_byte_count_; } - - private: - string data_; - size_t count_; // The number of strings that haven't been consuemd. - size_t position_; // Position in the string for the next read. - int64 total_byte_count_; -}; -} // namespace - -TEST(MessageTest, TestParseMessagesCloseTo2G) { - // Create a message with a large string field. - string value = string(64 * 1024 * 1024, 'x'); - protobuf_unittest::TestAllTypes message; - message.set_optional_string(value); - - // Repeat this message in the input stream to make the total input size - // close to 2G. - string data = message.SerializeAsString(); - size_t count = static_cast(kint32max) / data.size(); - RepeatedInputStream input(data, count); - - // The parsing should succeed. - protobuf_unittest::TestAllTypes result; - EXPECT_TRUE(result.ParseFromZeroCopyStream(&input)); - - // When there are multiple occurences of a singulr field, the last one - // should win. - EXPECT_EQ(value, result.optional_string()); -} - -TEST(MessageTest, TestParseMessagesOver2G) { - // Create a message with a large string field. - string value = string(64 * 1024 * 1024, 'x'); - protobuf_unittest::TestAllTypes message; - message.set_optional_string(value); - - // Repeat this message in the input stream to make the total input size - // larger than 2G. - string data = message.SerializeAsString(); - size_t count = static_cast(kint32max) / data.size() + 1; - RepeatedInputStream input(data, count); - - // The parsing should fail. - protobuf_unittest::TestAllTypes result; - EXPECT_FALSE(result.ParseFromZeroCopyStream(&input)); -} - -TEST(MessageTest, BypassInitializationCheckOnSerialize) { - unittest::TestRequired message; - io::ArrayOutputStream raw_output(NULL, 0); - io::CodedOutputStream output(&raw_output); - EXPECT_TRUE(message.SerializePartialToCodedStream(&output)); -} - -TEST(MessageTest, FindInitializationErrors) { - unittest::TestRequired message; - std::vector errors; - message.FindInitializationErrors(&errors); - ASSERT_EQ(3, errors.size()); - EXPECT_EQ("a", errors[0]); - EXPECT_EQ("b", errors[1]); - EXPECT_EQ("c", errors[2]); -} - -TEST(MessageTest, ParseFailsOnInvalidMessageEnd) { - unittest::TestAllTypes message; - - // Control case. - EXPECT_TRUE(message.ParseFromArray("", 0)); - - // The byte is a valid varint, but not a valid tag (zero). - EXPECT_FALSE(message.ParseFromArray("\0", 1)); - - // The byte is a malformed varint. - EXPECT_FALSE(message.ParseFromArray("\200", 1)); - - // The byte is an endgroup tag, but we aren't parsing a group. - EXPECT_FALSE(message.ParseFromArray("\014", 1)); -} - -// Regression test for b/23630858 -TEST(MessageTest, MessageIsStillValidAfterParseFails) { - unittest::TestAllTypes message; - - // 9 0xFFs for the "optional_uint64" field. - string invalid_data = "\x20\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; - - EXPECT_FALSE(message.ParseFromString(invalid_data)); - message.Clear(); - EXPECT_EQ(0, message.optional_uint64()); - - // invalid data for field "optional_string". Length prefix is 1 but no - // payload. - string invalid_string_data = "\x72\x01"; - { - google::protobuf::Arena arena; - unittest::TestAllTypes* arena_message = - google::protobuf::Arena::CreateMessage(&arena); - EXPECT_FALSE(arena_message->ParseFromString(invalid_string_data)); - arena_message->Clear(); - EXPECT_EQ("", arena_message->optional_string()); - } -} - -namespace { - -void ExpectMessageMerged(const unittest::TestAllTypes& message) { - EXPECT_EQ(3, message.optional_int32()); - EXPECT_EQ(2, message.optional_int64()); - EXPECT_EQ("hello", message.optional_string()); -} - -void AssignParsingMergeMessages( - unittest::TestAllTypes* msg1, - unittest::TestAllTypes* msg2, - unittest::TestAllTypes* msg3) { - msg1->set_optional_int32(1); - msg2->set_optional_int64(2); - msg3->set_optional_int32(3); - msg3->set_optional_string("hello"); -} - -} // namespace - -// Test that if an optional or required message/group field appears multiple -// times in the input, they need to be merged. -TEST(MessageTest, ParsingMerge) { - unittest::TestParsingMerge::RepeatedFieldsGenerator generator; - unittest::TestAllTypes* msg1; - unittest::TestAllTypes* msg2; - unittest::TestAllTypes* msg3; - -#define ASSIGN_REPEATED_FIELD(FIELD) \ - msg1 = generator.add_##FIELD(); \ - msg2 = generator.add_##FIELD(); \ - msg3 = generator.add_##FIELD(); \ - AssignParsingMergeMessages(msg1, msg2, msg3) - - ASSIGN_REPEATED_FIELD(field1); - ASSIGN_REPEATED_FIELD(field2); - ASSIGN_REPEATED_FIELD(field3); - ASSIGN_REPEATED_FIELD(ext1); - ASSIGN_REPEATED_FIELD(ext2); - -#undef ASSIGN_REPEATED_FIELD -#define ASSIGN_REPEATED_GROUP(FIELD) \ - msg1 = generator.add_##FIELD()->mutable_field1(); \ - msg2 = generator.add_##FIELD()->mutable_field1(); \ - msg3 = generator.add_##FIELD()->mutable_field1(); \ - AssignParsingMergeMessages(msg1, msg2, msg3) - - ASSIGN_REPEATED_GROUP(group1); - ASSIGN_REPEATED_GROUP(group2); - -#undef ASSIGN_REPEATED_GROUP - - string buffer; - generator.SerializeToString(&buffer); - unittest::TestParsingMerge parsing_merge; - parsing_merge.ParseFromString(buffer); - - // Required and optional fields should be merged. - ExpectMessageMerged(parsing_merge.required_all_types()); - ExpectMessageMerged(parsing_merge.optional_all_types()); - ExpectMessageMerged( - parsing_merge.optionalgroup().optional_group_all_types()); - ExpectMessageMerged( - parsing_merge.GetExtension(unittest::TestParsingMerge::optional_ext)); - - // Repeated fields should not be merged. - EXPECT_EQ(3, parsing_merge.repeated_all_types_size()); - EXPECT_EQ(3, parsing_merge.repeatedgroup_size()); - EXPECT_EQ(3, parsing_merge.ExtensionSize( - unittest::TestParsingMerge::repeated_ext)); -} - -TEST(MessageTest, MergeFrom) { - unittest::TestAllTypes source; - unittest::TestAllTypes dest; - - // Optional fields - source.set_optional_int32(1); // only source - source.set_optional_int64(2); // both source and dest - dest.set_optional_int64(3); - dest.set_optional_uint32(4); // only dest - - // Optional fields with defaults - source.set_default_int32(13); // only source - source.set_default_int64(14); // both source and dest - dest.set_default_int64(15); - dest.set_default_uint32(16); // only dest - - // Repeated fields - source.add_repeated_int32(5); // only source - source.add_repeated_int32(6); - source.add_repeated_int64(7); // both source and dest - source.add_repeated_int64(8); - dest.add_repeated_int64(9); - dest.add_repeated_int64(10); - dest.add_repeated_uint32(11); // only dest - dest.add_repeated_uint32(12); - - dest.MergeFrom(source); - - // Optional fields: source overwrites dest if source is specified - EXPECT_EQ(1, dest.optional_int32()); // only source: use source - EXPECT_EQ(2, dest.optional_int64()); // source and dest: use source - EXPECT_EQ(4, dest.optional_uint32()); // only dest: use dest - EXPECT_EQ(0, dest.optional_uint64()); // neither: use default - - // Optional fields with defaults - EXPECT_EQ(13, dest.default_int32()); // only source: use source - EXPECT_EQ(14, dest.default_int64()); // source and dest: use source - EXPECT_EQ(16, dest.default_uint32()); // only dest: use dest - EXPECT_EQ(44, dest.default_uint64()); // neither: use default - - // Repeated fields: concatenate source onto the end of dest - ASSERT_EQ(2, dest.repeated_int32_size()); - EXPECT_EQ(5, dest.repeated_int32(0)); - EXPECT_EQ(6, dest.repeated_int32(1)); - ASSERT_EQ(4, dest.repeated_int64_size()); - EXPECT_EQ(9, dest.repeated_int64(0)); - EXPECT_EQ(10, dest.repeated_int64(1)); - EXPECT_EQ(7, dest.repeated_int64(2)); - EXPECT_EQ(8, dest.repeated_int64(3)); - ASSERT_EQ(2, dest.repeated_uint32_size()); - EXPECT_EQ(11, dest.repeated_uint32(0)); - EXPECT_EQ(12, dest.repeated_uint32(1)); - ASSERT_EQ(0, dest.repeated_uint64_size()); -} - -TEST(MessageTest, IsInitialized) { - protobuf_unittest::TestIsInitialized msg; - EXPECT_TRUE(msg.IsInitialized()); - protobuf_unittest::TestIsInitialized::SubMessage* sub_message = msg.mutable_sub_message(); - EXPECT_TRUE(msg.IsInitialized()); - protobuf_unittest::TestIsInitialized::SubMessage::SubGroup* sub_group = sub_message->mutable_subgroup(); - EXPECT_FALSE(msg.IsInitialized()); - sub_group->set_i(1); - EXPECT_TRUE(msg.IsInitialized()); -} - -TEST(MessageFactoryTest, GeneratedFactoryLookup) { - EXPECT_EQ( - MessageFactory::generated_factory()->GetPrototype( - protobuf_unittest::TestAllTypes::descriptor()), - &protobuf_unittest::TestAllTypes::default_instance()); -} - -TEST(MessageFactoryTest, GeneratedFactoryUnknownType) { - // Construct a new descriptor. - DescriptorPool pool; - FileDescriptorProto file; - file.set_name("foo.proto"); - file.add_message_type()->set_name("Foo"); - const Descriptor* descriptor = pool.BuildFile(file)->message_type(0); - - // Trying to construct it should return NULL. - EXPECT_TRUE( - MessageFactory::generated_factory()->GetPrototype(descriptor) == NULL); -} +#define MESSAGE_TEST_NAME MessageTest +#define MESSAGE_FACTORY_TEST_NAME MessageFactoryTest +#define UNITTEST_PACKAGE_NAME "protobuf_unittest" +#define UNITTEST ::protobuf_unittest +#define UNITTEST_IMPORT ::protobuf_unittest_import -} // namespace protobuf -} // namespace google +// Must include after the above macros. +#include +#include diff --git a/src/google/protobuf/message_unittest.inc b/src/google/protobuf/message_unittest.inc new file mode 100644 index 0000000000000..003f1fe859b02 --- /dev/null +++ b/src/google/protobuf/message_unittest.inc @@ -0,0 +1,665 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file needs to be included as .inc as it depends on certain macros being +// defined prior to its inclusion. + +#include +#include +#include + +#include +#ifndef _MSC_VER +#include +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { + +#if defined(_WIN32) +// DO NOT include , instead create functions in io_win32.{h,cc} and import +// them like we do below. +using google::protobuf::io::win32::close; +using google::protobuf::io::win32::open; +#endif + +#ifndef O_BINARY +#ifdef _O_BINARY +#define O_BINARY _O_BINARY +#else +#define O_BINARY 0 // If this isn't defined, the platform doesn't need it. +#endif +#endif + +TEST(MESSAGE_TEST_NAME, SerializeHelpers) { + // TODO(kenton): Test more helpers? They're all two-liners so it seems + // like a waste of time. + + UNITTEST::TestAllTypes message; + TestUtil::SetAllFields(&message); + std::stringstream stream; + + std::string str1("foo"); + std::string str2("bar"); + + EXPECT_TRUE(message.SerializeToString(&str1)); + EXPECT_TRUE(message.AppendToString(&str2)); + EXPECT_TRUE(message.SerializeToOstream(&stream)); + + EXPECT_EQ(str1.size() + 3, str2.size()); + EXPECT_EQ("bar", str2.substr(0, 3)); + // Don't use EXPECT_EQ because we don't want to dump raw binary data to + // stdout. + EXPECT_TRUE(str2.substr(3) == str1); + + // GCC gives some sort of error if we try to just do stream.str() == str1. + std::string temp = stream.str(); + EXPECT_TRUE(temp == str1); + + EXPECT_TRUE(message.SerializeAsString() == str1); + +} + +TEST(MESSAGE_TEST_NAME, SerializeToBrokenOstream) { + std::ofstream out; + UNITTEST::TestAllTypes message; + message.set_optional_int32(123); + + EXPECT_FALSE(message.SerializeToOstream(&out)); +} + +TEST(MESSAGE_TEST_NAME, ParseFromFileDescriptor) { + std::string filename = + TestUtil::GetTestDataPath("net/proto2/internal/testdata/golden_message"); + int file = open(filename.c_str(), O_RDONLY | O_BINARY); + ASSERT_GE(file, 0); + + UNITTEST::TestAllTypes message; + EXPECT_TRUE(message.ParseFromFileDescriptor(file)); + TestUtil::ExpectAllFieldsSet(message); + + EXPECT_GE(close(file), 0); +} + +TEST(MESSAGE_TEST_NAME, ParsePackedFromFileDescriptor) { + std::string filename = TestUtil::GetTestDataPath( + "net/proto2/internal/testdata/golden_packed_fields_message"); + int file = open(filename.c_str(), O_RDONLY | O_BINARY); + ASSERT_GE(file, 0); + + UNITTEST::TestPackedTypes message; + EXPECT_TRUE(message.ParseFromFileDescriptor(file)); + TestUtil::ExpectPackedFieldsSet(message); + + EXPECT_GE(close(file), 0); +} + +TEST(MESSAGE_TEST_NAME, ParseHelpers) { + // TODO(kenton): Test more helpers? They're all two-liners so it seems + // like a waste of time. + std::string data; + + { + // Set up. + UNITTEST::TestAllTypes message; + TestUtil::SetAllFields(&message); + message.SerializeToString(&data); + } + + { + // Test ParseFromString. + UNITTEST::TestAllTypes message; + EXPECT_TRUE(message.ParseFromString(data)); + TestUtil::ExpectAllFieldsSet(message); + } + + { + // Test ParseFromIstream. + UNITTEST::TestAllTypes message; + std::stringstream stream(data); + EXPECT_TRUE(message.ParseFromIstream(&stream)); + EXPECT_TRUE(stream.eof()); + TestUtil::ExpectAllFieldsSet(message); + } + + { + // Test ParseFromBoundedZeroCopyStream. + std::string data_with_junk(data); + data_with_junk.append("some junk on the end"); + io::ArrayInputStream stream(data_with_junk.data(), data_with_junk.size()); + UNITTEST::TestAllTypes message; + EXPECT_TRUE(message.ParseFromBoundedZeroCopyStream(&stream, data.size())); + TestUtil::ExpectAllFieldsSet(message); + } + + { + // Test that ParseFromBoundedZeroCopyStream fails (but doesn't crash) if + // EOF is reached before the expected number of bytes. + io::ArrayInputStream stream(data.data(), data.size()); + UNITTEST::TestAllTypes message; + EXPECT_FALSE( + message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1)); + } +} + +TEST(MESSAGE_TEST_NAME, ParseFailsIfNotInitialized) { + UNITTEST::TestRequired message; + std::vector errors; + + { + ScopedMemoryLog log; + EXPECT_FALSE(message.ParseFromString("")); + errors = log.GetMessages(ERROR); + } + + ASSERT_EQ(1, errors.size()); + EXPECT_EQ( + "Can't parse message of type \"" + std::string(UNITTEST_PACKAGE_NAME) + + ".TestRequired\" because it is missing required fields: a, b, c", + errors[0]); +} + +TEST(MESSAGE_TEST_NAME, BypassInitializationCheckOnParse) { + UNITTEST::TestRequired message; + io::ArrayInputStream raw_input(nullptr, 0); + io::CodedInputStream input(&raw_input); + EXPECT_TRUE(message.MergePartialFromCodedStream(&input)); +} + +TEST(MESSAGE_TEST_NAME, InitializationErrorString) { + UNITTEST::TestRequired message; + EXPECT_EQ("a, b, c", message.InitializationErrorString()); +} + +TEST(MESSAGE_TEST_NAME, DynamicCastToGenerated) { + UNITTEST::TestAllTypes test_all_types; + + Message* test_all_types_pointer = &test_all_types; + EXPECT_EQ(&test_all_types, DynamicCastToGenerated( + test_all_types_pointer)); + EXPECT_EQ(nullptr, DynamicCastToGenerated( + test_all_types_pointer)); + + const Message* test_all_types_pointer_const = &test_all_types; + EXPECT_EQ(&test_all_types, + DynamicCastToGenerated( + test_all_types_pointer_const)); + EXPECT_EQ(nullptr, DynamicCastToGenerated( + test_all_types_pointer_const)); + + Message* test_all_types_pointer_nullptr = nullptr; + EXPECT_EQ(nullptr, DynamicCastToGenerated( + test_all_types_pointer_nullptr)); +} + +#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet. + +TEST(MESSAGE_TEST_NAME, SerializeFailsIfNotInitialized) { + UNITTEST::TestRequired message; + std::string data; + EXPECT_DEBUG_DEATH(EXPECT_TRUE(message.SerializeToString(&data)), + "Can't serialize message of type \"" + + std::string(UNITTEST_PACKAGE_NAME) + + ".TestRequired\" because " + "it is missing required fields: a, b, c"); +} + +TEST(MESSAGE_TEST_NAME, CheckInitialized) { + UNITTEST::TestRequired message; + EXPECT_DEATH(message.CheckInitialized(), + "Message of type \"" + std::string(UNITTEST_PACKAGE_NAME) + + ".TestRequired\" is missing required " + "fields: a, b, c"); +} + +#endif // PROTOBUF_HAS_DEATH_TEST + +namespace { +// An input stream that repeats a std::string's content for a number of times. +// It helps us create a really large input without consuming too much memory. +// Used to test the parsing behavior when the input size exceeds 2G or close to +// it. +class RepeatedInputStream : public io::ZeroCopyInputStream { + public: + RepeatedInputStream(const std::string& data, size_t count) + : data_(data), count_(count), position_(0), total_byte_count_(0) {} + + bool Next(const void** data, int* size) override { + if (position_ == data_.size()) { + if (--count_ == 0) { + return false; + } + position_ = 0; + } + *data = &data_[position_]; + *size = static_cast(data_.size() - position_); + position_ = data_.size(); + total_byte_count_ += *size; + return true; + } + + void BackUp(int count) override { + position_ -= static_cast(count); + total_byte_count_ -= count; + } + + bool Skip(int count) override { + while (count > 0) { + const void* data; + int size; + if (!Next(&data, &size)) { + break; + } + if (size >= count) { + BackUp(size - count); + return true; + } else { + count -= size; + } + } + return false; + } + + int64_t ByteCount() const override { return total_byte_count_; } + + private: + std::string data_; + size_t count_; // The number of strings that haven't been consumed. + size_t position_; // Position in the std::string for the next read. + int64 total_byte_count_; +}; +} // namespace + +TEST(MESSAGE_TEST_NAME, TestParseMessagesCloseTo2G) { + // Create a message with a large std::string field. + std::string value = std::string(64 * 1024 * 1024, 'x'); + UNITTEST::TestAllTypes message; + message.set_optional_string(value); + + // Repeat this message in the input stream to make the total input size + // close to 2G. + std::string data = message.SerializeAsString(); + size_t count = static_cast(kint32max) / data.size(); + RepeatedInputStream input(data, count); + + // The parsing should succeed. + UNITTEST::TestAllTypes result; + EXPECT_TRUE(result.ParseFromZeroCopyStream(&input)); + + // When there are multiple occurrences of a singular field, the last one + // should win. + EXPECT_EQ(value, result.optional_string()); +} + +TEST(MESSAGE_TEST_NAME, TestParseMessagesOver2G) { + // Create a message with a large std::string field. + std::string value = std::string(64 * 1024 * 1024, 'x'); + UNITTEST::TestAllTypes message; + message.set_optional_string(value); + + // Repeat this message in the input stream to make the total input size + // larger than 2G. + std::string data = message.SerializeAsString(); + size_t count = static_cast(kint32max) / data.size() + 1; + RepeatedInputStream input(data, count); + + // The parsing should fail. + UNITTEST::TestAllTypes result; + EXPECT_FALSE(result.ParseFromZeroCopyStream(&input)); +} + +TEST(MESSAGE_TEST_NAME, BypassInitializationCheckOnSerialize) { + UNITTEST::TestRequired message; + io::ArrayOutputStream raw_output(nullptr, 0); + io::CodedOutputStream output(&raw_output); + EXPECT_TRUE(message.SerializePartialToCodedStream(&output)); +} + +TEST(MESSAGE_TEST_NAME, FindInitializationErrors) { + UNITTEST::TestRequired message; + std::vector errors; + message.FindInitializationErrors(&errors); + ASSERT_EQ(3, errors.size()); + EXPECT_EQ("a", errors[0]); + EXPECT_EQ("b", errors[1]); + EXPECT_EQ("c", errors[2]); +} + +TEST(MESSAGE_TEST_NAME, ParseFailsOnInvalidMessageEnd) { + UNITTEST::TestAllTypes message; + + // Control case. + EXPECT_TRUE(message.ParseFromArray("", 0)); + + // The byte is a valid varint, but not a valid tag (zero). + EXPECT_FALSE(message.ParseFromArray("\0", 1)); + + // The byte is a malformed varint. + EXPECT_FALSE(message.ParseFromArray("\200", 1)); + + // The byte is an endgroup tag, but we aren't parsing a group. + EXPECT_FALSE(message.ParseFromArray("\014", 1)); +} + +// Regression test for b/23630858 +TEST(MESSAGE_TEST_NAME, MessageIsStillValidAfterParseFails) { + UNITTEST::TestAllTypes message; + + // 9 0xFFs for the "optional_uint64" field. + std::string invalid_data = "\x20\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; + + EXPECT_FALSE(message.ParseFromString(invalid_data)); + message.Clear(); + EXPECT_EQ(0, message.optional_uint64()); + + // invalid data for field "optional_string". Length prefix is 1 but no + // payload. + std::string invalid_string_data = "\x72\x01"; + { + Arena arena; + UNITTEST::TestAllTypes* arena_message = + Arena::CreateMessage(&arena); + EXPECT_FALSE(arena_message->ParseFromString(invalid_string_data)); + arena_message->Clear(); + EXPECT_EQ("", arena_message->optional_string()); + } +} + + +namespace { + +void ExpectMessageMerged(const UNITTEST::TestAllTypes& message) { + EXPECT_EQ(3, message.optional_int32()); + EXPECT_EQ(2, message.optional_int64()); + EXPECT_EQ("hello", message.optional_string()); +} + +void AssignParsingMergeMessages(UNITTEST::TestAllTypes* msg1, + UNITTEST::TestAllTypes* msg2, + UNITTEST::TestAllTypes* msg3) { + msg1->set_optional_int32(1); + msg2->set_optional_int64(2); + msg3->set_optional_int32(3); + msg3->set_optional_string("hello"); +} + +} // namespace + +// Test that if an optional or required message/group field appears multiple +// times in the input, they need to be merged. +TEST(MESSAGE_TEST_NAME, ParsingMerge) { + UNITTEST::TestParsingMerge::RepeatedFieldsGenerator generator; + UNITTEST::TestAllTypes* msg1; + UNITTEST::TestAllTypes* msg2; + UNITTEST::TestAllTypes* msg3; + +#define ASSIGN_REPEATED_FIELD(FIELD) \ + msg1 = generator.add_##FIELD(); \ + msg2 = generator.add_##FIELD(); \ + msg3 = generator.add_##FIELD(); \ + AssignParsingMergeMessages(msg1, msg2, msg3) + + ASSIGN_REPEATED_FIELD(field1); + ASSIGN_REPEATED_FIELD(field2); + ASSIGN_REPEATED_FIELD(field3); + ASSIGN_REPEATED_FIELD(ext1); + ASSIGN_REPEATED_FIELD(ext2); + +#undef ASSIGN_REPEATED_FIELD +#define ASSIGN_REPEATED_GROUP(FIELD) \ + msg1 = generator.add_##FIELD()->mutable_field1(); \ + msg2 = generator.add_##FIELD()->mutable_field1(); \ + msg3 = generator.add_##FIELD()->mutable_field1(); \ + AssignParsingMergeMessages(msg1, msg2, msg3) + + ASSIGN_REPEATED_GROUP(group1); + ASSIGN_REPEATED_GROUP(group2); + +#undef ASSIGN_REPEATED_GROUP + + std::string buffer; + generator.SerializeToString(&buffer); + UNITTEST::TestParsingMerge parsing_merge; + parsing_merge.ParseFromString(buffer); + + // Required and optional fields should be merged. + ExpectMessageMerged(parsing_merge.required_all_types()); + ExpectMessageMerged(parsing_merge.optional_all_types()); + ExpectMessageMerged(parsing_merge.optionalgroup().optional_group_all_types()); + ExpectMessageMerged( + parsing_merge.GetExtension(UNITTEST::TestParsingMerge::optional_ext)); + + // Repeated fields should not be merged. + EXPECT_EQ(3, parsing_merge.repeated_all_types_size()); + EXPECT_EQ(3, parsing_merge.repeatedgroup_size()); + EXPECT_EQ( + 3, parsing_merge.ExtensionSize(UNITTEST::TestParsingMerge::repeated_ext)); +} + +TEST(MESSAGE_TEST_NAME, MergeFrom) { + UNITTEST::TestAllTypes source, dest; + + // Optional fields + source.set_optional_int32(1); // only source + source.set_optional_int64(2); // both source and dest + dest.set_optional_int64(3); + dest.set_optional_uint32(4); // only dest + + // Optional fields with defaults + source.set_default_int32(13); // only source + source.set_default_int64(14); // both source and dest + dest.set_default_int64(15); + dest.set_default_uint32(16); // only dest + + // Repeated fields + source.add_repeated_int32(5); // only source + source.add_repeated_int32(6); + source.add_repeated_int64(7); // both source and dest + source.add_repeated_int64(8); + dest.add_repeated_int64(9); + dest.add_repeated_int64(10); + dest.add_repeated_uint32(11); // only dest + dest.add_repeated_uint32(12); + + dest.MergeFrom(source); + + // Optional fields: source overwrites dest if source is specified + EXPECT_EQ(1, dest.optional_int32()); // only source: use source + EXPECT_EQ(2, dest.optional_int64()); // source and dest: use source + EXPECT_EQ(4, dest.optional_uint32()); // only dest: use dest + EXPECT_EQ(0, dest.optional_uint64()); // neither: use default + + // Optional fields with defaults + EXPECT_EQ(13, dest.default_int32()); // only source: use source + EXPECT_EQ(14, dest.default_int64()); // source and dest: use source + EXPECT_EQ(16, dest.default_uint32()); // only dest: use dest + EXPECT_EQ(44, dest.default_uint64()); // neither: use default + + // Repeated fields: concatenate source onto the end of dest + ASSERT_EQ(2, dest.repeated_int32_size()); + EXPECT_EQ(5, dest.repeated_int32(0)); + EXPECT_EQ(6, dest.repeated_int32(1)); + ASSERT_EQ(4, dest.repeated_int64_size()); + EXPECT_EQ(9, dest.repeated_int64(0)); + EXPECT_EQ(10, dest.repeated_int64(1)); + EXPECT_EQ(7, dest.repeated_int64(2)); + EXPECT_EQ(8, dest.repeated_int64(3)); + ASSERT_EQ(2, dest.repeated_uint32_size()); + EXPECT_EQ(11, dest.repeated_uint32(0)); + EXPECT_EQ(12, dest.repeated_uint32(1)); + ASSERT_EQ(0, dest.repeated_uint64_size()); +} + +TEST(MESSAGE_TEST_NAME, IsInitialized) { + UNITTEST::TestIsInitialized msg; + EXPECT_TRUE(msg.IsInitialized()); + UNITTEST::TestIsInitialized::SubMessage* sub_message = + msg.mutable_sub_message(); + EXPECT_TRUE(msg.IsInitialized()); + UNITTEST::TestIsInitialized::SubMessage::SubGroup* sub_group = + sub_message->mutable_subgroup(); + EXPECT_FALSE(msg.IsInitialized()); + sub_group->set_i(1); + EXPECT_TRUE(msg.IsInitialized()); +} + +TEST(MESSAGE_TEST_NAME, IsInitializedSplitBytestream) { + UNITTEST::TestRequired ab, c; + ab.set_a(1); + ab.set_b(2); + c.set_c(3); + + // The protobuf represented by the concatenated string has all required + // fields (a,b,c) set. + std::string bytes = + ab.SerializePartialAsString() + c.SerializePartialAsString(); + + UNITTEST::TestRequired concatenated; + EXPECT_TRUE(concatenated.ParsePartialFromString(bytes)); + EXPECT_TRUE(concatenated.IsInitialized()); + + UNITTEST::TestRequiredForeign fab, fc; + fab.mutable_optional_message()->set_a(1); + fab.mutable_optional_message()->set_b(2); + fc.mutable_optional_message()->set_c(3); + + bytes = + fab.SerializePartialAsString() + fc.SerializePartialAsString(); + + UNITTEST::TestRequiredForeign fconcatenated; + EXPECT_TRUE(fconcatenated.ParsePartialFromString(bytes)); + EXPECT_TRUE(fconcatenated.IsInitialized()); +} + +TEST(MESSAGE_FACTORY_TEST_NAME, GeneratedFactoryLookup) { + EXPECT_EQ(MessageFactory::generated_factory()->GetPrototype( + UNITTEST::TestAllTypes::descriptor()), + &UNITTEST::TestAllTypes::default_instance()); +} + +TEST(MESSAGE_FACTORY_TEST_NAME, GeneratedFactoryUnknownType) { + // Construct a new descriptor. + DescriptorPool pool; + FileDescriptorProto file; + file.set_name("foo.proto"); + file.add_message_type()->set_name("Foo"); + const Descriptor* descriptor = pool.BuildFile(file)->message_type(0); + + // Trying to construct it should return nullptr. + EXPECT_TRUE(MessageFactory::generated_factory()->GetPrototype(descriptor) == + nullptr); +} + +TEST(MESSAGE_TEST_NAME, MOMIParserEdgeCases) { + { + UNITTEST::TestAllTypes msg; + // Parser ends in last 16 bytes of buffer due to a 0. + std::string data; + // 12 bytes of data + for (int i = 0; i < 4; i++) data += "\370\1\1"; + // 13 byte is terminator + data += '\0'; // Terminator + // followed by the rest of the stream + // space is ascii 32 so no end group + data += std::string(30, ' '); + io::ArrayInputStream zcis(data.data(), data.size(), 17); + io::CodedInputStream cis(&zcis); + EXPECT_TRUE(msg.MergePartialFromCodedStream(&cis)); + EXPECT_EQ(cis.CurrentPosition(), 3 * 4 + 1); + } + { + // Parser ends in last 16 bytes of buffer due to a end-group. + // Must use a message that is a group. Otherwise ending on a group end is + // a failure. + UNITTEST::TestAllTypes::OptionalGroup msg; + std::string data; + for (int i = 0; i < 3; i++) data += "\370\1\1"; + data += '\14'; // Octal end-group tag 12 (1 * 8 + 4( + data += std::string(30, ' '); + io::ArrayInputStream zcis(data.data(), data.size(), 17); + io::CodedInputStream cis(&zcis); + EXPECT_TRUE(msg.MergePartialFromCodedStream(&cis)); + EXPECT_EQ(cis.CurrentPosition(), 3 * 3 + 1); + EXPECT_TRUE(cis.LastTagWas(12)); + } + { + // Parser ends in last 16 bytes of buffer due to a end-group. But is inside + // a length delimited field. + // a failure. + UNITTEST::TestAllTypes::OptionalGroup msg; + std::string data; + data += "\22\3foo"; + data += '\14'; // Octal end-group tag 12 (1 * 8 + 4( + data += std::string(30, ' '); + io::ArrayInputStream zcis(data.data(), data.size(), 17); + io::CodedInputStream cis(&zcis); + EXPECT_TRUE(msg.MergePartialFromCodedStream(&cis)); + EXPECT_EQ(cis.CurrentPosition(), 6); + EXPECT_TRUE(cis.LastTagWas(12)); + } + { + // Parser fails when ending on 0 if from ZeroCopyInputStream + UNITTEST::TestAllTypes msg; + std::string data; + // 12 bytes of data + for (int i = 0; i < 4; i++) data += "\370\1\1"; + // 13 byte is terminator + data += '\0'; // Terminator + data += std::string(30, ' '); + io::ArrayInputStream zcis(data.data(), data.size(), 17); + EXPECT_FALSE(msg.ParsePartialFromZeroCopyStream(&zcis)); + } +} + + +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/metadata.h b/src/google/protobuf/metadata.h index 0a6507c0677df..4e89648ee6721 100644 --- a/src/google/protobuf/metadata.h +++ b/src/google/protobuf/metadata.h @@ -28,51 +28,9 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// This header file defines an internal class that encapsulates internal message -// metadata (Unknown-field set, Arena pointer, ...) and allows its -// representation to be made more space-efficient via various optimizations. -// -// Note that this is distinct from google::protobuf::Metadata, which encapsulates -// Descriptor and Reflection pointers. - #ifndef GOOGLE_PROTOBUF_METADATA_H__ #define GOOGLE_PROTOBUF_METADATA_H__ -#include -#include - -namespace google { -namespace protobuf { -namespace internal { - -class InternalMetadataWithArena - : public InternalMetadataWithArenaBase { - public: - InternalMetadataWithArena() {} - explicit InternalMetadataWithArena(Arena* arena) - : InternalMetadataWithArenaBase(arena) {} - - void DoSwap(UnknownFieldSet* other) { - mutable_unknown_fields()->Swap(other); - } - - void DoMergeFrom(const UnknownFieldSet& other) { - mutable_unknown_fields()->MergeFrom(other); - } - - void DoClear() { - mutable_unknown_fields()->Clear(); - } - - static const UnknownFieldSet& default_instance() { - return *UnknownFieldSet::default_instance(); - } -}; - -} // namespace internal -} // namespace protobuf +// TODO(b/151117630): Remove this file and all instances where it gets imported. -} // namespace google #endif // GOOGLE_PROTOBUF_METADATA_H__ diff --git a/src/google/protobuf/metadata_lite.h b/src/google/protobuf/metadata_lite.h index 64fde0c6c698e..8e1d24edea1aa 100644 --- a/src/google/protobuf/metadata_lite.h +++ b/src/google/protobuf/metadata_lite.h @@ -31,66 +31,84 @@ #ifndef GOOGLE_PROTOBUF_METADATA_LITE_H__ #define GOOGLE_PROTOBUF_METADATA_LITE_H__ +#include #include #include -#include +#include + +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif namespace google { namespace protobuf { namespace internal { // This is the representation for messages that support arena allocation. It -// uses a tagged pointer to either store the Arena pointer, if there are no -// unknown fields, or a pointer to a block of memory with both the Arena pointer -// and the UnknownFieldSet, if there are unknown fields. This optimization -// allows for "zero-overhead" storage of the Arena pointer, relative to the -// above baseline implementation. +// uses a tagged pointer to either store the owning Arena pointer, if there are +// no unknown fields, or a pointer to a block of memory with both the owning +// Arena pointer and the UnknownFieldSet, if there are unknown fields. Besides, +// it also uses the tag to distinguish whether the owning Arena pointer is also +// used by sub-structure allocation. This optimization allows for +// "zero-overhead" storage of the Arena pointer, relative to the above baseline +// implementation. // -// The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to -// indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container -// pointer. -template -class InternalMetadataWithArenaBase { +// The tagged pointer uses the least two significant bits to disambiguate cases. +// It uses bit 0 == 0 to indicate an arena pointer and bit 0 == 1 to indicate a +// UFS+Arena-container pointer. Besides it uses bit 1 == 0 to indicate arena +// allocation and bit 1 == 1 to indicate heap allocation. +class InternalMetadata { public: - InternalMetadataWithArenaBase() : ptr_(NULL) {} - explicit InternalMetadataWithArenaBase(Arena* arena) : ptr_(arena) {} + constexpr InternalMetadata() : ptr_(nullptr) {} + explicit InternalMetadata(Arena* arena) : ptr_(arena) {} - ~InternalMetadataWithArenaBase() { + template + void Delete() { + // Note that Delete<> should be called not more than once. if (have_unknown_fields() && arena() == NULL) { - delete PtrValue(); + DeleteOutOfLineHelper(); } - ptr_ = NULL; } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE const T& unknown_fields() const { - if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { - return PtrValue()->unknown_fields; + PROTOBUF_NDEBUG_INLINE Arena* arena() const { + if (PROTOBUF_PREDICT_TRUE(!has_tag())) { + return PtrValue(); + } else if (is_heap_allocating()) { + return nullptr; } else { - return Derived::default_instance(); + return PtrValue()->arena; } } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* mutable_unknown_fields() { - if (GOOGLE_PREDICT_TRUE(have_unknown_fields())) { - return &PtrValue()->unknown_fields; - } else { - return mutable_unknown_fields_slow(); - } + PROTOBUF_NDEBUG_INLINE bool have_unknown_fields() const { + return UnknownTag() == kUnknownTagMask; } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE Arena* arena() const { - if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { - return PtrValue()->arena; + PROTOBUF_NDEBUG_INLINE void* raw_arena_ptr() const { return ptr_; } + + template + PROTOBUF_NDEBUG_INLINE const T& unknown_fields( + const T& (*default_instance)()) const { + if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) { + return PtrValue>()->unknown_fields; } else { - return PtrValue(); + return default_instance(); } } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool have_unknown_fields() const { - return PtrTag() == kTagContainer; + template + PROTOBUF_NDEBUG_INLINE T* mutable_unknown_fields() { + if (PROTOBUF_PREDICT_TRUE(have_unknown_fields())) { + return &PtrValue>()->unknown_fields; + } else { + return mutable_unknown_fields_slow(); + } } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(Derived* other) { + template + PROTOBUF_NDEBUG_INLINE void Swap(InternalMetadata* other) { // Semantics here are that we swap only the unknown fields, not the arena // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in @@ -98,97 +116,172 @@ class InternalMetadataWithArenaBase { // cannot simply swap ptr_ and then restore the arena pointers. We reuse // UFS's swap implementation instead. if (have_unknown_fields() || other->have_unknown_fields()) { - static_cast(this)->DoSwap(other->mutable_unknown_fields()); + DoSwap(other->mutable_unknown_fields()); } } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE void MergeFrom(const Derived& other) { + template + PROTOBUF_NDEBUG_INLINE void MergeFrom(const InternalMetadata& other) { if (other.have_unknown_fields()) { - static_cast(this)->DoMergeFrom(other.unknown_fields()); + DoMergeFrom(other.unknown_fields(nullptr)); } } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Clear() { + template + PROTOBUF_NDEBUG_INLINE void Clear() { if (have_unknown_fields()) { - static_cast(this)->DoClear(); + DoClear(); + } + } + + PROTOBUF_ALWAYS_INLINE Arena* GetOwningArena() const { + if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) { + return PtrValue()->arena; + } else { + return PtrValue(); } } - GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* raw_arena_ptr() const { - return ptr_; + PROTOBUF_ALWAYS_INLINE void SetOwningArena(Arena* arena) { + Arena* owning_arena = GetOwningArena(); + GOOGLE_DCHECK(arena != nullptr); // Heap can't own. + GOOGLE_DCHECK(owning_arena == nullptr); // Only heap can be owned. + + if (have_unknown_fields()) { + ContainerBase* container = PtrValue(); + container->arena = arena; + ptr_ = reinterpret_cast(reinterpret_cast(ptr_) | + kHeapAllocatingTagMask); + } else { + ptr_ = reinterpret_cast(reinterpret_cast(arena) | + kHeapAllocatingTagMask); + } } private: void* ptr_; // Tagged pointer implementation. - enum { - // ptr_ is an Arena*. - kTagArena = 0, - // ptr_ is a Container*. - kTagContainer = 1, - }; - static const intptr_t kPtrTagMask = 1; - static const intptr_t kPtrValueMask = ~kPtrTagMask; + static constexpr intptr_t kUnknownTagMask = 1; + static constexpr intptr_t kHeapAllocatingTagMask = 2; + static constexpr intptr_t kPtrTagMask = + kUnknownTagMask | kHeapAllocatingTagMask; + static constexpr intptr_t kPtrValueMask = ~kPtrTagMask; // Accessors for pointer tag and pointer value. - GOOGLE_ATTRIBUTE_ALWAYS_INLINE int PtrTag() const { + PROTOBUF_NDEBUG_INLINE int PtrTag() const { return reinterpret_cast(ptr_) & kPtrTagMask; } + PROTOBUF_ALWAYS_INLINE int UnknownTag() const { + return reinterpret_cast(ptr_) & kUnknownTagMask; + } + PROTOBUF_ALWAYS_INLINE int HeapAllocatingTag() const { + return reinterpret_cast(ptr_) & kHeapAllocatingTagMask; + } + PROTOBUF_ALWAYS_INLINE bool has_tag() const { + return (reinterpret_cast(ptr_) & kPtrTagMask) != 0; + } + PROTOBUF_ALWAYS_INLINE bool is_heap_allocating() const { + return HeapAllocatingTag() == kHeapAllocatingTagMask; + } - template U* PtrValue() const { - return reinterpret_cast( - reinterpret_cast(ptr_) & kPtrValueMask); + template + U* PtrValue() const { + return reinterpret_cast(reinterpret_cast(ptr_) & + kPtrValueMask); } - // If ptr_'s tag is kTagContainer, it points to an instance of this struct. - struct Container { - T unknown_fields; + // If ptr_'s tag is kUnknownTagMask, it points to an instance of this + // struct. + struct ContainerBase { Arena* arena; }; - GOOGLE_ATTRIBUTE_NOINLINE T* mutable_unknown_fields_slow() { + template + struct Container : public ContainerBase { + T unknown_fields; + }; + + template + PROTOBUF_NOINLINE void DeleteOutOfLineHelper() { + delete PtrValue>(); + } + + template + PROTOBUF_NOINLINE T* mutable_unknown_fields_slow() { Arena* my_arena = arena(); - Container* container = Arena::Create(my_arena); - ptr_ = reinterpret_cast( - reinterpret_cast(container) | kTagContainer); - container->arena = my_arena; + Arena* owning_arena = GetOwningArena(); + Container* container = Arena::Create>(my_arena); + // Two-step assignment works around a bug in clang's static analyzer: + // https://bugs.llvm.org/show_bug.cgi?id=34198. + intptr_t allocating_tag = + reinterpret_cast(ptr_) & kHeapAllocatingTagMask; + ptr_ = container; + ptr_ = reinterpret_cast(reinterpret_cast(ptr_) | + kUnknownTagMask | allocating_tag); + container->arena = owning_arena; return &(container->unknown_fields); } -}; -// We store unknown fields as a string right now, because there is currently no -// good interface for reading unknown fields into an ArenaString. We may want -// to revisit this to allow unknown fields to be parsed onto the Arena. -class InternalMetadataWithArenaLite - : public InternalMetadataWithArenaBase { - public: - InternalMetadataWithArenaLite() {} + // Templated functions. - explicit InternalMetadataWithArenaLite(Arena* arena) - : InternalMetadataWithArenaBase(arena) {} - - void DoSwap(string* other) { - mutable_unknown_fields()->swap(*other); + template + PROTOBUF_NOINLINE void DoClear() { + mutable_unknown_fields()->Clear(); } - void DoMergeFrom(const string& other) { - mutable_unknown_fields()->append(other); + template + PROTOBUF_NOINLINE void DoMergeFrom(const T& other) { + mutable_unknown_fields()->MergeFrom(other); } - void DoClear() { - mutable_unknown_fields()->clear(); + template + PROTOBUF_NOINLINE void DoSwap(T* other) { + mutable_unknown_fields()->Swap(other); } +}; - static const string& default_instance() { - return GetEmptyStringAlreadyInited(); +// String Template specializations. + +template <> +PROTOBUF_EXPORT void InternalMetadata::DoClear(); +template <> +PROTOBUF_EXPORT void InternalMetadata::DoMergeFrom( + const std::string& other); +template <> +PROTOBUF_EXPORT void InternalMetadata::DoSwap(std::string* other); + +// This helper RAII class is needed to efficiently parse unknown fields. We +// should only call mutable_unknown_fields if there are actual unknown fields. +// The obvious thing to just use a stack string and swap it at the end of +// the parse won't work, because the destructor of StringOutputStream needs to +// be called before we can modify the string (it check-fails). Using +// LiteUnknownFieldSetter setter(&_internal_metadata_); +// StringOutputStream stream(setter.buffer()); +// guarantees that the string is only swapped after stream is destroyed. +class PROTOBUF_EXPORT LiteUnknownFieldSetter { + public: + explicit LiteUnknownFieldSetter(InternalMetadata* metadata) + : metadata_(metadata) { + if (metadata->have_unknown_fields()) { + buffer_.swap(*metadata->mutable_unknown_fields()); + } + } + ~LiteUnknownFieldSetter() { + if (!buffer_.empty()) + metadata_->mutable_unknown_fields()->swap(buffer_); } + std::string* buffer() { return &buffer_; } + + private: + InternalMetadata* metadata_; + std::string buffer_; }; } // namespace internal } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_METADATA_LITE_H__ diff --git a/src/google/protobuf/no_field_presence_test.cc b/src/google/protobuf/no_field_presence_test.cc index bc41beec8131a..2582cfea8e620 100644 --- a/src/google/protobuf/no_field_presence_test.cc +++ b/src/google/protobuf/no_field_presence_test.cc @@ -30,8 +30,8 @@ #include -#include #include +#include #include #include #include @@ -68,7 +68,7 @@ void CheckDefaultValues( // default instance. EXPECT_EQ(41, m.optional_proto2_message().default_int32()); EXPECT_EQ(false, m.has_optional_foreign_message()); - EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_FOO, + EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::FOO, m.optional_nested_enum()); EXPECT_EQ(proto2_nofieldpresence_unittest::FOREIGN_FOO, m.optional_foreign_enum()); @@ -119,9 +119,8 @@ void FillValues(proto2_nofieldpresence_unittest::TestAllTypes* m) { m->mutable_optional_foreign_message()->set_c(43); m->mutable_optional_proto2_message()->set_optional_int32(44); m->set_optional_nested_enum( - proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_BAZ); - m->set_optional_foreign_enum( - proto2_nofieldpresence_unittest::FOREIGN_BAZ); + proto2_nofieldpresence_unittest::TestAllTypes::BAZ); + m->set_optional_foreign_enum(proto2_nofieldpresence_unittest::FOREIGN_BAZ); m->mutable_optional_lazy_message()->set_bb(45); m->add_repeated_int32(100); m->add_repeated_int64(101); @@ -142,9 +141,8 @@ void FillValues(proto2_nofieldpresence_unittest::TestAllTypes* m) { m->add_repeated_foreign_message()->set_c(47); m->add_repeated_proto2_message()->set_optional_int32(48); m->add_repeated_nested_enum( - proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_BAZ); - m->add_repeated_foreign_enum( - proto2_nofieldpresence_unittest::FOREIGN_BAZ); + proto2_nofieldpresence_unittest::TestAllTypes::BAZ); + m->add_repeated_foreign_enum(proto2_nofieldpresence_unittest::FOREIGN_BAZ); m->add_repeated_lazy_message()->set_bb(49); m->set_oneof_uint32(1); @@ -153,7 +151,7 @@ void FillValues(proto2_nofieldpresence_unittest::TestAllTypes* m) { } void CheckNonDefaultValues( -const proto2_nofieldpresence_unittest::TestAllTypes& m) { + const proto2_nofieldpresence_unittest::TestAllTypes& m) { EXPECT_EQ(100, m.optional_int32()); EXPECT_EQ(101, m.optional_int64()); EXPECT_EQ(102, m.optional_uint32()); @@ -175,7 +173,7 @@ const proto2_nofieldpresence_unittest::TestAllTypes& m) { EXPECT_EQ(43, m.optional_foreign_message().c()); EXPECT_EQ(true, m.has_optional_proto2_message()); EXPECT_EQ(44, m.optional_proto2_message().optional_int32()); - EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_BAZ, + EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::BAZ, m.optional_nested_enum()); EXPECT_EQ(proto2_nofieldpresence_unittest::FOREIGN_BAZ, m.optional_foreign_enum()); @@ -219,7 +217,7 @@ const proto2_nofieldpresence_unittest::TestAllTypes& m) { EXPECT_EQ(1, m.repeated_proto2_message_size()); EXPECT_EQ(48, m.repeated_proto2_message(0).optional_int32()); EXPECT_EQ(1, m.repeated_nested_enum_size()); - EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_BAZ, + EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::BAZ, m.repeated_nested_enum(0)); EXPECT_EQ(1, m.repeated_foreign_enum_size()); EXPECT_EQ(proto2_nofieldpresence_unittest::FOREIGN_BAZ, @@ -271,8 +269,9 @@ TEST(NoFieldPresenceTest, MessageFieldPresenceTest) { EXPECT_EQ(false, message.has_optional_lazy_message()); // Test field presence of a message field on the default instance. - EXPECT_EQ(false, proto2_nofieldpresence_unittest::TestAllTypes:: - default_instance().has_optional_nested_message()); + EXPECT_EQ(false, + proto2_nofieldpresence_unittest::TestAllTypes::default_instance() + .has_optional_nested_message()); } TEST(NoFieldPresenceTest, ReflectionHasFieldTest) { @@ -280,32 +279,34 @@ TEST(NoFieldPresenceTest, ReflectionHasFieldTest) { // behaves properly for message fields. proto2_nofieldpresence_unittest::TestAllTypes message; - const google::protobuf::Reflection* r = message.GetReflection(); - const google::protobuf::Descriptor* desc = message.GetDescriptor(); + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); // Check initial state: scalars not present (due to need to be consistent with // MergeFrom()), message fields not present, oneofs not present. for (int i = 0; i < desc->field_count(); i++) { - const google::protobuf::FieldDescriptor* field = desc->field(i); + const FieldDescriptor* field = desc->field(i); if (field->is_repeated()) continue; EXPECT_EQ(false, r->HasField(message, field)); } // Test field presence of a message field on the default instance. - const google::protobuf::FieldDescriptor* msg_field = + const FieldDescriptor* msg_field = desc->FindFieldByName("optional_nested_message"); - EXPECT_EQ(false, r->HasField( - proto2_nofieldpresence_unittest::TestAllTypes:: - default_instance(), msg_field)); + EXPECT_EQ( + false, + r->HasField( + proto2_nofieldpresence_unittest::TestAllTypes::default_instance(), + msg_field)); // Fill all fields, expect everything to report true (check oneofs below). FillValues(&message); for (int i = 0; i < desc->field_count(); i++) { - const google::protobuf::FieldDescriptor* field = desc->field(i); + const FieldDescriptor* field = desc->field(i); if (field->is_repeated() || field->containing_oneof()) { continue; } - if (field->options().ctype() != google::protobuf::FieldOptions::STRING) { + if (field->options().ctype() != FieldOptions::STRING) { continue; } EXPECT_EQ(true, r->HasField(message, field)); @@ -314,12 +315,11 @@ TEST(NoFieldPresenceTest, ReflectionHasFieldTest) { message.Clear(); // Check zero/empty-means-not-present semantics. - const google::protobuf::FieldDescriptor* field_int32 = desc->FindFieldByName( - "optional_int32"); - const google::protobuf::FieldDescriptor* field_double = desc->FindFieldByName( - "optional_double"); - const google::protobuf::FieldDescriptor* field_string = desc->FindFieldByName( - "optional_string"); + const FieldDescriptor* field_int32 = desc->FindFieldByName("optional_int32"); + const FieldDescriptor* field_double = + desc->FindFieldByName("optional_double"); + const FieldDescriptor* field_string = + desc->FindFieldByName("optional_string"); EXPECT_EQ(false, r->HasField(message, field_int32)); EXPECT_EQ(false, r->HasField(message, field_double)); @@ -344,19 +344,18 @@ TEST(NoFieldPresenceTest, ReflectionHasFieldTest) { TEST(NoFieldPresenceTest, ReflectionClearFieldTest) { proto2_nofieldpresence_unittest::TestAllTypes message; - const google::protobuf::Reflection* r = message.GetReflection(); - const google::protobuf::Descriptor* desc = message.GetDescriptor(); + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); - const google::protobuf::FieldDescriptor* field_int32 = desc->FindFieldByName( - "optional_int32"); - const google::protobuf::FieldDescriptor* field_double = desc->FindFieldByName( - "optional_double"); - const google::protobuf::FieldDescriptor* field_string = desc->FindFieldByName( - "optional_string"); - const google::protobuf::FieldDescriptor* field_message = desc->FindFieldByName( - "optional_nested_message"); - const google::protobuf::FieldDescriptor* field_lazy = desc->FindFieldByName( - "optional_lazy_message"); + const FieldDescriptor* field_int32 = desc->FindFieldByName("optional_int32"); + const FieldDescriptor* field_double = + desc->FindFieldByName("optional_double"); + const FieldDescriptor* field_string = + desc->FindFieldByName("optional_string"); + const FieldDescriptor* field_message = + desc->FindFieldByName("optional_nested_message"); + const FieldDescriptor* field_lazy = + desc->FindFieldByName("optional_lazy_message"); message.set_optional_int32(42); r->ClearField(&message, field_int32); @@ -385,17 +384,17 @@ TEST(NoFieldPresenceTest, HasFieldOneofsTest) { // check that HasField behaves properly for oneofs. proto2_nofieldpresence_unittest::TestAllTypes message; - const google::protobuf::Reflection* r = message.GetReflection(); - const google::protobuf::Descriptor* desc = message.GetDescriptor(); - const google::protobuf::FieldDescriptor* desc_oneof_uint32 = + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + const FieldDescriptor* desc_oneof_uint32 = desc->FindFieldByName("oneof_uint32"); - const google::protobuf::FieldDescriptor* desc_oneof_nested_message = + const FieldDescriptor* desc_oneof_nested_message = desc->FindFieldByName("oneof_nested_message"); - const google::protobuf::FieldDescriptor* desc_oneof_string = + const FieldDescriptor* desc_oneof_string = desc->FindFieldByName("oneof_string"); - GOOGLE_CHECK_NOTNULL(desc_oneof_uint32); - GOOGLE_CHECK_NOTNULL(desc_oneof_nested_message); - GOOGLE_CHECK_NOTNULL(desc_oneof_string); + GOOGLE_CHECK(desc_oneof_uint32 != nullptr); + GOOGLE_CHECK(desc_oneof_nested_message != nullptr); + GOOGLE_CHECK(desc_oneof_string != nullptr); EXPECT_EQ(false, r->HasField(message, desc_oneof_uint32)); EXPECT_EQ(false, r->HasField(message, desc_oneof_nested_message)); @@ -420,7 +419,7 @@ TEST(NoFieldPresenceTest, DontSerializeDefaultValuesTest) { // check that serialized data contains only non-zero numeric fields/non-empty // string/byte fields. proto2_nofieldpresence_unittest::TestAllTypes message; - string output; + std::string output; // All default values -> no output. message.SerializeToString(&output); @@ -443,7 +442,7 @@ TEST(NoFieldPresenceTest, DontSerializeDefaultValuesTest) { message.set_optional_string(""); message.set_optional_bytes(""); message.set_optional_nested_enum( - proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_FOO); // first enum entry + proto2_nofieldpresence_unittest::TestAllTypes::FOO); // first enum entry message.set_optional_foreign_enum( proto2_nofieldpresence_unittest::FOREIGN_FOO); // first enum entry @@ -498,11 +497,10 @@ TEST(NoFieldPresenceTest, LazyMessageFieldHasBit) { // Check that has-bit interaction with lazy message works (has-bit before and // after lazy decode). proto2_nofieldpresence_unittest::TestAllTypes message; - const google::protobuf::Reflection* r = message.GetReflection(); - const google::protobuf::Descriptor* desc = message.GetDescriptor(); - const google::protobuf::FieldDescriptor* field = desc->FindFieldByName( - "optional_lazy_message"); - GOOGLE_CHECK_NOTNULL(field); + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + const FieldDescriptor* field = desc->FindFieldByName("optional_lazy_message"); + GOOGLE_CHECK(field != nullptr); EXPECT_EQ(false, message.has_optional_lazy_message()); EXPECT_EQ(false, r->HasField(message, field)); @@ -513,7 +511,7 @@ TEST(NoFieldPresenceTest, LazyMessageFieldHasBit) { // Serialize and parse with a new message object so that lazy field on new // object is in unparsed state. - string output; + std::string output; message.SerializeToString(&output); proto2_nofieldpresence_unittest::TestAllTypes message2; message2.ParseFromString(output); @@ -532,7 +530,7 @@ TEST(NoFieldPresenceTest, OneofPresence) { // oneof fields still have field presence -- ensure that this goes on the wire // even though its value is the empty string. message.set_oneof_string(""); - string serialized; + std::string serialized; message.SerializeToString(&serialized); // Tag: 113 --> tag is (113 << 3) | 2 (length delimited) = 906 // varint: 0x8a 0x07 @@ -557,8 +555,9 @@ TEST(NoFieldPresenceTest, OneofPresence) { message.oneof_field_case()); message.Clear(); - message.set_oneof_enum(proto2_nofieldpresence_unittest:: - TestAllTypes_NestedEnum_FOO); // default value. + message.set_oneof_enum( + proto2_nofieldpresence_unittest::TestAllTypes::FOO); // default + // value. message.SerializeToString(&serialized); EXPECT_EQ(3, serialized.size()); EXPECT_TRUE(message.ParseFromString(serialized)); @@ -568,10 +567,9 @@ TEST(NoFieldPresenceTest, OneofPresence) { message.Clear(); message.set_oneof_string("test"); message.clear_oneof_string(); - EXPECT_EQ(0, message.ByteSize()); + EXPECT_EQ(0, message.ByteSizeLong()); } } // namespace } // namespace protobuf - } // namespace google diff --git a/src/google/protobuf/package_info.h b/src/google/protobuf/package_info.h index 935e96396dc3f..2b61679af5aca 100644 --- a/src/google/protobuf/package_info.h +++ b/src/google/protobuf/package_info.h @@ -36,8 +36,6 @@ // It is not compiled into anything, but it may be read by an automated // documentation generator. -namespace google { - // Core components of the Protocol Buffers runtime library. // // The files in this package represent the core of the Protocol Buffer @@ -60,5 +58,9 @@ namespace google { // The implementation does contain some "const" methods which actually modify // the object behind the scenes -- e.g., to cache results -- but in these cases // mutex locking is used to make the access thread-safe. -namespace protobuf {} +namespace google { +namespace protobuf { +// TODO(gerbens) remove this comment, we need it to prevent clang-format +// from combining the brackets. Which would mess with extract script +} // namespace protobuf } // namespace google diff --git a/src/google/protobuf/parse_context.cc b/src/google/protobuf/parse_context.cc new file mode 100644 index 0000000000000..8143af8d8bcf8 --- /dev/null +++ b/src/google/protobuf/parse_context.cc @@ -0,0 +1,595 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace google { +namespace protobuf { +namespace internal { + +namespace { + +// Only call if at start of tag. +bool ParseEndsInSlopRegion(const char* begin, int overrun, int depth) { + constexpr int kSlopBytes = EpsCopyInputStream::kSlopBytes; + GOOGLE_DCHECK(overrun >= 0); + GOOGLE_DCHECK(overrun <= kSlopBytes); + auto ptr = begin + overrun; + auto end = begin + kSlopBytes; + while (ptr < end) { + uint32 tag; + ptr = ReadTag(ptr, &tag); + if (ptr == nullptr || ptr > end) return false; + // ending on 0 tag is allowed and is the major reason for the necessity of + // this function. + if (tag == 0) return true; + switch (tag & 7) { + case 0: { // Varint + uint64 val; + ptr = VarintParse(ptr, &val); + if (ptr == nullptr) return false; + break; + } + case 1: { // fixed64 + ptr += 8; + break; + } + case 2: { // len delim + int32 size = ReadSize(&ptr); + if (ptr == nullptr || size > end - ptr) return false; + ptr += size; + break; + } + case 3: { // start group + depth++; + break; + } + case 4: { // end group + if (--depth < 0) return true; // We exit early + break; + } + case 5: { // fixed32 + ptr += 4; + break; + } + default: + return false; // Unknown wireformat + } + } + return false; +} + +} // namespace + +const char* EpsCopyInputStream::NextBuffer(int overrun, int depth) { + if (next_chunk_ == nullptr) return nullptr; // We've reached end of stream. + if (next_chunk_ != buffer_) { + GOOGLE_DCHECK(size_ > kSlopBytes); + // The chunk is large enough to be used directly + buffer_end_ = next_chunk_ + size_ - kSlopBytes; + auto res = next_chunk_; + next_chunk_ = buffer_; + if (aliasing_ == kOnPatch) aliasing_ = kNoDelta; + return res; + } + // Move the slop bytes of previous buffer to start of the patch buffer. + // Note we must use memmove because the previous buffer could be part of + // buffer_. + std::memmove(buffer_, buffer_end_, kSlopBytes); + if (overall_limit_ > 0 && + (depth < 0 || !ParseEndsInSlopRegion(buffer_, overrun, depth))) { + const void* data; + // ZeroCopyInputStream indicates Next may return 0 size buffers. Hence + // we loop. + while (StreamNext(&data)) { + if (size_ > kSlopBytes) { + // We got a large chunk + std::memcpy(buffer_ + kSlopBytes, data, kSlopBytes); + next_chunk_ = static_cast(data); + buffer_end_ = buffer_ + kSlopBytes; + if (aliasing_ >= kNoDelta) aliasing_ = kOnPatch; + return buffer_; + } else if (size_ > 0) { + std::memcpy(buffer_ + kSlopBytes, data, size_); + next_chunk_ = buffer_; + buffer_end_ = buffer_ + size_; + if (aliasing_ >= kNoDelta) aliasing_ = kOnPatch; + return buffer_; + } + GOOGLE_DCHECK(size_ == 0) << size_; + } + overall_limit_ = 0; // Next failed, no more needs for next + } + // End of stream or array + if (aliasing_ == kNoDelta) { + // If there is no more block and aliasing is true, the previous block + // is still valid and we can alias. We have users relying on string_view's + // obtained from protos to outlive the proto, when the parse was from an + // array. This guarantees string_view's are always aliased if parsed from + // an array. + aliasing_ = reinterpret_cast(buffer_end_) - + reinterpret_cast(buffer_); + } + next_chunk_ = nullptr; + buffer_end_ = buffer_ + kSlopBytes; + size_ = 0; + return buffer_; +} + +const char* EpsCopyInputStream::Next() { + GOOGLE_DCHECK(limit_ > kSlopBytes); + auto p = NextBuffer(0 /* immaterial */, -1); + if (p == nullptr) { + limit_end_ = buffer_end_; + // Distinguish ending on a pushed limit or ending on end-of-stream. + SetEndOfStream(); + return nullptr; + } + limit_ -= buffer_end_ - p; // Adjust limit_ relative to new anchor + limit_end_ = buffer_end_ + std::min(0, limit_); + return p; +} + +std::pair EpsCopyInputStream::DoneFallback(int overrun, + int depth) { + // Did we exceeded the limit (parse error). + if (PROTOBUF_PREDICT_FALSE(overrun > limit_)) return {nullptr, true}; + GOOGLE_DCHECK(overrun != limit_); // Guaranteed by caller. + GOOGLE_DCHECK(overrun < limit_); // Follows from above + // TODO(gerbens) Instead of this dcheck we could just assign, and remove + // updating the limit_end from PopLimit, ie. + // limit_end_ = buffer_end_ + (std::min)(0, limit_); + // if (ptr < limit_end_) return {ptr, false}; + GOOGLE_DCHECK(limit_end_ == buffer_end_ + (std::min)(0, limit_)); + // At this point we know the following assertion holds. + GOOGLE_DCHECK(limit_ > 0); + GOOGLE_DCHECK(limit_end_ == buffer_end_); // because limit_ > 0 + const char* p; + do { + // We are past the end of buffer_end_, in the slop region. + GOOGLE_DCHECK(overrun >= 0); + p = NextBuffer(overrun, depth); + if (p == nullptr) { + // We are at the end of the stream + if (PROTOBUF_PREDICT_FALSE(overrun != 0)) return {nullptr, true}; + GOOGLE_DCHECK(limit_ > 0); + limit_end_ = buffer_end_; + // Distinguish ending on a pushed limit or ending on end-of-stream. + SetEndOfStream(); + return {buffer_end_, true}; + } + limit_ -= buffer_end_ - p; // Adjust limit_ relative to new anchor + p += overrun; + overrun = p - buffer_end_; + } while (overrun >= 0); + limit_end_ = buffer_end_ + std::min(0, limit_); + return {p, false}; +} + +const char* EpsCopyInputStream::SkipFallback(const char* ptr, int size) { + return AppendSize(ptr, size, [](const char* p, int s) {}); +} + +const char* EpsCopyInputStream::ReadStringFallback(const char* ptr, int size, + std::string* str) { + str->clear(); + if (PROTOBUF_PREDICT_TRUE(size <= buffer_end_ - ptr + limit_)) { + // Reserve the string up to a static safe size. If strings are bigger than + // this we proceed by growing the string as needed. This protects against + // malicious payloads making protobuf hold on to a lot of memory. + str->reserve(str->size() + std::min(size, kSafeStringSize)); + } + return AppendSize(ptr, size, + [str](const char* p, int s) { str->append(p, s); }); +} + +const char* EpsCopyInputStream::AppendStringFallback(const char* ptr, int size, + std::string* str) { + if (PROTOBUF_PREDICT_TRUE(size <= buffer_end_ - ptr + limit_)) { + // Reserve the string up to a static safe size. If strings are bigger than + // this we proceed by growing the string as needed. This protects against + // malicious payloads making protobuf hold on to a lot of memory. + str->reserve(str->size() + std::min(size, kSafeStringSize)); + } + return AppendSize(ptr, size, + [str](const char* p, int s) { str->append(p, s); }); +} + + +template +const char* EpsCopyInputStream::ReadRepeatedFixed(const char* ptr, + Tag expected_tag, + RepeatedField* out) { + do { + out->Add(UnalignedLoad(ptr)); + ptr += sizeof(T); + if (PROTOBUF_PREDICT_FALSE(ptr >= limit_end_)) return ptr; + } while (UnalignedLoad(ptr) == expected_tag&& ptr += sizeof(Tag)); + return ptr; +} + +template +void byteswap(void* p); +template <> +void byteswap<1>(void* p) {} +template <> +void byteswap<4>(void* p) { + *static_cast(p) = bswap_32(*static_cast(p)); +} +template <> +void byteswap<8>(void* p) { + *static_cast(p) = bswap_64(*static_cast(p)); +} + +template +const char* EpsCopyInputStream::ReadPackedFixed(const char* ptr, int size, + RepeatedField* out) { + int nbytes = buffer_end_ + kSlopBytes - ptr; + while (size > nbytes) { + int num = nbytes / sizeof(T); + int old_entries = out->size(); + out->Reserve(old_entries + num); + int block_size = num * sizeof(T); + auto dst = out->AddNAlreadyReserved(num); +#ifdef PROTOBUF_LITTLE_ENDIAN + std::memcpy(dst, ptr, block_size); +#else + for (int i = 0; i < num; i++) + dst[i] = UnalignedLoad(ptr + i * sizeof(T)); +#endif + size -= block_size; + if (limit_ <= kSlopBytes) return nullptr; + ptr = Next(); + if (ptr == nullptr) return nullptr; + ptr += kSlopBytes - (nbytes - block_size); + nbytes = buffer_end_ + kSlopBytes - ptr; + } + int num = size / sizeof(T); + int old_entries = out->size(); + out->Reserve(old_entries + num); + int block_size = num * sizeof(T); + auto dst = out->AddNAlreadyReserved(num); +#ifdef PROTOBUF_LITTLE_ENDIAN + std::memcpy(dst, ptr, block_size); +#else + for (int i = 0; i < num; i++) dst[i] = UnalignedLoad(ptr + i * sizeof(T)); +#endif + ptr += block_size; + if (size != block_size) return nullptr; + return ptr; +} + +const char* EpsCopyInputStream::InitFrom(io::ZeroCopyInputStream* zcis) { + zcis_ = zcis; + const void* data; + int size; + limit_ = INT_MAX; + if (zcis->Next(&data, &size)) { + overall_limit_ -= size; + if (size > kSlopBytes) { + auto ptr = static_cast(data); + limit_ -= size - kSlopBytes; + limit_end_ = buffer_end_ = ptr + size - kSlopBytes; + next_chunk_ = buffer_; + if (aliasing_ == kOnPatch) aliasing_ = kNoDelta; + return ptr; + } else { + limit_end_ = buffer_end_ = buffer_ + kSlopBytes; + next_chunk_ = buffer_; + auto ptr = buffer_ + 2 * kSlopBytes - size; + std::memcpy(ptr, data, size); + return ptr; + } + } + overall_limit_ = 0; + next_chunk_ = nullptr; + size_ = 0; + limit_end_ = buffer_end_ = buffer_; + return buffer_; +} + +const char* ParseContext::ParseMessage(MessageLite* msg, const char* ptr) { + return ParseMessage(msg, ptr); +} +const char* ParseContext::ParseMessage(Message* msg, const char* ptr) { + // Use reinterptret case to prevent inclusion of non lite header + return ParseMessage(reinterpret_cast(msg), ptr); +} + +inline void WriteVarint(uint64 val, std::string* s) { + while (val >= 128) { + uint8 c = val | 0x80; + s->push_back(c); + val >>= 7; + } + s->push_back(val); +} + +void WriteVarint(uint32 num, uint64 val, std::string* s) { + WriteVarint(num << 3, s); + WriteVarint(val, s); +} + +void WriteLengthDelimited(uint32 num, StringPiece val, std::string* s) { + WriteVarint((num << 3) + 2, s); + WriteVarint(val.size(), s); + s->append(val.data(), val.size()); +} + +std::pair VarintParseSlow32(const char* p, uint32 res) { + for (std::uint32_t i = 2; i < 5; i++) { + uint32 byte = static_cast(p[i]); + res += (byte - 1) << (7 * i); + if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + return {p + i + 1, res}; + } + } + // Accept >5 bytes + for (std::uint32_t i = 5; i < 10; i++) { + uint32 byte = static_cast(p[i]); + if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + return {p + i + 1, res}; + } + } + return {nullptr, 0}; +} + +std::pair VarintParseSlow64(const char* p, uint32 res32) { + uint64 res = res32; + for (std::uint32_t i = 2; i < 10; i++) { + uint64 byte = static_cast(p[i]); + res += (byte - 1) << (7 * i); + if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + return {p + i + 1, res}; + } + } + return {nullptr, 0}; +} + +std::pair ReadTagFallback(const char* p, uint32 res) { + for (std::uint32_t i = 2; i < 5; i++) { + uint32 byte = static_cast(p[i]); + res += (byte - 1) << (7 * i); + if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + return {p + i + 1, res}; + } + } + return {nullptr, 0}; +} + +std::pair ReadSizeFallback(const char* p, uint32 res) { + for (std::uint32_t i = 1; i < 4; i++) { + uint32 byte = static_cast(p[i]); + res += (byte - 1) << (7 * i); + if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + return {p + i + 1, res}; + } + } + std::uint32_t byte = static_cast(p[4]); + if (PROTOBUF_PREDICT_FALSE(byte >= 8)) return {nullptr, 0}; // size >= 2gb + res += (byte - 1) << 28; + // Protect against sign integer overflow in PushLimit. Limits are relative + // to buffer ends and ptr could potential be kSlopBytes beyond a buffer end. + // To protect against overflow we reject limits absurdly close to INT_MAX. + if (PROTOBUF_PREDICT_FALSE(res > INT_MAX - ParseContext::kSlopBytes)) { + return {nullptr, 0}; + } + return {p + 5, res}; +} + +const char* StringParser(const char* begin, const char* end, void* object, + ParseContext*) { + auto str = static_cast(object); + str->append(begin, end - begin); + return end; +} + +// Defined in wire_format_lite.cc +void PrintUTF8ErrorLog(const char* field_name, const char* operation_str, + bool emit_stacktrace); + +bool VerifyUTF8(StringPiece str, const char* field_name) { + if (!IsStructurallyValidUTF8(str)) { + PrintUTF8ErrorLog(field_name, "parsing", false); + return false; + } + return true; +} + +const char* InlineGreedyStringParser(std::string* s, const char* ptr, + ParseContext* ctx) { + int size = ReadSize(&ptr); + if (!ptr) return nullptr; + return ctx->ReadString(ptr, size, s); +} + + +template +const char* VarintParser(void* object, const char* ptr, ParseContext* ctx) { + return ctx->ReadPackedVarint(ptr, [object](uint64 varint) { + T val; + if (sign) { + if (sizeof(T) == 8) { + val = WireFormatLite::ZigZagDecode64(varint); + } else { + val = WireFormatLite::ZigZagDecode32(varint); + } + } else { + val = varint; + } + static_cast*>(object)->Add(val); + }); +} + +const char* PackedInt32Parser(void* object, const char* ptr, + ParseContext* ctx) { + return VarintParser(object, ptr, ctx); +} +const char* PackedUInt32Parser(void* object, const char* ptr, + ParseContext* ctx) { + return VarintParser(object, ptr, ctx); +} +const char* PackedInt64Parser(void* object, const char* ptr, + ParseContext* ctx) { + return VarintParser(object, ptr, ctx); +} +const char* PackedUInt64Parser(void* object, const char* ptr, + ParseContext* ctx) { + return VarintParser(object, ptr, ctx); +} +const char* PackedSInt32Parser(void* object, const char* ptr, + ParseContext* ctx) { + return VarintParser(object, ptr, ctx); +} +const char* PackedSInt64Parser(void* object, const char* ptr, + ParseContext* ctx) { + return VarintParser(object, ptr, ctx); +} + +const char* PackedEnumParser(void* object, const char* ptr, ParseContext* ctx) { + return VarintParser(object, ptr, ctx); +} + +const char* PackedBoolParser(void* object, const char* ptr, ParseContext* ctx) { + return VarintParser(object, ptr, ctx); +} + +template +const char* FixedParser(void* object, const char* ptr, ParseContext* ctx) { + int size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + return ctx->ReadPackedFixed(ptr, size, + static_cast*>(object)); +} + +const char* PackedFixed32Parser(void* object, const char* ptr, + ParseContext* ctx) { + return FixedParser(object, ptr, ctx); +} +const char* PackedSFixed32Parser(void* object, const char* ptr, + ParseContext* ctx) { + return FixedParser(object, ptr, ctx); +} +const char* PackedFixed64Parser(void* object, const char* ptr, + ParseContext* ctx) { + return FixedParser(object, ptr, ctx); +} +const char* PackedSFixed64Parser(void* object, const char* ptr, + ParseContext* ctx) { + return FixedParser(object, ptr, ctx); +} +const char* PackedFloatParser(void* object, const char* ptr, + ParseContext* ctx) { + return FixedParser(object, ptr, ctx); +} +const char* PackedDoubleParser(void* object, const char* ptr, + ParseContext* ctx) { + return FixedParser(object, ptr, ctx); +} + +class UnknownFieldLiteParserHelper { + public: + explicit UnknownFieldLiteParserHelper(std::string* unknown) + : unknown_(unknown) {} + + void AddVarint(uint32 num, uint64 value) { + if (unknown_ == nullptr) return; + WriteVarint(num * 8, unknown_); + WriteVarint(value, unknown_); + } + void AddFixed64(uint32 num, uint64 value) { + if (unknown_ == nullptr) return; + WriteVarint(num * 8 + 1, unknown_); + char buffer[8]; + io::CodedOutputStream::WriteLittleEndian64ToArray( + value, reinterpret_cast(buffer)); + unknown_->append(buffer, 8); + } + const char* ParseLengthDelimited(uint32 num, const char* ptr, + ParseContext* ctx) { + int size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + if (unknown_ == nullptr) return ctx->Skip(ptr, size); + WriteVarint(num * 8 + 2, unknown_); + WriteVarint(size, unknown_); + return ctx->AppendString(ptr, size, unknown_); + } + const char* ParseGroup(uint32 num, const char* ptr, ParseContext* ctx) { + if (unknown_) WriteVarint(num * 8 + 3, unknown_); + ptr = ctx->ParseGroup(this, ptr, num * 8 + 3); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + if (unknown_) WriteVarint(num * 8 + 4, unknown_); + return ptr; + } + void AddFixed32(uint32 num, uint32 value) { + if (unknown_ == nullptr) return; + WriteVarint(num * 8 + 5, unknown_); + char buffer[4]; + io::CodedOutputStream::WriteLittleEndian32ToArray( + value, reinterpret_cast(buffer)); + unknown_->append(buffer, 4); + } + + const char* _InternalParse(const char* ptr, ParseContext* ctx) { + return WireFormatParser(*this, ptr, ctx); + } + + private: + std::string* unknown_; +}; + +const char* UnknownGroupLiteParse(std::string* unknown, const char* ptr, + ParseContext* ctx) { + UnknownFieldLiteParserHelper field_parser(unknown); + return WireFormatParser(field_parser, ptr, ctx); +} + +const char* UnknownFieldParse(uint32 tag, std::string* unknown, const char* ptr, + ParseContext* ctx) { + UnknownFieldLiteParserHelper field_parser(unknown); + return FieldParser(tag, field_parser, ptr, ctx); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include diff --git a/src/google/protobuf/parse_context.h b/src/google/protobuf/parse_context.h new file mode 100644 index 0000000000000..7966d99d577b9 --- /dev/null +++ b/src/google/protobuf/parse_context.h @@ -0,0 +1,869 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_PARSE_CONTEXT_H__ +#define GOOGLE_PROTOBUF_PARSE_CONTEXT_H__ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace google { +namespace protobuf { + +class UnknownFieldSet; +class DescriptorPool; +class MessageFactory; + +namespace internal { + +// Template code below needs to know about the existence of these functions. +PROTOBUF_EXPORT void WriteVarint(uint32 num, uint64 val, std::string* s); +PROTOBUF_EXPORT void WriteLengthDelimited(uint32 num, StringPiece val, + std::string* s); +// Inline because it is just forwarding to s->WriteVarint +inline void WriteVarint(uint32 num, uint64 val, UnknownFieldSet* s); +inline void WriteLengthDelimited(uint32 num, StringPiece val, + UnknownFieldSet* s); + + +// The basic abstraction the parser is designed for is a slight modification +// of the ZeroCopyInputStream (ZCIS) abstraction. A ZCIS presents a serialized +// stream as a series of buffers that concatenate to the full stream. +// Pictorially a ZCIS presents a stream in chunks like so +// [---------------------------------------------------------------] +// [---------------------] chunk 1 +// [----------------------------] chunk 2 +// chunk 3 [--------------] +// +// Where the '-' represent the bytes which are vertically lined up with the +// bytes of the stream. The proto parser requires its input to be presented +// similarly with the extra +// property that each chunk has kSlopBytes past its end that overlaps with the +// first kSlopBytes of the next chunk, or if there is no next chunk at least its +// still valid to read those bytes. Again, pictorially, we now have +// +// [---------------------------------------------------------------] +// [-------------------....] chunk 1 +// [------------------------....] chunk 2 +// chunk 3 [------------------..**] +// chunk 4 [--****] +// Here '-' mean the bytes of the stream or chunk and '.' means bytes past the +// chunk that match up with the start of the next chunk. Above each chunk has +// 4 '.' after the chunk. In the case these 'overflow' bytes represents bytes +// past the stream, indicated by '*' above, their values are unspecified. It is +// still legal to read them (ie. should not segfault). Reading past the +// end should be detected by the user and indicated as an error. +// +// The reason for this, admittedly, unconventional invariant is to ruthlessly +// optimize the protobuf parser. Having an overlap helps in two important ways. +// Firstly it alleviates having to performing bounds checks if a piece of code +// is guaranteed to not read more than kSlopBytes. Secondly, and more +// importantly, the protobuf wireformat is such that reading a key/value pair is +// always less than 16 bytes. This removes the need to change to next buffer in +// the middle of reading primitive values. Hence there is no need to store and +// load the current position. + +class PROTOBUF_EXPORT EpsCopyInputStream { + public: + enum { kSlopBytes = 16, kMaxCordBytesToCopy = 512 }; + + explicit EpsCopyInputStream(bool enable_aliasing) + : aliasing_(enable_aliasing ? kOnPatch : kNoAliasing) {} + + void BackUp(const char* ptr) { + GOOGLE_DCHECK(ptr <= buffer_end_ + kSlopBytes); + int count; + if (next_chunk_ == buffer_) { + count = static_cast(buffer_end_ + kSlopBytes - ptr); + } else { + count = size_ + static_cast(buffer_end_ - ptr); + } + if (count > 0) StreamBackUp(count); + } + + // If return value is negative it's an error + PROTOBUF_MUST_USE_RESULT int PushLimit(const char* ptr, int limit) { + GOOGLE_DCHECK(limit >= 0 && limit <= INT_MAX - kSlopBytes); + // This add is safe due to the invariant above, because + // ptr - buffer_end_ <= kSlopBytes. + limit += static_cast(ptr - buffer_end_); + limit_end_ = buffer_end_ + (std::min)(0, limit); + auto old_limit = limit_; + limit_ = limit; + return old_limit - limit; + } + + PROTOBUF_MUST_USE_RESULT bool PopLimit(int delta) { + if (PROTOBUF_PREDICT_FALSE(!EndedAtLimit())) return false; + limit_ = limit_ + delta; + // TODO(gerbens) We could remove this line and hoist the code to + // DoneFallback. Study the perf/bin-size effects. + limit_end_ = buffer_end_ + (std::min)(0, limit_); + return true; + } + + PROTOBUF_MUST_USE_RESULT const char* Skip(const char* ptr, int size) { + if (size <= buffer_end_ + kSlopBytes - ptr) { + return ptr + size; + } + return SkipFallback(ptr, size); + } + PROTOBUF_MUST_USE_RESULT const char* ReadString(const char* ptr, int size, + std::string* s) { + if (size <= buffer_end_ + kSlopBytes - ptr) { + s->assign(ptr, size); + return ptr + size; + } + return ReadStringFallback(ptr, size, s); + } + PROTOBUF_MUST_USE_RESULT const char* AppendString(const char* ptr, int size, + std::string* s) { + if (size <= buffer_end_ + kSlopBytes - ptr) { + s->append(ptr, size); + return ptr + size; + } + return AppendStringFallback(ptr, size, s); + } + + template + PROTOBUF_MUST_USE_RESULT const char* ReadRepeatedFixed(const char* ptr, + Tag expected_tag, + RepeatedField* out); + + template + PROTOBUF_MUST_USE_RESULT const char* ReadPackedFixed(const char* ptr, + int size, + RepeatedField* out); + template + PROTOBUF_MUST_USE_RESULT const char* ReadPackedVarint(const char* ptr, + Add add); + + uint32 LastTag() const { return last_tag_minus_1_ + 1; } + bool ConsumeEndGroup(uint32 start_tag) { + bool res = last_tag_minus_1_ == start_tag; + last_tag_minus_1_ = 0; + return res; + } + bool EndedAtLimit() const { return last_tag_minus_1_ == 0; } + bool EndedAtEndOfStream() const { return last_tag_minus_1_ == 1; } + void SetLastTag(uint32 tag) { last_tag_minus_1_ = tag - 1; } + void SetEndOfStream() { last_tag_minus_1_ = 1; } + bool IsExceedingLimit(const char* ptr) { + return ptr > limit_end_ && + (next_chunk_ == nullptr || ptr - buffer_end_ > limit_); + } + int BytesUntilLimit(const char* ptr) const { + return limit_ + static_cast(buffer_end_ - ptr); + } + // Returns true if more data is available, if false is returned one has to + // call Done for further checks. + bool DataAvailable(const char* ptr) { return ptr < limit_end_; } + + protected: + // Returns true is limit (either an explicit limit or end of stream) is + // reached. It aligns *ptr across buffer seams. + // If limit is exceeded it returns true and ptr is set to null. + bool DoneWithCheck(const char** ptr, int d) { + GOOGLE_DCHECK(*ptr); + if (PROTOBUF_PREDICT_TRUE(*ptr < limit_end_)) return false; + int overrun = static_cast(*ptr - buffer_end_); + GOOGLE_DCHECK_LE(overrun, kSlopBytes); // Guaranteed by parse loop. + if (overrun == + limit_) { // No need to flip buffers if we ended on a limit. + // If we actually overrun the buffer and next_chunk_ is null. It means + // the stream ended and we passed the stream end. + if (overrun > 0 && next_chunk_ == nullptr) *ptr = nullptr; + return true; + } + auto res = DoneFallback(overrun, d); + *ptr = res.first; + return res.second; + } + + const char* InitFrom(StringPiece flat) { + overall_limit_ = 0; + if (flat.size() > kSlopBytes) { + limit_ = kSlopBytes; + limit_end_ = buffer_end_ = flat.data() + flat.size() - kSlopBytes; + next_chunk_ = buffer_; + if (aliasing_ == kOnPatch) aliasing_ = kNoDelta; + return flat.data(); + } else { + std::memcpy(buffer_, flat.data(), flat.size()); + limit_ = 0; + limit_end_ = buffer_end_ = buffer_ + flat.size(); + next_chunk_ = nullptr; + if (aliasing_ == kOnPatch) { + aliasing_ = reinterpret_cast(flat.data()) - + reinterpret_cast(buffer_); + } + return buffer_; + } + } + + const char* InitFrom(io::ZeroCopyInputStream* zcis); + + const char* InitFrom(io::ZeroCopyInputStream* zcis, int limit) { + if (limit == -1) return InitFrom(zcis); + overall_limit_ = limit; + auto res = InitFrom(zcis); + limit_ = limit - static_cast(buffer_end_ - res); + limit_end_ = buffer_end_ + (std::min)(0, limit_); + return res; + } + + private: + const char* limit_end_; // buffer_end_ + min(limit_, 0) + const char* buffer_end_; + const char* next_chunk_; + int size_; + int limit_; // relative to buffer_end_; + io::ZeroCopyInputStream* zcis_ = nullptr; + char buffer_[2 * kSlopBytes] = {}; + enum { kNoAliasing = 0, kOnPatch = 1, kNoDelta = 2 }; + std::uintptr_t aliasing_ = kNoAliasing; + // This variable is used to communicate how the parse ended, in order to + // completely verify the parsed data. A wire-format parse can end because of + // one of the following conditions: + // 1) A parse can end on a pushed limit. + // 2) A parse can end on End Of Stream (EOS). + // 3) A parse can end on 0 tag (only valid for toplevel message). + // 4) A parse can end on an end-group tag. + // This variable should always be set to 0, which indicates case 1. If the + // parse terminated due to EOS (case 2), it's set to 1. In case the parse + // ended due to a terminating tag (case 3 and 4) it's set to (tag - 1). + // This var doesn't really belong in EpsCopyInputStream and should be part of + // the ParseContext, but case 2 is most easily and optimally implemented in + // DoneFallback. + uint32 last_tag_minus_1_ = 0; + int overall_limit_ = INT_MAX; // Overall limit independent of pushed limits. + // Pretty random large number that seems like a safe allocation on most + // systems. TODO(gerbens) do we need to set this as build flag? + enum { kSafeStringSize = 50000000 }; + + // Advances to next buffer chunk returns a pointer to the same logical place + // in the stream as set by overrun. Overrun indicates the position in the slop + // region the parse was left (0 <= overrun <= kSlopBytes). Returns true if at + // limit, at which point the returned pointer maybe null if there was an + // error. The invariant of this function is that it's guaranteed that + // kSlopBytes bytes can be accessed from the returned ptr. This function might + // advance more buffers than one in the underlying ZeroCopyInputStream. + std::pair DoneFallback(int overrun, int depth); + // Advances to the next buffer, at most one call to Next() on the underlying + // ZeroCopyInputStream is made. This function DOES NOT match the returned + // pointer to where in the slop region the parse ends, hence no overrun + // parameter. This is useful for string operations where you always copy + // to the end of the buffer (including the slop region). + const char* Next(); + // overrun is the location in the slop region the stream currently is + // (0 <= overrun <= kSlopBytes). To prevent flipping to the next buffer of + // the ZeroCopyInputStream in the case the parse will end in the last + // kSlopBytes of the current buffer. depth is the current depth of nested + // groups (or negative if the use case does not need careful tracking). + inline const char* NextBuffer(int overrun, int depth); + const char* SkipFallback(const char* ptr, int size); + const char* AppendStringFallback(const char* ptr, int size, std::string* str); + const char* ReadStringFallback(const char* ptr, int size, std::string* str); + bool StreamNext(const void** data) { + bool res = zcis_->Next(data, &size_); + if (res) overall_limit_ -= size_; + return res; + } + void StreamBackUp(int count) { + zcis_->BackUp(count); + overall_limit_ += count; + } + + template + const char* AppendSize(const char* ptr, int size, const A& append) { + int chunk_size = buffer_end_ + kSlopBytes - ptr; + do { + GOOGLE_DCHECK(size > chunk_size); + if (next_chunk_ == nullptr) return nullptr; + append(ptr, chunk_size); + ptr += chunk_size; + size -= chunk_size; + // TODO(gerbens) Next calls NextBuffer which generates buffers with + // overlap and thus incurs cost of copying the slop regions. This is not + // necessary for reading strings. We should just call Next buffers. + if (limit_ <= kSlopBytes) return nullptr; + ptr = Next(); + if (ptr == nullptr) return nullptr; // passed the limit + ptr += kSlopBytes; + chunk_size = buffer_end_ + kSlopBytes - ptr; + } while (size > chunk_size); + append(ptr, size); + return ptr + size; + } + + // AppendUntilEnd appends data until a limit (either a PushLimit or end of + // stream. Normal payloads are from length delimited fields which have an + // explicit size. Reading until limit only comes when the string takes + // the place of a protobuf, ie RawMessage/StringRawMessage, lazy fields and + // implicit weak messages. We keep these methods private and friend them. + template + const char* AppendUntilEnd(const char* ptr, const A& append) { + if (ptr - buffer_end_ > limit_) return nullptr; + while (limit_ > kSlopBytes) { + size_t chunk_size = buffer_end_ + kSlopBytes - ptr; + GOOGLE_DCHECK_GE(chunk_size, static_cast(0)); + append(ptr, chunk_size); + ptr = Next(); + if (ptr == nullptr) return limit_end_; + ptr += kSlopBytes; + } + auto end = buffer_end_ + limit_; + GOOGLE_DCHECK(end >= ptr); + append(ptr, end - ptr); + return end; + } + + PROTOBUF_MUST_USE_RESULT const char* AppendString(const char* ptr, + std::string* str) { + return AppendUntilEnd( + ptr, [str](const char* p, ptrdiff_t s) { str->append(p, s); }); + } + friend class ImplicitWeakMessage; +}; + +// ParseContext holds all data that is global to the entire parse. Most +// importantly it contains the input stream, but also recursion depth and also +// stores the end group tag, in case a parser ended on a endgroup, to verify +// matching start/end group tags. +class PROTOBUF_EXPORT ParseContext : public EpsCopyInputStream { + public: + struct Data { + const DescriptorPool* pool = nullptr; + MessageFactory* factory = nullptr; + }; + + template + ParseContext(int depth, bool aliasing, const char** start, T&&... args) + : EpsCopyInputStream(aliasing), depth_(depth) { + *start = InitFrom(std::forward(args)...); + } + + void TrackCorrectEnding() { group_depth_ = 0; } + + bool Done(const char** ptr) { return DoneWithCheck(ptr, group_depth_); } + + int depth() const { return depth_; } + + Data& data() { return data_; } + const Data& data() const { return data_; } + + template + PROTOBUF_MUST_USE_RESULT const char* ParseMessage(T* msg, const char* ptr); + // We outline when the type is generic and we go through a virtual + const char* ParseMessage(MessageLite* msg, const char* ptr); + const char* ParseMessage(Message* msg, const char* ptr); + + template + PROTOBUF_MUST_USE_RESULT PROTOBUF_NDEBUG_INLINE const char* ParseGroup( + T* msg, const char* ptr, uint32 tag) { + if (--depth_ < 0) return nullptr; + group_depth_++; + ptr = msg->_InternalParse(ptr, this); + group_depth_--; + depth_++; + if (PROTOBUF_PREDICT_FALSE(!ConsumeEndGroup(tag))) return nullptr; + return ptr; + } + + private: + // The context keeps an internal stack to keep track of the recursive + // part of the parse state. + // Current depth of the active parser, depth counts down. + // This is used to limit recursion depth (to prevent overflow on malicious + // data), but is also used to index in stack_ to store the current state. + int depth_; + // Unfortunately necessary for the fringe case of ending on 0 or end-group tag + // in the last kSlopBytes of a ZeroCopyInputStream chunk. + int group_depth_ = INT_MIN; + Data data_; +}; + +template +bool ExpectTag(const char* ptr) { + if (tag < 128) { + return *ptr == static_cast(tag); + } else { + static_assert(tag < 128 * 128, "We only expect tags for 1 or 2 bytes"); + char buf[2] = {static_cast(tag | 0x80), static_cast(tag >> 7)}; + return std::memcmp(ptr, buf, 2) == 0; + } +} + +template +struct EndianHelper; + +template <> +struct EndianHelper<1> { + static uint8 Load(const void* p) { return *static_cast(p); } +}; + +template <> +struct EndianHelper<2> { + static uint16 Load(const void* p) { + uint16 tmp; + std::memcpy(&tmp, p, 2); +#ifndef PROTOBUF_LITTLE_ENDIAN + tmp = bswap_16(tmp); +#endif + return tmp; + } +}; + +template <> +struct EndianHelper<4> { + static uint32 Load(const void* p) { + uint32 tmp; + std::memcpy(&tmp, p, 4); +#ifndef PROTOBUF_LITTLE_ENDIAN + tmp = bswap_32(tmp); +#endif + return tmp; + } +}; + +template <> +struct EndianHelper<8> { + static uint64 Load(const void* p) { + uint64 tmp; + std::memcpy(&tmp, p, 8); +#ifndef PROTOBUF_LITTLE_ENDIAN + tmp = bswap_64(tmp); +#endif + return tmp; + } +}; + +template +T UnalignedLoad(const char* p) { + auto tmp = EndianHelper::Load(p); + T res; + memcpy(&res, &tmp, sizeof(T)); + return res; +} + +PROTOBUF_EXPORT +std::pair VarintParseSlow32(const char* p, uint32 res); +PROTOBUF_EXPORT +std::pair VarintParseSlow64(const char* p, uint32 res); + +inline const char* VarintParseSlow(const char* p, uint32 res, uint32* out) { + auto tmp = VarintParseSlow32(p, res); + *out = tmp.second; + return tmp.first; +} + +inline const char* VarintParseSlow(const char* p, uint32 res, uint64* out) { + auto tmp = VarintParseSlow64(p, res); + *out = tmp.second; + return tmp.first; +} + +template +PROTOBUF_MUST_USE_RESULT const char* VarintParse(const char* p, T* out) { + auto ptr = reinterpret_cast(p); + uint32 res = ptr[0]; + if (!(res & 0x80)) { + *out = res; + return p + 1; + } + uint32 byte = ptr[1]; + res += (byte - 1) << 7; + if (!(byte & 0x80)) { + *out = res; + return p + 2; + } + return VarintParseSlow(p, res, out); +} + +// Used for tags, could read up to 5 bytes which must be available. +// Caller must ensure its safe to call. + +PROTOBUF_EXPORT +std::pair ReadTagFallback(const char* p, uint32 res); + +// Same as ParseVarint but only accept 5 bytes at most. +inline const char* ReadTag(const char* p, uint32* out, uint32 /*max_tag*/ = 0) { + uint32 res = static_cast(p[0]); + if (res < 128) { + *out = res; + return p + 1; + } + uint32 second = static_cast(p[1]); + res += (second - 1) << 7; + if (second < 128) { + *out = res; + return p + 2; + } + auto tmp = ReadTagFallback(p, res); + *out = tmp.second; + return tmp.first; +} + +// Decode 2 consecutive bytes of a varint and returns the value, shifted left +// by 1. It simultaneous updates *ptr to *ptr + 1 or *ptr + 2 depending if the +// first byte's continuation bit is set. +// If bit 15 of return value is set (equivalent to the continuation bits of both +// bytes being set) the varint continues, otherwise the parse is done. On x86 +// movsx eax, dil +// add edi, eax +// adc [rsi], 1 +// add eax, eax +// and eax, edi +inline uint32 DecodeTwoBytes(const char** ptr) { + uint32 value = UnalignedLoad(*ptr); + // Sign extend the low byte continuation bit + uint32_t x = static_cast(value); + // This add is an amazing operation, it cancels the low byte continuation bit + // from y transferring it to the carry. Simultaneously it also shifts the 7 + // LSB left by one tightly against high byte varint bits. Hence value now + // contains the unpacked value shifted left by 1. + value += x; + // Use the carry to update the ptr appropriately. + *ptr += value < x ? 2 : 1; + return value & (x + x); // Mask out the high byte iff no continuation +} + +// More efficient varint parsing for big varints +inline const char* ParseBigVarint(const char* p, uint64* out) { + auto pnew = p; + auto tmp = DecodeTwoBytes(&pnew); + uint64 res = tmp >> 1; + if (PROTOBUF_PREDICT_TRUE(std::int16_t(tmp) >= 0)) { + *out = res; + return pnew; + } + for (std::uint32_t i = 1; i < 5; i++) { + pnew = p + 2 * i; + tmp = DecodeTwoBytes(&pnew); + res += (static_cast(tmp) - 2) << (14 * i - 1); + if (PROTOBUF_PREDICT_TRUE(std::int16_t(tmp) >= 0)) { + *out = res; + return pnew; + } + } + return nullptr; +} + +PROTOBUF_EXPORT +std::pair ReadSizeFallback(const char* p, uint32 first); +// Used for tags, could read up to 5 bytes which must be available. Additionally +// it makes sure the unsigned value fits a int32, otherwise returns nullptr. +// Caller must ensure its safe to call. +inline uint32 ReadSize(const char** pp) { + auto p = *pp; + uint32 res = static_cast(p[0]); + if (res < 128) { + *pp = p + 1; + return res; + } + auto x = ReadSizeFallback(p, res); + *pp = x.first; + return x.second; +} + +// Some convenience functions to simplify the generated parse loop code. +// Returning the value and updating the buffer pointer allows for nicer +// function composition. We rely on the compiler to inline this. +// Also in debug compiles having local scoped variables tend to generated +// stack frames that scale as O(num fields). +inline uint64 ReadVarint64(const char** p) { + uint64 tmp; + *p = VarintParse(*p, &tmp); + return tmp; +} + +inline uint32 ReadVarint32(const char** p) { + uint32 tmp; + *p = VarintParse(*p, &tmp); + return tmp; +} + +inline int64 ReadVarintZigZag64(const char** p) { + uint64 tmp; + *p = VarintParse(*p, &tmp); + return WireFormatLite::ZigZagDecode64(tmp); +} + +inline int32 ReadVarintZigZag32(const char** p) { + uint64 tmp; + *p = VarintParse(*p, &tmp); + return WireFormatLite::ZigZagDecode32(static_cast(tmp)); +} + +template +PROTOBUF_MUST_USE_RESULT const char* ParseContext::ParseMessage( + T* msg, const char* ptr) { + int size = ReadSize(&ptr); + if (!ptr) return nullptr; + auto old = PushLimit(ptr, size); + if (--depth_ < 0) return nullptr; + ptr = msg->_InternalParse(ptr, this); + if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr; + depth_++; + if (!PopLimit(old)) return nullptr; + return ptr; +} + +template +const char* ReadPackedVarintArray(const char* ptr, const char* end, Add add) { + while (ptr < end) { + uint64 varint; + ptr = VarintParse(ptr, &varint); + if (ptr == nullptr) return nullptr; + add(varint); + } + return ptr; +} + +template +const char* EpsCopyInputStream::ReadPackedVarint(const char* ptr, Add add) { + int size = ReadSize(&ptr); + if (ptr == nullptr) return nullptr; + int chunk_size = buffer_end_ - ptr; + while (size > chunk_size) { + ptr = ReadPackedVarintArray(ptr, buffer_end_, add); + if (ptr == nullptr) return nullptr; + int overrun = ptr - buffer_end_; + GOOGLE_DCHECK(overrun >= 0 && overrun <= kSlopBytes); + if (size - chunk_size <= kSlopBytes) { + // The current buffer contains all the information needed, we don't need + // to flip buffers. However we must parse from a buffer with enough space + // so we are not prone to a buffer overflow. + char buf[kSlopBytes + 10] = {}; + std::memcpy(buf, buffer_end_, kSlopBytes); + GOOGLE_CHECK_LE(size - chunk_size, kSlopBytes); + auto end = buf + (size - chunk_size); + auto res = ReadPackedVarintArray(buf + overrun, end, add); + if (res == nullptr || res != end) return nullptr; + return buffer_end_ + (res - buf); + } + size -= overrun + chunk_size; + GOOGLE_DCHECK_GT(size, 0); + // We must flip buffers + if (limit_ <= kSlopBytes) return nullptr; + ptr = Next(); + if (ptr == nullptr) return nullptr; + ptr += overrun; + chunk_size = buffer_end_ - ptr; + } + auto end = ptr + size; + ptr = ReadPackedVarintArray(ptr, end, add); + return end == ptr ? ptr : nullptr; +} + +// Helper for verification of utf8 +PROTOBUF_EXPORT +bool VerifyUTF8(StringPiece s, const char* field_name); + +inline bool VerifyUTF8(const std::string* s, const char* field_name) { + return VerifyUTF8(*s, field_name); +} + +// All the string parsers with or without UTF checking and for all CTypes. +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* InlineGreedyStringParser( + std::string* s, const char* ptr, ParseContext* ctx); + + +// Add any of the following lines to debug which parse function is failing. + +#define GOOGLE_PROTOBUF_ASSERT_RETURN(predicate, ret) \ + if (!(predicate)) { \ + /* ::raise(SIGINT); */ \ + /* GOOGLE_LOG(ERROR) << "Parse failure"; */ \ + return ret; \ + } + +#define GOOGLE_PROTOBUF_PARSER_ASSERT(predicate) \ + GOOGLE_PROTOBUF_ASSERT_RETURN(predicate, nullptr) + +template +PROTOBUF_MUST_USE_RESULT const char* FieldParser(uint64 tag, T& field_parser, + const char* ptr, + ParseContext* ctx) { + uint32 number = tag >> 3; + GOOGLE_PROTOBUF_PARSER_ASSERT(number != 0); + using WireType = internal::WireFormatLite::WireType; + switch (tag & 7) { + case WireType::WIRETYPE_VARINT: { + uint64 value; + ptr = VarintParse(ptr, &value); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + field_parser.AddVarint(number, value); + break; + } + case WireType::WIRETYPE_FIXED64: { + uint64 value = UnalignedLoad(ptr); + ptr += 8; + field_parser.AddFixed64(number, value); + break; + } + case WireType::WIRETYPE_LENGTH_DELIMITED: { + ptr = field_parser.ParseLengthDelimited(number, ptr, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + break; + } + case WireType::WIRETYPE_START_GROUP: { + ptr = field_parser.ParseGroup(number, ptr, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + break; + } + case WireType::WIRETYPE_END_GROUP: { + GOOGLE_LOG(FATAL) << "Can't happen"; + break; + } + case WireType::WIRETYPE_FIXED32: { + uint32 value = UnalignedLoad(ptr); + ptr += 4; + field_parser.AddFixed32(number, value); + break; + } + default: + return nullptr; + } + return ptr; +} + +template +PROTOBUF_MUST_USE_RESULT const char* WireFormatParser(T& field_parser, + const char* ptr, + ParseContext* ctx) { + while (!ctx->Done(&ptr)) { + uint32 tag; + ptr = ReadTag(ptr, &tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr); + if (tag == 0 || (tag & 7) == 4) { + ctx->SetLastTag(tag); + return ptr; + } + ptr = FieldParser(tag, field_parser, ptr, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr); + } + return ptr; +} + +// The packed parsers parse repeated numeric primitives directly into the +// corresponding field + +// These are packed varints +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedInt32Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedUInt32Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedInt64Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedUInt64Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedSInt32Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedSInt64Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedEnumParser( + void* object, const char* ptr, ParseContext* ctx); + +template +PROTOBUF_MUST_USE_RESULT const char* PackedEnumParser( + void* object, const char* ptr, ParseContext* ctx, bool (*is_valid)(int), + InternalMetadata* metadata, int field_num) { + return ctx->ReadPackedVarint( + ptr, [object, is_valid, metadata, field_num](uint64 val) { + if (is_valid(val)) { + static_cast*>(object)->Add(val); + } else { + WriteVarint(field_num, val, metadata->mutable_unknown_fields()); + } + }); +} + +template +PROTOBUF_MUST_USE_RESULT const char* PackedEnumParserArg( + void* object, const char* ptr, ParseContext* ctx, + bool (*is_valid)(const void*, int), const void* data, + InternalMetadata* metadata, int field_num) { + return ctx->ReadPackedVarint( + ptr, [object, is_valid, data, metadata, field_num](uint64 val) { + if (is_valid(data, val)) { + static_cast*>(object)->Add(val); + } else { + WriteVarint(field_num, val, metadata->mutable_unknown_fields()); + } + }); +} + +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedBoolParser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedFixed32Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedSFixed32Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedFixed64Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedSFixed64Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedFloatParser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* PackedDoubleParser( + void* object, const char* ptr, ParseContext* ctx); + +// This is the only recursive parser. +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* UnknownGroupLiteParse( + std::string* unknown, const char* ptr, ParseContext* ctx); +// This is a helper to for the UnknownGroupLiteParse but is actually also +// useful in the generated code. It uses overload on std::string* vs +// UnknownFieldSet* to make the generated code isomorphic between full and lite. +PROTOBUF_EXPORT PROTOBUF_MUST_USE_RESULT const char* UnknownFieldParse( + uint32 tag, std::string* unknown, const char* ptr, ParseContext* ctx); + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include + +#endif // GOOGLE_PROTOBUF_PARSE_CONTEXT_H__ diff --git a/src/google/protobuf/port.h b/src/google/protobuf/port.h new file mode 100644 index 0000000000000..aa2cfc1eb862b --- /dev/null +++ b/src/google/protobuf/port.h @@ -0,0 +1,47 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// A common header that is included across all protobuf headers. We do our best +// to avoid #defining any macros here; instead we generally put macros in +// port_def.inc and port_undef.inc so they are not visible from outside of +// protobuf. + +#ifndef GOOGLE_PROTOBUF_PORT_H__ +#define GOOGLE_PROTOBUF_PORT_H__ + + +#include + +// Protobuf intends to move into the pb:: namespace. +namespace protobuf_future_namespace_placeholder {} +namespace pb = ::protobuf_future_namespace_placeholder; + + +#endif // GOOGLE_PROTOBUF_PORT_H__ diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc new file mode 100644 index 0000000000000..3dc0ca7f97284 --- /dev/null +++ b/src/google/protobuf/port_def.inc @@ -0,0 +1,637 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file defines common macros that are used in protobuf. +// +// To hide these definitions from the outside world (and to prevent collisions +// if more than one version of protobuf is #included in the same project) you +// must follow this pattern when #including port_def.inc in a header file: +// +// #include "other_header.h" +// #include "message.h" +// // etc. +// +// #include "port_def.inc" // MUST be last header included +// +// // Definitions for this header. +// +// #include "port_undef.inc" +// +// This is a textual header with no include guard, because we want to +// detect/prohibit anytime it is #included twice without a corresponding +// #undef. + +// These macros are private and should always be +// ::util::RetrieveErrorSpace(*this) headers. If any of these errors fire, you +// should either properly #include port_undef.h at the end of your header that +// #includes port.h, or don't #include port.h twice in a .cc file. +#ifdef PROTOBUF_NAMESPACE +#error PROTOBUF_NAMESPACE was previously defined +#endif +#ifdef PROTOBUF_NAMESPACE_ID +#error PROTOBUF_NAMESPACE_ID was previously defined +#endif +#ifdef PROTOBUF_ALWAYS_INLINE +#error PROTOBUF_ALWAYS_INLINE was previously defined +#endif +#ifdef PROTOBUF_NDEBUG_INLINE +#error PROTOBUF_NDEBUG_INLINE was previously defined +#endif +#ifdef PROTOBUF_COLD +#error PROTOBUF_COLD was previously defined +#endif +#ifdef PROTOBUF_NOINLINE +#error PROTOBUF_NOINLINE was previously defined +#endif +#ifdef PROTOBUF_SECTION_VARIABLE +#error PROTOBUF_SECTION_VARIABLE was previously defined +#endif +#ifdef PROTOBUF_DEPRECATED +#error PROTOBUF_DEPRECATED was previously defined +#endif +#ifdef PROTOBUF_DEPRECATED_MSG +#error PROTOBUF_DEPRECATED_MSG was previously defined +#endif +#ifdef PROTOBUF_FUNC_ALIGN +#error PROTOBUF_FUNC_ALIGN was previously defined +#endif +#ifdef PROTOBUF_RETURNS_NONNULL +#error PROTOBUF_RETURNS_NONNULL was previously defined +#endif +#ifdef PROTOBUF_ATTRIBUTE_REINITIALIZES +#error PROTOBUF_ATTRIBUTE_REINITIALIZES was previously defined +#endif +#ifdef PROTOBUF_RTTI +#error PROTOBUF_RTTI was previously defined +#endif +#ifdef PROTOBUF_VERSION +#error PROTOBUF_VERSION was previously defined +#endif +#ifdef PROTOBUF_VERSION_SUFFIX +#error PROTOBUF_VERSION_SUFFIX was previously defined +#endif +#ifdef PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC +#error PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC was previously defined +#endif +#ifdef PROTOBUF_MIN_PROTOC_VERSION +#error PROTOBUF_MIN_PROTOC_VERSION was previously defined +#endif +#ifdef PROTOBUF_PREDICT_TRUE +#error PROTOBUF_PREDICT_TRUE was previously defined +#endif +#ifdef PROTOBUF_PREDICT_FALSE +#error PROTOBUF_PREDICT_FALSE was previously defined +#endif +#ifdef PROTOBUF_FIELD_OFFSET +#error PROTOBUF_FIELD_OFFSET was previously defined +#endif +#ifdef PROTOBUF_LL_FORMAT +#error PROTOBUF_LL_FORMAT was previously defined +#endif +#ifdef PROTOBUF_GUARDED_BY +#error PROTOBUF_GUARDED_BY was previously defined +#endif +#ifdef PROTOBUF_LONGLONG +#error PROTOBUF_LONGLONG was previously defined +#endif +#ifdef PROTOBUF_ULONGLONG +#error PROTOBUF_ULONGLONG was previously defined +#endif +#ifdef PROTOBUF_FALLTHROUGH_INTENDED +#error PROTOBUF_FALLTHROUGH_INTENDED was previously defined +#endif +#ifdef PROTOBUF_EXPORT +#error PROTOBUF_EXPORT was previously defined +#endif +#ifdef PROTOC_EXPORT +#error PROTOC_EXPORT was previously defined +#endif +#ifdef PROTOBUF_MUST_USE_RESULT +#error PROTOBUF_MUST_USE_RESULT was previously defined +#endif +#ifdef PROTOBUF_UNUSED +#error PROTOBUF_UNUSED was previously defined +#endif +#ifdef PROTOBUF_FINAL +#error PROTOBUF_FINAL was previously defined +#endif +#ifdef PROTOBUF_ENABLE_MSVC_UNION_WARNING +#error PROTOBUF_ENABLE_MSVC_UNION_WARNING was previously defined +#endif +#ifdef PROTOBUF_CONSTINIT +#error PROTOBUF_CONSTINIT was previously defined +#endif +#ifdef PROTOBUF_ATTRIBUTE_NO_DESTROY +#error PROTOBUF_ATTRIBUTE_NO_DESTROY was previously defined +#endif +#ifdef PROTOBUF_ATTRIBUTE_INIT_PRIORITY +#error PROTOBUF_ATTRIBUTE_INIT_PRIORITY was previously defined +#endif +#ifdef PROTOBUF_PRAGMA_INIT_SEG +#error PROTOBUF_PRAGMA_INIT_SEG was previously defined +#endif +#ifdef PROTOBUF_ATTRIBUTE_WEAK +#error PROTOBUF_ATTRIBUTE_WEAK was previously defined +#endif + + +#define PROTOBUF_NAMESPACE "google::protobuf" +#define PROTOBUF_NAMESPACE_ID google::protobuf +#define PROTOBUF_NAMESPACE_OPEN \ + namespace google { \ + namespace protobuf { +#define PROTOBUF_NAMESPACE_CLOSE \ + } /* namespace protobuf */ \ + } /* namespace google */ + +#if defined(__clang__) +#define PROTOBUF_DEPRECATED __attribute__((deprecated)) +#define PROTOBUF_DEPRECATED_ENUM __attribute__((deprecated)) +#define PROTOBUF_DEPRECATED_MSG(msg) __attribute__((deprecated(msg))) +#elif defined(__GNUC__) +#define PROTOBUF_DEPRECATED __attribute__((deprecated)) +#define PROTOBUF_DEPRECATED_MSG(msg) __attribute__((deprecated(msg))) +#if __GNUC__ >= 6 +#define PROTOBUF_DEPRECATED_ENUM __attribute__((deprecated)) +#else +#define PROTOBUF_DEPRECATED_ENUM +#endif +#elif defined(_MSC_VER) +#define PROTOBUF_DEPRECATED __declspec(deprecated) +#define PROTOBUF_DEPRECATED_ENUM +#define PROTOBUF_DEPRECATED_MSG(msg) __declspec(deprecated(msg)) +#endif + +#define PROTOBUF_SECTION_VARIABLE(x) +#define PROTOBUF_MUST_USE_RESULT + +// ---------------------------------------------------------------------------- +// Annotations: Some parts of the code have been annotated in ways that might +// be useful to some compilers or tools, but are not supported universally. +// You can #define these annotations yourself if the default implementation +// is not right for you. + +#ifdef GOOGLE_ATTRIBUTE_ALWAYS_INLINE +#define PROTOBUF_ALWAYS_INLINE GOOGLE_ATTRIBUTE_ALWAYS_INLINE +#define PROTOBUF_NDEBUG_INLINE GOOGLE_ATTRIBUTE_ALWAYS_INLINE +#else +#if defined(__GNUC__) && \ + (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +// For functions we want to force inline. +// Introduced in gcc 3.1. +#define PROTOBUF_ALWAYS_INLINE __attribute__((always_inline)) +#define PROTOBUF_NDEBUG_INLINE __attribute__((always_inline)) +#else +// Other compilers will have to figure it out for themselves. +#define PROTOBUF_ALWAYS_INLINE +#define PROTOBUF_NDEBUG_INLINE +#endif +#endif + +#ifdef GOOGLE_ATTRIBUTE_NOINLINE +#define PROTOBUF_NOINLINE GOOGLE_ATTRIBUTE_NOINLINE +#else +#if defined(__GNUC__) && \ + (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +// For functions we want to force not inline. +// Introduced in gcc 3.1. +#define PROTOBUF_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) +// Seems to have been around since at least Visual Studio 2005 +#define PROTOBUF_NOINLINE __declspec(noinline) +#else +// Other compilers will have to figure it out for themselves. +#define PROTOBUF_NOINLINE +#endif +#endif + +#ifdef GOOGLE_ATTRIBUTE_FUNC_ALIGN +#define PROTOBUF_FUNC_ALIGN GOOGLE_ATTRIBUTE_FUNC_ALIGN +#else +#if defined(__clang__) || \ + defined(__GNUC__) && \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) +// Function alignment attribute introduced in gcc 4.3 +#define PROTOBUF_FUNC_ALIGN(bytes) __attribute__((aligned(bytes))) +#else +#define PROTOBUF_FUNC_ALIGN(bytes) +#endif +#endif + +#ifdef GOOGLE_PREDICT_TRUE +#define PROTOBUF_PREDICT_TRUE GOOGLE_PREDICT_TRUE +#else +#ifdef __GNUC__ +// Provided at least since GCC 3.0. +#define PROTOBUF_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) +#else +#define PROTOBUF_PREDICT_TRUE(x) (x) +#endif +#endif + +#ifdef GOOGLE_PREDICT_FALSE +#define PROTOBUF_PREDICT_FALSE GOOGLE_PREDICT_FALSE +#else +#ifdef __GNUC__ +// Provided at least since GCC 3.0. +#define PROTOBUF_PREDICT_FALSE(x) (__builtin_expect(x, 0)) +#else +#define PROTOBUF_PREDICT_FALSE(x) (x) +#endif +#endif + +#ifdef GOOGLE_PROTOBUF_ATTRIBUTE_RETURNS_NONNULL +#define PROTOBUF_RETURNS_NONNULL GOOGLE_PROTOBUF_ATTRIBUTE_RETURNS_NONNULL +#else +#if defined(__has_attribute) +#if __has_attribute(returns_nonnull) +#define PROTOBUF_RETURNS_NONNULL __attribute__((returns_nonnull)) +#endif +#endif +#endif +#ifndef PROTOBUF_RETURNS_NONNULL +#define PROTOBUF_RETURNS_NONNULL +#endif + +#if defined(__has_cpp_attribute) +#if __has_cpp_attribute(clang::reinitializes) +#define PROTOBUF_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]] +#endif +#endif +#ifndef PROTOBUF_ATTRIBUTE_REINITIALIZES +#define PROTOBUF_ATTRIBUTE_REINITIALIZES +#endif + +#define PROTOBUF_GUARDED_BY(x) +#define PROTOBUF_COLD + +// Copied from ABSL. +#if defined(__clang__) && defined(__has_warning) +#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") +#define PROTOBUF_FALLTHROUGH_INTENDED [[clang::fallthrough]] +#endif +#elif defined(__GNUC__) && __GNUC__ >= 7 +#define PROTOBUF_FALLTHROUGH_INTENDED [[gnu::fallthrough]] +#endif + +#ifndef PROTOBUF_FALLTHROUGH_INTENDED +#define PROTOBUF_FALLTHROUGH_INTENDED +#endif + +#if defined(__has_cpp_attribute) +#define HAS_ATTRIBUTE(attr) __has_cpp_attribute(attr) +#else +#define HAS_ATTRIBUTE(attr) 0 +#endif + +#if HAS_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__)) +#define PROTOBUF_UNUSED __attribute__((__unused__)) +#else +#define PROTOBUF_UNUSED +#endif + +#undef HAS_ATTRIBUTE + +#ifdef _MSC_VER +#define PROTOBUF_LONGLONG(x) x##I64 +#define PROTOBUF_ULONGLONG(x) x##UI64 +#define PROTOBUF_LL_FORMAT "I64" // As in printf("%I64d", ...) +#else +// By long long, we actually mean int64. +#define PROTOBUF_LONGLONG(x) x##LL +#define PROTOBUF_ULONGLONG(x) x##ULL +// Used to format real long long integers. +#define PROTOBUF_LL_FORMAT \ + "ll" // As in "%lld". Note that "q" is poor form also. +#endif + + +// Shared google3/opensource definitions. ////////////////////////////////////// + +#define PROTOBUF_VERSION 3015000 +#define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC 3015000 +#define PROTOBUF_MIN_PROTOC_VERSION 3015000 +#define PROTOBUF_VERSION_SUFFIX "" + +// The minimum library version which works with the current version of the +// headers. +#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3015000 + +#if defined(GOOGLE_PROTOBUF_NO_RTTI) && GOOGLE_PROTOBUF_NO_RTTI +#define PROTOBUF_RTTI 0 +#elif defined(__has_feature) +// https://clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension +#define PROTOBUF_RTTI __has_feature(cxx_rtti) +#elif !defined(__cxx_rtti) +// https://en.cppreference.com/w/User:D41D8CD98F/feature_testing_macros#C.2B.2B98 +#define PROTOBUF_RTTI 0 +#elif defined(__GNUC__) && !defined(__GXX_RTTI) +#https: // gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html +#define PROTOBUF_RTTI 0 +#else +#define PROTOBUF_RTTI 1 +#endif + +// Returns the offset of the given field within the given aggregate type. +// This is equivalent to the ANSI C offsetof() macro. However, according +// to the C++ standard, offsetof() only works on POD types, and GCC +// enforces this requirement with a warning. In practice, this rule is +// unnecessarily strict; there is probably no compiler or platform on +// which the offsets of the direct fields of a class are non-constant. +// Fields inherited from superclasses *can* have non-constant offsets, +// but that's not what this macro will be used for. +#if defined(__clang__) +// For Clang we use __builtin_offsetof() and suppress the warning, +// to avoid Control Flow Integrity and UBSan vptr sanitizers from +// crashing while trying to validate the invalid reinterpet_casts. +#define PROTOBUF_FIELD_OFFSET(TYPE, FIELD) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(TYPE, FIELD) \ + _Pragma("clang diagnostic pop") +#elif defined(__GNUC__) && \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) +#define PROTOBUF_FIELD_OFFSET(TYPE, FIELD) __builtin_offsetof(TYPE, FIELD) +#else // defined(__clang__) +// Note that we calculate relative to the pointer value 16 here since if we +// just use zero, GCC complains about dereferencing a NULL pointer. We +// choose 16 rather than some other number just in case the compiler would +// be confused by an unaligned pointer. +#define PROTOBUF_FIELD_OFFSET(TYPE, FIELD) \ + static_cast< ::google::protobuf::uint32>(reinterpret_cast( \ + &reinterpret_cast(16)->FIELD) - \ + reinterpret_cast(16)) +#endif + +#if defined(PROTOBUF_USE_DLLS) +#if defined(_MSC_VER) +#ifdef LIBPROTOBUF_EXPORTS +#define PROTOBUF_EXPORT __declspec(dllexport) +#define PROTOBUF_EXPORT_TEMPLATE_DECLARE +#define PROTOBUF_EXPORT_TEMPLATE_DEFINE __declspec(dllexport) +#else +#define PROTOBUF_EXPORT __declspec(dllimport) +#define PROTOBUF_EXPORT_TEMPLATE_DECLARE +#define PROTOBUF_EXPORT_TEMPLATE_DEFINE __declspec(dllimport) +#endif +#ifdef LIBPROTOC_EXPORTS +#define PROTOC_EXPORT __declspec(dllexport) +#else +#define PROTOC_EXPORT __declspec(dllimport) +#endif +#else // defined(_MSC_VER) +#ifdef LIBPROTOBUF_EXPORTS +#define PROTOBUF_EXPORT __attribute__((visibility("default"))) +#define PROTOBUF_EXPORT_TEMPLATE_DECLARE __attribute__((visibility("default"))) +#define PROTOBUF_EXPORT_TEMPLATE_DEFINE +#else +#define PROTOBUF_EXPORT +#define PROTOBUF_EXPORT_TEMPLATE_DECLARE +#define PROTOBUF_EXPORT_TEMPLATE_DEFINE +#endif +#ifdef LIBPROTOC_EXPORTS +#define PROTOC_EXPORT __attribute__((visibility("default"))) +#else +#define PROTOC_EXPORT +#endif +#endif +#else // defined(PROTOBUF_USE_DLLS) +#define PROTOBUF_EXPORT +#define PROTOC_EXPORT +#define PROTOBUF_EXPORT_TEMPLATE_DECLARE +#define PROTOBUF_EXPORT_TEMPLATE_DEFINE +#endif + +// Windows declares several inconvenient macro names. We #undef them and then +// restore them in port_undef.inc. +#ifdef _MSC_VER +#pragma push_macro("CREATE_NEW") +#undef CREATE_NEW +#pragma push_macro("DOUBLE_CLICK") +#undef DOUBLE_CLICK +#pragma push_macro("ERROR") +#undef ERROR +#pragma push_macro("ERROR_BUSY") +#undef ERROR_BUSY +#pragma push_macro("ERROR_NOT_FOUND") +#undef ERROR_NOT_FOUND +#pragma push_macro("GetMessage") +#undef GetMessage +#pragma push_macro("IGNORE") +#undef IGNORE +#pragma push_macro("IN") +#undef IN +#pragma push_macro("INPUT_KEYBOARD") +#undef INPUT_KEYBOARD +#pragma push_macro("NO_ERROR") +#undef NO_ERROR +#pragma push_macro("OUT") +#undef OUT +#pragma push_macro("OPTIONAL") +#undef OPTIONAL +#pragma push_macro("min") +#undef min +#pragma push_macro("max") +#undef max +#pragma push_macro("NEAR") +#undef NEAR +#pragma push_macro("NO_DATA") +#undef NO_DATA +#pragma push_macro("REASON_UNKNOWN") +#undef REASON_UNKNOWN +#pragma push_macro("SERVICE_DISABLED") +#undef SERVICE_DISABLED +#pragma push_macro("SEVERITY_ERROR") +#undef SEVERITY_ERROR +#pragma push_macro("STRICT") +#undef STRICT +#pragma push_macro("timezone") +#undef timezone +#endif // _MSC_VER + +#if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER) +// Don't let Objective-C Macros interfere with proto identifiers with the same +// name. +#pragma push_macro("DEBUG") +#undef DEBUG +#endif // defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER) + +#if defined(__clang__) +#pragma clang diagnostic push +// TODO(gerbens) ideally we cleanup the code. But a cursory try shows many +// violations. So let's ignore for now. +#pragma clang diagnostic ignored "-Wshorten-64-to-32" +#elif defined(__GNUC__) +// GCC does not allow disabling diagnostics within an expression: +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60875, so we disable this one +// globally even though it's only used for PROTOBUF_FIELD_OFFSET. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winvalid-offsetof" +#endif + +// PROTOBUF_ASSUME(pred) tells the compiler that it can assume pred is true. To +// be safe, we also validate the assumption with a GOOGLE_DCHECK in unoptimized +// builds. The macro does not do anything useful if the compiler does not +// support __builtin_assume. +#ifdef __has_builtin +#if __has_builtin(__builtin_assume) +#define PROTOBUF_ASSUME(pred) \ + GOOGLE_DCHECK(pred); \ + __builtin_assume(pred) +#else +#define PROTOBUF_ASSUME(pred) GOOGLE_DCHECK(pred) +#endif +#else +#define PROTOBUF_ASSUME(pred) GOOGLE_DCHECK(pred) +#endif + +// Specify memory alignment for structs, classes, etc. +// Use like: +// class PROTOBUF_ALIGNAS(16) MyClass { ... } +// PROTOBUF_ALIGNAS(16) int array[4]; +// +// In most places you can use the C++11 keyword "alignas", which is preferred. +// +// But compilers have trouble mixing __attribute__((...)) syntax with +// alignas(...) syntax. +// +// Doesn't work in clang or gcc: +// struct alignas(16) __attribute__((packed)) S { char c; }; +// Works in clang but not gcc: +// struct __attribute__((packed)) alignas(16) S2 { char c; }; +// Works in clang and gcc: +// struct alignas(16) S3 { char c; } __attribute__((packed)); +// +// There are also some attributes that must be specified *before* a class +// definition: visibility (used for exporting functions/classes) is one of +// these attributes. This means that it is not possible to use alignas() with a +// class that is marked as exported. +#if defined(_MSC_VER) +#define PROTOBUF_ALIGNAS(byte_alignment) __declspec(align(byte_alignment)) +#elif defined(__GNUC__) +#define PROTOBUF_ALIGNAS(byte_alignment) \ + __attribute__((aligned(byte_alignment))) +#else +#define PROTOBUF_ALIGNAS(byte_alignment) alignas(byte_alignment) +#endif + +#define PROTOBUF_FINAL final + +#if defined(_MSC_VER) +#define PROTOBUF_THREAD_LOCAL __declspec(thread) +#else +#define PROTOBUF_THREAD_LOCAL __thread +#endif + +// For enabling message owned arena, one major blocker is semantic change from +// moving to copying when there is ownership transfer (e.g., move ctor, swap, +// set allocated, release). This change not only causes performance regression +// but also breaks users code (e.g., dangling reference). For top-level +// messages, since it owns the arena, we can mitigate the issue by transferring +// ownership of arena. However, we cannot do that for nested messages. In order +// to tell how many usages of nested messages affected by message owned arena, +// we need to simulate the arena ownership. +// This experiment is purely for the purpose of gathering data. All code guarded +// by this flag is supposed to be removed after this experiment. +// #define PROTOBUF_MESSAGE_OWNED_ARENA_EXPERIMENT + +#if defined(__cpp_constinit) +#define PROTOBUF_CONSTINIT constinit +#elif defined(__has_cpp_attribute) +#if __has_cpp_attribute(clang::require_constant_initialization) +#define PROTOBUF_CONSTINIT [[clang::require_constant_initialization]] +#endif +#endif +#ifndef PROTOBUF_CONSTINIT +#define PROTOBUF_CONSTINIT +#endif + +#if defined(__cpp_constinit) +#define PROTOBUF_CONSTINIT constinit +#elif defined(__has_cpp_attribute) +#if __has_cpp_attribute(clang::require_constant_initialization) +#define PROTOBUF_CONSTINIT [[clang::require_constant_initialization]] +#endif +#endif +#ifndef PROTOBUF_CONSTINIT +#define PROTOBUF_CONSTINIT +#endif + +// Some globals with an empty non-trivial destructor are annotated with +// no_destroy for performance reasons. It reduces the cost of these globals in +// non-opt mode and under sanitizers. +#if defined(__has_cpp_attribute) +#if __has_cpp_attribute(clang::no_destroy) +#define PROTOBUF_ATTRIBUTE_NO_DESTROY [[clang::no_destroy]] +#endif +#endif +#if !defined(PROTOBUF_ATTRIBUTE_NO_DESTROY) +#define PROTOBUF_ATTRIBUTE_NO_DESTROY +#endif + +#if defined(__GNUC__) +// Protobuf extensions and reflection require registration of the protos linked +// in the binary. Not until everything is registered does the runtime have a +// complete view on all protos. When code is using reflection or extensions +// in between registration calls this can lead to surprising behavior. By +// having the registration run first we mitigate this scenario. +// Highest priority is 101. We use 102 to allow code that really wants to +// higher priority to still beat us. +#define PROTOBUF_ATTRIBUTE_INIT_PRIORITY __attribute__((init_priority((102)))) +#else +#define PROTOBUF_ATTRIBUTE_INIT_PRIORITY +#endif + +#if _MSC_VER +#define PROTOBUF_PRAGMA_INIT_SEG __pragma(init_seg(lib)) +#else +#define PROTOBUF_PRAGMA_INIT_SEG +#endif + +#if defined(__has_attribute) && !defined(__MINGW32__) +#if __has_attribute(weak) +#define PROTOBUF_ATTRIBUTE_WEAK __attribute__((weak)) +#endif +#endif +#if !defined(PROTOBUF_ATTRIBUTE_WEAK) +#define PROTOBUF_ATTRIBUTE_WEAK +#endif + +// Silence some MSVC warnings in all our code. +#if _MSC_VER +#pragma warning(push) +// For non-trivial unions +#pragma warning(disable : 4582) +#pragma warning(disable : 4583) +// For init_seg(lib) +#pragma warning(disable : 4073) +// To silence the fact that we will pop this push from another file +#pragma warning(disable : 5031) +#endif diff --git a/src/google/protobuf/port_undef.inc b/src/google/protobuf/port_undef.inc new file mode 100644 index 0000000000000..daef09bc45afa --- /dev/null +++ b/src/google/protobuf/port_undef.inc @@ -0,0 +1,120 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// #undefs all macros defined in port_def.inc. See comments in port_def.inc +// for more info. + +#ifndef PROTOBUF_NAMESPACE +#error "port_undef.inc must be included after port_def.inc" +#endif +#undef PROTOBUF_NAMESPACE +#undef PROTOBUF_NAMESPACE_ID +#undef PROTOBUF_ALWAYS_INLINE +#undef PROTOBUF_NDEBUG_INLINE +#undef PROTOBUF_COLD +#undef PROTOBUF_NOINLINE +#undef PROTOBUF_SECTION_VARIABLE +#undef PROTOBUF_DEPRECATED +#undef PROTOBUF_DEPRECATED_ENUM +#undef PROTOBUF_DEPRECATED_MSG +#undef PROTOBUF_FUNC_ALIGN +#undef PROTOBUF_RETURNS_NONNULL +#undef PROTOBUF_ATTRIBUTE_REINITIALIZES +#undef PROTOBUF_RTTI +#undef PROTOBUF_VERSION +#undef PROTOBUF_VERSION_SUFFIX +#undef PROTOBUF_FIELD_OFFSET +#undef PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC +#undef PROTOBUF_MIN_PROTOC_VERSION +#undef PROTOBUF_PREDICT_TRUE +#undef PROTOBUF_PREDICT_FALSE +#undef PROTOBUF_LONGLONG +#undef PROTOBUF_ULONGLONG +#undef PROTOBUF_LL_FORMAT +#undef PROTOBUF_GUARDED_BY +#undef PROTOBUF_FALLTHROUGH_INTENDED +#undef PROTOBUF_EXPORT +#undef PROTOC_EXPORT +#undef PROTOBUF_MUST_USE_RESULT +#undef PROTOBUF_NAMESPACE_OPEN +#undef PROTOBUF_NAMESPACE_CLOSE +#undef PROTOBUF_UNUSED +#undef PROTOBUF_ASSUME +#undef PROTOBUF_EXPORT_TEMPLATE_DECLARE +#undef PROTOBUF_EXPORT_TEMPLATE_DEFINE +#undef PROTOBUF_ALIGNAS +#undef PROTOBUF_FINAL +#undef PROTOBUF_THREAD_LOCAL +#undef PROTOBUF_MESSAGE_OWNED_ARENA_EXPERIMENT +#undef PROTOBUF_CONSTINIT +#undef PROTOBUF_ATTRIBUTE_WEAK +#undef PROTOBUF_ATTRIBUTE_NO_DESTROY +#undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY +#undef PROTOBUF_PRAGMA_INIT_SEG + +// Restore macro that may have been #undef'd in port_def.inc. +#ifdef _MSC_VER +#pragma pop_macro("CREATE_NEW") +#pragma pop_macro("DOUBLE_CLICK") +#pragma pop_macro("ERROR") +#pragma pop_macro("ERROR_BUSY") +#pragma pop_macro("ERROR_NOT_FOUND") +#pragma pop_macro("GetMessage") +#pragma pop_macro("IGNORE") +#pragma pop_macro("IN") +#pragma pop_macro("INPUT_KEYBOARD") +#pragma pop_macro("OUT") +#pragma pop_macro("OPTIONAL") +#pragma pop_macro("min") +#pragma pop_macro("max") +#pragma pop_macro("NEAR") +#pragma pop_macro("NO_DATA") +#pragma pop_macro("NO_ERROR") +#pragma pop_macro("REASON_UNKNOWN") +#pragma pop_macro("SERVICE_DISABLED") +#pragma pop_macro("SEVERITY_ERROR") +#pragma pop_macro("STRICT") +#pragma pop_macro("timezone") +#endif + +#if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER) +#pragma pop_macro("DEBUG") +#endif // defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER) + +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +// Pop the warning(push) from port_def.inc +#if _MSC_VER +#pragma warning(pop) +#endif diff --git a/src/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc index 1673e8afaed02..ed21a88b81571 100644 --- a/src/google/protobuf/preserve_unknown_enum_test.cc +++ b/src/google/protobuf/preserve_unknown_enum_test.cc @@ -31,8 +31,8 @@ #include #include #include -#include #include +#include #include namespace google { @@ -41,22 +41,18 @@ namespace { void FillMessage( proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra* message) { - message->set_e( - proto3_preserve_unknown_enum_unittest::E_EXTRA); - message->add_repeated_e( - proto3_preserve_unknown_enum_unittest::E_EXTRA); + message->set_e(proto3_preserve_unknown_enum_unittest::E_EXTRA); + message->add_repeated_e(proto3_preserve_unknown_enum_unittest::E_EXTRA); message->add_repeated_packed_e( proto3_preserve_unknown_enum_unittest::E_EXTRA); message->add_repeated_packed_unexpected_e( proto3_preserve_unknown_enum_unittest::E_EXTRA); - message->set_oneof_e_1( - proto3_preserve_unknown_enum_unittest::E_EXTRA); + message->set_oneof_e_1(proto3_preserve_unknown_enum_unittest::E_EXTRA); } void CheckMessage( const proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra& message) { - EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, - message.e()); + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, message.e()); EXPECT_EQ(1, message.repeated_e_size()); EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, message.repeated_e(0)); @@ -72,23 +68,18 @@ void CheckMessage( void CheckMessage( const proto3_preserve_unknown_enum_unittest::MyMessage& message) { - EXPECT_EQ(static_cast( - proto3_preserve_unknown_enum_unittest::E_EXTRA), + EXPECT_EQ(static_cast(proto3_preserve_unknown_enum_unittest::E_EXTRA), static_cast(message.e())); EXPECT_EQ(1, message.repeated_e_size()); - EXPECT_EQ(static_cast( - proto3_preserve_unknown_enum_unittest::E_EXTRA), + EXPECT_EQ(static_cast(proto3_preserve_unknown_enum_unittest::E_EXTRA), static_cast(message.repeated_e(0))); EXPECT_EQ(1, message.repeated_packed_e_size()); - EXPECT_EQ(static_cast( - proto3_preserve_unknown_enum_unittest::E_EXTRA), + EXPECT_EQ(static_cast(proto3_preserve_unknown_enum_unittest::E_EXTRA), static_cast(message.repeated_packed_e(0))); EXPECT_EQ(1, message.repeated_packed_unexpected_e_size()); - EXPECT_EQ(static_cast( - proto3_preserve_unknown_enum_unittest::E_EXTRA), + EXPECT_EQ(static_cast(proto3_preserve_unknown_enum_unittest::E_EXTRA), static_cast(message.repeated_packed_unexpected_e(0))); - EXPECT_EQ(static_cast( - proto3_preserve_unknown_enum_unittest::E_EXTRA), + EXPECT_EQ(static_cast(proto3_preserve_unknown_enum_unittest::E_EXTRA), static_cast(message.oneof_e_1())); } @@ -99,7 +90,7 @@ void CheckMessage( TEST(PreserveUnknownEnumTest, PreserveParseAndSerialize) { proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; FillMessage(&orig_message); - string serialized; + std::string serialized; orig_message.SerializeToString(&serialized); proto3_preserve_unknown_enum_unittest::MyMessage message; @@ -117,11 +108,14 @@ TEST(PreserveUnknownEnumTest, PreserveParseAndSerialize) { TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) { proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; FillMessage(&orig_message); - string serialized = orig_message.SerializeAsString(); - - google::protobuf::DynamicMessageFactory factory; - google::protobuf::scoped_ptr message(factory.GetPrototype( - proto3_preserve_unknown_enum_unittest::MyMessage::descriptor())->New()); + std::string serialized = orig_message.SerializeAsString(); + + DynamicMessageFactory factory; + std::unique_ptr message( + factory + .GetPrototype( + proto3_preserve_unknown_enum_unittest::MyMessage::descriptor()) + ->New()); EXPECT_EQ(true, message->ParseFromString(serialized)); message->DiscardUnknownFields(); @@ -135,7 +129,7 @@ TEST(PreserveUnknownEnumTest, Proto2HidesUnknownValues) { proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; FillMessage(&orig_message); - string serialized; + std::string serialized; orig_message.SerializeToString(&serialized); proto2_preserve_unknown_enum_unittest::MyMessage message; @@ -143,7 +137,7 @@ TEST(PreserveUnknownEnumTest, Proto2HidesUnknownValues) { // The intermediate message has everything in its "unknown fields". proto2_preserve_unknown_enum_unittest::MyMessage message2 = message; message2.DiscardUnknownFields(); - EXPECT_EQ(0, message2.ByteSize()); + EXPECT_EQ(0, message2.ByteSizeLong()); // But when we pass it to the correct structure, all values are there. serialized.clear(); @@ -157,18 +151,21 @@ TEST(PreserveUnknownEnumTest, DynamicProto2HidesUnknownValues) { proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; FillMessage(&orig_message); - string serialized; + std::string serialized; orig_message.SerializeToString(&serialized); - google::protobuf::DynamicMessageFactory factory; - google::protobuf::scoped_ptr message(factory.GetPrototype( - proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New()); + DynamicMessageFactory factory; + std::unique_ptr message( + factory + .GetPrototype( + proto2_preserve_unknown_enum_unittest::MyMessage::descriptor()) + ->New()); EXPECT_EQ(true, message->ParseFromString(serialized)); // The intermediate message has everything in its "unknown fields". proto2_preserve_unknown_enum_unittest::MyMessage message2; message2.CopyFrom(*message); message2.DiscardUnknownFields(); - EXPECT_EQ(0, message2.ByteSize()); + EXPECT_EQ(0, message2.ByteSizeLong()); // But when we pass it to the correct structure, all values are there. serialized.clear(); @@ -181,30 +178,28 @@ TEST(PreserveUnknownEnumTest, DynamicProto2HidesUnknownValues) { TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) { proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; FillMessage(&orig_message); - string serialized; + std::string serialized; orig_message.SerializeToString(&serialized); proto3_preserve_unknown_enum_unittest::MyMessage message; EXPECT_EQ(true, message.ParseFromString(serialized)); CheckMessage(message); - const google::protobuf::Reflection* r = message.GetReflection(); - const google::protobuf::Descriptor* d = message.GetDescriptor(); - const google::protobuf::FieldDescriptor* field = d->FindFieldByName("e"); + const Reflection* r = message.GetReflection(); + const Descriptor* d = message.GetDescriptor(); + const FieldDescriptor* field = d->FindFieldByName("e"); // This should dynamically create an EnumValueDescriptor. - const google::protobuf::EnumValueDescriptor* enum_value = r->GetEnum(message, field); + const EnumValueDescriptor* enum_value = r->GetEnum(message, field); EXPECT_EQ(enum_value->number(), static_cast(proto3_preserve_unknown_enum_unittest::E_EXTRA)); // Fetching value for a second time should return the same pointer. - const google::protobuf::EnumValueDescriptor* enum_value_second = - r->GetEnum(message, field); + const EnumValueDescriptor* enum_value_second = r->GetEnum(message, field); EXPECT_EQ(enum_value, enum_value_second); // Check the repeated case too. - const google::protobuf::FieldDescriptor* repeated_field = - d->FindFieldByName("repeated_e"); + const FieldDescriptor* repeated_field = d->FindFieldByName("repeated_e"); enum_value = r->GetRepeatedEnum(message, repeated_field, 0); EXPECT_EQ(enum_value->number(), static_cast(proto3_preserve_unknown_enum_unittest::E_EXTRA)); @@ -213,7 +208,7 @@ TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) { // We should be able to use the returned value descriptor to set a value on // another message. - google::protobuf::Message* m = message.New(); + Message* m = message.New(); r->SetEnum(m, field, enum_value); EXPECT_EQ(enum_value, r->GetEnum(*m, field)); delete m; @@ -222,12 +217,11 @@ TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) { // Test that the new integer-based enum reflection API works. TEST(PreserveUnknownEnumTest, IntegerEnumReflectionAPI) { proto3_preserve_unknown_enum_unittest::MyMessage message; - const google::protobuf::Reflection* r = message.GetReflection(); - const google::protobuf::Descriptor* d = message.GetDescriptor(); + const Reflection* r = message.GetReflection(); + const Descriptor* d = message.GetDescriptor(); - const google::protobuf::FieldDescriptor* singular_field = d->FindFieldByName("e"); - const google::protobuf::FieldDescriptor* repeated_field = - d->FindFieldByName("repeated_e"); + const FieldDescriptor* singular_field = d->FindFieldByName("e"); + const FieldDescriptor* repeated_field = d->FindFieldByName("repeated_e"); r->SetEnumValue(&message, singular_field, 42); EXPECT_EQ(42, r->GetEnumValue(message, singular_field)); @@ -236,51 +230,58 @@ TEST(PreserveUnknownEnumTest, IntegerEnumReflectionAPI) { EXPECT_EQ(42, r->GetRepeatedEnumValue(message, repeated_field, 0)); r->SetRepeatedEnumValue(&message, repeated_field, 1, 84); EXPECT_EQ(84, r->GetRepeatedEnumValue(message, repeated_field, 1)); - const google::protobuf::EnumValueDescriptor* enum_value = r->GetEnum(message, - singular_field); + const EnumValueDescriptor* enum_value = r->GetEnum(message, singular_field); EXPECT_EQ(42, enum_value->number()); } // Test that the EnumValue API works properly for proto2 messages as well. TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) { protobuf_unittest::TestAllTypes message; // proto2 message - const google::protobuf::Reflection* r = message.GetReflection(); - const google::protobuf::Descriptor* d = message.GetDescriptor(); - const google::protobuf::FieldDescriptor* repeated_field = + const Reflection* r = message.GetReflection(); + const Descriptor* d = message.GetDescriptor(); + const FieldDescriptor* repeated_field = d->FindFieldByName("repeated_nested_enum"); // Add one element to the repeated field so that we can test // SetRepeatedEnumValue. - const google::protobuf::EnumValueDescriptor* enum_value = + const EnumValueDescriptor* enum_value = repeated_field->enum_type()->FindValueByName("BAR"); EXPECT_TRUE(enum_value != NULL); r->AddEnum(&message, repeated_field, enum_value); -#ifdef PROTOBUF_HAS_DEATH_TEST - const google::protobuf::FieldDescriptor* singular_field = + const FieldDescriptor* singular_field = d->FindFieldByName("optional_nested_enum"); - // Enum-field integer-based setters GOOGLE_DCHECK-fail on invalid values, in order to - // remain consistent with proto2 generated code. - EXPECT_DEBUG_DEATH({ - r->SetEnumValue(&message, singular_field, 4242); - r->GetEnum(message, singular_field)->number(); - }, "SetEnumValue accepts only valid integer values"); - EXPECT_DEBUG_DEATH({ - r->SetRepeatedEnumValue(&message, repeated_field, 0, 4242); - r->GetRepeatedEnum(message, repeated_field, 0); - }, "SetRepeatedEnumValue accepts only valid integer values"); - EXPECT_DEBUG_DEATH({ - r->AddEnumValue(&message, repeated_field, 4242); - r->GetRepeatedEnum(message, repeated_field, 1); - }, "AddEnumValue accepts only valid integer values"); -#endif // PROTOBUF_HAS_DEATH_TEST + // Enum-field integer-based setters treat as unknown integer values as + // unknown fields. + r->SetEnumValue(&message, singular_field, 4242); + EXPECT_EQ(r->GetEnum(message, singular_field)->number(), + protobuf_unittest::TestAllTypes::FOO); + r->SetRepeatedEnumValue(&message, repeated_field, 0, 4242); + // repeated_nested_enum was set to bar above, this should not have changed. + EXPECT_EQ(r->GetRepeatedEnum(message, repeated_field, 0)->number(), + protobuf_unittest::TestAllTypes::BAR); + r->AddEnumValue(&message, repeated_field, 4242); + // No element should be added + EXPECT_EQ(message.repeated_nested_enum_size(), 1); + + // We require the enums to end up in unknown field set + ASSERT_EQ(message.unknown_fields().field_count(), 3); + EXPECT_EQ(message.unknown_fields().field(0).number(), + singular_field->number()); + EXPECT_EQ(message.unknown_fields().field(0).varint(), 4242); + EXPECT_EQ(message.unknown_fields().field(1).number(), + repeated_field->number()); + EXPECT_EQ(message.unknown_fields().field(1).varint(), 4242); + EXPECT_EQ(message.unknown_fields().field(2).number(), + repeated_field->number()); + EXPECT_EQ(message.unknown_fields().field(2).varint(), 4242); } TEST(PreserveUnknownEnumTest, SupportsUnknownEnumValuesAPI) { protobuf_unittest::TestAllTypes proto2_message; proto3_preserve_unknown_enum_unittest::MyMessage new_message; - const google::protobuf::Reflection* proto2_reflection = proto2_message.GetReflection(); - const google::protobuf::Reflection* new_reflection = new_message.GetReflection(); + const Reflection* proto2_reflection = proto2_message.GetReflection(); + const Reflection* new_reflection = new_message.GetReflection(); EXPECT_FALSE(proto2_reflection->SupportsUnknownEnumValues()); EXPECT_TRUE(new_reflection->SupportsUnknownEnumValues()); diff --git a/src/google/protobuf/proto3_arena_lite_unittest.cc b/src/google/protobuf/proto3_arena_lite_unittest.cc index 0f18c027e86f1..06b8d08c8f4b0 100644 --- a/src/google/protobuf/proto3_arena_lite_unittest.cc +++ b/src/google/protobuf/proto3_arena_lite_unittest.cc @@ -28,23 +28,18 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include #include -#ifndef _SHARED_PTR_H -#include -#endif +#include #include -#include -#include -#include +#include #include #include #include -namespace google { -using proto3_arena_lite_unittest::TestAllTypes; +using proto3_arena_unittest::TestAllTypes; +namespace google { namespace protobuf { namespace { // We selectively set/check a few representative fields rather than all fields @@ -55,20 +50,16 @@ void SetAllFields(TestAllTypes* m) { m->set_optional_bytes("jkl;"); m->mutable_optional_nested_message()->set_bb(42); m->mutable_optional_foreign_message()->set_c(43); - m->set_optional_nested_enum( - proto3_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ); - m->set_optional_foreign_enum( - proto3_arena_lite_unittest::FOREIGN_BAZ); + m->set_optional_nested_enum(proto3_arena_unittest::TestAllTypes::BAZ); + m->set_optional_foreign_enum(proto3_arena_unittest::FOREIGN_BAZ); m->mutable_optional_lazy_message()->set_bb(45); m->add_repeated_int32(100); m->add_repeated_string("asdf"); m->add_repeated_bytes("jkl;"); m->add_repeated_nested_message()->set_bb(46); m->add_repeated_foreign_message()->set_c(47); - m->add_repeated_nested_enum( - proto3_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ); - m->add_repeated_foreign_enum( - proto3_arena_lite_unittest::FOREIGN_BAZ); + m->add_repeated_nested_enum(proto3_arena_unittest::TestAllTypes::BAZ); + m->add_repeated_foreign_enum(proto3_arena_unittest::FOREIGN_BAZ); m->add_repeated_lazy_message()->set_bb(49); m->set_oneof_uint32(1); @@ -84,10 +75,8 @@ void ExpectAllFieldsSet(const TestAllTypes& m) { EXPECT_EQ(42, m.optional_nested_message().bb()); EXPECT_EQ(true, m.has_optional_foreign_message()); EXPECT_EQ(43, m.optional_foreign_message().c()); - EXPECT_EQ(proto3_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ, - m.optional_nested_enum()); - EXPECT_EQ(proto3_arena_lite_unittest::FOREIGN_BAZ, - m.optional_foreign_enum()); + EXPECT_EQ(proto3_arena_unittest::TestAllTypes::BAZ, m.optional_nested_enum()); + EXPECT_EQ(proto3_arena_unittest::FOREIGN_BAZ, m.optional_foreign_enum()); EXPECT_EQ(true, m.has_optional_lazy_message()); EXPECT_EQ(45, m.optional_lazy_message().bb()); @@ -102,15 +91,14 @@ void ExpectAllFieldsSet(const TestAllTypes& m) { EXPECT_EQ(1, m.repeated_foreign_message_size()); EXPECT_EQ(47, m.repeated_foreign_message(0).c()); EXPECT_EQ(1, m.repeated_nested_enum_size()); - EXPECT_EQ(proto3_arena_lite_unittest::TestAllTypes_NestedEnum_BAZ, + EXPECT_EQ(proto3_arena_unittest::TestAllTypes::BAZ, m.repeated_nested_enum(0)); EXPECT_EQ(1, m.repeated_foreign_enum_size()); - EXPECT_EQ(proto3_arena_lite_unittest::FOREIGN_BAZ, - m.repeated_foreign_enum(0)); + EXPECT_EQ(proto3_arena_unittest::FOREIGN_BAZ, m.repeated_foreign_enum(0)); EXPECT_EQ(1, m.repeated_lazy_message_size()); EXPECT_EQ(49, m.repeated_lazy_message(0).bb()); - EXPECT_EQ(proto3_arena_lite_unittest::TestAllTypes::kOneofString, + EXPECT_EQ(proto3_arena_unittest::TestAllTypes::kOneofString, m.oneof_field_case()); EXPECT_EQ("test", m.oneof_string()); } @@ -143,7 +131,7 @@ TEST(Proto3ArenaLiteTest, Swap) { TEST(Proto3ArenaLiteTest, SetAllocatedMessage) { Arena arena; - TestAllTypes *arena_message = Arena::CreateMessage(&arena); + TestAllTypes* arena_message = Arena::CreateMessage(&arena); TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage; nested->set_bb(118); arena_message->set_allocated_optional_nested_message(nested); @@ -154,7 +142,7 @@ TEST(Proto3ArenaLiteTest, ReleaseMessage) { Arena arena; TestAllTypes* arena_message = Arena::CreateMessage(&arena); arena_message->mutable_optional_nested_message()->set_bb(118); - google::protobuf::scoped_ptr nested( + std::unique_ptr nested( arena_message->release_optional_nested_message()); EXPECT_EQ(118, nested->bb()); } diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc index 3a0fb804bee3e..7731b2841f511 100644 --- a/src/google/protobuf/proto3_arena_unittest.cc +++ b/src/google/protobuf/proto3_arena_unittest.cc @@ -28,24 +28,38 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include #include -#ifndef _SHARED_PTR_H -#include -#endif +#include #include #include #include #include +#include #include +#include #include #include +#include -namespace google { +using proto3_arena_unittest::ForeignMessage; using proto3_arena_unittest::TestAllTypes; +namespace google { namespace protobuf { + +namespace internal { + +class Proto3ArenaTestHelper { + public: + template + static Arena* GetOwningArena(const T& msg) { + return msg.GetOwningArena(); + } +}; + +} // namespace internal + namespace { // We selectively set/check a few representative fields rather than all fields // as this test is only expected to cover the basics of arena support. @@ -55,20 +69,16 @@ void SetAllFields(TestAllTypes* m) { m->set_optional_bytes("jkl;"); m->mutable_optional_nested_message()->set_bb(42); m->mutable_optional_foreign_message()->set_c(43); - m->set_optional_nested_enum( - proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ); - m->set_optional_foreign_enum( - proto3_arena_unittest::FOREIGN_BAZ); + m->set_optional_nested_enum(proto3_arena_unittest::TestAllTypes::BAZ); + m->set_optional_foreign_enum(proto3_arena_unittest::FOREIGN_BAZ); m->mutable_optional_lazy_message()->set_bb(45); m->add_repeated_int32(100); m->add_repeated_string("asdf"); m->add_repeated_bytes("jkl;"); m->add_repeated_nested_message()->set_bb(46); m->add_repeated_foreign_message()->set_c(47); - m->add_repeated_nested_enum( - proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ); - m->add_repeated_foreign_enum( - proto3_arena_unittest::FOREIGN_BAZ); + m->add_repeated_nested_enum(proto3_arena_unittest::TestAllTypes::BAZ); + m->add_repeated_foreign_enum(proto3_arena_unittest::FOREIGN_BAZ); m->add_repeated_lazy_message()->set_bb(49); m->set_oneof_uint32(1); @@ -84,10 +94,8 @@ void ExpectAllFieldsSet(const TestAllTypes& m) { EXPECT_EQ(42, m.optional_nested_message().bb()); EXPECT_EQ(true, m.has_optional_foreign_message()); EXPECT_EQ(43, m.optional_foreign_message().c()); - EXPECT_EQ(proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ, - m.optional_nested_enum()); - EXPECT_EQ(proto3_arena_unittest::FOREIGN_BAZ, - m.optional_foreign_enum()); + EXPECT_EQ(proto3_arena_unittest::TestAllTypes::BAZ, m.optional_nested_enum()); + EXPECT_EQ(proto3_arena_unittest::FOREIGN_BAZ, m.optional_foreign_enum()); EXPECT_EQ(true, m.has_optional_lazy_message()); EXPECT_EQ(45, m.optional_lazy_message().bb()); @@ -102,11 +110,10 @@ void ExpectAllFieldsSet(const TestAllTypes& m) { EXPECT_EQ(1, m.repeated_foreign_message_size()); EXPECT_EQ(47, m.repeated_foreign_message(0).c()); EXPECT_EQ(1, m.repeated_nested_enum_size()); - EXPECT_EQ(proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ, + EXPECT_EQ(proto3_arena_unittest::TestAllTypes::BAZ, m.repeated_nested_enum(0)); EXPECT_EQ(1, m.repeated_foreign_enum_size()); - EXPECT_EQ(proto3_arena_unittest::FOREIGN_BAZ, - m.repeated_foreign_enum(0)); + EXPECT_EQ(proto3_arena_unittest::FOREIGN_BAZ, m.repeated_foreign_enum(0)); EXPECT_EQ(1, m.repeated_lazy_message_size()); EXPECT_EQ(49, m.repeated_lazy_message(0).bb()); @@ -129,8 +136,7 @@ TEST(Proto3ArenaTest, Parsing) { ExpectAllFieldsSet(*arena_message); } -TEST(Proto3ArenaTest, UnknownFieldsDefaultDrop) { - ::google::protobuf::internal::SetProto3PreserveUnknownsDefault(false); +TEST(Proto3ArenaTest, UnknownFields) { TestAllTypes original; SetAllFields(&original); @@ -145,32 +151,83 @@ TEST(Proto3ArenaTest, UnknownFieldsDefaultDrop) { arena_message->GetReflection()->MutableUnknownFields(arena_message); // We can modify this UnknownFieldSet. unknown_fields->AddVarint(1, 2); - // But the change will never will serialized back. - ASSERT_EQ(original.ByteSize(), arena_message->ByteSize()); - ASSERT_TRUE( + // And the unknown fields should be changed. + ASSERT_NE(original.ByteSizeLong(), arena_message->ByteSizeLong()); + ASSERT_FALSE( arena_message->GetReflection()->GetUnknownFields(*arena_message).empty()); } -TEST(Proto3ArenaTest, UnknownFieldsDefaultPreserve) { - ::google::protobuf::internal::SetProto3PreserveUnknownsDefault(true); - TestAllTypes original; - SetAllFields(&original); +TEST(Proto3ArenaTest, GetArena) { + Arena arena; + + // Tests arena-allocated message and submessages. + auto* arena_message1 = Arena::CreateMessage(&arena); + auto* arena_submessage1 = arena_message1->mutable_optional_foreign_message(); + auto* arena_repeated_submessage1 = + arena_message1->add_repeated_foreign_message(); + EXPECT_EQ(&arena, arena_message1->GetArena()); + EXPECT_EQ(&arena, + internal::Proto3ArenaTestHelper::GetOwningArena(*arena_message1)); + EXPECT_EQ(&arena, arena_submessage1->GetArena()); + EXPECT_EQ(&arena, arena_repeated_submessage1->GetArena()); + + // Tests attached heap-allocated messages. + auto* arena_message2 = Arena::CreateMessage(&arena); + arena_message2->set_allocated_optional_foreign_message(new ForeignMessage()); + arena_message2->mutable_repeated_foreign_message()->AddAllocated( + new ForeignMessage()); + const auto& submessage2 = arena_message2->optional_foreign_message(); + const auto& repeated_submessage2 = + arena_message2->repeated_foreign_message(0); + EXPECT_EQ(nullptr, submessage2.GetArena()); + EXPECT_EQ(&arena, + internal::Proto3ArenaTestHelper::GetOwningArena(submessage2)); + EXPECT_EQ(nullptr, repeated_submessage2.GetArena()); + EXPECT_EQ(&arena, internal::Proto3ArenaTestHelper::GetOwningArena( + repeated_submessage2)); + // Tests message created by Arena::Create. + auto* arena_message3 = Arena::Create(&arena); + EXPECT_EQ(nullptr, arena_message3->GetArena()); + EXPECT_EQ(&arena, + internal::Proto3ArenaTestHelper::GetOwningArena(*arena_message3)); +} + +TEST(Proto3ArenaTest, GetArenaWithUnknown) { Arena arena; - TestAllTypes* arena_message = Arena::CreateMessage(&arena); - arena_message->ParseFromString(original.SerializeAsString()); - ExpectAllFieldsSet(*arena_message); - // In proto3 we can still get a pointer to the UnknownFieldSet through - // reflection API. - UnknownFieldSet* unknown_fields = - arena_message->GetReflection()->MutableUnknownFields(arena_message); - // We can modify this UnknownFieldSet. - unknown_fields->AddVarint(1, 2); - // And the unknown fields should be changed. - ASSERT_NE(original.ByteSize(), arena_message->ByteSize()); - ASSERT_FALSE( - arena_message->GetReflection()->GetUnknownFields(*arena_message).empty()); + // Tests arena-allocated message and submessages. + auto* arena_message1 = Arena::CreateMessage(&arena); + arena_message1->GetReflection()->MutableUnknownFields(arena_message1); + auto* arena_submessage1 = arena_message1->mutable_optional_foreign_message(); + arena_submessage1->GetReflection()->MutableUnknownFields(arena_submessage1); + auto* arena_repeated_submessage1 = + arena_message1->add_repeated_foreign_message(); + arena_repeated_submessage1->GetReflection()->MutableUnknownFields( + arena_repeated_submessage1); + EXPECT_EQ(&arena, arena_message1->GetArena()); + EXPECT_EQ(&arena, + internal::Proto3ArenaTestHelper::GetOwningArena(*arena_message1)); + EXPECT_EQ(&arena, arena_submessage1->GetArena()); + EXPECT_EQ(&arena, arena_repeated_submessage1->GetArena()); + + // Tests attached heap-allocated messages. + auto* arena_message2 = Arena::CreateMessage(&arena); + arena_message2->set_allocated_optional_foreign_message(new ForeignMessage()); + arena_message2->mutable_repeated_foreign_message()->AddAllocated( + new ForeignMessage()); + auto* submessage2 = arena_message2->mutable_optional_foreign_message(); + submessage2->GetReflection()->MutableUnknownFields(submessage2); + auto* repeated_submessage2 = + arena_message2->mutable_repeated_foreign_message(0); + repeated_submessage2->GetReflection()->MutableUnknownFields( + repeated_submessage2); + EXPECT_EQ(nullptr, submessage2->GetArena()); + EXPECT_EQ(&arena, + internal::Proto3ArenaTestHelper::GetOwningArena(*submessage2)); + EXPECT_EQ(nullptr, repeated_submessage2->GetArena()); + EXPECT_EQ(&arena, internal::Proto3ArenaTestHelper::GetOwningArena( + *repeated_submessage2)); } TEST(Proto3ArenaTest, Swap) { @@ -187,7 +244,7 @@ TEST(Proto3ArenaTest, Swap) { TEST(Proto3ArenaTest, SetAllocatedMessage) { Arena arena; - TestAllTypes *arena_message = Arena::CreateMessage(&arena); + TestAllTypes* arena_message = Arena::CreateMessage(&arena); TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage; nested->set_bb(118); arena_message->set_allocated_optional_nested_message(nested); @@ -198,13 +255,13 @@ TEST(Proto3ArenaTest, ReleaseMessage) { Arena arena; TestAllTypes* arena_message = Arena::CreateMessage(&arena); arena_message->mutable_optional_nested_message()->set_bb(118); - google::protobuf::scoped_ptr nested( + std::unique_ptr nested( arena_message->release_optional_nested_message()); EXPECT_EQ(118, nested->bb()); } TEST(Proto3ArenaTest, MessageFieldClear) { - // GitHub issue #310: https://github.com/google/protobuf/issues/310 + // GitHub issue #310: https://github.com/protocolbuffers/protobuf/issues/310 Arena arena; TestAllTypes* arena_message = Arena::CreateMessage(&arena); arena_message->mutable_optional_nested_message()->set_bb(118); @@ -218,8 +275,8 @@ TEST(Proto3ArenaTest, MessageFieldClearViaReflection) { TestAllTypes* message = Arena::CreateMessage(&arena); const Reflection* r = message->GetReflection(); const Descriptor* d = message->GetDescriptor(); - const FieldDescriptor* msg_field = d->FindFieldByName( - "optional_nested_message"); + const FieldDescriptor* msg_field = + d->FindFieldByName("optional_nested_message"); message->mutable_optional_nested_message()->set_bb(1); r->ClearField(message, msg_field); @@ -227,6 +284,331 @@ TEST(Proto3ArenaTest, MessageFieldClearViaReflection) { EXPECT_EQ(0, message->optional_nested_message().bb()); } +TEST(Proto3OptionalTest, OptionalFields) { + protobuf_unittest::TestProto3Optional msg; + EXPECT_FALSE(msg.has_optional_int32()); + msg.set_optional_int32(0); + EXPECT_TRUE(msg.has_optional_int32()); + + std::string serialized; + msg.SerializeToString(&serialized); + EXPECT_GT(serialized.size(), 0); + + msg.clear_optional_int32(); + EXPECT_FALSE(msg.has_optional_int32()); + msg.SerializeToString(&serialized); + EXPECT_EQ(serialized.size(), 0); +} + +TEST(Proto3OptionalTest, OptionalFieldDescriptor) { + const Descriptor* d = protobuf_unittest::TestProto3Optional::descriptor(); + + for (int i = 0; i < d->field_count(); i++) { + const FieldDescriptor* f = d->field(i); + if (HasPrefixString(f->name(), "singular")) { + EXPECT_FALSE(f->has_optional_keyword()) << f->full_name(); + EXPECT_FALSE(f->has_presence()) << f->full_name(); + EXPECT_FALSE(f->containing_oneof()) << f->full_name(); + } else { + EXPECT_TRUE(f->has_optional_keyword()) << f->full_name(); + EXPECT_TRUE(f->has_presence()) << f->full_name(); + EXPECT_TRUE(f->containing_oneof()) << f->full_name(); + } + } +} + +TEST(Proto3OptionalTest, OptionalField) { + protobuf_unittest::TestProto3Optional msg; + EXPECT_FALSE(msg.has_optional_int32()); + msg.set_optional_int32(0); + EXPECT_TRUE(msg.has_optional_int32()); + + std::string serialized; + msg.SerializeToString(&serialized); + EXPECT_GT(serialized.size(), 0); + + msg.clear_optional_int32(); + EXPECT_FALSE(msg.has_optional_int32()); + msg.SerializeToString(&serialized); + EXPECT_EQ(serialized.size(), 0); +} + +TEST(Proto3OptionalTest, OptionalFieldReflection) { + // Tests that oneof reflection works on synthetic oneofs. + // + // We test this more deeply elsewhere by parsing/serializing TextFormat (which + // doesn't treat synthetic oneofs specially, so reflects over them normally). + protobuf_unittest::TestProto3Optional msg; + const google::protobuf::Descriptor* d = msg.GetDescriptor(); + const google::protobuf::Reflection* r = msg.GetReflection(); + const google::protobuf::FieldDescriptor* f = d->FindFieldByName("optional_int32"); + const google::protobuf::OneofDescriptor* o = d->FindOneofByName("_optional_int32"); + GOOGLE_CHECK(f); + GOOGLE_CHECK(o); + EXPECT_TRUE(o->is_synthetic()); + + EXPECT_FALSE(r->HasField(msg, f)); + EXPECT_FALSE(r->HasOneof(msg, o)); + EXPECT_TRUE(r->GetOneofFieldDescriptor(msg, o) == nullptr); + + r->SetInt32(&msg, f, 123); + EXPECT_EQ(123, msg.optional_int32()); + EXPECT_EQ(123, r->GetInt32(msg, f)); + EXPECT_TRUE(r->HasField(msg, f)); + EXPECT_TRUE(r->HasOneof(msg, o)); + EXPECT_EQ(f, r->GetOneofFieldDescriptor(msg, o)); + + std::vector fields; + r->ListFields(msg, &fields); + EXPECT_EQ(1, fields.size()); + EXPECT_EQ(f, fields[0]); + + r->ClearOneof(&msg, o); + EXPECT_FALSE(r->HasField(msg, f)); + EXPECT_FALSE(r->HasOneof(msg, o)); + EXPECT_TRUE(r->GetOneofFieldDescriptor(msg, o) == nullptr); + + msg.set_optional_int32(123); + EXPECT_EQ(123, r->GetInt32(msg, f)); + EXPECT_TRUE(r->HasField(msg, f)); + EXPECT_TRUE(r->HasOneof(msg, o)); + EXPECT_EQ(f, r->GetOneofFieldDescriptor(msg, o)); + + r->ClearOneof(&msg, o); + EXPECT_FALSE(r->HasField(msg, f)); + EXPECT_FALSE(r->HasOneof(msg, o)); + EXPECT_TRUE(r->GetOneofFieldDescriptor(msg, o) == nullptr); +} + +// It's a regression test for b/160665543. +TEST(Proto3OptionalTest, ClearNonOptionalMessageField) { + protobuf_unittest::TestProto3OptionalMessage msg; + msg.mutable_nested_message(); + const google::protobuf::Descriptor* d = msg.GetDescriptor(); + const google::protobuf::Reflection* r = msg.GetReflection(); + const google::protobuf::FieldDescriptor* f = d->FindFieldByName("nested_message"); + r->ClearField(&msg, f); +} + +TEST(Proto3OptionalTest, ClearOptionalMessageField) { + protobuf_unittest::TestProto3OptionalMessage msg; + msg.mutable_optional_nested_message(); + const google::protobuf::Descriptor* d = msg.GetDescriptor(); + const google::protobuf::Reflection* r = msg.GetReflection(); + const google::protobuf::FieldDescriptor* f = + d->FindFieldByName("optional_nested_message"); + r->ClearField(&msg, f); +} + +TEST(Proto3OptionalTest, SwapNonOptionalMessageField) { + protobuf_unittest::TestProto3OptionalMessage msg1; + protobuf_unittest::TestProto3OptionalMessage msg2; + msg1.mutable_nested_message(); + const google::protobuf::Descriptor* d = msg1.GetDescriptor(); + const google::protobuf::Reflection* r = msg1.GetReflection(); + const google::protobuf::FieldDescriptor* f = d->FindFieldByName("nested_message"); + r->SwapFields(&msg1, &msg2, {f}); +} + +TEST(Proto3OptionalTest, SwapOptionalMessageField) { + protobuf_unittest::TestProto3OptionalMessage msg1; + protobuf_unittest::TestProto3OptionalMessage msg2; + msg1.mutable_optional_nested_message(); + const google::protobuf::Descriptor* d = msg1.GetDescriptor(); + const google::protobuf::Reflection* r = msg1.GetReflection(); + const google::protobuf::FieldDescriptor* f = + d->FindFieldByName("optional_nested_message"); + r->SwapFields(&msg1, &msg2, {f}); +} + +void SetAllFieldsZero(protobuf_unittest::TestProto3Optional* msg) { + msg->set_optional_int32(0); + msg->set_optional_int64(0); + msg->set_optional_uint32(0); + msg->set_optional_uint64(0); + msg->set_optional_sint32(0); + msg->set_optional_sint64(0); + msg->set_optional_fixed32(0); + msg->set_optional_fixed64(0); + msg->set_optional_sfixed32(0); + msg->set_optional_sfixed64(0); + msg->set_optional_float(0); + msg->set_optional_double(0); + msg->set_optional_bool(false); + msg->set_optional_string(""); + msg->set_optional_bytes(""); + msg->mutable_optional_nested_message(); + msg->mutable_lazy_nested_message(); + msg->set_optional_nested_enum( + protobuf_unittest::TestProto3Optional::UNSPECIFIED); +} + +void SetAllFieldsNonZero(protobuf_unittest::TestProto3Optional* msg) { + msg->set_optional_int32(101); + msg->set_optional_int64(102); + msg->set_optional_uint32(103); + msg->set_optional_uint64(104); + msg->set_optional_sint32(105); + msg->set_optional_sint64(106); + msg->set_optional_fixed32(107); + msg->set_optional_fixed64(108); + msg->set_optional_sfixed32(109); + msg->set_optional_sfixed64(110); + msg->set_optional_float(111); + msg->set_optional_double(112); + msg->set_optional_bool(true); + msg->set_optional_string("abc"); + msg->set_optional_bytes("def"); + msg->mutable_optional_nested_message(); + msg->mutable_lazy_nested_message(); + msg->set_optional_nested_enum(protobuf_unittest::TestProto3Optional::BAZ); +} + +void TestAllFieldsZero(const protobuf_unittest::TestProto3Optional& msg) { + EXPECT_EQ(0, msg.optional_int32()); + EXPECT_EQ(0, msg.optional_int64()); + EXPECT_EQ(0, msg.optional_uint32()); + EXPECT_EQ(0, msg.optional_uint64()); + EXPECT_EQ(0, msg.optional_sint32()); + EXPECT_EQ(0, msg.optional_sint64()); + EXPECT_EQ(0, msg.optional_fixed32()); + EXPECT_EQ(0, msg.optional_fixed64()); + EXPECT_EQ(0, msg.optional_sfixed32()); + EXPECT_EQ(0, msg.optional_sfixed64()); + EXPECT_EQ(0, msg.optional_float()); + EXPECT_EQ(0, msg.optional_double()); + EXPECT_EQ(0, msg.optional_bool()); + EXPECT_EQ("", msg.optional_string()); + EXPECT_EQ("", msg.optional_bytes()); + EXPECT_EQ(protobuf_unittest::TestProto3Optional::UNSPECIFIED, + msg.optional_nested_enum()); + + const Reflection* r = msg.GetReflection(); + const Descriptor* d = msg.GetDescriptor(); + EXPECT_EQ("", r->GetString(msg, d->FindFieldByName("optional_string"))); +} + +void TestAllFieldsNonZero(const protobuf_unittest::TestProto3Optional& msg) { + EXPECT_EQ(101, msg.optional_int32()); + EXPECT_EQ(102, msg.optional_int64()); + EXPECT_EQ(103, msg.optional_uint32()); + EXPECT_EQ(104, msg.optional_uint64()); + EXPECT_EQ(105, msg.optional_sint32()); + EXPECT_EQ(106, msg.optional_sint64()); + EXPECT_EQ(107, msg.optional_fixed32()); + EXPECT_EQ(108, msg.optional_fixed64()); + EXPECT_EQ(109, msg.optional_sfixed32()); + EXPECT_EQ(110, msg.optional_sfixed64()); + EXPECT_EQ(111, msg.optional_float()); + EXPECT_EQ(112, msg.optional_double()); + EXPECT_EQ(true, msg.optional_bool()); + EXPECT_EQ("abc", msg.optional_string()); + EXPECT_EQ("def", msg.optional_bytes()); + EXPECT_EQ(protobuf_unittest::TestProto3Optional::BAZ, + msg.optional_nested_enum()); +} + +void TestAllFieldsSet(const protobuf_unittest::TestProto3Optional& msg, + bool set) { + EXPECT_EQ(set, msg.has_optional_int32()); + EXPECT_EQ(set, msg.has_optional_int64()); + EXPECT_EQ(set, msg.has_optional_uint32()); + EXPECT_EQ(set, msg.has_optional_uint64()); + EXPECT_EQ(set, msg.has_optional_sint32()); + EXPECT_EQ(set, msg.has_optional_sint64()); + EXPECT_EQ(set, msg.has_optional_fixed32()); + EXPECT_EQ(set, msg.has_optional_fixed64()); + EXPECT_EQ(set, msg.has_optional_sfixed32()); + EXPECT_EQ(set, msg.has_optional_sfixed64()); + EXPECT_EQ(set, msg.has_optional_float()); + EXPECT_EQ(set, msg.has_optional_double()); + EXPECT_EQ(set, msg.has_optional_bool()); + EXPECT_EQ(set, msg.has_optional_string()); + EXPECT_EQ(set, msg.has_optional_bytes()); + EXPECT_EQ(set, msg.has_optional_nested_message()); + EXPECT_EQ(set, msg.has_lazy_nested_message()); + EXPECT_EQ(set, msg.has_optional_nested_enum()); +} + +TEST(Proto3OptionalTest, BinaryRoundTrip) { + protobuf_unittest::TestProto3Optional msg; + TestAllFieldsSet(msg, false); + SetAllFieldsZero(&msg); + TestAllFieldsZero(msg); + TestAllFieldsSet(msg, true); + + protobuf_unittest::TestProto3Optional msg2; + std::string serialized; + msg.SerializeToString(&serialized); + EXPECT_TRUE(msg2.ParseFromString(serialized)); + TestAllFieldsZero(msg2); + TestAllFieldsSet(msg2, true); +} + +TEST(Proto3OptionalTest, TextFormatRoundTripZeros) { + protobuf_unittest::TestProto3Optional msg; + SetAllFieldsZero(&msg); + + protobuf_unittest::TestProto3Optional msg2; + std::string text; + EXPECT_TRUE(TextFormat::PrintToString(msg, &text)); + EXPECT_TRUE(TextFormat::ParseFromString(text, &msg2)); + TestAllFieldsSet(msg2, true); + TestAllFieldsZero(msg2); +} + +TEST(Proto3OptionalTest, TextFormatRoundTripNonZeros) { + protobuf_unittest::TestProto3Optional msg; + SetAllFieldsNonZero(&msg); + + protobuf_unittest::TestProto3Optional msg2; + std::string text; + EXPECT_TRUE(TextFormat::PrintToString(msg, &text)); + EXPECT_TRUE(TextFormat::ParseFromString(text, &msg2)); + TestAllFieldsSet(msg2, true); + TestAllFieldsNonZero(msg2); +} + +TEST(Proto3OptionalTest, SwapRoundTripZero) { + protobuf_unittest::TestProto3Optional msg; + SetAllFieldsZero(&msg); + TestAllFieldsSet(msg, true); + + protobuf_unittest::TestProto3Optional msg2; + msg.Swap(&msg2); + TestAllFieldsSet(msg2, true); + TestAllFieldsZero(msg2); +} + +TEST(Proto3OptionalTest, SwapRoundTripNonZero) { + protobuf_unittest::TestProto3Optional msg; + SetAllFieldsNonZero(&msg); + TestAllFieldsSet(msg, true); + + protobuf_unittest::TestProto3Optional msg2; + msg.Swap(&msg2); + TestAllFieldsSet(msg2, true); + TestAllFieldsNonZero(msg2); +} + +TEST(Proto3OptionalTest, ReflectiveSwapRoundTrip) { + protobuf_unittest::TestProto3Optional msg; + SetAllFieldsZero(&msg); + TestAllFieldsSet(msg, true); + + protobuf_unittest::TestProto3Optional msg2; + msg2.GetReflection()->Swap(&msg, &msg2); + TestAllFieldsSet(msg2, true); + TestAllFieldsZero(msg2); +} + +TEST(Proto3OptionalTest, PlainFields) { + const Descriptor* d = TestAllTypes::descriptor(); + + EXPECT_FALSE(d->FindFieldByName("optional_int32")->has_presence()); + EXPECT_TRUE(d->FindFieldByName("oneof_nested_message")->has_presence()); +} + } // namespace } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/proto3_lite_unittest.cc b/src/google/protobuf/proto3_lite_unittest.cc index 2e2beea909883..abeeedb15f96c 100644 --- a/src/google/protobuf/proto3_lite_unittest.cc +++ b/src/google/protobuf/proto3_lite_unittest.cc @@ -28,118 +28,16 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include -#include -#ifndef _SHARED_PTR_H -#include -#endif -#include +#include -#include -#include -#include -#include -#include -#include +#define LITE_TEST_NAME Proto3LiteTest +#define UNITTEST ::proto3_unittest -namespace google { -using proto3_lite_unittest::TestAllTypes; +// Must include after the above macros. +#include +// Make extract script happy. +namespace google { namespace protobuf { -namespace { -// We selectively set/check a few representative fields rather than all fields -// as this test is only expected to cover the basics of lite support. -void SetAllFields(TestAllTypes* m) { - m->set_optional_int32(100); - m->set_optional_string("asdf"); - m->set_optional_bytes("jkl;"); - m->mutable_optional_nested_message()->set_bb(42); - m->mutable_optional_foreign_message()->set_c(43); - m->set_optional_nested_enum( - proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ); - m->set_optional_foreign_enum( - proto3_lite_unittest::FOREIGN_BAZ); - m->mutable_optional_lazy_message()->set_bb(45); - m->add_repeated_int32(100); - m->add_repeated_string("asdf"); - m->add_repeated_bytes("jkl;"); - m->add_repeated_nested_message()->set_bb(46); - m->add_repeated_foreign_message()->set_c(47); - m->add_repeated_nested_enum( - proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ); - m->add_repeated_foreign_enum( - proto3_lite_unittest::FOREIGN_BAZ); - m->add_repeated_lazy_message()->set_bb(49); - - m->set_oneof_uint32(1); - m->mutable_oneof_nested_message()->set_bb(50); - m->set_oneof_string("test"); // only this one remains set -} - -void ExpectAllFieldsSet(const TestAllTypes& m) { - EXPECT_EQ(100, m.optional_int32()); - EXPECT_EQ("asdf", m.optional_string()); - EXPECT_EQ("jkl;", m.optional_bytes()); - EXPECT_EQ(true, m.has_optional_nested_message()); - EXPECT_EQ(42, m.optional_nested_message().bb()); - EXPECT_EQ(true, m.has_optional_foreign_message()); - EXPECT_EQ(43, m.optional_foreign_message().c()); - EXPECT_EQ(proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ, - m.optional_nested_enum()); - EXPECT_EQ(proto3_lite_unittest::FOREIGN_BAZ, - m.optional_foreign_enum()); - EXPECT_EQ(true, m.has_optional_lazy_message()); - EXPECT_EQ(45, m.optional_lazy_message().bb()); - - EXPECT_EQ(1, m.repeated_int32_size()); - EXPECT_EQ(100, m.repeated_int32(0)); - EXPECT_EQ(1, m.repeated_string_size()); - EXPECT_EQ("asdf", m.repeated_string(0)); - EXPECT_EQ(1, m.repeated_bytes_size()); - EXPECT_EQ("jkl;", m.repeated_bytes(0)); - EXPECT_EQ(1, m.repeated_nested_message_size()); - EXPECT_EQ(46, m.repeated_nested_message(0).bb()); - EXPECT_EQ(1, m.repeated_foreign_message_size()); - EXPECT_EQ(47, m.repeated_foreign_message(0).c()); - EXPECT_EQ(1, m.repeated_nested_enum_size()); - EXPECT_EQ(proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ, - m.repeated_nested_enum(0)); - EXPECT_EQ(1, m.repeated_foreign_enum_size()); - EXPECT_EQ(proto3_lite_unittest::FOREIGN_BAZ, - m.repeated_foreign_enum(0)); - EXPECT_EQ(1, m.repeated_lazy_message_size()); - EXPECT_EQ(49, m.repeated_lazy_message(0).bb()); - - EXPECT_EQ(proto3_lite_unittest::TestAllTypes::kOneofString, - m.oneof_field_case()); - EXPECT_EQ("test", m.oneof_string()); -} - -// In this file we only test some basic functionalities of in proto3 and expect -// the rest is fully tested in proto2 unittests because proto3 shares most code -// with proto2. - -TEST(Proto3LiteTest, Parsing) { - TestAllTypes original; - SetAllFields(&original); - - TestAllTypes msg; - msg.ParseFromString(original.SerializeAsString()); - ExpectAllFieldsSet(msg); -} - -TEST(Proto3LiteTest, Swap) { - // Test Swap(). - TestAllTypes msg1; - TestAllTypes msg2; - msg1.set_optional_string("123"); - msg2.set_optional_string("3456"); - msg1.Swap(&msg2); - EXPECT_EQ("3456", msg1.optional_string()); - EXPECT_EQ("123", msg2.optional_string()); - EXPECT_EQ(msg1.ByteSize(), msg2.ByteSize() + 1); -} - -} // namespace } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/proto3_lite_unittest.inc b/src/google/protobuf/proto3_lite_unittest.inc new file mode 100644 index 0000000000000..85f428a0a8d59 --- /dev/null +++ b/src/google/protobuf/proto3_lite_unittest.inc @@ -0,0 +1,146 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include + +#include +#include +#include + +using UNITTEST::TestAllTypes; + +namespace google { +namespace protobuf { +namespace { +// We selectively set/check a few representative fields rather than all fields +// as this test is only expected to cover the basics of lite support. +void SetAllFields(TestAllTypes* m) { + m->set_optional_int32(100); + m->set_optional_string("asdf"); + m->set_optional_bytes("jkl;"); + m->mutable_optional_nested_message()->set_bb(42); + m->mutable_optional_foreign_message()->set_c(43); + m->set_optional_nested_enum(UNITTEST::TestAllTypes::BAZ); + m->set_optional_foreign_enum( + UNITTEST::FOREIGN_BAZ); + m->mutable_optional_lazy_message()->set_bb(45); + m->add_repeated_int32(100); + m->add_repeated_string("asdf"); + m->add_repeated_bytes("jkl;"); + m->add_repeated_nested_message()->set_bb(46); + m->add_repeated_foreign_message()->set_c(47); + m->add_repeated_nested_enum(UNITTEST::TestAllTypes::BAZ); + m->add_repeated_foreign_enum( + UNITTEST::FOREIGN_BAZ); + m->add_repeated_lazy_message()->set_bb(49); + + m->set_oneof_uint32(1); + m->mutable_oneof_nested_message()->set_bb(50); + m->set_oneof_string("test"); // only this one remains set +} + +void ExpectAllFieldsSet(const TestAllTypes& m) { + EXPECT_EQ(100, m.optional_int32()); + EXPECT_EQ("asdf", m.optional_string()); + EXPECT_EQ("jkl;", m.optional_bytes()); + EXPECT_EQ(true, m.has_optional_nested_message()); + EXPECT_EQ(42, m.optional_nested_message().bb()); + EXPECT_EQ(true, m.has_optional_foreign_message()); + EXPECT_EQ(43, m.optional_foreign_message().c()); + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, m.optional_nested_enum()); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, + m.optional_foreign_enum()); + EXPECT_EQ(true, m.has_optional_lazy_message()); + EXPECT_EQ(45, m.optional_lazy_message().bb()); + + EXPECT_EQ(1, m.repeated_int32_size()); + EXPECT_EQ(100, m.repeated_int32(0)); + EXPECT_EQ(1, m.repeated_string_size()); + EXPECT_EQ("asdf", m.repeated_string(0)); + EXPECT_EQ(1, m.repeated_bytes_size()); + EXPECT_EQ("jkl;", m.repeated_bytes(0)); + EXPECT_EQ(1, m.repeated_nested_message_size()); + EXPECT_EQ(46, m.repeated_nested_message(0).bb()); + EXPECT_EQ(1, m.repeated_foreign_message_size()); + EXPECT_EQ(47, m.repeated_foreign_message(0).c()); + EXPECT_EQ(1, m.repeated_nested_enum_size()); + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, m.repeated_nested_enum(0)); + EXPECT_EQ(1, m.repeated_foreign_enum_size()); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, + m.repeated_foreign_enum(0)); + EXPECT_EQ(1, m.repeated_lazy_message_size()); + EXPECT_EQ(49, m.repeated_lazy_message(0).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::kOneofString, + m.oneof_field_case()); + EXPECT_EQ("test", m.oneof_string()); +} + +// In this file we only test some basic functionalities of in proto3 and expect +// the rest is fully tested in proto2 unittests because proto3 shares most code +// with proto2. + +TEST(LITE_TEST_NAME, Parsing) { + TestAllTypes original; + SetAllFields(&original); + + TestAllTypes msg; + msg.ParseFromString(original.SerializeAsString()); + ExpectAllFieldsSet(msg); +} + +TEST(LITE_TEST_NAME, Swap) { + // Test Swap(). + TestAllTypes msg1; + TestAllTypes msg2; + msg1.set_optional_string("123"); + msg2.set_optional_string("3456"); + msg1.Swap(&msg2); + EXPECT_EQ("3456", msg1.optional_string()); + EXPECT_EQ("123", msg2.optional_string()); + EXPECT_EQ(msg1.ByteSize(), msg2.ByteSize() + 1); +} + +TEST(LITE_TEST_NAME, OneofHazzers) { + TestAllTypes msg; + msg.set_oneof_uint32(1); + msg.set_oneof_string("test"); + + EXPECT_EQ(true, msg.has_oneof_string()); + EXPECT_EQ(false, msg.has_oneof_uint32()); + EXPECT_EQ(false, msg.has_oneof_bytes()); + EXPECT_EQ(false, msg.has_oneof_nested_message()); +} + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h old mode 100755 new mode 100644 index fcb9a43559238..af8eb00ef84ca --- a/src/google/protobuf/reflection.h +++ b/src/google/protobuf/reflection.h @@ -34,49 +34,46 @@ #define GOOGLE_PROTOBUF_REFLECTION_H__ #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +#include + namespace google { namespace protobuf { namespace internal { -template +template struct RefTypeTraits; } // namespace internal -template +template RepeatedFieldRef Reflection::GetRepeatedFieldRef( const Message& message, const FieldDescriptor* field) const { return RepeatedFieldRef(message, field); } -template +template MutableRepeatedFieldRef Reflection::GetMutableRepeatedFieldRef( Message* message, const FieldDescriptor* field) const { return MutableRepeatedFieldRef(message, field); } // RepeatedFieldRef definition for non-message types. -template +template class RepeatedFieldRef< - T, typename internal::enable_if::value>::type> { + T, typename std::enable_if::value>::type> { typedef typename internal::RefTypeTraits::iterator IteratorType; typedef typename internal::RefTypeTraits::AccessorType AccessorType; public: - bool empty() const { - return accessor_->IsEmpty(data_); - } - int size() const { - return accessor_->Size(data_); - } - T Get(int index) const { - return accessor_->template Get(data_, index); - } + bool empty() const { return accessor_->IsEmpty(data_); } + int size() const { return accessor_->Size(data_); } + T Get(int index) const { return accessor_->template Get(data_, index); } typedef IteratorType iterator; typedef IteratorType const_iterator; @@ -86,22 +83,16 @@ class RepeatedFieldRef< typedef int size_type; typedef ptrdiff_t difference_type; - iterator begin() const { - return iterator(data_, accessor_, true); - } - iterator end() const { - return iterator(data_, accessor_, false); - } + iterator begin() const { return iterator(data_, accessor_, true); } + iterator end() const { return iterator(data_, accessor_, false); } private: friend class Reflection; - RepeatedFieldRef( - const Message& message, - const FieldDescriptor* field) { + RepeatedFieldRef(const Message& message, const FieldDescriptor* field) { const Reflection* reflection = message.GetReflection(); - data_ = reflection->RepeatedFieldData( - const_cast(&message), field, - internal::RefTypeTraits::cpp_type, NULL); + data_ = reflection->RepeatedFieldData(const_cast(&message), field, + internal::RefTypeTraits::cpp_type, + NULL); accessor_ = reflection->RepeatedFieldAccessor(field); } @@ -110,50 +101,38 @@ class RepeatedFieldRef< }; // MutableRepeatedFieldRef definition for non-message types. -template +template class MutableRepeatedFieldRef< - T, typename internal::enable_if::value>::type> { + T, typename std::enable_if::value>::type> { typedef typename internal::RefTypeTraits::AccessorType AccessorType; public: - bool empty() const { - return accessor_->IsEmpty(data_); - } - int size() const { - return accessor_->Size(data_); - } - T Get(int index) const { - return accessor_->template Get(data_, index); - } + bool empty() const { return accessor_->IsEmpty(data_); } + int size() const { return accessor_->Size(data_); } + T Get(int index) const { return accessor_->template Get(data_, index); } void Set(int index, const T& value) const { accessor_->template Set(data_, index, value); } - void Add(const T& value) const { - accessor_->template Add(data_, value); - } - void RemoveLast() const { - accessor_->RemoveLast(data_); - } + void Add(const T& value) const { accessor_->template Add(data_, value); } + void RemoveLast() const { accessor_->RemoveLast(data_); } void SwapElements(int index1, int index2) const { accessor_->SwapElements(data_, index1, index2); } - void Clear() const { - accessor_->Clear(data_); - } + void Clear() const { accessor_->Clear(data_); } void Swap(const MutableRepeatedFieldRef& other) const { accessor_->Swap(data_, other.accessor_, other.data_); } - template + template void MergeFrom(const Container& container) const { typedef typename Container::const_iterator Iterator; for (Iterator it = container.begin(); it != container.end(); ++it) { Add(*it); } } - template + template void CopyFrom(const Container& container) const { Clear(); MergeFrom(container); @@ -161,9 +140,7 @@ class MutableRepeatedFieldRef< private: friend class Reflection; - MutableRepeatedFieldRef( - Message* message, - const FieldDescriptor* field) { + MutableRepeatedFieldRef(Message* message, const FieldDescriptor* field) { const Reflection* reflection = message->GetReflection(); data_ = reflection->RepeatedFieldData( message, field, internal::RefTypeTraits::cpp_type, NULL); @@ -175,19 +152,15 @@ class MutableRepeatedFieldRef< }; // RepeatedFieldRef definition for message types. -template +template class RepeatedFieldRef< - T, typename internal::enable_if::value>::type> { + T, typename std::enable_if::value>::type> { typedef typename internal::RefTypeTraits::iterator IteratorType; typedef typename internal::RefTypeTraits::AccessorType AccessorType; public: - bool empty() const { - return accessor_->IsEmpty(data_); - } - int size() const { - return accessor_->Size(data_); - } + bool empty() const { return accessor_->IsEmpty(data_); } + int size() const { return accessor_->Size(data_); } // This method returns a reference to the underlying message object if it // exists. If a message object doesn't exist (e.g., data stored in serialized // form), scratch_space will be filled with the data and a reference to it @@ -202,9 +175,7 @@ class RepeatedFieldRef< } // Create a new message of the same type as the messages stored in this // repeated field. Caller takes ownership of the returned object. - T* NewMessage() const { - return static_cast(default_instance_->New()); - } + T* NewMessage() const { return static_cast(default_instance_->New()); } typedef IteratorType iterator; typedef IteratorType const_iterator; @@ -219,14 +190,12 @@ class RepeatedFieldRef< } iterator end() const { // The end iterator must not be dereferenced, no need for scratch space. - return iterator(data_, accessor_, false, NULL); + return iterator(data_, accessor_, false, nullptr); } private: friend class Reflection; - RepeatedFieldRef( - const Message& message, - const FieldDescriptor* field) { + RepeatedFieldRef(const Message& message, const FieldDescriptor* field) { const Reflection* reflection = message.GetReflection(); data_ = reflection->RepeatedFieldData( const_cast(&message), field, @@ -243,56 +212,44 @@ class RepeatedFieldRef< }; // MutableRepeatedFieldRef definition for message types. -template +template class MutableRepeatedFieldRef< - T, typename internal::enable_if::value>::type> { + T, typename std::enable_if::value>::type> { typedef typename internal::RefTypeTraits::AccessorType AccessorType; public: - bool empty() const { - return accessor_->IsEmpty(data_); - } - int size() const { - return accessor_->Size(data_); - } + bool empty() const { return accessor_->IsEmpty(data_); } + int size() const { return accessor_->Size(data_); } // See comments for RepeatedFieldRef::Get() const T& Get(int index, T* scratch_space) const { return *static_cast(accessor_->Get(data_, index, scratch_space)); } // Create a new message of the same type as the messages stored in this // repeated field. Caller takes ownership of the returned object. - T* NewMessage() const { - return static_cast(default_instance_->New()); - } + T* NewMessage() const { return static_cast(default_instance_->New()); } void Set(int index, const T& value) const { accessor_->Set(data_, index, &value); } - void Add(const T& value) const { - accessor_->Add(data_, &value); - } - void RemoveLast() const { - accessor_->RemoveLast(data_); - } + void Add(const T& value) const { accessor_->Add(data_, &value); } + void RemoveLast() const { accessor_->RemoveLast(data_); } void SwapElements(int index1, int index2) const { accessor_->SwapElements(data_, index1, index2); } - void Clear() const { - accessor_->Clear(data_); - } + void Clear() const { accessor_->Clear(data_); } void Swap(const MutableRepeatedFieldRef& other) const { accessor_->Swap(data_, other.accessor_, other.data_); } - template + template void MergeFrom(const Container& container) const { typedef typename Container::const_iterator Iterator; for (Iterator it = container.begin(); it != container.end(); ++it) { Add(*it); } } - template + template void CopyFrom(const Container& container) const { Clear(); MergeFrom(container); @@ -300,9 +257,7 @@ class MutableRepeatedFieldRef< private: friend class Reflection; - MutableRepeatedFieldRef( - Message* message, - const FieldDescriptor* field) { + MutableRepeatedFieldRef(Message* message, const FieldDescriptor* field) { const Reflection* reflection = message->GetReflection(); data_ = reflection->RepeatedFieldData( message, field, internal::RefTypeTraits::cpp_type, @@ -335,7 +290,7 @@ namespace internal { // CPPTYPE_FLOAT float float // CPPTYPE_BOOL bool bool // CPPTYPE_ENUM generated enum type int32 -// CPPTYPE_STRING string string +// CPPTYPE_STRING string std::string // CPPTYPE_MESSAGE generated message type google::protobuf::Message // or google::protobuf::Message // @@ -343,14 +298,13 @@ namespace internal { // // You can map from T to the actual type using RefTypeTraits: // typedef RefTypeTraits::AccessorValueType ActualType; -class LIBPROTOBUF_EXPORT RepeatedFieldAccessor { +class PROTOBUF_EXPORT RepeatedFieldAccessor { public: // Typedefs for clarity. typedef void Field; typedef void Value; typedef void Iterator; - virtual ~RepeatedFieldAccessor(); virtual bool IsEmpty(const Field* data) const = 0; virtual int Size(const Field* data) const = 0; // Depends on the underlying representation of the repeated field, this @@ -358,8 +312,8 @@ class LIBPROTOBUF_EXPORT RepeatedFieldAccessor { // exists, or fill the data into scratch_space and return scratch_space. // Callers of this method must ensure scratch_space is a valid pointer // to a mutable object of the correct type. - virtual const Value* Get( - const Field* data, int index, Value* scratch_space) const = 0; + virtual const Value* Get(const Field* data, int index, + Value* scratch_space) const = 0; virtual void Clear(Field* data) const = 0; virtual void Set(Field* data, int index, const Value* value) const = 0; @@ -392,16 +346,15 @@ class LIBPROTOBUF_EXPORT RepeatedFieldAccessor { // Templated methods that make using this interface easier for non-message // types. - template + template T Get(const Field* data, int index) const { typedef typename RefTypeTraits::AccessorValueType ActualType; ActualType scratch_space; - return static_cast( - *reinterpret_cast( - Get(data, index, static_cast(&scratch_space)))); + return static_cast(*reinterpret_cast( + Get(data, index, static_cast(&scratch_space)))); } - template + template void Set(Field* data, int index, const ValueType& value) const { typedef typename RefTypeTraits::AccessorValueType ActualType; // In this RepeatedFieldAccessor interface we pass/return data using @@ -415,7 +368,7 @@ class LIBPROTOBUF_EXPORT RepeatedFieldAccessor { Set(data, index, static_cast(&tmp)); } - template + template void Add(Field* data, const ValueType& value) const { typedef typename RefTypeTraits::AccessorValueType ActualType; // In this RepeatedFieldAccessor interface we pass/return data using @@ -428,10 +381,17 @@ class LIBPROTOBUF_EXPORT RepeatedFieldAccessor { ActualType tmp = static_cast(value); Add(data, static_cast(&tmp)); } + + protected: + // We want the destructor to be completely trivial as to allow it to be + // a function local static. Hence we make it non-virtual and protected, + // this class only live as part of a global singleton and should not be + // deleted. + ~RepeatedFieldAccessor() = default; }; // Implement (Mutable)RepeatedFieldRef::iterator -template +template class RepeatedFieldRefIterator : public std::iterator { typedef typename RefTypeTraits::AccessorValueType AccessorValueType; @@ -447,20 +407,17 @@ class RepeatedFieldRefIterator iterator_(begin ? accessor->BeginIterator(data) : accessor->EndIterator(data)), // The end iterator must not be dereferenced, no need for scratch space. - scratch_space_(begin ? new AccessorValueType : NULL) {} + scratch_space_(begin ? new AccessorValueType : nullptr) {} // Constructor for message fields. RepeatedFieldRefIterator(const void* data, - const RepeatedFieldAccessor* accessor, - bool begin, + const RepeatedFieldAccessor* accessor, bool begin, AccessorValueType* scratch_space) - : data_(data), accessor_(accessor), - iterator_(begin ? accessor->BeginIterator(data) : - accessor->EndIterator(data)), - scratch_space_(scratch_space) { - } - ~RepeatedFieldRefIterator() { - accessor_->DeleteIterator(data_, iterator_); - } + : data_(data), + accessor_(accessor), + iterator_(begin ? accessor->BeginIterator(data) + : accessor->EndIterator(data)), + scratch_space_(scratch_space) {} + ~RepeatedFieldRefIterator() { accessor_->DeleteIterator(data_, iterator_); } RepeatedFieldRefIterator operator++(int) { RepeatedFieldRefIterator tmp(*this); iterator_ = accessor_->AdvanceIterator(data_, iterator_); @@ -472,14 +429,12 @@ class RepeatedFieldRefIterator } IteratorValueType operator*() const { return static_cast( - *static_cast( - accessor_->GetIteratorValue( - data_, iterator_, scratch_space_.get()))); + *static_cast(accessor_->GetIteratorValue( + data_, iterator_, scratch_space_.get()))); } IteratorPointerType operator->() const { return static_cast( - accessor_->GetIteratorValue( - data_, iterator_, scratch_space_.get())); + accessor_->GetIteratorValue(data_, iterator_, scratch_space_.get())); } bool operator!=(const RepeatedFieldRefIterator& other) const { assert(data_ == other.data_); @@ -491,9 +446,9 @@ class RepeatedFieldRefIterator } RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other) - : data_(other.data_), accessor_(other.accessor_), - iterator_(accessor_->CopyIterator(data_, other.iterator_)) { - } + : data_(other.data_), + accessor_(other.accessor_), + iterator_(accessor_->CopyIterator(data_, other.iterator_)) {} RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) { if (this != &other) { accessor_->DeleteIterator(data_, iterator_); @@ -508,22 +463,23 @@ class RepeatedFieldRefIterator const void* data_; const RepeatedFieldAccessor* accessor_; void* iterator_; - google::protobuf::scoped_ptr scratch_space_; + std::unique_ptr scratch_space_; }; // TypeTraits that maps the type parameter T of RepeatedFieldRef or // MutableRepeatedFieldRef to corresponding iterator type, // RepeatedFieldAccessor type, etc. -template +template struct PrimitiveTraits { - static const bool is_primitive = false; + static constexpr bool is_primitive = false; }; -#define DEFINE_PRIMITIVE(TYPE, type) \ - template<> struct PrimitiveTraits { \ - static const bool is_primitive = true; \ - static const FieldDescriptor::CppType cpp_type = \ - FieldDescriptor::CPPTYPE_ ## TYPE; \ - }; +#define DEFINE_PRIMITIVE(TYPE, type) \ + template <> \ + struct PrimitiveTraits { \ + static const bool is_primitive = true; \ + static const FieldDescriptor::CppType cpp_type = \ + FieldDescriptor::CPPTYPE_##TYPE; \ + }; DEFINE_PRIMITIVE(INT32, int32) DEFINE_PRIMITIVE(UINT32, uint32) DEFINE_PRIMITIVE(INT64, int64) @@ -533,74 +489,66 @@ DEFINE_PRIMITIVE(DOUBLE, double) DEFINE_PRIMITIVE(BOOL, bool) #undef DEFINE_PRIMITIVE -template +template struct RefTypeTraits< - T, typename internal::enable_if::is_primitive>::type> { + T, typename std::enable_if::is_primitive>::type> { typedef RepeatedFieldRefIterator iterator; typedef RepeatedFieldAccessor AccessorType; typedef T AccessorValueType; typedef T IteratorValueType; typedef T* IteratorPointerType; - static const FieldDescriptor::CppType cpp_type = + static constexpr FieldDescriptor::CppType cpp_type = PrimitiveTraits::cpp_type; - static const Descriptor* GetMessageFieldDescriptor() { - return NULL; - } + static const Descriptor* GetMessageFieldDescriptor() { return NULL; } }; -template +template struct RefTypeTraits< - T, typename internal::enable_if::value>::type> { + T, typename std::enable_if::value>::type> { typedef RepeatedFieldRefIterator iterator; typedef RepeatedFieldAccessor AccessorType; // We use int32 for repeated enums in RepeatedFieldAccessor. typedef int32 AccessorValueType; typedef T IteratorValueType; typedef int32* IteratorPointerType; - static const FieldDescriptor::CppType cpp_type = + static constexpr FieldDescriptor::CppType cpp_type = FieldDescriptor::CPPTYPE_ENUM; - static const Descriptor* GetMessageFieldDescriptor() { - return NULL; - } + static const Descriptor* GetMessageFieldDescriptor() { return NULL; } }; -template +template struct RefTypeTraits< - T, typename internal::enable_if< ::google::protobuf::internal::is_same::value>::type> { + T, typename std::enable_if::value>::type> { typedef RepeatedFieldRefIterator iterator; typedef RepeatedFieldAccessor AccessorType; - typedef string AccessorValueType; - typedef const string IteratorValueType; - typedef const string* IteratorPointerType; - static const FieldDescriptor::CppType cpp_type = + typedef std::string AccessorValueType; + typedef const std::string IteratorValueType; + typedef const std::string* IteratorPointerType; + static constexpr FieldDescriptor::CppType cpp_type = FieldDescriptor::CPPTYPE_STRING; - static const Descriptor* GetMessageFieldDescriptor() { - return NULL; - } + static const Descriptor* GetMessageFieldDescriptor() { return NULL; } }; -template +template struct MessageDescriptorGetter { static const Descriptor* get() { return T::default_instance().GetDescriptor(); } }; -template<> +template <> struct MessageDescriptorGetter { - static const Descriptor* get() { - return NULL; - } + static const Descriptor* get() { return NULL; } }; -template +template struct RefTypeTraits< - T, typename internal::enable_if::value>::type> { + T, typename std::enable_if::value>::type> { typedef RepeatedFieldRefIterator iterator; typedef RepeatedFieldAccessor AccessorType; typedef Message AccessorValueType; typedef const T& IteratorValueType; typedef const T* IteratorPointerType; - static const FieldDescriptor::CppType cpp_type = + static constexpr FieldDescriptor::CppType cpp_type = FieldDescriptor::CPPTYPE_MESSAGE; static const Descriptor* GetMessageFieldDescriptor() { return MessageDescriptorGetter::get(); @@ -610,4 +558,6 @@ struct RefTypeTraits< } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_REFLECTION_H__ diff --git a/src/google/protobuf/reflection_internal.h b/src/google/protobuf/reflection_internal.h index fcb424715c39e..3ccf4a063f768 100644 --- a/src/google/protobuf/reflection_internal.h +++ b/src/google/protobuf/reflection_internal.h @@ -43,36 +43,34 @@ namespace internal { // corresponding random-access methods. class RandomAccessRepeatedFieldAccessor : public RepeatedFieldAccessor { public: - virtual ~RandomAccessRepeatedFieldAccessor() {} - - virtual Iterator* BeginIterator(const Field* data) const { + Iterator* BeginIterator(const Field* data) const override { return PositionToIterator(0); } - virtual Iterator* EndIterator(const Field* data) const { + Iterator* EndIterator(const Field* data) const override { return PositionToIterator(this->Size(data)); } - virtual Iterator* CopyIterator(const Field* data, - const Iterator* iterator) const { + Iterator* CopyIterator(const Field* data, + const Iterator* iterator) const override { return const_cast(iterator); } - virtual Iterator* AdvanceIterator(const Field* data, - Iterator* iterator) const { + Iterator* AdvanceIterator(const Field* data, + Iterator* iterator) const override { return PositionToIterator(IteratorToPosition(iterator) + 1); } - virtual bool EqualsIterator(const Field* data, - const Iterator* a, - const Iterator* b) const { + bool EqualsIterator(const Field* data, const Iterator* a, + const Iterator* b) const override { return a == b; } - virtual void DeleteIterator(const Field* data, Iterator* iterator) const { - } - virtual const Value* GetIteratorValue(const Field* data, - const Iterator* iterator, - Value* scratch_space) const { + void DeleteIterator(const Field* data, Iterator* iterator) const override {} + const Value* GetIteratorValue(const Field* data, const Iterator* iterator, + Value* scratch_space) const override { return Get(data, static_cast(IteratorToPosition(iterator)), scratch_space); } + protected: + ~RandomAccessRepeatedFieldAccessor() = default; + private: static intptr_t IteratorToPosition(const Iterator* iterator) { return reinterpret_cast(iterator); @@ -84,38 +82,38 @@ class RandomAccessRepeatedFieldAccessor : public RepeatedFieldAccessor { // Base class for RepeatedFieldAccessor implementations that manipulates // RepeatedField. -template +template class RepeatedFieldWrapper : public RandomAccessRepeatedFieldAccessor { public: RepeatedFieldWrapper() {} - virtual ~RepeatedFieldWrapper() {} - virtual bool IsEmpty(const Field* data) const { + bool IsEmpty(const Field* data) const override { return GetRepeatedField(data)->empty(); } - virtual int Size(const Field* data) const { + int Size(const Field* data) const override { return GetRepeatedField(data)->size(); } - virtual const Value* Get(const Field* data, int index, - Value* scratch_space) const { + const Value* Get(const Field* data, int index, + Value* scratch_space) const override { return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space); } - virtual void Clear(Field* data) const { + void Clear(Field* data) const override { MutableRepeatedField(data)->Clear(); } - virtual void Set(Field* data, int index, const Value* value) const { + void Set(Field* data, int index, const Value* value) const override { MutableRepeatedField(data)->Set(index, ConvertToT(value)); } - virtual void Add(Field* data, const Value* value) const { + void Add(Field* data, const Value* value) const override { MutableRepeatedField(data)->Add(ConvertToT(value)); } - virtual void RemoveLast(Field* data) const { + void RemoveLast(Field* data) const override { MutableRepeatedField(data)->RemoveLast(); } - virtual void SwapElements(Field* data, int index1, int index2) const { + void SwapElements(Field* data, int index1, int index2) const override { MutableRepeatedField(data)->SwapElements(index1, index2); } protected: + ~RepeatedFieldWrapper() = default; typedef RepeatedField RepeatedFieldType; static const RepeatedFieldType* GetRepeatedField(const Field* data) { return reinterpret_cast(data); @@ -124,14 +122,14 @@ class RepeatedFieldWrapper : public RandomAccessRepeatedFieldAccessor { return reinterpret_cast(data); } - // Convert an object recevied by this accessor to an object to be stored in + // Convert an object received by this accessor to an object to be stored in // the underlying RepeatedField. virtual T ConvertToT(const Value* value) const = 0; // Convert an object stored in RepeatedPtrField to an object that will be - // returned by this accessor. If the two objects have the same type (true - // for string fields with ctype=STRING), a pointer to the source object can - // be returned directly. Otherwise, data should be copied from value to + // returned by this accessor. If the two objects have the same type (true for + // string fields with ctype=STRING), a pointer to the source object can be + // returned directly. Otherwise, data should be copied from value to // scratch_space and scratch_space should be returned. virtual const Value* ConvertFromT(const T& value, Value* scratch_space) const = 0; @@ -139,40 +137,39 @@ class RepeatedFieldWrapper : public RandomAccessRepeatedFieldAccessor { // Base class for RepeatedFieldAccessor implementations that manipulates // RepeatedPtrField. -template +template class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor { public: - RepeatedPtrFieldWrapper() {} - virtual ~RepeatedPtrFieldWrapper() {} - virtual bool IsEmpty(const Field* data) const { + bool IsEmpty(const Field* data) const override { return GetRepeatedField(data)->empty(); } - virtual int Size(const Field* data) const { + int Size(const Field* data) const override { return GetRepeatedField(data)->size(); } - virtual const Value* Get(const Field* data, int index, - Value* scratch_space) const { + const Value* Get(const Field* data, int index, + Value* scratch_space) const override { return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space); } - virtual void Clear(Field* data) const { + void Clear(Field* data) const override { MutableRepeatedField(data)->Clear(); } - virtual void Set(Field* data, int index, const Value* value) const { + void Set(Field* data, int index, const Value* value) const override { ConvertToT(value, MutableRepeatedField(data)->Mutable(index)); } - virtual void Add(Field* data, const Value* value) const { + void Add(Field* data, const Value* value) const override { T* allocated = New(value); ConvertToT(value, allocated); MutableRepeatedField(data)->AddAllocated(allocated); } - virtual void RemoveLast(Field* data) const { + void RemoveLast(Field* data) const override { MutableRepeatedField(data)->RemoveLast(); } - virtual void SwapElements(Field* data, int index1, int index2) const { + void SwapElements(Field* data, int index1, int index2) const override { MutableRepeatedField(data)->SwapElements(index1, index2); } protected: + ~RepeatedPtrFieldWrapper() = default; typedef RepeatedPtrField RepeatedFieldType; static const RepeatedFieldType* GetRepeatedField(const Field* data) { return reinterpret_cast(data); @@ -192,9 +189,9 @@ class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor { virtual void ConvertToT(const Value* value, T* result) const = 0; // Convert an object stored in RepeatedPtrField to an object that will be - // returned by this accessor. If the two objects have the same type (true - // for string fields with ctype=STRING), a pointer to the source object can - // be returned directly. Otherwise, data should be copied from value to + // returned by this accessor. If the two objects have the same type (true for + // string fields with ctype=STRING), a pointer to the source object can be + // returned directly. Otherwise, data should be copied from value to // scratch_space and scratch_space should be returned. virtual const Value* ConvertFromT(const T& value, Value* scratch_space) const = 0; @@ -202,41 +199,39 @@ class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor { // An implementation of RandomAccessRepeatedFieldAccessor that manipulates // MapFieldBase. -class MapFieldAccessor : public RandomAccessRepeatedFieldAccessor { +class MapFieldAccessor final : public RandomAccessRepeatedFieldAccessor { public: MapFieldAccessor() {} virtual ~MapFieldAccessor() {} - virtual bool IsEmpty(const Field* data) const { + bool IsEmpty(const Field* data) const override { return GetRepeatedField(data)->empty(); } - virtual int Size(const Field* data) const { + int Size(const Field* data) const override { return GetRepeatedField(data)->size(); } - virtual const Value* Get(const Field* data, int index, - Value* scratch_space) const { + const Value* Get(const Field* data, int index, + Value* scratch_space) const override { return ConvertFromEntry(GetRepeatedField(data)->Get(index), scratch_space); } - virtual void Clear(Field* data) const { + void Clear(Field* data) const override { MutableRepeatedField(data)->Clear(); } - virtual void Set(Field* data, int index, const Value* value) const { + void Set(Field* data, int index, const Value* value) const override { ConvertToEntry(value, MutableRepeatedField(data)->Mutable(index)); } - virtual void Add(Field* data, const Value* value) const { + void Add(Field* data, const Value* value) const override { Message* allocated = New(value); ConvertToEntry(value, allocated); MutableRepeatedField(data)->AddAllocated(allocated); } - virtual void RemoveLast(Field* data) const { + void RemoveLast(Field* data) const override { MutableRepeatedField(data)->RemoveLast(); } - virtual void SwapElements(Field* data, int index1, int index2) const { + void SwapElements(Field* data, int index1, int index2) const override { MutableRepeatedField(data)->SwapElements(index1, index2); } - virtual void Swap( - Field* data, - const internal::RepeatedFieldAccessor* other_mutator, - Field* other_data) const { + void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, + Field* other_data) const override { GOOGLE_CHECK(this == other_mutator); MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); } @@ -268,19 +263,16 @@ class MapFieldAccessor : public RandomAccessRepeatedFieldAccessor { }; // Default implementations of RepeatedFieldAccessor for primitive types. -template -class RepeatedFieldPrimitiveAccessor : public RepeatedFieldWrapper { +template +class RepeatedFieldPrimitiveAccessor final : public RepeatedFieldWrapper { typedef void Field; typedef void Value; using RepeatedFieldWrapper::MutableRepeatedField; public: RepeatedFieldPrimitiveAccessor() {} - virtual ~RepeatedFieldPrimitiveAccessor() {} - virtual void Swap( - Field* data, - const internal::RepeatedFieldAccessor* other_mutator, - Field* other_data) const { + void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, + Field* other_data) const override { // Currently RepeatedFieldPrimitiveAccessor is the only implementation of // RepeatedFieldAccessor for primitive types. As we are using singletons // for these accessors, here "other_mutator" must be "this". @@ -289,90 +281,83 @@ class RepeatedFieldPrimitiveAccessor : public RepeatedFieldWrapper { } protected: - virtual T ConvertToT(const Value* value) const { + T ConvertToT(const Value* value) const override { return *static_cast(value); } - virtual const Value* ConvertFromT(const T& value, - Value* scratch_space) const { + const Value* ConvertFromT(const T& value, + Value* scratch_space) const override { return static_cast(&value); } }; // Default implementation of RepeatedFieldAccessor for string fields with // ctype=STRING. -class RepeatedPtrFieldStringAccessor : public RepeatedPtrFieldWrapper { +class RepeatedPtrFieldStringAccessor final + : public RepeatedPtrFieldWrapper { typedef void Field; typedef void Value; using RepeatedFieldAccessor::Add; public: RepeatedPtrFieldStringAccessor() {} - virtual ~RepeatedPtrFieldStringAccessor() {} - virtual void Swap( - Field* data, - const internal::RepeatedFieldAccessor* other_mutator, - Field* other_data) const { + void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, + Field* other_data) const override { if (this == other_mutator) { MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); } else { - RepeatedPtrField tmp; + RepeatedPtrField tmp; tmp.Swap(MutableRepeatedField(data)); int other_size = other_mutator->Size(other_data); for (int i = 0; i < other_size; ++i) { - Add(data, other_mutator->Get(other_data, i)); + Add(data, other_mutator->Get(other_data, i)); } int size = Size(data); other_mutator->Clear(other_data); for (int i = 0; i < size; ++i) { - other_mutator->Add(other_data, tmp.Get(i)); + other_mutator->Add(other_data, tmp.Get(i)); } } } protected: - virtual string* New(const Value*) const { - return new string(); - } - virtual void ConvertToT(const Value* value, string* result) const { - *result = *static_cast(value); + std::string* New(const Value*) const override { return new std::string(); } + void ConvertToT(const Value* value, std::string* result) const override { + *result = *static_cast(value); } - virtual const Value* ConvertFromT(const string& value, - Value* scratch_space) const { + const Value* ConvertFromT(const std::string& value, + Value* scratch_space) const override { return static_cast(&value); } }; -class RepeatedPtrFieldMessageAccessor +class RepeatedPtrFieldMessageAccessor final : public RepeatedPtrFieldWrapper { typedef void Field; typedef void Value; public: RepeatedPtrFieldMessageAccessor() {} - virtual ~RepeatedPtrFieldMessageAccessor() {} - virtual void Swap( - Field* data, - const internal::RepeatedFieldAccessor* other_mutator, - Field* other_data) const { + void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, + Field* other_data) const override { GOOGLE_CHECK(this == other_mutator); MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); } protected: - virtual Message* New(const Value* value) const { + Message* New(const Value* value) const override { return static_cast(value)->New(); } - virtual void ConvertToT(const Value* value, Message* result) const { + void ConvertToT(const Value* value, Message* result) const override { result->CopyFrom(*static_cast(value)); } - virtual const Value* ConvertFromT(const Message& value, - Value* scratch_space) const { + const Value* ConvertFromT(const Message& value, + Value* scratch_space) const override { return static_cast(&value); } }; } // namespace internal } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__ diff --git a/src/google/protobuf/reflection_ops.cc b/src/google/protobuf/reflection_ops.cc index d1867311848f9..9a622f4ac8a60 100644 --- a/src/google/protobuf/reflection_ops.cc +++ b/src/google/protobuf/reflection_ops.cc @@ -31,21 +31,36 @@ // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include #include #include -#include -#include +#include +#include #include +#include #include +#include #include -#include + +#include namespace google { namespace protobuf { namespace internal { +static const Reflection* GetReflectionOrDie(const Message& m) { + const Reflection* r = m.GetReflection(); + if (r == nullptr) { + const Descriptor* d = m.GetDescriptor(); + const std::string& mtype = d ? d->name() : "unknown"; + // RawMessage is one known type for which GetReflection() returns nullptr. + GOOGLE_LOG(FATAL) << "Message does not support reflection (type " << mtype << ")."; + } + return r; +} + void ReflectionOps::Copy(const Message& from, Message* to) { if (&from == to) return; Clear(to); @@ -57,113 +72,210 @@ void ReflectionOps::Merge(const Message& from, Message* to) { const Descriptor* descriptor = from.GetDescriptor(); GOOGLE_CHECK_EQ(to->GetDescriptor(), descriptor) - << "Tried to merge messages of different types " - << "(merge " << descriptor->full_name() - << " to " << to->GetDescriptor()->full_name() << ")"; + << "Tried to merge messages of different types " + << "(merge " << descriptor->full_name() << " to " + << to->GetDescriptor()->full_name() << ")"; - const Reflection* from_reflection = from.GetReflection(); - const Reflection* to_reflection = to->GetReflection(); + const Reflection* from_reflection = GetReflectionOrDie(from); + const Reflection* to_reflection = GetReflectionOrDie(*to); + bool is_from_generated = (from_reflection->GetMessageFactory() == + google::protobuf::MessageFactory::generated_factory()); + bool is_to_generated = (to_reflection->GetMessageFactory() == + google::protobuf::MessageFactory::generated_factory()); std::vector fields; - from_reflection->ListFields(from, &fields); - for (int i = 0; i < fields.size(); i++) { - const FieldDescriptor* field = fields[i]; - + from_reflection->ListFieldsOmitStripped(from, &fields); + for (const FieldDescriptor* field : fields) { if (field->is_repeated()) { + // Use map reflection if both are in map status and have the + // same map type to avoid sync with repeated field. + // Note: As from and to messages have the same descriptor, the + // map field types are the same if they are both generated + // messages or both dynamic messages. + if (is_from_generated == is_to_generated && field->is_map()) { + const MapFieldBase* from_field = + from_reflection->GetMapData(from, field); + MapFieldBase* to_field = to_reflection->MutableMapData(to, field); + if (to_field->IsMapValid() && from_field->IsMapValid()) { + to_field->MergeFrom(*from_field); + continue; + } + } int count = from_reflection->FieldSize(from, field); for (int j = 0; j < count; j++) { switch (field->cpp_type()) { -#define HANDLE_TYPE(CPPTYPE, METHOD) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - to_reflection->Add##METHOD(to, field, \ - from_reflection->GetRepeated##METHOD(from, field, j)); \ - break; - - HANDLE_TYPE(INT32 , Int32 ); - HANDLE_TYPE(INT64 , Int64 ); +#define HANDLE_TYPE(CPPTYPE, METHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + to_reflection->Add##METHOD( \ + to, field, from_reflection->GetRepeated##METHOD(from, field, j)); \ + break; + + HANDLE_TYPE(INT32, Int32); + HANDLE_TYPE(INT64, Int64); HANDLE_TYPE(UINT32, UInt32); HANDLE_TYPE(UINT64, UInt64); - HANDLE_TYPE(FLOAT , Float ); + HANDLE_TYPE(FLOAT, Float); HANDLE_TYPE(DOUBLE, Double); - HANDLE_TYPE(BOOL , Bool ); + HANDLE_TYPE(BOOL, Bool); HANDLE_TYPE(STRING, String); - HANDLE_TYPE(ENUM , Enum ); + HANDLE_TYPE(ENUM, Enum); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_MESSAGE: - to_reflection->AddMessage(to, field)->MergeFrom( - from_reflection->GetRepeatedMessage(from, field, j)); + const Message& from_child = + from_reflection->GetRepeatedMessage(from, field, j); + if (from_reflection == to_reflection) { + to_reflection + ->AddMessage(to, field, + from_child.GetReflection()->GetMessageFactory()) + ->MergeFrom(from_child); + } else { + to_reflection->AddMessage(to, field)->MergeFrom(from_child); + } break; } } } else { switch (field->cpp_type()) { -#define HANDLE_TYPE(CPPTYPE, METHOD) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - to_reflection->Set##METHOD(to, field, \ - from_reflection->Get##METHOD(from, field)); \ - break; - - HANDLE_TYPE(INT32 , Int32 ); - HANDLE_TYPE(INT64 , Int64 ); +#define HANDLE_TYPE(CPPTYPE, METHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + to_reflection->Set##METHOD(to, field, \ + from_reflection->Get##METHOD(from, field)); \ + break; + + HANDLE_TYPE(INT32, Int32); + HANDLE_TYPE(INT64, Int64); HANDLE_TYPE(UINT32, UInt32); HANDLE_TYPE(UINT64, UInt64); - HANDLE_TYPE(FLOAT , Float ); + HANDLE_TYPE(FLOAT, Float); HANDLE_TYPE(DOUBLE, Double); - HANDLE_TYPE(BOOL , Bool ); + HANDLE_TYPE(BOOL, Bool); HANDLE_TYPE(STRING, String); - HANDLE_TYPE(ENUM , Enum ); + HANDLE_TYPE(ENUM, Enum); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_MESSAGE: - to_reflection->MutableMessage(to, field)->MergeFrom( - from_reflection->GetMessage(from, field)); + const Message& from_child = from_reflection->GetMessage(from, field); + if (from_reflection == to_reflection) { + to_reflection + ->MutableMessage( + to, field, from_child.GetReflection()->GetMessageFactory()) + ->MergeFrom(from_child); + } else { + to_reflection->MutableMessage(to, field)->MergeFrom(from_child); + } break; } } } to_reflection->MutableUnknownFields(to)->MergeFrom( - from_reflection->GetUnknownFields(from)); + from_reflection->GetUnknownFields(from)); } void ReflectionOps::Clear(Message* message) { - const Reflection* reflection = message->GetReflection(); + const Reflection* reflection = GetReflectionOrDie(*message); std::vector fields; - reflection->ListFields(*message, &fields); - for (int i = 0; i < fields.size(); i++) { - reflection->ClearField(message, fields[i]); + reflection->ListFieldsOmitStripped(*message, &fields); + for (const FieldDescriptor* field : fields) { + reflection->ClearField(message, field); } reflection->MutableUnknownFields(message)->Clear(); } +bool ReflectionOps::IsInitialized(const Message& message, bool check_fields, + bool check_descendants) { + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* reflection = GetReflectionOrDie(message); + if (const int field_count = descriptor->field_count()) { + const FieldDescriptor* begin = descriptor->field(0); + const FieldDescriptor* end = begin + field_count; + GOOGLE_DCHECK_EQ(descriptor->field(field_count - 1), end - 1); + + if (check_fields) { + // Check required fields of this message. + for (const FieldDescriptor* field = begin; field != end; ++field) { + if (field->is_required() && !reflection->HasField(message, field)) { + return false; + } + } + } + + if (check_descendants) { + for (const FieldDescriptor* field = begin; field != end; ++field) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + const Descriptor* message_type = field->message_type(); + if (PROTOBUF_PREDICT_FALSE(message_type->options().map_entry())) { + if (message_type->field(1)->cpp_type() == + FieldDescriptor::CPPTYPE_MESSAGE) { + const MapFieldBase* map_field = + reflection->GetMapData(message, field); + if (map_field->IsMapValid()) { + MapIterator it(const_cast(&message), field); + MapIterator end(const_cast(&message), field); + for (map_field->MapBegin(&it), map_field->MapEnd(&end); + it != end; ++it) { + if (!it.GetValueRef().GetMessageValue().IsInitialized()) { + return false; + } + } + } + } + } else if (field->is_repeated()) { + const int size = reflection->FieldSize(message, field); + for (int j = 0; j < size; j++) { + if (!reflection->GetRepeatedMessage(message, field, j) + .IsInitialized()) { + return false; + } + } + } else if (reflection->HasField(message, field)) { + if (!reflection->GetMessage(message, field).IsInitialized()) { + return false; + } + } + } + } + } + } + if (check_descendants && reflection->HasExtensionSet(message) && + !reflection->GetExtensionSet(message).IsInitialized()) { + return false; + } + return true; +} + bool ReflectionOps::IsInitialized(const Message& message) { const Descriptor* descriptor = message.GetDescriptor(); - const Reflection* reflection = message.GetReflection(); + const Reflection* reflection = GetReflectionOrDie(message); // Check required fields of this message. - for (int i = 0; i < descriptor->field_count(); i++) { - if (descriptor->field(i)->is_required()) { - if (!reflection->HasField(message, descriptor->field(i))) { - return false; + { + const int field_count = descriptor->field_count(); + for (int i = 0; i < field_count; i++) { + if (descriptor->field(i)->is_required()) { + if (!reflection->HasField(message, descriptor->field(i))) { + return false; + } } } } // Check that sub-messages are initialized. std::vector fields; - reflection->ListFields(message, &fields); - for (int i = 0; i < fields.size(); i++) { - const FieldDescriptor* field = fields[i]; + // Should be safe to skip stripped fields because required fields are not + // stripped. + reflection->ListFieldsOmitStripped(message, &fields); + for (const FieldDescriptor* field : fields) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (field->is_map()) { const FieldDescriptor* value_field = field->message_type()->field(1); if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - MapFieldBase* map_field = - reflection->MapData(const_cast(&message), field); + const MapFieldBase* map_field = + reflection->GetMapData(message, field); if (map_field->IsMapValid()) { MapIterator iter(const_cast(&message), field); MapIterator end(const_cast(&message), field); @@ -185,7 +297,7 @@ bool ReflectionOps::IsInitialized(const Message& message) { for (int j = 0; j < size; j++) { if (!reflection->GetRepeatedMessage(message, field, j) - .IsInitialized()) { + .IsInitialized()) { return false; } } @@ -200,33 +312,54 @@ bool ReflectionOps::IsInitialized(const Message& message) { return true; } +static bool IsMapValueMessageTyped(const FieldDescriptor* map_field) { + return map_field->message_type()->field(1)->cpp_type() == + FieldDescriptor::CPPTYPE_MESSAGE; +} + void ReflectionOps::DiscardUnknownFields(Message* message) { - const Reflection* reflection = message->GetReflection(); + const Reflection* reflection = GetReflectionOrDie(*message); reflection->MutableUnknownFields(message)->Clear(); + // Walk through the fields of this message and DiscardUnknownFields on any + // messages present. std::vector fields; reflection->ListFields(*message, &fields); - for (int i = 0; i < fields.size(); i++) { - const FieldDescriptor* field = fields[i]; - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - if (field->is_repeated()) { - int size = reflection->FieldSize(*message, field); - for (int j = 0; j < size; j++) { - reflection->MutableRepeatedMessage(message, field, j) - ->DiscardUnknownFields(); + for (const FieldDescriptor* field : fields) { + // Skip over non-message fields. + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + continue; + } + // Discard the unknown fields in maps that contain message values. + if (field->is_map() && IsMapValueMessageTyped(field)) { + const MapFieldBase* map_field = + reflection->MutableMapData(message, field); + if (map_field->IsMapValid()) { + MapIterator iter(message, field); + MapIterator end(message, field); + for (map_field->MapBegin(&iter), map_field->MapEnd(&end); iter != end; + ++iter) { + iter.MutableValueRef()->MutableMessageValue()->DiscardUnknownFields(); } - } else { - reflection->MutableMessage(message, field)->DiscardUnknownFields(); } + // Discard every unknown field inside messages in a repeated field. + } else if (field->is_repeated()) { + int size = reflection->FieldSize(*message, field); + for (int j = 0; j < size; j++) { + reflection->MutableRepeatedMessage(message, field, j) + ->DiscardUnknownFields(); + } + // Discard the unknown fields inside an optional message. + } else { + reflection->MutableMessage(message, field)->DiscardUnknownFields(); } } } -static string SubMessagePrefix(const string& prefix, - const FieldDescriptor* field, - int index) { - string result(prefix); +static std::string SubMessagePrefix(const std::string& prefix, + const FieldDescriptor* field, int index) { + std::string result(prefix); if (field->is_extension()) { result.append("("); result.append(field->full_name()); @@ -236,34 +369,35 @@ static string SubMessagePrefix(const string& prefix, } if (index != -1) { result.append("["); - result.append(SimpleItoa(index)); + result.append(StrCat(index)); result.append("]"); } result.append("."); return result; } -void ReflectionOps::FindInitializationErrors( - const Message& message, - const string& prefix, - std::vector* errors) { +void ReflectionOps::FindInitializationErrors(const Message& message, + const std::string& prefix, + std::vector* errors) { const Descriptor* descriptor = message.GetDescriptor(); - const Reflection* reflection = message.GetReflection(); + const Reflection* reflection = GetReflectionOrDie(message); // Check required fields of this message. - for (int i = 0; i < descriptor->field_count(); i++) { - if (descriptor->field(i)->is_required()) { - if (!reflection->HasField(message, descriptor->field(i))) { - errors->push_back(prefix + descriptor->field(i)->name()); + { + const int field_count = descriptor->field_count(); + for (int i = 0; i < field_count; i++) { + if (descriptor->field(i)->is_required()) { + if (!reflection->HasField(message, descriptor->field(i))) { + errors->push_back(prefix + descriptor->field(i)->name()); + } } } } // Check sub-messages. std::vector fields; - reflection->ListFields(message, &fields); - for (int i = 0; i < fields.size(); i++) { - const FieldDescriptor* field = fields[i]; + reflection->ListFieldsOmitStripped(message, &fields); + for (const FieldDescriptor* field : fields) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (field->is_repeated()) { @@ -271,21 +405,36 @@ void ReflectionOps::FindInitializationErrors( for (int j = 0; j < size; j++) { const Message& sub_message = - reflection->GetRepeatedMessage(message, field, j); + reflection->GetRepeatedMessage(message, field, j); FindInitializationErrors(sub_message, - SubMessagePrefix(prefix, field, j), - errors); + SubMessagePrefix(prefix, field, j), errors); } } else { const Message& sub_message = reflection->GetMessage(message, field); FindInitializationErrors(sub_message, - SubMessagePrefix(prefix, field, -1), - errors); + SubMessagePrefix(prefix, field, -1), errors); } } } } +void GenericSwap(Message* m1, Message* m2) { + Arena* m2_arena = m2->GetArena(); + GOOGLE_DCHECK(m1->GetArena() != m2_arena); + + // Copy semantics in this case. We try to improve efficiency by placing the + // temporary on |m2|'s arena so that messages are copied twice rather than + // three times. + Message* tmp = m2->New(m2_arena); + std::unique_ptr tmp_deleter(m2_arena == nullptr ? tmp : nullptr); + tmp->CheckTypeAndMergeFrom(*m1); + m1->Clear(); + m1->CheckTypeAndMergeFrom(*m2); + m2->GetReflection()->Swap(tmp, m2); +} + } // namespace internal } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/reflection_ops.h b/src/google/protobuf/reflection_ops.h index 45d8c650ef815..fb98714defe33 100644 --- a/src/google/protobuf/reflection_ops.h +++ b/src/google/protobuf/reflection_ops.h @@ -41,6 +41,12 @@ #include #include +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +#include + namespace google { namespace protobuf { namespace internal { @@ -54,20 +60,22 @@ namespace internal { // the Message interface. // // This class is really a namespace that contains only static methods. -class LIBPROTOBUF_EXPORT ReflectionOps { +class PROTOBUF_EXPORT ReflectionOps { public: static void Copy(const Message& from, Message* to); static void Merge(const Message& from, Message* to); static void Clear(Message* message); static bool IsInitialized(const Message& message); + static bool IsInitialized(const Message& message, bool check_fields, + bool check_descendants); static void DiscardUnknownFields(Message* message); // Finds all unset required fields in the message and adds their full // paths (e.g. "foo.bar[5].baz") to *names. "prefix" will be attached to // the front of each name. static void FindInitializationErrors(const Message& message, - const string& prefix, - std::vector* errors); + const std::string& prefix, + std::vector* errors); private: // All methods are static. No need to construct. @@ -76,6 +84,8 @@ class LIBPROTOBUF_EXPORT ReflectionOps { } // namespace internal } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_REFLECTION_OPS_H__ diff --git a/src/google/protobuf/reflection_ops_unittest.cc b/src/google/protobuf/reflection_ops_unittest.cc index 9cedb34229fa0..dee2af2c5d9c1 100644 --- a/src/google/protobuf/reflection_ops_unittest.cc +++ b/src/google/protobuf/reflection_ops_unittest.cc @@ -33,9 +33,9 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include -#include -#include #include +#include +#include #include #include @@ -128,18 +128,21 @@ TEST(ReflectionOpsTest, MergeExtensions) { TestUtil::SetAllExtensions(&message); // This field will test merging into an empty spot. - message2.SetExtension(unittest::optional_int32_extension, - message.GetExtension(unittest::optional_int32_extension)); + message2.SetExtension( + unittest::optional_int32_extension, + message.GetExtension(unittest::optional_int32_extension)); message.ClearExtension(unittest::optional_int32_extension); // This tests overwriting. - message2.SetExtension(unittest::optional_string_extension, - message.GetExtension(unittest::optional_string_extension)); + message2.SetExtension( + unittest::optional_string_extension, + message.GetExtension(unittest::optional_string_extension)); message.SetExtension(unittest::optional_string_extension, "something else"); // This tests concatenating. - message2.AddExtension(unittest::repeated_int32_extension, - message.GetExtension(unittest::repeated_int32_extension, 1)); + message2.AddExtension( + unittest::repeated_int32_extension, + message.GetExtension(unittest::repeated_int32_extension, 1)); int32 i = message.GetExtension(unittest::repeated_int32_extension, 0); message.ClearExtension(unittest::repeated_int32_extension); message.AddExtension(unittest::repeated_int32_extension, i); @@ -192,9 +195,7 @@ TEST(ReflectionOpsTest, MergeFromSelf) { unittest::TestAllTypes message; - EXPECT_DEATH( - ReflectionOps::Merge(message, &message), - "&from"); + EXPECT_DEATH(ReflectionOps::Merge(message, &message), "&from"); } #endif // PROTOBUF_HAS_DEATH_TEST @@ -235,9 +236,9 @@ TEST(ReflectionOpsTest, ClearExtensions) { &message.GetExtension(unittest::optionalgroup_extension)); EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(), &message.GetExtension(unittest::optional_nested_message_extension)); - EXPECT_NE(&unittest::ForeignMessage::default_instance(), - &message.GetExtension( - unittest::optional_foreign_message_extension)); + EXPECT_NE( + &unittest::ForeignMessage::default_instance(), + &message.GetExtension(unittest::optional_foreign_message_extension)); EXPECT_NE(&unittest_import::ImportMessage::default_instance(), &message.GetExtension(unittest::optional_import_message_extension)); } @@ -274,30 +275,29 @@ TEST(ReflectionOpsTest, DiscardUnknownFields) { TestUtil::SetAllFields(&message); // Set some unknown fields in message. - message.mutable_unknown_fields() - ->AddVarint(123456, 654321); + message.mutable_unknown_fields()->AddVarint(123456, 654321); message.mutable_optional_nested_message() - ->mutable_unknown_fields() - ->AddVarint(123456, 654321); + ->mutable_unknown_fields() + ->AddVarint(123456, 654321); message.mutable_repeated_nested_message(0) - ->mutable_unknown_fields() - ->AddVarint(123456, 654321); + ->mutable_unknown_fields() + ->AddVarint(123456, 654321); EXPECT_EQ(1, message.unknown_fields().field_count()); - EXPECT_EQ(1, message.optional_nested_message() - .unknown_fields().field_count()); - EXPECT_EQ(1, message.repeated_nested_message(0) - .unknown_fields().field_count()); + EXPECT_EQ(1, + message.optional_nested_message().unknown_fields().field_count()); + EXPECT_EQ(1, + message.repeated_nested_message(0).unknown_fields().field_count()); // Discard them. ReflectionOps::DiscardUnknownFields(&message); TestUtil::ExpectAllFieldsSet(message); EXPECT_EQ(0, message.unknown_fields().field_count()); - EXPECT_EQ(0, message.optional_nested_message() - .unknown_fields().field_count()); - EXPECT_EQ(0, message.repeated_nested_message(0) - .unknown_fields().field_count()); + EXPECT_EQ(0, + message.optional_nested_message().unknown_fields().field_count()); + EXPECT_EQ(0, + message.repeated_nested_message(0).unknown_fields().field_count()); } TEST(ReflectionOpsTest, DiscardUnknownExtensions) { @@ -305,46 +305,55 @@ TEST(ReflectionOpsTest, DiscardUnknownExtensions) { TestUtil::SetAllExtensions(&message); // Set some unknown fields. - message.mutable_unknown_fields() - ->AddVarint(123456, 654321); + message.mutable_unknown_fields()->AddVarint(123456, 654321); message.MutableExtension(unittest::optional_nested_message_extension) - ->mutable_unknown_fields() - ->AddVarint(123456, 654321); + ->mutable_unknown_fields() + ->AddVarint(123456, 654321); message.MutableExtension(unittest::repeated_nested_message_extension, 0) - ->mutable_unknown_fields() - ->AddVarint(123456, 654321); + ->mutable_unknown_fields() + ->AddVarint(123456, 654321); EXPECT_EQ(1, message.unknown_fields().field_count()); + EXPECT_EQ(1, message.GetExtension(unittest::optional_nested_message_extension) + .unknown_fields() + .field_count()); EXPECT_EQ(1, - message.GetExtension(unittest::optional_nested_message_extension) - .unknown_fields().field_count()); - EXPECT_EQ(1, - message.GetExtension(unittest::repeated_nested_message_extension, 0) - .unknown_fields().field_count()); + message.GetExtension(unittest::repeated_nested_message_extension, 0) + .unknown_fields() + .field_count()); // Discard them. ReflectionOps::DiscardUnknownFields(&message); TestUtil::ExpectAllExtensionsSet(message); EXPECT_EQ(0, message.unknown_fields().field_count()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension) + .unknown_fields() + .field_count()); EXPECT_EQ(0, - message.GetExtension(unittest::optional_nested_message_extension) - .unknown_fields().field_count()); - EXPECT_EQ(0, - message.GetExtension(unittest::repeated_nested_message_extension, 0) - .unknown_fields().field_count()); + message.GetExtension(unittest::repeated_nested_message_extension, 0) + .unknown_fields() + .field_count()); } TEST(ReflectionOpsTest, IsInitialized) { unittest::TestRequired message; EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + EXPECT_FALSE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true)); message.set_a(1); EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + EXPECT_FALSE(ReflectionOps::IsInitialized(message, true, true)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true)); message.set_b(2); EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + EXPECT_FALSE(ReflectionOps::IsInitialized(message, true, true)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true)); message.set_c(3); EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true)); } TEST(ReflectionOpsTest, ForeignIsInitialized) { @@ -353,26 +362,35 @@ TEST(ReflectionOpsTest, ForeignIsInitialized) { // Starts out initialized because the foreign message is itself an optional // field. EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true)); // Once we create that field, the message is no longer initialized. message.mutable_optional_message(); EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true)); // Initialize it. Now we're initialized. message.mutable_optional_message()->set_a(1); message.mutable_optional_message()->set_b(2); message.mutable_optional_message()->set_c(3); EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true)); // Add a repeated version of the message. No longer initialized. unittest::TestRequired* sub_message = message.add_repeated_message(); EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true)); // Initialize that repeated version. sub_message->set_a(1); sub_message->set_b(2); sub_message->set_c(3); EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true)); } TEST(ReflectionOpsTest, ExtensionIsInitialized) { @@ -381,46 +399,66 @@ TEST(ReflectionOpsTest, ExtensionIsInitialized) { // Starts out initialized because the foreign message is itself an optional // field. EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true)); // Once we create that field, the message is no longer initialized. message.MutableExtension(unittest::TestRequired::single); EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true)); // Initialize it. Now we're initialized. message.MutableExtension(unittest::TestRequired::single)->set_a(1); message.MutableExtension(unittest::TestRequired::single)->set_b(2); message.MutableExtension(unittest::TestRequired::single)->set_c(3); EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true)); // Add a repeated version of the message. No longer initialized. message.AddExtension(unittest::TestRequired::multi); EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true)); // Initialize that repeated version. message.MutableExtension(unittest::TestRequired::multi, 0)->set_a(1); message.MutableExtension(unittest::TestRequired::multi, 0)->set_b(2); message.MutableExtension(unittest::TestRequired::multi, 0)->set_c(3); EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true)); } TEST(ReflectionOpsTest, OneofIsInitialized) { unittest::TestRequiredOneof message; EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true)); message.mutable_foo_message(); EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true)); message.set_foo_int(1); EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true)); message.mutable_foo_message(); EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true)); message.mutable_foo_message()->set_required_double(0.1); EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false)); + EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true)); } -static string FindInitializationErrors(const Message& message) { - std::vector errors; +static std::string FindInitializationErrors(const Message& message) { + std::vector errors; ReflectionOps::FindInitializationErrors(message, "", &errors); return Join(errors, ","); } @@ -435,16 +473,17 @@ TEST(ReflectionOpsTest, FindForeignInitializationErrors) { message.mutable_optional_message(); message.add_repeated_message(); message.add_repeated_message(); - EXPECT_EQ("optional_message.a," - "optional_message.b," - "optional_message.c," - "repeated_message[0].a," - "repeated_message[0].b," - "repeated_message[0].c," - "repeated_message[1].a," - "repeated_message[1].b," - "repeated_message[1].c", - FindInitializationErrors(message)); + EXPECT_EQ( + "optional_message.a," + "optional_message.b," + "optional_message.c," + "repeated_message[0].a," + "repeated_message[0].b," + "repeated_message[0].c," + "repeated_message[1].a," + "repeated_message[1].b," + "repeated_message[1].c", + FindInitializationErrors(message)); } TEST(ReflectionOpsTest, FindExtensionInitializationErrors) { @@ -452,23 +491,53 @@ TEST(ReflectionOpsTest, FindExtensionInitializationErrors) { message.MutableExtension(unittest::TestRequired::single); message.AddExtension(unittest::TestRequired::multi); message.AddExtension(unittest::TestRequired::multi); - EXPECT_EQ("(protobuf_unittest.TestRequired.single).a," - "(protobuf_unittest.TestRequired.single).b," - "(protobuf_unittest.TestRequired.single).c," - "(protobuf_unittest.TestRequired.multi)[0].a," - "(protobuf_unittest.TestRequired.multi)[0].b," - "(protobuf_unittest.TestRequired.multi)[0].c," - "(protobuf_unittest.TestRequired.multi)[1].a," - "(protobuf_unittest.TestRequired.multi)[1].b," - "(protobuf_unittest.TestRequired.multi)[1].c", - FindInitializationErrors(message)); + EXPECT_EQ( + "(protobuf_unittest.TestRequired.single).a," + "(protobuf_unittest.TestRequired.single).b," + "(protobuf_unittest.TestRequired.single).c," + "(protobuf_unittest.TestRequired.multi)[0].a," + "(protobuf_unittest.TestRequired.multi)[0].b," + "(protobuf_unittest.TestRequired.multi)[0].c," + "(protobuf_unittest.TestRequired.multi)[1].a," + "(protobuf_unittest.TestRequired.multi)[1].b," + "(protobuf_unittest.TestRequired.multi)[1].c", + FindInitializationErrors(message)); } TEST(ReflectionOpsTest, FindOneofInitializationErrors) { unittest::TestRequiredOneof message; message.mutable_foo_message(); - EXPECT_EQ("foo_message.required_double", - FindInitializationErrors(message)); + EXPECT_EQ("foo_message.required_double", FindInitializationErrors(message)); +} + +TEST(ReflectionOpsTest, GenericSwap) { + Arena arena; + { + unittest::TestAllTypes message; + auto* arena_message = Arena::CreateMessage(&arena); + TestUtil::SetAllFields(arena_message); + const uint64 initial_arena_size = arena.SpaceUsed(); + + GenericSwap(&message, arena_message); + + TestUtil::ExpectAllFieldsSet(message); + TestUtil::ExpectClear(*arena_message); + // The temp should be allocated on the arena in this case. + EXPECT_GT(arena.SpaceUsed(), initial_arena_size); + } + { + unittest::TestAllTypes message; + auto* arena_message = Arena::CreateMessage(&arena); + TestUtil::SetAllFields(arena_message); + const uint64 initial_arena_size = arena.SpaceUsed(); + + GenericSwap(arena_message, &message); + + TestUtil::ExpectAllFieldsSet(message); + TestUtil::ExpectClear(*arena_message); + // The temp shouldn't be allocated on the arena in this case. + EXPECT_EQ(arena.SpaceUsed(), initial_arena_size); + } } } // namespace diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc index 5ca964c16776a..f5e83ffaba917 100644 --- a/src/google/protobuf/repeated_field.cc +++ b/src/google/protobuf/repeated_field.cc @@ -32,11 +32,15 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include + #include -#include #include #include +#include + +#include namespace google { namespace protobuf { @@ -51,19 +55,19 @@ void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) { return &rep_->elements[current_size_]; } Rep* old_rep = rep_; - Arena* arena = GetArenaNoVirtual(); - new_size = std::max(kMinRepeatedFieldAllocationSize, + Arena* arena = GetArena(); + new_size = std::max(internal::kRepeatedFieldLowerClampLimit, std::max(total_size_ * 2, new_size)); - GOOGLE_CHECK_LE(new_size, - (std::numeric_limits::max() - kRepHeaderSize) / - sizeof(old_rep->elements[0])) + GOOGLE_CHECK_LE( + static_cast(new_size), + static_cast((std::numeric_limits::max() - kRepHeaderSize) / + sizeof(old_rep->elements[0]))) << "Requested size is too large to fit into size_t."; size_t bytes = kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size; if (arena == NULL) { rep_ = reinterpret_cast(::operator new(bytes)); } else { - rep_ = reinterpret_cast( - ::google::protobuf::Arena::CreateArray(arena, bytes)); + rep_ = reinterpret_cast(Arena::CreateArray(arena, bytes)); } #if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) const int old_total_size = total_size_; @@ -103,8 +107,34 @@ void RepeatedPtrFieldBase::CloseGap(int start, int num) { rep_->allocated_size -= num; } +MessageLite* RepeatedPtrFieldBase::AddWeak(const MessageLite* prototype) { + if (rep_ != NULL && current_size_ < rep_->allocated_size) { + return reinterpret_cast(rep_->elements[current_size_++]); + } + if (!rep_ || rep_->allocated_size == total_size_) { + Reserve(total_size_ + 1); + } + ++rep_->allocated_size; + MessageLite* result = prototype + ? prototype->New(arena_) + : Arena::CreateMessage(arena_); + rep_->elements[current_size_++] = result; + return result; +} + } // namespace internal +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedPtrField; + } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index d8003b8fa95c5..9ba9e9359e948 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -46,6 +46,7 @@ #ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__ #define GOOGLE_PROTOBUF_REPEATED_FIELD_H__ +#include #ifdef _MSC_VER // This is required for min/max on VS2013 only. #include @@ -54,38 +55,54 @@ #include #include #include -#include +#include + #include #include -#include #include #include +#include +#include +#include -// Forward-declare these so that we can make them friends. -namespace google { -namespace upb { -namespace google_opensource { -class GMR_Handlers; -} // namespace google_opensource -} // namespace upb +// Must be included last. +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif +namespace google { namespace protobuf { class Message; +class Reflection; + +template +struct WeakRepeatedPtrField; namespace internal { class MergePartialFromCodedStreamHelper; -static const int kMinRepeatedFieldAllocationSize = 4; +// kRepeatedFieldLowerClampLimit is the smallest size that will be allocated +// when growing a repeated field. +constexpr int kRepeatedFieldLowerClampLimit = 4; + +// kRepeatedFieldUpperClampLimit is the lowest signed integer value that +// overflows when multiplied by 2 (which is undefined behavior). Sizes above +// this will clamp to the maximum int value instead of following exponential +// growth when growing a repeated field. +constexpr int kRepeatedFieldUpperClampLimit = + (std::numeric_limits::max() / 2) + 1; // A utility function for logging that doesn't need any template types. void LogIndexOutOfBounds(int index, int size); template inline int CalculateReserve(Iter begin, Iter end, std::forward_iterator_tag) { - return std::distance(begin, end); + return static_cast(std::distance(begin, end)); } template @@ -99,17 +116,60 @@ inline int CalculateReserve(Iter begin, Iter end) { typedef typename std::iterator_traits::iterator_category Category; return CalculateReserve(begin, end, Category()); } -} // namespace internal +// Swaps two blocks of memory of size sizeof(T). +template +inline void SwapBlock(char* p, char* q) { + T tmp; + memcpy(&tmp, p, sizeof(T)); + memcpy(p, q, sizeof(T)); + memcpy(q, &tmp, sizeof(T)); +} + +// Swaps two blocks of memory of size kSize: +// template void memswap(char* p, char* q); + +template +inline typename std::enable_if<(kSize == 0), void>::type memswap(char*, char*) { +} + +#define PROTO_MEMSWAP_DEF_SIZE(reg_type, max_size) \ + template \ + typename std::enable_if<(kSize >= sizeof(reg_type) && kSize < (max_size)), \ + void>::type \ + memswap(char* p, char* q) { \ + SwapBlock(p, q); \ + memswap(p + sizeof(reg_type), \ + q + sizeof(reg_type)); \ + } + +PROTO_MEMSWAP_DEF_SIZE(uint8, 2) +PROTO_MEMSWAP_DEF_SIZE(uint16, 4) +PROTO_MEMSWAP_DEF_SIZE(uint32, 8) + +#ifdef __SIZEOF_INT128__ +PROTO_MEMSWAP_DEF_SIZE(uint64, 16) +PROTO_MEMSWAP_DEF_SIZE(__uint128_t, (1u << 31)) +#else +PROTO_MEMSWAP_DEF_SIZE(uint64, (1u << 31)) +#endif + +#undef PROTO_MEMSWAP_DEF_SIZE + +} // namespace internal // RepeatedField is used to represent repeated fields of a primitive type (in // other words, everything except strings and nested Messages). Most users will // not ever use a RepeatedField directly; they will use the get-by-index, // set-by-index, and add accessors that are generated for all repeated fields. template -class RepeatedField PROTOBUF_FINAL { +class RepeatedField final { + static_assert( + alignof(Arena) >= alignof(Element), + "We only support types that have an alignment smaller than Arena"); + public: - RepeatedField(); + constexpr RepeatedField(); explicit RepeatedField(Arena* arena); RepeatedField(const RepeatedField& other); template @@ -118,6 +178,9 @@ class RepeatedField PROTOBUF_FINAL { RepeatedField& operator=(const RepeatedField& other); + RepeatedField(RepeatedField&& other) noexcept; + RepeatedField& operator=(RepeatedField&& other) noexcept; + bool empty() const; int size() const; @@ -127,11 +190,19 @@ class RepeatedField PROTOBUF_FINAL { const Element& operator[](int index) const { return Get(index); } Element& operator[](int index) { return *Mutable(index); } + const Element& at(int index) const; + Element& at(int index); + void Set(int index, const Element& value); void Add(const Element& value); // Appends a new element and return a pointer to it. // The new element is uninitialized if |Element| is a POD type. Element* Add(); + // Append elements in the range [begin, end) after reserving + // the appropriate number of elements. + template + void Add(Iter begin, Iter end); + // Remove the last element in the array. void RemoveLast(); @@ -204,15 +275,11 @@ class RepeatedField PROTOBUF_FINAL { // Reverse iterator support typedef std::reverse_iterator const_reverse_iterator; typedef std::reverse_iterator reverse_iterator; - reverse_iterator rbegin() { - return reverse_iterator(end()); - } + reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } - reverse_iterator rend() { - return reverse_iterator(begin()); - } + reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } @@ -241,8 +308,9 @@ class RepeatedField PROTOBUF_FINAL { iterator erase(const_iterator first, const_iterator last); // Get the Arena on which this RepeatedField stores its elements. - ::google::protobuf::Arena* GetArena() const { - return GetArenaNoVirtual(); + inline Arena* GetArena() const { + return (total_size_ == 0) ? static_cast(arena_or_elements_) + : rep()->arena; } // For internal use only. @@ -251,7 +319,7 @@ class RepeatedField PROTOBUF_FINAL { inline void InternalSwap(RepeatedField* other); private: - static const int kInitialSize = 0; + static constexpr int kInitialSize = 0; // A note on the representation here (see also comment below for // RepeatedPtrFieldBase's struct Rep): // @@ -266,39 +334,60 @@ class RepeatedField PROTOBUF_FINAL { int total_size_; struct Rep { Arena* arena; - Element elements[1]; + // Here we declare a huge array as a way of approximating C's "flexible + // array member" feature without relying on undefined behavior. + Element elements[(std::numeric_limits::max() - 2 * sizeof(Arena*)) / + sizeof(Element)]; }; - // We can not use sizeof(Rep) - sizeof(Element) due to the trailing padding on - // the struct. We can not use sizeof(Arena*) as well because there might be - // a "gap" after the field arena and before the field elements (e.g., when - // Element is double and pointer is 32bit). - static const size_t kRepHeaderSize; - // Contains arena ptr and the elements array. We also keep the invariant that - // if rep_ is NULL, then arena is NULL. - Rep* rep_; + static constexpr size_t kRepHeaderSize = offsetof(Rep, elements); + + // If total_size_ == 0 this points to an Arena otherwise it points to the + // elements member of a Rep struct. Using this invariant allows the storage of + // the arena pointer without an extra allocation in the constructor. + void* arena_or_elements_; + + // Return pointer to elements array. + // pre-condition: the array must have been allocated. + Element* elements() const { + GOOGLE_DCHECK_GT(total_size_, 0); + // Because of above pre-condition this cast is safe. + return unsafe_elements(); + } + + // Return pointer to elements array if it exists otherwise either null or + // a invalid pointer is returned. This only happens for empty repeated fields, + // where you can't dereference this pointer anyway (it's empty). + Element* unsafe_elements() const { + return static_cast(arena_or_elements_); + } + + // Return pointer to the Rep struct. + // pre-condition: the Rep must have been allocated, ie elements() is safe. + Rep* rep() const { + char* addr = reinterpret_cast(elements()) - offsetof(Rep, elements); + return reinterpret_cast(addr); + } friend class Arena; typedef void InternalArenaConstructable_; + // Move the contents of |from| into |to|, possibly clobbering |from| in the + // process. For primitive types this is just a memcpy(), but it could be + // specialized for non-primitive types to, say, swap each element instead. void MoveArray(Element* to, Element* from, int size); // Copy the elements of |from| into |to|. void CopyArray(Element* to, const Element* from, int size); - // Internal helper expected by Arena methods. - inline Arena* GetArenaNoVirtual() const { - return (rep_ == NULL) ? NULL : rep_->arena; - } - // Internal helper to delete all elements and deallocate the storage. - // If Element has a trivial destructor (for example, if it's a fundamental - // type, like int32), the loop will be removed by the optimizer. void InternalDeallocate(Rep* rep, int size) { if (rep != NULL) { Element* e = &rep->elements[0]; - Element* limit = &rep->elements[size]; - for (; e < limit; e++) { - e->~Element(); + if (!std::is_trivial::value) { + Element* limit = &rep->elements[size]; + for (; e < limit; e++) { + e->~Element(); + } } if (rep->arena == NULL) { #if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) @@ -311,17 +400,97 @@ class RepeatedField PROTOBUF_FINAL { } } - friend class internal::WireFormatLite; - const Element* unsafe_data() const; -}; + // This class is a performance wrapper around RepeatedField::Add(const T&) + // function. In general unless a RepeatedField is a local stack variable LLVM + // has a hard time optimizing Add. The machine code tends to be + // loop: + // mov %size, dword ptr [%repeated_field] // load + // cmp %size, dword ptr [%repeated_field + 4] + // jae fallback + // mov %buffer, qword ptr [%repeated_field + 8] + // mov dword [%buffer + %size * 4], %value + // inc %size // increment + // mov dword ptr [%repeated_field], %size // store + // jmp loop + // + // This puts a load/store in each iteration of the important loop variable + // size. It's a pretty bad compile that happens even in simple cases, but + // largely the presence of the fallback path disturbs the compilers mem-to-reg + // analysis. + // + // This class takes ownership of a repeated field for the duration of it's + // lifetime. The repeated field should not be accessed during this time, ie. + // only access through this class is allowed. This class should always be a + // function local stack variable. Intended use + // + // void AddSequence(const int* begin, const int* end, RepeatedField* out) + // { + // RepeatedFieldAdder adder(out); // Take ownership of out + // for (auto it = begin; it != end; ++it) { + // adder.Add(*it); + // } + // } + // + // Typically due to the fact adder is a local stack variable. The compiler + // will be successful in mem-to-reg transformation and the machine code will + // be loop: cmp %size, %capacity jae fallback mov dword ptr [%buffer + %size * + // 4], %val inc %size jmp loop + // + // The first version executes at 7 cycles per iteration while the second + // version near 1 or 2 cycles. + template ::value> + class FastAdderImpl { + public: + explicit FastAdderImpl(RepeatedField* rf) : repeated_field_(rf) { + index_ = repeated_field_->current_size_; + capacity_ = repeated_field_->total_size_; + buffer_ = repeated_field_->unsafe_elements(); + } + ~FastAdderImpl() { repeated_field_->current_size_ = index_; } + + void Add(Element val) { + if (index_ == capacity_) { + repeated_field_->current_size_ = index_; + repeated_field_->Reserve(index_ + 1); + capacity_ = repeated_field_->total_size_; + buffer_ = repeated_field_->unsafe_elements(); + } + buffer_[index_++] = val; + } -template -const size_t RepeatedField::kRepHeaderSize = - reinterpret_cast(&reinterpret_cast(16)->elements[0]) - 16; + private: + RepeatedField* repeated_field_; + int index_; + int capacity_; + Element* buffer_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastAdderImpl); + }; + + // FastAdder is a wrapper for adding fields. The specialization above handles + // POD types more efficiently than RepeatedField. + template + class FastAdderImpl { + public: + explicit FastAdderImpl(RepeatedField* rf) : repeated_field_(rf) {} + void Add(const Element& val) { repeated_field_->Add(val); } + + private: + RepeatedField* repeated_field_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastAdderImpl); + }; + + using FastAdder = FastAdderImpl<>; + + friend class TestRepeatedFieldHelper; + friend class ::google::protobuf::internal::ParseContext; +}; namespace internal { -template class RepeatedPtrIterator; -template class RepeatedPtrOverPtrsIterator; +template +class RepeatedPtrIterator; +template +class RepeatedPtrOverPtrsIterator; } // namespace internal namespace internal { @@ -331,8 +500,7 @@ namespace internal { // shouldn't be necessary, but our compiler doesn't optimize std::copy very // effectively. template ::value> + bool HasTrivialCopy = std::is_trivial::value> struct ElementCopier { void operator()(Element* to, const Element* from, int array_size); }; @@ -345,7 +513,7 @@ namespace internal { // arena-related "copy if on different arena" behavior if the necessary methods // exist on the contained type. In particular, we rely on MergeFrom() existing // as a general proxy for the fact that a copy will work, and we also provide a -// specific override for string*. +// specific override for std::string*. template struct TypeImplementsMergeBehaviorProbeForMergeFrom { typedef char HasMerge; @@ -358,29 +526,36 @@ struct TypeImplementsMergeBehaviorProbeForMergeFrom { // We mangle these names a bit to avoid compatibility issues in 'unclean' // include environments that may have, e.g., "#define test ..." (yes, this // exists). - template - struct CheckType; - template static HasMerge Check( - CheckType*); - template static HasMerge Check( - CheckType*); - template static HasNoMerge Check(...); - - // Resovles to either google::protobuf::internal::true_type or google::protobuf::internal::false_type. - typedef google::protobuf::internal::integral_constant(0)) == sizeof(HasMerge))> type; + template + struct CheckType; + template + static HasMerge Check(CheckType*); + template + static HasMerge Check(CheckType*); + template + static HasNoMerge Check(...); + + // Resolves to either std::true_type or std::false_type. + typedef std::integral_constant(0)) == sizeof(HasMerge))> + type; }; template -struct TypeImplementsMergeBehavior : - TypeImplementsMergeBehaviorProbeForMergeFrom {}; +struct TypeImplementsMergeBehavior + : TypeImplementsMergeBehaviorProbeForMergeFrom {}; template <> -struct TypeImplementsMergeBehavior< ::std::string> { - typedef google::protobuf::internal::true_type type; +struct TypeImplementsMergeBehavior { + typedef std::true_type type; }; +template +struct IsMovable + : std::integral_constant::value && + std::is_move_assignable::value> {}; + // This is the common base class for RepeatedPtrFields. It deals only in void* // pointers. Users should not use this interface directly. // @@ -390,6 +565,8 @@ struct TypeImplementsMergeBehavior< ::std::string> { // public: // typedef MyType Type; // static Type* New(); +// static Type* NewFromPrototype(const Type* prototype, +// Arena* arena); // static void Delete(Type*); // static void Clear(Type*); // static void Merge(const Type& from, Type* to); @@ -397,64 +574,69 @@ struct TypeImplementsMergeBehavior< ::std::string> { // // Only needs to be implemented if SpaceUsedExcludingSelf() is called. // static int SpaceUsedLong(const Type&); // }; -class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { +class PROTOBUF_EXPORT RepeatedPtrFieldBase { protected: - // The reflection implementation needs to call protected methods directly, - // reinterpreting pointers as being to Message instead of a specific Message - // subclass. - friend class GeneratedMessageReflection; - - // ExtensionSet stores repeated message extensions as - // RepeatedPtrField, but non-lite ExtensionSets need to implement - // SpaceUsedLong(), and thus need to call SpaceUsedExcludingSelfLong() - // reinterpreting MessageLite as Message. ExtensionSet also needs to make use - // of AddFromCleared(), which is not part of the public interface. - friend class ExtensionSet; - - // The MapFieldBase implementation needs to call protected methods directly, - // reinterpreting pointers as being to Message instead of a specific Message - // subclass. - friend class MapFieldBase; - - // The table-driven MergePartialFromCodedStream implementation needs to - // operate on RepeatedPtrField. - friend class MergePartialFromCodedStreamHelper; - - // To parse directly into a proto2 generated class, the upb class GMR_Handlers - // needs to be able to modify a RepeatedPtrFieldBase directly. - friend class upb::google_opensource::GMR_Handlers; - - RepeatedPtrFieldBase(); - explicit RepeatedPtrFieldBase(::google::protobuf::Arena* arena); - ~RepeatedPtrFieldBase() {} + constexpr RepeatedPtrFieldBase(); + explicit RepeatedPtrFieldBase(Arena* arena); + ~RepeatedPtrFieldBase() { +#ifndef NDEBUG + // Try to trigger segfault / asan failure in non-opt builds. If arena_ + // lifetime has ended before the destructor. + if (arena_) (void)arena_->SpaceAllocated(); +#endif + } + public: // Must be called from destructor. template void Destroy(); + protected: bool empty() const; int size() const; template - const typename TypeHandler::Type& Get(int index) const; + const typename TypeHandler::Type& at(int index) const; + template + typename TypeHandler::Type& at(int index); + template typename TypeHandler::Type* Mutable(int index); template void Delete(int index); template typename TypeHandler::Type* Add(typename TypeHandler::Type* prototype = NULL); -#if LANG_CXX11 - template - void Add(typename TypeHandler::Type&& value, - internal::enable_if* dummy = NULL); -#endif + + public: + // The next few methods are public so that they can be called from generated + // code when implicit weak fields are used, but they should never be called by + // application code. template - void RemoveLast(); + const typename TypeHandler::Type& Get(int index) const; + + // Creates and adds an element using the given prototype, without introducing + // a link-time dependency on the concrete message type. This method is used to + // implement implicit weak fields. The prototype may be NULL, in which case an + // ImplicitWeakMessage will be used as a placeholder. + MessageLite* AddWeak(const MessageLite* prototype); + template void Clear(); + template void MergeFrom(const RepeatedPtrFieldBase& other); + + inline void InternalSwap(RepeatedPtrFieldBase* other); + + protected: + template < + typename TypeHandler, + typename std::enable_if::type* = nullptr> + void Add(typename TypeHandler::Type&& value); + + template + void RemoveLast(); template void CopyFrom(const RepeatedPtrFieldBase& other); @@ -474,21 +656,20 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { const typename TypeHandler::Type* const* data() const; template - GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(RepeatedPtrFieldBase* other); + PROTOBUF_NDEBUG_INLINE void Swap(RepeatedPtrFieldBase* other); void SwapElements(int index1, int index2); template size_t SpaceUsedExcludingSelfLong() const; - // Advanced memory management -------------------------------------- // Like Add(), but if there are no cleared objects to use, returns NULL. template typename TypeHandler::Type* AddFromCleared(); - template + template void AddAllocated(typename TypeHandler::Type* value) { typename TypeImplementsMergeBehavior::type t; AddAllocatedInternal(value, t); @@ -514,37 +695,30 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { template typename TypeHandler::Type* ReleaseCleared(); - protected: - inline void InternalSwap(RepeatedPtrFieldBase* other); - template - void AddAllocatedInternal(typename TypeHandler::Type* value, - google::protobuf::internal::true_type); + void AddAllocatedInternal(typename TypeHandler::Type* value, std::true_type); template - void AddAllocatedInternal(typename TypeHandler::Type* value, - google::protobuf::internal::false_type); + void AddAllocatedInternal(typename TypeHandler::Type* value, std::false_type); - template GOOGLE_ATTRIBUTE_NOINLINE - void AddAllocatedSlowWithCopy(typename TypeHandler::Type* value, - Arena* value_arena, - Arena* my_arena); - template GOOGLE_ATTRIBUTE_NOINLINE - void AddAllocatedSlowWithoutCopy(typename TypeHandler::Type* value); + template + PROTOBUF_NOINLINE void AddAllocatedSlowWithCopy( + typename TypeHandler::Type* value, Arena* value_arena, Arena* my_arena); + template + PROTOBUF_NOINLINE void AddAllocatedSlowWithoutCopy( + typename TypeHandler::Type* value); template - typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::true_type); + typename TypeHandler::Type* ReleaseLastInternal(std::true_type); template - typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::false_type); + typename TypeHandler::Type* ReleaseLastInternal(std::false_type); - template GOOGLE_ATTRIBUTE_NOINLINE - void SwapFallback(RepeatedPtrFieldBase* other); + template + PROTOBUF_NOINLINE void SwapFallback(RepeatedPtrFieldBase* other); - inline Arena* GetArenaNoVirtual() const { - return arena_; - } + inline Arena* GetArena() const { return arena_; } private: - static const int kInitialSize = 0; + static constexpr int kInitialSize = 0; // A few notes on internal representation: // // We use an indirected approach, with struct Rep, to keep @@ -557,15 +731,16 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { // Placing all fields directly in the RepeatedPtrFieldBase instance costs // significant performance for memory-sensitive workloads. Arena* arena_; - int current_size_; - int total_size_; + int current_size_; + int total_size_; struct Rep { - int allocated_size; - void* elements[1]; + int allocated_size; + // Here we declare a huge array as a way of approximating C's "flexible + // array member" feature without relying on undefined behavior. + void* elements[(std::numeric_limits::max() - 2 * sizeof(int)) / + sizeof(void*)]; }; - static const size_t kRepHeaderSize = sizeof(Rep) - sizeof(void*); - // Contains arena ptr and the elements array. We also keep the invariant that - // if rep_ is NULL, then arena is NULL. + static constexpr size_t kRepHeaderSize = offsetof(Rep, elements); Rep* rep_; template @@ -579,13 +754,14 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { // Non-templated inner function to avoid code duplication. Takes a function // pointer to the type-specific (templated) inner allocate/merge loop. - void MergeFromInternal( - const RepeatedPtrFieldBase& other, - void (RepeatedPtrFieldBase::*inner_loop)(void**, void**, int, int)); + void MergeFromInternal(const RepeatedPtrFieldBase& other, + void (RepeatedPtrFieldBase::*inner_loop)(void**, + void**, int, + int)); - template - void MergeFromInnerLoop( - void** our_elems, void** other_elems, int length, int already_allocated); + template + void MergeFromInnerLoop(void** our_elems, void** other_elems, int length, + int already_allocated); // Internal helper: extend array space if necessary to contain |extend_amount| // more elements, and return a pointer to the element immediately following @@ -593,7 +769,30 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { // Reserve() and MergeFrom() to reduce code size. |extend_amount| must be > 0. void** InternalExtend(int extend_amount); + // The reflection implementation needs to call protected methods directly, + // reinterpreting pointers as being to Message instead of a specific Message + // subclass. + friend class ::PROTOBUF_NAMESPACE_ID::Reflection; + + // ExtensionSet stores repeated message extensions as + // RepeatedPtrField, but non-lite ExtensionSets need to implement + // SpaceUsedLong(), and thus need to call SpaceUsedExcludingSelfLong() + // reinterpreting MessageLite as Message. ExtensionSet also needs to make use + // of AddFromCleared(), which is not part of the public interface. + friend class ExtensionSet; + + // The MapFieldBase implementation needs to call protected methods directly, + // reinterpreting pointers as being to Message instead of a specific Message + // subclass. + friend class MapFieldBase; + + // The table-driven MergePartialFromCodedStream implementation needs to + // operate on RepeatedPtrField. + friend class MergePartialFromCodedStreamHelper; friend class AccessorHelper; + template + friend struct google::protobuf::WeakRepeatedPtrField; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase); }; @@ -601,41 +800,39 @@ template class GenericTypeHandler { public: typedef GenericType Type; -#if LANG_CXX11 - static const bool Moveable = false; -#endif + using Movable = IsMovable; static inline GenericType* New(Arena* arena) { - return ::google::protobuf::Arena::CreateMaybeMessage(arena); + return Arena::CreateMaybeMessage(arena); } - static inline GenericType* NewFromPrototype( - const GenericType* prototype, ::google::protobuf::Arena* arena = NULL); + static inline GenericType* New(Arena* arena, GenericType&& value) { + return Arena::Create(arena, std::move(value)); + } + static inline GenericType* NewFromPrototype(const GenericType* prototype, + Arena* arena = NULL); static inline void Delete(GenericType* value, Arena* arena) { if (arena == NULL) { delete value; } } - static inline ::google::protobuf::Arena* GetArena(GenericType* value) { - return ::google::protobuf::Arena::GetArena(value); + static inline Arena* GetArena(GenericType* value) { + return Arena::GetArena(value); } static inline void* GetMaybeArenaPointer(GenericType* value) { - return ::google::protobuf::Arena::GetArena(value); + return Arena::GetArena(value); } static inline void Clear(GenericType* value) { value->Clear(); } - GOOGLE_ATTRIBUTE_NOINLINE static void Merge(const GenericType& from, - GenericType* to); + PROTOBUF_NOINLINE + static void Merge(const GenericType& from, GenericType* to); static inline size_t SpaceUsedLong(const GenericType& value) { return value.SpaceUsedLong(); } - static inline const Type& default_instance() { - return Type::default_instance(); - } }; template GenericType* GenericTypeHandler::NewFromPrototype( - const GenericType* /* prototype */, ::google::protobuf::Arena* arena) { + const GenericType* /* prototype */, Arena* arena) { return New(arena); } template @@ -647,15 +844,14 @@ void GenericTypeHandler::Merge(const GenericType& from, // NewFromPrototype() and Merge() are not defined inline here, as we will need // to do a virtual function dispatch anyways to go from Message* to call // New/Merge. -template<> +template <> MessageLite* GenericTypeHandler::NewFromPrototype( - const MessageLite* prototype, google::protobuf::Arena* arena); -template<> -inline google::protobuf::Arena* GenericTypeHandler::GetArena( - MessageLite* value) { + const MessageLite* prototype, Arena* arena); +template <> +inline Arena* GenericTypeHandler::GetArena(MessageLite* value) { return value->GetArena(); } -template<> +template <> inline void* GenericTypeHandler::GetMaybeArenaPointer( MessageLite* value) { return value->GetMaybeArenaPointer(); @@ -663,92 +859,55 @@ inline void* GenericTypeHandler::GetMaybeArenaPointer( template <> void GenericTypeHandler::Merge(const MessageLite& from, MessageLite* to); -template<> -inline void GenericTypeHandler::Clear(string* value) { +template <> +inline void GenericTypeHandler::Clear(std::string* value) { value->clear(); } -template<> -void GenericTypeHandler::Merge(const string& from, - string* to); - -// Declarations of the specialization as we cannot define them here, as the -// header that defines ProtocolMessage depends on types defined in this header. -#define DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(TypeName) \ - template<> \ - TypeName* GenericTypeHandler::NewFromPrototype( \ - const TypeName* prototype, google::protobuf::Arena* arena); \ - template<> \ - google::protobuf::Arena* GenericTypeHandler::GetArena( \ - TypeName* value); \ - template<> \ - void* GenericTypeHandler::GetMaybeArenaPointer( \ - TypeName* value); +template <> +void GenericTypeHandler::Merge(const std::string& from, + std::string* to); // Message specialization bodies defined in message.cc. This split is necessary // to allow proto2-lite (which includes this header) to be independent of // Message. -DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Message) - - -#undef DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES - template <> -inline const MessageLite& GenericTypeHandler::default_instance() { - // Yes, the behavior of the code is undefined, but this function is only - // called when we're already deep into the world of undefined, because the - // caller called Get(index) out of bounds. - MessageLite* null = NULL; - return *null; -} - +PROTOBUF_EXPORT Message* GenericTypeHandler::NewFromPrototype( + const Message* prototype, Arena* arena); template <> -inline const Message& GenericTypeHandler::default_instance() { - // Yes, the behavior of the code is undefined, but this function is only - // called when we're already deep into the world of undefined, because the - // caller called Get(index) out of bounds. - Message* null = NULL; - return *null; -} - +PROTOBUF_EXPORT Arena* GenericTypeHandler::GetArena(Message* value); +template <> +PROTOBUF_EXPORT void* GenericTypeHandler::GetMaybeArenaPointer( + Message* value); class StringTypeHandler { public: - typedef string Type; -#if LANG_CXX11 - static const bool Moveable = - std::is_move_constructible::value && - std::is_move_assignable::value; -#endif + typedef std::string Type; + using Movable = IsMovable; - static inline string* New(Arena* arena) { - return Arena::Create(arena); + static inline std::string* New(Arena* arena) { + return Arena::Create(arena); } -#if LANG_CXX11 - static inline string* New(Arena* arena, string&& value) { - return Arena::Create(arena, std::move(value)); + static inline std::string* New(Arena* arena, std::string&& value) { + return Arena::Create(arena, std::move(value)); } -#endif - static inline string* NewFromPrototype(const string*, - ::google::protobuf::Arena* arena) { + static inline std::string* NewFromPrototype(const std::string*, + Arena* arena) { return New(arena); } - static inline ::google::protobuf::Arena* GetArena(string*) { + static inline Arena* GetArena(std::string*) { return NULL; } + static inline void* GetMaybeArenaPointer(std::string* /* value */) { return NULL; } - static inline void* GetMaybeArenaPointer(string* /* value */) { - return NULL; - } - static inline void Delete(string* value, Arena* arena) { + static inline void Delete(std::string* value, Arena* arena) { if (arena == NULL) { delete value; } } - static inline void Clear(string* value) { value->clear(); } - static inline void Merge(const string& from, string* to) { *to = from; } - static inline const Type& default_instance() { - return ::google::protobuf::internal::GetEmptyString(); + static inline void Clear(std::string* value) { value->clear(); } + static inline void Merge(const std::string& from, std::string* to) { + *to = from; } - static size_t SpaceUsedLong(const string& value) { + static size_t SpaceUsedLong(const std::string& value) { return sizeof(value) + StringSpaceUsedExcludingSelfLong(value); } }; @@ -758,10 +917,10 @@ class StringTypeHandler { // RepeatedPtrField is like RepeatedField, but used for repeated strings or // Messages. template -class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { +class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { public: - RepeatedPtrField(); - explicit RepeatedPtrField(::google::protobuf::Arena* arena); + constexpr RepeatedPtrField(); + explicit RepeatedPtrField(Arena* arena); RepeatedPtrField(const RepeatedPtrField& other); template @@ -770,19 +929,23 @@ class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { RepeatedPtrField& operator=(const RepeatedPtrField& other); + RepeatedPtrField(RepeatedPtrField&& other) noexcept; + RepeatedPtrField& operator=(RepeatedPtrField&& other) noexcept; + bool empty() const; int size() const; const Element& Get(int index) const; Element* Mutable(int index); Element* Add(); -#if LANG_CXX11 void Add(Element&& value); -#endif const Element& operator[](int index) const { return Get(index); } Element& operator[](int index) { return *Mutable(index); } + const Element& at(int index) const; + Element& at(int index); + // Remove the last element in the array. // Ownership of the element is retained by the array. void RemoveLast(); @@ -842,15 +1005,11 @@ class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { // Reverse iterator support typedef std::reverse_iterator const_reverse_iterator; typedef std::reverse_iterator reverse_iterator; - reverse_iterator rbegin() { - return reverse_iterator(end()); - } + reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } - reverse_iterator rend() { - return reverse_iterator(begin()); - } + reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } @@ -908,7 +1067,7 @@ class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { // RepeatedPtrField temp_field; // temp_field.AddAllocated(new T); // ... // Do something with temp_field - // temp_field.ExtractSubrange(0, temp_field.size(), NULL); + // temp_field.ExtractSubrange(0, temp_field.size(), nullptr); // If you put temp_field on the arena this fails, because the ownership // transfers to the arena at the "AddAllocated" call and is not released // anymore causing a double delete. UnsafeArenaAddAllocated prevents this. @@ -986,32 +1145,33 @@ class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { iterator erase(const_iterator first, const_iterator last); // Gets the arena on which this RepeatedPtrField stores its elements. - ::google::protobuf::Arena* GetArena() const { - return GetArenaNoVirtual(); - } + inline Arena* GetArena() const; // For internal use only. // // This is public due to it being called by generated code. - using RepeatedPtrFieldBase::InternalSwap; + void InternalSwap(RepeatedPtrField* other) { + internal::RepeatedPtrFieldBase::InternalSwap(other); + } private: // Note: RepeatedPtrField SHOULD NOT be subclassed by users. class TypeHandler; - // Internal arena accessor expected by helpers in Arena. - inline Arena* GetArenaNoVirtual() const; - // Implementations for ExtractSubrange(). The copying behavior must be // included only if the type supports the necessary operations (e.g., // MergeFrom()), so we must resolve this at compile time. ExtractSubrange() // uses SFINAE to choose one of the below implementations. void ExtractSubrangeInternal(int start, int num, Element** elements, - google::protobuf::internal::true_type); + std::true_type); void ExtractSubrangeInternal(int start, int num, Element** elements, - google::protobuf::internal::false_type); + std::false_type); friend class Arena; + + template + friend struct WeakRepeatedPtrField; + typedef void InternalArenaConstructable_; }; @@ -1019,70 +1179,75 @@ class RepeatedPtrField PROTOBUF_FINAL : public internal::RepeatedPtrFieldBase { // implementation ==================================================== template -inline RepeatedField::RepeatedField() - : current_size_(0), - total_size_(0), - rep_(NULL) { -} +constexpr RepeatedField::RepeatedField() + : current_size_(0), total_size_(0), arena_or_elements_(nullptr) {} template inline RepeatedField::RepeatedField(Arena* arena) - : current_size_(0), - total_size_(0), - rep_(NULL) { - // In case arena is NULL, then we do not create rep_, as code has an invariant - // `rep_ == NULL then arena == NULL`. - if (arena != NULL) { - rep_ = reinterpret_cast( - ::google::protobuf::Arena::CreateArray(arena, kRepHeaderSize)); - rep_->arena = arena; - } -} + : current_size_(0), total_size_(0), arena_or_elements_(arena) {} template inline RepeatedField::RepeatedField(const RepeatedField& other) - : current_size_(0), - total_size_(0), - rep_(NULL) { + : current_size_(0), total_size_(0), arena_or_elements_(nullptr) { if (other.current_size_ != 0) { - Reserve(other.current_size_); - CopyArray(rep_->elements, - other.rep_->elements, other.current_size_); - current_size_ = other.current_size_; + Reserve(other.size()); + AddNAlreadyReserved(other.size()); + CopyArray(Mutable(0), &other.Get(0), other.size()); } } template template RepeatedField::RepeatedField(Iter begin, const Iter& end) - : current_size_(0), - total_size_(0), - rep_(NULL) { - int reserve = internal::CalculateReserve(begin, end); - if (reserve != -1) { - Reserve(reserve); - for (; begin != end; ++begin) { - AddAlreadyReserved(*begin); - } - } else { - for (; begin != end; ++begin) { - Add(*begin); - } - } + : current_size_(0), total_size_(0), arena_or_elements_(nullptr) { + Add(begin, end); } template RepeatedField::~RepeatedField() { - // See explanation in Reserve(): we need to invoke destructors here for the - // case that Element has a non-trivial destructor. - InternalDeallocate(rep_, total_size_); +#ifndef NDEBUG + // Try to trigger segfault / asan failure in non-opt builds. If arena_ + // lifetime has ended before the destructor. + auto arena = GetArena(); + if (arena) (void)arena->SpaceAllocated(); +#endif + if (total_size_ > 0) { + InternalDeallocate(rep(), total_size_); + } } template -inline RepeatedField& -RepeatedField::operator=(const RepeatedField& other) { - if (this != &other) +inline RepeatedField& RepeatedField::operator=( + const RepeatedField& other) { + if (this != &other) CopyFrom(other); + return *this; +} + +template +inline RepeatedField::RepeatedField(RepeatedField&& other) noexcept + : RepeatedField() { + // We don't just call Swap(&other) here because it would perform 3 copies if + // other is on an arena. This field can't be on an arena because arena + // construction always uses the Arena* accepting constructor. + if (other.GetArena()) { CopyFrom(other); + } else { + InternalSwap(&other); + } +} + +template +inline RepeatedField& RepeatedField::operator=( + RepeatedField&& other) noexcept { + // We don't just call Swap(&other) here because it would perform 3 copies if + // the two fields are on different arenas. + if (this != &other) { + if (this->GetArena() != other.GetArena()) { + CopyFrom(other); + } else { + InternalSwap(&other); + } + } return *this; } @@ -1101,33 +1266,37 @@ inline int RepeatedField::Capacity() const { return total_size_; } -template +template inline void RepeatedField::AddAlreadyReserved(const Element& value) { GOOGLE_DCHECK_LT(current_size_, total_size_); - rep_->elements[current_size_++] = value; + elements()[current_size_++] = value; } -template +template inline Element* RepeatedField::AddAlreadyReserved() { GOOGLE_DCHECK_LT(current_size_, total_size_); - return &rep_->elements[current_size_++]; + return &elements()[current_size_++]; } -template -inline Element* RepeatedField::AddNAlreadyReserved(int elements) { - GOOGLE_DCHECK_LE(current_size_ + elements, total_size_); - Element* ret = &rep_->elements[current_size_]; - current_size_ += elements; +template +inline Element* RepeatedField::AddNAlreadyReserved(int n) { + GOOGLE_DCHECK_GE(total_size_ - current_size_, n) + << total_size_ << ", " << current_size_; + // Warning: sometimes people call this when n == 0 and total_size_ == 0. In + // this case the return pointer points to a zero size array (n == 0). Hence + // we can just use unsafe_elements(), because the user cannot dereference the + // pointer anyway. + Element* ret = unsafe_elements() + current_size_; + current_size_ += n; return ret; } -template +template inline void RepeatedField::Resize(int new_size, const Element& value) { GOOGLE_DCHECK_GE(new_size, 0); if (new_size > current_size_) { Reserve(new_size); - std::fill(&rep_->elements[current_size_], - &rep_->elements[new_size], value); + std::fill(&elements()[current_size_], &elements()[new_size], value); } current_size_ = new_size; } @@ -1136,33 +1305,83 @@ template inline const Element& RepeatedField::Get(int index) const { GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, current_size_); - return rep_->elements[index]; + return elements()[index]; +} + +template +inline const Element& RepeatedField::at(int index) const { + GOOGLE_CHECK_GE(index, 0); + GOOGLE_CHECK_LT(index, current_size_); + return elements()[index]; +} + +template +inline Element& RepeatedField::at(int index) { + GOOGLE_CHECK_GE(index, 0); + GOOGLE_CHECK_LT(index, current_size_); + return elements()[index]; } template inline Element* RepeatedField::Mutable(int index) { GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, current_size_); - return &rep_->elements[index]; + return &elements()[index]; } template inline void RepeatedField::Set(int index, const Element& value) { GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, current_size_); - rep_->elements[index] = value; + elements()[index] = value; } template inline void RepeatedField::Add(const Element& value) { - if (current_size_ == total_size_) Reserve(total_size_ + 1); - rep_->elements[current_size_++] = value; + uint32 size = current_size_; + if (static_cast(size) == total_size_) { + // value could reference an element of the array. Reserving new space will + // invalidate the reference. So we must make a copy first. + auto tmp = value; + Reserve(total_size_ + 1); + elements()[size] = std::move(tmp); + } else { + elements()[size] = value; + } + current_size_ = size + 1; } template inline Element* RepeatedField::Add() { - if (current_size_ == total_size_) Reserve(total_size_ + 1); - return &rep_->elements[current_size_++]; + uint32 size = current_size_; + if (static_cast(size) == total_size_) Reserve(total_size_ + 1); + auto ptr = &elements()[size]; + current_size_ = size + 1; + return ptr; +} + +template +template +inline void RepeatedField::Add(Iter begin, Iter end) { + int reserve = internal::CalculateReserve(begin, end); + if (reserve != -1) { + if (reserve == 0) { + return; + } + + Reserve(reserve + size()); + // TODO(ckennelly): The compiler loses track of the buffer freshly + // allocated by Reserve() by the time we call elements, so it cannot + // guarantee that elements does not alias [begin(), end()). + // + // If restrict is available, annotating the pointer obtained from elements() + // causes this to lower to memcpy instead of memmove. + std::copy(begin, end, elements() + size()); + current_size_ = reserve + size(); + } else { + FastAdder fast_adder(this); + for (; begin != end; ++begin) fast_adder.Add(*begin); + } } template @@ -1172,16 +1391,15 @@ inline void RepeatedField::RemoveLast() { } template -void RepeatedField::ExtractSubrange( - int start, int num, Element* elements) { +void RepeatedField::ExtractSubrange(int start, int num, + Element* elements) { GOOGLE_DCHECK_GE(start, 0); GOOGLE_DCHECK_GE(num, 0); GOOGLE_DCHECK_LE(start + num, this->current_size_); // Save the values of the removed elements if requested. if (elements != NULL) { - for (int i = 0; i < num; ++i) - elements[i] = this->Get(i + start); + for (int i = 0; i < num; ++i) elements[i] = this->Get(i + start); } // Slide remaining elements down to fill the gap. @@ -1201,10 +1419,10 @@ template inline void RepeatedField::MergeFrom(const RepeatedField& other) { GOOGLE_DCHECK_NE(&other, this); if (other.current_size_ != 0) { - Reserve(current_size_ + other.current_size_); - CopyArray(rep_->elements + current_size_, - other.rep_->elements, other.current_size_); - current_size_ += other.current_size_; + int existing_size = size(); + Reserve(existing_size + other.size()); + AddNAlreadyReserved(other.size()); + CopyArray(Mutable(existing_size), &other.Get(0), other.size()); } } @@ -1233,37 +1451,36 @@ inline typename RepeatedField::iterator RepeatedField::erase( template inline Element* RepeatedField::mutable_data() { - return rep_ ? rep_->elements : NULL; + return unsafe_elements(); } template inline const Element* RepeatedField::data() const { - return rep_ ? rep_->elements : NULL; -} - -template -inline const Element* RepeatedField::unsafe_data() const { - GOOGLE_DCHECK(rep_); - return rep_->elements; + return unsafe_elements(); } template inline void RepeatedField::InternalSwap(RepeatedField* other) { GOOGLE_DCHECK(this != other); - GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); + GOOGLE_DCHECK(GetArena() == other->GetArena()); - std::swap(rep_, other->rep_); - std::swap(current_size_, other->current_size_); - std::swap(total_size_, other->total_size_); + // Swap all fields at once. + static_assert(std::is_standard_layout>::value, + "offsetof() requires standard layout before c++17"); + internal::memswaparena_or_elements_) - + offsetof(RepeatedField, current_size_)>( + reinterpret_cast(this) + offsetof(RepeatedField, current_size_), + reinterpret_cast(other) + offsetof(RepeatedField, current_size_)); } template void RepeatedField::Swap(RepeatedField* other) { if (this == other) return; - if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { + if (GetArena() == other->GetArena()) { InternalSwap(other); } else { - RepeatedField temp(other->GetArenaNoVirtual()); + RepeatedField temp(other->GetArena()); temp.MergeFrom(*this); CopyFrom(*other); other->UnsafeArenaSwap(&temp); @@ -1279,68 +1496,96 @@ void RepeatedField::UnsafeArenaSwap(RepeatedField* other) { template void RepeatedField::SwapElements(int index1, int index2) { using std::swap; // enable ADL with fallback - swap(rep_->elements[index1], rep_->elements[index2]); + swap(elements()[index1], elements()[index2]); } template inline typename RepeatedField::iterator RepeatedField::begin() { - return rep_ ? rep_->elements : NULL; + return unsafe_elements(); } template inline typename RepeatedField::const_iterator RepeatedField::begin() const { - return rep_ ? rep_->elements : NULL; + return unsafe_elements(); } template inline typename RepeatedField::const_iterator RepeatedField::cbegin() const { - return rep_ ? rep_->elements : NULL; + return unsafe_elements(); } template -inline typename RepeatedField::iterator -RepeatedField::end() { - return rep_ ? rep_->elements + current_size_ : NULL; +inline typename RepeatedField::iterator RepeatedField::end() { + return unsafe_elements() + current_size_; } template inline typename RepeatedField::const_iterator RepeatedField::end() const { - return rep_ ? rep_->elements + current_size_ : NULL; + return unsafe_elements() + current_size_; } template inline typename RepeatedField::const_iterator RepeatedField::cend() const { - return rep_ ? rep_->elements + current_size_ : NULL; + return unsafe_elements() + current_size_; } template inline size_t RepeatedField::SpaceUsedExcludingSelfLong() const { - return rep_ ? (total_size_ * sizeof(Element) + kRepHeaderSize) : 0; + return total_size_ > 0 ? (total_size_ * sizeof(Element) + kRepHeaderSize) : 0; +} + +namespace internal { +// Returns the new size for a reserved field based on its 'total_size' and the +// requested 'new_size'. The result is clamped to the closed interval: +// [internal::kMinRepeatedFieldAllocationSize, +// std::numeric_limits::max()] +// Requires: +// new_size > total_size && +// (total_size == 0 || +// total_size >= kRepeatedFieldLowerClampLimit) +inline int CalculateReserveSize(int total_size, int new_size) { + if (new_size < kRepeatedFieldLowerClampLimit) { + // Clamp to smallest allowed size. + return kRepeatedFieldLowerClampLimit; + } + if (total_size < kRepeatedFieldUpperClampLimit) { + return std::max(total_size * 2, new_size); + } else { + // Clamp to largest allowed size. + GOOGLE_DCHECK_GT(new_size, kRepeatedFieldUpperClampLimit); + return std::numeric_limits::max(); + } } +} // namespace internal // Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant // amount of code bloat. template void RepeatedField::Reserve(int new_size) { if (total_size_ >= new_size) return; - Rep* old_rep = rep_; - Arena* arena = GetArenaNoVirtual(); - new_size = std::max(google::protobuf::internal::kMinRepeatedFieldAllocationSize, - std::max(total_size_ * 2, new_size)); + Rep* old_rep = total_size_ > 0 ? rep() : NULL; + Rep* new_rep; + Arena* arena = GetArena(); + new_size = internal::CalculateReserveSize(total_size_, new_size); GOOGLE_DCHECK_LE( static_cast(new_size), (std::numeric_limits::max() - kRepHeaderSize) / sizeof(Element)) << "Requested size is too large to fit into size_t."; - size_t bytes = kRepHeaderSize + sizeof(Element) * static_cast(new_size); + size_t bytes = + kRepHeaderSize + sizeof(Element) * static_cast(new_size); if (arena == NULL) { - rep_ = static_cast(::operator new(bytes)); + new_rep = static_cast(::operator new(bytes)); } else { - rep_ = reinterpret_cast( - ::google::protobuf::Arena::CreateArray(arena, bytes)); + new_rep = reinterpret_cast(Arena::CreateArray(arena, bytes)); } - rep_->arena = arena; + new_rep->arena = arena; int old_total_size = total_size_; + // Already known: new_size >= internal::kMinRepeatedFieldAllocationSize + // Maintain invariant: + // total_size_ == 0 || + // total_size_ >= internal::kMinRepeatedFieldAllocationSize total_size_ = new_size; + arena_or_elements_ = new_rep->elements; // Invoke placement-new on newly allocated elements. We shouldn't have to do // this, since Element is supposed to be POD, but a previous version of this // code allocated storage with "new Element[size]" and some code uses @@ -1350,13 +1595,13 @@ void RepeatedField::Reserve(int new_size) { // effect unless its side-effects are required for correctness. // Note that we do this before MoveArray() below because Element's copy // assignment implementation will want an initialized instance first. - Element* e = &rep_->elements[0]; - Element* limit = &rep_->elements[total_size_]; + Element* e = &elements()[0]; + Element* limit = e + total_size_; for (; e < limit; e++) { new (e) Element; } if (current_size_ > 0) { - MoveArray(rep_->elements, old_rep->elements, current_size_); + MoveArray(&elements()[0], old_rep->elements, current_size_); } // Likewise, we need to invoke destructors on the old array. @@ -1373,22 +1618,23 @@ inline void RepeatedField::Truncate(int new_size) { } template -inline void RepeatedField::MoveArray( - Element* to, Element* from, int array_size) { +inline void RepeatedField::MoveArray(Element* to, Element* from, + int array_size) { CopyArray(to, from, array_size); } template -inline void RepeatedField::CopyArray( - Element* to, const Element* from, int array_size) { +inline void RepeatedField::CopyArray(Element* to, const Element* from, + int array_size) { internal::ElementCopier()(to, from, array_size); } namespace internal { template -void ElementCopier::operator()( - Element* to, const Element* from, int array_size) { +void ElementCopier::operator()(Element* to, + const Element* from, + int array_size) { std::copy(from, from + array_size, to); } @@ -1406,19 +1652,11 @@ struct ElementCopier { namespace internal { -inline RepeatedPtrFieldBase::RepeatedPtrFieldBase() - : arena_(NULL), - current_size_(0), - total_size_(0), - rep_(NULL) { -} +constexpr RepeatedPtrFieldBase::RepeatedPtrFieldBase() + : arena_(NULL), current_size_(0), total_size_(0), rep_(NULL) {} -inline RepeatedPtrFieldBase::RepeatedPtrFieldBase(::google::protobuf::Arena* arena) - : arena_(arena), - current_size_(0), - total_size_(0), - rep_(NULL) { -} +inline RepeatedPtrFieldBase::RepeatedPtrFieldBase(Arena* arena) + : arena_(arena), current_size_(0), total_size_(0), rep_(NULL) {} template void RepeatedPtrFieldBase::Destroy() { @@ -1440,7 +1678,7 @@ void RepeatedPtrFieldBase::Destroy() { template inline void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) { - if (other->GetArenaNoVirtual() == GetArenaNoVirtual()) { + if (other->GetArena() == GetArena()) { InternalSwap(other); } else { SwapFallback(other); @@ -1449,40 +1687,48 @@ inline void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) { template void RepeatedPtrFieldBase::SwapFallback(RepeatedPtrFieldBase* other) { - GOOGLE_DCHECK(other->GetArenaNoVirtual() != GetArenaNoVirtual()); + GOOGLE_DCHECK(other->GetArena() != GetArena()); // Copy semantics in this case. We try to improve efficiency by placing the - // temporary on |other|'s arena so that messages are copied cross-arena only - // once, not twice. - RepeatedPtrFieldBase temp(other->GetArenaNoVirtual()); + // temporary on |other|'s arena so that messages are copied twice rather than + // three times. + RepeatedPtrFieldBase temp(other->GetArena()); temp.MergeFrom(*this); this->Clear(); this->MergeFrom(*other); - other->Clear(); other->InternalSwap(&temp); temp.Destroy(); // Frees rep_ if `other` had no arena. } -inline bool RepeatedPtrFieldBase::empty() const { - return current_size_ == 0; -} +inline bool RepeatedPtrFieldBase::empty() const { return current_size_ == 0; } -inline int RepeatedPtrFieldBase::size() const { - return current_size_; -} +inline int RepeatedPtrFieldBase::size() const { return current_size_; } template -inline const typename TypeHandler::Type& -RepeatedPtrFieldBase::Get(int index) const { +inline const typename TypeHandler::Type& RepeatedPtrFieldBase::Get( + int index) const { GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, current_size_); return *cast(rep_->elements[index]); } +template +inline const typename TypeHandler::Type& RepeatedPtrFieldBase::at( + int index) const { + GOOGLE_CHECK_GE(index, 0); + GOOGLE_CHECK_LT(index, current_size_); + return *cast(rep_->elements[index]); +} template -inline typename TypeHandler::Type* -RepeatedPtrFieldBase::Mutable(int index) { +inline typename TypeHandler::Type& RepeatedPtrFieldBase::at(int index) { + GOOGLE_CHECK_GE(index, 0); + GOOGLE_CHECK_LT(index, current_size_); + return *cast(rep_->elements[index]); +} + +template +inline typename TypeHandler::Type* RepeatedPtrFieldBase::Mutable(int index) { GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, current_size_); return cast(rep_->elements[index]); @@ -1511,11 +1757,9 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add( return result; } -#if LANG_CXX11 -template -inline void RepeatedPtrFieldBase::Add( - typename TypeHandler::Type&& value, - internal::enable_if*) { +template ::type*> +inline void RepeatedPtrFieldBase::Add(typename TypeHandler::Type&& value) { if (rep_ != NULL && current_size_ < rep_->allocated_size) { *cast(rep_->elements[current_size_++]) = std::move(value); return; @@ -1528,7 +1772,6 @@ inline void RepeatedPtrFieldBase::Add( TypeHandler::New(arena_, std::move(value)); rep_->elements[current_size_++] = result; } -#endif template inline void RepeatedPtrFieldBase::RemoveLast() { @@ -1560,8 +1803,8 @@ template inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) { GOOGLE_DCHECK_NE(&other, this); if (other.current_size_ == 0) return; - MergeFromInternal( - other, &RepeatedPtrFieldBase::MergeFromInnerLoop); + MergeFromInternal(other, + &RepeatedPtrFieldBase::MergeFromInnerLoop); } inline void RepeatedPtrFieldBase::MergeFromInternal( @@ -1572,8 +1815,8 @@ inline void RepeatedPtrFieldBase::MergeFromInternal( void** other_elements = other.rep_->elements; void** new_elements = InternalExtend(other_size); int allocated_elems = rep_->allocated_size - current_size_; - (this->*inner_loop)(new_elements, other_elements, - other_size, allocated_elems); + (this->*inner_loop)(new_elements, other_elements, other_size, + allocated_elems); current_size_ += other_size; if (rep_->allocated_size < current_size_) { rep_->allocated_size = current_size_; @@ -1581,9 +1824,10 @@ inline void RepeatedPtrFieldBase::MergeFromInternal( } // Merges other_elems to our_elems. -template -void RepeatedPtrFieldBase::MergeFromInnerLoop( - void** our_elems, void** other_elems, int length, int already_allocated) { +template +void RepeatedPtrFieldBase::MergeFromInnerLoop(void** our_elems, + void** other_elems, int length, + int already_allocated) { // Split into two loops, over ranges [0, allocated) and [allocated, length), // to avoid a branch within the loop. for (int i = 0; i < already_allocated && i < length; i++) { @@ -1594,7 +1838,7 @@ void RepeatedPtrFieldBase::MergeFromInnerLoop( reinterpret_cast(our_elems[i]); TypeHandler::Merge(*other_elem, new_elem); } - Arena* arena = GetArenaNoVirtual(); + Arena* arena = GetArena(); for (int i = already_allocated; i < length; i++) { // Not allocated: alloc a new element first, then merge it. typename TypeHandler::Type* other_elem = @@ -1613,9 +1857,7 @@ inline void RepeatedPtrFieldBase::CopyFrom(const RepeatedPtrFieldBase& other) { RepeatedPtrFieldBase::MergeFrom(other); } -inline int RepeatedPtrFieldBase::Capacity() const { - return total_size_; -} +inline int RepeatedPtrFieldBase::Capacity() const { return total_size_; } inline void* const* RepeatedPtrFieldBase::raw_data() const { return rep_ ? rep_->elements : NULL; @@ -1633,8 +1875,8 @@ inline typename TypeHandler::Type** RepeatedPtrFieldBase::mutable_data() { } template -inline const typename TypeHandler::Type* const* -RepeatedPtrFieldBase::data() const { +inline const typename TypeHandler::Type* const* RepeatedPtrFieldBase::data() + const { // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this // method entirely. return reinterpret_cast(raw_data()); @@ -1650,8 +1892,8 @@ inline size_t RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong() const { size_t allocated_bytes = static_cast(total_size_) * sizeof(void*); if (rep_ != NULL) { for (int i = 0; i < rep_->allocated_size; ++i) { - allocated_bytes += TypeHandler::SpaceUsedLong( - *cast(rep_->elements[i])); + allocated_bytes += + TypeHandler::SpaceUsedLong(*cast(rep_->elements[i])); } allocated_bytes += kRepHeaderSize; } @@ -1670,13 +1912,11 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::AddFromCleared() { // AddAllocated version that implements arena-safe copying behavior. template void RepeatedPtrFieldBase::AddAllocatedInternal( - typename TypeHandler::Type* value, - google::protobuf::internal::true_type) { - Arena* element_arena = reinterpret_cast( - TypeHandler::GetMaybeArenaPointer(value)); - Arena* arena = GetArenaNoVirtual(); - if (arena == element_arena && rep_ && - rep_->allocated_size < total_size_) { + typename TypeHandler::Type* value, std::true_type) { + Arena* element_arena = + reinterpret_cast(TypeHandler::GetMaybeArenaPointer(value)); + Arena* arena = GetArena(); + if (arena == element_arena && rep_ && rep_->allocated_size < total_size_) { // Fast path: underlying arena representation (tagged pointer) is equal to // our arena pointer, and we can add to array without resizing it (at least // one slot that is not allocated). @@ -1689,15 +1929,14 @@ void RepeatedPtrFieldBase::AddAllocatedInternal( elems[current_size_] = value; current_size_ = current_size_ + 1; rep_->allocated_size = rep_->allocated_size + 1; - return; } else { - AddAllocatedSlowWithCopy( - value, TypeHandler::GetArena(value), arena); + AddAllocatedSlowWithCopy(value, TypeHandler::GetArena(value), + arena); } } // Slowpath handles all cases, copying if necessary. -template +template void RepeatedPtrFieldBase::AddAllocatedSlowWithCopy( // Pass value_arena and my_arena to avoid duplicate virtual call (value) or // load (mine). @@ -1721,9 +1960,8 @@ void RepeatedPtrFieldBase::AddAllocatedSlowWithCopy( // AddAllocated version that does not implement arena-safe copying behavior. template void RepeatedPtrFieldBase::AddAllocatedInternal( - typename TypeHandler::Type* value, - google::protobuf::internal::false_type) { - if (rep_ && rep_->allocated_size < total_size_) { + typename TypeHandler::Type* value, std::false_type) { + if (rep_ && rep_->allocated_size < total_size_) { // Fast path: underlying arena representation (tagged pointer) is equal to // our arena pointer, and we can add to array without resizing it (at least // one slot that is not allocated). @@ -1736,7 +1974,6 @@ void RepeatedPtrFieldBase::AddAllocatedInternal( elems[current_size_] = value; current_size_ = current_size_ + 1; ++rep_->allocated_size; - return; } else { UnsafeArenaAddAllocated(value); } @@ -1755,8 +1992,8 @@ void RepeatedPtrFieldBase::UnsafeArenaAddAllocated( // cleared objects awaiting reuse. We don't want to grow the array in this // case because otherwise a loop calling AddAllocated() followed by Clear() // would leak memory. - TypeHandler::Delete( - cast(rep_->elements[current_size_]), arena_); + TypeHandler::Delete(cast(rep_->elements[current_size_]), + arena_); } else if (current_size_ < rep_->allocated_size) { // We have some cleared objects. We don't care about their order, so we // can just move the first one to the end to make space. @@ -1772,12 +2009,12 @@ void RepeatedPtrFieldBase::UnsafeArenaAddAllocated( // ReleaseLast() for types that implement merge/copy behavior. template -inline typename TypeHandler::Type* -RepeatedPtrFieldBase::ReleaseLastInternal(google::protobuf::internal::true_type) { +inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseLastInternal( + std::true_type) { // First, release an element. typename TypeHandler::Type* result = UnsafeArenaReleaseLast(); // Now perform a copy if we're on an arena. - Arena* arena = GetArenaNoVirtual(); + Arena* arena = GetArena(); if (arena == NULL) { return result; } else { @@ -1793,9 +2030,9 @@ RepeatedPtrFieldBase::ReleaseLastInternal(google::protobuf::internal::true_type) // an arena, since the user really should implement the copy operation in this // case. template -inline typename TypeHandler::Type* -RepeatedPtrFieldBase::ReleaseLastInternal(google::protobuf::internal::false_type) { - GOOGLE_DCHECK(GetArenaNoVirtual() == NULL) +inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseLastInternal( + std::false_type) { + GOOGLE_DCHECK(GetArena() == NULL) << "ReleaseLast() called on a RepeatedPtrField that is on an arena, " << "with a type that does not implement MergeFrom. This is unsafe; " << "please implement MergeFrom for your type."; @@ -1804,7 +2041,7 @@ RepeatedPtrFieldBase::ReleaseLastInternal(google::protobuf::internal::false_type template inline typename TypeHandler::Type* - RepeatedPtrFieldBase::UnsafeArenaReleaseLast() { +RepeatedPtrFieldBase::UnsafeArenaReleaseLast() { GOOGLE_DCHECK_GT(current_size_, 0); typename TypeHandler::Type* result = cast(rep_->elements[--current_size_]); @@ -1824,7 +2061,7 @@ inline int RepeatedPtrFieldBase::ClearedCount() const { template inline void RepeatedPtrFieldBase::AddCleared( typename TypeHandler::Type* value) { - GOOGLE_DCHECK(GetArenaNoVirtual() == NULL) + GOOGLE_DCHECK(GetArena() == NULL) << "AddCleared() can only be used on a RepeatedPtrField not on an arena."; GOOGLE_DCHECK(TypeHandler::GetArena(value) == NULL) << "AddCleared() can only accept values not on an arena."; @@ -1836,10 +2073,10 @@ inline void RepeatedPtrFieldBase::AddCleared( template inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseCleared() { - GOOGLE_DCHECK(GetArenaNoVirtual() == NULL) + GOOGLE_DCHECK(GetArena() == NULL) << "ReleaseCleared() can only be used on a RepeatedPtrField not on " << "an arena."; - GOOGLE_DCHECK(GetArenaNoVirtual() == NULL); + GOOGLE_DCHECK(GetArena() == NULL); GOOGLE_DCHECK(rep_ != NULL); GOOGLE_DCHECK_GT(rep_->allocated_size, current_size_); return cast(rep_->elements[--rep_->allocated_size]); @@ -1851,33 +2088,31 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseCleared() { template class RepeatedPtrField::TypeHandler - : public internal::GenericTypeHandler { -}; + : public internal::GenericTypeHandler {}; template <> -class RepeatedPtrField::TypeHandler - : public internal::StringTypeHandler { -}; +class RepeatedPtrField::TypeHandler + : public internal::StringTypeHandler {}; template -inline RepeatedPtrField::RepeatedPtrField() - : RepeatedPtrFieldBase() {} +constexpr RepeatedPtrField::RepeatedPtrField() + : RepeatedPtrFieldBase() {} template -inline RepeatedPtrField::RepeatedPtrField(::google::protobuf::Arena* arena) : - RepeatedPtrFieldBase(arena) {} +inline RepeatedPtrField::RepeatedPtrField(Arena* arena) + : RepeatedPtrFieldBase(arena) {} template inline RepeatedPtrField::RepeatedPtrField( const RepeatedPtrField& other) - : RepeatedPtrFieldBase() { + : RepeatedPtrFieldBase() { MergeFrom(other); } template template -inline RepeatedPtrField::RepeatedPtrField( - Iter begin, const Iter& end) { +inline RepeatedPtrField::RepeatedPtrField(Iter begin, + const Iter& end) { int reserve = internal::CalculateReserve(begin, end); if (reserve != -1) { Reserve(reserve); @@ -1895,8 +2130,36 @@ RepeatedPtrField::~RepeatedPtrField() { template inline RepeatedPtrField& RepeatedPtrField::operator=( const RepeatedPtrField& other) { - if (this != &other) + if (this != &other) CopyFrom(other); + return *this; +} + +template +inline RepeatedPtrField::RepeatedPtrField( + RepeatedPtrField&& other) noexcept + : RepeatedPtrField() { + // We don't just call Swap(&other) here because it would perform 3 copies if + // other is on an arena. This field can't be on an arena because arena + // construction always uses the Arena* accepting constructor. + if (other.GetArena()) { CopyFrom(other); + } else { + InternalSwap(&other); + } +} + +template +inline RepeatedPtrField& RepeatedPtrField::operator=( + RepeatedPtrField&& other) noexcept { + // We don't just call Swap(&other) here because it would perform 3 copies if + // the two fields are on different arenas. + if (this != &other) { + if (this->GetArena() != other.GetArena()) { + CopyFrom(other); + } else { + InternalSwap(&other); + } + } return *this; } @@ -1915,6 +2178,16 @@ inline const Element& RepeatedPtrField::Get(int index) const { return RepeatedPtrFieldBase::Get(index); } +template +inline const Element& RepeatedPtrField::at(int index) const { + return RepeatedPtrFieldBase::at(index); +} + +template +inline Element& RepeatedPtrField::at(int index) { + return RepeatedPtrFieldBase::at(index); +} + template inline Element* RepeatedPtrField::Mutable(int index) { @@ -1926,12 +2199,10 @@ inline Element* RepeatedPtrField::Add() { return RepeatedPtrFieldBase::Add(); } -#if LANG_CXX11 template inline void RepeatedPtrField::Add(Element&& value) { RepeatedPtrFieldBase::Add(std::move(value)); } -#endif template inline void RepeatedPtrField::RemoveLast() { @@ -1950,8 +2221,8 @@ inline void RepeatedPtrField::DeleteSubrange(int start, int num) { } template -inline void RepeatedPtrField::ExtractSubrange( - int start, int num, Element** elements) { +inline void RepeatedPtrField::ExtractSubrange(int start, int num, + Element** elements) { typename internal::TypeImplementsMergeBehavior< typename TypeHandler::Type>::type t; ExtractSubrangeInternal(start, num, elements, t); @@ -1961,7 +2232,7 @@ inline void RepeatedPtrField::ExtractSubrange( // behavior. template inline void RepeatedPtrField::ExtractSubrangeInternal( - int start, int num, Element** elements, google::protobuf::internal::true_type) { + int start, int num, Element** elements, std::true_type) { GOOGLE_DCHECK_GE(start, 0); GOOGLE_DCHECK_GE(num, 0); GOOGLE_DCHECK_LE(start + num, size()); @@ -1969,12 +2240,12 @@ inline void RepeatedPtrField::ExtractSubrangeInternal( if (num > 0) { // Save the values of the removed elements if requested. if (elements != NULL) { - if (GetArenaNoVirtual() != NULL) { + if (GetArena() != NULL) { // If we're on an arena, we perform a copy for each element so that the // returned elements are heap-allocated. for (int i = 0; i < num; ++i) { - Element* element = RepeatedPtrFieldBase:: - Mutable(i + start); + Element* element = + RepeatedPtrFieldBase::Mutable(i + start); typename TypeHandler::Type* new_value = TypeHandler::NewFromPrototype(element, NULL); TypeHandler::Merge(*element, new_value); @@ -1992,14 +2263,14 @@ inline void RepeatedPtrField::ExtractSubrangeInternal( // ExtractSubrange() implementation for types that do not implement merge/copy // behavior. -template +template inline void RepeatedPtrField::ExtractSubrangeInternal( - int start, int num, Element** elements, google::protobuf::internal::false_type) { + int start, int num, Element** elements, std::false_type) { // This case is identical to UnsafeArenaExtractSubrange(). However, since // ExtractSubrange() must return heap-allocated objects by contract, and we // cannot fulfill this contract if we are an on arena, we must GOOGLE_DCHECK() that // we are not on an arena. - GOOGLE_DCHECK(GetArenaNoVirtual() == NULL) + GOOGLE_DCHECK(GetArena() == NULL) << "ExtractSubrange() when arena is non-NULL is only supported when " << "the Element type supplies a MergeFrom() operation to make copies."; UnsafeArenaExtractSubrange(start, num, elements); @@ -2035,8 +2306,7 @@ inline void RepeatedPtrField::MergeFrom( } template -inline void RepeatedPtrField::CopyFrom( - const RepeatedPtrField& other) { +inline void RepeatedPtrField::CopyFrom(const RepeatedPtrField& other) { RepeatedPtrFieldBase::CopyFrom(other); } @@ -2067,16 +2337,14 @@ inline const Element* const* RepeatedPtrField::data() const { template inline void RepeatedPtrField::Swap(RepeatedPtrField* other) { - if (this == other) - return; + if (this == other) return; RepeatedPtrFieldBase::Swap(other); } template inline void RepeatedPtrField::UnsafeArenaSwap( RepeatedPtrField* other) { - if (this == other) - return; + if (this == other) return; RepeatedPtrFieldBase::InternalSwap(other); } @@ -2086,8 +2354,8 @@ inline void RepeatedPtrField::SwapElements(int index1, int index2) { } template -inline Arena* RepeatedPtrField::GetArenaNoVirtual() const { - return RepeatedPtrFieldBase::GetArenaNoVirtual(); +inline Arena* RepeatedPtrField::GetArena() const { + return RepeatedPtrFieldBase::GetArena(); } template @@ -2155,48 +2423,45 @@ namespace internal { // // This code based on net/proto/proto-array-internal.h by Jeffrey Yasskin // (jyasskin@google.com). -template -class RepeatedPtrIterator - : public std::iterator< - std::random_access_iterator_tag, Element> { +template +class RepeatedPtrIterator { public: - typedef RepeatedPtrIterator iterator; - typedef std::iterator< - std::random_access_iterator_tag, Element> superclass; - - // Shadow the value_type in std::iterator<> because const_iterator::value_type - // needs to be T, not const T. - typedef typename remove_const::type value_type; - - // Let the compiler know that these are type names, so we don't have to - // write "typename" in front of them everywhere. - typedef typename superclass::reference reference; - typedef typename superclass::pointer pointer; - typedef typename superclass::difference_type difference_type; + using iterator = RepeatedPtrIterator; + using iterator_category = std::random_access_iterator_tag; + using value_type = typename std::remove_const::type; + using difference_type = std::ptrdiff_t; + using pointer = Element*; + using reference = Element&; RepeatedPtrIterator() : it_(NULL) {} explicit RepeatedPtrIterator(void* const* it) : it_(it) {} // Allow "upcasting" from RepeatedPtrIterator to // RepeatedPtrIterator. - template + template RepeatedPtrIterator(const RepeatedPtrIterator& other) : it_(other.it_) { // Force a compiler error if the other type is not convertible to ours. if (false) { - implicit_cast(0); + implicit_cast(static_cast(nullptr)); } } // dereferenceable reference operator*() const { return *reinterpret_cast(*it_); } - pointer operator->() const { return &(operator*()); } + pointer operator->() const { return &(operator*()); } // {inc,dec}rementable - iterator& operator++() { ++it_; return *this; } - iterator operator++(int) { return iterator(it_++); } - iterator& operator--() { --it_; return *this; } - iterator operator--(int) { return iterator(it_--); } + iterator& operator++() { + ++it_; + return *this; + } + iterator operator++(int) { return iterator(it_++); } + iterator& operator--() { + --it_; + return *this; + } + iterator operator--(int) { return iterator(it_--); } // equality_comparable bool operator==(const iterator& x) const { return it_ == x.it_; } @@ -2237,7 +2502,7 @@ class RepeatedPtrIterator difference_type operator-(const iterator& x) const { return it_ - x.it_; } private: - template + template friend class RepeatedPtrIterator; // The internal iterator. @@ -2252,34 +2517,33 @@ class RepeatedPtrIterator // referenced by the iterator. It should either be "void *" for a mutable // iterator, or "const void* const" for a constant iterator. template -class RepeatedPtrOverPtrsIterator - : public std::iterator { +class RepeatedPtrOverPtrsIterator { public: - typedef RepeatedPtrOverPtrsIterator iterator; - typedef std::iterator superclass; - - // Shadow the value_type in std::iterator<> because const_iterator::value_type - // needs to be T, not const T. - typedef typename remove_const::type value_type; - - // Let the compiler know that these are type names, so we don't have to - // write "typename" in front of them everywhere. - typedef typename superclass::reference reference; - typedef typename superclass::pointer pointer; - typedef typename superclass::difference_type difference_type; + using iterator = RepeatedPtrOverPtrsIterator; + using iterator_category = std::random_access_iterator_tag; + using value_type = typename std::remove_const::type; + using difference_type = std::ptrdiff_t; + using pointer = Element*; + using reference = Element&; RepeatedPtrOverPtrsIterator() : it_(NULL) {} explicit RepeatedPtrOverPtrsIterator(VoidPtr* it) : it_(it) {} // dereferenceable reference operator*() const { return *reinterpret_cast(it_); } - pointer operator->() const { return &(operator*()); } + pointer operator->() const { return &(operator*()); } // {inc,dec}rementable - iterator& operator++() { ++it_; return *this; } - iterator operator++(int) { return iterator(it_++); } - iterator& operator--() { --it_; return *this; } - iterator operator--(int) { return iterator(it_--); } + iterator& operator++() { + ++it_; + return *this; + } + iterator operator++(int) { return iterator(it_++); } + iterator& operator--() { + --it_; + return *this; + } + iterator operator--(int) { return iterator(it_--); } // equality_comparable bool operator==(const iterator& x) const { return it_ == x.it_; } @@ -2320,7 +2584,7 @@ class RepeatedPtrOverPtrsIterator difference_type operator-(const iterator& x) const { return it_ - x.it_; } private: - template + template friend class RepeatedPtrIterator; // The internal iterator. @@ -2329,11 +2593,17 @@ class RepeatedPtrOverPtrsIterator void RepeatedPtrFieldBase::InternalSwap(RepeatedPtrFieldBase* other) { GOOGLE_DCHECK(this != other); - GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); + GOOGLE_DCHECK(GetArena() == other->GetArena()); - std::swap(rep_, other->rep_); - std::swap(current_size_, other->current_size_); - std::swap(total_size_, other->total_size_); + // Swap all fields at once. + static_assert(std::is_standard_layout::value, + "offsetof() requires standard layout before c++17"); + internal::memswaprep_) - + offsetof(RepeatedPtrFieldBase, current_size_)>( + reinterpret_cast(this) + + offsetof(RepeatedPtrFieldBase, current_size_), + reinterpret_cast(other) + + offsetof(RepeatedPtrFieldBase, current_size_)); } } // namespace internal @@ -2391,35 +2661,30 @@ RepeatedPtrField::pointer_end() const { const_cast(raw_data() + size())); } - // Iterators and helper functions that follow the spirit of the STL // std::back_insert_iterator and std::back_inserter but are tailor-made // for RepeatedField and RepeatedPtrField. Typical usage would be: // // std::copy(some_sequence.begin(), some_sequence.end(), -// google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence())); +// RepeatedFieldBackInserter(proto.mutable_sequence())); // // Ported by johannes from util/gtl/proto-array-iterators.h namespace internal { // A back inserter for RepeatedField objects. -template class RepeatedFieldBackInsertIterator +template +class RepeatedFieldBackInsertIterator : public std::iterator { public: explicit RepeatedFieldBackInsertIterator( RepeatedField* const mutable_field) - : field_(mutable_field) { - } + : field_(mutable_field) {} RepeatedFieldBackInsertIterator& operator=(const T& value) { field_->Add(value); return *this; } - RepeatedFieldBackInsertIterator& operator*() { - return *this; - } - RepeatedFieldBackInsertIterator& operator++() { - return *this; - } + RepeatedFieldBackInsertIterator& operator*() { return *this; } + RepeatedFieldBackInsertIterator& operator++() { return *this; } RepeatedFieldBackInsertIterator& operator++(int /* unused */) { return *this; } @@ -2429,13 +2694,12 @@ template class RepeatedFieldBackInsertIterator }; // A back inserter for RepeatedPtrField objects. -template class RepeatedPtrFieldBackInsertIterator +template +class RepeatedPtrFieldBackInsertIterator : public std::iterator { public: - RepeatedPtrFieldBackInsertIterator( - RepeatedPtrField* const mutable_field) - : field_(mutable_field) { - } + RepeatedPtrFieldBackInsertIterator(RepeatedPtrField* const mutable_field) + : field_(mutable_field) {} RepeatedPtrFieldBackInsertIterator& operator=(const T& value) { *field_->Add() = value; return *this; @@ -2445,18 +2709,12 @@ template class RepeatedPtrFieldBackInsertIterator *field_->Add() = *ptr_to_value; return *this; } -#if LANG_CXX11 RepeatedPtrFieldBackInsertIterator& operator=(T&& value) { *field_->Add() = std::move(value); return *this; } -#endif - RepeatedPtrFieldBackInsertIterator& operator*() { - return *this; - } - RepeatedPtrFieldBackInsertIterator& operator++() { - return *this; - } + RepeatedPtrFieldBackInsertIterator& operator*() { return *this; } + RepeatedPtrFieldBackInsertIterator& operator++() { return *this; } RepeatedPtrFieldBackInsertIterator& operator++(int /* unused */) { return *this; } @@ -2467,26 +2725,21 @@ template class RepeatedPtrFieldBackInsertIterator // A back inserter for RepeatedPtrFields that inserts by transferring ownership // of a pointer. -template class AllocatedRepeatedPtrFieldBackInsertIterator +template +class AllocatedRepeatedPtrFieldBackInsertIterator : public std::iterator { public: explicit AllocatedRepeatedPtrFieldBackInsertIterator( RepeatedPtrField* const mutable_field) - : field_(mutable_field) { - } + : field_(mutable_field) {} AllocatedRepeatedPtrFieldBackInsertIterator& operator=( T* const ptr_to_value) { field_->AddAllocated(ptr_to_value); return *this; } - AllocatedRepeatedPtrFieldBackInsertIterator& operator*() { - return *this; - } - AllocatedRepeatedPtrFieldBackInsertIterator& operator++() { - return *this; - } - AllocatedRepeatedPtrFieldBackInsertIterator& operator++( - int /* unused */) { + AllocatedRepeatedPtrFieldBackInsertIterator& operator*() { return *this; } + AllocatedRepeatedPtrFieldBackInsertIterator& operator++() { return *this; } + AllocatedRepeatedPtrFieldBackInsertIterator& operator++(int /* unused */) { return *this; } @@ -2496,16 +2749,15 @@ template class AllocatedRepeatedPtrFieldBackInsertIterator // Almost identical to AllocatedRepeatedPtrFieldBackInsertIterator. This one // uses the UnsafeArenaAddAllocated instead. -template +template class UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator : public std::iterator { public: explicit UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator( - ::google::protobuf::RepeatedPtrField* const mutable_field) - : field_(mutable_field) { - } + RepeatedPtrField* const mutable_field) + : field_(mutable_field) {} UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator& operator=( - T const* const ptr_to_value) { + T const* const ptr_to_value) { field_->UnsafeArenaAddAllocated(const_cast(ptr_to_value)); return *this; } @@ -2521,37 +2773,41 @@ class UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator } private: - ::google::protobuf::RepeatedPtrField* field_; + RepeatedPtrField* field_; }; } // namespace internal // Provides a back insert iterator for RepeatedField instances, // similar to std::back_inserter(). -template internal::RepeatedFieldBackInsertIterator -RepeatedFieldBackInserter(RepeatedField* const mutable_field) { +template +internal::RepeatedFieldBackInsertIterator RepeatedFieldBackInserter( + RepeatedField* const mutable_field) { return internal::RepeatedFieldBackInsertIterator(mutable_field); } // Provides a back insert iterator for RepeatedPtrField instances, // similar to std::back_inserter(). -template internal::RepeatedPtrFieldBackInsertIterator -RepeatedPtrFieldBackInserter(RepeatedPtrField* const mutable_field) { +template +internal::RepeatedPtrFieldBackInsertIterator RepeatedPtrFieldBackInserter( + RepeatedPtrField* const mutable_field) { return internal::RepeatedPtrFieldBackInsertIterator(mutable_field); } // Special back insert iterator for RepeatedPtrField instances, just in // case someone wants to write generic template code that can access both // RepeatedFields and RepeatedPtrFields using a common name. -template internal::RepeatedPtrFieldBackInsertIterator -RepeatedFieldBackInserter(RepeatedPtrField* const mutable_field) { +template +internal::RepeatedPtrFieldBackInsertIterator RepeatedFieldBackInserter( + RepeatedPtrField* const mutable_field) { return internal::RepeatedPtrFieldBackInsertIterator(mutable_field); } // Provides a back insert iterator for RepeatedPtrField instances // similar to std::back_inserter() which transfers the ownership while // copying elements. -template internal::AllocatedRepeatedPtrFieldBackInsertIterator +template +internal::AllocatedRepeatedPtrFieldBackInsertIterator AllocatedRepeatedPtrFieldBackInserter( RepeatedPtrField* const mutable_field) { return internal::AllocatedRepeatedPtrFieldBackInsertIterator( @@ -2565,19 +2821,32 @@ AllocatedRepeatedPtrFieldBackInserter( // RepeatedPtrField temp_field; // temp_field.AddAllocated(new T); // ... // Do something with temp_field -// temp_field.ExtractSubrange(0, temp_field.size(), NULL); +// temp_field.ExtractSubrange(0, temp_field.size(), nullptr); // If you put temp_field on the arena this fails, because the ownership // transfers to the arena at the "AddAllocated" call and is not released anymore // causing a double delete. Using UnsafeArenaAddAllocated prevents this. -template +template internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator UnsafeArenaAllocatedRepeatedPtrFieldBackInserter( - ::google::protobuf::RepeatedPtrField* const mutable_field) { + RepeatedPtrField* const mutable_field) { return internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator( mutable_field); } -} // namespace protobuf +// Extern declarations of common instantiations to reduce library bloat. +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE + RepeatedPtrField; +} // namespace protobuf } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_REPEATED_FIELD_H__ diff --git a/src/google/protobuf/repeated_field_reflection_unittest.cc b/src/google/protobuf/repeated_field_reflection_unittest.cc index fd46656540186..384d32f530dfa 100644 --- a/src/google/protobuf/repeated_field_reflection_unittest.cc +++ b/src/google/protobuf/repeated_field_reflection_unittest.cc @@ -35,9 +35,9 @@ #include #include -#include -#include #include +#include +#include #include #include @@ -45,20 +45,14 @@ namespace google { namespace protobuf { using unittest::ForeignMessage; -using unittest::TestAllTypes; using unittest::TestAllExtensions; +using unittest::TestAllTypes; namespace { -static int Func(int i, int j) { - return i * j; -} +static int Func(int i, int j) { return i * j; } -static string StrFunc(int i, int j) { - string str; - SStringPrintf(&str, "%d", Func(i, 4)); - return str; -} +static std::string StrFunc(int i, int j) { return StrCat(Func(i, 4)); } TEST(RepeatedFieldReflectionTest, RegularFields) { TestAllTypes message; @@ -95,24 +89,23 @@ TEST(RepeatedFieldReflectionTest, RegularFields) { refl->MutableRepeatedField(&message, fd_repeated_double); // Get RepeatedPtrField objects for all fields of interest. - const RepeatedPtrField& rpf_string = - refl->GetRepeatedPtrField(message, fd_repeated_string); + const RepeatedPtrField& rpf_string = + refl->GetRepeatedPtrField(message, fd_repeated_string); const RepeatedPtrField& rpf_foreign_message = - refl->GetRepeatedPtrField( - message, fd_repeated_foreign_message); + refl->GetRepeatedPtrField(message, + fd_repeated_foreign_message); const RepeatedPtrField& rpf_message = - refl->GetRepeatedPtrField( - message, fd_repeated_foreign_message); + refl->GetRepeatedPtrField(message, fd_repeated_foreign_message); // Get mutable RepeatedPtrField objects for all fields of interest. - RepeatedPtrField* mrpf_string = - refl->MutableRepeatedPtrField(&message, fd_repeated_string); + RepeatedPtrField* mrpf_string = + refl->MutableRepeatedPtrField(&message, fd_repeated_string); RepeatedPtrField* mrpf_foreign_message = refl->MutableRepeatedPtrField( &message, fd_repeated_foreign_message); RepeatedPtrField* mrpf_message = - refl->MutableRepeatedPtrField( - &message, fd_repeated_foreign_message); + refl->MutableRepeatedPtrField(&message, + fd_repeated_foreign_message); // Make sure we can do gets and sets through the Repeated[Ptr]Field objects. for (int i = 0; i < 10; ++i) { @@ -149,12 +142,13 @@ TEST(RepeatedFieldReflectionTest, RegularFields) { // Make sure types are checked correctly at runtime. const FieldDescriptor* fd_optional_int32 = desc->FindFieldByName("optional_int32"); - EXPECT_DEATH(refl->GetRepeatedField( - message, fd_optional_int32), "requires a repeated field"); - EXPECT_DEATH(refl->GetRepeatedField( - message, fd_repeated_int32), "not the right type"); + EXPECT_DEATH(refl->GetRepeatedField(message, fd_optional_int32), + "requires a repeated field"); + EXPECT_DEATH(refl->GetRepeatedField(message, fd_repeated_int32), + "not the right type"); EXPECT_DEATH(refl->GetRepeatedPtrField( - message, fd_repeated_foreign_message), "wrong submessage type"); + message, fd_repeated_foreign_message), + "wrong submessage type"); #endif // PROTOBUF_HAS_DEATH_TEST } @@ -165,8 +159,8 @@ TEST(RepeatedFieldReflectionTest, ExtensionFields) { const Descriptor* desc = extended_message.GetDescriptor(); for (int i = 0; i < 10; ++i) { - extended_message.AddExtension( - unittest::repeated_int64_extension, Func(i, 1)); + extended_message.AddExtension(unittest::repeated_int64_extension, + Func(i, 1)); } const FieldDescriptor* fd_repeated_int64_extension = @@ -177,15 +171,14 @@ TEST(RepeatedFieldReflectionTest, ExtensionFields) { refl->GetRepeatedField(extended_message, fd_repeated_int64_extension); - RepeatedField* mrf_int64_extension = - refl->MutableRepeatedField(&extended_message, - fd_repeated_int64_extension); + RepeatedField* mrf_int64_extension = refl->MutableRepeatedField( + &extended_message, fd_repeated_int64_extension); for (int i = 0; i < 10; ++i) { EXPECT_EQ(Func(i, 1), rf_int64_extension.Get(i)); mrf_int64_extension->Set(i, Func(i, -1)); - EXPECT_EQ(Func(i, -1), - extended_message.GetExtension(unittest::repeated_int64_extension, i)); + EXPECT_EQ(Func(i, -1), extended_message.GetExtension( + unittest::repeated_int64_extension, i)); } } @@ -194,8 +187,8 @@ void TestRepeatedFieldRefIteratorForPrimitive( const Ref& handle, const MessageType& message, ValueType (MessageType::*GetFunc)(int) const) { int index = 0; - for (typename Ref::const_iterator it = handle.begin(); - it != handle.end(); ++it) { + for (typename Ref::const_iterator it = handle.begin(); it != handle.end(); + ++it) { EXPECT_EQ((message.*GetFunc)(index), *it); ++index; } @@ -204,10 +197,11 @@ void TestRepeatedFieldRefIteratorForPrimitive( template void TestRepeatedFieldRefIteratorForString( - const RepeatedFieldRef& handle, const MessageType& message, + const RepeatedFieldRef& handle, const MessageType& message, ValueType (MessageType::*GetFunc)(int) const) { int index = 0; - for (typename RepeatedFieldRef::const_iterator it = handle.begin(); + for (typename RepeatedFieldRef::const_iterator it = + handle.begin(); it != handle.end(); ++it) { // Test both operator* and operator-> EXPECT_EQ((message.*GetFunc)(index), *it); @@ -244,28 +238,28 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) { refl->GetRepeatedFieldRef(message, fd_repeated_int32); const RepeatedFieldRef rf_double = refl->GetRepeatedFieldRef(message, fd_repeated_double); - const RepeatedFieldRef rf_string = - refl->GetRepeatedFieldRef(message, fd_repeated_string); + const RepeatedFieldRef rf_string = + refl->GetRepeatedFieldRef(message, fd_repeated_string); const RepeatedFieldRef rf_foreign_message = - refl->GetRepeatedFieldRef( - message, fd_repeated_foreign_message); + refl->GetRepeatedFieldRef(message, + fd_repeated_foreign_message); const RepeatedFieldRef rf_message = - refl->GetRepeatedFieldRef( - message, fd_repeated_foreign_message); + refl->GetRepeatedFieldRef(message, fd_repeated_foreign_message); // Get MutableRepeatedFieldRef objects for all fields of interest. const MutableRepeatedFieldRef mrf_int32 = refl->GetMutableRepeatedFieldRef(&message, fd_repeated_int32); const MutableRepeatedFieldRef mrf_double = refl->GetMutableRepeatedFieldRef(&message, fd_repeated_double); - const MutableRepeatedFieldRef mrf_string = - refl->GetMutableRepeatedFieldRef(&message, fd_repeated_string); + const MutableRepeatedFieldRef mrf_string = + refl->GetMutableRepeatedFieldRef(&message, + fd_repeated_string); const MutableRepeatedFieldRef mrf_foreign_message = refl->GetMutableRepeatedFieldRef( &message, fd_repeated_foreign_message); const MutableRepeatedFieldRef mrf_message = - refl->GetMutableRepeatedFieldRef( - &message, fd_repeated_foreign_message); + refl->GetMutableRepeatedFieldRef(&message, + fd_repeated_foreign_message); EXPECT_EQ(message.repeated_int32_size(), rf_int32.size()); EXPECT_EQ(message.repeated_int32_size(), mrf_int32.size()); @@ -273,8 +267,7 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) { EXPECT_EQ(message.repeated_double_size(), mrf_double.size()); EXPECT_EQ(message.repeated_string_size(), rf_string.size()); EXPECT_EQ(message.repeated_string_size(), mrf_string.size()); - EXPECT_EQ(message.repeated_foreign_message_size(), - rf_foreign_message.size()); + EXPECT_EQ(message.repeated_foreign_message_size(), rf_foreign_message.size()); EXPECT_EQ(message.repeated_foreign_message_size(), mrf_foreign_message.size()); EXPECT_EQ(message.repeated_foreign_message_size(), rf_message.size()); @@ -299,16 +292,19 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) { EXPECT_EQ(rf_string.Get(i), StrFunc(i, 5)); ForeignMessage scratch_space; EXPECT_EQ(rf_foreign_message.Get(i, &scratch_space).c(), Func(i, 6)); - EXPECT_EQ(down_cast( - rf_message.Get(i, &scratch_space)).c(), Func(i, 6)); + EXPECT_EQ( + down_cast(rf_message.Get(i, &scratch_space)).c(), + Func(i, 6)); // Check gets through mutable objects. EXPECT_EQ(mrf_int32.Get(i), Func(i, 1)); EXPECT_EQ(mrf_double.Get(i), Func(i, 2)); EXPECT_EQ(mrf_string.Get(i), StrFunc(i, 5)); EXPECT_EQ(mrf_foreign_message.Get(i, &scratch_space).c(), Func(i, 6)); - EXPECT_EQ(down_cast( - mrf_message.Get(i, &scratch_space)).c(), Func(i, 6)); + EXPECT_EQ( + down_cast(mrf_message.Get(i, &scratch_space)) + .c(), + Func(i, 6)); // Check sets through mutable objects. mrf_int32.Set(i, Func(i, -1)); @@ -344,7 +340,7 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) { } EXPECT_EQ(10, index); - // Test iterator operators that are not ususally used in regular for-loops. + // Test iterator operators that are not usually used in regular for-loops. // Including: post increment, assign, ==. MessageIterator old_it = rf_foreign_message.begin(); MessageIterator new_it = old_it++; @@ -429,12 +425,13 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) { // Make sure types are checked correctly at runtime. const FieldDescriptor* fd_optional_int32 = desc->FindFieldByName("optional_int32"); - EXPECT_DEATH(refl->GetRepeatedFieldRef( - message, fd_optional_int32), ""); - EXPECT_DEATH(refl->GetRepeatedFieldRef( - message, fd_repeated_int32), ""); + EXPECT_DEATH(refl->GetRepeatedFieldRef(message, fd_optional_int32), + ""); + EXPECT_DEATH(refl->GetRepeatedFieldRef(message, fd_repeated_int32), + ""); EXPECT_DEATH(refl->GetRepeatedFieldRef( - message, fd_repeated_foreign_message), ""); + message, fd_repeated_foreign_message), + ""); #endif // PROTOBUF_HAS_DEATH_TEST } @@ -453,16 +450,14 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForEnums) { const RepeatedFieldRef enum_ref = refl->GetRepeatedFieldRef( message, fd_repeated_nested_enum); - const MutableRepeatedFieldRef - mutable_enum_ref = + const MutableRepeatedFieldRef mutable_enum_ref = refl->GetMutableRepeatedFieldRef( &message, fd_repeated_nested_enum); const RepeatedFieldRef int32_ref = - refl->GetRepeatedFieldRef( - message, fd_repeated_nested_enum); + refl->GetRepeatedFieldRef(message, fd_repeated_nested_enum); const MutableRepeatedFieldRef mutable_int32_ref = - refl->GetMutableRepeatedFieldRef( - &message, fd_repeated_nested_enum); + refl->GetMutableRepeatedFieldRef(&message, + fd_repeated_nested_enum); EXPECT_EQ(message.repeated_nested_enum_size(), enum_ref.size()); EXPECT_EQ(message.repeated_nested_enum_size(), mutable_enum_ref.size()); @@ -537,8 +532,8 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForExtensionFields) { const Descriptor* desc = extended_message.GetDescriptor(); for (int i = 0; i < 10; ++i) { - extended_message.AddExtension( - unittest::repeated_int64_extension, Func(i, 1)); + extended_message.AddExtension(unittest::repeated_int64_extension, + Func(i, 1)); } const FieldDescriptor* fd_repeated_int64_extension = @@ -547,17 +542,17 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForExtensionFields) { const RepeatedFieldRef rf_int64_extension = refl->GetRepeatedFieldRef(extended_message, - fd_repeated_int64_extension); + fd_repeated_int64_extension); const MutableRepeatedFieldRef mrf_int64_extension = refl->GetMutableRepeatedFieldRef(&extended_message, - fd_repeated_int64_extension); + fd_repeated_int64_extension); for (int i = 0; i < 10; ++i) { EXPECT_EQ(Func(i, 1), rf_int64_extension.Get(i)); mrf_int64_extension.Set(i, Func(i, -1)); - EXPECT_EQ(Func(i, -1), - extended_message.GetExtension(unittest::repeated_int64_extension, i)); + EXPECT_EQ(Func(i, -1), extended_message.GetExtension( + unittest::repeated_int64_extension, i)); } } @@ -603,29 +598,25 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefMergeFromAndSwap) { refl->GetMutableRepeatedFieldRef(&m0, fd_repeated_int32); const MutableRepeatedFieldRef mrf_double = refl->GetMutableRepeatedFieldRef(&m0, fd_repeated_double); - const MutableRepeatedFieldRef mrf_string = - refl->GetMutableRepeatedFieldRef(&m0, fd_repeated_string); + const MutableRepeatedFieldRef mrf_string = + refl->GetMutableRepeatedFieldRef(&m0, fd_repeated_string); const MutableRepeatedFieldRef mrf_foreign_message = refl->GetMutableRepeatedFieldRef( &m0, fd_repeated_foreign_message); - const MutableRepeatedFieldRef - mrf_nested_enum = + const MutableRepeatedFieldRef mrf_nested_enum = refl->GetMutableRepeatedFieldRef( &m0, fd_repeated_nested_enum); // Test MutableRepeatedRef::CopyFrom - mrf_int32.CopyFrom( - refl->GetRepeatedFieldRef(m1, fd_repeated_int32)); + mrf_int32.CopyFrom(refl->GetRepeatedFieldRef(m1, fd_repeated_int32)); mrf_double.CopyFrom( refl->GetRepeatedFieldRef(m1, fd_repeated_double)); mrf_string.CopyFrom( - refl->GetRepeatedFieldRef(m1, fd_repeated_string)); - mrf_foreign_message.CopyFrom( - refl->GetRepeatedFieldRef( - m1, fd_repeated_foreign_message)); - mrf_nested_enum.CopyFrom( - refl->GetRepeatedFieldRef( - m1, fd_repeated_nested_enum)); + refl->GetRepeatedFieldRef(m1, fd_repeated_string)); + mrf_foreign_message.CopyFrom(refl->GetRepeatedFieldRef( + m1, fd_repeated_foreign_message)); + mrf_nested_enum.CopyFrom(refl->GetRepeatedFieldRef( + m1, fd_repeated_nested_enum)); for (int i = 0; i < 10; ++i) { EXPECT_EQ(Func(i, 11), m0.repeated_int32(i)); EXPECT_EQ(Func(i, 12), m0.repeated_double(i)); @@ -635,18 +626,15 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefMergeFromAndSwap) { } // Test MutableRepeatedRef::MergeFrom - mrf_int32.MergeFrom( - refl->GetRepeatedFieldRef(m2, fd_repeated_int32)); + mrf_int32.MergeFrom(refl->GetRepeatedFieldRef(m2, fd_repeated_int32)); mrf_double.MergeFrom( refl->GetRepeatedFieldRef(m2, fd_repeated_double)); mrf_string.MergeFrom( - refl->GetRepeatedFieldRef(m2, fd_repeated_string)); - mrf_foreign_message.MergeFrom( - refl->GetRepeatedFieldRef( - m2, fd_repeated_foreign_message)); - mrf_nested_enum.MergeFrom( - refl->GetRepeatedFieldRef( - m2, fd_repeated_nested_enum)); + refl->GetRepeatedFieldRef(m2, fd_repeated_string)); + mrf_foreign_message.MergeFrom(refl->GetRepeatedFieldRef( + m2, fd_repeated_foreign_message)); + mrf_nested_enum.MergeFrom(refl->GetRepeatedFieldRef( + m2, fd_repeated_nested_enum)); for (int i = 0; i < 10; ++i) { EXPECT_EQ(Func(i, 21), m0.repeated_int32(i + 10)); EXPECT_EQ(Func(i, 22), m0.repeated_double(i + 10)); @@ -662,10 +650,9 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefMergeFromAndSwap) { mrf_double.Swap( refl->GetMutableRepeatedFieldRef(&m2, fd_repeated_double)); mrf_string.Swap( - refl->GetMutableRepeatedFieldRef(&m2, fd_repeated_string)); - mrf_foreign_message.Swap( - refl->GetMutableRepeatedFieldRef( - &m2, fd_repeated_foreign_message)); + refl->GetMutableRepeatedFieldRef(&m2, fd_repeated_string)); + mrf_foreign_message.Swap(refl->GetMutableRepeatedFieldRef( + &m2, fd_repeated_foreign_message)); mrf_nested_enum.Swap( refl->GetMutableRepeatedFieldRef( &m2, fd_repeated_nested_enum)); @@ -704,16 +691,16 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefDynamicMessage) { desc->FindFieldByName("repeated_int32"); DynamicMessageFactory factory; - google::protobuf::scoped_ptr dynamic_message(factory.GetPrototype(desc)->New()); + std::unique_ptr dynamic_message(factory.GetPrototype(desc)->New()); const Reflection* refl = dynamic_message->GetReflection(); MutableRepeatedFieldRef rf_int32 = - refl->GetMutableRepeatedFieldRef( - dynamic_message.get(), fd_repeated_int32); + refl->GetMutableRepeatedFieldRef(dynamic_message.get(), + fd_repeated_int32); rf_int32.Add(1234); EXPECT_EQ(1, refl->FieldSize(*dynamic_message, fd_repeated_int32)); - EXPECT_EQ(1234, refl->GetRepeatedInt32(*dynamic_message, - fd_repeated_int32, 0)); + EXPECT_EQ(1234, + refl->GetRepeatedInt32(*dynamic_message, fd_repeated_int32, 0)); } } // namespace diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc index ae50146597995..a396b619f2497 100644 --- a/src/google/protobuf/repeated_field_unittest.cc +++ b/src/google/protobuf/repeated_field_unittest.cc @@ -35,27 +35,41 @@ // TODO(kenton): Improve this unittest to bring it up to the standards of // other proto2 unittests. +#include + #include +#include +#include #include #include +#include +#include #include -#include - #include #include #include +#include +#include #include #include -#include #include -namespace google { -using protobuf_unittest::TestAllTypes; +// Must be included last. +#include +namespace google { namespace protobuf { namespace { +using ::protobuf_unittest::TestAllTypes; +using ::testing::ElementsAre; + +TEST(RepeatedField, ConstInit) { + PROTOBUF_CONSTINIT static RepeatedField field{}; // NOLINT + EXPECT_TRUE(field.empty()); +} + // Test operations on a small RepeatedField. TEST(RepeatedField, Small) { RepeatedField field; @@ -68,26 +82,41 @@ TEST(RepeatedField, Small) { EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 1); EXPECT_EQ(field.Get(0), 5); + EXPECT_EQ(field.at(0), 5); field.Add(42); EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 2); EXPECT_EQ(field.Get(0), 5); + EXPECT_EQ(field.at(0), 5); EXPECT_EQ(field.Get(1), 42); + EXPECT_EQ(field.at(1), 42); field.Set(1, 23); EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 2); EXPECT_EQ(field.Get(0), 5); + EXPECT_EQ(field.at(0), 5); EXPECT_EQ(field.Get(1), 23); + EXPECT_EQ(field.at(1), 23); + + field.at(1) = 25; + + EXPECT_FALSE(field.empty()); + EXPECT_EQ(field.size(), 2); + EXPECT_EQ(field.Get(0), 5); + EXPECT_EQ(field.at(0), 5); + EXPECT_EQ(field.Get(1), 25); + EXPECT_EQ(field.at(1), 25); field.RemoveLast(); EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 1); EXPECT_EQ(field.Get(0), 5); + EXPECT_EQ(field.at(0), 5); field.Clear(); @@ -249,6 +278,76 @@ TEST(RepeatedField, Resize) { EXPECT_TRUE(field.empty()); } +TEST(RepeatedField, ReserveNothing) { + RepeatedField field; + EXPECT_EQ(0, field.Capacity()); + + field.Reserve(-1); + EXPECT_EQ(0, field.Capacity()); +} + +TEST(RepeatedField, ReserveLowerClamp) { + const int clamped_value = internal::CalculateReserveSize(0, 1); + EXPECT_EQ(internal::kRepeatedFieldLowerClampLimit, clamped_value); + EXPECT_EQ(clamped_value, internal::CalculateReserveSize(clamped_value, 2)); +} + +TEST(RepeatedField, ReserveGrowth) { + // Make sure the field capacity doubles in size on repeated reservation. + for (int size = internal::kRepeatedFieldLowerClampLimit, i = 0; i < 4; + ++i, size *= 2) { + EXPECT_EQ(size * 2, internal::CalculateReserveSize(size, size + 1)); + } +} + +TEST(RepeatedField, ReserveLarge) { + const int old_size = 10; + // This is a size we won't get by doubling: + const int new_size = old_size * 3 + 1; + + // Reserving more than 2x current capacity should grow directly to that size. + EXPECT_EQ(new_size, internal::CalculateReserveSize(old_size, new_size)); +} + +TEST(RepeatedField, ReserveHuge) { + // Largest value that does not clamp to the large limit: + constexpr int non_clamping_limit = std::numeric_limits::max() / 2; + ASSERT_LT(2 * non_clamping_limit, std::numeric_limits::max()); + EXPECT_LT(internal::CalculateReserveSize(non_clamping_limit, + non_clamping_limit + 1), + std::numeric_limits::max()); + + // Smallest size that *will* clamp to the upper limit: + constexpr int min_clamping_size = std::numeric_limits::max() / 2 + 1; + EXPECT_EQ( + internal::CalculateReserveSize(min_clamping_size, min_clamping_size + 1), + std::numeric_limits::max()); + +#ifdef PROTOBUF_TEST_ALLOW_LARGE_ALLOC + // The rest of this test may allocate several GB of memory, so it is only + // built if explicitly requested. + RepeatedField huge_field; + + // Reserve a size for huge_field that will clamp. + huge_field.Reserve(min_clamping_size); + EXPECT_GE(huge_field.Capacity(), min_clamping_size); + ASSERT_LT(huge_field.Capacity(), std::numeric_limits::max() - 1); + +#ifndef ADDRESS_SANITIZER + // The array containing all the fields is, in theory, up to MAXINT-1 in size. + // However, some compilers can't handle a struct whose size is larger + // than 2GB, and the protocol buffer format doesn't handle more than 2GB of + // data at once, either. So we limit it, but the code below accesses beyond + // that limit. + + // Allocation may return more memory than we requested. However, the updated + // size must still be clamped to a valid range. + huge_field.Reserve(huge_field.Capacity() + 1); + EXPECT_EQ(huge_field.Capacity(), std::numeric_limits::max()); +#endif +#endif // PROTOBUF_TEST_ALLOW_LARGE_ALLOC +} + TEST(RepeatedField, MergeFrom) { RepeatedField source, destination; source.Add(4); @@ -267,15 +366,6 @@ TEST(RepeatedField, MergeFrom) { EXPECT_EQ(5, destination.Get(4)); } -#ifdef PROTOBUF_HAS_DEATH_TEST -#ifndef NDEBUG -TEST(RepeatedField, MergeFromSelf) { - RepeatedField me; - me.Add(3); - EXPECT_DEATH(me.MergeFrom(me), ""); -} -#endif // NDEBUG -#endif // PROTOBUF_HAS_DEATH_TEST TEST(RepeatedField, CopyFrom) { RepeatedField source, destination; @@ -333,6 +423,71 @@ TEST(RepeatedField, Erase) { EXPECT_EQ(8, me.Get(2)); } +// Add contents of empty container to an empty field. +TEST(RepeatedField, AddRange1) { + RepeatedField me; + std::vector values; + + me.Add(values.begin(), values.end()); + ASSERT_EQ(me.size(), 0); +} + +// Add contents of container with one thing to an empty field. +TEST(RepeatedField, AddRange2) { + RepeatedField me; + std::vector values; + values.push_back(-1); + + me.Add(values.begin(), values.end()); + ASSERT_EQ(me.size(), 1); + ASSERT_EQ(me.Get(0), values[0]); +} + +// Add contents of container with more than one thing to an empty field. +TEST(RepeatedField, AddRange3) { + RepeatedField me; + std::vector values; + values.push_back(0); + values.push_back(1); + + me.Add(values.begin(), values.end()); + ASSERT_EQ(me.size(), 2); + ASSERT_EQ(me.Get(0), values[0]); + ASSERT_EQ(me.Get(1), values[1]); +} + +// Add contents of container with more than one thing to a non-empty field. +TEST(RepeatedField, AddRange4) { + RepeatedField me; + me.Add(0); + me.Add(1); + + std::vector values; + values.push_back(2); + values.push_back(3); + + me.Add(values.begin(), values.end()); + ASSERT_EQ(me.size(), 4); + ASSERT_EQ(me.Get(0), 0); + ASSERT_EQ(me.Get(1), 1); + ASSERT_EQ(me.Get(2), values[0]); + ASSERT_EQ(me.Get(3), values[1]); +} + +// Add contents of a stringstream in order to test code paths where there is +// an input iterator. +TEST(RepeatedField, AddRange5) { + RepeatedField me; + + std::stringstream ss; + ss << 1 << ' ' << 2; + + me.Add(std::istream_iterator(ss), std::istream_iterator()); + ASSERT_EQ(me.size(), 2); + ASSERT_EQ(me.Get(0), 1); + ASSERT_EQ(me.Get(1), 2); +} + TEST(RepeatedField, CopyConstruct) { RepeatedField source; source.Add(1); @@ -347,6 +502,9 @@ TEST(RepeatedField, CopyConstruct) { TEST(RepeatedField, IteratorConstruct) { std::vector values; + RepeatedField empty(values.begin(), values.end()); + ASSERT_EQ(values.size(), empty.size()); + values.push_back(1); values.push_back(2); @@ -390,6 +548,180 @@ TEST(RepeatedField, SelfAssign) { EXPECT_EQ(8, source.Get(1)); } +TEST(RepeatedField, MoveConstruct) { + { + RepeatedField source; + source.Add(1); + source.Add(2); + const int* data = source.data(); + RepeatedField destination = std::move(source); + EXPECT_EQ(data, destination.data()); + EXPECT_THAT(destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_TRUE(source.empty()); + } + { + Arena arena; + RepeatedField* source = + Arena::CreateMessage>(&arena); + source->Add(1); + source->Add(2); + RepeatedField destination = std::move(*source); + EXPECT_EQ(nullptr, destination.GetArena()); + EXPECT_THAT(destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre(1, 2)); + } +} + +TEST(RepeatedField, MoveAssign) { + { + RepeatedField source; + source.Add(1); + source.Add(2); + RepeatedField destination; + destination.Add(3); + const int* source_data = source.data(); + const int* destination_data = destination.data(); + destination = std::move(source); + EXPECT_EQ(source_data, destination.data()); + EXPECT_THAT(destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_EQ(destination_data, source.data()); + EXPECT_THAT(source, ElementsAre(3)); + } + { + Arena arena; + RepeatedField* source = + Arena::CreateMessage>(&arena); + source->Add(1); + source->Add(2); + RepeatedField* destination = + Arena::CreateMessage>(&arena); + destination->Add(3); + const int* source_data = source->data(); + const int* destination_data = destination->data(); + *destination = std::move(*source); + EXPECT_EQ(source_data, destination->data()); + EXPECT_THAT(*destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_EQ(destination_data, source->data()); + EXPECT_THAT(*source, ElementsAre(3)); + } + { + Arena source_arena; + RepeatedField* source = + Arena::CreateMessage>(&source_arena); + source->Add(1); + source->Add(2); + Arena destination_arena; + RepeatedField* destination = + Arena::CreateMessage>(&destination_arena); + destination->Add(3); + *destination = std::move(*source); + EXPECT_THAT(*destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre(1, 2)); + } + { + Arena arena; + RepeatedField* source = + Arena::CreateMessage>(&arena); + source->Add(1); + source->Add(2); + RepeatedField destination; + destination.Add(3); + destination = std::move(*source); + EXPECT_THAT(destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre(1, 2)); + } + { + RepeatedField source; + source.Add(1); + source.Add(2); + Arena arena; + RepeatedField* destination = + Arena::CreateMessage>(&arena); + destination->Add(3); + *destination = std::move(source); + EXPECT_THAT(*destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(source, ElementsAre(1, 2)); + } + { + RepeatedField field; + // An alias to defeat -Wself-move. + RepeatedField& alias = field; + field.Add(1); + field.Add(2); + const int* data = field.data(); + field = std::move(alias); + EXPECT_EQ(data, field.data()); + EXPECT_THAT(field, ElementsAre(1, 2)); + } + { + Arena arena; + RepeatedField* field = + Arena::CreateMessage>(&arena); + field->Add(1); + field->Add(2); + const int* data = field->data(); + *field = std::move(*field); + EXPECT_EQ(data, field->data()); + EXPECT_THAT(*field, ElementsAre(1, 2)); + } +} + +TEST(Movable, Works) { + class NonMoveConstructible { + public: + NonMoveConstructible(NonMoveConstructible&&) = delete; + NonMoveConstructible& operator=(NonMoveConstructible&&) { return *this; } + }; + class NonMoveAssignable { + public: + NonMoveAssignable(NonMoveAssignable&&) {} + NonMoveAssignable& operator=(NonMoveConstructible&&) = delete; + }; + class NonMovable { + public: + NonMovable(NonMovable&&) = delete; + NonMovable& operator=(NonMovable&&) = delete; + }; + + EXPECT_TRUE(internal::IsMovable::value); + + EXPECT_FALSE(std::is_move_constructible::value); + EXPECT_TRUE(std::is_move_assignable::value); + EXPECT_FALSE(internal::IsMovable::value); + + EXPECT_TRUE(std::is_move_constructible::value); + EXPECT_FALSE(std::is_move_assignable::value); + EXPECT_FALSE(internal::IsMovable::value); + + EXPECT_FALSE(internal::IsMovable::value); +} + +TEST(RepeatedField, MoveAdd) { + RepeatedPtrField field; + TestAllTypes test_all_types; + auto* optional_nested_message = + test_all_types.mutable_optional_nested_message(); + optional_nested_message->set_bb(42); + field.Add(std::move(test_all_types)); + + EXPECT_EQ(optional_nested_message, + field.Mutable(0)->mutable_optional_nested_message()); +} + TEST(RepeatedField, MutableDataIsMutable) { RepeatedField field; field.Add(1); @@ -442,27 +774,23 @@ TEST(RepeatedField, ExtractSubrange) { for (int start = 0; start < sz - num; ++start) { // Create RepeatedField with sz elements having values 0 through sz-1. RepeatedField field; - for (int i = 0; i < sz; ++i) - field.Add(i); + for (int i = 0; i < sz; ++i) field.Add(i); EXPECT_EQ(field.size(), sz); // Create a catcher array and call ExtractSubrange. int32 catcher[10]; - for (int i = 0; i < 10; ++i) - catcher[i] = -1; + for (int i = 0; i < 10; ++i) catcher[i] = -1; field.ExtractSubrange(start, num, catcher); // Does the resulting array have the right size? EXPECT_EQ(field.size(), sz - num); // Were the removed elements extracted into the catcher array? - for (int i = 0; i < num; ++i) - EXPECT_EQ(catcher[i], start + i); + for (int i = 0; i < num; ++i) EXPECT_EQ(catcher[i], start + i); EXPECT_EQ(catcher[num], -1); // Does the resulting array contain the right values? - for (int i = 0; i < start; ++i) - EXPECT_EQ(field.Get(i), i); + for (int i = 0; i < start; ++i) EXPECT_EQ(field.Get(i), i); for (int i = start; i < field.size(); ++i) EXPECT_EQ(field.Get(i), i + num); } @@ -476,9 +804,9 @@ TEST(RepeatedField, ClearThenReserveMore) { // present. Use a 'string' and > 16 bytes length so that the elements are // non-POD and allocate -- the leak checker will catch any skipped destructor // calls here. - RepeatedField field; + RepeatedField field; for (int i = 0; i < 32; i++) { - field.Add(string("abcdefghijklmnopqrstuvwxyz0123456789")); + field.Add(std::string("abcdefghijklmnopqrstuvwxyz0123456789")); } EXPECT_EQ(32, field.size()); field.Clear(); @@ -492,12 +820,25 @@ TEST(RepeatedField, ClearThenReserveMore) { // strings. } +TEST(RepeatedField, TestSAddFromSelf) { + RepeatedField field; + field.Add(0); + for (int i = 0; i < 1000; i++) { + field.Add(field[0]); + } +} + // =================================================================== // RepeatedPtrField tests. These pretty much just mirror the RepeatedField // tests above. +TEST(RepeatedPtrField, ConstInit) { + PROTOBUF_CONSTINIT static RepeatedPtrField field{}; // NOLINT + EXPECT_TRUE(field.empty()); +} + TEST(RepeatedPtrField, Small) { - RepeatedPtrField field; + RepeatedPtrField field; EXPECT_TRUE(field.empty()); EXPECT_EQ(field.size(), 0); @@ -507,26 +848,32 @@ TEST(RepeatedPtrField, Small) { EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 1); EXPECT_EQ(field.Get(0), "foo"); + EXPECT_EQ(field.at(0), "foo"); field.Add()->assign("bar"); EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 2); EXPECT_EQ(field.Get(0), "foo"); + EXPECT_EQ(field.at(0), "foo"); EXPECT_EQ(field.Get(1), "bar"); + EXPECT_EQ(field.at(1), "bar"); field.Mutable(1)->assign("baz"); EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 2); EXPECT_EQ(field.Get(0), "foo"); + EXPECT_EQ(field.at(0), "foo"); EXPECT_EQ(field.Get(1), "baz"); + EXPECT_EQ(field.at(1), "baz"); field.RemoveLast(); EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 1); EXPECT_EQ(field.Get(0), "foo"); + EXPECT_EQ(field.at(0), "foo"); field.Clear(); @@ -535,7 +882,7 @@ TEST(RepeatedPtrField, Small) { } TEST(RepeatedPtrField, Large) { - RepeatedPtrField field; + RepeatedPtrField field; for (int i = 0; i < 16; i++) { *field.Add() += 'a' + i; @@ -548,13 +895,13 @@ TEST(RepeatedPtrField, Large) { EXPECT_EQ(field.Get(i)[0], 'a' + i); } - int min_expected_usage = 16 * sizeof(string); + int min_expected_usage = 16 * sizeof(std::string); EXPECT_GE(field.SpaceUsedExcludingSelf(), min_expected_usage); } TEST(RepeatedPtrField, SwapSmallSmall) { - RepeatedPtrField field1; - RepeatedPtrField field2; + RepeatedPtrField field1; + RepeatedPtrField field2; EXPECT_TRUE(field1.empty()); EXPECT_EQ(field1.size(), 0); @@ -583,8 +930,8 @@ TEST(RepeatedPtrField, SwapSmallSmall) { } TEST(RepeatedPtrField, SwapLargeSmall) { - RepeatedPtrField field1; - RepeatedPtrField field2; + RepeatedPtrField field1; + RepeatedPtrField field2; field2.Add()->assign("foo"); field2.Add()->assign("bar"); @@ -604,8 +951,8 @@ TEST(RepeatedPtrField, SwapLargeSmall) { } TEST(RepeatedPtrField, SwapLargeLarge) { - RepeatedPtrField field1; - RepeatedPtrField field2; + RepeatedPtrField field1; + RepeatedPtrField field2; field1.Add()->assign("foo"); field1.Add()->assign("bar"); @@ -629,8 +976,8 @@ TEST(RepeatedPtrField, SwapLargeLarge) { } } -static int ReservedSpace(RepeatedPtrField* field) { - const string* const* ptr = field->data(); +static int ReservedSpace(RepeatedPtrField* field) { + const std::string* const* ptr = field->data(); do { field->Add(); } while (field->data() == ptr); @@ -639,14 +986,14 @@ static int ReservedSpace(RepeatedPtrField* field) { } TEST(RepeatedPtrField, ReserveMoreThanDouble) { - RepeatedPtrField field; + RepeatedPtrField field; field.Reserve(20); EXPECT_LE(20, ReservedSpace(&field)); } TEST(RepeatedPtrField, ReserveLessThanDouble) { - RepeatedPtrField field; + RepeatedPtrField field; field.Reserve(20); int capacity = field.Capacity(); @@ -657,9 +1004,9 @@ TEST(RepeatedPtrField, ReserveLessThanDouble) { } TEST(RepeatedPtrField, ReserveLessThanExisting) { - RepeatedPtrField field; + RepeatedPtrField field; field.Reserve(20); - const string* const* previous_ptr = field.data(); + const std::string* const* previous_ptr = field.data(); field.Reserve(10); EXPECT_EQ(previous_ptr, field.data()); @@ -670,8 +1017,8 @@ TEST(RepeatedPtrField, ReserveDoesntLoseAllocated) { // Check that a bug is fixed: An earlier implementation of Reserve() // failed to copy pointers to allocated-but-cleared objects, possibly // leading to segfaults. - RepeatedPtrField field; - string* first = field.Add(); + RepeatedPtrField field; + std::string* first = field.Add(); field.RemoveLast(); field.Reserve(20); @@ -681,9 +1028,9 @@ TEST(RepeatedPtrField, ReserveDoesntLoseAllocated) { // Clearing elements is tricky with RepeatedPtrFields since the memory for // the elements is retained and reused. TEST(RepeatedPtrField, ClearedElements) { - RepeatedPtrField field; + RepeatedPtrField field; - string* original = field.Add(); + std::string* original = field.Add(); *original = "foo"; EXPECT_EQ(field.ClearedCount(), 0); @@ -692,7 +1039,8 @@ TEST(RepeatedPtrField, ClearedElements) { EXPECT_TRUE(original->empty()); EXPECT_EQ(field.ClearedCount(), 1); - EXPECT_EQ(field.Add(), original); // Should return same string for reuse. + EXPECT_EQ(field.Add(), + original); // Should return same string for reuse. EXPECT_EQ(field.ReleaseLast(), original); // We take ownership. EXPECT_EQ(field.ClearedCount(), 0); @@ -721,7 +1069,7 @@ TEST(RepeatedPtrField, ClearedElements) { // Test all code paths in AddAllocated(). TEST(RepeatedPtrField, AddAlocated) { - RepeatedPtrField field; + RepeatedPtrField field; while (field.size() < field.Capacity()) { field.Add()->assign("filler"); } @@ -729,14 +1077,14 @@ TEST(RepeatedPtrField, AddAlocated) { int index = field.size(); // First branch: Field is at capacity with no cleared objects. - string* foo = new string("foo"); + std::string* foo = new std::string("foo"); field.AddAllocated(foo); EXPECT_EQ(index + 1, field.size()); EXPECT_EQ(0, field.ClearedCount()); EXPECT_EQ(foo, &field.Get(index)); // Last branch: Field is not at capacity and there are no cleared objects. - string* bar = new string("bar"); + std::string* bar = new std::string("bar"); field.AddAllocated(bar); ++index; EXPECT_EQ(index + 1, field.size()); @@ -745,7 +1093,7 @@ TEST(RepeatedPtrField, AddAlocated) { // Third branch: Field is not at capacity and there are no cleared objects. field.RemoveLast(); - string* baz = new string("baz"); + std::string* baz = new std::string("baz"); field.AddAllocated(baz); EXPECT_EQ(index + 1, field.size()); EXPECT_EQ(1, field.ClearedCount()); @@ -757,7 +1105,7 @@ TEST(RepeatedPtrField, AddAlocated) { } field.RemoveLast(); index = field.size(); - string* qux = new string("qux"); + std::string* qux = new std::string("qux"); field.AddAllocated(qux); EXPECT_EQ(index + 1, field.size()); // We should have discarded the cleared object. @@ -766,7 +1114,7 @@ TEST(RepeatedPtrField, AddAlocated) { } TEST(RepeatedPtrField, MergeFrom) { - RepeatedPtrField source, destination; + RepeatedPtrField source, destination; source.Add()->assign("4"); source.Add()->assign("5"); destination.Add()->assign("1"); @@ -783,16 +1131,9 @@ TEST(RepeatedPtrField, MergeFrom) { EXPECT_EQ("5", destination.Get(4)); } -#ifdef PROTOBUF_HAS_DEATH_TEST -TEST(RepeatedPtrField, MergeFromSelf) { - RepeatedPtrField me; - me.Add()->assign("1"); - EXPECT_DEATH(me.MergeFrom(me), ""); -} -#endif // PROTOBUF_HAS_DEATH_TEST TEST(RepeatedPtrField, CopyFrom) { - RepeatedPtrField source, destination; + RepeatedPtrField source, destination; source.Add()->assign("4"); source.Add()->assign("5"); destination.Add()->assign("1"); @@ -807,7 +1148,7 @@ TEST(RepeatedPtrField, CopyFrom) { } TEST(RepeatedPtrField, CopyFromSelf) { - RepeatedPtrField me; + RepeatedPtrField me; me.Add()->assign("1"); me.CopyFrom(me); ASSERT_EQ(1, me.size()); @@ -815,8 +1156,8 @@ TEST(RepeatedPtrField, CopyFromSelf) { } TEST(RepeatedPtrField, Erase) { - RepeatedPtrField me; - RepeatedPtrField::iterator it = me.erase(me.begin(), me.end()); + RepeatedPtrField me; + RepeatedPtrField::iterator it = me.erase(me.begin(), me.end()); EXPECT_TRUE(me.begin() == it); EXPECT_EQ(0, me.size()); @@ -848,11 +1189,11 @@ TEST(RepeatedPtrField, Erase) { } TEST(RepeatedPtrField, CopyConstruct) { - RepeatedPtrField source; + RepeatedPtrField source; source.Add()->assign("1"); source.Add()->assign("2"); - RepeatedPtrField destination(source); + RepeatedPtrField destination(source); ASSERT_EQ(2, destination.size()); EXPECT_EQ("1", destination.Get(0)); @@ -860,16 +1201,16 @@ TEST(RepeatedPtrField, CopyConstruct) { } TEST(RepeatedPtrField, IteratorConstruct_String) { - std::vector values; + std::vector values; values.push_back("1"); values.push_back("2"); - RepeatedPtrField field(values.begin(), values.end()); + RepeatedPtrField field(values.begin(), values.end()); ASSERT_EQ(values.size(), field.size()); EXPECT_EQ(values[0], field.Get(0)); EXPECT_EQ(values[1], field.Get(1)); - RepeatedPtrField other(field.begin(), field.end()); + RepeatedPtrField other(field.begin(), field.end()); ASSERT_EQ(values.size(), other.size()); EXPECT_EQ(values[0], other.Get(0)); EXPECT_EQ(values[1], other.Get(1)); @@ -895,7 +1236,7 @@ TEST(RepeatedPtrField, IteratorConstruct_Proto) { } TEST(RepeatedPtrField, CopyAssign) { - RepeatedPtrField source, destination; + RepeatedPtrField source, destination; source.Add()->assign("4"); source.Add()->assign("5"); destination.Add()->assign("1"); @@ -911,7 +1252,7 @@ TEST(RepeatedPtrField, CopyAssign) { TEST(RepeatedPtrField, SelfAssign) { // Verify that assignment to self does not destroy data. - RepeatedPtrField source, *p; + RepeatedPtrField source, *p; p = &source; source.Add()->assign("7"); source.Add()->assign("8"); @@ -923,24 +1264,156 @@ TEST(RepeatedPtrField, SelfAssign) { EXPECT_EQ("8", source.Get(1)); } +TEST(RepeatedPtrField, MoveConstruct) { + { + RepeatedPtrField source; + *source.Add() = "1"; + *source.Add() = "2"; + const std::string* const* data = source.data(); + RepeatedPtrField destination = std::move(source); + EXPECT_EQ(data, destination.data()); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_TRUE(source.empty()); + } + { + Arena arena; + RepeatedPtrField* source = + Arena::CreateMessage>(&arena); + *source->Add() = "1"; + *source->Add() = "2"; + RepeatedPtrField destination = std::move(*source); + EXPECT_EQ(nullptr, destination.GetArena()); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre("1", "2")); + } +} + +TEST(RepeatedPtrField, MoveAssign) { + { + RepeatedPtrField source; + *source.Add() = "1"; + *source.Add() = "2"; + RepeatedPtrField destination; + *destination.Add() = "3"; + const std::string* const* source_data = source.data(); + const std::string* const* destination_data = destination.data(); + destination = std::move(source); + EXPECT_EQ(source_data, destination.data()); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_EQ(destination_data, source.data()); + EXPECT_THAT(source, ElementsAre("3")); + } + { + Arena arena; + RepeatedPtrField* source = + Arena::CreateMessage>(&arena); + *source->Add() = "1"; + *source->Add() = "2"; + RepeatedPtrField* destination = + Arena::CreateMessage>(&arena); + *destination->Add() = "3"; + const std::string* const* source_data = source->data(); + const std::string* const* destination_data = destination->data(); + *destination = std::move(*source); + EXPECT_EQ(source_data, destination->data()); + EXPECT_THAT(*destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_EQ(destination_data, source->data()); + EXPECT_THAT(*source, ElementsAre("3")); + } + { + Arena source_arena; + RepeatedPtrField* source = + Arena::CreateMessage>(&source_arena); + *source->Add() = "1"; + *source->Add() = "2"; + Arena destination_arena; + RepeatedPtrField* destination = + Arena::CreateMessage>(&destination_arena); + *destination->Add() = "3"; + *destination = std::move(*source); + EXPECT_THAT(*destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre("1", "2")); + } + { + Arena arena; + RepeatedPtrField* source = + Arena::CreateMessage>(&arena); + *source->Add() = "1"; + *source->Add() = "2"; + RepeatedPtrField destination; + *destination.Add() = "3"; + destination = std::move(*source); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre("1", "2")); + } + { + RepeatedPtrField source; + *source.Add() = "1"; + *source.Add() = "2"; + Arena arena; + RepeatedPtrField* destination = + Arena::CreateMessage>(&arena); + *destination->Add() = "3"; + *destination = std::move(source); + EXPECT_THAT(*destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(source, ElementsAre("1", "2")); + } + { + RepeatedPtrField field; + // An alias to defeat -Wself-move. + RepeatedPtrField& alias = field; + *field.Add() = "1"; + *field.Add() = "2"; + const std::string* const* data = field.data(); + field = std::move(alias); + EXPECT_EQ(data, field.data()); + EXPECT_THAT(field, ElementsAre("1", "2")); + } + { + Arena arena; + RepeatedPtrField* field = + Arena::CreateMessage>(&arena); + *field->Add() = "1"; + *field->Add() = "2"; + const std::string* const* data = field->data(); + *field = std::move(*field); + EXPECT_EQ(data, field->data()); + EXPECT_THAT(*field, ElementsAre("1", "2")); + } +} + TEST(RepeatedPtrField, MutableDataIsMutable) { - RepeatedPtrField field; + RepeatedPtrField field; *field.Add() = "1"; EXPECT_EQ("1", field.Get(0)); // The fact that this line compiles would be enough, but we'll check the // value anyway. - string** data = field.mutable_data(); + std::string** data = field.mutable_data(); **data = "2"; EXPECT_EQ("2", field.Get(0)); } TEST(RepeatedPtrField, SubscriptOperators) { - RepeatedPtrField field; + RepeatedPtrField field; *field.Add() = "1"; EXPECT_EQ("1", field.Get(0)); EXPECT_EQ("1", field[0]); EXPECT_EQ(field.Mutable(0), &field[0]); - const RepeatedPtrField& const_field = field; + const RepeatedPtrField& const_field = field; EXPECT_EQ(*field.data(), &const_field[0]); } @@ -951,24 +1424,22 @@ TEST(RepeatedPtrField, ExtractSubrange) { for (int num = 0; num <= sz; ++num) { for (int start = 0; start < sz - num; ++start) { for (int extra = 0; extra < 4; ++extra) { - std::vector subject; + std::vector subject; // Create an array with "sz" elements and "extra" cleared elements. - RepeatedPtrField field; + RepeatedPtrField field; for (int i = 0; i < sz + extra; ++i) { - subject.push_back(new string()); + subject.push_back(new std::string()); field.AddAllocated(subject[i]); } EXPECT_EQ(field.size(), sz + extra); - for (int i = 0; i < extra; ++i) - field.RemoveLast(); + for (int i = 0; i < extra; ++i) field.RemoveLast(); EXPECT_EQ(field.size(), sz); EXPECT_EQ(field.ClearedCount(), extra); // Create a catcher array and call ExtractSubrange. - string* catcher[10]; - for (int i = 0; i < 10; ++i) - catcher[i] = NULL; + std::string* catcher[10]; + for (int i = 0; i < 10; ++i) catcher[i] = NULL; field.ExtractSubrange(start, num, catcher); // Does the resulting array have the right size? @@ -987,8 +1458,7 @@ TEST(RepeatedPtrField, ExtractSubrange) { // Reinstate the cleared elements. EXPECT_EQ(field.ClearedCount(), extra); - for (int i = 0; i < extra; ++i) - field.Add(); + for (int i = 0; i < extra; ++i) field.Add(); EXPECT_EQ(field.ClearedCount(), 0); EXPECT_EQ(field.size(), sz - num + extra); @@ -996,15 +1466,13 @@ TEST(RepeatedPtrField, ExtractSubrange) { for (int i = sz; i < sz + extra; ++i) { int count = 0; for (int j = sz; j < sz + extra; ++j) { - if (field.Mutable(j - num) == subject[i]) - count += 1; + if (field.Mutable(j - num) == subject[i]) count += 1; } EXPECT_EQ(count, 1); } // Release the caught elements. - for (int i = 0; i < num; ++i) - delete catcher[i]; + for (int i = 0; i < num; ++i) delete catcher[i]; } } } @@ -1076,18 +1544,18 @@ class RepeatedPtrFieldIteratorTest : public testing::Test { proto_array_.Add()->assign("baz"); } - RepeatedPtrField proto_array_; + RepeatedPtrField proto_array_; }; TEST_F(RepeatedPtrFieldIteratorTest, Convertible) { - RepeatedPtrField::iterator iter = proto_array_.begin(); - RepeatedPtrField::const_iterator c_iter = iter; - RepeatedPtrField::value_type value = *c_iter; + RepeatedPtrField::iterator iter = proto_array_.begin(); + RepeatedPtrField::const_iterator c_iter = iter; + RepeatedPtrField::value_type value = *c_iter; EXPECT_EQ("foo", value); } TEST_F(RepeatedPtrFieldIteratorTest, MutableIteration) { - RepeatedPtrField::iterator iter = proto_array_.begin(); + RepeatedPtrField::iterator iter = proto_array_.begin(); EXPECT_EQ("foo", *iter); ++iter; EXPECT_EQ("bar", *(iter++)); @@ -1098,8 +1566,9 @@ TEST_F(RepeatedPtrFieldIteratorTest, MutableIteration) { } TEST_F(RepeatedPtrFieldIteratorTest, ConstIteration) { - const RepeatedPtrField& const_proto_array = proto_array_; - RepeatedPtrField::const_iterator iter = const_proto_array.begin(); + const RepeatedPtrField& const_proto_array = proto_array_; + RepeatedPtrField::const_iterator iter = + const_proto_array.begin(); EXPECT_EQ("foo", *iter); ++iter; EXPECT_EQ("bar", *(iter++)); @@ -1110,7 +1579,7 @@ TEST_F(RepeatedPtrFieldIteratorTest, ConstIteration) { } TEST_F(RepeatedPtrFieldIteratorTest, MutableReverseIteration) { - RepeatedPtrField::reverse_iterator iter = proto_array_.rbegin(); + RepeatedPtrField::reverse_iterator iter = proto_array_.rbegin(); EXPECT_EQ("baz", *iter); ++iter; EXPECT_EQ("bar", *(iter++)); @@ -1121,9 +1590,9 @@ TEST_F(RepeatedPtrFieldIteratorTest, MutableReverseIteration) { } TEST_F(RepeatedPtrFieldIteratorTest, ConstReverseIteration) { - const RepeatedPtrField& const_proto_array = proto_array_; - RepeatedPtrField::const_reverse_iterator iter - = const_proto_array.rbegin(); + const RepeatedPtrField& const_proto_array = proto_array_; + RepeatedPtrField::const_reverse_iterator iter = + const_proto_array.rbegin(); EXPECT_EQ("baz", *iter); ++iter; EXPECT_EQ("bar", *(iter++)); @@ -1134,8 +1603,8 @@ TEST_F(RepeatedPtrFieldIteratorTest, ConstReverseIteration) { } TEST_F(RepeatedPtrFieldIteratorTest, RandomAccess) { - RepeatedPtrField::iterator iter = proto_array_.begin(); - RepeatedPtrField::iterator iter2 = iter; + RepeatedPtrField::iterator iter = proto_array_.begin(); + RepeatedPtrField::iterator iter2 = iter; ++iter2; ++iter2; EXPECT_TRUE(iter + 2 == iter2); @@ -1146,8 +1615,8 @@ TEST_F(RepeatedPtrFieldIteratorTest, RandomAccess) { } TEST_F(RepeatedPtrFieldIteratorTest, Comparable) { - RepeatedPtrField::const_iterator iter = proto_array_.begin(); - RepeatedPtrField::const_iterator iter2 = iter + 1; + RepeatedPtrField::const_iterator iter = proto_array_.begin(); + RepeatedPtrField::const_iterator iter2 = iter + 1; EXPECT_TRUE(iter == iter); EXPECT_TRUE(iter != iter2); EXPECT_TRUE(iter < iter2); @@ -1160,7 +1629,7 @@ TEST_F(RepeatedPtrFieldIteratorTest, Comparable) { // Uninitialized iterator does not point to any of the RepeatedPtrField. TEST_F(RepeatedPtrFieldIteratorTest, UninitializedIterator) { - RepeatedPtrField::iterator iter; + RepeatedPtrField::iterator iter; EXPECT_TRUE(iter != proto_array_.begin()); EXPECT_TRUE(iter != proto_array_.begin() + 1); EXPECT_TRUE(iter != proto_array_.begin() + 2); @@ -1178,8 +1647,8 @@ TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) { proto_array_.Add()->assign("x"); proto_array_.Add()->assign("y"); - string v = "f"; - RepeatedPtrField::const_iterator it = + std::string v = "f"; + RepeatedPtrField::const_iterator it = std::lower_bound(proto_array_.begin(), proto_array_.end(), v); EXPECT_EQ(*it, "n"); @@ -1187,7 +1656,7 @@ TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) { } TEST_F(RepeatedPtrFieldIteratorTest, Mutation) { - RepeatedPtrField::iterator iter = proto_array_.begin(); + RepeatedPtrField::iterator iter = proto_array_.begin(); *iter = "qux"; EXPECT_EQ("qux", proto_array_.Get(0)); } @@ -1203,24 +1672,24 @@ class RepeatedPtrFieldPtrsIteratorTest : public testing::Test { const_proto_array_ = &proto_array_; } - RepeatedPtrField proto_array_; - const RepeatedPtrField* const_proto_array_; + RepeatedPtrField proto_array_; + const RepeatedPtrField* const_proto_array_; }; TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) { - RepeatedPtrField::pointer_iterator iter = + RepeatedPtrField::pointer_iterator iter = proto_array_.pointer_begin(); static_cast(iter); } TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertibleConstPtr) { - RepeatedPtrField::const_pointer_iterator iter = + RepeatedPtrField::const_pointer_iterator iter = const_proto_array_->pointer_begin(); static_cast(iter); } TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) { - RepeatedPtrField::pointer_iterator iter = + RepeatedPtrField::pointer_iterator iter = proto_array_.pointer_begin(); EXPECT_EQ("foo", **iter); ++iter; @@ -1232,7 +1701,7 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) { } TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutableConstPtrIteration) { - RepeatedPtrField::const_pointer_iterator iter = + RepeatedPtrField::const_pointer_iterator iter = const_proto_array_->pointer_begin(); EXPECT_EQ("foo", **iter); ++iter; @@ -1244,9 +1713,9 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutableConstPtrIteration) { } TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) { - RepeatedPtrField::pointer_iterator iter = + RepeatedPtrField::pointer_iterator iter = proto_array_.pointer_begin(); - RepeatedPtrField::pointer_iterator iter2 = iter; + RepeatedPtrField::pointer_iterator iter2 = iter; ++iter2; ++iter2; EXPECT_TRUE(iter + 2 == iter2); @@ -1257,9 +1726,9 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) { } TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomConstPtrAccess) { - RepeatedPtrField::const_pointer_iterator iter = + RepeatedPtrField::const_pointer_iterator iter = const_proto_array_->pointer_begin(); - RepeatedPtrField::const_pointer_iterator iter2 = iter; + RepeatedPtrField::const_pointer_iterator iter2 = iter; ++iter2; ++iter2; EXPECT_TRUE(iter + 2 == iter2); @@ -1270,9 +1739,9 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomConstPtrAccess) { } TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) { - RepeatedPtrField::pointer_iterator iter = + RepeatedPtrField::pointer_iterator iter = proto_array_.pointer_begin(); - RepeatedPtrField::pointer_iterator iter2 = iter + 1; + RepeatedPtrField::pointer_iterator iter2 = iter + 1; EXPECT_TRUE(iter == iter); EXPECT_TRUE(iter != iter2); EXPECT_TRUE(iter < iter2); @@ -1284,9 +1753,9 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) { } TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparableConstPtr) { - RepeatedPtrField::const_pointer_iterator iter = + RepeatedPtrField::const_pointer_iterator iter = const_proto_array_->pointer_begin(); - RepeatedPtrField::const_pointer_iterator iter2 = iter + 1; + RepeatedPtrField::const_pointer_iterator iter2 = iter + 1; EXPECT_TRUE(iter == iter); EXPECT_TRUE(iter != iter2); EXPECT_TRUE(iter < iter2); @@ -1300,7 +1769,7 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparableConstPtr) { // Uninitialized iterator does not point to any of the RepeatedPtrOverPtrs. // Dereferencing an uninitialized iterator crashes the process. TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) { - RepeatedPtrField::pointer_iterator iter; + RepeatedPtrField::pointer_iterator iter; EXPECT_TRUE(iter != proto_array_.pointer_begin()); EXPECT_TRUE(iter != proto_array_.pointer_begin() + 1); EXPECT_TRUE(iter != proto_array_.pointer_begin() + 2); @@ -1309,7 +1778,7 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) { } TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedConstPtrIterator) { - RepeatedPtrField::const_pointer_iterator iter; + RepeatedPtrField::const_pointer_iterator iter; EXPECT_TRUE(iter != const_proto_array_->pointer_begin()); EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 1); EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 2); @@ -1319,13 +1788,13 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedConstPtrIterator) { // This comparison functor is required by the tests for RepeatedPtrOverPtrs. // They operate on strings and need to compare strings as strings in -// any stl algorithm, even though the iterator returns a pointer to a string -// - i.e. *iter has type string*. +// any stl algorithm, even though the iterator returns a pointer to a +// string +// - i.e. *iter has type std::string*. struct StringLessThan { - bool operator()(const string* z, const string& y) { - return *z < y; + bool operator()(const std::string* z, const std::string* y) const { + return *z < *y; } - bool operator()(const string* z, const string* y) const { return *z < *y; } }; TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { @@ -1339,8 +1808,8 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { proto_array_.Add()->assign("y"); { - string v = "f"; - RepeatedPtrField::pointer_iterator it = + std::string v = "f"; + RepeatedPtrField::pointer_iterator it = std::lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(), &v, StringLessThan()); @@ -1350,8 +1819,8 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { EXPECT_TRUE(it == proto_array_.pointer_begin() + 3); } { - string v = "f"; - RepeatedPtrField::const_pointer_iterator it = std::lower_bound( + std::string v = "f"; + RepeatedPtrField::const_pointer_iterator it = std::lower_bound( const_proto_array_->pointer_begin(), const_proto_array_->pointer_end(), &v, StringLessThan()); @@ -1363,7 +1832,7 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { } TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrMutation) { - RepeatedPtrField::pointer_iterator iter = + RepeatedPtrField::pointer_iterator iter = proto_array_.pointer_begin(); **iter = "qux"; EXPECT_EQ("qux", proto_array_.Get(0)); @@ -1372,10 +1841,10 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrMutation) { EXPECT_EQ("baz", proto_array_.Get(2)); ++iter; delete *iter; - *iter = new string("a"); + *iter = new std::string("a"); ++iter; delete *iter; - *iter = new string("b"); + *iter = new std::string("b"); EXPECT_EQ("a", proto_array_.Get(1)); EXPECT_EQ("b", proto_array_.Get(2)); } @@ -1398,7 +1867,6 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) { EXPECT_EQ("y", proto_array_.Get(9)); } - // ----------------------------------------------------------------------------- // Unit-tests for the insert iterators // google::protobuf::RepeatedFieldBackInserter, @@ -1409,7 +1877,7 @@ class RepeatedFieldInsertionIteratorsTest : public testing::Test { protected: std::list halves; std::list fibonacci; - std::vector words; + std::vector words; typedef TestAllTypes::NestedMessage Nested; Nested nesteds[2]; std::vector nested_ptrs; @@ -1459,13 +1927,14 @@ class RepeatedFieldInsertionIteratorsTest : public testing::Test { } virtual void TearDown() { - STLDeleteContainerPointers(nested_ptrs.begin(), nested_ptrs.end()); + for (auto ptr : nested_ptrs) { + delete ptr; + } } }; TEST_F(RepeatedFieldInsertionIteratorsTest, Fibonacci) { - EXPECT_TRUE(std::equal(fibonacci.begin(), - fibonacci.end(), + EXPECT_TRUE(std::equal(fibonacci.begin(), fibonacci.end(), protobuffer.repeated_int32().begin())); EXPECT_TRUE(std::equal(protobuffer.repeated_int32().begin(), protobuffer.repeated_int32().end(), @@ -1473,12 +1942,10 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, Fibonacci) { } TEST_F(RepeatedFieldInsertionIteratorsTest, Halves) { - EXPECT_TRUE(std::equal(halves.begin(), - halves.end(), + EXPECT_TRUE(std::equal(halves.begin(), halves.end(), protobuffer.repeated_double().begin())); EXPECT_TRUE(std::equal(protobuffer.repeated_double().begin(), - protobuffer.repeated_double().end(), - halves.begin())); + protobuffer.repeated_double().end(), halves.begin())); } TEST_F(RepeatedFieldInsertionIteratorsTest, Words) { @@ -1496,8 +1963,9 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, Words2) { words.push_back("six"); words.push_back("pence"); protobuffer.mutable_repeated_string()->Clear(); - std::copy(words.begin(), words.end(), RepeatedPtrFieldBackInserter( - protobuffer.mutable_repeated_string())); + std::copy( + words.begin(), words.end(), + RepeatedPtrFieldBackInserter(protobuffer.mutable_repeated_string())); ASSERT_EQ(words.size(), protobuffer.repeated_string_size()); for (int i = 0; i < words.size(); ++i) EXPECT_EQ(words.at(i), protobuffer.repeated_string(i)); @@ -1532,19 +2000,20 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, TEST_F(RepeatedFieldInsertionIteratorsTest, AllocatedRepeatedPtrFieldWithString) { - std::vector data; + std::vector data; TestAllTypes goldenproto; for (int i = 0; i < 10; ++i) { - string* new_data = new string; - *new_data = "name-" + SimpleItoa(i); + std::string* new_data = new std::string; + *new_data = "name-" + StrCat(i); data.push_back(new_data); new_data = goldenproto.add_repeated_string(); - *new_data = "name-" + SimpleItoa(i); + *new_data = "name-" + StrCat(i); } TestAllTypes testproto; - std::copy(data.begin(), data.end(), AllocatedRepeatedPtrFieldBackInserter( - testproto.mutable_repeated_string())); + std::copy(data.begin(), data.end(), + AllocatedRepeatedPtrFieldBackInserter( + testproto.mutable_repeated_string())); EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); } @@ -1569,15 +2038,15 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, TEST_F(RepeatedFieldInsertionIteratorsTest, UnsafeArenaAllocatedRepeatedPtrFieldWithString) { - std::vector data; + std::vector data; TestAllTypes goldenproto; for (int i = 0; i < 10; ++i) { - string* new_data = new string; - *new_data = "name-" + SimpleItoa(i); + std::string* new_data = new std::string; + *new_data = "name-" + StrCat(i); data.push_back(new_data); new_data = goldenproto.add_repeated_string(); - *new_data = "name-" + SimpleItoa(i); + *new_data = "name-" + StrCat(i); } TestAllTypes testproto; std::copy(data.begin(), data.end(), @@ -1586,10 +2055,10 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); } -#if LANG_CXX11 TEST_F(RepeatedFieldInsertionIteratorsTest, MoveStrings) { - std::vector src = {"a", "b", "c", "d"}; - std::vector copy = src; // copy since move leaves in undefined state + std::vector src = {"a", "b", "c", "d"}; + std::vector copy = + src; // copy since move leaves in undefined state TestAllTypes testproto; std::move(copy.begin(), copy.end(), RepeatedFieldBackInserter(testproto.mutable_repeated_string())); @@ -1616,9 +2085,10 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, MoveProtos) { testproto.repeated_nested_message(i).DebugString()); } } -#endif } // namespace } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/service.cc b/src/google/protobuf/service.cc index ffa919daa7e6e..53945684cb9b6 100644 --- a/src/google/protobuf/service.cc +++ b/src/google/protobuf/service.cc @@ -42,5 +42,4 @@ RpcChannel::~RpcChannel() {} RpcController::~RpcController() {} } // namespace protobuf - } // namespace google diff --git a/src/google/protobuf/service.h b/src/google/protobuf/service.h index ad6f968548fe6..b18a80392bdc5 100644 --- a/src/google/protobuf/service.h +++ b/src/google/protobuf/service.h @@ -33,7 +33,7 @@ // Sanjay Ghemawat, Jeff Dean, and others. // // DEPRECATED: This module declares the abstract interfaces underlying proto2 -// RPC services. These are intented to be independent of any particular RPC +// RPC services. These are intended to be independent of any particular RPC // implementation, so that proto2 services can be used on top of a variety // of implementations. Starting with version 2.3.0, RPC implementations should // not try to build on these, but should instead provide code generator plugins @@ -101,8 +101,14 @@ #define GOOGLE_PROTOBUF_SERVICE_H__ #include -#include #include +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +#include namespace google { namespace protobuf { @@ -113,17 +119,17 @@ class RpcController; class RpcChannel; // Defined in other files. -class Descriptor; // descriptor.h -class ServiceDescriptor; // descriptor.h -class MethodDescriptor; // descriptor.h -class Message; // message.h +class Descriptor; // descriptor.h +class ServiceDescriptor; // descriptor.h +class MethodDescriptor; // descriptor.h +class Message; // message.h // Abstract base interface for protocol-buffer-based RPC services. Services // themselves are abstract interfaces (implemented either by servers or as // stubs), but they subclass this base interface. The methods of this // interface can be used to call the methods of the Service without knowing // its exact type at compile time (analogous to Reflection). -class LIBPROTOBUF_EXPORT Service { +class PROTOBUF_EXPORT Service { public: inline Service() {} virtual ~Service(); @@ -131,10 +137,7 @@ class LIBPROTOBUF_EXPORT Service { // When constructing a stub, you may pass STUB_OWNS_CHANNEL as the second // parameter to the constructor to tell it to delete its RpcChannel when // destroyed. - enum ChannelOwnership { - STUB_OWNS_CHANNEL, - STUB_DOESNT_OWN_CHANNEL - }; + enum ChannelOwnership { STUB_OWNS_CHANNEL, STUB_DOESNT_OWN_CHANNEL }; // Get the ServiceDescriptor describing this service and its methods. virtual const ServiceDescriptor* GetDescriptor() = 0; @@ -165,10 +168,8 @@ class LIBPROTOBUF_EXPORT Service { // RpcController can be queried to determine if an error occurred and // possibly to get more information about the error. virtual void CallMethod(const MethodDescriptor* method, - RpcController* controller, - const Message* request, - Message* response, - Closure* done) = 0; + RpcController* controller, const Message* request, + Message* response, Closure* done) = 0; // CallMethod() requires that the request and response passed in are of a // particular subclass of Message. GetRequestPrototype() and @@ -184,9 +185,9 @@ class LIBPROTOBUF_EXPORT Service { // request->ParseFromString(input); // service->CallMethod(method, *request, response, callback); virtual const Message& GetRequestPrototype( - const MethodDescriptor* method) const = 0; + const MethodDescriptor* method) const = 0; virtual const Message& GetResponsePrototype( - const MethodDescriptor* method) const = 0; + const MethodDescriptor* method) const = 0; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Service); @@ -200,7 +201,7 @@ class LIBPROTOBUF_EXPORT Service { // "least common denominator" set of features which we expect all // implementations to support. Specific implementations may provide more // advanced features (e.g. deadline propagation). -class LIBPROTOBUF_EXPORT RpcController { +class PROTOBUF_EXPORT RpcController { public: inline RpcController() {} virtual ~RpcController(); @@ -220,7 +221,7 @@ class LIBPROTOBUF_EXPORT RpcController { virtual bool Failed() const = 0; // If Failed() is true, returns a human-readable description of the error. - virtual string ErrorText() const = 0; + virtual std::string ErrorText() const = 0; // Advises the RPC system that the caller desires that the RPC call be // canceled. The RPC system may cancel it immediately, may wait awhile and @@ -238,7 +239,7 @@ class LIBPROTOBUF_EXPORT RpcController { // you need to return machine-readable information about failures, you // should incorporate it into your response protocol buffer and should // NOT call SetFailed(). - virtual void SetFailed(const string& reason) = 0; + virtual void SetFailed(const std::string& reason) = 0; // If true, indicates that the client canceled the RPC, so the server may // as well give up on replying to it. The server should still call the @@ -266,7 +267,7 @@ class LIBPROTOBUF_EXPORT RpcController { // RpcChannel* channel = new MyRpcChannel("remotehost.example.com:1234"); // MyService* service = new MyService::Stub(channel); // service->MyMethod(request, &response, callback); -class LIBPROTOBUF_EXPORT RpcChannel { +class PROTOBUF_EXPORT RpcChannel { public: inline RpcChannel() {} virtual ~RpcChannel(); @@ -277,16 +278,16 @@ class LIBPROTOBUF_EXPORT RpcChannel { // need not be of any specific class as long as their descriptors are // method->input_type() and method->output_type(). virtual void CallMethod(const MethodDescriptor* method, - RpcController* controller, - const Message* request, - Message* response, - Closure* done) = 0; + RpcController* controller, const Message* request, + Message* response, Closure* done) = 0; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcChannel); }; } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_SERVICE_H__ diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc index a69739c493a1d..641862ef39fc6 100644 --- a/src/google/protobuf/source_context.pb.cc +++ b/src/google/protobuf/source_context.pb.cc @@ -1,299 +1,195 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/source_context.proto -#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include #include -#include -#include -#include #include -#include +#include +#include #include #include #include #include // @@protoc_insertion_point(includes) - -namespace google { -namespace protobuf { -class SourceContextDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _SourceContext_default_instance_; - -namespace protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto { - - -namespace { - -::google::protobuf::Metadata file_level_metadata[1]; - -} // namespace - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField - const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0}, -}; - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField - const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - ::google::protobuf::internal::AuxillaryParseTableField(), -}; -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const - TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, +#include + +PROTOBUF_PRAGMA_INIT_SEG +PROTOBUF_NAMESPACE_OPEN +constexpr SourceContext::SourceContext( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : file_name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){} +struct SourceContextDefaultTypeInternal { + constexpr SourceContextDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~SourceContextDefaultTypeInternal() {} + union { + SourceContext _instance; + }; }; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT SourceContextDefaultTypeInternal _SourceContext_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto[1]; +static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto = nullptr; -const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { +const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { ~0u, // no _has_bits_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceContext, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceContext, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceContext, file_name_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceContext, file_name_), }; -static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { 0, -1, sizeof(SourceContext)}, +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, sizeof(PROTOBUF_NAMESPACE_ID::SourceContext)}, }; -static ::google::protobuf::Message const * const file_default_instances[] = { - reinterpret_cast(&_SourceContext_default_instance_), +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_), }; -namespace { - -void protobuf_AssignDescriptors() { - AddDescriptors(); - ::google::protobuf::MessageFactory* factory = NULL; - AssignDescriptors( - "google/protobuf/source_context.proto", schemas, file_default_instances, TableStruct::offsets, factory, - file_level_metadata, NULL, NULL); -} - -void protobuf_AssignDescriptorsOnce() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors); -} - -void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; -void protobuf_RegisterTypes(const ::std::string&) { - protobuf_AssignDescriptorsOnce(); - ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1); -} - -} // namespace -void TableStruct::InitDefaultsImpl() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - ::google::protobuf::internal::InitProtobufDefaults(); - _SourceContext_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_SourceContext_default_instance_);} - -void InitDefaults() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl); -} -namespace { -void AddDescriptorsImpl() { - InitDefaults(); - static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - "\n$google/protobuf/source_context.proto\022\017" - "google.protobuf\"\"\n\rSourceContext\022\021\n\tfile" - "_name\030\001 \001(\tB\225\001\n\023com.google.protobufB\022Sou" - "rceContextProtoP\001ZAgoogle.golang.org/gen" - "proto/protobuf/source_context;source_con" - "text\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTy" - "pesb\006proto3" - }; - ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( - descriptor, 251); - ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( - "google/protobuf/source_context.proto", &protobuf_RegisterTypes); -} -} // anonymous namespace - -void AddDescriptors() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl); +const char descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n$google/protobuf/source_context.proto\022\017" + "google.protobuf\"\"\n\rSourceContext\022\021\n\tfile" + "_name\030\001 \001(\tB\212\001\n\023com.google.protobufB\022Sou" + "rceContextProtoP\001Z6google.golang.org/pro" + "tobuf/types/known/sourcecontextpb\242\002\003GPB\252" + "\002\036Google.Protobuf.WellKnownTypesb\006proto3" + ; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto = { + false, false, 240, descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto, "google/protobuf/source_context.proto", + &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once, nullptr, 0, 1, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto, file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata +descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_metadata_getter(int index) { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto); + return descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto.file_level_metadata[index]; } -// Force AddDescriptors() to be called at dynamic initialization time. -struct StaticDescriptorInitializer { - StaticDescriptorInitializer() { - AddDescriptors(); - } -} static_descriptor_initializer; - -} // namespace protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fsource_5fcontext_2eproto(&descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto); +PROTOBUF_NAMESPACE_OPEN // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int SourceContext::kFileNameFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +class SourceContext::_Internal { + public: +}; -SourceContext::SourceContext() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::InitDefaults(); - } +SourceContext::SourceContext(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.SourceContext) + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.SourceContext) } SourceContext::SourceContext(const SourceContext& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); - file_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (from.file_name().size() > 0) { - file_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.file_name_); + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_file_name().empty()) { + file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_file_name(), + GetArena()); } // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceContext) } void SourceContext::SharedCtor() { - file_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - _cached_size_ = 0; +file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } SourceContext::~SourceContext() { // @@protoc_insertion_point(destructor:google.protobuf.SourceContext) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void SourceContext::SharedDtor() { - file_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + GOOGLE_DCHECK(GetArena() == nullptr); + file_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } -void SourceContext::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +void SourceContext::ArenaDtor(void* object) { + SourceContext* _this = reinterpret_cast< SourceContext* >(object); + (void)_this; } -const ::google::protobuf::Descriptor* SourceContext::descriptor() { - protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const SourceContext& SourceContext::default_instance() { - protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::InitDefaults(); - return *internal_default_instance(); +void SourceContext::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } - -SourceContext* SourceContext::New(::google::protobuf::Arena* arena) const { - SourceContext* n = new SourceContext; - if (arena != NULL) { - arena->Own(n); - } - return n; +void SourceContext::SetCachedSize(int size) const { + _cached_size_.Set(size); } void SourceContext::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceContext) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - _internal_metadata_.Clear(); + file_name_.ClearToEmpty(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } -bool SourceContext::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.SourceContext) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { +const char* SourceContext::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { // string file_name = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_file_name())); - DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->file_name().data(), static_cast(this->file_name().length()), - ::google::protobuf::internal::WireFormatLite::PARSE, - "google.protobuf.SourceContext.file_name")); - } else { - goto handle_unusual; - } - break; - } - + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_file_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.SourceContext.file_name")); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.SourceContext) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.SourceContext) - return false; -#undef DO_ -} - -void SourceContext::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.SourceContext) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // string file_name = 1; - if (this->file_name().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->file_name().data(), static_cast(this->file_name().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, - "google.protobuf.SourceContext.file_name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 1, this->file_name(), output); - } - - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.SourceContext) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* SourceContext::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* SourceContext::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceContext) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // string file_name = 1; if (this->file_name().size() > 0) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->file_name().data(), static_cast(this->file_name().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_file_name().data(), static_cast(this->_internal_file_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "google.protobuf.SourceContext.file_name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 1, this->file_name(), target); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_file_name(), target); } - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceContext) return target; @@ -303,34 +199,35 @@ size_t SourceContext::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceContext) size_t total_size = 0; - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // string file_name = 1; if (this->file_name().size() > 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->file_name()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_file_name()); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void SourceContext::MergeFrom(const ::google::protobuf::Message& from) { +void SourceContext::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceContext) GOOGLE_DCHECK_NE(&from, this); const SourceContext* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceContext) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceContext) MergeFrom(*source); @@ -340,17 +237,16 @@ void SourceContext::MergeFrom(const ::google::protobuf::Message& from) { void SourceContext::MergeFrom(const SourceContext& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceContext) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; if (from.file_name().size() > 0) { - - file_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.file_name_); + _internal_set_file_name(from._internal_file_name()); } } -void SourceContext::CopyFrom(const ::google::protobuf::Message& from) { +void SourceContext::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceContext) if (&from == this) return; Clear(); @@ -368,83 +264,24 @@ bool SourceContext::IsInitialized() const { return true; } -void SourceContext::Swap(SourceContext* other) { - if (other == this) return; - InternalSwap(other); -} void SourceContext::InternalSwap(SourceContext* other) { using std::swap; - file_name_.Swap(&other->file_name_); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata SourceContext::GetMetadata() const { - protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::file_level_metadata[kIndexInFileMessages]; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + file_name_.Swap(&other->file_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// SourceContext - -// string file_name = 1; -void SourceContext::clear_file_name() { - file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -const ::std::string& SourceContext::file_name() const { - // @@protoc_insertion_point(field_get:google.protobuf.SourceContext.file_name) - return file_name_.GetNoArena(); -} -void SourceContext::set_file_name(const ::std::string& value) { - - file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.SourceContext.file_name) -} -#if LANG_CXX11 -void SourceContext::set_file_name(::std::string&& value) { - - file_name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceContext.file_name) -} -#endif -void SourceContext::set_file_name(const char* value) { - GOOGLE_DCHECK(value != NULL); - - file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.SourceContext.file_name) -} -void SourceContext::set_file_name(const char* value, size_t size) { - - file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceContext.file_name) -} -::std::string* SourceContext::mutable_file_name() { - - // @@protoc_insertion_point(field_mutable:google.protobuf.SourceContext.file_name) - return file_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -::std::string* SourceContext::release_file_name() { - // @@protoc_insertion_point(field_release:google.protobuf.SourceContext.file_name) - - return file_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -void SourceContext::set_allocated_file_name(::std::string* file_name) { - if (file_name != NULL) { - - } else { - - } - file_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), file_name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceContext.file_name) +::PROTOBUF_NAMESPACE_ID::Metadata SourceContext::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::SourceContext* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::SourceContext >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::SourceContext >(arena); +} +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) +#include diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h index b4617c5776038..a5e9db67a980e 100644 --- a/src/google/protobuf/source_context.pb.h +++ b/src/google/protobuf/source_context.pb.h @@ -1,172 +1,218 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/source_context.proto -#ifndef PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto__INCLUDED -#define PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto__INCLUDED +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto +#include #include -#include - -#if GOOGLE_PROTOBUF_VERSION < 3004000 +#include +#if PROTOBUF_VERSION < 3015000 #error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update +#error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 3015000 < PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please +#error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif +#include #include #include #include #include #include -#include +#include +#include #include #include // IWYU pragma: export #include // IWYU pragma: export #include // @@protoc_insertion_point(includes) -namespace google { -namespace protobuf { -class SourceContext; -class SourceContextDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern SourceContextDefaultTypeInternal _SourceContext_default_instance_; -} // namespace protobuf -} // namespace google - -namespace google { -namespace protobuf { - -namespace protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto { -// Internal implementation detail -- do not call these. -struct LIBPROTOBUF_EXPORT TableStruct { - static const ::google::protobuf::internal::ParseTableField entries[]; - static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; - static const ::google::protobuf::internal::ParseTable schema[]; - static const ::google::protobuf::uint32 offsets[]; - static const ::google::protobuf::internal::FieldMetadata field_metadata[]; - static const ::google::protobuf::internal::SerializationTable serialization_table[]; - static void InitDefaultsImpl(); +#include +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fsource_5fcontext_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; }; -void LIBPROTOBUF_EXPORT AddDescriptors(); -void LIBPROTOBUF_EXPORT InitDefaults(); -} // namespace protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto +extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto; +PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_metadata_getter(int index); +PROTOBUF_NAMESPACE_OPEN +class SourceContext; +struct SourceContextDefaultTypeInternal; +PROTOBUF_EXPORT extern SourceContextDefaultTypeInternal _SourceContext_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::SourceContext* Arena::CreateMaybeMessage(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN // =================================================================== -class LIBPROTOBUF_EXPORT SourceContext : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceContext) */ { +class PROTOBUF_EXPORT SourceContext PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceContext) */ { public: - SourceContext(); + inline SourceContext() : SourceContext(nullptr) {} virtual ~SourceContext(); + explicit constexpr SourceContext(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); SourceContext(const SourceContext& from); - - inline SourceContext& operator=(const SourceContext& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 SourceContext(SourceContext&& from) noexcept : SourceContext() { *this = ::std::move(from); } + inline SourceContext& operator=(const SourceContext& from) { + CopyFrom(from); + return *this; + } inline SourceContext& operator=(SourceContext&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - static const ::google::protobuf::Descriptor* descriptor(); - static const SourceContext& default_instance(); + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const SourceContext& default_instance() { + return *internal_default_instance(); + } static inline const SourceContext* internal_default_instance() { return reinterpret_cast( &_SourceContext_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 0; - void Swap(SourceContext* other); friend void swap(SourceContext& a, SourceContext& b) { a.Swap(&b); } + inline void Swap(SourceContext* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SourceContext* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline SourceContext* New() const PROTOBUF_FINAL { return New(NULL); } + inline SourceContext* New() const final { + return CreateMaybeMessage(nullptr); + } - SourceContext* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + SourceContext* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const SourceContext& from); void MergeFrom(const SourceContext& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(SourceContext* other); - private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return NULL; - } - inline void* MaybeArenaPtr() const { - return NULL; + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.SourceContext"; } + protected: + explicit SourceContext(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_metadata_getter(kIndexInFileMessages); + } + + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kFileNameFieldNumber = 1, + }; // string file_name = 1; void clear_file_name(); - static const int kFileNameFieldNumber = 1; - const ::std::string& file_name() const; - void set_file_name(const ::std::string& value); - #if LANG_CXX11 - void set_file_name(::std::string&& value); - #endif + const std::string& file_name() const; + void set_file_name(const std::string& value); + void set_file_name(std::string&& value); void set_file_name(const char* value); void set_file_name(const char* value, size_t size); - ::std::string* mutable_file_name(); - ::std::string* release_file_name(); - void set_allocated_file_name(::std::string* file_name); + std::string* mutable_file_name(); + std::string* release_file_name(); + void set_allocated_file_name(std::string* file_name); + private: + const std::string& _internal_file_name() const; + void _internal_set_file_name(const std::string& value); + std::string* _internal_mutable_file_name(); + public: // @@protoc_insertion_point(class_scope:google.protobuf.SourceContext) private: - - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - ::google::protobuf::internal::ArenaStringPtr file_name_; - mutable int _cached_size_; - friend struct protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::TableStruct; + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr file_name_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto; }; // =================================================================== // =================================================================== -#if !PROTOBUF_INLINE_NOT_IN_HEADERS #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" @@ -175,68 +221,74 @@ class LIBPROTOBUF_EXPORT SourceContext : public ::google::protobuf::Message /* @ // string file_name = 1; inline void SourceContext::clear_file_name() { - file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + file_name_.ClearToEmpty(); } -inline const ::std::string& SourceContext::file_name() const { +inline const std::string& SourceContext::file_name() const { // @@protoc_insertion_point(field_get:google.protobuf.SourceContext.file_name) - return file_name_.GetNoArena(); + return _internal_file_name(); } -inline void SourceContext::set_file_name(const ::std::string& value) { - - file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); +inline void SourceContext::set_file_name(const std::string& value) { + _internal_set_file_name(value); // @@protoc_insertion_point(field_set:google.protobuf.SourceContext.file_name) } -#if LANG_CXX11 -inline void SourceContext::set_file_name(::std::string&& value) { +inline std::string* SourceContext::mutable_file_name() { + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceContext.file_name) + return _internal_mutable_file_name(); +} +inline const std::string& SourceContext::_internal_file_name() const { + return file_name_.Get(); +} +inline void SourceContext::_internal_set_file_name(const std::string& value) { - file_name_.SetNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); +} +inline void SourceContext::set_file_name(std::string&& value) { + + file_name_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceContext.file_name) } -#endif inline void SourceContext::set_file_name(const char* value) { - GOOGLE_DCHECK(value != NULL); + GOOGLE_DCHECK(value != nullptr); - file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.SourceContext.file_name) } -inline void SourceContext::set_file_name(const char* value, size_t size) { +inline void SourceContext::set_file_name(const char* value, + size_t size) { - file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); + file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( + reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceContext.file_name) } -inline ::std::string* SourceContext::mutable_file_name() { +inline std::string* SourceContext::_internal_mutable_file_name() { - // @@protoc_insertion_point(field_mutable:google.protobuf.SourceContext.file_name) - return file_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return file_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* SourceContext::release_file_name() { +inline std::string* SourceContext::release_file_name() { // @@protoc_insertion_point(field_release:google.protobuf.SourceContext.file_name) - - return file_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return file_name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } -inline void SourceContext::set_allocated_file_name(::std::string* file_name) { - if (file_name != NULL) { +inline void SourceContext::set_allocated_file_name(std::string* file_name) { + if (file_name != nullptr) { } else { } - file_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), file_name); + file_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), file_name, + GetArena()); // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceContext.file_name) } #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ -#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) -#endif // PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto__INCLUDED +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto diff --git a/src/google/protobuf/source_context.proto b/src/google/protobuf/source_context.proto index f3b2c966811f3..06bfc43a78ec8 100644 --- a/src/google/protobuf/source_context.proto +++ b/src/google/protobuf/source_context.proto @@ -37,7 +37,7 @@ option java_package = "com.google.protobuf"; option java_outer_classname = "SourceContextProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; -option go_package = "google.golang.org/genproto/protobuf/source_context;source_context"; +option go_package = "google.golang.org/protobuf/types/known/sourcecontextpb"; // `SourceContext` represents information about the source of a // protobuf element, like the file in which it is defined. diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc index 02d9306ed3713..61e9f80190e65 100644 --- a/src/google/protobuf/struct.pb.cc +++ b/src/google/protobuf/struct.pb.cc @@ -1,214 +1,160 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/struct.proto -#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include #include -#include -#include -#include #include -#include +#include +#include #include #include #include #include // @@protoc_insertion_point(includes) - -namespace google { -namespace protobuf { -class Struct_FieldsEntryDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _Struct_FieldsEntry_default_instance_; -class StructDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _Struct_default_instance_; -class ValueDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; - int null_value_; - double number_value_; - ::google::protobuf::internal::ArenaStringPtr string_value_; - bool bool_value_; - const ::google::protobuf::Struct* struct_value_; - const ::google::protobuf::ListValue* list_value_; -} _Value_default_instance_; -class ListValueDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _ListValue_default_instance_; - -namespace protobuf_google_2fprotobuf_2fstruct_2eproto { - - -namespace { - -::google::protobuf::Metadata file_level_metadata[4]; -const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors[1]; - -} // namespace - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField - const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0}, +#include + +PROTOBUF_PRAGMA_INIT_SEG +PROTOBUF_NAMESPACE_OPEN +constexpr Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized){} +struct Struct_FieldsEntry_DoNotUseDefaultTypeInternal { + constexpr Struct_FieldsEntry_DoNotUseDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~Struct_FieldsEntry_DoNotUseDefaultTypeInternal() {} + union { + Struct_FieldsEntry_DoNotUse _instance; + }; }; - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField - const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - ::google::protobuf::internal::AuxillaryParseTableField(), +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT Struct_FieldsEntry_DoNotUseDefaultTypeInternal _Struct_FieldsEntry_DoNotUse_default_instance_; +constexpr Struct::Struct( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : fields_(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}){} +struct StructDefaultTypeInternal { + constexpr StructDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~StructDefaultTypeInternal() {} + union { + Struct _instance; + }; }; -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const - TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT StructDefaultTypeInternal _Struct_default_instance_; +constexpr Value::Value( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : _oneof_case_{}{} +struct ValueDefaultTypeInternal { + constexpr ValueDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~ValueDefaultTypeInternal() {} + union { + Value _instance; + }; }; - -const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT ValueDefaultTypeInternal _Value_default_instance_; +constexpr ListValue::ListValue( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : values_(){} +struct ListValueDefaultTypeInternal { + constexpr ListValueDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~ListValueDefaultTypeInternal() {} + union { + ListValue _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT ListValueDefaultTypeInternal _ListValue_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fstruct_2eproto[4]; +static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto[1]; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto = nullptr; + +const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fstruct_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, _has_bits_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, key_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, value_), + 0, + 1, ~0u, // no _has_bits_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Struct, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Struct, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Struct, fields_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Struct, fields_), ~0u, // no _has_bits_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Value, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Value, _internal_metadata_), ~0u, // no _extensions_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Value, _oneof_case_[0]), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Value, _oneof_case_[0]), ~0u, // no _weak_field_map_ - offsetof(ValueDefaultTypeInternal, null_value_), - offsetof(ValueDefaultTypeInternal, number_value_), - offsetof(ValueDefaultTypeInternal, string_value_), - offsetof(ValueDefaultTypeInternal, bool_value_), - offsetof(ValueDefaultTypeInternal, struct_value_), - offsetof(ValueDefaultTypeInternal, list_value_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Value, kind_), + ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag, + ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag, + ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag, + ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag, + ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag, + ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag, + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Value, kind_), ~0u, // no _has_bits_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ListValue, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ListValue, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ListValue, values_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ListValue, values_), }; -static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { 0, -1, sizeof(Struct)}, - { 6, -1, sizeof(Value)}, - { 18, -1, sizeof(ListValue)}, +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, 7, sizeof(PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse)}, + { 9, -1, sizeof(PROTOBUF_NAMESPACE_ID::Struct)}, + { 15, -1, sizeof(PROTOBUF_NAMESPACE_ID::Value)}, + { 27, -1, sizeof(PROTOBUF_NAMESPACE_ID::ListValue)}, }; -static ::google::protobuf::Message const * const file_default_instances[] = { - reinterpret_cast(&_Struct_FieldsEntry_default_instance_), - reinterpret_cast(&_Struct_default_instance_), - reinterpret_cast(&_Value_default_instance_), - reinterpret_cast(&_ListValue_default_instance_), +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_Struct_FieldsEntry_DoNotUse_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_Struct_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_Value_default_instance_), + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_ListValue_default_instance_), }; -namespace { - -void protobuf_AssignDescriptors() { - AddDescriptors(); - ::google::protobuf::MessageFactory* factory = NULL; - AssignDescriptors( - "google/protobuf/struct.proto", schemas, file_default_instances, TableStruct::offsets, factory, - file_level_metadata, file_level_enum_descriptors, NULL); -file_level_metadata[0].reflection = Struct::Struct_FieldsEntry::CreateReflection(file_level_metadata[0].descriptor, _Struct_FieldsEntry_default_instance_._instance.get_mutable()); -} - -void protobuf_AssignDescriptorsOnce() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors); -} - -void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; -void protobuf_RegisterTypes(const ::std::string&) { - protobuf_AssignDescriptorsOnce(); - ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 4); -} - -} // namespace -void TableStruct::InitDefaultsImpl() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - ::google::protobuf::internal::InitProtobufDefaults(); - _Struct_FieldsEntry_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_Struct_FieldsEntry_default_instance_);_Struct_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_Struct_default_instance_);_Value_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_Value_default_instance_);_ListValue_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_ListValue_default_instance_);_Struct_FieldsEntry_default_instance_._instance.get_mutable()->set_default_instance(_Struct_FieldsEntry_default_instance_._instance.get_mutable()); - _Struct_FieldsEntry_default_instance_._instance.get_mutable()->InitAsDefaultInstance(); - _Value_default_instance_.null_value_ = 0; - _Value_default_instance_.number_value_ = 0; - _Value_default_instance_.string_value_.UnsafeSetDefault( - &::google::protobuf::internal::GetEmptyStringAlreadyInited()); - _Value_default_instance_.bool_value_ = false; - _Value_default_instance_.struct_value_ = const_cast< ::google::protobuf::Struct*>( - ::google::protobuf::Struct::internal_default_instance()); - _Value_default_instance_.list_value_ = const_cast< ::google::protobuf::ListValue*>( - ::google::protobuf::ListValue::internal_default_instance()); -} - -void InitDefaults() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl); -} -namespace { -void AddDescriptorsImpl() { - InitDefaults(); - static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - "\n\034google/protobuf/struct.proto\022\017google.p" - "rotobuf\"\204\001\n\006Struct\0223\n\006fields\030\001 \003(\0132#.goo" - "gle.protobuf.Struct.FieldsEntry\032E\n\013Field" - "sEntry\022\013\n\003key\030\001 \001(\t\022%\n\005value\030\002 \001(\0132\026.goo" - "gle.protobuf.Value:\0028\001\"\352\001\n\005Value\0220\n\nnull" - "_value\030\001 \001(\0162\032.google.protobuf.NullValue" - "H\000\022\026\n\014number_value\030\002 \001(\001H\000\022\026\n\014string_val" - "ue\030\003 \001(\tH\000\022\024\n\nbool_value\030\004 \001(\010H\000\022/\n\014stru" - "ct_value\030\005 \001(\0132\027.google.protobuf.StructH" - "\000\0220\n\nlist_value\030\006 \001(\0132\032.google.protobuf." - "ListValueH\000B\006\n\004kind\"3\n\tListValue\022&\n\006valu" - "es\030\001 \003(\0132\026.google.protobuf.Value*\033\n\tNull" - "Value\022\016\n\nNULL_VALUE\020\000B\201\001\n\023com.google.pro" - "tobufB\013StructProtoP\001Z1github.amrom.workers.dev/golang/" - "protobuf/ptypes/struct;structpb\370\001\001\242\002\003GPB" - "\252\002\036Google.Protobuf.WellKnownTypesb\006proto" - "3" - }; - ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( - descriptor, 641); - ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( - "google/protobuf/struct.proto", &protobuf_RegisterTypes); -} -} // anonymous namespace - -void AddDescriptors() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl); +const char descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\034google/protobuf/struct.proto\022\017google.p" + "rotobuf\"\204\001\n\006Struct\0223\n\006fields\030\001 \003(\0132#.goo" + "gle.protobuf.Struct.FieldsEntry\032E\n\013Field" + "sEntry\022\013\n\003key\030\001 \001(\t\022%\n\005value\030\002 \001(\0132\026.goo" + "gle.protobuf.Value:\0028\001\"\352\001\n\005Value\0220\n\nnull" + "_value\030\001 \001(\0162\032.google.protobuf.NullValue" + "H\000\022\026\n\014number_value\030\002 \001(\001H\000\022\026\n\014string_val" + "ue\030\003 \001(\tH\000\022\024\n\nbool_value\030\004 \001(\010H\000\022/\n\014stru" + "ct_value\030\005 \001(\0132\027.google.protobuf.StructH" + "\000\0220\n\nlist_value\030\006 \001(\0132\032.google.protobuf." + "ListValueH\000B\006\n\004kind\"3\n\tListValue\022&\n\006valu" + "es\030\001 \003(\0132\026.google.protobuf.Value*\033\n\tNull" + "Value\022\016\n\nNULL_VALUE\020\000B\177\n\023com.google.prot" + "obufB\013StructProtoP\001Z/google.golang.org/p" + "rotobuf/types/known/structpb\370\001\001\242\002\003GPB\252\002\036" + "Google.Protobuf.WellKnownTypesb\006proto3" + ; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fstruct_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fstruct_2eproto = { + false, false, 638, descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto, "google/protobuf/struct.proto", + &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once, nullptr, 0, 4, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fstruct_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fstruct_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto, file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata +descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(int index) { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fstruct_2eproto); + return descriptor_table_google_2fprotobuf_2fstruct_2eproto.file_level_metadata[index]; } -// Force AddDescriptors() to be called at dynamic initialization time. -struct StaticDescriptorInitializer { - StaticDescriptorInitializer() { - AddDescriptors(); - } -} static_descriptor_initializer; - -} // namespace protobuf_google_2fprotobuf_2fstruct_2eproto -const ::google::protobuf::EnumDescriptor* NullValue_descriptor() { - protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_enum_descriptors[0]; +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fstruct_2eproto(&descriptor_table_google_2fprotobuf_2fstruct_2eproto); +PROTOBUF_NAMESPACE_OPEN +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* NullValue_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fstruct_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto[0]; } bool NullValue_IsValid(int value) { switch (value) { @@ -222,298 +168,165 @@ bool NullValue_IsValid(int value) { // =================================================================== -Struct::Struct_FieldsEntry::Struct_FieldsEntry() {} -Struct::Struct_FieldsEntry::Struct_FieldsEntry(::google::protobuf::Arena* arena) : SuperType(arena) {} -::google::protobuf::Metadata Struct::Struct_FieldsEntry::GetMetadata() const { - protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_metadata[0]; +Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse() {} +Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : SuperType(arena) {} +void Struct_FieldsEntry_DoNotUse::MergeFrom(const Struct_FieldsEntry_DoNotUse& other) { + MergeFromInternal(other); } -void Struct::Struct_FieldsEntry::MergeFrom( - const ::google::protobuf::Message& other) { - ::google::protobuf::Message::MergeFrom(other); +::PROTOBUF_NAMESPACE_ID::Metadata Struct_FieldsEntry_DoNotUse::GetMetadata() const { + return GetMetadataStatic(); } -void Struct::Struct_FieldsEntry::MergeFrom(const Struct_FieldsEntry& other) { - MergeFromInternal(other); +void Struct_FieldsEntry_DoNotUse::MergeFrom( + const ::PROTOBUF_NAMESPACE_ID::Message& other) { + ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom(other); } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int Struct::kFieldsFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +class Struct::_Internal { + public: +}; -Struct::Struct() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fstruct_2eproto::InitDefaults(); - } - SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.Struct) -} -Struct::Struct(::google::protobuf::Arena* arena) - : ::google::protobuf::Message(), - _internal_metadata_(arena), +Struct::Struct(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), fields_(arena) { - protobuf_google_2fprotobuf_2fstruct_2eproto::InitDefaults(); SharedCtor(); RegisterArenaDtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Struct) } Struct::Struct(const Struct& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); fields_.MergeFrom(from.fields_); // @@protoc_insertion_point(copy_constructor:google.protobuf.Struct) } void Struct::SharedCtor() { - _cached_size_ = 0; } Struct::~Struct() { // @@protoc_insertion_point(destructor:google.protobuf.Struct) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void Struct::SharedDtor() { - ::google::protobuf::Arena* arena = GetArenaNoVirtual(); - GOOGLE_DCHECK(arena == NULL); - if (arena != NULL) { - return; - } - + GOOGLE_DCHECK(GetArena() == nullptr); } void Struct::ArenaDtor(void* object) { Struct* _this = reinterpret_cast< Struct* >(object); (void)_this; } -void Struct::RegisterArenaDtor(::google::protobuf::Arena* arena) { +void Struct::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } void Struct::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* Struct::descriptor() { - protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const Struct& Struct::default_instance() { - protobuf_google_2fprotobuf_2fstruct_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -Struct* Struct::New(::google::protobuf::Arena* arena) const { - return ::google::protobuf::Arena::CreateMessage(arena); + _cached_size_.Set(size); } void Struct::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Struct) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; fields_.Clear(); - _internal_metadata_.Clear(); -} - -bool Struct::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.Struct) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // map fields = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - Struct_FieldsEntry::Parser< ::google::protobuf::internal::MapField< - Struct_FieldsEntry, - ::std::string, ::google::protobuf::Value, - ::google::protobuf::internal::WireFormatLite::TYPE_STRING, - ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE, - 0 >, - ::google::protobuf::Map< ::std::string, ::google::protobuf::Value > > parser(&fields_); - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, &parser)); - DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - parser.key().data(), static_cast(parser.key().length()), - ::google::protobuf::internal::WireFormatLite::PARSE, - "google.protobuf.Struct.FieldsEntry.key")); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* Struct::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // map fields = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(&fields_, ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.Struct) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.Struct) - return false; -#undef DO_ + ptr = nullptr; + goto success; +#undef CHK_ } -void Struct::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.Struct) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // map fields = 1; - if (!this->fields().empty()) { - typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_pointer - ConstPtr; - typedef ConstPtr SortItem; - typedef ::google::protobuf::internal::CompareByDerefFirst Less; - struct Utf8Check { - static void Check(ConstPtr p) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - p->first.data(), static_cast(p->first.length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, - "google.protobuf.Struct.FieldsEntry.key"); - } - }; - - if (output->IsSerializationDeterministic() && - this->fields().size() > 1) { - ::google::protobuf::scoped_array items( - new SortItem[this->fields().size()]); - typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::size_type size_type; - size_type n = 0; - for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator - it = this->fields().begin(); - it != this->fields().end(); ++it, ++n) { - items[static_cast(n)] = SortItem(&*it); - } - ::std::sort(&items[0], &items[static_cast(n)], Less()); - ::google::protobuf::scoped_ptr entry; - for (size_type i = 0; i < n; i++) { - entry.reset(fields_.NewEntryWrapper( - items[static_cast(i)]->first, items[static_cast(i)]->second)); - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 1, *entry, output); - if (entry->GetArena() != NULL) { - entry.release(); - } - Utf8Check::Check(items[static_cast(i)]); - } - } else { - ::google::protobuf::scoped_ptr entry; - for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator - it = this->fields().begin(); - it != this->fields().end(); ++it) { - entry.reset(fields_.NewEntryWrapper( - it->first, it->second)); - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 1, *entry, output); - if (entry->GetArena() != NULL) { - entry.release(); - } - Utf8Check::Check(&*it); - } - } - } - - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.Struct) -} - -::google::protobuf::uint8* Struct::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* Struct::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Struct) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // map fields = 1; - if (!this->fields().empty()) { - typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_pointer + if (!this->_internal_fields().empty()) { + typedef ::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >::const_pointer ConstPtr; typedef ConstPtr SortItem; - typedef ::google::protobuf::internal::CompareByDerefFirst Less; + typedef ::PROTOBUF_NAMESPACE_ID::internal::CompareByDerefFirst Less; struct Utf8Check { static void Check(ConstPtr p) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( p->first.data(), static_cast(p->first.length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "google.protobuf.Struct.FieldsEntry.key"); } }; - if (deterministic && - this->fields().size() > 1) { - ::google::protobuf::scoped_array items( - new SortItem[this->fields().size()]); - typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::size_type size_type; + if (stream->IsSerializationDeterministic() && + this->_internal_fields().size() > 1) { + ::std::unique_ptr items( + new SortItem[this->_internal_fields().size()]); + typedef ::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >::size_type size_type; size_type n = 0; - for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator - it = this->fields().begin(); - it != this->fields().end(); ++it, ++n) { + for (::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >::const_iterator + it = this->_internal_fields().begin(); + it != this->_internal_fields().end(); ++it, ++n) { items[static_cast(n)] = SortItem(&*it); } ::std::sort(&items[0], &items[static_cast(n)], Less()); - ::google::protobuf::scoped_ptr entry; for (size_type i = 0; i < n; i++) { - entry.reset(fields_.NewEntryWrapper( - items[static_cast(i)]->first, items[static_cast(i)]->second)); - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 1, *entry, deterministic, target); -; - if (entry->GetArena() != NULL) { - entry.release(); - } - Utf8Check::Check(items[static_cast(i)]); + target = Struct_FieldsEntry_DoNotUse::Funcs::InternalSerialize(1, items[static_cast(i)]->first, items[static_cast(i)]->second, target, stream); + Utf8Check::Check(&(*items[static_cast(i)])); } } else { - ::google::protobuf::scoped_ptr entry; - for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator - it = this->fields().begin(); - it != this->fields().end(); ++it) { - entry.reset(fields_.NewEntryWrapper( - it->first, it->second)); - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 1, *entry, deterministic, target); -; - if (entry->GetArena() != NULL) { - entry.release(); - } - Utf8Check::Check(&*it); + for (::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >::const_iterator + it = this->_internal_fields().begin(); + it != this->_internal_fields().end(); ++it) { + target = Struct_FieldsEntry_DoNotUse::Funcs::InternalSerialize(1, it->first, it->second, target, stream); + Utf8Check::Check(&(*it)); } } } - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Struct) return target; @@ -523,47 +336,37 @@ size_t Struct::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Struct) size_t total_size = 0; - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // map fields = 1; total_size += 1 * - ::google::protobuf::internal::FromIntSize(this->fields_size()); - { - ::google::protobuf::scoped_ptr entry; - for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator - it = this->fields().begin(); - it != this->fields().end(); ++it) { - if (entry.get() != NULL && entry->GetArena() != NULL) { - entry.release(); - } - entry.reset(fields_.NewEntryWrapper(it->first, it->second)); - total_size += ::google::protobuf::internal::WireFormatLite:: - MessageSizeNoVirtual(*entry); - } - if (entry.get() != NULL && entry->GetArena() != NULL) { - entry.release(); - } + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(this->_internal_fields_size()); + for (::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >::const_iterator + it = this->_internal_fields().begin(); + it != this->_internal_fields().end(); ++it) { + total_size += Struct_FieldsEntry_DoNotUse::Funcs::ByteSizeLong(it->first, it->second); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void Struct::MergeFrom(const ::google::protobuf::Message& from) { +void Struct::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Struct) GOOGLE_DCHECK_NE(&from, this); const Struct* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Struct) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Struct) MergeFrom(*source); @@ -573,14 +376,14 @@ void Struct::MergeFrom(const ::google::protobuf::Message& from) { void Struct::MergeFrom(const Struct& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Struct) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; fields_.MergeFrom(from.fields_); } -void Struct::CopyFrom(const ::google::protobuf::Message& from) { +void Struct::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Struct) if (&from == this) return; Clear(); @@ -598,116 +401,96 @@ bool Struct::IsInitialized() const { return true; } -void Struct::Swap(Struct* other) { - if (other == this) return; - if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { - InternalSwap(other); - } else { - Struct* temp = New(GetArenaNoVirtual()); - temp->MergeFrom(*other); - other->CopyFrom(*this); - InternalSwap(temp); - if (GetArenaNoVirtual() == NULL) { - delete temp; - } - } -} -void Struct::UnsafeArenaSwap(Struct* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); - InternalSwap(other); -} void Struct::InternalSwap(Struct* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); fields_.Swap(&other->fields_); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); } -::google::protobuf::Metadata Struct::GetMetadata() const { - protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_metadata[kIndexInFileMessages]; +::PROTOBUF_NAMESPACE_ID::Metadata Struct::GetMetadata() const { + return GetMetadataStatic(); } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// Struct -// map fields = 1; -int Struct::fields_size() const { - return fields_.size(); -} -void Struct::clear_fields() { - fields_.Clear(); +// =================================================================== + +class Value::_Internal { + public: + static const PROTOBUF_NAMESPACE_ID::Struct& struct_value(const Value* msg); + static const PROTOBUF_NAMESPACE_ID::ListValue& list_value(const Value* msg); +}; + +const PROTOBUF_NAMESPACE_ID::Struct& +Value::_Internal::struct_value(const Value* msg) { + return *msg->kind_.struct_value_; } - const ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >& -Struct::fields() const { - // @@protoc_insertion_point(field_map:google.protobuf.Struct.fields) - return fields_.GetMap(); +const PROTOBUF_NAMESPACE_ID::ListValue& +Value::_Internal::list_value(const Value* msg) { + return *msg->kind_.list_value_; } - ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >* -Struct::mutable_fields() { - // @@protoc_insertion_point(field_mutable_map:google.protobuf.Struct.fields) - return fields_.MutableMap(); +void Value::set_allocated_struct_value(PROTOBUF_NAMESPACE_ID::Struct* struct_value) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + clear_kind(); + if (struct_value) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(struct_value); + if (message_arena != submessage_arena) { + struct_value = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, struct_value, submessage_arena); + } + set_has_struct_value(); + kind_.struct_value_ = struct_value; + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.struct_value) } - -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS - -// =================================================================== - -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int Value::kNullValueFieldNumber; -const int Value::kNumberValueFieldNumber; -const int Value::kStringValueFieldNumber; -const int Value::kBoolValueFieldNumber; -const int Value::kStructValueFieldNumber; -const int Value::kListValueFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 - -Value::Value() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fstruct_2eproto::InitDefaults(); +void Value::set_allocated_list_value(PROTOBUF_NAMESPACE_ID::ListValue* list_value) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + clear_kind(); + if (list_value) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(list_value); + if (message_arena != submessage_arena) { + list_value = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, list_value, submessage_arena); + } + set_has_list_value(); + kind_.list_value_ = list_value; } - SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.Value) + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.list_value) } -Value::Value(::google::protobuf::Arena* arena) - : ::google::protobuf::Message(), - _internal_metadata_(arena) { - protobuf_google_2fprotobuf_2fstruct_2eproto::InitDefaults(); +Value::Value(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); RegisterArenaDtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Value) } Value::Value(const Value& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); clear_has_kind(); switch (from.kind_case()) { case kNullValue: { - set_null_value(from.null_value()); + _internal_set_null_value(from._internal_null_value()); break; } case kNumberValue: { - set_number_value(from.number_value()); + _internal_set_number_value(from._internal_number_value()); break; } case kStringValue: { - set_string_value(from.string_value()); + _internal_set_string_value(from._internal_string_value()); break; } case kBoolValue: { - set_bool_value(from.bool_value()); + _internal_set_bool_value(from._internal_bool_value()); break; } case kStructValue: { - mutable_struct_value()->::google::protobuf::Struct::MergeFrom(from.struct_value()); + _internal_mutable_struct_value()->PROTOBUF_NAMESPACE_ID::Struct::MergeFrom(from._internal_struct_value()); break; } case kListValue: { - mutable_list_value()->::google::protobuf::ListValue::MergeFrom(from.list_value()); + _internal_mutable_list_value()->PROTOBUF_NAMESPACE_ID::ListValue::MergeFrom(from._internal_list_value()); break; } case KIND_NOT_SET: { @@ -718,22 +501,17 @@ Value::Value(const Value& from) } void Value::SharedCtor() { - clear_has_kind(); - _cached_size_ = 0; +clear_has_kind(); } Value::~Value() { // @@protoc_insertion_point(destructor:google.protobuf.Value) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void Value::SharedDtor() { - ::google::protobuf::Arena* arena = GetArenaNoVirtual(); - GOOGLE_DCHECK(arena == NULL); - if (arena != NULL) { - return; - } - + GOOGLE_DCHECK(GetArena() == nullptr); if (has_kind()) { clear_kind(); } @@ -743,25 +521,10 @@ void Value::ArenaDtor(void* object) { Value* _this = reinterpret_cast< Value* >(object); (void)_this; } -void Value::RegisterArenaDtor(::google::protobuf::Arena* arena) { +void Value::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } void Value::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* Value::descriptor() { - protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const Value& Value::default_instance() { - protobuf_google_2fprotobuf_2fstruct_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -Value* Value::New(::google::protobuf::Arena* arena) const { - return ::google::protobuf::Arena::CreateMessage(arena); + _cached_size_.Set(size); } void Value::clear_kind() { @@ -776,8 +539,7 @@ void Value::clear_kind() { break; } case kStringValue: { - kind_.string_value_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - GetArenaNoVirtual()); + kind_.string_value_.Destroy(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); break; } case kBoolValue: { @@ -785,13 +547,13 @@ void Value::clear_kind() { break; } case kStructValue: { - if (GetArenaNoVirtual() == NULL) { + if (GetArena() == nullptr) { delete kind_.struct_value_; } break; } case kListValue: { - if (GetArenaNoVirtual() == NULL) { + if (GetArena() == nullptr) { delete kind_.list_value_; } break; @@ -806,231 +568,142 @@ void Value::clear_kind() { void Value::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Value) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; clear_kind(); - _internal_metadata_.Clear(); -} - -bool Value::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.Value) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // .google.protobuf.NullValue null_value = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { - int value; - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( - input, &value))); - set_null_value(static_cast< ::google::protobuf::NullValue >(value)); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* Value::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // .google.protobuf.NullValue null_value = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + ::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + _internal_set_null_value(static_cast(val)); + } else goto handle_unusual; + continue; // double number_value = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(17u /* 17 & 0xFF */)) { - clear_kind(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( - input, &kind_.number_value_))); - set_has_number_value(); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 17)) { + _internal_set_number_value(::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr)); + ptr += sizeof(double); + } else goto handle_unusual; + continue; // string string_value = 3; - case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_string_value())); - DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->string_value().data(), static_cast(this->string_value().length()), - ::google::protobuf::internal::WireFormatLite::PARSE, - "google.protobuf.Value.string_value")); - } else { - goto handle_unusual; - } - break; - } - + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + auto str = _internal_mutable_string_value(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "google.protobuf.Value.string_value")); + CHK_(ptr); + } else goto handle_unusual; + continue; // bool bool_value = 4; - case 4: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(32u /* 32 & 0xFF */)) { - clear_kind(); - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( - input, &kind_.bool_value_))); - set_has_bool_value(); - } else { - goto handle_unusual; - } - break; - } - + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 32)) { + _internal_set_bool_value(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr)); + CHK_(ptr); + } else goto handle_unusual; + continue; // .google.protobuf.Struct struct_value = 5; - case 5: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(42u /* 42 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, mutable_struct_value())); - } else { - goto handle_unusual; - } - break; - } - + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 42)) { + ptr = ctx->ParseMessage(_internal_mutable_struct_value(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // .google.protobuf.ListValue list_value = 6; - case 6: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, mutable_list_value())); - } else { - goto handle_unusual; - } - break; - } - + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 50)) { + ptr = ctx->ParseMessage(_internal_mutable_list_value(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.Value) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.Value) - return false; -#undef DO_ -} - -void Value::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.Value) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // .google.protobuf.NullValue null_value = 1; - if (has_null_value()) { - ::google::protobuf::internal::WireFormatLite::WriteEnum( - 1, this->null_value(), output); - } - - // double number_value = 2; - if (has_number_value()) { - ::google::protobuf::internal::WireFormatLite::WriteDouble(2, this->number_value(), output); - } - - // string string_value = 3; - if (has_string_value()) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->string_value().data(), static_cast(this->string_value().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, - "google.protobuf.Value.string_value"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 3, this->string_value(), output); - } - - // bool bool_value = 4; - if (has_bool_value()) { - ::google::protobuf::internal::WireFormatLite::WriteBool(4, this->bool_value(), output); - } - - // .google.protobuf.Struct struct_value = 5; - if (has_struct_value()) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 5, *kind_.struct_value_, output); - } - - // .google.protobuf.ListValue list_value = 6; - if (has_list_value()) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 6, *kind_.list_value_, output); - } - - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.Value) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* Value::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* Value::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Value) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // .google.protobuf.NullValue null_value = 1; - if (has_null_value()) { - target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( - 1, this->null_value(), target); + if (_internal_has_null_value()) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray( + 1, this->_internal_null_value(), target); } // double number_value = 2; - if (has_number_value()) { - target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(2, this->number_value(), target); + if (_internal_has_number_value()) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteDoubleToArray(2, this->_internal_number_value(), target); } // string string_value = 3; - if (has_string_value()) { - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - this->string_value().data(), static_cast(this->string_value().length()), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, + if (_internal_has_string_value()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_string_value().data(), static_cast(this->_internal_string_value().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, "google.protobuf.Value.string_value"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 3, this->string_value(), target); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_string_value(), target); } // bool bool_value = 4; - if (has_bool_value()) { - target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(4, this->bool_value(), target); + if (_internal_has_bool_value()) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(4, this->_internal_bool_value(), target); } // .google.protobuf.Struct struct_value = 5; - if (has_struct_value()) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 5, *kind_.struct_value_, deterministic, target); + if (_internal_has_struct_value()) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 5, _Internal::struct_value(this), target, stream); } // .google.protobuf.ListValue list_value = 6; - if (has_list_value()) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 6, *kind_.list_value_, deterministic, target); + if (_internal_has_list_value()) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 6, _Internal::list_value(this), target, stream); } - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Value) return target; @@ -1040,16 +713,15 @@ size_t Value::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Value) size_t total_size = 0; - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + switch (kind_case()) { // .google.protobuf.NullValue null_value = 1; case kNullValue: { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::EnumSize(this->null_value()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_null_value()); break; } // double number_value = 2; @@ -1060,8 +732,8 @@ size_t Value::ByteSizeLong() const { // string string_value = 3; case kStringValue: { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->string_value()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_string_value()); break; } // bool bool_value = 4; @@ -1072,14 +744,14 @@ size_t Value::ByteSizeLong() const { // .google.protobuf.Struct struct_value = 5; case kStructValue: { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( *kind_.struct_value_); break; } // .google.protobuf.ListValue list_value = 6; case kListValue: { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( *kind_.list_value_); break; } @@ -1087,22 +759,24 @@ size_t Value::ByteSizeLong() const { break; } } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void Value::MergeFrom(const ::google::protobuf::Message& from) { +void Value::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Value) GOOGLE_DCHECK_NE(&from, this); const Value* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Value) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Value) MergeFrom(*source); @@ -1112,33 +786,33 @@ void Value::MergeFrom(const ::google::protobuf::Message& from) { void Value::MergeFrom(const Value& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Value) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; switch (from.kind_case()) { case kNullValue: { - set_null_value(from.null_value()); + _internal_set_null_value(from._internal_null_value()); break; } case kNumberValue: { - set_number_value(from.number_value()); + _internal_set_number_value(from._internal_number_value()); break; } case kStringValue: { - set_string_value(from.string_value()); + _internal_set_string_value(from._internal_string_value()); break; } case kBoolValue: { - set_bool_value(from.bool_value()); + _internal_set_bool_value(from._internal_bool_value()); break; } case kStructValue: { - mutable_struct_value()->::google::protobuf::Struct::MergeFrom(from.struct_value()); + _internal_mutable_struct_value()->PROTOBUF_NAMESPACE_ID::Struct::MergeFrom(from._internal_struct_value()); break; } case kListValue: { - mutable_list_value()->::google::protobuf::ListValue::MergeFrom(from.list_value()); + _internal_mutable_list_value()->PROTOBUF_NAMESPACE_ID::ListValue::MergeFrom(from._internal_list_value()); break; } case KIND_NOT_SET: { @@ -1147,7 +821,7 @@ void Value::MergeFrom(const Value& from) { } } -void Value::CopyFrom(const ::google::protobuf::Message& from) { +void Value::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Value) if (&from == this) return; Clear(); @@ -1165,603 +839,129 @@ bool Value::IsInitialized() const { return true; } -void Value::Swap(Value* other) { - if (other == this) return; - if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { - InternalSwap(other); - } else { - Value* temp = New(GetArenaNoVirtual()); - temp->MergeFrom(*other); - other->CopyFrom(*this); - InternalSwap(temp); - if (GetArenaNoVirtual() == NULL) { - delete temp; - } - } -} -void Value::UnsafeArenaSwap(Value* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); - InternalSwap(other); -} void Value::InternalSwap(Value* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); swap(kind_, other->kind_); swap(_oneof_case_[0], other->_oneof_case_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata Value::GetMetadata() const { - protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// Value - -// .google.protobuf.NullValue null_value = 1; -bool Value::has_null_value() const { - return kind_case() == kNullValue; -} -void Value::set_has_null_value() { - _oneof_case_[0] = kNullValue; -} -void Value::clear_null_value() { - if (has_null_value()) { - kind_.null_value_ = 0; - clear_has_kind(); - } -} -::google::protobuf::NullValue Value::null_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.Value.null_value) - if (has_null_value()) { - return static_cast< ::google::protobuf::NullValue >(kind_.null_value_); - } - return static_cast< ::google::protobuf::NullValue >(0); -} -void Value::set_null_value(::google::protobuf::NullValue value) { - if (!has_null_value()) { - clear_kind(); - set_has_null_value(); - } - kind_.null_value_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.Value.null_value) } -// double number_value = 2; -bool Value::has_number_value() const { - return kind_case() == kNumberValue; -} -void Value::set_has_number_value() { - _oneof_case_[0] = kNumberValue; -} -void Value::clear_number_value() { - if (has_number_value()) { - kind_.number_value_ = 0; - clear_has_kind(); - } -} -double Value::number_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.Value.number_value) - if (has_number_value()) { - return kind_.number_value_; - } - return 0; -} -void Value::set_number_value(double value) { - if (!has_number_value()) { - clear_kind(); - set_has_number_value(); - } - kind_.number_value_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.Value.number_value) +::PROTOBUF_NAMESPACE_ID::Metadata Value::GetMetadata() const { + return GetMetadataStatic(); } -// string string_value = 3; -bool Value::has_string_value() const { - return kind_case() == kStringValue; -} -void Value::set_has_string_value() { - _oneof_case_[0] = kStringValue; -} -void Value::clear_string_value() { - if (has_string_value()) { - kind_.string_value_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - GetArenaNoVirtual()); - clear_has_kind(); - } -} -const ::std::string& Value::string_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.Value.string_value) - if (has_string_value()) { - return kind_.string_value_.Get(); - } - return *&::google::protobuf::internal::GetEmptyStringAlreadyInited(); -} -void Value::set_string_value(const ::std::string& value) { - if (!has_string_value()) { - clear_kind(); - set_has_string_value(); - kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } - kind_.string_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, - GetArenaNoVirtual()); - // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value) -} -#if LANG_CXX11 -void Value::set_string_value(::std::string&& value) { - // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value) - if (!has_string_value()) { - clear_kind(); - set_has_string_value(); - kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } - kind_.string_value_.Set( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual()); - // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Value.string_value) -} -#endif -void Value::set_string_value(const char* value) { - GOOGLE_DCHECK(value != NULL); - if (!has_string_value()) { - clear_kind(); - set_has_string_value(); - kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } - kind_.string_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(value), GetArenaNoVirtual()); - // @@protoc_insertion_point(field_set_char:google.protobuf.Value.string_value) -} -void Value::set_string_value(const char* value, - size_t size) { - if (!has_string_value()) { - clear_kind(); - set_has_string_value(); - kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } - kind_.string_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string( - reinterpret_cast(value), size), - GetArenaNoVirtual()); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.Value.string_value) -} -::std::string* Value::mutable_string_value() { - if (!has_string_value()) { - clear_kind(); - set_has_string_value(); - kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } - return kind_.string_value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - GetArenaNoVirtual()); - // @@protoc_insertion_point(field_mutable:google.protobuf.Value.string_value) -} -::std::string* Value::release_string_value() { - // @@protoc_insertion_point(field_release:google.protobuf.Value.string_value) - if (has_string_value()) { - clear_has_kind(); - return kind_.string_value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - GetArenaNoVirtual()); - } else { - return NULL; - } -} -::std::string* Value::unsafe_arena_release_string_value() { - // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Value.string_value) - GOOGLE_DCHECK(GetArenaNoVirtual() != NULL); - if (has_string_value()) { - clear_has_kind(); - return kind_.string_value_.UnsafeArenaRelease( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); - } else { - return NULL; - } -} -void Value::set_allocated_string_value(::std::string* string_value) { - if (!has_string_value()) { - kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } - clear_kind(); - if (string_value != NULL) { - set_has_string_value(); - kind_.string_value_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value, - GetArenaNoVirtual()); - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.string_value) -} -void Value::unsafe_arena_set_allocated_string_value(::std::string* string_value) { - GOOGLE_DCHECK(GetArenaNoVirtual() != NULL); - if (!has_string_value()) { - kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } - clear_kind(); - if (string_value) { - set_has_string_value(); - kind_.string_value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value, GetArenaNoVirtual()); - } - // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Value.string_value) -} - -// bool bool_value = 4; -bool Value::has_bool_value() const { - return kind_case() == kBoolValue; -} -void Value::set_has_bool_value() { - _oneof_case_[0] = kBoolValue; -} -void Value::clear_bool_value() { - if (has_bool_value()) { - kind_.bool_value_ = false; - clear_has_kind(); - } -} -bool Value::bool_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.Value.bool_value) - if (has_bool_value()) { - return kind_.bool_value_; - } - return false; -} -void Value::set_bool_value(bool value) { - if (!has_bool_value()) { - clear_kind(); - set_has_bool_value(); - } - kind_.bool_value_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.Value.bool_value) -} - -// .google.protobuf.Struct struct_value = 5; -bool Value::has_struct_value() const { - return kind_case() == kStructValue; -} -void Value::set_has_struct_value() { - _oneof_case_[0] = kStructValue; -} -void Value::clear_struct_value() { - if (has_struct_value()) { - if (GetArenaNoVirtual() == NULL) { - delete kind_.struct_value_; - } - clear_has_kind(); - } -} - const ::google::protobuf::Struct& Value::struct_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.Value.struct_value) - return has_struct_value() - ? *kind_.struct_value_ - : ::google::protobuf::Struct::default_instance(); -} -::google::protobuf::Struct* Value::mutable_struct_value() { - if (!has_struct_value()) { - clear_kind(); - set_has_struct_value(); - kind_.struct_value_ = - ::google::protobuf::Arena::CreateMessage< ::google::protobuf::Struct >( - GetArenaNoVirtual()); - } - // @@protoc_insertion_point(field_mutable:google.protobuf.Value.struct_value) - return kind_.struct_value_; -} -::google::protobuf::Struct* Value::release_struct_value() { - // @@protoc_insertion_point(field_release:google.protobuf.Value.struct_value) - if (has_struct_value()) { - clear_has_kind(); - if (GetArenaNoVirtual() != NULL) { - ::google::protobuf::Struct* temp = new ::google::protobuf::Struct(*kind_.struct_value_); - kind_.struct_value_ = NULL; - return temp; - } else { - ::google::protobuf::Struct* temp = kind_.struct_value_; - kind_.struct_value_ = NULL; - return temp; - } - } else { - return NULL; - } -} -void Value::set_allocated_struct_value(::google::protobuf::Struct* struct_value) { - clear_kind(); - if (struct_value) { - if (GetArenaNoVirtual() != NULL && - ::google::protobuf::Arena::GetArena(struct_value) == NULL) { - GetArenaNoVirtual()->Own(struct_value); - } else if (GetArenaNoVirtual() != - ::google::protobuf::Arena::GetArena(struct_value)) { - ::google::protobuf::Struct* new_struct_value = - ::google::protobuf::Arena::CreateMessage< ::google::protobuf::Struct >( - GetArenaNoVirtual()); - new_struct_value->CopyFrom(*struct_value); - struct_value = new_struct_value; - } - set_has_struct_value(); - kind_.struct_value_ = struct_value; - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.struct_value) -} - ::google::protobuf::Struct* Value::unsafe_arena_release_struct_value() { - // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Value.struct_value) - if (has_struct_value()) { - clear_has_kind(); - ::google::protobuf::Struct* temp = kind_.struct_value_; - kind_.struct_value_ = NULL; - return temp; - } else { - return NULL; - } -} - void Value::unsafe_arena_set_allocated_struct_value(::google::protobuf::Struct* struct_value) { - clear_kind(); - if (struct_value) { - set_has_struct_value(); - kind_.struct_value_ = struct_value; - } - // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Value.struct_value) -} - -// .google.protobuf.ListValue list_value = 6; -bool Value::has_list_value() const { - return kind_case() == kListValue; -} -void Value::set_has_list_value() { - _oneof_case_[0] = kListValue; -} -void Value::clear_list_value() { - if (has_list_value()) { - if (GetArenaNoVirtual() == NULL) { - delete kind_.list_value_; - } - clear_has_kind(); - } -} - const ::google::protobuf::ListValue& Value::list_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.Value.list_value) - return has_list_value() - ? *kind_.list_value_ - : ::google::protobuf::ListValue::default_instance(); -} -::google::protobuf::ListValue* Value::mutable_list_value() { - if (!has_list_value()) { - clear_kind(); - set_has_list_value(); - kind_.list_value_ = - ::google::protobuf::Arena::CreateMessage< ::google::protobuf::ListValue >( - GetArenaNoVirtual()); - } - // @@protoc_insertion_point(field_mutable:google.protobuf.Value.list_value) - return kind_.list_value_; -} -::google::protobuf::ListValue* Value::release_list_value() { - // @@protoc_insertion_point(field_release:google.protobuf.Value.list_value) - if (has_list_value()) { - clear_has_kind(); - if (GetArenaNoVirtual() != NULL) { - ::google::protobuf::ListValue* temp = new ::google::protobuf::ListValue(*kind_.list_value_); - kind_.list_value_ = NULL; - return temp; - } else { - ::google::protobuf::ListValue* temp = kind_.list_value_; - kind_.list_value_ = NULL; - return temp; - } - } else { - return NULL; - } -} -void Value::set_allocated_list_value(::google::protobuf::ListValue* list_value) { - clear_kind(); - if (list_value) { - if (GetArenaNoVirtual() != NULL && - ::google::protobuf::Arena::GetArena(list_value) == NULL) { - GetArenaNoVirtual()->Own(list_value); - } else if (GetArenaNoVirtual() != - ::google::protobuf::Arena::GetArena(list_value)) { - ::google::protobuf::ListValue* new_list_value = - ::google::protobuf::Arena::CreateMessage< ::google::protobuf::ListValue >( - GetArenaNoVirtual()); - new_list_value->CopyFrom(*list_value); - list_value = new_list_value; - } - set_has_list_value(); - kind_.list_value_ = list_value; - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.list_value) -} - ::google::protobuf::ListValue* Value::unsafe_arena_release_list_value() { - // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Value.list_value) - if (has_list_value()) { - clear_has_kind(); - ::google::protobuf::ListValue* temp = kind_.list_value_; - kind_.list_value_ = NULL; - return temp; - } else { - return NULL; - } -} - void Value::unsafe_arena_set_allocated_list_value(::google::protobuf::ListValue* list_value) { - clear_kind(); - if (list_value) { - set_has_list_value(); - kind_.list_value_ = list_value; - } - // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Value.list_value) -} - -bool Value::has_kind() const { - return kind_case() != KIND_NOT_SET; -} -void Value::clear_has_kind() { - _oneof_case_[0] = KIND_NOT_SET; -} -Value::KindCase Value::kind_case() const { - return Value::KindCase(_oneof_case_[0]); -} -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int ListValue::kValuesFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +class ListValue::_Internal { + public: +}; -ListValue::ListValue() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2fstruct_2eproto::InitDefaults(); - } - SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.ListValue) -} -ListValue::ListValue(::google::protobuf::Arena* arena) - : ::google::protobuf::Message(), - _internal_metadata_(arena), +ListValue::ListValue(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), values_(arena) { - protobuf_google_2fprotobuf_2fstruct_2eproto::InitDefaults(); SharedCtor(); RegisterArenaDtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.ListValue) } ListValue::ListValue(const ListValue& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - values_(from.values_), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + : ::PROTOBUF_NAMESPACE_ID::Message(), + values_(from.values_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); // @@protoc_insertion_point(copy_constructor:google.protobuf.ListValue) } void ListValue::SharedCtor() { - _cached_size_ = 0; } ListValue::~ListValue() { // @@protoc_insertion_point(destructor:google.protobuf.ListValue) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void ListValue::SharedDtor() { - ::google::protobuf::Arena* arena = GetArenaNoVirtual(); - GOOGLE_DCHECK(arena == NULL); - if (arena != NULL) { - return; - } - + GOOGLE_DCHECK(GetArena() == nullptr); } void ListValue::ArenaDtor(void* object) { ListValue* _this = reinterpret_cast< ListValue* >(object); (void)_this; } -void ListValue::RegisterArenaDtor(::google::protobuf::Arena* arena) { +void ListValue::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } void ListValue::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* ListValue::descriptor() { - protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const ListValue& ListValue::default_instance() { - protobuf_google_2fprotobuf_2fstruct_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -ListValue* ListValue::New(::google::protobuf::Arena* arena) const { - return ::google::protobuf::Arena::CreateMessage(arena); + _cached_size_.Set(size); } void ListValue::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.ListValue) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; values_.Clear(); - _internal_metadata_.Clear(); -} - -bool ListValue::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.ListValue) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // repeated .google.protobuf.Value values = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( - input, add_values())); - } else { - goto handle_unusual; - } - break; - } + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} +const char* ListValue::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // repeated .google.protobuf.Value values = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_values(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.ListValue) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.ListValue) - return false; -#undef DO_ -} - -void ListValue::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.ListValue) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // repeated .google.protobuf.Value values = 1; - for (unsigned int i = 0, - n = static_cast(this->values_size()); i < n; i++) { - ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 1, this->values(static_cast(i)), output); - } - - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.ListValue) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* ListValue::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* ListValue::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ListValue) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // repeated .google.protobuf.Value values = 1; for (unsigned int i = 0, - n = static_cast(this->values_size()); i < n; i++) { - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 1, this->values(static_cast(i)), deterministic, target); + n = static_cast(this->_internal_values_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(1, this->_internal_values(i), target, stream); } - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ListValue) return target; @@ -1771,38 +971,35 @@ size_t ListValue::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ListValue) size_t total_size = 0; - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.Value values = 1; - { - unsigned int count = static_cast(this->values_size()); - total_size += 1UL * count; - for (unsigned int i = 0; i < count; i++) { - total_size += - ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( - this->values(static_cast(i))); - } + total_size += 1UL * this->_internal_values_size(); + for (const auto& msg : this->values_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void ListValue::MergeFrom(const ::google::protobuf::Message& from) { +void ListValue::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ListValue) GOOGLE_DCHECK_NE(&from, this); const ListValue* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ListValue) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ListValue) MergeFrom(*source); @@ -1812,14 +1009,14 @@ void ListValue::MergeFrom(const ::google::protobuf::Message& from) { void ListValue::MergeFrom(const ListValue& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ListValue) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; values_.MergeFrom(from.values_); } -void ListValue::CopyFrom(const ::google::protobuf::Message& from) { +void ListValue::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ListValue) if (&from == this) return; Clear(); @@ -1837,75 +1034,33 @@ bool ListValue::IsInitialized() const { return true; } -void ListValue::Swap(ListValue* other) { - if (other == this) return; - if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { - InternalSwap(other); - } else { - ListValue* temp = New(GetArenaNoVirtual()); - temp->MergeFrom(*other); - other->CopyFrom(*this); - InternalSwap(temp); - if (GetArenaNoVirtual() == NULL) { - delete temp; - } - } -} -void ListValue::UnsafeArenaSwap(ListValue* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); - InternalSwap(other); -} void ListValue::InternalSwap(ListValue* other) { using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); values_.InternalSwap(&other->values_); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); } -::google::protobuf::Metadata ListValue::GetMetadata() const { - protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_metadata[kIndexInFileMessages]; +::PROTOBUF_NAMESPACE_ID::Metadata ListValue::GetMetadata() const { + return GetMetadataStatic(); } -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// ListValue -// repeated .google.protobuf.Value values = 1; -int ListValue::values_size() const { - return values_.size(); -} -void ListValue::clear_values() { - values_.Clear(); -} -const ::google::protobuf::Value& ListValue::values(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.ListValue.values) - return values_.Get(index); -} -::google::protobuf::Value* ListValue::mutable_values(int index) { - // @@protoc_insertion_point(field_mutable:google.protobuf.ListValue.values) - return values_.Mutable(index); +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse >(arena); } -::google::protobuf::Value* ListValue::add_values() { - // @@protoc_insertion_point(field_add:google.protobuf.ListValue.values) - return values_.Add(); +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::Struct* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::Struct >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::Struct >(arena); } -::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >* -ListValue::mutable_values() { - // @@protoc_insertion_point(field_mutable_list:google.protobuf.ListValue.values) - return &values_; +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::Value* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::Value >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::Value >(arena); } -const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >& -ListValue::values() const { - // @@protoc_insertion_point(field_list:google.protobuf.ListValue.values) - return values_; +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::ListValue* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::ListValue >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::ListValue >(arena); } - -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS - -// @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) +#include diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h index 57ae7d90e4294..ac33ab601e0a2 100644 --- a/src/google/protobuf/struct.pb.h +++ b/src/google/protobuf/struct.pb.h @@ -1,30 +1,32 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/struct.proto -#ifndef PROTOBUF_google_2fprotobuf_2fstruct_2eproto__INCLUDED -#define PROTOBUF_google_2fprotobuf_2fstruct_2eproto__INCLUDED +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto +#include #include -#include - -#if GOOGLE_PROTOBUF_VERSION < 3004000 +#include +#if PROTOBUF_VERSION < 3015000 #error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update +#error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 3015000 < PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please +#error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif +#include #include #include #include #include #include -#include +#include +#include #include #include // IWYU pragma: export #include // IWYU pragma: export @@ -34,243 +36,296 @@ #include #include // @@protoc_insertion_point(includes) -namespace google { -namespace protobuf { +#include +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fstruct_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fstruct_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[4] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; +}; +extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fstruct_2eproto; +PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(int index); +PROTOBUF_NAMESPACE_OPEN class ListValue; -class ListValueDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern ListValueDefaultTypeInternal _ListValue_default_instance_; +struct ListValueDefaultTypeInternal; +PROTOBUF_EXPORT extern ListValueDefaultTypeInternal _ListValue_default_instance_; class Struct; -class StructDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern StructDefaultTypeInternal _Struct_default_instance_; -class Struct_FieldsEntry; -class Struct_FieldsEntryDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern Struct_FieldsEntryDefaultTypeInternal _Struct_FieldsEntry_default_instance_; +struct StructDefaultTypeInternal; +PROTOBUF_EXPORT extern StructDefaultTypeInternal _Struct_default_instance_; +class Struct_FieldsEntry_DoNotUse; +struct Struct_FieldsEntry_DoNotUseDefaultTypeInternal; +PROTOBUF_EXPORT extern Struct_FieldsEntry_DoNotUseDefaultTypeInternal _Struct_FieldsEntry_DoNotUse_default_instance_; class Value; -class ValueDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern ValueDefaultTypeInternal _Value_default_instance_; -} // namespace protobuf -} // namespace google - -namespace google { -namespace protobuf { - -namespace protobuf_google_2fprotobuf_2fstruct_2eproto { -// Internal implementation detail -- do not call these. -struct LIBPROTOBUF_EXPORT TableStruct { - static const ::google::protobuf::internal::ParseTableField entries[]; - static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; - static const ::google::protobuf::internal::ParseTable schema[]; - static const ::google::protobuf::uint32 offsets[]; - static const ::google::protobuf::internal::FieldMetadata field_metadata[]; - static const ::google::protobuf::internal::SerializationTable serialization_table[]; - static void InitDefaultsImpl(); -}; -void LIBPROTOBUF_EXPORT AddDescriptors(); -void LIBPROTOBUF_EXPORT InitDefaults(); -} // namespace protobuf_google_2fprotobuf_2fstruct_2eproto - -enum NullValue { +struct ValueDefaultTypeInternal; +PROTOBUF_EXPORT extern ValueDefaultTypeInternal _Value_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::ListValue* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::Struct* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse* Arena::CreateMaybeMessage(Arena*); +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::Value* Arena::CreateMaybeMessage(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN + +enum NullValue : int { NULL_VALUE = 0, - NullValue_INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min, - NullValue_INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max + NullValue_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::min(), + NullValue_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::max() }; -LIBPROTOBUF_EXPORT bool NullValue_IsValid(int value); -const NullValue NullValue_MIN = NULL_VALUE; -const NullValue NullValue_MAX = NULL_VALUE; -const int NullValue_ARRAYSIZE = NullValue_MAX + 1; - -LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* NullValue_descriptor(); -inline const ::std::string& NullValue_Name(NullValue value) { - return ::google::protobuf::internal::NameOfEnum( - NullValue_descriptor(), value); +PROTOBUF_EXPORT bool NullValue_IsValid(int value); +constexpr NullValue NullValue_MIN = NULL_VALUE; +constexpr NullValue NullValue_MAX = NULL_VALUE; +constexpr int NullValue_ARRAYSIZE = NullValue_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* NullValue_descriptor(); +template +inline const std::string& NullValue_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function NullValue_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + NullValue_descriptor(), enum_t_value); } inline bool NullValue_Parse( - const ::std::string& name, NullValue* value) { - return ::google::protobuf::internal::ParseNamedEnum( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, NullValue* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum( NullValue_descriptor(), name, value); } // =================================================================== +class Struct_FieldsEntry_DoNotUse : public ::PROTOBUF_NAMESPACE_ID::internal::MapEntry { +public: + typedef ::PROTOBUF_NAMESPACE_ID::internal::MapEntry SuperType; + Struct_FieldsEntry_DoNotUse(); + explicit constexpr Struct_FieldsEntry_DoNotUse( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + explicit Struct_FieldsEntry_DoNotUse(::PROTOBUF_NAMESPACE_ID::Arena* arena); + void MergeFrom(const Struct_FieldsEntry_DoNotUse& other); + static const Struct_FieldsEntry_DoNotUse* internal_default_instance() { return reinterpret_cast(&_Struct_FieldsEntry_DoNotUse_default_instance_); } + static bool ValidateKey(std::string* s) { + return ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(s->data(), static_cast(s->size()), ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE, "google.protobuf.Struct.FieldsEntry.key"); + } + static bool ValidateValue(void*) { return true; } + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& other) final; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fstruct_2eproto); + return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto.file_level_metadata[0]; + } + + public: +}; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT Struct : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Struct) */ { +class PROTOBUF_EXPORT Struct PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Struct) */ { public: - Struct(); + inline Struct() : Struct(nullptr) {} virtual ~Struct(); + explicit constexpr Struct(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); Struct(const Struct& from); - - inline Struct& operator=(const Struct& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 Struct(Struct&& from) noexcept : Struct() { *this = ::std::move(from); } + inline Struct& operator=(const Struct& from) { + CopyFrom(from); + return *this; + } inline Struct& operator=(Struct&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL { - return GetArenaNoVirtual(); + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); } - inline void* GetMaybeArenaPointer() const PROTOBUF_FINAL { - return MaybeArenaPtr(); + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const Struct& default_instance() { + return *internal_default_instance(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const Struct& default_instance(); - static inline const Struct* internal_default_instance() { return reinterpret_cast( &_Struct_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 1; - void UnsafeArenaSwap(Struct* other); - void Swap(Struct* other); friend void swap(Struct& a, Struct& b) { a.Swap(&b); } + inline void Swap(Struct* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Struct* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline Struct* New() const PROTOBUF_FINAL { return New(NULL); } + inline Struct* New() const final { + return CreateMaybeMessage(nullptr); + } - Struct* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + Struct* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const Struct& from); void MergeFrom(const Struct& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(Struct* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Struct"; + } protected: - explicit Struct(::google::protobuf::Arena* arena); + explicit Struct(::PROTOBUF_NAMESPACE_ID::Arena* arena); private: static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::google::protobuf::Arena* arena); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return _internal_metadata_.arena(); + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(kIndexInFileMessages); } - inline void* MaybeArenaPtr() const { - return _internal_metadata_.raw_arena_ptr(); - } - public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kFieldsFieldNumber = 1, + }; // map fields = 1; int fields_size() const; + private: + int _internal_fields_size() const; + public: void clear_fields(); - static const int kFieldsFieldNumber = 1; - const ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >& + private: + const ::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >& + _internal_fields() const; + ::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >* + _internal_mutable_fields(); + public: + const ::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >& fields() const; - ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >* + ::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >* mutable_fields(); // @@protoc_insertion_point(class_scope:google.protobuf.Struct) private: + class _Internal; - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - template friend class ::google::protobuf::Arena::InternalHelper; + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; - public: - class Struct_FieldsEntry : public ::google::protobuf::internal::MapEntry { - public: - typedef ::google::protobuf::internal::MapEntry SuperType; - Struct_FieldsEntry(); - Struct_FieldsEntry(::google::protobuf::Arena* arena); - void MergeFrom(const ::google::protobuf::Message& other) PROTOBUF_FINAL; - void MergeFrom(const Struct_FieldsEntry& other); - static const Message* internal_default_instance() { return reinterpret_cast(&_Struct_FieldsEntry_default_instance_); } - ::google::protobuf::Metadata GetMetadata() const; - }; - private: - ::google::protobuf::internal::MapField< - Struct_FieldsEntry, - ::std::string, ::google::protobuf::Value, - ::google::protobuf::internal::WireFormatLite::TYPE_STRING, - ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE, - 0 > fields_; - private: - mutable int _cached_size_; - friend struct protobuf_google_2fprotobuf_2fstruct_2eproto::TableStruct; + ::PROTOBUF_NAMESPACE_ID::internal::MapField< + Struct_FieldsEntry_DoNotUse, + std::string, PROTOBUF_NAMESPACE_ID::Value, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_STRING, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE> fields_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT Value : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Value) */ { +class PROTOBUF_EXPORT Value PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Value) */ { public: - Value(); + inline Value() : Value(nullptr) {} virtual ~Value(); + explicit constexpr Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); Value(const Value& from); - - inline Value& operator=(const Value& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 Value(Value&& from) noexcept : Value() { *this = ::std::move(from); } + inline Value& operator=(const Value& from) { + CopyFrom(from); + return *this; + } inline Value& operator=(Value&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL { - return GetArenaNoVirtual(); + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); } - inline void* GetMaybeArenaPointer() const PROTOBUF_FINAL { - return MaybeArenaPtr(); + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const Value& default_instance() { + return *internal_default_instance(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const Value& default_instance(); - enum KindCase { kNullValue = 1, kNumberValue = 2, @@ -285,146 +340,184 @@ class LIBPROTOBUF_EXPORT Value : public ::google::protobuf::Message /* @@protoc_ return reinterpret_cast( &_Value_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 2; - void UnsafeArenaSwap(Value* other); - void Swap(Value* other); friend void swap(Value& a, Value& b) { a.Swap(&b); } + inline void Swap(Value* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Value* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline Value* New() const PROTOBUF_FINAL { return New(NULL); } + inline Value* New() const final { + return CreateMaybeMessage(nullptr); + } - Value* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + Value* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const Value& from); void MergeFrom(const Value& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(Value* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Value"; + } protected: - explicit Value(::google::protobuf::Arena* arena); + explicit Value(::PROTOBUF_NAMESPACE_ID::Arena* arena); private: static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::google::protobuf::Arena* arena); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return _internal_metadata_.arena(); + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(kIndexInFileMessages); } - inline void* MaybeArenaPtr() const { - return _internal_metadata_.raw_arena_ptr(); - } - public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kNullValueFieldNumber = 1, + kNumberValueFieldNumber = 2, + kStringValueFieldNumber = 3, + kBoolValueFieldNumber = 4, + kStructValueFieldNumber = 5, + kListValueFieldNumber = 6, + }; // .google.protobuf.NullValue null_value = 1; - private: bool has_null_value() const; + private: + bool _internal_has_null_value() const; public: void clear_null_value(); - static const int kNullValueFieldNumber = 1; - ::google::protobuf::NullValue null_value() const; - void set_null_value(::google::protobuf::NullValue value); + PROTOBUF_NAMESPACE_ID::NullValue null_value() const; + void set_null_value(PROTOBUF_NAMESPACE_ID::NullValue value); + private: + PROTOBUF_NAMESPACE_ID::NullValue _internal_null_value() const; + void _internal_set_null_value(PROTOBUF_NAMESPACE_ID::NullValue value); + public: // double number_value = 2; - private: bool has_number_value() const; + private: + bool _internal_has_number_value() const; public: void clear_number_value(); - static const int kNumberValueFieldNumber = 2; double number_value() const; void set_number_value(double value); + private: + double _internal_number_value() const; + void _internal_set_number_value(double value); + public: // string string_value = 3; - private: bool has_string_value() const; + private: + bool _internal_has_string_value() const; public: void clear_string_value(); - static const int kStringValueFieldNumber = 3; - const ::std::string& string_value() const; - void set_string_value(const ::std::string& value); - #if LANG_CXX11 - void set_string_value(::std::string&& value); - #endif + const std::string& string_value() const; + void set_string_value(const std::string& value); + void set_string_value(std::string&& value); void set_string_value(const char* value); void set_string_value(const char* value, size_t size); - ::std::string* mutable_string_value(); - ::std::string* release_string_value(); - void set_allocated_string_value(::std::string* string_value); - ::std::string* unsafe_arena_release_string_value(); - void unsafe_arena_set_allocated_string_value( - ::std::string* string_value); + std::string* mutable_string_value(); + std::string* release_string_value(); + void set_allocated_string_value(std::string* string_value); + private: + const std::string& _internal_string_value() const; + void _internal_set_string_value(const std::string& value); + std::string* _internal_mutable_string_value(); + public: // bool bool_value = 4; - private: bool has_bool_value() const; + private: + bool _internal_has_bool_value() const; public: void clear_bool_value(); - static const int kBoolValueFieldNumber = 4; bool bool_value() const; void set_bool_value(bool value); + private: + bool _internal_bool_value() const; + void _internal_set_bool_value(bool value); + public: // .google.protobuf.Struct struct_value = 5; bool has_struct_value() const; + private: + bool _internal_has_struct_value() const; + public: void clear_struct_value(); - static const int kStructValueFieldNumber = 5; + const PROTOBUF_NAMESPACE_ID::Struct& struct_value() const; + PROTOBUF_NAMESPACE_ID::Struct* release_struct_value(); + PROTOBUF_NAMESPACE_ID::Struct* mutable_struct_value(); + void set_allocated_struct_value(PROTOBUF_NAMESPACE_ID::Struct* struct_value); private: - void _slow_mutable_struct_value(); - void _slow_set_allocated_struct_value( - ::google::protobuf::Arena* message_arena, ::google::protobuf::Struct** struct_value); - ::google::protobuf::Struct* _slow_release_struct_value(); + const PROTOBUF_NAMESPACE_ID::Struct& _internal_struct_value() const; + PROTOBUF_NAMESPACE_ID::Struct* _internal_mutable_struct_value(); public: - const ::google::protobuf::Struct& struct_value() const; - ::google::protobuf::Struct* mutable_struct_value(); - ::google::protobuf::Struct* release_struct_value(); - void set_allocated_struct_value(::google::protobuf::Struct* struct_value); - ::google::protobuf::Struct* unsafe_arena_release_struct_value(); void unsafe_arena_set_allocated_struct_value( - ::google::protobuf::Struct* struct_value); + PROTOBUF_NAMESPACE_ID::Struct* struct_value); + PROTOBUF_NAMESPACE_ID::Struct* unsafe_arena_release_struct_value(); // .google.protobuf.ListValue list_value = 6; bool has_list_value() const; + private: + bool _internal_has_list_value() const; + public: void clear_list_value(); - static const int kListValueFieldNumber = 6; + const PROTOBUF_NAMESPACE_ID::ListValue& list_value() const; + PROTOBUF_NAMESPACE_ID::ListValue* release_list_value(); + PROTOBUF_NAMESPACE_ID::ListValue* mutable_list_value(); + void set_allocated_list_value(PROTOBUF_NAMESPACE_ID::ListValue* list_value); private: - void _slow_mutable_list_value(); - void _slow_set_allocated_list_value( - ::google::protobuf::Arena* message_arena, ::google::protobuf::ListValue** list_value); - ::google::protobuf::ListValue* _slow_release_list_value(); + const PROTOBUF_NAMESPACE_ID::ListValue& _internal_list_value() const; + PROTOBUF_NAMESPACE_ID::ListValue* _internal_mutable_list_value(); public: - const ::google::protobuf::ListValue& list_value() const; - ::google::protobuf::ListValue* mutable_list_value(); - ::google::protobuf::ListValue* release_list_value(); - void set_allocated_list_value(::google::protobuf::ListValue* list_value); - ::google::protobuf::ListValue* unsafe_arena_release_list_value(); void unsafe_arena_set_allocated_list_value( - ::google::protobuf::ListValue* list_value); + PROTOBUF_NAMESPACE_ID::ListValue* list_value); + PROTOBUF_NAMESPACE_ID::ListValue* unsafe_arena_release_list_value(); + void clear_kind(); KindCase kind_case() const; // @@protoc_insertion_point(class_scope:google.protobuf.Value) private: + class _Internal; void set_has_null_value(); void set_has_number_value(); void set_has_string_value(); @@ -433,151 +526,177 @@ class LIBPROTOBUF_EXPORT Value : public ::google::protobuf::Message /* @@protoc_ void set_has_list_value(); inline bool has_kind() const; - void clear_kind(); inline void clear_has_kind(); - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - template friend class ::google::protobuf::Arena::InternalHelper; + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; union KindUnion { - KindUnion() {} + constexpr KindUnion() : _constinit_{} {} + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized _constinit_; int null_value_; double number_value_; - ::google::protobuf::internal::ArenaStringPtr string_value_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr string_value_; bool bool_value_; - ::google::protobuf::Struct* struct_value_; - ::google::protobuf::ListValue* list_value_; + PROTOBUF_NAMESPACE_ID::Struct* struct_value_; + PROTOBUF_NAMESPACE_ID::ListValue* list_value_; } kind_; - mutable int _cached_size_; - ::google::protobuf::uint32 _oneof_case_[1]; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::uint32 _oneof_case_[1]; - friend struct protobuf_google_2fprotobuf_2fstruct_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOBUF_EXPORT ListValue : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ListValue) */ { +class PROTOBUF_EXPORT ListValue PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ListValue) */ { public: - ListValue(); + inline ListValue() : ListValue(nullptr) {} virtual ~ListValue(); + explicit constexpr ListValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); ListValue(const ListValue& from); - - inline ListValue& operator=(const ListValue& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 ListValue(ListValue&& from) noexcept : ListValue() { *this = ::std::move(from); } + inline ListValue& operator=(const ListValue& from) { + CopyFrom(from); + return *this; + } inline ListValue& operator=(ListValue&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL { - return GetArenaNoVirtual(); + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); } - inline void* GetMaybeArenaPointer() const PROTOBUF_FINAL { - return MaybeArenaPtr(); + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const ListValue& default_instance() { + return *internal_default_instance(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const ListValue& default_instance(); - static inline const ListValue* internal_default_instance() { return reinterpret_cast( &_ListValue_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 3; - void UnsafeArenaSwap(ListValue* other); - void Swap(ListValue* other); friend void swap(ListValue& a, ListValue& b) { a.Swap(&b); } + inline void Swap(ListValue* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ListValue* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline ListValue* New() const PROTOBUF_FINAL { return New(NULL); } + inline ListValue* New() const final { + return CreateMaybeMessage(nullptr); + } - ListValue* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + ListValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const ListValue& from); void MergeFrom(const ListValue& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(ListValue* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.ListValue"; + } protected: - explicit ListValue(::google::protobuf::Arena* arena); + explicit ListValue(::PROTOBUF_NAMESPACE_ID::Arena* arena); private: static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::google::protobuf::Arena* arena); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return _internal_metadata_.arena(); + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(kIndexInFileMessages); } - inline void* MaybeArenaPtr() const { - return _internal_metadata_.raw_arena_ptr(); - } - public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kValuesFieldNumber = 1, + }; // repeated .google.protobuf.Value values = 1; int values_size() const; + private: + int _internal_values_size() const; + public: void clear_values(); - static const int kValuesFieldNumber = 1; - const ::google::protobuf::Value& values(int index) const; - ::google::protobuf::Value* mutable_values(int index); - ::google::protobuf::Value* add_values(); - ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >* + PROTOBUF_NAMESPACE_ID::Value* mutable_values(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Value >* mutable_values(); - const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >& + private: + const PROTOBUF_NAMESPACE_ID::Value& _internal_values(int index) const; + PROTOBUF_NAMESPACE_ID::Value* _internal_add_values(); + public: + const PROTOBUF_NAMESPACE_ID::Value& values(int index) const; + PROTOBUF_NAMESPACE_ID::Value* add_values(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Value >& values() const; // @@protoc_insertion_point(class_scope:google.protobuf.ListValue) private: + class _Internal; - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - template friend class ::google::protobuf::Arena::InternalHelper; + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value > values_; - mutable int _cached_size_; - friend struct protobuf_google_2fprotobuf_2fstruct_2eproto::TableStruct; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Value > values_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto; }; // =================================================================== // =================================================================== -#if !PROTOBUF_INLINE_NOT_IN_HEADERS #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" @@ -587,21 +706,32 @@ class LIBPROTOBUF_EXPORT ListValue : public ::google::protobuf::Message /* @@pro // Struct // map fields = 1; -inline int Struct::fields_size() const { +inline int Struct::_internal_fields_size() const { return fields_.size(); } +inline int Struct::fields_size() const { + return _internal_fields_size(); +} inline void Struct::clear_fields() { fields_.Clear(); } -inline const ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >& +inline const ::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >& +Struct::_internal_fields() const { + return fields_.GetMap(); +} +inline const ::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >& Struct::fields() const { // @@protoc_insertion_point(field_map:google.protobuf.Struct.fields) - return fields_.GetMap(); + return _internal_fields(); } -inline ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >* +inline ::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >* +Struct::_internal_mutable_fields() { + return fields_.MutableMap(); +} +inline ::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >* Struct::mutable_fields() { // @@protoc_insertion_point(field_mutable_map:google.protobuf.Struct.fields) - return fields_.MutableMap(); + return _internal_mutable_fields(); } // ------------------------------------------------------------------- @@ -609,295 +739,282 @@ Struct::mutable_fields() { // Value // .google.protobuf.NullValue null_value = 1; -inline bool Value::has_null_value() const { +inline bool Value::_internal_has_null_value() const { return kind_case() == kNullValue; } +inline bool Value::has_null_value() const { + return _internal_has_null_value(); +} inline void Value::set_has_null_value() { _oneof_case_[0] = kNullValue; } inline void Value::clear_null_value() { - if (has_null_value()) { + if (_internal_has_null_value()) { kind_.null_value_ = 0; clear_has_kind(); } } -inline ::google::protobuf::NullValue Value::null_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.Value.null_value) - if (has_null_value()) { - return static_cast< ::google::protobuf::NullValue >(kind_.null_value_); +inline PROTOBUF_NAMESPACE_ID::NullValue Value::_internal_null_value() const { + if (_internal_has_null_value()) { + return static_cast< PROTOBUF_NAMESPACE_ID::NullValue >(kind_.null_value_); } - return static_cast< ::google::protobuf::NullValue >(0); + return static_cast< PROTOBUF_NAMESPACE_ID::NullValue >(0); +} +inline PROTOBUF_NAMESPACE_ID::NullValue Value::null_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.null_value) + return _internal_null_value(); } -inline void Value::set_null_value(::google::protobuf::NullValue value) { - if (!has_null_value()) { +inline void Value::_internal_set_null_value(PROTOBUF_NAMESPACE_ID::NullValue value) { + if (!_internal_has_null_value()) { clear_kind(); set_has_null_value(); } kind_.null_value_ = value; +} +inline void Value::set_null_value(PROTOBUF_NAMESPACE_ID::NullValue value) { // @@protoc_insertion_point(field_set:google.protobuf.Value.null_value) + _internal_set_null_value(value); } // double number_value = 2; -inline bool Value::has_number_value() const { +inline bool Value::_internal_has_number_value() const { return kind_case() == kNumberValue; } +inline bool Value::has_number_value() const { + return _internal_has_number_value(); +} inline void Value::set_has_number_value() { _oneof_case_[0] = kNumberValue; } inline void Value::clear_number_value() { - if (has_number_value()) { + if (_internal_has_number_value()) { kind_.number_value_ = 0; clear_has_kind(); } } -inline double Value::number_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.Value.number_value) - if (has_number_value()) { +inline double Value::_internal_number_value() const { + if (_internal_has_number_value()) { return kind_.number_value_; } return 0; } -inline void Value::set_number_value(double value) { - if (!has_number_value()) { +inline void Value::_internal_set_number_value(double value) { + if (!_internal_has_number_value()) { clear_kind(); set_has_number_value(); } kind_.number_value_ = value; +} +inline double Value::number_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.number_value) + return _internal_number_value(); +} +inline void Value::set_number_value(double value) { + _internal_set_number_value(value); // @@protoc_insertion_point(field_set:google.protobuf.Value.number_value) } // string string_value = 3; -inline bool Value::has_string_value() const { +inline bool Value::_internal_has_string_value() const { return kind_case() == kStringValue; } +inline bool Value::has_string_value() const { + return _internal_has_string_value(); +} inline void Value::set_has_string_value() { _oneof_case_[0] = kStringValue; } inline void Value::clear_string_value() { - if (has_string_value()) { - kind_.string_value_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - GetArenaNoVirtual()); + if (_internal_has_string_value()) { + kind_.string_value_.Destroy(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); clear_has_kind(); } } -inline const ::std::string& Value::string_value() const { +inline const std::string& Value::string_value() const { // @@protoc_insertion_point(field_get:google.protobuf.Value.string_value) - if (has_string_value()) { + return _internal_string_value(); +} +inline void Value::set_string_value(const std::string& value) { + _internal_set_string_value(value); + // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value) +} +inline std::string* Value::mutable_string_value() { + // @@protoc_insertion_point(field_mutable:google.protobuf.Value.string_value) + return _internal_mutable_string_value(); +} +inline const std::string& Value::_internal_string_value() const { + if (_internal_has_string_value()) { return kind_.string_value_.Get(); } - return *&::google::protobuf::internal::GetEmptyStringAlreadyInited(); + return ::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(); } -inline void Value::set_string_value(const ::std::string& value) { - if (!has_string_value()) { +inline void Value::_internal_set_string_value(const std::string& value) { + if (!_internal_has_string_value()) { clear_kind(); set_has_string_value(); - kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } - kind_.string_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, - GetArenaNoVirtual()); - // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value) + kind_.string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } -#if LANG_CXX11 -inline void Value::set_string_value(::std::string&& value) { +inline void Value::set_string_value(std::string&& value) { // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value) - if (!has_string_value()) { + if (!_internal_has_string_value()) { clear_kind(); set_has_string_value(); - kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } kind_.string_value_.Set( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Value.string_value) } -#endif inline void Value::set_string_value(const char* value) { - GOOGLE_DCHECK(value != NULL); - if (!has_string_value()) { + GOOGLE_DCHECK(value != nullptr); + if (!_internal_has_string_value()) { clear_kind(); set_has_string_value(); - kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } - kind_.string_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(value), GetArenaNoVirtual()); + kind_.string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, + ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Value.string_value) } inline void Value::set_string_value(const char* value, size_t size) { - if (!has_string_value()) { + if (!_internal_has_string_value()) { clear_kind(); set_has_string_value(); - kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } - kind_.string_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string( + kind_.string_value_.Set( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), - GetArenaNoVirtual()); + GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Value.string_value) } -inline ::std::string* Value::mutable_string_value() { - if (!has_string_value()) { +inline std::string* Value::_internal_mutable_string_value() { + if (!_internal_has_string_value()) { clear_kind(); set_has_string_value(); - kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } - return kind_.string_value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - GetArenaNoVirtual()); - // @@protoc_insertion_point(field_mutable:google.protobuf.Value.string_value) + return kind_.string_value_.Mutable( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } -inline ::std::string* Value::release_string_value() { +inline std::string* Value::release_string_value() { // @@protoc_insertion_point(field_release:google.protobuf.Value.string_value) - if (has_string_value()) { + if (_internal_has_string_value()) { clear_has_kind(); - return kind_.string_value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - GetArenaNoVirtual()); + return kind_.string_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } else { - return NULL; + return nullptr; } } -inline ::std::string* Value::unsafe_arena_release_string_value() { - // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Value.string_value) - GOOGLE_DCHECK(GetArenaNoVirtual() != NULL); - if (has_string_value()) { - clear_has_kind(); - return kind_.string_value_.UnsafeArenaRelease( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); - } else { - return NULL; - } -} -inline void Value::set_allocated_string_value(::std::string* string_value) { - if (!has_string_value()) { - kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +inline void Value::set_allocated_string_value(std::string* string_value) { + if (has_kind()) { + clear_kind(); } - clear_kind(); - if (string_value != NULL) { + if (string_value != nullptr) { set_has_string_value(); - kind_.string_value_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value, - GetArenaNoVirtual()); + kind_.string_value_.UnsafeSetDefault(string_value); + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); + if (arena != nullptr) { + arena->Own(string_value); + } } // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.string_value) } -inline void Value::unsafe_arena_set_allocated_string_value(::std::string* string_value) { - GOOGLE_DCHECK(GetArenaNoVirtual() != NULL); - if (!has_string_value()) { - kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } - clear_kind(); - if (string_value) { - set_has_string_value(); - kind_.string_value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value, GetArenaNoVirtual()); - } - // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Value.string_value) -} // bool bool_value = 4; -inline bool Value::has_bool_value() const { +inline bool Value::_internal_has_bool_value() const { return kind_case() == kBoolValue; } +inline bool Value::has_bool_value() const { + return _internal_has_bool_value(); +} inline void Value::set_has_bool_value() { _oneof_case_[0] = kBoolValue; } inline void Value::clear_bool_value() { - if (has_bool_value()) { + if (_internal_has_bool_value()) { kind_.bool_value_ = false; clear_has_kind(); } } -inline bool Value::bool_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.Value.bool_value) - if (has_bool_value()) { +inline bool Value::_internal_bool_value() const { + if (_internal_has_bool_value()) { return kind_.bool_value_; } return false; } -inline void Value::set_bool_value(bool value) { - if (!has_bool_value()) { +inline void Value::_internal_set_bool_value(bool value) { + if (!_internal_has_bool_value()) { clear_kind(); set_has_bool_value(); } kind_.bool_value_ = value; +} +inline bool Value::bool_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.bool_value) + return _internal_bool_value(); +} +inline void Value::set_bool_value(bool value) { + _internal_set_bool_value(value); // @@protoc_insertion_point(field_set:google.protobuf.Value.bool_value) } // .google.protobuf.Struct struct_value = 5; -inline bool Value::has_struct_value() const { +inline bool Value::_internal_has_struct_value() const { return kind_case() == kStructValue; } +inline bool Value::has_struct_value() const { + return _internal_has_struct_value(); +} inline void Value::set_has_struct_value() { _oneof_case_[0] = kStructValue; } inline void Value::clear_struct_value() { - if (has_struct_value()) { - if (GetArenaNoVirtual() == NULL) { + if (_internal_has_struct_value()) { + if (GetArena() == nullptr) { delete kind_.struct_value_; } clear_has_kind(); } } -inline const ::google::protobuf::Struct& Value::struct_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.Value.struct_value) - return has_struct_value() - ? *kind_.struct_value_ - : ::google::protobuf::Struct::default_instance(); -} -inline ::google::protobuf::Struct* Value::mutable_struct_value() { - if (!has_struct_value()) { - clear_kind(); - set_has_struct_value(); - kind_.struct_value_ = - ::google::protobuf::Arena::CreateMessage< ::google::protobuf::Struct >( - GetArenaNoVirtual()); - } - // @@protoc_insertion_point(field_mutable:google.protobuf.Value.struct_value) - return kind_.struct_value_; -} -inline ::google::protobuf::Struct* Value::release_struct_value() { +inline PROTOBUF_NAMESPACE_ID::Struct* Value::release_struct_value() { // @@protoc_insertion_point(field_release:google.protobuf.Value.struct_value) - if (has_struct_value()) { + if (_internal_has_struct_value()) { clear_has_kind(); - if (GetArenaNoVirtual() != NULL) { - ::google::protobuf::Struct* temp = new ::google::protobuf::Struct(*kind_.struct_value_); - kind_.struct_value_ = NULL; - return temp; - } else { - ::google::protobuf::Struct* temp = kind_.struct_value_; - kind_.struct_value_ = NULL; - return temp; + PROTOBUF_NAMESPACE_ID::Struct* temp = kind_.struct_value_; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); } + kind_.struct_value_ = nullptr; + return temp; } else { - return NULL; + return nullptr; } } -inline void Value::set_allocated_struct_value(::google::protobuf::Struct* struct_value) { - clear_kind(); - if (struct_value) { - if (GetArenaNoVirtual() != NULL && - ::google::protobuf::Arena::GetArena(struct_value) == NULL) { - GetArenaNoVirtual()->Own(struct_value); - } else if (GetArenaNoVirtual() != - ::google::protobuf::Arena::GetArena(struct_value)) { - ::google::protobuf::Struct* new_struct_value = - ::google::protobuf::Arena::CreateMessage< ::google::protobuf::Struct >( - GetArenaNoVirtual()); - new_struct_value->CopyFrom(*struct_value); - struct_value = new_struct_value; - } - set_has_struct_value(); - kind_.struct_value_ = struct_value; - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.struct_value) +inline const PROTOBUF_NAMESPACE_ID::Struct& Value::_internal_struct_value() const { + return _internal_has_struct_value() + ? *kind_.struct_value_ + : reinterpret_cast< PROTOBUF_NAMESPACE_ID::Struct&>(PROTOBUF_NAMESPACE_ID::_Struct_default_instance_); +} +inline const PROTOBUF_NAMESPACE_ID::Struct& Value::struct_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.struct_value) + return _internal_struct_value(); } -inline ::google::protobuf::Struct* Value::unsafe_arena_release_struct_value() { +inline PROTOBUF_NAMESPACE_ID::Struct* Value::unsafe_arena_release_struct_value() { // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Value.struct_value) - if (has_struct_value()) { + if (_internal_has_struct_value()) { clear_has_kind(); - ::google::protobuf::Struct* temp = kind_.struct_value_; - kind_.struct_value_ = NULL; + PROTOBUF_NAMESPACE_ID::Struct* temp = kind_.struct_value_; + kind_.struct_value_ = nullptr; return temp; } else { - return NULL; + return nullptr; } } -inline void Value::unsafe_arena_set_allocated_struct_value(::google::protobuf::Struct* struct_value) { +inline void Value::unsafe_arena_set_allocated_struct_value(PROTOBUF_NAMESPACE_ID::Struct* struct_value) { clear_kind(); if (struct_value) { set_has_struct_value(); @@ -905,87 +1022,72 @@ inline void Value::unsafe_arena_set_allocated_struct_value(::google::protobuf:: } // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Value.struct_value) } +inline PROTOBUF_NAMESPACE_ID::Struct* Value::_internal_mutable_struct_value() { + if (!_internal_has_struct_value()) { + clear_kind(); + set_has_struct_value(); + kind_.struct_value_ = CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::Struct >(GetArena()); + } + return kind_.struct_value_; +} +inline PROTOBUF_NAMESPACE_ID::Struct* Value::mutable_struct_value() { + // @@protoc_insertion_point(field_mutable:google.protobuf.Value.struct_value) + return _internal_mutable_struct_value(); +} // .google.protobuf.ListValue list_value = 6; -inline bool Value::has_list_value() const { +inline bool Value::_internal_has_list_value() const { return kind_case() == kListValue; } +inline bool Value::has_list_value() const { + return _internal_has_list_value(); +} inline void Value::set_has_list_value() { _oneof_case_[0] = kListValue; } inline void Value::clear_list_value() { - if (has_list_value()) { - if (GetArenaNoVirtual() == NULL) { + if (_internal_has_list_value()) { + if (GetArena() == nullptr) { delete kind_.list_value_; } clear_has_kind(); } } -inline const ::google::protobuf::ListValue& Value::list_value() const { - // @@protoc_insertion_point(field_get:google.protobuf.Value.list_value) - return has_list_value() - ? *kind_.list_value_ - : ::google::protobuf::ListValue::default_instance(); -} -inline ::google::protobuf::ListValue* Value::mutable_list_value() { - if (!has_list_value()) { - clear_kind(); - set_has_list_value(); - kind_.list_value_ = - ::google::protobuf::Arena::CreateMessage< ::google::protobuf::ListValue >( - GetArenaNoVirtual()); - } - // @@protoc_insertion_point(field_mutable:google.protobuf.Value.list_value) - return kind_.list_value_; -} -inline ::google::protobuf::ListValue* Value::release_list_value() { +inline PROTOBUF_NAMESPACE_ID::ListValue* Value::release_list_value() { // @@protoc_insertion_point(field_release:google.protobuf.Value.list_value) - if (has_list_value()) { + if (_internal_has_list_value()) { clear_has_kind(); - if (GetArenaNoVirtual() != NULL) { - ::google::protobuf::ListValue* temp = new ::google::protobuf::ListValue(*kind_.list_value_); - kind_.list_value_ = NULL; - return temp; - } else { - ::google::protobuf::ListValue* temp = kind_.list_value_; - kind_.list_value_ = NULL; - return temp; + PROTOBUF_NAMESPACE_ID::ListValue* temp = kind_.list_value_; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); } + kind_.list_value_ = nullptr; + return temp; } else { - return NULL; + return nullptr; } } -inline void Value::set_allocated_list_value(::google::protobuf::ListValue* list_value) { - clear_kind(); - if (list_value) { - if (GetArenaNoVirtual() != NULL && - ::google::protobuf::Arena::GetArena(list_value) == NULL) { - GetArenaNoVirtual()->Own(list_value); - } else if (GetArenaNoVirtual() != - ::google::protobuf::Arena::GetArena(list_value)) { - ::google::protobuf::ListValue* new_list_value = - ::google::protobuf::Arena::CreateMessage< ::google::protobuf::ListValue >( - GetArenaNoVirtual()); - new_list_value->CopyFrom(*list_value); - list_value = new_list_value; - } - set_has_list_value(); - kind_.list_value_ = list_value; - } - // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.list_value) +inline const PROTOBUF_NAMESPACE_ID::ListValue& Value::_internal_list_value() const { + return _internal_has_list_value() + ? *kind_.list_value_ + : reinterpret_cast< PROTOBUF_NAMESPACE_ID::ListValue&>(PROTOBUF_NAMESPACE_ID::_ListValue_default_instance_); +} +inline const PROTOBUF_NAMESPACE_ID::ListValue& Value::list_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.list_value) + return _internal_list_value(); } -inline ::google::protobuf::ListValue* Value::unsafe_arena_release_list_value() { +inline PROTOBUF_NAMESPACE_ID::ListValue* Value::unsafe_arena_release_list_value() { // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Value.list_value) - if (has_list_value()) { + if (_internal_has_list_value()) { clear_has_kind(); - ::google::protobuf::ListValue* temp = kind_.list_value_; - kind_.list_value_ = NULL; + PROTOBUF_NAMESPACE_ID::ListValue* temp = kind_.list_value_; + kind_.list_value_ = nullptr; return temp; } else { - return NULL; + return nullptr; } } -inline void Value::unsafe_arena_set_allocated_list_value(::google::protobuf::ListValue* list_value) { +inline void Value::unsafe_arena_set_allocated_list_value(PROTOBUF_NAMESPACE_ID::ListValue* list_value) { clear_kind(); if (list_value) { set_has_list_value(); @@ -993,6 +1095,18 @@ inline void Value::unsafe_arena_set_allocated_list_value(::google::protobuf::Li } // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Value.list_value) } +inline PROTOBUF_NAMESPACE_ID::ListValue* Value::_internal_mutable_list_value() { + if (!_internal_has_list_value()) { + clear_kind(); + set_has_list_value(); + kind_.list_value_ = CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::ListValue >(GetArena()); + } + return kind_.list_value_; +} +inline PROTOBUF_NAMESPACE_ID::ListValue* Value::mutable_list_value() { + // @@protoc_insertion_point(field_mutable:google.protobuf.Value.list_value) + return _internal_mutable_list_value(); +} inline bool Value::has_kind() const { return kind_case() != KIND_NOT_SET; @@ -1008,30 +1122,39 @@ inline Value::KindCase Value::kind_case() const { // ListValue // repeated .google.protobuf.Value values = 1; -inline int ListValue::values_size() const { +inline int ListValue::_internal_values_size() const { return values_.size(); } +inline int ListValue::values_size() const { + return _internal_values_size(); +} inline void ListValue::clear_values() { values_.Clear(); } -inline const ::google::protobuf::Value& ListValue::values(int index) const { - // @@protoc_insertion_point(field_get:google.protobuf.ListValue.values) - return values_.Get(index); -} -inline ::google::protobuf::Value* ListValue::mutable_values(int index) { +inline PROTOBUF_NAMESPACE_ID::Value* ListValue::mutable_values(int index) { // @@protoc_insertion_point(field_mutable:google.protobuf.ListValue.values) return values_.Mutable(index); } -inline ::google::protobuf::Value* ListValue::add_values() { - // @@protoc_insertion_point(field_add:google.protobuf.ListValue.values) - return values_.Add(); -} -inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >* +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Value >* ListValue::mutable_values() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.ListValue.values) return &values_; } -inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >& +inline const PROTOBUF_NAMESPACE_ID::Value& ListValue::_internal_values(int index) const { + return values_.Get(index); +} +inline const PROTOBUF_NAMESPACE_ID::Value& ListValue::values(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ListValue.values) + return _internal_values(index); +} +inline PROTOBUF_NAMESPACE_ID::Value* ListValue::_internal_add_values() { + return values_.Add(); +} +inline PROTOBUF_NAMESPACE_ID::Value* ListValue::add_values() { + // @@protoc_insertion_point(field_add:google.protobuf.ListValue.values) + return _internal_add_values(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::Value >& ListValue::values() const { // @@protoc_insertion_point(field_list:google.protobuf.ListValue.values) return values_; @@ -1040,7 +1163,6 @@ ListValue::values() const { #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ -#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // ------------------------------------------------------------------- // ------------------------------------------------------------------- @@ -1050,22 +1172,19 @@ ListValue::values() const { // @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE -} // namespace protobuf -} // namespace google - -namespace google { -namespace protobuf { +PROTOBUF_NAMESPACE_OPEN -template <> struct is_proto_enum< ::google::protobuf::NullValue> : ::google::protobuf::internal::true_type {}; +template <> struct is_proto_enum< PROTOBUF_NAMESPACE_ID::NullValue> : ::std::true_type {}; template <> -inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::NullValue>() { - return ::google::protobuf::NullValue_descriptor(); +inline const EnumDescriptor* GetEnumDescriptor< PROTOBUF_NAMESPACE_ID::NullValue>() { + return PROTOBUF_NAMESPACE_ID::NullValue_descriptor(); } -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) -#endif // PROTOBUF_google_2fprotobuf_2fstruct_2eproto__INCLUDED +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto diff --git a/src/google/protobuf/struct.proto b/src/google/protobuf/struct.proto index 7d7808e7fbb69..545215c25276c 100644 --- a/src/google/protobuf/struct.proto +++ b/src/google/protobuf/struct.proto @@ -34,13 +34,12 @@ package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/struct;structpb"; +option go_package = "google.golang.org/protobuf/types/known/structpb"; option java_package = "com.google.protobuf"; option java_outer_classname = "StructProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; - // `Struct` represents a structured data value, consisting of fields // which map to dynamically typed values. In some languages, `Struct` // might be supported by a native representation. For example, in diff --git a/src/google/protobuf/stubs/atomic_sequence_num.h b/src/google/protobuf/stubs/atomic_sequence_num.h deleted file mode 100644 index bb20942f2f770..0000000000000 --- a/src/google/protobuf/stubs/atomic_sequence_num.h +++ /dev/null @@ -1,54 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2014 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#ifndef GOOGLE_PROTOBUF_ATOMIC_SEQUENCE_NUM_H_ -#define GOOGLE_PROTOBUF_ATOMIC_SEQUENCE_NUM_H_ - -#include - -namespace google { -namespace protobuf { -namespace internal { - -class SequenceNumber { - public: - SequenceNumber() : word_(0) {} - - AtomicWord GetNext() { - return NoBarrier_AtomicIncrement(&word_, 1) - 1; - } - private: - AtomicWord word_; -}; - -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_ATOMIC_SEQUENCE_NUM_H_ diff --git a/src/google/protobuf/stubs/atomicops.h b/src/google/protobuf/stubs/atomicops.h deleted file mode 100644 index 75aee30640044..0000000000000 --- a/src/google/protobuf/stubs/atomicops.h +++ /dev/null @@ -1,249 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2012 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. - -// The routines exported by this module are subtle. If you use them, even if -// you get the code right, it will depend on careful reasoning about atomicity -// and memory ordering; it will be less readable, and harder to maintain. If -// you plan to use these routines, you should have a good reason, such as solid -// evidence that performance would otherwise suffer, or there being no -// alternative. You should assume only properties explicitly guaranteed by the -// specifications in this file. You are almost certainly _not_ writing code -// just for the x86; if you assume x86 semantics, x86 hardware bugs and -// implementations on other archtectures will cause your code to break. If you -// do not know what you are doing, avoid these routines, and use a Mutex. -// -// It is incorrect to make direct assignments to/from an atomic variable. -// You should use one of the Load or Store routines. The NoBarrier -// versions are provided when no barriers are needed: -// NoBarrier_Store() -// NoBarrier_Load() -// Although there are currently no compiler enforcement, you are encouraged -// to use these. - -// This header and the implementations for each platform (located in -// atomicops_internals_*) must be kept in sync with the upstream code (V8). - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_H_ - -// Don't include this file for people not concerned about thread safety. -#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY - -#include -#include - -namespace google { -namespace protobuf { -namespace internal { - -#if defined(GOOGLE_PROTOBUF_ARCH_POWER) -#if defined(_LP64) || defined(__LP64__) -typedef int32 Atomic32; -typedef intptr_t Atomic64; -#else -typedef intptr_t Atomic32; -typedef int64 Atomic64; -#endif -#else -typedef int32 Atomic32; -#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT -// We need to be able to go between Atomic64 and AtomicWord implicitly. This -// means Atomic64 and AtomicWord should be the same type on 64-bit. -#if defined(__ILP32__) || defined(GOOGLE_PROTOBUF_OS_NACL) -// NaCl's intptr_t is not actually 64-bits on 64-bit! -// http://code.google.com/p/nativeclient/issues/detail?id=1162 -// sparcv9's pointer type is 32bits -typedef int64 Atomic64; -#else -typedef intptr_t Atomic64; -#endif -#endif -#endif - -// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or -// Atomic64 routines below, depending on your architecture. -typedef intptr_t AtomicWord; - -// Atomically execute: -// result = *ptr; -// if (*ptr == old_value) -// *ptr = new_value; -// return result; -// -// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". -// Always return the old value of "*ptr" -// -// This routine implies no memory barriers. -Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value); - -// Atomically store new_value into *ptr, returning the previous value held in -// *ptr. This routine implies no memory barriers. -Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); - -// Atomically increment *ptr by "increment". Returns the new value of -// *ptr with the increment applied. This routine implies no memory barriers. -Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment); - -Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment); - -// These following lower-level operations are typically useful only to people -// implementing higher-level synchronization operations like spinlocks, -// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or -// a store with appropriate memory-ordering instructions. "Acquire" operations -// ensure that no later memory access can be reordered ahead of the operation. -// "Release" operations ensure that no previous memory access can be reordered -// after the operation. "Barrier" operations have both "Acquire" and "Release" -// semantics. A MemoryBarrierInternal() has "Barrier" semantics, but does no -// memory access. -Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value); -Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value); - -// This function was renamed from MemoryBarrier to MemoryBarrierInternal -// because MemoryBarrier is a define in Windows ARM builds and we do not -// undefine it because we call it from this function. -void MemoryBarrierInternal(); -void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value); -void Acquire_Store(volatile Atomic32* ptr, Atomic32 value); -void Release_Store(volatile Atomic32* ptr, Atomic32 value); - -Atomic32 NoBarrier_Load(volatile const Atomic32* ptr); -Atomic32 Acquire_Load(volatile const Atomic32* ptr); -Atomic32 Release_Load(volatile const Atomic32* ptr); - -// 64-bit atomic operations (only available on 64-bit processors). -#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT -Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value); -Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value); -Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); -Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); - -Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value); -Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value); -void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value); -void Acquire_Store(volatile Atomic64* ptr, Atomic64 value); -void Release_Store(volatile Atomic64* ptr, Atomic64 value); -Atomic64 NoBarrier_Load(volatile const Atomic64* ptr); -Atomic64 Acquire_Load(volatile const Atomic64* ptr); -Atomic64 Release_Load(volatile const Atomic64* ptr); -#endif // GOOGLE_PROTOBUF_ARCH_64_BIT - -} // namespace internal -} // namespace protobuf -} // namespace google - -// Include our platform specific implementation. -#define GOOGLE_PROTOBUF_ATOMICOPS_ERROR \ -"Atomic operations are not supported on your platform" - -// ThreadSanitizer, http://clang.llvm.org/docs/ThreadSanitizer.html. -#if defined(THREAD_SANITIZER) -#include -// MSVC. -#elif defined(_MSC_VER) -#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64) || defined(GOOGLE_PROTOBUF_ARCH_ARM) -#include -#else -#error GOOGLE_PROTOBUF_ATOMICOPS_ERROR -#endif - -// Solaris -#elif defined(GOOGLE_PROTOBUF_OS_SOLARIS) -#include - -// AIX -#elif defined(GOOGLE_PROTOBUF_OS_AIX) -#include - -// GCC. -#elif defined(__GNUC__) -#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64) -#include -#elif defined(GOOGLE_PROTOBUF_ARCH_ARM) && defined(__linux__) -#if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)) -#include -#else -#include -#endif -#elif defined(GOOGLE_PROTOBUF_ARCH_AARCH64) -#include -#elif defined(GOOGLE_PROTOBUF_ARCH_ARM_QNX) -#include -#elif defined(GOOGLE_PROTOBUF_ARCH_MIPS) || defined(GOOGLE_PROTOBUF_ARCH_MIPS64) -#include -#elif defined(GOOGLE_PROTOBUF_ARCH_POWER) -#include -#elif defined(__native_client__) -// The static_asserts in the C++11 atomics implementation cause it to fail -// with certain compilers, e.g. nvcc on macOS. Don't use elsewhere unless -// the TODO in that file is addressed. -#include -#elif defined(GOOGLE_PROTOBUF_ARCH_PPC) -#include -#elif (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)) -#include -#elif defined(__clang__) -#if __has_extension(c_atomic) -#include -#else -#error GOOGLE_PROTOBUF_ATOMICOPS_ERROR -#endif -#else -#error GOOGLE_PROTOBUF_ATOMICOPS_ERROR -#endif - -// Unknown. -#else -#error GOOGLE_PROTOBUF_ATOMICOPS_ERROR -#endif - -// On some platforms we need additional declarations to make AtomicWord -// compatible with our other Atomic* types. -#if defined(GOOGLE_PROTOBUF_OS_APPLE) -#include -#endif - -#undef GOOGLE_PROTOBUF_ATOMICOPS_ERROR - -#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h b/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h deleted file mode 100644 index 9a69d21ad68d5..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h +++ /dev/null @@ -1,325 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2012 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This file is an internal atomic implementation, use atomicops.h instead. - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_ - -namespace google { -namespace protobuf { -namespace internal { - -inline void MemoryBarrierInternal() { - __asm__ __volatile__ ("dmb ish" ::: "memory"); // NOLINT -} - -// NoBarrier versions of the operation include "memory" in the clobber list. -// This is not required for direct usage of the NoBarrier versions of the -// operations. However this is required for correctness when they are used as -// part of the Acquire or Release versions, to ensure that nothing from outside -// the call is reordered between the operation and the memory barrier. This does -// not change the code generated, so has no or minimal impact on the -// NoBarrier operations. - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev; - int32_t temp; - - __asm__ __volatile__ ( // NOLINT - "0: \n\t" - "ldxr %w[prev], %[ptr] \n\t" // Load the previous value. - "cmp %w[prev], %w[old_value] \n\t" - "bne 1f \n\t" - "stxr %w[temp], %w[new_value], %[ptr] \n\t" // Try to store the new value. - "cbnz %w[temp], 0b \n\t" // Retry if it did not work. - "1: \n\t" - : [prev]"=&r" (prev), - [temp]"=&r" (temp), - [ptr]"+Q" (*ptr) - : [old_value]"IJr" (old_value), - [new_value]"r" (new_value) - : "cc", "memory" - ); // NOLINT - - return prev; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - Atomic32 result; - int32_t temp; - - __asm__ __volatile__ ( // NOLINT - "0: \n\t" - "ldxr %w[result], %[ptr] \n\t" // Load the previous value. - "stxr %w[temp], %w[new_value], %[ptr] \n\t" // Try to store the new value. - "cbnz %w[temp], 0b \n\t" // Retry if it did not work. - : [result]"=&r" (result), - [temp]"=&r" (temp), - [ptr]"+Q" (*ptr) - : [new_value]"r" (new_value) - : "memory" - ); // NOLINT - - return result; -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 result; - int32_t temp; - - __asm__ __volatile__ ( // NOLINT - "0: \n\t" - "ldxr %w[result], %[ptr] \n\t" // Load the previous value. - "add %w[result], %w[result], %w[increment]\n\t" - "stxr %w[temp], %w[result], %[ptr] \n\t" // Try to store the result. - "cbnz %w[temp], 0b \n\t" // Retry on failure. - : [result]"=&r" (result), - [temp]"=&r" (temp), - [ptr]"+Q" (*ptr) - : [increment]"IJr" (increment) - : "memory" - ); // NOLINT - - return result; -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - MemoryBarrierInternal(); - Atomic32 result = NoBarrier_AtomicIncrement(ptr, increment); - MemoryBarrierInternal(); - - return result; -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - MemoryBarrierInternal(); - - return prev; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - MemoryBarrierInternal(); - Atomic32 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - - return prev; -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; - MemoryBarrierInternal(); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - __asm__ __volatile__ ( // NOLINT - "stlr %w[value], %[ptr] \n\t" - : [ptr]"=Q" (*ptr) - : [value]"r" (value) - : "memory" - ); // NOLINT -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return *ptr; -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 value; - - __asm__ __volatile__ ( // NOLINT - "ldar %w[value], %[ptr] \n\t" - : [value]"=r" (value) - : [ptr]"Q" (*ptr) - : "memory" - ); // NOLINT - - return value; -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - MemoryBarrierInternal(); - return *ptr; -} - -// 64-bit versions of the operations. -// See the 32-bit versions for comments. - -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 prev; - int32_t temp; - - __asm__ __volatile__ ( // NOLINT - "0: \n\t" - "ldxr %[prev], %[ptr] \n\t" - "cmp %[prev], %[old_value] \n\t" - "bne 1f \n\t" - "stxr %w[temp], %[new_value], %[ptr] \n\t" - "cbnz %w[temp], 0b \n\t" - "1: \n\t" - : [prev]"=&r" (prev), - [temp]"=&r" (temp), - [ptr]"+Q" (*ptr) - : [old_value]"IJr" (old_value), - [new_value]"r" (new_value) - : "cc", "memory" - ); // NOLINT - - return prev; -} - -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - Atomic64 result; - int32_t temp; - - __asm__ __volatile__ ( // NOLINT - "0: \n\t" - "ldxr %[result], %[ptr] \n\t" - "stxr %w[temp], %[new_value], %[ptr] \n\t" - "cbnz %w[temp], 0b \n\t" - : [result]"=&r" (result), - [temp]"=&r" (temp), - [ptr]"+Q" (*ptr) - : [new_value]"r" (new_value) - : "memory" - ); // NOLINT - - return result; -} - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - Atomic64 result; - int32_t temp; - - __asm__ __volatile__ ( // NOLINT - "0: \n\t" - "ldxr %[result], %[ptr] \n\t" - "add %[result], %[result], %[increment] \n\t" - "stxr %w[temp], %[result], %[ptr] \n\t" - "cbnz %w[temp], 0b \n\t" - : [result]"=&r" (result), - [temp]"=&r" (temp), - [ptr]"+Q" (*ptr) - : [increment]"IJr" (increment) - : "memory" - ); // NOLINT - - return result; -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - MemoryBarrierInternal(); - Atomic64 result = NoBarrier_AtomicIncrement(ptr, increment); - MemoryBarrierInternal(); - - return result; -} - -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - MemoryBarrierInternal(); - - return prev; -} - -inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - MemoryBarrierInternal(); - Atomic64 prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - - return prev; -} - -inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; - MemoryBarrierInternal(); -} - -inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { - __asm__ __volatile__ ( // NOLINT - "stlr %x[value], %[ptr] \n\t" - : [ptr]"=Q" (*ptr) - : [value]"r" (value) - : "memory" - ); // NOLINT -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { - return *ptr; -} - -inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { - Atomic64 value; - - __asm__ __volatile__ ( // NOLINT - "ldar %x[value], %[ptr] \n\t" - : [value]"=r" (value) - : [ptr]"Q" (*ptr) - : "memory" - ); // NOLINT - - return value; -} - -inline Atomic64 Release_Load(volatile const Atomic64* ptr) { - MemoryBarrierInternal(); - return *ptr; -} - -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h b/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h deleted file mode 100644 index 6e2de67fa5a11..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h +++ /dev/null @@ -1,151 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2012 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This file is an internal atomic implementation, use atomicops.h instead. -// -// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears. - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_ - -namespace google { -namespace protobuf { -namespace internal { - -// 0xffff0fc0 is the hard coded address of a function provided by -// the kernel which implements an atomic compare-exchange. On older -// ARM architecture revisions (pre-v6) this may be implemented using -// a syscall. This address is stable, and in active use (hard coded) -// by at least glibc-2.7 and the Android C library. -typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value, - Atomic32 new_value, - volatile Atomic32* ptr); -LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak)) = - (LinuxKernelCmpxchgFunc) 0xffff0fc0; - -typedef void (*LinuxKernelMemoryBarrierFunc)(void); -LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) = - (LinuxKernelMemoryBarrierFunc) 0xffff0fa0; - - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev_value = *ptr; - do { - if (!pLinuxKernelCmpxchg(old_value, new_value, - const_cast(ptr))) { - return old_value; - } - prev_value = *ptr; - } while (prev_value == old_value); - return prev_value; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - Atomic32 old_value; - do { - old_value = *ptr; - } while (pLinuxKernelCmpxchg(old_value, new_value, - const_cast(ptr))); - return old_value; -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return Barrier_AtomicIncrement(ptr, increment); -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - for (;;) { - // Atomic exchange the old value with an incremented one. - Atomic32 old_value = *ptr; - Atomic32 new_value = old_value + increment; - if (pLinuxKernelCmpxchg(old_value, new_value, - const_cast(ptr)) == 0) { - // The exchange took place as expected. - return new_value; - } - // Otherwise, *ptr changed mid-loop and we need to retry. - } -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; -} - -inline void MemoryBarrierInternal() { - pLinuxKernelMemoryBarrier(); -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; - MemoryBarrierInternal(); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - MemoryBarrierInternal(); - *ptr = value; -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return *ptr; -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 value = *ptr; - MemoryBarrierInternal(); - return value; -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - MemoryBarrierInternal(); - return *ptr; -} - -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_arm_qnx.h b/src/google/protobuf/stubs/atomicops_internals_arm_qnx.h deleted file mode 100644 index cd97e0c994281..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_arm_qnx.h +++ /dev/null @@ -1,146 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2012 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This file is an internal atomic implementation, use atomicops.h instead. - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_ - -// For _smp_cmpxchg() -#include - -namespace google { -namespace protobuf { -namespace internal { - -inline Atomic32 QNXCmpxchg(Atomic32 old_value, - Atomic32 new_value, - volatile Atomic32* ptr) { - return static_cast( - _smp_cmpxchg((volatile unsigned *)ptr, - (unsigned)old_value, - (unsigned)new_value)); -} - - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev_value = *ptr; - do { - if (!QNXCmpxchg(old_value, new_value, - const_cast(ptr))) { - return old_value; - } - prev_value = *ptr; - } while (prev_value == old_value); - return prev_value; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - Atomic32 old_value; - do { - old_value = *ptr; - } while (QNXCmpxchg(old_value, new_value, - const_cast(ptr))); - return old_value; -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return Barrier_AtomicIncrement(ptr, increment); -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - for (;;) { - // Atomic exchange the old value with an incremented one. - Atomic32 old_value = *ptr; - Atomic32 new_value = old_value + increment; - if (QNXCmpxchg(old_value, new_value, - const_cast(ptr)) == 0) { - // The exchange took place as expected. - return new_value; - } - // Otherwise, *ptr changed mid-loop and we need to retry. - } -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; -} - -inline void MemoryBarrierInternal() { - __sync_synchronize(); -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; - MemoryBarrierInternal(); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - MemoryBarrierInternal(); - *ptr = value; -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return *ptr; -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 value = *ptr; - MemoryBarrierInternal(); - return value; -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - MemoryBarrierInternal(); - return *ptr; -} - -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h b/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h deleted file mode 100644 index eb198ff5cc236..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h +++ /dev/null @@ -1,122 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2012 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This file is an internal atomic implementation, use atomicops.h instead. - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ - -// AtomicWord is a synonym for intptr_t, and Atomic32 is a synonym for int32, -// which in turn means int. On some LP32 platforms, intptr_t is an int, but -// on others, it's a long. When AtomicWord and Atomic32 are based on different -// fundamental types, their pointers are incompatible. -// -// This file defines function overloads to allow both AtomicWord and Atomic32 -// data to be used with this interface. -// -// On LP64 platforms, AtomicWord and Atomic64 are both always long, -// so this problem doesn't occur. - -#if !defined(GOOGLE_PROTOBUF_ARCH_64_BIT) - -namespace google { -namespace protobuf { -namespace internal { - -inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr, - AtomicWord old_value, - AtomicWord new_value) { - return NoBarrier_CompareAndSwap( - reinterpret_cast(ptr), old_value, new_value); -} - -inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr, - AtomicWord new_value) { - return NoBarrier_AtomicExchange( - reinterpret_cast(ptr), new_value); -} - -inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr, - AtomicWord increment) { - return NoBarrier_AtomicIncrement( - reinterpret_cast(ptr), increment); -} - -inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr, - AtomicWord increment) { - return Barrier_AtomicIncrement( - reinterpret_cast(ptr), increment); -} - -inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, - AtomicWord old_value, - AtomicWord new_value) { - return Acquire_CompareAndSwap( - reinterpret_cast(ptr), old_value, new_value); -} - -inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, - AtomicWord old_value, - AtomicWord new_value) { - return Release_CompareAndSwap( - reinterpret_cast(ptr), old_value, new_value); -} - -inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) { - NoBarrier_Store(reinterpret_cast(ptr), value); -} - -inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) { - return Acquire_Store(reinterpret_cast(ptr), value); -} - -inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) { - return Release_Store(reinterpret_cast(ptr), value); -} - -inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) { - return NoBarrier_Load(reinterpret_cast(ptr)); -} - -inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) { - return Acquire_Load(reinterpret_cast(ptr)); -} - -inline AtomicWord Release_Load(volatile const AtomicWord* ptr) { - return Release_Load(reinterpret_cast(ptr)); -} - -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // !defined(GOOGLE_PROTOBUF_ARCH_64_BIT) - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h b/src/google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h deleted file mode 100644 index 44ef9c9e03512..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h +++ /dev/null @@ -1,231 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2012 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This file is an internal atomic implementation, use atomicops.h instead. - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_C11_ATOMIC_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_C11_ATOMIC_H_ - -#include - -namespace google { -namespace protobuf { -namespace internal { - -// This implementation is transitional and maintains the original API for -// atomicops.h. This requires casting memory locations to the atomic types, and -// assumes that the API and the C++11 implementation are layout-compatible, -// which isn't true for all implementations or hardware platforms. The static -// assertion should detect this issue, were it to fire then this header -// shouldn't be used. -// -// TODO(jfb) If this header manages to stay committed then the API should be -// modified, and all call sites updated. -typedef volatile std::atomic* AtomicLocation32; -static_assert(sizeof(*(AtomicLocation32) nullptr) == sizeof(Atomic32), - "incompatible 32-bit atomic layout"); - -inline void MemoryBarrierInternal() { -#if defined(__GLIBCXX__) - // Work around libstdc++ bug 51038 where atomic_thread_fence was declared but - // not defined, leading to the linker complaining about undefined references. - __atomic_thread_fence(std::memory_order_seq_cst); -#else - std::atomic_thread_fence(std::memory_order_seq_cst); -#endif -} - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - ((AtomicLocation32)ptr) - ->compare_exchange_strong(old_value, - new_value, - std::memory_order_relaxed, - std::memory_order_relaxed); - return old_value; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - return ((AtomicLocation32)ptr) - ->exchange(new_value, std::memory_order_relaxed); -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return increment + - ((AtomicLocation32)ptr) - ->fetch_add(increment, std::memory_order_relaxed); -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return increment + ((AtomicLocation32)ptr)->fetch_add(increment); -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - ((AtomicLocation32)ptr) - ->compare_exchange_strong(old_value, - new_value, - std::memory_order_acquire, - std::memory_order_acquire); - return old_value; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - ((AtomicLocation32)ptr) - ->compare_exchange_strong(old_value, - new_value, - std::memory_order_release, - std::memory_order_relaxed); - return old_value; -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed); -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed); - MemoryBarrierInternal(); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - ((AtomicLocation32)ptr)->store(value, std::memory_order_release); -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed); -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - return ((AtomicLocation32)ptr)->load(std::memory_order_acquire); -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - MemoryBarrierInternal(); - return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed); -} - -#if defined(GOOGLE_PROTOBUF_ARCH_64_BIT) - -typedef volatile std::atomic* AtomicLocation64; -static_assert(sizeof(*(AtomicLocation64) nullptr) == sizeof(Atomic64), - "incompatible 64-bit atomic layout"); - -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - ((AtomicLocation64)ptr) - ->compare_exchange_strong(old_value, - new_value, - std::memory_order_relaxed, - std::memory_order_relaxed); - return old_value; -} - -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - return ((AtomicLocation64)ptr) - ->exchange(new_value, std::memory_order_relaxed); -} - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - return increment + - ((AtomicLocation64)ptr) - ->fetch_add(increment, std::memory_order_relaxed); -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - return increment + ((AtomicLocation64)ptr)->fetch_add(increment); -} - -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - ((AtomicLocation64)ptr) - ->compare_exchange_strong(old_value, - new_value, - std::memory_order_acquire, - std::memory_order_acquire); - return old_value; -} - -inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - ((AtomicLocation64)ptr) - ->compare_exchange_strong(old_value, - new_value, - std::memory_order_release, - std::memory_order_relaxed); - return old_value; -} - -inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { - ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed); -} - -inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { - ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed); - MemoryBarrierInternal(); -} - -inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { - ((AtomicLocation64)ptr)->store(value, std::memory_order_release); -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { - return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed); -} - -inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { - return ((AtomicLocation64)ptr)->load(std::memory_order_acquire); -} - -inline Atomic64 Release_Load(volatile const Atomic64* ptr) { - MemoryBarrierInternal(); - return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed); -} - -#endif // defined(GOOGLE_PROTOBUF_ARCH_64_BIT) - -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_C11_ATOMIC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h b/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h deleted file mode 100644 index 0b0b06ce6cf92..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2013 Red Hat Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Red Hat Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This file is an internal atomic implementation, use atomicops.h instead. - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_ - -namespace google { -namespace protobuf { -namespace internal { - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - __atomic_compare_exchange_n(ptr, &old_value, new_value, false, - __ATOMIC_RELAXED, __ATOMIC_RELAXED); - return old_value; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - return __atomic_exchange_n(ptr, new_value, __ATOMIC_RELAXED); -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return __atomic_add_fetch(ptr, increment, __ATOMIC_RELAXED); -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return __atomic_add_fetch(ptr, increment, __ATOMIC_SEQ_CST); -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - __atomic_compare_exchange_n(ptr, &old_value, new_value, false, - __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); - return old_value; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - __atomic_compare_exchange_n(ptr, &old_value, new_value, false, - __ATOMIC_RELEASE, __ATOMIC_ACQUIRE); - return old_value; -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - __atomic_store_n(ptr, value, __ATOMIC_RELAXED); -} - -inline void MemoryBarrierInternal() { - __sync_synchronize(); -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - __atomic_store_n(ptr, value, __ATOMIC_SEQ_CST); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - __atomic_store_n(ptr, value, __ATOMIC_RELEASE); -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return __atomic_load_n(ptr, __ATOMIC_RELAXED); -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - return __atomic_load_n(ptr, __ATOMIC_ACQUIRE); -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - return __atomic_load_n(ptr, __ATOMIC_SEQ_CST); -} - -#ifdef __LP64__ - -inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { - __atomic_store_n(ptr, value, __ATOMIC_RELEASE); -} - -inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { - return __atomic_load_n(ptr, __ATOMIC_ACQUIRE); -} - -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - __atomic_compare_exchange_n(ptr, &old_value, new_value, false, - __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); - return old_value; -} - -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - __atomic_compare_exchange_n(ptr, &old_value, new_value, false, - __ATOMIC_RELAXED, __ATOMIC_RELAXED); - return old_value; -} - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - return __atomic_add_fetch(ptr, increment, __ATOMIC_RELAXED); -} - -inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { - __atomic_store_n(ptr, value, __ATOMIC_RELAXED); -} - -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - return __atomic_exchange_n(ptr, new_value, __ATOMIC_RELAXED); -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { - return __atomic_load_n(ptr, __ATOMIC_RELAXED); -} - -#endif // defined(__LP64__) - -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h b/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h deleted file mode 100644 index 6ce6820ec26c2..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h +++ /dev/null @@ -1,313 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2012 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This file is an internal atomic implementation, use atomicops.h instead. - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MIPS_GCC_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MIPS_GCC_H_ - -#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") - -namespace google { -namespace protobuf { -namespace internal { - -// Atomically execute: -// result = *ptr; -// if (*ptr == old_value) -// *ptr = new_value; -// return result; -// -// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". -// Always return the old value of "*ptr" -// -// This routine implies no memory barriers. -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev, tmp; - __asm__ __volatile__(".set push\n" - ".set noreorder\n" - "1:\n" - "ll %0, %5\n" // prev = *ptr - "bne %0, %3, 2f\n" // if (prev != old_value) goto 2 - "move %2, %4\n" // tmp = new_value - "sc %2, %1\n" // *ptr = tmp (with atomic check) - "beqz %2, 1b\n" // start again on atomic error - "nop\n" // delay slot nop - "2:\n" - ".set pop\n" - : "=&r" (prev), "=m" (*ptr), "=&r" (tmp) - : "r" (old_value), "r" (new_value), "m" (*ptr) - : "memory"); - return prev; -} - -// Atomically store new_value into *ptr, returning the previous value held in -// *ptr. This routine implies no memory barriers. -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - Atomic32 temp, old; - __asm__ __volatile__(".set push\n" - ".set noreorder\n" - "1:\n" - "ll %1, %4\n" // old = *ptr - "move %0, %3\n" // temp = new_value - "sc %0, %2\n" // *ptr = temp (with atomic check) - "beqz %0, 1b\n" // start again on atomic error - "nop\n" // delay slot nop - ".set pop\n" - : "=&r" (temp), "=&r" (old), "=m" (*ptr) - : "r" (new_value), "m" (*ptr) - : "memory"); - - return old; -} - -// Atomically increment *ptr by "increment". Returns the new value of -// *ptr with the increment applied. This routine implies no memory barriers. -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 temp, temp2; - - __asm__ __volatile__(".set push\n" - ".set noreorder\n" - "1:\n" - "ll %0, %4\n" // temp = *ptr - "addu %1, %0, %3\n" // temp2 = temp + increment - "sc %1, %2\n" // *ptr = temp2 (with atomic check) - "beqz %1, 1b\n" // start again on atomic error - "addu %1, %0, %3\n" // temp2 = temp + increment - ".set pop\n" - : "=&r" (temp), "=&r" (temp2), "=m" (*ptr) - : "Ir" (increment), "m" (*ptr) - : "memory"); - // temp2 now holds the final value. - return temp2; -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - ATOMICOPS_COMPILER_BARRIER(); - Atomic32 res = NoBarrier_AtomicIncrement(ptr, increment); - ATOMICOPS_COMPILER_BARRIER(); - return res; -} - -// "Acquire" operations -// ensure that no later memory access can be reordered ahead of the operation. -// "Release" operations ensure that no previous memory access can be reordered -// after the operation. "Barrier" operations have both "Acquire" and "Release" -// semantics. A MemoryBarrierInternal() has "Barrier" semantics, but does no -// memory access. -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - ATOMICOPS_COMPILER_BARRIER(); - Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - ATOMICOPS_COMPILER_BARRIER(); - return res; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - ATOMICOPS_COMPILER_BARRIER(); - Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - ATOMICOPS_COMPILER_BARRIER(); - return res; -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; -} - -inline void MemoryBarrierInternal() { - __asm__ __volatile__("sync" : : : "memory"); -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; - MemoryBarrierInternal(); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - MemoryBarrierInternal(); - *ptr = value; -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return *ptr; -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 value = *ptr; - MemoryBarrierInternal(); - return value; -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - MemoryBarrierInternal(); - return *ptr; -} - -#if defined(__LP64__) -// 64-bit versions of the atomic ops. - -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 prev, tmp; - __asm__ __volatile__(".set push\n" - ".set noreorder\n" - "1:\n" - "lld %0, %5\n" // prev = *ptr - "bne %0, %3, 2f\n" // if (prev != old_value) goto 2 - "move %2, %4\n" // tmp = new_value - "scd %2, %1\n" // *ptr = tmp (with atomic check) - "beqz %2, 1b\n" // start again on atomic error - "nop\n" // delay slot nop - "2:\n" - ".set pop\n" - : "=&r" (prev), "=m" (*ptr), "=&r" (tmp) - : "r" (old_value), "r" (new_value), "m" (*ptr) - : "memory"); - return prev; -} - -// Atomically store new_value into *ptr, returning the previous value held in -// *ptr. This routine implies no memory barriers. -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - Atomic64 temp, old; - __asm__ __volatile__(".set push\n" - ".set noreorder\n" - "1:\n" - "lld %1, %4\n" // old = *ptr - "move %0, %3\n" // temp = new_value - "scd %0, %2\n" // *ptr = temp (with atomic check) - "beqz %0, 1b\n" // start again on atomic error - "nop\n" // delay slot nop - ".set pop\n" - : "=&r" (temp), "=&r" (old), "=m" (*ptr) - : "r" (new_value), "m" (*ptr) - : "memory"); - - return old; -} - -// Atomically increment *ptr by "increment". Returns the new value of -// *ptr with the increment applied. This routine implies no memory barriers. -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - Atomic64 temp, temp2; - - __asm__ __volatile__(".set push\n" - ".set noreorder\n" - "1:\n" - "lld %0, %4\n" // temp = *ptr - "daddu %1, %0, %3\n" // temp2 = temp + increment - "scd %1, %2\n" // *ptr = temp2 (with atomic check) - "beqz %1, 1b\n" // start again on atomic error - "daddu %1, %0, %3\n" // temp2 = temp + increment - ".set pop\n" - : "=&r" (temp), "=&r" (temp2), "=m" (*ptr) - : "Ir" (increment), "m" (*ptr) - : "memory"); - // temp2 now holds the final value. - return temp2; -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - MemoryBarrierInternal(); - Atomic64 res = NoBarrier_AtomicIncrement(ptr, increment); - MemoryBarrierInternal(); - return res; -} - -// "Acquire" operations -// ensure that no later memory access can be reordered ahead of the operation. -// "Release" operations ensure that no previous memory access can be reordered -// after the operation. "Barrier" operations have both "Acquire" and "Release" -// semantics. A MemoryBarrierInternal() has "Barrier" semantics, but does no -// memory access. -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - MemoryBarrierInternal(); - return res; -} - -inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - MemoryBarrierInternal(); - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; - MemoryBarrierInternal(); -} - -inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { - MemoryBarrierInternal(); - *ptr = value; -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { - return *ptr; -} - -inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { - Atomic64 value = *ptr; - MemoryBarrierInternal(); - return value; -} - -inline Atomic64 Release_Load(volatile const Atomic64* ptr) { - MemoryBarrierInternal(); - return *ptr; -} -#endif - -} // namespace internal -} // namespace protobuf -} // namespace google - -#undef ATOMICOPS_COMPILER_BARRIER - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MIPS_GCC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_power.h b/src/google/protobuf/stubs/atomicops_internals_power.h deleted file mode 100644 index cad9f1e35444a..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_power.h +++ /dev/null @@ -1,440 +0,0 @@ -// Copyright 2014 Bloomberg Finance LP. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Bloomberg Finance LP. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This file is an internal atomic implementation, use atomicops.h instead. - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_AIX_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_AIX_H_ - -namespace google { -namespace protobuf { -namespace internal { - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 result; - - asm volatile ( - "1: lwarx %[res], %[zero], %[obj] \n\t" // load and reserve - " cmpw %[cmp], %[res] \n\t" // compare values - " bne- 2f \n\t" - " stwcx. %[val], %[zero], %[obj] \n\t" // store new value - " bne- 1b \n\t" - "2: \n\t" - : [res] "=&b" (result) - : [obj] "b" (ptr), - [cmp] "b" (old_value), - [val] "b" (new_value), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - Atomic32 result; - - asm volatile ( - "1: lwarx %[res], %[zero], %[obj] \n\t" - " stwcx. %[val], %[zero], %[obj] \n\t" - " bne- 1b \n\t" - : [res] "=&b" (result) - : [obj] "b" (ptr), - [val] "b" (new_value), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 result; - - asm volatile ( - "1: lwarx %[res], %[zero], %[obj] \n\t" // load and reserve - " add %[res], %[val], %[res] \n\t" // add the operand - " stwcx. %[res], %[zero], %[obj] \n\t" // store old value - // if still reserved - " bne- 1b \n\t" - : [res] "=&b" (result) - : [obj] "b" (ptr), - [val] "b" (increment), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -inline void MemoryBarrierInternal(void) { - asm volatile ( - " lwsync \n\t" - " isync \n\t" - : - : - : "memory"); -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 result; - - asm volatile ( - " lwsync \n\t" - - "1: lwarx %[res], %[zero], %[obj] \n\t" // load and reserve - " add %[res], %[val], %[res] \n\t" // add the operand - " stwcx. %[res], %[zero], %[obj] \n\t" // store old value - // if still reserved - " bne- 1b \n\t" - " isync \n\t" - : [res] "=&b" (result) - : [obj] "b" (ptr), - [val] "b" (increment), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 result; - - asm volatile ( - "1: lwarx %[res], %[zero], %[obj] \n\t" // load and reserve - " cmpw %[cmp], %[res] \n\t" // compare values - " bne- 2f \n\t" - " stwcx. %[val], %[zero], %[obj] \n\t" // store new value - " bne- 1b \n\t" - - " isync \n\t" - "2: \n\t" - : [res] "=&b" (result) - : [obj] "b" (ptr), - [cmp] "b" (old_value), - [val] "b" (new_value), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 result; - - asm volatile ( - " lwsync \n\t" - - "1: lwarx %[res], %[zero], %[obj] \n\t" // load and reserve - " cmpw %[cmp], %[res] \n\t" // compare values - " bne- 2f \n\t" - " stwcx. %[val], %[zero], %[obj] \n\t" // store new value - " bne- 1b \n\t" - - "2: \n\t" - : [res] "=&b" (result) - : [obj] "b" (ptr), - [cmp] "b" (old_value), - [val] "b" (new_value), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - asm volatile ( - " stw %[val], %[obj] \n\t" - " isync \n\t" - : [obj] "=m" (*ptr) - : [val] "b" (value)); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - asm volatile ( - " lwsync \n\t" - " stw %[val], %[obj] \n\t" - : [obj] "=m" (*ptr) - : [val] "b" (value)); -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return *ptr; -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 result; - - asm volatile ( - "1: lwz %[res], %[obj] \n\t" - " cmpw %[res], %[res] \n\t" // create data - // dependency for - // load/load ordering - " bne- 1b \n\t" // never taken - - " isync \n\t" - : [res] "=b" (result) - : [obj] "m" (*ptr), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - Atomic32 result; - - asm volatile ( - " lwsync \n\t" - - "1: lwz %[res], %[obj] \n\t" - " cmpw %[res], %[res] \n\t" // create data - // dependency for - // load/load ordering - " bne- 1b \n\t" // never taken - : [res] "=b" (result) - : [obj] "m" (*ptr), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 result; - - asm volatile ( - "1: ldarx %[res], %[zero], %[obj] \n\t" // load and reserve - " cmpd %[cmp], %[res] \n\t" // compare values - " bne- 2f \n\t" - - " stdcx. %[val], %[zero], %[obj] \n\t" // store the new value - " bne- 1b \n\t" - "2: \n\t" - : [res] "=&b" (result) - : [obj] "b" (ptr), - [cmp] "b" (old_value), - [val] "b" (new_value), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - Atomic64 result; - - asm volatile ( - "1: ldarx %[res], %[zero], %[obj] \n\t" - " stdcx. %[val], %[zero], %[obj] \n\t" - " bne- 1b \n\t" - : [res] "=&b" (result) - : [obj] "b" (ptr), - [val] "b" (new_value), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - Atomic64 result; - - asm volatile ( - "1: ldarx %[res], %[zero], %[obj] \n\t" // load and reserve - " add %[res], %[res], %[val] \n\t" // add the operand - " stdcx. %[res], %[zero], %[obj] \n\t" // store old value if - // still reserved - - " bne- 1b \n\t" - : [res] "=&b" (result) - : [obj] "b" (ptr), - [val] "b" (increment), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - - Atomic64 result; - - asm volatile ( - " lwsync \n\t" - - "1: ldarx %[res], %[zero], %[obj] \n\t" // load and reserve - " add %[res], %[res], %[val] \n\t" // add the operand - " stdcx. %[res], %[zero], %[obj] \n\t" // store old value if - // still reserved - - " bne- 1b \n\t" - - " isync \n\t" - : [res] "=&b" (result) - : [obj] "b" (ptr), - [val] "b" (increment), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 result; - - asm volatile ( - "1: ldarx %[res], %[zero], %[obj] \n\t" // load and reserve - " cmpd %[cmp], %[res] \n\t" // compare values - " bne- 2f \n\t" - - " stdcx. %[val], %[zero], %[obj] \n\t" // store the new value - " bne- 1b \n\t" - " isync \n\t" - "2: \n\t" - : [res] "=&b" (result) - : [obj] "b" (ptr), - [cmp] "b" (old_value), - [val] "b" (new_value), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 result; - - asm volatile ( - " lwsync \n\t" - - "1: ldarx %[res], %[zero], %[obj] \n\t" // load and reserve - " cmpd %[cmp], %[res] \n\t" // compare values - " bne- 2f \n\t" - - " stdcx. %[val], %[zero], %[obj] \n\t" // store the new value - " bne- 1b \n\t" - "2: \n\t" - : [res] "=&b" (result) - : [obj] "b" (ptr), - [cmp] "b" (old_value), - [val] "b" (new_value), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { - asm volatile ( - " std %[val], %[obj] \n\t" - " isync \n\t" - : [obj] "=m" (*ptr) - : [val] "b" (value)); -} - -inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { - asm volatile ( - " lwsync \n\t" - " std %[val], %[obj] \n\t" - : [obj] "=m" (*ptr) - : [val] "b" (value)); -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { - return *ptr; -} - -inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { - Atomic64 result; - - asm volatile ( - "1: ld %[res], %[obj] \n\t" - " cmpd %[res], %[res] \n\t" // create data - // dependency for - // load/load ordering - " bne- 1b \n\t" // never taken - - " isync \n\t" - : [res] "=b" (result) - : [obj] "m" (*ptr), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} - -inline Atomic64 Release_Load(volatile const Atomic64* ptr) { - Atomic64 result; - - asm volatile ( - " lwsync \n\t" - - "1: ld %[res], %[obj] \n\t" - " cmpd %[res], %[res] \n\t" // create data - // dependency for - // load/load ordering - " bne- 1b \n\t" // never taken - : [res] "=b" (result) - : [obj] "m" (*ptr), - [zero] "i" (0) - : "cr0", "ctr"); - - return result; -} -#endif - -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_SPARC_GCC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_ppc_gcc.h b/src/google/protobuf/stubs/atomicops_internals_ppc_gcc.h deleted file mode 100644 index d477dc6ddadb4..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_ppc_gcc.h +++ /dev/null @@ -1,155 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2015 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: ogabbay@advaoptical.com (Oded Gabbay) -// Cleaned up by: bsilver16384@gmail.com (Brian Silverman) -// -// This file is an internal atomic implementation, use atomicops.h instead. - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PPC_GCC_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PPC_GCC_H_ - -#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") - -namespace google { -namespace protobuf { -namespace internal { - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev; - - __asm__ __volatile__( - "0: \n\t" - "lwarx %[prev],0,%[ptr] \n\t" - "cmpw 0,%[prev],%[old_value] \n\t" - "bne- 1f \n\t" - "stwcx. %[new_value],0,%[ptr] \n\t" - "bne- 0b \n\t" - "1: \n\t" - : [prev] "=&r"(prev), "+m"(*ptr) - : [ptr] "r"(ptr), [old_value] "r"(old_value), [new_value] "r"(new_value) - : "cc", "memory"); - - return prev; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr, - Atomic32 new_value) { - Atomic32 old; - - __asm__ __volatile__( - "0: \n\t" - "lwarx %[old],0,%[ptr] \n\t" - "stwcx. %[new_value],0,%[ptr] \n\t" - "bne- 0b \n\t" - : [old] "=&r"(old), "+m"(*ptr) - : [ptr] "r"(ptr), [new_value] "r"(new_value) - : "cc", "memory"); - - return old; -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr, - Atomic32 increment) { - Atomic32 temp; - - __asm__ __volatile__( - "0: \n\t" - "lwarx %[temp],0,%[ptr] \n\t" - "add %[temp],%[increment],%[temp] \n\t" - "stwcx. %[temp],0,%[ptr] \n\t" - "bne- 0b \n\t" - : [temp] "=&r"(temp) - : [increment] "r"(increment), [ptr] "r"(ptr) - : "cc", "memory"); - - return temp; -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr, - Atomic32 increment) { - MemoryBarrierInternal(); - Atomic32 res = NoBarrier_AtomicIncrement(ptr, increment); - MemoryBarrierInternal(); - return res; -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr, - Atomic32 old_value, Atomic32 new_value) { - Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - MemoryBarrierInternal(); - return res; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr, - Atomic32 old_value, Atomic32 new_value) { - MemoryBarrierInternal(); - Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - return res; -} - -inline void NoBarrier_Store(volatile Atomic32 *ptr, Atomic32 value) { - *ptr = value; -} - -inline void MemoryBarrierInternal() { __asm__ __volatile__("sync" : : : "memory"); } - -inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) { - *ptr = value; - MemoryBarrierInternal(); -} - -inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) { - MemoryBarrierInternal(); - *ptr = value; -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32 *ptr) { return *ptr; } - -inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) { - Atomic32 value = *ptr; - MemoryBarrierInternal(); - return value; -} - -inline Atomic32 Release_Load(volatile const Atomic32 *ptr) { - MemoryBarrierInternal(); - return *ptr; -} - -} // namespace internal -} // namespace protobuf -} // namespace google - -#undef ATOMICOPS_COMPILER_BARRIER - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PPC_GCC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_solaris.h b/src/google/protobuf/stubs/atomicops_internals_solaris.h deleted file mode 100644 index baecb993bc0ce..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_solaris.h +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This file is an internal atomic implementation, use atomicops.h instead. - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_SPARC_GCC_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_SPARC_GCC_H_ - -#include - -namespace google { -namespace protobuf { -namespace internal { - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - return (Atomic32)atomic_cas_32((volatile uint32_t*)ptr, (uint32_t)old_value, (uint32_t)new_value); -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - return (Atomic32)atomic_swap_32((volatile uint32_t*)ptr, (uint32_t)new_value); -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return (Atomic32)atomic_add_32_nv((volatile uint32_t*)ptr, (uint32_t)increment); -} - -inline void MemoryBarrierInternal(void) { - membar_producer(); - membar_consumer(); -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - MemoryBarrierInternal(); - Atomic32 ret = NoBarrier_AtomicIncrement(ptr, increment); - MemoryBarrierInternal(); - - return ret; -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 ret = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - MemoryBarrierInternal(); - - return ret; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - MemoryBarrierInternal(); - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; - membar_producer(); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - membar_consumer(); - *ptr = value; -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return *ptr; -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 val = *ptr; - membar_consumer(); - return val; -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - membar_producer(); - return *ptr; -} - -#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - return atomic_cas_64((volatile uint64_t*)ptr, (uint64_t)old_value, (uint64_t)new_value); -} - -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value) { - return atomic_swap_64((volatile uint64_t*)ptr, (uint64_t)new_value); -} - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment) { - return atomic_add_64_nv((volatile uint64_t*)ptr, increment); -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment) { - MemoryBarrierInternal(); - Atomic64 ret = atomic_add_64_nv((volatile uint64_t*)ptr, increment); - MemoryBarrierInternal(); - return ret; -} - -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 ret = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - MemoryBarrierInternal(); - return ret; -} - -inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - MemoryBarrierInternal(); - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; - membar_producer(); -} - -inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { - membar_consumer(); - *ptr = value; -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { - return *ptr; -} - -inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { - Atomic64 ret = *ptr; - membar_consumer(); - return ret; -} - -inline Atomic64 Release_Load(volatile const Atomic64* ptr) { - membar_producer(); - return *ptr; -} -#endif - -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_SPARC_GCC_H_ - diff --git a/src/google/protobuf/stubs/atomicops_internals_tsan.h b/src/google/protobuf/stubs/atomicops_internals_tsan.h deleted file mode 100644 index 676380b1d5361..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_tsan.h +++ /dev/null @@ -1,219 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This file is an internal atomic implementation for compiler-based -// ThreadSanitizer (http://clang.llvm.org/docs/ThreadSanitizer.html). -// Use atomicops.h instead. - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TSAN_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TSAN_H_ - -#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") - -#include - -namespace google { -namespace protobuf { -namespace internal { - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 cmp = old_value; - __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value, - __tsan_memory_order_relaxed, __tsan_memory_order_relaxed); - return cmp; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr, - Atomic32 new_value) { - return __tsan_atomic32_exchange(ptr, new_value, - __tsan_memory_order_relaxed); -} - -inline Atomic32 Acquire_AtomicExchange(volatile Atomic32 *ptr, - Atomic32 new_value) { - return __tsan_atomic32_exchange(ptr, new_value, - __tsan_memory_order_acquire); -} - -inline Atomic32 Release_AtomicExchange(volatile Atomic32 *ptr, - Atomic32 new_value) { - return __tsan_atomic32_exchange(ptr, new_value, - __tsan_memory_order_release); -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr, - Atomic32 increment) { - return increment + __tsan_atomic32_fetch_add(ptr, increment, - __tsan_memory_order_relaxed); -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr, - Atomic32 increment) { - return increment + __tsan_atomic32_fetch_add(ptr, increment, - __tsan_memory_order_acq_rel); -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 cmp = old_value; - __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value, - __tsan_memory_order_acquire, __tsan_memory_order_acquire); - return cmp; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 cmp = old_value; - __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value, - __tsan_memory_order_release, __tsan_memory_order_relaxed); - return cmp; -} - -inline void NoBarrier_Store(volatile Atomic32 *ptr, Atomic32 value) { - __tsan_atomic32_store(ptr, value, __tsan_memory_order_relaxed); -} - -inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) { - __tsan_atomic32_store(ptr, value, __tsan_memory_order_relaxed); - __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); -} - -inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) { - __tsan_atomic32_store(ptr, value, __tsan_memory_order_release); -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32 *ptr) { - return __tsan_atomic32_load(ptr, __tsan_memory_order_relaxed); -} - -inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) { - return __tsan_atomic32_load(ptr, __tsan_memory_order_acquire); -} - -inline Atomic32 Release_Load(volatile const Atomic32 *ptr) { - __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); - return __tsan_atomic32_load(ptr, __tsan_memory_order_relaxed); -} - -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 cmp = old_value; - __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value, - __tsan_memory_order_relaxed, __tsan_memory_order_relaxed); - return cmp; -} - -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr, - Atomic64 new_value) { - return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_relaxed); -} - -inline Atomic64 Acquire_AtomicExchange(volatile Atomic64 *ptr, - Atomic64 new_value) { - return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_acquire); -} - -inline Atomic64 Release_AtomicExchange(volatile Atomic64 *ptr, - Atomic64 new_value) { - return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_release); -} - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr, - Atomic64 increment) { - return increment + __tsan_atomic64_fetch_add(ptr, increment, - __tsan_memory_order_relaxed); -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr, - Atomic64 increment) { - return increment + __tsan_atomic64_fetch_add(ptr, increment, - __tsan_memory_order_acq_rel); -} - -inline void NoBarrier_Store(volatile Atomic64 *ptr, Atomic64 value) { - __tsan_atomic64_store(ptr, value, __tsan_memory_order_relaxed); -} - -inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) { - __tsan_atomic64_store(ptr, value, __tsan_memory_order_relaxed); - __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); -} - -inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) { - __tsan_atomic64_store(ptr, value, __tsan_memory_order_release); -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64 *ptr) { - return __tsan_atomic64_load(ptr, __tsan_memory_order_relaxed); -} - -inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) { - return __tsan_atomic64_load(ptr, __tsan_memory_order_acquire); -} - -inline Atomic64 Release_Load(volatile const Atomic64 *ptr) { - __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); - return __tsan_atomic64_load(ptr, __tsan_memory_order_relaxed); -} - -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 cmp = old_value; - __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value, - __tsan_memory_order_acquire, __tsan_memory_order_acquire); - return cmp; -} - -inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 cmp = old_value; - __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value, - __tsan_memory_order_release, __tsan_memory_order_relaxed); - return cmp; -} - -inline void MemoryBarrierInternal() { - __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); -} - -} // namespace internal -} // namespace protobuf -} // namespace google - -#undef ATOMICOPS_COMPILER_BARRIER - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TSAN_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc b/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc deleted file mode 100644 index 53c9eae0fa73f..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc +++ /dev/null @@ -1,137 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2012 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This module gets enough CPU information to optimize the -// atomicops module on x86. - -#include - -#include - -// This file only makes sense with atomicops_internals_x86_gcc.h -- it -// depends on structs that are defined in that file. If atomicops.h -// doesn't sub-include that file, then we aren't needed, and shouldn't -// try to do anything. -#ifdef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ - -// Inline cpuid instruction. In PIC compilations, %ebx contains the address -// of the global offset table. To avoid breaking such executables, this code -// must preserve that register's value across cpuid instructions. -#if defined(__i386__) -#define cpuid(a, b, c, d, inp) \ - asm("mov %%ebx, %%edi\n" \ - "cpuid\n" \ - "xchg %%edi, %%ebx\n" \ - : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) -#elif defined(__x86_64__) -#define cpuid(a, b, c, d, inp) \ - asm("mov %%rbx, %%rdi\n" \ - "cpuid\n" \ - "xchg %%rdi, %%rbx\n" \ - : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) -#endif - -#if defined(cpuid) // initialize the struct only on x86 - -namespace google { -namespace protobuf { -namespace internal { - -// Set the flags so that code will run correctly and conservatively, so even -// if we haven't been initialized yet, we're probably single threaded, and our -// default values should hopefully be pretty safe. -struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = { - false, // bug can't exist before process spawns multiple threads - false, // no SSE2 -}; - -namespace { - -// Initialize the AtomicOps_Internalx86CPUFeatures struct. -void AtomicOps_Internalx86CPUFeaturesInit() { - uint32_t eax; - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - - // Get vendor string (issue CPUID with eax = 0) - cpuid(eax, ebx, ecx, edx, 0); - char vendor[13]; - memcpy(vendor, &ebx, 4); - memcpy(vendor + 4, &edx, 4); - memcpy(vendor + 8, &ecx, 4); - vendor[12] = 0; - - // get feature flags in ecx/edx, and family/model in eax - cpuid(eax, ebx, ecx, edx, 1); - - int family = (eax >> 8) & 0xf; // family and model fields - int model = (eax >> 4) & 0xf; - if (family == 0xf) { // use extended family and model fields - family += (eax >> 20) & 0xff; - model += ((eax >> 16) & 0xf) << 4; - } - - // Opteron Rev E has a bug in which on very rare occasions a locked - // instruction doesn't act as a read-acquire barrier if followed by a - // non-locked read-modify-write instruction. Rev F has this bug in - // pre-release versions, but not in versions released to customers, - // so we test only for Rev E, which is family 15, model 32..63 inclusive. - if (strcmp(vendor, "AuthenticAMD") == 0 && // AMD - family == 15 && - 32 <= model && model <= 63) { - AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true; - } else { - AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false; - } - - // edx bit 26 is SSE2 which we use to tell use whether we can use mfence - AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1); -} - -class AtomicOpsx86Initializer { - public: - AtomicOpsx86Initializer() { - AtomicOps_Internalx86CPUFeaturesInit(); - } -}; - -// A global to get use initialized on startup via static initialization :/ -AtomicOpsx86Initializer g_initer; - -} // namespace - -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // __i386__ - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h b/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h deleted file mode 100644 index e80121fdf8e0c..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h +++ /dev/null @@ -1,293 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2012 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This file is an internal atomic implementation, use atomicops.h instead. - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ - -namespace google { -namespace protobuf { -namespace internal { - -// This struct is not part of the public API of this module; clients may not -// use it. -// Features of this x86. Values may not be correct before main() is run, -// but are set conservatively. -struct AtomicOps_x86CPUFeatureStruct { - bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence - // after acquire compare-and-swap. - bool has_sse2; // Processor has SSE2. -}; -extern struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures; - -#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") - -// 32-bit low-level operations on any platform. - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 prev; - __asm__ __volatile__("lock; cmpxchgl %1,%2" - : "=a" (prev) - : "q" (new_value), "m" (*ptr), "0" (old_value) - : "memory"); - return prev; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - __asm__ __volatile__("xchgl %1,%0" // The lock prefix is implicit for xchg. - : "=r" (new_value) - : "m" (*ptr), "0" (new_value) - : "memory"); - return new_value; // Now it's the previous value. -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 temp = increment; - __asm__ __volatile__("lock; xaddl %0,%1" - : "+r" (temp), "+m" (*ptr) - : : "memory"); - // temp now holds the old value of *ptr - return temp + increment; -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - Atomic32 temp = increment; - __asm__ __volatile__("lock; xaddl %0,%1" - : "+r" (temp), "+m" (*ptr) - : : "memory"); - // temp now holds the old value of *ptr - if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { - __asm__ __volatile__("lfence" : : : "memory"); - } - return temp + increment; -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { - __asm__ __volatile__("lfence" : : : "memory"); - } - return x; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; -} - -#if defined(__x86_64__) - -// 64-bit implementations of memory barrier can be simpler, because it -// "mfence" is guaranteed to exist. -inline void MemoryBarrierInternal() { - __asm__ __volatile__("mfence" : : : "memory"); -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; - MemoryBarrierInternal(); -} - -#else - -inline void MemoryBarrierInternal() { - if (AtomicOps_Internalx86CPUFeatures.has_sse2) { - __asm__ __volatile__("mfence" : : : "memory"); - } else { // mfence is faster but not present on PIII - Atomic32 x = 0; - NoBarrier_AtomicExchange(&x, 0); // acts as a barrier on PIII - } -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - if (AtomicOps_Internalx86CPUFeatures.has_sse2) { - *ptr = value; - __asm__ __volatile__("mfence" : : : "memory"); - } else { - NoBarrier_AtomicExchange(ptr, value); - // acts as a barrier on PIII - } -} -#endif - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - ATOMICOPS_COMPILER_BARRIER(); - *ptr = value; // An x86 store acts as a release barrier. - // See comments in Atomic64 version of Release_Store(), below. -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return *ptr; -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 value = *ptr; // An x86 load acts as a acquire barrier. - // See comments in Atomic64 version of Release_Store(), below. - ATOMICOPS_COMPILER_BARRIER(); - return value; -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - MemoryBarrierInternal(); - return *ptr; -} - -#if defined(__x86_64__) - -// 64-bit low-level operations on 64-bit platform. - -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 prev; - __asm__ __volatile__("lock; cmpxchgq %1,%2" - : "=a" (prev) - : "q" (new_value), "m" (*ptr), "0" (old_value) - : "memory"); - return prev; -} - -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - __asm__ __volatile__("xchgq %1,%0" // The lock prefix is implicit for xchg. - : "=r" (new_value) - : "m" (*ptr), "0" (new_value) - : "memory"); - return new_value; // Now it's the previous value. -} - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - Atomic64 temp = increment; - __asm__ __volatile__("lock; xaddq %0,%1" - : "+r" (temp), "+m" (*ptr) - : : "memory"); - // temp now contains the previous value of *ptr - return temp + increment; -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - Atomic64 temp = increment; - __asm__ __volatile__("lock; xaddq %0,%1" - : "+r" (temp), "+m" (*ptr) - : : "memory"); - // temp now contains the previous value of *ptr - if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { - __asm__ __volatile__("lfence" : : : "memory"); - } - return temp + increment; -} - -inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; - MemoryBarrierInternal(); -} - -inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { - ATOMICOPS_COMPILER_BARRIER(); - - *ptr = value; // An x86 store acts as a release barrier - // for current AMD/Intel chips as of Jan 2008. - // See also Acquire_Load(), below. - - // When new chips come out, check: - // IA-32 Intel Architecture Software Developer's Manual, Volume 3: - // System Programming Guide, Chatper 7: Multiple-processor management, - // Section 7.2, Memory Ordering. - // Last seen at: - // http://developer.intel.com/design/pentium4/manuals/index_new.htm - // - // x86 stores/loads fail to act as barriers for a few instructions (clflush - // maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are - // not generated by the compiler, and are rare. Users of these instructions - // need to know about cache behaviour in any case since all of these involve - // either flushing cache lines or non-temporal cache hints. -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { - return *ptr; -} - -inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { - Atomic64 value = *ptr; // An x86 load acts as a acquire barrier, - // for current AMD/Intel chips as of Jan 2008. - // See also Release_Store(), above. - ATOMICOPS_COMPILER_BARRIER(); - return value; -} - -inline Atomic64 Release_Load(volatile const Atomic64* ptr) { - MemoryBarrierInternal(); - return *ptr; -} - -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { - __asm__ __volatile__("lfence" : : : "memory"); - } - return x; -} - -inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -#endif // defined(__x86_64__) - -} // namespace internal -} // namespace protobuf -} // namespace google - -#undef ATOMICOPS_COMPILER_BARRIER - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ diff --git a/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc b/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc deleted file mode 100644 index 74a1bd4e064b8..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc +++ /dev/null @@ -1,113 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2012 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. - -// The compilation of extension_set.cc fails when windows.h is included. -// Therefore we move the code depending on windows.h to this separate cc file. - -// Don't compile this file for people not concerned about thread safety. -#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY - -#include - -#ifdef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ - -#include - -namespace google { -namespace protobuf { -namespace internal { - -inline void MemoryBarrierInternal() { - // On ARM this is a define while on x86/x64 this is - // a function declared in WinNT.h - MemoryBarrier(); -} - -Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - LONG result = InterlockedCompareExchange( - reinterpret_cast(ptr), - static_cast(new_value), - static_cast(old_value)); - return static_cast(result); -} - -Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - LONG result = InterlockedExchange( - reinterpret_cast(ptr), - static_cast(new_value)); - return static_cast(result); -} - -Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return InterlockedExchangeAdd( - reinterpret_cast(ptr), - static_cast(increment)) + increment; -} - -#if defined(_WIN64) - -// 64-bit low-level operations on 64-bit platform. - -Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - PVOID result = InterlockedCompareExchangePointer( - reinterpret_cast(ptr), - reinterpret_cast(new_value), reinterpret_cast(old_value)); - return reinterpret_cast(result); -} - -Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - PVOID result = InterlockedExchangePointer( - reinterpret_cast(ptr), - reinterpret_cast(new_value)); - return reinterpret_cast(result); -} - -Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - return InterlockedExchangeAdd64( - reinterpret_cast(ptr), - static_cast(increment)) + increment; -} - -#endif // defined(_WIN64) - -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ -#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY diff --git a/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h b/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h deleted file mode 100644 index 34d60d98e02b3..0000000000000 --- a/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h +++ /dev/null @@ -1,150 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2012 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This file is an internal atomic implementation, use atomicops.h instead. - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ - -namespace google { -namespace protobuf { -namespace internal { - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return Barrier_AtomicIncrement(ptr, increment); -} - -#if !(defined(_MSC_VER) && _MSC_VER >= 1400) -#error "We require at least vs2005 for MemoryBarrier" -#endif - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - NoBarrier_AtomicExchange(ptr, value); - // acts as a barrier in this implementation -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; // works w/o barrier for current Intel chips as of June 2005 - // See comments in Atomic64 version of Release_Store() below. -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return *ptr; -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 value = *ptr; - return value; -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - MemoryBarrierInternal(); - return *ptr; -} - -#if defined(_WIN64) - -// 64-bit low-level operations on 64-bit platform. - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - return Barrier_AtomicIncrement(ptr, increment); -} - -inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { - NoBarrier_AtomicExchange(ptr, value); - // acts as a barrier in this implementation -} - -inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; // works w/o barrier for current Intel chips as of June 2005 - - // When new chips come out, check: - // IA-32 Intel Architecture Software Developer's Manual, Volume 3: - // System Programming Guide, Chatper 7: Multiple-processor management, - // Section 7.2, Memory Ordering. - // Last seen at: - // http://developer.intel.com/design/pentium4/manuals/index_new.htm -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { - return *ptr; -} - -inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { - Atomic64 value = *ptr; - return value; -} - -inline Atomic64 Release_Load(volatile const Atomic64* ptr) { - MemoryBarrierInternal(); - return *ptr; -} - -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -#endif // defined(_WIN64) - -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ diff --git a/src/google/protobuf/stubs/bytestream.cc b/src/google/protobuf/stubs/bytestream.cc index f4af6a50abef0..a0f298edb94e1 100644 --- a/src/google/protobuf/stubs/bytestream.cc +++ b/src/google/protobuf/stubs/bytestream.cc @@ -33,6 +33,8 @@ #include #include +#include + namespace google { namespace protobuf { namespace strings { @@ -113,7 +115,7 @@ char* GrowingArrayByteSink::GetBuffer(size_t* nbytes) { ShrinkToFit(); char* b = buf_; *nbytes = size_; - buf_ = NULL; + buf_ = nullptr; size_ = capacity_ = 0; return b; } diff --git a/src/google/protobuf/stubs/bytestream.h b/src/google/protobuf/stubs/bytestream.h index 86510d140bafc..c7a48dea544a4 100644 --- a/src/google/protobuf/stubs/bytestream.h +++ b/src/google/protobuf/stubs/bytestream.h @@ -56,8 +56,9 @@ #include #include +#include + class CordByteSink; -class MemBlock; namespace google { namespace protobuf { @@ -74,7 +75,7 @@ namespace strings { // sink->Append(my_data.data(), my_data.size()); // sink->Flush(); // -class LIBPROTOBUF_EXPORT ByteSink { +class PROTOBUF_EXPORT ByteSink { public: ByteSink() {} virtual ~ByteSink() {} @@ -82,7 +83,7 @@ class LIBPROTOBUF_EXPORT ByteSink { // Appends the "n" bytes starting at "bytes". virtual void Append(const char* bytes, size_t n) = 0; - // Flushes internal buffers. The default implemenation does nothing. ByteSink + // Flushes internal buffers. The default implementation does nothing. ByteSink // subclasses may use internal buffers that require calling Flush() at the end // of the stream. virtual void Flush(); @@ -103,7 +104,7 @@ class LIBPROTOBUF_EXPORT ByteSink { // source->Skip(data.length()); // } // -class LIBPROTOBUF_EXPORT ByteSource { +class PROTOBUF_EXPORT ByteSource { public: ByteSource() {} virtual ~ByteSource() {} @@ -159,10 +160,10 @@ class LIBPROTOBUF_EXPORT ByteSource { // sink.Append("hi", 2); // OK // sink.Append(data, 100); // WOOPS! Overflows buf[10]. // -class LIBPROTOBUF_EXPORT UncheckedArrayByteSink : public ByteSink { +class PROTOBUF_EXPORT UncheckedArrayByteSink : public ByteSink { public: explicit UncheckedArrayByteSink(char* dest) : dest_(dest) {} - virtual void Append(const char* data, size_t n); + virtual void Append(const char* data, size_t n) override; // Returns the current output pointer so that a caller can see how many bytes // were produced. @@ -187,10 +188,10 @@ class LIBPROTOBUF_EXPORT UncheckedArrayByteSink : public ByteSink { // sink.Append("hi", 2); // OK // sink.Append(data, 100); // Will only write 8 more bytes // -class LIBPROTOBUF_EXPORT CheckedArrayByteSink : public ByteSink { +class PROTOBUF_EXPORT CheckedArrayByteSink : public ByteSink { public: CheckedArrayByteSink(char* outbuf, size_t capacity); - virtual void Append(const char* bytes, size_t n); + virtual void Append(const char* bytes, size_t n) override; // Returns the number of bytes actually written to the sink. size_t NumberOfBytesWritten() const { return size_; } @@ -223,11 +224,11 @@ class LIBPROTOBUF_EXPORT CheckedArrayByteSink : public ByteSink { // const char* buf = sink.GetBuffer(); // Ownership transferred // delete[] buf; // -class LIBPROTOBUF_EXPORT GrowingArrayByteSink : public strings::ByteSink { +class PROTOBUF_EXPORT GrowingArrayByteSink : public strings::ByteSink { public: explicit GrowingArrayByteSink(size_t estimated_size); virtual ~GrowingArrayByteSink(); - virtual void Append(const char* bytes, size_t n); + virtual void Append(const char* bytes, size_t n) override; // Returns the allocated buffer, and sets nbytes to its size. The caller takes // ownership of the buffer and must delete it with delete[]. @@ -253,13 +254,13 @@ class LIBPROTOBUF_EXPORT GrowingArrayByteSink : public strings::ByteSink { // sink.Append("World", 5); // assert(dest == "Hello World"); // -class LIBPROTOBUF_EXPORT StringByteSink : public ByteSink { +class PROTOBUF_EXPORT StringByteSink : public ByteSink { public: - explicit StringByteSink(string* dest) : dest_(dest) {} - virtual void Append(const char* data, size_t n); + explicit StringByteSink(std::string* dest) : dest_(dest) {} + virtual void Append(const char* data, size_t n) override; private: - string* dest_; + std::string* dest_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringByteSink); }; @@ -270,10 +271,10 @@ class LIBPROTOBUF_EXPORT StringByteSink : public ByteSink { // NullByteSink sink; // sink.Append(data, data.size()); // All data ignored. // -class LIBPROTOBUF_EXPORT NullByteSink : public ByteSink { +class PROTOBUF_EXPORT NullByteSink : public ByteSink { public: NullByteSink() {} - virtual void Append(const char *data, size_t n) {} + void Append(const char* /*data*/, size_t /*n*/) override {} private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NullByteSink); @@ -292,13 +293,13 @@ class LIBPROTOBUF_EXPORT NullByteSink : public ByteSink { // assert(source.Available() == 5); // assert(source.Peek() == "Hello"); // -class LIBPROTOBUF_EXPORT ArrayByteSource : public ByteSource { +class PROTOBUF_EXPORT ArrayByteSource : public ByteSource { public: explicit ArrayByteSource(StringPiece s) : input_(s) {} - virtual size_t Available() const; - virtual StringPiece Peek(); - virtual void Skip(size_t n); + virtual size_t Available() const override; + virtual StringPiece Peek() override; + virtual void Skip(size_t n) override; private: StringPiece input_; @@ -323,18 +324,18 @@ class LIBPROTOBUF_EXPORT ArrayByteSource : public ByteSource { // assert(limit.Available() == 5); // assert(limit.Peek() == "Hello"); // -class LIBPROTOBUF_EXPORT LimitByteSource : public ByteSource { +class PROTOBUF_EXPORT LimitByteSource : public ByteSource { public: // Returns at most "limit" bytes from "source". LimitByteSource(ByteSource* source, size_t limit); - virtual size_t Available() const; - virtual StringPiece Peek(); - virtual void Skip(size_t n); + virtual size_t Available() const override; + virtual StringPiece Peek() override; + virtual void Skip(size_t n) override; // We override CopyTo so that we can forward to the underlying source, in // case it has an efficient implementation of CopyTo. - virtual void CopyTo(ByteSink* sink, size_t n); + virtual void CopyTo(ByteSink* sink, size_t n) override; private: ByteSource* source_; @@ -345,4 +346,6 @@ class LIBPROTOBUF_EXPORT LimitByteSource : public ByteSource { } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_ diff --git a/src/google/protobuf/stubs/bytestream_unittest.cc b/src/google/protobuf/stubs/bytestream_unittest.cc index 06f114abc7028..cb11825ef72ec 100644 --- a/src/google/protobuf/stubs/bytestream_unittest.cc +++ b/src/google/protobuf/stubs/bytestream_unittest.cc @@ -64,7 +64,7 @@ class MockByteSource : public ByteSource { TEST(ByteSourceTest, CopyTo) { StringPiece data("Hello world!"); MockByteSource source(data, 3); - string str; + std::string str; StringByteSink sink(&str); source.CopyTo(&sink, data.size()); @@ -75,7 +75,7 @@ TEST(ByteSourceTest, CopySubstringTo) { StringPiece data("Hello world!"); MockByteSource source(data, 3); source.Skip(1); - string str; + std::string str; StringByteSink sink(&str); source.CopyTo(&sink, data.size() - 2); @@ -92,7 +92,7 @@ TEST(ByteSourceTest, LimitByteSource) { EXPECT_EQ(5, limit_source.Available()); { - string str; + std::string str; StringByteSink sink(&str); limit_source.CopyTo(&sink, limit_source.Available()); EXPECT_EQ("ello ", str); @@ -101,7 +101,7 @@ TEST(ByteSourceTest, LimitByteSource) { } { - string str; + std::string str; StringByteSink sink(&str); source.CopyTo(&sink, source.Available()); EXPECT_EQ("world!", str); @@ -112,7 +112,7 @@ TEST(ByteSourceTest, LimitByteSource) { TEST(ByteSourceTest, CopyToStringByteSink) { StringPiece data("Hello world!"); MockByteSource source(data, 3); - string str; + std::string str; StringByteSink sink(&str); source.CopyTo(&sink, data.size()); EXPECT_EQ(data, str); @@ -121,7 +121,7 @@ TEST(ByteSourceTest, CopyToStringByteSink) { // Verify that ByteSink is subclassable and Flush() overridable. class FlushingByteSink : public StringByteSink { public: - explicit FlushingByteSink(string* dest) : StringByteSink(dest) {} + explicit FlushingByteSink(std::string* dest) : StringByteSink(dest) {} virtual void Flush() { Append("z", 1); } private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FlushingByteSink); @@ -134,7 +134,7 @@ void WriteAndFlush(ByteSink* s) { } TEST(ByteSinkTest, Flush) { - string str; + std::string str; FlushingByteSink f_sink(&str); WriteAndFlush(&f_sink); EXPECT_STREQ("abcz", str.c_str()); diff --git a/src/google/protobuf/stubs/callback.h b/src/google/protobuf/stubs/callback.h index 9ec049795579a..43d546d19987d 100644 --- a/src/google/protobuf/stubs/callback.h +++ b/src/google/protobuf/stubs/callback.h @@ -1,8 +1,11 @@ #ifndef GOOGLE_PROTOBUF_STUBS_CALLBACK_H_ #define GOOGLE_PROTOBUF_STUBS_CALLBACK_H_ +#include + #include -#include + +#include // =================================================================== // emulates google3/base/callback.h @@ -59,15 +62,15 @@ namespace protobuf { // Note that NewCallback() is a bit touchy regarding argument types. Generally, // the values you provide for the parameter bindings must exactly match the // types accepted by the callback function. For example: -// void Foo(string s); +// void Foo(std::string s); // NewCallback(&Foo, "foo"); // WON'T WORK: const char* != string -// NewCallback(&Foo, string("foo")); // WORKS +// NewCallback(&Foo, std::string("foo")); // WORKS // Also note that the arguments cannot be references: -// void Foo(const string& s); -// string my_str; -// NewCallback(&Foo, my_str); // WON'T WORK: Can't use referecnes. +// void Foo(const std::string& s); +// std::string my_str; +// NewCallback(&Foo, my_str); // WON'T WORK: Can't use references. // However, correctly-typed pointers will work just fine. -class LIBPROTOBUF_EXPORT Closure { +class PROTOBUF_EXPORT Closure { public: Closure() {} virtual ~Closure(); @@ -90,8 +93,8 @@ class ResultCallback { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback); }; -template -class LIBPROTOBUF_EXPORT ResultCallback1 { +template +class PROTOBUF_EXPORT ResultCallback1 { public: ResultCallback1() {} virtual ~ResultCallback1() {} @@ -102,8 +105,8 @@ class LIBPROTOBUF_EXPORT ResultCallback1 { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback1); }; -template -class LIBPROTOBUF_EXPORT ResultCallback2 { +template +class PROTOBUF_EXPORT ResultCallback2 { public: ResultCallback2() {} virtual ~ResultCallback2() {} @@ -116,7 +119,7 @@ class LIBPROTOBUF_EXPORT ResultCallback2 { namespace internal { -class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure { +class PROTOBUF_EXPORT FunctionClosure0 : public Closure { public: typedef void (*FunctionType)(); @@ -124,7 +127,7 @@ class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure { : function_(function), self_deleting_(self_deleting) {} ~FunctionClosure0(); - void Run() { + void Run() override { bool needs_delete = self_deleting_; // read in case callback deletes function_(); if (needs_delete) delete this; @@ -144,7 +147,7 @@ class MethodClosure0 : public Closure { : object_(object), method_(method), self_deleting_(self_deleting) {} ~MethodClosure0() {} - void Run() { + void Run() override { bool needs_delete = self_deleting_; // read in case callback deletes (object_->*method_)(); if (needs_delete) delete this; @@ -167,7 +170,7 @@ class FunctionClosure1 : public Closure { arg1_(arg1) {} ~FunctionClosure1() {} - void Run() { + void Run() override { bool needs_delete = self_deleting_; // read in case callback deletes function_(arg1_); if (needs_delete) delete this; @@ -190,7 +193,7 @@ class MethodClosure1 : public Closure { arg1_(arg1) {} ~MethodClosure1() {} - void Run() { + void Run() override { bool needs_delete = self_deleting_; // read in case callback deletes (object_->*method_)(arg1_); if (needs_delete) delete this; @@ -214,7 +217,7 @@ class FunctionClosure2 : public Closure { arg1_(arg1), arg2_(arg2) {} ~FunctionClosure2() {} - void Run() { + void Run() override { bool needs_delete = self_deleting_; // read in case callback deletes function_(arg1_, arg2_); if (needs_delete) delete this; @@ -238,7 +241,7 @@ class MethodClosure2 : public Closure { arg1_(arg1), arg2_(arg2) {} ~MethodClosure2() {} - void Run() { + void Run() override { bool needs_delete = self_deleting_; // read in case callback deletes (object_->*method_)(arg1_, arg2_); if (needs_delete) delete this; @@ -261,7 +264,7 @@ class FunctionResultCallback_0_0 : public ResultCallback { : function_(function), self_deleting_(self_deleting) {} ~FunctionResultCallback_0_0() {} - R Run() { + R Run() override { bool needs_delete = self_deleting_; // read in case callback deletes R result = function_(); if (needs_delete) delete this; @@ -283,7 +286,7 @@ class FunctionResultCallback_1_0 : public ResultCallback { : function_(function), self_deleting_(self_deleting), p1_(p1) {} ~FunctionResultCallback_1_0() {} - R Run() { + R Run() override { bool needs_delete = self_deleting_; // read in case callback deletes R result = function_(p1_); if (needs_delete) delete this; @@ -305,7 +308,7 @@ class FunctionResultCallback_0_1 : public ResultCallback1 { : function_(function), self_deleting_(self_deleting) {} ~FunctionResultCallback_0_1() {} - R Run(Arg1 a1) { + R Run(Arg1 a1) override { bool needs_delete = self_deleting_; // read in case callback deletes R result = function_(a1); if (needs_delete) delete this; @@ -327,7 +330,7 @@ class FunctionResultCallback_1_1 : public ResultCallback1 { : function_(function), self_deleting_(self_deleting), p1_(p1) {} ~FunctionResultCallback_1_1() {} - R Run(A1 a1) { + R Run(A1 a1) override { bool needs_delete = self_deleting_; // read in case callback deletes R result = function_(p1_, a1); if (needs_delete) delete this; @@ -342,7 +345,7 @@ class FunctionResultCallback_1_1 : public ResultCallback1 { template struct InternalConstRef { - typedef typename remove_reference::type base_type; + typedef typename std::remove_reference::type base_type; typedef const base_type& type; }; @@ -370,12 +373,12 @@ class MethodResultCallback_0_0 : public ResultCallback { }; template -class MethodResultCallback_5_2 : public ResultCallback2 { + typename P4, typename P5, typename P6, typename A1, typename A2> +class MethodResultCallback_6_2 : public ResultCallback2 { public: - typedef R (T::*MethodType)(P1, P2, P3, P4, P5, A1, A2); - MethodResultCallback_5_2(T* object, MethodType method, bool self_deleting, - P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + typedef R (T::*MethodType)(P1, P2, P3, P4, P5, P6, A1, A2); + MethodResultCallback_6_2(T* object, MethodType method, bool self_deleting, + P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) : object_(object), method_(method), self_deleting_(self_deleting), @@ -383,12 +386,13 @@ class MethodResultCallback_5_2 : public ResultCallback2 { p2_(p2), p3_(p3), p4_(p4), - p5_(p5) {} - ~MethodResultCallback_5_2() {} + p5_(p5), + p6_(p6) {} + ~MethodResultCallback_6_2() {} - R Run(A1 a1, A2 a2) { + R Run(A1 a1, A2 a2) override { bool needs_delete = self_deleting_; - R result = (object_->*method_)(p1_, p2_, p3_, p4_, p5_, a1, a2); + R result = (object_->*method_)(p1_, p2_, p3_, p4_, p5_, p6_, a1, a2); if (needs_delete) delete this; return result; } @@ -397,11 +401,12 @@ class MethodResultCallback_5_2 : public ResultCallback2 { T* object_; MethodType method_; bool self_deleting_; - typename remove_reference::type p1_; - typename remove_reference::type p2_; - typename remove_reference::type p3_; - typename remove_reference::type p4_; - typename remove_reference::type p5_; + typename std::remove_reference::type p1_; + typename std::remove_reference::type p2_; + typename std::remove_reference::type p3_; + typename std::remove_reference::type p4_; + typename std::remove_reference::type p5_; + typename std::remove_reference::type p6_; }; } // namespace internal @@ -550,27 +555,29 @@ inline ResultCallback* NewPermanentCallback( return new internal::MethodResultCallback_0_0(object, function, false); } -// See MethodResultCallback_5_2 +// See MethodResultCallback_6_2 template + typename P4, typename P5, typename P6, typename A1, typename A2> inline ResultCallback2* NewPermanentCallback( - T* object, R (T::*function)(P1, P2, P3, P4, P5, A1, A2), + T* object, R (T::*function)(P1, P2, P3, P4, P5, P6, A1, A2), typename internal::InternalConstRef::type p1, typename internal::InternalConstRef::type p2, typename internal::InternalConstRef::type p3, typename internal::InternalConstRef::type p4, - typename internal::InternalConstRef::type p5) { - return new internal::MethodResultCallback_5_2(object, function, false, p1, - p2, p3, p4, p5); + typename internal::InternalConstRef::type p5, + typename internal::InternalConstRef::type p6) { + return new internal::MethodResultCallback_6_2(object, function, false, + p1, p2, p3, p4, p5, p6); } // A function which does nothing. Useful for creating no-op callbacks, e.g.: // Closure* nothing = NewCallback(&DoNothing); -void LIBPROTOBUF_EXPORT DoNothing(); - +void PROTOBUF_EXPORT DoNothing(); } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_STUBS_CALLBACK_H_ diff --git a/src/google/protobuf/stubs/casts.h b/src/google/protobuf/stubs/casts.h index be652849ef14e..d8a49cec34b2b 100644 --- a/src/google/protobuf/stubs/casts.h +++ b/src/google/protobuf/stubs/casts.h @@ -32,11 +32,14 @@ #define GOOGLE_PROTOBUF_CASTS_H__ #include -#include + +#include +#include namespace google { namespace protobuf { namespace internal { + // Use implicit_cast as a safe version of static_cast or const_cast // for upcasting in the type hierarchy (i.e. casting a pointer to Foo // to a pointer to SuperclassOfFoo or casting a pointer to Foo to @@ -44,7 +47,7 @@ namespace internal { // When you use implicit_cast, the compiler checks that the cast is safe. // Such explicit implicit_casts are necessary in surprisingly many // situations where C++ demands an exact type match instead of an -// argument type convertable to a target type. +// argument type convertible to a target type. // // The From type can be inferred, so the preferred syntax for using // implicit_cast is the same as for static_cast etc.: @@ -87,15 +90,15 @@ inline To down_cast(From* f) { // so we only accept pointers implicit_cast(0); } -#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI) - assert(f == NULL || dynamic_cast(f) != NULL); // RTTI: debug mode only! +#if !defined(NDEBUG) && PROTOBUF_RTTI + assert(f == nullptr || dynamic_cast(f) != nullptr); // RTTI: debug mode only! #endif return static_cast(f); } template // use like this: down_cast(foo); inline To down_cast(From& f) { - typedef typename remove_reference::type* ToAsPointer; + typedef typename std::remove_reference::type* ToAsPointer; // Ensures that To is a sub-type of From *. This test is here only // for compile-time type checking, and has no overhead in an // optimized build at run-time, as it will be optimized away @@ -104,9 +107,9 @@ inline To down_cast(From& f) { implicit_cast(0); } -#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI) +#if !defined(NDEBUG) && PROTOBUF_RTTI // RTTI: debug mode only! - assert(dynamic_cast(&f) != NULL); + assert(dynamic_cast(&f) != nullptr); #endif return *static_cast(&f); } @@ -130,4 +133,7 @@ using internal::bit_cast; } // namespace protobuf } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_CASTS_H__ diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc old mode 100755 new mode 100644 index 73822168b68eb..f2859e94bbee9 --- a/src/google/protobuf/stubs/common.cc +++ b/src/google/protobuf/stubs/common.cc @@ -30,20 +30,18 @@ // Author: kenton@google.com (Kenton Varda) -#include // TODO(gerbens) ideally remove this. #include -#include -#include -#include -#include -#include + +#include #include #include #include #include #ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN // We only need minimal includes +#endif #include #define snprintf _snprintf // see comment in strutil.cc #elif defined(HAVE_PTHREAD) @@ -55,6 +53,16 @@ #include #endif +#include +#include +#include +#include +#include +#include +#include + +#include + namespace google { namespace protobuf { @@ -88,7 +96,7 @@ void VerifyVersion(int headerVersion, } } -string VersionString(int version) { +std::string VersionString(int version) { int major = version / 1000000; int minor = (version / 1000) % 1000; int micro = version % 1000; @@ -119,7 +127,7 @@ namespace internal { #if defined(__ANDROID__) inline void DefaultLogHandler(LogLevel level, const char* filename, int line, - const string& message) { + const std::string& message) { if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) { return; } @@ -154,7 +162,7 @@ inline void DefaultLogHandler(LogLevel level, const char* filename, int line, #else void DefaultLogHandler(LogLevel level, const char* filename, int line, - const string& message) { + const std::string& message) { if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) { return; } @@ -169,29 +177,14 @@ void DefaultLogHandler(LogLevel level, const char* filename, int line, #endif void NullLogHandler(LogLevel /* level */, const char* /* filename */, - int /* line */, const string& /* message */) { + int /* line */, const std::string& /* message */) { // Nothing. } static LogHandler* log_handler_ = &DefaultLogHandler; -static int log_silencer_count_ = 0; - -static Mutex* log_silencer_count_mutex_ = NULL; -GOOGLE_PROTOBUF_DECLARE_ONCE(log_silencer_count_init_); - -void DeleteLogSilencerCount() { - delete log_silencer_count_mutex_; - log_silencer_count_mutex_ = NULL; -} -void InitLogSilencerCount() { - log_silencer_count_mutex_ = new Mutex; - OnShutdown(&DeleteLogSilencerCount); -} -void InitLogSilencerCountOnce() { - GoogleOnceInit(&log_silencer_count_init_, &InitLogSilencerCount); -} +static std::atomic log_silencer_count_ = ATOMIC_VAR_INIT(0); -LogMessage& LogMessage::operator<<(const string& value) { +LogMessage& LogMessage::operator<<(const std::string& value) { message_ += value; return *this; } @@ -206,8 +199,7 @@ LogMessage& LogMessage::operator<<(const StringPiece& value) { return *this; } -LogMessage& LogMessage::operator<<( - const ::google::protobuf::util::Status& status) { +LogMessage& LogMessage::operator<<(const util::Status& status) { message_ += status.ToString(); return *this; } @@ -243,8 +235,8 @@ DECLARE_STREAM_OPERATOR(long , "%ld") DECLARE_STREAM_OPERATOR(unsigned long, "%lu") DECLARE_STREAM_OPERATOR(double , "%g" ) DECLARE_STREAM_OPERATOR(void* , "%p" ) -DECLARE_STREAM_OPERATOR(long long , "%" GOOGLE_LL_FORMAT "d") -DECLARE_STREAM_OPERATOR(unsigned long long, "%" GOOGLE_LL_FORMAT "u") +DECLARE_STREAM_OPERATOR(long long , "%" PROTOBUF_LL_FORMAT "d") +DECLARE_STREAM_OPERATOR(unsigned long long, "%" PROTOBUF_LL_FORMAT "u") #undef DECLARE_STREAM_OPERATOR LogMessage::LogMessage(LogLevel level, const char* filename, int line) @@ -255,8 +247,6 @@ void LogMessage::Finish() { bool suppress = false; if (level_ != LOGLEVEL_FATAL) { - InitLogSilencerCountOnce(); - MutexLock lock(log_silencer_count_mutex_); suppress = log_silencer_count_ > 0; } @@ -282,9 +272,9 @@ void LogFinisher::operator=(LogMessage& other) { LogHandler* SetLogHandler(LogHandler* new_func) { LogHandler* old = internal::log_handler_; if (old == &internal::NullLogHandler) { - old = NULL; + old = nullptr; } - if (new_func == NULL) { + if (new_func == nullptr) { internal::log_handler_ = &internal::NullLogHandler; } else { internal::log_handler_ = new_func; @@ -293,14 +283,10 @@ LogHandler* SetLogHandler(LogHandler* new_func) { } LogSilencer::LogSilencer() { - internal::InitLogSilencerCountOnce(); - MutexLock lock(internal::log_silencer_count_mutex_); ++internal::log_silencer_count_; }; LogSilencer::~LogSilencer() { - internal::InitLogSilencerCountOnce(); - MutexLock lock(internal::log_silencer_count_mutex_); --internal::log_silencer_count_; }; @@ -313,92 +299,12 @@ namespace internal { FunctionClosure0::~FunctionClosure0() {} } void DoNothing() {} -// =================================================================== -// emulates google3/base/mutex.cc - -#ifdef _WIN32 - -struct Mutex::Internal { - CRITICAL_SECTION mutex; -#ifndef NDEBUG - // Used only to implement AssertHeld(). - DWORD thread_id; -#endif -}; - -Mutex::Mutex() - : mInternal(new Internal) { - InitializeCriticalSection(&mInternal->mutex); -} - -Mutex::~Mutex() { - DeleteCriticalSection(&mInternal->mutex); - delete mInternal; -} - -void Mutex::Lock() { - EnterCriticalSection(&mInternal->mutex); -#ifndef NDEBUG - mInternal->thread_id = GetCurrentThreadId(); -#endif -} - -void Mutex::Unlock() { -#ifndef NDEBUG - mInternal->thread_id = 0; -#endif - LeaveCriticalSection(&mInternal->mutex); -} - -void Mutex::AssertHeld() { -#ifndef NDEBUG - GOOGLE_DCHECK_EQ(mInternal->thread_id, GetCurrentThreadId()); -#endif -} - -#elif defined(HAVE_PTHREAD) - -struct Mutex::Internal { - pthread_mutex_t mutex; -}; - -Mutex::Mutex() - : mInternal(new Internal) { - pthread_mutex_init(&mInternal->mutex, NULL); -} - -Mutex::~Mutex() { - pthread_mutex_destroy(&mInternal->mutex); - delete mInternal; -} - -void Mutex::Lock() { - int result = pthread_mutex_lock(&mInternal->mutex); - if (result != 0) { - GOOGLE_LOG(FATAL) << "pthread_mutex_lock: " << strerror(result); - } -} - -void Mutex::Unlock() { - int result = pthread_mutex_unlock(&mInternal->mutex); - if (result != 0) { - GOOGLE_LOG(FATAL) << "pthread_mutex_unlock: " << strerror(result); - } -} - -void Mutex::AssertHeld() { - // pthreads dosn't provide a way to check which thread holds the mutex. - // TODO(kenton): Maybe keep track of locking thread ID like with WIN32? -} - -#endif - // =================================================================== // emulates google3/util/endian/endian.h // // TODO(xiaofeng): PROTOBUF_LITTLE_ENDIAN is unfortunately defined in // google/protobuf/io/coded_stream.h and therefore can not be used here. -// Maybe move that macro definition here in the furture. +// Maybe move that macro definition here in the future. uint32 ghtonl(uint32 x) { union { uint32 result; @@ -411,76 +317,6 @@ uint32 ghtonl(uint32 x) { return result; } -// =================================================================== -// Shutdown support. - -namespace internal { - -typedef void OnShutdownFunc(); -struct ShutdownData { - ~ShutdownData() { - for (int i = 0; i < functions.size(); i++) { - functions[i](); - } - for (int i = 0; i < strings.size(); i++) { - strings[i]->~string(); - } - for (int i = 0; i < messages.size(); i++) { - messages[i]->~MessageLite(); - } - } - - vector functions; - vector strings; - vector messages; - Mutex mutex; -}; - -ShutdownData* shutdown_data = NULL; -GOOGLE_PROTOBUF_DECLARE_ONCE(shutdown_functions_init); - -void InitShutdownFunctions() { - shutdown_data = new ShutdownData; -} - -inline void InitShutdownFunctionsOnce() { - GoogleOnceInit(&shutdown_functions_init, &InitShutdownFunctions); -} - -void OnShutdown(void (*func)()) { - InitShutdownFunctionsOnce(); - MutexLock lock(&shutdown_data->mutex); - shutdown_data->functions.push_back(func); -} - -void OnShutdownDestroyString(const std::string* ptr) { - InitShutdownFunctionsOnce(); - MutexLock lock(&shutdown_data->mutex); - shutdown_data->strings.push_back(ptr); -} - -void OnShutdownDestroyMessage(const void* ptr) { - InitShutdownFunctionsOnce(); - MutexLock lock(&shutdown_data->mutex); - shutdown_data->messages.push_back(static_cast(ptr)); -} - -} // namespace internal - -void ShutdownProtobufLibrary() { - internal::InitShutdownFunctionsOnce(); - - // We don't need to lock shutdown_functions_mutex because it's up to the - // caller to make sure that no one is using the library before this is - // called. - - // Make it safe to call this multiple times. - if (internal::shutdown_data == NULL) return; - - delete internal::shutdown_data; - internal::shutdown_data = NULL; -} - #if PROTOBUF_USE_EXCEPTIONS FatalException::~FatalException() throw() {} @@ -491,3 +327,5 @@ const char* FatalException::what() const throw() { } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h index ff36348292afb..c2edf7c9c5c38 100644 --- a/src/google/protobuf/stubs/common.h +++ b/src/google/protobuf/stubs/common.h @@ -38,19 +38,15 @@ #include #include #include +#include #include #include #include -#include #include #include - -// TODO(liujisi): Remove the following includes after the include clean-up. -#include -#include -#include -#include +#include +#include #ifndef PROTOBUF_USE_EXCEPTIONS #if defined(_MSC_VER) && defined(_CPPUNWIND) @@ -73,22 +69,7 @@ #include #endif -#if defined(_WIN32) && defined(GetMessage) -// Allow GetMessage to be used as a valid method name in protobuf classes. -// windows.h defines GetMessage() as a macro. Let's re-define it as an inline -// function. The inline function should be equivalent for C++ users. -inline BOOL GetMessage_Win32( - LPMSG lpMsg, HWND hWnd, - UINT wMsgFilterMin, UINT wMsgFilterMax) { - return GetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); -} -#undef GetMessage -inline BOOL GetMessage( - LPMSG lpMsg, HWND hWnd, - UINT wMsgFilterMin, UINT wMsgFilterMax) { - return GetMessage_Win32(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); -} -#endif +#include namespace std {} @@ -101,35 +82,31 @@ namespace internal { // The current version, represented as a single integer to make comparison // easier: major * 10^6 + minor * 10^3 + micro -#define GOOGLE_PROTOBUF_VERSION 3004000 +#define GOOGLE_PROTOBUF_VERSION 3015000 // A suffix string for alpha, beta or rc releases. Empty for stable releases. #define GOOGLE_PROTOBUF_VERSION_SUFFIX "" -// The minimum library version which works with the current version of the -// headers. -#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3004000 - // The minimum header version which works with the current version of // the library. This constant should only be used by protoc's C++ code // generator. -static const int kMinHeaderVersionForLibrary = 3004000; +static const int kMinHeaderVersionForLibrary = 3015000; // The minimum protoc version which works with the current version of the // headers. -#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3004000 +#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3015000 // The minimum header version which works with the current version of // protoc. This constant should only be used in VerifyVersion(). -static const int kMinHeaderVersionForProtoc = 3004000; +static const int kMinHeaderVersionForProtoc = 3015000; // Verifies that the headers and libraries are compatible. Use the macro // below to call this. -void LIBPROTOBUF_EXPORT VerifyVersion(int headerVersion, int minLibraryVersion, - const char* filename); +void PROTOBUF_EXPORT VerifyVersion(int headerVersion, int minLibraryVersion, + const char* filename); // Converts a numeric version number to a string. -std::string LIBPROTOBUF_EXPORT VersionString(int version); +std::string PROTOBUF_EXPORT VersionString(int version); } // namespace internal @@ -151,14 +128,14 @@ namespace internal { // Checks if the buffer contains structurally-valid UTF-8. Implemented in // structurally_valid.cc. -LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len); +PROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len); -inline bool IsStructurallyValidUTF8(const std::string& str) { +inline bool IsStructurallyValidUTF8(StringPiece str) { return IsStructurallyValidUTF8(str.data(), static_cast(str.length())); } -// Returns initial number of bytes of structually valid UTF-8. -LIBPROTOBUF_EXPORT int UTF8SpnStructurallyValid(const StringPiece& str); +// Returns initial number of bytes of structurally valid UTF-8. +PROTOBUF_EXPORT int UTF8SpnStructurallyValid(StringPiece str); // Coerce UTF-8 byte string in src_str to be // a structurally-valid equal-length string by selectively @@ -172,38 +149,24 @@ LIBPROTOBUF_EXPORT int UTF8SpnStructurallyValid(const StringPiece& str); // // Optimized for: all structurally valid and no byte copying is done. // -LIBPROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid( - const StringPiece& str, char* dst, char replace_char); +PROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(StringPiece str, char* dst, + char replace_char); } // namespace internal - -// =================================================================== -// Shutdown support. - -// Shut down the entire protocol buffers library, deleting all static-duration -// objects allocated by the library or by generated .pb.cc files. -// -// There are two reasons you might want to call this: -// * You use a draconian definition of "memory leak" in which you expect -// every single malloc() to have a corresponding free(), even for objects -// which live until program exit. -// * You are writing a dynamically-loaded library which needs to clean up -// after itself when the library is unloaded. -// -// It is safe to call this multiple times. However, it is not safe to use -// any other part of the protocol buffers library after -// ShutdownProtobufLibrary() has been called. -LIBPROTOBUF_EXPORT void ShutdownProtobufLibrary(); +// This lives in message_lite.h now, but we leave this here for any users that +// #include common.h and not message_lite.h. +PROTOBUF_EXPORT void ShutdownProtobufLibrary(); namespace internal { -// Register a function to be called when ShutdownProtocolBuffers() is called. -LIBPROTOBUF_EXPORT void OnShutdown(void (*func)()); -// Destroy the string (call string destructor) -LIBPROTOBUF_EXPORT void OnShutdownDestroyString(const std::string* ptr); -// Destroy (not delete) the message -LIBPROTOBUF_EXPORT void OnShutdownDestroyMessage(const void* ptr); +// Strongly references the given variable such that the linker will be forced +// to pull in this variable's translation unit. +template +void StrongReference(const T& var) { + auto volatile unused = &var; + (void)&unused; // Use address to avoid an extra load of "unused". +} } // namespace internal @@ -229,14 +192,11 @@ class FatalException : public std::exception { // This is at the end of the file instead of the beginning to work around a bug // in some versions of MSVC. -// TODO(acozzette): remove these using statements -using std::istream; -using std::ostream; -using std::pair; using std::string; -using std::vector; } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_COMMON_H__ diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc index f9e2cfd4370ad..c55e452505746 100644 --- a/src/google/protobuf/stubs/common_unittest.cc +++ b/src/google/protobuf/stubs/common_unittest.cc @@ -31,8 +31,10 @@ // Author: kenton@google.com (Kenton Varda) #include +#include #include #include +#include #include #include @@ -51,7 +53,7 @@ TEST(VersionTest, VersionMatchesConfig) { // Verify that the version string specified in config.h matches the one // in common.h. The config.h version is a string which may have a suffix // like "beta" or "rc1", so we remove that. - string version = PACKAGE_VERSION; + std::string version = PACKAGE_VERSION; int pos = 0; while (pos < version.size() && (ascii_isdigit(version[pos]) || version[pos] == '.')) { @@ -75,10 +77,10 @@ TEST(CommonTest, IntMinMaxConstants) { EXPECT_EQ(0, kuint64max + 1); } -vector captured_messages_; +std::vector captured_messages_; void CaptureLog(LogLevel level, const char* filename, int line, - const string& message) { + const std::string& message) { captured_messages_.push_back( strings::Substitute("$0 $1:$2: $3", implicit_cast(level), filename, line, message)); @@ -91,7 +93,7 @@ TEST(LoggingTest, DefaultLogging) { GOOGLE_LOG(WARNING) << "A warning."; GOOGLE_LOG(ERROR ) << "An error."; - string text = GetCapturedTestStderr(); + std::string text = GetCapturedTestStderr(); EXPECT_EQ( "[libprotobuf INFO " __FILE__ ":" + SimpleItoa(line + 1) + "] A message.\n" "[libprotobuf WARNING " __FILE__ ":" + SimpleItoa(line + 2) + "] A warning.\n" @@ -100,16 +102,16 @@ TEST(LoggingTest, DefaultLogging) { } TEST(LoggingTest, NullLogging) { - LogHandler* old_handler = SetLogHandler(NULL); + LogHandler* old_handler = SetLogHandler(nullptr); CaptureTestStderr(); GOOGLE_LOG(INFO ) << "A message."; GOOGLE_LOG(WARNING) << "A warning."; GOOGLE_LOG(ERROR ) << "An error."; - EXPECT_TRUE(SetLogHandler(old_handler) == NULL); + EXPECT_TRUE(SetLogHandler(old_handler) == nullptr); - string text = GetCapturedTestStderr(); + std::string text = GetCapturedTestStderr(); EXPECT_EQ("", text); } @@ -165,10 +167,10 @@ class ClosureTest : public testing::Test { static void SetA123Function() { current_instance_->a_ = 123; } void SetAMethod(int a) { a_ = a; } - void SetCMethod(string c) { c_ = c; } + void SetCMethod(std::string c) { c_ = c; } static void SetAFunction(int a) { current_instance_->a_ = a; } - static void SetCFunction(string c) { current_instance_->c_ = c; } + static void SetCFunction(std::string c) { current_instance_->c_ = c; } void SetABMethod(int a, const char* b) { a_ = a; b_ = b; } static void SetABFunction(int a, const char* b) { @@ -179,9 +181,9 @@ class ClosureTest : public testing::Test { virtual void SetUp() { current_instance_ = this; a_ = 0; - b_ = NULL; + b_ = nullptr; c_.clear(); - permanent_closure_ = NULL; + permanent_closure_ = nullptr; } void DeleteClosureInCallback() { @@ -190,13 +192,13 @@ class ClosureTest : public testing::Test { int a_; const char* b_; - string c_; + std::string c_; Closure* permanent_closure_; static ClosureTest* current_instance_; }; -ClosureTest* ClosureTest::current_instance_ = NULL; +ClosureTest* ClosureTest::current_instance_ = nullptr; TEST_F(ClosureTest, TestClosureFunction0) { Closure* closure = NewCallback(&SetA123Function); @@ -229,15 +231,15 @@ TEST_F(ClosureTest, TestClosureMethod1) { } TEST_F(ClosureTest, TestClosureFunction1String) { - Closure* closure = NewCallback(&SetCFunction, string("test")); + Closure* closure = NewCallback(&SetCFunction, std::string("test")); EXPECT_NE("test", c_); closure->Run(); EXPECT_EQ("test", c_); } TEST_F(ClosureTest, TestClosureMethod1String) { - Closure* closure = NewCallback(current_instance_, - &ClosureTest::SetCMethod, string("test")); + Closure* closure = NewCallback(current_instance_, &ClosureTest::SetCMethod, + std::string("test")); EXPECT_NE("test", c_); closure->Run(); EXPECT_EQ("test", c_); @@ -321,7 +323,7 @@ TEST_F(ClosureTest, TestPermanentClosureFunction2) { EXPECT_EQ(789, a_); EXPECT_EQ(cstr, b_); a_ = 0; - b_ = NULL; + b_ = nullptr; closure->Run(); EXPECT_EQ(789, a_); EXPECT_EQ(cstr, b_); @@ -338,7 +340,7 @@ TEST_F(ClosureTest, TestPermanentClosureMethod2) { EXPECT_EQ(789, a_); EXPECT_EQ(cstr, b_); a_ = 0; - b_ = NULL; + b_ = nullptr; closure->Run(); EXPECT_EQ(789, a_); EXPECT_EQ(cstr, b_); diff --git a/src/google/protobuf/stubs/fastmem.h b/src/google/protobuf/stubs/fastmem.h deleted file mode 100644 index 1f1f6ed3df41a..0000000000000 --- a/src/google/protobuf/stubs/fastmem.h +++ /dev/null @@ -1,153 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2014 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Fast memory copying and comparison routines. -// strings::fastmemcmp_inlined() replaces memcmp() -// strings::memcpy_inlined() replaces memcpy() -// strings::memeq(a, b, n) replaces memcmp(a, b, n) == 0 -// -// strings::*_inlined() routines are inline versions of the -// routines exported by this module. Sometimes using the inlined -// versions is faster. Measure before using the inlined versions. -// -// Performance measurement: -// strings::fastmemcmp_inlined -// Analysis: memcmp, fastmemcmp_inlined, fastmemcmp -// 2012-01-30 - -#ifndef GOOGLE_PROTOBUF_STUBS_FASTMEM_H_ -#define GOOGLE_PROTOBUF_STUBS_FASTMEM_H_ - -#include -#include -#include - -#include - -namespace google { -namespace protobuf { -namespace internal { - -// Return true if the n bytes at a equal the n bytes at b. -// The regions are allowed to overlap. -// -// The performance is similar to the performance memcmp(), but faster for -// moderately-sized inputs, or inputs that share a common prefix and differ -// somewhere in their last 8 bytes. Further optimizations can be added later -// if it makes sense to do so.:w -inline bool memeq(const char* a, const char* b, size_t n) { - size_t n_rounded_down = n & ~static_cast(7); - if (GOOGLE_PREDICT_FALSE(n_rounded_down == 0)) { // n <= 7 - return memcmp(a, b, n) == 0; - } - // n >= 8 - uint64 u = GOOGLE_UNALIGNED_LOAD64(a) ^ GOOGLE_UNALIGNED_LOAD64(b); - uint64 v = GOOGLE_UNALIGNED_LOAD64(a + n - 8) ^ GOOGLE_UNALIGNED_LOAD64(b + n - 8); - if ((u | v) != 0) { // The first or last 8 bytes differ. - return false; - } - a += 8; - b += 8; - n = n_rounded_down - 8; - if (n > 128) { - // As of 2012, memcmp on x86-64 uses a big unrolled loop with SSE2 - // instructions, and while we could try to do something faster, it - // doesn't seem worth pursuing. - return memcmp(a, b, n) == 0; - } - for (; n >= 16; n -= 16) { - uint64 x = GOOGLE_UNALIGNED_LOAD64(a) ^ GOOGLE_UNALIGNED_LOAD64(b); - uint64 y = GOOGLE_UNALIGNED_LOAD64(a + 8) ^ GOOGLE_UNALIGNED_LOAD64(b + 8); - if ((x | y) != 0) { - return false; - } - a += 16; - b += 16; - } - // n must be 0 or 8 now because it was a multiple of 8 at the top of the loop. - return n == 0 || GOOGLE_UNALIGNED_LOAD64(a) == GOOGLE_UNALIGNED_LOAD64(b); -} - -inline int fastmemcmp_inlined(const char *a, const char *b, size_t n) { - if (n >= 64) { - return memcmp(a, b, n); - } - const char* a_limit = a + n; - while (a + sizeof(uint64) <= a_limit && - GOOGLE_UNALIGNED_LOAD64(a) == GOOGLE_UNALIGNED_LOAD64(b)) { - a += sizeof(uint64); - b += sizeof(uint64); - } - if (a + sizeof(uint32) <= a_limit && - GOOGLE_UNALIGNED_LOAD32(a) == GOOGLE_UNALIGNED_LOAD32(b)) { - a += sizeof(uint32); - b += sizeof(uint32); - } - while (a < a_limit) { - int d = - static_cast(static_cast(*a++) - static_cast(*b++)); - if (d) return d; - } - return 0; -} - -// The standard memcpy operation is slow for variable small sizes. -// This implementation inlines the optimal realization for sizes 1 to 16. -// To avoid code bloat don't use it in case of not performance-critical spots, -// nor when you don't expect very frequent values of size <= 16. -inline void memcpy_inlined(char *dst, const char *src, size_t size) { - // Compiler inlines code with minimal amount of data movement when third - // parameter of memcpy is a constant. - switch (size) { - case 1: memcpy(dst, src, 1); break; - case 2: memcpy(dst, src, 2); break; - case 3: memcpy(dst, src, 3); break; - case 4: memcpy(dst, src, 4); break; - case 5: memcpy(dst, src, 5); break; - case 6: memcpy(dst, src, 6); break; - case 7: memcpy(dst, src, 7); break; - case 8: memcpy(dst, src, 8); break; - case 9: memcpy(dst, src, 9); break; - case 10: memcpy(dst, src, 10); break; - case 11: memcpy(dst, src, 11); break; - case 12: memcpy(dst, src, 12); break; - case 13: memcpy(dst, src, 13); break; - case 14: memcpy(dst, src, 14); break; - case 15: memcpy(dst, src, 15); break; - case 16: memcpy(dst, src, 16); break; - default: memcpy(dst, src, size); break; - } -} - -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_STUBS_FASTMEM_H_ diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h index 612b5861ccf27..a7ec068074847 100644 --- a/src/google/protobuf/stubs/hash.h +++ b/src/google/protobuf/stubs/hash.h @@ -29,312 +29,25 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Author: kenton@google.com (Kenton Varda) -// -// Deals with the fact that hash_map is not defined everywhere. #ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__ #define GOOGLE_PROTOBUF_STUBS_HASH_H__ -#include -#include - -#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1 -#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1 - -// Use C++11 unordered_{map|set} if available. -#if ((defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER >= 11) || \ - (((__cplusplus >= 201103L) || defined(__GXX_EXPERIMENTAL_CXX0X)) && \ - (__GLIBCXX__ > 20090421))) -# define GOOGLE_PROTOBUF_HAS_CXX11_HASH - -// For XCode >= 4.6: the compiler is clang with libc++. -// For earlier XCode version: the compiler is gcc-4.2.1 with libstdc++. -// libc++ provides and friends even in non C++11 mode, -// and it does not provide the tr1 library. Therefore the following macro -// checks against this special case. -// Note that we should not test the __APPLE_CC__ version number or the -// __clang__ macro, since the new compiler can still use -stdlib=libstdc++, in -// which case is not compilable without -std=c++11 -#elif defined(__APPLE_CC__) -# if __GNUC__ >= 4 -# define GOOGLE_PROTOBUF_HAS_TR1 -# else -// Not tested for gcc < 4... These setting can compile under 4.2.1 though. -# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx -# include -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map -# include -# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set -# endif - -// Version checks for gcc. -#elif defined(__GNUC__) -// For GCC 4.x+, use tr1::unordered_map/set; otherwise, follow the -// instructions from: -// https://gcc.gnu.org/onlinedocs/libstdc++/manual/backwards.html -# if __GNUC__ >= 4 -# define GOOGLE_PROTOBUF_HAS_TR1 -# elif __GNUC__ >= 3 -# include -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map -# include -# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set -# if __GNUC__ == 3 && __GNUC_MINOR__ == 0 -# define GOOGLE_PROTOBUF_HASH_NAMESPACE std // GCC 3.0 -# else -# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx // GCC 3.1 and later -# endif -# else -# define GOOGLE_PROTOBUF_HASH_NAMESPACE -# include -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map -# include -# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set -# endif - -// GCC <= 4.1 does not define std::tr1::hash for `long long int` or `long long unsigned int` -# if __GNUC__ == 4 && __GNUC__MINOR__ <= 1 -# define GOOGLE_PROTOBUF_MISSING_HASH -# include -# include -# endif - -// Version checks for MSC. -// Apparently Microsoft decided to move hash_map *back* to the std namespace in -// MSVC 2010: -// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx -// And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That -// said, use unordered_map for MSVC 2010 and beyond is our safest bet. -#elif defined(_MSC_VER) -# if _MSC_VER >= 1600 // Since Visual Studio 2010 -# define GOOGLE_PROTOBUF_HAS_CXX11_HASH -# define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare -# elif _MSC_VER >= 1500 // Since Visual Studio 2008 -# define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext -# include -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map -# include -# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set -# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare -# define GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE -# elif _MSC_VER >= 1310 -# define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext -# include -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map -# include -# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set -# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare -# else -# define GOOGLE_PROTOBUF_HASH_NAMESPACE std -# include -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map -# include -# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set -# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare -# endif - -// **ADD NEW COMPILERS SUPPORT HERE.** -// For other compilers, undefine the macro and fallback to use std::map, in -// google/protobuf/stubs/hash.h -#else -# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP -# undef GOOGLE_PROTOBUF_HAVE_HASH_SET -#endif - -#if defined(GOOGLE_PROTOBUF_HAS_CXX11_HASH) -# define GOOGLE_PROTOBUF_HASH_NAMESPACE std -# include -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map -# include -# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set -#elif defined(GOOGLE_PROTOBUF_HAS_TR1) -# define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1 -# include -# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map -# include -# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set -#endif +#include +#include +#include +#include # define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START \ namespace google { \ namespace protobuf { # define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END }} -#undef GOOGLE_PROTOBUF_HAS_CXX11_HASH -#undef GOOGLE_PROTOBUF_HAS_TR1 - -#if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \ - defined(GOOGLE_PROTOBUF_HAVE_HASH_SET) -#else -#define GOOGLE_PROTOBUF_MISSING_HASH -#include -#include -#endif - namespace google { namespace protobuf { -#ifdef GOOGLE_PROTOBUF_MISSING_HASH -#undef GOOGLE_PROTOBUF_MISSING_HASH - -// This system doesn't have hash_map or hash_set. Emulate them using map and -// set. - -// Make hash be the same as less. Note that everywhere where custom -// hash functions are defined in the protobuf code, they are also defined such -// that they can be used as "less" functions, which is required by MSVC anyway. template -struct hash { - // Dummy, just to make derivative hash functions compile. - int operator()(const Key& key) { - GOOGLE_LOG(FATAL) << "Should never be called."; - return 0; - } - - inline bool operator()(const Key& a, const Key& b) const { - return a < b; - } -}; - -// Make sure char* is compared by value. -template <> -struct hash { - // Dummy, just to make derivative hash functions compile. - int operator()(const char* key) { - GOOGLE_LOG(FATAL) << "Should never be called."; - return 0; - } - - inline bool operator()(const char* a, const char* b) const { - return strcmp(a, b) < 0; - } -}; - -template , - typename EqualKey = std::equal_to, - typename Alloc = std::allocator< std::pair > > -class hash_map : public std::map { - typedef std::map BaseClass; - - public: - hash_map(int a = 0, const HashFcn& b = HashFcn(), - const EqualKey& c = EqualKey(), - const Alloc& d = Alloc()) : BaseClass(b, d) {} - - HashFcn hash_function() const { return HashFcn(); } -}; - -template , - typename EqualKey = std::equal_to > -class hash_set : public std::set { - public: - hash_set(int = 0) {} - - HashFcn hash_function() const { return HashFcn(); } -}; - -#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION) - -template -struct hash : public GOOGLE_PROTOBUF_HASH_COMPARE { -}; - -// MSVC's hash_compare hashes based on the string contents but -// compares based on the string pointer. WTF? -class CstringLess { - public: - inline bool operator()(const char* a, const char* b) const { - return strcmp(a, b) < 0; - } -}; - -template <> -struct hash - : public GOOGLE_PROTOBUF_HASH_COMPARE {}; - -#ifdef GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE - -template -struct InternalHashCompare : public GOOGLE_PROTOBUF_HASH_COMPARE { - InternalHashCompare() {} - InternalHashCompare(HashFcn hashfcn, EqualKey equalkey) - : hashfcn_(hashfcn), equalkey_(equalkey) {} - size_t operator()(const Key& key) const { return hashfcn_(key); } - bool operator()(const Key& key1, const Key& key2) const { - return !equalkey_(key1, key2); - } - HashFcn hashfcn_; - EqualKey equalkey_; -}; - -template , - typename EqualKey = std::equal_to, - typename Alloc = std::allocator< std::pair > > -class hash_map - : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< - Key, Data, InternalHashCompare, Alloc> { - typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< - Key, Data, InternalHashCompare, Alloc> BaseClass; - - public: - hash_map(int a = 0, const HashFcn& b = HashFcn(), - const EqualKey& c = EqualKey(), const Alloc& d = Alloc()) - : BaseClass(InternalHashCompare(b, c), d) {} - - HashFcn hash_function() const { return HashFcn(); } -}; - -template , - typename EqualKey = std::equal_to > -class hash_set - : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS< - Key, InternalHashCompare > { - public: - hash_set(int = 0) {} - - HashFcn hash_function() const { return HashFcn(); } -}; - -#else // GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE - -template , - typename EqualKey = std::equal_to, - typename Alloc = std::allocator< std::pair > > -class hash_map - : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< - Key, Data, HashFcn, EqualKey, Alloc> { - typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< - Key, Data, HashFcn, EqualKey, Alloc> BaseClass; - - public: - hash_map(int a = 0, const HashFcn& b = HashFcn(), - const EqualKey& c = EqualKey(), - const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {} - - HashFcn hash_function() const { return HashFcn(); } -}; - -template , - typename EqualKey = std::equal_to > -class hash_set - : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS< - Key, HashFcn, EqualKey> { - public: - hash_set(int = 0) {} - - HashFcn hash_function() const { return HashFcn(); } -}; -#endif // GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE - -#else // defined(_MSC_VER) && !defined(_STLPORT_VERSION) - -template -struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash { -}; +struct hash : public std::hash {}; template struct hash { @@ -363,53 +76,22 @@ struct hash { } }; -template , - typename EqualKey = std::equal_to, - typename Alloc = std::allocator< std::pair > > -class hash_map - : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< - Key, Data, HashFcn, EqualKey, Alloc> { - typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< - Key, Data, HashFcn, EqualKey, Alloc> BaseClass; - - public: - hash_map(int a = 0, const HashFcn& b = HashFcn(), - const EqualKey& c = EqualKey(), - const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {} - - HashFcn hash_function() const { return HashFcn(); } -}; - -template , - typename EqualKey = std::equal_to > -class hash_set - : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS< - Key, HashFcn, EqualKey> { - public: - hash_set(int = 0) {} - - HashFcn hash_function() const { return HashFcn(); } -}; - -#endif // !GOOGLE_PROTOBUF_MISSING_HASH - template <> -struct hash { - inline size_t operator()(const string& key) const { +struct hash { + inline size_t operator()(const std::string& key) const { return hash()(key.c_str()); } static const size_t bucket_size = 4; static const size_t min_buckets = 8; - inline bool operator()(const string& a, const string& b) const { + inline bool operator()(const std::string& a, const std::string& b) const { return a < b; } }; template -struct hash > { - inline size_t operator()(const pair& key) const { +struct hash > { + inline size_t operator()(const std::pair& key) const { size_t first_hash = hash()(key.first); size_t second_hash = hash()(key.second); @@ -420,20 +102,12 @@ struct hash > { static const size_t bucket_size = 4; static const size_t min_buckets = 8; - inline bool operator()(const pair& a, - const pair& b) const { + inline bool operator()(const std::pair& a, + const std::pair& b) const { return a < b; } }; -// Used by GCC/SGI STL only. (Why isn't this provided by the standard -// library? :( ) -struct streq { - inline bool operator()(const char* a, const char* b) const { - return strcmp(a, b) == 0; - } -}; - } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/int128.cc b/src/google/protobuf/stubs/int128.cc index a509080148009..7fc7dd8c5e19c 100644 --- a/src/google/protobuf/stubs/int128.cc +++ b/src/google/protobuf/stubs/int128.cc @@ -34,12 +34,16 @@ #include // NOLINT(readability/streams) #include +#include + +#include + namespace google { namespace protobuf { const uint128_pod kuint128max = { - static_cast(GOOGLE_LONGLONG(0xFFFFFFFFFFFFFFFF)), - static_cast(GOOGLE_LONGLONG(0xFFFFFFFFFFFFFFFF)) + static_cast(PROTOBUF_LONGLONG(0xFFFFFFFFFFFFFFFF)), + static_cast(PROTOBUF_LONGLONG(0xFFFFFFFFFFFFFFFF)) }; // Returns the 0-based position of the last set bit (i.e., most significant bit) @@ -63,7 +67,7 @@ static inline int Fls64(uint64 n) { STEP(uint32, n32, pos, 0x10); STEP(uint32, n32, pos, 0x08); STEP(uint32, n32, pos, 0x04); - return pos + ((GOOGLE_ULONGLONG(0x3333333322221100) >> (n32 << 2)) & 0x3); + return pos + ((PROTOBUF_ULONGLONG(0x3333333322221100) >> (n32 << 2)) & 0x3); } #undef STEP @@ -76,52 +80,36 @@ static inline int Fls128(uint128 n) { return Fls64(Uint128Low64(n)); } -// Long division/modulo for uint128 implemented using the shift-subtract -// division algorithm adapted from: -// http://stackoverflow.com/questions/5386377/division-without-using void uint128::DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret, uint128* remainder_ret) { if (divisor == 0) { GOOGLE_LOG(FATAL) << "Division or mod by zero: dividend.hi=" << dividend.hi_ << ", lo=" << dividend.lo_; - } - - if (divisor > dividend) { + } else if (dividend < divisor) { *quotient_ret = 0; *remainder_ret = dividend; return; - } - - if (divisor == dividend) { - *quotient_ret = 1; - *remainder_ret = 0; - return; - } - - uint128 denominator = divisor; - uint128 position = 1; - uint128 quotient = 0; - - // Left aligns the MSB of the denominator and the dividend. - int shift = Fls128(dividend) - Fls128(denominator); - denominator <<= shift; - position <<= shift; - - // Uses shift-subtract algorithm to divide dividend by denominator. The - // remainder will be left in dividend. - while (position > 0) { - if (dividend >= denominator) { - dividend -= denominator; - quotient |= position; + } else { + int dividend_bit_length = Fls128(dividend); + int divisor_bit_length = Fls128(divisor); + int difference = dividend_bit_length - divisor_bit_length; + uint128 quotient = 0; + while (difference >= 0) { + quotient <<= 1; + uint128 shifted_divisor = divisor << difference; + if (shifted_divisor <= dividend) { + dividend -= shifted_divisor; + quotient += 1; + } + difference -= 1; } - position >>= 1; - denominator >>= 1; + //record the final quotient and remainder + *quotient_ret = quotient; + *remainder_ret = dividend; } - - *quotient_ret = quotient; - *remainder_ret = dividend; } + uint128& uint128::operator/=(const uint128& divisor) { uint128 quotient = 0; uint128 remainder = 0; @@ -145,15 +133,18 @@ std::ostream& operator<<(std::ostream& o, const uint128& b) { std::streamsize div_base_log; switch (flags & std::ios::basefield) { case std::ios::hex: - div = static_cast(GOOGLE_ULONGLONG(0x1000000000000000)); // 16^15 + div = + static_cast(PROTOBUF_ULONGLONG(0x1000000000000000)); // 16^15 div_base_log = 15; break; case std::ios::oct: - div = static_cast(GOOGLE_ULONGLONG(01000000000000000000000)); // 8^21 + div = static_cast( + PROTOBUF_ULONGLONG(01000000000000000000000)); // 8^21 div_base_log = 21; break; default: // std::ios::dec - div = static_cast(GOOGLE_ULONGLONG(10000000000000000000)); // 10^19 + div = static_cast( + PROTOBUF_ULONGLONG(10000000000000000000)); // 10^19 div_base_log = 19; break; } @@ -199,3 +190,5 @@ std::ostream& operator<<(std::ostream& o, const uint128& b) { } // namespace protobuf } // namespace google + +#include // NOLINT diff --git a/src/google/protobuf/stubs/int128.h b/src/google/protobuf/stubs/int128.h index 1499bb76d5e0b..dc70d96eb3ea3 100644 --- a/src/google/protobuf/stubs/int128.h +++ b/src/google/protobuf/stubs/int128.h @@ -34,6 +34,8 @@ #include +#include + namespace google { namespace protobuf { @@ -48,7 +50,7 @@ struct uint128_pod; #endif // An unsigned 128-bit integer type. Thread-compatible. -class LIBPROTOBUF_EXPORT uint128 { +class PROTOBUF_EXPORT uint128 { public: UINT128_CONSTEXPR uint128(); // Sets to 0, but don't trust on this behavior. UINT128_CONSTEXPR uint128(uint64 top, uint64 bottom); @@ -84,8 +86,8 @@ class LIBPROTOBUF_EXPORT uint128 { friend uint64 Uint128High64(const uint128& v); // We add "std::" to avoid including all of port.h. - LIBPROTOBUF_EXPORT friend std::ostream& operator<<(std::ostream& o, - const uint128& b); + PROTOBUF_EXPORT friend std::ostream& operator<<(std::ostream& o, + const uint128& b); private: static void DivModImpl(uint128 dividend, uint128 divisor, @@ -116,11 +118,11 @@ struct uint128_pod { uint64 lo; }; -LIBPROTOBUF_EXPORT extern const uint128_pod kuint128max; +PROTOBUF_EXPORT extern const uint128_pod kuint128max; // allow uint128 to be logged -LIBPROTOBUF_EXPORT extern std::ostream& operator<<(std::ostream& o, - const uint128& b); +PROTOBUF_EXPORT extern std::ostream& operator<<(std::ostream& o, + const uint128& b); // Methods to access low and high pieces of 128-bit value. // Defined externally from uint128 to facilitate conversion @@ -380,4 +382,6 @@ inline uint128& uint128::operator--() { } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_STUBS_INT128_H_ diff --git a/src/google/protobuf/stubs/int128_unittest.cc b/src/google/protobuf/stubs/int128_unittest.cc index 1ec899ad7b75d..53dbd09ec0c4b 100644 --- a/src/google/protobuf/stubs/int128_unittest.cc +++ b/src/google/protobuf/stubs/int128_unittest.cc @@ -37,6 +37,8 @@ #include #include +#include + namespace google { namespace protobuf { @@ -291,24 +293,26 @@ TEST(Int128, Multiply) { } // Verified with dc. - a = uint128(GOOGLE_ULONGLONG(0xffffeeeeddddcccc), - GOOGLE_ULONGLONG(0xbbbbaaaa99998888)); - b = uint128(GOOGLE_ULONGLONG(0x7777666655554444), - GOOGLE_ULONGLONG(0x3333222211110000)); + a = uint128(PROTOBUF_ULONGLONG(0xffffeeeeddddcccc), + PROTOBUF_ULONGLONG(0xbbbbaaaa99998888)); + b = uint128(PROTOBUF_ULONGLONG(0x7777666655554444), + PROTOBUF_ULONGLONG(0x3333222211110000)); c = a * b; - EXPECT_EQ(uint128(GOOGLE_ULONGLONG(0x530EDA741C71D4C3), - GOOGLE_ULONGLONG(0xBF25975319080000)), c); + EXPECT_EQ(uint128(PROTOBUF_ULONGLONG(0x530EDA741C71D4C3), + PROTOBUF_ULONGLONG(0xBF25975319080000)), + c); EXPECT_EQ(0, c - b * a); - EXPECT_EQ(a*a - b*b, (a+b) * (a-b)); + EXPECT_EQ(a * a - b * b, (a + b) * (a - b)); // Verified with dc. - a = uint128(GOOGLE_ULONGLONG(0x0123456789abcdef), - GOOGLE_ULONGLONG(0xfedcba9876543210)); - b = uint128(GOOGLE_ULONGLONG(0x02468ace13579bdf), - GOOGLE_ULONGLONG(0xfdb97531eca86420)); + a = uint128(PROTOBUF_ULONGLONG(0x0123456789abcdef), + PROTOBUF_ULONGLONG(0xfedcba9876543210)); + b = uint128(PROTOBUF_ULONGLONG(0x02468ace13579bdf), + PROTOBUF_ULONGLONG(0xfdb97531eca86420)); c = a * b; - EXPECT_EQ(uint128(GOOGLE_ULONGLONG(0x97a87f4f261ba3f2), - GOOGLE_ULONGLONG(0x342d0bbf48948200)), c); + EXPECT_EQ(uint128(PROTOBUF_ULONGLONG(0x97a87f4f261ba3f2), + PROTOBUF_ULONGLONG(0x342d0bbf48948200)), + c); EXPECT_EQ(0, c - b * a); EXPECT_EQ(a*a - b*b, (a+b) * (a-b)); } @@ -355,10 +359,10 @@ TEST(Int128, DivideAndMod) { EXPECT_EQ(0, q); EXPECT_EQ(0, r); - a = uint128(GOOGLE_ULONGLONG(0x530eda741c71d4c3), - GOOGLE_ULONGLONG(0xbf25975319080000)); - q = uint128(GOOGLE_ULONGLONG(0x4de2cab081), - GOOGLE_ULONGLONG(0x14c34ab4676e4bab)); + a = uint128(PROTOBUF_ULONGLONG(0x530eda741c71d4c3), + PROTOBUF_ULONGLONG(0xbf25975319080000)); + q = uint128(PROTOBUF_ULONGLONG(0x4de2cab081), + PROTOBUF_ULONGLONG(0x14c34ab4676e4bab)); b = uint128(0x1110001); r = uint128(0x3eb455); ASSERT_EQ(a, q * b + r); // Sanity-check. @@ -396,8 +400,8 @@ TEST(Int128, DivideAndMod) { // Try a large remainder. b = a / 2 + 1; - uint128 expected_r(GOOGLE_ULONGLONG(0x29876d3a0e38ea61), - GOOGLE_ULONGLONG(0xdf92cba98c83ffff)); + uint128 expected_r(PROTOBUF_ULONGLONG(0x29876d3a0e38ea61), + PROTOBUF_ULONGLONG(0xdf92cba98c83ffff)); // Sanity checks. ASSERT_EQ(a / 2 - 1, expected_r); ASSERT_EQ(a, b + expected_r); @@ -455,50 +459,50 @@ TEST(Int128, OStream) { char fill; const char* rep; } cases[] = { - // zero with different bases - {uint128(0), std::ios::dec, 0, '_', "0"}, - {uint128(0), std::ios::oct, 0, '_', "0"}, - {uint128(0), std::ios::hex, 0, '_', "0"}, - // crossover between lo_ and hi_ - {uint128(0, -1), std::ios::dec, 0, '_', "18446744073709551615"}, - {uint128(0, -1), std::ios::oct, 0, '_', "1777777777777777777777"}, - {uint128(0, -1), std::ios::hex, 0, '_', "ffffffffffffffff"}, - {uint128(1, 0), std::ios::dec, 0, '_', "18446744073709551616"}, - {uint128(1, 0), std::ios::oct, 0, '_', "2000000000000000000000"}, - {uint128(1, 0), std::ios::hex, 0, '_', "10000000000000000"}, - // just the top bit - {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::dec, 0, '_', - "170141183460469231731687303715884105728"}, - {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::oct, 0, '_', - "2000000000000000000000000000000000000000000"}, - {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::hex, 0, '_', - "80000000000000000000000000000000"}, - // maximum uint128 value - {uint128(-1, -1), std::ios::dec, 0, '_', - "340282366920938463463374607431768211455"}, - {uint128(-1, -1), std::ios::oct, 0, '_', - "3777777777777777777777777777777777777777777"}, - {uint128(-1, -1), std::ios::hex, 0, '_', - "ffffffffffffffffffffffffffffffff"}, - // uppercase - {uint128(-1, -1), std::ios::hex | std::ios::uppercase, 0, '_', - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"}, - // showbase - {uint128(1), std::ios::dec | std::ios::showbase, 0, '_', "1"}, - {uint128(1), std::ios::oct | std::ios::showbase, 0, '_', "01"}, - {uint128(1), std::ios::hex | std::ios::showbase, 0, '_', "0x1"}, - // showbase does nothing on zero - {uint128(0), std::ios::dec | std::ios::showbase, 0, '_', "0"}, - {uint128(0), std::ios::oct | std::ios::showbase, 0, '_', "0"}, - {uint128(0), std::ios::hex | std::ios::showbase, 0, '_', "0"}, - // showpos does nothing on unsigned types - {uint128(1), std::ios::dec | std::ios::showpos, 0, '_', "1"}, - // padding - {uint128(9), std::ios::dec, 6, '_', "_____9"}, - {uint128(12345), std::ios::dec, 6, '_', "_12345"}, - // left adjustment - {uint128(9), std::ios::dec | std::ios::left, 6, '_', "9_____"}, - {uint128(12345), std::ios::dec | std::ios::left, 6, '_', "12345_"}, + // zero with different bases + {uint128(0), std::ios::dec, 0, '_', "0"}, + {uint128(0), std::ios::oct, 0, '_', "0"}, + {uint128(0), std::ios::hex, 0, '_', "0"}, + // crossover between lo_ and hi_ + {uint128(0, -1), std::ios::dec, 0, '_', "18446744073709551615"}, + {uint128(0, -1), std::ios::oct, 0, '_', "1777777777777777777777"}, + {uint128(0, -1), std::ios::hex, 0, '_', "ffffffffffffffff"}, + {uint128(1, 0), std::ios::dec, 0, '_', "18446744073709551616"}, + {uint128(1, 0), std::ios::oct, 0, '_', "2000000000000000000000"}, + {uint128(1, 0), std::ios::hex, 0, '_', "10000000000000000"}, + // just the top bit + {uint128(PROTOBUF_ULONGLONG(0x8000000000000000), 0), std::ios::dec, 0, + '_', "170141183460469231731687303715884105728"}, + {uint128(PROTOBUF_ULONGLONG(0x8000000000000000), 0), std::ios::oct, 0, + '_', "2000000000000000000000000000000000000000000"}, + {uint128(PROTOBUF_ULONGLONG(0x8000000000000000), 0), std::ios::hex, 0, + '_', "80000000000000000000000000000000"}, + // maximum uint128 value + {uint128(-1, -1), std::ios::dec, 0, '_', + "340282366920938463463374607431768211455"}, + {uint128(-1, -1), std::ios::oct, 0, '_', + "3777777777777777777777777777777777777777777"}, + {uint128(-1, -1), std::ios::hex, 0, '_', + "ffffffffffffffffffffffffffffffff"}, + // uppercase + {uint128(-1, -1), std::ios::hex | std::ios::uppercase, 0, '_', + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"}, + // showbase + {uint128(1), std::ios::dec | std::ios::showbase, 0, '_', "1"}, + {uint128(1), std::ios::oct | std::ios::showbase, 0, '_', "01"}, + {uint128(1), std::ios::hex | std::ios::showbase, 0, '_', "0x1"}, + // showbase does nothing on zero + {uint128(0), std::ios::dec | std::ios::showbase, 0, '_', "0"}, + {uint128(0), std::ios::oct | std::ios::showbase, 0, '_', "0"}, + {uint128(0), std::ios::hex | std::ios::showbase, 0, '_', "0"}, + // showpos does nothing on unsigned types + {uint128(1), std::ios::dec | std::ios::showpos, 0, '_', "1"}, + // padding + {uint128(9), std::ios::dec, 6, '_', "_____9"}, + {uint128(12345), std::ios::dec, 6, '_', "_12345"}, + // left adjustment + {uint128(9), std::ios::dec | std::ios::left, 6, '_', "9_____"}, + {uint128(12345), std::ios::dec | std::ios::left, 6, '_', "12345_"}, }; for (size_t i = 0; i < GOOGLE_ARRAYSIZE(cases); ++i) { std::ostringstream os; @@ -511,3 +515,5 @@ TEST(Int128, OStream) { } } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/stubs/io_win32.cc b/src/google/protobuf/stubs/io_win32.cc deleted file mode 100644 index b418986bcedce..0000000000000 --- a/src/google/protobuf/stubs/io_win32.cc +++ /dev/null @@ -1,362 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: laszlocsomor@google.com (Laszlo Csomor) -// -// Implementation for long-path-aware open/mkdir/etc. on Windows. -// -// These functions convert the input path to an absolute Windows path -// with "\\?\" prefix if necessary, then pass that to _wopen/_wmkdir/etc. -// (declared in ) respectively. This allows working with files/directories -// whose paths are longer than MAX_PATH (260 chars). -// -// This file is only used on Windows, it's empty on other platforms. - -#if defined(_MSC_VER) - -// Comment this out to fall back to using the ANSI versions (open, mkdir, ...) -// instead of the Unicode ones (_wopen, _wmkdir, ...). Doing so can be useful to -// debug failing tests if that's caused by the long path support. -#define SUPPORT_LONGPATHS - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace internal { -namespace win32 { -namespace { - -using std::string; -using std::unique_ptr; -using std::wstring; - -template -struct CharTraits { - static bool is_alpha(char_type ch); -}; - -template <> -struct CharTraits { - static bool is_alpha(char ch) { return isalpha(ch); } -}; - -template <> -struct CharTraits { - static bool is_alpha(wchar_t ch) { return iswalpha(ch); } -}; - -// Returns true if the path starts with a drive letter, e.g. "c:". -// Note that this won't check for the "\" after the drive letter, so this also -// returns true for "c:foo" (which is "c:\${PWD}\foo"). -// This check requires that a path not have a longpath prefix ("\\?\"). -template -bool has_drive_letter(const char_type* ch) { - return CharTraits::is_alpha(ch[0]) && ch[1] == ':'; -} - -// Returns true if the path starts with a longpath prefix ("\\?\"). -template -bool has_longpath_prefix(const char_type* path) { - return path[0] == '\\' && path[1] == '\\' && path[2] == '?' && - path[3] == '\\'; -} - -template -bool is_separator(char_type c) { - return c == '/' || c == '\\'; -} - -// Returns true if the path starts with a drive specifier (e.g. "c:\"). -template -bool is_path_absolute(const char_type* path) { - return has_drive_letter(path) && is_separator(path[2]); -} - -template -bool is_drive_relative(const char_type* path) { - return has_drive_letter(path) && (path[2] == 0 || !is_separator(path[2])); -} - -template -void replace_directory_separators(char_type* p) { - for (; *p; ++p) { - if (*p == '/') { - *p = '\\'; - } - } -} - -string join_paths(const string& path1, const string& path2) { - if (path1.empty() || is_path_absolute(path2.c_str()) || - has_longpath_prefix(path2.c_str())) { - return path2; - } - if (path2.empty()) { - return path1; - } - - if (is_separator(path1.back())) { - return is_separator(path2.front()) ? (path1 + path2.substr(1)) - : (path1 + path2); - } else { - return is_separator(path2.front()) ? (path1 + path2) - : (path1 + '\\' + path2); - } -} - -string normalize(string path) { - if (has_longpath_prefix(path.c_str())) { - path = path.substr(4); - } - - static const string dot("."); - static const string dotdot(".."); - - std::vector segments; - int segment_start = -1; - // Find the path segments in `path` (separated by "/"). - for (int i = 0;; ++i) { - if (!is_separator(path[i]) && path[i] != '\0') { - // The current character does not end a segment, so start one unless it's - // already started. - if (segment_start < 0) { - segment_start = i; - } - } else if (segment_start >= 0 && i > segment_start) { - // The current character is "/" or "\0", so this ends a segment. - // Add that to `segments` if there's anything to add; handle "." and "..". - string segment(path, segment_start, i - segment_start); - segment_start = -1; - if (segment == dotdot) { - if (!segments.empty() && - (!has_drive_letter(segments[0].c_str()) || segments.size() > 1)) { - segments.pop_back(); - } - } else if (segment != dot && !segment.empty()) { - segments.push_back(segment); - } - } - if (path[i] == '\0') { - break; - } - } - - // Handle the case when `path` is just a drive specifier (or some degenerate - // form of it, e.g. "c:\.."). - if (segments.size() == 1 && segments[0].size() == 2 && - has_drive_letter(segments[0].c_str())) { - return segments[0] + '\\'; - } - - // Join all segments. - bool first = true; - std::ostringstream result; - for (const auto& s : segments) { - if (!first) { - result << '\\'; - } - first = false; - result << s; - } - // Preserve trailing separator if the input contained it. - if (is_separator(path.back())) { - result << '\\'; - } - return result.str(); -} - -std::unique_ptr as_wstring(const string& s) { - int len = ::MultiByteToWideChar(CP_UTF8, 0, s.c_str(), s.size(), NULL, 0); - std::unique_ptr result(new WCHAR[len + 1]); - ::MultiByteToWideChar(CP_UTF8, 0, s.c_str(), s.size(), result.get(), len + 1); - result.get()[len] = 0; - return std::move(result); -} - -wstring as_wchar_path(const string& path) { - std::unique_ptr wbuf(as_wstring(path)); - replace_directory_separators(wbuf.get()); - return wstring(wbuf.get()); -} - -bool as_windows_path(const string& path, wstring* result) { - if (path.empty()) { - result->clear(); - return true; - } - if (is_separator(path[0]) || is_drive_relative(path.c_str())) { - return false; - } - - string mutable_path = path; - if (!is_path_absolute(mutable_path.c_str()) && - !has_longpath_prefix(mutable_path.c_str())) { - char cwd[MAX_PATH]; - ::GetCurrentDirectoryA(MAX_PATH, cwd); - mutable_path = join_paths(cwd, mutable_path); - } - *result = as_wchar_path(normalize(mutable_path)); - if (!has_longpath_prefix(result->c_str())) { - // Add the "\\?\" prefix unconditionally. This way we prevent the Win32 API - // from processing the path and "helpfully" removing trailing dots from the - // path, for example. - // See https://github.com/bazelbuild/bazel/issues/2935 - *result = wstring(L"\\\\?\\") + *result; - } - return true; -} - -} // namespace - -int open(const char* path, int flags, int mode) { -#ifdef SUPPORT_LONGPATHS - wstring wpath; - if (!as_windows_path(path, &wpath)) { - errno = ENOENT; - return -1; - } - return ::_wopen(wpath.c_str(), flags, mode); -#else - return ::_open(path, flags, mode); -#endif -} - -int mkdir(const char* path, int _mode) { -#ifdef SUPPORT_LONGPATHS - wstring wpath; - if (!as_windows_path(path, &wpath)) { - errno = ENOENT; - return -1; - } - return ::_wmkdir(wpath.c_str()); -#else // not SUPPORT_LONGPATHS - return ::_mkdir(path); -#endif // not SUPPORT_LONGPATHS -} - -int access(const char* path, int mode) { -#ifdef SUPPORT_LONGPATHS - wstring wpath; - if (!as_windows_path(path, &wpath)) { - errno = ENOENT; - return -1; - } - return ::_waccess(wpath.c_str(), mode); -#else - return ::_access(path, mode); -#endif -} - -int chdir(const char* path) { -#ifdef SUPPORT_LONGPATHS - wstring wpath; - if (!as_windows_path(path, &wpath)) { - errno = ENOENT; - return -1; - } - return ::_wchdir(wpath.c_str()); -#else - return ::_chdir(path); -#endif -} - -int stat(const char* path, struct _stat* buffer) { -#ifdef SUPPORT_LONGPATHS - wstring wpath; - if (!as_windows_path(path, &wpath)) { - errno = ENOENT; - return -1; - } - return ::_wstat(wpath.c_str(), buffer); -#else // not SUPPORT_LONGPATHS - return ::_stat(path, buffer); -#endif // not SUPPORT_LONGPATHS -} - -FILE* fopen(const char* path, const char* mode) { -#ifdef SUPPORT_LONGPATHS - wstring wpath; - if (!as_windows_path(path, &wpath)) { - errno = ENOENT; - return NULL; - } - std::unique_ptr wmode(as_wstring(mode)); - return ::_wfopen(wpath.c_str(), wmode.get()); -#else - return ::fopen(path, mode); -#endif -} - -int close(int fd) { return ::close(fd); } - -int dup(int fd) { return ::_dup(fd); } - -int dup2(int fd1, int fd2) { return ::_dup2(fd1, fd2); } - -int read(int fd, void* buffer, size_t size) { - return ::_read(fd, buffer, size); -} - -int setmode(int fd, int mode) { return ::_setmode(fd, mode); } - -int write(int fd, const void* buffer, size_t size) { - return ::_write(fd, buffer, size); -} - -wstring testonly_path_to_winpath(const string& path) { - wstring wpath; - as_windows_path(path, &wpath); - return wpath; -} - -} // namespace win32 -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // defined(_MSC_VER) - diff --git a/src/google/protobuf/stubs/io_win32.h b/src/google/protobuf/stubs/io_win32.h deleted file mode 100644 index a20e64c716a23..0000000000000 --- a/src/google/protobuf/stubs/io_win32.h +++ /dev/null @@ -1,104 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: laszlocsomor@google.com (Laszlo Csomor) -// -// This file contains the declarations for Windows implementations of -// commonly used POSIX functions such as open(2) and access(2), as well -// as macro definitions for flags of these functions. -// -// By including this file you'll redefine open/access/etc. to -// ::google::protobuf::internal::win32::{open/access/etc.}. -// Make sure you don't include a header that attempts to redeclare or -// redefine these functions, that'll lead to confusing compilation -// errors. It's best to #include this file as the last one to ensure that. -// -// This file is only used on Windows, it's empty on other platforms. - -#ifndef GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__ -#define GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__ - -#if defined(_WIN32) - -#include -#include - -// Compilers on Windows other than MSVC (e.g. Cygwin, MinGW32) define the -// following functions already, except for mkdir. -#ifdef _MSC_VER -namespace google { -namespace protobuf { -namespace internal { -namespace win32 { - -LIBPROTOBUF_EXPORT FILE* fopen(const char* path, const char* mode); -LIBPROTOBUF_EXPORT int access(const char* path, int mode); -LIBPROTOBUF_EXPORT int chdir(const char* path); -LIBPROTOBUF_EXPORT int close(int fd); -LIBPROTOBUF_EXPORT int dup(int fd); -LIBPROTOBUF_EXPORT int dup2(int fd1, int fd2); -LIBPROTOBUF_EXPORT int mkdir(const char* path, int _mode); -LIBPROTOBUF_EXPORT int open(const char* path, int flags, int mode = 0); -LIBPROTOBUF_EXPORT int read(int fd, void* buffer, size_t size); -LIBPROTOBUF_EXPORT int setmode(int fd, int mode); -LIBPROTOBUF_EXPORT int stat(const char* path, struct _stat* buffer); -LIBPROTOBUF_EXPORT int write(int fd, const void* buffer, size_t size); -LIBPROTOBUF_EXPORT std::wstring testonly_path_to_winpath( - const std::string& path); - -} // namespace win32 -} // namespace internal -} // namespace protobuf -} // namespace google -#else // _MSC_VER -#define mkdir(name, mode) mkdir(name) -#endif // !_MSC_VER - -#ifndef W_OK -#define W_OK 02 // not defined by MSVC for whatever reason -#endif - -#ifndef F_OK -#define F_OK 00 // not defined by MSVC for whatever reason -#endif - -#ifndef STDIN_FILENO -#define STDIN_FILENO 0 -#endif - -#ifndef STDOUT_FILENO -#define STDOUT_FILENO 1 -#endif - -#endif // defined(_WIN32) - -#endif // GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__ - - diff --git a/src/google/protobuf/stubs/io_win32_unittest.cc b/src/google/protobuf/stubs/io_win32_unittest.cc deleted file mode 100644 index 90bd9c9601330..0000000000000 --- a/src/google/protobuf/stubs/io_win32_unittest.cc +++ /dev/null @@ -1,367 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: laszlocsomor@google.com (Laszlo Csomor) -// -// Unit tests for long-path-aware open/mkdir/access on Windows. -// -// This file is only used on Windows, it's empty on other platforms. - -#if defined(_WIN32) - -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -namespace google { -namespace protobuf { -namespace internal { -namespace win32 { -namespace { - -using std::string; -using std::unique_ptr; -using std::wstring; - -class IoWin32Test : public ::testing::Test { - public: - void SetUp() override; - void TearDown() override; - - protected: - bool CreateAllUnder(wstring path); - bool DeleteAllUnder(wstring path); - - string test_tmpdir; - wstring wtest_tmpdir; -}; - -#define ASSERT_INITIALIZED \ - { \ - EXPECT_FALSE(test_tmpdir.empty()); \ - EXPECT_FALSE(wtest_tmpdir.empty()); \ - } - -void IoWin32Test::SetUp() { - test_tmpdir = string(TestTempDir()); - wtest_tmpdir.clear(); - if (test_tmpdir.empty()) { - const char* test_tmpdir_env = getenv("TEST_TMPDIR"); - if (test_tmpdir_env != nullptr && *test_tmpdir_env) { - test_tmpdir = string(test_tmpdir_env); - } - - // Only Bazel defines TEST_TMPDIR, CMake does not, so look for other - // suitable environment variables. - if (test_tmpdir.empty()) { - for (const char* name : {"TEMP", "TMP"}) { - test_tmpdir_env = getenv(name); - if (test_tmpdir_env != nullptr && *test_tmpdir_env) { - test_tmpdir = string(test_tmpdir_env); - break; - } - } - } - - // No other temp directory was found. Use the current director - if (test_tmpdir.empty()) { - char buffer[MAX_PATH]; - // Use GetCurrentDirectoryA instead of GetCurrentDirectoryW, because the - // current working directory must always be shorter than MAX_PATH, even - // with - // "\\?\" prefix (except on Windows 10 version 1607 and beyond, after - // opting in to long paths by default [1]). - // - // [1] https://msdn.microsoft.com/en-us/library/windows/ \ - // desktop/aa365247(v=vs.85).aspx#maxpath - DWORD result = ::GetCurrentDirectoryA(MAX_PATH, buffer); - if (result > 0) { - test_tmpdir = string(buffer); - } else { - // Using assertions in SetUp/TearDown seems to confuse the test - // framework, so just leave the member variables empty in case of - // failure. - GOOGLE_CHECK_OK(false); - return; - } - } - } - - while (test_tmpdir.back() == '/' || test_tmpdir.back() == '\\') { - test_tmpdir.pop_back(); - } - test_tmpdir += "\\io_win32_unittest.tmp"; - - // CreateDirectoryA's limit is 248 chars, see MSDN. - // https://msdn.microsoft.com/en-us/library/windows/ \ - // desktop/aa363855(v=vs.85).aspx - wtest_tmpdir = testonly_path_to_winpath(test_tmpdir); - if (!DeleteAllUnder(wtest_tmpdir) || !CreateAllUnder(wtest_tmpdir)) { - GOOGLE_CHECK_OK(false); - test_tmpdir.clear(); - wtest_tmpdir.clear(); - } -} - -void IoWin32Test::TearDown() { - if (!wtest_tmpdir.empty()) { - DeleteAllUnder(wtest_tmpdir); - } -} - -bool IoWin32Test::CreateAllUnder(wstring path) { - // Prepend UNC prefix if the path doesn't have it already. Don't bother - // checking if the path is shorter than MAX_PATH, let's just do it - // unconditionally. - if (path.find(L"\\\\?\\") != 0) { - path = wstring(L"\\\\?\\") + path; - } - if (::CreateDirectoryW(path.c_str(), NULL) || - GetLastError() == ERROR_ALREADY_EXISTS || - GetLastError() == ERROR_ACCESS_DENIED) { - return true; - } - if (GetLastError() == ERROR_PATH_NOT_FOUND) { - size_t pos = path.find_last_of(L'\\'); - if (pos != wstring::npos) { - wstring parent(path, 0, pos); - if (CreateAllUnder(parent) && CreateDirectoryW(path.c_str(), NULL)) { - return true; - } - } - } - return false; -} - -bool IoWin32Test::DeleteAllUnder(wstring path) { - static const wstring kDot(L"."); - static const wstring kDotDot(L".."); - - // Prepend UNC prefix if the path doesn't have it already. Don't bother - // checking if the path is shorter than MAX_PATH, let's just do it - // unconditionally. - if (path.find(L"\\\\?\\") != 0) { - path = wstring(L"\\\\?\\") + path; - } - // Append "\" if necessary. - if (path.back() != '\\') { - path.push_back('\\'); - } - - WIN32_FIND_DATAW metadata; - HANDLE handle = ::FindFirstFileW((path + L"*").c_str(), &metadata); - if (handle == INVALID_HANDLE_VALUE) { - return true; // directory doesn't exist - } - - bool result = true; - do { - wstring childname = metadata.cFileName; - if (kDot != childname && kDotDot != childname) { - wstring childpath = path + childname; - if ((metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { - // If this is not a junction, delete its contents recursively. - // Finally delete this directory/junction too. - if (((metadata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0 && - !DeleteAllUnder(childpath)) || - !::RemoveDirectoryW(childpath.c_str())) { - result = false; - break; - } - } else { - if (!::DeleteFileW(childpath.c_str())) { - result = false; - break; - } - } - } - } while (::FindNextFileW(handle, &metadata)); - ::FindClose(handle); - return result; -} - -TEST_F(IoWin32Test, AccessTest) { - ASSERT_INITIALIZED; - - string path = test_tmpdir; - while (path.size() < MAX_PATH - 30) { - path += "\\accesstest"; - EXPECT_EQ(mkdir(path.c_str(), 0644), 0); - } - string file = path + "\\file.txt"; - int fd = open(file.c_str(), O_CREAT | O_WRONLY, 0644); - if (fd > 0) { - EXPECT_EQ(close(fd), 0); - } else { - EXPECT_TRUE(false); - } - - EXPECT_EQ(access(test_tmpdir.c_str(), F_OK), 0); - EXPECT_EQ(access(path.c_str(), F_OK), 0); - EXPECT_EQ(access(path.c_str(), W_OK), 0); - EXPECT_EQ(access(file.c_str(), F_OK | W_OK), 0); - EXPECT_NE(access((file + ".blah").c_str(), F_OK), 0); - EXPECT_NE(access((file + ".blah").c_str(), W_OK), 0); - - EXPECT_EQ(access(".", F_OK), 0); - EXPECT_EQ(access(".", W_OK), 0); - EXPECT_EQ(access((test_tmpdir + "/accesstest").c_str(), F_OK | W_OK), 0); - ASSERT_EQ(access((test_tmpdir + "/./normalize_me/.././accesstest").c_str(), - F_OK | W_OK), - 0); - EXPECT_NE(access("io_win32_unittest.AccessTest.nonexistent", F_OK), 0); - EXPECT_NE(access("io_win32_unittest.AccessTest.nonexistent", W_OK), 0); - - ASSERT_EQ(access("c:bad", F_OK), -1); - ASSERT_EQ(errno, ENOENT); - ASSERT_EQ(access("/tmp/bad", F_OK), -1); - ASSERT_EQ(errno, ENOENT); - ASSERT_EQ(access("\\bad", F_OK), -1); - ASSERT_EQ(errno, ENOENT); -} - -TEST_F(IoWin32Test, OpenTest) { - ASSERT_INITIALIZED; - - string path = test_tmpdir; - while (path.size() < MAX_PATH) { - path += "\\opentest"; - EXPECT_EQ(mkdir(path.c_str(), 0644), 0); - } - string file = path + "\\file.txt"; - int fd = open(file.c_str(), O_CREAT | O_WRONLY, 0644); - if (fd > 0) { - EXPECT_EQ(write(fd, "hello", 5), 5); - EXPECT_EQ(close(fd), 0); - } else { - EXPECT_TRUE(false); - } - - ASSERT_EQ(open("c:bad.txt", O_CREAT | O_WRONLY, 0644), -1); - ASSERT_EQ(errno, ENOENT); - ASSERT_EQ(open("/tmp/bad.txt", O_CREAT | O_WRONLY, 0644), -1); - ASSERT_EQ(errno, ENOENT); - ASSERT_EQ(open("\\bad.txt", O_CREAT | O_WRONLY, 0644), -1); - ASSERT_EQ(errno, ENOENT); -} - -TEST_F(IoWin32Test, MkdirTest) { - ASSERT_INITIALIZED; - - string path = test_tmpdir; - do { - path += "\\mkdirtest"; - ASSERT_EQ(mkdir(path.c_str(), 0644), 0); - } while (path.size() <= MAX_PATH); - - ASSERT_EQ(mkdir("c:bad", 0644), -1); - ASSERT_EQ(errno, ENOENT); - ASSERT_EQ(mkdir("/tmp/bad", 0644), -1); - ASSERT_EQ(errno, ENOENT); - ASSERT_EQ(mkdir("\\bad", 0644), -1); - ASSERT_EQ(errno, ENOENT); -} - -TEST_F(IoWin32Test, ChdirTest) { - char owd[MAX_PATH]; - EXPECT_GT(::GetCurrentDirectoryA(MAX_PATH, owd), 0); - string path("C:\\"); - EXPECT_EQ(access(path.c_str(), F_OK), 0); - ASSERT_EQ(chdir(path.c_str()), 0); - EXPECT_TRUE(::SetCurrentDirectoryA(owd)); - - // Do not try to chdir into the test_tmpdir, it may already contain directory - // names with trailing dots. - // Instead test here with an obviously dot-trailed path. If the win32_chdir - // function would not convert the path to absolute and prefix with "\\?\" then - // the Win32 API would ignore the trailing dot, but because of the prefixing - // there'll be no path processing done, so we'll actually attempt to chdir - // into "C:\some\path\foo." - path = test_tmpdir + "/foo."; - EXPECT_EQ(mkdir(path.c_str(), 644), 0); - EXPECT_EQ(access(path.c_str(), F_OK), 0); - ASSERT_NE(chdir(path.c_str()), 0); -} - -TEST_F(IoWin32Test, AsWindowsPathTest) { - DWORD size = GetCurrentDirectoryW(0, NULL); - unique_ptr cwd_str(new wchar_t[size]); - EXPECT_GT(GetCurrentDirectoryW(size, cwd_str.get()), 0); - wstring cwd = wstring(L"\\\\?\\") + cwd_str.get(); - - ASSERT_EQ(testonly_path_to_winpath("relative_mkdirtest"), - cwd + L"\\relative_mkdirtest"); - ASSERT_EQ(testonly_path_to_winpath("preserve//\\trailing///"), - cwd + L"\\preserve\\trailing\\"); - ASSERT_EQ(testonly_path_to_winpath("./normalize_me\\/../blah"), - cwd + L"\\blah"); - std::ostringstream relpath; - for (wchar_t* p = cwd_str.get(); *p; ++p) { - if (*p == '/' || *p == '\\') { - relpath << "../"; - } - } - relpath << ".\\/../\\./beyond-toplevel"; - ASSERT_EQ(testonly_path_to_winpath(relpath.str()), - wstring(L"\\\\?\\") + cwd_str.get()[0] + L":\\beyond-toplevel"); - - // Absolute unix paths lack drive letters, driveless absolute windows paths - // do too. Neither can be converted to a drive-specifying absolute Windows - // path. - ASSERT_EQ(testonly_path_to_winpath("/absolute/unix/path"), L""); - // Though valid on Windows, we also don't support UNC paths (\\UNC\\blah). - ASSERT_EQ(testonly_path_to_winpath("\\driveless\\absolute"), L""); - // Though valid in cmd.exe, drive-relative paths are not supported. - ASSERT_EQ(testonly_path_to_winpath("c:foo"), L""); - ASSERT_EQ(testonly_path_to_winpath("c:/foo"), L"\\\\?\\c:\\foo"); -} - -} // namespace -} // namespace win32 -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // defined(_WIN32) - diff --git a/src/google/protobuf/stubs/logging.h b/src/google/protobuf/stubs/logging.h index f69605d9f6393..f37048d677825 100644 --- a/src/google/protobuf/stubs/logging.h +++ b/src/google/protobuf/stubs/logging.h @@ -34,6 +34,8 @@ #include #include +#include + // =================================================================== // emulates google3/base/logging.h @@ -70,7 +72,7 @@ namespace internal { class LogFinisher; -class LIBPROTOBUF_EXPORT LogMessage { +class PROTOBUF_EXPORT LogMessage { public: LogMessage(LogLevel level, const char* filename, int line); ~LogMessage(); @@ -87,7 +89,7 @@ class LIBPROTOBUF_EXPORT LogMessage { LogMessage& operator<<(double value); LogMessage& operator<<(void* value); LogMessage& operator<<(const StringPiece& value); - LogMessage& operator<<(const ::google::protobuf::util::Status& status); + LogMessage& operator<<(const util::Status& status); LogMessage& operator<<(const uint128& value); private: @@ -102,7 +104,7 @@ class LIBPROTOBUF_EXPORT LogMessage { // Used to make the entire "LOG(BLAH) << etc." expression have a void return // type and print a newline after each message. -class LIBPROTOBUF_EXPORT LogFinisher { +class PROTOBUF_EXPORT LogFinisher { public: void operator=(LogMessage& other); }; @@ -141,10 +143,10 @@ inline bool IsOk(bool status) { return status; } #undef GOOGLE_DCHECK_GT #undef GOOGLE_DCHECK_GE -#define GOOGLE_LOG(LEVEL) \ - ::google::protobuf::internal::LogFinisher() = \ - ::google::protobuf::internal::LogMessage( \ - ::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__) +#define GOOGLE_LOG(LEVEL) \ + ::google::protobuf::internal::LogFinisher() = \ + ::google::protobuf::internal::LogMessage( \ + ::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__) #define GOOGLE_LOG_IF(LEVEL, CONDITION) \ !(CONDITION) ? (void)0 : GOOGLE_LOG(LEVEL) @@ -162,15 +164,15 @@ namespace internal { template T* CheckNotNull(const char* /* file */, int /* line */, const char* name, T* val) { - if (val == NULL) { + if (val == nullptr) { GOOGLE_LOG(FATAL) << name; } return val; } } // namespace internal -#define GOOGLE_CHECK_NOTNULL(A) \ - ::google::protobuf::internal::CheckNotNull(\ - __FILE__, __LINE__, "'" #A "' must not be NULL", (A)) +#define GOOGLE_CHECK_NOTNULL(A) \ + ::google::protobuf::internal::CheckNotNull( \ + __FILE__, __LINE__, "'" #A "' must not be nullptr", (A)) #ifdef NDEBUG @@ -208,7 +210,7 @@ typedef void LogHandler(LogLevel level, const char* filename, int line, // also help end users figure out a problem. If you would prefer that // these messages be sent somewhere other than stderr, call SetLogHandler() // to set your own handler. This returns the old handler. Set the handler -// to NULL to ignore log messages (but see also LogSilencer, below). +// to nullptr to ignore log messages (but see also LogSilencer, below). // // Obviously, SetLogHandler is not thread-safe. You should only call it // at initialization time, and probably not from library code. If you @@ -216,7 +218,7 @@ typedef void LogHandler(LogLevel level, const char* filename, int line, // have some code that tends to trigger them frequently and you know // the warnings are not important to you), use the LogSilencer class // below. -LIBPROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func); +PROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func); // Create a LogSilencer if you want to temporarily suppress all log // messages. As long as any LogSilencer objects exist, non-fatal @@ -225,7 +227,7 @@ LIBPROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func); // accidentally suppress log messages occurring in another thread, but // since messages are generally for debugging purposes only, this isn't // a big deal. If you want to intercept log messages, use SetLogHandler(). -class LIBPROTOBUF_EXPORT LogSilencer { +class PROTOBUF_EXPORT LogSilencer { public: LogSilencer(); ~LogSilencer(); @@ -234,4 +236,6 @@ class LIBPROTOBUF_EXPORT LogSilencer { } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_STUBS_LOGGING_H_ diff --git a/src/google/protobuf/stubs/macros.h b/src/google/protobuf/stubs/macros.h index 0e9a9ec198208..c556d02233ae0 100644 --- a/src/google/protobuf/stubs/macros.h +++ b/src/google/protobuf/stubs/macros.h @@ -112,55 +112,7 @@ struct CompileAssert { } // namespace internal -#undef GOOGLE_COMPILE_ASSERT -#if __cplusplus >= 201103L #define GOOGLE_COMPILE_ASSERT(expr, msg) static_assert(expr, #msg) -#else -#define GOOGLE_COMPILE_ASSERT(expr, msg) \ - ::google::protobuf::internal::CompileAssert<(bool(expr))> \ - msg[bool(expr) ? 1 : -1]; \ - (void)msg -// Implementation details of COMPILE_ASSERT: -// -// - COMPILE_ASSERT works by defining an array type that has -1 -// elements (and thus is invalid) when the expression is false. -// -// - The simpler definition -// -// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1] -// -// does not work, as gcc supports variable-length arrays whose sizes -// are determined at run-time (this is gcc's extension and not part -// of the C++ standard). As a result, gcc fails to reject the -// following code with the simple definition: -// -// int foo; -// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is -// // not a compile-time constant. -// -// - By using the type CompileAssert<(bool(expr))>, we ensures that -// expr is a compile-time constant. (Template arguments must be -// determined at compile-time.) -// -// - The outter parentheses in CompileAssert<(bool(expr))> are necessary -// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written -// -// CompileAssert -// -// instead, these compilers will refuse to compile -// -// COMPILE_ASSERT(5 > 0, some_message); -// -// (They seem to think the ">" in "5 > 0" marks the end of the -// template argument list.) -// -// - The array size is (bool(expr) ? 1 : -1), instead of simply -// -// ((expr) ? 1 : -1). -// -// This is to avoid running into a bug in MS VC 7.1, which -// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. -#endif // __cplusplus >= 201103L } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/map_util.h b/src/google/protobuf/stubs/map_util.h index 887f12a600fa9..24e098ad1bc95 100644 --- a/src/google/protobuf/stubs/map_util.h +++ b/src/google/protobuf/stubs/map_util.h @@ -131,7 +131,7 @@ FindWithDefault(const Collection& collection, } // Returns a pointer to the const value associated with the given key if it -// exists, or NULL otherwise. +// exists, or nullptr otherwise. template const typename Collection::value_type::second_type* FindOrNull(const Collection& collection, @@ -156,11 +156,11 @@ FindOrNull(Collection& collection, // NOLINT } // Returns the pointer value associated with the given key. If none is found, -// NULL is returned. The function is designed to be used with a map of keys to +// nullptr is returned. The function is designed to be used with a map of keys to // pointers. // // This function does not distinguish between a missing key and a key mapped -// to a NULL value. +// to nullptr. template typename Collection::value_type::second_type FindPtrOrNull(const Collection& collection, @@ -188,7 +188,7 @@ FindPtrOrNull(Collection& collection, // NOLINT } // Finds the pointer value associated with the given key in a map whose values -// are linked_ptrs. Returns NULL if key is not found. +// are linked_ptrs. Returns nullptr if key is not found. template typename Collection::value_type::second_type::element_type* FindLinkedPtrOrNull(const Collection& collection, @@ -215,7 +215,7 @@ FindLinkedPtrOrDie(const Collection& collection, } // Finds the value associated with the given key and copies it to *value (if not -// NULL). Returns false if the key was not found, true otherwise. +// nullptr). Returns false if the key was not found, true otherwise. template bool FindCopy(const Collection& collection, const Key& key, @@ -447,7 +447,7 @@ LookupOrInsertNew(Collection* const collection, std::pair ret = collection->insert(typename Collection::value_type( key, - static_cast(NULL))); + static_cast(nullptr))); if (ret.second) { ret.first->second = new Element(); } @@ -466,7 +466,7 @@ LookupOrInsertNew(Collection* const collection, std::pair ret = collection->insert(typename Collection::value_type( key, - static_cast(NULL))); + static_cast(nullptr))); if (ret.second) { ret.first->second = new Element(arg); } @@ -612,7 +612,7 @@ bool UpdateReturnCopy(Collection* const collection, return false; } -// Tries to insert the given key-value pair into the collection. Returns NULL if +// Tries to insert the given key-value pair into the collection. Returns nullptr if // the insert succeeds. Otherwise, returns a pointer to the existing value. // // This complements UpdateReturnCopy in that it allows to update only after @@ -620,12 +620,11 @@ bool UpdateReturnCopy(Collection* const collection, // twice. Unlike UpdateReturnCopy this also does not come with the issue of an // undefined previous* in case new data was inserted. template -typename Collection::value_type::second_type* const -InsertOrReturnExisting(Collection* const collection, - const typename Collection::value_type& vt) { +typename Collection::value_type::second_type* InsertOrReturnExisting( + Collection* const collection, const typename Collection::value_type& vt) { std::pair ret = collection->insert(vt); if (ret.second) { - return NULL; // Inserted, no existing previous value. + return nullptr; // Inserted, no existing previous value. } else { return &ret.first->second; // Return address of already existing value. } @@ -633,8 +632,7 @@ InsertOrReturnExisting(Collection* const collection, // Same as above, except for explicit key and data. template -typename Collection::value_type::second_type* const -InsertOrReturnExisting( +typename Collection::value_type::second_type* InsertOrReturnExisting( Collection* const collection, const typename Collection::value_type::first_type& key, const typename Collection::value_type::second_type& data) { @@ -644,7 +642,7 @@ InsertOrReturnExisting( // Erases the collection item identified by the given key, and returns the value // associated with that key. It is assumed that the value (i.e., the -// mapped_type) is a pointer. Returns NULL if the key was not found in the +// mapped_type) is a pointer. Returns nullptr if the key was not found in the // collection. // // Examples: @@ -654,7 +652,8 @@ InsertOrReturnExisting( // delete EraseKeyReturnValuePtr(&my_map, "abc"); // // Use returned value: -// scoped_ptr value_ptr(EraseKeyReturnValuePtr(&my_map, "abc")); +// std::unique_ptr value_ptr( +// EraseKeyReturnValuePtr(&my_map, "abc")); // if (value_ptr.get()) // value_ptr->DoSomething(); // @@ -664,7 +663,7 @@ typename Collection::value_type::second_type EraseKeyReturnValuePtr( const typename Collection::value_type::first_type& key) { typename Collection::iterator it = collection->find(key); if (it == collection->end()) { - return NULL; + return nullptr; } typename Collection::value_type::second_type v = it->second; collection->erase(it); @@ -678,7 +677,7 @@ typename Collection::value_type::second_type EraseKeyReturnValuePtr( template void InsertKeysFromMap(const MapContainer& map_container, KeyContainer* key_container) { - GOOGLE_CHECK(key_container != NULL); + GOOGLE_CHECK(key_container != nullptr); for (typename MapContainer::const_iterator it = map_container.begin(); it != map_container.end(); ++it) { key_container->insert(it->first); @@ -692,7 +691,7 @@ void InsertKeysFromMap(const MapContainer& map_container, template void AppendKeysFromMap(const MapContainer& map_container, KeyContainer* key_container) { - GOOGLE_CHECK(key_container != NULL); + GOOGLE_CHECK(key_container != nullptr); for (typename MapContainer::const_iterator it = map_container.begin(); it != map_container.end(); ++it) { key_container->push_back(it->first); @@ -708,8 +707,8 @@ void AppendKeysFromMap(const MapContainer& map_container, // without the complexity of a SFINAE-based solution.) template void AppendKeysFromMap(const MapContainer& map_container, - vector* key_container) { - GOOGLE_CHECK(key_container != NULL); + std::vector* key_container) { + GOOGLE_CHECK(key_container != nullptr); // We now have the opportunity to call reserve(). Calling reserve() every // time is a bad idea for some use cases: libstdc++'s implementation of // vector<>::reserve() resizes the vector's backing store to exactly the @@ -736,7 +735,7 @@ void AppendKeysFromMap(const MapContainer& map_container, template void AppendValuesFromMap(const MapContainer& map_container, ValueContainer* value_container) { - GOOGLE_CHECK(value_container != NULL); + GOOGLE_CHECK(value_container != nullptr); for (typename MapContainer::const_iterator it = map_container.begin(); it != map_container.end(); ++it) { value_container->push_back(it->second); @@ -752,8 +751,8 @@ void AppendValuesFromMap(const MapContainer& map_container, // without the complexity of a SFINAE-based solution.) template void AppendValuesFromMap(const MapContainer& map_container, - vector* value_container) { - GOOGLE_CHECK(value_container != NULL); + std::vector* value_container) { + GOOGLE_CHECK(value_container != nullptr); // See AppendKeysFromMap for why this is done. if (value_container->empty()) { value_container->reserve(map_container.size()); diff --git a/src/google/protobuf/stubs/mathlimits.cc b/src/google/protobuf/stubs/mathlimits.cc deleted file mode 100644 index 0373b2bb97137..0000000000000 --- a/src/google/protobuf/stubs/mathlimits.cc +++ /dev/null @@ -1,144 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// All Rights Reserved. -// -// Author: Maxim Lifantsev -// - -#include - -#include - -namespace google { -namespace protobuf { - -// MSVC++ 2005 and older compilers think the header declaration was a -// definition, and erroneously flag these as a duplicate definition. -#if defined(COMPILER_MSVC) || __cpluscplus < 201103L - -#define DEF_COMMON_LIMITS(Type) -#define DEF_UNSIGNED_INT_LIMITS(Type) -#define DEF_SIGNED_INT_LIMITS(Type) -#define DEF_PRECISION_LIMITS(Type) - -#else - -#define DEF_COMMON_LIMITS(Type) \ -const bool MathLimits::kIsSigned; \ -const bool MathLimits::kIsInteger; \ -const int MathLimits::kMin10Exp; \ -const int MathLimits::kMax10Exp; - -#define DEF_UNSIGNED_INT_LIMITS(Type) \ -DEF_COMMON_LIMITS(Type) \ -const Type MathLimits::kPosMin; \ -const Type MathLimits::kPosMax; \ -const Type MathLimits::kMin; \ -const Type MathLimits::kMax; \ -const Type MathLimits::kEpsilon; \ -const Type MathLimits::kStdError; - -#define DEF_SIGNED_INT_LIMITS(Type) \ -DEF_UNSIGNED_INT_LIMITS(Type) \ -const Type MathLimits::kNegMin; \ -const Type MathLimits::kNegMax; - -#define DEF_PRECISION_LIMITS(Type) \ -const int MathLimits::kPrecisionDigits; - -#endif // not COMPILER_MSVC - -// http://en.wikipedia.org/wiki/Quadruple_precision_floating-point_format#Double-double_arithmetic -// With some compilers (gcc 4.6.x) on some platforms (powerpc64), -// "long double" is implemented as a pair of double: "double double" format. -// This causes a problem with epsilon (eps). -// eps is the smallest positive number such that 1.0 + eps > 1.0 -// -// Normal format: 1.0 + e = 1.0...01 // N-1 zeros for N fraction bits -// D-D format: 1.0 + e = 1.000...0001 // epsilon can be very small -// -// In the normal format, 1.0 + e has to fit in one stretch of bits. -// The maximum rounding error is half of eps. -// -// In the double-double format, 1.0 + e splits across two doubles: -// 1.0 in the high double, e in the low double, and they do not have to -// be contiguous. The maximum rounding error on a value close to 1.0 is -// much larger than eps. -// -// Some code checks for errors by comparing a computed value to a golden -// value +/- some multiple of the maximum rounding error. The maximum -// rounding error is not available so we use eps as an approximation -// instead. That fails when long double is in the double-double format. -// Therefore, we define kStdError as a multiple of -// max(DBL_EPSILON * DBL_EPSILON, kEpsilon) rather than a multiple of kEpsilon. - -#define DEF_FP_LIMITS(Type, PREFIX) \ -DEF_COMMON_LIMITS(Type) \ -const Type MathLimits::kPosMin = PREFIX##_MIN; \ -const Type MathLimits::kPosMax = PREFIX##_MAX; \ -const Type MathLimits::kMin = -MathLimits::kPosMax; \ -const Type MathLimits::kMax = MathLimits::kPosMax; \ -const Type MathLimits::kNegMin = -MathLimits::kPosMin; \ -const Type MathLimits::kNegMax = -MathLimits::kPosMax; \ -const Type MathLimits::kEpsilon = PREFIX##_EPSILON; \ -/* 32 is 5 bits of mantissa error; should be adequate for common errors */ \ -const Type MathLimits::kStdError = \ - 32 * (DBL_EPSILON * DBL_EPSILON > MathLimits::kEpsilon \ - ? DBL_EPSILON * DBL_EPSILON : MathLimits::kEpsilon); \ -DEF_PRECISION_LIMITS(Type) \ -const Type MathLimits::kNaN = HUGE_VAL - HUGE_VAL; \ -const Type MathLimits::kPosInf = HUGE_VAL; \ -const Type MathLimits::kNegInf = -HUGE_VAL; - -// The following are *not* casts! -DEF_SIGNED_INT_LIMITS(int8) -DEF_SIGNED_INT_LIMITS(int16) // NOLINT(readability/casting) -DEF_SIGNED_INT_LIMITS(int32) // NOLINT(readability/casting) -DEF_SIGNED_INT_LIMITS(int64) // NOLINT(readability/casting) -DEF_UNSIGNED_INT_LIMITS(uint8) -DEF_UNSIGNED_INT_LIMITS(uint16) // NOLINT(readability/casting) -DEF_UNSIGNED_INT_LIMITS(uint32) // NOLINT(readability/casting) -DEF_UNSIGNED_INT_LIMITS(uint64) // NOLINT(readability/casting) - -DEF_SIGNED_INT_LIMITS(long int) -DEF_UNSIGNED_INT_LIMITS(unsigned long int) - -DEF_FP_LIMITS(float, FLT) -DEF_FP_LIMITS(double, DBL) -DEF_FP_LIMITS(long double, LDBL); - -#undef DEF_COMMON_LIMITS -#undef DEF_SIGNED_INT_LIMITS -#undef DEF_UNSIGNED_INT_LIMITS -#undef DEF_FP_LIMITS -#undef DEF_PRECISION_LIMITS -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/stubs/mathlimits.h b/src/google/protobuf/stubs/mathlimits.h deleted file mode 100644 index 2391ac4caaba5..0000000000000 --- a/src/google/protobuf/stubs/mathlimits.h +++ /dev/null @@ -1,303 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// All Rights Reserved. -// -// Author: Maxim Lifantsev -// -// Useful integer and floating point limits and type traits. -// -// This partially replaces/duplictes numeric_limits<> from . -// We get a Google-style class that we have a greater control over -// and thus can add new features to it or fix whatever happens to be broken in -// numeric_limits for the compilers we use. -// - -#ifndef UTIL_MATH_MATHLIMITS_H__ -#define UTIL_MATH_MATHLIMITS_H__ - -// Note that for Windows we do something different because it does not support -// the plain isinf and isnan. -#if __cplusplus >= 201103L -// GCC 4.9 has a bug that makes isinf and isnan ambigious when both -// and get pulled into the same translation unit. We use the ones in -// std:: namespace explicitly for C++11 -#include -#define GOOGLE_PROTOBUF_USE_STD_CMATH -#elif _GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC -// libstdc++ header undefines the global macros and put functions in -// std:: namespace even before C++11. Use the ones in std:: instead too. -#include -#define GOOGLE_PROTOBUF_USE_STD_CMATH -#else -#include -#endif - -#include - -#include - -#include - -// ========================================================================= // - -// Useful integer and floating point limits and type traits. -// This is just for the documentation; -// real members are defined in our specializations below. -namespace google { -namespace protobuf { -template struct MathLimits { - // Type name. - typedef T Type; - // Unsigned version of the Type with the same byte size. - // Same as Type for floating point and unsigned types. - typedef T UnsignedType; - // If the type supports negative values. - static const bool kIsSigned; - // If the type supports only integer values. - static const bool kIsInteger; - // Magnitude-wise smallest representable positive value. - static const Type kPosMin; - // Magnitude-wise largest representable positive value. - static const Type kPosMax; - // Smallest representable value. - static const Type kMin; - // Largest representable value. - static const Type kMax; - // Magnitude-wise smallest representable negative value. - // Present only if kIsSigned. - static const Type kNegMin; - // Magnitude-wise largest representable negative value. - // Present only if kIsSigned. - static const Type kNegMax; - // Smallest integer x such that 10^x is representable. - static const int kMin10Exp; - // Largest integer x such that 10^x is representable. - static const int kMax10Exp; - // Smallest positive value such that Type(1) + kEpsilon != Type(1) - static const Type kEpsilon; - // Typical rounding error that is enough to cover - // a few simple floating-point operations. - // Slightly larger than kEpsilon to account for a few rounding errors. - // Is zero if kIsInteger. - static const Type kStdError; - // Number of decimal digits of mantissa precision. - // Present only if !kIsInteger. - static const int kPrecisionDigits; - // Not a number, i.e. result of 0/0. - // Present only if !kIsInteger. - static const Type kNaN; - // Positive infinity, i.e. result of 1/0. - // Present only if !kIsInteger. - static const Type kPosInf; - // Negative infinity, i.e. result of -1/0. - // Present only if !kIsInteger. - static const Type kNegInf; - - // NOTE: Special floating point values behave - // in a special (but mathematically-logical) way - // in terms of (in)equalty comparison and mathematical operations - // -- see out unittest for examples. - - // Special floating point value testers. - // Present in integer types for convenience. - static bool IsFinite(const Type x); - static bool IsNaN(const Type x); - static bool IsInf(const Type x); - static bool IsPosInf(const Type x); - static bool IsNegInf(const Type x); -}; - -// ========================================================================= // - -// All #define-s below are simply to refactor the declarations of -// MathLimits template specializations. -// They are all #undef-ined below. - -// The hoop-jumping in *_INT_(MAX|MIN) below is so that the compiler does not -// get an overflow while computing the constants. - -#define SIGNED_INT_MAX(Type) \ - (((Type(1) << (sizeof(Type)*8 - 2)) - 1) + (Type(1) << (sizeof(Type)*8 - 2))) - -#define SIGNED_INT_MIN(Type) \ - (-(Type(1) << (sizeof(Type)*8 - 2)) - (Type(1) << (sizeof(Type)*8 - 2))) - -#define UNSIGNED_INT_MAX(Type) \ - (((Type(1) << (sizeof(Type)*8 - 1)) - 1) + (Type(1) << (sizeof(Type)*8 - 1))) - -// Compile-time selected log10-related constants for integer types. -#define SIGNED_MAX_10_EXP(Type) \ - (sizeof(Type) == 1 ? 2 : ( \ - sizeof(Type) == 2 ? 4 : ( \ - sizeof(Type) == 4 ? 9 : ( \ - sizeof(Type) == 8 ? 18 : -1)))) - -#define UNSIGNED_MAX_10_EXP(Type) \ - (sizeof(Type) == 1 ? 2 : ( \ - sizeof(Type) == 2 ? 4 : ( \ - sizeof(Type) == 4 ? 9 : ( \ - sizeof(Type) == 8 ? 19 : -1)))) - -#define DECL_INT_LIMIT_FUNCS \ - static bool IsFinite(const Type /*x*/) { return true; } \ - static bool IsNaN(const Type /*x*/) { return false; } \ - static bool IsInf(const Type /*x*/) { return false; } \ - static bool IsPosInf(const Type /*x*/) { return false; } \ - static bool IsNegInf(const Type /*x*/) { return false; } - -#define DECL_SIGNED_INT_LIMITS(IntType, UnsignedIntType) \ -template<> \ -struct LIBPROTOBUF_EXPORT MathLimits { \ - typedef IntType Type; \ - typedef UnsignedIntType UnsignedType; \ - static const bool kIsSigned = true; \ - static const bool kIsInteger = true; \ - static const Type kPosMin = 1; \ - static const Type kPosMax = SIGNED_INT_MAX(Type); \ - static const Type kMin = SIGNED_INT_MIN(Type); \ - static const Type kMax = kPosMax; \ - static const Type kNegMin = -1; \ - static const Type kNegMax = kMin; \ - static const int kMin10Exp = 0; \ - static const int kMax10Exp = SIGNED_MAX_10_EXP(Type); \ - static const Type kEpsilon = 1; \ - static const Type kStdError = 0; \ - DECL_INT_LIMIT_FUNCS \ -}; - -#define DECL_UNSIGNED_INT_LIMITS(IntType) \ -template<> \ -struct LIBPROTOBUF_EXPORT MathLimits { \ - typedef IntType Type; \ - typedef IntType UnsignedType; \ - static const bool kIsSigned = false; \ - static const bool kIsInteger = true; \ - static const Type kPosMin = 1; \ - static const Type kPosMax = UNSIGNED_INT_MAX(Type); \ - static const Type kMin = 0; \ - static const Type kMax = kPosMax; \ - static const int kMin10Exp = 0; \ - static const int kMax10Exp = UNSIGNED_MAX_10_EXP(Type); \ - static const Type kEpsilon = 1; \ - static const Type kStdError = 0; \ - DECL_INT_LIMIT_FUNCS \ -}; - -DECL_SIGNED_INT_LIMITS(signed char, unsigned char) -DECL_SIGNED_INT_LIMITS(signed short int, unsigned short int) -DECL_SIGNED_INT_LIMITS(signed int, unsigned int) -DECL_SIGNED_INT_LIMITS(signed long int, unsigned long int) -DECL_SIGNED_INT_LIMITS(signed long long int, unsigned long long int) -DECL_UNSIGNED_INT_LIMITS(unsigned char) -DECL_UNSIGNED_INT_LIMITS(unsigned short int) -DECL_UNSIGNED_INT_LIMITS(unsigned int) -DECL_UNSIGNED_INT_LIMITS(unsigned long int) -DECL_UNSIGNED_INT_LIMITS(unsigned long long int) - -#undef DECL_SIGNED_INT_LIMITS -#undef DECL_UNSIGNED_INT_LIMITS -#undef SIGNED_INT_MAX -#undef SIGNED_INT_MIN -#undef UNSIGNED_INT_MAX -#undef SIGNED_MAX_10_EXP -#undef UNSIGNED_MAX_10_EXP -#undef DECL_INT_LIMIT_FUNCS - -// For non-Windows builds we use the std:: versions of isinf and isnan if they -// are available; see the comment about at the top of this file for the -// details on why we need to do this. -#ifdef GOOGLE_PROTOBUF_USE_STD_CMATH -#define ISINF std::isinf -#define ISNAN std::isnan -#else -#define ISINF isinf -#define ISNAN isnan -#endif - -// ========================================================================= // -#ifdef WIN32 // Lacks built-in isnan() and isinf() -#define DECL_FP_LIMIT_FUNCS \ - static bool IsFinite(const Type x) { return _finite(x); } \ - static bool IsNaN(const Type x) { return _isnan(x); } \ - static bool IsInf(const Type x) { return (_fpclass(x) & (_FPCLASS_NINF | _FPCLASS_PINF)) != 0; } \ - static bool IsPosInf(const Type x) { return _fpclass(x) == _FPCLASS_PINF; } \ - static bool IsNegInf(const Type x) { return _fpclass(x) == _FPCLASS_NINF; } -#else -#define DECL_FP_LIMIT_FUNCS \ - static bool IsFinite(const Type x) { return !ISINF(x) && !ISNAN(x); } \ - static bool IsNaN(const Type x) { return ISNAN(x); } \ - static bool IsInf(const Type x) { return ISINF(x); } \ - static bool IsPosInf(const Type x) { return ISINF(x) && x > 0; } \ - static bool IsNegInf(const Type x) { return ISINF(x) && x < 0; } -#endif - -// We can't put floating-point constant values in the header here because -// such constants are not considered to be primitive-type constants by gcc. -// CAVEAT: Hence, they are going to be initialized only during -// the global objects construction time. -#define DECL_FP_LIMITS(FP_Type, PREFIX) \ -template<> \ -struct LIBPROTOBUF_EXPORT MathLimits { \ - typedef FP_Type Type; \ - typedef FP_Type UnsignedType; \ - static const bool kIsSigned = true; \ - static const bool kIsInteger = false; \ - static const Type kPosMin; \ - static const Type kPosMax; \ - static const Type kMin; \ - static const Type kMax; \ - static const Type kNegMin; \ - static const Type kNegMax; \ - static const int kMin10Exp = PREFIX##_MIN_10_EXP; \ - static const int kMax10Exp = PREFIX##_MAX_10_EXP; \ - static const Type kEpsilon; \ - static const Type kStdError; \ - static const int kPrecisionDigits = PREFIX##_DIG; \ - static const Type kNaN; \ - static const Type kPosInf; \ - static const Type kNegInf; \ - DECL_FP_LIMIT_FUNCS \ -}; - -DECL_FP_LIMITS(float, FLT) -DECL_FP_LIMITS(double, DBL) -DECL_FP_LIMITS(long double, LDBL) - -#undef ISINF -#undef ISNAN -#undef DECL_FP_LIMITS -#undef DECL_FP_LIMIT_FUNCS - -// ========================================================================= // -} // namespace protobuf -} // namespace google - -#endif // UTIL_MATH_MATHLIMITS_H__ diff --git a/src/google/protobuf/stubs/mathutil.h b/src/google/protobuf/stubs/mathutil.h index 8a9f69a0b2251..7116d2d5560a3 100644 --- a/src/google/protobuf/stubs/mathutil.h +++ b/src/google/protobuf/stubs/mathutil.h @@ -30,16 +30,37 @@ #ifndef GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_ #define GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_ +#include #include -#include +#include #include #include -#include namespace google { namespace protobuf { namespace internal { + +// Like std::make_unsigned_t except floating point types map to themselves. +template +using MakeUnsignedT = + typename std::conditional::value, std::make_unsigned, + std::common_type>::type::type; + +// Like std::isnan() except a template function that is defined for all numeric +// types. +template ::value, int>::type = 0> +bool IsNan(T val) { + return false; +} + +template ::value, + int>::type = 0> +bool IsNan(T val) { + return std::isnan(val); +} + template bool AlmostEquals(T a, T b) { return a == b; @@ -53,21 +74,22 @@ template<> inline bool AlmostEquals(double a, double b) { return fabs(a - b) < 32 * DBL_EPSILON; } + } // namespace internal class MathUtil { public: - template + template static T Sign(T value) { - if (value == T(0) || MathLimits::IsNaN(value)) { + if (value == T(0) || internal::IsNan(value)) { return value; } return value > T(0) ? 1 : -1; } - template + template static bool AlmostEquals(T a, T b) { - return ::google::protobuf::internal::AlmostEquals(a, b); + return internal::AlmostEquals(a, b); } // Largest of two values. @@ -76,9 +98,9 @@ class MathUtil { // which should be OK because, although they (can) have different // bit representation, they are observably the same when examined // with arithmetic and (in)equality operators. - template + template static T Max(const T x, const T y) { - return MathLimits::IsNaN(x) || x > y ? x : y; + return internal::IsNan(x) || x > y ? x : y; } // Absolute value of x @@ -93,10 +115,10 @@ class MathUtil { // Absolute value of the difference between two numbers. // Works correctly for signed types and special floating point values. - template - static typename MathLimits::UnsignedType AbsDiff(const T x, const T y) { + template + static typename internal::MakeUnsignedT AbsDiff(const T x, const T y) { // Carries out arithmetic as unsigned to avoid overflow. - typedef typename MathLimits::UnsignedType R; + typedef typename internal::MakeUnsignedT R; return x > y ? R(x) - R(y) : R(y) - R(x); } @@ -123,11 +145,10 @@ bool MathUtil::WithinFractionOrMargin(const T x, const T y, // which will cause the compiler to generate code for either the "if" part // or the "then" part. In this way we avoid a compiler warning // about a potential integer overflow in crosstool v12 (gcc 4.3.1). - if (MathLimits::kIsInteger) { + if (std::numeric_limits::is_integer) { return x == y; } else { - // IsFinite checks are to make kPosInf and kNegInf not within fraction - if (!MathLimits::IsFinite(x) && !MathLimits::IsFinite(y)) { + if (!std::isfinite(x) || !std::isfinite(y)) { return false; } T relative_margin = static_cast(fraction * Max(Abs(x), Abs(y))); diff --git a/src/google/protobuf/stubs/mutex.h b/src/google/protobuf/stubs/mutex.h index 174290f624777..23f315f4726ac 100644 --- a/src/google/protobuf/stubs/mutex.h +++ b/src/google/protobuf/stubs/mutex.h @@ -30,48 +30,113 @@ #ifndef GOOGLE_PROTOBUF_STUBS_MUTEX_H_ #define GOOGLE_PROTOBUF_STUBS_MUTEX_H_ -#ifdef GOOGLE_PROTOBUF_NO_THREADLOCAL -#include +#include + +#ifdef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP + +#include + +// GetMessage conflicts with GeneratedMessageReflection::GetMessage(). +#ifdef GetMessage +#undef GetMessage +#endif + #endif #include +// Define thread-safety annotations for use below, if we are building with +// Clang. +#if defined(__clang__) && !defined(SWIG) +#define GOOGLE_PROTOBUF_ACQUIRE(...) \ + __attribute__((acquire_capability(__VA_ARGS__))) +#define GOOGLE_PROTOBUF_RELEASE(...) \ + __attribute__((release_capability(__VA_ARGS__))) +#define GOOGLE_PROTOBUF_CAPABILITY(x) __attribute__((capability(x))) +#else +#define GOOGLE_PROTOBUF_ACQUIRE(...) +#define GOOGLE_PROTOBUF_RELEASE(...) +#define GOOGLE_PROTOBUF_CAPABILITY(x) +#endif + +#include + // =================================================================== // emulates google3/base/mutex.h namespace google { namespace protobuf { namespace internal { -// A Mutex is a non-reentrant (aka non-recursive) mutex. At most one thread T -// may hold a mutex at a given time. If T attempts to Lock() the same Mutex -// while holding it, T will deadlock. -class LIBPROTOBUF_EXPORT Mutex { +#define GOOGLE_PROTOBUF_LINKER_INITIALIZED + +#ifdef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP + +// This class is a lightweight replacement for std::mutex on Windows platforms. +// std::mutex does not work on Windows XP SP2 with the latest VC++ libraries, +// because it utilizes the Concurrency Runtime that is only supported on Windows +// XP SP3 and above. +class PROTOBUF_EXPORT CriticalSectionLock { + public: + CriticalSectionLock() { InitializeCriticalSection(&critical_section_); } + ~CriticalSectionLock() { DeleteCriticalSection(&critical_section_); } + void lock() { EnterCriticalSection(&critical_section_); } + void unlock() { LeaveCriticalSection(&critical_section_); } + + private: + CRITICAL_SECTION critical_section_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CriticalSectionLock); +}; + +#endif + +// In MSVC std::mutex does not have a constexpr constructor. +// This wrapper makes the constructor constexpr. +template +class CallOnceInitializedMutex { public: - // Create a Mutex that is not held by anybody. - Mutex(); + constexpr CallOnceInitializedMutex() : flag_{}, buf_{} {} + ~CallOnceInitializedMutex() { get().~T(); } - // Destructor - ~Mutex(); + void lock() { get().lock(); } + void unlock() { get().unlock(); } - // Block if necessary until this Mutex is free, then acquire it exclusively. - void Lock(); + private: + T& get() { + std::call_once(flag_, [&] { ::new (static_cast(&buf_)) T(); }); + return reinterpret_cast(buf_); + } - // Release this Mutex. Caller must hold it exclusively. - void Unlock(); + std::once_flag flag_; + alignas(T) char buf_[sizeof(T)]; +}; +// Mutex is a natural type to wrap. As both google and other organization have +// specialized mutexes. gRPC also provides an injection mechanism for custom +// mutexes. +class GOOGLE_PROTOBUF_CAPABILITY("mutex") PROTOBUF_EXPORT WrappedMutex { + public: + constexpr WrappedMutex() = default; + void Lock() GOOGLE_PROTOBUF_ACQUIRE() { mu_.lock(); } + void Unlock() GOOGLE_PROTOBUF_RELEASE() { mu_.unlock(); } // Crash if this Mutex is not held exclusively by this thread. // May fail to crash when it should; will never crash when it should not. - void AssertHeld(); + void AssertHeld() const {} private: - struct Internal; - Internal* mInternal; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Mutex); +#if defined(GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP) + CallOnceInitializedMutex mu_{}; +#elif defined(_MSC_VER) + CallOnceInitializedMutex mu_{}; +#else + std::mutex mu_{}; +#endif }; +using Mutex = WrappedMutex; + // MutexLock(mu) acquires mu when constructed and releases it when destroyed. -class LIBPROTOBUF_EXPORT MutexLock { +class PROTOBUF_EXPORT MutexLock { public: explicit MutexLock(Mutex *mu) : mu_(mu) { this->mu_->Lock(); } ~MutexLock() { this->mu_->Unlock(); } @@ -84,12 +149,12 @@ class LIBPROTOBUF_EXPORT MutexLock { typedef MutexLock ReaderMutexLock; typedef MutexLock WriterMutexLock; -// MutexLockMaybe is like MutexLock, but is a no-op when mu is NULL. -class LIBPROTOBUF_EXPORT MutexLockMaybe { +// MutexLockMaybe is like MutexLock, but is a no-op when mu is nullptr. +class PROTOBUF_EXPORT MutexLockMaybe { public: explicit MutexLockMaybe(Mutex *mu) : - mu_(mu) { if (this->mu_ != NULL) { this->mu_->Lock(); } } - ~MutexLockMaybe() { if (this->mu_ != NULL) { this->mu_->Unlock(); } } + mu_(mu) { if (this->mu_ != nullptr) { this->mu_->Lock(); } } + ~MutexLockMaybe() { if (this->mu_ != nullptr) { this->mu_->Unlock(); } } private: Mutex *const mu_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe); @@ -107,7 +172,7 @@ class ThreadLocalStorage { } T* Get() { T* result = static_cast(pthread_getspecific(key_)); - if (result == NULL) { + if (result == nullptr) { result = new T(); pthread_setspecific(key_, result); } @@ -133,8 +198,12 @@ using internal::ReaderMutexLock; using internal::WriterMutexLock; using internal::MutexLockMaybe; - } // namespace protobuf } // namespace google +#undef GOOGLE_PROTOBUF_ACQUIRE +#undef GOOGLE_PROTOBUF_RELEASE + +#include + #endif // GOOGLE_PROTOBUF_STUBS_MUTEX_H_ diff --git a/src/google/protobuf/stubs/once.cc b/src/google/protobuf/stubs/once.cc deleted file mode 100644 index 889c647660ded..0000000000000 --- a/src/google/protobuf/stubs/once.cc +++ /dev/null @@ -1,99 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// -// emulates google3/base/once.h -// -// This header is intended to be included only by internal .cc files and -// generated .pb.cc files. Users should not use this directly. - -#include - -#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY - -#ifdef _WIN32 -#include -#else -#include -#endif - -#include - -namespace google { -namespace protobuf { - -namespace { - -void SchedYield() { -#ifdef _WIN32 - Sleep(0); -#else // POSIX - sched_yield(); -#endif -} - -} // namespace - -void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure) { - internal::AtomicWord state = internal::Acquire_Load(once); - // Fast path. The provided closure was already executed. - if (state == ONCE_STATE_DONE) { - return; - } - // The closure execution did not complete yet. The once object can be in one - // of the two following states: - // - UNINITIALIZED: We are the first thread calling this function. - // - EXECUTING_CLOSURE: Another thread is already executing the closure. - // - // First, try to change the state from UNINITIALIZED to EXECUTING_CLOSURE - // atomically. - state = internal::Acquire_CompareAndSwap( - once, ONCE_STATE_UNINITIALIZED, ONCE_STATE_EXECUTING_CLOSURE); - if (state == ONCE_STATE_UNINITIALIZED) { - // We are the first thread to call this function, so we have to call the - // closure. - closure->Run(); - internal::Release_Store(once, ONCE_STATE_DONE); - } else { - // Another thread has already started executing the closure. We need to - // wait until it completes the initialization. - while (state == ONCE_STATE_EXECUTING_CLOSURE) { - // Note that futex() could be used here on Linux as an improvement. - SchedYield(); - state = internal::Acquire_Load(once); - } - } -} - -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY diff --git a/src/google/protobuf/stubs/once.h b/src/google/protobuf/stubs/once.h index 1f082c37e9b1d..070d36d193088 100644 --- a/src/google/protobuf/stubs/once.h +++ b/src/google/protobuf/stubs/once.h @@ -28,140 +28,28 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Author: kenton@google.com (Kenton Varda) -// -// emulates google3/base/once.h -// -// This header is intended to be included only by internal .cc files and -// generated .pb.cc files. Users should not use this directly. -// -// This is basically a portable version of pthread_once(). -// -// This header declares: -// * A type called ProtobufOnceType. -// * A macro GOOGLE_PROTOBUF_DECLARE_ONCE() which declares a variable of type -// ProtobufOnceType. This is the only legal way to declare such a variable. -// The macro may only be used at the global scope (you cannot create local or -// class member variables of this type). -// * A function GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()). -// This function, when invoked multiple times given the same ProtobufOnceType -// object, will invoke init_func on the first call only, and will make sure -// none of the calls return before that first call to init_func has finished. -// * The user can provide a parameter which GoogleOnceInit() forwards to the -// user-provided function when it is called. Usage example: -// int a = 10; -// GoogleOnceInit(&my_once, &MyFunctionExpectingIntArgument, &a); -// * This implementation guarantees that ProtobufOnceType is a POD (i.e. no -// static initializer generated). -// -// This implements a way to perform lazy initialization. It's more efficient -// than using mutexes as no lock is needed if initialization has already -// happened. -// -// Example usage: -// void Init(); -// GOOGLE_PROTOBUF_DECLARE_ONCE(once_init); -// -// // Calls Init() exactly once. -// void InitOnce() { -// GoogleOnceInit(&once_init, &Init); -// } -// -// Note that if GoogleOnceInit() is called before main() has begun, it must -// only be called by the thread that will eventually call main() -- that is, -// the thread that performs dynamic initialization. In general this is a safe -// assumption since people don't usually construct threads before main() starts, -// but it is technically not guaranteed. Unfortunately, Win32 provides no way -// whatsoever to statically-initialize its synchronization primitives, so our -// only choice is to assume that dynamic initialization is single-threaded. - #ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__ #define GOOGLE_PROTOBUF_STUBS_ONCE_H__ -#include -#include -#include +#include +#include + +#include namespace google { namespace protobuf { +namespace internal { -#ifdef GOOGLE_PROTOBUF_NO_THREAD_SAFETY - -typedef bool ProtobufOnceType; - -#define GOOGLE_PROTOBUF_ONCE_INIT false - -inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) { - if (!*once) { - *once = true; - init_func(); - } -} - -template -inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg), - Arg arg) { - if (!*once) { - *once = true; - init_func(arg); - } +using once_flag = std::once_flag; +template +void call_once(Args&&... args ) { + std::call_once(std::forward(args)...); } -#else - -enum { - ONCE_STATE_UNINITIALIZED = 0, - ONCE_STATE_EXECUTING_CLOSURE = 1, - ONCE_STATE_DONE = 2 -}; - -typedef internal::AtomicWord ProtobufOnceType; - -#define GOOGLE_PROTOBUF_ONCE_INIT ::google::protobuf::ONCE_STATE_UNINITIALIZED - -LIBPROTOBUF_EXPORT -void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure); - -inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) { - if (internal::Acquire_Load(once) != ONCE_STATE_DONE) { - internal::FunctionClosure0 func(init_func, false); - GoogleOnceInitImpl(once, &func); - } -} - -template -inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg*), - Arg* arg) { - if (internal::Acquire_Load(once) != ONCE_STATE_DONE) { - internal::FunctionClosure1 func(init_func, false, arg); - GoogleOnceInitImpl(once, &func); - } -} - -#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY - -class GoogleOnceDynamic { - public: - GoogleOnceDynamic() : state_(GOOGLE_PROTOBUF_ONCE_INIT) { } - - // If this->Init() has not been called before by any thread, - // execute (*func_with_arg)(arg) then return. - // Otherwise, wait until that prior invocation has finished - // executing its function, then return. - template - void Init(void (*func_with_arg)(T*), T* arg) { - GoogleOnceInit(&this->state_, - func_with_arg, - arg); - } - private: - ProtobufOnceType state_; -}; - -#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \ - ::google::protobuf::ProtobufOnceType NAME = GOOGLE_PROTOBUF_ONCE_INIT - +} // namespace internal } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_STUBS_ONCE_H__ diff --git a/src/google/protobuf/stubs/once_unittest.cc b/src/google/protobuf/stubs/once_unittest.cc deleted file mode 100644 index d5f7779ec9b3a..0000000000000 --- a/src/google/protobuf/stubs/once_unittest.cc +++ /dev/null @@ -1,254 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) - -#ifdef _WIN32 -#include -#else -#include -#include -#endif - -#include -#include -#include - -namespace google { -namespace protobuf { -namespace { - -class OnceInitTest : public testing::Test { - protected: - void SetUp() { - state_ = INIT_NOT_STARTED; - current_test_ = this; - } - - // Since ProtobufOnceType is only allowed to be allocated in static storage, - // each test must use a different pair of ProtobufOnceType objects which it - // must declare itself. - void SetOnces(ProtobufOnceType* once, ProtobufOnceType* recursive_once) { - once_ = once; - recursive_once_ = recursive_once; - } - - void InitOnce() { - GoogleOnceInit(once_, &InitStatic); - } - void InitRecursiveOnce() { - GoogleOnceInit(recursive_once_, &InitRecursiveStatic); - } - - void BlockInit() { init_blocker_.Lock(); } - void UnblockInit() { init_blocker_.Unlock(); } - - class TestThread { - public: - TestThread(Closure* callback) - : done_(false), joined_(false), callback_(callback) { -#ifdef _WIN32 - thread_ = CreateThread(NULL, 0, &Start, this, 0, NULL); -#else - pthread_create(&thread_, NULL, &Start, this); -#endif - } - ~TestThread() { - if (!joined_) Join(); - } - - bool IsDone() { - MutexLock lock(&done_mutex_); - return done_; - } - void Join() { - joined_ = true; -#ifdef _WIN32 - WaitForSingleObject(thread_, INFINITE); - CloseHandle(thread_); -#else - pthread_join(thread_, NULL); -#endif - } - - private: -#ifdef _WIN32 - HANDLE thread_; -#else - pthread_t thread_; -#endif - - Mutex done_mutex_; - bool done_; - bool joined_; - Closure* callback_; - -#ifdef _WIN32 - static DWORD WINAPI Start(LPVOID arg) { -#else - static void* Start(void* arg) { -#endif - reinterpret_cast(arg)->Run(); - return 0; - } - - void Run() { - callback_->Run(); - MutexLock lock(&done_mutex_); - done_ = true; - } - }; - - TestThread* RunInitOnceInNewThread() { - return new TestThread(NewCallback(this, &OnceInitTest::InitOnce)); - } - TestThread* RunInitRecursiveOnceInNewThread() { - return new TestThread( - NewCallback(this, &OnceInitTest::InitRecursiveOnce)); - } - - enum State { - INIT_NOT_STARTED, - INIT_STARTED, - INIT_DONE - }; - State CurrentState() { - MutexLock lock(&mutex_); - return state_; - } - - void WaitABit() { -#ifdef _WIN32 - Sleep(1000); -#else - sleep(1); -#endif - } - - private: - Mutex mutex_; - Mutex init_blocker_; - State state_; - ProtobufOnceType* once_; - ProtobufOnceType* recursive_once_; - - void Init() { - MutexLock lock(&mutex_); - EXPECT_EQ(INIT_NOT_STARTED, state_); - state_ = INIT_STARTED; - mutex_.Unlock(); - init_blocker_.Lock(); - init_blocker_.Unlock(); - mutex_.Lock(); - state_ = INIT_DONE; - } - - static OnceInitTest* current_test_; - static void InitStatic() { current_test_->Init(); } - static void InitRecursiveStatic() { current_test_->InitOnce(); } -}; - -OnceInitTest* OnceInitTest::current_test_ = NULL; - -GOOGLE_PROTOBUF_DECLARE_ONCE(simple_once); - -TEST_F(OnceInitTest, Simple) { - SetOnces(&simple_once, NULL); - - EXPECT_EQ(INIT_NOT_STARTED, CurrentState()); - InitOnce(); - EXPECT_EQ(INIT_DONE, CurrentState()); - - // Calling again has no effect. - InitOnce(); - EXPECT_EQ(INIT_DONE, CurrentState()); -} - -GOOGLE_PROTOBUF_DECLARE_ONCE(recursive_once1); -GOOGLE_PROTOBUF_DECLARE_ONCE(recursive_once2); - -TEST_F(OnceInitTest, Recursive) { - SetOnces(&recursive_once1, &recursive_once2); - - EXPECT_EQ(INIT_NOT_STARTED, CurrentState()); - InitRecursiveOnce(); - EXPECT_EQ(INIT_DONE, CurrentState()); -} - -GOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_once); - -TEST_F(OnceInitTest, MultipleThreads) { - SetOnces(&multiple_threads_once, NULL); - - scoped_ptr threads[4]; - EXPECT_EQ(INIT_NOT_STARTED, CurrentState()); - for (int i = 0; i < 4; i++) { - threads[i].reset(RunInitOnceInNewThread()); - } - for (int i = 0; i < 4; i++) { - threads[i]->Join(); - } - EXPECT_EQ(INIT_DONE, CurrentState()); -} - -GOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_blocked_once1); -GOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_blocked_once2); - -TEST_F(OnceInitTest, MultipleThreadsBlocked) { - SetOnces(&multiple_threads_blocked_once1, &multiple_threads_blocked_once2); - - scoped_ptr threads[8]; - EXPECT_EQ(INIT_NOT_STARTED, CurrentState()); - - BlockInit(); - for (int i = 0; i < 4; i++) { - threads[i].reset(RunInitOnceInNewThread()); - } - for (int i = 4; i < 8; i++) { - threads[i].reset(RunInitRecursiveOnceInNewThread()); - } - - WaitABit(); - - // We should now have one thread blocked inside Init(), four blocked waiting - // for Init() to complete, and three blocked waiting for InitRecursive() to - // complete. - EXPECT_EQ(INIT_STARTED, CurrentState()); - UnblockInit(); - - for (int i = 0; i < 8; i++) { - threads[i]->Join(); - } - EXPECT_EQ(INIT_DONE, CurrentState()); -} - -} // anonymous namespace -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/stubs/platform_macros.h b/src/google/protobuf/stubs/platform_macros.h index 7a54060dfa31a..ce1b1e3655769 100644 --- a/src/google/protobuf/stubs/platform_macros.h +++ b/src/google/protobuf/stubs/platform_macros.h @@ -50,10 +50,13 @@ #elif defined(_M_ARM) || defined(__ARMEL__) #define GOOGLE_PROTOBUF_ARCH_ARM 1 #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(_M_ARM64) +#define GOOGLE_PROTOBUF_ARCH_ARM 1 +#define GOOGLE_PROTOBUF_ARCH_64_BIT 1 #elif defined(__aarch64__) #define GOOGLE_PROTOBUF_ARCH_AARCH64 1 #define GOOGLE_PROTOBUF_ARCH_64_BIT 1 -#elif defined(__MIPSEL__) +#elif defined(__mips__) #if defined(__LP64__) #define GOOGLE_PROTOBUF_ARCH_MIPS64 1 #define GOOGLE_PROTOBUF_ARCH_64_BIT 1 @@ -96,6 +99,7 @@ GOOGLE_PROTOBUF_PLATFORM_ERROR #if defined(__APPLE__) #define GOOGLE_PROTOBUF_OS_APPLE +#include #include #if TARGET_OS_IPHONE #define GOOGLE_PROTOBUF_OS_IPHONE @@ -122,4 +126,9 @@ GOOGLE_PROTOBUF_PLATFORM_ERROR #define GOOGLE_PROTOBUF_NO_THREADLOCAL #endif +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 1070 +// __thread keyword requires at least 10.7 +#define GOOGLE_PROTOBUF_NO_THREADLOCAL +#endif + #endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ diff --git a/src/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h index dbc29861a588d..b7aab404ca077 100644 --- a/src/google/protobuf/stubs/port.h +++ b/src/google/protobuf/stubs/port.h @@ -32,20 +32,16 @@ #define GOOGLE_PROTOBUF_STUBS_PORT_H_ #include +#include #include #include #include #include -#if defined(__osf__) -// Tru64 lacks stdint.h, but has inttypes.h which defines a superset of -// what stdint.h would define. -#include -#elif !defined(_MSC_VER) -#include -#endif #include +#include + #undef PROTOBUF_LITTLE_ENDIAN #ifdef _WIN32 // Assuming windows is always little-endian. @@ -55,23 +51,37 @@ #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) #define PROTOBUF_LITTLE_ENDIAN 1 #endif - #if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) - // If MSVC has "/RTCc" set, it will complain about truncating casts at - // runtime. This file contains some intentional truncating casts. - #pragma runtime_checks("c", off) - #endif +#if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) +// If MSVC has "/RTCc" set, it will complain about truncating casts at +// runtime. This file contains some intentional truncating casts. +#pragma runtime_checks("c", off) +#endif #else - #include // __BYTE_ORDER - #if defined(__OpenBSD__) - #include - #endif - #if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ - (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \ - (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN)) && \ - !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) - #define PROTOBUF_LITTLE_ENDIAN 1 - #endif +#ifdef __APPLE__ +#include // __BYTE_ORDER +#else +#include // __BYTE_ORDER +#endif +#if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ + (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN)) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) +#define PROTOBUF_LITTLE_ENDIAN 1 +#endif +#endif + +// These #includes are for the byte swap functions declared later on. +#ifdef _MSC_VER +#include // NOLINT(build/include) +#include +#elif defined(__APPLE__) +#include +#elif defined(__GLIBC__) || defined(__BIONIC__) || defined(__CYGWIN__) +#include // IWYU pragma: export #endif + +// Legacy: some users reference these (internal-only) macros even though we +// don't need them any more. #if defined(_MSC_VER) && defined(PROTOBUF_USE_DLLS) #ifdef LIBPROTOBUF_EXPORTS #define LIBPROTOBUF_EXPORT __declspec(dllexport) @@ -88,14 +98,9 @@ #define LIBPROTOC_EXPORT #endif -// These #includes are for the byte swap functions declared later on. -#ifdef _MSC_VER -#include // NOLINT(build/include) -#elif defined(__APPLE__) -#include -#elif defined(__GLIBC__) || defined(__CYGWIN__) -#include // IWYU pragma: export -#endif +#define PROTOBUF_RUNTIME_DEPRECATED(message) PROTOBUF_DEPRECATED_MSG(message) +#define GOOGLE_PROTOBUF_RUNTIME_DEPRECATED(message) \ + PROTOBUF_DEPRECATED_MSG(message) // =================================================================== // from google3/base/port.h @@ -106,24 +111,17 @@ // undefined otherwise. Do NOT define it to 0 -- that causes // '#ifdef LANG_CXX11' to behave differently from '#if LANG_CXX11'. #define LANG_CXX11 1 +#else +#error "Protobuf requires at least C++11." #endif namespace google { namespace protobuf { +using ConstStringParam = const std::string &; + typedef unsigned int uint; -#ifdef _MSC_VER -typedef signed __int8 int8; -typedef __int16 int16; -typedef __int32 int32; -typedef __int64 int64; - -typedef unsigned __int8 uint8; -typedef unsigned __int16 uint16; -typedef unsigned __int32 uint32; -typedef unsigned __int64 uint64; -#else typedef int8_t int8; typedef int16_t int16; typedef int32_t int32; @@ -133,134 +131,55 @@ typedef uint8_t uint8; typedef uint16_t uint16; typedef uint32_t uint32; typedef uint64_t uint64; -#endif - -// long long macros to be used because gcc and vc++ use different suffixes, -// and different size specifiers in format strings -#undef GOOGLE_LONGLONG -#undef GOOGLE_ULONGLONG -#undef GOOGLE_LL_FORMAT - -#ifdef _MSC_VER -#define GOOGLE_LONGLONG(x) x##I64 -#define GOOGLE_ULONGLONG(x) x##UI64 -#define GOOGLE_LL_FORMAT "I64" // As in printf("%I64d", ...) -#else -// By long long, we actually mean int64. -#define GOOGLE_LONGLONG(x) x##LL -#define GOOGLE_ULONGLONG(x) x##ULL -// Used to format real long long integers. -#define GOOGLE_LL_FORMAT "ll" // As in "%lld". Note that "q" is poor form also. -#endif static const int32 kint32max = 0x7FFFFFFF; static const int32 kint32min = -kint32max - 1; -static const int64 kint64max = GOOGLE_LONGLONG(0x7FFFFFFFFFFFFFFF); +static const int64 kint64max = PROTOBUF_LONGLONG(0x7FFFFFFFFFFFFFFF); static const int64 kint64min = -kint64max - 1; static const uint32 kuint32max = 0xFFFFFFFFu; -static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF); - -// ------------------------------------------------------------------- -// Annotations: Some parts of the code have been annotated in ways that might -// be useful to some compilers or tools, but are not supported universally. -// You can #define these annotations yourself if the default implementation -// is not right for you. - -#ifndef GOOGLE_ATTRIBUTE_ALWAYS_INLINE -#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -// For functions we want to force inline. -// Introduced in gcc 3.1. -#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline)) -#else -// Other compilers will have to figure it out for themselves. -#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE -#endif -#endif - -#ifndef GOOGLE_ATTRIBUTE_NOINLINE -#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -// For functions we want to force not inline. -// Introduced in gcc 3.1. -#define GOOGLE_ATTRIBUTE_NOINLINE __attribute__ ((noinline)) -#elif defined(_MSC_VER) && (_MSC_VER >= 1400) -// Seems to have been around since at least Visual Studio 2005 -#define GOOGLE_ATTRIBUTE_NOINLINE __declspec(noinline) -#else -// Other compilers will have to figure it out for themselves. -#define GOOGLE_ATTRIBUTE_NOINLINE -#endif -#endif +static const uint64 kuint64max = PROTOBUF_ULONGLONG(0xFFFFFFFFFFFFFFFF); + +#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||\ + defined(MEMORY_SANITIZER) + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus +uint16_t __sanitizer_unaligned_load16(const void *p); +uint32_t __sanitizer_unaligned_load32(const void *p); +uint64_t __sanitizer_unaligned_load64(const void *p); +void __sanitizer_unaligned_store16(void *p, uint16_t v); +void __sanitizer_unaligned_store32(void *p, uint32_t v); +void __sanitizer_unaligned_store64(void *p, uint64_t v); +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus -#ifndef GOOGLE_ATTRIBUTE_NORETURN -#ifdef __GNUC__ -// Tell the compiler that a given function never returns. -#define GOOGLE_ATTRIBUTE_NORETURN __attribute__((noreturn)) -#else -#define GOOGLE_ATTRIBUTE_NORETURN -#endif -#endif - -#ifndef GOOGLE_ATTRIBUTE_DEPRECATED -#ifdef __GNUC__ -// If the method/variable/type is used anywhere, produce a warning. -#define GOOGLE_ATTRIBUTE_DEPRECATED __attribute__((deprecated)) -#else -#define GOOGLE_ATTRIBUTE_DEPRECATED -#endif -#endif - -#ifndef GOOGLE_PREDICT_TRUE -#ifdef __GNUC__ -// Provided at least since GCC 3.0. -#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) -#else -#define GOOGLE_PREDICT_TRUE(x) (x) -#endif -#endif - -#ifndef GOOGLE_PREDICT_FALSE -#ifdef __GNUC__ -// Provided at least since GCC 3.0. -#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0)) -#else -#define GOOGLE_PREDICT_FALSE(x) (x) -#endif -#endif +inline uint16 GOOGLE_UNALIGNED_LOAD16(const void *p) { + return __sanitizer_unaligned_load16(p); +} -// Delimits a block of code which may write to memory which is simultaneously -// written by other threads, but which has been determined to be thread-safe -// (e.g. because it is an idempotent write). -#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN -#define GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN() -#endif -#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_END -#define GOOGLE_SAFE_CONCURRENT_WRITES_END() -#endif +inline uint32 GOOGLE_UNALIGNED_LOAD32(const void *p) { + return __sanitizer_unaligned_load32(p); +} -#if defined(__clang__) && defined(__has_cpp_attribute) \ - && !defined(GOOGLE_PROTOBUF_OS_APPLE) -# if defined(GOOGLE_PROTOBUF_OS_NACL) || defined(EMSCRIPTEN) || \ - __has_cpp_attribute(clang::fallthrough) -# define GOOGLE_FALLTHROUGH_INTENDED [[clang::fallthrough]] -# endif -#endif +inline uint64 GOOGLE_UNALIGNED_LOAD64(const void *p) { + return __sanitizer_unaligned_load64(p); +} -#ifndef GOOGLE_FALLTHROUGH_INTENDED -# define GOOGLE_FALLTHROUGH_INTENDED -#endif +inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16 v) { + __sanitizer_unaligned_store16(p, v); +} -#define GOOGLE_GUARDED_BY(x) -#define GOOGLE_ATTRIBUTE_COLD +inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32 v) { + __sanitizer_unaligned_store32(p, v); +} -#ifdef GOOGLE_PROTOBUF_DONT_USE_UNALIGNED -# define GOOGLE_PROTOBUF_USE_UNALIGNED 0 -#else -// x86 and x86-64 can perform unaligned loads/stores directly. -# define GOOGLE_PROTOBUF_USE_UNALIGNED defined(_M_X64) || \ - defined(__x86_64__) || defined(_M_IX86) || defined(__i386__) -#endif +inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) { + __sanitizer_unaligned_store64(p, v); +} -#if GOOGLE_PROTOBUF_USE_UNALIGNED +#elif defined(GOOGLE_PROTOBUF_USE_UNALIGNED) && GOOGLE_PROTOBUF_USE_UNALIGNED #define GOOGLE_UNALIGNED_LOAD16(_p) (*reinterpret_cast(_p)) #define GOOGLE_UNALIGNED_LOAD32(_p) (*reinterpret_cast(_p)) @@ -302,10 +221,11 @@ inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) { } #endif -#if defined(_MSC_VER) -#define GOOGLE_THREAD_LOCAL __declspec(thread) -#else -#define GOOGLE_THREAD_LOCAL __thread +#if defined(GOOGLE_PROTOBUF_OS_NACL) \ + || (defined(__ANDROID__) && defined(__clang__) \ + && (__clang_major__ == 3 && __clang_minor__ == 8) \ + && (__clang_patchlevel__ < 275480)) +# define GOOGLE_PROTOBUF_USE_PORTABLE_LOG2 #endif // The following guarantees declaration of the byte swap functions. @@ -320,12 +240,16 @@ inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) { #define bswap_32(x) OSSwapInt32(x) #define bswap_64(x) OSSwapInt64(x) -#elif !defined(__GLIBC__) && !defined(__CYGWIN__) +#elif !defined(__GLIBC__) && !defined(__BIONIC__) && !defined(__CYGWIN__) +#ifndef bswap_16 static inline uint16 bswap_16(uint16 x) { return static_cast(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); } #define bswap_16(x) bswap_16(x) +#endif + +#ifndef bswap_32 static inline uint32 bswap_32(uint32 x) { return (((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | @@ -333,17 +257,21 @@ static inline uint32 bswap_32(uint32 x) { ((x & 0xFF000000) >> 24)); } #define bswap_32(x) bswap_32(x) +#endif + +#ifndef bswap_64 static inline uint64 bswap_64(uint64 x) { - return (((x & GOOGLE_ULONGLONG(0xFF)) << 56) | - ((x & GOOGLE_ULONGLONG(0xFF00)) << 40) | - ((x & GOOGLE_ULONGLONG(0xFF0000)) << 24) | - ((x & GOOGLE_ULONGLONG(0xFF000000)) << 8) | - ((x & GOOGLE_ULONGLONG(0xFF00000000)) >> 8) | - ((x & GOOGLE_ULONGLONG(0xFF0000000000)) >> 24) | - ((x & GOOGLE_ULONGLONG(0xFF000000000000)) >> 40) | - ((x & GOOGLE_ULONGLONG(0xFF00000000000000)) >> 56)); + return (((x & PROTOBUF_ULONGLONG(0xFF)) << 56) | + ((x & PROTOBUF_ULONGLONG(0xFF00)) << 40) | + ((x & PROTOBUF_ULONGLONG(0xFF0000)) << 24) | + ((x & PROTOBUF_ULONGLONG(0xFF000000)) << 8) | + ((x & PROTOBUF_ULONGLONG(0xFF00000000)) >> 8) | + ((x & PROTOBUF_ULONGLONG(0xFF0000000000)) >> 24) | + ((x & PROTOBUF_ULONGLONG(0xFF000000000000)) >> 40) | + ((x & PROTOBUF_ULONGLONG(0xFF00000000000000)) >> 56)); } #define bswap_64(x) bswap_64(x) +#endif #endif @@ -355,25 +283,28 @@ class Bits { static uint32 Log2FloorNonZero(uint32 n) { #if defined(__GNUC__) return 31 ^ static_cast(__builtin_clz(n)); -#elif defined(COMPILER_MSVC) && defined(_M_IX86) - _asm { - bsr ebx, n - mov n, ebx - } - return n; +#elif defined(_MSC_VER) + unsigned long where; + _BitScanReverse(&where, n); + return where; #else return Log2FloorNonZero_Portable(n); #endif } static uint32 Log2FloorNonZero64(uint64 n) { - // arm-nacl-clang runs into an instruction-selection failure when it - // encounters __builtin_clzll: + // Older versions of clang run into an instruction-selection failure when + // it encounters __builtin_clzll: // https://bugs.chromium.org/p/nativeclient/issues/detail?id=4395 - // To work around this, when we build for NaCl we use the portable + // This includes arm-nacl-clang and clang in older Android NDK versions. + // To work around this, when we build with those we use the portable // implementation instead. -#if defined(__GNUC__) && !defined(GOOGLE_PROTOBUF_OS_NACL) +#if defined(__GNUC__) && !defined(GOOGLE_PROTOBUF_USE_PORTABLE_LOG2) return 63 ^ static_cast(__builtin_clzll(n)); +#elif defined(_MSC_VER) && defined(_M_X64) + unsigned long where; + _BitScanReverse64(&where, n); + return where; #else return Log2FloorNonZero64_Portable(n); #endif @@ -409,7 +340,7 @@ class Bits { // =================================================================== // from google3/util/endian/endian.h -LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x); +PROTOBUF_EXPORT uint32 ghtonl(uint32 x); class BigEndian { public: @@ -467,11 +398,9 @@ class BigEndian { } }; -#ifndef GOOGLE_ATTRIBUTE_SECTION_VARIABLE -#define GOOGLE_ATTRIBUTE_SECTION_VARIABLE(name) -#endif - } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_STUBS_PORT_H_ diff --git a/src/google/protobuf/stubs/scoped_ptr.h b/src/google/protobuf/stubs/scoped_ptr.h deleted file mode 100644 index 4423c118c40b5..0000000000000 --- a/src/google/protobuf/stubs/scoped_ptr.h +++ /dev/null @@ -1,236 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_STUBS_SCOPED_PTR_H_ -#define GOOGLE_PROTOBUF_STUBS_SCOPED_PTR_H_ - -#include - -namespace google { -namespace protobuf { - -// =================================================================== -// from google3/base/scoped_ptr.h - -namespace internal { - -// This is an implementation designed to match the anticipated future TR2 -// implementation of the scoped_ptr class, and its closely-related brethren, -// scoped_array, scoped_ptr_malloc, and make_scoped_ptr. - -template class scoped_ptr; -template class scoped_array; - -// A scoped_ptr is like a T*, except that the destructor of scoped_ptr -// automatically deletes the pointer it holds (if any). -// That is, scoped_ptr owns the T object that it points to. -// Like a T*, a scoped_ptr may hold either NULL or a pointer to a T object. -// -// The size of a scoped_ptr is small: -// sizeof(scoped_ptr) == sizeof(C*) -template -class scoped_ptr { - public: - - // The element type - typedef C element_type; - - // Constructor. Defaults to initializing with NULL. - // There is no way to create an uninitialized scoped_ptr. - // The input parameter must be allocated with new. - explicit scoped_ptr(C* p = NULL) : ptr_(p) { } - - // Destructor. If there is a C object, delete it. - // We don't need to test ptr_ == NULL because C++ does that for us. - ~scoped_ptr() { - enum { type_must_be_complete = sizeof(C) }; - delete ptr_; - } - - // Reset. Deletes the current owned object, if any. - // Then takes ownership of a new object, if given. - // this->reset(this->get()) works. - void reset(C* p = NULL) { - if (p != ptr_) { - enum { type_must_be_complete = sizeof(C) }; - delete ptr_; - ptr_ = p; - } - } - - // Accessors to get the owned object. - // operator* and operator-> will assert() if there is no current object. - C& operator*() const { - assert(ptr_ != NULL); - return *ptr_; - } - C* operator->() const { - assert(ptr_ != NULL); - return ptr_; - } - C* get() const { return ptr_; } - - // Comparison operators. - // These return whether two scoped_ptr refer to the same object, not just to - // two different but equal objects. - bool operator==(C* p) const { return ptr_ == p; } - bool operator!=(C* p) const { return ptr_ != p; } - - // Swap two scoped pointers. - void swap(scoped_ptr& p2) { - C* tmp = ptr_; - ptr_ = p2.ptr_; - p2.ptr_ = tmp; - } - - // Release a pointer. - // The return value is the current pointer held by this object. - // If this object holds a NULL pointer, the return value is NULL. - // After this operation, this object will hold a NULL pointer, - // and will not own the object any more. - C* release() { - C* retVal = ptr_; - ptr_ = NULL; - return retVal; - } - - private: - C* ptr_; - - // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't - // make sense, and if C2 == C, it still doesn't make sense because you should - // never have the same object owned by two different scoped_ptrs. - template bool operator==(scoped_ptr const& p2) const; - template bool operator!=(scoped_ptr const& p2) const; - - // Disallow evil constructors - scoped_ptr(const scoped_ptr&); - void operator=(const scoped_ptr&); -}; - -// scoped_array is like scoped_ptr, except that the caller must allocate -// with new [] and the destructor deletes objects with delete []. -// -// As with scoped_ptr, a scoped_array either points to an object -// or is NULL. A scoped_array owns the object that it points to. -// -// Size: sizeof(scoped_array) == sizeof(C*) -template -class scoped_array { - public: - - // The element type - typedef C element_type; - - // Constructor. Defaults to initializing with NULL. - // There is no way to create an uninitialized scoped_array. - // The input parameter must be allocated with new []. - explicit scoped_array(C* p = NULL) : array_(p) { } - - // Destructor. If there is a C object, delete it. - // We don't need to test ptr_ == NULL because C++ does that for us. - ~scoped_array() { - enum { type_must_be_complete = sizeof(C) }; - delete[] array_; - } - - // Reset. Deletes the current owned object, if any. - // Then takes ownership of a new object, if given. - // this->reset(this->get()) works. - void reset(C* p = NULL) { - if (p != array_) { - enum { type_must_be_complete = sizeof(C) }; - delete[] array_; - array_ = p; - } - } - - // Get one element of the current object. - // Will assert() if there is no current object, or index i is negative. - C& operator[](std::ptrdiff_t i) const { - assert(i >= 0); - assert(array_ != NULL); - return array_[i]; - } - - // Get a pointer to the zeroth element of the current object. - // If there is no current object, return NULL. - C* get() const { - return array_; - } - - // Comparison operators. - // These return whether two scoped_array refer to the same object, not just to - // two different but equal objects. - bool operator==(C* p) const { return array_ == p; } - bool operator!=(C* p) const { return array_ != p; } - - // Swap two scoped arrays. - void swap(scoped_array& p2) { - C* tmp = array_; - array_ = p2.array_; - p2.array_ = tmp; - } - - // Release an array. - // The return value is the current pointer held by this object. - // If this object holds a NULL pointer, the return value is NULL. - // After this operation, this object will hold a NULL pointer, - // and will not own the object any more. - C* release() { - C* retVal = array_; - array_ = NULL; - return retVal; - } - - private: - C* array_; - - // Forbid comparison of different scoped_array types. - template bool operator==(scoped_array const& p2) const; - template bool operator!=(scoped_array const& p2) const; - - // Disallow evil constructors - scoped_array(const scoped_array&); - void operator=(const scoped_array&); -}; - -} // namespace internal - -// We made these internal so that they would show up as such in the docs, -// but we don't want to stick "internal::" in front of them everywhere. -using internal::scoped_ptr; -using internal::scoped_array; - - -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_STUBS_SCOPED_PTR_H_ diff --git a/src/google/protobuf/stubs/shared_ptr.h b/src/google/protobuf/stubs/shared_ptr.h deleted file mode 100644 index 7da114e9367a6..0000000000000 --- a/src/google/protobuf/stubs/shared_ptr.h +++ /dev/null @@ -1,471 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2014 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// from google3/util/gtl/shared_ptr.h - -#ifndef GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__ -#define GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__ - -#include - -#include // for swap -#include -#include - -namespace google { -namespace protobuf { -namespace internal { - -// Alias to std::shared_ptr for any C++11 platform, -// and for any supported MSVC compiler. -#if !defined(UTIL_GTL_USE_STD_SHARED_PTR) && \ - (defined(COMPILER_MSVC) || defined(LANG_CXX11)) -#define UTIL_GTL_USE_STD_SHARED_PTR 1 -#endif - -#if defined(UTIL_GTL_USE_STD_SHARED_PTR) && UTIL_GTL_USE_STD_SHARED_PTR - -// These are transitional. They will be going away soon. -// Please just #include and just type std::shared_ptr yourself, instead -// of relying on this file. -// -// Migration doc: http://go/std-shared-ptr-lsc -using std::enable_shared_from_this; -using std::shared_ptr; -using std::static_pointer_cast; -using std::weak_ptr; - -#else // below, UTIL_GTL_USE_STD_SHARED_PTR not set or set to 0. - -// For everything else there is the google3 implementation. -inline bool RefCountDec(volatile Atomic32 *ptr) { - return Barrier_AtomicIncrement(ptr, -1) != 0; -} - -inline void RefCountInc(volatile Atomic32 *ptr) { - NoBarrier_AtomicIncrement(ptr, 1); -} - -template class shared_ptr; -template class weak_ptr; - -// This class is an internal implementation detail for shared_ptr. If two -// shared_ptrs point to the same object, they also share a control block. -// An "empty" shared_pointer refers to NULL and also has a NULL control block. -// It contains all of the state that's needed for reference counting or any -// other kind of resource management. In this implementation the control block -// happens to consist of two atomic words, the reference count (the number -// of shared_ptrs that share ownership of the object) and the weak count -// (the number of weak_ptrs that observe the object, plus 1 if the -// refcount is nonzero). -// -// The "plus 1" is to prevent a race condition in the shared_ptr and -// weak_ptr destructors. We need to make sure the control block is -// only deleted once, so we need to make sure that at most one -// object sees the weak count decremented from 1 to 0. -class SharedPtrControlBlock { - template friend class shared_ptr; - template friend class weak_ptr; - private: - SharedPtrControlBlock() : refcount_(1), weak_count_(1) { } - Atomic32 refcount_; - Atomic32 weak_count_; -}; - -// Forward declaration. The class is defined below. -template class enable_shared_from_this; - -template -class shared_ptr { - template friend class weak_ptr; - public: - typedef T element_type; - - shared_ptr() : ptr_(NULL), control_block_(NULL) {} - - explicit shared_ptr(T* ptr) - : ptr_(ptr), - control_block_(ptr != NULL ? new SharedPtrControlBlock : NULL) { - // If p is non-null and T inherits from enable_shared_from_this, we - // set up the data that shared_from_this needs. - MaybeSetupWeakThis(ptr); - } - - // Copy constructor: makes this object a copy of ptr, and increments - // the reference count. - template - shared_ptr(const shared_ptr& ptr) - : ptr_(NULL), - control_block_(NULL) { - Initialize(ptr); - } - // Need non-templated version to prevent the compiler-generated default - shared_ptr(const shared_ptr& ptr) - : ptr_(NULL), - control_block_(NULL) { - Initialize(ptr); - } - - // Assignment operator. Replaces the existing shared_ptr with ptr. - // Increment ptr's reference count and decrement the one being replaced. - template - shared_ptr& operator=(const shared_ptr& ptr) { - if (ptr_ != ptr.ptr_) { - shared_ptr me(ptr); // will hold our previous state to be destroyed. - swap(me); - } - return *this; - } - - // Need non-templated version to prevent the compiler-generated default - shared_ptr& operator=(const shared_ptr& ptr) { - if (ptr_ != ptr.ptr_) { - shared_ptr me(ptr); // will hold our previous state to be destroyed. - swap(me); - } - return *this; - } - - // TODO(austern): Consider providing this constructor. The draft C++ standard - // (20.8.10.2.1) includes it. However, it says that this constructor throws - // a bad_weak_ptr exception when ptr is expired. Is it better to provide this - // constructor and make it do something else, like fail with a CHECK, or to - // leave this constructor out entirely? - // - // template - // shared_ptr(const weak_ptr& ptr); - - ~shared_ptr() { - if (ptr_ != NULL) { - if (!RefCountDec(&control_block_->refcount_)) { - delete ptr_; - - // weak_count_ is defined as the number of weak_ptrs that observe - // ptr_, plus 1 if refcount_ is nonzero. - if (!RefCountDec(&control_block_->weak_count_)) { - delete control_block_; - } - } - } - } - - // Replaces underlying raw pointer with the one passed in. The reference - // count is set to one (or zero if the pointer is NULL) for the pointer - // being passed in and decremented for the one being replaced. - // - // If you have a compilation error with this code, make sure you aren't - // passing NULL, nullptr, or 0 to this function. Call reset without an - // argument to reset to a null ptr. - template - void reset(Y* p) { - if (p != ptr_) { - shared_ptr tmp(p); - tmp.swap(*this); - } - } - - void reset() { - reset(static_cast(NULL)); - } - - // Exchanges the contents of this with the contents of r. This function - // supports more efficient swapping since it eliminates the need for a - // temporary shared_ptr object. - void swap(shared_ptr& r) { - using std::swap; // http://go/using-std-swap - swap(ptr_, r.ptr_); - swap(control_block_, r.control_block_); - } - - // The following function is useful for gaining access to the underlying - // pointer when a shared_ptr remains in scope so the reference-count is - // known to be > 0 (e.g. for parameter passing). - T* get() const { - return ptr_; - } - - T& operator*() const { - return *ptr_; - } - - T* operator->() const { - return ptr_; - } - - long use_count() const { - return control_block_ ? control_block_->refcount_ : 1; - } - - bool unique() const { - return use_count() == 1; - } - - private: - // If r is non-empty, initialize *this to share ownership with r, - // increasing the underlying reference count. - // If r is empty, *this remains empty. - // Requires: this is empty, namely this->ptr_ == NULL. - template - void Initialize(const shared_ptr& r) { - // This performs a static_cast on r.ptr_ to U*, which is a no-op since it - // is already a U*. So initialization here requires that r.ptr_ is - // implicitly convertible to T*. - InitializeWithStaticCast(r); - } - - // Initializes *this as described in Initialize, but additionally performs a - // static_cast from r.ptr_ (V*) to U*. - // NOTE(gfc): We'd need a more general form to support const_pointer_cast and - // dynamic_pointer_cast, but those operations are sufficiently discouraged - // that supporting static_pointer_cast is sufficient. - template - void InitializeWithStaticCast(const shared_ptr& r) { - if (r.control_block_ != NULL) { - RefCountInc(&r.control_block_->refcount_); - - ptr_ = static_cast(r.ptr_); - control_block_ = r.control_block_; - } - } - - // Helper function for the constructor that takes a raw pointer. If T - // doesn't inherit from enable_shared_from_this then we have nothing to - // do, so this function is trivial and inline. The other version is declared - // out of line, after the class definition of enable_shared_from_this. - void MaybeSetupWeakThis(enable_shared_from_this* ptr); - void MaybeSetupWeakThis(...) { } - - T* ptr_; - SharedPtrControlBlock* control_block_; - -#ifndef SWIG - template - friend class shared_ptr; - - template - friend shared_ptr static_pointer_cast(const shared_ptr& rhs); -#endif -}; - -// Matches the interface of std::swap as an aid to generic programming. -template void swap(shared_ptr& r, shared_ptr& s) { - r.swap(s); -} - -template -shared_ptr static_pointer_cast(const shared_ptr& rhs) { - shared_ptr lhs; - lhs.template InitializeWithStaticCast(rhs); - return lhs; -} - -// See comments at the top of the file for a description of why this -// class exists, and the draft C++ standard (as of July 2009 the -// latest draft is N2914) for the detailed specification. -template -class weak_ptr { - template friend class weak_ptr; - public: - typedef T element_type; - - // Create an empty (i.e. already expired) weak_ptr. - weak_ptr() : ptr_(NULL), control_block_(NULL) { } - - // Create a weak_ptr that observes the same object that ptr points - // to. Note that there is no race condition here: we know that the - // control block can't disappear while we're looking at it because - // it is owned by at least one shared_ptr, ptr. - template weak_ptr(const shared_ptr& ptr) { - CopyFrom(ptr.ptr_, ptr.control_block_); - } - - // Copy a weak_ptr. The object it points to might disappear, but we - // don't care: we're only working with the control block, and it can't - // disappear while we're looking at because it's owned by at least one - // weak_ptr, ptr. - template weak_ptr(const weak_ptr& ptr) { - CopyFrom(ptr.ptr_, ptr.control_block_); - } - - // Need non-templated version to prevent default copy constructor - weak_ptr(const weak_ptr& ptr) { - CopyFrom(ptr.ptr_, ptr.control_block_); - } - - // Destroy the weak_ptr. If no shared_ptr owns the control block, and if - // we are the last weak_ptr to own it, then it can be deleted. Note that - // weak_count_ is defined as the number of weak_ptrs sharing this control - // block, plus 1 if there are any shared_ptrs. We therefore know that it's - // safe to delete the control block when weak_count_ reaches 0, without - // having to perform any additional tests. - ~weak_ptr() { - if (control_block_ != NULL && - !RefCountDec(&control_block_->weak_count_)) { - delete control_block_; - } - } - - weak_ptr& operator=(const weak_ptr& ptr) { - if (&ptr != this) { - weak_ptr tmp(ptr); - tmp.swap(*this); - } - return *this; - } - template weak_ptr& operator=(const weak_ptr& ptr) { - weak_ptr tmp(ptr); - tmp.swap(*this); - return *this; - } - template weak_ptr& operator=(const shared_ptr& ptr) { - weak_ptr tmp(ptr); - tmp.swap(*this); - return *this; - } - - void swap(weak_ptr& ptr) { - using std::swap; // http://go/using-std-swap - swap(ptr_, ptr.ptr_); - swap(control_block_, ptr.control_block_); - } - - void reset() { - weak_ptr tmp; - tmp.swap(*this); - } - - // Return the number of shared_ptrs that own the object we are observing. - // Note that this number can be 0 (if this pointer has expired). - long use_count() const { - return control_block_ != NULL ? control_block_->refcount_ : 0; - } - - bool expired() const { return use_count() == 0; } - - // Return a shared_ptr that owns the object we are observing. If we - // have expired, the shared_ptr will be empty. We have to be careful - // about concurrency, though, since some other thread might be - // destroying the last owning shared_ptr while we're in this - // function. We want to increment the refcount only if it's nonzero - // and get the new value, and we want that whole operation to be - // atomic. - shared_ptr lock() const { - shared_ptr result; - if (control_block_ != NULL) { - Atomic32 old_refcount; - do { - old_refcount = control_block_->refcount_; - if (old_refcount == 0) - break; - } while (old_refcount != - NoBarrier_CompareAndSwap( - &control_block_->refcount_, old_refcount, - old_refcount + 1)); - if (old_refcount > 0) { - result.ptr_ = ptr_; - result.control_block_ = control_block_; - } - } - - return result; - } - - private: - void CopyFrom(T* ptr, SharedPtrControlBlock* control_block) { - ptr_ = ptr; - control_block_ = control_block; - if (control_block_ != NULL) - RefCountInc(&control_block_->weak_count_); - } - - private: - element_type* ptr_; - SharedPtrControlBlock* control_block_; -}; - -template void swap(weak_ptr& r, weak_ptr& s) { - r.swap(s); -} - -// See comments at the top of the file for a description of why this class -// exists, and section 20.8.10.5 of the draft C++ standard (as of July 2009 -// the latest draft is N2914) for the detailed specification. -template -class enable_shared_from_this { - friend class shared_ptr; - public: - // Precondition: there must be a shared_ptr that owns *this and that was - // created, directly or indirectly, from a raw pointer of type T*. (The - // latter part of the condition is technical but not quite redundant; it - // rules out some complicated uses involving inheritance hierarchies.) - shared_ptr shared_from_this() { - // Behavior is undefined if the precondition isn't satisfied; we choose - // to die with a CHECK failure. - GOOGLE_CHECK(!weak_this_.expired()) << "No shared_ptr owns this object"; - return weak_this_.lock(); - } - shared_ptr shared_from_this() const { - GOOGLE_CHECK(!weak_this_.expired()) << "No shared_ptr owns this object"; - return weak_this_.lock(); - } - - protected: - enable_shared_from_this() { } - enable_shared_from_this(const enable_shared_from_this& other) { } - enable_shared_from_this& operator=(const enable_shared_from_this& other) { - return *this; - } - ~enable_shared_from_this() { } - - private: - weak_ptr weak_this_; -}; - -// This is a helper function called by shared_ptr's constructor from a raw -// pointer. If T inherits from enable_shared_from_this, it sets up -// weak_this_ so that shared_from_this works correctly. If T does not inherit -// from weak_this we get a different overload, defined inline, which does -// nothing. -template -void shared_ptr::MaybeSetupWeakThis(enable_shared_from_this* ptr) { - if (ptr) { - GOOGLE_CHECK(ptr->weak_this_.expired()) - << "Object already owned by a shared_ptr"; - ptr->weak_this_ = *this; - } -} - -#endif // UTIL_GTL_USE_STD_SHARED_PTR - -} // internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_STUBS_SHARED_PTR_H__ diff --git a/src/google/protobuf/stubs/singleton.h b/src/google/protobuf/stubs/singleton.h deleted file mode 100644 index 9301f549b1d6f..0000000000000 --- a/src/google/protobuf/stubs/singleton.h +++ /dev/null @@ -1,68 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2014 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#ifndef GOOGLE_PROTOBUF_STUBS_SINGLETON_H__ -#define GOOGLE_PROTOBUF_STUBS_SINGLETON_H__ - -#include -#include -#include - -namespace google { -namespace protobuf { -namespace internal { -template -class Singleton { - public: - static T* get() { - GoogleOnceInit(&once_, &Singleton::Init); - return instance_; - } - static void ShutDown() { - delete instance_; - instance_ = NULL; - } - private: - static void Init() { - instance_ = new T(); - } - static ProtobufOnceType once_; - static T* instance_; -}; - -template -ProtobufOnceType Singleton::once_; - -template -T* Singleton::instance_ = NULL; -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_STUBS_SINGLETON_H__ diff --git a/src/google/protobuf/stubs/status.cc b/src/google/protobuf/stubs/status.cc index dd1bd6141a697..03b37c365b835 100644 --- a/src/google/protobuf/stubs/status.cc +++ b/src/google/protobuf/stubs/status.cc @@ -38,7 +38,7 @@ namespace google { namespace protobuf { namespace util { namespace error { -inline string CodeEnumToString(error::Code code) { +inline std::string CodeEnumToString(error::Code code) { switch (code) { case OK: return "OK"; @@ -111,7 +111,7 @@ bool Status::operator==(const Status& x) const { error_message_ == x.error_message_; } -string Status::ToString() const { +std::string Status::ToString() const { if (error_code_ == error::OK) { return "OK"; } else { @@ -124,7 +124,7 @@ string Status::ToString() const { } } -ostream& operator<<(ostream& os, const Status& x) { +std::ostream& operator<<(std::ostream& os, const Status& x) { os << x.ToString(); return os; } diff --git a/src/google/protobuf/stubs/status.h b/src/google/protobuf/stubs/status.h index 614ab9941acab..bededad541c5c 100644 --- a/src/google/protobuf/stubs/status.h +++ b/src/google/protobuf/stubs/status.h @@ -36,6 +36,8 @@ #include #include +#include + namespace google { namespace protobuf { namespace util { @@ -62,7 +64,7 @@ enum Code { }; } // namespace error -class LIBPROTOBUF_EXPORT Status { +class PROTOBUF_EXPORT Status { public: // Creates a "successful" status. Status(); @@ -88,9 +90,15 @@ class LIBPROTOBUF_EXPORT Status { int error_code() const { return error_code_; } + error::Code code() const { + return error_code_; + } StringPiece error_message() const { return error_message_; } + StringPiece message() const { + return error_message_; + } bool operator==(const Status& x) const; bool operator!=(const Status& x) const { @@ -98,19 +106,20 @@ class LIBPROTOBUF_EXPORT Status { } // Return a combination of the error code name and message. - string ToString() const; + std::string ToString() const; private: error::Code error_code_; - string error_message_; + std::string error_message_; }; // Prints a human-readable representation of 'x' to 'os'. -LIBPROTOBUF_EXPORT ostream& operator<<(ostream& os, const Status& x); - -#define EXPECT_OK(value) EXPECT_TRUE((value).ok()) +PROTOBUF_EXPORT std::ostream& operator<<(std::ostream& os, const Status& x); } // namespace util } // namespace protobuf } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_ diff --git a/src/google/protobuf/stubs/status_macros.h b/src/google/protobuf/stubs/status_macros.h index 743e79a727d02..0c64317d3ca9c 100644 --- a/src/google/protobuf/stubs/status_macros.h +++ b/src/google/protobuf/stubs/status_macros.h @@ -46,11 +46,11 @@ namespace util { // // Example: // RETURN_IF_ERROR(DoThings(4)); -#define RETURN_IF_ERROR(expr) \ - do { \ +#define RETURN_IF_ERROR(expr) \ + do { \ /* Using _status below to avoid capture problems if expr is "status". */ \ - const ::google::protobuf::util::Status _status = (expr); \ - if (GOOGLE_PREDICT_FALSE(!_status.ok())) return _status; \ + const PROTOBUF_NAMESPACE_ID::util::Status _status = (expr); \ + if (PROTOBUF_PREDICT_FALSE(!_status.ok())) return _status; \ } while (0) // Internal helper for concatenating macro values. @@ -67,7 +67,7 @@ Status DoAssignOrReturn(T& lhs, StatusOr result) { #define ASSIGN_OR_RETURN_IMPL(status, lhs, rexpr) \ Status status = DoAssignOrReturn(lhs, (rexpr)); \ - if (GOOGLE_PREDICT_FALSE(!status.ok())) return status; + if (PROTOBUF_PREDICT_FALSE(!status.ok())) return status; // Executes an expression that returns a util::StatusOr, extracting its value // into the variable defined by lhs (or returning on error). diff --git a/src/google/protobuf/stubs/status_test.cc b/src/google/protobuf/stubs/status_test.cc index c70c33c47437b..8f4398c9c9888 100644 --- a/src/google/protobuf/stubs/status_test.cc +++ b/src/google/protobuf/stubs/status_test.cc @@ -40,13 +40,17 @@ namespace { TEST(Status, Empty) { util::Status status; EXPECT_EQ(util::error::OK, util::Status::OK.error_code()); + EXPECT_EQ(util::error::OK, util::Status::OK.code()); EXPECT_EQ("OK", util::Status::OK.ToString()); } TEST(Status, GenericCodes) { EXPECT_EQ(util::error::OK, util::Status::OK.error_code()); + EXPECT_EQ(util::error::OK, util::Status::OK.code()); EXPECT_EQ(util::error::CANCELLED, util::Status::CANCELLED.error_code()); + EXPECT_EQ(util::error::CANCELLED, util::Status::CANCELLED.code()); EXPECT_EQ(util::error::UNKNOWN, util::Status::UNKNOWN.error_code()); + EXPECT_EQ(util::error::UNKNOWN, util::Status::UNKNOWN.code()); } TEST(Status, ConstructorZero) { @@ -66,14 +70,17 @@ TEST(Status, ErrorMessage) { util::Status status(util::error::INVALID_ARGUMENT, ""); EXPECT_FALSE(status.ok()); EXPECT_EQ("", status.error_message().ToString()); + EXPECT_EQ("", status.message().ToString()); EXPECT_EQ("INVALID_ARGUMENT", status.ToString()); status = util::Status(util::error::INVALID_ARGUMENT, "msg"); EXPECT_FALSE(status.ok()); EXPECT_EQ("msg", status.error_message().ToString()); + EXPECT_EQ("msg", status.message().ToString()); EXPECT_EQ("INVALID_ARGUMENT:msg", status.ToString()); status = util::Status(util::error::OK, "msg"); EXPECT_TRUE(status.ok()); EXPECT_EQ("", status.error_message().ToString()); + EXPECT_EQ("", status.message().ToString()); EXPECT_EQ("OK", status.ToString()); } @@ -94,7 +101,7 @@ TEST(Status, AssignEmpty) { util::Status a(util::error::UNKNOWN, "message"); util::Status b; a = b; - ASSERT_EQ(string("OK"), a.ToString()); + ASSERT_EQ(std::string("OK"), a.ToString()); ASSERT_TRUE(b.ok()); ASSERT_TRUE(a.ok()); } diff --git a/src/google/protobuf/stubs/statusor.cc b/src/google/protobuf/stubs/statusor.cc index 48d1402ae0036..c744b8d23706f 100644 --- a/src/google/protobuf/stubs/statusor.cc +++ b/src/google/protobuf/stubs/statusor.cc @@ -30,6 +30,8 @@ #include +#include + namespace google { namespace protobuf { namespace util { diff --git a/src/google/protobuf/stubs/statusor.h b/src/google/protobuf/stubs/statusor.h index 29f869ad5e8d5..c02e89a9f0f72 100644 --- a/src/google/protobuf/stubs/statusor.h +++ b/src/google/protobuf/stubs/statusor.h @@ -33,7 +33,7 @@ // usable value, or an error Status explaining why such a value is // not present. To this end, StatusOr does not allow its Status // value to be Status::OK. Further, StatusOr does not allow the -// contained pointer to be NULL. +// contained pointer to be nullptr. // // The primary use-case for StatusOr is as the return value of a // function which may fail. @@ -89,6 +89,8 @@ #include +#include + namespace google { namespace protobuf { namespace util { @@ -114,15 +116,15 @@ class StatusOr { StatusOr(const Status& status); // NOLINT // Construct a new StatusOr with the given value. If T is a plain pointer, - // value must not be NULL. After calling this constructor, calls to + // value must not be nullptr. After calling this constructor, calls to // ValueOrDie() will succeed, and calls to status() will return OK. // // NOTE: Not explicit - we want to use StatusOr as a return type // so it is convenient and sensible to be able to do 'return T()' // when when the return type is StatusOr. // - // REQUIRES: if T is a plain pointer, value != NULL. This requirement is - // DCHECKed. In optimized builds, passing a NULL pointer here will have + // REQUIRES: if T is a plain pointer, value != nullptr. This requirement is + // DCHECKed. In optimized builds, passing a null pointer here will have // the effect of passing PosixErrorSpace::EINVAL as a fallback. StatusOr(const T& value); // NOLINT @@ -151,6 +153,7 @@ class StatusOr { // If you need to initialize a T object from the stored value, // ConsumeValueOrDie() may be more efficient. const T& ValueOrDie() const; + const T& value () const; private: Status status_; @@ -162,7 +165,7 @@ class StatusOr { namespace internal { -class LIBPROTOBUF_EXPORT StatusOrHelper { +class PROTOBUF_EXPORT StatusOrHelper { public: // Move type-agnostic error handling to the .cc. static void Crash(const util::Status& status); @@ -174,13 +177,13 @@ class LIBPROTOBUF_EXPORT StatusOrHelper { template struct StatusOrHelper::Specialize { - // For non-pointer T, a reference can never be NULL. + // For non-pointer T, a reference can never be nullptr. static inline bool IsValueNull(const T& t) { return false; } }; template struct StatusOrHelper::Specialize { - static inline bool IsValueNull(const T* t) { return t == NULL; } + static inline bool IsValueNull(const T* t) { return t == nullptr; } }; } // namespace internal @@ -202,7 +205,7 @@ inline StatusOr::StatusOr(const Status& status) { template inline StatusOr::StatusOr(const T& value) { if (internal::StatusOrHelper::Specialize::IsValueNull(value)) { - status_ = Status(error::INTERNAL, "NULL is not a vaild argument."); + status_ = Status(error::INTERNAL, "nullptr is not a valid argument."); } else { status_ = Status::OK; value_ = value; @@ -252,8 +255,18 @@ inline const T& StatusOr::ValueOrDie() const { } return value_; } + +template +inline const T& StatusOr::value() const { + if (!status_.ok()) { + internal::StatusOrHelper::Crash(status_); + } + return value_; +} } // namespace util } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ diff --git a/src/google/protobuf/stubs/stl_util.h b/src/google/protobuf/stubs/stl_util.h index 9e4c82a4c3be3..d01f9ec944f62 100644 --- a/src/google/protobuf/stubs/stl_util.h +++ b/src/google/protobuf/stubs/stl_util.h @@ -38,33 +38,13 @@ namespace google { namespace protobuf { -// STLDeleteContainerPointers() -// For a range within a container of pointers, calls delete -// (non-array version) on these pointers. -// NOTE: for these three functions, we could just implement a DeleteObject -// functor and then call for_each() on the range and functor, but this -// requires us to pull in all of algorithm.h, which seems expensive. -// For hash_[multi]set, it is important that this deletes behind the iterator -// because the hash_set may call the hash function on the iterator when it is -// advanced, which could result in the hash function trying to deference a -// stale pointer. -template -void STLDeleteContainerPointers(ForwardIterator begin, - ForwardIterator end) { - while (begin != end) { - ForwardIterator temp = begin; - ++begin; - delete *temp; - } -} - // Inside Google, this function implements a horrible, disgusting hack in which // we reach into the string's private implementation and resize it without // initializing the new bytes. In some cases doing this can significantly // improve performance. However, since it's totally non-portable it has no // place in open source code. Feel free to fill this function in with your // own disgusting hack if you want the perf boost. -inline void STLStringResizeUninitialized(string* s, size_t new_size) { +inline void STLStringResizeUninitialized(std::string* s, size_t new_size) { s->resize(new_size); } @@ -80,39 +60,9 @@ inline void STLStringResizeUninitialized(string* s, size_t new_size) { // (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530) // proposes this as the method. According to Matt Austern, this should // already work on all current implementations. -inline char* string_as_array(string* str) { +inline char* string_as_array(std::string* str) { // DO NOT USE const_cast(str->data())! See the unittest for why. - return str->empty() ? NULL : &*str->begin(); -} - -// STLDeleteElements() deletes all the elements in an STL container and clears -// the container. This function is suitable for use with a vector, set, -// hash_set, or any other STL container which defines sensible begin(), end(), -// and clear() methods. -// -// If container is NULL, this function is a no-op. -// -// As an alternative to calling STLDeleteElements() directly, consider -// ElementDeleter (defined below), which ensures that your container's elements -// are deleted when the ElementDeleter goes out of scope. -template -void STLDeleteElements(T *container) { - if (!container) return; - STLDeleteContainerPointers(container->begin(), container->end()); - container->clear(); -} - -// Given an STL container consisting of (key, value) pairs, STLDeleteValues -// deletes all the "value" components and clears the container. Does nothing -// in the case it's given a NULL pointer. - -template -void STLDeleteValues(T *v) { - if (!v) return; - for (typename T::iterator i = v->begin(); i != v->end(); ++i) { - delete i->second; - } - v->clear(); + return str->empty() ? nullptr : &*str->begin(); } } // namespace protobuf diff --git a/src/google/protobuf/stubs/stringpiece.cc b/src/google/protobuf/stubs/stringpiece.cc index 989474b74704d..353c78cad19b1 100644 --- a/src/google/protobuf/stubs/stringpiece.cc +++ b/src/google/protobuf/stubs/stringpiece.cc @@ -35,6 +35,8 @@ #include #include +#include + namespace google { namespace protobuf { std::ostream& operator<<(std::ostream& o, StringPiece piece) { @@ -62,11 +64,11 @@ StringPiece::StringPiece(StringPiece x, GOOGLE_DCHECK_GE(len, 0); } -void StringPiece::CopyToString(string* target) const { +void StringPiece::CopyToString(std::string* target) const { target->assign(ptr_, length_); } -void StringPiece::AppendToString(string* target) const { +void StringPiece::AppendToString(std::string* target) const { target->append(ptr_, length_); } @@ -115,7 +117,7 @@ stringpiece_ssize_type StringPiece::find(char c, size_type pos) const { } const char* result = static_cast( memchr(ptr_ + pos, c, length_ - pos)); - return result != NULL ? result - ptr_ : npos; + return result != nullptr ? result - ptr_ : npos; } stringpiece_ssize_type StringPiece::rfind(StringPiece s, size_type pos) const { diff --git a/src/google/protobuf/stubs/stringpiece.h b/src/google/protobuf/stubs/stringpiece.h index 563ff75dcf446..fbcb20afc4180 100644 --- a/src/google/protobuf/stubs/stringpiece.h +++ b/src/google/protobuf/stubs/stringpiece.h @@ -76,30 +76,30 @@ // // There are several ways to create a null StringPiece: // StringPiece() -// StringPiece(NULL) -// StringPiece(NULL, 0) -// For all of the above, sp.data() == NULL, sp.length() == 0, +// StringPiece(nullptr) +// StringPiece(nullptr, 0) +// For all of the above, sp.data() == nullptr, sp.length() == 0, // and sp.empty() == true. Also, if you create a StringPiece with -// a non-NULL pointer then sp.data() != NULL. Once created, -// sp.data() will stay either NULL or not-NULL, except if you call +// a non-null pointer then sp.data() != nullptr. Once created, +// sp.data() will stay either nullptr or not-nullptr, except if you call // sp.clear() or sp.set(). // -// Thus, you can use StringPiece(NULL) to signal an out-of-band value +// Thus, you can use StringPiece(nullptr) to signal an out-of-band value // that is different from other StringPiece values. This is similar -// to the way that const char* p1 = NULL; is different from +// to the way that const char* p1 = nullptr; is different from // const char* p2 = "";. // // There are many ways to create an empty StringPiece: // StringPiece() -// StringPiece(NULL) -// StringPiece(NULL, 0) +// StringPiece(nullptr) +// StringPiece(nullptr, 0) // StringPiece("") // StringPiece("", 0) // StringPiece("abcdef", 0) // StringPiece("abcdef"+6, 0) // For all of the above, sp.length() will be 0 and sp.empty() will be true. -// For some empty StringPiece values, sp.data() will be NULL. -// For some empty StringPiece values, sp.data() will not be NULL. +// For some empty StringPiece values, sp.data() will be nullptr. +// For some empty StringPiece values, sp.data() will not be nullptr. // // Be careful not to confuse: null StringPiece and empty StringPiece. // The set of empty StringPieces properly includes the set of null StringPieces. @@ -109,20 +109,20 @@ // All empty StringPiece values compare equal to each other. // Even a null StringPieces compares equal to a non-null empty StringPiece: // StringPiece() == StringPiece("", 0) -// StringPiece(NULL) == StringPiece("abc", 0) -// StringPiece(NULL, 0) == StringPiece("abcdef"+6, 0) +// StringPiece(nullptr) == StringPiece("abc", 0) +// StringPiece(nullptr, 0) == StringPiece("abcdef"+6, 0) // // Look carefully at this example: -// StringPiece("") == NULL +// StringPiece("") == nullptr // True or false? TRUE, because StringPiece::operator== converts -// the right-hand side from NULL to StringPiece(NULL), +// the right-hand side from nullptr to StringPiece(nullptr), // and then compares two zero-length spans of characters. // However, we are working to make this example produce a compile error. // // Suppose you want to write: -// bool TestWhat?(StringPiece sp) { return sp == NULL; } // BAD +// bool TestWhat?(StringPiece sp) { return sp == nullptr; } // BAD // Do not do that. Write one of these instead: -// bool TestNull(StringPiece sp) { return sp.data() == NULL; } +// bool TestNull(StringPiece sp) { return sp.data() == nullptr; } // bool TestEmpty(StringPiece sp) { return sp.empty(); } // The intent of TestWhat? is unclear. Did you mean TestNull or TestEmpty? // Right now, TestWhat? behaves likes TestEmpty. @@ -148,9 +148,10 @@ #include #include -#include #include +#include + namespace google { namespace protobuf { // StringPiece has *two* size types. @@ -163,7 +164,7 @@ namespace protobuf { // is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64 // future changes intended: http://go/64BitStringPiece // -typedef string::difference_type stringpiece_ssize_type; +typedef std::string::difference_type stringpiece_ssize_type; // STRINGPIECE_CHECK_SIZE protects us from 32-bit overflows. // TODO(mec): delete this after stringpiece_ssize_type goes 64 bit. @@ -175,7 +176,7 @@ typedef string::difference_type stringpiece_ssize_type; #define STRINGPIECE_CHECK_SIZE 0 #endif -class LIBPROTOBUF_EXPORT StringPiece { +class PROTOBUF_EXPORT StringPiece { private: const char* ptr_; stringpiece_ssize_type length_; @@ -207,11 +208,11 @@ class LIBPROTOBUF_EXPORT StringPiece { // // Style guide exception granted: // http://goto/style-guide-exception-20978288 - StringPiece() : ptr_(NULL), length_(0) {} + StringPiece() : ptr_(nullptr), length_(0) {} StringPiece(const char* str) // NOLINT(runtime/explicit) : ptr_(str), length_(0) { - if (str != NULL) { + if (str != nullptr) { length_ = CheckedSsizeTFromSizeT(strlen(str)); } } @@ -248,7 +249,7 @@ class LIBPROTOBUF_EXPORT StringPiece { bool empty() const { return length_ == 0; } void clear() { - ptr_ = NULL; + ptr_ = nullptr; length_ = 0; } @@ -260,7 +261,7 @@ class LIBPROTOBUF_EXPORT StringPiece { void set(const char* str) { ptr_ = str; - if (str != NULL) + if (str != nullptr) length_ = CheckedSsizeTFromSizeT(strlen(str)); else length_ = 0; @@ -300,25 +301,21 @@ class LIBPROTOBUF_EXPORT StringPiece { return 0; } - string as_string() const { - return ToString(); - } + std::string as_string() const { return ToString(); } // We also define ToString() here, since many other string-like // interfaces name the routine that converts to a C++ string // "ToString", and it's confusing to have the method that does that // for a StringPiece be called "as_string()". We also leave the // "as_string()" method defined here for existing code. - string ToString() const { - if (ptr_ == NULL) return string(); - return string(data(), static_cast(size())); + std::string ToString() const { + if (ptr_ == nullptr) return ""; + return std::string(data(), static_cast(size())); } - operator string() const { - return ToString(); - } + explicit operator std::string() const { return ToString(); } - void CopyToString(string* target) const; - void AppendToString(string* target) const; + void CopyToString(std::string* target) const; + void AppendToString(std::string* target) const; bool starts_with(StringPiece x) const { return (length_ >= x.length_) && @@ -463,6 +460,9 @@ struct StringPiecePod { std::string ToString() const { return std::string(data_, static_cast(size_)); } + + explicit operator std::string() const { return ToString(); } + private: const char* data_; stringpiece_ssize_type size_; @@ -476,7 +476,7 @@ GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START template<> struct hash { size_t operator()(const StringPiece& s) const { size_t result = 0; - for (const char *str = s.data(), *end = str + s.size(); str < end; str++) { + for (const char *str = s.data(), *end = str + s.size(); str < end; str++) { result = 5 * result + static_cast(*str); } return result; @@ -484,4 +484,6 @@ template<> struct hash { }; GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END +#include + #endif // STRINGS_STRINGPIECE_H_ diff --git a/src/google/protobuf/stubs/stringpiece_unittest.cc b/src/google/protobuf/stubs/stringpiece_unittest.cc index a6a8759547a4a..846e1aed3d366 100644 --- a/src/google/protobuf/stubs/stringpiece_unittest.cc +++ b/src/google/protobuf/stubs/stringpiece_unittest.cc @@ -46,7 +46,7 @@ TEST(StringPiece, Ctor) { { // Null. StringPiece s10; - EXPECT_TRUE(s10.data() == NULL); + EXPECT_TRUE(s10.data() == nullptr); EXPECT_EQ(0, s10.length()); } @@ -87,7 +87,7 @@ TEST(StringPiece, Ctor) { #if defined(HAS_GLOBAL_STRING) { // ::string - string bonjour = "bonjour"; + std::string bonjour = "bonjour"; StringPiece s40(bonjour); EXPECT_TRUE(s40.data() == bonjour.data()); EXPECT_EQ(7, s40.length()); @@ -100,9 +100,9 @@ TEST(StringPiece, Ctor) { } TEST(StringPiece, STLComparator) { - string s1("foo"); - string s2("bar"); - string s3("baz"); + std::string s1("foo"); + std::string s2("bar"); + std::string s3("baz"); StringPiece p1(s1); StringPiece p2(s2); @@ -148,8 +148,8 @@ TEST(StringPiece, ComparisonOperators) { EXPECT_EQ(result, StringPiece((x)).compare(StringPiece((y))) op 0) COMPARE(true, ==, "", ""); - COMPARE(true, ==, "", NULL); - COMPARE(true, ==, NULL, ""); + COMPARE(true, ==, "", nullptr); + COMPARE(true, ==, nullptr, ""); COMPARE(true, ==, "a", "a"); COMPARE(true, ==, "aa", "aa"); COMPARE(false, ==, "a", ""); @@ -207,13 +207,13 @@ TEST(StringPiece, ComparisonOperators) { COMPARE(true, >, "b", "aa"); COMPARE(true, >, "bb", "aa"); - string x; + std::string x; for (int i = 0; i < 256; i++) { x += 'a'; - string y = x; + std::string y = x; COMPARE(true, ==, x, y); for (int j = 0; j < i; j++) { - string z = x; + std::string z = x; z[j] = 'b'; // Differs in position 'j' COMPARE(false, ==, x, z); COMPARE(true, <, x, z); @@ -240,7 +240,7 @@ TEST(StringPiece, STL1) { const StringPiece c("xyz"); const StringPiece d("foobar"); const StringPiece e; - string temp("123"); + std::string temp("123"); temp += '\0'; temp += "456"; const StringPiece f(temp); @@ -253,7 +253,7 @@ TEST(StringPiece, STL1) { EXPECT_EQ(*d.data(), 'f'); EXPECT_EQ(d.data()[5], 'r'); - EXPECT_TRUE(e.data() == NULL); + EXPECT_TRUE(e.data() == nullptr); EXPECT_EQ(*a.begin(), 'a'); EXPECT_EQ(*(b.begin() + 2), 'c'); @@ -312,10 +312,10 @@ TEST(StringPiece, STL2) { d.clear(); EXPECT_EQ(d.size(), 0); EXPECT_TRUE(d.empty()); - EXPECT_TRUE(d.data() == NULL); + EXPECT_TRUE(d.data() == nullptr); EXPECT_TRUE(d.begin() == d.end()); - EXPECT_EQ(StringPiece::npos, string::npos); + EXPECT_EQ(StringPiece::npos, std::string::npos); EXPECT_EQ(a.find(b), 0); EXPECT_EQ(a.find(b, 1), StringPiece::npos); @@ -336,15 +336,15 @@ TEST(StringPiece, STL2) { EXPECT_EQ(d.find(b, 4), StringPiece::npos); EXPECT_EQ(e.find(b, 7), StringPiece::npos); - size_t empty_search_pos = string().find(string()); + size_t empty_search_pos = std::string().find(std::string()); EXPECT_EQ(d.find(d), empty_search_pos); EXPECT_EQ(d.find(e), empty_search_pos); EXPECT_EQ(e.find(d), empty_search_pos); EXPECT_EQ(e.find(e), empty_search_pos); - EXPECT_EQ(d.find(d, 4), string().find(string(), 4)); - EXPECT_EQ(d.find(e, 4), string().find(string(), 4)); - EXPECT_EQ(e.find(d, 4), string().find(string(), 4)); - EXPECT_EQ(e.find(e, 4), string().find(string(), 4)); + EXPECT_EQ(d.find(d, 4), std::string().find(std::string(), 4)); + EXPECT_EQ(d.find(e, 4), std::string().find(std::string(), 4)); + EXPECT_EQ(e.find(d, 4), std::string().find(std::string(), 4)); + EXPECT_EQ(e.find(e, 4), std::string().find(std::string(), 4)); EXPECT_EQ(a.find('a'), 0); EXPECT_EQ(a.find('c'), 2); @@ -376,8 +376,8 @@ TEST(StringPiece, STL2) { EXPECT_EQ(a.rfind(c, 0), StringPiece::npos); EXPECT_EQ(b.rfind(c), StringPiece::npos); EXPECT_EQ(b.rfind(c, 0), StringPiece::npos); - EXPECT_EQ(a.rfind(d), a.as_string().rfind(string())); - EXPECT_EQ(a.rfind(e), a.as_string().rfind(string())); + EXPECT_EQ(a.rfind(d), a.as_string().rfind(std::string())); + EXPECT_EQ(a.rfind(e), a.as_string().rfind(std::string())); EXPECT_EQ(a.rfind(d, 12), 12); EXPECT_EQ(a.rfind(e, 17), 17); EXPECT_EQ(a.rfind(g), StringPiece::npos); @@ -386,14 +386,14 @@ TEST(StringPiece, STL2) { EXPECT_EQ(d.rfind(b, 4), StringPiece::npos); EXPECT_EQ(e.rfind(b, 7), StringPiece::npos); // empty string nonsense - EXPECT_EQ(d.rfind(d, 4), string().rfind(string())); - EXPECT_EQ(e.rfind(d, 7), string().rfind(string())); - EXPECT_EQ(d.rfind(e, 4), string().rfind(string())); - EXPECT_EQ(e.rfind(e, 7), string().rfind(string())); - EXPECT_EQ(d.rfind(d), string().rfind(string())); - EXPECT_EQ(e.rfind(d), string().rfind(string())); - EXPECT_EQ(d.rfind(e), string().rfind(string())); - EXPECT_EQ(e.rfind(e), string().rfind(string())); + EXPECT_EQ(d.rfind(d, 4), std::string().rfind(std::string())); + EXPECT_EQ(e.rfind(d, 7), std::string().rfind(std::string())); + EXPECT_EQ(d.rfind(e, 4), std::string().rfind(std::string())); + EXPECT_EQ(e.rfind(e, 7), std::string().rfind(std::string())); + EXPECT_EQ(d.rfind(d), std::string().rfind(std::string())); + EXPECT_EQ(e.rfind(d), std::string().rfind(std::string())); + EXPECT_EQ(d.rfind(e), std::string().rfind(std::string())); + EXPECT_EQ(e.rfind(e), std::string().rfind(std::string())); EXPECT_EQ(g.rfind('o'), 8); EXPECT_EQ(g.rfind('q'), StringPiece::npos); @@ -566,7 +566,7 @@ TEST(StringPiece, STL2) { // empty string nonsense EXPECT_EQ(StringPiece(d, 0, 99), e); // Verify that they work taking an actual string, not just a StringPiece. - string a2 = a.as_string(); + std::string a2 = a.as_string(); EXPECT_EQ(StringPiece(a2, 0, 3), b); EXPECT_EQ(StringPiece(a2, 23), c); EXPECT_EQ(StringPiece(a2, 23, 3), c); @@ -577,12 +577,12 @@ TEST(StringPiece, STL2) { TEST(StringPiece, Custom) { StringPiece a("foobar"); - string s1("123"); + std::string s1("123"); s1 += '\0'; s1 += "456"; StringPiece b(s1); StringPiece e; - string s2; + std::string s2; // CopyToString a.CopyToString(&s2); @@ -666,16 +666,16 @@ TEST(StringPiece, Custom) { EXPECT_NE(c, a); // as_string - string s3(a.as_string().c_str(), 7); + std::string s3(a.as_string().c_str(), 7); EXPECT_EQ(c, s3); - string s4(e.as_string()); + std::string s4(e.as_string()); EXPECT_TRUE(s4.empty()); // ToString { - string s5(a.ToString().c_str(), 7); + std::string s5(a.ToString().c_str(), 7); EXPECT_EQ(c, s5); - string s6(e.ToString()); + std::string s6(e.ToString()); EXPECT_TRUE(s6.empty()); } @@ -707,17 +707,17 @@ TEST(StringPiece, Contains) { EXPECT_TRUE(!a.contains(d)); } -TEST(StringPiece, NULLInput) { +TEST(StringPiece, NullInput) { // we used to crash here, but now we don't. - StringPiece s(NULL); - EXPECT_EQ(s.data(), (const char*)NULL); + StringPiece s(nullptr); + EXPECT_EQ(s.data(), (const char*)nullptr); EXPECT_EQ(s.size(), 0); - s.set(NULL); - EXPECT_EQ(s.data(), (const char*)NULL); + s.set(nullptr); + EXPECT_EQ(s.data(), (const char*)nullptr); EXPECT_EQ(s.size(), 0); - // .ToString() on a StringPiece with NULL should produce the empty string. + // .ToString() on a StringPiece with nullptr should produce the empty string. EXPECT_EQ("", s.ToString()); EXPECT_EQ("", s.as_string()); } @@ -747,12 +747,12 @@ TEST(StringPiece, Comparisons2) { } TEST(ComparisonOpsTest, StringCompareNotAmbiguous) { - EXPECT_EQ("hello", string("hello")); - EXPECT_LT("hello", string("world")); + EXPECT_EQ("hello", std::string("hello")); + EXPECT_LT("hello", std::string("world")); } TEST(ComparisonOpsTest, HeterogenousStringPieceEquals) { - EXPECT_EQ(StringPiece("hello"), string("hello")); + EXPECT_EQ(StringPiece("hello"), std::string("hello")); EXPECT_EQ("hello", StringPiece("hello")); } diff --git a/src/google/protobuf/stubs/stringprintf.cc b/src/google/protobuf/stubs/stringprintf.cc index 83fdfe454e903..2603164936473 100644 --- a/src/google/protobuf/stubs/stringprintf.cc +++ b/src/google/protobuf/stubs/stringprintf.cc @@ -36,7 +36,9 @@ #include // For va_list and related operations #include // MSVC requires this for _vsnprintf #include + #include +#include namespace google { namespace protobuf { @@ -52,7 +54,7 @@ enum { IS_COMPILER_MSVC = 1 }; enum { IS_COMPILER_MSVC = 0 }; #endif -void StringAppendV(string* dst, const char* format, va_list ap) { +void StringAppendV(std::string* dst, const char* format, va_list ap) { // First try with a small fixed size buffer static const int kSpaceLength = 1024; char space[kSpaceLength]; @@ -76,7 +78,7 @@ void StringAppendV(string* dst, const char* format, va_list ap) { // Error or MSVC running out of space. MSVC 8.0 and higher // can be asked about space needed with the special idiom below: va_copy(backup_ap, ap); - result = vsnprintf(NULL, 0, format, backup_ap); + result = vsnprintf(nullptr, 0, format, backup_ap); va_end(backup_ap); } @@ -103,17 +105,16 @@ void StringAppendV(string* dst, const char* format, va_list ap) { delete[] buf; } - -string StringPrintf(const char* format, ...) { +std::string StringPrintf(const char* format, ...) { va_list ap; va_start(ap, format); - string result; + std::string result; StringAppendV(&result, format, ap); va_end(ap); return result; } -const string& SStringPrintf(string* dst, const char* format, ...) { +const std::string& SStringPrintf(std::string* dst, const char* format, ...) { va_list ap; va_start(ap, format); dst->clear(); @@ -122,7 +123,7 @@ const string& SStringPrintf(string* dst, const char* format, ...) { return *dst; } -void StringAppendF(string* dst, const char* format, ...) { +void StringAppendF(std::string* dst, const char* format, ...) { va_list ap; va_start(ap, format); StringAppendV(dst, format, ap); @@ -137,7 +138,8 @@ const int kStringPrintfVectorMaxArgs = 32; // and we can fix the problem or protect against an attack. static const char string_printf_empty_block[256] = { '\0' }; -string StringPrintfVector(const char* format, const vector& v) { +std::string StringPrintfVector(const char* format, + const std::vector& v) { GOOGLE_CHECK_LE(v.size(), kStringPrintfVectorMaxArgs) << "StringPrintfVector currently only supports up to " << kStringPrintfVectorMaxArgs << " arguments. " diff --git a/src/google/protobuf/stubs/stringprintf.h b/src/google/protobuf/stubs/stringprintf.h index ab1ab558329e4..e3858be130122 100644 --- a/src/google/protobuf/stubs/stringprintf.h +++ b/src/google/protobuf/stubs/stringprintf.h @@ -46,31 +46,40 @@ #include +#include + namespace google { namespace protobuf { // Return a C++ string -LIBPROTOBUF_EXPORT extern string StringPrintf(const char* format, ...); +PROTOBUF_EXPORT extern std::string StringPrintf(const char* format, ...); // Store result into a supplied string and return it -LIBPROTOBUF_EXPORT extern const string& SStringPrintf(string* dst, const char* format, ...); +PROTOBUF_EXPORT extern const std::string& SStringPrintf(std::string* dst, + const char* format, + ...); // Append result to a supplied string -LIBPROTOBUF_EXPORT extern void StringAppendF(string* dst, const char* format, ...); +PROTOBUF_EXPORT extern void StringAppendF(std::string* dst, const char* format, + ...); // Lower-level routine that takes a va_list and appends to a specified // string. All other routines are just convenience wrappers around it. -LIBPROTOBUF_EXPORT extern void StringAppendV(string* dst, const char* format, va_list ap); +PROTOBUF_EXPORT extern void StringAppendV(std::string* dst, const char* format, + va_list ap); // The max arguments supported by StringPrintfVector -LIBPROTOBUF_EXPORT extern const int kStringPrintfVectorMaxArgs; +PROTOBUF_EXPORT extern const int kStringPrintfVectorMaxArgs; // You can use this version when all your arguments are strings, but // you don't know how many arguments you'll have at compile time. // StringPrintfVector will LOG(FATAL) if v.size() > kStringPrintfVectorMaxArgs -LIBPROTOBUF_EXPORT extern string StringPrintfVector(const char* format, const vector& v); +PROTOBUF_EXPORT extern std::string StringPrintfVector( + const char* format, const std::vector& v); } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H diff --git a/src/google/protobuf/stubs/stringprintf_unittest.cc b/src/google/protobuf/stubs/stringprintf_unittest.cc index 15895e596cdc4..37172a9d9702a 100644 --- a/src/google/protobuf/stubs/stringprintf_unittest.cc +++ b/src/google/protobuf/stubs/stringprintf_unittest.cc @@ -49,7 +49,7 @@ TEST(StringPrintfTest, Empty) { // so we do not allow them in google3. EXPECT_EQ("", StringPrintf("")); #endif - EXPECT_EQ("", StringPrintf("%s", string().c_str())); + EXPECT_EQ("", StringPrintf("%s", std::string().c_str())); EXPECT_EQ("", StringPrintf("%s", "")); } @@ -61,26 +61,26 @@ TEST(StringPrintfTest, Misc) { } TEST(StringAppendFTest, Empty) { - string value("Hello"); + std::string value("Hello"); const char* empty = ""; StringAppendF(&value, "%s", empty); EXPECT_EQ("Hello", value); } TEST(StringAppendFTest, EmptyString) { - string value("Hello"); + std::string value("Hello"); StringAppendF(&value, "%s", ""); EXPECT_EQ("Hello", value); } TEST(StringAppendFTest, String) { - string value("Hello"); + std::string value("Hello"); StringAppendF(&value, " %s", "World"); EXPECT_EQ("Hello World", value); } TEST(StringAppendFTest, Int) { - string value("Hello"); + std::string value("Hello"); StringAppendF(&value, " %d", 123); EXPECT_EQ("Hello 123", value); } @@ -91,12 +91,12 @@ TEST(StringPrintfTest, Multibyte) { // out of memory while trying to determine destination buffer size. // see b/4194543. - char* old_locale = setlocale(LC_CTYPE, NULL); + char* old_locale = setlocale(LC_CTYPE, nullptr); // Push locale with multibyte mode setlocale(LC_CTYPE, "en_US.utf8"); const char kInvalidCodePoint[] = "\375\067s"; - string value = StringPrintf("%.*s", 3, kInvalidCodePoint); + std::string value = StringPrintf("%.*s", 3, kInvalidCodePoint); // In some versions of glibc (e.g. eglibc-2.11.1, aka GRTEv2), snprintf // returns error given an invalid codepoint. Other versions @@ -120,9 +120,9 @@ TEST(StringPrintfTest, Multibyte) { TEST(StringPrintfTest, NoMultibyte) { // No multibyte handling, but the string contains funny chars. - char* old_locale = setlocale(LC_CTYPE, NULL); + char* old_locale = setlocale(LC_CTYPE, nullptr); setlocale(LC_CTYPE, "POSIX"); - string value = StringPrintf("%.*s", 3, "\375\067s"); + std::string value = StringPrintf("%.*s", 3, "\375\067s"); setlocale(LC_CTYPE, old_locale); EXPECT_EQ("\375\067s", value); } @@ -132,7 +132,7 @@ TEST(StringPrintfTest, DontOverwriteErrno) { // something significantly larger than what people are normally // printing in their badly written PLOG() statements. errno = ECHILD; - string value = StringPrintf("Hello, %s!", "World"); + std::string value = StringPrintf("Hello, %s!", "World"); EXPECT_EQ(ECHILD, errno); } @@ -142,7 +142,7 @@ TEST(StringPrintfTest, LargeBuf) { char* buf = new char[n+1]; memset(buf, ' ', n); buf[n] = 0; - string value = StringPrintf("%s", buf); + std::string value = StringPrintf("%s", buf); EXPECT_EQ(buf, value); delete[] buf; } diff --git a/src/google/protobuf/stubs/structurally_valid.cc b/src/google/protobuf/stubs/structurally_valid.cc index d79a6ee45007c..9a476c3b4ca58 100644 --- a/src/google/protobuf/stubs/structurally_valid.cc +++ b/src/google/protobuf/stubs/structurally_valid.cc @@ -1,4 +1,33 @@ -// Copyright 2005-2008 Google Inc. All Rights Reserved. +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // Author: jrm@google.com (Jim Meehan) #include @@ -366,7 +395,7 @@ int UTF8GenericScan(const UTF8ScanObj* st, const uint8* isrc = reinterpret_cast(str); const uint8* src = isrc; const uint8* srclimit = isrc + str_length; - const uint8* srclimit8 = srclimit - 7; + const uint8* srclimit8 = str_length < 7 ? isrc : srclimit - 7; const uint8* Tbl_0 = &st->state_table[st->state0]; DoAgain: @@ -427,8 +456,7 @@ int UTF8GenericScan(const UTF8ScanObj* st, } //---------------------------- - - // Exit posibilities: + // Exit possibilities: // Some exit code, !state0, back up over last char // Some exit code, state0, back up one byte exactly // source consumed, !state0, back up over partial char @@ -475,7 +503,7 @@ int UTF8GenericScanFastAscii(const UTF8ScanObj* st, const uint8* isrc = reinterpret_cast(str); const uint8* src = isrc; const uint8* srclimit = isrc + str_length; - const uint8* srclimit8 = srclimit - 7; + const uint8* srclimit8 = str_length < 7 ? isrc : srclimit - 7; int n; int rest_consumed; int exit_reason; @@ -526,14 +554,14 @@ InitDetector init_detector; bool IsStructurallyValidUTF8(const char* buf, int len) { if (!module_initialized_) return true; - + int bytes_consumed = 0; UTF8GenericScanFastAscii(&utf8acceptnonsurrogates_obj, buf, len, &bytes_consumed); return (bytes_consumed == len); } -int UTF8SpnStructurallyValid(const StringPiece& str) { +int UTF8SpnStructurallyValid(StringPiece str) { if (!module_initialized_) return str.size(); int bytes_consumed = 0; @@ -554,8 +582,7 @@ int UTF8SpnStructurallyValid(const StringPiece& str) { // // Fast case: all is structurally valid and no byte copying is done. // -char* UTF8CoerceToStructurallyValid(const StringPiece& src_str, - char* idst, +char* UTF8CoerceToStructurallyValid(StringPiece src_str, char* idst, const char replace_char) { const char* isrc = src_str.data(); const int len = src_str.length(); diff --git a/src/google/protobuf/stubs/structurally_valid_unittest.cc b/src/google/protobuf/stubs/structurally_valid_unittest.cc index 90888885ad5f5..ebd9c42306ba4 100644 --- a/src/google/protobuf/stubs/structurally_valid_unittest.cc +++ b/src/google/protobuf/stubs/structurally_valid_unittest.cc @@ -1,3 +1,33 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // Copyright 2008 Google Inc. All Rights Reserved. // Author: xpeng@google.com (Peter Peng) @@ -13,7 +43,8 @@ TEST(StructurallyValidTest, ValidUTF8String) { // On GCC, this string can be written as: // "abcd 1234 - \u2014\u2013\u2212" // MSVC seems to interpret \u differently. - string valid_str("abcd 1234 - \342\200\224\342\200\223\342\210\222 - xyz789"); + std::string valid_str( + "abcd 1234 - \342\200\224\342\200\223\342\210\222 - xyz789"); EXPECT_TRUE(IsStructurallyValidUTF8(valid_str.data(), valid_str.size())); // Additional check for pointer alignment @@ -24,7 +55,7 @@ TEST(StructurallyValidTest, ValidUTF8String) { } TEST(StructurallyValidTest, InvalidUTF8String) { - const string invalid_str("abcd\xA0\xB0\xA0\xB0\xA0\xB0 - xyz789"); + const std::string invalid_str("abcd\xA0\xB0\xA0\xB0\xA0\xB0 - xyz789"); EXPECT_FALSE(IsStructurallyValidUTF8(invalid_str.data(), invalid_str.size())); // Additional check for pointer alignment diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc index 1a4d71c822be8..2ecdb2bf72bf5 100644 --- a/src/google/protobuf/stubs/strutil.cc +++ b/src/google/protobuf/stubs/strutil.cc @@ -31,15 +31,16 @@ // from google3/strings/strutil.cc #include -#include #include #include // FLT_DIG and DBL_DIG -#include #include #include +#include #include +#include +#include #include #ifdef _WIN32 @@ -78,37 +79,22 @@ inline bool isprint(char c) { return c >= 0x20 && c <= 0x7E; } -// ---------------------------------------------------------------------- -// StripString -// Replaces any occurrence of the character 'remove' (or the characters -// in 'remove') with the character 'replacewith'. -// ---------------------------------------------------------------------- -void StripString(string* s, const char* remove, char replacewith) { - const char * str_start = s->c_str(); - const char * str = str_start; - for (str = strpbrk(str, remove); - str != NULL; - str = strpbrk(str + 1, remove)) { - (*s)[str - str_start] = replacewith; - } -} - // ---------------------------------------------------------------------- // ReplaceCharacters // Replaces any occurrence of the character 'remove' (or the characters // in 'remove') with the character 'replacewith'. // ---------------------------------------------------------------------- -void ReplaceCharacters(string *s, const char *remove, char replacewith) { +void ReplaceCharacters(std::string *s, const char *remove, char replacewith) { const char *str_start = s->c_str(); const char *str = str_start; for (str = strpbrk(str, remove); - str != NULL; + str != nullptr; str = strpbrk(str + 1, remove)) { (*s)[str - str_start] = replacewith; } } -void StripWhitespace(string* str) { +void StripWhitespace(std::string *str) { int str_length = str->length(); // Strip off leading whitespace. @@ -132,7 +118,7 @@ void StripWhitespace(string* str) { --last; } if (last != (str_length - 1) && last >= 0) { - str->erase(last + 1, string::npos); + str->erase(last + 1, std::string::npos); } } @@ -143,19 +129,19 @@ void StripWhitespace(string* str) { // it only replaces the first instance of "old." // ---------------------------------------------------------------------- -void StringReplace(const string& s, const string& oldsub, - const string& newsub, bool replace_all, - string* res) { +void StringReplace(const std::string &s, const std::string &oldsub, + const std::string &newsub, bool replace_all, + std::string *res) { if (oldsub.empty()) { res->append(s); // if empty, append the given string. return; } - string::size_type start_pos = 0; - string::size_type pos; + std::string::size_type start_pos = 0; + std::string::size_type pos; do { pos = s.find(oldsub, start_pos); - if (pos == string::npos) { + if (pos == std::string::npos) { break; } res->append(s, start_pos, pos - start_pos); @@ -174,9 +160,9 @@ void StringReplace(const string& s, const string& oldsub, // happened or not. // ---------------------------------------------------------------------- -string StringReplace(const string& s, const string& oldsub, - const string& newsub, bool replace_all) { - string ret; +std::string StringReplace(const std::string &s, const std::string &oldsub, + const std::string &newsub, bool replace_all) { + std::string ret; StringReplace(s, oldsub, newsub, replace_all, &ret); return ret; } @@ -190,10 +176,8 @@ string StringReplace(const string& s, const string& oldsub, // the characters in the string, not the entire string as a single delimiter. // ---------------------------------------------------------------------- template -static inline -void SplitStringToIteratorUsing(const string& full, - const char* delim, - ITR& result) { +static inline void SplitStringToIteratorUsing(StringPiece full, + const char *delim, ITR &result) { // Optimize the common case where delim is a single character. if (delim[0] != '\0' && delim[1] == '\0') { char c = delim[0]; @@ -205,29 +189,29 @@ void SplitStringToIteratorUsing(const string& full, } else { const char* start = p; while (++p != end && *p != c); - *result++ = string(start, p - start); + *result++ = std::string(start, p - start); } } return; } - string::size_type begin_index, end_index; + std::string::size_type begin_index, end_index; begin_index = full.find_first_not_of(delim); - while (begin_index != string::npos) { + while (begin_index != std::string::npos) { end_index = full.find_first_of(delim, begin_index); - if (end_index == string::npos) { - *result++ = full.substr(begin_index); + if (end_index == std::string::npos) { + *result++ = std::string(full.substr(begin_index)); return; } - *result++ = full.substr(begin_index, (end_index - begin_index)); + *result++ = + std::string(full.substr(begin_index, (end_index - begin_index))); begin_index = full.find_first_not_of(delim, end_index); } } -void SplitStringUsing(const string& full, - const char* delim, - vector* result) { - std::back_insert_iterator< vector > it(*result); +void SplitStringUsing(StringPiece full, const char *delim, + std::vector *result) { + std::back_insert_iterator > it(*result); SplitStringToIteratorUsing(full, delim, it); } @@ -242,30 +226,29 @@ void SplitStringUsing(const string& full, // // If "pieces" is negative for some reason, it returns the whole string // ---------------------------------------------------------------------- -template -static inline -void SplitStringToIteratorAllowEmpty(const StringType& full, - const char* delim, - int pieces, - ITR& result) { - string::size_type begin_index, end_index; +template +static inline void SplitStringToIteratorAllowEmpty(StringPiece full, + const char *delim, + int pieces, ITR &result) { + std::string::size_type begin_index, end_index; begin_index = 0; for (int i = 0; (i < pieces-1) || (pieces == 0); i++) { end_index = full.find_first_of(delim, begin_index); - if (end_index == string::npos) { - *result++ = full.substr(begin_index); + if (end_index == std::string::npos) { + *result++ = std::string(full.substr(begin_index)); return; } - *result++ = full.substr(begin_index, (end_index - begin_index)); + *result++ = + std::string(full.substr(begin_index, (end_index - begin_index))); begin_index = end_index + 1; } - *result++ = full.substr(begin_index); + *result++ = std::string(full.substr(begin_index)); } -void SplitStringAllowEmpty(const string& full, const char* delim, - vector* result) { - std::back_insert_iterator > it(*result); +void SplitStringAllowEmpty(StringPiece full, const char *delim, + std::vector *result) { + std::back_insert_iterator > it(*result); SplitStringToIteratorAllowEmpty(full, delim, 0, it); } @@ -276,11 +259,9 @@ void SplitStringAllowEmpty(const string& full, const char* delim, // // ---------------------------------------------------------------------- template -static void JoinStringsIterator(const ITERATOR& start, - const ITERATOR& end, - const char* delim, - string* result) { - GOOGLE_CHECK(result != NULL); +static void JoinStringsIterator(const ITERATOR &start, const ITERATOR &end, + const char *delim, std::string *result) { + GOOGLE_CHECK(result != nullptr); result->clear(); int delim_length = strlen(delim); @@ -303,9 +284,8 @@ static void JoinStringsIterator(const ITERATOR& start, } } -void JoinStrings(const vector& components, - const char* delim, - string * result) { +void JoinStrings(const std::vector &components, const char *delim, + std::string *result) { JoinStringsIterator(components.begin(), components.end(), delim, result); } @@ -318,7 +298,7 @@ void JoinStrings(const vector& components, // result is truncated to 8 bits. // // The second call stores its errors in a supplied string vector. -// If the string vector pointer is NULL, it reports the errors with LOG(). +// If the string vector pointer is nullptr, it reports the errors with LOG(). // ---------------------------------------------------------------------- #define IS_OCTAL_DIGIT(c) (((c) >= '0') && ((c) <= '7')) @@ -328,12 +308,12 @@ void JoinStrings(const vector& components, #define LOG_STRING(LEVEL, VECTOR) GOOGLE_LOG_IF(LEVEL, false) int UnescapeCEscapeSequences(const char* source, char* dest) { - return UnescapeCEscapeSequences(source, dest, NULL); + return UnescapeCEscapeSequences(source, dest, nullptr); } -int UnescapeCEscapeSequences(const char* source, char* dest, - vector *errors) { - GOOGLE_DCHECK(errors == NULL) << "Error reporting not implemented."; +int UnescapeCEscapeSequences(const char *source, char *dest, + std::vector *errors) { + GOOGLE_DCHECK(errors == nullptr) << "Error reporting not implemented."; char* d = dest; const char* p = source; @@ -387,8 +367,10 @@ int UnescapeCEscapeSequences(const char* source, char* dest, while (isxdigit(p[1])) // arbitrarily many hex digits ch = (ch << 4) + hex_digit_to_int(*++p); if (ch > 0xFF) - LOG_STRING(ERROR, errors) << "Value of " << - "\\" << string(hex_start, p+1-hex_start) << " exceeds 8 bits"; + LOG_STRING(ERROR, errors) + << "Value of " + << "\\" << std::string(hex_start, p + 1 - hex_start) + << " exceeds 8 bits"; *d++ = ch; break; } @@ -403,7 +385,7 @@ int UnescapeCEscapeSequences(const char* source, char* dest, } else { LOG_STRING(ERROR, errors) << "\\u must be followed by 4 hex digits: \\" - << string(hex_start, p+1-hex_start); + << std::string(hex_start, p+1-hex_start); break; } } @@ -422,7 +404,7 @@ int UnescapeCEscapeSequences(const char* source, char* dest, if (newrune > 0x10FFFF) { LOG_STRING(ERROR, errors) << "Value of \\" - << string(hex_start, p + 1 - hex_start) + << std::string(hex_start, p + 1 - hex_start) << " exceeds Unicode limit (0x10FFFF)"; break; } else { @@ -431,7 +413,7 @@ int UnescapeCEscapeSequences(const char* source, char* dest, } else { LOG_STRING(ERROR, errors) << "\\U must be followed by 8 hex digits: \\" - << string(hex_start, p+1-hex_start); + << std::string(hex_start, p+1-hex_start); break; } } @@ -458,28 +440,28 @@ int UnescapeCEscapeSequences(const char* source, char* dest, // to be the same. // // The second call stores its errors in a supplied string vector. -// If the string vector pointer is NULL, it reports the errors with LOG(). +// If the string vector pointer is nullptr, it reports the errors with LOG(). // // In the first and second calls, the length of dest is returned. In the // the third call, the new string is returned. // ---------------------------------------------------------------------- -int UnescapeCEscapeString(const string& src, string* dest) { - return UnescapeCEscapeString(src, dest, NULL); +int UnescapeCEscapeString(const std::string &src, std::string *dest) { + return UnescapeCEscapeString(src, dest, nullptr); } -int UnescapeCEscapeString(const string& src, string* dest, - vector *errors) { - scoped_array unescaped(new char[src.size() + 1]); +int UnescapeCEscapeString(const std::string &src, std::string *dest, + std::vector *errors) { + std::unique_ptr unescaped(new char[src.size() + 1]); int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), errors); GOOGLE_CHECK(dest); dest->assign(unescaped.get(), len); return len; } -string UnescapeCEscapeString(const string& src) { - scoped_array unescaped(new char[src.size() + 1]); - int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), NULL); - return string(unescaped.get(), len); +std::string UnescapeCEscapeString(const std::string &src) { + std::unique_ptr unescaped(new char[src.size() + 1]); + int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), nullptr); + return std::string(unescaped.get(), len); } // ---------------------------------------------------------------------- @@ -576,7 +558,7 @@ static inline size_t CEscapedLength(StringPiece src) { // the required space using a lookup table, and also does not do any special // handling for Hex or UTF-8 characters. // ---------------------------------------------------------------------- -void CEscapeAndAppend(StringPiece src, string* dest) { +void CEscapeAndAppend(StringPiece src, std::string *dest) { size_t escaped_len = CEscapedLength(src); if (escaped_len == src.size()) { dest->append(src.data(), src.size()); @@ -610,30 +592,30 @@ void CEscapeAndAppend(StringPiece src, string* dest) { } } -string CEscape(const string& src) { - string dest; +std::string CEscape(const std::string &src) { + std::string dest; CEscapeAndAppend(src, &dest); return dest; } namespace strings { -string Utf8SafeCEscape(const string& src) { +std::string Utf8SafeCEscape(const std::string &src) { const int dest_length = src.size() * 4 + 1; // Maximum possible expansion - scoped_array dest(new char[dest_length]); + std::unique_ptr dest(new char[dest_length]); const int len = CEscapeInternal(src.data(), src.size(), dest.get(), dest_length, false, true); GOOGLE_DCHECK_GE(len, 0); - return string(dest.get(), len); + return std::string(dest.get(), len); } -string CHexEscape(const string& src) { +std::string CHexEscape(const std::string &src) { const int dest_length = src.size() * 4 + 1; // Maximum possible expansion - scoped_array dest(new char[dest_length]); + std::unique_ptr dest(new char[dest_length]); const int len = CEscapeInternal(src.data(), src.size(), dest.get(), dest_length, true, false); GOOGLE_DCHECK_GE(len, 0); - return string(dest.get(), len); + return std::string(dest.get(), len); } } // namespace strings @@ -681,8 +663,8 @@ uint32 strtou32_adaptor(const char *nptr, char **endptr, int base) { return static_cast(result); } -inline bool safe_parse_sign(string* text /*inout*/, - bool* negative_ptr /*output*/) { +inline bool safe_parse_sign(std::string *text /*inout*/, + bool *negative_ptr /*output*/) { const char* start = text->data(); const char* end = start + text->size(); @@ -709,9 +691,8 @@ inline bool safe_parse_sign(string* text /*inout*/, return true; } -template -bool safe_parse_positive_int( - string text, IntType* value_p) { +template +bool safe_parse_positive_int(std::string text, IntType *value_p) { int base = 10; IntType value = 0; const IntType vmax = std::numeric_limits::max(); @@ -743,9 +724,8 @@ bool safe_parse_positive_int( return true; } -template -bool safe_parse_negative_int( - const string& text, IntType* value_p) { +template +bool safe_parse_negative_int(const std::string &text, IntType *value_p) { int base = 10; IntType value = 0; const IntType vmin = std::numeric_limits::min(); @@ -784,8 +764,8 @@ bool safe_parse_negative_int( return true; } -template -bool safe_int_internal(string text, IntType* value_p) { +template +bool safe_int_internal(std::string text, IntType *value_p) { *value_p = 0; bool negative; if (!safe_parse_sign(&text, &negative)) { @@ -798,8 +778,8 @@ bool safe_int_internal(string text, IntType* value_p) { } } -template -bool safe_uint_internal(string text, IntType* value_p) { +template +bool safe_uint_internal(std::string text, IntType *value_p) { *value_p = 0; bool negative; if (!safe_parse_sign(&text, &negative) || negative) { @@ -982,7 +962,7 @@ static const char two_ASCII_digits[100][2] = { char* FastUInt32ToBufferLeft(uint32 u, char* buffer) { uint32 digits; - const char *ASCII_digits = NULL; + const char *ASCII_digits = nullptr; // The idea of this implementation is to trim the number of divides to as few // as possible by using multiplication and subtraction rather than mod (%), // and by outputting two digits at a time rather than one. @@ -1063,17 +1043,19 @@ char* FastUInt32ToBufferLeft(uint32 u, char* buffer) { } char* FastInt32ToBufferLeft(int32 i, char* buffer) { - uint32 u = i; + uint32 u = 0; if (i < 0) { *buffer++ = '-'; - u = -i; + u -= i; + } else { + u = i; } return FastUInt32ToBufferLeft(u, buffer); } char* FastUInt64ToBufferLeft(uint64 u64, char* buffer) { int digits; - const char *ASCII_digits = NULL; + const char *ASCII_digits = nullptr; uint32 u = static_cast(u64); if (u == u64) return FastUInt32ToBufferLeft(u, buffer); @@ -1114,10 +1096,12 @@ char* FastUInt64ToBufferLeft(uint64 u64, char* buffer) { } char* FastInt64ToBufferLeft(int64 i, char* buffer) { - uint64 u = i; + uint64 u = 0; if (i < 0) { *buffer++ = '-'; - u = -i; + u -= i; + } else { + u = i; } return FastUInt64ToBufferLeft(u, buffer); } @@ -1129,46 +1113,46 @@ char* FastInt64ToBufferLeft(int64 i, char* buffer) { // Return value: string // ---------------------------------------------------------------------- -string SimpleItoa(int i) { +std::string SimpleItoa(int i) { char buffer[kFastToBufferSize]; return (sizeof(i) == 4) ? FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer); } -string SimpleItoa(unsigned int i) { +std::string SimpleItoa(unsigned int i) { char buffer[kFastToBufferSize]; - return string(buffer, (sizeof(i) == 4) ? - FastUInt32ToBufferLeft(i, buffer) : - FastUInt64ToBufferLeft(i, buffer)); + return std::string(buffer, (sizeof(i) == 4) + ? FastUInt32ToBufferLeft(i, buffer) + : FastUInt64ToBufferLeft(i, buffer)); } -string SimpleItoa(long i) { +std::string SimpleItoa(long i) { char buffer[kFastToBufferSize]; return (sizeof(i) == 4) ? FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer); } -string SimpleItoa(unsigned long i) { +std::string SimpleItoa(unsigned long i) { char buffer[kFastToBufferSize]; - return string(buffer, (sizeof(i) == 4) ? - FastUInt32ToBufferLeft(i, buffer) : - FastUInt64ToBufferLeft(i, buffer)); + return std::string(buffer, (sizeof(i) == 4) + ? FastUInt32ToBufferLeft(i, buffer) + : FastUInt64ToBufferLeft(i, buffer)); } -string SimpleItoa(long long i) { +std::string SimpleItoa(long long i) { char buffer[kFastToBufferSize]; return (sizeof(i) == 4) ? FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer); } -string SimpleItoa(unsigned long long i) { +std::string SimpleItoa(unsigned long long i) { char buffer[kFastToBufferSize]; - return string(buffer, (sizeof(i) == 4) ? - FastUInt32ToBufferLeft(i, buffer) : - FastUInt64ToBufferLeft(i, buffer)); + return std::string(buffer, (sizeof(i) == 4) + ? FastUInt32ToBufferLeft(i, buffer) + : FastUInt64ToBufferLeft(i, buffer)); } // ---------------------------------------------------------------------- @@ -1212,12 +1196,12 @@ string SimpleItoa(unsigned long long i) { // implementation. // ---------------------------------------------------------------------- -string SimpleDtoa(double value) { +std::string SimpleDtoa(double value) { char buffer[kDoubleToBufferSize]; return DoubleToBuffer(value, buffer); } -string SimpleFtoa(float value) { +std::string SimpleFtoa(float value) { char buffer[kFloatToBufferSize]; return FloatToBuffer(value, buffer); } @@ -1231,7 +1215,7 @@ static inline bool IsValidFloatChar(char c) { void DelocalizeRadix(char* buffer) { // Fast check: if the buffer has a normal decimal point, assume no // translation is needed. - if (strchr(buffer, '.') != NULL) return; + if (strchr(buffer, '.') != nullptr) return; // Find the first unknown character. while (IsValidFloatChar(*buffer)) ++buffer; @@ -1268,7 +1252,7 @@ char* DoubleToBuffer(double value, char* buffer) { } else if (value == -std::numeric_limits::infinity()) { strcpy(buffer, "-inf"); return buffer; - } else if (MathLimits::IsNaN(value)) { + } else if (std::isnan(value)) { strcpy(buffer, "nan"); return buffer; } @@ -1286,7 +1270,7 @@ char* DoubleToBuffer(double value, char* buffer) { // of a double. This long double may have extra bits that make it compare // unequal to "value" even though it would be exactly equal if it were // truncated to a double. - volatile double parsed_value = strtod(buffer, NULL); + volatile double parsed_value = internal::NoLocaleStrtod(buffer, nullptr); if (parsed_value != value) { int snprintf_result = snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG+2, value); @@ -1318,7 +1302,7 @@ inline bool CaseEqual(StringPiece s1, StringPiece s2) { } bool safe_strtob(StringPiece str, bool* value) { - GOOGLE_CHECK(value != NULL) << "NULL output boolean given."; + GOOGLE_CHECK(value != nullptr) << "nullptr output boolean given."; if (CaseEqual(str, "true") || CaseEqual(str, "t") || CaseEqual(str, "yes") || CaseEqual(str, "y") || CaseEqual(str, "1")) { @@ -1338,7 +1322,7 @@ bool safe_strtof(const char* str, float* value) { char* endptr; errno = 0; // errno only gets set on errors #if defined(_WIN32) || defined (__hpux) // has no strtof() - *value = strtod(str, &endptr); + *value = internal::NoLocaleStrtod(str, &endptr); #else *value = strtof(str, &endptr); #endif @@ -1347,7 +1331,7 @@ bool safe_strtof(const char* str, float* value) { bool safe_strtod(const char* str, double* value) { char* endptr; - *value = strtod(str, &endptr); + *value = internal::NoLocaleStrtod(str, &endptr); if (endptr != str) { while (ascii_isspace(*endptr)) ++endptr; } @@ -1357,19 +1341,19 @@ bool safe_strtod(const char* str, double* value) { return *str != '\0' && *endptr == '\0'; } -bool safe_strto32(const string& str, int32* value) { +bool safe_strto32(const std::string &str, int32 *value) { return safe_int_internal(str, value); } -bool safe_strtou32(const string& str, uint32* value) { +bool safe_strtou32(const std::string &str, uint32 *value) { return safe_uint_internal(str, value); } -bool safe_strto64(const string& str, int64* value) { +bool safe_strto64(const std::string &str, int64 *value) { return safe_int_internal(str, value); } -bool safe_strtou64(const string& str, uint64* value) { +bool safe_strtou64(const std::string &str, uint64 *value) { return safe_uint_internal(str, value); } @@ -1386,7 +1370,7 @@ char* FloatToBuffer(float value, char* buffer) { } else if (value == -std::numeric_limits::infinity()) { strcpy(buffer, "-inf"); return buffer; - } else if (MathLimits::IsNaN(value)) { + } else if (std::isnan(value)) { strcpy(buffer, "nan"); return buffer; } @@ -1445,36 +1429,48 @@ AlphaNum::AlphaNum(strings::Hex hex) { // after the area just overwritten. It comes in multiple flavors to minimize // call overhead. static char *Append1(char *out, const AlphaNum &x) { - memcpy(out, x.data(), x.size()); - return out + x.size(); + if (x.size() > 0) { + memcpy(out, x.data(), x.size()); + out += x.size(); + } + return out; } static char *Append2(char *out, const AlphaNum &x1, const AlphaNum &x2) { - memcpy(out, x1.data(), x1.size()); - out += x1.size(); - - memcpy(out, x2.data(), x2.size()); - return out + x2.size(); + if (x1.size() > 0) { + memcpy(out, x1.data(), x1.size()); + out += x1.size(); + } + if (x2.size() > 0) { + memcpy(out, x2.data(), x2.size()); + out += x2.size(); + } + return out; } -static char *Append4(char *out, - const AlphaNum &x1, const AlphaNum &x2, +static char *Append4(char *out, const AlphaNum &x1, const AlphaNum &x2, const AlphaNum &x3, const AlphaNum &x4) { - memcpy(out, x1.data(), x1.size()); - out += x1.size(); - - memcpy(out, x2.data(), x2.size()); - out += x2.size(); - - memcpy(out, x3.data(), x3.size()); - out += x3.size(); - - memcpy(out, x4.data(), x4.size()); - return out + x4.size(); + if (x1.size() > 0) { + memcpy(out, x1.data(), x1.size()); + out += x1.size(); + } + if (x2.size() > 0) { + memcpy(out, x2.data(), x2.size()); + out += x2.size(); + } + if (x3.size() > 0) { + memcpy(out, x3.data(), x3.size()); + out += x3.size(); + } + if (x4.size() > 0) { + memcpy(out, x4.data(), x4.size()); + out += x4.size(); + } + return out; } -string StrCat(const AlphaNum &a, const AlphaNum &b) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b) { + std::string result; result.resize(a.size() + b.size()); char *const begin = &*result.begin(); char *out = Append2(begin, a, b); @@ -1482,8 +1478,8 @@ string StrCat(const AlphaNum &a, const AlphaNum &b) { return result; } -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { + std::string result; result.resize(a.size() + b.size() + c.size()); char *const begin = &*result.begin(); char *out = Append2(begin, a, b); @@ -1492,9 +1488,9 @@ string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { return result; } -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d) { + std::string result; result.resize(a.size() + b.size() + c.size() + d.size()); char *const begin = &*result.begin(); char *out = Append4(begin, a, b, c, d); @@ -1502,9 +1498,9 @@ string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, return result; } -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e) { + std::string result; result.resize(a.size() + b.size() + c.size() + d.size() + e.size()); char *const begin = &*result.begin(); char *out = Append4(begin, a, b, c, d); @@ -1513,9 +1509,9 @@ string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, return result; } -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) { + std::string result; result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + f.size()); char *const begin = &*result.begin(); @@ -1525,10 +1521,10 @@ string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, return result; } -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, - const AlphaNum &g) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g) { + std::string result; result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + f.size() + g.size()); char *const begin = &*result.begin(); @@ -1539,10 +1535,10 @@ string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, return result; } -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, - const AlphaNum &g, const AlphaNum &h) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h) { + std::string result; result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + f.size() + g.size() + h.size()); char *const begin = &*result.begin(); @@ -1552,10 +1548,10 @@ string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, return result; } -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, - const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) { + std::string result; result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + f.size() + g.size() + h.size() + i.size()); char *const begin = &*result.begin(); @@ -1574,27 +1570,27 @@ string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, GOOGLE_DCHECK_GT(uintptr_t((src).data() - (dest).data()), \ uintptr_t((dest).size())) -void StrAppend(string *result, const AlphaNum &a) { +void StrAppend(std::string *result, const AlphaNum &a) { GOOGLE_DCHECK_NO_OVERLAP(*result, a); result->append(a.data(), a.size()); } -void StrAppend(string *result, const AlphaNum &a, const AlphaNum &b) { +void StrAppend(std::string *result, const AlphaNum &a, const AlphaNum &b) { GOOGLE_DCHECK_NO_OVERLAP(*result, a); GOOGLE_DCHECK_NO_OVERLAP(*result, b); - string::size_type old_size = result->size(); + std::string::size_type old_size = result->size(); result->resize(old_size + a.size() + b.size()); char *const begin = &*result->begin(); char *out = Append2(begin + old_size, a, b); GOOGLE_DCHECK_EQ(out, begin + result->size()); } -void StrAppend(string *result, - const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { +void StrAppend(std::string *result, const AlphaNum &a, const AlphaNum &b, + const AlphaNum &c) { GOOGLE_DCHECK_NO_OVERLAP(*result, a); GOOGLE_DCHECK_NO_OVERLAP(*result, b); GOOGLE_DCHECK_NO_OVERLAP(*result, c); - string::size_type old_size = result->size(); + std::string::size_type old_size = result->size(); result->resize(old_size + a.size() + b.size() + c.size()); char *const begin = &*result->begin(); char *out = Append2(begin + old_size, a, b); @@ -1602,32 +1598,29 @@ void StrAppend(string *result, GOOGLE_DCHECK_EQ(out, begin + result->size()); } -void StrAppend(string *result, - const AlphaNum &a, const AlphaNum &b, +void StrAppend(std::string *result, const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, const AlphaNum &d) { GOOGLE_DCHECK_NO_OVERLAP(*result, a); GOOGLE_DCHECK_NO_OVERLAP(*result, b); GOOGLE_DCHECK_NO_OVERLAP(*result, c); GOOGLE_DCHECK_NO_OVERLAP(*result, d); - string::size_type old_size = result->size(); + std::string::size_type old_size = result->size(); result->resize(old_size + a.size() + b.size() + c.size() + d.size()); char *const begin = &*result->begin(); char *out = Append4(begin + old_size, a, b, c, d); GOOGLE_DCHECK_EQ(out, begin + result->size()); } -int GlobalReplaceSubstring(const string& substring, - const string& replacement, - string* s) { - GOOGLE_CHECK(s != NULL); +int GlobalReplaceSubstring(const std::string &substring, + const std::string &replacement, std::string *s) { + GOOGLE_CHECK(s != nullptr); if (s->empty() || substring.empty()) return 0; - string tmp; + std::string tmp; int num_replacements = 0; int pos = 0; for (int match_pos = s->find(substring.data(), pos, substring.length()); - match_pos != string::npos; - pos = match_pos + substring.length(), + match_pos != std::string::npos; pos = match_pos + substring.length(), match_pos = s->find(substring.data(), pos, substring.length())) { ++num_replacements; // Append the original content before the match. @@ -1959,24 +1952,25 @@ int Base64UnescapeInternal(const char *src_param, int szsrc, // #include // #include // #include +// #include // main() // { // static const char Base64[] = // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -// char *pos; +// const char *pos; // int idx, i, j; // printf(" "); // for (i = 0; i < 255; i += 8) { // for (j = i; j < i + 8; j++) { // pos = strchr(Base64, j); -// if ((pos == NULL) || (j == 0)) +// if ((pos == nullptr) || (j == 0)) // idx = -1; // else // idx = pos - Base64; // if (idx == -1) // printf(" %2d, ", idx); // else -// printf(" %2d/*%c*/,", idx, j); +// printf(" %2d/""*%c*""/,", idx, j); // } // printf("\n "); // } @@ -1994,7 +1988,7 @@ static const signed char kUnBase64[] = { 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1, -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, - 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, + 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1, -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, @@ -2028,7 +2022,7 @@ static const signed char kUnWebSafeBase64[] = { 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1, -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, - 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, + 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, 63/*_*/, -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, @@ -2057,8 +2051,8 @@ int WebSafeBase64Unescape(const char *src, int szsrc, char *dest, int szdest) { return Base64UnescapeInternal(src, szsrc, dest, szdest, kUnWebSafeBase64); } -static bool Base64UnescapeInternal(const char* src, int slen, string* dest, - const signed char* unbase64) { +static bool Base64UnescapeInternal(const char *src, int slen, std::string *dest, + const signed char *unbase64) { // Determine the size of the output string. Base64 encodes every 3 bytes into // 4 characters. any leftover chars are added directly for good measure. // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548 @@ -2082,11 +2076,11 @@ static bool Base64UnescapeInternal(const char* src, int slen, string* dest, return true; } -bool Base64Unescape(StringPiece src, string* dest) { +bool Base64Unescape(StringPiece src, std::string *dest) { return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64); } -bool WebSafeBase64Unescape(StringPiece src, string* dest) { +bool WebSafeBase64Unescape(StringPiece src, std::string *dest) { return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64); } @@ -2205,9 +2199,9 @@ int WebSafeBase64Escape(const unsigned char *src, int szsrc, char *dest, kWebSafeBase64Chars, do_padding); } -void Base64EscapeInternal(const unsigned char* src, int szsrc, - string* dest, bool do_padding, - const char* base64_chars) { +void Base64EscapeInternal(const unsigned char *src, int szsrc, + std::string *dest, bool do_padding, + const char *base64_chars) { const int calc_escaped_size = CalculateBase64EscapedLen(szsrc, do_padding); dest->resize(calc_escaped_size); @@ -2220,27 +2214,27 @@ void Base64EscapeInternal(const unsigned char* src, int szsrc, dest->erase(escaped_len); } -void Base64Escape(const unsigned char *src, int szsrc, - string* dest, bool do_padding) { +void Base64Escape(const unsigned char *src, int szsrc, std::string *dest, + bool do_padding) { Base64EscapeInternal(src, szsrc, dest, do_padding, kBase64Chars); } -void WebSafeBase64Escape(const unsigned char *src, int szsrc, - string *dest, bool do_padding) { +void WebSafeBase64Escape(const unsigned char *src, int szsrc, std::string *dest, + bool do_padding) { Base64EscapeInternal(src, szsrc, dest, do_padding, kWebSafeBase64Chars); } -void Base64Escape(StringPiece src, string* dest) { +void Base64Escape(StringPiece src, std::string *dest) { Base64Escape(reinterpret_cast(src.data()), src.size(), dest, true); } -void WebSafeBase64Escape(StringPiece src, string* dest) { +void WebSafeBase64Escape(StringPiece src, std::string *dest) { WebSafeBase64Escape(reinterpret_cast(src.data()), src.size(), dest, false); } -void WebSafeBase64EscapeWithPadding(StringPiece src, string* dest) { +void WebSafeBase64EscapeWithPadding(StringPiece src, std::string *dest) { WebSafeBase64Escape(reinterpret_cast(src.data()), src.size(), dest, true); } @@ -2281,16 +2275,19 @@ int EncodeAsUTF8Char(uint32 code_point, char* output) { // Table of UTF-8 character lengths, based on first byte static const unsigned char kUTF8LenTbl[256] = { - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4 -}; + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; // Return length of a single UTF-8 source character int UTF8FirstLetterNumBytes(const char* src, int len) { @@ -2300,5 +2297,181 @@ int UTF8FirstLetterNumBytes(const char* src, int len) { return kUTF8LenTbl[*reinterpret_cast(src)]; } +// ---------------------------------------------------------------------- +// CleanStringLineEndings() +// Clean up a multi-line string to conform to Unix line endings. +// Reads from src and appends to dst, so usually dst should be empty. +// +// If there is no line ending at the end of a non-empty string, it can +// be added automatically. +// +// Four different types of input are correctly handled: +// +// - Unix/Linux files: line ending is LF: pass through unchanged +// +// - DOS/Windows files: line ending is CRLF: convert to LF +// +// - Legacy Mac files: line ending is CR: convert to LF +// +// - Garbled files: random line endings: convert gracefully +// lonely CR, lonely LF, CRLF: convert to LF +// +// @param src The multi-line string to convert +// @param dst The converted string is appended to this string +// @param auto_end_last_line Automatically terminate the last line +// +// Limitations: +// +// This does not do the right thing for CRCRLF files created by +// broken programs that do another Unix->DOS conversion on files +// that are already in CRLF format. For this, a two-pass approach +// brute-force would be needed that +// +// (1) determines the presence of LF (first one is ok) +// (2) if yes, removes any CR, else convert every CR to LF + +void CleanStringLineEndings(const std::string &src, std::string *dst, + bool auto_end_last_line) { + if (dst->empty()) { + dst->append(src); + CleanStringLineEndings(dst, auto_end_last_line); + } else { + std::string tmp = src; + CleanStringLineEndings(&tmp, auto_end_last_line); + dst->append(tmp); + } +} + +void CleanStringLineEndings(std::string *str, bool auto_end_last_line) { + ptrdiff_t output_pos = 0; + bool r_seen = false; + ptrdiff_t len = str->size(); + + char *p = &(*str)[0]; + + for (ptrdiff_t input_pos = 0; input_pos < len;) { + if (!r_seen && input_pos + 8 < len) { + uint64_t v = GOOGLE_UNALIGNED_LOAD64(p + input_pos); + // Loop over groups of 8 bytes at a time until we come across + // a word that has a byte whose value is less than or equal to + // '\r' (i.e. could contain a \n (0x0a) or a \r (0x0d) ). + // + // We use a has_less macro that quickly tests a whole 64-bit + // word to see if any of the bytes has a value < N. + // + // For more details, see: + // http://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord +#define has_less(x, n) (((x) - ~0ULL / 255 * (n)) & ~(x) & ~0ULL / 255 * 128) + if (!has_less(v, '\r' + 1)) { +#undef has_less + // No byte in this word has a value that could be a \r or a \n + if (output_pos != input_pos) { + GOOGLE_UNALIGNED_STORE64(p + output_pos, v); + } + input_pos += 8; + output_pos += 8; + continue; + } + } + std::string::const_reference in = p[input_pos]; + if (in == '\r') { + if (r_seen) p[output_pos++] = '\n'; + r_seen = true; + } else if (in == '\n') { + if (input_pos != output_pos) + p[output_pos++] = '\n'; + else + output_pos++; + r_seen = false; + } else { + if (r_seen) p[output_pos++] = '\n'; + r_seen = false; + if (input_pos != output_pos) + p[output_pos++] = in; + else + output_pos++; + } + input_pos++; + } + if (r_seen || + (auto_end_last_line && output_pos > 0 && p[output_pos - 1] != '\n')) { + str->resize(output_pos + 1); + str->operator[](output_pos) = '\n'; + } else if (output_pos < len) { + str->resize(output_pos); + } +} + +namespace internal { + +// ---------------------------------------------------------------------- +// NoLocaleStrtod() +// This code will make you cry. +// ---------------------------------------------------------------------- + +namespace { + +// Returns a string identical to *input except that the character pointed to +// by radix_pos (which should be '.') is replaced with the locale-specific +// radix character. +std::string LocalizeRadix(const char *input, const char *radix_pos) { + // Determine the locale-specific radix character by calling sprintf() to + // print the number 1.5, then stripping off the digits. As far as I can + // tell, this is the only portable, thread-safe way to get the C library + // to divuldge the locale's radix character. No, localeconv() is NOT + // thread-safe. + char temp[16]; + int size = snprintf(temp, sizeof(temp), "%.1f", 1.5); + GOOGLE_CHECK_EQ(temp[0], '1'); + GOOGLE_CHECK_EQ(temp[size - 1], '5'); + GOOGLE_CHECK_LE(size, 6); + + // Now replace the '.' in the input with it. + std::string result; + result.reserve(strlen(input) + size - 3); + result.append(input, radix_pos); + result.append(temp + 1, size - 2); + result.append(radix_pos + 1); + return result; +} + +} // namespace + +double NoLocaleStrtod(const char *str, char **endptr) { + // We cannot simply set the locale to "C" temporarily with setlocale() + // as this is not thread-safe. Instead, we try to parse in the current + // locale first. If parsing stops at a '.' character, then this is a + // pretty good hint that we're actually in some other locale in which + // '.' is not the radix character. + + char *temp_endptr; + double result = strtod(str, &temp_endptr); + if (endptr != NULL) *endptr = temp_endptr; + if (*temp_endptr != '.') return result; + + // Parsing halted on a '.'. Perhaps we're in a different locale? Let's + // try to replace the '.' with a locale-specific radix character and + // try again. + std::string localized = LocalizeRadix(str, temp_endptr); + const char *localized_cstr = localized.c_str(); + char *localized_endptr; + result = strtod(localized_cstr, &localized_endptr); + if ((localized_endptr - localized_cstr) > (temp_endptr - str)) { + // This attempt got further, so replacing the decimal must have helped. + // Update endptr to point at the right location. + if (endptr != NULL) { + // size_diff is non-zero if the localized radix has multiple bytes. + int size_diff = localized.size() - strlen(str); + // const_cast is necessary to match the strtod() interface. + *endptr = const_cast( + str + (localized_endptr - localized_cstr - size_diff)); + } + } + + return result; +} + +} // namespace internal + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h index df28c94da8c3b..8ce81f28c398a 100644 --- a/src/google/protobuf/stubs/strutil.h +++ b/src/google/protobuf/stubs/strutil.h @@ -33,15 +33,18 @@ #ifndef GOOGLE_PROTOBUF_STUBS_STRUTIL_H__ #define GOOGLE_PROTOBUF_STUBS_STRUTIL_H__ -#include -#include #include #include +#include + +#include +#include +#include namespace google { namespace protobuf { -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 1800 #define strtoll _strtoi64 #define strtoull _strtoui64 #elif defined(__DECCXX) && defined(__osf__) @@ -110,13 +113,13 @@ inline int hex_digit_to_int(char c) { // prefix string if the prefix matches, otherwise the original // string. // ---------------------------------------------------------------------- -inline bool HasPrefixString(const string& str, - const string& prefix) { +inline bool HasPrefixString(StringPiece str, StringPiece prefix) { return str.size() >= prefix.size() && - str.compare(0, prefix.size(), prefix) == 0; + memcmp(str.data(), prefix.data(), prefix.size()) == 0; } -inline string StripPrefixString(const string& str, const string& prefix) { +inline std::string StripPrefixString(const std::string& str, + const std::string& prefix) { if (HasPrefixString(str, prefix)) { return str.substr(prefix.size()); } else { @@ -132,13 +135,14 @@ inline string StripPrefixString(const string& str, const string& prefix) { // suffix string if the suffix matches, otherwise the original // string. // ---------------------------------------------------------------------- -inline bool HasSuffixString(const string& str, - const string& suffix) { +inline bool HasSuffixString(StringPiece str, StringPiece suffix) { return str.size() >= suffix.size() && - str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; + memcmp(str.data() + str.size() - suffix.size(), suffix.data(), + suffix.size()) == 0; } -inline string StripSuffixString(const string& str, const string& suffix) { +inline std::string StripSuffixString(const std::string& str, + const std::string& suffix) { if (HasSuffixString(str, suffix)) { return str.substr(0, str.size() - suffix.size()); } else { @@ -155,13 +159,10 @@ inline string StripSuffixString(const string& str, const string& suffix) { // StripWhitespace // Removes whitespaces from both ends of the given string. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT void ReplaceCharacters(string* s, const char* remove, - char replacewith); -LIBPROTOBUF_EXPORT void StripString(string* s, const char* remove, - char replacewith); - -LIBPROTOBUF_EXPORT void StripWhitespace(string* s); +PROTOBUF_EXPORT void ReplaceCharacters(std::string* s, const char* remove, + char replacewith); +PROTOBUF_EXPORT void StripWhitespace(std::string* s); // ---------------------------------------------------------------------- // LowerString() @@ -173,24 +174,26 @@ LIBPROTOBUF_EXPORT void StripWhitespace(string* s); // strings. // ---------------------------------------------------------------------- -inline void LowerString(string * s) { - string::iterator end = s->end(); - for (string::iterator i = s->begin(); i != end; ++i) { +inline void LowerString(std::string* s) { + std::string::iterator end = s->end(); + for (std::string::iterator i = s->begin(); i != end; ++i) { // tolower() changes based on locale. We don't want this! if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A'; } } -inline void UpperString(string * s) { - string::iterator end = s->end(); - for (string::iterator i = s->begin(); i != end; ++i) { +inline void UpperString(std::string* s) { + std::string::iterator end = s->end(); + for (std::string::iterator i = s->begin(); i != end; ++i) { // toupper() changes based on locale. We don't want this! if ('a' <= *i && *i <= 'z') *i += 'A' - 'a'; } } -inline string ToUpper(const string& s) { - string out = s; +inline void ToUpper(std::string* s) { UpperString(s); } + +inline std::string ToUpper(const std::string& s) { + std::string out = s; UpperString(&out); return out; } @@ -203,8 +206,10 @@ inline string ToUpper(const string& s) { // happened or not. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT string StringReplace(const string& s, const string& oldsub, - const string& newsub, bool replace_all); +PROTOBUF_EXPORT std::string StringReplace(const std::string& s, + const std::string& oldsub, + const std::string& newsub, + bool replace_all); // ---------------------------------------------------------------------- // SplitStringUsing() @@ -212,8 +217,8 @@ LIBPROTOBUF_EXPORT string StringReplace(const string& s, const string& oldsub, // to 'result'. If there are consecutive delimiters, this function skips // over all of them. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT void SplitStringUsing(const string& full, const char* delim, - vector* res); +PROTOBUF_EXPORT void SplitStringUsing(StringPiece full, const char* delim, + std::vector* res); // Split a string using one or more byte delimiters, presented // as a nul-terminated c string. Append the components to 'result'. @@ -223,17 +228,16 @@ LIBPROTOBUF_EXPORT void SplitStringUsing(const string& full, const char* delim, // // If "full" is the empty string, yields an empty string as the only value. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT void SplitStringAllowEmpty(const string& full, - const char* delim, - vector* result); +PROTOBUF_EXPORT void SplitStringAllowEmpty(StringPiece full, const char* delim, + std::vector* result); // ---------------------------------------------------------------------- // Split() // Split a string using a character delimiter. // ---------------------------------------------------------------------- -inline vector Split( - const string& full, const char* delim, bool skip_empty = true) { - vector result; +inline std::vector Split(StringPiece full, const char* delim, + bool skip_empty = true) { + std::vector result; if (skip_empty) { SplitStringUsing(full, delim, &result); } else { @@ -250,12 +254,12 @@ inline vector Split( // another takes a pointer to the target string. In the latter case the // target string is cleared and overwritten. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT void JoinStrings(const vector& components, - const char* delim, string* result); +PROTOBUF_EXPORT void JoinStrings(const std::vector& components, + const char* delim, std::string* result); -inline string JoinStrings(const vector& components, - const char* delim) { - string result; +inline std::string JoinStrings(const std::vector& components, + const char* delim) { + std::string result; JoinStrings(components, delim, &result); return result; } @@ -285,15 +289,15 @@ inline string JoinStrings(const vector& components, // // Errors: In the first form of the call, errors are reported with // LOG(ERROR). The same is true for the second form of the call if -// the pointer to the string vector is NULL; otherwise, error -// messages are stored in the vector. In either case, the effect on +// the pointer to the string std::vector is nullptr; otherwise, error +// messages are stored in the std::vector. In either case, the effect on // the dest array is not defined, but rest of the source will be // processed. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest); -LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest, - vector *errors); +PROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest); +PROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest, + std::vector* errors); // ---------------------------------------------------------------------- // UnescapeCEscapeString() @@ -304,16 +308,18 @@ LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest, // to be the same. // // The second call stores its errors in a supplied string vector. -// If the string vector pointer is NULL, it reports the errors with LOG(). +// If the string vector pointer is nullptr, it reports the errors with LOG(). // // In the first and second calls, the length of dest is returned. In the // the third call, the new string is returned. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest); -LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest, - vector *errors); -LIBPROTOBUF_EXPORT string UnescapeCEscapeString(const string& src); +PROTOBUF_EXPORT int UnescapeCEscapeString(const std::string& src, + std::string* dest); +PROTOBUF_EXPORT int UnescapeCEscapeString(const std::string& src, + std::string* dest, + std::vector* errors); +PROTOBUF_EXPORT std::string UnescapeCEscapeString(const std::string& src); // ---------------------------------------------------------------------- // CEscape() @@ -322,21 +328,21 @@ LIBPROTOBUF_EXPORT string UnescapeCEscapeString(const string& src); // // Escaped chars: \n, \r, \t, ", ', \, and !isprint(). // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT string CEscape(const string& src); +PROTOBUF_EXPORT std::string CEscape(const std::string& src); // ---------------------------------------------------------------------- // CEscapeAndAppend() // Escapes 'src' using C-style escape sequences, and appends the escaped // string to 'dest'. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT void CEscapeAndAppend(StringPiece src, string* dest); +PROTOBUF_EXPORT void CEscapeAndAppend(StringPiece src, std::string* dest); namespace strings { // Like CEscape() but does not escape bytes with the upper bit set. -LIBPROTOBUF_EXPORT string Utf8SafeCEscape(const string& src); +PROTOBUF_EXPORT std::string Utf8SafeCEscape(const std::string& src); // Like CEscape() but uses hex (\x) escapes instead of octals. -LIBPROTOBUF_EXPORT string CHexEscape(const string& src); +PROTOBUF_EXPORT std::string CHexEscape(const std::string& src); } // namespace strings // ---------------------------------------------------------------------- @@ -349,10 +355,10 @@ LIBPROTOBUF_EXPORT string CHexEscape(const string& src); // platforms, so using these is safer, from the point of view of // overflow behavior, than using the standard libc functions. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT int32 strto32_adaptor(const char *nptr, char **endptr, - int base); -LIBPROTOBUF_EXPORT uint32 strtou32_adaptor(const char *nptr, char **endptr, - int base); +PROTOBUF_EXPORT int32 strto32_adaptor(const char* nptr, char** endptr, + int base); +PROTOBUF_EXPORT uint32 strtou32_adaptor(const char* nptr, char** endptr, + int base); inline int32 strto32(const char *nptr, char **endptr, int base) { if (sizeof(int32) == sizeof(long)) @@ -391,44 +397,44 @@ inline uint64 strtou64(const char *nptr, char **endptr, int base) { // safe_strtof() // safe_strtod() // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value); +PROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value); -LIBPROTOBUF_EXPORT bool safe_strto32(const string& str, int32* value); -LIBPROTOBUF_EXPORT bool safe_strtou32(const string& str, uint32* value); +PROTOBUF_EXPORT bool safe_strto32(const std::string& str, int32* value); +PROTOBUF_EXPORT bool safe_strtou32(const std::string& str, uint32* value); inline bool safe_strto32(const char* str, int32* value) { - return safe_strto32(string(str), value); + return safe_strto32(std::string(str), value); } inline bool safe_strto32(StringPiece str, int32* value) { return safe_strto32(str.ToString(), value); } inline bool safe_strtou32(const char* str, uint32* value) { - return safe_strtou32(string(str), value); + return safe_strtou32(std::string(str), value); } inline bool safe_strtou32(StringPiece str, uint32* value) { return safe_strtou32(str.ToString(), value); } -LIBPROTOBUF_EXPORT bool safe_strto64(const string& str, int64* value); -LIBPROTOBUF_EXPORT bool safe_strtou64(const string& str, uint64* value); +PROTOBUF_EXPORT bool safe_strto64(const std::string& str, int64* value); +PROTOBUF_EXPORT bool safe_strtou64(const std::string& str, uint64* value); inline bool safe_strto64(const char* str, int64* value) { - return safe_strto64(string(str), value); + return safe_strto64(std::string(str), value); } inline bool safe_strto64(StringPiece str, int64* value) { return safe_strto64(str.ToString(), value); } inline bool safe_strtou64(const char* str, uint64* value) { - return safe_strtou64(string(str), value); + return safe_strtou64(std::string(str), value); } inline bool safe_strtou64(StringPiece str, uint64* value) { return safe_strtou64(str.ToString(), value); } -LIBPROTOBUF_EXPORT bool safe_strtof(const char* str, float* value); -LIBPROTOBUF_EXPORT bool safe_strtod(const char* str, double* value); -inline bool safe_strtof(const string& str, float* value) { +PROTOBUF_EXPORT bool safe_strtof(const char* str, float* value); +PROTOBUF_EXPORT bool safe_strtod(const char* str, double* value); +inline bool safe_strtof(const std::string& str, float* value) { return safe_strtof(str.c_str(), value); } -inline bool safe_strtod(const string& str, double* value) { +inline bool safe_strtod(const std::string& str, double* value) { return safe_strtod(str.c_str(), value); } inline bool safe_strtof(StringPiece str, float* value) { @@ -464,13 +470,13 @@ inline bool safe_strtod(StringPiece str, double* value) { // DoubleToBuffer() and FloatToBuffer(). static const int kFastToBufferSize = 32; -LIBPROTOBUF_EXPORT char* FastInt32ToBuffer(int32 i, char* buffer); -LIBPROTOBUF_EXPORT char* FastInt64ToBuffer(int64 i, char* buffer); +PROTOBUF_EXPORT char* FastInt32ToBuffer(int32 i, char* buffer); +PROTOBUF_EXPORT char* FastInt64ToBuffer(int64 i, char* buffer); char* FastUInt32ToBuffer(uint32 i, char* buffer); // inline below char* FastUInt64ToBuffer(uint64 i, char* buffer); // inline below -LIBPROTOBUF_EXPORT char* FastHexToBuffer(int i, char* buffer); -LIBPROTOBUF_EXPORT char* FastHex64ToBuffer(uint64 i, char* buffer); -LIBPROTOBUF_EXPORT char* FastHex32ToBuffer(uint32 i, char* buffer); +PROTOBUF_EXPORT char* FastHexToBuffer(int i, char* buffer); +PROTOBUF_EXPORT char* FastHex64ToBuffer(uint64 i, char* buffer); +PROTOBUF_EXPORT char* FastHex32ToBuffer(uint32 i, char* buffer); // at least 22 bytes long inline char* FastIntToBuffer(int i, char* buffer) { @@ -506,10 +512,10 @@ inline char* FastULongToBuffer(unsigned long i, char* buffer) { // terminating the string). // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT char* FastInt32ToBufferLeft(int32 i, char* buffer); -LIBPROTOBUF_EXPORT char* FastUInt32ToBufferLeft(uint32 i, char* buffer); -LIBPROTOBUF_EXPORT char* FastInt64ToBufferLeft(int64 i, char* buffer); -LIBPROTOBUF_EXPORT char* FastUInt64ToBufferLeft(uint64 i, char* buffer); +PROTOBUF_EXPORT char* FastInt32ToBufferLeft(int32 i, char* buffer); +PROTOBUF_EXPORT char* FastUInt32ToBufferLeft(uint32 i, char* buffer); +PROTOBUF_EXPORT char* FastInt64ToBufferLeft(int64 i, char* buffer); +PROTOBUF_EXPORT char* FastUInt64ToBufferLeft(uint64 i, char* buffer); // Just define these in terms of the above. inline char* FastUInt32ToBuffer(uint32 i, char* buffer) { @@ -521,9 +527,7 @@ inline char* FastUInt64ToBuffer(uint64 i, char* buffer) { return buffer; } -inline string SimpleBtoa(bool value) { - return value ? "true" : "false"; -} +inline std::string SimpleBtoa(bool value) { return value ? "true" : "false"; } // ---------------------------------------------------------------------- // SimpleItoa() @@ -531,12 +535,12 @@ inline string SimpleBtoa(bool value) { // // Return value: string // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT string SimpleItoa(int i); -LIBPROTOBUF_EXPORT string SimpleItoa(unsigned int i); -LIBPROTOBUF_EXPORT string SimpleItoa(long i); -LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long i); -LIBPROTOBUF_EXPORT string SimpleItoa(long long i); -LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long long i); +PROTOBUF_EXPORT std::string SimpleItoa(int i); +PROTOBUF_EXPORT std::string SimpleItoa(unsigned int i); +PROTOBUF_EXPORT std::string SimpleItoa(long i); +PROTOBUF_EXPORT std::string SimpleItoa(unsigned long i); +PROTOBUF_EXPORT std::string SimpleItoa(long long i); +PROTOBUF_EXPORT std::string SimpleItoa(unsigned long long i); // ---------------------------------------------------------------------- // SimpleDtoa() @@ -557,11 +561,11 @@ LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long long i); // // Return value: string // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT string SimpleDtoa(double value); -LIBPROTOBUF_EXPORT string SimpleFtoa(float value); +PROTOBUF_EXPORT std::string SimpleDtoa(double value); +PROTOBUF_EXPORT std::string SimpleFtoa(float value); -LIBPROTOBUF_EXPORT char* DoubleToBuffer(double i, char* buffer); -LIBPROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer); +PROTOBUF_EXPORT char* DoubleToBuffer(double i, char* buffer); +PROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer); // In practice, doubles should never need more than 24 bytes and floats // should never need more than 14 (including null terminators), but we @@ -610,7 +614,7 @@ struct Hex { } }; -struct LIBPROTOBUF_EXPORT AlphaNum { +struct PROTOBUF_EXPORT AlphaNum { const char *piece_data_; // move these to string_ref eventually size_t piece_size_; // move these to string_ref eventually @@ -619,16 +623,26 @@ struct LIBPROTOBUF_EXPORT AlphaNum { // No bool ctor -- bools convert to an integral type. // A bool ctor would also convert incoming pointers (bletch). - AlphaNum(int32 i32) + AlphaNum(int i32) : piece_data_(digits), piece_size_(FastInt32ToBufferLeft(i32, digits) - &digits[0]) {} - AlphaNum(uint32 u32) + AlphaNum(unsigned int u32) : piece_data_(digits), piece_size_(FastUInt32ToBufferLeft(u32, digits) - &digits[0]) {} - AlphaNum(int64 i64) + AlphaNum(long long i64) + : piece_data_(digits), + piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {} + AlphaNum(unsigned long long u64) + : piece_data_(digits), + piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {} + + // Note: on some architectures, "long" is only 32 bits, not 64, but the + // performance hit of using FastInt64ToBufferLeft to handle 32-bit values + // is quite minor. + AlphaNum(long i64) : piece_data_(digits), piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {} - AlphaNum(uint64 u64) + AlphaNum(unsigned long u64) : piece_data_(digits), piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {} @@ -644,7 +658,7 @@ struct LIBPROTOBUF_EXPORT AlphaNum { // TODO: Add a string_ref constructor, eventually // AlphaNum(const StringPiece &pc) : piece(pc) {} - AlphaNum(const string& str) + AlphaNum(const std::string& str) : piece_data_(str.data()), piece_size_(str.size()) {} AlphaNum(StringPiece str) @@ -692,32 +706,34 @@ using strings::AlphaNum; // be a reference into str. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b); -LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c); -LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d); -LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d, - const AlphaNum& e); -LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d, - const AlphaNum& e, const AlphaNum& f); -LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d, - const AlphaNum& e, const AlphaNum& f, - const AlphaNum& g); -LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d, - const AlphaNum& e, const AlphaNum& f, - const AlphaNum& g, const AlphaNum& h); -LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d, - const AlphaNum& e, const AlphaNum& f, - const AlphaNum& g, const AlphaNum& h, - const AlphaNum& i); - -inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); } +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g, const AlphaNum& h); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g, const AlphaNum& h, + const AlphaNum& i); + +inline std::string StrCat(const AlphaNum& a) { + return std::string(a.data(), a.size()); +} // ---------------------------------------------------------------------- // StrAppend() @@ -740,14 +756,14 @@ inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); } // worked around as consecutive calls to StrAppend are quite efficient. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a); -LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a, - const AlphaNum& b); -LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a, - const AlphaNum& b, const AlphaNum& c); -LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a, - const AlphaNum& b, const AlphaNum& c, - const AlphaNum& d); +PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a); +PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a, + const AlphaNum& b); +PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a, + const AlphaNum& b, const AlphaNum& c); +PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a, + const AlphaNum& b, const AlphaNum& c, + const AlphaNum& d); // ---------------------------------------------------------------------- // Join() @@ -755,8 +771,8 @@ LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a, // the C-string "delim" as a separator between components. // ---------------------------------------------------------------------- template -void Join(Iterator start, Iterator end, - const char* delim, string* result) { +void Join(Iterator start, Iterator end, const char* delim, + std::string* result) { for (Iterator it = start; it != end; ++it) { if (it != start) { result->append(delim); @@ -766,9 +782,8 @@ void Join(Iterator start, Iterator end, } template -string Join(const Range& components, - const char* delim) { - string result; +std::string Join(const Range& components, const char* delim) { + std::string result; Join(components.begin(), components.end(), delim, &result); return result; } @@ -777,7 +792,7 @@ string Join(const Range& components, // ToHex() // Return a lower-case hex string representation of the given integer. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT string ToHex(uint64 num); +PROTOBUF_EXPORT std::string ToHex(uint64 num); // ---------------------------------------------------------------------- // GlobalReplaceSubstring() @@ -786,9 +801,9 @@ LIBPROTOBUF_EXPORT string ToHex(uint64 num); // // NOTE: The string pieces must not overlap s. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT int GlobalReplaceSubstring(const string& substring, - const string& replacement, - string* s); +PROTOBUF_EXPORT int GlobalReplaceSubstring(const std::string& substring, + const std::string& replacement, + std::string* s); // ---------------------------------------------------------------------- // Base64Unescape() @@ -796,7 +811,7 @@ LIBPROTOBUF_EXPORT int GlobalReplaceSubstring(const string& substring, // writes it to "dest". If src contains invalid characters, dest is cleared // and the function returns false. Returns true on success. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT bool Base64Unescape(StringPiece src, string* dest); +PROTOBUF_EXPORT bool Base64Unescape(StringPiece src, std::string* dest); // ---------------------------------------------------------------------- // WebSafeBase64Unescape() @@ -809,18 +824,17 @@ LIBPROTOBUF_EXPORT bool Base64Unescape(StringPiece src, string* dest); // returns false (with dest empty) if src contains invalid chars; for // this version src and dest must be different strings. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT int WebSafeBase64Unescape(const char* src, int slen, - char* dest, int szdest); -LIBPROTOBUF_EXPORT bool WebSafeBase64Unescape(StringPiece src, string* dest); +PROTOBUF_EXPORT int WebSafeBase64Unescape(const char* src, int slen, char* dest, + int szdest); +PROTOBUF_EXPORT bool WebSafeBase64Unescape(StringPiece src, std::string* dest); // Return the length to use for the output buffer given to the base64 escape // routines. Make sure to use the same value for do_padding in both. // This function may return incorrect results if given input_len values that // are extremely high, which should happen rarely. -LIBPROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len, - bool do_padding); +PROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len, bool do_padding); // Use this version when calling Base64Escape without a do_padding arg. -LIBPROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len); +PROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len); // ---------------------------------------------------------------------- // Base64Escape() @@ -834,23 +848,23 @@ LIBPROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len); // to escape them. It also has an extra parameter "do_padding", // which when set to false will prevent padding with "=". // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT int Base64Escape(const unsigned char* src, int slen, - char* dest, int szdest); -LIBPROTOBUF_EXPORT int WebSafeBase64Escape( - const unsigned char* src, int slen, char* dest, - int szdest, bool do_padding); +PROTOBUF_EXPORT int Base64Escape(const unsigned char* src, int slen, char* dest, + int szdest); +PROTOBUF_EXPORT int WebSafeBase64Escape(const unsigned char* src, int slen, + char* dest, int szdest, + bool do_padding); // Encode src into dest with padding. -LIBPROTOBUF_EXPORT void Base64Escape(StringPiece src, string* dest); +PROTOBUF_EXPORT void Base64Escape(StringPiece src, std::string* dest); // Encode src into dest web-safely without padding. -LIBPROTOBUF_EXPORT void WebSafeBase64Escape(StringPiece src, string* dest); +PROTOBUF_EXPORT void WebSafeBase64Escape(StringPiece src, std::string* dest); // Encode src into dest web-safely with padding. -LIBPROTOBUF_EXPORT void WebSafeBase64EscapeWithPadding(StringPiece src, - string* dest); +PROTOBUF_EXPORT void WebSafeBase64EscapeWithPadding(StringPiece src, + std::string* dest); -LIBPROTOBUF_EXPORT void Base64Escape(const unsigned char* src, int szsrc, - string* dest, bool do_padding); -LIBPROTOBUF_EXPORT void WebSafeBase64Escape(const unsigned char* src, int szsrc, - string* dest, bool do_padding); +PROTOBUF_EXPORT void Base64Escape(const unsigned char* src, int szsrc, + std::string* dest, bool do_padding); +PROTOBUF_EXPORT void WebSafeBase64Escape(const unsigned char* src, int szsrc, + std::string* dest, bool do_padding); inline bool IsValidCodePoint(uint32 code_point) { return code_point < 0xD800 || @@ -864,15 +878,76 @@ static const int UTFmax = 4; // in any external dependencies. The output buffer must be as least 4 bytes // large. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT int EncodeAsUTF8Char(uint32 code_point, char* output); +PROTOBUF_EXPORT int EncodeAsUTF8Char(uint32 code_point, char* output); // ---------------------------------------------------------------------- // UTF8FirstLetterNumBytes() // Length of the first UTF-8 character. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT int UTF8FirstLetterNumBytes(const char* src, int len); +PROTOBUF_EXPORT int UTF8FirstLetterNumBytes(const char* src, int len); + +// From google3/third_party/absl/strings/escaping.h + +// ---------------------------------------------------------------------- +// CleanStringLineEndings() +// Clean up a multi-line string to conform to Unix line endings. +// Reads from src and appends to dst, so usually dst should be empty. +// +// If there is no line ending at the end of a non-empty string, it can +// be added automatically. +// +// Four different types of input are correctly handled: +// +// - Unix/Linux files: line ending is LF: pass through unchanged +// +// - DOS/Windows files: line ending is CRLF: convert to LF +// +// - Legacy Mac files: line ending is CR: convert to LF +// +// - Garbled files: random line endings: convert gracefully +// lonely CR, lonely LF, CRLF: convert to LF +// +// @param src The multi-line string to convert +// @param dst The converted string is appended to this string +// @param auto_end_last_line Automatically terminate the last line +// +// Limitations: +// +// This does not do the right thing for CRCRLF files created by +// broken programs that do another Unix->DOS conversion on files +// that are already in CRLF format. For this, a two-pass approach +// brute-force would be needed that +// +// (1) determines the presence of LF (first one is ok) +// (2) if yes, removes any CR, else convert every CR to LF +PROTOBUF_EXPORT void CleanStringLineEndings(const std::string& src, + std::string* dst, + bool auto_end_last_line); + +// Same as above, but transforms the argument in place. +PROTOBUF_EXPORT void CleanStringLineEndings(std::string* str, + bool auto_end_last_line); + +namespace strings { +inline bool EndsWith(StringPiece text, StringPiece suffix) { + return suffix.empty() || + (text.size() >= suffix.size() && + memcmp(text.data() + (text.size() - suffix.size()), suffix.data(), + suffix.size()) == 0); +} +} // namespace strings + +namespace internal { + +// A locale-independent version of the standard strtod(), which always +// uses a dot as the decimal separator. +double NoLocaleStrtod(const char* str, char** endptr); + +} // namespace internal } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_STUBS_STRUTIL_H__ diff --git a/src/google/protobuf/stubs/strutil_unittest.cc b/src/google/protobuf/stubs/strutil_unittest.cc index 5d62fc4adf737..fc9a63f3f252b 100644 --- a/src/google/protobuf/stubs/strutil_unittest.cc +++ b/src/google/protobuf/stubs/strutil_unittest.cc @@ -50,18 +50,18 @@ namespace { TEST(StringUtilityTest, ImmuneToLocales) { // Remember the old locale. - char* old_locale_cstr = setlocale(LC_NUMERIC, NULL); - ASSERT_TRUE(old_locale_cstr != NULL); - string old_locale = old_locale_cstr; + char* old_locale_cstr = setlocale(LC_NUMERIC, nullptr); + ASSERT_TRUE(old_locale_cstr != nullptr); + std::string old_locale = old_locale_cstr; // Set the locale to "C". - ASSERT_TRUE(setlocale(LC_NUMERIC, "C") != NULL); + ASSERT_TRUE(setlocale(LC_NUMERIC, "C") != nullptr); EXPECT_EQ("1.5", SimpleDtoa(1.5)); EXPECT_EQ("1.5", SimpleFtoa(1.5)); - if (setlocale(LC_NUMERIC, "es_ES") == NULL && - setlocale(LC_NUMERIC, "es_ES.utf8") == NULL) { + if (setlocale(LC_NUMERIC, "es_ES") == nullptr && + setlocale(LC_NUMERIC, "es_ES.utf8") == nullptr) { // Some systems may not have the desired locale available. GOOGLE_LOG(WARNING) << "Couldn't set locale to es_ES. Skipping this test."; @@ -442,7 +442,7 @@ TEST(Base64, EscapeAndUnescape) { char decode_buffer[100]; int decode_length; int cypher_length; - string decode_str; + std::string decode_str; const unsigned char* unsigned_plaintext = reinterpret_cast(base64_tests[i].plaintext); @@ -491,13 +491,13 @@ TEST(Base64, EscapeAndUnescape) { EXPECT_EQ(plaintext, decode_str); // Let's try with a pre-populated string. - string encoded("this junk should be ignored"); - Base64Escape(string(base64_tests[i].plaintext, - base64_tests[i].plain_length), - &encoded); - EXPECT_EQ(encoded, string(encode_buffer, cypher_length)); + std::string encoded("this junk should be ignored"); + Base64Escape( + std::string(base64_tests[i].plaintext, base64_tests[i].plain_length), + &encoded); + EXPECT_EQ(encoded, std::string(encode_buffer, cypher_length)); - string decoded("this junk should be ignored"); + std::string decoded("this junk should be ignored"); EXPECT_TRUE(Base64Unescape( StringPiece(encode_buffer, cypher_length), &decoded)); EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); @@ -514,7 +514,7 @@ TEST(Base64, EscapeAndUnescape) { // Try chopping off the equals sign(s) entirely. The decoder // should still be okay with this. - string decoded2("this junk should also be ignored"); + std::string decoded2("this junk should also be ignored"); *first_equals = '\0'; EXPECT_TRUE(Base64Unescape( StringPiece(encode_buffer, first_equals - encode_buffer), &decoded2)); @@ -730,7 +730,7 @@ TEST(Base64, EscapeAndUnescape) { EXPECT_STREQ(encode_buffer, websafe); // Let's try the (other) string version of the encoder - string plain(base64_tests[i].plaintext, base64_tests[i].plain_length); + std::string plain(base64_tests[i].plaintext, base64_tests[i].plain_length); encoded = "this junk should be ignored"; WebSafeBase64Escape(plain, &encoded); EXPECT_EQ(encoded.size(), cypher_length); @@ -782,7 +782,7 @@ TEST(Base64, EscapeAndUnescape) { reinterpret_cast(base64_strings[i].plaintext); int plain_length = strlen(base64_strings[i].plaintext); int cypher_length = strlen(base64_strings[i].cyphertext); - vector buffer(cypher_length+1); + std::vector buffer(cypher_length+1); int encode_length = WebSafeBase64Escape(unsigned_plaintext, plain_length, &buffer[0], @@ -798,13 +798,100 @@ TEST(Base64, EscapeAndUnescape) { // Verify the behavior when decoding bad data { const char* bad_data = "ab-/"; - string buf; + std::string buf; EXPECT_FALSE(Base64Unescape(StringPiece(bad_data), &buf)); EXPECT_TRUE(!WebSafeBase64Unescape(bad_data, &buf)); EXPECT_TRUE(buf.empty()); } } +// Test StrCat of ints and longs of various sizes and signdedness. +TEST(StrCat, Ints) { + const short s = -1; // NOLINT(runtime/int) + const uint16_t us = 2; + const int i = -3; + const unsigned int ui = 4; + const long l = -5; // NOLINT(runtime/int) + const unsigned long ul = 6; // NOLINT(runtime/int) + const long long ll = -7; // NOLINT(runtime/int) + const unsigned long long ull = 8; // NOLINT(runtime/int) + const ptrdiff_t ptrdiff = -9; + const size_t size = 10; + const intptr_t intptr = -12; + const uintptr_t uintptr = 13; + std::string answer; + answer = StrCat(s, us); + EXPECT_EQ(answer, "-12"); + answer = StrCat(i, ui); + EXPECT_EQ(answer, "-34"); + answer = StrCat(l, ul); + EXPECT_EQ(answer, "-56"); + answer = StrCat(ll, ull); + EXPECT_EQ(answer, "-78"); + answer = StrCat(ptrdiff, size); + EXPECT_EQ(answer, "-910"); + answer = StrCat(ptrdiff, intptr); + EXPECT_EQ(answer, "-9-12"); + answer = StrCat(uintptr, 0); + EXPECT_EQ(answer, "130"); +} + +class ReplaceChars + : public ::testing::TestWithParam< + std::tuple> {}; + +TEST_P(ReplaceChars, ReplacesAllOccurencesOfAnyCharInReplaceWithAReplaceChar) { + std::string expected = std::get<0>(GetParam()); + std::string string_to_replace_in = std::get<1>(GetParam()); + const char* what_to_replace = std::get<2>(GetParam()); + char replacement = std::get<3>(GetParam()); + ReplaceCharacters(&string_to_replace_in, what_to_replace, replacement); + ASSERT_EQ(expected, string_to_replace_in); +} + +INSTANTIATE_TEST_CASE_P( + Replace, ReplaceChars, + ::testing::Values( + std::make_tuple("", "", "", '_'), // empty string should remain empty + std::make_tuple(" ", " ", "", '_'), // no replacement string + std::make_tuple(" ", " ", "_-abcedf", + '*'), // replacement character not in string + std::make_tuple("replace", "Replace", "R", + 'r'), // replace one character + std::make_tuple("not_spaces__", "not\nspaces\t ", " \t\r\n", + '_'), // replace some special characters + std::make_tuple("c++", "cxx", "x", + '+'), // same character multiple times + std::make_tuple("qvvvvvng v T", "queueing a T", "aeiou", + 'v'))); // replace all voewls + +class StripWs + : public ::testing::TestWithParam> {}; + +TEST_P(StripWs, AlwaysStripsLeadingAndTrailingWhitespace) { + std::string expected = std::get<0>(GetParam()); + std::string string_to_strip = std::get<1>(GetParam()); + StripWhitespace(&string_to_strip); + ASSERT_EQ(expected, string_to_strip); +} + +INSTANTIATE_TEST_CASE_P( + Strip, StripWs, + ::testing::Values( + std::make_tuple("", ""), // empty string should remain empty + std::make_tuple("", " "), // only ws should become empty + std::make_tuple("no whitespace", + " no whitespace"), // leading ws removed + std::make_tuple("no whitespace", + "no whitespace "), // trailing ws removed + std::make_tuple("no whitespace", + " no whitespace "), // same nb. of leading and trailing + std::make_tuple( + "no whitespace", + " no whitespace "), // different nb. of leading/trailing + std::make_tuple("no whitespace", + " no whitespace "))); // more trailing than leading + } // anonymous namespace } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/substitute.cc b/src/google/protobuf/stubs/substitute.cc index 7194a5b171e9e..92107416eb1b9 100644 --- a/src/google/protobuf/stubs/substitute.cc +++ b/src/google/protobuf/stubs/substitute.cc @@ -31,6 +31,8 @@ // Author: kenton@google.com (Kenton Varda) #include + +#include #include #include @@ -44,34 +46,32 @@ using internal::SubstituteArg; // to Substitute(). static int CountSubstituteArgs(const SubstituteArg* const* args_array) { int count = 0; - while (args_array[count] != NULL && args_array[count]->size() != -1) { + while (args_array[count] != nullptr && args_array[count]->size() != -1) { ++count; } return count; } -string Substitute( - const char* format, - const SubstituteArg& arg0, const SubstituteArg& arg1, - const SubstituteArg& arg2, const SubstituteArg& arg3, - const SubstituteArg& arg4, const SubstituteArg& arg5, - const SubstituteArg& arg6, const SubstituteArg& arg7, - const SubstituteArg& arg8, const SubstituteArg& arg9) { - string result; +std::string Substitute(const char* format, const SubstituteArg& arg0, + const SubstituteArg& arg1, const SubstituteArg& arg2, + const SubstituteArg& arg3, const SubstituteArg& arg4, + const SubstituteArg& arg5, const SubstituteArg& arg6, + const SubstituteArg& arg7, const SubstituteArg& arg8, + const SubstituteArg& arg9) { + std::string result; SubstituteAndAppend(&result, format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); return result; } -void SubstituteAndAppend( - string* output, const char* format, - const SubstituteArg& arg0, const SubstituteArg& arg1, - const SubstituteArg& arg2, const SubstituteArg& arg3, - const SubstituteArg& arg4, const SubstituteArg& arg5, - const SubstituteArg& arg6, const SubstituteArg& arg7, - const SubstituteArg& arg8, const SubstituteArg& arg9) { +void SubstituteAndAppend(std::string* output, const char* format, + const SubstituteArg& arg0, const SubstituteArg& arg1, + const SubstituteArg& arg2, const SubstituteArg& arg3, + const SubstituteArg& arg4, const SubstituteArg& arg5, + const SubstituteArg& arg6, const SubstituteArg& arg7, + const SubstituteArg& arg8, const SubstituteArg& arg9) { const SubstituteArg* const args_array[] = { - &arg0, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8, &arg9, NULL + &arg0, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8, &arg9, nullptr }; // Determine total size needed. diff --git a/src/google/protobuf/stubs/substitute.h b/src/google/protobuf/stubs/substitute.h index 7ee442af77b35..d4e72e1c51666 100644 --- a/src/google/protobuf/stubs/substitute.h +++ b/src/google/protobuf/stubs/substitute.h @@ -38,6 +38,8 @@ #ifndef GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_ #define GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_ +#include + namespace google { namespace protobuf { namespace strings { @@ -88,12 +90,12 @@ class SubstituteArg { public: inline SubstituteArg(const char* value) : text_(value), size_(strlen(text_)) {} - inline SubstituteArg(const string& value) - : text_(value.data()), size_(value.size()) {} + inline SubstituteArg(const std::string& value) + : text_(value.data()), size_(value.size()) {} // Indicates that no argument was given. inline explicit SubstituteArg() - : text_(NULL), size_(-1) {} + : text_(nullptr), size_(-1) {} // Primitives // We don't overload for signed and unsigned char because if people are @@ -137,34 +139,36 @@ class SubstituteArg { } // namespace internal -LIBPROTOBUF_EXPORT string Substitute( - const char* format, - const internal::SubstituteArg& arg0 = internal::SubstituteArg(), - const internal::SubstituteArg& arg1 = internal::SubstituteArg(), - const internal::SubstituteArg& arg2 = internal::SubstituteArg(), - const internal::SubstituteArg& arg3 = internal::SubstituteArg(), - const internal::SubstituteArg& arg4 = internal::SubstituteArg(), - const internal::SubstituteArg& arg5 = internal::SubstituteArg(), - const internal::SubstituteArg& arg6 = internal::SubstituteArg(), - const internal::SubstituteArg& arg7 = internal::SubstituteArg(), - const internal::SubstituteArg& arg8 = internal::SubstituteArg(), - const internal::SubstituteArg& arg9 = internal::SubstituteArg()); - -LIBPROTOBUF_EXPORT void SubstituteAndAppend( - string* output, const char* format, - const internal::SubstituteArg& arg0 = internal::SubstituteArg(), - const internal::SubstituteArg& arg1 = internal::SubstituteArg(), - const internal::SubstituteArg& arg2 = internal::SubstituteArg(), - const internal::SubstituteArg& arg3 = internal::SubstituteArg(), - const internal::SubstituteArg& arg4 = internal::SubstituteArg(), - const internal::SubstituteArg& arg5 = internal::SubstituteArg(), - const internal::SubstituteArg& arg6 = internal::SubstituteArg(), - const internal::SubstituteArg& arg7 = internal::SubstituteArg(), - const internal::SubstituteArg& arg8 = internal::SubstituteArg(), - const internal::SubstituteArg& arg9 = internal::SubstituteArg()); +PROTOBUF_EXPORT std::string Substitute( + const char* format, + const internal::SubstituteArg& arg0 = internal::SubstituteArg(), + const internal::SubstituteArg& arg1 = internal::SubstituteArg(), + const internal::SubstituteArg& arg2 = internal::SubstituteArg(), + const internal::SubstituteArg& arg3 = internal::SubstituteArg(), + const internal::SubstituteArg& arg4 = internal::SubstituteArg(), + const internal::SubstituteArg& arg5 = internal::SubstituteArg(), + const internal::SubstituteArg& arg6 = internal::SubstituteArg(), + const internal::SubstituteArg& arg7 = internal::SubstituteArg(), + const internal::SubstituteArg& arg8 = internal::SubstituteArg(), + const internal::SubstituteArg& arg9 = internal::SubstituteArg()); + +PROTOBUF_EXPORT void SubstituteAndAppend( + std::string* output, const char* format, + const internal::SubstituteArg& arg0 = internal::SubstituteArg(), + const internal::SubstituteArg& arg1 = internal::SubstituteArg(), + const internal::SubstituteArg& arg2 = internal::SubstituteArg(), + const internal::SubstituteArg& arg3 = internal::SubstituteArg(), + const internal::SubstituteArg& arg4 = internal::SubstituteArg(), + const internal::SubstituteArg& arg5 = internal::SubstituteArg(), + const internal::SubstituteArg& arg6 = internal::SubstituteArg(), + const internal::SubstituteArg& arg7 = internal::SubstituteArg(), + const internal::SubstituteArg& arg8 = internal::SubstituteArg(), + const internal::SubstituteArg& arg9 = internal::SubstituteArg()); } // namespace strings } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_ diff --git a/src/google/protobuf/stubs/time.cc b/src/google/protobuf/stubs/time.cc index 49c0412c17661..922be76d1ba30 100644 --- a/src/google/protobuf/stubs/time.cc +++ b/src/google/protobuf/stubs/time.cc @@ -80,9 +80,9 @@ bool ValidateDateTime(const DateTime& time) { return false; } if (time.month == 2 && IsLeapYear(time.year)) { - return time.month <= kDaysInMonth[time.month] + 1; + return time.day <= kDaysInMonth[time.month] + 1; } else { - return time.month <= kDaysInMonth[time.month]; + return time.day <= kDaysInMonth[time.month]; } } @@ -130,7 +130,7 @@ int64 SecondsSinceCommonEra(const DateTime& time) { // Format nanoseconds with either 3, 6, or 9 digits depending on the required // precision to represent the exact value. -string FormatNanos(int32 nanos) { +std::string FormatNanos(int32 nanos) { if (nanos % kNanosPerMillisecond == 0) { return StringPrintf("%03d", nanos / kNanosPerMillisecond); } else if (nanos % kNanosPerMicrosecond == 0) { @@ -142,12 +142,12 @@ string FormatNanos(int32 nanos) { // Parses an integer from a null-terminated char sequence. The method // consumes at most "width" chars. Returns a pointer after the consumed -// integer, or NULL if the data does not start with an integer or the +// integer, or nullptr if the data does not start with an integer or the // integer value does not fall in the range of [min_value, max_value]. const char* ParseInt(const char* data, int width, int min_value, int max_value, int* result) { if (!ascii_isdigit(*data)) { - return NULL; + return nullptr; } int value = 0; for (int i = 0; i < width; ++i, ++data) { @@ -161,7 +161,7 @@ const char* ParseInt(const char* data, int width, int min_value, *result = value; return data; } else { - return NULL; + return nullptr; } } @@ -169,7 +169,7 @@ const char* ParseInt(const char* data, int width, int min_value, // "010" will be parsed to 10000000 nanos. const char* ParseNanos(const char* data, int32* nanos) { if (!ascii_isdigit(*data)) { - return NULL; + return nullptr; } int value = 0; int len = 0; @@ -193,15 +193,15 @@ const char* ParseNanos(const char* data, int32* nanos) { const char* ParseTimezoneOffset(const char* data, int64* offset) { // Accept format "HH:MM". E.g., "08:00" int hour; - if ((data = ParseInt(data, 2, 0, 23, &hour)) == NULL) { - return NULL; + if ((data = ParseInt(data, 2, 0, 23, &hour)) == nullptr) { + return nullptr; } if (*data++ != ':') { - return NULL; + return nullptr; } int minute; - if ((data = ParseInt(data, 2, 0, 59, &minute)) == NULL) { - return NULL; + if ((data = ParseInt(data, 2, 0, 59, &minute)) == nullptr) { + return nullptr; } *offset = (hour * 60 + minute) * 60; return data; @@ -212,7 +212,7 @@ bool SecondsToDateTime(int64 seconds, DateTime* time) { if (seconds < kMinTime || seconds > kMaxTime) { return false; } - // It's easier to calcuate the DateTime starting from 0001-01-01T00:00:00 + // It's easier to calculate the DateTime starting from 0001-01-01T00:00:00 seconds = seconds + kSecondsFromEraToEpoch; int year = 1; if (seconds >= kSecondsPer400Years) { @@ -264,25 +264,25 @@ bool DateTimeToSeconds(const DateTime& time, int64* seconds) { void GetCurrentTime(int64* seconds, int32* nanos) { // TODO(xiaofeng): Improve the accuracy of this implementation (or just // remove this method from protobuf). - *seconds = time(NULL); + *seconds = time(nullptr); *nanos = 0; } -string FormatTime(int64 seconds, int32 nanos) { +std::string FormatTime(int64 seconds, int32 nanos) { DateTime time; if (nanos < 0 || nanos > 999999999 || !SecondsToDateTime(seconds, &time)) { return "InvalidTime"; } - string result = StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d", - time.year, time.month, time.day, - time.hour, time.minute, time.second); + std::string result = + StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d", time.year, time.month, + time.day, time.hour, time.minute, time.second); if (nanos != 0) { result += "." + FormatNanos(nanos); } return result + "Z"; } -bool ParseTime(const string& value, int64* seconds, int32* nanos) { +bool ParseTime(const std::string& value, int64* seconds, int32* nanos) { DateTime time; const char* data = value.c_str(); // We only accept: @@ -290,37 +290,37 @@ bool ParseTime(const string& value, int64* seconds, int32* nanos) { // With UTC offset: 2015-05-20T13:29:35.120-08:00 // Parse year - if ((data = ParseInt(data, 4, 1, 9999, &time.year)) == NULL) { + if ((data = ParseInt(data, 4, 1, 9999, &time.year)) == nullptr) { return false; } // Expect '-' if (*data++ != '-') return false; // Parse month - if ((data = ParseInt(data, 2, 1, 12, &time.month)) == NULL) { + if ((data = ParseInt(data, 2, 1, 12, &time.month)) == nullptr) { return false; } // Expect '-' if (*data++ != '-') return false; // Parse day - if ((data = ParseInt(data, 2, 1, 31, &time.day)) == NULL) { + if ((data = ParseInt(data, 2, 1, 31, &time.day)) == nullptr) { return false; } // Expect 'T' if (*data++ != 'T') return false; // Parse hour - if ((data = ParseInt(data, 2, 0, 23, &time.hour)) == NULL) { + if ((data = ParseInt(data, 2, 0, 23, &time.hour)) == nullptr) { return false; } // Expect ':' if (*data++ != ':') return false; // Parse minute - if ((data = ParseInt(data, 2, 0, 59, &time.minute)) == NULL) { + if ((data = ParseInt(data, 2, 0, 59, &time.minute)) == nullptr) { return false; } // Expect ':' if (*data++ != ':') return false; // Parse second - if ((data = ParseInt(data, 2, 0, 59, &time.second)) == NULL) { + if ((data = ParseInt(data, 2, 0, 59, &time.second)) == nullptr) { return false; } if (!DateTimeToSeconds(time, seconds)) { @@ -330,7 +330,7 @@ bool ParseTime(const string& value, int64* seconds, int32* nanos) { if (*data == '.') { ++data; // Parse nanoseconds. - if ((data = ParseNanos(data, nanos)) == NULL) { + if ((data = ParseNanos(data, nanos)) == nullptr) { return false; } } else { @@ -342,14 +342,14 @@ bool ParseTime(const string& value, int64* seconds, int32* nanos) { } else if (*data == '+') { ++data; int64 offset; - if ((data = ParseTimezoneOffset(data, &offset)) == NULL) { + if ((data = ParseTimezoneOffset(data, &offset)) == nullptr) { return false; } *seconds -= offset; } else if (*data == '-') { ++data; int64 offset; - if ((data = ParseTimezoneOffset(data, &offset)) == NULL) { + if ((data = ParseTimezoneOffset(data, &offset)) == nullptr) { return false; } *seconds += offset; diff --git a/src/google/protobuf/stubs/time.h b/src/google/protobuf/stubs/time.h index 45607ca9bb8da..b06117689e58c 100644 --- a/src/google/protobuf/stubs/time.h +++ b/src/google/protobuf/stubs/time.h @@ -32,6 +32,8 @@ #include +#include + namespace google { namespace protobuf { namespace internal { @@ -49,27 +51,30 @@ struct DateTime { // negative to represent time before 1970-01-01) to DateTime. Returns false // if the timestamp is not in the range between 0001-01-01T00:00:00 and // 9999-12-31T23:59:59. -bool LIBPROTOBUF_EXPORT SecondsToDateTime(int64 seconds, DateTime* time); +bool PROTOBUF_EXPORT SecondsToDateTime(int64 seconds, DateTime* time); // Converts DateTime to a timestamp (seconds since 1970-01-01T00:00:00). // Returns false if the DateTime is not valid or is not in the valid range. -bool LIBPROTOBUF_EXPORT DateTimeToSeconds(const DateTime& time, int64* seconds); +bool PROTOBUF_EXPORT DateTimeToSeconds(const DateTime& time, int64* seconds); -void LIBPROTOBUF_EXPORT GetCurrentTime(int64* seconds, int32* nanos); +void PROTOBUF_EXPORT GetCurrentTime(int64* seconds, int32* nanos); -// Formats a time string in RFC3339 fromat. +// Formats a time string in RFC3339 format. // // For example, "2015-05-20T13:29:35.120Z". For nanos, 0, 3, 6 or 9 fractional // digits will be used depending on how many are required to represent the exact // value. // // Note that "nanos" must in the range of [0, 999999999]. -string LIBPROTOBUF_EXPORT FormatTime(int64 seconds, int32 nanos); +std::string PROTOBUF_EXPORT FormatTime(int64 seconds, int32 nanos); // Parses a time string. This method accepts RFC3339 date/time string with UTC // offset. For example, "2015-05-20T13:29:35.120-08:00". -bool LIBPROTOBUF_EXPORT ParseTime(const string& value, int64* seconds, int32* nanos); +bool PROTOBUF_EXPORT ParseTime(const std::string& value, int64* seconds, + int32* nanos); } // namespace internal } // namespace protobuf } // namespace google +#include + #endif // GOOGLE_PROTOBUF_STUBS_TIME_H_ diff --git a/src/google/protobuf/stubs/time_test.cc b/src/google/protobuf/stubs/time_test.cc index 59e9d1c73cfd7..1ce0a1c130f77 100644 --- a/src/google/protobuf/stubs/time_test.cc +++ b/src/google/protobuf/stubs/time_test.cc @@ -38,7 +38,7 @@ namespace internal { namespace { static const int64 kSecondsPerDay = 3600 * 24; -// For DateTime, tests will mostly focuse on the date part because that's +// For DateTime, tests will mostly focus on the date part because that's // the tricky one. int64 CreateTimestamp(int year, int month, int day) { DateTime time; @@ -149,6 +149,59 @@ TEST(DateTimeTest, LeapYear) { CreateTimestamp(2400, 3, 1) - CreateTimestamp(2400, 2, 29)); } +TEST(DateTimeTest, WrongDays) { + int64 seconds; + DateTime time; + time.hour = 0; + time.minute = 0; + time.second = 0; + time.month = 2; + + // Non-leap year. + time.year = 2015; + time.day = 29; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); + + // Leap year. + time.year = 2016; + time.day = 29; + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + time.day = 30; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); + + // Non-leap year. + time.year = 2100; + time.day = 29; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); + + // Leap year. + time.year = 2400; + time.day = 29; + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + time.day = 30; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); + + // Non-february + time.year = 2015; + time.month = 1; + time.day = 0; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); + time.day = 1; + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + time.day = 31; + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + time.day = 32; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); + + // Bad month + time.year = 2015; + time.month = 0; + time.day = 1; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); + time.month = 13; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); +} + TEST(DateTimeTest, StringFormat) { DateTime start, end; start.year = 1; @@ -170,7 +223,7 @@ TEST(DateTimeTest, StringFormat) { EXPECT_EQ("0001-01-01T00:00:00Z", FormatTime(start_time, 0)); EXPECT_EQ("9999-12-31T23:59:59Z", FormatTime(end_time, 0)); - // Make sure the nanoseconds part is formated correctly. + // Make sure the nanoseconds part is formatted correctly. EXPECT_EQ("1970-01-01T00:00:00.010Z", FormatTime(0, 10000000)); EXPECT_EQ("1970-01-01T00:00:00.000010Z", FormatTime(0, 10000)); EXPECT_EQ("1970-01-01T00:00:00.000000010Z", FormatTime(0, 10)); diff --git a/src/google/protobuf/stubs/type_traits.h b/src/google/protobuf/stubs/type_traits.h deleted file mode 100644 index 3ab5ea7d4eab5..0000000000000 --- a/src/google/protobuf/stubs/type_traits.h +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// ---- -// Author: Matt Austern -// -// This code is compiled directly on many platforms, including client -// platforms like Windows, Mac, and embedded systems. Before making -// any changes here, make sure that you're not breaking any platforms. -// -// Define a small subset of tr1 type traits. The traits we define are: -// enable_if -// is_integral -// is_floating_point -// is_pointer -// is_enum -// is_reference -// is_pod -// has_trivial_constructor -// has_trivial_copy -// has_trivial_assign -// has_trivial_destructor -// remove_const -// remove_volatile -// remove_cv -// remove_reference -// add_reference -// remove_pointer -// is_same -// is_convertible -// We can add more type traits as required. - -#ifndef GOOGLE_PROTOBUF_TYPE_TRAITS_H_ -#define GOOGLE_PROTOBUF_TYPE_TRAITS_H_ - -#include // for NULL -#include // For pair - -#include // For true_type and false_type - -namespace google { -namespace protobuf { -namespace internal { - -template -struct is_base_of { - typedef char (&yes)[1]; - typedef char (&no)[2]; - - // BEGIN GOOGLE LOCAL MODIFICATION -- check is a #define on Mac. - #undef check - // END GOOGLE LOCAL MODIFICATION - - static yes check(const B*); - static no check(const void*); - - enum { - value = sizeof(check(static_cast(NULL))) == sizeof(yes), - }; -}; - -template struct enable_if; -template struct is_integral; -template struct is_floating_point; -template struct is_pointer; -// MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least) -#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) -// is_enum uses is_convertible, which is not available on MSVC. -template struct is_enum; -#endif -template struct is_reference; -template struct is_pod; -template struct has_trivial_constructor; -template struct has_trivial_copy; -template struct has_trivial_assign; -template struct has_trivial_destructor; -template struct remove_const; -template struct remove_volatile; -template struct remove_cv; -template struct remove_reference; -template struct add_reference; -template struct remove_pointer; -template struct is_same; -#if !(defined(__GNUC__) && __GNUC__ <= 3) -template struct is_convertible; -#endif - -// enable_if, equivalent semantics to c++11 std::enable_if, specifically: -// "If B is true, the member typedef type shall equal T; otherwise, there -// shall be no member typedef type." -// Specified by 20.9.7.6 [Other transformations] - -template struct enable_if { typedef T type; }; -template struct enable_if {}; -// is_integral is false except for the built-in integer types. A -// cv-qualified type is integral if and only if the underlying type is. -template struct is_integral : false_type { }; -template<> struct is_integral : true_type { }; -template<> struct is_integral : true_type { }; -template<> struct is_integral : true_type { }; -template<> struct is_integral : true_type { }; -#if defined(_MSC_VER) -// wchar_t is not by default a distinct type from unsigned short in -// Microsoft C. -// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx -template<> struct is_integral<__wchar_t> : true_type { }; -#else -template<> struct is_integral : true_type { }; -#endif -template<> struct is_integral : true_type { }; -template<> struct is_integral : true_type { }; -template<> struct is_integral : true_type { }; -template<> struct is_integral : true_type { }; -template<> struct is_integral : true_type { }; -template<> struct is_integral : true_type { }; -#if defined(HAVE_LONG_LONG) || defined(_MSC_VER) -template<> struct is_integral : true_type { }; -template<> struct is_integral : true_type { }; -#endif -template struct is_integral : is_integral { }; -template struct is_integral : is_integral { }; -template struct is_integral : is_integral { }; - -// is_floating_point is false except for the built-in floating-point types. -// A cv-qualified type is integral if and only if the underlying type is. -template struct is_floating_point : false_type { }; -template<> struct is_floating_point : true_type { }; -template<> struct is_floating_point : true_type { }; -template<> struct is_floating_point : true_type { }; -template struct is_floating_point - : is_floating_point { }; -template struct is_floating_point - : is_floating_point { }; -template struct is_floating_point - : is_floating_point { }; - -// is_pointer is false except for pointer types. A cv-qualified type (e.g. -// "int* const", as opposed to "int const*") is cv-qualified if and only if -// the underlying type is. -template struct is_pointer : false_type { }; -template struct is_pointer : true_type { }; -template struct is_pointer : is_pointer { }; -template struct is_pointer : is_pointer { }; -template struct is_pointer : is_pointer { }; - -#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) - -namespace type_traits_internal { - -template struct is_class_or_union { - template static small_ tester(void (U::*)()); - template static big_ tester(...); - static const bool value = sizeof(tester(0)) == sizeof(small_); -}; - -// is_convertible chokes if the first argument is an array. That's why -// we use add_reference here. -template struct is_enum_impl - : is_convertible::type, int> { }; - -template struct is_enum_impl : false_type { }; - -} // namespace type_traits_internal - -// Specified by TR1 [4.5.1] primary type categories. - -// Implementation note: -// -// Each type is either void, integral, floating point, array, pointer, -// reference, member object pointer, member function pointer, enum, -// union or class. Out of these, only integral, floating point, reference, -// class and enum types are potentially convertible to int. Therefore, -// if a type is not a reference, integral, floating point or class and -// is convertible to int, it's a enum. Adding cv-qualification to a type -// does not change whether it's an enum. -// -// Is-convertible-to-int check is done only if all other checks pass, -// because it can't be used with some types (e.g. void or classes with -// inaccessible conversion operators). -template struct is_enum - : type_traits_internal::is_enum_impl< - is_same::value || - is_integral::value || - is_floating_point::value || - is_reference::value || - type_traits_internal::is_class_or_union::value, - T> { }; - -template struct is_enum : is_enum { }; -template struct is_enum : is_enum { }; -template struct is_enum : is_enum { }; - -#endif - -// is_reference is false except for reference types. -template struct is_reference : false_type {}; -template struct is_reference : true_type {}; - - -// We can't get is_pod right without compiler help, so fail conservatively. -// We will assume it's false except for arithmetic types, enumerations, -// pointers and cv-qualified versions thereof. Note that std::pair -// is not a POD even if T and U are PODs. -template struct is_pod - : integral_constant::value || - is_floating_point::value || -#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) - // is_enum is not available on MSVC. - is_enum::value || -#endif - is_pointer::value)> { }; -template struct is_pod : is_pod { }; -template struct is_pod : is_pod { }; -template struct is_pod : is_pod { }; - - -// We can't get has_trivial_constructor right without compiler help, so -// fail conservatively. We will assume it's false except for: (1) types -// for which is_pod is true. (2) std::pair of types with trivial -// constructors. (3) array of a type with a trivial constructor. -// (4) const versions thereof. -template struct has_trivial_constructor : is_pod { }; -template struct has_trivial_constructor > - : integral_constant::value && - has_trivial_constructor::value)> { }; -template struct has_trivial_constructor - : has_trivial_constructor { }; -template struct has_trivial_constructor - : has_trivial_constructor { }; - -// We can't get has_trivial_copy right without compiler help, so fail -// conservatively. We will assume it's false except for: (1) types -// for which is_pod is true. (2) std::pair of types with trivial copy -// constructors. (3) array of a type with a trivial copy constructor. -// (4) const versions thereof. -template struct has_trivial_copy : is_pod { }; -template struct has_trivial_copy > - : integral_constant::value && - has_trivial_copy::value)> { }; -template struct has_trivial_copy - : has_trivial_copy { }; -template struct has_trivial_copy : has_trivial_copy { }; - -// We can't get has_trivial_assign right without compiler help, so fail -// conservatively. We will assume it's false except for: (1) types -// for which is_pod is true. (2) std::pair of types with trivial copy -// constructors. (3) array of a type with a trivial assign constructor. -template struct has_trivial_assign : is_pod { }; -template struct has_trivial_assign > - : integral_constant::value && - has_trivial_assign::value)> { }; -template struct has_trivial_assign - : has_trivial_assign { }; - -// We can't get has_trivial_destructor right without compiler help, so -// fail conservatively. We will assume it's false except for: (1) types -// for which is_pod is true. (2) std::pair of types with trivial -// destructors. (3) array of a type with a trivial destructor. -// (4) const versions thereof. -template struct has_trivial_destructor : is_pod { }; -template struct has_trivial_destructor > - : integral_constant::value && - has_trivial_destructor::value)> { }; -template struct has_trivial_destructor - : has_trivial_destructor { }; -template struct has_trivial_destructor - : has_trivial_destructor { }; - -// Specified by TR1 [4.7.1] -template struct remove_const { typedef T type; }; -template struct remove_const { typedef T type; }; -template struct remove_volatile { typedef T type; }; -template struct remove_volatile { typedef T type; }; -template struct remove_cv { - typedef typename remove_const::type>::type type; -}; - - -// Specified by TR1 [4.7.2] Reference modifications. -template struct remove_reference { typedef T type; }; -template struct remove_reference { typedef T type; }; - -template struct add_reference { typedef T& type; }; -template struct add_reference { typedef T& type; }; - -// Specified by TR1 [4.7.4] Pointer modifications. -template struct remove_pointer { typedef T type; }; -template struct remove_pointer { typedef T type; }; -template struct remove_pointer { typedef T type; }; -template struct remove_pointer { typedef T type; }; -template struct remove_pointer { - typedef T type; }; - -// Specified by TR1 [4.6] Relationships between types -template struct is_same : public false_type { }; -template struct is_same : public true_type { }; - -// Specified by TR1 [4.6] Relationships between types -#if !(defined(__GNUC__) && __GNUC__ <= 3) -namespace type_traits_internal { - -// This class is an implementation detail for is_convertible, and you -// don't need to know how it works to use is_convertible. For those -// who care: we declare two different functions, one whose argument is -// of type To and one with a variadic argument list. We give them -// return types of different size, so we can use sizeof to trick the -// compiler into telling us which function it would have chosen if we -// had called it with an argument of type From. See Alexandrescu's -// _Modern C++ Design_ for more details on this sort of trick. - -template -struct ConvertHelper { - static small_ Test(To); - static big_ Test(...); - static From Create(); - enum { - value = sizeof(Test(Create())) == sizeof(small_) - }; -}; -} // namespace type_traits_internal - -// Inherits from true_type if From is convertible to To, false_type otherwise. -template -struct is_convertible - : integral_constant::value> { -}; -#endif - -} // namespace internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_TYPE_TRAITS_H_ diff --git a/src/google/protobuf/stubs/type_traits_unittest.cc b/src/google/protobuf/stubs/type_traits_unittest.cc deleted file mode 100644 index 49c10aced6205..0000000000000 --- a/src/google/protobuf/stubs/type_traits_unittest.cc +++ /dev/null @@ -1,631 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// ---- -// Author: Matt Austern - -#include - -#include // for exit() -#include -#include -#include - -#include -#include - -typedef int int32; -// IBM AIX typedefs `int64` in `sys/inttypes.h`, included transitively above. -#ifndef _AIX -typedef long int64; -#endif - -using std::string; -using std::vector; -using std::pair; - - -// This assertion produces errors like "error: invalid use of -// incomplete type 'struct ::AssertTypesEq'" -// when it fails. -template struct AssertTypesEq; -template struct AssertTypesEq {}; -#define COMPILE_ASSERT_TYPES_EQ(T, U) static_cast(AssertTypesEq()) - -// A user-defined POD type. -struct A { - int n_; -}; - -// A user-defined non-POD type with a trivial copy constructor. -class B { - public: - explicit B(int n) : n_(n) { } - private: - int n_; -}; - -// Another user-defined non-POD type with a trivial copy constructor. -// We will explicitly declare C to have a trivial copy constructor -// by specializing has_trivial_copy. -class C { - public: - explicit C(int n) : n_(n) { } - private: - int n_; -}; - -namespace google { -namespace protobuf { -namespace internal { -template<> struct has_trivial_copy : true_type { }; -} // namespace internal -} // namespace protobuf -} // namespace google - -// Another user-defined non-POD type with a trivial assignment operator. -// We will explicitly declare C to have a trivial assignment operator -// by specializing has_trivial_assign. -class D { - public: - explicit D(int n) : n_(n) { } - private: - int n_; -}; - -namespace google { -namespace protobuf { -namespace internal { -template<> struct has_trivial_assign : true_type { }; -} // namespace internal -} // namespace protobuf -} // namespace google - -// Another user-defined non-POD type with a trivial constructor. -// We will explicitly declare E to have a trivial constructor -// by specializing has_trivial_constructor. -class E { - public: - int n_; -}; - -namespace google { -namespace protobuf { -namespace internal { -template<> struct has_trivial_constructor : true_type { }; -} // namespace internal -} // namespace protobuf -} // namespace google - -// Another user-defined non-POD type with a trivial destructor. -// We will explicitly declare E to have a trivial destructor -// by specializing has_trivial_destructor. -class F { - public: - explicit F(int n) : n_(n) { } - private: - int n_; -}; - -namespace google { -namespace protobuf { -namespace internal { -template<> struct has_trivial_destructor : true_type { }; -} // namespace internal -} // namespace protobuf -} // namespace google - -enum G {}; - -union H {}; - -class I { - public: - operator int() const; -}; - -class J { - private: - operator int() const; -}; - -namespace google { -namespace protobuf { -namespace internal { -namespace { - -// A base class and a derived class that inherits from it, used for -// testing conversion type traits. -class Base { - public: - virtual ~Base() { } -}; - -class Derived : public Base { -}; - -TEST(TypeTraitsTest, TestIsInteger) { - // Verify that is_integral is true for all integer types. - EXPECT_TRUE(is_integral::value); - EXPECT_TRUE(is_integral::value); - EXPECT_TRUE(is_integral::value); - EXPECT_TRUE(is_integral::value); - EXPECT_TRUE(is_integral::value); - EXPECT_TRUE(is_integral::value); - EXPECT_TRUE(is_integral::value); - EXPECT_TRUE(is_integral::value); - EXPECT_TRUE(is_integral::value); - EXPECT_TRUE(is_integral::value); - EXPECT_TRUE(is_integral::value); - - // Verify that is_integral is false for a few non-integer types. - EXPECT_FALSE(is_integral::value); - EXPECT_FALSE(is_integral::value); - EXPECT_FALSE(is_integral::value); - EXPECT_FALSE(is_integral::value); - EXPECT_FALSE(is_integral::value); - EXPECT_FALSE((is_integral >::value)); - - // Verify that cv-qualified integral types are still integral, and - // cv-qualified non-integral types are still non-integral. - EXPECT_TRUE(is_integral::value); - EXPECT_TRUE(is_integral::value); - EXPECT_TRUE(is_integral::value); - EXPECT_FALSE(is_integral::value); - EXPECT_FALSE(is_integral::value); - EXPECT_FALSE(is_integral::value); -} - -TEST(TypeTraitsTest, TestIsFloating) { - // Verify that is_floating_point is true for all floating-point types. - EXPECT_TRUE(is_floating_point::value); - EXPECT_TRUE(is_floating_point::value); - EXPECT_TRUE(is_floating_point::value); - - // Verify that is_floating_point is false for a few non-float types. - EXPECT_FALSE(is_floating_point::value); - EXPECT_FALSE(is_floating_point::value); - EXPECT_FALSE(is_floating_point::value); - EXPECT_FALSE(is_floating_point::value); - EXPECT_FALSE(is_floating_point::value); - EXPECT_FALSE((is_floating_point >::value)); - - // Verify that cv-qualified floating point types are still floating, and - // cv-qualified non-floating types are still non-floating. - EXPECT_TRUE(is_floating_point::value); - EXPECT_TRUE(is_floating_point::value); - EXPECT_TRUE(is_floating_point::value); - EXPECT_FALSE(is_floating_point::value); - EXPECT_FALSE(is_floating_point::value); - EXPECT_FALSE(is_floating_point::value); -} - -TEST(TypeTraitsTest, TestIsPointer) { - // Verify that is_pointer is true for some pointer types. - EXPECT_TRUE(is_pointer::value); - EXPECT_TRUE(is_pointer::value); - EXPECT_TRUE(is_pointer::value); - EXPECT_TRUE(is_pointer::value); - EXPECT_TRUE(is_pointer::value); - - // Verify that is_pointer is false for some non-pointer types. - EXPECT_FALSE(is_pointer::value); - EXPECT_FALSE(is_pointer::value); - EXPECT_FALSE(is_pointer::value); - EXPECT_FALSE(is_pointer >::value); - EXPECT_FALSE(is_pointer::value); - - // A function pointer is a pointer, but a function type, or a function - // reference type, is not. - EXPECT_TRUE(is_pointer::value); - EXPECT_FALSE(is_pointer::value); - EXPECT_FALSE(is_pointer::value); - - // Verify that is_pointer is true for some cv-qualified pointer types, - // and false for some cv-qualified non-pointer types. - EXPECT_TRUE(is_pointer::value); - EXPECT_TRUE(is_pointer::value); - EXPECT_TRUE(is_pointer::value); - EXPECT_FALSE(is_pointer::value); - EXPECT_FALSE(is_pointer >::value); - EXPECT_FALSE(is_pointer::value); -} - -TEST(TypeTraitsTest, TestIsEnum) { -// is_enum isn't supported on MSVC or gcc 3.x -#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) - // Verify that is_enum is true for enum types. - EXPECT_TRUE(is_enum::value); - EXPECT_TRUE(is_enum::value); - EXPECT_TRUE(is_enum::value); - EXPECT_TRUE(is_enum::value); - - // Verify that is_enum is false for a few non-enum types. - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); - EXPECT_FALSE(is_enum::value); -#endif -} - -TEST(TypeTraitsTest, TestIsReference) { - // Verifies that is_reference is true for all reference types. - typedef float& RefFloat; - EXPECT_TRUE(is_reference::value); - EXPECT_TRUE(is_reference::value); - EXPECT_TRUE(is_reference::value); - EXPECT_TRUE(is_reference::value); - EXPECT_TRUE(is_reference::value); - EXPECT_TRUE(is_reference::value); - EXPECT_TRUE(is_reference::value); - EXPECT_TRUE(is_reference::value); - - - // Verifies that is_reference is false for all non-reference types. - EXPECT_FALSE(is_reference::value); - EXPECT_FALSE(is_reference::value); - EXPECT_FALSE(is_reference::value); - EXPECT_FALSE(is_reference::value); - EXPECT_FALSE(is_reference::value); - EXPECT_FALSE(is_reference::value); - EXPECT_FALSE(is_reference::value); -} - -TEST(TypeTraitsTest, TestAddReference) { - COMPILE_ASSERT_TYPES_EQ(int&, add_reference::type); - COMPILE_ASSERT_TYPES_EQ(const int&, add_reference::type); - COMPILE_ASSERT_TYPES_EQ(volatile int&, - add_reference::type); - COMPILE_ASSERT_TYPES_EQ(const volatile int&, - add_reference::type); - COMPILE_ASSERT_TYPES_EQ(int&, add_reference::type); - COMPILE_ASSERT_TYPES_EQ(const int&, add_reference::type); - COMPILE_ASSERT_TYPES_EQ(volatile int&, - add_reference::type); - COMPILE_ASSERT_TYPES_EQ(const volatile int&, - add_reference::type); -} - -TEST(TypeTraitsTest, TestIsPod) { - // Verify that arithmetic types and pointers are marked as PODs. - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); -#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); - EXPECT_TRUE(is_pod::value); -#endif - - // Verify that some non-POD types are not marked as PODs. - EXPECT_FALSE(is_pod::value); - EXPECT_FALSE(is_pod::value); - EXPECT_FALSE((is_pod >::value)); - EXPECT_FALSE(is_pod::value); - EXPECT_FALSE(is_pod::value); - EXPECT_FALSE(is_pod::value); - EXPECT_FALSE(is_pod::value); - EXPECT_FALSE(is_pod::value); - EXPECT_FALSE(is_pod::value); -} - -TEST(TypeTraitsTest, TestHasTrivialConstructor) { - // Verify that arithmetic types and pointers have trivial constructors. - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - EXPECT_TRUE(has_trivial_constructor::value); - - // Verify that pairs and arrays of such types have trivial - // constructors. - typedef int int10[10]; - EXPECT_TRUE((has_trivial_constructor >::value)); - EXPECT_TRUE(has_trivial_constructor::value); - - // Verify that pairs of types without trivial constructors - // are not marked as trivial. - EXPECT_FALSE((has_trivial_constructor >::value)); - EXPECT_FALSE((has_trivial_constructor >::value)); - - // Verify that types without trivial constructors are - // correctly marked as such. - EXPECT_FALSE(has_trivial_constructor::value); - EXPECT_FALSE(has_trivial_constructor >::value); - - // Verify that E, which we have declared to have a trivial - // constructor, is correctly marked as such. - EXPECT_TRUE(has_trivial_constructor::value); -} - -TEST(TypeTraitsTest, TestHasTrivialCopy) { - // Verify that arithmetic types and pointers have trivial copy - // constructors. - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - EXPECT_TRUE(has_trivial_copy::value); - - // Verify that pairs and arrays of such types have trivial - // copy constructors. - typedef int int10[10]; - EXPECT_TRUE((has_trivial_copy >::value)); - EXPECT_TRUE(has_trivial_copy::value); - - // Verify that pairs of types without trivial copy constructors - // are not marked as trivial. - EXPECT_FALSE((has_trivial_copy >::value)); - EXPECT_FALSE((has_trivial_copy >::value)); - - // Verify that types without trivial copy constructors are - // correctly marked as such. - EXPECT_FALSE(has_trivial_copy::value); - EXPECT_FALSE(has_trivial_copy >::value); - - // Verify that C, which we have declared to have a trivial - // copy constructor, is correctly marked as such. - EXPECT_TRUE(has_trivial_copy::value); -} - -TEST(TypeTraitsTest, TestHasTrivialAssign) { - // Verify that arithmetic types and pointers have trivial assignment - // operators. - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - EXPECT_TRUE(has_trivial_assign::value); - - // Verify that pairs and arrays of such types have trivial - // assignment operators. - typedef int int10[10]; - EXPECT_TRUE((has_trivial_assign >::value)); - EXPECT_TRUE(has_trivial_assign::value); - - // Verify that pairs of types without trivial assignment operators - // are not marked as trivial. - EXPECT_FALSE((has_trivial_assign >::value)); - EXPECT_FALSE((has_trivial_assign >::value)); - - // Verify that types without trivial assignment operators are - // correctly marked as such. - EXPECT_FALSE(has_trivial_assign::value); - EXPECT_FALSE(has_trivial_assign >::value); - - // Verify that D, which we have declared to have a trivial - // assignment operator, is correctly marked as such. - EXPECT_TRUE(has_trivial_assign::value); -} - -TEST(TypeTraitsTest, TestHasTrivialDestructor) { - // Verify that arithmetic types and pointers have trivial destructors. - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - EXPECT_TRUE(has_trivial_destructor::value); - - // Verify that pairs and arrays of such types have trivial - // destructors. - typedef int int10[10]; - EXPECT_TRUE((has_trivial_destructor >::value)); - EXPECT_TRUE(has_trivial_destructor::value); - - // Verify that pairs of types without trivial destructors - // are not marked as trivial. - EXPECT_FALSE((has_trivial_destructor >::value)); - EXPECT_FALSE((has_trivial_destructor >::value)); - - // Verify that types without trivial destructors are - // correctly marked as such. - EXPECT_FALSE(has_trivial_destructor::value); - EXPECT_FALSE(has_trivial_destructor >::value); - - // Verify that F, which we have declared to have a trivial - // destructor, is correctly marked as such. - EXPECT_TRUE(has_trivial_destructor::value); -} - -// Tests remove_pointer. -TEST(TypeTraitsTest, TestRemovePointer) { - COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); - COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); - COMPILE_ASSERT_TYPES_EQ(const int, remove_pointer::type); - COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); - COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); -} - -TEST(TypeTraitsTest, TestRemoveConst) { - COMPILE_ASSERT_TYPES_EQ(int, remove_const::type); - COMPILE_ASSERT_TYPES_EQ(int, remove_const::type); - COMPILE_ASSERT_TYPES_EQ(int *, remove_const::type); - // TR1 examples. - COMPILE_ASSERT_TYPES_EQ(const int *, remove_const::type); - COMPILE_ASSERT_TYPES_EQ(volatile int, - remove_const::type); -} - -TEST(TypeTraitsTest, TestRemoveVolatile) { - COMPILE_ASSERT_TYPES_EQ(int, remove_volatile::type); - COMPILE_ASSERT_TYPES_EQ(int, remove_volatile::type); - COMPILE_ASSERT_TYPES_EQ(int *, remove_volatile::type); - // TR1 examples. - COMPILE_ASSERT_TYPES_EQ(volatile int *, - remove_volatile::type); - COMPILE_ASSERT_TYPES_EQ(const int, - remove_volatile::type); -} - -TEST(TypeTraitsTest, TestRemoveCV) { - COMPILE_ASSERT_TYPES_EQ(int, remove_cv::type); - COMPILE_ASSERT_TYPES_EQ(int, remove_cv::type); - COMPILE_ASSERT_TYPES_EQ(int, remove_cv::type); - COMPILE_ASSERT_TYPES_EQ(int *, remove_cv::type); - // TR1 examples. - COMPILE_ASSERT_TYPES_EQ(const volatile int *, - remove_cv::type); - COMPILE_ASSERT_TYPES_EQ(int, - remove_cv::type); -} - -TEST(TypeTraitsTest, TestRemoveReference) { - COMPILE_ASSERT_TYPES_EQ(int, remove_reference::type); - COMPILE_ASSERT_TYPES_EQ(int, remove_reference::type); - COMPILE_ASSERT_TYPES_EQ(const int, remove_reference::type); - COMPILE_ASSERT_TYPES_EQ(int*, remove_reference::type); -} - -TEST(TypeTraitsTest, TestIsSame) { - EXPECT_TRUE((is_same::value)); - EXPECT_FALSE((is_same::value)); - EXPECT_FALSE((is_same::value)); - EXPECT_FALSE((is_same::value)); - - EXPECT_TRUE((is_same::value)); - EXPECT_FALSE((is_same::value)); - EXPECT_FALSE((is_same::value)); - - EXPECT_TRUE((is_same::value)); - EXPECT_TRUE((is_same::value)); - EXPECT_FALSE((is_same::value)); - EXPECT_FALSE((is_same::value)); - EXPECT_FALSE((is_same::value)); - EXPECT_FALSE((is_same::value)); - - EXPECT_TRUE((is_same::value)); - EXPECT_TRUE((is_same::value)); - EXPECT_FALSE((is_same::value)); - EXPECT_FALSE((is_same::value)); -} - -TEST(TypeTraitsTest, TestConvertible) { -#if !(defined(__GNUC__) && __GNUC__ <= 3) - EXPECT_TRUE((is_convertible::value)); - EXPECT_TRUE((is_convertible::value)); - EXPECT_TRUE((is_convertible::value)); - - EXPECT_TRUE((is_convertible::value)); - EXPECT_FALSE((is_convertible::value)); - - EXPECT_TRUE((is_convertible::value)); - EXPECT_FALSE((is_convertible::value)); - EXPECT_TRUE((is_convertible::value)); - EXPECT_FALSE((is_convertible::value)); -#endif -} - -} // anonymous namespace -} // namespace internal -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/test_messages_proto2.proto b/src/google/protobuf/test_messages_proto2.proto index cbe0d17085d02..1d0c33f566eb7 100644 --- a/src/google/protobuf/test_messages_proto2.proto +++ b/src/google/protobuf/test_messages_proto2.proto @@ -33,9 +33,12 @@ // - conformance tests // +// LINT: ALLOW_GROUPS + syntax = "proto2"; package protobuf_test_messages.proto2; + option java_package = "com.google.protobuf_test_messages.proto2"; // This is the default, but we specify it here explicitly. @@ -64,79 +67,111 @@ message TestAllTypesProto2 { } // 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 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 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 NestedMessage optional_nested_message = 18; - optional ForeignMessage optional_foreign_message = 19; + optional NestedMessage optional_nested_message = 18; + optional ForeignMessageProto2 optional_foreign_message = 19; - optional NestedEnum optional_nested_enum = 21; - optional ForeignEnum optional_foreign_enum = 22; + optional NestedEnum optional_nested_enum = 21; + optional ForeignEnumProto2 optional_foreign_enum = 22; - optional string optional_string_piece = 24 [ctype=STRING_PIECE]; - optional string optional_cord = 25 [ctype=CORD]; + optional string optional_string_piece = 24 [ctype = STRING_PIECE]; + optional string optional_cord = 25 [ctype = CORD]; optional TestAllTypesProto2 recursive_message = 27; // Repeated - repeated int32 repeated_int32 = 31; - repeated int64 repeated_int64 = 32; - repeated uint32 repeated_uint32 = 33; - repeated uint64 repeated_uint64 = 34; - repeated sint32 repeated_sint32 = 35; - repeated sint64 repeated_sint64 = 36; - repeated fixed32 repeated_fixed32 = 37; - repeated fixed64 repeated_fixed64 = 38; + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; repeated sfixed32 repeated_sfixed32 = 39; repeated sfixed64 repeated_sfixed64 = 40; - repeated float repeated_float = 41; - repeated double repeated_double = 42; - repeated bool repeated_bool = 43; - repeated string repeated_string = 44; - repeated bytes repeated_bytes = 45; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessageProto2 repeated_foreign_message = 49; - repeated NestedMessage repeated_nested_message = 48; - repeated ForeignMessage repeated_foreign_message = 49; + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnumProto2 repeated_foreign_enum = 52; - repeated NestedEnum repeated_nested_enum = 51; - repeated ForeignEnum repeated_foreign_enum = 52; + repeated string repeated_string_piece = 54 [ctype = STRING_PIECE]; + repeated string repeated_cord = 55 [ctype = CORD]; - repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; - repeated string repeated_cord = 55 [ctype=CORD]; + // Packed + repeated int32 packed_int32 = 75 [packed = true]; + repeated int64 packed_int64 = 76 [packed = true]; + repeated uint32 packed_uint32 = 77 [packed = true]; + repeated uint64 packed_uint64 = 78 [packed = true]; + repeated sint32 packed_sint32 = 79 [packed = true]; + repeated sint64 packed_sint64 = 80 [packed = true]; + repeated fixed32 packed_fixed32 = 81 [packed = true]; + repeated fixed64 packed_fixed64 = 82 [packed = true]; + repeated sfixed32 packed_sfixed32 = 83 [packed = true]; + repeated sfixed64 packed_sfixed64 = 84 [packed = true]; + repeated float packed_float = 85 [packed = true]; + repeated double packed_double = 86 [packed = true]; + repeated bool packed_bool = 87 [packed = true]; + repeated NestedEnum packed_nested_enum = 88 [packed = true]; + + // Unpacked + repeated int32 unpacked_int32 = 89 [packed = false]; + repeated int64 unpacked_int64 = 90 [packed = false]; + repeated uint32 unpacked_uint32 = 91 [packed = false]; + repeated uint64 unpacked_uint64 = 92 [packed = false]; + repeated sint32 unpacked_sint32 = 93 [packed = false]; + repeated sint64 unpacked_sint64 = 94 [packed = false]; + repeated fixed32 unpacked_fixed32 = 95 [packed = false]; + repeated fixed64 unpacked_fixed64 = 96 [packed = false]; + repeated sfixed32 unpacked_sfixed32 = 97 [packed = false]; + repeated sfixed64 unpacked_sfixed64 = 98 [packed = false]; + repeated float unpacked_float = 99 [packed = false]; + repeated double unpacked_double = 100 [packed = false]; + repeated bool unpacked_bool = 101 [packed = false]; + repeated NestedEnum unpacked_nested_enum = 102 [packed = false]; // Map - map < int32, int32> map_int32_int32 = 56; - map < int64, int64> map_int64_int64 = 57; - map < uint32, uint32> map_uint32_uint32 = 58; - map < uint64, uint64> map_uint64_uint64 = 59; - map < sint32, sint32> map_sint32_sint32 = 60; - map < sint64, sint64> map_sint64_sint64 = 61; - map < fixed32, fixed32> map_fixed32_fixed32 = 62; - map < fixed64, fixed64> map_fixed64_fixed64 = 63; - map map_sfixed32_sfixed32 = 64; - map map_sfixed64_sfixed64 = 65; - map < int32, float> map_int32_float = 66; - map < int32, double> map_int32_double = 67; - map < bool, bool> map_bool_bool = 68; - map < string, string> map_string_string = 69; - map < string, bytes> map_string_bytes = 70; - map < string, NestedMessage> map_string_nested_message = 71; - map < string, ForeignMessage> map_string_foreign_message = 72; - map < string, NestedEnum> map_string_nested_enum = 73; - map < string, ForeignEnum> map_string_foreign_enum = 74; + map map_int32_int32 = 56; + map map_int64_int64 = 57; + map map_uint32_uint32 = 58; + map map_uint64_uint64 = 59; + map map_sint32_sint32 = 60; + map map_sint64_sint64 = 61; + map map_fixed32_fixed32 = 62; + map map_fixed64_fixed64 = 63; + map map_sfixed32_sfixed32 = 64; + map map_sfixed64_sfixed64 = 65; + map map_int32_float = 66; + map map_int32_double = 67; + map map_bool_bool = 68; + map map_string_string = 69; + map map_string_bytes = 70; + map map_string_nested_message = 71; + map map_string_foreign_message = 72; + map map_string_nested_enum = 73; + map map_string_foreign_enum = 74; oneof oneof_field { uint32 oneof_uint32 = 111; @@ -157,7 +192,7 @@ message TestAllTypesProto2 { optional group Data = 201 { optional int32 group_int32 = 202; optional uint32 group_uint32 = 203; - }; + } // Test field-name-to-JSON-name convention. // (protobuf says names can be any valid C/C++ identifier.) @@ -180,9 +215,13 @@ message TestAllTypesProto2 { optional int32 field_name17__ = 417; optional int32 Field_name18__ = 418; + // Reserved for unknown fields test. + reserved 1000 to 9999; + // message_set test case. message MessageSetCorrect { option message_set_wire_format = true; + extensions 4 to max; } @@ -201,11 +240,11 @@ message TestAllTypesProto2 { } } -message ForeignMessage { +message ForeignMessageProto2 { optional int32 c = 1; } -enum ForeignEnum { +enum ForeignEnumProto2 { FOREIGN_FOO = 0; FOREIGN_BAR = 1; FOREIGN_BAZ = 2; @@ -214,3 +253,14 @@ enum ForeignEnum { extend TestAllTypesProto2 { optional int32 extension_int32 = 120; } + +message UnknownToTestAllTypes { + optional int32 optional_int32 = 1001; + optional string optional_string = 1002; + optional ForeignMessageProto2 nested_message = 1003; + optional group OptionalGroup = 1004 { + optional int32 a = 1; + } + optional bool optional_bool = 1006; + repeated int32 repeated_int32 = 1011; +} diff --git a/src/google/protobuf/test_messages_proto3.proto b/src/google/protobuf/test_messages_proto3.proto index 84b9da992204b..4e409dc900e38 100644 --- a/src/google/protobuf/test_messages_proto3.proto +++ b/src/google/protobuf/test_messages_proto3.proto @@ -38,6 +38,7 @@ syntax = "proto3"; package protobuf_test_messages.proto3; + option java_package = "com.google.protobuf_test_messages.proto3"; option objc_class_prefix = "Proto3"; @@ -73,80 +74,124 @@ message TestAllTypesProto3 { NEG = -1; // Intentionally negative. } + enum AliasedEnum { + option allow_alias = true; + + ALIAS_FOO = 0; + ALIAS_BAR = 1; + ALIAS_BAZ = 2; + QUX = 2; + qux = 2; + bAz = 2; + } + // Singular - int32 optional_int32 = 1; - int64 optional_int64 = 2; - uint32 optional_uint32 = 3; - uint64 optional_uint64 = 4; - sint32 optional_sint32 = 5; - sint64 optional_sint64 = 6; - fixed32 optional_fixed32 = 7; - fixed64 optional_fixed64 = 8; - sfixed32 optional_sfixed32 = 9; + 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; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; - NestedMessage optional_nested_message = 18; - ForeignMessage optional_foreign_message = 19; + NestedMessage optional_nested_message = 18; + ForeignMessage optional_foreign_message = 19; - NestedEnum optional_nested_enum = 21; - ForeignEnum optional_foreign_enum = 22; + NestedEnum optional_nested_enum = 21; + ForeignEnum optional_foreign_enum = 22; + AliasedEnum optional_aliased_enum = 23; - string optional_string_piece = 24 [ctype=STRING_PIECE]; - string optional_cord = 25 [ctype=CORD]; + string optional_string_piece = 24 [ctype = STRING_PIECE]; + string optional_cord = 25 [ctype = CORD]; TestAllTypesProto3 recursive_message = 27; // Repeated - repeated int32 repeated_int32 = 31; - repeated int64 repeated_int64 = 32; - repeated uint32 repeated_uint32 = 33; - repeated uint64 repeated_uint64 = 34; - repeated sint32 repeated_sint32 = 35; - repeated sint64 repeated_sint64 = 36; - repeated fixed32 repeated_fixed32 = 37; - repeated fixed64 repeated_fixed64 = 38; + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; repeated sfixed32 repeated_sfixed32 = 39; repeated sfixed64 repeated_sfixed64 = 40; - repeated float repeated_float = 41; - repeated double repeated_double = 42; - repeated bool repeated_bool = 43; - repeated string repeated_string = 44; - repeated bytes repeated_bytes = 45; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; - repeated NestedMessage repeated_nested_message = 48; - repeated ForeignMessage repeated_foreign_message = 49; + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; - repeated NestedEnum repeated_nested_enum = 51; - repeated ForeignEnum repeated_foreign_enum = 52; + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; - repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; - repeated string repeated_cord = 55 [ctype=CORD]; + repeated string repeated_string_piece = 54 [ctype = STRING_PIECE]; + repeated string repeated_cord = 55 [ctype = CORD]; + + // Packed + repeated int32 packed_int32 = 75 [packed = true]; + repeated int64 packed_int64 = 76 [packed = true]; + repeated uint32 packed_uint32 = 77 [packed = true]; + repeated uint64 packed_uint64 = 78 [packed = true]; + repeated sint32 packed_sint32 = 79 [packed = true]; + repeated sint64 packed_sint64 = 80 [packed = true]; + repeated fixed32 packed_fixed32 = 81 [packed = true]; + repeated fixed64 packed_fixed64 = 82 [packed = true]; + repeated sfixed32 packed_sfixed32 = 83 [packed = true]; + repeated sfixed64 packed_sfixed64 = 84 [packed = true]; + repeated float packed_float = 85 [packed = true]; + repeated double packed_double = 86 [packed = true]; + repeated bool packed_bool = 87 [packed = true]; + repeated NestedEnum packed_nested_enum = 88 [packed = true]; + + // Unpacked + repeated int32 unpacked_int32 = 89 [packed = false]; + repeated int64 unpacked_int64 = 90 [packed = false]; + repeated uint32 unpacked_uint32 = 91 [packed = false]; + repeated uint64 unpacked_uint64 = 92 [packed = false]; + repeated sint32 unpacked_sint32 = 93 [packed = false]; + repeated sint64 unpacked_sint64 = 94 [packed = false]; + repeated fixed32 unpacked_fixed32 = 95 [packed = false]; + repeated fixed64 unpacked_fixed64 = 96 [packed = false]; + repeated sfixed32 unpacked_sfixed32 = 97 [packed = false]; + repeated sfixed64 unpacked_sfixed64 = 98 [packed = false]; + repeated float unpacked_float = 99 [packed = false]; + repeated double unpacked_double = 100 [packed = false]; + repeated bool unpacked_bool = 101 [packed = false]; + repeated NestedEnum unpacked_nested_enum = 102 [packed = false]; // Map - map < int32, int32> map_int32_int32 = 56; - map < int64, int64> map_int64_int64 = 57; - map < uint32, uint32> map_uint32_uint32 = 58; - map < uint64, uint64> map_uint64_uint64 = 59; - map < sint32, sint32> map_sint32_sint32 = 60; - map < sint64, sint64> map_sint64_sint64 = 61; - map < fixed32, fixed32> map_fixed32_fixed32 = 62; - map < fixed64, fixed64> map_fixed64_fixed64 = 63; - map map_sfixed32_sfixed32 = 64; - map map_sfixed64_sfixed64 = 65; - map < int32, float> map_int32_float = 66; - map < int32, double> map_int32_double = 67; - map < bool, bool> map_bool_bool = 68; - map < string, string> map_string_string = 69; - map < string, bytes> map_string_bytes = 70; - map < string, NestedMessage> map_string_nested_message = 71; - map < string, ForeignMessage> map_string_foreign_message = 72; - map < string, NestedEnum> map_string_nested_enum = 73; - map < string, ForeignEnum> map_string_foreign_enum = 74; + map map_int32_int32 = 56; + map map_int64_int64 = 57; + map map_uint32_uint32 = 58; + map map_uint64_uint64 = 59; + map map_sint32_sint32 = 60; + map map_sint64_sint64 = 61; + map map_fixed32_fixed32 = 62; + map map_fixed64_fixed64 = 63; + map map_sfixed32_sfixed32 = 64; + map map_sfixed64_sfixed64 = 65; + map map_int32_float = 66; + map map_int32_double = 67; + map map_bool_bool = 68; + map map_string_string = 69; + map map_string_bytes = 70; + map map_string_nested_message = 71; + map map_string_foreign_message = 72; + map map_string_nested_enum = 73; + map map_string_foreign_enum = 74; oneof oneof_field { uint32 oneof_uint32 = 111; @@ -158,6 +203,7 @@ message TestAllTypesProto3 { float oneof_float = 117; double oneof_double = 118; NestedEnum oneof_enum = 119; + google.protobuf.NullValue oneof_null_value = 120; } // Well-known types @@ -187,6 +233,7 @@ message TestAllTypesProto3 { google.protobuf.Struct optional_struct = 304; google.protobuf.Any optional_any = 305; google.protobuf.Value optional_value = 306; + google.protobuf.NullValue optional_null_value = 307; repeated google.protobuf.Duration repeated_duration = 311; repeated google.protobuf.Timestamp repeated_timestamp = 312; @@ -194,6 +241,7 @@ message TestAllTypesProto3 { repeated google.protobuf.Struct repeated_struct = 324; repeated google.protobuf.Any repeated_any = 315; repeated google.protobuf.Value repeated_value = 316; + repeated google.protobuf.ListValue repeated_list_value = 317; // Test field-name-to-JSON-name convention. // (protobuf says names can be any valid C/C++ identifier.) @@ -215,6 +263,9 @@ message TestAllTypesProto3 { int32 field__Name16 = 416; int32 field_name17__ = 417; int32 Field_name18__ = 418; + + // Reserved for testing unknown fields + reserved 501 to 510; } message ForeignMessage { diff --git a/src/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc index 4e02a85d85047..795cb6ae1776f 100644 --- a/src/google/protobuf/test_util.cc +++ b/src/google/protobuf/test_util.cc @@ -39,3312 +39,9 @@ #endif #include -#include -#include - -#include -#include -#include -#include namespace google { namespace protobuf { -void TestUtil::SetAllFields(unittest::TestAllTypes* message) { - SetOptionalFields(message); - AddRepeatedFields1(message); - AddRepeatedFields2(message); - SetDefaultFields(message); - SetOneofFields(message); -} - -void TestUtil::SetOptionalFields(unittest::TestAllTypes* message) { - message->set_optional_int32 (101); - message->set_optional_int64 (102); - message->set_optional_uint32 (103); - message->set_optional_uint64 (104); - message->set_optional_sint32 (105); - message->set_optional_sint64 (106); - message->set_optional_fixed32 (107); - message->set_optional_fixed64 (108); - message->set_optional_sfixed32(109); - message->set_optional_sfixed64(110); - message->set_optional_float (111); - message->set_optional_double (112); - message->set_optional_bool (true); - message->set_optional_string ("115"); - message->set_optional_bytes ("116"); - - message->mutable_optionalgroup ()->set_a(117); - message->mutable_optional_nested_message ()->set_bb(118); - message->mutable_optional_foreign_message ()->set_c(119); - message->mutable_optional_import_message ()->set_d(120); - message->mutable_optional_public_import_message()->set_e(126); - message->mutable_optional_lazy_message ()->set_bb(127); - - message->set_optional_nested_enum (unittest::TestAllTypes::BAZ); - message->set_optional_foreign_enum(unittest::FOREIGN_BAZ ); - message->set_optional_import_enum (unittest_import::IMPORT_BAZ); - - // StringPiece and Cord fields are only accessible via reflection in the - // open source release; see comments in compiler/cpp/string_field.cc. -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - message->GetReflection()->SetString( - message, - message->GetDescriptor()->FindFieldByName("optional_string_piece"), - "124"); - message->GetReflection()->SetString( - message, - message->GetDescriptor()->FindFieldByName("optional_cord"), - "125"); -#endif // !PROTOBUF_TEST_NO_DESCRIPTORS -} - -// ------------------------------------------------------------------- - -void TestUtil::AddRepeatedFields1(unittest::TestAllTypes* message) { - message->add_repeated_int32 (201); - message->add_repeated_int64 (202); - message->add_repeated_uint32 (203); - message->add_repeated_uint64 (204); - message->add_repeated_sint32 (205); - message->add_repeated_sint64 (206); - message->add_repeated_fixed32 (207); - message->add_repeated_fixed64 (208); - message->add_repeated_sfixed32(209); - message->add_repeated_sfixed64(210); - message->add_repeated_float (211); - message->add_repeated_double (212); - message->add_repeated_bool (true); - message->add_repeated_string ("215"); - message->add_repeated_bytes ("216"); - - message->add_repeatedgroup ()->set_a(217); - message->add_repeated_nested_message ()->set_bb(218); - message->add_repeated_foreign_message()->set_c(219); - message->add_repeated_import_message ()->set_d(220); - message->add_repeated_lazy_message ()->set_bb(227); - - message->add_repeated_nested_enum (unittest::TestAllTypes::BAR); - message->add_repeated_foreign_enum(unittest::FOREIGN_BAR ); - message->add_repeated_import_enum (unittest_import::IMPORT_BAR); - -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - message->GetReflection()->AddString( - message, - message->GetDescriptor()->FindFieldByName("repeated_string_piece"), - "224"); - message->GetReflection()->AddString( - message, - message->GetDescriptor()->FindFieldByName("repeated_cord"), - "225"); -#endif // !PROTOBUF_TEST_NO_DESCRIPTORS -} - -void TestUtil::AddRepeatedFields2(unittest::TestAllTypes* message) { - // Add a second one of each field. - message->add_repeated_int32 (301); - message->add_repeated_int64 (302); - message->add_repeated_uint32 (303); - message->add_repeated_uint64 (304); - message->add_repeated_sint32 (305); - message->add_repeated_sint64 (306); - message->add_repeated_fixed32 (307); - message->add_repeated_fixed64 (308); - message->add_repeated_sfixed32(309); - message->add_repeated_sfixed64(310); - message->add_repeated_float (311); - message->add_repeated_double (312); - message->add_repeated_bool (false); - message->add_repeated_string ("315"); - message->add_repeated_bytes ("316"); - - message->add_repeatedgroup ()->set_a(317); - message->add_repeated_nested_message ()->set_bb(318); - message->add_repeated_foreign_message()->set_c(319); - message->add_repeated_import_message ()->set_d(320); - message->add_repeated_lazy_message ()->set_bb(327); - - message->add_repeated_nested_enum (unittest::TestAllTypes::BAZ); - message->add_repeated_foreign_enum(unittest::FOREIGN_BAZ ); - message->add_repeated_import_enum (unittest_import::IMPORT_BAZ); - -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - message->GetReflection()->AddString( - message, - message->GetDescriptor()->FindFieldByName("repeated_string_piece"), - "324"); - message->GetReflection()->AddString( - message, - message->GetDescriptor()->FindFieldByName("repeated_cord"), - "325"); -#endif // !PROTOBUF_TEST_NO_DESCRIPTORS -} - -// ------------------------------------------------------------------- - -void TestUtil::SetDefaultFields(unittest::TestAllTypes* message) { - message->set_default_int32 (401); - message->set_default_int64 (402); - message->set_default_uint32 (403); - message->set_default_uint64 (404); - message->set_default_sint32 (405); - message->set_default_sint64 (406); - message->set_default_fixed32 (407); - message->set_default_fixed64 (408); - message->set_default_sfixed32(409); - message->set_default_sfixed64(410); - message->set_default_float (411); - message->set_default_double (412); - message->set_default_bool (false); - message->set_default_string ("415"); - message->set_default_bytes ("416"); - - message->set_default_nested_enum (unittest::TestAllTypes::FOO); - message->set_default_foreign_enum(unittest::FOREIGN_FOO ); - message->set_default_import_enum (unittest_import::IMPORT_FOO); - -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - message->GetReflection()->SetString( - message, - message->GetDescriptor()->FindFieldByName("default_string_piece"), - "424"); - message->GetReflection()->SetString( - message, - message->GetDescriptor()->FindFieldByName("default_cord"), - "425"); -#endif // !PROTOBUF_TEST_NO_DESCRIPTORS -} - -// ------------------------------------------------------------------- - -void TestUtil::ModifyRepeatedFields(unittest::TestAllTypes* message) { - message->set_repeated_int32 (1, 501); - message->set_repeated_int64 (1, 502); - message->set_repeated_uint32 (1, 503); - message->set_repeated_uint64 (1, 504); - message->set_repeated_sint32 (1, 505); - message->set_repeated_sint64 (1, 506); - message->set_repeated_fixed32 (1, 507); - message->set_repeated_fixed64 (1, 508); - message->set_repeated_sfixed32(1, 509); - message->set_repeated_sfixed64(1, 510); - message->set_repeated_float (1, 511); - message->set_repeated_double (1, 512); - message->set_repeated_bool (1, true); - message->set_repeated_string (1, "515"); - message->set_repeated_bytes (1, "516"); - - message->mutable_repeatedgroup (1)->set_a(517); - message->mutable_repeated_nested_message (1)->set_bb(518); - message->mutable_repeated_foreign_message(1)->set_c(519); - message->mutable_repeated_import_message (1)->set_d(520); - message->mutable_repeated_lazy_message (1)->set_bb(527); - - message->set_repeated_nested_enum (1, unittest::TestAllTypes::FOO); - message->set_repeated_foreign_enum(1, unittest::FOREIGN_FOO ); - message->set_repeated_import_enum (1, unittest_import::IMPORT_FOO); - -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - message->GetReflection()->SetRepeatedString( - message, - message->GetDescriptor()->FindFieldByName("repeated_string_piece"), - 1, "524"); - message->GetReflection()->SetRepeatedString( - message, - message->GetDescriptor()->FindFieldByName("repeated_cord"), - 1, "525"); -#endif // !PROTOBUF_TEST_NO_DESCRIPTORS -} - -// ------------------------------------------------------------------ -void TestUtil::SetOneofFields(unittest::TestAllTypes* message) { - message->set_oneof_uint32(601); - message->mutable_oneof_nested_message()->set_bb(602); - message->set_oneof_string("603"); - message->set_oneof_bytes("604"); -} - -// ------------------------------------------------------------------- - -void TestUtil::ExpectAllFieldsSet(const unittest::TestAllTypes& message) { - EXPECT_TRUE(message.has_optional_int32 ()); - EXPECT_TRUE(message.has_optional_int64 ()); - EXPECT_TRUE(message.has_optional_uint32 ()); - EXPECT_TRUE(message.has_optional_uint64 ()); - EXPECT_TRUE(message.has_optional_sint32 ()); - EXPECT_TRUE(message.has_optional_sint64 ()); - EXPECT_TRUE(message.has_optional_fixed32 ()); - EXPECT_TRUE(message.has_optional_fixed64 ()); - EXPECT_TRUE(message.has_optional_sfixed32()); - EXPECT_TRUE(message.has_optional_sfixed64()); - EXPECT_TRUE(message.has_optional_float ()); - EXPECT_TRUE(message.has_optional_double ()); - EXPECT_TRUE(message.has_optional_bool ()); - EXPECT_TRUE(message.has_optional_string ()); - EXPECT_TRUE(message.has_optional_bytes ()); - - EXPECT_TRUE(message.has_optionalgroup ()); - EXPECT_TRUE(message.has_optional_nested_message ()); - EXPECT_TRUE(message.has_optional_foreign_message ()); - EXPECT_TRUE(message.has_optional_import_message ()); - EXPECT_TRUE(message.has_optional_public_import_message()); - EXPECT_TRUE(message.has_optional_lazy_message ()); - - EXPECT_TRUE(message.optionalgroup ().has_a()); - EXPECT_TRUE(message.optional_nested_message ().has_bb()); - EXPECT_TRUE(message.optional_foreign_message ().has_c()); - EXPECT_TRUE(message.optional_import_message ().has_d()); - EXPECT_TRUE(message.optional_public_import_message().has_e()); - EXPECT_TRUE(message.optional_lazy_message ().has_bb()); - - EXPECT_TRUE(message.has_optional_nested_enum ()); - EXPECT_TRUE(message.has_optional_foreign_enum()); - EXPECT_TRUE(message.has_optional_import_enum ()); - -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - EXPECT_TRUE(message.has_optional_string_piece()); - EXPECT_TRUE(message.has_optional_cord()); -#endif - - EXPECT_EQ(101 , message.optional_int32 ()); - EXPECT_EQ(102 , message.optional_int64 ()); - EXPECT_EQ(103 , message.optional_uint32 ()); - EXPECT_EQ(104 , message.optional_uint64 ()); - EXPECT_EQ(105 , message.optional_sint32 ()); - EXPECT_EQ(106 , message.optional_sint64 ()); - EXPECT_EQ(107 , message.optional_fixed32 ()); - EXPECT_EQ(108 , message.optional_fixed64 ()); - EXPECT_EQ(109 , message.optional_sfixed32()); - EXPECT_EQ(110 , message.optional_sfixed64()); - EXPECT_EQ(111 , message.optional_float ()); - EXPECT_EQ(112 , message.optional_double ()); - EXPECT_TRUE( message.optional_bool ()); - EXPECT_EQ("115", message.optional_string ()); - EXPECT_EQ("116", message.optional_bytes ()); - - EXPECT_EQ(117, message.optionalgroup ().a()); - EXPECT_EQ(118, message.optional_nested_message ().bb()); - EXPECT_EQ(119, message.optional_foreign_message ().c()); - EXPECT_EQ(120, message.optional_import_message ().d()); - EXPECT_EQ(126, message.optional_public_import_message ().e()); - EXPECT_EQ(127, message.optional_lazy_message ().bb()); - - EXPECT_EQ(unittest::TestAllTypes::BAZ, message.optional_nested_enum ()); - EXPECT_EQ(unittest::FOREIGN_BAZ , message.optional_foreign_enum()); - EXPECT_EQ(unittest_import::IMPORT_BAZ, message.optional_import_enum ()); - - - // ----------------------------------------------------------------- - - ASSERT_EQ(2, message.repeated_int32_size ()); - ASSERT_EQ(2, message.repeated_int64_size ()); - ASSERT_EQ(2, message.repeated_uint32_size ()); - ASSERT_EQ(2, message.repeated_uint64_size ()); - ASSERT_EQ(2, message.repeated_sint32_size ()); - ASSERT_EQ(2, message.repeated_sint64_size ()); - ASSERT_EQ(2, message.repeated_fixed32_size ()); - ASSERT_EQ(2, message.repeated_fixed64_size ()); - ASSERT_EQ(2, message.repeated_sfixed32_size()); - ASSERT_EQ(2, message.repeated_sfixed64_size()); - ASSERT_EQ(2, message.repeated_float_size ()); - ASSERT_EQ(2, message.repeated_double_size ()); - ASSERT_EQ(2, message.repeated_bool_size ()); - ASSERT_EQ(2, message.repeated_string_size ()); - ASSERT_EQ(2, message.repeated_bytes_size ()); - - ASSERT_EQ(2, message.repeatedgroup_size ()); - ASSERT_EQ(2, message.repeated_nested_message_size ()); - ASSERT_EQ(2, message.repeated_foreign_message_size()); - ASSERT_EQ(2, message.repeated_import_message_size ()); - ASSERT_EQ(2, message.repeated_lazy_message_size ()); - ASSERT_EQ(2, message.repeated_nested_enum_size ()); - ASSERT_EQ(2, message.repeated_foreign_enum_size ()); - ASSERT_EQ(2, message.repeated_import_enum_size ()); - -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - ASSERT_EQ(2, message.repeated_string_piece_size()); - ASSERT_EQ(2, message.repeated_cord_size()); -#endif - - EXPECT_EQ(201 , message.repeated_int32 (0)); - EXPECT_EQ(202 , message.repeated_int64 (0)); - EXPECT_EQ(203 , message.repeated_uint32 (0)); - EXPECT_EQ(204 , message.repeated_uint64 (0)); - EXPECT_EQ(205 , message.repeated_sint32 (0)); - EXPECT_EQ(206 , message.repeated_sint64 (0)); - EXPECT_EQ(207 , message.repeated_fixed32 (0)); - EXPECT_EQ(208 , message.repeated_fixed64 (0)); - EXPECT_EQ(209 , message.repeated_sfixed32(0)); - EXPECT_EQ(210 , message.repeated_sfixed64(0)); - EXPECT_EQ(211 , message.repeated_float (0)); - EXPECT_EQ(212 , message.repeated_double (0)); - EXPECT_TRUE( message.repeated_bool (0)); - EXPECT_EQ("215", message.repeated_string (0)); - EXPECT_EQ("216", message.repeated_bytes (0)); - - EXPECT_EQ(217, message.repeatedgroup (0).a()); - EXPECT_EQ(218, message.repeated_nested_message (0).bb()); - EXPECT_EQ(219, message.repeated_foreign_message(0).c()); - EXPECT_EQ(220, message.repeated_import_message (0).d()); - EXPECT_EQ(227, message.repeated_lazy_message (0).bb()); - - - EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0)); - EXPECT_EQ(unittest::FOREIGN_BAR , message.repeated_foreign_enum(0)); - EXPECT_EQ(unittest_import::IMPORT_BAR, message.repeated_import_enum (0)); - - EXPECT_EQ(301 , message.repeated_int32 (1)); - EXPECT_EQ(302 , message.repeated_int64 (1)); - EXPECT_EQ(303 , message.repeated_uint32 (1)); - EXPECT_EQ(304 , message.repeated_uint64 (1)); - EXPECT_EQ(305 , message.repeated_sint32 (1)); - EXPECT_EQ(306 , message.repeated_sint64 (1)); - EXPECT_EQ(307 , message.repeated_fixed32 (1)); - EXPECT_EQ(308 , message.repeated_fixed64 (1)); - EXPECT_EQ(309 , message.repeated_sfixed32(1)); - EXPECT_EQ(310 , message.repeated_sfixed64(1)); - EXPECT_EQ(311 , message.repeated_float (1)); - EXPECT_EQ(312 , message.repeated_double (1)); - EXPECT_FALSE( message.repeated_bool (1)); - EXPECT_EQ("315", message.repeated_string (1)); - EXPECT_EQ("316", message.repeated_bytes (1)); - - EXPECT_EQ(317, message.repeatedgroup (1).a()); - EXPECT_EQ(318, message.repeated_nested_message (1).bb()); - EXPECT_EQ(319, message.repeated_foreign_message(1).c()); - EXPECT_EQ(320, message.repeated_import_message (1).d()); - EXPECT_EQ(327, message.repeated_lazy_message (1).bb()); - - EXPECT_EQ(unittest::TestAllTypes::BAZ, message.repeated_nested_enum (1)); - EXPECT_EQ(unittest::FOREIGN_BAZ , message.repeated_foreign_enum(1)); - EXPECT_EQ(unittest_import::IMPORT_BAZ, message.repeated_import_enum (1)); - - - // ----------------------------------------------------------------- - - EXPECT_TRUE(message.has_default_int32 ()); - EXPECT_TRUE(message.has_default_int64 ()); - EXPECT_TRUE(message.has_default_uint32 ()); - EXPECT_TRUE(message.has_default_uint64 ()); - EXPECT_TRUE(message.has_default_sint32 ()); - EXPECT_TRUE(message.has_default_sint64 ()); - EXPECT_TRUE(message.has_default_fixed32 ()); - EXPECT_TRUE(message.has_default_fixed64 ()); - EXPECT_TRUE(message.has_default_sfixed32()); - EXPECT_TRUE(message.has_default_sfixed64()); - EXPECT_TRUE(message.has_default_float ()); - EXPECT_TRUE(message.has_default_double ()); - EXPECT_TRUE(message.has_default_bool ()); - EXPECT_TRUE(message.has_default_string ()); - EXPECT_TRUE(message.has_default_bytes ()); - - EXPECT_TRUE(message.has_default_nested_enum ()); - EXPECT_TRUE(message.has_default_foreign_enum()); - EXPECT_TRUE(message.has_default_import_enum ()); - - - EXPECT_EQ(401 , message.default_int32 ()); - EXPECT_EQ(402 , message.default_int64 ()); - EXPECT_EQ(403 , message.default_uint32 ()); - EXPECT_EQ(404 , message.default_uint64 ()); - EXPECT_EQ(405 , message.default_sint32 ()); - EXPECT_EQ(406 , message.default_sint64 ()); - EXPECT_EQ(407 , message.default_fixed32 ()); - EXPECT_EQ(408 , message.default_fixed64 ()); - EXPECT_EQ(409 , message.default_sfixed32()); - EXPECT_EQ(410 , message.default_sfixed64()); - EXPECT_EQ(411 , message.default_float ()); - EXPECT_EQ(412 , message.default_double ()); - EXPECT_FALSE( message.default_bool ()); - EXPECT_EQ("415", message.default_string ()); - EXPECT_EQ("416", message.default_bytes ()); - - EXPECT_EQ(unittest::TestAllTypes::FOO, message.default_nested_enum ()); - EXPECT_EQ(unittest::FOREIGN_FOO , message.default_foreign_enum()); - EXPECT_EQ(unittest_import::IMPORT_FOO, message.default_import_enum ()); - - - EXPECT_FALSE(message.has_oneof_uint32 ()); - EXPECT_FALSE(message.has_oneof_nested_message()); - EXPECT_FALSE(message.has_oneof_string ()); - EXPECT_TRUE(message.has_oneof_bytes ()); - - EXPECT_EQ("604", message.oneof_bytes()); -} - -// ------------------------------------------------------------------- - -void TestUtil::ExpectClear(const unittest::TestAllTypes& message) { - // has_blah() should initially be false for all optional fields. - EXPECT_FALSE(message.has_optional_int32 ()); - EXPECT_FALSE(message.has_optional_int64 ()); - EXPECT_FALSE(message.has_optional_uint32 ()); - EXPECT_FALSE(message.has_optional_uint64 ()); - EXPECT_FALSE(message.has_optional_sint32 ()); - EXPECT_FALSE(message.has_optional_sint64 ()); - EXPECT_FALSE(message.has_optional_fixed32 ()); - EXPECT_FALSE(message.has_optional_fixed64 ()); - EXPECT_FALSE(message.has_optional_sfixed32()); - EXPECT_FALSE(message.has_optional_sfixed64()); - EXPECT_FALSE(message.has_optional_float ()); - EXPECT_FALSE(message.has_optional_double ()); - EXPECT_FALSE(message.has_optional_bool ()); - EXPECT_FALSE(message.has_optional_string ()); - EXPECT_FALSE(message.has_optional_bytes ()); - - EXPECT_FALSE(message.has_optionalgroup ()); - EXPECT_FALSE(message.has_optional_nested_message ()); - EXPECT_FALSE(message.has_optional_foreign_message ()); - EXPECT_FALSE(message.has_optional_import_message ()); - EXPECT_FALSE(message.has_optional_public_import_message()); - EXPECT_FALSE(message.has_optional_lazy_message ()); - - EXPECT_FALSE(message.has_optional_nested_enum ()); - EXPECT_FALSE(message.has_optional_foreign_enum()); - EXPECT_FALSE(message.has_optional_import_enum ()); - - EXPECT_FALSE(message.has_optional_string_piece()); - EXPECT_FALSE(message.has_optional_cord()); - - // Optional fields without defaults are set to zero or something like it. - EXPECT_EQ(0 , message.optional_int32 ()); - EXPECT_EQ(0 , message.optional_int64 ()); - EXPECT_EQ(0 , message.optional_uint32 ()); - EXPECT_EQ(0 , message.optional_uint64 ()); - EXPECT_EQ(0 , message.optional_sint32 ()); - EXPECT_EQ(0 , message.optional_sint64 ()); - EXPECT_EQ(0 , message.optional_fixed32 ()); - EXPECT_EQ(0 , message.optional_fixed64 ()); - EXPECT_EQ(0 , message.optional_sfixed32()); - EXPECT_EQ(0 , message.optional_sfixed64()); - EXPECT_EQ(0 , message.optional_float ()); - EXPECT_EQ(0 , message.optional_double ()); - EXPECT_FALSE( message.optional_bool ()); - EXPECT_EQ("" , message.optional_string ()); - EXPECT_EQ("" , message.optional_bytes ()); - - // Embedded messages should also be clear. - EXPECT_FALSE(message.optionalgroup ().has_a()); - EXPECT_FALSE(message.optional_nested_message ().has_bb()); - EXPECT_FALSE(message.optional_foreign_message ().has_c()); - EXPECT_FALSE(message.optional_import_message ().has_d()); - EXPECT_FALSE(message.optional_public_import_message().has_e()); - EXPECT_FALSE(message.optional_lazy_message ().has_bb()); - - EXPECT_EQ(0, message.optionalgroup ().a()); - EXPECT_EQ(0, message.optional_nested_message ().bb()); - EXPECT_EQ(0, message.optional_foreign_message ().c()); - EXPECT_EQ(0, message.optional_import_message ().d()); - EXPECT_EQ(0, message.optional_public_import_message().e()); - EXPECT_EQ(0, message.optional_lazy_message ().bb()); - - // Enums without defaults are set to the first value in the enum. - EXPECT_EQ(unittest::TestAllTypes::FOO, message.optional_nested_enum ()); - EXPECT_EQ(unittest::FOREIGN_FOO , message.optional_foreign_enum()); - EXPECT_EQ(unittest_import::IMPORT_FOO, message.optional_import_enum ()); - - - // Repeated fields are empty. - EXPECT_EQ(0, message.repeated_int32_size ()); - EXPECT_EQ(0, message.repeated_int64_size ()); - EXPECT_EQ(0, message.repeated_uint32_size ()); - EXPECT_EQ(0, message.repeated_uint64_size ()); - EXPECT_EQ(0, message.repeated_sint32_size ()); - EXPECT_EQ(0, message.repeated_sint64_size ()); - EXPECT_EQ(0, message.repeated_fixed32_size ()); - EXPECT_EQ(0, message.repeated_fixed64_size ()); - EXPECT_EQ(0, message.repeated_sfixed32_size()); - EXPECT_EQ(0, message.repeated_sfixed64_size()); - EXPECT_EQ(0, message.repeated_float_size ()); - EXPECT_EQ(0, message.repeated_double_size ()); - EXPECT_EQ(0, message.repeated_bool_size ()); - EXPECT_EQ(0, message.repeated_string_size ()); - EXPECT_EQ(0, message.repeated_bytes_size ()); - - EXPECT_EQ(0, message.repeatedgroup_size ()); - EXPECT_EQ(0, message.repeated_nested_message_size ()); - EXPECT_EQ(0, message.repeated_foreign_message_size()); - EXPECT_EQ(0, message.repeated_import_message_size ()); - EXPECT_EQ(0, message.repeated_lazy_message_size ()); - EXPECT_EQ(0, message.repeated_nested_enum_size ()); - EXPECT_EQ(0, message.repeated_foreign_enum_size ()); - EXPECT_EQ(0, message.repeated_import_enum_size ()); - - EXPECT_EQ(0, message.repeated_string_piece_size()); - EXPECT_EQ(0, message.repeated_cord_size()); - - // has_blah() should also be false for all default fields. - EXPECT_FALSE(message.has_default_int32 ()); - EXPECT_FALSE(message.has_default_int64 ()); - EXPECT_FALSE(message.has_default_uint32 ()); - EXPECT_FALSE(message.has_default_uint64 ()); - EXPECT_FALSE(message.has_default_sint32 ()); - EXPECT_FALSE(message.has_default_sint64 ()); - EXPECT_FALSE(message.has_default_fixed32 ()); - EXPECT_FALSE(message.has_default_fixed64 ()); - EXPECT_FALSE(message.has_default_sfixed32()); - EXPECT_FALSE(message.has_default_sfixed64()); - EXPECT_FALSE(message.has_default_float ()); - EXPECT_FALSE(message.has_default_double ()); - EXPECT_FALSE(message.has_default_bool ()); - EXPECT_FALSE(message.has_default_string ()); - EXPECT_FALSE(message.has_default_bytes ()); - - EXPECT_FALSE(message.has_default_nested_enum ()); - EXPECT_FALSE(message.has_default_foreign_enum()); - EXPECT_FALSE(message.has_default_import_enum ()); - - - // Fields with defaults have their default values (duh). - EXPECT_EQ( 41 , message.default_int32 ()); - EXPECT_EQ( 42 , message.default_int64 ()); - EXPECT_EQ( 43 , message.default_uint32 ()); - EXPECT_EQ( 44 , message.default_uint64 ()); - EXPECT_EQ(-45 , message.default_sint32 ()); - EXPECT_EQ( 46 , message.default_sint64 ()); - EXPECT_EQ( 47 , message.default_fixed32 ()); - EXPECT_EQ( 48 , message.default_fixed64 ()); - EXPECT_EQ( 49 , message.default_sfixed32()); - EXPECT_EQ(-50 , message.default_sfixed64()); - EXPECT_EQ( 51.5 , message.default_float ()); - EXPECT_EQ( 52e3 , message.default_double ()); - EXPECT_TRUE( message.default_bool ()); - EXPECT_EQ("hello", message.default_string ()); - EXPECT_EQ("world", message.default_bytes ()); - - EXPECT_EQ(unittest::TestAllTypes::BAR, message.default_nested_enum ()); - EXPECT_EQ(unittest::FOREIGN_BAR , message.default_foreign_enum()); - EXPECT_EQ(unittest_import::IMPORT_BAR, message.default_import_enum ()); - - - EXPECT_FALSE(message.has_oneof_uint32 ()); - EXPECT_FALSE(message.has_oneof_nested_message()); - EXPECT_FALSE(message.has_oneof_string ()); - EXPECT_FALSE(message.has_oneof_bytes ()); -} - -// ------------------------------------------------------------------- - -void TestUtil::ExpectRepeatedFieldsModified( - const unittest::TestAllTypes& message) { - // ModifyRepeatedFields only sets the second repeated element of each - // field. In addition to verifying this, we also verify that the first - // element and size were *not* modified. - ASSERT_EQ(2, message.repeated_int32_size ()); - ASSERT_EQ(2, message.repeated_int64_size ()); - ASSERT_EQ(2, message.repeated_uint32_size ()); - ASSERT_EQ(2, message.repeated_uint64_size ()); - ASSERT_EQ(2, message.repeated_sint32_size ()); - ASSERT_EQ(2, message.repeated_sint64_size ()); - ASSERT_EQ(2, message.repeated_fixed32_size ()); - ASSERT_EQ(2, message.repeated_fixed64_size ()); - ASSERT_EQ(2, message.repeated_sfixed32_size()); - ASSERT_EQ(2, message.repeated_sfixed64_size()); - ASSERT_EQ(2, message.repeated_float_size ()); - ASSERT_EQ(2, message.repeated_double_size ()); - ASSERT_EQ(2, message.repeated_bool_size ()); - ASSERT_EQ(2, message.repeated_string_size ()); - ASSERT_EQ(2, message.repeated_bytes_size ()); - - ASSERT_EQ(2, message.repeatedgroup_size ()); - ASSERT_EQ(2, message.repeated_nested_message_size ()); - ASSERT_EQ(2, message.repeated_foreign_message_size()); - ASSERT_EQ(2, message.repeated_import_message_size ()); - ASSERT_EQ(2, message.repeated_lazy_message_size ()); - ASSERT_EQ(2, message.repeated_nested_enum_size ()); - ASSERT_EQ(2, message.repeated_foreign_enum_size ()); - ASSERT_EQ(2, message.repeated_import_enum_size ()); - -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - ASSERT_EQ(2, message.repeated_string_piece_size()); - ASSERT_EQ(2, message.repeated_cord_size()); -#endif - - EXPECT_EQ(201 , message.repeated_int32 (0)); - EXPECT_EQ(202 , message.repeated_int64 (0)); - EXPECT_EQ(203 , message.repeated_uint32 (0)); - EXPECT_EQ(204 , message.repeated_uint64 (0)); - EXPECT_EQ(205 , message.repeated_sint32 (0)); - EXPECT_EQ(206 , message.repeated_sint64 (0)); - EXPECT_EQ(207 , message.repeated_fixed32 (0)); - EXPECT_EQ(208 , message.repeated_fixed64 (0)); - EXPECT_EQ(209 , message.repeated_sfixed32(0)); - EXPECT_EQ(210 , message.repeated_sfixed64(0)); - EXPECT_EQ(211 , message.repeated_float (0)); - EXPECT_EQ(212 , message.repeated_double (0)); - EXPECT_TRUE( message.repeated_bool (0)); - EXPECT_EQ("215", message.repeated_string (0)); - EXPECT_EQ("216", message.repeated_bytes (0)); - - EXPECT_EQ(217, message.repeatedgroup (0).a()); - EXPECT_EQ(218, message.repeated_nested_message (0).bb()); - EXPECT_EQ(219, message.repeated_foreign_message(0).c()); - EXPECT_EQ(220, message.repeated_import_message (0).d()); - EXPECT_EQ(227, message.repeated_lazy_message (0).bb()); - - EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0)); - EXPECT_EQ(unittest::FOREIGN_BAR , message.repeated_foreign_enum(0)); - EXPECT_EQ(unittest_import::IMPORT_BAR, message.repeated_import_enum (0)); - - - // Actually verify the second (modified) elements now. - EXPECT_EQ(501 , message.repeated_int32 (1)); - EXPECT_EQ(502 , message.repeated_int64 (1)); - EXPECT_EQ(503 , message.repeated_uint32 (1)); - EXPECT_EQ(504 , message.repeated_uint64 (1)); - EXPECT_EQ(505 , message.repeated_sint32 (1)); - EXPECT_EQ(506 , message.repeated_sint64 (1)); - EXPECT_EQ(507 , message.repeated_fixed32 (1)); - EXPECT_EQ(508 , message.repeated_fixed64 (1)); - EXPECT_EQ(509 , message.repeated_sfixed32(1)); - EXPECT_EQ(510 , message.repeated_sfixed64(1)); - EXPECT_EQ(511 , message.repeated_float (1)); - EXPECT_EQ(512 , message.repeated_double (1)); - EXPECT_TRUE( message.repeated_bool (1)); - EXPECT_EQ("515", message.repeated_string (1)); - EXPECT_EQ("516", message.repeated_bytes (1)); - - EXPECT_EQ(517, message.repeatedgroup (1).a()); - EXPECT_EQ(518, message.repeated_nested_message (1).bb()); - EXPECT_EQ(519, message.repeated_foreign_message(1).c()); - EXPECT_EQ(520, message.repeated_import_message (1).d()); - EXPECT_EQ(527, message.repeated_lazy_message (1).bb()); - - EXPECT_EQ(unittest::TestAllTypes::FOO, message.repeated_nested_enum (1)); - EXPECT_EQ(unittest::FOREIGN_FOO , message.repeated_foreign_enum(1)); - EXPECT_EQ(unittest_import::IMPORT_FOO, message.repeated_import_enum (1)); - -} - -// ------------------------------------------------------------------- - -void TestUtil::SetPackedFields(unittest::TestPackedTypes* message) { - message->add_packed_int32 (601); - message->add_packed_int64 (602); - message->add_packed_uint32 (603); - message->add_packed_uint64 (604); - message->add_packed_sint32 (605); - message->add_packed_sint64 (606); - message->add_packed_fixed32 (607); - message->add_packed_fixed64 (608); - message->add_packed_sfixed32(609); - message->add_packed_sfixed64(610); - message->add_packed_float (611); - message->add_packed_double (612); - message->add_packed_bool (true); - message->add_packed_enum (unittest::FOREIGN_BAR); - // add a second one of each field - message->add_packed_int32 (701); - message->add_packed_int64 (702); - message->add_packed_uint32 (703); - message->add_packed_uint64 (704); - message->add_packed_sint32 (705); - message->add_packed_sint64 (706); - message->add_packed_fixed32 (707); - message->add_packed_fixed64 (708); - message->add_packed_sfixed32(709); - message->add_packed_sfixed64(710); - message->add_packed_float (711); - message->add_packed_double (712); - message->add_packed_bool (false); - message->add_packed_enum (unittest::FOREIGN_BAZ); -} - -void TestUtil::SetUnpackedFields(unittest::TestUnpackedTypes* message) { - // The values applied here must match those of SetPackedFields. - - message->add_unpacked_int32 (601); - message->add_unpacked_int64 (602); - message->add_unpacked_uint32 (603); - message->add_unpacked_uint64 (604); - message->add_unpacked_sint32 (605); - message->add_unpacked_sint64 (606); - message->add_unpacked_fixed32 (607); - message->add_unpacked_fixed64 (608); - message->add_unpacked_sfixed32(609); - message->add_unpacked_sfixed64(610); - message->add_unpacked_float (611); - message->add_unpacked_double (612); - message->add_unpacked_bool (true); - message->add_unpacked_enum (unittest::FOREIGN_BAR); - // add a second one of each field - message->add_unpacked_int32 (701); - message->add_unpacked_int64 (702); - message->add_unpacked_uint32 (703); - message->add_unpacked_uint64 (704); - message->add_unpacked_sint32 (705); - message->add_unpacked_sint64 (706); - message->add_unpacked_fixed32 (707); - message->add_unpacked_fixed64 (708); - message->add_unpacked_sfixed32(709); - message->add_unpacked_sfixed64(710); - message->add_unpacked_float (711); - message->add_unpacked_double (712); - message->add_unpacked_bool (false); - message->add_unpacked_enum (unittest::FOREIGN_BAZ); -} - -// ------------------------------------------------------------------- - -void TestUtil::ModifyPackedFields(unittest::TestPackedTypes* message) { - message->set_packed_int32 (1, 801); - message->set_packed_int64 (1, 802); - message->set_packed_uint32 (1, 803); - message->set_packed_uint64 (1, 804); - message->set_packed_sint32 (1, 805); - message->set_packed_sint64 (1, 806); - message->set_packed_fixed32 (1, 807); - message->set_packed_fixed64 (1, 808); - message->set_packed_sfixed32(1, 809); - message->set_packed_sfixed64(1, 810); - message->set_packed_float (1, 811); - message->set_packed_double (1, 812); - message->set_packed_bool (1, true); - message->set_packed_enum (1, unittest::FOREIGN_FOO); -} - -// ------------------------------------------------------------------- - -void TestUtil::ExpectPackedFieldsSet(const unittest::TestPackedTypes& message) { - ASSERT_EQ(2, message.packed_int32_size ()); - ASSERT_EQ(2, message.packed_int64_size ()); - ASSERT_EQ(2, message.packed_uint32_size ()); - ASSERT_EQ(2, message.packed_uint64_size ()); - ASSERT_EQ(2, message.packed_sint32_size ()); - ASSERT_EQ(2, message.packed_sint64_size ()); - ASSERT_EQ(2, message.packed_fixed32_size ()); - ASSERT_EQ(2, message.packed_fixed64_size ()); - ASSERT_EQ(2, message.packed_sfixed32_size()); - ASSERT_EQ(2, message.packed_sfixed64_size()); - ASSERT_EQ(2, message.packed_float_size ()); - ASSERT_EQ(2, message.packed_double_size ()); - ASSERT_EQ(2, message.packed_bool_size ()); - ASSERT_EQ(2, message.packed_enum_size ()); - - EXPECT_EQ(601 , message.packed_int32 (0)); - EXPECT_EQ(602 , message.packed_int64 (0)); - EXPECT_EQ(603 , message.packed_uint32 (0)); - EXPECT_EQ(604 , message.packed_uint64 (0)); - EXPECT_EQ(605 , message.packed_sint32 (0)); - EXPECT_EQ(606 , message.packed_sint64 (0)); - EXPECT_EQ(607 , message.packed_fixed32 (0)); - EXPECT_EQ(608 , message.packed_fixed64 (0)); - EXPECT_EQ(609 , message.packed_sfixed32(0)); - EXPECT_EQ(610 , message.packed_sfixed64(0)); - EXPECT_EQ(611 , message.packed_float (0)); - EXPECT_EQ(612 , message.packed_double (0)); - EXPECT_TRUE( message.packed_bool (0)); - EXPECT_EQ(unittest::FOREIGN_BAR, message.packed_enum(0)); - - EXPECT_EQ(701 , message.packed_int32 (1)); - EXPECT_EQ(702 , message.packed_int64 (1)); - EXPECT_EQ(703 , message.packed_uint32 (1)); - EXPECT_EQ(704 , message.packed_uint64 (1)); - EXPECT_EQ(705 , message.packed_sint32 (1)); - EXPECT_EQ(706 , message.packed_sint64 (1)); - EXPECT_EQ(707 , message.packed_fixed32 (1)); - EXPECT_EQ(708 , message.packed_fixed64 (1)); - EXPECT_EQ(709 , message.packed_sfixed32(1)); - EXPECT_EQ(710 , message.packed_sfixed64(1)); - EXPECT_EQ(711 , message.packed_float (1)); - EXPECT_EQ(712 , message.packed_double (1)); - EXPECT_FALSE( message.packed_bool (1)); - EXPECT_EQ(unittest::FOREIGN_BAZ, message.packed_enum(1)); -} - -void TestUtil::ExpectUnpackedFieldsSet( - const unittest::TestUnpackedTypes& message) { - // The values expected here must match those of ExpectPackedFieldsSet. - - ASSERT_EQ(2, message.unpacked_int32_size ()); - ASSERT_EQ(2, message.unpacked_int64_size ()); - ASSERT_EQ(2, message.unpacked_uint32_size ()); - ASSERT_EQ(2, message.unpacked_uint64_size ()); - ASSERT_EQ(2, message.unpacked_sint32_size ()); - ASSERT_EQ(2, message.unpacked_sint64_size ()); - ASSERT_EQ(2, message.unpacked_fixed32_size ()); - ASSERT_EQ(2, message.unpacked_fixed64_size ()); - ASSERT_EQ(2, message.unpacked_sfixed32_size()); - ASSERT_EQ(2, message.unpacked_sfixed64_size()); - ASSERT_EQ(2, message.unpacked_float_size ()); - ASSERT_EQ(2, message.unpacked_double_size ()); - ASSERT_EQ(2, message.unpacked_bool_size ()); - ASSERT_EQ(2, message.unpacked_enum_size ()); - - EXPECT_EQ(601 , message.unpacked_int32 (0)); - EXPECT_EQ(602 , message.unpacked_int64 (0)); - EXPECT_EQ(603 , message.unpacked_uint32 (0)); - EXPECT_EQ(604 , message.unpacked_uint64 (0)); - EXPECT_EQ(605 , message.unpacked_sint32 (0)); - EXPECT_EQ(606 , message.unpacked_sint64 (0)); - EXPECT_EQ(607 , message.unpacked_fixed32 (0)); - EXPECT_EQ(608 , message.unpacked_fixed64 (0)); - EXPECT_EQ(609 , message.unpacked_sfixed32(0)); - EXPECT_EQ(610 , message.unpacked_sfixed64(0)); - EXPECT_EQ(611 , message.unpacked_float (0)); - EXPECT_EQ(612 , message.unpacked_double (0)); - EXPECT_TRUE( message.unpacked_bool (0)); - EXPECT_EQ(unittest::FOREIGN_BAR, message.unpacked_enum(0)); - - EXPECT_EQ(701 , message.unpacked_int32 (1)); - EXPECT_EQ(702 , message.unpacked_int64 (1)); - EXPECT_EQ(703 , message.unpacked_uint32 (1)); - EXPECT_EQ(704 , message.unpacked_uint64 (1)); - EXPECT_EQ(705 , message.unpacked_sint32 (1)); - EXPECT_EQ(706 , message.unpacked_sint64 (1)); - EXPECT_EQ(707 , message.unpacked_fixed32 (1)); - EXPECT_EQ(708 , message.unpacked_fixed64 (1)); - EXPECT_EQ(709 , message.unpacked_sfixed32(1)); - EXPECT_EQ(710 , message.unpacked_sfixed64(1)); - EXPECT_EQ(711 , message.unpacked_float (1)); - EXPECT_EQ(712 , message.unpacked_double (1)); - EXPECT_FALSE( message.unpacked_bool (1)); - EXPECT_EQ(unittest::FOREIGN_BAZ, message.unpacked_enum(1)); -} - -// ------------------------------------------------------------------- - -void TestUtil::ExpectPackedClear( - const unittest::TestPackedTypes& message) { - // Packed repeated fields are empty. - EXPECT_EQ(0, message.packed_int32_size ()); - EXPECT_EQ(0, message.packed_int64_size ()); - EXPECT_EQ(0, message.packed_uint32_size ()); - EXPECT_EQ(0, message.packed_uint64_size ()); - EXPECT_EQ(0, message.packed_sint32_size ()); - EXPECT_EQ(0, message.packed_sint64_size ()); - EXPECT_EQ(0, message.packed_fixed32_size ()); - EXPECT_EQ(0, message.packed_fixed64_size ()); - EXPECT_EQ(0, message.packed_sfixed32_size()); - EXPECT_EQ(0, message.packed_sfixed64_size()); - EXPECT_EQ(0, message.packed_float_size ()); - EXPECT_EQ(0, message.packed_double_size ()); - EXPECT_EQ(0, message.packed_bool_size ()); - EXPECT_EQ(0, message.packed_enum_size ()); -} - -// ------------------------------------------------------------------- - -void TestUtil::ExpectPackedFieldsModified( - const unittest::TestPackedTypes& message) { - // Do the same for packed repeated fields. - ASSERT_EQ(2, message.packed_int32_size ()); - ASSERT_EQ(2, message.packed_int64_size ()); - ASSERT_EQ(2, message.packed_uint32_size ()); - ASSERT_EQ(2, message.packed_uint64_size ()); - ASSERT_EQ(2, message.packed_sint32_size ()); - ASSERT_EQ(2, message.packed_sint64_size ()); - ASSERT_EQ(2, message.packed_fixed32_size ()); - ASSERT_EQ(2, message.packed_fixed64_size ()); - ASSERT_EQ(2, message.packed_sfixed32_size()); - ASSERT_EQ(2, message.packed_sfixed64_size()); - ASSERT_EQ(2, message.packed_float_size ()); - ASSERT_EQ(2, message.packed_double_size ()); - ASSERT_EQ(2, message.packed_bool_size ()); - ASSERT_EQ(2, message.packed_enum_size ()); - - EXPECT_EQ(601 , message.packed_int32 (0)); - EXPECT_EQ(602 , message.packed_int64 (0)); - EXPECT_EQ(603 , message.packed_uint32 (0)); - EXPECT_EQ(604 , message.packed_uint64 (0)); - EXPECT_EQ(605 , message.packed_sint32 (0)); - EXPECT_EQ(606 , message.packed_sint64 (0)); - EXPECT_EQ(607 , message.packed_fixed32 (0)); - EXPECT_EQ(608 , message.packed_fixed64 (0)); - EXPECT_EQ(609 , message.packed_sfixed32(0)); - EXPECT_EQ(610 , message.packed_sfixed64(0)); - EXPECT_EQ(611 , message.packed_float (0)); - EXPECT_EQ(612 , message.packed_double (0)); - EXPECT_TRUE( message.packed_bool (0)); - EXPECT_EQ(unittest::FOREIGN_BAR, message.packed_enum(0)); - // Actually verify the second (modified) elements now. - EXPECT_EQ(801 , message.packed_int32 (1)); - EXPECT_EQ(802 , message.packed_int64 (1)); - EXPECT_EQ(803 , message.packed_uint32 (1)); - EXPECT_EQ(804 , message.packed_uint64 (1)); - EXPECT_EQ(805 , message.packed_sint32 (1)); - EXPECT_EQ(806 , message.packed_sint64 (1)); - EXPECT_EQ(807 , message.packed_fixed32 (1)); - EXPECT_EQ(808 , message.packed_fixed64 (1)); - EXPECT_EQ(809 , message.packed_sfixed32(1)); - EXPECT_EQ(810 , message.packed_sfixed64(1)); - EXPECT_EQ(811 , message.packed_float (1)); - EXPECT_EQ(812 , message.packed_double (1)); - EXPECT_TRUE( message.packed_bool (1)); - EXPECT_EQ(unittest::FOREIGN_FOO, message.packed_enum(1)); -} - -// =================================================================== -// Extensions -// -// All this code is exactly equivalent to the above code except that it's -// manipulating extension fields instead of normal ones. -// -// I gave up on the 80-char limit here. Sorry. - -void TestUtil::SetAllExtensions(unittest::TestAllExtensions* message) { - message->SetExtension(unittest::optional_int32_extension , 101); - message->SetExtension(unittest::optional_int64_extension , 102); - message->SetExtension(unittest::optional_uint32_extension , 103); - message->SetExtension(unittest::optional_uint64_extension , 104); - message->SetExtension(unittest::optional_sint32_extension , 105); - message->SetExtension(unittest::optional_sint64_extension , 106); - message->SetExtension(unittest::optional_fixed32_extension , 107); - message->SetExtension(unittest::optional_fixed64_extension , 108); - message->SetExtension(unittest::optional_sfixed32_extension, 109); - message->SetExtension(unittest::optional_sfixed64_extension, 110); - message->SetExtension(unittest::optional_float_extension , 111); - message->SetExtension(unittest::optional_double_extension , 112); - message->SetExtension(unittest::optional_bool_extension , true); - message->SetExtension(unittest::optional_string_extension , "115"); - message->SetExtension(unittest::optional_bytes_extension , "116"); - - message->MutableExtension(unittest::optionalgroup_extension )->set_a(117); - message->MutableExtension(unittest::optional_nested_message_extension )->set_bb(118); - message->MutableExtension(unittest::optional_foreign_message_extension)->set_c(119); - message->MutableExtension(unittest::optional_import_message_extension )->set_d(120); - - message->SetExtension(unittest::optional_nested_enum_extension , unittest::TestAllTypes::BAZ); - message->SetExtension(unittest::optional_foreign_enum_extension, unittest::FOREIGN_BAZ ); - message->SetExtension(unittest::optional_import_enum_extension , unittest_import::IMPORT_BAZ); - - message->SetExtension(unittest::optional_string_piece_extension, "124"); - message->SetExtension(unittest::optional_cord_extension, "125"); - - message->MutableExtension(unittest::optional_public_import_message_extension)->set_e(126); - message->MutableExtension(unittest::optional_lazy_message_extension)->set_bb(127); - - // ----------------------------------------------------------------- - - message->AddExtension(unittest::repeated_int32_extension , 201); - message->AddExtension(unittest::repeated_int64_extension , 202); - message->AddExtension(unittest::repeated_uint32_extension , 203); - message->AddExtension(unittest::repeated_uint64_extension , 204); - message->AddExtension(unittest::repeated_sint32_extension , 205); - message->AddExtension(unittest::repeated_sint64_extension , 206); - message->AddExtension(unittest::repeated_fixed32_extension , 207); - message->AddExtension(unittest::repeated_fixed64_extension , 208); - message->AddExtension(unittest::repeated_sfixed32_extension, 209); - message->AddExtension(unittest::repeated_sfixed64_extension, 210); - message->AddExtension(unittest::repeated_float_extension , 211); - message->AddExtension(unittest::repeated_double_extension , 212); - message->AddExtension(unittest::repeated_bool_extension , true); - message->AddExtension(unittest::repeated_string_extension , "215"); - message->AddExtension(unittest::repeated_bytes_extension , "216"); - - message->AddExtension(unittest::repeatedgroup_extension )->set_a(217); - message->AddExtension(unittest::repeated_nested_message_extension )->set_bb(218); - message->AddExtension(unittest::repeated_foreign_message_extension)->set_c(219); - message->AddExtension(unittest::repeated_import_message_extension )->set_d(220); - message->AddExtension(unittest::repeated_lazy_message_extension )->set_bb(227); - - message->AddExtension(unittest::repeated_nested_enum_extension , unittest::TestAllTypes::BAR); - message->AddExtension(unittest::repeated_foreign_enum_extension, unittest::FOREIGN_BAR ); - message->AddExtension(unittest::repeated_import_enum_extension , unittest_import::IMPORT_BAR); - - message->AddExtension(unittest::repeated_string_piece_extension, "224"); - message->AddExtension(unittest::repeated_cord_extension, "225"); - - // Add a second one of each field. - message->AddExtension(unittest::repeated_int32_extension , 301); - message->AddExtension(unittest::repeated_int64_extension , 302); - message->AddExtension(unittest::repeated_uint32_extension , 303); - message->AddExtension(unittest::repeated_uint64_extension , 304); - message->AddExtension(unittest::repeated_sint32_extension , 305); - message->AddExtension(unittest::repeated_sint64_extension , 306); - message->AddExtension(unittest::repeated_fixed32_extension , 307); - message->AddExtension(unittest::repeated_fixed64_extension , 308); - message->AddExtension(unittest::repeated_sfixed32_extension, 309); - message->AddExtension(unittest::repeated_sfixed64_extension, 310); - message->AddExtension(unittest::repeated_float_extension , 311); - message->AddExtension(unittest::repeated_double_extension , 312); - message->AddExtension(unittest::repeated_bool_extension , false); - message->AddExtension(unittest::repeated_string_extension , "315"); - message->AddExtension(unittest::repeated_bytes_extension , "316"); - - message->AddExtension(unittest::repeatedgroup_extension )->set_a(317); - message->AddExtension(unittest::repeated_nested_message_extension )->set_bb(318); - message->AddExtension(unittest::repeated_foreign_message_extension)->set_c(319); - message->AddExtension(unittest::repeated_import_message_extension )->set_d(320); - message->AddExtension(unittest::repeated_lazy_message_extension )->set_bb(327); - - message->AddExtension(unittest::repeated_nested_enum_extension , unittest::TestAllTypes::BAZ); - message->AddExtension(unittest::repeated_foreign_enum_extension, unittest::FOREIGN_BAZ ); - message->AddExtension(unittest::repeated_import_enum_extension , unittest_import::IMPORT_BAZ); - - message->AddExtension(unittest::repeated_string_piece_extension, "324"); - message->AddExtension(unittest::repeated_cord_extension, "325"); - - // ----------------------------------------------------------------- - - message->SetExtension(unittest::default_int32_extension , 401); - message->SetExtension(unittest::default_int64_extension , 402); - message->SetExtension(unittest::default_uint32_extension , 403); - message->SetExtension(unittest::default_uint64_extension , 404); - message->SetExtension(unittest::default_sint32_extension , 405); - message->SetExtension(unittest::default_sint64_extension , 406); - message->SetExtension(unittest::default_fixed32_extension , 407); - message->SetExtension(unittest::default_fixed64_extension , 408); - message->SetExtension(unittest::default_sfixed32_extension, 409); - message->SetExtension(unittest::default_sfixed64_extension, 410); - message->SetExtension(unittest::default_float_extension , 411); - message->SetExtension(unittest::default_double_extension , 412); - message->SetExtension(unittest::default_bool_extension , false); - message->SetExtension(unittest::default_string_extension , "415"); - message->SetExtension(unittest::default_bytes_extension , "416"); - - message->SetExtension(unittest::default_nested_enum_extension , unittest::TestAllTypes::FOO); - message->SetExtension(unittest::default_foreign_enum_extension, unittest::FOREIGN_FOO ); - message->SetExtension(unittest::default_import_enum_extension , unittest_import::IMPORT_FOO); - - message->SetExtension(unittest::default_string_piece_extension, "424"); - message->SetExtension(unittest::default_cord_extension, "425"); - - SetOneofFields(message); -} - -void TestUtil::SetOneofFields(unittest::TestAllExtensions* message) { - message->SetExtension(unittest::oneof_uint32_extension, 601); - message->MutableExtension(unittest::oneof_nested_message_extension)->set_bb(602); - message->SetExtension(unittest::oneof_string_extension, "603"); - message->SetExtension(unittest::oneof_bytes_extension, "604"); -} - -// ------------------------------------------------------------------- - -void TestUtil::SetAllFieldsAndExtensions( - unittest::TestFieldOrderings* message) { - GOOGLE_CHECK(message); - message->set_my_int(1); - message->set_my_string("foo"); - message->set_my_float(1.0); - message->SetExtension(unittest::my_extension_int, 23); - message->SetExtension(unittest::my_extension_string, "bar"); -} - -// ------------------------------------------------------------------- - -void TestUtil::ModifyRepeatedExtensions(unittest::TestAllExtensions* message) { - message->SetExtension(unittest::repeated_int32_extension , 1, 501); - message->SetExtension(unittest::repeated_int64_extension , 1, 502); - message->SetExtension(unittest::repeated_uint32_extension , 1, 503); - message->SetExtension(unittest::repeated_uint64_extension , 1, 504); - message->SetExtension(unittest::repeated_sint32_extension , 1, 505); - message->SetExtension(unittest::repeated_sint64_extension , 1, 506); - message->SetExtension(unittest::repeated_fixed32_extension , 1, 507); - message->SetExtension(unittest::repeated_fixed64_extension , 1, 508); - message->SetExtension(unittest::repeated_sfixed32_extension, 1, 509); - message->SetExtension(unittest::repeated_sfixed64_extension, 1, 510); - message->SetExtension(unittest::repeated_float_extension , 1, 511); - message->SetExtension(unittest::repeated_double_extension , 1, 512); - message->SetExtension(unittest::repeated_bool_extension , 1, true); - message->SetExtension(unittest::repeated_string_extension , 1, "515"); - message->SetExtension(unittest::repeated_bytes_extension , 1, "516"); - - message->MutableExtension(unittest::repeatedgroup_extension , 1)->set_a(517); - message->MutableExtension(unittest::repeated_nested_message_extension , 1)->set_bb(518); - message->MutableExtension(unittest::repeated_foreign_message_extension, 1)->set_c(519); - message->MutableExtension(unittest::repeated_import_message_extension , 1)->set_d(520); - message->MutableExtension(unittest::repeated_lazy_message_extension , 1)->set_bb(527); - - message->SetExtension(unittest::repeated_nested_enum_extension , 1, unittest::TestAllTypes::FOO); - message->SetExtension(unittest::repeated_foreign_enum_extension, 1, unittest::FOREIGN_FOO ); - message->SetExtension(unittest::repeated_import_enum_extension , 1, unittest_import::IMPORT_FOO); - - message->SetExtension(unittest::repeated_string_piece_extension, 1, "524"); - message->SetExtension(unittest::repeated_cord_extension, 1, "525"); -} - -// ------------------------------------------------------------------- - -void TestUtil::ExpectAllExtensionsSet( - const unittest::TestAllExtensions& message) { - EXPECT_TRUE(message.HasExtension(unittest::optional_int32_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_int64_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_uint32_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_uint64_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_sint32_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_sint64_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_fixed32_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_fixed64_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_sfixed32_extension)); - EXPECT_TRUE(message.HasExtension(unittest::optional_sfixed64_extension)); - EXPECT_TRUE(message.HasExtension(unittest::optional_float_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_double_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_bool_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_bytes_extension )); - - EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_public_import_message_extension)); - EXPECT_TRUE(message.HasExtension(unittest::optional_lazy_message_extension )); - - EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension ).has_a()); - EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension ).has_bb()); - EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension ).has_c()); - EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension ).has_d()); - EXPECT_TRUE(message.GetExtension(unittest::optional_public_import_message_extension).has_e()); - EXPECT_TRUE(message.GetExtension(unittest::optional_lazy_message_extension ).has_bb()); - - EXPECT_TRUE(message.HasExtension(unittest::optional_nested_enum_extension )); - EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_enum_extension)); - EXPECT_TRUE(message.HasExtension(unittest::optional_import_enum_extension )); - - EXPECT_TRUE(message.HasExtension(unittest::optional_string_piece_extension)); - EXPECT_TRUE(message.HasExtension(unittest::optional_cord_extension)); - - EXPECT_EQ(101 , message.GetExtension(unittest::optional_int32_extension )); - EXPECT_EQ(102 , message.GetExtension(unittest::optional_int64_extension )); - EXPECT_EQ(103 , message.GetExtension(unittest::optional_uint32_extension )); - EXPECT_EQ(104 , message.GetExtension(unittest::optional_uint64_extension )); - EXPECT_EQ(105 , message.GetExtension(unittest::optional_sint32_extension )); - EXPECT_EQ(106 , message.GetExtension(unittest::optional_sint64_extension )); - EXPECT_EQ(107 , message.GetExtension(unittest::optional_fixed32_extension )); - EXPECT_EQ(108 , message.GetExtension(unittest::optional_fixed64_extension )); - EXPECT_EQ(109 , message.GetExtension(unittest::optional_sfixed32_extension)); - EXPECT_EQ(110 , message.GetExtension(unittest::optional_sfixed64_extension)); - EXPECT_EQ(111 , message.GetExtension(unittest::optional_float_extension )); - EXPECT_EQ(112 , message.GetExtension(unittest::optional_double_extension )); - EXPECT_TRUE( message.GetExtension(unittest::optional_bool_extension )); - EXPECT_EQ("115", message.GetExtension(unittest::optional_string_extension )); - EXPECT_EQ("116", message.GetExtension(unittest::optional_bytes_extension )); - - EXPECT_EQ(117, message.GetExtension(unittest::optionalgroup_extension ).a()); - EXPECT_EQ(118, message.GetExtension(unittest::optional_nested_message_extension ).bb()); - EXPECT_EQ(119, message.GetExtension(unittest::optional_foreign_message_extension).c()); - EXPECT_EQ(120, message.GetExtension(unittest::optional_import_message_extension ).d()); - - EXPECT_EQ(unittest::TestAllTypes::BAZ, message.GetExtension(unittest::optional_nested_enum_extension )); - EXPECT_EQ(unittest::FOREIGN_BAZ , message.GetExtension(unittest::optional_foreign_enum_extension)); - EXPECT_EQ(unittest_import::IMPORT_BAZ, message.GetExtension(unittest::optional_import_enum_extension )); - - EXPECT_EQ("124", message.GetExtension(unittest::optional_string_piece_extension)); - EXPECT_EQ("125", message.GetExtension(unittest::optional_cord_extension)); - EXPECT_EQ(126, message.GetExtension(unittest::optional_public_import_message_extension ).e()); - EXPECT_EQ(127, message.GetExtension(unittest::optional_lazy_message_extension).bb()); - - // ----------------------------------------------------------------- - - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension )); - - ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension )); - - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_piece_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_cord_extension)); - - EXPECT_EQ(201 , message.GetExtension(unittest::repeated_int32_extension , 0)); - EXPECT_EQ(202 , message.GetExtension(unittest::repeated_int64_extension , 0)); - EXPECT_EQ(203 , message.GetExtension(unittest::repeated_uint32_extension , 0)); - EXPECT_EQ(204 , message.GetExtension(unittest::repeated_uint64_extension , 0)); - EXPECT_EQ(205 , message.GetExtension(unittest::repeated_sint32_extension , 0)); - EXPECT_EQ(206 , message.GetExtension(unittest::repeated_sint64_extension , 0)); - EXPECT_EQ(207 , message.GetExtension(unittest::repeated_fixed32_extension , 0)); - EXPECT_EQ(208 , message.GetExtension(unittest::repeated_fixed64_extension , 0)); - EXPECT_EQ(209 , message.GetExtension(unittest::repeated_sfixed32_extension, 0)); - EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension, 0)); - EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension , 0)); - EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension , 0)); - EXPECT_TRUE( message.GetExtension(unittest::repeated_bool_extension , 0)); - EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension , 0)); - EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension , 0)); - - EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension , 0).a()); - EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb()); - EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c()); - EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d()); - EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb()); - - EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0)); - EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension, 0)); - EXPECT_EQ(unittest_import::IMPORT_BAR, message.GetExtension(unittest::repeated_import_enum_extension , 0)); - - EXPECT_EQ("224", message.GetExtension(unittest::repeated_string_piece_extension, 0)); - EXPECT_EQ("225", message.GetExtension(unittest::repeated_cord_extension, 0)); - - EXPECT_EQ(301 , message.GetExtension(unittest::repeated_int32_extension , 1)); - EXPECT_EQ(302 , message.GetExtension(unittest::repeated_int64_extension , 1)); - EXPECT_EQ(303 , message.GetExtension(unittest::repeated_uint32_extension , 1)); - EXPECT_EQ(304 , message.GetExtension(unittest::repeated_uint64_extension , 1)); - EXPECT_EQ(305 , message.GetExtension(unittest::repeated_sint32_extension , 1)); - EXPECT_EQ(306 , message.GetExtension(unittest::repeated_sint64_extension , 1)); - EXPECT_EQ(307 , message.GetExtension(unittest::repeated_fixed32_extension , 1)); - EXPECT_EQ(308 , message.GetExtension(unittest::repeated_fixed64_extension , 1)); - EXPECT_EQ(309 , message.GetExtension(unittest::repeated_sfixed32_extension, 1)); - EXPECT_EQ(310 , message.GetExtension(unittest::repeated_sfixed64_extension, 1)); - EXPECT_EQ(311 , message.GetExtension(unittest::repeated_float_extension , 1)); - EXPECT_EQ(312 , message.GetExtension(unittest::repeated_double_extension , 1)); - EXPECT_FALSE( message.GetExtension(unittest::repeated_bool_extension , 1)); - EXPECT_EQ("315", message.GetExtension(unittest::repeated_string_extension , 1)); - EXPECT_EQ("316", message.GetExtension(unittest::repeated_bytes_extension , 1)); - - EXPECT_EQ(317, message.GetExtension(unittest::repeatedgroup_extension , 1).a()); - EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb()); - EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c()); - EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension , 1).d()); - EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension , 1).bb()); - - EXPECT_EQ(unittest::TestAllTypes::BAZ, message.GetExtension(unittest::repeated_nested_enum_extension , 1)); - EXPECT_EQ(unittest::FOREIGN_BAZ , message.GetExtension(unittest::repeated_foreign_enum_extension, 1)); - EXPECT_EQ(unittest_import::IMPORT_BAZ, message.GetExtension(unittest::repeated_import_enum_extension , 1)); - - EXPECT_EQ("324", message.GetExtension(unittest::repeated_string_piece_extension, 1)); - EXPECT_EQ("325", message.GetExtension(unittest::repeated_cord_extension, 1)); - - // ----------------------------------------------------------------- - - EXPECT_TRUE(message.HasExtension(unittest::default_int32_extension )); - EXPECT_TRUE(message.HasExtension(unittest::default_int64_extension )); - EXPECT_TRUE(message.HasExtension(unittest::default_uint32_extension )); - EXPECT_TRUE(message.HasExtension(unittest::default_uint64_extension )); - EXPECT_TRUE(message.HasExtension(unittest::default_sint32_extension )); - EXPECT_TRUE(message.HasExtension(unittest::default_sint64_extension )); - EXPECT_TRUE(message.HasExtension(unittest::default_fixed32_extension )); - EXPECT_TRUE(message.HasExtension(unittest::default_fixed64_extension )); - EXPECT_TRUE(message.HasExtension(unittest::default_sfixed32_extension)); - EXPECT_TRUE(message.HasExtension(unittest::default_sfixed64_extension)); - EXPECT_TRUE(message.HasExtension(unittest::default_float_extension )); - EXPECT_TRUE(message.HasExtension(unittest::default_double_extension )); - EXPECT_TRUE(message.HasExtension(unittest::default_bool_extension )); - EXPECT_TRUE(message.HasExtension(unittest::default_string_extension )); - EXPECT_TRUE(message.HasExtension(unittest::default_bytes_extension )); - - EXPECT_TRUE(message.HasExtension(unittest::default_nested_enum_extension )); - EXPECT_TRUE(message.HasExtension(unittest::default_foreign_enum_extension)); - EXPECT_TRUE(message.HasExtension(unittest::default_import_enum_extension )); - - EXPECT_TRUE(message.HasExtension(unittest::default_string_piece_extension)); - EXPECT_TRUE(message.HasExtension(unittest::default_cord_extension)); - - EXPECT_EQ(401 , message.GetExtension(unittest::default_int32_extension )); - EXPECT_EQ(402 , message.GetExtension(unittest::default_int64_extension )); - EXPECT_EQ(403 , message.GetExtension(unittest::default_uint32_extension )); - EXPECT_EQ(404 , message.GetExtension(unittest::default_uint64_extension )); - EXPECT_EQ(405 , message.GetExtension(unittest::default_sint32_extension )); - EXPECT_EQ(406 , message.GetExtension(unittest::default_sint64_extension )); - EXPECT_EQ(407 , message.GetExtension(unittest::default_fixed32_extension )); - EXPECT_EQ(408 , message.GetExtension(unittest::default_fixed64_extension )); - EXPECT_EQ(409 , message.GetExtension(unittest::default_sfixed32_extension)); - EXPECT_EQ(410 , message.GetExtension(unittest::default_sfixed64_extension)); - EXPECT_EQ(411 , message.GetExtension(unittest::default_float_extension )); - EXPECT_EQ(412 , message.GetExtension(unittest::default_double_extension )); - EXPECT_FALSE( message.GetExtension(unittest::default_bool_extension )); - EXPECT_EQ("415", message.GetExtension(unittest::default_string_extension )); - EXPECT_EQ("416", message.GetExtension(unittest::default_bytes_extension )); - - EXPECT_EQ(unittest::TestAllTypes::FOO, message.GetExtension(unittest::default_nested_enum_extension )); - EXPECT_EQ(unittest::FOREIGN_FOO , message.GetExtension(unittest::default_foreign_enum_extension)); - EXPECT_EQ(unittest_import::IMPORT_FOO, message.GetExtension(unittest::default_import_enum_extension )); - - EXPECT_EQ("424", message.GetExtension(unittest::default_string_piece_extension)); - EXPECT_EQ("425", message.GetExtension(unittest::default_cord_extension)); - - EXPECT_TRUE(message.HasExtension(unittest::oneof_uint32_extension)); - EXPECT_TRUE(message.GetExtension(unittest::oneof_nested_message_extension).has_bb()); - EXPECT_TRUE(message.HasExtension(unittest::oneof_string_extension)); - EXPECT_TRUE(message.HasExtension(unittest::oneof_bytes_extension)); - - EXPECT_EQ(601, message.GetExtension(unittest::oneof_uint32_extension)); - EXPECT_EQ(602, message.GetExtension(unittest::oneof_nested_message_extension).bb()); - EXPECT_EQ("603", message.GetExtension(unittest::oneof_string_extension)); - EXPECT_EQ("604", message.GetExtension(unittest::oneof_bytes_extension)); -} - -// ------------------------------------------------------------------- - -void TestUtil::ExpectExtensionsClear( - const unittest::TestAllExtensions& message) { - string serialized; - ASSERT_TRUE(message.SerializeToString(&serialized)); - EXPECT_EQ("", serialized); - EXPECT_EQ(0, message.ByteSize()); - - // has_blah() should initially be false for all optional fields. - EXPECT_FALSE(message.HasExtension(unittest::optional_int32_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_int64_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_uint32_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_uint64_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_sint32_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_sint64_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_fixed32_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_fixed64_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_sfixed32_extension)); - EXPECT_FALSE(message.HasExtension(unittest::optional_sfixed64_extension)); - EXPECT_FALSE(message.HasExtension(unittest::optional_float_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_double_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_bool_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_string_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_bytes_extension )); - - EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_public_import_message_extension)); - EXPECT_FALSE(message.HasExtension(unittest::optional_lazy_message_extension )); - - EXPECT_FALSE(message.HasExtension(unittest::optional_nested_enum_extension )); - EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_enum_extension)); - EXPECT_FALSE(message.HasExtension(unittest::optional_import_enum_extension )); - - EXPECT_FALSE(message.HasExtension(unittest::optional_string_piece_extension)); - EXPECT_FALSE(message.HasExtension(unittest::optional_cord_extension)); - - // Optional fields without defaults are set to zero or something like it. - EXPECT_EQ(0 , message.GetExtension(unittest::optional_int32_extension )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_int64_extension )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_uint32_extension )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_uint64_extension )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_sint32_extension )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_sint64_extension )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_fixed32_extension )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_fixed64_extension )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_sfixed32_extension)); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_sfixed64_extension)); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_float_extension )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_double_extension )); - EXPECT_FALSE( message.GetExtension(unittest::optional_bool_extension )); - EXPECT_EQ("" , message.GetExtension(unittest::optional_string_extension )); - EXPECT_EQ("" , message.GetExtension(unittest::optional_bytes_extension )); - - // Embedded messages should also be clear. - EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension ).has_a()); - EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension ).has_bb()); - EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension ).has_c()); - EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension ).has_d()); - EXPECT_FALSE(message.GetExtension(unittest::optional_public_import_message_extension).has_e()); - EXPECT_FALSE(message.GetExtension(unittest::optional_lazy_message_extension ).has_bb()); - - EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension ).a()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension ).bb()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension ).c()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension ).d()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_public_import_message_extension).e()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_lazy_message_extension ).bb()); - - // Enums without defaults are set to the first value in the enum. - EXPECT_EQ(unittest::TestAllTypes::FOO, message.GetExtension(unittest::optional_nested_enum_extension )); - EXPECT_EQ(unittest::FOREIGN_FOO , message.GetExtension(unittest::optional_foreign_enum_extension)); - EXPECT_EQ(unittest_import::IMPORT_FOO, message.GetExtension(unittest::optional_import_enum_extension )); - - EXPECT_EQ("", message.GetExtension(unittest::optional_string_piece_extension)); - EXPECT_EQ("", message.GetExtension(unittest::optional_cord_extension)); - - // Repeated fields are empty. - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int32_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int64_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint32_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint64_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint32_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint64_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_fixed32_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_fixed64_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sfixed32_extension)); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sfixed64_extension)); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_float_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_double_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bool_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_string_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bytes_extension )); - - EXPECT_EQ(0, message.ExtensionSize(unittest::repeatedgroup_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_message_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_message_extension)); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_message_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_lazy_message_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_enum_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_enum_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_enum_extension )); - - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_string_piece_extension)); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_cord_extension)); - - // has_blah() should also be false for all default fields. - EXPECT_FALSE(message.HasExtension(unittest::default_int32_extension )); - EXPECT_FALSE(message.HasExtension(unittest::default_int64_extension )); - EXPECT_FALSE(message.HasExtension(unittest::default_uint32_extension )); - EXPECT_FALSE(message.HasExtension(unittest::default_uint64_extension )); - EXPECT_FALSE(message.HasExtension(unittest::default_sint32_extension )); - EXPECT_FALSE(message.HasExtension(unittest::default_sint64_extension )); - EXPECT_FALSE(message.HasExtension(unittest::default_fixed32_extension )); - EXPECT_FALSE(message.HasExtension(unittest::default_fixed64_extension )); - EXPECT_FALSE(message.HasExtension(unittest::default_sfixed32_extension)); - EXPECT_FALSE(message.HasExtension(unittest::default_sfixed64_extension)); - EXPECT_FALSE(message.HasExtension(unittest::default_float_extension )); - EXPECT_FALSE(message.HasExtension(unittest::default_double_extension )); - EXPECT_FALSE(message.HasExtension(unittest::default_bool_extension )); - EXPECT_FALSE(message.HasExtension(unittest::default_string_extension )); - EXPECT_FALSE(message.HasExtension(unittest::default_bytes_extension )); - - EXPECT_FALSE(message.HasExtension(unittest::default_nested_enum_extension )); - EXPECT_FALSE(message.HasExtension(unittest::default_foreign_enum_extension)); - EXPECT_FALSE(message.HasExtension(unittest::default_import_enum_extension )); - - EXPECT_FALSE(message.HasExtension(unittest::default_string_piece_extension)); - EXPECT_FALSE(message.HasExtension(unittest::default_cord_extension)); - - // Fields with defaults have their default values (duh). - EXPECT_EQ( 41 , message.GetExtension(unittest::default_int32_extension )); - EXPECT_EQ( 42 , message.GetExtension(unittest::default_int64_extension )); - EXPECT_EQ( 43 , message.GetExtension(unittest::default_uint32_extension )); - EXPECT_EQ( 44 , message.GetExtension(unittest::default_uint64_extension )); - EXPECT_EQ(-45 , message.GetExtension(unittest::default_sint32_extension )); - EXPECT_EQ( 46 , message.GetExtension(unittest::default_sint64_extension )); - EXPECT_EQ( 47 , message.GetExtension(unittest::default_fixed32_extension )); - EXPECT_EQ( 48 , message.GetExtension(unittest::default_fixed64_extension )); - EXPECT_EQ( 49 , message.GetExtension(unittest::default_sfixed32_extension)); - EXPECT_EQ(-50 , message.GetExtension(unittest::default_sfixed64_extension)); - EXPECT_EQ( 51.5 , message.GetExtension(unittest::default_float_extension )); - EXPECT_EQ( 52e3 , message.GetExtension(unittest::default_double_extension )); - EXPECT_TRUE( message.GetExtension(unittest::default_bool_extension )); - EXPECT_EQ("hello", message.GetExtension(unittest::default_string_extension )); - EXPECT_EQ("world", message.GetExtension(unittest::default_bytes_extension )); - - EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::default_nested_enum_extension )); - EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::default_foreign_enum_extension)); - EXPECT_EQ(unittest_import::IMPORT_BAR, message.GetExtension(unittest::default_import_enum_extension )); - - EXPECT_EQ("abc", message.GetExtension(unittest::default_string_piece_extension)); - EXPECT_EQ("123", message.GetExtension(unittest::default_cord_extension)); - - EXPECT_FALSE(message.HasExtension(unittest::oneof_uint32_extension)); - EXPECT_FALSE(message.GetExtension(unittest::oneof_nested_message_extension).has_bb()); - EXPECT_FALSE(message.HasExtension(unittest::oneof_string_extension)); - EXPECT_FALSE(message.HasExtension(unittest::oneof_bytes_extension)); -} - -// ------------------------------------------------------------------- - -void TestUtil::ExpectRepeatedExtensionsModified( - const unittest::TestAllExtensions& message) { - // ModifyRepeatedFields only sets the second repeated element of each - // field. In addition to verifying this, we also verify that the first - // element and size were *not* modified. - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension )); - - ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension )); - - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_piece_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_cord_extension)); - - EXPECT_EQ(201 , message.GetExtension(unittest::repeated_int32_extension , 0)); - EXPECT_EQ(202 , message.GetExtension(unittest::repeated_int64_extension , 0)); - EXPECT_EQ(203 , message.GetExtension(unittest::repeated_uint32_extension , 0)); - EXPECT_EQ(204 , message.GetExtension(unittest::repeated_uint64_extension , 0)); - EXPECT_EQ(205 , message.GetExtension(unittest::repeated_sint32_extension , 0)); - EXPECT_EQ(206 , message.GetExtension(unittest::repeated_sint64_extension , 0)); - EXPECT_EQ(207 , message.GetExtension(unittest::repeated_fixed32_extension , 0)); - EXPECT_EQ(208 , message.GetExtension(unittest::repeated_fixed64_extension , 0)); - EXPECT_EQ(209 , message.GetExtension(unittest::repeated_sfixed32_extension, 0)); - EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension, 0)); - EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension , 0)); - EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension , 0)); - EXPECT_TRUE( message.GetExtension(unittest::repeated_bool_extension , 0)); - EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension , 0)); - EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension , 0)); - - EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension , 0).a()); - EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb()); - EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c()); - EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d()); - EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb()); - - EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0)); - EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension, 0)); - EXPECT_EQ(unittest_import::IMPORT_BAR, message.GetExtension(unittest::repeated_import_enum_extension , 0)); - - EXPECT_EQ("224", message.GetExtension(unittest::repeated_string_piece_extension, 0)); - EXPECT_EQ("225", message.GetExtension(unittest::repeated_cord_extension, 0)); - - // Actually verify the second (modified) elements now. - EXPECT_EQ(501 , message.GetExtension(unittest::repeated_int32_extension , 1)); - EXPECT_EQ(502 , message.GetExtension(unittest::repeated_int64_extension , 1)); - EXPECT_EQ(503 , message.GetExtension(unittest::repeated_uint32_extension , 1)); - EXPECT_EQ(504 , message.GetExtension(unittest::repeated_uint64_extension , 1)); - EXPECT_EQ(505 , message.GetExtension(unittest::repeated_sint32_extension , 1)); - EXPECT_EQ(506 , message.GetExtension(unittest::repeated_sint64_extension , 1)); - EXPECT_EQ(507 , message.GetExtension(unittest::repeated_fixed32_extension , 1)); - EXPECT_EQ(508 , message.GetExtension(unittest::repeated_fixed64_extension , 1)); - EXPECT_EQ(509 , message.GetExtension(unittest::repeated_sfixed32_extension, 1)); - EXPECT_EQ(510 , message.GetExtension(unittest::repeated_sfixed64_extension, 1)); - EXPECT_EQ(511 , message.GetExtension(unittest::repeated_float_extension , 1)); - EXPECT_EQ(512 , message.GetExtension(unittest::repeated_double_extension , 1)); - EXPECT_TRUE( message.GetExtension(unittest::repeated_bool_extension , 1)); - EXPECT_EQ("515", message.GetExtension(unittest::repeated_string_extension , 1)); - EXPECT_EQ("516", message.GetExtension(unittest::repeated_bytes_extension , 1)); - - EXPECT_EQ(517, message.GetExtension(unittest::repeatedgroup_extension , 1).a()); - EXPECT_EQ(518, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb()); - EXPECT_EQ(519, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c()); - EXPECT_EQ(520, message.GetExtension(unittest::repeated_import_message_extension , 1).d()); - EXPECT_EQ(527, message.GetExtension(unittest::repeated_lazy_message_extension , 1).bb()); - - EXPECT_EQ(unittest::TestAllTypes::FOO, message.GetExtension(unittest::repeated_nested_enum_extension , 1)); - EXPECT_EQ(unittest::FOREIGN_FOO , message.GetExtension(unittest::repeated_foreign_enum_extension, 1)); - EXPECT_EQ(unittest_import::IMPORT_FOO, message.GetExtension(unittest::repeated_import_enum_extension , 1)); - - EXPECT_EQ("524", message.GetExtension(unittest::repeated_string_piece_extension, 1)); - EXPECT_EQ("525", message.GetExtension(unittest::repeated_cord_extension, 1)); -} - -// ------------------------------------------------------------------- - -void TestUtil::SetPackedExtensions(unittest::TestPackedExtensions* message) { - message->AddExtension(unittest::packed_int32_extension , 601); - message->AddExtension(unittest::packed_int64_extension , 602); - message->AddExtension(unittest::packed_uint32_extension , 603); - message->AddExtension(unittest::packed_uint64_extension , 604); - message->AddExtension(unittest::packed_sint32_extension , 605); - message->AddExtension(unittest::packed_sint64_extension , 606); - message->AddExtension(unittest::packed_fixed32_extension , 607); - message->AddExtension(unittest::packed_fixed64_extension , 608); - message->AddExtension(unittest::packed_sfixed32_extension, 609); - message->AddExtension(unittest::packed_sfixed64_extension, 610); - message->AddExtension(unittest::packed_float_extension , 611); - message->AddExtension(unittest::packed_double_extension , 612); - message->AddExtension(unittest::packed_bool_extension , true); - message->AddExtension(unittest::packed_enum_extension, unittest::FOREIGN_BAR); - // add a second one of each field - message->AddExtension(unittest::packed_int32_extension , 701); - message->AddExtension(unittest::packed_int64_extension , 702); - message->AddExtension(unittest::packed_uint32_extension , 703); - message->AddExtension(unittest::packed_uint64_extension , 704); - message->AddExtension(unittest::packed_sint32_extension , 705); - message->AddExtension(unittest::packed_sint64_extension , 706); - message->AddExtension(unittest::packed_fixed32_extension , 707); - message->AddExtension(unittest::packed_fixed64_extension , 708); - message->AddExtension(unittest::packed_sfixed32_extension, 709); - message->AddExtension(unittest::packed_sfixed64_extension, 710); - message->AddExtension(unittest::packed_float_extension , 711); - message->AddExtension(unittest::packed_double_extension , 712); - message->AddExtension(unittest::packed_bool_extension , false); - message->AddExtension(unittest::packed_enum_extension, unittest::FOREIGN_BAZ); -} - -// ------------------------------------------------------------------- - -void TestUtil::ModifyPackedExtensions(unittest::TestPackedExtensions* message) { - message->SetExtension(unittest::packed_int32_extension , 1, 801); - message->SetExtension(unittest::packed_int64_extension , 1, 802); - message->SetExtension(unittest::packed_uint32_extension , 1, 803); - message->SetExtension(unittest::packed_uint64_extension , 1, 804); - message->SetExtension(unittest::packed_sint32_extension , 1, 805); - message->SetExtension(unittest::packed_sint64_extension , 1, 806); - message->SetExtension(unittest::packed_fixed32_extension , 1, 807); - message->SetExtension(unittest::packed_fixed64_extension , 1, 808); - message->SetExtension(unittest::packed_sfixed32_extension, 1, 809); - message->SetExtension(unittest::packed_sfixed64_extension, 1, 810); - message->SetExtension(unittest::packed_float_extension , 1, 811); - message->SetExtension(unittest::packed_double_extension , 1, 812); - message->SetExtension(unittest::packed_bool_extension , 1, true); - message->SetExtension(unittest::packed_enum_extension , 1, - unittest::FOREIGN_FOO); -} - -// ------------------------------------------------------------------- - -void TestUtil::ExpectPackedExtensionsSet( - const unittest::TestPackedExtensions& message) { - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension )); - - EXPECT_EQ(601 , message.GetExtension(unittest::packed_int32_extension , 0)); - EXPECT_EQ(602 , message.GetExtension(unittest::packed_int64_extension , 0)); - EXPECT_EQ(603 , message.GetExtension(unittest::packed_uint32_extension , 0)); - EXPECT_EQ(604 , message.GetExtension(unittest::packed_uint64_extension , 0)); - EXPECT_EQ(605 , message.GetExtension(unittest::packed_sint32_extension , 0)); - EXPECT_EQ(606 , message.GetExtension(unittest::packed_sint64_extension , 0)); - EXPECT_EQ(607 , message.GetExtension(unittest::packed_fixed32_extension , 0)); - EXPECT_EQ(608 , message.GetExtension(unittest::packed_fixed64_extension , 0)); - EXPECT_EQ(609 , message.GetExtension(unittest::packed_sfixed32_extension, 0)); - EXPECT_EQ(610 , message.GetExtension(unittest::packed_sfixed64_extension, 0)); - EXPECT_EQ(611 , message.GetExtension(unittest::packed_float_extension , 0)); - EXPECT_EQ(612 , message.GetExtension(unittest::packed_double_extension , 0)); - EXPECT_TRUE( message.GetExtension(unittest::packed_bool_extension , 0)); - EXPECT_EQ(unittest::FOREIGN_BAR, - message.GetExtension(unittest::packed_enum_extension, 0)); - EXPECT_EQ(701 , message.GetExtension(unittest::packed_int32_extension , 1)); - EXPECT_EQ(702 , message.GetExtension(unittest::packed_int64_extension , 1)); - EXPECT_EQ(703 , message.GetExtension(unittest::packed_uint32_extension , 1)); - EXPECT_EQ(704 , message.GetExtension(unittest::packed_uint64_extension , 1)); - EXPECT_EQ(705 , message.GetExtension(unittest::packed_sint32_extension , 1)); - EXPECT_EQ(706 , message.GetExtension(unittest::packed_sint64_extension , 1)); - EXPECT_EQ(707 , message.GetExtension(unittest::packed_fixed32_extension , 1)); - EXPECT_EQ(708 , message.GetExtension(unittest::packed_fixed64_extension , 1)); - EXPECT_EQ(709 , message.GetExtension(unittest::packed_sfixed32_extension, 1)); - EXPECT_EQ(710 , message.GetExtension(unittest::packed_sfixed64_extension, 1)); - EXPECT_EQ(711 , message.GetExtension(unittest::packed_float_extension , 1)); - EXPECT_EQ(712 , message.GetExtension(unittest::packed_double_extension , 1)); - EXPECT_FALSE( message.GetExtension(unittest::packed_bool_extension , 1)); - EXPECT_EQ(unittest::FOREIGN_BAZ, - message.GetExtension(unittest::packed_enum_extension, 1)); -} - -// ------------------------------------------------------------------- - -void TestUtil::ExpectPackedExtensionsClear( - const unittest::TestPackedExtensions& message) { - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int32_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int64_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint32_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint64_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint32_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint64_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed32_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed64_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed32_extension)); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed64_extension)); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_float_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_double_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_bool_extension )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_enum_extension )); -} - -// ------------------------------------------------------------------- - -void TestUtil::ExpectPackedExtensionsModified( - const unittest::TestPackedExtensions& message) { - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension )); - EXPECT_EQ(601 , message.GetExtension(unittest::packed_int32_extension , 0)); - EXPECT_EQ(602 , message.GetExtension(unittest::packed_int64_extension , 0)); - EXPECT_EQ(603 , message.GetExtension(unittest::packed_uint32_extension , 0)); - EXPECT_EQ(604 , message.GetExtension(unittest::packed_uint64_extension , 0)); - EXPECT_EQ(605 , message.GetExtension(unittest::packed_sint32_extension , 0)); - EXPECT_EQ(606 , message.GetExtension(unittest::packed_sint64_extension , 0)); - EXPECT_EQ(607 , message.GetExtension(unittest::packed_fixed32_extension , 0)); - EXPECT_EQ(608 , message.GetExtension(unittest::packed_fixed64_extension , 0)); - EXPECT_EQ(609 , message.GetExtension(unittest::packed_sfixed32_extension, 0)); - EXPECT_EQ(610 , message.GetExtension(unittest::packed_sfixed64_extension, 0)); - EXPECT_EQ(611 , message.GetExtension(unittest::packed_float_extension , 0)); - EXPECT_EQ(612 , message.GetExtension(unittest::packed_double_extension , 0)); - EXPECT_TRUE( message.GetExtension(unittest::packed_bool_extension , 0)); - EXPECT_EQ(unittest::FOREIGN_BAR, - message.GetExtension(unittest::packed_enum_extension, 0)); - - // Actually verify the second (modified) elements now. - EXPECT_EQ(801 , message.GetExtension(unittest::packed_int32_extension , 1)); - EXPECT_EQ(802 , message.GetExtension(unittest::packed_int64_extension , 1)); - EXPECT_EQ(803 , message.GetExtension(unittest::packed_uint32_extension , 1)); - EXPECT_EQ(804 , message.GetExtension(unittest::packed_uint64_extension , 1)); - EXPECT_EQ(805 , message.GetExtension(unittest::packed_sint32_extension , 1)); - EXPECT_EQ(806 , message.GetExtension(unittest::packed_sint64_extension , 1)); - EXPECT_EQ(807 , message.GetExtension(unittest::packed_fixed32_extension , 1)); - EXPECT_EQ(808 , message.GetExtension(unittest::packed_fixed64_extension , 1)); - EXPECT_EQ(809 , message.GetExtension(unittest::packed_sfixed32_extension, 1)); - EXPECT_EQ(810 , message.GetExtension(unittest::packed_sfixed64_extension, 1)); - EXPECT_EQ(811 , message.GetExtension(unittest::packed_float_extension , 1)); - EXPECT_EQ(812 , message.GetExtension(unittest::packed_double_extension , 1)); - EXPECT_TRUE( message.GetExtension(unittest::packed_bool_extension , 1)); - EXPECT_EQ(unittest::FOREIGN_FOO, - message.GetExtension(unittest::packed_enum_extension, 1)); -} - -// ------------------------------------------------------------------- - -void TestUtil::ExpectUnpackedExtensionsSet( - const unittest::TestUnpackedExtensions& message) { - ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_int32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_int64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_uint32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_uint64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sint32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sint64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_fixed32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_fixed64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sfixed32_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sfixed64_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_float_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_double_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_bool_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_enum_extension )); - - EXPECT_EQ(601 , message.GetExtension(unittest::unpacked_int32_extension , 0)); - EXPECT_EQ(602 , message.GetExtension(unittest::unpacked_int64_extension , 0)); - EXPECT_EQ(603 , message.GetExtension(unittest::unpacked_uint32_extension , 0)); - EXPECT_EQ(604 , message.GetExtension(unittest::unpacked_uint64_extension , 0)); - EXPECT_EQ(605 , message.GetExtension(unittest::unpacked_sint32_extension , 0)); - EXPECT_EQ(606 , message.GetExtension(unittest::unpacked_sint64_extension , 0)); - EXPECT_EQ(607 , message.GetExtension(unittest::unpacked_fixed32_extension , 0)); - EXPECT_EQ(608 , message.GetExtension(unittest::unpacked_fixed64_extension , 0)); - EXPECT_EQ(609 , message.GetExtension(unittest::unpacked_sfixed32_extension, 0)); - EXPECT_EQ(610 , message.GetExtension(unittest::unpacked_sfixed64_extension, 0)); - EXPECT_EQ(611 , message.GetExtension(unittest::unpacked_float_extension , 0)); - EXPECT_EQ(612 , message.GetExtension(unittest::unpacked_double_extension , 0)); - EXPECT_EQ(true , message.GetExtension(unittest::unpacked_bool_extension , 0)); - EXPECT_EQ(unittest::FOREIGN_BAR, - message.GetExtension(unittest::unpacked_enum_extension, 0)); - EXPECT_EQ(701 , message.GetExtension(unittest::unpacked_int32_extension , 1)); - EXPECT_EQ(702 , message.GetExtension(unittest::unpacked_int64_extension , 1)); - EXPECT_EQ(703 , message.GetExtension(unittest::unpacked_uint32_extension , 1)); - EXPECT_EQ(704 , message.GetExtension(unittest::unpacked_uint64_extension , 1)); - EXPECT_EQ(705 , message.GetExtension(unittest::unpacked_sint32_extension , 1)); - EXPECT_EQ(706 , message.GetExtension(unittest::unpacked_sint64_extension , 1)); - EXPECT_EQ(707 , message.GetExtension(unittest::unpacked_fixed32_extension , 1)); - EXPECT_EQ(708 , message.GetExtension(unittest::unpacked_fixed64_extension , 1)); - EXPECT_EQ(709 , message.GetExtension(unittest::unpacked_sfixed32_extension, 1)); - EXPECT_EQ(710 , message.GetExtension(unittest::unpacked_sfixed64_extension, 1)); - EXPECT_EQ(711 , message.GetExtension(unittest::unpacked_float_extension , 1)); - EXPECT_EQ(712 , message.GetExtension(unittest::unpacked_double_extension , 1)); - EXPECT_EQ(false, message.GetExtension(unittest::unpacked_bool_extension , 1)); - EXPECT_EQ(unittest::FOREIGN_BAZ, - message.GetExtension(unittest::unpacked_enum_extension, 1)); -} - -// ------------------------------------------------------------------- - -void TestUtil::ExpectAllFieldsAndExtensionsInOrder(const string& serialized) { - // We set each field individually, serialize separately, and concatenate all - // the strings in canonical order to determine the expected serialization. - string expected; - unittest::TestFieldOrderings message; - message.set_my_int(1); // Field 1. - message.AppendToString(&expected); - message.Clear(); - message.SetExtension(unittest::my_extension_int, 23); // Field 5. - message.AppendToString(&expected); - message.Clear(); - message.set_my_string("foo"); // Field 11. - message.AppendToString(&expected); - message.Clear(); - message.SetExtension(unittest::my_extension_string, "bar"); // Field 50. - message.AppendToString(&expected); - message.Clear(); - message.set_my_float(1.0); // Field 101. - message.AppendToString(&expected); - message.Clear(); - - // We don't EXPECT_EQ() since we don't want to print raw bytes to stdout. - EXPECT_TRUE(serialized == expected); -} - -void TestUtil::ExpectLastRepeatedsRemoved( - const unittest::TestAllTypes& message) { - ASSERT_EQ(1, message.repeated_int32_size ()); - ASSERT_EQ(1, message.repeated_int64_size ()); - ASSERT_EQ(1, message.repeated_uint32_size ()); - ASSERT_EQ(1, message.repeated_uint64_size ()); - ASSERT_EQ(1, message.repeated_sint32_size ()); - ASSERT_EQ(1, message.repeated_sint64_size ()); - ASSERT_EQ(1, message.repeated_fixed32_size ()); - ASSERT_EQ(1, message.repeated_fixed64_size ()); - ASSERT_EQ(1, message.repeated_sfixed32_size()); - ASSERT_EQ(1, message.repeated_sfixed64_size()); - ASSERT_EQ(1, message.repeated_float_size ()); - ASSERT_EQ(1, message.repeated_double_size ()); - ASSERT_EQ(1, message.repeated_bool_size ()); - ASSERT_EQ(1, message.repeated_string_size ()); - ASSERT_EQ(1, message.repeated_bytes_size ()); - - ASSERT_EQ(1, message.repeatedgroup_size ()); - ASSERT_EQ(1, message.repeated_nested_message_size ()); - ASSERT_EQ(1, message.repeated_foreign_message_size()); - ASSERT_EQ(1, message.repeated_import_message_size ()); - ASSERT_EQ(1, message.repeated_import_message_size ()); - ASSERT_EQ(1, message.repeated_nested_enum_size ()); - ASSERT_EQ(1, message.repeated_foreign_enum_size ()); - ASSERT_EQ(1, message.repeated_import_enum_size ()); - -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - ASSERT_EQ(1, message.repeated_string_piece_size()); - ASSERT_EQ(1, message.repeated_cord_size()); -#endif - - // Test that the remaining element is the correct one. - EXPECT_EQ(201 , message.repeated_int32 (0)); - EXPECT_EQ(202 , message.repeated_int64 (0)); - EXPECT_EQ(203 , message.repeated_uint32 (0)); - EXPECT_EQ(204 , message.repeated_uint64 (0)); - EXPECT_EQ(205 , message.repeated_sint32 (0)); - EXPECT_EQ(206 , message.repeated_sint64 (0)); - EXPECT_EQ(207 , message.repeated_fixed32 (0)); - EXPECT_EQ(208 , message.repeated_fixed64 (0)); - EXPECT_EQ(209 , message.repeated_sfixed32(0)); - EXPECT_EQ(210 , message.repeated_sfixed64(0)); - EXPECT_EQ(211 , message.repeated_float (0)); - EXPECT_EQ(212 , message.repeated_double (0)); - EXPECT_TRUE( message.repeated_bool (0)); - EXPECT_EQ("215", message.repeated_string (0)); - EXPECT_EQ("216", message.repeated_bytes (0)); - - EXPECT_EQ(217, message.repeatedgroup (0).a()); - EXPECT_EQ(218, message.repeated_nested_message (0).bb()); - EXPECT_EQ(219, message.repeated_foreign_message(0).c()); - EXPECT_EQ(220, message.repeated_import_message (0).d()); - EXPECT_EQ(220, message.repeated_import_message (0).d()); - - EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0)); - EXPECT_EQ(unittest::FOREIGN_BAR , message.repeated_foreign_enum(0)); - EXPECT_EQ(unittest_import::IMPORT_BAR, message.repeated_import_enum (0)); -} - -void TestUtil::ExpectLastRepeatedExtensionsRemoved( - const unittest::TestAllExtensions& message) { - - // Test that one element was removed. - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_int32_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_int64_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_uint32_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_uint64_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_sint32_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_sint64_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_fixed32_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_fixed64_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_sfixed32_extension)); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_sfixed64_extension)); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_float_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_double_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_bool_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_string_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_bytes_extension )); - - ASSERT_EQ(1, message.ExtensionSize(unittest::repeatedgroup_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_message_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_message_extension)); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_message_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_lazy_message_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_enum_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_enum_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_enum_extension )); - - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_string_piece_extension)); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_cord_extension)); - - // Test that the remaining element is the correct one. - EXPECT_EQ(201 , message.GetExtension(unittest::repeated_int32_extension , 0)); - EXPECT_EQ(202 , message.GetExtension(unittest::repeated_int64_extension , 0)); - EXPECT_EQ(203 , message.GetExtension(unittest::repeated_uint32_extension , 0)); - EXPECT_EQ(204 , message.GetExtension(unittest::repeated_uint64_extension , 0)); - EXPECT_EQ(205 , message.GetExtension(unittest::repeated_sint32_extension , 0)); - EXPECT_EQ(206 , message.GetExtension(unittest::repeated_sint64_extension , 0)); - EXPECT_EQ(207 , message.GetExtension(unittest::repeated_fixed32_extension , 0)); - EXPECT_EQ(208 , message.GetExtension(unittest::repeated_fixed64_extension , 0)); - EXPECT_EQ(209 , message.GetExtension(unittest::repeated_sfixed32_extension, 0)); - EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension, 0)); - EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension , 0)); - EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension , 0)); - EXPECT_TRUE( message.GetExtension(unittest::repeated_bool_extension , 0)); - EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension , 0)); - EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension , 0)); - - EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension , 0).a()); - EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb()); - EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c()); - EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d()); - EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb()); - - EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0)); - EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension, 0)); - EXPECT_EQ(unittest_import::IMPORT_BAR, message.GetExtension(unittest::repeated_import_enum_extension , 0)); - - EXPECT_EQ("224", message.GetExtension(unittest::repeated_string_piece_extension, 0)); - EXPECT_EQ("225", message.GetExtension(unittest::repeated_cord_extension, 0)); -} - -void TestUtil::ExpectLastRepeatedsReleased( - const unittest::TestAllTypes& message) { - ASSERT_EQ(1, message.repeatedgroup_size ()); - ASSERT_EQ(1, message.repeated_nested_message_size ()); - ASSERT_EQ(1, message.repeated_foreign_message_size()); - ASSERT_EQ(1, message.repeated_import_message_size ()); - ASSERT_EQ(1, message.repeated_import_message_size ()); - - EXPECT_EQ(217, message.repeatedgroup (0).a()); - EXPECT_EQ(218, message.repeated_nested_message (0).bb()); - EXPECT_EQ(219, message.repeated_foreign_message(0).c()); - EXPECT_EQ(220, message.repeated_import_message (0).d()); - EXPECT_EQ(220, message.repeated_import_message (0).d()); -} - -void TestUtil::ExpectLastRepeatedExtensionsReleased( - const unittest::TestAllExtensions& message) { - ASSERT_EQ(1, message.ExtensionSize(unittest::repeatedgroup_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_message_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_message_extension)); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_message_extension )); - ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_lazy_message_extension )); - - EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension , 0).a()); - EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb()); - EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c()); - EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d()); - EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb()); -} - -void TestUtil::ExpectRepeatedsSwapped( - const unittest::TestAllTypes& message) { - ASSERT_EQ(2, message.repeated_int32_size ()); - ASSERT_EQ(2, message.repeated_int64_size ()); - ASSERT_EQ(2, message.repeated_uint32_size ()); - ASSERT_EQ(2, message.repeated_uint64_size ()); - ASSERT_EQ(2, message.repeated_sint32_size ()); - ASSERT_EQ(2, message.repeated_sint64_size ()); - ASSERT_EQ(2, message.repeated_fixed32_size ()); - ASSERT_EQ(2, message.repeated_fixed64_size ()); - ASSERT_EQ(2, message.repeated_sfixed32_size()); - ASSERT_EQ(2, message.repeated_sfixed64_size()); - ASSERT_EQ(2, message.repeated_float_size ()); - ASSERT_EQ(2, message.repeated_double_size ()); - ASSERT_EQ(2, message.repeated_bool_size ()); - ASSERT_EQ(2, message.repeated_string_size ()); - ASSERT_EQ(2, message.repeated_bytes_size ()); - - ASSERT_EQ(2, message.repeatedgroup_size ()); - ASSERT_EQ(2, message.repeated_nested_message_size ()); - ASSERT_EQ(2, message.repeated_foreign_message_size()); - ASSERT_EQ(2, message.repeated_import_message_size ()); - ASSERT_EQ(2, message.repeated_import_message_size ()); - ASSERT_EQ(2, message.repeated_nested_enum_size ()); - ASSERT_EQ(2, message.repeated_foreign_enum_size ()); - ASSERT_EQ(2, message.repeated_import_enum_size ()); - -#ifndef PROTOBUF_TEST_NO_DESCRIPTORS - ASSERT_EQ(2, message.repeated_string_piece_size()); - ASSERT_EQ(2, message.repeated_cord_size()); -#endif - - // Test that the first element and second element are flipped. - EXPECT_EQ(201 , message.repeated_int32 (1)); - EXPECT_EQ(202 , message.repeated_int64 (1)); - EXPECT_EQ(203 , message.repeated_uint32 (1)); - EXPECT_EQ(204 , message.repeated_uint64 (1)); - EXPECT_EQ(205 , message.repeated_sint32 (1)); - EXPECT_EQ(206 , message.repeated_sint64 (1)); - EXPECT_EQ(207 , message.repeated_fixed32 (1)); - EXPECT_EQ(208 , message.repeated_fixed64 (1)); - EXPECT_EQ(209 , message.repeated_sfixed32(1)); - EXPECT_EQ(210 , message.repeated_sfixed64(1)); - EXPECT_EQ(211 , message.repeated_float (1)); - EXPECT_EQ(212 , message.repeated_double (1)); - EXPECT_TRUE( message.repeated_bool (1)); - EXPECT_EQ("215", message.repeated_string (1)); - EXPECT_EQ("216", message.repeated_bytes (1)); - - EXPECT_EQ(217, message.repeatedgroup (1).a()); - EXPECT_EQ(218, message.repeated_nested_message (1).bb()); - EXPECT_EQ(219, message.repeated_foreign_message(1).c()); - EXPECT_EQ(220, message.repeated_import_message (1).d()); - EXPECT_EQ(220, message.repeated_import_message (1).d()); - - EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (1)); - EXPECT_EQ(unittest::FOREIGN_BAR , message.repeated_foreign_enum(1)); - EXPECT_EQ(unittest_import::IMPORT_BAR, message.repeated_import_enum (1)); - - EXPECT_EQ(301 , message.repeated_int32 (0)); - EXPECT_EQ(302 , message.repeated_int64 (0)); - EXPECT_EQ(303 , message.repeated_uint32 (0)); - EXPECT_EQ(304 , message.repeated_uint64 (0)); - EXPECT_EQ(305 , message.repeated_sint32 (0)); - EXPECT_EQ(306 , message.repeated_sint64 (0)); - EXPECT_EQ(307 , message.repeated_fixed32 (0)); - EXPECT_EQ(308 , message.repeated_fixed64 (0)); - EXPECT_EQ(309 , message.repeated_sfixed32(0)); - EXPECT_EQ(310 , message.repeated_sfixed64(0)); - EXPECT_EQ(311 , message.repeated_float (0)); - EXPECT_EQ(312 , message.repeated_double (0)); - EXPECT_FALSE( message.repeated_bool (0)); - EXPECT_EQ("315", message.repeated_string (0)); - EXPECT_EQ("316", message.repeated_bytes (0)); - - EXPECT_EQ(317, message.repeatedgroup (0).a()); - EXPECT_EQ(318, message.repeated_nested_message (0).bb()); - EXPECT_EQ(319, message.repeated_foreign_message(0).c()); - EXPECT_EQ(320, message.repeated_import_message (0).d()); - EXPECT_EQ(320, message.repeated_import_message (0).d()); - - EXPECT_EQ(unittest::TestAllTypes::BAZ, message.repeated_nested_enum (0)); - EXPECT_EQ(unittest::FOREIGN_BAZ , message.repeated_foreign_enum(0)); - EXPECT_EQ(unittest_import::IMPORT_BAZ, message.repeated_import_enum (0)); -} - -void TestUtil::ExpectRepeatedExtensionsSwapped( - const unittest::TestAllExtensions& message) { - - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension )); - - ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension )); - - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_piece_extension)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_cord_extension)); - - EXPECT_EQ(201 , message.GetExtension(unittest::repeated_int32_extension , 1)); - EXPECT_EQ(202 , message.GetExtension(unittest::repeated_int64_extension , 1)); - EXPECT_EQ(203 , message.GetExtension(unittest::repeated_uint32_extension , 1)); - EXPECT_EQ(204 , message.GetExtension(unittest::repeated_uint64_extension , 1)); - EXPECT_EQ(205 , message.GetExtension(unittest::repeated_sint32_extension , 1)); - EXPECT_EQ(206 , message.GetExtension(unittest::repeated_sint64_extension , 1)); - EXPECT_EQ(207 , message.GetExtension(unittest::repeated_fixed32_extension , 1)); - EXPECT_EQ(208 , message.GetExtension(unittest::repeated_fixed64_extension , 1)); - EXPECT_EQ(209 , message.GetExtension(unittest::repeated_sfixed32_extension, 1)); - EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension, 1)); - EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension , 1)); - EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension , 1)); - EXPECT_TRUE( message.GetExtension(unittest::repeated_bool_extension , 1)); - EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension , 1)); - EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension , 1)); - - EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension , 1).a()); - EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb()); - EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c()); - EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 1).d()); - EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 1).bb()); - - EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 1)); - EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension, 1)); - EXPECT_EQ(unittest_import::IMPORT_BAR, message.GetExtension(unittest::repeated_import_enum_extension , 1)); - - EXPECT_EQ("224", message.GetExtension(unittest::repeated_string_piece_extension, 1)); - EXPECT_EQ("225", message.GetExtension(unittest::repeated_cord_extension, 1)); - - EXPECT_EQ(301 , message.GetExtension(unittest::repeated_int32_extension , 0)); - EXPECT_EQ(302 , message.GetExtension(unittest::repeated_int64_extension , 0)); - EXPECT_EQ(303 , message.GetExtension(unittest::repeated_uint32_extension , 0)); - EXPECT_EQ(304 , message.GetExtension(unittest::repeated_uint64_extension , 0)); - EXPECT_EQ(305 , message.GetExtension(unittest::repeated_sint32_extension , 0)); - EXPECT_EQ(306 , message.GetExtension(unittest::repeated_sint64_extension , 0)); - EXPECT_EQ(307 , message.GetExtension(unittest::repeated_fixed32_extension , 0)); - EXPECT_EQ(308 , message.GetExtension(unittest::repeated_fixed64_extension , 0)); - EXPECT_EQ(309 , message.GetExtension(unittest::repeated_sfixed32_extension, 0)); - EXPECT_EQ(310 , message.GetExtension(unittest::repeated_sfixed64_extension, 0)); - EXPECT_EQ(311 , message.GetExtension(unittest::repeated_float_extension , 0)); - EXPECT_EQ(312 , message.GetExtension(unittest::repeated_double_extension , 0)); - EXPECT_FALSE( message.GetExtension(unittest::repeated_bool_extension , 0)); - EXPECT_EQ("315", message.GetExtension(unittest::repeated_string_extension , 0)); - EXPECT_EQ("316", message.GetExtension(unittest::repeated_bytes_extension , 0)); - - EXPECT_EQ(317, message.GetExtension(unittest::repeatedgroup_extension , 0).a()); - EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb()); - EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c()); - EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension , 0).d()); - EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb()); - - EXPECT_EQ(unittest::TestAllTypes::BAZ, message.GetExtension(unittest::repeated_nested_enum_extension , 0)); - EXPECT_EQ(unittest::FOREIGN_BAZ , message.GetExtension(unittest::repeated_foreign_enum_extension, 0)); - EXPECT_EQ(unittest_import::IMPORT_BAZ, message.GetExtension(unittest::repeated_import_enum_extension , 0)); - - EXPECT_EQ("324", message.GetExtension(unittest::repeated_string_piece_extension, 0)); - EXPECT_EQ("325", message.GetExtension(unittest::repeated_cord_extension, 0)); -} - -void TestUtil::SetOneof1(unittest::TestOneof2* message) { - message->mutable_foo_lazy_message()->set_qux_int(100); - message->set_bar_string("101"); - message->set_baz_int(102); - message->set_baz_string("103"); -} - -void TestUtil::SetOneof2(unittest::TestOneof2* message) { - message->set_foo_int(200); - message->set_bar_enum(unittest::TestOneof2::BAZ); - message->set_baz_int(202); - message->set_baz_string("203"); -} - -void TestUtil::ExpectOneofSet1(const unittest::TestOneof2& message) { - ExpectAtMostOneFieldSetInOneof(message); - - EXPECT_TRUE(message.has_foo_lazy_message ()); - EXPECT_TRUE(message.foo_lazy_message().has_qux_int()); - - EXPECT_TRUE(message.has_bar_string()); - EXPECT_TRUE(message.has_baz_int ()); - EXPECT_TRUE(message.has_baz_string()); - - ASSERT_EQ(0, message.foo_lazy_message().corge_int_size()); - - EXPECT_EQ(100 , message.foo_lazy_message().qux_int()); - EXPECT_EQ("101", message.bar_string ()); - EXPECT_EQ(102 , message.baz_int ()); - EXPECT_EQ("103", message.baz_string ()); -} - -void TestUtil::ExpectOneofSet2(const unittest::TestOneof2& message) { - ExpectAtMostOneFieldSetInOneof(message); - - EXPECT_TRUE(message.has_foo_int ()); - EXPECT_TRUE(message.has_bar_enum ()); - EXPECT_TRUE(message.has_baz_int ()); - EXPECT_TRUE(message.has_baz_string()); - - EXPECT_EQ(200 , message.foo_int ()); - EXPECT_EQ(unittest::TestOneof2::BAZ, message.bar_enum ()); - EXPECT_EQ(202 , message.baz_int ()); - EXPECT_EQ("203" , message.baz_string()); -} - -void TestUtil::ExpectOneofClear(const unittest::TestOneof2& message) { - EXPECT_FALSE(message.has_foo_int()); - EXPECT_FALSE(message.has_foo_string()); - EXPECT_FALSE(message.has_foo_bytes()); - EXPECT_FALSE(message.has_foo_enum()); - EXPECT_FALSE(message.has_foo_message()); - EXPECT_FALSE(message.has_foogroup()); - EXPECT_FALSE(message.has_foo_lazy_message()); - - EXPECT_FALSE(message.has_bar_int()); - EXPECT_FALSE(message.has_bar_string()); - EXPECT_FALSE(message.has_bar_bytes()); - EXPECT_FALSE(message.has_bar_enum()); - - EXPECT_FALSE(message.has_baz_int()); - EXPECT_FALSE(message.has_baz_string()); - - EXPECT_EQ(unittest::TestOneof2::FOO_NOT_SET, message.foo_case()); - EXPECT_EQ(unittest::TestOneof2::BAR_NOT_SET, message.bar_case()); -} - -void TestUtil::ExpectAtMostOneFieldSetInOneof( - const unittest::TestOneof2& message) { - int count = 0; - if (message.has_foo_int()) count++; - if (message.has_foo_string()) count++; - if (message.has_foo_bytes()) count++; - if (message.has_foo_enum()) count++; - if (message.has_foo_message()) count++; - if (message.has_foogroup()) count++; - if (message.has_foo_lazy_message()) count++; - EXPECT_LE(count, 1); - count = 0; - if (message.has_bar_int()) count++; - if (message.has_bar_string()) count++; - if (message.has_bar_bytes()) count++; - if (message.has_bar_enum()) count++; - EXPECT_TRUE(count == 0 || count == 1); -} - -// =================================================================== - -TestUtil::ReflectionTester::ReflectionTester( - const Descriptor* base_descriptor) - : base_descriptor_(base_descriptor) { - - const DescriptorPool* pool = base_descriptor->file()->pool(); - - nested_b_ = - pool->FindFieldByName("protobuf_unittest.TestAllTypes.NestedMessage.bb"); - foreign_c_ = - pool->FindFieldByName("protobuf_unittest.ForeignMessage.c"); - import_d_ = - pool->FindFieldByName("protobuf_unittest_import.ImportMessage.d"); - import_e_ = - pool->FindFieldByName("protobuf_unittest_import.PublicImportMessage.e"); - nested_foo_ = - pool->FindEnumValueByName("protobuf_unittest.TestAllTypes.FOO"); - nested_bar_ = - pool->FindEnumValueByName("protobuf_unittest.TestAllTypes.BAR"); - nested_baz_ = - pool->FindEnumValueByName("protobuf_unittest.TestAllTypes.BAZ"); - foreign_foo_ = - pool->FindEnumValueByName("protobuf_unittest.FOREIGN_FOO"); - foreign_bar_ = - pool->FindEnumValueByName("protobuf_unittest.FOREIGN_BAR"); - foreign_baz_ = - pool->FindEnumValueByName("protobuf_unittest.FOREIGN_BAZ"); - import_foo_ = - pool->FindEnumValueByName("protobuf_unittest_import.IMPORT_FOO"); - import_bar_ = - pool->FindEnumValueByName("protobuf_unittest_import.IMPORT_BAR"); - import_baz_ = - pool->FindEnumValueByName("protobuf_unittest_import.IMPORT_BAZ"); - - if (base_descriptor_->name() == "TestAllExtensions") { - group_a_ = - pool->FindFieldByName("protobuf_unittest.OptionalGroup_extension.a"); - repeated_group_a_ = - pool->FindFieldByName("protobuf_unittest.RepeatedGroup_extension.a"); - } else { - group_a_ = - pool->FindFieldByName("protobuf_unittest.TestAllTypes.OptionalGroup.a"); - repeated_group_a_ = - pool->FindFieldByName("protobuf_unittest.TestAllTypes.RepeatedGroup.a"); - } - - EXPECT_TRUE(group_a_ != NULL); - EXPECT_TRUE(repeated_group_a_ != NULL); - EXPECT_TRUE(nested_b_ != NULL); - EXPECT_TRUE(foreign_c_ != NULL); - EXPECT_TRUE(import_d_ != NULL); - EXPECT_TRUE(import_e_ != NULL); - EXPECT_TRUE(nested_foo_ != NULL); - EXPECT_TRUE(nested_bar_ != NULL); - EXPECT_TRUE(nested_baz_ != NULL); - EXPECT_TRUE(foreign_foo_ != NULL); - EXPECT_TRUE(foreign_bar_ != NULL); - EXPECT_TRUE(foreign_baz_ != NULL); - EXPECT_TRUE(import_foo_ != NULL); - EXPECT_TRUE(import_bar_ != NULL); - EXPECT_TRUE(import_baz_ != NULL); -} - -// Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes. -const FieldDescriptor* TestUtil::ReflectionTester::F(const string& name) { - const FieldDescriptor* result = NULL; - if (base_descriptor_->name() == "TestAllExtensions" || - base_descriptor_->name() == "TestPackedExtensions") { - result = base_descriptor_->file()->FindExtensionByName(name + "_extension"); - } else { - result = base_descriptor_->FindFieldByName(name); - } - GOOGLE_CHECK(result != NULL); - return result; -} - -// ------------------------------------------------------------------- - -void TestUtil::ReflectionTester::SetAllFieldsViaReflection(Message* message) { - const Reflection* reflection = message->GetReflection(); - Message* sub_message; - - reflection->SetInt32 (message, F("optional_int32" ), 101); - reflection->SetInt64 (message, F("optional_int64" ), 102); - reflection->SetUInt32(message, F("optional_uint32" ), 103); - reflection->SetUInt64(message, F("optional_uint64" ), 104); - reflection->SetInt32 (message, F("optional_sint32" ), 105); - reflection->SetInt64 (message, F("optional_sint64" ), 106); - reflection->SetUInt32(message, F("optional_fixed32" ), 107); - reflection->SetUInt64(message, F("optional_fixed64" ), 108); - reflection->SetInt32 (message, F("optional_sfixed32"), 109); - reflection->SetInt64 (message, F("optional_sfixed64"), 110); - reflection->SetFloat (message, F("optional_float" ), 111); - reflection->SetDouble(message, F("optional_double" ), 112); - reflection->SetBool (message, F("optional_bool" ), true); - reflection->SetString(message, F("optional_string" ), "115"); - reflection->SetString(message, F("optional_bytes" ), "116"); - - sub_message = reflection->MutableMessage(message, F("optionalgroup")); - sub_message->GetReflection()->SetInt32(sub_message, group_a_, 117); - sub_message = reflection->MutableMessage(message, F("optional_nested_message")); - sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 118); - sub_message = reflection->MutableMessage(message, F("optional_foreign_message")); - sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 119); - sub_message = reflection->MutableMessage(message, F("optional_import_message")); - sub_message->GetReflection()->SetInt32(sub_message, import_d_, 120); - - reflection->SetEnum(message, F("optional_nested_enum" ), nested_baz_); - reflection->SetEnum(message, F("optional_foreign_enum"), foreign_baz_); - reflection->SetEnum(message, F("optional_import_enum" ), import_baz_); - - reflection->SetString(message, F("optional_string_piece"), "124"); - reflection->SetString(message, F("optional_cord"), "125"); - - sub_message = reflection->MutableMessage(message, F("optional_public_import_message")); - sub_message->GetReflection()->SetInt32(sub_message, import_e_, 126); - - sub_message = reflection->MutableMessage(message, F("optional_lazy_message")); - sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 127); - - // ----------------------------------------------------------------- - - reflection->AddInt32 (message, F("repeated_int32" ), 201); - reflection->AddInt64 (message, F("repeated_int64" ), 202); - reflection->AddUInt32(message, F("repeated_uint32" ), 203); - reflection->AddUInt64(message, F("repeated_uint64" ), 204); - reflection->AddInt32 (message, F("repeated_sint32" ), 205); - reflection->AddInt64 (message, F("repeated_sint64" ), 206); - reflection->AddUInt32(message, F("repeated_fixed32" ), 207); - reflection->AddUInt64(message, F("repeated_fixed64" ), 208); - reflection->AddInt32 (message, F("repeated_sfixed32"), 209); - reflection->AddInt64 (message, F("repeated_sfixed64"), 210); - reflection->AddFloat (message, F("repeated_float" ), 211); - reflection->AddDouble(message, F("repeated_double" ), 212); - reflection->AddBool (message, F("repeated_bool" ), true); - reflection->AddString(message, F("repeated_string" ), "215"); - reflection->AddString(message, F("repeated_bytes" ), "216"); - - sub_message = reflection->AddMessage(message, F("repeatedgroup")); - sub_message->GetReflection()->SetInt32(sub_message, repeated_group_a_, 217); - sub_message = reflection->AddMessage(message, F("repeated_nested_message")); - sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 218); - sub_message = reflection->AddMessage(message, F("repeated_foreign_message")); - sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 219); - sub_message = reflection->AddMessage(message, F("repeated_import_message")); - sub_message->GetReflection()->SetInt32(sub_message, import_d_, 220); - sub_message = reflection->AddMessage(message, F("repeated_lazy_message")); - sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 227); - - reflection->AddEnum(message, F("repeated_nested_enum" ), nested_bar_); - reflection->AddEnum(message, F("repeated_foreign_enum"), foreign_bar_); - reflection->AddEnum(message, F("repeated_import_enum" ), import_bar_); - - reflection->AddString(message, F("repeated_string_piece"), "224"); - reflection->AddString(message, F("repeated_cord"), "225"); - - // Add a second one of each field. - reflection->AddInt32 (message, F("repeated_int32" ), 301); - reflection->AddInt64 (message, F("repeated_int64" ), 302); - reflection->AddUInt32(message, F("repeated_uint32" ), 303); - reflection->AddUInt64(message, F("repeated_uint64" ), 304); - reflection->AddInt32 (message, F("repeated_sint32" ), 305); - reflection->AddInt64 (message, F("repeated_sint64" ), 306); - reflection->AddUInt32(message, F("repeated_fixed32" ), 307); - reflection->AddUInt64(message, F("repeated_fixed64" ), 308); - reflection->AddInt32 (message, F("repeated_sfixed32"), 309); - reflection->AddInt64 (message, F("repeated_sfixed64"), 310); - reflection->AddFloat (message, F("repeated_float" ), 311); - reflection->AddDouble(message, F("repeated_double" ), 312); - reflection->AddBool (message, F("repeated_bool" ), false); - reflection->AddString(message, F("repeated_string" ), "315"); - reflection->AddString(message, F("repeated_bytes" ), "316"); - - sub_message = reflection->AddMessage(message, F("repeatedgroup")); - sub_message->GetReflection()->SetInt32(sub_message, repeated_group_a_, 317); - sub_message = reflection->AddMessage(message, F("repeated_nested_message")); - sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 318); - sub_message = reflection->AddMessage(message, F("repeated_foreign_message")); - sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 319); - sub_message = reflection->AddMessage(message, F("repeated_import_message")); - sub_message->GetReflection()->SetInt32(sub_message, import_d_, 320); - sub_message = reflection->AddMessage(message, F("repeated_lazy_message")); - sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 327); - - reflection->AddEnum(message, F("repeated_nested_enum" ), nested_baz_); - reflection->AddEnum(message, F("repeated_foreign_enum"), foreign_baz_); - reflection->AddEnum(message, F("repeated_import_enum" ), import_baz_); - - reflection->AddString(message, F("repeated_string_piece"), "324"); - reflection->AddString(message, F("repeated_cord"), "325"); - - // ----------------------------------------------------------------- - - reflection->SetInt32 (message, F("default_int32" ), 401); - reflection->SetInt64 (message, F("default_int64" ), 402); - reflection->SetUInt32(message, F("default_uint32" ), 403); - reflection->SetUInt64(message, F("default_uint64" ), 404); - reflection->SetInt32 (message, F("default_sint32" ), 405); - reflection->SetInt64 (message, F("default_sint64" ), 406); - reflection->SetUInt32(message, F("default_fixed32" ), 407); - reflection->SetUInt64(message, F("default_fixed64" ), 408); - reflection->SetInt32 (message, F("default_sfixed32"), 409); - reflection->SetInt64 (message, F("default_sfixed64"), 410); - reflection->SetFloat (message, F("default_float" ), 411); - reflection->SetDouble(message, F("default_double" ), 412); - reflection->SetBool (message, F("default_bool" ), false); - reflection->SetString(message, F("default_string" ), "415"); - reflection->SetString(message, F("default_bytes" ), "416"); - - reflection->SetEnum(message, F("default_nested_enum" ), nested_foo_); - reflection->SetEnum(message, F("default_foreign_enum"), foreign_foo_); - reflection->SetEnum(message, F("default_import_enum" ), import_foo_); - - reflection->SetString(message, F("default_string_piece"), "424"); - reflection->SetString(message, F("default_cord"), "425"); - - reflection->SetUInt32(message, F("oneof_uint32" ), 601); - sub_message = reflection->MutableMessage(message, F("oneof_nested_message")); - sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 602); - reflection->SetString(message, F("oneof_string"), "603"); - reflection->SetString(message, F("oneof_bytes" ), "604"); -} - -void TestUtil::ReflectionTester::SetOneofViaReflection(Message* message) { - const Descriptor* descriptor = message->GetDescriptor(); - const Reflection* reflection = message->GetReflection(); - Message* sub_message = reflection->MutableMessage( - message, descriptor->FindFieldByName("foo_lazy_message")); - sub_message->GetReflection()->SetInt64( - sub_message, - descriptor->file()->pool()->FindFieldByName( - "protobuf_unittest.TestOneof2.NestedMessage.qux_int"), - 100); - - reflection->SetString(message, - descriptor->FindFieldByName("bar_cord"), - "101"); - reflection->SetInt32(message, - descriptor->FindFieldByName("baz_int"), - 102); - reflection->SetString(message, - descriptor->FindFieldByName("baz_string"), - "103"); -} - -void TestUtil::ReflectionTester::ExpectOneofSetViaReflection( - const Message& message) { - const Descriptor* descriptor = message.GetDescriptor(); - const Reflection* reflection = message.GetReflection(); - string scratch; - EXPECT_TRUE(reflection->HasField( - message, descriptor->FindFieldByName("foo_lazy_message"))); - EXPECT_TRUE(reflection->HasField( - message, descriptor->FindFieldByName("bar_cord"))); - EXPECT_TRUE(reflection->HasField( - message, descriptor->FindFieldByName("baz_int"))); - EXPECT_TRUE(reflection->HasField( - message, descriptor->FindFieldByName("baz_string"))); - - const Message* sub_message = &reflection->GetMessage( - message, descriptor->FindFieldByName("foo_lazy_message")); - EXPECT_EQ(100, sub_message->GetReflection()->GetInt64( - *sub_message, - descriptor->file()->pool()->FindFieldByName( - "protobuf_unittest.TestOneof2.NestedMessage.qux_int"))); - - EXPECT_EQ("101", reflection->GetString( - message, descriptor->FindFieldByName("bar_cord"))); - EXPECT_EQ("101", reflection->GetStringReference( - message, descriptor->FindFieldByName("bar_cord"), &scratch)); - - EXPECT_EQ(102, reflection->GetInt32( - message, descriptor->FindFieldByName("baz_int"))); - - EXPECT_EQ("103", reflection->GetString( - message, descriptor->FindFieldByName("baz_string"))); - EXPECT_EQ("103", reflection->GetStringReference( - message, descriptor->FindFieldByName("baz_string"), &scratch)); -} - -void TestUtil::ReflectionTester::SetPackedFieldsViaReflection( - Message* message) { - const Reflection* reflection = message->GetReflection(); - reflection->AddInt32 (message, F("packed_int32" ), 601); - reflection->AddInt64 (message, F("packed_int64" ), 602); - reflection->AddUInt32(message, F("packed_uint32" ), 603); - reflection->AddUInt64(message, F("packed_uint64" ), 604); - reflection->AddInt32 (message, F("packed_sint32" ), 605); - reflection->AddInt64 (message, F("packed_sint64" ), 606); - reflection->AddUInt32(message, F("packed_fixed32" ), 607); - reflection->AddUInt64(message, F("packed_fixed64" ), 608); - reflection->AddInt32 (message, F("packed_sfixed32"), 609); - reflection->AddInt64 (message, F("packed_sfixed64"), 610); - reflection->AddFloat (message, F("packed_float" ), 611); - reflection->AddDouble(message, F("packed_double" ), 612); - reflection->AddBool (message, F("packed_bool" ), true); - reflection->AddEnum (message, F("packed_enum" ), foreign_bar_); - - reflection->AddInt32 (message, F("packed_int32" ), 701); - reflection->AddInt64 (message, F("packed_int64" ), 702); - reflection->AddUInt32(message, F("packed_uint32" ), 703); - reflection->AddUInt64(message, F("packed_uint64" ), 704); - reflection->AddInt32 (message, F("packed_sint32" ), 705); - reflection->AddInt64 (message, F("packed_sint64" ), 706); - reflection->AddUInt32(message, F("packed_fixed32" ), 707); - reflection->AddUInt64(message, F("packed_fixed64" ), 708); - reflection->AddInt32 (message, F("packed_sfixed32"), 709); - reflection->AddInt64 (message, F("packed_sfixed64"), 710); - reflection->AddFloat (message, F("packed_float" ), 711); - reflection->AddDouble(message, F("packed_double" ), 712); - reflection->AddBool (message, F("packed_bool" ), false); - reflection->AddEnum (message, F("packed_enum" ), foreign_baz_); -} - -// ------------------------------------------------------------------- - -void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection( - const Message& message) { - // We have to split this into three function otherwise it creates a stack - // frame so large that it triggers a warning. - ExpectAllFieldsSetViaReflection1(message); - ExpectAllFieldsSetViaReflection2(message); - ExpectAllFieldsSetViaReflection3(message); -} - -void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection1( - const Message& message) { - const Reflection* reflection = message.GetReflection(); - string scratch; - const Message* sub_message; - - EXPECT_TRUE(reflection->HasField(message, F("optional_int32" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_int64" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_uint32" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_uint64" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_sint32" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_sint64" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_fixed32" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_fixed64" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_sfixed32"))); - EXPECT_TRUE(reflection->HasField(message, F("optional_sfixed64"))); - EXPECT_TRUE(reflection->HasField(message, F("optional_float" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_double" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_bool" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_string" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_bytes" ))); - - EXPECT_TRUE(reflection->HasField(message, F("optionalgroup" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_nested_message" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_message" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_import_message" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_public_import_message"))); - EXPECT_TRUE(reflection->HasField(message, F("optional_lazy_message" ))); - - sub_message = &reflection->GetMessage(message, F("optionalgroup")); - EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, group_a_)); - sub_message = &reflection->GetMessage(message, F("optional_nested_message")); - EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, nested_b_)); - sub_message = &reflection->GetMessage(message, F("optional_foreign_message")); - EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, foreign_c_)); - sub_message = &reflection->GetMessage(message, F("optional_import_message")); - EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, import_d_)); - sub_message = &reflection->GetMessage(message, F("optional_public_import_message")); - EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, import_e_)); - sub_message = &reflection->GetMessage(message, F("optional_lazy_message")); - EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, nested_b_)); - - EXPECT_TRUE(reflection->HasField(message, F("optional_nested_enum" ))); - EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_enum"))); - EXPECT_TRUE(reflection->HasField(message, F("optional_import_enum" ))); - - EXPECT_TRUE(reflection->HasField(message, F("optional_string_piece"))); - EXPECT_TRUE(reflection->HasField(message, F("optional_cord"))); - - EXPECT_EQ(101 , reflection->GetInt32 (message, F("optional_int32" ))); - EXPECT_EQ(102 , reflection->GetInt64 (message, F("optional_int64" ))); - EXPECT_EQ(103 , reflection->GetUInt32(message, F("optional_uint32" ))); - EXPECT_EQ(104 , reflection->GetUInt64(message, F("optional_uint64" ))); - EXPECT_EQ(105 , reflection->GetInt32 (message, F("optional_sint32" ))); - EXPECT_EQ(106 , reflection->GetInt64 (message, F("optional_sint64" ))); - EXPECT_EQ(107 , reflection->GetUInt32(message, F("optional_fixed32" ))); - EXPECT_EQ(108 , reflection->GetUInt64(message, F("optional_fixed64" ))); - EXPECT_EQ(109 , reflection->GetInt32 (message, F("optional_sfixed32"))); - EXPECT_EQ(110 , reflection->GetInt64 (message, F("optional_sfixed64"))); - EXPECT_EQ(111 , reflection->GetFloat (message, F("optional_float" ))); - EXPECT_EQ(112 , reflection->GetDouble(message, F("optional_double" ))); - EXPECT_TRUE( reflection->GetBool (message, F("optional_bool" ))); - EXPECT_EQ("115", reflection->GetString(message, F("optional_string" ))); - EXPECT_EQ("116", reflection->GetString(message, F("optional_bytes" ))); - - EXPECT_EQ("115", reflection->GetStringReference(message, F("optional_string"), &scratch)); - EXPECT_EQ("116", reflection->GetStringReference(message, F("optional_bytes" ), &scratch)); - - sub_message = &reflection->GetMessage(message, F("optionalgroup")); - EXPECT_EQ(117, sub_message->GetReflection()->GetInt32(*sub_message, group_a_)); - sub_message = &reflection->GetMessage(message, F("optional_nested_message")); - EXPECT_EQ(118, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); - sub_message = &reflection->GetMessage(message, F("optional_foreign_message")); - EXPECT_EQ(119, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); - sub_message = &reflection->GetMessage(message, F("optional_import_message")); - EXPECT_EQ(120, sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); - sub_message = &reflection->GetMessage(message, F("optional_public_import_message")); - EXPECT_EQ(126, sub_message->GetReflection()->GetInt32(*sub_message, import_e_)); - sub_message = &reflection->GetMessage(message, F("optional_lazy_message")); - EXPECT_EQ(127, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); - - EXPECT_EQ( nested_baz_, reflection->GetEnum(message, F("optional_nested_enum" ))); - EXPECT_EQ(foreign_baz_, reflection->GetEnum(message, F("optional_foreign_enum"))); - EXPECT_EQ( import_baz_, reflection->GetEnum(message, F("optional_import_enum" ))); - - EXPECT_EQ("124", reflection->GetString(message, F("optional_string_piece"))); - EXPECT_EQ("124", reflection->GetStringReference(message, F("optional_string_piece"), &scratch)); - - EXPECT_EQ("125", reflection->GetString(message, F("optional_cord"))); - EXPECT_EQ("125", reflection->GetStringReference(message, F("optional_cord"), &scratch)); - - EXPECT_TRUE(reflection->HasField(message, F("oneof_bytes" ))); - EXPECT_EQ("604", reflection->GetString(message, F("oneof_bytes" ))); - - if (base_descriptor_->name() == "TestAllTypes") { - EXPECT_FALSE(reflection->HasField(message, F("oneof_uint32"))); - EXPECT_FALSE(reflection->HasField(message, F("oneof_string"))); - } else { - EXPECT_TRUE(reflection->HasField(message, F("oneof_uint32"))); - EXPECT_TRUE(reflection->HasField(message, F("oneof_string"))); - EXPECT_EQ(601 , reflection->GetUInt32(message, F("oneof_uint32"))); - EXPECT_EQ("603", reflection->GetString(message, F("oneof_string"))); - sub_message = &reflection->GetMessage(message, F("oneof_nested_message")); - EXPECT_EQ(602, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); - } -} - -void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection2( - const Message& message) { - const Reflection* reflection = message.GetReflection(); - string scratch; - const Message* sub_message; - - // ----------------------------------------------------------------- - - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_int32" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_int64" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_uint32" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_uint64" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sint32" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sint64" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_fixed32" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_fixed64" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sfixed32"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sfixed64"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_float" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_double" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_bool" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_string" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_bytes" ))); - - ASSERT_EQ(2, reflection->FieldSize(message, F("repeatedgroup" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_nested_message" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_foreign_message"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_import_message" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_lazy_message" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_nested_enum" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_foreign_enum" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_import_enum" ))); - - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_string_piece"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_cord"))); - - EXPECT_EQ(201 , reflection->GetRepeatedInt32 (message, F("repeated_int32" ), 0)); - EXPECT_EQ(202 , reflection->GetRepeatedInt64 (message, F("repeated_int64" ), 0)); - EXPECT_EQ(203 , reflection->GetRepeatedUInt32(message, F("repeated_uint32" ), 0)); - EXPECT_EQ(204 , reflection->GetRepeatedUInt64(message, F("repeated_uint64" ), 0)); - EXPECT_EQ(205 , reflection->GetRepeatedInt32 (message, F("repeated_sint32" ), 0)); - EXPECT_EQ(206 , reflection->GetRepeatedInt64 (message, F("repeated_sint64" ), 0)); - EXPECT_EQ(207 , reflection->GetRepeatedUInt32(message, F("repeated_fixed32" ), 0)); - EXPECT_EQ(208 , reflection->GetRepeatedUInt64(message, F("repeated_fixed64" ), 0)); - EXPECT_EQ(209 , reflection->GetRepeatedInt32 (message, F("repeated_sfixed32"), 0)); - EXPECT_EQ(210 , reflection->GetRepeatedInt64 (message, F("repeated_sfixed64"), 0)); - EXPECT_EQ(211 , reflection->GetRepeatedFloat (message, F("repeated_float" ), 0)); - EXPECT_EQ(212 , reflection->GetRepeatedDouble(message, F("repeated_double" ), 0)); - EXPECT_TRUE( reflection->GetRepeatedBool (message, F("repeated_bool" ), 0)); - EXPECT_EQ("215", reflection->GetRepeatedString(message, F("repeated_string" ), 0)); - EXPECT_EQ("216", reflection->GetRepeatedString(message, F("repeated_bytes" ), 0)); - - EXPECT_EQ("215", reflection->GetRepeatedStringReference(message, F("repeated_string"), 0, &scratch)); - EXPECT_EQ("216", reflection->GetRepeatedStringReference(message, F("repeated_bytes"), 0, &scratch)); - - sub_message = &reflection->GetRepeatedMessage(message, F("repeatedgroup"), 0); - EXPECT_EQ(217, sub_message->GetReflection()->GetInt32(*sub_message, repeated_group_a_)); - sub_message = &reflection->GetRepeatedMessage(message, F("repeated_nested_message"), 0); - EXPECT_EQ(218, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); - sub_message = &reflection->GetRepeatedMessage(message, F("repeated_foreign_message"), 0); - EXPECT_EQ(219, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); - sub_message = &reflection->GetRepeatedMessage(message, F("repeated_import_message"), 0); - EXPECT_EQ(220, sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); - sub_message = &reflection->GetRepeatedMessage(message, F("repeated_lazy_message"), 0); - EXPECT_EQ(227, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); - - EXPECT_EQ( nested_bar_, reflection->GetRepeatedEnum(message, F("repeated_nested_enum" ),0)); - EXPECT_EQ(foreign_bar_, reflection->GetRepeatedEnum(message, F("repeated_foreign_enum"),0)); - EXPECT_EQ( import_bar_, reflection->GetRepeatedEnum(message, F("repeated_import_enum" ),0)); - - EXPECT_EQ("224", reflection->GetRepeatedString(message, F("repeated_string_piece"), 0)); - EXPECT_EQ("224", reflection->GetRepeatedStringReference( - message, F("repeated_string_piece"), 0, &scratch)); - - EXPECT_EQ("225", reflection->GetRepeatedString(message, F("repeated_cord"), 0)); - EXPECT_EQ("225", reflection->GetRepeatedStringReference( - message, F("repeated_cord"), 0, &scratch)); - - EXPECT_EQ(301 , reflection->GetRepeatedInt32 (message, F("repeated_int32" ), 1)); - EXPECT_EQ(302 , reflection->GetRepeatedInt64 (message, F("repeated_int64" ), 1)); - EXPECT_EQ(303 , reflection->GetRepeatedUInt32(message, F("repeated_uint32" ), 1)); - EXPECT_EQ(304 , reflection->GetRepeatedUInt64(message, F("repeated_uint64" ), 1)); - EXPECT_EQ(305 , reflection->GetRepeatedInt32 (message, F("repeated_sint32" ), 1)); - EXPECT_EQ(306 , reflection->GetRepeatedInt64 (message, F("repeated_sint64" ), 1)); - EXPECT_EQ(307 , reflection->GetRepeatedUInt32(message, F("repeated_fixed32" ), 1)); - EXPECT_EQ(308 , reflection->GetRepeatedUInt64(message, F("repeated_fixed64" ), 1)); - EXPECT_EQ(309 , reflection->GetRepeatedInt32 (message, F("repeated_sfixed32"), 1)); - EXPECT_EQ(310 , reflection->GetRepeatedInt64 (message, F("repeated_sfixed64"), 1)); - EXPECT_EQ(311 , reflection->GetRepeatedFloat (message, F("repeated_float" ), 1)); - EXPECT_EQ(312 , reflection->GetRepeatedDouble(message, F("repeated_double" ), 1)); - EXPECT_FALSE( reflection->GetRepeatedBool (message, F("repeated_bool" ), 1)); - EXPECT_EQ("315", reflection->GetRepeatedString(message, F("repeated_string" ), 1)); - EXPECT_EQ("316", reflection->GetRepeatedString(message, F("repeated_bytes" ), 1)); - - EXPECT_EQ("315", reflection->GetRepeatedStringReference(message, F("repeated_string"), - 1, &scratch)); - EXPECT_EQ("316", reflection->GetRepeatedStringReference(message, F("repeated_bytes"), - 1, &scratch)); - - sub_message = &reflection->GetRepeatedMessage(message, F("repeatedgroup"), 1); - EXPECT_EQ(317, sub_message->GetReflection()->GetInt32(*sub_message, repeated_group_a_)); - sub_message = &reflection->GetRepeatedMessage(message, F("repeated_nested_message"), 1); - EXPECT_EQ(318, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); - sub_message = &reflection->GetRepeatedMessage(message, F("repeated_foreign_message"), 1); - EXPECT_EQ(319, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); - sub_message = &reflection->GetRepeatedMessage(message, F("repeated_import_message"), 1); - EXPECT_EQ(320, sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); - sub_message = &reflection->GetRepeatedMessage(message, F("repeated_lazy_message"), 1); - EXPECT_EQ(327, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); - - EXPECT_EQ( nested_baz_, reflection->GetRepeatedEnum(message, F("repeated_nested_enum" ),1)); - EXPECT_EQ(foreign_baz_, reflection->GetRepeatedEnum(message, F("repeated_foreign_enum"),1)); - EXPECT_EQ( import_baz_, reflection->GetRepeatedEnum(message, F("repeated_import_enum" ),1)); - - EXPECT_EQ("324", reflection->GetRepeatedString(message, F("repeated_string_piece"), 1)); - EXPECT_EQ("324", reflection->GetRepeatedStringReference( - message, F("repeated_string_piece"), 1, &scratch)); - - EXPECT_EQ("325", reflection->GetRepeatedString(message, F("repeated_cord"), 1)); - EXPECT_EQ("325", reflection->GetRepeatedStringReference( - message, F("repeated_cord"), 1, &scratch)); -} - -void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection3( - const Message& message) { - const Reflection* reflection = message.GetReflection(); - string scratch; - - // ----------------------------------------------------------------- - - EXPECT_TRUE(reflection->HasField(message, F("default_int32" ))); - EXPECT_TRUE(reflection->HasField(message, F("default_int64" ))); - EXPECT_TRUE(reflection->HasField(message, F("default_uint32" ))); - EXPECT_TRUE(reflection->HasField(message, F("default_uint64" ))); - EXPECT_TRUE(reflection->HasField(message, F("default_sint32" ))); - EXPECT_TRUE(reflection->HasField(message, F("default_sint64" ))); - EXPECT_TRUE(reflection->HasField(message, F("default_fixed32" ))); - EXPECT_TRUE(reflection->HasField(message, F("default_fixed64" ))); - EXPECT_TRUE(reflection->HasField(message, F("default_sfixed32"))); - EXPECT_TRUE(reflection->HasField(message, F("default_sfixed64"))); - EXPECT_TRUE(reflection->HasField(message, F("default_float" ))); - EXPECT_TRUE(reflection->HasField(message, F("default_double" ))); - EXPECT_TRUE(reflection->HasField(message, F("default_bool" ))); - EXPECT_TRUE(reflection->HasField(message, F("default_string" ))); - EXPECT_TRUE(reflection->HasField(message, F("default_bytes" ))); - - EXPECT_TRUE(reflection->HasField(message, F("default_nested_enum" ))); - EXPECT_TRUE(reflection->HasField(message, F("default_foreign_enum"))); - EXPECT_TRUE(reflection->HasField(message, F("default_import_enum" ))); - - EXPECT_TRUE(reflection->HasField(message, F("default_string_piece"))); - EXPECT_TRUE(reflection->HasField(message, F("default_cord"))); - - EXPECT_EQ(401 , reflection->GetInt32 (message, F("default_int32" ))); - EXPECT_EQ(402 , reflection->GetInt64 (message, F("default_int64" ))); - EXPECT_EQ(403 , reflection->GetUInt32(message, F("default_uint32" ))); - EXPECT_EQ(404 , reflection->GetUInt64(message, F("default_uint64" ))); - EXPECT_EQ(405 , reflection->GetInt32 (message, F("default_sint32" ))); - EXPECT_EQ(406 , reflection->GetInt64 (message, F("default_sint64" ))); - EXPECT_EQ(407 , reflection->GetUInt32(message, F("default_fixed32" ))); - EXPECT_EQ(408 , reflection->GetUInt64(message, F("default_fixed64" ))); - EXPECT_EQ(409 , reflection->GetInt32 (message, F("default_sfixed32"))); - EXPECT_EQ(410 , reflection->GetInt64 (message, F("default_sfixed64"))); - EXPECT_EQ(411 , reflection->GetFloat (message, F("default_float" ))); - EXPECT_EQ(412 , reflection->GetDouble(message, F("default_double" ))); - EXPECT_FALSE( reflection->GetBool (message, F("default_bool" ))); - EXPECT_EQ("415", reflection->GetString(message, F("default_string" ))); - EXPECT_EQ("416", reflection->GetString(message, F("default_bytes" ))); - - EXPECT_EQ("415", reflection->GetStringReference(message, F("default_string"), &scratch)); - EXPECT_EQ("416", reflection->GetStringReference(message, F("default_bytes" ), &scratch)); - - EXPECT_EQ( nested_foo_, reflection->GetEnum(message, F("default_nested_enum" ))); - EXPECT_EQ(foreign_foo_, reflection->GetEnum(message, F("default_foreign_enum"))); - EXPECT_EQ( import_foo_, reflection->GetEnum(message, F("default_import_enum" ))); - - EXPECT_EQ("424", reflection->GetString(message, F("default_string_piece"))); - EXPECT_EQ("424", reflection->GetStringReference(message, F("default_string_piece"), - &scratch)); - - EXPECT_EQ("425", reflection->GetString(message, F("default_cord"))); - EXPECT_EQ("425", reflection->GetStringReference(message, F("default_cord"), &scratch)); -} - -void TestUtil::ReflectionTester::ExpectPackedFieldsSetViaReflection( - const Message& message) { - const Reflection* reflection = message.GetReflection(); - - ASSERT_EQ(2, reflection->FieldSize(message, F("packed_int32" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("packed_int64" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("packed_uint32" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("packed_uint64" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sint32" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sint64" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("packed_fixed32" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("packed_fixed64" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sfixed32"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sfixed64"))); - ASSERT_EQ(2, reflection->FieldSize(message, F("packed_float" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("packed_double" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("packed_bool" ))); - ASSERT_EQ(2, reflection->FieldSize(message, F("packed_enum" ))); - - EXPECT_EQ(601 , reflection->GetRepeatedInt32 (message, F("packed_int32" ), 0)); - EXPECT_EQ(602 , reflection->GetRepeatedInt64 (message, F("packed_int64" ), 0)); - EXPECT_EQ(603 , reflection->GetRepeatedUInt32(message, F("packed_uint32" ), 0)); - EXPECT_EQ(604 , reflection->GetRepeatedUInt64(message, F("packed_uint64" ), 0)); - EXPECT_EQ(605 , reflection->GetRepeatedInt32 (message, F("packed_sint32" ), 0)); - EXPECT_EQ(606 , reflection->GetRepeatedInt64 (message, F("packed_sint64" ), 0)); - EXPECT_EQ(607 , reflection->GetRepeatedUInt32(message, F("packed_fixed32" ), 0)); - EXPECT_EQ(608 , reflection->GetRepeatedUInt64(message, F("packed_fixed64" ), 0)); - EXPECT_EQ(609 , reflection->GetRepeatedInt32 (message, F("packed_sfixed32"), 0)); - EXPECT_EQ(610 , reflection->GetRepeatedInt64 (message, F("packed_sfixed64"), 0)); - EXPECT_EQ(611 , reflection->GetRepeatedFloat (message, F("packed_float" ), 0)); - EXPECT_EQ(612 , reflection->GetRepeatedDouble(message, F("packed_double" ), 0)); - EXPECT_TRUE( reflection->GetRepeatedBool (message, F("packed_bool" ), 0)); - EXPECT_EQ(foreign_bar_, - reflection->GetRepeatedEnum(message, F("packed_enum"), 0)); - - EXPECT_EQ(701 , reflection->GetRepeatedInt32 (message, F("packed_int32" ), 1)); - EXPECT_EQ(702 , reflection->GetRepeatedInt64 (message, F("packed_int64" ), 1)); - EXPECT_EQ(703 , reflection->GetRepeatedUInt32(message, F("packed_uint32" ), 1)); - EXPECT_EQ(704 , reflection->GetRepeatedUInt64(message, F("packed_uint64" ), 1)); - EXPECT_EQ(705 , reflection->GetRepeatedInt32 (message, F("packed_sint32" ), 1)); - EXPECT_EQ(706 , reflection->GetRepeatedInt64 (message, F("packed_sint64" ), 1)); - EXPECT_EQ(707 , reflection->GetRepeatedUInt32(message, F("packed_fixed32" ), 1)); - EXPECT_EQ(708 , reflection->GetRepeatedUInt64(message, F("packed_fixed64" ), 1)); - EXPECT_EQ(709 , reflection->GetRepeatedInt32 (message, F("packed_sfixed32"), 1)); - EXPECT_EQ(710 , reflection->GetRepeatedInt64 (message, F("packed_sfixed64"), 1)); - EXPECT_EQ(711 , reflection->GetRepeatedFloat (message, F("packed_float" ), 1)); - EXPECT_EQ(712 , reflection->GetRepeatedDouble(message, F("packed_double" ), 1)); - EXPECT_FALSE( reflection->GetRepeatedBool (message, F("packed_bool" ), 1)); - EXPECT_EQ(foreign_baz_, - reflection->GetRepeatedEnum(message, F("packed_enum"), 1)); -} - -// ------------------------------------------------------------------- - -void TestUtil::ReflectionTester::ExpectClearViaReflection( - const Message& message) { - const Reflection* reflection = message.GetReflection(); - string scratch; - const Message* sub_message; - - // has_blah() should initially be false for all optional fields. - EXPECT_FALSE(reflection->HasField(message, F("optional_int32" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_int64" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_uint32" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_uint64" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_sint32" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_sint64" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_fixed32" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_fixed64" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_sfixed32"))); - EXPECT_FALSE(reflection->HasField(message, F("optional_sfixed64"))); - EXPECT_FALSE(reflection->HasField(message, F("optional_float" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_double" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_bool" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_string" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_bytes" ))); - - EXPECT_FALSE(reflection->HasField(message, F("optionalgroup" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_nested_message" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_foreign_message"))); - EXPECT_FALSE(reflection->HasField(message, F("optional_import_message" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_public_import_message"))); - EXPECT_FALSE(reflection->HasField(message, F("optional_lazy_message"))); - - EXPECT_FALSE(reflection->HasField(message, F("optional_nested_enum" ))); - EXPECT_FALSE(reflection->HasField(message, F("optional_foreign_enum"))); - EXPECT_FALSE(reflection->HasField(message, F("optional_import_enum" ))); - - EXPECT_FALSE(reflection->HasField(message, F("optional_string_piece"))); - EXPECT_FALSE(reflection->HasField(message, F("optional_cord"))); - - // Optional fields without defaults are set to zero or something like it. - EXPECT_EQ(0 , reflection->GetInt32 (message, F("optional_int32" ))); - EXPECT_EQ(0 , reflection->GetInt64 (message, F("optional_int64" ))); - EXPECT_EQ(0 , reflection->GetUInt32(message, F("optional_uint32" ))); - EXPECT_EQ(0 , reflection->GetUInt64(message, F("optional_uint64" ))); - EXPECT_EQ(0 , reflection->GetInt32 (message, F("optional_sint32" ))); - EXPECT_EQ(0 , reflection->GetInt64 (message, F("optional_sint64" ))); - EXPECT_EQ(0 , reflection->GetUInt32(message, F("optional_fixed32" ))); - EXPECT_EQ(0 , reflection->GetUInt64(message, F("optional_fixed64" ))); - EXPECT_EQ(0 , reflection->GetInt32 (message, F("optional_sfixed32"))); - EXPECT_EQ(0 , reflection->GetInt64 (message, F("optional_sfixed64"))); - EXPECT_EQ(0 , reflection->GetFloat (message, F("optional_float" ))); - EXPECT_EQ(0 , reflection->GetDouble(message, F("optional_double" ))); - EXPECT_FALSE( reflection->GetBool (message, F("optional_bool" ))); - EXPECT_EQ("" , reflection->GetString(message, F("optional_string" ))); - EXPECT_EQ("" , reflection->GetString(message, F("optional_bytes" ))); - - EXPECT_EQ("", reflection->GetStringReference(message, F("optional_string"), &scratch)); - EXPECT_EQ("", reflection->GetStringReference(message, F("optional_bytes" ), &scratch)); - - // Embedded messages should also be clear. - sub_message = &reflection->GetMessage(message, F("optionalgroup")); - EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, group_a_)); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, group_a_)); - sub_message = &reflection->GetMessage(message, F("optional_nested_message")); - EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, nested_b_)); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); - sub_message = &reflection->GetMessage(message, F("optional_foreign_message")); - EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, foreign_c_)); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); - sub_message = &reflection->GetMessage(message, F("optional_import_message")); - EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, import_d_)); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); - sub_message = &reflection->GetMessage(message, F("optional_public_import_message")); - EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, import_e_)); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, import_e_)); - sub_message = &reflection->GetMessage(message, F("optional_lazy_message")); - EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, nested_b_)); - EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); - - // Enums without defaults are set to the first value in the enum. - EXPECT_EQ( nested_foo_, reflection->GetEnum(message, F("optional_nested_enum" ))); - EXPECT_EQ(foreign_foo_, reflection->GetEnum(message, F("optional_foreign_enum"))); - EXPECT_EQ( import_foo_, reflection->GetEnum(message, F("optional_import_enum" ))); - - EXPECT_EQ("", reflection->GetString(message, F("optional_string_piece"))); - EXPECT_EQ("", reflection->GetStringReference(message, F("optional_string_piece"), &scratch)); - - EXPECT_EQ("", reflection->GetString(message, F("optional_cord"))); - EXPECT_EQ("", reflection->GetStringReference(message, F("optional_cord"), &scratch)); - - // Repeated fields are empty. - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_int32" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_int64" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_uint32" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_uint64" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sint32" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sint64" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_fixed32" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_fixed64" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sfixed32"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sfixed64"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_float" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_double" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_bool" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_string" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_bytes" ))); - - EXPECT_EQ(0, reflection->FieldSize(message, F("repeatedgroup" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_nested_message" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_foreign_message"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_import_message" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_lazy_message" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_nested_enum" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_foreign_enum" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_import_enum" ))); - - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_string_piece"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_cord"))); - - // has_blah() should also be false for all default fields. - EXPECT_FALSE(reflection->HasField(message, F("default_int32" ))); - EXPECT_FALSE(reflection->HasField(message, F("default_int64" ))); - EXPECT_FALSE(reflection->HasField(message, F("default_uint32" ))); - EXPECT_FALSE(reflection->HasField(message, F("default_uint64" ))); - EXPECT_FALSE(reflection->HasField(message, F("default_sint32" ))); - EXPECT_FALSE(reflection->HasField(message, F("default_sint64" ))); - EXPECT_FALSE(reflection->HasField(message, F("default_fixed32" ))); - EXPECT_FALSE(reflection->HasField(message, F("default_fixed64" ))); - EXPECT_FALSE(reflection->HasField(message, F("default_sfixed32"))); - EXPECT_FALSE(reflection->HasField(message, F("default_sfixed64"))); - EXPECT_FALSE(reflection->HasField(message, F("default_float" ))); - EXPECT_FALSE(reflection->HasField(message, F("default_double" ))); - EXPECT_FALSE(reflection->HasField(message, F("default_bool" ))); - EXPECT_FALSE(reflection->HasField(message, F("default_string" ))); - EXPECT_FALSE(reflection->HasField(message, F("default_bytes" ))); - - EXPECT_FALSE(reflection->HasField(message, F("default_nested_enum" ))); - EXPECT_FALSE(reflection->HasField(message, F("default_foreign_enum"))); - EXPECT_FALSE(reflection->HasField(message, F("default_import_enum" ))); - - EXPECT_FALSE(reflection->HasField(message, F("default_string_piece"))); - EXPECT_FALSE(reflection->HasField(message, F("default_cord"))); - - // Fields with defaults have their default values (duh). - EXPECT_EQ( 41 , reflection->GetInt32 (message, F("default_int32" ))); - EXPECT_EQ( 42 , reflection->GetInt64 (message, F("default_int64" ))); - EXPECT_EQ( 43 , reflection->GetUInt32(message, F("default_uint32" ))); - EXPECT_EQ( 44 , reflection->GetUInt64(message, F("default_uint64" ))); - EXPECT_EQ(-45 , reflection->GetInt32 (message, F("default_sint32" ))); - EXPECT_EQ( 46 , reflection->GetInt64 (message, F("default_sint64" ))); - EXPECT_EQ( 47 , reflection->GetUInt32(message, F("default_fixed32" ))); - EXPECT_EQ( 48 , reflection->GetUInt64(message, F("default_fixed64" ))); - EXPECT_EQ( 49 , reflection->GetInt32 (message, F("default_sfixed32"))); - EXPECT_EQ(-50 , reflection->GetInt64 (message, F("default_sfixed64"))); - EXPECT_EQ( 51.5 , reflection->GetFloat (message, F("default_float" ))); - EXPECT_EQ( 52e3 , reflection->GetDouble(message, F("default_double" ))); - EXPECT_TRUE( reflection->GetBool (message, F("default_bool" ))); - EXPECT_EQ("hello", reflection->GetString(message, F("default_string" ))); - EXPECT_EQ("world", reflection->GetString(message, F("default_bytes" ))); - - EXPECT_EQ("hello", reflection->GetStringReference(message, F("default_string"), &scratch)); - EXPECT_EQ("world", reflection->GetStringReference(message, F("default_bytes" ), &scratch)); - - EXPECT_EQ( nested_bar_, reflection->GetEnum(message, F("default_nested_enum" ))); - EXPECT_EQ(foreign_bar_, reflection->GetEnum(message, F("default_foreign_enum"))); - EXPECT_EQ( import_bar_, reflection->GetEnum(message, F("default_import_enum" ))); - - EXPECT_EQ("abc", reflection->GetString(message, F("default_string_piece"))); - EXPECT_EQ("abc", reflection->GetStringReference(message, F("default_string_piece"), &scratch)); - - EXPECT_EQ("123", reflection->GetString(message, F("default_cord"))); - EXPECT_EQ("123", reflection->GetStringReference(message, F("default_cord"), &scratch)); -} - -void TestUtil::ReflectionTester::ExpectPackedClearViaReflection( - const Message& message) { - const Reflection* reflection = message.GetReflection(); - - EXPECT_EQ(0, reflection->FieldSize(message, F("packed_int32" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("packed_int64" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("packed_uint32" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("packed_uint64" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sint32" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sint64" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("packed_fixed32" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("packed_fixed64" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sfixed32"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sfixed64"))); - EXPECT_EQ(0, reflection->FieldSize(message, F("packed_float" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("packed_double" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("packed_bool" ))); - EXPECT_EQ(0, reflection->FieldSize(message, F("packed_enum" ))); -} - -// ------------------------------------------------------------------- - -void TestUtil::ReflectionTester::ModifyRepeatedFieldsViaReflection( - Message* message) { - const Reflection* reflection = message->GetReflection(); - Message* sub_message; - - reflection->SetRepeatedInt32 (message, F("repeated_int32" ), 1, 501); - reflection->SetRepeatedInt64 (message, F("repeated_int64" ), 1, 502); - reflection->SetRepeatedUInt32(message, F("repeated_uint32" ), 1, 503); - reflection->SetRepeatedUInt64(message, F("repeated_uint64" ), 1, 504); - reflection->SetRepeatedInt32 (message, F("repeated_sint32" ), 1, 505); - reflection->SetRepeatedInt64 (message, F("repeated_sint64" ), 1, 506); - reflection->SetRepeatedUInt32(message, F("repeated_fixed32" ), 1, 507); - reflection->SetRepeatedUInt64(message, F("repeated_fixed64" ), 1, 508); - reflection->SetRepeatedInt32 (message, F("repeated_sfixed32"), 1, 509); - reflection->SetRepeatedInt64 (message, F("repeated_sfixed64"), 1, 510); - reflection->SetRepeatedFloat (message, F("repeated_float" ), 1, 511); - reflection->SetRepeatedDouble(message, F("repeated_double" ), 1, 512); - reflection->SetRepeatedBool (message, F("repeated_bool" ), 1, true); - reflection->SetRepeatedString(message, F("repeated_string" ), 1, "515"); - reflection->SetRepeatedString(message, F("repeated_bytes" ), 1, "516"); - - sub_message = reflection->MutableRepeatedMessage(message, F("repeatedgroup"), 1); - sub_message->GetReflection()->SetInt32(sub_message, repeated_group_a_, 517); - sub_message = reflection->MutableRepeatedMessage(message, F("repeated_nested_message"), 1); - sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 518); - sub_message = reflection->MutableRepeatedMessage(message, F("repeated_foreign_message"), 1); - sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 519); - sub_message = reflection->MutableRepeatedMessage(message, F("repeated_import_message"), 1); - sub_message->GetReflection()->SetInt32(sub_message, import_d_, 520); - sub_message = reflection->MutableRepeatedMessage(message, F("repeated_lazy_message"), 1); - sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 527); - - reflection->SetRepeatedEnum(message, F("repeated_nested_enum" ), 1, nested_foo_); - reflection->SetRepeatedEnum(message, F("repeated_foreign_enum"), 1, foreign_foo_); - reflection->SetRepeatedEnum(message, F("repeated_import_enum" ), 1, import_foo_); - - reflection->SetRepeatedString(message, F("repeated_string_piece"), 1, "524"); - reflection->SetRepeatedString(message, F("repeated_cord"), 1, "525"); -} - -void TestUtil::ReflectionTester::ModifyPackedFieldsViaReflection( - Message* message) { - const Reflection* reflection = message->GetReflection(); - reflection->SetRepeatedInt32 (message, F("packed_int32" ), 1, 801); - reflection->SetRepeatedInt64 (message, F("packed_int64" ), 1, 802); - reflection->SetRepeatedUInt32(message, F("packed_uint32" ), 1, 803); - reflection->SetRepeatedUInt64(message, F("packed_uint64" ), 1, 804); - reflection->SetRepeatedInt32 (message, F("packed_sint32" ), 1, 805); - reflection->SetRepeatedInt64 (message, F("packed_sint64" ), 1, 806); - reflection->SetRepeatedUInt32(message, F("packed_fixed32" ), 1, 807); - reflection->SetRepeatedUInt64(message, F("packed_fixed64" ), 1, 808); - reflection->SetRepeatedInt32 (message, F("packed_sfixed32"), 1, 809); - reflection->SetRepeatedInt64 (message, F("packed_sfixed64"), 1, 810); - reflection->SetRepeatedFloat (message, F("packed_float" ), 1, 811); - reflection->SetRepeatedDouble(message, F("packed_double" ), 1, 812); - reflection->SetRepeatedBool (message, F("packed_bool" ), 1, true); - reflection->SetRepeatedEnum (message, F("packed_enum" ), 1, foreign_foo_); -} - -void TestUtil::ReflectionTester::RemoveLastRepeatedsViaReflection( - Message* message) { - const Reflection* reflection = message->GetReflection(); - - std::vector output; - reflection->ListFields(*message, &output); - for (int i=0; iis_repeated()) continue; - - reflection->RemoveLast(message, field); - } -} - -void TestUtil::ReflectionTester::ReleaseLastRepeatedsViaReflection( - Message* message, bool expect_extensions_notnull) { - const Reflection* reflection = message->GetReflection(); - - std::vector output; - reflection->ListFields(*message, &output); - for (int i=0; iis_repeated()) continue; - if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; - - Message* released = reflection->ReleaseLast(message, field); - if (!field->is_extension() || expect_extensions_notnull) { - ASSERT_TRUE(released != NULL) << "ReleaseLast returned NULL for: " - << field->name(); - } - delete released; - } -} - -void TestUtil::ReflectionTester::SwapRepeatedsViaReflection(Message* message) { - const Reflection* reflection = message->GetReflection(); - - std::vector output; - reflection->ListFields(*message, &output); - for (int i=0; iis_repeated()) continue; - - reflection->SwapElements(message, field, 0, 1); - } -} - -void TestUtil::ReflectionTester:: -SetAllocatedOptionalMessageFieldsToNullViaReflection( - Message* message) { - const Reflection* reflection = message->GetReflection(); - - std::vector fields; - reflection->ListFields(*message, &fields); - - for (int i = 0; i < fields.size(); ++i) { - const FieldDescriptor* field = fields[i]; - if (!field->is_optional() || - field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; - - reflection->SetAllocatedMessage(message, NULL, field); - } -} - -void TestUtil::ReflectionTester:: -SetAllocatedOptionalMessageFieldsToMessageViaReflection( - Message* from_message, - Message* to_message) { - EXPECT_EQ(from_message->GetDescriptor(), to_message->GetDescriptor()); - const Reflection* from_reflection = from_message->GetReflection(); - const Reflection* to_reflection = to_message->GetReflection(); - - std::vector fields; - from_reflection->ListFields(*from_message, &fields); - - for (int i = 0; i < fields.size(); ++i) { - const FieldDescriptor* field = fields[i]; - if (!field->is_optional() || - field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; - - Message* sub_message = - from_reflection->ReleaseMessage(from_message, field); - to_reflection->SetAllocatedMessage(to_message, sub_message, field); - } -} - -void TestUtil::ReflectionTester::ExpectMessagesReleasedViaReflection( - Message* message, - TestUtil::ReflectionTester::MessageReleaseState expected_release_state) { - const Reflection* reflection = message->GetReflection(); - - static const char* fields[] = { - "optionalgroup", - "optional_nested_message", - "optional_foreign_message", - "optional_import_message", - }; - for (int i = 0; i < GOOGLE_ARRAYSIZE(fields); i++) { - const Message& sub_message = reflection->GetMessage(*message, F(fields[i])); - Message* released = reflection->ReleaseMessage(message, F(fields[i])); - switch (expected_release_state) { - case IS_NULL: - EXPECT_TRUE(released == NULL); - break; - case NOT_NULL: - EXPECT_TRUE(released != NULL); - if (message->GetArena() == NULL) { - // released message must be same as sub_message if source message is - // not on arena. - EXPECT_EQ(&sub_message, released); - } - break; - case CAN_BE_NULL: - break; - } - delete released; - EXPECT_FALSE(reflection->HasField(*message, F(fields[i]))); - } -} - } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/test_util.h b/src/google/protobuf/test_util.h index 1c13a1a7f61a7..de48c1a469603 100644 --- a/src/google/protobuf/test_util.h +++ b/src/google/protobuf/test_util.h @@ -35,181 +35,1229 @@ #ifndef GOOGLE_PROTOBUF_TEST_UTIL_H__ #define GOOGLE_PROTOBUF_TEST_UTIL_H__ -#include -#include -#include #include +#define UNITTEST ::protobuf_unittest +#define UNITTEST_IMPORT ::protobuf_unittest_import +// Must be included when the preprocessor symbols above are defined. +#include +#undef UNITTEST +#undef UNITTEST_IMPORT + +#include + namespace google { namespace protobuf { - +// This file doesn't use these declarations, but some .cc files do. namespace unittest = ::protobuf_unittest; -namespace unittest_import = protobuf_unittest_import; +namespace unittest_import = ::protobuf_unittest_import; -class TestUtil { +namespace TestUtil { + +class ReflectionTester { public: - // Set every field in the message to a unique value. - static void SetAllFields(unittest::TestAllTypes* message); - static void SetOptionalFields(unittest::TestAllTypes* message); - static void AddRepeatedFields1(unittest::TestAllTypes* message); - static void AddRepeatedFields2(unittest::TestAllTypes* message); - static void SetDefaultFields(unittest::TestAllTypes* message); - static void SetOneofFields(unittest::TestAllTypes* message); - static void SetAllExtensions(unittest::TestAllExtensions* message); - static void SetOneofFields(unittest::TestAllExtensions* message); - static void SetAllFieldsAndExtensions(unittest::TestFieldOrderings* message); - static void SetPackedFields(unittest::TestPackedTypes* message); - static void SetPackedExtensions(unittest::TestPackedExtensions* message); - static void SetUnpackedFields(unittest::TestUnpackedTypes* message); - static void SetOneof1(unittest::TestOneof2* message); - static void SetOneof2(unittest::TestOneof2* message); - - // Use the repeated versions of the set_*() accessors to modify all the - // repeated fields of the message (which should already have been - // initialized with Set*Fields()). Set*Fields() itself only tests - // the add_*() accessors. - static void ModifyRepeatedFields(unittest::TestAllTypes* message); - static void ModifyRepeatedExtensions(unittest::TestAllExtensions* message); - static void ModifyPackedFields(unittest::TestPackedTypes* message); - static void ModifyPackedExtensions(unittest::TestPackedExtensions* message); - - // Check that all fields have the values that they should have after - // Set*Fields() is called. - static void ExpectAllFieldsSet(const unittest::TestAllTypes& message); - static void ExpectAllExtensionsSet( - const unittest::TestAllExtensions& message); - static void ExpectPackedFieldsSet(const unittest::TestPackedTypes& message); - static void ExpectPackedExtensionsSet( - const unittest::TestPackedExtensions& message); - static void ExpectUnpackedFieldsSet( - const unittest::TestUnpackedTypes& message); - static void ExpectUnpackedExtensionsSet( - const unittest::TestUnpackedExtensions& message); - static void ExpectOneofSet1(const unittest::TestOneof2& message); - static void ExpectOneofSet2(const unittest::TestOneof2& message); - - // Expect that the message is modified as would be expected from - // Modify*Fields(). - static void ExpectRepeatedFieldsModified( - const unittest::TestAllTypes& message); - static void ExpectRepeatedExtensionsModified( - const unittest::TestAllExtensions& message); - static void ExpectPackedFieldsModified( - const unittest::TestPackedTypes& message); - static void ExpectPackedExtensionsModified( - const unittest::TestPackedExtensions& message); - - // Check that all fields have their default values. - static void ExpectClear(const unittest::TestAllTypes& message); - static void ExpectExtensionsClear(const unittest::TestAllExtensions& message); - static void ExpectPackedClear(const unittest::TestPackedTypes& message); - static void ExpectPackedExtensionsClear( - const unittest::TestPackedExtensions& message); - static void ExpectOneofClear(const unittest::TestOneof2& message); - - // Check that the passed-in serialization is the canonical serialization we - // expect for a TestFieldOrderings message filled in by - // SetAllFieldsAndExtensions(). - static void ExpectAllFieldsAndExtensionsInOrder(const string& serialized); - - // Check that all repeated fields have had their last elements removed. - static void ExpectLastRepeatedsRemoved( - const unittest::TestAllTypes& message); - static void ExpectLastRepeatedExtensionsRemoved( - const unittest::TestAllExtensions& message); - static void ExpectLastRepeatedsReleased( - const unittest::TestAllTypes& message); - static void ExpectLastRepeatedExtensionsReleased( - const unittest::TestAllExtensions& message); - - // Check that all repeated fields have had their first and last elements - // swapped. - static void ExpectRepeatedsSwapped(const unittest::TestAllTypes& message); - static void ExpectRepeatedExtensionsSwapped( - const unittest::TestAllExtensions& message); - - static void ExpectAtMostOneFieldSetInOneof( - const unittest::TestOneof2 &message); - - // Like above, but use the reflection interface. - class ReflectionTester { - public: - // base_descriptor must be a descriptor for TestAllTypes or - // TestAllExtensions. In the former case, ReflectionTester fetches from - // it the FieldDescriptors needed to use the reflection interface. In - // the latter case, ReflectionTester searches for extension fields in - // its file. - explicit ReflectionTester(const Descriptor* base_descriptor); - - void SetAllFieldsViaReflection(Message* message); - void ModifyRepeatedFieldsViaReflection(Message* message); - void ExpectAllFieldsSetViaReflection(const Message& message); - void ExpectClearViaReflection(const Message& message); - - void SetPackedFieldsViaReflection(Message* message); - void ModifyPackedFieldsViaReflection(Message* message); - void ExpectPackedFieldsSetViaReflection(const Message& message); - void ExpectPackedClearViaReflection(const Message& message); - - void RemoveLastRepeatedsViaReflection(Message* message); - void ReleaseLastRepeatedsViaReflection( - Message* message, bool expect_extensions_notnull); - void SwapRepeatedsViaReflection(Message* message); - void SetAllocatedOptionalMessageFieldsToNullViaReflection( - Message* message); - static void SetAllocatedOptionalMessageFieldsToMessageViaReflection( - Message* from_message, - Message* to_message); - - enum MessageReleaseState { - IS_NULL, - CAN_BE_NULL, - NOT_NULL, - }; - void ExpectMessagesReleasedViaReflection( - Message* message, MessageReleaseState expected_release_state); - - // Set and check functions for TestOneof2 messages. No need to construct - // the ReflectionTester by TestAllTypes nor TestAllExtensions. - static void SetOneofViaReflection(Message* message); - static void ExpectOneofSetViaReflection(const Message& message); - - private: - const FieldDescriptor* F(const string& name); - - const Descriptor* base_descriptor_; - - const FieldDescriptor* group_a_; - const FieldDescriptor* repeated_group_a_; - const FieldDescriptor* nested_b_; - const FieldDescriptor* foreign_c_; - const FieldDescriptor* import_d_; - const FieldDescriptor* import_e_; - - const EnumValueDescriptor* nested_foo_; - const EnumValueDescriptor* nested_bar_; - const EnumValueDescriptor* nested_baz_; - const EnumValueDescriptor* foreign_foo_; - const EnumValueDescriptor* foreign_bar_; - const EnumValueDescriptor* foreign_baz_; - const EnumValueDescriptor* import_foo_; - const EnumValueDescriptor* import_bar_; - const EnumValueDescriptor* import_baz_; - - // We have to split this into three function otherwise it creates a stack - // frame so large that it triggers a warning. - void ExpectAllFieldsSetViaReflection1(const Message& message); - void ExpectAllFieldsSetViaReflection2(const Message& message); - void ExpectAllFieldsSetViaReflection3(const Message& message); - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionTester); + // base_descriptor must be a descriptor for TestAllTypes or + // TestAllExtensions. In the former case, ReflectionTester fetches from + // it the FieldDescriptors needed to use the reflection interface. In + // the latter case, ReflectionTester searches for extension fields in + // its file. + explicit ReflectionTester(const Descriptor* base_descriptor); + + void SetAllFieldsViaReflection(Message* message); + void ModifyRepeatedFieldsViaReflection(Message* message); + void ExpectAllFieldsSetViaReflection(const Message& message); + void ExpectClearViaReflection(const Message& message); + + void SetPackedFieldsViaReflection(Message* message); + void ExpectPackedFieldsSetViaReflection(const Message& message); + + void RemoveLastRepeatedsViaReflection(Message* message); + void ReleaseLastRepeatedsViaReflection(Message* message, + bool expect_extensions_notnull); + void SwapRepeatedsViaReflection(Message* message); + void SetAllocatedOptionalMessageFieldsToNullViaReflection(Message* message); + static void SetAllocatedOptionalMessageFieldsToMessageViaReflection( + Message* from_message, Message* to_message); + + enum MessageReleaseState { + IS_NULL, + CAN_BE_NULL, + NOT_NULL, }; + void ExpectMessagesReleasedViaReflection( + Message* message, MessageReleaseState expected_release_state); + + // Set and check functions for TestOneof2 messages. No need to construct + // the ReflectionTester by TestAllTypes nor TestAllExtensions. + static void SetOneofViaReflection(Message* message); + static void ExpectOneofSetViaReflection(const Message& message); private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TestUtil); + const FieldDescriptor* F(const std::string& name); + + const Descriptor* base_descriptor_; + + const FieldDescriptor* group_a_; + const FieldDescriptor* repeated_group_a_; + const FieldDescriptor* nested_b_; + const FieldDescriptor* foreign_c_; + const FieldDescriptor* import_d_; + const FieldDescriptor* import_e_; + + const EnumValueDescriptor* nested_foo_; + const EnumValueDescriptor* nested_bar_; + const EnumValueDescriptor* nested_baz_; + const EnumValueDescriptor* foreign_foo_; + const EnumValueDescriptor* foreign_bar_; + const EnumValueDescriptor* foreign_baz_; + const EnumValueDescriptor* import_foo_; + const EnumValueDescriptor* import_bar_; + const EnumValueDescriptor* import_baz_; + + // We have to split this into three function otherwise it creates a stack + // frame so large that it triggers a warning. + void ExpectAllFieldsSetViaReflection1(const Message& message); + void ExpectAllFieldsSetViaReflection2(const Message& message); + void ExpectAllFieldsSetViaReflection3(const Message& message); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionTester); }; -} // namespace protobuf +inline TestUtil::ReflectionTester::ReflectionTester( + const Descriptor* base_descriptor) + : base_descriptor_(base_descriptor) { + const DescriptorPool* pool = base_descriptor->file()->pool(); + std::string package = base_descriptor->file()->package(); + const FieldDescriptor* import_descriptor = + pool->FindFieldByName(package + ".TestAllTypes.optional_import_message"); + std::string import_package = + import_descriptor->message_type()->file()->package(); + + nested_b_ = pool->FindFieldByName(package + ".TestAllTypes.NestedMessage.bb"); + foreign_c_ = pool->FindFieldByName(package + ".ForeignMessage.c"); + import_d_ = pool->FindFieldByName(import_package + ".ImportMessage.d"); + import_e_ = pool->FindFieldByName(import_package + ".PublicImportMessage.e"); + nested_foo_ = pool->FindEnumValueByName(package + ".TestAllTypes.FOO"); + nested_bar_ = pool->FindEnumValueByName(package + ".TestAllTypes.BAR"); + nested_baz_ = pool->FindEnumValueByName(package + ".TestAllTypes.BAZ"); + foreign_foo_ = pool->FindEnumValueByName(package + ".FOREIGN_FOO"); + foreign_bar_ = pool->FindEnumValueByName(package + ".FOREIGN_BAR"); + foreign_baz_ = pool->FindEnumValueByName(package + ".FOREIGN_BAZ"); + import_foo_ = pool->FindEnumValueByName(import_package + ".IMPORT_FOO"); + import_bar_ = pool->FindEnumValueByName(import_package + ".IMPORT_BAR"); + import_baz_ = pool->FindEnumValueByName(import_package + ".IMPORT_BAZ"); + + if (base_descriptor_->name() == "TestAllExtensions") { + group_a_ = pool->FindFieldByName(package + ".OptionalGroup_extension.a"); + repeated_group_a_ = + pool->FindFieldByName(package + ".RepeatedGroup_extension.a"); + } else { + group_a_ = pool->FindFieldByName(package + ".TestAllTypes.OptionalGroup.a"); + repeated_group_a_ = + pool->FindFieldByName(package + ".TestAllTypes.RepeatedGroup.a"); + } + + EXPECT_TRUE(group_a_ != nullptr); + EXPECT_TRUE(repeated_group_a_ != nullptr); + EXPECT_TRUE(nested_b_ != nullptr); + EXPECT_TRUE(foreign_c_ != nullptr); + EXPECT_TRUE(import_d_ != nullptr); + EXPECT_TRUE(import_e_ != nullptr); + EXPECT_TRUE(nested_foo_ != nullptr); + EXPECT_TRUE(nested_bar_ != nullptr); + EXPECT_TRUE(nested_baz_ != nullptr); + EXPECT_TRUE(foreign_foo_ != nullptr); + EXPECT_TRUE(foreign_bar_ != nullptr); + EXPECT_TRUE(foreign_baz_ != nullptr); + EXPECT_TRUE(import_foo_ != nullptr); + EXPECT_TRUE(import_bar_ != nullptr); + EXPECT_TRUE(import_baz_ != nullptr); +} + +// Shorthand to get a FieldDescriptor for a field of TestAllTypes. +inline const FieldDescriptor* TestUtil::ReflectionTester::F( + const std::string& name) { + const FieldDescriptor* result = nullptr; + if (base_descriptor_->name() == "TestAllExtensions" || + base_descriptor_->name() == "TestPackedExtensions") { + result = base_descriptor_->file()->FindExtensionByName(name + "_extension"); + } else { + result = base_descriptor_->FindFieldByName(name); + } + GOOGLE_CHECK(result != nullptr); + return result; +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ReflectionTester::SetAllFieldsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + Message* sub_message; + + reflection->SetInt32(message, F("optional_int32"), 101); + reflection->SetInt64(message, F("optional_int64"), 102); + reflection->SetUInt32(message, F("optional_uint32"), 103); + reflection->SetUInt64(message, F("optional_uint64"), 104); + reflection->SetInt32(message, F("optional_sint32"), 105); + reflection->SetInt64(message, F("optional_sint64"), 106); + reflection->SetUInt32(message, F("optional_fixed32"), 107); + reflection->SetUInt64(message, F("optional_fixed64"), 108); + reflection->SetInt32(message, F("optional_sfixed32"), 109); + reflection->SetInt64(message, F("optional_sfixed64"), 110); + reflection->SetFloat(message, F("optional_float"), 111); + reflection->SetDouble(message, F("optional_double"), 112); + reflection->SetBool(message, F("optional_bool"), true); + reflection->SetString(message, F("optional_string"), "115"); + reflection->SetString(message, F("optional_bytes"), "116"); + + sub_message = reflection->MutableMessage(message, F("optionalgroup")); + sub_message->GetReflection()->SetInt32(sub_message, group_a_, 117); + sub_message = + reflection->MutableMessage(message, F("optional_nested_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 118); + sub_message = + reflection->MutableMessage(message, F("optional_foreign_message")); + sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 119); + sub_message = + reflection->MutableMessage(message, F("optional_import_message")); + sub_message->GetReflection()->SetInt32(sub_message, import_d_, 120); + + reflection->SetEnum(message, F("optional_nested_enum"), nested_baz_); + reflection->SetEnum(message, F("optional_foreign_enum"), foreign_baz_); + reflection->SetEnum(message, F("optional_import_enum"), import_baz_); + + reflection->SetString(message, F("optional_string_piece"), "124"); + reflection->SetString(message, F("optional_cord"), "125"); + + sub_message = + reflection->MutableMessage(message, F("optional_public_import_message")); + sub_message->GetReflection()->SetInt32(sub_message, import_e_, 126); + + sub_message = reflection->MutableMessage(message, F("optional_lazy_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 127); + + // ----------------------------------------------------------------- + + reflection->AddInt32(message, F("repeated_int32"), 201); + reflection->AddInt64(message, F("repeated_int64"), 202); + reflection->AddUInt32(message, F("repeated_uint32"), 203); + reflection->AddUInt64(message, F("repeated_uint64"), 204); + reflection->AddInt32(message, F("repeated_sint32"), 205); + reflection->AddInt64(message, F("repeated_sint64"), 206); + reflection->AddUInt32(message, F("repeated_fixed32"), 207); + reflection->AddUInt64(message, F("repeated_fixed64"), 208); + reflection->AddInt32(message, F("repeated_sfixed32"), 209); + reflection->AddInt64(message, F("repeated_sfixed64"), 210); + reflection->AddFloat(message, F("repeated_float"), 211); + reflection->AddDouble(message, F("repeated_double"), 212); + reflection->AddBool(message, F("repeated_bool"), true); + reflection->AddString(message, F("repeated_string"), "215"); + reflection->AddString(message, F("repeated_bytes"), "216"); + + sub_message = reflection->AddMessage(message, F("repeatedgroup")); + sub_message->GetReflection()->SetInt32(sub_message, repeated_group_a_, 217); + sub_message = reflection->AddMessage(message, F("repeated_nested_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 218); + sub_message = reflection->AddMessage(message, F("repeated_foreign_message")); + sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 219); + sub_message = reflection->AddMessage(message, F("repeated_import_message")); + sub_message->GetReflection()->SetInt32(sub_message, import_d_, 220); + sub_message = reflection->AddMessage(message, F("repeated_lazy_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 227); + + reflection->AddEnum(message, F("repeated_nested_enum"), nested_bar_); + reflection->AddEnum(message, F("repeated_foreign_enum"), foreign_bar_); + reflection->AddEnum(message, F("repeated_import_enum"), import_bar_); + + reflection->AddString(message, F("repeated_string_piece"), "224"); + reflection->AddString(message, F("repeated_cord"), "225"); + + // Add a second one of each field. + reflection->AddInt32(message, F("repeated_int32"), 301); + reflection->AddInt64(message, F("repeated_int64"), 302); + reflection->AddUInt32(message, F("repeated_uint32"), 303); + reflection->AddUInt64(message, F("repeated_uint64"), 304); + reflection->AddInt32(message, F("repeated_sint32"), 305); + reflection->AddInt64(message, F("repeated_sint64"), 306); + reflection->AddUInt32(message, F("repeated_fixed32"), 307); + reflection->AddUInt64(message, F("repeated_fixed64"), 308); + reflection->AddInt32(message, F("repeated_sfixed32"), 309); + reflection->AddInt64(message, F("repeated_sfixed64"), 310); + reflection->AddFloat(message, F("repeated_float"), 311); + reflection->AddDouble(message, F("repeated_double"), 312); + reflection->AddBool(message, F("repeated_bool"), false); + reflection->AddString(message, F("repeated_string"), "315"); + reflection->AddString(message, F("repeated_bytes"), "316"); + + sub_message = reflection->AddMessage(message, F("repeatedgroup")); + sub_message->GetReflection()->SetInt32(sub_message, repeated_group_a_, 317); + sub_message = reflection->AddMessage(message, F("repeated_nested_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 318); + sub_message = reflection->AddMessage(message, F("repeated_foreign_message")); + sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 319); + sub_message = reflection->AddMessage(message, F("repeated_import_message")); + sub_message->GetReflection()->SetInt32(sub_message, import_d_, 320); + sub_message = reflection->AddMessage(message, F("repeated_lazy_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 327); + + reflection->AddEnum(message, F("repeated_nested_enum"), nested_baz_); + reflection->AddEnum(message, F("repeated_foreign_enum"), foreign_baz_); + reflection->AddEnum(message, F("repeated_import_enum"), import_baz_); + + reflection->AddString(message, F("repeated_string_piece"), "324"); + reflection->AddString(message, F("repeated_cord"), "325"); + + // ----------------------------------------------------------------- + + reflection->SetInt32(message, F("default_int32"), 401); + reflection->SetInt64(message, F("default_int64"), 402); + reflection->SetUInt32(message, F("default_uint32"), 403); + reflection->SetUInt64(message, F("default_uint64"), 404); + reflection->SetInt32(message, F("default_sint32"), 405); + reflection->SetInt64(message, F("default_sint64"), 406); + reflection->SetUInt32(message, F("default_fixed32"), 407); + reflection->SetUInt64(message, F("default_fixed64"), 408); + reflection->SetInt32(message, F("default_sfixed32"), 409); + reflection->SetInt64(message, F("default_sfixed64"), 410); + reflection->SetFloat(message, F("default_float"), 411); + reflection->SetDouble(message, F("default_double"), 412); + reflection->SetBool(message, F("default_bool"), false); + reflection->SetString(message, F("default_string"), "415"); + reflection->SetString(message, F("default_bytes"), "416"); + + reflection->SetEnum(message, F("default_nested_enum"), nested_foo_); + reflection->SetEnum(message, F("default_foreign_enum"), foreign_foo_); + reflection->SetEnum(message, F("default_import_enum"), import_foo_); + + reflection->SetString(message, F("default_string_piece"), "424"); + reflection->SetString(message, F("default_cord"), "425"); + + reflection->SetUInt32(message, F("oneof_uint32"), 601); + sub_message = reflection->MutableMessage(message, F("oneof_nested_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 602); + reflection->SetString(message, F("oneof_string"), "603"); + reflection->SetString(message, F("oneof_bytes"), "604"); +} + +inline void TestUtil::ReflectionTester::SetOneofViaReflection( + Message* message) { + const Descriptor* descriptor = message->GetDescriptor(); + const Reflection* reflection = message->GetReflection(); + Message* sub_message = reflection->MutableMessage( + message, descriptor->FindFieldByName("foo_lazy_message")); + sub_message->GetReflection()->SetInt64( + sub_message, sub_message->GetDescriptor()->FindFieldByName("qux_int"), + 100); + + reflection->SetString(message, descriptor->FindFieldByName("bar_cord"), + "101"); + reflection->SetInt32(message, descriptor->FindFieldByName("baz_int"), 102); + reflection->SetString(message, descriptor->FindFieldByName("baz_string"), + "103"); +} + +inline void TestUtil::ReflectionTester::ExpectOneofSetViaReflection( + const Message& message) { + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* reflection = message.GetReflection(); + std::string scratch; + EXPECT_TRUE(reflection->HasField( + message, descriptor->FindFieldByName("foo_lazy_message"))); + EXPECT_TRUE( + reflection->HasField(message, descriptor->FindFieldByName("bar_cord"))); + EXPECT_TRUE( + reflection->HasField(message, descriptor->FindFieldByName("baz_int"))); + EXPECT_TRUE( + reflection->HasField(message, descriptor->FindFieldByName("baz_string"))); + + const Message* sub_message = &reflection->GetMessage( + message, descriptor->FindFieldByName("foo_lazy_message")); + EXPECT_EQ(100, sub_message->GetReflection()->GetInt64( + *sub_message, + sub_message->GetDescriptor()->FindFieldByName("qux_int"))); + + EXPECT_EQ("101", reflection->GetString( + message, descriptor->FindFieldByName("bar_cord"))); + EXPECT_EQ("101", + reflection->GetStringReference( + message, descriptor->FindFieldByName("bar_cord"), &scratch)); + + EXPECT_EQ(102, reflection->GetInt32(message, + descriptor->FindFieldByName("baz_int"))); + + EXPECT_EQ("103", reflection->GetString( + message, descriptor->FindFieldByName("baz_string"))); + EXPECT_EQ("103", + reflection->GetStringReference( + message, descriptor->FindFieldByName("baz_string"), &scratch)); +} + +inline void TestUtil::ReflectionTester::SetPackedFieldsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + reflection->AddInt32(message, F("packed_int32"), 601); + reflection->AddInt64(message, F("packed_int64"), 602); + reflection->AddUInt32(message, F("packed_uint32"), 603); + reflection->AddUInt64(message, F("packed_uint64"), 604); + reflection->AddInt32(message, F("packed_sint32"), 605); + reflection->AddInt64(message, F("packed_sint64"), 606); + reflection->AddUInt32(message, F("packed_fixed32"), 607); + reflection->AddUInt64(message, F("packed_fixed64"), 608); + reflection->AddInt32(message, F("packed_sfixed32"), 609); + reflection->AddInt64(message, F("packed_sfixed64"), 610); + reflection->AddFloat(message, F("packed_float"), 611); + reflection->AddDouble(message, F("packed_double"), 612); + reflection->AddBool(message, F("packed_bool"), true); + reflection->AddEnum(message, F("packed_enum"), foreign_bar_); + + reflection->AddInt32(message, F("packed_int32"), 701); + reflection->AddInt64(message, F("packed_int64"), 702); + reflection->AddUInt32(message, F("packed_uint32"), 703); + reflection->AddUInt64(message, F("packed_uint64"), 704); + reflection->AddInt32(message, F("packed_sint32"), 705); + reflection->AddInt64(message, F("packed_sint64"), 706); + reflection->AddUInt32(message, F("packed_fixed32"), 707); + reflection->AddUInt64(message, F("packed_fixed64"), 708); + reflection->AddInt32(message, F("packed_sfixed32"), 709); + reflection->AddInt64(message, F("packed_sfixed64"), 710); + reflection->AddFloat(message, F("packed_float"), 711); + reflection->AddDouble(message, F("packed_double"), 712); + reflection->AddBool(message, F("packed_bool"), false); + reflection->AddEnum(message, F("packed_enum"), foreign_baz_); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection( + const Message& message) { + // We have to split this into three function otherwise it creates a stack + // frame so large that it triggers a warning. + ExpectAllFieldsSetViaReflection1(message); + ExpectAllFieldsSetViaReflection2(message); + ExpectAllFieldsSetViaReflection3(message); +} + +inline void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection1( + const Message& message) { + const Reflection* reflection = message.GetReflection(); + std::string scratch; + const Message* sub_message; + + EXPECT_TRUE(reflection->HasField(message, F("optional_int32"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_int64"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_uint32"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_uint64"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_sint32"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_sint64"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_fixed32"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_fixed64"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_sfixed32"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_sfixed64"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_float"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_double"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_bool"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_string"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_bytes"))); + + EXPECT_TRUE(reflection->HasField(message, F("optionalgroup"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_nested_message"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_message"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_import_message"))); + EXPECT_TRUE( + reflection->HasField(message, F("optional_public_import_message"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_lazy_message"))); + + sub_message = &reflection->GetMessage(message, F("optionalgroup")); + EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, group_a_)); + sub_message = &reflection->GetMessage(message, F("optional_nested_message")); + EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, nested_b_)); + sub_message = &reflection->GetMessage(message, F("optional_foreign_message")); + EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, foreign_c_)); + sub_message = &reflection->GetMessage(message, F("optional_import_message")); + EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, import_d_)); + sub_message = + &reflection->GetMessage(message, F("optional_public_import_message")); + EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, import_e_)); + sub_message = &reflection->GetMessage(message, F("optional_lazy_message")); + EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, nested_b_)); + + EXPECT_TRUE(reflection->HasField(message, F("optional_nested_enum"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_enum"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_import_enum"))); + + EXPECT_TRUE(reflection->HasField(message, F("optional_string_piece"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_cord"))); + + EXPECT_EQ(101, reflection->GetInt32(message, F("optional_int32"))); + EXPECT_EQ(102, reflection->GetInt64(message, F("optional_int64"))); + EXPECT_EQ(103, reflection->GetUInt32(message, F("optional_uint32"))); + EXPECT_EQ(104, reflection->GetUInt64(message, F("optional_uint64"))); + EXPECT_EQ(105, reflection->GetInt32(message, F("optional_sint32"))); + EXPECT_EQ(106, reflection->GetInt64(message, F("optional_sint64"))); + EXPECT_EQ(107, reflection->GetUInt32(message, F("optional_fixed32"))); + EXPECT_EQ(108, reflection->GetUInt64(message, F("optional_fixed64"))); + EXPECT_EQ(109, reflection->GetInt32(message, F("optional_sfixed32"))); + EXPECT_EQ(110, reflection->GetInt64(message, F("optional_sfixed64"))); + EXPECT_EQ(111, reflection->GetFloat(message, F("optional_float"))); + EXPECT_EQ(112, reflection->GetDouble(message, F("optional_double"))); + EXPECT_TRUE(reflection->GetBool(message, F("optional_bool"))); + EXPECT_EQ("115", reflection->GetString(message, F("optional_string"))); + EXPECT_EQ("116", reflection->GetString(message, F("optional_bytes"))); + + EXPECT_EQ("115", reflection->GetStringReference(message, F("optional_string"), + &scratch)); + EXPECT_EQ("116", reflection->GetStringReference(message, F("optional_bytes"), + &scratch)); + + sub_message = &reflection->GetMessage(message, F("optionalgroup")); + EXPECT_EQ(117, + sub_message->GetReflection()->GetInt32(*sub_message, group_a_)); + sub_message = &reflection->GetMessage(message, F("optional_nested_message")); + EXPECT_EQ(118, + sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + sub_message = &reflection->GetMessage(message, F("optional_foreign_message")); + EXPECT_EQ(119, + sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); + sub_message = &reflection->GetMessage(message, F("optional_import_message")); + EXPECT_EQ(120, + sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); + sub_message = + &reflection->GetMessage(message, F("optional_public_import_message")); + EXPECT_EQ(126, + sub_message->GetReflection()->GetInt32(*sub_message, import_e_)); + sub_message = &reflection->GetMessage(message, F("optional_lazy_message")); + EXPECT_EQ(127, + sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + + EXPECT_EQ(nested_baz_, + reflection->GetEnum(message, F("optional_nested_enum"))); + EXPECT_EQ(foreign_baz_, + reflection->GetEnum(message, F("optional_foreign_enum"))); + EXPECT_EQ(import_baz_, + reflection->GetEnum(message, F("optional_import_enum"))); + + EXPECT_EQ("124", reflection->GetString(message, F("optional_string_piece"))); + EXPECT_EQ("124", reflection->GetStringReference( + message, F("optional_string_piece"), &scratch)); + + EXPECT_EQ("125", reflection->GetString(message, F("optional_cord"))); + EXPECT_EQ("125", reflection->GetStringReference(message, F("optional_cord"), + &scratch)); + + EXPECT_TRUE(reflection->HasField(message, F("oneof_bytes"))); + EXPECT_EQ("604", reflection->GetString(message, F("oneof_bytes"))); + + if (base_descriptor_->name() == "TestAllTypes") { + EXPECT_FALSE(reflection->HasField(message, F("oneof_uint32"))); + EXPECT_FALSE(reflection->HasField(message, F("oneof_string"))); + } else { + EXPECT_TRUE(reflection->HasField(message, F("oneof_uint32"))); + EXPECT_TRUE(reflection->HasField(message, F("oneof_string"))); + EXPECT_EQ(601, reflection->GetUInt32(message, F("oneof_uint32"))); + EXPECT_EQ("603", reflection->GetString(message, F("oneof_string"))); + sub_message = &reflection->GetMessage(message, F("oneof_nested_message")); + EXPECT_EQ(602, + sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + } +} + +inline void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection2( + const Message& message) { + const Reflection* reflection = message.GetReflection(); + std::string scratch; + const Message* sub_message; + + // ----------------------------------------------------------------- + + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_int32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_int64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_uint32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_uint64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sint32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sint64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_fixed32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_fixed64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sfixed32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sfixed64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_float"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_double"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_bool"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_string"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_bytes"))); + + ASSERT_EQ(2, reflection->FieldSize(message, F("repeatedgroup"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_nested_message"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_foreign_message"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_import_message"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_lazy_message"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_nested_enum"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_foreign_enum"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_import_enum"))); + + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_string_piece"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_cord"))); + + EXPECT_EQ(201, reflection->GetRepeatedInt32(message, F("repeated_int32"), 0)); + EXPECT_EQ(202, reflection->GetRepeatedInt64(message, F("repeated_int64"), 0)); + EXPECT_EQ(203, + reflection->GetRepeatedUInt32(message, F("repeated_uint32"), 0)); + EXPECT_EQ(204, + reflection->GetRepeatedUInt64(message, F("repeated_uint64"), 0)); + EXPECT_EQ(205, + reflection->GetRepeatedInt32(message, F("repeated_sint32"), 0)); + EXPECT_EQ(206, + reflection->GetRepeatedInt64(message, F("repeated_sint64"), 0)); + EXPECT_EQ(207, + reflection->GetRepeatedUInt32(message, F("repeated_fixed32"), 0)); + EXPECT_EQ(208, + reflection->GetRepeatedUInt64(message, F("repeated_fixed64"), 0)); + EXPECT_EQ(209, + reflection->GetRepeatedInt32(message, F("repeated_sfixed32"), 0)); + EXPECT_EQ(210, + reflection->GetRepeatedInt64(message, F("repeated_sfixed64"), 0)); + EXPECT_EQ(211, reflection->GetRepeatedFloat(message, F("repeated_float"), 0)); + EXPECT_EQ(212, + reflection->GetRepeatedDouble(message, F("repeated_double"), 0)); + EXPECT_TRUE(reflection->GetRepeatedBool(message, F("repeated_bool"), 0)); + EXPECT_EQ("215", + reflection->GetRepeatedString(message, F("repeated_string"), 0)); + EXPECT_EQ("216", + reflection->GetRepeatedString(message, F("repeated_bytes"), 0)); + + EXPECT_EQ("215", reflection->GetRepeatedStringReference( + message, F("repeated_string"), 0, &scratch)); + EXPECT_EQ("216", reflection->GetRepeatedStringReference( + message, F("repeated_bytes"), 0, &scratch)); + + sub_message = &reflection->GetRepeatedMessage(message, F("repeatedgroup"), 0); + EXPECT_EQ(217, sub_message->GetReflection()->GetInt32(*sub_message, + repeated_group_a_)); + sub_message = + &reflection->GetRepeatedMessage(message, F("repeated_nested_message"), 0); + EXPECT_EQ(218, + sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + sub_message = &reflection->GetRepeatedMessage( + message, F("repeated_foreign_message"), 0); + EXPECT_EQ(219, + sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); + sub_message = + &reflection->GetRepeatedMessage(message, F("repeated_import_message"), 0); + EXPECT_EQ(220, + sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); + sub_message = + &reflection->GetRepeatedMessage(message, F("repeated_lazy_message"), 0); + EXPECT_EQ(227, + sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + + EXPECT_EQ(nested_bar_, + reflection->GetRepeatedEnum(message, F("repeated_nested_enum"), 0)); + EXPECT_EQ(foreign_bar_, reflection->GetRepeatedEnum( + message, F("repeated_foreign_enum"), 0)); + EXPECT_EQ(import_bar_, + reflection->GetRepeatedEnum(message, F("repeated_import_enum"), 0)); + + EXPECT_EQ("224", reflection->GetRepeatedString( + message, F("repeated_string_piece"), 0)); + EXPECT_EQ("224", reflection->GetRepeatedStringReference( + message, F("repeated_string_piece"), 0, &scratch)); + EXPECT_EQ("225", + reflection->GetRepeatedString(message, F("repeated_cord"), 0)); + EXPECT_EQ("225", reflection->GetRepeatedStringReference( + message, F("repeated_cord"), 0, &scratch)); + + EXPECT_EQ(301, reflection->GetRepeatedInt32(message, F("repeated_int32"), 1)); + EXPECT_EQ(302, reflection->GetRepeatedInt64(message, F("repeated_int64"), 1)); + EXPECT_EQ(303, + reflection->GetRepeatedUInt32(message, F("repeated_uint32"), 1)); + EXPECT_EQ(304, + reflection->GetRepeatedUInt64(message, F("repeated_uint64"), 1)); + EXPECT_EQ(305, + reflection->GetRepeatedInt32(message, F("repeated_sint32"), 1)); + EXPECT_EQ(306, + reflection->GetRepeatedInt64(message, F("repeated_sint64"), 1)); + EXPECT_EQ(307, + reflection->GetRepeatedUInt32(message, F("repeated_fixed32"), 1)); + EXPECT_EQ(308, + reflection->GetRepeatedUInt64(message, F("repeated_fixed64"), 1)); + EXPECT_EQ(309, + reflection->GetRepeatedInt32(message, F("repeated_sfixed32"), 1)); + EXPECT_EQ(310, + reflection->GetRepeatedInt64(message, F("repeated_sfixed64"), 1)); + EXPECT_EQ(311, reflection->GetRepeatedFloat(message, F("repeated_float"), 1)); + EXPECT_EQ(312, + reflection->GetRepeatedDouble(message, F("repeated_double"), 1)); + EXPECT_FALSE(reflection->GetRepeatedBool(message, F("repeated_bool"), 1)); + EXPECT_EQ("315", + reflection->GetRepeatedString(message, F("repeated_string"), 1)); + EXPECT_EQ("316", + reflection->GetRepeatedString(message, F("repeated_bytes"), 1)); + + EXPECT_EQ("315", reflection->GetRepeatedStringReference( + message, F("repeated_string"), 1, &scratch)); + EXPECT_EQ("316", reflection->GetRepeatedStringReference( + message, F("repeated_bytes"), 1, &scratch)); + + sub_message = &reflection->GetRepeatedMessage(message, F("repeatedgroup"), 1); + EXPECT_EQ(317, sub_message->GetReflection()->GetInt32(*sub_message, + repeated_group_a_)); + sub_message = + &reflection->GetRepeatedMessage(message, F("repeated_nested_message"), 1); + EXPECT_EQ(318, + sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + sub_message = &reflection->GetRepeatedMessage( + message, F("repeated_foreign_message"), 1); + EXPECT_EQ(319, + sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); + sub_message = + &reflection->GetRepeatedMessage(message, F("repeated_import_message"), 1); + EXPECT_EQ(320, + sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); + sub_message = + &reflection->GetRepeatedMessage(message, F("repeated_lazy_message"), 1); + EXPECT_EQ(327, + sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + + EXPECT_EQ(nested_baz_, + reflection->GetRepeatedEnum(message, F("repeated_nested_enum"), 1)); + EXPECT_EQ(foreign_baz_, reflection->GetRepeatedEnum( + message, F("repeated_foreign_enum"), 1)); + EXPECT_EQ(import_baz_, + reflection->GetRepeatedEnum(message, F("repeated_import_enum"), 1)); + + EXPECT_EQ("324", reflection->GetRepeatedString( + message, F("repeated_string_piece"), 1)); + EXPECT_EQ("324", reflection->GetRepeatedStringReference( + message, F("repeated_string_piece"), 1, &scratch)); + + EXPECT_EQ("325", + reflection->GetRepeatedString(message, F("repeated_cord"), 1)); + EXPECT_EQ("325", reflection->GetRepeatedStringReference( + message, F("repeated_cord"), 1, &scratch)); +} + +inline void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection3( + const Message& message) { + const Reflection* reflection = message.GetReflection(); + std::string scratch; + + // ----------------------------------------------------------------- + + EXPECT_TRUE(reflection->HasField(message, F("default_int32"))); + EXPECT_TRUE(reflection->HasField(message, F("default_int64"))); + EXPECT_TRUE(reflection->HasField(message, F("default_uint32"))); + EXPECT_TRUE(reflection->HasField(message, F("default_uint64"))); + EXPECT_TRUE(reflection->HasField(message, F("default_sint32"))); + EXPECT_TRUE(reflection->HasField(message, F("default_sint64"))); + EXPECT_TRUE(reflection->HasField(message, F("default_fixed32"))); + EXPECT_TRUE(reflection->HasField(message, F("default_fixed64"))); + EXPECT_TRUE(reflection->HasField(message, F("default_sfixed32"))); + EXPECT_TRUE(reflection->HasField(message, F("default_sfixed64"))); + EXPECT_TRUE(reflection->HasField(message, F("default_float"))); + EXPECT_TRUE(reflection->HasField(message, F("default_double"))); + EXPECT_TRUE(reflection->HasField(message, F("default_bool"))); + EXPECT_TRUE(reflection->HasField(message, F("default_string"))); + EXPECT_TRUE(reflection->HasField(message, F("default_bytes"))); + + EXPECT_TRUE(reflection->HasField(message, F("default_nested_enum"))); + EXPECT_TRUE(reflection->HasField(message, F("default_foreign_enum"))); + EXPECT_TRUE(reflection->HasField(message, F("default_import_enum"))); + + EXPECT_TRUE(reflection->HasField(message, F("default_string_piece"))); + EXPECT_TRUE(reflection->HasField(message, F("default_cord"))); + + EXPECT_EQ(401, reflection->GetInt32(message, F("default_int32"))); + EXPECT_EQ(402, reflection->GetInt64(message, F("default_int64"))); + EXPECT_EQ(403, reflection->GetUInt32(message, F("default_uint32"))); + EXPECT_EQ(404, reflection->GetUInt64(message, F("default_uint64"))); + EXPECT_EQ(405, reflection->GetInt32(message, F("default_sint32"))); + EXPECT_EQ(406, reflection->GetInt64(message, F("default_sint64"))); + EXPECT_EQ(407, reflection->GetUInt32(message, F("default_fixed32"))); + EXPECT_EQ(408, reflection->GetUInt64(message, F("default_fixed64"))); + EXPECT_EQ(409, reflection->GetInt32(message, F("default_sfixed32"))); + EXPECT_EQ(410, reflection->GetInt64(message, F("default_sfixed64"))); + EXPECT_EQ(411, reflection->GetFloat(message, F("default_float"))); + EXPECT_EQ(412, reflection->GetDouble(message, F("default_double"))); + EXPECT_FALSE(reflection->GetBool(message, F("default_bool"))); + EXPECT_EQ("415", reflection->GetString(message, F("default_string"))); + EXPECT_EQ("416", reflection->GetString(message, F("default_bytes"))); + + EXPECT_EQ("415", reflection->GetStringReference(message, F("default_string"), + &scratch)); + EXPECT_EQ("416", reflection->GetStringReference(message, F("default_bytes"), + &scratch)); + + EXPECT_EQ(nested_foo_, + reflection->GetEnum(message, F("default_nested_enum"))); + EXPECT_EQ(foreign_foo_, + reflection->GetEnum(message, F("default_foreign_enum"))); + EXPECT_EQ(import_foo_, + reflection->GetEnum(message, F("default_import_enum"))); + + EXPECT_EQ("424", reflection->GetString(message, F("default_string_piece"))); + EXPECT_EQ("424", reflection->GetStringReference( + message, F("default_string_piece"), &scratch)); + + EXPECT_EQ("425", reflection->GetString(message, F("default_cord"))); + EXPECT_EQ("425", reflection->GetStringReference(message, F("default_cord"), + &scratch)); +} + +inline void TestUtil::ReflectionTester::ExpectPackedFieldsSetViaReflection( + const Message& message) { + const Reflection* reflection = message.GetReflection(); + + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_int32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_int64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_uint32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_uint64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sint32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sint64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_fixed32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_fixed64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sfixed32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sfixed64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_float"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_double"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_bool"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_enum"))); + + EXPECT_EQ(601, reflection->GetRepeatedInt32(message, F("packed_int32"), 0)); + EXPECT_EQ(602, reflection->GetRepeatedInt64(message, F("packed_int64"), 0)); + EXPECT_EQ(603, reflection->GetRepeatedUInt32(message, F("packed_uint32"), 0)); + EXPECT_EQ(604, reflection->GetRepeatedUInt64(message, F("packed_uint64"), 0)); + EXPECT_EQ(605, reflection->GetRepeatedInt32(message, F("packed_sint32"), 0)); + EXPECT_EQ(606, reflection->GetRepeatedInt64(message, F("packed_sint64"), 0)); + EXPECT_EQ(607, + reflection->GetRepeatedUInt32(message, F("packed_fixed32"), 0)); + EXPECT_EQ(608, + reflection->GetRepeatedUInt64(message, F("packed_fixed64"), 0)); + EXPECT_EQ(609, + reflection->GetRepeatedInt32(message, F("packed_sfixed32"), 0)); + EXPECT_EQ(610, + reflection->GetRepeatedInt64(message, F("packed_sfixed64"), 0)); + EXPECT_EQ(611, reflection->GetRepeatedFloat(message, F("packed_float"), 0)); + EXPECT_EQ(612, reflection->GetRepeatedDouble(message, F("packed_double"), 0)); + EXPECT_TRUE(reflection->GetRepeatedBool(message, F("packed_bool"), 0)); + EXPECT_EQ(foreign_bar_, + reflection->GetRepeatedEnum(message, F("packed_enum"), 0)); + + EXPECT_EQ(701, reflection->GetRepeatedInt32(message, F("packed_int32"), 1)); + EXPECT_EQ(702, reflection->GetRepeatedInt64(message, F("packed_int64"), 1)); + EXPECT_EQ(703, reflection->GetRepeatedUInt32(message, F("packed_uint32"), 1)); + EXPECT_EQ(704, reflection->GetRepeatedUInt64(message, F("packed_uint64"), 1)); + EXPECT_EQ(705, reflection->GetRepeatedInt32(message, F("packed_sint32"), 1)); + EXPECT_EQ(706, reflection->GetRepeatedInt64(message, F("packed_sint64"), 1)); + EXPECT_EQ(707, + reflection->GetRepeatedUInt32(message, F("packed_fixed32"), 1)); + EXPECT_EQ(708, + reflection->GetRepeatedUInt64(message, F("packed_fixed64"), 1)); + EXPECT_EQ(709, + reflection->GetRepeatedInt32(message, F("packed_sfixed32"), 1)); + EXPECT_EQ(710, + reflection->GetRepeatedInt64(message, F("packed_sfixed64"), 1)); + EXPECT_EQ(711, reflection->GetRepeatedFloat(message, F("packed_float"), 1)); + EXPECT_EQ(712, reflection->GetRepeatedDouble(message, F("packed_double"), 1)); + EXPECT_FALSE(reflection->GetRepeatedBool(message, F("packed_bool"), 1)); + EXPECT_EQ(foreign_baz_, + reflection->GetRepeatedEnum(message, F("packed_enum"), 1)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ReflectionTester::ExpectClearViaReflection( + const Message& message) { + const Reflection* reflection = message.GetReflection(); + std::string scratch; + const Message* sub_message; + + // has_blah() should initially be false for all optional fields. + EXPECT_FALSE(reflection->HasField(message, F("optional_int32"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_int64"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_uint32"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_uint64"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_sint32"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_sint64"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_fixed32"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_fixed64"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_sfixed32"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_sfixed64"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_float"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_double"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_bool"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_string"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_bytes"))); + + EXPECT_FALSE(reflection->HasField(message, F("optionalgroup"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_nested_message"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_foreign_message"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_import_message"))); + EXPECT_FALSE( + reflection->HasField(message, F("optional_public_import_message"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_lazy_message"))); + + EXPECT_FALSE(reflection->HasField(message, F("optional_nested_enum"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_foreign_enum"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_import_enum"))); + + EXPECT_FALSE(reflection->HasField(message, F("optional_string_piece"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_cord"))); + + // Optional fields without defaults are set to zero or something like it. + EXPECT_EQ(0, reflection->GetInt32(message, F("optional_int32"))); + EXPECT_EQ(0, reflection->GetInt64(message, F("optional_int64"))); + EXPECT_EQ(0, reflection->GetUInt32(message, F("optional_uint32"))); + EXPECT_EQ(0, reflection->GetUInt64(message, F("optional_uint64"))); + EXPECT_EQ(0, reflection->GetInt32(message, F("optional_sint32"))); + EXPECT_EQ(0, reflection->GetInt64(message, F("optional_sint64"))); + EXPECT_EQ(0, reflection->GetUInt32(message, F("optional_fixed32"))); + EXPECT_EQ(0, reflection->GetUInt64(message, F("optional_fixed64"))); + EXPECT_EQ(0, reflection->GetInt32(message, F("optional_sfixed32"))); + EXPECT_EQ(0, reflection->GetInt64(message, F("optional_sfixed64"))); + EXPECT_EQ(0, reflection->GetFloat(message, F("optional_float"))); + EXPECT_EQ(0, reflection->GetDouble(message, F("optional_double"))); + EXPECT_FALSE(reflection->GetBool(message, F("optional_bool"))); + EXPECT_EQ("", reflection->GetString(message, F("optional_string"))); + EXPECT_EQ("", reflection->GetString(message, F("optional_bytes"))); + + EXPECT_EQ("", reflection->GetStringReference(message, F("optional_string"), + &scratch)); + EXPECT_EQ("", reflection->GetStringReference(message, F("optional_bytes"), + &scratch)); + + // Embedded messages should also be clear. + sub_message = &reflection->GetMessage(message, F("optionalgroup")); + EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, group_a_)); + EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, group_a_)); + sub_message = &reflection->GetMessage(message, F("optional_nested_message")); + EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, nested_b_)); + EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + sub_message = &reflection->GetMessage(message, F("optional_foreign_message")); + EXPECT_FALSE( + sub_message->GetReflection()->HasField(*sub_message, foreign_c_)); + EXPECT_EQ(0, + sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); + sub_message = &reflection->GetMessage(message, F("optional_import_message")); + EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, import_d_)); + EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); + sub_message = + &reflection->GetMessage(message, F("optional_public_import_message")); + EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, import_e_)); + EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, import_e_)); + sub_message = &reflection->GetMessage(message, F("optional_lazy_message")); + EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, nested_b_)); + EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + + // Enums without defaults are set to the first value in the enum. + EXPECT_EQ(nested_foo_, + reflection->GetEnum(message, F("optional_nested_enum"))); + EXPECT_EQ(foreign_foo_, + reflection->GetEnum(message, F("optional_foreign_enum"))); + EXPECT_EQ(import_foo_, + reflection->GetEnum(message, F("optional_import_enum"))); + + EXPECT_EQ("", reflection->GetString(message, F("optional_string_piece"))); + EXPECT_EQ("", reflection->GetStringReference( + message, F("optional_string_piece"), &scratch)); + + EXPECT_EQ("", reflection->GetString(message, F("optional_cord"))); + EXPECT_EQ("", reflection->GetStringReference(message, F("optional_cord"), + &scratch)); + + // Repeated fields are empty. + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_int32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_int64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_uint32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_uint64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sint32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sint64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_fixed32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_fixed64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sfixed32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sfixed64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_float"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_double"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_bool"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_string"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_bytes"))); + + EXPECT_EQ(0, reflection->FieldSize(message, F("repeatedgroup"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_nested_message"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_foreign_message"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_import_message"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_lazy_message"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_nested_enum"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_foreign_enum"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_import_enum"))); + + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_string_piece"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_cord"))); + + // has_blah() should also be false for all default fields. + EXPECT_FALSE(reflection->HasField(message, F("default_int32"))); + EXPECT_FALSE(reflection->HasField(message, F("default_int64"))); + EXPECT_FALSE(reflection->HasField(message, F("default_uint32"))); + EXPECT_FALSE(reflection->HasField(message, F("default_uint64"))); + EXPECT_FALSE(reflection->HasField(message, F("default_sint32"))); + EXPECT_FALSE(reflection->HasField(message, F("default_sint64"))); + EXPECT_FALSE(reflection->HasField(message, F("default_fixed32"))); + EXPECT_FALSE(reflection->HasField(message, F("default_fixed64"))); + EXPECT_FALSE(reflection->HasField(message, F("default_sfixed32"))); + EXPECT_FALSE(reflection->HasField(message, F("default_sfixed64"))); + EXPECT_FALSE(reflection->HasField(message, F("default_float"))); + EXPECT_FALSE(reflection->HasField(message, F("default_double"))); + EXPECT_FALSE(reflection->HasField(message, F("default_bool"))); + EXPECT_FALSE(reflection->HasField(message, F("default_string"))); + EXPECT_FALSE(reflection->HasField(message, F("default_bytes"))); + + EXPECT_FALSE(reflection->HasField(message, F("default_nested_enum"))); + EXPECT_FALSE(reflection->HasField(message, F("default_foreign_enum"))); + EXPECT_FALSE(reflection->HasField(message, F("default_import_enum"))); + + EXPECT_FALSE(reflection->HasField(message, F("default_string_piece"))); + EXPECT_FALSE(reflection->HasField(message, F("default_cord"))); + + // Fields with defaults have their default values (duh). + EXPECT_EQ(41, reflection->GetInt32(message, F("default_int32"))); + EXPECT_EQ(42, reflection->GetInt64(message, F("default_int64"))); + EXPECT_EQ(43, reflection->GetUInt32(message, F("default_uint32"))); + EXPECT_EQ(44, reflection->GetUInt64(message, F("default_uint64"))); + EXPECT_EQ(-45, reflection->GetInt32(message, F("default_sint32"))); + EXPECT_EQ(46, reflection->GetInt64(message, F("default_sint64"))); + EXPECT_EQ(47, reflection->GetUInt32(message, F("default_fixed32"))); + EXPECT_EQ(48, reflection->GetUInt64(message, F("default_fixed64"))); + EXPECT_EQ(49, reflection->GetInt32(message, F("default_sfixed32"))); + EXPECT_EQ(-50, reflection->GetInt64(message, F("default_sfixed64"))); + EXPECT_EQ(51.5, reflection->GetFloat(message, F("default_float"))); + EXPECT_EQ(52e3, reflection->GetDouble(message, F("default_double"))); + EXPECT_TRUE(reflection->GetBool(message, F("default_bool"))); + EXPECT_EQ("hello", reflection->GetString(message, F("default_string"))); + EXPECT_EQ("world", reflection->GetString(message, F("default_bytes"))); + + EXPECT_EQ("hello", reflection->GetStringReference( + message, F("default_string"), &scratch)); + EXPECT_EQ("world", reflection->GetStringReference(message, F("default_bytes"), + &scratch)); + + EXPECT_EQ(nested_bar_, + reflection->GetEnum(message, F("default_nested_enum"))); + EXPECT_EQ(foreign_bar_, + reflection->GetEnum(message, F("default_foreign_enum"))); + EXPECT_EQ(import_bar_, + reflection->GetEnum(message, F("default_import_enum"))); + + EXPECT_EQ("abc", reflection->GetString(message, F("default_string_piece"))); + EXPECT_EQ("abc", reflection->GetStringReference( + message, F("default_string_piece"), &scratch)); + + EXPECT_EQ("123", reflection->GetString(message, F("default_cord"))); + EXPECT_EQ("123", reflection->GetStringReference(message, F("default_cord"), + &scratch)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ReflectionTester::ModifyRepeatedFieldsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + Message* sub_message; + + reflection->SetRepeatedInt32(message, F("repeated_int32"), 1, 501); + reflection->SetRepeatedInt64(message, F("repeated_int64"), 1, 502); + reflection->SetRepeatedUInt32(message, F("repeated_uint32"), 1, 503); + reflection->SetRepeatedUInt64(message, F("repeated_uint64"), 1, 504); + reflection->SetRepeatedInt32(message, F("repeated_sint32"), 1, 505); + reflection->SetRepeatedInt64(message, F("repeated_sint64"), 1, 506); + reflection->SetRepeatedUInt32(message, F("repeated_fixed32"), 1, 507); + reflection->SetRepeatedUInt64(message, F("repeated_fixed64"), 1, 508); + reflection->SetRepeatedInt32(message, F("repeated_sfixed32"), 1, 509); + reflection->SetRepeatedInt64(message, F("repeated_sfixed64"), 1, 510); + reflection->SetRepeatedFloat(message, F("repeated_float"), 1, 511); + reflection->SetRepeatedDouble(message, F("repeated_double"), 1, 512); + reflection->SetRepeatedBool(message, F("repeated_bool"), 1, true); + reflection->SetRepeatedString(message, F("repeated_string"), 1, "515"); + reflection->SetRepeatedString(message, F("repeated_bytes"), 1, "516"); + + sub_message = + reflection->MutableRepeatedMessage(message, F("repeatedgroup"), 1); + sub_message->GetReflection()->SetInt32(sub_message, repeated_group_a_, 517); + sub_message = reflection->MutableRepeatedMessage( + message, F("repeated_nested_message"), 1); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 518); + sub_message = reflection->MutableRepeatedMessage( + message, F("repeated_foreign_message"), 1); + sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 519); + sub_message = reflection->MutableRepeatedMessage( + message, F("repeated_import_message"), 1); + sub_message->GetReflection()->SetInt32(sub_message, import_d_, 520); + sub_message = reflection->MutableRepeatedMessage( + message, F("repeated_lazy_message"), 1); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 527); + + reflection->SetRepeatedEnum(message, F("repeated_nested_enum"), 1, + nested_foo_); + reflection->SetRepeatedEnum(message, F("repeated_foreign_enum"), 1, + foreign_foo_); + reflection->SetRepeatedEnum(message, F("repeated_import_enum"), 1, + import_foo_); + + reflection->SetRepeatedString(message, F("repeated_string_piece"), 1, "524"); + reflection->SetRepeatedString(message, F("repeated_cord"), 1, "525"); +} + +inline void TestUtil::ReflectionTester::RemoveLastRepeatedsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + + std::vector output; + reflection->ListFields(*message, &output); + for (int i = 0; i < output.size(); ++i) { + const FieldDescriptor* field = output[i]; + if (!field->is_repeated()) continue; + + reflection->RemoveLast(message, field); + } +} + +inline void TestUtil::ReflectionTester::ReleaseLastRepeatedsViaReflection( + Message* message, bool expect_extensions_notnull) { + const Reflection* reflection = message->GetReflection(); + + std::vector output; + reflection->ListFields(*message, &output); + for (int i = 0; i < output.size(); ++i) { + const FieldDescriptor* field = output[i]; + if (!field->is_repeated()) continue; + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; + + Message* released = reflection->ReleaseLast(message, field); + if (!field->is_extension() || expect_extensions_notnull) { + ASSERT_TRUE(released != nullptr) + << "ReleaseLast returned nullptr for: " << field->name(); + } + delete released; + } +} + +inline void TestUtil::ReflectionTester::SwapRepeatedsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + + std::vector output; + reflection->ListFields(*message, &output); + for (int i = 0; i < output.size(); ++i) { + const FieldDescriptor* field = output[i]; + if (!field->is_repeated()) continue; + + reflection->SwapElements(message, field, 0, 1); + } +} + +inline void TestUtil::ReflectionTester:: + SetAllocatedOptionalMessageFieldsToNullViaReflection(Message* message) { + const Reflection* reflection = message->GetReflection(); + + std::vector fields; + reflection->ListFields(*message, &fields); + + for (int i = 0; i < fields.size(); ++i) { + const FieldDescriptor* field = fields[i]; + if (!field->is_optional() || + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) + continue; + + reflection->SetAllocatedMessage(message, nullptr, field); + } +} + +inline void TestUtil::ReflectionTester:: + SetAllocatedOptionalMessageFieldsToMessageViaReflection( + Message* from_message, Message* to_message) { + EXPECT_EQ(from_message->GetDescriptor(), to_message->GetDescriptor()); + const Reflection* from_reflection = from_message->GetReflection(); + const Reflection* to_reflection = to_message->GetReflection(); + + std::vector fields; + from_reflection->ListFields(*from_message, &fields); + + for (int i = 0; i < fields.size(); ++i) { + const FieldDescriptor* field = fields[i]; + if (!field->is_optional() || + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) + continue; + + Message* sub_message = from_reflection->ReleaseMessage(from_message, field); + to_reflection->SetAllocatedMessage(to_message, sub_message, field); + } +} + +inline void TestUtil::ReflectionTester::ExpectMessagesReleasedViaReflection( + Message* message, + TestUtil::ReflectionTester::MessageReleaseState expected_release_state) { + const Reflection* reflection = message->GetReflection(); + + static const char* fields[] = { + "optionalgroup", + "optional_nested_message", + "optional_foreign_message", + "optional_import_message", + }; + for (int i = 0; i < GOOGLE_ARRAYSIZE(fields); i++) { + const Message& sub_message = reflection->GetMessage(*message, F(fields[i])); + Message* released = reflection->ReleaseMessage(message, F(fields[i])); + switch (expected_release_state) { + case IS_NULL: + EXPECT_TRUE(released == nullptr); + break; + case NOT_NULL: + EXPECT_TRUE(released != nullptr); + if (message->GetArena() == nullptr) { + // released message must be same as sub_message if source message is + // not on arena. + EXPECT_EQ(&sub_message, released); + } + break; + case CAN_BE_NULL: + break; + } + delete released; + EXPECT_FALSE(reflection->HasField(*message, F(fields[i]))); + } +} + +// Check that the passed-in serialization is the canonical serialization we +// expect for a TestFieldOrderings message filled in by +// SetAllFieldsAndExtensions(). +inline void ExpectAllFieldsAndExtensionsInOrder(const std::string& serialized) { + // We set each field individually, serialize separately, and concatenate all + // the strings in canonical order to determine the expected serialization. + std::string expected; + unittest::TestFieldOrderings message; + message.set_my_int(1); // Field 1. + message.AppendToString(&expected); + message.Clear(); + message.SetExtension(unittest::my_extension_int, 23); // Field 5. + message.AppendToString(&expected); + message.Clear(); + message.set_my_string("foo"); // Field 11. + message.AppendToString(&expected); + message.Clear(); + message.SetExtension(unittest::my_extension_string, "bar"); // Field 50. + message.AppendToString(&expected); + message.Clear(); + message.set_my_float(1.0); // Field 101. + message.AppendToString(&expected); + message.Clear(); + + // We don't EXPECT_EQ() since we don't want to print raw bytes to stdout. + EXPECT_TRUE(serialized == expected); +} + +} // namespace TestUtil +} // namespace protobuf } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_TEST_UTIL_H__ diff --git a/src/google/protobuf/test_util.inc b/src/google/protobuf/test_util.inc new file mode 100644 index 0000000000000..0f1b147ba4625 --- /dev/null +++ b/src/google/protobuf/test_util.inc @@ -0,0 +1,2406 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file needs to be included as .inc as it depends on the namespaces +// (unittest and unittest_import) being set up properly. It is also included +// within an enclosing namespace and requires header files to be included +// out of this file. + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace TestUtil { + +// Set every field in the message to a unique value. +inline void SetAllFields(UNITTEST::TestAllTypes* message); +inline void SetOptionalFields(UNITTEST::TestAllTypes* message); +inline void AddRepeatedFields1(UNITTEST::TestAllTypes* message); +inline void AddRepeatedFields2(UNITTEST::TestAllTypes* message); +inline void SetDefaultFields(UNITTEST::TestAllTypes* message); +inline void SetOneofFields(UNITTEST::TestAllTypes* message); +inline void SetAllExtensions(UNITTEST::TestAllExtensions* message); +inline void SetOneofFields(UNITTEST::TestAllExtensions* message); +inline void SetAllFieldsAndExtensions(UNITTEST::TestFieldOrderings* message); +inline void SetPackedFields(UNITTEST::TestPackedTypes* message); +inline void SetPackedExtensions(UNITTEST::TestPackedExtensions* message); +inline void SetUnpackedFields(UNITTEST::TestUnpackedTypes* message); +inline void SetOneof1(UNITTEST::TestOneof2* message); +inline void SetOneof2(UNITTEST::TestOneof2* message); + +// Use the repeated versions of the set_*() accessors to modify all the +// repeated fields of the message (which should already have been +// initialized with Set*Fields()). Set*Fields() itself only tests +// the add_*() accessors. +inline void ModifyRepeatedFields(UNITTEST::TestAllTypes* message); +inline void ModifyRepeatedExtensions(UNITTEST::TestAllExtensions* message); + +// Check that all fields have the values that they should have after +// Set*Fields() is called. +inline void ExpectAllFieldsSet(const UNITTEST::TestAllTypes& message); +inline void ExpectAllExtensionsSet(const UNITTEST::TestAllExtensions& message); +inline void ExpectPackedFieldsSet(const UNITTEST::TestPackedTypes& message); +inline void ExpectPackedExtensionsSet( + const UNITTEST::TestPackedExtensions& message); +inline void ExpectUnpackedFieldsSet(const UNITTEST::TestUnpackedTypes& message); +inline void ExpectUnpackedExtensionsSet( + const UNITTEST::TestUnpackedExtensions& message); +inline void ExpectOneofSet1(const UNITTEST::TestOneof2& message); +inline void ExpectOneofSet2(const UNITTEST::TestOneof2& message); + +// Expect that the message is modified as would be expected from +// Modify*Fields(). +inline void ExpectRepeatedFieldsModified(const UNITTEST::TestAllTypes& message); +inline void ExpectRepeatedExtensionsModified( + const UNITTEST::TestAllExtensions& message); + +// Check that all fields have their default values. +inline void ExpectClear(const UNITTEST::TestAllTypes& message); +inline void ExpectExtensionsClear(const UNITTEST::TestAllExtensions& message); +inline void ExpectOneofClear(const UNITTEST::TestOneof2& message); + +// Check that all repeated fields have had their last elements removed. +inline void ExpectLastRepeatedsRemoved(const UNITTEST::TestAllTypes& message); +inline void ExpectLastRepeatedExtensionsRemoved( + const UNITTEST::TestAllExtensions& message); +inline void ExpectLastRepeatedsReleased(const UNITTEST::TestAllTypes& message); +inline void ExpectLastRepeatedExtensionsReleased( + const UNITTEST::TestAllExtensions& message); + +// Check that all repeated fields have had their first and last elements +// swapped. +inline void ExpectRepeatedsSwapped(const UNITTEST::TestAllTypes& message); +inline void ExpectRepeatedExtensionsSwapped( + const UNITTEST::TestAllExtensions& message); + +inline void ExpectAtMostOneFieldSetInOneof(const UNITTEST::TestOneof2& message); + +} // namespace TestUtil + +inline void TestUtil::SetAllFields(UNITTEST::TestAllTypes* message) { + SetOptionalFields(message); + AddRepeatedFields1(message); + AddRepeatedFields2(message); + SetDefaultFields(message); + SetOneofFields(message); +} + +inline void TestUtil::SetOptionalFields(UNITTEST::TestAllTypes* message) { + message->set_optional_int32(101); + message->set_optional_int64(102); + message->set_optional_uint32(103); + message->set_optional_uint64(104); + message->set_optional_sint32(105); + message->set_optional_sint64(106); + message->set_optional_fixed32(107); + message->set_optional_fixed64(108); + message->set_optional_sfixed32(109); + message->set_optional_sfixed64(110); + message->set_optional_float(111); + message->set_optional_double(112); + message->set_optional_bool(true); + message->set_optional_string("115"); + message->set_optional_bytes("116"); + + message->mutable_optionalgroup()->set_a(117); + message->mutable_optional_nested_message()->set_bb(118); + message->mutable_optional_foreign_message()->set_c(119); + message->mutable_optional_import_message()->set_d(120); + message->mutable_optional_public_import_message()->set_e(126); + message->mutable_optional_lazy_message()->set_bb(127); + + message->set_optional_nested_enum(UNITTEST::TestAllTypes::BAZ); + message->set_optional_foreign_enum(UNITTEST::FOREIGN_BAZ); + message->set_optional_import_enum(UNITTEST_IMPORT::IMPORT_BAZ); + + // StringPiece and Cord fields are only accessible via reflection in the + // open source release; see comments in compiler/cpp/string_field.cc. +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + message->GetReflection()->SetString( + message, + message->GetDescriptor()->FindFieldByName("optional_string_piece"), + "124"); + message->GetReflection()->SetString( + message, message->GetDescriptor()->FindFieldByName("optional_cord"), + "125"); +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS +} + +// ------------------------------------------------------------------- + +inline void TestUtil::AddRepeatedFields1(UNITTEST::TestAllTypes* message) { + message->add_repeated_int32(201); + message->add_repeated_int64(202); + message->add_repeated_uint32(203); + message->add_repeated_uint64(204); + message->add_repeated_sint32(205); + message->add_repeated_sint64(206); + message->add_repeated_fixed32(207); + message->add_repeated_fixed64(208); + message->add_repeated_sfixed32(209); + message->add_repeated_sfixed64(210); + message->add_repeated_float(211); + message->add_repeated_double(212); + message->add_repeated_bool(true); + message->add_repeated_string("215"); + message->add_repeated_bytes("216"); + + message->add_repeatedgroup()->set_a(217); + message->add_repeated_nested_message()->set_bb(218); + message->add_repeated_foreign_message()->set_c(219); + message->add_repeated_import_message()->set_d(220); + message->add_repeated_lazy_message()->set_bb(227); + + message->add_repeated_nested_enum(UNITTEST::TestAllTypes::BAR); + message->add_repeated_foreign_enum(UNITTEST::FOREIGN_BAR); + message->add_repeated_import_enum(UNITTEST_IMPORT::IMPORT_BAR); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + message->GetReflection()->AddString( + message, + message->GetDescriptor()->FindFieldByName("repeated_string_piece"), + "224"); + message->GetReflection()->AddString( + message, message->GetDescriptor()->FindFieldByName("repeated_cord"), + "225"); +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS +} + +inline void TestUtil::AddRepeatedFields2(UNITTEST::TestAllTypes* message) { + // Add a second one of each field. + message->add_repeated_int32(301); + message->add_repeated_int64(302); + message->add_repeated_uint32(303); + message->add_repeated_uint64(304); + message->add_repeated_sint32(305); + message->add_repeated_sint64(306); + message->add_repeated_fixed32(307); + message->add_repeated_fixed64(308); + message->add_repeated_sfixed32(309); + message->add_repeated_sfixed64(310); + message->add_repeated_float(311); + message->add_repeated_double(312); + message->add_repeated_bool(false); + message->add_repeated_string("315"); + message->add_repeated_bytes("316"); + + message->add_repeatedgroup()->set_a(317); + message->add_repeated_nested_message()->set_bb(318); + message->add_repeated_foreign_message()->set_c(319); + message->add_repeated_import_message()->set_d(320); + message->add_repeated_lazy_message()->set_bb(327); + + message->add_repeated_nested_enum(UNITTEST::TestAllTypes::BAZ); + message->add_repeated_foreign_enum(UNITTEST::FOREIGN_BAZ); + message->add_repeated_import_enum(UNITTEST_IMPORT::IMPORT_BAZ); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + message->GetReflection()->AddString( + message, + message->GetDescriptor()->FindFieldByName("repeated_string_piece"), + "324"); + message->GetReflection()->AddString( + message, message->GetDescriptor()->FindFieldByName("repeated_cord"), + "325"); +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS +} + +// ------------------------------------------------------------------- + +inline void TestUtil::SetDefaultFields(UNITTEST::TestAllTypes* message) { + message->set_default_int32(401); + message->set_default_int64(402); + message->set_default_uint32(403); + message->set_default_uint64(404); + message->set_default_sint32(405); + message->set_default_sint64(406); + message->set_default_fixed32(407); + message->set_default_fixed64(408); + message->set_default_sfixed32(409); + message->set_default_sfixed64(410); + message->set_default_float(411); + message->set_default_double(412); + message->set_default_bool(false); + message->set_default_string("415"); + message->set_default_bytes("416"); + + message->set_default_nested_enum(UNITTEST::TestAllTypes::FOO); + message->set_default_foreign_enum(UNITTEST::FOREIGN_FOO); + message->set_default_import_enum(UNITTEST_IMPORT::IMPORT_FOO); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + message->GetReflection()->SetString( + message, + message->GetDescriptor()->FindFieldByName("default_string_piece"), "424"); + message->GetReflection()->SetString( + message, message->GetDescriptor()->FindFieldByName("default_cord"), + "425"); +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ModifyRepeatedFields(UNITTEST::TestAllTypes* message) { + message->set_repeated_int32(1, 501); + message->set_repeated_int64(1, 502); + message->set_repeated_uint32(1, 503); + message->set_repeated_uint64(1, 504); + message->set_repeated_sint32(1, 505); + message->set_repeated_sint64(1, 506); + message->set_repeated_fixed32(1, 507); + message->set_repeated_fixed64(1, 508); + message->set_repeated_sfixed32(1, 509); + message->set_repeated_sfixed64(1, 510); + message->set_repeated_float(1, 511); + message->set_repeated_double(1, 512); + message->set_repeated_bool(1, true); + message->set_repeated_string(1, "515"); + message->set_repeated_bytes(1, "516"); + + message->mutable_repeatedgroup(1)->set_a(517); + message->mutable_repeated_nested_message(1)->set_bb(518); + message->mutable_repeated_foreign_message(1)->set_c(519); + message->mutable_repeated_import_message(1)->set_d(520); + message->mutable_repeated_lazy_message(1)->set_bb(527); + + message->set_repeated_nested_enum(1, UNITTEST::TestAllTypes::FOO); + message->set_repeated_foreign_enum(1, UNITTEST::FOREIGN_FOO); + message->set_repeated_import_enum(1, UNITTEST_IMPORT::IMPORT_FOO); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + message->GetReflection()->SetRepeatedString( + message, + message->GetDescriptor()->FindFieldByName("repeated_string_piece"), 1, + "524"); + message->GetReflection()->SetRepeatedString( + message, message->GetDescriptor()->FindFieldByName("repeated_cord"), 1, + "525"); +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS +} + +// ------------------------------------------------------------------ +inline void TestUtil::SetOneofFields(UNITTEST::TestAllTypes* message) { + message->set_oneof_uint32(601); + message->mutable_oneof_nested_message()->set_bb(602); + message->set_oneof_string("603"); + message->set_oneof_bytes("604"); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectAllFieldsSet( + const UNITTEST::TestAllTypes& message) { + EXPECT_TRUE(message.has_optional_int32()); + EXPECT_TRUE(message.has_optional_int64()); + EXPECT_TRUE(message.has_optional_uint32()); + EXPECT_TRUE(message.has_optional_uint64()); + EXPECT_TRUE(message.has_optional_sint32()); + EXPECT_TRUE(message.has_optional_sint64()); + EXPECT_TRUE(message.has_optional_fixed32()); + EXPECT_TRUE(message.has_optional_fixed64()); + EXPECT_TRUE(message.has_optional_sfixed32()); + EXPECT_TRUE(message.has_optional_sfixed64()); + EXPECT_TRUE(message.has_optional_float()); + EXPECT_TRUE(message.has_optional_double()); + EXPECT_TRUE(message.has_optional_bool()); + EXPECT_TRUE(message.has_optional_string()); + EXPECT_TRUE(message.has_optional_bytes()); + + EXPECT_TRUE(message.has_optionalgroup()); + EXPECT_TRUE(message.has_optional_nested_message()); + EXPECT_TRUE(message.has_optional_foreign_message()); + EXPECT_TRUE(message.has_optional_import_message()); + EXPECT_TRUE(message.has_optional_public_import_message()); + EXPECT_TRUE(message.has_optional_lazy_message()); + + EXPECT_TRUE(message.optionalgroup().has_a()); + EXPECT_TRUE(message.optional_nested_message().has_bb()); + EXPECT_TRUE(message.optional_foreign_message().has_c()); + EXPECT_TRUE(message.optional_import_message().has_d()); + EXPECT_TRUE(message.optional_public_import_message().has_e()); + EXPECT_TRUE(message.optional_lazy_message().has_bb()); + + EXPECT_TRUE(message.has_optional_nested_enum()); + EXPECT_TRUE(message.has_optional_foreign_enum()); + EXPECT_TRUE(message.has_optional_import_enum()); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + EXPECT_TRUE(message.has_optional_string_piece()); + EXPECT_TRUE(message.has_optional_cord()); +#endif + + EXPECT_EQ(101, message.optional_int32()); + EXPECT_EQ(102, message.optional_int64()); + EXPECT_EQ(103, message.optional_uint32()); + EXPECT_EQ(104, message.optional_uint64()); + EXPECT_EQ(105, message.optional_sint32()); + EXPECT_EQ(106, message.optional_sint64()); + EXPECT_EQ(107, message.optional_fixed32()); + EXPECT_EQ(108, message.optional_fixed64()); + EXPECT_EQ(109, message.optional_sfixed32()); + EXPECT_EQ(110, message.optional_sfixed64()); + EXPECT_EQ(111, message.optional_float()); + EXPECT_EQ(112, message.optional_double()); + EXPECT_TRUE(message.optional_bool()); + EXPECT_EQ("115", message.optional_string()); + EXPECT_EQ("116", message.optional_bytes()); + + EXPECT_EQ(117, message.optionalgroup().a()); + EXPECT_EQ(118, message.optional_nested_message().bb()); + EXPECT_EQ(119, message.optional_foreign_message().c()); + EXPECT_EQ(120, message.optional_import_message().d()); + EXPECT_EQ(126, message.optional_public_import_message().e()); + EXPECT_EQ(127, message.optional_lazy_message().bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, message.optional_nested_enum()); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, message.optional_foreign_enum()); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAZ, message.optional_import_enum()); + + + // ----------------------------------------------------------------- + + ASSERT_EQ(2, message.repeated_int32_size()); + ASSERT_EQ(2, message.repeated_int64_size()); + ASSERT_EQ(2, message.repeated_uint32_size()); + ASSERT_EQ(2, message.repeated_uint64_size()); + ASSERT_EQ(2, message.repeated_sint32_size()); + ASSERT_EQ(2, message.repeated_sint64_size()); + ASSERT_EQ(2, message.repeated_fixed32_size()); + ASSERT_EQ(2, message.repeated_fixed64_size()); + ASSERT_EQ(2, message.repeated_sfixed32_size()); + ASSERT_EQ(2, message.repeated_sfixed64_size()); + ASSERT_EQ(2, message.repeated_float_size()); + ASSERT_EQ(2, message.repeated_double_size()); + ASSERT_EQ(2, message.repeated_bool_size()); + ASSERT_EQ(2, message.repeated_string_size()); + ASSERT_EQ(2, message.repeated_bytes_size()); + + ASSERT_EQ(2, message.repeatedgroup_size()); + ASSERT_EQ(2, message.repeated_nested_message_size()); + ASSERT_EQ(2, message.repeated_foreign_message_size()); + ASSERT_EQ(2, message.repeated_import_message_size()); + ASSERT_EQ(2, message.repeated_lazy_message_size()); + ASSERT_EQ(2, message.repeated_nested_enum_size()); + ASSERT_EQ(2, message.repeated_foreign_enum_size()); + ASSERT_EQ(2, message.repeated_import_enum_size()); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + ASSERT_EQ(2, message.repeated_string_piece_size()); + ASSERT_EQ(2, message.repeated_cord_size()); +#endif + + EXPECT_EQ(201, message.repeated_int32(0)); + EXPECT_EQ(202, message.repeated_int64(0)); + EXPECT_EQ(203, message.repeated_uint32(0)); + EXPECT_EQ(204, message.repeated_uint64(0)); + EXPECT_EQ(205, message.repeated_sint32(0)); + EXPECT_EQ(206, message.repeated_sint64(0)); + EXPECT_EQ(207, message.repeated_fixed32(0)); + EXPECT_EQ(208, message.repeated_fixed64(0)); + EXPECT_EQ(209, message.repeated_sfixed32(0)); + EXPECT_EQ(210, message.repeated_sfixed64(0)); + EXPECT_EQ(211, message.repeated_float(0)); + EXPECT_EQ(212, message.repeated_double(0)); + EXPECT_TRUE(message.repeated_bool(0)); + EXPECT_EQ("215", message.repeated_string(0)); + EXPECT_EQ("216", message.repeated_bytes(0)); + + EXPECT_EQ(217, message.repeatedgroup(0).a()); + EXPECT_EQ(218, message.repeated_nested_message(0).bb()); + EXPECT_EQ(219, message.repeated_foreign_message(0).c()); + EXPECT_EQ(220, message.repeated_import_message(0).d()); + EXPECT_EQ(227, message.repeated_lazy_message(0).bb()); + + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message.repeated_nested_enum(0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.repeated_foreign_enum(0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, message.repeated_import_enum(0)); + + EXPECT_EQ(301, message.repeated_int32(1)); + EXPECT_EQ(302, message.repeated_int64(1)); + EXPECT_EQ(303, message.repeated_uint32(1)); + EXPECT_EQ(304, message.repeated_uint64(1)); + EXPECT_EQ(305, message.repeated_sint32(1)); + EXPECT_EQ(306, message.repeated_sint64(1)); + EXPECT_EQ(307, message.repeated_fixed32(1)); + EXPECT_EQ(308, message.repeated_fixed64(1)); + EXPECT_EQ(309, message.repeated_sfixed32(1)); + EXPECT_EQ(310, message.repeated_sfixed64(1)); + EXPECT_EQ(311, message.repeated_float(1)); + EXPECT_EQ(312, message.repeated_double(1)); + EXPECT_FALSE(message.repeated_bool(1)); + EXPECT_EQ("315", message.repeated_string(1)); + EXPECT_EQ("316", message.repeated_bytes(1)); + + EXPECT_EQ(317, message.repeatedgroup(1).a()); + EXPECT_EQ(318, message.repeated_nested_message(1).bb()); + EXPECT_EQ(319, message.repeated_foreign_message(1).c()); + EXPECT_EQ(320, message.repeated_import_message(1).d()); + EXPECT_EQ(327, message.repeated_lazy_message(1).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, message.repeated_nested_enum(1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, message.repeated_foreign_enum(1)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAZ, message.repeated_import_enum(1)); + + + // ----------------------------------------------------------------- + + EXPECT_TRUE(message.has_default_int32()); + EXPECT_TRUE(message.has_default_int64()); + EXPECT_TRUE(message.has_default_uint32()); + EXPECT_TRUE(message.has_default_uint64()); + EXPECT_TRUE(message.has_default_sint32()); + EXPECT_TRUE(message.has_default_sint64()); + EXPECT_TRUE(message.has_default_fixed32()); + EXPECT_TRUE(message.has_default_fixed64()); + EXPECT_TRUE(message.has_default_sfixed32()); + EXPECT_TRUE(message.has_default_sfixed64()); + EXPECT_TRUE(message.has_default_float()); + EXPECT_TRUE(message.has_default_double()); + EXPECT_TRUE(message.has_default_bool()); + EXPECT_TRUE(message.has_default_string()); + EXPECT_TRUE(message.has_default_bytes()); + + EXPECT_TRUE(message.has_default_nested_enum()); + EXPECT_TRUE(message.has_default_foreign_enum()); + EXPECT_TRUE(message.has_default_import_enum()); + + + EXPECT_EQ(401, message.default_int32()); + EXPECT_EQ(402, message.default_int64()); + EXPECT_EQ(403, message.default_uint32()); + EXPECT_EQ(404, message.default_uint64()); + EXPECT_EQ(405, message.default_sint32()); + EXPECT_EQ(406, message.default_sint64()); + EXPECT_EQ(407, message.default_fixed32()); + EXPECT_EQ(408, message.default_fixed64()); + EXPECT_EQ(409, message.default_sfixed32()); + EXPECT_EQ(410, message.default_sfixed64()); + EXPECT_EQ(411, message.default_float()); + EXPECT_EQ(412, message.default_double()); + EXPECT_FALSE(message.default_bool()); + EXPECT_EQ("415", message.default_string()); + EXPECT_EQ("416", message.default_bytes()); + + EXPECT_EQ(UNITTEST::TestAllTypes::FOO, message.default_nested_enum()); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, message.default_foreign_enum()); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_FOO, message.default_import_enum()); + + + EXPECT_FALSE(message.has_oneof_uint32()); + EXPECT_FALSE(message.has_oneof_nested_message()); + EXPECT_FALSE(message.has_oneof_string()); + EXPECT_TRUE(message.has_oneof_bytes()); + + EXPECT_EQ("604", message.oneof_bytes()); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectClear(const UNITTEST::TestAllTypes& message) { + // has_blah() should initially be false for all optional fields. + EXPECT_FALSE(message.has_optional_int32()); + EXPECT_FALSE(message.has_optional_int64()); + EXPECT_FALSE(message.has_optional_uint32()); + EXPECT_FALSE(message.has_optional_uint64()); + EXPECT_FALSE(message.has_optional_sint32()); + EXPECT_FALSE(message.has_optional_sint64()); + EXPECT_FALSE(message.has_optional_fixed32()); + EXPECT_FALSE(message.has_optional_fixed64()); + EXPECT_FALSE(message.has_optional_sfixed32()); + EXPECT_FALSE(message.has_optional_sfixed64()); + EXPECT_FALSE(message.has_optional_float()); + EXPECT_FALSE(message.has_optional_double()); + EXPECT_FALSE(message.has_optional_bool()); + EXPECT_FALSE(message.has_optional_string()); + EXPECT_FALSE(message.has_optional_bytes()); + + EXPECT_FALSE(message.has_optionalgroup()); + EXPECT_FALSE(message.has_optional_nested_message()); + EXPECT_FALSE(message.has_optional_foreign_message()); + EXPECT_FALSE(message.has_optional_import_message()); + EXPECT_FALSE(message.has_optional_public_import_message()); + EXPECT_FALSE(message.has_optional_lazy_message()); + + EXPECT_FALSE(message.has_optional_nested_enum()); + EXPECT_FALSE(message.has_optional_foreign_enum()); + EXPECT_FALSE(message.has_optional_import_enum()); + + EXPECT_FALSE(message.has_optional_string_piece()); + EXPECT_FALSE(message.has_optional_cord()); + + // Optional fields without defaults are set to zero or something like it. + EXPECT_EQ(0, message.optional_int32()); + EXPECT_EQ(0, message.optional_int64()); + EXPECT_EQ(0, message.optional_uint32()); + EXPECT_EQ(0, message.optional_uint64()); + EXPECT_EQ(0, message.optional_sint32()); + EXPECT_EQ(0, message.optional_sint64()); + EXPECT_EQ(0, message.optional_fixed32()); + EXPECT_EQ(0, message.optional_fixed64()); + EXPECT_EQ(0, message.optional_sfixed32()); + EXPECT_EQ(0, message.optional_sfixed64()); + EXPECT_EQ(0, message.optional_float()); + EXPECT_EQ(0, message.optional_double()); + EXPECT_FALSE(message.optional_bool()); + EXPECT_EQ("", message.optional_string()); + EXPECT_EQ("", message.optional_bytes()); + + // Embedded messages should also be clear. + EXPECT_FALSE(message.optionalgroup().has_a()); + EXPECT_FALSE(message.optional_nested_message().has_bb()); + EXPECT_FALSE(message.optional_foreign_message().has_c()); + EXPECT_FALSE(message.optional_import_message().has_d()); + EXPECT_FALSE(message.optional_public_import_message().has_e()); + EXPECT_FALSE(message.optional_lazy_message().has_bb()); + + EXPECT_EQ(0, message.optionalgroup().a()); + EXPECT_EQ(0, message.optional_nested_message().bb()); + EXPECT_EQ(0, message.optional_foreign_message().c()); + EXPECT_EQ(0, message.optional_import_message().d()); + EXPECT_EQ(0, message.optional_public_import_message().e()); + EXPECT_EQ(0, message.optional_lazy_message().bb()); + + // Enums without defaults are set to the first value in the enum. + EXPECT_EQ(UNITTEST::TestAllTypes::FOO, message.optional_nested_enum()); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, message.optional_foreign_enum()); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_FOO, message.optional_import_enum()); + + + // Repeated fields are empty. + EXPECT_EQ(0, message.repeated_int32_size()); + EXPECT_EQ(0, message.repeated_int64_size()); + EXPECT_EQ(0, message.repeated_uint32_size()); + EXPECT_EQ(0, message.repeated_uint64_size()); + EXPECT_EQ(0, message.repeated_sint32_size()); + EXPECT_EQ(0, message.repeated_sint64_size()); + EXPECT_EQ(0, message.repeated_fixed32_size()); + EXPECT_EQ(0, message.repeated_fixed64_size()); + EXPECT_EQ(0, message.repeated_sfixed32_size()); + EXPECT_EQ(0, message.repeated_sfixed64_size()); + EXPECT_EQ(0, message.repeated_float_size()); + EXPECT_EQ(0, message.repeated_double_size()); + EXPECT_EQ(0, message.repeated_bool_size()); + EXPECT_EQ(0, message.repeated_string_size()); + EXPECT_EQ(0, message.repeated_bytes_size()); + + EXPECT_EQ(0, message.repeatedgroup_size()); + EXPECT_EQ(0, message.repeated_nested_message_size()); + EXPECT_EQ(0, message.repeated_foreign_message_size()); + EXPECT_EQ(0, message.repeated_import_message_size()); + EXPECT_EQ(0, message.repeated_lazy_message_size()); + EXPECT_EQ(0, message.repeated_nested_enum_size()); + EXPECT_EQ(0, message.repeated_foreign_enum_size()); + EXPECT_EQ(0, message.repeated_import_enum_size()); + + EXPECT_EQ(0, message.repeated_string_piece_size()); + EXPECT_EQ(0, message.repeated_cord_size()); + + // has_blah() should also be false for all default fields. + EXPECT_FALSE(message.has_default_int32()); + EXPECT_FALSE(message.has_default_int64()); + EXPECT_FALSE(message.has_default_uint32()); + EXPECT_FALSE(message.has_default_uint64()); + EXPECT_FALSE(message.has_default_sint32()); + EXPECT_FALSE(message.has_default_sint64()); + EXPECT_FALSE(message.has_default_fixed32()); + EXPECT_FALSE(message.has_default_fixed64()); + EXPECT_FALSE(message.has_default_sfixed32()); + EXPECT_FALSE(message.has_default_sfixed64()); + EXPECT_FALSE(message.has_default_float()); + EXPECT_FALSE(message.has_default_double()); + EXPECT_FALSE(message.has_default_bool()); + EXPECT_FALSE(message.has_default_string()); + EXPECT_FALSE(message.has_default_bytes()); + + EXPECT_FALSE(message.has_default_nested_enum()); + EXPECT_FALSE(message.has_default_foreign_enum()); + EXPECT_FALSE(message.has_default_import_enum()); + + + // Fields with defaults have their default values (duh). + EXPECT_EQ(41, message.default_int32()); + EXPECT_EQ(42, message.default_int64()); + EXPECT_EQ(43, message.default_uint32()); + EXPECT_EQ(44, message.default_uint64()); + EXPECT_EQ(-45, message.default_sint32()); + EXPECT_EQ(46, message.default_sint64()); + EXPECT_EQ(47, message.default_fixed32()); + EXPECT_EQ(48, message.default_fixed64()); + EXPECT_EQ(49, message.default_sfixed32()); + EXPECT_EQ(-50, message.default_sfixed64()); + EXPECT_EQ(51.5, message.default_float()); + EXPECT_EQ(52e3, message.default_double()); + EXPECT_TRUE(message.default_bool()); + EXPECT_EQ("hello", message.default_string()); + EXPECT_EQ("world", message.default_bytes()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message.default_nested_enum()); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.default_foreign_enum()); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, message.default_import_enum()); + + + EXPECT_FALSE(message.has_oneof_uint32()); + EXPECT_FALSE(message.has_oneof_nested_message()); + EXPECT_FALSE(message.has_oneof_string()); + EXPECT_FALSE(message.has_oneof_bytes()); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectRepeatedFieldsModified( + const UNITTEST::TestAllTypes& message) { + // ModifyRepeatedFields only sets the second repeated element of each + // field. In addition to verifying this, we also verify that the first + // element and size were *not* modified. + ASSERT_EQ(2, message.repeated_int32_size()); + ASSERT_EQ(2, message.repeated_int64_size()); + ASSERT_EQ(2, message.repeated_uint32_size()); + ASSERT_EQ(2, message.repeated_uint64_size()); + ASSERT_EQ(2, message.repeated_sint32_size()); + ASSERT_EQ(2, message.repeated_sint64_size()); + ASSERT_EQ(2, message.repeated_fixed32_size()); + ASSERT_EQ(2, message.repeated_fixed64_size()); + ASSERT_EQ(2, message.repeated_sfixed32_size()); + ASSERT_EQ(2, message.repeated_sfixed64_size()); + ASSERT_EQ(2, message.repeated_float_size()); + ASSERT_EQ(2, message.repeated_double_size()); + ASSERT_EQ(2, message.repeated_bool_size()); + ASSERT_EQ(2, message.repeated_string_size()); + ASSERT_EQ(2, message.repeated_bytes_size()); + + ASSERT_EQ(2, message.repeatedgroup_size()); + ASSERT_EQ(2, message.repeated_nested_message_size()); + ASSERT_EQ(2, message.repeated_foreign_message_size()); + ASSERT_EQ(2, message.repeated_import_message_size()); + ASSERT_EQ(2, message.repeated_lazy_message_size()); + ASSERT_EQ(2, message.repeated_nested_enum_size()); + ASSERT_EQ(2, message.repeated_foreign_enum_size()); + ASSERT_EQ(2, message.repeated_import_enum_size()); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + ASSERT_EQ(2, message.repeated_string_piece_size()); + ASSERT_EQ(2, message.repeated_cord_size()); +#endif + + EXPECT_EQ(201, message.repeated_int32(0)); + EXPECT_EQ(202, message.repeated_int64(0)); + EXPECT_EQ(203, message.repeated_uint32(0)); + EXPECT_EQ(204, message.repeated_uint64(0)); + EXPECT_EQ(205, message.repeated_sint32(0)); + EXPECT_EQ(206, message.repeated_sint64(0)); + EXPECT_EQ(207, message.repeated_fixed32(0)); + EXPECT_EQ(208, message.repeated_fixed64(0)); + EXPECT_EQ(209, message.repeated_sfixed32(0)); + EXPECT_EQ(210, message.repeated_sfixed64(0)); + EXPECT_EQ(211, message.repeated_float(0)); + EXPECT_EQ(212, message.repeated_double(0)); + EXPECT_TRUE(message.repeated_bool(0)); + EXPECT_EQ("215", message.repeated_string(0)); + EXPECT_EQ("216", message.repeated_bytes(0)); + + EXPECT_EQ(217, message.repeatedgroup(0).a()); + EXPECT_EQ(218, message.repeated_nested_message(0).bb()); + EXPECT_EQ(219, message.repeated_foreign_message(0).c()); + EXPECT_EQ(220, message.repeated_import_message(0).d()); + EXPECT_EQ(227, message.repeated_lazy_message(0).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message.repeated_nested_enum(0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.repeated_foreign_enum(0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, message.repeated_import_enum(0)); + + + // Actually verify the second (modified) elements now. + EXPECT_EQ(501, message.repeated_int32(1)); + EXPECT_EQ(502, message.repeated_int64(1)); + EXPECT_EQ(503, message.repeated_uint32(1)); + EXPECT_EQ(504, message.repeated_uint64(1)); + EXPECT_EQ(505, message.repeated_sint32(1)); + EXPECT_EQ(506, message.repeated_sint64(1)); + EXPECT_EQ(507, message.repeated_fixed32(1)); + EXPECT_EQ(508, message.repeated_fixed64(1)); + EXPECT_EQ(509, message.repeated_sfixed32(1)); + EXPECT_EQ(510, message.repeated_sfixed64(1)); + EXPECT_EQ(511, message.repeated_float(1)); + EXPECT_EQ(512, message.repeated_double(1)); + EXPECT_TRUE(message.repeated_bool(1)); + EXPECT_EQ("515", message.repeated_string(1)); + EXPECT_EQ("516", message.repeated_bytes(1)); + + EXPECT_EQ(517, message.repeatedgroup(1).a()); + EXPECT_EQ(518, message.repeated_nested_message(1).bb()); + EXPECT_EQ(519, message.repeated_foreign_message(1).c()); + EXPECT_EQ(520, message.repeated_import_message(1).d()); + EXPECT_EQ(527, message.repeated_lazy_message(1).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::FOO, message.repeated_nested_enum(1)); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, message.repeated_foreign_enum(1)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_FOO, message.repeated_import_enum(1)); + +} + +// ------------------------------------------------------------------- + +inline void TestUtil::SetPackedFields(UNITTEST::TestPackedTypes* message) { + message->add_packed_int32(601); + message->add_packed_int64(602); + message->add_packed_uint32(603); + message->add_packed_uint64(604); + message->add_packed_sint32(605); + message->add_packed_sint64(606); + message->add_packed_fixed32(607); + message->add_packed_fixed64(608); + message->add_packed_sfixed32(609); + message->add_packed_sfixed64(610); + message->add_packed_float(611); + message->add_packed_double(612); + message->add_packed_bool(true); + message->add_packed_enum(UNITTEST::FOREIGN_BAR); + // add a second one of each field + message->add_packed_int32(701); + message->add_packed_int64(702); + message->add_packed_uint32(703); + message->add_packed_uint64(704); + message->add_packed_sint32(705); + message->add_packed_sint64(706); + message->add_packed_fixed32(707); + message->add_packed_fixed64(708); + message->add_packed_sfixed32(709); + message->add_packed_sfixed64(710); + message->add_packed_float(711); + message->add_packed_double(712); + message->add_packed_bool(false); + message->add_packed_enum(UNITTEST::FOREIGN_BAZ); +} + +inline void TestUtil::SetUnpackedFields(UNITTEST::TestUnpackedTypes* message) { + // The values applied here must match those of SetPackedFields. + + message->add_unpacked_int32(601); + message->add_unpacked_int64(602); + message->add_unpacked_uint32(603); + message->add_unpacked_uint64(604); + message->add_unpacked_sint32(605); + message->add_unpacked_sint64(606); + message->add_unpacked_fixed32(607); + message->add_unpacked_fixed64(608); + message->add_unpacked_sfixed32(609); + message->add_unpacked_sfixed64(610); + message->add_unpacked_float(611); + message->add_unpacked_double(612); + message->add_unpacked_bool(true); + message->add_unpacked_enum(UNITTEST::FOREIGN_BAR); + // add a second one of each field + message->add_unpacked_int32(701); + message->add_unpacked_int64(702); + message->add_unpacked_uint32(703); + message->add_unpacked_uint64(704); + message->add_unpacked_sint32(705); + message->add_unpacked_sint64(706); + message->add_unpacked_fixed32(707); + message->add_unpacked_fixed64(708); + message->add_unpacked_sfixed32(709); + message->add_unpacked_sfixed64(710); + message->add_unpacked_float(711); + message->add_unpacked_double(712); + message->add_unpacked_bool(false); + message->add_unpacked_enum(UNITTEST::FOREIGN_BAZ); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectPackedFieldsSet( + const UNITTEST::TestPackedTypes& message) { + ASSERT_EQ(2, message.packed_int32_size()); + ASSERT_EQ(2, message.packed_int64_size()); + ASSERT_EQ(2, message.packed_uint32_size()); + ASSERT_EQ(2, message.packed_uint64_size()); + ASSERT_EQ(2, message.packed_sint32_size()); + ASSERT_EQ(2, message.packed_sint64_size()); + ASSERT_EQ(2, message.packed_fixed32_size()); + ASSERT_EQ(2, message.packed_fixed64_size()); + ASSERT_EQ(2, message.packed_sfixed32_size()); + ASSERT_EQ(2, message.packed_sfixed64_size()); + ASSERT_EQ(2, message.packed_float_size()); + ASSERT_EQ(2, message.packed_double_size()); + ASSERT_EQ(2, message.packed_bool_size()); + ASSERT_EQ(2, message.packed_enum_size()); + + EXPECT_EQ(601, message.packed_int32(0)); + EXPECT_EQ(602, message.packed_int64(0)); + EXPECT_EQ(603, message.packed_uint32(0)); + EXPECT_EQ(604, message.packed_uint64(0)); + EXPECT_EQ(605, message.packed_sint32(0)); + EXPECT_EQ(606, message.packed_sint64(0)); + EXPECT_EQ(607, message.packed_fixed32(0)); + EXPECT_EQ(608, message.packed_fixed64(0)); + EXPECT_EQ(609, message.packed_sfixed32(0)); + EXPECT_EQ(610, message.packed_sfixed64(0)); + EXPECT_EQ(611, message.packed_float(0)); + EXPECT_EQ(612, message.packed_double(0)); + EXPECT_TRUE(message.packed_bool(0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.packed_enum(0)); + + EXPECT_EQ(701, message.packed_int32(1)); + EXPECT_EQ(702, message.packed_int64(1)); + EXPECT_EQ(703, message.packed_uint32(1)); + EXPECT_EQ(704, message.packed_uint64(1)); + EXPECT_EQ(705, message.packed_sint32(1)); + EXPECT_EQ(706, message.packed_sint64(1)); + EXPECT_EQ(707, message.packed_fixed32(1)); + EXPECT_EQ(708, message.packed_fixed64(1)); + EXPECT_EQ(709, message.packed_sfixed32(1)); + EXPECT_EQ(710, message.packed_sfixed64(1)); + EXPECT_EQ(711, message.packed_float(1)); + EXPECT_EQ(712, message.packed_double(1)); + EXPECT_FALSE(message.packed_bool(1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, message.packed_enum(1)); +} + +inline void TestUtil::ExpectUnpackedFieldsSet( + const UNITTEST::TestUnpackedTypes& message) { + // The values expected here must match those of ExpectPackedFieldsSet. + + ASSERT_EQ(2, message.unpacked_int32_size()); + ASSERT_EQ(2, message.unpacked_int64_size()); + ASSERT_EQ(2, message.unpacked_uint32_size()); + ASSERT_EQ(2, message.unpacked_uint64_size()); + ASSERT_EQ(2, message.unpacked_sint32_size()); + ASSERT_EQ(2, message.unpacked_sint64_size()); + ASSERT_EQ(2, message.unpacked_fixed32_size()); + ASSERT_EQ(2, message.unpacked_fixed64_size()); + ASSERT_EQ(2, message.unpacked_sfixed32_size()); + ASSERT_EQ(2, message.unpacked_sfixed64_size()); + ASSERT_EQ(2, message.unpacked_float_size()); + ASSERT_EQ(2, message.unpacked_double_size()); + ASSERT_EQ(2, message.unpacked_bool_size()); + ASSERT_EQ(2, message.unpacked_enum_size()); + + EXPECT_EQ(601, message.unpacked_int32(0)); + EXPECT_EQ(602, message.unpacked_int64(0)); + EXPECT_EQ(603, message.unpacked_uint32(0)); + EXPECT_EQ(604, message.unpacked_uint64(0)); + EXPECT_EQ(605, message.unpacked_sint32(0)); + EXPECT_EQ(606, message.unpacked_sint64(0)); + EXPECT_EQ(607, message.unpacked_fixed32(0)); + EXPECT_EQ(608, message.unpacked_fixed64(0)); + EXPECT_EQ(609, message.unpacked_sfixed32(0)); + EXPECT_EQ(610, message.unpacked_sfixed64(0)); + EXPECT_EQ(611, message.unpacked_float(0)); + EXPECT_EQ(612, message.unpacked_double(0)); + EXPECT_TRUE(message.unpacked_bool(0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.unpacked_enum(0)); + + EXPECT_EQ(701, message.unpacked_int32(1)); + EXPECT_EQ(702, message.unpacked_int64(1)); + EXPECT_EQ(703, message.unpacked_uint32(1)); + EXPECT_EQ(704, message.unpacked_uint64(1)); + EXPECT_EQ(705, message.unpacked_sint32(1)); + EXPECT_EQ(706, message.unpacked_sint64(1)); + EXPECT_EQ(707, message.unpacked_fixed32(1)); + EXPECT_EQ(708, message.unpacked_fixed64(1)); + EXPECT_EQ(709, message.unpacked_sfixed32(1)); + EXPECT_EQ(710, message.unpacked_sfixed64(1)); + EXPECT_EQ(711, message.unpacked_float(1)); + EXPECT_EQ(712, message.unpacked_double(1)); + EXPECT_FALSE(message.unpacked_bool(1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, message.unpacked_enum(1)); +} + +// =================================================================== +// Extensions +// +// All this code is exactly equivalent to the above code except that it's +// manipulating extension fields instead of normal ones. + +inline void TestUtil::SetAllExtensions(UNITTEST::TestAllExtensions* message) { + message->SetExtension(UNITTEST::optional_int32_extension, 101); + message->SetExtension(UNITTEST::optional_int64_extension, 102); + message->SetExtension(UNITTEST::optional_uint32_extension, 103); + message->SetExtension(UNITTEST::optional_uint64_extension, 104); + message->SetExtension(UNITTEST::optional_sint32_extension, 105); + message->SetExtension(UNITTEST::optional_sint64_extension, 106); + message->SetExtension(UNITTEST::optional_fixed32_extension, 107); + message->SetExtension(UNITTEST::optional_fixed64_extension, 108); + message->SetExtension(UNITTEST::optional_sfixed32_extension, 109); + message->SetExtension(UNITTEST::optional_sfixed64_extension, 110); + message->SetExtension(UNITTEST::optional_float_extension, 111); + message->SetExtension(UNITTEST::optional_double_extension, 112); + message->SetExtension(UNITTEST::optional_bool_extension, true); + message->SetExtension(UNITTEST::optional_string_extension, "115"); + message->SetExtension(UNITTEST::optional_bytes_extension, "116"); + + message->MutableExtension(UNITTEST::optionalgroup_extension)->set_a(117); + message->MutableExtension(UNITTEST::optional_nested_message_extension) + ->set_bb(118); + message->MutableExtension(UNITTEST::optional_foreign_message_extension) + ->set_c(119); + message->MutableExtension(UNITTEST::optional_import_message_extension) + ->set_d(120); + + message->SetExtension(UNITTEST::optional_nested_enum_extension, + UNITTEST::TestAllTypes::BAZ); + message->SetExtension(UNITTEST::optional_foreign_enum_extension, + UNITTEST::FOREIGN_BAZ); + message->SetExtension(UNITTEST::optional_import_enum_extension, + UNITTEST_IMPORT::IMPORT_BAZ); + + message->SetExtension(UNITTEST::optional_string_piece_extension, "124"); + message->SetExtension(UNITTEST::optional_cord_extension, "125"); + + message->MutableExtension(UNITTEST::optional_public_import_message_extension) + ->set_e(126); + message->MutableExtension(UNITTEST::optional_lazy_message_extension) + ->set_bb(127); + + // ----------------------------------------------------------------- + + message->AddExtension(UNITTEST::repeated_int32_extension, 201); + message->AddExtension(UNITTEST::repeated_int64_extension, 202); + message->AddExtension(UNITTEST::repeated_uint32_extension, 203); + message->AddExtension(UNITTEST::repeated_uint64_extension, 204); + message->AddExtension(UNITTEST::repeated_sint32_extension, 205); + message->AddExtension(UNITTEST::repeated_sint64_extension, 206); + message->AddExtension(UNITTEST::repeated_fixed32_extension, 207); + message->AddExtension(UNITTEST::repeated_fixed64_extension, 208); + message->AddExtension(UNITTEST::repeated_sfixed32_extension, 209); + message->AddExtension(UNITTEST::repeated_sfixed64_extension, 210); + message->AddExtension(UNITTEST::repeated_float_extension, 211); + message->AddExtension(UNITTEST::repeated_double_extension, 212); + message->AddExtension(UNITTEST::repeated_bool_extension, true); + message->AddExtension(UNITTEST::repeated_string_extension, "215"); + message->AddExtension(UNITTEST::repeated_bytes_extension, "216"); + + message->AddExtension(UNITTEST::repeatedgroup_extension)->set_a(217); + message->AddExtension(UNITTEST::repeated_nested_message_extension) + ->set_bb(218); + message->AddExtension(UNITTEST::repeated_foreign_message_extension) + ->set_c(219); + message->AddExtension(UNITTEST::repeated_import_message_extension) + ->set_d(220); + message->AddExtension(UNITTEST::repeated_lazy_message_extension)->set_bb(227); + + message->AddExtension(UNITTEST::repeated_nested_enum_extension, + UNITTEST::TestAllTypes::BAR); + message->AddExtension(UNITTEST::repeated_foreign_enum_extension, + UNITTEST::FOREIGN_BAR); + message->AddExtension(UNITTEST::repeated_import_enum_extension, + UNITTEST_IMPORT::IMPORT_BAR); + + message->AddExtension(UNITTEST::repeated_string_piece_extension, "224"); + message->AddExtension(UNITTEST::repeated_cord_extension, "225"); + + // Add a second one of each field. + message->AddExtension(UNITTEST::repeated_int32_extension, 301); + message->AddExtension(UNITTEST::repeated_int64_extension, 302); + message->AddExtension(UNITTEST::repeated_uint32_extension, 303); + message->AddExtension(UNITTEST::repeated_uint64_extension, 304); + message->AddExtension(UNITTEST::repeated_sint32_extension, 305); + message->AddExtension(UNITTEST::repeated_sint64_extension, 306); + message->AddExtension(UNITTEST::repeated_fixed32_extension, 307); + message->AddExtension(UNITTEST::repeated_fixed64_extension, 308); + message->AddExtension(UNITTEST::repeated_sfixed32_extension, 309); + message->AddExtension(UNITTEST::repeated_sfixed64_extension, 310); + message->AddExtension(UNITTEST::repeated_float_extension, 311); + message->AddExtension(UNITTEST::repeated_double_extension, 312); + message->AddExtension(UNITTEST::repeated_bool_extension, false); + message->AddExtension(UNITTEST::repeated_string_extension, "315"); + message->AddExtension(UNITTEST::repeated_bytes_extension, "316"); + + message->AddExtension(UNITTEST::repeatedgroup_extension)->set_a(317); + message->AddExtension(UNITTEST::repeated_nested_message_extension) + ->set_bb(318); + message->AddExtension(UNITTEST::repeated_foreign_message_extension) + ->set_c(319); + message->AddExtension(UNITTEST::repeated_import_message_extension) + ->set_d(320); + message->AddExtension(UNITTEST::repeated_lazy_message_extension)->set_bb(327); + + message->AddExtension(UNITTEST::repeated_nested_enum_extension, + UNITTEST::TestAllTypes::BAZ); + message->AddExtension(UNITTEST::repeated_foreign_enum_extension, + UNITTEST::FOREIGN_BAZ); + message->AddExtension(UNITTEST::repeated_import_enum_extension, + UNITTEST_IMPORT::IMPORT_BAZ); + + message->AddExtension(UNITTEST::repeated_string_piece_extension, "324"); + message->AddExtension(UNITTEST::repeated_cord_extension, "325"); + + // ----------------------------------------------------------------- + + message->SetExtension(UNITTEST::default_int32_extension, 401); + message->SetExtension(UNITTEST::default_int64_extension, 402); + message->SetExtension(UNITTEST::default_uint32_extension, 403); + message->SetExtension(UNITTEST::default_uint64_extension, 404); + message->SetExtension(UNITTEST::default_sint32_extension, 405); + message->SetExtension(UNITTEST::default_sint64_extension, 406); + message->SetExtension(UNITTEST::default_fixed32_extension, 407); + message->SetExtension(UNITTEST::default_fixed64_extension, 408); + message->SetExtension(UNITTEST::default_sfixed32_extension, 409); + message->SetExtension(UNITTEST::default_sfixed64_extension, 410); + message->SetExtension(UNITTEST::default_float_extension, 411); + message->SetExtension(UNITTEST::default_double_extension, 412); + message->SetExtension(UNITTEST::default_bool_extension, false); + message->SetExtension(UNITTEST::default_string_extension, "415"); + message->SetExtension(UNITTEST::default_bytes_extension, "416"); + + message->SetExtension(UNITTEST::default_nested_enum_extension, + UNITTEST::TestAllTypes::FOO); + message->SetExtension(UNITTEST::default_foreign_enum_extension, + UNITTEST::FOREIGN_FOO); + message->SetExtension(UNITTEST::default_import_enum_extension, + UNITTEST_IMPORT::IMPORT_FOO); + + message->SetExtension(UNITTEST::default_string_piece_extension, "424"); + message->SetExtension(UNITTEST::default_cord_extension, "425"); + + SetOneofFields(message); +} + +inline void TestUtil::SetOneofFields(UNITTEST::TestAllExtensions* message) { + message->SetExtension(UNITTEST::oneof_uint32_extension, 601); + message->MutableExtension(UNITTEST::oneof_nested_message_extension) + ->set_bb(602); + message->SetExtension(UNITTEST::oneof_string_extension, "603"); + message->SetExtension(UNITTEST::oneof_bytes_extension, "604"); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::SetAllFieldsAndExtensions( + UNITTEST::TestFieldOrderings* message) { + GOOGLE_CHECK(message); + message->set_my_int(1); + message->set_my_string("foo"); + message->set_my_float(1.0); + message->SetExtension(UNITTEST::my_extension_int, 23); + message->SetExtension(UNITTEST::my_extension_string, "bar"); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ModifyRepeatedExtensions( + UNITTEST::TestAllExtensions* message) { + message->SetExtension(UNITTEST::repeated_int32_extension, 1, 501); + message->SetExtension(UNITTEST::repeated_int64_extension, 1, 502); + message->SetExtension(UNITTEST::repeated_uint32_extension, 1, 503); + message->SetExtension(UNITTEST::repeated_uint64_extension, 1, 504); + message->SetExtension(UNITTEST::repeated_sint32_extension, 1, 505); + message->SetExtension(UNITTEST::repeated_sint64_extension, 1, 506); + message->SetExtension(UNITTEST::repeated_fixed32_extension, 1, 507); + message->SetExtension(UNITTEST::repeated_fixed64_extension, 1, 508); + message->SetExtension(UNITTEST::repeated_sfixed32_extension, 1, 509); + message->SetExtension(UNITTEST::repeated_sfixed64_extension, 1, 510); + message->SetExtension(UNITTEST::repeated_float_extension, 1, 511); + message->SetExtension(UNITTEST::repeated_double_extension, 1, 512); + message->SetExtension(UNITTEST::repeated_bool_extension, 1, true); + message->SetExtension(UNITTEST::repeated_string_extension, 1, "515"); + message->SetExtension(UNITTEST::repeated_bytes_extension, 1, "516"); + + message->MutableExtension(UNITTEST::repeatedgroup_extension, 1)->set_a(517); + message->MutableExtension(UNITTEST::repeated_nested_message_extension, 1) + ->set_bb(518); + message->MutableExtension(UNITTEST::repeated_foreign_message_extension, 1) + ->set_c(519); + message->MutableExtension(UNITTEST::repeated_import_message_extension, 1) + ->set_d(520); + message->MutableExtension(UNITTEST::repeated_lazy_message_extension, 1) + ->set_bb(527); + + message->SetExtension(UNITTEST::repeated_nested_enum_extension, 1, + UNITTEST::TestAllTypes::FOO); + message->SetExtension(UNITTEST::repeated_foreign_enum_extension, 1, + UNITTEST::FOREIGN_FOO); + message->SetExtension(UNITTEST::repeated_import_enum_extension, 1, + UNITTEST_IMPORT::IMPORT_FOO); + + message->SetExtension(UNITTEST::repeated_string_piece_extension, 1, "524"); + message->SetExtension(UNITTEST::repeated_cord_extension, 1, "525"); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectAllExtensionsSet( + const UNITTEST::TestAllExtensions& message) { + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_int32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_int64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_uint32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_uint64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_sint32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_sint64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_fixed32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_fixed64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_sfixed32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_sfixed64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_float_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_double_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_bool_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_string_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_bytes_extension)); + + EXPECT_TRUE(message.HasExtension(UNITTEST::optionalgroup_extension)); + EXPECT_TRUE( + message.HasExtension(UNITTEST::optional_nested_message_extension)); + EXPECT_TRUE( + message.HasExtension(UNITTEST::optional_foreign_message_extension)); + EXPECT_TRUE( + message.HasExtension(UNITTEST::optional_import_message_extension)); + EXPECT_TRUE( + message.HasExtension(UNITTEST::optional_public_import_message_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_lazy_message_extension)); + + EXPECT_TRUE(message.GetExtension(UNITTEST::optionalgroup_extension).has_a()); + EXPECT_TRUE(message.GetExtension(UNITTEST::optional_nested_message_extension) + .has_bb()); + EXPECT_TRUE(message.GetExtension(UNITTEST::optional_foreign_message_extension) + .has_c()); + EXPECT_TRUE(message.GetExtension(UNITTEST::optional_import_message_extension) + .has_d()); + EXPECT_TRUE( + message.GetExtension(UNITTEST::optional_public_import_message_extension) + .has_e()); + EXPECT_TRUE( + message.GetExtension(UNITTEST::optional_lazy_message_extension).has_bb()); + + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_nested_enum_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_foreign_enum_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_import_enum_extension)); + + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_string_piece_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_cord_extension)); + + EXPECT_EQ(101, message.GetExtension(UNITTEST::optional_int32_extension)); + EXPECT_EQ(102, message.GetExtension(UNITTEST::optional_int64_extension)); + EXPECT_EQ(103, message.GetExtension(UNITTEST::optional_uint32_extension)); + EXPECT_EQ(104, message.GetExtension(UNITTEST::optional_uint64_extension)); + EXPECT_EQ(105, message.GetExtension(UNITTEST::optional_sint32_extension)); + EXPECT_EQ(106, message.GetExtension(UNITTEST::optional_sint64_extension)); + EXPECT_EQ(107, message.GetExtension(UNITTEST::optional_fixed32_extension)); + EXPECT_EQ(108, message.GetExtension(UNITTEST::optional_fixed64_extension)); + EXPECT_EQ(109, message.GetExtension(UNITTEST::optional_sfixed32_extension)); + EXPECT_EQ(110, message.GetExtension(UNITTEST::optional_sfixed64_extension)); + EXPECT_EQ(111, message.GetExtension(UNITTEST::optional_float_extension)); + EXPECT_EQ(112, message.GetExtension(UNITTEST::optional_double_extension)); + EXPECT_TRUE(message.GetExtension(UNITTEST::optional_bool_extension)); + EXPECT_EQ("115", message.GetExtension(UNITTEST::optional_string_extension)); + EXPECT_EQ("116", message.GetExtension(UNITTEST::optional_bytes_extension)); + + EXPECT_EQ(117, message.GetExtension(UNITTEST::optionalgroup_extension).a()); + EXPECT_EQ( + 118, + message.GetExtension(UNITTEST::optional_nested_message_extension).bb()); + EXPECT_EQ( + 119, + message.GetExtension(UNITTEST::optional_foreign_message_extension).c()); + EXPECT_EQ( + 120, + message.GetExtension(UNITTEST::optional_import_message_extension).d()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, + message.GetExtension(UNITTEST::optional_nested_enum_extension)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, + message.GetExtension(UNITTEST::optional_foreign_enum_extension)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAZ, + message.GetExtension(UNITTEST::optional_import_enum_extension)); + + EXPECT_EQ("124", + message.GetExtension(UNITTEST::optional_string_piece_extension)); + EXPECT_EQ("125", message.GetExtension(UNITTEST::optional_cord_extension)); + EXPECT_EQ( + 126, + message.GetExtension(UNITTEST::optional_public_import_message_extension) + .e()); + EXPECT_EQ( + 127, + message.GetExtension(UNITTEST::optional_lazy_message_extension).bb()); + + // ----------------------------------------------------------------- + + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_int32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_int64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_uint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_uint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_fixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_fixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sfixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sfixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_float_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_double_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_bool_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_string_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_bytes_extension)); + + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeatedgroup_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_nested_message_extension)); + ASSERT_EQ( + 2, message.ExtensionSize(UNITTEST::repeated_foreign_message_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_import_message_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_lazy_message_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_nested_enum_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_foreign_enum_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_import_enum_extension)); + + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_string_piece_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_cord_extension)); + + EXPECT_EQ(201, message.GetExtension(UNITTEST::repeated_int32_extension, 0)); + EXPECT_EQ(202, message.GetExtension(UNITTEST::repeated_int64_extension, 0)); + EXPECT_EQ(203, message.GetExtension(UNITTEST::repeated_uint32_extension, 0)); + EXPECT_EQ(204, message.GetExtension(UNITTEST::repeated_uint64_extension, 0)); + EXPECT_EQ(205, message.GetExtension(UNITTEST::repeated_sint32_extension, 0)); + EXPECT_EQ(206, message.GetExtension(UNITTEST::repeated_sint64_extension, 0)); + EXPECT_EQ(207, message.GetExtension(UNITTEST::repeated_fixed32_extension, 0)); + EXPECT_EQ(208, message.GetExtension(UNITTEST::repeated_fixed64_extension, 0)); + EXPECT_EQ(209, + message.GetExtension(UNITTEST::repeated_sfixed32_extension, 0)); + EXPECT_EQ(210, + message.GetExtension(UNITTEST::repeated_sfixed64_extension, 0)); + EXPECT_EQ(211, message.GetExtension(UNITTEST::repeated_float_extension, 0)); + EXPECT_EQ(212, message.GetExtension(UNITTEST::repeated_double_extension, 0)); + EXPECT_TRUE(message.GetExtension(UNITTEST::repeated_bool_extension, 0)); + EXPECT_EQ("215", + message.GetExtension(UNITTEST::repeated_string_extension, 0)); + EXPECT_EQ("216", message.GetExtension(UNITTEST::repeated_bytes_extension, 0)); + + EXPECT_EQ(217, + message.GetExtension(UNITTEST::repeatedgroup_extension, 0).a()); + EXPECT_EQ(218, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 0) + .bb()); + EXPECT_EQ( + 219, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 0) + .c()); + EXPECT_EQ( + 220, + message.GetExtension(UNITTEST::repeated_import_message_extension, 0).d()); + EXPECT_EQ( + 227, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 0).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, + message.GetExtension(UNITTEST::repeated_nested_enum_extension, 0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::repeated_foreign_enum_extension, 0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, + message.GetExtension(UNITTEST::repeated_import_enum_extension, 0)); + + EXPECT_EQ("224", + message.GetExtension(UNITTEST::repeated_string_piece_extension, 0)); + EXPECT_EQ("225", message.GetExtension(UNITTEST::repeated_cord_extension, 0)); + + EXPECT_EQ(301, message.GetExtension(UNITTEST::repeated_int32_extension, 1)); + EXPECT_EQ(302, message.GetExtension(UNITTEST::repeated_int64_extension, 1)); + EXPECT_EQ(303, message.GetExtension(UNITTEST::repeated_uint32_extension, 1)); + EXPECT_EQ(304, message.GetExtension(UNITTEST::repeated_uint64_extension, 1)); + EXPECT_EQ(305, message.GetExtension(UNITTEST::repeated_sint32_extension, 1)); + EXPECT_EQ(306, message.GetExtension(UNITTEST::repeated_sint64_extension, 1)); + EXPECT_EQ(307, message.GetExtension(UNITTEST::repeated_fixed32_extension, 1)); + EXPECT_EQ(308, message.GetExtension(UNITTEST::repeated_fixed64_extension, 1)); + EXPECT_EQ(309, + message.GetExtension(UNITTEST::repeated_sfixed32_extension, 1)); + EXPECT_EQ(310, + message.GetExtension(UNITTEST::repeated_sfixed64_extension, 1)); + EXPECT_EQ(311, message.GetExtension(UNITTEST::repeated_float_extension, 1)); + EXPECT_EQ(312, message.GetExtension(UNITTEST::repeated_double_extension, 1)); + EXPECT_FALSE(message.GetExtension(UNITTEST::repeated_bool_extension, 1)); + EXPECT_EQ("315", + message.GetExtension(UNITTEST::repeated_string_extension, 1)); + EXPECT_EQ("316", message.GetExtension(UNITTEST::repeated_bytes_extension, 1)); + + EXPECT_EQ(317, + message.GetExtension(UNITTEST::repeatedgroup_extension, 1).a()); + EXPECT_EQ(318, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 1) + .bb()); + EXPECT_EQ( + 319, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 1) + .c()); + EXPECT_EQ( + 320, + message.GetExtension(UNITTEST::repeated_import_message_extension, 1).d()); + EXPECT_EQ( + 327, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 1).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, + message.GetExtension(UNITTEST::repeated_nested_enum_extension, 1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, + message.GetExtension(UNITTEST::repeated_foreign_enum_extension, 1)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAZ, + message.GetExtension(UNITTEST::repeated_import_enum_extension, 1)); + + EXPECT_EQ("324", + message.GetExtension(UNITTEST::repeated_string_piece_extension, 1)); + EXPECT_EQ("325", message.GetExtension(UNITTEST::repeated_cord_extension, 1)); + + // ----------------------------------------------------------------- + + EXPECT_TRUE(message.HasExtension(UNITTEST::default_int32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_int64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_uint32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_uint64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_sint32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_sint64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_fixed32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_fixed64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_sfixed32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_sfixed64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_float_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_double_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_bool_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_string_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_bytes_extension)); + + EXPECT_TRUE(message.HasExtension(UNITTEST::default_nested_enum_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_foreign_enum_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_import_enum_extension)); + + EXPECT_TRUE(message.HasExtension(UNITTEST::default_string_piece_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_cord_extension)); + + EXPECT_EQ(401, message.GetExtension(UNITTEST::default_int32_extension)); + EXPECT_EQ(402, message.GetExtension(UNITTEST::default_int64_extension)); + EXPECT_EQ(403, message.GetExtension(UNITTEST::default_uint32_extension)); + EXPECT_EQ(404, message.GetExtension(UNITTEST::default_uint64_extension)); + EXPECT_EQ(405, message.GetExtension(UNITTEST::default_sint32_extension)); + EXPECT_EQ(406, message.GetExtension(UNITTEST::default_sint64_extension)); + EXPECT_EQ(407, message.GetExtension(UNITTEST::default_fixed32_extension)); + EXPECT_EQ(408, message.GetExtension(UNITTEST::default_fixed64_extension)); + EXPECT_EQ(409, message.GetExtension(UNITTEST::default_sfixed32_extension)); + EXPECT_EQ(410, message.GetExtension(UNITTEST::default_sfixed64_extension)); + EXPECT_EQ(411, message.GetExtension(UNITTEST::default_float_extension)); + EXPECT_EQ(412, message.GetExtension(UNITTEST::default_double_extension)); + EXPECT_FALSE(message.GetExtension(UNITTEST::default_bool_extension)); + EXPECT_EQ("415", message.GetExtension(UNITTEST::default_string_extension)); + EXPECT_EQ("416", message.GetExtension(UNITTEST::default_bytes_extension)); + + EXPECT_EQ(UNITTEST::TestAllTypes::FOO, + message.GetExtension(UNITTEST::default_nested_enum_extension)); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, + message.GetExtension(UNITTEST::default_foreign_enum_extension)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_FOO, + message.GetExtension(UNITTEST::default_import_enum_extension)); + + EXPECT_EQ("424", + message.GetExtension(UNITTEST::default_string_piece_extension)); + EXPECT_EQ("425", message.GetExtension(UNITTEST::default_cord_extension)); + + EXPECT_TRUE(message.HasExtension(UNITTEST::oneof_uint32_extension)); + EXPECT_TRUE( + message.GetExtension(UNITTEST::oneof_nested_message_extension).has_bb()); + EXPECT_TRUE(message.HasExtension(UNITTEST::oneof_string_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::oneof_bytes_extension)); + + EXPECT_EQ(601, message.GetExtension(UNITTEST::oneof_uint32_extension)); + EXPECT_EQ( + 602, message.GetExtension(UNITTEST::oneof_nested_message_extension).bb()); + EXPECT_EQ("603", message.GetExtension(UNITTEST::oneof_string_extension)); + EXPECT_EQ("604", message.GetExtension(UNITTEST::oneof_bytes_extension)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectExtensionsClear( + const UNITTEST::TestAllExtensions& message) { + std::string serialized; + ASSERT_TRUE(message.SerializeToString(&serialized)); + EXPECT_EQ("", serialized); + EXPECT_EQ(0, message.ByteSizeLong()); + + // has_blah() should initially be false for all optional fields. + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_int32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_int64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_uint32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_uint64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_sint32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_sint64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_fixed32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_fixed64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_sfixed32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_sfixed64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_float_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_double_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_bool_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_string_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_bytes_extension)); + + EXPECT_FALSE(message.HasExtension(UNITTEST::optionalgroup_extension)); + EXPECT_FALSE( + message.HasExtension(UNITTEST::optional_nested_message_extension)); + EXPECT_FALSE( + message.HasExtension(UNITTEST::optional_foreign_message_extension)); + EXPECT_FALSE( + message.HasExtension(UNITTEST::optional_import_message_extension)); + EXPECT_FALSE( + message.HasExtension(UNITTEST::optional_public_import_message_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_lazy_message_extension)); + + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_nested_enum_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_foreign_enum_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_import_enum_extension)); + + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_string_piece_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_cord_extension)); + + // Optional fields without defaults are set to zero or something like it. + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_int32_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_int64_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_uint32_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_uint64_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_sint32_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_sint64_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_fixed32_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_fixed64_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_sfixed32_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_sfixed64_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_float_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_double_extension)); + EXPECT_FALSE(message.GetExtension(UNITTEST::optional_bool_extension)); + EXPECT_EQ("", message.GetExtension(UNITTEST::optional_string_extension)); + EXPECT_EQ("", message.GetExtension(UNITTEST::optional_bytes_extension)); + + // Embedded messages should also be clear. + EXPECT_FALSE(message.GetExtension(UNITTEST::optionalgroup_extension).has_a()); + EXPECT_FALSE(message.GetExtension(UNITTEST::optional_nested_message_extension) + .has_bb()); + EXPECT_FALSE( + message.GetExtension(UNITTEST::optional_foreign_message_extension) + .has_c()); + EXPECT_FALSE(message.GetExtension(UNITTEST::optional_import_message_extension) + .has_d()); + EXPECT_FALSE( + message.GetExtension(UNITTEST::optional_public_import_message_extension) + .has_e()); + EXPECT_FALSE( + message.GetExtension(UNITTEST::optional_lazy_message_extension).has_bb()); + + EXPECT_EQ(0, message.GetExtension(UNITTEST::optionalgroup_extension).a()); + EXPECT_EQ( + 0, + message.GetExtension(UNITTEST::optional_nested_message_extension).bb()); + EXPECT_EQ( + 0, + message.GetExtension(UNITTEST::optional_foreign_message_extension).c()); + EXPECT_EQ( + 0, message.GetExtension(UNITTEST::optional_import_message_extension).d()); + EXPECT_EQ( + 0, + message.GetExtension(UNITTEST::optional_public_import_message_extension) + .e()); + EXPECT_EQ( + 0, message.GetExtension(UNITTEST::optional_lazy_message_extension).bb()); + + // Enums without defaults are set to the first value in the enum. + EXPECT_EQ(UNITTEST::TestAllTypes::FOO, + message.GetExtension(UNITTEST::optional_nested_enum_extension)); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, + message.GetExtension(UNITTEST::optional_foreign_enum_extension)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_FOO, + message.GetExtension(UNITTEST::optional_import_enum_extension)); + + EXPECT_EQ("", + message.GetExtension(UNITTEST::optional_string_piece_extension)); + EXPECT_EQ("", message.GetExtension(UNITTEST::optional_cord_extension)); + + // Repeated fields are empty. + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_int32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_int64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_uint32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_uint64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_sint32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_sint64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_fixed32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_fixed64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_sfixed32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_sfixed64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_float_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_double_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_bool_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_string_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_bytes_extension)); + + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeatedgroup_extension)); + EXPECT_EQ(0, + message.ExtensionSize(UNITTEST::repeated_nested_message_extension)); + EXPECT_EQ( + 0, message.ExtensionSize(UNITTEST::repeated_foreign_message_extension)); + EXPECT_EQ(0, + message.ExtensionSize(UNITTEST::repeated_import_message_extension)); + EXPECT_EQ(0, + message.ExtensionSize(UNITTEST::repeated_lazy_message_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_nested_enum_extension)); + EXPECT_EQ(0, + message.ExtensionSize(UNITTEST::repeated_foreign_enum_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_import_enum_extension)); + + EXPECT_EQ(0, + message.ExtensionSize(UNITTEST::repeated_string_piece_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_cord_extension)); + + // has_blah() should also be false for all default fields. + EXPECT_FALSE(message.HasExtension(UNITTEST::default_int32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_int64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_uint32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_uint64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_sint32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_sint64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_fixed32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_fixed64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_sfixed32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_sfixed64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_float_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_double_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_bool_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_string_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_bytes_extension)); + + EXPECT_FALSE(message.HasExtension(UNITTEST::default_nested_enum_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_foreign_enum_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_import_enum_extension)); + + EXPECT_FALSE(message.HasExtension(UNITTEST::default_string_piece_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_cord_extension)); + + // Fields with defaults have their default values (duh). + EXPECT_EQ(41, message.GetExtension(UNITTEST::default_int32_extension)); + EXPECT_EQ(42, message.GetExtension(UNITTEST::default_int64_extension)); + EXPECT_EQ(43, message.GetExtension(UNITTEST::default_uint32_extension)); + EXPECT_EQ(44, message.GetExtension(UNITTEST::default_uint64_extension)); + EXPECT_EQ(-45, message.GetExtension(UNITTEST::default_sint32_extension)); + EXPECT_EQ(46, message.GetExtension(UNITTEST::default_sint64_extension)); + EXPECT_EQ(47, message.GetExtension(UNITTEST::default_fixed32_extension)); + EXPECT_EQ(48, message.GetExtension(UNITTEST::default_fixed64_extension)); + EXPECT_EQ(49, message.GetExtension(UNITTEST::default_sfixed32_extension)); + EXPECT_EQ(-50, message.GetExtension(UNITTEST::default_sfixed64_extension)); + EXPECT_EQ(51.5, message.GetExtension(UNITTEST::default_float_extension)); + EXPECT_EQ(52e3, message.GetExtension(UNITTEST::default_double_extension)); + EXPECT_TRUE(message.GetExtension(UNITTEST::default_bool_extension)); + EXPECT_EQ("hello", message.GetExtension(UNITTEST::default_string_extension)); + EXPECT_EQ("world", message.GetExtension(UNITTEST::default_bytes_extension)); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, + message.GetExtension(UNITTEST::default_nested_enum_extension)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::default_foreign_enum_extension)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, + message.GetExtension(UNITTEST::default_import_enum_extension)); + + EXPECT_EQ("abc", + message.GetExtension(UNITTEST::default_string_piece_extension)); + EXPECT_EQ("123", message.GetExtension(UNITTEST::default_cord_extension)); + + EXPECT_FALSE(message.HasExtension(UNITTEST::oneof_uint32_extension)); + EXPECT_FALSE( + message.GetExtension(UNITTEST::oneof_nested_message_extension).has_bb()); + EXPECT_FALSE(message.HasExtension(UNITTEST::oneof_string_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::oneof_bytes_extension)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectRepeatedExtensionsModified( + const UNITTEST::TestAllExtensions& message) { + // ModifyRepeatedFields only sets the second repeated element of each + // field. In addition to verifying this, we also verify that the first + // element and size were *not* modified. + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_int32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_int64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_uint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_uint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_fixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_fixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sfixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sfixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_float_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_double_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_bool_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_string_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_bytes_extension)); + + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeatedgroup_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_nested_message_extension)); + ASSERT_EQ( + 2, message.ExtensionSize(UNITTEST::repeated_foreign_message_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_import_message_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_lazy_message_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_nested_enum_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_foreign_enum_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_import_enum_extension)); + + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_string_piece_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_cord_extension)); + + EXPECT_EQ(201, message.GetExtension(UNITTEST::repeated_int32_extension, 0)); + EXPECT_EQ(202, message.GetExtension(UNITTEST::repeated_int64_extension, 0)); + EXPECT_EQ(203, message.GetExtension(UNITTEST::repeated_uint32_extension, 0)); + EXPECT_EQ(204, message.GetExtension(UNITTEST::repeated_uint64_extension, 0)); + EXPECT_EQ(205, message.GetExtension(UNITTEST::repeated_sint32_extension, 0)); + EXPECT_EQ(206, message.GetExtension(UNITTEST::repeated_sint64_extension, 0)); + EXPECT_EQ(207, message.GetExtension(UNITTEST::repeated_fixed32_extension, 0)); + EXPECT_EQ(208, message.GetExtension(UNITTEST::repeated_fixed64_extension, 0)); + EXPECT_EQ(209, + message.GetExtension(UNITTEST::repeated_sfixed32_extension, 0)); + EXPECT_EQ(210, + message.GetExtension(UNITTEST::repeated_sfixed64_extension, 0)); + EXPECT_EQ(211, message.GetExtension(UNITTEST::repeated_float_extension, 0)); + EXPECT_EQ(212, message.GetExtension(UNITTEST::repeated_double_extension, 0)); + EXPECT_TRUE(message.GetExtension(UNITTEST::repeated_bool_extension, 0)); + EXPECT_EQ("215", + message.GetExtension(UNITTEST::repeated_string_extension, 0)); + EXPECT_EQ("216", message.GetExtension(UNITTEST::repeated_bytes_extension, 0)); + + EXPECT_EQ(217, + message.GetExtension(UNITTEST::repeatedgroup_extension, 0).a()); + EXPECT_EQ(218, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 0) + .bb()); + EXPECT_EQ( + 219, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 0) + .c()); + EXPECT_EQ( + 220, + message.GetExtension(UNITTEST::repeated_import_message_extension, 0).d()); + EXPECT_EQ( + 227, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 0).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, + message.GetExtension(UNITTEST::repeated_nested_enum_extension, 0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::repeated_foreign_enum_extension, 0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, + message.GetExtension(UNITTEST::repeated_import_enum_extension, 0)); + + EXPECT_EQ("224", + message.GetExtension(UNITTEST::repeated_string_piece_extension, 0)); + EXPECT_EQ("225", message.GetExtension(UNITTEST::repeated_cord_extension, 0)); + + // Actually verify the second (modified) elements now. + EXPECT_EQ(501, message.GetExtension(UNITTEST::repeated_int32_extension, 1)); + EXPECT_EQ(502, message.GetExtension(UNITTEST::repeated_int64_extension, 1)); + EXPECT_EQ(503, message.GetExtension(UNITTEST::repeated_uint32_extension, 1)); + EXPECT_EQ(504, message.GetExtension(UNITTEST::repeated_uint64_extension, 1)); + EXPECT_EQ(505, message.GetExtension(UNITTEST::repeated_sint32_extension, 1)); + EXPECT_EQ(506, message.GetExtension(UNITTEST::repeated_sint64_extension, 1)); + EXPECT_EQ(507, message.GetExtension(UNITTEST::repeated_fixed32_extension, 1)); + EXPECT_EQ(508, message.GetExtension(UNITTEST::repeated_fixed64_extension, 1)); + EXPECT_EQ(509, + message.GetExtension(UNITTEST::repeated_sfixed32_extension, 1)); + EXPECT_EQ(510, + message.GetExtension(UNITTEST::repeated_sfixed64_extension, 1)); + EXPECT_EQ(511, message.GetExtension(UNITTEST::repeated_float_extension, 1)); + EXPECT_EQ(512, message.GetExtension(UNITTEST::repeated_double_extension, 1)); + EXPECT_TRUE(message.GetExtension(UNITTEST::repeated_bool_extension, 1)); + EXPECT_EQ("515", + message.GetExtension(UNITTEST::repeated_string_extension, 1)); + EXPECT_EQ("516", message.GetExtension(UNITTEST::repeated_bytes_extension, 1)); + + EXPECT_EQ(517, + message.GetExtension(UNITTEST::repeatedgroup_extension, 1).a()); + EXPECT_EQ(518, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 1) + .bb()); + EXPECT_EQ( + 519, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 1) + .c()); + EXPECT_EQ( + 520, + message.GetExtension(UNITTEST::repeated_import_message_extension, 1).d()); + EXPECT_EQ( + 527, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 1).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::FOO, + message.GetExtension(UNITTEST::repeated_nested_enum_extension, 1)); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, + message.GetExtension(UNITTEST::repeated_foreign_enum_extension, 1)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_FOO, + message.GetExtension(UNITTEST::repeated_import_enum_extension, 1)); + + EXPECT_EQ("524", + message.GetExtension(UNITTEST::repeated_string_piece_extension, 1)); + EXPECT_EQ("525", message.GetExtension(UNITTEST::repeated_cord_extension, 1)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::SetPackedExtensions( + UNITTEST::TestPackedExtensions* message) { + message->AddExtension(UNITTEST::packed_int32_extension, 601); + message->AddExtension(UNITTEST::packed_int64_extension, 602); + message->AddExtension(UNITTEST::packed_uint32_extension, 603); + message->AddExtension(UNITTEST::packed_uint64_extension, 604); + message->AddExtension(UNITTEST::packed_sint32_extension, 605); + message->AddExtension(UNITTEST::packed_sint64_extension, 606); + message->AddExtension(UNITTEST::packed_fixed32_extension, 607); + message->AddExtension(UNITTEST::packed_fixed64_extension, 608); + message->AddExtension(UNITTEST::packed_sfixed32_extension, 609); + message->AddExtension(UNITTEST::packed_sfixed64_extension, 610); + message->AddExtension(UNITTEST::packed_float_extension, 611); + message->AddExtension(UNITTEST::packed_double_extension, 612); + message->AddExtension(UNITTEST::packed_bool_extension, true); + message->AddExtension(UNITTEST::packed_enum_extension, UNITTEST::FOREIGN_BAR); + // add a second one of each field + message->AddExtension(UNITTEST::packed_int32_extension, 701); + message->AddExtension(UNITTEST::packed_int64_extension, 702); + message->AddExtension(UNITTEST::packed_uint32_extension, 703); + message->AddExtension(UNITTEST::packed_uint64_extension, 704); + message->AddExtension(UNITTEST::packed_sint32_extension, 705); + message->AddExtension(UNITTEST::packed_sint64_extension, 706); + message->AddExtension(UNITTEST::packed_fixed32_extension, 707); + message->AddExtension(UNITTEST::packed_fixed64_extension, 708); + message->AddExtension(UNITTEST::packed_sfixed32_extension, 709); + message->AddExtension(UNITTEST::packed_sfixed64_extension, 710); + message->AddExtension(UNITTEST::packed_float_extension, 711); + message->AddExtension(UNITTEST::packed_double_extension, 712); + message->AddExtension(UNITTEST::packed_bool_extension, false); + message->AddExtension(UNITTEST::packed_enum_extension, UNITTEST::FOREIGN_BAZ); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectPackedExtensionsSet( + const UNITTEST::TestPackedExtensions& message) { + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_int32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_int64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_uint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_uint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_sint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_sint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_fixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_fixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_sfixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_sfixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_float_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_double_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_bool_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_enum_extension)); + + EXPECT_EQ(601, message.GetExtension(UNITTEST::packed_int32_extension, 0)); + EXPECT_EQ(602, message.GetExtension(UNITTEST::packed_int64_extension, 0)); + EXPECT_EQ(603, message.GetExtension(UNITTEST::packed_uint32_extension, 0)); + EXPECT_EQ(604, message.GetExtension(UNITTEST::packed_uint64_extension, 0)); + EXPECT_EQ(605, message.GetExtension(UNITTEST::packed_sint32_extension, 0)); + EXPECT_EQ(606, message.GetExtension(UNITTEST::packed_sint64_extension, 0)); + EXPECT_EQ(607, message.GetExtension(UNITTEST::packed_fixed32_extension, 0)); + EXPECT_EQ(608, message.GetExtension(UNITTEST::packed_fixed64_extension, 0)); + EXPECT_EQ(609, message.GetExtension(UNITTEST::packed_sfixed32_extension, 0)); + EXPECT_EQ(610, message.GetExtension(UNITTEST::packed_sfixed64_extension, 0)); + EXPECT_EQ(611, message.GetExtension(UNITTEST::packed_float_extension, 0)); + EXPECT_EQ(612, message.GetExtension(UNITTEST::packed_double_extension, 0)); + EXPECT_TRUE(message.GetExtension(UNITTEST::packed_bool_extension, 0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::packed_enum_extension, 0)); + EXPECT_EQ(701, message.GetExtension(UNITTEST::packed_int32_extension, 1)); + EXPECT_EQ(702, message.GetExtension(UNITTEST::packed_int64_extension, 1)); + EXPECT_EQ(703, message.GetExtension(UNITTEST::packed_uint32_extension, 1)); + EXPECT_EQ(704, message.GetExtension(UNITTEST::packed_uint64_extension, 1)); + EXPECT_EQ(705, message.GetExtension(UNITTEST::packed_sint32_extension, 1)); + EXPECT_EQ(706, message.GetExtension(UNITTEST::packed_sint64_extension, 1)); + EXPECT_EQ(707, message.GetExtension(UNITTEST::packed_fixed32_extension, 1)); + EXPECT_EQ(708, message.GetExtension(UNITTEST::packed_fixed64_extension, 1)); + EXPECT_EQ(709, message.GetExtension(UNITTEST::packed_sfixed32_extension, 1)); + EXPECT_EQ(710, message.GetExtension(UNITTEST::packed_sfixed64_extension, 1)); + EXPECT_EQ(711, message.GetExtension(UNITTEST::packed_float_extension, 1)); + EXPECT_EQ(712, message.GetExtension(UNITTEST::packed_double_extension, 1)); + EXPECT_FALSE(message.GetExtension(UNITTEST::packed_bool_extension, 1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, + message.GetExtension(UNITTEST::packed_enum_extension, 1)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectUnpackedExtensionsSet( + const UNITTEST::TestUnpackedExtensions& message) { + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_int32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_int64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_uint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_uint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_sint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_sint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_fixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_fixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_sfixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_sfixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_float_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_double_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_bool_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_enum_extension)); + + EXPECT_EQ(601, message.GetExtension(UNITTEST::unpacked_int32_extension, 0)); + EXPECT_EQ(602, message.GetExtension(UNITTEST::unpacked_int64_extension, 0)); + EXPECT_EQ(603, message.GetExtension(UNITTEST::unpacked_uint32_extension, 0)); + EXPECT_EQ(604, message.GetExtension(UNITTEST::unpacked_uint64_extension, 0)); + EXPECT_EQ(605, message.GetExtension(UNITTEST::unpacked_sint32_extension, 0)); + EXPECT_EQ(606, message.GetExtension(UNITTEST::unpacked_sint64_extension, 0)); + EXPECT_EQ(607, message.GetExtension(UNITTEST::unpacked_fixed32_extension, 0)); + EXPECT_EQ(608, message.GetExtension(UNITTEST::unpacked_fixed64_extension, 0)); + EXPECT_EQ(609, + message.GetExtension(UNITTEST::unpacked_sfixed32_extension, 0)); + EXPECT_EQ(610, + message.GetExtension(UNITTEST::unpacked_sfixed64_extension, 0)); + EXPECT_EQ(611, message.GetExtension(UNITTEST::unpacked_float_extension, 0)); + EXPECT_EQ(612, message.GetExtension(UNITTEST::unpacked_double_extension, 0)); + EXPECT_EQ(true, message.GetExtension(UNITTEST::unpacked_bool_extension, 0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::unpacked_enum_extension, 0)); + EXPECT_EQ(701, message.GetExtension(UNITTEST::unpacked_int32_extension, 1)); + EXPECT_EQ(702, message.GetExtension(UNITTEST::unpacked_int64_extension, 1)); + EXPECT_EQ(703, message.GetExtension(UNITTEST::unpacked_uint32_extension, 1)); + EXPECT_EQ(704, message.GetExtension(UNITTEST::unpacked_uint64_extension, 1)); + EXPECT_EQ(705, message.GetExtension(UNITTEST::unpacked_sint32_extension, 1)); + EXPECT_EQ(706, message.GetExtension(UNITTEST::unpacked_sint64_extension, 1)); + EXPECT_EQ(707, message.GetExtension(UNITTEST::unpacked_fixed32_extension, 1)); + EXPECT_EQ(708, message.GetExtension(UNITTEST::unpacked_fixed64_extension, 1)); + EXPECT_EQ(709, + message.GetExtension(UNITTEST::unpacked_sfixed32_extension, 1)); + EXPECT_EQ(710, + message.GetExtension(UNITTEST::unpacked_sfixed64_extension, 1)); + EXPECT_EQ(711, message.GetExtension(UNITTEST::unpacked_float_extension, 1)); + EXPECT_EQ(712, message.GetExtension(UNITTEST::unpacked_double_extension, 1)); + EXPECT_EQ(false, message.GetExtension(UNITTEST::unpacked_bool_extension, 1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, + message.GetExtension(UNITTEST::unpacked_enum_extension, 1)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectLastRepeatedsRemoved( + const UNITTEST::TestAllTypes& message) { + ASSERT_EQ(1, message.repeated_int32_size()); + ASSERT_EQ(1, message.repeated_int64_size()); + ASSERT_EQ(1, message.repeated_uint32_size()); + ASSERT_EQ(1, message.repeated_uint64_size()); + ASSERT_EQ(1, message.repeated_sint32_size()); + ASSERT_EQ(1, message.repeated_sint64_size()); + ASSERT_EQ(1, message.repeated_fixed32_size()); + ASSERT_EQ(1, message.repeated_fixed64_size()); + ASSERT_EQ(1, message.repeated_sfixed32_size()); + ASSERT_EQ(1, message.repeated_sfixed64_size()); + ASSERT_EQ(1, message.repeated_float_size()); + ASSERT_EQ(1, message.repeated_double_size()); + ASSERT_EQ(1, message.repeated_bool_size()); + ASSERT_EQ(1, message.repeated_string_size()); + ASSERT_EQ(1, message.repeated_bytes_size()); + + ASSERT_EQ(1, message.repeatedgroup_size()); + ASSERT_EQ(1, message.repeated_nested_message_size()); + ASSERT_EQ(1, message.repeated_foreign_message_size()); + ASSERT_EQ(1, message.repeated_import_message_size()); + ASSERT_EQ(1, message.repeated_import_message_size()); + ASSERT_EQ(1, message.repeated_nested_enum_size()); + ASSERT_EQ(1, message.repeated_foreign_enum_size()); + ASSERT_EQ(1, message.repeated_import_enum_size()); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + ASSERT_EQ(1, message.repeated_string_piece_size()); + ASSERT_EQ(1, message.repeated_cord_size()); +#endif + + // Test that the remaining element is the correct one. + EXPECT_EQ(201, message.repeated_int32(0)); + EXPECT_EQ(202, message.repeated_int64(0)); + EXPECT_EQ(203, message.repeated_uint32(0)); + EXPECT_EQ(204, message.repeated_uint64(0)); + EXPECT_EQ(205, message.repeated_sint32(0)); + EXPECT_EQ(206, message.repeated_sint64(0)); + EXPECT_EQ(207, message.repeated_fixed32(0)); + EXPECT_EQ(208, message.repeated_fixed64(0)); + EXPECT_EQ(209, message.repeated_sfixed32(0)); + EXPECT_EQ(210, message.repeated_sfixed64(0)); + EXPECT_EQ(211, message.repeated_float(0)); + EXPECT_EQ(212, message.repeated_double(0)); + EXPECT_TRUE(message.repeated_bool(0)); + EXPECT_EQ("215", message.repeated_string(0)); + EXPECT_EQ("216", message.repeated_bytes(0)); + + EXPECT_EQ(217, message.repeatedgroup(0).a()); + EXPECT_EQ(218, message.repeated_nested_message(0).bb()); + EXPECT_EQ(219, message.repeated_foreign_message(0).c()); + EXPECT_EQ(220, message.repeated_import_message(0).d()); + EXPECT_EQ(220, message.repeated_import_message(0).d()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message.repeated_nested_enum(0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.repeated_foreign_enum(0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, message.repeated_import_enum(0)); +} + +inline void TestUtil::ExpectLastRepeatedExtensionsRemoved( + const UNITTEST::TestAllExtensions& message) { + // Test that one element was removed. + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_int32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_int64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_uint32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_uint64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_sint32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_sint64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_fixed32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_fixed64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_sfixed32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_sfixed64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_float_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_double_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_bool_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_string_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_bytes_extension)); + + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeatedgroup_extension)); + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_nested_message_extension)); + ASSERT_EQ( + 1, message.ExtensionSize(UNITTEST::repeated_foreign_message_extension)); + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_import_message_extension)); + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_lazy_message_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_nested_enum_extension)); + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_foreign_enum_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_import_enum_extension)); + + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_string_piece_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_cord_extension)); + + // Test that the remaining element is the correct one. + EXPECT_EQ(201, message.GetExtension(UNITTEST::repeated_int32_extension, 0)); + EXPECT_EQ(202, message.GetExtension(UNITTEST::repeated_int64_extension, 0)); + EXPECT_EQ(203, message.GetExtension(UNITTEST::repeated_uint32_extension, 0)); + EXPECT_EQ(204, message.GetExtension(UNITTEST::repeated_uint64_extension, 0)); + EXPECT_EQ(205, message.GetExtension(UNITTEST::repeated_sint32_extension, 0)); + EXPECT_EQ(206, message.GetExtension(UNITTEST::repeated_sint64_extension, 0)); + EXPECT_EQ(207, message.GetExtension(UNITTEST::repeated_fixed32_extension, 0)); + EXPECT_EQ(208, message.GetExtension(UNITTEST::repeated_fixed64_extension, 0)); + EXPECT_EQ(209, + message.GetExtension(UNITTEST::repeated_sfixed32_extension, 0)); + EXPECT_EQ(210, + message.GetExtension(UNITTEST::repeated_sfixed64_extension, 0)); + EXPECT_EQ(211, message.GetExtension(UNITTEST::repeated_float_extension, 0)); + EXPECT_EQ(212, message.GetExtension(UNITTEST::repeated_double_extension, 0)); + EXPECT_TRUE(message.GetExtension(UNITTEST::repeated_bool_extension, 0)); + EXPECT_EQ("215", + message.GetExtension(UNITTEST::repeated_string_extension, 0)); + EXPECT_EQ("216", message.GetExtension(UNITTEST::repeated_bytes_extension, 0)); + + EXPECT_EQ(217, + message.GetExtension(UNITTEST::repeatedgroup_extension, 0).a()); + EXPECT_EQ(218, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 0) + .bb()); + EXPECT_EQ( + 219, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 0) + .c()); + EXPECT_EQ( + 220, + message.GetExtension(UNITTEST::repeated_import_message_extension, 0).d()); + EXPECT_EQ( + 227, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 0).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, + message.GetExtension(UNITTEST::repeated_nested_enum_extension, 0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::repeated_foreign_enum_extension, 0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, + message.GetExtension(UNITTEST::repeated_import_enum_extension, 0)); + + EXPECT_EQ("224", + message.GetExtension(UNITTEST::repeated_string_piece_extension, 0)); + EXPECT_EQ("225", message.GetExtension(UNITTEST::repeated_cord_extension, 0)); +} + +inline void TestUtil::ExpectLastRepeatedsReleased( + const UNITTEST::TestAllTypes& message) { + ASSERT_EQ(1, message.repeatedgroup_size()); + ASSERT_EQ(1, message.repeated_nested_message_size()); + ASSERT_EQ(1, message.repeated_foreign_message_size()); + ASSERT_EQ(1, message.repeated_import_message_size()); + ASSERT_EQ(1, message.repeated_import_message_size()); + + EXPECT_EQ(217, message.repeatedgroup(0).a()); + EXPECT_EQ(218, message.repeated_nested_message(0).bb()); + EXPECT_EQ(219, message.repeated_foreign_message(0).c()); + EXPECT_EQ(220, message.repeated_import_message(0).d()); + EXPECT_EQ(220, message.repeated_import_message(0).d()); +} + +inline void TestUtil::ExpectLastRepeatedExtensionsReleased( + const UNITTEST::TestAllExtensions& message) { + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeatedgroup_extension)); + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_nested_message_extension)); + ASSERT_EQ( + 1, message.ExtensionSize(UNITTEST::repeated_foreign_message_extension)); + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_import_message_extension)); + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_lazy_message_extension)); + + EXPECT_EQ(217, + message.GetExtension(UNITTEST::repeatedgroup_extension, 0).a()); + EXPECT_EQ(218, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 0) + .bb()); + EXPECT_EQ( + 219, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 0) + .c()); + EXPECT_EQ( + 220, + message.GetExtension(UNITTEST::repeated_import_message_extension, 0).d()); + EXPECT_EQ( + 227, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 0).bb()); +} + +inline void TestUtil::ExpectRepeatedsSwapped( + const UNITTEST::TestAllTypes& message) { + ASSERT_EQ(2, message.repeated_int32_size()); + ASSERT_EQ(2, message.repeated_int64_size()); + ASSERT_EQ(2, message.repeated_uint32_size()); + ASSERT_EQ(2, message.repeated_uint64_size()); + ASSERT_EQ(2, message.repeated_sint32_size()); + ASSERT_EQ(2, message.repeated_sint64_size()); + ASSERT_EQ(2, message.repeated_fixed32_size()); + ASSERT_EQ(2, message.repeated_fixed64_size()); + ASSERT_EQ(2, message.repeated_sfixed32_size()); + ASSERT_EQ(2, message.repeated_sfixed64_size()); + ASSERT_EQ(2, message.repeated_float_size()); + ASSERT_EQ(2, message.repeated_double_size()); + ASSERT_EQ(2, message.repeated_bool_size()); + ASSERT_EQ(2, message.repeated_string_size()); + ASSERT_EQ(2, message.repeated_bytes_size()); + + ASSERT_EQ(2, message.repeatedgroup_size()); + ASSERT_EQ(2, message.repeated_nested_message_size()); + ASSERT_EQ(2, message.repeated_foreign_message_size()); + ASSERT_EQ(2, message.repeated_import_message_size()); + ASSERT_EQ(2, message.repeated_import_message_size()); + ASSERT_EQ(2, message.repeated_nested_enum_size()); + ASSERT_EQ(2, message.repeated_foreign_enum_size()); + ASSERT_EQ(2, message.repeated_import_enum_size()); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + ASSERT_EQ(2, message.repeated_string_piece_size()); + ASSERT_EQ(2, message.repeated_cord_size()); +#endif + + // Test that the first element and second element are flipped. + EXPECT_EQ(201, message.repeated_int32(1)); + EXPECT_EQ(202, message.repeated_int64(1)); + EXPECT_EQ(203, message.repeated_uint32(1)); + EXPECT_EQ(204, message.repeated_uint64(1)); + EXPECT_EQ(205, message.repeated_sint32(1)); + EXPECT_EQ(206, message.repeated_sint64(1)); + EXPECT_EQ(207, message.repeated_fixed32(1)); + EXPECT_EQ(208, message.repeated_fixed64(1)); + EXPECT_EQ(209, message.repeated_sfixed32(1)); + EXPECT_EQ(210, message.repeated_sfixed64(1)); + EXPECT_EQ(211, message.repeated_float(1)); + EXPECT_EQ(212, message.repeated_double(1)); + EXPECT_TRUE(message.repeated_bool(1)); + EXPECT_EQ("215", message.repeated_string(1)); + EXPECT_EQ("216", message.repeated_bytes(1)); + + EXPECT_EQ(217, message.repeatedgroup(1).a()); + EXPECT_EQ(218, message.repeated_nested_message(1).bb()); + EXPECT_EQ(219, message.repeated_foreign_message(1).c()); + EXPECT_EQ(220, message.repeated_import_message(1).d()); + EXPECT_EQ(220, message.repeated_import_message(1).d()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message.repeated_nested_enum(1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.repeated_foreign_enum(1)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, message.repeated_import_enum(1)); + + EXPECT_EQ(301, message.repeated_int32(0)); + EXPECT_EQ(302, message.repeated_int64(0)); + EXPECT_EQ(303, message.repeated_uint32(0)); + EXPECT_EQ(304, message.repeated_uint64(0)); + EXPECT_EQ(305, message.repeated_sint32(0)); + EXPECT_EQ(306, message.repeated_sint64(0)); + EXPECT_EQ(307, message.repeated_fixed32(0)); + EXPECT_EQ(308, message.repeated_fixed64(0)); + EXPECT_EQ(309, message.repeated_sfixed32(0)); + EXPECT_EQ(310, message.repeated_sfixed64(0)); + EXPECT_EQ(311, message.repeated_float(0)); + EXPECT_EQ(312, message.repeated_double(0)); + EXPECT_FALSE(message.repeated_bool(0)); + EXPECT_EQ("315", message.repeated_string(0)); + EXPECT_EQ("316", message.repeated_bytes(0)); + + EXPECT_EQ(317, message.repeatedgroup(0).a()); + EXPECT_EQ(318, message.repeated_nested_message(0).bb()); + EXPECT_EQ(319, message.repeated_foreign_message(0).c()); + EXPECT_EQ(320, message.repeated_import_message(0).d()); + EXPECT_EQ(320, message.repeated_import_message(0).d()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, message.repeated_nested_enum(0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, message.repeated_foreign_enum(0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAZ, message.repeated_import_enum(0)); +} + +inline void TestUtil::ExpectRepeatedExtensionsSwapped( + const UNITTEST::TestAllExtensions& message) { + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_int32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_int64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_uint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_uint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_fixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_fixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sfixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sfixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_float_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_double_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_bool_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_string_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_bytes_extension)); + + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeatedgroup_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_nested_message_extension)); + ASSERT_EQ( + 2, message.ExtensionSize(UNITTEST::repeated_foreign_message_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_import_message_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_lazy_message_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_nested_enum_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_foreign_enum_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_import_enum_extension)); + + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_string_piece_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_cord_extension)); + + EXPECT_EQ(201, message.GetExtension(UNITTEST::repeated_int32_extension, 1)); + EXPECT_EQ(202, message.GetExtension(UNITTEST::repeated_int64_extension, 1)); + EXPECT_EQ(203, message.GetExtension(UNITTEST::repeated_uint32_extension, 1)); + EXPECT_EQ(204, message.GetExtension(UNITTEST::repeated_uint64_extension, 1)); + EXPECT_EQ(205, message.GetExtension(UNITTEST::repeated_sint32_extension, 1)); + EXPECT_EQ(206, message.GetExtension(UNITTEST::repeated_sint64_extension, 1)); + EXPECT_EQ(207, message.GetExtension(UNITTEST::repeated_fixed32_extension, 1)); + EXPECT_EQ(208, message.GetExtension(UNITTEST::repeated_fixed64_extension, 1)); + EXPECT_EQ(209, + message.GetExtension(UNITTEST::repeated_sfixed32_extension, 1)); + EXPECT_EQ(210, + message.GetExtension(UNITTEST::repeated_sfixed64_extension, 1)); + EXPECT_EQ(211, message.GetExtension(UNITTEST::repeated_float_extension, 1)); + EXPECT_EQ(212, message.GetExtension(UNITTEST::repeated_double_extension, 1)); + EXPECT_TRUE(message.GetExtension(UNITTEST::repeated_bool_extension, 1)); + EXPECT_EQ("215", + message.GetExtension(UNITTEST::repeated_string_extension, 1)); + EXPECT_EQ("216", message.GetExtension(UNITTEST::repeated_bytes_extension, 1)); + + EXPECT_EQ(217, + message.GetExtension(UNITTEST::repeatedgroup_extension, 1).a()); + EXPECT_EQ(218, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 1) + .bb()); + EXPECT_EQ( + 219, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 1) + .c()); + EXPECT_EQ( + 220, + message.GetExtension(UNITTEST::repeated_import_message_extension, 1).d()); + EXPECT_EQ( + 227, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 1).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, + message.GetExtension(UNITTEST::repeated_nested_enum_extension, 1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::repeated_foreign_enum_extension, 1)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, + message.GetExtension(UNITTEST::repeated_import_enum_extension, 1)); + + EXPECT_EQ("224", + message.GetExtension(UNITTEST::repeated_string_piece_extension, 1)); + EXPECT_EQ("225", message.GetExtension(UNITTEST::repeated_cord_extension, 1)); + + EXPECT_EQ(301, message.GetExtension(UNITTEST::repeated_int32_extension, 0)); + EXPECT_EQ(302, message.GetExtension(UNITTEST::repeated_int64_extension, 0)); + EXPECT_EQ(303, message.GetExtension(UNITTEST::repeated_uint32_extension, 0)); + EXPECT_EQ(304, message.GetExtension(UNITTEST::repeated_uint64_extension, 0)); + EXPECT_EQ(305, message.GetExtension(UNITTEST::repeated_sint32_extension, 0)); + EXPECT_EQ(306, message.GetExtension(UNITTEST::repeated_sint64_extension, 0)); + EXPECT_EQ(307, message.GetExtension(UNITTEST::repeated_fixed32_extension, 0)); + EXPECT_EQ(308, message.GetExtension(UNITTEST::repeated_fixed64_extension, 0)); + EXPECT_EQ(309, + message.GetExtension(UNITTEST::repeated_sfixed32_extension, 0)); + EXPECT_EQ(310, + message.GetExtension(UNITTEST::repeated_sfixed64_extension, 0)); + EXPECT_EQ(311, message.GetExtension(UNITTEST::repeated_float_extension, 0)); + EXPECT_EQ(312, message.GetExtension(UNITTEST::repeated_double_extension, 0)); + EXPECT_FALSE(message.GetExtension(UNITTEST::repeated_bool_extension, 0)); + EXPECT_EQ("315", + message.GetExtension(UNITTEST::repeated_string_extension, 0)); + EXPECT_EQ("316", message.GetExtension(UNITTEST::repeated_bytes_extension, 0)); + + EXPECT_EQ(317, + message.GetExtension(UNITTEST::repeatedgroup_extension, 0).a()); + EXPECT_EQ(318, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 0) + .bb()); + EXPECT_EQ( + 319, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 0) + .c()); + EXPECT_EQ( + 320, + message.GetExtension(UNITTEST::repeated_import_message_extension, 0).d()); + EXPECT_EQ( + 327, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 0).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, + message.GetExtension(UNITTEST::repeated_nested_enum_extension, 0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, + message.GetExtension(UNITTEST::repeated_foreign_enum_extension, 0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAZ, + message.GetExtension(UNITTEST::repeated_import_enum_extension, 0)); + + EXPECT_EQ("324", + message.GetExtension(UNITTEST::repeated_string_piece_extension, 0)); + EXPECT_EQ("325", message.GetExtension(UNITTEST::repeated_cord_extension, 0)); +} + +inline void TestUtil::SetOneof1(UNITTEST::TestOneof2* message) { + message->mutable_foo_lazy_message()->set_qux_int(100); + message->set_bar_string("101"); + message->set_baz_int(102); + message->set_baz_string("103"); +} + +inline void TestUtil::SetOneof2(UNITTEST::TestOneof2* message) { + message->set_foo_int(200); + message->set_bar_enum(UNITTEST::TestOneof2::BAZ); + message->set_baz_int(202); + message->set_baz_string("203"); +} + +inline void TestUtil::ExpectOneofSet1(const UNITTEST::TestOneof2& message) { + ExpectAtMostOneFieldSetInOneof(message); + + EXPECT_TRUE(message.has_foo_lazy_message()); + EXPECT_TRUE(message.foo_lazy_message().has_qux_int()); + + EXPECT_TRUE(message.has_bar_string()); + EXPECT_TRUE(message.has_baz_int()); + EXPECT_TRUE(message.has_baz_string()); + + ASSERT_EQ(0, message.foo_lazy_message().corge_int_size()); + + EXPECT_EQ(100, message.foo_lazy_message().qux_int()); + EXPECT_EQ("101", message.bar_string()); + EXPECT_EQ(102, message.baz_int()); + EXPECT_EQ("103", message.baz_string()); +} + +inline void TestUtil::ExpectOneofSet2(const UNITTEST::TestOneof2& message) { + ExpectAtMostOneFieldSetInOneof(message); + + EXPECT_TRUE(message.has_foo_int()); + EXPECT_TRUE(message.has_bar_enum()); + EXPECT_TRUE(message.has_baz_int()); + EXPECT_TRUE(message.has_baz_string()); + + EXPECT_EQ(200, message.foo_int()); + EXPECT_EQ(UNITTEST::TestOneof2::BAZ, message.bar_enum()); + EXPECT_EQ(202, message.baz_int()); + EXPECT_EQ("203", message.baz_string()); +} + +inline void TestUtil::ExpectOneofClear(const UNITTEST::TestOneof2& message) { + EXPECT_FALSE(message.has_foo_int()); + EXPECT_FALSE(message.has_foo_string()); + EXPECT_FALSE(message.has_foo_bytes()); + EXPECT_FALSE(message.has_foo_enum()); + EXPECT_FALSE(message.has_foo_message()); + EXPECT_FALSE(message.has_foogroup()); + EXPECT_FALSE(message.has_foo_lazy_message()); + + EXPECT_FALSE(message.has_bar_int()); + EXPECT_FALSE(message.has_bar_string()); + EXPECT_FALSE(message.has_bar_bytes()); + EXPECT_FALSE(message.has_bar_enum()); + + EXPECT_FALSE(message.has_baz_int()); + EXPECT_FALSE(message.has_baz_string()); + + EXPECT_EQ(UNITTEST::TestOneof2::FOO_NOT_SET, message.foo_case()); + EXPECT_EQ(UNITTEST::TestOneof2::BAR_NOT_SET, message.bar_case()); +} + +inline void TestUtil::ExpectAtMostOneFieldSetInOneof( + const UNITTEST::TestOneof2& message) { + int count = 0; + if (message.has_foo_int()) count++; + if (message.has_foo_string()) count++; + if (message.has_foo_bytes()) count++; + if (message.has_foo_enum()) count++; + if (message.has_foo_message()) count++; + if (message.has_foogroup()) count++; + if (message.has_foo_lazy_message()) count++; + EXPECT_LE(count, 1); + count = 0; + if (message.has_bar_int()) count++; + if (message.has_bar_string()) count++; + if (message.has_bar_bytes()) count++; + if (message.has_bar_enum()) count++; + EXPECT_TRUE(count == 0 || count == 1); +} + +// =================================================================== + +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/test_util2.h b/src/google/protobuf/test_util2.h new file mode 100644 index 0000000000000..f12addb3137d0 --- /dev/null +++ b/src/google/protobuf/test_util2.h @@ -0,0 +1,82 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_TEST_UTIL2_H__ +#define GOOGLE_PROTOBUF_TEST_UTIL2_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace TestUtil { + +// Translate net/proto2/* -> google/protobuf/* +inline std::string TranslatePathToOpensource(const std::string& google3_path) { + const std::string prefix = "net/proto2/"; + GOOGLE_CHECK(google3_path.find(prefix) == 0) << google3_path; + std::string path = google3_path.substr(prefix.size()); + + path = StringReplace(path, "internal/", "", false); + path = StringReplace(path, "proto/", "", false); + path = StringReplace(path, "public/", "", false); + return "google/protobuf/" + path; +} + +inline std::string MaybeTranslatePath(const std::string& google3_path) { + std::string path = google3_path; + path = TranslatePathToOpensource(path); + return path; +} + +inline std::string TestSourceDir() { + return google::protobuf::TestSourceDir(); +} + +inline std::string GetTestDataPath(const std::string& google3_path) { + return TestSourceDir() + "/" + MaybeTranslatePath(google3_path); +} + +// Checks the equality of "message" and serialized proto of type "ProtoType". +// Do not directly compare two serialized protos. +template +bool EqualsToSerialized(const ProtoType& message, const std::string& data) { + ProtoType other; + other.ParsePartialFromString(data); + return util::MessageDifferencer::Equals(message, other); +} + +} // namespace TestUtil +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_TEST_UTIL2_H__ diff --git a/src/google/protobuf/test_util_lite.cc b/src/google/protobuf/test_util_lite.cc index 79c5abec6d157..e7eb60a6b7d6f 100644 --- a/src/google/protobuf/test_util_lite.cc +++ b/src/google/protobuf/test_util_lite.cc @@ -33,121 +33,122 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include + #include #include #include - +#include namespace google { namespace protobuf { void TestUtilLite::SetAllFields(unittest::TestAllTypesLite* message) { - message->set_optional_int32 (101); - message->set_optional_int64 (102); - message->set_optional_uint32 (103); - message->set_optional_uint64 (104); - message->set_optional_sint32 (105); - message->set_optional_sint64 (106); - message->set_optional_fixed32 (107); - message->set_optional_fixed64 (108); + message->set_optional_int32(101); + message->set_optional_int64(102); + message->set_optional_uint32(103); + message->set_optional_uint64(104); + message->set_optional_sint32(105); + message->set_optional_sint64(106); + message->set_optional_fixed32(107); + message->set_optional_fixed64(108); message->set_optional_sfixed32(109); message->set_optional_sfixed64(110); - message->set_optional_float (111); - message->set_optional_double (112); - message->set_optional_bool (true); - message->set_optional_string ("115"); - message->set_optional_bytes ("116"); - - message->mutable_optionalgroup ()->set_a(117); - message->mutable_optional_nested_message ()->set_bb(118); - message->mutable_optional_foreign_message ()->set_c(119); - message->mutable_optional_import_message ()->set_d(120); + message->set_optional_float(111); + message->set_optional_double(112); + message->set_optional_bool(true); + message->set_optional_string("115"); + message->set_optional_bytes("116"); + + message->mutable_optionalgroup()->set_a(117); + message->mutable_optional_nested_message()->set_bb(118); + message->mutable_optional_foreign_message()->set_c(119); + message->mutable_optional_import_message()->set_d(120); message->mutable_optional_public_import_message()->set_e(126); - message->mutable_optional_lazy_message ()->set_bb(127); + message->mutable_optional_lazy_message()->set_bb(127); - message->set_optional_nested_enum (unittest::TestAllTypesLite::BAZ ); - message->set_optional_foreign_enum(unittest::FOREIGN_LITE_BAZ ); - message->set_optional_import_enum (unittest_import::IMPORT_LITE_BAZ); + message->set_optional_nested_enum(unittest::TestAllTypesLite::BAZ); + message->set_optional_foreign_enum(unittest::FOREIGN_LITE_BAZ); + message->set_optional_import_enum(unittest_import::IMPORT_LITE_BAZ); // ----------------------------------------------------------------- - message->add_repeated_int32 (201); - message->add_repeated_int64 (202); - message->add_repeated_uint32 (203); - message->add_repeated_uint64 (204); - message->add_repeated_sint32 (205); - message->add_repeated_sint64 (206); - message->add_repeated_fixed32 (207); - message->add_repeated_fixed64 (208); + message->add_repeated_int32(201); + message->add_repeated_int64(202); + message->add_repeated_uint32(203); + message->add_repeated_uint64(204); + message->add_repeated_sint32(205); + message->add_repeated_sint64(206); + message->add_repeated_fixed32(207); + message->add_repeated_fixed64(208); message->add_repeated_sfixed32(209); message->add_repeated_sfixed64(210); - message->add_repeated_float (211); - message->add_repeated_double (212); - message->add_repeated_bool (true); - message->add_repeated_string ("215"); - message->add_repeated_bytes ("216"); - - message->add_repeatedgroup ()->set_a(217); - message->add_repeated_nested_message ()->set_bb(218); + message->add_repeated_float(211); + message->add_repeated_double(212); + message->add_repeated_bool(true); + message->add_repeated_string("215"); + message->add_repeated_bytes("216"); + + message->add_repeatedgroup()->set_a(217); + message->add_repeated_nested_message()->set_bb(218); message->add_repeated_foreign_message()->set_c(219); - message->add_repeated_import_message ()->set_d(220); - message->add_repeated_lazy_message ()->set_bb(227); + message->add_repeated_import_message()->set_d(220); + message->add_repeated_lazy_message()->set_bb(227); - message->add_repeated_nested_enum (unittest::TestAllTypesLite::BAR ); - message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAR ); - message->add_repeated_import_enum (unittest_import::IMPORT_LITE_BAR); + message->add_repeated_nested_enum(unittest::TestAllTypesLite::BAR); + message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAR); + message->add_repeated_import_enum(unittest_import::IMPORT_LITE_BAR); // Add a second one of each field. - message->add_repeated_int32 (301); - message->add_repeated_int64 (302); - message->add_repeated_uint32 (303); - message->add_repeated_uint64 (304); - message->add_repeated_sint32 (305); - message->add_repeated_sint64 (306); - message->add_repeated_fixed32 (307); - message->add_repeated_fixed64 (308); + message->add_repeated_int32(301); + message->add_repeated_int64(302); + message->add_repeated_uint32(303); + message->add_repeated_uint64(304); + message->add_repeated_sint32(305); + message->add_repeated_sint64(306); + message->add_repeated_fixed32(307); + message->add_repeated_fixed64(308); message->add_repeated_sfixed32(309); message->add_repeated_sfixed64(310); - message->add_repeated_float (311); - message->add_repeated_double (312); - message->add_repeated_bool (false); - message->add_repeated_string ("315"); - message->add_repeated_bytes ("316"); - - message->add_repeatedgroup ()->set_a(317); - message->add_repeated_nested_message ()->set_bb(318); + message->add_repeated_float(311); + message->add_repeated_double(312); + message->add_repeated_bool(false); + message->add_repeated_string("315"); + message->add_repeated_bytes("316"); + + message->add_repeatedgroup()->set_a(317); + message->add_repeated_nested_message()->set_bb(318); message->add_repeated_foreign_message()->set_c(319); - message->add_repeated_import_message ()->set_d(320); - message->add_repeated_lazy_message ()->set_bb(327); + message->add_repeated_import_message()->set_d(320); + message->add_repeated_lazy_message()->set_bb(327); - message->add_repeated_nested_enum (unittest::TestAllTypesLite::BAZ ); - message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAZ ); - message->add_repeated_import_enum (unittest_import::IMPORT_LITE_BAZ); + message->add_repeated_nested_enum(unittest::TestAllTypesLite::BAZ); + message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAZ); + message->add_repeated_import_enum(unittest_import::IMPORT_LITE_BAZ); // ----------------------------------------------------------------- - message->set_default_int32 (401); - message->set_default_int64 (402); - message->set_default_uint32 (403); - message->set_default_uint64 (404); - message->set_default_sint32 (405); - message->set_default_sint64 (406); - message->set_default_fixed32 (407); - message->set_default_fixed64 (408); + message->set_default_int32(401); + message->set_default_int64(402); + message->set_default_uint32(403); + message->set_default_uint64(404); + message->set_default_sint32(405); + message->set_default_sint64(406); + message->set_default_fixed32(407); + message->set_default_fixed64(408); message->set_default_sfixed32(409); message->set_default_sfixed64(410); - message->set_default_float (411); - message->set_default_double (412); - message->set_default_bool (false); - message->set_default_string ("415"); - message->set_default_bytes ("416"); + message->set_default_float(411); + message->set_default_double(412); + message->set_default_bool(false); + message->set_default_string("415"); + message->set_default_bytes("416"); - message->set_default_nested_enum (unittest::TestAllTypesLite::FOO ); - message->set_default_foreign_enum(unittest::FOREIGN_LITE_FOO ); - message->set_default_import_enum (unittest_import::IMPORT_LITE_FOO); + message->set_default_nested_enum(unittest::TestAllTypesLite::FOO); + message->set_default_foreign_enum(unittest::FOREIGN_LITE_FOO); + message->set_default_import_enum(unittest_import::IMPORT_LITE_FOO); message->set_oneof_uint32(601); @@ -159,31 +160,31 @@ void TestUtilLite::SetAllFields(unittest::TestAllTypesLite* message) { // ------------------------------------------------------------------- void TestUtilLite::ModifyRepeatedFields(unittest::TestAllTypesLite* message) { - message->set_repeated_int32 (1, 501); - message->set_repeated_int64 (1, 502); - message->set_repeated_uint32 (1, 503); - message->set_repeated_uint64 (1, 504); - message->set_repeated_sint32 (1, 505); - message->set_repeated_sint64 (1, 506); - message->set_repeated_fixed32 (1, 507); - message->set_repeated_fixed64 (1, 508); + message->set_repeated_int32(1, 501); + message->set_repeated_int64(1, 502); + message->set_repeated_uint32(1, 503); + message->set_repeated_uint64(1, 504); + message->set_repeated_sint32(1, 505); + message->set_repeated_sint64(1, 506); + message->set_repeated_fixed32(1, 507); + message->set_repeated_fixed64(1, 508); message->set_repeated_sfixed32(1, 509); message->set_repeated_sfixed64(1, 510); - message->set_repeated_float (1, 511); - message->set_repeated_double (1, 512); - message->set_repeated_bool (1, true); - message->set_repeated_string (1, "515"); - message->set_repeated_bytes (1, "516"); - - message->mutable_repeatedgroup (1)->set_a(517); - message->mutable_repeated_nested_message (1)->set_bb(518); + message->set_repeated_float(1, 511); + message->set_repeated_double(1, 512); + message->set_repeated_bool(1, true); + message->set_repeated_string(1, "515"); + message->set_repeated_bytes(1, "516"); + + message->mutable_repeatedgroup(1)->set_a(517); + message->mutable_repeated_nested_message(1)->set_bb(518); message->mutable_repeated_foreign_message(1)->set_c(519); - message->mutable_repeated_import_message (1)->set_d(520); - message->mutable_repeated_lazy_message (1)->set_bb(527); + message->mutable_repeated_import_message(1)->set_d(520); + message->mutable_repeated_lazy_message(1)->set_bb(527); - message->set_repeated_nested_enum (1, unittest::TestAllTypesLite::FOO ); - message->set_repeated_foreign_enum(1, unittest::FOREIGN_LITE_FOO ); - message->set_repeated_import_enum (1, unittest_import::IMPORT_LITE_FOO); + message->set_repeated_nested_enum(1, unittest::TestAllTypesLite::FOO); + message->set_repeated_foreign_enum(1, unittest::FOREIGN_LITE_FOO); + message->set_repeated_import_enum(1, unittest_import::IMPORT_LITE_FOO); } @@ -191,199 +192,199 @@ void TestUtilLite::ModifyRepeatedFields(unittest::TestAllTypesLite* message) { void TestUtilLite::ExpectAllFieldsSet( const unittest::TestAllTypesLite& message) { - EXPECT_TRUE(message.has_optional_int32 ()); - EXPECT_TRUE(message.has_optional_int64 ()); - EXPECT_TRUE(message.has_optional_uint32 ()); - EXPECT_TRUE(message.has_optional_uint64 ()); - EXPECT_TRUE(message.has_optional_sint32 ()); - EXPECT_TRUE(message.has_optional_sint64 ()); - EXPECT_TRUE(message.has_optional_fixed32 ()); - EXPECT_TRUE(message.has_optional_fixed64 ()); + EXPECT_TRUE(message.has_optional_int32()); + EXPECT_TRUE(message.has_optional_int64()); + EXPECT_TRUE(message.has_optional_uint32()); + EXPECT_TRUE(message.has_optional_uint64()); + EXPECT_TRUE(message.has_optional_sint32()); + EXPECT_TRUE(message.has_optional_sint64()); + EXPECT_TRUE(message.has_optional_fixed32()); + EXPECT_TRUE(message.has_optional_fixed64()); EXPECT_TRUE(message.has_optional_sfixed32()); EXPECT_TRUE(message.has_optional_sfixed64()); - EXPECT_TRUE(message.has_optional_float ()); - EXPECT_TRUE(message.has_optional_double ()); - EXPECT_TRUE(message.has_optional_bool ()); - EXPECT_TRUE(message.has_optional_string ()); - EXPECT_TRUE(message.has_optional_bytes ()); - - EXPECT_TRUE(message.has_optionalgroup ()); - EXPECT_TRUE(message.has_optional_nested_message ()); - EXPECT_TRUE(message.has_optional_foreign_message ()); - EXPECT_TRUE(message.has_optional_import_message ()); + EXPECT_TRUE(message.has_optional_float()); + EXPECT_TRUE(message.has_optional_double()); + EXPECT_TRUE(message.has_optional_bool()); + EXPECT_TRUE(message.has_optional_string()); + EXPECT_TRUE(message.has_optional_bytes()); + + EXPECT_TRUE(message.has_optionalgroup()); + EXPECT_TRUE(message.has_optional_nested_message()); + EXPECT_TRUE(message.has_optional_foreign_message()); + EXPECT_TRUE(message.has_optional_import_message()); EXPECT_TRUE(message.has_optional_public_import_message()); - EXPECT_TRUE(message.has_optional_lazy_message ()); + EXPECT_TRUE(message.has_optional_lazy_message()); - EXPECT_TRUE(message.optionalgroup ().has_a()); - EXPECT_TRUE(message.optional_nested_message ().has_bb()); - EXPECT_TRUE(message.optional_foreign_message ().has_c()); - EXPECT_TRUE(message.optional_import_message ().has_d()); + EXPECT_TRUE(message.optionalgroup().has_a()); + EXPECT_TRUE(message.optional_nested_message().has_bb()); + EXPECT_TRUE(message.optional_foreign_message().has_c()); + EXPECT_TRUE(message.optional_import_message().has_d()); EXPECT_TRUE(message.optional_public_import_message().has_e()); - EXPECT_TRUE(message.optional_lazy_message ().has_bb()); + EXPECT_TRUE(message.optional_lazy_message().has_bb()); - EXPECT_TRUE(message.has_optional_nested_enum ()); + EXPECT_TRUE(message.has_optional_nested_enum()); EXPECT_TRUE(message.has_optional_foreign_enum()); - EXPECT_TRUE(message.has_optional_import_enum ()); - - - EXPECT_EQ(101 , message.optional_int32 ()); - EXPECT_EQ(102 , message.optional_int64 ()); - EXPECT_EQ(103 , message.optional_uint32 ()); - EXPECT_EQ(104 , message.optional_uint64 ()); - EXPECT_EQ(105 , message.optional_sint32 ()); - EXPECT_EQ(106 , message.optional_sint64 ()); - EXPECT_EQ(107 , message.optional_fixed32 ()); - EXPECT_EQ(108 , message.optional_fixed64 ()); - EXPECT_EQ(109 , message.optional_sfixed32()); - EXPECT_EQ(110 , message.optional_sfixed64()); - EXPECT_EQ(111 , message.optional_float ()); - EXPECT_EQ(112 , message.optional_double ()); - EXPECT_EQ(true , message.optional_bool ()); - EXPECT_EQ("115", message.optional_string ()); - EXPECT_EQ("116", message.optional_bytes ()); - - EXPECT_EQ(117, message.optionalgroup ().a()); - EXPECT_EQ(118, message.optional_nested_message ().bb()); - EXPECT_EQ(119, message.optional_foreign_message ().c()); - EXPECT_EQ(120, message.optional_import_message ().d()); + EXPECT_TRUE(message.has_optional_import_enum()); + + + EXPECT_EQ(101, message.optional_int32()); + EXPECT_EQ(102, message.optional_int64()); + EXPECT_EQ(103, message.optional_uint32()); + EXPECT_EQ(104, message.optional_uint64()); + EXPECT_EQ(105, message.optional_sint32()); + EXPECT_EQ(106, message.optional_sint64()); + EXPECT_EQ(107, message.optional_fixed32()); + EXPECT_EQ(108, message.optional_fixed64()); + EXPECT_EQ(109, message.optional_sfixed32()); + EXPECT_EQ(110, message.optional_sfixed64()); + EXPECT_EQ(111, message.optional_float()); + EXPECT_EQ(112, message.optional_double()); + EXPECT_EQ(true, message.optional_bool()); + EXPECT_EQ("115", message.optional_string()); + EXPECT_EQ("116", message.optional_bytes()); + + EXPECT_EQ(117, message.optionalgroup().a()); + EXPECT_EQ(118, message.optional_nested_message().bb()); + EXPECT_EQ(119, message.optional_foreign_message().c()); + EXPECT_EQ(120, message.optional_import_message().d()); EXPECT_EQ(126, message.optional_public_import_message().e()); - EXPECT_EQ(127, message.optional_lazy_message ().bb()); + EXPECT_EQ(127, message.optional_lazy_message().bb()); - EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.optional_nested_enum ()); - EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.optional_foreign_enum()); - EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.optional_import_enum ()); + EXPECT_EQ(unittest::TestAllTypesLite::BAZ, message.optional_nested_enum()); + EXPECT_EQ(unittest::FOREIGN_LITE_BAZ, message.optional_foreign_enum()); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.optional_import_enum()); // ----------------------------------------------------------------- - ASSERT_EQ(2, message.repeated_int32_size ()); - ASSERT_EQ(2, message.repeated_int64_size ()); - ASSERT_EQ(2, message.repeated_uint32_size ()); - ASSERT_EQ(2, message.repeated_uint64_size ()); - ASSERT_EQ(2, message.repeated_sint32_size ()); - ASSERT_EQ(2, message.repeated_sint64_size ()); - ASSERT_EQ(2, message.repeated_fixed32_size ()); - ASSERT_EQ(2, message.repeated_fixed64_size ()); + ASSERT_EQ(2, message.repeated_int32_size()); + ASSERT_EQ(2, message.repeated_int64_size()); + ASSERT_EQ(2, message.repeated_uint32_size()); + ASSERT_EQ(2, message.repeated_uint64_size()); + ASSERT_EQ(2, message.repeated_sint32_size()); + ASSERT_EQ(2, message.repeated_sint64_size()); + ASSERT_EQ(2, message.repeated_fixed32_size()); + ASSERT_EQ(2, message.repeated_fixed64_size()); ASSERT_EQ(2, message.repeated_sfixed32_size()); ASSERT_EQ(2, message.repeated_sfixed64_size()); - ASSERT_EQ(2, message.repeated_float_size ()); - ASSERT_EQ(2, message.repeated_double_size ()); - ASSERT_EQ(2, message.repeated_bool_size ()); - ASSERT_EQ(2, message.repeated_string_size ()); - ASSERT_EQ(2, message.repeated_bytes_size ()); - - ASSERT_EQ(2, message.repeatedgroup_size ()); - ASSERT_EQ(2, message.repeated_nested_message_size ()); + ASSERT_EQ(2, message.repeated_float_size()); + ASSERT_EQ(2, message.repeated_double_size()); + ASSERT_EQ(2, message.repeated_bool_size()); + ASSERT_EQ(2, message.repeated_string_size()); + ASSERT_EQ(2, message.repeated_bytes_size()); + + ASSERT_EQ(2, message.repeatedgroup_size()); + ASSERT_EQ(2, message.repeated_nested_message_size()); ASSERT_EQ(2, message.repeated_foreign_message_size()); - ASSERT_EQ(2, message.repeated_import_message_size ()); - ASSERT_EQ(2, message.repeated_lazy_message_size ()); - ASSERT_EQ(2, message.repeated_nested_enum_size ()); - ASSERT_EQ(2, message.repeated_foreign_enum_size ()); - ASSERT_EQ(2, message.repeated_import_enum_size ()); - - - EXPECT_EQ(201 , message.repeated_int32 (0)); - EXPECT_EQ(202 , message.repeated_int64 (0)); - EXPECT_EQ(203 , message.repeated_uint32 (0)); - EXPECT_EQ(204 , message.repeated_uint64 (0)); - EXPECT_EQ(205 , message.repeated_sint32 (0)); - EXPECT_EQ(206 , message.repeated_sint64 (0)); - EXPECT_EQ(207 , message.repeated_fixed32 (0)); - EXPECT_EQ(208 , message.repeated_fixed64 (0)); - EXPECT_EQ(209 , message.repeated_sfixed32(0)); - EXPECT_EQ(210 , message.repeated_sfixed64(0)); - EXPECT_EQ(211 , message.repeated_float (0)); - EXPECT_EQ(212 , message.repeated_double (0)); - EXPECT_EQ(true , message.repeated_bool (0)); - EXPECT_EQ("215", message.repeated_string (0)); - EXPECT_EQ("216", message.repeated_bytes (0)); - - EXPECT_EQ(217, message.repeatedgroup (0).a()); - EXPECT_EQ(218, message.repeated_nested_message (0).bb()); + ASSERT_EQ(2, message.repeated_import_message_size()); + ASSERT_EQ(2, message.repeated_lazy_message_size()); + ASSERT_EQ(2, message.repeated_nested_enum_size()); + ASSERT_EQ(2, message.repeated_foreign_enum_size()); + ASSERT_EQ(2, message.repeated_import_enum_size()); + + + EXPECT_EQ(201, message.repeated_int32(0)); + EXPECT_EQ(202, message.repeated_int64(0)); + EXPECT_EQ(203, message.repeated_uint32(0)); + EXPECT_EQ(204, message.repeated_uint64(0)); + EXPECT_EQ(205, message.repeated_sint32(0)); + EXPECT_EQ(206, message.repeated_sint64(0)); + EXPECT_EQ(207, message.repeated_fixed32(0)); + EXPECT_EQ(208, message.repeated_fixed64(0)); + EXPECT_EQ(209, message.repeated_sfixed32(0)); + EXPECT_EQ(210, message.repeated_sfixed64(0)); + EXPECT_EQ(211, message.repeated_float(0)); + EXPECT_EQ(212, message.repeated_double(0)); + EXPECT_EQ(true, message.repeated_bool(0)); + EXPECT_EQ("215", message.repeated_string(0)); + EXPECT_EQ("216", message.repeated_bytes(0)); + + EXPECT_EQ(217, message.repeatedgroup(0).a()); + EXPECT_EQ(218, message.repeated_nested_message(0).bb()); EXPECT_EQ(219, message.repeated_foreign_message(0).c()); - EXPECT_EQ(220, message.repeated_import_message (0).d()); - EXPECT_EQ(227, message.repeated_lazy_message (0).bb()); - - - EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.repeated_nested_enum (0)); - EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.repeated_foreign_enum(0)); - EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.repeated_import_enum (0)); - - EXPECT_EQ(301 , message.repeated_int32 (1)); - EXPECT_EQ(302 , message.repeated_int64 (1)); - EXPECT_EQ(303 , message.repeated_uint32 (1)); - EXPECT_EQ(304 , message.repeated_uint64 (1)); - EXPECT_EQ(305 , message.repeated_sint32 (1)); - EXPECT_EQ(306 , message.repeated_sint64 (1)); - EXPECT_EQ(307 , message.repeated_fixed32 (1)); - EXPECT_EQ(308 , message.repeated_fixed64 (1)); - EXPECT_EQ(309 , message.repeated_sfixed32(1)); - EXPECT_EQ(310 , message.repeated_sfixed64(1)); - EXPECT_EQ(311 , message.repeated_float (1)); - EXPECT_EQ(312 , message.repeated_double (1)); - EXPECT_EQ(false, message.repeated_bool (1)); - EXPECT_EQ("315", message.repeated_string (1)); - EXPECT_EQ("316", message.repeated_bytes (1)); - - EXPECT_EQ(317, message.repeatedgroup (1).a()); - EXPECT_EQ(318, message.repeated_nested_message (1).bb()); + EXPECT_EQ(220, message.repeated_import_message(0).d()); + EXPECT_EQ(227, message.repeated_lazy_message(0).bb()); + + + EXPECT_EQ(unittest::TestAllTypesLite::BAR, message.repeated_nested_enum(0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR, message.repeated_foreign_enum(0)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.repeated_import_enum(0)); + + EXPECT_EQ(301, message.repeated_int32(1)); + EXPECT_EQ(302, message.repeated_int64(1)); + EXPECT_EQ(303, message.repeated_uint32(1)); + EXPECT_EQ(304, message.repeated_uint64(1)); + EXPECT_EQ(305, message.repeated_sint32(1)); + EXPECT_EQ(306, message.repeated_sint64(1)); + EXPECT_EQ(307, message.repeated_fixed32(1)); + EXPECT_EQ(308, message.repeated_fixed64(1)); + EXPECT_EQ(309, message.repeated_sfixed32(1)); + EXPECT_EQ(310, message.repeated_sfixed64(1)); + EXPECT_EQ(311, message.repeated_float(1)); + EXPECT_EQ(312, message.repeated_double(1)); + EXPECT_EQ(false, message.repeated_bool(1)); + EXPECT_EQ("315", message.repeated_string(1)); + EXPECT_EQ("316", message.repeated_bytes(1)); + + EXPECT_EQ(317, message.repeatedgroup(1).a()); + EXPECT_EQ(318, message.repeated_nested_message(1).bb()); EXPECT_EQ(319, message.repeated_foreign_message(1).c()); - EXPECT_EQ(320, message.repeated_import_message (1).d()); - EXPECT_EQ(327, message.repeated_lazy_message (1).bb()); + EXPECT_EQ(320, message.repeated_import_message(1).d()); + EXPECT_EQ(327, message.repeated_lazy_message(1).bb()); - EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.repeated_nested_enum (1)); - EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.repeated_foreign_enum(1)); - EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.repeated_import_enum (1)); + EXPECT_EQ(unittest::TestAllTypesLite::BAZ, message.repeated_nested_enum(1)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAZ, message.repeated_foreign_enum(1)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.repeated_import_enum(1)); // ----------------------------------------------------------------- - EXPECT_TRUE(message.has_default_int32 ()); - EXPECT_TRUE(message.has_default_int64 ()); - EXPECT_TRUE(message.has_default_uint32 ()); - EXPECT_TRUE(message.has_default_uint64 ()); - EXPECT_TRUE(message.has_default_sint32 ()); - EXPECT_TRUE(message.has_default_sint64 ()); - EXPECT_TRUE(message.has_default_fixed32 ()); - EXPECT_TRUE(message.has_default_fixed64 ()); + EXPECT_TRUE(message.has_default_int32()); + EXPECT_TRUE(message.has_default_int64()); + EXPECT_TRUE(message.has_default_uint32()); + EXPECT_TRUE(message.has_default_uint64()); + EXPECT_TRUE(message.has_default_sint32()); + EXPECT_TRUE(message.has_default_sint64()); + EXPECT_TRUE(message.has_default_fixed32()); + EXPECT_TRUE(message.has_default_fixed64()); EXPECT_TRUE(message.has_default_sfixed32()); EXPECT_TRUE(message.has_default_sfixed64()); - EXPECT_TRUE(message.has_default_float ()); - EXPECT_TRUE(message.has_default_double ()); - EXPECT_TRUE(message.has_default_bool ()); - EXPECT_TRUE(message.has_default_string ()); - EXPECT_TRUE(message.has_default_bytes ()); + EXPECT_TRUE(message.has_default_float()); + EXPECT_TRUE(message.has_default_double()); + EXPECT_TRUE(message.has_default_bool()); + EXPECT_TRUE(message.has_default_string()); + EXPECT_TRUE(message.has_default_bytes()); - EXPECT_TRUE(message.has_default_nested_enum ()); + EXPECT_TRUE(message.has_default_nested_enum()); EXPECT_TRUE(message.has_default_foreign_enum()); - EXPECT_TRUE(message.has_default_import_enum ()); - - - EXPECT_EQ(401 , message.default_int32 ()); - EXPECT_EQ(402 , message.default_int64 ()); - EXPECT_EQ(403 , message.default_uint32 ()); - EXPECT_EQ(404 , message.default_uint64 ()); - EXPECT_EQ(405 , message.default_sint32 ()); - EXPECT_EQ(406 , message.default_sint64 ()); - EXPECT_EQ(407 , message.default_fixed32 ()); - EXPECT_EQ(408 , message.default_fixed64 ()); - EXPECT_EQ(409 , message.default_sfixed32()); - EXPECT_EQ(410 , message.default_sfixed64()); - EXPECT_EQ(411 , message.default_float ()); - EXPECT_EQ(412 , message.default_double ()); - EXPECT_EQ(false, message.default_bool ()); - EXPECT_EQ("415", message.default_string ()); - EXPECT_EQ("416", message.default_bytes ()); - - EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.default_nested_enum ()); - EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.default_foreign_enum()); - EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.default_import_enum ()); - - - EXPECT_FALSE(message.has_oneof_uint32 ()); + EXPECT_TRUE(message.has_default_import_enum()); + + + EXPECT_EQ(401, message.default_int32()); + EXPECT_EQ(402, message.default_int64()); + EXPECT_EQ(403, message.default_uint32()); + EXPECT_EQ(404, message.default_uint64()); + EXPECT_EQ(405, message.default_sint32()); + EXPECT_EQ(406, message.default_sint64()); + EXPECT_EQ(407, message.default_fixed32()); + EXPECT_EQ(408, message.default_fixed64()); + EXPECT_EQ(409, message.default_sfixed32()); + EXPECT_EQ(410, message.default_sfixed64()); + EXPECT_EQ(411, message.default_float()); + EXPECT_EQ(412, message.default_double()); + EXPECT_EQ(false, message.default_bool()); + EXPECT_EQ("415", message.default_string()); + EXPECT_EQ("416", message.default_bytes()); + + EXPECT_EQ(unittest::TestAllTypesLite::FOO, message.default_nested_enum()); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO, message.default_foreign_enum()); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.default_import_enum()); + + + EXPECT_FALSE(message.has_oneof_uint32()); EXPECT_FALSE(message.has_oneof_nested_message()); - EXPECT_FALSE(message.has_oneof_string ()); - EXPECT_TRUE(message.has_oneof_bytes ()); + EXPECT_FALSE(message.has_oneof_string()); + EXPECT_TRUE(message.has_oneof_bytes()); EXPECT_EQ("604", message.oneof_bytes()); } @@ -392,145 +393,145 @@ void TestUtilLite::ExpectAllFieldsSet( void TestUtilLite::ExpectClear(const unittest::TestAllTypesLite& message) { // has_blah() should initially be false for all optional fields. - EXPECT_FALSE(message.has_optional_int32 ()); - EXPECT_FALSE(message.has_optional_int64 ()); - EXPECT_FALSE(message.has_optional_uint32 ()); - EXPECT_FALSE(message.has_optional_uint64 ()); - EXPECT_FALSE(message.has_optional_sint32 ()); - EXPECT_FALSE(message.has_optional_sint64 ()); - EXPECT_FALSE(message.has_optional_fixed32 ()); - EXPECT_FALSE(message.has_optional_fixed64 ()); + EXPECT_FALSE(message.has_optional_int32()); + EXPECT_FALSE(message.has_optional_int64()); + EXPECT_FALSE(message.has_optional_uint32()); + EXPECT_FALSE(message.has_optional_uint64()); + EXPECT_FALSE(message.has_optional_sint32()); + EXPECT_FALSE(message.has_optional_sint64()); + EXPECT_FALSE(message.has_optional_fixed32()); + EXPECT_FALSE(message.has_optional_fixed64()); EXPECT_FALSE(message.has_optional_sfixed32()); EXPECT_FALSE(message.has_optional_sfixed64()); - EXPECT_FALSE(message.has_optional_float ()); - EXPECT_FALSE(message.has_optional_double ()); - EXPECT_FALSE(message.has_optional_bool ()); - EXPECT_FALSE(message.has_optional_string ()); - EXPECT_FALSE(message.has_optional_bytes ()); - - EXPECT_FALSE(message.has_optionalgroup ()); - EXPECT_FALSE(message.has_optional_nested_message ()); - EXPECT_FALSE(message.has_optional_foreign_message ()); - EXPECT_FALSE(message.has_optional_import_message ()); + EXPECT_FALSE(message.has_optional_float()); + EXPECT_FALSE(message.has_optional_double()); + EXPECT_FALSE(message.has_optional_bool()); + EXPECT_FALSE(message.has_optional_string()); + EXPECT_FALSE(message.has_optional_bytes()); + + EXPECT_FALSE(message.has_optionalgroup()); + EXPECT_FALSE(message.has_optional_nested_message()); + EXPECT_FALSE(message.has_optional_foreign_message()); + EXPECT_FALSE(message.has_optional_import_message()); EXPECT_FALSE(message.has_optional_public_import_message()); - EXPECT_FALSE(message.has_optional_lazy_message ()); + EXPECT_FALSE(message.has_optional_lazy_message()); - EXPECT_FALSE(message.has_optional_nested_enum ()); + EXPECT_FALSE(message.has_optional_nested_enum()); EXPECT_FALSE(message.has_optional_foreign_enum()); - EXPECT_FALSE(message.has_optional_import_enum ()); + EXPECT_FALSE(message.has_optional_import_enum()); // Optional fields without defaults are set to zero or something like it. - EXPECT_EQ(0 , message.optional_int32 ()); - EXPECT_EQ(0 , message.optional_int64 ()); - EXPECT_EQ(0 , message.optional_uint32 ()); - EXPECT_EQ(0 , message.optional_uint64 ()); - EXPECT_EQ(0 , message.optional_sint32 ()); - EXPECT_EQ(0 , message.optional_sint64 ()); - EXPECT_EQ(0 , message.optional_fixed32 ()); - EXPECT_EQ(0 , message.optional_fixed64 ()); - EXPECT_EQ(0 , message.optional_sfixed32()); - EXPECT_EQ(0 , message.optional_sfixed64()); - EXPECT_EQ(0 , message.optional_float ()); - EXPECT_EQ(0 , message.optional_double ()); - EXPECT_EQ(false, message.optional_bool ()); - EXPECT_EQ("" , message.optional_string ()); - EXPECT_EQ("" , message.optional_bytes ()); + EXPECT_EQ(0, message.optional_int32()); + EXPECT_EQ(0, message.optional_int64()); + EXPECT_EQ(0, message.optional_uint32()); + EXPECT_EQ(0, message.optional_uint64()); + EXPECT_EQ(0, message.optional_sint32()); + EXPECT_EQ(0, message.optional_sint64()); + EXPECT_EQ(0, message.optional_fixed32()); + EXPECT_EQ(0, message.optional_fixed64()); + EXPECT_EQ(0, message.optional_sfixed32()); + EXPECT_EQ(0, message.optional_sfixed64()); + EXPECT_EQ(0, message.optional_float()); + EXPECT_EQ(0, message.optional_double()); + EXPECT_EQ(false, message.optional_bool()); + EXPECT_EQ("", message.optional_string()); + EXPECT_EQ("", message.optional_bytes()); // Embedded messages should also be clear. - EXPECT_FALSE(message.optionalgroup ().has_a()); - EXPECT_FALSE(message.optional_nested_message ().has_bb()); - EXPECT_FALSE(message.optional_foreign_message ().has_c()); - EXPECT_FALSE(message.optional_import_message ().has_d()); + EXPECT_FALSE(message.optionalgroup().has_a()); + EXPECT_FALSE(message.optional_nested_message().has_bb()); + EXPECT_FALSE(message.optional_foreign_message().has_c()); + EXPECT_FALSE(message.optional_import_message().has_d()); EXPECT_FALSE(message.optional_public_import_message().has_e()); - EXPECT_FALSE(message.optional_lazy_message ().has_bb()); + EXPECT_FALSE(message.optional_lazy_message().has_bb()); - EXPECT_EQ(0, message.optionalgroup ().a()); - EXPECT_EQ(0, message.optional_nested_message ().bb()); + EXPECT_EQ(0, message.optionalgroup().a()); + EXPECT_EQ(0, message.optional_nested_message().bb()); EXPECT_EQ(0, message.optional_foreign_message().c()); - EXPECT_EQ(0, message.optional_import_message ().d()); + EXPECT_EQ(0, message.optional_import_message().d()); // Enums without defaults are set to the first value in the enum. - EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.optional_nested_enum ()); - EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.optional_foreign_enum()); - EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.optional_import_enum ()); + EXPECT_EQ(unittest::TestAllTypesLite::FOO, message.optional_nested_enum()); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO, message.optional_foreign_enum()); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.optional_import_enum()); // Repeated fields are empty. - EXPECT_EQ(0, message.repeated_int32_size ()); - EXPECT_EQ(0, message.repeated_int64_size ()); - EXPECT_EQ(0, message.repeated_uint32_size ()); - EXPECT_EQ(0, message.repeated_uint64_size ()); - EXPECT_EQ(0, message.repeated_sint32_size ()); - EXPECT_EQ(0, message.repeated_sint64_size ()); - EXPECT_EQ(0, message.repeated_fixed32_size ()); - EXPECT_EQ(0, message.repeated_fixed64_size ()); + EXPECT_EQ(0, message.repeated_int32_size()); + EXPECT_EQ(0, message.repeated_int64_size()); + EXPECT_EQ(0, message.repeated_uint32_size()); + EXPECT_EQ(0, message.repeated_uint64_size()); + EXPECT_EQ(0, message.repeated_sint32_size()); + EXPECT_EQ(0, message.repeated_sint64_size()); + EXPECT_EQ(0, message.repeated_fixed32_size()); + EXPECT_EQ(0, message.repeated_fixed64_size()); EXPECT_EQ(0, message.repeated_sfixed32_size()); EXPECT_EQ(0, message.repeated_sfixed64_size()); - EXPECT_EQ(0, message.repeated_float_size ()); - EXPECT_EQ(0, message.repeated_double_size ()); - EXPECT_EQ(0, message.repeated_bool_size ()); - EXPECT_EQ(0, message.repeated_string_size ()); - EXPECT_EQ(0, message.repeated_bytes_size ()); - - EXPECT_EQ(0, message.repeatedgroup_size ()); - EXPECT_EQ(0, message.repeated_nested_message_size ()); + EXPECT_EQ(0, message.repeated_float_size()); + EXPECT_EQ(0, message.repeated_double_size()); + EXPECT_EQ(0, message.repeated_bool_size()); + EXPECT_EQ(0, message.repeated_string_size()); + EXPECT_EQ(0, message.repeated_bytes_size()); + + EXPECT_EQ(0, message.repeatedgroup_size()); + EXPECT_EQ(0, message.repeated_nested_message_size()); EXPECT_EQ(0, message.repeated_foreign_message_size()); - EXPECT_EQ(0, message.repeated_import_message_size ()); - EXPECT_EQ(0, message.repeated_lazy_message_size ()); - EXPECT_EQ(0, message.repeated_nested_enum_size ()); - EXPECT_EQ(0, message.repeated_foreign_enum_size ()); - EXPECT_EQ(0, message.repeated_import_enum_size ()); + EXPECT_EQ(0, message.repeated_import_message_size()); + EXPECT_EQ(0, message.repeated_lazy_message_size()); + EXPECT_EQ(0, message.repeated_nested_enum_size()); + EXPECT_EQ(0, message.repeated_foreign_enum_size()); + EXPECT_EQ(0, message.repeated_import_enum_size()); // has_blah() should also be false for all default fields. - EXPECT_FALSE(message.has_default_int32 ()); - EXPECT_FALSE(message.has_default_int64 ()); - EXPECT_FALSE(message.has_default_uint32 ()); - EXPECT_FALSE(message.has_default_uint64 ()); - EXPECT_FALSE(message.has_default_sint32 ()); - EXPECT_FALSE(message.has_default_sint64 ()); - EXPECT_FALSE(message.has_default_fixed32 ()); - EXPECT_FALSE(message.has_default_fixed64 ()); + EXPECT_FALSE(message.has_default_int32()); + EXPECT_FALSE(message.has_default_int64()); + EXPECT_FALSE(message.has_default_uint32()); + EXPECT_FALSE(message.has_default_uint64()); + EXPECT_FALSE(message.has_default_sint32()); + EXPECT_FALSE(message.has_default_sint64()); + EXPECT_FALSE(message.has_default_fixed32()); + EXPECT_FALSE(message.has_default_fixed64()); EXPECT_FALSE(message.has_default_sfixed32()); EXPECT_FALSE(message.has_default_sfixed64()); - EXPECT_FALSE(message.has_default_float ()); - EXPECT_FALSE(message.has_default_double ()); - EXPECT_FALSE(message.has_default_bool ()); - EXPECT_FALSE(message.has_default_string ()); - EXPECT_FALSE(message.has_default_bytes ()); + EXPECT_FALSE(message.has_default_float()); + EXPECT_FALSE(message.has_default_double()); + EXPECT_FALSE(message.has_default_bool()); + EXPECT_FALSE(message.has_default_string()); + EXPECT_FALSE(message.has_default_bytes()); - EXPECT_FALSE(message.has_default_nested_enum ()); + EXPECT_FALSE(message.has_default_nested_enum()); EXPECT_FALSE(message.has_default_foreign_enum()); - EXPECT_FALSE(message.has_default_import_enum ()); + EXPECT_FALSE(message.has_default_import_enum()); // Fields with defaults have their default values (duh). - EXPECT_EQ( 41 , message.default_int32 ()); - EXPECT_EQ( 42 , message.default_int64 ()); - EXPECT_EQ( 43 , message.default_uint32 ()); - EXPECT_EQ( 44 , message.default_uint64 ()); - EXPECT_EQ(-45 , message.default_sint32 ()); - EXPECT_EQ( 46 , message.default_sint64 ()); - EXPECT_EQ( 47 , message.default_fixed32 ()); - EXPECT_EQ( 48 , message.default_fixed64 ()); - EXPECT_EQ( 49 , message.default_sfixed32()); - EXPECT_EQ(-50 , message.default_sfixed64()); - EXPECT_EQ( 51.5 , message.default_float ()); - EXPECT_EQ( 52e3 , message.default_double ()); - EXPECT_EQ(true , message.default_bool ()); - EXPECT_EQ("hello", message.default_string ()); - EXPECT_EQ("world", message.default_bytes ()); - - EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.default_nested_enum ()); - EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.default_foreign_enum()); - EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.default_import_enum ()); - - - EXPECT_FALSE(message.has_oneof_uint32 ()); + EXPECT_EQ(41, message.default_int32()); + EXPECT_EQ(42, message.default_int64()); + EXPECT_EQ(43, message.default_uint32()); + EXPECT_EQ(44, message.default_uint64()); + EXPECT_EQ(-45, message.default_sint32()); + EXPECT_EQ(46, message.default_sint64()); + EXPECT_EQ(47, message.default_fixed32()); + EXPECT_EQ(48, message.default_fixed64()); + EXPECT_EQ(49, message.default_sfixed32()); + EXPECT_EQ(-50, message.default_sfixed64()); + EXPECT_EQ(51.5, message.default_float()); + EXPECT_EQ(52e3, message.default_double()); + EXPECT_EQ(true, message.default_bool()); + EXPECT_EQ("hello", message.default_string()); + EXPECT_EQ("world", message.default_bytes()); + + EXPECT_EQ(unittest::TestAllTypesLite::BAR, message.default_nested_enum()); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR, message.default_foreign_enum()); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.default_import_enum()); + + + EXPECT_FALSE(message.has_oneof_uint32()); EXPECT_FALSE(message.has_oneof_nested_message()); - EXPECT_FALSE(message.has_oneof_string ()); - EXPECT_FALSE(message.has_oneof_bytes ()); + EXPECT_FALSE(message.has_oneof_string()); + EXPECT_FALSE(message.has_oneof_bytes()); } // ------------------------------------------------------------------- @@ -540,188 +541,188 @@ void TestUtilLite::ExpectRepeatedFieldsModified( // ModifyRepeatedFields only sets the second repeated element of each // field. In addition to verifying this, we also verify that the first // element and size were *not* modified. - ASSERT_EQ(2, message.repeated_int32_size ()); - ASSERT_EQ(2, message.repeated_int64_size ()); - ASSERT_EQ(2, message.repeated_uint32_size ()); - ASSERT_EQ(2, message.repeated_uint64_size ()); - ASSERT_EQ(2, message.repeated_sint32_size ()); - ASSERT_EQ(2, message.repeated_sint64_size ()); - ASSERT_EQ(2, message.repeated_fixed32_size ()); - ASSERT_EQ(2, message.repeated_fixed64_size ()); + ASSERT_EQ(2, message.repeated_int32_size()); + ASSERT_EQ(2, message.repeated_int64_size()); + ASSERT_EQ(2, message.repeated_uint32_size()); + ASSERT_EQ(2, message.repeated_uint64_size()); + ASSERT_EQ(2, message.repeated_sint32_size()); + ASSERT_EQ(2, message.repeated_sint64_size()); + ASSERT_EQ(2, message.repeated_fixed32_size()); + ASSERT_EQ(2, message.repeated_fixed64_size()); ASSERT_EQ(2, message.repeated_sfixed32_size()); ASSERT_EQ(2, message.repeated_sfixed64_size()); - ASSERT_EQ(2, message.repeated_float_size ()); - ASSERT_EQ(2, message.repeated_double_size ()); - ASSERT_EQ(2, message.repeated_bool_size ()); - ASSERT_EQ(2, message.repeated_string_size ()); - ASSERT_EQ(2, message.repeated_bytes_size ()); - - ASSERT_EQ(2, message.repeatedgroup_size ()); - ASSERT_EQ(2, message.repeated_nested_message_size ()); + ASSERT_EQ(2, message.repeated_float_size()); + ASSERT_EQ(2, message.repeated_double_size()); + ASSERT_EQ(2, message.repeated_bool_size()); + ASSERT_EQ(2, message.repeated_string_size()); + ASSERT_EQ(2, message.repeated_bytes_size()); + + ASSERT_EQ(2, message.repeatedgroup_size()); + ASSERT_EQ(2, message.repeated_nested_message_size()); ASSERT_EQ(2, message.repeated_foreign_message_size()); - ASSERT_EQ(2, message.repeated_import_message_size ()); - ASSERT_EQ(2, message.repeated_lazy_message_size ()); - ASSERT_EQ(2, message.repeated_nested_enum_size ()); - ASSERT_EQ(2, message.repeated_foreign_enum_size ()); - ASSERT_EQ(2, message.repeated_import_enum_size ()); - - - EXPECT_EQ(201 , message.repeated_int32 (0)); - EXPECT_EQ(202 , message.repeated_int64 (0)); - EXPECT_EQ(203 , message.repeated_uint32 (0)); - EXPECT_EQ(204 , message.repeated_uint64 (0)); - EXPECT_EQ(205 , message.repeated_sint32 (0)); - EXPECT_EQ(206 , message.repeated_sint64 (0)); - EXPECT_EQ(207 , message.repeated_fixed32 (0)); - EXPECT_EQ(208 , message.repeated_fixed64 (0)); - EXPECT_EQ(209 , message.repeated_sfixed32(0)); - EXPECT_EQ(210 , message.repeated_sfixed64(0)); - EXPECT_EQ(211 , message.repeated_float (0)); - EXPECT_EQ(212 , message.repeated_double (0)); - EXPECT_EQ(true , message.repeated_bool (0)); - EXPECT_EQ("215", message.repeated_string (0)); - EXPECT_EQ("216", message.repeated_bytes (0)); - - EXPECT_EQ(217, message.repeatedgroup (0).a()); - EXPECT_EQ(218, message.repeated_nested_message (0).bb()); + ASSERT_EQ(2, message.repeated_import_message_size()); + ASSERT_EQ(2, message.repeated_lazy_message_size()); + ASSERT_EQ(2, message.repeated_nested_enum_size()); + ASSERT_EQ(2, message.repeated_foreign_enum_size()); + ASSERT_EQ(2, message.repeated_import_enum_size()); + + + EXPECT_EQ(201, message.repeated_int32(0)); + EXPECT_EQ(202, message.repeated_int64(0)); + EXPECT_EQ(203, message.repeated_uint32(0)); + EXPECT_EQ(204, message.repeated_uint64(0)); + EXPECT_EQ(205, message.repeated_sint32(0)); + EXPECT_EQ(206, message.repeated_sint64(0)); + EXPECT_EQ(207, message.repeated_fixed32(0)); + EXPECT_EQ(208, message.repeated_fixed64(0)); + EXPECT_EQ(209, message.repeated_sfixed32(0)); + EXPECT_EQ(210, message.repeated_sfixed64(0)); + EXPECT_EQ(211, message.repeated_float(0)); + EXPECT_EQ(212, message.repeated_double(0)); + EXPECT_EQ(true, message.repeated_bool(0)); + EXPECT_EQ("215", message.repeated_string(0)); + EXPECT_EQ("216", message.repeated_bytes(0)); + + EXPECT_EQ(217, message.repeatedgroup(0).a()); + EXPECT_EQ(218, message.repeated_nested_message(0).bb()); EXPECT_EQ(219, message.repeated_foreign_message(0).c()); - EXPECT_EQ(220, message.repeated_import_message (0).d()); - EXPECT_EQ(227, message.repeated_lazy_message (0).bb()); + EXPECT_EQ(220, message.repeated_import_message(0).d()); + EXPECT_EQ(227, message.repeated_lazy_message(0).bb()); - EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.repeated_nested_enum (0)); - EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.repeated_foreign_enum(0)); - EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.repeated_import_enum (0)); + EXPECT_EQ(unittest::TestAllTypesLite::BAR, message.repeated_nested_enum(0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR, message.repeated_foreign_enum(0)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.repeated_import_enum(0)); // Actually verify the second (modified) elements now. - EXPECT_EQ(501 , message.repeated_int32 (1)); - EXPECT_EQ(502 , message.repeated_int64 (1)); - EXPECT_EQ(503 , message.repeated_uint32 (1)); - EXPECT_EQ(504 , message.repeated_uint64 (1)); - EXPECT_EQ(505 , message.repeated_sint32 (1)); - EXPECT_EQ(506 , message.repeated_sint64 (1)); - EXPECT_EQ(507 , message.repeated_fixed32 (1)); - EXPECT_EQ(508 , message.repeated_fixed64 (1)); - EXPECT_EQ(509 , message.repeated_sfixed32(1)); - EXPECT_EQ(510 , message.repeated_sfixed64(1)); - EXPECT_EQ(511 , message.repeated_float (1)); - EXPECT_EQ(512 , message.repeated_double (1)); - EXPECT_EQ(true , message.repeated_bool (1)); - EXPECT_EQ("515", message.repeated_string (1)); - EXPECT_EQ("516", message.repeated_bytes (1)); - - EXPECT_EQ(517, message.repeatedgroup (1).a()); - EXPECT_EQ(518, message.repeated_nested_message (1).bb()); + EXPECT_EQ(501, message.repeated_int32(1)); + EXPECT_EQ(502, message.repeated_int64(1)); + EXPECT_EQ(503, message.repeated_uint32(1)); + EXPECT_EQ(504, message.repeated_uint64(1)); + EXPECT_EQ(505, message.repeated_sint32(1)); + EXPECT_EQ(506, message.repeated_sint64(1)); + EXPECT_EQ(507, message.repeated_fixed32(1)); + EXPECT_EQ(508, message.repeated_fixed64(1)); + EXPECT_EQ(509, message.repeated_sfixed32(1)); + EXPECT_EQ(510, message.repeated_sfixed64(1)); + EXPECT_EQ(511, message.repeated_float(1)); + EXPECT_EQ(512, message.repeated_double(1)); + EXPECT_EQ(true, message.repeated_bool(1)); + EXPECT_EQ("515", message.repeated_string(1)); + EXPECT_EQ("516", message.repeated_bytes(1)); + + EXPECT_EQ(517, message.repeatedgroup(1).a()); + EXPECT_EQ(518, message.repeated_nested_message(1).bb()); EXPECT_EQ(519, message.repeated_foreign_message(1).c()); - EXPECT_EQ(520, message.repeated_import_message (1).d()); - EXPECT_EQ(527, message.repeated_lazy_message (1).bb()); + EXPECT_EQ(520, message.repeated_import_message(1).d()); + EXPECT_EQ(527, message.repeated_lazy_message(1).bb()); - EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.repeated_nested_enum (1)); - EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.repeated_foreign_enum(1)); - EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.repeated_import_enum (1)); + EXPECT_EQ(unittest::TestAllTypesLite::FOO, message.repeated_nested_enum(1)); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO, message.repeated_foreign_enum(1)); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.repeated_import_enum(1)); } // ------------------------------------------------------------------- void TestUtilLite::SetPackedFields(unittest::TestPackedTypesLite* message) { - message->add_packed_int32 (601); - message->add_packed_int64 (602); - message->add_packed_uint32 (603); - message->add_packed_uint64 (604); - message->add_packed_sint32 (605); - message->add_packed_sint64 (606); - message->add_packed_fixed32 (607); - message->add_packed_fixed64 (608); + message->add_packed_int32(601); + message->add_packed_int64(602); + message->add_packed_uint32(603); + message->add_packed_uint64(604); + message->add_packed_sint32(605); + message->add_packed_sint64(606); + message->add_packed_fixed32(607); + message->add_packed_fixed64(608); message->add_packed_sfixed32(609); message->add_packed_sfixed64(610); - message->add_packed_float (611); - message->add_packed_double (612); - message->add_packed_bool (true); - message->add_packed_enum (unittest::FOREIGN_LITE_BAR); + message->add_packed_float(611); + message->add_packed_double(612); + message->add_packed_bool(true); + message->add_packed_enum(unittest::FOREIGN_LITE_BAR); // add a second one of each field - message->add_packed_int32 (701); - message->add_packed_int64 (702); - message->add_packed_uint32 (703); - message->add_packed_uint64 (704); - message->add_packed_sint32 (705); - message->add_packed_sint64 (706); - message->add_packed_fixed32 (707); - message->add_packed_fixed64 (708); + message->add_packed_int32(701); + message->add_packed_int64(702); + message->add_packed_uint32(703); + message->add_packed_uint64(704); + message->add_packed_sint32(705); + message->add_packed_sint64(706); + message->add_packed_fixed32(707); + message->add_packed_fixed64(708); message->add_packed_sfixed32(709); message->add_packed_sfixed64(710); - message->add_packed_float (711); - message->add_packed_double (712); - message->add_packed_bool (false); - message->add_packed_enum (unittest::FOREIGN_LITE_BAZ); + message->add_packed_float(711); + message->add_packed_double(712); + message->add_packed_bool(false); + message->add_packed_enum(unittest::FOREIGN_LITE_BAZ); } // ------------------------------------------------------------------- void TestUtilLite::ModifyPackedFields(unittest::TestPackedTypesLite* message) { - message->set_packed_int32 (1, 801); - message->set_packed_int64 (1, 802); - message->set_packed_uint32 (1, 803); - message->set_packed_uint64 (1, 804); - message->set_packed_sint32 (1, 805); - message->set_packed_sint64 (1, 806); - message->set_packed_fixed32 (1, 807); - message->set_packed_fixed64 (1, 808); + message->set_packed_int32(1, 801); + message->set_packed_int64(1, 802); + message->set_packed_uint32(1, 803); + message->set_packed_uint64(1, 804); + message->set_packed_sint32(1, 805); + message->set_packed_sint64(1, 806); + message->set_packed_fixed32(1, 807); + message->set_packed_fixed64(1, 808); message->set_packed_sfixed32(1, 809); message->set_packed_sfixed64(1, 810); - message->set_packed_float (1, 811); - message->set_packed_double (1, 812); - message->set_packed_bool (1, true); - message->set_packed_enum (1, unittest::FOREIGN_LITE_FOO); + message->set_packed_float(1, 811); + message->set_packed_double(1, 812); + message->set_packed_bool(1, true); + message->set_packed_enum(1, unittest::FOREIGN_LITE_FOO); } // ------------------------------------------------------------------- void TestUtilLite::ExpectPackedFieldsSet( const unittest::TestPackedTypesLite& message) { - ASSERT_EQ(2, message.packed_int32_size ()); - ASSERT_EQ(2, message.packed_int64_size ()); - ASSERT_EQ(2, message.packed_uint32_size ()); - ASSERT_EQ(2, message.packed_uint64_size ()); - ASSERT_EQ(2, message.packed_sint32_size ()); - ASSERT_EQ(2, message.packed_sint64_size ()); - ASSERT_EQ(2, message.packed_fixed32_size ()); - ASSERT_EQ(2, message.packed_fixed64_size ()); + ASSERT_EQ(2, message.packed_int32_size()); + ASSERT_EQ(2, message.packed_int64_size()); + ASSERT_EQ(2, message.packed_uint32_size()); + ASSERT_EQ(2, message.packed_uint64_size()); + ASSERT_EQ(2, message.packed_sint32_size()); + ASSERT_EQ(2, message.packed_sint64_size()); + ASSERT_EQ(2, message.packed_fixed32_size()); + ASSERT_EQ(2, message.packed_fixed64_size()); ASSERT_EQ(2, message.packed_sfixed32_size()); ASSERT_EQ(2, message.packed_sfixed64_size()); - ASSERT_EQ(2, message.packed_float_size ()); - ASSERT_EQ(2, message.packed_double_size ()); - ASSERT_EQ(2, message.packed_bool_size ()); - ASSERT_EQ(2, message.packed_enum_size ()); - - EXPECT_EQ(601 , message.packed_int32 (0)); - EXPECT_EQ(602 , message.packed_int64 (0)); - EXPECT_EQ(603 , message.packed_uint32 (0)); - EXPECT_EQ(604 , message.packed_uint64 (0)); - EXPECT_EQ(605 , message.packed_sint32 (0)); - EXPECT_EQ(606 , message.packed_sint64 (0)); - EXPECT_EQ(607 , message.packed_fixed32 (0)); - EXPECT_EQ(608 , message.packed_fixed64 (0)); - EXPECT_EQ(609 , message.packed_sfixed32(0)); - EXPECT_EQ(610 , message.packed_sfixed64(0)); - EXPECT_EQ(611 , message.packed_float (0)); - EXPECT_EQ(612 , message.packed_double (0)); - EXPECT_EQ(true , message.packed_bool (0)); + ASSERT_EQ(2, message.packed_float_size()); + ASSERT_EQ(2, message.packed_double_size()); + ASSERT_EQ(2, message.packed_bool_size()); + ASSERT_EQ(2, message.packed_enum_size()); + + EXPECT_EQ(601, message.packed_int32(0)); + EXPECT_EQ(602, message.packed_int64(0)); + EXPECT_EQ(603, message.packed_uint32(0)); + EXPECT_EQ(604, message.packed_uint64(0)); + EXPECT_EQ(605, message.packed_sint32(0)); + EXPECT_EQ(606, message.packed_sint64(0)); + EXPECT_EQ(607, message.packed_fixed32(0)); + EXPECT_EQ(608, message.packed_fixed64(0)); + EXPECT_EQ(609, message.packed_sfixed32(0)); + EXPECT_EQ(610, message.packed_sfixed64(0)); + EXPECT_EQ(611, message.packed_float(0)); + EXPECT_EQ(612, message.packed_double(0)); + EXPECT_EQ(true, message.packed_bool(0)); EXPECT_EQ(unittest::FOREIGN_LITE_BAR, message.packed_enum(0)); - EXPECT_EQ(701 , message.packed_int32 (1)); - EXPECT_EQ(702 , message.packed_int64 (1)); - EXPECT_EQ(703 , message.packed_uint32 (1)); - EXPECT_EQ(704 , message.packed_uint64 (1)); - EXPECT_EQ(705 , message.packed_sint32 (1)); - EXPECT_EQ(706 , message.packed_sint64 (1)); - EXPECT_EQ(707 , message.packed_fixed32 (1)); - EXPECT_EQ(708 , message.packed_fixed64 (1)); - EXPECT_EQ(709 , message.packed_sfixed32(1)); - EXPECT_EQ(710 , message.packed_sfixed64(1)); - EXPECT_EQ(711 , message.packed_float (1)); - EXPECT_EQ(712 , message.packed_double (1)); - EXPECT_EQ(false, message.packed_bool (1)); + EXPECT_EQ(701, message.packed_int32(1)); + EXPECT_EQ(702, message.packed_int64(1)); + EXPECT_EQ(703, message.packed_uint32(1)); + EXPECT_EQ(704, message.packed_uint64(1)); + EXPECT_EQ(705, message.packed_sint32(1)); + EXPECT_EQ(706, message.packed_sint64(1)); + EXPECT_EQ(707, message.packed_fixed32(1)); + EXPECT_EQ(708, message.packed_fixed64(1)); + EXPECT_EQ(709, message.packed_sfixed32(1)); + EXPECT_EQ(710, message.packed_sfixed64(1)); + EXPECT_EQ(711, message.packed_float(1)); + EXPECT_EQ(712, message.packed_double(1)); + EXPECT_EQ(false, message.packed_bool(1)); EXPECT_EQ(unittest::FOREIGN_LITE_BAZ, message.packed_enum(1)); } @@ -730,20 +731,20 @@ void TestUtilLite::ExpectPackedFieldsSet( void TestUtilLite::ExpectPackedClear( const unittest::TestPackedTypesLite& message) { // Packed repeated fields are empty. - EXPECT_EQ(0, message.packed_int32_size ()); - EXPECT_EQ(0, message.packed_int64_size ()); - EXPECT_EQ(0, message.packed_uint32_size ()); - EXPECT_EQ(0, message.packed_uint64_size ()); - EXPECT_EQ(0, message.packed_sint32_size ()); - EXPECT_EQ(0, message.packed_sint64_size ()); - EXPECT_EQ(0, message.packed_fixed32_size ()); - EXPECT_EQ(0, message.packed_fixed64_size ()); + EXPECT_EQ(0, message.packed_int32_size()); + EXPECT_EQ(0, message.packed_int64_size()); + EXPECT_EQ(0, message.packed_uint32_size()); + EXPECT_EQ(0, message.packed_uint64_size()); + EXPECT_EQ(0, message.packed_sint32_size()); + EXPECT_EQ(0, message.packed_sint64_size()); + EXPECT_EQ(0, message.packed_fixed32_size()); + EXPECT_EQ(0, message.packed_fixed64_size()); EXPECT_EQ(0, message.packed_sfixed32_size()); EXPECT_EQ(0, message.packed_sfixed64_size()); - EXPECT_EQ(0, message.packed_float_size ()); - EXPECT_EQ(0, message.packed_double_size ()); - EXPECT_EQ(0, message.packed_bool_size ()); - EXPECT_EQ(0, message.packed_enum_size ()); + EXPECT_EQ(0, message.packed_float_size()); + EXPECT_EQ(0, message.packed_double_size()); + EXPECT_EQ(0, message.packed_bool_size()); + EXPECT_EQ(0, message.packed_enum_size()); } // ------------------------------------------------------------------- @@ -751,49 +752,49 @@ void TestUtilLite::ExpectPackedClear( void TestUtilLite::ExpectPackedFieldsModified( const unittest::TestPackedTypesLite& message) { // Do the same for packed repeated fields. - ASSERT_EQ(2, message.packed_int32_size ()); - ASSERT_EQ(2, message.packed_int64_size ()); - ASSERT_EQ(2, message.packed_uint32_size ()); - ASSERT_EQ(2, message.packed_uint64_size ()); - ASSERT_EQ(2, message.packed_sint32_size ()); - ASSERT_EQ(2, message.packed_sint64_size ()); - ASSERT_EQ(2, message.packed_fixed32_size ()); - ASSERT_EQ(2, message.packed_fixed64_size ()); + ASSERT_EQ(2, message.packed_int32_size()); + ASSERT_EQ(2, message.packed_int64_size()); + ASSERT_EQ(2, message.packed_uint32_size()); + ASSERT_EQ(2, message.packed_uint64_size()); + ASSERT_EQ(2, message.packed_sint32_size()); + ASSERT_EQ(2, message.packed_sint64_size()); + ASSERT_EQ(2, message.packed_fixed32_size()); + ASSERT_EQ(2, message.packed_fixed64_size()); ASSERT_EQ(2, message.packed_sfixed32_size()); ASSERT_EQ(2, message.packed_sfixed64_size()); - ASSERT_EQ(2, message.packed_float_size ()); - ASSERT_EQ(2, message.packed_double_size ()); - ASSERT_EQ(2, message.packed_bool_size ()); - ASSERT_EQ(2, message.packed_enum_size ()); - - EXPECT_EQ(601 , message.packed_int32 (0)); - EXPECT_EQ(602 , message.packed_int64 (0)); - EXPECT_EQ(603 , message.packed_uint32 (0)); - EXPECT_EQ(604 , message.packed_uint64 (0)); - EXPECT_EQ(605 , message.packed_sint32 (0)); - EXPECT_EQ(606 , message.packed_sint64 (0)); - EXPECT_EQ(607 , message.packed_fixed32 (0)); - EXPECT_EQ(608 , message.packed_fixed64 (0)); - EXPECT_EQ(609 , message.packed_sfixed32(0)); - EXPECT_EQ(610 , message.packed_sfixed64(0)); - EXPECT_EQ(611 , message.packed_float (0)); - EXPECT_EQ(612 , message.packed_double (0)); - EXPECT_EQ(true , message.packed_bool (0)); + ASSERT_EQ(2, message.packed_float_size()); + ASSERT_EQ(2, message.packed_double_size()); + ASSERT_EQ(2, message.packed_bool_size()); + ASSERT_EQ(2, message.packed_enum_size()); + + EXPECT_EQ(601, message.packed_int32(0)); + EXPECT_EQ(602, message.packed_int64(0)); + EXPECT_EQ(603, message.packed_uint32(0)); + EXPECT_EQ(604, message.packed_uint64(0)); + EXPECT_EQ(605, message.packed_sint32(0)); + EXPECT_EQ(606, message.packed_sint64(0)); + EXPECT_EQ(607, message.packed_fixed32(0)); + EXPECT_EQ(608, message.packed_fixed64(0)); + EXPECT_EQ(609, message.packed_sfixed32(0)); + EXPECT_EQ(610, message.packed_sfixed64(0)); + EXPECT_EQ(611, message.packed_float(0)); + EXPECT_EQ(612, message.packed_double(0)); + EXPECT_EQ(true, message.packed_bool(0)); EXPECT_EQ(unittest::FOREIGN_LITE_BAR, message.packed_enum(0)); // Actually verify the second (modified) elements now. - EXPECT_EQ(801 , message.packed_int32 (1)); - EXPECT_EQ(802 , message.packed_int64 (1)); - EXPECT_EQ(803 , message.packed_uint32 (1)); - EXPECT_EQ(804 , message.packed_uint64 (1)); - EXPECT_EQ(805 , message.packed_sint32 (1)); - EXPECT_EQ(806 , message.packed_sint64 (1)); - EXPECT_EQ(807 , message.packed_fixed32 (1)); - EXPECT_EQ(808 , message.packed_fixed64 (1)); - EXPECT_EQ(809 , message.packed_sfixed32(1)); - EXPECT_EQ(810 , message.packed_sfixed64(1)); - EXPECT_EQ(811 , message.packed_float (1)); - EXPECT_EQ(812 , message.packed_double (1)); - EXPECT_EQ(true , message.packed_bool (1)); + EXPECT_EQ(801, message.packed_int32(1)); + EXPECT_EQ(802, message.packed_int64(1)); + EXPECT_EQ(803, message.packed_uint32(1)); + EXPECT_EQ(804, message.packed_uint64(1)); + EXPECT_EQ(805, message.packed_sint32(1)); + EXPECT_EQ(806, message.packed_sint64(1)); + EXPECT_EQ(807, message.packed_fixed32(1)); + EXPECT_EQ(808, message.packed_fixed64(1)); + EXPECT_EQ(809, message.packed_sfixed32(1)); + EXPECT_EQ(810, message.packed_sfixed64(1)); + EXPECT_EQ(811, message.packed_float(1)); + EXPECT_EQ(812, message.packed_double(1)); + EXPECT_EQ(true, message.packed_bool(1)); EXPECT_EQ(unittest::FOREIGN_LITE_FOO, message.packed_enum(1)); } @@ -806,116 +807,145 @@ void TestUtilLite::ExpectPackedFieldsModified( // I gave up on the 80-char limit here. Sorry. void TestUtilLite::SetAllExtensions(unittest::TestAllExtensionsLite* message) { - message->SetExtension(unittest::optional_int32_extension_lite , 101); - message->SetExtension(unittest::optional_int64_extension_lite , 102); - message->SetExtension(unittest::optional_uint32_extension_lite , 103); - message->SetExtension(unittest::optional_uint64_extension_lite , 104); - message->SetExtension(unittest::optional_sint32_extension_lite , 105); - message->SetExtension(unittest::optional_sint64_extension_lite , 106); - message->SetExtension(unittest::optional_fixed32_extension_lite , 107); - message->SetExtension(unittest::optional_fixed64_extension_lite , 108); + message->SetExtension(unittest::optional_int32_extension_lite, 101); + message->SetExtension(unittest::optional_int64_extension_lite, 102); + message->SetExtension(unittest::optional_uint32_extension_lite, 103); + message->SetExtension(unittest::optional_uint64_extension_lite, 104); + message->SetExtension(unittest::optional_sint32_extension_lite, 105); + message->SetExtension(unittest::optional_sint64_extension_lite, 106); + message->SetExtension(unittest::optional_fixed32_extension_lite, 107); + message->SetExtension(unittest::optional_fixed64_extension_lite, 108); message->SetExtension(unittest::optional_sfixed32_extension_lite, 109); message->SetExtension(unittest::optional_sfixed64_extension_lite, 110); - message->SetExtension(unittest::optional_float_extension_lite , 111); - message->SetExtension(unittest::optional_double_extension_lite , 112); - message->SetExtension(unittest::optional_bool_extension_lite , true); - message->SetExtension(unittest::optional_string_extension_lite , "115"); - message->SetExtension(unittest::optional_bytes_extension_lite , "116"); - - message->MutableExtension(unittest::optionalgroup_extension_lite )->set_a(117); - message->MutableExtension(unittest::optional_nested_message_extension_lite )->set_bb(118); - message->MutableExtension(unittest::optional_foreign_message_extension_lite )->set_c(119); - message->MutableExtension(unittest::optional_import_message_extension_lite )->set_d(120); - message->MutableExtension(unittest::optional_public_import_message_extension_lite)->set_e(126); - message->MutableExtension(unittest::optional_lazy_message_extension_lite )->set_bb(127); - - message->SetExtension(unittest::optional_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ ); - message->SetExtension(unittest::optional_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ ); - message->SetExtension(unittest::optional_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAZ); + message->SetExtension(unittest::optional_float_extension_lite, 111); + message->SetExtension(unittest::optional_double_extension_lite, 112); + message->SetExtension(unittest::optional_bool_extension_lite, true); + message->SetExtension(unittest::optional_string_extension_lite, "115"); + message->SetExtension(unittest::optional_bytes_extension_lite, "116"); + + message->MutableExtension(unittest::optionalgroup_extension_lite)->set_a(117); + message->MutableExtension(unittest::optional_nested_message_extension_lite) + ->set_bb(118); + message->MutableExtension(unittest::optional_foreign_message_extension_lite) + ->set_c(119); + message->MutableExtension(unittest::optional_import_message_extension_lite) + ->set_d(120); + message + ->MutableExtension( + unittest::optional_public_import_message_extension_lite) + ->set_e(126); + message->MutableExtension(unittest::optional_lazy_message_extension_lite) + ->set_bb(127); + + message->SetExtension(unittest::optional_nested_enum_extension_lite, + unittest::TestAllTypesLite::BAZ); + message->SetExtension(unittest::optional_foreign_enum_extension_lite, + unittest::FOREIGN_LITE_BAZ); + message->SetExtension(unittest::optional_import_enum_extension_lite, + unittest_import::IMPORT_LITE_BAZ); // ----------------------------------------------------------------- - message->AddExtension(unittest::repeated_int32_extension_lite , 201); - message->AddExtension(unittest::repeated_int64_extension_lite , 202); - message->AddExtension(unittest::repeated_uint32_extension_lite , 203); - message->AddExtension(unittest::repeated_uint64_extension_lite , 204); - message->AddExtension(unittest::repeated_sint32_extension_lite , 205); - message->AddExtension(unittest::repeated_sint64_extension_lite , 206); - message->AddExtension(unittest::repeated_fixed32_extension_lite , 207); - message->AddExtension(unittest::repeated_fixed64_extension_lite , 208); + message->AddExtension(unittest::repeated_int32_extension_lite, 201); + message->AddExtension(unittest::repeated_int64_extension_lite, 202); + message->AddExtension(unittest::repeated_uint32_extension_lite, 203); + message->AddExtension(unittest::repeated_uint64_extension_lite, 204); + message->AddExtension(unittest::repeated_sint32_extension_lite, 205); + message->AddExtension(unittest::repeated_sint64_extension_lite, 206); + message->AddExtension(unittest::repeated_fixed32_extension_lite, 207); + message->AddExtension(unittest::repeated_fixed64_extension_lite, 208); message->AddExtension(unittest::repeated_sfixed32_extension_lite, 209); message->AddExtension(unittest::repeated_sfixed64_extension_lite, 210); - message->AddExtension(unittest::repeated_float_extension_lite , 211); - message->AddExtension(unittest::repeated_double_extension_lite , 212); - message->AddExtension(unittest::repeated_bool_extension_lite , true); - message->AddExtension(unittest::repeated_string_extension_lite , "215"); - message->AddExtension(unittest::repeated_bytes_extension_lite , "216"); - - message->AddExtension(unittest::repeatedgroup_extension_lite )->set_a(217); - message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(218); - message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(219); - message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(220); - message->AddExtension(unittest::repeated_lazy_message_extension_lite )->set_bb(227); - - message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAR ); - message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAR ); - message->AddExtension(unittest::repeated_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAR); + message->AddExtension(unittest::repeated_float_extension_lite, 211); + message->AddExtension(unittest::repeated_double_extension_lite, 212); + message->AddExtension(unittest::repeated_bool_extension_lite, true); + message->AddExtension(unittest::repeated_string_extension_lite, "215"); + message->AddExtension(unittest::repeated_bytes_extension_lite, "216"); + + message->AddExtension(unittest::repeatedgroup_extension_lite)->set_a(217); + message->AddExtension(unittest::repeated_nested_message_extension_lite) + ->set_bb(218); + message->AddExtension(unittest::repeated_foreign_message_extension_lite) + ->set_c(219); + message->AddExtension(unittest::repeated_import_message_extension_lite) + ->set_d(220); + message->AddExtension(unittest::repeated_lazy_message_extension_lite) + ->set_bb(227); + + message->AddExtension(unittest::repeated_nested_enum_extension_lite, + unittest::TestAllTypesLite::BAR); + message->AddExtension(unittest::repeated_foreign_enum_extension_lite, + unittest::FOREIGN_LITE_BAR); + message->AddExtension(unittest::repeated_import_enum_extension_lite, + unittest_import::IMPORT_LITE_BAR); // Add a second one of each field. - message->AddExtension(unittest::repeated_int32_extension_lite , 301); - message->AddExtension(unittest::repeated_int64_extension_lite , 302); - message->AddExtension(unittest::repeated_uint32_extension_lite , 303); - message->AddExtension(unittest::repeated_uint64_extension_lite , 304); - message->AddExtension(unittest::repeated_sint32_extension_lite , 305); - message->AddExtension(unittest::repeated_sint64_extension_lite , 306); - message->AddExtension(unittest::repeated_fixed32_extension_lite , 307); - message->AddExtension(unittest::repeated_fixed64_extension_lite , 308); + message->AddExtension(unittest::repeated_int32_extension_lite, 301); + message->AddExtension(unittest::repeated_int64_extension_lite, 302); + message->AddExtension(unittest::repeated_uint32_extension_lite, 303); + message->AddExtension(unittest::repeated_uint64_extension_lite, 304); + message->AddExtension(unittest::repeated_sint32_extension_lite, 305); + message->AddExtension(unittest::repeated_sint64_extension_lite, 306); + message->AddExtension(unittest::repeated_fixed32_extension_lite, 307); + message->AddExtension(unittest::repeated_fixed64_extension_lite, 308); message->AddExtension(unittest::repeated_sfixed32_extension_lite, 309); message->AddExtension(unittest::repeated_sfixed64_extension_lite, 310); - message->AddExtension(unittest::repeated_float_extension_lite , 311); - message->AddExtension(unittest::repeated_double_extension_lite , 312); - message->AddExtension(unittest::repeated_bool_extension_lite , false); - message->AddExtension(unittest::repeated_string_extension_lite , "315"); - message->AddExtension(unittest::repeated_bytes_extension_lite , "316"); - - message->AddExtension(unittest::repeatedgroup_extension_lite )->set_a(317); - message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(318); - message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(319); - message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(320); - message->AddExtension(unittest::repeated_lazy_message_extension_lite )->set_bb(327); - - message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ ); - message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ ); - message->AddExtension(unittest::repeated_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAZ); + message->AddExtension(unittest::repeated_float_extension_lite, 311); + message->AddExtension(unittest::repeated_double_extension_lite, 312); + message->AddExtension(unittest::repeated_bool_extension_lite, false); + message->AddExtension(unittest::repeated_string_extension_lite, "315"); + message->AddExtension(unittest::repeated_bytes_extension_lite, "316"); + + message->AddExtension(unittest::repeatedgroup_extension_lite)->set_a(317); + message->AddExtension(unittest::repeated_nested_message_extension_lite) + ->set_bb(318); + message->AddExtension(unittest::repeated_foreign_message_extension_lite) + ->set_c(319); + message->AddExtension(unittest::repeated_import_message_extension_lite) + ->set_d(320); + message->AddExtension(unittest::repeated_lazy_message_extension_lite) + ->set_bb(327); + + message->AddExtension(unittest::repeated_nested_enum_extension_lite, + unittest::TestAllTypesLite::BAZ); + message->AddExtension(unittest::repeated_foreign_enum_extension_lite, + unittest::FOREIGN_LITE_BAZ); + message->AddExtension(unittest::repeated_import_enum_extension_lite, + unittest_import::IMPORT_LITE_BAZ); // ----------------------------------------------------------------- - message->SetExtension(unittest::default_int32_extension_lite , 401); - message->SetExtension(unittest::default_int64_extension_lite , 402); - message->SetExtension(unittest::default_uint32_extension_lite , 403); - message->SetExtension(unittest::default_uint64_extension_lite , 404); - message->SetExtension(unittest::default_sint32_extension_lite , 405); - message->SetExtension(unittest::default_sint64_extension_lite , 406); - message->SetExtension(unittest::default_fixed32_extension_lite , 407); - message->SetExtension(unittest::default_fixed64_extension_lite , 408); + message->SetExtension(unittest::default_int32_extension_lite, 401); + message->SetExtension(unittest::default_int64_extension_lite, 402); + message->SetExtension(unittest::default_uint32_extension_lite, 403); + message->SetExtension(unittest::default_uint64_extension_lite, 404); + message->SetExtension(unittest::default_sint32_extension_lite, 405); + message->SetExtension(unittest::default_sint64_extension_lite, 406); + message->SetExtension(unittest::default_fixed32_extension_lite, 407); + message->SetExtension(unittest::default_fixed64_extension_lite, 408); message->SetExtension(unittest::default_sfixed32_extension_lite, 409); message->SetExtension(unittest::default_sfixed64_extension_lite, 410); - message->SetExtension(unittest::default_float_extension_lite , 411); - message->SetExtension(unittest::default_double_extension_lite , 412); - message->SetExtension(unittest::default_bool_extension_lite , false); - message->SetExtension(unittest::default_string_extension_lite , "415"); - message->SetExtension(unittest::default_bytes_extension_lite , "416"); - - message->SetExtension(unittest::default_nested_enum_extension_lite , unittest::TestAllTypesLite::FOO ); - message->SetExtension(unittest::default_foreign_enum_extension_lite, unittest::FOREIGN_LITE_FOO ); - message->SetExtension(unittest::default_import_enum_extension_lite , unittest_import::IMPORT_LITE_FOO); + message->SetExtension(unittest::default_float_extension_lite, 411); + message->SetExtension(unittest::default_double_extension_lite, 412); + message->SetExtension(unittest::default_bool_extension_lite, false); + message->SetExtension(unittest::default_string_extension_lite, "415"); + message->SetExtension(unittest::default_bytes_extension_lite, "416"); + + message->SetExtension(unittest::default_nested_enum_extension_lite, + unittest::TestAllTypesLite::FOO); + message->SetExtension(unittest::default_foreign_enum_extension_lite, + unittest::FOREIGN_LITE_FOO); + message->SetExtension(unittest::default_import_enum_extension_lite, + unittest_import::IMPORT_LITE_FOO); message->SetExtension(unittest::oneof_uint32_extension_lite, 601); - message->MutableExtension(unittest::oneof_nested_message_extension_lite)->set_bb(602);; + message->MutableExtension(unittest::oneof_nested_message_extension_lite) + ->set_bb(602); + ; message->SetExtension(unittest::oneof_string_extension_lite, "603"); message->SetExtension(unittest::oneof_bytes_extension_lite, "604"); } @@ -924,31 +954,40 @@ void TestUtilLite::SetAllExtensions(unittest::TestAllExtensionsLite* message) { void TestUtilLite::ModifyRepeatedExtensions( unittest::TestAllExtensionsLite* message) { - message->SetExtension(unittest::repeated_int32_extension_lite , 1, 501); - message->SetExtension(unittest::repeated_int64_extension_lite , 1, 502); - message->SetExtension(unittest::repeated_uint32_extension_lite , 1, 503); - message->SetExtension(unittest::repeated_uint64_extension_lite , 1, 504); - message->SetExtension(unittest::repeated_sint32_extension_lite , 1, 505); - message->SetExtension(unittest::repeated_sint64_extension_lite , 1, 506); - message->SetExtension(unittest::repeated_fixed32_extension_lite , 1, 507); - message->SetExtension(unittest::repeated_fixed64_extension_lite , 1, 508); + message->SetExtension(unittest::repeated_int32_extension_lite, 1, 501); + message->SetExtension(unittest::repeated_int64_extension_lite, 1, 502); + message->SetExtension(unittest::repeated_uint32_extension_lite, 1, 503); + message->SetExtension(unittest::repeated_uint64_extension_lite, 1, 504); + message->SetExtension(unittest::repeated_sint32_extension_lite, 1, 505); + message->SetExtension(unittest::repeated_sint64_extension_lite, 1, 506); + message->SetExtension(unittest::repeated_fixed32_extension_lite, 1, 507); + message->SetExtension(unittest::repeated_fixed64_extension_lite, 1, 508); message->SetExtension(unittest::repeated_sfixed32_extension_lite, 1, 509); message->SetExtension(unittest::repeated_sfixed64_extension_lite, 1, 510); - message->SetExtension(unittest::repeated_float_extension_lite , 1, 511); - message->SetExtension(unittest::repeated_double_extension_lite , 1, 512); - message->SetExtension(unittest::repeated_bool_extension_lite , 1, true); - message->SetExtension(unittest::repeated_string_extension_lite , 1, "515"); - message->SetExtension(unittest::repeated_bytes_extension_lite , 1, "516"); - - message->MutableExtension(unittest::repeatedgroup_extension_lite , 1)->set_a(517); - message->MutableExtension(unittest::repeated_nested_message_extension_lite , 1)->set_bb(518); - message->MutableExtension(unittest::repeated_foreign_message_extension_lite, 1)->set_c(519); - message->MutableExtension(unittest::repeated_import_message_extension_lite , 1)->set_d(520); - message->MutableExtension(unittest::repeated_lazy_message_extension_lite , 1)->set_bb(527); - - message->SetExtension(unittest::repeated_nested_enum_extension_lite , 1, unittest::TestAllTypesLite::FOO ); - message->SetExtension(unittest::repeated_foreign_enum_extension_lite, 1, unittest::FOREIGN_LITE_FOO ); - message->SetExtension(unittest::repeated_import_enum_extension_lite , 1, unittest_import::IMPORT_LITE_FOO); + message->SetExtension(unittest::repeated_float_extension_lite, 1, 511); + message->SetExtension(unittest::repeated_double_extension_lite, 1, 512); + message->SetExtension(unittest::repeated_bool_extension_lite, 1, true); + message->SetExtension(unittest::repeated_string_extension_lite, 1, "515"); + message->SetExtension(unittest::repeated_bytes_extension_lite, 1, "516"); + + message->MutableExtension(unittest::repeatedgroup_extension_lite, 1) + ->set_a(517); + message->MutableExtension(unittest::repeated_nested_message_extension_lite, 1) + ->set_bb(518); + message + ->MutableExtension(unittest::repeated_foreign_message_extension_lite, 1) + ->set_c(519); + message->MutableExtension(unittest::repeated_import_message_extension_lite, 1) + ->set_d(520); + message->MutableExtension(unittest::repeated_lazy_message_extension_lite, 1) + ->set_bb(527); + + message->SetExtension(unittest::repeated_nested_enum_extension_lite, 1, + unittest::TestAllTypesLite::FOO); + message->SetExtension(unittest::repeated_foreign_enum_extension_lite, 1, + unittest::FOREIGN_LITE_FOO); + message->SetExtension(unittest::repeated_import_enum_extension_lite, 1, + unittest_import::IMPORT_LITE_FOO); } @@ -956,202 +995,351 @@ void TestUtilLite::ModifyRepeatedExtensions( void TestUtilLite::ExpectAllExtensionsSet( const unittest::TestAllExtensionsLite& message) { - EXPECT_TRUE(message.HasExtension(unittest::optional_int32_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_int64_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_uint32_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_uint64_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_sint32_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_sint64_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_fixed32_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_fixed64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_int32_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_int64_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_uint32_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_uint64_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_sint32_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_sint64_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_fixed32_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_fixed64_extension_lite)); EXPECT_TRUE(message.HasExtension(unittest::optional_sfixed32_extension_lite)); EXPECT_TRUE(message.HasExtension(unittest::optional_sfixed64_extension_lite)); - EXPECT_TRUE(message.HasExtension(unittest::optional_float_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_double_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_bool_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_bytes_extension_lite )); - - EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_public_import_message_extension_lite)); - EXPECT_TRUE(message.HasExtension(unittest::optional_lazy_message_extension_lite )); - - EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension_lite ).has_a()); - EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb()); - EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension_lite ).has_c()); - EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d()); - EXPECT_TRUE(message.GetExtension(unittest::optional_public_import_message_extension_lite).has_e()); - EXPECT_TRUE(message.GetExtension(unittest::optional_lazy_message_extension_lite ).has_bb()); - - EXPECT_TRUE(message.HasExtension(unittest::optional_nested_enum_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_enum_extension_lite)); - EXPECT_TRUE(message.HasExtension(unittest::optional_import_enum_extension_lite )); - - - EXPECT_EQ(101 , message.GetExtension(unittest::optional_int32_extension_lite )); - EXPECT_EQ(102 , message.GetExtension(unittest::optional_int64_extension_lite )); - EXPECT_EQ(103 , message.GetExtension(unittest::optional_uint32_extension_lite )); - EXPECT_EQ(104 , message.GetExtension(unittest::optional_uint64_extension_lite )); - EXPECT_EQ(105 , message.GetExtension(unittest::optional_sint32_extension_lite )); - EXPECT_EQ(106 , message.GetExtension(unittest::optional_sint64_extension_lite )); - EXPECT_EQ(107 , message.GetExtension(unittest::optional_fixed32_extension_lite )); - EXPECT_EQ(108 , message.GetExtension(unittest::optional_fixed64_extension_lite )); - EXPECT_EQ(109 , message.GetExtension(unittest::optional_sfixed32_extension_lite)); - EXPECT_EQ(110 , message.GetExtension(unittest::optional_sfixed64_extension_lite)); - EXPECT_EQ(111 , message.GetExtension(unittest::optional_float_extension_lite )); - EXPECT_EQ(112 , message.GetExtension(unittest::optional_double_extension_lite )); - EXPECT_EQ(true , message.GetExtension(unittest::optional_bool_extension_lite )); - EXPECT_EQ("115", message.GetExtension(unittest::optional_string_extension_lite )); - EXPECT_EQ("116", message.GetExtension(unittest::optional_bytes_extension_lite )); - - EXPECT_EQ(117, message.GetExtension(unittest::optionalgroup_extension_lite ).a()); - EXPECT_EQ(118, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb()); - EXPECT_EQ(119, message.GetExtension(unittest::optional_foreign_message_extension_lite ).c()); - EXPECT_EQ(120, message.GetExtension(unittest::optional_import_message_extension_lite ).d()); - EXPECT_EQ(126, message.GetExtension(unittest::optional_public_import_message_extension_lite).e()); - EXPECT_EQ(127, message.GetExtension(unittest::optional_lazy_message_extension_lite ).bb()); - - EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::optional_nested_enum_extension_lite )); - EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.GetExtension(unittest::optional_foreign_enum_extension_lite)); - EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.GetExtension(unittest::optional_import_enum_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_float_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_double_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_bool_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_bytes_extension_lite)); + + EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension_lite)); + EXPECT_TRUE( + message.HasExtension(unittest::optional_nested_message_extension_lite)); + EXPECT_TRUE( + message.HasExtension(unittest::optional_foreign_message_extension_lite)); + EXPECT_TRUE( + message.HasExtension(unittest::optional_import_message_extension_lite)); + EXPECT_TRUE(message.HasExtension( + unittest::optional_public_import_message_extension_lite)); + EXPECT_TRUE( + message.HasExtension(unittest::optional_lazy_message_extension_lite)); + + EXPECT_TRUE( + message.GetExtension(unittest::optionalgroup_extension_lite).has_a()); + EXPECT_TRUE( + message.GetExtension(unittest::optional_nested_message_extension_lite) + .has_bb()); + EXPECT_TRUE( + message.GetExtension(unittest::optional_foreign_message_extension_lite) + .has_c()); + EXPECT_TRUE( + message.GetExtension(unittest::optional_import_message_extension_lite) + .has_d()); + EXPECT_TRUE( + message + .GetExtension(unittest::optional_public_import_message_extension_lite) + .has_e()); + EXPECT_TRUE( + message.GetExtension(unittest::optional_lazy_message_extension_lite) + .has_bb()); + + EXPECT_TRUE( + message.HasExtension(unittest::optional_nested_enum_extension_lite)); + EXPECT_TRUE( + message.HasExtension(unittest::optional_foreign_enum_extension_lite)); + EXPECT_TRUE( + message.HasExtension(unittest::optional_import_enum_extension_lite)); + + + EXPECT_EQ(101, message.GetExtension(unittest::optional_int32_extension_lite)); + EXPECT_EQ(102, message.GetExtension(unittest::optional_int64_extension_lite)); + EXPECT_EQ(103, + message.GetExtension(unittest::optional_uint32_extension_lite)); + EXPECT_EQ(104, + message.GetExtension(unittest::optional_uint64_extension_lite)); + EXPECT_EQ(105, + message.GetExtension(unittest::optional_sint32_extension_lite)); + EXPECT_EQ(106, + message.GetExtension(unittest::optional_sint64_extension_lite)); + EXPECT_EQ(107, + message.GetExtension(unittest::optional_fixed32_extension_lite)); + EXPECT_EQ(108, + message.GetExtension(unittest::optional_fixed64_extension_lite)); + EXPECT_EQ(109, + message.GetExtension(unittest::optional_sfixed32_extension_lite)); + EXPECT_EQ(110, + message.GetExtension(unittest::optional_sfixed64_extension_lite)); + EXPECT_EQ(111, message.GetExtension(unittest::optional_float_extension_lite)); + EXPECT_EQ(112, + message.GetExtension(unittest::optional_double_extension_lite)); + EXPECT_EQ(true, message.GetExtension(unittest::optional_bool_extension_lite)); + EXPECT_EQ("115", + message.GetExtension(unittest::optional_string_extension_lite)); + EXPECT_EQ("116", + message.GetExtension(unittest::optional_bytes_extension_lite)); + + EXPECT_EQ(117, + message.GetExtension(unittest::optionalgroup_extension_lite).a()); + EXPECT_EQ( + 118, + message.GetExtension(unittest::optional_nested_message_extension_lite) + .bb()); + EXPECT_EQ( + 119, + message.GetExtension(unittest::optional_foreign_message_extension_lite) + .c()); + EXPECT_EQ( + 120, + message.GetExtension(unittest::optional_import_message_extension_lite) + .d()); + EXPECT_EQ( + 126, + message + .GetExtension(unittest::optional_public_import_message_extension_lite) + .e()); + EXPECT_EQ(127, + message.GetExtension(unittest::optional_lazy_message_extension_lite) + .bb()); + + EXPECT_EQ( + unittest::TestAllTypesLite::BAZ, + message.GetExtension(unittest::optional_nested_enum_extension_lite)); + EXPECT_EQ( + unittest::FOREIGN_LITE_BAZ, + message.GetExtension(unittest::optional_foreign_enum_extension_lite)); + EXPECT_EQ( + unittest_import::IMPORT_LITE_BAZ, + message.GetExtension(unittest::optional_import_enum_extension_lite)); // ----------------------------------------------------------------- - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension_lite )); - - ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite )); - - - EXPECT_EQ(201 , message.GetExtension(unittest::repeated_int32_extension_lite , 0)); - EXPECT_EQ(202 , message.GetExtension(unittest::repeated_int64_extension_lite , 0)); - EXPECT_EQ(203 , message.GetExtension(unittest::repeated_uint32_extension_lite , 0)); - EXPECT_EQ(204 , message.GetExtension(unittest::repeated_uint64_extension_lite , 0)); - EXPECT_EQ(205 , message.GetExtension(unittest::repeated_sint32_extension_lite , 0)); - EXPECT_EQ(206 , message.GetExtension(unittest::repeated_sint64_extension_lite , 0)); - EXPECT_EQ(207 , message.GetExtension(unittest::repeated_fixed32_extension_lite , 0)); - EXPECT_EQ(208 , message.GetExtension(unittest::repeated_fixed64_extension_lite , 0)); - EXPECT_EQ(209 , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 0)); - EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 0)); - EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension_lite , 0)); - EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension_lite , 0)); - EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite , 0)); - EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension_lite , 0)); - EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension_lite , 0)); - - EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension_lite , 0).a()); - EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb()); - EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c()); - EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d()); - EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 0).bb()); - - EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0)); - EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0)); - EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::repeated_import_enum_extension_lite , 0)); - - - EXPECT_EQ(301 , message.GetExtension(unittest::repeated_int32_extension_lite , 1)); - EXPECT_EQ(302 , message.GetExtension(unittest::repeated_int64_extension_lite , 1)); - EXPECT_EQ(303 , message.GetExtension(unittest::repeated_uint32_extension_lite , 1)); - EXPECT_EQ(304 , message.GetExtension(unittest::repeated_uint64_extension_lite , 1)); - EXPECT_EQ(305 , message.GetExtension(unittest::repeated_sint32_extension_lite , 1)); - EXPECT_EQ(306 , message.GetExtension(unittest::repeated_sint64_extension_lite , 1)); - EXPECT_EQ(307 , message.GetExtension(unittest::repeated_fixed32_extension_lite , 1)); - EXPECT_EQ(308 , message.GetExtension(unittest::repeated_fixed64_extension_lite , 1)); - EXPECT_EQ(309 , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 1)); - EXPECT_EQ(310 , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 1)); - EXPECT_EQ(311 , message.GetExtension(unittest::repeated_float_extension_lite , 1)); - EXPECT_EQ(312 , message.GetExtension(unittest::repeated_double_extension_lite , 1)); - EXPECT_EQ(false, message.GetExtension(unittest::repeated_bool_extension_lite , 1)); - EXPECT_EQ("315", message.GetExtension(unittest::repeated_string_extension_lite , 1)); - EXPECT_EQ("316", message.GetExtension(unittest::repeated_bytes_extension_lite , 1)); - - EXPECT_EQ(317, message.GetExtension(unittest::repeatedgroup_extension_lite , 1).a()); - EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb()); - EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c()); - EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d()); - EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 1).bb()); - - EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1)); - EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1)); - EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.GetExtension(unittest::repeated_import_enum_extension_lite , 1)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension_lite)); + ASSERT_EQ(2, + message.ExtensionSize(unittest::repeated_fixed32_extension_lite)); + ASSERT_EQ(2, + message.ExtensionSize(unittest::repeated_fixed64_extension_lite)); + ASSERT_EQ(2, + message.ExtensionSize(unittest::repeated_sfixed32_extension_lite)); + ASSERT_EQ(2, + message.ExtensionSize(unittest::repeated_sfixed64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension_lite)); + + ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize( + unittest::repeated_nested_message_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize( + unittest::repeated_foreign_message_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize( + unittest::repeated_import_message_extension_lite)); + ASSERT_EQ( + 2, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite)); + ASSERT_EQ( + 2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite)); + ASSERT_EQ( + 2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite)); + ASSERT_EQ( + 2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite)); + + + EXPECT_EQ(201, + message.GetExtension(unittest::repeated_int32_extension_lite, 0)); + EXPECT_EQ(202, + message.GetExtension(unittest::repeated_int64_extension_lite, 0)); + EXPECT_EQ(203, + message.GetExtension(unittest::repeated_uint32_extension_lite, 0)); + EXPECT_EQ(204, + message.GetExtension(unittest::repeated_uint64_extension_lite, 0)); + EXPECT_EQ(205, + message.GetExtension(unittest::repeated_sint32_extension_lite, 0)); + EXPECT_EQ(206, + message.GetExtension(unittest::repeated_sint64_extension_lite, 0)); + EXPECT_EQ(207, + message.GetExtension(unittest::repeated_fixed32_extension_lite, 0)); + EXPECT_EQ(208, + message.GetExtension(unittest::repeated_fixed64_extension_lite, 0)); + EXPECT_EQ( + 209, message.GetExtension(unittest::repeated_sfixed32_extension_lite, 0)); + EXPECT_EQ( + 210, message.GetExtension(unittest::repeated_sfixed64_extension_lite, 0)); + EXPECT_EQ(211, + message.GetExtension(unittest::repeated_float_extension_lite, 0)); + EXPECT_EQ(212, + message.GetExtension(unittest::repeated_double_extension_lite, 0)); + EXPECT_EQ(true, + message.GetExtension(unittest::repeated_bool_extension_lite, 0)); + EXPECT_EQ("215", + message.GetExtension(unittest::repeated_string_extension_lite, 0)); + EXPECT_EQ("216", + message.GetExtension(unittest::repeated_bytes_extension_lite, 0)); + + EXPECT_EQ( + 217, message.GetExtension(unittest::repeatedgroup_extension_lite, 0).a()); + EXPECT_EQ( + 218, + message.GetExtension(unittest::repeated_nested_message_extension_lite, 0) + .bb()); + EXPECT_EQ( + 219, + message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0) + .c()); + EXPECT_EQ( + 220, + message.GetExtension(unittest::repeated_import_message_extension_lite, 0) + .d()); + EXPECT_EQ( + 227, + message.GetExtension(unittest::repeated_lazy_message_extension_lite, 0) + .bb()); + + EXPECT_EQ( + unittest::TestAllTypesLite::BAR, + message.GetExtension(unittest::repeated_nested_enum_extension_lite, 0)); + EXPECT_EQ( + unittest::FOREIGN_LITE_BAR, + message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0)); + EXPECT_EQ( + unittest_import::IMPORT_LITE_BAR, + message.GetExtension(unittest::repeated_import_enum_extension_lite, 0)); + + + EXPECT_EQ(301, + message.GetExtension(unittest::repeated_int32_extension_lite, 1)); + EXPECT_EQ(302, + message.GetExtension(unittest::repeated_int64_extension_lite, 1)); + EXPECT_EQ(303, + message.GetExtension(unittest::repeated_uint32_extension_lite, 1)); + EXPECT_EQ(304, + message.GetExtension(unittest::repeated_uint64_extension_lite, 1)); + EXPECT_EQ(305, + message.GetExtension(unittest::repeated_sint32_extension_lite, 1)); + EXPECT_EQ(306, + message.GetExtension(unittest::repeated_sint64_extension_lite, 1)); + EXPECT_EQ(307, + message.GetExtension(unittest::repeated_fixed32_extension_lite, 1)); + EXPECT_EQ(308, + message.GetExtension(unittest::repeated_fixed64_extension_lite, 1)); + EXPECT_EQ( + 309, message.GetExtension(unittest::repeated_sfixed32_extension_lite, 1)); + EXPECT_EQ( + 310, message.GetExtension(unittest::repeated_sfixed64_extension_lite, 1)); + EXPECT_EQ(311, + message.GetExtension(unittest::repeated_float_extension_lite, 1)); + EXPECT_EQ(312, + message.GetExtension(unittest::repeated_double_extension_lite, 1)); + EXPECT_EQ(false, + message.GetExtension(unittest::repeated_bool_extension_lite, 1)); + EXPECT_EQ("315", + message.GetExtension(unittest::repeated_string_extension_lite, 1)); + EXPECT_EQ("316", + message.GetExtension(unittest::repeated_bytes_extension_lite, 1)); + + EXPECT_EQ( + 317, message.GetExtension(unittest::repeatedgroup_extension_lite, 1).a()); + EXPECT_EQ( + 318, + message.GetExtension(unittest::repeated_nested_message_extension_lite, 1) + .bb()); + EXPECT_EQ( + 319, + message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1) + .c()); + EXPECT_EQ( + 320, + message.GetExtension(unittest::repeated_import_message_extension_lite, 1) + .d()); + EXPECT_EQ( + 327, + message.GetExtension(unittest::repeated_lazy_message_extension_lite, 1) + .bb()); + + EXPECT_EQ( + unittest::TestAllTypesLite::BAZ, + message.GetExtension(unittest::repeated_nested_enum_extension_lite, 1)); + EXPECT_EQ( + unittest::FOREIGN_LITE_BAZ, + message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1)); + EXPECT_EQ( + unittest_import::IMPORT_LITE_BAZ, + message.GetExtension(unittest::repeated_import_enum_extension_lite, 1)); // ----------------------------------------------------------------- - EXPECT_TRUE(message.HasExtension(unittest::default_int32_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::default_int64_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::default_uint32_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::default_uint64_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::default_sint32_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::default_sint64_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::default_fixed32_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::default_fixed64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_int32_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_int64_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_uint32_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_uint64_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_sint32_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_sint64_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_fixed32_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_fixed64_extension_lite)); EXPECT_TRUE(message.HasExtension(unittest::default_sfixed32_extension_lite)); EXPECT_TRUE(message.HasExtension(unittest::default_sfixed64_extension_lite)); - EXPECT_TRUE(message.HasExtension(unittest::default_float_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::default_double_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::default_bool_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::default_string_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::default_bytes_extension_lite )); - - EXPECT_TRUE(message.HasExtension(unittest::default_nested_enum_extension_lite )); - EXPECT_TRUE(message.HasExtension(unittest::default_foreign_enum_extension_lite)); - EXPECT_TRUE(message.HasExtension(unittest::default_import_enum_extension_lite )); - - - EXPECT_EQ(401 , message.GetExtension(unittest::default_int32_extension_lite )); - EXPECT_EQ(402 , message.GetExtension(unittest::default_int64_extension_lite )); - EXPECT_EQ(403 , message.GetExtension(unittest::default_uint32_extension_lite )); - EXPECT_EQ(404 , message.GetExtension(unittest::default_uint64_extension_lite )); - EXPECT_EQ(405 , message.GetExtension(unittest::default_sint32_extension_lite )); - EXPECT_EQ(406 , message.GetExtension(unittest::default_sint64_extension_lite )); - EXPECT_EQ(407 , message.GetExtension(unittest::default_fixed32_extension_lite )); - EXPECT_EQ(408 , message.GetExtension(unittest::default_fixed64_extension_lite )); - EXPECT_EQ(409 , message.GetExtension(unittest::default_sfixed32_extension_lite)); - EXPECT_EQ(410 , message.GetExtension(unittest::default_sfixed64_extension_lite)); - EXPECT_EQ(411 , message.GetExtension(unittest::default_float_extension_lite )); - EXPECT_EQ(412 , message.GetExtension(unittest::default_double_extension_lite )); - EXPECT_EQ(false, message.GetExtension(unittest::default_bool_extension_lite )); - EXPECT_EQ("415", message.GetExtension(unittest::default_string_extension_lite )); - EXPECT_EQ("416", message.GetExtension(unittest::default_bytes_extension_lite )); - - EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::default_nested_enum_extension_lite )); - EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.GetExtension(unittest::default_foreign_enum_extension_lite)); - EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::default_import_enum_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_float_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_double_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_bool_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_string_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_bytes_extension_lite)); + + EXPECT_TRUE( + message.HasExtension(unittest::default_nested_enum_extension_lite)); + EXPECT_TRUE( + message.HasExtension(unittest::default_foreign_enum_extension_lite)); + EXPECT_TRUE( + message.HasExtension(unittest::default_import_enum_extension_lite)); + + + EXPECT_EQ(401, message.GetExtension(unittest::default_int32_extension_lite)); + EXPECT_EQ(402, message.GetExtension(unittest::default_int64_extension_lite)); + EXPECT_EQ(403, message.GetExtension(unittest::default_uint32_extension_lite)); + EXPECT_EQ(404, message.GetExtension(unittest::default_uint64_extension_lite)); + EXPECT_EQ(405, message.GetExtension(unittest::default_sint32_extension_lite)); + EXPECT_EQ(406, message.GetExtension(unittest::default_sint64_extension_lite)); + EXPECT_EQ(407, + message.GetExtension(unittest::default_fixed32_extension_lite)); + EXPECT_EQ(408, + message.GetExtension(unittest::default_fixed64_extension_lite)); + EXPECT_EQ(409, + message.GetExtension(unittest::default_sfixed32_extension_lite)); + EXPECT_EQ(410, + message.GetExtension(unittest::default_sfixed64_extension_lite)); + EXPECT_EQ(411, message.GetExtension(unittest::default_float_extension_lite)); + EXPECT_EQ(412, message.GetExtension(unittest::default_double_extension_lite)); + EXPECT_EQ(false, message.GetExtension(unittest::default_bool_extension_lite)); + EXPECT_EQ("415", + message.GetExtension(unittest::default_string_extension_lite)); + EXPECT_EQ("416", + message.GetExtension(unittest::default_bytes_extension_lite)); + + EXPECT_EQ(unittest::TestAllTypesLite::FOO, + message.GetExtension(unittest::default_nested_enum_extension_lite)); + EXPECT_EQ( + unittest::FOREIGN_LITE_FOO, + message.GetExtension(unittest::default_foreign_enum_extension_lite)); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, + message.GetExtension(unittest::default_import_enum_extension_lite)); EXPECT_TRUE(message.HasExtension(unittest::oneof_uint32_extension_lite)); - EXPECT_TRUE(message.GetExtension(unittest::oneof_nested_message_extension_lite).has_bb()); + EXPECT_TRUE( + message.GetExtension(unittest::oneof_nested_message_extension_lite) + .has_bb()); EXPECT_TRUE(message.HasExtension(unittest::oneof_string_extension_lite)); EXPECT_TRUE(message.HasExtension(unittest::oneof_bytes_extension_lite)); EXPECT_EQ(601, message.GetExtension(unittest::oneof_uint32_extension_lite)); - EXPECT_EQ(602, message.GetExtension(unittest::oneof_nested_message_extension_lite).bb()); + EXPECT_EQ( + 602, + message.GetExtension(unittest::oneof_nested_message_extension_lite).bb()); EXPECT_EQ("603", message.GetExtension(unittest::oneof_string_extension_lite)); EXPECT_EQ("604", message.GetExtension(unittest::oneof_bytes_extension_lite)); } @@ -1160,151 +1348,219 @@ void TestUtilLite::ExpectAllExtensionsSet( void TestUtilLite::ExpectExtensionsClear( const unittest::TestAllExtensionsLite& message) { - string serialized; + std::string serialized; ASSERT_TRUE(message.SerializeToString(&serialized)); EXPECT_EQ("", serialized); - EXPECT_EQ(0, message.ByteSize()); + EXPECT_EQ(0, message.ByteSizeLong()); // has_blah() should initially be false for all optional fields. - EXPECT_FALSE(message.HasExtension(unittest::optional_int32_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_int64_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_uint32_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_uint64_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_sint32_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_sint64_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_fixed32_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_fixed64_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_sfixed32_extension_lite)); - EXPECT_FALSE(message.HasExtension(unittest::optional_sfixed64_extension_lite)); - EXPECT_FALSE(message.HasExtension(unittest::optional_float_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_double_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_bool_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_string_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_bytes_extension_lite )); - - EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_public_import_message_extension_lite)); - EXPECT_FALSE(message.HasExtension(unittest::optional_lazy_message_extension_lite )); - - EXPECT_FALSE(message.HasExtension(unittest::optional_nested_enum_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_enum_extension_lite)); - EXPECT_FALSE(message.HasExtension(unittest::optional_import_enum_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_int32_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_int64_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_uint32_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_uint64_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_sint32_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_sint64_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_fixed32_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_fixed64_extension_lite)); + EXPECT_FALSE( + message.HasExtension(unittest::optional_sfixed32_extension_lite)); + EXPECT_FALSE( + message.HasExtension(unittest::optional_sfixed64_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_float_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_double_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_bool_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_string_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_bytes_extension_lite)); + + EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension_lite)); + EXPECT_FALSE( + message.HasExtension(unittest::optional_nested_message_extension_lite)); + EXPECT_FALSE( + message.HasExtension(unittest::optional_foreign_message_extension_lite)); + EXPECT_FALSE( + message.HasExtension(unittest::optional_import_message_extension_lite)); + EXPECT_FALSE(message.HasExtension( + unittest::optional_public_import_message_extension_lite)); + EXPECT_FALSE( + message.HasExtension(unittest::optional_lazy_message_extension_lite)); + + EXPECT_FALSE( + message.HasExtension(unittest::optional_nested_enum_extension_lite)); + EXPECT_FALSE( + message.HasExtension(unittest::optional_foreign_enum_extension_lite)); + EXPECT_FALSE( + message.HasExtension(unittest::optional_import_enum_extension_lite)); // Optional fields without defaults are set to zero or something like it. - EXPECT_EQ(0 , message.GetExtension(unittest::optional_int32_extension_lite )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_int64_extension_lite )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_uint32_extension_lite )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_uint64_extension_lite )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_sint32_extension_lite )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_sint64_extension_lite )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_fixed32_extension_lite )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_fixed64_extension_lite )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_sfixed32_extension_lite)); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_sfixed64_extension_lite)); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_float_extension_lite )); - EXPECT_EQ(0 , message.GetExtension(unittest::optional_double_extension_lite )); - EXPECT_EQ(false, message.GetExtension(unittest::optional_bool_extension_lite )); - EXPECT_EQ("" , message.GetExtension(unittest::optional_string_extension_lite )); - EXPECT_EQ("" , message.GetExtension(unittest::optional_bytes_extension_lite )); + EXPECT_EQ(0, message.GetExtension(unittest::optional_int32_extension_lite)); + EXPECT_EQ(0, message.GetExtension(unittest::optional_int64_extension_lite)); + EXPECT_EQ(0, message.GetExtension(unittest::optional_uint32_extension_lite)); + EXPECT_EQ(0, message.GetExtension(unittest::optional_uint64_extension_lite)); + EXPECT_EQ(0, message.GetExtension(unittest::optional_sint32_extension_lite)); + EXPECT_EQ(0, message.GetExtension(unittest::optional_sint64_extension_lite)); + EXPECT_EQ(0, message.GetExtension(unittest::optional_fixed32_extension_lite)); + EXPECT_EQ(0, message.GetExtension(unittest::optional_fixed64_extension_lite)); + EXPECT_EQ(0, + message.GetExtension(unittest::optional_sfixed32_extension_lite)); + EXPECT_EQ(0, + message.GetExtension(unittest::optional_sfixed64_extension_lite)); + EXPECT_EQ(0, message.GetExtension(unittest::optional_float_extension_lite)); + EXPECT_EQ(0, message.GetExtension(unittest::optional_double_extension_lite)); + EXPECT_EQ(false, + message.GetExtension(unittest::optional_bool_extension_lite)); + EXPECT_EQ("", message.GetExtension(unittest::optional_string_extension_lite)); + EXPECT_EQ("", message.GetExtension(unittest::optional_bytes_extension_lite)); // Embedded messages should also be clear. - EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension_lite ).has_a()); - EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb()); - EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension_lite ).has_c()); - EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d()); - EXPECT_FALSE(message.GetExtension(unittest::optional_public_import_message_extension_lite).has_e()); - EXPECT_FALSE(message.GetExtension(unittest::optional_lazy_message_extension_lite ).has_bb()); - - EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension_lite ).a()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension_lite ).c()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension_lite ).d()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_public_import_message_extension_lite).e()); - EXPECT_EQ(0, message.GetExtension(unittest::optional_lazy_message_extension_lite ).bb()); + EXPECT_FALSE( + message.GetExtension(unittest::optionalgroup_extension_lite).has_a()); + EXPECT_FALSE( + message.GetExtension(unittest::optional_nested_message_extension_lite) + .has_bb()); + EXPECT_FALSE( + message.GetExtension(unittest::optional_foreign_message_extension_lite) + .has_c()); + EXPECT_FALSE( + message.GetExtension(unittest::optional_import_message_extension_lite) + .has_d()); + EXPECT_FALSE( + message + .GetExtension(unittest::optional_public_import_message_extension_lite) + .has_e()); + EXPECT_FALSE( + message.GetExtension(unittest::optional_lazy_message_extension_lite) + .has_bb()); + + EXPECT_EQ(0, + message.GetExtension(unittest::optionalgroup_extension_lite).a()); + EXPECT_EQ( + 0, message.GetExtension(unittest::optional_nested_message_extension_lite) + .bb()); + EXPECT_EQ( + 0, message.GetExtension(unittest::optional_foreign_message_extension_lite) + .c()); + EXPECT_EQ( + 0, message.GetExtension(unittest::optional_import_message_extension_lite) + .d()); + EXPECT_EQ(0, message + .GetExtension( + unittest::optional_public_import_message_extension_lite) + .e()); + EXPECT_EQ(0, + message.GetExtension(unittest::optional_lazy_message_extension_lite) + .bb()); // Enums without defaults are set to the first value in the enum. - EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::optional_nested_enum_extension_lite )); - EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.GetExtension(unittest::optional_foreign_enum_extension_lite)); - EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::optional_import_enum_extension_lite )); + EXPECT_EQ( + unittest::TestAllTypesLite::FOO, + message.GetExtension(unittest::optional_nested_enum_extension_lite)); + EXPECT_EQ( + unittest::FOREIGN_LITE_FOO, + message.GetExtension(unittest::optional_foreign_enum_extension_lite)); + EXPECT_EQ( + unittest_import::IMPORT_LITE_FOO, + message.GetExtension(unittest::optional_import_enum_extension_lite)); // Repeated fields are empty. - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int32_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int64_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint32_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint64_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint32_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint64_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_fixed32_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_fixed64_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite)); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite)); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_float_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_double_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bool_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_string_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bytes_extension_lite )); - - EXPECT_EQ(0, message.ExtensionSize(unittest::repeatedgroup_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_message_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite)); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_message_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_enum_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int32_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int64_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint32_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint64_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint32_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint64_extension_lite)); + EXPECT_EQ(0, + message.ExtensionSize(unittest::repeated_fixed32_extension_lite)); + EXPECT_EQ(0, + message.ExtensionSize(unittest::repeated_fixed64_extension_lite)); + EXPECT_EQ(0, + message.ExtensionSize(unittest::repeated_sfixed32_extension_lite)); + EXPECT_EQ(0, + message.ExtensionSize(unittest::repeated_sfixed64_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_float_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_double_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bool_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_string_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bytes_extension_lite)); + + EXPECT_EQ(0, message.ExtensionSize(unittest::repeatedgroup_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize( + unittest::repeated_nested_message_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize( + unittest::repeated_foreign_message_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize( + unittest::repeated_import_message_extension_lite)); + EXPECT_EQ( + 0, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite)); + EXPECT_EQ( + 0, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite)); + EXPECT_EQ( + 0, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite)); + EXPECT_EQ( + 0, message.ExtensionSize(unittest::repeated_import_enum_extension_lite)); // has_blah() should also be false for all default fields. - EXPECT_FALSE(message.HasExtension(unittest::default_int32_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::default_int64_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::default_uint32_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::default_uint64_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::default_sint32_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::default_sint64_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::default_fixed32_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::default_fixed64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_int32_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_int64_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_uint32_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_uint64_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_sint32_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_sint64_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_fixed32_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_fixed64_extension_lite)); EXPECT_FALSE(message.HasExtension(unittest::default_sfixed32_extension_lite)); EXPECT_FALSE(message.HasExtension(unittest::default_sfixed64_extension_lite)); - EXPECT_FALSE(message.HasExtension(unittest::default_float_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::default_double_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::default_bool_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::default_string_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::default_bytes_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_float_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_double_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_bool_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_string_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_bytes_extension_lite)); - EXPECT_FALSE(message.HasExtension(unittest::default_nested_enum_extension_lite )); - EXPECT_FALSE(message.HasExtension(unittest::default_foreign_enum_extension_lite)); - EXPECT_FALSE(message.HasExtension(unittest::default_import_enum_extension_lite )); + EXPECT_FALSE( + message.HasExtension(unittest::default_nested_enum_extension_lite)); + EXPECT_FALSE( + message.HasExtension(unittest::default_foreign_enum_extension_lite)); + EXPECT_FALSE( + message.HasExtension(unittest::default_import_enum_extension_lite)); // Fields with defaults have their default values (duh). - EXPECT_EQ( 41 , message.GetExtension(unittest::default_int32_extension_lite )); - EXPECT_EQ( 42 , message.GetExtension(unittest::default_int64_extension_lite )); - EXPECT_EQ( 43 , message.GetExtension(unittest::default_uint32_extension_lite )); - EXPECT_EQ( 44 , message.GetExtension(unittest::default_uint64_extension_lite )); - EXPECT_EQ(-45 , message.GetExtension(unittest::default_sint32_extension_lite )); - EXPECT_EQ( 46 , message.GetExtension(unittest::default_sint64_extension_lite )); - EXPECT_EQ( 47 , message.GetExtension(unittest::default_fixed32_extension_lite )); - EXPECT_EQ( 48 , message.GetExtension(unittest::default_fixed64_extension_lite )); - EXPECT_EQ( 49 , message.GetExtension(unittest::default_sfixed32_extension_lite)); - EXPECT_EQ(-50 , message.GetExtension(unittest::default_sfixed64_extension_lite)); - EXPECT_EQ( 51.5 , message.GetExtension(unittest::default_float_extension_lite )); - EXPECT_EQ( 52e3 , message.GetExtension(unittest::default_double_extension_lite )); - EXPECT_EQ(true , message.GetExtension(unittest::default_bool_extension_lite )); - EXPECT_EQ("hello", message.GetExtension(unittest::default_string_extension_lite )); - EXPECT_EQ("world", message.GetExtension(unittest::default_bytes_extension_lite )); - - EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::default_nested_enum_extension_lite )); - EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::default_foreign_enum_extension_lite)); - EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::default_import_enum_extension_lite )); + EXPECT_EQ(41, message.GetExtension(unittest::default_int32_extension_lite)); + EXPECT_EQ(42, message.GetExtension(unittest::default_int64_extension_lite)); + EXPECT_EQ(43, message.GetExtension(unittest::default_uint32_extension_lite)); + EXPECT_EQ(44, message.GetExtension(unittest::default_uint64_extension_lite)); + EXPECT_EQ(-45, message.GetExtension(unittest::default_sint32_extension_lite)); + EXPECT_EQ(46, message.GetExtension(unittest::default_sint64_extension_lite)); + EXPECT_EQ(47, message.GetExtension(unittest::default_fixed32_extension_lite)); + EXPECT_EQ(48, message.GetExtension(unittest::default_fixed64_extension_lite)); + EXPECT_EQ(49, + message.GetExtension(unittest::default_sfixed32_extension_lite)); + EXPECT_EQ(-50, + message.GetExtension(unittest::default_sfixed64_extension_lite)); + EXPECT_EQ(51.5, message.GetExtension(unittest::default_float_extension_lite)); + EXPECT_EQ(52e3, + message.GetExtension(unittest::default_double_extension_lite)); + EXPECT_EQ(true, message.GetExtension(unittest::default_bool_extension_lite)); + EXPECT_EQ("hello", + message.GetExtension(unittest::default_string_extension_lite)); + EXPECT_EQ("world", + message.GetExtension(unittest::default_bytes_extension_lite)); + + EXPECT_EQ(unittest::TestAllTypesLite::BAR, + message.GetExtension(unittest::default_nested_enum_extension_lite)); + EXPECT_EQ( + unittest::FOREIGN_LITE_BAR, + message.GetExtension(unittest::default_foreign_enum_extension_lite)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, + message.GetExtension(unittest::default_import_enum_extension_lite)); EXPECT_FALSE(message.HasExtension(unittest::oneof_uint32_extension_lite)); - EXPECT_FALSE(message.GetExtension(unittest::oneof_nested_message_extension_lite).has_bb()); + EXPECT_FALSE( + message.GetExtension(unittest::oneof_nested_message_extension_lite) + .has_bb()); EXPECT_FALSE(message.HasExtension(unittest::oneof_string_extension_lite)); EXPECT_FALSE(message.HasExtension(unittest::oneof_bytes_extension_lite)); } @@ -1316,85 +1572,164 @@ void TestUtilLite::ExpectRepeatedExtensionsModified( // ModifyRepeatedFields only sets the second repeated element of each // field. In addition to verifying this, we also verify that the first // element and size were *not* modified. - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension_lite )); - - ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite)); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite )); - - - EXPECT_EQ(201 , message.GetExtension(unittest::repeated_int32_extension_lite , 0)); - EXPECT_EQ(202 , message.GetExtension(unittest::repeated_int64_extension_lite , 0)); - EXPECT_EQ(203 , message.GetExtension(unittest::repeated_uint32_extension_lite , 0)); - EXPECT_EQ(204 , message.GetExtension(unittest::repeated_uint64_extension_lite , 0)); - EXPECT_EQ(205 , message.GetExtension(unittest::repeated_sint32_extension_lite , 0)); - EXPECT_EQ(206 , message.GetExtension(unittest::repeated_sint64_extension_lite , 0)); - EXPECT_EQ(207 , message.GetExtension(unittest::repeated_fixed32_extension_lite , 0)); - EXPECT_EQ(208 , message.GetExtension(unittest::repeated_fixed64_extension_lite , 0)); - EXPECT_EQ(209 , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 0)); - EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 0)); - EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension_lite , 0)); - EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension_lite , 0)); - EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite , 0)); - EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension_lite , 0)); - EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension_lite , 0)); - - EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension_lite , 0).a()); - EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb()); - EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c()); - EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d()); - EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 0).bb()); - - EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0)); - EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0)); - EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::repeated_import_enum_extension_lite , 0)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension_lite)); + ASSERT_EQ(2, + message.ExtensionSize(unittest::repeated_fixed32_extension_lite)); + ASSERT_EQ(2, + message.ExtensionSize(unittest::repeated_fixed64_extension_lite)); + ASSERT_EQ(2, + message.ExtensionSize(unittest::repeated_sfixed32_extension_lite)); + ASSERT_EQ(2, + message.ExtensionSize(unittest::repeated_sfixed64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension_lite)); + + ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize( + unittest::repeated_nested_message_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize( + unittest::repeated_foreign_message_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize( + unittest::repeated_import_message_extension_lite)); + ASSERT_EQ( + 2, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite)); + ASSERT_EQ( + 2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite)); + ASSERT_EQ( + 2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite)); + ASSERT_EQ( + 2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite)); + + + EXPECT_EQ(201, + message.GetExtension(unittest::repeated_int32_extension_lite, 0)); + EXPECT_EQ(202, + message.GetExtension(unittest::repeated_int64_extension_lite, 0)); + EXPECT_EQ(203, + message.GetExtension(unittest::repeated_uint32_extension_lite, 0)); + EXPECT_EQ(204, + message.GetExtension(unittest::repeated_uint64_extension_lite, 0)); + EXPECT_EQ(205, + message.GetExtension(unittest::repeated_sint32_extension_lite, 0)); + EXPECT_EQ(206, + message.GetExtension(unittest::repeated_sint64_extension_lite, 0)); + EXPECT_EQ(207, + message.GetExtension(unittest::repeated_fixed32_extension_lite, 0)); + EXPECT_EQ(208, + message.GetExtension(unittest::repeated_fixed64_extension_lite, 0)); + EXPECT_EQ( + 209, message.GetExtension(unittest::repeated_sfixed32_extension_lite, 0)); + EXPECT_EQ( + 210, message.GetExtension(unittest::repeated_sfixed64_extension_lite, 0)); + EXPECT_EQ(211, + message.GetExtension(unittest::repeated_float_extension_lite, 0)); + EXPECT_EQ(212, + message.GetExtension(unittest::repeated_double_extension_lite, 0)); + EXPECT_EQ(true, + message.GetExtension(unittest::repeated_bool_extension_lite, 0)); + EXPECT_EQ("215", + message.GetExtension(unittest::repeated_string_extension_lite, 0)); + EXPECT_EQ("216", + message.GetExtension(unittest::repeated_bytes_extension_lite, 0)); + + EXPECT_EQ( + 217, message.GetExtension(unittest::repeatedgroup_extension_lite, 0).a()); + EXPECT_EQ( + 218, + message.GetExtension(unittest::repeated_nested_message_extension_lite, 0) + .bb()); + EXPECT_EQ( + 219, + message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0) + .c()); + EXPECT_EQ( + 220, + message.GetExtension(unittest::repeated_import_message_extension_lite, 0) + .d()); + EXPECT_EQ( + 227, + message.GetExtension(unittest::repeated_lazy_message_extension_lite, 0) + .bb()); + + EXPECT_EQ( + unittest::TestAllTypesLite::BAR, + message.GetExtension(unittest::repeated_nested_enum_extension_lite, 0)); + EXPECT_EQ( + unittest::FOREIGN_LITE_BAR, + message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0)); + EXPECT_EQ( + unittest_import::IMPORT_LITE_BAR, + message.GetExtension(unittest::repeated_import_enum_extension_lite, 0)); // Actually verify the second (modified) elements now. - EXPECT_EQ(501 , message.GetExtension(unittest::repeated_int32_extension_lite , 1)); - EXPECT_EQ(502 , message.GetExtension(unittest::repeated_int64_extension_lite , 1)); - EXPECT_EQ(503 , message.GetExtension(unittest::repeated_uint32_extension_lite , 1)); - EXPECT_EQ(504 , message.GetExtension(unittest::repeated_uint64_extension_lite , 1)); - EXPECT_EQ(505 , message.GetExtension(unittest::repeated_sint32_extension_lite , 1)); - EXPECT_EQ(506 , message.GetExtension(unittest::repeated_sint64_extension_lite , 1)); - EXPECT_EQ(507 , message.GetExtension(unittest::repeated_fixed32_extension_lite , 1)); - EXPECT_EQ(508 , message.GetExtension(unittest::repeated_fixed64_extension_lite , 1)); - EXPECT_EQ(509 , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 1)); - EXPECT_EQ(510 , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 1)); - EXPECT_EQ(511 , message.GetExtension(unittest::repeated_float_extension_lite , 1)); - EXPECT_EQ(512 , message.GetExtension(unittest::repeated_double_extension_lite , 1)); - EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite , 1)); - EXPECT_EQ("515", message.GetExtension(unittest::repeated_string_extension_lite , 1)); - EXPECT_EQ("516", message.GetExtension(unittest::repeated_bytes_extension_lite , 1)); - - EXPECT_EQ(517, message.GetExtension(unittest::repeatedgroup_extension_lite , 1).a()); - EXPECT_EQ(518, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb()); - EXPECT_EQ(519, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c()); - EXPECT_EQ(520, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d()); - EXPECT_EQ(527, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 1).bb()); - - EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1)); - EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1)); - EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::repeated_import_enum_extension_lite , 1)); + EXPECT_EQ(501, + message.GetExtension(unittest::repeated_int32_extension_lite, 1)); + EXPECT_EQ(502, + message.GetExtension(unittest::repeated_int64_extension_lite, 1)); + EXPECT_EQ(503, + message.GetExtension(unittest::repeated_uint32_extension_lite, 1)); + EXPECT_EQ(504, + message.GetExtension(unittest::repeated_uint64_extension_lite, 1)); + EXPECT_EQ(505, + message.GetExtension(unittest::repeated_sint32_extension_lite, 1)); + EXPECT_EQ(506, + message.GetExtension(unittest::repeated_sint64_extension_lite, 1)); + EXPECT_EQ(507, + message.GetExtension(unittest::repeated_fixed32_extension_lite, 1)); + EXPECT_EQ(508, + message.GetExtension(unittest::repeated_fixed64_extension_lite, 1)); + EXPECT_EQ( + 509, message.GetExtension(unittest::repeated_sfixed32_extension_lite, 1)); + EXPECT_EQ( + 510, message.GetExtension(unittest::repeated_sfixed64_extension_lite, 1)); + EXPECT_EQ(511, + message.GetExtension(unittest::repeated_float_extension_lite, 1)); + EXPECT_EQ(512, + message.GetExtension(unittest::repeated_double_extension_lite, 1)); + EXPECT_EQ(true, + message.GetExtension(unittest::repeated_bool_extension_lite, 1)); + EXPECT_EQ("515", + message.GetExtension(unittest::repeated_string_extension_lite, 1)); + EXPECT_EQ("516", + message.GetExtension(unittest::repeated_bytes_extension_lite, 1)); + + EXPECT_EQ( + 517, message.GetExtension(unittest::repeatedgroup_extension_lite, 1).a()); + EXPECT_EQ( + 518, + message.GetExtension(unittest::repeated_nested_message_extension_lite, 1) + .bb()); + EXPECT_EQ( + 519, + message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1) + .c()); + EXPECT_EQ( + 520, + message.GetExtension(unittest::repeated_import_message_extension_lite, 1) + .d()); + EXPECT_EQ( + 527, + message.GetExtension(unittest::repeated_lazy_message_extension_lite, 1) + .bb()); + + EXPECT_EQ( + unittest::TestAllTypesLite::FOO, + message.GetExtension(unittest::repeated_nested_enum_extension_lite, 1)); + EXPECT_EQ( + unittest::FOREIGN_LITE_FOO, + message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1)); + EXPECT_EQ( + unittest_import::IMPORT_LITE_FOO, + message.GetExtension(unittest::repeated_import_enum_extension_lite, 1)); } @@ -1402,55 +1737,57 @@ void TestUtilLite::ExpectRepeatedExtensionsModified( void TestUtilLite::SetPackedExtensions( unittest::TestPackedExtensionsLite* message) { - message->AddExtension(unittest::packed_int32_extension_lite , 601); - message->AddExtension(unittest::packed_int64_extension_lite , 602); - message->AddExtension(unittest::packed_uint32_extension_lite , 603); - message->AddExtension(unittest::packed_uint64_extension_lite , 604); - message->AddExtension(unittest::packed_sint32_extension_lite , 605); - message->AddExtension(unittest::packed_sint64_extension_lite , 606); - message->AddExtension(unittest::packed_fixed32_extension_lite , 607); - message->AddExtension(unittest::packed_fixed64_extension_lite , 608); + message->AddExtension(unittest::packed_int32_extension_lite, 601); + message->AddExtension(unittest::packed_int64_extension_lite, 602); + message->AddExtension(unittest::packed_uint32_extension_lite, 603); + message->AddExtension(unittest::packed_uint64_extension_lite, 604); + message->AddExtension(unittest::packed_sint32_extension_lite, 605); + message->AddExtension(unittest::packed_sint64_extension_lite, 606); + message->AddExtension(unittest::packed_fixed32_extension_lite, 607); + message->AddExtension(unittest::packed_fixed64_extension_lite, 608); message->AddExtension(unittest::packed_sfixed32_extension_lite, 609); message->AddExtension(unittest::packed_sfixed64_extension_lite, 610); - message->AddExtension(unittest::packed_float_extension_lite , 611); - message->AddExtension(unittest::packed_double_extension_lite , 612); - message->AddExtension(unittest::packed_bool_extension_lite , true); - message->AddExtension(unittest::packed_enum_extension_lite, unittest::FOREIGN_LITE_BAR); + message->AddExtension(unittest::packed_float_extension_lite, 611); + message->AddExtension(unittest::packed_double_extension_lite, 612); + message->AddExtension(unittest::packed_bool_extension_lite, true); + message->AddExtension(unittest::packed_enum_extension_lite, + unittest::FOREIGN_LITE_BAR); // add a second one of each field - message->AddExtension(unittest::packed_int32_extension_lite , 701); - message->AddExtension(unittest::packed_int64_extension_lite , 702); - message->AddExtension(unittest::packed_uint32_extension_lite , 703); - message->AddExtension(unittest::packed_uint64_extension_lite , 704); - message->AddExtension(unittest::packed_sint32_extension_lite , 705); - message->AddExtension(unittest::packed_sint64_extension_lite , 706); - message->AddExtension(unittest::packed_fixed32_extension_lite , 707); - message->AddExtension(unittest::packed_fixed64_extension_lite , 708); + message->AddExtension(unittest::packed_int32_extension_lite, 701); + message->AddExtension(unittest::packed_int64_extension_lite, 702); + message->AddExtension(unittest::packed_uint32_extension_lite, 703); + message->AddExtension(unittest::packed_uint64_extension_lite, 704); + message->AddExtension(unittest::packed_sint32_extension_lite, 705); + message->AddExtension(unittest::packed_sint64_extension_lite, 706); + message->AddExtension(unittest::packed_fixed32_extension_lite, 707); + message->AddExtension(unittest::packed_fixed64_extension_lite, 708); message->AddExtension(unittest::packed_sfixed32_extension_lite, 709); message->AddExtension(unittest::packed_sfixed64_extension_lite, 710); - message->AddExtension(unittest::packed_float_extension_lite , 711); - message->AddExtension(unittest::packed_double_extension_lite , 712); - message->AddExtension(unittest::packed_bool_extension_lite , false); - message->AddExtension(unittest::packed_enum_extension_lite, unittest::FOREIGN_LITE_BAZ); + message->AddExtension(unittest::packed_float_extension_lite, 711); + message->AddExtension(unittest::packed_double_extension_lite, 712); + message->AddExtension(unittest::packed_bool_extension_lite, false); + message->AddExtension(unittest::packed_enum_extension_lite, + unittest::FOREIGN_LITE_BAZ); } // ------------------------------------------------------------------- void TestUtilLite::ModifyPackedExtensions( unittest::TestPackedExtensionsLite* message) { - message->SetExtension(unittest::packed_int32_extension_lite , 1, 801); - message->SetExtension(unittest::packed_int64_extension_lite , 1, 802); - message->SetExtension(unittest::packed_uint32_extension_lite , 1, 803); - message->SetExtension(unittest::packed_uint64_extension_lite , 1, 804); - message->SetExtension(unittest::packed_sint32_extension_lite , 1, 805); - message->SetExtension(unittest::packed_sint64_extension_lite , 1, 806); - message->SetExtension(unittest::packed_fixed32_extension_lite , 1, 807); - message->SetExtension(unittest::packed_fixed64_extension_lite , 1, 808); + message->SetExtension(unittest::packed_int32_extension_lite, 1, 801); + message->SetExtension(unittest::packed_int64_extension_lite, 1, 802); + message->SetExtension(unittest::packed_uint32_extension_lite, 1, 803); + message->SetExtension(unittest::packed_uint64_extension_lite, 1, 804); + message->SetExtension(unittest::packed_sint32_extension_lite, 1, 805); + message->SetExtension(unittest::packed_sint64_extension_lite, 1, 806); + message->SetExtension(unittest::packed_fixed32_extension_lite, 1, 807); + message->SetExtension(unittest::packed_fixed64_extension_lite, 1, 808); message->SetExtension(unittest::packed_sfixed32_extension_lite, 1, 809); message->SetExtension(unittest::packed_sfixed64_extension_lite, 1, 810); - message->SetExtension(unittest::packed_float_extension_lite , 1, 811); - message->SetExtension(unittest::packed_double_extension_lite , 1, 812); - message->SetExtension(unittest::packed_bool_extension_lite , 1, true); - message->SetExtension(unittest::packed_enum_extension_lite , 1, + message->SetExtension(unittest::packed_float_extension_lite, 1, 811); + message->SetExtension(unittest::packed_double_extension_lite, 1, 812); + message->SetExtension(unittest::packed_bool_extension_lite, 1, true); + message->SetExtension(unittest::packed_enum_extension_lite, 1, unittest::FOREIGN_LITE_FOO); } @@ -1458,49 +1795,75 @@ void TestUtilLite::ModifyPackedExtensions( void TestUtilLite::ExpectPackedExtensionsSet( const unittest::TestPackedExtensionsLite& message) { - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension_lite)); ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension_lite)); ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension_lite)); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension_lite )); - - EXPECT_EQ(601 , message.GetExtension(unittest::packed_int32_extension_lite , 0)); - EXPECT_EQ(602 , message.GetExtension(unittest::packed_int64_extension_lite , 0)); - EXPECT_EQ(603 , message.GetExtension(unittest::packed_uint32_extension_lite , 0)); - EXPECT_EQ(604 , message.GetExtension(unittest::packed_uint64_extension_lite , 0)); - EXPECT_EQ(605 , message.GetExtension(unittest::packed_sint32_extension_lite , 0)); - EXPECT_EQ(606 , message.GetExtension(unittest::packed_sint64_extension_lite , 0)); - EXPECT_EQ(607 , message.GetExtension(unittest::packed_fixed32_extension_lite , 0)); - EXPECT_EQ(608 , message.GetExtension(unittest::packed_fixed64_extension_lite , 0)); - EXPECT_EQ(609 , message.GetExtension(unittest::packed_sfixed32_extension_lite, 0)); - EXPECT_EQ(610 , message.GetExtension(unittest::packed_sfixed64_extension_lite, 0)); - EXPECT_EQ(611 , message.GetExtension(unittest::packed_float_extension_lite , 0)); - EXPECT_EQ(612 , message.GetExtension(unittest::packed_double_extension_lite , 0)); - EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite , 0)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension_lite)); + + EXPECT_EQ(601, + message.GetExtension(unittest::packed_int32_extension_lite, 0)); + EXPECT_EQ(602, + message.GetExtension(unittest::packed_int64_extension_lite, 0)); + EXPECT_EQ(603, + message.GetExtension(unittest::packed_uint32_extension_lite, 0)); + EXPECT_EQ(604, + message.GetExtension(unittest::packed_uint64_extension_lite, 0)); + EXPECT_EQ(605, + message.GetExtension(unittest::packed_sint32_extension_lite, 0)); + EXPECT_EQ(606, + message.GetExtension(unittest::packed_sint64_extension_lite, 0)); + EXPECT_EQ(607, + message.GetExtension(unittest::packed_fixed32_extension_lite, 0)); + EXPECT_EQ(608, + message.GetExtension(unittest::packed_fixed64_extension_lite, 0)); + EXPECT_EQ(609, + message.GetExtension(unittest::packed_sfixed32_extension_lite, 0)); + EXPECT_EQ(610, + message.GetExtension(unittest::packed_sfixed64_extension_lite, 0)); + EXPECT_EQ(611, + message.GetExtension(unittest::packed_float_extension_lite, 0)); + EXPECT_EQ(612, + message.GetExtension(unittest::packed_double_extension_lite, 0)); + EXPECT_EQ(true, + message.GetExtension(unittest::packed_bool_extension_lite, 0)); EXPECT_EQ(unittest::FOREIGN_LITE_BAR, message.GetExtension(unittest::packed_enum_extension_lite, 0)); - EXPECT_EQ(701 , message.GetExtension(unittest::packed_int32_extension_lite , 1)); - EXPECT_EQ(702 , message.GetExtension(unittest::packed_int64_extension_lite , 1)); - EXPECT_EQ(703 , message.GetExtension(unittest::packed_uint32_extension_lite , 1)); - EXPECT_EQ(704 , message.GetExtension(unittest::packed_uint64_extension_lite , 1)); - EXPECT_EQ(705 , message.GetExtension(unittest::packed_sint32_extension_lite , 1)); - EXPECT_EQ(706 , message.GetExtension(unittest::packed_sint64_extension_lite , 1)); - EXPECT_EQ(707 , message.GetExtension(unittest::packed_fixed32_extension_lite , 1)); - EXPECT_EQ(708 , message.GetExtension(unittest::packed_fixed64_extension_lite , 1)); - EXPECT_EQ(709 , message.GetExtension(unittest::packed_sfixed32_extension_lite, 1)); - EXPECT_EQ(710 , message.GetExtension(unittest::packed_sfixed64_extension_lite, 1)); - EXPECT_EQ(711 , message.GetExtension(unittest::packed_float_extension_lite , 1)); - EXPECT_EQ(712 , message.GetExtension(unittest::packed_double_extension_lite , 1)); - EXPECT_EQ(false, message.GetExtension(unittest::packed_bool_extension_lite , 1)); + EXPECT_EQ(701, + message.GetExtension(unittest::packed_int32_extension_lite, 1)); + EXPECT_EQ(702, + message.GetExtension(unittest::packed_int64_extension_lite, 1)); + EXPECT_EQ(703, + message.GetExtension(unittest::packed_uint32_extension_lite, 1)); + EXPECT_EQ(704, + message.GetExtension(unittest::packed_uint64_extension_lite, 1)); + EXPECT_EQ(705, + message.GetExtension(unittest::packed_sint32_extension_lite, 1)); + EXPECT_EQ(706, + message.GetExtension(unittest::packed_sint64_extension_lite, 1)); + EXPECT_EQ(707, + message.GetExtension(unittest::packed_fixed32_extension_lite, 1)); + EXPECT_EQ(708, + message.GetExtension(unittest::packed_fixed64_extension_lite, 1)); + EXPECT_EQ(709, + message.GetExtension(unittest::packed_sfixed32_extension_lite, 1)); + EXPECT_EQ(710, + message.GetExtension(unittest::packed_sfixed64_extension_lite, 1)); + EXPECT_EQ(711, + message.GetExtension(unittest::packed_float_extension_lite, 1)); + EXPECT_EQ(712, + message.GetExtension(unittest::packed_double_extension_lite, 1)); + EXPECT_EQ(false, + message.GetExtension(unittest::packed_bool_extension_lite, 1)); EXPECT_EQ(unittest::FOREIGN_LITE_BAZ, message.GetExtension(unittest::packed_enum_extension_lite, 1)); } @@ -1509,70 +1872,96 @@ void TestUtilLite::ExpectPackedExtensionsSet( void TestUtilLite::ExpectPackedExtensionsClear( const unittest::TestPackedExtensionsLite& message) { - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int32_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int64_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint32_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint64_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint32_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint64_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed32_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int32_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int64_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint32_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint64_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint32_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint64_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed32_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed64_extension_lite)); EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed32_extension_lite)); EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed64_extension_lite)); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_float_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_double_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_bool_extension_lite )); - EXPECT_EQ(0, message.ExtensionSize(unittest::packed_enum_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_float_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_double_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_bool_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_enum_extension_lite)); } // ------------------------------------------------------------------- void TestUtilLite::ExpectPackedExtensionsModified( const unittest::TestPackedExtensionsLite& message) { - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension_lite)); ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension_lite)); ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension_lite)); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension_lite )); - ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension_lite )); - EXPECT_EQ(601 , message.GetExtension(unittest::packed_int32_extension_lite , 0)); - EXPECT_EQ(602 , message.GetExtension(unittest::packed_int64_extension_lite , 0)); - EXPECT_EQ(603 , message.GetExtension(unittest::packed_uint32_extension_lite , 0)); - EXPECT_EQ(604 , message.GetExtension(unittest::packed_uint64_extension_lite , 0)); - EXPECT_EQ(605 , message.GetExtension(unittest::packed_sint32_extension_lite , 0)); - EXPECT_EQ(606 , message.GetExtension(unittest::packed_sint64_extension_lite , 0)); - EXPECT_EQ(607 , message.GetExtension(unittest::packed_fixed32_extension_lite , 0)); - EXPECT_EQ(608 , message.GetExtension(unittest::packed_fixed64_extension_lite , 0)); - EXPECT_EQ(609 , message.GetExtension(unittest::packed_sfixed32_extension_lite, 0)); - EXPECT_EQ(610 , message.GetExtension(unittest::packed_sfixed64_extension_lite, 0)); - EXPECT_EQ(611 , message.GetExtension(unittest::packed_float_extension_lite , 0)); - EXPECT_EQ(612 , message.GetExtension(unittest::packed_double_extension_lite , 0)); - EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite , 0)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension_lite)); + EXPECT_EQ(601, + message.GetExtension(unittest::packed_int32_extension_lite, 0)); + EXPECT_EQ(602, + message.GetExtension(unittest::packed_int64_extension_lite, 0)); + EXPECT_EQ(603, + message.GetExtension(unittest::packed_uint32_extension_lite, 0)); + EXPECT_EQ(604, + message.GetExtension(unittest::packed_uint64_extension_lite, 0)); + EXPECT_EQ(605, + message.GetExtension(unittest::packed_sint32_extension_lite, 0)); + EXPECT_EQ(606, + message.GetExtension(unittest::packed_sint64_extension_lite, 0)); + EXPECT_EQ(607, + message.GetExtension(unittest::packed_fixed32_extension_lite, 0)); + EXPECT_EQ(608, + message.GetExtension(unittest::packed_fixed64_extension_lite, 0)); + EXPECT_EQ(609, + message.GetExtension(unittest::packed_sfixed32_extension_lite, 0)); + EXPECT_EQ(610, + message.GetExtension(unittest::packed_sfixed64_extension_lite, 0)); + EXPECT_EQ(611, + message.GetExtension(unittest::packed_float_extension_lite, 0)); + EXPECT_EQ(612, + message.GetExtension(unittest::packed_double_extension_lite, 0)); + EXPECT_EQ(true, + message.GetExtension(unittest::packed_bool_extension_lite, 0)); EXPECT_EQ(unittest::FOREIGN_LITE_BAR, message.GetExtension(unittest::packed_enum_extension_lite, 0)); // Actually verify the second (modified) elements now. - EXPECT_EQ(801 , message.GetExtension(unittest::packed_int32_extension_lite , 1)); - EXPECT_EQ(802 , message.GetExtension(unittest::packed_int64_extension_lite , 1)); - EXPECT_EQ(803 , message.GetExtension(unittest::packed_uint32_extension_lite , 1)); - EXPECT_EQ(804 , message.GetExtension(unittest::packed_uint64_extension_lite , 1)); - EXPECT_EQ(805 , message.GetExtension(unittest::packed_sint32_extension_lite , 1)); - EXPECT_EQ(806 , message.GetExtension(unittest::packed_sint64_extension_lite , 1)); - EXPECT_EQ(807 , message.GetExtension(unittest::packed_fixed32_extension_lite , 1)); - EXPECT_EQ(808 , message.GetExtension(unittest::packed_fixed64_extension_lite , 1)); - EXPECT_EQ(809 , message.GetExtension(unittest::packed_sfixed32_extension_lite, 1)); - EXPECT_EQ(810 , message.GetExtension(unittest::packed_sfixed64_extension_lite, 1)); - EXPECT_EQ(811 , message.GetExtension(unittest::packed_float_extension_lite , 1)); - EXPECT_EQ(812 , message.GetExtension(unittest::packed_double_extension_lite , 1)); - EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite , 1)); + EXPECT_EQ(801, + message.GetExtension(unittest::packed_int32_extension_lite, 1)); + EXPECT_EQ(802, + message.GetExtension(unittest::packed_int64_extension_lite, 1)); + EXPECT_EQ(803, + message.GetExtension(unittest::packed_uint32_extension_lite, 1)); + EXPECT_EQ(804, + message.GetExtension(unittest::packed_uint64_extension_lite, 1)); + EXPECT_EQ(805, + message.GetExtension(unittest::packed_sint32_extension_lite, 1)); + EXPECT_EQ(806, + message.GetExtension(unittest::packed_sint64_extension_lite, 1)); + EXPECT_EQ(807, + message.GetExtension(unittest::packed_fixed32_extension_lite, 1)); + EXPECT_EQ(808, + message.GetExtension(unittest::packed_fixed64_extension_lite, 1)); + EXPECT_EQ(809, + message.GetExtension(unittest::packed_sfixed32_extension_lite, 1)); + EXPECT_EQ(810, + message.GetExtension(unittest::packed_sfixed64_extension_lite, 1)); + EXPECT_EQ(811, + message.GetExtension(unittest::packed_float_extension_lite, 1)); + EXPECT_EQ(812, + message.GetExtension(unittest::packed_double_extension_lite, 1)); + EXPECT_EQ(true, + message.GetExtension(unittest::packed_bool_extension_lite, 1)); EXPECT_EQ(unittest::FOREIGN_LITE_FOO, message.GetExtension(unittest::packed_enum_extension_lite, 1)); } diff --git a/src/google/protobuf/test_util_lite.h b/src/google/protobuf/test_util_lite.h index 47a2269d363c5..34edf9443dfc3 100644 --- a/src/google/protobuf/test_util_lite.h +++ b/src/google/protobuf/test_util_lite.h @@ -96,6 +96,6 @@ class TestUtilLite { }; } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_TEST_UTIL_LITE_H__ diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc index f32222b7c4c52..7b628879c64e8 100644 --- a/src/google/protobuf/testing/file.cc +++ b/src/google/protobuf/testing/file.cc @@ -45,7 +45,8 @@ #endif #include -#include +#include +#include namespace google { namespace protobuf { @@ -57,21 +58,22 @@ namespace protobuf { // them like we do below. #endif -#ifdef _MSC_VER -using google::protobuf::internal::win32::access; -using google::protobuf::internal::win32::chdir; -using google::protobuf::internal::win32::fopen; -using google::protobuf::internal::win32::mkdir; -using google::protobuf::internal::win32::stat; +#ifdef _WIN32 +using google::protobuf::io::win32::access; +using google::protobuf::io::win32::chdir; +using google::protobuf::io::win32::fopen; +using google::protobuf::io::win32::mkdir; +using google::protobuf::io::win32::stat; #endif -bool File::Exists(const string& name) { +bool File::Exists(const std::string& name) { return access(name.c_str(), F_OK) == 0; } -bool File::ReadFileToString(const string& name, string* output) { +bool File::ReadFileToString(const std::string& name, std::string* output, + bool text_mode) { char buffer[1024]; - FILE* file = fopen(name.c_str(), "rb"); + FILE* file = fopen(name.c_str(), text_mode ? "rt" : "rb"); if (file == NULL) return false; while (true) { @@ -85,11 +87,12 @@ bool File::ReadFileToString(const string& name, string* output) { return error == 0; } -void File::ReadFileToStringOrDie(const string& name, string* output) { +void File::ReadFileToStringOrDie(const std::string& name, std::string* output) { GOOGLE_CHECK(ReadFileToString(name, output)) << "Could not read: " << name; } -bool File::WriteStringToFile(const string& contents, const string& name) { +bool File::WriteStringToFile(const std::string& contents, + const std::string& name) { FILE* file = fopen(name.c_str(), "wb"); if (file == NULL) { GOOGLE_LOG(ERROR) << "fopen(" << name << ", \"wb\"): " << strerror(errno); @@ -108,7 +111,8 @@ bool File::WriteStringToFile(const string& contents, const string& name) { return true; } -void File::WriteStringToFileOrDie(const string& contents, const string& name) { +void File::WriteStringToFileOrDie(const std::string& contents, + const std::string& name) { FILE* file = fopen(name.c_str(), "wb"); GOOGLE_CHECK(file != NULL) << "fopen(" << name << ", \"wb\"): " << strerror(errno); @@ -119,21 +123,21 @@ void File::WriteStringToFileOrDie(const string& contents, const string& name) { << "fclose(" << name << "): " << strerror(errno); } -bool File::CreateDir(const string& name, int mode) { +bool File::CreateDir(const std::string& name, int mode) { if (!name.empty()) { - GOOGLE_CHECK_OK(name.back() != '.'); + GOOGLE_CHECK_OK(name[name.size() - 1] != '.'); } return mkdir(name.c_str(), mode) == 0; } -bool File::RecursivelyCreateDir(const string& path, int mode) { +bool File::RecursivelyCreateDir(const std::string& path, int mode) { if (CreateDir(path, mode)) return true; if (Exists(path)) return false; // Try creating the parent. - string::size_type slashpos = path.find_last_of('/'); - if (slashpos == string::npos) { + std::string::size_type slashpos = path.find_last_of('/'); + if (slashpos == std::string::npos) { // No parent given. return false; } @@ -142,8 +146,8 @@ bool File::RecursivelyCreateDir(const string& path, int mode) { CreateDir(path, mode); } -void File::DeleteRecursively(const string& name, - void* dummy1, void* dummy2) { +void File::DeleteRecursively(const std::string& name, void* dummy1, + void* dummy2) { if (name.empty()) return; // We don't care too much about error checking here since this is only used @@ -161,9 +165,9 @@ void File::DeleteRecursively(const string& name, } do { - string entry_name = find_data.cFileName; + std::string entry_name = find_data.cFileName; if (entry_name != "." && entry_name != "..") { - string path = name + "/" + entry_name; + std::string path = name + "/" + entry_name; if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { DeleteRecursively(path, NULL, NULL); RemoveDirectoryA(path.c_str()); @@ -187,7 +191,7 @@ void File::DeleteRecursively(const string& name, while (true) { struct dirent* entry = readdir(dir); if (entry == NULL) break; - string entry_name = entry->d_name; + std::string entry_name = entry->d_name; if (entry_name != "." && entry_name != "..") { DeleteRecursively(name + "/" + entry_name, NULL, NULL); } @@ -203,7 +207,7 @@ void File::DeleteRecursively(const string& name, #endif } -bool File::ChangeWorkingDirectory(const string& new_working_directory) { +bool File::ChangeWorkingDirectory(const std::string& new_working_directory) { return chdir(new_working_directory.c_str()) == 0; } diff --git a/src/google/protobuf/testing/file.h b/src/google/protobuf/testing/file.h index 2f63f80e7b294..f18f68586521d 100644 --- a/src/google/protobuf/testing/file.h +++ b/src/google/protobuf/testing/file.h @@ -46,47 +46,54 @@ const int DEFAULT_FILE_MODE = 0777; class File { public: // Check if the file exists. - static bool Exists(const string& name); + static bool Exists(const std::string& name); // Read an entire file to a string. Return true if successful, false // otherwise. - static bool ReadFileToString(const string& name, string* output); + static bool ReadFileToString(const std::string& name, std::string* output, + bool text_mode = false); // Same as above, but crash on failure. - static void ReadFileToStringOrDie(const string& name, string* output); + static void ReadFileToStringOrDie(const std::string& name, + std::string* output); // Create a file and write a string to it. - static bool WriteStringToFile(const string& contents, - const string& name); + static bool WriteStringToFile(const std::string& contents, + const std::string& name); // Same as above, but crash on failure. - static void WriteStringToFileOrDie(const string& contents, - const string& name); + static void WriteStringToFileOrDie(const std::string& contents, + const std::string& name); // Create a directory. - static bool CreateDir(const string& name, int mode); + static bool CreateDir(const std::string& name, int mode); // Create a directory and all parent directories if necessary. - static bool RecursivelyCreateDir(const string& path, int mode); + static bool RecursivelyCreateDir(const std::string& path, int mode); // If "name" is a file, we delete it. If it is a directory, we // call DeleteRecursively() for each file or directory (other than // dot and double-dot) within it, and then delete the directory itself. // The "dummy" parameters have a meaning in the original version of this // method but they are not used anywhere in protocol buffers. - static void DeleteRecursively(const string& name, - void* dummy1, void* dummy2); + static void DeleteRecursively(const std::string& name, void* dummy1, + void* dummy2); // Change working directory to given directory. - static bool ChangeWorkingDirectory(const string& new_working_directory); + static bool ChangeWorkingDirectory(const std::string& new_working_directory); - static bool GetContents( - const string& name, string* output, bool /*is_default*/) { + static bool GetContents(const std::string& name, std::string* output, + bool /*is_default*/) { return ReadFileToString(name, output); } - static bool SetContents( - const string& name, const string& contents, bool /*is_default*/) { + static bool GetContentsAsText(const std::string& name, std::string* output, + bool /*is_default*/) { + return ReadFileToString(name, output, true); + } + + static bool SetContents(const std::string& name, const std::string& contents, + bool /*is_default*/) { return WriteStringToFile(contents, name); } diff --git a/src/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc index 33a75ed68097b..88343f934761a 100644 --- a/src/google/protobuf/testing/googletest.cc +++ b/src/google/protobuf/testing/googletest.cc @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include #include @@ -52,14 +52,14 @@ namespace google { namespace protobuf { -#ifdef _MSC_VER +#ifdef _WIN32 // DO NOT include , instead create functions in io_win32.{h,cc} and import // them like we do below. -using google::protobuf::internal::win32::close; -using google::protobuf::internal::win32::dup2; -using google::protobuf::internal::win32::dup; -using google::protobuf::internal::win32::mkdir; -using google::protobuf::internal::win32::open; +using google::protobuf::io::win32::close; +using google::protobuf::io::win32::dup2; +using google::protobuf::io::win32::dup; +using google::protobuf::io::win32::mkdir; +using google::protobuf::io::win32::open; #endif #ifndef O_BINARY @@ -70,7 +70,7 @@ using google::protobuf::internal::win32::open; #endif #endif -string TestSourceDir() { +std::string TestSourceDir() { #ifndef GOOGLE_THIRD_PARTY_PROTOBUF #ifdef GOOGLE_PROTOBUF_TEST_SOURCE_PATH return GOOGLE_PROTOBUF_TEST_SOURCE_PATH; @@ -84,9 +84,13 @@ string TestSourceDir() { #endif // _MSC_VER // Look for the "src" directory. - string prefix = "."; + std::string prefix = "."; - while (!File::Exists(prefix + "/src/google/protobuf")) { + // Keep looking further up the directory tree until we find + // src/.../descriptor.cc. It is important to look for a particular file, + // keeping in mind that with Bazel builds the directory structure under + // bazel-bin/ looks similar to the main directory tree in the Git repo. + while (!File::Exists(prefix + "/src/google/protobuf/descriptor.cc")) { if (!File::Exists(prefix)) { GOOGLE_LOG(FATAL) << "Could not find protobuf source code. Please run tests from " @@ -103,19 +107,22 @@ string TestSourceDir() { namespace { -string GetTemporaryDirectoryName() { +std::string GetTemporaryDirectoryName() { // Tests run under Bazel "should not" use /tmp. Bazel sets this environment // variable for tests to use instead. char *from_environment = getenv("TEST_TMPDIR"); if (from_environment != NULL && from_environment[0] != '\0') { - return string(from_environment) + "/protobuf_tmpdir"; + return std::string(from_environment) + "/protobuf_tmpdir"; } // tmpnam() is generally not considered safe but we're only using it for // testing. We cannot use tmpfile() or mkstemp() since we're creating a // directory. char b[L_tmpnam + 1]; // HPUX multithread return 0 if s is 0 - string result = tmpnam(b); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + std::string result = tmpnam(b); +#pragma GCC diagnostic pop #ifdef _WIN32 // Avoid a trailing dot by changing it to an underscore. On Win32 the names of // files and directories can, but should not, end with dot. @@ -132,7 +139,7 @@ string GetTemporaryDirectoryName() { // with "\\?\") but these will be degenerate in the sense that you cannot // chdir into such directories (or navigate into them with Windows Explorer) // nor can you open such files with some programs (e.g. Notepad). - if (result.back() == '.') { + if (result[result.size() - 1] == '.') { result[result.size() - 1] = '_'; } // On Win32, tmpnam() returns a file prefixed with '\', but which is supposed @@ -159,7 +166,7 @@ class TempDirDeleter { } } - string GetTempDir() { + std::string GetTempDir() { if (name_.empty()) { name_ = GetTemporaryDirectoryName(); GOOGLE_CHECK(mkdir(name_.c_str(), 0777) == 0) << strerror(errno); @@ -172,21 +179,19 @@ class TempDirDeleter { } private: - string name_; + std::string name_; }; TempDirDeleter temp_dir_deleter_; } // namespace -string TestTempDir() { - return temp_dir_deleter_.GetTempDir(); -} +std::string TestTempDir() { return temp_dir_deleter_.GetTempDir(); } // TODO(kenton): Share duplicated code below. Too busy/lazy for now. -static string stdout_capture_filename_; -static string stderr_capture_filename_; +static std::string stdout_capture_filename_; +static std::string stderr_capture_filename_; static int original_stdout_ = -1; static int original_stderr_ = -1; @@ -220,14 +225,14 @@ void CaptureTestStderr() { close(fd); } -string GetCapturedTestStdout() { +std::string GetCapturedTestStdout() { GOOGLE_CHECK_NE(original_stdout_, -1) << "Not capturing."; close(1); dup2(original_stdout_, 1); original_stdout_ = -1; - string result; + std::string result; File::ReadFileToStringOrDie(stdout_capture_filename_, &result); remove(stdout_capture_filename_.c_str()); @@ -235,14 +240,14 @@ string GetCapturedTestStdout() { return result; } -string GetCapturedTestStderr() { +std::string GetCapturedTestStderr() { GOOGLE_CHECK_NE(original_stderr_, -1) << "Not capturing."; close(2); dup2(original_stderr_, 2); original_stderr_ = -1; - string result; + std::string result; File::ReadFileToStringOrDie(stderr_capture_filename_, &result); remove(stderr_capture_filename_.c_str()); @@ -263,14 +268,14 @@ ScopedMemoryLog::~ScopedMemoryLog() { active_log_ = NULL; } -const vector& ScopedMemoryLog::GetMessages(LogLevel level) { +const std::vector& ScopedMemoryLog::GetMessages(LogLevel level) { GOOGLE_CHECK(level == ERROR || level == WARNING); return messages_[level]; } -void ScopedMemoryLog::HandleLog(LogLevel level, const char* filename, - int line, const string& message) { +void ScopedMemoryLog::HandleLog(LogLevel level, const char* filename, int line, + const std::string& message) { GOOGLE_CHECK(active_log_ != NULL); if (level == ERROR || level == WARNING) { active_log_->messages_[level].push_back(message); @@ -286,6 +291,8 @@ namespace { struct ForceShutdown { ~ForceShutdown() { ShutdownProtobufLibrary(); + // Test to shutdown the library twice, which should succeed. + ShutdownProtobufLibrary(); } } force_shutdown; diff --git a/src/google/protobuf/testing/googletest.h b/src/google/protobuf/testing/googletest.h index dc4401d032af8..6a0c694e71a6a 100644 --- a/src/google/protobuf/testing/googletest.h +++ b/src/google/protobuf/testing/googletest.h @@ -37,9 +37,11 @@ #include #include #include +#include #include // Disable death tests if we use exceptions in CHECK(). -#if !PROTOBUF_USE_EXCEPTIONS && defined(GTEST_HAS_DEATH_TEST) +#if !PROTOBUF_USE_EXCEPTIONS && defined(GTEST_HAS_DEATH_TEST) && \ + !GTEST_OS_WINDOWS #define PROTOBUF_HAS_DEATH_TEST #endif @@ -47,19 +49,19 @@ namespace google { namespace protobuf { // When running unittests, get the directory containing the source code. -string TestSourceDir(); +std::string TestSourceDir(); // When running unittests, get a directory where temporary files may be // placed. -string TestTempDir(); +std::string TestTempDir(); // Capture all text written to stdout or stderr. void CaptureTestStdout(); void CaptureTestStderr(); // Stop capturing stdout or stderr and return the text captured. -string GetCapturedTestStdout(); -string GetCapturedTestStderr(); +std::string GetCapturedTestStdout(); +std::string GetCapturedTestStderr(); // For use with ScopedMemoryLog::GetMessages(). Inside Google the LogLevel // constants don't have the LOGLEVEL_ prefix, so the code that used @@ -82,14 +84,14 @@ class ScopedMemoryLog { virtual ~ScopedMemoryLog(); // Fetches all messages with the given severity level. - const vector& GetMessages(LogLevel error); + const std::vector& GetMessages(LogLevel error); private: - std::map > messages_; + std::map > messages_; LogHandler* old_handler_; static void HandleLog(LogLevel level, const char* filename, int line, - const string& message); + const std::string& message); static ScopedMemoryLog* active_log_; diff --git a/src/google/protobuf/testing/zcgunzip.cc b/src/google/protobuf/testing/zcgunzip.cc index 76f8cfe11b2b3..68f8172f618db 100644 --- a/src/google/protobuf/testing/zcgunzip.cc +++ b/src/google/protobuf/testing/zcgunzip.cc @@ -39,9 +39,10 @@ // output. #include +#include #include #include -#include +#include #ifdef _WIN32 #ifndef STDIN_FILENO @@ -72,7 +73,10 @@ int main(int argc, const char** argv) { } if (inlen > 0) { int err = write(STDOUT_FILENO, inptr, inlen); - assert(err == inlen); + if (err != inlen) { + fprintf(stderr, "write unexpectedly returned %d.\n", err); + return 1; + } } } diff --git a/src/google/protobuf/testing/zcgzip.cc b/src/google/protobuf/testing/zcgzip.cc index 992ddc6ed66b3..808d058a1e528 100644 --- a/src/google/protobuf/testing/zcgzip.cc +++ b/src/google/protobuf/testing/zcgzip.cc @@ -38,9 +38,10 @@ // Reads data on standard input and writes compressed gzip stream to standard // output. +#include #include #include -#include +#include #ifdef _WIN32 #ifndef STDIN_FILENO diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index f1d2e8bc0f4c4..2abd92766cf90 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -32,53 +32,59 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include +#include + #include -#include #include -#include + +#include +#include +#include #include #include -#include - #include #include -#include +#include #include #include #include #include -#include #include #include +#include +#include #include #include #include #include - +#include #include #include +// Must be included last. +#include + + namespace google { namespace protobuf { namespace { -inline bool IsHexNumber(const string& str) { +inline bool IsHexNumber(const std::string& str) { return (str.length() >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')); } -inline bool IsOctNumber(const string& str) { +inline bool IsOctNumber(const std::string& str) { return (str.length() >= 2 && str[0] == '0' && (str[1] >= '0' && str[1] < '8')); } } // namespace -string Message::DebugString() const { - string debug_string; +std::string Message::DebugString() const { + std::string debug_string; TextFormat::Printer printer; printer.SetExpandAny(true); @@ -88,8 +94,8 @@ string Message::DebugString() const { return debug_string; } -string Message::ShortDebugString() const { - string debug_string; +std::string Message::ShortDebugString() const { + std::string debug_string; TextFormat::Printer printer; printer.SetSingleLineMode(true); @@ -97,16 +103,15 @@ string Message::ShortDebugString() const { printer.PrintToString(*this, &debug_string); // Single line mode currently might have an extra space at the end. - if (debug_string.size() > 0 && - debug_string[debug_string.size() - 1] == ' ') { + if (!debug_string.empty() && debug_string[debug_string.size() - 1] == ' ') { debug_string.resize(debug_string.size() - 1); } return debug_string; } -string Message::Utf8DebugString() const { - string debug_string; +std::string Message::Utf8DebugString() const { + std::string debug_string; TextFormat::Printer printer; printer.SetUseUtf8StringEscaping(true); @@ -117,40 +122,28 @@ string Message::Utf8DebugString() const { return debug_string; } -void Message::PrintDebugString() const { - printf("%s", DebugString().c_str()); -} +void Message::PrintDebugString() const { printf("%s", DebugString().c_str()); } // =========================================================================== // Implementation of the parse information tree class. -TextFormat::ParseInfoTree::ParseInfoTree() { } - -TextFormat::ParseInfoTree::~ParseInfoTree() { - // Remove any nested information trees, as they are owned by this tree. - for (NestedMap::iterator it = nested_.begin(); it != nested_.end(); ++it) { - STLDeleteElements(&(it->second)); - } -} - void TextFormat::ParseInfoTree::RecordLocation( - const FieldDescriptor* field, - TextFormat::ParseLocation location) { + const FieldDescriptor* field, TextFormat::ParseLocation location) { locations_[field].push_back(location); } TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::CreateNested( const FieldDescriptor* field) { // Owned by us in the map. - TextFormat::ParseInfoTree* instance = new TextFormat::ParseInfoTree(); - std::vector* trees = &nested_[field]; - GOOGLE_CHECK(trees); - trees->push_back(instance); - return instance; + auto& vec = nested_[field]; + vec.emplace_back(new TextFormat::ParseInfoTree()); + return vec.back().get(); } void CheckFieldIndex(const FieldDescriptor* field, int index) { - if (field == NULL) { return; } + if (field == nullptr) { + return; + } if (field->is_repeated() && index == -1) { GOOGLE_LOG(DFATAL) << "Index must be in range of repeated field values. " @@ -164,11 +157,13 @@ void CheckFieldIndex(const FieldDescriptor* field, int index) { TextFormat::ParseLocation TextFormat::ParseInfoTree::GetLocation( const FieldDescriptor* field, int index) const { CheckFieldIndex(field, index); - if (index == -1) { index = 0; } + if (index == -1) { + index = 0; + } const std::vector* locations = FindOrNull(locations_, field); - if (locations == NULL || index >= locations->size()) { + if (locations == nullptr || index >= static_cast(locations->size())) { return TextFormat::ParseLocation(); } @@ -178,33 +173,62 @@ TextFormat::ParseLocation TextFormat::ParseInfoTree::GetLocation( TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested( const FieldDescriptor* field, int index) const { CheckFieldIndex(field, index); - if (index == -1) { index = 0; } + if (index == -1) { + index = 0; + } - const std::vector* trees = - FindOrNull(nested_, field); - if (trees == NULL || index >= trees->size()) { - return NULL; + auto it = nested_.find(field); + if (it == nested_.end() || index >= static_cast(it->second.size())) { + return nullptr; } - return (*trees)[index]; + return it->second[index].get(); } +namespace { +// These functions implement the behavior of the "default" TextFormat::Finder, +// they are defined as standalone to be called when finder_ is nullptr. +const FieldDescriptor* DefaultFinderFindExtension(Message* message, + const std::string& name) { + const Descriptor* descriptor = message->GetDescriptor(); + return descriptor->file()->pool()->FindExtensionByPrintableName(descriptor, + name); +} + +const FieldDescriptor* DefaultFinderFindExtensionByNumber( + const Descriptor* descriptor, int number) { + return descriptor->file()->pool()->FindExtensionByNumber(descriptor, number); +} + +const Descriptor* DefaultFinderFindAnyType(const Message& message, + const std::string& prefix, + const std::string& name) { + if (prefix != internal::kTypeGoogleApisComPrefix && + prefix != internal::kTypeGoogleProdComPrefix) { + return nullptr; + } + return message.GetDescriptor()->file()->pool()->FindMessageTypeByName(name); +} +} // namespace // =========================================================================== // Internal class for parsing an ASCII representation of a Protocol Message. // This class makes use of the Protocol Message compiler's tokenizer found -// in //google/protobuf/io/tokenizer.h. Note that class's Parse +// in //net/proto2/io/public/tokenizer.h. Note that class's Parse // method is *not* thread-safe and should only be used in a single thread at // a time. // Makes code slightly more readable. The meaning of "DO(foo)" is // "Execute foo and fail if it fails.", where failure is indicated by // returning false. Borrowed from parser.cc (Thanks Kenton!). -#define DO(STATEMENT) if (STATEMENT) {} else return false +#define DO(STATEMENT) \ + if (STATEMENT) { \ + } else { \ + return false; \ + } class TextFormat::Parser::ParserImpl { public: - // Determines if repeated values for non-repeated fields and // oneofs are permitted, e.g., the string "foo: 1 foo: 2" for a // required/optional field named "foo", or "baz: 1 qux: 2" @@ -217,28 +241,28 @@ class TextFormat::Parser::ParserImpl { ParserImpl(const Descriptor* root_message_type, io::ZeroCopyInputStream* input_stream, io::ErrorCollector* error_collector, - TextFormat::Finder* finder, - ParseInfoTree* parse_info_tree, + const TextFormat::Finder* finder, ParseInfoTree* parse_info_tree, SingularOverwritePolicy singular_overwrite_policy, - bool allow_case_insensitive_field, - bool allow_unknown_field, - bool allow_unknown_enum, - bool allow_field_number, - bool allow_relaxed_whitespace, - bool allow_partial) - : error_collector_(error_collector), - finder_(finder), - parse_info_tree_(parse_info_tree), - tokenizer_error_collector_(this), - tokenizer_(input_stream, &tokenizer_error_collector_), - root_message_type_(root_message_type), - singular_overwrite_policy_(singular_overwrite_policy), - allow_case_insensitive_field_(allow_case_insensitive_field), - allow_unknown_field_(allow_unknown_field), - allow_unknown_enum_(allow_unknown_enum), - allow_field_number_(allow_field_number), - allow_partial_(allow_partial), - had_errors_(false) { + bool allow_case_insensitive_field, bool allow_unknown_field, + bool allow_unknown_extension, bool allow_unknown_enum, + bool allow_field_number, bool allow_relaxed_whitespace, + bool allow_partial, int recursion_limit) + : error_collector_(error_collector), + finder_(finder), + parse_info_tree_(parse_info_tree), + tokenizer_error_collector_(this), + tokenizer_(input_stream, &tokenizer_error_collector_), + root_message_type_(root_message_type), + singular_overwrite_policy_(singular_overwrite_policy), + allow_case_insensitive_field_(allow_case_insensitive_field), + allow_unknown_field_(allow_unknown_field), + allow_unknown_extension_(allow_unknown_extension), + allow_unknown_enum_(allow_unknown_enum), + allow_field_number_(allow_field_number), + allow_partial_(allow_partial), + initial_recursion_limit_(recursion_limit), + recursion_limit_(recursion_limit), + had_errors_(false) { // For backwards-compatibility with proto1, we need to allow the 'f' suffix // for floats. tokenizer_.set_allow_f_after_float(true); @@ -254,7 +278,7 @@ class TextFormat::Parser::ParserImpl { // Consume the starting token. tokenizer_.Next(); } - ~ParserImpl() { } + ~ParserImpl() {} // Parses the ASCII representation specified in input and saves the // information into the output pointer (a Message). Returns @@ -264,6 +288,15 @@ class TextFormat::Parser::ParserImpl { // Consume fields until we cannot do so anymore. while (true) { if (LookingAtType(io::Tokenizer::TYPE_END)) { + // Ensures recursion limit properly unwinded, but only for success + // cases. This implicitly avoids the check when `Parse` returns false + // via `DO(...)`. + GOOGLE_DCHECK(had_errors_ || recursion_limit_ == initial_recursion_limit_) + << "Recursion limit at end of parse should be " + << initial_recursion_limit_ << ", but was " << recursion_limit_ + << ". Difference of " << initial_recursion_limit_ - recursion_limit_ + << " stack frames not accounted for stack unwind."; + return !had_errors_; } @@ -281,35 +314,31 @@ class TextFormat::Parser::ParserImpl { return suc && LookingAtType(io::Tokenizer::TYPE_END); } - void ReportError(int line, int col, const string& message) { + void ReportError(int line, int col, const std::string& message) { had_errors_ = true; - if (error_collector_ == NULL) { + if (error_collector_ == nullptr) { if (line >= 0) { GOOGLE_LOG(ERROR) << "Error parsing text-format " - << root_message_type_->full_name() - << ": " << (line + 1) << ":" - << (col + 1) << ": " << message; + << root_message_type_->full_name() << ": " << (line + 1) + << ":" << (col + 1) << ": " << message; } else { GOOGLE_LOG(ERROR) << "Error parsing text-format " - << root_message_type_->full_name() - << ": " << message; + << root_message_type_->full_name() << ": " << message; } } else { error_collector_->AddError(line, col, message); } } - void ReportWarning(int line, int col, const string& message) { - if (error_collector_ == NULL) { + void ReportWarning(int line, int col, const std::string& message) { + if (error_collector_ == nullptr) { if (line >= 0) { GOOGLE_LOG(WARNING) << "Warning parsing text-format " - << root_message_type_->full_name() - << ": " << (line + 1) << ":" - << (col + 1) << ": " << message; + << root_message_type_->full_name() << ": " << (line + 1) + << ":" << (col + 1) << ": " << message; } else { GOOGLE_LOG(WARNING) << "Warning parsing text-format " - << root_message_type_->full_name() - << ": " << message; + << root_message_type_->full_name() << ": " << message; } } else { error_collector_->AddWarning(line, col, message); @@ -321,14 +350,14 @@ class TextFormat::Parser::ParserImpl { // Reports an error with the given message with information indicating // the position (as derived from the current token). - void ReportError(const string& message) { + void ReportError(const std::string& message) { ReportError(tokenizer_.current().line, tokenizer_.current().column, message); } // Reports a warning with the given message with information indicating // the position (as derived from the current token). - void ReportWarning(const string& message) { + void ReportWarning(const std::string& message) { ReportWarning(tokenizer_.current().line, tokenizer_.current().column, message); } @@ -336,8 +365,8 @@ class TextFormat::Parser::ParserImpl { // Consumes the specified message with the given starting delimiter. // This method checks to see that the end delimiter at the conclusion of // the consumption matches the starting delimiter passed in here. - bool ConsumeMessage(Message* message, const string delimiter) { - while (!LookingAt(">") && !LookingAt("}")) { + bool ConsumeMessage(Message* message, const std::string delimiter) { + while (!LookingAt(">") && !LookingAt("}")) { DO(ConsumeField(message)); } @@ -347,7 +376,7 @@ class TextFormat::Parser::ParserImpl { } // Consume either "<" or "{". - bool ConsumeMessageDelimiter(string* delimiter) { + bool ConsumeMessageDelimiter(std::string* delimiter) { if (TryConsume("<")) { *delimiter = ">"; } else { @@ -364,9 +393,9 @@ class TextFormat::Parser::ParserImpl { const Reflection* reflection = message->GetReflection(); const Descriptor* descriptor = message->GetDescriptor(); - string field_name; + std::string field_name; bool reserved_field = false; - const FieldDescriptor* field = NULL; + const FieldDescriptor* field = nullptr; int start_line = tokenizer_.current().line; int start_column = tokenizer_.current().column; @@ -375,14 +404,20 @@ class TextFormat::Parser::ParserImpl { if (internal::GetAnyFieldDescriptors(*message, &any_type_url_field, &any_value_field) && TryConsume("[")) { - string full_type_name, prefix; + std::string full_type_name, prefix; DO(ConsumeAnyTypeUrl(&full_type_name, &prefix)); DO(Consume("]")); TryConsume(":"); // ':' is optional between message labels and values. - string serialized_value; - DO(ConsumeAnyValue(full_type_name, - message->GetDescriptor()->file()->pool(), - &serialized_value)); + std::string serialized_value; + const Descriptor* value_descriptor = + finder_ ? finder_->FindAnyType(*message, prefix, full_type_name) + : DefaultFinderFindAnyType(*message, prefix, full_type_name); + if (value_descriptor == nullptr) { + ReportError("Could not find type \"" + prefix + full_type_name + + "\" stored in google.protobuf.Any."); + return false; + } + DO(ConsumeAnyValue(value_descriptor, &serialized_value)); if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) { // Fail if any_type_url_field has already been specified. if ((!any_type_url_field->is_repeated() && @@ -393,9 +428,8 @@ class TextFormat::Parser::ParserImpl { return false; } } - reflection->SetString( - message, any_type_url_field, - string(prefix + full_type_name)); + reflection->SetString(message, any_type_url_field, + std::string(prefix + full_type_name)); reflection->SetString(message, any_value_field, serialized_value); return true; } @@ -404,19 +438,19 @@ class TextFormat::Parser::ParserImpl { DO(ConsumeFullTypeName(&field_name)); DO(Consume("]")); - field = (finder_ != NULL - ? finder_->FindExtension(message, field_name) - : reflection->FindKnownExtensionByName(field_name)); + field = finder_ ? finder_->FindExtension(message, field_name) + : DefaultFinderFindExtension(message, field_name); - if (field == NULL) { - if (!allow_unknown_field_) { - ReportError("Extension \"" + field_name + "\" is not defined or " + if (field == nullptr) { + if (!allow_unknown_field_ && !allow_unknown_extension_) { + ReportError("Extension \"" + field_name + + "\" is not defined or " "is not an extension of \"" + descriptor->full_name() + "\"."); return false; } else { - ReportWarning("Extension \"" + field_name + "\" is not defined or " - "is not an extension of \"" + + ReportWarning("Ignoring extension \"" + field_name + + "\" which is not defined or is not an extension of \"" + descriptor->full_name() + "\"."); } } @@ -426,7 +460,10 @@ class TextFormat::Parser::ParserImpl { int32 field_number; if (allow_field_number_ && safe_strto32(field_name, &field_number)) { if (descriptor->IsExtensionNumber(field_number)) { - field = reflection->FindKnownExtensionByNumber(field_number); + field = finder_ + ? finder_->FindExtensionByNumber(descriptor, field_number) + : DefaultFinderFindExtensionByNumber(descriptor, + field_number); } else if (descriptor->IsReservedNumber(field_number)) { reserved_field = true; } else { @@ -437,33 +474,34 @@ class TextFormat::Parser::ParserImpl { // Group names are expected to be capitalized as they appear in the // .proto file, which actually matches their type names, not their // field names. - if (field == NULL) { - string lower_field_name = field_name; + if (field == nullptr) { + std::string lower_field_name = field_name; LowerString(&lower_field_name); field = descriptor->FindFieldByName(lower_field_name); // If the case-insensitive match worked but the field is NOT a group, - if (field != NULL && field->type() != FieldDescriptor::TYPE_GROUP) { - field = NULL; + if (field != nullptr && + field->type() != FieldDescriptor::TYPE_GROUP) { + field = nullptr; } } // Again, special-case group names as described above. - if (field != NULL && field->type() == FieldDescriptor::TYPE_GROUP - && field->message_type()->name() != field_name) { - field = NULL; + if (field != nullptr && field->type() == FieldDescriptor::TYPE_GROUP && + field->message_type()->name() != field_name) { + field = nullptr; } - if (field == NULL && allow_case_insensitive_field_) { - string lower_field_name = field_name; + if (field == nullptr && allow_case_insensitive_field_) { + std::string lower_field_name = field_name; LowerString(&lower_field_name); field = descriptor->FindFieldByLowercaseName(lower_field_name); } - if (field == NULL) { + if (field == nullptr) { reserved_field = descriptor->IsReservedName(field_name); } } - if (field == NULL && !reserved_field) { + if (field == nullptr && !reserved_field) { if (!allow_unknown_field_) { ReportError("Message type \"" + descriptor->full_name() + "\" has no field named \"" + field_name + "\"."); @@ -476,8 +514,8 @@ class TextFormat::Parser::ParserImpl { } // Skips unknown or reserved fields. - if (field == NULL) { - GOOGLE_CHECK(allow_unknown_field_ || reserved_field); + if (field == nullptr) { + GOOGLE_CHECK(allow_unknown_field_ || allow_unknown_extension_ || reserved_field); // Try to guess the type of this field. // If this field is not a message, there should be a ":" between the @@ -502,12 +540,16 @@ class TextFormat::Parser::ParserImpl { // Fail if the field is a member of a oneof and another member has already // been specified. const OneofDescriptor* oneof = field->containing_oneof(); - if (oneof != NULL && reflection->HasOneof(*message, oneof)) { + if (oneof != nullptr && reflection->HasOneof(*message, oneof)) { const FieldDescriptor* other_field = reflection->GetOneofFieldDescriptor(*message, oneof); - ReportError("Field \"" + field_name + "\" is specified along with " - "field \"" + other_field->name() + "\", another member " - "of oneof \"" + oneof->name() + "\"."); + ReportError("Field \"" + field_name + + "\" is specified along with " + "field \"" + + other_field->name() + + "\", another member " + "of oneof \"" + + oneof->name() + "\"."); return false; } } @@ -516,11 +558,15 @@ class TextFormat::Parser::ParserImpl { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { // ':' is optional here. bool consumed_semicolon = TryConsume(":"); - if (consumed_semicolon && field->options().weak() && LookingAtType(io::Tokenizer::TYPE_STRING)) { + if (consumed_semicolon && field->options().weak() && + LookingAtType(io::Tokenizer::TYPE_STRING)) { // we are getting a bytes string for a weak field. - string tmp; + std::string tmp; DO(ConsumeString(&tmp)); - reflection->MutableMessage(message, field)->ParseFromString(tmp); + MessageFactory* factory = + finder_ ? finder_->FindExtensionFactory(field) : nullptr; + reflection->MutableMessage(message, field, factory) + ->ParseFromString(tmp); goto label_skip_parsing; } } else { @@ -550,19 +596,19 @@ class TextFormat::Parser::ParserImpl { } else { DO(ConsumeFieldValue(message, reflection, field)); } -label_skip_parsing: + label_skip_parsing: // For historical reasons, fields may optionally be separated by commas or // semicolons. TryConsume(";") || TryConsume(","); if (field->options().deprecated()) { - ReportWarning("text format contains deprecated field \"" - + field_name + "\""); + ReportWarning("text format contains deprecated field \"" + field_name + + "\""); } // If a parse info tree exists, add the location for the parsed // field. - if (parse_info_tree_ != NULL) { + if (parse_info_tree_ != nullptr) { RecordLocation(parse_info_tree_, field, ParseLocation(start_line, start_column)); } @@ -572,12 +618,12 @@ class TextFormat::Parser::ParserImpl { // Skips the next field including the field's name and value. bool SkipField() { - string field_name; if (TryConsume("[")) { - // Extension name. - DO(ConsumeFullTypeName(&field_name)); + // Extension name or type URL. + DO(ConsumeTypeUrlOrFullTypeName()); DO(Consume("]")); } else { + std::string field_name; DO(ConsumeIdentifier(&field_name)); } @@ -598,26 +644,36 @@ class TextFormat::Parser::ParserImpl { return true; } - bool ConsumeFieldMessage(Message* message, - const Reflection* reflection, + bool ConsumeFieldMessage(Message* message, const Reflection* reflection, const FieldDescriptor* field) { - - // If the parse information tree is not NULL, create a nested one + if (--recursion_limit_ < 0) { + ReportError( + StrCat("Message is too deep, the parser exceeded the " + "configured recursion limit of ", + initial_recursion_limit_, ".")); + return false; + } + // If the parse information tree is not nullptr, create a nested one // for the nested message. ParseInfoTree* parent = parse_info_tree_; - if (parent != NULL) { + if (parent != nullptr) { parse_info_tree_ = CreateNested(parent, field); } - string delimiter; + std::string delimiter; DO(ConsumeMessageDelimiter(&delimiter)); + MessageFactory* factory = + finder_ ? finder_->FindExtensionFactory(field) : nullptr; if (field->is_repeated()) { - DO(ConsumeMessage(reflection->AddMessage(message, field), delimiter)); + DO(ConsumeMessage(reflection->AddMessage(message, field, factory), + delimiter)); } else { - DO(ConsumeMessage(reflection->MutableMessage(message, field), + DO(ConsumeMessage(reflection->MutableMessage(message, field, factory), delimiter)); } + ++recursion_limit_; + // Reset the parse information tree. parse_info_tree_ = parent; return true; @@ -626,30 +682,38 @@ class TextFormat::Parser::ParserImpl { // Skips the whole body of a message including the beginning delimiter and // the ending delimiter. bool SkipFieldMessage() { - string delimiter; + if (--recursion_limit_ < 0) { + ReportError( + StrCat("Message is too deep, the parser exceeded the " + "configured recursion limit of ", + initial_recursion_limit_, ".")); + return false; + } + + std::string delimiter; DO(ConsumeMessageDelimiter(&delimiter)); - while (!LookingAt(">") && !LookingAt("}")) { + while (!LookingAt(">") && !LookingAt("}")) { DO(SkipField()); } DO(Consume(delimiter)); + + ++recursion_limit_; return true; } - bool ConsumeFieldValue(Message* message, - const Reflection* reflection, + bool ConsumeFieldValue(Message* message, const Reflection* reflection, const FieldDescriptor* field) { - // Define an easy to use macro for setting fields. This macro checks // to see if the field is repeated (in which case we need to use the Add // methods or not (in which case we need to use the Set methods). -#define SET_FIELD(CPPTYPE, VALUE) \ - if (field->is_repeated()) { \ - reflection->Add##CPPTYPE(message, field, VALUE); \ - } else { \ - reflection->Set##CPPTYPE(message, field, VALUE); \ - } \ - - switch(field->cpp_type()) { +#define SET_FIELD(CPPTYPE, VALUE) \ + if (field->is_repeated()) { \ + reflection->Add##CPPTYPE(message, field, VALUE); \ + } else { \ + reflection->Set##CPPTYPE(message, field, VALUE); \ + } + + switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: { int64 value; DO(ConsumeSignedInteger(&value, kint32max)); @@ -693,7 +757,7 @@ class TextFormat::Parser::ParserImpl { } case FieldDescriptor::CPPTYPE_STRING: { - string value; + std::string value; DO(ConsumeString(&value)); SET_FIELD(String, value); break; @@ -705,15 +769,15 @@ class TextFormat::Parser::ParserImpl { DO(ConsumeUnsignedInteger(&value, 1)); SET_FIELD(Bool, value); } else { - string value; + std::string value; DO(ConsumeIdentifier(&value)); if (value == "true" || value == "True" || value == "t") { SET_FIELD(Bool, true); } else if (value == "false" || value == "False" || value == "f") { SET_FIELD(Bool, false); } else { - ReportError("Invalid value for boolean field \"" + field->name() - + "\". Value: \"" + value + "\"."); + ReportError("Invalid value for boolean field \"" + field->name() + + "\". Value: \"" + value + "\"."); return false; } } @@ -721,9 +785,10 @@ class TextFormat::Parser::ParserImpl { } case FieldDescriptor::CPPTYPE_ENUM: { - string value; + std::string value; + int64 int_value = kint64max; const EnumDescriptor* enum_type = field->enum_type(); - const EnumValueDescriptor* enum_value = NULL; + const EnumValueDescriptor* enum_value = nullptr; if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { DO(ConsumeIdentifier(&value)); @@ -732,9 +797,8 @@ class TextFormat::Parser::ParserImpl { } else if (LookingAt("-") || LookingAtType(io::Tokenizer::TYPE_INTEGER)) { - int64 int_value; DO(ConsumeSignedInteger(&int_value, kint32max)); - value = SimpleItoa(int_value); // for error reporting + value = StrCat(int_value); // for error reporting enum_value = enum_type->FindValueByNumber(int_value); } else { ReportError("Expected integer or identifier, got: " + @@ -742,14 +806,22 @@ class TextFormat::Parser::ParserImpl { return false; } - if (enum_value == NULL) { - if (!allow_unknown_enum_) { - ReportError("Unknown enumeration value of \"" + value + "\" for " - "field \"" + field->name() + "\"."); + if (enum_value == nullptr) { + if (int_value != kint64max && + reflection->SupportsUnknownEnumValues()) { + SET_FIELD(EnumValue, int_value); + return true; + } else if (!allow_unknown_enum_) { + ReportError("Unknown enumeration value of \"" + value + + "\" for " + "field \"" + + field->name() + "\"."); return false; } else { - ReportWarning("Unknown enumeration value of \"" + value + "\" for " - "field \"" + field->name() + "\"."); + ReportWarning("Unknown enumeration value of \"" + value + + "\" for " + "field \"" + + field->name() + "\"."); return true; } } @@ -770,10 +842,19 @@ class TextFormat::Parser::ParserImpl { } bool SkipFieldValue() { + if (--recursion_limit_ < 0) { + ReportError( + StrCat("Message is too deep, the parser exceeded the " + "configured recursion limit of ", + initial_recursion_limit_, ".")); + return false; + } + if (LookingAtType(io::Tokenizer::TYPE_STRING)) { while (LookingAtType(io::Tokenizer::TYPE_STRING)) { tokenizer_.Next(); } + ++recursion_limit_; return true; } if (TryConsume("[")) { @@ -788,6 +869,7 @@ class TextFormat::Parser::ParserImpl { } DO(Consume(",")); } + ++recursion_limit_; return true; } // Possible field values other than string: @@ -815,6 +897,9 @@ class TextFormat::Parser::ParserImpl { if (!LookingAtType(io::Tokenizer::TYPE_INTEGER) && !LookingAtType(io::Tokenizer::TYPE_FLOAT) && !LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + std::string text = tokenizer_.current().text; + ReportError("Cannot skip field value, unexpected token: " + text); + ++recursion_limit_; return false; } // Combination of '-' and TYPE_IDENTIFIER may result in an invalid field @@ -824,21 +909,22 @@ class TextFormat::Parser::ParserImpl { // below: // inf, inff, infinity, nan if (has_minus && LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { - string text = tokenizer_.current().text; + std::string text = tokenizer_.current().text; LowerString(&text); if (text != "inf" && - text != "infinity" && - text != "nan") { + text != "infinity" && text != "nan") { ReportError("Invalid float number: " + text); + ++recursion_limit_; return false; } } tokenizer_.Next(); + ++recursion_limit_; return true; } // Returns true if the current token's text is equal to that specified. - bool LookingAt(const string& text) { + bool LookingAt(const std::string& text) { return tokenizer_.current().text == text; } @@ -849,7 +935,7 @@ class TextFormat::Parser::ParserImpl { // Consumes an identifier and saves its value in the identifier parameter. // Returns false if the token is not of type IDENTFIER. - bool ConsumeIdentifier(string* identifier) { + bool ConsumeIdentifier(std::string* identifier) { if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { *identifier = tokenizer_.current().text; tokenizer_.Next(); @@ -858,8 +944,9 @@ class TextFormat::Parser::ParserImpl { // If allow_field_numer_ or allow_unknown_field_ is true, we should able // to parse integer identifiers. - if ((allow_field_number_ || allow_unknown_field_) - && LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + if ((allow_field_number_ || allow_unknown_field_ || + allow_unknown_extension_) && + LookingAtType(io::Tokenizer::TYPE_INTEGER)) { *identifier = tokenizer_.current().text; tokenizer_.Next(); return true; @@ -870,10 +957,10 @@ class TextFormat::Parser::ParserImpl { } // Consume a string of form ".....". - bool ConsumeFullTypeName(string* name) { + bool ConsumeFullTypeName(std::string* name) { DO(ConsumeIdentifier(name)); while (TryConsume(".")) { - string part; + std::string part; DO(ConsumeIdentifier(&part)); *name += "."; *name += part; @@ -881,9 +968,18 @@ class TextFormat::Parser::ParserImpl { return true; } + bool ConsumeTypeUrlOrFullTypeName() { + std::string discarded; + DO(ConsumeIdentifier(&discarded)); + while (TryConsume(".") || TryConsume("/")) { + DO(ConsumeIdentifier(&discarded)); + } + return true; + } + // Consumes a string and saves its value in the text parameter. // Returns false if the token is not of type STRING. - bool ConsumeString(string* text) { + bool ConsumeString(std::string* text) { if (!LookingAtType(io::Tokenizer::TYPE_STRING)) { ReportError("Expected string, got: " + tokenizer_.current().text); return false; @@ -907,8 +1003,8 @@ class TextFormat::Parser::ParserImpl { return false; } - if (!io::Tokenizer::ParseInteger(tokenizer_.current().text, - max_value, value)) { + if (!io::Tokenizer::ParseInteger(tokenizer_.current().text, max_value, + value)) { ReportError("Integer out of range (" + tokenizer_.current().text + ")"); return false; } @@ -949,23 +1045,26 @@ class TextFormat::Parser::ParserImpl { return true; } - // Consumes a uint64 and saves its value in the value parameter. + // Consumes a double and saves its value in the value parameter. // Accepts decimal numbers only, rejects hex or oct numbers. - bool ConsumeUnsignedDecimalInteger(uint64* value, uint64 max_value) { + bool ConsumeUnsignedDecimalAsDouble(double* value, uint64 max_value) { if (!LookingAtType(io::Tokenizer::TYPE_INTEGER)) { ReportError("Expected integer, got: " + tokenizer_.current().text); return false; } - const string& text = tokenizer_.current().text; + const std::string& text = tokenizer_.current().text; if (IsHexNumber(text) || IsOctNumber(text)) { ReportError("Expect a decimal number, got: " + text); return false; } - if (!io::Tokenizer::ParseInteger(text, max_value, value)) { - ReportError("Integer out of range (" + text + ")"); - return false; + uint64 uint64_value; + if (io::Tokenizer::ParseInteger(text, max_value, &uint64_value)) { + *value = static_cast(uint64_value); + } else { + // Uint64 overflow, attempt to parse as a double instead. + *value = io::Tokenizer::ParseFloat(text); } tokenizer_.Next(); @@ -988,10 +1087,7 @@ class TextFormat::Parser::ParserImpl { // Therefore, we must check both cases here. if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { // We have found an integer value for the double. - uint64 integer_value; - DO(ConsumeUnsignedDecimalInteger(&integer_value, kuint64max)); - - *value = static_cast(integer_value); + DO(ConsumeUnsignedDecimalAsDouble(value, kuint64max)); } else if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) { // We have found a float value for the double. *value = io::Tokenizer::ParseFloat(tokenizer_.current().text); @@ -999,7 +1095,7 @@ class TextFormat::Parser::ParserImpl { // Mark the current token as consumed. tokenizer_.Next(); } else if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { - string text = tokenizer_.current().text; + std::string text = tokenizer_.current().text; LowerString(&text); if (text == "inf" || text == "infinity") { @@ -1026,48 +1122,33 @@ class TextFormat::Parser::ParserImpl { // Consumes Any::type_url value, of form "type.googleapis.com/full.type.Name" // or "type.googleprod.com/full.type.Name" - bool ConsumeAnyTypeUrl(string* full_type_name, string* prefix) { + bool ConsumeAnyTypeUrl(std::string* full_type_name, std::string* prefix) { // TODO(saito) Extend Consume() to consume multiple tokens at once, so that // this code can be written as just DO(Consume(kGoogleApisTypePrefix)). - string url1, url2, url3; - DO(ConsumeIdentifier(&url1)); // type - DO(Consume(".")); - DO(ConsumeIdentifier(&url2)); // googleapis - DO(Consume(".")); - DO(ConsumeIdentifier(&url3)); // com + DO(ConsumeIdentifier(prefix)); + while (TryConsume(".")) { + std::string url; + DO(ConsumeIdentifier(&url)); + *prefix += "." + url; + } DO(Consume("/")); + *prefix += "/"; DO(ConsumeFullTypeName(full_type_name)); - *prefix = url1 + "." + url2 + "." + url3 + "/"; - if (*prefix != internal::kTypeGoogleApisComPrefix && - *prefix != internal::kTypeGoogleProdComPrefix) { - ReportError("TextFormat::Parser for Any supports only " - "type.googleapis.com and type.googleprod.com, " - "but found \"" + *prefix + "\""); - return false; - } return true; } // A helper function for reconstructing Any::value. Consumes a text of - // full_type_name, then serializes it into serialized_value. "pool" is used to - // look up and create a temporary object with full_type_name. - bool ConsumeAnyValue(const string& full_type_name, const DescriptorPool* pool, - string* serialized_value) { - const Descriptor* value_descriptor = - pool->FindMessageTypeByName(full_type_name); - if (value_descriptor == NULL) { - ReportError("Could not find type \"" + full_type_name + - "\" stored in google.protobuf.Any."); - return false; - } + // full_type_name, then serializes it into serialized_value. + bool ConsumeAnyValue(const Descriptor* value_descriptor, + std::string* serialized_value) { DynamicMessageFactory factory; const Message* value_prototype = factory.GetPrototype(value_descriptor); - if (value_prototype == NULL) { + if (value_prototype == nullptr) { return false; } - google::protobuf::scoped_ptr value(value_prototype->New()); - string sub_delimiter; + std::unique_ptr value(value_prototype->New()); + std::string sub_delimiter; DO(ConsumeMessageDelimiter(&sub_delimiter)); DO(ConsumeMessage(value.get(), sub_delimiter)); @@ -1076,7 +1157,7 @@ class TextFormat::Parser::ParserImpl { } else { if (!value->IsInitialized()) { ReportError( - "Value of type \"" + full_type_name + + "Value of type \"" + value_descriptor->full_name() + "\" stored in google.protobuf.Any has missing required fields"); return false; } @@ -1088,12 +1169,12 @@ class TextFormat::Parser::ParserImpl { // Consumes a token and confirms that it matches that specified in the // value parameter. Returns false if the token found does not match that // which was specified. - bool Consume(const string& value) { - const string& current_value = tokenizer_.current().text; + bool Consume(const std::string& value) { + const std::string& current_value = tokenizer_.current().text; if (current_value != value) { - ReportError("Expected \"" + value + "\", found \"" + current_value - + "\"."); + ReportError("Expected \"" + value + "\", found \"" + current_value + + "\"."); return false; } @@ -1104,7 +1185,7 @@ class TextFormat::Parser::ParserImpl { // Attempts to consume the supplied value. Returns false if a the // token found does not match the value specified. - bool TryConsume(const string& value) { + bool TryConsume(const std::string& value) { if (tokenizer_.current().text == value) { tokenizer_.Next(); return true; @@ -1117,16 +1198,16 @@ class TextFormat::Parser::ParserImpl { // collect any base-level parse errors and feed them to the ParserImpl. class ParserErrorCollector : public io::ErrorCollector { public: - explicit ParserErrorCollector(TextFormat::Parser::ParserImpl* parser) : - parser_(parser) { } + explicit ParserErrorCollector(TextFormat::Parser::ParserImpl* parser) + : parser_(parser) {} - virtual ~ParserErrorCollector() { } + ~ParserErrorCollector() override {} - virtual void AddError(int line, int column, const string& message) { + void AddError(int line, int column, const std::string& message) override { parser_->ReportError(line, column, message); } - virtual void AddWarning(int line, int column, const string& message) { + void AddWarning(int line, int column, const std::string& message) override { parser_->ReportWarning(line, column, message); } @@ -1136,7 +1217,7 @@ class TextFormat::Parser::ParserImpl { }; io::ErrorCollector* error_collector_; - TextFormat::Finder* finder_; + const TextFormat::Finder* finder_; ParseInfoTree* parse_info_tree_; ParserErrorCollector tokenizer_error_collector_; io::Tokenizer tokenizer_; @@ -1144,30 +1225,30 @@ class TextFormat::Parser::ParserImpl { SingularOverwritePolicy singular_overwrite_policy_; const bool allow_case_insensitive_field_; const bool allow_unknown_field_; + const bool allow_unknown_extension_; const bool allow_unknown_enum_; const bool allow_field_number_; const bool allow_partial_; + const int initial_recursion_limit_; + int recursion_limit_; bool had_errors_; }; -#undef DO - // =========================================================================== // Internal class for writing text to the io::ZeroCopyOutputStream. Adapted -// from the Printer found in //google/protobuf/io/printer.h +// from the Printer found in //net/proto2/io/public/printer.h class TextFormat::Printer::TextGenerator : public TextFormat::BaseTextGenerator { public: explicit TextGenerator(io::ZeroCopyOutputStream* output, int initial_indent_level) - : output_(output), - buffer_(NULL), - buffer_size_(0), - at_start_of_line_(true), - failed_(false), - indent_level_(initial_indent_level), - initial_indent_level_(initial_indent_level) { - } + : output_(output), + buffer_(nullptr), + buffer_size_(0), + at_start_of_line_(true), + failed_(false), + indent_level_(initial_indent_level), + initial_indent_level_(initial_indent_level) {} ~TextGenerator() { // Only BackUp() if we're sure we've successfully called Next() at least @@ -1180,15 +1261,12 @@ class TextFormat::Printer::TextGenerator // Indent text by two spaces. After calling Indent(), two spaces will be // inserted at the beginning of each line of text. Indent() may be called // multiple times to produce deeper indents. - void Indent() { - ++indent_level_; - } + void Indent() override { ++indent_level_; } // Reduces the current indent level by two spaces, or crashes if the indent // level is zero. - void Outdent() { - if (indent_level_ == 0 || - indent_level_ < initial_indent_level_) { + void Outdent() override { + if (indent_level_ == 0 || indent_level_ < initial_indent_level_) { GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent()."; return; } @@ -1196,8 +1274,12 @@ class TextFormat::Printer::TextGenerator --indent_level_; } + size_t GetCurrentIndentationSize() const override { + return 2 * indent_level_; + } + // Print text to the output stream. - void Print(const char* text, size_t size) { + void Print(const char* text, size_t size) override { if (indent_level_ > 0) { size_t pos = 0; // The number of bytes we've written so far. for (size_t i = 0; i < size; i++) { @@ -1216,7 +1298,7 @@ class TextFormat::Printer::TextGenerator Write(text + pos, size - pos); } else { Write(text, size); - if (text[size - 1] == '\n') { + if (size > 0 && text[size - 1] == '\n') { at_start_of_line_ = true; } } @@ -1241,13 +1323,15 @@ class TextFormat::Printer::TextGenerator if (failed_) return; } - while (size > buffer_size_) { + while (static_cast(size) > buffer_size_) { // Data exceeds space in the buffer. Copy what we can and request a // new buffer. - memcpy(buffer_, data, buffer_size_); - data += buffer_size_; - size -= buffer_size_; - void* void_buffer; + if (buffer_size_ > 0) { + memcpy(buffer_, data, buffer_size_); + data += buffer_size_; + size -= buffer_size_; + } + void* void_buffer = nullptr; failed_ = !output_->Next(&void_buffer, &buffer_size_); if (failed_) return; buffer_ = reinterpret_cast(void_buffer); @@ -1260,14 +1344,18 @@ class TextFormat::Printer::TextGenerator } void WriteIndent() { - if (indent_level_ == 0) { return; } + if (indent_level_ == 0) { + return; + } GOOGLE_DCHECK(!failed_); - int size = 2 * indent_level_; + int size = GetCurrentIndentationSize(); while (size > buffer_size_) { // Data exceeds space in the buffer. Write what we can and request a new // buffer. - memset(buffer_, ' ', buffer_size_); + if (buffer_size_ > 0) { + memset(buffer_, ' ', buffer_size_); + } size -= buffer_size_; void* void_buffer; failed_ = !output_->Next(&void_buffer, &buffer_size_); @@ -1292,45 +1380,84 @@ class TextFormat::Printer::TextGenerator }; // =========================================================================== +// Implementation of the default Finder for extensions. +TextFormat::Finder::~Finder() {} -TextFormat::Finder::~Finder() { +const FieldDescriptor* TextFormat::Finder::FindExtension( + Message* message, const std::string& name) const { + return DefaultFinderFindExtension(message, name); } -TextFormat::Parser::Parser() - : error_collector_(NULL), - finder_(NULL), - parse_info_tree_(NULL), - allow_partial_(false), - allow_case_insensitive_field_(false), - allow_unknown_field_(false), - allow_unknown_enum_(false), - allow_field_number_(false), - allow_relaxed_whitespace_(false), - allow_singular_overwrites_(false) { +const FieldDescriptor* TextFormat::Finder::FindExtensionByNumber( + const Descriptor* descriptor, int number) const { + return DefaultFinderFindExtensionByNumber(descriptor, number); +} + +const Descriptor* TextFormat::Finder::FindAnyType( + const Message& message, const std::string& prefix, + const std::string& name) const { + return DefaultFinderFindAnyType(message, prefix, name); +} + +MessageFactory* TextFormat::Finder::FindExtensionFactory( + const FieldDescriptor* field) const { + return nullptr; } +// =========================================================================== + +TextFormat::Parser::Parser() + : error_collector_(nullptr), + finder_(nullptr), + parse_info_tree_(nullptr), + allow_partial_(false), + allow_case_insensitive_field_(false), + allow_unknown_field_(false), + allow_unknown_extension_(false), + allow_unknown_enum_(false), + allow_field_number_(false), + allow_relaxed_whitespace_(false), + allow_singular_overwrites_(false), + recursion_limit_(std::numeric_limits::max()) {} + TextFormat::Parser::~Parser() {} +namespace { + +bool CheckParseInputSize(StringPiece input, + io::ErrorCollector* error_collector) { + if (input.size() > INT_MAX) { + error_collector->AddError( + -1, 0, + StrCat("Input size too large: ", static_cast(input.size()), + " bytes", " > ", INT_MAX, " bytes.")); + return false; + } + return true; +} + +} // namespace + bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input, Message* output) { output->Clear(); ParserImpl::SingularOverwritePolicy overwrites_policy = - allow_singular_overwrites_ - ? ParserImpl::ALLOW_SINGULAR_OVERWRITES - : ParserImpl::FORBID_SINGULAR_OVERWRITES; + allow_singular_overwrites_ ? ParserImpl::ALLOW_SINGULAR_OVERWRITES + : ParserImpl::FORBID_SINGULAR_OVERWRITES; - ParserImpl parser(output->GetDescriptor(), input, error_collector_, - finder_, parse_info_tree_, - overwrites_policy, + ParserImpl parser(output->GetDescriptor(), input, error_collector_, finder_, + parse_info_tree_, overwrites_policy, allow_case_insensitive_field_, allow_unknown_field_, - allow_unknown_enum_, allow_field_number_, - allow_relaxed_whitespace_, allow_partial_); + allow_unknown_extension_, allow_unknown_enum_, + allow_field_number_, allow_relaxed_whitespace_, + allow_partial_, recursion_limit_); return MergeUsingImpl(input, output, &parser); } -bool TextFormat::Parser::ParseFromString(const string& input, +bool TextFormat::Parser::ParseFromString(ConstStringParam input, Message* output) { + DO(CheckParseInputSize(input, error_collector_)); io::ArrayInputStream input_stream(input.data(), input.size()); return Parse(&input_stream, output); } @@ -1338,17 +1465,18 @@ bool TextFormat::Parser::ParseFromString(const string& input, bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, Message* output) { - ParserImpl parser(output->GetDescriptor(), input, error_collector_, - finder_, parse_info_tree_, - ParserImpl::ALLOW_SINGULAR_OVERWRITES, + ParserImpl parser(output->GetDescriptor(), input, error_collector_, finder_, + parse_info_tree_, ParserImpl::ALLOW_SINGULAR_OVERWRITES, allow_case_insensitive_field_, allow_unknown_field_, - allow_unknown_enum_, allow_field_number_, - allow_relaxed_whitespace_, allow_partial_); + allow_unknown_extension_, allow_unknown_enum_, + allow_field_number_, allow_relaxed_whitespace_, + allow_partial_, recursion_limit_); return MergeUsingImpl(input, output, &parser); } -bool TextFormat::Parser::MergeFromString(const string& input, +bool TextFormat::Parser::MergeFromString(ConstStringParam input, Message* output) { + DO(CheckParseInputSize(input, error_collector_)); io::ArrayInputStream input_stream(input.data(), input.size()); return Merge(&input_stream, output); } @@ -1359,26 +1487,26 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* /* input */, ParserImpl* parser_impl) { if (!parser_impl->Parse(output)) return false; if (!allow_partial_ && !output->IsInitialized()) { - std::vector missing_fields; + std::vector missing_fields; output->FindInitializationErrors(&missing_fields); - parser_impl->ReportError(-1, 0, "Message missing required fields: " + - Join(missing_fields, ", ")); + parser_impl->ReportError(-1, 0, + "Message missing required fields: " + + Join(missing_fields, ", ")); return false; } return true; } -bool TextFormat::Parser::ParseFieldValueFromString( - const string& input, - const FieldDescriptor* field, - Message* output) { +bool TextFormat::Parser::ParseFieldValueFromString(const std::string& input, + const FieldDescriptor* field, + Message* output) { io::ArrayInputStream input_stream(input.data(), input.size()); - ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_, - finder_, parse_info_tree_, - ParserImpl::ALLOW_SINGULAR_OVERWRITES, - allow_case_insensitive_field_, allow_unknown_field_, - allow_unknown_enum_, allow_field_number_, - allow_relaxed_whitespace_, allow_partial_); + ParserImpl parser( + output->GetDescriptor(), &input_stream, error_collector_, finder_, + parse_info_tree_, ParserImpl::ALLOW_SINGULAR_OVERWRITES, + allow_case_insensitive_field_, allow_unknown_field_, + allow_unknown_extension_, allow_unknown_enum_, allow_field_number_, + allow_relaxed_whitespace_, allow_partial_, recursion_limit_); return parser.ParseField(field, output); } @@ -1392,17 +1520,19 @@ bool TextFormat::Parser::ParseFieldValueFromString( return Parser().Merge(input, output); } -/* static */ bool TextFormat::ParseFromString(const string& input, +/* static */ bool TextFormat::ParseFromString(ConstStringParam input, Message* output) { return Parser().ParseFromString(input, output); } -/* static */ bool TextFormat::MergeFromString(const string& input, +/* static */ bool TextFormat::MergeFromString(ConstStringParam input, Message* output) { return Parser().MergeFromString(input, output); } +#undef DO + // =========================================================================== TextFormat::BaseTextGenerator::~BaseTextGenerator() {} @@ -1412,18 +1542,20 @@ namespace { // A BaseTextGenerator that writes to a string. class StringBaseTextGenerator : public TextFormat::BaseTextGenerator { public: - void Print(const char* text, size_t size) { output_.append(text, size); } + void Print(const char* text, size_t size) override { + output_.append(text, size); + } // Some compilers do not support ref-qualifiers even in C++11 mode. // Disable the optimization for now and revisit it later. -#if 0 // LANG_CXX11 - string Consume() && { return std::move(output_); } -#else // !LANG_CXX11 - const string& Get() { return output_; } +#if 0 // LANG_CXX11 + std::string Consume() && { return std::move(output_); } +#else // !LANG_CXX11 + const std::string& Get() { return output_; } #endif // LANG_CXX11 private: - string output_; + std::string output_; }; } // namespace @@ -1434,7 +1566,7 @@ class StringBaseTextGenerator : public TextFormat::BaseTextGenerator { TextFormat::FieldValuePrinter::FieldValuePrinter() {} TextFormat::FieldValuePrinter::~FieldValuePrinter() {} -#if 0 // LANG_CXX11 +#if 0 // LANG_CXX11 #define FORWARD_IMPL(fn, ...) \ StringBaseTextGenerator generator; \ delegate_.fn(__VA_ARGS__, &generator); \ @@ -1446,55 +1578,52 @@ TextFormat::FieldValuePrinter::~FieldValuePrinter() {} return generator.Get() #endif // LANG_CXX11 -string TextFormat::FieldValuePrinter::PrintBool(bool val) const { +std::string TextFormat::FieldValuePrinter::PrintBool(bool val) const { FORWARD_IMPL(PrintBool, val); } -string TextFormat::FieldValuePrinter::PrintInt32(int32 val) const { +std::string TextFormat::FieldValuePrinter::PrintInt32(int32 val) const { FORWARD_IMPL(PrintInt32, val); } -string TextFormat::FieldValuePrinter::PrintUInt32(uint32 val) const { +std::string TextFormat::FieldValuePrinter::PrintUInt32(uint32 val) const { FORWARD_IMPL(PrintUInt32, val); } -string TextFormat::FieldValuePrinter::PrintInt64(int64 val) const { +std::string TextFormat::FieldValuePrinter::PrintInt64(int64 val) const { FORWARD_IMPL(PrintInt64, val); } -string TextFormat::FieldValuePrinter::PrintUInt64(uint64 val) const { +std::string TextFormat::FieldValuePrinter::PrintUInt64(uint64 val) const { FORWARD_IMPL(PrintUInt64, val); } -string TextFormat::FieldValuePrinter::PrintFloat(float val) const { +std::string TextFormat::FieldValuePrinter::PrintFloat(float val) const { FORWARD_IMPL(PrintFloat, val); } -string TextFormat::FieldValuePrinter::PrintDouble(double val) const { +std::string TextFormat::FieldValuePrinter::PrintDouble(double val) const { FORWARD_IMPL(PrintDouble, val); } -string TextFormat::FieldValuePrinter::PrintString(const string& val) const { +std::string TextFormat::FieldValuePrinter::PrintString( + const std::string& val) const { FORWARD_IMPL(PrintString, val); } -string TextFormat::FieldValuePrinter::PrintBytes(const string& val) const { +std::string TextFormat::FieldValuePrinter::PrintBytes( + const std::string& val) const { return PrintString(val); } -string TextFormat::FieldValuePrinter::PrintEnum(int32 val, - const string& name) const { +std::string TextFormat::FieldValuePrinter::PrintEnum( + int32 val, const std::string& name) const { FORWARD_IMPL(PrintEnum, val, name); } -string TextFormat::FieldValuePrinter::PrintFieldName( - const Message& message, - const Reflection* reflection, +std::string TextFormat::FieldValuePrinter::PrintFieldName( + const Message& message, const Reflection* reflection, const FieldDescriptor* field) const { FORWARD_IMPL(PrintFieldName, message, reflection, field); } -string TextFormat::FieldValuePrinter::PrintMessageStart( - const Message& message, - int field_index, - int field_count, +std::string TextFormat::FieldValuePrinter::PrintMessageStart( + const Message& message, int field_index, int field_count, bool single_line_mode) const { FORWARD_IMPL(PrintMessageStart, message, field_index, field_count, single_line_mode); } -string TextFormat::FieldValuePrinter::PrintMessageEnd( - const Message& message, - int field_index, - int field_count, +std::string TextFormat::FieldValuePrinter::PrintMessageEnd( + const Message& message, int field_index, int field_count, bool single_line_mode) const { FORWARD_IMPL(PrintMessageEnd, message, field_index, field_count, single_line_mode); @@ -1513,57 +1642,55 @@ void TextFormat::FastFieldValuePrinter::PrintBool( } void TextFormat::FastFieldValuePrinter::PrintInt32( int32 val, BaseTextGenerator* generator) const { - generator->PrintString(SimpleItoa(val)); + generator->PrintString(StrCat(val)); } void TextFormat::FastFieldValuePrinter::PrintUInt32( uint32 val, BaseTextGenerator* generator) const { - generator->PrintString(SimpleItoa(val)); + generator->PrintString(StrCat(val)); } void TextFormat::FastFieldValuePrinter::PrintInt64( int64 val, BaseTextGenerator* generator) const { - generator->PrintString(SimpleItoa(val)); + generator->PrintString(StrCat(val)); } void TextFormat::FastFieldValuePrinter::PrintUInt64( uint64 val, BaseTextGenerator* generator) const { - generator->PrintString(SimpleItoa(val)); + generator->PrintString(StrCat(val)); } void TextFormat::FastFieldValuePrinter::PrintFloat( float val, BaseTextGenerator* generator) const { - generator->PrintString(SimpleFtoa(val)); + generator->PrintString(!std::isnan(val) ? SimpleFtoa(val) : "nan"); } void TextFormat::FastFieldValuePrinter::PrintDouble( double val, BaseTextGenerator* generator) const { - generator->PrintString(SimpleDtoa(val)); + generator->PrintString(!std::isnan(val) ? SimpleDtoa(val) : "nan"); } void TextFormat::FastFieldValuePrinter::PrintEnum( - int32 val, const string& name, BaseTextGenerator* generator) const { + int32 val, const std::string& name, BaseTextGenerator* generator) const { generator->PrintString(name); } void TextFormat::FastFieldValuePrinter::PrintString( - const string& val, BaseTextGenerator* generator) const { + const std::string& val, BaseTextGenerator* generator) const { generator->PrintLiteral("\""); generator->PrintString(CEscape(val)); generator->PrintLiteral("\""); } void TextFormat::FastFieldValuePrinter::PrintBytes( - const string& val, BaseTextGenerator* generator) const { + const std::string& val, BaseTextGenerator* generator) const { PrintString(val, generator); } +void TextFormat::FastFieldValuePrinter::PrintFieldName( + const Message& message, int field_index, int field_count, + const Reflection* reflection, const FieldDescriptor* field, + BaseTextGenerator* generator) const { + PrintFieldName(message, reflection, field, generator); +} void TextFormat::FastFieldValuePrinter::PrintFieldName( const Message& message, const Reflection* reflection, const FieldDescriptor* field, BaseTextGenerator* generator) const { if (field->is_extension()) { generator->PrintLiteral("["); - // We special-case MessageSet elements for compatibility with proto1. - if (field->containing_type()->options().message_set_wire_format() && - field->type() == FieldDescriptor::TYPE_MESSAGE && - field->is_optional() && - field->extension_scope() == field->message_type()) { - generator->PrintString(field->message_type()->full_name()); - } else { - generator->PrintString(field->full_name()); - } + generator->PrintString(field->PrintableNameForExtension()); generator->PrintLiteral("]"); } else if (field->type() == FieldDescriptor::TYPE_GROUP) { // Groups must be serialized with their original capitalization. @@ -1581,6 +1708,11 @@ void TextFormat::FastFieldValuePrinter::PrintMessageStart( generator->PrintLiteral(" {\n"); } } +bool TextFormat::FastFieldValuePrinter::PrintMessageContent( + const Message& message, int field_index, int field_count, + bool single_line_mode, BaseTextGenerator* generator) const { + return false; // Use the default printing function. +} void TextFormat::FastFieldValuePrinter::PrintMessageEnd( const Message& message, int field_index, int field_count, bool single_line_mode, BaseTextGenerator* generator) const { @@ -1604,96 +1736,112 @@ class FieldValuePrinterWrapper : public TextFormat::FastFieldValuePrinter { delegate_.reset(delegate); } - void PrintBool(bool val, TextFormat::BaseTextGenerator* generator) const { + void PrintBool(bool val, + TextFormat::BaseTextGenerator* generator) const override { generator->PrintString(delegate_->PrintBool(val)); } - void PrintInt32(int32 val, TextFormat::BaseTextGenerator* generator) const { + void PrintInt32(int32 val, + TextFormat::BaseTextGenerator* generator) const override { generator->PrintString(delegate_->PrintInt32(val)); } - void PrintUInt32(uint32 val, TextFormat::BaseTextGenerator* generator) const { + void PrintUInt32(uint32 val, + TextFormat::BaseTextGenerator* generator) const override { generator->PrintString(delegate_->PrintUInt32(val)); } - void PrintInt64(int64 val, TextFormat::BaseTextGenerator* generator) const { + void PrintInt64(int64 val, + TextFormat::BaseTextGenerator* generator) const override { generator->PrintString(delegate_->PrintInt64(val)); } - void PrintUInt64(uint64 val, TextFormat::BaseTextGenerator* generator) const { + void PrintUInt64(uint64 val, + TextFormat::BaseTextGenerator* generator) const override { generator->PrintString(delegate_->PrintUInt64(val)); } - void PrintFloat(float val, TextFormat::BaseTextGenerator* generator) const { + void PrintFloat(float val, + TextFormat::BaseTextGenerator* generator) const override { generator->PrintString(delegate_->PrintFloat(val)); } - void PrintDouble(double val, TextFormat::BaseTextGenerator* generator) const { + void PrintDouble(double val, + TextFormat::BaseTextGenerator* generator) const override { generator->PrintString(delegate_->PrintDouble(val)); } - void PrintString(const string& val, - TextFormat::BaseTextGenerator* generator) const { + void PrintString(const std::string& val, + TextFormat::BaseTextGenerator* generator) const override { generator->PrintString(delegate_->PrintString(val)); } - void PrintBytes(const string& val, - TextFormat::BaseTextGenerator* generator) const { + void PrintBytes(const std::string& val, + TextFormat::BaseTextGenerator* generator) const override { generator->PrintString(delegate_->PrintBytes(val)); } - void PrintEnum(int32 val, const string& name, - TextFormat::BaseTextGenerator* generator) const { + void PrintEnum(int32 val, const std::string& name, + TextFormat::BaseTextGenerator* generator) const override { generator->PrintString(delegate_->PrintEnum(val, name)); } + void PrintFieldName(const Message& message, int field_index, int field_count, + const Reflection* reflection, + const FieldDescriptor* field, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString( + delegate_->PrintFieldName(message, reflection, field)); + } void PrintFieldName(const Message& message, const Reflection* reflection, const FieldDescriptor* field, - TextFormat::BaseTextGenerator* generator) const { + TextFormat::BaseTextGenerator* generator) const override { generator->PrintString( delegate_->PrintFieldName(message, reflection, field)); } - void PrintMessageStart(const Message& message, int field_index, - int field_count, bool single_line_mode, - TextFormat::BaseTextGenerator* generator) const { + void PrintMessageStart( + const Message& message, int field_index, int field_count, + bool single_line_mode, + TextFormat::BaseTextGenerator* generator) const override { generator->PrintString(delegate_->PrintMessageStart( message, field_index, field_count, single_line_mode)); } - void PrintMessageEnd(const Message& message, int field_index, int field_count, - bool single_line_mode, - TextFormat::BaseTextGenerator* generator) const { + void PrintMessageEnd( + const Message& message, int field_index, int field_count, + bool single_line_mode, + TextFormat::BaseTextGenerator* generator) const override { generator->PrintString(delegate_->PrintMessageEnd( message, field_index, field_count, single_line_mode)); } private: - google::protobuf::scoped_ptr delegate_; + std::unique_ptr delegate_; }; // Our own specialization: for UTF8 escaped strings. class FastFieldValuePrinterUtf8Escaping : public TextFormat::FastFieldValuePrinter { public: - void PrintString(const string& val, - TextFormat::BaseTextGenerator* generator) const { + void PrintString(const std::string& val, + TextFormat::BaseTextGenerator* generator) const override { generator->PrintLiteral("\""); generator->PrintString(strings::Utf8SafeCEscape(val)); generator->PrintLiteral("\""); } - void PrintBytes(const string& val, - TextFormat::BaseTextGenerator* generator) const { + void PrintBytes(const std::string& val, + TextFormat::BaseTextGenerator* generator) const override { return FastFieldValuePrinter::PrintString(val, generator); } }; } // namespace +const char* const TextFormat::Printer::kDoNotParse = + "DO NOT PARSE: fields may be stripped and missing.\n"; + TextFormat::Printer::Printer() - : initial_indent_level_(0), - single_line_mode_(false), - use_field_number_(false), - use_short_repeated_primitives_(false), - hide_unknown_fields_(false), - print_message_fields_in_index_order_(false), - expand_any_(false), - truncate_string_field_longer_than_(0LL) { + : initial_indent_level_(0), + single_line_mode_(false), + use_field_number_(false), + use_short_repeated_primitives_(false), + hide_unknown_fields_(false), + print_message_fields_in_index_order_(false), + expand_any_(false), + truncate_string_field_longer_than_(0LL), + finder_(nullptr) { SetUseUtf8StringEscaping(false); } -TextFormat::Printer::~Printer() { - STLDeleteValues(&custom_printers_); -} - void TextFormat::Printer::SetUseUtf8StringEscaping(bool as_utf8) { SetDefaultFieldValuePrinter(as_utf8 ? new FastFieldValuePrinterUtf8Escaping() : new FastFieldValuePrinter()); @@ -1710,31 +1858,54 @@ void TextFormat::Printer::SetDefaultFieldValuePrinter( } bool TextFormat::Printer::RegisterFieldValuePrinter( - const FieldDescriptor* field, - const FieldValuePrinter* printer) { - if (field == NULL || printer == NULL) { + const FieldDescriptor* field, const FieldValuePrinter* printer) { + if (field == nullptr || printer == nullptr) { return false; } - FieldValuePrinterWrapper* const wrapper = - new FieldValuePrinterWrapper(NULL); - if (custom_printers_.insert(std::make_pair(field, wrapper)).second) { + std::unique_ptr wrapper( + new FieldValuePrinterWrapper(nullptr)); + auto pair = custom_printers_.insert(std::make_pair(field, nullptr)); + if (pair.second) { wrapper->SetDelegate(printer); + pair.first->second = std::move(wrapper); return true; } else { - delete wrapper; return false; } } bool TextFormat::Printer::RegisterFieldValuePrinter( const FieldDescriptor* field, const FastFieldValuePrinter* printer) { - return field != NULL && printer != NULL && - custom_printers_.insert(std::make_pair(field, printer)).second; + if (field == nullptr || printer == nullptr) { + return false; + } + auto pair = custom_printers_.insert(std::make_pair(field, nullptr)); + if (pair.second) { + pair.first->second.reset(printer); + return true; + } else { + return false; + } +} + +bool TextFormat::Printer::RegisterMessagePrinter( + const Descriptor* descriptor, const MessagePrinter* printer) { + if (descriptor == nullptr || printer == nullptr) { + return false; + } + auto pair = + custom_message_printers_.insert(std::make_pair(descriptor, nullptr)); + if (pair.second) { + pair.first->second.reset(printer); + return true; + } else { + return false; + } } bool TextFormat::Printer::PrintToString(const Message& message, - string* output) const { - GOOGLE_DCHECK(output) << "output specified is NULL"; + std::string* output) const { + GOOGLE_DCHECK(output) << "output specified is nullptr"; output->clear(); io::StringOutputStream output_stream(output); @@ -1743,9 +1914,8 @@ bool TextFormat::Printer::PrintToString(const Message& message, } bool TextFormat::Printer::PrintUnknownFieldsToString( - const UnknownFieldSet& unknown_fields, - string* output) const { - GOOGLE_DCHECK(output) << "output specified is NULL"; + const UnknownFieldSet& unknown_fields, std::string* output) const { + GOOGLE_DCHECK(output) << "output specified is nullptr"; output->clear(); io::StringOutputStream output_stream(output); @@ -1762,12 +1932,16 @@ bool TextFormat::Printer::Print(const Message& message, return !generator.failed(); } +// Maximum recursion depth for heuristically printing out length-delimited +// unknown fields as messages. +static constexpr int kUnknownFieldRecursionLimit = 10; + bool TextFormat::Printer::PrintUnknownFields( const UnknownFieldSet& unknown_fields, io::ZeroCopyOutputStream* output) const { TextGenerator generator(output, initial_indent_level_); - PrintUnknownFields(unknown_fields, &generator); + PrintUnknownFields(unknown_fields, &generator, kUnknownFieldRecursionLimit); // Output false if the generator failed internally. return !generator.failed(); @@ -1775,10 +1949,19 @@ bool TextFormat::Printer::PrintUnknownFields( namespace { // Comparison functor for sorting FieldDescriptors by field index. +// Normal fields have higher precedence than extensions. struct FieldIndexSorter { bool operator()(const FieldDescriptor* left, const FieldDescriptor* right) const { - return left->index() < right->index(); + if (left->is_extension() && right->is_extension()) { + return left->number() < right->number(); + } else if (left->is_extension()) { + return false; + } else if (right->is_extension()) { + return true; + } else { + return left->index() < right->index(); + } } }; @@ -1796,24 +1979,26 @@ bool TextFormat::Printer::PrintAny(const Message& message, const Reflection* reflection = message.GetReflection(); // Extract the full type name from the type_url field. - const string& type_url = reflection->GetString(message, type_url_field); - string full_type_name; - if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) { + const std::string& type_url = reflection->GetString(message, type_url_field); + std::string url_prefix; + std::string full_type_name; + if (!internal::ParseAnyTypeUrl(type_url, &url_prefix, &full_type_name)) { return false; } // Print the "value" in text. - const google::protobuf::Descriptor* value_descriptor = - message.GetDescriptor()->file()->pool()->FindMessageTypeByName( - full_type_name); - if (value_descriptor == NULL) { - GOOGLE_LOG(WARNING) << "Proto type " << type_url << " not found"; + const Descriptor* value_descriptor = + finder_ ? finder_->FindAnyType(message, url_prefix, full_type_name) + : DefaultFinderFindAnyType(message, url_prefix, full_type_name); + if (value_descriptor == nullptr) { + GOOGLE_LOG(WARNING) << "Can't print proto content: proto type " << type_url + << " not found"; return false; } DynamicMessageFactory factory; - google::protobuf::scoped_ptr value_message( + std::unique_ptr value_message( factory.GetPrototype(value_descriptor)->New()); - string serialized_value = reflection->GetString(message, value_field); + std::string serialized_value = reflection->GetString(message, value_field); if (!value_message->ParseFromString(serialized_value)) { GOOGLE_LOG(WARNING) << type_url << ": failed to parse contents"; return false; @@ -1821,8 +2006,7 @@ bool TextFormat::Printer::PrintAny(const Message& message, generator->PrintLiteral("["); generator->PrintString(type_url); generator->PrintLiteral("]"); - const FastFieldValuePrinter* printer = FindWithDefault( - custom_printers_, value_field, default_field_value_printer_.get()); + const FastFieldValuePrinter* printer = GetFieldPrinter(value_field); printer->PrintMessageStart(message, -1, 0, single_line_mode_, generator); generator->Indent(); Print(*value_message, generator); @@ -1833,32 +2017,57 @@ bool TextFormat::Printer::PrintAny(const Message& message, void TextFormat::Printer::Print(const Message& message, TextGenerator* generator) const { - const Descriptor* descriptor = message.GetDescriptor(); const Reflection* reflection = message.GetReflection(); + if (!reflection) { + // This message does not provide any way to describe its structure. + // Parse it again in an UnknownFieldSet, and display this instead. + UnknownFieldSet unknown_fields; + { + std::string serialized = message.SerializeAsString(); + io::ArrayInputStream input(serialized.data(), serialized.size()); + unknown_fields.ParseFromZeroCopyStream(&input); + } + PrintUnknownFields(unknown_fields, generator, kUnknownFieldRecursionLimit); + return; + } + const Descriptor* descriptor = message.GetDescriptor(); + auto itr = custom_message_printers_.find(descriptor); + if (itr != custom_message_printers_.end()) { + itr->second->Print(message, single_line_mode_, generator); + return; + } if (descriptor->full_name() == internal::kAnyFullTypeName && expand_any_ && PrintAny(message, generator)) { return; } std::vector fields; - reflection->ListFields(message, &fields); + if (descriptor->options().map_entry()) { + fields.push_back(descriptor->field(0)); + fields.push_back(descriptor->field(1)); + } else { + reflection->ListFieldsOmitStripped(message, &fields); + if (reflection->IsMessageStripped(message.GetDescriptor())) { + generator->Print(kDoNotParse, std::strlen(kDoNotParse)); + } + } + if (print_message_fields_in_index_order_) { std::sort(fields.begin(), fields.end(), FieldIndexSorter()); } - for (int i = 0; i < fields.size(); i++) { - PrintField(message, reflection, fields[i], generator); + for (const FieldDescriptor* field : fields) { + PrintField(message, reflection, field, generator); } if (!hide_unknown_fields_) { - PrintUnknownFields(reflection->GetUnknownFields(message), generator); + PrintUnknownFields(reflection->GetUnknownFields(message), generator, + kUnknownFieldRecursionLimit); } } -void TextFormat::Printer::PrintFieldValueToString( - const Message& message, - const FieldDescriptor* field, - int index, - string* output) const { - - GOOGLE_DCHECK(output) << "output specified is NULL"; +void TextFormat::Printer::PrintFieldValueToString(const Message& message, + const FieldDescriptor* field, + int index, + std::string* output) const { + GOOGLE_DCHECK(output) << "output specified is nullptr"; output->clear(); io::StringOutputStream output_stream(output); @@ -1867,12 +2076,186 @@ void TextFormat::Printer::PrintFieldValueToString( PrintFieldValue(message, message.GetReflection(), field, index, &generator); } +class MapEntryMessageComparator { + public: + explicit MapEntryMessageComparator(const Descriptor* descriptor) + : field_(descriptor->field(0)) {} + + bool operator()(const Message* a, const Message* b) { + const Reflection* reflection = a->GetReflection(); + switch (field_->cpp_type()) { + case FieldDescriptor::CPPTYPE_BOOL: { + bool first = reflection->GetBool(*a, field_); + bool second = reflection->GetBool(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_INT32: { + int32 first = reflection->GetInt32(*a, field_); + int32 second = reflection->GetInt32(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_INT64: { + int64 first = reflection->GetInt64(*a, field_); + int64 second = reflection->GetInt64(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_UINT32: { + uint32 first = reflection->GetUInt32(*a, field_); + uint32 second = reflection->GetUInt32(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_UINT64: { + uint64 first = reflection->GetUInt64(*a, field_); + uint64 second = reflection->GetUInt64(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_STRING: { + std::string first = reflection->GetString(*a, field_); + std::string second = reflection->GetString(*b, field_); + return first < second; + } + default: + GOOGLE_LOG(DFATAL) << "Invalid key for map field."; + return true; + } + } + + private: + const FieldDescriptor* field_; +}; + +namespace internal { +class MapFieldPrinterHelper { + public: + // DynamicMapSorter::Sort cannot be used because it enfores syncing with + // repeated field. + static bool SortMap(const Message& message, const Reflection* reflection, + const FieldDescriptor* field, + std::vector* sorted_map_field); + static void CopyKey(const MapKey& key, Message* message, + const FieldDescriptor* field_desc); + static void CopyValue(const MapValueRef& value, Message* message, + const FieldDescriptor* field_desc); +}; + +// Returns true if elements contained in sorted_map_field need to be released. +bool MapFieldPrinterHelper::SortMap( + const Message& message, const Reflection* reflection, + const FieldDescriptor* field, + std::vector* sorted_map_field) { + bool need_release = false; + const MapFieldBase& base = *reflection->GetMapData(message, field); + + if (base.IsRepeatedFieldValid()) { + const RepeatedPtrField& map_field = + reflection->GetRepeatedPtrFieldInternal(message, field); + for (int i = 0; i < map_field.size(); ++i) { + sorted_map_field->push_back( + const_cast*>(&map_field)->Mutable(i)); + } + } else { + // TODO(teboring): For performance, instead of creating map entry message + // for each element, just store map keys and sort them. + const Descriptor* map_entry_desc = field->message_type(); + const Message* prototype = + reflection->GetMessageFactory()->GetPrototype(map_entry_desc); + for (MapIterator iter = + reflection->MapBegin(const_cast(&message), field); + iter != reflection->MapEnd(const_cast(&message), field); + ++iter) { + Message* map_entry_message = prototype->New(); + CopyKey(iter.GetKey(), map_entry_message, map_entry_desc->field(0)); + CopyValue(iter.GetValueRef(), map_entry_message, + map_entry_desc->field(1)); + sorted_map_field->push_back(map_entry_message); + } + need_release = true; + } + + MapEntryMessageComparator comparator(field->message_type()); + std::stable_sort(sorted_map_field->begin(), sorted_map_field->end(), + comparator); + return need_release; +} + +void MapFieldPrinterHelper::CopyKey(const MapKey& key, Message* message, + const FieldDescriptor* field_desc) { + const Reflection* reflection = message->GetReflection(); + switch (field_desc->cpp_type()) { + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(ERROR) << "Not supported."; + break; + case FieldDescriptor::CPPTYPE_STRING: + reflection->SetString(message, field_desc, key.GetStringValue()); + return; + case FieldDescriptor::CPPTYPE_INT64: + reflection->SetInt64(message, field_desc, key.GetInt64Value()); + return; + case FieldDescriptor::CPPTYPE_INT32: + reflection->SetInt32(message, field_desc, key.GetInt32Value()); + return; + case FieldDescriptor::CPPTYPE_UINT64: + reflection->SetUInt64(message, field_desc, key.GetUInt64Value()); + return; + case FieldDescriptor::CPPTYPE_UINT32: + reflection->SetUInt32(message, field_desc, key.GetUInt32Value()); + return; + case FieldDescriptor::CPPTYPE_BOOL: + reflection->SetBool(message, field_desc, key.GetBoolValue()); + return; + } +} + +void MapFieldPrinterHelper::CopyValue(const MapValueRef& value, + Message* message, + const FieldDescriptor* field_desc) { + const Reflection* reflection = message->GetReflection(); + switch (field_desc->cpp_type()) { + case FieldDescriptor::CPPTYPE_DOUBLE: + reflection->SetDouble(message, field_desc, value.GetDoubleValue()); + return; + case FieldDescriptor::CPPTYPE_FLOAT: + reflection->SetFloat(message, field_desc, value.GetFloatValue()); + return; + case FieldDescriptor::CPPTYPE_ENUM: + reflection->SetEnumValue(message, field_desc, value.GetEnumValue()); + return; + case FieldDescriptor::CPPTYPE_MESSAGE: { + Message* sub_message = value.GetMessageValue().New(); + sub_message->CopyFrom(value.GetMessageValue()); + reflection->SetAllocatedMessage(message, sub_message, field_desc); + return; + } + case FieldDescriptor::CPPTYPE_STRING: + reflection->SetString(message, field_desc, value.GetStringValue()); + return; + case FieldDescriptor::CPPTYPE_INT64: + reflection->SetInt64(message, field_desc, value.GetInt64Value()); + return; + case FieldDescriptor::CPPTYPE_INT32: + reflection->SetInt32(message, field_desc, value.GetInt32Value()); + return; + case FieldDescriptor::CPPTYPE_UINT64: + reflection->SetUInt64(message, field_desc, value.GetUInt64Value()); + return; + case FieldDescriptor::CPPTYPE_UINT32: + reflection->SetUInt32(message, field_desc, value.GetUInt32Value()); + return; + case FieldDescriptor::CPPTYPE_BOOL: + reflection->SetBool(message, field_desc, value.GetBoolValue()); + return; + } +} +} // namespace internal + void TextFormat::Printer::PrintField(const Message& message, const Reflection* reflection, const FieldDescriptor* field, TextGenerator* generator) const { - if (use_short_repeated_primitives_ && - field->is_repeated() && + if (use_short_repeated_primitives_ && field->is_repeated() && field->cpp_type() != FieldDescriptor::CPPTYPE_STRING && field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { PrintShortRepeatedField(message, reflection, field, generator); @@ -1883,33 +2266,38 @@ void TextFormat::Printer::PrintField(const Message& message, if (field->is_repeated()) { count = reflection->FieldSize(message, field); - } else if (reflection->HasField(message, field)) { + } else if (reflection->HasField(message, field) || + field->containing_type()->options().map_entry()) { count = 1; } - std::vector map_entries; - const bool is_map = field->is_map(); + std::vector sorted_map_field; + bool need_release = false; + bool is_map = field->is_map(); if (is_map) { - map_entries = DynamicMapSorter::Sort(message, count, reflection, field); + need_release = internal::MapFieldPrinterHelper::SortMap( + message, reflection, field, &sorted_map_field); } for (int j = 0; j < count; ++j) { const int field_index = field->is_repeated() ? j : -1; - PrintFieldName(message, reflection, field, generator); + PrintFieldName(message, field_index, count, reflection, field, generator); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - const FastFieldValuePrinter* printer = FindWithDefault( - custom_printers_, field, default_field_value_printer_.get()); + const FastFieldValuePrinter* printer = GetFieldPrinter(field); const Message& sub_message = field->is_repeated() - ? (is_map ? *map_entries[j] + ? (is_map ? *sorted_map_field[j] : reflection->GetRepeatedMessage(message, field, j)) : reflection->GetMessage(message, field); printer->PrintMessageStart(sub_message, field_index, count, single_line_mode_, generator); generator->Indent(); - Print(sub_message, generator); + if (!printer->PrintMessageContent(sub_message, field_index, count, + single_line_mode_, generator)) { + Print(sub_message, generator); + } generator->Outdent(); printer->PrintMessageEnd(sub_message, field_index, count, single_line_mode_, generator); @@ -1924,15 +2312,21 @@ void TextFormat::Printer::PrintField(const Message& message, } } } + + if (need_release) { + for (const Message* message_to_delete : sorted_map_field) { + delete message_to_delete; + } + } } void TextFormat::Printer::PrintShortRepeatedField( const Message& message, const Reflection* reflection, const FieldDescriptor* field, TextGenerator* generator) const { // Print primitive repeated field in short form. - PrintFieldName(message, reflection, field, generator); - int size = reflection->FieldSize(message, field); + PrintFieldName(message, /*field_index=*/-1, /*field_count=*/size, reflection, + field, generator); generator->PrintLiteral(": ["); for (int i = 0; i < size; i++) { if (i > 0) generator->PrintLiteral(", "); @@ -1946,19 +2340,20 @@ void TextFormat::Printer::PrintShortRepeatedField( } void TextFormat::Printer::PrintFieldName(const Message& message, + int field_index, int field_count, const Reflection* reflection, const FieldDescriptor* field, TextGenerator* generator) const { // if use_field_number_ is true, prints field number instead // of field name. if (use_field_number_) { - generator->PrintString(SimpleItoa(field->number())); + generator->PrintString(StrCat(field->number())); return; } - const FastFieldValuePrinter* printer = FindWithDefault( - custom_printers_, field, default_field_value_printer_.get()); - printer->PrintFieldName(message, reflection, field, generator); + const FastFieldValuePrinter* printer = GetFieldPrinter(field); + printer->PrintFieldName(message, field_index, field_count, reflection, field, + generator); } void TextFormat::Printer::PrintFieldValue(const Message& message, @@ -1969,8 +2364,7 @@ void TextFormat::Printer::PrintFieldValue(const Message& message, GOOGLE_DCHECK(field->is_repeated() || (index == -1)) << "Index must be -1 for non-repeated fields"; - const FastFieldValuePrinter* printer = FindWithDefault( - custom_printers_, field, default_field_value_printer_.get()); + const FastFieldValuePrinter* printer = GetFieldPrinter(field); switch (field->cpp_type()) { #define OUTPUT_FIELD(CPPTYPE, METHOD) \ @@ -1982,25 +2376,27 @@ void TextFormat::Printer::PrintFieldValue(const Message& message, generator); \ break - OUTPUT_FIELD( INT32, Int32); - OUTPUT_FIELD( INT64, Int64); + OUTPUT_FIELD(INT32, Int32); + OUTPUT_FIELD(INT64, Int64); OUTPUT_FIELD(UINT32, UInt32); OUTPUT_FIELD(UINT64, UInt64); - OUTPUT_FIELD( FLOAT, Float); + OUTPUT_FIELD(FLOAT, Float); OUTPUT_FIELD(DOUBLE, Double); - OUTPUT_FIELD( BOOL, Bool); + OUTPUT_FIELD(BOOL, Bool); #undef OUTPUT_FIELD case FieldDescriptor::CPPTYPE_STRING: { - string scratch; - const string& value = field->is_repeated() - ? reflection->GetRepeatedStringReference( - message, field, index, &scratch) - : reflection->GetStringReference(message, field, &scratch); - const string* value_to_print = &value; - string truncated_value; + std::string scratch; + const std::string& value = + field->is_repeated() + ? reflection->GetRepeatedStringReference(message, field, index, + &scratch) + : reflection->GetStringReference(message, field, &scratch); + const std::string* value_to_print = &value; + std::string truncated_value; if (truncate_string_field_longer_than_ > 0 && - truncate_string_field_longer_than_ < value.size()) { + static_cast(truncate_string_field_longer_than_) < + value.size()) { truncated_value = value.substr(0, truncate_string_field_longer_than_) + "......"; value_to_print = &truncated_value; @@ -2015,12 +2411,13 @@ void TextFormat::Printer::PrintFieldValue(const Message& message, } case FieldDescriptor::CPPTYPE_ENUM: { - int enum_value = field->is_repeated() - ? reflection->GetRepeatedEnumValue(message, field, index) - : reflection->GetEnumValue(message, field); + int enum_value = + field->is_repeated() + ? reflection->GetRepeatedEnumValue(message, field, index) + : reflection->GetEnumValue(message, field); const EnumValueDescriptor* enum_desc = field->enum_type()->FindValueByNumber(enum_value); - if (enum_desc != NULL) { + if (enum_desc != nullptr) { printer->PrintEnum(enum_value, enum_desc->name(), generator); } else { // Ordinarily, enum_desc should not be null, because proto2 has the @@ -2029,16 +2426,15 @@ void TextFormat::Printer::PrintFieldValue(const Message& message, // it is possible for the user to force an unknown integer value. So we // simply use the integer value itself as the enum value name in this // case. - printer->PrintEnum(enum_value, StringPrintf("%d", enum_value), - generator); + printer->PrintEnum(enum_value, StrCat(enum_value), generator); } break; } case FieldDescriptor::CPPTYPE_MESSAGE: Print(field->is_repeated() - ? reflection->GetRepeatedMessage(message, field, index) - : reflection->GetMessage(message, field), + ? reflection->GetRepeatedMessage(message, field, index) + : reflection->GetMessage(message, field), generator); break; } @@ -2050,59 +2446,43 @@ void TextFormat::Printer::PrintFieldValue(const Message& message, } /* static */ bool TextFormat::PrintUnknownFields( - const UnknownFieldSet& unknown_fields, - io::ZeroCopyOutputStream* output) { + const UnknownFieldSet& unknown_fields, io::ZeroCopyOutputStream* output) { return Printer().PrintUnknownFields(unknown_fields, output); } -/* static */ bool TextFormat::PrintToString( - const Message& message, string* output) { +/* static */ bool TextFormat::PrintToString(const Message& message, + std::string* output) { return Printer().PrintToString(message, output); } /* static */ bool TextFormat::PrintUnknownFieldsToString( - const UnknownFieldSet& unknown_fields, string* output) { + const UnknownFieldSet& unknown_fields, std::string* output) { return Printer().PrintUnknownFieldsToString(unknown_fields, output); } /* static */ void TextFormat::PrintFieldValueToString( - const Message& message, - const FieldDescriptor* field, - int index, - string* output) { + const Message& message, const FieldDescriptor* field, int index, + std::string* output) { return Printer().PrintFieldValueToString(message, field, index, output); } /* static */ bool TextFormat::ParseFieldValueFromString( - const string& input, - const FieldDescriptor* field, - Message* message) { + const std::string& input, const FieldDescriptor* field, Message* message) { return Parser().ParseFieldValueFromString(input, field, message); } -// Prints an integer as hex with a fixed number of digits dependent on the -// integer type. -template -static string PaddedHex(IntType value) { - string result; - result.reserve(sizeof(value) * 2); - for (int i = sizeof(value) * 2 - 1; i >= 0; i--) { - result.push_back(int_to_hex_digit(value >> (i*4) & 0x0F)); - } - return result; -} - void TextFormat::Printer::PrintUnknownFields( - const UnknownFieldSet& unknown_fields, TextGenerator* generator) const { + const UnknownFieldSet& unknown_fields, TextGenerator* generator, + int recursion_budget) const { for (int i = 0; i < unknown_fields.field_count(); i++) { const UnknownField& field = unknown_fields.field(i); - string field_number = SimpleItoa(field.number()); + std::string field_number = StrCat(field.number()); switch (field.type()) { case UnknownField::TYPE_VARINT: generator->PrintString(field_number); generator->PrintLiteral(": "); - generator->PrintString(SimpleItoa(field.varint())); + generator->PrintString(StrCat(field.varint())); if (single_line_mode_) { generator->PrintLiteral(" "); } else { @@ -2135,9 +2515,16 @@ void TextFormat::Printer::PrintUnknownFields( } case UnknownField::TYPE_LENGTH_DELIMITED: { generator->PrintString(field_number); - const string& value = field.length_delimited(); + const std::string& value = field.length_delimited(); + // We create a CodedInputStream so that we can adhere to our recursion + // budget when we attempt to parse the data. UnknownFieldSet parsing is + // recursive because of groups. + io::CodedInputStream input_stream( + reinterpret_cast(value.data()), value.size()); + input_stream.SetRecursionLimit(recursion_budget); UnknownFieldSet embedded_unknown_fields; - if (!value.empty() && embedded_unknown_fields.ParseFromString(value)) { + if (!value.empty() && recursion_budget > 0 && + embedded_unknown_fields.ParseFromCodedStream(&input_stream)) { // This field is parseable as a Message. // So it is probably an embedded message. if (single_line_mode_) { @@ -2146,7 +2533,8 @@ void TextFormat::Printer::PrintUnknownFields( generator->PrintLiteral(" {\n"); generator->Indent(); } - PrintUnknownFields(embedded_unknown_fields, generator); + PrintUnknownFields(embedded_unknown_fields, generator, + recursion_budget - 1); if (single_line_mode_) { generator->PrintLiteral("} "); } else { @@ -2154,8 +2542,8 @@ void TextFormat::Printer::PrintUnknownFields( generator->PrintLiteral("}\n"); } } else { - // This field is not parseable as a Message. - // So it is probably just a plain string. + // This field is not parseable as a Message (or we ran out of + // recursion budget). So it is probably just a plain string. generator->PrintLiteral(": \""); generator->PrintString(CEscape(value)); if (single_line_mode_) { @@ -2174,7 +2562,10 @@ void TextFormat::Printer::PrintUnknownFields( generator->PrintLiteral(" {\n"); generator->Indent(); } - PrintUnknownFields(field.group(), generator); + // For groups, we recurse without checking the budget. This is OK, + // because if the groups were too deeply nested then we would have + // already rejected the message when we originally parsed it. + PrintUnknownFields(field.group(), generator, recursion_budget - 1); if (single_line_mode_) { generator->PrintLiteral("} "); } else { @@ -2188,3 +2579,5 @@ void TextFormat::Printer::PrintUnknownFields( } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h index cd0e307e9e9a7..3a3ee1563ab57 100644 --- a/src/google/protobuf/text_format.h +++ b/src/google/protobuf/text_format.h @@ -40,21 +40,26 @@ #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include #include #include #include +#include +#include + +#include + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif namespace google { namespace protobuf { namespace io { - class ErrorCollector; // tokenizer.h +class ErrorCollector; // tokenizer.h } // This class implements protocol buffer text format. Printing and parsing @@ -62,7 +67,7 @@ namespace io { // of messages. // // This class is really a namespace that contains only static methods. -class LIBPROTOBUF_EXPORT TextFormat { +class PROTOBUF_EXPORT TextFormat { public: // Outputs a textual representation of the given message to the given // output stream. Returns false if printing fails. @@ -77,29 +82,34 @@ class LIBPROTOBUF_EXPORT TextFormat { // Like Print(), but outputs directly to a string. // Note: output will be cleared prior to printing, and will be left empty // even if printing fails. Returns false if printing fails. - static bool PrintToString(const Message& message, string* output); + static bool PrintToString(const Message& message, std::string* output); - // Like PrintUnknownFields(), but outputs directly to a string. Returns false - // if printing fails. + // Like PrintUnknownFields(), but outputs directly to a string. Returns + // false if printing fails. static bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields, - string* output); + std::string* output); // Outputs a textual representation of the value of the field supplied on // the message supplied. For non-repeated fields, an index of -1 must // be supplied. Note that this method will print the default value for a // field if it is not set. static void PrintFieldValueToString(const Message& message, - const FieldDescriptor* field, - int index, - string* output); + const FieldDescriptor* field, int index, + std::string* output); - class LIBPROTOBUF_EXPORT BaseTextGenerator { + class PROTOBUF_EXPORT BaseTextGenerator { public: virtual ~BaseTextGenerator(); + + virtual void Indent() {} + virtual void Outdent() {} + // Returns the current indentation size in characters. + virtual size_t GetCurrentIndentationSize() const { return 0; } + // Print text to the output stream. virtual void Print(const char* text, size_t size) = 0; - void PrintString(const string& str) { Print(str.data(), str.size()); } + void PrintString(const std::string& str) { Print(str.data(), str.size()); } template void PrintLiteral(const char (&text)[n]) { @@ -111,7 +121,7 @@ class LIBPROTOBUF_EXPORT TextFormat { // string representation. // You can derive from this FastFieldValuePrinter if you want to have fields // to be printed in a different way and register it at the Printer. - class LIBPROTOBUF_EXPORT FastFieldValuePrinter { + class PROTOBUF_EXPORT FastFieldValuePrinter { public: FastFieldValuePrinter(); virtual ~FastFieldValuePrinter(); @@ -122,12 +132,16 @@ class LIBPROTOBUF_EXPORT TextFormat { virtual void PrintUInt64(uint64 val, BaseTextGenerator* generator) const; virtual void PrintFloat(float val, BaseTextGenerator* generator) const; virtual void PrintDouble(double val, BaseTextGenerator* generator) const; - virtual void PrintString(const string& val, + virtual void PrintString(const std::string& val, BaseTextGenerator* generator) const; - virtual void PrintBytes(const string& val, + virtual void PrintBytes(const std::string& val, BaseTextGenerator* generator) const; - virtual void PrintEnum(int32 val, const string& name, + virtual void PrintEnum(int32 val, const std::string& name, BaseTextGenerator* generator) const; + virtual void PrintFieldName(const Message& message, int field_index, + int field_count, const Reflection* reflection, + const FieldDescriptor* field, + BaseTextGenerator* generator) const; virtual void PrintFieldName(const Message& message, const Reflection* reflection, const FieldDescriptor* field, @@ -135,6 +149,14 @@ class LIBPROTOBUF_EXPORT TextFormat { virtual void PrintMessageStart(const Message& message, int field_index, int field_count, bool single_line_mode, BaseTextGenerator* generator) const; + // Allows to override the logic on how to print the content of a message. + // Return false to use the default printing logic. Note that it is legal for + // this function to print something and then return false to use the default + // content printing (although at that point it would behave similarly to + // PrintMessageStart). + virtual bool PrintMessageContent(const Message& message, int field_index, + int field_count, bool single_line_mode, + BaseTextGenerator* generator) const; virtual void PrintMessageEnd(const Message& message, int field_index, int field_count, bool single_line_mode, BaseTextGenerator* generator) const; @@ -143,44 +165,85 @@ class LIBPROTOBUF_EXPORT TextFormat { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastFieldValuePrinter); }; -// DEPRECATED: Please use FastFieldValuePrinter. - class LIBPROTOBUF_EXPORT FieldValuePrinter { + // Deprecated: please use FastFieldValuePrinter instead. + class PROTOBUF_EXPORT FieldValuePrinter { public: FieldValuePrinter(); virtual ~FieldValuePrinter(); - virtual string PrintBool(bool val) const; - virtual string PrintInt32(int32 val) const; - virtual string PrintUInt32(uint32 val) const; - virtual string PrintInt64(int64 val) const; - virtual string PrintUInt64(uint64 val) const; - virtual string PrintFloat(float val) const; - virtual string PrintDouble(double val) const; - virtual string PrintString(const string& val) const; - virtual string PrintBytes(const string& val) const; - virtual string PrintEnum(int32 val, const string& name) const; - virtual string PrintFieldName(const Message& message, - const Reflection* reflection, - const FieldDescriptor* field) const; - virtual string PrintMessageStart(const Message& message, - int field_index, - int field_count, - bool single_line_mode) const; - virtual string PrintMessageEnd(const Message& message, - int field_index, - int field_count, - bool single_line_mode) const; + virtual std::string PrintBool(bool val) const; + virtual std::string PrintInt32(int32 val) const; + virtual std::string PrintUInt32(uint32 val) const; + virtual std::string PrintInt64(int64 val) const; + virtual std::string PrintUInt64(uint64 val) const; + virtual std::string PrintFloat(float val) const; + virtual std::string PrintDouble(double val) const; + virtual std::string PrintString(const std::string& val) const; + virtual std::string PrintBytes(const std::string& val) const; + virtual std::string PrintEnum(int32 val, const std::string& name) const; + virtual std::string PrintFieldName(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field) const; + virtual std::string PrintMessageStart(const Message& message, + int field_index, int field_count, + bool single_line_mode) const; + virtual std::string PrintMessageEnd(const Message& message, int field_index, + int field_count, + bool single_line_mode) const; private: FastFieldValuePrinter delegate_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldValuePrinter); }; + class PROTOBUF_EXPORT MessagePrinter { + public: + MessagePrinter() {} + virtual ~MessagePrinter() {} + virtual void Print(const Message& message, bool single_line_mode, + BaseTextGenerator* generator) const = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessagePrinter); + }; + + // Interface that Printers or Parsers can use to find extensions, or types + // referenced in Any messages. + class PROTOBUF_EXPORT Finder { + public: + virtual ~Finder(); + + // Try to find an extension of *message by fully-qualified field + // name. Returns NULL if no extension is known for this name or number. + // The base implementation uses the extensions already known by the message. + virtual const FieldDescriptor* FindExtension(Message* message, + const std::string& name) const; + + // Similar to FindExtension, but uses a Descriptor and the extension number + // instead of using a Message and the name when doing the look up. + virtual const FieldDescriptor* FindExtensionByNumber( + const Descriptor* descriptor, int number) const; + + // Find the message type for an Any proto. + // Returns NULL if no message is known for this name. + // The base implementation only accepts prefixes of type.googleprod.com/ or + // type.googleapis.com/, and searches the DescriptorPool of the parent + // message. + virtual const Descriptor* FindAnyType(const Message& message, + const std::string& prefix, + const std::string& name) const; + + // Find the message factory for the given extension field. This can be used + // to generalize the Parser to add extension fields to a message in the same + // way as the "input" message for the Parser. + virtual MessageFactory* FindExtensionFactory( + const FieldDescriptor* field) const; + }; + // Class for those users which require more fine-grained control over how // a protobuffer message is printed out. - class LIBPROTOBUF_EXPORT Printer { + class PROTOBUF_EXPORT Printer { public: Printer(); - ~Printer(); // Like TextFormat::Print bool Print(const Message& message, io::ZeroCopyOutputStream* output) const; @@ -188,15 +251,14 @@ class LIBPROTOBUF_EXPORT TextFormat { bool PrintUnknownFields(const UnknownFieldSet& unknown_fields, io::ZeroCopyOutputStream* output) const; // Like TextFormat::PrintToString - bool PrintToString(const Message& message, string* output) const; + bool PrintToString(const Message& message, std::string* output) const; // Like TextFormat::PrintUnknownFieldsToString bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields, - string* output) const; + std::string* output) const; // Like TextFormat::PrintFieldValueToString void PrintFieldValueToString(const Message& message, - const FieldDescriptor* field, - int index, - string* output) const; + const FieldDescriptor* field, int index, + std::string* output) const; // Adjust the initial indent level of all output. Each indent level is // equal to two spaces. @@ -210,9 +272,7 @@ class LIBPROTOBUF_EXPORT TextFormat { single_line_mode_ = single_line_mode; } - bool IsInSingleLineMode() { - return single_line_mode_; - } + bool IsInSingleLineMode() const { return single_line_mode_; } // If use_field_number is true, uses field number instead of field name. void SetUseFieldNumber(bool use_field_number) { @@ -234,10 +294,12 @@ class LIBPROTOBUF_EXPORT TextFormat { // sequences. This will change the default FastFieldValuePrinter. void SetUseUtf8StringEscaping(bool as_utf8); - // Set the default (Fast)FieldValuePrinter that is used for all fields that + // Set the default FastFieldValuePrinter that is used for all fields that // don't have a field-specific printer registered. // Takes ownership of the printer. void SetDefaultFieldValuePrinter(const FastFieldValuePrinter* printer); + + PROTOBUF_DEPRECATED_MSG("Please use FastFieldValuePrinter") void SetDefaultFieldValuePrinter(const FieldValuePrinter* printer); // Sets whether we want to hide unknown fields or not. @@ -246,13 +308,13 @@ class LIBPROTOBUF_EXPORT TextFormat { // is useful to be able to print the message without unknown fields (e.g. // for the python protobuf version to maintain consistency between its pure // python and c++ implementations). - void SetHideUnknownFields(bool hide) { - hide_unknown_fields_ = hide; - } + void SetHideUnknownFields(bool hide) { hide_unknown_fields_ = hide; } - // If print_message_fields_in_index_order is true, print fields of a proto - // message using the order defined in source code instead of the field - // number. By default, use the field number order. + // If print_message_fields_in_index_order is true, fields of a proto message + // will be printed using the order defined in source code instead of the + // field number, extensions will be printed at the end of the message + // and their relative order is determined by the extension number. + // By default, use the field number order. void SetPrintMessageFieldsInIndexOrder( bool print_message_fields_in_index_order) { print_message_fields_in_index_order_ = @@ -266,13 +328,14 @@ class LIBPROTOBUF_EXPORT TextFormat { // If expand==false, print Any using the default printer. The output will // look like // type_url: "" value: "serialized_content" - void SetExpandAny(bool expand) { - expand_any_ = expand; - } + void SetExpandAny(bool expand) { expand_any_ = expand; } - // If non-zero, we truncate all string fields that are longer than this - // threshold. This is useful when the proto message has very long strings, - // e.g., dump of encoded image file. + // Set how parser finds message for Any payloads. + void SetFinder(const Finder* finder) { finder_ = finder; } + + // If non-zero, we truncate all string fields that are longer than + // this threshold. This is useful when the proto message has very long + // strings, e.g., dump of encoded image file. // // NOTE(hfgong): Setting a non-zero value breaks round-trip safe // property of TextFormat::Printer. That is, from the printed message, we @@ -282,21 +345,32 @@ class LIBPROTOBUF_EXPORT TextFormat { truncate_string_field_longer_than_ = truncate_string_field_longer_than; } - // Register a custom field-specific (Fast)FieldValuePrinter for fields + // Register a custom field-specific FastFieldValuePrinter for fields // with a particular FieldDescriptor. // Returns "true" if the registration succeeded, or "false", if there is // already a printer for that FieldDescriptor. // Takes ownership of the printer on successful registration. - bool RegisterFieldValuePrinter(const FieldDescriptor* field, - const FieldValuePrinter* printer); bool RegisterFieldValuePrinter(const FieldDescriptor* field, const FastFieldValuePrinter* printer); + PROTOBUF_DEPRECATED_MSG("Please use FastFieldValuePrinter") + bool RegisterFieldValuePrinter(const FieldDescriptor* field, + const FieldValuePrinter* printer); + + // Register a custom message-specific MessagePrinter for messages with a + // particular Descriptor. + // Returns "true" if the registration succeeded, or "false" if there is + // already a printer for that Descriptor. + bool RegisterMessagePrinter(const Descriptor* descriptor, + const MessagePrinter* printer); + private: // Forward declaration of an internal class used to print the text // output to the OutputStream (see text_format.cc for implementation). class TextGenerator; + static const char* const kDoNotParse; + // Internal Print method, used for writing to the OutputStream via // the TextGenerator class. void Print(const Message& message, TextGenerator* generator) const; @@ -314,7 +388,8 @@ class LIBPROTOBUF_EXPORT TextFormat { // Print the name of a field -- i.e. everything that comes before the // ':' for a single name/value pair. - void PrintFieldName(const Message& message, const Reflection* reflection, + void PrintFieldName(const Message& message, int field_index, + int field_count, const Reflection* reflection, const FieldDescriptor* field, TextGenerator* generator) const; @@ -326,32 +401,40 @@ class LIBPROTOBUF_EXPORT TextFormat { // Print the fields in an UnknownFieldSet. They are printed by tag number // only. Embedded messages are heuristically identified by attempting to - // parse them. + // parse them (subject to the recursion budget). void PrintUnknownFields(const UnknownFieldSet& unknown_fields, - TextGenerator* generator) const; + TextGenerator* generator, + int recursion_budget) const; bool PrintAny(const Message& message, TextGenerator* generator) const; - int initial_indent_level_; + const FastFieldValuePrinter* GetFieldPrinter( + const FieldDescriptor* field) const { + auto it = custom_printers_.find(field); + return it == custom_printers_.end() ? default_field_value_printer_.get() + : it->second.get(); + } + int initial_indent_level_; bool single_line_mode_; - bool use_field_number_; - bool use_short_repeated_primitives_; - bool hide_unknown_fields_; - bool print_message_fields_in_index_order_; - bool expand_any_; - int64 truncate_string_field_longer_than_; - google::protobuf::scoped_ptr default_field_value_printer_; - typedef std::map + std::unique_ptr default_field_value_printer_; + typedef std::map> CustomPrinterMap; CustomPrinterMap custom_printers_; + + typedef std::map> + CustomMessagePrinterMap; + CustomMessagePrinterMap custom_message_printers_; + + const Finder* finder_; }; // Parses a text-format protocol message from the given input stream to @@ -371,35 +454,21 @@ class LIBPROTOBUF_EXPORT TextFormat { // google::protobuf::MessageLite::ParseFromString(). static bool Parse(io::ZeroCopyInputStream* input, Message* output); // Like Parse(), but reads directly from a string. - static bool ParseFromString(const string& input, Message* output); + static bool ParseFromString(ConstStringParam input, Message* output); // Like Parse(), but the data is merged into the given message, as if // using Message::MergeFrom(). static bool Merge(io::ZeroCopyInputStream* input, Message* output); // Like Merge(), but reads directly from a string. - static bool MergeFromString(const string& input, Message* output); + static bool MergeFromString(ConstStringParam input, Message* output); // Parse the given text as a single field value and store it into the // given field of the given message. If the field is a repeated field, // the new value will be added to the end - static bool ParseFieldValueFromString(const string& input, + static bool ParseFieldValueFromString(const std::string& input, const FieldDescriptor* field, Message* message); - // Interface that TextFormat::Parser can use to find extensions. - // This class may be extended in the future to find more information - // like fields, etc. - class LIBPROTOBUF_EXPORT Finder { - public: - virtual ~Finder(); - - // Try to find an extension of *message by fully-qualified field - // name. Returns NULL if no extension is known for this name or number. - virtual const FieldDescriptor* FindExtension( - Message* message, - const string& name) const = 0; - }; - // A location in the parsed text. struct ParseLocation { int line; @@ -412,10 +481,11 @@ class LIBPROTOBUF_EXPORT TextFormat { // Data structure which is populated with the locations of each field // value parsed from the text. - class LIBPROTOBUF_EXPORT ParseInfoTree { + class PROTOBUF_EXPORT ParseInfoTree { public: - ParseInfoTree(); - ~ParseInfoTree(); + ParseInfoTree() = default; + ParseInfoTree(const ParseInfoTree&) = delete; + ParseInfoTree& operator=(const ParseInfoTree&) = delete; // Returns the parse location for index-th value of the field in the parsed // text. If none exists, returns a location with line = -1. Index should be @@ -439,22 +509,21 @@ class LIBPROTOBUF_EXPORT TextFormat { ParseInfoTree* CreateNested(const FieldDescriptor* field); // Defines the map from the index-th field descriptor to its parse location. - typedef std::map > LocationMap; + typedef std::map > + LocationMap; // Defines the map from the index-th field descriptor to the nested parse // info tree. typedef std::map > NestedMap; + std::vector>> + NestedMap; LocationMap locations_; NestedMap nested_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParseInfoTree); }; // For more control over parsing, use this class. - class LIBPROTOBUF_EXPORT Parser { + class PROTOBUF_EXPORT Parser { public: Parser(); ~Parser(); @@ -462,11 +531,11 @@ class LIBPROTOBUF_EXPORT TextFormat { // Like TextFormat::Parse(). bool Parse(io::ZeroCopyInputStream* input, Message* output); // Like TextFormat::ParseFromString(). - bool ParseFromString(const string& input, Message* output); + bool ParseFromString(ConstStringParam input, Message* output); // Like TextFormat::Merge(). bool Merge(io::ZeroCopyInputStream* input, Message* output); // Like TextFormat::MergeFromString(). - bool MergeFromString(const string& input, Message* output); + bool MergeFromString(ConstStringParam input, Message* output); // Set where to report parse errors. If NULL (the default), errors will // be printed to stderr. @@ -477,21 +546,15 @@ class LIBPROTOBUF_EXPORT TextFormat { // Set how parser finds extensions. If NULL (the default), the // parser will use the standard Reflection object associated with // the message being parsed. - void SetFinder(Finder* finder) { - finder_ = finder; - } + void SetFinder(const Finder* finder) { finder_ = finder; } // Sets where location information about the parse will be written. If NULL // (the default), then no location will be written. - void WriteLocationsTo(ParseInfoTree* tree) { - parse_info_tree_ = tree; - } + void WriteLocationsTo(ParseInfoTree* tree) { parse_info_tree_ = tree; } // Normally parsing fails if, after parsing, output->IsInitialized() // returns false. Call AllowPartialMessage(true) to skip this check. - void AllowPartialMessage(bool allow) { - allow_partial_ = allow; - } + void AllowPartialMessage(bool allow) { allow_partial_ = allow; } // Allow field names to be matched case-insensitively. // This is not advisable if there are fields that only differ in case, or @@ -502,14 +565,34 @@ class LIBPROTOBUF_EXPORT TextFormat { } // Like TextFormat::ParseFieldValueFromString - bool ParseFieldValueFromString(const string& input, + bool ParseFieldValueFromString(const std::string& input, const FieldDescriptor* field, Message* output); + // When an unknown extension is met, parsing will fail if this option is + // set to false (the default). If true, unknown extensions will be ignored + // and a warning message will be generated. + // Beware! Setting this option true may hide some errors (e.g. spelling + // error on extension name). This allows data loss; unlike binary format, + // text format cannot preserve unknown extensions. Avoid using this option + // if possible. + void AllowUnknownExtension(bool allow) { allow_unknown_extension_ = allow; } - void AllowFieldNumber(bool allow) { - allow_field_number_ = allow; - } + // When an unknown field is met, parsing will fail if this option is set + // to false (the default). If true, unknown fields will be ignored and + // a warning message will be generated. + // Beware! Setting this option true may hide some errors (e.g. spelling + // error on field name). This allows data loss; unlike binary format, text + // format cannot preserve unknown fields. Avoid using this option + // if possible. + void AllowUnknownField(bool allow) { allow_unknown_field_ = allow; } + + + void AllowFieldNumber(bool allow) { allow_field_number_ = allow; } + + // Sets maximum recursion depth which parser can use. This is effectively + // the maximum allowed nesting of proto messages. + void SetRecursionLimit(int limit) { recursion_limit_ = limit; } private: // Forward declaration of an internal class used to parse text @@ -518,20 +601,21 @@ class LIBPROTOBUF_EXPORT TextFormat { // Like TextFormat::Merge(). The provided implementation is used // to do the parsing. - bool MergeUsingImpl(io::ZeroCopyInputStream* input, - Message* output, + bool MergeUsingImpl(io::ZeroCopyInputStream* input, Message* output, ParserImpl* parser_impl); io::ErrorCollector* error_collector_; - Finder* finder_; + const Finder* finder_; ParseInfoTree* parse_info_tree_; bool allow_partial_; bool allow_case_insensitive_field_; bool allow_unknown_field_; + bool allow_unknown_extension_; bool allow_unknown_enum_; bool allow_field_number_; bool allow_relaxed_whitespace_; bool allow_singular_overwrites_; + int recursion_limit_; }; @@ -555,13 +639,14 @@ inline void TextFormat::RecordLocation(ParseInfoTree* info_tree, info_tree->RecordLocation(field, location); } - inline TextFormat::ParseInfoTree* TextFormat::CreateNested( ParseInfoTree* info_tree, const FieldDescriptor* field) { return info_tree->CreateNested(field); } } // namespace protobuf - } // namespace google + +#include + #endif // GOOGLE_PROTOBUF_TEXT_FORMAT_H__ diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc index f823bcb2ccf36..449a78c6dc2bf 100644 --- a/src/google/protobuf/text_format_unittest.cc +++ b/src/google/protobuf/text_format_unittest.cc @@ -36,31 +36,33 @@ #include #include + #include #include -#ifndef _SHARED_PTR_H -#include -#endif #include #include -#include #include #include +#include #include +#include #include #include #include +#include #include #include - #include -#include +#include #include #include -#include +#include +#include +#include + namespace google { namespace protobuf { @@ -68,44 +70,46 @@ namespace protobuf { namespace text_format_unittest { // A basic string with different escapable characters for testing. -const string kEscapeTestString = - "\"A string with ' characters \n and \r newlines and \t tabs and \001 " - "slashes \\ and multiple spaces"; +const std::string kEscapeTestString = + "\"A string with ' characters \n and \r newlines and \t tabs and \001 " + "slashes \\ and multiple spaces"; // A representation of the above string with all the characters escaped. -const string kEscapeTestStringEscaped = - "\"\\\"A string with \\' characters \\n and \\r newlines " - "and \\t tabs and \\001 slashes \\\\ and multiple spaces\""; +const std::string kEscapeTestStringEscaped = + "\"\\\"A string with \\' characters \\n and \\r newlines " + "and \\t tabs and \\001 slashes \\\\ and multiple spaces\""; class TextFormatTest : public testing::Test { public: - static void SetUpTestCase() { + static void SetUpTestSuite() { GOOGLE_CHECK_OK(File::GetContents( - TestSourceDir() + - "/google/protobuf/" - "testdata/text_format_unittest_data_oneof_implemented.txt", + TestUtil::GetTestDataPath( + "net/proto2/internal/" + "testdata/text_format_unittest_data_oneof_implemented.txt"), &static_proto_debug_string_, true)); + CleanStringLineEndings(&static_proto_debug_string_, false); } TextFormatTest() : proto_debug_string_(static_proto_debug_string_) {} protected: // Debug string read from text_format_unittest_data.txt. - const string proto_debug_string_; + const std::string proto_debug_string_; unittest::TestAllTypes proto_; private: - static string static_proto_debug_string_; + static std::string static_proto_debug_string_; }; -string TextFormatTest::static_proto_debug_string_; +std::string TextFormatTest::static_proto_debug_string_; class TextFormatExtensionsTest : public testing::Test { public: - static void SetUpTestCase() { - GOOGLE_CHECK_OK(File::GetContents(TestSourceDir() + - "/google/protobuf/testdata/" - "text_format_unittest_extensions_data.txt", - &static_proto_debug_string_, true)); + static void SetUpTestSuite() { + GOOGLE_CHECK_OK(File::GetContents( + TestUtil::GetTestDataPath("net/proto2/internal/testdata/" + "text_format_unittest_extensions_data.txt"), + &static_proto_debug_string_, true)); + CleanStringLineEndings(&static_proto_debug_string_, false); } TextFormatExtensionsTest() @@ -113,14 +117,13 @@ class TextFormatExtensionsTest : public testing::Test { protected: // Debug string read from text_format_unittest_data.txt. - const string proto_debug_string_; + const std::string proto_debug_string_; unittest::TestAllExtensions proto_; private: - static string static_proto_debug_string_; + static std::string static_proto_debug_string_; }; -string TextFormatExtensionsTest::static_proto_debug_string_; - +std::string TextFormatExtensionsTest::static_proto_debug_string_; TEST_F(TextFormatTest, Basic) { TestUtil::SetAllFields(&proto_); @@ -138,10 +141,11 @@ TEST_F(TextFormatTest, ShortDebugString) { proto_.mutable_optional_nested_message()->set_bb(2); proto_.mutable_optional_foreign_message(); - EXPECT_EQ("optional_int32: 1 optional_string: \"hello\" " - "optional_nested_message { bb: 2 } " - "optional_foreign_message { }", - proto_.ShortDebugString()); + EXPECT_EQ( + "optional_int32: 1 optional_string: \"hello\" " + "optional_nested_message { bb: 2 } " + "optional_foreign_message { }", + proto_.ShortDebugString()); } TEST_F(TextFormatTest, ShortPrimitiveRepeateds) { @@ -157,44 +161,47 @@ TEST_F(TextFormatTest, ShortPrimitiveRepeateds) { TextFormat::Printer printer; printer.SetUseShortRepeatedPrimitives(true); - string text; + std::string text; EXPECT_TRUE(printer.PrintToString(proto_, &text)); - EXPECT_EQ("optional_int32: 123\n" - "repeated_int32: [456, 789]\n" - "repeated_string: \"foo\"\n" - "repeated_string: \"bar\"\n" - "repeated_nested_message {\n bb: 2\n}\n" - "repeated_nested_message {\n bb: 3\n}\n" - "repeated_nested_enum: [FOO, BAR]\n", - text); - - // Verify that any existing data in the string is cleared when - // PrintToString() is called. + EXPECT_EQ( + "optional_int32: 123\n" + "repeated_int32: [456, 789]\n" + "repeated_string: \"foo\"\n" + "repeated_string: \"bar\"\n" + "repeated_nested_message {\n bb: 2\n}\n" + "repeated_nested_message {\n bb: 3\n}\n" + "repeated_nested_enum: [FOO, BAR]\n", + text); + + // Verify that any existing data in the string is cleared when PrintToString() + // is called. text = "just some data here...\n\nblah blah"; EXPECT_TRUE(printer.PrintToString(proto_, &text)); - EXPECT_EQ("optional_int32: 123\n" - "repeated_int32: [456, 789]\n" - "repeated_string: \"foo\"\n" - "repeated_string: \"bar\"\n" - "repeated_nested_message {\n bb: 2\n}\n" - "repeated_nested_message {\n bb: 3\n}\n" - "repeated_nested_enum: [FOO, BAR]\n", - text); + EXPECT_EQ( + "optional_int32: 123\n" + "repeated_int32: [456, 789]\n" + "repeated_string: \"foo\"\n" + "repeated_string: \"bar\"\n" + "repeated_nested_message {\n bb: 2\n}\n" + "repeated_nested_message {\n bb: 3\n}\n" + "repeated_nested_enum: [FOO, BAR]\n", + text); // Try in single-line mode. printer.SetSingleLineMode(true); EXPECT_TRUE(printer.PrintToString(proto_, &text)); - EXPECT_EQ("optional_int32: 123 " - "repeated_int32: [456, 789] " - "repeated_string: \"foo\" " - "repeated_string: \"bar\" " - "repeated_nested_message { bb: 2 } " - "repeated_nested_message { bb: 3 } " - "repeated_nested_enum: [FOO, BAR] ", - text); + EXPECT_EQ( + "optional_int32: 123 " + "repeated_int32: [456, 789] " + "repeated_string: \"foo\" " + "repeated_string: \"bar\" " + "repeated_nested_message { bb: 2 } " + "repeated_nested_message { bb: 3 } " + "repeated_nested_enum: [FOO, BAR] ", + text); } @@ -203,13 +210,12 @@ TEST_F(TextFormatTest, StringEscape) { proto_.set_optional_string(kEscapeTestString); // Get the DebugString from the proto. - string debug_string = proto_.DebugString(); - string utf8_debug_string = proto_.Utf8DebugString(); + std::string debug_string = proto_.DebugString(); + std::string utf8_debug_string = proto_.Utf8DebugString(); // Hardcode a correct value to test against. - string correct_string = "optional_string: " - + kEscapeTestStringEscaped - + "\n"; + std::string correct_string = + "optional_string: " + kEscapeTestStringEscaped + "\n"; // Compare. EXPECT_EQ(correct_string, debug_string); @@ -217,8 +223,8 @@ TEST_F(TextFormatTest, StringEscape) { // the protocol buffer contains no UTF-8 text. EXPECT_EQ(correct_string, utf8_debug_string); - string expected_short_debug_string = "optional_string: " - + kEscapeTestStringEscaped; + std::string expected_short_debug_string = + "optional_string: " + kEscapeTestStringEscaped; EXPECT_EQ(expected_short_debug_string, proto_.ShortDebugString()); } @@ -228,18 +234,18 @@ TEST_F(TextFormatTest, Utf8DebugString) { proto_.set_optional_bytes("\350\260\267\346\255\214"); // Get the DebugString from the proto. - string debug_string = proto_.DebugString(); - string utf8_debug_string = proto_.Utf8DebugString(); + std::string debug_string = proto_.DebugString(); + std::string utf8_debug_string = proto_.Utf8DebugString(); // Hardcode a correct value to test against. - string correct_utf8_string = + std::string correct_utf8_string = "optional_string: " "\"\350\260\267\346\255\214\"" "\n" "optional_bytes: " "\"\\350\\260\\267\\346\\255\\214\"" "\n"; - string correct_string = + std::string correct_string = "optional_string: " "\"\\350\\260\\267\\346\\255\\214\"" "\n" @@ -269,17 +275,17 @@ TEST_F(TextFormatTest, PrintUnknownFields) { unknown_fields->AddVarint(8, 3); EXPECT_EQ( - "5: 1\n" - "5: 0x00000002\n" - "5: 0x0000000000000003\n" - "5: \"4\"\n" - "5 {\n" - " 10: 5\n" - "}\n" - "8: 1\n" - "8: 2\n" - "8: 3\n", - message.DebugString()); + "5: 1\n" + "5: 0x00000002\n" + "5: 0x0000000000000003\n" + "5: \"4\"\n" + "5 {\n" + " 10: 5\n" + "}\n" + "8: 1\n" + "8: 2\n" + "8: 3\n", + message.DebugString()); } TEST_F(TextFormatTest, PrintUnknownFieldsHidden) { @@ -301,7 +307,7 @@ TEST_F(TextFormatTest, PrintUnknownFieldsHidden) { TextFormat::Printer printer; printer.SetHideUnknownFields(true); - string output; + std::string output; printer.PrintToString(message, &output); EXPECT_EQ("data: \"data\"\n", output); @@ -334,21 +340,53 @@ TEST_F(TextFormatTest, PrintUnknownMessage) { // nested message. message.add_repeated_nested_message()->set_bb(123); - string data; + std::string data; message.SerializeToString(&data); - string text; + std::string text; UnknownFieldSet unknown_fields; EXPECT_TRUE(unknown_fields.ParseFromString(data)); EXPECT_TRUE(TextFormat::PrintUnknownFieldsToString(unknown_fields, &text)); - EXPECT_EQ( - "44: \"abc\"\n" - "44: \"def\"\n" - "44: \"\"\n" - "48 {\n" - " 1: 123\n" - "}\n", - text); + // Field 44 and 48 can be printed in any order. + EXPECT_THAT(text, testing::HasSubstr("44: \"abc\"\n" + "44: \"def\"\n" + "44: \"\"\n")); + EXPECT_THAT(text, testing::HasSubstr("48 {\n" + " 1: 123\n" + "}\n")); +} + +TEST_F(TextFormatTest, PrintDeeplyNestedUnknownMessage) { + // Create a deeply nested message. + static constexpr int kNestingDepth = 25000; + static constexpr int kUnknownFieldNumber = 1; + std::vector lengths; + lengths.reserve(kNestingDepth); + lengths.push_back(0); + for (int i = 0; i < kNestingDepth - 1; ++i) { + lengths.push_back( + internal::WireFormatLite::TagSize( + kUnknownFieldNumber, internal::WireFormatLite::TYPE_BYTES) + + internal::WireFormatLite::LengthDelimitedSize(lengths.back())); + } + std::string serialized; + { + io::StringOutputStream zero_copy_stream(&serialized); + io::CodedOutputStream coded_stream(&zero_copy_stream); + for (int i = kNestingDepth - 1; i >= 0; --i) { + internal::WireFormatLite::WriteTag( + kUnknownFieldNumber, + internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, &coded_stream); + coded_stream.WriteVarint32(lengths[i]); + } + } + + // Parse the data and verify that we can print it without overflowing the + // stack. + unittest::TestEmptyMessage message; + ASSERT_TRUE(message.ParseFromString(serialized)); + std::string text; + EXPECT_TRUE(TextFormat::PrintToString(message, &text)); } TEST_F(TextFormatTest, PrintMessageWithIndent) { @@ -360,17 +398,17 @@ TEST_F(TextFormatTest, PrintMessageWithIndent) { message.add_repeated_string("def"); message.add_repeated_nested_message()->set_bb(123); - string text; + std::string text; TextFormat::Printer printer; printer.SetInitialIndentLevel(1); EXPECT_TRUE(printer.PrintToString(message, &text)); EXPECT_EQ( - " repeated_string: \"abc\"\n" - " repeated_string: \"def\"\n" - " repeated_nested_message {\n" - " bb: 123\n" - " }\n", - text); + " repeated_string: \"abc\"\n" + " repeated_string: \"def\"\n" + " repeated_nested_message {\n" + " bb: 123\n" + " }\n", + text); } TEST_F(TextFormatTest, PrintMessageSingleLine) { @@ -382,15 +420,15 @@ TEST_F(TextFormatTest, PrintMessageSingleLine) { message.add_repeated_string("def"); message.add_repeated_nested_message()->set_bb(123); - string text; + std::string text; TextFormat::Printer printer; printer.SetInitialIndentLevel(1); printer.SetSingleLineMode(true); EXPECT_TRUE(printer.PrintToString(message, &text)); EXPECT_EQ( - " repeated_string: \"abc\" repeated_string: \"def\" " - "repeated_nested_message { bb: 123 } ", - text); + " repeated_string: \"abc\" repeated_string: \"def\" " + "repeated_nested_message { bb: 123 } ", + text); } TEST_F(TextFormatTest, PrintBufferTooSmall) { @@ -411,7 +449,7 @@ TEST_F(TextFormatTest, PrintBufferTooSmall) { // A printer that appends 'u' to all unsigned int32. class CustomUInt32FieldValuePrinter : public TextFormat::FieldValuePrinter { public: - virtual string PrintUInt32(uint32 val) const { + virtual std::string PrintUInt32(uint32 val) const { return StrCat(FieldValuePrinter::PrintUInt32(val), "u"); } }; @@ -428,14 +466,14 @@ TEST_F(TextFormatTest, DefaultCustomFieldPrinter) { printer.SetDefaultFieldValuePrinter(new CustomUInt32FieldValuePrinter()); // Let's see if that works well together with the repeated primitives: printer.SetUseShortRepeatedPrimitives(true); - string text; + std::string text; printer.PrintToString(message, &text); EXPECT_EQ("optional_uint32: 42u\nrepeated_uint32: [1u, 2u, 3u]\n", text); } class CustomInt32FieldValuePrinter : public TextFormat::FieldValuePrinter { public: - virtual string PrintInt32(int32 val) const { + virtual std::string PrintInt32(int32 val) const { return StrCat("value-is(", FieldValuePrinter::PrintInt32(val), ")"); } }; @@ -450,7 +488,7 @@ TEST_F(TextFormatTest, FieldSpecificCustomPrinter) { EXPECT_TRUE(printer.RegisterFieldValuePrinter( message.GetDescriptor()->FindFieldByName("optional_int32"), new CustomInt32FieldValuePrinter())); - string text; + std::string text; printer.PrintToString(message, &text); EXPECT_EQ("optional_int32: value-is(42)\nrepeated_int32: 42\n", text); } @@ -474,31 +512,31 @@ TEST_F(TextFormatTest, ErrorCasesRegisteringFieldValuePrinterShouldFail) { // NULL printer. EXPECT_FALSE(printer.RegisterFieldValuePrinter( message.GetDescriptor()->FindFieldByName("optional_int32"), - static_cast(NULL))); + static_cast(nullptr))); EXPECT_FALSE(printer.RegisterFieldValuePrinter( message.GetDescriptor()->FindFieldByName("optional_int32"), - static_cast(NULL))); + static_cast(nullptr))); // Because registration fails, the ownership of this printer is never taken. TextFormat::FieldValuePrinter my_field_printer; // NULL field - EXPECT_FALSE(printer.RegisterFieldValuePrinter(NULL, &my_field_printer)); + EXPECT_FALSE(printer.RegisterFieldValuePrinter(nullptr, &my_field_printer)); } class CustomMessageFieldValuePrinter : public TextFormat::FieldValuePrinter { public: - virtual string PrintInt32(int32 v) const { - return StrCat(FieldValuePrinter::PrintInt32(v), " # x", strings::Hex(v)); + virtual std::string PrintInt32(int32 v) const { + return StrCat(FieldValuePrinter::PrintInt32(v), " # x", + strings::Hex(v)); } - virtual string PrintMessageStart(const Message& message, - int field_index, - int field_count, - bool single_line_mode) const { + virtual std::string PrintMessageStart(const Message& message, int field_index, + int field_count, + bool single_line_mode) const { if (single_line_mode) { return " { "; } - return StrCat( - " { # ", message.GetDescriptor()->name(), ": ", field_index, "\n"); + return StrCat(" { # ", message.GetDescriptor()->name(), ": ", + field_index, "\n"); } }; @@ -513,7 +551,7 @@ TEST_F(TextFormatTest, CustomPrinterForComments) { TextFormat::Printer printer; CustomMessageFieldValuePrinter my_field_printer; printer.SetDefaultFieldValuePrinter(new CustomMessageFieldValuePrinter()); - string text; + std::string text; printer.PrintToString(message, &text); EXPECT_EQ( "optional_nested_message { # NestedMessage: -1\n" @@ -534,12 +572,59 @@ TEST_F(TextFormatTest, CustomPrinterForComments) { text); } +class CustomMessageContentFieldValuePrinter + : public TextFormat::FastFieldValuePrinter { + public: + bool PrintMessageContent( + const Message& message, int field_index, int field_count, + bool single_line_mode, + TextFormat::BaseTextGenerator* generator) const override { + if (message.ByteSizeLong() > 0) { + generator->PrintString( + strings::Substitute("# REDACTED, $0 bytes\n", message.ByteSizeLong())); + } + return true; + } +}; + +TEST_F(TextFormatTest, CustomPrinterForMessageContent) { + protobuf_unittest::TestAllTypes message; + message.mutable_optional_nested_message(); + message.mutable_optional_import_message()->set_d(42); + message.add_repeated_nested_message(); + message.add_repeated_nested_message(); + message.add_repeated_import_message()->set_d(43); + message.add_repeated_import_message()->set_d(44); + TextFormat::Printer printer; + CustomMessageContentFieldValuePrinter my_field_printer; + printer.SetDefaultFieldValuePrinter( + new CustomMessageContentFieldValuePrinter()); + std::string text; + printer.PrintToString(message, &text); + EXPECT_EQ( + "optional_nested_message {\n" + "}\n" + "optional_import_message {\n" + " # REDACTED, 2 bytes\n" + "}\n" + "repeated_nested_message {\n" + "}\n" + "repeated_nested_message {\n" + "}\n" + "repeated_import_message {\n" + " # REDACTED, 2 bytes\n" + "}\n" + "repeated_import_message {\n" + " # REDACTED, 2 bytes\n" + "}\n", + text); +} + class CustomMultilineCommentPrinter : public TextFormat::FieldValuePrinter { public: - virtual string PrintMessageStart(const Message& message, - int field_index, - int field_count, - bool single_line_comment) const { + virtual std::string PrintMessageStart(const Message& message, int field_index, + int field_count, + bool single_line_comment) const { return StrCat(" { # 1\n", " # 2\n"); } }; @@ -551,7 +636,7 @@ TEST_F(TextFormatTest, CustomPrinterForMultilineComments) { TextFormat::Printer printer; CustomMessageFieldValuePrinter my_field_printer; printer.SetDefaultFieldValuePrinter(new CustomMultilineCommentPrinter()); - string text; + std::string text; printer.PrintToString(message, &text); EXPECT_EQ( "optional_nested_message { # 1\n" @@ -564,6 +649,148 @@ TEST_F(TextFormatTest, CustomPrinterForMultilineComments) { text); } +// Achieve effects similar to SetUseShortRepeatedPrimitives for messages, using +// RegisterFieldValuePrinter. Use this to test the version of PrintFieldName +// that accepts repeated field index and count. +class CompactRepeatedFieldPrinter : public TextFormat::FastFieldValuePrinter { + public: + void PrintFieldName(const Message& message, int field_index, int field_count, + const Reflection* reflection, + const FieldDescriptor* field, + TextFormat::BaseTextGenerator* generator) const override { + if (field_index == 0 || field_index == -1) { + generator->PrintString(field->name()); + } + } + // To prevent compiler complaining about Woverloaded-virtual + void PrintFieldName(const Message& message, const Reflection* reflection, + const FieldDescriptor* field, + TextFormat::BaseTextGenerator* generator) const override { + } + void PrintMessageStart( + const Message& message, int field_index, int field_count, + bool single_line_mode, + TextFormat::BaseTextGenerator* generator) const override { + if (field_index == 0 || field_index == -1) { + if (single_line_mode) { + generator->PrintLiteral(" { "); + } else { + generator->PrintLiteral(" {\n"); + } + } + } + void PrintMessageEnd( + const Message& message, int field_index, int field_count, + bool single_line_mode, + TextFormat::BaseTextGenerator* generator) const override { + if (field_index == field_count - 1 || field_index == -1) { + if (single_line_mode) { + generator->PrintLiteral("} "); + } else { + generator->PrintLiteral("}\n"); + } + } + } +}; + +TEST_F(TextFormatTest, CompactRepeatedFieldPrinter) { + TextFormat::Printer printer; + ASSERT_TRUE(printer.RegisterFieldValuePrinter( + unittest::TestAllTypes::default_instance() + .descriptor() + ->FindFieldByNumber( + unittest::TestAllTypes::kRepeatedNestedMessageFieldNumber), + new CompactRepeatedFieldPrinter)); + + protobuf_unittest::TestAllTypes message; + message.add_repeated_nested_message()->set_bb(1); + message.add_repeated_nested_message()->set_bb(2); + message.add_repeated_nested_message()->set_bb(3); + + std::string text; + ASSERT_TRUE(printer.PrintToString(message, &text)); + EXPECT_EQ( + "repeated_nested_message {\n" + " bb: 1\n" + " bb: 2\n" + " bb: 3\n" + "}\n", + text); +} + +// Print strings into multiple line, with indentation. Use this to test +// BaseTextGenerator::Indent and BaseTextGenerator::Outdent. +class MultilineStringPrinter : public TextFormat::FastFieldValuePrinter { + public: + void PrintString(const std::string& val, + TextFormat::BaseTextGenerator* generator) const override { + generator->Indent(); + int last_pos = 0; + int newline_pos = val.find('\n'); + while (newline_pos != std::string::npos) { + generator->PrintLiteral("\n"); + TextFormat::FastFieldValuePrinter::PrintString( + val.substr(last_pos, newline_pos + 1 - last_pos), generator); + last_pos = newline_pos + 1; + newline_pos = val.find('\n', last_pos); + } + if (last_pos < val.size()) { + generator->PrintLiteral("\n"); + TextFormat::FastFieldValuePrinter::PrintString(val.substr(last_pos), + generator); + } + generator->Outdent(); + } +}; + +TEST_F(TextFormatTest, MultilineStringPrinter) { + TextFormat::Printer printer; + ASSERT_TRUE(printer.RegisterFieldValuePrinter( + unittest::TestAllTypes::default_instance() + .descriptor() + ->FindFieldByNumber( + unittest::TestAllTypes::kOptionalStringFieldNumber), + new MultilineStringPrinter)); + + protobuf_unittest::TestAllTypes message; + message.set_optional_string("first line\nsecond line\nthird line"); + + std::string text; + ASSERT_TRUE(printer.PrintToString(message, &text)); + EXPECT_EQ( + "optional_string: \n" + " \"first line\\n\"\n" + " \"second line\\n\"\n" + " \"third line\"\n", + text); +} + +class CustomNestedMessagePrinter : public TextFormat::MessagePrinter { + public: + CustomNestedMessagePrinter() {} + ~CustomNestedMessagePrinter() override {} + void Print(const Message& message, bool single_line_mode, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintLiteral("custom"); + } +}; + +TEST_F(TextFormatTest, CustomMessagePrinter) { + TextFormat::Printer printer; + printer.RegisterMessagePrinter( + unittest::TestAllTypes::NestedMessage::default_instance().descriptor(), + new CustomNestedMessagePrinter); + + unittest::TestAllTypes message; + std::string text; + EXPECT_TRUE(printer.PrintToString(message, &text)); + EXPECT_EQ("", text); + + message.mutable_optional_nested_message()->set_bb(1); + EXPECT_TRUE(printer.PrintToString(message, &text)); + EXPECT_EQ("optional_nested_message {\n custom}\n", text); +} + TEST_F(TextFormatTest, ParseBasic) { io::ArrayInputStream input_stream(proto_debug_string_.data(), proto_debug_string_.size()); @@ -580,8 +807,8 @@ TEST_F(TextFormatExtensionsTest, ParseExtensions) { TEST_F(TextFormatTest, ParseEnumFieldFromNumber) { // Create a parse string with a numerical value for an enum field. - string parse_string = strings::Substitute("optional_nested_enum: $0", - unittest::TestAllTypes::BAZ); + std::string parse_string = + strings::Substitute("optional_nested_enum: $0", unittest::TestAllTypes::BAZ); EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto_)); EXPECT_TRUE(proto_.has_optional_nested_enum()); EXPECT_EQ(unittest::TestAllTypes::BAZ, proto_.optional_nested_enum()); @@ -589,22 +816,52 @@ TEST_F(TextFormatTest, ParseEnumFieldFromNumber) { TEST_F(TextFormatTest, ParseEnumFieldFromNegativeNumber) { ASSERT_LT(unittest::SPARSE_E, 0); - string parse_string = strings::Substitute("sparse_enum: $0", - unittest::SPARSE_E); + std::string parse_string = + strings::Substitute("sparse_enum: $0", unittest::SPARSE_E); unittest::SparseEnumMessage proto; EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto)); EXPECT_TRUE(proto.has_sparse_enum()); EXPECT_EQ(unittest::SPARSE_E, proto.sparse_enum()); } +TEST_F(TextFormatTest, PrintUnknownEnumFieldProto3) { + proto3_unittest::TestAllTypes proto; + + proto.add_repeated_nested_enum( + static_cast(10)); + proto.add_repeated_nested_enum( + static_cast(-10)); + proto.add_repeated_nested_enum( + static_cast(2147483647)); + proto.add_repeated_nested_enum( + static_cast(-2147483648)); + + EXPECT_EQ( + "repeated_nested_enum: 10\n" + "repeated_nested_enum: -10\n" + "repeated_nested_enum: 2147483647\n" + "repeated_nested_enum: -2147483648\n", + proto.DebugString()); +} + +TEST_F(TextFormatTest, ParseUnknownEnumFieldProto3) { + proto3_unittest::TestAllTypes proto; + std::string parse_string = + "repeated_nested_enum: [10, -10, 2147483647, -2147483648]"; + EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto)); + ASSERT_EQ(4, proto.repeated_nested_enum_size()); + EXPECT_EQ(10, proto.repeated_nested_enum(0)); + EXPECT_EQ(-10, proto.repeated_nested_enum(1)); + EXPECT_EQ(2147483647, proto.repeated_nested_enum(2)); + EXPECT_EQ(-2147483648, proto.repeated_nested_enum(3)); +} + TEST_F(TextFormatTest, ParseStringEscape) { - // Create a parse string with escpaed characters in it. - string parse_string = "optional_string: " - + kEscapeTestStringEscaped - + "\n"; + // Create a parse string with escaped characters in it. + std::string parse_string = + "optional_string: " + kEscapeTestStringEscaped + "\n"; - io::ArrayInputStream input_stream(parse_string.data(), - parse_string.size()); + io::ArrayInputStream input_stream(parse_string.data(), parse_string.size()); TextFormat::Parse(&input_stream, &proto_); // Compare. @@ -613,21 +870,20 @@ TEST_F(TextFormatTest, ParseStringEscape) { TEST_F(TextFormatTest, ParseConcatenatedString) { // Create a parse string with multiple parts on one line. - string parse_string = "optional_string: \"foo\" \"bar\"\n"; + std::string parse_string = "optional_string: \"foo\" \"bar\"\n"; - io::ArrayInputStream input_stream1(parse_string.data(), - parse_string.size()); + io::ArrayInputStream input_stream1(parse_string.data(), parse_string.size()); TextFormat::Parse(&input_stream1, &proto_); // Compare. EXPECT_EQ("foobar", proto_.optional_string()); // Create a parse string with multiple parts on separate lines. - parse_string = "optional_string: \"foo\"\n" - "\"bar\"\n"; + parse_string = + "optional_string: \"foo\"\n" + "\"bar\"\n"; - io::ArrayInputStream input_stream2(parse_string.data(), - parse_string.size()); + io::ArrayInputStream input_stream2(parse_string.data(), parse_string.size()); TextFormat::Parse(&input_stream2, &proto_); // Compare. @@ -639,10 +895,9 @@ TEST_F(TextFormatTest, ParseFloatWithSuffix) { // end. This is needed for backwards-compatibility with proto1. // Have it parse a float with the 'f' suffix. - string parse_string = "optional_float: 1.0f\n"; + std::string parse_string = "optional_float: 1.0f\n"; - io::ArrayInputStream input_stream(parse_string.data(), - parse_string.size()); + io::ArrayInputStream input_stream(parse_string.data(), parse_string.size()); TextFormat::Parse(&input_stream, &proto_); @@ -651,7 +906,7 @@ TEST_F(TextFormatTest, ParseFloatWithSuffix) { } TEST_F(TextFormatTest, ParseShortRepeatedForm) { - string parse_string = + std::string parse_string = // Mixed short-form and long-form are simply concatenated. "repeated_int32: 1\n" "repeated_int32: [456, 789]\n" @@ -691,7 +946,7 @@ TEST_F(TextFormatTest, ParseShortRepeatedForm) { } TEST_F(TextFormatTest, ParseShortRepeatedWithTrailingComma) { - string parse_string = "repeated_int32: [456,]\n"; + std::string parse_string = "repeated_int32: [456,]\n"; ASSERT_FALSE(TextFormat::ParseFromString(parse_string, &proto_)); parse_string = "repeated_nested_enum: [ FOO , ]"; ASSERT_FALSE(TextFormat::ParseFromString(parse_string, &proto_)); @@ -703,7 +958,7 @@ TEST_F(TextFormatTest, ParseShortRepeatedWithTrailingComma) { } TEST_F(TextFormatTest, ParseShortRepeatedEmpty) { - string parse_string = + std::string parse_string = "repeated_int32: []\n" "repeated_nested_enum: []\n" "repeated_string: []\n" @@ -720,7 +975,7 @@ TEST_F(TextFormatTest, ParseShortRepeatedEmpty) { } TEST_F(TextFormatTest, ParseShortRepeatedConcatenatedWithEmpty) { - string parse_string = + std::string parse_string = // Starting with empty [] should have no impact. "repeated_int32: []\n" "repeated_nested_enum: []\n" @@ -775,11 +1030,11 @@ TEST_F(TextFormatTest, ParseShortRepeatedConcatenatedWithEmpty) { TEST_F(TextFormatTest, Comments) { // Test that comments are ignored. - string parse_string = "optional_int32: 1 # a comment\n" - "optional_int64: 2 # another comment"; + std::string parse_string = + "optional_int32: 1 # a comment\n" + "optional_int64: 2 # another comment"; - io::ArrayInputStream input_stream(parse_string.data(), - parse_string.size()); + io::ArrayInputStream input_stream(parse_string.data(), parse_string.size()); TextFormat::Parse(&input_stream, &proto_); @@ -792,10 +1047,9 @@ TEST_F(TextFormatTest, OptionalColon) { // Test that we can place a ':' after the field name of a nested message, // even though we don't have to. - string parse_string = "optional_nested_message: { bb: 1}\n"; + std::string parse_string = "optional_nested_message: { bb: 1}\n"; - io::ArrayInputStream input_stream(parse_string.data(), - parse_string.size()); + io::ArrayInputStream input_stream(parse_string.data(), parse_string.size()); TextFormat::Parse(&input_stream, &proto_); @@ -806,7 +1060,7 @@ TEST_F(TextFormatTest, OptionalColon) { // Some platforms (e.g. Windows) insist on padding the exponent to three // digits when one or two would be just fine. -static string RemoveRedundantZeros(string text) { +static std::string RemoveRedundantZeros(std::string text) { text = StringReplace(text, "e+0", "e+", true); text = StringReplace(text, "e-0", "e-", true); return text; @@ -820,15 +1074,18 @@ TEST_F(TextFormatTest, PrintExotic) { // 9223372036854775808 is outside the range of int64. However, it is not // outside the range of uint64. Confusingly, this means that everything // works if we make the literal unsigned, even though we are negating it. - message.add_repeated_int64(-GOOGLE_ULONGLONG(9223372036854775808)); - message.add_repeated_uint64(GOOGLE_ULONGLONG(18446744073709551615)); + message.add_repeated_int64(-PROTOBUF_ULONGLONG(9223372036854775808)); + message.add_repeated_uint64(PROTOBUF_ULONGLONG(18446744073709551615)); message.add_repeated_double(123.456); message.add_repeated_double(1.23e21); message.add_repeated_double(1.23e-18); message.add_repeated_double(std::numeric_limits::infinity()); message.add_repeated_double(-std::numeric_limits::infinity()); message.add_repeated_double(std::numeric_limits::quiet_NaN()); - message.add_repeated_string(string("\000\001\a\b\f\n\r\t\v\\\'\"", 12)); + message.add_repeated_double(-std::numeric_limits::quiet_NaN()); + message.add_repeated_double(std::numeric_limits::signaling_NaN()); + message.add_repeated_double(-std::numeric_limits::signaling_NaN()); + message.add_repeated_string(std::string("\000\001\a\b\f\n\r\t\v\\\'\"", 12)); // Fun story: We used to use 1.23e22 instead of 1.23e21 above, but this // seemed to trigger an odd case on MinGW/GCC 3.4.5 where GCC's parsing of @@ -842,21 +1099,26 @@ TEST_F(TextFormatTest, PrintExotic) { // have this problem, so we switched to that instead. EXPECT_EQ( - "repeated_int64: -9223372036854775808\n" - "repeated_uint64: 18446744073709551615\n" - "repeated_double: 123.456\n" - "repeated_double: 1.23e+21\n" - "repeated_double: 1.23e-18\n" - "repeated_double: inf\n" - "repeated_double: -inf\n" - "repeated_double: nan\n" - "repeated_string: \"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\'\\\"\"\n", - RemoveRedundantZeros(message.DebugString())); + "repeated_int64: -9223372036854775808\n" + "repeated_uint64: 18446744073709551615\n" + "repeated_double: 123.456\n" + "repeated_double: 1.23e+21\n" + "repeated_double: 1.23e-18\n" + "repeated_double: inf\n" + "repeated_double: -inf\n" + "repeated_double: nan\n" + "repeated_double: nan\n" + "repeated_double: nan\n" + "repeated_double: nan\n" + "repeated_string: " + "\"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\'\\\"\"\n", + RemoveRedundantZeros(message.DebugString())); } TEST_F(TextFormatTest, PrintFloatPrecision) { unittest::TestAllTypes message; + message.add_repeated_float(1.0); message.add_repeated_float(1.2); message.add_repeated_float(1.23); message.add_repeated_float(1.234); @@ -897,48 +1159,48 @@ TEST_F(TextFormatTest, PrintFloatPrecision) { message.add_repeated_double(1.23456789876543e100); EXPECT_EQ( - "repeated_float: 1.2\n" - "repeated_float: 1.23\n" - "repeated_float: 1.234\n" - "repeated_float: 1.2345\n" - "repeated_float: 1.23456\n" - "repeated_float: 1.2e+10\n" - "repeated_float: 1.23e+10\n" - "repeated_float: 1.234e+10\n" - "repeated_float: 1.2345e+10\n" - "repeated_float: 1.23456e+10\n" - "repeated_double: 1.2\n" - "repeated_double: 1.23\n" - "repeated_double: 1.234\n" - "repeated_double: 1.2345\n" - "repeated_double: 1.23456\n" - "repeated_double: 1.234567\n" - "repeated_double: 1.2345678\n" - "repeated_double: 1.23456789\n" - "repeated_double: 1.234567898\n" - "repeated_double: 1.2345678987\n" - "repeated_double: 1.23456789876\n" - "repeated_double: 1.234567898765\n" - "repeated_double: 1.2345678987654\n" - "repeated_double: 1.23456789876543\n" - "repeated_double: 1.2e+100\n" - "repeated_double: 1.23e+100\n" - "repeated_double: 1.234e+100\n" - "repeated_double: 1.2345e+100\n" - "repeated_double: 1.23456e+100\n" - "repeated_double: 1.234567e+100\n" - "repeated_double: 1.2345678e+100\n" - "repeated_double: 1.23456789e+100\n" - "repeated_double: 1.234567898e+100\n" - "repeated_double: 1.2345678987e+100\n" - "repeated_double: 1.23456789876e+100\n" - "repeated_double: 1.234567898765e+100\n" - "repeated_double: 1.2345678987654e+100\n" - "repeated_double: 1.23456789876543e+100\n", - RemoveRedundantZeros(message.DebugString())); + "repeated_float: 1\n" + "repeated_float: 1.2\n" + "repeated_float: 1.23\n" + "repeated_float: 1.234\n" + "repeated_float: 1.2345\n" + "repeated_float: 1.23456\n" + "repeated_float: 1.2e+10\n" + "repeated_float: 1.23e+10\n" + "repeated_float: 1.234e+10\n" + "repeated_float: 1.2345e+10\n" + "repeated_float: 1.23456e+10\n" + "repeated_double: 1.2\n" + "repeated_double: 1.23\n" + "repeated_double: 1.234\n" + "repeated_double: 1.2345\n" + "repeated_double: 1.23456\n" + "repeated_double: 1.234567\n" + "repeated_double: 1.2345678\n" + "repeated_double: 1.23456789\n" + "repeated_double: 1.234567898\n" + "repeated_double: 1.2345678987\n" + "repeated_double: 1.23456789876\n" + "repeated_double: 1.234567898765\n" + "repeated_double: 1.2345678987654\n" + "repeated_double: 1.23456789876543\n" + "repeated_double: 1.2e+100\n" + "repeated_double: 1.23e+100\n" + "repeated_double: 1.234e+100\n" + "repeated_double: 1.2345e+100\n" + "repeated_double: 1.23456e+100\n" + "repeated_double: 1.234567e+100\n" + "repeated_double: 1.2345678e+100\n" + "repeated_double: 1.23456789e+100\n" + "repeated_double: 1.234567898e+100\n" + "repeated_double: 1.2345678987e+100\n" + "repeated_double: 1.23456789876e+100\n" + "repeated_double: 1.234567898765e+100\n" + "repeated_double: 1.2345678987654e+100\n" + "repeated_double: 1.23456789876543e+100\n", + RemoveRedundantZeros(message.DebugString())); } - TEST_F(TextFormatTest, AllowPartial) { unittest::TestRequired message; TextFormat::Parser parser; @@ -952,29 +1214,29 @@ TEST_F(TextFormatTest, AllowPartial) { TEST_F(TextFormatTest, ParseExotic) { unittest::TestAllTypes message; ASSERT_TRUE(TextFormat::ParseFromString( - "repeated_int32: -1\n" - "repeated_int32: -2147483648\n" - "repeated_int64: -1\n" - "repeated_int64: -9223372036854775808\n" - "repeated_uint32: 4294967295\n" - "repeated_uint32: 2147483648\n" - "repeated_uint64: 18446744073709551615\n" - "repeated_uint64: 9223372036854775808\n" - "repeated_double: 123.0\n" - "repeated_double: 123.5\n" - "repeated_double: 0.125\n" - "repeated_double: 1.23E17\n" - "repeated_double: 1.235E+22\n" - "repeated_double: 1.235e-18\n" - "repeated_double: 123.456789\n" - "repeated_double: inf\n" - "repeated_double: Infinity\n" - "repeated_double: -inf\n" - "repeated_double: -Infinity\n" - "repeated_double: nan\n" - "repeated_double: NaN\n" - "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\"\n", - &message)); + "repeated_int32: -1\n" + "repeated_int32: -2147483648\n" + "repeated_int64: -1\n" + "repeated_int64: -9223372036854775808\n" + "repeated_uint32: 4294967295\n" + "repeated_uint32: 2147483648\n" + "repeated_uint64: 18446744073709551615\n" + "repeated_uint64: 9223372036854775808\n" + "repeated_double: 123.0\n" + "repeated_double: 123.5\n" + "repeated_double: 0.125\n" + "repeated_double: 1.23E17\n" + "repeated_double: 1.235E+22\n" + "repeated_double: 1.235e-18\n" + "repeated_double: 123.456789\n" + "repeated_double: inf\n" + "repeated_double: Infinity\n" + "repeated_double: -inf\n" + "repeated_double: -Infinity\n" + "repeated_double: nan\n" + "repeated_double: NaN\n" + "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\"\n", + &message)); ASSERT_EQ(2, message.repeated_int32_size()); EXPECT_EQ(-1, message.repeated_int32(0)); @@ -992,23 +1254,26 @@ TEST_F(TextFormatTest, ParseExotic) { // 9223372036854775808 is outside the range of int64. However, it is not // outside the range of uint64. Confusingly, this means that everything // works if we make the literal unsigned, even though we are negating it. - EXPECT_EQ(-GOOGLE_ULONGLONG(9223372036854775808), message.repeated_int64(1)); + EXPECT_EQ(-PROTOBUF_ULONGLONG(9223372036854775808), + message.repeated_int64(1)); ASSERT_EQ(2, message.repeated_uint32_size()); EXPECT_EQ(4294967295u, message.repeated_uint32(0)); EXPECT_EQ(2147483648u, message.repeated_uint32(1)); ASSERT_EQ(2, message.repeated_uint64_size()); - EXPECT_EQ(GOOGLE_ULONGLONG(18446744073709551615), message.repeated_uint64(0)); - EXPECT_EQ(GOOGLE_ULONGLONG(9223372036854775808), message.repeated_uint64(1)); + EXPECT_EQ(PROTOBUF_ULONGLONG(18446744073709551615), + message.repeated_uint64(0)); + EXPECT_EQ(PROTOBUF_ULONGLONG(9223372036854775808), + message.repeated_uint64(1)); ASSERT_EQ(13, message.repeated_double_size()); - EXPECT_EQ(123.0 , message.repeated_double(0)); - EXPECT_EQ(123.5 , message.repeated_double(1)); - EXPECT_EQ(0.125 , message.repeated_double(2)); - EXPECT_EQ(1.23E17 , message.repeated_double(3)); - EXPECT_EQ(1.235E22 , message.repeated_double(4)); - EXPECT_EQ(1.235E-18 , message.repeated_double(5)); + EXPECT_EQ(123.0, message.repeated_double(0)); + EXPECT_EQ(123.5, message.repeated_double(1)); + EXPECT_EQ(0.125, message.repeated_double(2)); + EXPECT_EQ(1.23E17, message.repeated_double(3)); + EXPECT_EQ(1.235E22, message.repeated_double(4)); + EXPECT_EQ(1.235E-18, message.repeated_double(5)); EXPECT_EQ(123.456789, message.repeated_double(6)); EXPECT_EQ(message.repeated_double(7), std::numeric_limits::infinity()); @@ -1018,76 +1283,152 @@ TEST_F(TextFormatTest, ParseExotic) { -std::numeric_limits::infinity()); EXPECT_EQ(message.repeated_double(10), -std::numeric_limits::infinity()); - EXPECT_TRUE(MathLimits::IsNaN(message.repeated_double(11))); - EXPECT_TRUE(MathLimits::IsNaN(message.repeated_double(12))); + EXPECT_TRUE(std::isnan(message.repeated_double(11))); + EXPECT_TRUE(std::isnan(message.repeated_double(12))); // Note: Since these string literals have \0's in them, we must explicitly - // pass their sizes to string's constructor. + // pass their sizes to string's constructor. ASSERT_EQ(1, message.repeated_string_size()); - EXPECT_EQ(string("\000\001\a\b\f\n\r\t\v\\\'\"", 12), + EXPECT_EQ(std::string("\000\001\a\b\f\n\r\t\v\\\'\"", 12), message.repeated_string(0)); + + ASSERT_TRUE( + TextFormat::ParseFromString("repeated_float: 3.4028235e+38\n" + "repeated_float: -3.4028235e+38\n" + "repeated_float: 3.402823567797337e+38\n" + "repeated_float: -3.402823567797337e+38\n", + &message)); + EXPECT_EQ(message.repeated_float(0), std::numeric_limits::max()); + EXPECT_EQ(message.repeated_float(1), -std::numeric_limits::max()); + EXPECT_EQ(message.repeated_float(2), std::numeric_limits::infinity()); + EXPECT_EQ(message.repeated_float(3), -std::numeric_limits::infinity()); + } TEST_F(TextFormatTest, PrintFieldsInIndexOrder) { protobuf_unittest::TestFieldOrderings message; // Fields are listed in index order instead of field number. - message.set_my_string("Test String"); // Field number 11 - message.set_my_int(12345); // Field number 1 - message.set_my_float(0.999); // Field number 101 + message.set_my_string("str"); // Field number 11 + message.set_my_int(12345); // Field number 1 + message.set_my_float(0.999); // Field number 101 + // Extensions are listed based on the order of extension number. + // Extension number 12. + message + .MutableExtension( + protobuf_unittest::TestExtensionOrderings2::test_ext_orderings2) + ->set_my_string("ext_str2"); + // Extension number 13. + message + .MutableExtension( + protobuf_unittest::TestExtensionOrderings1::test_ext_orderings1) + ->set_my_string("ext_str1"); + // Extension number 14. + message + .MutableExtension(protobuf_unittest::TestExtensionOrderings2:: + TestExtensionOrderings3::test_ext_orderings3) + ->set_my_string("ext_str3"); + // Extension number 50. + *message.MutableExtension(protobuf_unittest::my_extension_string) = "ext_str0"; + TextFormat::Printer printer; - string text; + std::string text; // By default, print in field number order. + // my_int: 12345 + // my_string: "str" + // [protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] { + // my_string: "ext_str2" + // } + // [protobuf_unittest.TestExtensionOrderings1.test_ext_orderings1] { + // my_string: "ext_str1" + // } + // [protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3.test_ext_orderings3] + // { + // my_string: "ext_str3" + // } + // [protobuf_unittest.my_extension_string]: "ext_str0" + // my_float: 0.999 printer.PrintToString(message, &text); - EXPECT_EQ("my_int: 12345\nmy_string: \"Test String\"\nmy_float: 0.999\n", - text); + EXPECT_EQ( + "my_int: 12345\nmy_string: " + "\"str\"\n[protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] " + "{\n my_string: " + "\"ext_str2\"\n}\n[protobuf_unittest.TestExtensionOrderings1.test_ext_" + "orderings1] {\n my_string: " + "\"ext_str1\"\n}\n[protobuf_unittest.TestExtensionOrderings2." + "TestExtensionOrderings3.test_ext_orderings3] {\n my_string: " + "\"ext_str3\"\n}\n[protobuf_unittest.my_extension_string]: " + "\"ext_str0\"\nmy_float: 0.999\n", + text); // Print in index order. + // my_string: "str" + // my_int: 12345 + // my_float: 0.999 + // [protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] { + // my_string: "ext_str2" + // } + // [protobuf_unittest.TestExtensionOrderings1.test_ext_orderings1] { + // my_string: "ext_str1" + // } + // [protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3.test_ext_orderings3] + // { + // my_string: "ext_str3" + // } + // [protobuf_unittest.my_extension_string]: "ext_str0" printer.SetPrintMessageFieldsInIndexOrder(true); printer.PrintToString(message, &text); - EXPECT_EQ("my_string: \"Test String\"\nmy_int: 12345\nmy_float: 0.999\n", - text); + EXPECT_EQ( + "my_string: \"str\"\nmy_int: 12345\nmy_float: " + "0.999\n[protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] " + "{\n my_string: " + "\"ext_str2\"\n}\n[protobuf_unittest.TestExtensionOrderings1.test_ext_" + "orderings1] {\n my_string: " + "\"ext_str1\"\n}\n[protobuf_unittest.TestExtensionOrderings2." + "TestExtensionOrderings3.test_ext_orderings3] {\n my_string: " + "\"ext_str3\"\n}\n[protobuf_unittest.my_extension_string]: \"ext_str0\"\n", + text); } class TextFormatParserTest : public testing::Test { protected: - void ExpectFailure(const string& input, const string& message, int line, - int col) { - google::protobuf::scoped_ptr proto(new unittest::TestAllTypes); + void ExpectFailure(const std::string& input, const std::string& message, + int line, int col) { + std::unique_ptr proto(new unittest::TestAllTypes); ExpectFailure(input, message, line, col, proto.get()); } - void ExpectFailure(const string& input, const string& message, int line, - int col, Message* proto) { + void ExpectFailure(const std::string& input, const std::string& message, + int line, int col, Message* proto) { ExpectMessage(input, message, line, col, proto, false); } - void ExpectMessage(const string& input, const string& message, int line, - int col, Message* proto, bool expected_result) { - TextFormat::Parser parser; + void ExpectMessage(const std::string& input, const std::string& message, + int line, int col, Message* proto, bool expected_result) { MockErrorCollector error_collector; - parser.RecordErrorsTo(&error_collector); - EXPECT_EQ(expected_result, parser.ParseFromString(input, proto)) + parser_.RecordErrorsTo(&error_collector); + EXPECT_EQ(expected_result, parser_.ParseFromString(input, proto)) << input << " -> " << proto->DebugString(); - EXPECT_EQ(SimpleItoa(line) + ":" + SimpleItoa(col) + ": " + message + "\n", + EXPECT_EQ(StrCat(line, ":", col, ": ", message, "\n"), error_collector.text_); + parser_.RecordErrorsTo(nullptr); } - void ExpectSuccessAndTree(const string& input, Message* proto, + void ExpectSuccessAndTree(const std::string& input, Message* proto, TextFormat::ParseInfoTree* info_tree) { - TextFormat::Parser parser; MockErrorCollector error_collector; - parser.RecordErrorsTo(&error_collector); - parser.WriteLocationsTo(info_tree); - - EXPECT_TRUE(parser.ParseFromString(input, proto)); + parser_.RecordErrorsTo(&error_collector); + parser_.WriteLocationsTo(info_tree); + EXPECT_TRUE(parser_.ParseFromString(input, proto)); + parser_.WriteLocationsTo(nullptr); + parser_.RecordErrorsTo(nullptr); } - void ExpectLocation(TextFormat::ParseInfoTree* tree, - const Descriptor* d, const string& field_name, - int index, int line, int column) { - TextFormat::ParseLocation location = tree->GetLocation( - d->FindFieldByName(field_name), index); + void ExpectLocation(TextFormat::ParseInfoTree* tree, const Descriptor* d, + const std::string& field_name, int index, int line, + int column) { + TextFormat::ParseLocation location = + tree->GetLocation(d->FindFieldByName(field_name), index); EXPECT_EQ(line, location.line); EXPECT_EQ(column, location.column); } @@ -1099,25 +1440,27 @@ class TextFormatParserTest : public testing::Test { MockErrorCollector() {} ~MockErrorCollector() {} - string text_; + std::string text_; // implements ErrorCollector ------------------------------------- - void AddError(int line, int column, const string& message) { - strings::SubstituteAndAppend(&text_, "$0:$1: $2\n", - line + 1, column + 1, message); + void AddError(int line, int column, const std::string& message) { + strings::SubstituteAndAppend(&text_, "$0:$1: $2\n", line + 1, column + 1, + message); } - void AddWarning(int line, int column, const string& message) { + void AddWarning(int line, int column, const std::string& message) { AddError(line, column, "WARNING:" + message); } }; + + TextFormat::Parser parser_; }; TEST_F(TextFormatParserTest, ParseInfoTreeBuilding) { - google::protobuf::scoped_ptr message(new unittest::TestAllTypes); + std::unique_ptr message(new unittest::TestAllTypes); const Descriptor* d = message->GetDescriptor(); - string stringData = + std::string stringData = "optional_int32: 1\n" "optional_int64: 2\n" " optional_double: 2.4\n" @@ -1133,7 +1476,6 @@ TEST_F(TextFormatParserTest, ParseInfoTreeBuilding) { " bb: 80\n" ">"; - TextFormat::ParseInfoTree tree; ExpectSuccessAndTree(stringData, message.get(), &tree); @@ -1179,36 +1521,36 @@ TEST_F(TextFormatParserTest, ParseInfoTreeBuilding) { } TEST_F(TextFormatParserTest, ParseFieldValueFromString) { - google::protobuf::scoped_ptr message(new unittest::TestAllTypes); + std::unique_ptr message(new unittest::TestAllTypes); const Descriptor* d = message->GetDescriptor(); -#define EXPECT_FIELD(name, value, valuestring) \ - EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ - valuestring, d->FindFieldByName("optional_" #name), message.get())); \ - EXPECT_EQ(value, message->optional_##name()); \ +#define EXPECT_FIELD(name, value, valuestring) \ + EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ + valuestring, d->FindFieldByName("optional_" #name), message.get())); \ + EXPECT_EQ(value, message->optional_##name()); \ EXPECT_TRUE(message->has_optional_##name()); -#define EXPECT_BOOL_FIELD(name, value, valuestring) \ - EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ - valuestring, d->FindFieldByName("optional_" #name), message.get())); \ - EXPECT_TRUE(message->optional_##name() == value); \ +#define EXPECT_BOOL_FIELD(name, value, valuestring) \ + EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ + valuestring, d->FindFieldByName("optional_" #name), message.get())); \ + EXPECT_TRUE(message->optional_##name() == value); \ EXPECT_TRUE(message->has_optional_##name()); -#define EXPECT_FLOAT_FIELD(name, value, valuestring) \ - EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ - valuestring, d->FindFieldByName("optional_" #name), message.get())); \ - EXPECT_FLOAT_EQ(value, message->optional_##name()); \ +#define EXPECT_FLOAT_FIELD(name, value, valuestring) \ + EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ + valuestring, d->FindFieldByName("optional_" #name), message.get())); \ + EXPECT_FLOAT_EQ(value, message->optional_##name()); \ EXPECT_TRUE(message->has_optional_##name()); -#define EXPECT_DOUBLE_FIELD(name, value, valuestring) \ - EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ - valuestring, d->FindFieldByName("optional_" #name), message.get())); \ - EXPECT_DOUBLE_EQ(value, message->optional_##name()); \ +#define EXPECT_DOUBLE_FIELD(name, value, valuestring) \ + EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ + valuestring, d->FindFieldByName("optional_" #name), message.get())); \ + EXPECT_DOUBLE_EQ(value, message->optional_##name()); \ EXPECT_TRUE(message->has_optional_##name()); -#define EXPECT_INVALID(name, valuestring) \ +#define EXPECT_INVALID(name, valuestring) \ EXPECT_FALSE(TextFormat::ParseFieldValueFromString( \ - valuestring, d->FindFieldByName("optional_" #name), message.get())); + valuestring, d->FindFieldByName("optional_" #name), message.get())); // int32 EXPECT_FIELD(int32, 1, "1"); @@ -1293,13 +1635,13 @@ TEST_F(TextFormatParserTest, ParseFieldValueFromString) { // enum EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAR, "BAR"); EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAZ, - SimpleItoa(unittest::TestAllTypes::BAZ)); + StrCat(unittest::TestAllTypes::BAZ)); EXPECT_INVALID(nested_enum, "FOOBAR"); // message EXPECT_TRUE(TextFormat::ParseFieldValueFromString( - "", d->FindFieldByName("optional_nested_message"), message.get())); - EXPECT_EQ(12, message->optional_nested_message().bb()); \ + "", d->FindFieldByName("optional_nested_message"), message.get())); + EXPECT_EQ(12, message->optional_nested_message().bb()); EXPECT_TRUE(message->has_optional_nested_message()); EXPECT_INVALID(nested_message, "any"); @@ -1310,15 +1652,13 @@ TEST_F(TextFormatParserTest, ParseFieldValueFromString) { #undef EXPECT_INVALID } - TEST_F(TextFormatParserTest, InvalidToken) { - ExpectFailure("optional_bool: true\n-5\n", "Expected identifier, got: -", - 2, 1); + ExpectFailure("optional_bool: true\n-5\n", "Expected identifier, got: -", 2, + 1); - ExpectFailure("optional_bool: true!\n", "Expected identifier, got: !", 1, - 20); - ExpectFailure("\"some string\"", - "Expected identifier, got: \"some string\"", 1, 1); + ExpectFailure("optional_bool: true!\n", "Expected identifier, got: !", 1, 20); + ExpectFailure("\"some string\"", "Expected identifier, got: \"some string\"", + 1, 1); } TEST_F(TextFormatParserTest, InvalidFieldName) { @@ -1368,11 +1708,10 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { // Invalid values for a double/float field. ExpectFailure("optional_double: \"hello\"\n", "Expected double, got: \"hello\"", 1, 18); - ExpectFailure("optional_double: true\n", "Expected double, got: true", 1, - 18); + ExpectFailure("optional_double: true\n", "Expected double, got: true", 1, 18); ExpectFailure("optional_double: !\n", "Expected double, got: !", 1, 18); - ExpectFailure("optional_double {\n \n}\n", "Expected \":\", found \"{\".", - 1, 17); + ExpectFailure("optional_double {\n \n}\n", "Expected \":\", found \"{\".", 1, + 17); // Invalid values for a signed integer field. ExpectFailure("optional_int32: \"hello\"\n", @@ -1380,8 +1719,8 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { ExpectFailure("optional_int32: true\n", "Expected integer, got: true", 1, 17); ExpectFailure("optional_int32: 4.5\n", "Expected integer, got: 4.5", 1, 17); ExpectFailure("optional_int32: !\n", "Expected integer, got: !", 1, 17); - ExpectFailure("optional_int32 {\n \n}\n", "Expected \":\", found \"{\".", - 1, 16); + ExpectFailure("optional_int32 {\n \n}\n", "Expected \":\", found \"{\".", 1, + 16); ExpectFailure("optional_int32: 0x80000000\n", "Integer out of range (0x80000000)", 1, 17); ExpectFailure("optional_int64: 0x8000000000000000\n", @@ -1394,13 +1733,13 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { // Invalid values for an unsigned integer field. ExpectFailure("optional_uint64: \"hello\"\n", "Expected integer, got: \"hello\"", 1, 18); - ExpectFailure("optional_uint64: true\n", - "Expected integer, got: true", 1, 18); + ExpectFailure("optional_uint64: true\n", "Expected integer, got: true", 1, + 18); ExpectFailure("optional_uint64: 4.5\n", "Expected integer, got: 4.5", 1, 18); ExpectFailure("optional_uint64: -5\n", "Expected integer, got: -", 1, 18); ExpectFailure("optional_uint64: !\n", "Expected integer, got: !", 1, 18); - ExpectFailure("optional_uint64 {\n \n}\n", "Expected \":\", found \"{\".", - 1, 17); + ExpectFailure("optional_uint64 {\n \n}\n", "Expected \":\", found \"{\".", 1, + 17); ExpectFailure("optional_uint32: 0x100000000\n", "Integer out of range (0x100000000)", 1, 18); ExpectFailure("optional_uint64: 0x10000000000000000\n", @@ -1415,19 +1754,19 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { ExpectFailure( "optional_bool: meh\n", - "Invalid value for boolean field \"optional_bool\". Value: \"meh\".", - 2, 1); + "Invalid value for boolean field \"optional_bool\". Value: \"meh\".", 2, + 1); - ExpectFailure("optional_bool {\n \n}\n", "Expected \":\", found \"{\".", - 1, 15); + ExpectFailure("optional_bool {\n \n}\n", "Expected \":\", found \"{\".", 1, + 15); // Invalid values for a string field. ExpectFailure("optional_string: true\n", "Expected string, got: true", 1, 18); ExpectFailure("optional_string: 5\n", "Expected string, got: 5", 1, 18); ExpectFailure("optional_string: -7.5\n", "Expected string, got: -", 1, 18); ExpectFailure("optional_string: !\n", "Expected string, got: !", 1, 18); - ExpectFailure("optional_string {\n \n}\n", "Expected \":\", found \"{\".", - 1, 17); + ExpectFailure("optional_string {\n \n}\n", "Expected \":\", found \"{\".", 1, + 17); // Invalid values for an enumeration field. ExpectFailure("optional_nested_enum: \"hello\"\n", @@ -1436,7 +1775,8 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { // Valid token, but enum value is not defined. ExpectFailure("optional_nested_enum: 5\n", "Unknown enumeration value of \"5\" for field " - "\"optional_nested_enum\".", 2, 1); + "\"optional_nested_enum\".", + 2, 1); // We consume the negative sign, so the error position starts one character // later. ExpectFailure("optional_nested_enum: -7.5\n", "Expected integer, got: 7.5", 1, @@ -1444,29 +1784,27 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { ExpectFailure("optional_nested_enum: !\n", "Expected integer or identifier, got: !", 1, 23); - ExpectFailure( - "optional_nested_enum: grah\n", - "Unknown enumeration value of \"grah\" for field " - "\"optional_nested_enum\".", 2, 1); + ExpectFailure("optional_nested_enum: grah\n", + "Unknown enumeration value of \"grah\" for field " + "\"optional_nested_enum\".", + 2, 1); - ExpectFailure( - "optional_nested_enum {\n \n}\n", - "Expected \":\", found \"{\".", 1, 22); + ExpectFailure("optional_nested_enum {\n \n}\n", + "Expected \":\", found \"{\".", 1, 22); } TEST_F(TextFormatParserTest, MessageDelimiters) { // Non-matching delimiters. - ExpectFailure("OptionalGroup <\n \n}\n", "Expected \">\", found \"}\".", - 3, 1); + ExpectFailure("OptionalGroup <\n \n}\n", "Expected \">\", found \"}\".", 3, + 1); // Invalid delimiters. - ExpectFailure("OptionalGroup [\n \n]\n", "Expected \"{\", found \"[\".", - 1, 15); + ExpectFailure("OptionalGroup [\n \n]\n", "Expected \"{\", found \"[\".", 1, + 15); // Unending message. ExpectFailure("optional_nested_message {\n \nbb: 118\n", - "Expected identifier, got: ", - 4, 1); + "Expected identifier, got: ", 4, 1); } TEST_F(TextFormatParserTest, UnknownExtension) { @@ -1479,23 +1817,22 @@ TEST_F(TextFormatParserTest, UnknownExtension) { TEST_F(TextFormatParserTest, MissingRequired) { unittest::TestRequired message; - ExpectFailure("a: 1", - "Message missing required fields: b, c", - 0, 1, &message); + ExpectFailure("a: 1", "Message missing required fields: b, c", 0, 1, + &message); } TEST_F(TextFormatParserTest, ParseDuplicateRequired) { unittest::TestRequired message; ExpectFailure("a: 1 b: 2 c: 3 a: 1", - "Non-repeated field \"a\" is specified multiple times.", - 1, 17, &message); + "Non-repeated field \"a\" is specified multiple times.", 1, 17, + &message); } TEST_F(TextFormatParserTest, ParseDuplicateOptional) { unittest::ForeignMessage message; ExpectFailure("c: 1 c: 2", - "Non-repeated field \"c\" is specified multiple times.", - 1, 7, &message); + "Non-repeated field \"c\" is specified multiple times.", 1, 7, + &message); } TEST_F(TextFormatParserTest, MergeDuplicateRequired) { @@ -1521,7 +1858,7 @@ TEST_F(TextFormatParserTest, ExplicitDelimiters) { } TEST_F(TextFormatParserTest, PrintErrorsToStderr) { - std::vector errors; + std::vector errors; { ScopedMemoryLog log; @@ -1531,14 +1868,15 @@ TEST_F(TextFormatParserTest, PrintErrorsToStderr) { } ASSERT_EQ(1, errors.size()); - EXPECT_EQ("Error parsing text-format protobuf_unittest.TestAllTypes: " - "1:14: Message type \"protobuf_unittest.TestAllTypes\" has no field " - "named \"no_such_field\".", - errors[0]); + EXPECT_EQ( + "Error parsing text-format protobuf_unittest.TestAllTypes: " + "1:14: Message type \"protobuf_unittest.TestAllTypes\" has no field " + "named \"no_such_field\".", + errors[0]); } TEST_F(TextFormatParserTest, FailsOnTokenizationError) { - std::vector errors; + std::vector errors; { ScopedMemoryLog log; @@ -1548,16 +1886,85 @@ TEST_F(TextFormatParserTest, FailsOnTokenizationError) { } ASSERT_EQ(1, errors.size()); - EXPECT_EQ("Error parsing text-format protobuf_unittest.TestAllTypes: " - "1:1: Invalid control characters encountered in text.", - errors[0]); + EXPECT_EQ( + "Error parsing text-format protobuf_unittest.TestAllTypes: " + "1:1: Invalid control characters encountered in text.", + errors[0]); } TEST_F(TextFormatParserTest, ParseDeprecatedField) { unittest::TestDeprecatedFields message; ExpectMessage("deprecated_int32: 42", "WARNING:text format contains deprecated field " - "\"deprecated_int32\"", 1, 21, &message, true); + "\"deprecated_int32\"", + 1, 21, &message, true); +} + +TEST_F(TextFormatParserTest, SetRecursionLimit) { + const char* format = "child: { $0 }"; + std::string input; + for (int i = 0; i < 100; ++i) input = strings::Substitute(format, input); + + unittest::NestedTestAllTypes message; + ExpectSuccessAndTree(input, &message, nullptr); + + input = strings::Substitute(format, input); + parser_.SetRecursionLimit(100); + ExpectMessage(input, + "Message is too deep, the parser exceeded the configured " + "recursion limit of 100.", + 1, 908, &message, false); + + parser_.SetRecursionLimit(101); + ExpectSuccessAndTree(input, &message, nullptr); +} + +TEST_F(TextFormatParserTest, SetRecursionLimitUnknownFieldValue) { + const char* format = "[$0]"; + std::string input = "\"test_value\""; + for (int i = 0; i < 99; ++i) input = strings::Substitute(format, input); + std::string not_deep_input = StrCat("unknown_nested_array: ", input); + + parser_.AllowUnknownField(true); + parser_.SetRecursionLimit(100); + + unittest::NestedTestAllTypes message; + ExpectSuccessAndTree(not_deep_input, &message, nullptr); + + input = strings::Substitute(format, input); + std::string deep_input = StrCat("unknown_nested_array: ", input); + ExpectMessage( + deep_input, + "WARNING:Message type \"protobuf_unittest.NestedTestAllTypes\" has no " + "field named \"unknown_nested_array\".\n1:123: Message is too deep, the " + "parser exceeded the configured recursion limit of 100.", + 1, 21, &message, false); + + parser_.SetRecursionLimit(101); + ExpectSuccessAndTree(deep_input, &message, nullptr); +} + +TEST_F(TextFormatParserTest, SetRecursionLimitUnknownFieldMessage) { + const char* format = "unknown_child: { $0 }"; + std::string input; + for (int i = 0; i < 100; ++i) input = strings::Substitute(format, input); + + parser_.AllowUnknownField(true); + parser_.SetRecursionLimit(100); + + unittest::NestedTestAllTypes message; + ExpectSuccessAndTree(input, &message, nullptr); + + input = strings::Substitute(format, input); + ExpectMessage( + input, + "WARNING:Message type \"protobuf_unittest.NestedTestAllTypes\" has no " + "field named \"unknown_child\".\n1:1716: Message is too deep, the parser " + "exceeded the configured recursion limit of 100.", + 1, 14, &message, false); + + parser_.SetRecursionLimit(101); + ExpectSuccessAndTree(input, &message, nullptr); } class TextFormatMessageSetTest : public testing::Test { @@ -1565,25 +1972,24 @@ class TextFormatMessageSetTest : public testing::Test { static const char proto_debug_string_[]; }; const char TextFormatMessageSetTest::proto_debug_string_[] = -"message_set {\n" -" [protobuf_unittest.TestMessageSetExtension1] {\n" -" i: 23\n" -" }\n" -" [protobuf_unittest.TestMessageSetExtension2] {\n" -" str: \"foo\"\n" -" }\n" -"}\n"; - + "message_set {\n" + " [protobuf_unittest.TestMessageSetExtension1] {\n" + " i: 23\n" + " }\n" + " [protobuf_unittest.TestMessageSetExtension2] {\n" + " str: \"foo\"\n" + " }\n" + "}\n"; TEST_F(TextFormatMessageSetTest, Serialize) { protobuf_unittest::TestMessageSetContainer proto; protobuf_unittest::TestMessageSetExtension1* item_a = - proto.mutable_message_set()->MutableExtension( - protobuf_unittest::TestMessageSetExtension1::message_set_extension); + proto.mutable_message_set()->MutableExtension( + protobuf_unittest::TestMessageSetExtension1::message_set_extension); item_a->set_i(23); protobuf_unittest::TestMessageSetExtension2* item_b = - proto.mutable_message_set()->MutableExtension( - protobuf_unittest::TestMessageSetExtension2::message_set_extension); + proto.mutable_message_set()->MutableExtension( + protobuf_unittest::TestMessageSetExtension2::message_set_extension); item_b->set_str("foo"); EXPECT_EQ(proto_debug_string_, proto.DebugString()); } @@ -1591,19 +1997,168 @@ TEST_F(TextFormatMessageSetTest, Serialize) { TEST_F(TextFormatMessageSetTest, Deserialize) { protobuf_unittest::TestMessageSetContainer proto; ASSERT_TRUE(TextFormat::ParseFromString(proto_debug_string_, &proto)); - EXPECT_EQ(23, proto.message_set().GetExtension( - protobuf_unittest::TestMessageSetExtension1::message_set_extension).i()); - EXPECT_EQ("foo", proto.message_set().GetExtension( - protobuf_unittest::TestMessageSetExtension2::message_set_extension).str()); + EXPECT_EQ( + 23, + proto.message_set() + .GetExtension( + protobuf_unittest::TestMessageSetExtension1::message_set_extension) + .i()); + EXPECT_EQ( + "foo", + proto.message_set() + .GetExtension( + protobuf_unittest::TestMessageSetExtension2::message_set_extension) + .str()); // Ensure that these are the only entries present. std::vector descriptors; - proto.message_set().GetReflection()->ListFields( - proto.message_set(), &descriptors); + proto.message_set().GetReflection()->ListFields(proto.message_set(), + &descriptors); EXPECT_EQ(2, descriptors.size()); } +TEST(TextFormatUnknownFieldTest, TestUnknownField) { + protobuf_unittest::TestAllTypes proto; + TextFormat::Parser parser; + // Unknown field is not permitted by default. + EXPECT_FALSE(parser.ParseFromString("unknown_field: 12345", &proto)); + EXPECT_FALSE(parser.ParseFromString("12345678: 12345", &proto)); + + parser.AllowUnknownField(true); + EXPECT_TRUE(parser.ParseFromString("unknown_field: 12345", &proto)); + EXPECT_TRUE(parser.ParseFromString("unknown_field: -12345", &proto)); + EXPECT_TRUE(parser.ParseFromString("unknown_field: 1.2345", &proto)); + EXPECT_TRUE(parser.ParseFromString("unknown_field: -1.2345", &proto)); + EXPECT_TRUE(parser.ParseFromString("unknown_field: 1.2345f", &proto)); + EXPECT_TRUE(parser.ParseFromString("unknown_field: -1.2345f", &proto)); + EXPECT_TRUE(parser.ParseFromString("unknown_field: inf", &proto)); + EXPECT_TRUE(parser.ParseFromString("unknown_field: -inf", &proto)); + EXPECT_TRUE(parser.ParseFromString("unknown_field: TYPE_STRING", &proto)); + EXPECT_TRUE( + parser.ParseFromString("unknown_field: \"string value\"", &proto)); + // Invalid field value + EXPECT_FALSE(parser.ParseFromString("unknown_field: -TYPE_STRING", &proto)); + // Two or more unknown fields + EXPECT_TRUE( + parser.ParseFromString("unknown_field1: TYPE_STRING\n" + "unknown_field2: 12345", + &proto)); + // Unknown nested message + EXPECT_TRUE( + parser.ParseFromString("unknown_message1: {}\n" + "unknown_message2 {\n" + " unknown_field: 12345\n" + "}\n" + "unknown_message3 <\n" + " unknown_nested_message {\n" + " unknown_field: 12345\n" + " }\n" + ">", + &proto)); + // Unmatched delimiters for message body + EXPECT_FALSE(parser.ParseFromString("unknown_message: {>", &proto)); + // Unknown extension + EXPECT_TRUE( + parser.ParseFromString("[somewhere.unknown_extension1]: 12345\n" + "[somewhere.unknown_extension2] {\n" + " unknown_field: 12345\n" + "}", + &proto)); + // Unknown fields between known fields + ASSERT_TRUE( + parser.ParseFromString("optional_int32: 1\n" + "unknown_field: 12345\n" + "optional_string: \"string\"\n" + "unknown_message { unknown: 0 }\n" + "optional_nested_message { bb: 2 }", + &proto)); + EXPECT_EQ(1, proto.optional_int32()); + EXPECT_EQ("string", proto.optional_string()); + EXPECT_EQ(2, proto.optional_nested_message().bb()); + + // Unknown field with numeric tag number instead of identifier. + EXPECT_TRUE(parser.ParseFromString("12345678: 12345", &proto)); + + // Nested unknown extensions. + EXPECT_TRUE( + parser.ParseFromString("[test.extension1] <\n" + " unknown_nested_message <\n" + " [test.extension2] <\n" + " unknown_field: 12345\n" + " >\n" + " >\n" + ">", + &proto)); + EXPECT_TRUE( + parser.ParseFromString("[test.extension1] {\n" + " unknown_nested_message {\n" + " [test.extension2] {\n" + " unknown_field: 12345\n" + " }\n" + " }\n" + "}", + &proto)); + EXPECT_TRUE( + parser.ParseFromString("[test.extension1] <\n" + " some_unknown_fields: <\n" + " unknown_field: 12345\n" + " >\n" + ">", + &proto)); + EXPECT_TRUE( + parser.ParseFromString("[test.extension1] {\n" + " some_unknown_fields: {\n" + " unknown_field: 12345\n" + " }\n" + "}", + &proto)); + + // Unknown field with compact repetition. + EXPECT_TRUE(parser.ParseFromString("unknown_field: [1, 2]", &proto)); + // Unknown field with compact repetition of some unknown enum. + EXPECT_TRUE(parser.ParseFromString("unknown_field: [VAL1, VAL2]", &proto)); + // Unknown field with compact repetition with sub-message. + EXPECT_TRUE(parser.ParseFromString("unknown_field: [{a:1}, ]", &proto)); +} + +TEST(TextFormatUnknownFieldTest, TestAnyInUnknownField) { + protobuf_unittest::TestAllTypes proto; + TextFormat::Parser parser; + parser.AllowUnknownField(true); + EXPECT_TRUE( + parser.ParseFromString("unknown {\n" + " [type.googleapis.com/foo.bar] {\n" + " }\n" + "}", + &proto)); +} + +TEST(TextFormatUnknownFieldTest, TestUnknownExtension) { + protobuf_unittest::TestAllTypes proto; + TextFormat::Parser parser; + std::string message_with_ext = + "[test.extension1] {\n" + " some_unknown_fields: {\n" + " unknown_field: 12345\n" + " }\n" + "}"; + // Unknown extensions are not permitted by default. + EXPECT_FALSE(parser.ParseFromString(message_with_ext, &proto)); + // AllowUnknownField implies AllowUnknownExtension. + parser.AllowUnknownField(true); + EXPECT_TRUE(parser.ParseFromString(message_with_ext, &proto)); + + parser.AllowUnknownField(false); + EXPECT_FALSE(parser.ParseFromString(message_with_ext, &proto)); + parser.AllowUnknownExtension(true); + EXPECT_TRUE(parser.ParseFromString(message_with_ext, &proto)); + // Unknown fields are still not accepted. + EXPECT_FALSE(parser.ParseFromString("unknown_field: 1", &proto)); +} + } // namespace text_format_unittest } // namespace protobuf } // namespace google + +#include diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index 44ddc749a8986..ac920a1612efd 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -1,164 +1,97 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/timestamp.proto -#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include #include -#include -#include -#include #include -#include +#include +#include #include #include #include #include // @@protoc_insertion_point(includes) - -namespace google { -namespace protobuf { -class TimestampDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _Timestamp_default_instance_; - -namespace protobuf_google_2fprotobuf_2ftimestamp_2eproto { - - -namespace { - -::google::protobuf::Metadata file_level_metadata[1]; - -} // namespace - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField - const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0}, -}; - -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField - const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - ::google::protobuf::internal::AuxillaryParseTableField(), -}; -PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const - TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { NULL, NULL, 0, -1, -1, -1, -1, NULL, false }, +#include + +PROTOBUF_PRAGMA_INIT_SEG +PROTOBUF_NAMESPACE_OPEN +constexpr Timestamp::Timestamp( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : seconds_(PROTOBUF_LONGLONG(0)) + , nanos_(0){} +struct TimestampDefaultTypeInternal { + constexpr TimestampDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~TimestampDefaultTypeInternal() {} + union { + Timestamp _instance; + }; }; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT TimestampDefaultTypeInternal _Timestamp_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto[1]; +static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto = nullptr; -const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { +const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2ftimestamp_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { ~0u, // no _has_bits_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Timestamp, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Timestamp, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Timestamp, seconds_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Timestamp, nanos_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Timestamp, seconds_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Timestamp, nanos_), }; -static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - { 0, -1, sizeof(Timestamp)}, +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, sizeof(PROTOBUF_NAMESPACE_ID::Timestamp)}, }; -static ::google::protobuf::Message const * const file_default_instances[] = { - reinterpret_cast(&_Timestamp_default_instance_), +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&PROTOBUF_NAMESPACE_ID::_Timestamp_default_instance_), }; -namespace { - -void protobuf_AssignDescriptors() { - AddDescriptors(); - ::google::protobuf::MessageFactory* factory = NULL; - AssignDescriptors( - "google/protobuf/timestamp.proto", schemas, file_default_instances, TableStruct::offsets, factory, - file_level_metadata, NULL, NULL); -} - -void protobuf_AssignDescriptorsOnce() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors); -} - -void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; -void protobuf_RegisterTypes(const ::std::string&) { - protobuf_AssignDescriptorsOnce(); - ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1); -} - -} // namespace -void TableStruct::InitDefaultsImpl() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - ::google::protobuf::internal::InitProtobufDefaults(); - _Timestamp_default_instance_._instance.DefaultConstruct(); - ::google::protobuf::internal::OnShutdownDestroyMessage( - &_Timestamp_default_instance_);} - -void InitDefaults() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl); -} -namespace { -void AddDescriptorsImpl() { - InitDefaults(); - static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - "\n\037google/protobuf/timestamp.proto\022\017googl" - "e.protobuf\"+\n\tTimestamp\022\017\n\007seconds\030\001 \001(\003" - "\022\r\n\005nanos\030\002 \001(\005B~\n\023com.google.protobufB\016" - "TimestampProtoP\001Z+github.com/golang/prot" - "obuf/ptypes/timestamp\370\001\001\242\002\003GPB\252\002\036Google." - "Protobuf.WellKnownTypesb\006proto3" - }; - ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( - descriptor, 231); - ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( - "google/protobuf/timestamp.proto", &protobuf_RegisterTypes); -} -} // anonymous namespace - -void AddDescriptors() { - static GOOGLE_PROTOBUF_DECLARE_ONCE(once); - ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl); +const char descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\037google/protobuf/timestamp.proto\022\017googl" + "e.protobuf\"+\n\tTimestamp\022\017\n\007seconds\030\001 \001(\003" + "\022\r\n\005nanos\030\002 \001(\005B\205\001\n\023com.google.protobufB" + "\016TimestampProtoP\001Z2google.golang.org/pro" + "tobuf/types/known/timestamppb\370\001\001\242\002\003GPB\252\002" + "\036Google.Protobuf.WellKnownTypesb\006proto3" + ; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftimestamp_2eproto = { + false, false, 239, descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto, "google/protobuf/timestamp.proto", + &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once, nullptr, 0, 1, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2ftimestamp_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto, file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata +descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_metadata_getter(int index) { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ftimestamp_2eproto); + return descriptor_table_google_2fprotobuf_2ftimestamp_2eproto.file_level_metadata[index]; } -// Force AddDescriptors() to be called at dynamic initialization time. -struct StaticDescriptorInitializer { - StaticDescriptorInitializer() { - AddDescriptors(); - } -} static_descriptor_initializer; - -} // namespace protobuf_google_2fprotobuf_2ftimestamp_2eproto +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ftimestamp_2eproto(&descriptor_table_google_2fprotobuf_2ftimestamp_2eproto); +PROTOBUF_NAMESPACE_OPEN // =================================================================== -#if !defined(_MSC_VER) || _MSC_VER >= 1900 -const int Timestamp::kSecondsFieldNumber; -const int Timestamp::kNanosFieldNumber; -#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 +class Timestamp::_Internal { + public: +}; -Timestamp::Timestamp() - : ::google::protobuf::Message(), _internal_metadata_(NULL) { - if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { - protobuf_google_2fprotobuf_2ftimestamp_2eproto::InitDefaults(); - } - SharedCtor(); - // @@protoc_insertion_point(constructor:google.protobuf.Timestamp) -} -Timestamp::Timestamp(::google::protobuf::Arena* arena) - : ::google::protobuf::Message(), - _internal_metadata_(arena) { - protobuf_google_2fprotobuf_2ftimestamp_2eproto::InitDefaults(); +Timestamp::Timestamp(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); RegisterArenaDtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Timestamp) } Timestamp::Timestamp(const Timestamp& from) - : ::google::protobuf::Message(), - _internal_metadata_(NULL), - _cached_size_(0) { - _internal_metadata_.MergeFrom(from._internal_metadata_); + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); ::memcpy(&seconds_, &from.seconds_, static_cast(reinterpret_cast(&nanos_) - reinterpret_cast(&seconds_)) + sizeof(nanos_)); @@ -166,164 +99,108 @@ Timestamp::Timestamp(const Timestamp& from) } void Timestamp::SharedCtor() { - ::memset(&seconds_, 0, static_cast( - reinterpret_cast(&nanos_) - - reinterpret_cast(&seconds_)) + sizeof(nanos_)); - _cached_size_ = 0; +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&seconds_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&nanos_) - + reinterpret_cast(&seconds_)) + sizeof(nanos_)); } Timestamp::~Timestamp() { // @@protoc_insertion_point(destructor:google.protobuf.Timestamp) SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } void Timestamp::SharedDtor() { - ::google::protobuf::Arena* arena = GetArenaNoVirtual(); - GOOGLE_DCHECK(arena == NULL); - if (arena != NULL) { - return; - } - + GOOGLE_DCHECK(GetArena() == nullptr); } void Timestamp::ArenaDtor(void* object) { Timestamp* _this = reinterpret_cast< Timestamp* >(object); (void)_this; } -void Timestamp::RegisterArenaDtor(::google::protobuf::Arena* arena) { +void Timestamp::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { } void Timestamp::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); -} -const ::google::protobuf::Descriptor* Timestamp::descriptor() { - protobuf_google_2fprotobuf_2ftimestamp_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2ftimestamp_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - -const Timestamp& Timestamp::default_instance() { - protobuf_google_2fprotobuf_2ftimestamp_2eproto::InitDefaults(); - return *internal_default_instance(); -} - -Timestamp* Timestamp::New(::google::protobuf::Arena* arena) const { - return ::google::protobuf::Arena::CreateMessage(arena); + _cached_size_.Set(size); } void Timestamp::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Timestamp) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; ::memset(&seconds_, 0, static_cast( reinterpret_cast(&nanos_) - reinterpret_cast(&seconds_)) + sizeof(nanos_)); - _internal_metadata_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } -bool Timestamp::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:google.protobuf.Timestamp) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { +const char* Timestamp::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { // int64 seconds = 1; - case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { - - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>( - input, &seconds_))); - } else { - goto handle_unusual; - } - break; - } - + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + seconds_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; // int32 nanos = 2; - case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) { - - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( - input, &nanos_))); - } else { - goto handle_unusual; - } - break; - } - + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + nanos_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: - if (tag == 0) { + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); goto success; } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, _internal_metadata_.mutable_unknown_fields())); - break; + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; } - } - } + } // switch + } // while success: - // @@protoc_insertion_point(parse_success:google.protobuf.Timestamp) - return true; + return ptr; failure: - // @@protoc_insertion_point(parse_failure:google.protobuf.Timestamp) - return false; -#undef DO_ -} - -void Timestamp::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:google.protobuf.Timestamp) - ::google::protobuf::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // int64 seconds = 1; - if (this->seconds() != 0) { - ::google::protobuf::internal::WireFormatLite::WriteInt64(1, this->seconds(), output); - } - - // int32 nanos = 2; - if (this->nanos() != 0) { - ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->nanos(), output); - } - - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); - } - // @@protoc_insertion_point(serialize_end:google.protobuf.Timestamp) + ptr = nullptr; + goto success; +#undef CHK_ } -::google::protobuf::uint8* Timestamp::InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const { - (void)deterministic; // Unused +::PROTOBUF_NAMESPACE_ID::uint8* Timestamp::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Timestamp) - ::google::protobuf::uint32 cached_has_bits = 0; + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; // int64 seconds = 1; if (this->seconds() != 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(1, this->seconds(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(1, this->_internal_seconds(), target); } // int32 nanos = 2; if (this->nanos() != 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->nanos(), target); + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_nanos(), target); } - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); } // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Timestamp) return target; @@ -333,41 +210,42 @@ size_t Timestamp::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Timestamp) size_t total_size = 0; - if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); - } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // int64 seconds = 1; if (this->seconds() != 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int64Size( - this->seconds()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int64Size( + this->_internal_seconds()); } // int32 nanos = 2; if (this->nanos() != 0) { total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size( - this->nanos()); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_nanos()); } - int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = cached_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); return total_size; } -void Timestamp::MergeFrom(const ::google::protobuf::Message& from) { +void Timestamp::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Timestamp) GOOGLE_DCHECK_NE(&from, this); const Timestamp* source = - ::google::protobuf::internal::DynamicCastToGenerated( + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( &from); - if (source == NULL) { + if (source == nullptr) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Timestamp) - ::google::protobuf::internal::ReflectionOps::Merge(from, this); + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); } else { // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Timestamp) MergeFrom(*source); @@ -377,19 +255,19 @@ void Timestamp::MergeFrom(const ::google::protobuf::Message& from) { void Timestamp::MergeFrom(const Timestamp& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Timestamp) GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom(from._internal_metadata_); - ::google::protobuf::uint32 cached_has_bits = 0; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; (void) cached_has_bits; if (from.seconds() != 0) { - set_seconds(from.seconds()); + _internal_set_seconds(from._internal_seconds()); } if (from.nanos() != 0) { - set_nanos(from.nanos()); + _internal_set_nanos(from._internal_nanos()); } } -void Timestamp::CopyFrom(const ::google::protobuf::Message& from) { +void Timestamp::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { // @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Timestamp) if (&from == this) return; Clear(); @@ -407,74 +285,29 @@ bool Timestamp::IsInitialized() const { return true; } -void Timestamp::Swap(Timestamp* other) { - if (other == this) return; - if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { - InternalSwap(other); - } else { - Timestamp* temp = New(GetArenaNoVirtual()); - temp->MergeFrom(*other); - other->CopyFrom(*this); - InternalSwap(temp); - if (GetArenaNoVirtual() == NULL) { - delete temp; - } - } -} -void Timestamp::UnsafeArenaSwap(Timestamp* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); - InternalSwap(other); -} void Timestamp::InternalSwap(Timestamp* other) { using std::swap; - swap(seconds_, other->seconds_); - swap(nanos_, other->nanos_); - _internal_metadata_.Swap(&other->_internal_metadata_); - swap(_cached_size_, other->_cached_size_); -} - -::google::protobuf::Metadata Timestamp::GetMetadata() const { - protobuf_google_2fprotobuf_2ftimestamp_2eproto::protobuf_AssignDescriptorsOnce(); - return protobuf_google_2fprotobuf_2ftimestamp_2eproto::file_level_metadata[kIndexInFileMessages]; -} - -#if PROTOBUF_INLINE_NOT_IN_HEADERS -// Timestamp - -// int64 seconds = 1; -void Timestamp::clear_seconds() { - seconds_ = GOOGLE_LONGLONG(0); -} -::google::protobuf::int64 Timestamp::seconds() const { - // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.seconds) - return seconds_; -} -void Timestamp::set_seconds(::google::protobuf::int64 value) { - - seconds_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.seconds) + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(Timestamp, nanos_) + + sizeof(Timestamp::nanos_) + - PROTOBUF_FIELD_OFFSET(Timestamp, seconds_)>( + reinterpret_cast(&seconds_), + reinterpret_cast(&other->seconds_)); } -// int32 nanos = 2; -void Timestamp::clear_nanos() { - nanos_ = 0; -} -::google::protobuf::int32 Timestamp::nanos() const { - // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.nanos) - return nanos_; -} -void Timestamp::set_nanos(::google::protobuf::int32 value) { - - nanos_ = value; - // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.nanos) +::PROTOBUF_NAMESPACE_ID::Metadata Timestamp::GetMetadata() const { + return GetMetadataStatic(); } -#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE PROTOBUF_NAMESPACE_ID::Timestamp* Arena::CreateMaybeMessage< PROTOBUF_NAMESPACE_ID::Timestamp >(Arena* arena) { + return Arena::CreateMessageInternal< PROTOBUF_NAMESPACE_ID::Timestamp >(arena); +} +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) +#include diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h index 61596ed477a8f..bae459137c5f0 100644 --- a/src/google/protobuf/timestamp.pb.h +++ b/src/google/protobuf/timestamp.pb.h @@ -1,186 +1,222 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/timestamp.proto -#ifndef PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto__INCLUDED -#define PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto__INCLUDED +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto +#include #include -#include - -#if GOOGLE_PROTOBUF_VERSION < 3004000 +#include +#if PROTOBUF_VERSION < 3015000 #error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update +#error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 3015000 < PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please +#error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif +#include #include #include #include #include #include -#include +#include +#include #include #include // IWYU pragma: export #include // IWYU pragma: export #include // @@protoc_insertion_point(includes) -namespace google { -namespace protobuf { -class Timestamp; -class TimestampDefaultTypeInternal; -LIBPROTOBUF_EXPORT extern TimestampDefaultTypeInternal _Timestamp_default_instance_; -} // namespace protobuf -} // namespace google - -namespace google { -namespace protobuf { - -namespace protobuf_google_2fprotobuf_2ftimestamp_2eproto { -// Internal implementation detail -- do not call these. -struct LIBPROTOBUF_EXPORT TableStruct { - static const ::google::protobuf::internal::ParseTableField entries[]; - static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; - static const ::google::protobuf::internal::ParseTable schema[]; - static const ::google::protobuf::uint32 offsets[]; - static const ::google::protobuf::internal::FieldMetadata field_metadata[]; - static const ::google::protobuf::internal::SerializationTable serialization_table[]; - static void InitDefaultsImpl(); +#include +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftimestamp_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ftimestamp_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; }; -void LIBPROTOBUF_EXPORT AddDescriptors(); -void LIBPROTOBUF_EXPORT InitDefaults(); -} // namespace protobuf_google_2fprotobuf_2ftimestamp_2eproto +extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftimestamp_2eproto; +PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_metadata_getter(int index); +PROTOBUF_NAMESPACE_OPEN +class Timestamp; +struct TimestampDefaultTypeInternal; +PROTOBUF_EXPORT extern TimestampDefaultTypeInternal _Timestamp_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT PROTOBUF_NAMESPACE_ID::Timestamp* Arena::CreateMaybeMessage(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN // =================================================================== -class LIBPROTOBUF_EXPORT Timestamp : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Timestamp) */ { +class PROTOBUF_EXPORT Timestamp PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Timestamp) */ { public: - Timestamp(); + inline Timestamp() : Timestamp(nullptr) {} virtual ~Timestamp(); + explicit constexpr Timestamp(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); Timestamp(const Timestamp& from); - - inline Timestamp& operator=(const Timestamp& from) { - CopyFrom(from); - return *this; - } - #if LANG_CXX11 Timestamp(Timestamp&& from) noexcept : Timestamp() { *this = ::std::move(from); } + inline Timestamp& operator=(const Timestamp& from) { + CopyFrom(from); + return *this; + } inline Timestamp& operator=(Timestamp&& from) noexcept { - if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (GetArena() == from.GetArena()) { if (this != &from) InternalSwap(&from); } else { CopyFrom(from); } return *this; } - #endif - inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL { - return GetArenaNoVirtual(); + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); } - inline void* GetMaybeArenaPointer() const PROTOBUF_FINAL { - return MaybeArenaPtr(); + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const Timestamp& default_instance() { + return *internal_default_instance(); } - static const ::google::protobuf::Descriptor* descriptor(); - static const Timestamp& default_instance(); - static inline const Timestamp* internal_default_instance() { return reinterpret_cast( &_Timestamp_default_instance_); } - static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + static constexpr int kIndexInFileMessages = 0; - void UnsafeArenaSwap(Timestamp* other); - void Swap(Timestamp* other); friend void swap(Timestamp& a, Timestamp& b) { a.Swap(&b); } + inline void Swap(Timestamp* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Timestamp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } // implements Message ---------------------------------------------- - inline Timestamp* New() const PROTOBUF_FINAL { return New(NULL); } + inline Timestamp* New() const final { + return CreateMaybeMessage(nullptr); + } - Timestamp* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; - void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; - void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + Timestamp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; void CopyFrom(const Timestamp& from); void MergeFrom(const Timestamp& from); - void Clear() PROTOBUF_FINAL; - bool IsInitialized() const PROTOBUF_FINAL; - - size_t ByteSizeLong() const PROTOBUF_FINAL; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; - ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( - bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; - int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const PROTOBUF_FINAL; + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; void InternalSwap(Timestamp* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Timestamp"; + } protected: - explicit Timestamp(::google::protobuf::Arena* arena); + explicit Timestamp(::PROTOBUF_NAMESPACE_ID::Arena* arena); private: static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::google::protobuf::Arena* arena); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; private: - inline ::google::protobuf::Arena* GetArenaNoVirtual() const { - return _internal_metadata_.arena(); - } - inline void* MaybeArenaPtr() const { - return _internal_metadata_.raw_arena_ptr(); + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + return ::descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_metadata_getter(kIndexInFileMessages); } - public: - ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + public: // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + enum : int { + kSecondsFieldNumber = 1, + kNanosFieldNumber = 2, + }; // int64 seconds = 1; void clear_seconds(); - static const int kSecondsFieldNumber = 1; - ::google::protobuf::int64 seconds() const; - void set_seconds(::google::protobuf::int64 value); + ::PROTOBUF_NAMESPACE_ID::int64 seconds() const; + void set_seconds(::PROTOBUF_NAMESPACE_ID::int64 value); + private: + ::PROTOBUF_NAMESPACE_ID::int64 _internal_seconds() const; + void _internal_set_seconds(::PROTOBUF_NAMESPACE_ID::int64 value); + public: // int32 nanos = 2; void clear_nanos(); - static const int kNanosFieldNumber = 2; - ::google::protobuf::int32 nanos() const; - void set_nanos(::google::protobuf::int32 value); + ::PROTOBUF_NAMESPACE_ID::int32 nanos() const; + void set_nanos(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_nanos() const; + void _internal_set_nanos(::PROTOBUF_NAMESPACE_ID::int32 value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.Timestamp) private: + class _Internal; - ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; - template friend class ::google::protobuf::Arena::InternalHelper; + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; - ::google::protobuf::int64 seconds_; - ::google::protobuf::int32 nanos_; - mutable int _cached_size_; - friend struct protobuf_google_2fprotobuf_2ftimestamp_2eproto::TableStruct; + ::PROTOBUF_NAMESPACE_ID::int64 seconds_; + ::PROTOBUF_NAMESPACE_ID::int32 nanos_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_google_2fprotobuf_2ftimestamp_2eproto; }; // =================================================================== // =================================================================== -#if !PROTOBUF_INLINE_NOT_IN_HEADERS #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" @@ -189,15 +225,21 @@ class LIBPROTOBUF_EXPORT Timestamp : public ::google::protobuf::Message /* @@pro // int64 seconds = 1; inline void Timestamp::clear_seconds() { - seconds_ = GOOGLE_LONGLONG(0); + seconds_ = PROTOBUF_LONGLONG(0); } -inline ::google::protobuf::int64 Timestamp::seconds() const { - // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.seconds) +inline ::PROTOBUF_NAMESPACE_ID::int64 Timestamp::_internal_seconds() const { return seconds_; } -inline void Timestamp::set_seconds(::google::protobuf::int64 value) { +inline ::PROTOBUF_NAMESPACE_ID::int64 Timestamp::seconds() const { + // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.seconds) + return _internal_seconds(); +} +inline void Timestamp::_internal_set_seconds(::PROTOBUF_NAMESPACE_ID::int64 value) { seconds_ = value; +} +inline void Timestamp::set_seconds(::PROTOBUF_NAMESPACE_ID::int64 value) { + _internal_set_seconds(value); // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.seconds) } @@ -205,27 +247,31 @@ inline void Timestamp::set_seconds(::google::protobuf::int64 value) { inline void Timestamp::clear_nanos() { nanos_ = 0; } -inline ::google::protobuf::int32 Timestamp::nanos() const { - // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.nanos) +inline ::PROTOBUF_NAMESPACE_ID::int32 Timestamp::_internal_nanos() const { return nanos_; } -inline void Timestamp::set_nanos(::google::protobuf::int32 value) { +inline ::PROTOBUF_NAMESPACE_ID::int32 Timestamp::nanos() const { + // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.nanos) + return _internal_nanos(); +} +inline void Timestamp::_internal_set_nanos(::PROTOBUF_NAMESPACE_ID::int32 value) { nanos_ = value; +} +inline void Timestamp::set_nanos(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_nanos(value); // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.nanos) } #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ -#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) - -} // namespace protobuf -} // namespace google +PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) -#endif // PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto__INCLUDED +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto index b7cbd17502f28..3b2df6d91168e 100644 --- a/src/google/protobuf/timestamp.proto +++ b/src/google/protobuf/timestamp.proto @@ -34,23 +34,25 @@ package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/timestamp"; +option go_package = "google.golang.org/protobuf/types/known/timestamppb"; option java_package = "com.google.protobuf"; option java_outer_classname = "TimestampProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; -// A Timestamp represents a point in time independent of any time zone -// or calendar, represented as seconds and fractions of seconds at -// nanosecond resolution in UTC Epoch time. It is encoded using the -// Proleptic Gregorian Calendar which extends the Gregorian calendar -// backwards to year one. It is encoded assuming all minutes are 60 -// seconds long, i.e. leap seconds are "smeared" so that no leap second -// table is needed for interpretation. Range is from -// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. -// By restricting to that range, we ensure that we can convert to -// and from RFC 3339 date strings. -// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). +// A Timestamp represents a point in time independent of any time zone or local +// calendar, encoded as a count of seconds and fractions of seconds at +// nanosecond resolution. The count is relative to an epoch at UTC midnight on +// January 1, 1970, in the proleptic Gregorian calendar which extends the +// Gregorian calendar backwards to year one. +// +// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap +// second table is needed for interpretation, using a [24-hour linear +// smear](https://developers.google.com/time/smear). +// +// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By +// restricting to that range, we ensure that we can convert to and from [RFC +// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. // // # Examples // @@ -89,7 +91,16 @@ option objc_class_prefix = "GPB"; // .setNanos((int) ((millis % 1000) * 1000000)).build(); // // -// Example 5: Compute Timestamp from current time in Python. +// Example 5: Compute Timestamp from Java `Instant.now()`. +// +// Instant now = Instant.now(); +// +// Timestamp timestamp = +// Timestamp.newBuilder().setSeconds(now.getEpochSecond()) +// .setNanos(now.getNano()).build(); +// +// +// Example 6: Compute Timestamp from current time in Python. // // timestamp = Timestamp() // timestamp.GetCurrentTime() @@ -103,23 +114,26 @@ option objc_class_prefix = "GPB"; // {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional // seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone -// is required, though only UTC (as indicated by "Z") is presently supported. +// is required. A proto3 JSON serializer should always use UTC (as indicated by +// "Z") when printing the Timestamp type and a proto3 JSON parser should be +// able to accept both UTC and other timezones (as indicated by an offset). // // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past // 01:30 UTC on January 15, 2017. // // In JavaScript, one can convert a Date object to this format using the -// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString] +// standard +// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) // method. In Python, a standard `datetime.datetime` object can be converted -// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) -// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one -// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( -// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()) -// to obtain a formatter capable of generating timestamps in this format. +// to this format using +// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with +// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use +// the Joda Time's [`ISODateTimeFormat.dateTime()`]( +// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D +// ) to obtain a formatter capable of generating timestamps in this format. // // message Timestamp { - // Represents seconds of UTC time since Unix epoch // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to // 9999-12-31T23:59:59Z inclusive. diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index abb52395dcf11..e2f7a8fc535ef 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -1,267 +1,246 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/type.proto -#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include #include -#include -#include -#include #include -#include +#include +#include #include #include #include #include // @@protoc_insertion_point(includes) - -namespace google { -namespace protobuf { -class TypeDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _Type_default_instance_; -class FieldDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _Field_default_instance_; -class EnumDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _Enum_default_instance_; -class EnumValueDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed - _instance; -} _EnumValue_default_instance_; -class OptionDefaultTypeInternal { -public: - ::google::protobuf::internal::ExplicitlyConstructed